summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/wx-3.0-msw
diff options
context:
space:
mode:
authorrahulp132020-03-17 14:55:41 +0530
committerrahulp132020-03-17 14:55:41 +0530
commit296443137f4288cb030e92859ccfbe3204bc1088 (patch)
treeca4798c2da1e7244edc3bc108d81b462b537aea2 /lib/python2.7/site-packages/wx-3.0-msw
parent0db48f6533517ecebfd9f0693f89deca28408b76 (diff)
downloadKiCad-eSim-296443137f4288cb030e92859ccfbe3204bc1088.tar.gz
KiCad-eSim-296443137f4288cb030e92859ccfbe3204bc1088.tar.bz2
KiCad-eSim-296443137f4288cb030e92859ccfbe3204bc1088.zip
initial commit
Diffstat (limited to 'lib/python2.7/site-packages/wx-3.0-msw')
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/__init__.py61
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/__version__.py10
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_animate.pydbin0 -> 136704 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_aui.pydbin0 -> 654336 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_calendar.pydbin0 -> 174592 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_combo.pydbin0 -> 255488 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_controls.py7871
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_controls_.pydbin0 -> 1346560 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_core.py16933
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_core_.pydbin0 -> 1471488 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_dataview.pydbin0 -> 577536 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_gdi.py8500
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_gdi_.pydbin0 -> 1077248 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_gizmos.pydbin0 -> 628736 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_glcanvas.pydbin0 -> 124416 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_grid.pydbin0 -> 623104 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_html.pydbin0 -> 493568 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_html2.pydbin0 -> 165376 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_media.pydbin0 -> 138752 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_misc.py7014
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_misc_.pydbin0 -> 1011712 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_propgrid.pydbin0 -> 1155584 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_richtext.pydbin0 -> 914944 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_stc.pydbin0 -> 781312 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_webkit.pydbin0 -> 147456 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_windows.py5831
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_windows_.pydbin0 -> 1057280 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_wizard.pydbin0 -> 174080 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/_xrc.pydbin0 -> 247808 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/animate.py251
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/aui.py2454
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/build/__init__.py20
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/build/build_options.py10
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/build/cfg_version.py8
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/build/config.py1258
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/calendar.py683
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/combo.py1025
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/dataview.py2584
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/gizmos.py1051
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/glcanvas.py183
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/grid.py2564
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/html.py2028
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/html2.py425
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/CDate.py129
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ClickableHtmlWindow.py57
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/__init__.py4
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/activex.py173
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/activexwrapper.py155
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/__init__.py128
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/advancedsplash.py546
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aquabutton.py1086
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/artmanager.py2111
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/__init__.py298
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_constants.py2594
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_switcherdialog.py1215
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_utilities.py680
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/auibar.py3989
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/auibook.py6076
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/dockart.py1187
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/framemanager.py10697
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/tabart.py2809
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/tabmdi.py666
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/balloontip.py1092
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/buttonpanel.py2767
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/cubecolourdialog.py3494
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/customtreectrl.py8506
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_1.pngbin0 -> 71811 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_1_thumb.pngbin0 -> 17463 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_2.pngbin0 -> 64124 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_2_thumb.pngbin0 -> 16470 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_3.pngbin0 -> 61121 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_3_thumb.pngbin0 -> 16250 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_4.pngbin0 -> 87262 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_4_thumb.pngbin0 -> 17764 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/default_help_text.html105
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/flatmenu.py7304
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/flatnotebook.py6673
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/floatspin.py1712
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fmcustomizedlg.py519
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fmresources.py407
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/foldpanelbar.py2246
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fourwaysplitter.py1101
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/genericmessagedialog.py1586
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/gradientbutton.py708
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/hyperlink.py622
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/hypertreelist.py4886
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/infobar.py831
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/knobctrl.py902
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/labelbook.py3031
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/multidirdialog.py584
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/peakmeter.py957
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/__init__.py193
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persist_constants.py263
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persist_handlers.py2613
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persistencemanager.py845
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/piectrl.py988
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pybusyinfo.py331
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pycollapsiblepane.py861
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pygauge.py516
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pyprogress.py878
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/__init__.py177
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art.py203
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_aui.py1260
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_default.py68
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_internal.py230
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_msw.py2721
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_osx.py39
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/bar.py1253
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/buttonbar.py1314
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/control.py192
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/gallery.py960
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/page.py932
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/panel.py1157
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/toolbar.py1453
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/rulerctrl.py1848
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/shapedbutton.py1779
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/shortcuteditor.py2631
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/speedmeter.py1767
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/supertooltip.py1440
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/thumbnailctrl.py2599
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/toasterbox.py1331
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ultimatelistctrl.py13726
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/xlsgrid.py2114
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/zoombar.py1316
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/__init__.py144
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/analogclock.py633
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/helpers.py985
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/__init__.py0
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/buttontreectrlpanel.py290
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/colourselect.py80
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/fontselect.py61
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/setup.py473
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/styles.py47
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/anchors.py104
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/__init__.py1
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/flagart.py1583
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/img2pyartprov.py57
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/busy.py148
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/buttonpanel.py13
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/buttons.py657
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/calendar.py1236
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/__init__.py36
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/canvas.py143
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/intl.py24
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourbox.py87
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourchooser.py413
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourslider.py92
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pypalette.py176
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourdb.py676
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourselect.py176
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourutils.py92
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/combotreebox.py927
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/customtreectrl.py13
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/delayedresult.py420
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/dialogs.py505
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/docview.py3230
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/dragscroller.py79
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/README.txt77
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/__init__.py25
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/editor.py976
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/images.py15
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/selection.py44
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/embeddedimage.py75
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/eventStack.py136
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/eventwatcher.py458
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/evtmgr.py521
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/expando.py225
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/fancytext.py462
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/filebrowsebutton.py460
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flashwin.py262
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flashwin_old.py652
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flatnotebook.py13
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatbar.py310
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/FloatCanvas.py3301
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/GUIMode.py378
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/NavCanvas.py93
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Resources.py316
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/ScreenShot.py1785
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/BBox.py303
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/BBoxTest.py563
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/Colors.py127
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/GUI.py88
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/__init__.py7
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/__init__.py98
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/foldmenu.py89
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/foldpanelbar.py13
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/gestures.py310
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/graphics.py1706
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/gridmovers.py493
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/grids.py302
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/hyperlink.py13
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/iewin.py250
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/iewin_old.py895
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/imagebrowser.py753
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/imageutils.py98
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/infoframe.py492
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/inspection.py1237
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/intctrl.py921
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/itemspicker.py243
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/langlistctrl.py424
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/layoutf.py270
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/__init__.py26
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/combobox.py794
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/ctrl.py108
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/ipaddrctrl.py220
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/maskededit.py7265
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/numctrl.py1926
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/textctrl.py419
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/timectrl.py1405
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/__init__.py18
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/grid.py48
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/gridlabelrenderer.py248
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/imagelist.py78
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/inspection.py89
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/listctrl.py877
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/rubberband.py406
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/treemixin.py661
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/msgpanel.py96
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/multisash.py746
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mvctree.py1150
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/newevent.py115
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/nvdlg.py155
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/__init__.py22
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_basic.py3179
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_bmpshape.py64
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_canvas.py363
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_composit.py1442
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_diagram.py167
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_divided.py402
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_drawn.py888
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_lines.py1532
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_oglmisc.py415
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/__init__.py68
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/bezier.py64
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/buttonpanel.py211
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/dcgraphics.py353
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/images.py240
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/vec2d.py468
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/viewer.py1117
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfwin.py296
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfwin_old.py790
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/platebtn.py761
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/plot.py2531
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/popupctl.py249
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/printout.py1156
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/progressindicator.py152
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/__init__.py25
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/__init__.py92
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/__init__.py16
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/listenerimpl.py97
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/publisher.py40
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/publishermixin.py34
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/topicargspecimpl.py66
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/topicmgrimpl.py19
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/callables.py191
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/imp2.py63
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/itopicdefnprovider.py0
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/__init__.py16
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/datamsg.py27
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/listenerimpl.py93
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/publisher.py77
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/publishermixin.py65
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/topicargspecimpl.py217
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/topicmgrimpl.py13
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/listener.py40
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/listenerbase.py185
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/notificationmgr.py185
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/publisherbase.py191
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicargspec.py77
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicdefnprovider.py636
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicexc.py72
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicmgr.py456
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicobj.py472
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topictreetraverser.py143
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicutils.py118
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/treeconfig.py21
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/validatedefnargs.py29
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/weakmethod.py102
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/policies.py24
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/pub.py199
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/py2and3.py608
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/setuparg1.py33
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/setupkwargs.py29
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/__init__.py27
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/exchandling.py100
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/misc.py100
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/notification.py331
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/topictreeprinter.py195
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/xmltopicdefnprovider.py286
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pydocview.py3298
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pyshell.py349
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rcsizer.py228
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/resizewidget.py250
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rightalign.py109
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rpcMixin.py422
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/scrolledpanel.py136
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/sheet.py349
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/shell.py376
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/sized_controls.py746
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/softwareupdate.py354
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/splashscreen.py132
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/splitter.py788
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/statbmp.py89
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/stattext.py189
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/throbber.py322
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ticker.py215
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ticker_xrc.py49
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/utils.py79
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wordwrap.py97
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxPlotCanvas.py489
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxcairo.py487
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxpTag.py275
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/af/LC_MESSAGES/wxstd.mobin0 -> 99793 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/an/LC_MESSAGES/wxstd.mobin0 -> 146165 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ar/LC_MESSAGES/wxstd.mobin0 -> 39340 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ca/LC_MESSAGES/wxstd.mobin0 -> 53487 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ca@valencia/LC_MESSAGES/wxstd.mobin0 -> 53321 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/cs/LC_MESSAGES/wxstd.mobin0 -> 139772 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/da/LC_MESSAGES/wxstd.mobin0 -> 61454 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/de/LC_MESSAGES/wxstd.mobin0 -> 145886 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/el/LC_MESSAGES/wxstd.mobin0 -> 94252 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/es/LC_MESSAGES/wxstd.mobin0 -> 99822 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/eu/LC_MESSAGES/wxstd.mobin0 -> 141059 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/fi/LC_MESSAGES/wxstd.mobin0 -> 98588 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/fr/LC_MESSAGES/wxstd.mobin0 -> 141125 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/gl_ES/LC_MESSAGES/wxstd.mobin0 -> 143076 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/hi/LC_MESSAGES/wxstd.mobin0 -> 135231 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/hu/LC_MESSAGES/wxstd.mobin0 -> 81705 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/id/LC_MESSAGES/wxstd.mobin0 -> 136970 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/it/LC_MESSAGES/wxstd.mobin0 -> 144280 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ja/LC_MESSAGES/wxstd.mobin0 -> 138340 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ko_KR/LC_MESSAGES/wxstd.mobin0 -> 107503 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/lt/LC_MESSAGES/wxstd.mobin0 -> 11614 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/lv/LC_MESSAGES/wxstd.mobin0 -> 117936 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ms/LC_MESSAGES/wxstd.mobin0 -> 93352 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/nb/LC_MESSAGES/wxstd.mobin0 -> 70115 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ne/LC_MESSAGES/wxstd.mobin0 -> 196138 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/nl/LC_MESSAGES/wxstd.mobin0 -> 141026 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pl/LC_MESSAGES/wxstd.mobin0 -> 142716 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pt/LC_MESSAGES/wxstd.mobin0 -> 108391 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pt_BR/LC_MESSAGES/wxstd.mobin0 -> 143296 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ro/LC_MESSAGES/wxstd.mobin0 -> 145564 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ru/LC_MESSAGES/wxstd.mobin0 -> 154076 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sk/LC_MESSAGES/wxstd.mobin0 -> 76412 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sl/LC_MESSAGES/wxstd.mobin0 -> 127253 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sq/LC_MESSAGES/wxstd.mobin0 -> 75990 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sv/LC_MESSAGES/wxstd.mobin0 -> 137908 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ta/LC_MESSAGES/wxstd.mobin0 -> 235006 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/tr/LC_MESSAGES/wxstd.mobin0 -> 139203 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/uk/LC_MESSAGES/wxstd.mobin0 -> 182294 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/vi/LC_MESSAGES/wxstd.mobin0 -> 151584 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/zh_CN/LC_MESSAGES/wxstd.mobin0 -> 130099 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/locale/zh_TW/LC_MESSAGES/wxstd.mobin0 -> 129928 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/media.py205
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/propgrid.py4657
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/CHANGES.txt796
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/Py.icobin0 -> 4710 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaCarte.py37
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaMode.py37
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaModeTest.py36
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyCrust.icobin0 -> 4710 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyCrust.py82
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyFilling.py36
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyShell.py80
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlices.icobin0 -> 6502 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlices.py100
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlicesShell.py96
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyWrap.py49
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/README.txt83
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/__init__.py22
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/buffer.py138
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/crust.py379
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/crustslices.py416
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/dispatcher.py262
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/document.py43
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/editor.py838
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/editwindow.py297
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/filling.py360
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/frame.py984
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/images.py215
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/interpreter.py170
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/introspect.py389
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/magic.py92
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/parse.py128
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/path.py36
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/pseudo.py101
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/shell.py1575
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/sliceshell.py3789
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/py/version.py9
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/richtext.py4611
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/stc.py7318
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/AUTHORS35
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/CHANGELOG163
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/COPYING54
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Editra.pyw79
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/FAQ6
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/INSTALL63
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/MANIFEST.in25
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Makefile85
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/NEWS7
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/README40
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/THANKS12
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/TODO17
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/__init__.py13
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/docs/editra_style_sheets.txt180
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra79
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra-installer.nsi232
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra_pylintrc26
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/launcher.py13
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ca_ES@valencia/LC_MESSAGES/Editra.mobin0 -> 31713 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/cs_CZ/LC_MESSAGES/Editra.mobin0 -> 35054 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/da_DK/LC_MESSAGES/Editra.mobin0 -> 19355 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/de_DE/LC_MESSAGES/Editra.mobin0 -> 44063 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/en_US/LC_MESSAGES/Editra.mobin0 -> 378 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/es_ES/LC_MESSAGES/Editra.mobin0 -> 46924 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/fr_FR/LC_MESSAGES/Editra.mobin0 -> 47655 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/gl_ES/LC_MESSAGES/Editra.mobin0 -> 44908 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hr_HR/LC_MESSAGES/Editra.mobin0 -> 42441 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hu_HU/LC_MESSAGES/Editra.mobin0 -> 23804 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/it_IT/LC_MESSAGES/Editra.mobin0 -> 49879 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ja_JP/LC_MESSAGES/Editra.mobin0 -> 48506 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/lv_LV/LC_MESSAGES/Editra.mobin0 -> 52077 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nl_NL/LC_MESSAGES/Editra.mobin0 -> 44044 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nn_NO/LC_MESSAGES/Editra.mobin0 -> 24374 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pl_PL/LC_MESSAGES/Editra.mobin0 -> 40906 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pt_BR/LC_MESSAGES/Editra.mobin0 -> 44655 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ro_RO/LC_MESSAGES/Editra.mobin0 -> 41833 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ru_RU/LC_MESSAGES/Editra.mobin0 -> 48515 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sk_SK/LC_MESSAGES/Editra.mobin0 -> 44078 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sl_SI/LC_MESSAGES/Editra.mobin0 -> 37954 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sr_RS/LC_MESSAGES/Editra.mobin0 -> 37953 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sv_SE/LC_MESSAGES/Editra.mobin0 -> 32010 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/tr_TR/LC_MESSAGES/Editra.mobin0 -> 42458 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/uk_UA/LC_MESSAGES/Editra.mobin0 -> 54889 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_CN/LC_MESSAGES/Editra.mobin0 -> 40102 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_TW/LC_MESSAGES/Editra.mobin0 -> 28757 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/Editra.icnsbin0 -> 343464 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.icobin0 -> 275822 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.pngbin0 -> 30056 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra256.pngbin0 -> 93285 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra64.pngbin0 -> 12001 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.icnsbin0 -> 45045 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.icobin0 -> 67646 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.pngbin0 -> 12781 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/splashwarn.pngbin0 -> 44984 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Default/README2
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/AUTHORS9
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/COPYING67
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/about.pngbin0 -> 931 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/add.pngbin0 -> 322 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/advanced.pngbin0 -> 764 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/attribute.pngbin0 -> 836 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/backward.pngbin0 -> 3237 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bin_file.pngbin0 -> 628 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_add.pngbin0 -> 685 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_next.pngbin0 -> 675 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_pre.pngbin0 -> 654 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cdrom.pngbin0 -> 930 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/class.pngbin0 -> 824 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/computer.pngbin0 -> 442 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/copy.pngbin0 -> 497 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cut.pngbin0 -> 806 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete.pngbin0 -> 654 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete_all.pngbin0 -> 785 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/doc_props.pngbin0 -> 463 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/docs.pngbin0 -> 316 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/down.pngbin0 -> 682 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/element.pngbin0 -> 585 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/file.pngbin0 -> 332 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/find.pngbin0 -> 616 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/findr.pngbin0 -> 775 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/floppy.pngbin0 -> 560 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/folder.pngbin0 -> 497 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/font.pngbin0 -> 552 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/forward.pngbin0 -> 3234 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/function.pngbin0 -> 789 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/harddisk.pngbin0 -> 601 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/html_gen.pngbin0 -> 767 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/indent.pngbin0 -> 434 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/log.pngbin0 -> 610 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/mail.pngbin0 -> 549 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/method.pngbin0 -> 789 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/new.pngbin0 -> 476 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newfolder.pngbin0 -> 634 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newwin.pngbin0 -> 582 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/open.pngbin0 -> 536 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/outdent.pngbin0 -> 435 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/package.pngbin0 -> 539 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/paste.pngbin0 -> 560 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/plugin.pngbin0 -> 590 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pref.pngbin0 -> 610 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/print.pngbin0 -> 480 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/printpre.pngbin0 -> 778 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/property.pngbin0 -> 728 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pyshell.pngbin0 -> 3500 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/quit.pngbin0 -> 798 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/readonly.pngbin0 -> 429 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/redo.pngbin0 -> 590 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/refresh.pngbin0 -> 911 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/remove.pngbin0 -> 246 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/rtf_gen.pngbin0 -> 763 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/save.pngbin0 -> 910 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/saveas.pngbin0 -> 865 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/selectall.pngbin0 -> 440 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/stop.pngbin0 -> 819 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/style_edit.pngbin0 -> 573 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/tex_gen.pngbin0 -> 689 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/theme.pngbin0 -> 756 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/undo.pngbin0 -> 649 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/up.pngbin0 -> 651 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/usb.pngbin0 -> 509 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/variable.pngbin0 -> 451 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/web.pngbin0 -> 927 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/boo.pngbin0 -> 741 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/css.pngbin0 -> 707 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/html.pngbin0 -> 707 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/java.pngbin0 -> 766 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/php.pngbin0 -> 827 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/python.pngbin0 -> 792 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/ruby.pngbin0 -> 832 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/shell.pngbin0 -> 515 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/text.pngbin0 -> 332 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/other/doc_props.pngbin0 -> 2408 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/advanced.pngbin0 -> 2173 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/backward.pngbin0 -> 3701 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/copy.pngbin0 -> 722 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/cut.pngbin0 -> 2086 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/doc_props.pngbin0 -> 1114 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/find.pngbin0 -> 1635 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/findr.pngbin0 -> 2103 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/forward.pngbin0 -> 3712 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/new.pngbin0 -> 1007 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/open.pngbin0 -> 1436 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/package.pngbin0 -> 1066 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/paste.pngbin0 -> 1026 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/pref.pngbin0 -> 2128 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/print.pngbin0 -> 1012 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/redo.pngbin0 -> 1501 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/save.pngbin0 -> 1970 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/theme.pngbin0 -> 1529 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/undo.pngbin0 -> 1600 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/web.pngbin0 -> 2250 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.6.eggbin0 -> 164192 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.7.eggbin0 -> 163563 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.6.eggbin0 -> 54713 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.7.eggbin0 -> 54538 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.6.eggbin0 -> 59322 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.7.eggbin0 -> 59162 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.6.eggbin0 -> 5941 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.7.eggbin0 -> 5926 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.cfg5
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.py640
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/Editra.py1188
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/__init__.py13
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/__init__.py22
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/autocomp.py112
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/completer.py304
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/csscomp.py169
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/htmlcomp.py192
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/pycomp.py1039
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/simplecomp.py120
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/dev_tool.py343
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/doctools.py244
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/__init__.py46
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_dirmon.py331
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_efactory.py124
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_threads.py110
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_trash.py205
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_winrecycle.py338
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/backupmgr.py179
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/calllock.py95
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/clipboard.py151
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/cmenumgr.py114
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/e_weblib.py100
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/efilehist.py135
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fchecker.py89
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileimpl.py226
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileutil.py453
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/histcache.py262
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/logfile.py104
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/miscutil.py52
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/osutil.py129
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/searcheng.py418
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/txtutil.py46
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/__init__.py50
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_filetree.py458
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_infobar.py148
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/auinavi.py231
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/choicedlg.py249
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/colorsetter.py263
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ctrlbox.py1186
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecbasewin.py78
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/eclutil.py221
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecpickers.py154
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistctrl.py198
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistmix.py103
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/encdlg.py97
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/errdlg.py370
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filemgrdlg.py259
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filterdlg.py179
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/finddlg.py1347
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/infodlg.py299
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/outbuff.py1077
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/panelbox.py445
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/platebtn.py724
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/pstatbar.py299
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/segmentbk.py438
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/txtentry.py96
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_art.py148
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basestc.py1337
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basewin.py200
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_book.py123
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_bookmark.py296
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_cmdbar.py1314
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_crypt.py120
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_editv.py641
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_event.py89
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_fmgr.py81
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_glob.py403
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_i18n.py136
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_ipc.py273
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_keyh.py286
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_log.py277
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_main.py1659
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_marker.py377
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mdlg.py158
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_menu.py1228
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mpane.py100
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_msg.py496
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_pages.py1286
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_print.py163
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_search.py1550
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_session.py290
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_shelf.py677
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_statbar.py326
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_stc.py1969
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_style.py1087
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_tab.py157
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_theme.py418
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_thread.py35
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_toolbar.py149
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_txt.py836
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_vim.py1421
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_xml.py108
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/edimage.py923
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/README11
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/__init__.py22
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/decorlib.py105
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/embeddedimage.py69
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/events.py128
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/ez_setup.py228
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/flatnotebook.py4987
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pkg_resources.py2507
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pubsub.py1263
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcprint.py614
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcspellcheck.py815
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/vertedit.py291
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/generator.py939
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/iface.py170
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/info.py22
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/perspective.py414
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugdlg.py1206
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugin.py877
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/prefdlg.py2212
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/profiler.py456
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/style_editor.py919
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/README99
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/__init__.py26
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_actionscript.py86
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ada.py78
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_apache.py176
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm.py81
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm68k.py134
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_batch.py128
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_boo.py78
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_caml.py95
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cobra.py152
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cpp.py226
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_css.py223
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_d.py144
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_diff.py71
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_django.py141
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_dot.py114
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_editra_ss.py82
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_edje.py101
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_eiffel.py81
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_erlang.py105
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ferite.py68
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_flagship.py182
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_forth.py121
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_fortran.py197
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_glsl.py66
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_groovy.py117
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_gui4cli.py148
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haskell.py84
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haxe.py65
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_html.py297
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_inno.py176
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_issuelist.py127
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_java.py120
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_javascript.py109
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_kix.py100
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_latex.py95
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lisp.py405
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lout.py116
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lua.py131
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_make.py53
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mako.py134
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_masm.py196
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_matlab.py91
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mssql.py89
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nasm.py138
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nonmem.py207
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nsis.py160
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ooc.py68
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pascal.py124
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_perl.py147
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_php.py448
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pike.py55
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_postscript.py170
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_progress.py262
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_props.py62
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_python.py238
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ruby.py149
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_s.py231
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sh.py131
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_smalltalk.py91
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sql.py392
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_squirrel.py65
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_stata.py434
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_tcl.py198
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vbscript.py95
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_verilog.py375
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vhdl.py130
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_visualbasic.py205
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xml.py63
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xtext.py261
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_yaml.py77
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syndata.py141
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synextreg.py598
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synglob.py170
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syntax.py441
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synxml.py823
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/updater.py718
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/util.py791
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/wxcompat.py49
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlackBoard.ess172
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Blue.ess197
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlueMonday.ess184
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Cream.ess209
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Default.ess198
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Dessert.ess168
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Guepardo.ess109
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Midnight.ess189
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Mocha.ess210
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/68k_assembly.68k38
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/Xtext.xtext43
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/actionscript.as38
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ada.adb13
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/apache_conf.conf31
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/bash_shell_script.sh36
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/boo.boo27
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c-shell_script.csh14
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c.c25
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/caml.ml16
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cascading_style_sheet.css52
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cilk.cilk15
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cobra.cobra25
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/coldfusion.cfm43
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cpp.cpp30
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/csharp.cs30
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/d.d59
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/diff_file.diff39
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/django.django25
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dos_batch_script.bat23
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dot.dot32
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dsp56k_assembly.56k31
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/editra_style_sheet.ess23
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/edje.edc70
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/eiffel.e27
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/erlang.erl29
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ferite.fe66
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/flagship.prg23
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/forth.4th10
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_77.for42
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_95.f9545
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/glsl.glsl19
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/groovy.groovy73
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/gui4cli.gui20
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haskell.hs39
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haxe.hx32
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/html.html39
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/inno_setup_script.iss34
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/issuelist.isl26
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/java.java42
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/javascript.js16
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/kix.kix27
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/korn_shell_script.ksh11
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/latex.tex10
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lisp.lisp26
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lout.lt34
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lua.lua38
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/makefile.mak20
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/mako.mako17
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/masm.masm20
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/matlab.matlab54
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/microsoft_sql.sql149
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/netwide_assembler.nasm24
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/newlisp.lsp22
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nonmem_control_stream.ctl21
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nullsoft_installer_script.nsi26
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/objective_c.mm56
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/octave.oct15
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ooc.ooc38
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pascal.pas31
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/perl.pl45
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/php.php69
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pike.pike28
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pl_sql.plsql94
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/plain_text.txt4
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/postscript.ps11
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/progress_4gl.4gl34
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/properties.ini14
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/python.python43
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/r.r28
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ruby.rb27
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/s.s28
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/scheme.scm17
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/smalltalk.st41
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/sql.sql166
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/squirrel.nut40
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/stata.do14
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/svg.svg39
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/system_verilog.sv139
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/tcl_tk.tcl60
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/unicode_text.txt18
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vala.vala31
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vbscript.vbs51
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/verilog.v33
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vhdl.vhdl45
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/visual_basic.vb32
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/xml.xml20
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/yaml.yaml25
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/AttributePanel.py453
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/CHANGES.txt458
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/README.txt91
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/TODO.txt33
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/TestWin.py442
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/XMLTree.py265
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/XMLTreeMenu.py107
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/__init__.py4
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/attribute.py242
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/component.py793
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/encode_bitmaps.py42
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/generate.py73
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/globals.py142
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/images.py1216
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/images_32x32.py498
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/license.txt23
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/listener.py958
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/meta.py40
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/test.xrc67
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/test_wxlib.xrc19
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/tools.xrc571
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/model.py194
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/params.py1121
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugin.py150
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/_bitmaps.py321
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/DynamicSashWindow.pngbin0 -> 2431 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/EditableListBox.pngbin0 -> 4512 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/LEDNumberCtrl.pngbin0 -> 320 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/TreeListCtrl.pngbin0 -> 4758 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/separator.pngbin0 -> 154 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/sizer.pngbin0 -> 176 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/spacer.pngbin0 -> 208 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/tool.pngbin0 -> 1129 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxBitmapButton.pngbin0 -> 2992 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxBoxSizer.pngbin0 -> 184 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxButton.pngbin0 -> 3272 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxCheckBox.pngbin0 -> 2764 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxChoice.pngbin0 -> 4090 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxChoicebook.pngbin0 -> 6639 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxComboBox.pngbin0 -> 2041 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxDialog.pngbin0 -> 3302 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFilePickerCtrl.pngbin0 -> 4570 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFlexGridSizer.pngbin0 -> 193 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFrame.pngbin0 -> 3579 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGauge.pngbin0 -> 1904 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGrid.pngbin0 -> 1341 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGridBagSizer.pngbin0 -> 215 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGridSizer.pngbin0 -> 192 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGrid_bad.pngbin0 -> 6359 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxHyperlinkCtrl.pngbin0 -> 3150 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListBox.pngbin0 -> 7029 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListCtrl.pngbin0 -> 7128 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListbook.pngbin0 -> 8189 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenu.pngbin0 -> 3008 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenuBar.pngbin0 -> 2451 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenuItem.pngbin0 -> 1102 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxNotebook.pngbin0 -> 3660 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxRadioButton.pngbin0 -> 2485 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxScrollBar.pngbin0 -> 2010 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxScrolledWindow.pngbin0 -> 4525 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSlider.pngbin0 -> 2399 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSpinButton.pngbin0 -> 1083 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSpinCtrl.pngbin0 -> 2187 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSplitterWindow.pngbin0 -> 1841 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBitmap.pngbin0 -> 1441 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBox.pngbin0 -> 1586 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBoxSizer.pngbin0 -> 1559 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticLine.pngbin0 -> 450 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticText.pngbin0 -> 2756 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStatusBar.pngbin0 -> 817 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTextCtrl.pngbin0 -> 884 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxToggleButton.pngbin0 -> 3318 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxToolBar.pngbin0 -> 2613 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTreeCtrl.pngbin0 -> 8952 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTreebook.pngbin0 -> 9215 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/controls.py577
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/core.py607
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/gizmos.crx129
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/wxlib.py39
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/xh_gizmos.py158
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/xh_wxlib.py62
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/presenter.py738
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/tools.py230
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/undo.py201
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/view.py578
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.htbbin0 -> 50937 bytes
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.py267
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.xrc1064
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/__init__.py18
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/dbg.py268
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/genaxmodule.py46
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/helpviewer.py91
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2img.py90
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2png.py55
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2py.py317
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2xpm.py55
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/tools/pywxrc.py933
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/webkit.py290
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/wizard.py471
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wx/xrc.py791
-rw-r--r--lib/python2.7/site-packages/wx-3.0-msw/wxPython-3.0.2.0-py2.7.egg-info30
944 files changed, 400499 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/__init__.py
new file mode 100644
index 0000000..1bd0cd4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/__init__.py
@@ -0,0 +1,61 @@
+#----------------------------------------------------------------------------
+# Name: __init__.py
+# Purpose: The presence of this file turns this directory into a
+# Python package.
+#
+# Author: Robin Dunn
+#
+# Created: 8-Aug-1998
+# RCS-ID: $Id$
+# Copyright: (c) 1998 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+import __version__
+__version__ = __version__.VERSION_STRING
+
+
+__all__ = [
+ # Sub-packages
+ 'build',
+ 'lib',
+ 'py',
+ 'tools',
+
+ # other modules
+ 'animate',
+ 'aui',
+ 'calendar',
+ 'combo',
+ 'grid',
+ 'html',
+ 'media',
+ 'richtext',
+ 'webkit',
+ 'wizard',
+ 'xrc',
+
+ # contribs (need a better way to find these...)
+ 'gizmos',
+ 'glcanvas',
+ 'stc',
+ ]
+
+# Load the package namespace with the core classes and such
+from wx._core import *
+del wx
+
+if 'wxMSW' in PlatformInfo:
+ __all__ += ['activex']
+
+# Load up __all__ with all the names of items that should appear to be
+# defined in this pacakge so epydoc will document them that way.
+import wx._core
+__docfilter__ = wx._core.__DocFilter(globals())
+
+__all__ += [name for name in dir(wx._core) if not name.startswith('_')]
+
+
+
+#----------------------------------------------------------------------------
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/__version__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/__version__.py
new file mode 100644
index 0000000..b32e95a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/__version__.py
@@ -0,0 +1,10 @@
+# This file was generated by setup.py...
+
+VERSION_STRING = '3.0.2.0'
+MAJOR_VERSION = 3
+MINOR_VERSION = 0
+RELEASE_VERSION = 2
+SUBREL_VERSION = 0
+
+VERSION = (MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION,
+ SUBREL_VERSION, '')
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_animate.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_animate.pyd
new file mode 100644
index 0000000..8414dbf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_animate.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_aui.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_aui.pyd
new file mode 100644
index 0000000..180d802
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_aui.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_calendar.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_calendar.pyd
new file mode 100644
index 0000000..ca70dad
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_calendar.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_combo.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_combo.pyd
new file mode 100644
index 0000000..8b59fa1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_combo.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_controls.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/_controls.py
new file mode 100644
index 0000000..b47c1f7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_controls.py
@@ -0,0 +1,7871 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+import _controls_
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+wx = _core
+#---------------------------------------------------------------------------
+
+BU_LEFT = _controls_.BU_LEFT
+BU_TOP = _controls_.BU_TOP
+BU_RIGHT = _controls_.BU_RIGHT
+BU_BOTTOM = _controls_.BU_BOTTOM
+BU_ALIGN_MASK = _controls_.BU_ALIGN_MASK
+BU_EXACTFIT = _controls_.BU_EXACTFIT
+BU_AUTODRAW = _controls_.BU_AUTODRAW
+BU_NOTEXT = _controls_.BU_NOTEXT
+class AnyButton(_core.Control):
+ """Proxy of C++ AnyButton class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def SetBitmap(*args, **kwargs):
+ """SetBitmap(self, Bitmap bitmap, int dir=LEFT)"""
+ return _controls_.AnyButton_SetBitmap(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self) -> Bitmap"""
+ return _controls_.AnyButton_GetBitmap(*args, **kwargs)
+
+ Bitmap = property(GetBitmap,SetBitmap)
+ def SetBitmapLabel(*args, **kwargs):
+ """SetBitmapLabel(self, Bitmap bitmap)"""
+ return _controls_.AnyButton_SetBitmapLabel(*args, **kwargs)
+
+ def SetBitmapPressed(*args, **kwargs):
+ """SetBitmapPressed(self, Bitmap bitmap)"""
+ return _controls_.AnyButton_SetBitmapPressed(*args, **kwargs)
+
+ def SetBitmapDisabled(*args, **kwargs):
+ """SetBitmapDisabled(self, Bitmap bitmap)"""
+ return _controls_.AnyButton_SetBitmapDisabled(*args, **kwargs)
+
+ def SetBitmapCurrent(*args, **kwargs):
+ """SetBitmapCurrent(self, Bitmap bitmap)"""
+ return _controls_.AnyButton_SetBitmapCurrent(*args, **kwargs)
+
+ def SetBitmapFocus(*args, **kwargs):
+ """SetBitmapFocus(self, Bitmap bitmap)"""
+ return _controls_.AnyButton_SetBitmapFocus(*args, **kwargs)
+
+ def GetBitmapLabel(*args, **kwargs):
+ """GetBitmapLabel(self) -> Bitmap"""
+ return _controls_.AnyButton_GetBitmapLabel(*args, **kwargs)
+
+ def GetBitmapPressed(*args, **kwargs):
+ """GetBitmapPressed(self) -> Bitmap"""
+ return _controls_.AnyButton_GetBitmapPressed(*args, **kwargs)
+
+ def GetBitmapDisabled(*args, **kwargs):
+ """GetBitmapDisabled(self) -> Bitmap"""
+ return _controls_.AnyButton_GetBitmapDisabled(*args, **kwargs)
+
+ def GetBitmapCurrent(*args, **kwargs):
+ """GetBitmapCurrent(self) -> Bitmap"""
+ return _controls_.AnyButton_GetBitmapCurrent(*args, **kwargs)
+
+ def GetBitmapFocus(*args, **kwargs):
+ """GetBitmapFocus(self) -> Bitmap"""
+ return _controls_.AnyButton_GetBitmapFocus(*args, **kwargs)
+
+ BitmapLabel = property(GetBitmapLabel,SetBitmapLabel)
+ BitmapPressed = property(GetBitmapPressed,SetBitmapPressed)
+ BitmapDisabled = property(GetBitmapDisabled,SetBitmapDisabled)
+ BitmapCurrent = property(GetBitmapCurrent,SetBitmapCurrent)
+ BitmapFocus = property(GetBitmapFocus,SetBitmapFocus)
+ def GetBitmapSelected(*args, **kwargs):
+ """GetBitmapSelected(self) -> Bitmap"""
+ return _controls_.AnyButton_GetBitmapSelected(*args, **kwargs)
+
+ def GetBitmapHover(*args, **kwargs):
+ """GetBitmapHover(self) -> Bitmap"""
+ return _controls_.AnyButton_GetBitmapHover(*args, **kwargs)
+
+ def SetBitmapSelected(*args, **kwargs):
+ """SetBitmapSelected(self, Bitmap bitmap)"""
+ return _controls_.AnyButton_SetBitmapSelected(*args, **kwargs)
+
+ def SetBitmapHover(*args, **kwargs):
+ """SetBitmapHover(self, Bitmap bitmap)"""
+ return _controls_.AnyButton_SetBitmapHover(*args, **kwargs)
+
+ BitmapSelected = property(GetBitmapSelected,SetBitmapSelected)
+ BitmapHover = property(GetBitmapHover,SetBitmapHover)
+ def SetBitmapMargins(*args):
+ """
+ SetBitmapMargins(self, int x, int y)
+ SetBitmapMargins(self, Size sz)
+ """
+ return _controls_.AnyButton_SetBitmapMargins(*args)
+
+ def GetBitmapMargins(*args, **kwargs):
+ """GetBitmapMargins(self) -> Size"""
+ return _controls_.AnyButton_GetBitmapMargins(*args, **kwargs)
+
+ BitmapMargins = property(GetBitmapMargins,SetBitmapMargins)
+ def SetBitmapPosition(*args, **kwargs):
+ """SetBitmapPosition(self, int dir)"""
+ return _controls_.AnyButton_SetBitmapPosition(*args, **kwargs)
+
+ def DontShowLabel(*args, **kwargs):
+ """DontShowLabel(self) -> bool"""
+ return _controls_.AnyButton_DontShowLabel(*args, **kwargs)
+
+ def ShowsLabel(*args, **kwargs):
+ """ShowsLabel(self) -> bool"""
+ return _controls_.AnyButton_ShowsLabel(*args, **kwargs)
+
+_controls_.AnyButton_swigregister(AnyButton)
+cvar = _controls_.cvar
+ButtonNameStr = cvar.ButtonNameStr
+
+class Button(AnyButton):
+ """
+ A button is a control that contains a text string, and is one of the most
+ common elements of a GUI. It may be placed on a dialog box or panel, or
+ indeed almost any other window.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ButtonNameStr) -> Button
+
+ Create and show a button. The preferred way to create standard
+ buttons is to use a standard ID and an empty label. In this case
+ wxWigets will automatically use a stock label that corresponds to the
+ ID given. These labels may vary across platforms as the platform
+ itself will provide the label if possible. In addition, the button
+ will be decorated with stock icons under GTK+ 2.
+ """
+ _controls_.Button_swiginit(self,_controls_.new_Button(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ButtonNameStr) -> bool
+
+ Acutally create the GUI Button for 2-phase creation.
+ """
+ return _controls_.Button_Create(*args, **kwargs)
+
+ def SetAuthNeeded(*args, **kwargs):
+ """SetAuthNeeded(self, bool show=True)"""
+ return _controls_.Button_SetAuthNeeded(*args, **kwargs)
+
+ def GetAuthNeeded(*args, **kwargs):
+ """GetAuthNeeded(self) -> bool"""
+ return _controls_.Button_GetAuthNeeded(*args, **kwargs)
+
+ def SetDefault(*args, **kwargs):
+ """
+ SetDefault(self) -> Window
+
+ This sets the button to be the default item for the panel or dialog box.
+ """
+ return _controls_.Button_SetDefault(*args, **kwargs)
+
+ def GetDefaultSize(*args, **kwargs):
+ """
+ GetDefaultSize() -> Size
+
+ Returns the default button size for this platform.
+ """
+ return _controls_.Button_GetDefaultSize(*args, **kwargs)
+
+ GetDefaultSize = staticmethod(GetDefaultSize)
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.Button_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+_controls_.Button_swigregister(Button)
+
+def PreButton(*args, **kwargs):
+ """
+ PreButton() -> Button
+
+ Precreate a Button for 2-phase creation.
+ """
+ val = _controls_.new_PreButton(*args, **kwargs)
+ return val
+
+def Button_GetDefaultSize(*args):
+ """
+ Button_GetDefaultSize() -> Size
+
+ Returns the default button size for this platform.
+ """
+ return _controls_.Button_GetDefaultSize(*args)
+
+def Button_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Button_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.Button_GetClassDefaultAttributes(*args, **kwargs)
+
+class BitmapButton(Button):
+ """
+ A Button that contains a bitmap. A bitmap button can be supplied with a
+ single bitmap, and wxWidgets will draw all button states using this bitmap. If
+ the application needs more control, additional bitmaps for the selected state,
+ unpressed focused state, and greyed-out state may be supplied.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Bitmap bitmap=wxNullBitmap,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=BU_AUTODRAW, Validator validator=DefaultValidator,
+ String name=ButtonNameStr) -> BitmapButton
+
+ Create and show a button with a bitmap for the label.
+ """
+ _controls_.BitmapButton_swiginit(self,_controls_.new_BitmapButton(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Bitmap bitmap=wxNullBitmap,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=BU_AUTODRAW, Validator validator=DefaultValidator,
+ String name=ButtonNameStr) -> bool
+
+ Acutally create the GUI BitmapButton for 2-phase creation.
+ """
+ return _controls_.BitmapButton_Create(*args, **kwargs)
+
+_controls_.BitmapButton_swigregister(BitmapButton)
+
+def PreBitmapButton(*args, **kwargs):
+ """
+ PreBitmapButton() -> BitmapButton
+
+ Precreate a BitmapButton for 2-phase creation.
+ """
+ val = _controls_.new_PreBitmapButton(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+CHK_2STATE = _controls_.CHK_2STATE
+CHK_3STATE = _controls_.CHK_3STATE
+CHK_ALLOW_3RD_STATE_FOR_USER = _controls_.CHK_ALLOW_3RD_STATE_FOR_USER
+class CheckBox(_core.Control):
+ """
+ A checkbox is a labelled box which by default is either on (the
+ checkmark is visible) or off (no checkmark). Optionally (When the
+ wx.CHK_3STATE style flag is set) it can have a third state, called the
+ mixed or undetermined state. Often this is used as a "Does Not
+ Apply" state.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=CheckBoxNameStr) -> CheckBox
+
+ Creates and shows a CheckBox control
+ """
+ _controls_.CheckBox_swiginit(self,_controls_.new_CheckBox(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=CheckBoxNameStr) -> bool
+
+ Actually create the GUI CheckBox for 2-phase creation.
+ """
+ return _controls_.CheckBox_Create(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """
+ GetValue(self) -> bool
+
+ Gets the state of a 2-state CheckBox. Returns True if it is checked,
+ False otherwise.
+ """
+ return _controls_.CheckBox_GetValue(*args, **kwargs)
+
+ def IsChecked(*args, **kwargs):
+ """
+ IsChecked(self) -> bool
+
+ Similar to GetValue, but raises an exception if it is not a 2-state
+ CheckBox.
+ """
+ return _controls_.CheckBox_IsChecked(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """
+ SetValue(self, bool state)
+
+ Set the state of a 2-state CheckBox. Pass True for checked, False for
+ unchecked.
+ """
+ return _controls_.CheckBox_SetValue(*args, **kwargs)
+
+ def Get3StateValue(*args, **kwargs):
+ """
+ Get3StateValue(self) -> int
+
+ Returns wx.CHK_UNCHECKED when the CheckBox is unchecked,
+ wx.CHK_CHECKED when it is checked and wx.CHK_UNDETERMINED when it's in
+ the undetermined state. Raises an exceptiion when the function is
+ used with a 2-state CheckBox.
+ """
+ return _controls_.CheckBox_Get3StateValue(*args, **kwargs)
+
+ def Set3StateValue(*args, **kwargs):
+ """
+ Set3StateValue(self, int state)
+
+ Sets the CheckBox to the given state. The state parameter can be one
+ of the following: wx.CHK_UNCHECKED (Check is off), wx.CHK_CHECKED (the
+ Check is on) or wx.CHK_UNDETERMINED (Check is mixed). Raises an
+ exception when the CheckBox is a 2-state checkbox and setting the
+ state to wx.CHK_UNDETERMINED.
+ """
+ return _controls_.CheckBox_Set3StateValue(*args, **kwargs)
+
+ def Is3State(*args, **kwargs):
+ """
+ Is3State(self) -> bool
+
+ Returns whether or not the CheckBox is a 3-state CheckBox.
+ """
+ return _controls_.CheckBox_Is3State(*args, **kwargs)
+
+ def Is3rdStateAllowedForUser(*args, **kwargs):
+ """
+ Is3rdStateAllowedForUser(self) -> bool
+
+ Returns whether or not the user can set the CheckBox to the third
+ state.
+ """
+ return _controls_.CheckBox_Is3rdStateAllowedForUser(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.CheckBox_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ ThreeStateValue = property(Get3StateValue,Set3StateValue,doc="See `Get3StateValue` and `Set3StateValue`")
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_controls_.CheckBox_swigregister(CheckBox)
+CheckBoxNameStr = cvar.CheckBoxNameStr
+
+def PreCheckBox(*args, **kwargs):
+ """
+ PreCheckBox() -> CheckBox
+
+ Precreate a CheckBox for 2-phase creation.
+ """
+ val = _controls_.new_PreCheckBox(*args, **kwargs)
+ return val
+
+def CheckBox_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ CheckBox_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.CheckBox_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class Choice(_core.ControlWithItems):
+ """
+ A Choice control is used to select one of a list of strings.
+ Unlike a `wx.ListBox`, only the selection is visible until the
+ user pulls down the menu of choices.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize,
+ List choices=EmptyList, long style=0, Validator validator=DefaultValidator,
+ String name=ChoiceNameStr) -> Choice
+
+ Create and show a Choice control
+ """
+ _controls_.Choice_swiginit(self,_controls_.new_Choice(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize,
+ List choices=EmptyList, long style=0, Validator validator=DefaultValidator,
+ String name=ChoiceNameStr) -> bool
+
+ Actually create the GUI Choice control for 2-phase creation
+ """
+ return _controls_.Choice_Create(*args, **kwargs)
+
+ def GetCurrentSelection(*args, **kwargs):
+ """
+ GetCurrentSelection(self) -> int
+
+ Unlike `GetSelection` which only returns the accepted selection value,
+ i.e. the selection in the control once the user closes the dropdown
+ list, this function returns the current selection. That is, while the
+ dropdown list is shown, it returns the currently selected item in
+ it. When it is not shown, its result is the same as for the other
+ function.
+ """
+ return _controls_.Choice_GetCurrentSelection(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.Choice_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ CurrentSelection = property(GetCurrentSelection,doc="See `GetCurrentSelection`")
+_controls_.Choice_swigregister(Choice)
+ChoiceNameStr = cvar.ChoiceNameStr
+
+def PreChoice(*args, **kwargs):
+ """
+ PreChoice() -> Choice
+
+ Precreate a Choice control for 2-phase creation.
+ """
+ val = _controls_.new_PreChoice(*args, **kwargs)
+ return val
+
+def Choice_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Choice_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.Choice_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class ComboBox(Choice,_core.TextEntry):
+ """
+ A combobox is like a combination of an edit control and a
+ listbox. It can be displayed as static list with editable or
+ read-only text field; or a drop-down list with text field.
+
+ A combobox permits a single selection only. Combobox items are
+ numbered from zero.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ List choices=EmptyList, long style=0, Validator validator=DefaultValidator,
+ String name=ComboBoxNameStr) -> ComboBox
+
+ Constructor, creates and shows a ComboBox control.
+ """
+ _controls_.ComboBox_swiginit(self,_controls_.new_ComboBox(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ List choices=EmptyList, long style=0, Validator validator=DefaultValidator,
+ String name=ChoiceNameStr) -> bool
+
+ Actually create the GUI wxComboBox control for 2-phase creation
+ """
+ return _controls_.ComboBox_Create(*args, **kwargs)
+
+ def SetMark(*args, **kwargs):
+ """
+ SetMark(self, long from, long to)
+
+ Selects the text between the two positions in the combobox text field.
+ """
+ return _controls_.ComboBox_SetMark(*args, **kwargs)
+
+ def GetMark(*args, **kwargs):
+ """
+ GetMark(self) -> (from, to)
+
+ Gets the positions of the begining and ending of the selection mark in
+ the combobox text field.
+ """
+ return _controls_.ComboBox_GetMark(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """IsEmpty(self) -> bool"""
+ return _controls_.ComboBox_IsEmpty(*args, **kwargs)
+
+ def IsListEmpty(*args, **kwargs):
+ """IsListEmpty(self) -> bool"""
+ return _controls_.ComboBox_IsListEmpty(*args, **kwargs)
+
+ def IsTextEmpty(*args, **kwargs):
+ """IsTextEmpty(self) -> bool"""
+ return _controls_.ComboBox_IsTextEmpty(*args, **kwargs)
+
+ def Popup(*args, **kwargs):
+ """Popup(self)"""
+ return _controls_.ComboBox_Popup(*args, **kwargs)
+
+ def Dismiss(*args, **kwargs):
+ """Dismiss(self)"""
+ return _controls_.ComboBox_Dismiss(*args, **kwargs)
+
+ def GetCurrentSelection(*args, **kwargs):
+ """
+ GetCurrentSelection(self) -> int
+
+ Unlike `GetSelection` which only returns the accepted selection value,
+ i.e. the selection in the control once the user closes the dropdown
+ list, this function returns the current selection. That is, while the
+ dropdown list is shown, it returns the currently selected item in
+ it. When it is not shown, its result is the same as for the other
+ function.
+ """
+ return _controls_.ComboBox_GetCurrentSelection(*args, **kwargs)
+
+ def SetStringSelection(*args, **kwargs):
+ """
+ SetStringSelection(self, String string) -> bool
+
+ Select the item with the specifed string
+ """
+ return _controls_.ComboBox_SetStringSelection(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ComboBox_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ CurrentSelection = property(GetCurrentSelection)
+ Mark = property(GetMark,SetMark)
+_controls_.ComboBox_swigregister(ComboBox)
+ComboBoxNameStr = cvar.ComboBoxNameStr
+
+def PreComboBox(*args, **kwargs):
+ """
+ PreComboBox() -> ComboBox
+
+ Precreate a ComboBox control for 2-phase creation.
+ """
+ val = _controls_.new_PreComboBox(*args, **kwargs)
+ return val
+
+def ComboBox_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ ComboBox_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ComboBox_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+GA_HORIZONTAL = _controls_.GA_HORIZONTAL
+GA_VERTICAL = _controls_.GA_VERTICAL
+GA_SMOOTH = _controls_.GA_SMOOTH
+GA_PROGRESSBAR = 0 # obsolete
+class Gauge(_core.Control):
+ """Proxy of C++ Gauge class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, int range=100, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=GA_HORIZONTAL,
+ Validator validator=DefaultValidator,
+ String name=GaugeNameStr) -> Gauge
+ """
+ _controls_.Gauge_swiginit(self,_controls_.new_Gauge(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, int range=100, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=GA_HORIZONTAL,
+ Validator validator=DefaultValidator,
+ String name=GaugeNameStr) -> bool
+ """
+ return _controls_.Gauge_Create(*args, **kwargs)
+
+ def SetRange(*args, **kwargs):
+ """SetRange(self, int range)"""
+ return _controls_.Gauge_SetRange(*args, **kwargs)
+
+ def GetRange(*args, **kwargs):
+ """GetRange(self) -> int"""
+ return _controls_.Gauge_GetRange(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, int pos)"""
+ return _controls_.Gauge_SetValue(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> int"""
+ return _controls_.Gauge_GetValue(*args, **kwargs)
+
+ def Pulse(*args, **kwargs):
+ """Pulse(self)"""
+ return _controls_.Gauge_Pulse(*args, **kwargs)
+
+ def IsVertical(*args, **kwargs):
+ """IsVertical(self) -> bool"""
+ return _controls_.Gauge_IsVertical(*args, **kwargs)
+
+ def SetShadowWidth(*args, **kwargs):
+ """SetShadowWidth(self, int w)"""
+ return _controls_.Gauge_SetShadowWidth(*args, **kwargs)
+
+ def GetShadowWidth(*args, **kwargs):
+ """GetShadowWidth(self) -> int"""
+ return _controls_.Gauge_GetShadowWidth(*args, **kwargs)
+
+ def SetBezelFace(*args, **kwargs):
+ """SetBezelFace(self, int w)"""
+ return _controls_.Gauge_SetBezelFace(*args, **kwargs)
+
+ def GetBezelFace(*args, **kwargs):
+ """GetBezelFace(self) -> int"""
+ return _controls_.Gauge_GetBezelFace(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.Gauge_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ BezelFace = property(GetBezelFace,SetBezelFace,doc="See `GetBezelFace` and `SetBezelFace`")
+ Range = property(GetRange,SetRange,doc="See `GetRange` and `SetRange`")
+ ShadowWidth = property(GetShadowWidth,SetShadowWidth,doc="See `GetShadowWidth` and `SetShadowWidth`")
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_controls_.Gauge_swigregister(Gauge)
+GaugeNameStr = cvar.GaugeNameStr
+
+def PreGauge(*args, **kwargs):
+ """PreGauge() -> Gauge"""
+ val = _controls_.new_PreGauge(*args, **kwargs)
+ return val
+
+def Gauge_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Gauge_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.Gauge_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class StaticBox(_core.Control):
+ """Proxy of C++ StaticBox class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=StaticBoxNameStr) -> StaticBox
+ """
+ _controls_.StaticBox_swiginit(self,_controls_.new_StaticBox(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=StaticBoxNameStr) -> bool
+ """
+ return _controls_.StaticBox_Create(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.StaticBox_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+_controls_.StaticBox_swigregister(StaticBox)
+StaticBitmapNameStr = cvar.StaticBitmapNameStr
+StaticBoxNameStr = cvar.StaticBoxNameStr
+StaticTextNameStr = cvar.StaticTextNameStr
+StaticLineNameStr = cvar.StaticLineNameStr
+
+def PreStaticBox(*args, **kwargs):
+ """PreStaticBox() -> StaticBox"""
+ val = _controls_.new_PreStaticBox(*args, **kwargs)
+ return val
+
+def StaticBox_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ StaticBox_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.StaticBox_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class StaticLine(_core.Control):
+ """Proxy of C++ StaticLine class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=LI_HORIZONTAL,
+ String name=StaticLineNameStr) -> StaticLine
+ """
+ _controls_.StaticLine_swiginit(self,_controls_.new_StaticLine(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=LI_HORIZONTAL,
+ String name=StaticLineNameStr) -> bool
+ """
+ return _controls_.StaticLine_Create(*args, **kwargs)
+
+ def IsVertical(*args, **kwargs):
+ """IsVertical(self) -> bool"""
+ return _controls_.StaticLine_IsVertical(*args, **kwargs)
+
+ def GetDefaultSize(*args, **kwargs):
+ """GetDefaultSize() -> int"""
+ return _controls_.StaticLine_GetDefaultSize(*args, **kwargs)
+
+ GetDefaultSize = staticmethod(GetDefaultSize)
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.StaticLine_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+_controls_.StaticLine_swigregister(StaticLine)
+
+def PreStaticLine(*args, **kwargs):
+ """PreStaticLine() -> StaticLine"""
+ val = _controls_.new_PreStaticLine(*args, **kwargs)
+ return val
+
+def StaticLine_GetDefaultSize(*args):
+ """StaticLine_GetDefaultSize() -> int"""
+ return _controls_.StaticLine_GetDefaultSize(*args)
+
+def StaticLine_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ StaticLine_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.StaticLine_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+ST_NO_AUTORESIZE = _controls_.ST_NO_AUTORESIZE
+ST_ELLIPSIZE_START = _controls_.ST_ELLIPSIZE_START
+ST_ELLIPSIZE_MIDDLE = _controls_.ST_ELLIPSIZE_MIDDLE
+ST_ELLIPSIZE_END = _controls_.ST_ELLIPSIZE_END
+class StaticText(_core.Control):
+ """Proxy of C++ StaticText class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=StaticTextNameStr) -> StaticText
+ """
+ _controls_.StaticText_swiginit(self,_controls_.new_StaticText(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=StaticTextNameStr) -> bool
+ """
+ return _controls_.StaticText_Create(*args, **kwargs)
+
+ def Wrap(*args, **kwargs):
+ """
+ Wrap(self, int width)
+
+ This functions wraps the control's label so that each of its lines
+ becomes at most ``width`` pixels wide if possible (the lines are
+ broken at words boundaries so it might not be the case if words are
+ too long). If ``width`` is negative, no wrapping is done.
+ """
+ return _controls_.StaticText_Wrap(*args, **kwargs)
+
+ def IsEllipsized(*args, **kwargs):
+ """IsEllipsized(self) -> bool"""
+ return _controls_.StaticText_IsEllipsized(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.StaticText_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+_controls_.StaticText_swigregister(StaticText)
+
+def PreStaticText(*args, **kwargs):
+ """PreStaticText() -> StaticText"""
+ val = _controls_.new_PreStaticText(*args, **kwargs)
+ return val
+
+def StaticText_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ StaticText_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.StaticText_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class StaticBitmap(_core.Control):
+ """Proxy of C++ StaticBitmap class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Bitmap bitmap=wxNullBitmap,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=StaticBitmapNameStr) -> StaticBitmap
+ """
+ _controls_.StaticBitmap_swiginit(self,_controls_.new_StaticBitmap(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Bitmap bitmap=wxNullBitmap,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=StaticBitmapNameStr) -> bool
+ """
+ return _controls_.StaticBitmap_Create(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self) -> Bitmap"""
+ return _controls_.StaticBitmap_GetBitmap(*args, **kwargs)
+
+ def SetBitmap(*args, **kwargs):
+ """SetBitmap(self, Bitmap bitmap)"""
+ return _controls_.StaticBitmap_SetBitmap(*args, **kwargs)
+
+ def SetIcon(*args, **kwargs):
+ """SetIcon(self, Icon icon)"""
+ return _controls_.StaticBitmap_SetIcon(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.StaticBitmap_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+_controls_.StaticBitmap_swigregister(StaticBitmap)
+
+def PreStaticBitmap(*args, **kwargs):
+ """PreStaticBitmap() -> StaticBitmap"""
+ val = _controls_.new_PreStaticBitmap(*args, **kwargs)
+ return val
+
+def StaticBitmap_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ StaticBitmap_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.StaticBitmap_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class ListBox(_core.ControlWithItems):
+ """Proxy of C++ ListBox class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, wxArrayString choices=wxPyEmptyStringArray,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ListBoxNameStr) -> ListBox
+ """
+ _controls_.ListBox_swiginit(self,_controls_.new_ListBox(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, wxArrayString choices=wxPyEmptyStringArray,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ListBoxNameStr) -> bool
+ """
+ return _controls_.ListBox_Create(*args, **kwargs)
+
+ def Insert(*args, **kwargs):
+ """
+ Insert(self, String item, int pos, PyObject clientData=None)
+
+ Insert an item into the control before the item at the ``pos`` index,
+ optionally associating some data object with the item.
+ """
+ return _controls_.ListBox_Insert(*args, **kwargs)
+
+ def InsertItems(*args, **kwargs):
+ """InsertItems(self, wxArrayString items, unsigned int pos)"""
+ return _controls_.ListBox_InsertItems(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """
+ Set(self, List strings)
+
+ Replace all the items in the control
+ """
+ return _controls_.ListBox_Set(*args, **kwargs)
+
+ def IsSelected(*args, **kwargs):
+ """IsSelected(self, int n) -> bool"""
+ return _controls_.ListBox_IsSelected(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """SetSelection(self, int n, bool select=True)"""
+ return _controls_.ListBox_SetSelection(*args, **kwargs)
+
+ def Select(*args, **kwargs):
+ """
+ Select(self, int n)
+
+ This is the same as `SetSelection` and exists only because it is
+ slightly more natural for controls which support multiple selection.
+ """
+ return _controls_.ListBox_Select(*args, **kwargs)
+
+ def Deselect(*args, **kwargs):
+ """Deselect(self, int n)"""
+ return _controls_.ListBox_Deselect(*args, **kwargs)
+
+ def DeselectAll(*args, **kwargs):
+ """DeselectAll(self, int itemToLeaveSelected=-1)"""
+ return _controls_.ListBox_DeselectAll(*args, **kwargs)
+
+ def SetStringSelection(*args, **kwargs):
+ """SetStringSelection(self, String s, bool select=True) -> bool"""
+ return _controls_.ListBox_SetStringSelection(*args, **kwargs)
+
+ def GetSelections(*args, **kwargs):
+ """GetSelections(self) -> PyObject"""
+ return _controls_.ListBox_GetSelections(*args, **kwargs)
+
+ def SetFirstItem(*args, **kwargs):
+ """SetFirstItem(self, int n)"""
+ return _controls_.ListBox_SetFirstItem(*args, **kwargs)
+
+ def SetFirstItemStr(*args, **kwargs):
+ """SetFirstItemStr(self, String s)"""
+ return _controls_.ListBox_SetFirstItemStr(*args, **kwargs)
+
+ def EnsureVisible(*args, **kwargs):
+ """EnsureVisible(self, int n)"""
+ return _controls_.ListBox_EnsureVisible(*args, **kwargs)
+
+ def AppendAndEnsureVisible(*args, **kwargs):
+ """AppendAndEnsureVisible(self, String s)"""
+ return _controls_.ListBox_AppendAndEnsureVisible(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(self, Point pt) -> int
+
+ Test where the given (in client coords) point lies
+ """
+ return _controls_.ListBox_HitTest(*args, **kwargs)
+
+ def SetItemForegroundColour(*args, **kwargs):
+ """SetItemForegroundColour(self, int item, Colour c)"""
+ return _controls_.ListBox_SetItemForegroundColour(*args, **kwargs)
+
+ def SetItemBackgroundColour(*args, **kwargs):
+ """SetItemBackgroundColour(self, int item, Colour c)"""
+ return _controls_.ListBox_SetItemBackgroundColour(*args, **kwargs)
+
+ def SetItemFont(*args, **kwargs):
+ """SetItemFont(self, int item, Font f)"""
+ return _controls_.ListBox_SetItemFont(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ListBox_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ Selections = property(GetSelections,doc="See `GetSelections`")
+_controls_.ListBox_swigregister(ListBox)
+ListBoxNameStr = cvar.ListBoxNameStr
+
+def PreListBox(*args, **kwargs):
+ """PreListBox() -> ListBox"""
+ val = _controls_.new_PreListBox(*args, **kwargs)
+ return val
+
+def ListBox_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ ListBox_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ListBox_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class CheckListBox(ListBox):
+ """Proxy of C++ CheckListBox class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, wxArrayString choices=wxPyEmptyStringArray,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ListBoxNameStr) -> CheckListBox
+ """
+ _controls_.CheckListBox_swiginit(self,_controls_.new_CheckListBox(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, wxArrayString choices=wxPyEmptyStringArray,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ListBoxNameStr) -> bool
+ """
+ return _controls_.CheckListBox_Create(*args, **kwargs)
+
+ def IsChecked(*args, **kwargs):
+ """IsChecked(self, unsigned int index) -> bool"""
+ return _controls_.CheckListBox_IsChecked(*args, **kwargs)
+
+ def Check(*args, **kwargs):
+ """Check(self, unsigned int index, int check=True)"""
+ return _controls_.CheckListBox_Check(*args, **kwargs)
+
+ def GetChecked(self):
+ """
+ GetChecked(self)
+
+ Return a tuple of integers corresponding to the checked items in
+ the control, based on `IsChecked`.
+ """
+ return tuple([i for i in range(self.Count) if self.IsChecked(i)])
+
+ def GetCheckedStrings(self):
+ """
+ GetCheckedStrings(self)
+
+ Return a tuple of strings corresponding to the checked
+ items of the control, based on `GetChecked`.
+ """
+ return tuple([self.GetString(i) for i in self.GetChecked()])
+
+ def SetChecked(self, indexes):
+ """
+ SetChecked(self, indexes)
+
+ Sets the checked state of items if the index of the item is
+ found in the indexes sequence.
+ """
+ for i in indexes:
+ assert 0 <= i < self.Count, "Index (%s) out of range" % i
+ for i in range(self.Count):
+ self.Check(i, i in indexes)
+
+ def SetCheckedStrings(self, strings):
+ """
+ SetCheckedStrings(self, indexes)
+
+ Sets the checked state of items if the item's string is found
+ in the strings sequence.
+ """
+ for s in strings:
+ assert s in self.GetStrings(), "String ('%s') not found" % s
+ for i in range(self.Count):
+ self.Check(i, self.GetString(i) in strings)
+
+ Checked = property(GetChecked,SetChecked)
+ CheckedStrings = property(GetCheckedStrings,SetCheckedStrings)
+
+_controls_.CheckListBox_swigregister(CheckListBox)
+
+def PreCheckListBox(*args, **kwargs):
+ """PreCheckListBox() -> CheckListBox"""
+ val = _controls_.new_PreCheckListBox(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+TE_NO_VSCROLL = _controls_.TE_NO_VSCROLL
+TE_AUTO_SCROLL = _controls_.TE_AUTO_SCROLL
+TE_READONLY = _controls_.TE_READONLY
+TE_MULTILINE = _controls_.TE_MULTILINE
+TE_PROCESS_TAB = _controls_.TE_PROCESS_TAB
+TE_LEFT = _controls_.TE_LEFT
+TE_CENTER = _controls_.TE_CENTER
+TE_RIGHT = _controls_.TE_RIGHT
+TE_CENTRE = _controls_.TE_CENTRE
+TE_RICH = _controls_.TE_RICH
+TE_PROCESS_ENTER = _controls_.TE_PROCESS_ENTER
+TE_PASSWORD = _controls_.TE_PASSWORD
+TE_AUTO_URL = _controls_.TE_AUTO_URL
+TE_NOHIDESEL = _controls_.TE_NOHIDESEL
+TE_DONTWRAP = _controls_.TE_DONTWRAP
+TE_CHARWRAP = _controls_.TE_CHARWRAP
+TE_WORDWRAP = _controls_.TE_WORDWRAP
+TE_BESTWRAP = _controls_.TE_BESTWRAP
+TE_RICH2 = _controls_.TE_RICH2
+TE_CAPITALIZE = _controls_.TE_CAPITALIZE
+TE_LINEWRAP = TE_CHARWRAP
+PROCESS_ENTER = TE_PROCESS_ENTER
+PASSWORD = TE_PASSWORD
+
+TEXT_ALIGNMENT_DEFAULT = _controls_.TEXT_ALIGNMENT_DEFAULT
+TEXT_ALIGNMENT_LEFT = _controls_.TEXT_ALIGNMENT_LEFT
+TEXT_ALIGNMENT_CENTRE = _controls_.TEXT_ALIGNMENT_CENTRE
+TEXT_ALIGNMENT_CENTER = _controls_.TEXT_ALIGNMENT_CENTER
+TEXT_ALIGNMENT_RIGHT = _controls_.TEXT_ALIGNMENT_RIGHT
+TEXT_ALIGNMENT_JUSTIFIED = _controls_.TEXT_ALIGNMENT_JUSTIFIED
+TEXT_ATTR_TEXT_COLOUR = _controls_.TEXT_ATTR_TEXT_COLOUR
+TEXT_ATTR_BACKGROUND_COLOUR = _controls_.TEXT_ATTR_BACKGROUND_COLOUR
+TEXT_ATTR_FONT_FACE = _controls_.TEXT_ATTR_FONT_FACE
+TEXT_ATTR_FONT_SIZE = _controls_.TEXT_ATTR_FONT_SIZE
+TEXT_ATTR_FONT_WEIGHT = _controls_.TEXT_ATTR_FONT_WEIGHT
+TEXT_ATTR_FONT_ITALIC = _controls_.TEXT_ATTR_FONT_ITALIC
+TEXT_ATTR_FONT_UNDERLINE = _controls_.TEXT_ATTR_FONT_UNDERLINE
+TEXT_ATTR_FONT_STRIKETHROUGH = _controls_.TEXT_ATTR_FONT_STRIKETHROUGH
+TEXT_ATTR_FONT_ENCODING = _controls_.TEXT_ATTR_FONT_ENCODING
+TEXT_ATTR_FONT_FAMILY = _controls_.TEXT_ATTR_FONT_FAMILY
+TEXT_ATTR_FONT = _controls_.TEXT_ATTR_FONT
+TEXT_ATTR_ALIGNMENT = _controls_.TEXT_ATTR_ALIGNMENT
+TEXT_ATTR_LEFT_INDENT = _controls_.TEXT_ATTR_LEFT_INDENT
+TEXT_ATTR_RIGHT_INDENT = _controls_.TEXT_ATTR_RIGHT_INDENT
+TEXT_ATTR_TABS = _controls_.TEXT_ATTR_TABS
+TEXT_ATTR_PARA_SPACING_AFTER = _controls_.TEXT_ATTR_PARA_SPACING_AFTER
+TEXT_ATTR_LINE_SPACING = _controls_.TEXT_ATTR_LINE_SPACING
+TEXT_ATTR_CHARACTER_STYLE_NAME = _controls_.TEXT_ATTR_CHARACTER_STYLE_NAME
+TEXT_ATTR_PARAGRAPH_STYLE_NAME = _controls_.TEXT_ATTR_PARAGRAPH_STYLE_NAME
+TEXT_ATTR_LIST_STYLE_NAME = _controls_.TEXT_ATTR_LIST_STYLE_NAME
+TEXT_ATTR_BULLET_STYLE = _controls_.TEXT_ATTR_BULLET_STYLE
+TEXT_ATTR_BULLET_NUMBER = _controls_.TEXT_ATTR_BULLET_NUMBER
+TEXT_ATTR_BULLET_TEXT = _controls_.TEXT_ATTR_BULLET_TEXT
+TEXT_ATTR_BULLET_NAME = _controls_.TEXT_ATTR_BULLET_NAME
+TEXT_ATTR_BULLET = _controls_.TEXT_ATTR_BULLET
+TEXT_ATTR_URL = _controls_.TEXT_ATTR_URL
+TEXT_ATTR_PAGE_BREAK = _controls_.TEXT_ATTR_PAGE_BREAK
+TEXT_ATTR_EFFECTS = _controls_.TEXT_ATTR_EFFECTS
+TEXT_ATTR_OUTLINE_LEVEL = _controls_.TEXT_ATTR_OUTLINE_LEVEL
+TEXT_ATTR_CHARACTER = _controls_.TEXT_ATTR_CHARACTER
+TEXT_ATTR_PARAGRAPH = _controls_.TEXT_ATTR_PARAGRAPH
+TEXT_ATTR_ALL = _controls_.TEXT_ATTR_ALL
+TEXT_ATTR_BULLET_STYLE_NONE = _controls_.TEXT_ATTR_BULLET_STYLE_NONE
+TEXT_ATTR_BULLET_STYLE_ARABIC = _controls_.TEXT_ATTR_BULLET_STYLE_ARABIC
+TEXT_ATTR_BULLET_STYLE_LETTERS_UPPER = _controls_.TEXT_ATTR_BULLET_STYLE_LETTERS_UPPER
+TEXT_ATTR_BULLET_STYLE_LETTERS_LOWER = _controls_.TEXT_ATTR_BULLET_STYLE_LETTERS_LOWER
+TEXT_ATTR_BULLET_STYLE_ROMAN_UPPER = _controls_.TEXT_ATTR_BULLET_STYLE_ROMAN_UPPER
+TEXT_ATTR_BULLET_STYLE_ROMAN_LOWER = _controls_.TEXT_ATTR_BULLET_STYLE_ROMAN_LOWER
+TEXT_ATTR_BULLET_STYLE_SYMBOL = _controls_.TEXT_ATTR_BULLET_STYLE_SYMBOL
+TEXT_ATTR_BULLET_STYLE_BITMAP = _controls_.TEXT_ATTR_BULLET_STYLE_BITMAP
+TEXT_ATTR_BULLET_STYLE_PARENTHESES = _controls_.TEXT_ATTR_BULLET_STYLE_PARENTHESES
+TEXT_ATTR_BULLET_STYLE_PERIOD = _controls_.TEXT_ATTR_BULLET_STYLE_PERIOD
+TEXT_ATTR_BULLET_STYLE_STANDARD = _controls_.TEXT_ATTR_BULLET_STYLE_STANDARD
+TEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS = _controls_.TEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS
+TEXT_ATTR_BULLET_STYLE_OUTLINE = _controls_.TEXT_ATTR_BULLET_STYLE_OUTLINE
+TEXT_ATTR_BULLET_STYLE_ALIGN_LEFT = _controls_.TEXT_ATTR_BULLET_STYLE_ALIGN_LEFT
+TEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT = _controls_.TEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT
+TEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE = _controls_.TEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE
+TEXT_ATTR_EFFECT_NONE = _controls_.TEXT_ATTR_EFFECT_NONE
+TEXT_ATTR_EFFECT_CAPITALS = _controls_.TEXT_ATTR_EFFECT_CAPITALS
+TEXT_ATTR_EFFECT_SMALL_CAPITALS = _controls_.TEXT_ATTR_EFFECT_SMALL_CAPITALS
+TEXT_ATTR_EFFECT_STRIKETHROUGH = _controls_.TEXT_ATTR_EFFECT_STRIKETHROUGH
+TEXT_ATTR_EFFECT_DOUBLE_STRIKETHROUGH = _controls_.TEXT_ATTR_EFFECT_DOUBLE_STRIKETHROUGH
+TEXT_ATTR_EFFECT_SHADOW = _controls_.TEXT_ATTR_EFFECT_SHADOW
+TEXT_ATTR_EFFECT_EMBOSS = _controls_.TEXT_ATTR_EFFECT_EMBOSS
+TEXT_ATTR_EFFECT_OUTLINE = _controls_.TEXT_ATTR_EFFECT_OUTLINE
+TEXT_ATTR_EFFECT_ENGRAVE = _controls_.TEXT_ATTR_EFFECT_ENGRAVE
+TEXT_ATTR_EFFECT_SUPERSCRIPT = _controls_.TEXT_ATTR_EFFECT_SUPERSCRIPT
+TEXT_ATTR_EFFECT_SUBSCRIPT = _controls_.TEXT_ATTR_EFFECT_SUBSCRIPT
+TEXT_ATTR_LINE_SPACING_NORMAL = _controls_.TEXT_ATTR_LINE_SPACING_NORMAL
+TEXT_ATTR_LINE_SPACING_HALF = _controls_.TEXT_ATTR_LINE_SPACING_HALF
+TEXT_ATTR_LINE_SPACING_TWICE = _controls_.TEXT_ATTR_LINE_SPACING_TWICE
+OutOfRangeTextCoord = _controls_.OutOfRangeTextCoord
+InvalidTextCoord = _controls_.InvalidTextCoord
+TEXT_TYPE_ANY = _controls_.TEXT_TYPE_ANY
+class TextAttr(object):
+ """Proxy of C++ TextAttr class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Colour colText=wxNullColour, Colour colBack=wxNullColour,
+ Font font=wxNullFont, int alignment=TEXT_ALIGNMENT_DEFAULT) -> TextAttr
+ """
+ _controls_.TextAttr_swiginit(self,_controls_.new_TextAttr(*args, **kwargs))
+ __swig_destroy__ = _controls_.delete_TextAttr
+ __del__ = lambda self : None;
+ def Init(*args, **kwargs):
+ """Init(self)"""
+ return _controls_.TextAttr_Init(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self, TextAttr attr)"""
+ return _controls_.TextAttr_Copy(*args, **kwargs)
+
+ def EqPartial(*args, **kwargs):
+ """EqPartial(self, TextAttr attr) -> bool"""
+ return _controls_.TextAttr_EqPartial(*args, **kwargs)
+
+ def GetFontAttributes(*args, **kwargs):
+ """GetFontAttributes(self, Font font, int flags=TEXT_ATTR_FONT) -> bool"""
+ return _controls_.TextAttr_GetFontAttributes(*args, **kwargs)
+
+ def SetTextColour(*args, **kwargs):
+ """SetTextColour(self, Colour colText)"""
+ return _controls_.TextAttr_SetTextColour(*args, **kwargs)
+
+ def SetBackgroundColour(*args, **kwargs):
+ """SetBackgroundColour(self, Colour colBack)"""
+ return _controls_.TextAttr_SetBackgroundColour(*args, **kwargs)
+
+ def SetAlignment(*args, **kwargs):
+ """SetAlignment(self, int alignment)"""
+ return _controls_.TextAttr_SetAlignment(*args, **kwargs)
+
+ def SetTabs(*args, **kwargs):
+ """SetTabs(self, wxArrayInt tabs)"""
+ return _controls_.TextAttr_SetTabs(*args, **kwargs)
+
+ def SetLeftIndent(*args, **kwargs):
+ """SetLeftIndent(self, int indent, int subIndent=0)"""
+ return _controls_.TextAttr_SetLeftIndent(*args, **kwargs)
+
+ def SetRightIndent(*args, **kwargs):
+ """SetRightIndent(self, int indent)"""
+ return _controls_.TextAttr_SetRightIndent(*args, **kwargs)
+
+ def SetFontSize(*args, **kwargs):
+ """SetFontSize(self, int pointSize)"""
+ return _controls_.TextAttr_SetFontSize(*args, **kwargs)
+
+ def SetFontStyle(*args, **kwargs):
+ """SetFontStyle(self, int fontStyle)"""
+ return _controls_.TextAttr_SetFontStyle(*args, **kwargs)
+
+ def SetFontWeight(*args, **kwargs):
+ """SetFontWeight(self, int fontWeight)"""
+ return _controls_.TextAttr_SetFontWeight(*args, **kwargs)
+
+ def SetFontFaceName(*args, **kwargs):
+ """SetFontFaceName(self, String faceName)"""
+ return _controls_.TextAttr_SetFontFaceName(*args, **kwargs)
+
+ def SetFontUnderlined(*args, **kwargs):
+ """SetFontUnderlined(self, bool underlined)"""
+ return _controls_.TextAttr_SetFontUnderlined(*args, **kwargs)
+
+ def SetFontStrikethrough(*args, **kwargs):
+ """SetFontStrikethrough(self, bool strikethrough)"""
+ return _controls_.TextAttr_SetFontStrikethrough(*args, **kwargs)
+
+ def SetFontEncoding(*args, **kwargs):
+ """SetFontEncoding(self, int encoding)"""
+ return _controls_.TextAttr_SetFontEncoding(*args, **kwargs)
+
+ def SetFontFamily(*args, **kwargs):
+ """SetFontFamily(self, int family)"""
+ return _controls_.TextAttr_SetFontFamily(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """SetFont(self, Font font, int flags=TEXT_ATTR_FONT)"""
+ return _controls_.TextAttr_SetFont(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, long flags)"""
+ return _controls_.TextAttr_SetFlags(*args, **kwargs)
+
+ def SetCharacterStyleName(*args, **kwargs):
+ """SetCharacterStyleName(self, String name)"""
+ return _controls_.TextAttr_SetCharacterStyleName(*args, **kwargs)
+
+ def SetParagraphStyleName(*args, **kwargs):
+ """SetParagraphStyleName(self, String name)"""
+ return _controls_.TextAttr_SetParagraphStyleName(*args, **kwargs)
+
+ def SetListStyleName(*args, **kwargs):
+ """SetListStyleName(self, String name)"""
+ return _controls_.TextAttr_SetListStyleName(*args, **kwargs)
+
+ def SetParagraphSpacingAfter(*args, **kwargs):
+ """SetParagraphSpacingAfter(self, int spacing)"""
+ return _controls_.TextAttr_SetParagraphSpacingAfter(*args, **kwargs)
+
+ def SetParagraphSpacingBefore(*args, **kwargs):
+ """SetParagraphSpacingBefore(self, int spacing)"""
+ return _controls_.TextAttr_SetParagraphSpacingBefore(*args, **kwargs)
+
+ def SetLineSpacing(*args, **kwargs):
+ """SetLineSpacing(self, int spacing)"""
+ return _controls_.TextAttr_SetLineSpacing(*args, **kwargs)
+
+ def SetBulletStyle(*args, **kwargs):
+ """SetBulletStyle(self, int style)"""
+ return _controls_.TextAttr_SetBulletStyle(*args, **kwargs)
+
+ def SetBulletNumber(*args, **kwargs):
+ """SetBulletNumber(self, int n)"""
+ return _controls_.TextAttr_SetBulletNumber(*args, **kwargs)
+
+ def SetBulletText(*args, **kwargs):
+ """SetBulletText(self, String text)"""
+ return _controls_.TextAttr_SetBulletText(*args, **kwargs)
+
+ def SetBulletFont(*args, **kwargs):
+ """SetBulletFont(self, String bulletFont)"""
+ return _controls_.TextAttr_SetBulletFont(*args, **kwargs)
+
+ def SetBulletName(*args, **kwargs):
+ """SetBulletName(self, String name)"""
+ return _controls_.TextAttr_SetBulletName(*args, **kwargs)
+
+ def SetURL(*args, **kwargs):
+ """SetURL(self, String url)"""
+ return _controls_.TextAttr_SetURL(*args, **kwargs)
+
+ def SetPageBreak(*args, **kwargs):
+ """SetPageBreak(self, bool pageBreak=True)"""
+ return _controls_.TextAttr_SetPageBreak(*args, **kwargs)
+
+ def SetTextEffects(*args, **kwargs):
+ """SetTextEffects(self, int effects)"""
+ return _controls_.TextAttr_SetTextEffects(*args, **kwargs)
+
+ def SetTextEffectFlags(*args, **kwargs):
+ """SetTextEffectFlags(self, int effects)"""
+ return _controls_.TextAttr_SetTextEffectFlags(*args, **kwargs)
+
+ def SetOutlineLevel(*args, **kwargs):
+ """SetOutlineLevel(self, int level)"""
+ return _controls_.TextAttr_SetOutlineLevel(*args, **kwargs)
+
+ def GetTextColour(*args, **kwargs):
+ """GetTextColour(self) -> Colour"""
+ return _controls_.TextAttr_GetTextColour(*args, **kwargs)
+
+ def GetBackgroundColour(*args, **kwargs):
+ """GetBackgroundColour(self) -> Colour"""
+ return _controls_.TextAttr_GetBackgroundColour(*args, **kwargs)
+
+ def GetAlignment(*args, **kwargs):
+ """GetAlignment(self) -> int"""
+ return _controls_.TextAttr_GetAlignment(*args, **kwargs)
+
+ def GetTabs(*args, **kwargs):
+ """GetTabs(self) -> wxArrayInt"""
+ return _controls_.TextAttr_GetTabs(*args, **kwargs)
+
+ def GetLeftIndent(*args, **kwargs):
+ """GetLeftIndent(self) -> long"""
+ return _controls_.TextAttr_GetLeftIndent(*args, **kwargs)
+
+ def GetLeftSubIndent(*args, **kwargs):
+ """GetLeftSubIndent(self) -> long"""
+ return _controls_.TextAttr_GetLeftSubIndent(*args, **kwargs)
+
+ def GetRightIndent(*args, **kwargs):
+ """GetRightIndent(self) -> long"""
+ return _controls_.TextAttr_GetRightIndent(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> long"""
+ return _controls_.TextAttr_GetFlags(*args, **kwargs)
+
+ def GetFontSize(*args, **kwargs):
+ """GetFontSize(self) -> int"""
+ return _controls_.TextAttr_GetFontSize(*args, **kwargs)
+
+ def GetFontStyle(*args, **kwargs):
+ """GetFontStyle(self) -> int"""
+ return _controls_.TextAttr_GetFontStyle(*args, **kwargs)
+
+ def GetFontWeight(*args, **kwargs):
+ """GetFontWeight(self) -> int"""
+ return _controls_.TextAttr_GetFontWeight(*args, **kwargs)
+
+ def GetFontUnderlined(*args, **kwargs):
+ """GetFontUnderlined(self) -> bool"""
+ return _controls_.TextAttr_GetFontUnderlined(*args, **kwargs)
+
+ def GetFontStrikethrough(*args, **kwargs):
+ """GetFontStrikethrough(self) -> bool"""
+ return _controls_.TextAttr_GetFontStrikethrough(*args, **kwargs)
+
+ def GetFontFaceName(*args, **kwargs):
+ """GetFontFaceName(self) -> String"""
+ return _controls_.TextAttr_GetFontFaceName(*args, **kwargs)
+
+ def GetFontEncoding(*args, **kwargs):
+ """GetFontEncoding(self) -> int"""
+ return _controls_.TextAttr_GetFontEncoding(*args, **kwargs)
+
+ def GetFontFamily(*args, **kwargs):
+ """GetFontFamily(self) -> int"""
+ return _controls_.TextAttr_GetFontFamily(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """GetFont(self) -> Font"""
+ return _controls_.TextAttr_GetFont(*args, **kwargs)
+
+ CreateFont = GetFont
+ def GetCharacterStyleName(*args, **kwargs):
+ """GetCharacterStyleName(self) -> String"""
+ return _controls_.TextAttr_GetCharacterStyleName(*args, **kwargs)
+
+ def GetParagraphStyleName(*args, **kwargs):
+ """GetParagraphStyleName(self) -> String"""
+ return _controls_.TextAttr_GetParagraphStyleName(*args, **kwargs)
+
+ def GetListStyleName(*args, **kwargs):
+ """GetListStyleName(self) -> String"""
+ return _controls_.TextAttr_GetListStyleName(*args, **kwargs)
+
+ def GetParagraphSpacingAfter(*args, **kwargs):
+ """GetParagraphSpacingAfter(self) -> int"""
+ return _controls_.TextAttr_GetParagraphSpacingAfter(*args, **kwargs)
+
+ def GetParagraphSpacingBefore(*args, **kwargs):
+ """GetParagraphSpacingBefore(self) -> int"""
+ return _controls_.TextAttr_GetParagraphSpacingBefore(*args, **kwargs)
+
+ def GetLineSpacing(*args, **kwargs):
+ """GetLineSpacing(self) -> int"""
+ return _controls_.TextAttr_GetLineSpacing(*args, **kwargs)
+
+ def GetBulletStyle(*args, **kwargs):
+ """GetBulletStyle(self) -> int"""
+ return _controls_.TextAttr_GetBulletStyle(*args, **kwargs)
+
+ def GetBulletNumber(*args, **kwargs):
+ """GetBulletNumber(self) -> int"""
+ return _controls_.TextAttr_GetBulletNumber(*args, **kwargs)
+
+ def GetBulletText(*args, **kwargs):
+ """GetBulletText(self) -> String"""
+ return _controls_.TextAttr_GetBulletText(*args, **kwargs)
+
+ def GetBulletFont(*args, **kwargs):
+ """GetBulletFont(self) -> String"""
+ return _controls_.TextAttr_GetBulletFont(*args, **kwargs)
+
+ def GetBulletName(*args, **kwargs):
+ """GetBulletName(self) -> String"""
+ return _controls_.TextAttr_GetBulletName(*args, **kwargs)
+
+ def GetURL(*args, **kwargs):
+ """GetURL(self) -> String"""
+ return _controls_.TextAttr_GetURL(*args, **kwargs)
+
+ def GetTextEffects(*args, **kwargs):
+ """GetTextEffects(self) -> int"""
+ return _controls_.TextAttr_GetTextEffects(*args, **kwargs)
+
+ def GetTextEffectFlags(*args, **kwargs):
+ """GetTextEffectFlags(self) -> int"""
+ return _controls_.TextAttr_GetTextEffectFlags(*args, **kwargs)
+
+ def GetOutlineLevel(*args, **kwargs):
+ """GetOutlineLevel(self) -> int"""
+ return _controls_.TextAttr_GetOutlineLevel(*args, **kwargs)
+
+ def HasTextColour(*args, **kwargs):
+ """HasTextColour(self) -> bool"""
+ return _controls_.TextAttr_HasTextColour(*args, **kwargs)
+
+ def HasBackgroundColour(*args, **kwargs):
+ """HasBackgroundColour(self) -> bool"""
+ return _controls_.TextAttr_HasBackgroundColour(*args, **kwargs)
+
+ def HasAlignment(*args, **kwargs):
+ """HasAlignment(self) -> bool"""
+ return _controls_.TextAttr_HasAlignment(*args, **kwargs)
+
+ def HasTabs(*args, **kwargs):
+ """HasTabs(self) -> bool"""
+ return _controls_.TextAttr_HasTabs(*args, **kwargs)
+
+ def HasLeftIndent(*args, **kwargs):
+ """HasLeftIndent(self) -> bool"""
+ return _controls_.TextAttr_HasLeftIndent(*args, **kwargs)
+
+ def HasRightIndent(*args, **kwargs):
+ """HasRightIndent(self) -> bool"""
+ return _controls_.TextAttr_HasRightIndent(*args, **kwargs)
+
+ def HasFontWeight(*args, **kwargs):
+ """HasFontWeight(self) -> bool"""
+ return _controls_.TextAttr_HasFontWeight(*args, **kwargs)
+
+ def HasFontSize(*args, **kwargs):
+ """HasFontSize(self) -> bool"""
+ return _controls_.TextAttr_HasFontSize(*args, **kwargs)
+
+ def HasFontItalic(*args, **kwargs):
+ """HasFontItalic(self) -> bool"""
+ return _controls_.TextAttr_HasFontItalic(*args, **kwargs)
+
+ def HasFontUnderlined(*args, **kwargs):
+ """HasFontUnderlined(self) -> bool"""
+ return _controls_.TextAttr_HasFontUnderlined(*args, **kwargs)
+
+ def HasFontStrikethrough(*args, **kwargs):
+ """HasFontStrikethrough(self) -> bool"""
+ return _controls_.TextAttr_HasFontStrikethrough(*args, **kwargs)
+
+ def HasFontFaceName(*args, **kwargs):
+ """HasFontFaceName(self) -> bool"""
+ return _controls_.TextAttr_HasFontFaceName(*args, **kwargs)
+
+ def HasFontEncoding(*args, **kwargs):
+ """HasFontEncoding(self) -> bool"""
+ return _controls_.TextAttr_HasFontEncoding(*args, **kwargs)
+
+ def HasFontFamily(*args, **kwargs):
+ """HasFontFamily(self) -> bool"""
+ return _controls_.TextAttr_HasFontFamily(*args, **kwargs)
+
+ def HasFont(*args, **kwargs):
+ """HasFont(self) -> bool"""
+ return _controls_.TextAttr_HasFont(*args, **kwargs)
+
+ def HasParagraphSpacingAfter(*args, **kwargs):
+ """HasParagraphSpacingAfter(self) -> bool"""
+ return _controls_.TextAttr_HasParagraphSpacingAfter(*args, **kwargs)
+
+ def HasParagraphSpacingBefore(*args, **kwargs):
+ """HasParagraphSpacingBefore(self) -> bool"""
+ return _controls_.TextAttr_HasParagraphSpacingBefore(*args, **kwargs)
+
+ def HasLineSpacing(*args, **kwargs):
+ """HasLineSpacing(self) -> bool"""
+ return _controls_.TextAttr_HasLineSpacing(*args, **kwargs)
+
+ def HasCharacterStyleName(*args, **kwargs):
+ """HasCharacterStyleName(self) -> bool"""
+ return _controls_.TextAttr_HasCharacterStyleName(*args, **kwargs)
+
+ def HasParagraphStyleName(*args, **kwargs):
+ """HasParagraphStyleName(self) -> bool"""
+ return _controls_.TextAttr_HasParagraphStyleName(*args, **kwargs)
+
+ def HasListStyleName(*args, **kwargs):
+ """HasListStyleName(self) -> bool"""
+ return _controls_.TextAttr_HasListStyleName(*args, **kwargs)
+
+ def HasBulletStyle(*args, **kwargs):
+ """HasBulletStyle(self) -> bool"""
+ return _controls_.TextAttr_HasBulletStyle(*args, **kwargs)
+
+ def HasBulletNumber(*args, **kwargs):
+ """HasBulletNumber(self) -> bool"""
+ return _controls_.TextAttr_HasBulletNumber(*args, **kwargs)
+
+ def HasBulletText(*args, **kwargs):
+ """HasBulletText(self) -> bool"""
+ return _controls_.TextAttr_HasBulletText(*args, **kwargs)
+
+ def HasBulletName(*args, **kwargs):
+ """HasBulletName(self) -> bool"""
+ return _controls_.TextAttr_HasBulletName(*args, **kwargs)
+
+ def HasURL(*args, **kwargs):
+ """HasURL(self) -> bool"""
+ return _controls_.TextAttr_HasURL(*args, **kwargs)
+
+ def HasPageBreak(*args, **kwargs):
+ """HasPageBreak(self) -> bool"""
+ return _controls_.TextAttr_HasPageBreak(*args, **kwargs)
+
+ def HasTextEffects(*args, **kwargs):
+ """HasTextEffects(self) -> bool"""
+ return _controls_.TextAttr_HasTextEffects(*args, **kwargs)
+
+ def HasTextEffect(*args, **kwargs):
+ """HasTextEffect(self, int effect) -> bool"""
+ return _controls_.TextAttr_HasTextEffect(*args, **kwargs)
+
+ def HasOutlineLevel(*args, **kwargs):
+ """HasOutlineLevel(self) -> bool"""
+ return _controls_.TextAttr_HasOutlineLevel(*args, **kwargs)
+
+ def HasFlag(*args, **kwargs):
+ """HasFlag(self, long flag) -> bool"""
+ return _controls_.TextAttr_HasFlag(*args, **kwargs)
+
+ def RemoveFlag(*args, **kwargs):
+ """RemoveFlag(self, long flag)"""
+ return _controls_.TextAttr_RemoveFlag(*args, **kwargs)
+
+ def AddFlag(*args, **kwargs):
+ """AddFlag(self, long flag)"""
+ return _controls_.TextAttr_AddFlag(*args, **kwargs)
+
+ def IsCharacterStyle(*args, **kwargs):
+ """IsCharacterStyle(self) -> bool"""
+ return _controls_.TextAttr_IsCharacterStyle(*args, **kwargs)
+
+ def IsParagraphStyle(*args, **kwargs):
+ """IsParagraphStyle(self) -> bool"""
+ return _controls_.TextAttr_IsParagraphStyle(*args, **kwargs)
+
+ def IsDefault(*args, **kwargs):
+ """IsDefault(self) -> bool"""
+ return _controls_.TextAttr_IsDefault(*args, **kwargs)
+
+ def Apply(*args, **kwargs):
+ """Apply(self, TextAttr style, TextAttr compareWith=None) -> bool"""
+ return _controls_.TextAttr_Apply(*args, **kwargs)
+
+ def Merge(*args, **kwargs):
+ """Merge(self, TextAttr overlay)"""
+ return _controls_.TextAttr_Merge(*args, **kwargs)
+
+ def Combine(*args, **kwargs):
+ """Combine(TextAttr attr, TextAttr attrDef, TextCtrl text) -> TextAttr"""
+ return _controls_.TextAttr_Combine(*args, **kwargs)
+
+ Combine = staticmethod(Combine)
+ def TabsEq(*args, **kwargs):
+ """TabsEq(wxArrayInt tabs1, wxArrayInt tabs2) -> bool"""
+ return _controls_.TextAttr_TabsEq(*args, **kwargs)
+
+ TabsEq = staticmethod(TabsEq)
+ def RemoveStyle(*args, **kwargs):
+ """RemoveStyle(TextAttr destStyle, TextAttr style) -> bool"""
+ return _controls_.TextAttr_RemoveStyle(*args, **kwargs)
+
+ RemoveStyle = staticmethod(RemoveStyle)
+ def CombineBitlists(*args, **kwargs):
+ """CombineBitlists(int valueA, int valueB, int flagsA, int flagsB) -> bool"""
+ return _controls_.TextAttr_CombineBitlists(*args, **kwargs)
+
+ CombineBitlists = staticmethod(CombineBitlists)
+ def BitlistsEqPartial(*args, **kwargs):
+ """BitlistsEqPartial(int valueA, int valueB, int flags) -> bool"""
+ return _controls_.TextAttr_BitlistsEqPartial(*args, **kwargs)
+
+ BitlistsEqPartial = staticmethod(BitlistsEqPartial)
+ def SplitParaCharStyles(*args, **kwargs):
+ """SplitParaCharStyles(TextAttr style, TextAttr parStyle, TextAttr charStyle) -> bool"""
+ return _controls_.TextAttr_SplitParaCharStyles(*args, **kwargs)
+
+ SplitParaCharStyles = staticmethod(SplitParaCharStyles)
+ Alignment = property(GetAlignment,SetAlignment)
+ BackgroundColour = property(GetBackgroundColour,SetBackgroundColour)
+ Flags = property(GetFlags,SetFlags)
+ Font = property(GetFont,SetFont)
+ LeftIndent = property(GetLeftIndent,SetLeftIndent)
+ LeftSubIndent = property(GetLeftSubIndent)
+ RightIndent = property(GetRightIndent,SetRightIndent)
+ Tabs = property(GetTabs,SetTabs)
+ TextColour = property(GetTextColour,SetTextColour)
+ FontSize = property(GetFontSize,SetFontSize)
+ FontStyle = property(GetFontStyle,SetFontStyle)
+ FontWeight = property(GetFontWeight,SetFontWeight)
+ FontUnderlined = property(GetFontUnderlined,SetFontUnderlined)
+ FontFaceName = property(GetFontFaceName,SetFontFaceName)
+ FontEncoding = property(GetFontEncoding,SetFontEncoding)
+ FontFamily = property(GetFontFamily,SetFontFamily)
+ CharacterStyleName = property(GetCharacterStyleName,SetCharacterStyleName)
+ ParagraphStyleName = property(GetParagraphStyleName,SetParagraphStyleName)
+ ListStyleName = property(GetListStyleName,SetListStyleName)
+ ParagraphSpacingAfter = property(GetParagraphSpacingAfter,SetParagraphSpacingAfter)
+ ParagraphSpacingBefore = property(GetParagraphSpacingBefore,SetParagraphSpacingBefore)
+ LineSpacing = property(GetLineSpacing,SetLineSpacing)
+ BulletStyle = property(GetBulletStyle,SetBulletStyle)
+ BulletNumber = property(GetBulletNumber,SetBulletNumber)
+ BulletText = property(GetBulletText,SetBulletText)
+ BulletFont = property(GetBulletFont,SetBulletFont)
+ BulletName = property(GetBulletName,SetBulletName)
+ URL = property(GetURL,SetURL)
+ TextEffects = property(GetTextEffects,SetTextEffects)
+ TextEffectFlags = property(GetTextEffectFlags,SetTextEffectFlags)
+ OutlineLevel = property(GetOutlineLevel,SetOutlineLevel)
+_controls_.TextAttr_swigregister(TextAttr)
+TextCtrlNameStr = cvar.TextCtrlNameStr
+
+def TextAttr_Combine(*args, **kwargs):
+ """TextAttr_Combine(TextAttr attr, TextAttr attrDef, TextCtrl text) -> TextAttr"""
+ return _controls_.TextAttr_Combine(*args, **kwargs)
+
+def TextAttr_TabsEq(*args, **kwargs):
+ """TextAttr_TabsEq(wxArrayInt tabs1, wxArrayInt tabs2) -> bool"""
+ return _controls_.TextAttr_TabsEq(*args, **kwargs)
+
+def TextAttr_RemoveStyle(*args, **kwargs):
+ """TextAttr_RemoveStyle(TextAttr destStyle, TextAttr style) -> bool"""
+ return _controls_.TextAttr_RemoveStyle(*args, **kwargs)
+
+def TextAttr_CombineBitlists(*args, **kwargs):
+ """TextAttr_CombineBitlists(int valueA, int valueB, int flagsA, int flagsB) -> bool"""
+ return _controls_.TextAttr_CombineBitlists(*args, **kwargs)
+
+def TextAttr_BitlistsEqPartial(*args, **kwargs):
+ """TextAttr_BitlistsEqPartial(int valueA, int valueB, int flags) -> bool"""
+ return _controls_.TextAttr_BitlistsEqPartial(*args, **kwargs)
+
+def TextAttr_SplitParaCharStyles(*args, **kwargs):
+ """TextAttr_SplitParaCharStyles(TextAttr style, TextAttr parStyle, TextAttr charStyle) -> bool"""
+ return _controls_.TextAttr_SplitParaCharStyles(*args, **kwargs)
+
+class TextCtrl(_core.TextCtrlBase):
+ """Proxy of C++ TextCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=TextCtrlNameStr) -> TextCtrl
+ """
+ _controls_.TextCtrl_swiginit(self,_controls_.new_TextCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=TextCtrlNameStr) -> bool
+ """
+ return _controls_.TextCtrl_Create(*args, **kwargs)
+
+ def IsSingleLine(*args, **kwargs):
+ """IsSingleLine(self) -> bool"""
+ return _controls_.TextCtrl_IsSingleLine(*args, **kwargs)
+
+ def IsMultiLine(*args, **kwargs):
+ """IsMultiLine(self) -> bool"""
+ return _controls_.TextCtrl_IsMultiLine(*args, **kwargs)
+
+ def EmulateKeyPress(*args, **kwargs):
+ """EmulateKeyPress(self, KeyEvent event) -> bool"""
+ return _controls_.TextCtrl_EmulateKeyPress(*args, **kwargs)
+
+ def MacCheckSpelling(*args, **kwargs):
+ """MacCheckSpelling(self, bool check)"""
+ return _controls_.TextCtrl_MacCheckSpelling(*args, **kwargs)
+
+ def SendTextUpdatedEvent(*args, **kwargs):
+ """SendTextUpdatedEvent(self)"""
+ return _controls_.TextCtrl_SendTextUpdatedEvent(*args, **kwargs)
+
+ def ShowNativeCaret(*args, **kwargs):
+ """ShowNativeCaret(self, bool show=True) -> bool"""
+ return _controls_.TextCtrl_ShowNativeCaret(*args, **kwargs)
+
+ def HideNativeCaret(*args, **kwargs):
+ """HideNativeCaret(self) -> bool"""
+ return _controls_.TextCtrl_HideNativeCaret(*args, **kwargs)
+
+ def write(*args, **kwargs):
+ """write(self, String text)"""
+ return _controls_.TextCtrl_write(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.TextCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+_controls_.TextCtrl_swigregister(TextCtrl)
+
+def PreTextCtrl(*args, **kwargs):
+ """PreTextCtrl() -> TextCtrl"""
+ val = _controls_.new_PreTextCtrl(*args, **kwargs)
+ return val
+
+def TextCtrl_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ TextCtrl_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.TextCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+wxEVT_COMMAND_TEXT_UPDATED = _controls_.wxEVT_COMMAND_TEXT_UPDATED
+wxEVT_COMMAND_TEXT_ENTER = _controls_.wxEVT_COMMAND_TEXT_ENTER
+wxEVT_COMMAND_TEXT_URL = _controls_.wxEVT_COMMAND_TEXT_URL
+wxEVT_COMMAND_TEXT_MAXLEN = _controls_.wxEVT_COMMAND_TEXT_MAXLEN
+class TextUrlEvent(_core.CommandEvent):
+ """Proxy of C++ TextUrlEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int winid, MouseEvent evtMouse, long start, long end) -> TextUrlEvent"""
+ _controls_.TextUrlEvent_swiginit(self,_controls_.new_TextUrlEvent(*args, **kwargs))
+ def GetMouseEvent(*args, **kwargs):
+ """GetMouseEvent(self) -> MouseEvent"""
+ return _controls_.TextUrlEvent_GetMouseEvent(*args, **kwargs)
+
+ def GetURLStart(*args, **kwargs):
+ """GetURLStart(self) -> long"""
+ return _controls_.TextUrlEvent_GetURLStart(*args, **kwargs)
+
+ def GetURLEnd(*args, **kwargs):
+ """GetURLEnd(self) -> long"""
+ return _controls_.TextUrlEvent_GetURLEnd(*args, **kwargs)
+
+ MouseEvent = property(GetMouseEvent,doc="See `GetMouseEvent`")
+ URLEnd = property(GetURLEnd,doc="See `GetURLEnd`")
+ URLStart = property(GetURLStart,doc="See `GetURLStart`")
+_controls_.TextUrlEvent_swigregister(TextUrlEvent)
+
+EVT_TEXT = wx.PyEventBinder( wxEVT_COMMAND_TEXT_UPDATED, 1)
+EVT_TEXT_ENTER = wx.PyEventBinder( wxEVT_COMMAND_TEXT_ENTER, 1)
+EVT_TEXT_URL = wx.PyEventBinder( wxEVT_COMMAND_TEXT_URL, 1)
+EVT_TEXT_MAXLEN = wx.PyEventBinder( wxEVT_COMMAND_TEXT_MAXLEN, 1)
+
+#---------------------------------------------------------------------------
+
+class ScrollBar(_core.Control):
+ """Proxy of C++ ScrollBar class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=SB_HORIZONTAL,
+ Validator validator=DefaultValidator, String name=ScrollBarNameStr) -> ScrollBar
+ """
+ _controls_.ScrollBar_swiginit(self,_controls_.new_ScrollBar(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=SB_HORIZONTAL,
+ Validator validator=DefaultValidator, String name=ScrollBarNameStr) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _controls_.ScrollBar_Create(*args, **kwargs)
+
+ def GetThumbPosition(*args, **kwargs):
+ """GetThumbPosition(self) -> int"""
+ return _controls_.ScrollBar_GetThumbPosition(*args, **kwargs)
+
+ def GetThumbSize(*args, **kwargs):
+ """GetThumbSize(self) -> int"""
+ return _controls_.ScrollBar_GetThumbSize(*args, **kwargs)
+
+ GetThumbLength = GetThumbSize
+ def GetPageSize(*args, **kwargs):
+ """GetPageSize(self) -> int"""
+ return _controls_.ScrollBar_GetPageSize(*args, **kwargs)
+
+ def GetRange(*args, **kwargs):
+ """GetRange(self) -> int"""
+ return _controls_.ScrollBar_GetRange(*args, **kwargs)
+
+ def IsVertical(*args, **kwargs):
+ """IsVertical(self) -> bool"""
+ return _controls_.ScrollBar_IsVertical(*args, **kwargs)
+
+ def SetThumbPosition(*args, **kwargs):
+ """SetThumbPosition(self, int viewStart)"""
+ return _controls_.ScrollBar_SetThumbPosition(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ScrollBar_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ PageSize = property(GetPageSize,doc="See `GetPageSize`")
+ Range = property(GetRange,doc="See `GetRange`")
+ ThumbPosition = property(GetThumbPosition,SetThumbPosition,doc="See `GetThumbPosition` and `SetThumbPosition`")
+ ThumbSize = property(GetThumbSize,doc="See `GetThumbSize`")
+_controls_.ScrollBar_swigregister(ScrollBar)
+ScrollBarNameStr = cvar.ScrollBarNameStr
+
+def PreScrollBar(*args, **kwargs):
+ """PreScrollBar() -> ScrollBar"""
+ val = _controls_.new_PreScrollBar(*args, **kwargs)
+ return val
+
+def ScrollBar_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ ScrollBar_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ScrollBar_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+SP_HORIZONTAL = _controls_.SP_HORIZONTAL
+SP_VERTICAL = _controls_.SP_VERTICAL
+SP_ARROW_KEYS = _controls_.SP_ARROW_KEYS
+SP_WRAP = _controls_.SP_WRAP
+class SpinButton(_core.Control):
+ """Proxy of C++ SpinButton class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=SP_HORIZONTAL,
+ String name=SPIN_BUTTON_NAME) -> SpinButton
+ """
+ _controls_.SpinButton_swiginit(self,_controls_.new_SpinButton(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=SP_HORIZONTAL,
+ String name=SPIN_BUTTON_NAME) -> bool
+ """
+ return _controls_.SpinButton_Create(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> int"""
+ return _controls_.SpinButton_GetValue(*args, **kwargs)
+
+ def GetMin(*args, **kwargs):
+ """GetMin(self) -> int"""
+ return _controls_.SpinButton_GetMin(*args, **kwargs)
+
+ def GetMax(*args, **kwargs):
+ """GetMax(self) -> int"""
+ return _controls_.SpinButton_GetMax(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, int val)"""
+ return _controls_.SpinButton_SetValue(*args, **kwargs)
+
+ def SetMin(*args, **kwargs):
+ """SetMin(self, int minVal)"""
+ return _controls_.SpinButton_SetMin(*args, **kwargs)
+
+ def SetMax(*args, **kwargs):
+ """SetMax(self, int maxVal)"""
+ return _controls_.SpinButton_SetMax(*args, **kwargs)
+
+ def SetRange(*args, **kwargs):
+ """SetRange(self, int minVal, int maxVal)"""
+ return _controls_.SpinButton_SetRange(*args, **kwargs)
+
+ def IsVertical(*args, **kwargs):
+ """IsVertical(self) -> bool"""
+ return _controls_.SpinButton_IsVertical(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.SpinButton_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ Max = property(GetMax,SetMax,doc="See `GetMax` and `SetMax`")
+ Min = property(GetMin,SetMin,doc="See `GetMin` and `SetMin`")
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_controls_.SpinButton_swigregister(SpinButton)
+SPIN_BUTTON_NAME = cvar.SPIN_BUTTON_NAME
+SpinCtrlNameStr = cvar.SpinCtrlNameStr
+
+def PreSpinButton(*args, **kwargs):
+ """PreSpinButton() -> SpinButton"""
+ val = _controls_.new_PreSpinButton(*args, **kwargs)
+ return val
+
+def SpinButton_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ SpinButton_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.SpinButton_GetClassDefaultAttributes(*args, **kwargs)
+
+class SpinCtrl(_core.Control):
+ """Proxy of C++ SpinCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxSP_ARROW_KEYS|wxALIGN_RIGHT,
+ int min=0, int max=100, int initial=0, String name=SpinCtrlNameStr) -> SpinCtrl
+ """
+ _controls_.SpinCtrl_swiginit(self,_controls_.new_SpinCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=SP_ARROW_KEYS, int min=0, int max=100,
+ int initial=0, String name=SpinCtrlNameStr) -> bool
+ """
+ return _controls_.SpinCtrl_Create(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> int"""
+ return _controls_.SpinCtrl_GetValue(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, int value)"""
+ return _controls_.SpinCtrl_SetValue(*args, **kwargs)
+
+ def SetValueString(*args, **kwargs):
+ """SetValueString(self, String text)"""
+ return _controls_.SpinCtrl_SetValueString(*args, **kwargs)
+
+ def SetRange(*args, **kwargs):
+ """SetRange(self, int minVal, int maxVal)"""
+ return _controls_.SpinCtrl_SetRange(*args, **kwargs)
+
+ def GetMin(*args, **kwargs):
+ """GetMin(self) -> int"""
+ return _controls_.SpinCtrl_GetMin(*args, **kwargs)
+
+ def GetMax(*args, **kwargs):
+ """GetMax(self) -> int"""
+ return _controls_.SpinCtrl_GetMax(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """SetSelection(self, long from, long to)"""
+ return _controls_.SpinCtrl_SetSelection(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.SpinCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ Max = property(GetMax,doc="See `GetMax`")
+ Min = property(GetMin,doc="See `GetMin`")
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_controls_.SpinCtrl_swigregister(SpinCtrl)
+
+def PreSpinCtrl(*args, **kwargs):
+ """PreSpinCtrl() -> SpinCtrl"""
+ val = _controls_.new_PreSpinCtrl(*args, **kwargs)
+ return val
+
+def SpinCtrl_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ SpinCtrl_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.SpinCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+class SpinEvent(_core.NotifyEvent):
+ """Proxy of C++ SpinEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=wxEVT_NULL, int winid=0) -> SpinEvent"""
+ _controls_.SpinEvent_swiginit(self,_controls_.new_SpinEvent(*args, **kwargs))
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> int"""
+ return _controls_.SpinEvent_GetPosition(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, int pos)"""
+ return _controls_.SpinEvent_SetPosition(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> int"""
+ return _controls_.SpinEvent_GetValue(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, int value)"""
+ return _controls_.SpinEvent_SetValue(*args, **kwargs)
+
+ Position = property(GetPosition,SetPosition)
+ Value = property(GetValue,SetValue)
+_controls_.SpinEvent_swigregister(SpinEvent)
+
+wxEVT_SPIN_UP = _controls_.wxEVT_SPIN_UP
+wxEVT_SPIN_DOWN = _controls_.wxEVT_SPIN_DOWN
+wxEVT_SPIN = _controls_.wxEVT_SPIN
+wxEVT_COMMAND_SPINCTRL_UPDATED = _controls_.wxEVT_COMMAND_SPINCTRL_UPDATED
+wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED = _controls_.wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED
+EVT_SPIN_UP = wx.PyEventBinder( wxEVT_SPIN_UP, 1)
+EVT_SPIN_DOWN = wx.PyEventBinder( wxEVT_SPIN_DOWN, 1)
+EVT_SPIN = wx.PyEventBinder( wxEVT_SPIN, 1)
+EVT_SPINCTRL = wx.PyEventBinder( wxEVT_COMMAND_SPINCTRL_UPDATED, 1)
+EVT_SPINCTRLDOUBLE = wx.PyEventBinder( wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED, 1)
+
+class SpinCtrlDouble(_core.Control):
+ """Proxy of C++ SpinCtrlDouble class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, String value=wxEmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxSP_ARROW_KEYS|wxALIGN_RIGHT,
+ double min=0, double max=100, double initial=0,
+ double inc=1, String name="wxSpinCtrlDouble") -> SpinCtrlDouble
+ """
+ _controls_.SpinCtrlDouble_swiginit(self,_controls_.new_SpinCtrlDouble(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, String value=wxEmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=SP_ARROW_KEYS, double min=0,
+ double max=100, double initial=0, double inc=1,
+ String name="wxSpinCtrlDouble") -> bool
+ """
+ return _controls_.SpinCtrlDouble_Create(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> double"""
+ return _controls_.SpinCtrlDouble_GetValue(*args, **kwargs)
+
+ def GetMin(*args, **kwargs):
+ """GetMin(self) -> double"""
+ return _controls_.SpinCtrlDouble_GetMin(*args, **kwargs)
+
+ def GetMax(*args, **kwargs):
+ """GetMax(self) -> double"""
+ return _controls_.SpinCtrlDouble_GetMax(*args, **kwargs)
+
+ def GetIncrement(*args, **kwargs):
+ """GetIncrement(self) -> double"""
+ return _controls_.SpinCtrlDouble_GetIncrement(*args, **kwargs)
+
+ def GetDigits(*args, **kwargs):
+ """GetDigits(self) -> unsigned int"""
+ return _controls_.SpinCtrlDouble_GetDigits(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, double value)"""
+ return _controls_.SpinCtrlDouble_SetValue(*args, **kwargs)
+
+ def SetRange(*args, **kwargs):
+ """SetRange(self, double minVal, double maxVal)"""
+ return _controls_.SpinCtrlDouble_SetRange(*args, **kwargs)
+
+ def SetMin(self, minVal):
+ self.SetRange(minVal, self.GetMax())
+ def SetMax(self, maxVal):
+ self.SetRange(self.GetMin(), maxVal)
+
+ def SetIncrement(*args, **kwargs):
+ """SetIncrement(self, double inc)"""
+ return _controls_.SpinCtrlDouble_SetIncrement(*args, **kwargs)
+
+ def SetDigits(*args, **kwargs):
+ """SetDigits(self, unsigned int digits)"""
+ return _controls_.SpinCtrlDouble_SetDigits(*args, **kwargs)
+
+ Value = property(GetValue,SetValue)
+ Min = property(GetMin,SetMin)
+ Max = property(GetMax,SetMax)
+ Increment = property(GetIncrement,SetIncrement)
+ Digits = property(GetDigits,SetDigits)
+_controls_.SpinCtrlDouble_swigregister(SpinCtrlDouble)
+
+def PreSpinCtrlDouble(*args, **kwargs):
+ """PreSpinCtrlDouble() -> SpinCtrlDouble"""
+ val = _controls_.new_PreSpinCtrlDouble(*args, **kwargs)
+ return val
+
+class SpinDoubleEvent(_core.NotifyEvent):
+ """Proxy of C++ SpinDoubleEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=wxEVT_NULL, int winid=0, double value=0) -> SpinDoubleEvent"""
+ _controls_.SpinDoubleEvent_swiginit(self,_controls_.new_SpinDoubleEvent(*args, **kwargs))
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> double"""
+ return _controls_.SpinDoubleEvent_GetValue(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, double value)"""
+ return _controls_.SpinDoubleEvent_SetValue(*args, **kwargs)
+
+ Value = property(GetValue,SetValue)
+_controls_.SpinDoubleEvent_swigregister(SpinDoubleEvent)
+
+EVT_SPINCTRLDOUBLE = wx.PyEventBinder( wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED, 1 )
+
+#---------------------------------------------------------------------------
+
+class RadioBox(_core.Control):
+ """Proxy of C++ RadioBox class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ wxArrayString choices=wxPyEmptyStringArray,
+ int majorDimension=0, long style=RA_HORIZONTAL,
+ Validator validator=DefaultValidator,
+ String name=RadioBoxNameStr) -> RadioBox
+ """
+ if kwargs.has_key('point'): kwargs['pos'] = kwargs['point'];del kwargs['point']
+ _controls_.RadioBox_swiginit(self,_controls_.new_RadioBox(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ wxArrayString choices=wxPyEmptyStringArray,
+ int majorDimension=0, long style=RA_HORIZONTAL,
+ Validator validator=DefaultValidator,
+ String name=RadioBoxNameStr) -> bool
+ """
+ return _controls_.RadioBox_Create(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """SetSelection(self, int n)"""
+ return _controls_.RadioBox_SetSelection(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> int"""
+ return _controls_.RadioBox_GetSelection(*args, **kwargs)
+
+ def GetStringSelection(*args, **kwargs):
+ """GetStringSelection(self) -> String"""
+ return _controls_.RadioBox_GetStringSelection(*args, **kwargs)
+
+ def SetStringSelection(*args, **kwargs):
+ """SetStringSelection(self, String s) -> bool"""
+ return _controls_.RadioBox_SetStringSelection(*args, **kwargs)
+
+ def GetCount(*args, **kwargs):
+ """GetCount(self) -> size_t"""
+ return _controls_.RadioBox_GetCount(*args, **kwargs)
+
+ def FindString(*args, **kwargs):
+ """FindString(self, String s) -> int"""
+ return _controls_.RadioBox_FindString(*args, **kwargs)
+
+ def GetString(*args, **kwargs):
+ """GetString(self, int n) -> String"""
+ return _controls_.RadioBox_GetString(*args, **kwargs)
+
+ def SetString(*args, **kwargs):
+ """SetString(self, int n, String label)"""
+ return _controls_.RadioBox_SetString(*args, **kwargs)
+
+ GetItemLabel = GetString
+ SetItemLabel = SetString
+ def EnableItem(*args, **kwargs):
+ """EnableItem(self, unsigned int n, bool enable=True)"""
+ return _controls_.RadioBox_EnableItem(*args, **kwargs)
+
+ def ShowItem(*args, **kwargs):
+ """ShowItem(self, unsigned int n, bool show=True)"""
+ return _controls_.RadioBox_ShowItem(*args, **kwargs)
+
+ def IsItemEnabled(*args, **kwargs):
+ """IsItemEnabled(self, unsigned int n) -> bool"""
+ return _controls_.RadioBox_IsItemEnabled(*args, **kwargs)
+
+ def IsItemShown(*args, **kwargs):
+ """IsItemShown(self, unsigned int n) -> bool"""
+ return _controls_.RadioBox_IsItemShown(*args, **kwargs)
+
+ def GetColumnCount(*args, **kwargs):
+ """GetColumnCount(self) -> unsigned int"""
+ return _controls_.RadioBox_GetColumnCount(*args, **kwargs)
+
+ def GetRowCount(*args, **kwargs):
+ """GetRowCount(self) -> unsigned int"""
+ return _controls_.RadioBox_GetRowCount(*args, **kwargs)
+
+ def GetNextItem(*args, **kwargs):
+ """GetNextItem(self, int item, int dir, long style) -> int"""
+ return _controls_.RadioBox_GetNextItem(*args, **kwargs)
+
+ def SetItemToolTip(*args, **kwargs):
+ """SetItemToolTip(self, unsigned int item, String text)"""
+ return _controls_.RadioBox_SetItemToolTip(*args, **kwargs)
+
+ def GetItemToolTip(*args, **kwargs):
+ """GetItemToolTip(self, unsigned int item) -> ToolTip"""
+ return _controls_.RadioBox_GetItemToolTip(*args, **kwargs)
+
+ def SetItemHelpText(*args, **kwargs):
+ """SetItemHelpText(self, unsigned int n, String helpText)"""
+ return _controls_.RadioBox_SetItemHelpText(*args, **kwargs)
+
+ def GetItemHelpText(*args, **kwargs):
+ """GetItemHelpText(self, unsigned int n) -> String"""
+ return _controls_.RadioBox_GetItemHelpText(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.RadioBox_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ ColumnCount = property(GetColumnCount,doc="See `GetColumnCount`")
+ Count = property(GetCount,doc="See `GetCount`")
+ RowCount = property(GetRowCount,doc="See `GetRowCount`")
+ Selection = property(GetSelection,SetSelection,doc="See `GetSelection` and `SetSelection`")
+ StringSelection = property(GetStringSelection,SetStringSelection,doc="See `GetStringSelection` and `SetStringSelection`")
+_controls_.RadioBox_swigregister(RadioBox)
+RadioBoxNameStr = cvar.RadioBoxNameStr
+RadioButtonNameStr = cvar.RadioButtonNameStr
+
+def PreRadioBox(*args, **kwargs):
+ """PreRadioBox() -> RadioBox"""
+ val = _controls_.new_PreRadioBox(*args, **kwargs)
+ return val
+
+def RadioBox_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ RadioBox_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.RadioBox_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class RadioButton(_core.Control):
+ """Proxy of C++ RadioButton class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=RadioButtonNameStr) -> RadioButton
+ """
+ _controls_.RadioButton_swiginit(self,_controls_.new_RadioButton(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=RadioButtonNameStr) -> bool
+ """
+ return _controls_.RadioButton_Create(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> bool"""
+ return _controls_.RadioButton_GetValue(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, bool value)"""
+ return _controls_.RadioButton_SetValue(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.RadioButton_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_controls_.RadioButton_swigregister(RadioButton)
+
+def PreRadioButton(*args, **kwargs):
+ """PreRadioButton() -> RadioButton"""
+ val = _controls_.new_PreRadioButton(*args, **kwargs)
+ return val
+
+def RadioButton_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ RadioButton_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.RadioButton_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+SL_HORIZONTAL = _controls_.SL_HORIZONTAL
+SL_VERTICAL = _controls_.SL_VERTICAL
+SL_TICKS = _controls_.SL_TICKS
+SL_AUTOTICKS = _controls_.SL_AUTOTICKS
+SL_LEFT = _controls_.SL_LEFT
+SL_TOP = _controls_.SL_TOP
+SL_RIGHT = _controls_.SL_RIGHT
+SL_BOTTOM = _controls_.SL_BOTTOM
+SL_BOTH = _controls_.SL_BOTH
+SL_SELRANGE = _controls_.SL_SELRANGE
+SL_INVERSE = _controls_.SL_INVERSE
+SL_MIN_MAX_LABELS = _controls_.SL_MIN_MAX_LABELS
+SL_VALUE_LABEL = _controls_.SL_VALUE_LABEL
+SL_LABELS = _controls_.SL_LABELS
+class Slider(_core.Control):
+ """Proxy of C++ Slider class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, int value=0, int minValue=0,
+ int maxValue=100, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=SL_HORIZONTAL,
+ Validator validator=DefaultValidator,
+ String name=SliderNameStr) -> Slider
+ """
+ if kwargs.has_key('point'): kwargs['pos'] = kwargs['point'];del kwargs['point']
+ _controls_.Slider_swiginit(self,_controls_.new_Slider(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, int value=0, int minValue=0,
+ int maxValue=100, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=SL_HORIZONTAL,
+ Validator validator=DefaultValidator,
+ String name=SliderNameStr) -> bool
+ """
+ return _controls_.Slider_Create(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> int"""
+ return _controls_.Slider_GetValue(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, int value)"""
+ return _controls_.Slider_SetValue(*args, **kwargs)
+
+ def GetMin(*args, **kwargs):
+ """GetMin(self) -> int"""
+ return _controls_.Slider_GetMin(*args, **kwargs)
+
+ def GetMax(*args, **kwargs):
+ """GetMax(self) -> int"""
+ return _controls_.Slider_GetMax(*args, **kwargs)
+
+ def SetMin(*args, **kwargs):
+ """SetMin(self, int minValue)"""
+ return _controls_.Slider_SetMin(*args, **kwargs)
+
+ def SetMax(*args, **kwargs):
+ """SetMax(self, int maxValue)"""
+ return _controls_.Slider_SetMax(*args, **kwargs)
+
+ def SetRange(*args, **kwargs):
+ """SetRange(self, int minValue, int maxValue)"""
+ return _controls_.Slider_SetRange(*args, **kwargs)
+
+ def GetRange(self):
+ return self.GetMin(), self.GetMax()
+
+ def SetLineSize(*args, **kwargs):
+ """SetLineSize(self, int lineSize)"""
+ return _controls_.Slider_SetLineSize(*args, **kwargs)
+
+ def SetPageSize(*args, **kwargs):
+ """SetPageSize(self, int pageSize)"""
+ return _controls_.Slider_SetPageSize(*args, **kwargs)
+
+ def GetLineSize(*args, **kwargs):
+ """GetLineSize(self) -> int"""
+ return _controls_.Slider_GetLineSize(*args, **kwargs)
+
+ def GetPageSize(*args, **kwargs):
+ """GetPageSize(self) -> int"""
+ return _controls_.Slider_GetPageSize(*args, **kwargs)
+
+ def SetThumbLength(*args, **kwargs):
+ """SetThumbLength(self, int lenPixels)"""
+ return _controls_.Slider_SetThumbLength(*args, **kwargs)
+
+ def GetThumbLength(*args, **kwargs):
+ """GetThumbLength(self) -> int"""
+ return _controls_.Slider_GetThumbLength(*args, **kwargs)
+
+ def SetTickFreq(*args, **kwargs):
+ """SetTickFreq(self, int n, int pos=1)"""
+ return _controls_.Slider_SetTickFreq(*args, **kwargs)
+
+ def GetTickFreq(*args, **kwargs):
+ """GetTickFreq(self) -> int"""
+ return _controls_.Slider_GetTickFreq(*args, **kwargs)
+
+ def ClearTicks(*args, **kwargs):
+ """ClearTicks(self)"""
+ return _controls_.Slider_ClearTicks(*args, **kwargs)
+
+ def SetTick(*args, **kwargs):
+ """SetTick(self, int tickPos)"""
+ return _controls_.Slider_SetTick(*args, **kwargs)
+
+ def ClearSel(*args, **kwargs):
+ """ClearSel(self)"""
+ return _controls_.Slider_ClearSel(*args, **kwargs)
+
+ def GetSelEnd(*args, **kwargs):
+ """GetSelEnd(self) -> int"""
+ return _controls_.Slider_GetSelEnd(*args, **kwargs)
+
+ def GetSelStart(*args, **kwargs):
+ """GetSelStart(self) -> int"""
+ return _controls_.Slider_GetSelStart(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """SetSelection(self, int min, int max)"""
+ return _controls_.Slider_SetSelection(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.Slider_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ LineSize = property(GetLineSize,SetLineSize,doc="See `GetLineSize` and `SetLineSize`")
+ Max = property(GetMax,SetMax,doc="See `GetMax` and `SetMax`")
+ Min = property(GetMin,SetMin,doc="See `GetMin` and `SetMin`")
+ PageSize = property(GetPageSize,SetPageSize,doc="See `GetPageSize` and `SetPageSize`")
+ SelEnd = property(GetSelEnd,doc="See `GetSelEnd`")
+ SelStart = property(GetSelStart,doc="See `GetSelStart`")
+ ThumbLength = property(GetThumbLength,SetThumbLength,doc="See `GetThumbLength` and `SetThumbLength`")
+ TickFreq = property(GetTickFreq,SetTickFreq,doc="See `GetTickFreq` and `SetTickFreq`")
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_controls_.Slider_swigregister(Slider)
+SliderNameStr = cvar.SliderNameStr
+
+def PreSlider(*args, **kwargs):
+ """PreSlider() -> Slider"""
+ val = _controls_.new_PreSlider(*args, **kwargs)
+ return val
+
+def Slider_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Slider_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.Slider_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+wxEVT_COMMAND_TOGGLEBUTTON_CLICKED = _controls_.wxEVT_COMMAND_TOGGLEBUTTON_CLICKED
+EVT_TOGGLEBUTTON = wx.PyEventBinder( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, 1)
+
+class ToggleButton(AnyButton):
+ """Proxy of C++ ToggleButton class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ToggleButtonNameStr) -> ToggleButton
+ """
+ _controls_.ToggleButton_swiginit(self,_controls_.new_ToggleButton(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ToggleButtonNameStr) -> bool
+ """
+ return _controls_.ToggleButton_Create(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, bool value)"""
+ return _controls_.ToggleButton_SetValue(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> bool"""
+ return _controls_.ToggleButton_GetValue(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ToggleButton_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_controls_.ToggleButton_swigregister(ToggleButton)
+ToggleButtonNameStr = cvar.ToggleButtonNameStr
+
+def PreToggleButton(*args, **kwargs):
+ """PreToggleButton() -> ToggleButton"""
+ val = _controls_.new_PreToggleButton(*args, **kwargs)
+ return val
+
+def ToggleButton_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ ToggleButton_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ToggleButton_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+NB_FIXEDWIDTH = _controls_.NB_FIXEDWIDTH
+NB_TOP = _controls_.NB_TOP
+NB_LEFT = _controls_.NB_LEFT
+NB_RIGHT = _controls_.NB_RIGHT
+NB_BOTTOM = _controls_.NB_BOTTOM
+NB_MULTILINE = _controls_.NB_MULTILINE
+NB_NOPAGETHEME = _controls_.NB_NOPAGETHEME
+NB_HITTEST_NOWHERE = _controls_.NB_HITTEST_NOWHERE
+NB_HITTEST_ONICON = _controls_.NB_HITTEST_ONICON
+NB_HITTEST_ONLABEL = _controls_.NB_HITTEST_ONLABEL
+NB_HITTEST_ONITEM = _controls_.NB_HITTEST_ONITEM
+NB_HITTEST_ONPAGE = _controls_.NB_HITTEST_ONPAGE
+class Notebook(_core.BookCtrlBase):
+ """Proxy of C++ Notebook class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=NotebookNameStr) -> Notebook
+ """
+ _controls_.Notebook_swiginit(self,_controls_.new_Notebook(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=NotebookNameStr) -> bool
+ """
+ return _controls_.Notebook_Create(*args, **kwargs)
+
+ def GetRowCount(*args, **kwargs):
+ """GetRowCount(self) -> int"""
+ return _controls_.Notebook_GetRowCount(*args, **kwargs)
+
+ def SetPadding(*args, **kwargs):
+ """SetPadding(self, Size padding)"""
+ return _controls_.Notebook_SetPadding(*args, **kwargs)
+
+ def SetTabSize(*args, **kwargs):
+ """SetTabSize(self, Size sz)"""
+ return _controls_.Notebook_SetTabSize(*args, **kwargs)
+
+ def GetThemeBackgroundColour(*args, **kwargs):
+ """GetThemeBackgroundColour(self) -> Colour"""
+ return _controls_.Notebook_GetThemeBackgroundColour(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.Notebook_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ def SendPageChangingEvent(*args, **kwargs):
+ """SendPageChangingEvent(self, int nPage) -> bool"""
+ return _controls_.Notebook_SendPageChangingEvent(*args, **kwargs)
+
+ def SendPageChangedEvent(*args, **kwargs):
+ """SendPageChangedEvent(self, int nPageOld, int nPageNew=-1)"""
+ return _controls_.Notebook_SendPageChangedEvent(*args, **kwargs)
+
+ RowCount = property(GetRowCount,doc="See `GetRowCount`")
+ ThemeBackgroundColour = property(GetThemeBackgroundColour,doc="See `GetThemeBackgroundColour`")
+_controls_.Notebook_swigregister(Notebook)
+NotebookNameStr = cvar.NotebookNameStr
+
+def PreNotebook(*args, **kwargs):
+ """PreNotebook() -> Notebook"""
+ val = _controls_.new_PreNotebook(*args, **kwargs)
+ return val
+
+def Notebook_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Notebook_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.Notebook_GetClassDefaultAttributes(*args, **kwargs)
+
+NotebookEvent = wx.BookCtrlEvent
+
+wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED = _controls_.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
+wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING = _controls_.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
+# wxNotebook events
+EVT_NOTEBOOK_PAGE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, 1 )
+EVT_NOTEBOOK_PAGE_CHANGING = wx.PyEventBinder( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, 1 )
+
+#----------------------------------------------------------------------------
+
+class NotebookPage(wx.Panel):
+ """
+ There is an old (and apparently unsolvable) bug when placing a
+ window with a nonstandard background colour in a wx.Notebook on
+ wxGTK1, as the notbooks's background colour would always be used
+ when the window is refreshed. The solution is to place a panel in
+ the notbook and the coloured window on the panel, sized to cover
+ the panel. This simple class does that for you, just put an
+ instance of this in the notebook and make your regular window a
+ child of this one and it will handle the resize for you.
+ """
+ def __init__(self, parent, id=-1,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.TAB_TRAVERSAL, name="panel"):
+ wx.Panel.__init__(self, parent, id, pos, size, style, name)
+ self.child = None
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ def OnSize(self, evt):
+ if self.child is None:
+ children = self.GetChildren()
+ if len(children):
+ self.child = children[0]
+ if self.child:
+ self.child.SetPosition((0,0))
+ self.child.SetSize(self.GetSize())
+
+
+#---------------------------------------------------------------------------
+
+LB_DEFAULT = _controls_.LB_DEFAULT
+LB_TOP = _controls_.LB_TOP
+LB_BOTTOM = _controls_.LB_BOTTOM
+LB_LEFT = _controls_.LB_LEFT
+LB_RIGHT = _controls_.LB_RIGHT
+LB_ALIGN_MASK = _controls_.LB_ALIGN_MASK
+class Listbook(_core.BookCtrlBase):
+ """Proxy of C++ Listbook class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=EmptyString) -> Listbook
+ """
+ _controls_.Listbook_swiginit(self,_controls_.new_Listbook(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=EmptyString) -> bool
+ """
+ return _controls_.Listbook_Create(*args, **kwargs)
+
+ def GetListView(*args, **kwargs):
+ """GetListView(self) -> ListView"""
+ return _controls_.Listbook_GetListView(*args, **kwargs)
+
+ ListView = property(GetListView,doc="See `GetListView`")
+_controls_.Listbook_swigregister(Listbook)
+
+def PreListbook(*args, **kwargs):
+ """PreListbook() -> Listbook"""
+ val = _controls_.new_PreListbook(*args, **kwargs)
+ return val
+
+ListbookEvent = wx.BookCtrlEvent
+
+wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED = _controls_.wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED
+wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING = _controls_.wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING
+EVT_LISTBOOK_PAGE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED, 1 )
+EVT_LISTBOOK_PAGE_CHANGING = wx.PyEventBinder( wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING, 1 )
+
+CHB_DEFAULT = _controls_.CHB_DEFAULT
+CHB_TOP = _controls_.CHB_TOP
+CHB_BOTTOM = _controls_.CHB_BOTTOM
+CHB_LEFT = _controls_.CHB_LEFT
+CHB_RIGHT = _controls_.CHB_RIGHT
+CHB_ALIGN_MASK = _controls_.CHB_ALIGN_MASK
+class Choicebook(_core.BookCtrlBase):
+ """Proxy of C++ Choicebook class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=EmptyString) -> Choicebook
+ """
+ _controls_.Choicebook_swiginit(self,_controls_.new_Choicebook(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=EmptyString) -> bool
+ """
+ return _controls_.Choicebook_Create(*args, **kwargs)
+
+ def GetChoiceCtrl(*args, **kwargs):
+ """GetChoiceCtrl(self) -> Choice"""
+ return _controls_.Choicebook_GetChoiceCtrl(*args, **kwargs)
+
+ ChoiceCtrl = property(GetChoiceCtrl,doc="See `GetChoiceCtrl`")
+_controls_.Choicebook_swigregister(Choicebook)
+
+def PreChoicebook(*args, **kwargs):
+ """PreChoicebook() -> Choicebook"""
+ val = _controls_.new_PreChoicebook(*args, **kwargs)
+ return val
+
+ChoicebookEvent = wx.BookCtrlEvent
+
+wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGED = _controls_.wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGED
+wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGING = _controls_.wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGING
+EVT_CHOICEBOOK_PAGE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGED, 1 )
+EVT_CHOICEBOOK_PAGE_CHANGING = wx.PyEventBinder( wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGING, 1 )
+
+#---------------------------------------------------------------------------
+
+class Treebook(_core.BookCtrlBase):
+ """Proxy of C++ Treebook class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=BK_DEFAULT,
+ String name=EmptyString) -> Treebook
+ """
+ _controls_.Treebook_swiginit(self,_controls_.new_Treebook(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=BK_DEFAULT,
+ String name=EmptyString) -> bool
+ """
+ return _controls_.Treebook_Create(*args, **kwargs)
+
+ def InsertSubPage(*args, **kwargs):
+ """
+ InsertSubPage(self, size_t pos, Window page, String text, bool select=False,
+ int imageId=NOT_FOUND) -> bool
+ """
+ return _controls_.Treebook_InsertSubPage(*args, **kwargs)
+
+ def AddSubPage(*args, **kwargs):
+ """AddSubPage(self, Window page, String text, bool select=False, int imageId=NOT_FOUND) -> bool"""
+ return _controls_.Treebook_AddSubPage(*args, **kwargs)
+
+ def IsNodeExpanded(*args, **kwargs):
+ """IsNodeExpanded(self, size_t pos) -> bool"""
+ return _controls_.Treebook_IsNodeExpanded(*args, **kwargs)
+
+ def ExpandNode(*args, **kwargs):
+ """ExpandNode(self, size_t pos, bool expand=True) -> bool"""
+ return _controls_.Treebook_ExpandNode(*args, **kwargs)
+
+ def CollapseNode(*args, **kwargs):
+ """CollapseNode(self, size_t pos) -> bool"""
+ return _controls_.Treebook_CollapseNode(*args, **kwargs)
+
+ def GetPageParent(*args, **kwargs):
+ """GetPageParent(self, size_t pos) -> int"""
+ return _controls_.Treebook_GetPageParent(*args, **kwargs)
+
+ def GetTreeCtrl(*args, **kwargs):
+ """GetTreeCtrl(self) -> TreeCtrl"""
+ return _controls_.Treebook_GetTreeCtrl(*args, **kwargs)
+
+ TreeCtrl = property(GetTreeCtrl,doc="See `GetTreeCtrl`")
+_controls_.Treebook_swigregister(Treebook)
+
+def PreTreebook(*args, **kwargs):
+ """PreTreebook() -> Treebook"""
+ val = _controls_.new_PreTreebook(*args, **kwargs)
+ return val
+
+TreebookEvent = wx.BookCtrlEvent
+
+wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED = _controls_.wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED
+wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING = _controls_.wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING
+wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED = _controls_.wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED
+wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED = _controls_.wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED
+EVT_TREEBOOK_PAGE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_TREEBOOK_PAGE_CHANGED, 1 )
+EVT_TREEBOOK_PAGE_CHANGING = wx.PyEventBinder( wxEVT_COMMAND_TREEBOOK_PAGE_CHANGING, 1)
+EVT_TREEBOOK_NODE_COLLAPSED = wx.PyEventBinder( wxEVT_COMMAND_TREEBOOK_NODE_COLLAPSED, 1 )
+EVT_TREEBOOK_NODE_EXPANDED = wx.PyEventBinder( wxEVT_COMMAND_TREEBOOK_NODE_EXPANDED, 1 )
+
+#---------------------------------------------------------------------------
+
+class Toolbook(_core.BookCtrlBase):
+ """Proxy of C++ Toolbook class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=BK_DEFAULT,
+ String name=EmptyString) -> Toolbook
+ """
+ _controls_.Toolbook_swiginit(self,_controls_.new_Toolbook(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=wxEmptyString) -> bool
+ """
+ return _controls_.Toolbook_Create(*args, **kwargs)
+
+ def GetToolBar(*args, **kwargs):
+ """GetToolBar(self) -> ToolBarBase"""
+ return _controls_.Toolbook_GetToolBar(*args, **kwargs)
+
+ def Realize(*args, **kwargs):
+ """Realize(self)"""
+ return _controls_.Toolbook_Realize(*args, **kwargs)
+
+ ToolBar = property(GetToolBar,doc="See `GetToolBar`")
+_controls_.Toolbook_swigregister(Toolbook)
+
+def PreToolbook(*args, **kwargs):
+ """PreToolbook() -> Toolbook"""
+ val = _controls_.new_PreToolbook(*args, **kwargs)
+ return val
+
+ToolbookEvent = wx.BookCtrlEvent
+
+wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED = _controls_.wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED
+wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING = _controls_.wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING
+EVT_TOOLBOOK_PAGE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED, 1)
+EVT_TOOLBOOK_PAGE_CHANGING = wx.PyEventBinder( wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING, 1)
+
+#---------------------------------------------------------------------------
+
+TOOL_STYLE_BUTTON = _controls_.TOOL_STYLE_BUTTON
+TOOL_STYLE_SEPARATOR = _controls_.TOOL_STYLE_SEPARATOR
+TOOL_STYLE_CONTROL = _controls_.TOOL_STYLE_CONTROL
+TB_HORIZONTAL = _controls_.TB_HORIZONTAL
+TB_VERTICAL = _controls_.TB_VERTICAL
+TB_TOP = _controls_.TB_TOP
+TB_LEFT = _controls_.TB_LEFT
+TB_BOTTOM = _controls_.TB_BOTTOM
+TB_RIGHT = _controls_.TB_RIGHT
+TB_3DBUTTONS = _controls_.TB_3DBUTTONS
+TB_FLAT = _controls_.TB_FLAT
+TB_DOCKABLE = _controls_.TB_DOCKABLE
+TB_NOICONS = _controls_.TB_NOICONS
+TB_TEXT = _controls_.TB_TEXT
+TB_NODIVIDER = _controls_.TB_NODIVIDER
+TB_NOALIGN = _controls_.TB_NOALIGN
+TB_HORZ_LAYOUT = _controls_.TB_HORZ_LAYOUT
+TB_HORZ_TEXT = _controls_.TB_HORZ_TEXT
+TB_NO_TOOLTIPS = _controls_.TB_NO_TOOLTIPS
+class ToolBarToolBase(_core.Object):
+ """Proxy of C++ ToolBarToolBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetId(*args, **kwargs):
+ """GetId(self) -> int"""
+ return _controls_.ToolBarToolBase_GetId(*args, **kwargs)
+
+ def GetControl(*args, **kwargs):
+ """GetControl(self) -> Control"""
+ return _controls_.ToolBarToolBase_GetControl(*args, **kwargs)
+
+ def GetToolBar(*args, **kwargs):
+ """GetToolBar(self) -> ToolBarBase"""
+ return _controls_.ToolBarToolBase_GetToolBar(*args, **kwargs)
+
+ def IsStretchable(*args, **kwargs):
+ """IsStretchable(self) -> bool"""
+ return _controls_.ToolBarToolBase_IsStretchable(*args, **kwargs)
+
+ def IsButton(*args, **kwargs):
+ """IsButton(self) -> int"""
+ return _controls_.ToolBarToolBase_IsButton(*args, **kwargs)
+
+ def IsControl(*args, **kwargs):
+ """IsControl(self) -> int"""
+ return _controls_.ToolBarToolBase_IsControl(*args, **kwargs)
+
+ def IsSeparator(*args, **kwargs):
+ """IsSeparator(self) -> int"""
+ return _controls_.ToolBarToolBase_IsSeparator(*args, **kwargs)
+
+ def IsStretchableSpace(*args, **kwargs):
+ """IsStretchableSpace(self) -> bool"""
+ return _controls_.ToolBarToolBase_IsStretchableSpace(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self) -> int"""
+ return _controls_.ToolBarToolBase_GetStyle(*args, **kwargs)
+
+ def GetKind(*args, **kwargs):
+ """GetKind(self) -> int"""
+ return _controls_.ToolBarToolBase_GetKind(*args, **kwargs)
+
+ def MakeStretchable(*args, **kwargs):
+ """MakeStretchable(self)"""
+ return _controls_.ToolBarToolBase_MakeStretchable(*args, **kwargs)
+
+ def IsEnabled(*args, **kwargs):
+ """IsEnabled(self) -> bool"""
+ return _controls_.ToolBarToolBase_IsEnabled(*args, **kwargs)
+
+ def IsToggled(*args, **kwargs):
+ """IsToggled(self) -> bool"""
+ return _controls_.ToolBarToolBase_IsToggled(*args, **kwargs)
+
+ def CanBeToggled(*args, **kwargs):
+ """CanBeToggled(self) -> bool"""
+ return _controls_.ToolBarToolBase_CanBeToggled(*args, **kwargs)
+
+ def GetNormalBitmap(*args, **kwargs):
+ """GetNormalBitmap(self) -> Bitmap"""
+ return _controls_.ToolBarToolBase_GetNormalBitmap(*args, **kwargs)
+
+ def GetDisabledBitmap(*args, **kwargs):
+ """GetDisabledBitmap(self) -> Bitmap"""
+ return _controls_.ToolBarToolBase_GetDisabledBitmap(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self) -> Bitmap"""
+ return _controls_.ToolBarToolBase_GetBitmap(*args, **kwargs)
+
+ def GetLabel(*args, **kwargs):
+ """GetLabel(self) -> String"""
+ return _controls_.ToolBarToolBase_GetLabel(*args, **kwargs)
+
+ def GetShortHelp(*args, **kwargs):
+ """GetShortHelp(self) -> String"""
+ return _controls_.ToolBarToolBase_GetShortHelp(*args, **kwargs)
+
+ def GetLongHelp(*args, **kwargs):
+ """GetLongHelp(self) -> String"""
+ return _controls_.ToolBarToolBase_GetLongHelp(*args, **kwargs)
+
+ def Enable(*args, **kwargs):
+ """Enable(self, bool enable) -> bool"""
+ return _controls_.ToolBarToolBase_Enable(*args, **kwargs)
+
+ def Toggle(*args, **kwargs):
+ """Toggle(self)"""
+ return _controls_.ToolBarToolBase_Toggle(*args, **kwargs)
+
+ def SetToggle(*args, **kwargs):
+ """SetToggle(self, bool toggle) -> bool"""
+ return _controls_.ToolBarToolBase_SetToggle(*args, **kwargs)
+
+ def SetShortHelp(*args, **kwargs):
+ """SetShortHelp(self, String help) -> bool"""
+ return _controls_.ToolBarToolBase_SetShortHelp(*args, **kwargs)
+
+ def SetLongHelp(*args, **kwargs):
+ """SetLongHelp(self, String help) -> bool"""
+ return _controls_.ToolBarToolBase_SetLongHelp(*args, **kwargs)
+
+ def SetNormalBitmap(*args, **kwargs):
+ """SetNormalBitmap(self, Bitmap bmp)"""
+ return _controls_.ToolBarToolBase_SetNormalBitmap(*args, **kwargs)
+
+ def SetDisabledBitmap(*args, **kwargs):
+ """SetDisabledBitmap(self, Bitmap bmp)"""
+ return _controls_.ToolBarToolBase_SetDisabledBitmap(*args, **kwargs)
+
+ def SetLabel(*args, **kwargs):
+ """SetLabel(self, String label)"""
+ return _controls_.ToolBarToolBase_SetLabel(*args, **kwargs)
+
+ def Detach(*args, **kwargs):
+ """Detach(self)"""
+ return _controls_.ToolBarToolBase_Detach(*args, **kwargs)
+
+ def Attach(*args, **kwargs):
+ """Attach(self, ToolBarBase tbar)"""
+ return _controls_.ToolBarToolBase_Attach(*args, **kwargs)
+
+ def SetDropdownMenu(*args, **kwargs):
+ """SetDropdownMenu(self, Menu menu)"""
+ return _controls_.ToolBarToolBase_SetDropdownMenu(*args, **kwargs)
+
+ def GetDropdownMenu(*args, **kwargs):
+ """GetDropdownMenu(self) -> Menu"""
+ return _controls_.ToolBarToolBase_GetDropdownMenu(*args, **kwargs)
+
+ def GetClientData(*args, **kwargs):
+ """GetClientData(self) -> PyObject"""
+ return _controls_.ToolBarToolBase_GetClientData(*args, **kwargs)
+
+ def SetClientData(*args, **kwargs):
+ """SetClientData(self, PyObject clientData)"""
+ return _controls_.ToolBarToolBase_SetClientData(*args, **kwargs)
+
+ GetBitmap1 = GetNormalBitmap
+ GetBitmap2 = GetDisabledBitmap
+ SetBitmap1 = SetNormalBitmap
+ SetBitmap2 = SetDisabledBitmap
+
+ Bitmap = property(GetBitmap,doc="See `GetBitmap`")
+ ClientData = property(GetClientData,SetClientData,doc="See `GetClientData` and `SetClientData`")
+ Control = property(GetControl,doc="See `GetControl`")
+ DisabledBitmap = property(GetDisabledBitmap,SetDisabledBitmap,doc="See `GetDisabledBitmap` and `SetDisabledBitmap`")
+ Id = property(GetId,doc="See `GetId`")
+ Kind = property(GetKind,doc="See `GetKind`")
+ Label = property(GetLabel,SetLabel,doc="See `GetLabel` and `SetLabel`")
+ LongHelp = property(GetLongHelp,SetLongHelp,doc="See `GetLongHelp` and `SetLongHelp`")
+ NormalBitmap = property(GetNormalBitmap,SetNormalBitmap,doc="See `GetNormalBitmap` and `SetNormalBitmap`")
+ ShortHelp = property(GetShortHelp,SetShortHelp,doc="See `GetShortHelp` and `SetShortHelp`")
+ Style = property(GetStyle,doc="See `GetStyle`")
+ ToolBar = property(GetToolBar,doc="See `GetToolBar`")
+_controls_.ToolBarToolBase_swigregister(ToolBarToolBase)
+
+class ToolBarBase(_core.Control):
+ """Proxy of C++ ToolBarBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def DoAddTool(*args, **kwargs):
+ """
+ DoAddTool(self, int id, String label, Bitmap bitmap, Bitmap bmpDisabled=wxNullBitmap,
+ int kind=ITEM_NORMAL, String shortHelp=EmptyString,
+ String longHelp=EmptyString,
+ PyObject clientData=None) -> ToolBarToolBase
+ """
+ return _controls_.ToolBarBase_DoAddTool(*args, **kwargs)
+
+ def DoInsertTool(*args, **kwargs):
+ """
+ DoInsertTool(self, size_t pos, int id, String label, Bitmap bitmap, Bitmap bmpDisabled=wxNullBitmap,
+ int kind=ITEM_NORMAL,
+ String shortHelp=EmptyString, String longHelp=EmptyString,
+ PyObject clientData=None) -> ToolBarToolBase
+ """
+ return _controls_.ToolBarBase_DoInsertTool(*args, **kwargs)
+
+ # These match the original Add methods for this class, kept for
+ # backwards compatibility with versions < 2.3.3.
+
+
+ def AddTool(self, id, bitmap,
+ pushedBitmap = wx.NullBitmap,
+ isToggle = 0,
+ clientData = None,
+ shortHelpString = '',
+ longHelpString = '') :
+ '''Old style method to add a tool to the toolbar.'''
+ kind = wx.ITEM_NORMAL
+ if isToggle: kind = wx.ITEM_CHECK
+ return self.DoAddTool(id, '', bitmap, pushedBitmap, kind,
+ shortHelpString, longHelpString, clientData)
+
+ def AddSimpleTool(self, id, bitmap,
+ shortHelpString = '',
+ longHelpString = '',
+ isToggle = 0):
+ '''Old style method to add a tool to the toolbar.'''
+ kind = wx.ITEM_NORMAL
+ if isToggle: kind = wx.ITEM_CHECK
+ return self.DoAddTool(id, '', bitmap, wx.NullBitmap, kind,
+ shortHelpString, longHelpString, None)
+
+ def InsertTool(self, pos, id, bitmap,
+ pushedBitmap = wx.NullBitmap,
+ isToggle = 0,
+ clientData = None,
+ shortHelpString = '',
+ longHelpString = ''):
+ '''Old style method to insert a tool in the toolbar.'''
+ kind = wx.ITEM_NORMAL
+ if isToggle: kind = wx.ITEM_CHECK
+ return self.DoInsertTool(pos, id, '', bitmap, pushedBitmap, kind,
+ shortHelpString, longHelpString, clientData)
+
+ def InsertSimpleTool(self, pos, id, bitmap,
+ shortHelpString = '',
+ longHelpString = '',
+ isToggle = 0):
+ '''Old style method to insert a tool in the toolbar.'''
+ kind = wx.ITEM_NORMAL
+ if isToggle: kind = wx.ITEM_CHECK
+ return self.DoInsertTool(pos, id, '', bitmap, wx.NullBitmap, kind,
+ shortHelpString, longHelpString, None)
+
+
+ # The following are the new toolbar Add methods starting with
+ # 2.3.3. They are renamed to have 'Label' in the name so as to be
+ # able to keep backwards compatibility with using the above
+ # methods. Eventually these should migrate to be the methods used
+ # primarily and lose the 'Label' in the name...
+
+ def AddLabelTool(self, id, label, bitmap,
+ bmpDisabled = wx.NullBitmap,
+ kind = wx.ITEM_NORMAL,
+ shortHelp = '', longHelp = '',
+ clientData = None):
+ '''
+ The full AddTool() function.
+
+ If bmpDisabled is wx.NullBitmap, a shadowed version of the normal bitmap
+ is created and used as the disabled image.
+ '''
+ return self.DoAddTool(id, label, bitmap, bmpDisabled, kind,
+ shortHelp, longHelp, clientData)
+
+
+ def InsertLabelTool(self, pos, id, label, bitmap,
+ bmpDisabled = wx.NullBitmap,
+ kind = wx.ITEM_NORMAL,
+ shortHelp = '', longHelp = '',
+ clientData = None):
+ '''
+ Insert the new tool at the given position, if pos == GetToolsCount(), it
+ is equivalent to AddTool()
+ '''
+ return self.DoInsertTool(pos, id, label, bitmap, bmpDisabled, kind,
+ shortHelp, longHelp, clientData)
+
+ def AddCheckLabelTool(self, id, label, bitmap,
+ bmpDisabled = wx.NullBitmap,
+ shortHelp = '', longHelp = '',
+ clientData = None):
+ '''Add a check tool, i.e. a tool which can be toggled'''
+ return self.DoAddTool(id, label, bitmap, bmpDisabled, wx.ITEM_CHECK,
+ shortHelp, longHelp, clientData)
+
+ def AddRadioLabelTool(self, id, label, bitmap,
+ bmpDisabled = wx.NullBitmap,
+ shortHelp = '', longHelp = '',
+ clientData = None):
+ '''
+ Add a radio tool, i.e. a tool which can be toggled and releases any
+ other toggled radio tools in the same group when it happens
+ '''
+ return self.DoAddTool(id, label, bitmap, bmpDisabled, wx.ITEM_RADIO,
+ shortHelp, longHelp, clientData)
+
+
+ # For consistency with the backwards compatible methods above, here are
+ # some non-'Label' versions of the Check and Radio methods
+
+ def AddCheckTool(self, id, bitmap,
+ bmpDisabled = wx.NullBitmap,
+ shortHelp = '', longHelp = '',
+ clientData = None):
+ '''Add a check tool, i.e. a tool which can be toggled'''
+ return self.DoAddTool(id, '', bitmap, bmpDisabled, wx.ITEM_CHECK,
+ shortHelp, longHelp, clientData)
+
+ def AddRadioTool(self, id, bitmap,
+ bmpDisabled = wx.NullBitmap,
+ shortHelp = '', longHelp = '',
+ clientData = None):
+ '''
+ Add a radio tool, i.e. a tool which can be toggled and releases any
+ other toggled radio tools in the same group when it happens
+ '''
+ return self.DoAddTool(id, '', bitmap, bmpDisabled, wx.ITEM_RADIO,
+ shortHelp, longHelp, clientData)
+
+ def AddToolItem(*args, **kwargs):
+ """AddToolItem(self, ToolBarToolBase tool) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_AddToolItem(*args, **kwargs)
+
+ def InsertToolItem(*args, **kwargs):
+ """InsertToolItem(self, size_t pos, ToolBarToolBase tool) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_InsertToolItem(*args, **kwargs)
+
+ def AddControl(*args, **kwargs):
+ """AddControl(self, Control control, String label=wxEmptyString) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_AddControl(*args, **kwargs)
+
+ def InsertControl(*args, **kwargs):
+ """InsertControl(self, size_t pos, Control control, String label=wxEmptyString) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_InsertControl(*args, **kwargs)
+
+ def FindControl(*args, **kwargs):
+ """FindControl(self, int id) -> Control"""
+ return _controls_.ToolBarBase_FindControl(*args, **kwargs)
+
+ def AddSeparator(*args, **kwargs):
+ """AddSeparator(self) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_AddSeparator(*args, **kwargs)
+
+ def InsertSeparator(*args, **kwargs):
+ """InsertSeparator(self, size_t pos) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_InsertSeparator(*args, **kwargs)
+
+ def AddStretchableSpace(*args, **kwargs):
+ """AddStretchableSpace(self) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_AddStretchableSpace(*args, **kwargs)
+
+ def InsertStretchableSpace(*args, **kwargs):
+ """InsertStretchableSpace(self, size_t pos) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_InsertStretchableSpace(*args, **kwargs)
+
+ def RemoveTool(*args, **kwargs):
+ """RemoveTool(self, int id) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_RemoveTool(*args, **kwargs)
+
+ def DeleteToolByPos(*args, **kwargs):
+ """DeleteToolByPos(self, size_t pos) -> bool"""
+ return _controls_.ToolBarBase_DeleteToolByPos(*args, **kwargs)
+
+ def DeleteTool(*args, **kwargs):
+ """DeleteTool(self, int id) -> bool"""
+ return _controls_.ToolBarBase_DeleteTool(*args, **kwargs)
+
+ def ClearTools(*args, **kwargs):
+ """ClearTools(self)"""
+ return _controls_.ToolBarBase_ClearTools(*args, **kwargs)
+
+ def Realize(*args, **kwargs):
+ """Realize(self) -> bool"""
+ return _controls_.ToolBarBase_Realize(*args, **kwargs)
+
+ def EnableTool(*args, **kwargs):
+ """EnableTool(self, int id, bool enable)"""
+ return _controls_.ToolBarBase_EnableTool(*args, **kwargs)
+
+ def ToggleTool(*args, **kwargs):
+ """ToggleTool(self, int id, bool toggle)"""
+ return _controls_.ToolBarBase_ToggleTool(*args, **kwargs)
+
+ def SetToggle(*args, **kwargs):
+ """SetToggle(self, int id, bool toggle)"""
+ return _controls_.ToolBarBase_SetToggle(*args, **kwargs)
+
+ def GetToolClientData(*args, **kwargs):
+ """GetToolClientData(self, int id) -> PyObject"""
+ return _controls_.ToolBarBase_GetToolClientData(*args, **kwargs)
+
+ def SetToolClientData(*args, **kwargs):
+ """SetToolClientData(self, int id, PyObject clientData)"""
+ return _controls_.ToolBarBase_SetToolClientData(*args, **kwargs)
+
+ def GetToolPos(*args, **kwargs):
+ """GetToolPos(self, int id) -> int"""
+ return _controls_.ToolBarBase_GetToolPos(*args, **kwargs)
+
+ def GetToolState(*args, **kwargs):
+ """GetToolState(self, int id) -> bool"""
+ return _controls_.ToolBarBase_GetToolState(*args, **kwargs)
+
+ def GetToolEnabled(*args, **kwargs):
+ """GetToolEnabled(self, int id) -> bool"""
+ return _controls_.ToolBarBase_GetToolEnabled(*args, **kwargs)
+
+ def SetToolShortHelp(*args, **kwargs):
+ """SetToolShortHelp(self, int id, String helpString)"""
+ return _controls_.ToolBarBase_SetToolShortHelp(*args, **kwargs)
+
+ def GetToolShortHelp(*args, **kwargs):
+ """GetToolShortHelp(self, int id) -> String"""
+ return _controls_.ToolBarBase_GetToolShortHelp(*args, **kwargs)
+
+ def SetToolLongHelp(*args, **kwargs):
+ """SetToolLongHelp(self, int id, String helpString)"""
+ return _controls_.ToolBarBase_SetToolLongHelp(*args, **kwargs)
+
+ def GetToolLongHelp(*args, **kwargs):
+ """GetToolLongHelp(self, int id) -> String"""
+ return _controls_.ToolBarBase_GetToolLongHelp(*args, **kwargs)
+
+ def SetMarginsXY(*args, **kwargs):
+ """SetMarginsXY(self, int x, int y)"""
+ return _controls_.ToolBarBase_SetMarginsXY(*args, **kwargs)
+
+ def SetMargins(*args, **kwargs):
+ """SetMargins(self, Size size)"""
+ return _controls_.ToolBarBase_SetMargins(*args, **kwargs)
+
+ def SetToolPacking(*args, **kwargs):
+ """SetToolPacking(self, int packing)"""
+ return _controls_.ToolBarBase_SetToolPacking(*args, **kwargs)
+
+ def SetToolSeparation(*args, **kwargs):
+ """SetToolSeparation(self, int separation)"""
+ return _controls_.ToolBarBase_SetToolSeparation(*args, **kwargs)
+
+ def GetToolMargins(*args, **kwargs):
+ """GetToolMargins(self) -> Size"""
+ return _controls_.ToolBarBase_GetToolMargins(*args, **kwargs)
+
+ def GetMargins(*args, **kwargs):
+ """GetMargins(self) -> Size"""
+ return _controls_.ToolBarBase_GetMargins(*args, **kwargs)
+
+ def GetToolPacking(*args, **kwargs):
+ """GetToolPacking(self) -> int"""
+ return _controls_.ToolBarBase_GetToolPacking(*args, **kwargs)
+
+ def GetToolSeparation(*args, **kwargs):
+ """GetToolSeparation(self) -> int"""
+ return _controls_.ToolBarBase_GetToolSeparation(*args, **kwargs)
+
+ def SetRows(*args, **kwargs):
+ """SetRows(self, int nRows)"""
+ return _controls_.ToolBarBase_SetRows(*args, **kwargs)
+
+ def SetMaxRowsCols(*args, **kwargs):
+ """SetMaxRowsCols(self, int rows, int cols)"""
+ return _controls_.ToolBarBase_SetMaxRowsCols(*args, **kwargs)
+
+ def GetMaxRows(*args, **kwargs):
+ """GetMaxRows(self) -> int"""
+ return _controls_.ToolBarBase_GetMaxRows(*args, **kwargs)
+
+ def GetMaxCols(*args, **kwargs):
+ """GetMaxCols(self) -> int"""
+ return _controls_.ToolBarBase_GetMaxCols(*args, **kwargs)
+
+ def SetToolBitmapSize(*args, **kwargs):
+ """SetToolBitmapSize(self, Size size)"""
+ return _controls_.ToolBarBase_SetToolBitmapSize(*args, **kwargs)
+
+ def GetToolBitmapSize(*args, **kwargs):
+ """GetToolBitmapSize(self) -> Size"""
+ return _controls_.ToolBarBase_GetToolBitmapSize(*args, **kwargs)
+
+ def GetToolSize(*args, **kwargs):
+ """GetToolSize(self) -> Size"""
+ return _controls_.ToolBarBase_GetToolSize(*args, **kwargs)
+
+ def FindToolForPosition(*args, **kwargs):
+ """FindToolForPosition(self, int x, int y) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_FindToolForPosition(*args, **kwargs)
+
+ def FindById(*args, **kwargs):
+ """FindById(self, int toolid) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_FindById(*args, **kwargs)
+
+ def IsVertical(*args, **kwargs):
+ """IsVertical(self) -> bool"""
+ return _controls_.ToolBarBase_IsVertical(*args, **kwargs)
+
+ def GetToolsCount(*args, **kwargs):
+ """GetToolsCount(self) -> size_t"""
+ return _controls_.ToolBarBase_GetToolsCount(*args, **kwargs)
+
+ def GetToolByPos(*args, **kwargs):
+ """GetToolByPos(self, int pos) -> ToolBarToolBase"""
+ return _controls_.ToolBarBase_GetToolByPos(*args, **kwargs)
+
+ def SetDropdownMenu(*args, **kwargs):
+ """SetDropdownMenu(self, int toolid, Menu menu) -> bool"""
+ return _controls_.ToolBarBase_SetDropdownMenu(*args, **kwargs)
+
+ Margins = property(GetMargins,SetMargins,doc="See `GetMargins` and `SetMargins`")
+ MaxCols = property(GetMaxCols,doc="See `GetMaxCols`")
+ MaxRows = property(GetMaxRows,doc="See `GetMaxRows`")
+ ToolBitmapSize = property(GetToolBitmapSize,SetToolBitmapSize,doc="See `GetToolBitmapSize` and `SetToolBitmapSize`")
+ ToolMargins = property(GetToolMargins,doc="See `GetToolMargins`")
+ ToolPacking = property(GetToolPacking,SetToolPacking,doc="See `GetToolPacking` and `SetToolPacking`")
+ ToolSeparation = property(GetToolSeparation,SetToolSeparation,doc="See `GetToolSeparation` and `SetToolSeparation`")
+ ToolSize = property(GetToolSize,doc="See `GetToolSize`")
+ ToolsCount = property(GetToolsCount,doc="See `GetToolsCount`")
+_controls_.ToolBarBase_swigregister(ToolBarBase)
+
+class ToolBar(ToolBarBase):
+ """Proxy of C++ ToolBar class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxNO_BORDER|wxTB_HORIZONTAL,
+ String name=wxPyToolBarNameStr) -> ToolBar
+ """
+ _controls_.ToolBar_swiginit(self,_controls_.new_ToolBar(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxNO_BORDER|wxTB_HORIZONTAL,
+ String name=wxPyToolBarNameStr) -> bool
+ """
+ return _controls_.ToolBar_Create(*args, **kwargs)
+
+ def SetToolNormalBitmap(*args, **kwargs):
+ """SetToolNormalBitmap(self, int id, Bitmap bitmap)"""
+ return _controls_.ToolBar_SetToolNormalBitmap(*args, **kwargs)
+
+ def SetToolDisabledBitmap(*args, **kwargs):
+ """SetToolDisabledBitmap(self, int id, Bitmap bitmap)"""
+ return _controls_.ToolBar_SetToolDisabledBitmap(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ToolBar_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+_controls_.ToolBar_swigregister(ToolBar)
+
+def PreToolBar(*args, **kwargs):
+ """PreToolBar() -> ToolBar"""
+ val = _controls_.new_PreToolBar(*args, **kwargs)
+ return val
+
+def ToolBar_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ ToolBar_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ToolBar_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+LC_VRULES = _controls_.LC_VRULES
+LC_HRULES = _controls_.LC_HRULES
+LC_ICON = _controls_.LC_ICON
+LC_SMALL_ICON = _controls_.LC_SMALL_ICON
+LC_LIST = _controls_.LC_LIST
+LC_REPORT = _controls_.LC_REPORT
+LC_ALIGN_TOP = _controls_.LC_ALIGN_TOP
+LC_ALIGN_LEFT = _controls_.LC_ALIGN_LEFT
+LC_AUTOARRANGE = _controls_.LC_AUTOARRANGE
+LC_VIRTUAL = _controls_.LC_VIRTUAL
+LC_EDIT_LABELS = _controls_.LC_EDIT_LABELS
+LC_NO_HEADER = _controls_.LC_NO_HEADER
+LC_NO_SORT_HEADER = _controls_.LC_NO_SORT_HEADER
+LC_SINGLE_SEL = _controls_.LC_SINGLE_SEL
+LC_SORT_ASCENDING = _controls_.LC_SORT_ASCENDING
+LC_SORT_DESCENDING = _controls_.LC_SORT_DESCENDING
+LC_MASK_TYPE = _controls_.LC_MASK_TYPE
+LC_MASK_ALIGN = _controls_.LC_MASK_ALIGN
+LC_MASK_SORT = _controls_.LC_MASK_SORT
+LIST_MASK_STATE = _controls_.LIST_MASK_STATE
+LIST_MASK_TEXT = _controls_.LIST_MASK_TEXT
+LIST_MASK_IMAGE = _controls_.LIST_MASK_IMAGE
+LIST_MASK_DATA = _controls_.LIST_MASK_DATA
+LIST_SET_ITEM = _controls_.LIST_SET_ITEM
+LIST_MASK_WIDTH = _controls_.LIST_MASK_WIDTH
+LIST_MASK_FORMAT = _controls_.LIST_MASK_FORMAT
+LIST_STATE_DONTCARE = _controls_.LIST_STATE_DONTCARE
+LIST_STATE_DROPHILITED = _controls_.LIST_STATE_DROPHILITED
+LIST_STATE_FOCUSED = _controls_.LIST_STATE_FOCUSED
+LIST_STATE_SELECTED = _controls_.LIST_STATE_SELECTED
+LIST_STATE_CUT = _controls_.LIST_STATE_CUT
+LIST_STATE_DISABLED = _controls_.LIST_STATE_DISABLED
+LIST_STATE_FILTERED = _controls_.LIST_STATE_FILTERED
+LIST_STATE_INUSE = _controls_.LIST_STATE_INUSE
+LIST_STATE_PICKED = _controls_.LIST_STATE_PICKED
+LIST_STATE_SOURCE = _controls_.LIST_STATE_SOURCE
+LIST_HITTEST_ABOVE = _controls_.LIST_HITTEST_ABOVE
+LIST_HITTEST_BELOW = _controls_.LIST_HITTEST_BELOW
+LIST_HITTEST_NOWHERE = _controls_.LIST_HITTEST_NOWHERE
+LIST_HITTEST_ONITEMICON = _controls_.LIST_HITTEST_ONITEMICON
+LIST_HITTEST_ONITEMLABEL = _controls_.LIST_HITTEST_ONITEMLABEL
+LIST_HITTEST_ONITEMRIGHT = _controls_.LIST_HITTEST_ONITEMRIGHT
+LIST_HITTEST_ONITEMSTATEICON = _controls_.LIST_HITTEST_ONITEMSTATEICON
+LIST_HITTEST_TOLEFT = _controls_.LIST_HITTEST_TOLEFT
+LIST_HITTEST_TORIGHT = _controls_.LIST_HITTEST_TORIGHT
+LIST_HITTEST_ONITEM = _controls_.LIST_HITTEST_ONITEM
+LIST_GETSUBITEMRECT_WHOLEITEM = _controls_.LIST_GETSUBITEMRECT_WHOLEITEM
+LIST_NEXT_ABOVE = _controls_.LIST_NEXT_ABOVE
+LIST_NEXT_ALL = _controls_.LIST_NEXT_ALL
+LIST_NEXT_BELOW = _controls_.LIST_NEXT_BELOW
+LIST_NEXT_LEFT = _controls_.LIST_NEXT_LEFT
+LIST_NEXT_RIGHT = _controls_.LIST_NEXT_RIGHT
+LIST_ALIGN_DEFAULT = _controls_.LIST_ALIGN_DEFAULT
+LIST_ALIGN_LEFT = _controls_.LIST_ALIGN_LEFT
+LIST_ALIGN_TOP = _controls_.LIST_ALIGN_TOP
+LIST_ALIGN_SNAP_TO_GRID = _controls_.LIST_ALIGN_SNAP_TO_GRID
+LIST_FORMAT_LEFT = _controls_.LIST_FORMAT_LEFT
+LIST_FORMAT_RIGHT = _controls_.LIST_FORMAT_RIGHT
+LIST_FORMAT_CENTRE = _controls_.LIST_FORMAT_CENTRE
+LIST_FORMAT_CENTER = _controls_.LIST_FORMAT_CENTER
+LIST_AUTOSIZE = _controls_.LIST_AUTOSIZE
+LIST_AUTOSIZE_USEHEADER = _controls_.LIST_AUTOSIZE_USEHEADER
+LIST_RECT_BOUNDS = _controls_.LIST_RECT_BOUNDS
+LIST_RECT_ICON = _controls_.LIST_RECT_ICON
+LIST_RECT_LABEL = _controls_.LIST_RECT_LABEL
+LIST_FIND_UP = _controls_.LIST_FIND_UP
+LIST_FIND_DOWN = _controls_.LIST_FIND_DOWN
+LIST_FIND_LEFT = _controls_.LIST_FIND_LEFT
+LIST_FIND_RIGHT = _controls_.LIST_FIND_RIGHT
+#---------------------------------------------------------------------------
+
+class ListItemAttr(object):
+ """Proxy of C++ ListItemAttr class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Colour colText=wxNullColour, Colour colBack=wxNullColour,
+ Font font=wxNullFont) -> ListItemAttr
+ """
+ _controls_.ListItemAttr_swiginit(self,_controls_.new_ListItemAttr(*args, **kwargs))
+ __swig_destroy__ = _controls_.delete_ListItemAttr
+ __del__ = lambda self : None;
+ def SetTextColour(*args, **kwargs):
+ """SetTextColour(self, Colour colText)"""
+ return _controls_.ListItemAttr_SetTextColour(*args, **kwargs)
+
+ def SetBackgroundColour(*args, **kwargs):
+ """SetBackgroundColour(self, Colour colBack)"""
+ return _controls_.ListItemAttr_SetBackgroundColour(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """SetFont(self, Font font)"""
+ return _controls_.ListItemAttr_SetFont(*args, **kwargs)
+
+ def HasTextColour(*args, **kwargs):
+ """HasTextColour(self) -> bool"""
+ return _controls_.ListItemAttr_HasTextColour(*args, **kwargs)
+
+ def HasBackgroundColour(*args, **kwargs):
+ """HasBackgroundColour(self) -> bool"""
+ return _controls_.ListItemAttr_HasBackgroundColour(*args, **kwargs)
+
+ def HasFont(*args, **kwargs):
+ """HasFont(self) -> bool"""
+ return _controls_.ListItemAttr_HasFont(*args, **kwargs)
+
+ def GetTextColour(*args, **kwargs):
+ """GetTextColour(self) -> Colour"""
+ return _controls_.ListItemAttr_GetTextColour(*args, **kwargs)
+
+ def GetBackgroundColour(*args, **kwargs):
+ """GetBackgroundColour(self) -> Colour"""
+ return _controls_.ListItemAttr_GetBackgroundColour(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """GetFont(self) -> Font"""
+ return _controls_.ListItemAttr_GetFont(*args, **kwargs)
+
+ def AssignFrom(*args, **kwargs):
+ """AssignFrom(self, ListItemAttr source)"""
+ return _controls_.ListItemAttr_AssignFrom(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """Destroy(self)"""
+ args[0].this.own(False)
+ return _controls_.ListItemAttr_Destroy(*args, **kwargs)
+
+ BackgroundColour = property(GetBackgroundColour,SetBackgroundColour,doc="See `GetBackgroundColour` and `SetBackgroundColour`")
+ Font = property(GetFont,SetFont,doc="See `GetFont` and `SetFont`")
+ TextColour = property(GetTextColour,SetTextColour,doc="See `GetTextColour` and `SetTextColour`")
+_controls_.ListItemAttr_swigregister(ListItemAttr)
+ListCtrlNameStr = cvar.ListCtrlNameStr
+
+#---------------------------------------------------------------------------
+
+class ListItem(_core.Object):
+ """Proxy of C++ ListItem class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> ListItem"""
+ _controls_.ListItem_swiginit(self,_controls_.new_ListItem(*args, **kwargs))
+ __swig_destroy__ = _controls_.delete_ListItem
+ __del__ = lambda self : None;
+ def Clear(*args, **kwargs):
+ """Clear(self)"""
+ return _controls_.ListItem_Clear(*args, **kwargs)
+
+ def ClearAttributes(*args, **kwargs):
+ """ClearAttributes(self)"""
+ return _controls_.ListItem_ClearAttributes(*args, **kwargs)
+
+ def SetMask(*args, **kwargs):
+ """SetMask(self, long mask)"""
+ return _controls_.ListItem_SetMask(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """SetId(self, long id)"""
+ return _controls_.ListItem_SetId(*args, **kwargs)
+
+ def SetColumn(*args, **kwargs):
+ """SetColumn(self, int col)"""
+ return _controls_.ListItem_SetColumn(*args, **kwargs)
+
+ def SetState(*args, **kwargs):
+ """SetState(self, long state)"""
+ return _controls_.ListItem_SetState(*args, **kwargs)
+
+ def SetStateMask(*args, **kwargs):
+ """SetStateMask(self, long stateMask)"""
+ return _controls_.ListItem_SetStateMask(*args, **kwargs)
+
+ def SetText(*args, **kwargs):
+ """SetText(self, String text)"""
+ return _controls_.ListItem_SetText(*args, **kwargs)
+
+ def SetImage(*args, **kwargs):
+ """SetImage(self, int image)"""
+ return _controls_.ListItem_SetImage(*args, **kwargs)
+
+ def SetData(*args, **kwargs):
+ """SetData(self, long data)"""
+ return _controls_.ListItem_SetData(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """SetWidth(self, int width)"""
+ return _controls_.ListItem_SetWidth(*args, **kwargs)
+
+ def SetAlign(*args, **kwargs):
+ """SetAlign(self, int align)"""
+ return _controls_.ListItem_SetAlign(*args, **kwargs)
+
+ def SetTextColour(*args, **kwargs):
+ """SetTextColour(self, Colour colText)"""
+ return _controls_.ListItem_SetTextColour(*args, **kwargs)
+
+ def SetBackgroundColour(*args, **kwargs):
+ """SetBackgroundColour(self, Colour colBack)"""
+ return _controls_.ListItem_SetBackgroundColour(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """SetFont(self, Font font)"""
+ return _controls_.ListItem_SetFont(*args, **kwargs)
+
+ def GetMask(*args, **kwargs):
+ """GetMask(self) -> long"""
+ return _controls_.ListItem_GetMask(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """GetId(self) -> long"""
+ return _controls_.ListItem_GetId(*args, **kwargs)
+
+ def GetColumn(*args, **kwargs):
+ """GetColumn(self) -> int"""
+ return _controls_.ListItem_GetColumn(*args, **kwargs)
+
+ def GetState(*args, **kwargs):
+ """GetState(self) -> long"""
+ return _controls_.ListItem_GetState(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self) -> String"""
+ return _controls_.ListItem_GetText(*args, **kwargs)
+
+ def GetImage(*args, **kwargs):
+ """GetImage(self) -> int"""
+ return _controls_.ListItem_GetImage(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """GetData(self) -> long"""
+ return _controls_.ListItem_GetData(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _controls_.ListItem_GetWidth(*args, **kwargs)
+
+ def GetAlign(*args, **kwargs):
+ """GetAlign(self) -> int"""
+ return _controls_.ListItem_GetAlign(*args, **kwargs)
+
+ def GetAttributes(*args, **kwargs):
+ """GetAttributes(self) -> ListItemAttr"""
+ return _controls_.ListItem_GetAttributes(*args, **kwargs)
+
+ def HasAttributes(*args, **kwargs):
+ """HasAttributes(self) -> bool"""
+ return _controls_.ListItem_HasAttributes(*args, **kwargs)
+
+ def GetTextColour(*args, **kwargs):
+ """GetTextColour(self) -> Colour"""
+ return _controls_.ListItem_GetTextColour(*args, **kwargs)
+
+ def GetBackgroundColour(*args, **kwargs):
+ """GetBackgroundColour(self) -> Colour"""
+ return _controls_.ListItem_GetBackgroundColour(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """GetFont(self) -> Font"""
+ return _controls_.ListItem_GetFont(*args, **kwargs)
+
+ m_mask = property(_controls_.ListItem_m_mask_get, _controls_.ListItem_m_mask_set)
+ m_itemId = property(_controls_.ListItem_m_itemId_get, _controls_.ListItem_m_itemId_set)
+ m_col = property(_controls_.ListItem_m_col_get, _controls_.ListItem_m_col_set)
+ m_state = property(_controls_.ListItem_m_state_get, _controls_.ListItem_m_state_set)
+ m_stateMask = property(_controls_.ListItem_m_stateMask_get, _controls_.ListItem_m_stateMask_set)
+ m_text = property(_controls_.ListItem_m_text_get, _controls_.ListItem_m_text_set)
+ m_image = property(_controls_.ListItem_m_image_get, _controls_.ListItem_m_image_set)
+ m_data = property(_controls_.ListItem_m_data_get, _controls_.ListItem_m_data_set)
+ m_format = property(_controls_.ListItem_m_format_get, _controls_.ListItem_m_format_set)
+ m_width = property(_controls_.ListItem_m_width_get, _controls_.ListItem_m_width_set)
+ Align = property(GetAlign,SetAlign,doc="See `GetAlign` and `SetAlign`")
+ Attributes = property(GetAttributes,doc="See `GetAttributes`")
+ BackgroundColour = property(GetBackgroundColour,SetBackgroundColour,doc="See `GetBackgroundColour` and `SetBackgroundColour`")
+ Column = property(GetColumn,SetColumn,doc="See `GetColumn` and `SetColumn`")
+ Data = property(GetData,SetData,doc="See `GetData` and `SetData`")
+ Font = property(GetFont,SetFont,doc="See `GetFont` and `SetFont`")
+ Id = property(GetId,SetId,doc="See `GetId` and `SetId`")
+ Image = property(GetImage,SetImage,doc="See `GetImage` and `SetImage`")
+ Mask = property(GetMask,SetMask,doc="See `GetMask` and `SetMask`")
+ State = property(GetState,SetState,doc="See `GetState` and `SetState`")
+ Text = property(GetText,SetText,doc="See `GetText` and `SetText`")
+ TextColour = property(GetTextColour,SetTextColour,doc="See `GetTextColour` and `SetTextColour`")
+ Width = property(GetWidth,SetWidth,doc="See `GetWidth` and `SetWidth`")
+_controls_.ListItem_swigregister(ListItem)
+
+#---------------------------------------------------------------------------
+
+class ListEvent(_core.NotifyEvent):
+ """Proxy of C++ ListEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=wxEVT_NULL, int id=0) -> ListEvent"""
+ _controls_.ListEvent_swiginit(self,_controls_.new_ListEvent(*args, **kwargs))
+ m_code = property(_controls_.ListEvent_m_code_get, _controls_.ListEvent_m_code_set)
+ m_oldItemIndex = property(_controls_.ListEvent_m_oldItemIndex_get, _controls_.ListEvent_m_oldItemIndex_set)
+ m_itemIndex = property(_controls_.ListEvent_m_itemIndex_get, _controls_.ListEvent_m_itemIndex_set)
+ m_col = property(_controls_.ListEvent_m_col_get, _controls_.ListEvent_m_col_set)
+ m_pointDrag = property(_controls_.ListEvent_m_pointDrag_get, _controls_.ListEvent_m_pointDrag_set)
+ m_item = property(_controls_.ListEvent_m_item_get)
+ def GetKeyCode(*args, **kwargs):
+ """GetKeyCode(self) -> int"""
+ return _controls_.ListEvent_GetKeyCode(*args, **kwargs)
+
+ GetCode = GetKeyCode
+ def GetIndex(*args, **kwargs):
+ """GetIndex(self) -> long"""
+ return _controls_.ListEvent_GetIndex(*args, **kwargs)
+
+ def GetColumn(*args, **kwargs):
+ """GetColumn(self) -> int"""
+ return _controls_.ListEvent_GetColumn(*args, **kwargs)
+
+ def GetPoint(*args, **kwargs):
+ """GetPoint(self) -> Point"""
+ return _controls_.ListEvent_GetPoint(*args, **kwargs)
+
+ GetPosition = GetPoint
+ def GetLabel(*args, **kwargs):
+ """GetLabel(self) -> String"""
+ return _controls_.ListEvent_GetLabel(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self) -> String"""
+ return _controls_.ListEvent_GetText(*args, **kwargs)
+
+ def GetImage(*args, **kwargs):
+ """GetImage(self) -> int"""
+ return _controls_.ListEvent_GetImage(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """GetData(self) -> long"""
+ return _controls_.ListEvent_GetData(*args, **kwargs)
+
+ def GetMask(*args, **kwargs):
+ """GetMask(self) -> long"""
+ return _controls_.ListEvent_GetMask(*args, **kwargs)
+
+ def GetItem(*args, **kwargs):
+ """GetItem(self) -> ListItem"""
+ return _controls_.ListEvent_GetItem(*args, **kwargs)
+
+ def GetCacheFrom(*args, **kwargs):
+ """GetCacheFrom(self) -> long"""
+ return _controls_.ListEvent_GetCacheFrom(*args, **kwargs)
+
+ def GetCacheTo(*args, **kwargs):
+ """GetCacheTo(self) -> long"""
+ return _controls_.ListEvent_GetCacheTo(*args, **kwargs)
+
+ def IsEditCancelled(*args, **kwargs):
+ """IsEditCancelled(self) -> bool"""
+ return _controls_.ListEvent_IsEditCancelled(*args, **kwargs)
+
+ def SetEditCanceled(*args, **kwargs):
+ """SetEditCanceled(self, bool editCancelled)"""
+ return _controls_.ListEvent_SetEditCanceled(*args, **kwargs)
+
+ CacheFrom = property(GetCacheFrom,doc="See `GetCacheFrom`")
+ CacheTo = property(GetCacheTo,doc="See `GetCacheTo`")
+ Column = property(GetColumn,doc="See `GetColumn`")
+ Data = property(GetData,doc="See `GetData`")
+ Image = property(GetImage,doc="See `GetImage`")
+ Index = property(GetIndex,doc="See `GetIndex`")
+ Item = property(GetItem,doc="See `GetItem`")
+ KeyCode = property(GetKeyCode,doc="See `GetKeyCode`")
+ Label = property(GetLabel,doc="See `GetLabel`")
+ Mask = property(GetMask,doc="See `GetMask`")
+ Point = property(GetPoint,doc="See `GetPoint`")
+ Text = property(GetText,doc="See `GetText`")
+_controls_.ListEvent_swigregister(ListEvent)
+
+wxEVT_COMMAND_LIST_BEGIN_DRAG = _controls_.wxEVT_COMMAND_LIST_BEGIN_DRAG
+wxEVT_COMMAND_LIST_BEGIN_RDRAG = _controls_.wxEVT_COMMAND_LIST_BEGIN_RDRAG
+wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT = _controls_.wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
+wxEVT_COMMAND_LIST_END_LABEL_EDIT = _controls_.wxEVT_COMMAND_LIST_END_LABEL_EDIT
+wxEVT_COMMAND_LIST_DELETE_ITEM = _controls_.wxEVT_COMMAND_LIST_DELETE_ITEM
+wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS = _controls_.wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
+wxEVT_COMMAND_LIST_ITEM_SELECTED = _controls_.wxEVT_COMMAND_LIST_ITEM_SELECTED
+wxEVT_COMMAND_LIST_ITEM_DESELECTED = _controls_.wxEVT_COMMAND_LIST_ITEM_DESELECTED
+wxEVT_COMMAND_LIST_KEY_DOWN = _controls_.wxEVT_COMMAND_LIST_KEY_DOWN
+wxEVT_COMMAND_LIST_INSERT_ITEM = _controls_.wxEVT_COMMAND_LIST_INSERT_ITEM
+wxEVT_COMMAND_LIST_COL_CLICK = _controls_.wxEVT_COMMAND_LIST_COL_CLICK
+wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK = _controls_.wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
+wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK = _controls_.wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
+wxEVT_COMMAND_LIST_ITEM_ACTIVATED = _controls_.wxEVT_COMMAND_LIST_ITEM_ACTIVATED
+wxEVT_COMMAND_LIST_CACHE_HINT = _controls_.wxEVT_COMMAND_LIST_CACHE_HINT
+wxEVT_COMMAND_LIST_COL_RIGHT_CLICK = _controls_.wxEVT_COMMAND_LIST_COL_RIGHT_CLICK
+wxEVT_COMMAND_LIST_COL_BEGIN_DRAG = _controls_.wxEVT_COMMAND_LIST_COL_BEGIN_DRAG
+wxEVT_COMMAND_LIST_COL_DRAGGING = _controls_.wxEVT_COMMAND_LIST_COL_DRAGGING
+wxEVT_COMMAND_LIST_COL_END_DRAG = _controls_.wxEVT_COMMAND_LIST_COL_END_DRAG
+wxEVT_COMMAND_LIST_ITEM_FOCUSED = _controls_.wxEVT_COMMAND_LIST_ITEM_FOCUSED
+EVT_LIST_BEGIN_DRAG = wx.PyEventBinder(wxEVT_COMMAND_LIST_BEGIN_DRAG , 1)
+EVT_LIST_BEGIN_RDRAG = wx.PyEventBinder(wxEVT_COMMAND_LIST_BEGIN_RDRAG , 1)
+EVT_LIST_BEGIN_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT , 1)
+EVT_LIST_END_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_LIST_END_LABEL_EDIT , 1)
+EVT_LIST_DELETE_ITEM = wx.PyEventBinder(wxEVT_COMMAND_LIST_DELETE_ITEM , 1)
+EVT_LIST_DELETE_ALL_ITEMS = wx.PyEventBinder(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS , 1)
+
+
+
+
+EVT_LIST_ITEM_SELECTED = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_SELECTED , 1)
+EVT_LIST_ITEM_DESELECTED = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_DESELECTED , 1)
+EVT_LIST_KEY_DOWN = wx.PyEventBinder(wxEVT_COMMAND_LIST_KEY_DOWN , 1)
+EVT_LIST_INSERT_ITEM = wx.PyEventBinder(wxEVT_COMMAND_LIST_INSERT_ITEM , 1)
+EVT_LIST_COL_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_CLICK , 1)
+EVT_LIST_ITEM_RIGHT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK , 1)
+EVT_LIST_ITEM_MIDDLE_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 1)
+EVT_LIST_ITEM_ACTIVATED = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_ACTIVATED , 1)
+EVT_LIST_CACHE_HINT = wx.PyEventBinder(wxEVT_COMMAND_LIST_CACHE_HINT , 1)
+EVT_LIST_COL_RIGHT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK , 1)
+EVT_LIST_COL_BEGIN_DRAG = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG , 1)
+EVT_LIST_COL_DRAGGING = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_DRAGGING , 1)
+EVT_LIST_COL_END_DRAG = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_END_DRAG , 1)
+EVT_LIST_ITEM_FOCUSED = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_FOCUSED , 1)
+
+
+
+
+
+#---------------------------------------------------------------------------
+
+class ListCtrl(_core.Control):
+ """Proxy of C++ ListCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=LC_ICON,
+ Validator validator=DefaultValidator, String name=ListCtrlNameStr) -> ListCtrl
+ """
+ _controls_.ListCtrl_swiginit(self,_controls_.new_ListCtrl(*args, **kwargs))
+ self._setOORInfo(self);ListCtrl._setCallbackInfo(self, self, ListCtrl)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=LC_ICON,
+ Validator validator=DefaultValidator, String name=ListCtrlNameStr) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _controls_.ListCtrl_Create(*args, **kwargs)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _controls_.ListCtrl__setCallbackInfo(*args, **kwargs)
+
+ def GetColumn(*args, **kwargs):
+ """GetColumn(self, int col) -> ListItem"""
+ val = _controls_.ListCtrl_GetColumn(*args, **kwargs)
+ if val is not None: val.thisown = 1
+ return val
+
+ def SetColumn(*args, **kwargs):
+ """SetColumn(self, int col, ListItem item) -> bool"""
+ return _controls_.ListCtrl_SetColumn(*args, **kwargs)
+
+ def GetColumnWidth(*args, **kwargs):
+ """GetColumnWidth(self, int col) -> int"""
+ return _controls_.ListCtrl_GetColumnWidth(*args, **kwargs)
+
+ def SetColumnWidth(*args, **kwargs):
+ """SetColumnWidth(self, int col, int width) -> bool"""
+ return _controls_.ListCtrl_SetColumnWidth(*args, **kwargs)
+
+ def HasColumnOrderSupport(*args, **kwargs):
+ """HasColumnOrderSupport() -> bool"""
+ return _controls_.ListCtrl_HasColumnOrderSupport(*args, **kwargs)
+
+ HasColumnOrderSupport = staticmethod(HasColumnOrderSupport)
+ def GetColumnOrder(*args, **kwargs):
+ """GetColumnOrder(self, int col) -> int"""
+ return _controls_.ListCtrl_GetColumnOrder(*args, **kwargs)
+
+ def GetColumnIndexFromOrder(*args, **kwargs):
+ """GetColumnIndexFromOrder(self, int order) -> int"""
+ return _controls_.ListCtrl_GetColumnIndexFromOrder(*args, **kwargs)
+
+ def GetColumnsOrder(*args, **kwargs):
+ """GetColumnsOrder(self) -> wxArrayInt"""
+ return _controls_.ListCtrl_GetColumnsOrder(*args, **kwargs)
+
+ def SetColumnsOrder(*args, **kwargs):
+ """SetColumnsOrder(self, wxArrayInt orders) -> bool"""
+ return _controls_.ListCtrl_SetColumnsOrder(*args, **kwargs)
+
+ def GetCountPerPage(*args, **kwargs):
+ """GetCountPerPage(self) -> int"""
+ return _controls_.ListCtrl_GetCountPerPage(*args, **kwargs)
+
+ def GetViewRect(*args, **kwargs):
+ """GetViewRect(self) -> Rect"""
+ return _controls_.ListCtrl_GetViewRect(*args, **kwargs)
+
+ def GetEditControl(*args, **kwargs):
+ """GetEditControl(self) -> TextCtrl"""
+ return _controls_.ListCtrl_GetEditControl(*args, **kwargs)
+
+ def GetItem(*args, **kwargs):
+ """GetItem(self, long itemId, int col=0) -> ListItem"""
+ val = _controls_.ListCtrl_GetItem(*args, **kwargs)
+ if val is not None: val.thisown = 1
+ return val
+
+ def SetItem(*args, **kwargs):
+ """SetItem(self, ListItem info) -> bool"""
+ return _controls_.ListCtrl_SetItem(*args, **kwargs)
+
+ def SetStringItem(*args, **kwargs):
+ """SetStringItem(self, long index, int col, String label, int imageId=-1) -> long"""
+ return _controls_.ListCtrl_SetStringItem(*args, **kwargs)
+
+ def GetItemState(*args, **kwargs):
+ """GetItemState(self, long item, long stateMask) -> int"""
+ return _controls_.ListCtrl_GetItemState(*args, **kwargs)
+
+ def SetItemState(*args, **kwargs):
+ """SetItemState(self, long item, long state, long stateMask) -> bool"""
+ return _controls_.ListCtrl_SetItemState(*args, **kwargs)
+
+ def SetItemImage(*args, **kwargs):
+ """SetItemImage(self, long item, int image, int selImage=-1) -> bool"""
+ return _controls_.ListCtrl_SetItemImage(*args, **kwargs)
+
+ def SetItemColumnImage(*args, **kwargs):
+ """SetItemColumnImage(self, long item, long column, int image) -> bool"""
+ return _controls_.ListCtrl_SetItemColumnImage(*args, **kwargs)
+
+ def GetItemText(*args, **kwargs):
+ """GetItemText(self, long item, int col=0) -> String"""
+ return _controls_.ListCtrl_GetItemText(*args, **kwargs)
+
+ def SetItemText(*args, **kwargs):
+ """SetItemText(self, long item, String str)"""
+ return _controls_.ListCtrl_SetItemText(*args, **kwargs)
+
+ def GetItemData(*args, **kwargs):
+ """GetItemData(self, long item) -> long"""
+ return _controls_.ListCtrl_GetItemData(*args, **kwargs)
+
+ def SetItemData(*args, **kwargs):
+ """SetItemData(self, long item, long data) -> bool"""
+ return _controls_.ListCtrl_SetItemData(*args, **kwargs)
+
+ def GetItemPosition(*args, **kwargs):
+ """GetItemPosition(self, long item) -> Point"""
+ return _controls_.ListCtrl_GetItemPosition(*args, **kwargs)
+
+ def GetItemRect(*args, **kwargs):
+ """GetItemRect(self, long item, int code=LIST_RECT_BOUNDS) -> Rect"""
+ return _controls_.ListCtrl_GetItemRect(*args, **kwargs)
+
+ def SetItemPosition(*args, **kwargs):
+ """SetItemPosition(self, long item, Point pos) -> bool"""
+ return _controls_.ListCtrl_SetItemPosition(*args, **kwargs)
+
+ def GetItemCount(*args, **kwargs):
+ """GetItemCount(self) -> int"""
+ return _controls_.ListCtrl_GetItemCount(*args, **kwargs)
+
+ def GetColumnCount(*args, **kwargs):
+ """GetColumnCount(self) -> int"""
+ return _controls_.ListCtrl_GetColumnCount(*args, **kwargs)
+
+ def GetItemSpacing(*args, **kwargs):
+ """GetItemSpacing(self) -> Size"""
+ return _controls_.ListCtrl_GetItemSpacing(*args, **kwargs)
+
+ GetItemSpacing = wx.deprecated(GetItemSpacing)
+ def GetSelectedItemCount(*args, **kwargs):
+ """GetSelectedItemCount(self) -> int"""
+ return _controls_.ListCtrl_GetSelectedItemCount(*args, **kwargs)
+
+ def GetTextColour(*args, **kwargs):
+ """GetTextColour(self) -> Colour"""
+ return _controls_.ListCtrl_GetTextColour(*args, **kwargs)
+
+ def SetTextColour(*args, **kwargs):
+ """SetTextColour(self, Colour col)"""
+ return _controls_.ListCtrl_SetTextColour(*args, **kwargs)
+
+ def GetTopItem(*args, **kwargs):
+ """GetTopItem(self) -> long"""
+ return _controls_.ListCtrl_GetTopItem(*args, **kwargs)
+
+ def SetSingleStyle(*args, **kwargs):
+ """SetSingleStyle(self, long style, bool add=True)"""
+ return _controls_.ListCtrl_SetSingleStyle(*args, **kwargs)
+
+ def GetNextItem(*args, **kwargs):
+ """GetNextItem(self, long item, int geometry=LIST_NEXT_ALL, int state=LIST_STATE_DONTCARE) -> long"""
+ return _controls_.ListCtrl_GetNextItem(*args, **kwargs)
+
+ def GetImageList(*args, **kwargs):
+ """GetImageList(self, int which) -> ImageList"""
+ return _controls_.ListCtrl_GetImageList(*args, **kwargs)
+
+ def SetImageList(*args, **kwargs):
+ """SetImageList(self, ImageList imageList, int which)"""
+ return _controls_.ListCtrl_SetImageList(*args, **kwargs)
+
+ def AssignImageList(*args, **kwargs):
+ """AssignImageList(self, ImageList imageList, int which)"""
+ return _controls_.ListCtrl_AssignImageList(*args, **kwargs)
+
+ def InReportView(*args, **kwargs):
+ """InReportView(self) -> bool"""
+ return _controls_.ListCtrl_InReportView(*args, **kwargs)
+
+ def IsVirtual(*args, **kwargs):
+ """IsVirtual(self) -> bool"""
+ return _controls_.ListCtrl_IsVirtual(*args, **kwargs)
+
+ def RefreshItem(*args, **kwargs):
+ """RefreshItem(self, long item)"""
+ return _controls_.ListCtrl_RefreshItem(*args, **kwargs)
+
+ def RefreshItems(*args, **kwargs):
+ """RefreshItems(self, long itemFrom, long itemTo)"""
+ return _controls_.ListCtrl_RefreshItems(*args, **kwargs)
+
+ def Arrange(*args, **kwargs):
+ """Arrange(self, int flag=LIST_ALIGN_DEFAULT) -> bool"""
+ return _controls_.ListCtrl_Arrange(*args, **kwargs)
+
+ def DeleteItem(*args, **kwargs):
+ """DeleteItem(self, long item) -> bool"""
+ return _controls_.ListCtrl_DeleteItem(*args, **kwargs)
+
+ def DeleteAllItems(*args, **kwargs):
+ """DeleteAllItems(self) -> bool"""
+ return _controls_.ListCtrl_DeleteAllItems(*args, **kwargs)
+
+ def DeleteColumn(*args, **kwargs):
+ """DeleteColumn(self, int col) -> bool"""
+ return _controls_.ListCtrl_DeleteColumn(*args, **kwargs)
+
+ def DeleteAllColumns(*args, **kwargs):
+ """DeleteAllColumns(self) -> bool"""
+ return _controls_.ListCtrl_DeleteAllColumns(*args, **kwargs)
+
+ def ClearAll(*args, **kwargs):
+ """ClearAll(self)"""
+ return _controls_.ListCtrl_ClearAll(*args, **kwargs)
+
+ def EditLabel(*args, **kwargs):
+ """EditLabel(self, long item) -> TextCtrl"""
+ return _controls_.ListCtrl_EditLabel(*args, **kwargs)
+
+ def EndEditLabel(*args, **kwargs):
+ """EndEditLabel(self, bool cancel) -> bool"""
+ return _controls_.ListCtrl_EndEditLabel(*args, **kwargs)
+
+ def EnsureVisible(*args, **kwargs):
+ """EnsureVisible(self, long item) -> bool"""
+ return _controls_.ListCtrl_EnsureVisible(*args, **kwargs)
+
+ def FindItem(*args, **kwargs):
+ """FindItem(self, long start, String str, bool partial=False) -> long"""
+ return _controls_.ListCtrl_FindItem(*args, **kwargs)
+
+ def FindItemData(*args, **kwargs):
+ """FindItemData(self, long start, long data) -> long"""
+ return _controls_.ListCtrl_FindItemData(*args, **kwargs)
+
+ def FindItemAtPos(*args, **kwargs):
+ """FindItemAtPos(self, long start, Point pt, int direction) -> long"""
+ return _controls_.ListCtrl_FindItemAtPos(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(Point point) -> (item, where)
+
+ Determines which item (if any) is at the specified point, giving
+ in the second return value (see wx.LIST_HITTEST flags.)
+ """
+ return _controls_.ListCtrl_HitTest(*args, **kwargs)
+
+ def HitTestSubItem(*args, **kwargs):
+ """
+ HitTestSubItem(Point point) -> (item, where, subItem)
+
+ Determines which item (if any) is at the specified point, giving in
+ the second return value (see wx.LIST_HITTEST flags) and also the subItem, if
+ any.
+ """
+ return _controls_.ListCtrl_HitTestSubItem(*args, **kwargs)
+
+ def InsertItem(*args, **kwargs):
+ """InsertItem(self, ListItem info) -> long"""
+ return _controls_.ListCtrl_InsertItem(*args, **kwargs)
+
+ def InsertStringItem(*args, **kwargs):
+ """InsertStringItem(self, long index, String label, int imageIndex=-1) -> long"""
+ return _controls_.ListCtrl_InsertStringItem(*args, **kwargs)
+
+ def InsertImageItem(*args, **kwargs):
+ """InsertImageItem(self, long index, int imageIndex) -> long"""
+ return _controls_.ListCtrl_InsertImageItem(*args, **kwargs)
+
+ def InsertImageStringItem(*args, **kwargs):
+ """InsertImageStringItem(self, long index, String label, int imageIndex) -> long"""
+ return _controls_.ListCtrl_InsertImageStringItem(*args, **kwargs)
+
+ def InsertColumnItem(*args, **kwargs):
+ """InsertColumnItem(self, long col, ListItem info) -> long"""
+ return _controls_.ListCtrl_InsertColumnItem(*args, **kwargs)
+
+ InsertColumnInfo = InsertColumnItem
+ def InsertColumn(*args, **kwargs):
+ """
+ InsertColumn(self, long col, String heading, int format=LIST_FORMAT_LEFT,
+ int width=-1) -> long
+ """
+ return _controls_.ListCtrl_InsertColumn(*args, **kwargs)
+
+ def SetItemCount(*args, **kwargs):
+ """SetItemCount(self, long count)"""
+ return _controls_.ListCtrl_SetItemCount(*args, **kwargs)
+
+ def ScrollList(*args, **kwargs):
+ """ScrollList(self, int dx, int dy) -> bool"""
+ return _controls_.ListCtrl_ScrollList(*args, **kwargs)
+
+ def SetItemTextColour(*args, **kwargs):
+ """SetItemTextColour(self, long item, Colour col)"""
+ return _controls_.ListCtrl_SetItemTextColour(*args, **kwargs)
+
+ def GetItemTextColour(*args, **kwargs):
+ """GetItemTextColour(self, long item) -> Colour"""
+ return _controls_.ListCtrl_GetItemTextColour(*args, **kwargs)
+
+ def SetItemBackgroundColour(*args, **kwargs):
+ """SetItemBackgroundColour(self, long item, Colour col)"""
+ return _controls_.ListCtrl_SetItemBackgroundColour(*args, **kwargs)
+
+ def GetItemBackgroundColour(*args, **kwargs):
+ """GetItemBackgroundColour(self, long item) -> Colour"""
+ return _controls_.ListCtrl_GetItemBackgroundColour(*args, **kwargs)
+
+ def SetItemFont(*args, **kwargs):
+ """SetItemFont(self, long item, Font f)"""
+ return _controls_.ListCtrl_SetItemFont(*args, **kwargs)
+
+ def GetItemFont(*args, **kwargs):
+ """GetItemFont(self, long item) -> Font"""
+ return _controls_.ListCtrl_GetItemFont(*args, **kwargs)
+
+ #
+ # Some helpers...
+ def Select(self, idx, on=1):
+ '''[de]select an item'''
+ if on: state = wx.LIST_STATE_SELECTED
+ else: state = 0
+ self.SetItemState(idx, state, wx.LIST_STATE_SELECTED)
+
+ def Focus(self, idx):
+ '''Focus and show the given item'''
+ self.SetItemState(idx, wx.LIST_STATE_FOCUSED, wx.LIST_STATE_FOCUSED)
+ self.EnsureVisible(idx)
+
+ def GetFocusedItem(self):
+ '''get the currently focused item or -1 if none'''
+ return self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_FOCUSED)
+
+ def GetFirstSelected(self, *args):
+ '''return first selected item, or -1 when none'''
+ return self.GetNextSelected(-1)
+
+ def GetNextSelected(self, item):
+ '''return subsequent selected items, or -1 when no more'''
+ return self.GetNextItem(item, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
+
+ def IsSelected(self, idx):
+ '''return True if the item is selected'''
+ return (self.GetItemState(idx, wx.LIST_STATE_SELECTED) & wx.LIST_STATE_SELECTED) != 0
+
+ def SetColumnImage(self, col, image):
+ item = self.GetColumn(col)
+ # preserve all other attributes too
+ item.SetMask( wx.LIST_MASK_STATE |
+ wx.LIST_MASK_TEXT |
+ wx.LIST_MASK_IMAGE |
+ wx.LIST_MASK_DATA |
+ wx.LIST_SET_ITEM |
+ wx.LIST_MASK_WIDTH |
+ wx.LIST_MASK_FORMAT )
+ item.SetImage(image)
+ self.SetColumn(col, item)
+
+ def ClearColumnImage(self, col):
+ self.SetColumnImage(col, -1)
+
+ def Append(self, entry):
+ '''Append an item to the list control. The entry parameter should be a
+ sequence with an item for each column'''
+ if len(entry):
+ if wx.USE_UNICODE:
+ cvtfunc = unicode
+ else:
+ cvtfunc = str
+ pos = self.GetItemCount()
+ self.InsertStringItem(pos, cvtfunc(entry[0]))
+ for i in range(1, len(entry)):
+ self.SetStringItem(pos, i, cvtfunc(entry[i]))
+ return pos
+
+ def SortItems(*args, **kwargs):
+ """SortItems(self, PyObject func) -> bool"""
+ return _controls_.ListCtrl_SortItems(*args, **kwargs)
+
+ def GetMainWindow(*args, **kwargs):
+ """GetMainWindow(self) -> Window"""
+ return _controls_.ListCtrl_GetMainWindow(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ListCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ ColumnCount = property(GetColumnCount,doc="See `GetColumnCount`")
+ CountPerPage = property(GetCountPerPage,doc="See `GetCountPerPage`")
+ EditControl = property(GetEditControl,doc="See `GetEditControl`")
+ FocusedItem = property(GetFocusedItem,doc="See `GetFocusedItem`")
+ ItemCount = property(GetItemCount,SetItemCount,doc="See `GetItemCount` and `SetItemCount`")
+ MainWindow = property(GetMainWindow,doc="See `GetMainWindow`")
+ SelectedItemCount = property(GetSelectedItemCount,doc="See `GetSelectedItemCount`")
+ TextColour = property(GetTextColour,SetTextColour,doc="See `GetTextColour` and `SetTextColour`")
+ TopItem = property(GetTopItem,doc="See `GetTopItem`")
+ ViewRect = property(GetViewRect,doc="See `GetViewRect`")
+_controls_.ListCtrl_swigregister(ListCtrl)
+
+def PreListCtrl(*args, **kwargs):
+ """PreListCtrl() -> ListCtrl"""
+ val = _controls_.new_PreListCtrl(*args, **kwargs)
+ return val
+
+def ListCtrl_HasColumnOrderSupport(*args):
+ """ListCtrl_HasColumnOrderSupport() -> bool"""
+ return _controls_.ListCtrl_HasColumnOrderSupport(*args)
+
+def ListCtrl_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ ListCtrl_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.ListCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class ListView(ListCtrl):
+ """Proxy of C++ ListView class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=LC_REPORT,
+ Validator validator=DefaultValidator, String name=ListCtrlNameStr) -> ListView
+ """
+ _controls_.ListView_swiginit(self,_controls_.new_ListView(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=LC_REPORT,
+ Validator validator=DefaultValidator, String name=ListCtrlNameStr) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _controls_.ListView_Create(*args, **kwargs)
+
+ def Select(*args, **kwargs):
+ """Select(self, long n, bool on=True)"""
+ return _controls_.ListView_Select(*args, **kwargs)
+
+ def Focus(*args, **kwargs):
+ """Focus(self, long index)"""
+ return _controls_.ListView_Focus(*args, **kwargs)
+
+ def GetFocusedItem(*args, **kwargs):
+ """GetFocusedItem(self) -> long"""
+ return _controls_.ListView_GetFocusedItem(*args, **kwargs)
+
+ def GetNextSelected(*args, **kwargs):
+ """GetNextSelected(self, long item) -> long"""
+ return _controls_.ListView_GetNextSelected(*args, **kwargs)
+
+ def GetFirstSelected(*args, **kwargs):
+ """GetFirstSelected(self) -> long"""
+ return _controls_.ListView_GetFirstSelected(*args, **kwargs)
+
+ def IsSelected(*args, **kwargs):
+ """IsSelected(self, long index) -> bool"""
+ return _controls_.ListView_IsSelected(*args, **kwargs)
+
+ def SetColumnImage(*args, **kwargs):
+ """SetColumnImage(self, int col, int image)"""
+ return _controls_.ListView_SetColumnImage(*args, **kwargs)
+
+ def ClearColumnImage(*args, **kwargs):
+ """ClearColumnImage(self, int col)"""
+ return _controls_.ListView_ClearColumnImage(*args, **kwargs)
+
+ FocusedItem = property(GetFocusedItem,doc="See `GetFocusedItem`")
+_controls_.ListView_swigregister(ListView)
+
+def PreListView(*args, **kwargs):
+ """PreListView() -> ListView"""
+ val = _controls_.new_PreListView(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+TR_NO_BUTTONS = _controls_.TR_NO_BUTTONS
+TR_HAS_BUTTONS = _controls_.TR_HAS_BUTTONS
+TR_NO_LINES = _controls_.TR_NO_LINES
+TR_LINES_AT_ROOT = _controls_.TR_LINES_AT_ROOT
+TR_SINGLE = _controls_.TR_SINGLE
+TR_MULTIPLE = _controls_.TR_MULTIPLE
+TR_EXTENDED = _controls_.TR_EXTENDED
+TR_HAS_VARIABLE_ROW_HEIGHT = _controls_.TR_HAS_VARIABLE_ROW_HEIGHT
+TR_EDIT_LABELS = _controls_.TR_EDIT_LABELS
+TR_HIDE_ROOT = _controls_.TR_HIDE_ROOT
+TR_ROW_LINES = _controls_.TR_ROW_LINES
+TR_FULL_ROW_HIGHLIGHT = _controls_.TR_FULL_ROW_HIGHLIGHT
+TR_DEFAULT_STYLE = _controls_.TR_DEFAULT_STYLE
+TR_TWIST_BUTTONS = _controls_.TR_TWIST_BUTTONS
+# obsolete
+TR_MAC_BUTTONS = 0
+wxTR_AQUA_BUTTONS = 0
+
+TreeItemIcon_Normal = _controls_.TreeItemIcon_Normal
+TreeItemIcon_Selected = _controls_.TreeItemIcon_Selected
+TreeItemIcon_Expanded = _controls_.TreeItemIcon_Expanded
+TreeItemIcon_SelectedExpanded = _controls_.TreeItemIcon_SelectedExpanded
+TreeItemIcon_Max = _controls_.TreeItemIcon_Max
+TREE_ITEMSTATE_NONE = _controls_.TREE_ITEMSTATE_NONE
+TREE_ITEMSTATE_NEXT = _controls_.TREE_ITEMSTATE_NEXT
+TREE_ITEMSTATE_PREV = _controls_.TREE_ITEMSTATE_PREV
+TREE_HITTEST_ABOVE = _controls_.TREE_HITTEST_ABOVE
+TREE_HITTEST_BELOW = _controls_.TREE_HITTEST_BELOW
+TREE_HITTEST_NOWHERE = _controls_.TREE_HITTEST_NOWHERE
+TREE_HITTEST_ONITEMBUTTON = _controls_.TREE_HITTEST_ONITEMBUTTON
+TREE_HITTEST_ONITEMICON = _controls_.TREE_HITTEST_ONITEMICON
+TREE_HITTEST_ONITEMINDENT = _controls_.TREE_HITTEST_ONITEMINDENT
+TREE_HITTEST_ONITEMLABEL = _controls_.TREE_HITTEST_ONITEMLABEL
+TREE_HITTEST_ONITEMRIGHT = _controls_.TREE_HITTEST_ONITEMRIGHT
+TREE_HITTEST_ONITEMSTATEICON = _controls_.TREE_HITTEST_ONITEMSTATEICON
+TREE_HITTEST_TOLEFT = _controls_.TREE_HITTEST_TOLEFT
+TREE_HITTEST_TORIGHT = _controls_.TREE_HITTEST_TORIGHT
+TREE_HITTEST_ONITEMUPPERPART = _controls_.TREE_HITTEST_ONITEMUPPERPART
+TREE_HITTEST_ONITEMLOWERPART = _controls_.TREE_HITTEST_ONITEMLOWERPART
+TREE_HITTEST_ONITEM = _controls_.TREE_HITTEST_ONITEM
+#---------------------------------------------------------------------------
+
+class TreeItemId(object):
+ """Proxy of C++ TreeItemId class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> TreeItemId"""
+ _controls_.TreeItemId_swiginit(self,_controls_.new_TreeItemId(*args, **kwargs))
+ __swig_destroy__ = _controls_.delete_TreeItemId
+ __del__ = lambda self : None;
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _controls_.TreeItemId_IsOk(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """__eq__(self, TreeItemId other) -> bool"""
+ return _controls_.TreeItemId___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """__ne__(self, TreeItemId other) -> bool"""
+ return _controls_.TreeItemId___ne__(*args, **kwargs)
+
+ m_pItem = property(_controls_.TreeItemId_m_pItem_get, _controls_.TreeItemId_m_pItem_set)
+ Ok = IsOk
+ def __nonzero__(self): return self.IsOk()
+_controls_.TreeItemId_swigregister(TreeItemId)
+TreeCtrlNameStr = cvar.TreeCtrlNameStr
+
+class TreeItemData(object):
+ """Proxy of C++ TreeItemData class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, PyObject obj=None) -> TreeItemData"""
+ _controls_.TreeItemData_swiginit(self,_controls_.new_TreeItemData(*args, **kwargs))
+ __swig_destroy__ = _controls_.delete_TreeItemData
+ __del__ = lambda self : None;
+ def GetData(*args, **kwargs):
+ """GetData(self) -> PyObject"""
+ return _controls_.TreeItemData_GetData(*args, **kwargs)
+
+ def SetData(*args, **kwargs):
+ """SetData(self, PyObject obj)"""
+ return _controls_.TreeItemData_SetData(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """GetId(self) -> TreeItemId"""
+ return _controls_.TreeItemData_GetId(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """SetId(self, TreeItemId id)"""
+ return _controls_.TreeItemData_SetId(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """Destroy(self)"""
+ args[0].this.own(False)
+ return _controls_.TreeItemData_Destroy(*args, **kwargs)
+
+ Data = property(GetData,SetData,doc="See `GetData` and `SetData`")
+ Id = property(GetId,SetId,doc="See `GetId` and `SetId`")
+_controls_.TreeItemData_swigregister(TreeItemData)
+
+#---------------------------------------------------------------------------
+
+wxEVT_COMMAND_TREE_BEGIN_DRAG = _controls_.wxEVT_COMMAND_TREE_BEGIN_DRAG
+wxEVT_COMMAND_TREE_BEGIN_RDRAG = _controls_.wxEVT_COMMAND_TREE_BEGIN_RDRAG
+wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT = _controls_.wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT
+wxEVT_COMMAND_TREE_END_LABEL_EDIT = _controls_.wxEVT_COMMAND_TREE_END_LABEL_EDIT
+wxEVT_COMMAND_TREE_DELETE_ITEM = _controls_.wxEVT_COMMAND_TREE_DELETE_ITEM
+wxEVT_COMMAND_TREE_GET_INFO = _controls_.wxEVT_COMMAND_TREE_GET_INFO
+wxEVT_COMMAND_TREE_SET_INFO = _controls_.wxEVT_COMMAND_TREE_SET_INFO
+wxEVT_COMMAND_TREE_ITEM_EXPANDED = _controls_.wxEVT_COMMAND_TREE_ITEM_EXPANDED
+wxEVT_COMMAND_TREE_ITEM_EXPANDING = _controls_.wxEVT_COMMAND_TREE_ITEM_EXPANDING
+wxEVT_COMMAND_TREE_ITEM_COLLAPSED = _controls_.wxEVT_COMMAND_TREE_ITEM_COLLAPSED
+wxEVT_COMMAND_TREE_ITEM_COLLAPSING = _controls_.wxEVT_COMMAND_TREE_ITEM_COLLAPSING
+wxEVT_COMMAND_TREE_SEL_CHANGED = _controls_.wxEVT_COMMAND_TREE_SEL_CHANGED
+wxEVT_COMMAND_TREE_SEL_CHANGING = _controls_.wxEVT_COMMAND_TREE_SEL_CHANGING
+wxEVT_COMMAND_TREE_KEY_DOWN = _controls_.wxEVT_COMMAND_TREE_KEY_DOWN
+wxEVT_COMMAND_TREE_ITEM_ACTIVATED = _controls_.wxEVT_COMMAND_TREE_ITEM_ACTIVATED
+wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK = _controls_.wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK
+wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK = _controls_.wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK
+wxEVT_COMMAND_TREE_END_DRAG = _controls_.wxEVT_COMMAND_TREE_END_DRAG
+wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK = _controls_.wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK
+wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP = _controls_.wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP
+wxEVT_COMMAND_TREE_ITEM_MENU = _controls_.wxEVT_COMMAND_TREE_ITEM_MENU
+EVT_TREE_BEGIN_DRAG = wx.PyEventBinder(wxEVT_COMMAND_TREE_BEGIN_DRAG , 1)
+EVT_TREE_BEGIN_RDRAG = wx.PyEventBinder(wxEVT_COMMAND_TREE_BEGIN_RDRAG , 1)
+EVT_TREE_BEGIN_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT , 1)
+EVT_TREE_END_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_TREE_END_LABEL_EDIT , 1)
+EVT_TREE_DELETE_ITEM = wx.PyEventBinder(wxEVT_COMMAND_TREE_DELETE_ITEM , 1)
+EVT_TREE_GET_INFO = wx.PyEventBinder(wxEVT_COMMAND_TREE_GET_INFO , 1)
+EVT_TREE_SET_INFO = wx.PyEventBinder(wxEVT_COMMAND_TREE_SET_INFO , 1)
+EVT_TREE_ITEM_EXPANDED = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_EXPANDED , 1)
+EVT_TREE_ITEM_EXPANDING = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_EXPANDING , 1)
+EVT_TREE_ITEM_COLLAPSED = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_COLLAPSED , 1)
+EVT_TREE_ITEM_COLLAPSING = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_COLLAPSING , 1)
+EVT_TREE_SEL_CHANGED = wx.PyEventBinder(wxEVT_COMMAND_TREE_SEL_CHANGED , 1)
+EVT_TREE_SEL_CHANGING = wx.PyEventBinder(wxEVT_COMMAND_TREE_SEL_CHANGING , 1)
+EVT_TREE_KEY_DOWN = wx.PyEventBinder(wxEVT_COMMAND_TREE_KEY_DOWN , 1)
+EVT_TREE_ITEM_ACTIVATED = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_ACTIVATED , 1)
+EVT_TREE_ITEM_RIGHT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK , 1)
+EVT_TREE_ITEM_MIDDLE_CLICK = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, 1)
+EVT_TREE_END_DRAG = wx.PyEventBinder(wxEVT_COMMAND_TREE_END_DRAG , 1)
+EVT_TREE_STATE_IMAGE_CLICK = wx.PyEventBinder(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, 1)
+EVT_TREE_ITEM_GETTOOLTIP = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, 1)
+EVT_TREE_ITEM_MENU = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_MENU, 1)
+
+class TreeEvent(_core.NotifyEvent):
+ """Proxy of C++ TreeEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, EventType commandType=wxEVT_NULL, int id=0) -> TreeEvent
+ __init__(self, EventType commandType, TreeCtrl tree, TreeItemId item=NullTreeItemId) -> TreeEvent
+ """
+ _controls_.TreeEvent_swiginit(self,_controls_.new_TreeEvent(*args))
+ def GetItem(*args, **kwargs):
+ """GetItem(self) -> TreeItemId"""
+ return _controls_.TreeEvent_GetItem(*args, **kwargs)
+
+ def SetItem(*args, **kwargs):
+ """SetItem(self, TreeItemId item)"""
+ return _controls_.TreeEvent_SetItem(*args, **kwargs)
+
+ def GetOldItem(*args, **kwargs):
+ """GetOldItem(self) -> TreeItemId"""
+ return _controls_.TreeEvent_GetOldItem(*args, **kwargs)
+
+ def SetOldItem(*args, **kwargs):
+ """SetOldItem(self, TreeItemId item)"""
+ return _controls_.TreeEvent_SetOldItem(*args, **kwargs)
+
+ def GetPoint(*args, **kwargs):
+ """GetPoint(self) -> Point"""
+ return _controls_.TreeEvent_GetPoint(*args, **kwargs)
+
+ def SetPoint(*args, **kwargs):
+ """SetPoint(self, Point pt)"""
+ return _controls_.TreeEvent_SetPoint(*args, **kwargs)
+
+ def GetKeyEvent(*args, **kwargs):
+ """GetKeyEvent(self) -> KeyEvent"""
+ return _controls_.TreeEvent_GetKeyEvent(*args, **kwargs)
+
+ def GetKeyCode(*args, **kwargs):
+ """GetKeyCode(self) -> int"""
+ return _controls_.TreeEvent_GetKeyCode(*args, **kwargs)
+
+ def SetKeyEvent(*args, **kwargs):
+ """SetKeyEvent(self, KeyEvent evt)"""
+ return _controls_.TreeEvent_SetKeyEvent(*args, **kwargs)
+
+ def GetLabel(*args, **kwargs):
+ """GetLabel(self) -> String"""
+ return _controls_.TreeEvent_GetLabel(*args, **kwargs)
+
+ def SetLabel(*args, **kwargs):
+ """SetLabel(self, String label)"""
+ return _controls_.TreeEvent_SetLabel(*args, **kwargs)
+
+ def IsEditCancelled(*args, **kwargs):
+ """IsEditCancelled(self) -> bool"""
+ return _controls_.TreeEvent_IsEditCancelled(*args, **kwargs)
+
+ def SetEditCanceled(*args, **kwargs):
+ """SetEditCanceled(self, bool editCancelled)"""
+ return _controls_.TreeEvent_SetEditCanceled(*args, **kwargs)
+
+ def SetToolTip(*args, **kwargs):
+ """SetToolTip(self, String toolTip)"""
+ return _controls_.TreeEvent_SetToolTip(*args, **kwargs)
+
+ def GetToolTip(*args, **kwargs):
+ """GetToolTip(self) -> String"""
+ return _controls_.TreeEvent_GetToolTip(*args, **kwargs)
+
+ Item = property(GetItem,SetItem,doc="See `GetItem` and `SetItem`")
+ KeyCode = property(GetKeyCode,doc="See `GetKeyCode`")
+ KeyEvent = property(GetKeyEvent,SetKeyEvent,doc="See `GetKeyEvent` and `SetKeyEvent`")
+ Label = property(GetLabel,SetLabel,doc="See `GetLabel` and `SetLabel`")
+ OldItem = property(GetOldItem,SetOldItem,doc="See `GetOldItem` and `SetOldItem`")
+ Point = property(GetPoint,SetPoint,doc="See `GetPoint` and `SetPoint`")
+ ToolTip = property(GetToolTip,SetToolTip,doc="See `GetToolTip` and `SetToolTip`")
+ EditCancelled = property(IsEditCancelled,SetEditCanceled,doc="See `IsEditCancelled` and `SetEditCanceled`")
+_controls_.TreeEvent_swigregister(TreeEvent)
+
+#---------------------------------------------------------------------------
+
+class TreeCtrl(_core.Control):
+ """Proxy of C++ TreeCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=TR_DEFAULT_STYLE,
+ Validator validator=DefaultValidator,
+ String name=TreeCtrlNameStr) -> TreeCtrl
+ """
+ _controls_.TreeCtrl_swiginit(self,_controls_.new_TreeCtrl(*args, **kwargs))
+ self._setOORInfo(self);TreeCtrl._setCallbackInfo(self, self, TreeCtrl)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=TR_DEFAULT_STYLE,
+ Validator validator=DefaultValidator,
+ String name=TreeCtrlNameStr) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _controls_.TreeCtrl_Create(*args, **kwargs)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _controls_.TreeCtrl__setCallbackInfo(*args, **kwargs)
+
+ def GetCount(*args, **kwargs):
+ """GetCount(self) -> unsigned int"""
+ return _controls_.TreeCtrl_GetCount(*args, **kwargs)
+
+ def GetIndent(*args, **kwargs):
+ """GetIndent(self) -> unsigned int"""
+ return _controls_.TreeCtrl_GetIndent(*args, **kwargs)
+
+ def SetIndent(*args, **kwargs):
+ """SetIndent(self, unsigned int indent)"""
+ return _controls_.TreeCtrl_SetIndent(*args, **kwargs)
+
+ def GetSpacing(*args, **kwargs):
+ """GetSpacing(self) -> unsigned int"""
+ return _controls_.TreeCtrl_GetSpacing(*args, **kwargs)
+
+ def SetSpacing(*args, **kwargs):
+ """SetSpacing(self, unsigned int spacing)"""
+ return _controls_.TreeCtrl_SetSpacing(*args, **kwargs)
+
+ def GetImageList(*args, **kwargs):
+ """GetImageList(self) -> ImageList"""
+ return _controls_.TreeCtrl_GetImageList(*args, **kwargs)
+
+ def GetStateImageList(*args, **kwargs):
+ """GetStateImageList(self) -> ImageList"""
+ return _controls_.TreeCtrl_GetStateImageList(*args, **kwargs)
+
+ def SetImageList(*args, **kwargs):
+ """SetImageList(self, ImageList imageList)"""
+ return _controls_.TreeCtrl_SetImageList(*args, **kwargs)
+
+ def SetStateImageList(*args, **kwargs):
+ """SetStateImageList(self, ImageList imageList)"""
+ return _controls_.TreeCtrl_SetStateImageList(*args, **kwargs)
+
+ def AssignImageList(*args, **kwargs):
+ """AssignImageList(self, ImageList imageList)"""
+ return _controls_.TreeCtrl_AssignImageList(*args, **kwargs)
+
+ def AssignStateImageList(*args, **kwargs):
+ """AssignStateImageList(self, ImageList imageList)"""
+ return _controls_.TreeCtrl_AssignStateImageList(*args, **kwargs)
+
+ def GetItemText(*args, **kwargs):
+ """GetItemText(self, TreeItemId item) -> String"""
+ return _controls_.TreeCtrl_GetItemText(*args, **kwargs)
+
+ def GetItemImage(*args, **kwargs):
+ """GetItemImage(self, TreeItemId item, int which=TreeItemIcon_Normal) -> int"""
+ return _controls_.TreeCtrl_GetItemImage(*args, **kwargs)
+
+ def GetItemData(*args, **kwargs):
+ """GetItemData(self, TreeItemId item) -> TreeItemData"""
+ return _controls_.TreeCtrl_GetItemData(*args, **kwargs)
+
+ def GetItemPyData(*args, **kwargs):
+ """GetItemPyData(self, TreeItemId item) -> PyObject"""
+ return _controls_.TreeCtrl_GetItemPyData(*args, **kwargs)
+
+ GetPyData = GetItemPyData
+ def GetItemTextColour(*args, **kwargs):
+ """GetItemTextColour(self, TreeItemId item) -> Colour"""
+ return _controls_.TreeCtrl_GetItemTextColour(*args, **kwargs)
+
+ def GetItemBackgroundColour(*args, **kwargs):
+ """GetItemBackgroundColour(self, TreeItemId item) -> Colour"""
+ return _controls_.TreeCtrl_GetItemBackgroundColour(*args, **kwargs)
+
+ def GetItemFont(*args, **kwargs):
+ """GetItemFont(self, TreeItemId item) -> Font"""
+ return _controls_.TreeCtrl_GetItemFont(*args, **kwargs)
+
+ def GetItemState(*args, **kwargs):
+ """GetItemState(self, TreeItemId item) -> int"""
+ return _controls_.TreeCtrl_GetItemState(*args, **kwargs)
+
+ def SetItemText(*args, **kwargs):
+ """SetItemText(self, TreeItemId item, String text)"""
+ return _controls_.TreeCtrl_SetItemText(*args, **kwargs)
+
+ def SetItemImage(*args, **kwargs):
+ """SetItemImage(self, TreeItemId item, int image, int which=TreeItemIcon_Normal)"""
+ return _controls_.TreeCtrl_SetItemImage(*args, **kwargs)
+
+ def SetItemData(*args, **kwargs):
+ """SetItemData(self, TreeItemId item, TreeItemData data)"""
+ return _controls_.TreeCtrl_SetItemData(*args, **kwargs)
+
+ def SetItemPyData(*args, **kwargs):
+ """SetItemPyData(self, TreeItemId item, PyObject obj)"""
+ return _controls_.TreeCtrl_SetItemPyData(*args, **kwargs)
+
+ SetPyData = SetItemPyData
+ def SetItemHasChildren(*args, **kwargs):
+ """SetItemHasChildren(self, TreeItemId item, bool has=True)"""
+ return _controls_.TreeCtrl_SetItemHasChildren(*args, **kwargs)
+
+ def SetItemBold(*args, **kwargs):
+ """SetItemBold(self, TreeItemId item, bool bold=True)"""
+ return _controls_.TreeCtrl_SetItemBold(*args, **kwargs)
+
+ def SetItemDropHighlight(*args, **kwargs):
+ """SetItemDropHighlight(self, TreeItemId item, bool highlight=True)"""
+ return _controls_.TreeCtrl_SetItemDropHighlight(*args, **kwargs)
+
+ def SetItemTextColour(*args, **kwargs):
+ """SetItemTextColour(self, TreeItemId item, Colour col)"""
+ return _controls_.TreeCtrl_SetItemTextColour(*args, **kwargs)
+
+ def SetItemBackgroundColour(*args, **kwargs):
+ """SetItemBackgroundColour(self, TreeItemId item, Colour col)"""
+ return _controls_.TreeCtrl_SetItemBackgroundColour(*args, **kwargs)
+
+ def SetItemFont(*args, **kwargs):
+ """SetItemFont(self, TreeItemId item, Font font)"""
+ return _controls_.TreeCtrl_SetItemFont(*args, **kwargs)
+
+ def SetItemState(*args, **kwargs):
+ """SetItemState(self, TreeItemId item, int state)"""
+ return _controls_.TreeCtrl_SetItemState(*args, **kwargs)
+
+ def IsVisible(*args, **kwargs):
+ """IsVisible(self, TreeItemId item) -> bool"""
+ return _controls_.TreeCtrl_IsVisible(*args, **kwargs)
+
+ def ItemHasChildren(*args, **kwargs):
+ """ItemHasChildren(self, TreeItemId item) -> bool"""
+ return _controls_.TreeCtrl_ItemHasChildren(*args, **kwargs)
+
+ def IsExpanded(*args, **kwargs):
+ """IsExpanded(self, TreeItemId item) -> bool"""
+ return _controls_.TreeCtrl_IsExpanded(*args, **kwargs)
+
+ def IsSelected(*args, **kwargs):
+ """IsSelected(self, TreeItemId item) -> bool"""
+ return _controls_.TreeCtrl_IsSelected(*args, **kwargs)
+
+ def IsBold(*args, **kwargs):
+ """IsBold(self, TreeItemId item) -> bool"""
+ return _controls_.TreeCtrl_IsBold(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """IsEmpty(self) -> bool"""
+ return _controls_.TreeCtrl_IsEmpty(*args, **kwargs)
+
+ def GetChildrenCount(*args, **kwargs):
+ """GetChildrenCount(self, TreeItemId item, bool recursively=True) -> size_t"""
+ return _controls_.TreeCtrl_GetChildrenCount(*args, **kwargs)
+
+ def GetRootItem(*args, **kwargs):
+ """GetRootItem(self) -> TreeItemId"""
+ return _controls_.TreeCtrl_GetRootItem(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> TreeItemId"""
+ return _controls_.TreeCtrl_GetSelection(*args, **kwargs)
+
+ def GetSelections(*args, **kwargs):
+ """GetSelections(self) -> PyObject"""
+ return _controls_.TreeCtrl_GetSelections(*args, **kwargs)
+
+ def GetFocusedItem(*args, **kwargs):
+ """GetFocusedItem(self) -> TreeItemId"""
+ return _controls_.TreeCtrl_GetFocusedItem(*args, **kwargs)
+
+ def ClearFocusedItem(*args, **kwargs):
+ """ClearFocusedItem(self)"""
+ return _controls_.TreeCtrl_ClearFocusedItem(*args, **kwargs)
+
+ def SetFocusedItem(*args, **kwargs):
+ """SetFocusedItem(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_SetFocusedItem(*args, **kwargs)
+
+ def GetItemParent(*args, **kwargs):
+ """GetItemParent(self, TreeItemId item) -> TreeItemId"""
+ return _controls_.TreeCtrl_GetItemParent(*args, **kwargs)
+
+ def GetFirstChild(*args, **kwargs):
+ """GetFirstChild(self, TreeItemId item) -> PyObject"""
+ return _controls_.TreeCtrl_GetFirstChild(*args, **kwargs)
+
+ def GetNextChild(*args, **kwargs):
+ """GetNextChild(self, TreeItemId item, void cookie) -> PyObject"""
+ return _controls_.TreeCtrl_GetNextChild(*args, **kwargs)
+
+ def GetLastChild(*args, **kwargs):
+ """GetLastChild(self, TreeItemId item) -> TreeItemId"""
+ return _controls_.TreeCtrl_GetLastChild(*args, **kwargs)
+
+ def GetNextSibling(*args, **kwargs):
+ """GetNextSibling(self, TreeItemId item) -> TreeItemId"""
+ return _controls_.TreeCtrl_GetNextSibling(*args, **kwargs)
+
+ def GetPrevSibling(*args, **kwargs):
+ """GetPrevSibling(self, TreeItemId item) -> TreeItemId"""
+ return _controls_.TreeCtrl_GetPrevSibling(*args, **kwargs)
+
+ def GetFirstVisibleItem(*args, **kwargs):
+ """GetFirstVisibleItem(self) -> TreeItemId"""
+ return _controls_.TreeCtrl_GetFirstVisibleItem(*args, **kwargs)
+
+ def GetNextVisible(*args, **kwargs):
+ """GetNextVisible(self, TreeItemId item) -> TreeItemId"""
+ return _controls_.TreeCtrl_GetNextVisible(*args, **kwargs)
+
+ def GetPrevVisible(*args, **kwargs):
+ """GetPrevVisible(self, TreeItemId item) -> TreeItemId"""
+ return _controls_.TreeCtrl_GetPrevVisible(*args, **kwargs)
+
+ def AddRoot(*args, **kwargs):
+ """AddRoot(self, String text, int image=-1, int selectedImage=-1, TreeItemData data=None) -> TreeItemId"""
+ return _controls_.TreeCtrl_AddRoot(*args, **kwargs)
+
+ def PrependItem(*args, **kwargs):
+ """
+ PrependItem(self, TreeItemId parent, String text, int image=-1, int selectedImage=-1,
+ TreeItemData data=None) -> TreeItemId
+ """
+ return _controls_.TreeCtrl_PrependItem(*args, **kwargs)
+
+ def InsertItem(*args, **kwargs):
+ """
+ InsertItem(self, TreeItemId parent, TreeItemId idPrevious, String text,
+ int image=-1, int selectedImage=-1, TreeItemData data=None) -> TreeItemId
+ """
+ return _controls_.TreeCtrl_InsertItem(*args, **kwargs)
+
+ def InsertItemBefore(*args, **kwargs):
+ """
+ InsertItemBefore(self, TreeItemId parent, size_t index, String text, int image=-1,
+ int selectedImage=-1, TreeItemData data=None) -> TreeItemId
+ """
+ return _controls_.TreeCtrl_InsertItemBefore(*args, **kwargs)
+
+ def AppendItem(*args, **kwargs):
+ """
+ AppendItem(self, TreeItemId parent, String text, int image=-1, int selectedImage=-1,
+ TreeItemData data=None) -> TreeItemId
+ """
+ return _controls_.TreeCtrl_AppendItem(*args, **kwargs)
+
+ def Delete(*args, **kwargs):
+ """Delete(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_Delete(*args, **kwargs)
+
+ def DeleteChildren(*args, **kwargs):
+ """DeleteChildren(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_DeleteChildren(*args, **kwargs)
+
+ def DeleteAllItems(*args, **kwargs):
+ """DeleteAllItems(self)"""
+ return _controls_.TreeCtrl_DeleteAllItems(*args, **kwargs)
+
+ def Expand(*args, **kwargs):
+ """Expand(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_Expand(*args, **kwargs)
+
+ def ExpandAllChildren(*args, **kwargs):
+ """ExpandAllChildren(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_ExpandAllChildren(*args, **kwargs)
+
+ def ExpandAll(*args, **kwargs):
+ """ExpandAll(self)"""
+ return _controls_.TreeCtrl_ExpandAll(*args, **kwargs)
+
+ def Collapse(*args, **kwargs):
+ """Collapse(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_Collapse(*args, **kwargs)
+
+ def CollapseAllChildren(*args, **kwargs):
+ """CollapseAllChildren(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_CollapseAllChildren(*args, **kwargs)
+
+ def CollapseAll(*args, **kwargs):
+ """CollapseAll(self)"""
+ return _controls_.TreeCtrl_CollapseAll(*args, **kwargs)
+
+ def CollapseAndReset(*args, **kwargs):
+ """CollapseAndReset(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_CollapseAndReset(*args, **kwargs)
+
+ def Toggle(*args, **kwargs):
+ """Toggle(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_Toggle(*args, **kwargs)
+
+ def Unselect(*args, **kwargs):
+ """Unselect(self)"""
+ return _controls_.TreeCtrl_Unselect(*args, **kwargs)
+
+ def UnselectItem(*args, **kwargs):
+ """UnselectItem(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_UnselectItem(*args, **kwargs)
+
+ def UnselectAll(*args, **kwargs):
+ """UnselectAll(self)"""
+ return _controls_.TreeCtrl_UnselectAll(*args, **kwargs)
+
+ def SelectItem(*args, **kwargs):
+ """SelectItem(self, TreeItemId item, bool select=True)"""
+ return _controls_.TreeCtrl_SelectItem(*args, **kwargs)
+
+ def SelectChildren(*args, **kwargs):
+ """SelectChildren(self, TreeItemId parent)"""
+ return _controls_.TreeCtrl_SelectChildren(*args, **kwargs)
+
+ def ToggleItemSelection(*args, **kwargs):
+ """ToggleItemSelection(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_ToggleItemSelection(*args, **kwargs)
+
+ def EnsureVisible(*args, **kwargs):
+ """EnsureVisible(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_EnsureVisible(*args, **kwargs)
+
+ def ScrollTo(*args, **kwargs):
+ """ScrollTo(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_ScrollTo(*args, **kwargs)
+
+ def EditLabel(*args, **kwargs):
+ """EditLabel(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_EditLabel(*args, **kwargs)
+
+ def GetEditControl(*args, **kwargs):
+ """GetEditControl(self) -> TextCtrl"""
+ return _controls_.TreeCtrl_GetEditControl(*args, **kwargs)
+
+ def EndEditLabel(*args, **kwargs):
+ """EndEditLabel(self, TreeItemId item, bool discardChanges=False)"""
+ return _controls_.TreeCtrl_EndEditLabel(*args, **kwargs)
+
+ def SortChildren(*args, **kwargs):
+ """SortChildren(self, TreeItemId item)"""
+ return _controls_.TreeCtrl_SortChildren(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(Point point) -> (item, where)
+
+ Determine which item (if any) belongs the given point. The coordinates
+ specified are relative to the client area of tree ctrl and the where return
+ value is set to a bitmask of wxTREE_HITTEST_xxx constants.
+
+ """
+ return _controls_.TreeCtrl_HitTest(*args, **kwargs)
+
+ def GetBoundingRect(*args, **kwargs):
+ """GetBoundingRect(self, TreeItemId item, bool textOnly=False) -> PyObject"""
+ return _controls_.TreeCtrl_GetBoundingRect(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.TreeCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ def SetQuickBestSize(*args, **kwargs):
+ """SetQuickBestSize(self, bool q)"""
+ return _controls_.TreeCtrl_SetQuickBestSize(*args, **kwargs)
+
+ def GetQuickBestSize(*args, **kwargs):
+ """GetQuickBestSize(self) -> bool"""
+ return _controls_.TreeCtrl_GetQuickBestSize(*args, **kwargs)
+
+ Count = property(GetCount,doc="See `GetCount`")
+ EditControl = property(GetEditControl,doc="See `GetEditControl`")
+ FirstVisibleItem = property(GetFirstVisibleItem,doc="See `GetFirstVisibleItem`")
+ ImageList = property(GetImageList,SetImageList,doc="See `GetImageList` and `SetImageList`")
+ Indent = property(GetIndent,SetIndent,doc="See `GetIndent` and `SetIndent`")
+ QuickBestSize = property(GetQuickBestSize,SetQuickBestSize,doc="See `GetQuickBestSize` and `SetQuickBestSize`")
+ RootItem = property(GetRootItem,doc="See `GetRootItem`")
+ Selection = property(GetSelection,doc="See `GetSelection`")
+ Selections = property(GetSelections,doc="See `GetSelections`")
+ Spacing = property(GetSpacing,SetSpacing,doc="See `GetSpacing` and `SetSpacing`")
+ StateImageList = property(GetStateImageList,SetStateImageList,doc="See `GetStateImageList` and `SetStateImageList`")
+_controls_.TreeCtrl_swigregister(TreeCtrl)
+
+def PreTreeCtrl(*args, **kwargs):
+ """PreTreeCtrl() -> TreeCtrl"""
+ val = _controls_.new_PreTreeCtrl(*args, **kwargs)
+ return val
+
+def TreeCtrl_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ TreeCtrl_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _controls_.TreeCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+DIRCTRL_DIR_ONLY = _controls_.DIRCTRL_DIR_ONLY
+DIRCTRL_SELECT_FIRST = _controls_.DIRCTRL_SELECT_FIRST
+DIRCTRL_SHOW_FILTERS = _controls_.DIRCTRL_SHOW_FILTERS
+DIRCTRL_3D_INTERNAL = _controls_.DIRCTRL_3D_INTERNAL
+DIRCTRL_EDIT_LABELS = _controls_.DIRCTRL_EDIT_LABELS
+DIRCTRL_MULTIPLE = _controls_.DIRCTRL_MULTIPLE
+class DirItemData(_core.Object):
+ """Proxy of C++ DirItemData class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def SetNewDirName(*args, **kwargs):
+ """SetNewDirName(self, String path)"""
+ return _controls_.DirItemData_SetNewDirName(*args, **kwargs)
+
+ m_path = property(_controls_.DirItemData_m_path_get, _controls_.DirItemData_m_path_set)
+ m_name = property(_controls_.DirItemData_m_name_get, _controls_.DirItemData_m_name_set)
+ m_isHidden = property(_controls_.DirItemData_m_isHidden_get, _controls_.DirItemData_m_isHidden_set)
+ m_isExpanded = property(_controls_.DirItemData_m_isExpanded_get, _controls_.DirItemData_m_isExpanded_set)
+ m_isDir = property(_controls_.DirItemData_m_isDir_get, _controls_.DirItemData_m_isDir_set)
+_controls_.DirItemData_swigregister(DirItemData)
+DirDialogDefaultFolderStr = cvar.DirDialogDefaultFolderStr
+
+class GenericDirCtrl(_core.Control):
+ """Proxy of C++ GenericDirCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String dir=DirDialogDefaultFolderStr,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DIRCTRL_3D_INTERNAL,
+ String filter=EmptyString, int defaultFilter=0,
+ String name=TreeCtrlNameStr) -> GenericDirCtrl
+ """
+ _controls_.GenericDirCtrl_swiginit(self,_controls_.new_GenericDirCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String dir=DirDialogDefaultFolderStr,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DIRCTRL_3D_INTERNAL,
+ String filter=EmptyString, int defaultFilter=0,
+ String name=TreeCtrlNameStr) -> bool
+ """
+ return _controls_.GenericDirCtrl_Create(*args, **kwargs)
+
+ def ExpandPath(*args, **kwargs):
+ """ExpandPath(self, String path) -> bool"""
+ return _controls_.GenericDirCtrl_ExpandPath(*args, **kwargs)
+
+ def CollapsePath(*args, **kwargs):
+ """CollapsePath(self, String path) -> bool"""
+ return _controls_.GenericDirCtrl_CollapsePath(*args, **kwargs)
+
+ def GetDefaultPath(*args, **kwargs):
+ """GetDefaultPath(self) -> String"""
+ return _controls_.GenericDirCtrl_GetDefaultPath(*args, **kwargs)
+
+ def SetDefaultPath(*args, **kwargs):
+ """SetDefaultPath(self, String path)"""
+ return _controls_.GenericDirCtrl_SetDefaultPath(*args, **kwargs)
+
+ def GetPath(*args, **kwargs):
+ """GetPath(self) -> String"""
+ return _controls_.GenericDirCtrl_GetPath(*args, **kwargs)
+
+ def GetPaths(*args, **kwargs):
+ """GetPaths(self) -> wxArrayString"""
+ return _controls_.GenericDirCtrl_GetPaths(*args, **kwargs)
+
+ def GetFilePath(*args, **kwargs):
+ """GetFilePath(self) -> String"""
+ return _controls_.GenericDirCtrl_GetFilePath(*args, **kwargs)
+
+ def SetPath(*args, **kwargs):
+ """SetPath(self, String path)"""
+ return _controls_.GenericDirCtrl_SetPath(*args, **kwargs)
+
+ def GetFilePaths(*args, **kwargs):
+ """GetFilePaths(self) -> wxArrayString"""
+ return _controls_.GenericDirCtrl_GetFilePaths(*args, **kwargs)
+
+ def SelectPath(*args, **kwargs):
+ """SelectPath(self, String path, bool select=True)"""
+ return _controls_.GenericDirCtrl_SelectPath(*args, **kwargs)
+
+ def SelectPaths(*args, **kwargs):
+ """SelectPaths(self, wxArrayString paths)"""
+ return _controls_.GenericDirCtrl_SelectPaths(*args, **kwargs)
+
+ def ShowHidden(*args, **kwargs):
+ """ShowHidden(self, bool show)"""
+ return _controls_.GenericDirCtrl_ShowHidden(*args, **kwargs)
+
+ def GetShowHidden(*args, **kwargs):
+ """GetShowHidden(self) -> bool"""
+ return _controls_.GenericDirCtrl_GetShowHidden(*args, **kwargs)
+
+ def GetFilter(*args, **kwargs):
+ """GetFilter(self) -> String"""
+ return _controls_.GenericDirCtrl_GetFilter(*args, **kwargs)
+
+ def SetFilter(*args, **kwargs):
+ """SetFilter(self, String filter)"""
+ return _controls_.GenericDirCtrl_SetFilter(*args, **kwargs)
+
+ def GetFilterIndex(*args, **kwargs):
+ """GetFilterIndex(self) -> int"""
+ return _controls_.GenericDirCtrl_GetFilterIndex(*args, **kwargs)
+
+ def SetFilterIndex(*args, **kwargs):
+ """SetFilterIndex(self, int n)"""
+ return _controls_.GenericDirCtrl_SetFilterIndex(*args, **kwargs)
+
+ def GetRootId(*args, **kwargs):
+ """GetRootId(self) -> TreeItemId"""
+ return _controls_.GenericDirCtrl_GetRootId(*args, **kwargs)
+
+ def GetTreeCtrl(*args, **kwargs):
+ """GetTreeCtrl(self) -> TreeCtrl"""
+ return _controls_.GenericDirCtrl_GetTreeCtrl(*args, **kwargs)
+
+ def GetFilterListCtrl(*args, **kwargs):
+ """GetFilterListCtrl(self) -> DirFilterListCtrl"""
+ return _controls_.GenericDirCtrl_GetFilterListCtrl(*args, **kwargs)
+
+ def UnselectAll(*args, **kwargs):
+ """UnselectAll(self)"""
+ return _controls_.GenericDirCtrl_UnselectAll(*args, **kwargs)
+
+ def GetDirItemData(*args, **kwargs):
+ """GetDirItemData(self, TreeItemId id) -> DirItemData"""
+ return _controls_.GenericDirCtrl_GetDirItemData(*args, **kwargs)
+
+ def FindChild(*args, **kwargs):
+ """
+ FindChild(wxTreeItemId parentId, wxString path) -> (item, done)
+
+ Find the child that matches the first part of 'path'. E.g. if a child
+ path is "/usr" and 'path' is "/usr/include" then the child for
+ /usr is returned. If the path string has been used (we're at the
+ leaf), done is set to True.
+
+ """
+ return _controls_.GenericDirCtrl_FindChild(*args, **kwargs)
+
+ def DoResize(*args, **kwargs):
+ """DoResize(self)"""
+ return _controls_.GenericDirCtrl_DoResize(*args, **kwargs)
+
+ def ReCreateTree(*args, **kwargs):
+ """ReCreateTree(self)"""
+ return _controls_.GenericDirCtrl_ReCreateTree(*args, **kwargs)
+
+ DefaultPath = property(GetDefaultPath,SetDefaultPath,doc="See `GetDefaultPath` and `SetDefaultPath`")
+ FilePath = property(GetFilePath,doc="See `GetFilePath`")
+ Filter = property(GetFilter,SetFilter,doc="See `GetFilter` and `SetFilter`")
+ FilterIndex = property(GetFilterIndex,SetFilterIndex,doc="See `GetFilterIndex` and `SetFilterIndex`")
+ FilterListCtrl = property(GetFilterListCtrl,doc="See `GetFilterListCtrl`")
+ Path = property(GetPath,SetPath,doc="See `GetPath` and `SetPath`")
+ RootId = property(GetRootId,doc="See `GetRootId`")
+ TreeCtrl = property(GetTreeCtrl,doc="See `GetTreeCtrl`")
+_controls_.GenericDirCtrl_swigregister(GenericDirCtrl)
+
+def PreGenericDirCtrl(*args, **kwargs):
+ """PreGenericDirCtrl() -> GenericDirCtrl"""
+ val = _controls_.new_PreGenericDirCtrl(*args, **kwargs)
+ return val
+
+class DirFilterListCtrl(Choice):
+ """Proxy of C++ DirFilterListCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, GenericDirCtrl parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0) -> DirFilterListCtrl
+ """
+ _controls_.DirFilterListCtrl_swiginit(self,_controls_.new_DirFilterListCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, GenericDirCtrl parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0) -> bool
+ """
+ return _controls_.DirFilterListCtrl_Create(*args, **kwargs)
+
+ def FillFilterList(*args, **kwargs):
+ """FillFilterList(self, String filter, int defaultFilter)"""
+ return _controls_.DirFilterListCtrl_FillFilterList(*args, **kwargs)
+
+_controls_.DirFilterListCtrl_swigregister(DirFilterListCtrl)
+
+def PreDirFilterListCtrl(*args, **kwargs):
+ """PreDirFilterListCtrl() -> DirFilterListCtrl"""
+ val = _controls_.new_PreDirFilterListCtrl(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+class PyControl(_core.Control):
+ """Proxy of C++ PyControl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, Validator validator=DefaultValidator,
+ String name=ControlNameStr) -> PyControl
+ """
+ _controls_.PyControl_swiginit(self,_controls_.new_PyControl(*args, **kwargs))
+ self._setOORInfo(self);PyControl._setCallbackInfo(self, self, PyControl)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _controls_.PyControl__setCallbackInfo(*args, **kwargs)
+
+ SetBestSize = wx.Window.SetInitialSize
+ def DoEraseBackground(*args, **kwargs):
+ """DoEraseBackground(self, DC dc) -> bool"""
+ return _controls_.PyControl_DoEraseBackground(*args, **kwargs)
+
+ def DoMoveWindow(*args, **kwargs):
+ """DoMoveWindow(self, int x, int y, int width, int height)"""
+ return _controls_.PyControl_DoMoveWindow(*args, **kwargs)
+
+ def DoSetSize(*args, **kwargs):
+ """DoSetSize(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO)"""
+ return _controls_.PyControl_DoSetSize(*args, **kwargs)
+
+ def DoSetClientSize(*args, **kwargs):
+ """DoSetClientSize(self, int width, int height)"""
+ return _controls_.PyControl_DoSetClientSize(*args, **kwargs)
+
+ def DoSetVirtualSize(*args, **kwargs):
+ """DoSetVirtualSize(self, int x, int y)"""
+ return _controls_.PyControl_DoSetVirtualSize(*args, **kwargs)
+
+ def DoGetSize(*args, **kwargs):
+ """DoGetSize() -> (width, height)"""
+ return _controls_.PyControl_DoGetSize(*args, **kwargs)
+
+ def DoGetClientSize(*args, **kwargs):
+ """DoGetClientSize() -> (width, height)"""
+ return _controls_.PyControl_DoGetClientSize(*args, **kwargs)
+
+ def DoGetPosition(*args, **kwargs):
+ """DoGetPosition() -> (x,y)"""
+ return _controls_.PyControl_DoGetPosition(*args, **kwargs)
+
+ def DoGetVirtualSize(*args, **kwargs):
+ """DoGetVirtualSize(self) -> Size"""
+ return _controls_.PyControl_DoGetVirtualSize(*args, **kwargs)
+
+ def DoGetBestSize(*args, **kwargs):
+ """DoGetBestSize(self) -> Size"""
+ return _controls_.PyControl_DoGetBestSize(*args, **kwargs)
+
+ def GetDefaultAttributes(*args, **kwargs):
+ """GetDefaultAttributes(self) -> VisualAttributes"""
+ return _controls_.PyControl_GetDefaultAttributes(*args, **kwargs)
+
+ def OnInternalIdle(*args, **kwargs):
+ """OnInternalIdle(self)"""
+ return _controls_.PyControl_OnInternalIdle(*args, **kwargs)
+
+ def base_DoMoveWindow(*args, **kw):
+ return PyControl.DoMoveWindow(*args, **kw)
+ base_DoMoveWindow = wx.deprecated(base_DoMoveWindow,
+ "Please use PyControl.DoMoveWindow instead.")
+
+ def base_DoSetSize(*args, **kw):
+ return PyControl.DoSetSize(*args, **kw)
+ base_DoSetSize = wx.deprecated(base_DoSetSize,
+ "Please use PyControl.DoSetSize instead.")
+
+ def base_DoSetClientSize(*args, **kw):
+ return PyControl.DoSetClientSize(*args, **kw)
+ base_DoSetClientSize = wx.deprecated(base_DoSetClientSize,
+ "Please use PyControl.DoSetClientSize instead.")
+
+ def base_DoSetVirtualSize(*args, **kw):
+ return PyControl.DoSetVirtualSize(*args, **kw)
+ base_DoSetVirtualSize = wx.deprecated(base_DoSetVirtualSize,
+ "Please use PyControl.DoSetVirtualSize instead.")
+
+ def base_DoGetSize(*args, **kw):
+ return PyControl.DoGetSize(*args, **kw)
+ base_DoGetSize = wx.deprecated(base_DoGetSize,
+ "Please use PyControl.DoGetSize instead.")
+
+ def base_DoGetClientSize(*args, **kw):
+ return PyControl.DoGetClientSize(*args, **kw)
+ base_DoGetClientSize = wx.deprecated(base_DoGetClientSize,
+ "Please use PyControl.DoGetClientSize instead.")
+
+ def base_DoGetPosition(*args, **kw):
+ return PyControl.DoGetPosition(*args, **kw)
+ base_DoGetPosition = wx.deprecated(base_DoGetPosition,
+ "Please use PyControl.DoGetPosition instead.")
+
+ def base_DoGetVirtualSize(*args, **kw):
+ return PyControl.DoGetVirtualSize(*args, **kw)
+ base_DoGetVirtualSize = wx.deprecated(base_DoGetVirtualSize,
+ "Please use PyControl.DoGetVirtualSize instead.")
+
+ def base_DoGetBestSize(*args, **kw):
+ return PyControl.DoGetBestSize(*args, **kw)
+ base_DoGetBestSize = wx.deprecated(base_DoGetBestSize,
+ "Please use PyControl.DoGetBestSize instead.")
+
+ def base_InitDialog(*args, **kw):
+ return PyControl.InitDialog(*args, **kw)
+ base_InitDialog = wx.deprecated(base_InitDialog,
+ "Please use PyControl.InitDialog instead.")
+
+ def base_TransferDataToWindow(*args, **kw):
+ return PyControl.TransferDataToWindow(*args, **kw)
+ base_TransferDataToWindow = wx.deprecated(base_TransferDataToWindow,
+ "Please use PyControl.TransferDataToWindow instead.")
+
+ def base_TransferDataFromWindow(*args, **kw):
+ return PyControl.TransferDataFromWindow(*args, **kw)
+ base_TransferDataFromWindow = wx.deprecated(base_TransferDataFromWindow,
+ "Please use PyControl.TransferDataFromWindow instead.")
+
+ def base_Validate(*args, **kw):
+ return PyControl.Validate(*args, **kw)
+ base_Validate = wx.deprecated(base_Validate,
+ "Please use PyControl.Validate instead.")
+
+ def base_AcceptsFocus(*args, **kw):
+ return PyControl.AcceptsFocus(*args, **kw)
+ base_AcceptsFocus = wx.deprecated(base_AcceptsFocus,
+ "Please use PyControl.AcceptsFocus instead.")
+
+ def base_AcceptsFocusFromKeyboard(*args, **kw):
+ return PyControl.AcceptsFocusFromKeyboard(*args, **kw)
+ base_AcceptsFocusFromKeyboard = wx.deprecated(base_AcceptsFocusFromKeyboard,
+ "Please use PyControl.AcceptsFocusFromKeyboard instead.")
+
+ def base_GetMaxSize(*args, **kw):
+ return PyControl.GetMaxSize(*args, **kw)
+ base_GetMaxSize = wx.deprecated(base_GetMaxSize,
+ "Please use PyControl.GetMaxSize instead.")
+
+ def base_Enable(*args, **kw):
+ return PyControl.Enable(*args, **kw)
+ base_Enable = wx.deprecated(base_Enable,
+ "Please use PyControl.Enable instead.")
+
+ def base_AddChild(*args, **kw):
+ return PyControl.AddChild(*args, **kw)
+ base_AddChild = wx.deprecated(base_AddChild,
+ "Please use PyControl.AddChild instead.")
+
+ def base_RemoveChild(*args, **kw):
+ return PyControl.RemoveChild(*args, **kw)
+ base_RemoveChild = wx.deprecated(base_RemoveChild,
+ "Please use PyControl.RemoveChild instead.")
+
+ def base_ShouldInheritColours(*args, **kw):
+ return PyControl.ShouldInheritColours(*args, **kw)
+ base_ShouldInheritColours = wx.deprecated(base_ShouldInheritColours,
+ "Please use PyControl.ShouldInheritColours instead.")
+
+ def base_GetDefaultAttributes(*args, **kw):
+ return PyControl.GetDefaultAttributes(*args, **kw)
+ base_GetDefaultAttributes = wx.deprecated(base_GetDefaultAttributes,
+ "Please use PyControl.GetDefaultAttributes instead.")
+
+ def base_OnInternalIdle(*args, **kw):
+ return PyControl.OnInternalIdle(*args, **kw)
+ base_OnInternalIdle = wx.deprecated(base_OnInternalIdle,
+ "Please use PyControl.OnInternalIdle instead.")
+
+_controls_.PyControl_swigregister(PyControl)
+
+def PrePyControl(*args, **kwargs):
+ """PrePyControl() -> PyControl"""
+ val = _controls_.new_PrePyControl(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+wxEVT_HELP = _controls_.wxEVT_HELP
+wxEVT_DETAILED_HELP = _controls_.wxEVT_DETAILED_HELP
+EVT_HELP = wx.PyEventBinder( wxEVT_HELP, 1)
+EVT_HELP_RANGE = wx.PyEventBinder( wxEVT_HELP, 2)
+EVT_DETAILED_HELP = wx.PyEventBinder( wxEVT_DETAILED_HELP, 1)
+EVT_DETAILED_HELP_RANGE = wx.PyEventBinder( wxEVT_DETAILED_HELP, 2)
+
+class HelpEvent(_core.CommandEvent):
+ """
+ A help event is sent when the user has requested context-sensitive
+ help. This can either be caused by the application requesting
+ context-sensitive help mode via wx.ContextHelp, or (on MS Windows) by
+ the system generating a WM_HELP message when the user pressed F1 or
+ clicked on the query button in a dialog caption.
+
+ A help event is sent to the window that the user clicked on, and is
+ propagated up the window hierarchy until the event is processed or
+ there are no more event handlers. The application should call
+ event.GetId to check the identity of the clicked-on window, and then
+ either show some suitable help or call event.Skip if the identifier is
+ unrecognised. Calling Skip is important because it allows wxWindows to
+ generate further events for ancestors of the clicked-on
+ window. Otherwise it would be impossible to show help for container
+ windows, since processing would stop after the first window found.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ Origin_Unknown = _controls_.HelpEvent_Origin_Unknown
+ Origin_Keyboard = _controls_.HelpEvent_Origin_Keyboard
+ Origin_HelpButton = _controls_.HelpEvent_Origin_HelpButton
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType type=wxEVT_NULL, int winid=0, Point pt=DefaultPosition,
+ int origin=Origin_Unknown) -> HelpEvent
+ """
+ _controls_.HelpEvent_swiginit(self,_controls_.new_HelpEvent(*args, **kwargs))
+ def GetPosition(*args, **kwargs):
+ """
+ GetPosition(self) -> Point
+
+ Returns the left-click position of the mouse, in screen
+ coordinates. This allows the application to position the help
+ appropriately.
+ """
+ return _controls_.HelpEvent_GetPosition(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """
+ SetPosition(self, Point pos)
+
+ Sets the left-click position of the mouse, in screen coordinates.
+ """
+ return _controls_.HelpEvent_SetPosition(*args, **kwargs)
+
+ def GetLink(*args, **kwargs):
+ """
+ GetLink(self) -> String
+
+ Get an optional link to further help
+ """
+ return _controls_.HelpEvent_GetLink(*args, **kwargs)
+
+ def SetLink(*args, **kwargs):
+ """
+ SetLink(self, String link)
+
+ Set an optional link to further help
+ """
+ return _controls_.HelpEvent_SetLink(*args, **kwargs)
+
+ def GetTarget(*args, **kwargs):
+ """
+ GetTarget(self) -> String
+
+ Get an optional target to display help in. E.g. a window specification
+ """
+ return _controls_.HelpEvent_GetTarget(*args, **kwargs)
+
+ def SetTarget(*args, **kwargs):
+ """
+ SetTarget(self, String target)
+
+ Set an optional target to display help in. E.g. a window specification
+ """
+ return _controls_.HelpEvent_SetTarget(*args, **kwargs)
+
+ def GetOrigin(*args, **kwargs):
+ """
+ GetOrigin(self) -> int
+
+ Optiononal indication of the source of the event.
+ """
+ return _controls_.HelpEvent_GetOrigin(*args, **kwargs)
+
+ def SetOrigin(*args, **kwargs):
+ """SetOrigin(self, int origin)"""
+ return _controls_.HelpEvent_SetOrigin(*args, **kwargs)
+
+ Link = property(GetLink,SetLink,doc="See `GetLink` and `SetLink`")
+ Origin = property(GetOrigin,SetOrigin,doc="See `GetOrigin` and `SetOrigin`")
+ Position = property(GetPosition,SetPosition,doc="See `GetPosition` and `SetPosition`")
+ Target = property(GetTarget,SetTarget,doc="See `GetTarget` and `SetTarget`")
+_controls_.HelpEvent_swigregister(HelpEvent)
+
+class ContextHelp(_core.Object):
+ """
+ This class changes the cursor to a query and puts the application into
+ a 'context-sensitive help mode'. When the user left-clicks on a window
+ within the specified window, a ``EVT_HELP`` event is sent to that
+ control, and the application may respond to it by popping up some
+ help.
+
+ There are a couple of ways to invoke this behaviour implicitly:
+
+ * Use the wx.WS_EX_CONTEXTHELP extended style for a dialog or frame
+ (Windows only). This will put a question mark in the titlebar,
+ and Windows will put the application into context-sensitive help
+ mode automatically, with further programming.
+
+ * Create a `wx.ContextHelpButton`, whose predefined behaviour is
+ to create a context help object. Normally you will write your
+ application so that this button is only added to a dialog for
+ non-Windows platforms (use ``wx.WS_EX_CONTEXTHELP`` on
+ Windows).
+
+ :see: `wx.ContextHelpButton`
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window window=None, bool doNow=True) -> ContextHelp
+
+ Constructs a context help object, calling BeginContextHelp if doNow is
+ true (the default).
+
+ If window is None, the top window is used.
+ """
+ _controls_.ContextHelp_swiginit(self,_controls_.new_ContextHelp(*args, **kwargs))
+ __swig_destroy__ = _controls_.delete_ContextHelp
+ __del__ = lambda self : None;
+ def BeginContextHelp(*args, **kwargs):
+ """
+ BeginContextHelp(self, Window window=None) -> bool
+
+ Puts the application into context-sensitive help mode. window is the
+ window which will be used to catch events; if NULL, the top window
+ will be used.
+
+ Returns true if the application was successfully put into
+ context-sensitive help mode. This function only returns when the event
+ loop has finished.
+ """
+ return _controls_.ContextHelp_BeginContextHelp(*args, **kwargs)
+
+ def EndContextHelp(*args, **kwargs):
+ """
+ EndContextHelp(self) -> bool
+
+ Ends context-sensitive help mode. Not normally called by the
+ application.
+ """
+ return _controls_.ContextHelp_EndContextHelp(*args, **kwargs)
+
+_controls_.ContextHelp_swigregister(ContextHelp)
+
+class ContextHelpButton(BitmapButton):
+ """
+ Instances of this class may be used to add a question mark button that
+ when pressed, puts the application into context-help mode. It does
+ this by creating a wx.ContextHelp object which itself generates a
+ ``EVT_HELP`` event when the user clicks on a window.
+
+ On Windows, you may add a question-mark icon to a dialog by use of the
+ ``wx.DIALOG_EX_CONTEXTHELP`` extra style, but on other platforms you
+ will have to add a button explicitly, usually next to OK, Cancel or
+ similar buttons.
+
+ :see: `wx.ContextHelp`, `wx.ContextHelpButton`
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_CONTEXT_HELP, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=BU_AUTODRAW) -> ContextHelpButton
+
+ Constructor, creating and showing a context help button.
+ """
+ _controls_.ContextHelpButton_swiginit(self,_controls_.new_ContextHelpButton(*args, **kwargs))
+ self._setOORInfo(self)
+
+_controls_.ContextHelpButton_swigregister(ContextHelpButton)
+
+class HelpProvider(object):
+ """
+ wx.HelpProvider is an abstract class used by a program
+ implementing context-sensitive help to show the help text for the
+ given window.
+
+ The current help provider must be explicitly set by the
+ application using wx.HelpProvider.Set().
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _controls_.delete_HelpProvider
+ __del__ = lambda self : None;
+ def Set(*args, **kwargs):
+ """
+ Set(HelpProvider helpProvider) -> HelpProvider
+
+ Sset the current, application-wide help provider. Returns the previous
+ one. Unlike some other classes, the help provider is not created on
+ demand. This must be explicitly done by the application.
+ """
+ return _controls_.HelpProvider_Set(*args, **kwargs)
+
+ Set = staticmethod(Set)
+ def Get(*args, **kwargs):
+ """
+ Get() -> HelpProvider
+
+ Return the current application-wide help provider.
+ """
+ return _controls_.HelpProvider_Get(*args, **kwargs)
+
+ Get = staticmethod(Get)
+ def GetHelp(*args, **kwargs):
+ """
+ GetHelp(self, Window window) -> String
+
+ Gets the help string for this window. Its interpretation is dependent
+ on the help provider except that empty string always means that no
+ help is associated with the window.
+ """
+ return _controls_.HelpProvider_GetHelp(*args, **kwargs)
+
+ def ShowHelp(*args, **kwargs):
+ """
+ ShowHelp(self, Window window) -> bool
+
+ Shows help for the given window. Uses GetHelp internally if
+ applicable. Returns True if it was done, or False if no help was
+ available for this window.
+ """
+ return _controls_.HelpProvider_ShowHelp(*args, **kwargs)
+
+ def ShowHelpAtPoint(*args, **kwargs):
+ """
+ ShowHelpAtPoint(self, wxWindowBase window, Point pt, int origin) -> bool
+
+ Show help for the given window (uses window.GetHelpAtPoint()
+ internally if applicable), return true if it was done or false if no
+ help available for this window.
+ """
+ return _controls_.HelpProvider_ShowHelpAtPoint(*args, **kwargs)
+
+ def AddHelp(*args, **kwargs):
+ """
+ AddHelp(self, Window window, String text)
+
+ Associates the text with the given window.
+ """
+ return _controls_.HelpProvider_AddHelp(*args, **kwargs)
+
+ def AddHelpById(*args, **kwargs):
+ """
+ AddHelpById(self, int id, String text)
+
+ This version associates the given text with all windows with this
+ id. May be used to set the same help string for all Cancel buttons in
+ the application, for example.
+ """
+ return _controls_.HelpProvider_AddHelpById(*args, **kwargs)
+
+ def RemoveHelp(*args, **kwargs):
+ """
+ RemoveHelp(self, Window window)
+
+ Removes the association between the window pointer and the help
+ text. This is called by the wx.Window destructor. Without this, the
+ table of help strings will fill up and when window pointers are
+ reused, the wrong help string will be found.
+ """
+ return _controls_.HelpProvider_RemoveHelp(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """Destroy(self)"""
+ args[0].this.own(False)
+ return _controls_.HelpProvider_Destroy(*args, **kwargs)
+
+_controls_.HelpProvider_swigregister(HelpProvider)
+
+def HelpProvider_Set(*args, **kwargs):
+ """
+ HelpProvider_Set(HelpProvider helpProvider) -> HelpProvider
+
+ Sset the current, application-wide help provider. Returns the previous
+ one. Unlike some other classes, the help provider is not created on
+ demand. This must be explicitly done by the application.
+ """
+ return _controls_.HelpProvider_Set(*args, **kwargs)
+
+def HelpProvider_Get(*args):
+ """
+ HelpProvider_Get() -> HelpProvider
+
+ Return the current application-wide help provider.
+ """
+ return _controls_.HelpProvider_Get(*args)
+
+class SimpleHelpProvider(HelpProvider):
+ """
+ wx.SimpleHelpProvider is an implementation of `wx.HelpProvider` which
+ supports only plain text help strings, and shows the string associated
+ with the control (if any) in a tooltip.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> SimpleHelpProvider
+
+ wx.SimpleHelpProvider is an implementation of `wx.HelpProvider` which
+ supports only plain text help strings, and shows the string associated
+ with the control (if any) in a tooltip.
+ """
+ _controls_.SimpleHelpProvider_swiginit(self,_controls_.new_SimpleHelpProvider(*args, **kwargs))
+_controls_.SimpleHelpProvider_swigregister(SimpleHelpProvider)
+
+#---------------------------------------------------------------------------
+
+class DragImage(_core.Object):
+ """Proxy of C++ DragImage class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Bitmap image, Cursor cursor=wxNullCursor) -> DragImage"""
+ _controls_.DragImage_swiginit(self,_controls_.new_DragImage(*args, **kwargs))
+ __swig_destroy__ = _controls_.delete_DragImage
+ __del__ = lambda self : None;
+ def SetBackingBitmap(*args, **kwargs):
+ """SetBackingBitmap(self, Bitmap bitmap)"""
+ return _controls_.DragImage_SetBackingBitmap(*args, **kwargs)
+
+ def BeginDrag(*args, **kwargs):
+ """
+ BeginDrag(self, Point hotspot, Window window, bool fullScreen=False,
+ Rect rect=None) -> bool
+ """
+ return _controls_.DragImage_BeginDrag(*args, **kwargs)
+
+ def BeginDragBounded(*args, **kwargs):
+ """BeginDragBounded(self, Point hotspot, Window window, Window boundingWindow) -> bool"""
+ return _controls_.DragImage_BeginDragBounded(*args, **kwargs)
+
+ def EndDrag(*args, **kwargs):
+ """EndDrag(self) -> bool"""
+ return _controls_.DragImage_EndDrag(*args, **kwargs)
+
+ def Move(*args, **kwargs):
+ """Move(self, Point pt) -> bool"""
+ return _controls_.DragImage_Move(*args, **kwargs)
+
+ def Show(*args, **kwargs):
+ """Show(self) -> bool"""
+ return _controls_.DragImage_Show(*args, **kwargs)
+
+ def Hide(*args, **kwargs):
+ """Hide(self) -> bool"""
+ return _controls_.DragImage_Hide(*args, **kwargs)
+
+ def GetImageRect(*args, **kwargs):
+ """GetImageRect(self, Point pos) -> Rect"""
+ return _controls_.DragImage_GetImageRect(*args, **kwargs)
+
+ def DoDrawImage(*args, **kwargs):
+ """DoDrawImage(self, DC dc, Point pos) -> bool"""
+ return _controls_.DragImage_DoDrawImage(*args, **kwargs)
+
+ def UpdateBackingFromWindow(*args, **kwargs):
+ """UpdateBackingFromWindow(self, DC windowDC, MemoryDC destDC, Rect sourceRect, Rect destRect) -> bool"""
+ return _controls_.DragImage_UpdateBackingFromWindow(*args, **kwargs)
+
+ def RedrawImage(*args, **kwargs):
+ """RedrawImage(self, Point oldPos, Point newPos, bool eraseOld, bool drawNew) -> bool"""
+ return _controls_.DragImage_RedrawImage(*args, **kwargs)
+
+ ImageRect = property(GetImageRect,doc="See `GetImageRect`")
+_controls_.DragImage_swigregister(DragImage)
+
+def DragIcon(*args, **kwargs):
+ """DragIcon(Icon image, Cursor cursor=wxNullCursor) -> DragImage"""
+ val = _controls_.new_DragIcon(*args, **kwargs)
+ return val
+
+def DragString(*args, **kwargs):
+ """DragString(String str, Cursor cursor=wxNullCursor) -> DragImage"""
+ val = _controls_.new_DragString(*args, **kwargs)
+ return val
+
+def DragTreeItem(*args, **kwargs):
+ """DragTreeItem(TreeCtrl treeCtrl, TreeItemId id) -> DragImage"""
+ val = _controls_.new_DragTreeItem(*args, **kwargs)
+ return val
+
+def DragListItem(*args, **kwargs):
+ """DragListItem(ListCtrl listCtrl, long id) -> DragImage"""
+ val = _controls_.new_DragListItem(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+DP_DEFAULT = _controls_.DP_DEFAULT
+DP_SPIN = _controls_.DP_SPIN
+DP_DROPDOWN = _controls_.DP_DROPDOWN
+DP_SHOWCENTURY = _controls_.DP_SHOWCENTURY
+DP_ALLOWNONE = _controls_.DP_ALLOWNONE
+class DatePickerCtrlBase(_core.Control):
+ """Proxy of C++ DatePickerCtrlBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def SetValue(*args, **kwargs):
+ """
+ SetValue(self, DateTime dt)
+
+ Changes the current value of the control. The date should be valid and
+ included in the currently selected range, if any.
+
+ Calling this method does not result in a date change event.
+ """
+ return _controls_.DatePickerCtrlBase_SetValue(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """
+ GetValue(self) -> DateTime
+
+ Returns the currently selected date. If there is no selection or the
+ selection is outside of the current range, an invalid `wx.DateTime`
+ object is returned.
+ """
+ return _controls_.DatePickerCtrlBase_GetValue(*args, **kwargs)
+
+ def SetRange(*args, **kwargs):
+ """
+ SetRange(self, DateTime dt1, DateTime dt2)
+
+ Sets the valid range for the date selection. If dt1 is valid, it
+ becomes the earliest date (inclusive) accepted by the control. If dt2
+ is valid, it becomes the latest possible date.
+
+ If the current value of the control is outside of the newly set range
+ bounds, the behaviour is undefined.
+ """
+ return _controls_.DatePickerCtrlBase_SetRange(*args, **kwargs)
+
+ def GetLowerLimit(*args, **kwargs):
+ """
+ GetLowerLimit(self) -> DateTime
+
+ Get the lower limit of the valid range for the date selection, if any.
+ If there is no range or there is no lower limit, then the
+ `wx.DateTime` value returned will be invalid.
+ """
+ return _controls_.DatePickerCtrlBase_GetLowerLimit(*args, **kwargs)
+
+ def GetUpperLimit(*args, **kwargs):
+ """
+ GetUpperLimit(self) -> DateTime
+
+ Get the upper limit of the valid range for the date selection, if any.
+ If there is no range or there is no upper limit, then the
+ `wx.DateTime` value returned will be invalid.
+ """
+ return _controls_.DatePickerCtrlBase_GetUpperLimit(*args, **kwargs)
+
+ LowerLimit = property(GetLowerLimit,doc="See `GetLowerLimit`")
+ UpperLimit = property(GetUpperLimit,doc="See `GetUpperLimit`")
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_controls_.DatePickerCtrlBase_swigregister(DatePickerCtrlBase)
+DatePickerCtrlNameStr = cvar.DatePickerCtrlNameStr
+
+class DatePickerCtrl(DatePickerCtrlBase):
+ """
+ This control allows the user to select a date. Unlike
+ `wx.calendar.CalendarCtrl`, which is a relatively big control,
+ `wx.DatePickerCtrl` is implemented as a small window showing the
+ currently selected date. The control can be edited using the keyboard,
+ and can also display a popup window for more user-friendly date
+ selection, depending on the styles used and the platform.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, DateTime dt=wxDefaultDateTime,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxDP_DEFAULT|wxDP_SHOWCENTURY,
+ Validator validator=DefaultValidator,
+ String name=DatePickerCtrlNameStr) -> DatePickerCtrl
+
+ Create a new DatePickerCtrl.
+ """
+ _controls_.DatePickerCtrl_swiginit(self,_controls_.new_DatePickerCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, DateTime dt=wxDefaultDateTime,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxDP_DEFAULT|wxDP_SHOWCENTURY,
+ Validator validator=DefaultValidator,
+ String name=DatePickerCtrlNameStr) -> bool
+
+ Create the GUI parts of the DatePickerCtrl, for use in 2-phase
+ creation.
+ """
+ return _controls_.DatePickerCtrl_Create(*args, **kwargs)
+
+_controls_.DatePickerCtrl_swigregister(DatePickerCtrl)
+
+def PreDatePickerCtrl(*args, **kwargs):
+ """
+ PreDatePickerCtrl() -> DatePickerCtrl
+
+ Precreate a DatePickerCtrl for use in 2-phase creation.
+ """
+ val = _controls_.new_PreDatePickerCtrl(*args, **kwargs)
+ return val
+
+class GenericDatePickerCtrl(DatePickerCtrlBase):
+ """Proxy of C++ GenericDatePickerCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, DateTime dt=wxDefaultDateTime,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxDP_DEFAULT|wxDP_SHOWCENTURY,
+ Validator validator=DefaultValidator,
+ String name=DatePickerCtrlNameStr) -> GenericDatePickerCtrl
+
+ Create a new GenericDatePickerCtrl.
+ """
+ _controls_.GenericDatePickerCtrl_swiginit(self,_controls_.new_GenericDatePickerCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, DateTime dt=wxDefaultDateTime,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxDP_DEFAULT|wxDP_SHOWCENTURY,
+ Validator validator=DefaultValidator,
+ String name=DatePickerCtrlNameStr) -> bool
+
+ Create the GUI parts of the GenericDatePickerCtrl, for use in 2-phase
+ creation.
+ """
+ return _controls_.GenericDatePickerCtrl_Create(*args, **kwargs)
+
+_controls_.GenericDatePickerCtrl_swigregister(GenericDatePickerCtrl)
+
+def PreGenericDatePickerCtrl(*args, **kwargs):
+ """
+ PreGenericDatePickerCtrl() -> GenericDatePickerCtrl
+
+ Precreate a GenericDatePickerCtrl for use in 2-phase creation.
+ """
+ val = _controls_.new_PreGenericDatePickerCtrl(*args, **kwargs)
+ return val
+
+HL_CONTEXTMENU = _controls_.HL_CONTEXTMENU
+HL_ALIGN_LEFT = _controls_.HL_ALIGN_LEFT
+HL_ALIGN_RIGHT = _controls_.HL_ALIGN_RIGHT
+HL_ALIGN_CENTRE = _controls_.HL_ALIGN_CENTRE
+HL_DEFAULT_STYLE = _controls_.HL_DEFAULT_STYLE
+#---------------------------------------------------------------------------
+
+class HyperlinkCtrl(_core.Control):
+ """
+ A static text control that emulates a hyperlink. The link is displayed
+ in an appropriate text style, derived from the control's normal font.
+ When the mouse rolls over the link, the cursor changes to a hand and
+ the link's color changes to the active color.
+
+ Clicking on the link does not launch a web browser; instead, a
+ wx.HyperlinkEvent is fired. Use the wx.EVT_HYPERLINK to catch link
+ events.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String label=wxEmptyString,
+ String url=wxEmptyString, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=HL_DEFAULT_STYLE,
+ String name=HyperlinkCtrlNameStr) -> HyperlinkCtrl
+
+ A static text control that emulates a hyperlink. The link is displayed
+ in an appropriate text style, derived from the control's normal font.
+ When the mouse rolls over the link, the cursor changes to a hand and
+ the link's color changes to the active color.
+
+ Clicking on the link does not launch a web browser; instead, a
+ wx.HyperlinkEvent is fired. Use the wx.EVT_HYPERLINK to catch link
+ events.
+
+ """
+ _controls_.HyperlinkCtrl_swiginit(self,_controls_.new_HyperlinkCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String label=wxEmptyString,
+ String url=wxEmptyString, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=HL_DEFAULT_STYLE,
+ String name=HyperlinkCtrlNameStr) -> bool
+ """
+ return _controls_.HyperlinkCtrl_Create(*args, **kwargs)
+
+ def GetHoverColour(*args, **kwargs):
+ """GetHoverColour(self) -> Colour"""
+ return _controls_.HyperlinkCtrl_GetHoverColour(*args, **kwargs)
+
+ def SetHoverColour(*args, **kwargs):
+ """SetHoverColour(self, Colour colour)"""
+ return _controls_.HyperlinkCtrl_SetHoverColour(*args, **kwargs)
+
+ def GetNormalColour(*args, **kwargs):
+ """GetNormalColour(self) -> Colour"""
+ return _controls_.HyperlinkCtrl_GetNormalColour(*args, **kwargs)
+
+ def SetNormalColour(*args, **kwargs):
+ """SetNormalColour(self, Colour colour)"""
+ return _controls_.HyperlinkCtrl_SetNormalColour(*args, **kwargs)
+
+ def GetVisitedColour(*args, **kwargs):
+ """GetVisitedColour(self) -> Colour"""
+ return _controls_.HyperlinkCtrl_GetVisitedColour(*args, **kwargs)
+
+ def SetVisitedColour(*args, **kwargs):
+ """SetVisitedColour(self, Colour colour)"""
+ return _controls_.HyperlinkCtrl_SetVisitedColour(*args, **kwargs)
+
+ def GetURL(*args, **kwargs):
+ """GetURL(self) -> String"""
+ return _controls_.HyperlinkCtrl_GetURL(*args, **kwargs)
+
+ def SetURL(*args, **kwargs):
+ """SetURL(self, String url)"""
+ return _controls_.HyperlinkCtrl_SetURL(*args, **kwargs)
+
+ def SetVisited(*args, **kwargs):
+ """SetVisited(self, bool visited=True)"""
+ return _controls_.HyperlinkCtrl_SetVisited(*args, **kwargs)
+
+ def GetVisited(*args, **kwargs):
+ """GetVisited(self) -> bool"""
+ return _controls_.HyperlinkCtrl_GetVisited(*args, **kwargs)
+
+ HoverColour = property(GetHoverColour,SetHoverColour,doc="See `GetHoverColour` and `SetHoverColour`")
+ NormalColour = property(GetNormalColour,SetNormalColour,doc="See `GetNormalColour` and `SetNormalColour`")
+ URL = property(GetURL,SetURL,doc="See `GetURL` and `SetURL`")
+ Visited = property(GetVisited,SetVisited,doc="See `GetVisited` and `SetVisited`")
+ VisitedColour = property(GetVisitedColour,SetVisitedColour,doc="See `GetVisitedColour` and `SetVisitedColour`")
+_controls_.HyperlinkCtrl_swigregister(HyperlinkCtrl)
+HyperlinkCtrlNameStr = cvar.HyperlinkCtrlNameStr
+
+def PreHyperlinkCtrl(*args, **kwargs):
+ """
+ PreHyperlinkCtrl() -> HyperlinkCtrl
+
+ A static text control that emulates a hyperlink. The link is displayed
+ in an appropriate text style, derived from the control's normal font.
+ When the mouse rolls over the link, the cursor changes to a hand and
+ the link's color changes to the active color.
+
+ Clicking on the link does not launch a web browser; instead, a
+ wx.HyperlinkEvent is fired. Use the wx.EVT_HYPERLINK to catch link
+ events.
+
+ """
+ val = _controls_.new_PreHyperlinkCtrl(*args, **kwargs)
+ return val
+
+wxEVT_COMMAND_HYPERLINK = _controls_.wxEVT_COMMAND_HYPERLINK
+class HyperlinkEvent(_core.CommandEvent):
+ """Proxy of C++ HyperlinkEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Object generator, int id, String url) -> HyperlinkEvent"""
+ _controls_.HyperlinkEvent_swiginit(self,_controls_.new_HyperlinkEvent(*args, **kwargs))
+ def GetURL(*args, **kwargs):
+ """GetURL(self) -> String"""
+ return _controls_.HyperlinkEvent_GetURL(*args, **kwargs)
+
+ def SetURL(*args, **kwargs):
+ """SetURL(self, String url)"""
+ return _controls_.HyperlinkEvent_SetURL(*args, **kwargs)
+
+ URL = property(GetURL,SetURL,doc="See `GetURL` and `SetURL`")
+_controls_.HyperlinkEvent_swigregister(HyperlinkEvent)
+
+EVT_HYPERLINK = wx.PyEventBinder( wxEVT_COMMAND_HYPERLINK, 1 )
+
+#---------------------------------------------------------------------------
+
+PB_USE_TEXTCTRL = _controls_.PB_USE_TEXTCTRL
+class PickerBase(_core.Control):
+ """
+ Base abstract class for all pickers which support an auxiliary text
+ control. This class handles all positioning and sizing of the text
+ control like a horizontal `wx.BoxSizer` would do, with the text
+ control on the left of the picker button and the proportion of the
+ picker fixed to value 1.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def CreateBase(*args, **kwargs):
+ """
+ CreateBase(self, Window parent, int id, String text=wxEmptyString, Point pos=DefaultPosition,
+ Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=wxButtonNameStr) -> bool
+ """
+ return _controls_.PickerBase_CreateBase(*args, **kwargs)
+
+ def SetInternalMargin(*args, **kwargs):
+ """
+ SetInternalMargin(self, int newmargin)
+
+ Sets the margin (in pixels) between the picker and the text control.
+ """
+ return _controls_.PickerBase_SetInternalMargin(*args, **kwargs)
+
+ def GetInternalMargin(*args, **kwargs):
+ """
+ GetInternalMargin(self) -> int
+
+ Returns the margin (in pixels) between the picker and the text
+ control.
+ """
+ return _controls_.PickerBase_GetInternalMargin(*args, **kwargs)
+
+ def SetTextCtrlProportion(*args, **kwargs):
+ """
+ SetTextCtrlProportion(self, int prop)
+
+ Sets the proportion between the text control and the picker button.
+ This is used to set relative sizes of the text contorl and the picker.
+ The value passed to this function must be >= 1.
+ """
+ return _controls_.PickerBase_SetTextCtrlProportion(*args, **kwargs)
+
+ def GetTextCtrlProportion(*args, **kwargs):
+ """
+ GetTextCtrlProportion(self) -> int
+
+ Returns the proportion between the text control and the picker.
+ """
+ return _controls_.PickerBase_GetTextCtrlProportion(*args, **kwargs)
+
+ def SetPickerCtrlProportion(*args, **kwargs):
+ """
+ SetPickerCtrlProportion(self, int prop)
+
+ Sets the proportion value of the picker.
+ """
+ return _controls_.PickerBase_SetPickerCtrlProportion(*args, **kwargs)
+
+ def GetPickerCtrlProportion(*args, **kwargs):
+ """
+ GetPickerCtrlProportion(self) -> int
+
+ Gets the proportion value of the picker.
+ """
+ return _controls_.PickerBase_GetPickerCtrlProportion(*args, **kwargs)
+
+ def IsTextCtrlGrowable(*args, **kwargs):
+ """IsTextCtrlGrowable(self) -> bool"""
+ return _controls_.PickerBase_IsTextCtrlGrowable(*args, **kwargs)
+
+ def SetTextCtrlGrowable(*args, **kwargs):
+ """SetTextCtrlGrowable(self, bool grow=True)"""
+ return _controls_.PickerBase_SetTextCtrlGrowable(*args, **kwargs)
+
+ def IsPickerCtrlGrowable(*args, **kwargs):
+ """IsPickerCtrlGrowable(self) -> bool"""
+ return _controls_.PickerBase_IsPickerCtrlGrowable(*args, **kwargs)
+
+ def SetPickerCtrlGrowable(*args, **kwargs):
+ """SetPickerCtrlGrowable(self, bool grow=True)"""
+ return _controls_.PickerBase_SetPickerCtrlGrowable(*args, **kwargs)
+
+ def HasTextCtrl(*args, **kwargs):
+ """
+ HasTextCtrl(self) -> bool
+
+ Returns true if this class has a valid text control (i.e. if the
+ wx.PB_USE_TEXTCTRL style was given when creating this control).
+ """
+ return _controls_.PickerBase_HasTextCtrl(*args, **kwargs)
+
+ def GetTextCtrl(*args, **kwargs):
+ """
+ GetTextCtrl(self) -> TextCtrl
+
+ Returns a pointer to the text control handled by this class or None if
+ the wx.PB_USE_TEXTCTRL style was not specified when this control was
+ created.
+
+ Very important: the contents of the text control could be containing
+ an invalid representation of the entity which can be chosen through
+ the picker (e.g. the user entered an invalid colour syntax because of
+ a typo). Thus you should never parse the content of the textctrl to
+ get the user's input; rather use the derived-class getter
+ (e.g. `wx.ColourPickerCtrl.GetColour`, `wx.FilePickerCtrl.GetPath`,
+ etc).
+ """
+ return _controls_.PickerBase_GetTextCtrl(*args, **kwargs)
+
+ def GetPickerCtrl(*args, **kwargs):
+ """GetPickerCtrl(self) -> Control"""
+ return _controls_.PickerBase_GetPickerCtrl(*args, **kwargs)
+
+ InternalMargin = property(GetInternalMargin,SetInternalMargin,doc="See `GetInternalMargin` and `SetInternalMargin`")
+ PickerCtrl = property(GetPickerCtrl,doc="See `GetPickerCtrl`")
+ PickerCtrlProportion = property(GetPickerCtrlProportion,SetPickerCtrlProportion,doc="See `GetPickerCtrlProportion` and `SetPickerCtrlProportion`")
+ TextCtrl = property(GetTextCtrl,doc="See `GetTextCtrl`")
+ TextCtrlProportion = property(GetTextCtrlProportion,SetTextCtrlProportion,doc="See `GetTextCtrlProportion` and `SetTextCtrlProportion`")
+ TextCtrlGrowable = property(IsTextCtrlGrowable,SetTextCtrlGrowable,doc="See `IsTextCtrlGrowable` and `SetTextCtrlGrowable`")
+ PickerCtrlGrowable = property(IsPickerCtrlGrowable,SetPickerCtrlGrowable,doc="See `IsPickerCtrlGrowable` and `SetPickerCtrlGrowable`")
+_controls_.PickerBase_swigregister(PickerBase)
+
+class PyPickerBase(PickerBase):
+ """Proxy of C++ PyPickerBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String text=wxEmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=wxButtonNameStr) -> PyPickerBase
+ """
+ _controls_.PyPickerBase_swiginit(self,_controls_.new_PyPickerBase(*args, **kwargs))
+ self._setOORInfo(self);PyPickerBase._setCallbackInfo(self, self, PyPickerBase)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _controls_.PyPickerBase__setCallbackInfo(*args, **kwargs)
+
+ def UpdatePickerFromTextCtrl(*args, **kwargs):
+ """UpdatePickerFromTextCtrl(self)"""
+ return _controls_.PyPickerBase_UpdatePickerFromTextCtrl(*args, **kwargs)
+
+ def UpdateTextCtrlFromPicker(*args, **kwargs):
+ """UpdateTextCtrlFromPicker(self)"""
+ return _controls_.PyPickerBase_UpdateTextCtrlFromPicker(*args, **kwargs)
+
+ def GetTextCtrlStyle(*args, **kwargs):
+ """GetTextCtrlStyle(self, long style) -> long"""
+ return _controls_.PyPickerBase_GetTextCtrlStyle(*args, **kwargs)
+
+ def GetPickerStyle(*args, **kwargs):
+ """GetPickerStyle(self, long style) -> long"""
+ return _controls_.PyPickerBase_GetPickerStyle(*args, **kwargs)
+
+ def SetTextCtrl(*args, **kwargs):
+ """SetTextCtrl(self, TextCtrl text)"""
+ return _controls_.PyPickerBase_SetTextCtrl(*args, **kwargs)
+
+ def SetPickerCtrl(*args, **kwargs):
+ """SetPickerCtrl(self, Control picker)"""
+ return _controls_.PyPickerBase_SetPickerCtrl(*args, **kwargs)
+
+ def PostCreation(*args, **kwargs):
+ """PostCreation(self)"""
+ return _controls_.PyPickerBase_PostCreation(*args, **kwargs)
+
+_controls_.PyPickerBase_swigregister(PyPickerBase)
+
+def PrePyPickerBase(*args, **kwargs):
+ """PrePyPickerBase() -> PyPickerBase"""
+ val = _controls_.new_PrePyPickerBase(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+CLRP_SHOW_LABEL = _controls_.CLRP_SHOW_LABEL
+CLRP_USE_TEXTCTRL = _controls_.CLRP_USE_TEXTCTRL
+CLRP_DEFAULT_STYLE = _controls_.CLRP_DEFAULT_STYLE
+class ColourPickerCtrl(PickerBase):
+ """
+ This control allows the user to select a colour. The implementation
+ varies by platform but is usually a button which brings up a
+ `wx.ColourDialog` when clicked.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Colour col=*wxBLACK, Point pos=DefaultPosition,
+ Size size=DefaultSize,
+ long style=CLRP_DEFAULT_STYLE, Validator validator=DefaultValidator,
+ String name=ColourPickerCtrlNameStr) -> ColourPickerCtrl
+
+ This control allows the user to select a colour. The implementation
+ varies by platform but is usually a button which brings up a
+ `wx.ColourDialog` when clicked.
+ """
+ _controls_.ColourPickerCtrl_swiginit(self,_controls_.new_ColourPickerCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id, Colour col=*wxBLACK, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=CLRP_DEFAULT_STYLE,
+ Validator validator=DefaultValidator,
+ String name=ColourPickerCtrlNameStr) -> bool
+ """
+ return _controls_.ColourPickerCtrl_Create(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """
+ GetColour(self) -> Colour
+
+ Returns the currently selected colour.
+ """
+ return _controls_.ColourPickerCtrl_GetColour(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """
+ SetColour(self, Colour col)
+
+ Set the displayed colour.
+ """
+ return _controls_.ColourPickerCtrl_SetColour(*args, **kwargs)
+
+ Colour = property(GetColour,SetColour,doc="See `GetColour` and `SetColour`")
+_controls_.ColourPickerCtrl_swigregister(ColourPickerCtrl)
+ColourPickerCtrlNameStr = cvar.ColourPickerCtrlNameStr
+
+def PreColourPickerCtrl(*args, **kwargs):
+ """
+ PreColourPickerCtrl() -> ColourPickerCtrl
+
+ This control allows the user to select a colour. The implementation
+ varies by platform but is usually a button which brings up a
+ `wx.ColourDialog` when clicked.
+ """
+ val = _controls_.new_PreColourPickerCtrl(*args, **kwargs)
+ return val
+
+wxEVT_COMMAND_COLOURPICKER_CHANGED = _controls_.wxEVT_COMMAND_COLOURPICKER_CHANGED
+EVT_COLOURPICKER_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_COLOURPICKER_CHANGED, 1 )
+
+class ColourPickerEvent(_core.CommandEvent):
+ """Proxy of C++ ColourPickerEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Object generator, int id, Colour col) -> ColourPickerEvent"""
+ _controls_.ColourPickerEvent_swiginit(self,_controls_.new_ColourPickerEvent(*args, **kwargs))
+ def GetColour(*args, **kwargs):
+ """GetColour(self) -> Colour"""
+ return _controls_.ColourPickerEvent_GetColour(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """SetColour(self, Colour c)"""
+ return _controls_.ColourPickerEvent_SetColour(*args, **kwargs)
+
+ Colour = property(GetColour,SetColour,doc="See `GetColour` and `SetColour`")
+_controls_.ColourPickerEvent_swigregister(ColourPickerEvent)
+
+#---------------------------------------------------------------------------
+
+FLP_OPEN = _controls_.FLP_OPEN
+FLP_SAVE = _controls_.FLP_SAVE
+FLP_OVERWRITE_PROMPT = _controls_.FLP_OVERWRITE_PROMPT
+FLP_FILE_MUST_EXIST = _controls_.FLP_FILE_MUST_EXIST
+FLP_CHANGE_DIR = _controls_.FLP_CHANGE_DIR
+FLP_SMALL = _controls_.FLP_SMALL
+DIRP_DIR_MUST_EXIST = _controls_.DIRP_DIR_MUST_EXIST
+DIRP_CHANGE_DIR = _controls_.DIRP_CHANGE_DIR
+DIRP_SMALL = _controls_.DIRP_SMALL
+FLP_USE_TEXTCTRL = _controls_.FLP_USE_TEXTCTRL
+FLP_DEFAULT_STYLE = _controls_.FLP_DEFAULT_STYLE
+DIRP_USE_TEXTCTRL = _controls_.DIRP_USE_TEXTCTRL
+DIRP_DEFAULT_STYLE = _controls_.DIRP_DEFAULT_STYLE
+class FilePickerCtrl(PickerBase):
+ """Proxy of C++ FilePickerCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String path=EmptyString,
+ String message=FileSelectorPromptStr, String wildcard=FileSelectorDefaultWildcardStr,
+ Point pos=DefaultPosition,
+ Size size=DefaultSize,
+ long style=FLP_DEFAULT_STYLE, Validator validator=DefaultValidator,
+ String name=FilePickerCtrlNameStr) -> FilePickerCtrl
+ """
+ _controls_.FilePickerCtrl_swiginit(self,_controls_.new_FilePickerCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String path=EmptyString,
+ String message=FileSelectorPromptStr, String wildcard=FileSelectorDefaultWildcardStr,
+ Point pos=DefaultPosition,
+ Size size=DefaultSize,
+ long style=FLP_DEFAULT_STYLE, Validator validator=DefaultValidator,
+ String name=FilePickerCtrlNameStr) -> bool
+ """
+ return _controls_.FilePickerCtrl_Create(*args, **kwargs)
+
+ def GetPath(*args, **kwargs):
+ """GetPath(self) -> String"""
+ return _controls_.FilePickerCtrl_GetPath(*args, **kwargs)
+
+ def SetPath(*args, **kwargs):
+ """SetPath(self, String str)"""
+ return _controls_.FilePickerCtrl_SetPath(*args, **kwargs)
+
+ def GetTextCtrlValue(*args, **kwargs):
+ """GetTextCtrlValue(self) -> String"""
+ return _controls_.FilePickerCtrl_GetTextCtrlValue(*args, **kwargs)
+
+ def SetInitialDirectory(*args, **kwargs):
+ """SetInitialDirectory(self, String dir)"""
+ return _controls_.FilePickerCtrl_SetInitialDirectory(*args, **kwargs)
+
+ Path = property(GetPath,SetPath,doc="See `GetPath` and `SetPath`")
+ TextCtrlValue = property(GetTextCtrlValue,doc="See `GetTextCtrlValue`")
+_controls_.FilePickerCtrl_swigregister(FilePickerCtrl)
+FilePickerCtrlNameStr = cvar.FilePickerCtrlNameStr
+FileSelectorPromptStr = cvar.FileSelectorPromptStr
+DirPickerCtrlNameStr = cvar.DirPickerCtrlNameStr
+DirSelectorPromptStr = cvar.DirSelectorPromptStr
+FileSelectorDefaultWildcardStr = cvar.FileSelectorDefaultWildcardStr
+
+def PreFilePickerCtrl(*args, **kwargs):
+ """PreFilePickerCtrl() -> FilePickerCtrl"""
+ val = _controls_.new_PreFilePickerCtrl(*args, **kwargs)
+ return val
+
+class DirPickerCtrl(PickerBase):
+ """Proxy of C++ DirPickerCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String path=EmptyString,
+ String message=DirSelectorPromptStr, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=DIRP_DEFAULT_STYLE,
+ Validator validator=DefaultValidator,
+ String name=DirPickerCtrlNameStr) -> DirPickerCtrl
+ """
+ _controls_.DirPickerCtrl_swiginit(self,_controls_.new_DirPickerCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String path=EmptyString,
+ String message=DirSelectorPromptStr, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=DIRP_DEFAULT_STYLE,
+ Validator validator=DefaultValidator,
+ String name=DirPickerCtrlNameStr) -> bool
+ """
+ return _controls_.DirPickerCtrl_Create(*args, **kwargs)
+
+ def GetPath(*args, **kwargs):
+ """GetPath(self) -> String"""
+ return _controls_.DirPickerCtrl_GetPath(*args, **kwargs)
+
+ def SetPath(*args, **kwargs):
+ """SetPath(self, String str)"""
+ return _controls_.DirPickerCtrl_SetPath(*args, **kwargs)
+
+ def GetTextCtrlValue(*args, **kwargs):
+ """GetTextCtrlValue(self) -> String"""
+ return _controls_.DirPickerCtrl_GetTextCtrlValue(*args, **kwargs)
+
+ Path = property(GetPath,SetPath,doc="See `GetPath` and `SetPath`")
+ TextCtrlValue = property(GetTextCtrlValue,doc="See `GetTextCtrlValue`")
+_controls_.DirPickerCtrl_swigregister(DirPickerCtrl)
+
+def PreDirPickerCtrl(*args, **kwargs):
+ """PreDirPickerCtrl() -> DirPickerCtrl"""
+ val = _controls_.new_PreDirPickerCtrl(*args, **kwargs)
+ return val
+
+wxEVT_COMMAND_FILEPICKER_CHANGED = _controls_.wxEVT_COMMAND_FILEPICKER_CHANGED
+wxEVT_COMMAND_DIRPICKER_CHANGED = _controls_.wxEVT_COMMAND_DIRPICKER_CHANGED
+EVT_FILEPICKER_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_FILEPICKER_CHANGED, 1 )
+EVT_DIRPICKER_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_DIRPICKER_CHANGED, 1 )
+
+class FileDirPickerEvent(_core.CommandEvent):
+ """Proxy of C++ FileDirPickerEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType type, Object generator, int id, String path) -> FileDirPickerEvent"""
+ _controls_.FileDirPickerEvent_swiginit(self,_controls_.new_FileDirPickerEvent(*args, **kwargs))
+ def GetPath(*args, **kwargs):
+ """GetPath(self) -> String"""
+ return _controls_.FileDirPickerEvent_GetPath(*args, **kwargs)
+
+ def SetPath(*args, **kwargs):
+ """SetPath(self, String p)"""
+ return _controls_.FileDirPickerEvent_SetPath(*args, **kwargs)
+
+ Path = property(GetPath,SetPath,doc="See `GetPath` and `SetPath`")
+_controls_.FileDirPickerEvent_swigregister(FileDirPickerEvent)
+
+#---------------------------------------------------------------------------
+
+FNTP_FONTDESC_AS_LABEL = _controls_.FNTP_FONTDESC_AS_LABEL
+FNTP_USEFONT_FOR_LABEL = _controls_.FNTP_USEFONT_FOR_LABEL
+FNTP_USE_TEXTCTRL = _controls_.FNTP_USE_TEXTCTRL
+FNTP_DEFAULT_STYLE = _controls_.FNTP_DEFAULT_STYLE
+class FontPickerCtrl(PickerBase):
+ """Proxy of C++ FontPickerCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Font initial=wxNullFont,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=FNTP_DEFAULT_STYLE, Validator validator=DefaultValidator,
+ String name=FontPickerCtrlNameStr) -> FontPickerCtrl
+ """
+ _controls_.FontPickerCtrl_swiginit(self,_controls_.new_FontPickerCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Font initial=wxNullFont,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=FNTP_DEFAULT_STYLE, Validator validator=DefaultValidator,
+ String name=FontPickerCtrlNameStr) -> bool
+ """
+ return _controls_.FontPickerCtrl_Create(*args, **kwargs)
+
+ def GetSelectedFont(*args, **kwargs):
+ """GetSelectedFont(self) -> Font"""
+ return _controls_.FontPickerCtrl_GetSelectedFont(*args, **kwargs)
+
+ def SetSelectedFont(*args, **kwargs):
+ """SetSelectedFont(self, Font f)"""
+ return _controls_.FontPickerCtrl_SetSelectedFont(*args, **kwargs)
+
+ def SetMaxPointSize(*args, **kwargs):
+ """SetMaxPointSize(self, unsigned int max)"""
+ return _controls_.FontPickerCtrl_SetMaxPointSize(*args, **kwargs)
+
+ def GetMaxPointSize(*args, **kwargs):
+ """GetMaxPointSize(self) -> unsigned int"""
+ return _controls_.FontPickerCtrl_GetMaxPointSize(*args, **kwargs)
+
+ MaxPointSize = property(GetMaxPointSize,SetMaxPointSize,doc="See `GetMaxPointSize` and `SetMaxPointSize`")
+ SelectedFont = property(GetSelectedFont,SetSelectedFont,doc="See `GetSelectedFont` and `SetSelectedFont`")
+_controls_.FontPickerCtrl_swigregister(FontPickerCtrl)
+FontPickerCtrlNameStr = cvar.FontPickerCtrlNameStr
+
+def PreFontPickerCtrl(*args, **kwargs):
+ """PreFontPickerCtrl() -> FontPickerCtrl"""
+ val = _controls_.new_PreFontPickerCtrl(*args, **kwargs)
+ return val
+
+wxEVT_COMMAND_FONTPICKER_CHANGED = _controls_.wxEVT_COMMAND_FONTPICKER_CHANGED
+EVT_FONTPICKER_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_FONTPICKER_CHANGED, 1 )
+
+class FontPickerEvent(_core.CommandEvent):
+ """Proxy of C++ FontPickerEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Object generator, int id, Font f) -> FontPickerEvent"""
+ _controls_.FontPickerEvent_swiginit(self,_controls_.new_FontPickerEvent(*args, **kwargs))
+ def GetFont(*args, **kwargs):
+ """GetFont(self) -> Font"""
+ return _controls_.FontPickerEvent_GetFont(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """SetFont(self, Font c)"""
+ return _controls_.FontPickerEvent_SetFont(*args, **kwargs)
+
+ Font = property(GetFont,SetFont,doc="See `GetFont` and `SetFont`")
+_controls_.FontPickerEvent_swigregister(FontPickerEvent)
+
+#---------------------------------------------------------------------------
+
+CP_DEFAULT_STYLE = _controls_.CP_DEFAULT_STYLE
+CP_NO_TLW_RESIZE = _controls_.CP_NO_TLW_RESIZE
+class CollapsiblePane(_core.Control):
+ """
+ A collapsable pane is a container with an embedded button-like
+ control which can be used by the user to collapse or expand the pane's
+ contents.
+
+ Once constructed you should use the `GetPane` function to access the
+ pane and add your controls inside it (i.e. use the window returned
+ from `GetPane` as the parent for the controls which must go in the
+ pane, NOT the wx.CollapsiblePane itself!).
+
+ Note that because of its nature of control which can dynamically (and
+ drastically) change its size at run-time under user-input, when
+ putting a wx.CollapsiblePane inside a `wx.Sizer` you should be careful
+ to add it with a proportion value of zero; this is because otherwise
+ all other windows with non-zero proportion values would automatically
+ get resized each time the user expands or collapses the pane window,
+ usually resulting a weird, flickering effect.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int winid=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=CP_DEFAULT_STYLE, Validator val=DefaultValidator,
+ String name=CollapsiblePaneNameStr) -> CollapsiblePane
+
+ Create and show a wx.CollapsiblePane
+ """
+ _controls_.CollapsiblePane_swiginit(self,_controls_.new_CollapsiblePane(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int winid=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=CP_DEFAULT_STYLE, Validator val=DefaultValidator,
+ String name=CollapsiblePaneNameStr) -> bool
+ """
+ return _controls_.CollapsiblePane_Create(*args, **kwargs)
+
+ def Collapse(*args, **kwargs):
+ """
+ Collapse(self, bool collapse=True)
+
+ Collapses or expands the pane window.
+ """
+ return _controls_.CollapsiblePane_Collapse(*args, **kwargs)
+
+ def Expand(*args, **kwargs):
+ """
+ Expand(self)
+
+ Same as Collapse(False).
+ """
+ return _controls_.CollapsiblePane_Expand(*args, **kwargs)
+
+ def IsCollapsed(*args, **kwargs):
+ """
+ IsCollapsed(self) -> bool
+
+ Returns ``True`` if the pane window is currently hidden.
+ """
+ return _controls_.CollapsiblePane_IsCollapsed(*args, **kwargs)
+
+ def IsExpanded(*args, **kwargs):
+ """
+ IsExpanded(self) -> bool
+
+ Returns ``True`` if the pane window is currently shown.
+ """
+ return _controls_.CollapsiblePane_IsExpanded(*args, **kwargs)
+
+ def GetPane(*args, **kwargs):
+ """
+ GetPane(self) -> Window
+
+ Returns a reference to the pane window. Use the returned `wx.Window`
+ as the parent of widgets to make them part of the collapsible area.
+ """
+ return _controls_.CollapsiblePane_GetPane(*args, **kwargs)
+
+ Expanded = property(IsExpanded)
+ Collapsed = property(IsCollapsed)
+_controls_.CollapsiblePane_swigregister(CollapsiblePane)
+CollapsiblePaneNameStr = cvar.CollapsiblePaneNameStr
+
+def PreCollapsiblePane(*args, **kwargs):
+ """
+ PreCollapsiblePane() -> CollapsiblePane
+
+ Precreate a wx.CollapsiblePane for 2-phase creation.
+ """
+ val = _controls_.new_PreCollapsiblePane(*args, **kwargs)
+ return val
+
+wxEVT_COMMAND_COLLPANE_CHANGED = _controls_.wxEVT_COMMAND_COLLPANE_CHANGED
+EVT_COLLAPSIBLEPANE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_COLLPANE_CHANGED, 1 )
+
+class CollapsiblePaneEvent(_core.CommandEvent):
+ """Proxy of C++ CollapsiblePaneEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Object generator, int id, bool collapsed) -> CollapsiblePaneEvent"""
+ _controls_.CollapsiblePaneEvent_swiginit(self,_controls_.new_CollapsiblePaneEvent(*args, **kwargs))
+ def GetCollapsed(*args, **kwargs):
+ """GetCollapsed(self) -> bool"""
+ return _controls_.CollapsiblePaneEvent_GetCollapsed(*args, **kwargs)
+
+ def SetCollapsed(*args, **kwargs):
+ """SetCollapsed(self, bool c)"""
+ return _controls_.CollapsiblePaneEvent_SetCollapsed(*args, **kwargs)
+
+ Collapsed = property(GetCollapsed,SetCollapsed)
+_controls_.CollapsiblePaneEvent_swigregister(CollapsiblePaneEvent)
+
+#---------------------------------------------------------------------------
+
+class SearchCtrlBase(_core.Control,_core.TextCtrlIface):
+ """Proxy of C++ SearchCtrlBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+_controls_.SearchCtrlBase_swigregister(SearchCtrlBase)
+SearchCtrlNameStr = cvar.SearchCtrlNameStr
+
+class SearchCtrl(SearchCtrlBase):
+ """
+ A search control is a composite of a `wx.TextCtrl` with optional
+ bitmap buttons and a drop-down menu. Controls like this can typically
+ be found on a toolbar of applications that support some form of search
+ functionality. On the Mac this control is implemented using the
+ native HISearchField control, on the other platforms a generic control
+ is used, although that may change in the future as more platforms
+ introduce native search widgets.
+
+ If you wish to use a drop-down menu with your wx.SearchCtrl then you
+ will need to manage its content and handle the menu events yourself,
+ but this is an easy thing to do. Simply build the menu, pass it to
+ `SetMenu`, and also bind a handler for a range of EVT_MENU events.
+ This gives you the flexibility to use the drop-down menu however you
+ wish, such as for a history of searches, or as a way to select
+ different kinds of searches. The ToolBar.py sample in the demo shows
+ one way to do this.
+
+ Since the control derives from `wx.TextCtrl` it is convenient to use
+ the styles and events designed for `wx.TextCtrl`. For example you can
+ use the ``wx.TE_PROCESS_ENTER`` style and catch the
+ ``wx.EVT_TEXT_ENTER`` event to know when the user has pressed the
+ Enter key in the control and wishes to start a search.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String value=wxEmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=SearchCtrlNameStr) -> SearchCtrl
+
+ A search control is a composite of a `wx.TextCtrl` with optional
+ bitmap buttons and a drop-down menu. Controls like this can typically
+ be found on a toolbar of applications that support some form of search
+ functionality. On the Mac this control is implemented using the
+ native HISearchField control, on the other platforms a generic control
+ is used, although that may change in the future as more platforms
+ introduce native search widgets.
+
+ If you wish to use a drop-down menu with your wx.SearchCtrl then you
+ will need to manage its content and handle the menu events yourself,
+ but this is an easy thing to do. Simply build the menu, pass it to
+ `SetMenu`, and also bind a handler for a range of EVT_MENU events.
+ This gives you the flexibility to use the drop-down menu however you
+ wish, such as for a history of searches, or as a way to select
+ different kinds of searches. The ToolBar.py sample in the demo shows
+ one way to do this.
+
+ Since the control derives from `wx.TextCtrl` it is convenient to use
+ the styles and events designed for `wx.TextCtrl`. For example you can
+ use the ``wx.TE_PROCESS_ENTER`` style and catch the
+ ``wx.EVT_TEXT_ENTER`` event to know when the user has pressed the
+ Enter key in the control and wishes to start a search.
+
+ """
+ _controls_.SearchCtrl_swiginit(self,_controls_.new_SearchCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String value=wxEmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=SearchCtrlNameStr) -> bool
+ """
+ return _controls_.SearchCtrl_Create(*args, **kwargs)
+
+ def SetMenu(*args, **kwargs):
+ """
+ SetMenu(self, Menu menu)
+
+ Sets the search control's menu object. If there is already a menu
+ associated with the search control it is deleted.
+ """
+ return _controls_.SearchCtrl_SetMenu(*args, **kwargs)
+
+ def GetMenu(*args, **kwargs):
+ """
+ GetMenu(self) -> Menu
+
+ Returns a pointer to the search control's menu object or None if there
+ is no menu attached.
+ """
+ return _controls_.SearchCtrl_GetMenu(*args, **kwargs)
+
+ def ShowSearchButton(*args, **kwargs):
+ """
+ ShowSearchButton(self, bool show)
+
+ Sets the search button visibility value on the search control. If
+ there is a menu attached, the search button will be visible regardless
+ of the search button visibility value. This has no effect in Mac OS X
+ v10.3
+ """
+ return _controls_.SearchCtrl_ShowSearchButton(*args, **kwargs)
+
+ def IsSearchButtonVisible(*args, **kwargs):
+ """
+ IsSearchButtonVisible(self) -> bool
+
+ Returns the search button visibility value. If there is a menu
+ attached, the search button will be visible regardless of the search
+ button visibility value. This always returns false in Mac OS X v10.3
+ """
+ return _controls_.SearchCtrl_IsSearchButtonVisible(*args, **kwargs)
+
+ def ShowCancelButton(*args, **kwargs):
+ """
+ ShowCancelButton(self, bool show)
+
+ Shows or hides the cancel button.
+ """
+ return _controls_.SearchCtrl_ShowCancelButton(*args, **kwargs)
+
+ def IsCancelButtonVisible(*args, **kwargs):
+ """
+ IsCancelButtonVisible(self) -> bool
+
+ Indicates whether the cancel button is visible.
+ """
+ return _controls_.SearchCtrl_IsCancelButtonVisible(*args, **kwargs)
+
+ def SetDescriptiveText(*args, **kwargs):
+ """
+ SetDescriptiveText(self, String text)
+
+ Set the text to be displayed when the user has not yet typed anything
+ in the control.
+ """
+ return _controls_.SearchCtrl_SetDescriptiveText(*args, **kwargs)
+
+ def GetDescriptiveText(*args, **kwargs):
+ """
+ GetDescriptiveText(self) -> String
+
+ Get the text to be displayed when the user has not yet typed anything
+ in the control.
+ """
+ return _controls_.SearchCtrl_GetDescriptiveText(*args, **kwargs)
+
+ def SetSearchBitmap(*args, **kwargs):
+ """
+ SetSearchBitmap(self, Bitmap bitmap)
+
+ Sets the bitmap to use for the search button. This currently does not
+ work on the Mac.
+ """
+ return _controls_.SearchCtrl_SetSearchBitmap(*args, **kwargs)
+
+ def SetSearchMenuBitmap(*args, **kwargs):
+ """
+ SetSearchMenuBitmap(self, Bitmap bitmap)
+
+ Sets the bitmap to use for the search button when there is a drop-down
+ menu associated with the search control. This currently does not work
+ on the Mac.
+ """
+ return _controls_.SearchCtrl_SetSearchMenuBitmap(*args, **kwargs)
+
+ def SetCancelBitmap(*args, **kwargs):
+ """
+ SetCancelBitmap(self, Bitmap bitmap)
+
+ Sets the bitmap to use for the cancel button. This currently does not
+ work on the Mac.
+ """
+ return _controls_.SearchCtrl_SetCancelBitmap(*args, **kwargs)
+
+ Menu = property(GetMenu,SetMenu)
+ SearchButtonVisible = property(IsSearchButtonVisible,ShowSearchButton)
+ CancelButtonVisible = property(IsCancelButtonVisible,ShowCancelButton)
+ DescriptiveText = property(GetDescriptiveText,SetDescriptiveText)
+_controls_.SearchCtrl_swigregister(SearchCtrl)
+
+def PreSearchCtrl(*args, **kwargs):
+ """
+ PreSearchCtrl() -> SearchCtrl
+
+ Precreate a wx.SearchCtrl for 2-phase creation.
+ """
+ val = _controls_.new_PreSearchCtrl(*args, **kwargs)
+ return val
+
+wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN = _controls_.wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN
+wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN = _controls_.wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
+EVT_SEARCHCTRL_CANCEL_BTN = wx.PyEventBinder( wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN, 1)
+EVT_SEARCHCTRL_SEARCH_BTN = wx.PyEventBinder( wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN, 1)
+
+#---------------------------------------------------------------------------
+
+class PyAxBaseWindow(_core.Window):
+ """Proxy of C++ PyAxBaseWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=PanelNameStr) -> PyAxBaseWindow
+ """
+ _controls_.PyAxBaseWindow_swiginit(self,_controls_.new_PyAxBaseWindow(*args, **kwargs))
+ self._setOORInfo(self);PyAxBaseWindow._setCallbackInfo(self, self, PyAxBaseWindow)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _controls_.PyAxBaseWindow__setCallbackInfo(*args, **kwargs)
+
+ def MSWTranslateMessage(*args, **kwargs):
+ """MSWTranslateMessage(self, long msg) -> bool"""
+ return _controls_.PyAxBaseWindow_MSWTranslateMessage(*args, **kwargs)
+
+_controls_.PyAxBaseWindow_swigregister(PyAxBaseWindow)
+
+def PrePyAxBaseWindow(*args, **kwargs):
+ """PrePyAxBaseWindow() -> PyAxBaseWindow"""
+ val = _controls_.new_PrePyAxBaseWindow(*args, **kwargs)
+ return val
+
+
+def PyAxBaseWindow_FromHWND(*args, **kwargs):
+ """PyAxBaseWindow_FromHWND(Window parent, unsigned long _hWnd) -> PyAxBaseWindow"""
+ return _controls_.PyAxBaseWindow_FromHWND(*args, **kwargs)
+#---------------------------------------------------------------------------
+
+FC_OPEN = _controls_.FC_OPEN
+FC_SAVE = _controls_.FC_SAVE
+FC_MULTIPLE = _controls_.FC_MULTIPLE
+FC_NOSHOWHIDDEN = _controls_.FC_NOSHOWHIDDEN
+FC_DEFAULT_STYLE = _controls_.FC_DEFAULT_STYLE
+class FileCtrl(_core.Window):
+ """
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String defaultDirectory=wxEmptyString,
+ String defaultFilename=wxEmptyString,
+ String wildCard=wxFileSelectorDefaultWildcardStr,
+ long style=FC_DEFAULT_STYLE, Point pos=DefaultPosition,
+ Size size=DefaultSize,
+ String name=FileCtrlNameStr) -> FileCtrl
+
+ """
+ _controls_.FileCtrl_swiginit(self,_controls_.new_FileCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String defaultDirectory=wxEmptyString,
+ String defaultFilename=wxEmptyString,
+ String wildCard=wxFileSelectorDefaultWildcardStr,
+ long style=FC_DEFAULT_STYLE, Point pos=DefaultPosition,
+ Size size=DefaultSize,
+ String name=FileCtrlNameStr) -> bool
+ """
+ return _controls_.FileCtrl_Create(*args, **kwargs)
+
+ def SetWildcard(*args, **kwargs):
+ """SetWildcard(self, String wildCard)"""
+ return _controls_.FileCtrl_SetWildcard(*args, **kwargs)
+
+ def SetFilterIndex(*args, **kwargs):
+ """SetFilterIndex(self, int filterindex)"""
+ return _controls_.FileCtrl_SetFilterIndex(*args, **kwargs)
+
+ def SetDirectory(*args, **kwargs):
+ """SetDirectory(self, String dir) -> bool"""
+ return _controls_.FileCtrl_SetDirectory(*args, **kwargs)
+
+ def SetFilename(*args, **kwargs):
+ """SetFilename(self, String name) -> bool"""
+ return _controls_.FileCtrl_SetFilename(*args, **kwargs)
+
+ def SetPath(*args, **kwargs):
+ """SetPath(self, String path) -> bool"""
+ return _controls_.FileCtrl_SetPath(*args, **kwargs)
+
+ def GetFilename(*args, **kwargs):
+ """GetFilename(self) -> String"""
+ return _controls_.FileCtrl_GetFilename(*args, **kwargs)
+
+ def GetDirectory(*args, **kwargs):
+ """GetDirectory(self) -> String"""
+ return _controls_.FileCtrl_GetDirectory(*args, **kwargs)
+
+ def GetWildcard(*args, **kwargs):
+ """GetWildcard(self) -> String"""
+ return _controls_.FileCtrl_GetWildcard(*args, **kwargs)
+
+ def GetPath(*args, **kwargs):
+ """GetPath(self) -> String"""
+ return _controls_.FileCtrl_GetPath(*args, **kwargs)
+
+ def GetFilterIndex(*args, **kwargs):
+ """GetFilterIndex(self) -> int"""
+ return _controls_.FileCtrl_GetFilterIndex(*args, **kwargs)
+
+ def GetPaths(*args, **kwargs):
+ """GetPaths(self) -> wxArrayString"""
+ return _controls_.FileCtrl_GetPaths(*args, **kwargs)
+
+ def GetFilenames(*args, **kwargs):
+ """GetFilenames(self) -> wxArrayString"""
+ return _controls_.FileCtrl_GetFilenames(*args, **kwargs)
+
+ def HasMultipleFileSelection(*args, **kwargs):
+ """HasMultipleFileSelection(self) -> bool"""
+ return _controls_.FileCtrl_HasMultipleFileSelection(*args, **kwargs)
+
+ def ShowHidden(*args, **kwargs):
+ """ShowHidden(self, bool show)"""
+ return _controls_.FileCtrl_ShowHidden(*args, **kwargs)
+
+ Filename = property(GetFilename,SetFilename)
+ Directory = property(GetDirectory,SetDirectory)
+ Wildcard = property(GetWildcard,SetWildcard)
+ Path = property(GetPath,SetPath)
+ FilterIndex = property(GetFilterIndex,SetFilterIndex)
+ Paths = property(GetPaths)
+ Filenames = property(GetFilenames)
+_controls_.FileCtrl_swigregister(FileCtrl)
+FileCtrlNameStr = cvar.FileCtrlNameStr
+
+def PreFileCtrl(*args, **kwargs):
+ """
+ PreFileCtrl() -> FileCtrl
+
+ Precreate a wx.FileCtrl for 2-phase creation.
+ """
+ val = _controls_.new_PreFileCtrl(*args, **kwargs)
+ return val
+
+class FileCtrlEvent(_core.CommandEvent):
+ """Proxy of C++ FileCtrlEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType type, Object evtObject, int id) -> FileCtrlEvent"""
+ _controls_.FileCtrlEvent_swiginit(self,_controls_.new_FileCtrlEvent(*args, **kwargs))
+ def SetFiles(*args, **kwargs):
+ """SetFiles(self, wxArrayString files)"""
+ return _controls_.FileCtrlEvent_SetFiles(*args, **kwargs)
+
+ def SetDirectory(*args, **kwargs):
+ """SetDirectory(self, String directory)"""
+ return _controls_.FileCtrlEvent_SetDirectory(*args, **kwargs)
+
+ def SetFilterIndex(*args, **kwargs):
+ """SetFilterIndex(self, int filterIndex)"""
+ return _controls_.FileCtrlEvent_SetFilterIndex(*args, **kwargs)
+
+ def GetFiles(*args, **kwargs):
+ """GetFiles(self) -> wxArrayString"""
+ return _controls_.FileCtrlEvent_GetFiles(*args, **kwargs)
+
+ def GetDirectory(*args, **kwargs):
+ """GetDirectory(self) -> String"""
+ return _controls_.FileCtrlEvent_GetDirectory(*args, **kwargs)
+
+ def GetFilterIndex(*args, **kwargs):
+ """GetFilterIndex(self) -> int"""
+ return _controls_.FileCtrlEvent_GetFilterIndex(*args, **kwargs)
+
+ def GetFile(*args, **kwargs):
+ """GetFile(self) -> String"""
+ return _controls_.FileCtrlEvent_GetFile(*args, **kwargs)
+
+ Files = property(GetFiles,SetFiles)
+ Directory = property(GetDirectory,SetDirectory)
+ FilterIndex = property(GetFilterIndex,SetFilterIndex)
+_controls_.FileCtrlEvent_swigregister(FileCtrlEvent)
+
+wxEVT_FILECTRL_SELECTIONCHANGED = _controls_.wxEVT_FILECTRL_SELECTIONCHANGED
+wxEVT_FILECTRL_FILEACTIVATED = _controls_.wxEVT_FILECTRL_FILEACTIVATED
+wxEVT_FILECTRL_FOLDERCHANGED = _controls_.wxEVT_FILECTRL_FOLDERCHANGED
+wxEVT_FILECTRL_FILTERCHANGED = _controls_.wxEVT_FILECTRL_FILTERCHANGED
+EVT_FILECTRL_SELECTIONCHANGED = wx.PyEventBinder( wxEVT_FILECTRL_SELECTIONCHANGED, 1)
+EVT_FILECTRL_FILEACTIVATED = wx.PyEventBinder( wxEVT_FILECTRL_FILEACTIVATED, 1)
+EVT_FILECTRL_FOLDERCHANGED = wx.PyEventBinder( wxEVT_FILECTRL_FOLDERCHANGED, 1)
+EVT_FILECTRL_FILTERCHANGED = wx.PyEventBinder( wxEVT_FILECTRL_FILTERCHANGED, 1)
+
+#---------------------------------------------------------------------------
+
+class InfoBar(_core.Control):
+ """
+ An info bar is a transient window shown at top or bottom of its parent
+ window to display non-critical information to the user. It works
+ similarly to message bars in current web browsers.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int winid=ID_ANY) -> InfoBar
+
+ An info bar is a transient window shown at top or bottom of its parent
+ window to display non-critical information to the user. It works
+ similarly to message bars in current web browsers.
+ """
+ _controls_.InfoBar_swiginit(self,_controls_.new_InfoBar(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int winid=ID_ANY) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _controls_.InfoBar_Create(*args, **kwargs)
+
+ def ShowMessage(*args, **kwargs):
+ """ShowMessage(self, String msg, int flags=ICON_INFORMATION)"""
+ return _controls_.InfoBar_ShowMessage(*args, **kwargs)
+
+ def Dismiss(*args, **kwargs):
+ """Dismiss(self)"""
+ return _controls_.InfoBar_Dismiss(*args, **kwargs)
+
+ def AddButton(*args, **kwargs):
+ """AddButton(self, int btnid, String label=wxEmptyString)"""
+ return _controls_.InfoBar_AddButton(*args, **kwargs)
+
+ def RemoveButton(*args, **kwargs):
+ """RemoveButton(self, int btnid)"""
+ return _controls_.InfoBar_RemoveButton(*args, **kwargs)
+
+ def SetShowHideEffects(*args, **kwargs):
+ """SetShowHideEffects(self, int showEffect, int hideEffect)"""
+ return _controls_.InfoBar_SetShowHideEffects(*args, **kwargs)
+
+ def GetShowEffect(*args, **kwargs):
+ """GetShowEffect(self) -> int"""
+ return _controls_.InfoBar_GetShowEffect(*args, **kwargs)
+
+ def GetHideEffect(*args, **kwargs):
+ """GetHideEffect(self) -> int"""
+ return _controls_.InfoBar_GetHideEffect(*args, **kwargs)
+
+ def SetEffectDuration(*args, **kwargs):
+ """SetEffectDuration(self, int duration)"""
+ return _controls_.InfoBar_SetEffectDuration(*args, **kwargs)
+
+ def GetEffectDuration(*args, **kwargs):
+ """GetEffectDuration(self) -> int"""
+ return _controls_.InfoBar_GetEffectDuration(*args, **kwargs)
+
+_controls_.InfoBar_swigregister(InfoBar)
+
+def PreInfoBar(*args, **kwargs):
+ """
+ PreInfoBar() -> InfoBar
+
+ An info bar is a transient window shown at top or bottom of its parent
+ window to display non-critical information to the user. It works
+ similarly to message bars in current web browsers.
+ """
+ val = _controls_.new_PreInfoBar(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+class CommandLinkButton(Button):
+ """Proxy of C++ CommandLinkButton class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String mainLabel=wxEmptyString,
+ String note=wxEmptyString, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0,
+ Validator validator=DefaultValidator,
+ String name=wxButtonNameStr) -> CommandLinkButton
+ """
+ _controls_.CommandLinkButton_swiginit(self,_controls_.new_CommandLinkButton(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String mainLabel=wxEmptyString,
+ String note=wxEmptyString, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0,
+ Validator validator=DefaultValidator,
+ String name=wxButtonNameStr) -> bool
+ """
+ return _controls_.CommandLinkButton_Create(*args, **kwargs)
+
+ def SetMainLabelAndNote(*args, **kwargs):
+ """SetMainLabelAndNote(self, String mainLabel, String note)"""
+ return _controls_.CommandLinkButton_SetMainLabelAndNote(*args, **kwargs)
+
+ def SetMainLabel(*args, **kwargs):
+ """SetMainLabel(self, String mainLabel)"""
+ return _controls_.CommandLinkButton_SetMainLabel(*args, **kwargs)
+
+ def SetNote(*args, **kwargs):
+ """SetNote(self, String note)"""
+ return _controls_.CommandLinkButton_SetNote(*args, **kwargs)
+
+ def GetMainLabel(*args, **kwargs):
+ """GetMainLabel(self) -> String"""
+ return _controls_.CommandLinkButton_GetMainLabel(*args, **kwargs)
+
+ def GetNote(*args, **kwargs):
+ """GetNote(self) -> String"""
+ return _controls_.CommandLinkButton_GetNote(*args, **kwargs)
+
+ MainLabel = property(GetMainLabel,SetMainLabel)
+ Note = property(GetNote,SetNote)
+_controls_.CommandLinkButton_swigregister(CommandLinkButton)
+
+def PreCommandLinkButton(*args, **kwargs):
+ """
+ PreCommandLinkButton() -> CommandLinkButton
+
+ Precreate a Button for 2-phase creation.
+ """
+ val = _controls_.new_PreCommandLinkButton(*args, **kwargs)
+ return val
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_controls_.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_controls_.pyd
new file mode 100644
index 0000000..91d5da1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_controls_.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_core.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/_core.py
new file mode 100644
index 0000000..f435396
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_core.py
@@ -0,0 +1,16933 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+import _core_
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+#//----------------------------------------------------------------------------
+#// These will be reset when the _wxPySetDictionary is called. Dummy
+#// values are set here for tools that do static source analysis.
+Platform = ""
+PlatformInfo = ()
+
+#// Give a reference to the dictionary of this module to the C++ extension
+#// code.
+_core_._wxPySetDictionary(vars())
+
+#// A little trick to make 'wx' be a reference to this module so wx.Names can
+#// be used here.
+import sys as _sys
+wx = _sys.modules[__name__]
+
+
+#----------------------------------------------------------------------------
+
+import warnings
+class wxPyDeprecationWarning(DeprecationWarning):
+ pass
+warnings.simplefilter('default', wxPyDeprecationWarning)
+del warnings
+
+def deprecated(item, msg=''):
+ """
+ Create a delegating wrapper that raises a deprecation warning. Can be
+ used with callable objects (functions, methods, classes) or with
+ properties.
+ """
+ import warnings
+ if isinstance(item, type):
+ # It is a class. Make a subclass that raises a warning.
+ class DeprecatedClassProxy(item):
+ def __init__(*args, **kw):
+ warnings.warn("Using deprecated class %s. %s" % (item.__name__, msg),
+ wxPyDeprecationWarning, stacklevel=2)
+ item.__init__(*args, **kw)
+ DeprecatedClassProxy.__name__ = item.__name__
+ return DeprecatedClassProxy
+
+ elif callable(item):
+ # wrap a new function around the callable
+ def deprecated_func(*args, **kw):
+ warnings.warn("Call to deprecated item. %s" % msg,
+ wxPyDeprecationWarning, stacklevel=2)
+ return item(*args, **kw)
+ deprecated_func.__name__ = item.__name__
+ deprecated_func.__doc__ = item.__doc__
+ if hasattr(item, '__dict__'):
+ deprecated_func.__dict__.update(item.__dict__)
+ return deprecated_func
+
+ elif hasattr(item, '__get__'):
+ # it should be a property if there is a getter
+ class DepGetProp(object):
+ def __init__(self,item, msg):
+ self.item = item
+ self.msg = msg
+ def __get__(self, inst, klass):
+ warnings.warn("Accessing deprecated property. %s" % msg,
+ wxPyDeprecationWarning, stacklevel=2)
+ return self.item.__get__(inst, klass)
+ class DepGetSetProp(DepGetProp):
+ def __set__(self, inst, val):
+ warnings.warn("Accessing deprecated property. %s" % msg,
+ wxPyDeprecationWarning, stacklevel=2)
+ return self.item.__set__(inst, val)
+ class DepGetSetDelProp(DepGetSetProp):
+ def __delete__(self, inst):
+ warnings.warn("Accessing deprecated property. %s" % msg,
+ wxPyDeprecationWarning, stacklevel=2)
+ return self.item.__delete__(inst)
+
+ if hasattr(item, '__set__') and hasattr(item, '__delete__'):
+ return DepGetSetDelProp(item, msg)
+ elif hasattr(item, '__set__'):
+ return DepGetSetProp(item, msg)
+ else:
+ return DepGetProp(item, msg)
+ else:
+ raise TypeError, "unsupported type %s" % type(item)
+
+
+
+#----------------------------------------------------------------------------
+
+DefaultCoord = _core_.DefaultCoord
+NOT_FOUND = _core_.NOT_FOUND
+NO_LEN = _core_.NO_LEN
+VSCROLL = _core_.VSCROLL
+HSCROLL = _core_.HSCROLL
+CAPTION = _core_.CAPTION
+DOUBLE_BORDER = _core_.DOUBLE_BORDER
+SUNKEN_BORDER = _core_.SUNKEN_BORDER
+RAISED_BORDER = _core_.RAISED_BORDER
+BORDER = _core_.BORDER
+SIMPLE_BORDER = _core_.SIMPLE_BORDER
+STATIC_BORDER = _core_.STATIC_BORDER
+TRANSPARENT_WINDOW = _core_.TRANSPARENT_WINDOW
+NO_BORDER = _core_.NO_BORDER
+DEFAULT_CONTROL_BORDER = _core_.DEFAULT_CONTROL_BORDER
+DEFAULT_STATUSBAR_STYLE = _core_.DEFAULT_STATUSBAR_STYLE
+TAB_TRAVERSAL = _core_.TAB_TRAVERSAL
+WANTS_CHARS = _core_.WANTS_CHARS
+POPUP_WINDOW = _core_.POPUP_WINDOW
+CENTER_FRAME = _core_.CENTER_FRAME
+CENTRE_ON_SCREEN = _core_.CENTRE_ON_SCREEN
+CENTER_ON_SCREEN = _core_.CENTER_ON_SCREEN
+CLIP_CHILDREN = _core_.CLIP_CHILDREN
+CLIP_SIBLINGS = _core_.CLIP_SIBLINGS
+WINDOW_STYLE_MASK = _core_.WINDOW_STYLE_MASK
+ALWAYS_SHOW_SB = _core_.ALWAYS_SHOW_SB
+RETAINED = _core_.RETAINED
+BACKINGSTORE = _core_.BACKINGSTORE
+COLOURED = _core_.COLOURED
+FIXED_LENGTH = _core_.FIXED_LENGTH
+LB_NEEDED_SB = _core_.LB_NEEDED_SB
+LB_ALWAYS_SB = _core_.LB_ALWAYS_SB
+LB_SORT = _core_.LB_SORT
+LB_SINGLE = _core_.LB_SINGLE
+LB_MULTIPLE = _core_.LB_MULTIPLE
+LB_EXTENDED = _core_.LB_EXTENDED
+LB_OWNERDRAW = _core_.LB_OWNERDRAW
+LB_HSCROLL = _core_.LB_HSCROLL
+CB_SIMPLE = _core_.CB_SIMPLE
+CB_DROPDOWN = _core_.CB_DROPDOWN
+CB_SORT = _core_.CB_SORT
+CB_READONLY = _core_.CB_READONLY
+RA_HORIZONTAL = _core_.RA_HORIZONTAL
+RA_VERTICAL = _core_.RA_VERTICAL
+RA_SPECIFY_ROWS = _core_.RA_SPECIFY_ROWS
+RA_SPECIFY_COLS = _core_.RA_SPECIFY_COLS
+RB_GROUP = _core_.RB_GROUP
+RB_SINGLE = _core_.RB_SINGLE
+SB_HORIZONTAL = _core_.SB_HORIZONTAL
+SB_VERTICAL = _core_.SB_VERTICAL
+TOOL_TOP = _core_.TOOL_TOP
+TOOL_BOTTOM = _core_.TOOL_BOTTOM
+TOOL_LEFT = _core_.TOOL_LEFT
+TOOL_RIGHT = _core_.TOOL_RIGHT
+OK = _core_.OK
+YES_NO = _core_.YES_NO
+CANCEL = _core_.CANCEL
+YES = _core_.YES
+NO = _core_.NO
+NO_DEFAULT = _core_.NO_DEFAULT
+YES_DEFAULT = _core_.YES_DEFAULT
+OK_DEFAULT = _core_.OK_DEFAULT
+CANCEL_DEFAULT = _core_.CANCEL_DEFAULT
+APPLY = _core_.APPLY
+CLOSE = _core_.CLOSE
+ICON_EXCLAMATION = _core_.ICON_EXCLAMATION
+ICON_HAND = _core_.ICON_HAND
+ICON_QUESTION = _core_.ICON_QUESTION
+ICON_INFORMATION = _core_.ICON_INFORMATION
+ICON_STOP = _core_.ICON_STOP
+ICON_ASTERISK = _core_.ICON_ASTERISK
+ICON_MASK = _core_.ICON_MASK
+ICON_WARNING = _core_.ICON_WARNING
+ICON_ERROR = _core_.ICON_ERROR
+ICON_NONE = _core_.ICON_NONE
+FORWARD = _core_.FORWARD
+BACKWARD = _core_.BACKWARD
+RESET = _core_.RESET
+HELP = _core_.HELP
+MORE = _core_.MORE
+SETUP = _core_.SETUP
+SIZE_AUTO_WIDTH = _core_.SIZE_AUTO_WIDTH
+SIZE_AUTO_HEIGHT = _core_.SIZE_AUTO_HEIGHT
+SIZE_AUTO = _core_.SIZE_AUTO
+SIZE_USE_EXISTING = _core_.SIZE_USE_EXISTING
+SIZE_ALLOW_MINUS_ONE = _core_.SIZE_ALLOW_MINUS_ONE
+SIZE_FORCE = _core_.SIZE_FORCE
+SIZE_FORCE_EVENT = _core_.SIZE_FORCE_EVENT
+PRINT_QUALITY_HIGH = _core_.PRINT_QUALITY_HIGH
+PRINT_QUALITY_MEDIUM = _core_.PRINT_QUALITY_MEDIUM
+PRINT_QUALITY_LOW = _core_.PRINT_QUALITY_LOW
+PRINT_QUALITY_DRAFT = _core_.PRINT_QUALITY_DRAFT
+ID_AUTO_LOWEST = _core_.ID_AUTO_LOWEST
+ID_AUTO_HIGHEST = _core_.ID_AUTO_HIGHEST
+ID_ANY = _core_.ID_ANY
+ID_SEPARATOR = _core_.ID_SEPARATOR
+ID_NONE = _core_.ID_NONE
+ID_LOWEST = _core_.ID_LOWEST
+ID_OPEN = _core_.ID_OPEN
+ID_CLOSE = _core_.ID_CLOSE
+ID_NEW = _core_.ID_NEW
+ID_SAVE = _core_.ID_SAVE
+ID_SAVEAS = _core_.ID_SAVEAS
+ID_REVERT = _core_.ID_REVERT
+ID_EXIT = _core_.ID_EXIT
+ID_UNDO = _core_.ID_UNDO
+ID_REDO = _core_.ID_REDO
+ID_HELP = _core_.ID_HELP
+ID_PRINT = _core_.ID_PRINT
+ID_PRINT_SETUP = _core_.ID_PRINT_SETUP
+ID_PAGE_SETUP = _core_.ID_PAGE_SETUP
+ID_PREVIEW = _core_.ID_PREVIEW
+ID_ABOUT = _core_.ID_ABOUT
+ID_HELP_CONTENTS = _core_.ID_HELP_CONTENTS
+ID_HELP_COMMANDS = _core_.ID_HELP_COMMANDS
+ID_HELP_PROCEDURES = _core_.ID_HELP_PROCEDURES
+ID_HELP_CONTEXT = _core_.ID_HELP_CONTEXT
+ID_HELP_INDEX = _core_.ID_HELP_INDEX
+ID_HELP_SEARCH = _core_.ID_HELP_SEARCH
+ID_CLOSE_ALL = _core_.ID_CLOSE_ALL
+ID_PREFERENCES = _core_.ID_PREFERENCES
+ID_EDIT = _core_.ID_EDIT
+ID_CUT = _core_.ID_CUT
+ID_COPY = _core_.ID_COPY
+ID_PASTE = _core_.ID_PASTE
+ID_CLEAR = _core_.ID_CLEAR
+ID_FIND = _core_.ID_FIND
+ID_DUPLICATE = _core_.ID_DUPLICATE
+ID_SELECTALL = _core_.ID_SELECTALL
+ID_DELETE = _core_.ID_DELETE
+ID_REPLACE = _core_.ID_REPLACE
+ID_REPLACE_ALL = _core_.ID_REPLACE_ALL
+ID_PROPERTIES = _core_.ID_PROPERTIES
+ID_VIEW_DETAILS = _core_.ID_VIEW_DETAILS
+ID_VIEW_LARGEICONS = _core_.ID_VIEW_LARGEICONS
+ID_VIEW_SMALLICONS = _core_.ID_VIEW_SMALLICONS
+ID_VIEW_LIST = _core_.ID_VIEW_LIST
+ID_VIEW_SORTDATE = _core_.ID_VIEW_SORTDATE
+ID_VIEW_SORTNAME = _core_.ID_VIEW_SORTNAME
+ID_VIEW_SORTSIZE = _core_.ID_VIEW_SORTSIZE
+ID_VIEW_SORTTYPE = _core_.ID_VIEW_SORTTYPE
+ID_FILE = _core_.ID_FILE
+ID_FILE1 = _core_.ID_FILE1
+ID_FILE2 = _core_.ID_FILE2
+ID_FILE3 = _core_.ID_FILE3
+ID_FILE4 = _core_.ID_FILE4
+ID_FILE5 = _core_.ID_FILE5
+ID_FILE6 = _core_.ID_FILE6
+ID_FILE7 = _core_.ID_FILE7
+ID_FILE8 = _core_.ID_FILE8
+ID_FILE9 = _core_.ID_FILE9
+ID_OK = _core_.ID_OK
+ID_CANCEL = _core_.ID_CANCEL
+ID_APPLY = _core_.ID_APPLY
+ID_YES = _core_.ID_YES
+ID_NO = _core_.ID_NO
+ID_STATIC = _core_.ID_STATIC
+ID_FORWARD = _core_.ID_FORWARD
+ID_BACKWARD = _core_.ID_BACKWARD
+ID_DEFAULT = _core_.ID_DEFAULT
+ID_MORE = _core_.ID_MORE
+ID_SETUP = _core_.ID_SETUP
+ID_RESET = _core_.ID_RESET
+ID_CONTEXT_HELP = _core_.ID_CONTEXT_HELP
+ID_YESTOALL = _core_.ID_YESTOALL
+ID_NOTOALL = _core_.ID_NOTOALL
+ID_ABORT = _core_.ID_ABORT
+ID_RETRY = _core_.ID_RETRY
+ID_IGNORE = _core_.ID_IGNORE
+ID_ADD = _core_.ID_ADD
+ID_REMOVE = _core_.ID_REMOVE
+ID_UP = _core_.ID_UP
+ID_DOWN = _core_.ID_DOWN
+ID_HOME = _core_.ID_HOME
+ID_REFRESH = _core_.ID_REFRESH
+ID_STOP = _core_.ID_STOP
+ID_INDEX = _core_.ID_INDEX
+ID_BOLD = _core_.ID_BOLD
+ID_ITALIC = _core_.ID_ITALIC
+ID_JUSTIFY_CENTER = _core_.ID_JUSTIFY_CENTER
+ID_JUSTIFY_FILL = _core_.ID_JUSTIFY_FILL
+ID_JUSTIFY_RIGHT = _core_.ID_JUSTIFY_RIGHT
+ID_JUSTIFY_LEFT = _core_.ID_JUSTIFY_LEFT
+ID_UNDERLINE = _core_.ID_UNDERLINE
+ID_INDENT = _core_.ID_INDENT
+ID_UNINDENT = _core_.ID_UNINDENT
+ID_ZOOM_100 = _core_.ID_ZOOM_100
+ID_ZOOM_FIT = _core_.ID_ZOOM_FIT
+ID_ZOOM_IN = _core_.ID_ZOOM_IN
+ID_ZOOM_OUT = _core_.ID_ZOOM_OUT
+ID_UNDELETE = _core_.ID_UNDELETE
+ID_REVERT_TO_SAVED = _core_.ID_REVERT_TO_SAVED
+ID_CDROM = _core_.ID_CDROM
+ID_CONVERT = _core_.ID_CONVERT
+ID_EXECUTE = _core_.ID_EXECUTE
+ID_FLOPPY = _core_.ID_FLOPPY
+ID_HARDDISK = _core_.ID_HARDDISK
+ID_BOTTOM = _core_.ID_BOTTOM
+ID_FIRST = _core_.ID_FIRST
+ID_LAST = _core_.ID_LAST
+ID_TOP = _core_.ID_TOP
+ID_INFO = _core_.ID_INFO
+ID_JUMP_TO = _core_.ID_JUMP_TO
+ID_NETWORK = _core_.ID_NETWORK
+ID_SELECT_COLOR = _core_.ID_SELECT_COLOR
+ID_SELECT_FONT = _core_.ID_SELECT_FONT
+ID_SORT_ASCENDING = _core_.ID_SORT_ASCENDING
+ID_SORT_DESCENDING = _core_.ID_SORT_DESCENDING
+ID_SPELL_CHECK = _core_.ID_SPELL_CHECK
+ID_STRIKETHROUGH = _core_.ID_STRIKETHROUGH
+ID_SYSTEM_MENU = _core_.ID_SYSTEM_MENU
+ID_CLOSE_FRAME = _core_.ID_CLOSE_FRAME
+ID_MOVE_FRAME = _core_.ID_MOVE_FRAME
+ID_RESIZE_FRAME = _core_.ID_RESIZE_FRAME
+ID_MAXIMIZE_FRAME = _core_.ID_MAXIMIZE_FRAME
+ID_ICONIZE_FRAME = _core_.ID_ICONIZE_FRAME
+ID_RESTORE_FRAME = _core_.ID_RESTORE_FRAME
+ID_MDI_WINDOW_FIRST = _core_.ID_MDI_WINDOW_FIRST
+ID_MDI_WINDOW_CASCADE = _core_.ID_MDI_WINDOW_CASCADE
+ID_MDI_WINDOW_TILE_HORZ = _core_.ID_MDI_WINDOW_TILE_HORZ
+ID_MDI_WINDOW_TILE_VERT = _core_.ID_MDI_WINDOW_TILE_VERT
+ID_MDI_WINDOW_ARRANGE_ICONS = _core_.ID_MDI_WINDOW_ARRANGE_ICONS
+ID_MDI_WINDOW_PREV = _core_.ID_MDI_WINDOW_PREV
+ID_MDI_WINDOW_NEXT = _core_.ID_MDI_WINDOW_NEXT
+ID_MDI_WINDOW_LAST = _core_.ID_MDI_WINDOW_LAST
+ID_OSX_MENU_FIRST = _core_.ID_OSX_MENU_FIRST
+ID_OSX_HIDE = _core_.ID_OSX_HIDE
+ID_OSX_HIDEOTHERS = _core_.ID_OSX_HIDEOTHERS
+ID_OSX_SHOWALL = _core_.ID_OSX_SHOWALL
+ID_OSX_MENU_LAST = _core_.ID_OSX_MENU_LAST
+ID_FILEDLGG = _core_.ID_FILEDLGG
+ID_FILECTRL = _core_.ID_FILECTRL
+ID_HIGHEST = _core_.ID_HIGHEST
+MENU_TEAROFF = _core_.MENU_TEAROFF
+MB_DOCKABLE = _core_.MB_DOCKABLE
+NO_FULL_REPAINT_ON_RESIZE = _core_.NO_FULL_REPAINT_ON_RESIZE
+FULL_REPAINT_ON_RESIZE = _core_.FULL_REPAINT_ON_RESIZE
+LI_HORIZONTAL = _core_.LI_HORIZONTAL
+LI_VERTICAL = _core_.LI_VERTICAL
+WS_EX_VALIDATE_RECURSIVELY = _core_.WS_EX_VALIDATE_RECURSIVELY
+WS_EX_BLOCK_EVENTS = _core_.WS_EX_BLOCK_EVENTS
+WS_EX_TRANSIENT = _core_.WS_EX_TRANSIENT
+WS_EX_THEMED_BACKGROUND = _core_.WS_EX_THEMED_BACKGROUND
+WS_EX_PROCESS_IDLE = _core_.WS_EX_PROCESS_IDLE
+WS_EX_PROCESS_UI_UPDATES = _core_.WS_EX_PROCESS_UI_UPDATES
+CENTRE = _core_.CENTRE
+CENTER = _core_.CENTER
+HORIZONTAL = _core_.HORIZONTAL
+VERTICAL = _core_.VERTICAL
+BOTH = _core_.BOTH
+ORIENTATION_MASK = _core_.ORIENTATION_MASK
+LEFT = _core_.LEFT
+RIGHT = _core_.RIGHT
+UP = _core_.UP
+DOWN = _core_.DOWN
+TOP = _core_.TOP
+BOTTOM = _core_.BOTTOM
+NORTH = _core_.NORTH
+SOUTH = _core_.SOUTH
+WEST = _core_.WEST
+EAST = _core_.EAST
+ALL = _core_.ALL
+DIRECTION_MASK = _core_.DIRECTION_MASK
+ALIGN_INVALID = _core_.ALIGN_INVALID
+ALIGN_NOT = _core_.ALIGN_NOT
+ALIGN_CENTER_HORIZONTAL = _core_.ALIGN_CENTER_HORIZONTAL
+ALIGN_CENTRE_HORIZONTAL = _core_.ALIGN_CENTRE_HORIZONTAL
+ALIGN_LEFT = _core_.ALIGN_LEFT
+ALIGN_TOP = _core_.ALIGN_TOP
+ALIGN_RIGHT = _core_.ALIGN_RIGHT
+ALIGN_BOTTOM = _core_.ALIGN_BOTTOM
+ALIGN_CENTER_VERTICAL = _core_.ALIGN_CENTER_VERTICAL
+ALIGN_CENTRE_VERTICAL = _core_.ALIGN_CENTRE_VERTICAL
+ALIGN_CENTER = _core_.ALIGN_CENTER
+ALIGN_CENTRE = _core_.ALIGN_CENTRE
+ALIGN_MASK = _core_.ALIGN_MASK
+FIXED_MINSIZE = _core_.FIXED_MINSIZE
+RESERVE_SPACE_EVEN_IF_HIDDEN = _core_.RESERVE_SPACE_EVEN_IF_HIDDEN
+SIZER_FLAG_BITS_MASK = _core_.SIZER_FLAG_BITS_MASK
+ADJUST_MINSIZE = 0
+STRETCH_NOT = _core_.STRETCH_NOT
+SHRINK = _core_.SHRINK
+GROW = _core_.GROW
+EXPAND = _core_.EXPAND
+SHAPED = _core_.SHAPED
+TILE = _core_.TILE
+STRETCH_MASK = _core_.STRETCH_MASK
+BORDER_DEFAULT = _core_.BORDER_DEFAULT
+BORDER_NONE = _core_.BORDER_NONE
+BORDER_STATIC = _core_.BORDER_STATIC
+BORDER_SIMPLE = _core_.BORDER_SIMPLE
+BORDER_RAISED = _core_.BORDER_RAISED
+BORDER_SUNKEN = _core_.BORDER_SUNKEN
+BORDER_DOUBLE = _core_.BORDER_DOUBLE
+BORDER_THEME = _core_.BORDER_THEME
+BORDER_MASK = _core_.BORDER_MASK
+BG_STYLE_ERASE = _core_.BG_STYLE_ERASE
+BG_STYLE_SYSTEM = _core_.BG_STYLE_SYSTEM
+BG_STYLE_PAINT = _core_.BG_STYLE_PAINT
+BG_STYLE_TRANSPARENT = _core_.BG_STYLE_TRANSPARENT
+BG_STYLE_COLOUR = _core_.BG_STYLE_COLOUR
+BG_STYLE_CUSTOM = _core_.BG_STYLE_CUSTOM
+DEFAULT = _core_.DEFAULT
+DECORATIVE = _core_.DECORATIVE
+ROMAN = _core_.ROMAN
+SCRIPT = _core_.SCRIPT
+SWISS = _core_.SWISS
+MODERN = _core_.MODERN
+TELETYPE = _core_.TELETYPE
+VARIABLE = _core_.VARIABLE
+FIXED = _core_.FIXED
+NORMAL = _core_.NORMAL
+LIGHT = _core_.LIGHT
+BOLD = _core_.BOLD
+ITALIC = _core_.ITALIC
+SLANT = _core_.SLANT
+SOLID = _core_.SOLID
+DOT = _core_.DOT
+LONG_DASH = _core_.LONG_DASH
+SHORT_DASH = _core_.SHORT_DASH
+DOT_DASH = _core_.DOT_DASH
+USER_DASH = _core_.USER_DASH
+TRANSPARENT = _core_.TRANSPARENT
+STIPPLE = _core_.STIPPLE
+STIPPLE_MASK = _core_.STIPPLE_MASK
+STIPPLE_MASK_OPAQUE = _core_.STIPPLE_MASK_OPAQUE
+BDIAGONAL_HATCH = _core_.BDIAGONAL_HATCH
+CROSSDIAG_HATCH = _core_.CROSSDIAG_HATCH
+FDIAGONAL_HATCH = _core_.FDIAGONAL_HATCH
+CROSS_HATCH = _core_.CROSS_HATCH
+HORIZONTAL_HATCH = _core_.HORIZONTAL_HATCH
+VERTICAL_HATCH = _core_.VERTICAL_HATCH
+WXK_NONE = _core_.WXK_NONE
+WXK_CONTROL_A = _core_.WXK_CONTROL_A
+WXK_CONTROL_B = _core_.WXK_CONTROL_B
+WXK_CONTROL_C = _core_.WXK_CONTROL_C
+WXK_CONTROL_D = _core_.WXK_CONTROL_D
+WXK_CONTROL_E = _core_.WXK_CONTROL_E
+WXK_CONTROL_F = _core_.WXK_CONTROL_F
+WXK_CONTROL_G = _core_.WXK_CONTROL_G
+WXK_CONTROL_H = _core_.WXK_CONTROL_H
+WXK_CONTROL_I = _core_.WXK_CONTROL_I
+WXK_CONTROL_J = _core_.WXK_CONTROL_J
+WXK_CONTROL_K = _core_.WXK_CONTROL_K
+WXK_CONTROL_L = _core_.WXK_CONTROL_L
+WXK_CONTROL_M = _core_.WXK_CONTROL_M
+WXK_CONTROL_N = _core_.WXK_CONTROL_N
+WXK_CONTROL_O = _core_.WXK_CONTROL_O
+WXK_CONTROL_P = _core_.WXK_CONTROL_P
+WXK_CONTROL_Q = _core_.WXK_CONTROL_Q
+WXK_CONTROL_R = _core_.WXK_CONTROL_R
+WXK_CONTROL_S = _core_.WXK_CONTROL_S
+WXK_CONTROL_T = _core_.WXK_CONTROL_T
+WXK_CONTROL_U = _core_.WXK_CONTROL_U
+WXK_CONTROL_V = _core_.WXK_CONTROL_V
+WXK_CONTROL_W = _core_.WXK_CONTROL_W
+WXK_CONTROL_X = _core_.WXK_CONTROL_X
+WXK_CONTROL_Y = _core_.WXK_CONTROL_Y
+WXK_CONTROL_Z = _core_.WXK_CONTROL_Z
+WXK_BACK = _core_.WXK_BACK
+WXK_TAB = _core_.WXK_TAB
+WXK_RETURN = _core_.WXK_RETURN
+WXK_ESCAPE = _core_.WXK_ESCAPE
+WXK_SPACE = _core_.WXK_SPACE
+WXK_DELETE = _core_.WXK_DELETE
+WXK_START = _core_.WXK_START
+WXK_LBUTTON = _core_.WXK_LBUTTON
+WXK_RBUTTON = _core_.WXK_RBUTTON
+WXK_CANCEL = _core_.WXK_CANCEL
+WXK_MBUTTON = _core_.WXK_MBUTTON
+WXK_CLEAR = _core_.WXK_CLEAR
+WXK_SHIFT = _core_.WXK_SHIFT
+WXK_ALT = _core_.WXK_ALT
+WXK_CONTROL = _core_.WXK_CONTROL
+WXK_MENU = _core_.WXK_MENU
+WXK_PAUSE = _core_.WXK_PAUSE
+WXK_CAPITAL = _core_.WXK_CAPITAL
+WXK_END = _core_.WXK_END
+WXK_HOME = _core_.WXK_HOME
+WXK_LEFT = _core_.WXK_LEFT
+WXK_UP = _core_.WXK_UP
+WXK_RIGHT = _core_.WXK_RIGHT
+WXK_DOWN = _core_.WXK_DOWN
+WXK_SELECT = _core_.WXK_SELECT
+WXK_PRINT = _core_.WXK_PRINT
+WXK_EXECUTE = _core_.WXK_EXECUTE
+WXK_SNAPSHOT = _core_.WXK_SNAPSHOT
+WXK_INSERT = _core_.WXK_INSERT
+WXK_HELP = _core_.WXK_HELP
+WXK_NUMPAD0 = _core_.WXK_NUMPAD0
+WXK_NUMPAD1 = _core_.WXK_NUMPAD1
+WXK_NUMPAD2 = _core_.WXK_NUMPAD2
+WXK_NUMPAD3 = _core_.WXK_NUMPAD3
+WXK_NUMPAD4 = _core_.WXK_NUMPAD4
+WXK_NUMPAD5 = _core_.WXK_NUMPAD5
+WXK_NUMPAD6 = _core_.WXK_NUMPAD6
+WXK_NUMPAD7 = _core_.WXK_NUMPAD7
+WXK_NUMPAD8 = _core_.WXK_NUMPAD8
+WXK_NUMPAD9 = _core_.WXK_NUMPAD9
+WXK_MULTIPLY = _core_.WXK_MULTIPLY
+WXK_ADD = _core_.WXK_ADD
+WXK_SEPARATOR = _core_.WXK_SEPARATOR
+WXK_SUBTRACT = _core_.WXK_SUBTRACT
+WXK_DECIMAL = _core_.WXK_DECIMAL
+WXK_DIVIDE = _core_.WXK_DIVIDE
+WXK_F1 = _core_.WXK_F1
+WXK_F2 = _core_.WXK_F2
+WXK_F3 = _core_.WXK_F3
+WXK_F4 = _core_.WXK_F4
+WXK_F5 = _core_.WXK_F5
+WXK_F6 = _core_.WXK_F6
+WXK_F7 = _core_.WXK_F7
+WXK_F8 = _core_.WXK_F8
+WXK_F9 = _core_.WXK_F9
+WXK_F10 = _core_.WXK_F10
+WXK_F11 = _core_.WXK_F11
+WXK_F12 = _core_.WXK_F12
+WXK_F13 = _core_.WXK_F13
+WXK_F14 = _core_.WXK_F14
+WXK_F15 = _core_.WXK_F15
+WXK_F16 = _core_.WXK_F16
+WXK_F17 = _core_.WXK_F17
+WXK_F18 = _core_.WXK_F18
+WXK_F19 = _core_.WXK_F19
+WXK_F20 = _core_.WXK_F20
+WXK_F21 = _core_.WXK_F21
+WXK_F22 = _core_.WXK_F22
+WXK_F23 = _core_.WXK_F23
+WXK_F24 = _core_.WXK_F24
+WXK_NUMLOCK = _core_.WXK_NUMLOCK
+WXK_SCROLL = _core_.WXK_SCROLL
+WXK_PAGEUP = _core_.WXK_PAGEUP
+WXK_PAGEDOWN = _core_.WXK_PAGEDOWN
+WXK_NUMPAD_SPACE = _core_.WXK_NUMPAD_SPACE
+WXK_NUMPAD_TAB = _core_.WXK_NUMPAD_TAB
+WXK_NUMPAD_ENTER = _core_.WXK_NUMPAD_ENTER
+WXK_NUMPAD_F1 = _core_.WXK_NUMPAD_F1
+WXK_NUMPAD_F2 = _core_.WXK_NUMPAD_F2
+WXK_NUMPAD_F3 = _core_.WXK_NUMPAD_F3
+WXK_NUMPAD_F4 = _core_.WXK_NUMPAD_F4
+WXK_NUMPAD_HOME = _core_.WXK_NUMPAD_HOME
+WXK_NUMPAD_LEFT = _core_.WXK_NUMPAD_LEFT
+WXK_NUMPAD_UP = _core_.WXK_NUMPAD_UP
+WXK_NUMPAD_RIGHT = _core_.WXK_NUMPAD_RIGHT
+WXK_NUMPAD_DOWN = _core_.WXK_NUMPAD_DOWN
+WXK_NUMPAD_PAGEUP = _core_.WXK_NUMPAD_PAGEUP
+WXK_NUMPAD_PAGEDOWN = _core_.WXK_NUMPAD_PAGEDOWN
+WXK_NUMPAD_END = _core_.WXK_NUMPAD_END
+WXK_NUMPAD_BEGIN = _core_.WXK_NUMPAD_BEGIN
+WXK_NUMPAD_INSERT = _core_.WXK_NUMPAD_INSERT
+WXK_NUMPAD_DELETE = _core_.WXK_NUMPAD_DELETE
+WXK_NUMPAD_EQUAL = _core_.WXK_NUMPAD_EQUAL
+WXK_NUMPAD_MULTIPLY = _core_.WXK_NUMPAD_MULTIPLY
+WXK_NUMPAD_ADD = _core_.WXK_NUMPAD_ADD
+WXK_NUMPAD_SEPARATOR = _core_.WXK_NUMPAD_SEPARATOR
+WXK_NUMPAD_SUBTRACT = _core_.WXK_NUMPAD_SUBTRACT
+WXK_NUMPAD_DECIMAL = _core_.WXK_NUMPAD_DECIMAL
+WXK_NUMPAD_DIVIDE = _core_.WXK_NUMPAD_DIVIDE
+WXK_WINDOWS_LEFT = _core_.WXK_WINDOWS_LEFT
+WXK_WINDOWS_RIGHT = _core_.WXK_WINDOWS_RIGHT
+WXK_WINDOWS_MENU = _core_.WXK_WINDOWS_MENU
+WXK_RAW_CONTROL = _core_.WXK_RAW_CONTROL
+WXK_COMMAND = _core_.WXK_COMMAND
+WXK_SPECIAL1 = _core_.WXK_SPECIAL1
+WXK_SPECIAL2 = _core_.WXK_SPECIAL2
+WXK_SPECIAL3 = _core_.WXK_SPECIAL3
+WXK_SPECIAL4 = _core_.WXK_SPECIAL4
+WXK_SPECIAL5 = _core_.WXK_SPECIAL5
+WXK_SPECIAL6 = _core_.WXK_SPECIAL6
+WXK_SPECIAL7 = _core_.WXK_SPECIAL7
+WXK_SPECIAL8 = _core_.WXK_SPECIAL8
+WXK_SPECIAL9 = _core_.WXK_SPECIAL9
+WXK_SPECIAL10 = _core_.WXK_SPECIAL10
+WXK_SPECIAL11 = _core_.WXK_SPECIAL11
+WXK_SPECIAL12 = _core_.WXK_SPECIAL12
+WXK_SPECIAL13 = _core_.WXK_SPECIAL13
+WXK_SPECIAL14 = _core_.WXK_SPECIAL14
+WXK_SPECIAL15 = _core_.WXK_SPECIAL15
+WXK_SPECIAL16 = _core_.WXK_SPECIAL16
+WXK_SPECIAL17 = _core_.WXK_SPECIAL17
+WXK_SPECIAL18 = _core_.WXK_SPECIAL18
+WXK_SPECIAL19 = _core_.WXK_SPECIAL19
+WXK_SPECIAL20 = _core_.WXK_SPECIAL20
+WXK_PRIOR = WXK_PAGEUP
+WXK_NEXT = WXK_PAGEDOWN
+WXK_NUMPAD_PRIOR = WXK_NUMPAD_PAGEUP
+WXK_NUMPAD_NEXT = WXK_NUMPAD_PAGEDOWN
+
+PAPER_NONE = _core_.PAPER_NONE
+PAPER_LETTER = _core_.PAPER_LETTER
+PAPER_LEGAL = _core_.PAPER_LEGAL
+PAPER_A4 = _core_.PAPER_A4
+PAPER_CSHEET = _core_.PAPER_CSHEET
+PAPER_DSHEET = _core_.PAPER_DSHEET
+PAPER_ESHEET = _core_.PAPER_ESHEET
+PAPER_LETTERSMALL = _core_.PAPER_LETTERSMALL
+PAPER_TABLOID = _core_.PAPER_TABLOID
+PAPER_LEDGER = _core_.PAPER_LEDGER
+PAPER_STATEMENT = _core_.PAPER_STATEMENT
+PAPER_EXECUTIVE = _core_.PAPER_EXECUTIVE
+PAPER_A3 = _core_.PAPER_A3
+PAPER_A4SMALL = _core_.PAPER_A4SMALL
+PAPER_A5 = _core_.PAPER_A5
+PAPER_B4 = _core_.PAPER_B4
+PAPER_B5 = _core_.PAPER_B5
+PAPER_FOLIO = _core_.PAPER_FOLIO
+PAPER_QUARTO = _core_.PAPER_QUARTO
+PAPER_10X14 = _core_.PAPER_10X14
+PAPER_11X17 = _core_.PAPER_11X17
+PAPER_NOTE = _core_.PAPER_NOTE
+PAPER_ENV_9 = _core_.PAPER_ENV_9
+PAPER_ENV_10 = _core_.PAPER_ENV_10
+PAPER_ENV_11 = _core_.PAPER_ENV_11
+PAPER_ENV_12 = _core_.PAPER_ENV_12
+PAPER_ENV_14 = _core_.PAPER_ENV_14
+PAPER_ENV_DL = _core_.PAPER_ENV_DL
+PAPER_ENV_C5 = _core_.PAPER_ENV_C5
+PAPER_ENV_C3 = _core_.PAPER_ENV_C3
+PAPER_ENV_C4 = _core_.PAPER_ENV_C4
+PAPER_ENV_C6 = _core_.PAPER_ENV_C6
+PAPER_ENV_C65 = _core_.PAPER_ENV_C65
+PAPER_ENV_B4 = _core_.PAPER_ENV_B4
+PAPER_ENV_B5 = _core_.PAPER_ENV_B5
+PAPER_ENV_B6 = _core_.PAPER_ENV_B6
+PAPER_ENV_ITALY = _core_.PAPER_ENV_ITALY
+PAPER_ENV_MONARCH = _core_.PAPER_ENV_MONARCH
+PAPER_ENV_PERSONAL = _core_.PAPER_ENV_PERSONAL
+PAPER_FANFOLD_US = _core_.PAPER_FANFOLD_US
+PAPER_FANFOLD_STD_GERMAN = _core_.PAPER_FANFOLD_STD_GERMAN
+PAPER_FANFOLD_LGL_GERMAN = _core_.PAPER_FANFOLD_LGL_GERMAN
+PAPER_ISO_B4 = _core_.PAPER_ISO_B4
+PAPER_JAPANESE_POSTCARD = _core_.PAPER_JAPANESE_POSTCARD
+PAPER_9X11 = _core_.PAPER_9X11
+PAPER_10X11 = _core_.PAPER_10X11
+PAPER_15X11 = _core_.PAPER_15X11
+PAPER_ENV_INVITE = _core_.PAPER_ENV_INVITE
+PAPER_LETTER_EXTRA = _core_.PAPER_LETTER_EXTRA
+PAPER_LEGAL_EXTRA = _core_.PAPER_LEGAL_EXTRA
+PAPER_TABLOID_EXTRA = _core_.PAPER_TABLOID_EXTRA
+PAPER_A4_EXTRA = _core_.PAPER_A4_EXTRA
+PAPER_LETTER_TRANSVERSE = _core_.PAPER_LETTER_TRANSVERSE
+PAPER_A4_TRANSVERSE = _core_.PAPER_A4_TRANSVERSE
+PAPER_LETTER_EXTRA_TRANSVERSE = _core_.PAPER_LETTER_EXTRA_TRANSVERSE
+PAPER_A_PLUS = _core_.PAPER_A_PLUS
+PAPER_B_PLUS = _core_.PAPER_B_PLUS
+PAPER_LETTER_PLUS = _core_.PAPER_LETTER_PLUS
+PAPER_A4_PLUS = _core_.PAPER_A4_PLUS
+PAPER_A5_TRANSVERSE = _core_.PAPER_A5_TRANSVERSE
+PAPER_B5_TRANSVERSE = _core_.PAPER_B5_TRANSVERSE
+PAPER_A3_EXTRA = _core_.PAPER_A3_EXTRA
+PAPER_A5_EXTRA = _core_.PAPER_A5_EXTRA
+PAPER_B5_EXTRA = _core_.PAPER_B5_EXTRA
+PAPER_A2 = _core_.PAPER_A2
+PAPER_A3_TRANSVERSE = _core_.PAPER_A3_TRANSVERSE
+PAPER_A3_EXTRA_TRANSVERSE = _core_.PAPER_A3_EXTRA_TRANSVERSE
+PAPER_DBL_JAPANESE_POSTCARD = _core_.PAPER_DBL_JAPANESE_POSTCARD
+PAPER_A6 = _core_.PAPER_A6
+PAPER_JENV_KAKU2 = _core_.PAPER_JENV_KAKU2
+PAPER_JENV_KAKU3 = _core_.PAPER_JENV_KAKU3
+PAPER_JENV_CHOU3 = _core_.PAPER_JENV_CHOU3
+PAPER_JENV_CHOU4 = _core_.PAPER_JENV_CHOU4
+PAPER_LETTER_ROTATED = _core_.PAPER_LETTER_ROTATED
+PAPER_A3_ROTATED = _core_.PAPER_A3_ROTATED
+PAPER_A4_ROTATED = _core_.PAPER_A4_ROTATED
+PAPER_A5_ROTATED = _core_.PAPER_A5_ROTATED
+PAPER_B4_JIS_ROTATED = _core_.PAPER_B4_JIS_ROTATED
+PAPER_B5_JIS_ROTATED = _core_.PAPER_B5_JIS_ROTATED
+PAPER_JAPANESE_POSTCARD_ROTATED = _core_.PAPER_JAPANESE_POSTCARD_ROTATED
+PAPER_DBL_JAPANESE_POSTCARD_ROTATED = _core_.PAPER_DBL_JAPANESE_POSTCARD_ROTATED
+PAPER_A6_ROTATED = _core_.PAPER_A6_ROTATED
+PAPER_JENV_KAKU2_ROTATED = _core_.PAPER_JENV_KAKU2_ROTATED
+PAPER_JENV_KAKU3_ROTATED = _core_.PAPER_JENV_KAKU3_ROTATED
+PAPER_JENV_CHOU3_ROTATED = _core_.PAPER_JENV_CHOU3_ROTATED
+PAPER_JENV_CHOU4_ROTATED = _core_.PAPER_JENV_CHOU4_ROTATED
+PAPER_B6_JIS = _core_.PAPER_B6_JIS
+PAPER_B6_JIS_ROTATED = _core_.PAPER_B6_JIS_ROTATED
+PAPER_12X11 = _core_.PAPER_12X11
+PAPER_JENV_YOU4 = _core_.PAPER_JENV_YOU4
+PAPER_JENV_YOU4_ROTATED = _core_.PAPER_JENV_YOU4_ROTATED
+PAPER_P16K = _core_.PAPER_P16K
+PAPER_P32K = _core_.PAPER_P32K
+PAPER_P32KBIG = _core_.PAPER_P32KBIG
+PAPER_PENV_1 = _core_.PAPER_PENV_1
+PAPER_PENV_2 = _core_.PAPER_PENV_2
+PAPER_PENV_3 = _core_.PAPER_PENV_3
+PAPER_PENV_4 = _core_.PAPER_PENV_4
+PAPER_PENV_5 = _core_.PAPER_PENV_5
+PAPER_PENV_6 = _core_.PAPER_PENV_6
+PAPER_PENV_7 = _core_.PAPER_PENV_7
+PAPER_PENV_8 = _core_.PAPER_PENV_8
+PAPER_PENV_9 = _core_.PAPER_PENV_9
+PAPER_PENV_10 = _core_.PAPER_PENV_10
+PAPER_P16K_ROTATED = _core_.PAPER_P16K_ROTATED
+PAPER_P32K_ROTATED = _core_.PAPER_P32K_ROTATED
+PAPER_P32KBIG_ROTATED = _core_.PAPER_P32KBIG_ROTATED
+PAPER_PENV_1_ROTATED = _core_.PAPER_PENV_1_ROTATED
+PAPER_PENV_2_ROTATED = _core_.PAPER_PENV_2_ROTATED
+PAPER_PENV_3_ROTATED = _core_.PAPER_PENV_3_ROTATED
+PAPER_PENV_4_ROTATED = _core_.PAPER_PENV_4_ROTATED
+PAPER_PENV_5_ROTATED = _core_.PAPER_PENV_5_ROTATED
+PAPER_PENV_6_ROTATED = _core_.PAPER_PENV_6_ROTATED
+PAPER_PENV_7_ROTATED = _core_.PAPER_PENV_7_ROTATED
+PAPER_PENV_8_ROTATED = _core_.PAPER_PENV_8_ROTATED
+PAPER_PENV_9_ROTATED = _core_.PAPER_PENV_9_ROTATED
+PAPER_PENV_10_ROTATED = _core_.PAPER_PENV_10_ROTATED
+PAPER_A0 = _core_.PAPER_A0
+PAPER_A1 = _core_.PAPER_A1
+PORTRAIT = _core_.PORTRAIT
+LANDSCAPE = _core_.LANDSCAPE
+DUPLEX_SIMPLEX = _core_.DUPLEX_SIMPLEX
+DUPLEX_HORIZONTAL = _core_.DUPLEX_HORIZONTAL
+DUPLEX_VERTICAL = _core_.DUPLEX_VERTICAL
+ITEM_SEPARATOR = _core_.ITEM_SEPARATOR
+ITEM_NORMAL = _core_.ITEM_NORMAL
+ITEM_CHECK = _core_.ITEM_CHECK
+ITEM_RADIO = _core_.ITEM_RADIO
+ITEM_DROPDOWN = _core_.ITEM_DROPDOWN
+ITEM_MAX = _core_.ITEM_MAX
+CHK_UNCHECKED = _core_.CHK_UNCHECKED
+CHK_CHECKED = _core_.CHK_CHECKED
+CHK_UNDETERMINED = _core_.CHK_UNDETERMINED
+HT_NOWHERE = _core_.HT_NOWHERE
+HT_SCROLLBAR_FIRST = _core_.HT_SCROLLBAR_FIRST
+HT_SCROLLBAR_ARROW_LINE_1 = _core_.HT_SCROLLBAR_ARROW_LINE_1
+HT_SCROLLBAR_ARROW_LINE_2 = _core_.HT_SCROLLBAR_ARROW_LINE_2
+HT_SCROLLBAR_ARROW_PAGE_1 = _core_.HT_SCROLLBAR_ARROW_PAGE_1
+HT_SCROLLBAR_ARROW_PAGE_2 = _core_.HT_SCROLLBAR_ARROW_PAGE_2
+HT_SCROLLBAR_THUMB = _core_.HT_SCROLLBAR_THUMB
+HT_SCROLLBAR_BAR_1 = _core_.HT_SCROLLBAR_BAR_1
+HT_SCROLLBAR_BAR_2 = _core_.HT_SCROLLBAR_BAR_2
+HT_SCROLLBAR_LAST = _core_.HT_SCROLLBAR_LAST
+HT_WINDOW_OUTSIDE = _core_.HT_WINDOW_OUTSIDE
+HT_WINDOW_INSIDE = _core_.HT_WINDOW_INSIDE
+HT_WINDOW_VERT_SCROLLBAR = _core_.HT_WINDOW_VERT_SCROLLBAR
+HT_WINDOW_HORZ_SCROLLBAR = _core_.HT_WINDOW_HORZ_SCROLLBAR
+HT_WINDOW_CORNER = _core_.HT_WINDOW_CORNER
+HT_MAX = _core_.HT_MAX
+MOD_NONE = _core_.MOD_NONE
+MOD_ALT = _core_.MOD_ALT
+MOD_CONTROL = _core_.MOD_CONTROL
+MOD_ALTGR = _core_.MOD_ALTGR
+MOD_SHIFT = _core_.MOD_SHIFT
+MOD_META = _core_.MOD_META
+MOD_WIN = _core_.MOD_WIN
+MOD_RAW_CONTROL = _core_.MOD_RAW_CONTROL
+MOD_CMD = _core_.MOD_CMD
+MOD_ALL = _core_.MOD_ALL
+UPDATE_UI_NONE = _core_.UPDATE_UI_NONE
+UPDATE_UI_RECURSE = _core_.UPDATE_UI_RECURSE
+UPDATE_UI_FROMIDLE = _core_.UPDATE_UI_FROMIDLE
+Layout_Default = _core_.Layout_Default
+Layout_LeftToRight = _core_.Layout_LeftToRight
+Layout_RightToLeft = _core_.Layout_RightToLeft
+#---------------------------------------------------------------------------
+
+class Object(object):
+ """
+ The base class for most wx objects, although in wxPython not
+ much functionality is needed nor exposed.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetClassName(*args, **kwargs):
+ """
+ GetClassName(self) -> String
+
+ Returns the class name of the C++ class using wxRTTI.
+ """
+ return _core_.Object_GetClassName(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """
+ Destroy(self)
+
+ Deletes the C++ object this Python object is a proxy for.
+ """
+ args[0].this.own(False)
+ return _core_.Object_Destroy(*args, **kwargs)
+
+ def IsSameAs(*args, **kwargs):
+ """
+ IsSameAs(self, Object p) -> bool
+
+ For wx.Objects that use C++ reference counting internally, this method
+ can be used to determine if two objects are referencing the same data
+ object.
+ """
+ return _core_.Object_IsSameAs(*args, **kwargs)
+
+ ClassName = property(GetClassName,doc="See `GetClassName`")
+_core_.Object_swigregister(Object)
+_wxPySetDictionary = _core_._wxPySetDictionary
+cvar = _core_.cvar
+EmptyString = cvar.EmptyString
+
+class RefCounter(object):
+ """Proxy of C++ RefCounter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> RefCounter"""
+ _core_.RefCounter_swiginit(self,_core_.new_RefCounter(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_RefCounter
+ __del__ = lambda self : None;
+ def GetRefCount(*args, **kwargs):
+ """GetRefCount(self) -> int"""
+ return _core_.RefCounter_GetRefCount(*args, **kwargs)
+
+ def IncRef(*args, **kwargs):
+ """IncRef(self)"""
+ return _core_.RefCounter_IncRef(*args, **kwargs)
+
+ def DecRef(*args, **kwargs):
+ """DecRef(self)"""
+ return _core_.RefCounter_DecRef(*args, **kwargs)
+
+_core_.RefCounter_swigregister(RefCounter)
+
+#---------------------------------------------------------------------------
+
+BITMAP_TYPE_INVALID = _core_.BITMAP_TYPE_INVALID
+BITMAP_TYPE_BMP = _core_.BITMAP_TYPE_BMP
+BITMAP_TYPE_ICO = _core_.BITMAP_TYPE_ICO
+BITMAP_TYPE_CUR = _core_.BITMAP_TYPE_CUR
+BITMAP_TYPE_XBM = _core_.BITMAP_TYPE_XBM
+BITMAP_TYPE_XBM_DATA = _core_.BITMAP_TYPE_XBM_DATA
+BITMAP_TYPE_XPM = _core_.BITMAP_TYPE_XPM
+BITMAP_TYPE_XPM_DATA = _core_.BITMAP_TYPE_XPM_DATA
+BITMAP_TYPE_TIF = _core_.BITMAP_TYPE_TIF
+BITMAP_TYPE_TIFF = _core_.BITMAP_TYPE_TIFF
+BITMAP_TYPE_GIF = _core_.BITMAP_TYPE_GIF
+BITMAP_TYPE_PNG = _core_.BITMAP_TYPE_PNG
+BITMAP_TYPE_JPEG = _core_.BITMAP_TYPE_JPEG
+BITMAP_TYPE_PNM = _core_.BITMAP_TYPE_PNM
+BITMAP_TYPE_PCX = _core_.BITMAP_TYPE_PCX
+BITMAP_TYPE_PICT = _core_.BITMAP_TYPE_PICT
+BITMAP_TYPE_ICON = _core_.BITMAP_TYPE_ICON
+BITMAP_TYPE_ANI = _core_.BITMAP_TYPE_ANI
+BITMAP_TYPE_IFF = _core_.BITMAP_TYPE_IFF
+BITMAP_TYPE_TGA = _core_.BITMAP_TYPE_TGA
+BITMAP_TYPE_MACCURSOR = _core_.BITMAP_TYPE_MACCURSOR
+BITMAP_TYPE_MAX = _core_.BITMAP_TYPE_MAX
+BITMAP_TYPE_ANY = _core_.BITMAP_TYPE_ANY
+BITMAP_DEFAULT_TYPE = _core_.BITMAP_DEFAULT_TYPE
+ODDEVEN_RULE = _core_.ODDEVEN_RULE
+WINDING_RULE = _core_.WINDING_RULE
+CURSOR_NONE = _core_.CURSOR_NONE
+CURSOR_ARROW = _core_.CURSOR_ARROW
+CURSOR_RIGHT_ARROW = _core_.CURSOR_RIGHT_ARROW
+CURSOR_BULLSEYE = _core_.CURSOR_BULLSEYE
+CURSOR_CHAR = _core_.CURSOR_CHAR
+CURSOR_CROSS = _core_.CURSOR_CROSS
+CURSOR_HAND = _core_.CURSOR_HAND
+CURSOR_IBEAM = _core_.CURSOR_IBEAM
+CURSOR_LEFT_BUTTON = _core_.CURSOR_LEFT_BUTTON
+CURSOR_MAGNIFIER = _core_.CURSOR_MAGNIFIER
+CURSOR_MIDDLE_BUTTON = _core_.CURSOR_MIDDLE_BUTTON
+CURSOR_NO_ENTRY = _core_.CURSOR_NO_ENTRY
+CURSOR_PAINT_BRUSH = _core_.CURSOR_PAINT_BRUSH
+CURSOR_PENCIL = _core_.CURSOR_PENCIL
+CURSOR_POINT_LEFT = _core_.CURSOR_POINT_LEFT
+CURSOR_POINT_RIGHT = _core_.CURSOR_POINT_RIGHT
+CURSOR_QUESTION_ARROW = _core_.CURSOR_QUESTION_ARROW
+CURSOR_RIGHT_BUTTON = _core_.CURSOR_RIGHT_BUTTON
+CURSOR_SIZENESW = _core_.CURSOR_SIZENESW
+CURSOR_SIZENS = _core_.CURSOR_SIZENS
+CURSOR_SIZENWSE = _core_.CURSOR_SIZENWSE
+CURSOR_SIZEWE = _core_.CURSOR_SIZEWE
+CURSOR_SIZING = _core_.CURSOR_SIZING
+CURSOR_SPRAYCAN = _core_.CURSOR_SPRAYCAN
+CURSOR_WAIT = _core_.CURSOR_WAIT
+CURSOR_WATCH = _core_.CURSOR_WATCH
+CURSOR_BLANK = _core_.CURSOR_BLANK
+CURSOR_DEFAULT = _core_.CURSOR_DEFAULT
+CURSOR_COPY_ARROW = _core_.CURSOR_COPY_ARROW
+CURSOR_ARROWWAIT = _core_.CURSOR_ARROWWAIT
+CURSOR_OPEN_HAND = _core_.CURSOR_OPEN_HAND
+CURSOR_CLOSED_HAND = _core_.CURSOR_CLOSED_HAND
+CURSOR_MAX = _core_.CURSOR_MAX
+#---------------------------------------------------------------------------
+
+class Size(object):
+ """
+ wx.Size is a useful data structure used to represent the size of
+ something. It simply contains integer width and height
+ properties. In most places in wxPython where a wx.Size is
+ expected a (width, height) tuple can be used instead.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ width = property(_core_.Size_width_get, _core_.Size_width_set)
+ height = property(_core_.Size_height_get, _core_.Size_height_set)
+ x = width; y = height
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int w=0, int h=0) -> Size
+
+ Creates a size object.
+ """
+ _core_.Size_swiginit(self,_core_.new_Size(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_Size
+ __del__ = lambda self : None;
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Test for equality of wx.Size objects.
+ """
+ return _core_.Size___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Test for inequality of wx.Size objects.
+ """
+ return _core_.Size___ne__(*args, **kwargs)
+
+ def __add__(*args, **kwargs):
+ """
+ __add__(self, Size sz) -> Size
+
+ Add sz's proprties to this and return the result.
+ """
+ return _core_.Size___add__(*args, **kwargs)
+
+ def __sub__(*args, **kwargs):
+ """
+ __sub__(self, Size sz) -> Size
+
+ Subtract sz's properties from this and return the result.
+ """
+ return _core_.Size___sub__(*args, **kwargs)
+
+ def IncTo(*args, **kwargs):
+ """
+ IncTo(self, Size sz)
+
+ Increments this object so that both of its dimensions are not less
+ than the corresponding dimensions of the size.
+ """
+ return _core_.Size_IncTo(*args, **kwargs)
+
+ def DecTo(*args, **kwargs):
+ """
+ DecTo(self, Size sz)
+
+ Decrements this object so that both of its dimensions are not greater
+ than the corresponding dimensions of the size.
+ """
+ return _core_.Size_DecTo(*args, **kwargs)
+
+ def IncBy(*args, **kwargs):
+ """IncBy(self, int dx, int dy)"""
+ return _core_.Size_IncBy(*args, **kwargs)
+
+ def DecBy(*args, **kwargs):
+ """DecBy(self, int dx, int dy)"""
+ return _core_.Size_DecBy(*args, **kwargs)
+
+ def Scale(*args, **kwargs):
+ """
+ Scale(self, float xscale, float yscale)
+
+ Scales the dimensions of this object by the given factors.
+ """
+ return _core_.Size_Scale(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """
+ Set(self, int w, int h)
+
+ Set both width and height.
+ """
+ return _core_.Size_Set(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """SetWidth(self, int w)"""
+ return _core_.Size_SetWidth(*args, **kwargs)
+
+ def SetHeight(*args, **kwargs):
+ """SetHeight(self, int h)"""
+ return _core_.Size_SetHeight(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _core_.Size_GetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """GetHeight(self) -> int"""
+ return _core_.Size_GetHeight(*args, **kwargs)
+
+ def IsFullySpecified(*args, **kwargs):
+ """
+ IsFullySpecified(self) -> bool
+
+ Returns True if both components of the size are non-default values.
+ """
+ return _core_.Size_IsFullySpecified(*args, **kwargs)
+
+ def SetDefaults(*args, **kwargs):
+ """
+ SetDefaults(self, Size size)
+
+ Combine this size with the other one replacing the default components
+ of this object (i.e. equal to -1) with those of the other.
+ """
+ return _core_.Size_SetDefaults(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get() -> (width,height)
+
+ Returns the width and height properties as a tuple.
+ """
+ return _core_.Size_Get(*args, **kwargs)
+
+ asTuple = wx.deprecated(Get, "asTuple is deprecated, use `Get` instead")
+ def __str__(self): return str(self.Get())
+ def __repr__(self): return 'wx.Size'+str(self.Get())
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __setitem__(self, index, val):
+ if index == 0: self.width = val
+ elif index == 1: self.height = val
+ else: raise IndexError
+ def __nonzero__(self): return self.Get() != (0,0)
+ __safe_for_unpickling__ = True
+ def __reduce__(self): return (wx.Size, self.Get())
+
+_core_.Size_swigregister(Size)
+
+#---------------------------------------------------------------------------
+
+class RealPoint(object):
+ """
+ A data structure for representing a point or position with floating
+ point x and y properties. In wxPython most places that expect a
+ wx.RealPoint can also accept a (x,y) tuple.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ x = property(_core_.RealPoint_x_get, _core_.RealPoint_x_set)
+ y = property(_core_.RealPoint_y_get, _core_.RealPoint_y_set)
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, double x=0.0, double y=0.0) -> RealPoint
+
+ Create a wx.RealPoint object
+ """
+ _core_.RealPoint_swiginit(self,_core_.new_RealPoint(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_RealPoint
+ __del__ = lambda self : None;
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Test for equality of wx.RealPoint objects.
+ """
+ return _core_.RealPoint___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Test for inequality of wx.RealPoint objects.
+ """
+ return _core_.RealPoint___ne__(*args, **kwargs)
+
+ def __add__(*args, **kwargs):
+ """
+ __add__(self, RealPoint pt) -> RealPoint
+
+ Add pt's proprties to this and return the result.
+ """
+ return _core_.RealPoint___add__(*args, **kwargs)
+
+ def __sub__(*args, **kwargs):
+ """
+ __sub__(self, RealPoint pt) -> RealPoint
+
+ Subtract pt's properties from this and return the result.
+ """
+ return _core_.RealPoint___sub__(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """
+ Set(self, double x, double y)
+
+ Set both the x and y properties
+ """
+ return _core_.RealPoint_Set(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get() -> (x,y)
+
+ Return the x and y properties as a tuple.
+ """
+ return _core_.RealPoint_Get(*args, **kwargs)
+
+ asTuple = wx.deprecated(Get, "asTuple is deprecated, use `Get` instead")
+ def __str__(self): return str(self.Get())
+ def __repr__(self): return 'wx.RealPoint'+str(self.Get())
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __setitem__(self, index, val):
+ if index == 0: self.x = val
+ elif index == 1: self.y = val
+ else: raise IndexError
+ def __nonzero__(self): return self.Get() != (0.0, 0.0)
+ __safe_for_unpickling__ = True
+ def __reduce__(self): return (wx.RealPoint, self.Get())
+
+_core_.RealPoint_swigregister(RealPoint)
+
+#---------------------------------------------------------------------------
+
+class Point(object):
+ """
+ A data structure for representing a point or position with integer x
+ and y properties. Most places in wxPython that expect a wx.Point can
+ also accept a (x,y) tuple.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ x = property(_core_.Point_x_get, _core_.Point_x_set)
+ y = property(_core_.Point_y_get, _core_.Point_y_set)
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int x=0, int y=0) -> Point
+
+ Create a wx.Point object
+ """
+ _core_.Point_swiginit(self,_core_.new_Point(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_Point
+ __del__ = lambda self : None;
+ def IsFullySpecified(*args, **kwargs):
+ """IsFullySpecified(self) -> bool"""
+ return _core_.Point_IsFullySpecified(*args, **kwargs)
+
+ def SetDefaults(*args, **kwargs):
+ """SetDefaults(self, Point pt)"""
+ return _core_.Point_SetDefaults(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Test for equality of wx.Point objects.
+ """
+ return _core_.Point___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Test for inequality of wx.Point objects.
+ """
+ return _core_.Point___ne__(*args, **kwargs)
+
+ def __add__(*args, **kwargs):
+ """
+ __add__(self, Point pt) -> Point
+
+ Add pt's proprties to this and return the result.
+ """
+ return _core_.Point___add__(*args, **kwargs)
+
+ def __sub__(*args, **kwargs):
+ """
+ __sub__(self, Point pt) -> Point
+
+ Subtract pt's properties from this and return the result.
+ """
+ return _core_.Point___sub__(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """
+ Set(self, long x, long y)
+
+ Set both the x and y properties
+ """
+ return _core_.Point_Set(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get() -> (x,y)
+
+ Return the x and y properties as a tuple.
+ """
+ return _core_.Point_Get(*args, **kwargs)
+
+ asTuple = wx.deprecated(Get, "asTuple is deprecated, use `Get` instead")
+ def __str__(self): return str(self.Get())
+ def __repr__(self): return 'wx.Point'+str(self.Get())
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __setitem__(self, index, val):
+ if index == 0: self.x = val
+ elif index == 1: self.y = val
+ else: raise IndexError
+ def __nonzero__(self): return self.Get() != (0,0)
+ __safe_for_unpickling__ = True
+ def __reduce__(self): return (wx.Point, self.Get())
+
+_core_.Point_swigregister(Point)
+
+#---------------------------------------------------------------------------
+
+class Rect(object):
+ """
+ A class for representing and manipulating rectangles. It has x, y,
+ width and height properties. In wxPython most palces that expect a
+ wx.Rect can also accept a (x,y,width,height) tuple.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int x=0, int y=0, int width=0, int height=0) -> Rect
+
+ Create a new Rect object.
+ """
+ _core_.Rect_swiginit(self,_core_.new_Rect(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_Rect
+ __del__ = lambda self : None;
+ def GetX(*args, **kwargs):
+ """GetX(self) -> int"""
+ return _core_.Rect_GetX(*args, **kwargs)
+
+ def SetX(*args, **kwargs):
+ """SetX(self, int x)"""
+ return _core_.Rect_SetX(*args, **kwargs)
+
+ def GetY(*args, **kwargs):
+ """GetY(self) -> int"""
+ return _core_.Rect_GetY(*args, **kwargs)
+
+ def SetY(*args, **kwargs):
+ """SetY(self, int y)"""
+ return _core_.Rect_SetY(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _core_.Rect_GetWidth(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """SetWidth(self, int w)"""
+ return _core_.Rect_SetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """GetHeight(self) -> int"""
+ return _core_.Rect_GetHeight(*args, **kwargs)
+
+ def SetHeight(*args, **kwargs):
+ """SetHeight(self, int h)"""
+ return _core_.Rect_SetHeight(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point"""
+ return _core_.Rect_GetPosition(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, Point p)"""
+ return _core_.Rect_SetPosition(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(self) -> Size"""
+ return _core_.Rect_GetSize(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, Size s)"""
+ return _core_.Rect_SetSize(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """IsEmpty(self) -> bool"""
+ return _core_.Rect_IsEmpty(*args, **kwargs)
+
+ def GetTopLeft(*args, **kwargs):
+ """GetTopLeft(self) -> Point"""
+ return _core_.Rect_GetTopLeft(*args, **kwargs)
+
+ def SetTopLeft(*args, **kwargs):
+ """SetTopLeft(self, Point p)"""
+ return _core_.Rect_SetTopLeft(*args, **kwargs)
+
+ def GetBottomRight(*args, **kwargs):
+ """GetBottomRight(self) -> Point"""
+ return _core_.Rect_GetBottomRight(*args, **kwargs)
+
+ def SetBottomRight(*args, **kwargs):
+ """SetBottomRight(self, Point p)"""
+ return _core_.Rect_SetBottomRight(*args, **kwargs)
+
+ def GetTopRight(*args, **kwargs):
+ """GetTopRight(self) -> Point"""
+ return _core_.Rect_GetTopRight(*args, **kwargs)
+
+ def SetTopRight(*args, **kwargs):
+ """SetTopRight(self, Point p)"""
+ return _core_.Rect_SetTopRight(*args, **kwargs)
+
+ def GetBottomLeft(*args, **kwargs):
+ """GetBottomLeft(self) -> Point"""
+ return _core_.Rect_GetBottomLeft(*args, **kwargs)
+
+ def SetBottomLeft(*args, **kwargs):
+ """SetBottomLeft(self, Point p)"""
+ return _core_.Rect_SetBottomLeft(*args, **kwargs)
+
+ def GetLeft(*args, **kwargs):
+ """GetLeft(self) -> int"""
+ return _core_.Rect_GetLeft(*args, **kwargs)
+
+ def GetTop(*args, **kwargs):
+ """GetTop(self) -> int"""
+ return _core_.Rect_GetTop(*args, **kwargs)
+
+ def GetBottom(*args, **kwargs):
+ """GetBottom(self) -> int"""
+ return _core_.Rect_GetBottom(*args, **kwargs)
+
+ def GetRight(*args, **kwargs):
+ """GetRight(self) -> int"""
+ return _core_.Rect_GetRight(*args, **kwargs)
+
+ def SetLeft(*args, **kwargs):
+ """SetLeft(self, int left)"""
+ return _core_.Rect_SetLeft(*args, **kwargs)
+
+ def SetRight(*args, **kwargs):
+ """SetRight(self, int right)"""
+ return _core_.Rect_SetRight(*args, **kwargs)
+
+ def SetTop(*args, **kwargs):
+ """SetTop(self, int top)"""
+ return _core_.Rect_SetTop(*args, **kwargs)
+
+ def SetBottom(*args, **kwargs):
+ """SetBottom(self, int bottom)"""
+ return _core_.Rect_SetBottom(*args, **kwargs)
+
+ position = property(GetPosition, SetPosition)
+ size = property(GetSize, SetSize)
+ left = property(GetLeft, SetLeft)
+ right = property(GetRight, SetRight)
+ top = property(GetTop, SetTop)
+ bottom = property(GetBottom, SetBottom)
+
+ def Inflate(*args, **kwargs):
+ """
+ Inflate(self, int dx, int dy) -> Rect
+
+ Increases the size of the rectangle.
+
+ The left border is moved farther left and the right border is moved
+ farther right by ``dx``. The upper border is moved farther up and the
+ bottom border is moved farther down by ``dy``. (Note the the width and
+ height of the rectangle thus change by ``2*dx`` and ``2*dy``,
+ respectively.) If one or both of ``dx`` and ``dy`` are negative, the
+ opposite happens: the rectangle size decreases in the respective
+ direction.
+
+ The change is made to the rectangle inplace, if instead you need a
+ copy that is inflated, preserving the original then make the copy
+ first::
+
+ copy = wx.Rect(*original)
+ copy.Inflate(10,15)
+
+
+ """
+ return _core_.Rect_Inflate(*args, **kwargs)
+
+ def Deflate(*args, **kwargs):
+ """
+ Deflate(self, int dx, int dy) -> Rect
+
+ Decrease the rectangle size. This method is the opposite of `Inflate`
+ in that Deflate(a,b) is equivalent to Inflate(-a,-b). Please refer to
+ `Inflate` for a full description.
+ """
+ return _core_.Rect_Deflate(*args, **kwargs)
+
+ def OffsetXY(*args, **kwargs):
+ """
+ OffsetXY(self, int dx, int dy)
+
+ Moves the rectangle by the specified offset. If dx is positive, the
+ rectangle is moved to the right, if dy is positive, it is moved to the
+ bottom, otherwise it is moved to the left or top respectively.
+ """
+ return _core_.Rect_OffsetXY(*args, **kwargs)
+
+ def Offset(*args, **kwargs):
+ """
+ Offset(self, Point pt)
+
+ Same as `OffsetXY` but uses dx,dy from Point
+ """
+ return _core_.Rect_Offset(*args, **kwargs)
+
+ def Intersect(*args, **kwargs):
+ """
+ Intersect(self, Rect rect) -> Rect
+
+ Returns the intersectsion of this rectangle and rect.
+ """
+ return _core_.Rect_Intersect(*args, **kwargs)
+
+ def Union(*args, **kwargs):
+ """
+ Union(self, Rect rect) -> Rect
+
+ Returns the union of this rectangle and rect.
+ """
+ return _core_.Rect_Union(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Test for equality of wx.Rect objects.
+ """
+ return _core_.Rect___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Test for inequality of wx.Rect objects.
+ """
+ return _core_.Rect___ne__(*args, **kwargs)
+
+ def __add__(*args, **kwargs):
+ """
+ __add__(self, Rect rect) -> Rect
+
+ Add rect's proprties to this and return the result.
+ """
+ return _core_.Rect___add__(*args, **kwargs)
+
+ def __mul__(*args, **kwargs):
+ """
+ __mul__(self, Rect rect) -> Rect
+
+ Calculate the intersection of the rectangles and return the result.
+ """
+ return _core_.Rect___mul__(*args, **kwargs)
+
+ def __iadd__(*args, **kwargs):
+ """
+ __iadd__(self, Rect rect) -> Rect
+
+ Add the properties of rect to this rectangle, updating this rectangle.
+ """
+ return _core_.Rect___iadd__(*args, **kwargs)
+
+ def ContainsXY(*args, **kwargs):
+ """
+ ContainsXY(self, int x, int y) -> bool
+
+ Return True if the point is inside the rect.
+ """
+ return _core_.Rect_ContainsXY(*args, **kwargs)
+
+ def Contains(*args, **kwargs):
+ """
+ Contains(self, Point pt) -> bool
+
+ Return True if the point is inside the rect.
+ """
+ return _core_.Rect_Contains(*args, **kwargs)
+
+ def ContainsRect(*args, **kwargs):
+ """
+ ContainsRect(self, Rect rect) -> bool
+
+ Returns ``True`` if the given rectangle is completely inside this
+ rectangle or touches its boundary.
+ """
+ return _core_.Rect_ContainsRect(*args, **kwargs)
+
+ #Inside = wx.deprecated(Contains, "Use `Contains` instead.")
+ #InsideXY = wx.deprecated(ContainsXY, "Use `ContainsXY` instead.")
+ #InsideRect = wx.deprecated(ContainsRect, "Use `ContainsRect` instead.")
+ Inside = Contains
+ InsideXY = ContainsXY
+ InsideRect = ContainsRect
+
+ def Intersects(*args, **kwargs):
+ """
+ Intersects(self, Rect rect) -> bool
+
+ Returns True if the rectangles have a non empty intersection.
+ """
+ return _core_.Rect_Intersects(*args, **kwargs)
+
+ def CenterIn(*args, **kwargs):
+ """
+ CenterIn(self, Rect r, int dir=BOTH) -> Rect
+
+ Center this rectangle within the one passed to the method, which is
+ usually, but not necessarily, the larger one.
+ """
+ return _core_.Rect_CenterIn(*args, **kwargs)
+
+ CentreIn = CenterIn
+ x = property(_core_.Rect_x_get, _core_.Rect_x_set)
+ y = property(_core_.Rect_y_get, _core_.Rect_y_set)
+ width = property(_core_.Rect_width_get, _core_.Rect_width_set)
+ height = property(_core_.Rect_height_get, _core_.Rect_height_set)
+ def Set(*args, **kwargs):
+ """
+ Set(self, int x=0, int y=0, int width=0, int height=0)
+
+ Set all rectangle properties.
+ """
+ return _core_.Rect_Set(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get() -> (x,y,width,height)
+
+ Return the rectangle properties as a tuple.
+ """
+ return _core_.Rect_Get(*args, **kwargs)
+
+ asTuple = wx.deprecated(Get, "asTuple is deprecated, use `Get` instead")
+ def __str__(self): return str(self.Get())
+ def __repr__(self): return 'wx.Rect'+str(self.Get())
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __setitem__(self, index, val):
+ if index == 0: self.x = val
+ elif index == 1: self.y = val
+ elif index == 2: self.width = val
+ elif index == 3: self.height = val
+ else: raise IndexError
+ def __nonzero__(self): return self.Get() != (0,0,0,0)
+ __safe_for_unpickling__ = True
+ def __reduce__(self): return (wx.Rect, self.Get())
+
+ Bottom = property(GetBottom,SetBottom,doc="See `GetBottom` and `SetBottom`")
+ BottomRight = property(GetBottomRight,SetBottomRight,doc="See `GetBottomRight` and `SetBottomRight`")
+ BottomLeft = property(GetBottomLeft,SetBottomLeft,doc="See `GetBottomLeft` and `SetBottomLeft`")
+ Height = property(GetHeight,SetHeight,doc="See `GetHeight` and `SetHeight`")
+ Left = property(GetLeft,SetLeft,doc="See `GetLeft` and `SetLeft`")
+ Position = property(GetPosition,SetPosition,doc="See `GetPosition` and `SetPosition`")
+ Right = property(GetRight,SetRight,doc="See `GetRight` and `SetRight`")
+ Size = property(GetSize,SetSize,doc="See `GetSize` and `SetSize`")
+ Top = property(GetTop,SetTop,doc="See `GetTop` and `SetTop`")
+ TopLeft = property(GetTopLeft,SetTopLeft,doc="See `GetTopLeft` and `SetTopLeft`")
+ TopRight = property(GetTopRight,SetTopRight,doc="See `GetTopRight` and `SetTopRight`")
+ Width = property(GetWidth,SetWidth,doc="See `GetWidth` and `SetWidth`")
+ X = property(GetX,SetX,doc="See `GetX` and `SetX`")
+ Y = property(GetY,SetY,doc="See `GetY` and `SetY`")
+ Empty = property(IsEmpty,doc="See `IsEmpty`")
+_core_.Rect_swigregister(Rect)
+
+def RectPP(*args, **kwargs):
+ """
+ RectPP(Point topLeft, Point bottomRight) -> Rect
+
+ Create a new Rect object from Points representing two corners.
+ """
+ val = _core_.new_RectPP(*args, **kwargs)
+ return val
+
+def RectPS(*args, **kwargs):
+ """
+ RectPS(Point pos, Size size) -> Rect
+
+ Create a new Rect from a position and size.
+ """
+ val = _core_.new_RectPS(*args, **kwargs)
+ return val
+
+def RectS(*args, **kwargs):
+ """
+ RectS(Size size) -> Rect
+
+ Create a new Rect from a size only.
+ """
+ val = _core_.new_RectS(*args, **kwargs)
+ return val
+
+
+def IntersectRect(*args, **kwargs):
+ """
+ IntersectRect(Rect r1, Rect r2) -> Rect
+
+ Calculate and return the intersection of r1 and r2.
+ """
+ return _core_.IntersectRect(*args, **kwargs)
+#---------------------------------------------------------------------------
+
+class Point2D(object):
+ """
+ wx.Point2Ds represent a point or a vector in a 2d coordinate system
+ with floating point values.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, double x=0.0, double y=0.0) -> Point2D
+
+ Create a w.Point2D object.
+ """
+ _core_.Point2D_swiginit(self,_core_.new_Point2D(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_Point2D
+ __del__ = lambda self : None;
+ def GetFloor(*args, **kwargs):
+ """
+ GetFloor() -> (x,y)
+
+ Convert to integer
+ """
+ return _core_.Point2D_GetFloor(*args, **kwargs)
+
+ def GetRounded(*args, **kwargs):
+ """
+ GetRounded() -> (x,y)
+
+ Convert to integer
+ """
+ return _core_.Point2D_GetRounded(*args, **kwargs)
+
+ def GetVectorLength(*args, **kwargs):
+ """GetVectorLength(self) -> double"""
+ return _core_.Point2D_GetVectorLength(*args, **kwargs)
+
+ def GetVectorAngle(*args, **kwargs):
+ """GetVectorAngle(self) -> double"""
+ return _core_.Point2D_GetVectorAngle(*args, **kwargs)
+
+ def SetVectorLength(*args, **kwargs):
+ """SetVectorLength(self, double length)"""
+ return _core_.Point2D_SetVectorLength(*args, **kwargs)
+
+ def SetVectorAngle(*args, **kwargs):
+ """SetVectorAngle(self, double degrees)"""
+ return _core_.Point2D_SetVectorAngle(*args, **kwargs)
+
+ def SetPolarCoordinates(self, angle, length):
+ self.SetVectorLength(length)
+ self.SetVectorAngle(angle)
+ def Normalize(self):
+ self.SetVectorLength(1.0)
+
+ def GetDistance(*args, **kwargs):
+ """GetDistance(self, Point2D pt) -> double"""
+ return _core_.Point2D_GetDistance(*args, **kwargs)
+
+ def GetDistanceSquare(*args, **kwargs):
+ """GetDistanceSquare(self, Point2D pt) -> double"""
+ return _core_.Point2D_GetDistanceSquare(*args, **kwargs)
+
+ def GetDotProduct(*args, **kwargs):
+ """GetDotProduct(self, Point2D vec) -> double"""
+ return _core_.Point2D_GetDotProduct(*args, **kwargs)
+
+ def GetCrossProduct(*args, **kwargs):
+ """GetCrossProduct(self, Point2D vec) -> double"""
+ return _core_.Point2D_GetCrossProduct(*args, **kwargs)
+
+ def __neg__(*args, **kwargs):
+ """
+ __neg__(self) -> Point2D
+
+ the reflection of this point
+ """
+ return _core_.Point2D___neg__(*args, **kwargs)
+
+ def __iadd__(*args, **kwargs):
+ """__iadd__(self, Point2D pt) -> Point2D"""
+ return _core_.Point2D___iadd__(*args, **kwargs)
+
+ def __isub__(*args, **kwargs):
+ """__isub__(self, Point2D pt) -> Point2D"""
+ return _core_.Point2D___isub__(*args, **kwargs)
+
+ def __imul__(*args):
+ """__imul__(self, Point2D pt) -> Point2D"""
+ return _core_.Point2D___imul__(*args)
+
+ def __idiv__(*args):
+ """__idiv__(self, wxPoint2DDouble pt) -> Point2D"""
+ return _core_.Point2D___idiv__(*args)
+
+ def __add__(*args):
+ """__add__(self, Point2D pt) -> Point2D"""
+ return _core_.Point2D___add__(*args)
+
+ def __sub__(*args):
+ """__sub__(self, Point2D pt) -> Point2D"""
+ return _core_.Point2D___sub__(*args)
+
+ def __mul__(*args):
+ """
+ __mul__(self, Point2D pt) -> Point2D
+ __mul__(self, double n) -> Point2D
+ """
+ return _core_.Point2D___mul__(*args)
+
+ def __div__(*args):
+ """
+ __div__(self, Point2D pt) -> Point2D
+ __div__(self, double n) -> Point2D
+ """
+ return _core_.Point2D___div__(*args)
+
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Test for equality of wx.Point2D objects.
+ """
+ return _core_.Point2D___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Test for inequality of wx.Point2D objects.
+ """
+ return _core_.Point2D___ne__(*args, **kwargs)
+
+ x = property(_core_.Point2D_x_get, _core_.Point2D_x_set)
+ y = property(_core_.Point2D_y_get, _core_.Point2D_y_set)
+ def Set(*args, **kwargs):
+ """Set(self, double x=0, double y=0)"""
+ return _core_.Point2D_Set(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get() -> (x,y)
+
+ Return x and y properties as a tuple.
+ """
+ return _core_.Point2D_Get(*args, **kwargs)
+
+ asTuple = wx.deprecated(Get, "asTuple is deprecated, use `Get` instead")
+ def __str__(self): return str(self.Get())
+ def __repr__(self): return 'wx.Point2D'+str(self.Get())
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __setitem__(self, index, val):
+ if index == 0: self.x = val
+ elif index == 1: self.y = val
+ else: raise IndexError
+ def __nonzero__(self): return self.Get() != (0.0, 0.0)
+ __safe_for_unpickling__ = True
+ def __reduce__(self): return (wx.Point2D, self.Get())
+
+ Floor = property(GetFloor,doc="See `GetFloor`")
+ Rounded = property(GetRounded,doc="See `GetRounded`")
+ VectorAngle = property(GetVectorAngle,SetVectorAngle,doc="See `GetVectorAngle` and `SetVectorAngle`")
+ VectorLength = property(GetVectorLength,SetVectorLength,doc="See `GetVectorLength` and `SetVectorLength`")
+_core_.Point2D_swigregister(Point2D)
+
+def Point2DCopy(*args, **kwargs):
+ """
+ Point2DCopy(Point2D pt) -> Point2D
+
+ Create a w.Point2D object.
+ """
+ val = _core_.new_Point2DCopy(*args, **kwargs)
+ return val
+
+def Point2DFromPoint(*args, **kwargs):
+ """
+ Point2DFromPoint(Point pt) -> Point2D
+
+ Create a w.Point2D object.
+ """
+ val = _core_.new_Point2DFromPoint(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+Inside = _core_.Inside
+OutLeft = _core_.OutLeft
+OutRight = _core_.OutRight
+OutTop = _core_.OutTop
+OutBottom = _core_.OutBottom
+class Rect2D(object):
+ """
+ wx.Rect2D is a rectangle, with position and size, in a 2D coordinate system
+ with floating point component values.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Double x=0.0, Double y=0.0, Double w=0.0, Double h=0.0) -> Rect2D
+
+ wx.Rect2D is a rectangle, with position and size, in a 2D coordinate system
+ with floating point component values.
+ """
+ _core_.Rect2D_swiginit(self,_core_.new_Rect2D(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_Rect2D
+ __del__ = lambda self : None;
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point2D"""
+ return _core_.Rect2D_GetPosition(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(self) -> Size"""
+ return _core_.Rect2D_GetSize(*args, **kwargs)
+
+ def GetLeft(*args, **kwargs):
+ """GetLeft(self) -> Double"""
+ return _core_.Rect2D_GetLeft(*args, **kwargs)
+
+ def SetLeft(*args, **kwargs):
+ """SetLeft(self, Double n)"""
+ return _core_.Rect2D_SetLeft(*args, **kwargs)
+
+ def MoveLeftTo(*args, **kwargs):
+ """MoveLeftTo(self, Double n)"""
+ return _core_.Rect2D_MoveLeftTo(*args, **kwargs)
+
+ def GetTop(*args, **kwargs):
+ """GetTop(self) -> Double"""
+ return _core_.Rect2D_GetTop(*args, **kwargs)
+
+ def SetTop(*args, **kwargs):
+ """SetTop(self, Double n)"""
+ return _core_.Rect2D_SetTop(*args, **kwargs)
+
+ def MoveTopTo(*args, **kwargs):
+ """MoveTopTo(self, Double n)"""
+ return _core_.Rect2D_MoveTopTo(*args, **kwargs)
+
+ def GetBottom(*args, **kwargs):
+ """GetBottom(self) -> Double"""
+ return _core_.Rect2D_GetBottom(*args, **kwargs)
+
+ def SetBottom(*args, **kwargs):
+ """SetBottom(self, Double n)"""
+ return _core_.Rect2D_SetBottom(*args, **kwargs)
+
+ def MoveBottomTo(*args, **kwargs):
+ """MoveBottomTo(self, Double n)"""
+ return _core_.Rect2D_MoveBottomTo(*args, **kwargs)
+
+ def GetRight(*args, **kwargs):
+ """GetRight(self) -> Double"""
+ return _core_.Rect2D_GetRight(*args, **kwargs)
+
+ def SetRight(*args, **kwargs):
+ """SetRight(self, Double n)"""
+ return _core_.Rect2D_SetRight(*args, **kwargs)
+
+ def MoveRightTo(*args, **kwargs):
+ """MoveRightTo(self, Double n)"""
+ return _core_.Rect2D_MoveRightTo(*args, **kwargs)
+
+ def GetLeftTop(*args, **kwargs):
+ """GetLeftTop(self) -> Point2D"""
+ return _core_.Rect2D_GetLeftTop(*args, **kwargs)
+
+ def SetLeftTop(*args, **kwargs):
+ """SetLeftTop(self, Point2D pt)"""
+ return _core_.Rect2D_SetLeftTop(*args, **kwargs)
+
+ def MoveLeftTopTo(*args, **kwargs):
+ """MoveLeftTopTo(self, Point2D pt)"""
+ return _core_.Rect2D_MoveLeftTopTo(*args, **kwargs)
+
+ def GetLeftBottom(*args, **kwargs):
+ """GetLeftBottom(self) -> Point2D"""
+ return _core_.Rect2D_GetLeftBottom(*args, **kwargs)
+
+ def SetLeftBottom(*args, **kwargs):
+ """SetLeftBottom(self, Point2D pt)"""
+ return _core_.Rect2D_SetLeftBottom(*args, **kwargs)
+
+ def MoveLeftBottomTo(*args, **kwargs):
+ """MoveLeftBottomTo(self, Point2D pt)"""
+ return _core_.Rect2D_MoveLeftBottomTo(*args, **kwargs)
+
+ def GetRightTop(*args, **kwargs):
+ """GetRightTop(self) -> Point2D"""
+ return _core_.Rect2D_GetRightTop(*args, **kwargs)
+
+ def SetRightTop(*args, **kwargs):
+ """SetRightTop(self, Point2D pt)"""
+ return _core_.Rect2D_SetRightTop(*args, **kwargs)
+
+ def MoveRightTopTo(*args, **kwargs):
+ """MoveRightTopTo(self, Point2D pt)"""
+ return _core_.Rect2D_MoveRightTopTo(*args, **kwargs)
+
+ def GetRightBottom(*args, **kwargs):
+ """GetRightBottom(self) -> Point2D"""
+ return _core_.Rect2D_GetRightBottom(*args, **kwargs)
+
+ def SetRightBottom(*args, **kwargs):
+ """SetRightBottom(self, Point2D pt)"""
+ return _core_.Rect2D_SetRightBottom(*args, **kwargs)
+
+ def MoveRightBottomTo(*args, **kwargs):
+ """MoveRightBottomTo(self, Point2D pt)"""
+ return _core_.Rect2D_MoveRightBottomTo(*args, **kwargs)
+
+ def GetCentre(*args, **kwargs):
+ """GetCentre(self) -> Point2D"""
+ return _core_.Rect2D_GetCentre(*args, **kwargs)
+
+ def SetCentre(*args, **kwargs):
+ """SetCentre(self, Point2D pt)"""
+ return _core_.Rect2D_SetCentre(*args, **kwargs)
+
+ def MoveCentreTo(*args, **kwargs):
+ """MoveCentreTo(self, Point2D pt)"""
+ return _core_.Rect2D_MoveCentreTo(*args, **kwargs)
+
+ def GetOutcode(*args, **kwargs):
+ """GetOutcode(self, Point2D pt) -> int"""
+ return _core_.Rect2D_GetOutcode(*args, **kwargs)
+
+ def Contains(*args, **kwargs):
+ """Contains(self, Point2D pt) -> bool"""
+ return _core_.Rect2D_Contains(*args, **kwargs)
+
+ def ContainsRect(*args, **kwargs):
+ """ContainsRect(self, Rect2D rect) -> bool"""
+ return _core_.Rect2D_ContainsRect(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """IsEmpty(self) -> bool"""
+ return _core_.Rect2D_IsEmpty(*args, **kwargs)
+
+ def HaveEqualSize(*args, **kwargs):
+ """HaveEqualSize(self, Rect2D rect) -> bool"""
+ return _core_.Rect2D_HaveEqualSize(*args, **kwargs)
+
+ def Inset(*args):
+ """
+ Inset(self, Double x, Double y)
+ Inset(self, Double left, Double top, Double right, Double bottom)
+ """
+ return _core_.Rect2D_Inset(*args)
+
+ def Offset(*args, **kwargs):
+ """Offset(self, Point2D pt)"""
+ return _core_.Rect2D_Offset(*args, **kwargs)
+
+ def ConstrainTo(*args, **kwargs):
+ """ConstrainTo(self, Rect2D rect)"""
+ return _core_.Rect2D_ConstrainTo(*args, **kwargs)
+
+ def Interpolate(*args, **kwargs):
+ """Interpolate(self, int widthfactor, int heightfactor) -> Point2D"""
+ return _core_.Rect2D_Interpolate(*args, **kwargs)
+
+ def Intersect(*args, **kwargs):
+ """Intersect(self, Rect2D otherRect)"""
+ return _core_.Rect2D_Intersect(*args, **kwargs)
+
+ def CreateIntersection(*args, **kwargs):
+ """CreateIntersection(self, Rect2D otherRect) -> Rect2D"""
+ return _core_.Rect2D_CreateIntersection(*args, **kwargs)
+
+ def Intersects(*args, **kwargs):
+ """Intersects(self, Rect2D rect) -> bool"""
+ return _core_.Rect2D_Intersects(*args, **kwargs)
+
+ def Union(*args, **kwargs):
+ """Union(self, Rect2D otherRect)"""
+ return _core_.Rect2D_Union(*args, **kwargs)
+
+ def CreateUnion(*args, **kwargs):
+ """CreateUnion(self, Rect2D otherRect) -> Rect2D"""
+ return _core_.Rect2D_CreateUnion(*args, **kwargs)
+
+ def Scale(*args):
+ """
+ Scale(self, Double f)
+ Scale(self, int num, int denum)
+ """
+ return _core_.Rect2D_Scale(*args)
+
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Test for equality of wx.Rect2D objects.
+ """
+ return _core_.Rect2D___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Test for inequality of wx.Rect2D objects.
+ """
+ return _core_.Rect2D___ne__(*args, **kwargs)
+
+ x = property(_core_.Rect2D_x_get, _core_.Rect2D_x_set)
+ y = property(_core_.Rect2D_y_get, _core_.Rect2D_y_set)
+ width = property(_core_.Rect2D_width_get, _core_.Rect2D_width_set)
+ height = property(_core_.Rect2D_height_get, _core_.Rect2D_height_set)
+ def Set(*args, **kwargs):
+ """Set(self, Double x=0, Double y=0, Double width=0, Double height=0)"""
+ return _core_.Rect2D_Set(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get() -> (x,y, width, height)
+
+ Return x, y, width and height y properties as a tuple.
+ """
+ return _core_.Rect2D_Get(*args, **kwargs)
+
+ def __str__(self): return str(self.Get())
+ def __repr__(self): return 'wx.Rect2D'+str(self.Get())
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __setitem__(self, index, val):
+ if index == 0: self.x = val
+ elif index == 1: self.y = val
+ elif index == 2: self.width = val
+ elif index == 3: self.height = val
+ else: raise IndexError
+ def __nonzero__(self): return self.Get() != (0.0, 0.0, 0.0, 0.0)
+ __safe_for_unpickling__ = True
+ def __reduce__(self): return (wx.Rect2D, self.Get())
+
+_core_.Rect2D_swigregister(Rect2D)
+
+class Position(object):
+ """Proxy of C++ Position class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int row=0, int col=0) -> Position"""
+ _core_.Position_swiginit(self,_core_.new_Position(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_Position
+ __del__ = lambda self : None;
+ def GetRow(*args, **kwargs):
+ """GetRow(self) -> int"""
+ return _core_.Position_GetRow(*args, **kwargs)
+
+ def GetColumn(*args, **kwargs):
+ """GetColumn(self) -> int"""
+ return _core_.Position_GetColumn(*args, **kwargs)
+
+ def GetCol(*args, **kwargs):
+ """GetCol(self) -> int"""
+ return _core_.Position_GetCol(*args, **kwargs)
+
+ def SetRow(*args, **kwargs):
+ """SetRow(self, int row)"""
+ return _core_.Position_SetRow(*args, **kwargs)
+
+ def SetColumn(*args, **kwargs):
+ """SetColumn(self, int column)"""
+ return _core_.Position_SetColumn(*args, **kwargs)
+
+ def SetCol(*args, **kwargs):
+ """SetCol(self, int column)"""
+ return _core_.Position_SetCol(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Test for equality of wx.Position objects.
+ """
+ return _core_.Position___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Test for inequality of wx.Position objects.
+ """
+ return _core_.Position___ne__(*args, **kwargs)
+
+ def __add__(*args):
+ """
+ __add__(self, Position p) -> Position
+ __add__(self, Size s) -> Position
+ """
+ return _core_.Position___add__(*args)
+
+ def __sub__(*args):
+ """
+ __sub__(self, Position p) -> Position
+ __sub__(self, Size s) -> Position
+ """
+ return _core_.Position___sub__(*args)
+
+ row = property(GetRow,SetRow)
+ col = property(GetCol,SetCol)
+_core_.Position_swigregister(Position)
+
+#---------------------------------------------------------------------------
+
+FromStart = _core_.FromStart
+FromCurrent = _core_.FromCurrent
+FromEnd = _core_.FromEnd
+class InputStream(object):
+ """Proxy of C++ InputStream class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, PyObject p) -> InputStream"""
+ _core_.InputStream_swiginit(self,_core_.new_InputStream(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_InputStream
+ __del__ = lambda self : None;
+ def close(*args, **kwargs):
+ """close(self)"""
+ return _core_.InputStream_close(*args, **kwargs)
+
+ def flush(*args, **kwargs):
+ """flush(self)"""
+ return _core_.InputStream_flush(*args, **kwargs)
+
+ def eof(*args, **kwargs):
+ """eof(self) -> bool"""
+ return _core_.InputStream_eof(*args, **kwargs)
+
+ def read(*args, **kwargs):
+ """read(self, int size=-1) -> PyObject"""
+ return _core_.InputStream_read(*args, **kwargs)
+
+ def readline(*args, **kwargs):
+ """readline(self, int size=-1) -> PyObject"""
+ return _core_.InputStream_readline(*args, **kwargs)
+
+ def readlines(*args, **kwargs):
+ """readlines(self, int sizehint=-1) -> PyObject"""
+ return _core_.InputStream_readlines(*args, **kwargs)
+
+ def seek(*args, **kwargs):
+ """seek(self, int offset, int whence=0)"""
+ return _core_.InputStream_seek(*args, **kwargs)
+
+ def tell(*args, **kwargs):
+ """tell(self) -> int"""
+ return _core_.InputStream_tell(*args, **kwargs)
+
+ def Peek(*args, **kwargs):
+ """Peek(self) -> char"""
+ return _core_.InputStream_Peek(*args, **kwargs)
+
+ def GetC(*args, **kwargs):
+ """GetC(self) -> char"""
+ return _core_.InputStream_GetC(*args, **kwargs)
+
+ def LastRead(*args, **kwargs):
+ """LastRead(self) -> size_t"""
+ return _core_.InputStream_LastRead(*args, **kwargs)
+
+ def CanRead(*args, **kwargs):
+ """CanRead(self) -> bool"""
+ return _core_.InputStream_CanRead(*args, **kwargs)
+
+ def Eof(*args, **kwargs):
+ """Eof(self) -> bool"""
+ return _core_.InputStream_Eof(*args, **kwargs)
+
+ def Ungetch(*args, **kwargs):
+ """Ungetch(self, char c) -> bool"""
+ return _core_.InputStream_Ungetch(*args, **kwargs)
+
+ def SeekI(*args, **kwargs):
+ """SeekI(self, long pos, int mode=FromStart) -> long"""
+ return _core_.InputStream_SeekI(*args, **kwargs)
+
+ def TellI(*args, **kwargs):
+ """TellI(self) -> long"""
+ return _core_.InputStream_TellI(*args, **kwargs)
+
+_core_.InputStream_swigregister(InputStream)
+DefaultPosition = cvar.DefaultPosition
+DefaultSize = cvar.DefaultSize
+
+class OutputStream(object):
+ """Proxy of C++ OutputStream class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, PyObject p) -> OutputStream"""
+ _core_.OutputStream_swiginit(self,_core_.new_OutputStream(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_OutputStream
+ __del__ = lambda self : None;
+ def close(*args, **kwargs):
+ """close(self)"""
+ return _core_.OutputStream_close(*args, **kwargs)
+
+ def flush(*args, **kwargs):
+ """flush(self)"""
+ return _core_.OutputStream_flush(*args, **kwargs)
+
+ def eof(*args, **kwargs):
+ """eof(self) -> bool"""
+ return _core_.OutputStream_eof(*args, **kwargs)
+
+ def seek(*args, **kwargs):
+ """seek(self, int offset, int whence=0)"""
+ return _core_.OutputStream_seek(*args, **kwargs)
+
+ def tell(*args, **kwargs):
+ """tell(self) -> int"""
+ return _core_.OutputStream_tell(*args, **kwargs)
+
+ def write(*args, **kwargs):
+ """write(self, PyObject data)"""
+ return _core_.OutputStream_write(*args, **kwargs)
+
+ def PutC(*args, **kwargs):
+ """PutC(self, char c)"""
+ return _core_.OutputStream_PutC(*args, **kwargs)
+
+ def LastWrite(*args, **kwargs):
+ """LastWrite(self) -> size_t"""
+ return _core_.OutputStream_LastWrite(*args, **kwargs)
+
+ def SeekO(*args, **kwargs):
+ """SeekO(self, unsigned long pos, int mode=FromStart) -> unsigned long"""
+ return _core_.OutputStream_SeekO(*args, **kwargs)
+
+ def TellO(*args, **kwargs):
+ """TellO(self) -> unsigned long"""
+ return _core_.OutputStream_TellO(*args, **kwargs)
+
+_core_.OutputStream_swigregister(OutputStream)
+
+#---------------------------------------------------------------------------
+
+class FSFile(Object):
+ """Proxy of C++ FSFile class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, InputStream stream, String loc, String mimetype, String anchor,
+ DateTime modif) -> FSFile
+ """
+ _core_.FSFile_swiginit(self,_core_.new_FSFile(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_FSFile
+ __del__ = lambda self : None;
+ def GetStream(*args, **kwargs):
+ """GetStream(self) -> InputStream"""
+ return _core_.FSFile_GetStream(*args, **kwargs)
+
+ def DetachStream(*args, **kwargs):
+ """DetachStream(self)"""
+ return _core_.FSFile_DetachStream(*args, **kwargs)
+
+ def GetMimeType(*args, **kwargs):
+ """GetMimeType(self) -> String"""
+ return _core_.FSFile_GetMimeType(*args, **kwargs)
+
+ def GetLocation(*args, **kwargs):
+ """GetLocation(self) -> String"""
+ return _core_.FSFile_GetLocation(*args, **kwargs)
+
+ def GetAnchor(*args, **kwargs):
+ """GetAnchor(self) -> String"""
+ return _core_.FSFile_GetAnchor(*args, **kwargs)
+
+ def GetModificationTime(*args, **kwargs):
+ """GetModificationTime(self) -> DateTime"""
+ return _core_.FSFile_GetModificationTime(*args, **kwargs)
+
+ Anchor = property(GetAnchor,doc="See `GetAnchor`")
+ Location = property(GetLocation,doc="See `GetLocation`")
+ MimeType = property(GetMimeType,doc="See `GetMimeType`")
+ ModificationTime = property(GetModificationTime,doc="See `GetModificationTime`")
+ Stream = property(GetStream,doc="See `GetStream`")
+_core_.FSFile_swigregister(FSFile)
+
+class CPPFileSystemHandler(object):
+ """Proxy of C++ CPPFileSystemHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_CPPFileSystemHandler
+ __del__ = lambda self : None;
+_core_.CPPFileSystemHandler_swigregister(CPPFileSystemHandler)
+
+class FileSystemHandler(CPPFileSystemHandler):
+ """Proxy of C++ FileSystemHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> FileSystemHandler"""
+ _core_.FileSystemHandler_swiginit(self,_core_.new_FileSystemHandler(*args, **kwargs))
+ FileSystemHandler._setCallbackInfo(self, self, FileSystemHandler)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _core_.FileSystemHandler__setCallbackInfo(*args, **kwargs)
+
+ def CanOpen(*args, **kwargs):
+ """CanOpen(self, String location) -> bool"""
+ return _core_.FileSystemHandler_CanOpen(*args, **kwargs)
+
+ def OpenFile(*args, **kwargs):
+ """OpenFile(self, FileSystem fs, String location) -> FSFile"""
+ return _core_.FileSystemHandler_OpenFile(*args, **kwargs)
+
+ def FindFirst(*args, **kwargs):
+ """FindFirst(self, String spec, int flags=0) -> String"""
+ return _core_.FileSystemHandler_FindFirst(*args, **kwargs)
+
+ def FindNext(*args, **kwargs):
+ """FindNext(self) -> String"""
+ return _core_.FileSystemHandler_FindNext(*args, **kwargs)
+
+ def GetProtocol(*args, **kwargs):
+ """GetProtocol(String location) -> String"""
+ return _core_.FileSystemHandler_GetProtocol(*args, **kwargs)
+
+ GetProtocol = staticmethod(GetProtocol)
+ def GetLeftLocation(*args, **kwargs):
+ """GetLeftLocation(String location) -> String"""
+ return _core_.FileSystemHandler_GetLeftLocation(*args, **kwargs)
+
+ GetLeftLocation = staticmethod(GetLeftLocation)
+ def GetAnchor(*args, **kwargs):
+ """GetAnchor(String location) -> String"""
+ return _core_.FileSystemHandler_GetAnchor(*args, **kwargs)
+
+ GetAnchor = staticmethod(GetAnchor)
+ def GetRightLocation(*args, **kwargs):
+ """GetRightLocation(String location) -> String"""
+ return _core_.FileSystemHandler_GetRightLocation(*args, **kwargs)
+
+ GetRightLocation = staticmethod(GetRightLocation)
+ def GetMimeTypeFromExt(*args, **kwargs):
+ """GetMimeTypeFromExt(String location) -> String"""
+ return _core_.FileSystemHandler_GetMimeTypeFromExt(*args, **kwargs)
+
+ GetMimeTypeFromExt = staticmethod(GetMimeTypeFromExt)
+_core_.FileSystemHandler_swigregister(FileSystemHandler)
+
+def FileSystemHandler_GetProtocol(*args, **kwargs):
+ """FileSystemHandler_GetProtocol(String location) -> String"""
+ return _core_.FileSystemHandler_GetProtocol(*args, **kwargs)
+
+def FileSystemHandler_GetLeftLocation(*args, **kwargs):
+ """FileSystemHandler_GetLeftLocation(String location) -> String"""
+ return _core_.FileSystemHandler_GetLeftLocation(*args, **kwargs)
+
+def FileSystemHandler_GetAnchor(*args, **kwargs):
+ """FileSystemHandler_GetAnchor(String location) -> String"""
+ return _core_.FileSystemHandler_GetAnchor(*args, **kwargs)
+
+def FileSystemHandler_GetRightLocation(*args, **kwargs):
+ """FileSystemHandler_GetRightLocation(String location) -> String"""
+ return _core_.FileSystemHandler_GetRightLocation(*args, **kwargs)
+
+def FileSystemHandler_GetMimeTypeFromExt(*args, **kwargs):
+ """FileSystemHandler_GetMimeTypeFromExt(String location) -> String"""
+ return _core_.FileSystemHandler_GetMimeTypeFromExt(*args, **kwargs)
+
+class FileSystem(Object):
+ """Proxy of C++ FileSystem class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> FileSystem"""
+ _core_.FileSystem_swiginit(self,_core_.new_FileSystem(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_FileSystem
+ __del__ = lambda self : None;
+ def ChangePathTo(*args, **kwargs):
+ """ChangePathTo(self, String location, bool is_dir=False)"""
+ return _core_.FileSystem_ChangePathTo(*args, **kwargs)
+
+ def GetPath(*args, **kwargs):
+ """GetPath(self) -> String"""
+ return _core_.FileSystem_GetPath(*args, **kwargs)
+
+ def OpenFile(*args, **kwargs):
+ """OpenFile(self, String location) -> FSFile"""
+ return _core_.FileSystem_OpenFile(*args, **kwargs)
+
+ def FindFirst(*args, **kwargs):
+ """FindFirst(self, String spec, int flags=0) -> String"""
+ return _core_.FileSystem_FindFirst(*args, **kwargs)
+
+ def FindNext(*args, **kwargs):
+ """FindNext(self) -> String"""
+ return _core_.FileSystem_FindNext(*args, **kwargs)
+
+ def AddHandler(*args, **kwargs):
+ """AddHandler(CPPFileSystemHandler handler)"""
+ return _core_.FileSystem_AddHandler(*args, **kwargs)
+
+ AddHandler = staticmethod(AddHandler)
+ def RemoveHandler(*args, **kwargs):
+ """RemoveHandler(CPPFileSystemHandler handler) -> CPPFileSystemHandler"""
+ return _core_.FileSystem_RemoveHandler(*args, **kwargs)
+
+ RemoveHandler = staticmethod(RemoveHandler)
+ def CleanUpHandlers(*args, **kwargs):
+ """CleanUpHandlers()"""
+ return _core_.FileSystem_CleanUpHandlers(*args, **kwargs)
+
+ CleanUpHandlers = staticmethod(CleanUpHandlers)
+ def FileNameToURL(*args, **kwargs):
+ """FileNameToURL(String filename) -> String"""
+ return _core_.FileSystem_FileNameToURL(*args, **kwargs)
+
+ FileNameToURL = staticmethod(FileNameToURL)
+ def URLToFileName(*args, **kwargs):
+ """URLToFileName(String url) -> String"""
+ return _core_.FileSystem_URLToFileName(*args, **kwargs)
+
+ URLToFileName = staticmethod(URLToFileName)
+ Path = property(GetPath,doc="See `GetPath`")
+_core_.FileSystem_swigregister(FileSystem)
+
+def FileSystem_AddHandler(*args, **kwargs):
+ """FileSystem_AddHandler(CPPFileSystemHandler handler)"""
+ return _core_.FileSystem_AddHandler(*args, **kwargs)
+
+def FileSystem_RemoveHandler(*args, **kwargs):
+ """FileSystem_RemoveHandler(CPPFileSystemHandler handler) -> CPPFileSystemHandler"""
+ return _core_.FileSystem_RemoveHandler(*args, **kwargs)
+
+def FileSystem_CleanUpHandlers(*args):
+ """FileSystem_CleanUpHandlers()"""
+ return _core_.FileSystem_CleanUpHandlers(*args)
+
+def FileSystem_FileNameToURL(*args, **kwargs):
+ """FileSystem_FileNameToURL(String filename) -> String"""
+ return _core_.FileSystem_FileNameToURL(*args, **kwargs)
+
+def FileSystem_URLToFileName(*args, **kwargs):
+ """FileSystem_URLToFileName(String url) -> String"""
+ return _core_.FileSystem_URLToFileName(*args, **kwargs)
+
+class InternetFSHandler(CPPFileSystemHandler):
+ """Proxy of C++ InternetFSHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> InternetFSHandler"""
+ _core_.InternetFSHandler_swiginit(self,_core_.new_InternetFSHandler(*args, **kwargs))
+ def CanOpen(*args, **kwargs):
+ """CanOpen(self, String location) -> bool"""
+ return _core_.InternetFSHandler_CanOpen(*args, **kwargs)
+
+ def OpenFile(*args, **kwargs):
+ """OpenFile(self, FileSystem fs, String location) -> FSFile"""
+ return _core_.InternetFSHandler_OpenFile(*args, **kwargs)
+
+_core_.InternetFSHandler_swigregister(InternetFSHandler)
+
+class ZipFSHandler(CPPFileSystemHandler):
+ """Proxy of C++ ZipFSHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> ZipFSHandler"""
+ _core_.ZipFSHandler_swiginit(self,_core_.new_ZipFSHandler(*args, **kwargs))
+ def CanOpen(*args, **kwargs):
+ """CanOpen(self, String location) -> bool"""
+ return _core_.ZipFSHandler_CanOpen(*args, **kwargs)
+
+ def OpenFile(*args, **kwargs):
+ """OpenFile(self, FileSystem fs, String location) -> FSFile"""
+ return _core_.ZipFSHandler_OpenFile(*args, **kwargs)
+
+ def FindFirst(*args, **kwargs):
+ """FindFirst(self, String spec, int flags=0) -> String"""
+ return _core_.ZipFSHandler_FindFirst(*args, **kwargs)
+
+ def FindNext(*args, **kwargs):
+ """FindNext(self) -> String"""
+ return _core_.ZipFSHandler_FindNext(*args, **kwargs)
+
+_core_.ZipFSHandler_swigregister(ZipFSHandler)
+
+
+def __wxMemoryFSHandler_AddFile_wxImage(*args, **kwargs):
+ """__wxMemoryFSHandler_AddFile_wxImage(String filename, Image image, int type)"""
+ return _core_.__wxMemoryFSHandler_AddFile_wxImage(*args, **kwargs)
+
+def __wxMemoryFSHandler_AddFile_wxBitmap(*args, **kwargs):
+ """__wxMemoryFSHandler_AddFile_wxBitmap(String filename, Bitmap bitmap, int type)"""
+ return _core_.__wxMemoryFSHandler_AddFile_wxBitmap(*args, **kwargs)
+
+def __wxMemoryFSHandler_AddFile_Data(*args, **kwargs):
+ """__wxMemoryFSHandler_AddFile_Data(String filename, buffer data)"""
+ return _core_.__wxMemoryFSHandler_AddFile_Data(*args, **kwargs)
+def MemoryFSHandler_AddFile(filename, dataItem, imgType=-1):
+ """
+ Add 'file' to the memory filesystem. The dataItem parameter can
+ either be a `wx.Bitmap`, `wx.Image` or a string that can contain
+ arbitrary data. If a bitmap or image is used then the imgType
+ parameter should specify what kind of image file it should be
+ written as, wx.BITMAP_TYPE_PNG, etc.
+ """
+ if isinstance(dataItem, wx.Image):
+ __wxMemoryFSHandler_AddFile_wxImage(filename, dataItem, imgType)
+ elif isinstance(dataItem, wx.Bitmap):
+ __wxMemoryFSHandler_AddFile_wxBitmap(filename, dataItem, imgType)
+ else:
+ try:
+ __wxMemoryFSHandler_AddFile_Data(filename, dataItem)
+ except TypeError:
+ raise TypeError, 'wx.Image, wx.Bitmap or buffer object expected'
+
+class MemoryFSHandler(CPPFileSystemHandler):
+ """Proxy of C++ MemoryFSHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> MemoryFSHandler"""
+ _core_.MemoryFSHandler_swiginit(self,_core_.new_MemoryFSHandler(*args, **kwargs))
+ def RemoveFile(*args, **kwargs):
+ """RemoveFile(String filename)"""
+ return _core_.MemoryFSHandler_RemoveFile(*args, **kwargs)
+
+ RemoveFile = staticmethod(RemoveFile)
+ AddFile = staticmethod(MemoryFSHandler_AddFile)
+ def AddFileWithMimeType(*args, **kwargs):
+ """AddFileWithMimeType(String filename, buffer data, String mimetype)"""
+ return _core_.MemoryFSHandler_AddFileWithMimeType(*args, **kwargs)
+
+ AddFileWithMimeType = staticmethod(AddFileWithMimeType)
+ def CanOpen(*args, **kwargs):
+ """CanOpen(self, String location) -> bool"""
+ return _core_.MemoryFSHandler_CanOpen(*args, **kwargs)
+
+ def OpenFile(*args, **kwargs):
+ """OpenFile(self, FileSystem fs, String location) -> FSFile"""
+ return _core_.MemoryFSHandler_OpenFile(*args, **kwargs)
+
+ def FindFirst(*args, **kwargs):
+ """FindFirst(self, String spec, int flags=0) -> String"""
+ return _core_.MemoryFSHandler_FindFirst(*args, **kwargs)
+
+ def FindNext(*args, **kwargs):
+ """FindNext(self) -> String"""
+ return _core_.MemoryFSHandler_FindNext(*args, **kwargs)
+
+_core_.MemoryFSHandler_swigregister(MemoryFSHandler)
+
+def MemoryFSHandler_RemoveFile(*args, **kwargs):
+ """MemoryFSHandler_RemoveFile(String filename)"""
+ return _core_.MemoryFSHandler_RemoveFile(*args, **kwargs)
+
+def MemoryFSHandler_AddFileWithMimeType(*args, **kwargs):
+ """MemoryFSHandler_AddFileWithMimeType(String filename, buffer data, String mimetype)"""
+ return _core_.MemoryFSHandler_AddFileWithMimeType(*args, **kwargs)
+
+IMAGE_ALPHA_TRANSPARENT = _core_.IMAGE_ALPHA_TRANSPARENT
+IMAGE_ALPHA_THRESHOLD = _core_.IMAGE_ALPHA_THRESHOLD
+IMAGE_ALPHA_OPAQUE = _core_.IMAGE_ALPHA_OPAQUE
+IMAGE_QUALITY_NEAREST = _core_.IMAGE_QUALITY_NEAREST
+IMAGE_QUALITY_BILINEAR = _core_.IMAGE_QUALITY_BILINEAR
+IMAGE_QUALITY_BICUBIC = _core_.IMAGE_QUALITY_BICUBIC
+IMAGE_QUALITY_BOX_AVERAGE = _core_.IMAGE_QUALITY_BOX_AVERAGE
+IMAGE_QUALITY_NORMAL = _core_.IMAGE_QUALITY_NORMAL
+IMAGE_QUALITY_HIGH = _core_.IMAGE_QUALITY_HIGH
+#---------------------------------------------------------------------------
+
+class ImageHandler(Object):
+ """
+ This is the base class for implementing image file loading/saving, and
+ image creation from data. It is used within `wx.Image` and is not
+ normally seen by the application.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _core_.ImageHandler_GetName(*args, **kwargs)
+
+ def GetExtension(*args, **kwargs):
+ """GetExtension(self) -> String"""
+ return _core_.ImageHandler_GetExtension(*args, **kwargs)
+
+ def GetAltExtensions(*args, **kwargs):
+ """GetAltExtensions(self) -> wxArrayString"""
+ return _core_.ImageHandler_GetAltExtensions(*args, **kwargs)
+
+ def GetType(*args, **kwargs):
+ """GetType(self) -> int"""
+ return _core_.ImageHandler_GetType(*args, **kwargs)
+
+ def GetMimeType(*args, **kwargs):
+ """GetMimeType(self) -> String"""
+ return _core_.ImageHandler_GetMimeType(*args, **kwargs)
+
+ def CanRead(*args, **kwargs):
+ """CanRead(self, String name) -> bool"""
+ return _core_.ImageHandler_CanRead(*args, **kwargs)
+
+ def CanReadStream(*args, **kwargs):
+ """CanReadStream(self, InputStream stream) -> bool"""
+ return _core_.ImageHandler_CanReadStream(*args, **kwargs)
+
+ def SetName(*args, **kwargs):
+ """SetName(self, String name)"""
+ return _core_.ImageHandler_SetName(*args, **kwargs)
+
+ def SetExtension(*args, **kwargs):
+ """SetExtension(self, String extension)"""
+ return _core_.ImageHandler_SetExtension(*args, **kwargs)
+
+ def SetAltExtensions(*args, **kwargs):
+ """SetAltExtensions(self, wxArrayString exts)"""
+ return _core_.ImageHandler_SetAltExtensions(*args, **kwargs)
+
+ def SetType(*args, **kwargs):
+ """SetType(self, int type)"""
+ return _core_.ImageHandler_SetType(*args, **kwargs)
+
+ def SetMimeType(*args, **kwargs):
+ """SetMimeType(self, String mimetype)"""
+ return _core_.ImageHandler_SetMimeType(*args, **kwargs)
+
+ Extension = property(GetExtension,SetExtension,doc="See `GetExtension` and `SetExtension`")
+ AltExtensions = property(GetAltExtensions,SetAltExtensions)
+ MimeType = property(GetMimeType,SetMimeType,doc="See `GetMimeType` and `SetMimeType`")
+ Name = property(GetName,SetName,doc="See `GetName` and `SetName`")
+ Type = property(GetType,SetType,doc="See `GetType` and `SetType`")
+_core_.ImageHandler_swigregister(ImageHandler)
+
+class PyImageHandler(ImageHandler):
+ """
+ This is the base class for implementing image file loading/saving, and
+ image creation from data, all written in Python. To create a custom
+ image handler derive a new class from wx.PyImageHandler and provide
+ the following methods::
+
+ def DoCanRead(self, stream) --> bool
+ '''Check if this handler can read the image on the stream'''
+
+ def LoadFile(self, image, stream, verbose, index) --> bool
+ '''Load image data from the stream and load it into image.'''
+
+ def SaveFile(self, image, stream, verbose) --> bool
+ '''Save the iamge data in image to the stream using
+ this handler's image file format.'''
+
+ def GetImageCount(self, stream) --> int
+ '''If this image format can hold more than one image,
+ how many does the image on the stream have?'''
+
+ To activate your handler create an instance of it and pass it to
+ `wx.Image_AddHandler`. Be sure to call `SetName`, `SetType`, and
+ `SetExtension` from your constructor.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PyImageHandler
+
+ This is the base class for implementing image file loading/saving, and
+ image creation from data, all written in Python. To create a custom
+ image handler derive a new class from wx.PyImageHandler and provide
+ the following methods::
+
+ def DoCanRead(self, stream) --> bool
+ '''Check if this handler can read the image on the stream'''
+
+ def LoadFile(self, image, stream, verbose, index) --> bool
+ '''Load image data from the stream and load it into image.'''
+
+ def SaveFile(self, image, stream, verbose) --> bool
+ '''Save the iamge data in image to the stream using
+ this handler's image file format.'''
+
+ def GetImageCount(self, stream) --> int
+ '''If this image format can hold more than one image,
+ how many does the image on the stream have?'''
+
+ To activate your handler create an instance of it and pass it to
+ `wx.Image_AddHandler`. Be sure to call `SetName`, `SetType`, and
+ `SetExtension` from your constructor.
+
+ """
+ _core_.PyImageHandler_swiginit(self,_core_.new_PyImageHandler(*args, **kwargs))
+ self._SetSelf(self)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _core_.PyImageHandler__SetSelf(*args, **kwargs)
+
+_core_.PyImageHandler_swigregister(PyImageHandler)
+
+class ImageHistogram(object):
+ """Proxy of C++ ImageHistogram class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> ImageHistogram"""
+ _core_.ImageHistogram_swiginit(self,_core_.new_ImageHistogram(*args, **kwargs))
+ def MakeKey(*args, **kwargs):
+ """
+ MakeKey(byte r, byte g, byte b) -> unsigned long
+
+ Get the key in the histogram for the given RGB values
+ """
+ return _core_.ImageHistogram_MakeKey(*args, **kwargs)
+
+ MakeKey = staticmethod(MakeKey)
+ def FindFirstUnusedColour(*args, **kwargs):
+ """
+ FindFirstUnusedColour(int startR=1, int startG=0, int startB=0) -> (success, r, g, b)
+
+ Find first colour that is not used in the image and has higher RGB
+ values than startR, startG, startB. Returns a tuple consisting of a
+ success flag and rgb values.
+ """
+ return _core_.ImageHistogram_FindFirstUnusedColour(*args, **kwargs)
+
+ def GetCount(*args, **kwargs):
+ """
+ GetCount(self, unsigned long key) -> unsigned long
+
+ Returns the pixel count for the given key. Use `MakeKey` to create a
+ key value from a RGB tripple.
+ """
+ return _core_.ImageHistogram_GetCount(*args, **kwargs)
+
+ def GetCountRGB(*args, **kwargs):
+ """
+ GetCountRGB(self, byte r, byte g, byte b) -> unsigned long
+
+ Returns the pixel count for the given RGB values.
+ """
+ return _core_.ImageHistogram_GetCountRGB(*args, **kwargs)
+
+ def GetCountColour(*args, **kwargs):
+ """
+ GetCountColour(self, Colour colour) -> unsigned long
+
+ Returns the pixel count for the given `wx.Colour` value.
+ """
+ return _core_.ImageHistogram_GetCountColour(*args, **kwargs)
+
+_core_.ImageHistogram_swigregister(ImageHistogram)
+
+def ImageHistogram_MakeKey(*args, **kwargs):
+ """
+ ImageHistogram_MakeKey(byte r, byte g, byte b) -> unsigned long
+
+ Get the key in the histogram for the given RGB values
+ """
+ return _core_.ImageHistogram_MakeKey(*args, **kwargs)
+
+class Image_RGBValue(object):
+ """
+ An object that contains values for red, green and blue which represent
+ the value of a color. It is used by `wx.Image.HSVtoRGB` and
+ `wx.Image.RGBtoHSV`, which converts between HSV color space and RGB
+ color space.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, byte r=0, byte g=0, byte b=0) -> Image_RGBValue
+
+ Constructor.
+ """
+ _core_.Image_RGBValue_swiginit(self,_core_.new_Image_RGBValue(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_Image_RGBValue
+ __del__ = lambda self : None;
+ red = property(_core_.Image_RGBValue_red_get, _core_.Image_RGBValue_red_set)
+ green = property(_core_.Image_RGBValue_green_get, _core_.Image_RGBValue_green_set)
+ blue = property(_core_.Image_RGBValue_blue_get, _core_.Image_RGBValue_blue_set)
+_core_.Image_RGBValue_swigregister(Image_RGBValue)
+
+class Image_HSVValue(object):
+ """
+ An object that contains values for hue, saturation and value which
+ represent the value of a color. It is used by `wx.Image.HSVtoRGB` and
+ `wx.Image.RGBtoHSV`, which converts between HSV color space and RGB
+ color space.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, double h=0.0, double s=0.0, double v=0.0) -> Image_HSVValue
+
+ Constructor.
+ """
+ _core_.Image_HSVValue_swiginit(self,_core_.new_Image_HSVValue(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_Image_HSVValue
+ __del__ = lambda self : None;
+ hue = property(_core_.Image_HSVValue_hue_get, _core_.Image_HSVValue_hue_set)
+ saturation = property(_core_.Image_HSVValue_saturation_get, _core_.Image_HSVValue_saturation_set)
+ value = property(_core_.Image_HSVValue_value_get, _core_.Image_HSVValue_value_set)
+_core_.Image_HSVValue_swigregister(Image_HSVValue)
+
+class Image(Object):
+ """
+ A platform-independent image class. An image can be created from
+ data, or using `wx.Bitmap.ConvertToImage`, or loaded from a file in a
+ variety of formats. Functions are available to set and get image
+ bits, so it can be used for basic image manipulation.
+
+ A wx.Image cannot be drawn directly to a `wx.DC`. Instead, a
+ platform-specific `wx.Bitmap` object must be created from it using the
+ `wx.BitmapFromImage` constructor. This bitmap can then be drawn in a
+ device context, using `wx.DC.DrawBitmap`.
+
+ One colour value of the image may be used as a mask colour which will
+ lead to the automatic creation of a `wx.Mask` object associated to the
+ bitmap object.
+
+ wx.Image supports alpha channel data, that is in addition to a byte
+ for the red, green and blue colour components for each pixel it also
+ stores a byte representing the pixel opacity. An alpha value of 0
+ corresponds to a transparent pixel (null opacity) while a value of 255
+ means that the pixel is 100% opaque.
+
+ Unlike RGB data, not all images have an alpha channel and before using
+ `GetAlpha` you should check if this image contains an alpha channel
+ with `HasAlpha`. Note that currently only images loaded from PNG files
+ with transparency information will have an alpha channel.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String name, int type=BITMAP_TYPE_ANY, int index=-1) -> Image
+
+ Loads an image from a file.
+ """
+ _core_.Image_swiginit(self,_core_.new_Image(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_Image
+ __del__ = lambda self : None;
+ def Create(*args, **kwargs):
+ """
+ Create(self, int width, int height, bool clear=True)
+
+ Creates a fresh image. If clear is ``True``, the new image will be
+ initialized to black. Otherwise, the image data will be uninitialized.
+ """
+ return _core_.Image_Create(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """
+ Destroy(self)
+
+ Destroys the image data.
+ """
+ args[0].this.own(False)
+ return _core_.Image_Destroy(*args, **kwargs)
+
+ def Scale(*args, **kwargs):
+ """
+ Scale(self, int width, int height, int quality=IMAGE_QUALITY_NORMAL) -> Image
+
+ Returns a scaled version of the image. This is also useful for scaling
+ bitmaps in general as the only other way to scale bitmaps is to blit a
+ `wx.MemoryDC` into another `wx.MemoryDC`. The ``quality`` parameter
+ specifies what method to use for resampling the image. It can be
+ either wx.IMAGE_QUALITY_NORMAL, which uses the normal default scaling
+ method of pixel replication, or wx.IMAGE_QUALITY_HIGH which uses
+ bicubic and box averaging resampling methods for upsampling and
+ downsampling respectively.
+ """
+ return _core_.Image_Scale(*args, **kwargs)
+
+ def ResampleNearest(*args, **kwargs):
+ """ResampleNearest(self, int width, int height) -> Image"""
+ return _core_.Image_ResampleNearest(*args, **kwargs)
+
+ def ResampleBox(*args, **kwargs):
+ """ResampleBox(self, int width, int height) -> Image"""
+ return _core_.Image_ResampleBox(*args, **kwargs)
+
+ def ResampleBilinear(*args, **kwargs):
+ """ResampleBilinear(self, int width, int height) -> Image"""
+ return _core_.Image_ResampleBilinear(*args, **kwargs)
+
+ def ResampleBicubic(*args, **kwargs):
+ """ResampleBicubic(self, int width, int height) -> Image"""
+ return _core_.Image_ResampleBicubic(*args, **kwargs)
+
+ def Blur(*args, **kwargs):
+ """
+ Blur(self, int radius) -> Image
+
+ Blurs the image in both horizontal and vertical directions by the
+ specified pixel ``radius``. This should not be used when using a
+ single mask colour for transparency.
+ """
+ return _core_.Image_Blur(*args, **kwargs)
+
+ def BlurHorizontal(*args, **kwargs):
+ """
+ BlurHorizontal(self, int radius) -> Image
+
+ Blurs the image in the horizontal direction only. This should not be
+ used when using a single mask colour for transparency.
+
+ """
+ return _core_.Image_BlurHorizontal(*args, **kwargs)
+
+ def BlurVertical(*args, **kwargs):
+ """
+ BlurVertical(self, int radius) -> Image
+
+ Blurs the image in the vertical direction only. This should not be
+ used when using a single mask colour for transparency.
+ """
+ return _core_.Image_BlurVertical(*args, **kwargs)
+
+ def ShrinkBy(*args, **kwargs):
+ """
+ ShrinkBy(self, int xFactor, int yFactor) -> Image
+
+ Return a version of the image scaled smaller by the given factors.
+ """
+ return _core_.Image_ShrinkBy(*args, **kwargs)
+
+ def Rescale(*args, **kwargs):
+ """
+ Rescale(self, int width, int height, int quality=IMAGE_QUALITY_NORMAL) -> Image
+
+ Changes the size of the image in-place by scaling it: after a call to
+ this function, the image will have the given width and height.
+
+ Returns the (modified) image itself.
+ """
+ return _core_.Image_Rescale(*args, **kwargs)
+
+ def Resize(*args, **kwargs):
+ """
+ Resize(self, Size size, Point pos, int r=-1, int g=-1, int b=-1) -> Image
+
+ Changes the size of the image in-place without scaling it, by adding
+ either a border with the given colour or cropping as necessary. The
+ image is pasted into a new image with the given size and background
+ colour at the position pos relative to the upper left of the new
+ image. If red = green = blue = -1 then use either the current mask
+ colour if set or find, use, and set a suitable mask colour for any
+ newly exposed areas.
+
+ Returns the (modified) image itself.
+ """
+ return _core_.Image_Resize(*args, **kwargs)
+
+ def SetRGB(*args, **kwargs):
+ """
+ SetRGB(self, int x, int y, byte r, byte g, byte b)
+
+ Sets the pixel at the given coordinate. This routine performs
+ bounds-checks for the coordinate so it can be considered a safe way to
+ manipulate the data, but in some cases this might be too slow so that
+ the data will have to be set directly. In that case you will have to
+ get access to the image data using the `GetData` method.
+ """
+ return _core_.Image_SetRGB(*args, **kwargs)
+
+ def SetRGBRect(*args, **kwargs):
+ """
+ SetRGBRect(self, Rect rect, byte r, byte g, byte b)
+
+ Sets the colour of the pixels within the given rectangle. This routine
+ performs bounds-checks for the rectangle so it can be considered a
+ safe way to manipulate the data.
+ """
+ return _core_.Image_SetRGBRect(*args, **kwargs)
+
+ def GetRed(*args, **kwargs):
+ """
+ GetRed(self, int x, int y) -> byte
+
+ Returns the red intensity at the given coordinate.
+ """
+ return _core_.Image_GetRed(*args, **kwargs)
+
+ def GetGreen(*args, **kwargs):
+ """
+ GetGreen(self, int x, int y) -> byte
+
+ Returns the green intensity at the given coordinate.
+ """
+ return _core_.Image_GetGreen(*args, **kwargs)
+
+ def GetBlue(*args, **kwargs):
+ """
+ GetBlue(self, int x, int y) -> byte
+
+ Returns the blue intensity at the given coordinate.
+ """
+ return _core_.Image_GetBlue(*args, **kwargs)
+
+ def SetAlpha(*args, **kwargs):
+ """
+ SetAlpha(self, int x, int y, byte alpha)
+
+ Sets the alpha value for the given pixel. This function should only be
+ called if the image has alpha channel data, use `HasAlpha` to check
+ for this.
+ """
+ return _core_.Image_SetAlpha(*args, **kwargs)
+
+ def GetAlpha(*args, **kwargs):
+ """
+ GetAlpha(self, int x, int y) -> byte
+
+ Returns the alpha value for the given pixel. This function may only be
+ called for the images with alpha channel, use `HasAlpha` to check for
+ this.
+
+ The returned value is the *opacity* of the image, i.e. the value of 0
+ corresponds to the fully transparent pixels while the value of 255 to
+ the fully opaque pixels.
+ """
+ return _core_.Image_GetAlpha(*args, **kwargs)
+
+ def HasAlpha(*args, **kwargs):
+ """
+ HasAlpha(self) -> bool
+
+ Returns true if this image has alpha channel, false otherwise.
+ """
+ return _core_.Image_HasAlpha(*args, **kwargs)
+
+ def InitAlpha(*args, **kwargs):
+ """
+ InitAlpha(self)
+
+ Initializes the image alpha channel data. It is an error to call it if
+ the image already has alpha data. If it doesn't, alpha data will be by
+ default initialized to all pixels being fully opaque. But if the image
+ has a a mask colour, all mask pixels will be completely transparent.
+ """
+ return _core_.Image_InitAlpha(*args, **kwargs)
+
+ def ClearAlpha(*args, **kwargs):
+ """ClearAlpha(self)"""
+ return _core_.Image_ClearAlpha(*args, **kwargs)
+
+ def IsTransparent(*args, **kwargs):
+ """
+ IsTransparent(self, int x, int y, byte threshold=IMAGE_ALPHA_THRESHOLD) -> bool
+
+ Returns ``True`` if this pixel is masked or has an alpha value less
+ than the spcified threshold.
+ """
+ return _core_.Image_IsTransparent(*args, **kwargs)
+
+ def FindFirstUnusedColour(*args, **kwargs):
+ """
+ FindFirstUnusedColour(int startR=1, int startG=0, int startB=0) -> (success, r, g, b)
+
+ Find first colour that is not used in the image and has higher RGB
+ values than startR, startG, startB. Returns a tuple consisting of a
+ success flag and rgb values.
+ """
+ return _core_.Image_FindFirstUnusedColour(*args, **kwargs)
+
+ def ConvertAlphaToMask(*args, **kwargs):
+ """
+ ConvertAlphaToMask(self, byte threshold=IMAGE_ALPHA_THRESHOLD) -> bool
+
+ If the image has alpha channel, this method converts it to mask. All
+ pixels with alpha value less than ``threshold`` are replaced with the
+ mask colour and the alpha channel is removed. The mask colour is
+ chosen automatically using `FindFirstUnusedColour`.
+
+ If the image image doesn't have alpha channel, ConvertAlphaToMask does
+ nothing.
+ """
+ return _core_.Image_ConvertAlphaToMask(*args, **kwargs)
+
+ def ConvertColourToAlpha(*args, **kwargs):
+ """
+ ConvertColourToAlpha(self, byte r, byte g, byte b) -> bool
+
+ This method converts an image where the original alpha information is
+ only available as a shades of a colour (actually shades of grey)
+ typically when you draw anti-aliased text into a bitmap. The DC
+ drawing routines draw grey values on the black background although
+ they actually mean to draw white with differnt alpha values. This
+ method reverses it, assuming a black (!) background and white text.
+ The method will then fill up the whole image with the colour given.
+ """
+ return _core_.Image_ConvertColourToAlpha(*args, **kwargs)
+
+ def SetMaskFromImage(*args, **kwargs):
+ """
+ SetMaskFromImage(self, Image mask, byte mr, byte mg, byte mb) -> bool
+
+ Sets the image's mask so that the pixels that have RGB value of
+ ``(mr,mg,mb)`` in ``mask`` will be masked in this image. This is done
+ by first finding an unused colour in the image, setting this colour as
+ the mask colour and then using this colour to draw all pixels in the
+ image who corresponding pixel in mask has given RGB value.
+
+ Returns ``False`` if ``mask`` does not have same dimensions as the
+ image or if there is no unused colour left. Returns ``True`` if the
+ mask was successfully applied.
+
+ Note that this method involves computing the histogram, which is
+ computationally intensive operation.
+ """
+ return _core_.Image_SetMaskFromImage(*args, **kwargs)
+
+ def CanRead(*args, **kwargs):
+ """
+ CanRead(String filename) -> bool
+
+ Returns True if the image handlers can read this file.
+ """
+ return _core_.Image_CanRead(*args, **kwargs)
+
+ CanRead = staticmethod(CanRead)
+ def GetImageCount(*args, **kwargs):
+ """
+ GetImageCount(String filename, int type=BITMAP_TYPE_ANY) -> int
+
+ If the image file contains more than one image and the image handler
+ is capable of retrieving these individually, this function will return
+ the number of available images.
+ """
+ return _core_.Image_GetImageCount(*args, **kwargs)
+
+ GetImageCount = staticmethod(GetImageCount)
+ def LoadFile(*args, **kwargs):
+ """
+ LoadFile(self, String name, int type=BITMAP_TYPE_ANY, int index=-1) -> bool
+
+ Loads an image from a file. If no handler type is provided, the
+ library will try to autodetect the format.
+ """
+ return _core_.Image_LoadFile(*args, **kwargs)
+
+ def LoadMimeFile(*args, **kwargs):
+ """
+ LoadMimeFile(self, String name, String mimetype, int index=-1) -> bool
+
+ Loads an image from a file, specifying the image type with a MIME type
+ string.
+ """
+ return _core_.Image_LoadMimeFile(*args, **kwargs)
+
+ def SaveFile(*args, **kwargs):
+ """
+ SaveFile(self, String name, int type) -> bool
+
+ Saves an image in the named file.
+ """
+ return _core_.Image_SaveFile(*args, **kwargs)
+
+ def SaveMimeFile(*args, **kwargs):
+ """
+ SaveMimeFile(self, String name, String mimetype) -> bool
+
+ Saves an image in the named file.
+ """
+ return _core_.Image_SaveMimeFile(*args, **kwargs)
+
+ def SaveStream(*args, **kwargs):
+ """
+ SaveStream(self, wxOutputStream stream, int type) -> bool
+
+ Saves an image in the named file.
+ """
+ return _core_.Image_SaveStream(*args, **kwargs)
+
+ def SaveMimeStream(*args, **kwargs):
+ """
+ SaveMimeStream(self, wxOutputStream stream, String mimetype) -> bool
+
+ Saves an image in the named file.
+ """
+ return _core_.Image_SaveMimeStream(*args, **kwargs)
+
+ def CanReadStream(*args, **kwargs):
+ """
+ CanReadStream(InputStream stream) -> bool
+
+ Returns True if the image handlers can read an image file from the
+ data currently on the input stream, or a readable Python file-like
+ object.
+ """
+ return _core_.Image_CanReadStream(*args, **kwargs)
+
+ CanReadStream = staticmethod(CanReadStream)
+ def LoadStream(*args, **kwargs):
+ """
+ LoadStream(self, InputStream stream, int type=BITMAP_TYPE_ANY, int index=-1) -> bool
+
+ Loads an image from an input stream or a readable Python file-like
+ object. If no handler type is provided, the library will try to
+ autodetect the format.
+ """
+ return _core_.Image_LoadStream(*args, **kwargs)
+
+ def LoadMimeStream(*args, **kwargs):
+ """
+ LoadMimeStream(self, InputStream stream, String mimetype, int index=-1) -> bool
+
+ Loads an image from an input stream or a readable Python file-like
+ object, using a MIME type string to specify the image file format.
+ """
+ return _core_.Image_LoadMimeStream(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """
+ IsOk(self) -> bool
+
+ Returns true if image data is present.
+ """
+ return _core_.Image_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def GetWidth(*args, **kwargs):
+ """
+ GetWidth(self) -> int
+
+ Gets the width of the image in pixels.
+ """
+ return _core_.Image_GetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """
+ GetHeight(self) -> int
+
+ Gets the height of the image in pixels.
+ """
+ return _core_.Image_GetHeight(*args, **kwargs)
+
+ def GetType(*args, **kwargs):
+ """
+ GetType(self) -> int
+
+ Gets the type of image found by LoadFile or specified with SaveFile
+ """
+ return _core_.Image_GetType(*args, **kwargs)
+
+ def SetType(*args, **kwargs):
+ """
+ SetType(self, int type)
+
+ Set the image type, this is normally only called if the image is being
+ created from data in the given format but not using LoadFile() (e.g.
+ wxGIFDecoder uses this)
+
+ """
+ return _core_.Image_SetType(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """
+ GetSize(self) -> Size
+
+ Returns the size of the image in pixels.
+ """
+ return _core_.Image_GetSize(*args, **kwargs)
+
+ def GetSubImage(*args, **kwargs):
+ """
+ GetSubImage(self, Rect rect) -> Image
+
+ Returns a sub image of the current one as long as the rect belongs
+ entirely to the image.
+ """
+ return _core_.Image_GetSubImage(*args, **kwargs)
+
+ def Size(*args, **kwargs):
+ """
+ Size(self, Size size, Point pos, int r=-1, int g=-1, int b=-1) -> Image
+
+ Returns a resized version of this image without scaling it by adding
+ either a border with the given colour or cropping as necessary. The
+ image is pasted into a new image with the given size and background
+ colour at the position ``pos`` relative to the upper left of the new
+ image. If red = green = blue = -1 then use either the current mask
+ colour if set or find, use, and set a suitable mask colour for any
+ newly exposed areas.
+ """
+ return _core_.Image_Size(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """
+ Clear(self, unsigned char value=0)
+
+ initialize the image data with zeroes
+ """
+ return _core_.Image_Clear(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """
+ Copy(self) -> Image
+
+ Returns an identical copy of the image.
+ """
+ return _core_.Image_Copy(*args, **kwargs)
+
+ def Paste(*args, **kwargs):
+ """
+ Paste(self, Image image, int x, int y)
+
+ Pastes ``image`` into this instance and takes care of the mask colour
+ and any out of bounds problems.
+ """
+ return _core_.Image_Paste(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """
+ GetData(self) -> PyObject
+
+ Returns a string containing a copy of the RGB bytes of the image.
+ """
+ return _core_.Image_GetData(*args, **kwargs)
+
+ def SetData(*args, **kwargs):
+ """
+ SetData(self, buffer data)
+
+ Resets the Image's RGB data from a buffer of RGB bytes. Accepts
+ either a string or a buffer object holding the data and the length of
+ the data must be width*height*3.
+ """
+ return _core_.Image_SetData(*args, **kwargs)
+
+ def GetDataBuffer(*args, **kwargs):
+ """
+ GetDataBuffer(self) -> PyObject
+
+ Returns a writable Python buffer object that is pointing at the RGB
+ image data buffer inside the wx.Image. You need to ensure that you do
+ not use this buffer object after the image has been destroyed.
+ """
+ return _core_.Image_GetDataBuffer(*args, **kwargs)
+
+ def SetDataBuffer(*args, **kwargs):
+ """
+ SetDataBuffer(self, buffer data)
+
+ Sets the internal image data pointer to point at a Python buffer
+ object. This can save making an extra copy of the data but you must
+ ensure that the buffer object lives longer than the wx.Image does.
+ """
+ return _core_.Image_SetDataBuffer(*args, **kwargs)
+
+ def GetAlphaData(*args, **kwargs):
+ """
+ GetAlphaData(self) -> PyObject
+
+ Returns a string containing a copy of the alpha bytes of the image.
+ """
+ return _core_.Image_GetAlphaData(*args, **kwargs)
+
+ def SetAlphaData(*args, **kwargs):
+ """
+ SetAlphaData(self, buffer alpha)
+
+ Resets the Image's alpha data from a buffer of bytes. Accepts either
+ a string or a buffer object holding the data and the length of the
+ data must be width*height.
+ """
+ return _core_.Image_SetAlphaData(*args, **kwargs)
+
+ def GetAlphaBuffer(*args, **kwargs):
+ """
+ GetAlphaBuffer(self) -> PyObject
+
+ Returns a writable Python buffer object that is pointing at the Alpha
+ data buffer inside the wx.Image. You need to ensure that you do not
+ use this buffer object after the image has been destroyed.
+ """
+ return _core_.Image_GetAlphaBuffer(*args, **kwargs)
+
+ def SetAlphaBuffer(*args, **kwargs):
+ """
+ SetAlphaBuffer(self, buffer alpha)
+
+ Sets the internal image alpha pointer to point at a Python buffer
+ object. This can save making an extra copy of the data but you must
+ ensure that the buffer object lives as long as the wx.Image does.
+ """
+ return _core_.Image_SetAlphaBuffer(*args, **kwargs)
+
+ def SetMaskColour(*args, **kwargs):
+ """
+ SetMaskColour(self, byte r, byte g, byte b)
+
+ Sets the mask colour for this image (and tells the image to use the
+ mask).
+ """
+ return _core_.Image_SetMaskColour(*args, **kwargs)
+
+ def GetOrFindMaskColour(*args, **kwargs):
+ """
+ GetOrFindMaskColour() -> (r,g,b)
+
+ Get the current mask colour or find a suitable colour.
+ """
+ return _core_.Image_GetOrFindMaskColour(*args, **kwargs)
+
+ def GetMaskRed(*args, **kwargs):
+ """
+ GetMaskRed(self) -> byte
+
+ Gets the red component of the mask colour.
+ """
+ return _core_.Image_GetMaskRed(*args, **kwargs)
+
+ def GetMaskGreen(*args, **kwargs):
+ """
+ GetMaskGreen(self) -> byte
+
+ Gets the green component of the mask colour.
+ """
+ return _core_.Image_GetMaskGreen(*args, **kwargs)
+
+ def GetMaskBlue(*args, **kwargs):
+ """
+ GetMaskBlue(self) -> byte
+
+ Gets the blue component of the mask colour.
+ """
+ return _core_.Image_GetMaskBlue(*args, **kwargs)
+
+ def SetMask(*args, **kwargs):
+ """
+ SetMask(self, bool mask=True)
+
+ Specifies whether there is a mask or not. The area of the mask is
+ determined by the current mask colour.
+ """
+ return _core_.Image_SetMask(*args, **kwargs)
+
+ def HasMask(*args, **kwargs):
+ """
+ HasMask(self) -> bool
+
+ Returns ``True`` if there is a mask active, ``False`` otherwise.
+ """
+ return _core_.Image_HasMask(*args, **kwargs)
+
+ def Rotate(*args, **kwargs):
+ """
+ Rotate(self, double angle, Point centre_of_rotation, bool interpolating=True,
+ Point offset_after_rotation=None) -> Image
+
+ Rotates the image about the given point, by ``angle`` radians. Passing
+ ``True`` to ``interpolating`` results in better image quality, but is
+ slower. If the image has a mask, then the mask colour is used for the
+ uncovered pixels in the rotated image background. Otherwise, black
+ will be used as the fill colour.
+
+ Returns the rotated image, leaving this image intact.
+ """
+ return _core_.Image_Rotate(*args, **kwargs)
+
+ def Rotate90(*args, **kwargs):
+ """
+ Rotate90(self, bool clockwise=True) -> Image
+
+ Returns a copy of the image rotated 90 degrees in the direction
+ indicated by ``clockwise``.
+ """
+ return _core_.Image_Rotate90(*args, **kwargs)
+
+ def Rotate180(*args, **kwargs):
+ """Rotate180(self) -> Image"""
+ return _core_.Image_Rotate180(*args, **kwargs)
+
+ def Mirror(*args, **kwargs):
+ """
+ Mirror(self, bool horizontally=True) -> Image
+
+ Returns a mirrored copy of the image. The parameter ``horizontally``
+ indicates the orientation.
+ """
+ return _core_.Image_Mirror(*args, **kwargs)
+
+ def Replace(*args, **kwargs):
+ """
+ Replace(self, byte r1, byte g1, byte b1, byte r2, byte g2, byte b2)
+
+ Replaces the colour specified by ``(r1,g1,b1)`` by the colour
+ ``(r2,g2,b2)``.
+ """
+ return _core_.Image_Replace(*args, **kwargs)
+
+ def ConvertToGreyscale(*args):
+ """
+ ConvertToGreyscale(self) -> Image
+ ConvertToGreyscale(self, double lr, double lg, double lb) -> Image
+
+ Convert to greyscale image. Uses the luminance component (Y) of the
+ image. The luma value (YUV) is calculated using (R * lr) + (G * lg) + (B * lb),
+ defaults to ITU-T BT.601
+ """
+ return _core_.Image_ConvertToGreyscale(*args)
+
+ def ConvertToMono(*args, **kwargs):
+ """
+ ConvertToMono(self, byte r, byte g, byte b) -> Image
+
+ Returns monochromatic version of the image. The returned image has
+ white colour where the original has ``(r,g,b)`` colour and black
+ colour everywhere else.
+ """
+ return _core_.Image_ConvertToMono(*args, **kwargs)
+
+ def ConvertToDisabled(*args, **kwargs):
+ """ConvertToDisabled(self, unsigned char brightness=255) -> Image"""
+ return _core_.Image_ConvertToDisabled(*args, **kwargs)
+
+ def SetOption(*args, **kwargs):
+ """
+ SetOption(self, String name, String value)
+
+ Sets an image handler defined option. For example, when saving as a
+ JPEG file, the option ``wx.IMAGE_OPTION_QUALITY`` is used, which is a
+ number between 0 and 100 (0 is terrible, 100 is very good).
+ """
+ return _core_.Image_SetOption(*args, **kwargs)
+
+ def SetOptionInt(*args, **kwargs):
+ """
+ SetOptionInt(self, String name, int value)
+
+ Sets an image option as an integer.
+ """
+ return _core_.Image_SetOptionInt(*args, **kwargs)
+
+ def GetOption(*args, **kwargs):
+ """
+ GetOption(self, String name) -> String
+
+ Gets the value of an image handler option.
+ """
+ return _core_.Image_GetOption(*args, **kwargs)
+
+ def GetOptionInt(*args, **kwargs):
+ """
+ GetOptionInt(self, String name) -> int
+
+ Gets the value of an image handler option as an integer. If the given
+ option is not present, the function returns 0.
+ """
+ return _core_.Image_GetOptionInt(*args, **kwargs)
+
+ def HasOption(*args, **kwargs):
+ """
+ HasOption(self, String name) -> bool
+
+ Returns true if the given option is present.
+ """
+ return _core_.Image_HasOption(*args, **kwargs)
+
+ def CountColours(*args, **kwargs):
+ """CountColours(self, unsigned long stopafter=(unsigned long) -1) -> unsigned long"""
+ return _core_.Image_CountColours(*args, **kwargs)
+
+ def ComputeHistogram(*args, **kwargs):
+ """ComputeHistogram(self, ImageHistogram h) -> unsigned long"""
+ return _core_.Image_ComputeHistogram(*args, **kwargs)
+
+ def AddHandler(*args, **kwargs):
+ """AddHandler(ImageHandler handler)"""
+ return _core_.Image_AddHandler(*args, **kwargs)
+
+ AddHandler = staticmethod(AddHandler)
+ def InsertHandler(*args, **kwargs):
+ """InsertHandler(ImageHandler handler)"""
+ return _core_.Image_InsertHandler(*args, **kwargs)
+
+ InsertHandler = staticmethod(InsertHandler)
+ def RemoveHandler(*args, **kwargs):
+ """RemoveHandler(String name) -> bool"""
+ return _core_.Image_RemoveHandler(*args, **kwargs)
+
+ RemoveHandler = staticmethod(RemoveHandler)
+ def GetHandlers(*args, **kwargs):
+ """GetHandlers() -> PyObject"""
+ return _core_.Image_GetHandlers(*args, **kwargs)
+
+ GetHandlers = staticmethod(GetHandlers)
+ def GetImageExtWildcard(*args, **kwargs):
+ """
+ GetImageExtWildcard() -> String
+
+ Iterates all registered wxImageHandler objects, and returns a string
+ containing file extension masks suitable for passing to file open/save
+ dialog boxes.
+ """
+ return _core_.Image_GetImageExtWildcard(*args, **kwargs)
+
+ GetImageExtWildcard = staticmethod(GetImageExtWildcard)
+ def ConvertToBitmap(*args, **kwargs):
+ """ConvertToBitmap(self, int depth=-1) -> Bitmap"""
+ return _core_.Image_ConvertToBitmap(*args, **kwargs)
+
+ def ConvertToMonoBitmap(*args, **kwargs):
+ """ConvertToMonoBitmap(self, byte red, byte green, byte blue) -> Bitmap"""
+ return _core_.Image_ConvertToMonoBitmap(*args, **kwargs)
+
+ def RotateHue(*args, **kwargs):
+ """
+ RotateHue(self, double angle)
+
+ Rotates the hue of each pixel of the image. Hue is a double in the
+ range -1.0..1.0 where -1.0 is -360 degrees and 1.0 is 360 degrees
+ """
+ return _core_.Image_RotateHue(*args, **kwargs)
+
+ def RGBtoHSV(*args, **kwargs):
+ """
+ RGBtoHSV(Image_RGBValue rgb) -> Image_HSVValue
+
+ Converts a color in RGB color space to HSV color space.
+ """
+ return _core_.Image_RGBtoHSV(*args, **kwargs)
+
+ RGBtoHSV = staticmethod(RGBtoHSV)
+ def HSVtoRGB(*args, **kwargs):
+ """
+ HSVtoRGB(Image_HSVValue hsv) -> Image_RGBValue
+
+ Converts a color in HSV color space to RGB color space.
+ """
+ return _core_.Image_HSVtoRGB(*args, **kwargs)
+
+ HSVtoRGB = staticmethod(HSVtoRGB)
+ def __nonzero__(self): return self.IsOk()
+ def AdjustChannels(*args, **kwargs):
+ """
+ AdjustChannels(self, double factor_red, double factor_green, double factor_blue,
+ double factor_alpha=1.0) -> Image
+
+ This function muliplies all 4 channels (red, green, blue, alpha) with
+ a factor (around 1.0). Useful for gamma correction, colour correction
+ and to add a certain amount of transparency to a image (fade in fade
+ out effects). If factor_alpha is given but the original image has no
+ alpha channel then a alpha channel will be added.
+ """
+ return _core_.Image_AdjustChannels(*args, **kwargs)
+
+ AlphaBuffer = property(GetAlphaBuffer,SetAlphaBuffer,doc="See `GetAlphaBuffer` and `SetAlphaBuffer`")
+ AlphaData = property(GetAlphaData,SetAlphaData,doc="See `GetAlphaData` and `SetAlphaData`")
+ Data = property(GetData,SetData,doc="See `GetData` and `SetData`")
+ DataBuffer = property(GetDataBuffer,SetDataBuffer,doc="See `GetDataBuffer` and `SetDataBuffer`")
+ Height = property(GetHeight,doc="See `GetHeight`")
+ MaskBlue = property(GetMaskBlue,doc="See `GetMaskBlue`")
+ MaskGreen = property(GetMaskGreen,doc="See `GetMaskGreen`")
+ MaskRed = property(GetMaskRed,doc="See `GetMaskRed`")
+ Width = property(GetWidth,doc="See `GetWidth`")
+_core_.Image_swigregister(Image)
+
+def ImageFromMime(*args, **kwargs):
+ """
+ ImageFromMime(String name, String mimetype, int index=-1) -> Image
+
+ Loads an image from a file, using a MIME type string (such as
+ 'image/jpeg') to specify image type.
+ """
+ val = _core_.new_ImageFromMime(*args, **kwargs)
+ return val
+
+def ImageFromStream(*args, **kwargs):
+ """
+ ImageFromStream(InputStream stream, int type=BITMAP_TYPE_ANY, int index=-1) -> Image
+
+ Loads an image from an input stream, or any readable Python file-like
+ object.
+ """
+ val = _core_.new_ImageFromStream(*args, **kwargs)
+ return val
+
+def ImageFromStreamMime(*args, **kwargs):
+ """
+ ImageFromStreamMime(InputStream stream, String mimetype, int index=-1) -> Image
+
+ Loads an image from an input stream, or any readable Python file-like
+ object, specifying the image format with a MIME type string.
+ """
+ val = _core_.new_ImageFromStreamMime(*args, **kwargs)
+ return val
+
+def EmptyImage(*args, **kwargs):
+ """
+ EmptyImage(int width=0, int height=0, bool clear=True) -> Image
+
+ Construct an empty image of a given size, optionally setting all
+ pixels to black.
+ """
+ val = _core_.new_EmptyImage(*args, **kwargs)
+ return val
+
+def ImageFromBitmap(*args, **kwargs):
+ """
+ ImageFromBitmap(Bitmap bitmap) -> Image
+
+ Construct an Image from a `wx.Bitmap`.
+ """
+ val = _core_.new_ImageFromBitmap(*args, **kwargs)
+ return val
+
+def ImageFromData(*args, **kwargs):
+ """
+ ImageFromData(int width, int height, buffer data) -> Image
+
+ Construct an Image from a buffer of RGB bytes. Accepts either a
+ string or a buffer object holding the data and the length of the data
+ must be width*height*3.
+ """
+ val = _core_.new_ImageFromData(*args, **kwargs)
+ return val
+
+def ImageFromDataWithAlpha(*args, **kwargs):
+ """
+ ImageFromDataWithAlpha(int width, int height, buffer data, buffer alpha) -> Image
+
+ Construct an Image from a buffer of RGB bytes with an Alpha channel.
+ Accepts either a string or a buffer object holding the data and the
+ length of the data must be width*height*3 bytes, and the length of the
+ alpha data must be width*height bytes.
+ """
+ val = _core_.new_ImageFromDataWithAlpha(*args, **kwargs)
+ return val
+
+def Image_CanRead(*args, **kwargs):
+ """
+ Image_CanRead(String filename) -> bool
+
+ Returns True if the image handlers can read this file.
+ """
+ return _core_.Image_CanRead(*args, **kwargs)
+
+def Image_GetImageCount(*args, **kwargs):
+ """
+ Image_GetImageCount(String filename, int type=BITMAP_TYPE_ANY) -> int
+
+ If the image file contains more than one image and the image handler
+ is capable of retrieving these individually, this function will return
+ the number of available images.
+ """
+ return _core_.Image_GetImageCount(*args, **kwargs)
+
+def Image_CanReadStream(*args, **kwargs):
+ """
+ Image_CanReadStream(InputStream stream) -> bool
+
+ Returns True if the image handlers can read an image file from the
+ data currently on the input stream, or a readable Python file-like
+ object.
+ """
+ return _core_.Image_CanReadStream(*args, **kwargs)
+
+def Image_AddHandler(*args, **kwargs):
+ """Image_AddHandler(ImageHandler handler)"""
+ return _core_.Image_AddHandler(*args, **kwargs)
+
+def Image_InsertHandler(*args, **kwargs):
+ """Image_InsertHandler(ImageHandler handler)"""
+ return _core_.Image_InsertHandler(*args, **kwargs)
+
+def Image_RemoveHandler(*args, **kwargs):
+ """Image_RemoveHandler(String name) -> bool"""
+ return _core_.Image_RemoveHandler(*args, **kwargs)
+
+def Image_GetHandlers(*args):
+ """Image_GetHandlers() -> PyObject"""
+ return _core_.Image_GetHandlers(*args)
+
+def Image_GetImageExtWildcard(*args):
+ """
+ Image_GetImageExtWildcard() -> String
+
+ Iterates all registered wxImageHandler objects, and returns a string
+ containing file extension masks suitable for passing to file open/save
+ dialog boxes.
+ """
+ return _core_.Image_GetImageExtWildcard(*args)
+
+def Image_RGBtoHSV(*args, **kwargs):
+ """
+ Image_RGBtoHSV(Image_RGBValue rgb) -> Image_HSVValue
+
+ Converts a color in RGB color space to HSV color space.
+ """
+ return _core_.Image_RGBtoHSV(*args, **kwargs)
+
+def Image_HSVtoRGB(*args, **kwargs):
+ """
+ Image_HSVtoRGB(Image_HSVValue hsv) -> Image_RGBValue
+
+ Converts a color in HSV color space to RGB color space.
+ """
+ return _core_.Image_HSVtoRGB(*args, **kwargs)
+
+
+def _ImageFromBuffer(*args, **kwargs):
+ """_ImageFromBuffer(int width, int height, buffer data, buffer alpha=None) -> Image"""
+ return _core_._ImageFromBuffer(*args, **kwargs)
+def ImageFromBuffer(width, height, dataBuffer, alphaBuffer=None):
+ """
+ Creates a `wx.Image` from the data in dataBuffer. The dataBuffer
+ parameter must be a Python object that implements the buffer interface,
+ such as a string, array, etc. The dataBuffer object is expected to
+ contain a series of RGB bytes and be width*height*3 bytes long. A buffer
+ object can optionally be supplied for the image's alpha channel data, and
+ it is expected to be width*height bytes long.
+
+ The wx.Image will be created with its data and alpha pointers initialized
+ to the memory address pointed to by the buffer objects, thus saving the
+ time needed to copy the image data from the buffer object to the wx.Image.
+ While this has advantages, it also has the shoot-yourself-in-the-foot
+ risks associated with sharing a C pointer between two objects.
+
+ To help alleviate the risk a reference to the data and alpha buffer
+ objects are kept with the wx.Image, so that they won't get deleted until
+ after the wx.Image is deleted. However please be aware that it is not
+ guaranteed that an object won't move its memory buffer to a new location
+ when it needs to resize its contents. If that happens then the wx.Image
+ will end up referring to an invalid memory location and could cause the
+ application to crash. Therefore care should be taken to not manipulate
+ the objects used for the data and alpha buffers in a way that would cause
+ them to change size.
+ """
+ image = _core_._ImageFromBuffer(width, height, dataBuffer, alphaBuffer)
+ image._buffer = dataBuffer
+ image._alpha = alphaBuffer
+ return image
+
+@wx.deprecated
+def InitAllImageHandlers():
+ """
+ The former functionality of InitAllImageHanders is now done internal to
+ the _core_ extension module and so this function has become a simple NOP.
+ """
+ pass
+
+IMAGE_RESOLUTION_NONE = _core_.IMAGE_RESOLUTION_NONE
+IMAGE_RESOLUTION_INCHES = _core_.IMAGE_RESOLUTION_INCHES
+IMAGE_RESOLUTION_CM = _core_.IMAGE_RESOLUTION_CM
+PNG_TYPE_COLOUR = _core_.PNG_TYPE_COLOUR
+PNG_TYPE_GREY = _core_.PNG_TYPE_GREY
+PNG_TYPE_GREY_RED = _core_.PNG_TYPE_GREY_RED
+BMP_24BPP = _core_.BMP_24BPP
+BMP_8BPP = _core_.BMP_8BPP
+BMP_8BPP_GREY = _core_.BMP_8BPP_GREY
+BMP_8BPP_GRAY = _core_.BMP_8BPP_GRAY
+BMP_8BPP_RED = _core_.BMP_8BPP_RED
+BMP_8BPP_PALETTE = _core_.BMP_8BPP_PALETTE
+BMP_4BPP = _core_.BMP_4BPP
+BMP_1BPP = _core_.BMP_1BPP
+BMP_1BPP_BW = _core_.BMP_1BPP_BW
+class BMPHandler(ImageHandler):
+ """A `wx.ImageHandler` for \*.bmp bitmap files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> BMPHandler
+
+ A `wx.ImageHandler` for \*.bmp bitmap files.
+ """
+ _core_.BMPHandler_swiginit(self,_core_.new_BMPHandler(*args, **kwargs))
+_core_.BMPHandler_swigregister(BMPHandler)
+NullImage = cvar.NullImage
+IMAGE_OPTION_FILENAME = cvar.IMAGE_OPTION_FILENAME
+IMAGE_OPTION_BMP_FORMAT = cvar.IMAGE_OPTION_BMP_FORMAT
+IMAGE_OPTION_CUR_HOTSPOT_X = cvar.IMAGE_OPTION_CUR_HOTSPOT_X
+IMAGE_OPTION_CUR_HOTSPOT_Y = cvar.IMAGE_OPTION_CUR_HOTSPOT_Y
+IMAGE_OPTION_RESOLUTION = cvar.IMAGE_OPTION_RESOLUTION
+IMAGE_OPTION_RESOLUTIONX = cvar.IMAGE_OPTION_RESOLUTIONX
+IMAGE_OPTION_RESOLUTIONY = cvar.IMAGE_OPTION_RESOLUTIONY
+IMAGE_OPTION_RESOLUTIONUNIT = cvar.IMAGE_OPTION_RESOLUTIONUNIT
+IMAGE_OPTION_QUALITY = cvar.IMAGE_OPTION_QUALITY
+IMAGE_OPTION_MAX_WIDTH = cvar.IMAGE_OPTION_MAX_WIDTH
+IMAGE_OPTION_MAX_HEIGHT = cvar.IMAGE_OPTION_MAX_HEIGHT
+IMAGE_OPTION_ORIGINAL_WIDTH = cvar.IMAGE_OPTION_ORIGINAL_WIDTH
+IMAGE_OPTION_ORIGINAL_HEIGHT = cvar.IMAGE_OPTION_ORIGINAL_HEIGHT
+IMAGE_OPTION_BITSPERSAMPLE = cvar.IMAGE_OPTION_BITSPERSAMPLE
+IMAGE_OPTION_SAMPLESPERPIXEL = cvar.IMAGE_OPTION_SAMPLESPERPIXEL
+IMAGE_OPTION_COMPRESSION = cvar.IMAGE_OPTION_COMPRESSION
+IMAGE_OPTION_IMAGEDESCRIPTOR = cvar.IMAGE_OPTION_IMAGEDESCRIPTOR
+IMAGE_OPTION_PNG_FORMAT = cvar.IMAGE_OPTION_PNG_FORMAT
+IMAGE_OPTION_PNG_BITDEPTH = cvar.IMAGE_OPTION_PNG_BITDEPTH
+
+class ICOHandler(BMPHandler):
+ """A `wx.ImageHandler` for \*.ico icon files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> ICOHandler
+
+ A `wx.ImageHandler` for \*.ico icon files.
+ """
+ _core_.ICOHandler_swiginit(self,_core_.new_ICOHandler(*args, **kwargs))
+_core_.ICOHandler_swigregister(ICOHandler)
+
+class CURHandler(ICOHandler):
+ """A `wx.ImageHandler` for \*.cur cursor files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> CURHandler
+
+ A `wx.ImageHandler` for \*.cur cursor files.
+ """
+ _core_.CURHandler_swiginit(self,_core_.new_CURHandler(*args, **kwargs))
+_core_.CURHandler_swigregister(CURHandler)
+
+class ANIHandler(CURHandler):
+ """A `wx.ImageHandler` for \*.ani animated cursor files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> ANIHandler
+
+ A `wx.ImageHandler` for \*.ani animated cursor files.
+ """
+ _core_.ANIHandler_swiginit(self,_core_.new_ANIHandler(*args, **kwargs))
+_core_.ANIHandler_swigregister(ANIHandler)
+
+class PNGHandler(ImageHandler):
+ """A `wx.ImageHandler` for PNG image files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PNGHandler
+
+ A `wx.ImageHandler` for PNG image files.
+ """
+ _core_.PNGHandler_swiginit(self,_core_.new_PNGHandler(*args, **kwargs))
+_core_.PNGHandler_swigregister(PNGHandler)
+
+class GIFHandler(ImageHandler):
+ """A `wx.ImageHandler` for GIF image files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> GIFHandler
+
+ A `wx.ImageHandler` for GIF image files.
+ """
+ _core_.GIFHandler_swiginit(self,_core_.new_GIFHandler(*args, **kwargs))
+_core_.GIFHandler_swigregister(GIFHandler)
+
+class PCXHandler(ImageHandler):
+ """A `wx.ImageHandler` for PCX imager files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PCXHandler
+
+ A `wx.ImageHandler` for PCX imager files.
+ """
+ _core_.PCXHandler_swiginit(self,_core_.new_PCXHandler(*args, **kwargs))
+_core_.PCXHandler_swigregister(PCXHandler)
+
+class JPEGHandler(ImageHandler):
+ """A `wx.ImageHandler` for JPEG/JPG image files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> JPEGHandler
+
+ A `wx.ImageHandler` for JPEG/JPG image files.
+ """
+ _core_.JPEGHandler_swiginit(self,_core_.new_JPEGHandler(*args, **kwargs))
+_core_.JPEGHandler_swigregister(JPEGHandler)
+
+class PNMHandler(ImageHandler):
+ """A `wx.ImageHandler` for PNM image files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PNMHandler
+
+ A `wx.ImageHandler` for PNM image files.
+ """
+ _core_.PNMHandler_swiginit(self,_core_.new_PNMHandler(*args, **kwargs))
+_core_.PNMHandler_swigregister(PNMHandler)
+
+class XPMHandler(ImageHandler):
+ """A `wx.ImageHandler` for XPM image."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> XPMHandler
+
+ A `wx.ImageHandler` for XPM image.
+ """
+ _core_.XPMHandler_swiginit(self,_core_.new_XPMHandler(*args, **kwargs))
+_core_.XPMHandler_swigregister(XPMHandler)
+
+class TIFFHandler(ImageHandler):
+ """A `wx.ImageHandler` for TIFF image files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> TIFFHandler
+
+ A `wx.ImageHandler` for TIFF image files.
+ """
+ _core_.TIFFHandler_swiginit(self,_core_.new_TIFFHandler(*args, **kwargs))
+_core_.TIFFHandler_swigregister(TIFFHandler)
+
+class TGAHandler(ImageHandler):
+ """A `wx.ImageHandler` for TGA image files."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> TGAHandler
+
+ A `wx.ImageHandler` for TGA image files.
+ """
+ _core_.TGAHandler_swiginit(self,_core_.new_TGAHandler(*args, **kwargs))
+_core_.TGAHandler_swigregister(TGAHandler)
+
+QUANTIZE_INCLUDE_WINDOWS_COLOURS = _core_.QUANTIZE_INCLUDE_WINDOWS_COLOURS
+QUANTIZE_FILL_DESTINATION_IMAGE = _core_.QUANTIZE_FILL_DESTINATION_IMAGE
+class Quantize(object):
+ """Performs quantization, or colour reduction, on a wxImage."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Quantize(*args, **kwargs):
+ """
+ Quantize(Image src, Image dest, int desiredNoColours=236, int flags=wxQUANTIZE_INCLUDE_WINDOWS_COLOURS|wxQUANTIZE_FILL_DESTINATION_IMAGE) -> bool
+
+ Reduce the colours in the source image and put the result into the
+ destination image, setting the palette in the destination if
+ needed. Both images may be the same, to overwrite the source image.
+ """
+ return _core_.Quantize_Quantize(*args, **kwargs)
+
+ Quantize = staticmethod(Quantize)
+_core_.Quantize_swigregister(Quantize)
+
+def Quantize_Quantize(*args, **kwargs):
+ """
+ Quantize_Quantize(Image src, Image dest, int desiredNoColours=236, int flags=wxQUANTIZE_INCLUDE_WINDOWS_COLOURS|wxQUANTIZE_FILL_DESTINATION_IMAGE) -> bool
+
+ Reduce the colours in the source image and put the result into the
+ destination image, setting the palette in the destination if
+ needed. Both images may be the same, to overwrite the source image.
+ """
+ return _core_.Quantize_Quantize(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class EvtHandler(Object):
+ """Proxy of C++ EvtHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> EvtHandler"""
+ _core_.EvtHandler_swiginit(self,_core_.new_EvtHandler(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetNextHandler(*args, **kwargs):
+ """GetNextHandler(self) -> EvtHandler"""
+ return _core_.EvtHandler_GetNextHandler(*args, **kwargs)
+
+ def GetPreviousHandler(*args, **kwargs):
+ """GetPreviousHandler(self) -> EvtHandler"""
+ return _core_.EvtHandler_GetPreviousHandler(*args, **kwargs)
+
+ def SetNextHandler(*args, **kwargs):
+ """SetNextHandler(self, EvtHandler handler)"""
+ return _core_.EvtHandler_SetNextHandler(*args, **kwargs)
+
+ def SetPreviousHandler(*args, **kwargs):
+ """SetPreviousHandler(self, EvtHandler handler)"""
+ return _core_.EvtHandler_SetPreviousHandler(*args, **kwargs)
+
+ def GetEvtHandlerEnabled(*args, **kwargs):
+ """GetEvtHandlerEnabled(self) -> bool"""
+ return _core_.EvtHandler_GetEvtHandlerEnabled(*args, **kwargs)
+
+ def SetEvtHandlerEnabled(*args, **kwargs):
+ """SetEvtHandlerEnabled(self, bool enabled)"""
+ return _core_.EvtHandler_SetEvtHandlerEnabled(*args, **kwargs)
+
+ def Unlink(*args, **kwargs):
+ """Unlink(self)"""
+ return _core_.EvtHandler_Unlink(*args, **kwargs)
+
+ def IsUnlinked(*args, **kwargs):
+ """IsUnlinked(self) -> bool"""
+ return _core_.EvtHandler_IsUnlinked(*args, **kwargs)
+
+ def ProcessEvent(*args, **kwargs):
+ """ProcessEvent(self, Event event) -> bool"""
+ return _core_.EvtHandler_ProcessEvent(*args, **kwargs)
+
+ def SafelyProcessEvent(*args, **kwargs):
+ """SafelyProcessEvent(self, Event event) -> bool"""
+ return _core_.EvtHandler_SafelyProcessEvent(*args, **kwargs)
+
+ def ProcessEventLocally(*args, **kwargs):
+ """ProcessEventLocally(self, Event event) -> bool"""
+ return _core_.EvtHandler_ProcessEventLocally(*args, **kwargs)
+
+ def QueueEvent(*args, **kwargs):
+ """QueueEvent(self, Event event)"""
+ return _core_.EvtHandler_QueueEvent(*args, **kwargs)
+
+ def AddPendingEvent(*args, **kwargs):
+ """AddPendingEvent(self, Event event)"""
+ return _core_.EvtHandler_AddPendingEvent(*args, **kwargs)
+
+ def ProcessPendingEvents(*args, **kwargs):
+ """ProcessPendingEvents(self)"""
+ return _core_.EvtHandler_ProcessPendingEvents(*args, **kwargs)
+
+ def DeletePendingEvents(*args, **kwargs):
+ """DeletePendingEvents(self)"""
+ return _core_.EvtHandler_DeletePendingEvents(*args, **kwargs)
+
+ def Connect(*args, **kwargs):
+ """Connect(self, int id, int lastId, EventType eventType, PyObject func)"""
+ return _core_.EvtHandler_Connect(*args, **kwargs)
+
+ def Disconnect(*args, **kwargs):
+ """
+ Disconnect(self, int id, int lastId=-1, EventType eventType=wxEVT_NULL,
+ PyObject func=None) -> bool
+ """
+ return _core_.EvtHandler_Disconnect(*args, **kwargs)
+
+ def _setOORInfo(*args, **kwargs):
+ """_setOORInfo(self, PyObject _self, bool incref=True)"""
+ val = _core_.EvtHandler__setOORInfo(*args, **kwargs)
+ args[0].this.own(False)
+ return val
+
+ def Bind(self, event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY):
+ """
+ Bind an event to an event handler.
+
+ :param event: One of the EVT_* objects that specifies the
+ type of event to bind,
+
+ :param handler: A callable object to be invoked when the
+ event is delivered to self. Pass None to
+ disconnect an event handler.
+
+ :param source: Sometimes the event originates from a
+ different window than self, but you still
+ want to catch it in self. (For example, a
+ button event delivered to a frame.) By
+ passing the source of the event, the event
+ handling system is able to differentiate
+ between the same event type from different
+ controls.
+
+ :param id: Used to spcify the event source by ID instead
+ of instance.
+
+ :param id2: Used when it is desirable to bind a handler
+ to a range of IDs, such as with EVT_MENU_RANGE.
+ """
+ assert isinstance(event, wx.PyEventBinder)
+ assert handler is None or callable(handler)
+ assert source is None or hasattr(source, 'GetId')
+ if source is not None:
+ id = source.GetId()
+ event.Bind(self, id, id2, handler)
+
+ def Unbind(self, event, source=None, id=wx.ID_ANY, id2=wx.ID_ANY, handler=None):
+ """
+ Disconnects the event handler binding for event from self.
+ Returns True if successful.
+ """
+ if source is not None:
+ id = source.GetId()
+ return event.Unbind(self, id, id2, handler)
+
+ EvtHandlerEnabled = property(GetEvtHandlerEnabled,SetEvtHandlerEnabled,doc="See `GetEvtHandlerEnabled` and `SetEvtHandlerEnabled`")
+ NextHandler = property(GetNextHandler,SetNextHandler,doc="See `GetNextHandler` and `SetNextHandler`")
+ PreviousHandler = property(GetPreviousHandler,SetPreviousHandler,doc="See `GetPreviousHandler` and `SetPreviousHandler`")
+_core_.EvtHandler_swigregister(EvtHandler)
+
+class PyEvtHandler(EvtHandler):
+ """
+ The wx.PyEvtHandler class can be used to intercept calls to the
+ `ProcessEvent` method. Simply derive a new class from this one,
+ override ProcessEvent, and then push an instance of the class onto the
+ event handler chain for a window using `wx.Window.PushEventHandler`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PyEvtHandler
+
+ The wx.PyEvtHandler class can be used to intercept calls to the
+ `ProcessEvent` method. Simply derive a new class from this one,
+ override ProcessEvent, and then push an instance of the class onto the
+ event handler chain for a window using `wx.Window.PushEventHandler`.
+ """
+ _core_.PyEvtHandler_swiginit(self,_core_.new_PyEvtHandler(*args, **kwargs))
+ self._setOORInfo(self);PyEvtHandler._setCallbackInfo(self, self, PyEvtHandler)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _core_.PyEvtHandler__setCallbackInfo(*args, **kwargs)
+
+ def ProcessEvent(*args, **kwargs):
+ """
+ ProcessEvent(self, Event event) -> bool
+
+ Override this method to intercept the events being sent to the window.
+ The default implementation searches the event tables and calls event
+ handler functions if matching event bindings are found.
+ """
+ return _core_.PyEvtHandler_ProcessEvent(*args, **kwargs)
+
+_core_.PyEvtHandler_swigregister(PyEvtHandler)
+
+#---------------------------------------------------------------------------
+
+class KeyboardState(object):
+ """wx.KeyboardState stores the state of the keyboard modifier keys"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, bool controlDown=False, bool shiftDown=False, bool altDown=False,
+ bool metaDown=False) -> KeyboardState
+
+ wx.KeyboardState stores the state of the keyboard modifier keys
+ """
+ _core_.KeyboardState_swiginit(self,_core_.new_KeyboardState(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_KeyboardState
+ __del__ = lambda self : None;
+ def GetModifiers(*args, **kwargs):
+ """
+ GetModifiers(self) -> int
+
+ Returns a bitmask of the current modifier settings. Can be used to
+ check if the key event has exactly the given modifiers without having
+ to explicitly check that the other modifiers are not down. For
+ example::
+
+ if event.GetModifers() == wx.MOD_CONTROL:
+ DoSomething()
+
+ """
+ return _core_.KeyboardState_GetModifiers(*args, **kwargs)
+
+ Modifiers = property(GetModifiers,doc="See `GetModifiers`")
+ def ControlDown(*args, **kwargs):
+ """
+ ControlDown(self) -> bool
+
+ Returns ``True`` if the Control key was down at the time of the event.
+ """
+ return _core_.KeyboardState_ControlDown(*args, **kwargs)
+
+ def RawControlDown(*args, **kwargs):
+ """RawControlDown(self) -> bool"""
+ return _core_.KeyboardState_RawControlDown(*args, **kwargs)
+
+ def SetRawControlDown(*args, **kwargs):
+ """SetRawControlDown(self, bool down)"""
+ return _core_.KeyboardState_SetRawControlDown(*args, **kwargs)
+
+ def MetaDown(*args, **kwargs):
+ """
+ MetaDown(self) -> bool
+
+ Returns ``True`` if the Meta key was down at the time of the event.
+ """
+ return _core_.KeyboardState_MetaDown(*args, **kwargs)
+
+ def AltDown(*args, **kwargs):
+ """
+ AltDown(self) -> bool
+
+ Returns ``True`` if the Alt key was down at the time of the event.
+ """
+ return _core_.KeyboardState_AltDown(*args, **kwargs)
+
+ def ShiftDown(*args, **kwargs):
+ """
+ ShiftDown(self) -> bool
+
+ Returns ``True`` if the Shift key was down at the time of the event.
+ """
+ return _core_.KeyboardState_ShiftDown(*args, **kwargs)
+
+ def CmdDown(*args, **kwargs):
+ """
+ CmdDown(self) -> bool
+
+ "Cmd" is a pseudo key which is the same as Control for PC and Unix
+ platforms but the special "Apple" (a.k.a as "Command") key on
+ Macs. It makes often sense to use it instead of, say, `ControlDown`
+ because Cmd key is used for the same thing under Mac as Ctrl
+ elsewhere. The Ctrl still exists, it's just not used for this
+ purpose. So for non-Mac platforms this is the same as `ControlDown`
+ and Macs this is the same as `MetaDown`.
+ """
+ return _core_.KeyboardState_CmdDown(*args, **kwargs)
+
+ def HasModifiers(*args, **kwargs):
+ """
+ HasModifiers(self) -> bool
+
+ Returns true if either CTRL or ALT keys was down at the time of the
+ key event. Note that this function does not take into account neither
+ SHIFT nor META key states (the reason for ignoring the latter is that
+ it is common for NUMLOCK key to be configured as META under X but the
+ key presses even while NUMLOCK is on should be still processed
+ normally).
+ """
+ return _core_.KeyboardState_HasModifiers(*args, **kwargs)
+
+ def SetControlDown(*args, **kwargs):
+ """SetControlDown(self, bool down)"""
+ return _core_.KeyboardState_SetControlDown(*args, **kwargs)
+
+ def SetShiftDown(*args, **kwargs):
+ """SetShiftDown(self, bool down)"""
+ return _core_.KeyboardState_SetShiftDown(*args, **kwargs)
+
+ def SetAltDown(*args, **kwargs):
+ """SetAltDown(self, bool down)"""
+ return _core_.KeyboardState_SetAltDown(*args, **kwargs)
+
+ def SetMetaDown(*args, **kwargs):
+ """SetMetaDown(self, bool down)"""
+ return _core_.KeyboardState_SetMetaDown(*args, **kwargs)
+
+ controlDown = property(ControlDown, SetControlDown)
+ rawControlDown = property(RawControlDown, SetRawControlDown)
+ shiftDown = property(ShiftDown, SetShiftDown)
+ altDown = property(AltDown, SetAltDown)
+ metaDown = property(MetaDown, SetMetaDown)
+ cmdDown = property(CmdDown)
+
+
+ m_controlDown = wx.deprecated(controlDown)
+ m_shiftDown = wx.deprecated(shiftDown)
+ m_altDown = wx.deprecated(altDown)
+ m_metaDown = wx.deprecated(metaDown)
+
+_core_.KeyboardState_swigregister(KeyboardState)
+
+#---------------------------------------------------------------------------
+
+MOUSE_BTN_ANY = _core_.MOUSE_BTN_ANY
+MOUSE_BTN_NONE = _core_.MOUSE_BTN_NONE
+MOUSE_BTN_LEFT = _core_.MOUSE_BTN_LEFT
+MOUSE_BTN_MIDDLE = _core_.MOUSE_BTN_MIDDLE
+MOUSE_BTN_RIGHT = _core_.MOUSE_BTN_RIGHT
+MOUSE_BTN_AUX1 = _core_.MOUSE_BTN_AUX1
+MOUSE_BTN_AUX2 = _core_.MOUSE_BTN_AUX2
+MOUSE_BTN_MAX = _core_.MOUSE_BTN_MAX
+class MouseState(KeyboardState):
+ """
+ `wx.MouseState` is used to hold information about mouse button and
+ modifier key states and is what is returned from `wx.GetMouseState`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> MouseState
+
+ `wx.MouseState` is used to hold information about mouse button and
+ modifier key states and is what is returned from `wx.GetMouseState`.
+ """
+ _core_.MouseState_swiginit(self,_core_.new_MouseState(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_MouseState
+ __del__ = lambda self : None;
+ def GetX(*args, **kwargs):
+ """GetX(self) -> int"""
+ return _core_.MouseState_GetX(*args, **kwargs)
+
+ def GetY(*args, **kwargs):
+ """GetY(self) -> int"""
+ return _core_.MouseState_GetY(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point"""
+ return _core_.MouseState_GetPosition(*args, **kwargs)
+
+ def GetPositionTuple(*args, **kwargs):
+ """GetPositionTuple() -> (x,y)"""
+ return _core_.MouseState_GetPositionTuple(*args, **kwargs)
+
+ def LeftIsDown(*args, **kwargs):
+ """LeftIsDown(self) -> bool"""
+ return _core_.MouseState_LeftIsDown(*args, **kwargs)
+
+ def MiddleIsDown(*args, **kwargs):
+ """MiddleIsDown(self) -> bool"""
+ return _core_.MouseState_MiddleIsDown(*args, **kwargs)
+
+ def RightIsDown(*args, **kwargs):
+ """RightIsDown(self) -> bool"""
+ return _core_.MouseState_RightIsDown(*args, **kwargs)
+
+ def Aux1IsDown(*args, **kwargs):
+ """Aux1IsDown(self) -> bool"""
+ return _core_.MouseState_Aux1IsDown(*args, **kwargs)
+
+ def Aux2IsDown(*args, **kwargs):
+ """Aux2IsDown(self) -> bool"""
+ return _core_.MouseState_Aux2IsDown(*args, **kwargs)
+
+ def ButtonIsDown(*args, **kwargs):
+ """ButtonIsDown(self, int but) -> bool"""
+ return _core_.MouseState_ButtonIsDown(*args, **kwargs)
+
+ LeftDown = wx.deprecated(LeftIsDown)
+ MiddleDown = wx.deprecated(MiddleIsDown)
+ RightDown = wx.deprecated(RightIsDown)
+
+ def SetX(*args, **kwargs):
+ """SetX(self, int x)"""
+ return _core_.MouseState_SetX(*args, **kwargs)
+
+ def SetY(*args, **kwargs):
+ """SetY(self, int y)"""
+ return _core_.MouseState_SetY(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, Point pos)"""
+ return _core_.MouseState_SetPosition(*args, **kwargs)
+
+ def SetLeftDown(*args, **kwargs):
+ """SetLeftDown(self, bool down)"""
+ return _core_.MouseState_SetLeftDown(*args, **kwargs)
+
+ def SetMiddleDown(*args, **kwargs):
+ """SetMiddleDown(self, bool down)"""
+ return _core_.MouseState_SetMiddleDown(*args, **kwargs)
+
+ def SetRightDown(*args, **kwargs):
+ """SetRightDown(self, bool down)"""
+ return _core_.MouseState_SetRightDown(*args, **kwargs)
+
+ def SetAux1Down(*args, **kwargs):
+ """SetAux1Down(self, bool down)"""
+ return _core_.MouseState_SetAux1Down(*args, **kwargs)
+
+ def SetAux2Down(*args, **kwargs):
+ """SetAux2Down(self, bool down)"""
+ return _core_.MouseState_SetAux2Down(*args, **kwargs)
+
+ def SetState(*args, **kwargs):
+ """SetState(self, MouseState state)"""
+ return _core_.MouseState_SetState(*args, **kwargs)
+
+ x = property(GetX, SetX)
+ y = property(GetY, SetY)
+ X = property(GetX, SetX) # uppercase versions for 2.8 compatibility
+ Y = property(GetY, SetY)
+ leftIsDown = property(LeftIsDown, SetLeftDown)
+ middleIsDown = property(MiddleIsDown, SetMiddleDown)
+ rightIsDown = property(RightIsDown, SetRightDown)
+ aux1IsDown = property(Aux1IsDown, SetAux1Down)
+ aux2IsDown = property(Aux2IsDown, SetAux2Down)
+
+
+ m_leftDown = wx.deprecated(leftIsDown)
+ m_middleDown = wx.deprecated(middleIsDown)
+ m_rightDown = wx.deprecated(rightIsDown)
+ m_aux1Down = wx.deprecated(aux1IsDown)
+ m_aux2Down = wx.deprecated(aux2IsDown)
+ m_x = wx.deprecated(x)
+ m_y = wx.deprecated(y)
+
+ Position = property(GetPosition,doc="See `GetPosition`")
+_core_.MouseState_swigregister(MouseState)
+
+
+def GetMouseState(*args):
+ """
+ GetMouseState() -> MouseState
+
+ Returns the current state of the mouse. Returns an instance of a
+ `wx.MouseState` object that contains the current position of the mouse
+ pointer in screen coordinants, as well as boolean values indicating
+ the up/down status of the mouse buttons and the modifier keys.
+ """
+ return _core_.GetMouseState(*args)
+#---------------------------------------------------------------------------
+
+class PyEventBinder(object):
+ """
+ Instances of this class are used to bind specific events to event
+ handlers.
+ """
+ def __init__(self, evtType, expectedIDs=0):
+ if expectedIDs not in [0, 1, 2]:
+ raise ValueError, "Invalid number of expectedIDs"
+ self.expectedIDs = expectedIDs
+
+ if type(evtType) == list or type(evtType) == tuple:
+ self.evtType = evtType
+ else:
+ self.evtType = [evtType]
+
+
+ def Bind(self, target, id1, id2, function):
+ """Bind this set of event types to target."""
+ for et in self.evtType:
+ target.Connect(id1, id2, et, function)
+
+
+ def Unbind(self, target, id1, id2, handler=None):
+ """Remove an event binding."""
+ success = 0
+ for et in self.evtType:
+ success += target.Disconnect(id1, id2, et, handler)
+ return success != 0
+
+ def _getEvtType(self):
+ """
+ Make it easy to get to the default wxEventType typeID for this
+ event binder.
+ """
+ return self.evtType[0]
+
+ typeId = property(_getEvtType)
+
+
+ def __call__(self, *args):
+ """
+ For backwards compatibility with the old EVT_* functions.
+ Should be called with either (window, func), (window, ID,
+ func) or (window, ID1, ID2, func) parameters depending on the
+ type of the event.
+ """
+ assert len(args) == 2 + self.expectedIDs
+ id1 = wx.ID_ANY
+ id2 = wx.ID_ANY
+ target = args[0]
+ if self.expectedIDs == 0:
+ func = args[1]
+ elif self.expectedIDs == 1:
+ id1 = args[1]
+ func = args[2]
+ elif self.expectedIDs == 2:
+ id1 = args[1]
+ id2 = args[2]
+ func = args[3]
+ else:
+ raise ValueError, "Unexpected number of IDs"
+
+ self.Bind(target, id1, id2, func)
+
+
+# These two are square pegs that don't fit the PyEventBinder hole...
+def EVT_COMMAND(win, id, cmd, func):
+ win.Connect(id, -1, cmd, func)
+def EVT_COMMAND_RANGE(win, id1, id2, cmd, func):
+ win.Connect(id1, id2, cmd, func)
+
+
+#---------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+
+EVENT_PROPAGATE_NONE = _core_.EVENT_PROPAGATE_NONE
+EVENT_PROPAGATE_MAX = _core_.EVENT_PROPAGATE_MAX
+wxEVT_CATEGORY_UI = _core_.wxEVT_CATEGORY_UI
+wxEVT_CATEGORY_USER_INPUT = _core_.wxEVT_CATEGORY_USER_INPUT
+wxEVT_CATEGORY_SOCKET = _core_.wxEVT_CATEGORY_SOCKET
+wxEVT_CATEGORY_TIMER = _core_.wxEVT_CATEGORY_TIMER
+wxEVT_CATEGORY_THREAD = _core_.wxEVT_CATEGORY_THREAD
+wxEVT_CATEGORY_UNKNOWN = _core_.wxEVT_CATEGORY_UNKNOWN
+wxEVT_CATEGORY_CLIPBOARD = _core_.wxEVT_CATEGORY_CLIPBOARD
+wxEVT_CATEGORY_NATIVE_EVENTS = _core_.wxEVT_CATEGORY_NATIVE_EVENTS
+wxEVT_CATEGORY_ALL = _core_.wxEVT_CATEGORY_ALL
+
+def NewEventType(*args):
+ """NewEventType() -> EventType"""
+ return _core_.NewEventType(*args)
+wxEVT_ANY = _core_.wxEVT_ANY
+wxEVT_NULL = _core_.wxEVT_NULL
+wxEVT_FIRST = _core_.wxEVT_FIRST
+wxEVT_USER_FIRST = _core_.wxEVT_USER_FIRST
+wxEVT_COMMAND_BUTTON_CLICKED = _core_.wxEVT_COMMAND_BUTTON_CLICKED
+wxEVT_COMMAND_CHECKBOX_CLICKED = _core_.wxEVT_COMMAND_CHECKBOX_CLICKED
+wxEVT_COMMAND_CHOICE_SELECTED = _core_.wxEVT_COMMAND_CHOICE_SELECTED
+wxEVT_COMMAND_LISTBOX_SELECTED = _core_.wxEVT_COMMAND_LISTBOX_SELECTED
+wxEVT_COMMAND_LISTBOX_DOUBLECLICKED = _core_.wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
+wxEVT_COMMAND_CHECKLISTBOX_TOGGLED = _core_.wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
+wxEVT_COMMAND_MENU_SELECTED = _core_.wxEVT_COMMAND_MENU_SELECTED
+wxEVT_COMMAND_TOOL_CLICKED = _core_.wxEVT_COMMAND_TOOL_CLICKED
+wxEVT_COMMAND_SLIDER_UPDATED = _core_.wxEVT_COMMAND_SLIDER_UPDATED
+wxEVT_COMMAND_RADIOBOX_SELECTED = _core_.wxEVT_COMMAND_RADIOBOX_SELECTED
+wxEVT_COMMAND_RADIOBUTTON_SELECTED = _core_.wxEVT_COMMAND_RADIOBUTTON_SELECTED
+wxEVT_COMMAND_SCROLLBAR_UPDATED = _core_.wxEVT_COMMAND_SCROLLBAR_UPDATED
+wxEVT_COMMAND_VLBOX_SELECTED = _core_.wxEVT_COMMAND_VLBOX_SELECTED
+wxEVT_COMMAND_COMBOBOX_SELECTED = _core_.wxEVT_COMMAND_COMBOBOX_SELECTED
+wxEVT_COMMAND_TOOL_RCLICKED = _core_.wxEVT_COMMAND_TOOL_RCLICKED
+wxEVT_COMMAND_TOOL_ENTER = _core_.wxEVT_COMMAND_TOOL_ENTER
+wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED = _core_.wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED
+wxEVT_COMMAND_COMBOBOX_DROPDOWN = _core_.wxEVT_COMMAND_COMBOBOX_DROPDOWN
+wxEVT_COMMAND_COMBOBOX_CLOSEUP = _core_.wxEVT_COMMAND_COMBOBOX_CLOSEUP
+wxEVT_THREAD = _core_.wxEVT_THREAD
+wxEVT_LEFT_DOWN = _core_.wxEVT_LEFT_DOWN
+wxEVT_LEFT_UP = _core_.wxEVT_LEFT_UP
+wxEVT_MIDDLE_DOWN = _core_.wxEVT_MIDDLE_DOWN
+wxEVT_MIDDLE_UP = _core_.wxEVT_MIDDLE_UP
+wxEVT_RIGHT_DOWN = _core_.wxEVT_RIGHT_DOWN
+wxEVT_RIGHT_UP = _core_.wxEVT_RIGHT_UP
+wxEVT_MOTION = _core_.wxEVT_MOTION
+wxEVT_ENTER_WINDOW = _core_.wxEVT_ENTER_WINDOW
+wxEVT_LEAVE_WINDOW = _core_.wxEVT_LEAVE_WINDOW
+wxEVT_LEFT_DCLICK = _core_.wxEVT_LEFT_DCLICK
+wxEVT_MIDDLE_DCLICK = _core_.wxEVT_MIDDLE_DCLICK
+wxEVT_RIGHT_DCLICK = _core_.wxEVT_RIGHT_DCLICK
+wxEVT_SET_FOCUS = _core_.wxEVT_SET_FOCUS
+wxEVT_KILL_FOCUS = _core_.wxEVT_KILL_FOCUS
+wxEVT_CHILD_FOCUS = _core_.wxEVT_CHILD_FOCUS
+wxEVT_MOUSEWHEEL = _core_.wxEVT_MOUSEWHEEL
+wxEVT_AUX1_DOWN = _core_.wxEVT_AUX1_DOWN
+wxEVT_AUX1_UP = _core_.wxEVT_AUX1_UP
+wxEVT_AUX1_DCLICK = _core_.wxEVT_AUX1_DCLICK
+wxEVT_AUX2_DOWN = _core_.wxEVT_AUX2_DOWN
+wxEVT_AUX2_UP = _core_.wxEVT_AUX2_UP
+wxEVT_AUX2_DCLICK = _core_.wxEVT_AUX2_DCLICK
+wxEVT_CHAR = _core_.wxEVT_CHAR
+wxEVT_CHAR_HOOK = _core_.wxEVT_CHAR_HOOK
+wxEVT_NAVIGATION_KEY = _core_.wxEVT_NAVIGATION_KEY
+wxEVT_KEY_DOWN = _core_.wxEVT_KEY_DOWN
+wxEVT_KEY_UP = _core_.wxEVT_KEY_UP
+wxEVT_HOTKEY = _core_.wxEVT_HOTKEY
+wxEVT_SET_CURSOR = _core_.wxEVT_SET_CURSOR
+wxEVT_SCROLL_TOP = _core_.wxEVT_SCROLL_TOP
+wxEVT_SCROLL_BOTTOM = _core_.wxEVT_SCROLL_BOTTOM
+wxEVT_SCROLL_LINEUP = _core_.wxEVT_SCROLL_LINEUP
+wxEVT_SCROLL_LINEDOWN = _core_.wxEVT_SCROLL_LINEDOWN
+wxEVT_SCROLL_PAGEUP = _core_.wxEVT_SCROLL_PAGEUP
+wxEVT_SCROLL_PAGEDOWN = _core_.wxEVT_SCROLL_PAGEDOWN
+wxEVT_SCROLL_THUMBTRACK = _core_.wxEVT_SCROLL_THUMBTRACK
+wxEVT_SCROLL_THUMBRELEASE = _core_.wxEVT_SCROLL_THUMBRELEASE
+wxEVT_SCROLL_CHANGED = _core_.wxEVT_SCROLL_CHANGED
+wxEVT_SCROLL_ENDSCROLL = wxEVT_SCROLL_CHANGED
+wxEVT_SCROLLWIN_TOP = _core_.wxEVT_SCROLLWIN_TOP
+wxEVT_SCROLLWIN_BOTTOM = _core_.wxEVT_SCROLLWIN_BOTTOM
+wxEVT_SCROLLWIN_LINEUP = _core_.wxEVT_SCROLLWIN_LINEUP
+wxEVT_SCROLLWIN_LINEDOWN = _core_.wxEVT_SCROLLWIN_LINEDOWN
+wxEVT_SCROLLWIN_PAGEUP = _core_.wxEVT_SCROLLWIN_PAGEUP
+wxEVT_SCROLLWIN_PAGEDOWN = _core_.wxEVT_SCROLLWIN_PAGEDOWN
+wxEVT_SCROLLWIN_THUMBTRACK = _core_.wxEVT_SCROLLWIN_THUMBTRACK
+wxEVT_SCROLLWIN_THUMBRELEASE = _core_.wxEVT_SCROLLWIN_THUMBRELEASE
+wxEVT_SIZE = _core_.wxEVT_SIZE
+wxEVT_MOVE = _core_.wxEVT_MOVE
+wxEVT_CLOSE_WINDOW = _core_.wxEVT_CLOSE_WINDOW
+wxEVT_END_SESSION = _core_.wxEVT_END_SESSION
+wxEVT_QUERY_END_SESSION = _core_.wxEVT_QUERY_END_SESSION
+wxEVT_ACTIVATE_APP = _core_.wxEVT_ACTIVATE_APP
+wxEVT_ACTIVATE = _core_.wxEVT_ACTIVATE
+wxEVT_CREATE = _core_.wxEVT_CREATE
+wxEVT_DESTROY = _core_.wxEVT_DESTROY
+wxEVT_SHOW = _core_.wxEVT_SHOW
+wxEVT_ICONIZE = _core_.wxEVT_ICONIZE
+wxEVT_MAXIMIZE = _core_.wxEVT_MAXIMIZE
+wxEVT_MOUSE_CAPTURE_CHANGED = _core_.wxEVT_MOUSE_CAPTURE_CHANGED
+wxEVT_MOUSE_CAPTURE_LOST = _core_.wxEVT_MOUSE_CAPTURE_LOST
+wxEVT_PAINT = _core_.wxEVT_PAINT
+wxEVT_ERASE_BACKGROUND = _core_.wxEVT_ERASE_BACKGROUND
+wxEVT_NC_PAINT = _core_.wxEVT_NC_PAINT
+wxEVT_MENU_OPEN = _core_.wxEVT_MENU_OPEN
+wxEVT_MENU_CLOSE = _core_.wxEVT_MENU_CLOSE
+wxEVT_MENU_HIGHLIGHT = _core_.wxEVT_MENU_HIGHLIGHT
+wxEVT_CONTEXT_MENU = _core_.wxEVT_CONTEXT_MENU
+wxEVT_SYS_COLOUR_CHANGED = _core_.wxEVT_SYS_COLOUR_CHANGED
+wxEVT_DISPLAY_CHANGED = _core_.wxEVT_DISPLAY_CHANGED
+wxEVT_QUERY_NEW_PALETTE = _core_.wxEVT_QUERY_NEW_PALETTE
+wxEVT_PALETTE_CHANGED = _core_.wxEVT_PALETTE_CHANGED
+wxEVT_DROP_FILES = _core_.wxEVT_DROP_FILES
+wxEVT_INIT_DIALOG = _core_.wxEVT_INIT_DIALOG
+wxEVT_IDLE = _core_.wxEVT_IDLE
+wxEVT_UPDATE_UI = _core_.wxEVT_UPDATE_UI
+wxEVT_SIZING = _core_.wxEVT_SIZING
+wxEVT_MOVING = _core_.wxEVT_MOVING
+wxEVT_MOVE_START = _core_.wxEVT_MOVE_START
+wxEVT_MOVE_END = _core_.wxEVT_MOVE_END
+wxEVT_HIBERNATE = _core_.wxEVT_HIBERNATE
+wxEVT_COMMAND_TEXT_COPY = _core_.wxEVT_COMMAND_TEXT_COPY
+wxEVT_COMMAND_TEXT_CUT = _core_.wxEVT_COMMAND_TEXT_CUT
+wxEVT_COMMAND_TEXT_PASTE = _core_.wxEVT_COMMAND_TEXT_PASTE
+wxEVT_COMMAND_LEFT_CLICK = _core_.wxEVT_COMMAND_LEFT_CLICK
+wxEVT_COMMAND_LEFT_DCLICK = _core_.wxEVT_COMMAND_LEFT_DCLICK
+wxEVT_COMMAND_RIGHT_CLICK = _core_.wxEVT_COMMAND_RIGHT_CLICK
+wxEVT_COMMAND_RIGHT_DCLICK = _core_.wxEVT_COMMAND_RIGHT_DCLICK
+wxEVT_COMMAND_SET_FOCUS = _core_.wxEVT_COMMAND_SET_FOCUS
+wxEVT_COMMAND_KILL_FOCUS = _core_.wxEVT_COMMAND_KILL_FOCUS
+wxEVT_COMMAND_ENTER = _core_.wxEVT_COMMAND_ENTER
+#
+# Create some event binders
+EVT_SIZE = wx.PyEventBinder( wxEVT_SIZE )
+EVT_SIZING = wx.PyEventBinder( wxEVT_SIZING )
+EVT_MOVE = wx.PyEventBinder( wxEVT_MOVE )
+EVT_MOVING = wx.PyEventBinder( wxEVT_MOVING )
+EVT_MOVE_START = wx.PyEventBinder( wxEVT_MOVE_START )
+EVT_MOVE_END = wx.PyEventBinder( wxEVT_MOVE_END )
+EVT_CLOSE = wx.PyEventBinder( wxEVT_CLOSE_WINDOW )
+EVT_END_SESSION = wx.PyEventBinder( wxEVT_END_SESSION )
+EVT_QUERY_END_SESSION = wx.PyEventBinder( wxEVT_QUERY_END_SESSION )
+EVT_PAINT = wx.PyEventBinder( wxEVT_PAINT )
+EVT_NC_PAINT = wx.PyEventBinder( wxEVT_NC_PAINT )
+EVT_ERASE_BACKGROUND = wx.PyEventBinder( wxEVT_ERASE_BACKGROUND )
+EVT_CHAR = wx.PyEventBinder( wxEVT_CHAR )
+EVT_KEY_DOWN = wx.PyEventBinder( wxEVT_KEY_DOWN )
+EVT_KEY_UP = wx.PyEventBinder( wxEVT_KEY_UP )
+EVT_HOTKEY = wx.PyEventBinder( wxEVT_HOTKEY, 1)
+EVT_CHAR_HOOK = wx.PyEventBinder( wxEVT_CHAR_HOOK )
+EVT_MENU_OPEN = wx.PyEventBinder( wxEVT_MENU_OPEN )
+EVT_MENU_CLOSE = wx.PyEventBinder( wxEVT_MENU_CLOSE )
+EVT_MENU_HIGHLIGHT = wx.PyEventBinder( wxEVT_MENU_HIGHLIGHT, 1)
+EVT_MENU_HIGHLIGHT_ALL = wx.PyEventBinder( wxEVT_MENU_HIGHLIGHT )
+EVT_SET_FOCUS = wx.PyEventBinder( wxEVT_SET_FOCUS )
+EVT_KILL_FOCUS = wx.PyEventBinder( wxEVT_KILL_FOCUS )
+EVT_CHILD_FOCUS = wx.PyEventBinder( wxEVT_CHILD_FOCUS )
+EVT_ACTIVATE = wx.PyEventBinder( wxEVT_ACTIVATE )
+EVT_ACTIVATE_APP = wx.PyEventBinder( wxEVT_ACTIVATE_APP )
+EVT_HIBERNATE = wx.PyEventBinder( wxEVT_HIBERNATE )
+EVT_END_SESSION = wx.PyEventBinder( wxEVT_END_SESSION )
+EVT_QUERY_END_SESSION = wx.PyEventBinder( wxEVT_QUERY_END_SESSION )
+EVT_DROP_FILES = wx.PyEventBinder( wxEVT_DROP_FILES )
+EVT_INIT_DIALOG = wx.PyEventBinder( wxEVT_INIT_DIALOG )
+EVT_SYS_COLOUR_CHANGED = wx.PyEventBinder( wxEVT_SYS_COLOUR_CHANGED )
+EVT_DISPLAY_CHANGED = wx.PyEventBinder( wxEVT_DISPLAY_CHANGED )
+EVT_SHOW = wx.PyEventBinder( wxEVT_SHOW )
+EVT_MAXIMIZE = wx.PyEventBinder( wxEVT_MAXIMIZE )
+EVT_ICONIZE = wx.PyEventBinder( wxEVT_ICONIZE )
+EVT_NAVIGATION_KEY = wx.PyEventBinder( wxEVT_NAVIGATION_KEY )
+EVT_PALETTE_CHANGED = wx.PyEventBinder( wxEVT_PALETTE_CHANGED )
+EVT_QUERY_NEW_PALETTE = wx.PyEventBinder( wxEVT_QUERY_NEW_PALETTE )
+EVT_WINDOW_CREATE = wx.PyEventBinder( wxEVT_CREATE )
+EVT_WINDOW_DESTROY = wx.PyEventBinder( wxEVT_DESTROY )
+EVT_SET_CURSOR = wx.PyEventBinder( wxEVT_SET_CURSOR )
+EVT_MOUSE_CAPTURE_CHANGED = wx.PyEventBinder( wxEVT_MOUSE_CAPTURE_CHANGED )
+EVT_MOUSE_CAPTURE_LOST = wx.PyEventBinder( wxEVT_MOUSE_CAPTURE_LOST )
+
+EVT_LEFT_DOWN = wx.PyEventBinder( wxEVT_LEFT_DOWN )
+EVT_LEFT_UP = wx.PyEventBinder( wxEVT_LEFT_UP )
+EVT_MIDDLE_DOWN = wx.PyEventBinder( wxEVT_MIDDLE_DOWN )
+EVT_MIDDLE_UP = wx.PyEventBinder( wxEVT_MIDDLE_UP )
+EVT_RIGHT_DOWN = wx.PyEventBinder( wxEVT_RIGHT_DOWN )
+EVT_RIGHT_UP = wx.PyEventBinder( wxEVT_RIGHT_UP )
+EVT_MOTION = wx.PyEventBinder( wxEVT_MOTION )
+EVT_LEFT_DCLICK = wx.PyEventBinder( wxEVT_LEFT_DCLICK )
+EVT_MIDDLE_DCLICK = wx.PyEventBinder( wxEVT_MIDDLE_DCLICK )
+EVT_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_RIGHT_DCLICK )
+EVT_LEAVE_WINDOW = wx.PyEventBinder( wxEVT_LEAVE_WINDOW )
+EVT_ENTER_WINDOW = wx.PyEventBinder( wxEVT_ENTER_WINDOW )
+EVT_MOUSEWHEEL = wx.PyEventBinder( wxEVT_MOUSEWHEEL )
+EVT_MOUSE_AUX1_DOWN = wx.PyEventBinder( wxEVT_AUX1_DOWN )
+EVT_MOUSE_AUX1_UP = wx.PyEventBinder( wxEVT_AUX1_UP )
+EVT_MOUSE_AUX1_DCLICK = wx.PyEventBinder( wxEVT_AUX1_DCLICK )
+EVT_MOUSE_AUX2_DOWN = wx.PyEventBinder( wxEVT_AUX2_DOWN )
+EVT_MOUSE_AUX2_UP = wx.PyEventBinder( wxEVT_AUX2_UP )
+EVT_MOUSE_AUX2_DCLICK = wx.PyEventBinder( wxEVT_AUX2_DCLICK )
+
+EVT_MOUSE_EVENTS = wx.PyEventBinder([ wxEVT_LEFT_DOWN,
+ wxEVT_LEFT_UP,
+ wxEVT_MIDDLE_DOWN,
+ wxEVT_MIDDLE_UP,
+ wxEVT_RIGHT_DOWN,
+ wxEVT_RIGHT_UP,
+ wxEVT_MOTION,
+ wxEVT_LEFT_DCLICK,
+ wxEVT_MIDDLE_DCLICK,
+ wxEVT_RIGHT_DCLICK,
+ wxEVT_ENTER_WINDOW,
+ wxEVT_LEAVE_WINDOW,
+ wxEVT_MOUSEWHEEL,
+ wxEVT_AUX1_DOWN,
+ wxEVT_AUX1_UP,
+ wxEVT_AUX1_DCLICK,
+ wxEVT_AUX2_DOWN,
+ wxEVT_AUX2_UP,
+ wxEVT_AUX2_DCLICK,
+ ])
+
+
+# Scrolling from wxWindow (sent to wxScrolledWindow)
+EVT_SCROLLWIN = wx.PyEventBinder([ wxEVT_SCROLLWIN_TOP,
+ wxEVT_SCROLLWIN_BOTTOM,
+ wxEVT_SCROLLWIN_LINEUP,
+ wxEVT_SCROLLWIN_LINEDOWN,
+ wxEVT_SCROLLWIN_PAGEUP,
+ wxEVT_SCROLLWIN_PAGEDOWN,
+ wxEVT_SCROLLWIN_THUMBTRACK,
+ wxEVT_SCROLLWIN_THUMBRELEASE,
+ ])
+
+EVT_SCROLLWIN_TOP = wx.PyEventBinder( wxEVT_SCROLLWIN_TOP )
+EVT_SCROLLWIN_BOTTOM = wx.PyEventBinder( wxEVT_SCROLLWIN_BOTTOM )
+EVT_SCROLLWIN_LINEUP = wx.PyEventBinder( wxEVT_SCROLLWIN_LINEUP )
+EVT_SCROLLWIN_LINEDOWN = wx.PyEventBinder( wxEVT_SCROLLWIN_LINEDOWN )
+EVT_SCROLLWIN_PAGEUP = wx.PyEventBinder( wxEVT_SCROLLWIN_PAGEUP )
+EVT_SCROLLWIN_PAGEDOWN = wx.PyEventBinder( wxEVT_SCROLLWIN_PAGEDOWN )
+EVT_SCROLLWIN_THUMBTRACK = wx.PyEventBinder( wxEVT_SCROLLWIN_THUMBTRACK )
+EVT_SCROLLWIN_THUMBRELEASE = wx.PyEventBinder( wxEVT_SCROLLWIN_THUMBRELEASE )
+
+# Scrolling from wx.Slider and wx.ScrollBar
+EVT_SCROLL = wx.PyEventBinder([ wxEVT_SCROLL_TOP,
+ wxEVT_SCROLL_BOTTOM,
+ wxEVT_SCROLL_LINEUP,
+ wxEVT_SCROLL_LINEDOWN,
+ wxEVT_SCROLL_PAGEUP,
+ wxEVT_SCROLL_PAGEDOWN,
+ wxEVT_SCROLL_THUMBTRACK,
+ wxEVT_SCROLL_THUMBRELEASE,
+ wxEVT_SCROLL_CHANGED,
+ ])
+
+EVT_SCROLL_TOP = wx.PyEventBinder( wxEVT_SCROLL_TOP )
+EVT_SCROLL_BOTTOM = wx.PyEventBinder( wxEVT_SCROLL_BOTTOM )
+EVT_SCROLL_LINEUP = wx.PyEventBinder( wxEVT_SCROLL_LINEUP )
+EVT_SCROLL_LINEDOWN = wx.PyEventBinder( wxEVT_SCROLL_LINEDOWN )
+EVT_SCROLL_PAGEUP = wx.PyEventBinder( wxEVT_SCROLL_PAGEUP )
+EVT_SCROLL_PAGEDOWN = wx.PyEventBinder( wxEVT_SCROLL_PAGEDOWN )
+EVT_SCROLL_THUMBTRACK = wx.PyEventBinder( wxEVT_SCROLL_THUMBTRACK )
+EVT_SCROLL_THUMBRELEASE = wx.PyEventBinder( wxEVT_SCROLL_THUMBRELEASE )
+EVT_SCROLL_CHANGED = wx.PyEventBinder( wxEVT_SCROLL_CHANGED )
+EVT_SCROLL_ENDSCROLL = EVT_SCROLL_CHANGED
+
+# Scrolling from wx.Slider and wx.ScrollBar, with an id
+EVT_COMMAND_SCROLL = wx.PyEventBinder([ wxEVT_SCROLL_TOP,
+ wxEVT_SCROLL_BOTTOM,
+ wxEVT_SCROLL_LINEUP,
+ wxEVT_SCROLL_LINEDOWN,
+ wxEVT_SCROLL_PAGEUP,
+ wxEVT_SCROLL_PAGEDOWN,
+ wxEVT_SCROLL_THUMBTRACK,
+ wxEVT_SCROLL_THUMBRELEASE,
+ wxEVT_SCROLL_CHANGED,
+ ], 1)
+
+EVT_COMMAND_SCROLL_TOP = wx.PyEventBinder( wxEVT_SCROLL_TOP, 1)
+EVT_COMMAND_SCROLL_BOTTOM = wx.PyEventBinder( wxEVT_SCROLL_BOTTOM, 1)
+EVT_COMMAND_SCROLL_LINEUP = wx.PyEventBinder( wxEVT_SCROLL_LINEUP, 1)
+EVT_COMMAND_SCROLL_LINEDOWN = wx.PyEventBinder( wxEVT_SCROLL_LINEDOWN, 1)
+EVT_COMMAND_SCROLL_PAGEUP = wx.PyEventBinder( wxEVT_SCROLL_PAGEUP, 1)
+EVT_COMMAND_SCROLL_PAGEDOWN = wx.PyEventBinder( wxEVT_SCROLL_PAGEDOWN, 1)
+EVT_COMMAND_SCROLL_THUMBTRACK = wx.PyEventBinder( wxEVT_SCROLL_THUMBTRACK, 1)
+EVT_COMMAND_SCROLL_THUMBRELEASE = wx.PyEventBinder( wxEVT_SCROLL_THUMBRELEASE, 1)
+EVT_COMMAND_SCROLL_CHANGED = wx.PyEventBinder( wxEVT_SCROLL_CHANGED, 1)
+EVT_COMMAND_SCROLL_ENDSCROLL = EVT_COMMAND_SCROLL_CHANGED
+
+EVT_BUTTON = wx.PyEventBinder( wxEVT_COMMAND_BUTTON_CLICKED, 1)
+EVT_CHECKBOX = wx.PyEventBinder( wxEVT_COMMAND_CHECKBOX_CLICKED, 1)
+EVT_CHOICE = wx.PyEventBinder( wxEVT_COMMAND_CHOICE_SELECTED, 1)
+EVT_LISTBOX = wx.PyEventBinder( wxEVT_COMMAND_LISTBOX_SELECTED, 1)
+EVT_LISTBOX_DCLICK = wx.PyEventBinder( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 1)
+EVT_MENU = wx.PyEventBinder( wxEVT_COMMAND_MENU_SELECTED, 1)
+EVT_MENU_RANGE = wx.PyEventBinder( wxEVT_COMMAND_MENU_SELECTED, 2)
+EVT_SLIDER = wx.PyEventBinder( wxEVT_COMMAND_SLIDER_UPDATED, 1)
+EVT_RADIOBOX = wx.PyEventBinder( wxEVT_COMMAND_RADIOBOX_SELECTED, 1)
+EVT_RADIOBUTTON = wx.PyEventBinder( wxEVT_COMMAND_RADIOBUTTON_SELECTED, 1)
+
+EVT_SCROLLBAR = wx.PyEventBinder( wxEVT_COMMAND_SCROLLBAR_UPDATED, 1)
+EVT_VLBOX = wx.PyEventBinder( wxEVT_COMMAND_VLBOX_SELECTED, 1)
+EVT_COMBOBOX = wx.PyEventBinder( wxEVT_COMMAND_COMBOBOX_SELECTED, 1)
+EVT_TOOL = wx.PyEventBinder( wxEVT_COMMAND_TOOL_CLICKED, 1)
+EVT_TOOL_RANGE = wx.PyEventBinder( wxEVT_COMMAND_TOOL_CLICKED, 2)
+EVT_TOOL_RCLICKED = wx.PyEventBinder( wxEVT_COMMAND_TOOL_RCLICKED, 1)
+EVT_TOOL_RCLICKED_RANGE = wx.PyEventBinder( wxEVT_COMMAND_TOOL_RCLICKED, 2)
+EVT_TOOL_ENTER = wx.PyEventBinder( wxEVT_COMMAND_TOOL_ENTER, 1)
+EVT_TOOL_DROPDOWN = wx.PyEventBinder( wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED, 1)
+EVT_CHECKLISTBOX = wx.PyEventBinder( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 1)
+EVT_COMBOBOX_DROPDOWN = wx.PyEventBinder( wxEVT_COMMAND_COMBOBOX_DROPDOWN , 1)
+EVT_COMBOBOX_CLOSEUP = wx.PyEventBinder( wxEVT_COMMAND_COMBOBOX_CLOSEUP , 1)
+
+EVT_COMMAND_LEFT_CLICK = wx.PyEventBinder( wxEVT_COMMAND_LEFT_CLICK, 1)
+EVT_COMMAND_LEFT_DCLICK = wx.PyEventBinder( wxEVT_COMMAND_LEFT_DCLICK, 1)
+EVT_COMMAND_RIGHT_CLICK = wx.PyEventBinder( wxEVT_COMMAND_RIGHT_CLICK, 1)
+EVT_COMMAND_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_COMMAND_RIGHT_DCLICK, 1)
+EVT_COMMAND_SET_FOCUS = wx.PyEventBinder( wxEVT_COMMAND_SET_FOCUS, 1)
+EVT_COMMAND_KILL_FOCUS = wx.PyEventBinder( wxEVT_COMMAND_KILL_FOCUS, 1)
+EVT_COMMAND_ENTER = wx.PyEventBinder( wxEVT_COMMAND_ENTER, 1)
+
+EVT_IDLE = wx.PyEventBinder( wxEVT_IDLE )
+
+EVT_UPDATE_UI = wx.PyEventBinder( wxEVT_UPDATE_UI, 1)
+EVT_UPDATE_UI_RANGE = wx.PyEventBinder( wxEVT_UPDATE_UI, 2)
+
+EVT_CONTEXT_MENU = wx.PyEventBinder( wxEVT_CONTEXT_MENU )
+
+EVT_TEXT_CUT = wx.PyEventBinder( wxEVT_COMMAND_TEXT_CUT )
+EVT_TEXT_COPY = wx.PyEventBinder( wxEVT_COMMAND_TEXT_COPY )
+EVT_TEXT_PASTE = wx.PyEventBinder( wxEVT_COMMAND_TEXT_PASTE )
+
+EVT_THREAD = wx.PyEventBinder( wxEVT_THREAD )
+
+#---------------------------------------------------------------------------
+
+class Event(Object):
+ """
+ An event is a structure holding information about an event passed to a
+ callback or member function. wx.Event is an abstract base class for
+ other event classes
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_Event
+ __del__ = lambda self : None;
+ def SetEventType(*args, **kwargs):
+ """
+ SetEventType(self, EventType typ)
+
+ Sets the specific type of the event.
+ """
+ return _core_.Event_SetEventType(*args, **kwargs)
+
+ def GetEventType(*args, **kwargs):
+ """
+ GetEventType(self) -> EventType
+
+ Returns the identifier of the given event type, such as
+ ``wxEVT_COMMAND_BUTTON_CLICKED``.
+ """
+ return _core_.Event_GetEventType(*args, **kwargs)
+
+ def GetEventObject(*args, **kwargs):
+ """
+ GetEventObject(self) -> Object
+
+ Returns the object (usually a window) associated with the event, if
+ any.
+ """
+ return _core_.Event_GetEventObject(*args, **kwargs)
+
+ def SetEventObject(*args, **kwargs):
+ """
+ SetEventObject(self, Object obj)
+
+ Sets the originating object, or in other words, obj is normally the
+ object that is sending the event.
+ """
+ return _core_.Event_SetEventObject(*args, **kwargs)
+
+ def GetTimestamp(*args, **kwargs):
+ """GetTimestamp(self) -> long"""
+ return _core_.Event_GetTimestamp(*args, **kwargs)
+
+ def SetTimestamp(*args, **kwargs):
+ """SetTimestamp(self, long ts=0)"""
+ return _core_.Event_SetTimestamp(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """
+ GetId(self) -> int
+
+ Returns the identifier associated with this event, such as a button
+ command id.
+ """
+ return _core_.Event_GetId(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """
+ SetId(self, int Id)
+
+ Set's the ID for the event. This is usually the ID of the window that
+ is sending the event, but it can also be a command id from a menu
+ item, etc.
+ """
+ return _core_.Event_SetId(*args, **kwargs)
+
+ def GetEventCategory(*args, **kwargs):
+ """GetEventCategory(self) -> int"""
+ return _core_.Event_GetEventCategory(*args, **kwargs)
+
+ def IsCommandEvent(*args, **kwargs):
+ """
+ IsCommandEvent(self) -> bool
+
+ Returns true if the event is or is derived from `wx.CommandEvent` else
+ it returns false. Note: Exists only for optimization purposes.
+ """
+ return _core_.Event_IsCommandEvent(*args, **kwargs)
+
+ def Skip(*args, **kwargs):
+ """
+ Skip(self, bool skip=True)
+
+ This method can be used inside an event handler to control whether
+ further event handlers bound to this event will be called after the
+ current one returns. Without Skip() (or equivalently if Skip(False) is
+ used), the event will not be processed any more. If Skip(True) is
+ called, the event processing system continues searching for a further
+ handler function for this event, even though it has been processed
+ already in the current handler.
+ """
+ return _core_.Event_Skip(*args, **kwargs)
+
+ def GetSkipped(*args, **kwargs):
+ """
+ GetSkipped(self) -> bool
+
+ Returns true if the event handler should be skipped, false otherwise.
+ :see: `Skip`
+ """
+ return _core_.Event_GetSkipped(*args, **kwargs)
+
+ def ShouldPropagate(*args, **kwargs):
+ """
+ ShouldPropagate(self) -> bool
+
+ Test if this event should be propagated to the parent window or not,
+ i.e. if the propagation level is currently greater than 0.
+ """
+ return _core_.Event_ShouldPropagate(*args, **kwargs)
+
+ def StopPropagation(*args, **kwargs):
+ """
+ StopPropagation(self) -> int
+
+ Stop the event from propagating to its parent window. Returns the old
+ propagation level value which may be later passed to
+ `ResumePropagation` to allow propagating the event again.
+ """
+ return _core_.Event_StopPropagation(*args, **kwargs)
+
+ def ResumePropagation(*args, **kwargs):
+ """
+ ResumePropagation(self, int propagationLevel)
+
+ Resume the event propagation by restoring the propagation level. (For
+ example, you can use the value returned by an earlier call to
+ `StopPropagation`.)
+
+ """
+ return _core_.Event_ResumePropagation(*args, **kwargs)
+
+ def WasProcessed(*args, **kwargs):
+ """WasProcessed(self) -> bool"""
+ return _core_.Event_WasProcessed(*args, **kwargs)
+
+ def ShouldProcessOnlyIn(*args, **kwargs):
+ """ShouldProcessOnlyIn(self, EvtHandler h) -> bool"""
+ return _core_.Event_ShouldProcessOnlyIn(*args, **kwargs)
+
+ def DidntHonourProcessOnlyIn(*args, **kwargs):
+ """DidntHonourProcessOnlyIn(self)"""
+ return _core_.Event_DidntHonourProcessOnlyIn(*args, **kwargs)
+
+ def Clone(*args, **kwargs):
+ """Clone(self) -> Event"""
+ return _core_.Event_Clone(*args, **kwargs)
+
+ EventObject = property(GetEventObject,SetEventObject,doc="See `GetEventObject` and `SetEventObject`")
+ EventType = property(GetEventType,SetEventType,doc="See `GetEventType` and `SetEventType`")
+ Id = property(GetId,SetId,doc="See `GetId` and `SetId`")
+ Skipped = property(GetSkipped,doc="See `GetSkipped`")
+ Timestamp = property(GetTimestamp,SetTimestamp,doc="See `GetTimestamp` and `SetTimestamp`")
+_core_.Event_swigregister(Event)
+
+#---------------------------------------------------------------------------
+
+class PropagationDisabler(object):
+ """
+ Helper class to temporarily change an event not to propagate. Simply
+ create an instance of this class and then whe it is destroyed the
+ propogation of the event will be restored.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Event event) -> PropagationDisabler
+
+ Helper class to temporarily change an event not to propagate. Simply
+ create an instance of this class and then whe it is destroyed the
+ propogation of the event will be restored.
+ """
+ _core_.PropagationDisabler_swiginit(self,_core_.new_PropagationDisabler(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_PropagationDisabler
+ __del__ = lambda self : None;
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_core_.PropagationDisabler_swigregister(PropagationDisabler)
+
+class PropagateOnce(object):
+ """
+ A helper class that will temporarily lower propagation level of an
+ event. Simply create an instance of this class and then whe it is
+ destroyed the propogation of the event will be restored.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Event event) -> PropagateOnce
+
+ A helper class that will temporarily lower propagation level of an
+ event. Simply create an instance of this class and then whe it is
+ destroyed the propogation of the event will be restored.
+ """
+ _core_.PropagateOnce_swiginit(self,_core_.new_PropagateOnce(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_PropagateOnce
+ __del__ = lambda self : None;
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_core_.PropagateOnce_swigregister(PropagateOnce)
+
+class EventProcessInHandlerOnly(object):
+ """Proxy of C++ EventProcessInHandlerOnly class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Event event, EvtHandler handler) -> EventProcessInHandlerOnly"""
+ _core_.EventProcessInHandlerOnly_swiginit(self,_core_.new_EventProcessInHandlerOnly(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_EventProcessInHandlerOnly
+ __del__ = lambda self : None;
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_core_.EventProcessInHandlerOnly_swigregister(EventProcessInHandlerOnly)
+
+#---------------------------------------------------------------------------
+
+class CommandEvent(Event):
+ """
+ This event class contains information about command events, which
+ originate from a variety of simple controls, as well as menus and
+ toolbars.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType commandType=wxEVT_NULL, int winid=0) -> CommandEvent
+
+ This event class contains information about command events, which
+ originate from a variety of simple controls, as well as menus and
+ toolbars.
+ """
+ _core_.CommandEvent_swiginit(self,_core_.new_CommandEvent(*args, **kwargs))
+ def GetSelection(*args, **kwargs):
+ """
+ GetSelection(self) -> int
+
+ Returns item index for a listbox or choice selection event (not valid
+ for a deselection).
+ """
+ return _core_.CommandEvent_GetSelection(*args, **kwargs)
+
+ def SetString(*args, **kwargs):
+ """SetString(self, String s)"""
+ return _core_.CommandEvent_SetString(*args, **kwargs)
+
+ def GetString(*args, **kwargs):
+ """
+ GetString(self) -> String
+
+ Returns item string for a listbox or choice selection event (not valid
+ for a deselection).
+ """
+ return _core_.CommandEvent_GetString(*args, **kwargs)
+
+ def IsChecked(*args, **kwargs):
+ """
+ IsChecked(self) -> bool
+
+ This method can be used with checkbox and menu events: for the
+ checkboxes, the method returns true for a selection event and false
+ for a deselection one. For the menu events, this method indicates if
+ the menu item just has become checked or unchecked (and thus only
+ makes sense for checkable menu items).
+ """
+ return _core_.CommandEvent_IsChecked(*args, **kwargs)
+
+ Checked = IsChecked
+ def IsSelection(*args, **kwargs):
+ """
+ IsSelection(self) -> bool
+
+ For a listbox or similar event, returns true if it is a selection,
+ false if it is a deselection.
+ """
+ return _core_.CommandEvent_IsSelection(*args, **kwargs)
+
+ def SetExtraLong(*args, **kwargs):
+ """SetExtraLong(self, long extraLong)"""
+ return _core_.CommandEvent_SetExtraLong(*args, **kwargs)
+
+ def GetExtraLong(*args, **kwargs):
+ """
+ GetExtraLong(self) -> long
+
+ Returns extra information dependant on the event objects type. If the
+ event comes from a listbox selection, it is a boolean determining
+ whether the event was a selection (true) or a deselection (false). A
+ listbox deselection only occurs for multiple-selection boxes, and in
+ this case the index and string values are indeterminate and the
+ listbox must be examined by the application.
+ """
+ return _core_.CommandEvent_GetExtraLong(*args, **kwargs)
+
+ def SetInt(*args, **kwargs):
+ """SetInt(self, int i)"""
+ return _core_.CommandEvent_SetInt(*args, **kwargs)
+
+ def GetInt(*args, **kwargs):
+ """
+ GetInt(self) -> int
+
+ Returns the integer identifier corresponding to a listbox, choice or
+ radiobox selection (only if the event was a selection, not a
+ deselection), or a boolean value representing the value of a checkbox.
+ """
+ return _core_.CommandEvent_GetInt(*args, **kwargs)
+
+ def GetClientData(*args, **kwargs):
+ """
+ GetClientData(self) -> PyObject
+
+ Returns the client data object for a listbox or choice selection event, (if any.)
+ """
+ return _core_.CommandEvent_GetClientData(*args, **kwargs)
+
+ def SetClientData(*args, **kwargs):
+ """
+ SetClientData(self, PyObject clientData)
+
+ Associate the given client data with the item at position n.
+ """
+ return _core_.CommandEvent_SetClientData(*args, **kwargs)
+
+ GetClientObject = GetClientData
+ SetClientObject = SetClientData
+
+ def Clone(*args, **kwargs):
+ """Clone(self) -> Event"""
+ return _core_.CommandEvent_Clone(*args, **kwargs)
+
+ ClientData = property(GetClientData,SetClientData,doc="See `GetClientData` and `SetClientData`")
+ ClientObject = property(GetClientObject,SetClientObject,doc="See `GetClientObject` and `SetClientObject`")
+ ExtraLong = property(GetExtraLong,SetExtraLong,doc="See `GetExtraLong` and `SetExtraLong`")
+ Int = property(GetInt,SetInt,doc="See `GetInt` and `SetInt`")
+ Selection = property(GetSelection,doc="See `GetSelection`")
+ String = property(GetString,SetString,doc="See `GetString` and `SetString`")
+_core_.CommandEvent_swigregister(CommandEvent)
+
+#---------------------------------------------------------------------------
+
+class NotifyEvent(CommandEvent):
+ """
+ An instance of this class (or one of its derived classes) is sent from
+ a control when the control's state is being changed and the control
+ allows that change to be prevented from happening. The event handler
+ can call `Veto` or `Allow` to tell the control what to do.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType commandType=wxEVT_NULL, int winid=0) -> NotifyEvent
+
+ An instance of this class (or one of its derived classes) is sent from
+ a control when the control's state is being changed and the control
+ allows that change to be prevented from happening. The event handler
+ can call `Veto` or `Allow` to tell the control what to do.
+ """
+ _core_.NotifyEvent_swiginit(self,_core_.new_NotifyEvent(*args, **kwargs))
+ def Veto(*args, **kwargs):
+ """
+ Veto(self)
+
+ Prevents the change announced by this event from happening.
+
+ It is in general a good idea to notify the user about the reasons for
+ vetoing the change because otherwise the applications behaviour (which
+ just refuses to do what the user wants) might be quite surprising.
+ """
+ return _core_.NotifyEvent_Veto(*args, **kwargs)
+
+ def Allow(*args, **kwargs):
+ """
+ Allow(self)
+
+ This is the opposite of `Veto`: it explicitly allows the event to be
+ processed. For most events it is not necessary to call this method as
+ the events are allowed anyhow but some are forbidden by default (this
+ will be mentioned in the corresponding event description).
+ """
+ return _core_.NotifyEvent_Allow(*args, **kwargs)
+
+ def IsAllowed(*args, **kwargs):
+ """
+ IsAllowed(self) -> bool
+
+ Returns true if the change is allowed (`Veto` hasn't been called) or
+ false otherwise (if it was).
+ """
+ return _core_.NotifyEvent_IsAllowed(*args, **kwargs)
+
+_core_.NotifyEvent_swigregister(NotifyEvent)
+
+#---------------------------------------------------------------------------
+
+class ThreadEvent(Event):
+ """Proxy of C++ ThreadEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType eventType=wxEVT_THREAD, int id=ID_ANY) -> ThreadEvent"""
+ _core_.ThreadEvent_swiginit(self,_core_.new_ThreadEvent(*args, **kwargs))
+ def GetExtraLong(*args, **kwargs):
+ """GetExtraLong(self) -> long"""
+ return _core_.ThreadEvent_GetExtraLong(*args, **kwargs)
+
+ def GetInt(*args, **kwargs):
+ """GetInt(self) -> int"""
+ return _core_.ThreadEvent_GetInt(*args, **kwargs)
+
+ def GetString(*args, **kwargs):
+ """GetString(self) -> String"""
+ return _core_.ThreadEvent_GetString(*args, **kwargs)
+
+ def SetExtraLong(*args, **kwargs):
+ """SetExtraLong(self, long extraLong)"""
+ return _core_.ThreadEvent_SetExtraLong(*args, **kwargs)
+
+ def SetInt(*args, **kwargs):
+ """SetInt(self, int intCommand)"""
+ return _core_.ThreadEvent_SetInt(*args, **kwargs)
+
+ def SetString(*args, **kwargs):
+ """SetString(self, String string)"""
+ return _core_.ThreadEvent_SetString(*args, **kwargs)
+
+ ExtraLong = property(GetExtraLong,SetExtraLong,doc="See `GetExtraLong` and `SetExtraLong`")
+ Int = property(GetInt,SetInt,doc="See `GetInt` and `SetInt`")
+ String = property(GetString,SetString,doc="See `GetString` and `SetString`")
+_core_.ThreadEvent_swigregister(ThreadEvent)
+
+#---------------------------------------------------------------------------
+
+class ScrollEvent(CommandEvent):
+ """
+ A scroll event holds information about events sent from stand-alone
+ scrollbars and sliders. Note that scrolled windows do not send
+ instances of this event class, but send the `wx.ScrollWinEvent`
+ instead.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType commandType=wxEVT_NULL, int winid=0, int pos=0,
+ int orient=0) -> ScrollEvent
+ """
+ _core_.ScrollEvent_swiginit(self,_core_.new_ScrollEvent(*args, **kwargs))
+ def GetOrientation(*args, **kwargs):
+ """
+ GetOrientation(self) -> int
+
+ Returns wx.HORIZONTAL or wx.VERTICAL, depending on the orientation of
+ the scrollbar.
+ """
+ return _core_.ScrollEvent_GetOrientation(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """
+ GetPosition(self) -> int
+
+ Returns the position of the scrollbar.
+ """
+ return _core_.ScrollEvent_GetPosition(*args, **kwargs)
+
+ def SetOrientation(*args, **kwargs):
+ """SetOrientation(self, int orient)"""
+ return _core_.ScrollEvent_SetOrientation(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, int pos)"""
+ return _core_.ScrollEvent_SetPosition(*args, **kwargs)
+
+ Orientation = property(GetOrientation,SetOrientation,doc="See `GetOrientation` and `SetOrientation`")
+ Position = property(GetPosition,SetPosition,doc="See `GetPosition` and `SetPosition`")
+_core_.ScrollEvent_swigregister(ScrollEvent)
+
+#---------------------------------------------------------------------------
+
+class ScrollWinEvent(Event):
+ """
+ A wx.ScrollWinEvent holds information about scrolling and is sent from
+ scrolling windows.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType commandType=wxEVT_NULL, int pos=0, int orient=0) -> ScrollWinEvent
+
+ A wx.ScrollWinEvent holds information about scrolling and is sent from
+ scrolling windows.
+ """
+ _core_.ScrollWinEvent_swiginit(self,_core_.new_ScrollWinEvent(*args, **kwargs))
+ def GetOrientation(*args, **kwargs):
+ """
+ GetOrientation(self) -> int
+
+ Returns wx.HORIZONTAL or wx.VERTICAL, depending on the orientation of
+ the scrollbar.
+ """
+ return _core_.ScrollWinEvent_GetOrientation(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """
+ GetPosition(self) -> int
+
+ Returns the position of the scrollbar for the thumb track and release
+ events. Note that this field can't be used for the other events, you
+ need to query the window itself for the current position in that case.
+ """
+ return _core_.ScrollWinEvent_GetPosition(*args, **kwargs)
+
+ def SetOrientation(*args, **kwargs):
+ """SetOrientation(self, int orient)"""
+ return _core_.ScrollWinEvent_SetOrientation(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, int pos)"""
+ return _core_.ScrollWinEvent_SetPosition(*args, **kwargs)
+
+ Orientation = property(GetOrientation,SetOrientation,doc="See `GetOrientation` and `SetOrientation`")
+ Position = property(GetPosition,SetPosition,doc="See `GetPosition` and `SetPosition`")
+_core_.ScrollWinEvent_swigregister(ScrollWinEvent)
+
+#---------------------------------------------------------------------------
+
+MOUSE_WHEEL_VERTICAL = _core_.MOUSE_WHEEL_VERTICAL
+MOUSE_WHEEL_HORIZONTAL = _core_.MOUSE_WHEEL_HORIZONTAL
+class MouseEvent(Event,MouseState):
+ """
+ This event class contains information about the events generated by
+ the mouse: they include mouse buttons press and release events and
+ mouse move events.
+
+ All mouse events involving the buttons use ``wx.MOUSE_BTN_LEFT`` for
+ the left mouse button, ``wx.MOUSE_BTN_MIDDLE`` for the middle one and
+ ``wx.MOUSE_BTN_RIGHT`` for the right one. Note that not all mice have
+ a middle button so a portable application should avoid relying on the
+ events from it.
+
+ Note the difference between methods like `LeftDown` and `LeftIsDown`:
+ the former returns true when the event corresponds to the left mouse
+ button click while the latter returns true if the left mouse button is
+ currently being pressed. For example, when the user is dragging the
+ mouse you can use `LeftIsDown` to test whether the left mouse button
+ is (still) depressed. Also, by convention, if `LeftDown` returns true,
+ `LeftIsDown` will also return true in wxWidgets whatever the
+ underlying GUI behaviour is (which is platform-dependent). The same
+ applies, of course, to other mouse buttons as well.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType mouseType=wxEVT_NULL) -> MouseEvent
+
+ Constructs a wx.MouseEvent. Valid event types are:
+
+ * wxEVT_ENTER_WINDOW
+ * wxEVT_LEAVE_WINDOW
+ * wxEVT_LEFT_DOWN
+ * wxEVT_LEFT_UP
+ * wxEVT_LEFT_DCLICK
+ * wxEVT_MIDDLE_DOWN
+ * wxEVT_MIDDLE_UP
+ * wxEVT_MIDDLE_DCLICK
+ * wxEVT_RIGHT_DOWN
+ * wxEVT_RIGHT_UP
+ * wxEVT_RIGHT_DCLICK
+ * wxEVT_MOTION
+ * wxEVT_MOUSEWHEEL
+ """
+ _core_.MouseEvent_swiginit(self,_core_.new_MouseEvent(*args, **kwargs))
+ def IsButton(*args, **kwargs):
+ """
+ IsButton(self) -> bool
+
+ Returns true if the event was a mouse button event (not necessarily a
+ button down event - that may be tested using `ButtonDown`).
+ """
+ return _core_.MouseEvent_IsButton(*args, **kwargs)
+
+ def ButtonDown(*args, **kwargs):
+ """
+ ButtonDown(self, int but=MOUSE_BTN_ANY) -> bool
+
+ If the argument is omitted, this returns true if the event was any
+ mouse button down event. Otherwise the argument specifies which
+ button-down event shold be checked for (see `Button` for the possible
+ values).
+ """
+ return _core_.MouseEvent_ButtonDown(*args, **kwargs)
+
+ def ButtonDClick(*args, **kwargs):
+ """
+ ButtonDClick(self, int but=MOUSE_BTN_ANY) -> bool
+
+ If the argument is omitted, this returns true if the event was any
+ mouse double click event. Otherwise the argument specifies which
+ double click event to check for (see `Button` for the possible
+ values).
+ """
+ return _core_.MouseEvent_ButtonDClick(*args, **kwargs)
+
+ def ButtonUp(*args, **kwargs):
+ """
+ ButtonUp(self, int but=MOUSE_BTN_ANY) -> bool
+
+ If the argument is omitted, this returns true if the event was any
+ mouse button up event. Otherwise the argument specifies which button
+ up event to check for (see `Button` for the possible values).
+ """
+ return _core_.MouseEvent_ButtonUp(*args, **kwargs)
+
+ def Button(*args, **kwargs):
+ """
+ Button(self, int button) -> bool
+
+ Returns true if the identified mouse button is changing state. Valid
+ values of button are:
+
+ ==================== =====================================
+ wx.MOUSE_BTN_LEFT check if left button was pressed
+ wx.MOUSE_BTN_MIDDLE check if middle button was pressed
+ wx.MOUSE_BTN_RIGHT check if right button was pressed
+ wx.MOUSE_BTN_ANY check if any button was pressed
+ ==================== =====================================
+
+ """
+ return _core_.MouseEvent_Button(*args, **kwargs)
+
+ def GetButton(*args, **kwargs):
+ """
+ GetButton(self) -> int
+
+ Returns the mouse button which generated this event or
+ wx.MOUSE_BTN_NONE if no button is involved (for mouse move, enter or
+ leave event, for example). Otherwise wx.MOUSE_BTN_LEFT is returned for
+ the left button down, up and double click events, wx.MOUSE_BTN_MIDDLE
+ and wx.MOUSE_BTN_RIGHT for the same events for the middle and the
+ right buttons respectively.
+ """
+ return _core_.MouseEvent_GetButton(*args, **kwargs)
+
+ def LeftDown(*args, **kwargs):
+ """
+ LeftDown(self) -> bool
+
+ Returns true if the left mouse button state changed to down.
+ """
+ return _core_.MouseEvent_LeftDown(*args, **kwargs)
+
+ def MiddleDown(*args, **kwargs):
+ """
+ MiddleDown(self) -> bool
+
+ Returns true if the middle mouse button state changed to down.
+ """
+ return _core_.MouseEvent_MiddleDown(*args, **kwargs)
+
+ def RightDown(*args, **kwargs):
+ """
+ RightDown(self) -> bool
+
+ Returns true if the right mouse button state changed to down.
+ """
+ return _core_.MouseEvent_RightDown(*args, **kwargs)
+
+ def Aux1Down(*args, **kwargs):
+ """
+ Aux1Down(self) -> bool
+
+ Returns true if the AUX1 mouse button state changed to down.
+ """
+ return _core_.MouseEvent_Aux1Down(*args, **kwargs)
+
+ def Aux2Down(*args, **kwargs):
+ """
+ Aux2Down(self) -> bool
+
+ Returns true if the AUX2 mouse button state changed to down.
+ """
+ return _core_.MouseEvent_Aux2Down(*args, **kwargs)
+
+ def LeftUp(*args, **kwargs):
+ """
+ LeftUp(self) -> bool
+
+ Returns true if the left mouse button state changed to up.
+ """
+ return _core_.MouseEvent_LeftUp(*args, **kwargs)
+
+ def MiddleUp(*args, **kwargs):
+ """
+ MiddleUp(self) -> bool
+
+ Returns true if the middle mouse button state changed to up.
+ """
+ return _core_.MouseEvent_MiddleUp(*args, **kwargs)
+
+ def RightUp(*args, **kwargs):
+ """
+ RightUp(self) -> bool
+
+ Returns true if the right mouse button state changed to up.
+ """
+ return _core_.MouseEvent_RightUp(*args, **kwargs)
+
+ def Aux1Up(*args, **kwargs):
+ """
+ Aux1Up(self) -> bool
+
+ Returns true if the AUX1 mouse button state changed to up.
+ """
+ return _core_.MouseEvent_Aux1Up(*args, **kwargs)
+
+ def Aux2Up(*args, **kwargs):
+ """
+ Aux2Up(self) -> bool
+
+ Returns true if the AUX2 mouse button state changed to up.
+ """
+ return _core_.MouseEvent_Aux2Up(*args, **kwargs)
+
+ def LeftDClick(*args, **kwargs):
+ """
+ LeftDClick(self) -> bool
+
+ Returns true if the event was a left button double click.
+ """
+ return _core_.MouseEvent_LeftDClick(*args, **kwargs)
+
+ def MiddleDClick(*args, **kwargs):
+ """
+ MiddleDClick(self) -> bool
+
+ Returns true if the event was a middle button double click.
+ """
+ return _core_.MouseEvent_MiddleDClick(*args, **kwargs)
+
+ def RightDClick(*args, **kwargs):
+ """
+ RightDClick(self) -> bool
+
+ Returns true if the event was a right button double click.
+ """
+ return _core_.MouseEvent_RightDClick(*args, **kwargs)
+
+ def Aux1DClick(*args, **kwargs):
+ """
+ Aux1DClick(self) -> bool
+
+ Returns true if the event was a AUX2 button double click.
+ """
+ return _core_.MouseEvent_Aux1DClick(*args, **kwargs)
+
+ def Aux2DClick(*args, **kwargs):
+ """
+ Aux2DClick(self) -> bool
+
+ Returns true if the event was a AUX2 button double click.
+ """
+ return _core_.MouseEvent_Aux2DClick(*args, **kwargs)
+
+ def Dragging(*args, **kwargs):
+ """
+ Dragging(self) -> bool
+
+ Returns true if this was a dragging event (motion while a button is
+ depressed).
+ """
+ return _core_.MouseEvent_Dragging(*args, **kwargs)
+
+ def Moving(*args, **kwargs):
+ """
+ Moving(self) -> bool
+
+ Returns true if this was a motion event and no mouse buttons were
+ pressed. If any mouse button is held pressed, then this method returns
+ false and Dragging returns true.
+ """
+ return _core_.MouseEvent_Moving(*args, **kwargs)
+
+ def Entering(*args, **kwargs):
+ """
+ Entering(self) -> bool
+
+ Returns true if the mouse was entering the window.
+ """
+ return _core_.MouseEvent_Entering(*args, **kwargs)
+
+ def Leaving(*args, **kwargs):
+ """
+ Leaving(self) -> bool
+
+ Returns true if the mouse was leaving the window.
+ """
+ return _core_.MouseEvent_Leaving(*args, **kwargs)
+
+ def GetClickCount(*args, **kwargs):
+ """
+ GetClickCount(self) -> int
+
+ Returns the number of mouse clicks associated with this event.
+ """
+ return _core_.MouseEvent_GetClickCount(*args, **kwargs)
+
+ def GetLogicalPosition(*args, **kwargs):
+ """
+ GetLogicalPosition(self, DC dc) -> Point
+
+ Returns the logical mouse position in pixels (i.e. translated
+ according to the translation set for the DC, which usually indicates
+ that the window has been scrolled).
+ """
+ return _core_.MouseEvent_GetLogicalPosition(*args, **kwargs)
+
+ def GetWheelRotation(*args, **kwargs):
+ """
+ GetWheelRotation(self) -> int
+
+ Get wheel rotation, positive or negative indicates direction of
+ rotation. Current devices all send an event when rotation is equal to
+ +/-WheelDelta, but this allows for finer resolution devices to be
+ created in the future. Because of this you shouldn't assume that one
+ event is equal to 1 line or whatever, but you should be able to either
+ do partial line scrolling or wait until +/-WheelDelta rotation values
+ have been accumulated before scrolling.
+ """
+ return _core_.MouseEvent_GetWheelRotation(*args, **kwargs)
+
+ def GetWheelDelta(*args, **kwargs):
+ """
+ GetWheelDelta(self) -> int
+
+ Get wheel delta, normally 120. This is the threshold for action to be
+ taken, and one such action (for example, scrolling one increment)
+ should occur for each delta.
+ """
+ return _core_.MouseEvent_GetWheelDelta(*args, **kwargs)
+
+ def GetWheelAxis(*args, **kwargs):
+ """
+ GetWheelAxis(self) -> int
+
+ Gets the axis the wheel operation concerns, 0 being the y axis as on
+ most mouse wheels, 1 is the x axis for things like MightyMouse scrolls
+ or horizontal trackpad scrolling.
+ """
+ return _core_.MouseEvent_GetWheelAxis(*args, **kwargs)
+
+ def GetLinesPerAction(*args, **kwargs):
+ """
+ GetLinesPerAction(self) -> int
+
+ Returns the configured number of lines (or whatever) to be scrolled
+ per wheel action. Defaults to three.
+ """
+ return _core_.MouseEvent_GetLinesPerAction(*args, **kwargs)
+
+ def IsPageScroll(*args, **kwargs):
+ """
+ IsPageScroll(self) -> bool
+
+ Returns true if the system has been setup to do page scrolling with
+ the mouse wheel instead of line scrolling.
+ """
+ return _core_.MouseEvent_IsPageScroll(*args, **kwargs)
+
+ LinesPerAction = property(GetLinesPerAction,doc="See `GetLinesPerAction`")
+ LogicalPosition = property(GetLogicalPosition,doc="See `GetLogicalPosition`")
+ WheelDelta = property(GetWheelDelta,doc="See `GetWheelDelta`")
+ WheelRotation = property(GetWheelRotation,doc="See `GetWheelRotation`")
+_core_.MouseEvent_swigregister(MouseEvent)
+
+#---------------------------------------------------------------------------
+
+class SetCursorEvent(Event):
+ """
+ A SetCursorEvent is generated when the mouse cursor is about to be set
+ as a result of mouse motion. This event gives the application the
+ chance to perform specific mouse cursor processing based on the
+ current position of the mouse within the window. Use the `SetCursor`
+ method to specify the cursor you want to be displayed.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int x=0, int y=0) -> SetCursorEvent
+
+ Construct a new `wx.SetCursorEvent`.
+ """
+ _core_.SetCursorEvent_swiginit(self,_core_.new_SetCursorEvent(*args, **kwargs))
+ def GetX(*args, **kwargs):
+ """
+ GetX(self) -> int
+
+ Returns the X coordinate of the mouse in client coordinates.
+ """
+ return _core_.SetCursorEvent_GetX(*args, **kwargs)
+
+ def GetY(*args, **kwargs):
+ """
+ GetY(self) -> int
+
+ Returns the Y coordinate of the mouse in client coordinates.
+ """
+ return _core_.SetCursorEvent_GetY(*args, **kwargs)
+
+ def SetCursor(*args, **kwargs):
+ """
+ SetCursor(self, Cursor cursor)
+
+ Sets the cursor associated with this event.
+ """
+ return _core_.SetCursorEvent_SetCursor(*args, **kwargs)
+
+ def GetCursor(*args, **kwargs):
+ """
+ GetCursor(self) -> Cursor
+
+ Returns a reference to the cursor specified by this event.
+ """
+ return _core_.SetCursorEvent_GetCursor(*args, **kwargs)
+
+ def HasCursor(*args, **kwargs):
+ """
+ HasCursor(self) -> bool
+
+ Returns true if the cursor specified by this event is a valid cursor.
+ """
+ return _core_.SetCursorEvent_HasCursor(*args, **kwargs)
+
+ Cursor = property(GetCursor,SetCursor,doc="See `GetCursor` and `SetCursor`")
+ X = property(GetX,doc="See `GetX`")
+ Y = property(GetY,doc="See `GetY`")
+_core_.SetCursorEvent_swigregister(SetCursorEvent)
+
+#---------------------------------------------------------------------------
+
+WXK_CATEGORY_ARROW = _core_.WXK_CATEGORY_ARROW
+WXK_CATEGORY_PAGING = _core_.WXK_CATEGORY_PAGING
+WXK_CATEGORY_JUMP = _core_.WXK_CATEGORY_JUMP
+WXK_CATEGORY_TAB = _core_.WXK_CATEGORY_TAB
+WXK_CATEGORY_CUT = _core_.WXK_CATEGORY_CUT
+WXK_CATEGORY_NAVIGATION = _core_.WXK_CATEGORY_NAVIGATION
+class KeyEvent(Event,KeyboardState):
+ """
+ This event class contains information about keypress and character
+ events. These events are only sent to the widget that currently has
+ the keyboard focus.
+
+ Notice that there are three different kinds of keyboard events in
+ wxWidgets: key down and up events and char events. The difference
+ between the first two is clear - the first corresponds to a key press
+ and the second to a key release - otherwise they are identical. Just
+ note that if the key is maintained in a pressed state you will
+ typically get a lot of (automatically generated) down events but only
+ one up so it is wrong to assume that there is one up event
+ corresponding to each down one.
+
+ Both key events provide untranslated key codes while the char event
+ carries the translated one. The untranslated code for alphanumeric
+ keys is always an upper case value. For the other keys it is one of
+ WXK_XXX values from the keycodes table. The translated key is, in
+ general, the character the user expects to appear as the result of the
+ key combination when typing the text into a text entry zone, for
+ example.
+
+ A few examples to clarify this (all assume that CAPS LOCK is unpressed
+ and the standard US keyboard): when the 'A' key is pressed, the key
+ down event key code is equal to ASCII A == 65. But the char event key
+ code is ASCII a == 97. On the other hand, if you press both SHIFT and
+ 'A' keys simultaneously , the key code in key down event will still be
+ just 'A' while the char event key code parameter will now be 'A' as
+ well.
+
+ Although in this simple case it is clear that the correct key code
+ could be found in the key down event handler by checking the value
+ returned by `ShiftDown`, in general you should use EVT_CHAR for this
+ as for non alphanumeric keys or non-US keyboard layouts the
+ translation is keyboard-layout dependent and can only be done properly
+ by the system itself.
+
+ Another kind of translation is done when the control key is pressed:
+ for example, for CTRL-A key press the key down event still carries the
+ same key code 'A' as usual but the char event will have key code of 1,
+ the ASCII value of this key combination.
+
+ You may discover how the other keys on your system behave
+ interactively by running the KeyEvents sample in the wxPython demo and
+ pressing some keys while the blue box at the top has the keyboard
+ focus.
+
+ **Note**: If a key down event is caught and the event handler does not
+ call event.Skip() then the coresponding char event will not
+ happen. This is by design and enables the programs that handle both
+ types of events to be a bit simpler.
+
+ **Note for Windows programmers**: The key and char events in wxWidgets
+ are similar to but slightly different from Windows WM_KEYDOWN and
+ WM_CHAR events. In particular, Alt-x combination will generate a char
+ event in wxWidgets (unless it is used as an accelerator).
+
+ **Tip**: be sure to call event.Skip() for events that you don't
+ process in key event function, otherwise menu shortcuts may cease to
+ work under Windows.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType eventType=wxEVT_NULL) -> KeyEvent
+
+ Construct a new `wx.KeyEvent`. Valid event types are:
+ *
+ """
+ _core_.KeyEvent_swiginit(self,_core_.new_KeyEvent(*args, **kwargs))
+ def GetKeyCode(*args, **kwargs):
+ """
+ GetKeyCode(self) -> int
+
+ Returns the virtual key code. ASCII events return normal ASCII values,
+ while non-ASCII events return values such as WXK_LEFT for the left
+ cursor key. See `wx.KeyEvent` for a full list of the virtual key
+ codes.
+
+ Note that in Unicode build, the returned value is meaningful only if
+ the user entered a character that can be represented in current
+ locale's default charset. You can obtain the corresponding Unicode
+ character using `GetUnicodeKey`.
+ """
+ return _core_.KeyEvent_GetKeyCode(*args, **kwargs)
+
+ def IsKeyInCategory(*args, **kwargs):
+ """IsKeyInCategory(self, int category) -> bool"""
+ return _core_.KeyEvent_IsKeyInCategory(*args, **kwargs)
+
+ def GetUnicodeKey(*args, **kwargs):
+ """
+ GetUnicodeKey(self) -> int
+
+ Returns the Unicode character corresponding to this key event. This
+ function is only meaningful in a Unicode build of wxPython.
+ """
+ return _core_.KeyEvent_GetUnicodeKey(*args, **kwargs)
+
+ GetUniChar = GetUnicodeKey
+ def SetUnicodeKey(*args, **kwargs):
+ """
+ SetUnicodeKey(self, int uniChar)
+
+ Set the Unicode value of the key event, but only if this is a Unicode
+ build of wxPython.
+ """
+ return _core_.KeyEvent_SetUnicodeKey(*args, **kwargs)
+
+ def GetRawKeyCode(*args, **kwargs):
+ """
+ GetRawKeyCode(self) -> unsigned int
+
+ Returns the raw key code for this event. This is a platform-dependent
+ scan code which should only be used in advanced
+ applications. Currently the raw key codes are not supported by all
+ ports.
+ """
+ return _core_.KeyEvent_GetRawKeyCode(*args, **kwargs)
+
+ def GetRawKeyFlags(*args, **kwargs):
+ """
+ GetRawKeyFlags(self) -> unsigned int
+
+ Returns the low level key flags for this event. The flags are
+ platform-dependent and should only be used in advanced applications.
+ Currently the raw key flags are not supported by all ports.
+ """
+ return _core_.KeyEvent_GetRawKeyFlags(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """
+ GetPosition(self) -> Point
+
+ Find the position of the event, if applicable.
+ """
+ return _core_.KeyEvent_GetPosition(*args, **kwargs)
+
+ def GetPositionTuple(*args, **kwargs):
+ """
+ GetPositionTuple() -> (x,y)
+
+ Find the position of the event, if applicable.
+ """
+ return _core_.KeyEvent_GetPositionTuple(*args, **kwargs)
+
+ def GetX(*args, **kwargs):
+ """
+ GetX(self) -> int
+
+ Returns the X position (in client coordinates) of the event, if
+ applicable.
+ """
+ return _core_.KeyEvent_GetX(*args, **kwargs)
+
+ def GetY(*args, **kwargs):
+ """
+ GetY(self) -> int
+
+ Returns the Y position (in client coordinates) of the event, if
+ applicable.
+ """
+ return _core_.KeyEvent_GetY(*args, **kwargs)
+
+ def DoAllowNextEvent(*args, **kwargs):
+ """DoAllowNextEvent(self)"""
+ return _core_.KeyEvent_DoAllowNextEvent(*args, **kwargs)
+
+ def IsNextEventAllowed(*args, **kwargs):
+ """IsNextEventAllowed(self) -> bool"""
+ return _core_.KeyEvent_IsNextEventAllowed(*args, **kwargs)
+
+ m_x = property(_core_.KeyEvent_m_x_get, _core_.KeyEvent_m_x_set)
+ m_y = property(_core_.KeyEvent_m_y_get, _core_.KeyEvent_m_y_set)
+ m_keyCode = property(_core_.KeyEvent_m_keyCode_get, _core_.KeyEvent_m_keyCode_set)
+ m_rawCode = property(_core_.KeyEvent_m_rawCode_get, _core_.KeyEvent_m_rawCode_set)
+ m_rawFlags = property(_core_.KeyEvent_m_rawFlags_get, _core_.KeyEvent_m_rawFlags_set)
+ KeyCode = property(GetKeyCode,doc="See `GetKeyCode`")
+ Position = property(GetPosition,doc="See `GetPosition`")
+ RawKeyCode = property(GetRawKeyCode,doc="See `GetRawKeyCode`")
+ RawKeyFlags = property(GetRawKeyFlags,doc="See `GetRawKeyFlags`")
+ UnicodeKey = property(GetUnicodeKey,SetUnicodeKey,doc="See `GetUnicodeKey` and `SetUnicodeKey`")
+ X = property(GetX,doc="See `GetX`")
+ Y = property(GetY,doc="See `GetY`")
+_core_.KeyEvent_swigregister(KeyEvent)
+
+#---------------------------------------------------------------------------
+
+class SizeEvent(Event):
+ """
+ A size event holds information about size change events. The EVT_SIZE
+ handler function will be called when the window it is bound to has
+ been resized.
+
+ Note that the size passed is of the whole window: call
+ `wx.Window.GetClientSize` for the area which may be used by the
+ application.
+
+ When a window is resized, usually only a small part of the window is
+ damaged and and that area is all that is in the update region for the
+ next paint event. However, if your drawing depends on the size of the
+ window, you may need to clear the DC explicitly and repaint the whole
+ window. In which case, you may need to call `wx.Window.Refresh` to
+ invalidate the entire window.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Size sz=DefaultSize, int winid=0) -> SizeEvent
+
+ Construct a new ``wx.SizeEvent``.
+ """
+ _core_.SizeEvent_swiginit(self,_core_.new_SizeEvent(*args, **kwargs))
+ def GetSize(*args, **kwargs):
+ """
+ GetSize(self) -> Size
+
+ Returns the entire size of the window generating the size change
+ event.
+ """
+ return _core_.SizeEvent_GetSize(*args, **kwargs)
+
+ def GetRect(*args, **kwargs):
+ """GetRect(self) -> Rect"""
+ return _core_.SizeEvent_GetRect(*args, **kwargs)
+
+ def SetRect(*args, **kwargs):
+ """SetRect(self, Rect rect)"""
+ return _core_.SizeEvent_SetRect(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, Size size)"""
+ return _core_.SizeEvent_SetSize(*args, **kwargs)
+
+ m_size = property(_core_.SizeEvent_m_size_get, _core_.SizeEvent_m_size_set)
+ m_rect = property(_core_.SizeEvent_m_rect_get, _core_.SizeEvent_m_rect_set)
+ Rect = property(GetRect,SetRect,doc="See `GetRect` and `SetRect`")
+ Size = property(GetSize,SetSize,doc="See `GetSize` and `SetSize`")
+_core_.SizeEvent_swigregister(SizeEvent)
+
+#---------------------------------------------------------------------------
+
+class MoveEvent(Event):
+ """
+ This event object is sent for EVT_MOVE event bindings when a window is
+ moved to a new position.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Point pos=DefaultPosition, int winid=0) -> MoveEvent
+
+ Constructor.
+ """
+ _core_.MoveEvent_swiginit(self,_core_.new_MoveEvent(*args, **kwargs))
+ def GetPosition(*args, **kwargs):
+ """
+ GetPosition(self) -> Point
+
+ Returns the position of the window generating the move change event.
+ """
+ return _core_.MoveEvent_GetPosition(*args, **kwargs)
+
+ def GetRect(*args, **kwargs):
+ """GetRect(self) -> Rect"""
+ return _core_.MoveEvent_GetRect(*args, **kwargs)
+
+ def SetRect(*args, **kwargs):
+ """SetRect(self, Rect rect)"""
+ return _core_.MoveEvent_SetRect(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, Point pos)"""
+ return _core_.MoveEvent_SetPosition(*args, **kwargs)
+
+ m_pos = property(GetPosition, SetPosition)
+ m_rect = property(GetRect, SetRect)
+
+ Position = property(GetPosition,SetPosition,doc="See `GetPosition` and `SetPosition`")
+ Rect = property(GetRect,SetRect,doc="See `GetRect` and `SetRect`")
+_core_.MoveEvent_swigregister(MoveEvent)
+
+#---------------------------------------------------------------------------
+
+class PaintEvent(Event):
+ """
+ A paint event is sent when a window's contents needs to be repainted.
+ Note that in an EVT_PAINT handler the application must *always* create
+ a `wx.PaintDC` object, even if you do not use it. Otherwise MS
+ Windows assumes that the window has not been painted yet and will send
+ the event again, causing endless refreshes.
+
+ You can optimize painting by retrieving the rectangles that have been
+ damaged using `wx.Window.GetUpdateRegion` and/or `wx.RegionIterator`,
+ and only repainting these rectangles. The rectangles are in terms of
+ the client area, and are unscrolled, so you will need to do some
+ calculations using the current view position to obtain logical,
+ scrolled units.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int Id=0) -> PaintEvent"""
+ _core_.PaintEvent_swiginit(self,_core_.new_PaintEvent(*args, **kwargs))
+_core_.PaintEvent_swigregister(PaintEvent)
+
+class NcPaintEvent(Event):
+ """Proxy of C++ NcPaintEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int winid=0) -> NcPaintEvent"""
+ _core_.NcPaintEvent_swiginit(self,_core_.new_NcPaintEvent(*args, **kwargs))
+_core_.NcPaintEvent_swigregister(NcPaintEvent)
+
+#---------------------------------------------------------------------------
+
+class EraseEvent(Event):
+ """
+ An erase event is sent whenever the background of a window needs to be
+ repainted. To intercept this event use the EVT_ERASE_BACKGROUND event
+ binder. On some platforms, such as GTK+, this event is simulated
+ (simply generated just before the paint event) and may cause flicker.
+
+ To paint a custom background use the `GetDC` method and use the returned
+ device context if it is not ``None``, otherwise create a temporary
+ `wx.ClientDC` and draw on that.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int Id=0, DC dc=None) -> EraseEvent
+
+ Constructor
+ """
+ _core_.EraseEvent_swiginit(self,_core_.new_EraseEvent(*args, **kwargs))
+ def GetDC(*args, **kwargs):
+ """
+ GetDC(self) -> DC
+
+ Returns the device context the event handler should draw upon. If
+ ``None`` is returned then create a temporary `wx.ClientDC` and use
+ that instead.
+ """
+ return _core_.EraseEvent_GetDC(*args, **kwargs)
+
+ DC = property(GetDC,doc="See `GetDC`")
+_core_.EraseEvent_swigregister(EraseEvent)
+
+#---------------------------------------------------------------------------
+
+class FocusEvent(Event):
+ """
+ A focus event is sent when a window's focus changes. The window losing
+ focus receives an EVT_KILL_FOCUS event while the window gaining it
+ gets an EVT_SET_FOCUS event.
+
+ Notice that the set focus event happens both when the user gives focus
+ to the window (whether using the mouse or keyboard) and when it is
+ done from the program itself using `wx.Window.SetFocus`.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType type=wxEVT_NULL, int winid=0) -> FocusEvent
+
+ Constructor
+ """
+ _core_.FocusEvent_swiginit(self,_core_.new_FocusEvent(*args, **kwargs))
+ def GetWindow(*args, **kwargs):
+ """
+ GetWindow(self) -> Window
+
+ Returns the other window associated with this event, that is the
+ window which had the focus before for the EVT_SET_FOCUS event and the
+ window which is going to receive focus for the wxEVT_KILL_FOCUS event.
+
+ Warning: the window returned may be None!
+ """
+ return _core_.FocusEvent_GetWindow(*args, **kwargs)
+
+ def SetWindow(*args, **kwargs):
+ """SetWindow(self, Window win)"""
+ return _core_.FocusEvent_SetWindow(*args, **kwargs)
+
+ Window = property(GetWindow,SetWindow,doc="See `GetWindow` and `SetWindow`")
+_core_.FocusEvent_swigregister(FocusEvent)
+
+#---------------------------------------------------------------------------
+
+class ChildFocusEvent(CommandEvent):
+ """
+ A child focus event is sent to a (parent-)window when one of its child
+ windows gains focus, so that the window could restore the focus back
+ to its corresponding child if it loses it now and regains later.
+
+ Notice that child window is the direct child of the window receiving
+ the event, and so may not be the actual widget recieving focus if it
+ is further down the containment heirarchy. Use `wx.Window.FindFocus`
+ to get the widget that is actually receiving focus.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window win=None) -> ChildFocusEvent
+
+ Constructor
+ """
+ _core_.ChildFocusEvent_swiginit(self,_core_.new_ChildFocusEvent(*args, **kwargs))
+ def GetWindow(*args, **kwargs):
+ """
+ GetWindow(self) -> Window
+
+ The window, or (grand)parent of the window which has just received the
+ focus.
+ """
+ return _core_.ChildFocusEvent_GetWindow(*args, **kwargs)
+
+ Window = property(GetWindow,doc="See `GetWindow`")
+_core_.ChildFocusEvent_swigregister(ChildFocusEvent)
+
+#---------------------------------------------------------------------------
+
+class ActivateEvent(Event):
+ """
+ An activate event is sent when a top-level window or the entire
+ application is being activated or deactivated.
+
+ A top-level window (a dialog or frame) receives an activate event when
+ is being activated or deactivated. This is indicated visually by the
+ title bar changing colour, and a subwindow gaining the keyboard focus.
+ An application is activated or deactivated when one of its frames
+ becomes activated, or a frame becomes inactivate resulting in all
+ application frames being inactive.
+
+ Please note that usually you should call event.Skip() in your handlers
+ for these events so the default handlers will still be called, as not
+ doing so can result in strange effects.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType type=wxEVT_NULL, bool active=True, int Id=0) -> ActivateEvent
+
+ Constructor
+ """
+ _core_.ActivateEvent_swiginit(self,_core_.new_ActivateEvent(*args, **kwargs))
+ def GetActive(*args, **kwargs):
+ """
+ GetActive(self) -> bool
+
+ Returns true if the application or window is being activated, false
+ otherwise.
+ """
+ return _core_.ActivateEvent_GetActive(*args, **kwargs)
+
+ Active = property(GetActive,doc="See `GetActive`")
+_core_.ActivateEvent_swigregister(ActivateEvent)
+
+#---------------------------------------------------------------------------
+
+class InitDialogEvent(Event):
+ """
+ A wx.InitDialogEvent is sent as a dialog is being initialised, or for
+ any window when `wx.Window.InitDialog` is called. Handlers for this
+ event can transfer data to the window, or anything else that should be
+ done before the user begins editing the form. The default handler
+ calls `wx.Window.TransferDataToWindow`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int Id=0) -> InitDialogEvent
+
+ Constructor
+ """
+ _core_.InitDialogEvent_swiginit(self,_core_.new_InitDialogEvent(*args, **kwargs))
+_core_.InitDialogEvent_swigregister(InitDialogEvent)
+
+#---------------------------------------------------------------------------
+
+class MenuEvent(Event):
+ """
+ This class is used for a variety of menu-related events. Note that
+ these do not include menu command events, which are handled by sending
+ `wx.CommandEvent` objects.
+
+ The default handler for wx.EVT_MENU_HIGHLIGHT displays menu item help
+ text in the first field of the status bar.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType type=wxEVT_NULL, int winid=0, Menu menu=None) -> MenuEvent
+
+ Constructor
+ """
+ _core_.MenuEvent_swiginit(self,_core_.new_MenuEvent(*args, **kwargs))
+ def GetMenuId(*args, **kwargs):
+ """
+ GetMenuId(self) -> int
+
+ Returns the menu identifier associated with the event. This method
+ should be only used with the HIGHLIGHT events.
+ """
+ return _core_.MenuEvent_GetMenuId(*args, **kwargs)
+
+ def IsPopup(*args, **kwargs):
+ """
+ IsPopup(self) -> bool
+
+ Returns ``True`` if the menu which is being opened or closed is a
+ popup menu, ``False`` if it is a normal one. This method should only
+ be used with the OPEN and CLOSE events.
+ """
+ return _core_.MenuEvent_IsPopup(*args, **kwargs)
+
+ def GetMenu(*args, **kwargs):
+ """
+ GetMenu(self) -> Menu
+
+ Returns the menu which is being opened or closed. This method should
+ only be used with the OPEN and CLOSE events.
+ """
+ return _core_.MenuEvent_GetMenu(*args, **kwargs)
+
+ Menu = property(GetMenu,doc="See `GetMenu`")
+ MenuId = property(GetMenuId,doc="See `GetMenuId`")
+_core_.MenuEvent_swigregister(MenuEvent)
+
+#---------------------------------------------------------------------------
+
+class CloseEvent(Event):
+ """
+ This event class contains information about window and session close
+ events.
+
+ The handler function for EVT_CLOSE is called when the user has tried
+ to close a a frame or dialog box using the window manager controls or
+ the system menu. It can also be invoked by the application itself
+ programmatically, for example by calling the `wx.Window.Close`
+ function.
+
+ You should check whether the application is forcing the deletion of
+ the window using `CanVeto`. If it returns ``False``, you must destroy
+ the window using `wx.Window.Destroy`. If the return value is ``True``,
+ it is up to you whether you respond by destroying the window or not.
+ For example you may wish to display a message dialog prompting to save
+ files or to cancel the close.
+
+ If you don't destroy the window, you should call `Veto` to let the
+ calling code know that you did not destroy the window. This allows the
+ `wx.Window.Close` function to return ``True`` or ``False`` depending
+ on whether the close instruction was honored or not.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType type=wxEVT_NULL, int winid=0) -> CloseEvent
+
+ Constructor.
+ """
+ _core_.CloseEvent_swiginit(self,_core_.new_CloseEvent(*args, **kwargs))
+ def SetLoggingOff(*args, **kwargs):
+ """
+ SetLoggingOff(self, bool logOff)
+
+ Sets the 'logging off' flag.
+ """
+ return _core_.CloseEvent_SetLoggingOff(*args, **kwargs)
+
+ def GetLoggingOff(*args, **kwargs):
+ """
+ GetLoggingOff(self) -> bool
+
+ Returns ``True`` if the user is logging off or ``False`` if the
+ system is shutting down. This method can only be called for end
+ session and query end session events, it doesn't make sense for close
+ window event.
+ """
+ return _core_.CloseEvent_GetLoggingOff(*args, **kwargs)
+
+ def Veto(*args, **kwargs):
+ """
+ Veto(self, bool veto=True)
+
+ Call this from your event handler to veto a system shutdown or to
+ signal to the calling application that a window close did not happen.
+
+ You can only veto a shutdown or close if `CanVeto` returns true.
+ """
+ return _core_.CloseEvent_Veto(*args, **kwargs)
+
+ def GetVeto(*args, **kwargs):
+ """GetVeto(self) -> bool"""
+ return _core_.CloseEvent_GetVeto(*args, **kwargs)
+
+ def SetCanVeto(*args, **kwargs):
+ """
+ SetCanVeto(self, bool canVeto)
+
+ Sets the 'can veto' flag.
+ """
+ return _core_.CloseEvent_SetCanVeto(*args, **kwargs)
+
+ def CanVeto(*args, **kwargs):
+ """
+ CanVeto(self) -> bool
+
+ Returns true if you can veto a system shutdown or a window close
+ event. Vetoing a window close event is not possible if the calling
+ code wishes to force the application to exit, and so this function
+ must be called to check this.
+ """
+ return _core_.CloseEvent_CanVeto(*args, **kwargs)
+
+ LoggingOff = property(GetLoggingOff,SetLoggingOff,doc="See `GetLoggingOff` and `SetLoggingOff`")
+_core_.CloseEvent_swigregister(CloseEvent)
+
+#---------------------------------------------------------------------------
+
+class ShowEvent(Event):
+ """An EVT_SHOW event is sent when a window is shown or hidden."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int winid=0, bool show=False) -> ShowEvent
+
+ An EVT_SHOW event is sent when a window is shown or hidden.
+ """
+ _core_.ShowEvent_swiginit(self,_core_.new_ShowEvent(*args, **kwargs))
+ def SetShow(*args, **kwargs):
+ """SetShow(self, bool show)"""
+ return _core_.ShowEvent_SetShow(*args, **kwargs)
+
+ def IsShown(*args, **kwargs):
+ """IsShown(self) -> bool"""
+ return _core_.ShowEvent_IsShown(*args, **kwargs)
+
+ GetShow = IsShown
+ Show = property(IsShown,SetShow,doc="See `GetShow` and `SetShow`")
+_core_.ShowEvent_swigregister(ShowEvent)
+
+#---------------------------------------------------------------------------
+
+class IconizeEvent(Event):
+ """
+ An EVT_ICONIZE event is sent when a frame is iconized (minimized) or
+ restored.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int id=0, bool iconized=True) -> IconizeEvent
+
+ An EVT_ICONIZE event is sent when a frame is iconized (minimized) or
+ restored.
+ """
+ _core_.IconizeEvent_swiginit(self,_core_.new_IconizeEvent(*args, **kwargs))
+ def IsIconized(*args, **kwargs):
+ """
+ IsIconized(self) -> bool
+
+ Returns ``True`` if the frame has been iconized, ``False`` if it has
+ been restored.
+ """
+ return _core_.IconizeEvent_IsIconized(*args, **kwargs)
+
+ Iconized = IsIconized
+_core_.IconizeEvent_swigregister(IconizeEvent)
+
+#---------------------------------------------------------------------------
+
+class MaximizeEvent(Event):
+ """An EVT_MAXIMIZE event is sent when a frame is maximized or restored."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int id=0) -> MaximizeEvent
+
+ An EVT_MAXIMIZE event is sent when a frame is maximized or restored.
+ """
+ _core_.MaximizeEvent_swiginit(self,_core_.new_MaximizeEvent(*args, **kwargs))
+_core_.MaximizeEvent_swigregister(MaximizeEvent)
+
+#---------------------------------------------------------------------------
+
+class DropFilesEvent(Event):
+ """
+ This class is used for drop files events, that is, when files have
+ been dropped onto the window. This functionality is only available
+ under Windows. The window must have previously been enabled for
+ dropping by calling `wx.Window.DragAcceptFiles`.
+
+ Important note: this is a separate implementation to the more general
+ drag and drop implementation using `wx.FileDropTarget`, and etc. This
+ implementation uses the older, Windows message-based approach of
+ dropping files.
+
+ Use wx.EVT_DROP_FILES to bind an event handler to receive file drop
+ events.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetPosition(*args, **kwargs):
+ """
+ GetPosition(self) -> Point
+
+ Returns the position at which the files were dropped.
+ """
+ return _core_.DropFilesEvent_GetPosition(*args, **kwargs)
+
+ def GetNumberOfFiles(*args, **kwargs):
+ """
+ GetNumberOfFiles(self) -> int
+
+ Returns the number of files dropped.
+ """
+ return _core_.DropFilesEvent_GetNumberOfFiles(*args, **kwargs)
+
+ def GetFiles(*args, **kwargs):
+ """
+ GetFiles(self) -> PyObject
+
+ Returns a list of the filenames that were dropped.
+ """
+ return _core_.DropFilesEvent_GetFiles(*args, **kwargs)
+
+ Files = property(GetFiles,doc="See `GetFiles`")
+ NumberOfFiles = property(GetNumberOfFiles,doc="See `GetNumberOfFiles`")
+ Position = property(GetPosition,doc="See `GetPosition`")
+_core_.DropFilesEvent_swigregister(DropFilesEvent)
+
+#---------------------------------------------------------------------------
+
+UPDATE_UI_PROCESS_ALL = _core_.UPDATE_UI_PROCESS_ALL
+UPDATE_UI_PROCESS_SPECIFIED = _core_.UPDATE_UI_PROCESS_SPECIFIED
+class UpdateUIEvent(CommandEvent):
+ """
+ This class is used for EVT_UPDATE_UI pseudo-events which are sent by
+ wxWidgets to give an application the chance to update various user
+ interface elements.
+
+ Without update UI events, an application has to work hard to
+ check/uncheck, enable/disable, and set the text for elements such as
+ menu items and toolbar buttons. The code for doing this has to be
+ mixed up with the code that is invoked when an action is invoked for a
+ menu item or button.
+
+ With update UI events, you define an event handler to look at the
+ state of the application and change UI elements accordingly. wxWidgets
+ will call your handler functions in idle time, so you don't have to
+ worry where to call this code. In addition to being a clearer and more
+ declarative method, it also means you don't have to worry whether
+ you're updating a toolbar or menubar identifier. The same handler can
+ update a menu item and toolbar button, if the ID values are the same.
+
+ Instead of directly manipulating the menu or button, you call
+ functions in the event object, such as `Check`. wxWidgets will
+ determine whether such a call has been made, and which UI element to
+ update.
+
+ These events will work for popup menus as well as menubars. Just
+ before a menu is popped up, `wx.Menu.UpdateUI` is called to process
+ any UI events for the window that owns the menu.
+
+ If you find that the overhead of UI update processing is affecting
+ your application, you can do one or both of the following:
+
+ 1. Call `wx.UpdateUIEvent.SetMode` with a value of
+ wx.UPDATE_UI_PROCESS_SPECIFIED, and set the extra style
+ wx.WS_EX_PROCESS_UPDATE_EVENTS for every window that should
+ receive update events. No other windows will receive update
+ events.
+
+ 2. Call `wx.UpdateUIEvent.SetUpdateInterval` with a millisecond
+ value to set the delay between updates. You may need to call
+ `wx.Window.UpdateWindowUI` at critical points, for example when
+ a dialog is about to be shown, in case the user sees a slight
+ delay before windows are updated.
+
+ Note that although events are sent in idle time, defining a EVT_IDLE
+ handler for a window does not affect this because the events are sent
+ from an internal idle handler.
+
+ wxWidgets tries to optimize update events on some platforms. On
+ Windows and GTK+, events for menubar items are only sent when the menu
+ is about to be shown, and not in idle time.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int commandId=0) -> UpdateUIEvent
+
+ Constructor
+ """
+ _core_.UpdateUIEvent_swiginit(self,_core_.new_UpdateUIEvent(*args, **kwargs))
+ def GetChecked(*args, **kwargs):
+ """
+ GetChecked(self) -> bool
+
+ Returns ``True`` if the UI element should be checked.
+ """
+ return _core_.UpdateUIEvent_GetChecked(*args, **kwargs)
+
+ def GetEnabled(*args, **kwargs):
+ """
+ GetEnabled(self) -> bool
+
+ Returns ``True`` if the UI element should be enabled.
+ """
+ return _core_.UpdateUIEvent_GetEnabled(*args, **kwargs)
+
+ def GetShown(*args, **kwargs):
+ """
+ GetShown(self) -> bool
+
+ Returns ``True`` if the UI element should be shown.
+ """
+ return _core_.UpdateUIEvent_GetShown(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """
+ GetText(self) -> String
+
+ Returns the text that should be set for the UI element.
+ """
+ return _core_.UpdateUIEvent_GetText(*args, **kwargs)
+
+ def GetSetText(*args, **kwargs):
+ """
+ GetSetText(self) -> bool
+
+ Returns ``True`` if the application has called `SetText`. For
+ wxWidgets internal use only.
+ """
+ return _core_.UpdateUIEvent_GetSetText(*args, **kwargs)
+
+ def GetSetChecked(*args, **kwargs):
+ """
+ GetSetChecked(self) -> bool
+
+ Returns ``True`` if the application has called `Check`. For wxWidgets
+ internal use only.
+ """
+ return _core_.UpdateUIEvent_GetSetChecked(*args, **kwargs)
+
+ def GetSetEnabled(*args, **kwargs):
+ """
+ GetSetEnabled(self) -> bool
+
+ Returns ``True`` if the application has called `Enable`. For wxWidgets
+ internal use only.
+ """
+ return _core_.UpdateUIEvent_GetSetEnabled(*args, **kwargs)
+
+ def GetSetShown(*args, **kwargs):
+ """
+ GetSetShown(self) -> bool
+
+ Returns ``True`` if the application has called `Show`. For wxWidgets
+ internal use only.
+ """
+ return _core_.UpdateUIEvent_GetSetShown(*args, **kwargs)
+
+ def Check(*args, **kwargs):
+ """
+ Check(self, bool check)
+
+ Check or uncheck the UI element.
+ """
+ return _core_.UpdateUIEvent_Check(*args, **kwargs)
+
+ def Enable(*args, **kwargs):
+ """
+ Enable(self, bool enable)
+
+ Enable or disable the UI element.
+ """
+ return _core_.UpdateUIEvent_Enable(*args, **kwargs)
+
+ def Show(*args, **kwargs):
+ """
+ Show(self, bool show)
+
+ Show or hide the UI element.
+ """
+ return _core_.UpdateUIEvent_Show(*args, **kwargs)
+
+ def SetText(*args, **kwargs):
+ """
+ SetText(self, String text)
+
+ Sets the text for this UI element.
+ """
+ return _core_.UpdateUIEvent_SetText(*args, **kwargs)
+
+ def SetUpdateInterval(*args, **kwargs):
+ """
+ SetUpdateInterval(long updateInterval)
+
+ Sets the interval between updates in milliseconds. Set to -1 to
+ disable updates, or to 0 to update as frequently as possible. The
+ default is 0.
+
+ Use this to reduce the overhead of UI update events if your
+ application has a lot of windows. If you set the value to -1 or
+ greater than 0, you may also need to call `wx.Window.UpdateWindowUI`
+ at appropriate points in your application, such as when a dialog is
+ about to be shown.
+ """
+ return _core_.UpdateUIEvent_SetUpdateInterval(*args, **kwargs)
+
+ SetUpdateInterval = staticmethod(SetUpdateInterval)
+ def GetUpdateInterval(*args, **kwargs):
+ """
+ GetUpdateInterval() -> long
+
+ Returns the current interval between updates in milliseconds. -1
+ disables updates, 0 updates as frequently as possible.
+ """
+ return _core_.UpdateUIEvent_GetUpdateInterval(*args, **kwargs)
+
+ GetUpdateInterval = staticmethod(GetUpdateInterval)
+ def CanUpdate(*args, **kwargs):
+ """
+ CanUpdate(Window win) -> bool
+
+ Returns ``True`` if it is appropriate to update (send UI update events
+ to) this window.
+
+ This function looks at the mode used (see `wx.UpdateUIEvent.SetMode`),
+ the wx.WS_EX_PROCESS_UPDATE_EVENTS flag in window, the time update
+ events were last sent in idle time, and the update interval, to
+ determine whether events should be sent to this window now. By default
+ this will always return true because the update mode is initially
+ wx.UPDATE_UI_PROCESS_ALL and the interval is set to 0; so update
+ events will be sent as often as possible. You can reduce the frequency
+ that events are sent by changing the mode and/or setting an update
+ interval.
+
+ """
+ return _core_.UpdateUIEvent_CanUpdate(*args, **kwargs)
+
+ CanUpdate = staticmethod(CanUpdate)
+ def ResetUpdateTime(*args, **kwargs):
+ """
+ ResetUpdateTime()
+
+ Used internally to reset the last-updated time to the current time. It
+ is assumed that update events are normally sent in idle time, so this
+ is called at the end of idle processing.
+ """
+ return _core_.UpdateUIEvent_ResetUpdateTime(*args, **kwargs)
+
+ ResetUpdateTime = staticmethod(ResetUpdateTime)
+ def SetMode(*args, **kwargs):
+ """
+ SetMode(int mode)
+
+ Specify how wxWidgets will send update events: to all windows, or only
+ to those which specify that they will process the events.
+
+ The mode may be one of the following values:
+
+ ============================= ==========================================
+ wxUPDATE_UI_PROCESS_ALL Send UI update events to all windows. This
+ is the default setting.
+ wxUPDATE_UI_PROCESS_SPECIFIED Send UI update events only to windows that
+ have the wx.WS_EX_PROCESS_UI_UPDATES extra
+ style set.
+ ============================= ==========================================
+
+ """
+ return _core_.UpdateUIEvent_SetMode(*args, **kwargs)
+
+ SetMode = staticmethod(SetMode)
+ def GetMode(*args, **kwargs):
+ """
+ GetMode() -> int
+
+ Returns a value specifying how wxWidgets will send update events: to
+ all windows, or only to those which specify that they will process the
+ events.
+ """
+ return _core_.UpdateUIEvent_GetMode(*args, **kwargs)
+
+ GetMode = staticmethod(GetMode)
+ Checked = property(GetChecked,Check,doc="See `GetChecked`")
+ Enabled = property(GetEnabled,Enable,doc="See `GetEnabled`")
+ Shown = property(GetShown,Show,doc="See `GetShown`")
+ Text = property(GetText,SetText,doc="See `GetText` and `SetText`")
+_core_.UpdateUIEvent_swigregister(UpdateUIEvent)
+
+def UpdateUIEvent_SetUpdateInterval(*args, **kwargs):
+ """
+ UpdateUIEvent_SetUpdateInterval(long updateInterval)
+
+ Sets the interval between updates in milliseconds. Set to -1 to
+ disable updates, or to 0 to update as frequently as possible. The
+ default is 0.
+
+ Use this to reduce the overhead of UI update events if your
+ application has a lot of windows. If you set the value to -1 or
+ greater than 0, you may also need to call `wx.Window.UpdateWindowUI`
+ at appropriate points in your application, such as when a dialog is
+ about to be shown.
+ """
+ return _core_.UpdateUIEvent_SetUpdateInterval(*args, **kwargs)
+
+def UpdateUIEvent_GetUpdateInterval(*args):
+ """
+ UpdateUIEvent_GetUpdateInterval() -> long
+
+ Returns the current interval between updates in milliseconds. -1
+ disables updates, 0 updates as frequently as possible.
+ """
+ return _core_.UpdateUIEvent_GetUpdateInterval(*args)
+
+def UpdateUIEvent_CanUpdate(*args, **kwargs):
+ """
+ UpdateUIEvent_CanUpdate(Window win) -> bool
+
+ Returns ``True`` if it is appropriate to update (send UI update events
+ to) this window.
+
+ This function looks at the mode used (see `wx.UpdateUIEvent.SetMode`),
+ the wx.WS_EX_PROCESS_UPDATE_EVENTS flag in window, the time update
+ events were last sent in idle time, and the update interval, to
+ determine whether events should be sent to this window now. By default
+ this will always return true because the update mode is initially
+ wx.UPDATE_UI_PROCESS_ALL and the interval is set to 0; so update
+ events will be sent as often as possible. You can reduce the frequency
+ that events are sent by changing the mode and/or setting an update
+ interval.
+
+ """
+ return _core_.UpdateUIEvent_CanUpdate(*args, **kwargs)
+
+def UpdateUIEvent_ResetUpdateTime(*args):
+ """
+ UpdateUIEvent_ResetUpdateTime()
+
+ Used internally to reset the last-updated time to the current time. It
+ is assumed that update events are normally sent in idle time, so this
+ is called at the end of idle processing.
+ """
+ return _core_.UpdateUIEvent_ResetUpdateTime(*args)
+
+def UpdateUIEvent_SetMode(*args, **kwargs):
+ """
+ UpdateUIEvent_SetMode(int mode)
+
+ Specify how wxWidgets will send update events: to all windows, or only
+ to those which specify that they will process the events.
+
+ The mode may be one of the following values:
+
+ ============================= ==========================================
+ wxUPDATE_UI_PROCESS_ALL Send UI update events to all windows. This
+ is the default setting.
+ wxUPDATE_UI_PROCESS_SPECIFIED Send UI update events only to windows that
+ have the wx.WS_EX_PROCESS_UI_UPDATES extra
+ style set.
+ ============================= ==========================================
+
+ """
+ return _core_.UpdateUIEvent_SetMode(*args, **kwargs)
+
+def UpdateUIEvent_GetMode(*args):
+ """
+ UpdateUIEvent_GetMode() -> int
+
+ Returns a value specifying how wxWidgets will send update events: to
+ all windows, or only to those which specify that they will process the
+ events.
+ """
+ return _core_.UpdateUIEvent_GetMode(*args)
+
+#---------------------------------------------------------------------------
+
+class SysColourChangedEvent(Event):
+ """
+ This class is used for EVT_SYS_COLOUR_CHANGED, which are generated
+ when the user changes the colour settings using the control
+ panel. This is only applicable under Windows.
+
+ The default event handler for this event propagates the event to child
+ windows, since Windows only sends the events to top-level windows. If
+ intercepting this event for a top-level window, remember to call
+ `Skip` so the the base class handler will still be executed, or to
+ pass the event on to the window's children explicitly.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> SysColourChangedEvent
+
+ Constructor
+ """
+ _core_.SysColourChangedEvent_swiginit(self,_core_.new_SysColourChangedEvent(*args, **kwargs))
+_core_.SysColourChangedEvent_swigregister(SysColourChangedEvent)
+
+#---------------------------------------------------------------------------
+
+class MouseCaptureChangedEvent(Event):
+ """
+ An mouse capture changed event (EVT_MOUSE_CAPTURE_CHANGED) is sent to
+ a window that loses its mouse capture. This is called even if
+ `wx.Window.ReleaseMouse` was called by the application code. Handling
+ this event allows an application to cater for unexpected capture
+ releases which might otherwise confuse mouse handling code.
+
+ This event is implemented under Windows only.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int winid=0, Window gainedCapture=None) -> MouseCaptureChangedEvent
+
+ Constructor
+ """
+ _core_.MouseCaptureChangedEvent_swiginit(self,_core_.new_MouseCaptureChangedEvent(*args, **kwargs))
+ def GetCapturedWindow(*args, **kwargs):
+ """
+ GetCapturedWindow(self) -> Window
+
+ Returns the window that gained the capture, or ``None`` if it was a
+ non-wxWidgets window.
+ """
+ return _core_.MouseCaptureChangedEvent_GetCapturedWindow(*args, **kwargs)
+
+ CapturedWindow = property(GetCapturedWindow,doc="See `GetCapturedWindow`")
+_core_.MouseCaptureChangedEvent_swigregister(MouseCaptureChangedEvent)
+
+#---------------------------------------------------------------------------
+
+class MouseCaptureLostEvent(Event):
+ """
+ A mouse capture lost event is sent to a window that obtained mouse
+ capture, which was subsequently loss due to "external" event, for
+ example when a dialog box is shown or if another application captures
+ the mouse.
+
+ If this happens, this event is sent to all windows that are on the
+ capture stack (i.e. a window that called `wx.Window.CaptureMouse`, but
+ didn't call `wx.Window.ReleaseMouse` yet). The event is *not* sent
+ if the capture changes because of a call to CaptureMouse or
+ ReleaseMouse.
+
+ This event is currently emitted under Windows only.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int winid=0) -> MouseCaptureLostEvent
+
+ A mouse capture lost event is sent to a window that obtained mouse
+ capture, which was subsequently loss due to "external" event, for
+ example when a dialog box is shown or if another application captures
+ the mouse.
+
+ If this happens, this event is sent to all windows that are on the
+ capture stack (i.e. a window that called `wx.Window.CaptureMouse`, but
+ didn't call `wx.Window.ReleaseMouse` yet). The event is *not* sent
+ if the capture changes because of a call to CaptureMouse or
+ ReleaseMouse.
+
+ This event is currently emitted under Windows only.
+
+ """
+ _core_.MouseCaptureLostEvent_swiginit(self,_core_.new_MouseCaptureLostEvent(*args, **kwargs))
+_core_.MouseCaptureLostEvent_swigregister(MouseCaptureLostEvent)
+
+#---------------------------------------------------------------------------
+
+class DisplayChangedEvent(Event):
+ """
+ An EVT_DISPLAY_CHANGED event is sent to all windows when the display
+ resolution has changed.
+
+ This event is implemented under Windows only.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> DisplayChangedEvent"""
+ _core_.DisplayChangedEvent_swiginit(self,_core_.new_DisplayChangedEvent(*args, **kwargs))
+_core_.DisplayChangedEvent_swigregister(DisplayChangedEvent)
+
+#---------------------------------------------------------------------------
+
+class PaletteChangedEvent(Event):
+ """
+ An EVT_PALETTE_CHANGED event is sent when the system palette has
+ changed, thereby giving each window a chance to redo their own to
+ match.
+
+ This event is implemented under Windows only.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int id=0) -> PaletteChangedEvent
+
+ An EVT_PALETTE_CHANGED event is sent when the system palette has
+ changed, thereby giving each window a chance to redo their own to
+ match.
+
+ This event is implemented under Windows only.
+ """
+ _core_.PaletteChangedEvent_swiginit(self,_core_.new_PaletteChangedEvent(*args, **kwargs))
+ def SetChangedWindow(*args, **kwargs):
+ """SetChangedWindow(self, Window win)"""
+ return _core_.PaletteChangedEvent_SetChangedWindow(*args, **kwargs)
+
+ def GetChangedWindow(*args, **kwargs):
+ """GetChangedWindow(self) -> Window"""
+ return _core_.PaletteChangedEvent_GetChangedWindow(*args, **kwargs)
+
+ ChangedWindow = property(GetChangedWindow,SetChangedWindow,doc="See `GetChangedWindow` and `SetChangedWindow`")
+_core_.PaletteChangedEvent_swigregister(PaletteChangedEvent)
+
+#---------------------------------------------------------------------------
+
+class QueryNewPaletteEvent(Event):
+ """
+ An EVT_QUERY_NEW_PALETE event indicates the window is getting keyboard
+ focus and should re-do its palette.
+
+ This event is implemented under Windows only.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int winid=0) -> QueryNewPaletteEvent
+
+ Constructor.
+ """
+ _core_.QueryNewPaletteEvent_swiginit(self,_core_.new_QueryNewPaletteEvent(*args, **kwargs))
+ def SetPaletteRealized(*args, **kwargs):
+ """
+ SetPaletteRealized(self, bool realized)
+
+ App should set this if it changes the palette.
+ """
+ return _core_.QueryNewPaletteEvent_SetPaletteRealized(*args, **kwargs)
+
+ def GetPaletteRealized(*args, **kwargs):
+ """GetPaletteRealized(self) -> bool"""
+ return _core_.QueryNewPaletteEvent_GetPaletteRealized(*args, **kwargs)
+
+ PaletteRealized = property(GetPaletteRealized,SetPaletteRealized,doc="See `GetPaletteRealized` and `SetPaletteRealized`")
+_core_.QueryNewPaletteEvent_swigregister(QueryNewPaletteEvent)
+
+#---------------------------------------------------------------------------
+
+class NavigationKeyEvent(Event):
+ """
+ EVT_NAVIGATION_KEY events are used to control moving the focus between
+ widgets, otherwise known as tab-traversal. You woudl normally not
+ catch navigation events in applications as there are already
+ appropriate handlers in `wx.Dialog` and `wx.Panel`, but you may find
+ it useful to send navigation events in certain situations to change
+ the focus in certain ways, although it's probably easier to just call
+ `wx.Window.Navigate`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> NavigationKeyEvent"""
+ _core_.NavigationKeyEvent_swiginit(self,_core_.new_NavigationKeyEvent(*args, **kwargs))
+ def GetDirection(*args, **kwargs):
+ """
+ GetDirection(self) -> bool
+
+ Returns ``True`` if the direction is forward, ``False`` otherwise.
+ """
+ return _core_.NavigationKeyEvent_GetDirection(*args, **kwargs)
+
+ def SetDirection(*args, **kwargs):
+ """
+ SetDirection(self, bool forward)
+
+ Specify the direction that the navigation should take. Usually the
+ difference between using Tab and Shift-Tab.
+ """
+ return _core_.NavigationKeyEvent_SetDirection(*args, **kwargs)
+
+ def IsWindowChange(*args, **kwargs):
+ """
+ IsWindowChange(self) -> bool
+
+ Returns ``True`` if window change is allowed.
+ """
+ return _core_.NavigationKeyEvent_IsWindowChange(*args, **kwargs)
+
+ def SetWindowChange(*args, **kwargs):
+ """
+ SetWindowChange(self, bool ischange)
+
+ Specify if the navigation should be able to change parent windows.
+ For example, changing notebook pages, etc. This is usually implemented
+ by using Control-Tab.
+ """
+ return _core_.NavigationKeyEvent_SetWindowChange(*args, **kwargs)
+
+ def IsFromTab(*args, **kwargs):
+ """
+ IsFromTab(self) -> bool
+
+ Returns ``True`` if the navigation event is originated from the Tab
+ key.
+ """
+ return _core_.NavigationKeyEvent_IsFromTab(*args, **kwargs)
+
+ def SetFromTab(*args, **kwargs):
+ """
+ SetFromTab(self, bool bIs)
+
+ Set to true under MSW if the event was generated using the tab key.
+ This is required for proper navogation over radio buttons.
+ """
+ return _core_.NavigationKeyEvent_SetFromTab(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """
+ SetFlags(self, long flags)
+
+ Set the navigation flags to a combination of the following:
+
+ * wx.NavigationKeyEvent.IsBackward
+ * wx.NavigationKeyEvent.IsForward
+ * wx.NavigationKeyEvent.WinChange
+ * wx.NavigationKeyEvent.FromTab
+
+ """
+ return _core_.NavigationKeyEvent_SetFlags(*args, **kwargs)
+
+ def GetCurrentFocus(*args, **kwargs):
+ """
+ GetCurrentFocus(self) -> Window
+
+ Returns the child window which currenty has the focus. May be
+ ``None``.
+ """
+ return _core_.NavigationKeyEvent_GetCurrentFocus(*args, **kwargs)
+
+ def SetCurrentFocus(*args, **kwargs):
+ """
+ SetCurrentFocus(self, Window win)
+
+ Set the window that has the focus.
+ """
+ return _core_.NavigationKeyEvent_SetCurrentFocus(*args, **kwargs)
+
+ IsBackward = _core_.NavigationKeyEvent_IsBackward
+ IsForward = _core_.NavigationKeyEvent_IsForward
+ WinChange = _core_.NavigationKeyEvent_WinChange
+ FromTab = _core_.NavigationKeyEvent_FromTab
+ CurrentFocus = property(GetCurrentFocus,SetCurrentFocus,doc="See `GetCurrentFocus` and `SetCurrentFocus`")
+ Direction = property(GetDirection,SetDirection,doc="See `GetDirection` and `SetDirection`")
+_core_.NavigationKeyEvent_swigregister(NavigationKeyEvent)
+
+#---------------------------------------------------------------------------
+
+class WindowCreateEvent(CommandEvent):
+ """
+ The EVT_WINDOW_CREATE event is sent as soon as the window object (the
+ underlying GUI object) exists.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window win=None) -> WindowCreateEvent
+
+ The EVT_WINDOW_CREATE event is sent as soon as the window object (the
+ underlying GUI object) exists.
+ """
+ _core_.WindowCreateEvent_swiginit(self,_core_.new_WindowCreateEvent(*args, **kwargs))
+ def GetWindow(*args, **kwargs):
+ """
+ GetWindow(self) -> Window
+
+ Returns the window that this event refers to.
+ """
+ return _core_.WindowCreateEvent_GetWindow(*args, **kwargs)
+
+ Window = property(GetWindow,doc="See `GetWindow`")
+_core_.WindowCreateEvent_swigregister(WindowCreateEvent)
+
+class WindowDestroyEvent(CommandEvent):
+ """
+ The EVT_WINDOW_DESTROY event is sent from the `wx.Window` destructor
+ when the GUI window is destroyed.
+
+ When a class derived from `wx.Window` is destroyed its destructor will
+ have already run by the time this event is sent. Therefore this event
+ will not usually be received at all by the window itself. Since it is
+ received after the destructor has run, an object should not try to
+ handle its own wx.WindowDestroyEvent, but it can be used to get
+ notification of the destruction of another window.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window win=None) -> WindowDestroyEvent
+
+ The EVT_WINDOW_DESTROY event is sent from the `wx.Window` destructor
+ when the GUI window is destroyed.
+
+ When a class derived from `wx.Window` is destroyed its destructor will
+ have already run by the time this event is sent. Therefore this event
+ will not usually be received at all by the window itself. Since it is
+ received after the destructor has run, an object should not try to
+ handle its own wx.WindowDestroyEvent, but it can be used to get
+ notification of the destruction of another window.
+ """
+ _core_.WindowDestroyEvent_swiginit(self,_core_.new_WindowDestroyEvent(*args, **kwargs))
+ def GetWindow(*args, **kwargs):
+ """
+ GetWindow(self) -> Window
+
+ Returns the window that this event refers to.
+ """
+ return _core_.WindowDestroyEvent_GetWindow(*args, **kwargs)
+
+ Window = property(GetWindow,doc="See `GetWindow`")
+_core_.WindowDestroyEvent_swigregister(WindowDestroyEvent)
+
+#---------------------------------------------------------------------------
+
+class ContextMenuEvent(CommandEvent):
+ """
+ This class is used for context menu events (EVT_CONTECT_MENU,) sent to
+ give the application a chance to show a context (popup) menu.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType type=wxEVT_NULL, int winid=0, Point pt=DefaultPosition) -> ContextMenuEvent
+
+ Constructor.
+ """
+ _core_.ContextMenuEvent_swiginit(self,_core_.new_ContextMenuEvent(*args, **kwargs))
+ def GetPosition(*args, **kwargs):
+ """
+ GetPosition(self) -> Point
+
+ Returns the position (in screen coordinants) at which the menu should
+ be shown.
+ """
+ return _core_.ContextMenuEvent_GetPosition(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """
+ SetPosition(self, Point pos)
+
+ Sets the position at which the menu should be shown.
+ """
+ return _core_.ContextMenuEvent_SetPosition(*args, **kwargs)
+
+ Position = property(GetPosition,SetPosition,doc="See `GetPosition` and `SetPosition`")
+_core_.ContextMenuEvent_swigregister(ContextMenuEvent)
+
+#---------------------------------------------------------------------------
+
+IDLE_PROCESS_ALL = _core_.IDLE_PROCESS_ALL
+IDLE_PROCESS_SPECIFIED = _core_.IDLE_PROCESS_SPECIFIED
+class IdleEvent(Event):
+ """
+ This class is used for EVT_IDLE events, which are generated and sent
+ when the application *becomes* idle. In other words, the when the
+ event queue becomes empty then idle events are sent to all windows (by
+ default) and as long as none of them call `RequestMore` then there are
+ no more idle events until after the system event queue has some normal
+ events and then becomes empty again.
+
+ By default, idle events are sent to all windows. If this is causing a
+ significant overhead in your application, you can call
+ `wx.IdleEvent.SetMode` with the value wx.IDLE_PROCESS_SPECIFIED, and
+ set the wx.WS_EX_PROCESS_IDLE extra window style for every window
+ which should receive idle events. Then idle events will only be sent
+ to those windows and not to any others.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> IdleEvent
+
+ Constructor
+ """
+ _core_.IdleEvent_swiginit(self,_core_.new_IdleEvent(*args, **kwargs))
+ def RequestMore(*args, **kwargs):
+ """
+ RequestMore(self, bool needMore=True)
+
+ Tells wxWidgets that more processing is required. This function can be
+ called by an EVT_IDLE handler for a window to indicate that the
+ application should forward the EVT_IDLE event once more to the
+ application windows. If no window calls this function during its
+ EVT_IDLE handler, then the application will remain in a passive event
+ loop until a new event is posted to the application by the windowing
+ system.
+ """
+ return _core_.IdleEvent_RequestMore(*args, **kwargs)
+
+ def MoreRequested(*args, **kwargs):
+ """
+ MoreRequested(self) -> bool
+
+ Returns ``True`` if the OnIdle function processing this event
+ requested more processing time.
+ """
+ return _core_.IdleEvent_MoreRequested(*args, **kwargs)
+
+ def SetMode(*args, **kwargs):
+ """
+ SetMode(int mode)
+
+ Static method for specifying how wxWidgets will send idle events: to
+ all windows, or only to those which specify that they will process the
+ events.
+
+ The mode can be one of the following values:
+
+ ========================= ========================================
+ wx.IDLE_PROCESS_ALL Send idle events to all windows
+ wx.IDLE_PROCESS_SPECIFIED Send idle events only to windows that have
+ the wx.WS_EX_PROCESS_IDLE extra style
+ flag set.
+ ========================= ========================================
+
+ """
+ return _core_.IdleEvent_SetMode(*args, **kwargs)
+
+ SetMode = staticmethod(SetMode)
+ def GetMode(*args, **kwargs):
+ """
+ GetMode() -> int
+
+ Static method returning a value specifying how wxWidgets will send
+ idle events: to all windows, or only to those which specify that they
+ will process the events.
+ """
+ return _core_.IdleEvent_GetMode(*args, **kwargs)
+
+ GetMode = staticmethod(GetMode)
+_core_.IdleEvent_swigregister(IdleEvent)
+
+def IdleEvent_SetMode(*args, **kwargs):
+ """
+ IdleEvent_SetMode(int mode)
+
+ Static method for specifying how wxWidgets will send idle events: to
+ all windows, or only to those which specify that they will process the
+ events.
+
+ The mode can be one of the following values:
+
+ ========================= ========================================
+ wx.IDLE_PROCESS_ALL Send idle events to all windows
+ wx.IDLE_PROCESS_SPECIFIED Send idle events only to windows that have
+ the wx.WS_EX_PROCESS_IDLE extra style
+ flag set.
+ ========================= ========================================
+
+ """
+ return _core_.IdleEvent_SetMode(*args, **kwargs)
+
+def IdleEvent_GetMode(*args):
+ """
+ IdleEvent_GetMode() -> int
+
+ Static method returning a value specifying how wxWidgets will send
+ idle events: to all windows, or only to those which specify that they
+ will process the events.
+ """
+ return _core_.IdleEvent_GetMode(*args)
+
+#---------------------------------------------------------------------------
+
+class ClipboardTextEvent(CommandEvent):
+ """
+ A Clipboard Text event is sent when a window intercepts a text
+ copy/cut/paste message, i.e. the user has cut/copied/pasted data
+ from/into a text control via ctrl-C/X/V, ctrl/shift-del/insert, a
+ popup menu command, etc. NOTE : under windows these events are *NOT*
+ generated automatically for a Rich Edit text control.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType type=wxEVT_NULL, int winid=0) -> ClipboardTextEvent
+
+ A Clipboard Text event is sent when a window intercepts a text
+ copy/cut/paste message, i.e. the user has cut/copied/pasted data
+ from/into a text control via ctrl-C/X/V, ctrl/shift-del/insert, a
+ popup menu command, etc. NOTE : under windows these events are *NOT*
+ generated automatically for a Rich Edit text control.
+ """
+ _core_.ClipboardTextEvent_swiginit(self,_core_.new_ClipboardTextEvent(*args, **kwargs))
+_core_.ClipboardTextEvent_swigregister(ClipboardTextEvent)
+
+#---------------------------------------------------------------------------
+
+class PyEvent(Event):
+ """
+ wx.PyEvent can be used as a base class for implementing custom event
+ types in Python. You should derived from this class instead of
+ `wx.Event` because this class is Python-aware and is able to transport
+ its Python bits safely through the wxWidgets event system and have
+ them still be there when the event handler is invoked.
+
+ :see: `wx.PyCommandEvent`
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int winid=0, EventType eventType=wxEVT_NULL) -> PyEvent"""
+ _core_.PyEvent_swiginit(self,_core_.new_PyEvent(*args, **kwargs))
+ self._SetSelf(self)
+
+ __swig_destroy__ = _core_.delete_PyEvent
+ __del__ = lambda self : None;
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _core_.PyEvent__SetSelf(*args, **kwargs)
+
+ def _GetSelf(*args, **kwargs):
+ """_GetSelf(self) -> PyObject"""
+ return _core_.PyEvent__GetSelf(*args, **kwargs)
+
+_core_.PyEvent_swigregister(PyEvent)
+
+class PyCommandEvent(CommandEvent):
+ """
+ wx.PyCommandEvent can be used as a base class for implementing custom
+ event types in Python, where the event should travel up to parent
+ windows looking for a handler. You should derived from this class
+ instead of `wx.CommandEvent` because this class is Python-aware and is
+ able to transport its Python bits safely through the wxWidgets event
+ system and have them still be there when the event handler is invoked.
+
+ :see: `wx.PyEvent`
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType eventType=wxEVT_NULL, int id=0) -> PyCommandEvent"""
+ _core_.PyCommandEvent_swiginit(self,_core_.new_PyCommandEvent(*args, **kwargs))
+ self._SetSelf(self)
+
+ __swig_destroy__ = _core_.delete_PyCommandEvent
+ __del__ = lambda self : None;
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _core_.PyCommandEvent__SetSelf(*args, **kwargs)
+
+ def _GetSelf(*args, **kwargs):
+ """_GetSelf(self) -> PyObject"""
+ return _core_.PyCommandEvent__GetSelf(*args, **kwargs)
+
+_core_.PyCommandEvent_swigregister(PyCommandEvent)
+
+class DateEvent(CommandEvent):
+ """
+ This event class holds information about a date change event and is
+ used together with `wx.DatePickerCtrl`. It also serves as a base class
+ for `wx.calendar.CalendarEvent`. Bind these event types with
+ EVT_DATE_CHANGED.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window win, DateTime dt, EventType type) -> DateEvent"""
+ _core_.DateEvent_swiginit(self,_core_.new_DateEvent(*args, **kwargs))
+ def GetDate(*args, **kwargs):
+ """
+ GetDate(self) -> DateTime
+
+ Returns the date.
+ """
+ return _core_.DateEvent_GetDate(*args, **kwargs)
+
+ def SetDate(*args, **kwargs):
+ """
+ SetDate(self, DateTime date)
+
+ Sets the date carried by the event, normally only used by the library
+ internally.
+ """
+ return _core_.DateEvent_SetDate(*args, **kwargs)
+
+ Date = property(GetDate,SetDate,doc="See `GetDate` and `SetDate`")
+_core_.DateEvent_swigregister(DateEvent)
+
+wxEVT_DATE_CHANGED = _core_.wxEVT_DATE_CHANGED
+EVT_DATE_CHANGED = wx.PyEventBinder( wxEVT_DATE_CHANGED, 1 )
+
+class EventBlocker(EvtHandler):
+ """Helper class to temporarily disable event handling for a window."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window win, EventType type=wxEVT_ANY) -> EventBlocker
+
+ Helper class to temporarily disable event handling for a window.
+ """
+ _core_.EventBlocker_swiginit(self,_core_.new_EventBlocker(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_EventBlocker
+ __del__ = lambda self : None;
+ def Block(*args, **kwargs):
+ """Block(self, EventType type)"""
+ return _core_.EventBlocker_Block(*args, **kwargs)
+
+_core_.EventBlocker_swigregister(EventBlocker)
+
+#---------------------------------------------------------------------------
+
+PYAPP_ASSERT_SUPPRESS = _core_.PYAPP_ASSERT_SUPPRESS
+PYAPP_ASSERT_EXCEPTION = _core_.PYAPP_ASSERT_EXCEPTION
+PYAPP_ASSERT_DIALOG = _core_.PYAPP_ASSERT_DIALOG
+PYAPP_ASSERT_LOG = _core_.PYAPP_ASSERT_LOG
+PRINT_WINDOWS = _core_.PRINT_WINDOWS
+PRINT_POSTSCRIPT = _core_.PRINT_POSTSCRIPT
+class PyApp(EvtHandler):
+ """
+ The ``wx.PyApp`` class is an *implementation detail*, please use the
+ `wx.App` class (or some other derived class) instead.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PyApp
+
+ Create a new application object, starting the bootstrap process.
+ """
+ _core_.PyApp_swiginit(self,_core_.new_PyApp(*args, **kwargs))
+ self._setOORInfo(self, False);PyApp._setCallbackInfo(self, self, PyApp);self.this.own(True)
+
+ __swig_destroy__ = _core_.delete_PyApp
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class, bool incref=False)"""
+ return _core_.PyApp__setCallbackInfo(*args, **kwargs)
+
+ def GetAppName(*args, **kwargs):
+ """
+ GetAppName(self) -> String
+
+ Get the application name.
+ """
+ return _core_.PyApp_GetAppName(*args, **kwargs)
+
+ def SetAppName(*args, **kwargs):
+ """
+ SetAppName(self, String name)
+
+ Set the application name. This value may be used automatically by
+ `wx.Config` and such.
+ """
+ return _core_.PyApp_SetAppName(*args, **kwargs)
+
+ def GetAppDisplayName(*args, **kwargs):
+ """
+ GetAppDisplayName(self) -> String
+
+ Get the application display name.
+ """
+ return _core_.PyApp_GetAppDisplayName(*args, **kwargs)
+
+ def SetAppDisplayName(*args, **kwargs):
+ """
+ SetAppDisplayName(self, String name)
+
+ Set the application display name. The display name is the name shown
+ to the user in titles, reports, etc while the app name is used for
+ paths, config, and other places the user doesn't see, for example the
+ app name could be myapp while display name could be 'My App'
+
+ """
+ return _core_.PyApp_SetAppDisplayName(*args, **kwargs)
+
+ def GetClassName(*args, **kwargs):
+ """
+ GetClassName(self) -> String
+
+ Get the application's class name.
+ """
+ return _core_.PyApp_GetClassName(*args, **kwargs)
+
+ def SetClassName(*args, **kwargs):
+ """
+ SetClassName(self, String name)
+
+ Set the application's class name. This value may be used for
+ X-resources if applicable for the platform
+ """
+ return _core_.PyApp_SetClassName(*args, **kwargs)
+
+ def GetVendorName(*args, **kwargs):
+ """
+ GetVendorName(self) -> String
+
+ Get the application's vendor name.
+ """
+ return _core_.PyApp_GetVendorName(*args, **kwargs)
+
+ def SetVendorName(*args, **kwargs):
+ """
+ SetVendorName(self, String name)
+
+ Set the application's vendor name. This value may be used
+ automatically by `wx.Config` and such.
+ """
+ return _core_.PyApp_SetVendorName(*args, **kwargs)
+
+ def GetVendorDisplayName(*args, **kwargs):
+ """
+ GetVendorDisplayName(self) -> String
+
+ Get the vendor display name.
+ """
+ return _core_.PyApp_GetVendorDisplayName(*args, **kwargs)
+
+ def SetVendorDisplayName(*args, **kwargs):
+ """
+ SetVendorDisplayName(self, String name)
+
+ Set the vendor display name. The display name is shown in
+ titles/reports/dialogs to the user, while the vendor name is used in
+ some areas such as wxConfig, wxStandardPaths, etc.
+ """
+ return _core_.PyApp_SetVendorDisplayName(*args, **kwargs)
+
+ def GetTraits(*args, **kwargs):
+ """
+ GetTraits(self) -> wxAppTraits
+
+ Return (and create if necessary) the app traits object to which we
+ delegate for everything which either should be configurable by the
+ user (then he can change the default behaviour simply by overriding
+ CreateTraits() and returning his own traits object) or which is
+ GUI/console dependent as then wx.AppTraits allows us to abstract the
+ differences behind the common facade.
+
+ :todo: Add support for overriding CreateAppTraits in wxPython.
+ """
+ return _core_.PyApp_GetTraits(*args, **kwargs)
+
+ def GetTraitsIfExists(*args, **kwargs):
+ """
+ GetTraitsIfExists() -> wxAppTraits
+
+ This function provides safer access to traits object than
+ wx.GetApp().GetTraits() during startup or termination when the global
+ application object itself may be unavailable.
+ """
+ return _core_.PyApp_GetTraitsIfExists(*args, **kwargs)
+
+ GetTraitsIfExists = staticmethod(GetTraitsIfExists)
+ def GetMainLoop(*args, **kwargs):
+ """
+ GetMainLoop(self) -> EventLoopBase
+
+ Returns the main event loop instance, i.e. the event loop which is started
+ by OnRun() and which dispatches all events sent from the native toolkit
+ to the application (except when new event loops are temporarily set-up).
+ The returned value maybe None. Put initialization code which needs a
+ non-None main event loop into OnEventLoopEnter().
+ """
+ return _core_.PyApp_GetMainLoop(*args, **kwargs)
+
+ def SuspendProcessingOfPendingEvents(*args, **kwargs):
+ """
+ SuspendProcessingOfPendingEvents(self)
+
+ Temporarily suspends the processing of pending events.
+ """
+ return _core_.PyApp_SuspendProcessingOfPendingEvents(*args, **kwargs)
+
+ def ResumeProcessingOfPendingEvents(*args, **kwargs):
+ """
+ ResumeProcessingOfPendingEvents(self)
+
+ Resume (after having been suspended) the processing of pending events.
+ """
+ return _core_.PyApp_ResumeProcessingOfPendingEvents(*args, **kwargs)
+
+ def ProcessPendingEvents(*args, **kwargs):
+ """
+ ProcessPendingEvents(self)
+
+ Process all events in the Pending Events list -- it is necessary to
+ call this function to process posted events. This normally happens
+ during each event loop iteration.
+ """
+ return _core_.PyApp_ProcessPendingEvents(*args, **kwargs)
+
+ def HasPendingEvents(*args, **kwargs):
+ """
+ HasPendingEvents(self) -> bool
+
+ Check if there are pending events on global pending event list
+ """
+ return _core_.PyApp_HasPendingEvents(*args, **kwargs)
+
+ def RemovePendingEventHandler(*args, **kwargs):
+ """RemovePendingEventHandler(self, EvtHandler toRemove)"""
+ return _core_.PyApp_RemovePendingEventHandler(*args, **kwargs)
+
+ def AppendPendingEventHandler(*args, **kwargs):
+ """AppendPendingEventHandler(self, EvtHandler toAppend)"""
+ return _core_.PyApp_AppendPendingEventHandler(*args, **kwargs)
+
+ def DelayPendingEventHandler(*args, **kwargs):
+ """DelayPendingEventHandler(self, EvtHandler toDelay)"""
+ return _core_.PyApp_DelayPendingEventHandler(*args, **kwargs)
+
+ def DeletePendingEvents(*args, **kwargs):
+ """DeletePendingEvents(self)"""
+ return _core_.PyApp_DeletePendingEvents(*args, **kwargs)
+
+ def ScheduleForDestruction(*args, **kwargs):
+ """ScheduleForDestruction(self, Object object)"""
+ return _core_.PyApp_ScheduleForDestruction(*args, **kwargs)
+
+ def IsScheduledForDestruction(*args, **kwargs):
+ """IsScheduledForDestruction(self, Object object) -> bool"""
+ return _core_.PyApp_IsScheduledForDestruction(*args, **kwargs)
+
+ def Yield(*args, **kwargs):
+ """
+ Yield(self, bool onlyIfNeeded=False) -> bool
+
+ Process all currently pending events right now, instead of waiting
+ until return to the event loop. It is an error to call ``Yield``
+ recursively unless the value of ``onlyIfNeeded`` is True.
+
+ :warning: This function is dangerous as it can lead to unexpected
+ reentrancies (i.e. when called from an event handler it may
+ result in calling the same event handler again), use with
+ extreme care or, better, don't use at all!
+
+ :see: `wx.Yield`, `wx.YieldIfNeeded`, `wx.SafeYield`
+
+ """
+ return _core_.PyApp_Yield(*args, **kwargs)
+
+ def SafeYield(*args, **kwargs):
+ """SafeYield(self, Window win, bool onlyIfNeeded) -> bool"""
+ return _core_.PyApp_SafeYield(*args, **kwargs)
+
+ def SafeYieldFor(*args, **kwargs):
+ """SafeYieldFor(self, Window win, long eventsToProcess) -> bool"""
+ return _core_.PyApp_SafeYieldFor(*args, **kwargs)
+
+ def WakeUpIdle(*args, **kwargs):
+ """
+ WakeUpIdle(self)
+
+ Make sure that idle events are sent again.
+ :see: `wx.WakeUpIdle`
+ """
+ return _core_.PyApp_WakeUpIdle(*args, **kwargs)
+
+ def IsMainLoopRunning(*args, **kwargs):
+ """
+ IsMainLoopRunning() -> bool
+
+ Returns True if we're running the main loop, i.e. if the events can
+ currently be dispatched.
+ """
+ return _core_.PyApp_IsMainLoopRunning(*args, **kwargs)
+
+ IsMainLoopRunning = staticmethod(IsMainLoopRunning)
+ def MainLoop(*args, **kwargs):
+ """
+ MainLoop(self) -> int
+
+ Execute the main GUI loop, the function doesn't normally return until
+ all top level windows have been closed and destroyed.
+ """
+ return _core_.PyApp_MainLoop(*args, **kwargs)
+
+ def Exit(*args, **kwargs):
+ """
+ Exit(self)
+
+ Exit the main loop thus terminating the application.
+ :see: `wx.Exit`
+ """
+ return _core_.PyApp_Exit(*args, **kwargs)
+
+ def GetLayoutDirection(*args, **kwargs):
+ """
+ GetLayoutDirection(self) -> int
+
+ Return the layout direction for the current locale.
+ """
+ return _core_.PyApp_GetLayoutDirection(*args, **kwargs)
+
+ def SetNativeTheme(*args, **kwargs):
+ """
+ SetNativeTheme(self, String theme) -> bool
+
+ Change the theme used by the application, return true on success.
+ """
+ return _core_.PyApp_SetNativeTheme(*args, **kwargs)
+
+ def ExitMainLoop(*args, **kwargs):
+ """
+ ExitMainLoop(self)
+
+ Exit the main GUI loop during the next iteration of the main
+ loop, (i.e. it does not stop the program immediately!)
+ """
+ return _core_.PyApp_ExitMainLoop(*args, **kwargs)
+
+ def FilterEvent(*args, **kwargs):
+ """
+ FilterEvent(self, Event event) -> int
+
+ Filters all events. `SetCallFilterEvent` controls whether or not your
+ override is called.
+ """
+ return _core_.PyApp_FilterEvent(*args, **kwargs)
+
+ def GetCallFilterEvent(*args, **kwargs):
+ """
+ GetCallFilterEvent(self) -> bool
+
+ Returns the state of the Call FilterEvent flag.
+ """
+ return _core_.PyApp_GetCallFilterEvent(*args, **kwargs)
+
+ def SetCallFilterEvent(*args, **kwargs):
+ """
+ SetCallFilterEvent(self, bool callFilterEvent=True)
+
+ Set the Call FilterEvent flag. When set your override of FilterEvent
+ will be called. SetCallFilterEvent's purpose is to avoid any
+ performance penalty when you have overriden FilterEvent, but don't
+ want it to be called, and also to reduce the runtime overhead when it
+ is not overridden.
+ """
+ return _core_.PyApp_SetCallFilterEvent(*args, **kwargs)
+
+ def Pending(*args, **kwargs):
+ """
+ Pending(self) -> bool
+
+ Returns True if there are unprocessed events in the event queue.
+ """
+ return _core_.PyApp_Pending(*args, **kwargs)
+
+ def Dispatch(*args, **kwargs):
+ """
+ Dispatch(self) -> bool
+
+ Process the first event in the event queue (blocks until an event
+ appears if there are none currently)
+ """
+ return _core_.PyApp_Dispatch(*args, **kwargs)
+
+ def ProcessIdle(*args, **kwargs):
+ """
+ ProcessIdle(self) -> bool
+
+ Called from the MainLoop when the application becomes idle (there are
+ no pending events) and sends a `wx.IdleEvent` to all interested
+ parties. Returns True if more idle events are needed, False if not.
+ """
+ return _core_.PyApp_ProcessIdle(*args, **kwargs)
+
+ def IsActive(*args, **kwargs):
+ """
+ IsActive(self) -> bool
+
+ Return True if our app has focus.
+ """
+ return _core_.PyApp_IsActive(*args, **kwargs)
+
+ def SetTopWindow(*args, **kwargs):
+ """
+ SetTopWindow(self, Window win)
+
+ Set the *main* top level window
+ """
+ return _core_.PyApp_SetTopWindow(*args, **kwargs)
+
+ def GetTopWindow(*args, **kwargs):
+ """
+ GetTopWindow(self) -> Window
+
+ Return the *main* top level window (if it hadn't been set previously
+ with SetTopWindow(), will return just some top level window and, if
+ there not any, will return None)
+ """
+ return _core_.PyApp_GetTopWindow(*args, **kwargs)
+
+ def SetExitOnFrameDelete(*args, **kwargs):
+ """
+ SetExitOnFrameDelete(self, bool flag)
+
+ Control the exit behaviour: by default, the program will exit the main
+ loop (and so, usually, terminate) when the last top-level program
+ window is deleted. Beware that if you disable this behaviour (with
+ SetExitOnFrameDelete(False)), you'll have to call ExitMainLoop()
+ explicitly from somewhere.
+ """
+ return _core_.PyApp_SetExitOnFrameDelete(*args, **kwargs)
+
+ def GetExitOnFrameDelete(*args, **kwargs):
+ """
+ GetExitOnFrameDelete(self) -> bool
+
+ Get the current exit behaviour setting.
+ """
+ return _core_.PyApp_GetExitOnFrameDelete(*args, **kwargs)
+
+ def SetUseBestVisual(*args, **kwargs):
+ """
+ SetUseBestVisual(self, bool flag, bool forceTrueColour=False)
+
+ Set whether the app should try to use the best available visual on
+ systems where more than one is available, (Sun, SGI, XFree86 4, etc.)
+ """
+ return _core_.PyApp_SetUseBestVisual(*args, **kwargs)
+
+ def GetUseBestVisual(*args, **kwargs):
+ """
+ GetUseBestVisual(self) -> bool
+
+ Get current UseBestVisual setting.
+ """
+ return _core_.PyApp_GetUseBestVisual(*args, **kwargs)
+
+ def SetPrintMode(*args, **kwargs):
+ """SetPrintMode(self, int mode)"""
+ return _core_.PyApp_SetPrintMode(*args, **kwargs)
+
+ def GetPrintMode(*args, **kwargs):
+ """GetPrintMode(self) -> int"""
+ return _core_.PyApp_GetPrintMode(*args, **kwargs)
+
+ def SetAssertMode(*args, **kwargs):
+ """
+ SetAssertMode(self, int mode)
+
+ Set the OnAssert behaviour for debug and hybrid builds.
+ """
+ return _core_.PyApp_SetAssertMode(*args, **kwargs)
+
+ def GetAssertMode(*args, **kwargs):
+ """
+ GetAssertMode(self) -> int
+
+ Get the current OnAssert behaviour setting.
+ """
+ return _core_.PyApp_GetAssertMode(*args, **kwargs)
+
+ def MacHideApp(*args, **kwargs):
+ """
+ MacHideApp(self)
+
+ Hide all application windows just as the user can do with the system
+ Hide command. Mac only.
+ """
+ return _core_.PyApp_MacHideApp(*args, **kwargs)
+
+ def GetMacSupportPCMenuShortcuts(*args, **kwargs):
+ """GetMacSupportPCMenuShortcuts() -> bool"""
+ return _core_.PyApp_GetMacSupportPCMenuShortcuts(*args, **kwargs)
+
+ GetMacSupportPCMenuShortcuts = staticmethod(GetMacSupportPCMenuShortcuts)
+ def GetMacAboutMenuItemId(*args, **kwargs):
+ """GetMacAboutMenuItemId() -> long"""
+ return _core_.PyApp_GetMacAboutMenuItemId(*args, **kwargs)
+
+ GetMacAboutMenuItemId = staticmethod(GetMacAboutMenuItemId)
+ def GetMacPreferencesMenuItemId(*args, **kwargs):
+ """GetMacPreferencesMenuItemId() -> long"""
+ return _core_.PyApp_GetMacPreferencesMenuItemId(*args, **kwargs)
+
+ GetMacPreferencesMenuItemId = staticmethod(GetMacPreferencesMenuItemId)
+ def GetMacExitMenuItemId(*args, **kwargs):
+ """GetMacExitMenuItemId() -> long"""
+ return _core_.PyApp_GetMacExitMenuItemId(*args, **kwargs)
+
+ GetMacExitMenuItemId = staticmethod(GetMacExitMenuItemId)
+ def GetMacHelpMenuTitleName(*args, **kwargs):
+ """GetMacHelpMenuTitleName() -> String"""
+ return _core_.PyApp_GetMacHelpMenuTitleName(*args, **kwargs)
+
+ GetMacHelpMenuTitleName = staticmethod(GetMacHelpMenuTitleName)
+ def SetMacSupportPCMenuShortcuts(*args, **kwargs):
+ """SetMacSupportPCMenuShortcuts(bool val)"""
+ return _core_.PyApp_SetMacSupportPCMenuShortcuts(*args, **kwargs)
+
+ SetMacSupportPCMenuShortcuts = staticmethod(SetMacSupportPCMenuShortcuts)
+ def SetMacAboutMenuItemId(*args, **kwargs):
+ """SetMacAboutMenuItemId(long val)"""
+ return _core_.PyApp_SetMacAboutMenuItemId(*args, **kwargs)
+
+ SetMacAboutMenuItemId = staticmethod(SetMacAboutMenuItemId)
+ def SetMacPreferencesMenuItemId(*args, **kwargs):
+ """SetMacPreferencesMenuItemId(long val)"""
+ return _core_.PyApp_SetMacPreferencesMenuItemId(*args, **kwargs)
+
+ SetMacPreferencesMenuItemId = staticmethod(SetMacPreferencesMenuItemId)
+ def SetMacExitMenuItemId(*args, **kwargs):
+ """SetMacExitMenuItemId(long val)"""
+ return _core_.PyApp_SetMacExitMenuItemId(*args, **kwargs)
+
+ SetMacExitMenuItemId = staticmethod(SetMacExitMenuItemId)
+ def SetMacHelpMenuTitleName(*args, **kwargs):
+ """SetMacHelpMenuTitleName(String val)"""
+ return _core_.PyApp_SetMacHelpMenuTitleName(*args, **kwargs)
+
+ SetMacHelpMenuTitleName = staticmethod(SetMacHelpMenuTitleName)
+ def _BootstrapApp(*args, **kwargs):
+ """
+ _BootstrapApp(self)
+
+ For internal use only
+ """
+ return _core_.PyApp__BootstrapApp(*args, **kwargs)
+
+ def GetComCtl32Version(*args, **kwargs):
+ """
+ GetComCtl32Version() -> int
+
+ Returns 400, 470, 471, etc. for comctl32.dll 4.00, 4.70, 4.71 or 0 if
+ it wasn't found at all. Raises an exception on non-Windows platforms.
+ """
+ return _core_.PyApp_GetComCtl32Version(*args, **kwargs)
+
+ GetComCtl32Version = staticmethod(GetComCtl32Version)
+ def GetShell32Version(*args, **kwargs):
+ """
+ GetShell32Version() -> int
+
+ Returns 400, 470, 471, etc. for shell32.dll 4.00, 4.70, 4.71 or 0 if
+ it wasn't found at all. Raises an exception on non-Windows platforms.
+ """
+ return _core_.PyApp_GetShell32Version(*args, **kwargs)
+
+ GetShell32Version = staticmethod(GetShell32Version)
+ def IsDisplayAvailable(*args, **kwargs):
+ """
+ IsDisplayAvailable() -> bool
+
+ Tests if it is possible to create a GUI in the current environment.
+ This will mean different things on the different platforms.
+
+ * On X Windows systems this function will return ``False`` if it is
+ not able to open a connection to the X server, which can happen
+ if $DISPLAY is not set, or is not set correctly.
+
+ * On Mac OS X a ``False`` return value will mean that wx is not
+ able to access the window manager, which can happen if logged in
+ remotely or if running from the normal version of python instead
+ of the framework version, (i.e., pythonw.)
+
+ * On MS Windows...
+
+ """
+ return _core_.PyApp_IsDisplayAvailable(*args, **kwargs)
+
+ IsDisplayAvailable = staticmethod(IsDisplayAvailable)
+ AppName = property(GetAppName,SetAppName,doc="See `GetAppName` and `SetAppName`")
+ AssertMode = property(GetAssertMode,SetAssertMode,doc="See `GetAssertMode` and `SetAssertMode`")
+ ClassName = property(GetClassName,SetClassName,doc="See `GetClassName` and `SetClassName`")
+ ExitOnFrameDelete = property(GetExitOnFrameDelete,SetExitOnFrameDelete,doc="See `GetExitOnFrameDelete` and `SetExitOnFrameDelete`")
+ LayoutDirection = property(GetLayoutDirection,doc="See `GetLayoutDirection`")
+ PrintMode = property(GetPrintMode,SetPrintMode,doc="See `GetPrintMode` and `SetPrintMode`")
+ TopWindow = property(GetTopWindow,SetTopWindow,doc="See `GetTopWindow` and `SetTopWindow`")
+ Traits = property(GetTraits,doc="See `GetTraits`")
+ UseBestVisual = property(GetUseBestVisual,SetUseBestVisual,doc="See `GetUseBestVisual` and `SetUseBestVisual`")
+ VendorName = property(GetVendorName,SetVendorName,doc="See `GetVendorName` and `SetVendorName`")
+ Active = property(IsActive)
+ AppDisplayName = property(GetAppDisplayName,SetAppDisplayName)
+ VendorDisplayName = property(GetVendorDisplayName,SetVendorDisplayName)
+_core_.PyApp_swigregister(PyApp)
+
+def PyApp_GetTraitsIfExists(*args):
+ """
+ PyApp_GetTraitsIfExists() -> wxAppTraits
+
+ This function provides safer access to traits object than
+ wx.GetApp().GetTraits() during startup or termination when the global
+ application object itself may be unavailable.
+ """
+ return _core_.PyApp_GetTraitsIfExists(*args)
+
+def PyApp_IsMainLoopRunning(*args):
+ """
+ PyApp_IsMainLoopRunning() -> bool
+
+ Returns True if we're running the main loop, i.e. if the events can
+ currently be dispatched.
+ """
+ return _core_.PyApp_IsMainLoopRunning(*args)
+
+def PyApp_GetMacSupportPCMenuShortcuts(*args):
+ """PyApp_GetMacSupportPCMenuShortcuts() -> bool"""
+ return _core_.PyApp_GetMacSupportPCMenuShortcuts(*args)
+
+def PyApp_GetMacAboutMenuItemId(*args):
+ """PyApp_GetMacAboutMenuItemId() -> long"""
+ return _core_.PyApp_GetMacAboutMenuItemId(*args)
+
+def PyApp_GetMacPreferencesMenuItemId(*args):
+ """PyApp_GetMacPreferencesMenuItemId() -> long"""
+ return _core_.PyApp_GetMacPreferencesMenuItemId(*args)
+
+def PyApp_GetMacExitMenuItemId(*args):
+ """PyApp_GetMacExitMenuItemId() -> long"""
+ return _core_.PyApp_GetMacExitMenuItemId(*args)
+
+def PyApp_GetMacHelpMenuTitleName(*args):
+ """PyApp_GetMacHelpMenuTitleName() -> String"""
+ return _core_.PyApp_GetMacHelpMenuTitleName(*args)
+
+def PyApp_SetMacSupportPCMenuShortcuts(*args, **kwargs):
+ """PyApp_SetMacSupportPCMenuShortcuts(bool val)"""
+ return _core_.PyApp_SetMacSupportPCMenuShortcuts(*args, **kwargs)
+
+def PyApp_SetMacAboutMenuItemId(*args, **kwargs):
+ """PyApp_SetMacAboutMenuItemId(long val)"""
+ return _core_.PyApp_SetMacAboutMenuItemId(*args, **kwargs)
+
+def PyApp_SetMacPreferencesMenuItemId(*args, **kwargs):
+ """PyApp_SetMacPreferencesMenuItemId(long val)"""
+ return _core_.PyApp_SetMacPreferencesMenuItemId(*args, **kwargs)
+
+def PyApp_SetMacExitMenuItemId(*args, **kwargs):
+ """PyApp_SetMacExitMenuItemId(long val)"""
+ return _core_.PyApp_SetMacExitMenuItemId(*args, **kwargs)
+
+def PyApp_SetMacHelpMenuTitleName(*args, **kwargs):
+ """PyApp_SetMacHelpMenuTitleName(String val)"""
+ return _core_.PyApp_SetMacHelpMenuTitleName(*args, **kwargs)
+
+def PyApp_GetComCtl32Version(*args):
+ """
+ PyApp_GetComCtl32Version() -> int
+
+ Returns 400, 470, 471, etc. for comctl32.dll 4.00, 4.70, 4.71 or 0 if
+ it wasn't found at all. Raises an exception on non-Windows platforms.
+ """
+ return _core_.PyApp_GetComCtl32Version(*args)
+
+def PyApp_GetShell32Version(*args):
+ """
+ PyApp_GetShell32Version() -> int
+
+ Returns 400, 470, 471, etc. for shell32.dll 4.00, 4.70, 4.71 or 0 if
+ it wasn't found at all. Raises an exception on non-Windows platforms.
+ """
+ return _core_.PyApp_GetShell32Version(*args)
+
+def PyApp_IsDisplayAvailable(*args):
+ """
+ PyApp_IsDisplayAvailable() -> bool
+
+ Tests if it is possible to create a GUI in the current environment.
+ This will mean different things on the different platforms.
+
+ * On X Windows systems this function will return ``False`` if it is
+ not able to open a connection to the X server, which can happen
+ if $DISPLAY is not set, or is not set correctly.
+
+ * On Mac OS X a ``False`` return value will mean that wx is not
+ able to access the window manager, which can happen if logged in
+ remotely or if running from the normal version of python instead
+ of the framework version, (i.e., pythonw.)
+
+ * On MS Windows...
+
+ """
+ return _core_.PyApp_IsDisplayAvailable(*args)
+
+#---------------------------------------------------------------------------
+
+
+def Exit(*args):
+ """
+ Exit()
+
+ Force an exit of the application. Convenience for wx.GetApp().Exit()
+ """
+ return _core_.Exit(*args)
+
+def Yield(*args):
+ """
+ Yield() -> bool
+
+ Yield to other apps/messages. Convenience for wx.GetApp().Yield()
+ """
+ return _core_.Yield(*args)
+
+def YieldIfNeeded(*args):
+ """
+ YieldIfNeeded() -> bool
+
+ Yield to other apps/messages. Convenience for wx.GetApp().Yield(True)
+ """
+ return _core_.YieldIfNeeded(*args)
+
+def SafeYield(*args, **kwargs):
+ """
+ SafeYield(Window win=None, bool onlyIfNeeded=False) -> bool
+
+ This function is similar to `wx.Yield`, except that it disables the
+ user input to all program windows before calling `wx.Yield` and
+ re-enables it again afterwards. If ``win`` is not None, this window
+ will remain enabled, allowing the implementation of some limited user
+ interaction.
+
+ :Returns: the result of the call to `wx.Yield`.
+ """
+ return _core_.SafeYield(*args, **kwargs)
+
+def WakeUpIdle(*args):
+ """
+ WakeUpIdle()
+
+ Cause the message queue to become empty again, so idle events will be
+ sent.
+ """
+ return _core_.WakeUpIdle(*args)
+
+def PostEvent(*args, **kwargs):
+ """
+ PostEvent(EvtHandler dest, Event event)
+
+ Send an event to a window or other wx.EvtHandler to be processed
+ later.
+ """
+ return _core_.PostEvent(*args, **kwargs)
+
+def App_CleanUp(*args):
+ """
+ App_CleanUp()
+
+ For internal use only, it is used to cleanup after wxWidgets when
+ Python shuts down.
+ """
+ return _core_.App_CleanUp(*args)
+
+def GetApp(*args):
+ """
+ GetApp() -> PyApp
+
+ Return a reference to the current wx.App object.
+ """
+ return _core_.GetApp(*args)
+
+def SetDefaultPyEncoding(*args, **kwargs):
+ """
+ SetDefaultPyEncoding(string encoding)
+
+ Sets the encoding that wxPython will use when it needs to convert a
+ Python string or unicode object to or from a wxString.
+
+ The default encoding is the value of ``locale.getdefaultlocale()[1]``
+ but please be aware that the default encoding within the same locale
+ may be slightly different on different platforms. For example, please
+ see http://www.alanwood.net/demos/charsetdiffs.html for differences
+ between the common latin/roman encodings.
+ """
+ return _core_.SetDefaultPyEncoding(*args, **kwargs)
+
+def GetDefaultPyEncoding(*args):
+ """
+ GetDefaultPyEncoding() -> string
+
+ Gets the current encoding that wxPython will use when it needs to
+ convert a Python string or unicode object to or from a wxString.
+ """
+ return _core_.GetDefaultPyEncoding(*args)
+#----------------------------------------------------------------------
+
+class PyOnDemandOutputWindow:
+ """
+ A class that can be used for redirecting Python's stdout and
+ stderr streams. It will do nothing until something is wrriten to
+ the stream at which point it will create a Frame with a text area
+ and write the text there.
+ """
+ def __init__(self, title = "wxPython: stdout/stderr"):
+ self.frame = None
+ self.title = title
+ self.pos = wx.DefaultPosition
+ self.size = (450, 300)
+ self.parent = None
+
+ def SetParent(self, parent):
+ """Set the window to be used as the popup Frame's parent."""
+ self.parent = parent
+
+
+ def CreateOutputWindow(self, st):
+ self.frame = wx.Frame(self.parent, -1, self.title, self.pos, self.size,
+ style=wx.DEFAULT_FRAME_STYLE)
+ self.text = wx.TextCtrl(self.frame, -1, "",
+ style=wx.TE_MULTILINE|wx.TE_READONLY)
+ self.text.AppendText(st)
+ self.frame.Show(True)
+ self.frame.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+
+ def OnCloseWindow(self, event):
+ if self.frame is not None:
+ self.frame.Destroy()
+ self.frame = None
+ self.text = None
+ self.parent = None
+
+
+ # These methods provide the file-like output behaviour.
+ def write(self, text):
+ """
+ Create the output window if needed and write the string to it.
+ If not called in the context of the gui thread then uses
+ CallAfter to do the work there.
+ """
+ if self.frame is None:
+ if not wx.Thread_IsMain():
+ wx.CallAfter(self.CreateOutputWindow, text)
+ else:
+ self.CreateOutputWindow(text)
+ else:
+ if not wx.Thread_IsMain():
+ wx.CallAfter(self.text.AppendText, text)
+ else:
+ self.text.AppendText(text)
+
+
+ def close(self):
+ if self.frame is not None:
+ wx.CallAfter(self.frame.Close)
+
+
+ def flush(self):
+ pass
+
+
+
+#----------------------------------------------------------------------
+
+class App(wx.PyApp):
+ """
+ The ``wx.App`` class represents the application and is used to:
+
+ * bootstrap the wxPython system and initialize the underlying
+ gui toolkit
+ * set and get application-wide properties
+ * implement the windowing system main message or event loop,
+ and to dispatch events to window instances
+ * etc.
+
+ Every application must have a ``wx.App`` instance, and all
+ creation of UI objects should be delayed until after the
+ ``wx.App`` object has been created in order to ensure that the gui
+ platform and wxWidgets have been fully initialized.
+
+ Normally you would derive from this class and implement an
+ ``OnInit`` method that creates a frame and then calls
+ ``self.SetTopWindow(frame)``.
+ """
+
+ outputWindowClass = PyOnDemandOutputWindow
+
+ def __init__(self,
+ redirect=False,
+ filename=None,
+ useBestVisual=False,
+ clearSigInt=True):
+ """
+ Construct a ``wx.App`` object.
+
+ :param redirect: Should ``sys.stdout`` and ``sys.stderr`` be
+ redirected? Defaults to False. If ``filename`` is None
+ then output will be redirected to a window that pops up
+ as needed. (You can control what kind of window is created
+ for the output by resetting the class variable
+ ``outputWindowClass`` to a class of your choosing.)
+
+ :param filename: The name of a file to redirect output to, if
+ redirect is True.
+
+ :param useBestVisual: Should the app try to use the best
+ available visual provided by the system (only relevant on
+ systems that have more than one visual.) This parameter
+ must be used instead of calling `SetUseBestVisual` later
+ on because it must be set before the underlying GUI
+ toolkit is initialized.
+
+ :param clearSigInt: Should SIGINT be cleared? This allows the
+ app to terminate upon a Ctrl-C in the console like other
+ GUI apps will.
+
+ :note: You should override OnInit to do applicaition
+ initialization to ensure that the system, toolkit and
+ wxWidgets are fully initialized.
+ """
+
+ wx.PyApp.__init__(self)
+
+ # make sure we can create a GUI
+ if not self.IsDisplayAvailable():
+
+ if wx.Platform == "__WXMAC__":
+ msg = """This program needs access to the screen.
+Please run with a Framework build of python, and only when you are
+logged in on the main display of your Mac."""
+
+ elif wx.Platform == "__WXGTK__":
+ msg ="Unable to access the X Display, is $DISPLAY set properly?"
+
+ else:
+ msg = "Unable to create GUI"
+ # TODO: more description is needed for wxMSW...
+
+ raise SystemExit(msg)
+
+ # This has to be done before OnInit
+ self.SetUseBestVisual(useBestVisual)
+
+ # Set the default handler for SIGINT. This fixes a problem
+ # where if Ctrl-C is pressed in the console that started this
+ # app then it will not appear to do anything, (not even send
+ # KeyboardInterrupt???) but will later segfault on exit. By
+ # setting the default handler then the app will exit, as
+ # expected (depending on platform.)
+ if clearSigInt:
+ try:
+ import signal
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ except:
+ pass
+
+ # Save and redirect the stdio to a window?
+ self.stdioWin = None
+ self.saveStdio = (_sys.stdout, _sys.stderr)
+ if redirect:
+ self.RedirectStdio(filename)
+
+ # Use Python's install prefix as the default
+ wx.StandardPaths.Get().SetInstallPrefix(_sys.prefix)
+
+ # Until the new native control for wxMac is up to par, still use the generic one.
+ wx.SystemOptions.SetOptionInt("mac.listctrl.always_use_generic", 1)
+
+ # This finishes the initialization of wxWindows and then calls
+ # the OnInit that should be present in the derived class
+ self._BootstrapApp()
+
+
+ def OnPreInit(self):
+ """
+ Things that must be done after _BootstrapApp has done its
+ thing, but would be nice if they were already done by the time
+ that OnInit is called.
+ """
+ wx.StockGDI._initStockObjects()
+
+
+ def __del__(self, destroy=wx.PyApp.__del__):
+ self.RestoreStdio() # Just in case the MainLoop was overridden
+ destroy(self)
+
+ def Destroy(self):
+ self.this.own(False)
+ wx.PyApp.Destroy(self)
+
+ def SetTopWindow(self, frame):
+ """Set the \"main\" top level window"""
+ if self.stdioWin:
+ self.stdioWin.SetParent(frame)
+ wx.PyApp.SetTopWindow(self, frame)
+
+
+ def MainLoop(self):
+ """Execute the main GUI event loop"""
+ wx.PyApp.MainLoop(self)
+ self.RestoreStdio()
+
+
+ def RedirectStdio(self, filename=None):
+ """Redirect sys.stdout and sys.stderr to a file or a popup window."""
+ if filename:
+ _sys.stdout = _sys.stderr = open(filename, 'a')
+ else:
+ self.stdioWin = self.outputWindowClass()
+ _sys.stdout = _sys.stderr = self.stdioWin
+
+
+ def RestoreStdio(self):
+ try:
+ _sys.stdout, _sys.stderr = self.saveStdio
+ except:
+ pass
+
+
+ def SetOutputWindowAttributes(self, title=None, pos=None, size=None):
+ """
+ Set the title, position and/or size of the output window if
+ the stdio has been redirected. This should be called before
+ any output would cause the output window to be created.
+ """
+ if self.stdioWin:
+ if title is not None:
+ self.stdioWin.title = title
+ if pos is not None:
+ self.stdioWin.pos = pos
+ if size is not None:
+ self.stdioWin.size = size
+
+
+ @staticmethod
+ def Get():
+ return wx.GetApp()
+
+# change from wx.PyApp_XX to wx.App_XX
+App_GetMacSupportPCMenuShortcuts = _core_.PyApp_GetMacSupportPCMenuShortcuts
+App_GetMacAboutMenuItemId = _core_.PyApp_GetMacAboutMenuItemId
+App_GetMacPreferencesMenuItemId = _core_.PyApp_GetMacPreferencesMenuItemId
+App_GetMacExitMenuItemId = _core_.PyApp_GetMacExitMenuItemId
+App_GetMacHelpMenuTitleName = _core_.PyApp_GetMacHelpMenuTitleName
+App_SetMacSupportPCMenuShortcuts = _core_.PyApp_SetMacSupportPCMenuShortcuts
+App_SetMacAboutMenuItemId = _core_.PyApp_SetMacAboutMenuItemId
+App_SetMacPreferencesMenuItemId = _core_.PyApp_SetMacPreferencesMenuItemId
+App_SetMacExitMenuItemId = _core_.PyApp_SetMacExitMenuItemId
+App_SetMacHelpMenuTitleName = _core_.PyApp_SetMacHelpMenuTitleName
+App_GetComCtl32Version = _core_.PyApp_GetComCtl32Version
+
+#----------------------------------------------------------------------------
+
+@wx.deprecated
+class PySimpleApp(wx.App):
+ """
+ A simple application class. You can just create one of these and
+ then then make your top level windows later, and not have to worry
+ about OnInit. For example::
+
+ app = wx.PySimpleApp()
+ frame = wx.Frame(None, title='Hello World')
+ frame.Show()
+ app.MainLoop()
+
+ :see: `wx.App`
+ """
+
+ def __init__(self, redirect=False, filename=None,
+ useBestVisual=False, clearSigInt=True):
+ """
+ :see: `wx.App.__init__`
+ """
+ wx.App.__init__(self, redirect, filename, useBestVisual, clearSigInt)
+
+ def OnInit(self):
+ return True
+
+
+
+# Is anybody using this one?
+class PyWidgetTester(wx.App):
+ def __init__(self, size = (250, 100)):
+ self.size = size
+ wx.App.__init__(self, 0)
+
+ def OnInit(self):
+ self.frame = wx.Frame(None, -1, "Widget Tester", pos=(0,0), size=self.size)
+ self.SetTopWindow(self.frame)
+ return True
+
+ def SetWidget(self, widgetClass, *args, **kwargs):
+ w = widgetClass(self.frame, *args, **kwargs)
+ self.frame.Show(True)
+
+#----------------------------------------------------------------------------
+# Make sure that system resources allocated by wx are properly cleaned
+# up when the Python interpreter exits.
+
+import atexit
+atexit.register(_core_.App_CleanUp)
+del atexit
+
+#----------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+
+class EventLoopBase(object):
+ """Proxy of C++ EventLoopBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_EventLoopBase
+ __del__ = lambda self : None;
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _core_.EventLoopBase_IsOk(*args, **kwargs)
+
+ def IsMain(*args, **kwargs):
+ """IsMain(self) -> bool"""
+ return _core_.EventLoopBase_IsMain(*args, **kwargs)
+
+ def Run(*args, **kwargs):
+ """Run(self) -> int"""
+ return _core_.EventLoopBase_Run(*args, **kwargs)
+
+ def IsRunning(*args, **kwargs):
+ """IsRunning(self) -> bool"""
+ return _core_.EventLoopBase_IsRunning(*args, **kwargs)
+
+ def Exit(*args, **kwargs):
+ """Exit(self, int rc=0)"""
+ return _core_.EventLoopBase_Exit(*args, **kwargs)
+
+ def Pending(*args, **kwargs):
+ """Pending(self) -> bool"""
+ return _core_.EventLoopBase_Pending(*args, **kwargs)
+
+ def Dispatch(*args, **kwargs):
+ """Dispatch(self) -> bool"""
+ return _core_.EventLoopBase_Dispatch(*args, **kwargs)
+
+ def DispatchTimeout(*args, **kwargs):
+ """DispatchTimeout(self, unsigned long timeout) -> int"""
+ return _core_.EventLoopBase_DispatchTimeout(*args, **kwargs)
+
+ def WakeUp(*args, **kwargs):
+ """WakeUp(self)"""
+ return _core_.EventLoopBase_WakeUp(*args, **kwargs)
+
+ def WakeUpIdle(*args, **kwargs):
+ """WakeUpIdle(self)"""
+ return _core_.EventLoopBase_WakeUpIdle(*args, **kwargs)
+
+ def ProcessIdle(*args, **kwargs):
+ """ProcessIdle(self) -> bool"""
+ return _core_.EventLoopBase_ProcessIdle(*args, **kwargs)
+
+ def Yield(*args, **kwargs):
+ """Yield(self, bool onlyIfNeeded=False) -> bool"""
+ return _core_.EventLoopBase_Yield(*args, **kwargs)
+
+ def YieldFor(*args, **kwargs):
+ """YieldFor(self, long eventsToProcess) -> bool"""
+ return _core_.EventLoopBase_YieldFor(*args, **kwargs)
+
+ def IsYielding(*args, **kwargs):
+ """IsYielding(self) -> bool"""
+ return _core_.EventLoopBase_IsYielding(*args, **kwargs)
+
+ def IsEventAllowedInsideYield(*args, **kwargs):
+ """IsEventAllowedInsideYield(self, int cat) -> bool"""
+ return _core_.EventLoopBase_IsEventAllowedInsideYield(*args, **kwargs)
+
+ def GetActive(*args, **kwargs):
+ """GetActive() -> EventLoopBase"""
+ return _core_.EventLoopBase_GetActive(*args, **kwargs)
+
+ GetActive = staticmethod(GetActive)
+ def SetActive(*args, **kwargs):
+ """SetActive(EventLoopBase loop)"""
+ return _core_.EventLoopBase_SetActive(*args, **kwargs)
+
+ SetActive = staticmethod(SetActive)
+_core_.EventLoopBase_swigregister(EventLoopBase)
+
+def EventLoopBase_GetActive(*args):
+ """EventLoopBase_GetActive() -> EventLoopBase"""
+ return _core_.EventLoopBase_GetActive(*args)
+
+def EventLoopBase_SetActive(*args, **kwargs):
+ """EventLoopBase_SetActive(EventLoopBase loop)"""
+ return _core_.EventLoopBase_SetActive(*args, **kwargs)
+
+class GUIEventLoop(EventLoopBase):
+ """Proxy of C++ GUIEventLoop class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GUIEventLoop"""
+ _core_.GUIEventLoop_swiginit(self,_core_.new_GUIEventLoop(*args, **kwargs))
+_core_.GUIEventLoop_swigregister(GUIEventLoop)
+
+class EventLoop(GUIEventLoop):
+ """Class using the old name for compatibility."""
+ pass
+
+class ModalEventLoop(GUIEventLoop):
+ """Proxy of C++ ModalEventLoop class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window winModal) -> ModalEventLoop"""
+ _core_.ModalEventLoop_swiginit(self,_core_.new_ModalEventLoop(*args, **kwargs))
+_core_.ModalEventLoop_swigregister(ModalEventLoop)
+
+class EventLoopActivator(object):
+ """Proxy of C++ EventLoopActivator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventLoopBase evtLoop) -> EventLoopActivator"""
+ _core_.EventLoopActivator_swiginit(self,_core_.new_EventLoopActivator(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_EventLoopActivator
+ __del__ = lambda self : None;
+_core_.EventLoopActivator_swigregister(EventLoopActivator)
+
+#---------------------------------------------------------------------------
+
+ACCEL_ALT = _core_.ACCEL_ALT
+ACCEL_CTRL = _core_.ACCEL_CTRL
+ACCEL_SHIFT = _core_.ACCEL_SHIFT
+ACCEL_NORMAL = _core_.ACCEL_NORMAL
+ACCEL_RAW_CTRL = _core_.ACCEL_RAW_CTRL
+ACCEL_CMD = _core_.ACCEL_CMD
+class AcceleratorEntry(object):
+ """
+ A class used to define items in an `wx.AcceleratorTable`. wxPython
+ programs can choose to use wx.AcceleratorEntry objects, but using a
+ list of 3-tuple of integers (flags, keyCode, cmdID) usually works just
+ as well. See `__init__` for of the tuple values.
+
+ :see: `wx.AcceleratorTable`
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int flags=0, int keyCode=0, int cmdID=0) -> AcceleratorEntry
+
+ Construct a wx.AcceleratorEntry.
+ """
+ _core_.AcceleratorEntry_swiginit(self,_core_.new_AcceleratorEntry(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_AcceleratorEntry
+ __del__ = lambda self : None;
+ def Set(*args, **kwargs):
+ """
+ Set(self, int flags, int keyCode, int cmd)
+
+ (Re)set the attributes of a wx.AcceleratorEntry.
+ :see `__init__`
+ """
+ return _core_.AcceleratorEntry_Set(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(String str) -> AcceleratorEntry
+
+ Create accelerator corresponding to the specified string, or None if
+ it coulnd't be parsed.
+ """
+ return _core_.AcceleratorEntry_Create(*args, **kwargs)
+
+ Create = staticmethod(Create)
+ def GetFlags(*args, **kwargs):
+ """
+ GetFlags(self) -> int
+
+ Get the AcceleratorEntry's flags.
+ """
+ return _core_.AcceleratorEntry_GetFlags(*args, **kwargs)
+
+ def GetKeyCode(*args, **kwargs):
+ """
+ GetKeyCode(self) -> int
+
+ Get the AcceleratorEntry's keycode.
+ """
+ return _core_.AcceleratorEntry_GetKeyCode(*args, **kwargs)
+
+ def GetCommand(*args, **kwargs):
+ """
+ GetCommand(self) -> int
+
+ Get the AcceleratorEntry's command ID.
+ """
+ return _core_.AcceleratorEntry_GetCommand(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _core_.AcceleratorEntry_IsOk(*args, **kwargs)
+
+ def ToString(*args, **kwargs):
+ """
+ ToString(self) -> String
+
+ Returns a string representation for the this accelerator. The string
+ is formatted using the <flags>-<keycode> format where <flags> maybe a
+ hyphen-separed list of "shift|alt|ctrl"
+
+ """
+ return _core_.AcceleratorEntry_ToString(*args, **kwargs)
+
+ def FromString(*args, **kwargs):
+ """
+ FromString(self, String str) -> bool
+
+ Returns true if the given string correctly initialized this object.
+ """
+ return _core_.AcceleratorEntry_FromString(*args, **kwargs)
+
+ Command = property(GetCommand,doc="See `GetCommand`")
+ Flags = property(GetFlags,doc="See `GetFlags`")
+ KeyCode = property(GetKeyCode,doc="See `GetKeyCode`")
+_core_.AcceleratorEntry_swigregister(AcceleratorEntry)
+
+def AcceleratorEntry_Create(*args, **kwargs):
+ """
+ AcceleratorEntry_Create(String str) -> AcceleratorEntry
+
+ Create accelerator corresponding to the specified string, or None if
+ it coulnd't be parsed.
+ """
+ return _core_.AcceleratorEntry_Create(*args, **kwargs)
+
+class AcceleratorTable(Object):
+ """
+ An accelerator table allows the application to specify a table of
+ keyboard shortcuts for menus or other commands. On Windows, menu or
+ button commands are supported; on GTK, only menu commands are
+ supported.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(entries) -> AcceleratorTable
+
+ Construct an AcceleratorTable from a list of `wx.AcceleratorEntry`
+ items or or of 3-tuples (flags, keyCode, cmdID)
+
+ :see: `wx.AcceleratorEntry`
+ """
+ _core_.AcceleratorTable_swiginit(self,_core_.new_AcceleratorTable(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_AcceleratorTable
+ __del__ = lambda self : None;
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _core_.AcceleratorTable_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+_core_.AcceleratorTable_swigregister(AcceleratorTable)
+
+def GetAccelFromString(label):
+ entry = AcceleratorEntry()
+ if '\t' in label:
+ entry.FromString(label)
+ return entry
+
+#---------------------------------------------------------------------------
+
+class WindowList_iterator(object):
+ """This class serves as an iterator for a wxWindowList object."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_WindowList_iterator
+ __del__ = lambda self : None;
+ def next(*args, **kwargs):
+ """next(self) -> Window"""
+ return _core_.WindowList_iterator_next(*args, **kwargs)
+
+_core_.WindowList_iterator_swigregister(WindowList_iterator)
+NullAcceleratorTable = cvar.NullAcceleratorTable
+PanelNameStr = cvar.PanelNameStr
+
+class WindowList(object):
+ """
+ This class wraps a wxList-based class and gives it a Python
+ sequence-like interface. Sequence operations supported are length,
+ index access and iteration.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_WindowList
+ __del__ = lambda self : None;
+ def __len__(*args, **kwargs):
+ """__len__(self) -> size_t"""
+ return _core_.WindowList___len__(*args, **kwargs)
+
+ def __getitem__(*args, **kwargs):
+ """__getitem__(self, size_t index) -> Window"""
+ return _core_.WindowList___getitem__(*args, **kwargs)
+
+ def __contains__(*args, **kwargs):
+ """__contains__(self, Window obj) -> bool"""
+ return _core_.WindowList___contains__(*args, **kwargs)
+
+ def __iter__(*args, **kwargs):
+ """__iter__(self) -> WindowList_iterator"""
+ return _core_.WindowList___iter__(*args, **kwargs)
+
+ def index(*args, **kwargs):
+ """index(self, Window obj) -> int"""
+ return _core_.WindowList_index(*args, **kwargs)
+
+ def __repr__(self):
+ return "wxWindowList: " + repr(list(self))
+
+_core_.WindowList_swigregister(WindowList)
+
+class VisualAttributes(object):
+ """struct containing all the visual attributes of a control"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> VisualAttributes
+
+ struct containing all the visual attributes of a control
+ """
+ _core_.VisualAttributes_swiginit(self,_core_.new_VisualAttributes(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_VisualAttributes
+ __del__ = lambda self : None;
+ def _get_font(*args, **kwargs):
+ """_get_font(self) -> Font"""
+ return _core_.VisualAttributes__get_font(*args, **kwargs)
+
+ def _get_colFg(*args, **kwargs):
+ """_get_colFg(self) -> Colour"""
+ return _core_.VisualAttributes__get_colFg(*args, **kwargs)
+
+ def _get_colBg(*args, **kwargs):
+ """_get_colBg(self) -> Colour"""
+ return _core_.VisualAttributes__get_colBg(*args, **kwargs)
+
+ font = property(_get_font)
+ colFg = property(_get_colFg)
+ colBg = property(_get_colBg)
+_core_.VisualAttributes_swigregister(VisualAttributes)
+
+WINDOW_VARIANT_NORMAL = _core_.WINDOW_VARIANT_NORMAL
+WINDOW_VARIANT_SMALL = _core_.WINDOW_VARIANT_SMALL
+WINDOW_VARIANT_MINI = _core_.WINDOW_VARIANT_MINI
+WINDOW_VARIANT_LARGE = _core_.WINDOW_VARIANT_LARGE
+WINDOW_VARIANT_MAX = _core_.WINDOW_VARIANT_MAX
+SHOW_EFFECT_NONE = _core_.SHOW_EFFECT_NONE
+SHOW_EFFECT_ROLL_TO_LEFT = _core_.SHOW_EFFECT_ROLL_TO_LEFT
+SHOW_EFFECT_ROLL_TO_RIGHT = _core_.SHOW_EFFECT_ROLL_TO_RIGHT
+SHOW_EFFECT_ROLL_TO_TOP = _core_.SHOW_EFFECT_ROLL_TO_TOP
+SHOW_EFFECT_ROLL_TO_BOTTOM = _core_.SHOW_EFFECT_ROLL_TO_BOTTOM
+SHOW_EFFECT_SLIDE_TO_LEFT = _core_.SHOW_EFFECT_SLIDE_TO_LEFT
+SHOW_EFFECT_SLIDE_TO_RIGHT = _core_.SHOW_EFFECT_SLIDE_TO_RIGHT
+SHOW_EFFECT_SLIDE_TO_TOP = _core_.SHOW_EFFECT_SLIDE_TO_TOP
+SHOW_EFFECT_SLIDE_TO_BOTTOM = _core_.SHOW_EFFECT_SLIDE_TO_BOTTOM
+SHOW_EFFECT_BLEND = _core_.SHOW_EFFECT_BLEND
+SHOW_EFFECT_EXPAND = _core_.SHOW_EFFECT_EXPAND
+SHOW_EFFECT_MAX = _core_.SHOW_EFFECT_MAX
+SEND_EVENT_POST = _core_.SEND_EVENT_POST
+class Window(EvtHandler):
+ """
+ wx.Window is the base class for all windows and represents any visible
+ object on the screen. All controls, top level windows and so on are
+ wx.Windows. Sizers and device contexts are not however, as they don't
+ appear on screen themselves.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=PanelNameStr) -> Window
+
+ Construct and show a generic Window.
+ """
+ _core_.Window_swiginit(self,_core_.new_Window(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=PanelNameStr) -> bool
+
+ Create the GUI part of the Window for 2-phase creation mode.
+ """
+ return _core_.Window_Create(*args, **kwargs)
+
+ def Close(*args, **kwargs):
+ """
+ Close(self, bool force=False) -> bool
+
+ This function simply generates a EVT_CLOSE event whose handler usually
+ tries to close the window. It doesn't close the window itself,
+ however. If force is False (the default) then the window's close
+ handler will be allowed to veto the destruction of the window.
+ """
+ return _core_.Window_Close(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """
+ Destroy(self) -> bool
+
+ Destroys the window safely. Frames and dialogs are not destroyed
+ immediately when this function is called -- they are added to a list
+ of windows to be deleted on idle time, when all the window's events
+ have been processed. This prevents problems with events being sent to
+ non-existent windows.
+
+ Returns True if the window has either been successfully deleted, or it
+ has been added to the list of windows pending real deletion.
+ """
+ args[0].this.own(False)
+ return _core_.Window_Destroy(*args, **kwargs)
+
+ def DestroyChildren(*args, **kwargs):
+ """
+ DestroyChildren(self) -> bool
+
+ Destroys all children of a window. Called automatically by the
+ destructor.
+ """
+ return _core_.Window_DestroyChildren(*args, **kwargs)
+
+ def IsBeingDeleted(*args, **kwargs):
+ """
+ IsBeingDeleted(self) -> bool
+
+ Is the window in the process of being deleted?
+ """
+ return _core_.Window_IsBeingDeleted(*args, **kwargs)
+
+ def SetLabel(*args, **kwargs):
+ """
+ SetLabel(self, String label)
+
+ Set the text which the window shows in its label if applicable.
+ """
+ return _core_.Window_SetLabel(*args, **kwargs)
+
+ def GetLabel(*args, **kwargs):
+ """
+ GetLabel(self) -> String
+
+ Generic way of getting a label from any window, for identification
+ purposes. The interpretation of this function differs from class to
+ class. For frames and dialogs, the value returned is the title. For
+ buttons or static text controls, it is the button text. This function
+ can be useful for meta-programs such as testing tools or special-needs
+ access programs)which need to identify windows by name.
+ """
+ return _core_.Window_GetLabel(*args, **kwargs)
+
+ def SetName(*args, **kwargs):
+ """
+ SetName(self, String name)
+
+ Sets the window's name. The window name is used for ressource setting
+ in X, it is not the same as the window title/label
+ """
+ return _core_.Window_SetName(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """
+ GetName(self) -> String
+
+ Returns the windows name. This name is not guaranteed to be unique;
+ it is up to the programmer to supply an appropriate name in the window
+ constructor or via wx.Window.SetName.
+ """
+ return _core_.Window_GetName(*args, **kwargs)
+
+ def SetWindowVariant(*args, **kwargs):
+ """
+ SetWindowVariant(self, int variant)
+
+ Sets the variant of the window/font size to use for this window, if
+ the platform supports variants, for example, wxMac.
+ """
+ return _core_.Window_SetWindowVariant(*args, **kwargs)
+
+ def GetWindowVariant(*args, **kwargs):
+ """GetWindowVariant(self) -> int"""
+ return _core_.Window_GetWindowVariant(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """
+ SetId(self, int winid)
+
+ Sets the identifier of the window. Each window has an integer
+ identifier. If the application has not provided one, an identifier
+ will be generated. Normally, the identifier should be provided on
+ creation and should not be modified subsequently.
+ """
+ return _core_.Window_SetId(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """
+ GetId(self) -> int
+
+ Returns the identifier of the window. Each window has an integer
+ identifier. If the application has not provided one (or the default Id
+ -1 is used) then an unique identifier with a negative value will be
+ generated.
+ """
+ return _core_.Window_GetId(*args, **kwargs)
+
+ def NewControlId(*args, **kwargs):
+ """
+ NewControlId(int count=1) -> int
+
+ Generate a unique id (or count of them consecutively), returns a
+ valid id in the auto-id range or wxID_NONE if failed. If using
+ autoid management, it will mark the id as reserved until it is
+ used (by assigning it to a wxWindowIDRef) or unreserved.
+ """
+ return _core_.Window_NewControlId(*args, **kwargs)
+
+ NewControlId = staticmethod(NewControlId)
+ def UnreserveControlId(*args, **kwargs):
+ """
+ UnreserveControlId(int id, int count=1)
+
+ If an ID generated from NewControlId is not assigned to a wxWindowIDRef,
+ it must be unreserved.
+ """
+ return _core_.Window_UnreserveControlId(*args, **kwargs)
+
+ UnreserveControlId = staticmethod(UnreserveControlId)
+ def ReleaseControlId(id):
+ UnreserveControlId(id)
+ ReleaseControlId = staticmethod(ReleaseControlId)
+
+ def GetLayoutDirection(*args, **kwargs):
+ """
+ GetLayoutDirection(self) -> int
+
+ Get the layout direction (LTR or RTL) for this window. Returns
+ ``wx.Layout_Default`` if layout direction is not supported.
+ """
+ return _core_.Window_GetLayoutDirection(*args, **kwargs)
+
+ def SetLayoutDirection(*args, **kwargs):
+ """
+ SetLayoutDirection(self, int dir)
+
+ Set the layout direction (LTR or RTL) for this window.
+ """
+ return _core_.Window_SetLayoutDirection(*args, **kwargs)
+
+ def AdjustForLayoutDirection(*args, **kwargs):
+ """
+ AdjustForLayoutDirection(self, int x, int width, int widthTotal) -> int
+
+ Mirror coordinates for RTL layout if this window uses it and if the
+ mirroring is not done automatically like Win32.
+ """
+ return _core_.Window_AdjustForLayoutDirection(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """
+ SetSize(self, Size size)
+
+ Sets the size of the window in pixels.
+ """
+ return _core_.Window_SetSize(*args, **kwargs)
+
+ def SetDimensions(*args, **kwargs):
+ """
+ SetDimensions(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO)
+
+ Sets the position and size of the window in pixels. The sizeFlags
+ parameter indicates the interpretation of the other params if they are
+ equal to -1.
+
+ ======================== ======================================
+ wx.SIZE_AUTO A -1 indicates that a class-specific
+ default should be used.
+ wx.SIZE_USE_EXISTING Existing dimensions should be used if
+ -1 values are supplied.
+ wxSIZE_ALLOW_MINUS_ONE Allow dimensions of -1 and less to be
+ interpreted as real dimensions, not
+ default values.
+ ======================== ======================================
+
+ """
+ return _core_.Window_SetDimensions(*args, **kwargs)
+
+ def SetRect(*args, **kwargs):
+ """
+ SetRect(self, Rect rect, int sizeFlags=SIZE_AUTO)
+
+ Sets the position and size of the window in pixels using a wx.Rect.
+ """
+ return _core_.Window_SetRect(*args, **kwargs)
+
+ def SetSizeWH(*args, **kwargs):
+ """
+ SetSizeWH(self, int width, int height)
+
+ Sets the size of the window in pixels.
+ """
+ return _core_.Window_SetSizeWH(*args, **kwargs)
+
+ def Move(*args, **kwargs):
+ """
+ Move(self, Point pt, int flags=SIZE_USE_EXISTING)
+
+ Moves the window to the given position.
+ """
+ return _core_.Window_Move(*args, **kwargs)
+
+ SetPosition = Move
+ def MoveXY(*args, **kwargs):
+ """
+ MoveXY(self, int x, int y, int flags=SIZE_USE_EXISTING)
+
+ Moves the window to the given position.
+ """
+ return _core_.Window_MoveXY(*args, **kwargs)
+
+ def SetInitialSize(*args, **kwargs):
+ """
+ SetInitialSize(self, Size size=DefaultSize)
+
+ A 'Smart' SetSize that will fill in default size components with the
+ window's *best size* values. Also set's the minsize for use with sizers.
+ """
+ return _core_.Window_SetInitialSize(*args, **kwargs)
+
+ SetBestFittingSize = wx.deprecated(SetInitialSize, 'Use `SetInitialSize`')
+ def Raise(*args, **kwargs):
+ """
+ Raise(self)
+
+ Raises the window to the top of the window hierarchy. In current
+ version of wxWidgets this works both for managed and child windows.
+ """
+ return _core_.Window_Raise(*args, **kwargs)
+
+ def Lower(*args, **kwargs):
+ """
+ Lower(self)
+
+ Lowers the window to the bottom of the window hierarchy. In current
+ version of wxWidgets this works both for managed and child windows.
+ """
+ return _core_.Window_Lower(*args, **kwargs)
+
+ def SetClientSize(*args, **kwargs):
+ """
+ SetClientSize(self, Size size)
+
+ This sets the size of the window client area in pixels. Using this
+ function to size a window tends to be more device-independent than
+ wx.Window.SetSize, since the application need not worry about what
+ dimensions the border or title bar have when trying to fit the window
+ around panel items, for example.
+ """
+ return _core_.Window_SetClientSize(*args, **kwargs)
+
+ def SetClientSizeWH(*args, **kwargs):
+ """
+ SetClientSizeWH(self, int width, int height)
+
+ This sets the size of the window client area in pixels. Using this
+ function to size a window tends to be more device-independent than
+ wx.Window.SetSize, since the application need not worry about what
+ dimensions the border or title bar have when trying to fit the window
+ around panel items, for example.
+ """
+ return _core_.Window_SetClientSizeWH(*args, **kwargs)
+
+ def SetClientRect(*args, **kwargs):
+ """
+ SetClientRect(self, Rect rect)
+
+ This sets the size of the window client area in pixels. Using this
+ function to size a window tends to be more device-independent than
+ wx.Window.SetSize, since the application need not worry about what
+ dimensions the border or title bar have when trying to fit the window
+ around panel items, for example.
+ """
+ return _core_.Window_SetClientRect(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """
+ GetPosition(self) -> Point
+
+ Get the window's position. Notice that the position is in client
+ coordinates for child windows and screen coordinates for the top level
+ ones, use `GetScreenPosition` if you need screen coordinates for all
+ kinds of windows.
+ """
+ return _core_.Window_GetPosition(*args, **kwargs)
+
+ def GetPositionTuple(*args, **kwargs):
+ """
+ GetPositionTuple() -> (x,y)
+
+ Get the window's position. Notice that the position is in client
+ coordinates for child windows and screen coordinates for the top level
+ ones, use `GetScreenPosition` if you need screen coordinates for all
+ kinds of windows.
+ """
+ return _core_.Window_GetPositionTuple(*args, **kwargs)
+
+ def GetScreenPosition(*args, **kwargs):
+ """
+ GetScreenPosition(self) -> Point
+
+ Get the position of the window in screen coordinantes.
+ """
+ return _core_.Window_GetScreenPosition(*args, **kwargs)
+
+ def GetScreenPositionTuple(*args, **kwargs):
+ """
+ GetScreenPositionTuple() -> (x,y)
+
+ Get the position of the window in screen coordinantes.
+ """
+ return _core_.Window_GetScreenPositionTuple(*args, **kwargs)
+
+ def GetScreenRect(*args, **kwargs):
+ """
+ GetScreenRect(self) -> Rect
+
+ Returns the size and position of the window in screen coordinantes as
+ a `wx.Rect` object.
+ """
+ return _core_.Window_GetScreenRect(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """
+ GetSize(self) -> Size
+
+ Get the window size.
+ """
+ return _core_.Window_GetSize(*args, **kwargs)
+
+ def GetSizeTuple(*args, **kwargs):
+ """
+ GetSizeTuple() -> (width, height)
+
+ Get the window size.
+ """
+ return _core_.Window_GetSizeTuple(*args, **kwargs)
+
+ def GetRect(*args, **kwargs):
+ """
+ GetRect(self) -> Rect
+
+ Returns the size and position of the window as a `wx.Rect` object.
+ """
+ return _core_.Window_GetRect(*args, **kwargs)
+
+ def GetClientSize(*args, **kwargs):
+ """
+ GetClientSize(self) -> Size
+
+ This gets the size of the window's 'client area' in pixels. The client
+ area is the area which may be drawn on by the programmer, excluding
+ title bar, border, scrollbars, etc.
+ """
+ return _core_.Window_GetClientSize(*args, **kwargs)
+
+ def GetClientSizeTuple(*args, **kwargs):
+ """
+ GetClientSizeTuple() -> (width, height)
+
+ This gets the size of the window's 'client area' in pixels. The client
+ area is the area which may be drawn on by the programmer, excluding
+ title bar, border, scrollbars, etc.
+ """
+ return _core_.Window_GetClientSizeTuple(*args, **kwargs)
+
+ def GetClientAreaOrigin(*args, **kwargs):
+ """
+ GetClientAreaOrigin(self) -> Point
+
+ Get the origin of the client area of the window relative to the
+ window's top left corner (the client area may be shifted because of
+ the borders, scrollbars, other decorations...)
+ """
+ return _core_.Window_GetClientAreaOrigin(*args, **kwargs)
+
+ def GetClientRect(*args, **kwargs):
+ """
+ GetClientRect(self) -> Rect
+
+ Get the client area position and size as a `wx.Rect` object.
+ """
+ return _core_.Window_GetClientRect(*args, **kwargs)
+
+ def ClientToWindowSize(*args, **kwargs):
+ """
+ ClientToWindowSize(self, Size size) -> Size
+
+ Converts client area size ``size to corresponding window size. In
+ other words, the returned value is what `GetSize` would return if this
+ window had client area of given size. Components with
+ ``wx.DefaultCoord`` (-1) value are left unchanged.
+
+ Note that the conversion is not always exact, it assumes that
+ non-client area doesn't change and so doesn't take into account things
+ like menu bar (un)wrapping or (dis)appearance of the scrollbars.
+ """
+ return _core_.Window_ClientToWindowSize(*args, **kwargs)
+
+ def WindowToClientSize(*args, **kwargs):
+ """
+ WindowToClientSize(self, Size size) -> Size
+
+ Converts window size ``size`` to corresponding client area size. In
+ other words, the returned value is what `GetClientSize` would return
+ if this window had given window size. Components with
+ ``wxDefaultCoord`` (-1) value are left unchanged.
+
+ Note that the conversion is not always exact, it assumes that
+ non-client area doesn't change and so doesn't take into account things
+ like menu bar (un)wrapping or (dis)appearance of the scrollbars.
+ """
+ return _core_.Window_WindowToClientSize(*args, **kwargs)
+
+ def GetBestSize(*args, **kwargs):
+ """
+ GetBestSize(self) -> Size
+
+ This function returns the best acceptable minimal size for the
+ window, if applicable. For example, for a static text control, it will
+ be the minimal size such that the control label is not truncated. For
+ windows containing subwindows (such as wx.Panel), the size returned by
+ this function will be the same as the size the window would have had
+ after calling Fit.
+ """
+ return _core_.Window_GetBestSize(*args, **kwargs)
+
+ def GetBestSizeTuple(*args, **kwargs):
+ """
+ GetBestSizeTuple() -> (width, height)
+
+ This function returns the best acceptable minimal size for the
+ window, if applicable. For example, for a static text control, it will
+ be the minimal size such that the control label is not truncated. For
+ windows containing subwindows (such as wx.Panel), the size returned by
+ this function will be the same as the size the window would have had
+ after calling Fit.
+ """
+ return _core_.Window_GetBestSizeTuple(*args, **kwargs)
+
+ def InvalidateBestSize(*args, **kwargs):
+ """
+ InvalidateBestSize(self)
+
+ Reset the cached best size value so it will be recalculated the next
+ time it is needed.
+ """
+ return _core_.Window_InvalidateBestSize(*args, **kwargs)
+
+ def CacheBestSize(*args, **kwargs):
+ """
+ CacheBestSize(self, Size size)
+
+ Cache the best size so it doesn't need to be calculated again, (at least until
+ some properties of the window change.)
+ """
+ return _core_.Window_CacheBestSize(*args, **kwargs)
+
+ def GetEffectiveMinSize(*args, **kwargs):
+ """
+ GetEffectiveMinSize(self) -> Size
+
+ This function will merge the window's best size into the window's
+ minimum size, giving priority to the min size components, and returns
+ the results.
+
+ """
+ return _core_.Window_GetEffectiveMinSize(*args, **kwargs)
+
+ GetBestFittingSize = wx.deprecated(GetEffectiveMinSize, 'Use `GetEffectiveMinSize` instead.')
+ def GetAdjustedBestSize(self):
+ s = self.GetBestSize()
+ return wx.Size(max(s.width, self.GetMinWidth()),
+ max(s.height, self.GetMinHeight()))
+ GetAdjustedBestSize = wx.deprecated(GetAdjustedBestSize, 'Use `GetEffectiveMinSize` instead.')
+
+ def Center(*args, **kwargs):
+ """
+ Center(self, int direction=BOTH)
+
+ Centers the window. The parameter specifies the direction for
+ centering, and may be wx.HORIZONTAL, wx.VERTICAL or wx.BOTH. It may
+ also include wx.CENTER_ON_SCREEN flag if you want to center the window
+ on the entire screen and not on its parent window. If it is a
+ top-level window and has no parent then it will always be centered
+ relative to the screen.
+ """
+ return _core_.Window_Center(*args, **kwargs)
+
+ Centre = Center
+ def CenterOnParent(*args, **kwargs):
+ """
+ CenterOnParent(self, int dir=BOTH)
+
+ Center with respect to the the parent window
+ """
+ return _core_.Window_CenterOnParent(*args, **kwargs)
+
+ CentreOnParent = CenterOnParent
+ def Fit(*args, **kwargs):
+ """
+ Fit(self)
+
+ Sizes the window so that it fits around its subwindows. This function
+ won't do anything if there are no subwindows and will only really work
+ correctly if sizers are used for the subwindows layout. Also, if the
+ window has exactly one subwindow it is better (faster and the result
+ is more precise as Fit adds some margin to account for fuzziness of
+ its calculations) to call window.SetClientSize(child.GetSize())
+ instead of calling Fit.
+ """
+ return _core_.Window_Fit(*args, **kwargs)
+
+ def FitInside(*args, **kwargs):
+ """
+ FitInside(self)
+
+ Similar to Fit, but sizes the interior (virtual) size of a
+ window. Mainly useful with scrolled windows to reset scrollbars after
+ sizing changes that do not trigger a size event, and/or scrolled
+ windows without an interior sizer. This function similarly won't do
+ anything if there are no subwindows.
+ """
+ return _core_.Window_FitInside(*args, **kwargs)
+
+ def SetSizeHints(*args, **kwargs):
+ """
+ SetSizeHints(self, int minW, int minH, int maxW=-1, int maxH=-1, int incW=-1,
+ int incH=-1)
+
+ Allows specification of minimum and maximum window sizes, and window
+ size increments. If a pair of values is not set (or set to -1), the
+ default values will be used. If this function is called, the user
+ will not be able to size the window outside the given bounds (if it is
+ a top-level window.) Sizers will also inspect the minimum window size
+ and will use that value if set when calculating layout.
+
+ The resizing increments are only significant under Motif or Xt.
+ """
+ return _core_.Window_SetSizeHints(*args, **kwargs)
+
+ def SetSizeHintsSz(*args, **kwargs):
+ """
+ SetSizeHintsSz(self, Size minSize, Size maxSize=DefaultSize, Size incSize=DefaultSize)
+
+ Allows specification of minimum and maximum window sizes, and window
+ size increments. If a pair of values is not set (or set to -1), the
+ default values will be used. If this function is called, the user
+ will not be able to size the window outside the given bounds (if it is
+ a top-level window.) Sizers will also inspect the minimum window size
+ and will use that value if set when calculating layout.
+
+ The resizing increments are only significant under Motif or Xt.
+ """
+ return _core_.Window_SetSizeHintsSz(*args, **kwargs)
+
+ def SetVirtualSizeHints(*args, **kwargs):
+ """SetVirtualSizeHints(self, int minW, int minH, int maxW=-1, int maxH=-1)"""
+ return _core_.Window_SetVirtualSizeHints(*args, **kwargs)
+
+ def SetVirtualSizeHintsSz(*args, **kwargs):
+ """SetVirtualSizeHintsSz(self, Size minSize, Size maxSize=DefaultSize)"""
+ return _core_.Window_SetVirtualSizeHintsSz(*args, **kwargs)
+
+ SetVirtualSizeHints = wx.deprecated(SetVirtualSizeHints)
+ SetVirtualSizeHintsSz = wx.deprecated(SetVirtualSizeHintsSz)
+
+ def GetMaxSize(*args, **kwargs):
+ """GetMaxSize(self) -> Size"""
+ return _core_.Window_GetMaxSize(*args, **kwargs)
+
+ def GetMinSize(*args, **kwargs):
+ """GetMinSize(self) -> Size"""
+ return _core_.Window_GetMinSize(*args, **kwargs)
+
+ def SetMinSize(*args, **kwargs):
+ """
+ SetMinSize(self, Size minSize)
+
+ A more convenient method than `SetSizeHints` for setting just the
+ min size.
+ """
+ return _core_.Window_SetMinSize(*args, **kwargs)
+
+ def SetMaxSize(*args, **kwargs):
+ """
+ SetMaxSize(self, Size maxSize)
+
+ A more convenient method than `SetSizeHints` for setting just the
+ max size.
+ """
+ return _core_.Window_SetMaxSize(*args, **kwargs)
+
+ def GetMinWidth(*args, **kwargs):
+ """GetMinWidth(self) -> int"""
+ return _core_.Window_GetMinWidth(*args, **kwargs)
+
+ def GetMinHeight(*args, **kwargs):
+ """GetMinHeight(self) -> int"""
+ return _core_.Window_GetMinHeight(*args, **kwargs)
+
+ def GetMaxWidth(*args, **kwargs):
+ """GetMaxWidth(self) -> int"""
+ return _core_.Window_GetMaxWidth(*args, **kwargs)
+
+ def GetMaxHeight(*args, **kwargs):
+ """GetMaxHeight(self) -> int"""
+ return _core_.Window_GetMaxHeight(*args, **kwargs)
+
+ def SetMinClientSize(*args, **kwargs):
+ """SetMinClientSize(self, Size size)"""
+ return _core_.Window_SetMinClientSize(*args, **kwargs)
+
+ def SetMaxClientSize(*args, **kwargs):
+ """SetMaxClientSize(self, Size size)"""
+ return _core_.Window_SetMaxClientSize(*args, **kwargs)
+
+ def GetMinClientSize(*args, **kwargs):
+ """GetMinClientSize(self) -> Size"""
+ return _core_.Window_GetMinClientSize(*args, **kwargs)
+
+ def GetMaxClientSize(*args, **kwargs):
+ """GetMaxClientSize(self) -> Size"""
+ return _core_.Window_GetMaxClientSize(*args, **kwargs)
+
+ def SetVirtualSize(*args, **kwargs):
+ """
+ SetVirtualSize(self, Size size)
+
+ Set the the virtual size of a window in pixels. For most windows this
+ is just the client area of the window, but for some like scrolled
+ windows it is more or less independent of the screen window size.
+ """
+ return _core_.Window_SetVirtualSize(*args, **kwargs)
+
+ def SetVirtualSizeWH(*args, **kwargs):
+ """
+ SetVirtualSizeWH(self, int w, int h)
+
+ Set the the virtual size of a window in pixels. For most windows this
+ is just the client area of the window, but for some like scrolled
+ windows it is more or less independent of the screen window size.
+ """
+ return _core_.Window_SetVirtualSizeWH(*args, **kwargs)
+
+ def GetVirtualSize(*args, **kwargs):
+ """
+ GetVirtualSize(self) -> Size
+
+ Get the the virtual size of the window in pixels. For most windows
+ this is just the client area of the window, but for some like scrolled
+ windows it is more or less independent of the screen window size.
+ """
+ return _core_.Window_GetVirtualSize(*args, **kwargs)
+
+ def GetVirtualSizeTuple(*args, **kwargs):
+ """
+ GetVirtualSizeTuple() -> (width, height)
+
+ Get the the virtual size of the window in pixels. For most windows
+ this is just the client area of the window, but for some like scrolled
+ windows it is more or less independent of the screen window size.
+ """
+ return _core_.Window_GetVirtualSizeTuple(*args, **kwargs)
+
+ def GetWindowBorderSize(*args, **kwargs):
+ """
+ GetWindowBorderSize(self) -> Size
+
+ Return the size of the left/right and top/bottom borders.
+ """
+ return _core_.Window_GetWindowBorderSize(*args, **kwargs)
+
+ def GetBestVirtualSize(*args, **kwargs):
+ """
+ GetBestVirtualSize(self) -> Size
+
+ Return the largest of ClientSize and BestSize (as determined by a
+ sizer, interior children, or other means)
+ """
+ return _core_.Window_GetBestVirtualSize(*args, **kwargs)
+
+ def InformFirstDirection(*args, **kwargs):
+ """
+ InformFirstDirection(self, int direction, int size, int availableOtherDir) -> bool
+
+ wxSizer and friends use this to give a chance to a component to recalc
+ its min size once one of the final size components is known. Override
+ this function when that is useful (such as for wxStaticText which can
+ stretch over several lines). Parameter availableOtherDir
+ tells the item how much more space there is available in the opposite
+ direction (-1 if unknown).
+ """
+ return _core_.Window_InformFirstDirection(*args, **kwargs)
+
+ def SendSizeEvent(*args, **kwargs):
+ """
+ SendSizeEvent(self, int flags=0)
+
+ Sends a size event to the window using its current size -- this has an
+ effect of refreshing the window layout.
+
+ By default the event is sent, i.e. processed immediately, but if flags
+ value includes wxSEND_EVENT_POST then it's posted, i.e. only schedule
+ for later processing.
+ """
+ return _core_.Window_SendSizeEvent(*args, **kwargs)
+
+ def SendSizeEventToParent(*args, **kwargs):
+ """
+ SendSizeEventToParent(self, int flags=0)
+
+ This is a safe wrapper for GetParent().SendSizeEvent(): it checks that
+ we have a parent window and it's not in process of being deleted.
+ """
+ return _core_.Window_SendSizeEventToParent(*args, **kwargs)
+
+ def PostSizeEvent(*args, **kwargs):
+ """
+ PostSizeEvent(self)
+
+ This is a more readable synonym for SendSizeEvent(wx.SEND_EVENT_POST)
+ """
+ return _core_.Window_PostSizeEvent(*args, **kwargs)
+
+ def PostSizeEventToParent(*args, **kwargs):
+ """
+ PostSizeEventToParent(self)
+
+ This is the same as SendSizeEventToParent() but using PostSizeEvent()
+ """
+ return _core_.Window_PostSizeEventToParent(*args, **kwargs)
+
+ def Show(*args, **kwargs):
+ """
+ Show(self, bool show=True) -> bool
+
+ Shows or hides the window. You may need to call Raise for a top level
+ window if you want to bring it to top, although this is not needed if
+ Show is called immediately after the frame creation. Returns True if
+ the window has been shown or hidden or False if nothing was done
+ because it already was in the requested state.
+ """
+ return _core_.Window_Show(*args, **kwargs)
+
+ def Hide(*args, **kwargs):
+ """
+ Hide(self) -> bool
+
+ Equivalent to calling Show(False).
+ """
+ return _core_.Window_Hide(*args, **kwargs)
+
+ def ShowWithEffect(*args, **kwargs):
+ """
+ ShowWithEffect(self, int effect, unsigned int timeout=0) -> bool
+
+ Show the window with a special effect, not implemented on most
+ platforms (where it is the same as Show())
+
+ Timeout specifies how long the animation should take, in ms, the
+ default value of 0 means to use the default (system-dependent) value.
+
+ """
+ return _core_.Window_ShowWithEffect(*args, **kwargs)
+
+ def HideWithEffect(*args, **kwargs):
+ """
+ HideWithEffect(self, int effect, unsigned int timeout=0) -> bool
+
+ Hide the window with a special effect, not implemented on most
+ platforms (where it is the same as Hide())
+
+ Timeout specifies how long the animation should take, in ms, the
+ default value of 0 means to use the default (system-dependent) value.
+
+ """
+ return _core_.Window_HideWithEffect(*args, **kwargs)
+
+ def Enable(*args, **kwargs):
+ """
+ Enable(self, bool enable=True) -> bool
+
+ Enable or disable the window for user input. Note that when a parent
+ window is disabled, all of its children are disabled as well and they
+ are reenabled again when the parent is. Returns true if the window
+ has been enabled or disabled, false if nothing was done, i.e. if the
+ window had already been in the specified state.
+ """
+ return _core_.Window_Enable(*args, **kwargs)
+
+ def Disable(*args, **kwargs):
+ """
+ Disable(self) -> bool
+
+ Disables the window, same as Enable(false).
+ """
+ return _core_.Window_Disable(*args, **kwargs)
+
+ def IsShown(*args, **kwargs):
+ """
+ IsShown(self) -> bool
+
+ Returns true if the window is shown, false if it has been hidden.
+ """
+ return _core_.Window_IsShown(*args, **kwargs)
+
+ def IsEnabled(*args, **kwargs):
+ """
+ IsEnabled(self) -> bool
+
+ Returns true if the window is enabled for input, false otherwise.
+ This method takes into account the enabled state of parent windows up
+ to the top-level window.
+ """
+ return _core_.Window_IsEnabled(*args, **kwargs)
+
+ def IsThisEnabled(*args, **kwargs):
+ """
+ IsThisEnabled(self) -> bool
+
+ Returns the internal enabled state independent of the parent(s) state,
+ i.e. the state in which the window would be if all of its parents are
+ enabled. Use `IsEnabled` to get the effective window state.
+ """
+ return _core_.Window_IsThisEnabled(*args, **kwargs)
+
+ def IsShownOnScreen(*args, **kwargs):
+ """
+ IsShownOnScreen(self) -> bool
+
+ Returns ``True`` if the window is physically visible on the screen,
+ i.e. it is shown and all its parents up to the toplevel window are
+ shown as well.
+ """
+ return _core_.Window_IsShownOnScreen(*args, **kwargs)
+
+ def SetWindowStyleFlag(*args, **kwargs):
+ """
+ SetWindowStyleFlag(self, long style)
+
+ Sets the style of the window. Please note that some styles cannot be
+ changed after the window creation and that Refresh() might need to be
+ called after changing the others for the change to take place
+ immediately.
+ """
+ return _core_.Window_SetWindowStyleFlag(*args, **kwargs)
+
+ def GetWindowStyleFlag(*args, **kwargs):
+ """
+ GetWindowStyleFlag(self) -> long
+
+ Gets the window style that was passed to the constructor or Create
+ method.
+ """
+ return _core_.Window_GetWindowStyleFlag(*args, **kwargs)
+
+ SetWindowStyle = SetWindowStyleFlag; GetWindowStyle = GetWindowStyleFlag
+ def HasFlag(*args, **kwargs):
+ """
+ HasFlag(self, int flag) -> bool
+
+ Test if the given style is set for this window.
+ """
+ return _core_.Window_HasFlag(*args, **kwargs)
+
+ def IsRetained(*args, **kwargs):
+ """
+ IsRetained(self) -> bool
+
+ Returns true if the window is retained, false otherwise. Retained
+ windows are only available on X platforms.
+ """
+ return _core_.Window_IsRetained(*args, **kwargs)
+
+ def ToggleWindowStyle(*args, **kwargs):
+ """
+ ToggleWindowStyle(self, int flag) -> bool
+
+ Turn the flag on if it had been turned off before and vice versa,
+ returns True if the flag is turned on by this function call.
+ """
+ return _core_.Window_ToggleWindowStyle(*args, **kwargs)
+
+ def SetExtraStyle(*args, **kwargs):
+ """
+ SetExtraStyle(self, long exStyle)
+
+ Sets the extra style bits for the window. Extra styles are the less
+ often used style bits which can't be set with the constructor or with
+ SetWindowStyleFlag()
+ """
+ return _core_.Window_SetExtraStyle(*args, **kwargs)
+
+ def GetExtraStyle(*args, **kwargs):
+ """
+ GetExtraStyle(self) -> long
+
+ Returns the extra style bits for the window.
+ """
+ return _core_.Window_GetExtraStyle(*args, **kwargs)
+
+ def HasExtraStyle(*args, **kwargs):
+ """
+ HasExtraStyle(self, int exFlag) -> bool
+
+ Returns ``True`` if the given extra flag is set.
+ """
+ return _core_.Window_HasExtraStyle(*args, **kwargs)
+
+ def MakeModal(*args, **kwargs):
+ """
+ MakeModal(self, bool modal=True)
+
+ Disables all other windows in the application so that the user can
+ only interact with this window. Passing False will reverse this
+ effect.
+ """
+ return _core_.Window_MakeModal(*args, **kwargs)
+
+ def SetThemeEnabled(*args, **kwargs):
+ """
+ SetThemeEnabled(self, bool enableTheme)
+
+ This function tells a window if it should use the system's "theme"
+ code to draw the windows' background instead if its own background
+ drawing code. This will only have an effect on platforms that support
+ the notion of themes in user defined windows. One such platform is
+ GTK+ where windows can have (very colourful) backgrounds defined by a
+ user's selected theme.
+
+ Dialogs, notebook pages and the status bar have this flag set to true
+ by default so that the default look and feel is simulated best.
+ """
+ return _core_.Window_SetThemeEnabled(*args, **kwargs)
+
+ def GetThemeEnabled(*args, **kwargs):
+ """
+ GetThemeEnabled(self) -> bool
+
+ Return the themeEnabled flag.
+ """
+ return _core_.Window_GetThemeEnabled(*args, **kwargs)
+
+ def SetFocus(*args, **kwargs):
+ """
+ SetFocus(self)
+
+ Set's the focus to this window, allowing it to receive keyboard input.
+ """
+ return _core_.Window_SetFocus(*args, **kwargs)
+
+ def SetFocusFromKbd(*args, **kwargs):
+ """
+ SetFocusFromKbd(self)
+
+ Set focus to this window as the result of a keyboard action. Normally
+ only called internally.
+ """
+ return _core_.Window_SetFocusFromKbd(*args, **kwargs)
+
+ def FindFocus(*args, **kwargs):
+ """
+ FindFocus() -> Window
+
+ Returns the window or control that currently has the keyboard focus,
+ or None.
+ """
+ return _core_.Window_FindFocus(*args, **kwargs)
+
+ FindFocus = staticmethod(FindFocus)
+ def HasFocus(*args, **kwargs):
+ """
+ HasFocus(self) -> bool
+
+ Returns ``True`` if the window has the keyboard focus.
+ """
+ return _core_.Window_HasFocus(*args, **kwargs)
+
+ def AcceptsFocus(*args, **kwargs):
+ """
+ AcceptsFocus(self) -> bool
+
+ Can this window have focus?
+ """
+ return _core_.Window_AcceptsFocus(*args, **kwargs)
+
+ def CanAcceptFocus(*args, **kwargs):
+ """
+ CanAcceptFocus(self) -> bool
+
+ Can this window have focus right now?
+ """
+ return _core_.Window_CanAcceptFocus(*args, **kwargs)
+
+ def AcceptsFocusFromKeyboard(*args, **kwargs):
+ """
+ AcceptsFocusFromKeyboard(self) -> bool
+
+ Can this window be given focus by keyboard navigation? if not, the
+ only way to give it focus (provided it accepts it at all) is to click
+ it.
+ """
+ return _core_.Window_AcceptsFocusFromKeyboard(*args, **kwargs)
+
+ def CanAcceptFocusFromKeyboard(*args, **kwargs):
+ """
+ CanAcceptFocusFromKeyboard(self) -> bool
+
+ Can this window be assigned focus from keyboard right now?
+ """
+ return _core_.Window_CanAcceptFocusFromKeyboard(*args, **kwargs)
+
+ def SetCanFocus(*args, **kwargs):
+ """SetCanFocus(self, bool canFocus)"""
+ return _core_.Window_SetCanFocus(*args, **kwargs)
+
+ def NavigateIn(*args, **kwargs):
+ """
+ NavigateIn(self, int flags=NavigationKeyEvent.IsForward) -> bool
+
+ Navigates inside this window.
+ """
+ return _core_.Window_NavigateIn(*args, **kwargs)
+
+ def Navigate(*args, **kwargs):
+ """
+ Navigate(self, int flags=NavigationKeyEvent.IsForward) -> bool
+
+ Does keyboard navigation starting from this window to another. This is
+ equivalient to self.GetParent().NavigateIn().
+ """
+ return _core_.Window_Navigate(*args, **kwargs)
+
+ def HandleAsNavigationKey(*args, **kwargs):
+ """
+ HandleAsNavigationKey(self, KeyEvent event) -> bool
+
+ This function will generate the appropriate call to `Navigate` if the
+ key event is one normally used for keyboard navigation. Returns
+ ``True`` if the key pressed was for navigation and was handled,
+ ``False`` otherwise.
+ """
+ return _core_.Window_HandleAsNavigationKey(*args, **kwargs)
+
+ def MoveAfterInTabOrder(*args, **kwargs):
+ """
+ MoveAfterInTabOrder(self, Window win)
+
+ Moves this window in the tab navigation order after the specified
+ sibling window. This means that when the user presses the TAB key on
+ that other window, the focus switches to this window.
+
+ The default tab order is the same as creation order. This function
+ and `MoveBeforeInTabOrder` allow to change it after creating all the
+ windows.
+ """
+ return _core_.Window_MoveAfterInTabOrder(*args, **kwargs)
+
+ def MoveBeforeInTabOrder(*args, **kwargs):
+ """
+ MoveBeforeInTabOrder(self, Window win)
+
+ Same as `MoveAfterInTabOrder` except that it inserts this window just
+ before win instead of putting it right after it.
+ """
+ return _core_.Window_MoveBeforeInTabOrder(*args, **kwargs)
+
+ def GetChildren(*args, **kwargs):
+ """
+ GetChildren(self) -> WindowList
+
+ Returns an object containing a list of the window's children. The
+ object provides a Python sequence-like interface over the internal
+ list maintained by the window..
+ """
+ return _core_.Window_GetChildren(*args, **kwargs)
+
+ def GetPrevSibling(*args, **kwargs):
+ """GetPrevSibling(self) -> Window"""
+ return _core_.Window_GetPrevSibling(*args, **kwargs)
+
+ def GetNextSibling(*args, **kwargs):
+ """GetNextSibling(self) -> Window"""
+ return _core_.Window_GetNextSibling(*args, **kwargs)
+
+ def GetParent(*args, **kwargs):
+ """
+ GetParent(self) -> Window
+
+ Returns the parent window of this window, or None if there isn't one.
+ """
+ return _core_.Window_GetParent(*args, **kwargs)
+
+ def GetGrandParent(*args, **kwargs):
+ """
+ GetGrandParent(self) -> Window
+
+ Returns the parent of the parent of this window, or None if there
+ isn't one.
+ """
+ return _core_.Window_GetGrandParent(*args, **kwargs)
+
+ def GetTopLevelParent(*args, **kwargs):
+ """
+ GetTopLevelParent(self) -> Window
+
+ Returns the first frame or dialog in this window's parental hierarchy.
+ """
+ return _core_.Window_GetTopLevelParent(*args, **kwargs)
+
+ def IsTopLevel(*args, **kwargs):
+ """
+ IsTopLevel(self) -> bool
+
+ Returns true if the given window is a top-level one. Currently all
+ frames and dialogs are always considered to be top-level windows (even
+ if they have a parent window).
+ """
+ return _core_.Window_IsTopLevel(*args, **kwargs)
+
+ def Reparent(*args, **kwargs):
+ """
+ Reparent(self, Window newParent) -> bool
+
+ Reparents the window, i.e the window will be removed from its current
+ parent window (e.g. a non-standard toolbar in a wxFrame) and then
+ re-inserted into another. Available on Windows and GTK. Returns True
+ if the parent was changed, False otherwise (error or newParent ==
+ oldParent)
+ """
+ return _core_.Window_Reparent(*args, **kwargs)
+
+ def AddChild(*args, **kwargs):
+ """
+ AddChild(self, Window child)
+
+ Adds a child window. This is called automatically by window creation
+ functions so should not be required by the application programmer.
+ """
+ return _core_.Window_AddChild(*args, **kwargs)
+
+ def RemoveChild(*args, **kwargs):
+ """
+ RemoveChild(self, Window child)
+
+ Removes a child window. This is called automatically by window
+ deletion functions so should not be required by the application
+ programmer.
+ """
+ return _core_.Window_RemoveChild(*args, **kwargs)
+
+ def FindWindowById(*args, **kwargs):
+ """
+ FindWindowById(self, long winid) -> Window
+
+ Find a child of this window by window ID
+ """
+ return _core_.Window_FindWindowById(*args, **kwargs)
+
+ def FindWindowByName(*args, **kwargs):
+ """
+ FindWindowByName(self, String name) -> Window
+
+ Find a child of this window by name
+ """
+ return _core_.Window_FindWindowByName(*args, **kwargs)
+
+ def FindWindowByLabel(*args, **kwargs):
+ """
+ FindWindowByLabel(self, String label) -> Window
+
+ Find a child of this window by label
+ """
+ return _core_.Window_FindWindowByLabel(*args, **kwargs)
+
+ def GetEventHandler(*args, **kwargs):
+ """
+ GetEventHandler(self) -> EvtHandler
+
+ Returns the event handler for this window. By default, the window is
+ its own event handler.
+ """
+ return _core_.Window_GetEventHandler(*args, **kwargs)
+
+ def SetEventHandler(*args, **kwargs):
+ """
+ SetEventHandler(self, EvtHandler handler)
+
+ Sets the event handler for this window. An event handler is an object
+ that is capable of processing the events sent to a window. (In other
+ words, is able to dispatch the events to handler function.) By
+ default, the window is its own event handler, but an application may
+ wish to substitute another, for example to allow central
+ implementation of event-handling for a variety of different window
+ classes.
+
+ It is usually better to use `wx.Window.PushEventHandler` since this sets
+ up a chain of event handlers, where an event not handled by one event
+ handler is handed off to the next one in the chain.
+ """
+ return _core_.Window_SetEventHandler(*args, **kwargs)
+
+ def PushEventHandler(*args, **kwargs):
+ """
+ PushEventHandler(self, EvtHandler handler)
+
+ Pushes this event handler onto the event handler stack for the window.
+ An event handler is an object that is capable of processing the events
+ sent to a window. (In other words, is able to dispatch the events to a
+ handler function.) By default, the window is its own event handler,
+ but an application may wish to substitute another, for example to
+ allow central implementation of event-handling for a variety of
+ different window classes.
+
+ wx.Window.PushEventHandler allows an application to set up a chain of
+ event handlers, where an event not handled by one event handler is
+ handed to the next one in the chain. Use `wx.Window.PopEventHandler`
+ to remove the event handler. Ownership of the handler is *not* given
+ to the window, so you should be sure to pop the handler before the
+ window is destroyed and either let PopEventHandler destroy it, or call
+ its Destroy method yourself.
+ """
+ return _core_.Window_PushEventHandler(*args, **kwargs)
+
+ def PopEventHandler(*args, **kwargs):
+ """
+ PopEventHandler(self, bool deleteHandler=False) -> EvtHandler
+
+ Removes and returns the top-most event handler on the event handler
+ stack. If deleteHandler is True then the wx.EvtHandler object will be
+ destroyed after it is popped, and ``None`` will be returned instead.
+ """
+ return _core_.Window_PopEventHandler(*args, **kwargs)
+
+ def RemoveEventHandler(*args, **kwargs):
+ """
+ RemoveEventHandler(self, EvtHandler handler) -> bool
+
+ Find the given handler in the event handler chain and remove (but not
+ delete) it from the event handler chain, returns True if it was found
+ and False otherwise (this also results in an assert failure so this
+ function should only be called when the handler is supposed to be
+ there.)
+ """
+ return _core_.Window_RemoveEventHandler(*args, **kwargs)
+
+ def ProcessWindowEvent(*args, **kwargs):
+ """
+ ProcessWindowEvent(self, Event event) -> bool
+
+ Process an event by calling GetEventHandler().ProcessEvent(): this
+ is a straightforward replacement for ProcessEvent() itself which
+ shouldn't be used directly with windows as it doesn't take into
+ account any event handlers associated with the window
+ """
+ return _core_.Window_ProcessWindowEvent(*args, **kwargs)
+
+ def HandleWindowEvent(*args, **kwargs):
+ """
+ HandleWindowEvent(self, Event event) -> bool
+
+ Process an event by calling GetEventHandler()->ProcessEvent() and
+ handling any exceptions thrown by event handlers. It's mostly useful
+ when processing wx events when called from C code (e.g. in GTK+
+ callback) when the exception wouldn't correctly propagate to
+ wx.EventLoop.
+ """
+ return _core_.Window_HandleWindowEvent(*args, **kwargs)
+
+ def SetValidator(*args, **kwargs):
+ """
+ SetValidator(self, Validator validator)
+
+ Deletes the current validator (if any) and sets the window validator,
+ having called wx.Validator.Clone to create a new validator of this
+ type.
+ """
+ return _core_.Window_SetValidator(*args, **kwargs)
+
+ def GetValidator(*args, **kwargs):
+ """
+ GetValidator(self) -> Validator
+
+ Returns a pointer to the current validator for the window, or None if
+ there is none.
+ """
+ return _core_.Window_GetValidator(*args, **kwargs)
+
+ def Validate(*args, **kwargs):
+ """
+ Validate(self) -> bool
+
+ Validates the current values of the child controls using their
+ validators. If the window has wx.WS_EX_VALIDATE_RECURSIVELY extra
+ style flag set, the method will also call Validate() of all child
+ windows. Returns false if any of the validations failed.
+ """
+ return _core_.Window_Validate(*args, **kwargs)
+
+ def TransferDataToWindow(*args, **kwargs):
+ """
+ TransferDataToWindow(self) -> bool
+
+ Transfers values to child controls from data areas specified by their
+ validators. If the window has wx.WS_EX_VALIDATE_RECURSIVELY extra
+ style flag set, the method will also call TransferDataToWindow() of
+ all child windows.
+ """
+ return _core_.Window_TransferDataToWindow(*args, **kwargs)
+
+ def TransferDataFromWindow(*args, **kwargs):
+ """
+ TransferDataFromWindow(self) -> bool
+
+ Transfers values from child controls to data areas specified by their
+ validators. Returns false if a transfer failed. If the window has
+ wx.WS_EX_VALIDATE_RECURSIVELY extra style flag set, the method will
+ also call TransferDataFromWindow() of all child windows.
+ """
+ return _core_.Window_TransferDataFromWindow(*args, **kwargs)
+
+ def InitDialog(*args, **kwargs):
+ """
+ InitDialog(self)
+
+ Sends an EVT_INIT_DIALOG event, whose handler usually transfers data
+ to the dialog via validators.
+ """
+ return _core_.Window_InitDialog(*args, **kwargs)
+
+ def SetAcceleratorTable(*args, **kwargs):
+ """
+ SetAcceleratorTable(self, AcceleratorTable accel)
+
+ Sets the accelerator table for this window.
+ """
+ return _core_.Window_SetAcceleratorTable(*args, **kwargs)
+
+ def GetAcceleratorTable(*args, **kwargs):
+ """
+ GetAcceleratorTable(self) -> AcceleratorTable
+
+ Gets the accelerator table for this window.
+ """
+ return _core_.Window_GetAcceleratorTable(*args, **kwargs)
+
+ def RegisterHotKey(*args, **kwargs):
+ """
+ RegisterHotKey(self, int hotkeyId, int modifiers, int keycode) -> bool
+
+ Registers a system wide hotkey. Every time the user presses the hotkey
+ registered here, this window will receive a hotkey event. It will
+ receive the event even if the application is in the background and
+ does not have the input focus because the user is working with some
+ other application. To bind an event handler function to this hotkey
+ use EVT_HOTKEY with an id equal to hotkeyId. Returns True if the
+ hotkey was registered successfully.
+ """
+ return _core_.Window_RegisterHotKey(*args, **kwargs)
+
+ def UnregisterHotKey(*args, **kwargs):
+ """
+ UnregisterHotKey(self, int hotkeyId) -> bool
+
+ Unregisters a system wide hotkey.
+ """
+ return _core_.Window_UnregisterHotKey(*args, **kwargs)
+
+ def ConvertDialogPointToPixels(*args, **kwargs):
+ """
+ ConvertDialogPointToPixels(self, Point pt) -> Point
+
+ Converts a point or size from dialog units to pixels. Dialog units
+ are used for maintaining a dialog's proportions even if the font
+ changes. For the x dimension, the dialog units are multiplied by the
+ average character width and then divided by 4. For the y dimension,
+ the dialog units are multiplied by the average character height and
+ then divided by 8.
+ """
+ return _core_.Window_ConvertDialogPointToPixels(*args, **kwargs)
+
+ def ConvertDialogSizeToPixels(*args, **kwargs):
+ """
+ ConvertDialogSizeToPixels(self, Size sz) -> Size
+
+ Converts a point or size from dialog units to pixels. Dialog units
+ are used for maintaining a dialog's proportions even if the font
+ changes. For the x dimension, the dialog units are multiplied by the
+ average character width and then divided by 4. For the y dimension,
+ the dialog units are multiplied by the average character height and
+ then divided by 8.
+ """
+ return _core_.Window_ConvertDialogSizeToPixels(*args, **kwargs)
+
+ def DLG_PNT(*args, **kwargs):
+ """
+ DLG_PNT(self, Point pt) -> Point
+
+ Converts a point or size from dialog units to pixels. Dialog units
+ are used for maintaining a dialog's proportions even if the font
+ changes. For the x dimension, the dialog units are multiplied by the
+ average character width and then divided by 4. For the y dimension,
+ the dialog units are multiplied by the average character height and
+ then divided by 8.
+ """
+ return _core_.Window_DLG_PNT(*args, **kwargs)
+
+ def DLG_SZE(*args, **kwargs):
+ """
+ DLG_SZE(self, Size sz) -> Size
+
+ Converts a point or size from dialog units to pixels. Dialog units
+ are used for maintaining a dialog's proportions even if the font
+ changes. For the x dimension, the dialog units are multiplied by the
+ average character width and then divided by 4. For the y dimension,
+ the dialog units are multiplied by the average character height and
+ then divided by 8.
+ """
+ return _core_.Window_DLG_SZE(*args, **kwargs)
+
+ def ConvertPixelPointToDialog(*args, **kwargs):
+ """ConvertPixelPointToDialog(self, Point pt) -> Point"""
+ return _core_.Window_ConvertPixelPointToDialog(*args, **kwargs)
+
+ def ConvertPixelSizeToDialog(*args, **kwargs):
+ """ConvertPixelSizeToDialog(self, Size sz) -> Size"""
+ return _core_.Window_ConvertPixelSizeToDialog(*args, **kwargs)
+
+ def WarpPointer(*args, **kwargs):
+ """
+ WarpPointer(self, int x, int y)
+
+ Moves the pointer to the given position on the window.
+
+ NOTE: This function is not supported under Mac because Apple Human
+ Interface Guidelines forbid moving the mouse cursor programmatically.
+ """
+ return _core_.Window_WarpPointer(*args, **kwargs)
+
+ def CaptureMouse(*args, **kwargs):
+ """
+ CaptureMouse(self)
+
+ Directs all mouse input to this window. Call wx.Window.ReleaseMouse to
+ release the capture.
+
+ Note that wxWindows maintains the stack of windows having captured the
+ mouse and when the mouse is released the capture returns to the window
+ which had had captured it previously and it is only really released if
+ there were no previous window. In particular, this means that you must
+ release the mouse as many times as you capture it, unless the window
+ receives the `wx.MouseCaptureLostEvent` event.
+
+ Any application which captures the mouse in the beginning of some
+ operation *must* handle `wx.MouseCaptureLostEvent` and cancel this
+ operation when it receives the event. The event handler must not
+ recapture mouse.
+ """
+ return _core_.Window_CaptureMouse(*args, **kwargs)
+
+ def ReleaseMouse(*args, **kwargs):
+ """
+ ReleaseMouse(self)
+
+ Releases mouse input captured with wx.Window.CaptureMouse.
+ """
+ return _core_.Window_ReleaseMouse(*args, **kwargs)
+
+ def GetCapture(*args, **kwargs):
+ """
+ GetCapture() -> Window
+
+ Returns the window which currently captures the mouse or None
+ """
+ return _core_.Window_GetCapture(*args, **kwargs)
+
+ GetCapture = staticmethod(GetCapture)
+ def HasCapture(*args, **kwargs):
+ """
+ HasCapture(self) -> bool
+
+ Returns true if this window has the current mouse capture.
+ """
+ return _core_.Window_HasCapture(*args, **kwargs)
+
+ def Refresh(*args, **kwargs):
+ """
+ Refresh(self, bool eraseBackground=True, Rect rect=None)
+
+ Mark the specified rectangle (or the whole window) as "dirty" so it
+ will be repainted. Causes an EVT_PAINT event to be generated and sent
+ to the window.
+ """
+ return _core_.Window_Refresh(*args, **kwargs)
+
+ def RefreshRect(*args, **kwargs):
+ """
+ RefreshRect(self, Rect rect, bool eraseBackground=True)
+
+ Redraws the contents of the given rectangle: the area inside it will
+ be repainted. This is the same as Refresh but has a nicer syntax.
+ """
+ return _core_.Window_RefreshRect(*args, **kwargs)
+
+ def Update(*args, **kwargs):
+ """
+ Update(self)
+
+ Calling this method immediately repaints the invalidated area of the
+ window instead of waiting for the EVT_PAINT event to happen, (normally
+ this would usually only happen when the flow of control returns to the
+ event loop.) Notice that this function doesn't refresh the window and
+ does nothing if the window has been already repainted. Use `Refresh`
+ first if you want to immediately redraw the window (or some portion of
+ it) unconditionally.
+ """
+ return _core_.Window_Update(*args, **kwargs)
+
+ def ClearBackground(*args, **kwargs):
+ """
+ ClearBackground(self)
+
+ Clears the window by filling it with the current background
+ colour. Does not cause an erase background event to be generated.
+ """
+ return _core_.Window_ClearBackground(*args, **kwargs)
+
+ def Freeze(*args, **kwargs):
+ """
+ Freeze(self)
+
+ Freezes the window or, in other words, prevents any updates from
+ taking place on screen, the window is not redrawn at all. Thaw must be
+ called to reenable window redrawing. Calls to Freeze/Thaw may be
+ nested, with the actual Thaw being delayed until all the nesting has
+ been undone.
+
+ This method is useful for visual appearance optimization (for example,
+ it is a good idea to use it before inserting large amount of text into
+ a wxTextCtrl under wxGTK) but is not implemented on all platforms nor
+ for all controls so it is mostly just a hint to wxWindows and not a
+ mandatory directive.
+ """
+ return _core_.Window_Freeze(*args, **kwargs)
+
+ def IsFrozen(*args, **kwargs):
+ """
+ IsFrozen(self) -> bool
+
+ Returns ``True`` if the window has been frozen and not thawed yet.
+
+ :see: `Freeze` and `Thaw`
+ """
+ return _core_.Window_IsFrozen(*args, **kwargs)
+
+ def Thaw(*args, **kwargs):
+ """
+ Thaw(self)
+
+ Reenables window updating after a previous call to Freeze. Calls to
+ Freeze/Thaw may be nested, so Thaw must be called the same number of
+ times that Freeze was before the window will be updated.
+ """
+ return _core_.Window_Thaw(*args, **kwargs)
+
+ def IsDoubleBuffered(*args, **kwargs):
+ """
+ IsDoubleBuffered(self) -> bool
+
+ Returns ``True`` if the window contents is double-buffered by the
+ system, i.e. if any drawing done on the window is really done on a
+ temporary backing surface and transferred to the screen all at once
+ later.
+ """
+ return _core_.Window_IsDoubleBuffered(*args, **kwargs)
+
+ def SetDoubleBuffered(*args, **kwargs):
+ """
+ SetDoubleBuffered(self, bool on)
+
+ Put the native window into double buffered or composited mode.
+ """
+ return _core_.Window_SetDoubleBuffered(*args, **kwargs)
+
+ def GetUpdateRegion(*args, **kwargs):
+ """
+ GetUpdateRegion(self) -> Region
+
+ Returns the region specifying which parts of the window have been
+ damaged. Should only be called within an EVT_PAINT handler.
+ """
+ return _core_.Window_GetUpdateRegion(*args, **kwargs)
+
+ def GetUpdateClientRect(*args, **kwargs):
+ """
+ GetUpdateClientRect(self) -> Rect
+
+ Get the update rectangle region bounding box in client coords.
+ """
+ return _core_.Window_GetUpdateClientRect(*args, **kwargs)
+
+ def IsExposed(*args, **kwargs):
+ """
+ IsExposed(self, int x, int y, int w=1, int h=1) -> bool
+
+ Returns true if the given point or rectangle area has been exposed
+ since the last repaint. Call this in an paint event handler to
+ optimize redrawing by only redrawing those areas, which have been
+ exposed.
+ """
+ return _core_.Window_IsExposed(*args, **kwargs)
+
+ def IsExposedPoint(*args, **kwargs):
+ """
+ IsExposedPoint(self, Point pt) -> bool
+
+ Returns true if the given point or rectangle area has been exposed
+ since the last repaint. Call this in an paint event handler to
+ optimize redrawing by only redrawing those areas, which have been
+ exposed.
+ """
+ return _core_.Window_IsExposedPoint(*args, **kwargs)
+
+ def IsExposedRect(*args, **kwargs):
+ """
+ IsExposedRect(self, Rect rect) -> bool
+
+ Returns true if the given point or rectangle area has been exposed
+ since the last repaint. Call this in an paint event handler to
+ optimize redrawing by only redrawing those areas, which have been
+ exposed.
+ """
+ return _core_.Window_IsExposedRect(*args, **kwargs)
+
+ def GetDefaultAttributes(*args, **kwargs):
+ """
+ GetDefaultAttributes(self) -> VisualAttributes
+
+ Get the default attributes for an instance of this class. This is
+ useful if you want to use the same font or colour in your own control
+ as in a standard control -- which is a much better idea than hard
+ coding specific colours or fonts which might look completely out of
+ place on the user's system, especially if it uses themes.
+ """
+ return _core_.Window_GetDefaultAttributes(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _core_.Window_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ def SetBackgroundColour(*args, **kwargs):
+ """
+ SetBackgroundColour(self, Colour colour) -> bool
+
+ Sets the background colour of the window. Returns True if the colour
+ was changed. The background colour is usually painted by the default
+ EVT_ERASE_BACKGROUND event handler function under Windows and
+ automatically under GTK. Using `wx.NullColour` will reset the window
+ to the default background colour.
+
+ Note that setting the background colour may not cause an immediate
+ refresh, so you may wish to call `ClearBackground` or `Refresh` after
+ calling this function.
+
+ Using this function will disable attempts to use themes for this
+ window, if the system supports them. Use with care since usually the
+ themes represent the appearance chosen by the user to be used for all
+ applications on the system.
+ """
+ return _core_.Window_SetBackgroundColour(*args, **kwargs)
+
+ def SetOwnBackgroundColour(*args, **kwargs):
+ """SetOwnBackgroundColour(self, Colour colour)"""
+ return _core_.Window_SetOwnBackgroundColour(*args, **kwargs)
+
+ def SetForegroundColour(*args, **kwargs):
+ """
+ SetForegroundColour(self, Colour colour) -> bool
+
+ Sets the foreground colour of the window. Returns True is the colour
+ was changed. The interpretation of foreground colour is dependent on
+ the window class; it may be the text colour or other colour, or it may
+ not be used at all.
+ """
+ return _core_.Window_SetForegroundColour(*args, **kwargs)
+
+ def SetOwnForegroundColour(*args, **kwargs):
+ """SetOwnForegroundColour(self, Colour colour)"""
+ return _core_.Window_SetOwnForegroundColour(*args, **kwargs)
+
+ def GetBackgroundColour(*args, **kwargs):
+ """
+ GetBackgroundColour(self) -> Colour
+
+ Returns the background colour of the window.
+ """
+ return _core_.Window_GetBackgroundColour(*args, **kwargs)
+
+ def GetForegroundColour(*args, **kwargs):
+ """
+ GetForegroundColour(self) -> Colour
+
+ Returns the foreground colour of the window. The interpretation of
+ foreground colour is dependent on the window class; it may be the text
+ colour or other colour, or it may not be used at all.
+ """
+ return _core_.Window_GetForegroundColour(*args, **kwargs)
+
+ def InheritsBackgroundColour(*args, **kwargs):
+ """InheritsBackgroundColour(self) -> bool"""
+ return _core_.Window_InheritsBackgroundColour(*args, **kwargs)
+
+ def UseBgCol(*args, **kwargs):
+ """UseBgCol(self) -> bool"""
+ return _core_.Window_UseBgCol(*args, **kwargs)
+
+ def SetBackgroundStyle(*args, **kwargs):
+ """
+ SetBackgroundStyle(self, int style) -> bool
+
+ Returns the background style of the window. The background style
+ indicates how the background of the window is drawn.
+
+ ====================== ========================================
+ wx.BG_STYLE_SYSTEM The background colour or pattern should
+ be determined by the system
+ wx.BG_STYLE_COLOUR The background should be a solid colour
+ wx.BG_STYLE_CUSTOM The background will be implemented by the
+ application.
+ ====================== ========================================
+
+ On GTK+, use of wx.BG_STYLE_CUSTOM allows the flicker-free drawing of
+ a custom background, such as a tiled bitmap. Currently the style has
+ no effect on other platforms.
+
+ :see: `GetBackgroundStyle`, `SetBackgroundColour`
+ """
+ return _core_.Window_SetBackgroundStyle(*args, **kwargs)
+
+ def GetBackgroundStyle(*args, **kwargs):
+ """
+ GetBackgroundStyle(self) -> int
+
+ Returns the background style of the window.
+
+ :see: `SetBackgroundStyle`
+ """
+ return _core_.Window_GetBackgroundStyle(*args, **kwargs)
+
+ def HasTransparentBackground(*args, **kwargs):
+ """
+ HasTransparentBackground(self) -> bool
+
+ Returns True if this window's background is transparent (as, for
+ example, for `wx.StaticText`) and should show the parent window's
+ background.
+
+ This method is mostly used internally by the library itself and you
+ normally shouldn't have to call it. You may, however, have to override
+ it in your custom control classes to ensure that background is painted
+ correctly.
+ """
+ return _core_.Window_HasTransparentBackground(*args, **kwargs)
+
+ def SetCursor(*args, **kwargs):
+ """
+ SetCursor(self, Cursor cursor) -> bool
+
+ Sets the window's cursor. Notice that the window cursor also sets it
+ for the children of the window implicitly.
+
+ The cursor may be wx.NullCursor in which case the window cursor will
+ be reset back to default.
+ """
+ return _core_.Window_SetCursor(*args, **kwargs)
+
+ def GetCursor(*args, **kwargs):
+ """
+ GetCursor(self) -> Cursor
+
+ Return the cursor associated with this window.
+ """
+ return _core_.Window_GetCursor(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """
+ SetFont(self, Font font) -> bool
+
+ Sets the font for this window.
+ """
+ return _core_.Window_SetFont(*args, **kwargs)
+
+ def SetOwnFont(*args, **kwargs):
+ """SetOwnFont(self, Font font)"""
+ return _core_.Window_SetOwnFont(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """
+ GetFont(self) -> Font
+
+ Returns the default font used for this window.
+ """
+ return _core_.Window_GetFont(*args, **kwargs)
+
+ def SetCaret(*args, **kwargs):
+ """
+ SetCaret(self, Caret caret)
+
+ Sets the caret associated with the window.
+ """
+ return _core_.Window_SetCaret(*args, **kwargs)
+
+ def GetCaret(*args, **kwargs):
+ """
+ GetCaret(self) -> Caret
+
+ Returns the caret associated with the window.
+ """
+ return _core_.Window_GetCaret(*args, **kwargs)
+
+ def GetCharHeight(*args, **kwargs):
+ """
+ GetCharHeight(self) -> int
+
+ Get the (average) character size for the current font.
+ """
+ return _core_.Window_GetCharHeight(*args, **kwargs)
+
+ def GetCharWidth(*args, **kwargs):
+ """
+ GetCharWidth(self) -> int
+
+ Get the (average) character size for the current font.
+ """
+ return _core_.Window_GetCharWidth(*args, **kwargs)
+
+ def GetTextExtent(*args, **kwargs):
+ """
+ GetTextExtent(String string) -> (width, height)
+
+ Get the width and height of the text using the current font.
+ """
+ return _core_.Window_GetTextExtent(*args, **kwargs)
+
+ def GetFullTextExtent(*args, **kwargs):
+ """
+ GetFullTextExtent(String string, Font font=None) ->
+ (width, height, descent, externalLeading)
+
+ Get the width, height, decent and leading of the text using the
+ current or specified font.
+ """
+ return _core_.Window_GetFullTextExtent(*args, **kwargs)
+
+ def ClientToScreenXY(*args, **kwargs):
+ """
+ ClientToScreenXY(int x, int y) -> (x,y)
+
+ Converts to screen coordinates from coordinates relative to this window.
+ """
+ return _core_.Window_ClientToScreenXY(*args, **kwargs)
+
+ def ScreenToClientXY(*args, **kwargs):
+ """
+ ScreenToClientXY(int x, int y) -> (x,y)
+
+ Converts from screen to client window coordinates.
+ """
+ return _core_.Window_ScreenToClientXY(*args, **kwargs)
+
+ def ClientToScreen(*args, **kwargs):
+ """
+ ClientToScreen(self, Point pt) -> Point
+
+ Converts to screen coordinates from coordinates relative to this window.
+ """
+ return _core_.Window_ClientToScreen(*args, **kwargs)
+
+ def ScreenToClient(*args, **kwargs):
+ """
+ ScreenToClient(self, Point pt) -> Point
+
+ Converts from screen to client window coordinates.
+ """
+ return _core_.Window_ScreenToClient(*args, **kwargs)
+
+ def HitTestXY(*args, **kwargs):
+ """
+ HitTestXY(self, int x, int y) -> int
+
+ Test where the given (in client coords) point lies
+ """
+ return _core_.Window_HitTestXY(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(self, Point pt) -> int
+
+ Test where the given (in client coords) point lies
+ """
+ return _core_.Window_HitTest(*args, **kwargs)
+
+ def GetBorder(*args):
+ """
+ GetBorder(self, long flags) -> int
+ GetBorder(self) -> int
+
+ Get border for the flags of this window
+ """
+ return _core_.Window_GetBorder(*args)
+
+ def UpdateWindowUI(*args, **kwargs):
+ """
+ UpdateWindowUI(self, long flags=UPDATE_UI_NONE)
+
+ This function sends EVT_UPDATE_UI events to the window. The particular
+ implementation depends on the window; for example a wx.ToolBar will
+ send an update UI event for each toolbar button, and a wx.Frame will
+ send an update UI event for each menubar menu item. You can call this
+ function from your application to ensure that your UI is up-to-date at
+ a particular point in time (as far as your EVT_UPDATE_UI handlers are
+ concerned). This may be necessary if you have called
+ `wx.UpdateUIEvent.SetMode` or `wx.UpdateUIEvent.SetUpdateInterval` to
+ limit the overhead that wxWindows incurs by sending update UI events
+ in idle time.
+ """
+ return _core_.Window_UpdateWindowUI(*args, **kwargs)
+
+ def PopupMenuXY(*args, **kwargs):
+ """
+ PopupMenuXY(self, Menu menu, int x=-1, int y=-1) -> bool
+
+ Pops up the given menu at the specified coordinates, relative to this window,
+ and returns control when the user has dismissed the menu. If a menu item is
+ selected, the corresponding menu event is generated and will be processed as
+ usual. If the default position is given then the current position of the
+ mouse cursor will be used.
+ """
+ return _core_.Window_PopupMenuXY(*args, **kwargs)
+
+ def PopupMenu(*args, **kwargs):
+ """
+ PopupMenu(self, Menu menu, Point pos=DefaultPosition) -> bool
+
+ Pops up the given menu at the specified coordinates, relative to this window,
+ and returns control when the user has dismissed the menu. If a menu item is
+ selected, the corresponding menu event is generated and will be processed as
+ usual. If the default position is given then the current position of the
+ mouse cursor will be used.
+ """
+ return _core_.Window_PopupMenu(*args, **kwargs)
+
+ def GetPopupMenuSelectionFromUser(*args, **kwargs):
+ """
+ GetPopupMenuSelectionFromUser(self, Menu menu, Point pos=DefaultPosition) -> int
+
+ Simply return the id of the selected item or wxID_NONE without
+ generating any events.
+ """
+ return _core_.Window_GetPopupMenuSelectionFromUser(*args, **kwargs)
+
+ def HasMultiplePages(*args, **kwargs):
+ """HasMultiplePages(self) -> bool"""
+ return _core_.Window_HasMultiplePages(*args, **kwargs)
+
+ def SendIdleEvents(*args, **kwargs):
+ """
+ SendIdleEvents(self, IdleEvent event) -> bool
+
+ Send idle event to window and all subwindows. Returns True if more
+ idle time is requested.
+ """
+ return _core_.Window_SendIdleEvents(*args, **kwargs)
+
+ def GetHandle(*args, **kwargs):
+ """
+ GetHandle(self) -> long
+
+ Returns the platform-specific handle (as a long integer) of the
+ physical window. On wxMSW this is the win32 window handle, on wxGTK
+ it is the XWindow ID, and on wxMac it is the ControlRef.
+ """
+ return _core_.Window_GetHandle(*args, **kwargs)
+
+ def AssociateHandle(*args, **kwargs):
+ """
+ AssociateHandle(self, long handle)
+
+ Associate the window with a new native handle
+ """
+ return _core_.Window_AssociateHandle(*args, **kwargs)
+
+ def DissociateHandle(*args, **kwargs):
+ """
+ DissociateHandle(self)
+
+ Dissociate the current native handle from the window
+ """
+ return _core_.Window_DissociateHandle(*args, **kwargs)
+
+ def GetGtkWidget(*args, **kwargs):
+ """
+ GetGtkWidget(self) -> long
+
+ On wxGTK returns a pointer to the GtkWidget for this window as a long
+ integer. On the other platforms this method returns zero.
+ """
+ return _core_.Window_GetGtkWidget(*args, **kwargs)
+
+ def OnPaint(*args, **kwargs):
+ """OnPaint(self, PaintEvent event)"""
+ return _core_.Window_OnPaint(*args, **kwargs)
+
+ def CanScroll(*args, **kwargs):
+ """
+ CanScroll(self, int orient) -> bool
+
+ Can the window have the scrollbar in this orientation?
+ """
+ return _core_.Window_CanScroll(*args, **kwargs)
+
+ def HasScrollbar(*args, **kwargs):
+ """
+ HasScrollbar(self, int orient) -> bool
+
+ Does the window have the scrollbar for this orientation?
+ """
+ return _core_.Window_HasScrollbar(*args, **kwargs)
+
+ def SetScrollbar(*args, **kwargs):
+ """
+ SetScrollbar(self, int orientation, int position, int thumbSize, int range,
+ bool refresh=True)
+
+ Sets the scrollbar properties of a built-in scrollbar.
+ """
+ return _core_.Window_SetScrollbar(*args, **kwargs)
+
+ def SetScrollPos(*args, **kwargs):
+ """
+ SetScrollPos(self, int orientation, int pos, bool refresh=True)
+
+ Sets the position of one of the built-in scrollbars.
+ """
+ return _core_.Window_SetScrollPos(*args, **kwargs)
+
+ def GetScrollPos(*args, **kwargs):
+ """
+ GetScrollPos(self, int orientation) -> int
+
+ Returns the built-in scrollbar position.
+ """
+ return _core_.Window_GetScrollPos(*args, **kwargs)
+
+ def GetScrollThumb(*args, **kwargs):
+ """
+ GetScrollThumb(self, int orientation) -> int
+
+ Returns the built-in scrollbar thumb size.
+ """
+ return _core_.Window_GetScrollThumb(*args, **kwargs)
+
+ def GetScrollRange(*args, **kwargs):
+ """
+ GetScrollRange(self, int orientation) -> int
+
+ Returns the built-in scrollbar range.
+ """
+ return _core_.Window_GetScrollRange(*args, **kwargs)
+
+ def ScrollWindow(*args, **kwargs):
+ """
+ ScrollWindow(self, int dx, int dy, Rect rect=None)
+
+ Physically scrolls the pixels in the window and move child windows
+ accordingly. Use this function to optimise your scrolling
+ implementations, to minimise the area that must be redrawn. Note that
+ it is rarely required to call this function from a user program.
+ """
+ return _core_.Window_ScrollWindow(*args, **kwargs)
+
+ def ScrollLines(*args, **kwargs):
+ """
+ ScrollLines(self, int lines) -> bool
+
+ If the platform and window class supports it, scrolls the window by
+ the given number of lines down, if lines is positive, or up if lines
+ is negative. Returns True if the window was scrolled, False if it was
+ already on top/bottom and nothing was done.
+ """
+ return _core_.Window_ScrollLines(*args, **kwargs)
+
+ def ScrollPages(*args, **kwargs):
+ """
+ ScrollPages(self, int pages) -> bool
+
+ If the platform and window class supports it, scrolls the window by
+ the given number of pages down, if pages is positive, or up if pages
+ is negative. Returns True if the window was scrolled, False if it was
+ already on top/bottom and nothing was done.
+ """
+ return _core_.Window_ScrollPages(*args, **kwargs)
+
+ def LineUp(*args, **kwargs):
+ """
+ LineUp(self) -> bool
+
+ This is just a wrapper for ScrollLines(-1).
+ """
+ return _core_.Window_LineUp(*args, **kwargs)
+
+ def LineDown(*args, **kwargs):
+ """
+ LineDown(self) -> bool
+
+ This is just a wrapper for ScrollLines(1).
+ """
+ return _core_.Window_LineDown(*args, **kwargs)
+
+ def PageUp(*args, **kwargs):
+ """
+ PageUp(self) -> bool
+
+ This is just a wrapper for ScrollPages(-1).
+ """
+ return _core_.Window_PageUp(*args, **kwargs)
+
+ def PageDown(*args, **kwargs):
+ """
+ PageDown(self) -> bool
+
+ This is just a wrapper for ScrollPages(1).
+ """
+ return _core_.Window_PageDown(*args, **kwargs)
+
+ def AlwaysShowScrollbars(*args, **kwargs):
+ """AlwaysShowScrollbars(self, bool horz=True, bool vert=True)"""
+ return _core_.Window_AlwaysShowScrollbars(*args, **kwargs)
+
+ def IsScrollbarAlwaysShown(*args, **kwargs):
+ """IsScrollbarAlwaysShown(self, int orient) -> bool"""
+ return _core_.Window_IsScrollbarAlwaysShown(*args, **kwargs)
+
+ def SetHelpText(*args, **kwargs):
+ """
+ SetHelpText(self, String text)
+
+ Sets the help text to be used as context-sensitive help for this
+ window. Note that the text is actually stored by the current
+ `wx.HelpProvider` implementation, and not in the window object itself.
+ """
+ return _core_.Window_SetHelpText(*args, **kwargs)
+
+ def SetHelpTextForId(*args, **kwargs):
+ """
+ SetHelpTextForId(self, String text)
+
+ Associate this help text with all windows with the same id as this
+ one.
+ """
+ return _core_.Window_SetHelpTextForId(*args, **kwargs)
+
+ SetHelpTextForId = wx.deprecated(SetHelpTextForId,
+ 'Use wx.HelpProvider.Get().AddHelp(id, text)')
+ def GetHelpTextAtPoint(*args, **kwargs):
+ """
+ GetHelpTextAtPoint(self, Point pt, wxHelpEvent::Origin origin) -> String
+
+ Get the help string associated with the given position in this window.
+
+ Notice that pt may be invalid if event origin is keyboard or unknown
+ and this method should return the global window help text then
+
+ """
+ return _core_.Window_GetHelpTextAtPoint(*args, **kwargs)
+
+ def GetHelpText(*args, **kwargs):
+ """
+ GetHelpText(self) -> String
+
+ Gets the help text to be used as context-sensitive help for this
+ window. Note that the text is actually stored by the current
+ `wx.HelpProvider` implementation, and not in the window object itself.
+ """
+ return _core_.Window_GetHelpText(*args, **kwargs)
+
+ def SetToolTipString(*args, **kwargs):
+ """
+ SetToolTipString(self, String tip)
+
+ Attach a tooltip to the window.
+ """
+ return _core_.Window_SetToolTipString(*args, **kwargs)
+
+ def SetToolTip(*args, **kwargs):
+ """
+ SetToolTip(self, ToolTip tip)
+
+ Attach a tooltip to the window.
+ """
+ return _core_.Window_SetToolTip(*args, **kwargs)
+
+ def UnsetToolTip(*args, **kwargs):
+ """UnsetToolTip(self)"""
+ return _core_.Window_UnsetToolTip(*args, **kwargs)
+
+ def GetToolTip(*args, **kwargs):
+ """
+ GetToolTip(self) -> ToolTip
+
+ get the associated tooltip or None if none
+ """
+ return _core_.Window_GetToolTip(*args, **kwargs)
+
+ def GetToolTipString(self):
+ tip = self.GetToolTip()
+ if tip:
+ return tip.GetTip()
+ else:
+ return None
+
+ ToolTipString = property(GetToolTipString, SetToolTipString)
+
+ def SetDropTarget(*args, **kwargs):
+ """
+ SetDropTarget(self, DropTarget dropTarget)
+
+ Associates a drop target with this window. If the window already has
+ a drop target, it is deleted.
+ """
+ return _core_.Window_SetDropTarget(*args, **kwargs)
+
+ def GetDropTarget(*args, **kwargs):
+ """
+ GetDropTarget(self) -> DropTarget
+
+ Returns the associated drop target, which may be None.
+ """
+ return _core_.Window_GetDropTarget(*args, **kwargs)
+
+ def DragAcceptFiles(*args, **kwargs):
+ """
+ DragAcceptFiles(self, bool accept)
+
+ Enables or disables eligibility for drop file events, EVT_DROP_FILES.
+ """
+ return _core_.Window_DragAcceptFiles(*args, **kwargs)
+
+ def SetConstraints(*args, **kwargs):
+ """
+ SetConstraints(self, LayoutConstraints constraints)
+
+ Sets the window to have the given layout constraints. If an existing
+ layout constraints object is already owned by the window, it will be
+ deleted. Pass None to disassociate and delete the window's current
+ constraints.
+
+ You must call SetAutoLayout to tell a window to use the constraints
+ automatically in its default EVT_SIZE handler; otherwise, you must
+ handle EVT_SIZE yourself and call Layout() explicitly. When setting
+ both a wx.LayoutConstraints and a wx.Sizer, only the sizer will have
+ effect.
+ """
+ return _core_.Window_SetConstraints(*args, **kwargs)
+
+ def GetConstraints(*args, **kwargs):
+ """
+ GetConstraints(self) -> LayoutConstraints
+
+ Returns a pointer to the window's layout constraints, or None if there
+ are none.
+ """
+ return _core_.Window_GetConstraints(*args, **kwargs)
+
+ def SetAutoLayout(*args, **kwargs):
+ """
+ SetAutoLayout(self, bool autoLayout)
+
+ Determines whether the Layout function will be called automatically
+ when the window is resized. lease note that this only happens for the
+ windows usually used to contain children, namely `wx.Panel` and
+ `wx.TopLevelWindow` (and the classes deriving from them).
+
+ This method is called implicitly by `SetSizer` but if you use
+ `SetConstraints` you should call it manually or otherwise the window
+ layout won't be correctly updated when its size changes.
+ """
+ return _core_.Window_SetAutoLayout(*args, **kwargs)
+
+ def GetAutoLayout(*args, **kwargs):
+ """
+ GetAutoLayout(self) -> bool
+
+ Returns the current autoLayout setting
+ """
+ return _core_.Window_GetAutoLayout(*args, **kwargs)
+
+ def Layout(*args, **kwargs):
+ """
+ Layout(self) -> bool
+
+ Invokes the constraint-based layout algorithm or the sizer-based
+ algorithm for this window. See SetAutoLayout: when auto layout is on,
+ this function gets called automatically by the default EVT_SIZE
+ handler when the window is resized.
+ """
+ return _core_.Window_Layout(*args, **kwargs)
+
+ def SetSizer(*args, **kwargs):
+ """
+ SetSizer(self, Sizer sizer, bool deleteOld=True)
+
+ Sets the window to have the given layout sizer. The window will then
+ own the object, and will take care of its deletion. If an existing
+ layout sizer object is already owned by the window, it will be deleted
+ if the deleteOld parameter is true. Note that this function will also
+ call SetAutoLayout implicitly with a True parameter if the sizer is
+ non-None, and False otherwise.
+ """
+ return _core_.Window_SetSizer(*args, **kwargs)
+
+ def SetSizerAndFit(*args, **kwargs):
+ """
+ SetSizerAndFit(self, Sizer sizer, bool deleteOld=True)
+
+ The same as SetSizer, except it also sets the size hints for the
+ window based on the sizer's minimum size.
+ """
+ return _core_.Window_SetSizerAndFit(*args, **kwargs)
+
+ def GetSizer(*args, **kwargs):
+ """
+ GetSizer(self) -> Sizer
+
+ Return the sizer associated with the window by a previous call to
+ SetSizer or None if there isn't one.
+ """
+ return _core_.Window_GetSizer(*args, **kwargs)
+
+ def SetContainingSizer(*args, **kwargs):
+ """
+ SetContainingSizer(self, Sizer sizer)
+
+ This normally does not need to be called by application code. It is
+ called internally when a window is added to a sizer, and is used so
+ the window can remove itself from the sizer when it is destroyed.
+ """
+ return _core_.Window_SetContainingSizer(*args, **kwargs)
+
+ def GetContainingSizer(*args, **kwargs):
+ """
+ GetContainingSizer(self) -> Sizer
+
+ Return the sizer that this window is a member of, if any, otherwise None.
+ """
+ return _core_.Window_GetContainingSizer(*args, **kwargs)
+
+ def InheritAttributes(*args, **kwargs):
+ """
+ InheritAttributes(self)
+
+ This function is (or should be, in case of custom controls) called
+ during window creation to intelligently set up the window visual
+ attributes, that is the font and the foreground and background
+ colours.
+
+ By 'intelligently' the following is meant: by default, all windows use
+ their own default attributes. However if some of the parent's
+ attributes are explicitly changed (that is, using SetFont and not
+ SetOwnFont) and if the corresponding attribute hadn't been
+ explicitly set for this window itself, then this window takes the same
+ value as used by the parent. In addition, if the window overrides
+ ShouldInheritColours to return false, the colours will not be changed
+ no matter what and only the font might.
+
+ This rather complicated logic is necessary in order to accommodate the
+ different usage scenarios. The most common one is when all default
+ attributes are used and in this case, nothing should be inherited as
+ in modern GUIs different controls use different fonts (and colours)
+ than their siblings so they can't inherit the same value from the
+ parent. However it was also deemed desirable to allow to simply change
+ the attributes of all children at once by just changing the font or
+ colour of their common parent, hence in this case we do inherit the
+ parents attributes.
+
+ """
+ return _core_.Window_InheritAttributes(*args, **kwargs)
+
+ def ShouldInheritColours(*args, **kwargs):
+ """
+ ShouldInheritColours(self) -> bool
+
+ Return true from here to allow the colours of this window to be
+ changed by InheritAttributes, returning false forbids inheriting them
+ from the parent window.
+
+ The base class version returns false, but this method is overridden in
+ wxControl where it returns true.
+ """
+ return _core_.Window_ShouldInheritColours(*args, **kwargs)
+
+ def CanBeOutsideClientArea(*args, **kwargs):
+ """CanBeOutsideClientArea(self) -> bool"""
+ return _core_.Window_CanBeOutsideClientArea(*args, **kwargs)
+
+ def CanApplyThemeBorder(*args, **kwargs):
+ """CanApplyThemeBorder(self) -> bool"""
+ return _core_.Window_CanApplyThemeBorder(*args, **kwargs)
+
+ def GetMainWindowOfCompositeControl(*args, **kwargs):
+ """GetMainWindowOfCompositeControl(self) -> Window"""
+ return _core_.Window_GetMainWindowOfCompositeControl(*args, **kwargs)
+
+ def CanSetTransparent(*args, **kwargs):
+ """
+ CanSetTransparent(self) -> bool
+
+ Returns ``True`` if the platform supports setting the transparency for
+ this window. Note that this method will err on the side of caution,
+ so it is possible that this will return ``False`` when it is in fact
+ possible to set the transparency.
+
+ NOTE: On X-windows systems the X server must have the composite
+ extension loaded, and there must be a composite manager program (such
+ as xcompmgr) running.
+ """
+ return _core_.Window_CanSetTransparent(*args, **kwargs)
+
+ def SetTransparent(*args, **kwargs):
+ """
+ SetTransparent(self, byte alpha) -> bool
+
+ Attempt to set the transparency of this window to the ``alpha`` value,
+ returns True on success. The ``alpha`` value is an integer in the
+ range of 0 to 255, where 0 is fully transparent and 255 is fully
+ opaque.
+ """
+ return _core_.Window_SetTransparent(*args, **kwargs)
+
+ def PostCreate(self, pre):
+ """
+ Phase 3 of the 2-phase create <wink!>
+ Call this method after precreating the window with the 2-phase create method.
+ """
+ self.this = pre.this
+ self.thisown = pre.thisown
+ pre.thisown = 0
+ if hasattr(self, '_setOORInfo'):
+ try:
+ self._setOORInfo(self)
+ except TypeError:
+ pass
+ if hasattr(self, '_setCallbackInfo'):
+ try:
+ self._setCallbackInfo(self, pre.__class__)
+ except TypeError:
+ pass
+
+ AcceleratorTable = property(GetAcceleratorTable,SetAcceleratorTable,doc="See `GetAcceleratorTable` and `SetAcceleratorTable`")
+ AutoLayout = property(GetAutoLayout,SetAutoLayout,doc="See `GetAutoLayout` and `SetAutoLayout`")
+ BackgroundColour = property(GetBackgroundColour,SetBackgroundColour,doc="See `GetBackgroundColour` and `SetBackgroundColour`")
+ BackgroundStyle = property(GetBackgroundStyle,SetBackgroundStyle,doc="See `GetBackgroundStyle` and `SetBackgroundStyle`")
+ EffectiveMinSize = property(GetEffectiveMinSize,doc="See `GetEffectiveMinSize`")
+ BestSize = property(GetBestSize,doc="See `GetBestSize`")
+ BestVirtualSize = property(GetBestVirtualSize,doc="See `GetBestVirtualSize`")
+ Border = property(GetBorder,doc="See `GetBorder`")
+ Caret = property(GetCaret,SetCaret,doc="See `GetCaret` and `SetCaret`")
+ CharHeight = property(GetCharHeight,doc="See `GetCharHeight`")
+ CharWidth = property(GetCharWidth,doc="See `GetCharWidth`")
+ Children = property(GetChildren,doc="See `GetChildren`")
+ ClientAreaOrigin = property(GetClientAreaOrigin,doc="See `GetClientAreaOrigin`")
+ ClientRect = property(GetClientRect,SetClientRect,doc="See `GetClientRect` and `SetClientRect`")
+ ClientSize = property(GetClientSize,SetClientSize,doc="See `GetClientSize` and `SetClientSize`")
+ Constraints = property(GetConstraints,SetConstraints,doc="See `GetConstraints` and `SetConstraints`")
+ ContainingSizer = property(GetContainingSizer,SetContainingSizer,doc="See `GetContainingSizer` and `SetContainingSizer`")
+ Cursor = property(GetCursor,SetCursor,doc="See `GetCursor` and `SetCursor`")
+ DefaultAttributes = property(GetDefaultAttributes,doc="See `GetDefaultAttributes`")
+ DropTarget = property(GetDropTarget,SetDropTarget,doc="See `GetDropTarget` and `SetDropTarget`")
+ EventHandler = property(GetEventHandler,SetEventHandler,doc="See `GetEventHandler` and `SetEventHandler`")
+ ExtraStyle = property(GetExtraStyle,SetExtraStyle,doc="See `GetExtraStyle` and `SetExtraStyle`")
+ Font = property(GetFont,SetFont,doc="See `GetFont` and `SetFont`")
+ ForegroundColour = property(GetForegroundColour,SetForegroundColour,doc="See `GetForegroundColour` and `SetForegroundColour`")
+ GrandParent = property(GetGrandParent,doc="See `GetGrandParent`")
+ TopLevelParent = property(GetTopLevelParent,doc="See `GetTopLevelParent`")
+ Handle = property(GetHandle,doc="See `GetHandle`")
+ HelpText = property(GetHelpText,SetHelpText,doc="See `GetHelpText` and `SetHelpText`")
+ Id = property(GetId,SetId,doc="See `GetId` and `SetId`")
+ Label = property(GetLabel,SetLabel,doc="See `GetLabel` and `SetLabel`")
+ LayoutDirection = property(GetLayoutDirection,SetLayoutDirection,doc="See `GetLayoutDirection` and `SetLayoutDirection`")
+ MaxHeight = property(GetMaxHeight,doc="See `GetMaxHeight`")
+ MaxSize = property(GetMaxSize,SetMaxSize,doc="See `GetMaxSize` and `SetMaxSize`")
+ MaxWidth = property(GetMaxWidth,doc="See `GetMaxWidth`")
+ MinHeight = property(GetMinHeight,doc="See `GetMinHeight`")
+ MinSize = property(GetMinSize,SetMinSize,doc="See `GetMinSize` and `SetMinSize`")
+ MinWidth = property(GetMinWidth,doc="See `GetMinWidth`")
+ Name = property(GetName,SetName,doc="See `GetName` and `SetName`")
+ Parent = property(GetParent,doc="See `GetParent`")
+ Position = property(GetPosition,SetPosition,doc="See `GetPosition` and `SetPosition`")
+ Rect = property(GetRect,SetRect,doc="See `GetRect` and `SetRect`")
+ ScreenPosition = property(GetScreenPosition,doc="See `GetScreenPosition`")
+ ScreenRect = property(GetScreenRect,doc="See `GetScreenRect`")
+ Size = property(GetSize,SetSize,doc="See `GetSize` and `SetSize`")
+ Sizer = property(GetSizer,SetSizer,doc="See `GetSizer` and `SetSizer`")
+ ThemeEnabled = property(GetThemeEnabled,SetThemeEnabled,doc="See `GetThemeEnabled` and `SetThemeEnabled`")
+ ToolTip = property(GetToolTip,SetToolTip,doc="See `GetToolTip` and `SetToolTip`")
+ UpdateClientRect = property(GetUpdateClientRect,doc="See `GetUpdateClientRect`")
+ UpdateRegion = property(GetUpdateRegion,doc="See `GetUpdateRegion`")
+ Validator = property(GetValidator,SetValidator,doc="See `GetValidator` and `SetValidator`")
+ VirtualSize = property(GetVirtualSize,SetVirtualSize,doc="See `GetVirtualSize` and `SetVirtualSize`")
+ WindowStyle = property(GetWindowStyle,SetWindowStyle,doc="See `GetWindowStyle` and `SetWindowStyle`")
+ WindowStyleFlag = property(GetWindowStyleFlag,SetWindowStyleFlag,doc="See `GetWindowStyleFlag` and `SetWindowStyleFlag`")
+ WindowVariant = property(GetWindowVariant,SetWindowVariant,doc="See `GetWindowVariant` and `SetWindowVariant`")
+ Shown = property(IsShown,Show,doc="See `IsShown` and `Show`")
+ Enabled = property(IsEnabled,Enable,doc="See `IsEnabled` and `Enable`")
+ TopLevel = property(IsTopLevel,doc="See `IsTopLevel`")
+ GtkWidget = property(GetGtkWidget)
+ MinClientSize = property(GetMinClientSize,SetMinClientSize)
+ MaxClientSize = property(GetMaxClientSize,SetMaxClientSize)
+_core_.Window_swigregister(Window)
+
+def PreWindow(*args, **kwargs):
+ """
+ PreWindow() -> Window
+
+ Precreate a Window for 2-phase creation.
+ """
+ val = _core_.new_PreWindow(*args, **kwargs)
+ return val
+
+def Window_NewControlId(*args, **kwargs):
+ """
+ Window_NewControlId(int count=1) -> int
+
+ Generate a unique id (or count of them consecutively), returns a
+ valid id in the auto-id range or wxID_NONE if failed. If using
+ autoid management, it will mark the id as reserved until it is
+ used (by assigning it to a wxWindowIDRef) or unreserved.
+ """
+ return _core_.Window_NewControlId(*args, **kwargs)
+
+def Window_UnreserveControlId(*args, **kwargs):
+ """
+ Window_UnreserveControlId(int id, int count=1)
+
+ If an ID generated from NewControlId is not assigned to a wxWindowIDRef,
+ it must be unreserved.
+ """
+ return _core_.Window_UnreserveControlId(*args, **kwargs)
+
+def Window_FindFocus(*args):
+ """
+ Window_FindFocus() -> Window
+
+ Returns the window or control that currently has the keyboard focus,
+ or None.
+ """
+ return _core_.Window_FindFocus(*args)
+
+def Window_GetCapture(*args):
+ """
+ Window_GetCapture() -> Window
+
+ Returns the window which currently captures the mouse or None
+ """
+ return _core_.Window_GetCapture(*args)
+
+def Window_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Window_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _core_.Window_GetClassDefaultAttributes(*args, **kwargs)
+
+def DLG_PNT(win, point_or_x, y=None):
+ """
+ Convenience function for converting a Point or (x,y) in
+ dialog units to pixel units.
+ """
+ if y is None:
+ return win.ConvertDialogPointToPixels(point_or_x)
+ else:
+ return win.ConvertDialogPointToPixels(wx.Point(point_or_x, y))
+
+def DLG_SZE(win, size_width, height=None):
+ """
+ Convenience function for converting a Size or (w,h) in
+ dialog units to pixel units.
+ """
+ if height is None:
+ return win.ConvertDialogSizeToPixels(size_width)
+ else:
+ return win.ConvertDialogSizeToPixels(wx.Size(size_width, height))
+
+
+def FindWindowById(*args, **kwargs):
+ """
+ FindWindowById(long id, Window parent=None) -> Window
+
+ Find the first window in the application with the given id. If parent
+ is None, the search will start from all top-level frames and dialog
+ boxes; if non-None, the search will be limited to the given window
+ hierarchy. The search is recursive in both cases.
+ """
+ return _core_.FindWindowById(*args, **kwargs)
+
+def FindWindowByName(*args, **kwargs):
+ """
+ FindWindowByName(String name, Window parent=None) -> Window
+
+ Find a window by its name (as given in a window constructor or Create
+ function call). If parent is None, the search will start from all
+ top-level frames and dialog boxes; if non-None, the search will be
+ limited to the given window hierarchy. The search is recursive in both
+ cases.
+
+ If no window with such name is found, wx.FindWindowByLabel is called.
+ """
+ return _core_.FindWindowByName(*args, **kwargs)
+
+def FindWindowByLabel(*args, **kwargs):
+ """
+ FindWindowByLabel(String label, Window parent=None) -> Window
+
+ Find a window by its label. Depending on the type of window, the label
+ may be a window title or panel item label. If parent is None, the
+ search will start from all top-level frames and dialog boxes; if
+ non-None, the search will be limited to the given window
+ hierarchy. The search is recursive in both cases.
+ """
+ return _core_.FindWindowByLabel(*args, **kwargs)
+
+def Window_FromHWND(*args, **kwargs):
+ """Window_FromHWND(Window parent, unsigned long _hWnd) -> Window"""
+ return _core_.Window_FromHWND(*args, **kwargs)
+
+def GetTopLevelWindows(*args):
+ """
+ GetTopLevelWindows() -> WindowList
+
+ Returns a list-like object of the the application's top-level windows, (frames,
+ dialogs, etc.)
+ """
+ return _core_.GetTopLevelWindows(*args)
+class FrozenWindow(object):
+ """
+ A context manager to be used with Python 'with' statements
+ that will freeze the given window for the duration of the
+ with block.
+ """
+ def __init__(self, window):
+ self._win = window
+ def __enter__(self):
+ self._win.Freeze()
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self._win.Thaw()
+
+#---------------------------------------------------------------------------
+
+class Validator(EvtHandler):
+ """Proxy of C++ Validator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> Validator"""
+ _core_.Validator_swiginit(self,_core_.new_Validator(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Clone(*args, **kwargs):
+ """Clone(self) -> Validator"""
+ return _core_.Validator_Clone(*args, **kwargs)
+
+ def Validate(*args, **kwargs):
+ """Validate(self, Window parent) -> bool"""
+ return _core_.Validator_Validate(*args, **kwargs)
+
+ def TransferToWindow(*args, **kwargs):
+ """TransferToWindow(self) -> bool"""
+ return _core_.Validator_TransferToWindow(*args, **kwargs)
+
+ def TransferFromWindow(*args, **kwargs):
+ """TransferFromWindow(self) -> bool"""
+ return _core_.Validator_TransferFromWindow(*args, **kwargs)
+
+ def GetWindow(*args, **kwargs):
+ """GetWindow(self) -> Window"""
+ return _core_.Validator_GetWindow(*args, **kwargs)
+
+ def SetWindow(*args, **kwargs):
+ """SetWindow(self, Window window)"""
+ return _core_.Validator_SetWindow(*args, **kwargs)
+
+ def IsSilent(*args, **kwargs):
+ """IsSilent() -> bool"""
+ return _core_.Validator_IsSilent(*args, **kwargs)
+
+ IsSilent = staticmethod(IsSilent)
+ def SuppressBellOnError(*args, **kwargs):
+ """SuppressBellOnError(bool suppress=True)"""
+ return _core_.Validator_SuppressBellOnError(*args, **kwargs)
+
+ SuppressBellOnError = staticmethod(SuppressBellOnError)
+ def SetBellOnError(*args, **kwargs):
+ """SetBellOnError(int doIt=True)"""
+ return _core_.Validator_SetBellOnError(*args, **kwargs)
+
+ SetBellOnError = staticmethod(SetBellOnError)
+ Window = property(GetWindow,SetWindow,doc="See `GetWindow` and `SetWindow`")
+_core_.Validator_swigregister(Validator)
+
+def Validator_IsSilent(*args):
+ """Validator_IsSilent() -> bool"""
+ return _core_.Validator_IsSilent(*args)
+
+def Validator_SuppressBellOnError(*args, **kwargs):
+ """Validator_SuppressBellOnError(bool suppress=True)"""
+ return _core_.Validator_SuppressBellOnError(*args, **kwargs)
+
+def Validator_SetBellOnError(*args, **kwargs):
+ """Validator_SetBellOnError(int doIt=True)"""
+ return _core_.Validator_SetBellOnError(*args, **kwargs)
+
+class PyValidator(Validator):
+ """Proxy of C++ PyValidator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyValidator"""
+ _core_.PyValidator_swiginit(self,_core_.new_PyValidator(*args, **kwargs))
+ self._setOORInfo(self);PyValidator._setCallbackInfo(self, self, PyValidator)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class, int incref=1)"""
+ return _core_.PyValidator__setCallbackInfo(*args, **kwargs)
+
+_core_.PyValidator_swigregister(PyValidator)
+
+#---------------------------------------------------------------------------
+
+class MenuItemList_iterator(object):
+ """This class serves as an iterator for a wxMenuItemList object."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_MenuItemList_iterator
+ __del__ = lambda self : None;
+ def next(*args, **kwargs):
+ """next(self) -> MenuItem"""
+ return _core_.MenuItemList_iterator_next(*args, **kwargs)
+
+_core_.MenuItemList_iterator_swigregister(MenuItemList_iterator)
+DefaultValidator = cvar.DefaultValidator
+
+class MenuItemList(object):
+ """
+ This class wraps a wxList-based class and gives it a Python
+ sequence-like interface. Sequence operations supported are length,
+ index access and iteration.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_MenuItemList
+ __del__ = lambda self : None;
+ def __len__(*args, **kwargs):
+ """__len__(self) -> size_t"""
+ return _core_.MenuItemList___len__(*args, **kwargs)
+
+ def __getitem__(*args, **kwargs):
+ """__getitem__(self, size_t index) -> MenuItem"""
+ return _core_.MenuItemList___getitem__(*args, **kwargs)
+
+ def __contains__(*args, **kwargs):
+ """__contains__(self, MenuItem obj) -> bool"""
+ return _core_.MenuItemList___contains__(*args, **kwargs)
+
+ def __iter__(*args, **kwargs):
+ """__iter__(self) -> MenuItemList_iterator"""
+ return _core_.MenuItemList___iter__(*args, **kwargs)
+
+ def index(*args, **kwargs):
+ """index(self, MenuItem obj) -> int"""
+ return _core_.MenuItemList_index(*args, **kwargs)
+
+ def __repr__(self):
+ return "wxMenuItemList: " + repr(list(self))
+
+_core_.MenuItemList_swigregister(MenuItemList)
+
+class Menu(EvtHandler):
+ """Proxy of C++ Menu class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String title=EmptyString, long style=0) -> Menu"""
+ _core_.Menu_swiginit(self,_core_.new_Menu(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Append(*args, **kwargs):
+ """
+ Append(self, int id, String text=EmptyString, String help=EmptyString,
+ int kind=ITEM_NORMAL) -> MenuItem
+ """
+ return _core_.Menu_Append(*args, **kwargs)
+
+ def AppendSeparator(*args, **kwargs):
+ """AppendSeparator(self) -> MenuItem"""
+ return _core_.Menu_AppendSeparator(*args, **kwargs)
+
+ def AppendCheckItem(*args, **kwargs):
+ """AppendCheckItem(self, int id, String text, String help=EmptyString) -> MenuItem"""
+ return _core_.Menu_AppendCheckItem(*args, **kwargs)
+
+ def AppendRadioItem(*args, **kwargs):
+ """AppendRadioItem(self, int id, String text, String help=EmptyString) -> MenuItem"""
+ return _core_.Menu_AppendRadioItem(*args, **kwargs)
+
+ def AppendMenu(*args, **kwargs):
+ """AppendMenu(self, int id, String text, Menu submenu, String help=EmptyString) -> MenuItem"""
+ return _core_.Menu_AppendMenu(*args, **kwargs)
+
+ def AppendSubMenu(*args, **kwargs):
+ """AppendSubMenu(self, Menu submenu, String text, String help=EmptyString) -> MenuItem"""
+ return _core_.Menu_AppendSubMenu(*args, **kwargs)
+
+ def AppendItem(*args, **kwargs):
+ """AppendItem(self, MenuItem item) -> MenuItem"""
+ return _core_.Menu_AppendItem(*args, **kwargs)
+
+ def InsertItem(*args, **kwargs):
+ """InsertItem(self, size_t pos, MenuItem item) -> MenuItem"""
+ return _core_.Menu_InsertItem(*args, **kwargs)
+
+ def PrependItem(*args, **kwargs):
+ """PrependItem(self, MenuItem item) -> MenuItem"""
+ return _core_.Menu_PrependItem(*args, **kwargs)
+
+ def Break(*args, **kwargs):
+ """Break(self)"""
+ return _core_.Menu_Break(*args, **kwargs)
+
+ def Insert(*args, **kwargs):
+ """
+ Insert(self, size_t pos, int id, String text=EmptyString, String help=EmptyString,
+ int kind=ITEM_NORMAL) -> MenuItem
+ """
+ return _core_.Menu_Insert(*args, **kwargs)
+
+ def InsertSeparator(*args, **kwargs):
+ """InsertSeparator(self, size_t pos) -> MenuItem"""
+ return _core_.Menu_InsertSeparator(*args, **kwargs)
+
+ def InsertCheckItem(*args, **kwargs):
+ """InsertCheckItem(self, size_t pos, int id, String text, String help=EmptyString) -> MenuItem"""
+ return _core_.Menu_InsertCheckItem(*args, **kwargs)
+
+ def InsertRadioItem(*args, **kwargs):
+ """InsertRadioItem(self, size_t pos, int id, String text, String help=EmptyString) -> MenuItem"""
+ return _core_.Menu_InsertRadioItem(*args, **kwargs)
+
+ def InsertMenu(*args, **kwargs):
+ """InsertMenu(self, size_t pos, int id, String text, Menu submenu, String help=EmptyString) -> MenuItem"""
+ return _core_.Menu_InsertMenu(*args, **kwargs)
+
+ def Prepend(*args, **kwargs):
+ """
+ Prepend(self, int id, String text=EmptyString, String help=EmptyString,
+ int kind=ITEM_NORMAL) -> MenuItem
+ """
+ return _core_.Menu_Prepend(*args, **kwargs)
+
+ def PrependSeparator(*args, **kwargs):
+ """PrependSeparator(self) -> MenuItem"""
+ return _core_.Menu_PrependSeparator(*args, **kwargs)
+
+ def PrependCheckItem(*args, **kwargs):
+ """PrependCheckItem(self, int id, String text, String help=EmptyString) -> MenuItem"""
+ return _core_.Menu_PrependCheckItem(*args, **kwargs)
+
+ def PrependRadioItem(*args, **kwargs):
+ """PrependRadioItem(self, int id, String text, String help=EmptyString) -> MenuItem"""
+ return _core_.Menu_PrependRadioItem(*args, **kwargs)
+
+ def PrependMenu(*args, **kwargs):
+ """PrependMenu(self, int id, String text, Menu submenu, String help=EmptyString) -> MenuItem"""
+ return _core_.Menu_PrependMenu(*args, **kwargs)
+
+ def Remove(*args, **kwargs):
+ """Remove(self, int id) -> MenuItem"""
+ return _core_.Menu_Remove(*args, **kwargs)
+
+ def RemoveItem(self, item):
+ """RemoveItem(self, MenuItem item) -> MenuItem"""
+ #// The return object is always the parameter, so return that
+ #// proxy instead of the new one
+ val = _core_.Menu_RemoveItem(self, item)
+ item.this.own(val.this.own())
+ val.this.disown()
+ return item
+
+
+ def Delete(*args, **kwargs):
+ """Delete(self, int id) -> bool"""
+ return _core_.Menu_Delete(*args, **kwargs)
+
+ def DeleteItem(*args, **kwargs):
+ """DeleteItem(self, MenuItem item) -> bool"""
+ return _core_.Menu_DeleteItem(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """
+ Destroy(self)
+
+ Deletes the C++ object this Python object is a proxy for.
+ """
+ args[0].this.own(False)
+ return _core_.Menu_Destroy(*args, **kwargs)
+
+ def DestroyId(*args, **kwargs):
+ """DestroyId(self, int id) -> bool"""
+ return _core_.Menu_DestroyId(*args, **kwargs)
+
+ def DestroyItem(*args, **kwargs):
+ """DestroyItem(self, MenuItem item) -> bool"""
+ return _core_.Menu_DestroyItem(*args, **kwargs)
+
+ def GetMenuItemCount(*args, **kwargs):
+ """GetMenuItemCount(self) -> size_t"""
+ return _core_.Menu_GetMenuItemCount(*args, **kwargs)
+
+ def GetMenuItems(*args, **kwargs):
+ """GetMenuItems(self) -> MenuItemList"""
+ return _core_.Menu_GetMenuItems(*args, **kwargs)
+
+ def FindItem(*args, **kwargs):
+ """FindItem(self, String item) -> int"""
+ return _core_.Menu_FindItem(*args, **kwargs)
+
+ def FindItemById(*args, **kwargs):
+ """FindItemById(self, int id) -> MenuItem"""
+ return _core_.Menu_FindItemById(*args, **kwargs)
+
+ def FindItemByPosition(*args, **kwargs):
+ """FindItemByPosition(self, size_t position) -> MenuItem"""
+ return _core_.Menu_FindItemByPosition(*args, **kwargs)
+
+ def Enable(*args, **kwargs):
+ """Enable(self, int id, bool enable)"""
+ return _core_.Menu_Enable(*args, **kwargs)
+
+ def IsEnabled(*args, **kwargs):
+ """IsEnabled(self, int id) -> bool"""
+ return _core_.Menu_IsEnabled(*args, **kwargs)
+
+ def Check(*args, **kwargs):
+ """Check(self, int id, bool check)"""
+ return _core_.Menu_Check(*args, **kwargs)
+
+ def IsChecked(*args, **kwargs):
+ """IsChecked(self, int id) -> bool"""
+ return _core_.Menu_IsChecked(*args, **kwargs)
+
+ def SetLabel(*args, **kwargs):
+ """SetLabel(self, int id, String label)"""
+ return _core_.Menu_SetLabel(*args, **kwargs)
+
+ def GetLabel(*args, **kwargs):
+ """GetLabel(self, int id) -> String"""
+ return _core_.Menu_GetLabel(*args, **kwargs)
+
+ def GetLabelText(*args, **kwargs):
+ """GetLabelText(self, int itemid) -> String"""
+ return _core_.Menu_GetLabelText(*args, **kwargs)
+
+ def SetHelpString(*args, **kwargs):
+ """SetHelpString(self, int id, String helpString)"""
+ return _core_.Menu_SetHelpString(*args, **kwargs)
+
+ def GetHelpString(*args, **kwargs):
+ """GetHelpString(self, int id) -> String"""
+ return _core_.Menu_GetHelpString(*args, **kwargs)
+
+ def SetTitle(*args, **kwargs):
+ """SetTitle(self, String title)"""
+ return _core_.Menu_SetTitle(*args, **kwargs)
+
+ def GetTitle(*args, **kwargs):
+ """GetTitle(self) -> String"""
+ return _core_.Menu_GetTitle(*args, **kwargs)
+
+ def SetEventHandler(*args, **kwargs):
+ """SetEventHandler(self, EvtHandler handler)"""
+ return _core_.Menu_SetEventHandler(*args, **kwargs)
+
+ def GetEventHandler(*args, **kwargs):
+ """GetEventHandler(self) -> EvtHandler"""
+ return _core_.Menu_GetEventHandler(*args, **kwargs)
+
+ def SetInvokingWindow(*args, **kwargs):
+ """SetInvokingWindow(self, Window win)"""
+ return _core_.Menu_SetInvokingWindow(*args, **kwargs)
+
+ def GetInvokingWindow(*args, **kwargs):
+ """GetInvokingWindow(self) -> Window"""
+ return _core_.Menu_GetInvokingWindow(*args, **kwargs)
+
+ def GetWindow(*args, **kwargs):
+ """GetWindow(self) -> Window"""
+ return _core_.Menu_GetWindow(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self) -> long"""
+ return _core_.Menu_GetStyle(*args, **kwargs)
+
+ def UpdateUI(*args, **kwargs):
+ """UpdateUI(self, EvtHandler source=None)"""
+ return _core_.Menu_UpdateUI(*args, **kwargs)
+
+ def GetMenuBar(*args, **kwargs):
+ """GetMenuBar(self) -> MenuBar"""
+ return _core_.Menu_GetMenuBar(*args, **kwargs)
+
+ def Attach(*args, **kwargs):
+ """Attach(self, wxMenuBarBase menubar)"""
+ return _core_.Menu_Attach(*args, **kwargs)
+
+ def Detach(*args, **kwargs):
+ """Detach(self)"""
+ return _core_.Menu_Detach(*args, **kwargs)
+
+ def IsAttached(*args, **kwargs):
+ """IsAttached(self) -> bool"""
+ return _core_.Menu_IsAttached(*args, **kwargs)
+
+ def SetParent(*args, **kwargs):
+ """SetParent(self, Menu parent)"""
+ return _core_.Menu_SetParent(*args, **kwargs)
+
+ def GetParent(*args, **kwargs):
+ """GetParent(self) -> Menu"""
+ return _core_.Menu_GetParent(*args, **kwargs)
+
+ EventHandler = property(GetEventHandler,SetEventHandler,doc="See `GetEventHandler` and `SetEventHandler`")
+ HelpString = property(GetHelpString,SetHelpString,doc="See `GetHelpString` and `SetHelpString`")
+ InvokingWindow = property(GetInvokingWindow,SetInvokingWindow,doc="See `GetInvokingWindow` and `SetInvokingWindow`")
+ MenuBar = property(GetMenuBar,doc="See `GetMenuBar`")
+ MenuItemCount = property(GetMenuItemCount,doc="See `GetMenuItemCount`")
+ MenuItems = property(GetMenuItems,doc="See `GetMenuItems`")
+ Parent = property(GetParent,SetParent,doc="See `GetParent` and `SetParent`")
+ Style = property(GetStyle,doc="See `GetStyle`")
+ Title = property(GetTitle,SetTitle,doc="See `GetTitle` and `SetTitle`")
+_core_.Menu_swigregister(Menu)
+
+#---------------------------------------------------------------------------
+
+class MenuBar(Window):
+ """Proxy of C++ MenuBar class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, long style=0) -> MenuBar"""
+ _core_.MenuBar_swiginit(self,_core_.new_MenuBar(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Append(*args, **kwargs):
+ """Append(self, Menu menu, String title) -> bool"""
+ return _core_.MenuBar_Append(*args, **kwargs)
+
+ def Insert(*args, **kwargs):
+ """Insert(self, size_t pos, Menu menu, String title) -> bool"""
+ return _core_.MenuBar_Insert(*args, **kwargs)
+
+ def GetMenuCount(*args, **kwargs):
+ """GetMenuCount(self) -> size_t"""
+ return _core_.MenuBar_GetMenuCount(*args, **kwargs)
+
+ def GetMenu(*args, **kwargs):
+ """GetMenu(self, size_t pos) -> Menu"""
+ return _core_.MenuBar_GetMenu(*args, **kwargs)
+
+ def Replace(*args, **kwargs):
+ """Replace(self, size_t pos, Menu menu, String title) -> Menu"""
+ return _core_.MenuBar_Replace(*args, **kwargs)
+
+ def Remove(*args, **kwargs):
+ """Remove(self, size_t pos) -> Menu"""
+ return _core_.MenuBar_Remove(*args, **kwargs)
+
+ def EnableTop(*args, **kwargs):
+ """EnableTop(self, size_t pos, bool enable)"""
+ return _core_.MenuBar_EnableTop(*args, **kwargs)
+
+ def IsEnabledTop(*args, **kwargs):
+ """IsEnabledTop(self, size_t pos) -> bool"""
+ return _core_.MenuBar_IsEnabledTop(*args, **kwargs)
+
+ def SetMenuLabel(*args, **kwargs):
+ """SetMenuLabel(self, size_t pos, String label)"""
+ return _core_.MenuBar_SetMenuLabel(*args, **kwargs)
+
+ def GetMenuLabel(*args, **kwargs):
+ """GetMenuLabel(self, size_t pos) -> String"""
+ return _core_.MenuBar_GetMenuLabel(*args, **kwargs)
+
+ SetLabelTop = SetMenuLabel
+ GetLabelTop = GetMenuLabel
+
+ def GetMenuLabelText(*args, **kwargs):
+ """GetMenuLabelText(self, size_t pos) -> String"""
+ return _core_.MenuBar_GetMenuLabelText(*args, **kwargs)
+
+ def FindMenuItem(*args, **kwargs):
+ """FindMenuItem(self, String menu, String item) -> int"""
+ return _core_.MenuBar_FindMenuItem(*args, **kwargs)
+
+ def FindItemById(*args, **kwargs):
+ """FindItemById(self, int id) -> MenuItem"""
+ return _core_.MenuBar_FindItemById(*args, **kwargs)
+
+ def FindMenu(*args, **kwargs):
+ """FindMenu(self, String title) -> int"""
+ return _core_.MenuBar_FindMenu(*args, **kwargs)
+
+ def Enable(*args, **kwargs):
+ """Enable(self, int id, bool enable)"""
+ return _core_.MenuBar_Enable(*args, **kwargs)
+
+ def Check(*args, **kwargs):
+ """Check(self, int id, bool check)"""
+ return _core_.MenuBar_Check(*args, **kwargs)
+
+ def IsChecked(*args, **kwargs):
+ """IsChecked(self, int id) -> bool"""
+ return _core_.MenuBar_IsChecked(*args, **kwargs)
+
+ def IsEnabled(*args, **kwargs):
+ """IsEnabled(self, int id) -> bool"""
+ return _core_.MenuBar_IsEnabled(*args, **kwargs)
+
+ def SetLabel(*args, **kwargs):
+ """SetLabel(self, int id, String label)"""
+ return _core_.MenuBar_SetLabel(*args, **kwargs)
+
+ def GetLabel(*args, **kwargs):
+ """GetLabel(self, int id) -> String"""
+ return _core_.MenuBar_GetLabel(*args, **kwargs)
+
+ def SetHelpString(*args, **kwargs):
+ """SetHelpString(self, int id, String helpString)"""
+ return _core_.MenuBar_SetHelpString(*args, **kwargs)
+
+ def GetHelpString(*args, **kwargs):
+ """GetHelpString(self, int id) -> String"""
+ return _core_.MenuBar_GetHelpString(*args, **kwargs)
+
+ def GetFrame(*args, **kwargs):
+ """GetFrame(self) -> wxFrame"""
+ return _core_.MenuBar_GetFrame(*args, **kwargs)
+
+ def IsAttached(*args, **kwargs):
+ """IsAttached(self) -> bool"""
+ return _core_.MenuBar_IsAttached(*args, **kwargs)
+
+ def Attach(*args, **kwargs):
+ """Attach(self, wxFrame frame)"""
+ return _core_.MenuBar_Attach(*args, **kwargs)
+
+ def Detach(*args, **kwargs):
+ """Detach(self)"""
+ return _core_.MenuBar_Detach(*args, **kwargs)
+
+ def UpdateMenus(*args, **kwargs):
+ """UpdateMenus(self)"""
+ return _core_.MenuBar_UpdateMenus(*args, **kwargs)
+
+ def SetAutoWindowMenu(*args, **kwargs):
+ """SetAutoWindowMenu(bool enable)"""
+ return _core_.MenuBar_SetAutoWindowMenu(*args, **kwargs)
+
+ SetAutoWindowMenu = staticmethod(SetAutoWindowMenu)
+ def GetAutoWindowMenu(*args, **kwargs):
+ """GetAutoWindowMenu() -> bool"""
+ return _core_.MenuBar_GetAutoWindowMenu(*args, **kwargs)
+
+ GetAutoWindowMenu = staticmethod(GetAutoWindowMenu)
+ def MacSetCommonMenuBar(*args, **kwargs):
+ """MacSetCommonMenuBar(MenuBar menubar)"""
+ return _core_.MenuBar_MacSetCommonMenuBar(*args, **kwargs)
+
+ MacSetCommonMenuBar = staticmethod(MacSetCommonMenuBar)
+ def GetMenus(self):
+ """Return a list of (menu, label) items for the menus in the MenuBar. """
+ return [(self.GetMenu(i), self.GetLabelTop(i))
+ for i in range(self.GetMenuCount())]
+
+ def SetMenus(self, items):
+ """Clear and add new menus to the MenuBar from a list of (menu, label) items. """
+ for i in range(self.GetMenuCount()-1, -1, -1):
+ self.Remove(i)
+ for m, l in items:
+ self.Append(m, l)
+
+ Frame = property(GetFrame,doc="See `GetFrame`")
+ MenuCount = property(GetMenuCount,doc="See `GetMenuCount`")
+ Menus = property(GetMenus,SetMenus,doc="See `GetMenus` and `SetMenus`")
+_core_.MenuBar_swigregister(MenuBar)
+
+def MenuBar_SetAutoWindowMenu(*args, **kwargs):
+ """MenuBar_SetAutoWindowMenu(bool enable)"""
+ return _core_.MenuBar_SetAutoWindowMenu(*args, **kwargs)
+
+def MenuBar_GetAutoWindowMenu(*args):
+ """MenuBar_GetAutoWindowMenu() -> bool"""
+ return _core_.MenuBar_GetAutoWindowMenu(*args)
+
+def MenuBar_MacSetCommonMenuBar(*args, **kwargs):
+ """MenuBar_MacSetCommonMenuBar(MenuBar menubar)"""
+ return _core_.MenuBar_MacSetCommonMenuBar(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class MenuItem(Object):
+ """Proxy of C++ MenuItem class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Menu parentMenu=None, int id=ID_SEPARATOR, String text=EmptyString,
+ String help=EmptyString, int kind=ITEM_NORMAL,
+ Menu subMenu=None) -> MenuItem
+ """
+ _core_.MenuItem_swiginit(self,_core_.new_MenuItem(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_MenuItem
+ __del__ = lambda self : None;
+ def Destroy(self): pass
+ def GetMenu(*args, **kwargs):
+ """GetMenu(self) -> Menu"""
+ return _core_.MenuItem_GetMenu(*args, **kwargs)
+
+ def SetMenu(*args, **kwargs):
+ """SetMenu(self, Menu menu)"""
+ return _core_.MenuItem_SetMenu(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """SetId(self, int id)"""
+ return _core_.MenuItem_SetId(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """GetId(self) -> int"""
+ return _core_.MenuItem_GetId(*args, **kwargs)
+
+ def IsSeparator(*args, **kwargs):
+ """IsSeparator(self) -> bool"""
+ return _core_.MenuItem_IsSeparator(*args, **kwargs)
+
+ def SetItemLabel(*args, **kwargs):
+ """SetItemLabel(self, String str)"""
+ return _core_.MenuItem_SetItemLabel(*args, **kwargs)
+
+ def GetItemLabel(*args, **kwargs):
+ """GetItemLabel(self) -> String"""
+ return _core_.MenuItem_GetItemLabel(*args, **kwargs)
+
+ def GetItemLabelText(*args, **kwargs):
+ """GetItemLabelText(self) -> String"""
+ return _core_.MenuItem_GetItemLabelText(*args, **kwargs)
+
+ def GetLabelText(*args, **kwargs):
+ """GetLabelText(String label) -> String"""
+ return _core_.MenuItem_GetLabelText(*args, **kwargs)
+
+ GetLabelText = staticmethod(GetLabelText)
+ GetLabel = GetItemLabelText
+ GetText = GetItemLabel
+ SetText = SetItemLabel
+ GetLabelFromText = GetLabelText
+
+ def GetKind(*args, **kwargs):
+ """GetKind(self) -> int"""
+ return _core_.MenuItem_GetKind(*args, **kwargs)
+
+ def SetKind(*args, **kwargs):
+ """SetKind(self, int kind)"""
+ return _core_.MenuItem_SetKind(*args, **kwargs)
+
+ def SetCheckable(*args, **kwargs):
+ """SetCheckable(self, bool checkable)"""
+ return _core_.MenuItem_SetCheckable(*args, **kwargs)
+
+ def IsCheckable(*args, **kwargs):
+ """IsCheckable(self) -> bool"""
+ return _core_.MenuItem_IsCheckable(*args, **kwargs)
+
+ def IsSubMenu(*args, **kwargs):
+ """IsSubMenu(self) -> bool"""
+ return _core_.MenuItem_IsSubMenu(*args, **kwargs)
+
+ def SetSubMenu(*args, **kwargs):
+ """SetSubMenu(self, Menu menu)"""
+ return _core_.MenuItem_SetSubMenu(*args, **kwargs)
+
+ def GetSubMenu(*args, **kwargs):
+ """GetSubMenu(self) -> Menu"""
+ return _core_.MenuItem_GetSubMenu(*args, **kwargs)
+
+ def Enable(*args, **kwargs):
+ """Enable(self, bool enable=True)"""
+ return _core_.MenuItem_Enable(*args, **kwargs)
+
+ def IsEnabled(*args, **kwargs):
+ """IsEnabled(self) -> bool"""
+ return _core_.MenuItem_IsEnabled(*args, **kwargs)
+
+ def Check(*args, **kwargs):
+ """Check(self, bool check=True)"""
+ return _core_.MenuItem_Check(*args, **kwargs)
+
+ def IsChecked(*args, **kwargs):
+ """IsChecked(self) -> bool"""
+ return _core_.MenuItem_IsChecked(*args, **kwargs)
+
+ def Toggle(*args, **kwargs):
+ """Toggle(self)"""
+ return _core_.MenuItem_Toggle(*args, **kwargs)
+
+ def SetHelp(*args, **kwargs):
+ """SetHelp(self, String str)"""
+ return _core_.MenuItem_SetHelp(*args, **kwargs)
+
+ def GetHelp(*args, **kwargs):
+ """GetHelp(self) -> String"""
+ return _core_.MenuItem_GetHelp(*args, **kwargs)
+
+ def GetAccel(*args, **kwargs):
+ """GetAccel(self) -> AcceleratorEntry"""
+ return _core_.MenuItem_GetAccel(*args, **kwargs)
+
+ def SetAccel(*args, **kwargs):
+ """SetAccel(self, AcceleratorEntry accel)"""
+ return _core_.MenuItem_SetAccel(*args, **kwargs)
+
+ def SetBitmap(*args, **kwargs):
+ """SetBitmap(self, Bitmap bmp, bool bChecked=True)"""
+ return _core_.MenuItem_SetBitmap(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self, bool bChecked=True) -> Bitmap"""
+ return _core_.MenuItem_GetBitmap(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """SetFont(self, Font font)"""
+ return _core_.MenuItem_SetFont(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """GetFont(self) -> Font"""
+ return _core_.MenuItem_GetFont(*args, **kwargs)
+
+ def SetTextColour(*args, **kwargs):
+ """SetTextColour(self, Colour colText)"""
+ return _core_.MenuItem_SetTextColour(*args, **kwargs)
+
+ def GetTextColour(*args, **kwargs):
+ """GetTextColour(self) -> Colour"""
+ return _core_.MenuItem_GetTextColour(*args, **kwargs)
+
+ def SetBackgroundColour(*args, **kwargs):
+ """SetBackgroundColour(self, Colour colBack)"""
+ return _core_.MenuItem_SetBackgroundColour(*args, **kwargs)
+
+ def GetBackgroundColour(*args, **kwargs):
+ """GetBackgroundColour(self) -> Colour"""
+ return _core_.MenuItem_GetBackgroundColour(*args, **kwargs)
+
+ def SetBitmaps(*args, **kwargs):
+ """SetBitmaps(self, Bitmap bmpChecked, Bitmap bmpUnchecked=wxNullBitmap)"""
+ return _core_.MenuItem_SetBitmaps(*args, **kwargs)
+
+ def SetDisabledBitmap(*args, **kwargs):
+ """SetDisabledBitmap(self, Bitmap bmpDisabled)"""
+ return _core_.MenuItem_SetDisabledBitmap(*args, **kwargs)
+
+ def GetDisabledBitmap(*args, **kwargs):
+ """GetDisabledBitmap(self) -> Bitmap"""
+ return _core_.MenuItem_GetDisabledBitmap(*args, **kwargs)
+
+ def SetMarginWidth(*args, **kwargs):
+ """SetMarginWidth(self, int nWidth)"""
+ return _core_.MenuItem_SetMarginWidth(*args, **kwargs)
+
+ def GetMarginWidth(*args, **kwargs):
+ """GetMarginWidth(self) -> int"""
+ return _core_.MenuItem_GetMarginWidth(*args, **kwargs)
+
+ def GetDefaultMarginWidth(*args, **kwargs):
+ """GetDefaultMarginWidth() -> int"""
+ return _core_.MenuItem_GetDefaultMarginWidth(*args, **kwargs)
+
+ GetDefaultMarginWidth = staticmethod(GetDefaultMarginWidth)
+ def IsOwnerDrawn(*args, **kwargs):
+ """IsOwnerDrawn(self) -> bool"""
+ return _core_.MenuItem_IsOwnerDrawn(*args, **kwargs)
+
+ def SetOwnerDrawn(*args, **kwargs):
+ """SetOwnerDrawn(self, bool ownerDrawn=True)"""
+ return _core_.MenuItem_SetOwnerDrawn(*args, **kwargs)
+
+ Accel = property(GetAccel,SetAccel,doc="See `GetAccel` and `SetAccel`")
+ BackgroundColour = property(GetBackgroundColour,SetBackgroundColour,doc="See `GetBackgroundColour` and `SetBackgroundColour`")
+ Bitmap = property(GetBitmap,SetBitmap,doc="See `GetBitmap` and `SetBitmap`")
+ DisabledBitmap = property(GetDisabledBitmap,SetDisabledBitmap,doc="See `GetDisabledBitmap` and `SetDisabledBitmap`")
+ Font = property(GetFont,SetFont,doc="See `GetFont` and `SetFont`")
+ Help = property(GetHelp,SetHelp,doc="See `GetHelp` and `SetHelp`")
+ Id = property(GetId,SetId,doc="See `GetId` and `SetId`")
+ Kind = property(GetKind,SetKind,doc="See `GetKind` and `SetKind`")
+ Label = property(GetLabel,doc="See `GetLabel`")
+ MarginWidth = property(GetMarginWidth,SetMarginWidth,doc="See `GetMarginWidth` and `SetMarginWidth`")
+ Menu = property(GetMenu,SetMenu,doc="See `GetMenu` and `SetMenu`")
+ SubMenu = property(GetSubMenu,SetSubMenu,doc="See `GetSubMenu` and `SetSubMenu`")
+ Text = property(GetText,SetText,doc="See `GetText` and `SetText`")
+ TextColour = property(GetTextColour,SetTextColour,doc="See `GetTextColour` and `SetTextColour`")
+ ItemLabel = property(GetItemLabel,SetItemLabel)
+ ItemLabelText = property(GetItemLabelText)
+_core_.MenuItem_swigregister(MenuItem)
+
+def MenuItem_GetLabelText(*args, **kwargs):
+ """MenuItem_GetLabelText(String label) -> String"""
+ return _core_.MenuItem_GetLabelText(*args, **kwargs)
+
+def MenuItem_GetDefaultMarginWidth(*args):
+ """MenuItem_GetDefaultMarginWidth() -> int"""
+ return _core_.MenuItem_GetDefaultMarginWidth(*args)
+
+#---------------------------------------------------------------------------
+
+ELLIPSIZE_FLAGS_NONE = _core_.ELLIPSIZE_FLAGS_NONE
+ELLIPSIZE_FLAGS_PROCESS_MNEMONICS = _core_.ELLIPSIZE_FLAGS_PROCESS_MNEMONICS
+ELLIPSIZE_FLAGS_EXPAND_TABS = _core_.ELLIPSIZE_FLAGS_EXPAND_TABS
+ELLIPSIZE_FLAGS_DEFAULT = _core_.ELLIPSIZE_FLAGS_DEFAULT
+ELLIPSIZE_NONE = _core_.ELLIPSIZE_NONE
+ELLIPSIZE_START = _core_.ELLIPSIZE_START
+ELLIPSIZE_MIDDLE = _core_.ELLIPSIZE_MIDDLE
+ELLIPSIZE_END = _core_.ELLIPSIZE_END
+class Control(Window):
+ """
+ This is the base class for a control or 'widget'.
+
+ A control is generally a small window which processes user input
+ and/or displays one or more item of data.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, Validator validator=DefaultValidator,
+ String name=ControlNameStr) -> Control
+
+ Create a Control. Normally you should only call this from a subclass'
+ __init__ as a plain old wx.Control is not very useful.
+ """
+ _core_.Control_swiginit(self,_core_.new_Control(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, Validator validator=DefaultValidator,
+ String name=ControlNameStr) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _core_.Control_Create(*args, **kwargs)
+
+ def GetAlignment(*args, **kwargs):
+ """
+ GetAlignment(self) -> int
+
+ Get the control alignment (left/right/centre, top/bottom/centre)
+ """
+ return _core_.Control_GetAlignment(*args, **kwargs)
+
+ def GetLabelText(*args, **kwargs):
+ """
+ GetLabelText(self) -> String
+
+ Get just the text of the label, without mnemonic characters ('&')
+ """
+ return _core_.Control_GetLabelText(*args, **kwargs)
+
+ def SetLabelText(*args, **kwargs):
+ """SetLabelText(self, String text)"""
+ return _core_.Control_SetLabelText(*args, **kwargs)
+
+ def SetLabelMarkup(*args, **kwargs):
+ """SetLabelMarkup(self, String markup) -> bool"""
+ return _core_.Control_SetLabelMarkup(*args, **kwargs)
+
+ def Command(*args, **kwargs):
+ """
+ Command(self, CommandEvent event)
+
+ Simulates the effect of the user issuing a command to the item.
+
+ :see: `wx.CommandEvent`
+
+ """
+ return _core_.Control_Command(*args, **kwargs)
+
+ def RemoveMnemonics(*args, **kwargs):
+ """
+ RemoveMnemonics(String str) -> String
+
+ removes the mnemonics characters
+ """
+ return _core_.Control_RemoveMnemonics(*args, **kwargs)
+
+ RemoveMnemonics = staticmethod(RemoveMnemonics)
+ def EscapeMnemonics(*args, **kwargs):
+ """
+ EscapeMnemonics(String str) -> String
+
+ escapes (by doubling them) the mnemonics
+ """
+ return _core_.Control_EscapeMnemonics(*args, **kwargs)
+
+ EscapeMnemonics = staticmethod(EscapeMnemonics)
+ def FindAccelIndex(*args, **kwargs):
+ """
+ FindAccelIndex(String label) -> int
+
+ Return the accel index in the string or -1 if none.
+ """
+ return _core_.Control_FindAccelIndex(*args, **kwargs)
+
+ FindAccelIndex = staticmethod(FindAccelIndex)
+ def Ellipsize(*args, **kwargs):
+ """Ellipsize(String label, DC dc, int mode, int maxWidth, int flags=ELLIPSIZE_FLAGS_DEFAULT) -> String"""
+ return _core_.Control_Ellipsize(*args, **kwargs)
+
+ Ellipsize = staticmethod(Ellipsize)
+ def GetCompositeControlsDefaultAttributes(*args, **kwargs):
+ """GetCompositeControlsDefaultAttributes(int variant) -> VisualAttributes"""
+ return _core_.Control_GetCompositeControlsDefaultAttributes(*args, **kwargs)
+
+ GetCompositeControlsDefaultAttributes = staticmethod(GetCompositeControlsDefaultAttributes)
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _core_.Control_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ Alignment = property(GetAlignment,doc="See `GetAlignment`")
+ LabelText = property(GetLabelText,SetLabelText,doc="See `GetLabelText`")
+_core_.Control_swigregister(Control)
+ControlNameStr = cvar.ControlNameStr
+
+def PreControl(*args, **kwargs):
+ """
+ PreControl() -> Control
+
+ Precreate a Control control for 2-phase creation
+ """
+ val = _core_.new_PreControl(*args, **kwargs)
+ return val
+
+def Control_RemoveMnemonics(*args, **kwargs):
+ """
+ Control_RemoveMnemonics(String str) -> String
+
+ removes the mnemonics characters
+ """
+ return _core_.Control_RemoveMnemonics(*args, **kwargs)
+
+def Control_EscapeMnemonics(*args, **kwargs):
+ """
+ Control_EscapeMnemonics(String str) -> String
+
+ escapes (by doubling them) the mnemonics
+ """
+ return _core_.Control_EscapeMnemonics(*args, **kwargs)
+
+def Control_FindAccelIndex(*args, **kwargs):
+ """
+ Control_FindAccelIndex(String label) -> int
+
+ Return the accel index in the string or -1 if none.
+ """
+ return _core_.Control_FindAccelIndex(*args, **kwargs)
+
+def Control_Ellipsize(*args, **kwargs):
+ """Control_Ellipsize(String label, DC dc, int mode, int maxWidth, int flags=ELLIPSIZE_FLAGS_DEFAULT) -> String"""
+ return _core_.Control_Ellipsize(*args, **kwargs)
+
+def Control_GetCompositeControlsDefaultAttributes(*args, **kwargs):
+ """Control_GetCompositeControlsDefaultAttributes(int variant) -> VisualAttributes"""
+ return _core_.Control_GetCompositeControlsDefaultAttributes(*args, **kwargs)
+
+def Control_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Control_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _core_.Control_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class ItemContainer(object):
+ """
+ The wx.ItemContainer class defines an interface which is implemented
+ by all controls which have string subitems, each of which may be
+ selected, such as `wx.ListBox`, `wx.CheckListBox`, `wx.Choice` as well
+ as `wx.ComboBox` which implements an extended interface deriving from
+ this one.
+
+ It defines the methods for accessing the control's items and although
+ each of the derived classes implements them differently, they still
+ all conform to the same interface.
+
+ The items in a wx.ItemContainer have (non empty) string labels and,
+ optionally, client data associated with them.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Append(*args, **kwargs):
+ """
+ Append(self, String item, PyObject clientData=None) -> int
+
+ Adds the item to the control, associating the given data with the item
+ if not None. The return value is the index of the newly added item
+ which may be different from the last one if the control is sorted (e.g.
+ has wx.LB_SORT or wx.CB_SORT style).
+ """
+ return _core_.ItemContainer_Append(*args, **kwargs)
+
+ def AppendItems(*args, **kwargs):
+ """
+ AppendItems(self, List strings)
+
+ Apend several items at once to the control. Notice that calling this
+ method may be much faster than appending the items one by one if you
+ need to add a lot of items.
+ """
+ return _core_.ItemContainer_AppendItems(*args, **kwargs)
+
+ def Insert(*args, **kwargs):
+ """
+ Insert(self, String item, int pos, PyObject clientData=None) -> int
+
+ Insert an item into the control before the item at the ``pos`` index,
+ optionally associating some data object with the item.
+ """
+ return _core_.ItemContainer_Insert(*args, **kwargs)
+
+ def InsertItems(*args, **kwargs):
+ """
+ InsertItems(self, List strings, int pos) --> int
+
+ Inserts several items at once into the control. Returns the index of
+ the last item inserted.
+ """
+ return _core_.ItemContainer_InsertItems(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """
+ Set(self, List strings)
+
+ Replace all the items in the control
+ """
+ return _core_.ItemContainer_Set(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """
+ Clear(self)
+
+ Removes all items from the control.
+ """
+ return _core_.ItemContainer_Clear(*args, **kwargs)
+
+ def Delete(*args, **kwargs):
+ """
+ Delete(self, int n)
+
+ Deletes the item at the zero-based index 'n' from the control. Note
+ that it is an error (signalled by a `wx.PyAssertionError` exception if
+ enabled) to remove an item with the index negative or greater or equal
+ than the number of items in the control.
+ """
+ return _core_.ItemContainer_Delete(*args, **kwargs)
+
+ def GetClientData(*args, **kwargs):
+ """
+ GetClientData(self, int n) -> PyObject
+
+ Returns the client data associated with the given item, (if any.)
+ """
+ return _core_.ItemContainer_GetClientData(*args, **kwargs)
+
+ def SetClientData(*args, **kwargs):
+ """
+ SetClientData(self, int n, PyObject clientData)
+
+ Associate the given client data with the item at position n.
+ """
+ return _core_.ItemContainer_SetClientData(*args, **kwargs)
+
+ def HasClientData(*args, **kwargs):
+ """HasClientData(self) -> bool"""
+ return _core_.ItemContainer_HasClientData(*args, **kwargs)
+
+ def GetCount(*args, **kwargs):
+ """
+ GetCount(self) -> int
+
+ Returns the number of items in the control.
+ """
+ return _core_.ItemContainer_GetCount(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """
+ IsEmpty(self) -> bool
+
+ Returns True if the control is empty or False if it has some items.
+ """
+ return _core_.ItemContainer_IsEmpty(*args, **kwargs)
+
+ def GetString(*args, **kwargs):
+ """
+ GetString(self, int n) -> String
+
+ Returns the label of the item with the given index.
+ """
+ return _core_.ItemContainer_GetString(*args, **kwargs)
+
+ def GetStrings(*args, **kwargs):
+ """GetStrings(self) -> wxArrayString"""
+ return _core_.ItemContainer_GetStrings(*args, **kwargs)
+
+ def IsSorted(*args, **kwargs):
+ """IsSorted(self) -> bool"""
+ return _core_.ItemContainer_IsSorted(*args, **kwargs)
+
+ def SetString(*args, **kwargs):
+ """
+ SetString(self, int n, String s)
+
+ Sets the label for the given item.
+ """
+ return _core_.ItemContainer_SetString(*args, **kwargs)
+
+ def FindString(*args, **kwargs):
+ """
+ FindString(self, String s) -> int
+
+ Finds an item whose label matches the given string. Returns the
+ zero-based position of the item, or ``wx.NOT_FOUND`` if the string was not
+ found.
+ """
+ return _core_.ItemContainer_FindString(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """
+ SetSelection(self, int n)
+
+ Sets the item at index 'n' to be the selected item.
+ """
+ return _core_.ItemContainer_SetSelection(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """
+ GetSelection(self) -> int
+
+ Returns the index of the selected item or ``wx.NOT_FOUND`` if no item
+ is selected.
+ """
+ return _core_.ItemContainer_GetSelection(*args, **kwargs)
+
+ def SetStringSelection(*args, **kwargs):
+ """SetStringSelection(self, String s) -> bool"""
+ return _core_.ItemContainer_SetStringSelection(*args, **kwargs)
+
+ def GetStringSelection(*args, **kwargs):
+ """
+ GetStringSelection(self) -> String
+
+ Returns the label of the selected item or an empty string if no item
+ is selected.
+ """
+ return _core_.ItemContainer_GetStringSelection(*args, **kwargs)
+
+ def Select(*args, **kwargs):
+ """
+ Select(self, int n)
+
+ This is the same as `SetSelection` and exists only because it is
+ slightly more natural for controls which support multiple selection.
+ """
+ return _core_.ItemContainer_Select(*args, **kwargs)
+
+ def GetItems(self):
+ """Return a list of the strings in the control"""
+ return [self.GetString(i) for i in xrange(self.GetCount())]
+
+ def SetItems(self, items):
+ """Clear and set the strings in the control from a list"""
+ self.Clear()
+ self.AppendItems(items)
+
+ Count = property(GetCount,doc="See `GetCount`")
+ Items = property(GetItems,SetItems,doc="See `GetItems` and `SetItems`")
+ Selection = property(GetSelection,SetSelection,doc="See `GetSelection` and `SetSelection`")
+ StringSelection = property(GetStringSelection,SetStringSelection,doc="See `GetStringSelection` and `SetStringSelection`")
+ Strings = property(GetStrings,doc="See `GetStrings`")
+_core_.ItemContainer_swigregister(ItemContainer)
+
+#---------------------------------------------------------------------------
+
+class ControlWithItems(Control,ItemContainer):
+ """
+ wx.ControlWithItems combines the ``wx.ItemContainer`` class with the
+ wx.Control class, and is used for the base class of various controls
+ that have items.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+_core_.ControlWithItems_swigregister(ControlWithItems)
+
+#---------------------------------------------------------------------------
+
+TE_HT_UNKNOWN = _core_.TE_HT_UNKNOWN
+TE_HT_BEFORE = _core_.TE_HT_BEFORE
+TE_HT_ON_TEXT = _core_.TE_HT_ON_TEXT
+TE_HT_BELOW = _core_.TE_HT_BELOW
+TE_HT_BEYOND = _core_.TE_HT_BEYOND
+class TextEntryBase(object):
+ """Proxy of C++ TextEntryBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_TextEntryBase
+ __del__ = lambda self : None;
+ def SetValue(*args, **kwargs):
+ """
+ SetValue(self, String value)
+
+ Set the value in the text entry field. Generates a text change event.
+ """
+ return _core_.TextEntryBase_SetValue(*args, **kwargs)
+
+ def ChangeValue(*args, **kwargs):
+ """
+ ChangeValue(self, String value)
+
+ Set the value in the text entry field. Does not generate a text change event.
+ """
+ return _core_.TextEntryBase_ChangeValue(*args, **kwargs)
+
+ def WriteText(*args, **kwargs):
+ """
+ WriteText(self, String text)
+
+ Insert text at the current insertion point in the text field,
+ replacing any text that is currently selected.
+ """
+ return _core_.TextEntryBase_WriteText(*args, **kwargs)
+
+ def AppendText(*args, **kwargs):
+ """
+ AppendText(self, String text)
+
+ Add text to the end of the text field, without removing any existing
+ text. Will reset the selection if any.
+ """
+ return _core_.TextEntryBase_AppendText(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """
+ GetValue(self) -> String
+
+ Returns the current value in the text field.
+ """
+ return _core_.TextEntryBase_GetValue(*args, **kwargs)
+
+ def GetRange(*args, **kwargs):
+ """
+ GetRange(self, long from, long to) -> String
+
+ Returns a subset of the value in the text field.
+ """
+ return _core_.TextEntryBase_GetRange(*args, **kwargs)
+
+ GetString = wx.deprecated(GetRange, "Use `GetRange` instead.")
+ def IsEmpty(*args, **kwargs):
+ """
+ IsEmpty(self) -> bool
+
+ Returns True if the value in the text field is empty.
+ """
+ return _core_.TextEntryBase_IsEmpty(*args, **kwargs)
+
+ def Replace(*args, **kwargs):
+ """
+ Replace(self, long from, long to, String value)
+
+ Replaces the text between two positions with the given text.
+ """
+ return _core_.TextEntryBase_Replace(*args, **kwargs)
+
+ def Remove(*args, **kwargs):
+ """
+ Remove(self, long from, long to)
+
+ Removes the text between two positions in the text field
+ """
+ return _core_.TextEntryBase_Remove(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """
+ Clear(self)
+
+ Clear all text from the text field
+ """
+ return _core_.TextEntryBase_Clear(*args, **kwargs)
+
+ def RemoveSelection(*args, **kwargs):
+ """RemoveSelection(self)"""
+ return _core_.TextEntryBase_RemoveSelection(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """
+ Copy(self)
+
+ Copies the selected text to the clipboard.
+ """
+ return _core_.TextEntryBase_Copy(*args, **kwargs)
+
+ def Cut(*args, **kwargs):
+ """
+ Cut(self)
+
+ Copies the selected text to the clipboard and removes the selection.
+ """
+ return _core_.TextEntryBase_Cut(*args, **kwargs)
+
+ def Paste(*args, **kwargs):
+ """
+ Paste(self)
+
+ Pastes text from the clipboard to the text field.
+ """
+ return _core_.TextEntryBase_Paste(*args, **kwargs)
+
+ def CanCopy(*args, **kwargs):
+ """
+ CanCopy(self) -> bool
+
+ Returns True if the text field has a text selection to copy to the
+ clipboard.
+ """
+ return _core_.TextEntryBase_CanCopy(*args, **kwargs)
+
+ def CanCut(*args, **kwargs):
+ """
+ CanCut(self) -> bool
+
+ Returns True if the text field is editable and there is a text
+ selection to copy to the clipboard.
+ """
+ return _core_.TextEntryBase_CanCut(*args, **kwargs)
+
+ def CanPaste(*args, **kwargs):
+ """
+ CanPaste(self) -> bool
+
+ Returns True if the text field is editable and there is text on the
+ clipboard that can be pasted into the text field.
+ """
+ return _core_.TextEntryBase_CanPaste(*args, **kwargs)
+
+ def Undo(*args, **kwargs):
+ """
+ Undo(self)
+
+ Undoes the last edit in the text field
+ """
+ return _core_.TextEntryBase_Undo(*args, **kwargs)
+
+ def Redo(*args, **kwargs):
+ """
+ Redo(self)
+
+ Redoes the last undo in the text field
+ """
+ return _core_.TextEntryBase_Redo(*args, **kwargs)
+
+ def CanUndo(*args, **kwargs):
+ """
+ CanUndo(self) -> bool
+
+ Returns True if the text field is editable and the last edit can be
+ undone.
+ """
+ return _core_.TextEntryBase_CanUndo(*args, **kwargs)
+
+ def CanRedo(*args, **kwargs):
+ """
+ CanRedo(self) -> bool
+
+ Returns True if the text field is editable and the last undo can be
+ redone.
+ """
+ return _core_.TextEntryBase_CanRedo(*args, **kwargs)
+
+ def SetInsertionPoint(*args, **kwargs):
+ """
+ SetInsertionPoint(self, long pos)
+
+ Sets the insertion point in the combobox text field.
+ """
+ return _core_.TextEntryBase_SetInsertionPoint(*args, **kwargs)
+
+ def GetInsertionPoint(*args, **kwargs):
+ """
+ GetInsertionPoint(self) -> long
+
+ Returns the insertion point for the combobox's text field.
+ """
+ return _core_.TextEntryBase_GetInsertionPoint(*args, **kwargs)
+
+ def SetInsertionPointEnd(*args, **kwargs):
+ """
+ SetInsertionPointEnd(self)
+
+ Move the insertion point to the end of the current value.
+ """
+ return _core_.TextEntryBase_SetInsertionPointEnd(*args, **kwargs)
+
+ def GetLastPosition(*args, **kwargs):
+ """
+ GetLastPosition(self) -> long
+
+ Returns the last position in the combobox text field.
+ """
+ return _core_.TextEntryBase_GetLastPosition(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """
+ SetSelection(self, long from, long to)
+
+ Selects the text starting at the first position up to (but not
+ including) the character at the last position. If both parameters are
+ -1 then all text in the control is selected.
+ """
+ return _core_.TextEntryBase_SetSelection(*args, **kwargs)
+
+ def SelectAll(*args, **kwargs):
+ """
+ SelectAll(self)
+
+ Select all text in the text field.
+ """
+ return _core_.TextEntryBase_SelectAll(*args, **kwargs)
+
+ def HasSelection(*args, **kwargs):
+ """
+ HasSelection(self) -> bool
+
+ Returns True if there is a non-empty selection in the text field.
+ """
+ return _core_.TextEntryBase_HasSelection(*args, **kwargs)
+
+ def GetStringSelection(*args, **kwargs):
+ """
+ GetStringSelection(self) -> String
+
+ Returns the selected text.
+ """
+ return _core_.TextEntryBase_GetStringSelection(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """
+ GetSelection() -> (from, to)
+
+ If the return values from and to are the same, there is no selection.
+ """
+ return _core_.TextEntryBase_GetSelection(*args, **kwargs)
+
+ Selection = property(GetSelection)
+ def AutoComplete(*args, **kwargs):
+ """AutoComplete(self, wxArrayString choices) -> bool"""
+ return _core_.TextEntryBase_AutoComplete(*args, **kwargs)
+
+ def AutoCompleteFileNames(*args, **kwargs):
+ """AutoCompleteFileNames(self) -> bool"""
+ return _core_.TextEntryBase_AutoCompleteFileNames(*args, **kwargs)
+
+ def AutoCompleteDirectories(*args, **kwargs):
+ """AutoCompleteDirectories(self) -> bool"""
+ return _core_.TextEntryBase_AutoCompleteDirectories(*args, **kwargs)
+
+ def IsEditable(*args, **kwargs):
+ """IsEditable(self) -> bool"""
+ return _core_.TextEntryBase_IsEditable(*args, **kwargs)
+
+ def SetEditable(*args, **kwargs):
+ """SetEditable(self, bool editable)"""
+ return _core_.TextEntryBase_SetEditable(*args, **kwargs)
+
+ def SetMaxLength(*args, **kwargs):
+ """
+ SetMaxLength(self, long len)
+
+ Set the max number of characters which may be entered in a single line
+ text control.
+ """
+ return _core_.TextEntryBase_SetMaxLength(*args, **kwargs)
+
+ def SetHint(*args, **kwargs):
+ """SetHint(self, String hint) -> bool"""
+ return _core_.TextEntryBase_SetHint(*args, **kwargs)
+
+ def GetHint(*args, **kwargs):
+ """GetHint(self) -> String"""
+ return _core_.TextEntryBase_GetHint(*args, **kwargs)
+
+ def SetMargins(*args, **kwargs):
+ """SetMargins(self, Point pt) -> bool"""
+ return _core_.TextEntryBase_SetMargins(*args, **kwargs)
+
+ def GetMargins(*args, **kwargs):
+ """GetMargins(self) -> Point"""
+ return _core_.TextEntryBase_GetMargins(*args, **kwargs)
+
+ InsertionPoint = property(GetInsertionPoint,SetInsertionPoint)
+ LastPosition = property(GetLastPosition)
+ Value = property(GetValue,SetValue)
+_core_.TextEntryBase_swigregister(TextEntryBase)
+
+class TextEntry(TextEntryBase):
+ """Proxy of C++ TextEntry class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+_core_.TextEntry_swigregister(TextEntry)
+
+class TextAreaBase(object):
+ """multiline text control specific methods"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_TextAreaBase
+ __del__ = lambda self : None;
+ def GetLineLength(*args, **kwargs):
+ """GetLineLength(self, long lineNo) -> int"""
+ return _core_.TextAreaBase_GetLineLength(*args, **kwargs)
+
+ def GetLineText(*args, **kwargs):
+ """GetLineText(self, long lineNo) -> String"""
+ return _core_.TextAreaBase_GetLineText(*args, **kwargs)
+
+ def GetNumberOfLines(*args, **kwargs):
+ """GetNumberOfLines(self) -> int"""
+ return _core_.TextAreaBase_GetNumberOfLines(*args, **kwargs)
+
+ def LoadFile(*args, **kwargs):
+ """LoadFile(self, String file, int fileType=wxTEXT_TYPE_ANY) -> bool"""
+ return _core_.TextAreaBase_LoadFile(*args, **kwargs)
+
+ def SaveFile(*args, **kwargs):
+ """SaveFile(self, String file=wxEmptyString, int fileType=wxTEXT_TYPE_ANY) -> bool"""
+ return _core_.TextAreaBase_SaveFile(*args, **kwargs)
+
+ def IsModified(*args, **kwargs):
+ """IsModified(self) -> bool"""
+ return _core_.TextAreaBase_IsModified(*args, **kwargs)
+
+ def MarkDirty(*args, **kwargs):
+ """MarkDirty(self)"""
+ return _core_.TextAreaBase_MarkDirty(*args, **kwargs)
+
+ def DiscardEdits(*args, **kwargs):
+ """DiscardEdits(self)"""
+ return _core_.TextAreaBase_DiscardEdits(*args, **kwargs)
+
+ def SetModified(*args, **kwargs):
+ """SetModified(self, bool modified)"""
+ return _core_.TextAreaBase_SetModified(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """SetStyle(self, long start, long end, wxTextAttr style) -> bool"""
+ return _core_.TextAreaBase_SetStyle(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self, long position, wxTextAttr style) -> bool"""
+ return _core_.TextAreaBase_GetStyle(*args, **kwargs)
+
+ def SetDefaultStyle(*args, **kwargs):
+ """SetDefaultStyle(self, wxTextAttr style) -> bool"""
+ return _core_.TextAreaBase_SetDefaultStyle(*args, **kwargs)
+
+ def GetDefaultStyle(*args, **kwargs):
+ """GetDefaultStyle(self) -> wxTextAttr"""
+ return _core_.TextAreaBase_GetDefaultStyle(*args, **kwargs)
+
+ def XYToPosition(*args, **kwargs):
+ """XYToPosition(self, long x, long y) -> long"""
+ return _core_.TextAreaBase_XYToPosition(*args, **kwargs)
+
+ def PositionToXY(*args, **kwargs):
+ """PositionToXY(long pos) -> (x, y)"""
+ return _core_.TextAreaBase_PositionToXY(*args, **kwargs)
+
+ def PositionToCoords(*args, **kwargs):
+ """PositionToCoords(self, long pos) -> Point"""
+ return _core_.TextAreaBase_PositionToCoords(*args, **kwargs)
+
+ def ShowPosition(*args, **kwargs):
+ """ShowPosition(self, long pos)"""
+ return _core_.TextAreaBase_ShowPosition(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(Point pt) -> (result, col, row)
+
+ Find the row, col coresponding to the character at the point given in
+ pixels. NB: pt is in device coords but is not adjusted for the client
+ area origin nor scrolling.
+ """
+ return _core_.TextAreaBase_HitTest(*args, **kwargs)
+
+ def HitTestPos(*args, **kwargs):
+ """
+ HitTestPos(Point pt) -> (result, position)
+
+ Find the character position in the text coresponding to the point
+ given in pixels. NB: pt is in device coords but is not adjusted for
+ the client area origin nor scrolling.
+ """
+ return _core_.TextAreaBase_HitTestPos(*args, **kwargs)
+
+ DefaultStyle = property(GetDefaultStyle,SetDefaultStyle)
+ NumberOfLines = property(GetNumberOfLines)
+_core_.TextAreaBase_swigregister(TextAreaBase)
+
+class TextCtrlIface(TextAreaBase,TextEntryBase):
+ """This class defines the wx.TextCtrl interface"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+_core_.TextCtrlIface_swigregister(TextCtrlIface)
+
+class TextCtrlBase(Control,TextAreaBase,TextEntry):
+ """An abstract base class for wx.TextCtrl."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+_core_.TextCtrlBase_swigregister(TextCtrlBase)
+
+#---------------------------------------------------------------------------
+
+class WithImages(object):
+ """Proxy of C++ WithImages class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ NO_IMAGE = _core_.WithImages_NO_IMAGE
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> WithImages"""
+ _core_.WithImages_swiginit(self,_core_.new_WithImages(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_WithImages
+ __del__ = lambda self : None;
+ def SetImageList(*args, **kwargs):
+ """SetImageList(self, ImageList imageList)"""
+ return _core_.WithImages_SetImageList(*args, **kwargs)
+
+ def AssignImageList(*args, **kwargs):
+ """AssignImageList(self, ImageList imageList)"""
+ return _core_.WithImages_AssignImageList(*args, **kwargs)
+
+ def GetImageList(*args, **kwargs):
+ """GetImageList(self) -> ImageList"""
+ return _core_.WithImages_GetImageList(*args, **kwargs)
+
+ ImageList = property(GetImageList,SetImageList,doc="See `GetImageList` and `SetImageList`")
+_core_.WithImages_swigregister(WithImages)
+
+#---------------------------------------------------------------------------
+
+BK_DEFAULT = _core_.BK_DEFAULT
+BK_TOP = _core_.BK_TOP
+BK_BOTTOM = _core_.BK_BOTTOM
+BK_LEFT = _core_.BK_LEFT
+BK_RIGHT = _core_.BK_RIGHT
+BK_ALIGN_MASK = _core_.BK_ALIGN_MASK
+BK_BUTTONBAR = _core_.BK_BUTTONBAR
+TBK_BUTTONBAR = _core_.TBK_BUTTONBAR
+TBK_HORZ_LAYOUT = _core_.TBK_HORZ_LAYOUT
+BK_HITTEST_NOWHERE = _core_.BK_HITTEST_NOWHERE
+BK_HITTEST_ONICON = _core_.BK_HITTEST_ONICON
+BK_HITTEST_ONLABEL = _core_.BK_HITTEST_ONLABEL
+BK_HITTEST_ONITEM = _core_.BK_HITTEST_ONITEM
+BK_HITTEST_ONPAGE = _core_.BK_HITTEST_ONPAGE
+class BookCtrlBase(Control,WithImages):
+ """Proxy of C++ BookCtrlBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetPageCount(*args, **kwargs):
+ """GetPageCount(self) -> size_t"""
+ return _core_.BookCtrlBase_GetPageCount(*args, **kwargs)
+
+ def GetPage(*args, **kwargs):
+ """GetPage(self, size_t n) -> Window"""
+ return _core_.BookCtrlBase_GetPage(*args, **kwargs)
+
+ def GetCurrentPage(*args, **kwargs):
+ """GetCurrentPage(self) -> Window"""
+ return _core_.BookCtrlBase_GetCurrentPage(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> int"""
+ return _core_.BookCtrlBase_GetSelection(*args, **kwargs)
+
+ def SetPageText(*args, **kwargs):
+ """SetPageText(self, size_t n, String strText) -> bool"""
+ return _core_.BookCtrlBase_SetPageText(*args, **kwargs)
+
+ def GetPageText(*args, **kwargs):
+ """GetPageText(self, size_t n) -> String"""
+ return _core_.BookCtrlBase_GetPageText(*args, **kwargs)
+
+ def GetPageImage(*args, **kwargs):
+ """GetPageImage(self, size_t n) -> int"""
+ return _core_.BookCtrlBase_GetPageImage(*args, **kwargs)
+
+ def SetPageImage(*args, **kwargs):
+ """SetPageImage(self, size_t n, int imageId) -> bool"""
+ return _core_.BookCtrlBase_SetPageImage(*args, **kwargs)
+
+ def SetPageSize(*args, **kwargs):
+ """SetPageSize(self, Size size)"""
+ return _core_.BookCtrlBase_SetPageSize(*args, **kwargs)
+
+ def CalcSizeFromPage(*args, **kwargs):
+ """CalcSizeFromPage(self, Size sizePage) -> Size"""
+ return _core_.BookCtrlBase_CalcSizeFromPage(*args, **kwargs)
+
+ def GetInternalBorder(*args, **kwargs):
+ """GetInternalBorder(self) -> unsigned int"""
+ return _core_.BookCtrlBase_GetInternalBorder(*args, **kwargs)
+
+ def SetInternalBorder(*args, **kwargs):
+ """SetInternalBorder(self, unsigned int internalBorder)"""
+ return _core_.BookCtrlBase_SetInternalBorder(*args, **kwargs)
+
+ def IsVertical(*args, **kwargs):
+ """IsVertical(self) -> bool"""
+ return _core_.BookCtrlBase_IsVertical(*args, **kwargs)
+
+ def SetControlMargin(*args, **kwargs):
+ """SetControlMargin(self, int margin)"""
+ return _core_.BookCtrlBase_SetControlMargin(*args, **kwargs)
+
+ def GetControlMargin(*args, **kwargs):
+ """GetControlMargin(self) -> int"""
+ return _core_.BookCtrlBase_GetControlMargin(*args, **kwargs)
+
+ def SetFitToCurrentPage(*args, **kwargs):
+ """SetFitToCurrentPage(self, bool fit)"""
+ return _core_.BookCtrlBase_SetFitToCurrentPage(*args, **kwargs)
+
+ def GetFitToCurrentPage(*args, **kwargs):
+ """GetFitToCurrentPage(self) -> bool"""
+ return _core_.BookCtrlBase_GetFitToCurrentPage(*args, **kwargs)
+
+ def GetControlSizer(*args, **kwargs):
+ """GetControlSizer(self) -> Sizer"""
+ return _core_.BookCtrlBase_GetControlSizer(*args, **kwargs)
+
+ def DeletePage(*args, **kwargs):
+ """DeletePage(self, size_t n) -> bool"""
+ return _core_.BookCtrlBase_DeletePage(*args, **kwargs)
+
+ def RemovePage(*args, **kwargs):
+ """RemovePage(self, size_t n) -> bool"""
+ return _core_.BookCtrlBase_RemovePage(*args, **kwargs)
+
+ def DeleteAllPages(*args, **kwargs):
+ """DeleteAllPages(self) -> bool"""
+ return _core_.BookCtrlBase_DeleteAllPages(*args, **kwargs)
+
+ def AddPage(*args, **kwargs):
+ """AddPage(self, Window page, String text, bool select=False, int imageId=-1) -> bool"""
+ return _core_.BookCtrlBase_AddPage(*args, **kwargs)
+
+ def InsertPage(*args, **kwargs):
+ """
+ InsertPage(self, size_t n, Window page, String text, bool select=False,
+ int imageId=-1) -> bool
+ """
+ return _core_.BookCtrlBase_InsertPage(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """SetSelection(self, size_t n) -> int"""
+ return _core_.BookCtrlBase_SetSelection(*args, **kwargs)
+
+ def ChangeSelection(*args, **kwargs):
+ """ChangeSelection(self, size_t n) -> int"""
+ return _core_.BookCtrlBase_ChangeSelection(*args, **kwargs)
+
+ def AdvanceSelection(*args, **kwargs):
+ """AdvanceSelection(self, bool forward=True)"""
+ return _core_.BookCtrlBase_AdvanceSelection(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(Point pt) -> (tab, where)
+
+ Returns the page/tab which is hit, and flags indicating where using
+ wx.NB_HITTEST flags.
+ """
+ return _core_.BookCtrlBase_HitTest(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _core_.BookCtrlBase_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ ControlMargin = property(GetControlMargin,SetControlMargin,doc="See `GetControlMargin` and `SetControlMargin`")
+ ControlSizer = property(GetControlSizer,doc="See `GetControlSizer`")
+ CurrentPage = property(GetCurrentPage,doc="See `GetCurrentPage`")
+ FitToCurrentPage = property(GetFitToCurrentPage,SetFitToCurrentPage,doc="See `GetFitToCurrentPage` and `SetFitToCurrentPage`")
+ InternalBorder = property(GetInternalBorder,SetInternalBorder,doc="See `GetInternalBorder` and `SetInternalBorder`")
+ PageCount = property(GetPageCount,doc="See `GetPageCount`")
+ PageImage = property(GetPageImage,SetPageImage,doc="See `GetPageImage` and `SetPageImage`")
+ PageText = property(GetPageText,SetPageText,doc="See `GetPageText` and `SetPageText`")
+ Selection = property(GetSelection,SetSelection,doc="See `GetSelection` and `SetSelection`")
+_core_.BookCtrlBase_swigregister(BookCtrlBase)
+
+def BookCtrlBase_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ BookCtrlBase_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _core_.BookCtrlBase_GetClassDefaultAttributes(*args, **kwargs)
+
+class BookCtrlEvent(NotifyEvent):
+ """Proxy of C++ BookCtrlEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType commandType=wxEVT_NULL, int id=0, int nSel=-1,
+ int nOldSel=-1) -> BookCtrlEvent
+ """
+ _core_.BookCtrlEvent_swiginit(self,_core_.new_BookCtrlEvent(*args, **kwargs))
+ def GetSelection(*args, **kwargs):
+ """
+ GetSelection(self) -> int
+
+ Returns item index for a listbox or choice selection event (not valid
+ for a deselection).
+ """
+ return _core_.BookCtrlEvent_GetSelection(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """SetSelection(self, int nSel)"""
+ return _core_.BookCtrlEvent_SetSelection(*args, **kwargs)
+
+ def GetOldSelection(*args, **kwargs):
+ """GetOldSelection(self) -> int"""
+ return _core_.BookCtrlEvent_GetOldSelection(*args, **kwargs)
+
+ def SetOldSelection(*args, **kwargs):
+ """SetOldSelection(self, int nOldSel)"""
+ return _core_.BookCtrlEvent_SetOldSelection(*args, **kwargs)
+
+ OldSelection = property(GetOldSelection,SetOldSelection,doc="See `GetOldSelection` and `SetOldSelection`")
+ Selection = property(GetSelection,SetSelection,doc="See `GetSelection` and `SetSelection`")
+_core_.BookCtrlEvent_swigregister(BookCtrlEvent)
+
+#---------------------------------------------------------------------------
+
+class SizerFlags(object):
+ """
+ Normally, when you add an item to a sizer via `wx.Sizer.Add`, you have
+ to specify a lot of flags and parameters which can be unwieldy. This
+ is where wx.SizerFlags comes in: it allows you to specify all
+ parameters using the named methods instead. For example, instead of::
+
+ sizer.Add(ctrl, 0, wx.EXPAND | wx.ALL, 10)
+
+ you can now write::
+
+ sizer.AddF(ctrl, wx.SizerFlags().Expand().Border(wx.ALL, 10))
+
+ This is more readable and also allows you to create wx.SizerFlags
+ objects which can be reused for several sizer items.::
+
+ flagsExpand = wx.SizerFlags(1)
+ flagsExpand.Expand().Border(wx.ALL, 10)
+ sizer.AddF(ctrl1, flagsExpand)
+ sizer.AddF(ctrl2, flagsExpand)
+
+ Note that by specification, all methods of wx.SizerFlags return the
+ wx.SizerFlags object itself allowing chaining multiple method calls
+ like in the examples above.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int proportion=0) -> SizerFlags
+
+ Constructs the flags object with the specified proportion.
+ """
+ _core_.SizerFlags_swiginit(self,_core_.new_SizerFlags(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_SizerFlags
+ __del__ = lambda self : None;
+ def Proportion(*args, **kwargs):
+ """
+ Proportion(self, int proportion) -> SizerFlags
+
+ Sets the item's proportion value.
+ """
+ return _core_.SizerFlags_Proportion(*args, **kwargs)
+
+ def Align(*args, **kwargs):
+ """
+ Align(self, int alignment) -> SizerFlags
+
+ Sets the item's alignment
+ """
+ return _core_.SizerFlags_Align(*args, **kwargs)
+
+ def Expand(*args, **kwargs):
+ """
+ Expand(self) -> SizerFlags
+
+ Sets the wx.EXPAND flag, which will cause the item to be expanded to
+ fill as much space as it is given by the sizer.
+ """
+ return _core_.SizerFlags_Expand(*args, **kwargs)
+
+ def Centre(*args, **kwargs):
+ """
+ Centre(self) -> SizerFlags
+
+ Same as `Center` for those with an alternate dialect of English.
+ """
+ return _core_.SizerFlags_Centre(*args, **kwargs)
+
+ def Center(*args, **kwargs):
+ """
+ Center(self) -> SizerFlags
+
+ Sets the centering alignment flags.
+ """
+ return _core_.SizerFlags_Center(*args, **kwargs)
+
+ def Left(*args, **kwargs):
+ """
+ Left(self) -> SizerFlags
+
+ Aligns the object to the left, a shortcut for calling
+ Align(wx.ALIGN_LEFT)
+ """
+ return _core_.SizerFlags_Left(*args, **kwargs)
+
+ def Right(*args, **kwargs):
+ """
+ Right(self) -> SizerFlags
+
+ Aligns the object to the right, a shortcut for calling
+ Align(wx.ALIGN_RIGHT)
+ """
+ return _core_.SizerFlags_Right(*args, **kwargs)
+
+ def Top(*args, **kwargs):
+ """
+ Top(self) -> SizerFlags
+
+ Aligns the object to the top of the available space, a shortcut for
+ calling Align(wx.ALIGN_TOP)
+ """
+ return _core_.SizerFlags_Top(*args, **kwargs)
+
+ def Bottom(*args, **kwargs):
+ """
+ Bottom(self) -> SizerFlags
+
+ Aligns the object to the bottom of the available space, a shortcut for
+ calling Align(wx.ALIGN_BOTTOM)
+ """
+ return _core_.SizerFlags_Bottom(*args, **kwargs)
+
+ def Shaped(*args, **kwargs):
+ """
+ Shaped(self) -> SizerFlags
+
+ Sets the wx.SHAPED flag.
+ """
+ return _core_.SizerFlags_Shaped(*args, **kwargs)
+
+ def FixedMinSize(*args, **kwargs):
+ """
+ FixedMinSize(self) -> SizerFlags
+
+ Sets the wx.FIXED_MINSIZE flag.
+ """
+ return _core_.SizerFlags_FixedMinSize(*args, **kwargs)
+
+ def ReserveSpaceEvenIfHidden(*args, **kwargs):
+ """
+ ReserveSpaceEvenIfHidden(self) -> SizerFlags
+
+ Makes the item ignore window's visibility status
+ """
+ return _core_.SizerFlags_ReserveSpaceEvenIfHidden(*args, **kwargs)
+
+ def Border(*args, **kwargs):
+ """
+ Border(self, int direction=ALL, int borderInPixels=-1) -> SizerFlags
+
+ Sets the border of the item in the direction(s) or sides given by the
+ direction parameter. If the borderInPixels value is not given then
+ the default border size (see `GetDefaultBorder`) will be used.
+ """
+ return _core_.SizerFlags_Border(*args, **kwargs)
+
+ def DoubleBorder(*args, **kwargs):
+ """
+ DoubleBorder(self, int direction=ALL) -> SizerFlags
+
+ Sets the border in the given direction to twice the default border
+ size.
+ """
+ return _core_.SizerFlags_DoubleBorder(*args, **kwargs)
+
+ def TripleBorder(*args, **kwargs):
+ """
+ TripleBorder(self, int direction=ALL) -> SizerFlags
+
+ Sets the border in the given direction to three times the default
+ border size.
+ """
+ return _core_.SizerFlags_TripleBorder(*args, **kwargs)
+
+ def HorzBorder(*args, **kwargs):
+ """
+ HorzBorder(self) -> SizerFlags
+
+ Sets the left and right borders to the default border size.
+ """
+ return _core_.SizerFlags_HorzBorder(*args, **kwargs)
+
+ def DoubleHorzBorder(*args, **kwargs):
+ """
+ DoubleHorzBorder(self) -> SizerFlags
+
+ Sets the left and right borders to twice the default border size.
+ """
+ return _core_.SizerFlags_DoubleHorzBorder(*args, **kwargs)
+
+ def GetDefaultBorder(*args, **kwargs):
+ """
+ GetDefaultBorder() -> int
+
+ Returns the default border size used by the other border methods
+ """
+ return _core_.SizerFlags_GetDefaultBorder(*args, **kwargs)
+
+ GetDefaultBorder = staticmethod(GetDefaultBorder)
+ def GetProportion(*args, **kwargs):
+ """
+ GetProportion(self) -> int
+
+ Returns the proportion value to be used in the sizer item.
+ """
+ return _core_.SizerFlags_GetProportion(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """
+ GetFlags(self) -> int
+
+ Returns the flags value to be used in the sizer item.
+ """
+ return _core_.SizerFlags_GetFlags(*args, **kwargs)
+
+ def GetBorderInPixels(*args, **kwargs):
+ """
+ GetBorderInPixels(self) -> int
+
+ Returns the border value in pixels to be used in the sizer item.
+ """
+ return _core_.SizerFlags_GetBorderInPixels(*args, **kwargs)
+
+_core_.SizerFlags_swigregister(SizerFlags)
+
+def SizerFlags_GetDefaultBorder(*args):
+ """
+ SizerFlags_GetDefaultBorder() -> int
+
+ Returns the default border size used by the other border methods
+ """
+ return _core_.SizerFlags_GetDefaultBorder(*args)
+
+#---------------------------------------------------------------------------
+
+class SizerItemList_iterator(object):
+ """This class serves as an iterator for a wxSizerItemList object."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_SizerItemList_iterator
+ __del__ = lambda self : None;
+ def next(*args, **kwargs):
+ """next(self) -> SizerItem"""
+ return _core_.SizerItemList_iterator_next(*args, **kwargs)
+
+_core_.SizerItemList_iterator_swigregister(SizerItemList_iterator)
+
+class SizerItemList(object):
+ """
+ This class wraps a wxList-based class and gives it a Python
+ sequence-like interface. Sequence operations supported are length,
+ index access and iteration.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_SizerItemList
+ __del__ = lambda self : None;
+ def __len__(*args, **kwargs):
+ """__len__(self) -> size_t"""
+ return _core_.SizerItemList___len__(*args, **kwargs)
+
+ def __getitem__(*args, **kwargs):
+ """__getitem__(self, size_t index) -> SizerItem"""
+ return _core_.SizerItemList___getitem__(*args, **kwargs)
+
+ def __contains__(*args, **kwargs):
+ """__contains__(self, SizerItem obj) -> bool"""
+ return _core_.SizerItemList___contains__(*args, **kwargs)
+
+ def __iter__(*args, **kwargs):
+ """__iter__(self) -> SizerItemList_iterator"""
+ return _core_.SizerItemList___iter__(*args, **kwargs)
+
+ def index(*args, **kwargs):
+ """index(self, SizerItem obj) -> int"""
+ return _core_.SizerItemList_index(*args, **kwargs)
+
+ def __repr__(self):
+ return "wxSizerItemList: " + repr(list(self))
+
+_core_.SizerItemList_swigregister(SizerItemList)
+
+class SizerItem(Object):
+ """
+ The wx.SizerItem class is used to track the position, size and other
+ attributes of each item managed by a `wx.Sizer`. It is not usually
+ necessary to use this class because the sizer elements can also be
+ identified by their positions or window or sizer references but
+ sometimes it may be more convenient to use wx.SizerItem directly.
+ Also, custom classes derived from `wx.PySizer` will probably need to
+ use the collection of wx.SizerItems held by wx.Sizer when calculating
+ layout.
+
+ :see: `wx.Sizer`, `wx.GBSizerItem`
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> SizerItem
+
+ Constructs an empty wx.SizerItem. Either a window, sizer or spacer
+ size will need to be set before this item can be used in a Sizer.
+
+ You will probably never need to create a wx.SizerItem directly as they
+ are created automatically when the sizer's Add, Insert or Prepend
+ methods are called.
+
+ :see: `wx.SizerItemSpacer`, `wx.SizerItemWindow`, `wx.SizerItemSizer`
+ """
+ _core_.SizerItem_swiginit(self,_core_.new_SizerItem(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_SizerItem
+ __del__ = lambda self : None;
+ def DeleteWindows(*args, **kwargs):
+ """
+ DeleteWindows(self)
+
+ Destroy the window or the windows in a subsizer, depending on the type
+ of item.
+ """
+ return _core_.SizerItem_DeleteWindows(*args, **kwargs)
+
+ def DetachSizer(*args, **kwargs):
+ """
+ DetachSizer(self)
+
+ Enable deleting the SizerItem without destroying the contained sizer.
+ """
+ return _core_.SizerItem_DetachSizer(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """
+ GetSize(self) -> Size
+
+ Get the current size of the item, as set in the last Layout.
+ """
+ return _core_.SizerItem_GetSize(*args, **kwargs)
+
+ def CalcMin(*args, **kwargs):
+ """
+ CalcMin(self) -> Size
+
+ Calculates the minimum desired size for the item, including any space
+ needed by borders.
+ """
+ return _core_.SizerItem_CalcMin(*args, **kwargs)
+
+ def SetDimension(*args, **kwargs):
+ """
+ SetDimension(self, Point pos, Size size)
+
+ Set the position and size of the space allocated for this item by the
+ sizer, and adjust the position and size of the item (window or
+ subsizer) to be within that space taking alignment and borders into
+ account.
+ """
+ return _core_.SizerItem_SetDimension(*args, **kwargs)
+
+ def GetMinSize(*args, **kwargs):
+ """
+ GetMinSize(self) -> Size
+
+ Get the minimum size needed for the item.
+ """
+ return _core_.SizerItem_GetMinSize(*args, **kwargs)
+
+ def SetMinSize(*args, **kwargs):
+ """
+ SetMinSize(self, Size size)
+
+ Set the min size needed for the item
+ """
+ return _core_.SizerItem_SetMinSize(*args, **kwargs)
+
+ def GetMinSizeWithBorder(*args, **kwargs):
+ """
+ GetMinSizeWithBorder(self) -> Size
+
+ Get the minimum size needed for the item with space for the borders
+ added, if needed.
+ """
+ return _core_.SizerItem_GetMinSizeWithBorder(*args, **kwargs)
+
+ def SetInitSize(*args, **kwargs):
+ """SetInitSize(self, int x, int y)"""
+ return _core_.SizerItem_SetInitSize(*args, **kwargs)
+
+ def SetRatioWH(*args, **kwargs):
+ """
+ SetRatioWH(self, int width, int height)
+
+ Set the ratio item attribute.
+ """
+ return _core_.SizerItem_SetRatioWH(*args, **kwargs)
+
+ def SetRatioSize(*args, **kwargs):
+ """
+ SetRatioSize(self, Size size)
+
+ Set the ratio item attribute.
+ """
+ return _core_.SizerItem_SetRatioSize(*args, **kwargs)
+
+ def SetRatio(*args, **kwargs):
+ """
+ SetRatio(self, float ratio)
+
+ Set the ratio item attribute.
+ """
+ return _core_.SizerItem_SetRatio(*args, **kwargs)
+
+ def GetRatio(*args, **kwargs):
+ """
+ GetRatio(self) -> float
+
+ Set the ratio item attribute.
+ """
+ return _core_.SizerItem_GetRatio(*args, **kwargs)
+
+ def GetRect(*args, **kwargs):
+ """
+ GetRect(self) -> Rect
+
+ Returns the rectangle that the sizer item should occupy
+ """
+ return _core_.SizerItem_GetRect(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """SetId(self, int id)"""
+ return _core_.SizerItem_SetId(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """GetId(self) -> int"""
+ return _core_.SizerItem_GetId(*args, **kwargs)
+
+ def IsWindow(*args, **kwargs):
+ """
+ IsWindow(self) -> bool
+
+ Is this sizer item a window?
+ """
+ return _core_.SizerItem_IsWindow(*args, **kwargs)
+
+ def IsSizer(*args, **kwargs):
+ """
+ IsSizer(self) -> bool
+
+ Is this sizer item a subsizer?
+ """
+ return _core_.SizerItem_IsSizer(*args, **kwargs)
+
+ def IsSpacer(*args, **kwargs):
+ """
+ IsSpacer(self) -> bool
+
+ Is this sizer item a spacer?
+ """
+ return _core_.SizerItem_IsSpacer(*args, **kwargs)
+
+ def SetProportion(*args, **kwargs):
+ """
+ SetProportion(self, int proportion)
+
+ Set the proportion value for this item.
+ """
+ return _core_.SizerItem_SetProportion(*args, **kwargs)
+
+ def GetProportion(*args, **kwargs):
+ """
+ GetProportion(self) -> int
+
+ Get the proportion value for this item.
+ """
+ return _core_.SizerItem_GetProportion(*args, **kwargs)
+
+ SetOption = wx.deprecated(SetProportion, "Please use `SetProportion` instead.")
+ GetOption = wx.deprecated(GetProportion, "Please use `GetProportion` instead.")
+ def SetFlag(*args, **kwargs):
+ """
+ SetFlag(self, int flag)
+
+ Set the flag value for this item.
+ """
+ return _core_.SizerItem_SetFlag(*args, **kwargs)
+
+ def GetFlag(*args, **kwargs):
+ """
+ GetFlag(self) -> int
+
+ Get the flag value for this item.
+ """
+ return _core_.SizerItem_GetFlag(*args, **kwargs)
+
+ def SetBorder(*args, **kwargs):
+ """
+ SetBorder(self, int border)
+
+ Set the border value for this item.
+ """
+ return _core_.SizerItem_SetBorder(*args, **kwargs)
+
+ def GetBorder(*args, **kwargs):
+ """
+ GetBorder(self) -> int
+
+ Get the border value for this item.
+ """
+ return _core_.SizerItem_GetBorder(*args, **kwargs)
+
+ def GetWindow(*args, **kwargs):
+ """
+ GetWindow(self) -> Window
+
+ Get the window (if any) that is managed by this sizer item.
+ """
+ return _core_.SizerItem_GetWindow(*args, **kwargs)
+
+ def GetSizer(*args, **kwargs):
+ """
+ GetSizer(self) -> Sizer
+
+ Get the subsizer (if any) that is managed by this sizer item.
+ """
+ return _core_.SizerItem_GetSizer(*args, **kwargs)
+
+ def GetSpacer(*args, **kwargs):
+ """
+ GetSpacer(self) -> Size
+
+ Get the size of the spacer managed by this sizer item.
+ """
+ return _core_.SizerItem_GetSpacer(*args, **kwargs)
+
+ def SetWindow(*args, **kwargs):
+ """
+ SetWindow(self, Window window)
+
+ Set the window to be managed by this sizer item.
+ """
+ return _core_.SizerItem_SetWindow(*args, **kwargs)
+
+ def SetSizer(*args, **kwargs):
+ """
+ SetSizer(self, Sizer sizer)
+
+ Set the subsizer to be managed by this sizer item.
+ """
+ return _core_.SizerItem_SetSizer(*args, **kwargs)
+
+ def SetSpacer(*args, **kwargs):
+ """
+ SetSpacer(self, Size size)
+
+ Set the size of the spacer to be managed by this sizer item.
+ """
+ return _core_.SizerItem_SetSpacer(*args, **kwargs)
+
+ SetWindow = wx.deprecated(SetWindow, "Use `AssignWindow` instead.")
+ SetSizer = wx.deprecated(SetSizer, "Use `AssignSizer` instead.")
+ SetSpacer = wx.deprecated(SetSpacer, "Use `AssignSpacer` instead.")
+
+ def AssignWindow(*args, **kwargs):
+ """
+ AssignWindow(self, Window window)
+
+ Set the window to be managed by this sizer item.
+ """
+ return _core_.SizerItem_AssignWindow(*args, **kwargs)
+
+ def AssignSizer(*args, **kwargs):
+ """
+ AssignSizer(self, Sizer sizer)
+
+ Set the subsizer to be managed by this sizer item.
+ """
+ return _core_.SizerItem_AssignSizer(*args, **kwargs)
+
+ def AssignSpacer(*args, **kwargs):
+ """
+ AssignSpacer(self, Size size)
+
+ Set the size of the spacer to be managed by this sizer item.
+ """
+ return _core_.SizerItem_AssignSpacer(*args, **kwargs)
+
+ def Show(*args, **kwargs):
+ """
+ Show(self, bool show)
+
+ Set the show item attribute, which sizers use to determine if the item
+ is to be made part of the layout or not. If the item is tracking a
+ window then it is shown or hidden as needed.
+ """
+ return _core_.SizerItem_Show(*args, **kwargs)
+
+ def IsShown(*args, **kwargs):
+ """
+ IsShown(self) -> bool
+
+ Is the item to be shown in the layout?
+ """
+ return _core_.SizerItem_IsShown(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """
+ GetPosition(self) -> Point
+
+ Returns the current position of the item, as set in the last Layout.
+ """
+ return _core_.SizerItem_GetPosition(*args, **kwargs)
+
+ def InformFirstDirection(*args, **kwargs):
+ """
+ InformFirstDirection(self, int direction, int size, int availableOtherDir=-1) -> bool
+
+ Called once the first component of an item has been decided. This is
+ used in algorithms that depend on knowing the size in one direction
+ before the min size in the other direction can be known. Returns true
+ if it made use of the information (and min size was changed).
+ """
+ return _core_.SizerItem_InformFirstDirection(*args, **kwargs)
+
+ def GetUserData(*args, **kwargs):
+ """
+ GetUserData(self) -> PyObject
+
+ Returns the userData associated with this sizer item, or None if there
+ isn't any.
+ """
+ return _core_.SizerItem_GetUserData(*args, **kwargs)
+
+ def SetUserData(*args, **kwargs):
+ """
+ SetUserData(self, PyObject userData)
+
+ Associate a Python object with this sizer item.
+ """
+ return _core_.SizerItem_SetUserData(*args, **kwargs)
+
+ Border = property(GetBorder,SetBorder,doc="See `GetBorder` and `SetBorder`")
+ Flag = property(GetFlag,SetFlag,doc="See `GetFlag` and `SetFlag`")
+ MinSize = property(GetMinSize,doc="See `GetMinSize`")
+ MinSizeWithBorder = property(GetMinSizeWithBorder,doc="See `GetMinSizeWithBorder`")
+ Position = property(GetPosition,doc="See `GetPosition`")
+ Proportion = property(GetProportion,SetProportion,doc="See `GetProportion` and `SetProportion`")
+ Ratio = property(GetRatio,SetRatio,doc="See `GetRatio` and `SetRatio`")
+ Rect = property(GetRect,doc="See `GetRect`")
+ Size = property(GetSize,doc="See `GetSize`")
+ Sizer = property(GetSizer,AssignSizer,doc="See `GetSizer` and `AssignSizer`")
+ Spacer = property(GetSpacer,AssignSpacer,doc="See `GetSpacer` and `AssignSpacer`")
+ UserData = property(GetUserData,SetUserData,doc="See `GetUserData` and `SetUserData`")
+ Window = property(GetWindow,AssignWindow,doc="See `GetWindow` and `AssignWindow`")
+ Id = property(GetId,SetId)
+_core_.SizerItem_swigregister(SizerItem)
+
+def SizerItemWindow(*args, **kwargs):
+ """
+ SizerItemWindow(Window window, int proportion=0, int flag=0, int border=0,
+ PyObject userData=None) -> SizerItem
+
+ Constructs a `wx.SizerItem` for tracking a window.
+ """
+ val = _core_.new_SizerItemWindow(*args, **kwargs)
+ return val
+
+def SizerItemSpacer(*args, **kwargs):
+ """
+ SizerItemSpacer(int width, int height, int proportion=0, int flag=0,
+ int border=0, PyObject userData=None) -> SizerItem
+
+ Constructs a `wx.SizerItem` for tracking a spacer.
+ """
+ val = _core_.new_SizerItemSpacer(*args, **kwargs)
+ return val
+
+def SizerItemSizer(*args, **kwargs):
+ """
+ SizerItemSizer(Sizer sizer, int proportion=0, int flag=0, int border=0,
+ PyObject userData=None) -> SizerItem
+
+ Constructs a `wx.SizerItem` for tracking a subsizer
+ """
+ val = _core_.new_SizerItemSizer(*args, **kwargs)
+ return val
+
+class Sizer(Object):
+ """
+ wx.Sizer is the abstract base class used for laying out subwindows in
+ a window. You cannot use wx.Sizer directly; instead, you will have to
+ use one of the sizer classes derived from it such as `wx.BoxSizer`,
+ `wx.StaticBoxSizer`, `wx.GridSizer`, `wx.FlexGridSizer` and
+ `wx.GridBagSizer`.
+
+ The concept implemented by sizers in wxWidgets is closely related to
+ layout tools in other GUI toolkits, such as Java's AWT, the GTK
+ toolkit or the Qt toolkit. It is based upon the idea of the individual
+ subwindows reporting their minimal required size and their ability to
+ get stretched if the size of the parent window has changed. This will
+ most often mean that the programmer does not set the original size of
+ a dialog in the beginning, rather the dialog will assigned a sizer and
+ this sizer will be queried about the recommended size. The sizer in
+ turn will query its children, which can be normal windows or contorls,
+ empty space or other sizers, so that a hierarchy of sizers can be
+ constructed. Note that wxSizer does not derive from wxWindow and thus
+ do not interfere with tab ordering and requires very little resources
+ compared to a real window on screen.
+
+ What makes sizers so well fitted for use in wxWidgets is the fact that
+ every control reports its own minimal size and the algorithm can
+ handle differences in font sizes or different window (dialog item)
+ sizes on different platforms without problems. If for example the
+ standard font as well as the overall design of Mac widgets requires
+ more space than on Windows, then the initial size of a dialog using a
+ sizer will automatically be bigger on Mac than on Windows.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_Sizer
+ __del__ = lambda self : None;
+ def _setOORInfo(*args, **kwargs):
+ """_setOORInfo(self, PyObject _self)"""
+ return _core_.Sizer__setOORInfo(*args, **kwargs)
+
+ def Add(*args, **kwargs):
+ """
+ Add(self, item, int proportion=0, int flag=0, int border=0,
+ PyObject userData=None) -> wx.SizerItem
+
+ Appends a child item to the sizer.
+ """
+ return _core_.Sizer_Add(*args, **kwargs)
+
+ def AddF(*args, **kwargs):
+ """
+ AddF(self, item, wx.SizerFlags flags) -> wx.SizerItem
+
+ Similar to `Add` but uses the `wx.SizerFlags` convenience class for
+ setting the various flags, options and borders.
+ """
+ return _core_.Sizer_AddF(*args, **kwargs)
+
+ def Insert(*args, **kwargs):
+ """
+ Insert(self, int before, item, int proportion=0, int flag=0, int border=0,
+ PyObject userData=None) -> wx.SizerItem
+
+ Inserts a new item into the list of items managed by this sizer before
+ the item at index *before*. See `Add` for a description of the parameters.
+ """
+ return _core_.Sizer_Insert(*args, **kwargs)
+
+ def InsertF(*args, **kwargs):
+ """
+ InsertF(self, int before, item, wx.SizerFlags flags) -> wx.SizerItem
+
+ Similar to `Insert`, but uses the `wx.SizerFlags` convenience class
+ for setting the various flags, options and borders.
+ """
+ return _core_.Sizer_InsertF(*args, **kwargs)
+
+ def Prepend(*args, **kwargs):
+ """
+ Prepend(self, item, int proportion=0, int flag=0, int border=0,
+ PyObject userData=None) -> wx.SizerItem
+
+ Adds a new item to the begining of the list of sizer items managed by
+ this sizer. See `Add` for a description of the parameters.
+ """
+ return _core_.Sizer_Prepend(*args, **kwargs)
+
+ def PrependF(*args, **kwargs):
+ """
+ PrependF(self, item, wx.SizerFlags flags) -> wx.SizerItem
+
+ Similar to `Prepend` but uses the `wx.SizerFlags` convenience class
+ for setting the various flags, options and borders.
+ """
+ return _core_.Sizer_PrependF(*args, **kwargs)
+
+ def Remove(*args, **kwargs):
+ """
+ Remove(self, item) -> bool
+
+ Removes an item from the sizer and destroys it. This method does not
+ cause any layout or resizing to take place, call `Layout` to update
+ the layout on screen after removing a child from the sizer. The
+ *item* parameter can be either a window, a sizer, or the zero-based
+ index of an item to remove. Returns True if the child item was found
+ and removed.
+ """
+ return _core_.Sizer_Remove(*args, **kwargs)
+
+ def Detach(*args, **kwargs):
+ """
+ Detach(self, item) -> bool
+
+ Detaches an item from the sizer without destroying it. This method
+ does not cause any layout or resizing to take place, call `Layout` to
+ do so. The *item* parameter can be either a window, a sizer, or the
+ zero-based index of the item to be detached. Returns True if the child item
+ was found and detached.
+ """
+ return _core_.Sizer_Detach(*args, **kwargs)
+
+ def GetItem(*args, **kwargs):
+ """
+ GetItem(self, item, recursive=False) -> wx.SizerItem
+
+ Returns the `wx.SizerItem` which holds the *item* given. The *item*
+ parameter can be either a window, a sizer, or the zero-based index of
+ the item to be found.
+ """
+ return _core_.Sizer_GetItem(*args, **kwargs)
+
+ def _SetItemMinSize(*args, **kwargs):
+ """_SetItemMinSize(self, PyObject item, Size size)"""
+ return _core_.Sizer__SetItemMinSize(*args, **kwargs)
+
+ def GetItemIndex(self, item):
+ """
+ Returns the index of the given *item* within the sizer. Does not
+ search recursively. The *item* parameter can be either a window
+ or a sizer. An assertion is raised if the item is not found in
+ the sizer.
+ """
+ sItem = self.GetItem(item)
+ assert sItem is not None, "Item not found in the sizer."
+ allItems = self.Children
+ idx = 0
+ for i in allItems:
+ if i.this == sItem.this:
+ break
+ idx += 1
+ return idx
+
+ def GetItemById(*args, **kwargs):
+ """GetItemById(self, int id, bool recursive=False) -> SizerItem"""
+ return _core_.Sizer_GetItemById(*args, **kwargs)
+
+ def _ReplaceWin(*args, **kwargs):
+ """_ReplaceWin(self, Window oldwin, Window newwin, bool recursive=False) -> bool"""
+ return _core_.Sizer__ReplaceWin(*args, **kwargs)
+
+ def _ReplaceSizer(*args, **kwargs):
+ """_ReplaceSizer(self, Sizer oldsz, Sizer newsz, bool recursive=False) -> bool"""
+ return _core_.Sizer__ReplaceSizer(*args, **kwargs)
+
+ def _ReplaceItem(*args, **kwargs):
+ """_ReplaceItem(self, size_t index, SizerItem newitem) -> bool"""
+ return _core_.Sizer__ReplaceItem(*args, **kwargs)
+
+ def Replace(self, olditem, item, recursive=False):
+ """
+ Detaches the given ``olditem`` from the sizer and replaces it with
+ ``item`` which can be a window, sizer, or `wx.SizerItem`. The
+ detached child is destroyed only if it is not a window, (because
+ windows are owned by their parent, not the sizer.) The
+ ``recursive`` parameter can be used to search for the given
+ element recursivly in subsizers.
+
+ This method does not cause any layout or resizing to take place,
+ call `Layout` to do so.
+
+ Returns ``True`` if the child item was found and removed.
+ """
+ if isinstance(olditem, wx.Window):
+ return self._ReplaceWin(olditem, item, recursive)
+ elif isinstance(olditem, wx.Sizer):
+ return self._ReplaceSizer(olditem, item, recursive)
+ elif isinstance(olditem, int):
+ return self._ReplaceItem(olditem, item)
+ else:
+ raise TypeError("Expected Window, Sizer, or integer for first parameter.")
+
+ def SetContainingWindow(*args, **kwargs):
+ """
+ SetContainingWindow(self, Window window)
+
+ Set (or unset) the window this sizer is used in.
+ """
+ return _core_.Sizer_SetContainingWindow(*args, **kwargs)
+
+ def GetContainingWindow(*args, **kwargs):
+ """
+ GetContainingWindow(self) -> Window
+
+ Get the window this sizer is used in.
+ """
+ return _core_.Sizer_GetContainingWindow(*args, **kwargs)
+
+ def SetItemMinSize(self, item, *args):
+ """
+ SetItemMinSize(self, item, Size size)
+
+ Sets the minimum size that will be allocated for an item in the sizer.
+ The *item* parameter can be either a window, a sizer, or the
+ zero-based index of the item. If a window or sizer is given then it
+ will be searched for recursivly in subsizers if neccessary.
+ """
+ if len(args) == 2:
+ # for backward compatibility accept separate width,height args too
+ return self._SetItemMinSize(item, args)
+ else:
+ return self._SetItemMinSize(item, args[0])
+
+ def AddItem(*args, **kwargs):
+ """
+ AddItem(self, SizerItem item)
+
+ Adds a `wx.SizerItem` to the sizer.
+ """
+ return _core_.Sizer_AddItem(*args, **kwargs)
+
+ def InsertItem(*args, **kwargs):
+ """
+ InsertItem(self, int index, SizerItem item)
+
+ Inserts a `wx.SizerItem` to the sizer at the position given by *index*.
+ """
+ return _core_.Sizer_InsertItem(*args, **kwargs)
+
+ def PrependItem(*args, **kwargs):
+ """
+ PrependItem(self, SizerItem item)
+
+ Prepends a `wx.SizerItem` to the sizer.
+ """
+ return _core_.Sizer_PrependItem(*args, **kwargs)
+
+ def AddMany(self, items):
+ """
+ AddMany is a convenience method for adding several items
+ to a sizer at one time. Simply pass it a list of tuples,
+ where each tuple consists of the parameters that you
+ would normally pass to the `Add` method.
+ """
+ for item in items:
+ if type(item) != type(()) or (len(item) == 2 and type(item[0]) == type(1)):
+ item = (item, )
+ self.Add(*item)
+
+ def AddSpacer(self, *args, **kw):
+ """AddSpacer(int size) --> SizerItem
+
+ Add a spacer that is (size,size) pixels.
+ """
+ if args and type(args[0]) == int:
+ return self.Add( (args[0],args[0] ), 0)
+ else: # otherwise stay compatible with old AddSpacer
+ return self.Add(*args, **kw)
+ def PrependSpacer(self, *args, **kw):
+ """PrependSpacer(int size) --> SizerItem
+
+ Prepend a spacer that is (size, size) pixels."""
+ if args and type(args[0]) == int:
+ return self.Prepend( (args[0],args[0] ), 0)
+ else: # otherwise stay compatible with old PrependSpacer
+ return self.Prepend(*args, **kw)
+ def InsertSpacer(self, index, *args, **kw):
+ """InsertSpacer(int index, int size) --> SizerItem
+
+ Insert a spacer at position index that is (size, size) pixels."""
+ if args and type(args[0]) == int:
+ return self.Insert( index, (args[0],args[0] ), 0)
+ else: # otherwise stay compatible with old InsertSpacer
+ return self.Insert(index, *args, **kw)
+
+
+ def AddStretchSpacer(self, prop=1):
+ """AddStretchSpacer(int prop=1) --> SizerItem
+
+ Add a stretchable spacer."""
+ return self.Add((0,0), prop)
+ def PrependStretchSpacer(self, prop=1):
+ """PrependStretchSpacer(int prop=1) --> SizerItem
+
+ Prepend a stretchable spacer."""
+ return self.Prepend((0,0), prop)
+ def InsertStretchSpacer(self, index, prop=1):
+ """InsertStretchSpacer(int index, int prop=1) --> SizerItem
+
+ Insert a stretchable spacer."""
+ return self.Insert(index, (0,0), prop)
+
+
+ # for backwards compatibility only, please do not use in new code
+ def AddWindow(self, *args, **kw):
+ """Compatibility alias for `Add`."""
+ return self.Add(*args, **kw)
+ def AddSizer(self, *args, **kw):
+ """Compatibility alias for `Add`."""
+ return self.Add(*args, **kw)
+
+ def PrependWindow(self, *args, **kw):
+ """Compatibility alias for `Prepend`."""
+ return self.Prepend(*args, **kw)
+ def PrependSizer(self, *args, **kw):
+ """Compatibility alias for `Prepend`."""
+ return self.Prepend(*args, **kw)
+
+ def InsertWindow(self, *args, **kw):
+ """Compatibility alias for `Insert`."""
+ return self.Insert(*args, **kw)
+ def InsertSizer(self, *args, **kw):
+ """Compatibility alias for `Insert`."""
+ return self.Insert(*args, **kw)
+
+ def RemoveWindow(self, *args, **kw):
+ """Compatibility alias for `Remove`."""
+ return self.Remove(*args, **kw)
+ def RemoveSizer(self, *args, **kw):
+ """Compatibility alias for `Remove`."""
+ return self.Remove(*args, **kw)
+ def RemovePos(self, *args, **kw):
+ """Compatibility alias for `Remove`."""
+ return self.Remove(*args, **kw)
+
+
+ def SetDimension(*args):
+ """
+ SetDimension(self, int x, int y, int width, int height)
+ SetDimension(self, Point pos, Size size)
+ """
+ return _core_.Sizer_SetDimension(*args)
+
+ def GetItemCount(*args, **kwargs):
+ """GetItemCount(self) -> size_t"""
+ return _core_.Sizer_GetItemCount(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """IsEmpty(self) -> bool"""
+ return _core_.Sizer_IsEmpty(*args, **kwargs)
+
+ def SetMinSize(*args, **kwargs):
+ """
+ SetMinSize(self, Size size)
+
+ Call this to give the sizer a minimal size. Normally, the sizer will
+ calculate its minimal size based purely on how much space its children
+ need. After calling this method `GetMinSize` will return either the
+ minimal size as requested by its children or the minimal size set
+ here, depending on which is bigger.
+ """
+ return _core_.Sizer_SetMinSize(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """
+ GetSize(self) -> Size
+
+ Returns the current size of the space managed by the sizer.
+ """
+ return _core_.Sizer_GetSize(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """
+ GetPosition(self) -> Point
+
+ Returns the current position of the sizer's managed space.
+ """
+ return _core_.Sizer_GetPosition(*args, **kwargs)
+
+ def GetMinSize(*args, **kwargs):
+ """
+ GetMinSize(self) -> Size
+
+ Returns the minimal size of the sizer. This is either the combined
+ minimal size of all the children and their borders or the minimal size
+ set by `SetMinSize`, depending on which is bigger.
+
+ Note that the returned value is *client* size, not window size. In
+ particular, if you use the value to set toplevel window's minimal or
+ actual size, use `wx.Window.SetMinClientSize` or
+ `wx.Window.SetClientSize`, *not* `wx.Window.SetMinSize` or
+ `wx.Window.SetSize`.
+ """
+ return _core_.Sizer_GetMinSize(*args, **kwargs)
+
+ def GetSizeTuple(self):
+ return self.GetSize().Get()
+ def GetPositionTuple(self):
+ return self.GetPosition().Get()
+ def GetMinSizeTuple(self):
+ return self.GetMinSize().Get()
+
+ def RecalcSizes(*args, **kwargs):
+ """
+ RecalcSizes(self)
+
+ Using the sizes calculated by `CalcMin` reposition and resize all the
+ items managed by this sizer. You should not need to call this directly as
+ it is called by `Layout`.
+ """
+ return _core_.Sizer_RecalcSizes(*args, **kwargs)
+
+ def CalcMin(*args, **kwargs):
+ """
+ CalcMin(self) -> Size
+
+ This method is where the sizer will do the actual calculation of its
+ children's minimal sizes. You should not need to call this directly as
+ it is called by `Layout`.
+ """
+ return _core_.Sizer_CalcMin(*args, **kwargs)
+
+ def Layout(*args, **kwargs):
+ """
+ Layout(self)
+
+ This method will force the recalculation and layout of the items
+ controlled by the sizer using the current space allocated to the
+ sizer. Normally this is called automatically from the owning window's
+ EVT_SIZE handler, but it is also useful to call it from user code when
+ one of the items in a sizer change size, or items are added or
+ removed.
+ """
+ return _core_.Sizer_Layout(*args, **kwargs)
+
+ def ComputeFittingClientSize(*args, **kwargs):
+ """
+ ComputeFittingClientSize(self, Window window) -> Size
+
+ Computes client area size for ``window`` so that it matches the
+ sizer's minimal size. Unlike `GetMinSize`, this method accounts for
+ other constraints imposed on ``window``, namely display's size
+ (returned size will never be too large for the display) and maximum
+ window size if previously set by `wx.Window.SetMaxSize`.
+
+ The returned value is suitable for passing to
+ `wx.Window.SetClientSize` or `wx`Window.SetMinClientSize`.
+ """
+ return _core_.Sizer_ComputeFittingClientSize(*args, **kwargs)
+
+ def ComputeFittingWindowSize(*args, **kwargs):
+ """
+ ComputeFittingWindowSize(self, Window window) -> Size
+
+ Like `ComputeFittingClientSize`, but converts the result into *window*
+ size.
+
+ The returned value is suitable for passing to `wx.Window.SetSize` or
+ `wx.Window.SetMinSize`.
+
+ """
+ return _core_.Sizer_ComputeFittingWindowSize(*args, **kwargs)
+
+ def Fit(*args, **kwargs):
+ """
+ Fit(self, Window window) -> Size
+
+ Tell the sizer to resize the *window* to match the sizer's minimal
+ size. This is commonly done in the constructor of the window itself in
+ order to set its initial size to match the needs of the children as
+ determined by the sizer. Returns the new size.
+
+ For a top level window this is the total window size, not the client size.
+ """
+ return _core_.Sizer_Fit(*args, **kwargs)
+
+ def FitInside(*args, **kwargs):
+ """
+ FitInside(self, Window window)
+
+ Tell the sizer to resize the *virtual size* of the *window* to match the
+ sizer's minimal size. This will not alter the on screen size of the
+ window, but may cause the addition/removal/alteration of scrollbars
+ required to view the virtual area in windows which manage it.
+
+ :see: `wx.ScrolledWindow.SetScrollbars`
+
+ """
+ return _core_.Sizer_FitInside(*args, **kwargs)
+
+ def SetSizeHints(*args, **kwargs):
+ """
+ SetSizeHints(self, Window window)
+
+ Tell the sizer to set (and `Fit`) the minimal size of the *window* to
+ match the sizer's minimal size. This is commonly done in the
+ constructor of the window itself if the window is resizable (as are
+ many dialogs under Unix and frames on probably all platforms) in order
+ to prevent the window from being sized smaller than the minimal size
+ required by the sizer.
+ """
+ return _core_.Sizer_SetSizeHints(*args, **kwargs)
+
+ def SetVirtualSizeHints(*args, **kwargs):
+ """
+ SetVirtualSizeHints(self, Window window)
+
+ Tell the sizer to set the minimal size of the window virtual area to
+ match the sizer's minimal size. For windows with managed scrollbars
+ this will set them appropriately.
+
+ :see: `wx.ScrolledWindow.SetScrollbars`
+
+ """
+ return _core_.Sizer_SetVirtualSizeHints(*args, **kwargs)
+
+ SetVirtualSizeHints = wx.deprecated(SetVirtualSizeHints)
+ def Clear(*args, **kwargs):
+ """
+ Clear(self, bool deleteWindows=False)
+
+ Clear all items from the sizer, optionally destroying the window items
+ as well.
+ """
+ return _core_.Sizer_Clear(*args, **kwargs)
+
+ def DeleteWindows(*args, **kwargs):
+ """
+ DeleteWindows(self)
+
+ Destroy all windows managed by the sizer.
+ """
+ return _core_.Sizer_DeleteWindows(*args, **kwargs)
+
+ def InformFirstDirection(*args, **kwargs):
+ """
+ InformFirstDirection(self, int direction, int size, int availableOtherDir) -> bool
+
+ Inform sizer about the first direction that has been decided (by
+ parent item). Returns true if it made use of the informtion (and
+ recalculated min size).
+ """
+ return _core_.Sizer_InformFirstDirection(*args, **kwargs)
+
+ def GetChildren(*args, **kwargs):
+ """
+ GetChildren(self) -> SizerItemList
+
+ Returns all of the `wx.SizerItem` objects managed by the sizer in a
+ list-like object.
+ """
+ return _core_.Sizer_GetChildren(*args, **kwargs)
+
+ def Show(*args, **kwargs):
+ """
+ Show(self, item, bool show=True, bool recursive=false) -> bool
+
+ Shows or hides an item managed by the sizer. To make a sizer item
+ disappear or reappear, use Show followed by `Layout`. The *item*
+ parameter can be either a window, a sizer, or the zero-based index of
+ the item. Use the recursive parameter to show or hide an item in a
+ subsizer. Returns True if the item was found.
+ """
+ return _core_.Sizer_Show(*args, **kwargs)
+
+ def IsShown(*args, **kwargs):
+ """
+ IsShown(self, item)
+
+ Determines if the item is currently shown. To make a sizer
+ item disappear or reappear, use Show followed by `Layout`. The *item*
+ parameter can be either a window, a sizer, or the zero-based index of
+ the item.
+ """
+ return _core_.Sizer_IsShown(*args, **kwargs)
+
+ def Hide(self, item, recursive=False):
+ """
+ A convenience method for `Show` (item, False, recursive).
+ """
+ return self.Show(item, False, recursive)
+
+ def ShowItems(*args, **kwargs):
+ """
+ ShowItems(self, bool show)
+
+ Recursively call `wx.SizerItem.Show` on all sizer items.
+ """
+ return _core_.Sizer_ShowItems(*args, **kwargs)
+
+ Children = property(GetChildren,doc="See `GetChildren`")
+ ContainingWindow = property(GetContainingWindow,SetContainingWindow,doc="See `GetContainingWindow` and `SetContainingWindow`")
+ MinSize = property(GetMinSize,SetMinSize,doc="See `GetMinSize` and `SetMinSize`")
+ Position = property(GetPosition,doc="See `GetPosition`")
+ Size = property(GetSize,doc="See `GetSize`")
+_core_.Sizer_swigregister(Sizer)
+
+class PySizer(Sizer):
+ """
+ wx.PySizer is a special version of `wx.Sizer` that has been
+ instrumented to allow the C++ virtual methods to be overloaded in
+ Python derived classes. You would derive from this class if you are
+ wanting to implement a custom sizer in Python code. Simply implement
+ `CalcMin` and `RecalcSizes` in the derived class and you're all set.
+ For example::
+
+ class MySizer(wx.PySizer):
+ def __init__(self):
+ wx.PySizer.__init__(self)
+
+ def CalcMin(self):
+ for item in self.GetChildren():
+ # calculate the total minimum width and height needed
+ # by all items in the sizer according to this sizer's
+ # layout algorithm.
+ ...
+ return wx.Size(width, height)
+
+ def RecalcSizes(self):
+ # find the space allotted to this sizer
+ pos = self.GetPosition()
+ size = self.GetSize()
+ for item in self.GetChildren():
+ # Recalculate (if necessary) the position and size of
+ # each item and then call item.SetDimension to do the
+ # actual positioning and sizing of the items within the
+ # space alloted to this sizer.
+ ...
+ item.SetDimension(itemPos, itemSize)
+
+
+ When `Layout` is called it first calls `CalcMin` followed by
+ `RecalcSizes` so you can optimize a bit by saving the results of
+ `CalcMin` and reusing them in `RecalcSizes`.
+
+ :see: `wx.SizerItem`, `wx.Sizer.GetChildren`
+
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PySizer
+
+ Creates a wx.PySizer. Must be called from the __init__ in the derived
+ class.
+ """
+ _core_.PySizer_swiginit(self,_core_.new_PySizer(*args, **kwargs))
+ self._setOORInfo(self);PySizer._setCallbackInfo(self, self, PySizer)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _core_.PySizer__setCallbackInfo(*args, **kwargs)
+
+_core_.PySizer_swigregister(PySizer)
+
+#---------------------------------------------------------------------------
+
+class BoxSizer(Sizer):
+ """
+ The basic idea behind a box sizer is that windows will most often be
+ laid out in rather simple basic geometry, typically in a row or a
+ column or nested hierarchies of either. A wx.BoxSizer will lay out
+ its items in a simple row or column, depending on the orientation
+ parameter passed to the constructor.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int orient=HORIZONTAL) -> BoxSizer
+
+ Constructor for a wx.BoxSizer. *orient* may be one of ``wx.VERTICAL``
+ or ``wx.HORIZONTAL`` for creating either a column sizer or a row
+ sizer.
+ """
+ _core_.BoxSizer_swiginit(self,_core_.new_BoxSizer(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetOrientation(*args, **kwargs):
+ """
+ GetOrientation(self) -> int
+
+ Returns the current orientation of the sizer.
+ """
+ return _core_.BoxSizer_GetOrientation(*args, **kwargs)
+
+ def SetOrientation(*args, **kwargs):
+ """
+ SetOrientation(self, int orient)
+
+ Resets the orientation of the sizer.
+ """
+ return _core_.BoxSizer_SetOrientation(*args, **kwargs)
+
+ def IsVertical(*args, **kwargs):
+ """IsVertical(self) -> bool"""
+ return _core_.BoxSizer_IsVertical(*args, **kwargs)
+
+ Orientation = property(GetOrientation,SetOrientation,doc="See `GetOrientation` and `SetOrientation`")
+_core_.BoxSizer_swigregister(BoxSizer)
+
+#---------------------------------------------------------------------------
+
+EXTEND_LAST_ON_EACH_LINE = _core_.EXTEND_LAST_ON_EACH_LINE
+class WrapSizer(BoxSizer):
+ """
+ A box sizer that can wrap items on several lines when widths exceed
+ available width.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int orient=HORIZONTAL, int flags=EXTEND_LAST_ON_EACH_LINE) -> WrapSizer
+
+ A box sizer that can wrap items on several lines when widths exceed
+ available width.
+ """
+ _core_.WrapSizer_swiginit(self,_core_.new_WrapSizer(*args, **kwargs))
+_core_.WrapSizer_swigregister(WrapSizer)
+
+#---------------------------------------------------------------------------
+
+class StaticBoxSizer(BoxSizer):
+ """
+ wx.StaticBoxSizer derives from and functions identically to the
+ `wx.BoxSizer` and adds a `wx.StaticBox` around the items that the sizer
+ manages. Note that this static box must be created separately and
+ passed to the sizer constructor.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, StaticBox box, int orient=HORIZONTAL) -> StaticBoxSizer
+
+ Constructor. It takes an associated static box and the orientation
+ *orient* as parameters - orient can be either of ``wx.VERTICAL`` or
+ ``wx.HORIZONTAL``.
+ """
+ _core_.StaticBoxSizer_swiginit(self,_core_.new_StaticBoxSizer(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetStaticBox(*args, **kwargs):
+ """
+ GetStaticBox(self) -> StaticBox
+
+ Returns the static box associated with this sizer.
+ """
+ return _core_.StaticBoxSizer_GetStaticBox(*args, **kwargs)
+
+ StaticBox = property(GetStaticBox,doc="See `GetStaticBox`")
+_core_.StaticBoxSizer_swigregister(StaticBoxSizer)
+
+#---------------------------------------------------------------------------
+
+class GridSizer(Sizer):
+ """
+ A grid sizer is a sizer which lays out its children in a
+ two-dimensional table with all cells having the same size. In other
+ words, the width of each cell within the grid is the width of the
+ widest item added to the sizer and the height of each grid cell is the
+ height of the tallest item. An optional vertical and/or horizontal
+ gap between items can also be specified (in pixels.)
+
+ Items are placed in the cells of the grid in the order they are added,
+ in row-major order. In other words, the first row is filled first,
+ then the second, and so on until all items have been added. (If
+ neccessary, additional rows will be added as items are added.) If you
+ need to have greater control over the cells that items are placed in
+ then use the `wx.GridBagSizer`.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int rows=0, int cols=0, int vgap=0, int hgap=0) -> GridSizer
+
+ Constructor for a wx.GridSizer. *rows* and *cols* determine the number
+ of columns and rows in the sizer - if either of the parameters is
+ zero, it will be calculated to from the total number of children in
+ the sizer, thus making the sizer grow dynamically. *vgap* and *hgap*
+ define extra space between all children.
+ """
+ _core_.GridSizer_swiginit(self,_core_.new_GridSizer(*args, **kwargs))
+ self._setOORInfo(self)
+ if self.Rows == 0 and self.Cols == 0:
+ self.Rows = 1
+
+ def SetCols(*args, **kwargs):
+ """
+ SetCols(self, int cols)
+
+ Sets the number of columns in the sizer.
+ """
+ return _core_.GridSizer_SetCols(*args, **kwargs)
+
+ def SetRows(*args, **kwargs):
+ """
+ SetRows(self, int rows)
+
+ Sets the number of rows in the sizer.
+ """
+ return _core_.GridSizer_SetRows(*args, **kwargs)
+
+ def SetVGap(*args, **kwargs):
+ """
+ SetVGap(self, int gap)
+
+ Sets the vertical gap (in pixels) between the cells in the sizer.
+ """
+ return _core_.GridSizer_SetVGap(*args, **kwargs)
+
+ def SetHGap(*args, **kwargs):
+ """
+ SetHGap(self, int gap)
+
+ Sets the horizontal gap (in pixels) between cells in the sizer
+ """
+ return _core_.GridSizer_SetHGap(*args, **kwargs)
+
+ def GetCols(*args, **kwargs):
+ """
+ GetCols(self) -> int
+
+ Returns the number of columns in the sizer.
+ """
+ return _core_.GridSizer_GetCols(*args, **kwargs)
+
+ def GetRows(*args, **kwargs):
+ """
+ GetRows(self) -> int
+
+ Returns the number of rows in the sizer.
+ """
+ return _core_.GridSizer_GetRows(*args, **kwargs)
+
+ def GetVGap(*args, **kwargs):
+ """
+ GetVGap(self) -> int
+
+ Returns the vertical gap (in pixels) between the cells in the sizer.
+ """
+ return _core_.GridSizer_GetVGap(*args, **kwargs)
+
+ def GetHGap(*args, **kwargs):
+ """
+ GetHGap(self) -> int
+
+ Returns the horizontal gap (in pixels) between cells in the sizer.
+ """
+ return _core_.GridSizer_GetHGap(*args, **kwargs)
+
+ def GetEffectiveColsCount(*args, **kwargs):
+ """GetEffectiveColsCount(self) -> int"""
+ return _core_.GridSizer_GetEffectiveColsCount(*args, **kwargs)
+
+ def GetEffectiveRowsCount(*args, **kwargs):
+ """GetEffectiveRowsCount(self) -> int"""
+ return _core_.GridSizer_GetEffectiveRowsCount(*args, **kwargs)
+
+ def CalcRowsCols(self):
+ """
+ CalcRowsCols() -> (rows, cols)
+
+ Calculates how many rows and columns will be in the sizer based
+ on the current number of items and also the rows, cols specified
+ in the constructor.
+ """
+ nitems = len(self.GetChildren())
+ rows = self.GetRows()
+ cols = self.GetCols()
+ assert rows != 0 or cols != 0, "Grid sizer must have either rows or columns fixed"
+ if cols != 0:
+ rows = (nitems + cols - 1) / cols
+ elif rows != 0:
+ cols = (nitems + rows - 1) / rows
+ return (rows, cols)
+
+ Cols = property(GetCols,SetCols,doc="See `GetCols` and `SetCols`")
+ HGap = property(GetHGap,SetHGap,doc="See `GetHGap` and `SetHGap`")
+ Rows = property(GetRows,SetRows,doc="See `GetRows` and `SetRows`")
+ VGap = property(GetVGap,SetVGap,doc="See `GetVGap` and `SetVGap`")
+_core_.GridSizer_swigregister(GridSizer)
+
+#---------------------------------------------------------------------------
+
+FLEX_GROWMODE_NONE = _core_.FLEX_GROWMODE_NONE
+FLEX_GROWMODE_SPECIFIED = _core_.FLEX_GROWMODE_SPECIFIED
+FLEX_GROWMODE_ALL = _core_.FLEX_GROWMODE_ALL
+class FlexGridSizer(GridSizer):
+ """
+ A flex grid sizer is a sizer which lays out its children in a
+ two-dimensional table with all table cells in one row having the same
+ height and all cells in one column having the same width, but all
+ rows or all columns are not necessarily the same height or width as in
+ the `wx.GridSizer`.
+
+ wx.FlexGridSizer can also size items equally in one direction but
+ unequally ("flexibly") in the other. If the sizer is only flexible
+ in one direction (this can be changed using `SetFlexibleDirection`), it
+ needs to be decided how the sizer should grow in the other ("non
+ flexible") direction in order to fill the available space. The
+ `SetNonFlexibleGrowMode` method serves this purpose.
+
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int rows=0, int cols=0, int vgap=0, int hgap=0) -> FlexGridSizer
+
+ Constructor for a wx.FlexGridSizer. *rows* and *cols* determine the
+ number of columns and rows in the sizer - if either of the parameters
+ is zero, it will be calculated to from the total number of children in
+ the sizer, thus making the sizer grow dynamically. *vgap* and *hgap*
+ define extra space between all children.
+ """
+ _core_.FlexGridSizer_swiginit(self,_core_.new_FlexGridSizer(*args, **kwargs))
+ self._setOORInfo(self)
+ if self.Rows == 0 and self.Cols == 0:
+ self.Rows = 1
+
+ def AddGrowableRow(*args, **kwargs):
+ """
+ AddGrowableRow(self, size_t idx, int proportion=0)
+
+ Specifies that row *idx* (starting from zero) should be grown if there
+ is extra space available to the sizer.
+
+ The *proportion* parameter has the same meaning as the stretch factor
+ for the box sizers except that if all proportions are 0, then all
+ columns are resized equally (instead of not being resized at all).
+ """
+ return _core_.FlexGridSizer_AddGrowableRow(*args, **kwargs)
+
+ def RemoveGrowableRow(*args, **kwargs):
+ """
+ RemoveGrowableRow(self, size_t idx)
+
+ Specifies that row *idx* is no longer growable.
+ """
+ return _core_.FlexGridSizer_RemoveGrowableRow(*args, **kwargs)
+
+ def AddGrowableCol(*args, **kwargs):
+ """
+ AddGrowableCol(self, size_t idx, int proportion=0)
+
+ Specifies that column *idx* (starting from zero) should be grown if
+ there is extra space available to the sizer.
+
+ The *proportion* parameter has the same meaning as the stretch factor
+ for the box sizers except that if all proportions are 0, then all
+ columns are resized equally (instead of not being resized at all).
+ """
+ return _core_.FlexGridSizer_AddGrowableCol(*args, **kwargs)
+
+ def RemoveGrowableCol(*args, **kwargs):
+ """
+ RemoveGrowableCol(self, size_t idx)
+
+ Specifies that column *idx* is no longer growable.
+ """
+ return _core_.FlexGridSizer_RemoveGrowableCol(*args, **kwargs)
+
+ def IsRowGrowable(*args, **kwargs):
+ """IsRowGrowable(self, size_t idx) -> bool"""
+ return _core_.FlexGridSizer_IsRowGrowable(*args, **kwargs)
+
+ def IsColGrowable(*args, **kwargs):
+ """IsColGrowable(self, size_t idx) -> bool"""
+ return _core_.FlexGridSizer_IsColGrowable(*args, **kwargs)
+
+ def SetFlexibleDirection(*args, **kwargs):
+ """
+ SetFlexibleDirection(self, int direction)
+
+ Specifies whether the sizer should flexibly resize its columns, rows,
+ or both. Argument *direction* can be one of the following values. Any
+ other value is ignored.
+
+ ============== =======================================
+ wx.VERTICAL Rows are flexibly sized.
+ wx.HORIZONTAL Columns are flexibly sized.
+ wx.BOTH Both rows and columns are flexibly sized
+ (this is the default value).
+ ============== =======================================
+
+ Note that this method does not trigger relayout.
+
+ """
+ return _core_.FlexGridSizer_SetFlexibleDirection(*args, **kwargs)
+
+ def GetFlexibleDirection(*args, **kwargs):
+ """
+ GetFlexibleDirection(self) -> int
+
+ Returns a value that specifies whether the sizer
+ flexibly resizes its columns, rows, or both (default).
+
+ :see: `SetFlexibleDirection`
+ """
+ return _core_.FlexGridSizer_GetFlexibleDirection(*args, **kwargs)
+
+ def SetNonFlexibleGrowMode(*args, **kwargs):
+ """
+ SetNonFlexibleGrowMode(self, int mode)
+
+ Specifies how the sizer should grow in the non-flexible direction if
+ there is one (so `SetFlexibleDirection` must have been called
+ previously). Argument *mode* can be one of the following values:
+
+ ========================== =================================================
+ wx.FLEX_GROWMODE_NONE Sizer doesn't grow in the non flexible direction.
+ wx.FLEX_GROWMODE_SPECIFIED Sizer honors growable columns/rows set with
+ `AddGrowableCol` and `AddGrowableRow`. In this
+ case equal sizing applies to minimum sizes of
+ columns or rows (this is the default value).
+ wx.FLEX_GROWMODE_ALL Sizer equally stretches all columns or rows in
+ the non flexible direction, whether they are
+ growable or not in the flexbile direction.
+ ========================== =================================================
+
+ Note that this method does not trigger relayout.
+ """
+ return _core_.FlexGridSizer_SetNonFlexibleGrowMode(*args, **kwargs)
+
+ def GetNonFlexibleGrowMode(*args, **kwargs):
+ """
+ GetNonFlexibleGrowMode(self) -> int
+
+ Returns the value that specifies how the sizer grows in the
+ non-flexible direction if there is one.
+
+ :see: `SetNonFlexibleGrowMode`
+ """
+ return _core_.FlexGridSizer_GetNonFlexibleGrowMode(*args, **kwargs)
+
+ def GetRowHeights(*args, **kwargs):
+ """
+ GetRowHeights(self) -> list
+
+ Returns a list of integers representing the heights of each of the
+ rows in the sizer.
+ """
+ return _core_.FlexGridSizer_GetRowHeights(*args, **kwargs)
+
+ def GetColWidths(*args, **kwargs):
+ """
+ GetColWidths(self) -> list
+
+ Returns a list of integers representing the widths of each of the
+ columns in the sizer.
+ """
+ return _core_.FlexGridSizer_GetColWidths(*args, **kwargs)
+
+ ColWidths = property(GetColWidths,doc="See `GetColWidths`")
+ FlexibleDirection = property(GetFlexibleDirection,SetFlexibleDirection,doc="See `GetFlexibleDirection` and `SetFlexibleDirection`")
+ NonFlexibleGrowMode = property(GetNonFlexibleGrowMode,SetNonFlexibleGrowMode,doc="See `GetNonFlexibleGrowMode` and `SetNonFlexibleGrowMode`")
+ RowHeights = property(GetRowHeights,doc="See `GetRowHeights`")
+_core_.FlexGridSizer_swigregister(FlexGridSizer)
+
+class StdDialogButtonSizer(BoxSizer):
+ """
+ A special sizer that knows how to order and position standard buttons
+ in order to conform to the current platform's standards. You simply
+ need to add each `wx.Button` to the sizer, and be sure to create the
+ buttons using the standard ID's. Then call `Realize` and the sizer
+ will take care of the rest.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> StdDialogButtonSizer"""
+ _core_.StdDialogButtonSizer_swiginit(self,_core_.new_StdDialogButtonSizer(*args, **kwargs))
+ def AddButton(*args, **kwargs):
+ """
+ AddButton(self, wxButton button)
+
+ Use this to add the buttons to this sizer. Do not use the `Add`
+ method in the base class.
+ """
+ return _core_.StdDialogButtonSizer_AddButton(*args, **kwargs)
+
+ def Realize(*args, **kwargs):
+ """
+ Realize(self)
+
+ This funciton needs to be called after all the buttons have been added
+ to the sizer. It will reorder them and position them in a platform
+ specifc manner.
+ """
+ return _core_.StdDialogButtonSizer_Realize(*args, **kwargs)
+
+ def SetAffirmativeButton(*args, **kwargs):
+ """SetAffirmativeButton(self, wxButton button)"""
+ return _core_.StdDialogButtonSizer_SetAffirmativeButton(*args, **kwargs)
+
+ def SetNegativeButton(*args, **kwargs):
+ """SetNegativeButton(self, wxButton button)"""
+ return _core_.StdDialogButtonSizer_SetNegativeButton(*args, **kwargs)
+
+ def SetCancelButton(*args, **kwargs):
+ """SetCancelButton(self, wxButton button)"""
+ return _core_.StdDialogButtonSizer_SetCancelButton(*args, **kwargs)
+
+ def GetAffirmativeButton(*args, **kwargs):
+ """GetAffirmativeButton(self) -> wxButton"""
+ return _core_.StdDialogButtonSizer_GetAffirmativeButton(*args, **kwargs)
+
+ def GetApplyButton(*args, **kwargs):
+ """GetApplyButton(self) -> wxButton"""
+ return _core_.StdDialogButtonSizer_GetApplyButton(*args, **kwargs)
+
+ def GetNegativeButton(*args, **kwargs):
+ """GetNegativeButton(self) -> wxButton"""
+ return _core_.StdDialogButtonSizer_GetNegativeButton(*args, **kwargs)
+
+ def GetCancelButton(*args, **kwargs):
+ """GetCancelButton(self) -> wxButton"""
+ return _core_.StdDialogButtonSizer_GetCancelButton(*args, **kwargs)
+
+ def GetHelpButton(*args, **kwargs):
+ """GetHelpButton(self) -> wxButton"""
+ return _core_.StdDialogButtonSizer_GetHelpButton(*args, **kwargs)
+
+ AffirmativeButton = property(GetAffirmativeButton,SetAffirmativeButton,doc="See `GetAffirmativeButton` and `SetAffirmativeButton`")
+ ApplyButton = property(GetApplyButton,doc="See `GetApplyButton`")
+ CancelButton = property(GetCancelButton,SetCancelButton,doc="See `GetCancelButton` and `SetCancelButton`")
+ HelpButton = property(GetHelpButton,doc="See `GetHelpButton`")
+ NegativeButton = property(GetNegativeButton,SetNegativeButton,doc="See `GetNegativeButton` and `SetNegativeButton`")
+_core_.StdDialogButtonSizer_swigregister(StdDialogButtonSizer)
+
+#---------------------------------------------------------------------------
+
+class GBPosition(object):
+ """
+ This class represents the position of an item in a virtual grid of
+ rows and columns managed by a `wx.GridBagSizer`. wxPython has
+ typemaps that will automatically convert from a 2-element sequence of
+ integers to a wx.GBPosition, so you can use the more pythonic
+ representation of the position nearly transparently in Python code.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int row=0, int col=0) -> GBPosition
+
+ This class represents the position of an item in a virtual grid of
+ rows and columns managed by a `wx.GridBagSizer`. wxPython has
+ typemaps that will automatically convert from a 2-element sequence of
+ integers to a wx.GBPosition, so you can use the more pythonic
+ representation of the position nearly transparently in Python code.
+ """
+ _core_.GBPosition_swiginit(self,_core_.new_GBPosition(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_GBPosition
+ __del__ = lambda self : None;
+ def GetRow(*args, **kwargs):
+ """GetRow(self) -> int"""
+ return _core_.GBPosition_GetRow(*args, **kwargs)
+
+ def GetCol(*args, **kwargs):
+ """GetCol(self) -> int"""
+ return _core_.GBPosition_GetCol(*args, **kwargs)
+
+ def SetRow(*args, **kwargs):
+ """SetRow(self, int row)"""
+ return _core_.GBPosition_SetRow(*args, **kwargs)
+
+ def SetCol(*args, **kwargs):
+ """SetCol(self, int col)"""
+ return _core_.GBPosition_SetCol(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Compare GBPosition for equality.
+ """
+ return _core_.GBPosition___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Compare GBPosition for inequality.
+ """
+ return _core_.GBPosition___ne__(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """Set(self, int row=0, int col=0)"""
+ return _core_.GBPosition_Set(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """Get(self) -> PyObject"""
+ return _core_.GBPosition_Get(*args, **kwargs)
+
+ asTuple = wx.deprecated(Get, "asTuple is deprecated, use `Get` instead")
+ def __str__(self): return str(self.Get())
+ def __repr__(self): return 'wx.GBPosition'+str(self.Get())
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __setitem__(self, index, val):
+ if index == 0: self.SetRow(val)
+ elif index == 1: self.SetCol(val)
+ else: raise IndexError
+ def __nonzero__(self): return self.Get() != (0,0)
+ __safe_for_unpickling__ = True
+ def __reduce__(self): return (wx.GBPosition, self.Get())
+
+ row = property(GetRow, SetRow)
+ col = property(GetCol, SetCol)
+
+_core_.GBPosition_swigregister(GBPosition)
+
+class GBSpan(object):
+ """
+ This class is used to hold the row and column spanning attributes of
+ items in a `wx.GridBagSizer`. wxPython has typemaps that will
+ automatically convert from a 2-element sequence of integers to a
+ wx.GBSpan, so you can use the more pythonic representation of the span
+ nearly transparently in Python code.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int rowspan=1, int colspan=1) -> GBSpan
+
+ Construct a new wxGBSpan, optionally setting the rowspan and
+ colspan. The default is (1,1). (Meaning that the item occupies one
+ cell in each direction.
+ """
+ _core_.GBSpan_swiginit(self,_core_.new_GBSpan(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_GBSpan
+ __del__ = lambda self : None;
+ def GetRowspan(*args, **kwargs):
+ """GetRowspan(self) -> int"""
+ return _core_.GBSpan_GetRowspan(*args, **kwargs)
+
+ def GetColspan(*args, **kwargs):
+ """GetColspan(self) -> int"""
+ return _core_.GBSpan_GetColspan(*args, **kwargs)
+
+ def SetRowspan(*args, **kwargs):
+ """SetRowspan(self, int rowspan)"""
+ return _core_.GBSpan_SetRowspan(*args, **kwargs)
+
+ def SetColspan(*args, **kwargs):
+ """SetColspan(self, int colspan)"""
+ return _core_.GBSpan_SetColspan(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Compare wxGBSpan for equality.
+ """
+ return _core_.GBSpan___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Compare GBSpan for inequality.
+ """
+ return _core_.GBSpan___ne__(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """Set(self, int rowspan=1, int colspan=1)"""
+ return _core_.GBSpan_Set(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """Get(self) -> PyObject"""
+ return _core_.GBSpan_Get(*args, **kwargs)
+
+ asTuple = wx.deprecated(Get, "asTuple is deprecated, use `Get` instead")
+ def __str__(self): return str(self.Get())
+ def __repr__(self): return 'wx.GBSpan'+str(self.Get())
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __setitem__(self, index, val):
+ if index == 0: self.SetRowspan(val)
+ elif index == 1: self.SetColspan(val)
+ else: raise IndexError
+ def __nonzero__(self): return self.Get() != (0,0)
+ __safe_for_unpickling__ = True
+ def __reduce__(self): return (wx.GBSpan, self.Get())
+
+ rowspan = property(GetRowspan, SetRowspan)
+ colspan = property(GetColspan, SetColspan)
+
+_core_.GBSpan_swigregister(GBSpan)
+
+class GBSizerItem(SizerItem):
+ """
+ The wx.GBSizerItem class is used to track the additional data about
+ items in a `wx.GridBagSizer` such as the item's position in the grid
+ and how many rows or columns it spans.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> GBSizerItem
+
+ Constructs an empty wx.GBSizerItem. Either a window, sizer or spacer
+ size will need to be set, as well as a position and span before this
+ item can be used in a Sizer.
+
+ You will probably never need to create a wx.GBSizerItem directly as they
+ are created automatically when the sizer's Add method is called.
+ """
+ _core_.GBSizerItem_swiginit(self,_core_.new_GBSizerItem(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_GBSizerItem
+ __del__ = lambda self : None;
+ def GetPos(*args, **kwargs):
+ """
+ GetPos(self) -> GBPosition
+
+ Get the grid position of the item
+ """
+ return _core_.GBSizerItem_GetPos(*args, **kwargs)
+
+ def GetPosTuple(self): return self.GetPos().Get()
+ def GetSpan(*args, **kwargs):
+ """
+ GetSpan(self) -> GBSpan
+
+ Get the row and column spanning of the item
+ """
+ return _core_.GBSizerItem_GetSpan(*args, **kwargs)
+
+ def GetSpanTuple(self): return self.GetSpan().Get()
+ def SetPos(*args, **kwargs):
+ """
+ SetPos(self, GBPosition pos) -> bool
+
+ If the item is already a member of a sizer then first ensure that
+ there is no other item that would intersect with this one at the new
+ position, then set the new position. Returns True if the change is
+ successful and after the next Layout() the item will be moved.
+ """
+ return _core_.GBSizerItem_SetPos(*args, **kwargs)
+
+ def SetSpan(*args, **kwargs):
+ """
+ SetSpan(self, GBSpan span) -> bool
+
+ If the item is already a member of a sizer then first ensure that
+ there is no other item that would intersect with this one with its new
+ spanning size, then set the new spanning. Returns True if the change
+ is successful and after the next Layout() the item will be resized.
+
+ """
+ return _core_.GBSizerItem_SetSpan(*args, **kwargs)
+
+ def Intersects(*args, **kwargs):
+ """
+ Intersects(self, GBSizerItem other) -> bool
+
+ Returns True if this item and the other item instersect.
+ """
+ return _core_.GBSizerItem_Intersects(*args, **kwargs)
+
+ def IntersectsPos(*args, **kwargs):
+ """
+ IntersectsPos(self, GBPosition pos, GBSpan span) -> bool
+
+ Returns True if the given pos/span would intersect with this item.
+ """
+ return _core_.GBSizerItem_IntersectsPos(*args, **kwargs)
+
+ def GetEndPos(*args, **kwargs):
+ """
+ GetEndPos(self) -> GBPosition
+
+ Get the row and column of the endpoint of this item.
+ """
+ return _core_.GBSizerItem_GetEndPos(*args, **kwargs)
+
+ def GetGBSizer(*args, **kwargs):
+ """
+ GetGBSizer(self) -> GridBagSizer
+
+ Get the sizer this item is a member of.
+ """
+ return _core_.GBSizerItem_GetGBSizer(*args, **kwargs)
+
+ def SetGBSizer(*args, **kwargs):
+ """
+ SetGBSizer(self, GridBagSizer sizer)
+
+ Set the sizer this item is a member of.
+ """
+ return _core_.GBSizerItem_SetGBSizer(*args, **kwargs)
+
+ EndPos = property(GetEndPos,doc="See `GetEndPos`")
+ GBSizer = property(GetGBSizer,SetGBSizer,doc="See `GetGBSizer` and `SetGBSizer`")
+ Pos = property(GetPos,SetPos,doc="See `GetPos` and `SetPos`")
+ Span = property(GetSpan,SetSpan,doc="See `GetSpan` and `SetSpan`")
+_core_.GBSizerItem_swigregister(GBSizerItem)
+DefaultSpan = cvar.DefaultSpan
+
+def GBSizerItemWindow(*args, **kwargs):
+ """
+ GBSizerItemWindow(Window window, GBPosition pos, GBSpan span=DefaultSpan,
+ int flag=0, int border=0, PyObject userData=None) -> GBSizerItem
+
+ Construct a `wx.GBSizerItem` for a window.
+ """
+ val = _core_.new_GBSizerItemWindow(*args, **kwargs)
+ return val
+
+def GBSizerItemSizer(*args, **kwargs):
+ """
+ GBSizerItemSizer(Sizer sizer, GBPosition pos, GBSpan span=DefaultSpan,
+ int flag=0, int border=0, PyObject userData=None) -> GBSizerItem
+
+ Construct a `wx.GBSizerItem` for a sizer
+ """
+ val = _core_.new_GBSizerItemSizer(*args, **kwargs)
+ return val
+
+def GBSizerItemSpacer(*args, **kwargs):
+ """
+ GBSizerItemSpacer(int width, int height, GBPosition pos, GBSpan span=DefaultSpan,
+ int flag=0, int border=0, PyObject userData=None) -> GBSizerItem
+
+ Construct a `wx.GBSizerItem` for a spacer.
+ """
+ val = _core_.new_GBSizerItemSpacer(*args, **kwargs)
+ return val
+
+class GBSizerItemList_iterator(object):
+ """This class serves as an iterator for a wxGBSizerItemList object."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_GBSizerItemList_iterator
+ __del__ = lambda self : None;
+ def next(*args, **kwargs):
+ """next(self) -> GBSizerItem"""
+ return _core_.GBSizerItemList_iterator_next(*args, **kwargs)
+
+_core_.GBSizerItemList_iterator_swigregister(GBSizerItemList_iterator)
+
+class GBSizerItemList(object):
+ """
+ This class wraps a wxList-based class and gives it a Python
+ sequence-like interface. Sequence operations supported are length,
+ index access and iteration.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_GBSizerItemList
+ __del__ = lambda self : None;
+ def __len__(*args, **kwargs):
+ """__len__(self) -> size_t"""
+ return _core_.GBSizerItemList___len__(*args, **kwargs)
+
+ def __getitem__(*args, **kwargs):
+ """__getitem__(self, size_t index) -> GBSizerItem"""
+ return _core_.GBSizerItemList___getitem__(*args, **kwargs)
+
+ def __contains__(*args, **kwargs):
+ """__contains__(self, GBSizerItem obj) -> bool"""
+ return _core_.GBSizerItemList___contains__(*args, **kwargs)
+
+ def __iter__(*args, **kwargs):
+ """__iter__(self) -> GBSizerItemList_iterator"""
+ return _core_.GBSizerItemList___iter__(*args, **kwargs)
+
+ def index(*args, **kwargs):
+ """index(self, GBSizerItem obj) -> int"""
+ return _core_.GBSizerItemList_index(*args, **kwargs)
+
+ def __repr__(self):
+ return "wxGBSizerItemList: " + repr(list(self))
+
+_core_.GBSizerItemList_swigregister(GBSizerItemList)
+
+class GridBagSizer(FlexGridSizer):
+ """
+ A `wx.Sizer` that can lay out items in a virtual grid like a
+ `wx.FlexGridSizer` but in this case explicit positioning of the items
+ is allowed using `wx.GBPosition`, and items can optionally span more
+ than one row and/or column using `wx.GBSpan`. The total size of the
+ virtual grid is determined by the largest row and column that items are
+ positioned at, adjusted for spanning.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int vgap=0, int hgap=0) -> GridBagSizer
+
+ Constructor, with optional parameters to specify the gap between the
+ rows and columns.
+ """
+ _core_.GridBagSizer_swiginit(self,_core_.new_GridBagSizer(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Add(*args, **kwargs):
+ """
+ Add(self, item, GBPosition pos, GBSpan span=DefaultSpan, int flag=0,
+ int border=0, userData=None) -> wx.GBSizerItem
+
+ Adds an item to the sizer at the grid cell *pos*, optionally spanning
+ more than one row or column as specified with *span*. The remaining
+ args behave similarly to `wx.Sizer.Add`.
+
+ Returns True if the item was successfully placed at the given cell
+ position, False if something was already there.
+
+ """
+ return _core_.GridBagSizer_Add(*args, **kwargs)
+
+ def AddItem(*args, **kwargs):
+ """
+ Add(self, GBSizerItem item) -> wx.GBSizerItem
+
+ Add an item to the sizer using a `wx.GBSizerItem`. Returns True if
+ the item was successfully placed at its given cell position, False if
+ something was already there.
+ """
+ return _core_.GridBagSizer_AddItem(*args, **kwargs)
+
+ def GetCellSize(*args, **kwargs):
+ """
+ GetCellSize(self, int row, int col) -> Size
+
+ Get the size of the specified cell, including hgap and
+ vgap. Only valid after a Layout.
+ """
+ return _core_.GridBagSizer_GetCellSize(*args, **kwargs)
+
+ def GetEmptyCellSize(*args, **kwargs):
+ """
+ GetEmptyCellSize(self) -> Size
+
+ Get the size used for cells in the grid with no item.
+ """
+ return _core_.GridBagSizer_GetEmptyCellSize(*args, **kwargs)
+
+ def SetEmptyCellSize(*args, **kwargs):
+ """
+ SetEmptyCellSize(self, Size sz)
+
+ Set the size used for cells in the grid with no item.
+ """
+ return _core_.GridBagSizer_SetEmptyCellSize(*args, **kwargs)
+
+ def GetItemPosition(*args):
+ """
+ GetItemPosition(self, item) -> GBPosition
+
+ Get the grid position of the specified *item* where *item* is either a
+ window or subsizer that is a member of this sizer, or a zero-based
+ index of an item.
+ """
+ return _core_.GridBagSizer_GetItemPosition(*args)
+
+ def SetItemPosition(*args):
+ """
+ SetItemPosition(self, item, GBPosition pos) -> bool
+
+ Set the grid position of the specified *item* where *item* is either a
+ window or subsizer that is a member of this sizer, or a zero-based
+ index of an item. Returns True on success. If the move is not
+ allowed (because an item is already there) then False is returned.
+
+ """
+ return _core_.GridBagSizer_SetItemPosition(*args)
+
+ def GetItemSpan(*args):
+ """
+ GetItemSpan(self, item) -> GBSpan
+
+ Get the row/col spanning of the specified *item* where *item* is
+ either a window or subsizer that is a member of this sizer, or a
+ zero-based index of an item.
+ """
+ return _core_.GridBagSizer_GetItemSpan(*args)
+
+ def SetItemSpan(*args):
+ """
+ SetItemSpan(self, item, GBSpan span) -> bool
+
+ Set the row/col spanning of the specified *item* where *item* is
+ either a window or subsizer that is a member of this sizer, or a
+ zero-based index of an item. Returns True on success. If the move is
+ not allowed (because an item is already there) then False is returned.
+ """
+ return _core_.GridBagSizer_SetItemSpan(*args)
+
+ def FindItem(*args):
+ """
+ FindItem(self, item) -> GBSizerItem
+
+ Find the sizer item for the given window or subsizer, returns None if
+ not found. (non-recursive)
+ """
+ return _core_.GridBagSizer_FindItem(*args)
+
+ def GetItem(self, item):
+ gbsi = None
+ si = wx.FlexGridSizer.GetItem(self, item)
+ if not si:
+ return None
+ if type(item) is not int:
+ gbsi = self.FindItem(item)
+ if gbsi: return gbsi
+ return si
+
+ def FindItemAtPosition(*args, **kwargs):
+ """
+ FindItemAtPosition(self, GBPosition pos) -> GBSizerItem
+
+ Return the sizer item for the given grid cell, or None if there is no
+ item at that position. (non-recursive)
+ """
+ return _core_.GridBagSizer_FindItemAtPosition(*args, **kwargs)
+
+ def FindItemAtPoint(*args, **kwargs):
+ """
+ FindItemAtPoint(self, Point pt) -> GBSizerItem
+
+ Return the sizer item located at the point given in *pt*, or None if
+ there is no item at that point. The (x,y) coordinates in pt correspond
+ to the client coordinates of the window using the sizer for
+ layout. (non-recursive)
+ """
+ return _core_.GridBagSizer_FindItemAtPoint(*args, **kwargs)
+
+ def GetChildren(*args, **kwargs):
+ """
+ GetChildren(self) -> GBSizerItemList
+
+ Returns all of the `wx.GBSizerItem` objects managed by the sizer in a
+ list-like object.
+ """
+ return _core_.GridBagSizer_GetChildren(*args, **kwargs)
+
+ def CheckForIntersection(*args, **kwargs):
+ """
+ CheckForIntersection(self, GBSizerItem item, GBSizerItem excludeItem=None) -> bool
+
+ Look at all items and see if any intersect (or would overlap) the
+ given *item*. Returns True if so, False if there would be no overlap.
+ If an *excludeItem* is given then it will not be checked for
+ intersection, for example it may be the item we are checking the
+ position of.
+
+ """
+ return _core_.GridBagSizer_CheckForIntersection(*args, **kwargs)
+
+ def CheckForIntersectionPos(*args, **kwargs):
+ """
+ CheckForIntersectionPos(self, GBPosition pos, GBSpan span, GBSizerItem excludeItem=None) -> bool
+
+ Look at all items and see if any intersect (or would overlap) the
+ given position and span. Returns True if so, False if there would be
+ no overlap. If an *excludeItem* is given then it will not be checked
+ for intersection, for example it may be the item we are checking the
+ position of.
+ """
+ return _core_.GridBagSizer_CheckForIntersectionPos(*args, **kwargs)
+
+_core_.GridBagSizer_swigregister(GridBagSizer)
+
+#---------------------------------------------------------------------------
+
+Left = _core_.Left
+Top = _core_.Top
+Right = _core_.Right
+Bottom = _core_.Bottom
+Width = _core_.Width
+Height = _core_.Height
+Centre = _core_.Centre
+Center = _core_.Center
+CentreX = _core_.CentreX
+CentreY = _core_.CentreY
+Unconstrained = _core_.Unconstrained
+AsIs = _core_.AsIs
+PercentOf = _core_.PercentOf
+Above = _core_.Above
+Below = _core_.Below
+LeftOf = _core_.LeftOf
+RightOf = _core_.RightOf
+SameAs = _core_.SameAs
+Absolute = _core_.Absolute
+class IndividualLayoutConstraint(Object):
+ """
+ Objects of this class are stored in the `wx.LayoutConstraints` class as
+ one of eight possible constraints that a window can be involved in.
+ You will never need to create an instance of
+ wx.IndividualLayoutConstraint, rather you should create a
+ `wx.LayoutConstraints` instance and use the individual contstraints
+ that it contains.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Set(*args, **kwargs):
+ """
+ Set(self, int rel, Window otherW, int otherE, int val=0, int marg=wxLAYOUT_DEFAULT_MARGIN)
+
+ Sets the properties of the constraint. Normally called by one of the
+ convenience functions such as Above, RightOf, SameAs.
+ """
+ return _core_.IndividualLayoutConstraint_Set(*args, **kwargs)
+
+ def LeftOf(*args, **kwargs):
+ """
+ LeftOf(self, Window sibling, int marg=0)
+
+ Constrains this edge to be to the left of the given window, with an
+ optional margin. Implicitly, this is relative to the left edge of the
+ other window.
+ """
+ return _core_.IndividualLayoutConstraint_LeftOf(*args, **kwargs)
+
+ def RightOf(*args, **kwargs):
+ """
+ RightOf(self, Window sibling, int marg=0)
+
+ Constrains this edge to be to the right of the given window, with an
+ optional margin. Implicitly, this is relative to the right edge of the
+ other window.
+ """
+ return _core_.IndividualLayoutConstraint_RightOf(*args, **kwargs)
+
+ def Above(*args, **kwargs):
+ """
+ Above(self, Window sibling, int marg=0)
+
+ Constrains this edge to be above the given window, with an optional
+ margin. Implicitly, this is relative to the top edge of the other
+ window.
+ """
+ return _core_.IndividualLayoutConstraint_Above(*args, **kwargs)
+
+ def Below(*args, **kwargs):
+ """
+ Below(self, Window sibling, int marg=0)
+
+ Constrains this edge to be below the given window, with an optional
+ margin. Implicitly, this is relative to the bottom edge of the other
+ window.
+ """
+ return _core_.IndividualLayoutConstraint_Below(*args, **kwargs)
+
+ def SameAs(*args, **kwargs):
+ """
+ SameAs(self, Window otherW, int edge, int marg=0)
+
+ Constrains this edge or dimension to be to the same as the edge of the
+ given window, with an optional margin.
+ """
+ return _core_.IndividualLayoutConstraint_SameAs(*args, **kwargs)
+
+ def PercentOf(*args, **kwargs):
+ """
+ PercentOf(self, Window otherW, int wh, int per)
+
+ Constrains this edge or dimension to be to a percentage of the given
+ window, with an optional margin.
+ """
+ return _core_.IndividualLayoutConstraint_PercentOf(*args, **kwargs)
+
+ def Absolute(*args, **kwargs):
+ """
+ Absolute(self, int val)
+
+ Constrains this edge or dimension to be the given absolute value.
+ """
+ return _core_.IndividualLayoutConstraint_Absolute(*args, **kwargs)
+
+ def Unconstrained(*args, **kwargs):
+ """
+ Unconstrained(self)
+
+ Sets this edge or dimension to be unconstrained, that is, dependent on
+ other edges and dimensions from which this value can be deduced.
+ """
+ return _core_.IndividualLayoutConstraint_Unconstrained(*args, **kwargs)
+
+ def AsIs(*args, **kwargs):
+ """
+ AsIs(self)
+
+ Sets this edge or constraint to be whatever the window's value is at
+ the moment. If either of the width and height constraints are *as is*,
+ the window will not be resized, but moved instead. This is important
+ when considering panel items which are intended to have a default
+ size, such as a button, which may take its size from the size of the
+ button label.
+ """
+ return _core_.IndividualLayoutConstraint_AsIs(*args, **kwargs)
+
+ def GetOtherWindow(*args, **kwargs):
+ """GetOtherWindow(self) -> Window"""
+ return _core_.IndividualLayoutConstraint_GetOtherWindow(*args, **kwargs)
+
+ def GetMyEdge(*args, **kwargs):
+ """GetMyEdge(self) -> int"""
+ return _core_.IndividualLayoutConstraint_GetMyEdge(*args, **kwargs)
+
+ def SetEdge(*args, **kwargs):
+ """SetEdge(self, int which)"""
+ return _core_.IndividualLayoutConstraint_SetEdge(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, int v)"""
+ return _core_.IndividualLayoutConstraint_SetValue(*args, **kwargs)
+
+ def GetMargin(*args, **kwargs):
+ """GetMargin(self) -> int"""
+ return _core_.IndividualLayoutConstraint_GetMargin(*args, **kwargs)
+
+ def SetMargin(*args, **kwargs):
+ """SetMargin(self, int m)"""
+ return _core_.IndividualLayoutConstraint_SetMargin(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> int"""
+ return _core_.IndividualLayoutConstraint_GetValue(*args, **kwargs)
+
+ def GetPercent(*args, **kwargs):
+ """GetPercent(self) -> int"""
+ return _core_.IndividualLayoutConstraint_GetPercent(*args, **kwargs)
+
+ def GetOtherEdge(*args, **kwargs):
+ """GetOtherEdge(self) -> int"""
+ return _core_.IndividualLayoutConstraint_GetOtherEdge(*args, **kwargs)
+
+ def GetDone(*args, **kwargs):
+ """GetDone(self) -> bool"""
+ return _core_.IndividualLayoutConstraint_GetDone(*args, **kwargs)
+
+ def SetDone(*args, **kwargs):
+ """SetDone(self, bool d)"""
+ return _core_.IndividualLayoutConstraint_SetDone(*args, **kwargs)
+
+ def GetRelationship(*args, **kwargs):
+ """GetRelationship(self) -> int"""
+ return _core_.IndividualLayoutConstraint_GetRelationship(*args, **kwargs)
+
+ def SetRelationship(*args, **kwargs):
+ """SetRelationship(self, int r)"""
+ return _core_.IndividualLayoutConstraint_SetRelationship(*args, **kwargs)
+
+ def ResetIfWin(*args, **kwargs):
+ """
+ ResetIfWin(self, Window otherW) -> bool
+
+ Reset constraint if it mentions otherWin
+ """
+ return _core_.IndividualLayoutConstraint_ResetIfWin(*args, **kwargs)
+
+ def SatisfyConstraint(*args, **kwargs):
+ """
+ SatisfyConstraint(self, LayoutConstraints constraints, Window win) -> bool
+
+ Try to satisfy constraint
+ """
+ return _core_.IndividualLayoutConstraint_SatisfyConstraint(*args, **kwargs)
+
+ def GetEdge(*args, **kwargs):
+ """
+ GetEdge(self, int which, Window thisWin, Window other) -> int
+
+ Get the value of this edge or dimension, or if this
+ is not determinable, -1.
+ """
+ return _core_.IndividualLayoutConstraint_GetEdge(*args, **kwargs)
+
+ Done = property(GetDone,SetDone,doc="See `GetDone` and `SetDone`")
+ Margin = property(GetMargin,SetMargin,doc="See `GetMargin` and `SetMargin`")
+ MyEdge = property(GetMyEdge,doc="See `GetMyEdge`")
+ OtherEdge = property(GetOtherEdge,doc="See `GetOtherEdge`")
+ OtherWindow = property(GetOtherWindow,doc="See `GetOtherWindow`")
+ Percent = property(GetPercent,doc="See `GetPercent`")
+ Relationship = property(GetRelationship,SetRelationship,doc="See `GetRelationship` and `SetRelationship`")
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_core_.IndividualLayoutConstraint_swigregister(IndividualLayoutConstraint)
+
+class LayoutConstraints(Object):
+ """
+ **Note:** constraints are now deprecated and you should use sizers
+ instead.
+
+ Objects of this class can be associated with a window to define its
+ layout constraints, with respect to siblings or its parent.
+
+ The class consists of the following eight constraints of class
+ wx.IndividualLayoutConstraint, some or all of which should be accessed
+ directly to set the appropriate constraints.
+
+ * left: represents the left hand edge of the window
+ * right: represents the right hand edge of the window
+ * top: represents the top edge of the window
+ * bottom: represents the bottom edge of the window
+ * width: represents the width of the window
+ * height: represents the height of the window
+ * centreX: represents the horizontal centre point of the window
+ * centreY: represents the vertical centre point of the window
+
+ Most constraints are initially set to have the relationship
+ wxUnconstrained, which means that their values should be calculated by
+ looking at known constraints. The exceptions are width and height,
+ which are set to wxAsIs to ensure that if the user does not specify a
+ constraint, the existing width and height will be used, to be
+ compatible with panel items which often have take a default size. If
+ the constraint is ``wx.AsIs``, the dimension will not be changed.
+
+ :see: `wx.IndividualLayoutConstraint`, `wx.Window.SetConstraints`
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ left = property(_core_.LayoutConstraints_left_get)
+ top = property(_core_.LayoutConstraints_top_get)
+ right = property(_core_.LayoutConstraints_right_get)
+ bottom = property(_core_.LayoutConstraints_bottom_get)
+ width = property(_core_.LayoutConstraints_width_get)
+ height = property(_core_.LayoutConstraints_height_get)
+ centreX = property(_core_.LayoutConstraints_centreX_get)
+ centreY = property(_core_.LayoutConstraints_centreY_get)
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> LayoutConstraints"""
+ _core_.LayoutConstraints_swiginit(self,_core_.new_LayoutConstraints(*args, **kwargs))
+ __swig_destroy__ = _core_.delete_LayoutConstraints
+ __del__ = lambda self : None;
+ def SatisfyConstraints(*args, **kwargs):
+ """SatisfyConstraints(Window win) -> (areSatisfied, noChanges)"""
+ return _core_.LayoutConstraints_SatisfyConstraints(*args, **kwargs)
+
+ def AreSatisfied(*args, **kwargs):
+ """AreSatisfied(self) -> bool"""
+ return _core_.LayoutConstraints_AreSatisfied(*args, **kwargs)
+
+_core_.LayoutConstraints_swigregister(LayoutConstraints)
+
+#---------------------------------------------------------------------------
+
+COL_WIDTH_DEFAULT = _core_.COL_WIDTH_DEFAULT
+COL_WIDTH_AUTOSIZE = _core_.COL_WIDTH_AUTOSIZE
+COL_RESIZABLE = _core_.COL_RESIZABLE
+COL_SORTABLE = _core_.COL_SORTABLE
+COL_REORDERABLE = _core_.COL_REORDERABLE
+COL_HIDDEN = _core_.COL_HIDDEN
+COL_DEFAULT_FLAGS = _core_.COL_DEFAULT_FLAGS
+class HeaderColumn(object):
+ """Proxy of C++ HeaderColumn class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _core_.delete_HeaderColumn
+ __del__ = lambda self : None;
+ def GetTitle(*args, **kwargs):
+ """GetTitle(self) -> String"""
+ return _core_.HeaderColumn_GetTitle(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self) -> Bitmap"""
+ return _core_.HeaderColumn_GetBitmap(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _core_.HeaderColumn_GetWidth(*args, **kwargs)
+
+ def GetMinWidth(*args, **kwargs):
+ """GetMinWidth(self) -> int"""
+ return _core_.HeaderColumn_GetMinWidth(*args, **kwargs)
+
+ def GetAlignment(*args, **kwargs):
+ """GetAlignment(self) -> int"""
+ return _core_.HeaderColumn_GetAlignment(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _core_.HeaderColumn_GetFlags(*args, **kwargs)
+
+ def HasFlag(*args, **kwargs):
+ """HasFlag(self, int flag) -> bool"""
+ return _core_.HeaderColumn_HasFlag(*args, **kwargs)
+
+ def IsResizeable(*args, **kwargs):
+ """IsResizeable(self) -> bool"""
+ return _core_.HeaderColumn_IsResizeable(*args, **kwargs)
+
+ def IsSortable(*args, **kwargs):
+ """IsSortable(self) -> bool"""
+ return _core_.HeaderColumn_IsSortable(*args, **kwargs)
+
+ def IsReorderable(*args, **kwargs):
+ """IsReorderable(self) -> bool"""
+ return _core_.HeaderColumn_IsReorderable(*args, **kwargs)
+
+ def IsHidden(*args, **kwargs):
+ """IsHidden(self) -> bool"""
+ return _core_.HeaderColumn_IsHidden(*args, **kwargs)
+
+ def IsShown(*args, **kwargs):
+ """IsShown(self) -> bool"""
+ return _core_.HeaderColumn_IsShown(*args, **kwargs)
+
+ def IsSortKey(*args, **kwargs):
+ """IsSortKey(self) -> bool"""
+ return _core_.HeaderColumn_IsSortKey(*args, **kwargs)
+
+ def IsSortOrderAscending(*args, **kwargs):
+ """IsSortOrderAscending(self) -> bool"""
+ return _core_.HeaderColumn_IsSortOrderAscending(*args, **kwargs)
+
+ Title = property(GetTitle)
+ Bitmap = property(GetBitmap)
+ Width = property(GetWidth)
+ MinWidth = property(GetMinWidth)
+ Alignment = property(GetAlignment)
+ Flags = property(GetFlags)
+ Resizeable = property(IsResizeable)
+ Sortable = property(IsSortable)
+ Reorderable = property(IsReorderable)
+ Hidden = property(IsHidden)
+ Shown = property(IsShown)
+ SortOrderAscending = property(IsSortOrderAscending)
+ SortKey = property(IsSortKey)
+_core_.HeaderColumn_swigregister(HeaderColumn)
+
+class SettableHeaderColumn(HeaderColumn):
+ """Proxy of C++ SettableHeaderColumn class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def SetTitle(*args, **kwargs):
+ """SetTitle(self, String title)"""
+ return _core_.SettableHeaderColumn_SetTitle(*args, **kwargs)
+
+ def SetBitmap(*args, **kwargs):
+ """SetBitmap(self, Bitmap bitmap)"""
+ return _core_.SettableHeaderColumn_SetBitmap(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """SetWidth(self, int width)"""
+ return _core_.SettableHeaderColumn_SetWidth(*args, **kwargs)
+
+ def SetMinWidth(*args, **kwargs):
+ """SetMinWidth(self, int minWidth)"""
+ return _core_.SettableHeaderColumn_SetMinWidth(*args, **kwargs)
+
+ def SetAlignment(*args, **kwargs):
+ """SetAlignment(self, int align)"""
+ return _core_.SettableHeaderColumn_SetAlignment(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _core_.SettableHeaderColumn_SetFlags(*args, **kwargs)
+
+ def ChangeFlag(*args, **kwargs):
+ """ChangeFlag(self, int flag, bool set)"""
+ return _core_.SettableHeaderColumn_ChangeFlag(*args, **kwargs)
+
+ def SetFlag(*args, **kwargs):
+ """SetFlag(self, int flag)"""
+ return _core_.SettableHeaderColumn_SetFlag(*args, **kwargs)
+
+ def ClearFlag(*args, **kwargs):
+ """ClearFlag(self, int flag)"""
+ return _core_.SettableHeaderColumn_ClearFlag(*args, **kwargs)
+
+ def ToggleFlag(*args, **kwargs):
+ """ToggleFlag(self, int flag)"""
+ return _core_.SettableHeaderColumn_ToggleFlag(*args, **kwargs)
+
+ def SetResizeable(*args, **kwargs):
+ """SetResizeable(self, bool resizeable)"""
+ return _core_.SettableHeaderColumn_SetResizeable(*args, **kwargs)
+
+ def SetSortable(*args, **kwargs):
+ """SetSortable(self, bool sortable)"""
+ return _core_.SettableHeaderColumn_SetSortable(*args, **kwargs)
+
+ def SetReorderable(*args, **kwargs):
+ """SetReorderable(self, bool reorderable)"""
+ return _core_.SettableHeaderColumn_SetReorderable(*args, **kwargs)
+
+ def SetHidden(*args, **kwargs):
+ """SetHidden(self, bool hidden)"""
+ return _core_.SettableHeaderColumn_SetHidden(*args, **kwargs)
+
+ def UnsetAsSortKey(*args, **kwargs):
+ """UnsetAsSortKey(self)"""
+ return _core_.SettableHeaderColumn_UnsetAsSortKey(*args, **kwargs)
+
+ def SetSortOrder(*args, **kwargs):
+ """SetSortOrder(self, bool ascending)"""
+ return _core_.SettableHeaderColumn_SetSortOrder(*args, **kwargs)
+
+ def ToggleSortOrder(*args, **kwargs):
+ """ToggleSortOrder(self)"""
+ return _core_.SettableHeaderColumn_ToggleSortOrder(*args, **kwargs)
+
+ Title = property(HeaderColumn.GetTitle,SetTitle)
+ Bitmap = property(HeaderColumn.GetBitmap,SetBitmap)
+ Width = property(HeaderColumn.GetWidth,SetWidth)
+ MinWidth = property(HeaderColumn.GetMinWidth,SetMinWidth)
+ Alignment = property(HeaderColumn.GetAlignment,SetAlignment)
+ Flags = property(HeaderColumn.GetFlags,SetFlags)
+ Resizeable = property(HeaderColumn.IsResizeable,SetResizeable)
+ Sortable = property(HeaderColumn.IsSortable,SetSortable)
+ Reorderable = property(HeaderColumn.IsReorderable,SetReorderable)
+ Hidden = property(HeaderColumn.IsHidden,SetHidden)
+ SortKey = property(HeaderColumn.IsSortKey)
+_core_.SettableHeaderColumn_swigregister(SettableHeaderColumn)
+
+class HeaderColumnSimple(SettableHeaderColumn):
+ """Proxy of C++ HeaderColumnSimple class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, PyObject title_or_bitmap, int width=COL_WIDTH_DEFAULT,
+ int align=ALIGN_NOT, int flags=COL_DEFAULT_FLAGS) -> HeaderColumnSimple
+ """
+ _core_.HeaderColumnSimple_swiginit(self,_core_.new_HeaderColumnSimple(*args, **kwargs))
+_core_.HeaderColumnSimple_swigregister(HeaderColumnSimple)
+
+#---------------------------------------------------------------------------
+
+class VersionInfo(object):
+ """Proxy of C++ VersionInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String name, int major, int minor, int micro=0, String description=wxEmptyString,
+ String copyright=wxEmptyString) -> VersionInfo
+ """
+ _core_.VersionInfo_swiginit(self,_core_.new_VersionInfo(*args, **kwargs))
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _core_.VersionInfo_GetName(*args, **kwargs)
+
+ def GetMajor(*args, **kwargs):
+ """GetMajor(self) -> int"""
+ return _core_.VersionInfo_GetMajor(*args, **kwargs)
+
+ def GetMinor(*args, **kwargs):
+ """GetMinor(self) -> int"""
+ return _core_.VersionInfo_GetMinor(*args, **kwargs)
+
+ def GetMicro(*args, **kwargs):
+ """GetMicro(self) -> int"""
+ return _core_.VersionInfo_GetMicro(*args, **kwargs)
+
+ def ToString(*args, **kwargs):
+ """ToString(self) -> String"""
+ return _core_.VersionInfo_ToString(*args, **kwargs)
+
+ def GetVersionString(*args, **kwargs):
+ """GetVersionString(self) -> String"""
+ return _core_.VersionInfo_GetVersionString(*args, **kwargs)
+
+ def HasDescription(*args, **kwargs):
+ """HasDescription(self) -> bool"""
+ return _core_.VersionInfo_HasDescription(*args, **kwargs)
+
+ def GetDescription(*args, **kwargs):
+ """GetDescription(self) -> String"""
+ return _core_.VersionInfo_GetDescription(*args, **kwargs)
+
+ def HasCopyright(*args, **kwargs):
+ """HasCopyright(self) -> bool"""
+ return _core_.VersionInfo_HasCopyright(*args, **kwargs)
+
+ def GetCopyright(*args, **kwargs):
+ """GetCopyright(self) -> String"""
+ return _core_.VersionInfo_GetCopyright(*args, **kwargs)
+
+_core_.VersionInfo_swigregister(VersionInfo)
+
+#----------------------------------------------------------------------------
+
+# Use Python's bool constants if available, make some if not
+try:
+ True
+except NameError:
+ __builtins__.True = 1==1
+ __builtins__.False = 1==0
+ def bool(value): return not not value
+ __builtins__.bool = bool
+
+
+
+# workarounds for bad wxRTTI names
+__wxPyPtrTypeMap['wxGauge95'] = 'wxGauge'
+__wxPyPtrTypeMap['wxSlider95'] = 'wxSlider'
+__wxPyPtrTypeMap['wxStatusBar95'] = 'wxStatusBar'
+
+
+#----------------------------------------------------------------------------
+# Load version numbers from __version__... Ensure that major and minor
+# versions are the same for both wxPython and wxWidgets.
+
+from __version__ import *
+__version__ = VERSION_STRING
+
+assert MAJOR_VERSION == _core_.MAJOR_VERSION, "wxPython/wxWidgets version mismatch"
+assert MINOR_VERSION == _core_.MINOR_VERSION, "wxPython/wxWidgets version mismatch"
+if RELEASE_VERSION != _core_.RELEASE_VERSION:
+ import warnings
+ warnings.warn("wxPython/wxWidgets release number mismatch")
+
+
+def version():
+ """Returns a string containing version and port info"""
+ if wx.Platform == '__WXMSW__':
+ port = 'msw'
+ elif wx.Platform == '__WXMAC__':
+ if 'wxOSX-carbon' in wx.PlatformInfo:
+ port = 'osx-carbon'
+ else:
+ port = 'osx-cocoa'
+ elif wx.Platform == '__WXGTK__':
+ port = 'gtk'
+ if 'gtk2' in wx.PlatformInfo:
+ port = 'gtk2'
+ elif 'gtk3' in wx.PlatformInfo:
+ port = 'gtk3'
+ else:
+ port = '?'
+
+ return "%s %s (classic)" % (wx.VERSION_STRING, port)
+
+
+#----------------------------------------------------------------------------
+
+# Set wxPython's default string<-->unicode conversion encoding from
+# the locale, but only if Python's default hasn't been changed. (We
+# assume that if the user has customized it already then that is the
+# encoding we need to use as well.)
+#
+# The encoding selected here is used when string or unicode objects
+# need to be converted in order to pass them to wxWidgets. Please be
+# aware that the default encoding within the same locale may be
+# slightly different on different platforms. For example, please see
+# http://www.alanwood.net/demos/charsetdiffs.html for differences
+# between the common latin/roman encodings.
+
+default = _sys.getdefaultencoding()
+if default == 'ascii':
+ import locale
+ import codecs
+ try:
+ if hasattr(locale, 'getpreferredencoding'):
+ default = locale.getpreferredencoding()
+ else:
+ default = locale.getdefaultlocale()[1]
+ codecs.lookup(default)
+ except (ValueError, LookupError, TypeError):
+ default = _sys.getdefaultencoding()
+ del locale
+ del codecs
+if default:
+ wx.SetDefaultPyEncoding(default)
+del default
+
+#----------------------------------------------------------------------------
+
+class PyDeadObjectError(AttributeError):
+ pass
+
+class _wxPyDeadObject(object):
+ """
+ Instances of wx objects that are OOR capable will have their __class__
+ changed to this class when the C++ object is deleted. This should help
+ prevent crashes due to referencing a bogus C++ pointer.
+ """
+ reprStr = "wxPython wrapper for DELETED %s object! (The C++ object no longer exists.)"
+ attrStr = "The C++ part of the %s object has been deleted, attribute access no longer allowed."
+
+ def __repr__(self):
+ if not hasattr(self, "_name"):
+ self._name = "[unknown]"
+ return self.reprStr % self._name
+
+ def __getattr__(self, *args):
+ if not hasattr(self, "_name"):
+ self._name = "[unknown]"
+ raise PyDeadObjectError(self.attrStr % self._name)
+
+ def __nonzero__(self):
+ return 0
+
+
+
+class PyUnbornObjectError(AttributeError):
+ pass
+
+class _wxPyUnbornObject(object):
+ """
+ Some stock objects are created when the wx._core module is
+ imported, but their C++ instance is not created until the wx.App
+ object is created and initialized. These object instances will
+ temporarily have their __class__ changed to this class so an
+ exception will be raised if they are used before the C++ instance
+ is ready.
+ """
+
+ reprStr = "wxPython wrapper for UNBORN object! (The C++ object is not initialized yet.)"
+ attrStr = "The C++ part of this object has not been initialized, attribute access not allowed."
+
+ def __repr__(self):
+ #if not hasattr(self, "_name"):
+ # self._name = "[unknown]"
+ return self.reprStr #% self._name
+
+ def __getattr__(self, *args):
+ #if not hasattr(self, "_name"):
+ # self._name = "[unknown]"
+ raise PyUnbornObjectError(self.attrStr) # % self._name )
+
+ def __nonzero__(self):
+ return 0
+
+
+#----------------------------------------------------------------------------
+
+def CallAfter(callableObj, *args, **kw):
+ """
+ Call the specified function after the current and pending event
+ handlers have been completed. This is also good for making GUI
+ method calls from non-GUI threads. Any extra positional or
+ keyword args are passed on to the callable when it is called.
+
+ :see: `wx.CallLater`
+ """
+ assert callable(callableObj), "callableObj is not callable"
+ app = wx.GetApp()
+ assert app is not None, 'No wx.App created yet'
+
+ if not hasattr(app, "_CallAfterId"):
+ app._CallAfterId = wx.NewEventType()
+ app.Connect(-1, -1, app._CallAfterId,
+ lambda event: event.callable(*event.args, **event.kw) )
+ evt = wx.PyEvent()
+ evt.SetEventType(app._CallAfterId)
+ evt.callable = callableObj
+ evt.args = args
+ evt.kw = kw
+ wx.PostEvent(app, evt)
+
+#----------------------------------------------------------------------------
+
+
+class CallLater:
+ """
+ A convenience class for `wx.Timer`, that calls the given callable
+ object once after the given amount of milliseconds, passing any
+ positional or keyword args. The return value of the callable is
+ availbale after it has been run with the `GetResult` method.
+
+ If you don't need to get the return value or restart the timer
+ then there is no need to hold a reference to this object.
+
+ :see: `wx.CallAfter`
+ """
+
+ __RUNNING = set()
+
+ def __init__(self, millis, callableObj, *args, **kwargs):
+ assert callable(callableObj), "callableObj is not callable"
+ self.millis = millis
+ self.callable = callableObj
+ self.SetArgs(*args, **kwargs)
+ self.runCount = 0
+ self.running = False
+ self.hasRun = False
+ self.result = None
+ self.timer = None
+ self.Start()
+
+
+ def Start(self, millis=None, *args, **kwargs):
+ """
+ (Re)start the timer
+ """
+ self.hasRun = False
+ if millis is not None:
+ self.millis = millis
+ if args or kwargs:
+ self.SetArgs(*args, **kwargs)
+ self.Stop()
+ self.timer = wx.PyTimer(self.Notify)
+ self.timer.Start(self.millis, wx.TIMER_ONE_SHOT)
+ self.running = True
+ self.__RUNNING.add(self)
+ Restart = Start
+
+
+ def Stop(self):
+ """
+ Stop and destroy the timer.
+ """
+ if self.timer is not None:
+ self.timer.Stop()
+ self.timer = None
+ self.__RUNNING.discard(self)
+
+
+ def GetInterval(self):
+ if self.timer is not None:
+ return self.timer.GetInterval()
+ else:
+ return 0
+
+
+ def IsRunning(self):
+ return self.timer is not None and self.timer.IsRunning()
+
+
+ def SetArgs(self, *args, **kwargs):
+ """
+ (Re)set the args passed to the callable object. This is
+ useful in conjunction with Restart if you want to schedule a
+ new call to the same callable object but with different
+ parameters.
+ """
+ self.args = args
+ self.kwargs = kwargs
+
+
+ def HasRun(self):
+ return self.hasRun
+
+
+ def GetResult(self):
+ return self.result
+
+
+ def Notify(self):
+ """
+ The timer has expired so call the callable.
+ """
+ if self.callable and getattr(self.callable, 'im_self', True):
+ self.runCount += 1
+ self.running = False
+ self.result = self.callable(*self.args, **self.kwargs)
+ self.hasRun = True
+ if not self.running:
+ # if it wasn't restarted, then cleanup
+ wx.CallAfter(self.Stop)
+
+ Interval = property(GetInterval)
+ Result = property(GetResult)
+
+
+class FutureCall(CallLater):
+ """A compatibility alias for `CallLater`."""
+
+#----------------------------------------------------------------------------
+# Control which items in this module should be documented by epydoc.
+# We allow only classes and functions, which will help reduce the size
+# of the docs by filtering out the zillions of constants, EVT objects,
+# and etc that don't make much sense by themselves, but are instead
+# documented (or will be) as part of the classes/functions/methods
+# where they should be used.
+
+class __DocFilter:
+ """
+ A filter for epydoc that only allows non-Ptr classes and
+ functions, in order to reduce the clutter in the API docs.
+ """
+ def __init__(self, globals):
+ self._globals = globals
+
+ def __call__(self, name):
+ import types
+ obj = self._globals.get(name, None)
+
+ # only document classes and function
+ if type(obj) not in [type, types.ClassType, types.FunctionType, types.BuiltinFunctionType]:
+ return False
+
+ # skip other things that are private or will be documented as part of somethign else
+ if name.startswith('_') or name.startswith('EVT') or name.endswith('_swigregister') or name.endswith('Ptr') :
+ return False
+
+ # skip functions that are duplicates of static functions in a class
+ if name.find('_') != -1:
+ cls = self._globals.get(name.split('_')[0], None)
+ methname = name.split('_')[1]
+ if hasattr(cls, methname) and type(getattr(cls, methname)) is types.FunctionType:
+ return False
+
+ return True
+
+#----------------------------------------------------------------------------
+#----------------------------------------------------------------------------
+
+# Import other modules in this package that should show up in the
+# "core" wx namespace
+from _gdi import *
+from _windows import *
+from _controls import *
+from _misc import *
+
+#----------------------------------------------------------------------------
+#----------------------------------------------------------------------------
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_core_.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_core_.pyd
new file mode 100644
index 0000000..8d17b45
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_core_.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_dataview.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_dataview.pyd
new file mode 100644
index 0000000..10c0004
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_dataview.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_gdi.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/_gdi.py
new file mode 100644
index 0000000..f1c688a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_gdi.py
@@ -0,0 +1,8500 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+import _gdi_
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+wx = _core
+#---------------------------------------------------------------------------
+
+class GDIObject(_core.Object):
+ """Proxy of C++ GDIObject class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _gdi_.delete_GDIObject
+ __del__ = lambda self : None;
+ def IsNull(*args, **kwargs):
+ """IsNull(self) -> bool"""
+ return _gdi_.GDIObject_IsNull(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.GDIObject_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+_gdi_.GDIObject_swigregister(GDIObject)
+
+#---------------------------------------------------------------------------
+
+C2S_NAME = _gdi_.C2S_NAME
+C2S_CSS_SYNTAX = _gdi_.C2S_CSS_SYNTAX
+C2S_HTML_SYNTAX = _gdi_.C2S_HTML_SYNTAX
+ALPHA_TRANSPARENT = _gdi_.ALPHA_TRANSPARENT
+ALPHA_OPAQUE = _gdi_.ALPHA_OPAQUE
+class Colour(_core.Object):
+ """
+ A colour is an object representing a combination of Red, Green, and
+ Blue (RGB) intensity values, and is used to determine drawing colours,
+ window colours, etc. Valid RGB values are in the range 0 to 255.
+
+ In wxPython there are typemaps that will automatically convert from a
+ colour name, from a '#RRGGBB' colour hex value string, or from a 3 or 4
+ integer tuple to a wx.Colour object when calling C++ methods that
+ expect a wxColour. This means that the following are all
+ equivallent::
+
+ win.SetBackgroundColour(wxColour(0,0,255))
+ win.SetBackgroundColour('BLUE')
+ win.SetBackgroundColour('#0000FF')
+ win.SetBackgroundColour((0,0,255))
+
+ In addition to the RGB values, the alpha transparency can optionally
+ be set. This is supported by the typemaps as well as the wx.Colour
+ constructors and setters. (The alpha value is ignored in many places
+ that take a wx.Colour object, but it is honored in things like wx.GCDC
+ or wx.GraphicsContext.) Adding an alpha value of 0xC0 (192) to the
+ above samples looks like this:
+
+ win.SetBackgroundColour(wxColour(0,0,255,192))
+ win.SetBackgroundColour('BLUE:C0')
+ win.SetBackgroundColour('#0000FFC0')
+ win.SetBackgroundColour((0,0,255,192))
+
+ Additional colour names and their coresponding values can be added
+ using `wx.ColourDatabase`. Also see `wx.lib.colourdb` for a large set
+ of colour names and values. Various system colours (as set in the
+ user's system preferences or control panel) can be retrieved with
+ `wx.SystemSettings.GetColour`.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, byte red=0, byte green=0, byte blue=0, byte alpha=ALPHA_OPAQUE) -> Colour
+
+ Constructs a colour from red, green, blue and alpha values.
+
+ :see: Alternate constructors `wx.NamedColour`, `wx.ColourRGB` and `MacThemeColour`.
+
+ """
+ _gdi_.Colour_swiginit(self,_gdi_.new_Colour(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Colour
+ __del__ = lambda self : None;
+ def Red(*args, **kwargs):
+ """
+ Red(self) -> byte
+
+ Returns the red intensity.
+ """
+ return _gdi_.Colour_Red(*args, **kwargs)
+
+ def Green(*args, **kwargs):
+ """
+ Green(self) -> byte
+
+ Returns the green intensity.
+ """
+ return _gdi_.Colour_Green(*args, **kwargs)
+
+ def Blue(*args, **kwargs):
+ """
+ Blue(self) -> byte
+
+ Returns the blue intensity.
+ """
+ return _gdi_.Colour_Blue(*args, **kwargs)
+
+ def Alpha(*args, **kwargs):
+ """
+ Alpha(self) -> byte
+
+ Returns the Alpha value.
+ """
+ return _gdi_.Colour_Alpha(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """
+ IsOk(self) -> bool
+
+ Returns True if the colour object is valid (the colour has been
+ initialised with RGB values).
+ """
+ return _gdi_.Colour_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def Set(*args, **kwargs):
+ """
+ Set(self, byte red, byte green, byte blue, byte alpha=ALPHA_OPAQUE)
+
+ Sets the RGB intensity values.
+ """
+ return _gdi_.Colour_Set(*args, **kwargs)
+
+ def SetFromString(self, colourName):
+ """
+ Sets the RGB intensity values using a colour name listed in
+ ``wx.TheColourDatabase``, or any string format supported by
+ the wxColour typemaps.
+ """
+ c = wx.NamedColour(colourName)
+ self.Set(c.red, c.green, c.blue, c.alpha)
+ SetFromName = SetFromString
+
+ def GetAsString(*args, **kwargs):
+ """
+ GetAsString(self, long flags=wxC2S_NAME|wxC2S_CSS_SYNTAX) -> String
+
+ Return the colour as a string. Acceptable flags are:
+
+ =================== ==================================
+ wx.C2S_NAME return colour name, when possible
+ wx.C2S_CSS_SYNTAX return colour in rgb(r,g,b) syntax
+ wx.C2S_HTML_SYNTAX return colour in #rrggbb syntax
+ =================== ==================================
+ """
+ return _gdi_.Colour_GetAsString(*args, **kwargs)
+
+ def SetRGB(*args, **kwargs):
+ """
+ SetRGB(self, unsigned int colRGB)
+
+ Sets the RGB colour values from a single 32 bit value.
+
+ The argument colRGB should be of the form 0x00BBGGRR and where 0xRR,
+ 0xGG and 0xBB are the values of the red, green and blue components.
+ """
+ return _gdi_.Colour_SetRGB(*args, **kwargs)
+
+ def SetRGBA(*args, **kwargs):
+ """
+ SetRGBA(self, unsigned int colRGBA)
+
+ Sets the RGBA colour values from a single 32 bit value.
+
+ The argument colRGBA should be of the form 0xAABBGGRR where 0xRR,
+ 0xGG, 0xBB and 0xAA are the values of the red, green, blue and alpha
+ components.
+ """
+ return _gdi_.Colour_SetRGBA(*args, **kwargs)
+
+ def GetRGBA(*args, **kwargs):
+ """GetRGBA(self) -> unsigned int"""
+ return _gdi_.Colour_GetRGBA(*args, **kwargs)
+
+ def GetPixel(*args, **kwargs):
+ """
+ GetPixel(self) -> long
+
+ Returns a pixel value which is platform-dependent. On Windows, a
+ COLORREF is returned. On X, an allocated pixel value is returned. -1
+ is returned if the pixel is invalid (on X, unallocated).
+ """
+ return _gdi_.Colour_GetPixel(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Compare colours for equality.
+ """
+ return _gdi_.Colour___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Compare colours for inequality.
+ """
+ return _gdi_.Colour___ne__(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get(self, bool includeAlpha=False) -> (r,g,b) or (r,g,b,a)
+
+ Returns the RGB intensity values as a tuple, optionally the alpha value as well.
+ """
+ return _gdi_.Colour_Get(*args, **kwargs)
+
+ def GetRGB(*args):
+ """
+ GetRGB(self) -> unsigned int
+ GetRGB(self) -> unsigned long
+
+ Return the colour as a packed RGB value
+ """
+ return _gdi_.Colour_GetRGB(*args)
+
+ asTuple = wx.deprecated(Get, "asTuple is deprecated, use `Get` instead")
+ def __str__(self): return str(self.Get(True))
+
+ # help() can access the stock colors before they are created,
+ # so make sure there is a this attribute before calling any wrapper method.
+ def __repr__(self):
+ if hasattr(self, 'this'):
+ return 'wx.Colour' + str(self.Get(True))
+ else:
+ return 'wx.Colour()'
+
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __nonzero__(self): return self.IsOk()
+ __safe_for_unpickling__ = True
+ def __reduce__(self): return (Colour, self.Get(True))
+
+ Pixel = property(GetPixel,doc="See `GetPixel`")
+ RGB = property(GetRGB,SetRGB,doc="See `GetRGB` and `SetRGB`")
+ red = property(Red)
+ green = property(Green)
+ blue = property(Blue)
+ alpha = property(Alpha)
+_gdi_.Colour_swigregister(Colour)
+
+def NamedColour(*args, **kwargs):
+ """
+ NamedColour(String colourName) -> Colour
+
+ Constructs a colour object using a colour name listed in
+ ``wx.TheColourDatabase``, or any string format supported by the
+ wxColour typemaps.
+ """
+ val = _gdi_.new_NamedColour(*args, **kwargs)
+ return val
+
+def ColourRGB(*args, **kwargs):
+ """
+ ColourRGB(unsigned long colRGB) -> Colour
+
+ Constructs a colour from a packed RGB value.
+ """
+ val = _gdi_.new_ColourRGB(*args, **kwargs)
+ return val
+
+def MacThemeColour(*args, **kwargs):
+ """
+ MacThemeColour(int themeBrushID) -> Colour
+
+ Creates a color (or pattern) from a Mac theme brush ID. Raises a
+ NotImplemented exception on other platforms.
+ """
+ val = _gdi_.new_MacThemeColour(*args, **kwargs)
+ return val
+
+class Palette(GDIObject):
+ """Proxy of C++ Palette class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, wxArrayInt red, wxArrayInt green, wxArrayInt blue) -> Palette"""
+ _gdi_.Palette_swiginit(self,_gdi_.new_Palette(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Palette
+ __del__ = lambda self : None;
+ def GetPixel(*args, **kwargs):
+ """GetPixel(self, byte red, byte green, byte blue) -> int"""
+ return _gdi_.Palette_GetPixel(*args, **kwargs)
+
+ def GetRGB(*args, **kwargs):
+ """GetRGB(self, int pixel) -> (success, R,G,B)"""
+ return _gdi_.Palette_GetRGB(*args, **kwargs)
+
+ def GetColoursCount(*args, **kwargs):
+ """GetColoursCount(self) -> int"""
+ return _gdi_.Palette_GetColoursCount(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.Palette_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def __nonzero__(self): return self.IsOk()
+ ColoursCount = property(GetColoursCount,doc="See `GetColoursCount`")
+_gdi_.Palette_swigregister(Palette)
+
+#---------------------------------------------------------------------------
+
+PENSTYLE_INVALID = _gdi_.PENSTYLE_INVALID
+PENSTYLE_SOLID = _gdi_.PENSTYLE_SOLID
+PENSTYLE_DOT = _gdi_.PENSTYLE_DOT
+PENSTYLE_LONG_DASH = _gdi_.PENSTYLE_LONG_DASH
+PENSTYLE_SHORT_DASH = _gdi_.PENSTYLE_SHORT_DASH
+PENSTYLE_DOT_DASH = _gdi_.PENSTYLE_DOT_DASH
+PENSTYLE_USER_DASH = _gdi_.PENSTYLE_USER_DASH
+PENSTYLE_TRANSPARENT = _gdi_.PENSTYLE_TRANSPARENT
+PENSTYLE_STIPPLE_MASK_OPAQUE = _gdi_.PENSTYLE_STIPPLE_MASK_OPAQUE
+PENSTYLE_STIPPLE_MASK = _gdi_.PENSTYLE_STIPPLE_MASK
+PENSTYLE_STIPPLE = _gdi_.PENSTYLE_STIPPLE
+PENSTYLE_BDIAGONAL_HATCH = _gdi_.PENSTYLE_BDIAGONAL_HATCH
+PENSTYLE_CROSSDIAG_HATCH = _gdi_.PENSTYLE_CROSSDIAG_HATCH
+PENSTYLE_FDIAGONAL_HATCH = _gdi_.PENSTYLE_FDIAGONAL_HATCH
+PENSTYLE_CROSS_HATCH = _gdi_.PENSTYLE_CROSS_HATCH
+PENSTYLE_HORIZONTAL_HATCH = _gdi_.PENSTYLE_HORIZONTAL_HATCH
+PENSTYLE_VERTICAL_HATCH = _gdi_.PENSTYLE_VERTICAL_HATCH
+PENSTYLE_FIRST_HATCH = _gdi_.PENSTYLE_FIRST_HATCH
+PENSTYLE_LAST_HATCH = _gdi_.PENSTYLE_LAST_HATCH
+JOIN_INVALID = _gdi_.JOIN_INVALID
+JOIN_BEVEL = _gdi_.JOIN_BEVEL
+JOIN_MITER = _gdi_.JOIN_MITER
+JOIN_ROUND = _gdi_.JOIN_ROUND
+CAP_INVALID = _gdi_.CAP_INVALID
+CAP_ROUND = _gdi_.CAP_ROUND
+CAP_PROJECTING = _gdi_.CAP_PROJECTING
+CAP_BUTT = _gdi_.CAP_BUTT
+class Pen(GDIObject):
+ """Proxy of C++ Pen class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Colour colour, int width=1, int style=SOLID) -> Pen"""
+ _gdi_.Pen_swiginit(self,_gdi_.new_Pen(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Pen
+ __del__ = lambda self : None;
+ def GetCap(*args, **kwargs):
+ """GetCap(self) -> int"""
+ return _gdi_.Pen_GetCap(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """GetColour(self) -> Colour"""
+ return _gdi_.Pen_GetColour(*args, **kwargs)
+
+ def GetJoin(*args, **kwargs):
+ """GetJoin(self) -> int"""
+ return _gdi_.Pen_GetJoin(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self) -> int"""
+ return _gdi_.Pen_GetStyle(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _gdi_.Pen_GetWidth(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.Pen_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def SetCap(*args, **kwargs):
+ """SetCap(self, int cap_style)"""
+ return _gdi_.Pen_SetCap(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """SetColour(self, Colour colour)"""
+ return _gdi_.Pen_SetColour(*args, **kwargs)
+
+ def SetJoin(*args, **kwargs):
+ """SetJoin(self, int join_style)"""
+ return _gdi_.Pen_SetJoin(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """SetStyle(self, int style)"""
+ return _gdi_.Pen_SetStyle(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """SetWidth(self, int width)"""
+ return _gdi_.Pen_SetWidth(*args, **kwargs)
+
+ def SetDashes(*args, **kwargs):
+ """SetDashes(self, int dashes)"""
+ return _gdi_.Pen_SetDashes(*args, **kwargs)
+
+ def GetDashes(*args, **kwargs):
+ """GetDashes(self) -> PyObject"""
+ return _gdi_.Pen_GetDashes(*args, **kwargs)
+
+ def _SetDashes(*args, **kwargs):
+ """_SetDashes(self, PyObject _self, PyObject pyDashes)"""
+ return _gdi_.Pen__SetDashes(*args, **kwargs)
+
+ def SetDashes(self, dashes):
+ """
+ Associate a list of dash lengths with the Pen.
+ """
+ self._SetDashes(self, dashes)
+
+ def GetDashCount(*args, **kwargs):
+ """GetDashCount(self) -> int"""
+ return _gdi_.Pen_GetDashCount(*args, **kwargs)
+
+ DashCount = property(GetDashCount,doc="See `GetDashCount`")
+ def GetStipple(*args, **kwargs):
+ """GetStipple(self) -> Bitmap"""
+ return _gdi_.Pen_GetStipple(*args, **kwargs)
+
+ def SetStipple(*args, **kwargs):
+ """SetStipple(self, Bitmap stipple)"""
+ return _gdi_.Pen_SetStipple(*args, **kwargs)
+
+ Stipple = property(GetStipple,SetStipple,doc="See `GetStipple` and `SetStipple`")
+ def IsTransparent(*args, **kwargs):
+ """IsTransparent(self) -> bool"""
+ return _gdi_.Pen_IsTransparent(*args, **kwargs)
+
+ def IsNonTransparent(*args, **kwargs):
+ """IsNonTransparent(self) -> bool"""
+ return _gdi_.Pen_IsNonTransparent(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """__eq__(self, Pen other) -> bool"""
+ return _gdi_.Pen___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """__ne__(self, Pen other) -> bool"""
+ return _gdi_.Pen___ne__(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ Cap = property(GetCap,SetCap,doc="See `GetCap` and `SetCap`")
+ Colour = property(GetColour,SetColour,doc="See `GetColour` and `SetColour`")
+ Dashes = property(GetDashes,SetDashes,doc="See `GetDashes` and `SetDashes`")
+ Join = property(GetJoin,SetJoin,doc="See `GetJoin` and `SetJoin`")
+ Style = property(GetStyle,SetStyle,doc="See `GetStyle` and `SetStyle`")
+ Width = property(GetWidth,SetWidth,doc="See `GetWidth` and `SetWidth`")
+_gdi_.Pen_swigregister(Pen)
+
+#---------------------------------------------------------------------------
+
+BRUSHSTYLE_INVALID = _gdi_.BRUSHSTYLE_INVALID
+BRUSHSTYLE_SOLID = _gdi_.BRUSHSTYLE_SOLID
+BRUSHSTYLE_TRANSPARENT = _gdi_.BRUSHSTYLE_TRANSPARENT
+BRUSHSTYLE_STIPPLE_MASK_OPAQUE = _gdi_.BRUSHSTYLE_STIPPLE_MASK_OPAQUE
+BRUSHSTYLE_STIPPLE_MASK = _gdi_.BRUSHSTYLE_STIPPLE_MASK
+BRUSHSTYLE_STIPPLE = _gdi_.BRUSHSTYLE_STIPPLE
+BRUSHSTYLE_BDIAGONAL_HATCH = _gdi_.BRUSHSTYLE_BDIAGONAL_HATCH
+BRUSHSTYLE_CROSSDIAG_HATCH = _gdi_.BRUSHSTYLE_CROSSDIAG_HATCH
+BRUSHSTYLE_FDIAGONAL_HATCH = _gdi_.BRUSHSTYLE_FDIAGONAL_HATCH
+BRUSHSTYLE_CROSS_HATCH = _gdi_.BRUSHSTYLE_CROSS_HATCH
+BRUSHSTYLE_HORIZONTAL_HATCH = _gdi_.BRUSHSTYLE_HORIZONTAL_HATCH
+BRUSHSTYLE_VERTICAL_HATCH = _gdi_.BRUSHSTYLE_VERTICAL_HATCH
+BRUSHSTYLE_FIRST_HATCH = _gdi_.BRUSHSTYLE_FIRST_HATCH
+BRUSHSTYLE_LAST_HATCH = _gdi_.BRUSHSTYLE_LAST_HATCH
+class Brush(GDIObject):
+ """
+ A brush is a drawing tool for filling in areas. It is used for
+ painting the background of rectangles, ellipses, etc. when drawing on
+ a `wx.DC`. It has a colour and a style.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Colour colour, int style=SOLID) -> Brush
+
+ Constructs a brush from a `wx.Colour` object and a style.
+ """
+ _gdi_.Brush_swiginit(self,_gdi_.new_Brush(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Brush
+ __del__ = lambda self : None;
+ def SetColour(*args, **kwargs):
+ """
+ SetColour(self, Colour col)
+
+ Set the brush's `wx.Colour`.
+ """
+ return _gdi_.Brush_SetColour(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """
+ SetStyle(self, int style)
+
+ Sets the style of the brush. See `__init__` for a listing of styles.
+ """
+ return _gdi_.Brush_SetStyle(*args, **kwargs)
+
+ def SetStipple(*args, **kwargs):
+ """
+ SetStipple(self, Bitmap stipple)
+
+ Sets the stipple `wx.Bitmap`.
+ """
+ return _gdi_.Brush_SetStipple(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """
+ GetColour(self) -> Colour
+
+ Returns the `wx.Colour` of the brush.
+ """
+ return _gdi_.Brush_GetColour(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """
+ GetStyle(self) -> int
+
+ Returns the style of the brush. See `__init__` for a listing of
+ styles.
+ """
+ return _gdi_.Brush_GetStyle(*args, **kwargs)
+
+ def GetStipple(*args, **kwargs):
+ """
+ GetStipple(self) -> Bitmap
+
+ Returns the stiple `wx.Bitmap` of the brush. If the brush does not
+ have a wx.STIPPLE style, then the return value may be non-None but an
+ uninitialised bitmap (`wx.Bitmap.Ok` returns False).
+ """
+ return _gdi_.Brush_GetStipple(*args, **kwargs)
+
+ def IsHatch(*args, **kwargs):
+ """
+ IsHatch(self) -> bool
+
+ Is the current style a hatch type?
+ """
+ return _gdi_.Brush_IsHatch(*args, **kwargs)
+
+ def IsTransparent(*args, **kwargs):
+ """IsTransparent(self) -> bool"""
+ return _gdi_.Brush_IsTransparent(*args, **kwargs)
+
+ def IsNonTransparent(*args, **kwargs):
+ """IsNonTransparent(self) -> bool"""
+ return _gdi_.Brush_IsNonTransparent(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """
+ IsOk(self) -> bool
+
+ Returns True if the brush is initialised and valid.
+ """
+ return _gdi_.Brush_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def __nonzero__(self): return self.IsOk()
+ Colour = property(GetColour,SetColour,doc="See `GetColour` and `SetColour`")
+ Stipple = property(GetStipple,SetStipple,doc="See `GetStipple` and `SetStipple`")
+ Style = property(GetStyle,SetStyle,doc="See `GetStyle` and `SetStyle`")
+_gdi_.Brush_swigregister(Brush)
+
+def BrushFromBitmap(*args, **kwargs):
+ """
+ BrushFromBitmap(Bitmap stippleBitmap) -> Brush
+
+ Constructs a stippled brush using a bitmap.
+ """
+ val = _gdi_.new_BrushFromBitmap(*args, **kwargs)
+ return val
+
+BitmapBufferFormat_RGB = _gdi_.BitmapBufferFormat_RGB
+BitmapBufferFormat_RGBA = _gdi_.BitmapBufferFormat_RGBA
+BitmapBufferFormat_RGB32 = _gdi_.BitmapBufferFormat_RGB32
+BitmapBufferFormat_ARGB32 = _gdi_.BitmapBufferFormat_ARGB32
+BITMAP_SCREEN_DEPTH = _gdi_.BITMAP_SCREEN_DEPTH
+class Bitmap(GDIObject):
+ """
+ The wx.Bitmap class encapsulates the concept of a platform-dependent
+ bitmap. It can be either monochrome or colour, and either loaded from
+ a file or created dynamically. A bitmap can be selected into a memory
+ device context (instance of `wx.MemoryDC`). This enables the bitmap to
+ be copied to a window or memory device context using `wx.DC.Blit`, or
+ to be used as a drawing surface.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String name, int type=BITMAP_TYPE_ANY) -> Bitmap
+
+ Loads a bitmap from a file.
+ """
+ _gdi_.Bitmap_swiginit(self,_gdi_.new_Bitmap(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Bitmap
+ __del__ = lambda self : None;
+ def GetHandle(*args, **kwargs):
+ """GetHandle(self) -> long"""
+ return _gdi_.Bitmap_GetHandle(*args, **kwargs)
+
+ def SetHandle(*args, **kwargs):
+ """SetHandle(self, long handle)"""
+ return _gdi_.Bitmap_SetHandle(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.Bitmap_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def GetWidth(*args, **kwargs):
+ """
+ GetWidth(self) -> int
+
+ Gets the width of the bitmap in pixels.
+ """
+ return _gdi_.Bitmap_GetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """
+ GetHeight(self) -> int
+
+ Gets the height of the bitmap in pixels.
+ """
+ return _gdi_.Bitmap_GetHeight(*args, **kwargs)
+
+ def GetDepth(*args, **kwargs):
+ """
+ GetDepth(self) -> int
+
+ Gets the colour depth of the bitmap. A value of 1 indicates a
+ monochrome bitmap.
+ """
+ return _gdi_.Bitmap_GetDepth(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """
+ GetSize(self) -> Size
+
+ Get the size of the bitmap.
+ """
+ return _gdi_.Bitmap_GetSize(*args, **kwargs)
+
+ def ConvertToImage(*args, **kwargs):
+ """
+ ConvertToImage(self) -> Image
+
+ Creates a platform-independent image from a platform-dependent
+ bitmap. This preserves mask information so that bitmaps and images can
+ be converted back and forth without loss in that respect.
+ """
+ return _gdi_.Bitmap_ConvertToImage(*args, **kwargs)
+
+ def GetMask(*args, **kwargs):
+ """
+ GetMask(self) -> Mask
+
+ Gets the associated mask (if any) which may have been loaded from a
+ file or explpicitly set for the bitmap.
+
+ :see: `SetMask`, `wx.Mask`
+
+ """
+ return _gdi_.Bitmap_GetMask(*args, **kwargs)
+
+ def SetMask(*args, **kwargs):
+ """
+ SetMask(self, Mask mask)
+
+ Sets the mask for this bitmap.
+
+ :see: `GetMask`, `wx.Mask`
+
+ """
+ return _gdi_.Bitmap_SetMask(*args, **kwargs)
+
+ def SetMaskColour(*args, **kwargs):
+ """
+ SetMaskColour(self, Colour colour)
+
+ Create a Mask based on a specified colour in the Bitmap.
+ """
+ return _gdi_.Bitmap_SetMaskColour(*args, **kwargs)
+
+ def GetSubBitmap(*args, **kwargs):
+ """
+ GetSubBitmap(self, Rect rect) -> Bitmap
+
+ Returns a sub-bitmap of the current one as long as the rect belongs
+ entirely to the bitmap. This function preserves bit depth and mask
+ information.
+ """
+ return _gdi_.Bitmap_GetSubBitmap(*args, **kwargs)
+
+ def ConvertToDisabled(*args, **kwargs):
+ """ConvertToDisabled(self, byte brightness=255) -> Bitmap"""
+ return _gdi_.Bitmap_ConvertToDisabled(*args, **kwargs)
+
+ def SaveFile(*args, **kwargs):
+ """
+ SaveFile(self, String name, int type, Palette palette=None) -> bool
+
+ Saves a bitmap in the named file. See `__init__` for a description of
+ the ``type`` parameter.
+ """
+ return _gdi_.Bitmap_SaveFile(*args, **kwargs)
+
+ def LoadFile(*args, **kwargs):
+ """
+ LoadFile(self, String name, int type) -> bool
+
+ Loads a bitmap from a file. See `__init__` for a description of the
+ ``type`` parameter.
+ """
+ return _gdi_.Bitmap_LoadFile(*args, **kwargs)
+
+ def GetPalette(*args, **kwargs):
+ """GetPalette(self) -> Palette"""
+ return _gdi_.Bitmap_GetPalette(*args, **kwargs)
+
+ def SetPalette(*args, **kwargs):
+ """SetPalette(self, Palette palette)"""
+ return _gdi_.Bitmap_SetPalette(*args, **kwargs)
+
+ def CopyFromIcon(*args, **kwargs):
+ """CopyFromIcon(self, Icon icon) -> bool"""
+ return _gdi_.Bitmap_CopyFromIcon(*args, **kwargs)
+
+ def SetHeight(*args, **kwargs):
+ """
+ SetHeight(self, int height)
+
+ Set the height property (does not affect the existing bitmap data).
+ """
+ return _gdi_.Bitmap_SetHeight(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """
+ SetWidth(self, int width)
+
+ Set the width property (does not affect the existing bitmap data).
+ """
+ return _gdi_.Bitmap_SetWidth(*args, **kwargs)
+
+ def SetDepth(*args, **kwargs):
+ """
+ SetDepth(self, int depth)
+
+ Set the depth property (does not affect the existing bitmap data).
+ """
+ return _gdi_.Bitmap_SetDepth(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """
+ SetSize(self, Size size)
+
+ Set the bitmap size (does not affect the existing bitmap data).
+ """
+ return _gdi_.Bitmap_SetSize(*args, **kwargs)
+
+ def CopyFromCursor(*args, **kwargs):
+ """CopyFromCursor(self, Cursor cursor) -> bool"""
+ return _gdi_.Bitmap_CopyFromCursor(*args, **kwargs)
+
+ def CopyFromBuffer(*args, **kwargs):
+ """
+ CopyFromBuffer(self, buffer data, int format=BitmapBufferFormat_RGB, int stride=-1)
+
+ Copy data from a buffer object to replace the bitmap pixel data.
+ Default format is plain RGB, but other formats are now supported as
+ well. The following symbols are used to specify the format of the
+ bytes in the buffer:
+
+ ============================= ================================
+ wx.BitmapBufferFormat_RGB A simple sequence of RGB bytes
+ wx.BitmapBufferFormat_RGBA A simple sequence of RGBA bytes
+ wx.BitmapBufferFormat_ARGB32 A sequence of 32-bit values in native
+ endian order, with alpha in the upper
+ 8 bits, followed by red, green, and
+ blue.
+ wx.BitmapBufferFormat_RGB32 Same as above but the alpha byte
+ is ignored.
+ ============================= ================================
+
+ """
+ return _gdi_.Bitmap_CopyFromBuffer(*args, **kwargs)
+
+ def CopyFromBufferRGBA(self, buffer):
+ """
+ Copy data from a RGBA buffer object to replace the bitmap pixel
+ data. This method is now just a compatibility wrapper around
+ CopyFromBuffer.
+ """
+ self.CopyFromBuffer(buffer, wx.BitmapBufferFormat_RGBA)
+
+ def CopyToBuffer(*args, **kwargs):
+ """
+ CopyToBuffer(self, buffer data, int format=BitmapBufferFormat_RGB, int stride=-1)
+
+ Copy pixel data to a buffer object. See `CopyFromBuffer` for buffer
+ format .
+ """
+ return _gdi_.Bitmap_CopyToBuffer(*args, **kwargs)
+
+ def HasAlpha(*args, **kwargs):
+ """HasAlpha(self) -> bool"""
+ return _gdi_.Bitmap_HasAlpha(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def __eq__(*args, **kwargs):
+ """__eq__(self, Bitmap other) -> bool"""
+ return _gdi_.Bitmap___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """__ne__(self, Bitmap other) -> bool"""
+ return _gdi_.Bitmap___ne__(*args, **kwargs)
+
+ Depth = property(GetDepth,SetDepth,doc="See `GetDepth` and `SetDepth`")
+ Height = property(GetHeight,SetHeight,doc="See `GetHeight` and `SetHeight`")
+ Mask = property(GetMask,SetMask,doc="See `GetMask` and `SetMask`")
+ Palette = property(GetPalette,doc="See `GetPalette`")
+ Size = property(GetSize,SetSize,doc="See `GetSize` and `SetSize`")
+ Width = property(GetWidth,SetWidth,doc="See `GetWidth` and `SetWidth`")
+_gdi_.Bitmap_swigregister(Bitmap)
+
+def EmptyBitmap(*args, **kwargs):
+ """
+ EmptyBitmap(int width, int height, int depth=BITMAP_SCREEN_DEPTH) -> Bitmap
+
+ Creates a new bitmap of the given size. A depth of -1 indicates the
+ depth of the current screen or visual. Some platforms only support 1
+ for monochrome and -1 for the current display depth.
+ """
+ val = _gdi_.new_EmptyBitmap(*args, **kwargs)
+ return val
+
+def BitmapFromIcon(*args, **kwargs):
+ """
+ BitmapFromIcon(Icon icon) -> Bitmap
+
+ Create a new bitmap from a `wx.Icon` object.
+ """
+ val = _gdi_.new_BitmapFromIcon(*args, **kwargs)
+ return val
+
+def BitmapFromImage(*args, **kwargs):
+ """
+ BitmapFromImage(Image image, int depth=BITMAP_SCREEN_DEPTH) -> Bitmap
+
+ Creates bitmap object from a `wx.Image`. This has to be done to
+ actually display a `wx.Image` as you cannot draw an image directly on
+ a window. The resulting bitmap will use the provided colour depth (or
+ that of the current screen colour depth if depth is -1) which entails
+ that a colour reduction may have to take place.
+ """
+ val = _gdi_.new_BitmapFromImage(*args, **kwargs)
+ return val
+
+def BitmapFromXPMData(*args, **kwargs):
+ """
+ BitmapFromXPMData(PyObject listOfStrings) -> Bitmap
+
+ Construct a Bitmap from a list of strings formatted as XPM data.
+ """
+ val = _gdi_.new_BitmapFromXPMData(*args, **kwargs)
+ return val
+
+def BitmapFromBits(*args, **kwargs):
+ """
+ BitmapFromBits(PyObject bits, int width, int height, int depth=1) -> Bitmap
+
+ Creates a bitmap from an array of bits. You should only use this
+ function for monochrome bitmaps (depth 1) in portable programs: in
+ this case the bits parameter should contain an XBM image as a data
+ string. For other bit depths, the behaviour is platform dependent.
+ """
+ val = _gdi_.new_BitmapFromBits(*args, **kwargs)
+ return val
+
+
+def _BitmapFromBufferAlpha(*args, **kwargs):
+ """_BitmapFromBufferAlpha(int width, int height, buffer data, buffer alpha) -> Bitmap"""
+ return _gdi_._BitmapFromBufferAlpha(*args, **kwargs)
+
+def _BitmapFromBuffer(*args, **kwargs):
+ """_BitmapFromBuffer(int width, int height, buffer data) -> Bitmap"""
+ return _gdi_._BitmapFromBuffer(*args, **kwargs)
+def BitmapFromBuffer(width, height, dataBuffer, alphaBuffer=None):
+ """
+ Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer
+ parameter must be a Python object that implements the buffer
+ interface, such as a string, array, etc. The dataBuffer object is
+ expected to contain a series of RGB bytes and be width*height*3
+ bytes long. A buffer object can optionally be supplied for the
+ image's alpha channel data, and it is expected to be width*height
+ bytes long. On Windows and Mac the RGB values are 'premultiplied'
+ by the alpha values. (The other platforms do the multiplication
+ themselves.)
+
+ Unlike `wx.ImageFromBuffer` the bitmap created with this function
+ does not share the memory buffer with the buffer object. This is
+ because the native pixel buffer format varies on different
+ platforms, and so instead an efficient as possible copy of the
+ data is made from the buffer objects to the bitmap's native pixel
+ buffer. For direct access to a bitmap's pixel buffer see
+ `wx.NativePixelData` and `wx.AlphaPixelData`.
+
+ :see: `wx.Bitmap`, `wx.BitmapFromBufferRGBA`, `wx.NativePixelData`,
+ `wx.AlphaPixelData`, `wx.ImageFromBuffer`
+ """
+ if alphaBuffer is not None:
+ return _gdi_._BitmapFromBufferAlpha(width, height, dataBuffer, alphaBuffer)
+ else:
+ return _gdi_._BitmapFromBuffer(width, height, dataBuffer)
+
+
+def _BitmapFromBufferRGBA(*args, **kwargs):
+ """_BitmapFromBufferRGBA(int width, int height, buffer data) -> Bitmap"""
+ return _gdi_._BitmapFromBufferRGBA(*args, **kwargs)
+def BitmapFromBufferRGBA(width, height, dataBuffer):
+ """
+ Creates a `wx.Bitmap` from the data in dataBuffer. The dataBuffer
+ parameter must be a Python object that implements the buffer
+ interface, such as a string, array, etc. The dataBuffer object is
+ expected to contain a series of RGBA bytes (red, green, blue and
+ alpha) and be width*height*4 bytes long. On Windows and Mac the
+ RGB values are 'premultiplied' by the alpha values. (The other
+ platforms do the multiplication themselves.)
+
+ Unlike `wx.ImageFromBuffer` the bitmap created with this function
+ does not share the memory buffer with the buffer object. This is
+ because the native pixel buffer format varies on different
+ platforms, and so instead an efficient as possible copy of the
+ data is made from the buffer object to the bitmap's native pixel
+ buffer. For direct access to a bitmap's pixel buffer see
+ `wx.NativePixelData` and `wx.AlphaPixelData`.
+
+ :see: `wx.Bitmap`, `wx.BitmapFromBuffer`, `wx.NativePixelData`,
+ `wx.AlphaPixelData`, `wx.ImageFromBuffer`
+ """
+ return _gdi_._BitmapFromBufferRGBA(width, height, dataBuffer)
+
+
+def _EmptyBitmapRGBA(*args, **kwargs):
+ """
+ _EmptyBitmapRGBA(int width, int height, byte red, byte green, byte blue,
+ byte alpha) -> Bitmap
+ """
+ return _gdi_._EmptyBitmapRGBA(*args, **kwargs)
+def EmptyBitmapRGBA(width, height, red=0, green=0, blue=0, alpha=0):
+ """
+ Returns a new empty 32-bit bitmap where every pixel has been
+ initialized with the given RGBA values.
+ """
+ return _gdi_._EmptyBitmapRGBA(width, height, red, green, blue, alpha)
+
+class PixelDataBase(object):
+ """Proxy of C++ PixelDataBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetOrigin(*args, **kwargs):
+ """GetOrigin(self) -> Point"""
+ return _gdi_.PixelDataBase_GetOrigin(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _gdi_.PixelDataBase_GetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """GetHeight(self) -> int"""
+ return _gdi_.PixelDataBase_GetHeight(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(self) -> Size"""
+ return _gdi_.PixelDataBase_GetSize(*args, **kwargs)
+
+ def GetRowStride(*args, **kwargs):
+ """GetRowStride(self) -> int"""
+ return _gdi_.PixelDataBase_GetRowStride(*args, **kwargs)
+
+ Height = property(GetHeight,doc="See `GetHeight`")
+ Origin = property(GetOrigin,doc="See `GetOrigin`")
+ RowStride = property(GetRowStride,doc="See `GetRowStride`")
+ Size = property(GetSize,doc="See `GetSize`")
+ Width = property(GetWidth,doc="See `GetWidth`")
+_gdi_.PixelDataBase_swigregister(PixelDataBase)
+
+class NativePixelData(PixelDataBase):
+ """Proxy of C++ NativePixelData class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, Bitmap bmp) -> NativePixelData
+ __init__(self, Bitmap bmp, Rect rect) -> NativePixelData
+ __init__(self, Bitmap bmp, Point pt, Size sz) -> NativePixelData
+ """
+ _gdi_.NativePixelData_swiginit(self,_gdi_.new_NativePixelData(*args))
+ __swig_destroy__ = _gdi_.delete_NativePixelData
+ __del__ = lambda self : None;
+ def GetPixels(*args, **kwargs):
+ """GetPixels(self) -> NativePixelData_Accessor"""
+ return _gdi_.NativePixelData_GetPixels(*args, **kwargs)
+
+ def UseAlpha(self): pass
+ UseAlpha = wx.deprecated(UseAlpha)
+
+ def __nonzero__(*args, **kwargs):
+ """__nonzero__(self) -> bool"""
+ return _gdi_.NativePixelData___nonzero__(*args, **kwargs)
+
+ def __iter__(self):
+ """
+ Create and return an iterator object for this pixel data
+ object. (It's really a generator but I won't tell if you
+ don't tell.)
+ """
+ width = self.GetWidth()
+ height = self.GetHeight()
+ pixels = self.GetPixels()
+
+
+
+
+ class PixelFacade(object):
+ def Get(self):
+ return pixels.Get()
+ def Set(self, *args, **kw):
+ return pixels.Set(*args, **kw)
+ def __str__(self):
+ return str(self.Get())
+ def __repr__(self):
+ return 'pixel(%d,%d): %s' % (x,y,self.Get())
+ X = property(lambda self: x)
+ Y = property(lambda self: y)
+
+ pf = PixelFacade()
+ for y in xrange(height):
+ pixels.MoveTo(self, 0, y)
+ for x in xrange(width):
+
+
+
+ yield pf
+ pixels.nextPixel()
+
+ Pixels = property(GetPixels,doc="See `GetPixels`")
+_gdi_.NativePixelData_swigregister(NativePixelData)
+
+class NativePixelData_Accessor(object):
+ """Proxy of C++ NativePixelData_Accessor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, NativePixelData data) -> NativePixelData_Accessor
+ __init__(self, Bitmap bmp, NativePixelData data) -> NativePixelData_Accessor
+ __init__(self) -> NativePixelData_Accessor
+ """
+ _gdi_.NativePixelData_Accessor_swiginit(self,_gdi_.new_NativePixelData_Accessor(*args))
+ __swig_destroy__ = _gdi_.delete_NativePixelData_Accessor
+ __del__ = lambda self : None;
+ def Reset(*args, **kwargs):
+ """Reset(self, NativePixelData data)"""
+ return _gdi_.NativePixelData_Accessor_Reset(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.NativePixelData_Accessor_IsOk(*args, **kwargs)
+
+ def nextPixel(*args, **kwargs):
+ """nextPixel(self)"""
+ return _gdi_.NativePixelData_Accessor_nextPixel(*args, **kwargs)
+
+ def Offset(*args, **kwargs):
+ """Offset(self, NativePixelData data, int x, int y)"""
+ return _gdi_.NativePixelData_Accessor_Offset(*args, **kwargs)
+
+ def OffsetX(*args, **kwargs):
+ """OffsetX(self, NativePixelData data, int x)"""
+ return _gdi_.NativePixelData_Accessor_OffsetX(*args, **kwargs)
+
+ def OffsetY(*args, **kwargs):
+ """OffsetY(self, NativePixelData data, int y)"""
+ return _gdi_.NativePixelData_Accessor_OffsetY(*args, **kwargs)
+
+ def MoveTo(*args, **kwargs):
+ """MoveTo(self, NativePixelData data, int x, int y)"""
+ return _gdi_.NativePixelData_Accessor_MoveTo(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """Set(self, byte red, byte green, byte blue)"""
+ return _gdi_.NativePixelData_Accessor_Set(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """Get(self) -> PyObject"""
+ return _gdi_.NativePixelData_Accessor_Get(*args, **kwargs)
+
+_gdi_.NativePixelData_Accessor_swigregister(NativePixelData_Accessor)
+
+class AlphaPixelData(PixelDataBase):
+ """Proxy of C++ AlphaPixelData class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, Bitmap bmp) -> AlphaPixelData
+ __init__(self, Bitmap bmp, Rect rect) -> AlphaPixelData
+ __init__(self, Bitmap bmp, Point pt, Size sz) -> AlphaPixelData
+ """
+ _gdi_.AlphaPixelData_swiginit(self,_gdi_.new_AlphaPixelData(*args))
+ __swig_destroy__ = _gdi_.delete_AlphaPixelData
+ __del__ = lambda self : None;
+ def GetPixels(*args, **kwargs):
+ """GetPixels(self) -> AlphaPixelData_Accessor"""
+ return _gdi_.AlphaPixelData_GetPixels(*args, **kwargs)
+
+ def UseAlpha(self): pass
+ UseAlpha = wx.deprecated(UseAlpha)
+
+ def __nonzero__(*args, **kwargs):
+ """__nonzero__(self) -> bool"""
+ return _gdi_.AlphaPixelData___nonzero__(*args, **kwargs)
+
+ def __iter__(self):
+ """
+ Create and return an iterator object for this pixel data
+ object. (It's really a generator but I won't tell if you
+ don't tell.)
+ """
+ width = self.GetWidth()
+ height = self.GetHeight()
+ pixels = self.GetPixels()
+
+
+
+
+ class PixelFacade(object):
+ def Get(self):
+ return pixels.Get()
+ def Set(self, *args, **kw):
+ return pixels.Set(*args, **kw)
+ def __str__(self):
+ return str(self.Get())
+ def __repr__(self):
+ return 'pixel(%d,%d): %s' % (x,y,self.Get())
+ X = property(lambda self: x)
+ Y = property(lambda self: y)
+
+ pf = PixelFacade()
+ for y in xrange(height):
+ pixels.MoveTo(self, 0, y)
+ for x in xrange(width):
+
+
+
+ yield pf
+ pixels.nextPixel()
+
+ Pixels = property(GetPixels,doc="See `GetPixels`")
+_gdi_.AlphaPixelData_swigregister(AlphaPixelData)
+
+class AlphaPixelData_Accessor(object):
+ """Proxy of C++ AlphaPixelData_Accessor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, AlphaPixelData data) -> AlphaPixelData_Accessor
+ __init__(self, Bitmap bmp, AlphaPixelData data) -> AlphaPixelData_Accessor
+ __init__(self) -> AlphaPixelData_Accessor
+ """
+ _gdi_.AlphaPixelData_Accessor_swiginit(self,_gdi_.new_AlphaPixelData_Accessor(*args))
+ __swig_destroy__ = _gdi_.delete_AlphaPixelData_Accessor
+ __del__ = lambda self : None;
+ def Reset(*args, **kwargs):
+ """Reset(self, AlphaPixelData data)"""
+ return _gdi_.AlphaPixelData_Accessor_Reset(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.AlphaPixelData_Accessor_IsOk(*args, **kwargs)
+
+ def nextPixel(*args, **kwargs):
+ """nextPixel(self)"""
+ return _gdi_.AlphaPixelData_Accessor_nextPixel(*args, **kwargs)
+
+ def Offset(*args, **kwargs):
+ """Offset(self, AlphaPixelData data, int x, int y)"""
+ return _gdi_.AlphaPixelData_Accessor_Offset(*args, **kwargs)
+
+ def OffsetX(*args, **kwargs):
+ """OffsetX(self, AlphaPixelData data, int x)"""
+ return _gdi_.AlphaPixelData_Accessor_OffsetX(*args, **kwargs)
+
+ def OffsetY(*args, **kwargs):
+ """OffsetY(self, AlphaPixelData data, int y)"""
+ return _gdi_.AlphaPixelData_Accessor_OffsetY(*args, **kwargs)
+
+ def MoveTo(*args, **kwargs):
+ """MoveTo(self, AlphaPixelData data, int x, int y)"""
+ return _gdi_.AlphaPixelData_Accessor_MoveTo(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """Set(self, byte red, byte green, byte blue, byte alpha)"""
+ return _gdi_.AlphaPixelData_Accessor_Set(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """Get(self) -> PyObject"""
+ return _gdi_.AlphaPixelData_Accessor_Get(*args, **kwargs)
+
+_gdi_.AlphaPixelData_Accessor_swigregister(AlphaPixelData_Accessor)
+
+class Mask(_core.Object):
+ """
+ This class encapsulates a monochrome mask bitmap, where the masked
+ area is black and the unmasked area is white. When associated with a
+ bitmap and drawn in a device context, the unmasked area of the bitmap
+ will be drawn, and the masked area will not be drawn.
+
+ A mask may be associated with a `wx.Bitmap`. It is used in
+ `wx.DC.DrawBitmap` or `wx.DC.Blit` when the source device context is a
+ `wx.MemoryDC` with a `wx.Bitmap` selected into it that contains a
+ mask.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Bitmap bitmap, Colour colour=NullColour) -> Mask
+
+ Constructs a mask from a `wx.Bitmap` and a `wx.Colour` in that bitmap
+ that indicates the transparent portions of the mask. In other words,
+ the pixels in ``bitmap`` that match ``colour`` will be the transparent
+ portions of the mask. If no ``colour`` or an invalid ``colour`` is
+ passed then BLACK is used.
+
+ :see: `wx.Bitmap`, `wx.Colour`
+ """
+ _gdi_.Mask_swiginit(self,_gdi_.new_Mask(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Mask
+ __del__ = lambda self : None;
+_gdi_.Mask_swigregister(Mask)
+
+MaskColour = wx.deprecated(Mask, "wx.MaskColour is deprecated, use `wx.Mask` instead.")
+class Icon(GDIObject):
+ """Proxy of C++ Icon class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String name, int type=BITMAP_TYPE_ANY, int desiredWidth=-1,
+ int desiredHeight=-1) -> Icon
+ """
+ _gdi_.Icon_swiginit(self,_gdi_.new_Icon(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Icon
+ __del__ = lambda self : None;
+ def LoadFile(*args, **kwargs):
+ """LoadFile(self, String name, int type) -> bool"""
+ return _gdi_.Icon_LoadFile(*args, **kwargs)
+
+ def GetHandle(*args, **kwargs):
+ """GetHandle(self) -> long"""
+ return _gdi_.Icon_GetHandle(*args, **kwargs)
+
+ def SetHandle(*args, **kwargs):
+ """SetHandle(self, long handle)"""
+ return _gdi_.Icon_SetHandle(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.Icon_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _gdi_.Icon_GetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """GetHeight(self) -> int"""
+ return _gdi_.Icon_GetHeight(*args, **kwargs)
+
+ def GetDepth(*args, **kwargs):
+ """GetDepth(self) -> int"""
+ return _gdi_.Icon_GetDepth(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """SetWidth(self, int w)"""
+ return _gdi_.Icon_SetWidth(*args, **kwargs)
+
+ def SetHeight(*args, **kwargs):
+ """SetHeight(self, int h)"""
+ return _gdi_.Icon_SetHeight(*args, **kwargs)
+
+ def SetDepth(*args, **kwargs):
+ """SetDepth(self, int d)"""
+ return _gdi_.Icon_SetDepth(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, Size size)"""
+ return _gdi_.Icon_SetSize(*args, **kwargs)
+
+ def CopyFromBitmap(*args, **kwargs):
+ """CopyFromBitmap(self, Bitmap bmp)"""
+ return _gdi_.Icon_CopyFromBitmap(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ Depth = property(GetDepth,SetDepth,doc="See `GetDepth` and `SetDepth`")
+ Height = property(GetHeight,SetHeight,doc="See `GetHeight` and `SetHeight`")
+ Width = property(GetWidth,SetWidth,doc="See `GetWidth` and `SetWidth`")
+_gdi_.Icon_swigregister(Icon)
+
+def EmptyIcon(*args, **kwargs):
+ """EmptyIcon() -> Icon"""
+ val = _gdi_.new_EmptyIcon(*args, **kwargs)
+ return val
+
+def IconFromLocation(*args, **kwargs):
+ """IconFromLocation(IconLocation loc) -> Icon"""
+ val = _gdi_.new_IconFromLocation(*args, **kwargs)
+ return val
+
+def IconFromBitmap(*args, **kwargs):
+ """IconFromBitmap(Bitmap bmp) -> Icon"""
+ val = _gdi_.new_IconFromBitmap(*args, **kwargs)
+ return val
+
+def IconFromXPMData(*args, **kwargs):
+ """IconFromXPMData(PyObject listOfStrings) -> Icon"""
+ val = _gdi_.new_IconFromXPMData(*args, **kwargs)
+ return val
+
+class IconLocation(object):
+ """Proxy of C++ IconLocation class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String filename=&wxPyEmptyString, int num=0) -> IconLocation"""
+ _gdi_.IconLocation_swiginit(self,_gdi_.new_IconLocation(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_IconLocation
+ __del__ = lambda self : None;
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.IconLocation_IsOk(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def SetFileName(*args, **kwargs):
+ """SetFileName(self, String filename)"""
+ return _gdi_.IconLocation_SetFileName(*args, **kwargs)
+
+ def GetFileName(*args, **kwargs):
+ """GetFileName(self) -> String"""
+ return _gdi_.IconLocation_GetFileName(*args, **kwargs)
+
+ def SetIndex(*args, **kwargs):
+ """SetIndex(self, int num)"""
+ return _gdi_.IconLocation_SetIndex(*args, **kwargs)
+
+ def GetIndex(*args, **kwargs):
+ """GetIndex(self) -> int"""
+ return _gdi_.IconLocation_GetIndex(*args, **kwargs)
+
+ FileName = property(GetFileName,SetFileName,doc="See `GetFileName` and `SetFileName`")
+ Index = property(GetIndex,SetIndex,doc="See `GetIndex` and `SetIndex`")
+_gdi_.IconLocation_swigregister(IconLocation)
+
+class IconBundle(object):
+ """Proxy of C++ IconBundle class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ FALLBACK_NONE = _gdi_.IconBundle_FALLBACK_NONE
+ FALLBACK_SYSTEM = _gdi_.IconBundle_FALLBACK_SYSTEM
+ FALLBACK_NEAREST_LARGER = _gdi_.IconBundle_FALLBACK_NEAREST_LARGER
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> IconBundle"""
+ _gdi_.IconBundle_swiginit(self,_gdi_.new_IconBundle(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_IconBundle
+ __del__ = lambda self : None;
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.IconBundle_IsOk(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def AddIcon(*args, **kwargs):
+ """
+ AddIcon(self, Icon icon)
+
+ Adds the icon to the collection, if the collection already contains an
+ icon with the same width and height, it is replaced
+ """
+ return _gdi_.IconBundle_AddIcon(*args, **kwargs)
+
+ def AddIconFromFile(*args, **kwargs):
+ """
+ AddIconFromFile(self, String file, int type=BITMAP_TYPE_ANY)
+
+ Adds all the icons contained in the file to the collection, if the
+ collection already contains icons with the same width and height, they
+ are replaced
+ """
+ return _gdi_.IconBundle_AddIconFromFile(*args, **kwargs)
+
+ def AddIconFromStream(*args, **kwargs):
+ """
+ AddIconFromStream(self, InputStream stream, int type=BITMAP_TYPE_ANY)
+
+ Just like `AddIconFromFile` but pulls icons from a file-liek object.
+ """
+ return _gdi_.IconBundle_AddIconFromStream(*args, **kwargs)
+
+ def GetIcon(*args, **kwargs):
+ """
+ GetIcon(self, Size size, int flags=FALLBACK_SYSTEM) -> Icon
+
+ Returns the icon with the given size; if no such icon exists, returns
+ the icon with size wxSYS_ICON_[XY]; if no such icon exists, returns
+ the first icon in the bundle
+ """
+ return _gdi_.IconBundle_GetIcon(*args, **kwargs)
+
+ def GetIconOfExactSize(*args, **kwargs):
+ """
+ GetIconOfExactSize(self, Size size) -> Icon
+
+ Returns the icon exactly of the specified size or wxNullIcon if no
+ icon of exactly given size are available.
+ """
+ return _gdi_.IconBundle_GetIconOfExactSize(*args, **kwargs)
+
+ def GetIconCount(*args, **kwargs):
+ """
+ GetIconCount(self) -> size_t
+
+ return the number of available icons
+ """
+ return _gdi_.IconBundle_GetIconCount(*args, **kwargs)
+
+ def GetIconByIndex(*args, **kwargs):
+ """
+ GetIconByIndex(self, size_t n) -> Icon
+
+ Return the icon at index (must be < GetIconCount())
+ """
+ return _gdi_.IconBundle_GetIconByIndex(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """
+ IsEmpty(self) -> bool
+
+ Check if we have any icons at all
+ """
+ return _gdi_.IconBundle_IsEmpty(*args, **kwargs)
+
+_gdi_.IconBundle_swigregister(IconBundle)
+
+def IconBundleFromFile(*args, **kwargs):
+ """IconBundleFromFile(String file, int type=BITMAP_TYPE_ANY) -> IconBundle"""
+ val = _gdi_.new_IconBundleFromFile(*args, **kwargs)
+ return val
+
+def IconBundleFromIcon(*args, **kwargs):
+ """IconBundleFromIcon(Icon icon) -> IconBundle"""
+ val = _gdi_.new_IconBundleFromIcon(*args, **kwargs)
+ return val
+
+def IconBundleFromStream(*args, **kwargs):
+ """IconBundleFromStream(InputStream stream, int type=BITMAP_TYPE_ANY) -> IconBundle"""
+ val = _gdi_.new_IconBundleFromStream(*args, **kwargs)
+ return val
+
+class Cursor(GDIObject):
+ """
+ A cursor is a small bitmap usually used for denoting where the mouse
+ pointer is, with a picture that might indicate the interpretation of a
+ mouse click.
+
+ A single cursor object may be used in many windows (any subwindow
+ type). The wxWindows convention is to set the cursor for a window, as
+ in X, rather than to set it globally as in MS Windows, although a
+ global `wx.SetCursor` function is also available for use on MS Windows.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String cursorName, int type, int hotSpotX=0, int hotSpotY=0) -> Cursor
+
+ Construct a Cursor from a file. Specify the type of file using
+ wx.BITMAP_TYPE* constants, and specify the hotspot if not using a .cur
+ file.
+ """
+ _gdi_.Cursor_swiginit(self,_gdi_.new_Cursor(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Cursor
+ __del__ = lambda self : None;
+ def GetHandle(*args, **kwargs):
+ """
+ GetHandle(self) -> long
+
+ Get the MS Windows handle for the cursor
+ """
+ return _gdi_.Cursor_GetHandle(*args, **kwargs)
+
+ def SetHandle(*args, **kwargs):
+ """
+ SetHandle(self, long handle)
+
+ Set the MS Windows handle to use for the cursor
+ """
+ return _gdi_.Cursor_SetHandle(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.Cursor_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def __nonzero__(self): return self.IsOk()
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _gdi_.Cursor_GetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """GetHeight(self) -> int"""
+ return _gdi_.Cursor_GetHeight(*args, **kwargs)
+
+ def GetDepth(*args, **kwargs):
+ """GetDepth(self) -> int"""
+ return _gdi_.Cursor_GetDepth(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """SetWidth(self, int w)"""
+ return _gdi_.Cursor_SetWidth(*args, **kwargs)
+
+ def SetHeight(*args, **kwargs):
+ """SetHeight(self, int h)"""
+ return _gdi_.Cursor_SetHeight(*args, **kwargs)
+
+ def SetDepth(*args, **kwargs):
+ """SetDepth(self, int d)"""
+ return _gdi_.Cursor_SetDepth(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, Size size)"""
+ return _gdi_.Cursor_SetSize(*args, **kwargs)
+
+_gdi_.Cursor_swigregister(Cursor)
+
+def StockCursor(*args, **kwargs):
+ """
+ StockCursor(int id) -> Cursor
+
+ Create a cursor using one of the stock cursors. Note that not all
+ stock cursors are available on all platforms.
+ """
+ val = _gdi_.new_StockCursor(*args, **kwargs)
+ return val
+
+def CursorFromImage(*args, **kwargs):
+ """
+ CursorFromImage(Image image) -> Cursor
+
+ Constructs a cursor from a `wx.Image`. The mask (if any) will be used
+ for setting the transparent portions of the cursor.
+ """
+ val = _gdi_.new_CursorFromImage(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+OutRegion = _gdi_.OutRegion
+PartRegion = _gdi_.PartRegion
+InRegion = _gdi_.InRegion
+class Region(GDIObject):
+ """Proxy of C++ Region class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int x=0, int y=0, int width=0, int height=0) -> Region"""
+ _gdi_.Region_swiginit(self,_gdi_.new_Region(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Region
+ __del__ = lambda self : None;
+ def Clear(*args, **kwargs):
+ """Clear(self)"""
+ return _gdi_.Region_Clear(*args, **kwargs)
+
+ def Offset(*args, **kwargs):
+ """Offset(self, int x, int y) -> bool"""
+ return _gdi_.Region_Offset(*args, **kwargs)
+
+ def Contains(*args, **kwargs):
+ """Contains(self, int x, int y) -> int"""
+ return _gdi_.Region_Contains(*args, **kwargs)
+
+ def ContainsPoint(*args, **kwargs):
+ """ContainsPoint(self, Point pt) -> int"""
+ return _gdi_.Region_ContainsPoint(*args, **kwargs)
+
+ def ContainsRect(*args, **kwargs):
+ """ContainsRect(self, Rect rect) -> int"""
+ return _gdi_.Region_ContainsRect(*args, **kwargs)
+
+ def ContainsRectDim(*args, **kwargs):
+ """ContainsRectDim(self, int x, int y, int w, int h) -> int"""
+ return _gdi_.Region_ContainsRectDim(*args, **kwargs)
+
+ def GetBox(*args, **kwargs):
+ """GetBox(self) -> Rect"""
+ return _gdi_.Region_GetBox(*args, **kwargs)
+
+ def Intersect(*args, **kwargs):
+ """Intersect(self, int x, int y, int width, int height) -> bool"""
+ return _gdi_.Region_Intersect(*args, **kwargs)
+
+ def IntersectRect(*args, **kwargs):
+ """IntersectRect(self, Rect rect) -> bool"""
+ return _gdi_.Region_IntersectRect(*args, **kwargs)
+
+ def IntersectRegion(*args, **kwargs):
+ """IntersectRegion(self, Region region) -> bool"""
+ return _gdi_.Region_IntersectRegion(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """IsEmpty(self) -> bool"""
+ return _gdi_.Region_IsEmpty(*args, **kwargs)
+
+ def IsEqual(*args, **kwargs):
+ """IsEqual(self, Region region) -> bool"""
+ return _gdi_.Region_IsEqual(*args, **kwargs)
+
+ def Union(*args, **kwargs):
+ """Union(self, int x, int y, int width, int height) -> bool"""
+ return _gdi_.Region_Union(*args, **kwargs)
+
+ def UnionRect(*args, **kwargs):
+ """UnionRect(self, Rect rect) -> bool"""
+ return _gdi_.Region_UnionRect(*args, **kwargs)
+
+ def UnionRegion(*args, **kwargs):
+ """UnionRegion(self, Region region) -> bool"""
+ return _gdi_.Region_UnionRegion(*args, **kwargs)
+
+ def Subtract(*args, **kwargs):
+ """Subtract(self, int x, int y, int width, int height) -> bool"""
+ return _gdi_.Region_Subtract(*args, **kwargs)
+
+ def SubtractRect(*args, **kwargs):
+ """SubtractRect(self, Rect rect) -> bool"""
+ return _gdi_.Region_SubtractRect(*args, **kwargs)
+
+ def SubtractRegion(*args, **kwargs):
+ """SubtractRegion(self, Region region) -> bool"""
+ return _gdi_.Region_SubtractRegion(*args, **kwargs)
+
+ def Xor(*args, **kwargs):
+ """Xor(self, int x, int y, int width, int height) -> bool"""
+ return _gdi_.Region_Xor(*args, **kwargs)
+
+ def XorRect(*args, **kwargs):
+ """XorRect(self, Rect rect) -> bool"""
+ return _gdi_.Region_XorRect(*args, **kwargs)
+
+ def XorRegion(*args, **kwargs):
+ """XorRegion(self, Region region) -> bool"""
+ return _gdi_.Region_XorRegion(*args, **kwargs)
+
+ def ConvertToBitmap(*args, **kwargs):
+ """ConvertToBitmap(self) -> Bitmap"""
+ return _gdi_.Region_ConvertToBitmap(*args, **kwargs)
+
+ def UnionBitmap(*args, **kwargs):
+ """UnionBitmap(self, Bitmap bmp) -> bool"""
+ return _gdi_.Region_UnionBitmap(*args, **kwargs)
+
+ def UnionBitmapColour(*args, **kwargs):
+ """UnionBitmapColour(self, Bitmap bmp, Colour transColour, int tolerance=0) -> bool"""
+ return _gdi_.Region_UnionBitmapColour(*args, **kwargs)
+
+ Box = property(GetBox,doc="See `GetBox`")
+_gdi_.Region_swigregister(Region)
+
+def RegionFromBitmap(*args, **kwargs):
+ """RegionFromBitmap(Bitmap bmp) -> Region"""
+ val = _gdi_.new_RegionFromBitmap(*args, **kwargs)
+ return val
+
+def RegionFromBitmapColour(*args, **kwargs):
+ """RegionFromBitmapColour(Bitmap bmp, Colour transColour, int tolerance=0) -> Region"""
+ val = _gdi_.new_RegionFromBitmapColour(*args, **kwargs)
+ return val
+
+def RegionFromPoints(*args, **kwargs):
+ """RegionFromPoints(int points, int fillStyle=WINDING_RULE) -> Region"""
+ val = _gdi_.new_RegionFromPoints(*args, **kwargs)
+ return val
+
+class RegionIterator(_core.Object):
+ """Proxy of C++ RegionIterator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Region region) -> RegionIterator"""
+ _gdi_.RegionIterator_swiginit(self,_gdi_.new_RegionIterator(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_RegionIterator
+ __del__ = lambda self : None;
+ def GetX(*args, **kwargs):
+ """GetX(self) -> int"""
+ return _gdi_.RegionIterator_GetX(*args, **kwargs)
+
+ def GetY(*args, **kwargs):
+ """GetY(self) -> int"""
+ return _gdi_.RegionIterator_GetY(*args, **kwargs)
+
+ def GetW(*args, **kwargs):
+ """GetW(self) -> int"""
+ return _gdi_.RegionIterator_GetW(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _gdi_.RegionIterator_GetWidth(*args, **kwargs)
+
+ def GetH(*args, **kwargs):
+ """GetH(self) -> int"""
+ return _gdi_.RegionIterator_GetH(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """GetHeight(self) -> int"""
+ return _gdi_.RegionIterator_GetHeight(*args, **kwargs)
+
+ def GetRect(*args, **kwargs):
+ """GetRect(self) -> Rect"""
+ return _gdi_.RegionIterator_GetRect(*args, **kwargs)
+
+ def HaveRects(*args, **kwargs):
+ """HaveRects(self) -> bool"""
+ return _gdi_.RegionIterator_HaveRects(*args, **kwargs)
+
+ def Reset(*args, **kwargs):
+ """Reset(self)"""
+ return _gdi_.RegionIterator_Reset(*args, **kwargs)
+
+ def Next(*args, **kwargs):
+ """Next(self)"""
+ return _gdi_.RegionIterator_Next(*args, **kwargs)
+
+ def __nonzero__(*args, **kwargs):
+ """__nonzero__(self) -> bool"""
+ return _gdi_.RegionIterator___nonzero__(*args, **kwargs)
+
+ H = property(GetH,doc="See `GetH`")
+ Height = property(GetHeight,doc="See `GetHeight`")
+ Rect = property(GetRect,doc="See `GetRect`")
+ W = property(GetW,doc="See `GetW`")
+ Width = property(GetWidth,doc="See `GetWidth`")
+ X = property(GetX,doc="See `GetX`")
+ Y = property(GetY,doc="See `GetY`")
+_gdi_.RegionIterator_swigregister(RegionIterator)
+
+#---------------------------------------------------------------------------
+
+FONTFAMILY_DEFAULT = _gdi_.FONTFAMILY_DEFAULT
+FONTFAMILY_DECORATIVE = _gdi_.FONTFAMILY_DECORATIVE
+FONTFAMILY_ROMAN = _gdi_.FONTFAMILY_ROMAN
+FONTFAMILY_SCRIPT = _gdi_.FONTFAMILY_SCRIPT
+FONTFAMILY_SWISS = _gdi_.FONTFAMILY_SWISS
+FONTFAMILY_MODERN = _gdi_.FONTFAMILY_MODERN
+FONTFAMILY_TELETYPE = _gdi_.FONTFAMILY_TELETYPE
+FONTFAMILY_MAX = _gdi_.FONTFAMILY_MAX
+FONTFAMILY_UNKNOWN = _gdi_.FONTFAMILY_UNKNOWN
+FONTSTYLE_NORMAL = _gdi_.FONTSTYLE_NORMAL
+FONTSTYLE_ITALIC = _gdi_.FONTSTYLE_ITALIC
+FONTSTYLE_SLANT = _gdi_.FONTSTYLE_SLANT
+FONTSTYLE_MAX = _gdi_.FONTSTYLE_MAX
+FONTWEIGHT_NORMAL = _gdi_.FONTWEIGHT_NORMAL
+FONTWEIGHT_LIGHT = _gdi_.FONTWEIGHT_LIGHT
+FONTWEIGHT_BOLD = _gdi_.FONTWEIGHT_BOLD
+FONTWEIGHT_MAX = _gdi_.FONTWEIGHT_MAX
+FONTSIZE_XX_SMALL = _gdi_.FONTSIZE_XX_SMALL
+FONTSIZE_X_SMALL = _gdi_.FONTSIZE_X_SMALL
+FONTSIZE_SMALL = _gdi_.FONTSIZE_SMALL
+FONTSIZE_MEDIUM = _gdi_.FONTSIZE_MEDIUM
+FONTSIZE_LARGE = _gdi_.FONTSIZE_LARGE
+FONTSIZE_X_LARGE = _gdi_.FONTSIZE_X_LARGE
+FONTSIZE_XX_LARGE = _gdi_.FONTSIZE_XX_LARGE
+FONTFLAG_DEFAULT = _gdi_.FONTFLAG_DEFAULT
+FONTFLAG_ITALIC = _gdi_.FONTFLAG_ITALIC
+FONTFLAG_SLANT = _gdi_.FONTFLAG_SLANT
+FONTFLAG_LIGHT = _gdi_.FONTFLAG_LIGHT
+FONTFLAG_BOLD = _gdi_.FONTFLAG_BOLD
+FONTFLAG_ANTIALIASED = _gdi_.FONTFLAG_ANTIALIASED
+FONTFLAG_NOT_ANTIALIASED = _gdi_.FONTFLAG_NOT_ANTIALIASED
+FONTFLAG_UNDERLINED = _gdi_.FONTFLAG_UNDERLINED
+FONTFLAG_STRIKETHROUGH = _gdi_.FONTFLAG_STRIKETHROUGH
+FONTFLAG_MASK = _gdi_.FONTFLAG_MASK
+FONTENCODING_SYSTEM = _gdi_.FONTENCODING_SYSTEM
+FONTENCODING_DEFAULT = _gdi_.FONTENCODING_DEFAULT
+FONTENCODING_ISO8859_1 = _gdi_.FONTENCODING_ISO8859_1
+FONTENCODING_ISO8859_2 = _gdi_.FONTENCODING_ISO8859_2
+FONTENCODING_ISO8859_3 = _gdi_.FONTENCODING_ISO8859_3
+FONTENCODING_ISO8859_4 = _gdi_.FONTENCODING_ISO8859_4
+FONTENCODING_ISO8859_5 = _gdi_.FONTENCODING_ISO8859_5
+FONTENCODING_ISO8859_6 = _gdi_.FONTENCODING_ISO8859_6
+FONTENCODING_ISO8859_7 = _gdi_.FONTENCODING_ISO8859_7
+FONTENCODING_ISO8859_8 = _gdi_.FONTENCODING_ISO8859_8
+FONTENCODING_ISO8859_9 = _gdi_.FONTENCODING_ISO8859_9
+FONTENCODING_ISO8859_10 = _gdi_.FONTENCODING_ISO8859_10
+FONTENCODING_ISO8859_11 = _gdi_.FONTENCODING_ISO8859_11
+FONTENCODING_ISO8859_12 = _gdi_.FONTENCODING_ISO8859_12
+FONTENCODING_ISO8859_13 = _gdi_.FONTENCODING_ISO8859_13
+FONTENCODING_ISO8859_14 = _gdi_.FONTENCODING_ISO8859_14
+FONTENCODING_ISO8859_15 = _gdi_.FONTENCODING_ISO8859_15
+FONTENCODING_ISO8859_MAX = _gdi_.FONTENCODING_ISO8859_MAX
+FONTENCODING_KOI8 = _gdi_.FONTENCODING_KOI8
+FONTENCODING_KOI8_U = _gdi_.FONTENCODING_KOI8_U
+FONTENCODING_ALTERNATIVE = _gdi_.FONTENCODING_ALTERNATIVE
+FONTENCODING_BULGARIAN = _gdi_.FONTENCODING_BULGARIAN
+FONTENCODING_CP437 = _gdi_.FONTENCODING_CP437
+FONTENCODING_CP850 = _gdi_.FONTENCODING_CP850
+FONTENCODING_CP852 = _gdi_.FONTENCODING_CP852
+FONTENCODING_CP855 = _gdi_.FONTENCODING_CP855
+FONTENCODING_CP866 = _gdi_.FONTENCODING_CP866
+FONTENCODING_CP874 = _gdi_.FONTENCODING_CP874
+FONTENCODING_CP932 = _gdi_.FONTENCODING_CP932
+FONTENCODING_CP936 = _gdi_.FONTENCODING_CP936
+FONTENCODING_CP949 = _gdi_.FONTENCODING_CP949
+FONTENCODING_CP950 = _gdi_.FONTENCODING_CP950
+FONTENCODING_CP1250 = _gdi_.FONTENCODING_CP1250
+FONTENCODING_CP1251 = _gdi_.FONTENCODING_CP1251
+FONTENCODING_CP1252 = _gdi_.FONTENCODING_CP1252
+FONTENCODING_CP1253 = _gdi_.FONTENCODING_CP1253
+FONTENCODING_CP1254 = _gdi_.FONTENCODING_CP1254
+FONTENCODING_CP1255 = _gdi_.FONTENCODING_CP1255
+FONTENCODING_CP1256 = _gdi_.FONTENCODING_CP1256
+FONTENCODING_CP1257 = _gdi_.FONTENCODING_CP1257
+FONTENCODING_CP12_MAX = _gdi_.FONTENCODING_CP12_MAX
+FONTENCODING_UTF7 = _gdi_.FONTENCODING_UTF7
+FONTENCODING_UTF8 = _gdi_.FONTENCODING_UTF8
+FONTENCODING_EUC_JP = _gdi_.FONTENCODING_EUC_JP
+FONTENCODING_UTF16BE = _gdi_.FONTENCODING_UTF16BE
+FONTENCODING_UTF16LE = _gdi_.FONTENCODING_UTF16LE
+FONTENCODING_UTF32BE = _gdi_.FONTENCODING_UTF32BE
+FONTENCODING_UTF32LE = _gdi_.FONTENCODING_UTF32LE
+FONTENCODING_MACROMAN = _gdi_.FONTENCODING_MACROMAN
+FONTENCODING_MACJAPANESE = _gdi_.FONTENCODING_MACJAPANESE
+FONTENCODING_MACCHINESETRAD = _gdi_.FONTENCODING_MACCHINESETRAD
+FONTENCODING_MACKOREAN = _gdi_.FONTENCODING_MACKOREAN
+FONTENCODING_MACARABIC = _gdi_.FONTENCODING_MACARABIC
+FONTENCODING_MACHEBREW = _gdi_.FONTENCODING_MACHEBREW
+FONTENCODING_MACGREEK = _gdi_.FONTENCODING_MACGREEK
+FONTENCODING_MACCYRILLIC = _gdi_.FONTENCODING_MACCYRILLIC
+FONTENCODING_MACDEVANAGARI = _gdi_.FONTENCODING_MACDEVANAGARI
+FONTENCODING_MACGURMUKHI = _gdi_.FONTENCODING_MACGURMUKHI
+FONTENCODING_MACGUJARATI = _gdi_.FONTENCODING_MACGUJARATI
+FONTENCODING_MACORIYA = _gdi_.FONTENCODING_MACORIYA
+FONTENCODING_MACBENGALI = _gdi_.FONTENCODING_MACBENGALI
+FONTENCODING_MACTAMIL = _gdi_.FONTENCODING_MACTAMIL
+FONTENCODING_MACTELUGU = _gdi_.FONTENCODING_MACTELUGU
+FONTENCODING_MACKANNADA = _gdi_.FONTENCODING_MACKANNADA
+FONTENCODING_MACMALAJALAM = _gdi_.FONTENCODING_MACMALAJALAM
+FONTENCODING_MACSINHALESE = _gdi_.FONTENCODING_MACSINHALESE
+FONTENCODING_MACBURMESE = _gdi_.FONTENCODING_MACBURMESE
+FONTENCODING_MACKHMER = _gdi_.FONTENCODING_MACKHMER
+FONTENCODING_MACTHAI = _gdi_.FONTENCODING_MACTHAI
+FONTENCODING_MACLAOTIAN = _gdi_.FONTENCODING_MACLAOTIAN
+FONTENCODING_MACGEORGIAN = _gdi_.FONTENCODING_MACGEORGIAN
+FONTENCODING_MACARMENIAN = _gdi_.FONTENCODING_MACARMENIAN
+FONTENCODING_MACCHINESESIMP = _gdi_.FONTENCODING_MACCHINESESIMP
+FONTENCODING_MACTIBETAN = _gdi_.FONTENCODING_MACTIBETAN
+FONTENCODING_MACMONGOLIAN = _gdi_.FONTENCODING_MACMONGOLIAN
+FONTENCODING_MACETHIOPIC = _gdi_.FONTENCODING_MACETHIOPIC
+FONTENCODING_MACCENTRALEUR = _gdi_.FONTENCODING_MACCENTRALEUR
+FONTENCODING_MACVIATNAMESE = _gdi_.FONTENCODING_MACVIATNAMESE
+FONTENCODING_MACARABICEXT = _gdi_.FONTENCODING_MACARABICEXT
+FONTENCODING_MACSYMBOL = _gdi_.FONTENCODING_MACSYMBOL
+FONTENCODING_MACDINGBATS = _gdi_.FONTENCODING_MACDINGBATS
+FONTENCODING_MACTURKISH = _gdi_.FONTENCODING_MACTURKISH
+FONTENCODING_MACCROATIAN = _gdi_.FONTENCODING_MACCROATIAN
+FONTENCODING_MACICELANDIC = _gdi_.FONTENCODING_MACICELANDIC
+FONTENCODING_MACROMANIAN = _gdi_.FONTENCODING_MACROMANIAN
+FONTENCODING_MACCELTIC = _gdi_.FONTENCODING_MACCELTIC
+FONTENCODING_MACGAELIC = _gdi_.FONTENCODING_MACGAELIC
+FONTENCODING_MACKEYBOARD = _gdi_.FONTENCODING_MACKEYBOARD
+FONTENCODING_ISO2022_JP = _gdi_.FONTENCODING_ISO2022_JP
+FONTENCODING_MACMIN = _gdi_.FONTENCODING_MACMIN
+FONTENCODING_MACMAX = _gdi_.FONTENCODING_MACMAX
+FONTENCODING_MAX = _gdi_.FONTENCODING_MAX
+FONTENCODING_UTF16 = _gdi_.FONTENCODING_UTF16
+FONTENCODING_UTF32 = _gdi_.FONTENCODING_UTF32
+FONTENCODING_UNICODE = _gdi_.FONTENCODING_UNICODE
+FONTENCODING_GB2312 = _gdi_.FONTENCODING_GB2312
+FONTENCODING_BIG5 = _gdi_.FONTENCODING_BIG5
+FONTENCODING_SHIFT_JIS = _gdi_.FONTENCODING_SHIFT_JIS
+FONTENCODING_EUC_KR = _gdi_.FONTENCODING_EUC_KR
+#---------------------------------------------------------------------------
+
+class NativeFontInfo(object):
+ """Proxy of C++ NativeFontInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> NativeFontInfo"""
+ _gdi_.NativeFontInfo_swiginit(self,_gdi_.new_NativeFontInfo(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_NativeFontInfo
+ __del__ = lambda self : None;
+ def Init(*args, **kwargs):
+ """Init(self)"""
+ return _gdi_.NativeFontInfo_Init(*args, **kwargs)
+
+ def InitFromFont(*args, **kwargs):
+ """InitFromFont(self, Font font)"""
+ return _gdi_.NativeFontInfo_InitFromFont(*args, **kwargs)
+
+ def GetPointSize(*args, **kwargs):
+ """GetPointSize(self) -> int"""
+ return _gdi_.NativeFontInfo_GetPointSize(*args, **kwargs)
+
+ def GetPixelSize(*args, **kwargs):
+ """GetPixelSize(self) -> Size"""
+ return _gdi_.NativeFontInfo_GetPixelSize(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self) -> int"""
+ return _gdi_.NativeFontInfo_GetStyle(*args, **kwargs)
+
+ def GetWeight(*args, **kwargs):
+ """GetWeight(self) -> int"""
+ return _gdi_.NativeFontInfo_GetWeight(*args, **kwargs)
+
+ def GetUnderlined(*args, **kwargs):
+ """GetUnderlined(self) -> bool"""
+ return _gdi_.NativeFontInfo_GetUnderlined(*args, **kwargs)
+
+ def GetStrikethrough(*args, **kwargs):
+ """GetStrikethrough(self) -> bool"""
+ return _gdi_.NativeFontInfo_GetStrikethrough(*args, **kwargs)
+
+ def GetFaceName(*args, **kwargs):
+ """GetFaceName(self) -> String"""
+ return _gdi_.NativeFontInfo_GetFaceName(*args, **kwargs)
+
+ def GetFamily(*args, **kwargs):
+ """GetFamily(self) -> int"""
+ return _gdi_.NativeFontInfo_GetFamily(*args, **kwargs)
+
+ def GetEncoding(*args, **kwargs):
+ """GetEncoding(self) -> int"""
+ return _gdi_.NativeFontInfo_GetEncoding(*args, **kwargs)
+
+ def SetPointSize(*args, **kwargs):
+ """SetPointSize(self, int pointsize)"""
+ return _gdi_.NativeFontInfo_SetPointSize(*args, **kwargs)
+
+ def SetPixelSize(*args, **kwargs):
+ """SetPixelSize(self, Size pixelSize)"""
+ return _gdi_.NativeFontInfo_SetPixelSize(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """SetStyle(self, int style)"""
+ return _gdi_.NativeFontInfo_SetStyle(*args, **kwargs)
+
+ def SetWeight(*args, **kwargs):
+ """SetWeight(self, int weight)"""
+ return _gdi_.NativeFontInfo_SetWeight(*args, **kwargs)
+
+ def SetUnderlined(*args, **kwargs):
+ """SetUnderlined(self, bool underlined)"""
+ return _gdi_.NativeFontInfo_SetUnderlined(*args, **kwargs)
+
+ def SetStrikethrough(*args, **kwargs):
+ """SetStrikethrough(self, bool strikethrough)"""
+ return _gdi_.NativeFontInfo_SetStrikethrough(*args, **kwargs)
+
+ def SetFaceName(*args, **kwargs):
+ """SetFaceName(self, String facename) -> bool"""
+ return _gdi_.NativeFontInfo_SetFaceName(*args, **kwargs)
+
+ def SetFamily(*args, **kwargs):
+ """SetFamily(self, int family)"""
+ return _gdi_.NativeFontInfo_SetFamily(*args, **kwargs)
+
+ def SetEncoding(*args, **kwargs):
+ """SetEncoding(self, int encoding)"""
+ return _gdi_.NativeFontInfo_SetEncoding(*args, **kwargs)
+
+ def FromString(*args, **kwargs):
+ """FromString(self, String s) -> bool"""
+ return _gdi_.NativeFontInfo_FromString(*args, **kwargs)
+
+ def ToString(*args, **kwargs):
+ """ToString(self) -> String"""
+ return _gdi_.NativeFontInfo_ToString(*args, **kwargs)
+
+ def __str__(*args, **kwargs):
+ """__str__(self) -> String"""
+ return _gdi_.NativeFontInfo___str__(*args, **kwargs)
+
+ def FromUserString(*args, **kwargs):
+ """FromUserString(self, String s) -> bool"""
+ return _gdi_.NativeFontInfo_FromUserString(*args, **kwargs)
+
+ def ToUserString(*args, **kwargs):
+ """ToUserString(self) -> String"""
+ return _gdi_.NativeFontInfo_ToUserString(*args, **kwargs)
+
+ Encoding = property(GetEncoding,SetEncoding,doc="See `GetEncoding` and `SetEncoding`")
+ FaceName = property(GetFaceName,SetFaceName,doc="See `GetFaceName` and `SetFaceName`")
+ Family = property(GetFamily,SetFamily,doc="See `GetFamily` and `SetFamily`")
+ PointSize = property(GetPointSize,SetPointSize,doc="See `GetPointSize` and `SetPointSize`")
+ Style = property(GetStyle,SetStyle,doc="See `GetStyle` and `SetStyle`")
+ Underlined = property(GetUnderlined,SetUnderlined,doc="See `GetUnderlined` and `SetUnderlined`")
+ Weight = property(GetWeight,SetWeight,doc="See `GetWeight` and `SetWeight`")
+_gdi_.NativeFontInfo_swigregister(NativeFontInfo)
+
+class NativeEncodingInfo(object):
+ """Proxy of C++ NativeEncodingInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ facename = property(_gdi_.NativeEncodingInfo_facename_get, _gdi_.NativeEncodingInfo_facename_set)
+ encoding = property(_gdi_.NativeEncodingInfo_encoding_get, _gdi_.NativeEncodingInfo_encoding_set)
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> NativeEncodingInfo"""
+ _gdi_.NativeEncodingInfo_swiginit(self,_gdi_.new_NativeEncodingInfo(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_NativeEncodingInfo
+ __del__ = lambda self : None;
+ def FromString(*args, **kwargs):
+ """FromString(self, String s) -> bool"""
+ return _gdi_.NativeEncodingInfo_FromString(*args, **kwargs)
+
+ def ToString(*args, **kwargs):
+ """ToString(self) -> String"""
+ return _gdi_.NativeEncodingInfo_ToString(*args, **kwargs)
+
+_gdi_.NativeEncodingInfo_swigregister(NativeEncodingInfo)
+
+
+def GetNativeFontEncoding(*args, **kwargs):
+ """GetNativeFontEncoding(int encoding) -> NativeEncodingInfo"""
+ return _gdi_.GetNativeFontEncoding(*args, **kwargs)
+
+def TestFontEncoding(*args, **kwargs):
+ """TestFontEncoding(NativeEncodingInfo info) -> bool"""
+ return _gdi_.TestFontEncoding(*args, **kwargs)
+#---------------------------------------------------------------------------
+
+class FontMapper(object):
+ """Proxy of C++ FontMapper class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> FontMapper"""
+ _gdi_.FontMapper_swiginit(self,_gdi_.new_FontMapper(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_FontMapper
+ __del__ = lambda self : None;
+ def Get(*args, **kwargs):
+ """Get() -> FontMapper"""
+ return _gdi_.FontMapper_Get(*args, **kwargs)
+
+ Get = staticmethod(Get)
+ def Set(*args, **kwargs):
+ """Set(FontMapper mapper) -> FontMapper"""
+ return _gdi_.FontMapper_Set(*args, **kwargs)
+
+ Set = staticmethod(Set)
+ def CharsetToEncoding(*args, **kwargs):
+ """CharsetToEncoding(self, String charset, bool interactive=True) -> int"""
+ return _gdi_.FontMapper_CharsetToEncoding(*args, **kwargs)
+
+ def GetSupportedEncodingsCount(*args, **kwargs):
+ """GetSupportedEncodingsCount() -> size_t"""
+ return _gdi_.FontMapper_GetSupportedEncodingsCount(*args, **kwargs)
+
+ GetSupportedEncodingsCount = staticmethod(GetSupportedEncodingsCount)
+ def GetEncoding(*args, **kwargs):
+ """GetEncoding(size_t n) -> int"""
+ return _gdi_.FontMapper_GetEncoding(*args, **kwargs)
+
+ GetEncoding = staticmethod(GetEncoding)
+ def GetEncodingName(*args, **kwargs):
+ """GetEncodingName(int encoding) -> String"""
+ return _gdi_.FontMapper_GetEncodingName(*args, **kwargs)
+
+ GetEncodingName = staticmethod(GetEncodingName)
+ def GetEncodingDescription(*args, **kwargs):
+ """GetEncodingDescription(int encoding) -> String"""
+ return _gdi_.FontMapper_GetEncodingDescription(*args, **kwargs)
+
+ GetEncodingDescription = staticmethod(GetEncodingDescription)
+ def GetEncodingFromName(*args, **kwargs):
+ """GetEncodingFromName(String name) -> int"""
+ return _gdi_.FontMapper_GetEncodingFromName(*args, **kwargs)
+
+ GetEncodingFromName = staticmethod(GetEncodingFromName)
+ def SetConfigPath(*args, **kwargs):
+ """SetConfigPath(self, String prefix)"""
+ return _gdi_.FontMapper_SetConfigPath(*args, **kwargs)
+
+ def GetDefaultConfigPath(*args, **kwargs):
+ """GetDefaultConfigPath() -> String"""
+ return _gdi_.FontMapper_GetDefaultConfigPath(*args, **kwargs)
+
+ GetDefaultConfigPath = staticmethod(GetDefaultConfigPath)
+ def GetAltForEncoding(*args, **kwargs):
+ """GetAltForEncoding(self, int encoding, String facename=EmptyString, bool interactive=True) -> PyObject"""
+ return _gdi_.FontMapper_GetAltForEncoding(*args, **kwargs)
+
+ def IsEncodingAvailable(*args, **kwargs):
+ """IsEncodingAvailable(self, int encoding, String facename=EmptyString) -> bool"""
+ return _gdi_.FontMapper_IsEncodingAvailable(*args, **kwargs)
+
+ def SetDialogParent(*args, **kwargs):
+ """SetDialogParent(self, Window parent)"""
+ return _gdi_.FontMapper_SetDialogParent(*args, **kwargs)
+
+ def SetDialogTitle(*args, **kwargs):
+ """SetDialogTitle(self, String title)"""
+ return _gdi_.FontMapper_SetDialogTitle(*args, **kwargs)
+
+_gdi_.FontMapper_swigregister(FontMapper)
+
+def FontMapper_Get(*args):
+ """FontMapper_Get() -> FontMapper"""
+ return _gdi_.FontMapper_Get(*args)
+
+def FontMapper_Set(*args, **kwargs):
+ """FontMapper_Set(FontMapper mapper) -> FontMapper"""
+ return _gdi_.FontMapper_Set(*args, **kwargs)
+
+def FontMapper_GetSupportedEncodingsCount(*args):
+ """FontMapper_GetSupportedEncodingsCount() -> size_t"""
+ return _gdi_.FontMapper_GetSupportedEncodingsCount(*args)
+
+def FontMapper_GetEncoding(*args, **kwargs):
+ """FontMapper_GetEncoding(size_t n) -> int"""
+ return _gdi_.FontMapper_GetEncoding(*args, **kwargs)
+
+def FontMapper_GetEncodingName(*args, **kwargs):
+ """FontMapper_GetEncodingName(int encoding) -> String"""
+ return _gdi_.FontMapper_GetEncodingName(*args, **kwargs)
+
+def FontMapper_GetEncodingDescription(*args, **kwargs):
+ """FontMapper_GetEncodingDescription(int encoding) -> String"""
+ return _gdi_.FontMapper_GetEncodingDescription(*args, **kwargs)
+
+def FontMapper_GetEncodingFromName(*args, **kwargs):
+ """FontMapper_GetEncodingFromName(String name) -> int"""
+ return _gdi_.FontMapper_GetEncodingFromName(*args, **kwargs)
+
+def FontMapper_GetDefaultConfigPath(*args):
+ """FontMapper_GetDefaultConfigPath() -> String"""
+ return _gdi_.FontMapper_GetDefaultConfigPath(*args)
+
+#---------------------------------------------------------------------------
+
+class Font(GDIObject):
+ """
+ A font is an object which determines the appearance of text. Fonts are
+ used for drawing text to a device context, and setting the appearance
+ of a window's text.
+
+ You can retrieve the current system font settings with `wx.SystemSettings`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int pointSize, int family, int style, int weight, bool underline=False,
+ String face=EmptyString,
+ int encoding=FONTENCODING_DEFAULT) -> Font
+
+ Creates a font object with the specified attributes.
+
+ :param pointSize: The size of the font in points.
+
+ :param family: Font family. A generic way of referring to fonts
+ without specifying actual facename. It can be One of
+ the ``wx.FONTFAMILY_xxx`` constants.
+
+ :param style: One of the ``wx.FONTSTYLE_xxx`` constants.
+
+ :param weight: Font weight, sometimes also referred to as font
+ boldness. One of the ``wx.FONTWEIGHT_xxx`` constants.
+
+ :param underline: The value can be ``True`` or ``False`` and
+ indicates whether the font will include an underline. This
+ may not be supported on all platforms.
+
+ :param face: An optional string specifying the actual typeface to
+ be used. If it is an empty string, a default typeface will be
+ chosen based on the family.
+
+ :param encoding: An encoding which may be one of the
+ ``wx.FONTENCODING_xxx`` constants. If the specified encoding isn't
+ available, no font is created.
+
+ :see: `wx.FFont`, `wx.FontFromPixelSize`, `wx.FFontFromPixelSize`,
+ `wx.FontFromNativeInfoString`, `wx.FontFromNativeInfo`
+
+ """
+ if kwargs.has_key('faceName'): kwargs['face'] = kwargs['faceName'];del kwargs['faceName']
+ _gdi_.Font_swiginit(self,_gdi_.new_Font(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Font
+ __del__ = lambda self : None;
+ def IsOk(*args, **kwargs):
+ """
+ IsOk(self) -> bool
+
+ Returns ``True`` if this font was successfully created.
+ """
+ return _gdi_.Font_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def __nonzero__(self): return self.IsOk()
+ def __eq__(*args, **kwargs):
+ """__eq__(self, Font other) -> bool"""
+ return _gdi_.Font___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """__ne__(self, Font other) -> bool"""
+ return _gdi_.Font___ne__(*args, **kwargs)
+
+ def GetPointSize(*args, **kwargs):
+ """
+ GetPointSize(self) -> int
+
+ Gets the point size.
+ """
+ return _gdi_.Font_GetPointSize(*args, **kwargs)
+
+ def GetPixelSize(*args, **kwargs):
+ """
+ GetPixelSize(self) -> Size
+
+ Returns the size in pixels if the font was constructed with a pixel
+ size.
+ """
+ return _gdi_.Font_GetPixelSize(*args, **kwargs)
+
+ def IsUsingSizeInPixels(*args, **kwargs):
+ """
+ IsUsingSizeInPixels(self) -> bool
+
+ Returns ``True`` if the font is using a pixelSize.
+ """
+ return _gdi_.Font_IsUsingSizeInPixels(*args, **kwargs)
+
+ def GetFamily(*args, **kwargs):
+ """
+ GetFamily(self) -> int
+
+ Gets the font family.
+ """
+ return _gdi_.Font_GetFamily(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """
+ GetStyle(self) -> int
+
+ Gets the font style.
+ """
+ return _gdi_.Font_GetStyle(*args, **kwargs)
+
+ def GetWeight(*args, **kwargs):
+ """
+ GetWeight(self) -> int
+
+ Gets the font weight.
+ """
+ return _gdi_.Font_GetWeight(*args, **kwargs)
+
+ def GetUnderlined(*args, **kwargs):
+ """
+ GetUnderlined(self) -> bool
+
+ Returns ``True`` if the font is underlined, ``False`` otherwise.
+ """
+ return _gdi_.Font_GetUnderlined(*args, **kwargs)
+
+ def GetStrikethrough(*args, **kwargs):
+ """GetStrikethrough(self) -> bool"""
+ return _gdi_.Font_GetStrikethrough(*args, **kwargs)
+
+ def GetFaceName(*args, **kwargs):
+ """
+ GetFaceName(self) -> String
+
+ Returns the typeface name associated with the font, or the empty
+ string if there is no typeface information.
+ """
+ return _gdi_.Font_GetFaceName(*args, **kwargs)
+
+ def GetEncoding(*args, **kwargs):
+ """
+ GetEncoding(self) -> int
+
+ Get the font's encoding.
+ """
+ return _gdi_.Font_GetEncoding(*args, **kwargs)
+
+ def GetNativeFontInfo(*args, **kwargs):
+ """
+ GetNativeFontInfo(self) -> NativeFontInfo
+
+ Constructs a `wx.NativeFontInfo` object from this font.
+ """
+ return _gdi_.Font_GetNativeFontInfo(*args, **kwargs)
+
+ def IsFixedWidth(*args, **kwargs):
+ """
+ IsFixedWidth(self) -> bool
+
+ Returns true if the font is a fixed width (or monospaced) font, false
+ if it is a proportional one or font is invalid.
+ """
+ return _gdi_.Font_IsFixedWidth(*args, **kwargs)
+
+ def GetNativeFontInfoDesc(*args, **kwargs):
+ """
+ GetNativeFontInfoDesc(self) -> String
+
+ Returns the platform-dependent string completely describing this font
+ or an empty string if the font isn't valid.
+ """
+ return _gdi_.Font_GetNativeFontInfoDesc(*args, **kwargs)
+
+ def GetNativeFontInfoUserDesc(*args, **kwargs):
+ """
+ GetNativeFontInfoUserDesc(self) -> String
+
+ Returns a human readable version of `GetNativeFontInfoDesc`.
+ """
+ return _gdi_.Font_GetNativeFontInfoUserDesc(*args, **kwargs)
+
+ def SetPointSize(*args, **kwargs):
+ """
+ SetPointSize(self, int pointSize)
+
+ Sets the point size.
+ """
+ return _gdi_.Font_SetPointSize(*args, **kwargs)
+
+ def SetPixelSize(*args, **kwargs):
+ """
+ SetPixelSize(self, Size pixelSize)
+
+ Sets the size in pixels rather than points. If there is platform API
+ support for this then it is used, otherwise a font with the closest
+ size is found using a binary search.
+ """
+ return _gdi_.Font_SetPixelSize(*args, **kwargs)
+
+ def SetFamily(*args, **kwargs):
+ """
+ SetFamily(self, int family)
+
+ Sets the font family.
+ """
+ return _gdi_.Font_SetFamily(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """
+ SetStyle(self, int style)
+
+ Sets the font style.
+ """
+ return _gdi_.Font_SetStyle(*args, **kwargs)
+
+ def SetWeight(*args, **kwargs):
+ """
+ SetWeight(self, int weight)
+
+ Sets the font weight.
+ """
+ return _gdi_.Font_SetWeight(*args, **kwargs)
+
+ def SetFaceName(*args, **kwargs):
+ """
+ SetFaceName(self, String faceName) -> bool
+
+ Sets the facename for the font. The facename, which should be a valid
+ font installed on the end-user's system.
+
+ To avoid portability problems, don't rely on a specific face, but
+ specify the font family instead or as well. A suitable font will be
+ found on the end-user's system. If both the family and the facename
+ are specified, wxWidgets will first search for the specific face, and
+ then for a font belonging to the same family.
+ """
+ return _gdi_.Font_SetFaceName(*args, **kwargs)
+
+ def SetUnderlined(*args, **kwargs):
+ """
+ SetUnderlined(self, bool underlined)
+
+ Sets underlining.
+ """
+ return _gdi_.Font_SetUnderlined(*args, **kwargs)
+
+ def SetStrikethrough(*args, **kwargs):
+ """SetStrikethrough(self, bool strikethrough)"""
+ return _gdi_.Font_SetStrikethrough(*args, **kwargs)
+
+ def SetEncoding(*args, **kwargs):
+ """
+ SetEncoding(self, int encoding)
+
+ Set the font encoding.
+ """
+ return _gdi_.Font_SetEncoding(*args, **kwargs)
+
+ def SetNativeFontInfo(*args, **kwargs):
+ """
+ SetNativeFontInfo(self, NativeFontInfo info)
+
+ Set the font's attributes from a `wx.NativeFontInfo` object.
+ """
+ return _gdi_.Font_SetNativeFontInfo(*args, **kwargs)
+
+ def SetNativeFontInfoFromString(*args, **kwargs):
+ """
+ SetNativeFontInfoFromString(self, String info) -> bool
+
+ Set the font's attributes from string representation of a
+ `wx.NativeFontInfo` object.
+ """
+ return _gdi_.Font_SetNativeFontInfoFromString(*args, **kwargs)
+
+ def SetNativeFontInfoUserDesc(*args, **kwargs):
+ """
+ SetNativeFontInfoUserDesc(self, String info) -> bool
+
+ Set the font's attributes from a string formerly returned from
+ `GetNativeFontInfoDesc`.
+ """
+ return _gdi_.Font_SetNativeFontInfoUserDesc(*args, **kwargs)
+
+ def SetSymbolicSize(*args, **kwargs):
+ """SetSymbolicSize(self, int size)"""
+ return _gdi_.Font_SetSymbolicSize(*args, **kwargs)
+
+ def SetSymbolicSizeRelativeTo(*args, **kwargs):
+ """SetSymbolicSizeRelativeTo(self, int size, int base)"""
+ return _gdi_.Font_SetSymbolicSizeRelativeTo(*args, **kwargs)
+
+ def AdjustToSymbolicSize(*args, **kwargs):
+ """AdjustToSymbolicSize(int size, int base) -> int"""
+ return _gdi_.Font_AdjustToSymbolicSize(*args, **kwargs)
+
+ AdjustToSymbolicSize = staticmethod(AdjustToSymbolicSize)
+ def GetFamilyString(*args, **kwargs):
+ """
+ GetFamilyString(self) -> String
+
+ Returns a string representation of the font family.
+ """
+ return _gdi_.Font_GetFamilyString(*args, **kwargs)
+
+ def GetStyleString(*args, **kwargs):
+ """
+ GetStyleString(self) -> String
+
+ Returns a string representation of the font style.
+ """
+ return _gdi_.Font_GetStyleString(*args, **kwargs)
+
+ def GetWeightString(*args, **kwargs):
+ """
+ GetWeightString(self) -> String
+
+ Return a string representation of the font weight.
+ """
+ return _gdi_.Font_GetWeightString(*args, **kwargs)
+
+ def SetNoAntiAliasing(*args, **kwargs):
+ """SetNoAntiAliasing(self, bool no=True)"""
+ return _gdi_.Font_SetNoAntiAliasing(*args, **kwargs)
+
+ def GetNoAntiAliasing(*args, **kwargs):
+ """GetNoAntiAliasing(self) -> bool"""
+ return _gdi_.Font_GetNoAntiAliasing(*args, **kwargs)
+
+ SetNoAntiAliasing = wx.deprecated(SetNoAntiAliasing)
+ GetNoAntiAliasing = wx.deprecated(GetNoAntiAliasing)
+
+ def MakeBold(*args, **kwargs):
+ """MakeBold(self) -> Font"""
+ return _gdi_.Font_MakeBold(*args, **kwargs)
+
+ def MakeItalic(*args, **kwargs):
+ """MakeItalic(self) -> Font"""
+ return _gdi_.Font_MakeItalic(*args, **kwargs)
+
+ def MakeUnderlined(*args, **kwargs):
+ """MakeUnderlined(self) -> Font"""
+ return _gdi_.Font_MakeUnderlined(*args, **kwargs)
+
+ def MakeStrikethrough(*args, **kwargs):
+ """MakeStrikethrough(self) -> Font"""
+ return _gdi_.Font_MakeStrikethrough(*args, **kwargs)
+
+ def MakeLarger(*args, **kwargs):
+ """MakeLarger(self) -> Font"""
+ return _gdi_.Font_MakeLarger(*args, **kwargs)
+
+ def MakeSmaller(*args, **kwargs):
+ """MakeSmaller(self) -> Font"""
+ return _gdi_.Font_MakeSmaller(*args, **kwargs)
+
+ def Scale(*args, **kwargs):
+ """Scale(self, float x) -> Font"""
+ return _gdi_.Font_Scale(*args, **kwargs)
+
+ def Bold(*args, **kwargs):
+ """Bold(self) -> Font"""
+ return _gdi_.Font_Bold(*args, **kwargs)
+
+ def Italic(*args, **kwargs):
+ """Italic(self) -> Font"""
+ return _gdi_.Font_Italic(*args, **kwargs)
+
+ def Underlined(*args, **kwargs):
+ """Underlined(self) -> Font"""
+ return _gdi_.Font_Underlined(*args, **kwargs)
+
+ def Strikethrough(*args, **kwargs):
+ """Strikethrough(self) -> Font"""
+ return _gdi_.Font_Strikethrough(*args, **kwargs)
+
+ def Larger(*args, **kwargs):
+ """Larger(self) -> Font"""
+ return _gdi_.Font_Larger(*args, **kwargs)
+
+ def Smaller(*args, **kwargs):
+ """Smaller(self) -> Font"""
+ return _gdi_.Font_Smaller(*args, **kwargs)
+
+ def Scaled(*args, **kwargs):
+ """Scaled(self, float x) -> Font"""
+ return _gdi_.Font_Scaled(*args, **kwargs)
+
+ def GetHFONT(*args, **kwargs):
+ """GetHFONT(self) -> void"""
+ return _gdi_.Font_GetHFONT(*args, **kwargs)
+
+ def GetDefaultEncoding(*args, **kwargs):
+ """
+ GetDefaultEncoding() -> int
+
+ Returns the encoding used for all fonts created with an encoding of
+ ``wx.FONTENCODING_DEFAULT``.
+ """
+ return _gdi_.Font_GetDefaultEncoding(*args, **kwargs)
+
+ GetDefaultEncoding = staticmethod(GetDefaultEncoding)
+ def SetDefaultEncoding(*args, **kwargs):
+ """
+ SetDefaultEncoding(int encoding)
+
+ Sets the default font encoding.
+ """
+ return _gdi_.Font_SetDefaultEncoding(*args, **kwargs)
+
+ SetDefaultEncoding = staticmethod(SetDefaultEncoding)
+ Encoding = property(GetEncoding,SetEncoding,doc="See `GetEncoding` and `SetEncoding`")
+ FaceName = property(GetFaceName,SetFaceName,doc="See `GetFaceName` and `SetFaceName`")
+ Family = property(GetFamily,SetFamily,doc="See `GetFamily` and `SetFamily`")
+ FamilyString = property(GetFamilyString,doc="See `GetFamilyString`")
+ NativeFontInfo = property(GetNativeFontInfo,SetNativeFontInfo,doc="See `GetNativeFontInfo` and `SetNativeFontInfo`")
+ NativeFontInfoDesc = property(GetNativeFontInfoDesc,doc="See `GetNativeFontInfoDesc`")
+ NativeFontInfoUserDesc = property(GetNativeFontInfoUserDesc,SetNativeFontInfoUserDesc,doc="See `GetNativeFontInfoUserDesc` and `SetNativeFontInfoUserDesc`")
+ NoAntiAliasing = property(GetNoAntiAliasing,SetNoAntiAliasing,doc="See `GetNoAntiAliasing` and `SetNoAntiAliasing`")
+ PixelSize = property(GetPixelSize,SetPixelSize,doc="See `GetPixelSize` and `SetPixelSize`")
+ PointSize = property(GetPointSize,SetPointSize,doc="See `GetPointSize` and `SetPointSize`")
+ Style = property(GetStyle,SetStyle,doc="See `GetStyle` and `SetStyle`")
+ StyleString = property(GetStyleString,doc="See `GetStyleString`")
+ Weight = property(GetWeight,SetWeight,doc="See `GetWeight` and `SetWeight`")
+ WeightString = property(GetWeightString,doc="See `GetWeightString`")
+_gdi_.Font_swigregister(Font)
+
+def FontFromNativeInfo(*args, **kwargs):
+ """
+ FontFromNativeInfo(NativeFontInfo info) -> Font
+
+ Construct a `wx.Font` from a `wx.NativeFontInfo` object.
+ """
+ if kwargs.has_key('faceName'): kwargs['face'] = kwargs['faceName'];del kwargs['faceName']
+ val = _gdi_.new_FontFromNativeInfo(*args, **kwargs)
+ return val
+
+def FontFromNativeInfoString(*args, **kwargs):
+ """
+ FontFromNativeInfoString(String info) -> Font
+
+ Construct a `wx.Font` from the string representation of a
+ `wx.NativeFontInfo` object.
+ """
+ if kwargs.has_key('faceName'): kwargs['face'] = kwargs['faceName'];del kwargs['faceName']
+ val = _gdi_.new_FontFromNativeInfoString(*args, **kwargs)
+ return val
+
+def FFont(*args, **kwargs):
+ """
+ FFont(int pointSize, int family, int flags=FONTFLAG_DEFAULT,
+ String face=EmptyString, int encoding=FONTENCODING_DEFAULT) -> Font
+
+ A bit of a simpler way to create a `wx.Font` using flags instead of
+ individual attribute settings. The value of flags can be a
+ combination of the following:
+
+ ============================ ==
+ wx.FONTFLAG_DEFAULT
+ wx.FONTFLAG_ITALIC
+ wx.FONTFLAG_SLANT
+ wx.FONTFLAG_LIGHT
+ wx.FONTFLAG_BOLD
+ wx.FONTFLAG_ANTIALIASED
+ wx.FONTFLAG_NOT_ANTIALIASED
+ wx.FONTFLAG_UNDERLINED
+ wx.FONTFLAG_STRIKETHROUGH
+ ============================ ==
+
+ :see: `wx.Font.__init__`
+ """
+ if kwargs.has_key('faceName'): kwargs['face'] = kwargs['faceName'];del kwargs['faceName']
+ val = _gdi_.new_FFont(*args, **kwargs)
+ return val
+
+def FontFromPixelSize(*args, **kwargs):
+ """
+ FontFromPixelSize(Size pixelSize, int family, int style, int weight,
+ bool underlined=False, String face=wxEmptyString,
+ int encoding=FONTENCODING_DEFAULT) -> Font
+
+ Creates a font using a size in pixels rather than points. If there is
+ platform API support for this then it is used, otherwise a font with
+ the closest size is found using a binary search.
+
+ :see: `wx.Font.__init__`
+ """
+ if kwargs.has_key('faceName'): kwargs['face'] = kwargs['faceName'];del kwargs['faceName']
+ val = _gdi_.new_FontFromPixelSize(*args, **kwargs)
+ return val
+
+def FFontFromPixelSize(*args, **kwargs):
+ """
+ FFontFromPixelSize(Size pixelSize, int family, int flags=FONTFLAG_DEFAULT,
+ String face=wxEmptyString, int encoding=FONTENCODING_DEFAULT) -> Font
+
+ Creates a font using a size in pixels rather than points. If there is
+ platform API support for this then it is used, otherwise a font with
+ the closest size is found using a binary search.
+
+ :see: `wx.Font.__init__`, `wx.FFont`
+ """
+ if kwargs.has_key('faceName'): kwargs['face'] = kwargs['faceName'];del kwargs['faceName']
+ val = _gdi_.new_FFontFromPixelSize(*args, **kwargs)
+ return val
+
+def Font_AdjustToSymbolicSize(*args, **kwargs):
+ """Font_AdjustToSymbolicSize(int size, int base) -> int"""
+ return _gdi_.Font_AdjustToSymbolicSize(*args, **kwargs)
+
+def Font_GetDefaultEncoding(*args):
+ """
+ Font_GetDefaultEncoding() -> int
+
+ Returns the encoding used for all fonts created with an encoding of
+ ``wx.FONTENCODING_DEFAULT``.
+ """
+ return _gdi_.Font_GetDefaultEncoding(*args)
+
+def Font_SetDefaultEncoding(*args, **kwargs):
+ """
+ Font_SetDefaultEncoding(int encoding)
+
+ Sets the default font encoding.
+ """
+ return _gdi_.Font_SetDefaultEncoding(*args, **kwargs)
+
+Font2 = wx.deprecated(FFont, "Use `wx.FFont` instead.")
+#---------------------------------------------------------------------------
+
+class FontEnumerator(object):
+ """Proxy of C++ FontEnumerator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> FontEnumerator"""
+ _gdi_.FontEnumerator_swiginit(self,_gdi_.new_FontEnumerator(*args, **kwargs))
+ FontEnumerator._setCallbackInfo(self, self, FontEnumerator)
+
+ __swig_destroy__ = _gdi_.delete_FontEnumerator
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class, int incref=0)"""
+ return _gdi_.FontEnumerator__setCallbackInfo(*args, **kwargs)
+
+ def EnumerateFacenames(*args, **kwargs):
+ """EnumerateFacenames(self, int encoding=FONTENCODING_SYSTEM, bool fixedWidthOnly=False) -> bool"""
+ return _gdi_.FontEnumerator_EnumerateFacenames(*args, **kwargs)
+
+ def EnumerateEncodings(*args, **kwargs):
+ """EnumerateEncodings(self, String facename=EmptyString) -> bool"""
+ return _gdi_.FontEnumerator_EnumerateEncodings(*args, **kwargs)
+
+ def GetEncodings(*args, **kwargs):
+ """GetEncodings() -> PyObject"""
+ return _gdi_.FontEnumerator_GetEncodings(*args, **kwargs)
+
+ GetEncodings = staticmethod(GetEncodings)
+ def GetFacenames(*args, **kwargs):
+ """GetFacenames() -> PyObject"""
+ return _gdi_.FontEnumerator_GetFacenames(*args, **kwargs)
+
+ GetFacenames = staticmethod(GetFacenames)
+ def IsValidFacename(*args, **kwargs):
+ """
+ IsValidFacename(String str) -> bool
+
+ Convenience function that returns true if the given face name exist in
+ the user's system
+ """
+ return _gdi_.FontEnumerator_IsValidFacename(*args, **kwargs)
+
+ IsValidFacename = staticmethod(IsValidFacename)
+_gdi_.FontEnumerator_swigregister(FontEnumerator)
+
+def FontEnumerator_GetEncodings(*args):
+ """FontEnumerator_GetEncodings() -> PyObject"""
+ return _gdi_.FontEnumerator_GetEncodings(*args)
+
+def FontEnumerator_GetFacenames(*args):
+ """FontEnumerator_GetFacenames() -> PyObject"""
+ return _gdi_.FontEnumerator_GetFacenames(*args)
+
+def FontEnumerator_IsValidFacename(*args, **kwargs):
+ """
+ FontEnumerator_IsValidFacename(String str) -> bool
+
+ Convenience function that returns true if the given face name exist in
+ the user's system
+ """
+ return _gdi_.FontEnumerator_IsValidFacename(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+LANGUAGE_DEFAULT = _gdi_.LANGUAGE_DEFAULT
+LANGUAGE_UNKNOWN = _gdi_.LANGUAGE_UNKNOWN
+LANGUAGE_ABKHAZIAN = _gdi_.LANGUAGE_ABKHAZIAN
+LANGUAGE_AFAR = _gdi_.LANGUAGE_AFAR
+LANGUAGE_AFRIKAANS = _gdi_.LANGUAGE_AFRIKAANS
+LANGUAGE_ALBANIAN = _gdi_.LANGUAGE_ALBANIAN
+LANGUAGE_AMHARIC = _gdi_.LANGUAGE_AMHARIC
+LANGUAGE_ARABIC = _gdi_.LANGUAGE_ARABIC
+LANGUAGE_ARABIC_ALGERIA = _gdi_.LANGUAGE_ARABIC_ALGERIA
+LANGUAGE_ARABIC_BAHRAIN = _gdi_.LANGUAGE_ARABIC_BAHRAIN
+LANGUAGE_ARABIC_EGYPT = _gdi_.LANGUAGE_ARABIC_EGYPT
+LANGUAGE_ARABIC_IRAQ = _gdi_.LANGUAGE_ARABIC_IRAQ
+LANGUAGE_ARABIC_JORDAN = _gdi_.LANGUAGE_ARABIC_JORDAN
+LANGUAGE_ARABIC_KUWAIT = _gdi_.LANGUAGE_ARABIC_KUWAIT
+LANGUAGE_ARABIC_LEBANON = _gdi_.LANGUAGE_ARABIC_LEBANON
+LANGUAGE_ARABIC_LIBYA = _gdi_.LANGUAGE_ARABIC_LIBYA
+LANGUAGE_ARABIC_MOROCCO = _gdi_.LANGUAGE_ARABIC_MOROCCO
+LANGUAGE_ARABIC_OMAN = _gdi_.LANGUAGE_ARABIC_OMAN
+LANGUAGE_ARABIC_QATAR = _gdi_.LANGUAGE_ARABIC_QATAR
+LANGUAGE_ARABIC_SAUDI_ARABIA = _gdi_.LANGUAGE_ARABIC_SAUDI_ARABIA
+LANGUAGE_ARABIC_SUDAN = _gdi_.LANGUAGE_ARABIC_SUDAN
+LANGUAGE_ARABIC_SYRIA = _gdi_.LANGUAGE_ARABIC_SYRIA
+LANGUAGE_ARABIC_TUNISIA = _gdi_.LANGUAGE_ARABIC_TUNISIA
+LANGUAGE_ARABIC_UAE = _gdi_.LANGUAGE_ARABIC_UAE
+LANGUAGE_ARABIC_YEMEN = _gdi_.LANGUAGE_ARABIC_YEMEN
+LANGUAGE_ARMENIAN = _gdi_.LANGUAGE_ARMENIAN
+LANGUAGE_ASSAMESE = _gdi_.LANGUAGE_ASSAMESE
+LANGUAGE_ASTURIAN = _gdi_.LANGUAGE_ASTURIAN
+LANGUAGE_AYMARA = _gdi_.LANGUAGE_AYMARA
+LANGUAGE_AZERI = _gdi_.LANGUAGE_AZERI
+LANGUAGE_AZERI_CYRILLIC = _gdi_.LANGUAGE_AZERI_CYRILLIC
+LANGUAGE_AZERI_LATIN = _gdi_.LANGUAGE_AZERI_LATIN
+LANGUAGE_BASHKIR = _gdi_.LANGUAGE_BASHKIR
+LANGUAGE_BASQUE = _gdi_.LANGUAGE_BASQUE
+LANGUAGE_BELARUSIAN = _gdi_.LANGUAGE_BELARUSIAN
+LANGUAGE_BENGALI = _gdi_.LANGUAGE_BENGALI
+LANGUAGE_BHUTANI = _gdi_.LANGUAGE_BHUTANI
+LANGUAGE_BIHARI = _gdi_.LANGUAGE_BIHARI
+LANGUAGE_BISLAMA = _gdi_.LANGUAGE_BISLAMA
+LANGUAGE_BRETON = _gdi_.LANGUAGE_BRETON
+LANGUAGE_BULGARIAN = _gdi_.LANGUAGE_BULGARIAN
+LANGUAGE_BURMESE = _gdi_.LANGUAGE_BURMESE
+LANGUAGE_CAMBODIAN = _gdi_.LANGUAGE_CAMBODIAN
+LANGUAGE_CATALAN = _gdi_.LANGUAGE_CATALAN
+LANGUAGE_CHINESE = _gdi_.LANGUAGE_CHINESE
+LANGUAGE_CHINESE_SIMPLIFIED = _gdi_.LANGUAGE_CHINESE_SIMPLIFIED
+LANGUAGE_CHINESE_TRADITIONAL = _gdi_.LANGUAGE_CHINESE_TRADITIONAL
+LANGUAGE_CHINESE_HONGKONG = _gdi_.LANGUAGE_CHINESE_HONGKONG
+LANGUAGE_CHINESE_MACAU = _gdi_.LANGUAGE_CHINESE_MACAU
+LANGUAGE_CHINESE_SINGAPORE = _gdi_.LANGUAGE_CHINESE_SINGAPORE
+LANGUAGE_CHINESE_TAIWAN = _gdi_.LANGUAGE_CHINESE_TAIWAN
+LANGUAGE_CORSICAN = _gdi_.LANGUAGE_CORSICAN
+LANGUAGE_CROATIAN = _gdi_.LANGUAGE_CROATIAN
+LANGUAGE_CZECH = _gdi_.LANGUAGE_CZECH
+LANGUAGE_DANISH = _gdi_.LANGUAGE_DANISH
+LANGUAGE_DUTCH = _gdi_.LANGUAGE_DUTCH
+LANGUAGE_DUTCH_BELGIAN = _gdi_.LANGUAGE_DUTCH_BELGIAN
+LANGUAGE_ENGLISH = _gdi_.LANGUAGE_ENGLISH
+LANGUAGE_ENGLISH_UK = _gdi_.LANGUAGE_ENGLISH_UK
+LANGUAGE_ENGLISH_US = _gdi_.LANGUAGE_ENGLISH_US
+LANGUAGE_ENGLISH_AUSTRALIA = _gdi_.LANGUAGE_ENGLISH_AUSTRALIA
+LANGUAGE_ENGLISH_BELIZE = _gdi_.LANGUAGE_ENGLISH_BELIZE
+LANGUAGE_ENGLISH_BOTSWANA = _gdi_.LANGUAGE_ENGLISH_BOTSWANA
+LANGUAGE_ENGLISH_CANADA = _gdi_.LANGUAGE_ENGLISH_CANADA
+LANGUAGE_ENGLISH_CARIBBEAN = _gdi_.LANGUAGE_ENGLISH_CARIBBEAN
+LANGUAGE_ENGLISH_DENMARK = _gdi_.LANGUAGE_ENGLISH_DENMARK
+LANGUAGE_ENGLISH_EIRE = _gdi_.LANGUAGE_ENGLISH_EIRE
+LANGUAGE_ENGLISH_JAMAICA = _gdi_.LANGUAGE_ENGLISH_JAMAICA
+LANGUAGE_ENGLISH_NEW_ZEALAND = _gdi_.LANGUAGE_ENGLISH_NEW_ZEALAND
+LANGUAGE_ENGLISH_PHILIPPINES = _gdi_.LANGUAGE_ENGLISH_PHILIPPINES
+LANGUAGE_ENGLISH_SOUTH_AFRICA = _gdi_.LANGUAGE_ENGLISH_SOUTH_AFRICA
+LANGUAGE_ENGLISH_TRINIDAD = _gdi_.LANGUAGE_ENGLISH_TRINIDAD
+LANGUAGE_ENGLISH_ZIMBABWE = _gdi_.LANGUAGE_ENGLISH_ZIMBABWE
+LANGUAGE_ESPERANTO = _gdi_.LANGUAGE_ESPERANTO
+LANGUAGE_ESTONIAN = _gdi_.LANGUAGE_ESTONIAN
+LANGUAGE_FAEROESE = _gdi_.LANGUAGE_FAEROESE
+LANGUAGE_FARSI = _gdi_.LANGUAGE_FARSI
+LANGUAGE_FIJI = _gdi_.LANGUAGE_FIJI
+LANGUAGE_FINNISH = _gdi_.LANGUAGE_FINNISH
+LANGUAGE_FRENCH = _gdi_.LANGUAGE_FRENCH
+LANGUAGE_FRENCH_BELGIAN = _gdi_.LANGUAGE_FRENCH_BELGIAN
+LANGUAGE_FRENCH_CANADIAN = _gdi_.LANGUAGE_FRENCH_CANADIAN
+LANGUAGE_FRENCH_LUXEMBOURG = _gdi_.LANGUAGE_FRENCH_LUXEMBOURG
+LANGUAGE_FRENCH_MONACO = _gdi_.LANGUAGE_FRENCH_MONACO
+LANGUAGE_FRENCH_SWISS = _gdi_.LANGUAGE_FRENCH_SWISS
+LANGUAGE_FRISIAN = _gdi_.LANGUAGE_FRISIAN
+LANGUAGE_GALICIAN = _gdi_.LANGUAGE_GALICIAN
+LANGUAGE_GEORGIAN = _gdi_.LANGUAGE_GEORGIAN
+LANGUAGE_GERMAN = _gdi_.LANGUAGE_GERMAN
+LANGUAGE_GERMAN_AUSTRIAN = _gdi_.LANGUAGE_GERMAN_AUSTRIAN
+LANGUAGE_GERMAN_BELGIUM = _gdi_.LANGUAGE_GERMAN_BELGIUM
+LANGUAGE_GERMAN_LIECHTENSTEIN = _gdi_.LANGUAGE_GERMAN_LIECHTENSTEIN
+LANGUAGE_GERMAN_LUXEMBOURG = _gdi_.LANGUAGE_GERMAN_LUXEMBOURG
+LANGUAGE_GERMAN_SWISS = _gdi_.LANGUAGE_GERMAN_SWISS
+LANGUAGE_GREEK = _gdi_.LANGUAGE_GREEK
+LANGUAGE_GREENLANDIC = _gdi_.LANGUAGE_GREENLANDIC
+LANGUAGE_GUARANI = _gdi_.LANGUAGE_GUARANI
+LANGUAGE_GUJARATI = _gdi_.LANGUAGE_GUJARATI
+LANGUAGE_HAUSA = _gdi_.LANGUAGE_HAUSA
+LANGUAGE_HEBREW = _gdi_.LANGUAGE_HEBREW
+LANGUAGE_HINDI = _gdi_.LANGUAGE_HINDI
+LANGUAGE_HUNGARIAN = _gdi_.LANGUAGE_HUNGARIAN
+LANGUAGE_ICELANDIC = _gdi_.LANGUAGE_ICELANDIC
+LANGUAGE_INDONESIAN = _gdi_.LANGUAGE_INDONESIAN
+LANGUAGE_INTERLINGUA = _gdi_.LANGUAGE_INTERLINGUA
+LANGUAGE_INTERLINGUE = _gdi_.LANGUAGE_INTERLINGUE
+LANGUAGE_INUKTITUT = _gdi_.LANGUAGE_INUKTITUT
+LANGUAGE_INUPIAK = _gdi_.LANGUAGE_INUPIAK
+LANGUAGE_IRISH = _gdi_.LANGUAGE_IRISH
+LANGUAGE_ITALIAN = _gdi_.LANGUAGE_ITALIAN
+LANGUAGE_ITALIAN_SWISS = _gdi_.LANGUAGE_ITALIAN_SWISS
+LANGUAGE_JAPANESE = _gdi_.LANGUAGE_JAPANESE
+LANGUAGE_JAVANESE = _gdi_.LANGUAGE_JAVANESE
+LANGUAGE_KANNADA = _gdi_.LANGUAGE_KANNADA
+LANGUAGE_KASHMIRI = _gdi_.LANGUAGE_KASHMIRI
+LANGUAGE_KASHMIRI_INDIA = _gdi_.LANGUAGE_KASHMIRI_INDIA
+LANGUAGE_KAZAKH = _gdi_.LANGUAGE_KAZAKH
+LANGUAGE_KERNEWEK = _gdi_.LANGUAGE_KERNEWEK
+LANGUAGE_KINYARWANDA = _gdi_.LANGUAGE_KINYARWANDA
+LANGUAGE_KIRGHIZ = _gdi_.LANGUAGE_KIRGHIZ
+LANGUAGE_KIRUNDI = _gdi_.LANGUAGE_KIRUNDI
+LANGUAGE_KONKANI = _gdi_.LANGUAGE_KONKANI
+LANGUAGE_KOREAN = _gdi_.LANGUAGE_KOREAN
+LANGUAGE_KURDISH = _gdi_.LANGUAGE_KURDISH
+LANGUAGE_LAOTHIAN = _gdi_.LANGUAGE_LAOTHIAN
+LANGUAGE_LATIN = _gdi_.LANGUAGE_LATIN
+LANGUAGE_LATVIAN = _gdi_.LANGUAGE_LATVIAN
+LANGUAGE_LINGALA = _gdi_.LANGUAGE_LINGALA
+LANGUAGE_LITHUANIAN = _gdi_.LANGUAGE_LITHUANIAN
+LANGUAGE_MACEDONIAN = _gdi_.LANGUAGE_MACEDONIAN
+LANGUAGE_MALAGASY = _gdi_.LANGUAGE_MALAGASY
+LANGUAGE_MALAY = _gdi_.LANGUAGE_MALAY
+LANGUAGE_MALAYALAM = _gdi_.LANGUAGE_MALAYALAM
+LANGUAGE_MALAY_BRUNEI_DARUSSALAM = _gdi_.LANGUAGE_MALAY_BRUNEI_DARUSSALAM
+LANGUAGE_MALAY_MALAYSIA = _gdi_.LANGUAGE_MALAY_MALAYSIA
+LANGUAGE_MALTESE = _gdi_.LANGUAGE_MALTESE
+LANGUAGE_MANIPURI = _gdi_.LANGUAGE_MANIPURI
+LANGUAGE_MAORI = _gdi_.LANGUAGE_MAORI
+LANGUAGE_MARATHI = _gdi_.LANGUAGE_MARATHI
+LANGUAGE_MOLDAVIAN = _gdi_.LANGUAGE_MOLDAVIAN
+LANGUAGE_MONGOLIAN = _gdi_.LANGUAGE_MONGOLIAN
+LANGUAGE_NAURU = _gdi_.LANGUAGE_NAURU
+LANGUAGE_NEPALI = _gdi_.LANGUAGE_NEPALI
+LANGUAGE_NEPALI_INDIA = _gdi_.LANGUAGE_NEPALI_INDIA
+LANGUAGE_NORWEGIAN_BOKMAL = _gdi_.LANGUAGE_NORWEGIAN_BOKMAL
+LANGUAGE_NORWEGIAN_NYNORSK = _gdi_.LANGUAGE_NORWEGIAN_NYNORSK
+LANGUAGE_OCCITAN = _gdi_.LANGUAGE_OCCITAN
+LANGUAGE_ORIYA = _gdi_.LANGUAGE_ORIYA
+LANGUAGE_OROMO = _gdi_.LANGUAGE_OROMO
+LANGUAGE_PASHTO = _gdi_.LANGUAGE_PASHTO
+LANGUAGE_POLISH = _gdi_.LANGUAGE_POLISH
+LANGUAGE_PORTUGUESE = _gdi_.LANGUAGE_PORTUGUESE
+LANGUAGE_PORTUGUESE_BRAZILIAN = _gdi_.LANGUAGE_PORTUGUESE_BRAZILIAN
+LANGUAGE_PUNJABI = _gdi_.LANGUAGE_PUNJABI
+LANGUAGE_QUECHUA = _gdi_.LANGUAGE_QUECHUA
+LANGUAGE_RHAETO_ROMANCE = _gdi_.LANGUAGE_RHAETO_ROMANCE
+LANGUAGE_ROMANIAN = _gdi_.LANGUAGE_ROMANIAN
+LANGUAGE_RUSSIAN = _gdi_.LANGUAGE_RUSSIAN
+LANGUAGE_RUSSIAN_UKRAINE = _gdi_.LANGUAGE_RUSSIAN_UKRAINE
+LANGUAGE_SAMI = _gdi_.LANGUAGE_SAMI
+LANGUAGE_SAMOAN = _gdi_.LANGUAGE_SAMOAN
+LANGUAGE_SANGHO = _gdi_.LANGUAGE_SANGHO
+LANGUAGE_SANSKRIT = _gdi_.LANGUAGE_SANSKRIT
+LANGUAGE_SCOTS_GAELIC = _gdi_.LANGUAGE_SCOTS_GAELIC
+LANGUAGE_SERBIAN = _gdi_.LANGUAGE_SERBIAN
+LANGUAGE_SERBIAN_CYRILLIC = _gdi_.LANGUAGE_SERBIAN_CYRILLIC
+LANGUAGE_SERBIAN_LATIN = _gdi_.LANGUAGE_SERBIAN_LATIN
+LANGUAGE_SERBO_CROATIAN = _gdi_.LANGUAGE_SERBO_CROATIAN
+LANGUAGE_SESOTHO = _gdi_.LANGUAGE_SESOTHO
+LANGUAGE_SETSWANA = _gdi_.LANGUAGE_SETSWANA
+LANGUAGE_SHONA = _gdi_.LANGUAGE_SHONA
+LANGUAGE_SINDHI = _gdi_.LANGUAGE_SINDHI
+LANGUAGE_SINHALESE = _gdi_.LANGUAGE_SINHALESE
+LANGUAGE_SISWATI = _gdi_.LANGUAGE_SISWATI
+LANGUAGE_SLOVAK = _gdi_.LANGUAGE_SLOVAK
+LANGUAGE_SLOVENIAN = _gdi_.LANGUAGE_SLOVENIAN
+LANGUAGE_SOMALI = _gdi_.LANGUAGE_SOMALI
+LANGUAGE_SPANISH = _gdi_.LANGUAGE_SPANISH
+LANGUAGE_SPANISH_ARGENTINA = _gdi_.LANGUAGE_SPANISH_ARGENTINA
+LANGUAGE_SPANISH_BOLIVIA = _gdi_.LANGUAGE_SPANISH_BOLIVIA
+LANGUAGE_SPANISH_CHILE = _gdi_.LANGUAGE_SPANISH_CHILE
+LANGUAGE_SPANISH_COLOMBIA = _gdi_.LANGUAGE_SPANISH_COLOMBIA
+LANGUAGE_SPANISH_COSTA_RICA = _gdi_.LANGUAGE_SPANISH_COSTA_RICA
+LANGUAGE_SPANISH_DOMINICAN_REPUBLIC = _gdi_.LANGUAGE_SPANISH_DOMINICAN_REPUBLIC
+LANGUAGE_SPANISH_ECUADOR = _gdi_.LANGUAGE_SPANISH_ECUADOR
+LANGUAGE_SPANISH_EL_SALVADOR = _gdi_.LANGUAGE_SPANISH_EL_SALVADOR
+LANGUAGE_SPANISH_GUATEMALA = _gdi_.LANGUAGE_SPANISH_GUATEMALA
+LANGUAGE_SPANISH_HONDURAS = _gdi_.LANGUAGE_SPANISH_HONDURAS
+LANGUAGE_SPANISH_MEXICAN = _gdi_.LANGUAGE_SPANISH_MEXICAN
+LANGUAGE_SPANISH_MODERN = _gdi_.LANGUAGE_SPANISH_MODERN
+LANGUAGE_SPANISH_NICARAGUA = _gdi_.LANGUAGE_SPANISH_NICARAGUA
+LANGUAGE_SPANISH_PANAMA = _gdi_.LANGUAGE_SPANISH_PANAMA
+LANGUAGE_SPANISH_PARAGUAY = _gdi_.LANGUAGE_SPANISH_PARAGUAY
+LANGUAGE_SPANISH_PERU = _gdi_.LANGUAGE_SPANISH_PERU
+LANGUAGE_SPANISH_PUERTO_RICO = _gdi_.LANGUAGE_SPANISH_PUERTO_RICO
+LANGUAGE_SPANISH_URUGUAY = _gdi_.LANGUAGE_SPANISH_URUGUAY
+LANGUAGE_SPANISH_US = _gdi_.LANGUAGE_SPANISH_US
+LANGUAGE_SPANISH_VENEZUELA = _gdi_.LANGUAGE_SPANISH_VENEZUELA
+LANGUAGE_SUNDANESE = _gdi_.LANGUAGE_SUNDANESE
+LANGUAGE_SWAHILI = _gdi_.LANGUAGE_SWAHILI
+LANGUAGE_SWEDISH = _gdi_.LANGUAGE_SWEDISH
+LANGUAGE_SWEDISH_FINLAND = _gdi_.LANGUAGE_SWEDISH_FINLAND
+LANGUAGE_TAGALOG = _gdi_.LANGUAGE_TAGALOG
+LANGUAGE_TAJIK = _gdi_.LANGUAGE_TAJIK
+LANGUAGE_TAMIL = _gdi_.LANGUAGE_TAMIL
+LANGUAGE_TATAR = _gdi_.LANGUAGE_TATAR
+LANGUAGE_TELUGU = _gdi_.LANGUAGE_TELUGU
+LANGUAGE_THAI = _gdi_.LANGUAGE_THAI
+LANGUAGE_TIBETAN = _gdi_.LANGUAGE_TIBETAN
+LANGUAGE_TIGRINYA = _gdi_.LANGUAGE_TIGRINYA
+LANGUAGE_TONGA = _gdi_.LANGUAGE_TONGA
+LANGUAGE_TSONGA = _gdi_.LANGUAGE_TSONGA
+LANGUAGE_TURKISH = _gdi_.LANGUAGE_TURKISH
+LANGUAGE_TURKMEN = _gdi_.LANGUAGE_TURKMEN
+LANGUAGE_TWI = _gdi_.LANGUAGE_TWI
+LANGUAGE_UIGHUR = _gdi_.LANGUAGE_UIGHUR
+LANGUAGE_UKRAINIAN = _gdi_.LANGUAGE_UKRAINIAN
+LANGUAGE_URDU = _gdi_.LANGUAGE_URDU
+LANGUAGE_URDU_INDIA = _gdi_.LANGUAGE_URDU_INDIA
+LANGUAGE_URDU_PAKISTAN = _gdi_.LANGUAGE_URDU_PAKISTAN
+LANGUAGE_UZBEK = _gdi_.LANGUAGE_UZBEK
+LANGUAGE_UZBEK_CYRILLIC = _gdi_.LANGUAGE_UZBEK_CYRILLIC
+LANGUAGE_UZBEK_LATIN = _gdi_.LANGUAGE_UZBEK_LATIN
+LANGUAGE_VALENCIAN = _gdi_.LANGUAGE_VALENCIAN
+LANGUAGE_VIETNAMESE = _gdi_.LANGUAGE_VIETNAMESE
+LANGUAGE_VOLAPUK = _gdi_.LANGUAGE_VOLAPUK
+LANGUAGE_WELSH = _gdi_.LANGUAGE_WELSH
+LANGUAGE_WOLOF = _gdi_.LANGUAGE_WOLOF
+LANGUAGE_XHOSA = _gdi_.LANGUAGE_XHOSA
+LANGUAGE_YIDDISH = _gdi_.LANGUAGE_YIDDISH
+LANGUAGE_YORUBA = _gdi_.LANGUAGE_YORUBA
+LANGUAGE_ZHUANG = _gdi_.LANGUAGE_ZHUANG
+LANGUAGE_ZULU = _gdi_.LANGUAGE_ZULU
+LANGUAGE_USER_DEFINED = _gdi_.LANGUAGE_USER_DEFINED
+class LanguageInfo(object):
+ """Proxy of C++ LanguageInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ Language = property(_gdi_.LanguageInfo_Language_get, _gdi_.LanguageInfo_Language_set)
+ CanonicalName = property(_gdi_.LanguageInfo_CanonicalName_get, _gdi_.LanguageInfo_CanonicalName_set)
+ Description = property(_gdi_.LanguageInfo_Description_get, _gdi_.LanguageInfo_Description_set)
+ LayoutDirection = property(_gdi_.LanguageInfo_LayoutDirection_get, _gdi_.LanguageInfo_LayoutDirection_set)
+ def GetLocaleName(*args, **kwargs):
+ """GetLocaleName(self) -> String"""
+ return _gdi_.LanguageInfo_GetLocaleName(*args, **kwargs)
+
+_gdi_.LanguageInfo_swigregister(LanguageInfo)
+
+LOCALE_CAT_NUMBER = _gdi_.LOCALE_CAT_NUMBER
+LOCALE_CAT_DATE = _gdi_.LOCALE_CAT_DATE
+LOCALE_CAT_MONEY = _gdi_.LOCALE_CAT_MONEY
+LOCALE_CAT_DEFAULT = _gdi_.LOCALE_CAT_DEFAULT
+LOCALE_CAT_MAX = _gdi_.LOCALE_CAT_MAX
+LOCALE_THOUSANDS_SEP = _gdi_.LOCALE_THOUSANDS_SEP
+LOCALE_DECIMAL_POINT = _gdi_.LOCALE_DECIMAL_POINT
+LOCALE_SHORT_DATE_FMT = _gdi_.LOCALE_SHORT_DATE_FMT
+LOCALE_LONG_DATE_FMT = _gdi_.LOCALE_LONG_DATE_FMT
+LOCALE_DATE_TIME_FMT = _gdi_.LOCALE_DATE_TIME_FMT
+LOCALE_TIME_FMT = _gdi_.LOCALE_TIME_FMT
+LOCALE_DONT_LOAD_DEFAULT = _gdi_.LOCALE_DONT_LOAD_DEFAULT
+LOCALE_LOAD_DEFAULT = _gdi_.LOCALE_LOAD_DEFAULT
+LOCALE_CONV_ENCODING = _gdi_.LOCALE_CONV_ENCODING
+class Locale(object):
+ """Proxy of C++ Locale class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int language=-1, int flags=LOCALE_LOAD_DEFAULT) -> Locale"""
+ _gdi_.Locale_swiginit(self,_gdi_.new_Locale(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Locale
+ __del__ = lambda self : None;
+ def Init1(*args, **kwargs):
+ """
+ Init1(self, String name, String shortName=EmptyString, String locale=EmptyString,
+ bool bLoadDefault=True) -> bool
+ """
+ return _gdi_.Locale_Init1(*args, **kwargs)
+
+ def Init2(*args, **kwargs):
+ """Init2(self, int language=LANGUAGE_DEFAULT, int flags=LOCALE_LOAD_DEFAULT) -> bool"""
+ return _gdi_.Locale_Init2(*args, **kwargs)
+
+ def Init(self, *_args, **_kwargs):
+ if type(_args[0]) in [type(''), type(u'')]:
+ val = self.Init1(*_args, **_kwargs)
+ else:
+ val = self.Init2(*_args, **_kwargs)
+ return val
+
+ def GetSystemLanguage(*args, **kwargs):
+ """GetSystemLanguage() -> int"""
+ return _gdi_.Locale_GetSystemLanguage(*args, **kwargs)
+
+ GetSystemLanguage = staticmethod(GetSystemLanguage)
+ def GetSystemEncoding(*args, **kwargs):
+ """GetSystemEncoding() -> int"""
+ return _gdi_.Locale_GetSystemEncoding(*args, **kwargs)
+
+ GetSystemEncoding = staticmethod(GetSystemEncoding)
+ def GetSystemEncodingName(*args, **kwargs):
+ """GetSystemEncodingName() -> String"""
+ return _gdi_.Locale_GetSystemEncodingName(*args, **kwargs)
+
+ GetSystemEncodingName = staticmethod(GetSystemEncodingName)
+ def GetInfo(*args, **kwargs):
+ """GetInfo(int index, int cat=LOCALE_CAT_DEFAULT) -> String"""
+ return _gdi_.Locale_GetInfo(*args, **kwargs)
+
+ GetInfo = staticmethod(GetInfo)
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.Locale_IsOk(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def GetLocale(*args, **kwargs):
+ """GetLocale(self) -> String"""
+ return _gdi_.Locale_GetLocale(*args, **kwargs)
+
+ def GetLanguage(*args, **kwargs):
+ """GetLanguage(self) -> int"""
+ return _gdi_.Locale_GetLanguage(*args, **kwargs)
+
+ def GetSysName(*args, **kwargs):
+ """GetSysName(self) -> String"""
+ return _gdi_.Locale_GetSysName(*args, **kwargs)
+
+ def GetCanonicalName(*args, **kwargs):
+ """GetCanonicalName(self) -> String"""
+ return _gdi_.Locale_GetCanonicalName(*args, **kwargs)
+
+ def AddCatalogLookupPathPrefix(*args, **kwargs):
+ """AddCatalogLookupPathPrefix(String prefix)"""
+ return _gdi_.Locale_AddCatalogLookupPathPrefix(*args, **kwargs)
+
+ AddCatalogLookupPathPrefix = staticmethod(AddCatalogLookupPathPrefix)
+ def AddCatalog(*args):
+ """
+ AddCatalog(self, String domain) -> bool
+ AddCatalog(self, String domain, int msgIdLanguage) -> bool
+ AddCatalog(self, String domain, int msgIdLanguage, String msgIdCharset) -> bool
+ """
+ return _gdi_.Locale_AddCatalog(*args)
+
+ def IsAvailable(*args, **kwargs):
+ """IsAvailable(int lang) -> bool"""
+ return _gdi_.Locale_IsAvailable(*args, **kwargs)
+
+ IsAvailable = staticmethod(IsAvailable)
+ def IsLoaded(*args, **kwargs):
+ """IsLoaded(self, String domain) -> bool"""
+ return _gdi_.Locale_IsLoaded(*args, **kwargs)
+
+ def GetLanguageInfo(*args, **kwargs):
+ """GetLanguageInfo(int lang) -> LanguageInfo"""
+ return _gdi_.Locale_GetLanguageInfo(*args, **kwargs)
+
+ GetLanguageInfo = staticmethod(GetLanguageInfo)
+ def GetLanguageName(*args, **kwargs):
+ """GetLanguageName(int lang) -> String"""
+ return _gdi_.Locale_GetLanguageName(*args, **kwargs)
+
+ GetLanguageName = staticmethod(GetLanguageName)
+ def GetLanguageCanonicalName(*args, **kwargs):
+ """GetLanguageCanonicalName(int lang) -> String"""
+ return _gdi_.Locale_GetLanguageCanonicalName(*args, **kwargs)
+
+ GetLanguageCanonicalName = staticmethod(GetLanguageCanonicalName)
+ def FindLanguageInfo(*args, **kwargs):
+ """FindLanguageInfo(String locale) -> LanguageInfo"""
+ return _gdi_.Locale_FindLanguageInfo(*args, **kwargs)
+
+ FindLanguageInfo = staticmethod(FindLanguageInfo)
+ def AddLanguage(*args, **kwargs):
+ """AddLanguage(LanguageInfo info)"""
+ return _gdi_.Locale_AddLanguage(*args, **kwargs)
+
+ AddLanguage = staticmethod(AddLanguage)
+ def GetString(*args, **kwargs):
+ """GetString(self, String origString, String domain=EmptyString) -> String"""
+ return _gdi_.Locale_GetString(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _gdi_.Locale_GetName(*args, **kwargs)
+
+ CanonicalName = property(GetCanonicalName,doc="See `GetCanonicalName`")
+ Language = property(GetLanguage,doc="See `GetLanguage`")
+ Locale = property(GetLocale,doc="See `GetLocale`")
+ Name = property(GetName,doc="See `GetName`")
+ String = property(GetString,doc="See `GetString`")
+ SysName = property(GetSysName,doc="See `GetSysName`")
+_gdi_.Locale_swigregister(Locale)
+
+def Locale_GetSystemLanguage(*args):
+ """Locale_GetSystemLanguage() -> int"""
+ return _gdi_.Locale_GetSystemLanguage(*args)
+
+def Locale_GetSystemEncoding(*args):
+ """Locale_GetSystemEncoding() -> int"""
+ return _gdi_.Locale_GetSystemEncoding(*args)
+
+def Locale_GetSystemEncodingName(*args):
+ """Locale_GetSystemEncodingName() -> String"""
+ return _gdi_.Locale_GetSystemEncodingName(*args)
+
+def Locale_GetInfo(*args, **kwargs):
+ """Locale_GetInfo(int index, int cat=LOCALE_CAT_DEFAULT) -> String"""
+ return _gdi_.Locale_GetInfo(*args, **kwargs)
+
+def Locale_AddCatalogLookupPathPrefix(*args, **kwargs):
+ """Locale_AddCatalogLookupPathPrefix(String prefix)"""
+ return _gdi_.Locale_AddCatalogLookupPathPrefix(*args, **kwargs)
+
+def Locale_IsAvailable(*args, **kwargs):
+ """Locale_IsAvailable(int lang) -> bool"""
+ return _gdi_.Locale_IsAvailable(*args, **kwargs)
+
+def Locale_GetLanguageInfo(*args, **kwargs):
+ """Locale_GetLanguageInfo(int lang) -> LanguageInfo"""
+ return _gdi_.Locale_GetLanguageInfo(*args, **kwargs)
+
+def Locale_GetLanguageName(*args, **kwargs):
+ """Locale_GetLanguageName(int lang) -> String"""
+ return _gdi_.Locale_GetLanguageName(*args, **kwargs)
+
+def Locale_GetLanguageCanonicalName(*args, **kwargs):
+ """Locale_GetLanguageCanonicalName(int lang) -> String"""
+ return _gdi_.Locale_GetLanguageCanonicalName(*args, **kwargs)
+
+def Locale_FindLanguageInfo(*args, **kwargs):
+ """Locale_FindLanguageInfo(String locale) -> LanguageInfo"""
+ return _gdi_.Locale_FindLanguageInfo(*args, **kwargs)
+
+def Locale_AddLanguage(*args, **kwargs):
+ """Locale_AddLanguage(LanguageInfo info)"""
+ return _gdi_.Locale_AddLanguage(*args, **kwargs)
+
+class PyLocale(Locale):
+ """Proxy of C++ PyLocale class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int language=-1, int flags=LOCALE_LOAD_DEFAULT) -> PyLocale"""
+ _gdi_.PyLocale_swiginit(self,_gdi_.new_PyLocale(*args, **kwargs))
+ PyLocale._setCallbackInfo(self, self, PyLocale)
+
+ __swig_destroy__ = _gdi_.delete_PyLocale
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _gdi_.PyLocale__setCallbackInfo(*args, **kwargs)
+
+ def GetSingularString(*args, **kwargs):
+ """GetSingularString(self, String origString, String domain=EmptyString) -> String"""
+ return _gdi_.PyLocale_GetSingularString(*args, **kwargs)
+
+ def GetPluralString(*args, **kwargs):
+ """GetPluralString(self, String origString, String origString2, size_t n, String domain=EmptyString) -> String"""
+ return _gdi_.PyLocale_GetPluralString(*args, **kwargs)
+
+_gdi_.PyLocale_swigregister(PyLocale)
+
+
+def GetLocale(*args):
+ """GetLocale() -> Locale"""
+ return _gdi_.GetLocale(*args)
+#---------------------------------------------------------------------------
+
+CONVERT_STRICT = _gdi_.CONVERT_STRICT
+CONVERT_SUBSTITUTE = _gdi_.CONVERT_SUBSTITUTE
+PLATFORM_CURRENT = _gdi_.PLATFORM_CURRENT
+PLATFORM_UNIX = _gdi_.PLATFORM_UNIX
+PLATFORM_WINDOWS = _gdi_.PLATFORM_WINDOWS
+PLATFORM_OS2 = _gdi_.PLATFORM_OS2
+PLATFORM_MAC = _gdi_.PLATFORM_MAC
+class EncodingConverter(_core.Object):
+ """Proxy of C++ EncodingConverter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> EncodingConverter"""
+ _gdi_.EncodingConverter_swiginit(self,_gdi_.new_EncodingConverter(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_EncodingConverter
+ __del__ = lambda self : None;
+ def Init(*args, **kwargs):
+ """Init(self, int input_enc, int output_enc, int method=CONVERT_STRICT) -> bool"""
+ return _gdi_.EncodingConverter_Init(*args, **kwargs)
+
+ def Convert(*args, **kwargs):
+ """Convert(self, String input) -> String"""
+ return _gdi_.EncodingConverter_Convert(*args, **kwargs)
+
+ def GetPlatformEquivalents(*args, **kwargs):
+ """GetPlatformEquivalents(int enc, int platform=PLATFORM_CURRENT) -> wxFontEncodingArray"""
+ return _gdi_.EncodingConverter_GetPlatformEquivalents(*args, **kwargs)
+
+ GetPlatformEquivalents = staticmethod(GetPlatformEquivalents)
+ def GetAllEquivalents(*args, **kwargs):
+ """GetAllEquivalents(int enc) -> wxFontEncodingArray"""
+ return _gdi_.EncodingConverter_GetAllEquivalents(*args, **kwargs)
+
+ GetAllEquivalents = staticmethod(GetAllEquivalents)
+ def CanConvert(*args, **kwargs):
+ """CanConvert(int encIn, int encOut) -> bool"""
+ return _gdi_.EncodingConverter_CanConvert(*args, **kwargs)
+
+ CanConvert = staticmethod(CanConvert)
+ def __nonzero__(self): return self.IsOk()
+_gdi_.EncodingConverter_swigregister(EncodingConverter)
+
+def GetTranslation(*args):
+ """
+ GetTranslation(String str) -> String
+ GetTranslation(String str, String domain) -> String
+ GetTranslation(String str, String strPlural, size_t n) -> String
+ GetTranslation(String str, String strPlural, size_t n, String domain) -> String
+ """
+ return _gdi_.GetTranslation(*args)
+
+def EncodingConverter_GetPlatformEquivalents(*args, **kwargs):
+ """EncodingConverter_GetPlatformEquivalents(int enc, int platform=PLATFORM_CURRENT) -> wxFontEncodingArray"""
+ return _gdi_.EncodingConverter_GetPlatformEquivalents(*args, **kwargs)
+
+def EncodingConverter_GetAllEquivalents(*args, **kwargs):
+ """EncodingConverter_GetAllEquivalents(int enc) -> wxFontEncodingArray"""
+ return _gdi_.EncodingConverter_GetAllEquivalents(*args, **kwargs)
+
+def EncodingConverter_CanConvert(*args, **kwargs):
+ """EncodingConverter_CanConvert(int encIn, int encOut) -> bool"""
+ return _gdi_.EncodingConverter_CanConvert(*args, **kwargs)
+
+#----------------------------------------------------------------------------
+# Add the directory where the wxWidgets catalogs were installed
+# to the default catalog path, if they were put in the pacakge dir.
+import os
+_localedir = os.path.join(os.path.dirname(__file__), "locale")
+if os.path.exists(_localedir):
+ Locale.AddCatalogLookupPathPrefix(_localedir)
+del os
+
+#----------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+
+CLEAR = _gdi_.CLEAR
+XOR = _gdi_.XOR
+INVERT = _gdi_.INVERT
+OR_REVERSE = _gdi_.OR_REVERSE
+AND_REVERSE = _gdi_.AND_REVERSE
+COPY = _gdi_.COPY
+AND = _gdi_.AND
+AND_INVERT = _gdi_.AND_INVERT
+NO_OP = _gdi_.NO_OP
+NOR = _gdi_.NOR
+EQUIV = _gdi_.EQUIV
+SRC_INVERT = _gdi_.SRC_INVERT
+OR_INVERT = _gdi_.OR_INVERT
+NAND = _gdi_.NAND
+OR = _gdi_.OR
+SET = _gdi_.SET
+FLOOD_SURFACE = _gdi_.FLOOD_SURFACE
+FLOOD_BORDER = _gdi_.FLOOD_BORDER
+MM_TEXT = _gdi_.MM_TEXT
+MM_TWIPS = _gdi_.MM_TWIPS
+MM_POINTS = _gdi_.MM_POINTS
+MM_METRIC = _gdi_.MM_METRIC
+class FontMetrics(object):
+ """Proxy of C++ FontMetrics class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> FontMetrics"""
+ _gdi_.FontMetrics_swiginit(self,_gdi_.new_FontMetrics(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_FontMetrics
+ __del__ = lambda self : None;
+ height = property(_gdi_.FontMetrics_height_get, _gdi_.FontMetrics_height_set)
+ ascent = property(_gdi_.FontMetrics_ascent_get, _gdi_.FontMetrics_ascent_set)
+ descent = property(_gdi_.FontMetrics_descent_get, _gdi_.FontMetrics_descent_set)
+ internalLeading = property(_gdi_.FontMetrics_internalLeading_get, _gdi_.FontMetrics_internalLeading_set)
+ externalLeading = property(_gdi_.FontMetrics_externalLeading_get, _gdi_.FontMetrics_externalLeading_set)
+ averageWidth = property(_gdi_.FontMetrics_averageWidth_get, _gdi_.FontMetrics_averageWidth_set)
+_gdi_.FontMetrics_swigregister(FontMetrics)
+
+class DC(_core.Object):
+ """
+ A wx.DC is a device context onto which graphics and text can be
+ drawn. It is intended to represent a number of output devices in a
+ generic way, so a window can have a device context associated with it,
+ and a printer also has a device context. In this way, the same piece
+ of code may write to a number of different devices, if the device
+ context is used as a parameter.
+
+ Derived types of wxDC have documentation for specific features only,
+ so refer to this section for most device context information.
+
+ The wx.DC class is abstract and can not be instantiated, you must use
+ one of the derived classes instead. Which one will depend on the
+ situation in which it is used.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _gdi_.delete_DC
+ __del__ = lambda self : None;
+ # These have been deprecated in wxWidgets. Since they never
+ # really did anything to begin with, just make them be NOPs.
+ def BeginDrawing(self): pass
+ def EndDrawing(self): pass
+
+ def GetImpl(*args, **kwargs):
+ """GetImpl(self) -> DCImpl"""
+ return _gdi_.DC_GetImpl(*args, **kwargs)
+
+ def GetWindow(*args, **kwargs):
+ """GetWindow(self) -> Window"""
+ return _gdi_.DC_GetWindow(*args, **kwargs)
+
+ def CopyAttributes(*args, **kwargs):
+ """CopyAttributes(self, DC dc)"""
+ return _gdi_.DC_CopyAttributes(*args, **kwargs)
+
+ def FloodFill(*args, **kwargs):
+ """
+ FloodFill(self, int x, int y, Colour col, int style=FLOOD_SURFACE) -> bool
+
+ Flood fills the device context starting from the given point, using
+ the current brush colour, and using a style:
+
+ - **wxFLOOD_SURFACE**: the flooding occurs until a colour other than
+ the given colour is encountered.
+
+ - **wxFLOOD_BORDER**: the area to be flooded is bounded by the given
+ colour.
+
+ Returns False if the operation failed.
+
+ Note: The present implementation for non-Windows platforms may fail to
+ find colour borders if the pixels do not match the colour
+ exactly. However the function will still return true.
+ """
+ return _gdi_.DC_FloodFill(*args, **kwargs)
+
+ def FloodFillPoint(*args, **kwargs):
+ """
+ FloodFillPoint(self, Point pt, Colour col, int style=FLOOD_SURFACE) -> bool
+
+ Flood fills the device context starting from the given point, using
+ the current brush colour, and using a style:
+
+ - **wxFLOOD_SURFACE**: the flooding occurs until a colour other than
+ the given colour is encountered.
+
+ - **wxFLOOD_BORDER**: the area to be flooded is bounded by the given
+ colour.
+
+ Returns False if the operation failed.
+
+ Note: The present implementation for non-Windows platforms may fail to
+ find colour borders if the pixels do not match the colour
+ exactly. However the function will still return true.
+ """
+ return _gdi_.DC_FloodFillPoint(*args, **kwargs)
+
+ def GradientFillConcentric(*args, **kwargs):
+ """
+ GradientFillConcentric(self, Rect rect, Colour initialColour, Colour destColour,
+ Point circleCenter)
+
+ Fill the area specified by rect with a radial gradient, starting from
+ initialColour in the center of the circle and fading to destColour on
+ the outside of the circle. The circleCenter argument is the relative
+ coordinants of the center of the circle in the specified rect.
+
+ Note: Currently this function is very slow, don't use it for real-time
+ drawing.
+ """
+ return _gdi_.DC_GradientFillConcentric(*args, **kwargs)
+
+ def GradientFillLinear(*args, **kwargs):
+ """
+ GradientFillLinear(self, Rect rect, Colour initialColour, Colour destColour,
+ int nDirection=EAST)
+
+ Fill the area specified by rect with a linear gradient, starting from
+ initialColour and eventually fading to destColour. The nDirection
+ parameter specifies the direction of the colour change, default is to
+ use initialColour on the left part of the rectangle and destColour on
+ the right side.
+ """
+ return _gdi_.DC_GradientFillLinear(*args, **kwargs)
+
+ def GetPixel(*args, **kwargs):
+ """
+ GetPixel(self, int x, int y) -> Colour
+
+ Gets the colour at the specified location on the DC.
+ """
+ return _gdi_.DC_GetPixel(*args, **kwargs)
+
+ def GetPixelPoint(*args, **kwargs):
+ """GetPixelPoint(self, Point pt) -> Colour"""
+ return _gdi_.DC_GetPixelPoint(*args, **kwargs)
+
+ def DrawLine(*args, **kwargs):
+ """
+ DrawLine(self, int x1, int y1, int x2, int y2)
+
+ Draws a line from the first point to the second. The current pen is
+ used for drawing the line. Note that the second point is *not* part of
+ the line and is not drawn by this function (this is consistent with
+ the behaviour of many other toolkits).
+ """
+ return _gdi_.DC_DrawLine(*args, **kwargs)
+
+ def DrawLinePoint(*args, **kwargs):
+ """
+ DrawLinePoint(self, Point pt1, Point pt2)
+
+ Draws a line from the first point to the second. The current pen is
+ used for drawing the line. Note that the second point is *not* part of
+ the line and is not drawn by this function (this is consistent with
+ the behaviour of many other toolkits).
+ """
+ return _gdi_.DC_DrawLinePoint(*args, **kwargs)
+
+ def CrossHair(*args, **kwargs):
+ """
+ CrossHair(self, int x, int y)
+
+ Displays a cross hair using the current pen. This is a vertical and
+ horizontal line the height and width of the window, centred on the
+ given point.
+ """
+ return _gdi_.DC_CrossHair(*args, **kwargs)
+
+ def CrossHairPoint(*args, **kwargs):
+ """
+ CrossHairPoint(self, Point pt)
+
+ Displays a cross hair using the current pen. This is a vertical and
+ horizontal line the height and width of the window, centred on the
+ given point.
+ """
+ return _gdi_.DC_CrossHairPoint(*args, **kwargs)
+
+ def DrawArc(*args, **kwargs):
+ """
+ DrawArc(self, int x1, int y1, int x2, int y2, int xc, int yc)
+
+ Draws an arc of a circle, centred on the *center* point (xc, yc), from
+ the first point to the second. The current pen is used for the outline
+ and the current brush for filling the shape.
+
+ The arc is drawn in an anticlockwise direction from the start point to
+ the end point.
+ """
+ return _gdi_.DC_DrawArc(*args, **kwargs)
+
+ def DrawArcPoint(*args, **kwargs):
+ """
+ DrawArcPoint(self, Point pt1, Point pt2, Point center)
+
+ Draws an arc of a circle, centred on the *center* point (xc, yc), from
+ the first point to the second. The current pen is used for the outline
+ and the current brush for filling the shape.
+
+ The arc is drawn in an anticlockwise direction from the start point to
+ the end point.
+ """
+ return _gdi_.DC_DrawArcPoint(*args, **kwargs)
+
+ def DrawCheckMark(*args, **kwargs):
+ """
+ DrawCheckMark(self, int x, int y, int width, int height)
+
+ Draws a check mark inside the given rectangle.
+ """
+ return _gdi_.DC_DrawCheckMark(*args, **kwargs)
+
+ def DrawCheckMarkRect(*args, **kwargs):
+ """
+ DrawCheckMarkRect(self, Rect rect)
+
+ Draws a check mark inside the given rectangle.
+ """
+ return _gdi_.DC_DrawCheckMarkRect(*args, **kwargs)
+
+ def DrawEllipticArc(*args, **kwargs):
+ """
+ DrawEllipticArc(self, int x, int y, int w, int h, double start, double end)
+
+ Draws an arc of an ellipse, with the given rectangle defining the
+ bounds of the ellipse. The current pen is used for drawing the arc and
+ the current brush is used for drawing the pie.
+
+ The *start* and *end* parameters specify the start and end of the arc
+ relative to the three-o'clock position from the center of the
+ rectangle. Angles are specified in degrees (360 is a complete
+ circle). Positive values mean counter-clockwise motion. If start is
+ equal to end, a complete ellipse will be drawn.
+ """
+ return _gdi_.DC_DrawEllipticArc(*args, **kwargs)
+
+ def DrawEllipticArcPointSize(*args, **kwargs):
+ """
+ DrawEllipticArcPointSize(self, Point pt, Size sz, double start, double end)
+
+ Draws an arc of an ellipse, with the given rectangle defining the
+ bounds of the ellipse. The current pen is used for drawing the arc and
+ the current brush is used for drawing the pie.
+
+ The *start* and *end* parameters specify the start and end of the arc
+ relative to the three-o'clock position from the center of the
+ rectangle. Angles are specified in degrees (360 is a complete
+ circle). Positive values mean counter-clockwise motion. If start is
+ equal to end, a complete ellipse will be drawn.
+ """
+ return _gdi_.DC_DrawEllipticArcPointSize(*args, **kwargs)
+
+ def DrawPoint(*args, **kwargs):
+ """
+ DrawPoint(self, int x, int y)
+
+ Draws a point using the current pen.
+ """
+ return _gdi_.DC_DrawPoint(*args, **kwargs)
+
+ def DrawPointPoint(*args, **kwargs):
+ """
+ DrawPointPoint(self, Point pt)
+
+ Draws a point using the current pen.
+ """
+ return _gdi_.DC_DrawPointPoint(*args, **kwargs)
+
+ def DrawRectangle(*args, **kwargs):
+ """
+ DrawRectangle(self, int x, int y, int width, int height)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The current pen is used for the outline and the current brush
+ for filling the shape.
+ """
+ return _gdi_.DC_DrawRectangle(*args, **kwargs)
+
+ def DrawRectangleRect(*args, **kwargs):
+ """
+ DrawRectangleRect(self, Rect rect)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The current pen is used for the outline and the current brush
+ for filling the shape.
+ """
+ return _gdi_.DC_DrawRectangleRect(*args, **kwargs)
+
+ def DrawRectanglePointSize(*args, **kwargs):
+ """
+ DrawRectanglePointSize(self, Point pt, Size sz)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The current pen is used for the outline and the current brush
+ for filling the shape.
+ """
+ return _gdi_.DC_DrawRectanglePointSize(*args, **kwargs)
+
+ def DrawRoundedRectangle(*args, **kwargs):
+ """
+ DrawRoundedRectangle(self, int x, int y, int width, int height, double radius)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The corners are quarter-circles using the given radius. The
+ current pen is used for the outline and the current brush for filling
+ the shape.
+
+ If radius is positive, the value is assumed to be the radius of the
+ rounded corner. If radius is negative, the absolute value is assumed
+ to be the proportion of the smallest dimension of the rectangle. This
+ means that the corner can be a sensible size relative to the size of
+ the rectangle, and also avoids the strange effects X produces when the
+ corners are too big for the rectangle.
+ """
+ return _gdi_.DC_DrawRoundedRectangle(*args, **kwargs)
+
+ def DrawRoundedRectangleRect(*args, **kwargs):
+ """
+ DrawRoundedRectangleRect(self, Rect r, double radius)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The corners are quarter-circles using the given radius. The
+ current pen is used for the outline and the current brush for filling
+ the shape.
+
+ If radius is positive, the value is assumed to be the radius of the
+ rounded corner. If radius is negative, the absolute value is assumed
+ to be the proportion of the smallest dimension of the rectangle. This
+ means that the corner can be a sensible size relative to the size of
+ the rectangle, and also avoids the strange effects X produces when the
+ corners are too big for the rectangle.
+ """
+ return _gdi_.DC_DrawRoundedRectangleRect(*args, **kwargs)
+
+ def DrawRoundedRectanglePointSize(*args, **kwargs):
+ """
+ DrawRoundedRectanglePointSize(self, Point pt, Size sz, double radius)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The corners are quarter-circles using the given radius. The
+ current pen is used for the outline and the current brush for filling
+ the shape.
+
+ If radius is positive, the value is assumed to be the radius of the
+ rounded corner. If radius is negative, the absolute value is assumed
+ to be the proportion of the smallest dimension of the rectangle. This
+ means that the corner can be a sensible size relative to the size of
+ the rectangle, and also avoids the strange effects X produces when the
+ corners are too big for the rectangle.
+ """
+ return _gdi_.DC_DrawRoundedRectanglePointSize(*args, **kwargs)
+
+ def DrawCircle(*args, **kwargs):
+ """
+ DrawCircle(self, int x, int y, int radius)
+
+ Draws a circle with the given center point and radius. The current
+ pen is used for the outline and the current brush for filling the
+ shape.
+ """
+ return _gdi_.DC_DrawCircle(*args, **kwargs)
+
+ def DrawCirclePoint(*args, **kwargs):
+ """
+ DrawCirclePoint(self, Point pt, int radius)
+
+ Draws a circle with the given center point and radius. The current
+ pen is used for the outline and the current brush for filling the
+ shape.
+ """
+ return _gdi_.DC_DrawCirclePoint(*args, **kwargs)
+
+ def DrawEllipse(*args, **kwargs):
+ """
+ DrawEllipse(self, int x, int y, int width, int height)
+
+ Draws an ellipse contained in the specified rectangle. The current pen
+ is used for the outline and the current brush for filling the shape.
+ """
+ return _gdi_.DC_DrawEllipse(*args, **kwargs)
+
+ def DrawEllipseRect(*args, **kwargs):
+ """
+ DrawEllipseRect(self, Rect rect)
+
+ Draws an ellipse contained in the specified rectangle. The current pen
+ is used for the outline and the current brush for filling the shape.
+ """
+ return _gdi_.DC_DrawEllipseRect(*args, **kwargs)
+
+ def DrawEllipsePointSize(*args, **kwargs):
+ """
+ DrawEllipsePointSize(self, Point pt, Size sz)
+
+ Draws an ellipse contained in the specified rectangle. The current pen
+ is used for the outline and the current brush for filling the shape.
+ """
+ return _gdi_.DC_DrawEllipsePointSize(*args, **kwargs)
+
+ def DrawIcon(*args, **kwargs):
+ """
+ DrawIcon(self, Icon icon, int x, int y)
+
+ Draw an icon on the display (does nothing if the device context is
+ PostScript). This can be the simplest way of drawing bitmaps on a
+ window.
+ """
+ return _gdi_.DC_DrawIcon(*args, **kwargs)
+
+ def DrawIconPoint(*args, **kwargs):
+ """
+ DrawIconPoint(self, Icon icon, Point pt)
+
+ Draw an icon on the display (does nothing if the device context is
+ PostScript). This can be the simplest way of drawing bitmaps on a
+ window.
+ """
+ return _gdi_.DC_DrawIconPoint(*args, **kwargs)
+
+ def DrawBitmap(*args, **kwargs):
+ """
+ DrawBitmap(self, Bitmap bmp, int x, int y, bool useMask=False)
+
+ Draw a bitmap on the device context at the specified point. If
+ *transparent* is true and the bitmap has a transparency mask, (or
+ alpha channel on the platforms that support it) then the bitmap will
+ be drawn transparently.
+ """
+ return _gdi_.DC_DrawBitmap(*args, **kwargs)
+
+ def DrawBitmapPoint(*args, **kwargs):
+ """
+ DrawBitmapPoint(self, Bitmap bmp, Point pt, bool useMask=False)
+
+ Draw a bitmap on the device context at the specified point. If
+ *transparent* is true and the bitmap has a transparency mask, (or
+ alpha channel on the platforms that support it) then the bitmap will
+ be drawn transparently.
+ """
+ return _gdi_.DC_DrawBitmapPoint(*args, **kwargs)
+
+ def DrawText(*args, **kwargs):
+ """
+ DrawText(self, String text, int x, int y)
+
+ Draws a text string at the specified point, using the current text
+ font, and the current text foreground and background colours.
+
+ The coordinates refer to the top-left corner of the rectangle bounding
+ the string. See `GetTextExtent` for how to get the dimensions of a
+ text string, which can be used to position the text more precisely.
+
+ **NOTE**: under wxGTK the current logical function is used by this
+ function but it is ignored by wxMSW. Thus, you should avoid using
+ logical functions with this function in portable programs.
+ """
+ return _gdi_.DC_DrawText(*args, **kwargs)
+
+ def DrawTextPoint(*args, **kwargs):
+ """
+ DrawTextPoint(self, String text, Point pt)
+
+ Draws a text string at the specified point, using the current text
+ font, and the current text foreground and background colours.
+
+ The coordinates refer to the top-left corner of the rectangle bounding
+ the string. See `GetTextExtent` for how to get the dimensions of a
+ text string, which can be used to position the text more precisely.
+
+ **NOTE**: under wxGTK the current logical function is used by this
+ function but it is ignored by wxMSW. Thus, you should avoid using
+ logical functions with this function in portable programs.
+ """
+ return _gdi_.DC_DrawTextPoint(*args, **kwargs)
+
+ def DrawRotatedText(*args, **kwargs):
+ """
+ DrawRotatedText(self, String text, int x, int y, double angle)
+
+ Draws the text rotated by *angle* degrees, if supported by the platform.
+
+ **NOTE**: Under Win9x only TrueType fonts can be drawn by this
+ function. In particular, a font different from ``wx.NORMAL_FONT``
+ should be used as the it is not normally a TrueType
+ font. ``wx.SWISS_FONT`` is an example of a font which is.
+ """
+ return _gdi_.DC_DrawRotatedText(*args, **kwargs)
+
+ def DrawRotatedTextPoint(*args, **kwargs):
+ """
+ DrawRotatedTextPoint(self, String text, Point pt, double angle)
+
+ Draws the text rotated by *angle* degrees, if supported by the platform.
+
+ **NOTE**: Under Win9x only TrueType fonts can be drawn by this
+ function. In particular, a font different from ``wx.NORMAL_FONT``
+ should be used as the it is not normally a TrueType
+ font. ``wx.SWISS_FONT`` is an example of a font which is.
+ """
+ return _gdi_.DC_DrawRotatedTextPoint(*args, **kwargs)
+
+ def Blit(*args, **kwargs):
+ """
+ Blit(self, int xdest, int ydest, int width, int height, DC source,
+ int xsrc, int ysrc, int rop=COPY, bool useMask=False,
+ int xsrcMask=-1, int ysrcMask=-1) -> bool
+
+ Copy from a source DC to this DC. Parameters specify the destination
+ coordinates, size of area to copy, source DC, source coordinates,
+ logical function, whether to use a bitmap mask, and mask source
+ position.
+ """
+ return _gdi_.DC_Blit(*args, **kwargs)
+
+ def BlitPointSize(*args, **kwargs):
+ """
+ BlitPointSize(self, Point destPt, Size sz, DC source, Point srcPt, int rop=COPY,
+ bool useMask=False, Point srcPtMask=DefaultPosition) -> bool
+
+ Copy from a source DC to this DC. Parameters specify the destination
+ coordinates, size of area to copy, source DC, source coordinates,
+ logical function, whether to use a bitmap mask, and mask source
+ position.
+ """
+ return _gdi_.DC_BlitPointSize(*args, **kwargs)
+
+ def StretchBlit(*args, **kwargs):
+ """
+ StretchBlit(self, int dstX, int dstY, int dstWidth, int dstHeight, DC source,
+ int srcX, int srcY, int srcWidth, int srcHeight,
+ int rop=COPY, bool useMask=False,
+ int srcMaskX=DefaultCoord, int srcMaskY=DefaultCoord) -> bool
+
+ Copy from a source DC to this DC, specifying the destination
+ coordinates, destination size, source DC, source coordinates, size of
+ source area to copy, logical function, whether to use a bitmap mask,
+ and mask source position.
+ """
+ return _gdi_.DC_StretchBlit(*args, **kwargs)
+
+ def StretchBlitPointSize(*args, **kwargs):
+ """
+ StretchBlitPointSize(self, Point dstPt, Size dstSize, DC source, Point srcPt,
+ Size srcSize, int rop=COPY, bool useMask=False,
+ Point srcMaskPt=DefaultPosition) -> bool
+
+ Copy from a source DC to this DC, specifying the destination
+ coordinates, destination size, source DC, source coordinates, size of
+ source area to copy, logical function, whether to use a bitmap mask,
+ and mask source position. This version is the same as `StretchBlit`
+ except `wx.Point` and `wx.Size` objects are used instead of individual
+ position and size components.
+ """
+ return _gdi_.DC_StretchBlitPointSize(*args, **kwargs)
+
+ def GetAsBitmap(*args, **kwargs):
+ """GetAsBitmap(self, Rect subrect=None) -> Bitmap"""
+ return _gdi_.DC_GetAsBitmap(*args, **kwargs)
+
+ def SetClippingRegion(*args, **kwargs):
+ """
+ SetClippingRegion(self, int x, int y, int width, int height)
+
+ Sets the clipping region for this device context to the intersection
+ of the given region described by the parameters of this method and the
+ previously set clipping region. You should call `DestroyClippingRegion`
+ if you want to set the clipping region exactly to the region
+ specified.
+
+ The clipping region is an area to which drawing is
+ restricted. Possible uses for the clipping region are for clipping
+ text or for speeding up window redraws when only a known area of the
+ screen is damaged.
+ """
+ return _gdi_.DC_SetClippingRegion(*args, **kwargs)
+
+ def SetClippingRegionPointSize(*args, **kwargs):
+ """
+ SetClippingRegionPointSize(self, Point pt, Size sz)
+
+ Sets the clipping region for this device context to the intersection
+ of the given region described by the parameters of this method and the
+ previously set clipping region. You should call `DestroyClippingRegion`
+ if you want to set the clipping region exactly to the region
+ specified.
+
+ The clipping region is an area to which drawing is
+ restricted. Possible uses for the clipping region are for clipping
+ text or for speeding up window redraws when only a known area of the
+ screen is damaged.
+ """
+ return _gdi_.DC_SetClippingRegionPointSize(*args, **kwargs)
+
+ def SetClippingRegionAsRegion(*args, **kwargs):
+ """
+ SetClippingRegionAsRegion(self, Region region)
+
+ Sets the clipping region for this device context to the intersection
+ of the given region described by the parameters of this method and the
+ previously set clipping region. You should call `DestroyClippingRegion`
+ if you want to set the clipping region exactly to the region
+ specified.
+
+ The clipping region is an area to which drawing is
+ restricted. Possible uses for the clipping region are for clipping
+ text or for speeding up window redraws when only a known area of the
+ screen is damaged.
+ """
+ return _gdi_.DC_SetClippingRegionAsRegion(*args, **kwargs)
+
+ def SetClippingRect(*args, **kwargs):
+ """
+ SetClippingRect(self, Rect rect)
+
+ Sets the clipping region for this device context to the intersection
+ of the given region described by the parameters of this method and the
+ previously set clipping region. You should call `DestroyClippingRegion`
+ if you want to set the clipping region exactly to the region
+ specified.
+
+ The clipping region is an area to which drawing is
+ restricted. Possible uses for the clipping region are for clipping
+ text or for speeding up window redraws when only a known area of the
+ screen is damaged.
+ """
+ return _gdi_.DC_SetClippingRect(*args, **kwargs)
+
+ def SetDeviceClippingRegion(*args, **kwargs):
+ """
+ SetDeviceClippingRegion(self, Region region)
+
+ The coordinates of the region used in this method one are in device
+ coordinates, not the logical ones
+ """
+ return _gdi_.DC_SetDeviceClippingRegion(*args, **kwargs)
+
+ def DrawLines(*args, **kwargs):
+ """
+ DrawLines(self, List points, int xoffset=0, int yoffset=0)
+
+ Draws lines using a sequence of `wx.Point` objects, adding the
+ optional offset coordinate. The current pen is used for drawing the
+ lines.
+ """
+ return _gdi_.DC_DrawLines(*args, **kwargs)
+
+ def DrawPolygon(*args, **kwargs):
+ """
+ DrawPolygon(self, List points, int xoffset=0, int yoffset=0,
+ wxPolygonFillMode fillStyle=ODDEVEN_RULE)
+
+ Draws a filled polygon using a sequence of `wx.Point` objects, adding
+ the optional offset coordinate. The last argument specifies the fill
+ rule: ``wx.ODDEVEN_RULE`` (the default) or ``wx.WINDING_RULE``.
+
+ The current pen is used for drawing the outline, and the current brush
+ for filling the shape. Using a transparent brush suppresses
+ filling. Note that wxWidgets automatically closes the first and last
+ points.
+ """
+ return _gdi_.DC_DrawPolygon(*args, **kwargs)
+
+ def DrawLabel(*args, **kwargs):
+ """
+ DrawLabel(self, String text, Rect rect, int alignment=wxALIGN_LEFT|wxALIGN_TOP,
+ int indexAccel=-1)
+
+ Draw *text* within the specified rectangle, abiding by the alignment
+ flags. Will additionally emphasize the character at *indexAccel* if
+ it is not -1.
+ """
+ return _gdi_.DC_DrawLabel(*args, **kwargs)
+
+ def DrawImageLabel(*args, **kwargs):
+ """
+ DrawImageLabel(self, String text, Bitmap image, Rect rect, int alignment=wxALIGN_LEFT|wxALIGN_TOP,
+ int indexAccel=-1) -> Rect
+
+ Draw *text* and an image (which may be ``wx.NullBitmap`` to skip
+ drawing it) within the specified rectangle, abiding by the alignment
+ flags. Will additionally emphasize the character at *indexAccel* if
+ it is not -1. Returns the bounding rectangle.
+ """
+ return _gdi_.DC_DrawImageLabel(*args, **kwargs)
+
+ def DrawSpline(*args, **kwargs):
+ """
+ DrawSpline(self, List points)
+
+ Draws a spline between all given control points, (a list of `wx.Point`
+ objects) using the current pen. The spline is drawn using a series of
+ lines, using an algorithm taken from the X drawing program 'XFIG'.
+ """
+ return _gdi_.DC_DrawSpline(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """
+ Clear(self)
+
+ Clears the device context using the current background brush.
+ """
+ return _gdi_.DC_Clear(*args, **kwargs)
+
+ def StartDoc(*args, **kwargs):
+ """
+ StartDoc(self, String message) -> bool
+
+ Starts a document (only relevant when outputting to a
+ printer). *Message* is a message to show whilst printing.
+ """
+ return _gdi_.DC_StartDoc(*args, **kwargs)
+
+ def EndDoc(*args, **kwargs):
+ """
+ EndDoc(self)
+
+ Ends a document (only relevant when outputting to a printer).
+ """
+ return _gdi_.DC_EndDoc(*args, **kwargs)
+
+ def StartPage(*args, **kwargs):
+ """
+ StartPage(self)
+
+ Starts a document page (only relevant when outputting to a printer).
+ """
+ return _gdi_.DC_StartPage(*args, **kwargs)
+
+ def EndPage(*args, **kwargs):
+ """
+ EndPage(self)
+
+ Ends a document page (only relevant when outputting to a printer).
+ """
+ return _gdi_.DC_EndPage(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """
+ SetFont(self, Font font)
+
+ Sets the current font for the DC. It must be a valid font, in
+ particular you should not pass ``wx.NullFont`` to this method.
+ """
+ return _gdi_.DC_SetFont(*args, **kwargs)
+
+ def SetPen(*args, **kwargs):
+ """
+ SetPen(self, Pen pen)
+
+ Sets the current pen for the DC.
+
+ If the argument is ``wx.NullPen``, the current pen is selected out of the
+ device context, and the original pen restored.
+ """
+ return _gdi_.DC_SetPen(*args, **kwargs)
+
+ def SetBrush(*args, **kwargs):
+ """
+ SetBrush(self, Brush brush)
+
+ Sets the current brush for the DC.
+
+ If the argument is ``wx.NullBrush``, the current brush is selected out
+ of the device context, and the original brush restored, allowing the
+ current brush to be destroyed safely.
+ """
+ return _gdi_.DC_SetBrush(*args, **kwargs)
+
+ def SetBackground(*args, **kwargs):
+ """
+ SetBackground(self, Brush brush)
+
+ Sets the current background brush for the DC.
+ """
+ return _gdi_.DC_SetBackground(*args, **kwargs)
+
+ def SetBackgroundMode(*args, **kwargs):
+ """
+ SetBackgroundMode(self, int mode)
+
+ *mode* may be one of ``wx.SOLID`` and ``wx.TRANSPARENT``. This setting
+ determines whether text will be drawn with a background colour or
+ not.
+ """
+ return _gdi_.DC_SetBackgroundMode(*args, **kwargs)
+
+ def SetPalette(*args, **kwargs):
+ """
+ SetPalette(self, Palette palette)
+
+ If this is a window DC or memory DC, assigns the given palette to the
+ window or bitmap associated with the DC. If the argument is
+ ``wx.NullPalette``, the current palette is selected out of the device
+ context, and the original palette restored.
+ """
+ return _gdi_.DC_SetPalette(*args, **kwargs)
+
+ def DestroyClippingRegion(*args, **kwargs):
+ """
+ DestroyClippingRegion(self)
+
+ Destroys the current clipping region so that none of the DC is
+ clipped.
+ """
+ return _gdi_.DC_DestroyClippingRegion(*args, **kwargs)
+
+ def GetClippingBox(*args, **kwargs):
+ """
+ GetClippingBox() -> (x, y, width, height)
+
+ Gets the rectangle surrounding the current clipping region.
+ """
+ return _gdi_.DC_GetClippingBox(*args, **kwargs)
+
+ def GetClippingRect(*args, **kwargs):
+ """
+ GetClippingRect(self) -> Rect
+
+ Gets the rectangle surrounding the current clipping region.
+ """
+ return _gdi_.DC_GetClippingRect(*args, **kwargs)
+
+ def GetCharHeight(*args, **kwargs):
+ """
+ GetCharHeight(self) -> int
+
+ Gets the character height of the currently set font.
+ """
+ return _gdi_.DC_GetCharHeight(*args, **kwargs)
+
+ def GetCharWidth(*args, **kwargs):
+ """
+ GetCharWidth(self) -> int
+
+ Gets the average character width of the currently set font.
+ """
+ return _gdi_.DC_GetCharWidth(*args, **kwargs)
+
+ def GetFontMetrics(*args, **kwargs):
+ """GetFontMetrics(self) -> FontMetrics"""
+ return _gdi_.DC_GetFontMetrics(*args, **kwargs)
+
+ def GetTextExtent(*args, **kwargs):
+ """
+ GetTextExtent(wxString string) -> (width, height)
+
+ Get the width and height of the text using the current font. Only
+ works for single line strings.
+ """
+ return _gdi_.DC_GetTextExtent(*args, **kwargs)
+
+ def GetFullTextExtent(*args, **kwargs):
+ """
+ GetFullTextExtent(wxString string, Font font=None) ->
+ (width, height, descent, externalLeading)
+
+ Get the width, height, decent and leading of the text using the
+ current or specified font. Only works for single line strings.
+ """
+ return _gdi_.DC_GetFullTextExtent(*args, **kwargs)
+
+ def GetMultiLineTextExtent(*args, **kwargs):
+ """
+ GetMultiLineTextExtent(wxString string, Font font=None) ->
+ (width, height, lineHeight)
+
+ Get the width, height, and line height of the text using the
+ current or specified font. Works for single as well as multi-line
+ strings.
+ """
+ return _gdi_.DC_GetMultiLineTextExtent(*args, **kwargs)
+
+ def GetPartialTextExtents(*args, **kwargs):
+ """
+ GetPartialTextExtents(self, text) -> [widths]
+
+ Returns a list of integers such that each value is the distance in
+ pixels from the begining of text to the coresponding character of
+ *text*. The generic version simply builds a running total of the widths
+ of each character using GetTextExtent, however if the various
+ platforms have a native API function that is faster or more accurate
+ than the generic implementation then it will be used instead.
+ """
+ return _gdi_.DC_GetPartialTextExtents(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """
+ GetSize(self) -> Size
+
+ This gets the horizontal and vertical resolution in device units. It
+ can be used to scale graphics to fit the page. For example, if *maxX*
+ and *maxY* represent the maximum horizontal and vertical 'pixel' values
+ used in your application, the following code will scale the graphic to
+ fit on the printer page::
+
+ w, h = dc.GetSize()
+ scaleX = maxX*1.0 / w
+ scaleY = maxY*1.0 / h
+ dc.SetUserScale(min(scaleX,scaleY),min(scaleX,scaleY))
+
+ """
+ return _gdi_.DC_GetSize(*args, **kwargs)
+
+ def GetSizeTuple(*args, **kwargs):
+ """
+ GetSizeTuple() -> (width, height)
+
+ This gets the horizontal and vertical resolution in device units. It
+ can be used to scale graphics to fit the page. For example, if *maxX*
+ and *maxY* represent the maximum horizontal and vertical 'pixel' values
+ used in your application, the following code will scale the graphic to
+ fit on the printer page::
+
+ w, h = dc.GetSize()
+ scaleX = maxX*1.0 / w
+ scaleY = maxY*1.0 / h
+ dc.SetUserScale(min(scaleX,scaleY),min(scaleX,scaleY))
+
+ """
+ return _gdi_.DC_GetSizeTuple(*args, **kwargs)
+
+ def GetSizeMM(*args, **kwargs):
+ """
+ GetSizeMM(self) -> Size
+
+ Get the DC size in milimeters.
+ """
+ return _gdi_.DC_GetSizeMM(*args, **kwargs)
+
+ def GetSizeMMTuple(*args, **kwargs):
+ """
+ GetSizeMMTuple() -> (width, height)
+
+ Get the DC size in milimeters.
+ """
+ return _gdi_.DC_GetSizeMMTuple(*args, **kwargs)
+
+ def GetResolution(*args, **kwargs):
+ """GetResolution(self) -> int"""
+ return _gdi_.DC_GetResolution(*args, **kwargs)
+
+ def DeviceToLogicalX(*args, **kwargs):
+ """
+ DeviceToLogicalX(self, int x) -> int
+
+ Convert device X coordinate to logical coordinate, using the current
+ mapping mode.
+ """
+ return _gdi_.DC_DeviceToLogicalX(*args, **kwargs)
+
+ def DeviceToLogicalY(*args, **kwargs):
+ """
+ DeviceToLogicalY(self, int y) -> int
+
+ Converts device Y coordinate to logical coordinate, using the current
+ mapping mode.
+ """
+ return _gdi_.DC_DeviceToLogicalY(*args, **kwargs)
+
+ def DeviceToLogicalXRel(*args, **kwargs):
+ """
+ DeviceToLogicalXRel(self, int x) -> int
+
+ Convert device X coordinate to relative logical coordinate, using the
+ current mapping mode but ignoring the x axis orientation. Use this
+ function for converting a width, for example.
+ """
+ return _gdi_.DC_DeviceToLogicalXRel(*args, **kwargs)
+
+ def DeviceToLogicalYRel(*args, **kwargs):
+ """
+ DeviceToLogicalYRel(self, int y) -> int
+
+ Convert device Y coordinate to relative logical coordinate, using the
+ current mapping mode but ignoring the y axis orientation. Use this
+ function for converting a height, for example.
+ """
+ return _gdi_.DC_DeviceToLogicalYRel(*args, **kwargs)
+
+ def LogicalToDeviceX(*args, **kwargs):
+ """
+ LogicalToDeviceX(self, int x) -> int
+
+ Converts logical X coordinate to device coordinate, using the current
+ mapping mode.
+ """
+ return _gdi_.DC_LogicalToDeviceX(*args, **kwargs)
+
+ def LogicalToDeviceY(*args, **kwargs):
+ """
+ LogicalToDeviceY(self, int y) -> int
+
+ Converts logical Y coordinate to device coordinate, using the current
+ mapping mode.
+ """
+ return _gdi_.DC_LogicalToDeviceY(*args, **kwargs)
+
+ def LogicalToDeviceXRel(*args, **kwargs):
+ """
+ LogicalToDeviceXRel(self, int x) -> int
+
+ Converts logical X coordinate to relative device coordinate, using the
+ current mapping mode but ignoring the x axis orientation. Use this for
+ converting a width, for example.
+ """
+ return _gdi_.DC_LogicalToDeviceXRel(*args, **kwargs)
+
+ def LogicalToDeviceYRel(*args, **kwargs):
+ """
+ LogicalToDeviceYRel(self, int y) -> int
+
+ Converts logical Y coordinate to relative device coordinate, using the
+ current mapping mode but ignoring the y axis orientation. Use this for
+ converting a height, for example.
+ """
+ return _gdi_.DC_LogicalToDeviceYRel(*args, **kwargs)
+
+ def CanDrawBitmap(*args, **kwargs):
+ """CanDrawBitmap(self) -> bool"""
+ return _gdi_.DC_CanDrawBitmap(*args, **kwargs)
+
+ def CanGetTextExtent(*args, **kwargs):
+ """CanGetTextExtent(self) -> bool"""
+ return _gdi_.DC_CanGetTextExtent(*args, **kwargs)
+
+ def GetDepth(*args, **kwargs):
+ """
+ GetDepth(self) -> int
+
+ Returns the colour depth of the DC.
+ """
+ return _gdi_.DC_GetDepth(*args, **kwargs)
+
+ def GetPPI(*args, **kwargs):
+ """
+ GetPPI(self) -> Size
+
+ Resolution in pixels per inch
+ """
+ return _gdi_.DC_GetPPI(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """
+ IsOk(self) -> bool
+
+ Returns true if the DC is ok to use.
+ """
+ return _gdi_.DC_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def GetBackgroundMode(*args, **kwargs):
+ """
+ GetBackgroundMode(self) -> int
+
+ Returns the current background mode, either ``wx.SOLID`` or
+ ``wx.TRANSPARENT``.
+ """
+ return _gdi_.DC_GetBackgroundMode(*args, **kwargs)
+
+ def GetBackground(*args, **kwargs):
+ """
+ GetBackground(self) -> Brush
+
+ Gets the brush used for painting the background.
+ """
+ return _gdi_.DC_GetBackground(*args, **kwargs)
+
+ def GetBrush(*args, **kwargs):
+ """
+ GetBrush(self) -> Brush
+
+ Gets the current brush
+ """
+ return _gdi_.DC_GetBrush(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """
+ GetFont(self) -> Font
+
+ Gets the current font
+ """
+ return _gdi_.DC_GetFont(*args, **kwargs)
+
+ def GetPen(*args, **kwargs):
+ """
+ GetPen(self) -> Pen
+
+ Gets the current pen
+ """
+ return _gdi_.DC_GetPen(*args, **kwargs)
+
+ def GetTextBackground(*args, **kwargs):
+ """
+ GetTextBackground(self) -> Colour
+
+ Gets the current text background colour
+ """
+ return _gdi_.DC_GetTextBackground(*args, **kwargs)
+
+ def GetTextForeground(*args, **kwargs):
+ """
+ GetTextForeground(self) -> Colour
+
+ Gets the current text foreground colour
+ """
+ return _gdi_.DC_GetTextForeground(*args, **kwargs)
+
+ def SetTextForeground(*args, **kwargs):
+ """
+ SetTextForeground(self, Colour colour)
+
+ Sets the current text foreground colour for the DC.
+ """
+ return _gdi_.DC_SetTextForeground(*args, **kwargs)
+
+ def SetTextBackground(*args, **kwargs):
+ """
+ SetTextBackground(self, Colour colour)
+
+ Sets the current text background colour for the DC.
+ """
+ return _gdi_.DC_SetTextBackground(*args, **kwargs)
+
+ def GetMapMode(*args, **kwargs):
+ """
+ GetMapMode(self) -> int
+
+ Gets the current *mapping mode* for the device context
+ """
+ return _gdi_.DC_GetMapMode(*args, **kwargs)
+
+ def SetMapMode(*args, **kwargs):
+ """
+ SetMapMode(self, int mode)
+
+ The *mapping mode* of the device context defines the unit of
+ measurement used to convert logical units to device units. The
+ mapping mode can be one of the following:
+
+ ================ =============================================
+ wx.MM_TWIPS Each logical unit is 1/20 of a point, or 1/1440
+ of an inch.
+ wx.MM_POINTS Each logical unit is a point, or 1/72 of an inch.
+ wx.MM_METRIC Each logical unit is 1 mm.
+ wx.MM_LOMETRIC Each logical unit is 1/10 of a mm.
+ wx.MM_TEXT Each logical unit is 1 pixel.
+ ================ =============================================
+
+ """
+ return _gdi_.DC_SetMapMode(*args, **kwargs)
+
+ def GetUserScale(*args, **kwargs):
+ """
+ GetUserScale(self) -> (xScale, yScale)
+
+ Gets the current user scale factor (set by `SetUserScale`).
+ """
+ return _gdi_.DC_GetUserScale(*args, **kwargs)
+
+ def SetUserScale(*args, **kwargs):
+ """
+ SetUserScale(self, double x, double y)
+
+ Sets the user scaling factor, useful for applications which require
+ 'zooming'.
+ """
+ return _gdi_.DC_SetUserScale(*args, **kwargs)
+
+ def GetLogicalScale(*args, **kwargs):
+ """GetLogicalScale() -> (xScale, yScale)"""
+ return _gdi_.DC_GetLogicalScale(*args, **kwargs)
+
+ def SetLogicalScale(*args, **kwargs):
+ """SetLogicalScale(self, double x, double y)"""
+ return _gdi_.DC_SetLogicalScale(*args, **kwargs)
+
+ def GetLogicalOrigin(*args, **kwargs):
+ """GetLogicalOrigin(self) -> Point"""
+ return _gdi_.DC_GetLogicalOrigin(*args, **kwargs)
+
+ def GetLogicalOriginTuple(*args, **kwargs):
+ """GetLogicalOriginTuple() -> (x,y)"""
+ return _gdi_.DC_GetLogicalOriginTuple(*args, **kwargs)
+
+ def SetLogicalOrigin(*args, **kwargs):
+ """SetLogicalOrigin(self, int x, int y)"""
+ return _gdi_.DC_SetLogicalOrigin(*args, **kwargs)
+
+ def SetLogicalOriginPoint(*args, **kwargs):
+ """SetLogicalOriginPoint(self, Point point)"""
+ return _gdi_.DC_SetLogicalOriginPoint(*args, **kwargs)
+
+ def GetDeviceOrigin(*args, **kwargs):
+ """GetDeviceOrigin(self) -> Point"""
+ return _gdi_.DC_GetDeviceOrigin(*args, **kwargs)
+
+ def GetDeviceOriginTuple(*args, **kwargs):
+ """GetDeviceOriginTuple() -> (x,y)"""
+ return _gdi_.DC_GetDeviceOriginTuple(*args, **kwargs)
+
+ def SetDeviceOrigin(*args, **kwargs):
+ """SetDeviceOrigin(self, int x, int y)"""
+ return _gdi_.DC_SetDeviceOrigin(*args, **kwargs)
+
+ def SetDeviceOriginPoint(*args, **kwargs):
+ """SetDeviceOriginPoint(self, Point point)"""
+ return _gdi_.DC_SetDeviceOriginPoint(*args, **kwargs)
+
+ def SetAxisOrientation(*args, **kwargs):
+ """
+ SetAxisOrientation(self, bool xLeftRight, bool yBottomUp)
+
+ Sets the x and y axis orientation (i.e., the direction from lowest to
+ highest values on the axis). The default orientation is the natural
+ orientation, e.g. x axis from left to right and y axis from bottom up.
+ """
+ return _gdi_.DC_SetAxisOrientation(*args, **kwargs)
+
+ def GetLogicalFunction(*args, **kwargs):
+ """
+ GetLogicalFunction(self) -> int
+
+ Gets the current logical function (set by `SetLogicalFunction`).
+ """
+ return _gdi_.DC_GetLogicalFunction(*args, **kwargs)
+
+ def SetLogicalFunction(*args, **kwargs):
+ """
+ SetLogicalFunction(self, int function)
+
+ Sets the current logical function for the device context. This
+ determines how a source pixel (from a pen or brush colour, or source
+ device context if using `Blit`) combines with a destination pixel in
+ the current device context.
+
+ The possible values and their meaning in terms of source and
+ destination pixel values are as follows:
+
+ ================ ==========================
+ wx.AND src AND dst
+ wx.AND_INVERT (NOT src) AND dst
+ wx.AND_REVERSE src AND (NOT dst)
+ wx.CLEAR 0
+ wx.COPY src
+ wx.EQUIV (NOT src) XOR dst
+ wx.INVERT NOT dst
+ wx.NAND (NOT src) OR (NOT dst)
+ wx.NOR (NOT src) AND (NOT dst)
+ wx.NO_OP dst
+ wx.OR src OR dst
+ wx.OR_INVERT (NOT src) OR dst
+ wx.OR_REVERSE src OR (NOT dst)
+ wx.SET 1
+ wx.SRC_INVERT NOT src
+ wx.XOR src XOR dst
+ ================ ==========================
+
+ The default is wx.COPY, which simply draws with the current
+ colour. The others combine the current colour and the background using
+ a logical operation. wx.INVERT is commonly used for drawing rubber
+ bands or moving outlines, since drawing twice reverts to the original
+ colour.
+
+ """
+ return _gdi_.DC_SetLogicalFunction(*args, **kwargs)
+
+ def SetOptimization(self, optimize):
+ pass
+ def GetOptimization(self):
+ return False
+
+ SetOptimization = wx.deprecated(SetOptimization)
+ GetOptimization = wx.deprecated(GetOptimization)
+
+ def CalcBoundingBox(*args, **kwargs):
+ """
+ CalcBoundingBox(self, int x, int y)
+
+ Adds the specified point to the bounding box which can be retrieved
+ with `MinX`, `MaxX` and `MinY`, `MaxY` or `GetBoundingBox` functions.
+ """
+ return _gdi_.DC_CalcBoundingBox(*args, **kwargs)
+
+ def CalcBoundingBoxPoint(*args, **kwargs):
+ """
+ CalcBoundingBoxPoint(self, Point point)
+
+ Adds the specified point to the bounding box which can be retrieved
+ with `MinX`, `MaxX` and `MinY`, `MaxY` or `GetBoundingBox` functions.
+ """
+ return _gdi_.DC_CalcBoundingBoxPoint(*args, **kwargs)
+
+ def ResetBoundingBox(*args, **kwargs):
+ """
+ ResetBoundingBox(self)
+
+ Resets the bounding box: after a call to this function, the bounding
+ box doesn't contain anything.
+ """
+ return _gdi_.DC_ResetBoundingBox(*args, **kwargs)
+
+ def MinX(*args, **kwargs):
+ """
+ MinX(self) -> int
+
+ Gets the minimum horizontal extent used in drawing commands so far.
+ """
+ return _gdi_.DC_MinX(*args, **kwargs)
+
+ def MaxX(*args, **kwargs):
+ """
+ MaxX(self) -> int
+
+ Gets the maximum horizontal extent used in drawing commands so far.
+ """
+ return _gdi_.DC_MaxX(*args, **kwargs)
+
+ def MinY(*args, **kwargs):
+ """
+ MinY(self) -> int
+
+ Gets the minimum vertical extent used in drawing commands so far.
+ """
+ return _gdi_.DC_MinY(*args, **kwargs)
+
+ def MaxY(*args, **kwargs):
+ """
+ MaxY(self) -> int
+
+ Gets the maximum vertical extent used in drawing commands so far.
+ """
+ return _gdi_.DC_MaxY(*args, **kwargs)
+
+ def GetBoundingBox(*args, **kwargs):
+ """
+ GetBoundingBox() -> (x1,y1, x2,y2)
+
+ Returns the min and max points used in drawing commands so far.
+ """
+ return _gdi_.DC_GetBoundingBox(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def GetLayoutDirection(*args, **kwargs):
+ """
+ GetLayoutDirection(self) -> int
+
+ Get the layout direction (LTR or RTL)_ for this dc. On platforms
+ where RTL layout is supported, the return value will either be
+ ``wx.Layout_LeftToRight`` or ``wx.Layout_RightToLeft``.
+ ``wx.Layout_Default`` is returned if layout direction is not
+ supported.
+ """
+ return _gdi_.DC_GetLayoutDirection(*args, **kwargs)
+
+ def SetLayoutDirection(*args, **kwargs):
+ """
+ SetLayoutDirection(self, int dir)
+
+ Change the layout direction for this dc.
+ """
+ return _gdi_.DC_SetLayoutDirection(*args, **kwargs)
+
+ def GetHandle(*args, **kwargs):
+ """GetHandle(self) -> void"""
+ return _gdi_.DC_GetHandle(*args, **kwargs)
+
+ def GetHDC(*args, **kwargs):
+ """GetHDC(self) -> long"""
+ return _gdi_.DC_GetHDC(*args, **kwargs)
+
+ def _DrawPointList(*args, **kwargs):
+ """_DrawPointList(self, PyObject pyCoords, PyObject pyPens, PyObject pyBrushes) -> PyObject"""
+ return _gdi_.DC__DrawPointList(*args, **kwargs)
+
+ def _DrawLineList(*args, **kwargs):
+ """_DrawLineList(self, PyObject pyCoords, PyObject pyPens, PyObject pyBrushes) -> PyObject"""
+ return _gdi_.DC__DrawLineList(*args, **kwargs)
+
+ def _DrawRectangleList(*args, **kwargs):
+ """_DrawRectangleList(self, PyObject pyCoords, PyObject pyPens, PyObject pyBrushes) -> PyObject"""
+ return _gdi_.DC__DrawRectangleList(*args, **kwargs)
+
+ def _DrawEllipseList(*args, **kwargs):
+ """_DrawEllipseList(self, PyObject pyCoords, PyObject pyPens, PyObject pyBrushes) -> PyObject"""
+ return _gdi_.DC__DrawEllipseList(*args, **kwargs)
+
+ def _DrawPolygonList(*args, **kwargs):
+ """_DrawPolygonList(self, PyObject pyCoords, PyObject pyPens, PyObject pyBrushes) -> PyObject"""
+ return _gdi_.DC__DrawPolygonList(*args, **kwargs)
+
+ def _DrawTextList(*args, **kwargs):
+ """
+ _DrawTextList(self, PyObject textList, PyObject pyPoints, PyObject foregroundList,
+ PyObject backgroundList) -> PyObject
+ """
+ return _gdi_.DC__DrawTextList(*args, **kwargs)
+
+ def DrawPointList(self, points, pens=None):
+ """
+ Draw a list of points as quickly as possible.
+
+ :param points: A sequence of 2-element sequences representing
+ each point to draw, (x,y).
+ :param pens: If None, then the current pen is used. If a
+ single pen then it will be used for all points. If
+ a list of pens then there should be one for each point
+ in points.
+ """
+ if pens is None:
+ pens = []
+ elif isinstance(pens, wx.Pen):
+ pens = [pens]
+ elif len(pens) != len(points):
+ raise ValueError('points and pens must have same length')
+ return self._DrawPointList(points, pens, [])
+
+
+ def DrawLineList(self, lines, pens=None):
+ """
+ Draw a list of lines as quickly as possible.
+
+ :param lines: A sequence of 4-element sequences representing
+ each line to draw, (x1,y1, x2,y2).
+ :param pens: If None, then the current pen is used. If a
+ single pen then it will be used for all lines. If
+ a list of pens then there should be one for each line
+ in lines.
+ """
+ if pens is None:
+ pens = []
+ elif isinstance(pens, wx.Pen):
+ pens = [pens]
+ elif len(pens) != len(lines):
+ raise ValueError('lines and pens must have same length')
+ return self._DrawLineList(lines, pens, [])
+
+
+ def DrawRectangleList(self, rectangles, pens=None, brushes=None):
+ """
+ Draw a list of rectangles as quickly as possible.
+
+ :param rectangles: A sequence of 4-element sequences representing
+ each rectangle to draw, (x,y, w,h).
+ :param pens: If None, then the current pen is used. If a
+ single pen then it will be used for all rectangles.
+ If a list of pens then there should be one for each
+ rectangle in rectangles.
+ :param brushes: A brush or brushes to be used to fill the rectagles,
+ with similar semantics as the pens parameter.
+ """
+ if pens is None:
+ pens = []
+ elif isinstance(pens, wx.Pen):
+ pens = [pens]
+ elif len(pens) != len(rectangles):
+ raise ValueError('rectangles and pens must have same length')
+ if brushes is None:
+ brushes = []
+ elif isinstance(brushes, wx.Brush):
+ brushes = [brushes]
+ elif len(brushes) != len(rectangles):
+ raise ValueError('rectangles and brushes must have same length')
+ return self._DrawRectangleList(rectangles, pens, brushes)
+
+
+ def DrawEllipseList(self, ellipses, pens=None, brushes=None):
+ """
+ Draw a list of ellipses as quickly as possible.
+
+ :param ellipses: A sequence of 4-element sequences representing
+ each ellipse to draw, (x,y, w,h).
+ :param pens: If None, then the current pen is used. If a
+ single pen then it will be used for all ellipses.
+ If a list of pens then there should be one for each
+ ellipse in ellipses.
+ :param brushes: A brush or brushes to be used to fill the ellipses,
+ with similar semantics as the pens parameter.
+ """
+ if pens is None:
+ pens = []
+ elif isinstance(pens, wx.Pen):
+ pens = [pens]
+ elif len(pens) != len(ellipses):
+ raise ValueError('ellipses and pens must have same length')
+ if brushes is None:
+ brushes = []
+ elif isinstance(brushes, wx.Brush):
+ brushes = [brushes]
+ elif len(brushes) != len(ellipses):
+ raise ValueError('ellipses and brushes must have same length')
+ return self._DrawEllipseList(ellipses, pens, brushes)
+
+
+ def DrawPolygonList(self, polygons, pens=None, brushes=None):
+ """
+ Draw a list of polygons, each of which is a list of points.
+
+ :param polygons: A sequence of sequences of sequences.
+ [[(x1,y1),(x2,y2),(x3,y3)...],
+ [(x1,y1),(x2,y2),(x3,y3)...]]
+
+ :param pens: If None, then the current pen is used. If a
+ single pen then it will be used for all polygons.
+ If a list of pens then there should be one for each
+ polygon.
+ :param brushes: A brush or brushes to be used to fill the polygons,
+ with similar semantics as the pens parameter.
+ """
+ if pens is None:
+ pens = []
+ elif isinstance(pens, wx.Pen):
+ pens = [pens]
+ elif len(pens) != len(polygons):
+ raise ValueError('polygons and pens must have same length')
+ if brushes is None:
+ brushes = []
+ elif isinstance(brushes, wx.Brush):
+ brushes = [brushes]
+ elif len(brushes) != len(polygons):
+ raise ValueError('polygons and brushes must have same length')
+ return self._DrawPolygonList(polygons, pens, brushes)
+
+
+ def DrawTextList(self, textList, coords, foregrounds = None, backgrounds = None):
+ """
+ Draw a list of strings using a list of coordinants for positioning each string.
+
+ :param textList: A list of strings
+ :param coords: A list of (x,y) positions
+ :param foregrounds: A list of `wx.Colour` objects to use for the
+ foregrounds of the strings.
+ :param backgrounds: A list of `wx.Colour` objects to use for the
+ backgrounds of the strings.
+
+ NOTE: Make sure you set Background mode to wx.Solid (DC.SetBackgroundMode)
+ If you want backgrounds to do anything.
+ """
+ if type(textList) == type(''):
+ textList = [textList]
+ elif len(textList) != len(coords):
+ raise ValueError('textlist and coords must have same length')
+ if foregrounds is None:
+ foregrounds = []
+ elif isinstance(foregrounds, wx.Colour):
+ foregrounds = [foregrounds]
+ elif len(foregrounds) != len(coords):
+ raise ValueError('foregrounds and coords must have same length')
+ if backgrounds is None:
+ backgrounds = []
+ elif isinstance(backgrounds, wx.Colour):
+ backgrounds = [backgrounds]
+ elif len(backgrounds) != len(coords):
+ raise ValueError('backgrounds and coords must have same length')
+ return self._DrawTextList(textList, coords, foregrounds, backgrounds)
+
+ Background = property(GetBackground,SetBackground,doc="See `GetBackground` and `SetBackground`")
+ BackgroundMode = property(GetBackgroundMode,SetBackgroundMode,doc="See `GetBackgroundMode` and `SetBackgroundMode`")
+ BoundingBox = property(GetBoundingBox,doc="See `GetBoundingBox`")
+ Brush = property(GetBrush,SetBrush,doc="See `GetBrush` and `SetBrush`")
+ CharHeight = property(GetCharHeight,doc="See `GetCharHeight`")
+ CharWidth = property(GetCharWidth,doc="See `GetCharWidth`")
+ ClippingBox = property(GetClippingBox,doc="See `GetClippingBox`")
+ ClippingRect = property(GetClippingRect,SetClippingRect,doc="See `GetClippingRect` and `SetClippingRect`")
+ Depth = property(GetDepth,doc="See `GetDepth`")
+ DeviceOrigin = property(GetDeviceOrigin,SetDeviceOrigin,doc="See `GetDeviceOrigin` and `SetDeviceOrigin`")
+ Font = property(GetFont,SetFont,doc="See `GetFont` and `SetFont`")
+ FullTextExtent = property(GetFullTextExtent,doc="See `GetFullTextExtent`")
+ LogicalFunction = property(GetLogicalFunction,SetLogicalFunction,doc="See `GetLogicalFunction` and `SetLogicalFunction`")
+ LogicalOrigin = property(GetLogicalOrigin,SetLogicalOrigin,doc="See `GetLogicalOrigin` and `SetLogicalOrigin`")
+ LogicalScale = property(GetLogicalScale,SetLogicalScale,doc="See `GetLogicalScale` and `SetLogicalScale`")
+ MapMode = property(GetMapMode,SetMapMode,doc="See `GetMapMode` and `SetMapMode`")
+ MultiLineTextExtent = property(GetMultiLineTextExtent,doc="See `GetMultiLineTextExtent`")
+ Optimization = property(GetOptimization,SetOptimization,doc="See `GetOptimization` and `SetOptimization`")
+ PPI = property(GetPPI,doc="See `GetPPI`")
+ PartialTextExtents = property(GetPartialTextExtents,doc="See `GetPartialTextExtents`")
+ Pen = property(GetPen,SetPen,doc="See `GetPen` and `SetPen`")
+ Size = property(GetSize,doc="See `GetSize`")
+ SizeMM = property(GetSizeMM,doc="See `GetSizeMM`")
+ TextBackground = property(GetTextBackground,SetTextBackground,doc="See `GetTextBackground` and `SetTextBackground`")
+ TextExtent = property(GetTextExtent,doc="See `GetTextExtent`")
+ TextForeground = property(GetTextForeground,SetTextForeground,doc="See `GetTextForeground` and `SetTextForeground`")
+ UserScale = property(GetUserScale,SetUserScale,doc="See `GetUserScale` and `SetUserScale`")
+ LayoutDirection = property(GetLayoutDirection,SetLayoutDirection)
+_gdi_.DC_swigregister(DC)
+
+#---------------------------------------------------------------------------
+
+class DCTextColourChanger(object):
+ """
+ wx.DCTextColourChanger can be used to temporarily change the DC text
+ colour and restore it automatically when the object goes out of scope
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, DC dc, Colour col) -> DCTextColourChanger
+
+ wx.DCTextColourChanger can be used to temporarily change the DC text
+ colour and restore it automatically when the object goes out of scope
+ """
+ _gdi_.DCTextColourChanger_swiginit(self,_gdi_.new_DCTextColourChanger(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_DCTextColourChanger
+ __del__ = lambda self : None;
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_gdi_.DCTextColourChanger_swigregister(DCTextColourChanger)
+
+class DCPenChanger(object):
+ """
+ wx.DCPenChanger can be used to temporarily change the DC pen and
+ restore it automatically when the object goes out of scope
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, DC dc, Pen pen) -> DCPenChanger
+
+ wx.DCPenChanger can be used to temporarily change the DC pen and
+ restore it automatically when the object goes out of scope
+ """
+ _gdi_.DCPenChanger_swiginit(self,_gdi_.new_DCPenChanger(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_DCPenChanger
+ __del__ = lambda self : None;
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_gdi_.DCPenChanger_swigregister(DCPenChanger)
+
+class DCBrushChanger(object):
+ """
+ wx.DCBrushChanger can be used to temporarily change the DC brush and
+ restore it automatically when the object goes out of scope
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, DC dc, Brush brush) -> DCBrushChanger
+
+ wx.DCBrushChanger can be used to temporarily change the DC brush and
+ restore it automatically when the object goes out of scope
+ """
+ _gdi_.DCBrushChanger_swiginit(self,_gdi_.new_DCBrushChanger(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_DCBrushChanger
+ __del__ = lambda self : None;
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_gdi_.DCBrushChanger_swigregister(DCBrushChanger)
+
+class DCClipper(object):
+ """
+ wx.wxDCClipper sets the DC's clipping region when it is constructed,
+ and then automatically destroys the clipping region when the clipper
+ goes out of scope.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, DC dc, Region r) -> DCClipper
+ __init__(self, DC dc, Rect r) -> DCClipper
+ __init__(self, DC dc, int x, int y, int w, int h) -> DCClipper
+
+ wx.wxDCClipper sets the DC's clipping region when it is constructed,
+ and then automatically destroys the clipping region when the clipper
+ goes out of scope.
+ """
+ _gdi_.DCClipper_swiginit(self,_gdi_.new_DCClipper(*args))
+ __swig_destroy__ = _gdi_.delete_DCClipper
+ __del__ = lambda self : None;
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_gdi_.DCClipper_swigregister(DCClipper)
+
+class DCFontChanger(object):
+ """
+ wx.wxDCFontChanger sets the DC's font when it is constructed,
+ and then restores the old font whrn it goes out of scope.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, DC dc, Font font) -> DCFontChanger
+
+ wx.wxDCFontChanger sets the DC's font when it is constructed,
+ and then restores the old font whrn it goes out of scope.
+ """
+ _gdi_.DCFontChanger_swiginit(self,_gdi_.new_DCFontChanger(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_DCFontChanger
+ __del__ = lambda self : None;
+ def Set(*args, **kwargs):
+ """Set(self, Font font)"""
+ return _gdi_.DCFontChanger_Set(*args, **kwargs)
+
+_gdi_.DCFontChanger_swigregister(DCFontChanger)
+
+#---------------------------------------------------------------------------
+
+class ScreenDC(DC):
+ """
+ A wxScreenDC can be used to paint anywhere on the screen. This should
+ normally be constructed as a temporary stack object; don't store a
+ wxScreenDC object.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> ScreenDC
+
+ A wxScreenDC can be used to paint anywhere on the screen. This should
+ normally be constructed as a temporary stack object; don't store a
+ wxScreenDC object.
+
+ """
+ _gdi_.ScreenDC_swiginit(self,_gdi_.new_ScreenDC(*args, **kwargs))
+ def StartDrawingOnTopWin(*args, **kwargs):
+ """
+ StartDrawingOnTopWin(self, Window window) -> bool
+
+ Specify that the area of the screen to be drawn upon coincides with
+ the given window.
+
+ :see: `EndDrawingOnTop`
+ """
+ return _gdi_.ScreenDC_StartDrawingOnTopWin(*args, **kwargs)
+
+ def StartDrawingOnTop(*args, **kwargs):
+ """
+ StartDrawingOnTop(self, Rect rect=None) -> bool
+
+ Specify that the area is the given rectangle, or the whole screen if
+ ``None`` is passed.
+
+ :see: `EndDrawingOnTop`
+ """
+ return _gdi_.ScreenDC_StartDrawingOnTop(*args, **kwargs)
+
+ def EndDrawingOnTop(*args, **kwargs):
+ """
+ EndDrawingOnTop(self) -> bool
+
+ Use this in conjunction with `StartDrawingOnTop` or
+ `StartDrawingOnTopWin` to ensure that drawing to the screen occurs on
+ top of existing windows. Without this, some window systems (such as X)
+ only allow drawing to take place underneath other windows.
+
+ You might use this pair of functions when implementing a drag feature,
+ for example as in the `wx.SplitterWindow` implementation.
+
+ These functions are probably obsolete since the X implementations
+ allow drawing directly on the screen now. However, the fact that this
+ function allows the screen to be refreshed afterwards may be useful
+ to some applications.
+ """
+ return _gdi_.ScreenDC_EndDrawingOnTop(*args, **kwargs)
+
+_gdi_.ScreenDC_swigregister(ScreenDC)
+
+#---------------------------------------------------------------------------
+
+class WindowDC(DC):
+ """
+ A wx.WindowDC must be constructed if an application wishes to paint on
+ the whole area of a window (client and decorations). This should
+ normally be constructed as a temporary stack object; don't store a
+ wx.WindowDC object.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window win) -> WindowDC
+
+ Constructor. Pass the window on which you wish to paint.
+ """
+ _gdi_.WindowDC_swiginit(self,_gdi_.new_WindowDC(*args, **kwargs))
+_gdi_.WindowDC_swigregister(WindowDC)
+
+#---------------------------------------------------------------------------
+
+class ClientDC(WindowDC):
+ """
+ A wx.ClientDC must be constructed if an application wishes to paint on
+ the client area of a window from outside an EVT_PAINT event. This should
+ normally be constructed as a temporary stack object; don't store a
+ wx.ClientDC object long term.
+
+ To draw on a window from within an EVT_PAINT handler, construct a
+ `wx.PaintDC` object.
+
+ To draw on the whole window including decorations, construct a
+ `wx.WindowDC` object (Windows only).
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window win) -> ClientDC
+
+ Constructor. Pass the window on which you wish to paint.
+ """
+ _gdi_.ClientDC_swiginit(self,_gdi_.new_ClientDC(*args, **kwargs))
+_gdi_.ClientDC_swigregister(ClientDC)
+
+#---------------------------------------------------------------------------
+
+class PaintDC(ClientDC):
+ """
+ A wx.PaintDC must be constructed if an application wishes to paint on
+ the client area of a window from within an EVT_PAINT event
+ handler. This should normally be constructed as a temporary stack
+ object; don't store a wx.PaintDC object. If you have an EVT_PAINT
+ handler, you **must** create a wx.PaintDC object within it even if you
+ don't actually use it.
+
+ Using wx.PaintDC within EVT_PAINT handlers is important because it
+ automatically sets the clipping area to the damaged area of the
+ window. Attempts to draw outside this area do not appear.
+
+ To draw on a window from outside EVT_PAINT handlers, construct a
+ `wx.ClientDC` object.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window win) -> PaintDC
+
+ Constructor. Pass the window on which you wish to paint.
+ """
+ _gdi_.PaintDC_swiginit(self,_gdi_.new_PaintDC(*args, **kwargs))
+_gdi_.PaintDC_swigregister(PaintDC)
+
+#---------------------------------------------------------------------------
+
+class MemoryDC(WindowDC):
+ """
+ A memory device context provides a means to draw graphics onto a
+ bitmap. A bitmap must be selected into the new memory DC before it may
+ be used for anything. Typical usage is as follows::
+
+ dc = wx.MemoryDC()
+ dc.SelectObject(bitmap)
+ # draw on the dc using any of the Draw methods
+ dc.SelectObject(wx.NullBitmap)
+ # the bitmap now contains wahtever was drawn upon it
+
+ Note that the memory DC *must* be deleted (or the bitmap selected out
+ of it) before a bitmap can be reselected into another memory DC.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Bitmap bitmap=NullBitmap) -> MemoryDC
+
+ Constructs a new memory device context.
+
+ Use the Ok member to test whether the constructor was successful in
+ creating a usable device context. If a bitmap is not given to this
+ constructor then don't forget to select a bitmap into the DC before
+ drawing on it.
+ """
+ _gdi_.MemoryDC_swiginit(self,_gdi_.new_MemoryDC(*args, **kwargs))
+ def SelectObject(*args, **kwargs):
+ """
+ SelectObject(self, Bitmap bitmap)
+
+ Selects the bitmap into the device context, to use as the memory
+ bitmap. Selecting the bitmap into a memory DC allows you to draw into
+ the DC, and therefore the bitmap, and also to use Blit to copy the
+ bitmap to a window.
+
+ If the argument is wx.NullBitmap (or some other uninitialised
+ `wx.Bitmap`) the current bitmap is selected out of the device context,
+ and the original bitmap restored, allowing the current bitmap to be
+ destroyed safely.
+ """
+ return _gdi_.MemoryDC_SelectObject(*args, **kwargs)
+
+ def SelectObjectAsSource(*args, **kwargs):
+ """SelectObjectAsSource(self, Bitmap bmp)"""
+ return _gdi_.MemoryDC_SelectObjectAsSource(*args, **kwargs)
+
+_gdi_.MemoryDC_swigregister(MemoryDC)
+
+def MemoryDCFromDC(*args, **kwargs):
+ """
+ MemoryDCFromDC(DC oldDC) -> MemoryDC
+
+ Creates a DC that is compatible with the oldDC.
+ """
+ val = _gdi_.new_MemoryDCFromDC(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+BUFFER_VIRTUAL_AREA = _gdi_.BUFFER_VIRTUAL_AREA
+BUFFER_CLIENT_AREA = _gdi_.BUFFER_CLIENT_AREA
+BUFFER_USES_SHARED_BUFFER = _gdi_.BUFFER_USES_SHARED_BUFFER
+class BufferedDC(MemoryDC):
+ """
+ This simple class provides a simple way to avoid flicker: when drawing
+ on it, everything is in fact first drawn on an in-memory buffer (a
+ `wx.Bitmap`) and then copied to the screen only once, when this object
+ is destroyed. You can either provide a buffer bitmap yourself, and
+ reuse it the next time something needs painted, or you can let the
+ buffered DC create and provide a buffer bitmap itself.
+
+ Buffered DCs can be used in the same way as any other device context.
+ wx.BufferedDC itself typically replaces `wx.ClientDC`, if you want to
+ use it in your EVT_PAINT handler, you should look at
+ `wx.BufferedPaintDC`. You can also use a wx.BufferedDC without
+ providing a target DC. In this case the operations done on the dc
+ will only be written to the buffer bitmap and *not* to any window, so
+ you will want to have provided the buffer bitmap and then reuse it
+ when it needs painted to the window.
+
+ Please note that GTK+ 2.0 and OS X provide double buffering themselves
+ natively. You may want to use `wx.Window.IsDoubleBuffered` to
+ determine whether you need to use buffering or not, or use
+ `wx.AutoBufferedPaintDC` to avoid needless double buffering on systems
+ that already do it automatically.
+
+
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, DC dc, Bitmap buffer=NullBitmap, int style=BUFFER_CLIENT_AREA) -> BufferedDC
+ __init__(self, DC dc, Size area, int style=BUFFER_CLIENT_AREA) -> BufferedDC
+
+ Constructs a buffered DC.
+ """
+ _gdi_.BufferedDC_swiginit(self,_gdi_.new_BufferedDC(*args))
+ # save a ref so the other dc will not be deleted before self
+ self.__dc = args[0]
+ # also save a ref to the bitmap
+ if len(args) > 1: self.__bmp = args[1]
+
+
+ __swig_destroy__ = _gdi_.delete_BufferedDC
+ __del__ = lambda self : None;
+ def UnMask(*args, **kwargs):
+ """
+ UnMask(self)
+
+ Blits the buffer to the dc, and detaches the dc from the buffer (so it
+ can be effectively used once only). This is usually only called in
+ the destructor.
+ """
+ return _gdi_.BufferedDC_UnMask(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """SetStyle(self, int style)"""
+ return _gdi_.BufferedDC_SetStyle(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self) -> int"""
+ return _gdi_.BufferedDC_GetStyle(*args, **kwargs)
+
+_gdi_.BufferedDC_swigregister(BufferedDC)
+
+class BufferedPaintDC(BufferedDC):
+ """
+ This is a subclass of `wx.BufferedDC` which can be used inside of an
+ EVT_PAINT event handler. Just create an object of this class instead
+ of `wx.PaintDC` and that's all you have to do to (mostly) avoid
+ flicker. The only thing to watch out for is that if you are using this
+ class together with `wx.ScrolledWindow`, you probably do **not** want
+ to call `wx.ScrolledWindow.PrepareDC` on it as it already does this internally
+ for the real underlying `wx.PaintDC`.
+
+ If your window is already fully buffered in a `wx.Bitmap` then your
+ EVT_PAINT handler can be as simple as just creating a
+ ``wx.BufferedPaintDC`` as it will `Blit` the buffer to the window
+ automatically when it is destroyed. For example::
+
+ def OnPaint(self, event):
+ dc = wx.BufferedPaintDC(self, self.buffer)
+
+
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window window, Bitmap buffer=NullBitmap, int style=BUFFER_CLIENT_AREA) -> BufferedPaintDC
+
+ Create a buffered paint DC. As with `wx.BufferedDC`, you may either
+ provide the bitmap to be used for buffering or let this object create
+ one internally (in the latter case, the size of the client part of the
+ window is automatically used).
+ """
+ _gdi_.BufferedPaintDC_swiginit(self,_gdi_.new_BufferedPaintDC(*args, **kwargs))
+ if len(args) > 1: self.__bmp = args[1]
+
+_gdi_.BufferedPaintDC_swigregister(BufferedPaintDC)
+
+#---------------------------------------------------------------------------
+
+class AutoBufferedPaintDC(DC):
+ """
+ If the current platform double buffers by default then this DC is the
+ same as a plain `wx.PaintDC`, otherwise it is a `wx.BufferedPaintDC`.
+
+ :see: `wx.AutoBufferedPaintDCFactory`
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window win) -> AutoBufferedPaintDC
+
+ If the current platform double buffers by default then this DC is the
+ same as a plain `wx.PaintDC`, otherwise it is a `wx.BufferedPaintDC`.
+
+ :see: `wx.AutoBufferedPaintDCFactory`
+
+ """
+ _gdi_.AutoBufferedPaintDC_swiginit(self,_gdi_.new_AutoBufferedPaintDC(*args, **kwargs))
+_gdi_.AutoBufferedPaintDC_swigregister(AutoBufferedPaintDC)
+
+
+def AutoBufferedPaintDCFactory(*args, **kwargs):
+ """
+ AutoBufferedPaintDCFactory(Window window) -> DC
+
+ Checks if the window is natively double buffered and will return a
+ `wx.PaintDC` if it is, a `wx.BufferedPaintDC` otherwise. The advantage of
+ this function over `wx.AutoBufferedPaintDC` is that this function will check
+ if the the specified window has double-buffering enabled rather than just
+ going by platform defaults.
+ """
+ return _gdi_.AutoBufferedPaintDCFactory(*args, **kwargs)
+#---------------------------------------------------------------------------
+
+class MirrorDC(DC):
+ """
+ wx.MirrorDC is a simple wrapper class which is always associated with a
+ real `wx.DC` object and either forwards all of its operations to it
+ without changes (no mirroring takes place) or exchanges x and y
+ coordinates which makes it possible to reuse the same code to draw a
+ figure and its mirror -- i.e. reflection related to the diagonal line
+ x == y.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, DC dc, bool mirror) -> MirrorDC
+
+ Creates a mirrored DC associated with the real *dc*. Everything drawn
+ on the wx.MirrorDC will appear on the *dc*, and will be mirrored if
+ *mirror* is True.
+ """
+ _gdi_.MirrorDC_swiginit(self,_gdi_.new_MirrorDC(*args, **kwargs))
+_gdi_.MirrorDC_swigregister(MirrorDC)
+
+#---------------------------------------------------------------------------
+
+class PostScriptDC(DC):
+ """This is a `wx.DC` that can write to PostScript files on any platform."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, wxPrintData printData) -> PostScriptDC
+
+ Constructs a PostScript printer device context from a `wx.PrintData`
+ object.
+ """
+ _gdi_.PostScriptDC_swiginit(self,_gdi_.new_PostScriptDC(*args, **kwargs))
+_gdi_.PostScriptDC_swigregister(PostScriptDC)
+
+#---------------------------------------------------------------------------
+
+class MetaFile(_core.Object):
+ """Proxy of C++ MetaFile class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String filename=EmptyString) -> MetaFile"""
+ _gdi_.MetaFile_swiginit(self,_gdi_.new_MetaFile(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_MetaFile
+ __del__ = lambda self : None;
+ def Play(*args, **kwargs):
+ """Play(self, DC dc) -> bool"""
+ return _gdi_.MetaFile_Play(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.MetaFile_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def SetClipboard(*args, **kwargs):
+ """SetClipboard(self, int width=0, int height=0) -> bool"""
+ return _gdi_.MetaFile_SetClipboard(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(self) -> Size"""
+ return _gdi_.MetaFile_GetSize(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _gdi_.MetaFile_GetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """GetHeight(self) -> int"""
+ return _gdi_.MetaFile_GetHeight(*args, **kwargs)
+
+ def GetFileName(*args, **kwargs):
+ """GetFileName(self) -> String"""
+ return _gdi_.MetaFile_GetFileName(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+_gdi_.MetaFile_swigregister(MetaFile)
+
+class MetaFileDC(DC):
+ """Proxy of C++ MetaFileDC class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String filename=EmptyString, int width=0, int height=0,
+ String description=EmptyString) -> MetaFileDC
+ """
+ _gdi_.MetaFileDC_swiginit(self,_gdi_.new_MetaFileDC(*args, **kwargs))
+ def Close(*args, **kwargs):
+ """Close(self) -> MetaFile"""
+ return _gdi_.MetaFileDC_Close(*args, **kwargs)
+
+_gdi_.MetaFileDC_swigregister(MetaFileDC)
+
+class EnhMetaFile(GDIObject):
+ """Proxy of C++ EnhMetaFile class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, String file=wxEmptyString) -> EnhMetaFile
+ __init__(self, EnhMetaFile metafile) -> EnhMetaFile
+ """
+ _gdi_.EnhMetaFile_swiginit(self,_gdi_.new_EnhMetaFile(*args))
+ __swig_destroy__ = _gdi_.delete_EnhMetaFile
+ __del__ = lambda self : None;
+ def Play(*args, **kwargs):
+ """Play(self, DC dc, Rect rectBound=None) -> bool"""
+ return _gdi_.EnhMetaFile_Play(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _gdi_.EnhMetaFile_IsOk(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(self) -> Size"""
+ return _gdi_.EnhMetaFile_GetSize(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _gdi_.EnhMetaFile_GetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """GetHeight(self) -> int"""
+ return _gdi_.EnhMetaFile_GetHeight(*args, **kwargs)
+
+ def GetFileName(*args, **kwargs):
+ """GetFileName(self) -> String"""
+ return _gdi_.EnhMetaFile_GetFileName(*args, **kwargs)
+
+ def SetClipboard(*args, **kwargs):
+ """SetClipboard(self, int width=0, int height=0) -> bool"""
+ return _gdi_.EnhMetaFile_SetClipboard(*args, **kwargs)
+
+_gdi_.EnhMetaFile_swigregister(EnhMetaFile)
+
+class EnhMetaFileDC(DC):
+ """Proxy of C++ EnhMetaFileDC class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, String filename=wxEmptyString, int width=0, int height=0,
+ String description=wxEmptyString) -> EnhMetaFileDC
+ __init__(self, DC referenceDC, String filename=wxEmptyString, int width=0,
+ int height=0, String description=wxEmptyString) -> EnhMetaFileDC
+ """
+ _gdi_.EnhMetaFileDC_swiginit(self,_gdi_.new_EnhMetaFileDC(*args))
+ def Close(*args, **kwargs):
+ """Close(self) -> EnhMetaFile"""
+ return _gdi_.EnhMetaFileDC_Close(*args, **kwargs)
+
+_gdi_.EnhMetaFileDC_swigregister(EnhMetaFileDC)
+
+class PrinterDC(DC):
+ """Proxy of C++ PrinterDC class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, wxPrintData printData) -> PrinterDC"""
+ _gdi_.PrinterDC_swiginit(self,_gdi_.new_PrinterDC(*args, **kwargs))
+ def GetPaperRect(*args, **kwargs):
+ """GetPaperRect(self) -> Rect"""
+ return _gdi_.PrinterDC_GetPaperRect(*args, **kwargs)
+
+_gdi_.PrinterDC_swigregister(PrinterDC)
+
+class SVGFileDC(DC):
+ """Proxy of C++ SVGFileDC class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String filename, int width=320, int height=240, double dpi=72.0) -> SVGFileDC"""
+ _gdi_.SVGFileDC_swiginit(self,_gdi_.new_SVGFileDC(*args, **kwargs))
+_gdi_.SVGFileDC_swigregister(SVGFileDC)
+
+#---------------------------------------------------------------------------
+
+ANTIALIAS_NONE = _gdi_.ANTIALIAS_NONE
+ANTIALIAS_DEFAULT = _gdi_.ANTIALIAS_DEFAULT
+INTERPOLATION_DEFAULT = _gdi_.INTERPOLATION_DEFAULT
+INTERPOLATION_NONE = _gdi_.INTERPOLATION_NONE
+INTERPOLATION_FAST = _gdi_.INTERPOLATION_FAST
+INTERPOLATION_GOOD = _gdi_.INTERPOLATION_GOOD
+INTERPOLATION_BEST = _gdi_.INTERPOLATION_BEST
+COMPOSITION_INVALID = _gdi_.COMPOSITION_INVALID
+COMPOSITION_CLEAR = _gdi_.COMPOSITION_CLEAR
+COMPOSITION_SOURCE = _gdi_.COMPOSITION_SOURCE
+COMPOSITION_OVER = _gdi_.COMPOSITION_OVER
+COMPOSITION_IN = _gdi_.COMPOSITION_IN
+COMPOSITION_OUT = _gdi_.COMPOSITION_OUT
+COMPOSITION_ATOP = _gdi_.COMPOSITION_ATOP
+COMPOSITION_DEST = _gdi_.COMPOSITION_DEST
+COMPOSITION_DEST_OVER = _gdi_.COMPOSITION_DEST_OVER
+COMPOSITION_DEST_IN = _gdi_.COMPOSITION_DEST_IN
+COMPOSITION_DEST_OUT = _gdi_.COMPOSITION_DEST_OUT
+COMPOSITION_DEST_ATOP = _gdi_.COMPOSITION_DEST_ATOP
+COMPOSITION_XOR = _gdi_.COMPOSITION_XOR
+COMPOSITION_ADD = _gdi_.COMPOSITION_ADD
+class GraphicsObject(_core.Object):
+ """
+ This class is the superclass of native graphics objects like pens
+ etc. It provides the internal reference counting. It is not to be
+ instantiated by user code.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, GraphicsRenderer renderer=None) -> GraphicsObject
+
+ This class is the superclass of native graphics objects like pens
+ etc. It provides the internal reference counting. It is not to be
+ instantiated by user code.
+ """
+ _gdi_.GraphicsObject_swiginit(self,_gdi_.new_GraphicsObject(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_GraphicsObject
+ __del__ = lambda self : None;
+ def IsNull(*args, **kwargs):
+ """
+ IsNull(self) -> bool
+
+ Is this object valid (false) or still empty (true)?
+ """
+ return _gdi_.GraphicsObject_IsNull(*args, **kwargs)
+
+ def GetRenderer(*args, **kwargs):
+ """
+ GetRenderer(self) -> GraphicsRenderer
+
+ Returns the renderer that was used to create this instance, or
+ ``None`` if it has not been initialized yet.
+ """
+ return _gdi_.GraphicsObject_GetRenderer(*args, **kwargs)
+
+_gdi_.GraphicsObject_swigregister(GraphicsObject)
+
+class GraphicsPen(GraphicsObject):
+ """
+ A wx.GraphicsPen is a native representation of a pen. It is used for
+ stroking a path on a `wx.GraphicsContext`. The contents are specific and
+ private to the respective renderer. The only way to get a valid instance
+ is via a CreatePen call on the graphics context or the renderer
+ instance.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> GraphicsPen
+
+ A wx.GraphicsPen is a native representation of a pen. It is used for
+ stroking a path on a `wx.GraphicsContext`. The contents are specific and
+ private to the respective renderer. The only way to get a valid instance
+ is via a CreatePen call on the graphics context or the renderer
+ instance.
+ """
+ _gdi_.GraphicsPen_swiginit(self,_gdi_.new_GraphicsPen(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_GraphicsPen
+ __del__ = lambda self : None;
+_gdi_.GraphicsPen_swigregister(GraphicsPen)
+
+class GraphicsBrush(GraphicsObject):
+ """
+ A wx.GraphicsBrush is a native representation of a brush. It is used
+ for filling a path on a `wx.GraphicsContext`. The contents are
+ specific and private to the respective renderer. The only way to get a
+ valid instance is via a Create...Brush call on the graphics context or
+ the renderer instance.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> GraphicsBrush
+
+ A wx.GraphicsBrush is a native representation of a brush. It is used
+ for filling a path on a `wx.GraphicsContext`. The contents are
+ specific and private to the respective renderer. The only way to get a
+ valid instance is via a Create...Brush call on the graphics context or
+ the renderer instance.
+ """
+ _gdi_.GraphicsBrush_swiginit(self,_gdi_.new_GraphicsBrush(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_GraphicsBrush
+ __del__ = lambda self : None;
+_gdi_.GraphicsBrush_swigregister(GraphicsBrush)
+
+class GraphicsFont(GraphicsObject):
+ """
+ A `wx.GraphicsFont` is a native representation of a font (including
+ text colour). The contents are specific an private to the respective
+ renderer. The only way to get a valid instance is via a CreateFont
+ call on the graphics context or the renderer instance.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> GraphicsFont
+
+ A `wx.GraphicsFont` is a native representation of a font (including
+ text colour). The contents are specific an private to the respective
+ renderer. The only way to get a valid instance is via a CreateFont
+ call on the graphics context or the renderer instance.
+ """
+ _gdi_.GraphicsFont_swiginit(self,_gdi_.new_GraphicsFont(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_GraphicsFont
+ __del__ = lambda self : None;
+_gdi_.GraphicsFont_swigregister(GraphicsFont)
+
+class GraphicsBitmap(GraphicsObject):
+ """Proxy of C++ GraphicsBitmap class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GraphicsBitmap"""
+ _gdi_.GraphicsBitmap_swiginit(self,_gdi_.new_GraphicsBitmap(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_GraphicsBitmap
+ __del__ = lambda self : None;
+_gdi_.GraphicsBitmap_swigregister(GraphicsBitmap)
+
+class GraphicsMatrix(GraphicsObject):
+ """
+ A wx.GraphicsMatrix is a native representation of an affine
+ matrix. The contents are specific and private to the respective
+ renderer. The only way to get a valid instance is via a CreateMatrix
+ call on the graphics context or the renderer instance.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _gdi_.delete_GraphicsMatrix
+ __del__ = lambda self : None;
+ def Concat(*args, **kwargs):
+ """
+ Concat(self, GraphicsMatrix t)
+
+ Concatenates the passed in matrix to the current matrix.
+ """
+ return _gdi_.GraphicsMatrix_Concat(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """
+ Set(self, Double a=1.0, Double b=0.0, Double c=0.0, Double d=1.0,
+ Double tx=0.0, Double ty=0.0)
+
+ Sets the matrix to the specified values (default values are the
+ identity matrix.)
+ """
+ return _gdi_.GraphicsMatrix_Set(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get(self) --> (a, b, c, d, tx, ty)
+
+ Gets the component values of the matrix and returns them as a tuple.
+ """
+ return _gdi_.GraphicsMatrix_Get(*args, **kwargs)
+
+ def Invert(*args, **kwargs):
+ """
+ Invert(self)
+
+ Inverts the matrix.
+ """
+ return _gdi_.GraphicsMatrix_Invert(*args, **kwargs)
+
+ def IsEqual(*args, **kwargs):
+ """
+ IsEqual(self, GraphicsMatrix t) -> bool
+
+ Returns ``True`` if the elements of the transformation matrix are
+ equal
+ """
+ return _gdi_.GraphicsMatrix_IsEqual(*args, **kwargs)
+
+ def IsIdentity(*args, **kwargs):
+ """
+ IsIdentity(self) -> bool
+
+ Returns ``True`` if this is the identity matrix
+ """
+ return _gdi_.GraphicsMatrix_IsIdentity(*args, **kwargs)
+
+ def Translate(*args, **kwargs):
+ """
+ Translate(self, Double dx, Double dy)
+
+ Add a translation to this matrix.
+ """
+ return _gdi_.GraphicsMatrix_Translate(*args, **kwargs)
+
+ def Scale(*args, **kwargs):
+ """
+ Scale(self, Double xScale, Double yScale)
+
+ Scales this matrix.
+ """
+ return _gdi_.GraphicsMatrix_Scale(*args, **kwargs)
+
+ def Rotate(*args, **kwargs):
+ """
+ Rotate(self, Double angle)
+
+ Rotates this matrix. The angle should be specified in radians.
+ """
+ return _gdi_.GraphicsMatrix_Rotate(*args, **kwargs)
+
+ def TransformPoint(*args, **kwargs):
+ """
+ TransformPoint(self, x, y) --> (x, y)
+
+ Applies this matrix to a point, returns the resulting point values
+ """
+ return _gdi_.GraphicsMatrix_TransformPoint(*args, **kwargs)
+
+ def TransformDistance(*args, **kwargs):
+ """
+ TransformDistance(self, dx, dy) --> (dx, dy)
+
+ Applies this matrix to a distance (ie. performs all transforms except
+ translations)
+ """
+ return _gdi_.GraphicsMatrix_TransformDistance(*args, **kwargs)
+
+ def GetNativeMatrix(*args, **kwargs):
+ """
+ GetNativeMatrix(self) -> void
+
+ Returns the native representation of the matrix. For CoreGraphics this
+ is a CFAffineMatrix pointer. For GDIPlus a Matrix Pointer and for
+ Cairo a cairo_matrix_t pointer. NOTE: For wxPython we still need a
+ way to make this value usable.
+ """
+ return _gdi_.GraphicsMatrix_GetNativeMatrix(*args, **kwargs)
+
+_gdi_.GraphicsMatrix_swigregister(GraphicsMatrix)
+
+class GraphicsPath(GraphicsObject):
+ """Proxy of C++ GraphicsPath class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _gdi_.delete_GraphicsPath
+ __del__ = lambda self : None;
+ def MoveToPoint(*args):
+ """
+ MoveToPoint(self, Double x, Double y)
+ MoveToPoint(self, Point2D p)
+
+ Begins a new subpath at the specified point.
+ """
+ return _gdi_.GraphicsPath_MoveToPoint(*args)
+
+ def AddLineToPoint(*args):
+ """
+ AddLineToPoint(self, Double x, Double y)
+ AddLineToPoint(self, Point2D p)
+
+ Adds a straight line from the current point to the specified point.
+ """
+ return _gdi_.GraphicsPath_AddLineToPoint(*args)
+
+ def AddCurveToPoint(*args):
+ """
+ AddCurveToPoint(self, Double cx1, Double cy1, Double cx2, Double cy2, Double x,
+ Double y)
+ AddCurveToPoint(self, Point2D c1, Point2D c2, Point2D e)
+
+ Adds a cubic Bezier curve from the current point, using two control
+ points and an end point
+ """
+ return _gdi_.GraphicsPath_AddCurveToPoint(*args)
+
+ def AddPath(*args, **kwargs):
+ """
+ AddPath(self, GraphicsPath path)
+
+ Adds another path
+ """
+ return _gdi_.GraphicsPath_AddPath(*args, **kwargs)
+
+ def CloseSubpath(*args, **kwargs):
+ """
+ CloseSubpath(self)
+
+ Closes the current sub-path.
+ """
+ return _gdi_.GraphicsPath_CloseSubpath(*args, **kwargs)
+
+ def GetCurrentPoint(*args, **kwargs):
+ """
+ GetCurrentPoint(self) -> Point2D
+
+ Gets the last point of the current path, (0,0) if not yet set
+ """
+ return _gdi_.GraphicsPath_GetCurrentPoint(*args, **kwargs)
+
+ def AddArc(*args):
+ """
+ AddArc(self, Double x, Double y, Double r, Double startAngle, Double endAngle,
+ bool clockwise=True)
+ AddArc(self, Point2D c, Double r, Double startAngle, Double endAngle,
+ bool clockwise=True)
+
+ Adds an arc of a circle centering at (x,y) with radius (r) from
+ startAngle to endAngle
+ """
+ return _gdi_.GraphicsPath_AddArc(*args)
+
+ def AddQuadCurveToPoint(*args, **kwargs):
+ """
+ AddQuadCurveToPoint(self, Double cx, Double cy, Double x, Double y)
+
+ Adds a quadratic Bezier curve from the current point, using a control
+ point and an end point
+ """
+ return _gdi_.GraphicsPath_AddQuadCurveToPoint(*args, **kwargs)
+
+ def AddRectangle(*args, **kwargs):
+ """
+ AddRectangle(self, Double x, Double y, Double w, Double h)
+
+ Appends a rectangle as a new closed subpath.
+ """
+ return _gdi_.GraphicsPath_AddRectangle(*args, **kwargs)
+
+ def AddCircle(*args, **kwargs):
+ """
+ AddCircle(self, Double x, Double y, Double r)
+
+ Appends a circle around (x,y) with radius r as a new closed subpath.
+ """
+ return _gdi_.GraphicsPath_AddCircle(*args, **kwargs)
+
+ def AddArcToPoint(*args, **kwargs):
+ """
+ AddArcToPoint(self, Double x1, Double y1, Double x2, Double y2, Double r)
+
+ Appends an arc to two tangents connecting (current) to (x1,y1) and
+ (x1,y1) to (x2,y2), also a straight line from (current) to (x1,y1)
+ """
+ return _gdi_.GraphicsPath_AddArcToPoint(*args, **kwargs)
+
+ def AddEllipse(*args, **kwargs):
+ """
+ AddEllipse(self, Double x, Double y, Double w, Double h)
+
+ Appends an ellipse fitting into the passed in rectangle.
+ """
+ return _gdi_.GraphicsPath_AddEllipse(*args, **kwargs)
+
+ def AddRoundedRectangle(*args, **kwargs):
+ """
+ AddRoundedRectangle(self, Double x, Double y, Double w, Double h, Double radius)
+
+ Appends a rounded rectangle.
+ """
+ return _gdi_.GraphicsPath_AddRoundedRectangle(*args, **kwargs)
+
+ def GetNativePath(*args, **kwargs):
+ """
+ GetNativePath(self) -> void
+
+ Returns the native path (CGPathRef for Core Graphics, Path pointer for
+ GDIPlus and a cairo_path_t pointer for cairo). NOTE: For wxPython we
+ still need a way to make this value usable.
+ """
+ return _gdi_.GraphicsPath_GetNativePath(*args, **kwargs)
+
+ def UnGetNativePath(*args, **kwargs):
+ """
+ UnGetNativePath(self, void p)
+
+ Gives back the native path returned by GetNativePath() because there
+ might be some deallocations necessary (eg on cairo the native path
+ returned by GetNativePath is newly allocated each time).
+ """
+ return _gdi_.GraphicsPath_UnGetNativePath(*args, **kwargs)
+
+ def Transform(*args, **kwargs):
+ """
+ Transform(self, GraphicsMatrix matrix)
+
+ Transforms each point of this path by the matrix
+ """
+ return _gdi_.GraphicsPath_Transform(*args, **kwargs)
+
+ def GetBox(*args, **kwargs):
+ """
+ GetBox(self) -> Rect2D
+
+ Gets the bounding box enclosing all points (possibly including control
+ points)
+ """
+ return _gdi_.GraphicsPath_GetBox(*args, **kwargs)
+
+ def Contains(*args):
+ """
+ Contains(self, Double x, Double y, int fillStyle=ODDEVEN_RULE) -> bool
+ Contains(self, Point2D c, int fillStyle=ODDEVEN_RULE) -> bool
+
+ Returns ``True`` if the point is within the path.
+ """
+ return _gdi_.GraphicsPath_Contains(*args)
+
+_gdi_.GraphicsPath_swigregister(GraphicsPath)
+
+class GraphicsGradientStop(object):
+ """Proxy of C++ GraphicsGradientStop class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Colour col=wxTransparentColour, float pos=0.0) -> GraphicsGradientStop"""
+ _gdi_.GraphicsGradientStop_swiginit(self,_gdi_.new_GraphicsGradientStop(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_GraphicsGradientStop
+ __del__ = lambda self : None;
+ def GetColour(*args, **kwargs):
+ """GetColour(self) -> Colour"""
+ return _gdi_.GraphicsGradientStop_GetColour(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """SetColour(self, Colour col)"""
+ return _gdi_.GraphicsGradientStop_SetColour(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> float"""
+ return _gdi_.GraphicsGradientStop_GetPosition(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, float pos)"""
+ return _gdi_.GraphicsGradientStop_SetPosition(*args, **kwargs)
+
+ Position = property(GetPosition,SetPosition)
+ Colour = property(GetColour,SetColour)
+_gdi_.GraphicsGradientStop_swigregister(GraphicsGradientStop)
+cvar = _gdi_.cvar
+NullGraphicsPen = cvar.NullGraphicsPen
+NullGraphicsBrush = cvar.NullGraphicsBrush
+NullGraphicsFont = cvar.NullGraphicsFont
+NullGraphicsBitmap = cvar.NullGraphicsBitmap
+NullGraphicsMatrix = cvar.NullGraphicsMatrix
+NullGraphicsPath = cvar.NullGraphicsPath
+
+class GraphicsGradientStops(object):
+ """Proxy of C++ GraphicsGradientStops class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Colour startCol=wxTransparentColour, Colour endCol=wxTransparentColour) -> GraphicsGradientStops"""
+ _gdi_.GraphicsGradientStops_swiginit(self,_gdi_.new_GraphicsGradientStops(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_GraphicsGradientStops
+ __del__ = lambda self : None;
+ def Add(*args):
+ """
+ Add(self, GraphicsGradientStop stop)
+ Add(self, Colour col, float pos)
+ """
+ return _gdi_.GraphicsGradientStops_Add(*args)
+
+ def GetCount(*args, **kwargs):
+ """GetCount(self) -> unsigned int"""
+ return _gdi_.GraphicsGradientStops_GetCount(*args, **kwargs)
+
+ def Item(*args, **kwargs):
+ """Item(self, unsigned int n) -> GraphicsGradientStop"""
+ return _gdi_.GraphicsGradientStops_Item(*args, **kwargs)
+
+ def SetStartColour(*args, **kwargs):
+ """SetStartColour(self, Colour col)"""
+ return _gdi_.GraphicsGradientStops_SetStartColour(*args, **kwargs)
+
+ def GetStartColour(*args, **kwargs):
+ """GetStartColour(self) -> Colour"""
+ return _gdi_.GraphicsGradientStops_GetStartColour(*args, **kwargs)
+
+ def SetEndColour(*args, **kwargs):
+ """SetEndColour(self, Colour col)"""
+ return _gdi_.GraphicsGradientStops_SetEndColour(*args, **kwargs)
+
+ def GetEndColour(*args, **kwargs):
+ """GetEndColour(self) -> Colour"""
+ return _gdi_.GraphicsGradientStops_GetEndColour(*args, **kwargs)
+
+ def __len__(*args, **kwargs):
+ """__len__(self) -> unsigned int"""
+ return _gdi_.GraphicsGradientStops___len__(*args, **kwargs)
+
+ def __getitem__(*args, **kwargs):
+ """__getitem__(self, unsigned int n) -> GraphicsGradientStop"""
+ return _gdi_.GraphicsGradientStops___getitem__(*args, **kwargs)
+
+ Count = property(GetCount)
+ StartColour = property(GetStartColour,SetStartColour)
+ EndColour = property(GetEndColour,SetEndColour)
+_gdi_.GraphicsGradientStops_swigregister(GraphicsGradientStops)
+
+class GraphicsContext(GraphicsObject):
+ """
+ A `wx.GraphicsContext` instance is the object that is drawn upon. It is
+ created by a renderer using the CreateContext calls, this can be done
+ either directly using a renderer instance, or indirectly using the
+ static convenience CreateXXX functions of wx.GraphicsContext that
+ always delegate the task to the default renderer.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _gdi_.delete_GraphicsContext
+ __del__ = lambda self : None;
+ def Create(*args):
+ """
+ Create(WindowDC dc) -> GraphicsContext
+ Create(MemoryDC dc) -> GraphicsContext
+ Create(Window window) -> GraphicsContext
+ Create(PrinterDC dc) -> GraphicsContext
+ Create(MetaFileDC dc) -> GraphicsContext
+ Create(EnhMetaFileDC dc) -> GraphicsContext
+ Create(Image ?) -> GraphicsContext
+
+ Creates a wx.GraphicsContext either from a window or a DC.
+ """
+ val = _gdi_.GraphicsContext_Create(*args)
+ val.__dc = args[0] # save a ref so the dc will not be deleted before self
+ return val
+
+ Create = staticmethod(Create)
+ def CreateMeasuringContext(*args):
+ """
+ CreateMeasuringContext() -> GraphicsContext
+
+ Create a lightwieght context that can be used for measuring text only.
+ """
+ return _gdi_.GraphicsContext_CreateMeasuringContext(*args)
+
+ CreateMeasuringContext = staticmethod(CreateMeasuringContext)
+ def CreateFromNative(*args, **kwargs):
+ """
+ CreateFromNative(void context) -> GraphicsContext
+
+ Creates a wx.GraphicsContext from a native context. This native
+ context must be eg a CGContextRef for Core Graphics, a Graphics
+ pointer for GDIPlus or a cairo_t pointer for Cairo. NOTE: For
+ wxPython we still need a way to make this value usable.
+ """
+ return _gdi_.GraphicsContext_CreateFromNative(*args, **kwargs)
+
+ CreateFromNative = staticmethod(CreateFromNative)
+ def CreateFromNativeWindow(*args, **kwargs):
+ """
+ CreateFromNativeWindow(void window) -> GraphicsContext
+
+ Creates a wx.GraphicsContext from a native window. NOTE: For wxPython
+ we still need a way to make this value usable.
+ """
+ return _gdi_.GraphicsContext_CreateFromNativeWindow(*args, **kwargs)
+
+ CreateFromNativeWindow = staticmethod(CreateFromNativeWindow)
+ def StartDoc(*args, **kwargs):
+ """
+ StartDoc(self, String message) -> bool
+
+ Begin a new document (relevant only for printing / pdf etc) if there
+ is a progress dialog, message will be shown
+ """
+ return _gdi_.GraphicsContext_StartDoc(*args, **kwargs)
+
+ def EndDoc(*args, **kwargs):
+ """
+ EndDoc(self)
+
+ Done with that document (relevant only for printing / pdf etc)
+ """
+ return _gdi_.GraphicsContext_EndDoc(*args, **kwargs)
+
+ def StartPage(*args, **kwargs):
+ """
+ StartPage(self, Double width=0, Double height=0)
+
+ Opens a new page (relevant only for printing / pdf etc) with the given
+ size in points (if both are null the default page size will be used)
+
+ """
+ return _gdi_.GraphicsContext_StartPage(*args, **kwargs)
+
+ def EndPage(*args, **kwargs):
+ """
+ EndPage(self)
+
+ Ends the current page (relevant only for printing / pdf etc)
+ """
+ return _gdi_.GraphicsContext_EndPage(*args, **kwargs)
+
+ def Flush(*args, **kwargs):
+ """
+ Flush(self)
+
+ Make sure that the current content of this context is immediately visible
+ """
+ return _gdi_.GraphicsContext_Flush(*args, **kwargs)
+
+ def CreatePath(*args, **kwargs):
+ """
+ CreatePath(self) -> GraphicsPath
+
+ Creates a native graphics path which is initially empty.
+ """
+ return _gdi_.GraphicsContext_CreatePath(*args, **kwargs)
+
+ def CreatePen(*args, **kwargs):
+ """
+ CreatePen(self, Pen pen) -> GraphicsPen
+
+ Creates a native pen from a `wx.Pen`.
+ """
+ return _gdi_.GraphicsContext_CreatePen(*args, **kwargs)
+
+ def CreateBrush(*args, **kwargs):
+ """
+ CreateBrush(self, Brush brush) -> GraphicsBrush
+
+ Creates a native brush from a `wx.Brush`.
+ """
+ return _gdi_.GraphicsContext_CreateBrush(*args, **kwargs)
+
+ def CreateLinearGradientBrush(*args):
+ """
+ CreateLinearGradientBrush(self, Double x1, Double y1, Double x2, Double y2, Colour c1,
+ Colour c2) -> GraphicsBrush
+ CreateLinearGradientBrush(self, Double x1, Double y1, Double x2, Double y2, GraphicsGradientStops stops) -> GraphicsBrush
+
+ Creates a native brush, having a linear gradient, starting at (x1,y1)
+ to (x2,y2) with the given boundary colors or the specified stops.
+ """
+ return _gdi_.GraphicsContext_CreateLinearGradientBrush(*args)
+
+ def CreateRadialGradientBrush(*args):
+ """
+ CreateRadialGradientBrush(self, Double xo, Double yo, Double xc, Double yc, Double radius,
+ Colour oColor, Colour cColor) -> GraphicsBrush
+ CreateRadialGradientBrush(self, Double xo, Double yo, Double xc, Double yc, Double radius,
+ GraphicsGradientStops stops) -> GraphicsBrush
+
+ Creates a native brush, having a radial gradient originating at point
+ (xo,yo) and ending on a circle around (xc,yc) with the given radius; the colours may be
+ specified by just the two extremes or the full array of gradient stops.
+ """
+ return _gdi_.GraphicsContext_CreateRadialGradientBrush(*args)
+
+ def CreateFont(*args):
+ """
+ CreateFont(self, Font font, Colour col=*wxBLACK) -> GraphicsFont
+ CreateFont(self, double sizeInPixels, String facename, int flags=FONTFLAG_DEFAULT,
+ Colour col=*wxBLACK) -> GraphicsFont
+ """
+ return _gdi_.GraphicsContext_CreateFont(*args)
+
+ def CreateBitmap(*args, **kwargs):
+ """
+ CreateBitmap(self, Bitmap bitmap) -> GraphicsBitmap
+
+ Create a native bitmap representation.
+ """
+ return _gdi_.GraphicsContext_CreateBitmap(*args, **kwargs)
+
+ def CreateBitmapFromImage(*args, **kwargs):
+ """CreateBitmapFromImage(self, Image image) -> GraphicsBitmap"""
+ return _gdi_.GraphicsContext_CreateBitmapFromImage(*args, **kwargs)
+
+ def CreateSubBitmap(*args, **kwargs):
+ """
+ CreateSubBitmap(self, GraphicsBitmap bitmap, Double x, Double y, Double w,
+ Double h) -> GraphicsBitmap
+
+ Create a native bitmap representation using a subset of a wx.Bitmap.
+ """
+ return _gdi_.GraphicsContext_CreateSubBitmap(*args, **kwargs)
+
+ def CreateMatrix(*args, **kwargs):
+ """
+ CreateMatrix(self, Double a=1.0, Double b=0.0, Double c=0.0, Double d=1.0,
+ Double tx=0.0, Double ty=0.0) -> GraphicsMatrix
+
+ Creates a native affine transformation matrix from the passed in
+ values. The defaults result in an identity matrix.
+ """
+ return _gdi_.GraphicsContext_CreateMatrix(*args, **kwargs)
+
+ def PushState(*args, **kwargs):
+ """
+ PushState(self)
+
+ Push the current state of the context, (ie the transformation matrix)
+ on a stack
+ """
+ return _gdi_.GraphicsContext_PushState(*args, **kwargs)
+
+ def PopState(*args, **kwargs):
+ """
+ PopState(self)
+
+ Pops a stored state from the stack
+ """
+ return _gdi_.GraphicsContext_PopState(*args, **kwargs)
+
+ def ClipRegion(*args, **kwargs):
+ """
+ ClipRegion(self, Region region)
+
+ Clips drawings to the region intersected with the current clipping region.
+ """
+ return _gdi_.GraphicsContext_ClipRegion(*args, **kwargs)
+
+ def Clip(*args, **kwargs):
+ """
+ Clip(self, Double x, Double y, Double w, Double h)
+
+ Clips drawings to the rectangle intersected with the current clipping region..
+ """
+ return _gdi_.GraphicsContext_Clip(*args, **kwargs)
+
+ def ResetClip(*args, **kwargs):
+ """
+ ResetClip(self)
+
+ Resets the clipping to original shape.
+ """
+ return _gdi_.GraphicsContext_ResetClip(*args, **kwargs)
+
+ def GetNativeContext(*args, **kwargs):
+ """
+ GetNativeContext(self) -> void
+
+ Returns the native context (CGContextRef for Core Graphics, Graphics
+ pointer for GDIPlus and cairo_t pointer for cairo).
+ """
+ return _gdi_.GraphicsContext_GetNativeContext(*args, **kwargs)
+
+ def GetAntialiasMode(*args, **kwargs):
+ """
+ GetAntialiasMode(self) -> int
+
+ Returns the current shape antialiasing mode
+ """
+ return _gdi_.GraphicsContext_GetAntialiasMode(*args, **kwargs)
+
+ def SetAntialiasMode(*args, **kwargs):
+ """
+ SetAntialiasMode(self, int antialias) -> bool
+
+ Sets the antialiasing mode, returns true if it is supported
+ """
+ return _gdi_.GraphicsContext_SetAntialiasMode(*args, **kwargs)
+
+ def GetInterpolationQuality(*args, **kwargs):
+ """GetInterpolationQuality(self) -> int"""
+ return _gdi_.GraphicsContext_GetInterpolationQuality(*args, **kwargs)
+
+ def SetInterpolationQuality(*args, **kwargs):
+ """SetInterpolationQuality(self, int interpolation) -> bool"""
+ return _gdi_.GraphicsContext_SetInterpolationQuality(*args, **kwargs)
+
+ def GetCompositionMode(*args, **kwargs):
+ """
+ GetCompositionMode(self) -> int
+
+ Returns the current compositing operator
+ """
+ return _gdi_.GraphicsContext_GetCompositionMode(*args, **kwargs)
+
+ def SetCompositionMode(*args, **kwargs):
+ """
+ SetCompositionMode(self, int op) -> bool
+
+ Sets the compositing operator, returns True if it supported
+ """
+ return _gdi_.GraphicsContext_SetCompositionMode(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """
+ GetSize(self) --> (width, height)
+
+ Returns the size of the graphics context in device coordinates
+ """
+ return _gdi_.GraphicsContext_GetSize(*args, **kwargs)
+
+ def GetDPI(*args, **kwargs):
+ """
+ GetDPI(self) --> (dpiX, dpiY)
+
+ Returns the resolution of the graphics context in device points per inch
+ """
+ return _gdi_.GraphicsContext_GetDPI(*args, **kwargs)
+
+ def BeginLayer(*args, **kwargs):
+ """
+ BeginLayer(self, Double opacity)
+
+ all rendering is done into a fully transparent temporary context
+ """
+ return _gdi_.GraphicsContext_BeginLayer(*args, **kwargs)
+
+ def EndLayer(*args, **kwargs):
+ """
+ EndLayer(self)
+
+ composites back the drawings into the context with the opacity given
+ at the BeginLayer call
+ """
+ return _gdi_.GraphicsContext_EndLayer(*args, **kwargs)
+
+ def Translate(*args, **kwargs):
+ """
+ Translate(self, Double dx, Double dy)
+
+ Translates the current transformation matrix.
+ """
+ return _gdi_.GraphicsContext_Translate(*args, **kwargs)
+
+ def Scale(*args, **kwargs):
+ """
+ Scale(self, Double xScale, Double yScale)
+
+ Scale the current transformation matrix of the context.
+ """
+ return _gdi_.GraphicsContext_Scale(*args, **kwargs)
+
+ def Rotate(*args, **kwargs):
+ """
+ Rotate(self, Double angle)
+
+ Rotate the current transformation matrix of the context. ``angle`` is
+ specified in radians.
+ """
+ return _gdi_.GraphicsContext_Rotate(*args, **kwargs)
+
+ def ConcatTransform(*args, **kwargs):
+ """
+ ConcatTransform(self, GraphicsMatrix matrix)
+
+ Concatenates the passed in transform with the current transform of
+ this context.
+ """
+ return _gdi_.GraphicsContext_ConcatTransform(*args, **kwargs)
+
+ def SetTransform(*args, **kwargs):
+ """
+ SetTransform(self, GraphicsMatrix matrix)
+
+ Sets the current transform of this context.
+ """
+ return _gdi_.GraphicsContext_SetTransform(*args, **kwargs)
+
+ def GetTransform(*args, **kwargs):
+ """
+ GetTransform(self) -> GraphicsMatrix
+
+ Gets the current transformation matrix of this context.
+ """
+ return _gdi_.GraphicsContext_GetTransform(*args, **kwargs)
+
+ def SetPen(*args):
+ """
+ SetPen(self, GraphicsPen pen)
+ SetPen(self, Pen pen)
+
+ Sets the stroke pen
+ """
+ return _gdi_.GraphicsContext_SetPen(*args)
+
+ def SetBrush(*args):
+ """
+ SetBrush(self, GraphicsBrush brush)
+ SetBrush(self, Brush brush)
+
+ Sets the brush for filling
+ """
+ return _gdi_.GraphicsContext_SetBrush(*args)
+
+ def SetFont(*args):
+ """
+ SetFont(self, GraphicsFont font)
+ SetFont(self, Font font, Colour colour=*wxBLACK)
+
+ Sets the font
+ """
+ return _gdi_.GraphicsContext_SetFont(*args)
+
+ def StrokePath(*args, **kwargs):
+ """
+ StrokePath(self, GraphicsPath path)
+
+ Strokes along a path with the current pen.
+ """
+ return _gdi_.GraphicsContext_StrokePath(*args, **kwargs)
+
+ def FillPath(*args, **kwargs):
+ """
+ FillPath(self, GraphicsPath path, int fillStyle=ODDEVEN_RULE)
+
+ Fills a path with the current brush.
+ """
+ return _gdi_.GraphicsContext_FillPath(*args, **kwargs)
+
+ def DrawPath(*args, **kwargs):
+ """
+ DrawPath(self, GraphicsPath path, int fillStyle=ODDEVEN_RULE)
+
+ Draws the path by first filling and then stroking.
+ """
+ return _gdi_.GraphicsContext_DrawPath(*args, **kwargs)
+
+ def DrawText(*args, **kwargs):
+ """
+ DrawText(self, String str, Double x, Double y, GraphicsBrush backgroundBrush=NullGraphicsBrush)
+
+ Draws a text string at the defined position.
+ """
+ return _gdi_.GraphicsContext_DrawText(*args, **kwargs)
+
+ def DrawRotatedText(*args, **kwargs):
+ """
+ DrawRotatedText(self, String str, Double x, Double y, Double angle, GraphicsBrush backgroundBrush=NullGraphicsBrush)
+
+ Draws a text string at the defined position, at the specified angle,
+ which is given in radians.
+ """
+ return _gdi_.GraphicsContext_DrawRotatedText(*args, **kwargs)
+
+ def GetFullTextExtent(*args, **kwargs):
+ """
+ GetFullTextExtent(self, text) --> (width, height, descent, externalLeading)
+
+ Gets the dimensions of the string using the currently selected
+ font. ``text`` is the string to measure, ``w`` and ``h`` are the total
+ width and height respectively, ``descent`` is the dimension from the
+ baseline of the font to the bottom of the descender, and
+ ``externalLeading`` is any extra vertical space added to the font by
+ the font designer (usually is zero).
+ """
+ return _gdi_.GraphicsContext_GetFullTextExtent(*args, **kwargs)
+
+ def GetTextExtent(*args, **kwargs):
+ """
+ GetTextExtent(self, text) --> (width, height)
+
+ Gets the dimensions of the string using the currently selected
+ font. ``text`` is the string to measure, ``w`` and ``h`` are the total
+ width and height respectively.
+ """
+ return _gdi_.GraphicsContext_GetTextExtent(*args, **kwargs)
+
+ def GetPartialTextExtents(*args, **kwargs):
+ """
+ GetPartialTextExtents(self, text) -> [widths]
+
+ Returns a list of widths from the beginning of ``text`` to the
+ coresponding character in ``text``.
+ """
+ return _gdi_.GraphicsContext_GetPartialTextExtents(*args, **kwargs)
+
+ def DrawBitmap(*args):
+ """
+ DrawBitmap(self, GraphicsBitmap bmp, Double x, Double y, Double w, Double h)
+ DrawBitmap(self, Bitmap bmp, Double x, Double y, Double w, Double h)
+
+ Draws the bitmap. In case of a mono bitmap, this is treated as a mask
+ and the current brush is used for filling.
+ """
+ return _gdi_.GraphicsContext_DrawBitmap(*args)
+
+ def DrawIcon(*args, **kwargs):
+ """
+ DrawIcon(self, Icon icon, Double x, Double y, Double w, Double h)
+
+ Draws the icon.
+ """
+ return _gdi_.GraphicsContext_DrawIcon(*args, **kwargs)
+
+ def StrokeLine(*args, **kwargs):
+ """
+ StrokeLine(self, Double x1, Double y1, Double x2, Double y2)
+
+ Strokes a single line.
+ """
+ return _gdi_.GraphicsContext_StrokeLine(*args, **kwargs)
+
+ def StrokeLines(*args, **kwargs):
+ """
+ StrokeLines(self, List points)
+
+ Stroke lines connecting each of the points
+ """
+ return _gdi_.GraphicsContext_StrokeLines(*args, **kwargs)
+
+ def StrokeLineSegements(*args, **kwargs):
+ """
+ StrokeLineSegments(self, List beginPoints, List endPoints)
+
+ Stroke disconnected lines from begin to end points
+ """
+ return _gdi_.GraphicsContext_StrokeLineSegements(*args, **kwargs)
+
+ def DrawLines(*args, **kwargs):
+ """
+ DrawLines(self, size_t points, int fillStyle=ODDEVEN_RULE)
+
+ Draws a polygon.
+ """
+ return _gdi_.GraphicsContext_DrawLines(*args, **kwargs)
+
+ def DrawRectangle(*args, **kwargs):
+ """
+ DrawRectangle(self, Double x, Double y, Double w, Double h)
+
+ Draws a rectangle.
+ """
+ return _gdi_.GraphicsContext_DrawRectangle(*args, **kwargs)
+
+ def DrawEllipse(*args, **kwargs):
+ """
+ DrawEllipse(self, Double x, Double y, Double w, Double h)
+
+ Draws an ellipse.
+ """
+ return _gdi_.GraphicsContext_DrawEllipse(*args, **kwargs)
+
+ def DrawRoundedRectangle(*args, **kwargs):
+ """
+ DrawRoundedRectangle(self, Double x, Double y, Double w, Double h, Double radius)
+
+ Draws a rounded rectangle
+ """
+ return _gdi_.GraphicsContext_DrawRoundedRectangle(*args, **kwargs)
+
+ def ShouldOffset(*args, **kwargs):
+ """
+ ShouldOffset(self) -> bool
+
+ helper to determine if a 0.5 offset should be applied for the drawing operation
+ """
+ return _gdi_.GraphicsContext_ShouldOffset(*args, **kwargs)
+
+ def EnableOffset(*args, **kwargs):
+ """EnableOffset(self, bool enable=True)"""
+ return _gdi_.GraphicsContext_EnableOffset(*args, **kwargs)
+
+ def DisableOffset(*args, **kwargs):
+ """DisableOffset(self)"""
+ return _gdi_.GraphicsContext_DisableOffset(*args, **kwargs)
+
+ def OffsetEnabled(*args, **kwargs):
+ """OffsetEnabled(self) -> bool"""
+ return _gdi_.GraphicsContext_OffsetEnabled(*args, **kwargs)
+
+_gdi_.GraphicsContext_swigregister(GraphicsContext)
+
+def GraphicsContext_Create(*args):
+ """
+ Create(WindowDC dc) -> GraphicsContext
+ Create(MemoryDC dc) -> GraphicsContext
+ Create(Window window) -> GraphicsContext
+ Create(PrinterDC dc) -> GraphicsContext
+ Create(MetaFileDC dc) -> GraphicsContext
+ Create(EnhMetaFileDC dc) -> GraphicsContext
+ GraphicsContext_Create(Image ?) -> GraphicsContext
+
+ Creates a wx.GraphicsContext either from a window or a DC.
+ """
+ val = _gdi_.GraphicsContext_Create(*args)
+ val.__dc = args[0] # save a ref so the dc will not be deleted before self
+ return val
+
+def GraphicsContext_CreateMeasuringContext(*args):
+ """
+ GraphicsContext_CreateMeasuringContext() -> GraphicsContext
+
+ Create a lightwieght context that can be used for measuring text only.
+ """
+ return _gdi_.GraphicsContext_CreateMeasuringContext(*args)
+
+def GraphicsContext_CreateFromNative(*args, **kwargs):
+ """
+ GraphicsContext_CreateFromNative(void context) -> GraphicsContext
+
+ Creates a wx.GraphicsContext from a native context. This native
+ context must be eg a CGContextRef for Core Graphics, a Graphics
+ pointer for GDIPlus or a cairo_t pointer for Cairo. NOTE: For
+ wxPython we still need a way to make this value usable.
+ """
+ return _gdi_.GraphicsContext_CreateFromNative(*args, **kwargs)
+
+def GraphicsContext_CreateFromNativeWindow(*args, **kwargs):
+ """
+ GraphicsContext_CreateFromNativeWindow(void window) -> GraphicsContext
+
+ Creates a wx.GraphicsContext from a native window. NOTE: For wxPython
+ we still need a way to make this value usable.
+ """
+ return _gdi_.GraphicsContext_CreateFromNativeWindow(*args, **kwargs)
+
+class GraphicsRenderer(_core.Object):
+ """Proxy of C++ GraphicsRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _gdi_.delete_GraphicsRenderer
+ __del__ = lambda self : None;
+ def GetDefaultRenderer(*args, **kwargs):
+ """GetDefaultRenderer() -> GraphicsRenderer"""
+ return _gdi_.GraphicsRenderer_GetDefaultRenderer(*args, **kwargs)
+
+ GetDefaultRenderer = staticmethod(GetDefaultRenderer)
+ def GetCairoRenderer(*args, **kwargs):
+ """GetCairoRenderer() -> GraphicsRenderer"""
+ return _gdi_.GraphicsRenderer_GetCairoRenderer(*args, **kwargs)
+
+ GetCairoRenderer = staticmethod(GetCairoRenderer)
+ def CreateContext(*args):
+ """
+ CreateContext(self, WindowDC dc) -> GraphicsContext
+ CreateContext(self, MemoryDC dc) -> GraphicsContext
+ CreateContext(self, PrinterDC dc) -> GraphicsContext
+ CreateContext(self, Window window) -> GraphicsContext
+ CreateContext(self, MetaFileDC dc) -> GraphicsContext
+ CreateContext(self, EnhMetaFileDC dc) -> GraphicsContext
+ """
+ return _gdi_.GraphicsRenderer_CreateContext(*args)
+
+ def CreateContextFromImage(*args, **kwargs):
+ """CreateContextFromImage(self, Image image) -> GraphicsContext"""
+ return _gdi_.GraphicsRenderer_CreateContextFromImage(*args, **kwargs)
+
+ def CreateMeasuringContext(*args, **kwargs):
+ """CreateMeasuringContext(self) -> GraphicsContext"""
+ return _gdi_.GraphicsRenderer_CreateMeasuringContext(*args, **kwargs)
+
+ def CreateContextFromNativeContext(*args, **kwargs):
+ """CreateContextFromNativeContext(self, void context) -> GraphicsContext"""
+ return _gdi_.GraphicsRenderer_CreateContextFromNativeContext(*args, **kwargs)
+
+ def CreateContextFromNativeWindow(*args, **kwargs):
+ """CreateContextFromNativeWindow(self, void window) -> GraphicsContext"""
+ return _gdi_.GraphicsRenderer_CreateContextFromNativeWindow(*args, **kwargs)
+
+ def CreatePath(*args, **kwargs):
+ """CreatePath(self) -> GraphicsPath"""
+ return _gdi_.GraphicsRenderer_CreatePath(*args, **kwargs)
+
+ def CreateMatrix(*args, **kwargs):
+ """
+ CreateMatrix(self, Double a=1.0, Double b=0.0, Double c=0.0, Double d=1.0,
+ Double tx=0.0, Double ty=0.0) -> GraphicsMatrix
+ """
+ return _gdi_.GraphicsRenderer_CreateMatrix(*args, **kwargs)
+
+ def CreatePen(*args, **kwargs):
+ """CreatePen(self, Pen pen) -> GraphicsPen"""
+ return _gdi_.GraphicsRenderer_CreatePen(*args, **kwargs)
+
+ def CreateBrush(*args, **kwargs):
+ """CreateBrush(self, Brush brush) -> GraphicsBrush"""
+ return _gdi_.GraphicsRenderer_CreateBrush(*args, **kwargs)
+
+ def CreateLinearGradientBrush(*args, **kwargs):
+ """CreateLinearGradientBrush(self, Double x1, Double y1, Double x2, Double y2, GraphicsGradientStops stops) -> GraphicsBrush"""
+ return _gdi_.GraphicsRenderer_CreateLinearGradientBrush(*args, **kwargs)
+
+ def CreateRadialGradientBrush(*args, **kwargs):
+ """
+ CreateRadialGradientBrush(self, Double xo, Double yo, Double xc, Double yc, Double radius,
+ GraphicsGradientStops stops) -> GraphicsBrush
+ """
+ return _gdi_.GraphicsRenderer_CreateRadialGradientBrush(*args, **kwargs)
+
+ def CreateFont(*args):
+ """
+ CreateFont(self, Font font, Colour col=*wxBLACK) -> GraphicsFont
+ CreateFont(self, double sizeInPixels, String facename, int flags=FONTFLAG_DEFAULT,
+ Colour col=*wxBLACK) -> GraphicsFont
+ """
+ return _gdi_.GraphicsRenderer_CreateFont(*args)
+
+ def CreateBitmap(*args, **kwargs):
+ """CreateBitmap(self, Bitmap bitmap) -> GraphicsBitmap"""
+ return _gdi_.GraphicsRenderer_CreateBitmap(*args, **kwargs)
+
+ def CreateBitmapFromImage(*args, **kwargs):
+ """CreateBitmapFromImage(self, Image image) -> GraphicsBitmap"""
+ return _gdi_.GraphicsRenderer_CreateBitmapFromImage(*args, **kwargs)
+
+ def CreateSubBitmap(*args, **kwargs):
+ """
+ CreateSubBitmap(self, GraphicsBitmap bitmap, Double x, Double y, Double w,
+ Double h) -> GraphicsBitmap
+ """
+ return _gdi_.GraphicsRenderer_CreateSubBitmap(*args, **kwargs)
+
+_gdi_.GraphicsRenderer_swigregister(GraphicsRenderer)
+
+def GraphicsRenderer_GetDefaultRenderer(*args):
+ """GraphicsRenderer_GetDefaultRenderer() -> GraphicsRenderer"""
+ return _gdi_.GraphicsRenderer_GetDefaultRenderer(*args)
+
+def GraphicsRenderer_GetCairoRenderer(*args):
+ """GraphicsRenderer_GetCairoRenderer() -> GraphicsRenderer"""
+ return _gdi_.GraphicsRenderer_GetCairoRenderer(*args)
+
+class GCDC(DC):
+ """Proxy of C++ GCDC class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, WindowDC dc) -> GCDC
+ __init__(self, MemoryDC dc) -> GCDC
+ __init__(self, PrinterDC dc) -> GCDC
+ __init__(self, Window window) -> GCDC
+ __init__(self, GraphicsContext ctx) -> GCDC
+ """
+ _gdi_.GCDC_swiginit(self,_gdi_.new_GCDC(*args))
+ self.__dc = args[0] # save a ref so the other dc will not be deleted before self
+
+ __swig_destroy__ = _gdi_.delete_GCDC
+ __del__ = lambda self : None;
+ def GetGraphicsContext(*args, **kwargs):
+ """GetGraphicsContext(self) -> GraphicsContext"""
+ return _gdi_.GCDC_GetGraphicsContext(*args, **kwargs)
+
+ def SetGraphicsContext(*args, **kwargs):
+ """SetGraphicsContext(self, GraphicsContext ctx)"""
+ return _gdi_.GCDC_SetGraphicsContext(*args, **kwargs)
+
+ GraphicsContext = property(GetGraphicsContext,SetGraphicsContext)
+_gdi_.GCDC_swigregister(GCDC)
+
+class Overlay(object):
+ """Proxy of C++ Overlay class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> Overlay"""
+ _gdi_.Overlay_swiginit(self,_gdi_.new_Overlay(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_Overlay
+ __del__ = lambda self : None;
+ def Reset(*args, **kwargs):
+ """Reset(self)"""
+ return _gdi_.Overlay_Reset(*args, **kwargs)
+
+_gdi_.Overlay_swigregister(Overlay)
+
+class DCOverlay(object):
+ """Proxy of C++ DCOverlay class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, Overlay overlay, DC dc, int x, int y, int width, int height) -> DCOverlay
+ __init__(self, Overlay overlay, DC dc) -> DCOverlay
+ """
+ _gdi_.DCOverlay_swiginit(self,_gdi_.new_DCOverlay(*args))
+ self.__dc = args[1] # save a ref so the dc will not be deleted before self
+
+ __swig_destroy__ = _gdi_.delete_DCOverlay
+ __del__ = lambda self : None;
+ def Clear(*args, **kwargs):
+ """Clear(self)"""
+ return _gdi_.DCOverlay_Clear(*args, **kwargs)
+
+_gdi_.DCOverlay_swigregister(DCOverlay)
+
+#---------------------------------------------------------------------------
+
+IMAGELIST_DRAW_NORMAL = _gdi_.IMAGELIST_DRAW_NORMAL
+IMAGELIST_DRAW_TRANSPARENT = _gdi_.IMAGELIST_DRAW_TRANSPARENT
+IMAGELIST_DRAW_SELECTED = _gdi_.IMAGELIST_DRAW_SELECTED
+IMAGELIST_DRAW_FOCUSED = _gdi_.IMAGELIST_DRAW_FOCUSED
+IMAGE_LIST_NORMAL = _gdi_.IMAGE_LIST_NORMAL
+IMAGE_LIST_SMALL = _gdi_.IMAGE_LIST_SMALL
+IMAGE_LIST_STATE = _gdi_.IMAGE_LIST_STATE
+class ImageList(_core.Object):
+ """Proxy of C++ ImageList class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int width, int height, int mask=True, int initialCount=1) -> ImageList"""
+ _gdi_.ImageList_swiginit(self,_gdi_.new_ImageList(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_ImageList
+ __del__ = lambda self : None;
+ def Add(*args, **kwargs):
+ """Add(self, Bitmap bitmap, Bitmap mask=NullBitmap) -> int"""
+ return _gdi_.ImageList_Add(*args, **kwargs)
+
+ def AddWithColourMask(*args, **kwargs):
+ """AddWithColourMask(self, Bitmap bitmap, Colour maskColour) -> int"""
+ return _gdi_.ImageList_AddWithColourMask(*args, **kwargs)
+
+ def AddIcon(*args, **kwargs):
+ """AddIcon(self, Icon icon) -> int"""
+ return _gdi_.ImageList_AddIcon(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self, int index) -> Bitmap"""
+ return _gdi_.ImageList_GetBitmap(*args, **kwargs)
+
+ def GetIcon(*args, **kwargs):
+ """GetIcon(self, int index) -> Icon"""
+ return _gdi_.ImageList_GetIcon(*args, **kwargs)
+
+ def Replace(*args, **kwargs):
+ """Replace(self, int index, Bitmap bitmap, Bitmap mask=NullBitmap) -> bool"""
+ return _gdi_.ImageList_Replace(*args, **kwargs)
+
+ def Draw(*args, **kwargs):
+ """
+ Draw(self, int index, DC dc, int x, int x, int flags=IMAGELIST_DRAW_NORMAL,
+ bool solidBackground=False) -> bool
+ """
+ return _gdi_.ImageList_Draw(*args, **kwargs)
+
+ def GetImageCount(*args, **kwargs):
+ """GetImageCount(self) -> int"""
+ return _gdi_.ImageList_GetImageCount(*args, **kwargs)
+
+ def Remove(*args, **kwargs):
+ """Remove(self, int index) -> bool"""
+ return _gdi_.ImageList_Remove(*args, **kwargs)
+
+ def RemoveAll(*args, **kwargs):
+ """RemoveAll(self) -> bool"""
+ return _gdi_.ImageList_RemoveAll(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(index) -> (width,height)"""
+ return _gdi_.ImageList_GetSize(*args, **kwargs)
+
+ ImageCount = property(GetImageCount,doc="See `GetImageCount`")
+ Size = property(GetSize,doc="See `GetSize`")
+_gdi_.ImageList_swigregister(ImageList)
+
+#---------------------------------------------------------------------------
+
+class StockGDI(object):
+ """Proxy of C++ StockGDI class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ BRUSH_BLACK = _gdi_.StockGDI_BRUSH_BLACK
+ BRUSH_BLUE = _gdi_.StockGDI_BRUSH_BLUE
+ BRUSH_CYAN = _gdi_.StockGDI_BRUSH_CYAN
+ BRUSH_GREEN = _gdi_.StockGDI_BRUSH_GREEN
+ BRUSH_YELLOW = _gdi_.StockGDI_BRUSH_YELLOW
+ BRUSH_GREY = _gdi_.StockGDI_BRUSH_GREY
+ BRUSH_LIGHTGREY = _gdi_.StockGDI_BRUSH_LIGHTGREY
+ BRUSH_MEDIUMGREY = _gdi_.StockGDI_BRUSH_MEDIUMGREY
+ BRUSH_RED = _gdi_.StockGDI_BRUSH_RED
+ BRUSH_TRANSPARENT = _gdi_.StockGDI_BRUSH_TRANSPARENT
+ BRUSH_WHITE = _gdi_.StockGDI_BRUSH_WHITE
+ COLOUR_BLACK = _gdi_.StockGDI_COLOUR_BLACK
+ COLOUR_BLUE = _gdi_.StockGDI_COLOUR_BLUE
+ COLOUR_CYAN = _gdi_.StockGDI_COLOUR_CYAN
+ COLOUR_GREEN = _gdi_.StockGDI_COLOUR_GREEN
+ COLOUR_YELLOW = _gdi_.StockGDI_COLOUR_YELLOW
+ COLOUR_LIGHTGREY = _gdi_.StockGDI_COLOUR_LIGHTGREY
+ COLOUR_RED = _gdi_.StockGDI_COLOUR_RED
+ COLOUR_WHITE = _gdi_.StockGDI_COLOUR_WHITE
+ CURSOR_CROSS = _gdi_.StockGDI_CURSOR_CROSS
+ CURSOR_HOURGLASS = _gdi_.StockGDI_CURSOR_HOURGLASS
+ CURSOR_STANDARD = _gdi_.StockGDI_CURSOR_STANDARD
+ FONT_ITALIC = _gdi_.StockGDI_FONT_ITALIC
+ FONT_NORMAL = _gdi_.StockGDI_FONT_NORMAL
+ FONT_SMALL = _gdi_.StockGDI_FONT_SMALL
+ FONT_SWISS = _gdi_.StockGDI_FONT_SWISS
+ PEN_BLACK = _gdi_.StockGDI_PEN_BLACK
+ PEN_BLACKDASHED = _gdi_.StockGDI_PEN_BLACKDASHED
+ PEN_BLUE = _gdi_.StockGDI_PEN_BLUE
+ PEN_CYAN = _gdi_.StockGDI_PEN_CYAN
+ PEN_GREEN = _gdi_.StockGDI_PEN_GREEN
+ PEN_YELLOW = _gdi_.StockGDI_PEN_YELLOW
+ PEN_GREY = _gdi_.StockGDI_PEN_GREY
+ PEN_LIGHTGREY = _gdi_.StockGDI_PEN_LIGHTGREY
+ PEN_MEDIUMGREY = _gdi_.StockGDI_PEN_MEDIUMGREY
+ PEN_RED = _gdi_.StockGDI_PEN_RED
+ PEN_TRANSPARENT = _gdi_.StockGDI_PEN_TRANSPARENT
+ PEN_WHITE = _gdi_.StockGDI_PEN_WHITE
+ ITEMCOUNT = _gdi_.StockGDI_ITEMCOUNT
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> StockGDI"""
+ _gdi_.StockGDI_swiginit(self,_gdi_.new_StockGDI(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_StockGDI
+ __del__ = lambda self : None;
+ def DeleteAll(*args, **kwargs):
+ """DeleteAll()"""
+ return _gdi_.StockGDI_DeleteAll(*args, **kwargs)
+
+ DeleteAll = staticmethod(DeleteAll)
+ def instance(*args, **kwargs):
+ """instance() -> StockGDI"""
+ return _gdi_.StockGDI_instance(*args, **kwargs)
+
+ instance = staticmethod(instance)
+ def GetBrush(*args, **kwargs):
+ """GetBrush(int item) -> Brush"""
+ return _gdi_.StockGDI_GetBrush(*args, **kwargs)
+
+ GetBrush = staticmethod(GetBrush)
+ def GetColour(*args, **kwargs):
+ """GetColour(int item) -> Colour"""
+ return _gdi_.StockGDI_GetColour(*args, **kwargs)
+
+ GetColour = staticmethod(GetColour)
+ def GetCursor(*args, **kwargs):
+ """GetCursor(int item) -> Cursor"""
+ return _gdi_.StockGDI_GetCursor(*args, **kwargs)
+
+ GetCursor = staticmethod(GetCursor)
+ def GetPen(*args, **kwargs):
+ """GetPen(int item) -> Pen"""
+ return _gdi_.StockGDI_GetPen(*args, **kwargs)
+
+ GetPen = staticmethod(GetPen)
+ def GetFont(*args, **kwargs):
+ """GetFont(self, int item) -> Font"""
+ return _gdi_.StockGDI_GetFont(*args, **kwargs)
+
+ def _initStockObjects():
+ import wx
+ wx.ITALIC_FONT.this = StockGDI.instance().GetFont(StockGDI.FONT_ITALIC).this
+ wx.NORMAL_FONT.this = StockGDI.instance().GetFont(StockGDI.FONT_NORMAL).this
+ wx.SMALL_FONT.this = StockGDI.instance().GetFont(StockGDI.FONT_SMALL).this
+ wx.SWISS_FONT.this = StockGDI.instance().GetFont(StockGDI.FONT_SWISS).this
+
+ wx.BLACK_DASHED_PEN.this = StockGDI.GetPen(StockGDI.PEN_BLACKDASHED).this
+ wx.BLACK_PEN.this = StockGDI.GetPen(StockGDI.PEN_BLACK).this
+ wx.BLUE_PEN.this = StockGDI.GetPen(StockGDI.PEN_BLUE).this
+ wx.CYAN_PEN.this = StockGDI.GetPen(StockGDI.PEN_CYAN).this
+ wx.GREEN_PEN.this = StockGDI.GetPen(StockGDI.PEN_GREEN).this
+ wx.YELLOW_PEN.this = StockGDI.GetPen(StockGDI.PEN_YELLOW).this
+ wx.GREY_PEN.this = StockGDI.GetPen(StockGDI.PEN_GREY).this
+ wx.LIGHT_GREY_PEN.this = StockGDI.GetPen(StockGDI.PEN_LIGHTGREY).this
+ wx.MEDIUM_GREY_PEN.this = StockGDI.GetPen(StockGDI.PEN_MEDIUMGREY).this
+ wx.RED_PEN.this = StockGDI.GetPen(StockGDI.PEN_RED).this
+ wx.TRANSPARENT_PEN.this = StockGDI.GetPen(StockGDI.PEN_TRANSPARENT).this
+ wx.WHITE_PEN.this = StockGDI.GetPen(StockGDI.PEN_WHITE).this
+
+ wx.BLACK_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_BLACK).this
+ wx.BLUE_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_BLUE).this
+ wx.CYAN_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_CYAN).this
+ wx.GREEN_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_GREEN).this
+ wx.YELLOW_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_YELLOW).this
+ wx.GREY_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_GREY).this
+ wx.LIGHT_GREY_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_LIGHTGREY).this
+ wx.MEDIUM_GREY_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_MEDIUMGREY).this
+ wx.RED_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_RED).this
+ wx.TRANSPARENT_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_TRANSPARENT).this
+ wx.WHITE_BRUSH.this = StockGDI.GetBrush(StockGDI.BRUSH_WHITE).this
+
+ wx.BLACK.this = StockGDI.GetColour(StockGDI.COLOUR_BLACK).this
+ wx.BLUE.this = StockGDI.GetColour(StockGDI.COLOUR_BLUE).this
+ wx.CYAN.this = StockGDI.GetColour(StockGDI.COLOUR_CYAN).this
+ wx.GREEN.this = StockGDI.GetColour(StockGDI.COLOUR_GREEN).this
+ wx.YELLOW.this = StockGDI.GetColour(StockGDI.COLOUR_YELLOW).this
+ wx.LIGHT_GREY.this = StockGDI.GetColour(StockGDI.COLOUR_LIGHTGREY).this
+ wx.RED.this = StockGDI.GetColour(StockGDI.COLOUR_RED).this
+ wx.WHITE.this = StockGDI.GetColour(StockGDI.COLOUR_WHITE).this
+
+ wx.CROSS_CURSOR.this = StockGDI.GetCursor(StockGDI.CURSOR_CROSS).this
+ wx.HOURGLASS_CURSOR.this = StockGDI.GetCursor(StockGDI.CURSOR_HOURGLASS).this
+ wx.STANDARD_CURSOR.this = StockGDI.GetCursor(StockGDI.CURSOR_STANDARD).this
+
+ wx.TheFontList.this = _wxPyInitTheFontList().this
+ wx.ThePenList.this = _wxPyInitThePenList().this
+ wx.TheBrushList.this = _wxPyInitTheBrushList().this
+ wx.TheColourDatabase.this = _wxPyInitTheColourDatabase().this
+
+ _initStockObjects = staticmethod(_initStockObjects)
+
+_gdi_.StockGDI_swigregister(StockGDI)
+
+def StockGDI_DeleteAll(*args):
+ """StockGDI_DeleteAll()"""
+ return _gdi_.StockGDI_DeleteAll(*args)
+
+def StockGDI_instance(*args):
+ """StockGDI_instance() -> StockGDI"""
+ return _gdi_.StockGDI_instance(*args)
+
+def StockGDI_GetBrush(*args, **kwargs):
+ """StockGDI_GetBrush(int item) -> Brush"""
+ return _gdi_.StockGDI_GetBrush(*args, **kwargs)
+
+def StockGDI_GetColour(*args, **kwargs):
+ """StockGDI_GetColour(int item) -> Colour"""
+ return _gdi_.StockGDI_GetColour(*args, **kwargs)
+
+def StockGDI_GetCursor(*args, **kwargs):
+ """StockGDI_GetCursor(int item) -> Cursor"""
+ return _gdi_.StockGDI_GetCursor(*args, **kwargs)
+
+def StockGDI_GetPen(*args, **kwargs):
+ """StockGDI_GetPen(int item) -> Pen"""
+ return _gdi_.StockGDI_GetPen(*args, **kwargs)
+
+# Create an uninitialized instance for the stock objects, they will
+# be initialized later when the wx.App object is created.
+ITALIC_FONT = Font.__new__(Font)
+NORMAL_FONT = Font.__new__(Font)
+SMALL_FONT = Font.__new__(Font)
+SWISS_FONT = Font.__new__(Font)
+
+BLACK_DASHED_PEN = Pen.__new__(Pen)
+BLACK_PEN = Pen.__new__(Pen)
+BLUE_PEN = Pen.__new__(Pen)
+CYAN_PEN = Pen.__new__(Pen)
+GREEN_PEN = Pen.__new__(Pen)
+YELLOW_PEN = Pen.__new__(Pen)
+GREY_PEN = Pen.__new__(Pen)
+LIGHT_GREY_PEN = Pen.__new__(Pen)
+MEDIUM_GREY_PEN = Pen.__new__(Pen)
+RED_PEN = Pen.__new__(Pen)
+TRANSPARENT_PEN = Pen.__new__(Pen)
+WHITE_PEN = Pen.__new__(Pen)
+
+BLACK_BRUSH = Brush.__new__(Brush)
+BLUE_BRUSH = Brush.__new__(Brush)
+CYAN_BRUSH = Brush.__new__(Brush)
+GREEN_BRUSH = Brush.__new__(Brush)
+YELLOW_BRUSH = Brush.__new__(Brush)
+GREY_BRUSH = Brush.__new__(Brush)
+LIGHT_GREY_BRUSH = Brush.__new__(Brush)
+MEDIUM_GREY_BRUSH = Brush.__new__(Brush)
+RED_BRUSH = Brush.__new__(Brush)
+TRANSPARENT_BRUSH = Brush.__new__(Brush)
+WHITE_BRUSH = Brush.__new__(Brush)
+
+BLACK = Colour.__new__(Colour)
+BLUE = Colour.__new__(Colour)
+CYAN = Colour.__new__(Colour)
+GREEN = Colour.__new__(Colour)
+YELLOW = Colour.__new__(Colour)
+LIGHT_GREY = Colour.__new__(Colour)
+RED = Colour.__new__(Colour)
+WHITE = Colour.__new__(Colour)
+
+CROSS_CURSOR = Cursor.__new__(Cursor)
+HOURGLASS_CURSOR = Cursor.__new__(Cursor)
+STANDARD_CURSOR = Cursor.__new__(Cursor)
+
+TransparentColour = Colour(0,0,0,ALPHA_TRANSPARENT)
+
+class GDIObjListBase(object):
+ """Proxy of C++ GDIObjListBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GDIObjListBase"""
+ _gdi_.GDIObjListBase_swiginit(self,_gdi_.new_GDIObjListBase(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_GDIObjListBase
+ __del__ = lambda self : None;
+_gdi_.GDIObjListBase_swigregister(GDIObjListBase)
+NullBitmap = cvar.NullBitmap
+NullIcon = cvar.NullIcon
+NullCursor = cvar.NullCursor
+NullPen = cvar.NullPen
+NullBrush = cvar.NullBrush
+NullPalette = cvar.NullPalette
+NullFont = cvar.NullFont
+NullColour = cvar.NullColour
+NullIconBundle = cvar.NullIconBundle
+
+class PenList(GDIObjListBase):
+ """Proxy of C++ PenList class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def FindOrCreatePen(*args, **kwargs):
+ """FindOrCreatePen(self, Colour colour, int width, int style) -> Pen"""
+ return _gdi_.PenList_FindOrCreatePen(*args, **kwargs)
+
+_gdi_.PenList_swigregister(PenList)
+
+class BrushList(GDIObjListBase):
+ """Proxy of C++ BrushList class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def FindOrCreateBrush(*args, **kwargs):
+ """FindOrCreateBrush(self, Colour colour, int style=SOLID) -> Brush"""
+ return _gdi_.BrushList_FindOrCreateBrush(*args, **kwargs)
+
+_gdi_.BrushList_swigregister(BrushList)
+
+class FontList(GDIObjListBase):
+ """Proxy of C++ FontList class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def FindOrCreateFont(*args, **kwargs):
+ """
+ FindOrCreateFont(self, int point_size, int family, int style, int weight,
+ bool underline=False, String facename=EmptyString,
+ int encoding=FONTENCODING_DEFAULT) -> Font
+ """
+ return _gdi_.FontList_FindOrCreateFont(*args, **kwargs)
+
+_gdi_.FontList_swigregister(FontList)
+
+class ColourDatabase(object):
+ """Proxy of C++ ColourDatabase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> ColourDatabase"""
+ _gdi_.ColourDatabase_swiginit(self,_gdi_.new_ColourDatabase(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_ColourDatabase
+ __del__ = lambda self : None;
+ def Find(*args, **kwargs):
+ """Find(self, String name) -> Colour"""
+ return _gdi_.ColourDatabase_Find(*args, **kwargs)
+
+ def FindName(*args, **kwargs):
+ """FindName(self, Colour colour) -> String"""
+ return _gdi_.ColourDatabase_FindName(*args, **kwargs)
+
+ FindColour = Find
+ def AddColour(*args, **kwargs):
+ """AddColour(self, String name, Colour colour)"""
+ return _gdi_.ColourDatabase_AddColour(*args, **kwargs)
+
+ def Append(*args, **kwargs):
+ """Append(self, String name, int red, int green, int blue)"""
+ return _gdi_.ColourDatabase_Append(*args, **kwargs)
+
+_gdi_.ColourDatabase_swigregister(ColourDatabase)
+
+#---------------------------------------------------------------------------
+
+
+def _wxPyInitTheFontList(*args):
+ """_wxPyInitTheFontList() -> FontList"""
+ return _gdi_._wxPyInitTheFontList(*args)
+
+def _wxPyInitThePenList(*args):
+ """_wxPyInitThePenList() -> PenList"""
+ return _gdi_._wxPyInitThePenList(*args)
+
+def _wxPyInitTheBrushList(*args):
+ """_wxPyInitTheBrushList() -> BrushList"""
+ return _gdi_._wxPyInitTheBrushList(*args)
+
+def _wxPyInitTheColourDatabase(*args):
+ """_wxPyInitTheColourDatabase() -> ColourDatabase"""
+ return _gdi_._wxPyInitTheColourDatabase(*args)
+# Create an uninitialized instance for the stock objects, they will
+# be initialized later when the wx.App object is created.
+TheFontList = FontList.__new__(FontList)
+ThePenList = PenList.__new__(PenList)
+TheBrushList = BrushList.__new__(BrushList)
+TheColourDatabase = ColourDatabase.__new__(ColourDatabase)
+
+#---------------------------------------------------------------------------
+
+CONTROL_DISABLED = _gdi_.CONTROL_DISABLED
+CONTROL_FOCUSED = _gdi_.CONTROL_FOCUSED
+CONTROL_PRESSED = _gdi_.CONTROL_PRESSED
+CONTROL_SPECIAL = _gdi_.CONTROL_SPECIAL
+CONTROL_ISDEFAULT = _gdi_.CONTROL_ISDEFAULT
+CONTROL_ISSUBMENU = _gdi_.CONTROL_ISSUBMENU
+CONTROL_EXPANDED = _gdi_.CONTROL_EXPANDED
+CONTROL_SIZEGRIP = _gdi_.CONTROL_SIZEGRIP
+CONTROL_FLAT = _gdi_.CONTROL_FLAT
+CONTROL_CURRENT = _gdi_.CONTROL_CURRENT
+CONTROL_SELECTED = _gdi_.CONTROL_SELECTED
+CONTROL_CHECKED = _gdi_.CONTROL_CHECKED
+CONTROL_CHECKABLE = _gdi_.CONTROL_CHECKABLE
+CONTROL_UNDETERMINED = _gdi_.CONTROL_UNDETERMINED
+CONTROL_FLAGS_MASK = _gdi_.CONTROL_FLAGS_MASK
+CONTROL_DIRTY = _gdi_.CONTROL_DIRTY
+TITLEBAR_BUTTON_CLOSE = _gdi_.TITLEBAR_BUTTON_CLOSE
+TITLEBAR_BUTTON_MAXIMIZE = _gdi_.TITLEBAR_BUTTON_MAXIMIZE
+TITLEBAR_BUTTON_ICONIZE = _gdi_.TITLEBAR_BUTTON_ICONIZE
+TITLEBAR_BUTTON_RESTORE = _gdi_.TITLEBAR_BUTTON_RESTORE
+TITLEBAR_BUTTON_HELP = _gdi_.TITLEBAR_BUTTON_HELP
+class SplitterRenderParams(object):
+ """
+ This is just a simple struct used as a return value of
+ `wx.RendererNative.GetSplitterParams` and contains some platform
+ specific metrics about splitters.
+
+ * widthSash: the width of the splitter sash.
+ * border: the width of the border of the splitter window.
+ * isHotSensitive: ``True`` if the splitter changes its
+ appearance when the mouse is over it.
+
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int widthSash_, int border_, bool isSens_) -> SplitterRenderParams
+
+ This is just a simple struct used as a return value of
+ `wx.RendererNative.GetSplitterParams` and contains some platform
+ specific metrics about splitters.
+
+ * widthSash: the width of the splitter sash.
+ * border: the width of the border of the splitter window.
+ * isHotSensitive: ``True`` if the splitter changes its
+ appearance when the mouse is over it.
+
+
+ """
+ _gdi_.SplitterRenderParams_swiginit(self,_gdi_.new_SplitterRenderParams(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_SplitterRenderParams
+ __del__ = lambda self : None;
+ widthSash = property(_gdi_.SplitterRenderParams_widthSash_get)
+ border = property(_gdi_.SplitterRenderParams_border_get)
+ isHotSensitive = property(_gdi_.SplitterRenderParams_isHotSensitive_get)
+_gdi_.SplitterRenderParams_swigregister(SplitterRenderParams)
+
+class HeaderButtonParams(object):
+ """Extra (optional) parameters for `wx.RendererNative.DrawHeaderButton`"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> HeaderButtonParams
+
+ Extra (optional) parameters for `wx.RendererNative.DrawHeaderButton`
+ """
+ _gdi_.HeaderButtonParams_swiginit(self,_gdi_.new_HeaderButtonParams(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_HeaderButtonParams
+ __del__ = lambda self : None;
+ m_arrowColour = property(_gdi_.HeaderButtonParams_m_arrowColour_get, _gdi_.HeaderButtonParams_m_arrowColour_set)
+ m_selectionColour = property(_gdi_.HeaderButtonParams_m_selectionColour_get, _gdi_.HeaderButtonParams_m_selectionColour_set)
+ m_labelText = property(_gdi_.HeaderButtonParams_m_labelText_get, _gdi_.HeaderButtonParams_m_labelText_set)
+ m_labelFont = property(_gdi_.HeaderButtonParams_m_labelFont_get, _gdi_.HeaderButtonParams_m_labelFont_set)
+ m_labelColour = property(_gdi_.HeaderButtonParams_m_labelColour_get, _gdi_.HeaderButtonParams_m_labelColour_set)
+ m_labelBitmap = property(_gdi_.HeaderButtonParams_m_labelBitmap_get, _gdi_.HeaderButtonParams_m_labelBitmap_set)
+ m_labelAlignment = property(_gdi_.HeaderButtonParams_m_labelAlignment_get, _gdi_.HeaderButtonParams_m_labelAlignment_set)
+_gdi_.HeaderButtonParams_swigregister(HeaderButtonParams)
+
+HDR_SORT_ICON_NONE = _gdi_.HDR_SORT_ICON_NONE
+HDR_SORT_ICON_UP = _gdi_.HDR_SORT_ICON_UP
+HDR_SORT_ICON_DOWN = _gdi_.HDR_SORT_ICON_DOWN
+class RendererVersion(object):
+ """
+ This simple struct represents the `wx.RendererNative` interface
+ version and is only used as the return value of
+ `wx.RendererNative.GetVersion`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int version_, int age_) -> RendererVersion
+
+ This simple struct represents the `wx.RendererNative` interface
+ version and is only used as the return value of
+ `wx.RendererNative.GetVersion`.
+ """
+ _gdi_.RendererVersion_swiginit(self,_gdi_.new_RendererVersion(*args, **kwargs))
+ __swig_destroy__ = _gdi_.delete_RendererVersion
+ __del__ = lambda self : None;
+ Current_Version = _gdi_.RendererVersion_Current_Version
+ Current_Age = _gdi_.RendererVersion_Current_Age
+ def IsCompatible(*args, **kwargs):
+ """IsCompatible(RendererVersion ver) -> bool"""
+ return _gdi_.RendererVersion_IsCompatible(*args, **kwargs)
+
+ IsCompatible = staticmethod(IsCompatible)
+ version = property(_gdi_.RendererVersion_version_get)
+ age = property(_gdi_.RendererVersion_age_get)
+_gdi_.RendererVersion_swigregister(RendererVersion)
+
+def RendererVersion_IsCompatible(*args, **kwargs):
+ """RendererVersion_IsCompatible(RendererVersion ver) -> bool"""
+ return _gdi_.RendererVersion_IsCompatible(*args, **kwargs)
+
+class RendererNative(object):
+ """
+ One of the design principles of wxWidgets is to use the native
+ widgets on every platform in order to be as close as possible to
+ the native look and feel on every platform. However there are
+ still cases when some generic widgets are needed for various
+ reasons, but it can sometimes take a lot of messy work to make
+ them conform to the native LnF.
+
+ The wx.RendererNative class is a collection of functions that have
+ platform-specific implementations for drawing certain parts of
+ genereic controls in ways that are as close to the native look as
+ possible.
+
+ Note that each drawing function restores the `wx.DC` attributes if it
+ changes them, so it is safe to assume that the same pen, brush and
+ colours that were active before the call to this function are still in
+ effect after it.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def DrawHeaderButton(*args, **kwargs):
+ """
+ DrawHeaderButton(self, Window win, DC dc, Rect rect, int flags=0, int sortArrow=HDR_SORT_ICON_NONE,
+ HeaderButtonParams params=None) -> int
+
+ Draw a header control button (such as what is used by `wx.ListCtrl` in report
+ mode.) The optimal size of the label (text and icons) is returned.
+ """
+ return _gdi_.RendererNative_DrawHeaderButton(*args, **kwargs)
+
+ def DrawHeaderButtonContents(*args, **kwargs):
+ """
+ DrawHeaderButtonContents(self, Window win, DC dc, Rect rect, int flags=0, int sortArrow=HDR_SORT_ICON_NONE,
+ HeaderButtonParams params=None) -> int
+
+ Draw the contents of a header control button, (label, sort
+ arrows, etc.) Normally this is only called by `DrawHeaderButton`.
+ """
+ return _gdi_.RendererNative_DrawHeaderButtonContents(*args, **kwargs)
+
+ def GetHeaderButtonHeight(*args, **kwargs):
+ """
+ GetHeaderButtonHeight(self, Window win) -> int
+
+ Returns the default height of a header button, either a fixed platform
+ height if available, or a generic height based on the window's font.
+ """
+ return _gdi_.RendererNative_GetHeaderButtonHeight(*args, **kwargs)
+
+ def GetHeaderButtonMargin(*args, **kwargs):
+ """GetHeaderButtonMargin(self, Window win) -> int"""
+ return _gdi_.RendererNative_GetHeaderButtonMargin(*args, **kwargs)
+
+ def DrawTreeItemButton(*args, **kwargs):
+ """
+ DrawTreeItemButton(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw the expanded/collapsed icon for a tree control item.
+ """
+ return _gdi_.RendererNative_DrawTreeItemButton(*args, **kwargs)
+
+ def DrawSplitterBorder(*args, **kwargs):
+ """
+ DrawSplitterBorder(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw the border for a sash window: this border must be such that the
+ sash drawn by `DrawSplitterSash` blends into it well.
+ """
+ return _gdi_.RendererNative_DrawSplitterBorder(*args, **kwargs)
+
+ def DrawSplitterSash(*args, **kwargs):
+ """
+ DrawSplitterSash(self, Window win, DC dc, Size size, int position, int orient,
+ int flags=0)
+
+ Draw a sash. The orient parameter defines whether the sash should be
+ vertical or horizontal and how the position should be interpreted.
+ """
+ return _gdi_.RendererNative_DrawSplitterSash(*args, **kwargs)
+
+ def DrawComboBoxDropButton(*args, **kwargs):
+ """
+ DrawComboBoxDropButton(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw a button like the one used by `wx.ComboBox` to show a drop down
+ window. The usual appearance is a downwards pointing arrow.
+
+ The ``flags`` parameter may have the ``wx.CONTROL_PRESSED`` or
+ ``wx.CONTROL_CURRENT`` bits set.
+ """
+ return _gdi_.RendererNative_DrawComboBoxDropButton(*args, **kwargs)
+
+ def DrawDropArrow(*args, **kwargs):
+ """
+ DrawDropArrow(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw a drop down arrow that is suitable for use outside a combo
+ box. Arrow will have a transparent background.
+
+ ``rect`` is not entirely filled by the arrow. Instead, you should use
+ bounding rectangle of a drop down button which arrow matches the size
+ you need. ``flags`` may have the ``wx.CONTROL_PRESSED`` or
+ ``wx.CONTROL_CURRENT`` bit set.
+ """
+ return _gdi_.RendererNative_DrawDropArrow(*args, **kwargs)
+
+ def DrawCheckBox(*args, **kwargs):
+ """
+ DrawCheckBox(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw a check button. Flags may use wx.CONTROL_CHECKED,
+ wx.CONTROL_UNDETERMINED and wx.CONTROL_CURRENT.
+ """
+ return _gdi_.RendererNative_DrawCheckBox(*args, **kwargs)
+
+ def GetCheckBoxSize(*args, **kwargs):
+ """GetCheckBoxSize(self, Window win) -> Size"""
+ return _gdi_.RendererNative_GetCheckBoxSize(*args, **kwargs)
+
+ def DrawPushButton(*args, **kwargs):
+ """
+ DrawPushButton(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw a blank button. Flags may be wx.CONTROL_PRESSED, wx.CONTROL_CURRENT and
+ wx.CONTROL_ISDEFAULT
+ """
+ return _gdi_.RendererNative_DrawPushButton(*args, **kwargs)
+
+ def DrawItemSelectionRect(*args, **kwargs):
+ """
+ DrawItemSelectionRect(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw rectangle indicating that an item in e.g. a list control has been
+ selected or focused
+
+ The flags parameter may be:
+
+ ==================== ============================================
+ wx.CONTROL_SELECTED item is selected, e.g. draw background
+ wx.CONTROL_CURRENT item is the current item, e.g. dotted border
+ wx.CONTROL_FOCUSED the whole control has focus, e.g. blue
+ background vs. grey otherwise
+ ==================== ============================================
+
+ """
+ return _gdi_.RendererNative_DrawItemSelectionRect(*args, **kwargs)
+
+ def DrawFocusRect(*args, **kwargs):
+ """
+ DrawFocusRect(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw the focus rectangle around the label contained in the given rect.
+ Only wxCONTROL_SELECTED makes sense in flags here
+ """
+ return _gdi_.RendererNative_DrawFocusRect(*args, **kwargs)
+
+ def GetSplitterParams(*args, **kwargs):
+ """
+ GetSplitterParams(self, Window win) -> SplitterRenderParams
+
+ Get the splitter parameters, see `wx.SplitterRenderParams`.
+ """
+ return _gdi_.RendererNative_GetSplitterParams(*args, **kwargs)
+
+ def DrawChoice(*args, **kwargs):
+ """
+ DrawChoice(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw a native wxChoice
+ """
+ return _gdi_.RendererNative_DrawChoice(*args, **kwargs)
+
+ def DrawComboBox(*args, **kwargs):
+ """
+ DrawComboBox(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw a native wxComboBox
+ """
+ return _gdi_.RendererNative_DrawComboBox(*args, **kwargs)
+
+ def DrawTextCtrl(*args, **kwargs):
+ """
+ DrawTextCtrl(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw a native wxTextCtrl
+ """
+ return _gdi_.RendererNative_DrawTextCtrl(*args, **kwargs)
+
+ def DrawRadioBitmap(*args, **kwargs):
+ """
+ DrawRadioBitmap(self, Window win, DC dc, Rect rect, int flags=0)
+
+ Draw a native wxRadioButton (just the button image, not the text)
+ """
+ return _gdi_.RendererNative_DrawRadioBitmap(*args, **kwargs)
+
+ DrawRadioButton = wx.deprecated(DrawRadioBitmap,
+ 'DrawRadioButton is deprecated, use `DrawRadioBitmap` instead.')
+
+ def DrawTitleBarBitmap(*args, **kwargs):
+ """
+ DrawTitleBarBitmap(self, Window win, DC dc, Rect rect, int button, int flags=0)
+
+ Draw one of the standard title bar buttons.
+
+ This is currently implemented only for MSW and OS X (for the close
+ button only) because there is no way to render standard title bar
+ buttons under the other platforms, the best can be done is to use
+ normal (only) images which wxArtProvider provides for wxART_HELP and
+ wxART_CLOSE (but not any other title bar buttons)
+ """
+ return _gdi_.RendererNative_DrawTitleBarBitmap(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get() -> RendererNative
+
+ Return the currently used renderer
+ """
+ return _gdi_.RendererNative_Get(*args, **kwargs)
+
+ Get = staticmethod(Get)
+ def GetGeneric(*args, **kwargs):
+ """
+ GetGeneric() -> RendererNative
+
+ Return the generic implementation of the renderer. Under some
+ platforms, this is the default renderer implementation, others have
+ platform-specific default renderer which can be retrieved by calling
+ `wx.RendererNative.GetDefault`.
+ """
+ return _gdi_.RendererNative_GetGeneric(*args, **kwargs)
+
+ GetGeneric = staticmethod(GetGeneric)
+ def GetDefault(*args, **kwargs):
+ """
+ GetDefault() -> RendererNative
+
+ Return the default (native) implementation for this platform -- this
+ is also the one used by default but this may be changed by calling
+ `wx.RendererNative.Set` in which case the return value of this method
+ may be different from the return value of `wx.RendererNative.Get`.
+ """
+ return _gdi_.RendererNative_GetDefault(*args, **kwargs)
+
+ GetDefault = staticmethod(GetDefault)
+ def Set(*args, **kwargs):
+ """
+ Set(RendererNative renderer) -> RendererNative
+
+ Set the renderer to use, passing None reverts to using the default
+ renderer. Returns the previous renderer used with Set or None.
+ """
+ return _gdi_.RendererNative_Set(*args, **kwargs)
+
+ Set = staticmethod(Set)
+ def GetVersion(*args, **kwargs):
+ """
+ GetVersion(self) -> RendererVersion
+
+ Returns the version of the renderer. Will be used for ensuring
+ compatibility of dynamically loaded renderers.
+ """
+ return _gdi_.RendererNative_GetVersion(*args, **kwargs)
+
+ SplitterParams = property(GetSplitterParams,doc="See `GetSplitterParams`")
+ Version = property(GetVersion,doc="See `GetVersion`")
+_gdi_.RendererNative_swigregister(RendererNative)
+
+def RendererNative_Get(*args):
+ """
+ RendererNative_Get() -> RendererNative
+
+ Return the currently used renderer
+ """
+ return _gdi_.RendererNative_Get(*args)
+
+def RendererNative_GetGeneric(*args):
+ """
+ RendererNative_GetGeneric() -> RendererNative
+
+ Return the generic implementation of the renderer. Under some
+ platforms, this is the default renderer implementation, others have
+ platform-specific default renderer which can be retrieved by calling
+ `wx.RendererNative.GetDefault`.
+ """
+ return _gdi_.RendererNative_GetGeneric(*args)
+
+def RendererNative_GetDefault(*args):
+ """
+ RendererNative_GetDefault() -> RendererNative
+
+ Return the default (native) implementation for this platform -- this
+ is also the one used by default but this may be changed by calling
+ `wx.RendererNative.Set` in which case the return value of this method
+ may be different from the return value of `wx.RendererNative.Get`.
+ """
+ return _gdi_.RendererNative_GetDefault(*args)
+
+def RendererNative_Set(*args, **kwargs):
+ """
+ RendererNative_Set(RendererNative renderer) -> RendererNative
+
+ Set the renderer to use, passing None reverts to using the default
+ renderer. Returns the previous renderer used with Set or None.
+ """
+ return _gdi_.RendererNative_Set(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class PseudoDC(_core.Object):
+ """
+ A PseudoDC is an object that can be used as if it were a `wx.DC`. All
+ commands issued to the PseudoDC are stored in a list. You can then
+ play these commands back to a real DC object using the DrawToDC
+ method. Commands in the command list are indexed by ID. You can use
+ this to clear the operations associated with a single ID and then
+ re-draw the object associated with that ID.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PseudoDC
+
+ Constructs a new Pseudo device context for recording dc operations
+ """
+ _gdi_.PseudoDC_swiginit(self,_gdi_.new_PseudoDC(*args, **kwargs))
+ def BeginDrawing(*args, **kwargs):
+ """
+ BeginDrawing(self)
+
+ Allows for optimization of drawing code on platforms that need it. On
+ other platforms this is just an empty function and is harmless. To
+ take advantage of this postential optimization simply enclose each
+ group of calls to the drawing primitives within calls to
+ `BeginDrawing` and `EndDrawing`.
+ """
+ return _gdi_.PseudoDC_BeginDrawing(*args, **kwargs)
+
+ def EndDrawing(*args, **kwargs):
+ """
+ EndDrawing(self)
+
+ Ends the group of drawing primitives started with `BeginDrawing`, and
+ invokes whatever optimization is available for this DC type on the
+ current platform.
+ """
+ return _gdi_.PseudoDC_EndDrawing(*args, **kwargs)
+
+ __swig_destroy__ = _gdi_.delete_PseudoDC
+ __del__ = lambda self : None;
+ def RemoveAll(*args, **kwargs):
+ """
+ RemoveAll(self)
+
+ Removes all objects and operations from the recorded list.
+ """
+ return _gdi_.PseudoDC_RemoveAll(*args, **kwargs)
+
+ def GetLen(*args, **kwargs):
+ """
+ GetLen(self) -> int
+
+ Returns the number of operations in the recorded list.
+ """
+ return _gdi_.PseudoDC_GetLen(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """
+ SetId(self, int id)
+
+ Sets the id to be associated with subsequent operations.
+ """
+ return _gdi_.PseudoDC_SetId(*args, **kwargs)
+
+ def ClearId(*args, **kwargs):
+ """
+ ClearId(self, int id)
+
+ Removes all operations associated with id so the object can be redrawn.
+ """
+ return _gdi_.PseudoDC_ClearId(*args, **kwargs)
+
+ def RemoveId(*args, **kwargs):
+ """
+ RemoveId(self, int id)
+
+ Remove the object node (and all operations) associated with an id.
+ """
+ return _gdi_.PseudoDC_RemoveId(*args, **kwargs)
+
+ def TranslateId(*args, **kwargs):
+ """
+ TranslateId(self, int id, int dx, int dy)
+
+ Translate the operations of id by dx,dy.
+ """
+ return _gdi_.PseudoDC_TranslateId(*args, **kwargs)
+
+ def SetIdGreyedOut(*args, **kwargs):
+ """
+ SetIdGreyedOut(self, int id, bool greyout=True)
+
+ Set whether an object is drawn greyed out or not.
+ """
+ return _gdi_.PseudoDC_SetIdGreyedOut(*args, **kwargs)
+
+ def GetIdGreyedOut(*args, **kwargs):
+ """
+ GetIdGreyedOut(self, int id) -> bool
+
+ Get whether an object is drawn greyed out or not.
+ """
+ return _gdi_.PseudoDC_GetIdGreyedOut(*args, **kwargs)
+
+ def FindObjects(*args, **kwargs):
+ """
+ FindObjects(self, int x, int y, int radius=1, Colour bg=*wxWHITE) -> PyObject
+
+ Returns a list of all the id's that draw a pixel with color
+ not equal to bg within radius of (x,y).
+ Returns an empty list if nothing is found. The list is in
+ reverse drawing order so list[0] is the top id.
+ """
+ return _gdi_.PseudoDC_FindObjects(*args, **kwargs)
+
+ def FindObjectsByBBox(*args, **kwargs):
+ """
+ FindObjectsByBBox(self, int x, int y) -> PyObject
+
+ Returns a list of all the id's whose bounding boxes include (x,y).
+ Returns an empty list if nothing is found. The list is in
+ reverse drawing order so list[0] is the top id.
+ """
+ return _gdi_.PseudoDC_FindObjectsByBBox(*args, **kwargs)
+
+ def DrawIdToDC(*args, **kwargs):
+ """
+ DrawIdToDC(self, int id, DC dc)
+
+ Draw recorded operations of id to dc.
+ """
+ return _gdi_.PseudoDC_DrawIdToDC(*args, **kwargs)
+
+ def SetIdBounds(*args, **kwargs):
+ """
+ SetIdBounds(self, int id, Rect rect)
+
+ Set the bounding rect of a given object. This will create
+ an object node if one doesn't exist.
+ """
+ return _gdi_.PseudoDC_SetIdBounds(*args, **kwargs)
+
+ def GetIdBounds(*args, **kwargs):
+ """
+ GetIdBounds(self, int id) -> Rect
+
+ Returns the bounding rectangle previouly set with SetIdBounds. If
+ no bounds have been set, it returns wx.Rect(0,0,0,0).
+ """
+ return _gdi_.PseudoDC_GetIdBounds(*args, **kwargs)
+
+ def DrawToDCClipped(*args, **kwargs):
+ """
+ DrawToDCClipped(self, DC dc, Rect rect)
+
+ Draws the recorded operations to dc unless the operation is known to
+ be outside rect.
+ """
+ return _gdi_.PseudoDC_DrawToDCClipped(*args, **kwargs)
+
+ def DrawToDCClippedRgn(*args, **kwargs):
+ """
+ DrawToDCClippedRgn(self, DC dc, Region region)
+
+ Draws the recorded operations to dc unless the operation is known to
+ be outside rect.
+ """
+ return _gdi_.PseudoDC_DrawToDCClippedRgn(*args, **kwargs)
+
+ def DrawToDC(*args, **kwargs):
+ """
+ DrawToDC(self, DC dc)
+
+ Draws the recorded operations to dc.
+ """
+ return _gdi_.PseudoDC_DrawToDC(*args, **kwargs)
+
+ def FloodFill(*args, **kwargs):
+ """
+ FloodFill(self, int x, int y, Colour col, int style=FLOOD_SURFACE)
+
+ Flood fills the device context starting from the given point, using
+ the current brush colour, and using a style:
+
+ - **wxFLOOD_SURFACE**: the flooding occurs until a colour other than
+ the given colour is encountered.
+
+ - **wxFLOOD_BORDER**: the area to be flooded is bounded by the given
+ colour.
+
+ Returns False if the operation failed.
+
+ Note: The present implementation for non-Windows platforms may fail to
+ find colour borders if the pixels do not match the colour
+ exactly. However the function will still return true.
+ """
+ return _gdi_.PseudoDC_FloodFill(*args, **kwargs)
+
+ def FloodFillPoint(*args, **kwargs):
+ """
+ FloodFillPoint(self, Point pt, Colour col, int style=FLOOD_SURFACE)
+
+ Flood fills the device context starting from the given point, using
+ the current brush colour, and using a style:
+
+ - **wxFLOOD_SURFACE**: the flooding occurs until a colour other than
+ the given colour is encountered.
+
+ - **wxFLOOD_BORDER**: the area to be flooded is bounded by the given
+ colour.
+
+ Returns False if the operation failed.
+
+ Note: The present implementation for non-Windows platforms may fail to
+ find colour borders if the pixels do not match the colour
+ exactly. However the function will still return true.
+ """
+ return _gdi_.PseudoDC_FloodFillPoint(*args, **kwargs)
+
+ def DrawLine(*args, **kwargs):
+ """
+ DrawLine(self, int x1, int y1, int x2, int y2)
+
+ Draws a line from the first point to the second. The current pen is
+ used for drawing the line. Note that the second point is *not* part of
+ the line and is not drawn by this function (this is consistent with
+ the behaviour of many other toolkits).
+ """
+ return _gdi_.PseudoDC_DrawLine(*args, **kwargs)
+
+ def DrawLinePoint(*args, **kwargs):
+ """
+ DrawLinePoint(self, Point pt1, Point pt2)
+
+ Draws a line from the first point to the second. The current pen is
+ used for drawing the line. Note that the second point is *not* part of
+ the line and is not drawn by this function (this is consistent with
+ the behaviour of many other toolkits).
+ """
+ return _gdi_.PseudoDC_DrawLinePoint(*args, **kwargs)
+
+ def CrossHair(*args, **kwargs):
+ """
+ CrossHair(self, int x, int y)
+
+ Displays a cross hair using the current pen. This is a vertical and
+ horizontal line the height and width of the window, centred on the
+ given point.
+ """
+ return _gdi_.PseudoDC_CrossHair(*args, **kwargs)
+
+ def CrossHairPoint(*args, **kwargs):
+ """
+ CrossHairPoint(self, Point pt)
+
+ Displays a cross hair using the current pen. This is a vertical and
+ horizontal line the height and width of the window, centred on the
+ given point.
+ """
+ return _gdi_.PseudoDC_CrossHairPoint(*args, **kwargs)
+
+ def DrawArc(*args, **kwargs):
+ """
+ DrawArc(self, int x1, int y1, int x2, int y2, int xc, int yc)
+
+ Draws an arc of a circle, centred on the *center* point (xc, yc), from
+ the first point to the second. The current pen is used for the outline
+ and the current brush for filling the shape.
+
+ The arc is drawn in an anticlockwise direction from the start point to
+ the end point.
+ """
+ return _gdi_.PseudoDC_DrawArc(*args, **kwargs)
+
+ def DrawArcPoint(*args, **kwargs):
+ """
+ DrawArcPoint(self, Point pt1, Point pt2, Point center)
+
+ Draws an arc of a circle, centred on the *center* point (xc, yc), from
+ the first point to the second. The current pen is used for the outline
+ and the current brush for filling the shape.
+
+ The arc is drawn in an anticlockwise direction from the start point to
+ the end point.
+ """
+ return _gdi_.PseudoDC_DrawArcPoint(*args, **kwargs)
+
+ def DrawCheckMark(*args, **kwargs):
+ """
+ DrawCheckMark(self, int x, int y, int width, int height)
+
+ Draws a check mark inside the given rectangle.
+ """
+ return _gdi_.PseudoDC_DrawCheckMark(*args, **kwargs)
+
+ def DrawCheckMarkRect(*args, **kwargs):
+ """
+ DrawCheckMarkRect(self, Rect rect)
+
+ Draws a check mark inside the given rectangle.
+ """
+ return _gdi_.PseudoDC_DrawCheckMarkRect(*args, **kwargs)
+
+ def DrawEllipticArc(*args, **kwargs):
+ """
+ DrawEllipticArc(self, int x, int y, int w, int h, double start, double end)
+
+ Draws an arc of an ellipse, with the given rectangle defining the
+ bounds of the ellipse. The current pen is used for drawing the arc and
+ the current brush is used for drawing the pie.
+
+ The *start* and *end* parameters specify the start and end of the arc
+ relative to the three-o'clock position from the center of the
+ rectangle. Angles are specified in degrees (360 is a complete
+ circle). Positive values mean counter-clockwise motion. If start is
+ equal to end, a complete ellipse will be drawn.
+ """
+ return _gdi_.PseudoDC_DrawEllipticArc(*args, **kwargs)
+
+ def DrawEllipticArcPointSize(*args, **kwargs):
+ """
+ DrawEllipticArcPointSize(self, Point pt, Size sz, double start, double end)
+
+ Draws an arc of an ellipse, with the given rectangle defining the
+ bounds of the ellipse. The current pen is used for drawing the arc and
+ the current brush is used for drawing the pie.
+
+ The *start* and *end* parameters specify the start and end of the arc
+ relative to the three-o'clock position from the center of the
+ rectangle. Angles are specified in degrees (360 is a complete
+ circle). Positive values mean counter-clockwise motion. If start is
+ equal to end, a complete ellipse will be drawn.
+ """
+ return _gdi_.PseudoDC_DrawEllipticArcPointSize(*args, **kwargs)
+
+ def DrawPoint(*args, **kwargs):
+ """
+ DrawPoint(self, int x, int y)
+
+ Draws a point using the current pen.
+ """
+ return _gdi_.PseudoDC_DrawPoint(*args, **kwargs)
+
+ def DrawPointPoint(*args, **kwargs):
+ """
+ DrawPointPoint(self, Point pt)
+
+ Draws a point using the current pen.
+ """
+ return _gdi_.PseudoDC_DrawPointPoint(*args, **kwargs)
+
+ def DrawRectangle(*args, **kwargs):
+ """
+ DrawRectangle(self, int x, int y, int width, int height)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The current pen is used for the outline and the current brush
+ for filling the shape.
+ """
+ return _gdi_.PseudoDC_DrawRectangle(*args, **kwargs)
+
+ def DrawRectangleRect(*args, **kwargs):
+ """
+ DrawRectangleRect(self, Rect rect)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The current pen is used for the outline and the current brush
+ for filling the shape.
+ """
+ return _gdi_.PseudoDC_DrawRectangleRect(*args, **kwargs)
+
+ def DrawRectanglePointSize(*args, **kwargs):
+ """
+ DrawRectanglePointSize(self, Point pt, Size sz)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The current pen is used for the outline and the current brush
+ for filling the shape.
+ """
+ return _gdi_.PseudoDC_DrawRectanglePointSize(*args, **kwargs)
+
+ def DrawRoundedRectangle(*args, **kwargs):
+ """
+ DrawRoundedRectangle(self, int x, int y, int width, int height, double radius)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The corners are quarter-circles using the given radius. The
+ current pen is used for the outline and the current brush for filling
+ the shape.
+
+ If radius is positive, the value is assumed to be the radius of the
+ rounded corner. If radius is negative, the absolute value is assumed
+ to be the proportion of the smallest dimension of the rectangle. This
+ means that the corner can be a sensible size relative to the size of
+ the rectangle, and also avoids the strange effects X produces when the
+ corners are too big for the rectangle.
+ """
+ return _gdi_.PseudoDC_DrawRoundedRectangle(*args, **kwargs)
+
+ def DrawRoundedRectangleRect(*args, **kwargs):
+ """
+ DrawRoundedRectangleRect(self, Rect r, double radius)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The corners are quarter-circles using the given radius. The
+ current pen is used for the outline and the current brush for filling
+ the shape.
+
+ If radius is positive, the value is assumed to be the radius of the
+ rounded corner. If radius is negative, the absolute value is assumed
+ to be the proportion of the smallest dimension of the rectangle. This
+ means that the corner can be a sensible size relative to the size of
+ the rectangle, and also avoids the strange effects X produces when the
+ corners are too big for the rectangle.
+ """
+ return _gdi_.PseudoDC_DrawRoundedRectangleRect(*args, **kwargs)
+
+ def DrawRoundedRectanglePointSize(*args, **kwargs):
+ """
+ DrawRoundedRectanglePointSize(self, Point pt, Size sz, double radius)
+
+ Draws a rectangle with the given top left corner, and with the given
+ size. The corners are quarter-circles using the given radius. The
+ current pen is used for the outline and the current brush for filling
+ the shape.
+
+ If radius is positive, the value is assumed to be the radius of the
+ rounded corner. If radius is negative, the absolute value is assumed
+ to be the proportion of the smallest dimension of the rectangle. This
+ means that the corner can be a sensible size relative to the size of
+ the rectangle, and also avoids the strange effects X produces when the
+ corners are too big for the rectangle.
+ """
+ return _gdi_.PseudoDC_DrawRoundedRectanglePointSize(*args, **kwargs)
+
+ def DrawCircle(*args, **kwargs):
+ """
+ DrawCircle(self, int x, int y, int radius)
+
+ Draws a circle with the given center point and radius. The current
+ pen is used for the outline and the current brush for filling the
+ shape.
+ """
+ return _gdi_.PseudoDC_DrawCircle(*args, **kwargs)
+
+ def DrawCirclePoint(*args, **kwargs):
+ """
+ DrawCirclePoint(self, Point pt, int radius)
+
+ Draws a circle with the given center point and radius. The current
+ pen is used for the outline and the current brush for filling the
+ shape.
+ """
+ return _gdi_.PseudoDC_DrawCirclePoint(*args, **kwargs)
+
+ def DrawEllipse(*args, **kwargs):
+ """
+ DrawEllipse(self, int x, int y, int width, int height)
+
+ Draws an ellipse contained in the specified rectangle. The current pen
+ is used for the outline and the current brush for filling the shape.
+ """
+ return _gdi_.PseudoDC_DrawEllipse(*args, **kwargs)
+
+ def DrawEllipseRect(*args, **kwargs):
+ """
+ DrawEllipseRect(self, Rect rect)
+
+ Draws an ellipse contained in the specified rectangle. The current pen
+ is used for the outline and the current brush for filling the shape.
+ """
+ return _gdi_.PseudoDC_DrawEllipseRect(*args, **kwargs)
+
+ def DrawEllipsePointSize(*args, **kwargs):
+ """
+ DrawEllipsePointSize(self, Point pt, Size sz)
+
+ Draws an ellipse contained in the specified rectangle. The current pen
+ is used for the outline and the current brush for filling the shape.
+ """
+ return _gdi_.PseudoDC_DrawEllipsePointSize(*args, **kwargs)
+
+ def DrawIcon(*args, **kwargs):
+ """
+ DrawIcon(self, Icon icon, int x, int y)
+
+ Draw an icon on the display (does nothing if the device context is
+ PostScript). This can be the simplest way of drawing bitmaps on a
+ window.
+ """
+ return _gdi_.PseudoDC_DrawIcon(*args, **kwargs)
+
+ def DrawIconPoint(*args, **kwargs):
+ """
+ DrawIconPoint(self, Icon icon, Point pt)
+
+ Draw an icon on the display (does nothing if the device context is
+ PostScript). This can be the simplest way of drawing bitmaps on a
+ window.
+ """
+ return _gdi_.PseudoDC_DrawIconPoint(*args, **kwargs)
+
+ def DrawBitmap(*args, **kwargs):
+ """
+ DrawBitmap(self, Bitmap bmp, int x, int y, bool useMask=False)
+
+ Draw a bitmap on the device context at the specified point. If
+ *transparent* is true and the bitmap has a transparency mask, (or
+ alpha channel on the platforms that support it) then the bitmap will
+ be drawn transparently.
+ """
+ return _gdi_.PseudoDC_DrawBitmap(*args, **kwargs)
+
+ def DrawBitmapPoint(*args, **kwargs):
+ """
+ DrawBitmapPoint(self, Bitmap bmp, Point pt, bool useMask=False)
+
+ Draw a bitmap on the device context at the specified point. If
+ *transparent* is true and the bitmap has a transparency mask, (or
+ alpha channel on the platforms that support it) then the bitmap will
+ be drawn transparently.
+ """
+ return _gdi_.PseudoDC_DrawBitmapPoint(*args, **kwargs)
+
+ def DrawText(*args, **kwargs):
+ """
+ DrawText(self, String text, int x, int y)
+
+ Draws a text string at the specified point, using the current text
+ font, and the current text foreground and background colours.
+
+ The coordinates refer to the top-left corner of the rectangle bounding
+ the string. See `wx.DC.GetTextExtent` for how to get the dimensions of
+ a text string, which can be used to position the text more precisely,
+ (you will need to use a real DC with GetTextExtent as wx.PseudoDC does
+ not implement it.)
+
+ **NOTE**: under wxGTK the current logical function is used by this
+ function but it is ignored by wxMSW. Thus, you should avoid using
+ logical functions with this function in portable programs.
+ """
+ return _gdi_.PseudoDC_DrawText(*args, **kwargs)
+
+ def DrawTextPoint(*args, **kwargs):
+ """
+ DrawTextPoint(self, String text, Point pt)
+
+ Draws a text string at the specified point, using the current text
+ font, and the current text foreground and background colours.
+
+ The coordinates refer to the top-left corner of the rectangle bounding
+ the string. See `wx.DC.GetTextExtent` for how to get the dimensions of
+ a text string, which can be used to position the text more precisely,
+ (you will need to use a real DC with GetTextExtent as wx.PseudoDC does
+ not implement it.)
+
+ **NOTE**: under wxGTK the current logical function is used by this
+ function but it is ignored by wxMSW. Thus, you should avoid using
+ logical functions with this function in portable programs.
+ """
+ return _gdi_.PseudoDC_DrawTextPoint(*args, **kwargs)
+
+ def DrawRotatedText(*args, **kwargs):
+ """
+ DrawRotatedText(self, String text, int x, int y, double angle)
+
+ Draws the text rotated by *angle* degrees, if supported by the platform.
+
+ **NOTE**: Under Win9x only TrueType fonts can be drawn by this
+ function. In particular, a font different from ``wx.NORMAL_FONT``
+ should be used as the it is not normally a TrueType
+ font. ``wx.SWISS_FONT`` is an example of a font which is.
+ """
+ return _gdi_.PseudoDC_DrawRotatedText(*args, **kwargs)
+
+ def DrawRotatedTextPoint(*args, **kwargs):
+ """
+ DrawRotatedTextPoint(self, String text, Point pt, double angle)
+
+ Draws the text rotated by *angle* degrees, if supported by the platform.
+
+ **NOTE**: Under Win9x only TrueType fonts can be drawn by this
+ function. In particular, a font different from ``wx.NORMAL_FONT``
+ should be used as the it is not normally a TrueType
+ font. ``wx.SWISS_FONT`` is an example of a font which is.
+ """
+ return _gdi_.PseudoDC_DrawRotatedTextPoint(*args, **kwargs)
+
+ def DrawLines(*args, **kwargs):
+ """
+ DrawLines(self, List points, int xoffset=0, int yoffset=0)
+
+ Draws lines using a sequence of `wx.Point` objects, adding the
+ optional offset coordinate. The current pen is used for drawing the
+ lines.
+ """
+ return _gdi_.PseudoDC_DrawLines(*args, **kwargs)
+
+ def DrawPolygon(*args, **kwargs):
+ """
+ DrawPolygon(self, List points, int xoffset=0, int yoffset=0,
+ wxPolygonFillMode fillStyle=ODDEVEN_RULE)
+
+ Draws a filled polygon using a sequence of `wx.Point` objects, adding
+ the optional offset coordinate. The last argument specifies the fill
+ rule: ``wx.ODDEVEN_RULE`` (the default) or ``wx.WINDING_RULE``.
+
+ The current pen is used for drawing the outline, and the current brush
+ for filling the shape. Using a transparent brush suppresses
+ filling. Note that wxWidgets automatically closes the first and last
+ points.
+ """
+ return _gdi_.PseudoDC_DrawPolygon(*args, **kwargs)
+
+ def DrawLabel(*args, **kwargs):
+ """
+ DrawLabel(self, String text, Rect rect, int alignment=wxALIGN_LEFT|wxALIGN_TOP,
+ int indexAccel=-1)
+
+ Draw *text* within the specified rectangle, abiding by the alignment
+ flags. Will additionally emphasize the character at *indexAccel* if
+ it is not -1.
+ """
+ return _gdi_.PseudoDC_DrawLabel(*args, **kwargs)
+
+ def DrawImageLabel(*args, **kwargs):
+ """
+ DrawImageLabel(self, String text, Bitmap image, Rect rect, int alignment=wxALIGN_LEFT|wxALIGN_TOP,
+ int indexAccel=-1)
+
+ Draw *text* and an image (which may be ``wx.NullBitmap`` to skip
+ drawing it) within the specified rectangle, abiding by the alignment
+ flags. Will additionally emphasize the character at *indexAccel* if
+ it is not -1.
+ """
+ return _gdi_.PseudoDC_DrawImageLabel(*args, **kwargs)
+
+ def DrawSpline(*args, **kwargs):
+ """
+ DrawSpline(self, List points)
+
+ Draws a spline between all given control points, (a list of `wx.Point`
+ objects) using the current pen. The spline is drawn using a series of
+ lines, using an algorithm taken from the X drawing program 'XFIG'.
+ """
+ return _gdi_.PseudoDC_DrawSpline(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """
+ Clear(self)
+
+ Clears the device context using the current background brush.
+ """
+ return _gdi_.PseudoDC_Clear(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """
+ SetFont(self, Font font)
+
+ Sets the current font for the DC. It must be a valid font, in
+ particular you should not pass ``wx.NullFont`` to this method.
+ """
+ return _gdi_.PseudoDC_SetFont(*args, **kwargs)
+
+ def SetPen(*args, **kwargs):
+ """
+ SetPen(self, Pen pen)
+
+ Sets the current pen for the DC.
+
+ If the argument is ``wx.NullPen``, the current pen is selected out of the
+ device context, and the original pen restored.
+ """
+ return _gdi_.PseudoDC_SetPen(*args, **kwargs)
+
+ def SetBrush(*args, **kwargs):
+ """
+ SetBrush(self, Brush brush)
+
+ Sets the current brush for the DC.
+
+ If the argument is ``wx.NullBrush``, the current brush is selected out
+ of the device context, and the original brush restored, allowing the
+ current brush to be destroyed safely.
+ """
+ return _gdi_.PseudoDC_SetBrush(*args, **kwargs)
+
+ def SetBackground(*args, **kwargs):
+ """
+ SetBackground(self, Brush brush)
+
+ Sets the current background brush for the DC.
+ """
+ return _gdi_.PseudoDC_SetBackground(*args, **kwargs)
+
+ def SetBackgroundMode(*args, **kwargs):
+ """
+ SetBackgroundMode(self, int mode)
+
+ *mode* may be one of ``wx.SOLID`` and ``wx.TRANSPARENT``. This setting
+ determines whether text will be drawn with a background colour or
+ not.
+ """
+ return _gdi_.PseudoDC_SetBackgroundMode(*args, **kwargs)
+
+ def SetPalette(*args, **kwargs):
+ """
+ SetPalette(self, Palette palette)
+
+ If this is a window DC or memory DC, assigns the given palette to the
+ window or bitmap associated with the DC. If the argument is
+ ``wx.NullPalette``, the current palette is selected out of the device
+ context, and the original palette restored.
+ """
+ return _gdi_.PseudoDC_SetPalette(*args, **kwargs)
+
+ def SetTextForeground(*args, **kwargs):
+ """
+ SetTextForeground(self, Colour colour)
+
+ Sets the current text foreground colour for the DC.
+ """
+ return _gdi_.PseudoDC_SetTextForeground(*args, **kwargs)
+
+ def SetTextBackground(*args, **kwargs):
+ """
+ SetTextBackground(self, Colour colour)
+
+ Sets the current text background colour for the DC.
+ """
+ return _gdi_.PseudoDC_SetTextBackground(*args, **kwargs)
+
+ def SetLogicalFunction(*args, **kwargs):
+ """
+ SetLogicalFunction(self, int function)
+
+ Sets the current logical function for the device context. This
+ determines how a source pixel (from a pen or brush colour, combines
+ with a destination pixel in the current device context.
+
+ The possible values and their meaning in terms of source and
+ destination pixel values are as follows:
+
+ ================ ==========================
+ wx.AND src AND dst
+ wx.AND_INVERT (NOT src) AND dst
+ wx.AND_REVERSE src AND (NOT dst)
+ wx.CLEAR 0
+ wx.COPY src
+ wx.EQUIV (NOT src) XOR dst
+ wx.INVERT NOT dst
+ wx.NAND (NOT src) OR (NOT dst)
+ wx.NOR (NOT src) AND (NOT dst)
+ wx.NO_OP dst
+ wx.OR src OR dst
+ wx.OR_INVERT (NOT src) OR dst
+ wx.OR_REVERSE src OR (NOT dst)
+ wx.SET 1
+ wx.SRC_INVERT NOT src
+ wx.XOR src XOR dst
+ ================ ==========================
+
+ The default is wx.COPY, which simply draws with the current
+ colour. The others combine the current colour and the background using
+ a logical operation. wx.INVERT is commonly used for drawing rubber
+ bands or moving outlines, since drawing twice reverts to the original
+ colour.
+
+ """
+ return _gdi_.PseudoDC_SetLogicalFunction(*args, **kwargs)
+
+ IdBounds = property(GetIdBounds,SetIdBounds,doc="See `GetIdBounds` and `SetIdBounds`")
+ Len = property(GetLen,doc="See `GetLen`")
+_gdi_.PseudoDC_swigregister(PseudoDC)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_gdi_.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_gdi_.pyd
new file mode 100644
index 0000000..f5fe14f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_gdi_.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_gizmos.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_gizmos.pyd
new file mode 100644
index 0000000..c70458f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_gizmos.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_glcanvas.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_glcanvas.pyd
new file mode 100644
index 0000000..bb6907b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_glcanvas.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_grid.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_grid.pyd
new file mode 100644
index 0000000..412e752
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_grid.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_html.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_html.pyd
new file mode 100644
index 0000000..3fe73fd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_html.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_html2.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_html2.pyd
new file mode 100644
index 0000000..c62307d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_html2.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_media.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_media.pyd
new file mode 100644
index 0000000..b9bda88
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_media.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_misc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/_misc.py
new file mode 100644
index 0000000..b5a9bae
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_misc.py
@@ -0,0 +1,7014 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+import _misc_
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+wx = _core
+#---------------------------------------------------------------------------
+
+SYS_OEM_FIXED_FONT = _misc_.SYS_OEM_FIXED_FONT
+SYS_ANSI_FIXED_FONT = _misc_.SYS_ANSI_FIXED_FONT
+SYS_ANSI_VAR_FONT = _misc_.SYS_ANSI_VAR_FONT
+SYS_SYSTEM_FONT = _misc_.SYS_SYSTEM_FONT
+SYS_DEVICE_DEFAULT_FONT = _misc_.SYS_DEVICE_DEFAULT_FONT
+SYS_SYSTEM_FIXED_FONT = _misc_.SYS_SYSTEM_FIXED_FONT
+SYS_DEFAULT_GUI_FONT = _misc_.SYS_DEFAULT_GUI_FONT
+SYS_ICONTITLE_FONT = _misc_.SYS_ICONTITLE_FONT
+SYS_COLOUR_SCROLLBAR = _misc_.SYS_COLOUR_SCROLLBAR
+SYS_COLOUR_BACKGROUND = _misc_.SYS_COLOUR_BACKGROUND
+SYS_COLOUR_ACTIVECAPTION = _misc_.SYS_COLOUR_ACTIVECAPTION
+SYS_COLOUR_INACTIVECAPTION = _misc_.SYS_COLOUR_INACTIVECAPTION
+SYS_COLOUR_MENU = _misc_.SYS_COLOUR_MENU
+SYS_COLOUR_WINDOW = _misc_.SYS_COLOUR_WINDOW
+SYS_COLOUR_WINDOWFRAME = _misc_.SYS_COLOUR_WINDOWFRAME
+SYS_COLOUR_MENUTEXT = _misc_.SYS_COLOUR_MENUTEXT
+SYS_COLOUR_WINDOWTEXT = _misc_.SYS_COLOUR_WINDOWTEXT
+SYS_COLOUR_CAPTIONTEXT = _misc_.SYS_COLOUR_CAPTIONTEXT
+SYS_COLOUR_ACTIVEBORDER = _misc_.SYS_COLOUR_ACTIVEBORDER
+SYS_COLOUR_INACTIVEBORDER = _misc_.SYS_COLOUR_INACTIVEBORDER
+SYS_COLOUR_APPWORKSPACE = _misc_.SYS_COLOUR_APPWORKSPACE
+SYS_COLOUR_HIGHLIGHT = _misc_.SYS_COLOUR_HIGHLIGHT
+SYS_COLOUR_HIGHLIGHTTEXT = _misc_.SYS_COLOUR_HIGHLIGHTTEXT
+SYS_COLOUR_BTNFACE = _misc_.SYS_COLOUR_BTNFACE
+SYS_COLOUR_BTNSHADOW = _misc_.SYS_COLOUR_BTNSHADOW
+SYS_COLOUR_GRAYTEXT = _misc_.SYS_COLOUR_GRAYTEXT
+SYS_COLOUR_BTNTEXT = _misc_.SYS_COLOUR_BTNTEXT
+SYS_COLOUR_INACTIVECAPTIONTEXT = _misc_.SYS_COLOUR_INACTIVECAPTIONTEXT
+SYS_COLOUR_BTNHIGHLIGHT = _misc_.SYS_COLOUR_BTNHIGHLIGHT
+SYS_COLOUR_3DDKSHADOW = _misc_.SYS_COLOUR_3DDKSHADOW
+SYS_COLOUR_3DLIGHT = _misc_.SYS_COLOUR_3DLIGHT
+SYS_COLOUR_INFOTEXT = _misc_.SYS_COLOUR_INFOTEXT
+SYS_COLOUR_INFOBK = _misc_.SYS_COLOUR_INFOBK
+SYS_COLOUR_LISTBOX = _misc_.SYS_COLOUR_LISTBOX
+SYS_COLOUR_HOTLIGHT = _misc_.SYS_COLOUR_HOTLIGHT
+SYS_COLOUR_GRADIENTACTIVECAPTION = _misc_.SYS_COLOUR_GRADIENTACTIVECAPTION
+SYS_COLOUR_GRADIENTINACTIVECAPTION = _misc_.SYS_COLOUR_GRADIENTINACTIVECAPTION
+SYS_COLOUR_MENUHILIGHT = _misc_.SYS_COLOUR_MENUHILIGHT
+SYS_COLOUR_MENUBAR = _misc_.SYS_COLOUR_MENUBAR
+SYS_COLOUR_LISTBOXTEXT = _misc_.SYS_COLOUR_LISTBOXTEXT
+SYS_COLOUR_LISTBOXHIGHLIGHTTEXT = _misc_.SYS_COLOUR_LISTBOXHIGHLIGHTTEXT
+SYS_COLOUR_MAX = _misc_.SYS_COLOUR_MAX
+SYS_COLOUR_DESKTOP = _misc_.SYS_COLOUR_DESKTOP
+SYS_COLOUR_3DFACE = _misc_.SYS_COLOUR_3DFACE
+SYS_COLOUR_3DSHADOW = _misc_.SYS_COLOUR_3DSHADOW
+SYS_COLOUR_BTNHILIGHT = _misc_.SYS_COLOUR_BTNHILIGHT
+SYS_COLOUR_3DHIGHLIGHT = _misc_.SYS_COLOUR_3DHIGHLIGHT
+SYS_COLOUR_3DHILIGHT = _misc_.SYS_COLOUR_3DHILIGHT
+SYS_COLOUR_FRAMEBK = _misc_.SYS_COLOUR_FRAMEBK
+SYS_MOUSE_BUTTONS = _misc_.SYS_MOUSE_BUTTONS
+SYS_BORDER_X = _misc_.SYS_BORDER_X
+SYS_BORDER_Y = _misc_.SYS_BORDER_Y
+SYS_CURSOR_X = _misc_.SYS_CURSOR_X
+SYS_CURSOR_Y = _misc_.SYS_CURSOR_Y
+SYS_DCLICK_X = _misc_.SYS_DCLICK_X
+SYS_DCLICK_Y = _misc_.SYS_DCLICK_Y
+SYS_DRAG_X = _misc_.SYS_DRAG_X
+SYS_DRAG_Y = _misc_.SYS_DRAG_Y
+SYS_EDGE_X = _misc_.SYS_EDGE_X
+SYS_EDGE_Y = _misc_.SYS_EDGE_Y
+SYS_HSCROLL_ARROW_X = _misc_.SYS_HSCROLL_ARROW_X
+SYS_HSCROLL_ARROW_Y = _misc_.SYS_HSCROLL_ARROW_Y
+SYS_HTHUMB_X = _misc_.SYS_HTHUMB_X
+SYS_ICON_X = _misc_.SYS_ICON_X
+SYS_ICON_Y = _misc_.SYS_ICON_Y
+SYS_ICONSPACING_X = _misc_.SYS_ICONSPACING_X
+SYS_ICONSPACING_Y = _misc_.SYS_ICONSPACING_Y
+SYS_WINDOWMIN_X = _misc_.SYS_WINDOWMIN_X
+SYS_WINDOWMIN_Y = _misc_.SYS_WINDOWMIN_Y
+SYS_SCREEN_X = _misc_.SYS_SCREEN_X
+SYS_SCREEN_Y = _misc_.SYS_SCREEN_Y
+SYS_FRAMESIZE_X = _misc_.SYS_FRAMESIZE_X
+SYS_FRAMESIZE_Y = _misc_.SYS_FRAMESIZE_Y
+SYS_SMALLICON_X = _misc_.SYS_SMALLICON_X
+SYS_SMALLICON_Y = _misc_.SYS_SMALLICON_Y
+SYS_HSCROLL_Y = _misc_.SYS_HSCROLL_Y
+SYS_VSCROLL_X = _misc_.SYS_VSCROLL_X
+SYS_VSCROLL_ARROW_X = _misc_.SYS_VSCROLL_ARROW_X
+SYS_VSCROLL_ARROW_Y = _misc_.SYS_VSCROLL_ARROW_Y
+SYS_VTHUMB_Y = _misc_.SYS_VTHUMB_Y
+SYS_CAPTION_Y = _misc_.SYS_CAPTION_Y
+SYS_MENU_Y = _misc_.SYS_MENU_Y
+SYS_NETWORK_PRESENT = _misc_.SYS_NETWORK_PRESENT
+SYS_PENWINDOWS_PRESENT = _misc_.SYS_PENWINDOWS_PRESENT
+SYS_SHOW_SOUNDS = _misc_.SYS_SHOW_SOUNDS
+SYS_SWAP_BUTTONS = _misc_.SYS_SWAP_BUTTONS
+SYS_DCLICK_MSEC = _misc_.SYS_DCLICK_MSEC
+SYS_CAN_DRAW_FRAME_DECORATIONS = _misc_.SYS_CAN_DRAW_FRAME_DECORATIONS
+SYS_CAN_ICONIZE_FRAME = _misc_.SYS_CAN_ICONIZE_FRAME
+SYS_TABLET_PRESENT = _misc_.SYS_TABLET_PRESENT
+SYS_SCREEN_NONE = _misc_.SYS_SCREEN_NONE
+SYS_SCREEN_TINY = _misc_.SYS_SCREEN_TINY
+SYS_SCREEN_PDA = _misc_.SYS_SCREEN_PDA
+SYS_SCREEN_SMALL = _misc_.SYS_SCREEN_SMALL
+SYS_SCREEN_DESKTOP = _misc_.SYS_SCREEN_DESKTOP
+class SystemSettings(object):
+ """Proxy of C++ SystemSettings class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetColour(*args, **kwargs):
+ """GetColour(int index) -> Colour"""
+ return _misc_.SystemSettings_GetColour(*args, **kwargs)
+
+ GetColour = staticmethod(GetColour)
+ def GetFont(*args, **kwargs):
+ """GetFont(int index) -> Font"""
+ return _misc_.SystemSettings_GetFont(*args, **kwargs)
+
+ GetFont = staticmethod(GetFont)
+ def GetMetric(*args, **kwargs):
+ """GetMetric(int index, Window win=None) -> int"""
+ return _misc_.SystemSettings_GetMetric(*args, **kwargs)
+
+ GetMetric = staticmethod(GetMetric)
+ def HasFeature(*args, **kwargs):
+ """HasFeature(int index) -> bool"""
+ return _misc_.SystemSettings_HasFeature(*args, **kwargs)
+
+ HasFeature = staticmethod(HasFeature)
+ def GetScreenType(*args, **kwargs):
+ """GetScreenType() -> int"""
+ return _misc_.SystemSettings_GetScreenType(*args, **kwargs)
+
+ GetScreenType = staticmethod(GetScreenType)
+ def SetScreenType(*args, **kwargs):
+ """SetScreenType(int screen)"""
+ return _misc_.SystemSettings_SetScreenType(*args, **kwargs)
+
+ SetScreenType = staticmethod(SetScreenType)
+_misc_.SystemSettings_swigregister(SystemSettings)
+
+def SystemSettings_GetColour(*args, **kwargs):
+ """SystemSettings_GetColour(int index) -> Colour"""
+ return _misc_.SystemSettings_GetColour(*args, **kwargs)
+
+def SystemSettings_GetFont(*args, **kwargs):
+ """SystemSettings_GetFont(int index) -> Font"""
+ return _misc_.SystemSettings_GetFont(*args, **kwargs)
+
+def SystemSettings_GetMetric(*args, **kwargs):
+ """SystemSettings_GetMetric(int index, Window win=None) -> int"""
+ return _misc_.SystemSettings_GetMetric(*args, **kwargs)
+
+def SystemSettings_HasFeature(*args, **kwargs):
+ """SystemSettings_HasFeature(int index) -> bool"""
+ return _misc_.SystemSettings_HasFeature(*args, **kwargs)
+
+def SystemSettings_GetScreenType(*args):
+ """SystemSettings_GetScreenType() -> int"""
+ return _misc_.SystemSettings_GetScreenType(*args)
+
+def SystemSettings_SetScreenType(*args, **kwargs):
+ """SystemSettings_SetScreenType(int screen)"""
+ return _misc_.SystemSettings_SetScreenType(*args, **kwargs)
+
+class SystemOptions(_core.Object):
+ """Proxy of C++ SystemOptions class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> SystemOptions"""
+ _misc_.SystemOptions_swiginit(self,_misc_.new_SystemOptions(*args, **kwargs))
+ def SetOption(*args, **kwargs):
+ """SetOption(String name, String value)"""
+ return _misc_.SystemOptions_SetOption(*args, **kwargs)
+
+ SetOption = staticmethod(SetOption)
+ def SetOptionInt(*args, **kwargs):
+ """SetOptionInt(String name, int value)"""
+ return _misc_.SystemOptions_SetOptionInt(*args, **kwargs)
+
+ SetOptionInt = staticmethod(SetOptionInt)
+ def GetOption(*args, **kwargs):
+ """GetOption(String name) -> String"""
+ return _misc_.SystemOptions_GetOption(*args, **kwargs)
+
+ GetOption = staticmethod(GetOption)
+ def GetOptionInt(*args, **kwargs):
+ """GetOptionInt(String name) -> int"""
+ return _misc_.SystemOptions_GetOptionInt(*args, **kwargs)
+
+ GetOptionInt = staticmethod(GetOptionInt)
+ def HasOption(*args, **kwargs):
+ """HasOption(String name) -> bool"""
+ return _misc_.SystemOptions_HasOption(*args, **kwargs)
+
+ HasOption = staticmethod(HasOption)
+ def IsFalse(*args, **kwargs):
+ """IsFalse(String name) -> bool"""
+ return _misc_.SystemOptions_IsFalse(*args, **kwargs)
+
+ IsFalse = staticmethod(IsFalse)
+_misc_.SystemOptions_swigregister(SystemOptions)
+cvar = _misc_.cvar
+WINDOW_DEFAULT_VARIANT = cvar.WINDOW_DEFAULT_VARIANT
+
+def SystemOptions_SetOption(*args, **kwargs):
+ """SystemOptions_SetOption(String name, String value)"""
+ return _misc_.SystemOptions_SetOption(*args, **kwargs)
+
+def SystemOptions_SetOptionInt(*args, **kwargs):
+ """SystemOptions_SetOptionInt(String name, int value)"""
+ return _misc_.SystemOptions_SetOptionInt(*args, **kwargs)
+
+def SystemOptions_GetOption(*args, **kwargs):
+ """SystemOptions_GetOption(String name) -> String"""
+ return _misc_.SystemOptions_GetOption(*args, **kwargs)
+
+def SystemOptions_GetOptionInt(*args, **kwargs):
+ """SystemOptions_GetOptionInt(String name) -> int"""
+ return _misc_.SystemOptions_GetOptionInt(*args, **kwargs)
+
+def SystemOptions_HasOption(*args, **kwargs):
+ """SystemOptions_HasOption(String name) -> bool"""
+ return _misc_.SystemOptions_HasOption(*args, **kwargs)
+
+def SystemOptions_IsFalse(*args, **kwargs):
+ """SystemOptions_IsFalse(String name) -> bool"""
+ return _misc_.SystemOptions_IsFalse(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+
+def NewId(*args):
+ """NewId() -> long"""
+ return _misc_.NewId(*args)
+
+def RegisterId(*args, **kwargs):
+ """RegisterId(long id)"""
+ return _misc_.RegisterId(*args, **kwargs)
+
+def GetCurrentId(*args):
+ """GetCurrentId() -> long"""
+ return _misc_.GetCurrentId(*args)
+
+def IsStockID(*args, **kwargs):
+ """IsStockID(int id) -> bool"""
+ return _misc_.IsStockID(*args, **kwargs)
+
+def IsStockLabel(*args, **kwargs):
+ """IsStockLabel(int id, String label) -> bool"""
+ return _misc_.IsStockLabel(*args, **kwargs)
+STOCK_NOFLAGS = _misc_.STOCK_NOFLAGS
+STOCK_WITH_MNEMONIC = _misc_.STOCK_WITH_MNEMONIC
+STOCK_WITH_ACCELERATOR = _misc_.STOCK_WITH_ACCELERATOR
+STOCK_WITHOUT_ELLIPSIS = _misc_.STOCK_WITHOUT_ELLIPSIS
+STOCK_FOR_BUTTON = _misc_.STOCK_FOR_BUTTON
+
+def GetStockLabel(*args, **kwargs):
+ """GetStockLabel(int id, long flags=STOCK_WITH_MNEMONIC) -> String"""
+ return _misc_.GetStockLabel(*args, **kwargs)
+STOCK_MENU = _misc_.STOCK_MENU
+
+def GetStockHelpString(*args, **kwargs):
+ """GetStockHelpString(int id, int client=STOCK_MENU) -> String"""
+ return _misc_.GetStockHelpString(*args, **kwargs)
+
+def Bell(*args):
+ """Bell()"""
+ return _misc_.Bell(*args)
+
+def EndBusyCursor(*args):
+ """EndBusyCursor()"""
+ return _misc_.EndBusyCursor(*args)
+
+def IsBusy(*args):
+ """IsBusy() -> bool"""
+ return _misc_.IsBusy(*args)
+
+def Now(*args):
+ """Now() -> String"""
+ return _misc_.Now(*args)
+
+def Shell(*args, **kwargs):
+ """Shell(String command=EmptyString) -> bool"""
+ return _misc_.Shell(*args, **kwargs)
+
+def GetOsVersion(*args):
+ """GetOsVersion() -> (platform, major, minor)"""
+ return _misc_.GetOsVersion(*args)
+
+def GetOsDescription(*args):
+ """GetOsDescription() -> String"""
+ return _misc_.GetOsDescription(*args)
+
+def IsPlatformLittleEndian(*args):
+ """IsPlatformLittleEndian() -> bool"""
+ return _misc_.IsPlatformLittleEndian(*args)
+
+def IsPlatform64Bit(*args):
+ """IsPlatform64Bit() -> bool"""
+ return _misc_.IsPlatform64Bit(*args)
+
+def GetFreeMemory(*args):
+ """GetFreeMemory() -> wxMemorySize"""
+ return _misc_.GetFreeMemory(*args)
+SHUTDOWN_FORCE = _misc_.SHUTDOWN_FORCE
+SHUTDOWN_POWEROFF = _misc_.SHUTDOWN_POWEROFF
+SHUTDOWN_REBOOT = _misc_.SHUTDOWN_REBOOT
+SHUTDOWN_LOGOFF = _misc_.SHUTDOWN_LOGOFF
+
+def Shutdown(*args, **kwargs):
+ """Shutdown(int wFlags) -> bool"""
+ return _misc_.Shutdown(*args, **kwargs)
+
+def Sleep(*args, **kwargs):
+ """Sleep(int secs)"""
+ return _misc_.Sleep(*args, **kwargs)
+
+def MilliSleep(*args, **kwargs):
+ """MilliSleep(unsigned long milliseconds)"""
+ return _misc_.MilliSleep(*args, **kwargs)
+
+def MicroSleep(*args, **kwargs):
+ """MicroSleep(unsigned long microseconds)"""
+ return _misc_.MicroSleep(*args, **kwargs)
+Usleep = MilliSleep
+
+def EnableTopLevelWindows(*args, **kwargs):
+ """EnableTopLevelWindows(bool enable)"""
+ return _misc_.EnableTopLevelWindows(*args, **kwargs)
+
+def StripMenuCodes(*args, **kwargs):
+ """StripMenuCodes(String in) -> String"""
+ return _misc_.StripMenuCodes(*args, **kwargs)
+
+def GetEmailAddress(*args):
+ """GetEmailAddress() -> String"""
+ return _misc_.GetEmailAddress(*args)
+
+def GetHostName(*args):
+ """GetHostName() -> String"""
+ return _misc_.GetHostName(*args)
+
+def GetFullHostName(*args):
+ """GetFullHostName() -> String"""
+ return _misc_.GetFullHostName(*args)
+
+def GetUserId(*args):
+ """GetUserId() -> String"""
+ return _misc_.GetUserId(*args)
+
+def GetUserName(*args):
+ """GetUserName() -> String"""
+ return _misc_.GetUserName(*args)
+
+def GetHomeDir(*args):
+ """GetHomeDir() -> String"""
+ return _misc_.GetHomeDir(*args)
+
+def GetUserHome(*args, **kwargs):
+ """GetUserHome(String user=EmptyString) -> String"""
+ return _misc_.GetUserHome(*args, **kwargs)
+
+def GetProcessId(*args):
+ """GetProcessId() -> unsigned long"""
+ return _misc_.GetProcessId(*args)
+
+def Trap(*args):
+ """Trap()"""
+ return _misc_.Trap(*args)
+
+def FileSelector(*args, **kwargs):
+ """
+ FileSelector(String message=FileSelectorPromptStr, String default_path=EmptyString,
+ String default_filename=EmptyString,
+ String default_extension=EmptyString,
+ String wildcard=FileSelectorDefaultWildcardStr,
+ int flags=0, Window parent=None, int x=-1,
+ int y=-1) -> String
+ """
+ return _misc_.FileSelector(*args, **kwargs)
+
+def LoadFileSelector(*args, **kwargs):
+ """
+ LoadFileSelector(String what, String extension, String default_name=EmptyString,
+ Window parent=None) -> String
+ """
+ return _misc_.LoadFileSelector(*args, **kwargs)
+
+def SaveFileSelector(*args, **kwargs):
+ """
+ SaveFileSelector(String what, String extension, String default_name=EmptyString,
+ Window parent=None) -> String
+ """
+ return _misc_.SaveFileSelector(*args, **kwargs)
+
+def DirSelector(*args, **kwargs):
+ """
+ DirSelector(String message=DirSelectorPromptStr, String defaultPath=EmptyString,
+ long style=wxDD_DEFAULT_STYLE,
+ Point pos=DefaultPosition, Window parent=None) -> String
+ """
+ return _misc_.DirSelector(*args, **kwargs)
+
+def GetTextFromUser(*args, **kwargs):
+ """
+ GetTextFromUser(String message, String caption=EmptyString, String default_value=EmptyString,
+ Window parent=None,
+ int x=-1, int y=-1, bool centre=True) -> String
+ """
+ return _misc_.GetTextFromUser(*args, **kwargs)
+
+def GetPasswordFromUser(*args, **kwargs):
+ """
+ GetPasswordFromUser(String message, String caption=EmptyString, String default_value=EmptyString,
+ Window parent=None) -> String
+ """
+ return _misc_.GetPasswordFromUser(*args, **kwargs)
+
+def GetSingleChoice(*args, **kwargs):
+ """
+ GetSingleChoice(String message, String caption, int choices, Window parent=None,
+ int x=-1, int y=-1, bool centre=True,
+ int width=150, int height=200) -> String
+ """
+ return _misc_.GetSingleChoice(*args, **kwargs)
+
+def GetSingleChoiceIndex(*args, **kwargs):
+ """
+ GetSingleChoiceIndex(String message, String caption, int choices, Window parent=None,
+ int x=-1, int y=-1, bool centre=True,
+ int width=150, int height=200) -> int
+ """
+ return _misc_.GetSingleChoiceIndex(*args, **kwargs)
+
+def MessageBox(*args, **kwargs):
+ """
+ MessageBox(String message, String caption=EmptyString, int style=wxOK|wxCENTRE,
+ Window parent=None, int x=-1,
+ int y=-1) -> int
+ """
+ return _misc_.MessageBox(*args, **kwargs)
+
+def GetNumberFromUser(*args, **kwargs):
+ """
+ GetNumberFromUser(String message, String prompt, String caption, long value,
+ long min=0, long max=100, Window parent=None,
+ Point pos=DefaultPosition) -> long
+ """
+ return _misc_.GetNumberFromUser(*args, **kwargs)
+
+def ColourDisplay(*args):
+ """ColourDisplay() -> bool"""
+ return _misc_.ColourDisplay(*args)
+
+def DisplayDepth(*args):
+ """DisplayDepth() -> int"""
+ return _misc_.DisplayDepth(*args)
+
+def GetDisplayDepth(*args):
+ """GetDisplayDepth() -> int"""
+ return _misc_.GetDisplayDepth(*args)
+
+def DisplaySize(*args):
+ """DisplaySize() -> (width, height)"""
+ return _misc_.DisplaySize(*args)
+
+def GetDisplaySize(*args):
+ """GetDisplaySize() -> Size"""
+ return _misc_.GetDisplaySize(*args)
+
+def DisplaySizeMM(*args):
+ """DisplaySizeMM() -> (width, height)"""
+ return _misc_.DisplaySizeMM(*args)
+
+def GetDisplaySizeMM(*args):
+ """GetDisplaySizeMM() -> Size"""
+ return _misc_.GetDisplaySizeMM(*args)
+
+def GetDisplayPPI(*args):
+ """GetDisplayPPI() -> Size"""
+ return _misc_.GetDisplayPPI(*args)
+
+def ClientDisplayRect(*args):
+ """ClientDisplayRect() -> (x, y, width, height)"""
+ return _misc_.ClientDisplayRect(*args)
+
+def GetClientDisplayRect(*args):
+ """GetClientDisplayRect() -> Rect"""
+ return _misc_.GetClientDisplayRect(*args)
+
+def SetCursor(*args, **kwargs):
+ """SetCursor(Cursor cursor)"""
+ return _misc_.SetCursor(*args, **kwargs)
+
+def GetXDisplay(*args):
+ """
+ GetXDisplay() -> void
+
+ Returns a swigified pointer to the X11 display. Returns None on
+ other platforms.
+ """
+ return _misc_.GetXDisplay(*args)
+
+def BeginBusyCursor(*args, **kwargs):
+ """BeginBusyCursor(Cursor cursor=wxHOURGLASS_CURSOR)"""
+ return _misc_.BeginBusyCursor(*args, **kwargs)
+
+def GetMousePosition(*args):
+ """
+ GetMousePosition() -> Point
+
+ Get the current mouse position on the screen.
+ """
+ return _misc_.GetMousePosition(*args)
+
+def FindWindowAtPointer(*args):
+ """
+ FindWindowAtPointer() -> Window
+
+ Returns the window currently under the mouse pointer, if it belongs to
+ this application. Otherwise it returns None.
+ """
+ return _misc_.FindWindowAtPointer(*args)
+
+def GetActiveWindow(*args):
+ """
+ GetActiveWindow() -> Window
+
+ Get the currently active window of this application, or None
+ """
+ return _misc_.GetActiveWindow(*args)
+
+def GenericFindWindowAtPoint(*args, **kwargs):
+ """GenericFindWindowAtPoint(Point pt) -> Window"""
+ return _misc_.GenericFindWindowAtPoint(*args, **kwargs)
+
+def FindWindowAtPoint(*args, **kwargs):
+ """FindWindowAtPoint(Point pt) -> Window"""
+ return _misc_.FindWindowAtPoint(*args, **kwargs)
+
+def GetTopLevelParent(*args, **kwargs):
+ """GetTopLevelParent(Window win) -> Window"""
+ return _misc_.GetTopLevelParent(*args, **kwargs)
+BROWSER_NEW_WINDOW = _misc_.BROWSER_NEW_WINDOW
+BROWSER_NOBUSYCURSOR = _misc_.BROWSER_NOBUSYCURSOR
+
+def LaunchDefaultBrowser(*args, **kwargs):
+ """
+ LaunchDefaultBrowser(String url, int flags=0) -> bool
+
+ Launches the user's default browser and tells it to open the location
+ at ``url``. Returns ``True`` if the application was successfully
+ launched.
+ """
+ return _misc_.LaunchDefaultBrowser(*args, **kwargs)
+
+def LaunchDefaultApplication(*args, **kwargs):
+ """
+ LaunchDefaultApplication(String path, int flags=0) -> bool
+
+ Launch document in the user's default application.
+ """
+ return _misc_.LaunchDefaultApplication(*args, **kwargs)
+
+def GetKeyState(*args, **kwargs):
+ """
+ GetKeyState(int key) -> bool
+
+ Get the state of a key (true if pressed or toggled on, false if not.)
+ This is generally most useful getting the state of the modifier or
+ toggle keys. On some platforms those may be the only keys that this
+ function is able to detect.
+
+ """
+ return _misc_.GetKeyState(*args, **kwargs)
+
+def WakeUpMainThread(*args):
+ """WakeUpMainThread()"""
+ return _misc_.WakeUpMainThread(*args)
+
+def MutexGuiEnter(*args):
+ """MutexGuiEnter()"""
+ return _misc_.MutexGuiEnter(*args)
+
+def MutexGuiLeave(*args):
+ """MutexGuiLeave()"""
+ return _misc_.MutexGuiLeave(*args)
+class MutexGuiLocker(object):
+ """Proxy of C++ MutexGuiLocker class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> MutexGuiLocker"""
+ _misc_.MutexGuiLocker_swiginit(self,_misc_.new_MutexGuiLocker(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_MutexGuiLocker
+ __del__ = lambda self : None;
+_misc_.MutexGuiLocker_swigregister(MutexGuiLocker)
+FileSelectorPromptStr = cvar.FileSelectorPromptStr
+FileSelectorDefaultWildcardStr = cvar.FileSelectorDefaultWildcardStr
+DirSelectorPromptStr = cvar.DirSelectorPromptStr
+
+
+def Thread_IsMain(*args):
+ """Thread_IsMain() -> bool"""
+ return _misc_.Thread_IsMain(*args)
+#---------------------------------------------------------------------------
+
+class ToolTip(_core.Object):
+ """Proxy of C++ ToolTip class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String tip) -> ToolTip"""
+ _misc_.ToolTip_swiginit(self,_misc_.new_ToolTip(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_ToolTip
+ __del__ = lambda self : None;
+ def SetTip(*args, **kwargs):
+ """SetTip(self, String tip)"""
+ return _misc_.ToolTip_SetTip(*args, **kwargs)
+
+ def GetTip(*args, **kwargs):
+ """GetTip(self) -> String"""
+ return _misc_.ToolTip_GetTip(*args, **kwargs)
+
+ def GetWindow(*args, **kwargs):
+ """GetWindow(self) -> Window"""
+ return _misc_.ToolTip_GetWindow(*args, **kwargs)
+
+ def Enable(*args, **kwargs):
+ """Enable(bool flag)"""
+ return _misc_.ToolTip_Enable(*args, **kwargs)
+
+ Enable = staticmethod(Enable)
+ def SetDelay(*args, **kwargs):
+ """SetDelay(long milliseconds)"""
+ return _misc_.ToolTip_SetDelay(*args, **kwargs)
+
+ SetDelay = staticmethod(SetDelay)
+ def SetAutoPop(*args, **kwargs):
+ """SetAutoPop(long milliseconds)"""
+ return _misc_.ToolTip_SetAutoPop(*args, **kwargs)
+
+ SetAutoPop = staticmethod(SetAutoPop)
+ def SetReshow(*args, **kwargs):
+ """SetReshow(long milliseconds)"""
+ return _misc_.ToolTip_SetReshow(*args, **kwargs)
+
+ SetReshow = staticmethod(SetReshow)
+ def SetMaxWidth(*args, **kwargs):
+ """SetMaxWidth(int width)"""
+ return _misc_.ToolTip_SetMaxWidth(*args, **kwargs)
+
+ SetMaxWidth = staticmethod(SetMaxWidth)
+ Tip = property(GetTip,SetTip,doc="See `GetTip` and `SetTip`")
+ Window = property(GetWindow,doc="See `GetWindow`")
+_misc_.ToolTip_swigregister(ToolTip)
+
+def ToolTip_Enable(*args, **kwargs):
+ """ToolTip_Enable(bool flag)"""
+ return _misc_.ToolTip_Enable(*args, **kwargs)
+
+def ToolTip_SetDelay(*args, **kwargs):
+ """ToolTip_SetDelay(long milliseconds)"""
+ return _misc_.ToolTip_SetDelay(*args, **kwargs)
+
+def ToolTip_SetAutoPop(*args, **kwargs):
+ """ToolTip_SetAutoPop(long milliseconds)"""
+ return _misc_.ToolTip_SetAutoPop(*args, **kwargs)
+
+def ToolTip_SetReshow(*args, **kwargs):
+ """ToolTip_SetReshow(long milliseconds)"""
+ return _misc_.ToolTip_SetReshow(*args, **kwargs)
+
+def ToolTip_SetMaxWidth(*args, **kwargs):
+ """ToolTip_SetMaxWidth(int width)"""
+ return _misc_.ToolTip_SetMaxWidth(*args, **kwargs)
+
+class Caret(object):
+ """Proxy of C++ Caret class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window window, Size size) -> Caret"""
+ _misc_.Caret_swiginit(self,_misc_.new_Caret(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_Caret
+ __del__ = lambda self : None;
+ def Destroy(*args, **kwargs):
+ """
+ Destroy(self)
+
+ Deletes the C++ object this Python object is a proxy for.
+ """
+ args[0].this.own(False)
+ return _misc_.Caret_Destroy(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _misc_.Caret_IsOk(*args, **kwargs)
+
+ def IsVisible(*args, **kwargs):
+ """IsVisible(self) -> bool"""
+ return _misc_.Caret_IsVisible(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point"""
+ return _misc_.Caret_GetPosition(*args, **kwargs)
+
+ def GetPositionTuple(*args, **kwargs):
+ """GetPositionTuple() -> (x,y)"""
+ return _misc_.Caret_GetPositionTuple(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(self) -> Size"""
+ return _misc_.Caret_GetSize(*args, **kwargs)
+
+ def GetSizeTuple(*args, **kwargs):
+ """GetSizeTuple() -> (width, height)"""
+ return _misc_.Caret_GetSizeTuple(*args, **kwargs)
+
+ def GetWindow(*args, **kwargs):
+ """GetWindow(self) -> Window"""
+ return _misc_.Caret_GetWindow(*args, **kwargs)
+
+ def MoveXY(*args, **kwargs):
+ """MoveXY(self, int x, int y)"""
+ return _misc_.Caret_MoveXY(*args, **kwargs)
+
+ def Move(*args, **kwargs):
+ """Move(self, Point pt)"""
+ return _misc_.Caret_Move(*args, **kwargs)
+
+ def SetSizeWH(*args, **kwargs):
+ """SetSizeWH(self, int width, int height)"""
+ return _misc_.Caret_SetSizeWH(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, Size size)"""
+ return _misc_.Caret_SetSize(*args, **kwargs)
+
+ def Show(*args, **kwargs):
+ """Show(self, int show=True)"""
+ return _misc_.Caret_Show(*args, **kwargs)
+
+ def Hide(*args, **kwargs):
+ """Hide(self)"""
+ return _misc_.Caret_Hide(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def GetBlinkTime(*args, **kwargs):
+ """GetBlinkTime() -> int"""
+ return _misc_.Caret_GetBlinkTime(*args, **kwargs)
+
+ GetBlinkTime = staticmethod(GetBlinkTime)
+ def SetBlinkTime(*args, **kwargs):
+ """SetBlinkTime(int milliseconds)"""
+ return _misc_.Caret_SetBlinkTime(*args, **kwargs)
+
+ SetBlinkTime = staticmethod(SetBlinkTime)
+ Position = property(GetPosition,doc="See `GetPosition`")
+ Size = property(GetSize,SetSize,doc="See `GetSize` and `SetSize`")
+ Window = property(GetWindow,doc="See `GetWindow`")
+_misc_.Caret_swigregister(Caret)
+
+def Caret_GetBlinkTime(*args):
+ """Caret_GetBlinkTime() -> int"""
+ return _misc_.Caret_GetBlinkTime(*args)
+
+def Caret_SetBlinkTime(*args, **kwargs):
+ """Caret_SetBlinkTime(int milliseconds)"""
+ return _misc_.Caret_SetBlinkTime(*args, **kwargs)
+
+class BusyCursor(object):
+ """Proxy of C++ BusyCursor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Cursor cursor=wxHOURGLASS_CURSOR) -> BusyCursor"""
+ _misc_.BusyCursor_swiginit(self,_misc_.new_BusyCursor(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_BusyCursor
+ __del__ = lambda self : None;
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_misc_.BusyCursor_swigregister(BusyCursor)
+
+class WindowDisabler(object):
+ """Proxy of C++ WindowDisabler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, bool disable=True) -> WindowDisabler
+ __init__(self, Window winToSkip) -> WindowDisabler
+ """
+ _misc_.WindowDisabler_swiginit(self,_misc_.new_WindowDisabler(*args))
+ __swig_destroy__ = _misc_.delete_WindowDisabler
+ __del__ = lambda self : None;
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_misc_.WindowDisabler_swigregister(WindowDisabler)
+
+class BusyInfo(_core.Object):
+ """Proxy of C++ BusyInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String message, Window parent=None) -> BusyInfo"""
+ _misc_.BusyInfo_swiginit(self,_misc_.new_BusyInfo(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_BusyInfo
+ __del__ = lambda self : None;
+ def Destroy(self): pass
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_misc_.BusyInfo_swigregister(BusyInfo)
+
+class StopWatch(object):
+ """Proxy of C++ StopWatch class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> StopWatch"""
+ _misc_.StopWatch_swiginit(self,_misc_.new_StopWatch(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_StopWatch
+ __del__ = lambda self : None;
+ def Start(*args, **kwargs):
+ """Start(self, long t0=0)"""
+ return _misc_.StopWatch_Start(*args, **kwargs)
+
+ def Pause(*args, **kwargs):
+ """Pause(self)"""
+ return _misc_.StopWatch_Pause(*args, **kwargs)
+
+ def Resume(*args, **kwargs):
+ """Resume(self)"""
+ return _misc_.StopWatch_Resume(*args, **kwargs)
+
+ def TimeInMicro(*args, **kwargs):
+ """TimeInMicro(self) -> wxLongLong"""
+ return _misc_.StopWatch_TimeInMicro(*args, **kwargs)
+
+ def Time(*args, **kwargs):
+ """Time(self) -> long"""
+ return _misc_.StopWatch_Time(*args, **kwargs)
+
+_misc_.StopWatch_swigregister(StopWatch)
+
+class FileHistory(_core.Object):
+ """Proxy of C++ FileHistory class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int maxFiles=9, int idBase=ID_FILE1) -> FileHistory"""
+ _misc_.FileHistory_swiginit(self,_misc_.new_FileHistory(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_FileHistory
+ __del__ = lambda self : None;
+ def AddFileToHistory(*args, **kwargs):
+ """AddFileToHistory(self, String file)"""
+ return _misc_.FileHistory_AddFileToHistory(*args, **kwargs)
+
+ def RemoveFileFromHistory(*args, **kwargs):
+ """RemoveFileFromHistory(self, int i)"""
+ return _misc_.FileHistory_RemoveFileFromHistory(*args, **kwargs)
+
+ def GetMaxFiles(*args, **kwargs):
+ """GetMaxFiles(self) -> int"""
+ return _misc_.FileHistory_GetMaxFiles(*args, **kwargs)
+
+ def UseMenu(*args, **kwargs):
+ """UseMenu(self, Menu menu)"""
+ return _misc_.FileHistory_UseMenu(*args, **kwargs)
+
+ def RemoveMenu(*args, **kwargs):
+ """RemoveMenu(self, Menu menu)"""
+ return _misc_.FileHistory_RemoveMenu(*args, **kwargs)
+
+ def Load(*args, **kwargs):
+ """Load(self, ConfigBase config)"""
+ return _misc_.FileHistory_Load(*args, **kwargs)
+
+ def Save(*args, **kwargs):
+ """Save(self, ConfigBase config)"""
+ return _misc_.FileHistory_Save(*args, **kwargs)
+
+ def AddFilesToMenu(*args, **kwargs):
+ """AddFilesToMenu(self)"""
+ return _misc_.FileHistory_AddFilesToMenu(*args, **kwargs)
+
+ def AddFilesToThisMenu(*args, **kwargs):
+ """AddFilesToThisMenu(self, Menu menu)"""
+ return _misc_.FileHistory_AddFilesToThisMenu(*args, **kwargs)
+
+ def GetHistoryFile(*args, **kwargs):
+ """GetHistoryFile(self, int i) -> String"""
+ return _misc_.FileHistory_GetHistoryFile(*args, **kwargs)
+
+ def GetCount(*args, **kwargs):
+ """GetCount(self) -> int"""
+ return _misc_.FileHistory_GetCount(*args, **kwargs)
+
+ GetNoHistoryFiles = GetCount
+ Count = property(GetCount,doc="See `GetCount`")
+ HistoryFile = property(GetHistoryFile,doc="See `GetHistoryFile`")
+ MaxFiles = property(GetMaxFiles,doc="See `GetMaxFiles`")
+ NoHistoryFiles = property(GetNoHistoryFiles,doc="See `GetNoHistoryFiles`")
+_misc_.FileHistory_swigregister(FileHistory)
+
+class SingleInstanceChecker(object):
+ """Proxy of C++ SingleInstanceChecker class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String name, String path=EmptyString) -> SingleInstanceChecker"""
+ _misc_.SingleInstanceChecker_swiginit(self,_misc_.new_SingleInstanceChecker(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_SingleInstanceChecker
+ __del__ = lambda self : None;
+ def Create(*args, **kwargs):
+ """Create(self, String name, String path=EmptyString) -> bool"""
+ return _misc_.SingleInstanceChecker_Create(*args, **kwargs)
+
+ def CreateDefault(*args, **kwargs):
+ """CreateDefault(self) -> bool"""
+ return _misc_.SingleInstanceChecker_CreateDefault(*args, **kwargs)
+
+ def IsAnotherRunning(*args, **kwargs):
+ """IsAnotherRunning(self) -> bool"""
+ return _misc_.SingleInstanceChecker_IsAnotherRunning(*args, **kwargs)
+
+_misc_.SingleInstanceChecker_swigregister(SingleInstanceChecker)
+
+def PreSingleInstanceChecker(*args, **kwargs):
+ """PreSingleInstanceChecker() -> SingleInstanceChecker"""
+ val = _misc_.new_PreSingleInstanceChecker(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+OS_UNKNOWN = _misc_.OS_UNKNOWN
+OS_MAC_OS = _misc_.OS_MAC_OS
+OS_MAC_OSX_DARWIN = _misc_.OS_MAC_OSX_DARWIN
+OS_MAC = _misc_.OS_MAC
+OS_WINDOWS_9X = _misc_.OS_WINDOWS_9X
+OS_WINDOWS_NT = _misc_.OS_WINDOWS_NT
+OS_WINDOWS_MICRO = _misc_.OS_WINDOWS_MICRO
+OS_WINDOWS_CE = _misc_.OS_WINDOWS_CE
+OS_WINDOWS = _misc_.OS_WINDOWS
+OS_UNIX_LINUX = _misc_.OS_UNIX_LINUX
+OS_UNIX_FREEBSD = _misc_.OS_UNIX_FREEBSD
+OS_UNIX_OPENBSD = _misc_.OS_UNIX_OPENBSD
+OS_UNIX_NETBSD = _misc_.OS_UNIX_NETBSD
+OS_UNIX_SOLARIS = _misc_.OS_UNIX_SOLARIS
+OS_UNIX_AIX = _misc_.OS_UNIX_AIX
+OS_UNIX_HPUX = _misc_.OS_UNIX_HPUX
+OS_UNIX = _misc_.OS_UNIX
+OS_DOS = _misc_.OS_DOS
+OS_OS2 = _misc_.OS_OS2
+PORT_UNKNOWN = _misc_.PORT_UNKNOWN
+PORT_BASE = _misc_.PORT_BASE
+PORT_MSW = _misc_.PORT_MSW
+PORT_MOTIF = _misc_.PORT_MOTIF
+PORT_GTK = _misc_.PORT_GTK
+PORT_X11 = _misc_.PORT_X11
+PORT_PM = _misc_.PORT_PM
+PORT_OS2 = _misc_.PORT_OS2
+PORT_MAC = _misc_.PORT_MAC
+PORT_COCOA = _misc_.PORT_COCOA
+PORT_WINCE = _misc_.PORT_WINCE
+PORT_DFB = _misc_.PORT_DFB
+ARCH_INVALID = _misc_.ARCH_INVALID
+ARCH_32 = _misc_.ARCH_32
+ARCH_64 = _misc_.ARCH_64
+ARCH_MAX = _misc_.ARCH_MAX
+ENDIAN_INVALID = _misc_.ENDIAN_INVALID
+ENDIAN_BIG = _misc_.ENDIAN_BIG
+ENDIAN_LITTLE = _misc_.ENDIAN_LITTLE
+ENDIAN_PDP = _misc_.ENDIAN_PDP
+ENDIAN_MAX = _misc_.ENDIAN_MAX
+class LinuxDistributionInfo(object):
+ """Proxy of C++ LinuxDistributionInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ Id = property(_misc_.LinuxDistributionInfo_Id_get, _misc_.LinuxDistributionInfo_Id_set)
+ Release = property(_misc_.LinuxDistributionInfo_Release_get, _misc_.LinuxDistributionInfo_Release_set)
+ CodeName = property(_misc_.LinuxDistributionInfo_CodeName_get, _misc_.LinuxDistributionInfo_CodeName_set)
+ Description = property(_misc_.LinuxDistributionInfo_Description_get, _misc_.LinuxDistributionInfo_Description_set)
+_misc_.LinuxDistributionInfo_swigregister(LinuxDistributionInfo)
+
+class PlatformInformation(object):
+ """Proxy of C++ PlatformInformation class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PlatformInformation"""
+ _misc_.PlatformInformation_swiginit(self,_misc_.new_PlatformInformation(*args, **kwargs))
+ def __eq__(*args, **kwargs):
+ """__eq__(self, PlatformInformation t) -> bool"""
+ return _misc_.PlatformInformation___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """__ne__(self, PlatformInformation t) -> bool"""
+ return _misc_.PlatformInformation___ne__(*args, **kwargs)
+
+ def GetOSMajorVersion(*args, **kwargs):
+ """GetOSMajorVersion(self) -> int"""
+ return _misc_.PlatformInformation_GetOSMajorVersion(*args, **kwargs)
+
+ def GetOSMinorVersion(*args, **kwargs):
+ """GetOSMinorVersion(self) -> int"""
+ return _misc_.PlatformInformation_GetOSMinorVersion(*args, **kwargs)
+
+ def CheckOSVersion(*args, **kwargs):
+ """CheckOSVersion(self, int major, int minor) -> bool"""
+ return _misc_.PlatformInformation_CheckOSVersion(*args, **kwargs)
+
+ def GetToolkitMajorVersion(*args, **kwargs):
+ """GetToolkitMajorVersion(self) -> int"""
+ return _misc_.PlatformInformation_GetToolkitMajorVersion(*args, **kwargs)
+
+ def GetToolkitMinorVersion(*args, **kwargs):
+ """GetToolkitMinorVersion(self) -> int"""
+ return _misc_.PlatformInformation_GetToolkitMinorVersion(*args, **kwargs)
+
+ def CheckToolkitVersion(*args, **kwargs):
+ """CheckToolkitVersion(self, int major, int minor) -> bool"""
+ return _misc_.PlatformInformation_CheckToolkitVersion(*args, **kwargs)
+
+ def IsUsingUniversalWidgets(*args, **kwargs):
+ """IsUsingUniversalWidgets(self) -> bool"""
+ return _misc_.PlatformInformation_IsUsingUniversalWidgets(*args, **kwargs)
+
+ def GetOperatingSystemId(*args, **kwargs):
+ """GetOperatingSystemId(self) -> int"""
+ return _misc_.PlatformInformation_GetOperatingSystemId(*args, **kwargs)
+
+ def GetLinuxDistributionInfo(*args, **kwargs):
+ """GetLinuxDistributionInfo(self) -> LinuxDistributionInfo"""
+ return _misc_.PlatformInformation_GetLinuxDistributionInfo(*args, **kwargs)
+
+ def GetPortId(*args, **kwargs):
+ """GetPortId(self) -> int"""
+ return _misc_.PlatformInformation_GetPortId(*args, **kwargs)
+
+ def GetArchitecture(*args, **kwargs):
+ """GetArchitecture(self) -> int"""
+ return _misc_.PlatformInformation_GetArchitecture(*args, **kwargs)
+
+ def GetEndianness(*args, **kwargs):
+ """GetEndianness(self) -> int"""
+ return _misc_.PlatformInformation_GetEndianness(*args, **kwargs)
+
+ def GetOperatingSystemFamilyName(*args, **kwargs):
+ """GetOperatingSystemFamilyName(self) -> String"""
+ return _misc_.PlatformInformation_GetOperatingSystemFamilyName(*args, **kwargs)
+
+ def GetOperatingSystemIdName(*args, **kwargs):
+ """GetOperatingSystemIdName(self) -> String"""
+ return _misc_.PlatformInformation_GetOperatingSystemIdName(*args, **kwargs)
+
+ def GetPortIdName(*args, **kwargs):
+ """GetPortIdName(self) -> String"""
+ return _misc_.PlatformInformation_GetPortIdName(*args, **kwargs)
+
+ def GetPortIdShortName(*args, **kwargs):
+ """GetPortIdShortName(self) -> String"""
+ return _misc_.PlatformInformation_GetPortIdShortName(*args, **kwargs)
+
+ def GetArchName(*args, **kwargs):
+ """GetArchName(self) -> String"""
+ return _misc_.PlatformInformation_GetArchName(*args, **kwargs)
+
+ def GetEndiannessName(*args, **kwargs):
+ """GetEndiannessName(self) -> String"""
+ return _misc_.PlatformInformation_GetEndiannessName(*args, **kwargs)
+
+ def GetOperatingSystemDescription(*args, **kwargs):
+ """GetOperatingSystemDescription(self) -> String"""
+ return _misc_.PlatformInformation_GetOperatingSystemDescription(*args, **kwargs)
+
+ def GetDesktopEnvironment(*args, **kwargs):
+ """GetDesktopEnvironment(self) -> String"""
+ return _misc_.PlatformInformation_GetDesktopEnvironment(*args, **kwargs)
+
+ def GetOperatingSystemDirectory(*args, **kwargs):
+ """GetOperatingSystemDirectory() -> String"""
+ return _misc_.PlatformInformation_GetOperatingSystemDirectory(*args, **kwargs)
+
+ GetOperatingSystemDirectory = staticmethod(GetOperatingSystemDirectory)
+ def SetOSVersion(*args, **kwargs):
+ """SetOSVersion(self, int major, int minor)"""
+ return _misc_.PlatformInformation_SetOSVersion(*args, **kwargs)
+
+ def SetToolkitVersion(*args, **kwargs):
+ """SetToolkitVersion(self, int major, int minor)"""
+ return _misc_.PlatformInformation_SetToolkitVersion(*args, **kwargs)
+
+ def SetOperatingSystemId(*args, **kwargs):
+ """SetOperatingSystemId(self, int n)"""
+ return _misc_.PlatformInformation_SetOperatingSystemId(*args, **kwargs)
+
+ def SetOperatingSystemDescription(*args, **kwargs):
+ """SetOperatingSystemDescription(self, String desc)"""
+ return _misc_.PlatformInformation_SetOperatingSystemDescription(*args, **kwargs)
+
+ def SetPortId(*args, **kwargs):
+ """SetPortId(self, int n)"""
+ return _misc_.PlatformInformation_SetPortId(*args, **kwargs)
+
+ def SetArchitecture(*args, **kwargs):
+ """SetArchitecture(self, int n)"""
+ return _misc_.PlatformInformation_SetArchitecture(*args, **kwargs)
+
+ def SetEndianness(*args, **kwargs):
+ """SetEndianness(self, int n)"""
+ return _misc_.PlatformInformation_SetEndianness(*args, **kwargs)
+
+ def SetDesktopEnvironment(*args, **kwargs):
+ """SetDesktopEnvironment(self, String de)"""
+ return _misc_.PlatformInformation_SetDesktopEnvironment(*args, **kwargs)
+
+ def SetLinuxDistributionInfo(*args, **kwargs):
+ """SetLinuxDistributionInfo(self, LinuxDistributionInfo di)"""
+ return _misc_.PlatformInformation_SetLinuxDistributionInfo(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _misc_.PlatformInformation_IsOk(*args, **kwargs)
+
+ ArchName = property(GetArchName,doc="See `GetArchName`")
+ Architecture = property(GetArchitecture,SetArchitecture,doc="See `GetArchitecture` and `SetArchitecture`")
+ Endianness = property(GetEndianness,SetEndianness,doc="See `GetEndianness` and `SetEndianness`")
+ EndiannessName = property(GetEndiannessName,doc="See `GetEndiannessName`")
+ OSMajorVersion = property(GetOSMajorVersion,doc="See `GetOSMajorVersion`")
+ OSMinorVersion = property(GetOSMinorVersion,doc="See `GetOSMinorVersion`")
+ OperatingSystemFamilyName = property(GetOperatingSystemFamilyName,doc="See `GetOperatingSystemFamilyName`")
+ OperatingSystemId = property(GetOperatingSystemId,SetOperatingSystemId,doc="See `GetOperatingSystemId` and `SetOperatingSystemId`")
+ OperatingSystemIdName = property(GetOperatingSystemIdName,doc="See `GetOperatingSystemIdName`")
+ PortId = property(GetPortId,SetPortId,doc="See `GetPortId` and `SetPortId`")
+ PortIdName = property(GetPortIdName,doc="See `GetPortIdName`")
+ PortIdShortName = property(GetPortIdShortName,doc="See `GetPortIdShortName`")
+ ToolkitMajorVersion = property(GetToolkitMajorVersion,doc="See `GetToolkitMajorVersion`")
+ ToolkitMinorVersion = property(GetToolkitMinorVersion,doc="See `GetToolkitMinorVersion`")
+_misc_.PlatformInformation_swigregister(PlatformInformation)
+
+def PlatformInformation_GetOperatingSystemDirectory(*args):
+ """PlatformInformation_GetOperatingSystemDirectory() -> String"""
+ return _misc_.PlatformInformation_GetOperatingSystemDirectory(*args)
+
+class NotificationMessage(_core.EvtHandler):
+ """Proxy of C++ NotificationMessage class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> NotificationMessage
+ __init__(self, String title, String message=wxEmptyString, Window parent=None) -> NotificationMessage
+ """
+ _misc_.NotificationMessage_swiginit(self,_misc_.new_NotificationMessage(*args))
+ __swig_destroy__ = _misc_.delete_NotificationMessage
+ __del__ = lambda self : None;
+ def SetTitle(*args, **kwargs):
+ """SetTitle(self, String title)"""
+ return _misc_.NotificationMessage_SetTitle(*args, **kwargs)
+
+ def SetMessage(*args, **kwargs):
+ """SetMessage(self, String message)"""
+ return _misc_.NotificationMessage_SetMessage(*args, **kwargs)
+
+ def SetParent(*args, **kwargs):
+ """SetParent(self, Window parent)"""
+ return _misc_.NotificationMessage_SetParent(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _misc_.NotificationMessage_SetFlags(*args, **kwargs)
+
+ Timeout_Auto = _misc_.NotificationMessage_Timeout_Auto
+ Timeout_Never = _misc_.NotificationMessage_Timeout_Never
+ def Show(*args, **kwargs):
+ """Show(self, int timeout=Timeout_Auto) -> bool"""
+ return _misc_.NotificationMessage_Show(*args, **kwargs)
+
+ def Close(*args, **kwargs):
+ """Close(self) -> bool"""
+ return _misc_.NotificationMessage_Close(*args, **kwargs)
+
+_misc_.NotificationMessage_swigregister(NotificationMessage)
+
+#---------------------------------------------------------------------------
+
+class TipProvider(object):
+ """Proxy of C++ TipProvider class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _misc_.delete_TipProvider
+ __del__ = lambda self : None;
+ def GetTip(*args, **kwargs):
+ """GetTip(self) -> String"""
+ return _misc_.TipProvider_GetTip(*args, **kwargs)
+
+ def GetCurrentTip(*args, **kwargs):
+ """GetCurrentTip(self) -> size_t"""
+ return _misc_.TipProvider_GetCurrentTip(*args, **kwargs)
+
+ def PreprocessTip(*args, **kwargs):
+ """PreprocessTip(self, String tip) -> String"""
+ return _misc_.TipProvider_PreprocessTip(*args, **kwargs)
+
+ CurrentTip = property(GetCurrentTip,doc="See `GetCurrentTip`")
+ Tip = property(GetTip,doc="See `GetTip`")
+_misc_.TipProvider_swigregister(TipProvider)
+
+class PyTipProvider(TipProvider):
+ """Proxy of C++ PyTipProvider class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, size_t currentTip) -> PyTipProvider"""
+ _misc_.PyTipProvider_swiginit(self,_misc_.new_PyTipProvider(*args, **kwargs))
+ PyTipProvider._setCallbackInfo(self, self, PyTipProvider)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _misc_.PyTipProvider__setCallbackInfo(*args, **kwargs)
+
+_misc_.PyTipProvider_swigregister(PyTipProvider)
+
+
+def ShowTip(*args, **kwargs):
+ """ShowTip(Window parent, TipProvider tipProvider, bool showAtStartup=True) -> bool"""
+ return _misc_.ShowTip(*args, **kwargs)
+
+def CreateFileTipProvider(*args, **kwargs):
+ """CreateFileTipProvider(String filename, size_t currentTip) -> TipProvider"""
+ return _misc_.CreateFileTipProvider(*args, **kwargs)
+#---------------------------------------------------------------------------
+
+TIMER_CONTINUOUS = _misc_.TIMER_CONTINUOUS
+TIMER_ONE_SHOT = _misc_.TIMER_ONE_SHOT
+wxEVT_TIMER = _misc_.wxEVT_TIMER
+class Timer(_core.EvtHandler):
+ """Proxy of C++ Timer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EvtHandler owner=None, int id=ID_ANY) -> Timer"""
+ _misc_.Timer_swiginit(self,_misc_.new_Timer(*args, **kwargs))
+ self._setOORInfo(self,0); self.this.own(True); Timer._setCallbackInfo(self, self, Timer)
+
+ __swig_destroy__ = _misc_.delete_Timer
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class, int incref=0)"""
+ return _misc_.Timer__setCallbackInfo(*args, **kwargs)
+
+ def SetOwner(*args, **kwargs):
+ """SetOwner(self, EvtHandler owner, int id=ID_ANY)"""
+ return _misc_.Timer_SetOwner(*args, **kwargs)
+
+ def GetOwner(*args, **kwargs):
+ """GetOwner(self) -> EvtHandler"""
+ return _misc_.Timer_GetOwner(*args, **kwargs)
+
+ def Start(*args, **kwargs):
+ """Start(self, int milliseconds=-1, bool oneShot=False) -> bool"""
+ return _misc_.Timer_Start(*args, **kwargs)
+
+ def Stop(*args, **kwargs):
+ """Stop(self)"""
+ return _misc_.Timer_Stop(*args, **kwargs)
+
+ def Notify(*args, **kwargs):
+ """Notify(self)"""
+ return _misc_.Timer_Notify(*args, **kwargs)
+
+ def IsRunning(*args, **kwargs):
+ """IsRunning(self) -> bool"""
+ return _misc_.Timer_IsRunning(*args, **kwargs)
+
+ def GetInterval(*args, **kwargs):
+ """GetInterval(self) -> int"""
+ return _misc_.Timer_GetInterval(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """GetId(self) -> int"""
+ return _misc_.Timer_GetId(*args, **kwargs)
+
+ def IsOneShot(*args, **kwargs):
+ """IsOneShot(self) -> bool"""
+ return _misc_.Timer_IsOneShot(*args, **kwargs)
+
+ def Destroy(self):
+ """NO-OP: Timers must be destroyed by normal reference counting"""
+ pass
+
+ Id = property(GetId,doc="See `GetId`")
+ Interval = property(GetInterval,doc="See `GetInterval`")
+ Owner = property(GetOwner,SetOwner,doc="See `GetOwner` and `SetOwner`")
+_misc_.Timer_swigregister(Timer)
+
+# For backwards compatibility with 2.4
+class PyTimer(Timer):
+ def __init__(self, notify):
+ Timer.__init__(self)
+ self.notify = notify
+
+ def Notify(self):
+ if self.notify:
+ self.notify()
+
+
+EVT_TIMER = wx.PyEventBinder( wxEVT_TIMER, 1 )
+
+
+class TimerEvent(_core.Event):
+ """Proxy of C++ TimerEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, wxTimer timer) -> TimerEvent"""
+ _misc_.TimerEvent_swiginit(self,_misc_.new_TimerEvent(*args, **kwargs))
+ def GetInterval(*args, **kwargs):
+ """GetInterval(self) -> int"""
+ return _misc_.TimerEvent_GetInterval(*args, **kwargs)
+
+ def GetTimer(*args, **kwargs):
+ """GetTimer(self) -> wxTimer"""
+ return _misc_.TimerEvent_GetTimer(*args, **kwargs)
+
+ Interval = property(GetInterval,doc="See `GetInterval`")
+ Timer = property(GetTimer)
+_misc_.TimerEvent_swigregister(TimerEvent)
+
+class TimerRunner(object):
+ """Proxy of C++ TimerRunner class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, wxTimer timer) -> TimerRunner
+ __init__(self, wxTimer timer, int milli, bool oneShot=False) -> TimerRunner
+ """
+ _misc_.TimerRunner_swiginit(self,_misc_.new_TimerRunner(*args))
+ __swig_destroy__ = _misc_.delete_TimerRunner
+ __del__ = lambda self : None;
+ def Start(*args, **kwargs):
+ """Start(self, int milli, bool oneShot=False)"""
+ return _misc_.TimerRunner_Start(*args, **kwargs)
+
+_misc_.TimerRunner_swigregister(TimerRunner)
+
+#---------------------------------------------------------------------------
+
+LOG_FatalError = _misc_.LOG_FatalError
+LOG_Error = _misc_.LOG_Error
+LOG_Warning = _misc_.LOG_Warning
+LOG_Message = _misc_.LOG_Message
+LOG_Status = _misc_.LOG_Status
+LOG_Info = _misc_.LOG_Info
+LOG_Debug = _misc_.LOG_Debug
+LOG_Trace = _misc_.LOG_Trace
+LOG_Progress = _misc_.LOG_Progress
+LOG_User = _misc_.LOG_User
+LOG_Max = _misc_.LOG_Max
+TRACE_MemAlloc = _misc_.TRACE_MemAlloc
+TRACE_Messages = _misc_.TRACE_Messages
+TRACE_ResAlloc = _misc_.TRACE_ResAlloc
+TRACE_RefCount = _misc_.TRACE_RefCount
+TRACE_OleCalls = _misc_.TRACE_OleCalls
+TraceMemAlloc = _misc_.TraceMemAlloc
+TraceMessages = _misc_.TraceMessages
+TraceResAlloc = _misc_.TraceResAlloc
+TraceRefCount = _misc_.TraceRefCount
+TraceOleCalls = _misc_.TraceOleCalls
+class LogRecordInfo(object):
+ """Proxy of C++ LogRecordInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> LogRecordInfo
+ __init__(self, char filename_, int line_, char func_, char component_) -> LogRecordInfo
+ """
+ _misc_.LogRecordInfo_swiginit(self,_misc_.new_LogRecordInfo(*args))
+ __swig_destroy__ = _misc_.delete_LogRecordInfo
+ __del__ = lambda self : None;
+ filename = property(_misc_.LogRecordInfo_filename_get)
+ line = property(_misc_.LogRecordInfo_line_get)
+ func = property(_misc_.LogRecordInfo_func_get)
+ component = property(_misc_.LogRecordInfo_component_get)
+ timestamp = property(_misc_.LogRecordInfo_timestamp_get)
+_misc_.LogRecordInfo_swigregister(LogRecordInfo)
+
+class Log(object):
+ """Proxy of C++ Log class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> Log"""
+ _misc_.Log_swiginit(self,_misc_.new_Log(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_Log
+ __del__ = lambda self : None;
+ def IsEnabled(*args, **kwargs):
+ """IsEnabled() -> bool"""
+ return _misc_.Log_IsEnabled(*args, **kwargs)
+
+ IsEnabled = staticmethod(IsEnabled)
+ def EnableLogging(*args, **kwargs):
+ """EnableLogging(bool enable=True) -> bool"""
+ return _misc_.Log_EnableLogging(*args, **kwargs)
+
+ EnableLogging = staticmethod(EnableLogging)
+ def GetLogLevel(*args, **kwargs):
+ """GetLogLevel() -> LogLevel"""
+ return _misc_.Log_GetLogLevel(*args, **kwargs)
+
+ GetLogLevel = staticmethod(GetLogLevel)
+ def SetLogLevel(*args, **kwargs):
+ """SetLogLevel(LogLevel logLevel)"""
+ return _misc_.Log_SetLogLevel(*args, **kwargs)
+
+ SetLogLevel = staticmethod(SetLogLevel)
+ def SetComponentLevel(*args, **kwargs):
+ """SetComponentLevel(String component, LogLevel level)"""
+ return _misc_.Log_SetComponentLevel(*args, **kwargs)
+
+ SetComponentLevel = staticmethod(SetComponentLevel)
+ def GetComponentLevel(*args, **kwargs):
+ """GetComponentLevel(String component) -> LogLevel"""
+ return _misc_.Log_GetComponentLevel(*args, **kwargs)
+
+ GetComponentLevel = staticmethod(GetComponentLevel)
+ def IsLevelEnabled(*args, **kwargs):
+ """IsLevelEnabled(LogLevel level, String component) -> bool"""
+ return _misc_.Log_IsLevelEnabled(*args, **kwargs)
+
+ IsLevelEnabled = staticmethod(IsLevelEnabled)
+ def SetVerbose(*args, **kwargs):
+ """SetVerbose(bool bVerbose=True)"""
+ return _misc_.Log_SetVerbose(*args, **kwargs)
+
+ SetVerbose = staticmethod(SetVerbose)
+ def GetVerbose(*args, **kwargs):
+ """GetVerbose() -> bool"""
+ return _misc_.Log_GetVerbose(*args, **kwargs)
+
+ GetVerbose = staticmethod(GetVerbose)
+ def Flush(*args, **kwargs):
+ """Flush(self)"""
+ return _misc_.Log_Flush(*args, **kwargs)
+
+ def FlushActive(*args, **kwargs):
+ """FlushActive()"""
+ return _misc_.Log_FlushActive(*args, **kwargs)
+
+ FlushActive = staticmethod(FlushActive)
+ def GetActiveTarget(*args, **kwargs):
+ """GetActiveTarget() -> Log"""
+ return _misc_.Log_GetActiveTarget(*args, **kwargs)
+
+ GetActiveTarget = staticmethod(GetActiveTarget)
+ def SetActiveTarget(*args, **kwargs):
+ """SetActiveTarget(Log pLogger) -> Log"""
+ return _misc_.Log_SetActiveTarget(*args, **kwargs)
+
+ SetActiveTarget = staticmethod(SetActiveTarget)
+ def Suspend(*args, **kwargs):
+ """Suspend()"""
+ return _misc_.Log_Suspend(*args, **kwargs)
+
+ Suspend = staticmethod(Suspend)
+ def Resume(*args, **kwargs):
+ """Resume()"""
+ return _misc_.Log_Resume(*args, **kwargs)
+
+ Resume = staticmethod(Resume)
+ def DontCreateOnDemand(*args, **kwargs):
+ """DontCreateOnDemand()"""
+ return _misc_.Log_DontCreateOnDemand(*args, **kwargs)
+
+ DontCreateOnDemand = staticmethod(DontCreateOnDemand)
+ def DoCreateOnDemand(*args, **kwargs):
+ """DoCreateOnDemand()"""
+ return _misc_.Log_DoCreateOnDemand(*args, **kwargs)
+
+ DoCreateOnDemand = staticmethod(DoCreateOnDemand)
+ def SetRepetitionCounting(*args, **kwargs):
+ """SetRepetitionCounting(bool bRepetCounting=True)"""
+ return _misc_.Log_SetRepetitionCounting(*args, **kwargs)
+
+ SetRepetitionCounting = staticmethod(SetRepetitionCounting)
+ def GetRepetitionCounting(*args, **kwargs):
+ """GetRepetitionCounting() -> bool"""
+ return _misc_.Log_GetRepetitionCounting(*args, **kwargs)
+
+ GetRepetitionCounting = staticmethod(GetRepetitionCounting)
+ def SetTraceMask(*args, **kwargs):
+ """SetTraceMask(TraceMask ulMask)"""
+ return _misc_.Log_SetTraceMask(*args, **kwargs)
+
+ SetTraceMask = staticmethod(SetTraceMask)
+ def AddTraceMask(*args, **kwargs):
+ """AddTraceMask(String str)"""
+ return _misc_.Log_AddTraceMask(*args, **kwargs)
+
+ AddTraceMask = staticmethod(AddTraceMask)
+ def RemoveTraceMask(*args, **kwargs):
+ """RemoveTraceMask(String str)"""
+ return _misc_.Log_RemoveTraceMask(*args, **kwargs)
+
+ RemoveTraceMask = staticmethod(RemoveTraceMask)
+ def ClearTraceMasks(*args, **kwargs):
+ """ClearTraceMasks()"""
+ return _misc_.Log_ClearTraceMasks(*args, **kwargs)
+
+ ClearTraceMasks = staticmethod(ClearTraceMasks)
+ def GetTraceMasks(*args, **kwargs):
+ """GetTraceMasks() -> wxArrayString"""
+ return _misc_.Log_GetTraceMasks(*args, **kwargs)
+
+ GetTraceMasks = staticmethod(GetTraceMasks)
+ def SetTimestamp(*args, **kwargs):
+ """SetTimestamp(String ts)"""
+ return _misc_.Log_SetTimestamp(*args, **kwargs)
+
+ SetTimestamp = staticmethod(SetTimestamp)
+ def GetTraceMask(*args, **kwargs):
+ """GetTraceMask() -> TraceMask"""
+ return _misc_.Log_GetTraceMask(*args, **kwargs)
+
+ GetTraceMask = staticmethod(GetTraceMask)
+ def IsAllowedTraceMask(*args, **kwargs):
+ """IsAllowedTraceMask(String mask) -> bool"""
+ return _misc_.Log_IsAllowedTraceMask(*args, **kwargs)
+
+ IsAllowedTraceMask = staticmethod(IsAllowedTraceMask)
+ def GetTimestamp(*args, **kwargs):
+ """GetTimestamp() -> String"""
+ return _misc_.Log_GetTimestamp(*args, **kwargs)
+
+ GetTimestamp = staticmethod(GetTimestamp)
+ def TimeStamp(*args, **kwargs):
+ """TimeStamp() -> String"""
+ return _misc_.Log_TimeStamp(*args, **kwargs)
+
+ TimeStamp = staticmethod(TimeStamp)
+ def LogRecord(*args, **kwargs):
+ """LogRecord(self, LogLevel level, String msg, LogRecordInfo info)"""
+ return _misc_.Log_LogRecord(*args, **kwargs)
+
+ def LogTextAtLevel(*args, **kwargs):
+ """LogTextAtLevel(self, LogLevel level, String msg)"""
+ return _misc_.Log_LogTextAtLevel(*args, **kwargs)
+
+ def LogText(*args, **kwargs):
+ """LogText(self, String msg)"""
+ return _misc_.Log_LogText(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """Destroy(self)"""
+ args[0].this.own(False)
+ return _misc_.Log_Destroy(*args, **kwargs)
+
+_misc_.Log_swigregister(Log)
+
+def Log_IsEnabled(*args):
+ """Log_IsEnabled() -> bool"""
+ return _misc_.Log_IsEnabled(*args)
+
+def Log_EnableLogging(*args, **kwargs):
+ """Log_EnableLogging(bool enable=True) -> bool"""
+ return _misc_.Log_EnableLogging(*args, **kwargs)
+
+def Log_GetLogLevel(*args):
+ """Log_GetLogLevel() -> LogLevel"""
+ return _misc_.Log_GetLogLevel(*args)
+
+def Log_SetLogLevel(*args, **kwargs):
+ """Log_SetLogLevel(LogLevel logLevel)"""
+ return _misc_.Log_SetLogLevel(*args, **kwargs)
+
+def Log_SetComponentLevel(*args, **kwargs):
+ """Log_SetComponentLevel(String component, LogLevel level)"""
+ return _misc_.Log_SetComponentLevel(*args, **kwargs)
+
+def Log_GetComponentLevel(*args, **kwargs):
+ """Log_GetComponentLevel(String component) -> LogLevel"""
+ return _misc_.Log_GetComponentLevel(*args, **kwargs)
+
+def Log_IsLevelEnabled(*args, **kwargs):
+ """Log_IsLevelEnabled(LogLevel level, String component) -> bool"""
+ return _misc_.Log_IsLevelEnabled(*args, **kwargs)
+
+def Log_SetVerbose(*args, **kwargs):
+ """Log_SetVerbose(bool bVerbose=True)"""
+ return _misc_.Log_SetVerbose(*args, **kwargs)
+
+def Log_GetVerbose(*args):
+ """Log_GetVerbose() -> bool"""
+ return _misc_.Log_GetVerbose(*args)
+
+def Log_FlushActive(*args):
+ """Log_FlushActive()"""
+ return _misc_.Log_FlushActive(*args)
+
+def Log_GetActiveTarget(*args):
+ """Log_GetActiveTarget() -> Log"""
+ return _misc_.Log_GetActiveTarget(*args)
+
+def Log_SetActiveTarget(*args, **kwargs):
+ """Log_SetActiveTarget(Log pLogger) -> Log"""
+ return _misc_.Log_SetActiveTarget(*args, **kwargs)
+
+def Log_Suspend(*args):
+ """Log_Suspend()"""
+ return _misc_.Log_Suspend(*args)
+
+def Log_Resume(*args):
+ """Log_Resume()"""
+ return _misc_.Log_Resume(*args)
+
+def Log_DontCreateOnDemand(*args):
+ """Log_DontCreateOnDemand()"""
+ return _misc_.Log_DontCreateOnDemand(*args)
+
+def Log_DoCreateOnDemand(*args):
+ """Log_DoCreateOnDemand()"""
+ return _misc_.Log_DoCreateOnDemand(*args)
+
+def Log_SetRepetitionCounting(*args, **kwargs):
+ """Log_SetRepetitionCounting(bool bRepetCounting=True)"""
+ return _misc_.Log_SetRepetitionCounting(*args, **kwargs)
+
+def Log_GetRepetitionCounting(*args):
+ """Log_GetRepetitionCounting() -> bool"""
+ return _misc_.Log_GetRepetitionCounting(*args)
+
+def Log_SetTraceMask(*args, **kwargs):
+ """Log_SetTraceMask(TraceMask ulMask)"""
+ return _misc_.Log_SetTraceMask(*args, **kwargs)
+
+def Log_AddTraceMask(*args, **kwargs):
+ """Log_AddTraceMask(String str)"""
+ return _misc_.Log_AddTraceMask(*args, **kwargs)
+
+def Log_RemoveTraceMask(*args, **kwargs):
+ """Log_RemoveTraceMask(String str)"""
+ return _misc_.Log_RemoveTraceMask(*args, **kwargs)
+
+def Log_ClearTraceMasks(*args):
+ """Log_ClearTraceMasks()"""
+ return _misc_.Log_ClearTraceMasks(*args)
+
+def Log_GetTraceMasks(*args):
+ """Log_GetTraceMasks() -> wxArrayString"""
+ return _misc_.Log_GetTraceMasks(*args)
+
+def Log_SetTimestamp(*args, **kwargs):
+ """Log_SetTimestamp(String ts)"""
+ return _misc_.Log_SetTimestamp(*args, **kwargs)
+
+def Log_GetTraceMask(*args):
+ """Log_GetTraceMask() -> TraceMask"""
+ return _misc_.Log_GetTraceMask(*args)
+
+def Log_IsAllowedTraceMask(*args, **kwargs):
+ """Log_IsAllowedTraceMask(String mask) -> bool"""
+ return _misc_.Log_IsAllowedTraceMask(*args, **kwargs)
+
+def Log_GetTimestamp(*args):
+ """Log_GetTimestamp() -> String"""
+ return _misc_.Log_GetTimestamp(*args)
+
+def Log_TimeStamp(*args):
+ """Log_TimeStamp() -> String"""
+ return _misc_.Log_TimeStamp(*args)
+
+class LogStderr(Log):
+ """Proxy of C++ LogStderr class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> LogStderr"""
+ _misc_.LogStderr_swiginit(self,_misc_.new_LogStderr(*args, **kwargs))
+_misc_.LogStderr_swigregister(LogStderr)
+
+class LogTextCtrl(Log):
+ """Proxy of C++ LogTextCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, wxTextCtrl pTextCtrl) -> LogTextCtrl"""
+ _misc_.LogTextCtrl_swiginit(self,_misc_.new_LogTextCtrl(*args, **kwargs))
+_misc_.LogTextCtrl_swigregister(LogTextCtrl)
+
+class LogGui(Log):
+ """Proxy of C++ LogGui class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> LogGui"""
+ _misc_.LogGui_swiginit(self,_misc_.new_LogGui(*args, **kwargs))
+_misc_.LogGui_swigregister(LogGui)
+
+class LogWindow(Log):
+ """Proxy of C++ LogWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, wxFrame pParent, String szTitle, bool bShow=True, bool bPassToOld=True) -> LogWindow"""
+ _misc_.LogWindow_swiginit(self,_misc_.new_LogWindow(*args, **kwargs))
+ def Show(*args, **kwargs):
+ """Show(self, bool bShow=True)"""
+ return _misc_.LogWindow_Show(*args, **kwargs)
+
+ def GetFrame(*args, **kwargs):
+ """GetFrame(self) -> wxFrame"""
+ return _misc_.LogWindow_GetFrame(*args, **kwargs)
+
+ def GetOldLog(*args, **kwargs):
+ """GetOldLog(self) -> Log"""
+ return _misc_.LogWindow_GetOldLog(*args, **kwargs)
+
+ def IsPassingMessages(*args, **kwargs):
+ """IsPassingMessages(self) -> bool"""
+ return _misc_.LogWindow_IsPassingMessages(*args, **kwargs)
+
+ def PassMessages(*args, **kwargs):
+ """PassMessages(self, bool bDoPass)"""
+ return _misc_.LogWindow_PassMessages(*args, **kwargs)
+
+ Frame = property(GetFrame,doc="See `GetFrame`")
+ OldLog = property(GetOldLog,doc="See `GetOldLog`")
+_misc_.LogWindow_swigregister(LogWindow)
+
+class LogChain(Log):
+ """Proxy of C++ LogChain class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Log logger) -> LogChain"""
+ _misc_.LogChain_swiginit(self,_misc_.new_LogChain(*args, **kwargs))
+ def SetLog(*args, **kwargs):
+ """SetLog(self, Log logger)"""
+ return _misc_.LogChain_SetLog(*args, **kwargs)
+
+ def PassMessages(*args, **kwargs):
+ """PassMessages(self, bool bDoPass)"""
+ return _misc_.LogChain_PassMessages(*args, **kwargs)
+
+ def IsPassingMessages(*args, **kwargs):
+ """IsPassingMessages(self) -> bool"""
+ return _misc_.LogChain_IsPassingMessages(*args, **kwargs)
+
+ def GetOldLog(*args, **kwargs):
+ """GetOldLog(self) -> Log"""
+ return _misc_.LogChain_GetOldLog(*args, **kwargs)
+
+ def DetachOldLog(*args, **kwargs):
+ """DetachOldLog(self)"""
+ return _misc_.LogChain_DetachOldLog(*args, **kwargs)
+
+ OldLog = property(GetOldLog,doc="See `GetOldLog`")
+_misc_.LogChain_swigregister(LogChain)
+
+class LogBuffer(Log):
+ """Proxy of C++ LogBuffer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> LogBuffer"""
+ _misc_.LogBuffer_swiginit(self,_misc_.new_LogBuffer(*args, **kwargs))
+ def GetBuffer(*args, **kwargs):
+ """GetBuffer(self) -> String"""
+ return _misc_.LogBuffer_GetBuffer(*args, **kwargs)
+
+ Buffer = property(GetBuffer,doc="See `GetBuffer`")
+_misc_.LogBuffer_swigregister(LogBuffer)
+
+
+def SysErrorCode(*args):
+ """SysErrorCode() -> unsigned long"""
+ return _misc_.SysErrorCode(*args)
+
+def SysErrorMsg(*args, **kwargs):
+ """SysErrorMsg(unsigned long nErrCode=0) -> String"""
+ return _misc_.SysErrorMsg(*args, **kwargs)
+
+def LogFatalError(*args, **kwargs):
+ """LogFatalError(String msg)"""
+ return _misc_.LogFatalError(*args, **kwargs)
+
+def LogError(*args, **kwargs):
+ """LogError(String msg)"""
+ return _misc_.LogError(*args, **kwargs)
+
+def LogWarning(*args, **kwargs):
+ """LogWarning(String msg)"""
+ return _misc_.LogWarning(*args, **kwargs)
+
+def LogMessage(*args, **kwargs):
+ """LogMessage(String msg)"""
+ return _misc_.LogMessage(*args, **kwargs)
+
+def LogInfo(*args, **kwargs):
+ """LogInfo(String msg)"""
+ return _misc_.LogInfo(*args, **kwargs)
+
+def LogDebug(*args, **kwargs):
+ """LogDebug(String msg)"""
+ return _misc_.LogDebug(*args, **kwargs)
+
+def LogVerbose(*args, **kwargs):
+ """LogVerbose(String msg)"""
+ return _misc_.LogVerbose(*args, **kwargs)
+
+def LogStatus(*args, **kwargs):
+ """LogStatus(String msg)"""
+ return _misc_.LogStatus(*args, **kwargs)
+
+def LogStatusFrame(*args, **kwargs):
+ """LogStatusFrame(wxFrame pFrame, String msg)"""
+ return _misc_.LogStatusFrame(*args, **kwargs)
+
+def LogSysError(*args, **kwargs):
+ """LogSysError(String msg)"""
+ return _misc_.LogSysError(*args, **kwargs)
+
+def LogGeneric(*args, **kwargs):
+ """LogGeneric(unsigned long level, String msg)"""
+ return _misc_.LogGeneric(*args, **kwargs)
+
+def SafeShowMessage(*args, **kwargs):
+ """SafeShowMessage(String title, String text)"""
+ return _misc_.SafeShowMessage(*args, **kwargs)
+class LogNull(object):
+ """Proxy of C++ LogNull class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> LogNull"""
+ _misc_.LogNull_swiginit(self,_misc_.new_LogNull(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_LogNull
+ __del__ = lambda self : None;
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ return False
+
+_misc_.LogNull_swigregister(LogNull)
+
+def LogTrace(*args):
+ """
+ LogTrace(unsigned long mask, String msg)
+ LogTrace(String mask, String msg)
+ """
+ return _misc_.LogTrace(*args)
+
+class PyLog(Log):
+ """Proxy of C++ PyLog class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyLog"""
+ _misc_.PyLog_swiginit(self,_misc_.new_PyLog(*args, **kwargs))
+ PyLog._setCallbackInfo(self, self, PyLog)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _misc_.PyLog__setCallbackInfo(*args, **kwargs)
+
+_misc_.PyLog_swigregister(PyLog)
+
+#---------------------------------------------------------------------------
+
+PROCESS_DEFAULT = _misc_.PROCESS_DEFAULT
+PROCESS_REDIRECT = _misc_.PROCESS_REDIRECT
+KILL_OK = _misc_.KILL_OK
+KILL_BAD_SIGNAL = _misc_.KILL_BAD_SIGNAL
+KILL_ACCESS_DENIED = _misc_.KILL_ACCESS_DENIED
+KILL_NO_PROCESS = _misc_.KILL_NO_PROCESS
+KILL_ERROR = _misc_.KILL_ERROR
+KILL_NOCHILDREN = _misc_.KILL_NOCHILDREN
+KILL_CHILDREN = _misc_.KILL_CHILDREN
+SIGNONE = _misc_.SIGNONE
+SIGHUP = _misc_.SIGHUP
+SIGINT = _misc_.SIGINT
+SIGQUIT = _misc_.SIGQUIT
+SIGILL = _misc_.SIGILL
+SIGTRAP = _misc_.SIGTRAP
+SIGABRT = _misc_.SIGABRT
+SIGIOT = _misc_.SIGIOT
+SIGEMT = _misc_.SIGEMT
+SIGFPE = _misc_.SIGFPE
+SIGKILL = _misc_.SIGKILL
+SIGBUS = _misc_.SIGBUS
+SIGSEGV = _misc_.SIGSEGV
+SIGSYS = _misc_.SIGSYS
+SIGPIPE = _misc_.SIGPIPE
+SIGALRM = _misc_.SIGALRM
+SIGTERM = _misc_.SIGTERM
+class Process(_core.EvtHandler):
+ """Proxy of C++ Process class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def Kill(*args, **kwargs):
+ """Kill(int pid, int sig=SIGTERM, int flags=KILL_NOCHILDREN) -> int"""
+ return _misc_.Process_Kill(*args, **kwargs)
+
+ Kill = staticmethod(Kill)
+ def Exists(*args, **kwargs):
+ """Exists(int pid) -> bool"""
+ return _misc_.Process_Exists(*args, **kwargs)
+
+ Exists = staticmethod(Exists)
+ def Open(*args, **kwargs):
+ """Open(String cmd, int flags=EXEC_ASYNC) -> Process"""
+ return _misc_.Process_Open(*args, **kwargs)
+
+ Open = staticmethod(Open)
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EvtHandler parent=None, int id=-1) -> Process"""
+ _misc_.Process_swiginit(self,_misc_.new_Process(*args, **kwargs))
+ Process._setCallbackInfo(self, self, Process); self.this.own(False)
+
+ __swig_destroy__ = _misc_.delete_Process
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _misc_.Process__setCallbackInfo(*args, **kwargs)
+
+ def GetPid(*args, **kwargs):
+ """
+ GetPid(self) -> long
+
+ get the process ID of the process executed by Open()
+ """
+ return _misc_.Process_GetPid(*args, **kwargs)
+
+ def OnTerminate(*args, **kwargs):
+ """OnTerminate(self, int pid, int status)"""
+ return _misc_.Process_OnTerminate(*args, **kwargs)
+
+ def base_OnTerminate(*args, **kw):
+ return Process.OnTerminate(*args, **kw)
+ base_OnTerminate = wx.deprecated(base_OnTerminate,
+ "Please use Process.OnTerminate instead.")
+
+ def Redirect(*args, **kwargs):
+ """Redirect(self)"""
+ return _misc_.Process_Redirect(*args, **kwargs)
+
+ def IsRedirected(*args, **kwargs):
+ """IsRedirected(self) -> bool"""
+ return _misc_.Process_IsRedirected(*args, **kwargs)
+
+ def Detach(*args, **kwargs):
+ """Detach(self)"""
+ return _misc_.Process_Detach(*args, **kwargs)
+
+ def GetInputStream(*args, **kwargs):
+ """GetInputStream(self) -> InputStream"""
+ return _misc_.Process_GetInputStream(*args, **kwargs)
+
+ def GetErrorStream(*args, **kwargs):
+ """GetErrorStream(self) -> InputStream"""
+ return _misc_.Process_GetErrorStream(*args, **kwargs)
+
+ def GetOutputStream(*args, **kwargs):
+ """GetOutputStream(self) -> wxOutputStream"""
+ return _misc_.Process_GetOutputStream(*args, **kwargs)
+
+ def CloseOutput(*args, **kwargs):
+ """CloseOutput(self)"""
+ return _misc_.Process_CloseOutput(*args, **kwargs)
+
+ def IsInputOpened(*args, **kwargs):
+ """IsInputOpened(self) -> bool"""
+ return _misc_.Process_IsInputOpened(*args, **kwargs)
+
+ def IsInputAvailable(*args, **kwargs):
+ """IsInputAvailable(self) -> bool"""
+ return _misc_.Process_IsInputAvailable(*args, **kwargs)
+
+ def IsErrorAvailable(*args, **kwargs):
+ """IsErrorAvailable(self) -> bool"""
+ return _misc_.Process_IsErrorAvailable(*args, **kwargs)
+
+ ErrorStream = property(GetErrorStream,doc="See `GetErrorStream`")
+ InputStream = property(GetInputStream,doc="See `GetInputStream`")
+ OutputStream = property(GetOutputStream,doc="See `GetOutputStream`")
+ InputOpened = property(IsInputOpened)
+ InputAvailable = property(IsInputAvailable)
+ ErrorAvailable = property(IsErrorAvailable)
+_misc_.Process_swigregister(Process)
+
+def Process_Kill(*args, **kwargs):
+ """Process_Kill(int pid, int sig=SIGTERM, int flags=KILL_NOCHILDREN) -> int"""
+ return _misc_.Process_Kill(*args, **kwargs)
+
+def Process_Exists(*args, **kwargs):
+ """Process_Exists(int pid) -> bool"""
+ return _misc_.Process_Exists(*args, **kwargs)
+
+def Process_Open(*args, **kwargs):
+ """Process_Open(String cmd, int flags=EXEC_ASYNC) -> Process"""
+ return _misc_.Process_Open(*args, **kwargs)
+
+class ProcessEvent(_core.Event):
+ """Proxy of C++ ProcessEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int id=0, int pid=0, int exitcode=0) -> ProcessEvent"""
+ _misc_.ProcessEvent_swiginit(self,_misc_.new_ProcessEvent(*args, **kwargs))
+ def GetPid(*args, **kwargs):
+ """GetPid(self) -> int"""
+ return _misc_.ProcessEvent_GetPid(*args, **kwargs)
+
+ def GetExitCode(*args, **kwargs):
+ """GetExitCode(self) -> int"""
+ return _misc_.ProcessEvent_GetExitCode(*args, **kwargs)
+
+ m_pid = property(_misc_.ProcessEvent_m_pid_get, _misc_.ProcessEvent_m_pid_set)
+ m_exitcode = property(_misc_.ProcessEvent_m_exitcode_get, _misc_.ProcessEvent_m_exitcode_set)
+ ExitCode = property(GetExitCode,doc="See `GetExitCode`")
+ Pid = property(GetPid,doc="See `GetPid`")
+_misc_.ProcessEvent_swigregister(ProcessEvent)
+
+wxEVT_END_PROCESS = _misc_.wxEVT_END_PROCESS
+EVT_END_PROCESS = wx.PyEventBinder( wxEVT_END_PROCESS, 1 )
+
+EXEC_ASYNC = _misc_.EXEC_ASYNC
+EXEC_SYNC = _misc_.EXEC_SYNC
+EXEC_NOHIDE = _misc_.EXEC_NOHIDE
+EXEC_MAKE_GROUP_LEADER = _misc_.EXEC_MAKE_GROUP_LEADER
+EXEC_NODISABLE = _misc_.EXEC_NODISABLE
+EXEC_NOEVENTS = _misc_.EXEC_NOEVENTS
+EXEC_BLOCK = _misc_.EXEC_BLOCK
+EXEC_SHOW_CONSOLE = _misc_.EXEC_SHOW_CONSOLE
+EXEC_HIDE_CONSOLE = _misc_.EXEC_HIDE_CONSOLE
+
+def Execute(*args, **kwargs):
+ """Execute(String command, int flags=EXEC_ASYNC, Process process=None) -> long"""
+ return _misc_.Execute(*args, **kwargs)
+
+def Kill(*args, **kwargs):
+ """Kill(long pid, int sig=SIGTERM, int rc, int flags=KILL_NOCHILDREN) -> int"""
+ return _misc_.Kill(*args, **kwargs)
+#---------------------------------------------------------------------------
+
+JOYSTICK1 = _misc_.JOYSTICK1
+JOYSTICK2 = _misc_.JOYSTICK2
+JOY_BUTTON_ANY = _misc_.JOY_BUTTON_ANY
+JOY_BUTTON1 = _misc_.JOY_BUTTON1
+JOY_BUTTON2 = _misc_.JOY_BUTTON2
+JOY_BUTTON3 = _misc_.JOY_BUTTON3
+JOY_BUTTON4 = _misc_.JOY_BUTTON4
+class Joystick(object):
+ """Proxy of C++ Joystick class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int joystick=JOYSTICK1) -> Joystick"""
+ _misc_.Joystick_swiginit(self,_misc_.new_Joystick(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_Joystick
+ __del__ = lambda self : None;
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point"""
+ return _misc_.Joystick_GetPosition(*args, **kwargs)
+
+ def GetZPosition(*args, **kwargs):
+ """GetZPosition(self) -> int"""
+ return _misc_.Joystick_GetZPosition(*args, **kwargs)
+
+ def GetButtonState(*args, **kwargs):
+ """GetButtonState(self) -> int"""
+ return _misc_.Joystick_GetButtonState(*args, **kwargs)
+
+ def GetPOVPosition(*args, **kwargs):
+ """GetPOVPosition(self) -> int"""
+ return _misc_.Joystick_GetPOVPosition(*args, **kwargs)
+
+ def GetPOVCTSPosition(*args, **kwargs):
+ """GetPOVCTSPosition(self) -> int"""
+ return _misc_.Joystick_GetPOVCTSPosition(*args, **kwargs)
+
+ def GetRudderPosition(*args, **kwargs):
+ """GetRudderPosition(self) -> int"""
+ return _misc_.Joystick_GetRudderPosition(*args, **kwargs)
+
+ def GetUPosition(*args, **kwargs):
+ """GetUPosition(self) -> int"""
+ return _misc_.Joystick_GetUPosition(*args, **kwargs)
+
+ def GetVPosition(*args, **kwargs):
+ """GetVPosition(self) -> int"""
+ return _misc_.Joystick_GetVPosition(*args, **kwargs)
+
+ def GetMovementThreshold(*args, **kwargs):
+ """GetMovementThreshold(self) -> int"""
+ return _misc_.Joystick_GetMovementThreshold(*args, **kwargs)
+
+ def SetMovementThreshold(*args, **kwargs):
+ """SetMovementThreshold(self, int threshold)"""
+ return _misc_.Joystick_SetMovementThreshold(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _misc_.Joystick_IsOk(*args, **kwargs)
+
+ def GetNumberJoysticks(*args, **kwargs):
+ """GetNumberJoysticks(self) -> int"""
+ return _misc_.Joystick_GetNumberJoysticks(*args, **kwargs)
+
+ def GetManufacturerId(*args, **kwargs):
+ """GetManufacturerId(self) -> int"""
+ return _misc_.Joystick_GetManufacturerId(*args, **kwargs)
+
+ def GetProductId(*args, **kwargs):
+ """GetProductId(self) -> int"""
+ return _misc_.Joystick_GetProductId(*args, **kwargs)
+
+ def GetProductName(*args, **kwargs):
+ """GetProductName(self) -> String"""
+ return _misc_.Joystick_GetProductName(*args, **kwargs)
+
+ def GetXMin(*args, **kwargs):
+ """GetXMin(self) -> int"""
+ return _misc_.Joystick_GetXMin(*args, **kwargs)
+
+ def GetYMin(*args, **kwargs):
+ """GetYMin(self) -> int"""
+ return _misc_.Joystick_GetYMin(*args, **kwargs)
+
+ def GetZMin(*args, **kwargs):
+ """GetZMin(self) -> int"""
+ return _misc_.Joystick_GetZMin(*args, **kwargs)
+
+ def GetXMax(*args, **kwargs):
+ """GetXMax(self) -> int"""
+ return _misc_.Joystick_GetXMax(*args, **kwargs)
+
+ def GetYMax(*args, **kwargs):
+ """GetYMax(self) -> int"""
+ return _misc_.Joystick_GetYMax(*args, **kwargs)
+
+ def GetZMax(*args, **kwargs):
+ """GetZMax(self) -> int"""
+ return _misc_.Joystick_GetZMax(*args, **kwargs)
+
+ def GetNumberButtons(*args, **kwargs):
+ """GetNumberButtons(self) -> int"""
+ return _misc_.Joystick_GetNumberButtons(*args, **kwargs)
+
+ def GetNumberAxes(*args, **kwargs):
+ """GetNumberAxes(self) -> int"""
+ return _misc_.Joystick_GetNumberAxes(*args, **kwargs)
+
+ def GetMaxButtons(*args, **kwargs):
+ """GetMaxButtons(self) -> int"""
+ return _misc_.Joystick_GetMaxButtons(*args, **kwargs)
+
+ def GetMaxAxes(*args, **kwargs):
+ """GetMaxAxes(self) -> int"""
+ return _misc_.Joystick_GetMaxAxes(*args, **kwargs)
+
+ def GetPollingMin(*args, **kwargs):
+ """GetPollingMin(self) -> int"""
+ return _misc_.Joystick_GetPollingMin(*args, **kwargs)
+
+ def GetPollingMax(*args, **kwargs):
+ """GetPollingMax(self) -> int"""
+ return _misc_.Joystick_GetPollingMax(*args, **kwargs)
+
+ def GetRudderMin(*args, **kwargs):
+ """GetRudderMin(self) -> int"""
+ return _misc_.Joystick_GetRudderMin(*args, **kwargs)
+
+ def GetRudderMax(*args, **kwargs):
+ """GetRudderMax(self) -> int"""
+ return _misc_.Joystick_GetRudderMax(*args, **kwargs)
+
+ def GetUMin(*args, **kwargs):
+ """GetUMin(self) -> int"""
+ return _misc_.Joystick_GetUMin(*args, **kwargs)
+
+ def GetUMax(*args, **kwargs):
+ """GetUMax(self) -> int"""
+ return _misc_.Joystick_GetUMax(*args, **kwargs)
+
+ def GetVMin(*args, **kwargs):
+ """GetVMin(self) -> int"""
+ return _misc_.Joystick_GetVMin(*args, **kwargs)
+
+ def GetVMax(*args, **kwargs):
+ """GetVMax(self) -> int"""
+ return _misc_.Joystick_GetVMax(*args, **kwargs)
+
+ def HasRudder(*args, **kwargs):
+ """HasRudder(self) -> bool"""
+ return _misc_.Joystick_HasRudder(*args, **kwargs)
+
+ def HasZ(*args, **kwargs):
+ """HasZ(self) -> bool"""
+ return _misc_.Joystick_HasZ(*args, **kwargs)
+
+ def HasU(*args, **kwargs):
+ """HasU(self) -> bool"""
+ return _misc_.Joystick_HasU(*args, **kwargs)
+
+ def HasV(*args, **kwargs):
+ """HasV(self) -> bool"""
+ return _misc_.Joystick_HasV(*args, **kwargs)
+
+ def HasPOV(*args, **kwargs):
+ """HasPOV(self) -> bool"""
+ return _misc_.Joystick_HasPOV(*args, **kwargs)
+
+ def HasPOV4Dir(*args, **kwargs):
+ """HasPOV4Dir(self) -> bool"""
+ return _misc_.Joystick_HasPOV4Dir(*args, **kwargs)
+
+ def HasPOVCTS(*args, **kwargs):
+ """HasPOVCTS(self) -> bool"""
+ return _misc_.Joystick_HasPOVCTS(*args, **kwargs)
+
+ def SetCapture(*args, **kwargs):
+ """SetCapture(self, Window win, int pollingFreq=0) -> bool"""
+ return _misc_.Joystick_SetCapture(*args, **kwargs)
+
+ def ReleaseCapture(*args, **kwargs):
+ """ReleaseCapture(self) -> bool"""
+ return _misc_.Joystick_ReleaseCapture(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ ButtonState = property(GetButtonState,doc="See `GetButtonState`")
+ ManufacturerId = property(GetManufacturerId,doc="See `GetManufacturerId`")
+ MaxAxes = property(GetMaxAxes,doc="See `GetMaxAxes`")
+ MaxButtons = property(GetMaxButtons,doc="See `GetMaxButtons`")
+ MovementThreshold = property(GetMovementThreshold,SetMovementThreshold,doc="See `GetMovementThreshold` and `SetMovementThreshold`")
+ NumberAxes = property(GetNumberAxes,doc="See `GetNumberAxes`")
+ NumberButtons = property(GetNumberButtons,doc="See `GetNumberButtons`")
+ NumberJoysticks = property(GetNumberJoysticks,doc="See `GetNumberJoysticks`")
+ POVCTSPosition = property(GetPOVCTSPosition,doc="See `GetPOVCTSPosition`")
+ POVPosition = property(GetPOVPosition,doc="See `GetPOVPosition`")
+ PollingMax = property(GetPollingMax,doc="See `GetPollingMax`")
+ PollingMin = property(GetPollingMin,doc="See `GetPollingMin`")
+ Position = property(GetPosition,doc="See `GetPosition`")
+ ProductId = property(GetProductId,doc="See `GetProductId`")
+ ProductName = property(GetProductName,doc="See `GetProductName`")
+ RudderMax = property(GetRudderMax,doc="See `GetRudderMax`")
+ RudderMin = property(GetRudderMin,doc="See `GetRudderMin`")
+ RudderPosition = property(GetRudderPosition,doc="See `GetRudderPosition`")
+ UMax = property(GetUMax,doc="See `GetUMax`")
+ UMin = property(GetUMin,doc="See `GetUMin`")
+ UPosition = property(GetUPosition,doc="See `GetUPosition`")
+ VMax = property(GetVMax,doc="See `GetVMax`")
+ VMin = property(GetVMin,doc="See `GetVMin`")
+ VPosition = property(GetVPosition,doc="See `GetVPosition`")
+ XMax = property(GetXMax,doc="See `GetXMax`")
+ XMin = property(GetXMin,doc="See `GetXMin`")
+ YMax = property(GetYMax,doc="See `GetYMax`")
+ YMin = property(GetYMin,doc="See `GetYMin`")
+ ZMax = property(GetZMax,doc="See `GetZMax`")
+ ZMin = property(GetZMin,doc="See `GetZMin`")
+ ZPosition = property(GetZPosition,doc="See `GetZPosition`")
+_misc_.Joystick_swigregister(Joystick)
+
+wxEVT_JOY_BUTTON_DOWN = _misc_.wxEVT_JOY_BUTTON_DOWN
+wxEVT_JOY_BUTTON_UP = _misc_.wxEVT_JOY_BUTTON_UP
+wxEVT_JOY_MOVE = _misc_.wxEVT_JOY_MOVE
+wxEVT_JOY_ZMOVE = _misc_.wxEVT_JOY_ZMOVE
+class JoystickEvent(_core.Event):
+ """Proxy of C++ JoystickEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType type=wxEVT_NULL, int state=0, int joystick=JOYSTICK1,
+ int change=0) -> JoystickEvent
+ """
+ _misc_.JoystickEvent_swiginit(self,_misc_.new_JoystickEvent(*args, **kwargs))
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point"""
+ return _misc_.JoystickEvent_GetPosition(*args, **kwargs)
+
+ def GetZPosition(*args, **kwargs):
+ """GetZPosition(self) -> int"""
+ return _misc_.JoystickEvent_GetZPosition(*args, **kwargs)
+
+ def GetButtonState(*args, **kwargs):
+ """GetButtonState(self) -> int"""
+ return _misc_.JoystickEvent_GetButtonState(*args, **kwargs)
+
+ def GetButtonChange(*args, **kwargs):
+ """GetButtonChange(self) -> int"""
+ return _misc_.JoystickEvent_GetButtonChange(*args, **kwargs)
+
+ def GetJoystick(*args, **kwargs):
+ """GetJoystick(self) -> int"""
+ return _misc_.JoystickEvent_GetJoystick(*args, **kwargs)
+
+ def SetJoystick(*args, **kwargs):
+ """SetJoystick(self, int stick)"""
+ return _misc_.JoystickEvent_SetJoystick(*args, **kwargs)
+
+ def SetButtonState(*args, **kwargs):
+ """SetButtonState(self, int state)"""
+ return _misc_.JoystickEvent_SetButtonState(*args, **kwargs)
+
+ def SetButtonChange(*args, **kwargs):
+ """SetButtonChange(self, int change)"""
+ return _misc_.JoystickEvent_SetButtonChange(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, Point pos)"""
+ return _misc_.JoystickEvent_SetPosition(*args, **kwargs)
+
+ def SetZPosition(*args, **kwargs):
+ """SetZPosition(self, int zPos)"""
+ return _misc_.JoystickEvent_SetZPosition(*args, **kwargs)
+
+ def IsButton(*args, **kwargs):
+ """IsButton(self) -> bool"""
+ return _misc_.JoystickEvent_IsButton(*args, **kwargs)
+
+ def IsMove(*args, **kwargs):
+ """IsMove(self) -> bool"""
+ return _misc_.JoystickEvent_IsMove(*args, **kwargs)
+
+ def IsZMove(*args, **kwargs):
+ """IsZMove(self) -> bool"""
+ return _misc_.JoystickEvent_IsZMove(*args, **kwargs)
+
+ def ButtonDown(*args, **kwargs):
+ """ButtonDown(self, int but=JOY_BUTTON_ANY) -> bool"""
+ return _misc_.JoystickEvent_ButtonDown(*args, **kwargs)
+
+ def ButtonUp(*args, **kwargs):
+ """ButtonUp(self, int but=JOY_BUTTON_ANY) -> bool"""
+ return _misc_.JoystickEvent_ButtonUp(*args, **kwargs)
+
+ def ButtonIsDown(*args, **kwargs):
+ """ButtonIsDown(self, int but=JOY_BUTTON_ANY) -> bool"""
+ return _misc_.JoystickEvent_ButtonIsDown(*args, **kwargs)
+
+ m_pos = property(GetPosition, SetPosition)
+ m_zPosition = property(GetZPosition, SetZPosition)
+ m_buttonChange = property(GetButtonChange, SetButtonChange)
+ m_buttonState = property(GetButtonState, SetButtonState)
+ m_joyStick = property(GetJoystick, SetJoystick)
+
+ ButtonChange = property(GetButtonChange,SetButtonChange,doc="See `GetButtonChange` and `SetButtonChange`")
+ ButtonState = property(GetButtonState,SetButtonState,doc="See `GetButtonState` and `SetButtonState`")
+ Joystick = property(GetJoystick,SetJoystick,doc="See `GetJoystick` and `SetJoystick`")
+ Position = property(GetPosition,SetPosition,doc="See `GetPosition` and `SetPosition`")
+ ZPosition = property(GetZPosition,SetZPosition,doc="See `GetZPosition` and `SetZPosition`")
+_misc_.JoystickEvent_swigregister(JoystickEvent)
+
+EVT_JOY_BUTTON_DOWN = wx.PyEventBinder( wxEVT_JOY_BUTTON_DOWN )
+EVT_JOY_BUTTON_UP = wx.PyEventBinder( wxEVT_JOY_BUTTON_UP )
+EVT_JOY_MOVE = wx.PyEventBinder( wxEVT_JOY_MOVE )
+EVT_JOY_ZMOVE = wx.PyEventBinder( wxEVT_JOY_ZMOVE )
+
+EVT_JOYSTICK_EVENTS = wx.PyEventBinder([ wxEVT_JOY_BUTTON_DOWN,
+ wxEVT_JOY_BUTTON_UP,
+ wxEVT_JOY_MOVE,
+ wxEVT_JOY_ZMOVE,
+ ])
+
+
+#---------------------------------------------------------------------------
+
+SOUND_SYNC = _misc_.SOUND_SYNC
+SOUND_ASYNC = _misc_.SOUND_ASYNC
+SOUND_LOOP = _misc_.SOUND_LOOP
+class Sound(object):
+ """Proxy of C++ Sound class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String fileName=EmptyString) -> Sound"""
+ _misc_.Sound_swiginit(self,_misc_.new_Sound(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_Sound
+ __del__ = lambda self : None;
+ def Create(*args, **kwargs):
+ """Create(self, String fileName) -> bool"""
+ return _misc_.Sound_Create(*args, **kwargs)
+
+ def CreateFromData(*args, **kwargs):
+ """CreateFromData(self, PyObject data) -> bool"""
+ return _misc_.Sound_CreateFromData(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _misc_.Sound_IsOk(*args, **kwargs)
+
+ def Play(*args, **kwargs):
+ """Play(self, unsigned int flags=SOUND_ASYNC) -> bool"""
+ return _misc_.Sound_Play(*args, **kwargs)
+
+ def PlaySound(*args, **kwargs):
+ """PlaySound(String filename, unsigned int flags=SOUND_ASYNC) -> bool"""
+ return _misc_.Sound_PlaySound(*args, **kwargs)
+
+ PlaySound = staticmethod(PlaySound)
+ def Stop(*args, **kwargs):
+ """Stop()"""
+ return _misc_.Sound_Stop(*args, **kwargs)
+
+ Stop = staticmethod(Stop)
+ def __nonzero__(self): return self.IsOk()
+_misc_.Sound_swigregister(Sound)
+
+def SoundFromData(*args, **kwargs):
+ """SoundFromData(PyObject data) -> Sound"""
+ val = _misc_.new_SoundFromData(*args, **kwargs)
+ return val
+
+def Sound_PlaySound(*args, **kwargs):
+ """Sound_PlaySound(String filename, unsigned int flags=SOUND_ASYNC) -> bool"""
+ return _misc_.Sound_PlaySound(*args, **kwargs)
+
+def Sound_Stop(*args):
+ """Sound_Stop()"""
+ return _misc_.Sound_Stop(*args)
+
+#---------------------------------------------------------------------------
+
+MAILCAP_STANDARD = _misc_.MAILCAP_STANDARD
+MAILCAP_NETSCAPE = _misc_.MAILCAP_NETSCAPE
+MAILCAP_KDE = _misc_.MAILCAP_KDE
+MAILCAP_GNOME = _misc_.MAILCAP_GNOME
+MAILCAP_ALL = _misc_.MAILCAP_ALL
+class FileTypeInfo(object):
+ """Proxy of C++ FileTypeInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String mimeType, String openCmd, String printCmd, String desc) -> FileTypeInfo"""
+ _misc_.FileTypeInfo_swiginit(self,_misc_.new_FileTypeInfo(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_FileTypeInfo
+ __del__ = lambda self : None;
+ def IsValid(*args, **kwargs):
+ """IsValid(self) -> bool"""
+ return _misc_.FileTypeInfo_IsValid(*args, **kwargs)
+
+ def SetIcon(*args, **kwargs):
+ """SetIcon(self, String iconFile, int iconIndex=0)"""
+ return _misc_.FileTypeInfo_SetIcon(*args, **kwargs)
+
+ def SetShortDesc(*args, **kwargs):
+ """SetShortDesc(self, String shortDesc)"""
+ return _misc_.FileTypeInfo_SetShortDesc(*args, **kwargs)
+
+ def GetMimeType(*args, **kwargs):
+ """GetMimeType(self) -> String"""
+ return _misc_.FileTypeInfo_GetMimeType(*args, **kwargs)
+
+ def GetOpenCommand(*args, **kwargs):
+ """GetOpenCommand(self) -> String"""
+ return _misc_.FileTypeInfo_GetOpenCommand(*args, **kwargs)
+
+ def GetPrintCommand(*args, **kwargs):
+ """GetPrintCommand(self) -> String"""
+ return _misc_.FileTypeInfo_GetPrintCommand(*args, **kwargs)
+
+ def GetShortDesc(*args, **kwargs):
+ """GetShortDesc(self) -> String"""
+ return _misc_.FileTypeInfo_GetShortDesc(*args, **kwargs)
+
+ def GetDescription(*args, **kwargs):
+ """GetDescription(self) -> String"""
+ return _misc_.FileTypeInfo_GetDescription(*args, **kwargs)
+
+ def GetExtensions(*args, **kwargs):
+ """GetExtensions(self) -> wxArrayString"""
+ return _misc_.FileTypeInfo_GetExtensions(*args, **kwargs)
+
+ def GetExtensionsCount(*args, **kwargs):
+ """GetExtensionsCount(self) -> size_t"""
+ return _misc_.FileTypeInfo_GetExtensionsCount(*args, **kwargs)
+
+ def GetIconFile(*args, **kwargs):
+ """GetIconFile(self) -> String"""
+ return _misc_.FileTypeInfo_GetIconFile(*args, **kwargs)
+
+ def GetIconIndex(*args, **kwargs):
+ """GetIconIndex(self) -> int"""
+ return _misc_.FileTypeInfo_GetIconIndex(*args, **kwargs)
+
+ Description = property(GetDescription,doc="See `GetDescription`")
+ Extensions = property(GetExtensions,doc="See `GetExtensions`")
+ ExtensionsCount = property(GetExtensionsCount,doc="See `GetExtensionsCount`")
+ IconFile = property(GetIconFile,doc="See `GetIconFile`")
+ IconIndex = property(GetIconIndex,doc="See `GetIconIndex`")
+ MimeType = property(GetMimeType,doc="See `GetMimeType`")
+ OpenCommand = property(GetOpenCommand,doc="See `GetOpenCommand`")
+ PrintCommand = property(GetPrintCommand,doc="See `GetPrintCommand`")
+ ShortDesc = property(GetShortDesc,SetShortDesc,doc="See `GetShortDesc` and `SetShortDesc`")
+_misc_.FileTypeInfo_swigregister(FileTypeInfo)
+
+def FileTypeInfoSequence(*args, **kwargs):
+ """FileTypeInfoSequence(wxArrayString sArray) -> FileTypeInfo"""
+ val = _misc_.new_FileTypeInfoSequence(*args, **kwargs)
+ return val
+
+def NullFileTypeInfo(*args, **kwargs):
+ """NullFileTypeInfo() -> FileTypeInfo"""
+ val = _misc_.new_NullFileTypeInfo(*args, **kwargs)
+ return val
+
+class FileType(object):
+ """Proxy of C++ FileType class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, FileTypeInfo ftInfo) -> FileType"""
+ _misc_.FileType_swiginit(self,_misc_.new_FileType(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_FileType
+ __del__ = lambda self : None;
+ def GetMimeType(*args, **kwargs):
+ """GetMimeType(self) -> PyObject"""
+ return _misc_.FileType_GetMimeType(*args, **kwargs)
+
+ def GetMimeTypes(*args, **kwargs):
+ """GetMimeTypes(self) -> PyObject"""
+ return _misc_.FileType_GetMimeTypes(*args, **kwargs)
+
+ def GetExtensions(*args, **kwargs):
+ """GetExtensions(self) -> PyObject"""
+ return _misc_.FileType_GetExtensions(*args, **kwargs)
+
+ def GetIcon(*args, **kwargs):
+ """GetIcon(self) -> Icon"""
+ return _misc_.FileType_GetIcon(*args, **kwargs)
+
+ def GetIconInfo(*args, **kwargs):
+ """GetIconInfo(self) -> PyObject"""
+ return _misc_.FileType_GetIconInfo(*args, **kwargs)
+
+ def GetDescription(*args, **kwargs):
+ """GetDescription(self) -> PyObject"""
+ return _misc_.FileType_GetDescription(*args, **kwargs)
+
+ def GetOpenCommand(*args, **kwargs):
+ """GetOpenCommand(self, String filename, String mimetype=EmptyString) -> PyObject"""
+ return _misc_.FileType_GetOpenCommand(*args, **kwargs)
+
+ def GetPrintCommand(*args, **kwargs):
+ """GetPrintCommand(self, String filename, String mimetype=EmptyString) -> PyObject"""
+ return _misc_.FileType_GetPrintCommand(*args, **kwargs)
+
+ def GetAllCommands(*args, **kwargs):
+ """GetAllCommands(self, String filename, String mimetype=EmptyString) -> PyObject"""
+ return _misc_.FileType_GetAllCommands(*args, **kwargs)
+
+ def SetCommand(*args, **kwargs):
+ """SetCommand(self, String cmd, String verb, bool overwriteprompt=True) -> bool"""
+ return _misc_.FileType_SetCommand(*args, **kwargs)
+
+ def SetDefaultIcon(*args, **kwargs):
+ """SetDefaultIcon(self, String cmd=EmptyString, int index=0) -> bool"""
+ return _misc_.FileType_SetDefaultIcon(*args, **kwargs)
+
+ def Unassociate(*args, **kwargs):
+ """Unassociate(self) -> bool"""
+ return _misc_.FileType_Unassociate(*args, **kwargs)
+
+ def ExpandCommand(*args, **kwargs):
+ """ExpandCommand(String command, String filename, String mimetype=EmptyString) -> String"""
+ return _misc_.FileType_ExpandCommand(*args, **kwargs)
+
+ ExpandCommand = staticmethod(ExpandCommand)
+ AllCommands = property(GetAllCommands,doc="See `GetAllCommands`")
+ Description = property(GetDescription,doc="See `GetDescription`")
+ Extensions = property(GetExtensions,doc="See `GetExtensions`")
+ Icon = property(GetIcon,doc="See `GetIcon`")
+ IconInfo = property(GetIconInfo,doc="See `GetIconInfo`")
+ MimeType = property(GetMimeType,doc="See `GetMimeType`")
+ MimeTypes = property(GetMimeTypes,doc="See `GetMimeTypes`")
+ OpenCommand = property(GetOpenCommand,doc="See `GetOpenCommand`")
+ PrintCommand = property(GetPrintCommand,doc="See `GetPrintCommand`")
+_misc_.FileType_swigregister(FileType)
+
+def FileType_ExpandCommand(*args, **kwargs):
+ """FileType_ExpandCommand(String command, String filename, String mimetype=EmptyString) -> String"""
+ return _misc_.FileType_ExpandCommand(*args, **kwargs)
+
+class MimeTypesManager(object):
+ """Proxy of C++ MimeTypesManager class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def IsOfType(*args, **kwargs):
+ """IsOfType(String mimeType, String wildcard) -> bool"""
+ return _misc_.MimeTypesManager_IsOfType(*args, **kwargs)
+
+ IsOfType = staticmethod(IsOfType)
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> MimeTypesManager"""
+ _misc_.MimeTypesManager_swiginit(self,_misc_.new_MimeTypesManager(*args, **kwargs))
+ def Initialize(*args, **kwargs):
+ """Initialize(self, int mailcapStyle=MAILCAP_ALL, String extraDir=EmptyString)"""
+ return _misc_.MimeTypesManager_Initialize(*args, **kwargs)
+
+ def ClearData(*args, **kwargs):
+ """ClearData(self)"""
+ return _misc_.MimeTypesManager_ClearData(*args, **kwargs)
+
+ def GetFileTypeFromExtension(*args, **kwargs):
+ """GetFileTypeFromExtension(self, String ext) -> FileType"""
+ return _misc_.MimeTypesManager_GetFileTypeFromExtension(*args, **kwargs)
+
+ def GetFileTypeFromMimeType(*args, **kwargs):
+ """GetFileTypeFromMimeType(self, String mimeType) -> FileType"""
+ return _misc_.MimeTypesManager_GetFileTypeFromMimeType(*args, **kwargs)
+
+ def EnumAllFileTypes(*args, **kwargs):
+ """EnumAllFileTypes(self) -> PyObject"""
+ return _misc_.MimeTypesManager_EnumAllFileTypes(*args, **kwargs)
+
+ def AddFallback(*args, **kwargs):
+ """AddFallback(self, FileTypeInfo ft)"""
+ return _misc_.MimeTypesManager_AddFallback(*args, **kwargs)
+
+ def Associate(*args, **kwargs):
+ """Associate(self, FileTypeInfo ftInfo) -> FileType"""
+ return _misc_.MimeTypesManager_Associate(*args, **kwargs)
+
+ def Unassociate(*args, **kwargs):
+ """Unassociate(self, FileType ft) -> bool"""
+ return _misc_.MimeTypesManager_Unassociate(*args, **kwargs)
+
+ __swig_destroy__ = _misc_.delete_MimeTypesManager
+ __del__ = lambda self : None;
+_misc_.MimeTypesManager_swigregister(MimeTypesManager)
+TheMimeTypesManager = cvar.TheMimeTypesManager
+
+def MimeTypesManager_IsOfType(*args, **kwargs):
+ """MimeTypesManager_IsOfType(String mimeType, String wildcard) -> bool"""
+ return _misc_.MimeTypesManager_IsOfType(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class ArtProvider(object):
+ """
+ The wx.ArtProvider class is used to customize the look of wxWidgets
+ application. When wxWidgets needs to display an icon or a bitmap (e.g.
+ in the standard file dialog), it does not use hard-coded resource but
+ asks wx.ArtProvider for it instead. This way the users can plug in
+ their own wx.ArtProvider class and easily replace standard art with
+ his/her own version. It is easy thing to do: all that is needed is
+ to derive a class from wx.ArtProvider, override it's CreateBitmap
+ method and register the provider with `wx.ArtProvider.Push`::
+
+ class MyArtProvider(wx.ArtProvider):
+ def __init__(self):
+ wx.ArtProvider.__init__(self)
+
+ def CreateBitmap(self, artid, client, size):
+ ...
+ return bmp
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> ArtProvider
+
+ The wx.ArtProvider class is used to customize the look of wxWidgets
+ application. When wxWidgets needs to display an icon or a bitmap (e.g.
+ in the standard file dialog), it does not use hard-coded resource but
+ asks wx.ArtProvider for it instead. This way the users can plug in
+ their own wx.ArtProvider class and easily replace standard art with
+ his/her own version. It is easy thing to do: all that is needed is
+ to derive a class from wx.ArtProvider, override it's CreateBitmap
+ method and register the provider with `wx.ArtProvider.Push`::
+
+ class MyArtProvider(wx.ArtProvider):
+ def __init__(self):
+ wx.ArtProvider.__init__(self)
+
+ def CreateBitmap(self, artid, client, size):
+ ...
+ return bmp
+
+ """
+ _misc_.ArtProvider_swiginit(self,_misc_.new_ArtProvider(*args, **kwargs))
+ ArtProvider._setCallbackInfo(self, self, ArtProvider)
+
+ __swig_destroy__ = _misc_.delete_ArtProvider
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _misc_.ArtProvider__setCallbackInfo(*args, **kwargs)
+
+ def HasNativeProvider(*args, **kwargs):
+ """
+ HasNativeProvider() -> bool
+
+ Does this platform implement native icons theme?
+ """
+ return _misc_.ArtProvider_HasNativeProvider(*args, **kwargs)
+
+ HasNativeProvider = staticmethod(HasNativeProvider)
+ def Push(*args, **kwargs):
+ """
+ Push(ArtProvider provider)
+
+ Add new provider to the top of providers stack.
+ """
+ return _misc_.ArtProvider_Push(*args, **kwargs)
+
+ Push = staticmethod(Push)
+ PushProvider = Push
+ def PushBack(*args, **kwargs):
+ """
+ PushBack(wxArtProvider provider)
+
+ Add new provider to the bottom of providers stack (i.e. the provider
+ will be queried as the last one).
+ """
+ return _misc_.ArtProvider_PushBack(*args, **kwargs)
+
+ PushBack = staticmethod(PushBack)
+ def Insert(*args, **kwargs):
+ """
+ Insert(ArtProvider provider)
+
+ Add new provider to the bottom of providers stack.
+ """
+ return _misc_.ArtProvider_Insert(*args, **kwargs)
+
+ Insert = staticmethod(Insert)
+ InsertProvider = Insert
+ def Pop(*args, **kwargs):
+ """
+ Pop() -> bool
+
+ Remove latest added provider and delete it.
+ """
+ return _misc_.ArtProvider_Pop(*args, **kwargs)
+
+ Pop = staticmethod(Pop)
+ PopProvider = Pop
+ def Delete(*args, **kwargs):
+ """
+ Delete(ArtProvider provider) -> bool
+
+ Remove provider. The provider must have been added previously! The
+ provider is _not_ deleted.
+ """
+ val = _misc_.ArtProvider_Delete(*args, **kwargs)
+ args[1].thisown = 1
+ return val
+
+ Delete = staticmethod(Delete)
+ RemoveProvider = Delete
+ def GetBitmap(*args, **kwargs):
+ """
+ GetBitmap(String id, String client=ART_OTHER, Size size=DefaultSize) -> Bitmap
+
+ Query the providers for bitmap with given ID and return it. Return
+ wx.NullBitmap if no provider provides it.
+ """
+ return _misc_.ArtProvider_GetBitmap(*args, **kwargs)
+
+ GetBitmap = staticmethod(GetBitmap)
+ def GetIcon(*args, **kwargs):
+ """
+ GetIcon(String id, String client=ART_OTHER, Size size=DefaultSize) -> Icon
+
+ Query the providers for icon with given ID and return it. Return
+ wx.NullIcon if no provider provides it.
+ """
+ return _misc_.ArtProvider_GetIcon(*args, **kwargs)
+
+ GetIcon = staticmethod(GetIcon)
+ def GetMessageBoxIconId(*args, **kwargs):
+ """GetMessageBoxIconId(int flags) -> wxArtID"""
+ return _misc_.ArtProvider_GetMessageBoxIconId(*args, **kwargs)
+
+ GetMessageBoxIconId = staticmethod(GetMessageBoxIconId)
+ def GetMessageBoxIcon(*args, **kwargs):
+ """
+ GetMessageBoxIcon(int flags) -> Icon
+
+ Helper used by several generic classes: return the icon corresponding
+ to the standard wx.ICON_INFORMATION/WARNING/ERROR/QUESTION flags (only
+ one can be set)
+ """
+ return _misc_.ArtProvider_GetMessageBoxIcon(*args, **kwargs)
+
+ GetMessageBoxIcon = staticmethod(GetMessageBoxIcon)
+ def GetIconBundle(*args, **kwargs):
+ """
+ GetIconBundle(wxArtID id, wxArtClient client=wxART_OTHER) -> wxIconBundle
+
+ Query the providers for iconbundle with given ID and return it. Return
+ wx.NullIconBundle if no provider provides it.
+ """
+ return _misc_.ArtProvider_GetIconBundle(*args, **kwargs)
+
+ GetIconBundle = staticmethod(GetIconBundle)
+ def GetNativeSizeHint(*args, **kwargs):
+ """
+ GetNativeSizeHint(wxArtClient client) -> Size
+
+ Gets native size for given 'client' or wxDefaultSize if it doesn't
+ have native equivalent.
+ """
+ return _misc_.ArtProvider_GetNativeSizeHint(*args, **kwargs)
+
+ GetNativeSizeHint = staticmethod(GetNativeSizeHint)
+ def GetSizeHint(*args, **kwargs):
+ """
+ GetSizeHint(String client, bool platform_dependent=False) -> Size
+
+ Get the size hint of an icon from a specific Art Client, queries the
+ topmost provider if platform_dependent = false
+ """
+ return _misc_.ArtProvider_GetSizeHint(*args, **kwargs)
+
+ GetSizeHint = staticmethod(GetSizeHint)
+ def Destroy(*args, **kwargs):
+ """Destroy(self)"""
+ args[0].this.own(False)
+ return _misc_.ArtProvider_Destroy(*args, **kwargs)
+
+_misc_.ArtProvider_swigregister(ArtProvider)
+ART_TOOLBAR = cvar.ART_TOOLBAR
+ART_MENU = cvar.ART_MENU
+ART_FRAME_ICON = cvar.ART_FRAME_ICON
+ART_CMN_DIALOG = cvar.ART_CMN_DIALOG
+ART_HELP_BROWSER = cvar.ART_HELP_BROWSER
+ART_MESSAGE_BOX = cvar.ART_MESSAGE_BOX
+ART_BUTTON = cvar.ART_BUTTON
+ART_LIST = cvar.ART_LIST
+ART_OTHER = cvar.ART_OTHER
+ART_ADD_BOOKMARK = cvar.ART_ADD_BOOKMARK
+ART_DEL_BOOKMARK = cvar.ART_DEL_BOOKMARK
+ART_HELP_SIDE_PANEL = cvar.ART_HELP_SIDE_PANEL
+ART_HELP_SETTINGS = cvar.ART_HELP_SETTINGS
+ART_HELP_BOOK = cvar.ART_HELP_BOOK
+ART_HELP_FOLDER = cvar.ART_HELP_FOLDER
+ART_HELP_PAGE = cvar.ART_HELP_PAGE
+ART_GO_BACK = cvar.ART_GO_BACK
+ART_GO_FORWARD = cvar.ART_GO_FORWARD
+ART_GO_UP = cvar.ART_GO_UP
+ART_GO_DOWN = cvar.ART_GO_DOWN
+ART_GO_TO_PARENT = cvar.ART_GO_TO_PARENT
+ART_GO_HOME = cvar.ART_GO_HOME
+ART_GOTO_FIRST = cvar.ART_GOTO_FIRST
+ART_GOTO_LAST = cvar.ART_GOTO_LAST
+ART_FILE_OPEN = cvar.ART_FILE_OPEN
+ART_FILE_SAVE = cvar.ART_FILE_SAVE
+ART_FILE_SAVE_AS = cvar.ART_FILE_SAVE_AS
+ART_PRINT = cvar.ART_PRINT
+ART_HELP = cvar.ART_HELP
+ART_TIP = cvar.ART_TIP
+ART_REPORT_VIEW = cvar.ART_REPORT_VIEW
+ART_LIST_VIEW = cvar.ART_LIST_VIEW
+ART_NEW_DIR = cvar.ART_NEW_DIR
+ART_HARDDISK = cvar.ART_HARDDISK
+ART_FLOPPY = cvar.ART_FLOPPY
+ART_CDROM = cvar.ART_CDROM
+ART_REMOVABLE = cvar.ART_REMOVABLE
+ART_FOLDER = cvar.ART_FOLDER
+ART_FOLDER_OPEN = cvar.ART_FOLDER_OPEN
+ART_GO_DIR_UP = cvar.ART_GO_DIR_UP
+ART_EXECUTABLE_FILE = cvar.ART_EXECUTABLE_FILE
+ART_NORMAL_FILE = cvar.ART_NORMAL_FILE
+ART_TICK_MARK = cvar.ART_TICK_MARK
+ART_CROSS_MARK = cvar.ART_CROSS_MARK
+ART_ERROR = cvar.ART_ERROR
+ART_QUESTION = cvar.ART_QUESTION
+ART_WARNING = cvar.ART_WARNING
+ART_INFORMATION = cvar.ART_INFORMATION
+ART_MISSING_IMAGE = cvar.ART_MISSING_IMAGE
+ART_COPY = cvar.ART_COPY
+ART_CUT = cvar.ART_CUT
+ART_PASTE = cvar.ART_PASTE
+ART_DELETE = cvar.ART_DELETE
+ART_NEW = cvar.ART_NEW
+ART_UNDO = cvar.ART_UNDO
+ART_REDO = cvar.ART_REDO
+ART_PLUS = cvar.ART_PLUS
+ART_MINUS = cvar.ART_MINUS
+ART_CLOSE = cvar.ART_CLOSE
+ART_QUIT = cvar.ART_QUIT
+ART_FIND = cvar.ART_FIND
+ART_FIND_AND_REPLACE = cvar.ART_FIND_AND_REPLACE
+
+def ArtProvider_HasNativeProvider(*args):
+ """
+ ArtProvider_HasNativeProvider() -> bool
+
+ Does this platform implement native icons theme?
+ """
+ return _misc_.ArtProvider_HasNativeProvider(*args)
+
+def ArtProvider_Push(*args, **kwargs):
+ """
+ ArtProvider_Push(ArtProvider provider)
+
+ Add new provider to the top of providers stack.
+ """
+ return _misc_.ArtProvider_Push(*args, **kwargs)
+
+def ArtProvider_PushBack(*args, **kwargs):
+ """
+ ArtProvider_PushBack(wxArtProvider provider)
+
+ Add new provider to the bottom of providers stack (i.e. the provider
+ will be queried as the last one).
+ """
+ return _misc_.ArtProvider_PushBack(*args, **kwargs)
+
+def ArtProvider_Insert(*args, **kwargs):
+ """
+ ArtProvider_Insert(ArtProvider provider)
+
+ Add new provider to the bottom of providers stack.
+ """
+ return _misc_.ArtProvider_Insert(*args, **kwargs)
+
+def ArtProvider_Pop(*args):
+ """
+ ArtProvider_Pop() -> bool
+
+ Remove latest added provider and delete it.
+ """
+ return _misc_.ArtProvider_Pop(*args)
+
+def ArtProvider_Delete(*args, **kwargs):
+ """
+ ArtProvider_Delete(ArtProvider provider) -> bool
+
+ Remove provider. The provider must have been added previously! The
+ provider is _not_ deleted.
+ """
+ val = _misc_.ArtProvider_Delete(*args, **kwargs)
+ args[1].thisown = 1
+ return val
+
+def ArtProvider_GetBitmap(*args, **kwargs):
+ """
+ ArtProvider_GetBitmap(String id, String client=ART_OTHER, Size size=DefaultSize) -> Bitmap
+
+ Query the providers for bitmap with given ID and return it. Return
+ wx.NullBitmap if no provider provides it.
+ """
+ return _misc_.ArtProvider_GetBitmap(*args, **kwargs)
+
+def ArtProvider_GetIcon(*args, **kwargs):
+ """
+ ArtProvider_GetIcon(String id, String client=ART_OTHER, Size size=DefaultSize) -> Icon
+
+ Query the providers for icon with given ID and return it. Return
+ wx.NullIcon if no provider provides it.
+ """
+ return _misc_.ArtProvider_GetIcon(*args, **kwargs)
+
+def ArtProvider_GetMessageBoxIconId(*args, **kwargs):
+ """ArtProvider_GetMessageBoxIconId(int flags) -> wxArtID"""
+ return _misc_.ArtProvider_GetMessageBoxIconId(*args, **kwargs)
+
+def ArtProvider_GetMessageBoxIcon(*args, **kwargs):
+ """
+ ArtProvider_GetMessageBoxIcon(int flags) -> Icon
+
+ Helper used by several generic classes: return the icon corresponding
+ to the standard wx.ICON_INFORMATION/WARNING/ERROR/QUESTION flags (only
+ one can be set)
+ """
+ return _misc_.ArtProvider_GetMessageBoxIcon(*args, **kwargs)
+
+def ArtProvider_GetIconBundle(*args, **kwargs):
+ """
+ ArtProvider_GetIconBundle(wxArtID id, wxArtClient client=wxART_OTHER) -> wxIconBundle
+
+ Query the providers for iconbundle with given ID and return it. Return
+ wx.NullIconBundle if no provider provides it.
+ """
+ return _misc_.ArtProvider_GetIconBundle(*args, **kwargs)
+
+def ArtProvider_GetNativeSizeHint(*args, **kwargs):
+ """
+ ArtProvider_GetNativeSizeHint(wxArtClient client) -> Size
+
+ Gets native size for given 'client' or wxDefaultSize if it doesn't
+ have native equivalent.
+ """
+ return _misc_.ArtProvider_GetNativeSizeHint(*args, **kwargs)
+
+def ArtProvider_GetSizeHint(*args, **kwargs):
+ """
+ ArtProvider_GetSizeHint(String client, bool platform_dependent=False) -> Size
+
+ Get the size hint of an icon from a specific Art Client, queries the
+ topmost provider if platform_dependent = false
+ """
+ return _misc_.ArtProvider_GetSizeHint(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+CONFIG_USE_LOCAL_FILE = _misc_.CONFIG_USE_LOCAL_FILE
+CONFIG_USE_GLOBAL_FILE = _misc_.CONFIG_USE_GLOBAL_FILE
+CONFIG_USE_RELATIVE_PATH = _misc_.CONFIG_USE_RELATIVE_PATH
+CONFIG_USE_NO_ESCAPE_CHARACTERS = _misc_.CONFIG_USE_NO_ESCAPE_CHARACTERS
+CONFIG_USE_SUBDIR = _misc_.CONFIG_USE_SUBDIR
+class ConfigBase(object):
+ """
+ wx.ConfigBase class defines the basic interface of all config
+ classes. It can not be used by itself (it is an abstract base class)
+ and you will always use one of its derivations: wx.Config or
+ wx.FileConfig.
+
+ wx.ConfigBase organizes the items in a tree-like structure, modeled
+ after the Unix/Dos filesystem. There are groups that act like
+ directories and entries, key/value pairs that act like files. There
+ is always one current group given by the current path. As in the file
+ system case, to specify a key in the config class you must use a path
+ to it. Config classes also support the notion of the current group,
+ which makes it possible to use relative paths.
+
+ Keys are pairs "key_name = value" where value may be of string,
+ integer floating point or boolean, you can not store binary data
+ without first encoding it as a string. For performance reasons items
+ should be kept small, no more than a couple kilobytes.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _misc_.delete_ConfigBase
+ __del__ = lambda self : None;
+ Type_Unknown = _misc_.ConfigBase_Type_Unknown
+ Type_String = _misc_.ConfigBase_Type_String
+ Type_Boolean = _misc_.ConfigBase_Type_Boolean
+ Type_Integer = _misc_.ConfigBase_Type_Integer
+ Type_Float = _misc_.ConfigBase_Type_Float
+ def Set(*args, **kwargs):
+ """
+ Set(ConfigBase config) -> ConfigBase
+
+ Sets the global config object (the one returned by Get) and returns a
+ reference to the previous global config object.
+ """
+ return _misc_.ConfigBase_Set(*args, **kwargs)
+
+ Set = staticmethod(Set)
+ def Get(*args, **kwargs):
+ """
+ Get(bool createOnDemand=True) -> ConfigBase
+
+ Returns the current global config object, creating one if neccessary.
+ """
+ return _misc_.ConfigBase_Get(*args, **kwargs)
+
+ Get = staticmethod(Get)
+ def Create(*args, **kwargs):
+ """
+ Create() -> ConfigBase
+
+ Create and return a new global config object. This function will
+ create the "best" implementation of wx.Config available for the
+ current platform.
+ """
+ return _misc_.ConfigBase_Create(*args, **kwargs)
+
+ Create = staticmethod(Create)
+ def DontCreateOnDemand(*args, **kwargs):
+ """
+ DontCreateOnDemand()
+
+ Should Get() try to create a new log object if there isn't a current
+ one?
+ """
+ return _misc_.ConfigBase_DontCreateOnDemand(*args, **kwargs)
+
+ DontCreateOnDemand = staticmethod(DontCreateOnDemand)
+ def SetPath(*args, **kwargs):
+ """
+ SetPath(self, String path)
+
+ Set current path: if the first character is '/', it's the absolute
+ path, otherwise it's a relative path. '..' is supported. If the
+ strPath doesn't exist it is created.
+ """
+ return _misc_.ConfigBase_SetPath(*args, **kwargs)
+
+ def GetPath(*args, **kwargs):
+ """
+ GetPath(self) -> String
+
+ Retrieve the current path (always as absolute path)
+ """
+ return _misc_.ConfigBase_GetPath(*args, **kwargs)
+
+ def GetFirstGroup(*args, **kwargs):
+ """
+ GetFirstGroup() -> (more, value, index)
+
+ Allows enumerating the subgroups in a config object. Returns a tuple
+ containing a flag indicating there are more items, the name of the
+ current item, and an index to pass to GetNextGroup to fetch the next
+ item.
+ """
+ return _misc_.ConfigBase_GetFirstGroup(*args, **kwargs)
+
+ def GetNextGroup(*args, **kwargs):
+ """
+ GetNextGroup(long index) -> (more, value, index)
+
+ Allows enumerating the subgroups in a config object. Returns a tuple
+ containing a flag indicating there are more items, the name of the
+ current item, and an index to pass to GetNextGroup to fetch the next
+ item.
+ """
+ return _misc_.ConfigBase_GetNextGroup(*args, **kwargs)
+
+ def GetFirstEntry(*args, **kwargs):
+ """
+ GetFirstEntry() -> (more, value, index)
+
+ Allows enumerating the entries in the current group in a config
+ object. Returns a tuple containing a flag indicating there are more
+ items, the name of the current item, and an index to pass to
+ GetNextGroup to fetch the next item.
+ """
+ return _misc_.ConfigBase_GetFirstEntry(*args, **kwargs)
+
+ def GetNextEntry(*args, **kwargs):
+ """
+ GetNextEntry(long index) -> (more, value, index)
+
+ Allows enumerating the entries in the current group in a config
+ object. Returns a tuple containing a flag indicating there are more
+ items, the name of the current item, and an index to pass to
+ GetNextGroup to fetch the next item.
+ """
+ return _misc_.ConfigBase_GetNextEntry(*args, **kwargs)
+
+ def GetNumberOfEntries(*args, **kwargs):
+ """
+ GetNumberOfEntries(self, bool recursive=False) -> size_t
+
+ Get the number of entries in the current group, with or without its
+ subgroups.
+ """
+ return _misc_.ConfigBase_GetNumberOfEntries(*args, **kwargs)
+
+ def GetNumberOfGroups(*args, **kwargs):
+ """
+ GetNumberOfGroups(self, bool recursive=False) -> size_t
+
+ Get the number of subgroups in the current group, with or without its
+ subgroups.
+ """
+ return _misc_.ConfigBase_GetNumberOfGroups(*args, **kwargs)
+
+ def HasGroup(*args, **kwargs):
+ """
+ HasGroup(self, String name) -> bool
+
+ Returns True if the group by this name exists
+ """
+ return _misc_.ConfigBase_HasGroup(*args, **kwargs)
+
+ def HasEntry(*args, **kwargs):
+ """
+ HasEntry(self, String name) -> bool
+
+ Returns True if the entry by this name exists
+ """
+ return _misc_.ConfigBase_HasEntry(*args, **kwargs)
+
+ def Exists(*args, **kwargs):
+ """
+ Exists(self, String name) -> bool
+
+ Returns True if either a group or an entry with a given name exists
+ """
+ return _misc_.ConfigBase_Exists(*args, **kwargs)
+
+ def GetEntryType(*args, **kwargs):
+ """
+ GetEntryType(self, String name) -> int
+
+ Get the type of the entry. Returns one of the wx.Config.Type_XXX values.
+ """
+ return _misc_.ConfigBase_GetEntryType(*args, **kwargs)
+
+ def Read(*args, **kwargs):
+ """
+ Read(self, String key, String defaultVal=EmptyString) -> String
+
+ Returns the value of key if it exists, defaultVal otherwise.
+ """
+ return _misc_.ConfigBase_Read(*args, **kwargs)
+
+ def ReadInt(*args, **kwargs):
+ """
+ ReadInt(self, String key, long defaultVal=0) -> long
+
+ Returns the value of key if it exists, defaultVal otherwise.
+ """
+ return _misc_.ConfigBase_ReadInt(*args, **kwargs)
+
+ def ReadFloat(*args, **kwargs):
+ """
+ ReadFloat(self, String key, double defaultVal=0.0) -> double
+
+ Returns the value of key if it exists, defaultVal otherwise.
+ """
+ return _misc_.ConfigBase_ReadFloat(*args, **kwargs)
+
+ def ReadBool(*args, **kwargs):
+ """
+ ReadBool(self, String key, bool defaultVal=False) -> bool
+
+ Returns the value of key if it exists, defaultVal otherwise.
+ """
+ return _misc_.ConfigBase_ReadBool(*args, **kwargs)
+
+ def Write(*args, **kwargs):
+ """
+ Write(self, String key, String value) -> bool
+
+ write the value (return True on success)
+ """
+ return _misc_.ConfigBase_Write(*args, **kwargs)
+
+ def WriteInt(*args, **kwargs):
+ """
+ WriteInt(self, String key, long value) -> bool
+
+ write the value (return True on success)
+ """
+ return _misc_.ConfigBase_WriteInt(*args, **kwargs)
+
+ def WriteFloat(*args, **kwargs):
+ """
+ WriteFloat(self, String key, double value) -> bool
+
+ write the value (return True on success)
+ """
+ return _misc_.ConfigBase_WriteFloat(*args, **kwargs)
+
+ def WriteBool(*args, **kwargs):
+ """
+ WriteBool(self, String key, bool value) -> bool
+
+ write the value (return True on success)
+ """
+ return _misc_.ConfigBase_WriteBool(*args, **kwargs)
+
+ def Flush(*args, **kwargs):
+ """
+ Flush(self, bool currentOnly=False) -> bool
+
+ permanently writes all changes
+ """
+ return _misc_.ConfigBase_Flush(*args, **kwargs)
+
+ def RenameEntry(*args, **kwargs):
+ """
+ RenameEntry(self, String oldName, String newName) -> bool
+
+ Rename an entry. Returns False on failure (probably because the new
+ name is already taken by an existing entry)
+ """
+ return _misc_.ConfigBase_RenameEntry(*args, **kwargs)
+
+ def RenameGroup(*args, **kwargs):
+ """
+ RenameGroup(self, String oldName, String newName) -> bool
+
+ Rename a group. Returns False on failure (probably because the new
+ name is already taken by an existing entry)
+ """
+ return _misc_.ConfigBase_RenameGroup(*args, **kwargs)
+
+ def DeleteEntry(*args, **kwargs):
+ """
+ DeleteEntry(self, String key, bool deleteGroupIfEmpty=True) -> bool
+
+ Deletes the specified entry and the group it belongs to if it was the
+ last key in it and the second parameter is True
+ """
+ return _misc_.ConfigBase_DeleteEntry(*args, **kwargs)
+
+ def DeleteGroup(*args, **kwargs):
+ """
+ DeleteGroup(self, String key) -> bool
+
+ Delete the group (with all subgroups)
+ """
+ return _misc_.ConfigBase_DeleteGroup(*args, **kwargs)
+
+ def DeleteAll(*args, **kwargs):
+ """
+ DeleteAll(self) -> bool
+
+ Delete the whole underlying object (disk file, registry key, ...)
+ primarly intended for use by deinstallation routine.
+ """
+ return _misc_.ConfigBase_DeleteAll(*args, **kwargs)
+
+ def SetExpandEnvVars(*args, **kwargs):
+ """
+ SetExpandEnvVars(self, bool doIt=True)
+
+ We can automatically expand environment variables in the config
+ entries this option is on by default, you can turn it on/off at any
+ time)
+ """
+ return _misc_.ConfigBase_SetExpandEnvVars(*args, **kwargs)
+
+ def IsExpandingEnvVars(*args, **kwargs):
+ """
+ IsExpandingEnvVars(self) -> bool
+
+ Are we currently expanding environment variables?
+ """
+ return _misc_.ConfigBase_IsExpandingEnvVars(*args, **kwargs)
+
+ def SetRecordDefaults(*args, **kwargs):
+ """
+ SetRecordDefaults(self, bool doIt=True)
+
+ Set whether the config objec should record default values.
+ """
+ return _misc_.ConfigBase_SetRecordDefaults(*args, **kwargs)
+
+ def IsRecordingDefaults(*args, **kwargs):
+ """
+ IsRecordingDefaults(self) -> bool
+
+ Are we currently recording default values?
+ """
+ return _misc_.ConfigBase_IsRecordingDefaults(*args, **kwargs)
+
+ def ExpandEnvVars(*args, **kwargs):
+ """
+ ExpandEnvVars(self, String str) -> String
+
+ Expand any environment variables in str and return the result
+ """
+ return _misc_.ConfigBase_ExpandEnvVars(*args, **kwargs)
+
+ def GetAppName(*args, **kwargs):
+ """GetAppName(self) -> String"""
+ return _misc_.ConfigBase_GetAppName(*args, **kwargs)
+
+ def GetVendorName(*args, **kwargs):
+ """GetVendorName(self) -> String"""
+ return _misc_.ConfigBase_GetVendorName(*args, **kwargs)
+
+ def SetAppName(*args, **kwargs):
+ """SetAppName(self, String appName)"""
+ return _misc_.ConfigBase_SetAppName(*args, **kwargs)
+
+ def SetVendorName(*args, **kwargs):
+ """SetVendorName(self, String vendorName)"""
+ return _misc_.ConfigBase_SetVendorName(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """SetStyle(self, long style)"""
+ return _misc_.ConfigBase_SetStyle(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self) -> long"""
+ return _misc_.ConfigBase_GetStyle(*args, **kwargs)
+
+ AppName = property(GetAppName,SetAppName,doc="See `GetAppName` and `SetAppName`")
+ EntryType = property(GetEntryType,doc="See `GetEntryType`")
+ FirstEntry = property(GetFirstEntry,doc="See `GetFirstEntry`")
+ FirstGroup = property(GetFirstGroup,doc="See `GetFirstGroup`")
+ NextEntry = property(GetNextEntry,doc="See `GetNextEntry`")
+ NextGroup = property(GetNextGroup,doc="See `GetNextGroup`")
+ NumberOfEntries = property(GetNumberOfEntries,doc="See `GetNumberOfEntries`")
+ NumberOfGroups = property(GetNumberOfGroups,doc="See `GetNumberOfGroups`")
+ Path = property(GetPath,SetPath,doc="See `GetPath` and `SetPath`")
+ Style = property(GetStyle,SetStyle,doc="See `GetStyle` and `SetStyle`")
+ VendorName = property(GetVendorName,SetVendorName,doc="See `GetVendorName` and `SetVendorName`")
+_misc_.ConfigBase_swigregister(ConfigBase)
+
+def ConfigBase_Set(*args, **kwargs):
+ """
+ ConfigBase_Set(ConfigBase config) -> ConfigBase
+
+ Sets the global config object (the one returned by Get) and returns a
+ reference to the previous global config object.
+ """
+ return _misc_.ConfigBase_Set(*args, **kwargs)
+
+def ConfigBase_Get(*args, **kwargs):
+ """
+ ConfigBase_Get(bool createOnDemand=True) -> ConfigBase
+
+ Returns the current global config object, creating one if neccessary.
+ """
+ return _misc_.ConfigBase_Get(*args, **kwargs)
+
+def ConfigBase_Create(*args):
+ """
+ ConfigBase_Create() -> ConfigBase
+
+ Create and return a new global config object. This function will
+ create the "best" implementation of wx.Config available for the
+ current platform.
+ """
+ return _misc_.ConfigBase_Create(*args)
+
+def ConfigBase_DontCreateOnDemand(*args):
+ """
+ ConfigBase_DontCreateOnDemand()
+
+ Should Get() try to create a new log object if there isn't a current
+ one?
+ """
+ return _misc_.ConfigBase_DontCreateOnDemand(*args)
+
+class Config(ConfigBase):
+ """
+ This ConfigBase-derived class will use the registry on Windows,
+ and will be a wx.FileConfig on other platforms.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String appName=EmptyString, String vendorName=EmptyString,
+ String localFilename=EmptyString, String globalFilename=EmptyString,
+ long style=wxCONFIG_USE_LOCAL_FILE|wxCONFIG_USE_GLOBAL_FILE) -> Config
+ """
+ _misc_.Config_swiginit(self,_misc_.new_Config(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_Config
+ __del__ = lambda self : None;
+_misc_.Config_swigregister(Config)
+
+class FileConfig(ConfigBase):
+ """This config class will use a file for storage on all platforms."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String appName=EmptyString, String vendorName=EmptyString,
+ String localFilename=EmptyString, String globalFilename=EmptyString,
+ long style=wxCONFIG_USE_LOCAL_FILE|wxCONFIG_USE_GLOBAL_FILE) -> FileConfig
+ """
+ _misc_.FileConfig_swiginit(self,_misc_.new_FileConfig(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_FileConfig
+ __del__ = lambda self : None;
+ def GetGlobalFileName(*args, **kwargs):
+ """GetGlobalFileName(String szFile) -> String"""
+ return _misc_.FileConfig_GetGlobalFileName(*args, **kwargs)
+
+ GetGlobalFileName = staticmethod(GetGlobalFileName)
+ def GetLocalFileName(*args, **kwargs):
+ """GetLocalFileName(String szFile, int style=0) -> String"""
+ return _misc_.FileConfig_GetLocalFileName(*args, **kwargs)
+
+ GetLocalFileName = staticmethod(GetLocalFileName)
+_misc_.FileConfig_swigregister(FileConfig)
+
+def FileConfig_GetGlobalFileName(*args, **kwargs):
+ """FileConfig_GetGlobalFileName(String szFile) -> String"""
+ return _misc_.FileConfig_GetGlobalFileName(*args, **kwargs)
+
+def FileConfig_GetLocalFileName(*args, **kwargs):
+ """FileConfig_GetLocalFileName(String szFile, int style=0) -> String"""
+ return _misc_.FileConfig_GetLocalFileName(*args, **kwargs)
+
+class ConfigPathChanger(object):
+ """
+ A handy little class which changes current path to the path of given
+ entry and restores it in the destructoir: so if you declare a local
+ variable of this type, you work in the entry directory and the path is
+ automatically restored when the function returns.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, ConfigBase config, String entry) -> ConfigPathChanger"""
+ _misc_.ConfigPathChanger_swiginit(self,_misc_.new_ConfigPathChanger(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_ConfigPathChanger
+ __del__ = lambda self : None;
+ def Name(*args, **kwargs):
+ """
+ Name(self) -> String
+
+ Get the key name
+ """
+ return _misc_.ConfigPathChanger_Name(*args, **kwargs)
+
+_misc_.ConfigPathChanger_swigregister(ConfigPathChanger)
+
+
+def ExpandEnvVars(*args, **kwargs):
+ """
+ ExpandEnvVars(String sz) -> String
+
+ Replace environment variables ($SOMETHING) with their values. The
+ format is $VARNAME or ${VARNAME} where VARNAME contains alphanumeric
+ characters and '_' only. '$' must be escaped ('\$') in order to be
+ taken literally.
+ """
+ return _misc_.ExpandEnvVars(*args, **kwargs)
+#---------------------------------------------------------------------------
+
+class DateTime(object):
+ """Proxy of C++ DateTime class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ Local = _misc_.DateTime_Local
+ GMT_12 = _misc_.DateTime_GMT_12
+ GMT_11 = _misc_.DateTime_GMT_11
+ GMT_10 = _misc_.DateTime_GMT_10
+ GMT_9 = _misc_.DateTime_GMT_9
+ GMT_8 = _misc_.DateTime_GMT_8
+ GMT_7 = _misc_.DateTime_GMT_7
+ GMT_6 = _misc_.DateTime_GMT_6
+ GMT_5 = _misc_.DateTime_GMT_5
+ GMT_4 = _misc_.DateTime_GMT_4
+ GMT_3 = _misc_.DateTime_GMT_3
+ GMT_2 = _misc_.DateTime_GMT_2
+ GMT_1 = _misc_.DateTime_GMT_1
+ GMT0 = _misc_.DateTime_GMT0
+ GMT1 = _misc_.DateTime_GMT1
+ GMT2 = _misc_.DateTime_GMT2
+ GMT3 = _misc_.DateTime_GMT3
+ GMT4 = _misc_.DateTime_GMT4
+ GMT5 = _misc_.DateTime_GMT5
+ GMT6 = _misc_.DateTime_GMT6
+ GMT7 = _misc_.DateTime_GMT7
+ GMT8 = _misc_.DateTime_GMT8
+ GMT9 = _misc_.DateTime_GMT9
+ GMT10 = _misc_.DateTime_GMT10
+ GMT11 = _misc_.DateTime_GMT11
+ GMT12 = _misc_.DateTime_GMT12
+ GMT13 = _misc_.DateTime_GMT13
+ WET = _misc_.DateTime_WET
+ WEST = _misc_.DateTime_WEST
+ CET = _misc_.DateTime_CET
+ CEST = _misc_.DateTime_CEST
+ EET = _misc_.DateTime_EET
+ EEST = _misc_.DateTime_EEST
+ MSK = _misc_.DateTime_MSK
+ MSD = _misc_.DateTime_MSD
+ AST = _misc_.DateTime_AST
+ ADT = _misc_.DateTime_ADT
+ EST = _misc_.DateTime_EST
+ EDT = _misc_.DateTime_EDT
+ CST = _misc_.DateTime_CST
+ CDT = _misc_.DateTime_CDT
+ MST = _misc_.DateTime_MST
+ MDT = _misc_.DateTime_MDT
+ PST = _misc_.DateTime_PST
+ PDT = _misc_.DateTime_PDT
+ HST = _misc_.DateTime_HST
+ AKST = _misc_.DateTime_AKST
+ AKDT = _misc_.DateTime_AKDT
+ A_WST = _misc_.DateTime_A_WST
+ A_CST = _misc_.DateTime_A_CST
+ A_EST = _misc_.DateTime_A_EST
+ A_ESST = _misc_.DateTime_A_ESST
+ NZST = _misc_.DateTime_NZST
+ NZDT = _misc_.DateTime_NZDT
+ UTC = _misc_.DateTime_UTC
+ Gregorian = _misc_.DateTime_Gregorian
+ Julian = _misc_.DateTime_Julian
+ Country_Unknown = _misc_.DateTime_Country_Unknown
+ Country_Default = _misc_.DateTime_Country_Default
+ Country_WesternEurope_Start = _misc_.DateTime_Country_WesternEurope_Start
+ Country_EEC = _misc_.DateTime_Country_EEC
+ France = _misc_.DateTime_France
+ Germany = _misc_.DateTime_Germany
+ UK = _misc_.DateTime_UK
+ Country_WesternEurope_End = _misc_.DateTime_Country_WesternEurope_End
+ Russia = _misc_.DateTime_Russia
+ USA = _misc_.DateTime_USA
+ Jan = _misc_.DateTime_Jan
+ Feb = _misc_.DateTime_Feb
+ Mar = _misc_.DateTime_Mar
+ Apr = _misc_.DateTime_Apr
+ May = _misc_.DateTime_May
+ Jun = _misc_.DateTime_Jun
+ Jul = _misc_.DateTime_Jul
+ Aug = _misc_.DateTime_Aug
+ Sep = _misc_.DateTime_Sep
+ Oct = _misc_.DateTime_Oct
+ Nov = _misc_.DateTime_Nov
+ Dec = _misc_.DateTime_Dec
+ Inv_Month = _misc_.DateTime_Inv_Month
+ Sun = _misc_.DateTime_Sun
+ Mon = _misc_.DateTime_Mon
+ Tue = _misc_.DateTime_Tue
+ Wed = _misc_.DateTime_Wed
+ Thu = _misc_.DateTime_Thu
+ Fri = _misc_.DateTime_Fri
+ Sat = _misc_.DateTime_Sat
+ Inv_WeekDay = _misc_.DateTime_Inv_WeekDay
+ Inv_Year = _misc_.DateTime_Inv_Year
+ Name_Full = _misc_.DateTime_Name_Full
+ Name_Abbr = _misc_.DateTime_Name_Abbr
+ Default_First = _misc_.DateTime_Default_First
+ Monday_First = _misc_.DateTime_Monday_First
+ Sunday_First = _misc_.DateTime_Sunday_First
+ def SetCountry(*args, **kwargs):
+ """SetCountry(int country)"""
+ return _misc_.DateTime_SetCountry(*args, **kwargs)
+
+ SetCountry = staticmethod(SetCountry)
+ def GetCountry(*args, **kwargs):
+ """GetCountry() -> int"""
+ return _misc_.DateTime_GetCountry(*args, **kwargs)
+
+ GetCountry = staticmethod(GetCountry)
+ def IsWestEuropeanCountry(*args, **kwargs):
+ """IsWestEuropeanCountry(int country=Country_Default) -> bool"""
+ return _misc_.DateTime_IsWestEuropeanCountry(*args, **kwargs)
+
+ IsWestEuropeanCountry = staticmethod(IsWestEuropeanCountry)
+ def GetCurrentYear(*args, **kwargs):
+ """GetCurrentYear(int cal=Gregorian) -> int"""
+ return _misc_.DateTime_GetCurrentYear(*args, **kwargs)
+
+ GetCurrentYear = staticmethod(GetCurrentYear)
+ def ConvertYearToBC(*args, **kwargs):
+ """ConvertYearToBC(int year) -> int"""
+ return _misc_.DateTime_ConvertYearToBC(*args, **kwargs)
+
+ ConvertYearToBC = staticmethod(ConvertYearToBC)
+ def GetCurrentMonth(*args, **kwargs):
+ """GetCurrentMonth(int cal=Gregorian) -> int"""
+ return _misc_.DateTime_GetCurrentMonth(*args, **kwargs)
+
+ GetCurrentMonth = staticmethod(GetCurrentMonth)
+ def IsLeapYear(*args, **kwargs):
+ """IsLeapYear(int year=Inv_Year, int cal=Gregorian) -> bool"""
+ return _misc_.DateTime_IsLeapYear(*args, **kwargs)
+
+ IsLeapYear = staticmethod(IsLeapYear)
+ def GetCentury(*args, **kwargs):
+ """GetCentury(int year=Inv_Year) -> int"""
+ return _misc_.DateTime_GetCentury(*args, **kwargs)
+
+ GetCentury = staticmethod(GetCentury)
+ def GetNumberOfDaysinYear(*args, **kwargs):
+ """GetNumberOfDaysinYear(int year, int cal=Gregorian) -> int"""
+ return _misc_.DateTime_GetNumberOfDaysinYear(*args, **kwargs)
+
+ GetNumberOfDaysinYear = staticmethod(GetNumberOfDaysinYear)
+ def GetNumberOfDaysInMonth(*args, **kwargs):
+ """GetNumberOfDaysInMonth(int month, int year=Inv_Year, int cal=Gregorian) -> int"""
+ return _misc_.DateTime_GetNumberOfDaysInMonth(*args, **kwargs)
+
+ GetNumberOfDaysInMonth = staticmethod(GetNumberOfDaysInMonth)
+ def GetMonthName(*args, **kwargs):
+ """GetMonthName(int month, int flags=Name_Full) -> String"""
+ return _misc_.DateTime_GetMonthName(*args, **kwargs)
+
+ GetMonthName = staticmethod(GetMonthName)
+ def GetWeekDayName(*args, **kwargs):
+ """GetWeekDayName(int weekday, int flags=Name_Full) -> String"""
+ return _misc_.DateTime_GetWeekDayName(*args, **kwargs)
+
+ GetWeekDayName = staticmethod(GetWeekDayName)
+ def GetEnglishMonthName(*args, **kwargs):
+ """GetEnglishMonthName(int month, int flags=Name_Full) -> String"""
+ return _misc_.DateTime_GetEnglishMonthName(*args, **kwargs)
+
+ GetEnglishMonthName = staticmethod(GetEnglishMonthName)
+ def GetEnglishWeekDayName(*args, **kwargs):
+ """GetEnglishWeekDayName(int weekday, int flags=Name_Full) -> String"""
+ return _misc_.DateTime_GetEnglishWeekDayName(*args, **kwargs)
+
+ GetEnglishWeekDayName = staticmethod(GetEnglishWeekDayName)
+ def GetAmPmStrings(*args, **kwargs):
+ """
+ GetAmPmStrings() -> (am, pm)
+
+ Get the AM and PM strings in the current locale (may be empty)
+ """
+ return _misc_.DateTime_GetAmPmStrings(*args, **kwargs)
+
+ GetAmPmStrings = staticmethod(GetAmPmStrings)
+ def IsDSTApplicable(*args, **kwargs):
+ """IsDSTApplicable(int year=Inv_Year, int country=Country_Default) -> bool"""
+ return _misc_.DateTime_IsDSTApplicable(*args, **kwargs)
+
+ IsDSTApplicable = staticmethod(IsDSTApplicable)
+ def GetBeginDST(*args, **kwargs):
+ """GetBeginDST(int year=Inv_Year, int country=Country_Default) -> DateTime"""
+ return _misc_.DateTime_GetBeginDST(*args, **kwargs)
+
+ GetBeginDST = staticmethod(GetBeginDST)
+ def GetEndDST(*args, **kwargs):
+ """GetEndDST(int year=Inv_Year, int country=Country_Default) -> DateTime"""
+ return _misc_.DateTime_GetEndDST(*args, **kwargs)
+
+ GetEndDST = staticmethod(GetEndDST)
+ def Now(*args, **kwargs):
+ """Now() -> DateTime"""
+ return _misc_.DateTime_Now(*args, **kwargs)
+
+ Now = staticmethod(Now)
+ def UNow(*args, **kwargs):
+ """UNow() -> DateTime"""
+ return _misc_.DateTime_UNow(*args, **kwargs)
+
+ UNow = staticmethod(UNow)
+ def Today(*args, **kwargs):
+ """Today() -> DateTime"""
+ return _misc_.DateTime_Today(*args, **kwargs)
+
+ Today = staticmethod(Today)
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> DateTime"""
+ _misc_.DateTime_swiginit(self,_misc_.new_DateTime(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_DateTime
+ __del__ = lambda self : None;
+ def SetToCurrent(*args, **kwargs):
+ """SetToCurrent(self) -> DateTime"""
+ return _misc_.DateTime_SetToCurrent(*args, **kwargs)
+
+ def SetTimeT(*args, **kwargs):
+ """SetTimeT(self, time_t timet) -> DateTime"""
+ return _misc_.DateTime_SetTimeT(*args, **kwargs)
+
+ def SetJDN(*args, **kwargs):
+ """SetJDN(self, double jdn) -> DateTime"""
+ return _misc_.DateTime_SetJDN(*args, **kwargs)
+
+ def SetHMS(*args, **kwargs):
+ """SetHMS(self, int hour, int minute=0, int second=0, int millisec=0) -> DateTime"""
+ return _misc_.DateTime_SetHMS(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """
+ Set(self, int day, int month=Inv_Month, int year=Inv_Year, int hour=0,
+ int minute=0, int second=0, int millisec=0) -> DateTime
+ """
+ return _misc_.DateTime_Set(*args, **kwargs)
+
+ def ResetTime(*args, **kwargs):
+ """ResetTime(self) -> DateTime"""
+ return _misc_.DateTime_ResetTime(*args, **kwargs)
+
+ def GetDateOnly(*args, **kwargs):
+ """GetDateOnly(self) -> DateTime"""
+ return _misc_.DateTime_GetDateOnly(*args, **kwargs)
+
+ def SetYear(*args, **kwargs):
+ """SetYear(self, int year) -> DateTime"""
+ return _misc_.DateTime_SetYear(*args, **kwargs)
+
+ def SetMonth(*args, **kwargs):
+ """SetMonth(self, int month) -> DateTime"""
+ return _misc_.DateTime_SetMonth(*args, **kwargs)
+
+ def SetDay(*args, **kwargs):
+ """SetDay(self, int day) -> DateTime"""
+ return _misc_.DateTime_SetDay(*args, **kwargs)
+
+ def SetHour(*args, **kwargs):
+ """SetHour(self, int hour) -> DateTime"""
+ return _misc_.DateTime_SetHour(*args, **kwargs)
+
+ def SetMinute(*args, **kwargs):
+ """SetMinute(self, int minute) -> DateTime"""
+ return _misc_.DateTime_SetMinute(*args, **kwargs)
+
+ def SetSecond(*args, **kwargs):
+ """SetSecond(self, int second) -> DateTime"""
+ return _misc_.DateTime_SetSecond(*args, **kwargs)
+
+ def SetMillisecond(*args, **kwargs):
+ """SetMillisecond(self, int millisecond) -> DateTime"""
+ return _misc_.DateTime_SetMillisecond(*args, **kwargs)
+
+ def SetToWeekDayInSameWeek(*args, **kwargs):
+ """SetToWeekDayInSameWeek(self, int weekday, int flags=Monday_First) -> DateTime"""
+ return _misc_.DateTime_SetToWeekDayInSameWeek(*args, **kwargs)
+
+ def GetWeekDayInSameWeek(*args, **kwargs):
+ """GetWeekDayInSameWeek(self, int weekday, int flags=Monday_First) -> DateTime"""
+ return _misc_.DateTime_GetWeekDayInSameWeek(*args, **kwargs)
+
+ def SetToNextWeekDay(*args, **kwargs):
+ """SetToNextWeekDay(self, int weekday) -> DateTime"""
+ return _misc_.DateTime_SetToNextWeekDay(*args, **kwargs)
+
+ def GetNextWeekDay(*args, **kwargs):
+ """GetNextWeekDay(self, int weekday) -> DateTime"""
+ return _misc_.DateTime_GetNextWeekDay(*args, **kwargs)
+
+ def SetToPrevWeekDay(*args, **kwargs):
+ """SetToPrevWeekDay(self, int weekday) -> DateTime"""
+ return _misc_.DateTime_SetToPrevWeekDay(*args, **kwargs)
+
+ def GetPrevWeekDay(*args, **kwargs):
+ """GetPrevWeekDay(self, int weekday) -> DateTime"""
+ return _misc_.DateTime_GetPrevWeekDay(*args, **kwargs)
+
+ def SetToWeekDay(*args, **kwargs):
+ """SetToWeekDay(self, int weekday, int n=1, int month=Inv_Month, int year=Inv_Year) -> bool"""
+ return _misc_.DateTime_SetToWeekDay(*args, **kwargs)
+
+ def SetToLastWeekDay(*args, **kwargs):
+ """SetToLastWeekDay(self, int weekday, int month=Inv_Month, int year=Inv_Year) -> bool"""
+ return _misc_.DateTime_SetToLastWeekDay(*args, **kwargs)
+
+ def GetLastWeekDay(*args, **kwargs):
+ """GetLastWeekDay(self, int weekday, int month=Inv_Month, int year=Inv_Year) -> DateTime"""
+ return _misc_.DateTime_GetLastWeekDay(*args, **kwargs)
+
+ def SetToWeekOfYear(*args, **kwargs):
+ """SetToWeekOfYear(int year, int numWeek, int weekday=Mon) -> DateTime"""
+ return _misc_.DateTime_SetToWeekOfYear(*args, **kwargs)
+
+ SetToWeekOfYear = staticmethod(SetToWeekOfYear)
+ def SetToLastMonthDay(*args, **kwargs):
+ """SetToLastMonthDay(self, int month=Inv_Month, int year=Inv_Year) -> DateTime"""
+ return _misc_.DateTime_SetToLastMonthDay(*args, **kwargs)
+
+ def GetLastMonthDay(*args, **kwargs):
+ """GetLastMonthDay(self, int month=Inv_Month, int year=Inv_Year) -> DateTime"""
+ return _misc_.DateTime_GetLastMonthDay(*args, **kwargs)
+
+ def SetToYearDay(*args, **kwargs):
+ """SetToYearDay(self, int yday) -> DateTime"""
+ return _misc_.DateTime_SetToYearDay(*args, **kwargs)
+
+ def GetYearDay(*args, **kwargs):
+ """GetYearDay(self, int yday) -> DateTime"""
+ return _misc_.DateTime_GetYearDay(*args, **kwargs)
+
+ def GetJulianDayNumber(*args, **kwargs):
+ """GetJulianDayNumber(self) -> double"""
+ return _misc_.DateTime_GetJulianDayNumber(*args, **kwargs)
+
+ def GetJDN(*args, **kwargs):
+ """GetJDN(self) -> double"""
+ return _misc_.DateTime_GetJDN(*args, **kwargs)
+
+ def GetModifiedJulianDayNumber(*args, **kwargs):
+ """GetModifiedJulianDayNumber(self) -> double"""
+ return _misc_.DateTime_GetModifiedJulianDayNumber(*args, **kwargs)
+
+ def GetMJD(*args, **kwargs):
+ """GetMJD(self) -> double"""
+ return _misc_.DateTime_GetMJD(*args, **kwargs)
+
+ def GetRataDie(*args, **kwargs):
+ """GetRataDie(self) -> double"""
+ return _misc_.DateTime_GetRataDie(*args, **kwargs)
+
+ def ToTimezone(*args, **kwargs):
+ """ToTimezone(self, wxDateTime::TimeZone tz, bool noDST=False) -> DateTime"""
+ return _misc_.DateTime_ToTimezone(*args, **kwargs)
+
+ def MakeTimezone(*args, **kwargs):
+ """MakeTimezone(self, wxDateTime::TimeZone tz, bool noDST=False) -> DateTime"""
+ return _misc_.DateTime_MakeTimezone(*args, **kwargs)
+
+ def FromTimezone(*args, **kwargs):
+ """FromTimezone(self, wxDateTime::TimeZone tz, bool noDST=False) -> DateTime"""
+ return _misc_.DateTime_FromTimezone(*args, **kwargs)
+
+ def MakeFromTimezone(*args, **kwargs):
+ """MakeFromTimezone(self, wxDateTime::TimeZone tz, bool noDST=False) -> DateTime"""
+ return _misc_.DateTime_MakeFromTimezone(*args, **kwargs)
+
+ def ToUTC(*args, **kwargs):
+ """ToUTC(self, bool noDST=False) -> DateTime"""
+ return _misc_.DateTime_ToUTC(*args, **kwargs)
+
+ def MakeUTC(*args, **kwargs):
+ """MakeUTC(self, bool noDST=False) -> DateTime"""
+ return _misc_.DateTime_MakeUTC(*args, **kwargs)
+
+ def ToGMT(*args, **kwargs):
+ """ToGMT(self, bool noDST=False) -> DateTime"""
+ return _misc_.DateTime_ToGMT(*args, **kwargs)
+
+ def MakeGMT(*args, **kwargs):
+ """MakeGMT(self, bool noDST=False) -> DateTime"""
+ return _misc_.DateTime_MakeGMT(*args, **kwargs)
+
+ def FromUTC(*args, **kwargs):
+ """FromUTC(self, bool noDST=False) -> DateTime"""
+ return _misc_.DateTime_FromUTC(*args, **kwargs)
+
+ def MakeFromUTC(*args, **kwargs):
+ """MakeFromUTC(self, bool noDST=False) -> DateTime"""
+ return _misc_.DateTime_MakeFromUTC(*args, **kwargs)
+
+ def IsDST(*args, **kwargs):
+ """IsDST(self, int country=Country_Default) -> int"""
+ return _misc_.DateTime_IsDST(*args, **kwargs)
+
+ def IsValid(*args, **kwargs):
+ """IsValid(self) -> bool"""
+ return _misc_.DateTime_IsValid(*args, **kwargs)
+
+ IsOk = IsValid
+ Ok = IsOk
+ def __nonzero__(self): return self.IsOk()
+ def GetTicks(*args, **kwargs):
+ """GetTicks(self) -> time_t"""
+ return _misc_.DateTime_GetTicks(*args, **kwargs)
+
+ def GetYear(*args, **kwargs):
+ """GetYear(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetYear(*args, **kwargs)
+
+ def GetMonth(*args, **kwargs):
+ """GetMonth(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetMonth(*args, **kwargs)
+
+ def GetDay(*args, **kwargs):
+ """GetDay(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetDay(*args, **kwargs)
+
+ def GetWeekDay(*args, **kwargs):
+ """GetWeekDay(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetWeekDay(*args, **kwargs)
+
+ def GetHour(*args, **kwargs):
+ """GetHour(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetHour(*args, **kwargs)
+
+ def GetMinute(*args, **kwargs):
+ """GetMinute(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetMinute(*args, **kwargs)
+
+ def GetSecond(*args, **kwargs):
+ """GetSecond(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetSecond(*args, **kwargs)
+
+ def GetMillisecond(*args, **kwargs):
+ """GetMillisecond(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetMillisecond(*args, **kwargs)
+
+ def GetDayOfYear(*args, **kwargs):
+ """GetDayOfYear(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetDayOfYear(*args, **kwargs)
+
+ def GetWeekOfYear(*args, **kwargs):
+ """GetWeekOfYear(self, int flags=Monday_First, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetWeekOfYear(*args, **kwargs)
+
+ def GetWeekOfMonth(*args, **kwargs):
+ """GetWeekOfMonth(self, int flags=Monday_First, wxDateTime::TimeZone tz=LOCAL_TZ) -> int"""
+ return _misc_.DateTime_GetWeekOfMonth(*args, **kwargs)
+
+ def IsWorkDay(*args, **kwargs):
+ """IsWorkDay(self, int country=Country_Default) -> bool"""
+ return _misc_.DateTime_IsWorkDay(*args, **kwargs)
+
+ def IsEqualTo(*args, **kwargs):
+ """IsEqualTo(self, DateTime datetime) -> bool"""
+ return _misc_.DateTime_IsEqualTo(*args, **kwargs)
+
+ def IsEarlierThan(*args, **kwargs):
+ """IsEarlierThan(self, DateTime datetime) -> bool"""
+ return _misc_.DateTime_IsEarlierThan(*args, **kwargs)
+
+ def IsLaterThan(*args, **kwargs):
+ """IsLaterThan(self, DateTime datetime) -> bool"""
+ return _misc_.DateTime_IsLaterThan(*args, **kwargs)
+
+ def IsStrictlyBetween(*args, **kwargs):
+ """IsStrictlyBetween(self, DateTime t1, DateTime t2) -> bool"""
+ return _misc_.DateTime_IsStrictlyBetween(*args, **kwargs)
+
+ def IsBetween(*args, **kwargs):
+ """IsBetween(self, DateTime t1, DateTime t2) -> bool"""
+ return _misc_.DateTime_IsBetween(*args, **kwargs)
+
+ def IsSameDate(*args, **kwargs):
+ """IsSameDate(self, DateTime dt) -> bool"""
+ return _misc_.DateTime_IsSameDate(*args, **kwargs)
+
+ def IsSameTime(*args, **kwargs):
+ """IsSameTime(self, DateTime dt) -> bool"""
+ return _misc_.DateTime_IsSameTime(*args, **kwargs)
+
+ def IsEqualUpTo(*args, **kwargs):
+ """IsEqualUpTo(self, DateTime dt, TimeSpan ts) -> bool"""
+ return _misc_.DateTime_IsEqualUpTo(*args, **kwargs)
+
+ def AddTS(*args, **kwargs):
+ """AddTS(self, TimeSpan diff) -> DateTime"""
+ return _misc_.DateTime_AddTS(*args, **kwargs)
+
+ def AddDS(*args, **kwargs):
+ """AddDS(self, DateSpan diff) -> DateTime"""
+ return _misc_.DateTime_AddDS(*args, **kwargs)
+
+ def SubtractTS(*args, **kwargs):
+ """SubtractTS(self, TimeSpan diff) -> DateTime"""
+ return _misc_.DateTime_SubtractTS(*args, **kwargs)
+
+ def SubtractDS(*args, **kwargs):
+ """SubtractDS(self, DateSpan diff) -> DateTime"""
+ return _misc_.DateTime_SubtractDS(*args, **kwargs)
+
+ def Subtract(*args, **kwargs):
+ """Subtract(self, DateTime dt) -> TimeSpan"""
+ return _misc_.DateTime_Subtract(*args, **kwargs)
+
+ def __iadd__(*args):
+ """
+ __iadd__(self, TimeSpan diff) -> DateTime
+ __iadd__(self, DateSpan diff) -> DateTime
+ """
+ return _misc_.DateTime___iadd__(*args)
+
+ def __isub__(*args):
+ """
+ __isub__(self, TimeSpan diff) -> DateTime
+ __isub__(self, DateSpan diff) -> DateTime
+ """
+ return _misc_.DateTime___isub__(*args)
+
+ def __add__(*args):
+ """
+ __add__(self, TimeSpan other) -> DateTime
+ __add__(self, DateSpan other) -> DateTime
+ """
+ return _misc_.DateTime___add__(*args)
+
+ def __sub__(*args):
+ """
+ __sub__(self, DateTime other) -> TimeSpan
+ __sub__(self, TimeSpan other) -> DateTime
+ __sub__(self, DateSpan other) -> DateTime
+ """
+ return _misc_.DateTime___sub__(*args)
+
+ def __lt__(*args, **kwargs):
+ """__lt__(self, DateTime other) -> bool"""
+ return _misc_.DateTime___lt__(*args, **kwargs)
+
+ def __le__(*args, **kwargs):
+ """__le__(self, DateTime other) -> bool"""
+ return _misc_.DateTime___le__(*args, **kwargs)
+
+ def __gt__(*args, **kwargs):
+ """__gt__(self, DateTime other) -> bool"""
+ return _misc_.DateTime___gt__(*args, **kwargs)
+
+ def __ge__(*args, **kwargs):
+ """__ge__(self, DateTime other) -> bool"""
+ return _misc_.DateTime___ge__(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """__eq__(self, DateTime other) -> bool"""
+ return _misc_.DateTime___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """__ne__(self, DateTime other) -> bool"""
+ return _misc_.DateTime___ne__(*args, **kwargs)
+
+ def ParseRfc822Date(*args, **kwargs):
+ """ParseRfc822Date(self, String date) -> int"""
+ return _misc_.DateTime_ParseRfc822Date(*args, **kwargs)
+
+ def ParseFormat(*args, **kwargs):
+ """ParseFormat(self, String date, String format=DefaultDateTimeFormat, DateTime dateDef=DefaultDateTime) -> int"""
+ return _misc_.DateTime_ParseFormat(*args, **kwargs)
+
+ def ParseISODate(*args, **kwargs):
+ """ParseISODate(self, String date) -> bool"""
+ return _misc_.DateTime_ParseISODate(*args, **kwargs)
+
+ def ParseISOTime(*args, **kwargs):
+ """ParseISOTime(self, String time) -> bool"""
+ return _misc_.DateTime_ParseISOTime(*args, **kwargs)
+
+ def ParseISOCombined(*args, **kwargs):
+ """ParseISOCombined(self, String datetime, char sep='T') -> bool"""
+ return _misc_.DateTime_ParseISOCombined(*args, **kwargs)
+
+ def ParseDateTime(*args, **kwargs):
+ """ParseDateTime(self, String datetime) -> int"""
+ return _misc_.DateTime_ParseDateTime(*args, **kwargs)
+
+ def ParseDate(*args, **kwargs):
+ """ParseDate(self, String date) -> int"""
+ return _misc_.DateTime_ParseDate(*args, **kwargs)
+
+ def ParseTime(*args, **kwargs):
+ """ParseTime(self, String time) -> int"""
+ return _misc_.DateTime_ParseTime(*args, **kwargs)
+
+ def Format(*args, **kwargs):
+ """Format(self, String format=DefaultDateTimeFormat, wxDateTime::TimeZone tz=LOCAL_TZ) -> String"""
+ return _misc_.DateTime_Format(*args, **kwargs)
+
+ def FormatDate(*args, **kwargs):
+ """FormatDate(self) -> String"""
+ return _misc_.DateTime_FormatDate(*args, **kwargs)
+
+ def FormatTime(*args, **kwargs):
+ """FormatTime(self) -> String"""
+ return _misc_.DateTime_FormatTime(*args, **kwargs)
+
+ def FormatISODate(*args, **kwargs):
+ """FormatISODate(self) -> String"""
+ return _misc_.DateTime_FormatISODate(*args, **kwargs)
+
+ def FormatISOTime(*args, **kwargs):
+ """FormatISOTime(self) -> String"""
+ return _misc_.DateTime_FormatISOTime(*args, **kwargs)
+
+ def FormatISOCombined(*args, **kwargs):
+ """FormatISOCombined(self, char sep='T') -> String"""
+ return _misc_.DateTime_FormatISOCombined(*args, **kwargs)
+
+ def __repr__(self):
+ if self.IsValid():
+ f = self.Format().encode(wx.GetDefaultPyEncoding())
+ return '<wx.DateTime: \"%s\" at %s>' % ( f, self.this)
+ else:
+ return '<wx.DateTime: \"INVALID\" at %s>' % self.this
+ def __str__(self):
+ if self.IsValid():
+ return self.Format().encode(wx.GetDefaultPyEncoding())
+ else:
+ return "INVALID DateTime"
+
+ Day = property(GetDay,SetDay,doc="See `GetDay` and `SetDay`")
+ DayOfYear = property(GetDayOfYear,doc="See `GetDayOfYear`")
+ Hour = property(GetHour,SetHour,doc="See `GetHour` and `SetHour`")
+ JDN = property(GetJDN,SetJDN,doc="See `GetJDN` and `SetJDN`")
+ JulianDayNumber = property(GetJulianDayNumber,doc="See `GetJulianDayNumber`")
+ LastMonthDay = property(GetLastMonthDay,doc="See `GetLastMonthDay`")
+ LastWeekDay = property(GetLastWeekDay,doc="See `GetLastWeekDay`")
+ MJD = property(GetMJD,doc="See `GetMJD`")
+ Millisecond = property(GetMillisecond,SetMillisecond,doc="See `GetMillisecond` and `SetMillisecond`")
+ Minute = property(GetMinute,SetMinute,doc="See `GetMinute` and `SetMinute`")
+ ModifiedJulianDayNumber = property(GetModifiedJulianDayNumber,doc="See `GetModifiedJulianDayNumber`")
+ Month = property(GetMonth,SetMonth,doc="See `GetMonth` and `SetMonth`")
+ NextWeekDay = property(GetNextWeekDay,doc="See `GetNextWeekDay`")
+ PrevWeekDay = property(GetPrevWeekDay,doc="See `GetPrevWeekDay`")
+ RataDie = property(GetRataDie,doc="See `GetRataDie`")
+ Second = property(GetSecond,SetSecond,doc="See `GetSecond` and `SetSecond`")
+ Ticks = property(GetTicks,doc="See `GetTicks`")
+ WeekDay = property(GetWeekDay,doc="See `GetWeekDay`")
+ WeekDayInSameWeek = property(GetWeekDayInSameWeek,doc="See `GetWeekDayInSameWeek`")
+ WeekOfMonth = property(GetWeekOfMonth,doc="See `GetWeekOfMonth`")
+ WeekOfYear = property(GetWeekOfYear,doc="See `GetWeekOfYear`")
+ Year = property(GetYear,SetYear,doc="See `GetYear` and `SetYear`")
+ YearDay = property(GetYearDay,doc="See `GetYearDay`")
+_misc_.DateTime_swigregister(DateTime)
+DefaultDateTimeFormat = cvar.DefaultDateTimeFormat
+DefaultTimeSpanFormat = cvar.DefaultTimeSpanFormat
+
+def DateTime_SetCountry(*args, **kwargs):
+ """DateTime_SetCountry(int country)"""
+ return _misc_.DateTime_SetCountry(*args, **kwargs)
+
+def DateTime_GetCountry(*args):
+ """DateTime_GetCountry() -> int"""
+ return _misc_.DateTime_GetCountry(*args)
+
+def DateTime_IsWestEuropeanCountry(*args, **kwargs):
+ """DateTime_IsWestEuropeanCountry(int country=Country_Default) -> bool"""
+ return _misc_.DateTime_IsWestEuropeanCountry(*args, **kwargs)
+
+def DateTime_GetCurrentYear(*args, **kwargs):
+ """DateTime_GetCurrentYear(int cal=Gregorian) -> int"""
+ return _misc_.DateTime_GetCurrentYear(*args, **kwargs)
+
+def DateTime_ConvertYearToBC(*args, **kwargs):
+ """DateTime_ConvertYearToBC(int year) -> int"""
+ return _misc_.DateTime_ConvertYearToBC(*args, **kwargs)
+
+def DateTime_GetCurrentMonth(*args, **kwargs):
+ """DateTime_GetCurrentMonth(int cal=Gregorian) -> int"""
+ return _misc_.DateTime_GetCurrentMonth(*args, **kwargs)
+
+def DateTime_IsLeapYear(*args, **kwargs):
+ """DateTime_IsLeapYear(int year=Inv_Year, int cal=Gregorian) -> bool"""
+ return _misc_.DateTime_IsLeapYear(*args, **kwargs)
+
+def DateTime_GetCentury(*args, **kwargs):
+ """DateTime_GetCentury(int year=Inv_Year) -> int"""
+ return _misc_.DateTime_GetCentury(*args, **kwargs)
+
+def DateTime_GetNumberOfDaysinYear(*args, **kwargs):
+ """DateTime_GetNumberOfDaysinYear(int year, int cal=Gregorian) -> int"""
+ return _misc_.DateTime_GetNumberOfDaysinYear(*args, **kwargs)
+
+def DateTime_GetNumberOfDaysInMonth(*args, **kwargs):
+ """DateTime_GetNumberOfDaysInMonth(int month, int year=Inv_Year, int cal=Gregorian) -> int"""
+ return _misc_.DateTime_GetNumberOfDaysInMonth(*args, **kwargs)
+
+def DateTime_GetMonthName(*args, **kwargs):
+ """DateTime_GetMonthName(int month, int flags=Name_Full) -> String"""
+ return _misc_.DateTime_GetMonthName(*args, **kwargs)
+
+def DateTime_GetWeekDayName(*args, **kwargs):
+ """DateTime_GetWeekDayName(int weekday, int flags=Name_Full) -> String"""
+ return _misc_.DateTime_GetWeekDayName(*args, **kwargs)
+
+def DateTime_GetEnglishMonthName(*args, **kwargs):
+ """DateTime_GetEnglishMonthName(int month, int flags=Name_Full) -> String"""
+ return _misc_.DateTime_GetEnglishMonthName(*args, **kwargs)
+
+def DateTime_GetEnglishWeekDayName(*args, **kwargs):
+ """DateTime_GetEnglishWeekDayName(int weekday, int flags=Name_Full) -> String"""
+ return _misc_.DateTime_GetEnglishWeekDayName(*args, **kwargs)
+
+def DateTime_GetAmPmStrings(*args):
+ """
+ GetAmPmStrings() -> (am, pm)
+
+ Get the AM and PM strings in the current locale (may be empty)
+ """
+ return _misc_.DateTime_GetAmPmStrings(*args)
+
+def DateTime_IsDSTApplicable(*args, **kwargs):
+ """DateTime_IsDSTApplicable(int year=Inv_Year, int country=Country_Default) -> bool"""
+ return _misc_.DateTime_IsDSTApplicable(*args, **kwargs)
+
+def DateTime_GetBeginDST(*args, **kwargs):
+ """DateTime_GetBeginDST(int year=Inv_Year, int country=Country_Default) -> DateTime"""
+ return _misc_.DateTime_GetBeginDST(*args, **kwargs)
+
+def DateTime_GetEndDST(*args, **kwargs):
+ """DateTime_GetEndDST(int year=Inv_Year, int country=Country_Default) -> DateTime"""
+ return _misc_.DateTime_GetEndDST(*args, **kwargs)
+
+def DateTime_Now(*args):
+ """DateTime_Now() -> DateTime"""
+ return _misc_.DateTime_Now(*args)
+
+def DateTime_UNow(*args):
+ """DateTime_UNow() -> DateTime"""
+ return _misc_.DateTime_UNow(*args)
+
+def DateTime_Today(*args):
+ """DateTime_Today() -> DateTime"""
+ return _misc_.DateTime_Today(*args)
+
+def DateTimeFromTimeT(*args, **kwargs):
+ """DateTimeFromTimeT(time_t timet) -> DateTime"""
+ val = _misc_.new_DateTimeFromTimeT(*args, **kwargs)
+ return val
+
+def DateTimeFromJDN(*args, **kwargs):
+ """DateTimeFromJDN(double jdn) -> DateTime"""
+ val = _misc_.new_DateTimeFromJDN(*args, **kwargs)
+ return val
+
+def DateTimeFromHMS(*args, **kwargs):
+ """DateTimeFromHMS(int hour, int minute=0, int second=0, int millisec=0) -> DateTime"""
+ val = _misc_.new_DateTimeFromHMS(*args, **kwargs)
+ return val
+
+def DateTimeFromDMY(*args, **kwargs):
+ """
+ DateTimeFromDMY(int day, int month=Inv_Month, int year=Inv_Year, int hour=0,
+ int minute=0, int second=0, int millisec=0) -> DateTime
+ """
+ val = _misc_.new_DateTimeFromDMY(*args, **kwargs)
+ return val
+
+def DateTimeFromDateTime(*args, **kwargs):
+ """DateTimeFromDateTime(DateTime date) -> DateTime"""
+ val = _misc_.new_DateTimeFromDateTime(*args, **kwargs)
+ return val
+
+def DateTime_SetToWeekOfYear(*args, **kwargs):
+ """DateTime_SetToWeekOfYear(int year, int numWeek, int weekday=Mon) -> DateTime"""
+ return _misc_.DateTime_SetToWeekOfYear(*args, **kwargs)
+
+class TimeSpan(object):
+ """Proxy of C++ TimeSpan class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def Milliseconds(*args, **kwargs):
+ """Milliseconds(long ms) -> TimeSpan"""
+ return _misc_.TimeSpan_Milliseconds(*args, **kwargs)
+
+ Milliseconds = staticmethod(Milliseconds)
+ def Millisecond(*args, **kwargs):
+ """Millisecond() -> TimeSpan"""
+ return _misc_.TimeSpan_Millisecond(*args, **kwargs)
+
+ Millisecond = staticmethod(Millisecond)
+ def Seconds(*args, **kwargs):
+ """Seconds(long sec) -> TimeSpan"""
+ return _misc_.TimeSpan_Seconds(*args, **kwargs)
+
+ Seconds = staticmethod(Seconds)
+ def Second(*args, **kwargs):
+ """Second() -> TimeSpan"""
+ return _misc_.TimeSpan_Second(*args, **kwargs)
+
+ Second = staticmethod(Second)
+ def Minutes(*args, **kwargs):
+ """Minutes(long min) -> TimeSpan"""
+ return _misc_.TimeSpan_Minutes(*args, **kwargs)
+
+ Minutes = staticmethod(Minutes)
+ def Minute(*args, **kwargs):
+ """Minute() -> TimeSpan"""
+ return _misc_.TimeSpan_Minute(*args, **kwargs)
+
+ Minute = staticmethod(Minute)
+ def Hours(*args, **kwargs):
+ """Hours(long hours) -> TimeSpan"""
+ return _misc_.TimeSpan_Hours(*args, **kwargs)
+
+ Hours = staticmethod(Hours)
+ def Hour(*args, **kwargs):
+ """Hour() -> TimeSpan"""
+ return _misc_.TimeSpan_Hour(*args, **kwargs)
+
+ Hour = staticmethod(Hour)
+ def Days(*args, **kwargs):
+ """Days(long days) -> TimeSpan"""
+ return _misc_.TimeSpan_Days(*args, **kwargs)
+
+ Days = staticmethod(Days)
+ def Day(*args, **kwargs):
+ """Day() -> TimeSpan"""
+ return _misc_.TimeSpan_Day(*args, **kwargs)
+
+ Day = staticmethod(Day)
+ def Weeks(*args, **kwargs):
+ """Weeks(long days) -> TimeSpan"""
+ return _misc_.TimeSpan_Weeks(*args, **kwargs)
+
+ Weeks = staticmethod(Weeks)
+ def Week(*args, **kwargs):
+ """Week() -> TimeSpan"""
+ return _misc_.TimeSpan_Week(*args, **kwargs)
+
+ Week = staticmethod(Week)
+ def __init__(self, *args, **kwargs):
+ """__init__(self, long hours=0, long minutes=0, long seconds=0, long milliseconds=0) -> TimeSpan"""
+ _misc_.TimeSpan_swiginit(self,_misc_.new_TimeSpan(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_TimeSpan
+ __del__ = lambda self : None;
+ def Add(*args, **kwargs):
+ """Add(self, TimeSpan diff) -> TimeSpan"""
+ return _misc_.TimeSpan_Add(*args, **kwargs)
+
+ def Subtract(*args, **kwargs):
+ """Subtract(self, TimeSpan diff) -> TimeSpan"""
+ return _misc_.TimeSpan_Subtract(*args, **kwargs)
+
+ def Multiply(*args, **kwargs):
+ """Multiply(self, int n) -> TimeSpan"""
+ return _misc_.TimeSpan_Multiply(*args, **kwargs)
+
+ def Neg(*args, **kwargs):
+ """Neg(self) -> TimeSpan"""
+ return _misc_.TimeSpan_Neg(*args, **kwargs)
+
+ def Abs(*args, **kwargs):
+ """Abs(self) -> TimeSpan"""
+ return _misc_.TimeSpan_Abs(*args, **kwargs)
+
+ def __iadd__(*args, **kwargs):
+ """__iadd__(self, TimeSpan diff) -> TimeSpan"""
+ return _misc_.TimeSpan___iadd__(*args, **kwargs)
+
+ def __isub__(*args, **kwargs):
+ """__isub__(self, TimeSpan diff) -> TimeSpan"""
+ return _misc_.TimeSpan___isub__(*args, **kwargs)
+
+ def __imul__(*args, **kwargs):
+ """__imul__(self, int n) -> TimeSpan"""
+ return _misc_.TimeSpan___imul__(*args, **kwargs)
+
+ def __neg__(*args, **kwargs):
+ """__neg__(self) -> TimeSpan"""
+ return _misc_.TimeSpan___neg__(*args, **kwargs)
+
+ def __add__(*args, **kwargs):
+ """__add__(self, TimeSpan other) -> TimeSpan"""
+ return _misc_.TimeSpan___add__(*args, **kwargs)
+
+ def __sub__(*args, **kwargs):
+ """__sub__(self, TimeSpan other) -> TimeSpan"""
+ return _misc_.TimeSpan___sub__(*args, **kwargs)
+
+ def __mul__(*args, **kwargs):
+ """__mul__(self, int n) -> TimeSpan"""
+ return _misc_.TimeSpan___mul__(*args, **kwargs)
+
+ def __rmul__(*args, **kwargs):
+ """__rmul__(self, int n) -> TimeSpan"""
+ return _misc_.TimeSpan___rmul__(*args, **kwargs)
+
+ def __lt__(*args, **kwargs):
+ """__lt__(self, TimeSpan other) -> bool"""
+ return _misc_.TimeSpan___lt__(*args, **kwargs)
+
+ def __le__(*args, **kwargs):
+ """__le__(self, TimeSpan other) -> bool"""
+ return _misc_.TimeSpan___le__(*args, **kwargs)
+
+ def __gt__(*args, **kwargs):
+ """__gt__(self, TimeSpan other) -> bool"""
+ return _misc_.TimeSpan___gt__(*args, **kwargs)
+
+ def __ge__(*args, **kwargs):
+ """__ge__(self, TimeSpan other) -> bool"""
+ return _misc_.TimeSpan___ge__(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """__eq__(self, TimeSpan other) -> bool"""
+ return _misc_.TimeSpan___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """__ne__(self, TimeSpan other) -> bool"""
+ return _misc_.TimeSpan___ne__(*args, **kwargs)
+
+ def IsNull(*args, **kwargs):
+ """IsNull(self) -> bool"""
+ return _misc_.TimeSpan_IsNull(*args, **kwargs)
+
+ def IsPositive(*args, **kwargs):
+ """IsPositive(self) -> bool"""
+ return _misc_.TimeSpan_IsPositive(*args, **kwargs)
+
+ def IsNegative(*args, **kwargs):
+ """IsNegative(self) -> bool"""
+ return _misc_.TimeSpan_IsNegative(*args, **kwargs)
+
+ def IsEqualTo(*args, **kwargs):
+ """IsEqualTo(self, TimeSpan ts) -> bool"""
+ return _misc_.TimeSpan_IsEqualTo(*args, **kwargs)
+
+ def IsLongerThan(*args, **kwargs):
+ """IsLongerThan(self, TimeSpan ts) -> bool"""
+ return _misc_.TimeSpan_IsLongerThan(*args, **kwargs)
+
+ def IsShorterThan(*args, **kwargs):
+ """IsShorterThan(self, TimeSpan t) -> bool"""
+ return _misc_.TimeSpan_IsShorterThan(*args, **kwargs)
+
+ def GetWeeks(*args, **kwargs):
+ """GetWeeks(self) -> int"""
+ return _misc_.TimeSpan_GetWeeks(*args, **kwargs)
+
+ def GetDays(*args, **kwargs):
+ """GetDays(self) -> int"""
+ return _misc_.TimeSpan_GetDays(*args, **kwargs)
+
+ def GetHours(*args, **kwargs):
+ """GetHours(self) -> int"""
+ return _misc_.TimeSpan_GetHours(*args, **kwargs)
+
+ def GetMinutes(*args, **kwargs):
+ """GetMinutes(self) -> int"""
+ return _misc_.TimeSpan_GetMinutes(*args, **kwargs)
+
+ def GetSeconds(*args, **kwargs):
+ """GetSeconds(self) -> wxLongLong"""
+ return _misc_.TimeSpan_GetSeconds(*args, **kwargs)
+
+ def GetMilliseconds(*args, **kwargs):
+ """GetMilliseconds(self) -> wxLongLong"""
+ return _misc_.TimeSpan_GetMilliseconds(*args, **kwargs)
+
+ def Format(*args, **kwargs):
+ """Format(self, String format=DefaultTimeSpanFormat) -> String"""
+ return _misc_.TimeSpan_Format(*args, **kwargs)
+
+ def __repr__(self):
+ f = self.Format().encode(wx.GetDefaultPyEncoding())
+ return '<wx.TimeSpan: \"%s\" at %s>' % ( f, self.this)
+ def __str__(self):
+ return self.Format().encode(wx.GetDefaultPyEncoding())
+
+ days = property(GetDays,doc="See `GetDays`")
+ hours = property(GetHours,doc="See `GetHours`")
+ milliseconds = property(GetMilliseconds,doc="See `GetMilliseconds`")
+ minutes = property(GetMinutes,doc="See `GetMinutes`")
+ seconds = property(GetSeconds,doc="See `GetSeconds`")
+ weeks = property(GetWeeks,doc="See `GetWeeks`")
+_misc_.TimeSpan_swigregister(TimeSpan)
+
+def TimeSpan_Milliseconds(*args, **kwargs):
+ """TimeSpan_Milliseconds(long ms) -> TimeSpan"""
+ return _misc_.TimeSpan_Milliseconds(*args, **kwargs)
+
+def TimeSpan_Millisecond(*args):
+ """TimeSpan_Millisecond() -> TimeSpan"""
+ return _misc_.TimeSpan_Millisecond(*args)
+
+def TimeSpan_Seconds(*args, **kwargs):
+ """TimeSpan_Seconds(long sec) -> TimeSpan"""
+ return _misc_.TimeSpan_Seconds(*args, **kwargs)
+
+def TimeSpan_Second(*args):
+ """TimeSpan_Second() -> TimeSpan"""
+ return _misc_.TimeSpan_Second(*args)
+
+def TimeSpan_Minutes(*args, **kwargs):
+ """TimeSpan_Minutes(long min) -> TimeSpan"""
+ return _misc_.TimeSpan_Minutes(*args, **kwargs)
+
+def TimeSpan_Minute(*args):
+ """TimeSpan_Minute() -> TimeSpan"""
+ return _misc_.TimeSpan_Minute(*args)
+
+def TimeSpan_Hours(*args, **kwargs):
+ """TimeSpan_Hours(long hours) -> TimeSpan"""
+ return _misc_.TimeSpan_Hours(*args, **kwargs)
+
+def TimeSpan_Hour(*args):
+ """TimeSpan_Hour() -> TimeSpan"""
+ return _misc_.TimeSpan_Hour(*args)
+
+def TimeSpan_Days(*args, **kwargs):
+ """TimeSpan_Days(long days) -> TimeSpan"""
+ return _misc_.TimeSpan_Days(*args, **kwargs)
+
+def TimeSpan_Day(*args):
+ """TimeSpan_Day() -> TimeSpan"""
+ return _misc_.TimeSpan_Day(*args)
+
+def TimeSpan_Weeks(*args, **kwargs):
+ """TimeSpan_Weeks(long days) -> TimeSpan"""
+ return _misc_.TimeSpan_Weeks(*args, **kwargs)
+
+def TimeSpan_Week(*args):
+ """TimeSpan_Week() -> TimeSpan"""
+ return _misc_.TimeSpan_Week(*args)
+
+class DateSpan(object):
+ """Proxy of C++ DateSpan class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int years=0, int months=0, int weeks=0, int days=0) -> DateSpan"""
+ _misc_.DateSpan_swiginit(self,_misc_.new_DateSpan(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_DateSpan
+ __del__ = lambda self : None;
+ def Days(*args, **kwargs):
+ """Days(int days) -> DateSpan"""
+ return _misc_.DateSpan_Days(*args, **kwargs)
+
+ Days = staticmethod(Days)
+ def Day(*args, **kwargs):
+ """Day() -> DateSpan"""
+ return _misc_.DateSpan_Day(*args, **kwargs)
+
+ Day = staticmethod(Day)
+ def Weeks(*args, **kwargs):
+ """Weeks(int weeks) -> DateSpan"""
+ return _misc_.DateSpan_Weeks(*args, **kwargs)
+
+ Weeks = staticmethod(Weeks)
+ def Week(*args, **kwargs):
+ """Week() -> DateSpan"""
+ return _misc_.DateSpan_Week(*args, **kwargs)
+
+ Week = staticmethod(Week)
+ def Months(*args, **kwargs):
+ """Months(int mon) -> DateSpan"""
+ return _misc_.DateSpan_Months(*args, **kwargs)
+
+ Months = staticmethod(Months)
+ def Month(*args, **kwargs):
+ """Month() -> DateSpan"""
+ return _misc_.DateSpan_Month(*args, **kwargs)
+
+ Month = staticmethod(Month)
+ def Years(*args, **kwargs):
+ """Years(int years) -> DateSpan"""
+ return _misc_.DateSpan_Years(*args, **kwargs)
+
+ Years = staticmethod(Years)
+ def Year(*args, **kwargs):
+ """Year() -> DateSpan"""
+ return _misc_.DateSpan_Year(*args, **kwargs)
+
+ Year = staticmethod(Year)
+ def SetYears(*args, **kwargs):
+ """SetYears(self, int n) -> DateSpan"""
+ return _misc_.DateSpan_SetYears(*args, **kwargs)
+
+ def SetMonths(*args, **kwargs):
+ """SetMonths(self, int n) -> DateSpan"""
+ return _misc_.DateSpan_SetMonths(*args, **kwargs)
+
+ def SetWeeks(*args, **kwargs):
+ """SetWeeks(self, int n) -> DateSpan"""
+ return _misc_.DateSpan_SetWeeks(*args, **kwargs)
+
+ def SetDays(*args, **kwargs):
+ """SetDays(self, int n) -> DateSpan"""
+ return _misc_.DateSpan_SetDays(*args, **kwargs)
+
+ def GetYears(*args, **kwargs):
+ """GetYears(self) -> int"""
+ return _misc_.DateSpan_GetYears(*args, **kwargs)
+
+ def GetMonths(*args, **kwargs):
+ """GetMonths(self) -> int"""
+ return _misc_.DateSpan_GetMonths(*args, **kwargs)
+
+ def GetWeeks(*args, **kwargs):
+ """GetWeeks(self) -> int"""
+ return _misc_.DateSpan_GetWeeks(*args, **kwargs)
+
+ def GetDays(*args, **kwargs):
+ """GetDays(self) -> int"""
+ return _misc_.DateSpan_GetDays(*args, **kwargs)
+
+ def GetTotalDays(*args, **kwargs):
+ """GetTotalDays(self) -> int"""
+ return _misc_.DateSpan_GetTotalDays(*args, **kwargs)
+
+ def Add(*args, **kwargs):
+ """Add(self, DateSpan other) -> DateSpan"""
+ return _misc_.DateSpan_Add(*args, **kwargs)
+
+ def Subtract(*args, **kwargs):
+ """Subtract(self, DateSpan other) -> DateSpan"""
+ return _misc_.DateSpan_Subtract(*args, **kwargs)
+
+ def Neg(*args, **kwargs):
+ """Neg(self) -> DateSpan"""
+ return _misc_.DateSpan_Neg(*args, **kwargs)
+
+ def Multiply(*args, **kwargs):
+ """Multiply(self, int factor) -> DateSpan"""
+ return _misc_.DateSpan_Multiply(*args, **kwargs)
+
+ def __iadd__(*args, **kwargs):
+ """__iadd__(self, DateSpan other) -> DateSpan"""
+ return _misc_.DateSpan___iadd__(*args, **kwargs)
+
+ def __isub__(*args, **kwargs):
+ """__isub__(self, DateSpan other) -> DateSpan"""
+ return _misc_.DateSpan___isub__(*args, **kwargs)
+
+ def __neg__(*args, **kwargs):
+ """__neg__(self) -> DateSpan"""
+ return _misc_.DateSpan___neg__(*args, **kwargs)
+
+ def __imul__(*args, **kwargs):
+ """__imul__(self, int factor) -> DateSpan"""
+ return _misc_.DateSpan___imul__(*args, **kwargs)
+
+ def __add__(*args, **kwargs):
+ """__add__(self, DateSpan other) -> DateSpan"""
+ return _misc_.DateSpan___add__(*args, **kwargs)
+
+ def __sub__(*args, **kwargs):
+ """__sub__(self, DateSpan other) -> DateSpan"""
+ return _misc_.DateSpan___sub__(*args, **kwargs)
+
+ def __mul__(*args, **kwargs):
+ """__mul__(self, int n) -> DateSpan"""
+ return _misc_.DateSpan___mul__(*args, **kwargs)
+
+ def __rmul__(*args, **kwargs):
+ """__rmul__(self, int n) -> DateSpan"""
+ return _misc_.DateSpan___rmul__(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """__eq__(self, DateSpan other) -> bool"""
+ return _misc_.DateSpan___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """__ne__(self, DateSpan other) -> bool"""
+ return _misc_.DateSpan___ne__(*args, **kwargs)
+
+ days = property(GetDays,SetDays,doc="See `GetDays` and `SetDays`")
+ months = property(GetMonths,SetMonths,doc="See `GetMonths` and `SetMonths`")
+ totalDays = property(GetTotalDays,doc="See `GetTotalDays`")
+ weeks = property(GetWeeks,SetWeeks,doc="See `GetWeeks` and `SetWeeks`")
+ years = property(GetYears,SetYears,doc="See `GetYears` and `SetYears`")
+_misc_.DateSpan_swigregister(DateSpan)
+
+def DateSpan_Days(*args, **kwargs):
+ """DateSpan_Days(int days) -> DateSpan"""
+ return _misc_.DateSpan_Days(*args, **kwargs)
+
+def DateSpan_Day(*args):
+ """DateSpan_Day() -> DateSpan"""
+ return _misc_.DateSpan_Day(*args)
+
+def DateSpan_Weeks(*args, **kwargs):
+ """DateSpan_Weeks(int weeks) -> DateSpan"""
+ return _misc_.DateSpan_Weeks(*args, **kwargs)
+
+def DateSpan_Week(*args):
+ """DateSpan_Week() -> DateSpan"""
+ return _misc_.DateSpan_Week(*args)
+
+def DateSpan_Months(*args, **kwargs):
+ """DateSpan_Months(int mon) -> DateSpan"""
+ return _misc_.DateSpan_Months(*args, **kwargs)
+
+def DateSpan_Month(*args):
+ """DateSpan_Month() -> DateSpan"""
+ return _misc_.DateSpan_Month(*args)
+
+def DateSpan_Years(*args, **kwargs):
+ """DateSpan_Years(int years) -> DateSpan"""
+ return _misc_.DateSpan_Years(*args, **kwargs)
+
+def DateSpan_Year(*args):
+ """DateSpan_Year() -> DateSpan"""
+ return _misc_.DateSpan_Year(*args)
+
+
+def GetLocalTime(*args):
+ """GetLocalTime() -> long"""
+ return _misc_.GetLocalTime(*args)
+
+def GetUTCTime(*args):
+ """GetUTCTime() -> long"""
+ return _misc_.GetUTCTime(*args)
+
+def GetCurrentTime(*args):
+ """GetCurrentTime() -> long"""
+ return _misc_.GetCurrentTime(*args)
+
+def GetLocalTimeMillis(*args):
+ """GetLocalTimeMillis() -> wxLongLong"""
+ return _misc_.GetLocalTimeMillis(*args)
+#---------------------------------------------------------------------------
+
+DF_INVALID = _misc_.DF_INVALID
+DF_TEXT = _misc_.DF_TEXT
+DF_BITMAP = _misc_.DF_BITMAP
+DF_METAFILE = _misc_.DF_METAFILE
+DF_SYLK = _misc_.DF_SYLK
+DF_DIF = _misc_.DF_DIF
+DF_TIFF = _misc_.DF_TIFF
+DF_OEMTEXT = _misc_.DF_OEMTEXT
+DF_DIB = _misc_.DF_DIB
+DF_PALETTE = _misc_.DF_PALETTE
+DF_PENDATA = _misc_.DF_PENDATA
+DF_RIFF = _misc_.DF_RIFF
+DF_WAVE = _misc_.DF_WAVE
+DF_UNICODETEXT = _misc_.DF_UNICODETEXT
+DF_ENHMETAFILE = _misc_.DF_ENHMETAFILE
+DF_FILENAME = _misc_.DF_FILENAME
+DF_LOCALE = _misc_.DF_LOCALE
+DF_PRIVATE = _misc_.DF_PRIVATE
+DF_HTML = _misc_.DF_HTML
+DF_MAX = _misc_.DF_MAX
+class DataFormat(object):
+ """
+ A wx.DataFormat is an encapsulation of a platform-specific format
+ handle which is used by the system for the clipboard and drag and drop
+ operations. The applications are usually only interested in, for
+ example, pasting data from the clipboard only if the data is in a
+ format the program understands. A data format is is used to uniquely
+ identify this format.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int type) -> DataFormat
+
+ Constructs a data format object for one of the standard data formats
+ or an empty data object (use SetType or SetId later in this case)
+ """
+ _misc_.DataFormat_swiginit(self,_misc_.new_DataFormat(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_DataFormat
+ __del__ = lambda self : None;
+ def __eq__(*args):
+ """
+ __eq__(self, int format) -> bool
+ __eq__(self, DataFormat format) -> bool
+ """
+ return _misc_.DataFormat___eq__(*args)
+
+ def __ne__(*args):
+ """
+ __ne__(self, int format) -> bool
+ __ne__(self, DataFormat format) -> bool
+ """
+ return _misc_.DataFormat___ne__(*args)
+
+ def SetType(*args, **kwargs):
+ """
+ SetType(self, int format)
+
+ Sets the format to the given value, which should be one of wx.DF_XXX
+ constants.
+ """
+ return _misc_.DataFormat_SetType(*args, **kwargs)
+
+ def GetType(*args, **kwargs):
+ """
+ GetType(self) -> int
+
+ Returns the platform-specific number identifying the format.
+ """
+ return _misc_.DataFormat_GetType(*args, **kwargs)
+
+ def _GetId(*args, **kwargs):
+ """_GetId(self) -> String"""
+ return _misc_.DataFormat__GetId(*args, **kwargs)
+
+ def GetId(self):
+ """Returns the name of a custom format (this function will fail for a
+ format)."""
+ nolog = wx.LogNull()
+ return self._GetId()
+
+ def SetId(*args, **kwargs):
+ """
+ SetId(self, String format)
+
+ Sets the format to be the custom format identified by the given name.
+ """
+ return _misc_.DataFormat_SetId(*args, **kwargs)
+
+ Id = property(GetId,SetId,doc="See `GetId` and `SetId`")
+ Type = property(GetType,SetType,doc="See `GetType` and `SetType`")
+_misc_.DataFormat_swigregister(DataFormat)
+DefaultDateTime = cvar.DefaultDateTime
+
+def CustomDataFormat(*args, **kwargs):
+ """
+ CustomDataFormat(String format) -> DataFormat
+
+ Constructs a data format object for a custom format identified by its
+ name.
+ """
+ val = _misc_.new_CustomDataFormat(*args, **kwargs)
+ return val
+
+class DataObject(object):
+ """
+ A wx.DataObject represents data that can be copied to or from the
+ clipboard, or dragged and dropped. The important thing about
+ wx.DataObject is that this is a 'smart' piece of data unlike usual
+ 'dumb' data containers such as memory buffers or files. Being 'smart'
+ here means that the data object itself should know what data formats
+ it supports and how to render itself in each of supported formats.
+
+ **NOTE**: This class is an abstract base class and can not be used
+ directly from Python. If you need a custom type of data object then
+ you should instead derive from `wx.PyDataObjectSimple` or use
+ `wx.CustomDataObject`.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ Get = _misc_.DataObject_Get
+ Set = _misc_.DataObject_Set
+ Both = _misc_.DataObject_Both
+ __swig_destroy__ = _misc_.delete_DataObject
+ __del__ = lambda self : None;
+ def GetPreferredFormat(*args, **kwargs):
+ """
+ GetPreferredFormat(self, int dir=Get) -> DataFormat
+
+ Returns the preferred format for either rendering the data (if dir is
+ Get, its default value) or for setting it. Usually this will be the
+ native format of the wx.DataObject.
+ """
+ return _misc_.DataObject_GetPreferredFormat(*args, **kwargs)
+
+ def GetFormatCount(*args, **kwargs):
+ """
+ GetFormatCount(self, int dir=Get) -> size_t
+
+ Returns the number of available formats for rendering or setting the
+ data.
+ """
+ return _misc_.DataObject_GetFormatCount(*args, **kwargs)
+
+ def IsSupported(*args, **kwargs):
+ """
+ IsSupported(self, DataFormat format, int dir=Get) -> bool
+
+ Returns True if this format is supported.
+ """
+ return _misc_.DataObject_IsSupported(*args, **kwargs)
+
+ def GetDataSize(*args, **kwargs):
+ """
+ GetDataSize(self, DataFormat format) -> size_t
+
+ Get the (total) size of data for the given format
+ """
+ return _misc_.DataObject_GetDataSize(*args, **kwargs)
+
+ def GetAllFormats(*args, **kwargs):
+ """
+ GetAllFormats(self, int dir=Get) -> [formats]
+
+ Returns a list of all the wx.DataFormats that this dataobject supports
+ in the given direction.
+ """
+ return _misc_.DataObject_GetAllFormats(*args, **kwargs)
+
+ def GetDataHere(*args, **kwargs):
+ """
+ GetDataHere(self, DataFormat format) -> String
+
+ Get the data bytes in the specified format, returns None on failure.
+ """
+ return _misc_.DataObject_GetDataHere(*args, **kwargs)
+
+ def SetData(*args, **kwargs):
+ """
+ SetData(self, DataFormat format, String data) -> bool
+
+ Set the data in the specified format from the bytes in the the data string.
+
+ """
+ return _misc_.DataObject_SetData(*args, **kwargs)
+
+ AllFormats = property(GetAllFormats,doc="See `GetAllFormats`")
+ DataHere = property(GetDataHere,doc="See `GetDataHere`")
+ DataSize = property(GetDataSize,doc="See `GetDataSize`")
+ FormatCount = property(GetFormatCount,doc="See `GetFormatCount`")
+ PreferredFormat = property(GetPreferredFormat,doc="See `GetPreferredFormat`")
+_misc_.DataObject_swigregister(DataObject)
+FormatInvalid = cvar.FormatInvalid
+
+class DataObjectSimple(DataObject):
+ """
+ wx.DataObjectSimple is a `wx.DataObject` which only supports one
+ format. This is the simplest possible `wx.DataObject` implementation.
+
+ This is still an "abstract base class" meaning that you can't use it
+ directly. You either need to use one of the predefined base classes,
+ or derive your own class from `wx.PyDataObjectSimple`.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, DataFormat format=FormatInvalid) -> DataObjectSimple
+
+ Constructor accepts the supported format (none by default) which may
+ also be set later with `SetFormat`.
+ """
+ _misc_.DataObjectSimple_swiginit(self,_misc_.new_DataObjectSimple(*args, **kwargs))
+ def GetFormat(*args, **kwargs):
+ """
+ GetFormat(self) -> DataFormat
+
+ Returns the (one and only one) format supported by this object. It is
+ assumed that the format is supported in both directions.
+ """
+ return _misc_.DataObjectSimple_GetFormat(*args, **kwargs)
+
+ def SetFormat(*args, **kwargs):
+ """
+ SetFormat(self, DataFormat format)
+
+ Sets the supported format.
+ """
+ return _misc_.DataObjectSimple_SetFormat(*args, **kwargs)
+
+ def GetDataSize(*args, **kwargs):
+ """
+ GetDataSize(self) -> size_t
+
+ Get the size of our data.
+ """
+ return _misc_.DataObjectSimple_GetDataSize(*args, **kwargs)
+
+ def GetDataHere(*args, **kwargs):
+ """
+ GetDataHere(self) -> String
+
+ Returns the data bytes from the data object as a string, returns None
+ on failure. Must be implemented in the derived class if the object
+ supports rendering its data.
+ """
+ return _misc_.DataObjectSimple_GetDataHere(*args, **kwargs)
+
+ def SetData(*args, **kwargs):
+ """
+ SetData(self, String data) -> bool
+
+ Copy the data value to the data object. Must be implemented in the
+ derived class if the object supports setting its data.
+
+ """
+ return _misc_.DataObjectSimple_SetData(*args, **kwargs)
+
+ Format = property(GetFormat,SetFormat,doc="See `GetFormat` and `SetFormat`")
+_misc_.DataObjectSimple_swigregister(DataObjectSimple)
+
+class PyDataObjectSimple(DataObjectSimple):
+ """
+ wx.PyDataObjectSimple is a version of `wx.DataObjectSimple` that is
+ Python-aware and knows how to reflect calls to its C++ virtual methods
+ to methods in the Python derived class. You should derive from this
+ class and overload `GetDataSize`, `GetDataHere` and `SetData` when you
+ need to create your own simple single-format type of `wx.DataObject`.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, DataFormat format=FormatInvalid) -> PyDataObjectSimple
+
+ wx.PyDataObjectSimple is a version of `wx.DataObjectSimple` that is
+ Python-aware and knows how to reflect calls to its C++ virtual methods
+ to methods in the Python derived class. You should derive from this
+ class and overload `GetDataSize`, `GetDataHere` and `SetData` when you
+ need to create your own simple single-format type of `wx.DataObject`.
+
+ """
+ _misc_.PyDataObjectSimple_swiginit(self,_misc_.new_PyDataObjectSimple(*args, **kwargs))
+ PyDataObjectSimple._setCallbackInfo(self, self, PyDataObjectSimple)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _misc_.PyDataObjectSimple__setCallbackInfo(*args, **kwargs)
+
+_misc_.PyDataObjectSimple_swigregister(PyDataObjectSimple)
+
+class DataObjectComposite(DataObject):
+ """
+ wx.DataObjectComposite is the simplest `wx.DataObject` derivation
+ which may be used to support multiple formats. It contains several
+ 'wx.DataObjectSimple` objects and supports any format supported by at
+ least one of them. Only one of these data objects is *preferred* (the
+ first one if not explicitly changed by using the second parameter of
+ `Add`) and its format determines the preferred format of the composite
+ data object as well.
+
+ See `wx.DataObject` documentation for the reasons why you might prefer
+ to use wx.DataObject directly instead of wx.DataObjectComposite for
+ efficiency reasons.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> DataObjectComposite
+
+ wx.DataObjectComposite is the simplest `wx.DataObject` derivation
+ which may be used to support multiple formats. It contains several
+ 'wx.DataObjectSimple` objects and supports any format supported by at
+ least one of them. Only one of these data objects is *preferred* (the
+ first one if not explicitly changed by using the second parameter of
+ `Add`) and its format determines the preferred format of the composite
+ data object as well.
+
+ See `wx.DataObject` documentation for the reasons why you might prefer
+ to use wx.DataObject directly instead of wx.DataObjectComposite for
+ efficiency reasons.
+
+ """
+ _misc_.DataObjectComposite_swiginit(self,_misc_.new_DataObjectComposite(*args, **kwargs))
+ def Add(*args, **kwargs):
+ """
+ Add(self, DataObjectSimple dataObject, bool preferred=False)
+
+ Adds the dataObject to the list of supported objects and it becomes
+ the preferred object if preferred is True.
+ """
+ return _misc_.DataObjectComposite_Add(*args, **kwargs)
+
+ def GetReceivedFormat(*args, **kwargs):
+ """
+ GetReceivedFormat(self) -> DataFormat
+
+ Report the format passed to the `SetData` method. This should be the
+ format of the data object within the composite that recieved data from
+ the clipboard or the DnD operation. You can use this method to find
+ out what kind of data object was recieved.
+ """
+ return _misc_.DataObjectComposite_GetReceivedFormat(*args, **kwargs)
+
+ ReceivedFormat = property(GetReceivedFormat,doc="See `GetReceivedFormat`")
+ def GetObject(*args, **kwargs):
+ """
+ GetObject(self, DataFormat format, wxDataObjectBase::Direction dir=Get) -> DataObjectSimple
+
+ Returns the pointer to the object which supports this format or None.
+ TODO: Fix this to use OOR and return the right object type.
+ """
+ return _misc_.DataObjectComposite_GetObject(*args, **kwargs)
+
+_misc_.DataObjectComposite_swigregister(DataObjectComposite)
+
+class TextDataObject(DataObjectSimple):
+ """
+ wx.TextDataObject is a specialization of `wx.DataObject` for text
+ data. It can be used without change to paste data into the `wx.Clipboard`
+ or a `wx.DropSource`.
+
+ Alternativly, you may wish to derive a new class from the
+ `wx.PyTextDataObject` class for providing text on-demand in order to
+ minimize memory consumption when offering data in several formats,
+ such as plain text and RTF, because by default the text is stored in a
+ string in this class, but it might as well be generated on demand when
+ requested. For this, `GetTextLength` and `GetText` will have to be
+ overridden.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String text=EmptyString) -> TextDataObject
+
+ Constructor, may be used to initialise the text (otherwise `SetText`
+ should be used later).
+ """
+ _misc_.TextDataObject_swiginit(self,_misc_.new_TextDataObject(*args, **kwargs))
+ def GetTextLength(*args, **kwargs):
+ """
+ GetTextLength(self) -> size_t
+
+ Returns the data size. By default, returns the size of the text data
+ set in the constructor or using `SetText`. This can be overridden (via
+ `wx.PyTextDataObject`) to provide text size data on-demand. It is
+ recommended to return the text length plus 1 for a trailing zero, but
+ this is not strictly required.
+ """
+ return _misc_.TextDataObject_GetTextLength(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """
+ GetText(self) -> String
+
+ Returns the text associated with the data object.
+ """
+ return _misc_.TextDataObject_GetText(*args, **kwargs)
+
+ def SetText(*args, **kwargs):
+ """
+ SetText(self, String text)
+
+ Sets the text associated with the data object. This method is called
+ when the data object receives the data and, by default, copies the
+ text into the member variable. If you want to process the text on the
+ fly you may wish to override this function (via
+ `wx.PyTextDataObject`.)
+ """
+ return _misc_.TextDataObject_SetText(*args, **kwargs)
+
+ Text = property(GetText,SetText,doc="See `GetText` and `SetText`")
+ TextLength = property(GetTextLength,doc="See `GetTextLength`")
+_misc_.TextDataObject_swigregister(TextDataObject)
+
+class PyTextDataObject(TextDataObject):
+ """
+ wx.PyTextDataObject is a version of `wx.TextDataObject` that is
+ Python-aware and knows how to reflect calls to its C++ virtual methods
+ to methods in the Python derived class. You should derive from this
+ class and overload `GetTextLength`, `GetText`, and `SetText` when you
+ want to be able to provide text on demand instead of preloading it
+ into the data object.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String text=EmptyString) -> PyTextDataObject
+
+ wx.PyTextDataObject is a version of `wx.TextDataObject` that is
+ Python-aware and knows how to reflect calls to its C++ virtual methods
+ to methods in the Python derived class. You should derive from this
+ class and overload `GetTextLength`, `GetText`, and `SetText` when you
+ want to be able to provide text on demand instead of preloading it
+ into the data object.
+ """
+ _misc_.PyTextDataObject_swiginit(self,_misc_.new_PyTextDataObject(*args, **kwargs))
+ PyTextDataObject._setCallbackInfo(self, self, PyTextDataObject)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _misc_.PyTextDataObject__setCallbackInfo(*args, **kwargs)
+
+_misc_.PyTextDataObject_swigregister(PyTextDataObject)
+
+class BitmapDataObject(DataObjectSimple):
+ """
+ wx.BitmapDataObject is a specialization of wxDataObject for bitmap
+ data. It can be used without change to paste data into the `wx.Clipboard`
+ or a `wx.DropSource`.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Bitmap bitmap=wxNullBitmap) -> BitmapDataObject
+
+ Constructor, optionally passing a bitmap (otherwise use `SetBitmap`
+ later).
+ """
+ _misc_.BitmapDataObject_swiginit(self,_misc_.new_BitmapDataObject(*args, **kwargs))
+ def GetBitmap(*args, **kwargs):
+ """
+ GetBitmap(self) -> Bitmap
+
+ Returns the bitmap associated with the data object. You may wish to
+ override this method (by deriving from `wx.PyBitmapDataObject`) when
+ offering data on-demand, but this is not required by wxWidgets'
+ internals. Use this method to get data in bitmap form from the
+ `wx.Clipboard`.
+ """
+ return _misc_.BitmapDataObject_GetBitmap(*args, **kwargs)
+
+ def SetBitmap(*args, **kwargs):
+ """
+ SetBitmap(self, Bitmap bitmap)
+
+ Sets the bitmap associated with the data object. This method is called
+ when the data object receives data. Usually there will be no reason to
+ override this function.
+ """
+ return _misc_.BitmapDataObject_SetBitmap(*args, **kwargs)
+
+ Bitmap = property(GetBitmap,SetBitmap,doc="See `GetBitmap` and `SetBitmap`")
+_misc_.BitmapDataObject_swigregister(BitmapDataObject)
+
+class PyBitmapDataObject(BitmapDataObject):
+ """
+ wx.PyBitmapDataObject is a version of `wx.BitmapDataObject` that is
+ Python-aware and knows how to reflect calls to its C++ virtual methods
+ to methods in the Python derived class. To be able to provide bitmap
+ data on demand derive from this class and overload `GetBitmap`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Bitmap bitmap=wxNullBitmap) -> PyBitmapDataObject
+
+ wx.PyBitmapDataObject is a version of `wx.BitmapDataObject` that is
+ Python-aware and knows how to reflect calls to its C++ virtual methods
+ to methods in the Python derived class. To be able to provide bitmap
+ data on demand derive from this class and overload `GetBitmap`.
+ """
+ _misc_.PyBitmapDataObject_swiginit(self,_misc_.new_PyBitmapDataObject(*args, **kwargs))
+ PyBitmapDataObject._setCallbackInfo(self, self, PyBitmapDataObject)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _misc_.PyBitmapDataObject__setCallbackInfo(*args, **kwargs)
+
+_misc_.PyBitmapDataObject_swigregister(PyBitmapDataObject)
+
+class FileDataObject(DataObjectSimple):
+ """
+ wx.FileDataObject is a specialization of `wx.DataObjectSimple` for
+ file names. The program works with it just as if it were a list of
+ absolute file names, but internally it uses the same format as
+ Explorer and other compatible programs under Windows or GNOME/KDE
+ filemanager under Unix which makes it possible to receive files from
+ them using this class.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> FileDataObject"""
+ _misc_.FileDataObject_swiginit(self,_misc_.new_FileDataObject(*args, **kwargs))
+ def GetFilenames(*args, **kwargs):
+ """
+ GetFilenames(self) -> [names]
+
+ Returns a list of file names.
+ """
+ return _misc_.FileDataObject_GetFilenames(*args, **kwargs)
+
+ def AddFile(*args, **kwargs):
+ """
+ AddFile(self, String filename)
+
+ Adds a file to the list of files represented by this data object.
+ """
+ return _misc_.FileDataObject_AddFile(*args, **kwargs)
+
+ Filenames = property(GetFilenames,doc="See `GetFilenames`")
+_misc_.FileDataObject_swigregister(FileDataObject)
+
+class CustomDataObject(DataObjectSimple):
+ """
+ wx.CustomDataObject is a specialization of `wx.DataObjectSimple` for
+ some application-specific data in arbitrary format. Python strings
+ are used for getting and setting data, but any picklable object can
+ easily be transfered via strings. A copy of the data is stored in the
+ data object.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, DataFormat format) -> CustomDataObject
+ __init__(self, String formatName) -> CustomDataObject
+ __init__(self) -> CustomDataObject
+
+ wx.CustomDataObject is a specialization of `wx.DataObjectSimple` for
+ some application-specific data in arbitrary format. Python strings
+ are used for getting and setting data, but any picklable object can
+ easily be transfered via strings. A copy of the data is stored in the
+ data object.
+ """
+ _misc_.CustomDataObject_swiginit(self,_misc_.new_CustomDataObject(*args))
+ def SetData(*args, **kwargs):
+ """
+ SetData(self, String data) -> bool
+
+ Copy the data value to the data object.
+ """
+ return _misc_.CustomDataObject_SetData(*args, **kwargs)
+
+ TakeData = SetData
+ def GetSize(*args, **kwargs):
+ """
+ GetSize(self) -> size_t
+
+ Get the size of the data.
+ """
+ return _misc_.CustomDataObject_GetSize(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """
+ GetData(self) -> String
+
+ Returns the data bytes from the data object as a string.
+ """
+ return _misc_.CustomDataObject_GetData(*args, **kwargs)
+
+ Data = property(GetData,SetData,doc="See `GetData` and `SetData`")
+ Size = property(GetSize,doc="See `GetSize`")
+_misc_.CustomDataObject_swigregister(CustomDataObject)
+
+class URLDataObject(DataObject):
+ """
+ This data object holds a URL in a format that is compatible with some
+ browsers such that it is able to be dragged to or from them.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String url=EmptyString) -> URLDataObject
+
+ This data object holds a URL in a format that is compatible with some
+ browsers such that it is able to be dragged to or from them.
+ """
+ _misc_.URLDataObject_swiginit(self,_misc_.new_URLDataObject(*args, **kwargs))
+ def GetURL(*args, **kwargs):
+ """
+ GetURL(self) -> String
+
+ Returns a string containing the current URL.
+ """
+ return _misc_.URLDataObject_GetURL(*args, **kwargs)
+
+ def SetURL(*args, **kwargs):
+ """
+ SetURL(self, String url)
+
+ Set the URL.
+ """
+ return _misc_.URLDataObject_SetURL(*args, **kwargs)
+
+ URL = property(GetURL,SetURL,doc="See `GetURL` and `SetURL`")
+_misc_.URLDataObject_swigregister(URLDataObject)
+
+class HTMLDataObject(DataObjectSimple):
+ """Proxy of C++ HTMLDataObject class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String html=wxEmptyString) -> HTMLDataObject"""
+ _misc_.HTMLDataObject_swiginit(self,_misc_.new_HTMLDataObject(*args, **kwargs))
+ def GetHTML(*args, **kwargs):
+ """GetHTML(self) -> String"""
+ return _misc_.HTMLDataObject_GetHTML(*args, **kwargs)
+
+ def SetHTML(*args, **kwargs):
+ """SetHTML(self, String html)"""
+ return _misc_.HTMLDataObject_SetHTML(*args, **kwargs)
+
+ HTML = property(GetHTML,SetHTML)
+_misc_.HTMLDataObject_swigregister(HTMLDataObject)
+
+class MetafileDataObject(DataObjectSimple):
+ """Proxy of C++ MetafileDataObject class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> MetafileDataObject"""
+ _misc_.MetafileDataObject_swiginit(self,_misc_.new_MetafileDataObject(*args, **kwargs))
+ def SetMetafile(*args, **kwargs):
+ """SetMetafile(self, MetaFile metafile)"""
+ return _misc_.MetafileDataObject_SetMetafile(*args, **kwargs)
+
+ def GetMetafile(*args, **kwargs):
+ """GetMetafile(self) -> MetaFile"""
+ return _misc_.MetafileDataObject_GetMetafile(*args, **kwargs)
+
+_misc_.MetafileDataObject_swigregister(MetafileDataObject)
+
+#---------------------------------------------------------------------------
+
+Drag_CopyOnly = _misc_.Drag_CopyOnly
+Drag_AllowMove = _misc_.Drag_AllowMove
+Drag_DefaultMove = _misc_.Drag_DefaultMove
+DragError = _misc_.DragError
+DragNone = _misc_.DragNone
+DragCopy = _misc_.DragCopy
+DragMove = _misc_.DragMove
+DragLink = _misc_.DragLink
+DragCancel = _misc_.DragCancel
+
+def IsDragResultOk(*args, **kwargs):
+ """IsDragResultOk(int res) -> bool"""
+ return _misc_.IsDragResultOk(*args, **kwargs)
+class DropSource(object):
+ """Proxy of C++ DropSource class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window win, Cursor copy=wxNullCursor, Cursor move=wxNullCursor,
+ Cursor none=wxNullCursor) -> DropSource
+ """
+ _misc_.DropSource_swiginit(self,_misc_.new_DropSource(*args, **kwargs))
+ DropSource._setCallbackInfo(self, self, DropSource)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class, int incref=0)"""
+ return _misc_.DropSource__setCallbackInfo(*args, **kwargs)
+
+ __swig_destroy__ = _misc_.delete_DropSource
+ __del__ = lambda self : None;
+ def SetData(*args, **kwargs):
+ """SetData(self, DataObject data)"""
+ return _misc_.DropSource_SetData(*args, **kwargs)
+
+ def GetDataObject(*args, **kwargs):
+ """GetDataObject(self) -> DataObject"""
+ return _misc_.DropSource_GetDataObject(*args, **kwargs)
+
+ def SetCursor(*args, **kwargs):
+ """SetCursor(self, int res, Cursor cursor)"""
+ return _misc_.DropSource_SetCursor(*args, **kwargs)
+
+ def DoDragDrop(*args, **kwargs):
+ """DoDragDrop(self, int flags=Drag_CopyOnly) -> int"""
+ return _misc_.DropSource_DoDragDrop(*args, **kwargs)
+
+ def GiveFeedback(*args, **kwargs):
+ """GiveFeedback(self, int effect) -> bool"""
+ return _misc_.DropSource_GiveFeedback(*args, **kwargs)
+
+ def base_GiveFeedback(*args, **kw):
+ return DropSource.GiveFeedback(*args, **kw)
+ base_GiveFeedback = wx.deprecated(base_GiveFeedback,
+ "Please use DropSource.GiveFeedback instead.")
+
+ DataObject = property(GetDataObject,SetData,doc="See `GetDataObject` and `SetData`")
+_misc_.DropSource_swigregister(DropSource)
+
+def DROP_ICON(filename):
+ """
+ Returns either a `wx.Cursor` or `wx.Icon` created from the image file
+ ``filename``. This function is useful with the `wx.DropSource` class
+ which, depending on platform accepts either an icon or a cursor.
+ """
+ img = wx.Image(filename)
+ if wx.Platform == '__WXGTK__':
+ return wx.IconFromBitmap(wx.BitmapFromImage(img))
+ else:
+ return wx.CursorFromImage(img)
+
+class DropTarget(object):
+ """Proxy of C++ DropTarget class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, DataObject dataObject=None) -> DropTarget"""
+ _misc_.DropTarget_swiginit(self,_misc_.new_DropTarget(*args, **kwargs))
+ DropTarget._setCallbackInfo(self, self, DropTarget)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _misc_.DropTarget__setCallbackInfo(*args, **kwargs)
+
+ __swig_destroy__ = _misc_.delete_DropTarget
+ __del__ = lambda self : None;
+ def GetDataObject(*args, **kwargs):
+ """GetDataObject(self) -> DataObject"""
+ return _misc_.DropTarget_GetDataObject(*args, **kwargs)
+
+ def SetDataObject(*args, **kwargs):
+ """SetDataObject(self, DataObject dataObject)"""
+ return _misc_.DropTarget_SetDataObject(*args, **kwargs)
+
+ def OnEnter(*args, **kwargs):
+ """OnEnter(self, int x, int y, int def) -> int"""
+ return _misc_.DropTarget_OnEnter(*args, **kwargs)
+
+ def OnDragOver(*args, **kwargs):
+ """OnDragOver(self, int x, int y, int def) -> int"""
+ return _misc_.DropTarget_OnDragOver(*args, **kwargs)
+
+ def OnLeave(*args, **kwargs):
+ """OnLeave(self)"""
+ return _misc_.DropTarget_OnLeave(*args, **kwargs)
+
+ def OnDrop(*args, **kwargs):
+ """OnDrop(self, int x, int y) -> bool"""
+ return _misc_.DropTarget_OnDrop(*args, **kwargs)
+
+ def base_OnEnter(*args, **kw):
+ return DropTarget.OnEnter(*args, **kw)
+ base_OnEnter = wx.deprecated(base_OnEnter,
+ "Please use DropTarget.OnEnter instead.")
+
+ def base_OnDragOver(*args, **kw):
+ return DropTarget.OnDragOver(*args, **kw)
+ base_OnDragOver = wx.deprecated(base_OnDragOver,
+ "Please use DropTarget.OnDragOver instead.")
+
+ def base_OnLeave(*args, **kw):
+ return DropTarget.OnLeave(*args, **kw)
+ base_OnLeave = wx.deprecated(base_OnLeave,
+ "Please use DropTarget.OnLeave instead.")
+
+ def base_OnDrop(*args, **kw):
+ return DropTarget.OnDrop(*args, **kw)
+ base_OnDrop = wx.deprecated(base_OnDrop,
+ "Please use DropTarget.OnDrop instead.")
+
+ def GetData(*args, **kwargs):
+ """GetData(self) -> bool"""
+ return _misc_.DropTarget_GetData(*args, **kwargs)
+
+ def SetDefaultAction(*args, **kwargs):
+ """SetDefaultAction(self, int action)"""
+ return _misc_.DropTarget_SetDefaultAction(*args, **kwargs)
+
+ def GetDefaultAction(*args, **kwargs):
+ """GetDefaultAction(self) -> int"""
+ return _misc_.DropTarget_GetDefaultAction(*args, **kwargs)
+
+ DataObject = property(GetDataObject,SetDataObject,doc="See `GetDataObject` and `SetDataObject`")
+ DefaultAction = property(GetDefaultAction,SetDefaultAction,doc="See `GetDefaultAction` and `SetDefaultAction`")
+_misc_.DropTarget_swigregister(DropTarget)
+
+PyDropTarget = DropTarget
+class TextDropTarget(DropTarget):
+ """Proxy of C++ TextDropTarget class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> TextDropTarget"""
+ _misc_.TextDropTarget_swiginit(self,_misc_.new_TextDropTarget(*args, **kwargs))
+ TextDropTarget._setCallbackInfo(self, self, TextDropTarget)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _misc_.TextDropTarget__setCallbackInfo(*args, **kwargs)
+
+ def OnDropText(*args, **kwargs):
+ """OnDropText(self, int x, int y, String text) -> bool"""
+ return _misc_.TextDropTarget_OnDropText(*args, **kwargs)
+
+ def OnEnter(*args, **kwargs):
+ """OnEnter(self, int x, int y, int def) -> int"""
+ return _misc_.TextDropTarget_OnEnter(*args, **kwargs)
+
+ def OnDragOver(*args, **kwargs):
+ """OnDragOver(self, int x, int y, int def) -> int"""
+ return _misc_.TextDropTarget_OnDragOver(*args, **kwargs)
+
+ def OnLeave(*args, **kwargs):
+ """OnLeave(self)"""
+ return _misc_.TextDropTarget_OnLeave(*args, **kwargs)
+
+ def OnDrop(*args, **kwargs):
+ """OnDrop(self, int x, int y) -> bool"""
+ return _misc_.TextDropTarget_OnDrop(*args, **kwargs)
+
+ def OnData(*args, **kwargs):
+ """OnData(self, int x, int y, int def) -> int"""
+ return _misc_.TextDropTarget_OnData(*args, **kwargs)
+
+ def base_OnDropText(*args, **kw):
+ return TextDropTarget.OnDropText(*args, **kw)
+ base_OnDropText = wx.deprecated(base_OnDropText,
+ "Please use TextDropTarget.OnDropText instead.")
+
+ def base_OnEnter(*args, **kw):
+ return TextDropTarget.OnEnter(*args, **kw)
+ base_OnEnter = wx.deprecated(base_OnEnter,
+ "Please use TextDropTarget.OnEnter instead.")
+
+ def base_OnDragOver(*args, **kw):
+ return TextDropTarget.OnDragOver(*args, **kw)
+ base_OnDragOver = wx.deprecated(base_OnDragOver,
+ "Please use TextDropTarget.OnDragOver instead.")
+
+ def base_OnLeave(*args, **kw):
+ return TextDropTarget.OnLeave(*args, **kw)
+ base_OnLeave = wx.deprecated(base_OnLeave,
+ "Please use TextDropTarget.OnLeave instead.")
+
+ def base_OnDrop(*args, **kw):
+ return TextDropTarget.OnDrop(*args, **kw)
+ base_OnDrop = wx.deprecated(base_OnDrop,
+ "Please use TextDropTarget.OnDrop instead.")
+
+ def base_OnData(*args, **kw):
+ return TextDropTarget.OnData(*args, **kw)
+ base_OnData = wx.deprecated(base_OnData,
+ "Please use TextDropTarget.OnData instead.")
+
+_misc_.TextDropTarget_swigregister(TextDropTarget)
+
+class FileDropTarget(DropTarget):
+ """Proxy of C++ FileDropTarget class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> FileDropTarget"""
+ _misc_.FileDropTarget_swiginit(self,_misc_.new_FileDropTarget(*args, **kwargs))
+ FileDropTarget._setCallbackInfo(self, self, FileDropTarget)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _misc_.FileDropTarget__setCallbackInfo(*args, **kwargs)
+
+ def OnDropFiles(*args, **kwargs):
+ """OnDropFiles(self, int x, int y, wxArrayString filenames) -> bool"""
+ return _misc_.FileDropTarget_OnDropFiles(*args, **kwargs)
+
+ def OnEnter(*args, **kwargs):
+ """OnEnter(self, int x, int y, int def) -> int"""
+ return _misc_.FileDropTarget_OnEnter(*args, **kwargs)
+
+ def OnDragOver(*args, **kwargs):
+ """OnDragOver(self, int x, int y, int def) -> int"""
+ return _misc_.FileDropTarget_OnDragOver(*args, **kwargs)
+
+ def OnLeave(*args, **kwargs):
+ """OnLeave(self)"""
+ return _misc_.FileDropTarget_OnLeave(*args, **kwargs)
+
+ def OnDrop(*args, **kwargs):
+ """OnDrop(self, int x, int y) -> bool"""
+ return _misc_.FileDropTarget_OnDrop(*args, **kwargs)
+
+ def OnData(*args, **kwargs):
+ """OnData(self, int x, int y, int def) -> int"""
+ return _misc_.FileDropTarget_OnData(*args, **kwargs)
+
+ def base_OnDropFiles(*args, **kw):
+ return FileDropTarget.OnDropFiles(*args, **kw)
+ base_OnDropFiles = wx.deprecated(base_OnDropFiles,
+ "Please use FileDropTarget.OnDropFiles instead.")
+
+ def base_OnEnter(*args, **kw):
+ return FileDropTarget.OnEnter(*args, **kw)
+ base_OnEnter = wx.deprecated(base_OnEnter,
+ "Please use FileDropTarget.OnEnter instead.")
+
+ def base_OnDragOver(*args, **kw):
+ return FileDropTarget.OnDragOver(*args, **kw)
+ base_OnDragOver = wx.deprecated(base_OnDragOver,
+ "Please use FileDropTarget.OnDragOver instead.")
+
+ def base_OnLeave(*args, **kw):
+ return FileDropTarget.OnLeave(*args, **kw)
+ base_OnLeave = wx.deprecated(base_OnLeave,
+ "Please use FileDropTarget.OnLeave instead.")
+
+ def base_OnDrop(*args, **kw):
+ return FileDropTarget.OnDrop(*args, **kw)
+ base_OnDrop = wx.deprecated(base_OnDrop,
+ "Please use FileDropTarget.OnDrop instead.")
+
+ def base_OnData(*args, **kw):
+ return FileDropTarget.OnData(*args, **kw)
+ base_OnData = wx.deprecated(base_OnData,
+ "Please use FileDropTarget.OnData instead.")
+
+_misc_.FileDropTarget_swigregister(FileDropTarget)
+
+#---------------------------------------------------------------------------
+
+class Clipboard(_core.Object):
+ """
+ wx.Clipboard represents the system clipboard and provides methods to
+ copy data to it or paste data from it. Normally, you should only use
+ ``wx.TheClipboard`` which is a reference to a global wx.Clipboard
+ instance.
+
+ Call ``wx.TheClipboard``'s `Open` method to get ownership of the
+ clipboard. If this operation returns True, you now own the
+ clipboard. Call `SetData` to put data on the clipboard, or `GetData`
+ to retrieve data from the clipboard. Call `Close` to close the
+ clipboard and relinquish ownership. You should keep the clipboard open
+ only momentarily.
+
+ :see: `wx.DataObject`
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> Clipboard"""
+ _misc_.Clipboard_swiginit(self,_misc_.new_Clipboard(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_Clipboard
+ __del__ = lambda self : None;
+ def Open(*args, **kwargs):
+ """
+ Open(self) -> bool
+
+ Call this function to open the clipboard before calling SetData and
+ GetData. Call Close when you have finished with the clipboard. You
+ should keep the clipboard open for only a very short time. Returns
+ True on success.
+ """
+ return _misc_.Clipboard_Open(*args, **kwargs)
+
+ def Close(*args, **kwargs):
+ """
+ Close(self)
+
+ Closes the clipboard.
+ """
+ return _misc_.Clipboard_Close(*args, **kwargs)
+
+ def IsOpened(*args, **kwargs):
+ """
+ IsOpened(self) -> bool
+
+ Query whether the clipboard is opened
+ """
+ return _misc_.Clipboard_IsOpened(*args, **kwargs)
+
+ def AddData(*args, **kwargs):
+ """
+ AddData(self, DataObject data) -> bool
+
+ Call this function to add the data object to the clipboard. You may
+ call this function repeatedly after having cleared the clipboard.
+ After this function has been called, the clipboard owns the data, so
+ do not delete the data explicitly.
+
+ :see: `wx.DataObject`
+ """
+ return _misc_.Clipboard_AddData(*args, **kwargs)
+
+ def SetData(*args, **kwargs):
+ """
+ SetData(self, DataObject data) -> bool
+
+ Set the clipboard data, this is the same as `Clear` followed by
+ `AddData`.
+
+ :see: `wx.DataObject`
+ """
+ return _misc_.Clipboard_SetData(*args, **kwargs)
+
+ def IsSupported(*args, **kwargs):
+ """
+ IsSupported(self, DataFormat format) -> bool
+
+ Returns True if the given format is available in the data object(s) on
+ the clipboard.
+ """
+ return _misc_.Clipboard_IsSupported(*args, **kwargs)
+
+ def IsSupportedAsync(*args, **kwargs):
+ """IsSupportedAsync(self, EvtHandler sink) -> bool"""
+ return _misc_.Clipboard_IsSupportedAsync(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """
+ GetData(self, DataObject data) -> bool
+
+ Call this function to fill data with data on the clipboard, if
+ available in the required format. Returns true on success.
+ """
+ return _misc_.Clipboard_GetData(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """
+ Clear(self)
+
+ Clears data from the clipboard object and also the system's clipboard
+ if possible.
+ """
+ return _misc_.Clipboard_Clear(*args, **kwargs)
+
+ def Flush(*args, **kwargs):
+ """
+ Flush(self) -> bool
+
+ Flushes the clipboard: this means that the data which is currently on
+ clipboard will stay available even after the application exits,
+ possibly eating memory, otherwise the clipboard will be emptied on
+ exit. Returns False if the operation is unsuccesful for any reason.
+ """
+ return _misc_.Clipboard_Flush(*args, **kwargs)
+
+ def UsePrimarySelection(*args, **kwargs):
+ """
+ UsePrimarySelection(self, bool primary=True)
+
+ On platforms supporting it (the X11 based platforms), selects the so
+ called PRIMARY SELECTION as the clipboard as opposed to the normal
+ clipboard, if primary is True. On other platforms all clipboard
+ operations fail when using the primary selection. This allows code
+ supporting the primary selection to be written without ill effects on
+ the other platforms.
+ """
+ return _misc_.Clipboard_UsePrimarySelection(*args, **kwargs)
+
+ def IsUsingPrimarySelection(*args, **kwargs):
+ """
+ IsUsingPrimarySelection(self) -> bool
+
+ Return true if we're using primary selection
+ """
+ return _misc_.Clipboard_IsUsingPrimarySelection(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get() -> Clipboard
+
+ Returns global instance (wxTheClipboard) of the object.
+ """
+ return _misc_.Clipboard_Get(*args, **kwargs)
+
+ Get = staticmethod(Get)
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.Close()
+
+_misc_.Clipboard_swigregister(Clipboard)
+
+def Clipboard_Get(*args):
+ """
+ Clipboard_Get() -> Clipboard
+
+ Returns global instance (wxTheClipboard) of the object.
+ """
+ return _misc_.Clipboard_Get(*args)
+
+class _wxPyDelayedInitWrapper(object):
+ def __init__(self, initfunc, *args, **kwargs):
+ self._initfunc = initfunc
+ self._args = args
+ self._kwargs = kwargs
+ self._instance = None
+ def _checkInstance(self):
+ if self._instance is None:
+ if wx.GetApp():
+ self._instance = self._initfunc(*self._args, **self._kwargs)
+ def __getattr__(self, name):
+ self._checkInstance()
+ return getattr(self._instance, name)
+ def __repr__(self):
+ self._checkInstance()
+ return repr(self._instance)
+TheClipboard = _wxPyDelayedInitWrapper(Clipboard.Get)
+
+class ClipboardLocker(object):
+ """
+ A helpful class for opening the clipboard and automatically
+ closing it when the locker is destroyed.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Clipboard clipboard=None) -> ClipboardLocker
+
+ A helpful class for opening the clipboard and automatically
+ closing it when the locker is destroyed.
+ """
+ _misc_.ClipboardLocker_swiginit(self,_misc_.new_ClipboardLocker(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_ClipboardLocker
+ __del__ = lambda self : None;
+ def __nonzero__(*args, **kwargs):
+ """
+ __nonzero__(self) -> bool
+
+ A ClipboardLocker instance evaluates to True if the clipboard was
+ successfully opened.
+ """
+ return _misc_.ClipboardLocker___nonzero__(*args, **kwargs)
+
+_misc_.ClipboardLocker_swigregister(ClipboardLocker)
+
+class ClipboardEvent(_core.Event):
+ """Proxy of C++ ClipboardEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType evtType=wxEVT_NULL) -> ClipboardEvent"""
+ _misc_.ClipboardEvent_swiginit(self,_misc_.new_ClipboardEvent(*args, **kwargs))
+ def SupportsFormat(*args, **kwargs):
+ """SupportsFormat(self, DataFormat format) -> bool"""
+ return _misc_.ClipboardEvent_SupportsFormat(*args, **kwargs)
+
+ def AddFormat(*args, **kwargs):
+ """AddFormat(self, DataFormat format)"""
+ return _misc_.ClipboardEvent_AddFormat(*args, **kwargs)
+
+_misc_.ClipboardEvent_swigregister(ClipboardEvent)
+
+wxEVT_CLIPBOARD_CHANGED = _misc_.wxEVT_CLIPBOARD_CHANGED
+EVT_CLIPBOARD_CHANGED = wx.PyEventBinder( wxEVT_CLIPBOARD_CHANGED )
+
+#---------------------------------------------------------------------------
+
+class VideoMode(object):
+ """A simple struct containing video mode parameters for a display"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int width=0, int height=0, int depth=0, int freq=0) -> VideoMode
+
+ A simple struct containing video mode parameters for a display
+ """
+ _misc_.VideoMode_swiginit(self,_misc_.new_VideoMode(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_VideoMode
+ __del__ = lambda self : None;
+ def Matches(*args, **kwargs):
+ """
+ Matches(self, VideoMode other) -> bool
+
+ Returns True if this mode matches the other one in the sense that all
+ non-zero fields of the other mode have the same value in this
+ one (except for refresh which is allowed to have a greater value)
+ """
+ return _misc_.VideoMode_Matches(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """
+ GetWidth(self) -> int
+
+ Returns the screen width in pixels (e.g. 640*480), 0 means unspecified
+ """
+ return _misc_.VideoMode_GetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """
+ GetHeight(self) -> int
+
+ Returns the screen height in pixels (e.g. 640*480), 0 means unspecified
+ """
+ return _misc_.VideoMode_GetHeight(*args, **kwargs)
+
+ def GetDepth(*args, **kwargs):
+ """
+ GetDepth(self) -> int
+
+ Returns the screen's bits per pixel (e.g. 32), 1 is monochrome and 0
+ means unspecified/known
+ """
+ return _misc_.VideoMode_GetDepth(*args, **kwargs)
+
+ def GetRefresh(*args, **kwargs):
+ """GetRefresh(self) -> int"""
+ return _misc_.VideoMode_GetRefresh(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """
+ IsOk(self) -> bool
+
+ returns true if the object has been initialized
+ """
+ return _misc_.VideoMode_IsOk(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def __eq__(*args, **kwargs):
+ """__eq__(self, VideoMode other) -> bool"""
+ return _misc_.VideoMode___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """__ne__(self, VideoMode other) -> bool"""
+ return _misc_.VideoMode___ne__(*args, **kwargs)
+
+ w = property(_misc_.VideoMode_w_get, _misc_.VideoMode_w_set)
+ h = property(_misc_.VideoMode_h_get, _misc_.VideoMode_h_set)
+ bpp = property(_misc_.VideoMode_bpp_get, _misc_.VideoMode_bpp_set)
+ refresh = property(_misc_.VideoMode_refresh_get, _misc_.VideoMode_refresh_set)
+ Depth = property(GetDepth,doc="See `GetDepth`")
+ Height = property(GetHeight,doc="See `GetHeight`")
+ Width = property(GetWidth,doc="See `GetWidth`")
+ Refresh = property(GetRefresh)
+_misc_.VideoMode_swigregister(VideoMode)
+
+class Display(object):
+ """Represents a display/monitor attached to the system"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, unsigned int index=0) -> Display
+
+ Set up a Display instance with the specified display. The displays
+ are numbered from 0 to GetCount() - 1, 0 is always the primary display
+ and the only one which is always supported
+ """
+ _misc_.Display_swiginit(self,_misc_.new_Display(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_Display
+ __del__ = lambda self : None;
+ def GetCount(*args, **kwargs):
+ """
+ GetCount() -> unsigned int
+
+ Return the number of available displays.
+ """
+ return _misc_.Display_GetCount(*args, **kwargs)
+
+ GetCount = staticmethod(GetCount)
+ def GetFromPoint(*args, **kwargs):
+ """
+ GetFromPoint(Point pt) -> int
+
+ Find the display where the given point lies, return wx.NOT_FOUND if it
+ doesn't belong to any display
+ """
+ return _misc_.Display_GetFromPoint(*args, **kwargs)
+
+ GetFromPoint = staticmethod(GetFromPoint)
+ def GetFromWindow(*args, **kwargs):
+ """
+ GetFromWindow(Window window) -> int
+
+ Find the display where the given window lies, return wx.NOT_FOUND if
+ it is not shown at all.
+ """
+ return _misc_.Display_GetFromWindow(*args, **kwargs)
+
+ GetFromWindow = staticmethod(GetFromWindow)
+ def IsOk(*args, **kwargs):
+ """
+ IsOk(self) -> bool
+
+ Return true if the object was initialized successfully
+ """
+ return _misc_.Display_IsOk(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def GetGeometry(*args, **kwargs):
+ """
+ GetGeometry(self) -> Rect
+
+ Returns the bounding rectangle of the display whose index was passed
+ to the constructor.
+ """
+ return _misc_.Display_GetGeometry(*args, **kwargs)
+
+ def GetClientArea(*args, **kwargs):
+ """
+ GetClientArea(self) -> Rect
+
+ Returns the bounding rectangle the client area of the display,
+ i.e., without taskbars and such.
+ """
+ return _misc_.Display_GetClientArea(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """
+ GetName(self) -> String
+
+ Returns the display's name. A name is not available on all platforms.
+ """
+ return _misc_.Display_GetName(*args, **kwargs)
+
+ def IsPrimary(*args, **kwargs):
+ """
+ IsPrimary(self) -> bool
+
+ Returns True if the display is the primary display. The primary
+ display is the one whose index is 0.
+ """
+ return _misc_.Display_IsPrimary(*args, **kwargs)
+
+ def GetModes(*args, **kwargs):
+ """
+ GetModes(VideoMode mode=DefaultVideoMode) -> [videoMode...]
+
+ Enumerate all video modes supported by this display matching the given
+ one (in the sense of VideoMode.Match()).
+
+ As any mode matches the default value of the argument and there is
+ always at least one video mode supported by display, the returned
+ array is only empty for the default value of the argument if this
+ function is not supported at all on this platform.
+ """
+ return _misc_.Display_GetModes(*args, **kwargs)
+
+ def GetCurrentMode(*args, **kwargs):
+ """
+ GetCurrentMode(self) -> VideoMode
+
+ Get the current video mode.
+ """
+ return _misc_.Display_GetCurrentMode(*args, **kwargs)
+
+ def ChangeMode(*args, **kwargs):
+ """
+ ChangeMode(self, VideoMode mode=DefaultVideoMode) -> bool
+
+ Changes the video mode of this display to the mode specified in the
+ mode parameter.
+
+ If wx.DefaultVideoMode is passed in as the mode parameter, the defined
+ behaviour is that wx.Display will reset the video mode to the default
+ mode used by the display. On Windows, the behavior is normal.
+ However, there are differences on other platforms. On Unix variations
+ using X11 extensions it should behave as defined, but some
+ irregularities may occur.
+
+ On wxMac passing in wx.DefaultVideoMode as the mode parameter does
+ nothing. This happens because Carbon no longer has access to
+ DMUseScreenPrefs, an undocumented function that changed the video mode
+ to the system default by using the system's 'scrn' resource.
+
+ Returns True if succeeded, False otherwise
+ """
+ return _misc_.Display_ChangeMode(*args, **kwargs)
+
+ def ResetMode(*args, **kwargs):
+ """
+ ResetMode(self)
+
+ Restore the default video mode (just a more readable synonym)
+ """
+ return _misc_.Display_ResetMode(*args, **kwargs)
+
+ ClientArea = property(GetClientArea,doc="See `GetClientArea`")
+ CurrentMode = property(GetCurrentMode,doc="See `GetCurrentMode`")
+ Geometry = property(GetGeometry,doc="See `GetGeometry`")
+ Modes = property(GetModes,doc="See `GetModes`")
+ Name = property(GetName,doc="See `GetName`")
+_misc_.Display_swigregister(Display)
+DefaultVideoMode = cvar.DefaultVideoMode
+
+def Display_GetCount(*args):
+ """
+ Display_GetCount() -> unsigned int
+
+ Return the number of available displays.
+ """
+ return _misc_.Display_GetCount(*args)
+
+def Display_GetFromPoint(*args, **kwargs):
+ """
+ Display_GetFromPoint(Point pt) -> int
+
+ Find the display where the given point lies, return wx.NOT_FOUND if it
+ doesn't belong to any display
+ """
+ return _misc_.Display_GetFromPoint(*args, **kwargs)
+
+def Display_GetFromWindow(*args, **kwargs):
+ """
+ Display_GetFromWindow(Window window) -> int
+
+ Find the display where the given window lies, return wx.NOT_FOUND if
+ it is not shown at all.
+ """
+ return _misc_.Display_GetFromWindow(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class StandardPaths(object):
+ """
+ wx.StandardPaths returns standard locations in the file system and
+ should be used by programs to find their data files in a portable way.
+
+ In the description of the methods below, the example return values are
+ given for the Unix, Windows and Mac OS X systems, however please note
+ that these are just examples and the actual values may differ. For
+ example, under Windows the system administrator may change the
+ standard directories locations, i.e. the Windows directory may be
+ named W:/Win2003 instead of the default C:/Windows.
+
+ The strings appname and username should be replaced with the value
+ returned by `wx.App.GetAppName` and the name of the currently logged
+ in user, respectively. The string prefix is only used under Unix and
+ is /usr/local by default but may be changed using `SetInstallPrefix`.
+
+ The directories returned by the methods of this class may or may not
+ exist. If they don't exist, it's up to the caller to create them,
+ wx.StandardPaths doesn't do it.
+
+ Finally note that these functions only work with standardly packaged
+ applications. I.e. under Unix you should follow the standard
+ installation conventions and under Mac you should create your
+ application bundle according to the Apple guidelines. Again, this
+ class doesn't help you to do it.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ ResourceCat_None = _misc_.StandardPaths_ResourceCat_None
+ ResourceCat_Messages = _misc_.StandardPaths_ResourceCat_Messages
+ ResourceCat_Max = _misc_.StandardPaths_ResourceCat_Max
+ AppInfo_None = _misc_.StandardPaths_AppInfo_None
+ AppInfo_AppName = _misc_.StandardPaths_AppInfo_AppName
+ AppInfo_VendorName = _misc_.StandardPaths_AppInfo_VendorName
+ def Get(*args, **kwargs):
+ """
+ Get() -> StandardPaths
+
+ Return the global standard paths singleton
+ """
+ return _misc_.StandardPaths_Get(*args, **kwargs)
+
+ Get = staticmethod(Get)
+ def GetExecutablePath(*args, **kwargs):
+ """
+ GetExecutablePath(self) -> String
+
+ Return the path (directory+filename) of the running executable or an
+ empty string if it couldn't be determined. The path is returned as an
+ absolute path whenever possible.
+ """
+ return _misc_.StandardPaths_GetExecutablePath(*args, **kwargs)
+
+ def GetConfigDir(*args, **kwargs):
+ """
+ GetConfigDir(self) -> String
+
+ Return the directory with system config files: /etc under Unix,
+ 'c:/Documents and Settings/All Users/Application Data' under Windows,
+ /Library/Preferences for Mac
+ """
+ return _misc_.StandardPaths_GetConfigDir(*args, **kwargs)
+
+ def GetUserConfigDir(*args, **kwargs):
+ """
+ GetUserConfigDir(self) -> String
+
+ Return the directory for the user config files: $HOME under Unix,
+ 'c:/Documents and Settings/username' under Windows, and
+ ~/Library/Preferences under Mac
+
+ Only use this if you have a single file to put there, otherwise
+ `GetUserDataDir` is more appropriate
+ """
+ return _misc_.StandardPaths_GetUserConfigDir(*args, **kwargs)
+
+ def GetDataDir(*args, **kwargs):
+ """
+ GetDataDir(self) -> String
+
+ Return the location of the application's global, (i.e. not
+ user-specific,) data files: prefix/share/appname under Unix,
+ 'c:/Program Files/appname' under Windows,
+ appname.app/Contents/SharedSupport app bundle directory under Mac.
+ """
+ return _misc_.StandardPaths_GetDataDir(*args, **kwargs)
+
+ def GetLocalDataDir(*args, **kwargs):
+ """
+ GetLocalDataDir(self) -> String
+
+ Return the location for application data files which are
+ host-specific. Same as `GetDataDir` except under Unix where it is
+ /etc/appname
+ """
+ return _misc_.StandardPaths_GetLocalDataDir(*args, **kwargs)
+
+ def GetUserDataDir(*args, **kwargs):
+ """
+ GetUserDataDir(self) -> String
+
+ Return the directory for the user-dependent application data files:
+ $HOME/.appname under Unix, c:/Documents and
+ Settings/username/Application Data/appname under Windows and
+ ~/Library/Application Support/appname under Mac
+ """
+ return _misc_.StandardPaths_GetUserDataDir(*args, **kwargs)
+
+ def GetUserLocalDataDir(*args, **kwargs):
+ """
+ GetUserLocalDataDir(self) -> String
+
+ Return the directory for user data files which shouldn't be shared
+ with the other machines
+
+ Same as `GetUserDataDir` for all platforms except Windows where it is
+ the 'Local Settings/Application Data/appname' directory.
+ """
+ return _misc_.StandardPaths_GetUserLocalDataDir(*args, **kwargs)
+
+ def GetPluginsDir(*args, **kwargs):
+ """
+ GetPluginsDir(self) -> String
+
+ Return the directory where the loadable modules (plugins) live:
+ prefix/lib/appname under Unix, program directory under Windows and
+ Contents/Plugins app bundle subdirectory under Mac
+ """
+ return _misc_.StandardPaths_GetPluginsDir(*args, **kwargs)
+
+ def GetResourcesDir(*args, **kwargs):
+ """
+ GetResourcesDir(self) -> String
+
+ Get resources directory. Resources are auxiliary files used by the
+ application and include things like image and sound files.
+
+ Same as `GetDataDir` for all platforms except Mac where it returns
+ Contents/Resources subdirectory of the app bundle.
+ """
+ return _misc_.StandardPaths_GetResourcesDir(*args, **kwargs)
+
+ def GetLocalizedResourcesDir(*args, **kwargs):
+ """
+ GetLocalizedResourcesDir(self, String lang, int category=ResourceCat_None) -> String
+
+ Get localized resources directory containing the resource files of the
+ specified category for the given language.
+
+ In general this is just GetResourcesDir()/lang under Windows and Unix
+ and GetResourcesDir()/lang.lproj under Mac but is something quite
+ different under Unix for the message catalog category (namely the
+ standard prefix/share/locale/lang/LC_MESSAGES.)
+ """
+ return _misc_.StandardPaths_GetLocalizedResourcesDir(*args, **kwargs)
+
+ def GetDocumentsDir(*args, **kwargs):
+ """
+ GetDocumentsDir(self) -> String
+
+ Return the Documents directory for the current user.
+
+ C:/Documents and Settings/username/Documents under Windows,
+ $HOME under Unix and ~/Documents under Mac
+ """
+ return _misc_.StandardPaths_GetDocumentsDir(*args, **kwargs)
+
+ def GetAppDocumentsDir(*args, **kwargs):
+ """
+ GetAppDocumentsDir(self) -> String
+
+ Return the directory for the documents files used by this application:
+ it's a subdirectory of GetDocumentsDir() constructed using the
+ application name/vendor if it exists or just GetDocumentsDir()
+ otherwise.
+ """
+ return _misc_.StandardPaths_GetAppDocumentsDir(*args, **kwargs)
+
+ def GetTempDir(*args, **kwargs):
+ """
+ GetTempDir(self) -> String
+
+ Return the user's directory for temporary files.
+ """
+ return _misc_.StandardPaths_GetTempDir(*args, **kwargs)
+
+ def SetInstallPrefix(*args, **kwargs):
+ """
+ SetInstallPrefix(self, String prefix)
+
+ Set the program installation directory which is /usr/local by default.
+ This value will be used by other methods such as `GetDataDir` and
+ `GetPluginsDir` as the prefix for what they return. (This function
+ only has meaning on Unix systems.)
+ """
+ return _misc_.StandardPaths_SetInstallPrefix(*args, **kwargs)
+
+ def GetInstallPrefix(*args, **kwargs):
+ """
+ GetInstallPrefix(self) -> String
+
+ Get the program installation prefix. The default is the prefix where
+ Python is installed. (This function only has meaning on Unix systems.)
+ """
+ return _misc_.StandardPaths_GetInstallPrefix(*args, **kwargs)
+
+ def UseAppInfo(*args, **kwargs):
+ """UseAppInfo(self, int info)"""
+ return _misc_.StandardPaths_UseAppInfo(*args, **kwargs)
+
+ def UsesAppInfo(*args, **kwargs):
+ """UsesAppInfo(self, int info) -> bool"""
+ return _misc_.StandardPaths_UsesAppInfo(*args, **kwargs)
+
+_misc_.StandardPaths_swigregister(StandardPaths)
+
+def StandardPaths_Get(*args):
+ """
+ StandardPaths_Get() -> StandardPaths
+
+ Return the global standard paths singleton
+ """
+ return _misc_.StandardPaths_Get(*args)
+
+#---------------------------------------------------------------------------
+
+POWER_SOCKET = _misc_.POWER_SOCKET
+POWER_BATTERY = _misc_.POWER_BATTERY
+POWER_UNKNOWN = _misc_.POWER_UNKNOWN
+BATTERY_NORMAL_STATE = _misc_.BATTERY_NORMAL_STATE
+BATTERY_LOW_STATE = _misc_.BATTERY_LOW_STATE
+BATTERY_CRITICAL_STATE = _misc_.BATTERY_CRITICAL_STATE
+BATTERY_SHUTDOWN_STATE = _misc_.BATTERY_SHUTDOWN_STATE
+BATTERY_UNKNOWN_STATE = _misc_.BATTERY_UNKNOWN_STATE
+class PowerEvent(_core.Event):
+ """
+ wx.PowerEvent is generated when the system online status changes.
+ Currently this is only implemented for Windows.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType evtType) -> PowerEvent
+
+ wx.PowerEvent is generated when the system online status changes.
+ Currently this is only implemented for Windows.
+ """
+ _misc_.PowerEvent_swiginit(self,_misc_.new_PowerEvent(*args, **kwargs))
+ def Veto(*args, **kwargs):
+ """Veto(self)"""
+ return _misc_.PowerEvent_Veto(*args, **kwargs)
+
+ def IsVetoed(*args, **kwargs):
+ """IsVetoed(self) -> bool"""
+ return _misc_.PowerEvent_IsVetoed(*args, **kwargs)
+
+_misc_.PowerEvent_swigregister(PowerEvent)
+
+wxEVT_POWER_SUSPENDING = _misc_.wxEVT_POWER_SUSPENDING
+wxEVT_POWER_SUSPENDED = _misc_.wxEVT_POWER_SUSPENDED
+wxEVT_POWER_SUSPEND_CANCEL = _misc_.wxEVT_POWER_SUSPEND_CANCEL
+wxEVT_POWER_RESUME = _misc_.wxEVT_POWER_RESUME
+EVT_POWER_SUSPENDING = wx.PyEventBinder( wxEVT_POWER_SUSPENDING , 1 )
+EVT_POWER_SUSPENDED = wx.PyEventBinder( wxEVT_POWER_SUSPENDED , 1 )
+EVT_POWER_SUSPEND_CANCEL = wx.PyEventBinder( wxEVT_POWER_SUSPEND_CANCEL , 1 )
+EVT_POWER_RESUME = wx.PyEventBinder( wxEVT_POWER_RESUME , 1 )
+
+
+def GetPowerType(*args):
+ """
+ GetPowerType() -> int
+
+ return the current system power state: online or offline
+ """
+ return _misc_.GetPowerType(*args)
+
+def GetBatteryState(*args):
+ """
+ GetBatteryState() -> int
+
+ return approximate battery state
+ """
+ return _misc_.GetBatteryState(*args)
+#---------------------------------------------------------------------------
+
+class AboutDialogInfo(object):
+ """
+ `wx.AboutDialogInfo` contains information to be shown in the standard
+ About dialog displayed by the `wx.AboutBox` function. This class
+ contains the general information about the program, such as its name,
+ version, copyright and so on, as well as lists of the program
+ developers, documentation writers, artists and translators.
+
+ While all the main platforms have a native implementation of the about
+ dialog, they are often more limited than the generic version provided
+ by wxWidgets and so the generic version is used if
+ `wx.AboutDialogInfo` has any fields not supported by the native
+ version. Currently GTK+ version supports all the possible fields
+ natively but MSW and Mac versions don't support URLs, licence text nor
+ custom icons in the about dialog and if either of those is used,
+ wxAboutBox() will automatically use the generic version so you should
+ avoid specifying these fields to achieve more native look and feel.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> AboutDialogInfo
+
+ `wx.AboutDialogInfo` contains information to be shown in the standard
+ About dialog displayed by the `wx.AboutBox` function. This class
+ contains the general information about the program, such as its name,
+ version, copyright and so on, as well as lists of the program
+ developers, documentation writers, artists and translators.
+
+ While all the main platforms have a native implementation of the about
+ dialog, they are often more limited than the generic version provided
+ by wxWidgets and so the generic version is used if
+ `wx.AboutDialogInfo` has any fields not supported by the native
+ version. Currently GTK+ version supports all the possible fields
+ natively but MSW and Mac versions don't support URLs, licence text nor
+ custom icons in the about dialog and if either of those is used,
+ wxAboutBox() will automatically use the generic version so you should
+ avoid specifying these fields to achieve more native look and feel.
+
+ """
+ _misc_.AboutDialogInfo_swiginit(self,_misc_.new_AboutDialogInfo(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_AboutDialogInfo
+ __del__ = lambda self : None;
+ def SetName(*args, **kwargs):
+ """
+ SetName(self, String name)
+
+ Set the name of the program. If this method is not called, the string
+ returned by `wx.App.GetAppName` will be shown in the dialog.
+ """
+ return _misc_.AboutDialogInfo_SetName(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """
+ GetName(self) -> String
+
+ Returns the program name.
+ """
+ return _misc_.AboutDialogInfo_GetName(*args, **kwargs)
+
+ Name = property(GetName,SetName)
+ def SetVersion(*args, **kwargs):
+ """
+ SetVersion(self, String version, String longVersion=wxEmptyString)
+
+ Set the version of the program. The version is in free format,
+ i.e. not necessarily in the x.y.z form but it shouldn't contain the
+ "version" word.
+ """
+ return _misc_.AboutDialogInfo_SetVersion(*args, **kwargs)
+
+ def HasVersion(*args, **kwargs):
+ """
+ HasVersion(self) -> bool
+
+ Returns ``True`` if the version property has been set.
+ """
+ return _misc_.AboutDialogInfo_HasVersion(*args, **kwargs)
+
+ def GetVersion(*args, **kwargs):
+ """
+ GetVersion(self) -> String
+
+ Returns the version value.
+ """
+ return _misc_.AboutDialogInfo_GetVersion(*args, **kwargs)
+
+ Version = property(GetVersion,SetVersion)
+ def GetLongVersion(*args, **kwargs):
+ """GetLongVersion(self) -> String"""
+ return _misc_.AboutDialogInfo_GetLongVersion(*args, **kwargs)
+
+ LongVersion = property(GetLongVersion)
+ def SetDescription(*args, **kwargs):
+ """
+ SetDescription(self, String desc)
+
+ Set brief, but possibly multiline, description of the program.
+ """
+ return _misc_.AboutDialogInfo_SetDescription(*args, **kwargs)
+
+ def HasDescription(*args, **kwargs):
+ """
+ HasDescription(self) -> bool
+
+ Returns ``True`` if the description property has been set.
+ """
+ return _misc_.AboutDialogInfo_HasDescription(*args, **kwargs)
+
+ def GetDescription(*args, **kwargs):
+ """
+ GetDescription(self) -> String
+
+ Returns the description value.
+ """
+ return _misc_.AboutDialogInfo_GetDescription(*args, **kwargs)
+
+ Description = property(GetDescription,SetDescription)
+ def SetCopyright(*args, **kwargs):
+ """
+ SetCopyright(self, String copyright)
+
+ Set the short string containing the program copyright
+ information. Notice that any occurrences of "(C)" in ``copyright``
+ will be replaced by the copyright symbol (circled C) automatically,
+ which means that you can avoid using this symbol in the program source
+ code which can be problematic.
+ """
+ return _misc_.AboutDialogInfo_SetCopyright(*args, **kwargs)
+
+ def HasCopyright(*args, **kwargs):
+ """
+ HasCopyright(self) -> bool
+
+ Returns ``True`` if the copyright property has been set.
+ """
+ return _misc_.AboutDialogInfo_HasCopyright(*args, **kwargs)
+
+ def GetCopyright(*args, **kwargs):
+ """
+ GetCopyright(self) -> String
+
+ Returns the copyright value.
+ """
+ return _misc_.AboutDialogInfo_GetCopyright(*args, **kwargs)
+
+ Copyright = property(GetCopyright,SetCopyright)
+ def SetLicence(*args, **kwargs):
+ """
+ SetLicence(self, String licence)
+
+ Set the long, multiline string containing the text of the program
+ licence.
+
+ Only GTK+ version supports showing the licence text in the native
+ about dialog currently so the generic version will be used under all
+ the other platforms if this method is called. To preserve the native
+ look and feel it is advised that you do not call this method but
+ provide a separate menu item in the "Help" menu for displaying the
+ text of your program licence.
+
+ """
+ return _misc_.AboutDialogInfo_SetLicence(*args, **kwargs)
+
+ def SetLicense(*args, **kwargs):
+ """
+ SetLicense(self, String licence)
+
+ This is the same as `SetLicence`.
+ """
+ return _misc_.AboutDialogInfo_SetLicense(*args, **kwargs)
+
+ def HasLicence(*args, **kwargs):
+ """
+ HasLicence(self) -> bool
+
+ Returns ``True`` if the licence property has been set.
+ """
+ return _misc_.AboutDialogInfo_HasLicence(*args, **kwargs)
+
+ def GetLicence(*args, **kwargs):
+ """
+ GetLicence(self) -> String
+
+ Returns the licence value.
+ """
+ return _misc_.AboutDialogInfo_GetLicence(*args, **kwargs)
+
+ Licence = property(GetLicence,SetLicence)
+ License = Licence
+ def SetIcon(*args, **kwargs):
+ """
+ SetIcon(self, Icon icon)
+
+ Set the icon to be shown in the dialog. By default the icon of the
+ main frame will be shown if the native about dialog supports custom
+ icons. If it doesn't but a valid icon is specified using this method,
+ the generic about dialog is used instead so you should avoid calling
+ this function for maximally native look and feel.
+ """
+ return _misc_.AboutDialogInfo_SetIcon(*args, **kwargs)
+
+ def HasIcon(*args, **kwargs):
+ """
+ HasIcon(self) -> bool
+
+ Returns ``True`` if the icon property has been set.
+ """
+ return _misc_.AboutDialogInfo_HasIcon(*args, **kwargs)
+
+ def GetIcon(*args, **kwargs):
+ """
+ GetIcon(self) -> Icon
+
+ Return the current icon value.
+ """
+ return _misc_.AboutDialogInfo_GetIcon(*args, **kwargs)
+
+ Icon = property(GetIcon,SetIcon)
+ def _SetWebSite(*args, **kwargs):
+ """_SetWebSite(self, String url, String desc=wxEmptyString)"""
+ return _misc_.AboutDialogInfo__SetWebSite(*args, **kwargs)
+
+ def _GetWebSiteURL(*args, **kwargs):
+ """_GetWebSiteURL(self) -> String"""
+ return _misc_.AboutDialogInfo__GetWebSiteURL(*args, **kwargs)
+
+ def _GetWebSiteDescription(*args, **kwargs):
+ """_GetWebSiteDescription(self) -> String"""
+ return _misc_.AboutDialogInfo__GetWebSiteDescription(*args, **kwargs)
+
+ def HasWebSite(*args, **kwargs):
+ """HasWebSite(self) -> bool"""
+ return _misc_.AboutDialogInfo_HasWebSite(*args, **kwargs)
+
+ def SetWebSite(self, args):
+ """
+ SetWebSite(self, URL, [Description])
+
+ Set the web site property. The ``args`` parameter can
+ either be a single string for the URL, to a 2-tuple of
+ (URL, Description) strings.
+ """
+ if type(args) in [str, unicode]:
+ self._SetWebSite(args)
+ else:
+ self._SetWebSite(args[0], args[1])
+
+ def GetWebSite(self):
+ """
+ GetWebSite(self) --> (URL, Description)
+ """
+ return (self._GetWebSiteURL(), self._GetWebSiteDescription())
+
+ WebSite = property(GetWebSite,SetWebSite)
+ def SetDevelopers(*args, **kwargs):
+ """
+ SetDevelopers(self, list developers)
+
+ Set the list of the developers of the program.
+ """
+ return _misc_.AboutDialogInfo_SetDevelopers(*args, **kwargs)
+
+ def AddDeveloper(*args, **kwargs):
+ """
+ AddDeveloper(self, String developer)
+
+ Add a string to the list of developers.
+ """
+ return _misc_.AboutDialogInfo_AddDeveloper(*args, **kwargs)
+
+ def HasDevelopers(*args, **kwargs):
+ """
+ HasDevelopers(self) -> bool
+
+ Returns ``True if any developers have been set.
+ """
+ return _misc_.AboutDialogInfo_HasDevelopers(*args, **kwargs)
+
+ def GetDevelopers(*args, **kwargs):
+ """
+ GetDevelopers(self) --> list
+
+ Returns the list of developers.
+ """
+ return _misc_.AboutDialogInfo_GetDevelopers(*args, **kwargs)
+
+ Developers = property(GetDevelopers,SetDevelopers)
+ def SetDocWriters(*args, **kwargs):
+ """
+ SetDocWriters(self, list docwriters)
+
+ Set the list of the documentation writers.
+ """
+ return _misc_.AboutDialogInfo_SetDocWriters(*args, **kwargs)
+
+ def AddDocWriter(*args, **kwargs):
+ """
+ AddDocWriter(self, String docwriter)
+
+ Add a string to the list of documentation writers.
+ """
+ return _misc_.AboutDialogInfo_AddDocWriter(*args, **kwargs)
+
+ def HasDocWriters(*args, **kwargs):
+ """
+ HasDocWriters(self) -> bool
+
+ Returns ``True if any documentation writers have been set.
+ """
+ return _misc_.AboutDialogInfo_HasDocWriters(*args, **kwargs)
+
+ def GetDocWriters(*args, **kwargs):
+ """
+ GetDocWriters(self) --> list
+
+ Returns the list of documentation writers.
+ """
+ return _misc_.AboutDialogInfo_GetDocWriters(*args, **kwargs)
+
+ DocWriters = property(GetDocWriters,SetDocWriters)
+ def SetArtists(*args, **kwargs):
+ """
+ SetArtists(self, list artists)
+
+ Set the list of artists for the program.
+ """
+ return _misc_.AboutDialogInfo_SetArtists(*args, **kwargs)
+
+ def AddArtist(*args, **kwargs):
+ """
+ AddArtist(self, String artist)
+
+ Add a string to the list of artists.
+ """
+ return _misc_.AboutDialogInfo_AddArtist(*args, **kwargs)
+
+ def HasArtists(*args, **kwargs):
+ """
+ HasArtists(self) -> bool
+
+ Returns ``True`` if any artists have been set.
+ """
+ return _misc_.AboutDialogInfo_HasArtists(*args, **kwargs)
+
+ def GetArtists(*args, **kwargs):
+ """
+ GetArtists(self) --> list
+
+ Returns the list od artists.
+ """
+ return _misc_.AboutDialogInfo_GetArtists(*args, **kwargs)
+
+ Artists = property(GetArtists,SetArtists)
+ def SetTranslators(*args, **kwargs):
+ """
+ SetTranslators(self, list translators)
+
+ Sets the list of program translators.
+ """
+ return _misc_.AboutDialogInfo_SetTranslators(*args, **kwargs)
+
+ def AddTranslator(*args, **kwargs):
+ """
+ AddTranslator(self, String translator)
+
+ Add a string to the list of translators.
+ """
+ return _misc_.AboutDialogInfo_AddTranslator(*args, **kwargs)
+
+ def HasTranslators(*args, **kwargs):
+ """
+ HasTranslators(self) -> bool
+
+ Returns ``True`` if any translators have been set.
+ """
+ return _misc_.AboutDialogInfo_HasTranslators(*args, **kwargs)
+
+ def GetTranslators(*args, **kwargs):
+ """
+ GetTranslators(self) --> list
+
+ Returns the list of program translators.
+ """
+ return _misc_.AboutDialogInfo_GetTranslators(*args, **kwargs)
+
+ Translators = property(GetTranslators,SetTranslators)
+ def IsSimple(*args, **kwargs):
+ """IsSimple(self) -> bool"""
+ return _misc_.AboutDialogInfo_IsSimple(*args, **kwargs)
+
+ def GetDescriptionAndCredits(*args, **kwargs):
+ """GetDescriptionAndCredits(self) -> String"""
+ return _misc_.AboutDialogInfo_GetDescriptionAndCredits(*args, **kwargs)
+
+ def GetCopyrightToDisplay(*args, **kwargs):
+ """GetCopyrightToDisplay(self) -> String"""
+ return _misc_.AboutDialogInfo_GetCopyrightToDisplay(*args, **kwargs)
+
+_misc_.AboutDialogInfo_swigregister(AboutDialogInfo)
+
+
+def AboutBox(*args, **kwargs):
+ """
+ AboutBox(AboutDialogInfo info, Window parent=None)
+
+ This function shows the standard about dialog containing the
+ information specified in ``info``. If the current platform has a
+ native about dialog which is capable of showing all the fields in
+ `wx.AboutDialogInfo`, the native dialog is used, otherwise the
+ function falls back to the generic wxWidgets version of the dialog.
+ """
+ return _misc_.AboutBox(*args, **kwargs)
+#---------------------------------------------------------------------------
+
+class UIActionSimulator(object):
+ """Proxy of C++ UIActionSimulator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> UIActionSimulator"""
+ _misc_.UIActionSimulator_swiginit(self,_misc_.new_UIActionSimulator(*args, **kwargs))
+ __swig_destroy__ = _misc_.delete_UIActionSimulator
+ __del__ = lambda self : None;
+ def MouseMove(*args):
+ """
+ MouseMove(self, long x, long y) -> bool
+ MouseMove(self, Point point) -> bool
+ """
+ return _misc_.UIActionSimulator_MouseMove(*args)
+
+ def MouseDown(*args, **kwargs):
+ """MouseDown(self, int button=MOUSE_BTN_LEFT) -> bool"""
+ return _misc_.UIActionSimulator_MouseDown(*args, **kwargs)
+
+ def MouseUp(*args, **kwargs):
+ """MouseUp(self, int button=MOUSE_BTN_LEFT) -> bool"""
+ return _misc_.UIActionSimulator_MouseUp(*args, **kwargs)
+
+ def MouseClick(*args, **kwargs):
+ """MouseClick(self, int button=MOUSE_BTN_LEFT) -> bool"""
+ return _misc_.UIActionSimulator_MouseClick(*args, **kwargs)
+
+ def MouseDblClick(*args, **kwargs):
+ """MouseDblClick(self, int button=MOUSE_BTN_LEFT) -> bool"""
+ return _misc_.UIActionSimulator_MouseDblClick(*args, **kwargs)
+
+ def MouseDragDrop(*args, **kwargs):
+ """MouseDragDrop(self, long x1, long y1, long x2, long y2, int button=MOUSE_BTN_LEFT) -> bool"""
+ return _misc_.UIActionSimulator_MouseDragDrop(*args, **kwargs)
+
+ def KeyDown(*args, **kwargs):
+ """KeyDown(self, int keycode, int modifiers=MOD_NONE) -> bool"""
+ return _misc_.UIActionSimulator_KeyDown(*args, **kwargs)
+
+ def KeyUp(*args, **kwargs):
+ """KeyUp(self, int keycode, int modifiers=MOD_NONE) -> bool"""
+ return _misc_.UIActionSimulator_KeyUp(*args, **kwargs)
+
+ def Char(*args, **kwargs):
+ """Char(self, int keycode, int modifiers=MOD_NONE) -> bool"""
+ return _misc_.UIActionSimulator_Char(*args, **kwargs)
+
+ def Text(*args, **kwargs):
+ """Text(self, char text) -> bool"""
+ return _misc_.UIActionSimulator_Text(*args, **kwargs)
+
+_misc_.UIActionSimulator_swigregister(UIActionSimulator)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_misc_.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_misc_.pyd
new file mode 100644
index 0000000..0f6a085
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_misc_.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_propgrid.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_propgrid.pyd
new file mode 100644
index 0000000..574fdb9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_propgrid.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_richtext.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_richtext.pyd
new file mode 100644
index 0000000..a638da5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_richtext.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_stc.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_stc.pyd
new file mode 100644
index 0000000..54e3283
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_stc.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_webkit.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_webkit.pyd
new file mode 100644
index 0000000..90953c4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_webkit.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_windows.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/_windows.py
new file mode 100644
index 0000000..4e22d41
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_windows.py
@@ -0,0 +1,5831 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+import _windows_
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+wx = _core
+#---------------------------------------------------------------------------
+
+class Panel(_core.Window):
+ """Proxy of C++ Panel class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxTAB_TRAVERSAL|wxNO_BORDER,
+ String name=PanelNameStr) -> Panel
+ """
+ _windows_.Panel_swiginit(self,_windows_.new_Panel(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxTAB_TRAVERSAL|wxNO_BORDER,
+ String name=PanelNameStr) -> bool
+
+ Create the GUI part of the Window for 2-phase creation mode.
+ """
+ return _windows_.Panel_Create(*args, **kwargs)
+
+ def SetFocusIgnoringChildren(*args, **kwargs):
+ """
+ SetFocusIgnoringChildren(self)
+
+ In contrast to `SetFocus` (see above) this will set the focus to the
+ panel even of there are child windows in the panel. This is only
+ rarely needed.
+ """
+ return _windows_.Panel_SetFocusIgnoringChildren(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.Panel_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+_windows_.Panel_swigregister(Panel)
+
+def PrePanel(*args, **kwargs):
+ """PrePanel() -> Panel"""
+ val = _windows_.new_PrePanel(*args, **kwargs)
+ return val
+
+def Panel_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Panel_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.Panel_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+SHOW_SB_NEVER = _windows_.SHOW_SB_NEVER
+SHOW_SB_DEFAULT = _windows_.SHOW_SB_DEFAULT
+SHOW_SB_ALWAYS = _windows_.SHOW_SB_ALWAYS
+class ScrollHelper(object):
+ """Proxy of C++ ScrollHelper class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window winToScroll) -> ScrollHelper"""
+ _windows_.ScrollHelper_swiginit(self,_windows_.new_ScrollHelper(*args, **kwargs))
+ def SetScrollbars(*args, **kwargs):
+ """
+ SetScrollbars(self, int pixelsPerUnitX, int pixelsPerUnitY, int noUnitsX,
+ int noUnitsY, int xPos=0, int yPos=0, bool noRefresh=False)
+ """
+ return _windows_.ScrollHelper_SetScrollbars(*args, **kwargs)
+
+ def Scroll(*args):
+ """
+ Scroll(self, int x, int y)
+ Scroll(self, Point pt)
+ """
+ return _windows_.ScrollHelper_Scroll(*args)
+
+ def GetScrollPageSize(*args, **kwargs):
+ """GetScrollPageSize(self, int orient) -> int"""
+ return _windows_.ScrollHelper_GetScrollPageSize(*args, **kwargs)
+
+ def SetScrollPageSize(*args, **kwargs):
+ """SetScrollPageSize(self, int orient, int pageSize)"""
+ return _windows_.ScrollHelper_SetScrollPageSize(*args, **kwargs)
+
+ def GetScrollLines(*args, **kwargs):
+ """GetScrollLines(self, int orient) -> int"""
+ return _windows_.ScrollHelper_GetScrollLines(*args, **kwargs)
+
+ def SetScrollRate(*args, **kwargs):
+ """SetScrollRate(self, int xstep, int ystep)"""
+ return _windows_.ScrollHelper_SetScrollRate(*args, **kwargs)
+
+ def GetScrollPixelsPerUnit(*args, **kwargs):
+ """
+ GetScrollPixelsPerUnit() -> (xUnit, yUnit)
+
+ Get the size of one logical unit in physical units.
+ """
+ return _windows_.ScrollHelper_GetScrollPixelsPerUnit(*args, **kwargs)
+
+ def ShowScrollbars(*args, **kwargs):
+ """ShowScrollbars(self, int horz, int vert)"""
+ return _windows_.ScrollHelper_ShowScrollbars(*args, **kwargs)
+
+ def EnableScrolling(*args, **kwargs):
+ """EnableScrolling(self, bool x_scrolling, bool y_scrolling)"""
+ return _windows_.ScrollHelper_EnableScrolling(*args, **kwargs)
+
+ def GetViewStart(*args, **kwargs):
+ """
+ GetViewStart(self) -> Point
+
+ Get the view start
+ """
+ return _windows_.ScrollHelper_GetViewStart(*args, **kwargs)
+
+ def DisableKeyboardScrolling(*args, **kwargs):
+ """DisableKeyboardScrolling(self)"""
+ return _windows_.ScrollHelper_DisableKeyboardScrolling(*args, **kwargs)
+
+ def SetScale(*args, **kwargs):
+ """SetScale(self, double xs, double ys)"""
+ return _windows_.ScrollHelper_SetScale(*args, **kwargs)
+
+ def GetScaleX(*args, **kwargs):
+ """GetScaleX(self) -> double"""
+ return _windows_.ScrollHelper_GetScaleX(*args, **kwargs)
+
+ def GetScaleY(*args, **kwargs):
+ """GetScaleY(self) -> double"""
+ return _windows_.ScrollHelper_GetScaleY(*args, **kwargs)
+
+ def CalcScrolledPosition(*args):
+ """
+ CalcScrolledPosition(self, Point pt) -> Point
+ CalcScrolledPosition(int x, int y) -> (sx, sy)
+
+ Translate between scrolled and unscrolled coordinates.
+ """
+ return _windows_.ScrollHelper_CalcScrolledPosition(*args)
+
+ def CalcUnscrolledPosition(*args):
+ """
+ CalcUnscrolledPosition(self, Point pt) -> Point
+ CalcUnscrolledPosition(int x, int y) -> (ux, uy)
+
+ Translate between scrolled and unscrolled coordinates.
+ """
+ return _windows_.ScrollHelper_CalcUnscrolledPosition(*args)
+
+ def AdjustScrollbars(*args, **kwargs):
+ """AdjustScrollbars(self)"""
+ return _windows_.ScrollHelper_AdjustScrollbars(*args, **kwargs)
+
+ def CalcScrollInc(*args, **kwargs):
+ """CalcScrollInc(self, ScrollWinEvent event) -> int"""
+ return _windows_.ScrollHelper_CalcScrollInc(*args, **kwargs)
+
+ def SetTargetWindow(*args, **kwargs):
+ """SetTargetWindow(self, Window target)"""
+ return _windows_.ScrollHelper_SetTargetWindow(*args, **kwargs)
+
+ def GetTargetWindow(*args, **kwargs):
+ """GetTargetWindow(self) -> Window"""
+ return _windows_.ScrollHelper_GetTargetWindow(*args, **kwargs)
+
+ def SetTargetRect(*args, **kwargs):
+ """SetTargetRect(self, Rect rect)"""
+ return _windows_.ScrollHelper_SetTargetRect(*args, **kwargs)
+
+ def GetTargetRect(*args, **kwargs):
+ """GetTargetRect(self) -> Rect"""
+ return _windows_.ScrollHelper_GetTargetRect(*args, **kwargs)
+
+ def IsAutoScrolling(*args, **kwargs):
+ """IsAutoScrolling(self) -> bool"""
+ return _windows_.ScrollHelper_IsAutoScrolling(*args, **kwargs)
+
+ def StopAutoScrolling(*args, **kwargs):
+ """StopAutoScrolling(self)"""
+ return _windows_.ScrollHelper_StopAutoScrolling(*args, **kwargs)
+
+ def SendAutoScrollEvents(*args, **kwargs):
+ """SendAutoScrollEvents(self, ScrollWinEvent event) -> bool"""
+ return _windows_.ScrollHelper_SendAutoScrollEvents(*args, **kwargs)
+
+ def DoPrepareDC(*args, **kwargs):
+ """
+ DoPrepareDC(self, DC dc)
+
+ Call this function to prepare the device context for drawing a
+ scrolled image. It sets the device origin according to the current
+ scroll position.
+ """
+ return _windows_.ScrollHelper_DoPrepareDC(*args, **kwargs)
+
+ PrepareDC = DoPrepareDC
+ ScaleX = property(GetScaleX)
+ ScaleY = property(GetScaleY)
+ TargetWindow = property(GetTargetWindow,SetTargetWindow)
+ ViewStart = property(GetViewStart)
+_windows_.ScrollHelper_swigregister(ScrollHelper)
+
+class ScrolledWindow(Panel,ScrollHelper):
+ """Proxy of C++ ScrolledWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxHSCROLL|wxVSCROLL,
+ String name=PanelNameStr) -> ScrolledWindow
+ """
+ _windows_.ScrolledWindow_swiginit(self,_windows_.new_ScrolledWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxHSCROLL|wxVSCROLL,
+ String name=PanelNameStr) -> bool
+
+ Create the GUI part of the Window for 2-phase creation mode.
+ """
+ return _windows_.ScrolledWindow_Create(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.ScrolledWindow_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+_windows_.ScrolledWindow_swigregister(ScrolledWindow)
+
+def PreScrolledWindow(*args, **kwargs):
+ """PreScrolledWindow() -> ScrolledWindow"""
+ val = _windows_.new_PreScrolledWindow(*args, **kwargs)
+ return val
+
+def ScrolledWindow_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ ScrolledWindow_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.ScrolledWindow_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+STAY_ON_TOP = _windows_.STAY_ON_TOP
+ICONIZE = _windows_.ICONIZE
+MINIMIZE = _windows_.MINIMIZE
+MAXIMIZE = _windows_.MAXIMIZE
+CLOSE_BOX = _windows_.CLOSE_BOX
+SYSTEM_MENU = _windows_.SYSTEM_MENU
+MINIMIZE_BOX = _windows_.MINIMIZE_BOX
+MAXIMIZE_BOX = _windows_.MAXIMIZE_BOX
+TINY_CAPTION_HORIZ = _windows_.TINY_CAPTION_HORIZ
+TINY_CAPTION_VERT = _windows_.TINY_CAPTION_VERT
+RESIZE_BORDER = _windows_.RESIZE_BORDER
+DIALOG_NO_PARENT = _windows_.DIALOG_NO_PARENT
+DEFAULT_FRAME_STYLE = _windows_.DEFAULT_FRAME_STYLE
+DEFAULT_DIALOG_STYLE = _windows_.DEFAULT_DIALOG_STYLE
+FRAME_TOOL_WINDOW = _windows_.FRAME_TOOL_WINDOW
+FRAME_FLOAT_ON_PARENT = _windows_.FRAME_FLOAT_ON_PARENT
+FRAME_NO_WINDOW_MENU = _windows_.FRAME_NO_WINDOW_MENU
+FRAME_NO_TASKBAR = _windows_.FRAME_NO_TASKBAR
+FRAME_SHAPED = _windows_.FRAME_SHAPED
+FRAME_DRAWER = _windows_.FRAME_DRAWER
+FRAME_EX_METAL = _windows_.FRAME_EX_METAL
+DIALOG_EX_METAL = _windows_.DIALOG_EX_METAL
+WS_EX_CONTEXTHELP = _windows_.WS_EX_CONTEXTHELP
+FRAME_EX_CONTEXTHELP = _windows_.FRAME_EX_CONTEXTHELP
+DIALOG_EX_CONTEXTHELP = _windows_.DIALOG_EX_CONTEXTHELP
+# deprecated
+RESIZE_BOX = MAXIMIZE_BOX
+THICK_FRAME = RESIZE_BORDER
+
+# Obsolete
+wxDIALOG_MODAL = 0
+wxDIALOG_MODELESS = 0
+wxUSER_COLOURS = 0
+wxNO_3D = 0
+
+FULLSCREEN_NOMENUBAR = _windows_.FULLSCREEN_NOMENUBAR
+FULLSCREEN_NOTOOLBAR = _windows_.FULLSCREEN_NOTOOLBAR
+FULLSCREEN_NOSTATUSBAR = _windows_.FULLSCREEN_NOSTATUSBAR
+FULLSCREEN_NOBORDER = _windows_.FULLSCREEN_NOBORDER
+FULLSCREEN_NOCAPTION = _windows_.FULLSCREEN_NOCAPTION
+FULLSCREEN_ALL = _windows_.FULLSCREEN_ALL
+TOPLEVEL_EX_DIALOG = _windows_.TOPLEVEL_EX_DIALOG
+USER_ATTENTION_INFO = _windows_.USER_ATTENTION_INFO
+USER_ATTENTION_ERROR = _windows_.USER_ATTENTION_ERROR
+DIALOG_MODALITY_NONE = _windows_.DIALOG_MODALITY_NONE
+DIALOG_MODALITY_WINDOW_MODAL = _windows_.DIALOG_MODALITY_WINDOW_MODAL
+DIALOG_MODALITY_APP_MODAL = _windows_.DIALOG_MODALITY_APP_MODAL
+class TopLevelWindow(_core.Window):
+ """Proxy of C++ TopLevelWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Maximize(*args, **kwargs):
+ """Maximize(self, bool maximize=True)"""
+ return _windows_.TopLevelWindow_Maximize(*args, **kwargs)
+
+ def Restore(*args, **kwargs):
+ """Restore(self)"""
+ return _windows_.TopLevelWindow_Restore(*args, **kwargs)
+
+ def Iconize(*args, **kwargs):
+ """Iconize(self, bool iconize=True)"""
+ return _windows_.TopLevelWindow_Iconize(*args, **kwargs)
+
+ def IsMaximized(*args, **kwargs):
+ """IsMaximized(self) -> bool"""
+ return _windows_.TopLevelWindow_IsMaximized(*args, **kwargs)
+
+ def IsAlwaysMaximized(*args, **kwargs):
+ """IsAlwaysMaximized(self) -> bool"""
+ return _windows_.TopLevelWindow_IsAlwaysMaximized(*args, **kwargs)
+
+ def IsIconized(*args, **kwargs):
+ """IsIconized(self) -> bool"""
+ return _windows_.TopLevelWindow_IsIconized(*args, **kwargs)
+
+ def GetIcon(*args, **kwargs):
+ """GetIcon(self) -> Icon"""
+ return _windows_.TopLevelWindow_GetIcon(*args, **kwargs)
+
+ def SetIcon(*args, **kwargs):
+ """SetIcon(self, Icon icon)"""
+ return _windows_.TopLevelWindow_SetIcon(*args, **kwargs)
+
+ def SetIcons(*args, **kwargs):
+ """SetIcons(self, wxIconBundle icons)"""
+ return _windows_.TopLevelWindow_SetIcons(*args, **kwargs)
+
+ def ShowFullScreen(*args, **kwargs):
+ """ShowFullScreen(self, bool show, long style=FULLSCREEN_ALL) -> bool"""
+ return _windows_.TopLevelWindow_ShowFullScreen(*args, **kwargs)
+
+ def ShowWithoutActivating(*args, **kwargs):
+ """ShowWithoutActivating(self)"""
+ return _windows_.TopLevelWindow_ShowWithoutActivating(*args, **kwargs)
+
+ def IsFullScreen(*args, **kwargs):
+ """IsFullScreen(self) -> bool"""
+ return _windows_.TopLevelWindow_IsFullScreen(*args, **kwargs)
+
+ def SetTitle(*args, **kwargs):
+ """SetTitle(self, String title)"""
+ return _windows_.TopLevelWindow_SetTitle(*args, **kwargs)
+
+ def GetTitle(*args, **kwargs):
+ """GetTitle(self) -> String"""
+ return _windows_.TopLevelWindow_GetTitle(*args, **kwargs)
+
+ def EnableCloseButton(*args, **kwargs):
+ """EnableCloseButton(self, bool enable) -> bool"""
+ return _windows_.TopLevelWindow_EnableCloseButton(*args, **kwargs)
+
+ def SetShape(*args, **kwargs):
+ """SetShape(self, Region region) -> bool"""
+ return _windows_.TopLevelWindow_SetShape(*args, **kwargs)
+
+ def RequestUserAttention(*args, **kwargs):
+ """RequestUserAttention(self, int flags=USER_ATTENTION_INFO)"""
+ return _windows_.TopLevelWindow_RequestUserAttention(*args, **kwargs)
+
+ def IsActive(*args, **kwargs):
+ """IsActive(self) -> bool"""
+ return _windows_.TopLevelWindow_IsActive(*args, **kwargs)
+
+ def MacSetMetalAppearance(*args, **kwargs):
+ """MacSetMetalAppearance(self, bool on)"""
+ return _windows_.TopLevelWindow_MacSetMetalAppearance(*args, **kwargs)
+
+ def MacGetMetalAppearance(*args, **kwargs):
+ """MacGetMetalAppearance(self) -> bool"""
+ return _windows_.TopLevelWindow_MacGetMetalAppearance(*args, **kwargs)
+
+ def MacGetUnifiedAppearance(*args, **kwargs):
+ """MacGetUnifiedAppearance(self) -> bool"""
+ return _windows_.TopLevelWindow_MacGetUnifiedAppearance(*args, **kwargs)
+
+ def MacGetTopLevelWindowRef(*args, **kwargs):
+ """MacGetTopLevelWindowRef(self) -> long"""
+ return _windows_.TopLevelWindow_MacGetTopLevelWindowRef(*args, **kwargs)
+
+ def CenterOnScreen(*args, **kwargs):
+ """
+ CenterOnScreen(self, int dir=BOTH)
+
+ Center the window on screen
+ """
+ return _windows_.TopLevelWindow_CenterOnScreen(*args, **kwargs)
+
+ CentreOnScreen = CenterOnScreen
+ def GetDefaultSize(*args, **kwargs):
+ """GetDefaultSize() -> Size"""
+ return _windows_.TopLevelWindow_GetDefaultSize(*args, **kwargs)
+
+ GetDefaultSize = staticmethod(GetDefaultSize)
+ def GetDefaultItem(*args, **kwargs):
+ """
+ GetDefaultItem(self) -> Window
+
+ Get the default child of this parent, i.e. the one which is activated
+ by pressing <Enter> such as the OK button on a wx.Dialog.
+ """
+ return _windows_.TopLevelWindow_GetDefaultItem(*args, **kwargs)
+
+ def SetDefaultItem(*args, **kwargs):
+ """
+ SetDefaultItem(self, Window child) -> Window
+
+ Set this child as default, return the old default.
+ """
+ return _windows_.TopLevelWindow_SetDefaultItem(*args, **kwargs)
+
+ def SetTmpDefaultItem(*args, **kwargs):
+ """
+ SetTmpDefaultItem(self, Window win)
+
+ Set this child as temporary default
+ """
+ return _windows_.TopLevelWindow_SetTmpDefaultItem(*args, **kwargs)
+
+ def GetTmpDefaultItem(*args, **kwargs):
+ """
+ GetTmpDefaultItem(self) -> Window
+
+ Return the temporary default item, which can be None.
+ """
+ return _windows_.TopLevelWindow_GetTmpDefaultItem(*args, **kwargs)
+
+ def OSXIsModified(*args, **kwargs):
+ """OSXIsModified(self) -> bool"""
+ return _windows_.TopLevelWindow_OSXIsModified(*args, **kwargs)
+
+ def OSXSetModified(*args, **kwargs):
+ """OSXSetModified(self, bool modified)"""
+ return _windows_.TopLevelWindow_OSXSetModified(*args, **kwargs)
+
+ def SetRepresentedFilename(*args, **kwargs):
+ """SetRepresentedFilename(self, String filename)"""
+ return _windows_.TopLevelWindow_SetRepresentedFilename(*args, **kwargs)
+
+ DefaultItem = property(GetDefaultItem,SetDefaultItem,doc="See `GetDefaultItem` and `SetDefaultItem`")
+ Icon = property(GetIcon,SetIcon,doc="See `GetIcon` and `SetIcon`")
+ Title = property(GetTitle,SetTitle,doc="See `GetTitle` and `SetTitle`")
+ TmpDefaultItem = property(GetTmpDefaultItem,SetTmpDefaultItem,doc="See `GetTmpDefaultItem` and `SetTmpDefaultItem`")
+ OSXModified = property(OSXIsModified,OSXSetModified)
+_windows_.TopLevelWindow_swigregister(TopLevelWindow)
+cvar = _windows_.cvar
+FrameNameStr = cvar.FrameNameStr
+DialogNameStr = cvar.DialogNameStr
+StatusLineNameStr = cvar.StatusLineNameStr
+ToolBarNameStr = cvar.ToolBarNameStr
+
+def TopLevelWindow_GetDefaultSize(*args):
+ """TopLevelWindow_GetDefaultSize() -> Size"""
+ return _windows_.TopLevelWindow_GetDefaultSize(*args)
+
+#---------------------------------------------------------------------------
+
+class Frame(TopLevelWindow):
+ """Proxy of C++ Frame class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String title=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> Frame
+ """
+ _windows_.Frame_swiginit(self,_windows_.new_Frame(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String title=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> bool
+ """
+ return _windows_.Frame_Create(*args, **kwargs)
+
+ def SetMenuBar(*args, **kwargs):
+ """SetMenuBar(self, MenuBar menubar)"""
+ return _windows_.Frame_SetMenuBar(*args, **kwargs)
+
+ def GetMenuBar(*args, **kwargs):
+ """GetMenuBar(self) -> MenuBar"""
+ return _windows_.Frame_GetMenuBar(*args, **kwargs)
+
+ def FindItemInMenuBar(*args, **kwargs):
+ """FindItemInMenuBar(self, int menuId) -> MenuItem"""
+ return _windows_.Frame_FindItemInMenuBar(*args, **kwargs)
+
+ def ProcessCommand(*args):
+ """
+ ProcessCommand(self, int winid) -> bool
+ ProcessCommand(self, MenuItem item) -> bool
+ """
+ return _windows_.Frame_ProcessCommand(*args)
+
+ def CreateStatusBar(*args, **kwargs):
+ """
+ CreateStatusBar(self, int number=1, long style=DEFAULT_STATUSBAR_STYLE, int winid=0,
+ String name=StatusLineNameStr) -> StatusBar
+ """
+ return _windows_.Frame_CreateStatusBar(*args, **kwargs)
+
+ def GetStatusBar(*args, **kwargs):
+ """GetStatusBar(self) -> StatusBar"""
+ return _windows_.Frame_GetStatusBar(*args, **kwargs)
+
+ def SetStatusBar(*args, **kwargs):
+ """SetStatusBar(self, StatusBar statBar)"""
+ return _windows_.Frame_SetStatusBar(*args, **kwargs)
+
+ def SetStatusText(*args, **kwargs):
+ """SetStatusText(self, String text, int number=0)"""
+ return _windows_.Frame_SetStatusText(*args, **kwargs)
+
+ def SetStatusWidths(*args, **kwargs):
+ """SetStatusWidths(self, int widths)"""
+ return _windows_.Frame_SetStatusWidths(*args, **kwargs)
+
+ def PushStatusText(*args, **kwargs):
+ """PushStatusText(self, String text, int number=0)"""
+ return _windows_.Frame_PushStatusText(*args, **kwargs)
+
+ def PopStatusText(*args, **kwargs):
+ """PopStatusText(self, int number=0)"""
+ return _windows_.Frame_PopStatusText(*args, **kwargs)
+
+ def SetStatusBarPane(*args, **kwargs):
+ """SetStatusBarPane(self, int n)"""
+ return _windows_.Frame_SetStatusBarPane(*args, **kwargs)
+
+ def GetStatusBarPane(*args, **kwargs):
+ """GetStatusBarPane(self) -> int"""
+ return _windows_.Frame_GetStatusBarPane(*args, **kwargs)
+
+ def CreateToolBar(*args, **kwargs):
+ """CreateToolBar(self, long style=-1, int winid=-1, String name=ToolBarNameStr) -> wxToolBar"""
+ return _windows_.Frame_CreateToolBar(*args, **kwargs)
+
+ def GetToolBar(*args, **kwargs):
+ """GetToolBar(self) -> wxToolBar"""
+ return _windows_.Frame_GetToolBar(*args, **kwargs)
+
+ def SetToolBar(*args, **kwargs):
+ """SetToolBar(self, wxToolBar toolbar)"""
+ return _windows_.Frame_SetToolBar(*args, **kwargs)
+
+ def DoGiveHelp(*args, **kwargs):
+ """DoGiveHelp(self, String text, bool show)"""
+ return _windows_.Frame_DoGiveHelp(*args, **kwargs)
+
+ def DoMenuUpdates(*args, **kwargs):
+ """DoMenuUpdates(self, Menu menu=None)"""
+ return _windows_.Frame_DoMenuUpdates(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.Frame_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ MenuBar = property(GetMenuBar,SetMenuBar,doc="See `GetMenuBar` and `SetMenuBar`")
+ StatusBar = property(GetStatusBar,SetStatusBar,doc="See `GetStatusBar` and `SetStatusBar`")
+ StatusBarPane = property(GetStatusBarPane,SetStatusBarPane,doc="See `GetStatusBarPane` and `SetStatusBarPane`")
+ ToolBar = property(GetToolBar,SetToolBar,doc="See `GetToolBar` and `SetToolBar`")
+_windows_.Frame_swigregister(Frame)
+
+def PreFrame(*args, **kwargs):
+ """PreFrame() -> Frame"""
+ val = _windows_.new_PreFrame(*args, **kwargs)
+ return val
+
+def Frame_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Frame_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.Frame_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+DIALOG_ADAPTATION_NONE = _windows_.DIALOG_ADAPTATION_NONE
+DIALOG_ADAPTATION_STANDARD_SIZER = _windows_.DIALOG_ADAPTATION_STANDARD_SIZER
+DIALOG_ADAPTATION_ANY_SIZER = _windows_.DIALOG_ADAPTATION_ANY_SIZER
+DIALOG_ADAPTATION_LOOSE_BUTTONS = _windows_.DIALOG_ADAPTATION_LOOSE_BUTTONS
+DIALOG_ADAPTATION_MODE_DEFAULT = _windows_.DIALOG_ADAPTATION_MODE_DEFAULT
+DIALOG_ADAPTATION_MODE_ENABLED = _windows_.DIALOG_ADAPTATION_MODE_ENABLED
+DIALOG_ADAPTATION_MODE_DISABLED = _windows_.DIALOG_ADAPTATION_MODE_DISABLED
+class Dialog(TopLevelWindow):
+ """Proxy of C++ Dialog class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String title=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DEFAULT_DIALOG_STYLE, String name=DialogNameStr) -> Dialog
+ """
+ _windows_.Dialog_swiginit(self,_windows_.new_Dialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String title=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DEFAULT_DIALOG_STYLE, String name=DialogNameStr) -> bool
+ """
+ return _windows_.Dialog_Create(*args, **kwargs)
+
+ def SetReturnCode(*args, **kwargs):
+ """SetReturnCode(self, int returnCode)"""
+ return _windows_.Dialog_SetReturnCode(*args, **kwargs)
+
+ def GetReturnCode(*args, **kwargs):
+ """GetReturnCode(self) -> int"""
+ return _windows_.Dialog_GetReturnCode(*args, **kwargs)
+
+ def SetAffirmativeId(*args, **kwargs):
+ """SetAffirmativeId(self, int affirmativeId)"""
+ return _windows_.Dialog_SetAffirmativeId(*args, **kwargs)
+
+ def GetAffirmativeId(*args, **kwargs):
+ """GetAffirmativeId(self) -> int"""
+ return _windows_.Dialog_GetAffirmativeId(*args, **kwargs)
+
+ def SetEscapeId(*args, **kwargs):
+ """SetEscapeId(self, int escapeId)"""
+ return _windows_.Dialog_SetEscapeId(*args, **kwargs)
+
+ def GetEscapeId(*args, **kwargs):
+ """GetEscapeId(self) -> int"""
+ return _windows_.Dialog_GetEscapeId(*args, **kwargs)
+
+ def GetParentForModalDialog(*args):
+ """
+ GetParentForModalDialog(self, Window parent, long style) -> Window
+ GetParentForModalDialog(self) -> Window
+ """
+ return _windows_.Dialog_GetParentForModalDialog(*args)
+
+ def CreateTextSizer(*args, **kwargs):
+ """CreateTextSizer(self, String message) -> Sizer"""
+ return _windows_.Dialog_CreateTextSizer(*args, **kwargs)
+
+ def CreateSeparatedSizer(*args, **kwargs):
+ """CreateSeparatedSizer(self, Sizer sizer) -> Sizer"""
+ return _windows_.Dialog_CreateSeparatedSizer(*args, **kwargs)
+
+ def _CreateButtonSizer(*args, **kwargs):
+ """_CreateButtonSizer(self, long flags) -> Sizer"""
+ return _windows_.Dialog__CreateButtonSizer(*args, **kwargs)
+
+ def CreateButtonSizer(self, flags, *ignored):
+ return self._CreateButtonSizer(flags)
+
+ def CreateSeparatedButtonSizer(*args, **kwargs):
+ """CreateSeparatedButtonSizer(self, long flags) -> Sizer"""
+ return _windows_.Dialog_CreateSeparatedButtonSizer(*args, **kwargs)
+
+ def CreateStdDialogButtonSizer(*args, **kwargs):
+ """CreateStdDialogButtonSizer(self, long flags) -> StdDialogButtonSizer"""
+ return _windows_.Dialog_CreateStdDialogButtonSizer(*args, **kwargs)
+
+ def IsModal(*args, **kwargs):
+ """IsModal(self) -> bool"""
+ return _windows_.Dialog_IsModal(*args, **kwargs)
+
+ def ShowModal(*args, **kwargs):
+ """ShowModal(self) -> int"""
+ return _windows_.Dialog_ShowModal(*args, **kwargs)
+
+ def EndModal(*args, **kwargs):
+ """EndModal(self, int retCode)"""
+ return _windows_.Dialog_EndModal(*args, **kwargs)
+
+ def ShowWindowModal(*args, **kwargs):
+ """ShowWindowModal(self)"""
+ return _windows_.Dialog_ShowWindowModal(*args, **kwargs)
+
+ def SendWindowModalDialogEvent(*args, **kwargs):
+ """SendWindowModalDialogEvent(self, EventType type)"""
+ return _windows_.Dialog_SendWindowModalDialogEvent(*args, **kwargs)
+
+ def DoLayoutAdaptation(*args, **kwargs):
+ """DoLayoutAdaptation(self) -> bool"""
+ return _windows_.Dialog_DoLayoutAdaptation(*args, **kwargs)
+
+ def CanDoLayoutAdaptation(*args, **kwargs):
+ """CanDoLayoutAdaptation(self) -> bool"""
+ return _windows_.Dialog_CanDoLayoutAdaptation(*args, **kwargs)
+
+ def GetContentWindow(*args, **kwargs):
+ """GetContentWindow(self) -> Window"""
+ return _windows_.Dialog_GetContentWindow(*args, **kwargs)
+
+ def AddMainButtonId(*args, **kwargs):
+ """AddMainButtonId(self, int id)"""
+ return _windows_.Dialog_AddMainButtonId(*args, **kwargs)
+
+ def GetMainButtonIds(*args, **kwargs):
+ """GetMainButtonIds(self) -> wxArrayInt"""
+ return _windows_.Dialog_GetMainButtonIds(*args, **kwargs)
+
+ def IsMainButtonId(*args, **kwargs):
+ """IsMainButtonId(self, int id) -> bool"""
+ return _windows_.Dialog_IsMainButtonId(*args, **kwargs)
+
+ def SetLayoutAdaptationLevel(*args, **kwargs):
+ """SetLayoutAdaptationLevel(self, int level)"""
+ return _windows_.Dialog_SetLayoutAdaptationLevel(*args, **kwargs)
+
+ def GetLayoutAdaptationLevel(*args, **kwargs):
+ """GetLayoutAdaptationLevel(self) -> int"""
+ return _windows_.Dialog_GetLayoutAdaptationLevel(*args, **kwargs)
+
+ def SetLayoutAdaptationMode(*args, **kwargs):
+ """SetLayoutAdaptationMode(self, int mode)"""
+ return _windows_.Dialog_SetLayoutAdaptationMode(*args, **kwargs)
+
+ def GetLayoutAdaptationMode(*args, **kwargs):
+ """GetLayoutAdaptationMode(self) -> int"""
+ return _windows_.Dialog_GetLayoutAdaptationMode(*args, **kwargs)
+
+ def SetLayoutAdaptationDone(*args, **kwargs):
+ """SetLayoutAdaptationDone(self, bool adaptationDone)"""
+ return _windows_.Dialog_SetLayoutAdaptationDone(*args, **kwargs)
+
+ def GetLayoutAdaptationDone(*args, **kwargs):
+ """GetLayoutAdaptationDone(self) -> bool"""
+ return _windows_.Dialog_GetLayoutAdaptationDone(*args, **kwargs)
+
+ def SetLayoutAdapter(*args, **kwargs):
+ """SetLayoutAdapter(DialogLayoutAdapter adapter) -> DialogLayoutAdapter"""
+ return _windows_.Dialog_SetLayoutAdapter(*args, **kwargs)
+
+ SetLayoutAdapter = staticmethod(SetLayoutAdapter)
+ def GetLayoutAdapter(*args, **kwargs):
+ """GetLayoutAdapter() -> DialogLayoutAdapter"""
+ return _windows_.Dialog_GetLayoutAdapter(*args, **kwargs)
+
+ GetLayoutAdapter = staticmethod(GetLayoutAdapter)
+ def IsLayoutAdaptationEnabled(*args, **kwargs):
+ """IsLayoutAdaptationEnabled() -> bool"""
+ return _windows_.Dialog_IsLayoutAdaptationEnabled(*args, **kwargs)
+
+ IsLayoutAdaptationEnabled = staticmethod(IsLayoutAdaptationEnabled)
+ def EnableLayoutAdaptation(*args, **kwargs):
+ """EnableLayoutAdaptation(bool enable)"""
+ return _windows_.Dialog_EnableLayoutAdaptation(*args, **kwargs)
+
+ EnableLayoutAdaptation = staticmethod(EnableLayoutAdaptation)
+ def GetModality(*args, **kwargs):
+ """GetModality(self) -> int"""
+ return _windows_.Dialog_GetModality(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.Dialog_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.Destroy()
+
+ AffirmativeId = property(GetAffirmativeId,SetAffirmativeId,doc="See `GetAffirmativeId` and `SetAffirmativeId`")
+ EscapeId = property(GetEscapeId,SetEscapeId,doc="See `GetEscapeId` and `SetEscapeId`")
+ ReturnCode = property(GetReturnCode,SetReturnCode,doc="See `GetReturnCode` and `SetReturnCode`")
+_windows_.Dialog_swigregister(Dialog)
+
+def PreDialog(*args, **kwargs):
+ """PreDialog() -> Dialog"""
+ val = _windows_.new_PreDialog(*args, **kwargs)
+ return val
+
+def Dialog_SetLayoutAdapter(*args, **kwargs):
+ """Dialog_SetLayoutAdapter(DialogLayoutAdapter adapter) -> DialogLayoutAdapter"""
+ return _windows_.Dialog_SetLayoutAdapter(*args, **kwargs)
+
+def Dialog_GetLayoutAdapter(*args):
+ """Dialog_GetLayoutAdapter() -> DialogLayoutAdapter"""
+ return _windows_.Dialog_GetLayoutAdapter(*args)
+
+def Dialog_IsLayoutAdaptationEnabled(*args):
+ """Dialog_IsLayoutAdaptationEnabled() -> bool"""
+ return _windows_.Dialog_IsLayoutAdaptationEnabled(*args)
+
+def Dialog_EnableLayoutAdaptation(*args, **kwargs):
+ """Dialog_EnableLayoutAdaptation(bool enable)"""
+ return _windows_.Dialog_EnableLayoutAdaptation(*args, **kwargs)
+
+def Dialog_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Dialog_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.Dialog_GetClassDefaultAttributes(*args, **kwargs)
+
+class DialogLayoutAdapter(_core.Object):
+ """Proxy of C++ DialogLayoutAdapter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def CanDoLayoutAdaptation(*args, **kwargs):
+ """CanDoLayoutAdaptation(self, Dialog dialog) -> bool"""
+ return _windows_.DialogLayoutAdapter_CanDoLayoutAdaptation(*args, **kwargs)
+
+ def DoLayoutAdaptation(*args, **kwargs):
+ """DoLayoutAdaptation(self, Dialog dialog) -> bool"""
+ return _windows_.DialogLayoutAdapter_DoLayoutAdaptation(*args, **kwargs)
+
+_windows_.DialogLayoutAdapter_swigregister(DialogLayoutAdapter)
+
+class StandardDialogLayoutAdapter(DialogLayoutAdapter):
+ """Proxy of C++ StandardDialogLayoutAdapter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> StandardDialogLayoutAdapter"""
+ _windows_.StandardDialogLayoutAdapter_swiginit(self,_windows_.new_StandardDialogLayoutAdapter(*args, **kwargs))
+ def CreateScrolledWindow(*args, **kwargs):
+ """CreateScrolledWindow(self, Window parent) -> ScrolledWindow"""
+ return _windows_.StandardDialogLayoutAdapter_CreateScrolledWindow(*args, **kwargs)
+
+ def FindButtonSizer(*args, **kwargs):
+ """
+ FindButtonSizer(self, bool stdButtonSizer, Dialog dialog, Sizer sizer, int retBorder,
+ int accumlatedBorder=0) -> Sizer
+ """
+ return _windows_.StandardDialogLayoutAdapter_FindButtonSizer(*args, **kwargs)
+
+ def IsOrdinaryButtonSizer(*args, **kwargs):
+ """IsOrdinaryButtonSizer(self, Dialog dialog, BoxSizer sizer) -> bool"""
+ return _windows_.StandardDialogLayoutAdapter_IsOrdinaryButtonSizer(*args, **kwargs)
+
+ def IsStandardButton(*args, **kwargs):
+ """IsStandardButton(self, Dialog dialog, wxButton button) -> bool"""
+ return _windows_.StandardDialogLayoutAdapter_IsStandardButton(*args, **kwargs)
+
+ def FindLooseButtons(*args, **kwargs):
+ """
+ FindLooseButtons(self, Dialog dialog, StdDialogButtonSizer buttonSizer, Sizer sizer,
+ int count) -> bool
+ """
+ return _windows_.StandardDialogLayoutAdapter_FindLooseButtons(*args, **kwargs)
+
+ def ReparentControls(*args, **kwargs):
+ """ReparentControls(self, Window parent, Window reparentTo, Sizer buttonSizer=None)"""
+ return _windows_.StandardDialogLayoutAdapter_ReparentControls(*args, **kwargs)
+
+ def DoReparentControls(*args, **kwargs):
+ """DoReparentControls(Window parent, Window reparentTo, Sizer buttonSizer=None)"""
+ return _windows_.StandardDialogLayoutAdapter_DoReparentControls(*args, **kwargs)
+
+ DoReparentControls = staticmethod(DoReparentControls)
+ def FitWithScrolling(*args, **kwargs):
+ """FitWithScrolling(self, Dialog dialog, ScrolledWindow scrolledWindow) -> bool"""
+ return _windows_.StandardDialogLayoutAdapter_FitWithScrolling(*args, **kwargs)
+
+ def DoFitWithScrolling(*args, **kwargs):
+ """DoFitWithScrolling(Dialog dialog, ScrolledWindow scrolledWindow) -> bool"""
+ return _windows_.StandardDialogLayoutAdapter_DoFitWithScrolling(*args, **kwargs)
+
+ DoFitWithScrolling = staticmethod(DoFitWithScrolling)
+ def MustScroll(*args, **kwargs):
+ """MustScroll(self, Dialog dialog, Size windowSize, Size displaySize) -> int"""
+ return _windows_.StandardDialogLayoutAdapter_MustScroll(*args, **kwargs)
+
+ def DoMustScroll(*args, **kwargs):
+ """DoMustScroll(Dialog dialog, Size windowSize, Size displaySize) -> int"""
+ return _windows_.StandardDialogLayoutAdapter_DoMustScroll(*args, **kwargs)
+
+ DoMustScroll = staticmethod(DoMustScroll)
+_windows_.StandardDialogLayoutAdapter_swigregister(StandardDialogLayoutAdapter)
+
+def StandardDialogLayoutAdapter_DoReparentControls(*args, **kwargs):
+ """StandardDialogLayoutAdapter_DoReparentControls(Window parent, Window reparentTo, Sizer buttonSizer=None)"""
+ return _windows_.StandardDialogLayoutAdapter_DoReparentControls(*args, **kwargs)
+
+def StandardDialogLayoutAdapter_DoFitWithScrolling(*args, **kwargs):
+ """StandardDialogLayoutAdapter_DoFitWithScrolling(Dialog dialog, ScrolledWindow scrolledWindow) -> bool"""
+ return _windows_.StandardDialogLayoutAdapter_DoFitWithScrolling(*args, **kwargs)
+
+def StandardDialogLayoutAdapter_DoMustScroll(*args, **kwargs):
+ """StandardDialogLayoutAdapter_DoMustScroll(Dialog dialog, Size windowSize, Size displaySize) -> int"""
+ return _windows_.StandardDialogLayoutAdapter_DoMustScroll(*args, **kwargs)
+
+class WindowModalDialogEvent(_core.CommandEvent):
+ """Proxy of C++ WindowModalDialogEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=wxEVT_NULL, int id=0) -> WindowModalDialogEvent"""
+ _windows_.WindowModalDialogEvent_swiginit(self,_windows_.new_WindowModalDialogEvent(*args, **kwargs))
+ def GetDialog(*args, **kwargs):
+ """GetDialog(self) -> Dialog"""
+ return _windows_.WindowModalDialogEvent_GetDialog(*args, **kwargs)
+
+ def GetReturnCode(*args, **kwargs):
+ """GetReturnCode(self) -> int"""
+ return _windows_.WindowModalDialogEvent_GetReturnCode(*args, **kwargs)
+
+ Dialog = property(GetDialog)
+ ReturnCode = property(GetReturnCode)
+_windows_.WindowModalDialogEvent_swigregister(WindowModalDialogEvent)
+
+wxEVT_WINDOW_MODAL_DIALOG_CLOSED = _windows_.wxEVT_WINDOW_MODAL_DIALOG_CLOSED
+EVT_WINDOW_MODAL_DIALOG_CLOSED = wx.PyEventBinder(wxEVT_WINDOW_MODAL_DIALOG_CLOSED)
+
+#---------------------------------------------------------------------------
+
+DEFAULT_MINIFRAME_STYLE = _windows_.DEFAULT_MINIFRAME_STYLE
+class MiniFrame(Frame):
+ """Proxy of C++ MiniFrame class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String title=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DEFAULT_MINIFRAME_STYLE, String name=FrameNameStr) -> MiniFrame
+ """
+ _windows_.MiniFrame_swiginit(self,_windows_.new_MiniFrame(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String title=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DEFAULT_MINIFRAME_STYLE, String name=FrameNameStr) -> bool
+ """
+ return _windows_.MiniFrame_Create(*args, **kwargs)
+
+_windows_.MiniFrame_swigregister(MiniFrame)
+
+def PreMiniFrame(*args, **kwargs):
+ """PreMiniFrame() -> MiniFrame"""
+ val = _windows_.new_PreMiniFrame(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+SPLASH_CENTRE_ON_PARENT = _windows_.SPLASH_CENTRE_ON_PARENT
+SPLASH_CENTRE_ON_SCREEN = _windows_.SPLASH_CENTRE_ON_SCREEN
+SPLASH_NO_CENTRE = _windows_.SPLASH_NO_CENTRE
+SPLASH_CENTER_ON_PARENT = _windows_.SPLASH_CENTER_ON_PARENT
+SPLASH_CENTER_ON_SCREEN = _windows_.SPLASH_CENTER_ON_SCREEN
+SPLASH_NO_CENTER = _windows_.SPLASH_NO_CENTER
+SPLASH_TIMEOUT = _windows_.SPLASH_TIMEOUT
+SPLASH_NO_TIMEOUT = _windows_.SPLASH_NO_TIMEOUT
+class SplashScreenWindow(_core.Window):
+ """Proxy of C++ SplashScreenWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Bitmap bitmap, Window parent, int id, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=NO_BORDER) -> SplashScreenWindow
+ """
+ _windows_.SplashScreenWindow_swiginit(self,_windows_.new_SplashScreenWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def SetBitmap(*args, **kwargs):
+ """SetBitmap(self, Bitmap bitmap)"""
+ return _windows_.SplashScreenWindow_SetBitmap(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self) -> Bitmap"""
+ return _windows_.SplashScreenWindow_GetBitmap(*args, **kwargs)
+
+ Bitmap = property(GetBitmap,SetBitmap,doc="See `GetBitmap` and `SetBitmap`")
+_windows_.SplashScreenWindow_swigregister(SplashScreenWindow)
+
+class SplashScreen(Frame):
+ """Proxy of C++ SplashScreen class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Bitmap bitmap, long splashStyle, int milliseconds,
+ Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP) -> SplashScreen
+ """
+ _windows_.SplashScreen_swiginit(self,_windows_.new_SplashScreen(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetSplashStyle(*args, **kwargs):
+ """GetSplashStyle(self) -> long"""
+ return _windows_.SplashScreen_GetSplashStyle(*args, **kwargs)
+
+ def GetSplashWindow(*args, **kwargs):
+ """GetSplashWindow(self) -> SplashScreenWindow"""
+ return _windows_.SplashScreen_GetSplashWindow(*args, **kwargs)
+
+ def GetTimeout(*args, **kwargs):
+ """GetTimeout(self) -> int"""
+ return _windows_.SplashScreen_GetTimeout(*args, **kwargs)
+
+ SplashStyle = property(GetSplashStyle,doc="See `GetSplashStyle`")
+ SplashWindow = property(GetSplashWindow,doc="See `GetSplashWindow`")
+ Timeout = property(GetTimeout,doc="See `GetTimeout`")
+_windows_.SplashScreen_swigregister(SplashScreen)
+
+#---------------------------------------------------------------------------
+
+STB_SIZEGRIP = _windows_.STB_SIZEGRIP
+STB_SHOW_TIPS = _windows_.STB_SHOW_TIPS
+STB_ELLIPSIZE_START = _windows_.STB_ELLIPSIZE_START
+STB_ELLIPSIZE_MIDDLE = _windows_.STB_ELLIPSIZE_MIDDLE
+STB_ELLIPSIZE_END = _windows_.STB_ELLIPSIZE_END
+STB_DEFAULT_STYLE = _windows_.STB_DEFAULT_STYLE
+ST_SIZEGRIP = _windows_.ST_SIZEGRIP
+SB_NORMAL = _windows_.SB_NORMAL
+SB_FLAT = _windows_.SB_FLAT
+SB_RAISED = _windows_.SB_RAISED
+class StatusBarPane(object):
+ """Proxy of C++ StatusBarPane class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int style=SB_NORMAL, size_t width=0) -> StatusBarPane"""
+ _windows_.StatusBarPane_swiginit(self,_windows_.new_StatusBarPane(*args, **kwargs))
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _windows_.StatusBarPane_GetWidth(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self) -> int"""
+ return _windows_.StatusBarPane_GetStyle(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self) -> String"""
+ return _windows_.StatusBarPane_GetText(*args, **kwargs)
+
+ def IsEllipsized(*args, **kwargs):
+ """IsEllipsized(self) -> bool"""
+ return _windows_.StatusBarPane_IsEllipsized(*args, **kwargs)
+
+ def SetIsEllipsized(*args, **kwargs):
+ """SetIsEllipsized(self, bool isEllipsized)"""
+ return _windows_.StatusBarPane_SetIsEllipsized(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """SetWidth(self, int width)"""
+ return _windows_.StatusBarPane_SetWidth(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """SetStyle(self, int style)"""
+ return _windows_.StatusBarPane_SetStyle(*args, **kwargs)
+
+ def SetText(*args, **kwargs):
+ """SetText(self, String text) -> bool"""
+ return _windows_.StatusBarPane_SetText(*args, **kwargs)
+
+ def PushText(*args, **kwargs):
+ """PushText(self, String text) -> bool"""
+ return _windows_.StatusBarPane_PushText(*args, **kwargs)
+
+ def PopText(*args, **kwargs):
+ """PopText(self) -> bool"""
+ return _windows_.StatusBarPane_PopText(*args, **kwargs)
+
+_windows_.StatusBarPane_swigregister(StatusBarPane)
+
+class StatusBar(_core.Window):
+ """Proxy of C++ StatusBar class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, long style=DEFAULT_STATUSBAR_STYLE,
+ String name=StatusLineNameStr) -> StatusBar
+ """
+ _windows_.StatusBar_swiginit(self,_windows_.new_StatusBar(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """Create(self, Window parent, int id=-1, long style=ST_SIZEGRIP, String name=StatusLineNameStr) -> bool"""
+ return _windows_.StatusBar_Create(*args, **kwargs)
+
+ def SetFieldsCount(*args, **kwargs):
+ """SetFieldsCount(self, int number=1)"""
+ return _windows_.StatusBar_SetFieldsCount(*args, **kwargs)
+
+ def GetFieldsCount(*args, **kwargs):
+ """GetFieldsCount(self) -> int"""
+ return _windows_.StatusBar_GetFieldsCount(*args, **kwargs)
+
+ def SetStatusText(*args, **kwargs):
+ """SetStatusText(self, String text, int number=0)"""
+ return _windows_.StatusBar_SetStatusText(*args, **kwargs)
+
+ def GetStatusText(*args, **kwargs):
+ """GetStatusText(self, int number=0) -> String"""
+ return _windows_.StatusBar_GetStatusText(*args, **kwargs)
+
+ def PushStatusText(*args, **kwargs):
+ """PushStatusText(self, String text, int number=0)"""
+ return _windows_.StatusBar_PushStatusText(*args, **kwargs)
+
+ def PopStatusText(*args, **kwargs):
+ """PopStatusText(self, int number=0)"""
+ return _windows_.StatusBar_PopStatusText(*args, **kwargs)
+
+ def SetStatusWidths(*args, **kwargs):
+ """SetStatusWidths(self, int widths)"""
+ return _windows_.StatusBar_SetStatusWidths(*args, **kwargs)
+
+ def GetStatusWidth(*args, **kwargs):
+ """GetStatusWidth(self, int n) -> int"""
+ return _windows_.StatusBar_GetStatusWidth(*args, **kwargs)
+
+ def SetStatusStyles(*args, **kwargs):
+ """SetStatusStyles(self, int styles)"""
+ return _windows_.StatusBar_SetStatusStyles(*args, **kwargs)
+
+ def GetStatusStyle(*args, **kwargs):
+ """GetStatusStyle(self, int n) -> int"""
+ return _windows_.StatusBar_GetStatusStyle(*args, **kwargs)
+
+ def GetFieldRect(*args, **kwargs):
+ """GetFieldRect(self, int i) -> Rect"""
+ return _windows_.StatusBar_GetFieldRect(*args, **kwargs)
+
+ def SetMinHeight(*args, **kwargs):
+ """SetMinHeight(self, int height)"""
+ return _windows_.StatusBar_SetMinHeight(*args, **kwargs)
+
+ def GetBorderX(*args, **kwargs):
+ """GetBorderX(self) -> int"""
+ return _windows_.StatusBar_GetBorderX(*args, **kwargs)
+
+ def GetBorderY(*args, **kwargs):
+ """GetBorderY(self) -> int"""
+ return _windows_.StatusBar_GetBorderY(*args, **kwargs)
+
+ def GetBorders(*args, **kwargs):
+ """GetBorders(self) -> Size"""
+ return _windows_.StatusBar_GetBorders(*args, **kwargs)
+
+ def GetField(*args, **kwargs):
+ """GetField(self, int n) -> StatusBarPane"""
+ return _windows_.StatusBar_GetField(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.StatusBar_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ def GetFields(self):
+ """Return a list of field values in the status bar. """
+ return [self.GetStatusText(i) for i in range(self.GetFieldsCount())]
+
+ def SetFields(self, items):
+ """Set the values of the statusbar fields from a list of strings. """
+ self.SetFieldsCount(len(items))
+ for i in range(len(items)):
+ self.SetStatusText(items[i], i)
+
+ BorderX = property(GetBorderX,doc="See `GetBorderX`")
+ BorderY = property(GetBorderY,doc="See `GetBorderY`")
+ FieldRect = property(GetFieldRect,doc="See `GetFieldRect`")
+ Fields = property(GetFields,SetFields,doc="See `GetFields` and `SetFields`")
+ FieldsCount = property(GetFieldsCount,SetFieldsCount,doc="See `GetFieldsCount` and `SetFieldsCount`")
+ StatusText = property(GetStatusText,SetStatusText,doc="See `GetStatusText` and `SetStatusText`")
+_windows_.StatusBar_swigregister(StatusBar)
+
+def PreStatusBar(*args, **kwargs):
+ """PreStatusBar() -> StatusBar"""
+ val = _windows_.new_PreStatusBar(*args, **kwargs)
+ return val
+
+def StatusBar_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ StatusBar_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.StatusBar_GetClassDefaultAttributes(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+SP_NOBORDER = _windows_.SP_NOBORDER
+SP_THIN_SASH = _windows_.SP_THIN_SASH
+SP_NOSASH = _windows_.SP_NOSASH
+SP_PERMIT_UNSPLIT = _windows_.SP_PERMIT_UNSPLIT
+SP_LIVE_UPDATE = _windows_.SP_LIVE_UPDATE
+SP_3DSASH = _windows_.SP_3DSASH
+SP_3DBORDER = _windows_.SP_3DBORDER
+SP_NO_XP_THEME = _windows_.SP_NO_XP_THEME
+SP_BORDER = _windows_.SP_BORDER
+SP_3D = _windows_.SP_3D
+SPLIT_HORIZONTAL = _windows_.SPLIT_HORIZONTAL
+SPLIT_VERTICAL = _windows_.SPLIT_VERTICAL
+SPLIT_DRAG_NONE = _windows_.SPLIT_DRAG_NONE
+SPLIT_DRAG_DRAGGING = _windows_.SPLIT_DRAG_DRAGGING
+SPLIT_DRAG_LEFT_DOWN = _windows_.SPLIT_DRAG_LEFT_DOWN
+class SplitterWindow(_core.Window):
+ """
+ wx.SplitterWindow manages up to two subwindows or panes, with an
+ optional vertical or horizontal split which can be used with the mouse
+ or programmatically.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=SP_3D, String name=SplitterNameStr) -> SplitterWindow
+
+ Constructor. Creates and shows a SplitterWindow.
+ """
+ if kwargs.has_key('point'): kwargs['pos'] = kwargs['point'];del kwargs['point']
+ _windows_.SplitterWindow_swiginit(self,_windows_.new_SplitterWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=SP_3D, String name=SplitterNameStr) -> bool
+
+ Create the GUI part of the SplitterWindow for the 2-phase create.
+ """
+ return _windows_.SplitterWindow_Create(*args, **kwargs)
+
+ def GetWindow1(*args, **kwargs):
+ """
+ GetWindow1(self) -> Window
+
+ Gets the only or left/top pane.
+ """
+ return _windows_.SplitterWindow_GetWindow1(*args, **kwargs)
+
+ def GetWindow2(*args, **kwargs):
+ """
+ GetWindow2(self) -> Window
+
+ Gets the right/bottom pane.
+ """
+ return _windows_.SplitterWindow_GetWindow2(*args, **kwargs)
+
+ def SetSplitMode(*args, **kwargs):
+ """
+ SetSplitMode(self, int mode)
+
+ Sets the split mode. The mode can be wx.SPLIT_VERTICAL or
+ wx.SPLIT_HORIZONTAL. This only sets the internal variable; does not
+ update the display.
+ """
+ return _windows_.SplitterWindow_SetSplitMode(*args, **kwargs)
+
+ def GetSplitMode(*args, **kwargs):
+ """
+ GetSplitMode(self) -> int
+
+ Gets the split mode
+ """
+ return _windows_.SplitterWindow_GetSplitMode(*args, **kwargs)
+
+ def Initialize(*args, **kwargs):
+ """
+ Initialize(self, Window window)
+
+ Initializes the splitter window to have one pane. This should be
+ called if you wish to initially view only a single pane in the
+ splitter window. The child window is shown if it is currently hidden.
+ """
+ return _windows_.SplitterWindow_Initialize(*args, **kwargs)
+
+ def SplitVertically(*args, **kwargs):
+ """
+ SplitVertically(self, Window window1, Window window2, int sashPosition=0) -> bool
+
+ Initializes the left and right panes of the splitter window. The
+ child windows are shown if they are currently hidden.
+ """
+ return _windows_.SplitterWindow_SplitVertically(*args, **kwargs)
+
+ def SplitHorizontally(*args, **kwargs):
+ """
+ SplitHorizontally(self, Window window1, Window window2, int sashPosition=0) -> bool
+
+ Initializes the top and bottom panes of the splitter window. The
+ child windows are shown if they are currently hidden.
+ """
+ return _windows_.SplitterWindow_SplitHorizontally(*args, **kwargs)
+
+ def Unsplit(*args, **kwargs):
+ """
+ Unsplit(self, Window toRemove=None) -> bool
+
+ Unsplits the window. Pass the pane to remove, or None to remove the
+ right or bottom pane. Returns True if successful, False otherwise (the
+ window was not split).
+
+ This function will not actually delete the pane being
+ removed; it sends EVT_SPLITTER_UNSPLIT which can be handled
+ for the desired behaviour. By default, the pane being
+ removed is only hidden.
+ """
+ return _windows_.SplitterWindow_Unsplit(*args, **kwargs)
+
+ def ReplaceWindow(*args, **kwargs):
+ """
+ ReplaceWindow(self, Window winOld, Window winNew) -> bool
+
+ This function replaces one of the windows managed by the
+ SplitterWindow with another one. It is in general better to use it
+ instead of calling Unsplit() and then resplitting the window back
+ because it will provoke much less flicker. It is valid to call this
+ function whether the splitter has two windows or only one.
+
+ Both parameters should be non-None and winOld must specify one of the
+ windows managed by the splitter. If the parameters are incorrect or
+ the window couldn't be replaced, False is returned. Otherwise the
+ function will return True, but please notice that it will not Destroy
+ the replaced window and you may wish to do it yourself.
+ """
+ return _windows_.SplitterWindow_ReplaceWindow(*args, **kwargs)
+
+ def UpdateSize(*args, **kwargs):
+ """
+ UpdateSize(self)
+
+ Causes any pending sizing of the sash and child panes to take place
+ immediately.
+
+ Such resizing normally takes place in idle time, in order to wait for
+ layout to be completed. However, this can cause unacceptable flicker
+ as the panes are resized after the window has been shown. To work
+ around this, you can perform window layout (for example by sending a
+ size event to the parent window), and then call this function, before
+ showing the top-level window.
+ """
+ return _windows_.SplitterWindow_UpdateSize(*args, **kwargs)
+
+ def IsSplit(*args, **kwargs):
+ """
+ IsSplit(self) -> bool
+
+ Is the window split?
+ """
+ return _windows_.SplitterWindow_IsSplit(*args, **kwargs)
+
+ def SetSashSize(*args, **kwargs):
+ """
+ SetSashSize(self, int width)
+
+ Sets the sash size.
+ """
+ return _windows_.SplitterWindow_SetSashSize(*args, **kwargs)
+
+ def SetBorderSize(*args, **kwargs):
+ """
+ SetBorderSize(self, int width)
+
+ Sets the border size. Currently a NOP.
+ """
+ return _windows_.SplitterWindow_SetBorderSize(*args, **kwargs)
+
+ def GetSashSize(*args, **kwargs):
+ """
+ GetSashSize(self) -> int
+
+ Gets the sash size
+ """
+ return _windows_.SplitterWindow_GetSashSize(*args, **kwargs)
+
+ def GetBorderSize(*args, **kwargs):
+ """
+ GetBorderSize(self) -> int
+
+ Gets the border size
+ """
+ return _windows_.SplitterWindow_GetBorderSize(*args, **kwargs)
+
+ def SetSashPosition(*args, **kwargs):
+ """
+ SetSashPosition(self, int position, bool redraw=True)
+
+ Sets the sash position, in pixels. If redraw is True then the panes
+ are resized and the sash and border are redrawn.
+ """
+ return _windows_.SplitterWindow_SetSashPosition(*args, **kwargs)
+
+ def GetSashPosition(*args, **kwargs):
+ """
+ GetSashPosition(self) -> int
+
+ Returns the surrent sash position.
+ """
+ return _windows_.SplitterWindow_GetSashPosition(*args, **kwargs)
+
+ def SetSashGravity(*args, **kwargs):
+ """
+ SetSashGravity(self, double gravity)
+
+ Set the sash gravity. Gravity is a floating-point factor between 0.0
+ and 1.0 which controls position of sash while resizing the
+ `wx.SplitterWindow`. The gravity specifies how much the left/top
+ window will grow while resizing.
+ """
+ return _windows_.SplitterWindow_SetSashGravity(*args, **kwargs)
+
+ def GetSashGravity(*args, **kwargs):
+ """
+ GetSashGravity(self) -> double
+
+ Gets the sash gravity.
+
+ :see: `SetSashGravity`
+
+ """
+ return _windows_.SplitterWindow_GetSashGravity(*args, **kwargs)
+
+ def SetMinimumPaneSize(*args, **kwargs):
+ """
+ SetMinimumPaneSize(self, int min)
+
+ Sets the minimum pane size in pixels.
+
+ The default minimum pane size is zero, which means that either pane
+ can be reduced to zero by dragging the sash, thus removing one of the
+ panes. To prevent this behaviour (and veto out-of-range sash
+ dragging), set a minimum size, for example 20 pixels. If the
+ wx.SP_PERMIT_UNSPLIT style is used when a splitter window is created,
+ the window may be unsplit even if minimum size is non-zero.
+ """
+ return _windows_.SplitterWindow_SetMinimumPaneSize(*args, **kwargs)
+
+ def GetMinimumPaneSize(*args, **kwargs):
+ """
+ GetMinimumPaneSize(self) -> int
+
+ Gets the minimum pane size in pixels.
+ """
+ return _windows_.SplitterWindow_GetMinimumPaneSize(*args, **kwargs)
+
+ def SashHitTest(*args, **kwargs):
+ """
+ SashHitTest(self, int x, int y) -> bool
+
+ Tests for x, y over the sash
+ """
+ return _windows_.SplitterWindow_SashHitTest(*args, **kwargs)
+
+ def SizeWindows(*args, **kwargs):
+ """
+ SizeWindows(self)
+
+ Resizes subwindows
+ """
+ return _windows_.SplitterWindow_SizeWindows(*args, **kwargs)
+
+ def SetSashInvisible(*args, **kwargs):
+ """SetSashInvisible(self, bool invisible=True)"""
+ return _windows_.SplitterWindow_SetSashInvisible(*args, **kwargs)
+
+ def IsSashInvisible(*args, **kwargs):
+ """IsSashInvisible(self) -> bool"""
+ return _windows_.SplitterWindow_IsSashInvisible(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.SplitterWindow_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ BorderSize = property(GetBorderSize,SetBorderSize,doc="See `GetBorderSize` and `SetBorderSize`")
+ MinimumPaneSize = property(GetMinimumPaneSize,SetMinimumPaneSize,doc="See `GetMinimumPaneSize` and `SetMinimumPaneSize`")
+ SashGravity = property(GetSashGravity,SetSashGravity,doc="See `GetSashGravity` and `SetSashGravity`")
+ SashPosition = property(GetSashPosition,SetSashPosition,doc="See `GetSashPosition` and `SetSashPosition`")
+ SashSize = property(GetSashSize,SetSashSize,doc="See `GetSashSize` and `SetSashSize`")
+ SplitMode = property(GetSplitMode,SetSplitMode,doc="See `GetSplitMode` and `SetSplitMode`")
+ Window1 = property(GetWindow1,doc="See `GetWindow1`")
+ Window2 = property(GetWindow2,doc="See `GetWindow2`")
+_windows_.SplitterWindow_swigregister(SplitterWindow)
+SplitterNameStr = cvar.SplitterNameStr
+
+def PreSplitterWindow(*args, **kwargs):
+ """
+ PreSplitterWindow() -> SplitterWindow
+
+ Precreate a SplitterWindow for 2-phase creation.
+ """
+ val = _windows_.new_PreSplitterWindow(*args, **kwargs)
+ return val
+
+def SplitterWindow_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ SplitterWindow_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _windows_.SplitterWindow_GetClassDefaultAttributes(*args, **kwargs)
+
+class SplitterEvent(_core.NotifyEvent):
+ """This class represents the events generated by a splitter control."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType type=wxEVT_NULL, SplitterWindow splitter=(wxSplitterWindow *) NULL) -> SplitterEvent
+
+ This class represents the events generated by a splitter control.
+ """
+ _windows_.SplitterEvent_swiginit(self,_windows_.new_SplitterEvent(*args, **kwargs))
+ def SetSashPosition(*args, **kwargs):
+ """
+ SetSashPosition(self, int pos)
+
+ This function is only meaningful during EVT_SPLITTER_SASH_POS_CHANGING
+ and EVT_SPLITTER_SASH_POS_CHANGED events. In the case of _CHANGED
+ events, sets the the new sash position. In the case of _CHANGING
+ events, sets the new tracking bar position so visual feedback during
+ dragging will represent that change that will actually take place. Set
+ to -1 from the event handler code to prevent repositioning.
+ """
+ return _windows_.SplitterEvent_SetSashPosition(*args, **kwargs)
+
+ def GetSashPosition(*args, **kwargs):
+ """
+ GetSashPosition(self) -> int
+
+ Returns the new sash position while in EVT_SPLITTER_SASH_POS_CHANGING
+ and EVT_SPLITTER_SASH_POS_CHANGED events.
+ """
+ return _windows_.SplitterEvent_GetSashPosition(*args, **kwargs)
+
+ def GetWindowBeingRemoved(*args, **kwargs):
+ """
+ GetWindowBeingRemoved(self) -> Window
+
+ Returns a pointer to the window being removed when a splitter window
+ is unsplit.
+ """
+ return _windows_.SplitterEvent_GetWindowBeingRemoved(*args, **kwargs)
+
+ def GetX(*args, **kwargs):
+ """
+ GetX(self) -> int
+
+ Returns the x coordinate of the double-click point in a
+ EVT_SPLITTER_DCLICK event.
+ """
+ return _windows_.SplitterEvent_GetX(*args, **kwargs)
+
+ def GetY(*args, **kwargs):
+ """
+ GetY(self) -> int
+
+ Returns the y coordinate of the double-click point in a
+ EVT_SPLITTER_DCLICK event.
+ """
+ return _windows_.SplitterEvent_GetY(*args, **kwargs)
+
+ SashPosition = property(GetSashPosition,SetSashPosition,doc="See `GetSashPosition` and `SetSashPosition`")
+ WindowBeingRemoved = property(GetWindowBeingRemoved,doc="See `GetWindowBeingRemoved`")
+ X = property(GetX,doc="See `GetX`")
+ Y = property(GetY,doc="See `GetY`")
+_windows_.SplitterEvent_swigregister(SplitterEvent)
+
+wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED = _windows_.wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED
+wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING = _windows_.wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING
+wxEVT_COMMAND_SPLITTER_DOUBLECLICKED = _windows_.wxEVT_COMMAND_SPLITTER_DOUBLECLICKED
+wxEVT_COMMAND_SPLITTER_UNSPLIT = _windows_.wxEVT_COMMAND_SPLITTER_UNSPLIT
+EVT_SPLITTER_SASH_POS_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, 1 )
+EVT_SPLITTER_SASH_POS_CHANGING = wx.PyEventBinder( wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, 1 )
+EVT_SPLITTER_DOUBLECLICKED = wx.PyEventBinder( wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 1 )
+EVT_SPLITTER_UNSPLIT = wx.PyEventBinder( wxEVT_COMMAND_SPLITTER_UNSPLIT, 1 )
+EVT_SPLITTER_DCLICK = EVT_SPLITTER_DOUBLECLICKED
+
+#---------------------------------------------------------------------------
+
+SASH_DRAG_NONE = _windows_.SASH_DRAG_NONE
+SASH_DRAG_DRAGGING = _windows_.SASH_DRAG_DRAGGING
+SASH_DRAG_LEFT_DOWN = _windows_.SASH_DRAG_LEFT_DOWN
+SW_NOBORDER = _windows_.SW_NOBORDER
+SW_BORDER = _windows_.SW_BORDER
+SW_3DSASH = _windows_.SW_3DSASH
+SW_3DBORDER = _windows_.SW_3DBORDER
+SW_3D = _windows_.SW_3D
+SASH_TOP = _windows_.SASH_TOP
+SASH_RIGHT = _windows_.SASH_RIGHT
+SASH_BOTTOM = _windows_.SASH_BOTTOM
+SASH_LEFT = _windows_.SASH_LEFT
+SASH_NONE = _windows_.SASH_NONE
+class SashWindow(_core.Window):
+ """Proxy of C++ SashWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxSW_3D,
+ String name=SashNameStr) -> SashWindow
+ """
+ _windows_.SashWindow_swiginit(self,_windows_.new_SashWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxSW_3D,
+ String name=SashNameStr) -> bool
+ """
+ return _windows_.SashWindow_Create(*args, **kwargs)
+
+ def SetSashVisible(*args, **kwargs):
+ """SetSashVisible(self, int edge, bool sash)"""
+ return _windows_.SashWindow_SetSashVisible(*args, **kwargs)
+
+ def GetSashVisible(*args, **kwargs):
+ """GetSashVisible(self, int edge) -> bool"""
+ return _windows_.SashWindow_GetSashVisible(*args, **kwargs)
+
+ def GetEdgeMargin(*args, **kwargs):
+ """GetEdgeMargin(self, int edge) -> int"""
+ return _windows_.SashWindow_GetEdgeMargin(*args, **kwargs)
+
+ def SetDefaultBorderSize(*args, **kwargs):
+ """SetDefaultBorderSize(self, int width)"""
+ return _windows_.SashWindow_SetDefaultBorderSize(*args, **kwargs)
+
+ def GetDefaultBorderSize(*args, **kwargs):
+ """GetDefaultBorderSize(self) -> int"""
+ return _windows_.SashWindow_GetDefaultBorderSize(*args, **kwargs)
+
+ def SetExtraBorderSize(*args, **kwargs):
+ """SetExtraBorderSize(self, int width)"""
+ return _windows_.SashWindow_SetExtraBorderSize(*args, **kwargs)
+
+ def GetExtraBorderSize(*args, **kwargs):
+ """GetExtraBorderSize(self) -> int"""
+ return _windows_.SashWindow_GetExtraBorderSize(*args, **kwargs)
+
+ def SetMinimumSizeX(*args, **kwargs):
+ """SetMinimumSizeX(self, int min)"""
+ return _windows_.SashWindow_SetMinimumSizeX(*args, **kwargs)
+
+ def SetMinimumSizeY(*args, **kwargs):
+ """SetMinimumSizeY(self, int min)"""
+ return _windows_.SashWindow_SetMinimumSizeY(*args, **kwargs)
+
+ def GetMinimumSizeX(*args, **kwargs):
+ """GetMinimumSizeX(self) -> int"""
+ return _windows_.SashWindow_GetMinimumSizeX(*args, **kwargs)
+
+ def GetMinimumSizeY(*args, **kwargs):
+ """GetMinimumSizeY(self) -> int"""
+ return _windows_.SashWindow_GetMinimumSizeY(*args, **kwargs)
+
+ def SetMaximumSizeX(*args, **kwargs):
+ """SetMaximumSizeX(self, int max)"""
+ return _windows_.SashWindow_SetMaximumSizeX(*args, **kwargs)
+
+ def SetMaximumSizeY(*args, **kwargs):
+ """SetMaximumSizeY(self, int max)"""
+ return _windows_.SashWindow_SetMaximumSizeY(*args, **kwargs)
+
+ def GetMaximumSizeX(*args, **kwargs):
+ """GetMaximumSizeX(self) -> int"""
+ return _windows_.SashWindow_GetMaximumSizeX(*args, **kwargs)
+
+ def GetMaximumSizeY(*args, **kwargs):
+ """GetMaximumSizeY(self) -> int"""
+ return _windows_.SashWindow_GetMaximumSizeY(*args, **kwargs)
+
+ def SashHitTest(*args, **kwargs):
+ """SashHitTest(self, int x, int y, int tolerance=2) -> int"""
+ return _windows_.SashWindow_SashHitTest(*args, **kwargs)
+
+ def SizeWindows(*args, **kwargs):
+ """SizeWindows(self)"""
+ return _windows_.SashWindow_SizeWindows(*args, **kwargs)
+
+ DefaultBorderSize = property(GetDefaultBorderSize,SetDefaultBorderSize,doc="See `GetDefaultBorderSize` and `SetDefaultBorderSize`")
+ ExtraBorderSize = property(GetExtraBorderSize,SetExtraBorderSize,doc="See `GetExtraBorderSize` and `SetExtraBorderSize`")
+ MaximumSizeX = property(GetMaximumSizeX,SetMaximumSizeX,doc="See `GetMaximumSizeX` and `SetMaximumSizeX`")
+ MaximumSizeY = property(GetMaximumSizeY,SetMaximumSizeY,doc="See `GetMaximumSizeY` and `SetMaximumSizeY`")
+ MinimumSizeX = property(GetMinimumSizeX,SetMinimumSizeX,doc="See `GetMinimumSizeX` and `SetMinimumSizeX`")
+ MinimumSizeY = property(GetMinimumSizeY,SetMinimumSizeY,doc="See `GetMinimumSizeY` and `SetMinimumSizeY`")
+_windows_.SashWindow_swigregister(SashWindow)
+SashNameStr = cvar.SashNameStr
+SashLayoutNameStr = cvar.SashLayoutNameStr
+
+def PreSashWindow(*args, **kwargs):
+ """PreSashWindow() -> SashWindow"""
+ val = _windows_.new_PreSashWindow(*args, **kwargs)
+ return val
+
+SASH_STATUS_OK = _windows_.SASH_STATUS_OK
+SASH_STATUS_OUT_OF_RANGE = _windows_.SASH_STATUS_OUT_OF_RANGE
+class SashEvent(_core.CommandEvent):
+ """Proxy of C++ SashEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int id=0, int edge=SASH_NONE) -> SashEvent"""
+ _windows_.SashEvent_swiginit(self,_windows_.new_SashEvent(*args, **kwargs))
+ def SetEdge(*args, **kwargs):
+ """SetEdge(self, int edge)"""
+ return _windows_.SashEvent_SetEdge(*args, **kwargs)
+
+ def GetEdge(*args, **kwargs):
+ """GetEdge(self) -> int"""
+ return _windows_.SashEvent_GetEdge(*args, **kwargs)
+
+ def SetDragRect(*args, **kwargs):
+ """SetDragRect(self, Rect rect)"""
+ return _windows_.SashEvent_SetDragRect(*args, **kwargs)
+
+ def GetDragRect(*args, **kwargs):
+ """GetDragRect(self) -> Rect"""
+ return _windows_.SashEvent_GetDragRect(*args, **kwargs)
+
+ def SetDragStatus(*args, **kwargs):
+ """SetDragStatus(self, int status)"""
+ return _windows_.SashEvent_SetDragStatus(*args, **kwargs)
+
+ def GetDragStatus(*args, **kwargs):
+ """GetDragStatus(self) -> int"""
+ return _windows_.SashEvent_GetDragStatus(*args, **kwargs)
+
+ DragRect = property(GetDragRect,SetDragRect,doc="See `GetDragRect` and `SetDragRect`")
+ DragStatus = property(GetDragStatus,SetDragStatus,doc="See `GetDragStatus` and `SetDragStatus`")
+ Edge = property(GetEdge,SetEdge,doc="See `GetEdge` and `SetEdge`")
+_windows_.SashEvent_swigregister(SashEvent)
+
+wxEVT_SASH_DRAGGED = _windows_.wxEVT_SASH_DRAGGED
+EVT_SASH_DRAGGED = wx.PyEventBinder( wxEVT_SASH_DRAGGED, 1 )
+EVT_SASH_DRAGGED_RANGE = wx.PyEventBinder( wxEVT_SASH_DRAGGED, 2 )
+
+#---------------------------------------------------------------------------
+
+LAYOUT_HORIZONTAL = _windows_.LAYOUT_HORIZONTAL
+LAYOUT_VERTICAL = _windows_.LAYOUT_VERTICAL
+LAYOUT_NONE = _windows_.LAYOUT_NONE
+LAYOUT_TOP = _windows_.LAYOUT_TOP
+LAYOUT_LEFT = _windows_.LAYOUT_LEFT
+LAYOUT_RIGHT = _windows_.LAYOUT_RIGHT
+LAYOUT_BOTTOM = _windows_.LAYOUT_BOTTOM
+LAYOUT_LENGTH_Y = _windows_.LAYOUT_LENGTH_Y
+LAYOUT_LENGTH_X = _windows_.LAYOUT_LENGTH_X
+LAYOUT_MRU_LENGTH = _windows_.LAYOUT_MRU_LENGTH
+LAYOUT_QUERY = _windows_.LAYOUT_QUERY
+wxEVT_QUERY_LAYOUT_INFO = _windows_.wxEVT_QUERY_LAYOUT_INFO
+wxEVT_CALCULATE_LAYOUT = _windows_.wxEVT_CALCULATE_LAYOUT
+class QueryLayoutInfoEvent(_core.Event):
+ """Proxy of C++ QueryLayoutInfoEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int id=0) -> QueryLayoutInfoEvent"""
+ _windows_.QueryLayoutInfoEvent_swiginit(self,_windows_.new_QueryLayoutInfoEvent(*args, **kwargs))
+ def SetRequestedLength(*args, **kwargs):
+ """SetRequestedLength(self, int length)"""
+ return _windows_.QueryLayoutInfoEvent_SetRequestedLength(*args, **kwargs)
+
+ def GetRequestedLength(*args, **kwargs):
+ """GetRequestedLength(self) -> int"""
+ return _windows_.QueryLayoutInfoEvent_GetRequestedLength(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _windows_.QueryLayoutInfoEvent_SetFlags(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _windows_.QueryLayoutInfoEvent_GetFlags(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, Size size)"""
+ return _windows_.QueryLayoutInfoEvent_SetSize(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(self) -> Size"""
+ return _windows_.QueryLayoutInfoEvent_GetSize(*args, **kwargs)
+
+ def SetOrientation(*args, **kwargs):
+ """SetOrientation(self, int orient)"""
+ return _windows_.QueryLayoutInfoEvent_SetOrientation(*args, **kwargs)
+
+ def GetOrientation(*args, **kwargs):
+ """GetOrientation(self) -> int"""
+ return _windows_.QueryLayoutInfoEvent_GetOrientation(*args, **kwargs)
+
+ def SetAlignment(*args, **kwargs):
+ """SetAlignment(self, int align)"""
+ return _windows_.QueryLayoutInfoEvent_SetAlignment(*args, **kwargs)
+
+ def GetAlignment(*args, **kwargs):
+ """GetAlignment(self) -> int"""
+ return _windows_.QueryLayoutInfoEvent_GetAlignment(*args, **kwargs)
+
+ Alignment = property(GetAlignment,SetAlignment,doc="See `GetAlignment` and `SetAlignment`")
+ Flags = property(GetFlags,SetFlags,doc="See `GetFlags` and `SetFlags`")
+ Orientation = property(GetOrientation,SetOrientation,doc="See `GetOrientation` and `SetOrientation`")
+ RequestedLength = property(GetRequestedLength,SetRequestedLength,doc="See `GetRequestedLength` and `SetRequestedLength`")
+ Size = property(GetSize,SetSize,doc="See `GetSize` and `SetSize`")
+_windows_.QueryLayoutInfoEvent_swigregister(QueryLayoutInfoEvent)
+
+class CalculateLayoutEvent(_core.Event):
+ """Proxy of C++ CalculateLayoutEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int id=0) -> CalculateLayoutEvent"""
+ _windows_.CalculateLayoutEvent_swiginit(self,_windows_.new_CalculateLayoutEvent(*args, **kwargs))
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _windows_.CalculateLayoutEvent_SetFlags(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _windows_.CalculateLayoutEvent_GetFlags(*args, **kwargs)
+
+ def SetRect(*args, **kwargs):
+ """SetRect(self, Rect rect)"""
+ return _windows_.CalculateLayoutEvent_SetRect(*args, **kwargs)
+
+ def GetRect(*args, **kwargs):
+ """GetRect(self) -> Rect"""
+ return _windows_.CalculateLayoutEvent_GetRect(*args, **kwargs)
+
+ Flags = property(GetFlags,SetFlags,doc="See `GetFlags` and `SetFlags`")
+ Rect = property(GetRect,SetRect,doc="See `GetRect` and `SetRect`")
+_windows_.CalculateLayoutEvent_swigregister(CalculateLayoutEvent)
+
+EVT_QUERY_LAYOUT_INFO = wx.PyEventBinder( wxEVT_QUERY_LAYOUT_INFO )
+EVT_CALCULATE_LAYOUT = wx.PyEventBinder( wxEVT_CALCULATE_LAYOUT )
+
+class SashLayoutWindow(SashWindow):
+ """Proxy of C++ SashLayoutWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxSW_3D,
+ String name=SashLayoutNameStr) -> SashLayoutWindow
+ """
+ _windows_.SashLayoutWindow_swiginit(self,_windows_.new_SashLayoutWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxSW_3D,
+ String name=SashLayoutNameStr) -> bool
+ """
+ return _windows_.SashLayoutWindow_Create(*args, **kwargs)
+
+ def GetAlignment(*args, **kwargs):
+ """GetAlignment(self) -> int"""
+ return _windows_.SashLayoutWindow_GetAlignment(*args, **kwargs)
+
+ def GetOrientation(*args, **kwargs):
+ """GetOrientation(self) -> int"""
+ return _windows_.SashLayoutWindow_GetOrientation(*args, **kwargs)
+
+ def SetAlignment(*args, **kwargs):
+ """SetAlignment(self, int alignment)"""
+ return _windows_.SashLayoutWindow_SetAlignment(*args, **kwargs)
+
+ def SetDefaultSize(*args, **kwargs):
+ """SetDefaultSize(self, Size size)"""
+ return _windows_.SashLayoutWindow_SetDefaultSize(*args, **kwargs)
+
+ def SetOrientation(*args, **kwargs):
+ """SetOrientation(self, int orientation)"""
+ return _windows_.SashLayoutWindow_SetOrientation(*args, **kwargs)
+
+ Alignment = property(GetAlignment,SetAlignment,doc="See `GetAlignment` and `SetAlignment`")
+ Orientation = property(GetOrientation,SetOrientation,doc="See `GetOrientation` and `SetOrientation`")
+_windows_.SashLayoutWindow_swigregister(SashLayoutWindow)
+
+def PreSashLayoutWindow(*args, **kwargs):
+ """PreSashLayoutWindow() -> SashLayoutWindow"""
+ val = _windows_.new_PreSashLayoutWindow(*args, **kwargs)
+ return val
+
+class LayoutAlgorithm(_core.Object):
+ """Proxy of C++ LayoutAlgorithm class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> LayoutAlgorithm"""
+ _windows_.LayoutAlgorithm_swiginit(self,_windows_.new_LayoutAlgorithm(*args, **kwargs))
+ __swig_destroy__ = _windows_.delete_LayoutAlgorithm
+ __del__ = lambda self : None;
+ def LayoutMDIFrame(*args, **kwargs):
+ """LayoutMDIFrame(self, MDIParentFrame frame, Rect rect=None) -> bool"""
+ return _windows_.LayoutAlgorithm_LayoutMDIFrame(*args, **kwargs)
+
+ def LayoutFrame(*args, **kwargs):
+ """LayoutFrame(self, Frame frame, Window mainWindow=None) -> bool"""
+ return _windows_.LayoutAlgorithm_LayoutFrame(*args, **kwargs)
+
+ def LayoutWindow(*args, **kwargs):
+ """LayoutWindow(self, Window parent, Window mainWindow=None) -> bool"""
+ return _windows_.LayoutAlgorithm_LayoutWindow(*args, **kwargs)
+
+_windows_.LayoutAlgorithm_swigregister(LayoutAlgorithm)
+
+#---------------------------------------------------------------------------
+
+class PopupWindow(_core.Window):
+ """Proxy of C++ PopupWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window parent, int flags=BORDER_NONE) -> PopupWindow"""
+ _windows_.PopupWindow_swiginit(self,_windows_.new_PopupWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """Create(self, Window parent, int flags=BORDER_NONE) -> bool"""
+ return _windows_.PopupWindow_Create(*args, **kwargs)
+
+ def Position(*args, **kwargs):
+ """Position(self, Point ptOrigin, Size size)"""
+ return _windows_.PopupWindow_Position(*args, **kwargs)
+
+_windows_.PopupWindow_swigregister(PopupWindow)
+
+def PrePopupWindow(*args, **kwargs):
+ """PrePopupWindow() -> PopupWindow"""
+ val = _windows_.new_PrePopupWindow(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+class PopupTransientWindow(PopupWindow):
+ """Proxy of C++ PopupTransientWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window parent, int style=BORDER_NONE) -> PopupTransientWindow"""
+ _windows_.PopupTransientWindow_swiginit(self,_windows_.new_PopupTransientWindow(*args, **kwargs))
+ self._setOORInfo(self);PopupTransientWindow._setCallbackInfo(self, self, PopupTransientWindow)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.PopupTransientWindow__setCallbackInfo(*args, **kwargs)
+
+ def Popup(*args, **kwargs):
+ """Popup(self, Window focus=None)"""
+ return _windows_.PopupTransientWindow_Popup(*args, **kwargs)
+
+ def Dismiss(*args, **kwargs):
+ """Dismiss(self)"""
+ return _windows_.PopupTransientWindow_Dismiss(*args, **kwargs)
+
+ def CanDismiss(*args, **kwargs):
+ """CanDismiss(self) -> bool"""
+ return _windows_.PopupTransientWindow_CanDismiss(*args, **kwargs)
+
+ def ProcessLeftDown(*args, **kwargs):
+ """ProcessLeftDown(self, MouseEvent event) -> bool"""
+ return _windows_.PopupTransientWindow_ProcessLeftDown(*args, **kwargs)
+
+_windows_.PopupTransientWindow_swigregister(PopupTransientWindow)
+
+def PrePopupTransientWindow(*args, **kwargs):
+ """PrePopupTransientWindow() -> PopupTransientWindow"""
+ val = _windows_.new_PrePopupTransientWindow(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+class TipWindow(PopupTransientWindow):
+ """Proxy of C++ TipWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window parent, String text, int maxLength=100, Rect rectBound=None) -> TipWindow"""
+ _windows_.TipWindow_swiginit(self,_windows_.new_TipWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def SetBoundingRect(*args, **kwargs):
+ """SetBoundingRect(self, Rect rectBound)"""
+ return _windows_.TipWindow_SetBoundingRect(*args, **kwargs)
+
+ def Close(*args, **kwargs):
+ """
+ Close(self)
+
+ This function simply generates a EVT_CLOSE event whose handler usually
+ tries to close the window. It doesn't close the window itself,
+ however. If force is False (the default) then the window's close
+ handler will be allowed to veto the destruction of the window.
+ """
+ return _windows_.TipWindow_Close(*args, **kwargs)
+
+_windows_.TipWindow_swigregister(TipWindow)
+
+#---------------------------------------------------------------------------
+
+class VarScrollHelperBase(object):
+ """Proxy of C++ VarScrollHelperBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def EnablePhysicalScrolling(*args, **kwargs):
+ """EnablePhysicalScrolling(self, bool scrolling=True)"""
+ return _windows_.VarScrollHelperBase_EnablePhysicalScrolling(*args, **kwargs)
+
+ def VirtualHitTest(*args, **kwargs):
+ """VirtualHitTest(self, int coord) -> int"""
+ return _windows_.VarScrollHelperBase_VirtualHitTest(*args, **kwargs)
+
+ def RefreshAll(*args, **kwargs):
+ """RefreshAll(self)"""
+ return _windows_.VarScrollHelperBase_RefreshAll(*args, **kwargs)
+
+ def GetVisibleBegin(*args, **kwargs):
+ """GetVisibleBegin(self) -> size_t"""
+ return _windows_.VarScrollHelperBase_GetVisibleBegin(*args, **kwargs)
+
+ def GetVisibleEnd(*args, **kwargs):
+ """GetVisibleEnd(self) -> size_t"""
+ return _windows_.VarScrollHelperBase_GetVisibleEnd(*args, **kwargs)
+
+ def IsVisible(*args, **kwargs):
+ """IsVisible(self, size_t unit) -> bool"""
+ return _windows_.VarScrollHelperBase_IsVisible(*args, **kwargs)
+
+ def CalcScrolledPosition(*args, **kwargs):
+ """CalcScrolledPosition(self, int coord) -> int"""
+ return _windows_.VarScrollHelperBase_CalcScrolledPosition(*args, **kwargs)
+
+ def CalcUnscrolledPosition(*args, **kwargs):
+ """CalcUnscrolledPosition(self, int coord) -> int"""
+ return _windows_.VarScrollHelperBase_CalcUnscrolledPosition(*args, **kwargs)
+
+ def UpdateScrollbar(*args, **kwargs):
+ """UpdateScrollbar(self)"""
+ return _windows_.VarScrollHelperBase_UpdateScrollbar(*args, **kwargs)
+
+ def RemoveScrollbar(*args, **kwargs):
+ """RemoveScrollbar(self)"""
+ return _windows_.VarScrollHelperBase_RemoveScrollbar(*args, **kwargs)
+
+ def SetTargetWindow(*args, **kwargs):
+ """SetTargetWindow(self, Window target)"""
+ return _windows_.VarScrollHelperBase_SetTargetWindow(*args, **kwargs)
+
+ def GetTargetWindow(*args, **kwargs):
+ """GetTargetWindow(self) -> Window"""
+ return _windows_.VarScrollHelperBase_GetTargetWindow(*args, **kwargs)
+
+ def GetOrientationTargetSize(*args, **kwargs):
+ """GetOrientationTargetSize(self) -> int"""
+ return _windows_.VarScrollHelperBase_GetOrientationTargetSize(*args, **kwargs)
+
+ def GetNonOrientationTargetSize(*args, **kwargs):
+ """GetNonOrientationTargetSize(self) -> int"""
+ return _windows_.VarScrollHelperBase_GetNonOrientationTargetSize(*args, **kwargs)
+
+ def GetOrientation(*args, **kwargs):
+ """GetOrientation(self) -> int"""
+ return _windows_.VarScrollHelperBase_GetOrientation(*args, **kwargs)
+
+_windows_.VarScrollHelperBase_swigregister(VarScrollHelperBase)
+
+class VarVScrollHelper(VarScrollHelperBase):
+ """Proxy of C++ VarVScrollHelper class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def SetRowCount(*args, **kwargs):
+ """SetRowCount(self, size_t rowCount)"""
+ return _windows_.VarVScrollHelper_SetRowCount(*args, **kwargs)
+
+ def ScrollToRow(*args, **kwargs):
+ """ScrollToRow(self, size_t row) -> bool"""
+ return _windows_.VarVScrollHelper_ScrollToRow(*args, **kwargs)
+
+ def ScrollRows(*args, **kwargs):
+ """ScrollRows(self, int rows) -> bool"""
+ return _windows_.VarVScrollHelper_ScrollRows(*args, **kwargs)
+
+ def ScrollRowPages(*args, **kwargs):
+ """ScrollRowPages(self, int pages) -> bool"""
+ return _windows_.VarVScrollHelper_ScrollRowPages(*args, **kwargs)
+
+ def RefreshRow(*args, **kwargs):
+ """RefreshRow(self, size_t row)"""
+ return _windows_.VarVScrollHelper_RefreshRow(*args, **kwargs)
+
+ def RefreshRows(*args, **kwargs):
+ """RefreshRows(self, size_t from, size_t to)"""
+ return _windows_.VarVScrollHelper_RefreshRows(*args, **kwargs)
+
+ def GetRowCount(*args, **kwargs):
+ """GetRowCount(self) -> size_t"""
+ return _windows_.VarVScrollHelper_GetRowCount(*args, **kwargs)
+
+ def GetVisibleRowsBegin(*args, **kwargs):
+ """GetVisibleRowsBegin(self) -> size_t"""
+ return _windows_.VarVScrollHelper_GetVisibleRowsBegin(*args, **kwargs)
+
+ def GetVisibleRowsEnd(*args, **kwargs):
+ """GetVisibleRowsEnd(self) -> size_t"""
+ return _windows_.VarVScrollHelper_GetVisibleRowsEnd(*args, **kwargs)
+
+ def IsRowVisible(*args, **kwargs):
+ """IsRowVisible(self, size_t row) -> bool"""
+ return _windows_.VarVScrollHelper_IsRowVisible(*args, **kwargs)
+
+_windows_.VarVScrollHelper_swigregister(VarVScrollHelper)
+
+class VarHScrollHelper(VarScrollHelperBase):
+ """Proxy of C++ VarHScrollHelper class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def SetColumnCount(*args, **kwargs):
+ """SetColumnCount(self, size_t columnCount)"""
+ return _windows_.VarHScrollHelper_SetColumnCount(*args, **kwargs)
+
+ def ScrollToColumn(*args, **kwargs):
+ """ScrollToColumn(self, size_t column) -> bool"""
+ return _windows_.VarHScrollHelper_ScrollToColumn(*args, **kwargs)
+
+ def ScrollColumns(*args, **kwargs):
+ """ScrollColumns(self, int columns) -> bool"""
+ return _windows_.VarHScrollHelper_ScrollColumns(*args, **kwargs)
+
+ def ScrollColumnPages(*args, **kwargs):
+ """ScrollColumnPages(self, int pages) -> bool"""
+ return _windows_.VarHScrollHelper_ScrollColumnPages(*args, **kwargs)
+
+ def RefreshColumn(*args, **kwargs):
+ """RefreshColumn(self, size_t column)"""
+ return _windows_.VarHScrollHelper_RefreshColumn(*args, **kwargs)
+
+ def RefreshColumns(*args, **kwargs):
+ """RefreshColumns(self, size_t from, size_t to)"""
+ return _windows_.VarHScrollHelper_RefreshColumns(*args, **kwargs)
+
+ def GetColumnCount(*args, **kwargs):
+ """GetColumnCount(self) -> size_t"""
+ return _windows_.VarHScrollHelper_GetColumnCount(*args, **kwargs)
+
+ def GetVisibleColumnsBegin(*args, **kwargs):
+ """GetVisibleColumnsBegin(self) -> size_t"""
+ return _windows_.VarHScrollHelper_GetVisibleColumnsBegin(*args, **kwargs)
+
+ def GetVisibleColumnsEnd(*args, **kwargs):
+ """GetVisibleColumnsEnd(self) -> size_t"""
+ return _windows_.VarHScrollHelper_GetVisibleColumnsEnd(*args, **kwargs)
+
+ def IsColumnVisible(*args, **kwargs):
+ """IsColumnVisible(self, size_t column) -> bool"""
+ return _windows_.VarHScrollHelper_IsColumnVisible(*args, **kwargs)
+
+_windows_.VarHScrollHelper_swigregister(VarHScrollHelper)
+
+class VarHVScrollHelper(VarVScrollHelper,VarHScrollHelper):
+ """Proxy of C++ VarHVScrollHelper class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def SetRowColumnCount(*args, **kwargs):
+ """SetRowColumnCount(self, size_t rowCount, size_t columnCount)"""
+ return _windows_.VarHVScrollHelper_SetRowColumnCount(*args, **kwargs)
+
+ def EnablePhysicalScrolling(*args, **kwargs):
+ """EnablePhysicalScrolling(self, bool vscrolling=True, bool hscrolling=True)"""
+ return _windows_.VarHVScrollHelper_EnablePhysicalScrolling(*args, **kwargs)
+
+ def ScrollToRowColumn(*args, **kwargs):
+ """ScrollToRowColumn(self, Position pos) -> bool"""
+ return _windows_.VarHVScrollHelper_ScrollToRowColumn(*args, **kwargs)
+
+ def RefreshRowColumn(*args, **kwargs):
+ """RefreshRowColumn(self, Position pos)"""
+ return _windows_.VarHVScrollHelper_RefreshRowColumn(*args, **kwargs)
+
+ def RefreshRowsColumns(*args, **kwargs):
+ """RefreshRowsColumns(self, Position from, Position to)"""
+ return _windows_.VarHVScrollHelper_RefreshRowsColumns(*args, **kwargs)
+
+ def VirtualHitTest(*args, **kwargs):
+ """VirtualHitTest(self, Point pos) -> Position"""
+ return _windows_.VarHVScrollHelper_VirtualHitTest(*args, **kwargs)
+
+ def ScrollLayout(*args, **kwargs):
+ """ScrollLayout(self) -> bool"""
+ return _windows_.VarHVScrollHelper_ScrollLayout(*args, **kwargs)
+
+ def GetRowColumnCount(*args, **kwargs):
+ """GetRowColumnCount(self) -> Size"""
+ return _windows_.VarHVScrollHelper_GetRowColumnCount(*args, **kwargs)
+
+ def GetVisibleBegin(*args, **kwargs):
+ """GetVisibleBegin(self) -> Position"""
+ return _windows_.VarHVScrollHelper_GetVisibleBegin(*args, **kwargs)
+
+ def GetVisibleEnd(*args, **kwargs):
+ """GetVisibleEnd(self) -> Position"""
+ return _windows_.VarHVScrollHelper_GetVisibleEnd(*args, **kwargs)
+
+ def IsVisible(*args, **kwargs):
+ """IsVisible(self, Position pos) -> bool"""
+ return _windows_.VarHVScrollHelper_IsVisible(*args, **kwargs)
+
+_windows_.VarHVScrollHelper_swigregister(VarHVScrollHelper)
+
+class VScrolledWindow(Panel,VarVScrollHelper):
+ """Proxy of C++ VScrolledWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=PanelNameStr) -> VScrolledWindow
+ """
+ _windows_.VScrolledWindow_swiginit(self,_windows_.new_VScrolledWindow(*args, **kwargs))
+ self._setOORInfo(self);VScrolledWindow._setCallbackInfo(self, self, VScrolledWindow)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.VScrolledWindow__setCallbackInfo(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=PanelNameStr) -> bool
+ """
+ return _windows_.VScrolledWindow_Create(*args, **kwargs)
+
+ def GetRowsHeight(*args, **kwargs):
+ """GetRowsHeight(self, size_t lineMin, size_t lineMax) -> int"""
+ return _windows_.VScrolledWindow_GetRowsHeight(*args, **kwargs)
+
+ GetLinesHeight = wx.deprecated(GetRowsHeight,
+ "Use GetRowsHeight instead.")
+ def EstimateTotalHeight(*args, **kwargs):
+ """EstimateTotalHeight(self) -> int"""
+ return _windows_.VScrolledWindow_EstimateTotalHeight(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(self, Point pt) -> int
+
+ Test where the given (in client coords) point lies
+ """
+ return _windows_.VScrolledWindow_HitTest(*args, **kwargs)
+
+ def GetFirstVisibleLine(self):
+ return self.GetVisibleRowsBegin()
+ GetFirstVisibleLine = wx.deprecated(GetFirstVisibleLine, "Use GetVisibleRowsBegin instead" )
+
+ def GetLastVisibleLine(self):
+ return self.GetVisibleRowsEnd() - 1
+ GetLastVisibleLine = wx.deprecated(GetLastVisibleLine, "Use GetVisibleRowsEnd instead")
+
+ def GetLineCount(self):
+ return self.GetRowCount()
+ GetLineCount = wx.deprecated(GetLineCount, "Use GetRowCount instead")
+
+ def SetLineCount(self, count):
+ self.SetRowCount(count)
+ SetLineCount = wx.deprecated(SetLineCount, "Use SetRowCount instead")
+
+ def RefreshLine(self, line):
+ self.RefreshRow(line)
+ RefreshLine = wx.deprecated(RefreshLine, "Use RefreshRow instead")
+
+ def RefreshLines(self, frm, to):
+ self.RefreshRows(frm, to)
+ RefreshLines = wx.deprecated(RefreshLines, "Use RefreshRows instead")
+
+ def ScrollToLine(self, line):
+ return self.ScrollToRow(line)
+ ScrollToLine = wx.deprecated(ScrollToLine, "Use RefreshRow instead")
+
+ def ScrollLines(self, lines):
+ return self.ScrollRows(lines)
+ ScrollLines = wx.deprecated(ScrollLines, "Use ScrollRows instead")
+
+ def ScrollPages(self, pages):
+ return self.ScrollRowPages(pages)
+ ScrollPages = wx.deprecated(ScrollPages, "Use ScrollRowPages instead")
+
+_windows_.VScrolledWindow_swigregister(VScrolledWindow)
+
+def PreVScrolledWindow(*args, **kwargs):
+ """PreVScrolledWindow() -> VScrolledWindow"""
+ val = _windows_.new_PreVScrolledWindow(*args, **kwargs)
+ return val
+
+class HScrolledWindow(Panel,VarHScrollHelper):
+ """Proxy of C++ HScrolledWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=PanelNameStr) -> HScrolledWindow
+ """
+ _windows_.HScrolledWindow_swiginit(self,_windows_.new_HScrolledWindow(*args, **kwargs))
+ self._setOORInfo(self);HScrolledWindow._setCallbackInfo(self, self, HScrolledWindow)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.HScrolledWindow__setCallbackInfo(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=PanelNameStr) -> bool
+ """
+ return _windows_.HScrolledWindow_Create(*args, **kwargs)
+
+ def GetColumnsWidth(*args, **kwargs):
+ """GetColumnsWidth(self, size_t columnMin, size_t columnMax) -> int"""
+ return _windows_.HScrolledWindow_GetColumnsWidth(*args, **kwargs)
+
+ def EstimateTotalWidth(*args, **kwargs):
+ """EstimateTotalWidth(self) -> int"""
+ return _windows_.HScrolledWindow_EstimateTotalWidth(*args, **kwargs)
+
+_windows_.HScrolledWindow_swigregister(HScrolledWindow)
+
+def PreHScrolledWindow(*args, **kwargs):
+ """PreHScrolledWindow() -> HScrolledWindow"""
+ val = _windows_.new_PreHScrolledWindow(*args, **kwargs)
+ return val
+
+class HVScrolledWindow(Panel,VarHVScrollHelper):
+ """Proxy of C++ HVScrolledWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=PanelNameStr) -> HVScrolledWindow
+ """
+ _windows_.HVScrolledWindow_swiginit(self,_windows_.new_HVScrolledWindow(*args, **kwargs))
+ self._setOORInfo(self);HVScrolledWindow._setCallbackInfo(self, self, HVScrolledWindow)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.HVScrolledWindow__setCallbackInfo(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=PanelNameStr) -> bool
+ """
+ return _windows_.HVScrolledWindow_Create(*args, **kwargs)
+
+ def GetRowsHeight(*args, **kwargs):
+ """GetRowsHeight(self, size_t lineMin, size_t lineMax) -> int"""
+ return _windows_.HVScrolledWindow_GetRowsHeight(*args, **kwargs)
+
+ def EstimateTotalHeight(*args, **kwargs):
+ """EstimateTotalHeight(self) -> int"""
+ return _windows_.HVScrolledWindow_EstimateTotalHeight(*args, **kwargs)
+
+ def GetColumnsWidth(*args, **kwargs):
+ """GetColumnsWidth(self, size_t columnMin, size_t columnMax) -> int"""
+ return _windows_.HVScrolledWindow_GetColumnsWidth(*args, **kwargs)
+
+ def EstimateTotalWidth(*args, **kwargs):
+ """EstimateTotalWidth(self) -> int"""
+ return _windows_.HVScrolledWindow_EstimateTotalWidth(*args, **kwargs)
+
+_windows_.HVScrolledWindow_swigregister(HVScrolledWindow)
+
+def PreHVScrolledWindow(*args, **kwargs):
+ """PreHVScrolledWindow() -> HVScrolledWindow"""
+ val = _windows_.new_PreHVScrolledWindow(*args, **kwargs)
+ return val
+
+class VListBox(VScrolledWindow):
+ """Proxy of C++ VListBox class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=VListBoxNameStr) -> VListBox
+ """
+ _windows_.VListBox_swiginit(self,_windows_.new_VListBox(*args, **kwargs))
+ self._setOORInfo(self);VListBox._setCallbackInfo(self, self, VListBox)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.VListBox__setCallbackInfo(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=VListBoxNameStr) -> bool
+ """
+ return _windows_.VListBox_Create(*args, **kwargs)
+
+ def GetItemCount(*args, **kwargs):
+ """GetItemCount(self) -> size_t"""
+ return _windows_.VListBox_GetItemCount(*args, **kwargs)
+
+ def HasMultipleSelection(*args, **kwargs):
+ """HasMultipleSelection(self) -> bool"""
+ return _windows_.VListBox_HasMultipleSelection(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> int"""
+ return _windows_.VListBox_GetSelection(*args, **kwargs)
+
+ def IsCurrent(*args, **kwargs):
+ """IsCurrent(self, size_t item) -> bool"""
+ return _windows_.VListBox_IsCurrent(*args, **kwargs)
+
+ def IsSelected(*args, **kwargs):
+ """IsSelected(self, size_t item) -> bool"""
+ return _windows_.VListBox_IsSelected(*args, **kwargs)
+
+ def GetSelectedCount(*args, **kwargs):
+ """GetSelectedCount(self) -> size_t"""
+ return _windows_.VListBox_GetSelectedCount(*args, **kwargs)
+
+ def GetFirstSelected(*args, **kwargs):
+ """GetFirstSelected(self) -> PyObject"""
+ return _windows_.VListBox_GetFirstSelected(*args, **kwargs)
+
+ def GetNextSelected(*args, **kwargs):
+ """GetNextSelected(self, unsigned long cookie) -> PyObject"""
+ return _windows_.VListBox_GetNextSelected(*args, **kwargs)
+
+ def GetMargins(*args, **kwargs):
+ """GetMargins(self) -> Point"""
+ return _windows_.VListBox_GetMargins(*args, **kwargs)
+
+ def GetSelectionBackground(*args, **kwargs):
+ """GetSelectionBackground(self) -> Colour"""
+ return _windows_.VListBox_GetSelectionBackground(*args, **kwargs)
+
+ def GetItemRect(*args, **kwargs):
+ """GetItemRect(self, size_t n) -> Rect"""
+ return _windows_.VListBox_GetItemRect(*args, **kwargs)
+
+ def SetItemCount(*args, **kwargs):
+ """SetItemCount(self, size_t count)"""
+ return _windows_.VListBox_SetItemCount(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """Clear(self)"""
+ return _windows_.VListBox_Clear(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """SetSelection(self, int selection)"""
+ return _windows_.VListBox_SetSelection(*args, **kwargs)
+
+ def Select(*args, **kwargs):
+ """Select(self, size_t item, bool select=True) -> bool"""
+ return _windows_.VListBox_Select(*args, **kwargs)
+
+ def SelectRange(*args, **kwargs):
+ """SelectRange(self, size_t from, size_t to) -> bool"""
+ return _windows_.VListBox_SelectRange(*args, **kwargs)
+
+ def Toggle(*args, **kwargs):
+ """Toggle(self, size_t item)"""
+ return _windows_.VListBox_Toggle(*args, **kwargs)
+
+ def SelectAll(*args, **kwargs):
+ """SelectAll(self) -> bool"""
+ return _windows_.VListBox_SelectAll(*args, **kwargs)
+
+ def DeselectAll(*args, **kwargs):
+ """DeselectAll(self) -> bool"""
+ return _windows_.VListBox_DeselectAll(*args, **kwargs)
+
+ def SetMargins(*args, **kwargs):
+ """SetMargins(self, Point pt)"""
+ return _windows_.VListBox_SetMargins(*args, **kwargs)
+
+ def SetMarginsXY(*args, **kwargs):
+ """SetMarginsXY(self, int x, int y)"""
+ return _windows_.VListBox_SetMarginsXY(*args, **kwargs)
+
+ def SetSelectionBackground(*args, **kwargs):
+ """SetSelectionBackground(self, Colour col)"""
+ return _windows_.VListBox_SetSelectionBackground(*args, **kwargs)
+
+ def RefreshSelected(*args, **kwargs):
+ """RefreshSelected(self)"""
+ return _windows_.VListBox_RefreshSelected(*args, **kwargs)
+
+ def OnDrawSeparator(*args, **kwargs):
+ """OnDrawSeparator(self, DC dc, Rect rect, size_t n)"""
+ return _windows_.VListBox_OnDrawSeparator(*args, **kwargs)
+
+ def OnDrawBackground(*args, **kwargs):
+ """OnDrawBackground(self, DC dc, Rect rect, size_t n)"""
+ return _windows_.VListBox_OnDrawBackground(*args, **kwargs)
+
+ FirstSelected = property(GetFirstSelected,doc="See `GetFirstSelected`")
+ ItemCount = property(GetItemCount,SetItemCount,doc="See `GetItemCount` and `SetItemCount`")
+ Margins = property(GetMargins,SetMargins,doc="See `GetMargins` and `SetMargins`")
+ SelectedCount = property(GetSelectedCount,doc="See `GetSelectedCount`")
+ Selection = property(GetSelection,SetSelection,doc="See `GetSelection` and `SetSelection`")
+ SelectionBackground = property(GetSelectionBackground,SetSelectionBackground,doc="See `GetSelectionBackground` and `SetSelectionBackground`")
+_windows_.VListBox_swigregister(VListBox)
+VListBoxNameStr = cvar.VListBoxNameStr
+
+def PreVListBox(*args, **kwargs):
+ """PreVListBox() -> VListBox"""
+ val = _windows_.new_PreVListBox(*args, **kwargs)
+ return val
+
+class HtmlListBox(VListBox):
+ """Proxy of C++ HtmlListBox class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=VListBoxNameStr) -> HtmlListBox
+ """
+ _windows_.HtmlListBox_swiginit(self,_windows_.new_HtmlListBox(*args, **kwargs))
+ self._setOORInfo(self);HtmlListBox._setCallbackInfo(self, self, HtmlListBox)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.HtmlListBox__setCallbackInfo(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=VListBoxNameStr) -> bool
+ """
+ return _windows_.HtmlListBox_Create(*args, **kwargs)
+
+ def SetItemCount(*args, **kwargs):
+ """SetItemCount(self, size_t count)"""
+ return _windows_.HtmlListBox_SetItemCount(*args, **kwargs)
+
+ def GetFileSystem(*args, **kwargs):
+ """GetFileSystem(self) -> FileSystem"""
+ return _windows_.HtmlListBox_GetFileSystem(*args, **kwargs)
+
+ def OnLinkClicked(*args, **kwargs):
+ """OnLinkClicked(self, size_t n, wxHtmlLinkInfo link)"""
+ return _windows_.HtmlListBox_OnLinkClicked(*args, **kwargs)
+
+ FileSystem = property(GetFileSystem,doc="See `GetFileSystem`")
+_windows_.HtmlListBox_swigregister(HtmlListBox)
+
+def PreHtmlListBox(*args, **kwargs):
+ """PreHtmlListBox() -> HtmlListBox"""
+ val = _windows_.new_PreHtmlListBox(*args, **kwargs)
+ return val
+
+HLB_DEFAULT_STYLE = _windows_.HLB_DEFAULT_STYLE
+HLB_MULTIPLE = _windows_.HLB_MULTIPLE
+class SimpleHtmlListBox(HtmlListBox,_core.ItemContainer):
+ """Proxy of C++ SimpleHtmlListBox class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, wxArrayString choices=wxPyEmptyStringArray,
+ long style=HLB_DEFAULT_STYLE,
+ Validator validator=DefaultValidator,
+ String name=SimpleHtmlListBoxNameStr) -> SimpleHtmlListBox
+ """
+ _windows_.SimpleHtmlListBox_swiginit(self,_windows_.new_SimpleHtmlListBox(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, wxArrayString choices=wxPyEmptyStringArray,
+ long style=HLB_DEFAULT_STYLE,
+ Validator validator=DefaultValidator,
+ String name=SimpleHtmlListBoxNameStr) -> bool
+ """
+ return _windows_.SimpleHtmlListBox_Create(*args, **kwargs)
+
+ def _Clear(*args, **kwargs):
+ """_Clear(self)"""
+ return _windows_.SimpleHtmlListBox__Clear(*args, **kwargs)
+
+ Clear = _Clear
+_windows_.SimpleHtmlListBox_swigregister(SimpleHtmlListBox)
+SimpleHtmlListBoxNameStr = cvar.SimpleHtmlListBoxNameStr
+
+def PreSimpleHtmlListBox(*args, **kwargs):
+ """PreSimpleHtmlListBox() -> SimpleHtmlListBox"""
+ val = _windows_.new_PreSimpleHtmlListBox(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+TBI_DOCK = _windows_.TBI_DOCK
+TBI_CUSTOM_STATUSITEM = _windows_.TBI_CUSTOM_STATUSITEM
+TBI_DEFAULT_TYPE = _windows_.TBI_DEFAULT_TYPE
+class TaskBarIcon(_core.EvtHandler):
+ """Proxy of C++ TaskBarIcon class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int iconType=TBI_DEFAULT_TYPE) -> TaskBarIcon"""
+ _windows_.TaskBarIcon_swiginit(self,_windows_.new_TaskBarIcon(*args, **kwargs))
+ self._setOORInfo(self);TaskBarIcon._setCallbackInfo(self, self, TaskBarIcon)
+
+ __swig_destroy__ = _windows_.delete_TaskBarIcon
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class, int incref=0)"""
+ return _windows_.TaskBarIcon__setCallbackInfo(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """
+ Destroy(self)
+
+ Deletes the C++ object this Python object is a proxy for.
+ """
+ args[0].this.own(False)
+ return _windows_.TaskBarIcon_Destroy(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _windows_.TaskBarIcon_IsOk(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def IsIconInstalled(*args, **kwargs):
+ """IsIconInstalled(self) -> bool"""
+ return _windows_.TaskBarIcon_IsIconInstalled(*args, **kwargs)
+
+ def SetIcon(*args, **kwargs):
+ """SetIcon(self, Icon icon, String tooltip=EmptyString) -> bool"""
+ return _windows_.TaskBarIcon_SetIcon(*args, **kwargs)
+
+ def RemoveIcon(*args, **kwargs):
+ """RemoveIcon(self) -> bool"""
+ return _windows_.TaskBarIcon_RemoveIcon(*args, **kwargs)
+
+ def PopupMenu(*args, **kwargs):
+ """PopupMenu(self, Menu menu) -> bool"""
+ return _windows_.TaskBarIcon_PopupMenu(*args, **kwargs)
+
+ def ShowBalloon(*args, **kwargs):
+ """
+ ShowBalloon(self, String title, String text, unsigned int msec=0, int flags=0) -> bool
+
+ Show a balloon notification (the icon must have been already
+ initialized using SetIcon). Only implemented for Windows.
+
+ title and text are limited to 63 and 255 characters respectively, msec
+ is the timeout, in milliseconds, before the balloon disappears (will
+ be clamped down to the allowed 10-30s range by Windows if it's outside
+ it) and flags can include wxICON_ERROR/INFO/WARNING to show a
+ corresponding icon
+
+ Returns True if balloon was shown, False on error (incorrect parameters
+ or function unsupported by OS)
+
+ """
+ return _windows_.TaskBarIcon_ShowBalloon(*args, **kwargs)
+
+ def IsAvailable(*args, **kwargs):
+ """IsAvailable() -> bool"""
+ return _windows_.TaskBarIcon_IsAvailable(*args, **kwargs)
+
+ IsAvailable = staticmethod(IsAvailable)
+_windows_.TaskBarIcon_swigregister(TaskBarIcon)
+
+def TaskBarIcon_IsAvailable(*args):
+ """TaskBarIcon_IsAvailable() -> bool"""
+ return _windows_.TaskBarIcon_IsAvailable(*args)
+
+class TaskBarIconEvent(_core.Event):
+ """Proxy of C++ TaskBarIconEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType evtType, wxTaskBarIcon tbIcon) -> TaskBarIconEvent"""
+ _windows_.TaskBarIconEvent_swiginit(self,_windows_.new_TaskBarIconEvent(*args, **kwargs))
+_windows_.TaskBarIconEvent_swigregister(TaskBarIconEvent)
+
+wxEVT_TASKBAR_MOVE = _windows_.wxEVT_TASKBAR_MOVE
+wxEVT_TASKBAR_LEFT_DOWN = _windows_.wxEVT_TASKBAR_LEFT_DOWN
+wxEVT_TASKBAR_LEFT_UP = _windows_.wxEVT_TASKBAR_LEFT_UP
+wxEVT_TASKBAR_RIGHT_DOWN = _windows_.wxEVT_TASKBAR_RIGHT_DOWN
+wxEVT_TASKBAR_RIGHT_UP = _windows_.wxEVT_TASKBAR_RIGHT_UP
+wxEVT_TASKBAR_LEFT_DCLICK = _windows_.wxEVT_TASKBAR_LEFT_DCLICK
+wxEVT_TASKBAR_RIGHT_DCLICK = _windows_.wxEVT_TASKBAR_RIGHT_DCLICK
+wxEVT_TASKBAR_CLICK = _windows_.wxEVT_TASKBAR_CLICK
+wxEVT_TASKBAR_BALLOON_TIMEOUT = _windows_.wxEVT_TASKBAR_BALLOON_TIMEOUT
+wxEVT_TASKBAR_BALLOON_CLICK = _windows_.wxEVT_TASKBAR_BALLOON_CLICK
+EVT_TASKBAR_MOVE = wx.PyEventBinder ( wxEVT_TASKBAR_MOVE )
+EVT_TASKBAR_LEFT_DOWN = wx.PyEventBinder ( wxEVT_TASKBAR_LEFT_DOWN )
+EVT_TASKBAR_LEFT_UP = wx.PyEventBinder ( wxEVT_TASKBAR_LEFT_UP )
+EVT_TASKBAR_RIGHT_DOWN = wx.PyEventBinder ( wxEVT_TASKBAR_RIGHT_DOWN )
+EVT_TASKBAR_RIGHT_UP = wx.PyEventBinder ( wxEVT_TASKBAR_RIGHT_UP )
+EVT_TASKBAR_LEFT_DCLICK = wx.PyEventBinder ( wxEVT_TASKBAR_LEFT_DCLICK )
+EVT_TASKBAR_RIGHT_DCLICK = wx.PyEventBinder ( wxEVT_TASKBAR_RIGHT_DCLICK )
+EVT_TASKBAR_CLICK = wx.PyEventBinder ( wxEVT_TASKBAR_CLICK )
+EVT_TASKBAR_BALLOON_TIMEOUT = wx.PyEventBinder ( wxEVT_TASKBAR_BALLOON_TIMEOUT )
+EVT_TASKBAR_BALLOON_CLICK = wx.PyEventBinder ( wxEVT_TASKBAR_BALLOON_CLICK )
+
+#---------------------------------------------------------------------------
+
+class ColourData(_core.Object):
+ """
+ This class holds a variety of information related to the colour
+ chooser dialog, used to transfer settings and results to and from the
+ `wx.ColourDialog`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ NUM_CUSTOM = _windows_.ColourData_NUM_CUSTOM
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> ColourData
+
+ Constructor, sets default values.
+ """
+ _windows_.ColourData_swiginit(self,_windows_.new_ColourData(*args, **kwargs))
+ __swig_destroy__ = _windows_.delete_ColourData
+ __del__ = lambda self : None;
+ def GetChooseFull(*args, **kwargs):
+ """
+ GetChooseFull(self) -> bool
+
+ Under Windows, determines whether the Windows colour dialog will
+ display the full dialog with custom colour selection controls. Has no
+ meaning under other platforms. The default value is true.
+ """
+ return _windows_.ColourData_GetChooseFull(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """
+ GetColour(self) -> Colour
+
+ Gets the colour (pre)selected by the dialog.
+ """
+ return _windows_.ColourData_GetColour(*args, **kwargs)
+
+ def GetCustomColour(*args, **kwargs):
+ """
+ GetCustomColour(self, int i) -> Colour
+
+ Gets the i'th custom colour associated with the colour dialog. i
+ should be an integer between 0 and 15. The default custom colours are
+ all invalid colours.
+ """
+ return _windows_.ColourData_GetCustomColour(*args, **kwargs)
+
+ def SetChooseFull(*args, **kwargs):
+ """
+ SetChooseFull(self, int flag)
+
+ Under Windows, tells the Windows colour dialog to display the full
+ dialog with custom colour selection controls. Under other platforms,
+ has no effect. The default value is true.
+ """
+ return _windows_.ColourData_SetChooseFull(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """
+ SetColour(self, Colour colour)
+
+ Sets the default colour for the colour dialog. The default colour is
+ black.
+ """
+ return _windows_.ColourData_SetColour(*args, **kwargs)
+
+ def SetCustomColour(*args, **kwargs):
+ """
+ SetCustomColour(self, int i, Colour colour)
+
+ Sets the i'th custom colour for the colour dialog. i should be an
+ integer between 0 and 15. The default custom colours are all invalid colours.
+ """
+ return _windows_.ColourData_SetCustomColour(*args, **kwargs)
+
+ def ToString(*args, **kwargs):
+ """
+ ToString(self) -> String
+
+ Serialize to a string.
+ """
+ return _windows_.ColourData_ToString(*args, **kwargs)
+
+ def FromString(*args, **kwargs):
+ """
+ FromString(self, String str) -> bool
+
+ Restore from a serialized string.
+ """
+ return _windows_.ColourData_FromString(*args, **kwargs)
+
+ ChooseFull = property(GetChooseFull,SetChooseFull,doc="See `GetChooseFull` and `SetChooseFull`")
+ Colour = property(GetColour,SetColour,doc="See `GetColour` and `SetColour`")
+ CustomColour = property(GetCustomColour,SetCustomColour,doc="See `GetCustomColour` and `SetCustomColour`")
+_windows_.ColourData_swigregister(ColourData)
+FileSelectorPromptStr = cvar.FileSelectorPromptStr
+DirSelectorPromptStr = cvar.DirSelectorPromptStr
+DirDialogNameStr = cvar.DirDialogNameStr
+FileSelectorDefaultWildcardStr = cvar.FileSelectorDefaultWildcardStr
+GetTextFromUserPromptStr = cvar.GetTextFromUserPromptStr
+MessageBoxCaptionStr = cvar.MessageBoxCaptionStr
+
+class ColourDialog(Dialog):
+ """This class represents the colour chooser dialog."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, ColourData data=None) -> ColourDialog
+
+ Constructor. Pass a parent window, and optionally a `wx.ColourData`,
+ which will be copied to the colour dialog's internal ColourData
+ instance.
+ """
+ _windows_.ColourDialog_swiginit(self,_windows_.new_ColourDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetColourData(*args, **kwargs):
+ """
+ GetColourData(self) -> ColourData
+
+ Returns a copy of the `wx.ColourData` used by the dialog.
+ """
+ return _windows_.ColourDialog_GetColourData(*args, **kwargs)
+
+ ColourData = property(GetColourData,doc="See `GetColourData`")
+_windows_.ColourDialog_swigregister(ColourDialog)
+
+
+def GetColourFromUser(*args, **kwargs):
+ """
+ GetColourFromUser(Window parent=(wxWindow *) NULL, Colour colInit=wxNullColour,
+ String caption=EmptyString, ColourData data=None) -> Colour
+ """
+ return _windows_.GetColourFromUser(*args, **kwargs)
+DD_CHANGE_DIR = _windows_.DD_CHANGE_DIR
+DD_DIR_MUST_EXIST = _windows_.DD_DIR_MUST_EXIST
+DD_NEW_DIR_BUTTON = _windows_.DD_NEW_DIR_BUTTON
+DD_DEFAULT_STYLE = _windows_.DD_DEFAULT_STYLE
+class DirDialog(Dialog):
+ """
+ wx.DirDialog allows the user to select a directory by browising the
+ file system.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, String message=DirSelectorPromptStr,
+ String defaultPath=EmptyString, long style=DD_DEFAULT_STYLE,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ String name=DirDialogNameStr) -> DirDialog
+
+ Constructor. Use ShowModal method to show the dialog.
+ """
+ _windows_.DirDialog_swiginit(self,_windows_.new_DirDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetPath(*args, **kwargs):
+ """
+ GetPath(self) -> String
+
+ Returns the default or user-selected path.
+ """
+ return _windows_.DirDialog_GetPath(*args, **kwargs)
+
+ def GetMessage(*args, **kwargs):
+ """
+ GetMessage(self) -> String
+
+ Returns the message that will be displayed on the dialog.
+ """
+ return _windows_.DirDialog_GetMessage(*args, **kwargs)
+
+ def SetMessage(*args, **kwargs):
+ """
+ SetMessage(self, String message)
+
+ Sets the message that will be displayed on the dialog.
+ """
+ return _windows_.DirDialog_SetMessage(*args, **kwargs)
+
+ def SetPath(*args, **kwargs):
+ """
+ SetPath(self, String path)
+
+ Sets the default path.
+ """
+ return _windows_.DirDialog_SetPath(*args, **kwargs)
+
+ Message = property(GetMessage,SetMessage,doc="See `GetMessage` and `SetMessage`")
+ Path = property(GetPath,SetPath,doc="See `GetPath` and `SetPath`")
+_windows_.DirDialog_swigregister(DirDialog)
+
+FD_OPEN = _windows_.FD_OPEN
+FD_SAVE = _windows_.FD_SAVE
+FD_OVERWRITE_PROMPT = _windows_.FD_OVERWRITE_PROMPT
+FD_FILE_MUST_EXIST = _windows_.FD_FILE_MUST_EXIST
+FD_MULTIPLE = _windows_.FD_MULTIPLE
+FD_CHANGE_DIR = _windows_.FD_CHANGE_DIR
+FD_PREVIEW = _windows_.FD_PREVIEW
+FD_DEFAULT_STYLE = _windows_.FD_DEFAULT_STYLE
+# deprecated names
+OPEN = FD_OPEN
+SAVE = FD_SAVE
+OVERWRITE_PROMPT = FD_OVERWRITE_PROMPT
+FILE_MUST_EXIST = FD_FILE_MUST_EXIST
+MULTIPLE = FD_MULTIPLE
+CHANGE_DIR = FD_CHANGE_DIR
+
+class FileDialog(Dialog):
+ """
+ wx.FileDialog allows the user to select one or more files from the
+ filesystem.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, String message=FileSelectorPromptStr,
+ String defaultDir=EmptyString, String defaultFile=EmptyString,
+ String wildcard=FileSelectorDefaultWildcardStr,
+ long style=FD_DEFAULT_STYLE,
+ Point pos=DefaultPosition, Size size=DefaultSize) -> FileDialog
+
+ Constructor. Use ShowModal method to show the dialog.
+ """
+ _windows_.FileDialog_swiginit(self,_windows_.new_FileDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def SetMessage(*args, **kwargs):
+ """
+ SetMessage(self, String message)
+
+ Sets the message that will be displayed on the dialog.
+ """
+ return _windows_.FileDialog_SetMessage(*args, **kwargs)
+
+ def SetPath(*args, **kwargs):
+ """
+ SetPath(self, String path)
+
+ Sets the path (the combined directory and filename that will be
+ returned when the dialog is dismissed).
+ """
+ return _windows_.FileDialog_SetPath(*args, **kwargs)
+
+ def SetDirectory(*args, **kwargs):
+ """
+ SetDirectory(self, String dir)
+
+ Sets the default directory.
+ """
+ return _windows_.FileDialog_SetDirectory(*args, **kwargs)
+
+ def SetFilename(*args, **kwargs):
+ """
+ SetFilename(self, String name)
+
+ Sets the default filename.
+ """
+ return _windows_.FileDialog_SetFilename(*args, **kwargs)
+
+ def SetWildcard(*args, **kwargs):
+ """
+ SetWildcard(self, String wildCard)
+
+ Sets the wildcard, which can contain multiple file types, for
+ example::
+
+ "BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif"
+
+ """
+ return _windows_.FileDialog_SetWildcard(*args, **kwargs)
+
+ def SetFilterIndex(*args, **kwargs):
+ """
+ SetFilterIndex(self, int filterIndex)
+
+ Sets the default filter index, starting from zero.
+ """
+ return _windows_.FileDialog_SetFilterIndex(*args, **kwargs)
+
+ def GetMessage(*args, **kwargs):
+ """
+ GetMessage(self) -> String
+
+ Returns the message that will be displayed on the dialog.
+ """
+ return _windows_.FileDialog_GetMessage(*args, **kwargs)
+
+ def GetPath(*args, **kwargs):
+ """
+ GetPath(self) -> String
+
+ Returns the full path (directory and filename) of the selected file.
+ """
+ return _windows_.FileDialog_GetPath(*args, **kwargs)
+
+ def GetDirectory(*args, **kwargs):
+ """
+ GetDirectory(self) -> String
+
+ Returns the default directory.
+ """
+ return _windows_.FileDialog_GetDirectory(*args, **kwargs)
+
+ def GetFilename(*args, **kwargs):
+ """
+ GetFilename(self) -> String
+
+ Returns the default filename.
+ """
+ return _windows_.FileDialog_GetFilename(*args, **kwargs)
+
+ def GetWildcard(*args, **kwargs):
+ """
+ GetWildcard(self) -> String
+
+ Returns the file dialog wildcard.
+ """
+ return _windows_.FileDialog_GetWildcard(*args, **kwargs)
+
+ def GetFilterIndex(*args, **kwargs):
+ """
+ GetFilterIndex(self) -> int
+
+ Returns the index into the list of filters supplied, optionally, in
+ the wildcard parameter. Before the dialog is shown, this is the index
+ which will be used when the dialog is first displayed. After the
+ dialog is shown, this is the index selected by the user.
+ """
+ return _windows_.FileDialog_GetFilterIndex(*args, **kwargs)
+
+ def GetFilenames(*args, **kwargs):
+ """
+ GetFilenames(self) -> PyObject
+
+ Returns a list of filenames chosen in the dialog. This function
+ should only be used with the dialogs which have wx.MULTIPLE style, use
+ GetFilename for the others.
+ """
+ return _windows_.FileDialog_GetFilenames(*args, **kwargs)
+
+ def GetPaths(*args, **kwargs):
+ """
+ GetPaths(self) -> PyObject
+
+ Fills the array paths with the full paths of the files chosen. This
+ function should only be used with the dialogs which have wx.MULTIPLE
+ style, use GetPath for the others.
+ """
+ return _windows_.FileDialog_GetPaths(*args, **kwargs)
+
+ Directory = property(GetDirectory,SetDirectory,doc="See `GetDirectory` and `SetDirectory`")
+ Filename = property(GetFilename,SetFilename,doc="See `GetFilename` and `SetFilename`")
+ Filenames = property(GetFilenames,doc="See `GetFilenames`")
+ FilterIndex = property(GetFilterIndex,SetFilterIndex,doc="See `GetFilterIndex` and `SetFilterIndex`")
+ Message = property(GetMessage,SetMessage,doc="See `GetMessage` and `SetMessage`")
+ Path = property(GetPath,SetPath,doc="See `GetPath` and `SetPath`")
+ Paths = property(GetPaths,doc="See `GetPaths`")
+ Wildcard = property(GetWildcard,SetWildcard,doc="See `GetWildcard` and `SetWildcard`")
+_windows_.FileDialog_swigregister(FileDialog)
+
+CHOICEDLG_STYLE = _windows_.CHOICEDLG_STYLE
+class MultiChoiceDialog(Dialog):
+ """A simple dialog with a multi selection listbox."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, String message, String caption,
+ List choices=EmptyList, long style=CHOICEDLG_STYLE,
+ Point pos=DefaultPosition) -> MultiChoiceDialog
+
+ Constructor. Use the `ShowModal` method to show the dialog.
+
+ :param parent: The parent window.
+ :param message: Text to display above the list of selections.
+ :param caption: Text to use in the title bar of the dialog.
+ :param choices: A list of strings or unicode objects that the
+ user is allowed to choose from.
+ :param style: Styles to apply to the dialog. The default value is
+ equivallent to wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.OK|wx.CANCEL|wx.CENTER.
+ :param pos: Where to position the dialog (not used on Windows)
+
+
+ """
+ _windows_.MultiChoiceDialog_swiginit(self,_windows_.new_MultiChoiceDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def SetSelections(*args, **kwargs):
+ """
+ SetSelections(List selections)
+
+ Specify the items in the list that should be selected, using a list of
+ integers. The list should specify the indexes of the items that
+ should be selected.
+ """
+ return _windows_.MultiChoiceDialog_SetSelections(*args, **kwargs)
+
+ def GetSelections(*args, **kwargs):
+ """
+ GetSelections() -> [selections]
+
+ Returns a list of integers representing the items that are selected.
+ If an item is selected then its index will appear in the list.
+ """
+ return _windows_.MultiChoiceDialog_GetSelections(*args, **kwargs)
+
+ Selections = property(GetSelections,SetSelections,doc="See `GetSelections` and `SetSelections`")
+_windows_.MultiChoiceDialog_swigregister(MultiChoiceDialog)
+
+class SingleChoiceDialog(Dialog):
+ """A simple dialog with a single selection listbox."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(Window parent, String message, String caption,
+ List choices=EmptyList, long style=CHOICEDLG_STYLE,
+ Point pos=DefaultPosition) -> SingleChoiceDialog
+
+ Constructor. Use ShowModal method to show the dialog.
+ """
+ _windows_.SingleChoiceDialog_swiginit(self,_windows_.new_SingleChoiceDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetSelection(*args, **kwargs):
+ """
+ GetSelection(self) -> int
+
+ Get the index of the currently selected item.
+ """
+ return _windows_.SingleChoiceDialog_GetSelection(*args, **kwargs)
+
+ def GetStringSelection(*args, **kwargs):
+ """
+ GetStringSelection(self) -> String
+
+ Returns the string value of the currently selected item
+ """
+ return _windows_.SingleChoiceDialog_GetStringSelection(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """
+ SetSelection(self, int sel)
+
+ Set the current selected item to sel
+ """
+ return _windows_.SingleChoiceDialog_SetSelection(*args, **kwargs)
+
+ Selection = property(GetSelection,SetSelection,doc="See `GetSelection` and `SetSelection`")
+ StringSelection = property(GetStringSelection,doc="See `GetStringSelection`")
+_windows_.SingleChoiceDialog_swigregister(SingleChoiceDialog)
+
+TextEntryDialogStyle = _windows_.TextEntryDialogStyle
+class TextEntryDialog(Dialog):
+ """A dialog with text control, [ok] and [cancel] buttons"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, String message, String caption=GetTextFromUserPromptStr,
+ String defaultValue=EmptyString,
+ long style=TextEntryDialogStyle, Point pos=DefaultPosition) -> TextEntryDialog
+
+ Constructor. Use ShowModal method to show the dialog.
+ """
+ _windows_.TextEntryDialog_swiginit(self,_windows_.new_TextEntryDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetValue(*args, **kwargs):
+ """
+ GetValue(self) -> String
+
+ Returns the text that the user has entered if the user has pressed OK,
+ or the original value if the user has pressed Cancel.
+ """
+ return _windows_.TextEntryDialog_GetValue(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """
+ SetValue(self, String value)
+
+ Sets the default text value.
+ """
+ return _windows_.TextEntryDialog_SetValue(*args, **kwargs)
+
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_windows_.TextEntryDialog_swigregister(TextEntryDialog)
+
+class PasswordEntryDialog(TextEntryDialog):
+ """Proxy of C++ PasswordEntryDialog class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, String message, String caption=GetPasswordFromUserPromptStr,
+ String value=EmptyString,
+ long style=TextEntryDialogStyle, Point pos=DefaultPosition) -> PasswordEntryDialog
+ """
+ _windows_.PasswordEntryDialog_swiginit(self,_windows_.new_PasswordEntryDialog(*args, **kwargs))
+_windows_.PasswordEntryDialog_swigregister(PasswordEntryDialog)
+GetPasswordFromUserPromptStr = cvar.GetPasswordFromUserPromptStr
+
+class NumberEntryDialog(Dialog):
+ """A dialog with spin control, ok and cancel buttons."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, String message, String prompt, String caption,
+ long value, long min, long max, Point pos=DefaultPosition) -> NumberEntryDialog
+
+ Constructor. Use ShowModal method to show the dialog.
+ """
+ _windows_.NumberEntryDialog_swiginit(self,_windows_.new_NumberEntryDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> long"""
+ return _windows_.NumberEntryDialog_GetValue(*args, **kwargs)
+
+ Value = property(GetValue,doc="See `GetValue`")
+_windows_.NumberEntryDialog_swigregister(NumberEntryDialog)
+
+class FontData(_core.Object):
+ """
+ This class holds a variety of information related to font dialogs and
+ is used to transfer settings to and results from a `wx.FontDialog`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> FontData
+
+ This class holds a variety of information related to font dialogs and
+ is used to transfer settings to and results from a `wx.FontDialog`.
+ """
+ _windows_.FontData_swiginit(self,_windows_.new_FontData(*args, **kwargs))
+ __swig_destroy__ = _windows_.delete_FontData
+ __del__ = lambda self : None;
+ def EnableEffects(*args, **kwargs):
+ """
+ EnableEffects(self, bool enable)
+
+ Enables or disables 'effects' under MS Windows only. This refers to
+ the controls for manipulating colour, strikeout and underline
+ properties. The default value is true.
+ """
+ return _windows_.FontData_EnableEffects(*args, **kwargs)
+
+ def GetAllowSymbols(*args, **kwargs):
+ """
+ GetAllowSymbols(self) -> bool
+
+ Under MS Windows, returns a flag determining whether symbol fonts can
+ be selected. Has no effect on other platforms. The default value is
+ true.
+ """
+ return _windows_.FontData_GetAllowSymbols(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """
+ GetColour(self) -> Colour
+
+ Gets the colour associated with the font dialog. The default value is
+ black.
+ """
+ return _windows_.FontData_GetColour(*args, **kwargs)
+
+ def GetChosenFont(*args, **kwargs):
+ """
+ GetChosenFont(self) -> Font
+
+ Gets the font chosen by the user.
+ """
+ return _windows_.FontData_GetChosenFont(*args, **kwargs)
+
+ def GetEnableEffects(*args, **kwargs):
+ """
+ GetEnableEffects(self) -> bool
+
+ Determines whether 'effects' are enabled under Windows.
+ """
+ return _windows_.FontData_GetEnableEffects(*args, **kwargs)
+
+ def GetInitialFont(*args, **kwargs):
+ """
+ GetInitialFont(self) -> Font
+
+ Gets the font that will be initially used by the font dialog. This
+ should have previously been set by the application.
+ """
+ return _windows_.FontData_GetInitialFont(*args, **kwargs)
+
+ def GetShowHelp(*args, **kwargs):
+ """
+ GetShowHelp(self) -> bool
+
+ Returns true if the Help button will be shown (Windows only). The
+ default value is false.
+ """
+ return _windows_.FontData_GetShowHelp(*args, **kwargs)
+
+ def SetAllowSymbols(*args, **kwargs):
+ """
+ SetAllowSymbols(self, bool allowSymbols)
+
+ Under MS Windows, determines whether symbol fonts can be selected. Has
+ no effect on other platforms. The default value is true.
+ """
+ return _windows_.FontData_SetAllowSymbols(*args, **kwargs)
+
+ def SetChosenFont(*args, **kwargs):
+ """
+ SetChosenFont(self, Font font)
+
+ Sets the font that will be returned to the user (normally for internal
+ use only).
+ """
+ return _windows_.FontData_SetChosenFont(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """
+ SetColour(self, Colour colour)
+
+ Sets the colour that will be used for the font foreground colour. The
+ default colour is black.
+ """
+ return _windows_.FontData_SetColour(*args, **kwargs)
+
+ def SetInitialFont(*args, **kwargs):
+ """
+ SetInitialFont(self, Font font)
+
+ Sets the font that will be initially used by the font dialog.
+ """
+ return _windows_.FontData_SetInitialFont(*args, **kwargs)
+
+ def SetRange(*args, **kwargs):
+ """
+ SetRange(self, int min, int max)
+
+ Sets the valid range for the font point size (Windows only). The
+ default is 0, 0 (unrestricted range).
+ """
+ return _windows_.FontData_SetRange(*args, **kwargs)
+
+ def SetShowHelp(*args, **kwargs):
+ """
+ SetShowHelp(self, bool showHelp)
+
+ Determines whether the Help button will be displayed in the font
+ dialog (Windows only). The default value is false.
+ """
+ return _windows_.FontData_SetShowHelp(*args, **kwargs)
+
+ AllowSymbols = property(GetAllowSymbols,SetAllowSymbols,doc="See `GetAllowSymbols` and `SetAllowSymbols`")
+ ChosenFont = property(GetChosenFont,SetChosenFont,doc="See `GetChosenFont` and `SetChosenFont`")
+ Colour = property(GetColour,SetColour,doc="See `GetColour` and `SetColour`")
+ InitialFont = property(GetInitialFont,SetInitialFont,doc="See `GetInitialFont` and `SetInitialFont`")
+ ShowHelp = property(GetShowHelp,SetShowHelp,doc="See `GetShowHelp` and `SetShowHelp`")
+_windows_.FontData_swigregister(FontData)
+
+class FontDialog(Dialog):
+ """
+ wx.FontDialog allows the user to select a system font and its attributes.
+
+ :see: `wx.FontData`
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, FontData data) -> FontDialog
+
+ Constructor. Pass a parent window and the `wx.FontData` object to be
+ used to initialize the dialog controls. Call `ShowModal` to display
+ the dialog. If ShowModal returns ``wx.ID_OK`` then you can fetch the
+ results with via the `wx.FontData` returned by `GetFontData`.
+ """
+ _windows_.FontDialog_swiginit(self,_windows_.new_FontDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetFontData(*args, **kwargs):
+ """
+ GetFontData(self) -> FontData
+
+ Returns a reference to the internal `wx.FontData` used by the
+ wx.FontDialog.
+ """
+ return _windows_.FontDialog_GetFontData(*args, **kwargs)
+
+ FontData = property(GetFontData,doc="See `GetFontData`")
+_windows_.FontDialog_swigregister(FontDialog)
+
+
+def GetFontFromUser(*args, **kwargs):
+ """GetFontFromUser(Window parent=None, Font fontInit=wxNullFont, String caption=EmptyString) -> Font"""
+ return _windows_.GetFontFromUser(*args, **kwargs)
+class MessageDialog(Dialog):
+ """
+ This class provides a simple dialog that shows a single or multi-line
+ message, with a choice of OK, Yes, No and/or Cancel buttons.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, String message, String caption=MessageBoxCaptionStr,
+ long style=wxOK|wxCANCEL|wxCENTRE,
+ Point pos=DefaultPosition) -> MessageDialog
+
+ Constructor, use `ShowModal` to display the dialog.
+ """
+ _windows_.MessageDialog_swiginit(self,_windows_.new_MessageDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def SetYesNoLabels(*args, **kwargs):
+ """SetYesNoLabels(self, String yes, String no) -> bool"""
+ return _windows_.MessageDialog_SetYesNoLabels(*args, **kwargs)
+
+ def SetYesNoCancelLabels(*args, **kwargs):
+ """SetYesNoCancelLabels(self, String yes, String no, String cancel) -> bool"""
+ return _windows_.MessageDialog_SetYesNoCancelLabels(*args, **kwargs)
+
+ def SetOKLabel(*args, **kwargs):
+ """SetOKLabel(self, String ok) -> bool"""
+ return _windows_.MessageDialog_SetOKLabel(*args, **kwargs)
+
+ def SetOKCancelLabels(*args, **kwargs):
+ """SetOKCancelLabels(self, String ok, String cancel) -> bool"""
+ return _windows_.MessageDialog_SetOKCancelLabels(*args, **kwargs)
+
+ def SetHelpLabel(*args, **kwargs):
+ """SetHelpLabel(self, String help) -> bool"""
+ return _windows_.MessageDialog_SetHelpLabel(*args, **kwargs)
+
+ def GetHelpLabel(*args, **kwargs):
+ """GetHelpLabel(self) -> String"""
+ return _windows_.MessageDialog_GetHelpLabel(*args, **kwargs)
+
+ def SetMessage(*args, **kwargs):
+ """SetMessage(self, String message)"""
+ return _windows_.MessageDialog_SetMessage(*args, **kwargs)
+
+ def SetExtendedMessage(*args, **kwargs):
+ """SetExtendedMessage(self, String extendedMessage)"""
+ return _windows_.MessageDialog_SetExtendedMessage(*args, **kwargs)
+
+_windows_.MessageDialog_swigregister(MessageDialog)
+
+PD_CAN_ABORT = _windows_.PD_CAN_ABORT
+PD_APP_MODAL = _windows_.PD_APP_MODAL
+PD_AUTO_HIDE = _windows_.PD_AUTO_HIDE
+PD_ELAPSED_TIME = _windows_.PD_ELAPSED_TIME
+PD_ESTIMATED_TIME = _windows_.PD_ESTIMATED_TIME
+PD_SMOOTH = _windows_.PD_SMOOTH
+PD_REMAINING_TIME = _windows_.PD_REMAINING_TIME
+PD_CAN_SKIP = _windows_.PD_CAN_SKIP
+class GenericProgressDialog(Dialog):
+ """
+ A dialog that shows a short message and a progress bar. Optionally, it
+ can display an ABORT button.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String title, String message, int maximum=100, Window parent=None,
+ int style=wxPD_AUTO_HIDE|wxPD_APP_MODAL) -> GenericProgressDialog
+
+ Constructor. Creates the dialog, displays it and disables user input
+ for other windows, or, if wx.PD_APP_MODAL flag is not given, for its
+ parent window only.
+ """
+ _windows_.GenericProgressDialog_swiginit(self,_windows_.new_GenericProgressDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Update(*args, **kwargs):
+ """
+ Update(self, int value, String newmsg) --> (continue, skip)
+
+ Updates the dialog, setting the progress bar to the new value and, if
+ given changes the message above it. The value given should be less
+ than or equal to the maximum value given to the constructor and the
+ dialog is closed if it is equal to the maximum. Returns a tuple of
+ boolean values, ``(continue, skip)`` where ``continue`` is ``True``
+ unless the Cancel button has been pressed, and ``skip`` is ``False``
+ unless the Skip button (if any) has been pressed.
+
+ If the ``continue`` return value is ``False``, the application can either
+ immediately destroy the dialog or ask the user for confirmation, and if the
+ abort is not confirmed the dialog may be resumed with `Resume` function.
+
+ """
+ return _windows_.GenericProgressDialog_Update(*args, **kwargs)
+
+ def Pulse(*args, **kwargs):
+ """
+ Pulse(self, String newmsg) --> (continue, skip)
+
+ Just like `Update` but switches the dialog to use a gauge in
+ indeterminate mode and calls `wx.Gauge.Pulse` to show the user a bit of
+ progress.
+ """
+ return _windows_.GenericProgressDialog_Pulse(*args, **kwargs)
+
+ UpdatePulse = Pulse
+ def Resume(*args, **kwargs):
+ """
+ Resume(self)
+
+ Can be used to continue with the dialog, after the user had chosen to
+ abort.
+ """
+ return _windows_.GenericProgressDialog_Resume(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> int"""
+ return _windows_.GenericProgressDialog_GetValue(*args, **kwargs)
+
+ def GetRange(*args, **kwargs):
+ """GetRange(self) -> int"""
+ return _windows_.GenericProgressDialog_GetRange(*args, **kwargs)
+
+ def SetRange(*args, **kwargs):
+ """SetRange(self, int maximum)"""
+ return _windows_.GenericProgressDialog_SetRange(*args, **kwargs)
+
+ def GetMessage(*args, **kwargs):
+ """GetMessage(self) -> String"""
+ return _windows_.GenericProgressDialog_GetMessage(*args, **kwargs)
+
+ def WasCancelled(*args, **kwargs):
+ """WasCancelled(self) -> bool"""
+ return _windows_.GenericProgressDialog_WasCancelled(*args, **kwargs)
+
+ def WasSkipped(*args, **kwargs):
+ """WasSkipped(self) -> bool"""
+ return _windows_.GenericProgressDialog_WasSkipped(*args, **kwargs)
+
+ Value = property(GetValue)
+ Range = property(GetRange,SetRange)
+ Message = property(GetMessage)
+_windows_.GenericProgressDialog_swigregister(GenericProgressDialog)
+
+class ProgressDialog(GenericProgressDialog):
+ """Proxy of C++ ProgressDialog class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String title, String message, int maximum=100, Window parent=None,
+ int style=wxPD_APP_MODAL|wxPD_AUTO_HIDE) -> ProgressDialog
+ """
+ _windows_.ProgressDialog_swiginit(self,_windows_.new_ProgressDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+_windows_.ProgressDialog_swigregister(ProgressDialog)
+
+FR_DOWN = _windows_.FR_DOWN
+FR_WHOLEWORD = _windows_.FR_WHOLEWORD
+FR_MATCHCASE = _windows_.FR_MATCHCASE
+FR_REPLACEDIALOG = _windows_.FR_REPLACEDIALOG
+FR_NOUPDOWN = _windows_.FR_NOUPDOWN
+FR_NOMATCHCASE = _windows_.FR_NOMATCHCASE
+FR_NOWHOLEWORD = _windows_.FR_NOWHOLEWORD
+wxEVT_COMMAND_FIND = _windows_.wxEVT_COMMAND_FIND
+wxEVT_COMMAND_FIND_NEXT = _windows_.wxEVT_COMMAND_FIND_NEXT
+wxEVT_COMMAND_FIND_REPLACE = _windows_.wxEVT_COMMAND_FIND_REPLACE
+wxEVT_COMMAND_FIND_REPLACE_ALL = _windows_.wxEVT_COMMAND_FIND_REPLACE_ALL
+wxEVT_COMMAND_FIND_CLOSE = _windows_.wxEVT_COMMAND_FIND_CLOSE
+EVT_FIND = wx.PyEventBinder( wxEVT_COMMAND_FIND, 1 )
+EVT_FIND_NEXT = wx.PyEventBinder( wxEVT_COMMAND_FIND_NEXT, 1 )
+EVT_FIND_REPLACE = wx.PyEventBinder( wxEVT_COMMAND_FIND_REPLACE, 1 )
+EVT_FIND_REPLACE_ALL = wx.PyEventBinder( wxEVT_COMMAND_FIND_REPLACE_ALL, 1 )
+EVT_FIND_CLOSE = wx.PyEventBinder( wxEVT_COMMAND_FIND_CLOSE, 1 )
+
+# For backwards compatibility. Should they be removed?
+EVT_COMMAND_FIND = EVT_FIND
+EVT_COMMAND_FIND_NEXT = EVT_FIND_NEXT
+EVT_COMMAND_FIND_REPLACE = EVT_FIND_REPLACE
+EVT_COMMAND_FIND_REPLACE_ALL = EVT_FIND_REPLACE_ALL
+EVT_COMMAND_FIND_CLOSE = EVT_FIND_CLOSE
+
+class FindDialogEvent(_core.CommandEvent):
+ """Events for the FindReplaceDialog"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType commandType=wxEVT_NULL, int id=0) -> FindDialogEvent
+
+ Events for the FindReplaceDialog
+ """
+ _windows_.FindDialogEvent_swiginit(self,_windows_.new_FindDialogEvent(*args, **kwargs))
+ def GetFlags(*args, **kwargs):
+ """
+ GetFlags(self) -> int
+
+ Get the currently selected flags: this is the combination of
+ wx.FR_DOWN, wx.FR_WHOLEWORD and wx.FR_MATCHCASE flags.
+ """
+ return _windows_.FindDialogEvent_GetFlags(*args, **kwargs)
+
+ def GetFindString(*args, **kwargs):
+ """
+ GetFindString(self) -> String
+
+ Return the string to find (never empty).
+ """
+ return _windows_.FindDialogEvent_GetFindString(*args, **kwargs)
+
+ def GetReplaceString(*args, **kwargs):
+ """
+ GetReplaceString(self) -> String
+
+ Return the string to replace the search string with (only for replace
+ and replace all events).
+ """
+ return _windows_.FindDialogEvent_GetReplaceString(*args, **kwargs)
+
+ def GetDialog(*args, **kwargs):
+ """
+ GetDialog(self) -> FindReplaceDialog
+
+ Return the pointer to the dialog which generated this event.
+ """
+ return _windows_.FindDialogEvent_GetDialog(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _windows_.FindDialogEvent_SetFlags(*args, **kwargs)
+
+ def SetFindString(*args, **kwargs):
+ """SetFindString(self, String str)"""
+ return _windows_.FindDialogEvent_SetFindString(*args, **kwargs)
+
+ def SetReplaceString(*args, **kwargs):
+ """SetReplaceString(self, String str)"""
+ return _windows_.FindDialogEvent_SetReplaceString(*args, **kwargs)
+
+ Dialog = property(GetDialog,doc="See `GetDialog`")
+ FindString = property(GetFindString,SetFindString,doc="See `GetFindString` and `SetFindString`")
+ Flags = property(GetFlags,SetFlags,doc="See `GetFlags` and `SetFlags`")
+ ReplaceString = property(GetReplaceString,SetReplaceString,doc="See `GetReplaceString` and `SetReplaceString`")
+_windows_.FindDialogEvent_swigregister(FindDialogEvent)
+
+class FindReplaceData(_core.Object):
+ """
+ wx.FindReplaceData holds the data for wx.FindReplaceDialog. It is used
+ to initialize the dialog with the default values and will keep the
+ last values from the dialog when it is closed. It is also updated each
+ time a `wx.FindDialogEvent` is generated so instead of using the
+ `wx.FindDialogEvent` methods you can also directly query this object.
+
+ Note that all SetXXX() methods may only be called before showing the
+ dialog and calling them has no effect later.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int flags=0) -> FindReplaceData
+
+ Constuctor initializes the flags to default value (0).
+ """
+ _windows_.FindReplaceData_swiginit(self,_windows_.new_FindReplaceData(*args, **kwargs))
+ __swig_destroy__ = _windows_.delete_FindReplaceData
+ __del__ = lambda self : None;
+ def GetFindString(*args, **kwargs):
+ """
+ GetFindString(self) -> String
+
+ Get the string to find.
+ """
+ return _windows_.FindReplaceData_GetFindString(*args, **kwargs)
+
+ def GetReplaceString(*args, **kwargs):
+ """
+ GetReplaceString(self) -> String
+
+ Get the replacement string.
+ """
+ return _windows_.FindReplaceData_GetReplaceString(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """
+ GetFlags(self) -> int
+
+ Get the combination of flag values.
+ """
+ return _windows_.FindReplaceData_GetFlags(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """
+ SetFlags(self, int flags)
+
+ Set the flags to use to initialize the controls of the dialog.
+ """
+ return _windows_.FindReplaceData_SetFlags(*args, **kwargs)
+
+ def SetFindString(*args, **kwargs):
+ """
+ SetFindString(self, String str)
+
+ Set the string to find (used as initial value by the dialog).
+ """
+ return _windows_.FindReplaceData_SetFindString(*args, **kwargs)
+
+ def SetReplaceString(*args, **kwargs):
+ """
+ SetReplaceString(self, String str)
+
+ Set the replacement string (used as initial value by the dialog).
+ """
+ return _windows_.FindReplaceData_SetReplaceString(*args, **kwargs)
+
+ FindString = property(GetFindString,SetFindString,doc="See `GetFindString` and `SetFindString`")
+ Flags = property(GetFlags,SetFlags,doc="See `GetFlags` and `SetFlags`")
+ ReplaceString = property(GetReplaceString,SetReplaceString,doc="See `GetReplaceString` and `SetReplaceString`")
+_windows_.FindReplaceData_swigregister(FindReplaceData)
+
+class FindReplaceDialog(Dialog):
+ """
+ wx.FindReplaceDialog is a standard modeless dialog which is used to
+ allow the user to search for some text (and possibly replace it with
+ something else). The actual searching is supposed to be done in the
+ owner window which is the parent of this dialog. Note that it means
+ that unlike for the other standard dialogs this one must have a parent
+ window. Also note that there is no way to use this dialog in a modal
+ way; it is always, by design and implementation, modeless.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, FindReplaceData data, String title,
+ int style=0) -> FindReplaceDialog
+
+ Create a FindReplaceDialog. The parent and data parameters must be
+ non-None. Use Show to display the dialog.
+ """
+ _windows_.FindReplaceDialog_swiginit(self,_windows_.new_FindReplaceDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, FindReplaceData data, String title,
+ int style=0) -> bool
+
+ Create the dialog, for 2-phase create.
+ """
+ return _windows_.FindReplaceDialog_Create(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """
+ GetData(self) -> FindReplaceData
+
+ Get the FindReplaceData object used by this dialog.
+ """
+ return _windows_.FindReplaceDialog_GetData(*args, **kwargs)
+
+ def SetData(*args, **kwargs):
+ """
+ SetData(self, FindReplaceData data)
+
+ Set the FindReplaceData object used by this dialog.
+ """
+ return _windows_.FindReplaceDialog_SetData(*args, **kwargs)
+
+ Data = property(GetData,SetData,doc="See `GetData` and `SetData`")
+_windows_.FindReplaceDialog_swigregister(FindReplaceDialog)
+
+def PreFindReplaceDialog(*args, **kwargs):
+ """
+ PreFindReplaceDialog() -> FindReplaceDialog
+
+ Precreate a FindReplaceDialog for 2-phase creation
+ """
+ val = _windows_.new_PreFindReplaceDialog(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+IDM_WINDOWTILE = _windows_.IDM_WINDOWTILE
+IDM_WINDOWTILEHOR = _windows_.IDM_WINDOWTILEHOR
+IDM_WINDOWCASCADE = _windows_.IDM_WINDOWCASCADE
+IDM_WINDOWICONS = _windows_.IDM_WINDOWICONS
+IDM_WINDOWNEXT = _windows_.IDM_WINDOWNEXT
+IDM_WINDOWTILEVERT = _windows_.IDM_WINDOWTILEVERT
+IDM_WINDOWPREV = _windows_.IDM_WINDOWPREV
+FIRST_MDI_CHILD = _windows_.FIRST_MDI_CHILD
+LAST_MDI_CHILD = _windows_.LAST_MDI_CHILD
+class MDIParentFrame(Frame):
+ """Proxy of C++ MDIParentFrame class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String title=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxDEFAULT_FRAME_STYLE|wxVSCROLL|wxHSCROLL,
+ String name=FrameNameStr) -> MDIParentFrame
+ """
+ _windows_.MDIParentFrame_swiginit(self,_windows_.new_MDIParentFrame(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String title=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxDEFAULT_FRAME_STYLE|wxVSCROLL|wxHSCROLL,
+ String name=FrameNameStr) -> bool
+ """
+ return _windows_.MDIParentFrame_Create(*args, **kwargs)
+
+ def ActivateNext(*args, **kwargs):
+ """ActivateNext(self)"""
+ return _windows_.MDIParentFrame_ActivateNext(*args, **kwargs)
+
+ def ActivatePrevious(*args, **kwargs):
+ """ActivatePrevious(self)"""
+ return _windows_.MDIParentFrame_ActivatePrevious(*args, **kwargs)
+
+ def ArrangeIcons(*args, **kwargs):
+ """ArrangeIcons(self)"""
+ return _windows_.MDIParentFrame_ArrangeIcons(*args, **kwargs)
+
+ def Cascade(*args, **kwargs):
+ """Cascade(self)"""
+ return _windows_.MDIParentFrame_Cascade(*args, **kwargs)
+
+ def GetActiveChild(*args, **kwargs):
+ """GetActiveChild(self) -> MDIChildFrame"""
+ return _windows_.MDIParentFrame_GetActiveChild(*args, **kwargs)
+
+ def GetClientWindow(*args, **kwargs):
+ """GetClientWindow(self) -> MDIClientWindow"""
+ return _windows_.MDIParentFrame_GetClientWindow(*args, **kwargs)
+
+ def GetWindowMenu(*args, **kwargs):
+ """GetWindowMenu(self) -> Menu"""
+ return _windows_.MDIParentFrame_GetWindowMenu(*args, **kwargs)
+
+ def SetWindowMenu(*args, **kwargs):
+ """SetWindowMenu(self, Menu menu)"""
+ return _windows_.MDIParentFrame_SetWindowMenu(*args, **kwargs)
+
+ def Tile(*args, **kwargs):
+ """Tile(self, int orient=HORIZONTAL)"""
+ return _windows_.MDIParentFrame_Tile(*args, **kwargs)
+
+ ActiveChild = property(GetActiveChild,doc="See `GetActiveChild`")
+ ClientWindow = property(GetClientWindow,doc="See `GetClientWindow`")
+_windows_.MDIParentFrame_swigregister(MDIParentFrame)
+
+def PreMDIParentFrame(*args, **kwargs):
+ """PreMDIParentFrame() -> MDIParentFrame"""
+ val = _windows_.new_PreMDIParentFrame(*args, **kwargs)
+ return val
+
+class MDIChildFrame(Frame):
+ """Proxy of C++ MDIChildFrame class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, MDIParentFrame parent, int id=-1, String title=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DEFAULT_FRAME_STYLE,
+ String name=FrameNameStr) -> MDIChildFrame
+ """
+ _windows_.MDIChildFrame_swiginit(self,_windows_.new_MDIChildFrame(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, MDIParentFrame parent, int id=-1, String title=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DEFAULT_FRAME_STYLE,
+ String name=FrameNameStr) -> bool
+ """
+ return _windows_.MDIChildFrame_Create(*args, **kwargs)
+
+ def Activate(*args, **kwargs):
+ """Activate(self)"""
+ return _windows_.MDIChildFrame_Activate(*args, **kwargs)
+
+_windows_.MDIChildFrame_swigregister(MDIChildFrame)
+
+def PreMDIChildFrame(*args, **kwargs):
+ """PreMDIChildFrame() -> MDIChildFrame"""
+ val = _windows_.new_PreMDIChildFrame(*args, **kwargs)
+ return val
+
+class MDIClientWindow(_core.Window):
+ """Proxy of C++ MDIClientWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> MDIClientWindow"""
+ _windows_.MDIClientWindow_swiginit(self,_windows_.new_MDIClientWindow(*args, **kwargs))
+ def CreateClient(*args, **kwargs):
+ """CreateClient(self, MDIParentFrame parent, long style=wxVSCROLL|wxHSCROLL) -> bool"""
+ return _windows_.MDIClientWindow_CreateClient(*args, **kwargs)
+
+_windows_.MDIClientWindow_swigregister(MDIClientWindow)
+
+def PreMDIClientWindow(*args, **kwargs):
+ """PreMDIClientWindow() -> MDIClientWindow"""
+ val = _windows_.new_PreMDIClientWindow(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+class PyWindow(_core.Window):
+ """Proxy of C++ PyWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=PanelNameStr) -> PyWindow
+ """
+ _windows_.PyWindow_swiginit(self,_windows_.new_PyWindow(*args, **kwargs))
+ self._setOORInfo(self);PyWindow._setCallbackInfo(self, self, PyWindow)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.PyWindow__setCallbackInfo(*args, **kwargs)
+
+ SetBestSize = wx.Window.SetInitialSize
+ def DoEraseBackground(*args, **kwargs):
+ """DoEraseBackground(self, DC dc) -> bool"""
+ return _windows_.PyWindow_DoEraseBackground(*args, **kwargs)
+
+ def DoMoveWindow(*args, **kwargs):
+ """DoMoveWindow(self, int x, int y, int width, int height)"""
+ return _windows_.PyWindow_DoMoveWindow(*args, **kwargs)
+
+ def DoSetSize(*args, **kwargs):
+ """DoSetSize(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO)"""
+ return _windows_.PyWindow_DoSetSize(*args, **kwargs)
+
+ def DoSetClientSize(*args, **kwargs):
+ """DoSetClientSize(self, int width, int height)"""
+ return _windows_.PyWindow_DoSetClientSize(*args, **kwargs)
+
+ def DoSetVirtualSize(*args, **kwargs):
+ """DoSetVirtualSize(self, int x, int y)"""
+ return _windows_.PyWindow_DoSetVirtualSize(*args, **kwargs)
+
+ def DoGetSize(*args, **kwargs):
+ """DoGetSize() -> (width, height)"""
+ return _windows_.PyWindow_DoGetSize(*args, **kwargs)
+
+ def DoGetClientSize(*args, **kwargs):
+ """DoGetClientSize() -> (width, height)"""
+ return _windows_.PyWindow_DoGetClientSize(*args, **kwargs)
+
+ def DoGetPosition(*args, **kwargs):
+ """DoGetPosition() -> (x,y)"""
+ return _windows_.PyWindow_DoGetPosition(*args, **kwargs)
+
+ def DoGetVirtualSize(*args, **kwargs):
+ """DoGetVirtualSize(self) -> Size"""
+ return _windows_.PyWindow_DoGetVirtualSize(*args, **kwargs)
+
+ def DoGetBestSize(*args, **kwargs):
+ """DoGetBestSize(self) -> Size"""
+ return _windows_.PyWindow_DoGetBestSize(*args, **kwargs)
+
+ def GetDefaultAttributes(*args, **kwargs):
+ """GetDefaultAttributes(self) -> VisualAttributes"""
+ return _windows_.PyWindow_GetDefaultAttributes(*args, **kwargs)
+
+ def OnInternalIdle(*args, **kwargs):
+ """OnInternalIdle(self)"""
+ return _windows_.PyWindow_OnInternalIdle(*args, **kwargs)
+
+ def base_DoMoveWindow(*args, **kw):
+ return PyWindow.DoMoveWindow(*args, **kw)
+ base_DoMoveWindow = wx.deprecated(base_DoMoveWindow,
+ "Please use PyWindow.DoMoveWindow instead.")
+
+ def base_DoSetSize(*args, **kw):
+ return PyWindow.DoSetSize(*args, **kw)
+ base_DoSetSize = wx.deprecated(base_DoSetSize,
+ "Please use PyWindow.DoSetSize instead.")
+
+ def base_DoSetClientSize(*args, **kw):
+ return PyWindow.DoSetClientSize(*args, **kw)
+ base_DoSetClientSize = wx.deprecated(base_DoSetClientSize,
+ "Please use PyWindow.DoSetClientSize instead.")
+
+ def base_DoSetVirtualSize(*args, **kw):
+ return PyWindow.DoSetVirtualSize(*args, **kw)
+ base_DoSetVirtualSize = wx.deprecated(base_DoSetVirtualSize,
+ "Please use PyWindow.DoSetVirtualSize instead.")
+
+ def base_DoGetSize(*args, **kw):
+ return PyWindow.DoGetSize(*args, **kw)
+ base_DoGetSize = wx.deprecated(base_DoGetSize,
+ "Please use PyWindow.DoGetSize instead.")
+
+ def base_DoGetClientSize(*args, **kw):
+ return PyWindow.DoGetClientSize(*args, **kw)
+ base_DoGetClientSize = wx.deprecated(base_DoGetClientSize,
+ "Please use PyWindow.DoGetClientSize instead.")
+
+ def base_DoGetPosition(*args, **kw):
+ return PyWindow.DoGetPosition(*args, **kw)
+ base_DoGetPosition = wx.deprecated(base_DoGetPosition,
+ "Please use PyWindow.DoGetPosition instead.")
+
+ def base_DoGetVirtualSize(*args, **kw):
+ return PyWindow.DoGetVirtualSize(*args, **kw)
+ base_DoGetVirtualSize = wx.deprecated(base_DoGetVirtualSize,
+ "Please use PyWindow.DoGetVirtualSize instead.")
+
+ def base_DoGetBestSize(*args, **kw):
+ return PyWindow.DoGetBestSize(*args, **kw)
+ base_DoGetBestSize = wx.deprecated(base_DoGetBestSize,
+ "Please use PyWindow.DoGetBestSize instead.")
+
+ def base_InitDialog(*args, **kw):
+ return PyWindow.InitDialog(*args, **kw)
+ base_InitDialog = wx.deprecated(base_InitDialog,
+ "Please use PyWindow.InitDialog instead.")
+
+ def base_TransferDataToWindow(*args, **kw):
+ return PyWindow.TransferDataToWindow(*args, **kw)
+ base_TransferDataToWindow = wx.deprecated(base_TransferDataToWindow,
+ "Please use PyWindow.TransferDataToWindow instead.")
+
+ def base_TransferDataFromWindow(*args, **kw):
+ return PyWindow.TransferDataFromWindow(*args, **kw)
+ base_TransferDataFromWindow = wx.deprecated(base_TransferDataFromWindow,
+ "Please use PyWindow.TransferDataFromWindow instead.")
+
+ def base_Validate(*args, **kw):
+ return PyWindow.Validate(*args, **kw)
+ base_Validate = wx.deprecated(base_Validate,
+ "Please use PyWindow.Validate instead.")
+
+ def base_AcceptsFocus(*args, **kw):
+ return PyWindow.AcceptsFocus(*args, **kw)
+ base_AcceptsFocus = wx.deprecated(base_AcceptsFocus,
+ "Please use PyWindow.AcceptsFocus instead.")
+
+ def base_AcceptsFocusFromKeyboard(*args, **kw):
+ return PyWindow.AcceptsFocusFromKeyboard(*args, **kw)
+ base_AcceptsFocusFromKeyboard = wx.deprecated(base_AcceptsFocusFromKeyboard,
+ "Please use PyWindow.AcceptsFocusFromKeyboard instead.")
+
+ def base_GetMaxSize(*args, **kw):
+ return PyWindow.GetMaxSize(*args, **kw)
+ base_GetMaxSize = wx.deprecated(base_GetMaxSize,
+ "Please use PyWindow.GetMaxSize instead.")
+
+ def base_Enable(*args, **kw):
+ return PyWindow.Enable(*args, **kw)
+ base_Enable = wx.deprecated(base_Enable,
+ "Please use PyWindow.Enable instead.")
+
+ def base_AddChild(*args, **kw):
+ return PyWindow.AddChild(*args, **kw)
+ base_AddChild = wx.deprecated(base_AddChild,
+ "Please use PyWindow.AddChild instead.")
+
+ def base_RemoveChild(*args, **kw):
+ return PyWindow.RemoveChild(*args, **kw)
+ base_RemoveChild = wx.deprecated(base_RemoveChild,
+ "Please use PyWindow.RemoveChild instead.")
+
+ def base_ShouldInheritColours(*args, **kw):
+ return PyWindow.ShouldInheritColours(*args, **kw)
+ base_ShouldInheritColours = wx.deprecated(base_ShouldInheritColours,
+ "Please use PyWindow.ShouldInheritColours instead.")
+
+ def base_GetDefaultAttributes(*args, **kw):
+ return PyWindow.GetDefaultAttributes(*args, **kw)
+ base_GetDefaultAttributes = wx.deprecated(base_GetDefaultAttributes,
+ "Please use PyWindow.GetDefaultAttributes instead.")
+
+ def base_OnInternalIdle(*args, **kw):
+ return PyWindow.OnInternalIdle(*args, **kw)
+ base_OnInternalIdle = wx.deprecated(base_OnInternalIdle,
+ "Please use PyWindow.OnInternalIdle instead.")
+
+_windows_.PyWindow_swigregister(PyWindow)
+
+def PrePyWindow(*args, **kwargs):
+ """PrePyWindow() -> PyWindow"""
+ val = _windows_.new_PrePyWindow(*args, **kwargs)
+ return val
+
+class PyPanel(Panel):
+ """Proxy of C++ PyPanel class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxTAB_TRAVERSAL|wxNO_BORDER,
+ String name=PanelNameStr) -> PyPanel
+ """
+ _windows_.PyPanel_swiginit(self,_windows_.new_PyPanel(*args, **kwargs))
+ self._setOORInfo(self);PyPanel._setCallbackInfo(self, self, PyPanel)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.PyPanel__setCallbackInfo(*args, **kwargs)
+
+ SetBestSize = wx.Window.SetInitialSize
+ def DoEraseBackground(*args, **kwargs):
+ """DoEraseBackground(self, DC dc) -> bool"""
+ return _windows_.PyPanel_DoEraseBackground(*args, **kwargs)
+
+ def DoMoveWindow(*args, **kwargs):
+ """DoMoveWindow(self, int x, int y, int width, int height)"""
+ return _windows_.PyPanel_DoMoveWindow(*args, **kwargs)
+
+ def DoSetSize(*args, **kwargs):
+ """DoSetSize(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO)"""
+ return _windows_.PyPanel_DoSetSize(*args, **kwargs)
+
+ def DoSetClientSize(*args, **kwargs):
+ """DoSetClientSize(self, int width, int height)"""
+ return _windows_.PyPanel_DoSetClientSize(*args, **kwargs)
+
+ def DoSetVirtualSize(*args, **kwargs):
+ """DoSetVirtualSize(self, int x, int y)"""
+ return _windows_.PyPanel_DoSetVirtualSize(*args, **kwargs)
+
+ def DoGetSize(*args, **kwargs):
+ """DoGetSize() -> (width, height)"""
+ return _windows_.PyPanel_DoGetSize(*args, **kwargs)
+
+ def DoGetClientSize(*args, **kwargs):
+ """DoGetClientSize() -> (width, height)"""
+ return _windows_.PyPanel_DoGetClientSize(*args, **kwargs)
+
+ def DoGetPosition(*args, **kwargs):
+ """DoGetPosition() -> (x,y)"""
+ return _windows_.PyPanel_DoGetPosition(*args, **kwargs)
+
+ def DoGetVirtualSize(*args, **kwargs):
+ """DoGetVirtualSize(self) -> Size"""
+ return _windows_.PyPanel_DoGetVirtualSize(*args, **kwargs)
+
+ def DoGetBestSize(*args, **kwargs):
+ """DoGetBestSize(self) -> Size"""
+ return _windows_.PyPanel_DoGetBestSize(*args, **kwargs)
+
+ def GetDefaultAttributes(*args, **kwargs):
+ """GetDefaultAttributes(self) -> VisualAttributes"""
+ return _windows_.PyPanel_GetDefaultAttributes(*args, **kwargs)
+
+ def OnInternalIdle(*args, **kwargs):
+ """OnInternalIdle(self)"""
+ return _windows_.PyPanel_OnInternalIdle(*args, **kwargs)
+
+ def base_DoMoveWindow(*args, **kw):
+ return PyPanel.DoMoveWindow(*args, **kw)
+ base_DoMoveWindow = wx.deprecated(base_DoMoveWindow,
+ "Please use PyPanel.DoMoveWindow instead.")
+
+ def base_DoSetSize(*args, **kw):
+ return PyPanel.DoSetSize(*args, **kw)
+ base_DoSetSize = wx.deprecated(base_DoSetSize,
+ "Please use PyPanel.DoSetSize instead.")
+
+ def base_DoSetClientSize(*args, **kw):
+ return PyPanel.DoSetClientSize(*args, **kw)
+ base_DoSetClientSize = wx.deprecated(base_DoSetClientSize,
+ "Please use PyPanel.DoSetClientSize instead.")
+
+ def base_DoSetVirtualSize(*args, **kw):
+ return PyPanel.DoSetVirtualSize(*args, **kw)
+ base_DoSetVirtualSize = wx.deprecated(base_DoSetVirtualSize,
+ "Please use PyPanel.DoSetVirtualSize instead.")
+
+ def base_DoGetSize(*args, **kw):
+ return PyPanel.DoGetSize(*args, **kw)
+ base_DoGetSize = wx.deprecated(base_DoGetSize,
+ "Please use PyPanel.DoGetSize instead.")
+
+ def base_DoGetClientSize(*args, **kw):
+ return PyPanel.DoGetClientSize(*args, **kw)
+ base_DoGetClientSize = wx.deprecated(base_DoGetClientSize,
+ "Please use PyPanel.DoGetClientSize instead.")
+
+ def base_DoGetPosition(*args, **kw):
+ return PyPanel.DoGetPosition(*args, **kw)
+ base_DoGetPosition = wx.deprecated(base_DoGetPosition,
+ "Please use PyPanel.DoGetPosition instead.")
+
+ def base_DoGetVirtualSize(*args, **kw):
+ return PyPanel.DoGetVirtualSize(*args, **kw)
+ base_DoGetVirtualSize = wx.deprecated(base_DoGetVirtualSize,
+ "Please use PyPanel.DoGetVirtualSize instead.")
+
+ def base_DoGetBestSize(*args, **kw):
+ return PyPanel.DoGetBestSize(*args, **kw)
+ base_DoGetBestSize = wx.deprecated(base_DoGetBestSize,
+ "Please use PyPanel.DoGetBestSize instead.")
+
+ def base_InitDialog(*args, **kw):
+ return PyPanel.InitDialog(*args, **kw)
+ base_InitDialog = wx.deprecated(base_InitDialog,
+ "Please use PyPanel.InitDialog instead.")
+
+ def base_TransferDataToWindow(*args, **kw):
+ return PyPanel.TransferDataToWindow(*args, **kw)
+ base_TransferDataToWindow = wx.deprecated(base_TransferDataToWindow,
+ "Please use PyPanel.TransferDataToWindow instead.")
+
+ def base_TransferDataFromWindow(*args, **kw):
+ return PyPanel.TransferDataFromWindow(*args, **kw)
+ base_TransferDataFromWindow = wx.deprecated(base_TransferDataFromWindow,
+ "Please use PyPanel.TransferDataFromWindow instead.")
+
+ def base_Validate(*args, **kw):
+ return PyPanel.Validate(*args, **kw)
+ base_Validate = wx.deprecated(base_Validate,
+ "Please use PyPanel.Validate instead.")
+
+ def base_AcceptsFocus(*args, **kw):
+ return PyPanel.AcceptsFocus(*args, **kw)
+ base_AcceptsFocus = wx.deprecated(base_AcceptsFocus,
+ "Please use PyPanel.AcceptsFocus instead.")
+
+ def base_AcceptsFocusFromKeyboard(*args, **kw):
+ return PyPanel.AcceptsFocusFromKeyboard(*args, **kw)
+ base_AcceptsFocusFromKeyboard = wx.deprecated(base_AcceptsFocusFromKeyboard,
+ "Please use PyPanel.AcceptsFocusFromKeyboard instead.")
+
+ def base_GetMaxSize(*args, **kw):
+ return PyPanel.GetMaxSize(*args, **kw)
+ base_GetMaxSize = wx.deprecated(base_GetMaxSize,
+ "Please use PyPanel.GetMaxSize instead.")
+
+ def base_Enable(*args, **kw):
+ return PyPanel.Enable(*args, **kw)
+ base_Enable = wx.deprecated(base_Enable,
+ "Please use PyPanel.Enable instead.")
+
+ def base_AddChild(*args, **kw):
+ return PyPanel.AddChild(*args, **kw)
+ base_AddChild = wx.deprecated(base_AddChild,
+ "Please use PyPanel.AddChild instead.")
+
+ def base_RemoveChild(*args, **kw):
+ return PyPanel.RemoveChild(*args, **kw)
+ base_RemoveChild = wx.deprecated(base_RemoveChild,
+ "Please use PyPanel.RemoveChild instead.")
+
+ def base_ShouldInheritColours(*args, **kw):
+ return PyPanel.ShouldInheritColours(*args, **kw)
+ base_ShouldInheritColours = wx.deprecated(base_ShouldInheritColours,
+ "Please use PyPanel.ShouldInheritColours instead.")
+
+ def base_GetDefaultAttributes(*args, **kw):
+ return PyPanel.GetDefaultAttributes(*args, **kw)
+ base_GetDefaultAttributes = wx.deprecated(base_GetDefaultAttributes,
+ "Please use PyPanel.GetDefaultAttributes instead.")
+
+ def base_OnInternalIdle(*args, **kw):
+ return PyPanel.OnInternalIdle(*args, **kw)
+ base_OnInternalIdle = wx.deprecated(base_OnInternalIdle,
+ "Please use PyPanel.OnInternalIdle instead.")
+
+_windows_.PyPanel_swigregister(PyPanel)
+
+def PrePyPanel(*args, **kwargs):
+ """PrePyPanel() -> PyPanel"""
+ val = _windows_.new_PrePyPanel(*args, **kwargs)
+ return val
+
+class PyScrolledWindow(ScrolledWindow):
+ """Proxy of C++ PyScrolledWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxHSCROLL|wxVSCROLL,
+ String name=PanelNameStr) -> PyScrolledWindow
+ """
+ _windows_.PyScrolledWindow_swiginit(self,_windows_.new_PyScrolledWindow(*args, **kwargs))
+ self._setOORInfo(self);PyScrolledWindow._setCallbackInfo(self, self, PyScrolledWindow)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.PyScrolledWindow__setCallbackInfo(*args, **kwargs)
+
+ SetBestSize = wx.Window.SetInitialSize
+ def DoEraseBackground(*args, **kwargs):
+ """DoEraseBackground(self, DC dc) -> bool"""
+ return _windows_.PyScrolledWindow_DoEraseBackground(*args, **kwargs)
+
+ def DoMoveWindow(*args, **kwargs):
+ """DoMoveWindow(self, int x, int y, int width, int height)"""
+ return _windows_.PyScrolledWindow_DoMoveWindow(*args, **kwargs)
+
+ def DoSetSize(*args, **kwargs):
+ """DoSetSize(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO)"""
+ return _windows_.PyScrolledWindow_DoSetSize(*args, **kwargs)
+
+ def DoSetClientSize(*args, **kwargs):
+ """DoSetClientSize(self, int width, int height)"""
+ return _windows_.PyScrolledWindow_DoSetClientSize(*args, **kwargs)
+
+ def DoSetVirtualSize(*args, **kwargs):
+ """DoSetVirtualSize(self, int x, int y)"""
+ return _windows_.PyScrolledWindow_DoSetVirtualSize(*args, **kwargs)
+
+ def DoGetSize(*args, **kwargs):
+ """DoGetSize() -> (width, height)"""
+ return _windows_.PyScrolledWindow_DoGetSize(*args, **kwargs)
+
+ def DoGetClientSize(*args, **kwargs):
+ """DoGetClientSize() -> (width, height)"""
+ return _windows_.PyScrolledWindow_DoGetClientSize(*args, **kwargs)
+
+ def DoGetPosition(*args, **kwargs):
+ """DoGetPosition() -> (x,y)"""
+ return _windows_.PyScrolledWindow_DoGetPosition(*args, **kwargs)
+
+ def DoGetVirtualSize(*args, **kwargs):
+ """DoGetVirtualSize(self) -> Size"""
+ return _windows_.PyScrolledWindow_DoGetVirtualSize(*args, **kwargs)
+
+ def DoGetBestSize(*args, **kwargs):
+ """DoGetBestSize(self) -> Size"""
+ return _windows_.PyScrolledWindow_DoGetBestSize(*args, **kwargs)
+
+ def GetDefaultAttributes(*args, **kwargs):
+ """GetDefaultAttributes(self) -> VisualAttributes"""
+ return _windows_.PyScrolledWindow_GetDefaultAttributes(*args, **kwargs)
+
+ def OnInternalIdle(*args, **kwargs):
+ """OnInternalIdle(self)"""
+ return _windows_.PyScrolledWindow_OnInternalIdle(*args, **kwargs)
+
+ def base_DoMoveWindow(*args, **kw):
+ return PyScrolledWindow.DoMoveWindow(*args, **kw)
+ base_DoMoveWindow = wx.deprecated(base_DoMoveWindow,
+ "Please use PyScrolledWindow.DoMoveWindow instead.")
+
+ def base_DoSetSize(*args, **kw):
+ return PyScrolledWindow.DoSetSize(*args, **kw)
+ base_DoSetSize = wx.deprecated(base_DoSetSize,
+ "Please use PyScrolledWindow.DoSetSize instead.")
+
+ def base_DoSetClientSize(*args, **kw):
+ return PyScrolledWindow.DoSetClientSize(*args, **kw)
+ base_DoSetClientSize = wx.deprecated(base_DoSetClientSize,
+ "Please use PyScrolledWindow.DoSetClientSize instead.")
+
+ def base_DoSetVirtualSize(*args, **kw):
+ return PyScrolledWindow.DoSetVirtualSize(*args, **kw)
+ base_DoSetVirtualSize = wx.deprecated(base_DoSetVirtualSize,
+ "Please use PyScrolledWindow.DoSetVirtualSize instead.")
+
+ def base_DoGetSize(*args, **kw):
+ return PyScrolledWindow.DoGetSize(*args, **kw)
+ base_DoGetSize = wx.deprecated(base_DoGetSize,
+ "Please use PyScrolledWindow.DoGetSize instead.")
+
+ def base_DoGetClientSize(*args, **kw):
+ return PyScrolledWindow.DoGetClientSize(*args, **kw)
+ base_DoGetClientSize = wx.deprecated(base_DoGetClientSize,
+ "Please use PyScrolledWindow.DoGetClientSize instead.")
+
+ def base_DoGetPosition(*args, **kw):
+ return PyScrolledWindow.DoGetPosition(*args, **kw)
+ base_DoGetPosition = wx.deprecated(base_DoGetPosition,
+ "Please use PyScrolledWindow.DoGetPosition instead.")
+
+ def base_DoGetVirtualSize(*args, **kw):
+ return PyScrolledWindow.DoGetVirtualSize(*args, **kw)
+ base_DoGetVirtualSize = wx.deprecated(base_DoGetVirtualSize,
+ "Please use PyScrolledWindow.DoGetVirtualSize instead.")
+
+ def base_DoGetBestSize(*args, **kw):
+ return PyScrolledWindow.DoGetBestSize(*args, **kw)
+ base_DoGetBestSize = wx.deprecated(base_DoGetBestSize,
+ "Please use PyScrolledWindow.DoGetBestSize instead.")
+
+ def base_InitDialog(*args, **kw):
+ return PyScrolledWindow.InitDialog(*args, **kw)
+ base_InitDialog = wx.deprecated(base_InitDialog,
+ "Please use PyScrolledWindow.InitDialog instead.")
+
+ def base_TransferDataToWindow(*args, **kw):
+ return PyScrolledWindow.TransferDataToWindow(*args, **kw)
+ base_TransferDataToWindow = wx.deprecated(base_TransferDataToWindow,
+ "Please use PyScrolledWindow.TransferDataToWindow instead.")
+
+ def base_TransferDataFromWindow(*args, **kw):
+ return PyScrolledWindow.TransferDataFromWindow(*args, **kw)
+ base_TransferDataFromWindow = wx.deprecated(base_TransferDataFromWindow,
+ "Please use PyScrolledWindow.TransferDataFromWindow instead.")
+
+ def base_Validate(*args, **kw):
+ return PyScrolledWindow.Validate(*args, **kw)
+ base_Validate = wx.deprecated(base_Validate,
+ "Please use PyScrolledWindow.Validate instead.")
+
+ def base_AcceptsFocus(*args, **kw):
+ return PyScrolledWindow.AcceptsFocus(*args, **kw)
+ base_AcceptsFocus = wx.deprecated(base_AcceptsFocus,
+ "Please use PyScrolledWindow.AcceptsFocus instead.")
+
+ def base_AcceptsFocusFromKeyboard(*args, **kw):
+ return PyScrolledWindow.AcceptsFocusFromKeyboard(*args, **kw)
+ base_AcceptsFocusFromKeyboard = wx.deprecated(base_AcceptsFocusFromKeyboard,
+ "Please use PyScrolledWindow.AcceptsFocusFromKeyboard instead.")
+
+ def base_GetMaxSize(*args, **kw):
+ return PyScrolledWindow.GetMaxSize(*args, **kw)
+ base_GetMaxSize = wx.deprecated(base_GetMaxSize,
+ "Please use PyScrolledWindow.GetMaxSize instead.")
+
+ def base_Enable(*args, **kw):
+ return PyScrolledWindow.Enable(*args, **kw)
+ base_Enable = wx.deprecated(base_Enable,
+ "Please use PyScrolledWindow.Enable instead.")
+
+ def base_AddChild(*args, **kw):
+ return PyScrolledWindow.AddChild(*args, **kw)
+ base_AddChild = wx.deprecated(base_AddChild,
+ "Please use PyScrolledWindow.AddChild instead.")
+
+ def base_RemoveChild(*args, **kw):
+ return PyScrolledWindow.RemoveChild(*args, **kw)
+ base_RemoveChild = wx.deprecated(base_RemoveChild,
+ "Please use PyScrolledWindow.RemoveChild instead.")
+
+ def base_ShouldInheritColours(*args, **kw):
+ return PyScrolledWindow.ShouldInheritColours(*args, **kw)
+ base_ShouldInheritColours = wx.deprecated(base_ShouldInheritColours,
+ "Please use PyScrolledWindow.ShouldInheritColours instead.")
+
+ def base_GetDefaultAttributes(*args, **kw):
+ return PyScrolledWindow.GetDefaultAttributes(*args, **kw)
+ base_GetDefaultAttributes = wx.deprecated(base_GetDefaultAttributes,
+ "Please use PyScrolledWindow.GetDefaultAttributes instead.")
+
+ def base_OnInternalIdle(*args, **kw):
+ return PyScrolledWindow.OnInternalIdle(*args, **kw)
+ base_OnInternalIdle = wx.deprecated(base_OnInternalIdle,
+ "Please use PyScrolledWindow.OnInternalIdle instead.")
+
+_windows_.PyScrolledWindow_swigregister(PyScrolledWindow)
+
+def PrePyScrolledWindow(*args, **kwargs):
+ """PrePyScrolledWindow() -> PyScrolledWindow"""
+ val = _windows_.new_PrePyScrolledWindow(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+PRINT_MODE_NONE = _windows_.PRINT_MODE_NONE
+PRINT_MODE_PREVIEW = _windows_.PRINT_MODE_PREVIEW
+PRINT_MODE_FILE = _windows_.PRINT_MODE_FILE
+PRINT_MODE_PRINTER = _windows_.PRINT_MODE_PRINTER
+PRINT_MODE_STREAM = _windows_.PRINT_MODE_STREAM
+PRINTBIN_DEFAULT = _windows_.PRINTBIN_DEFAULT
+PRINTBIN_ONLYONE = _windows_.PRINTBIN_ONLYONE
+PRINTBIN_LOWER = _windows_.PRINTBIN_LOWER
+PRINTBIN_MIDDLE = _windows_.PRINTBIN_MIDDLE
+PRINTBIN_MANUAL = _windows_.PRINTBIN_MANUAL
+PRINTBIN_ENVELOPE = _windows_.PRINTBIN_ENVELOPE
+PRINTBIN_ENVMANUAL = _windows_.PRINTBIN_ENVMANUAL
+PRINTBIN_AUTO = _windows_.PRINTBIN_AUTO
+PRINTBIN_TRACTOR = _windows_.PRINTBIN_TRACTOR
+PRINTBIN_SMALLFMT = _windows_.PRINTBIN_SMALLFMT
+PRINTBIN_LARGEFMT = _windows_.PRINTBIN_LARGEFMT
+PRINTBIN_LARGECAPACITY = _windows_.PRINTBIN_LARGECAPACITY
+PRINTBIN_CASSETTE = _windows_.PRINTBIN_CASSETTE
+PRINTBIN_FORMSOURCE = _windows_.PRINTBIN_FORMSOURCE
+PRINTBIN_USER = _windows_.PRINTBIN_USER
+PreviewFrame_AppModal = _windows_.PreviewFrame_AppModal
+PreviewFrame_WindowModal = _windows_.PreviewFrame_WindowModal
+PreviewFrame_NonModal = _windows_.PreviewFrame_NonModal
+class PrintData(_core.Object):
+ """Proxy of C++ PrintData class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> PrintData
+ __init__(self, PrintData data) -> PrintData
+ """
+ _windows_.PrintData_swiginit(self,_windows_.new_PrintData(*args))
+ __swig_destroy__ = _windows_.delete_PrintData
+ __del__ = lambda self : None;
+ def GetNoCopies(*args, **kwargs):
+ """GetNoCopies(self) -> int"""
+ return _windows_.PrintData_GetNoCopies(*args, **kwargs)
+
+ def GetCollate(*args, **kwargs):
+ """GetCollate(self) -> bool"""
+ return _windows_.PrintData_GetCollate(*args, **kwargs)
+
+ def GetOrientation(*args, **kwargs):
+ """GetOrientation(self) -> int"""
+ return _windows_.PrintData_GetOrientation(*args, **kwargs)
+
+ def IsOrientationReversed(*args, **kwargs):
+ """IsOrientationReversed(self) -> bool"""
+ return _windows_.PrintData_IsOrientationReversed(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _windows_.PrintData_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def GetPrinterName(*args, **kwargs):
+ """GetPrinterName(self) -> String"""
+ return _windows_.PrintData_GetPrinterName(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """GetColour(self) -> bool"""
+ return _windows_.PrintData_GetColour(*args, **kwargs)
+
+ def GetDuplex(*args, **kwargs):
+ """GetDuplex(self) -> int"""
+ return _windows_.PrintData_GetDuplex(*args, **kwargs)
+
+ def GetPaperId(*args, **kwargs):
+ """GetPaperId(self) -> int"""
+ return _windows_.PrintData_GetPaperId(*args, **kwargs)
+
+ def GetPaperSize(*args, **kwargs):
+ """GetPaperSize(self) -> Size"""
+ return _windows_.PrintData_GetPaperSize(*args, **kwargs)
+
+ def GetQuality(*args, **kwargs):
+ """GetQuality(self) -> int"""
+ return _windows_.PrintData_GetQuality(*args, **kwargs)
+
+ def GetBin(*args, **kwargs):
+ """GetBin(self) -> int"""
+ return _windows_.PrintData_GetBin(*args, **kwargs)
+
+ def GetPrintMode(*args, **kwargs):
+ """GetPrintMode(self) -> int"""
+ return _windows_.PrintData_GetPrintMode(*args, **kwargs)
+
+ def GetMedia(*args, **kwargs):
+ """GetMedia(self) -> int"""
+ return _windows_.PrintData_GetMedia(*args, **kwargs)
+
+ def SetNoCopies(*args, **kwargs):
+ """SetNoCopies(self, int v)"""
+ return _windows_.PrintData_SetNoCopies(*args, **kwargs)
+
+ def SetCollate(*args, **kwargs):
+ """SetCollate(self, bool flag)"""
+ return _windows_.PrintData_SetCollate(*args, **kwargs)
+
+ def SetOrientation(*args, **kwargs):
+ """SetOrientation(self, int orient)"""
+ return _windows_.PrintData_SetOrientation(*args, **kwargs)
+
+ def SetOrientationReversed(*args, **kwargs):
+ """SetOrientationReversed(self, bool reversed)"""
+ return _windows_.PrintData_SetOrientationReversed(*args, **kwargs)
+
+ def SetPrinterName(*args, **kwargs):
+ """SetPrinterName(self, String name)"""
+ return _windows_.PrintData_SetPrinterName(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """SetColour(self, bool colour)"""
+ return _windows_.PrintData_SetColour(*args, **kwargs)
+
+ def SetDuplex(*args, **kwargs):
+ """SetDuplex(self, int duplex)"""
+ return _windows_.PrintData_SetDuplex(*args, **kwargs)
+
+ def SetPaperId(*args, **kwargs):
+ """SetPaperId(self, int sizeId)"""
+ return _windows_.PrintData_SetPaperId(*args, **kwargs)
+
+ def SetPaperSize(*args, **kwargs):
+ """SetPaperSize(self, Size sz)"""
+ return _windows_.PrintData_SetPaperSize(*args, **kwargs)
+
+ def SetQuality(*args, **kwargs):
+ """SetQuality(self, int quality)"""
+ return _windows_.PrintData_SetQuality(*args, **kwargs)
+
+ def SetBin(*args, **kwargs):
+ """SetBin(self, int bin)"""
+ return _windows_.PrintData_SetBin(*args, **kwargs)
+
+ def SetPrintMode(*args, **kwargs):
+ """SetPrintMode(self, int printMode)"""
+ return _windows_.PrintData_SetPrintMode(*args, **kwargs)
+
+ def SetMedia(*args, **kwargs):
+ """SetMedia(self, int media)"""
+ return _windows_.PrintData_SetMedia(*args, **kwargs)
+
+ def GetFilename(*args, **kwargs):
+ """GetFilename(self) -> String"""
+ return _windows_.PrintData_GetFilename(*args, **kwargs)
+
+ def SetFilename(*args, **kwargs):
+ """SetFilename(self, String filename)"""
+ return _windows_.PrintData_SetFilename(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def GetPrivData(*args, **kwargs):
+ """GetPrivData(self) -> PyObject"""
+ return _windows_.PrintData_GetPrivData(*args, **kwargs)
+
+ def SetPrivData(*args, **kwargs):
+ """SetPrivData(self, PyObject data)"""
+ return _windows_.PrintData_SetPrivData(*args, **kwargs)
+
+ Bin = property(GetBin,SetBin,doc="See `GetBin` and `SetBin`")
+ Collate = property(GetCollate,SetCollate,doc="See `GetCollate` and `SetCollate`")
+ Colour = property(GetColour,SetColour,doc="See `GetColour` and `SetColour`")
+ Duplex = property(GetDuplex,SetDuplex,doc="See `GetDuplex` and `SetDuplex`")
+ Filename = property(GetFilename,SetFilename,doc="See `GetFilename` and `SetFilename`")
+ NoCopies = property(GetNoCopies,SetNoCopies,doc="See `GetNoCopies` and `SetNoCopies`")
+ Orientation = property(GetOrientation,SetOrientation,doc="See `GetOrientation` and `SetOrientation`")
+ PaperId = property(GetPaperId,SetPaperId,doc="See `GetPaperId` and `SetPaperId`")
+ PaperSize = property(GetPaperSize,SetPaperSize,doc="See `GetPaperSize` and `SetPaperSize`")
+ PrintMode = property(GetPrintMode,SetPrintMode,doc="See `GetPrintMode` and `SetPrintMode`")
+ PrinterName = property(GetPrinterName,SetPrinterName,doc="See `GetPrinterName` and `SetPrinterName`")
+ PrivData = property(GetPrivData,SetPrivData,doc="See `GetPrivData` and `SetPrivData`")
+ Quality = property(GetQuality,SetQuality,doc="See `GetQuality` and `SetQuality`")
+_windows_.PrintData_swigregister(PrintData)
+PrintoutTitleStr = cvar.PrintoutTitleStr
+PreviewCanvasNameStr = cvar.PreviewCanvasNameStr
+
+class PageSetupDialogData(_core.Object):
+ """Proxy of C++ PageSetupDialogData class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> PageSetupDialogData
+ __init__(self, PageSetupDialogData data) -> PageSetupDialogData
+ __init__(self, PrintData data) -> PageSetupDialogData
+ """
+ _windows_.PageSetupDialogData_swiginit(self,_windows_.new_PageSetupDialogData(*args))
+ __swig_destroy__ = _windows_.delete_PageSetupDialogData
+ __del__ = lambda self : None;
+ def EnableHelp(*args, **kwargs):
+ """EnableHelp(self, bool flag)"""
+ return _windows_.PageSetupDialogData_EnableHelp(*args, **kwargs)
+
+ def EnableMargins(*args, **kwargs):
+ """EnableMargins(self, bool flag)"""
+ return _windows_.PageSetupDialogData_EnableMargins(*args, **kwargs)
+
+ def EnableOrientation(*args, **kwargs):
+ """EnableOrientation(self, bool flag)"""
+ return _windows_.PageSetupDialogData_EnableOrientation(*args, **kwargs)
+
+ def EnablePaper(*args, **kwargs):
+ """EnablePaper(self, bool flag)"""
+ return _windows_.PageSetupDialogData_EnablePaper(*args, **kwargs)
+
+ def EnablePrinter(*args, **kwargs):
+ """EnablePrinter(self, bool flag)"""
+ return _windows_.PageSetupDialogData_EnablePrinter(*args, **kwargs)
+
+ def GetDefaultMinMargins(*args, **kwargs):
+ """GetDefaultMinMargins(self) -> bool"""
+ return _windows_.PageSetupDialogData_GetDefaultMinMargins(*args, **kwargs)
+
+ def GetEnableMargins(*args, **kwargs):
+ """GetEnableMargins(self) -> bool"""
+ return _windows_.PageSetupDialogData_GetEnableMargins(*args, **kwargs)
+
+ def GetEnableOrientation(*args, **kwargs):
+ """GetEnableOrientation(self) -> bool"""
+ return _windows_.PageSetupDialogData_GetEnableOrientation(*args, **kwargs)
+
+ def GetEnablePaper(*args, **kwargs):
+ """GetEnablePaper(self) -> bool"""
+ return _windows_.PageSetupDialogData_GetEnablePaper(*args, **kwargs)
+
+ def GetEnablePrinter(*args, **kwargs):
+ """GetEnablePrinter(self) -> bool"""
+ return _windows_.PageSetupDialogData_GetEnablePrinter(*args, **kwargs)
+
+ def GetEnableHelp(*args, **kwargs):
+ """GetEnableHelp(self) -> bool"""
+ return _windows_.PageSetupDialogData_GetEnableHelp(*args, **kwargs)
+
+ def GetDefaultInfo(*args, **kwargs):
+ """GetDefaultInfo(self) -> bool"""
+ return _windows_.PageSetupDialogData_GetDefaultInfo(*args, **kwargs)
+
+ def GetMarginTopLeft(*args, **kwargs):
+ """GetMarginTopLeft(self) -> Point"""
+ return _windows_.PageSetupDialogData_GetMarginTopLeft(*args, **kwargs)
+
+ def GetMarginBottomRight(*args, **kwargs):
+ """GetMarginBottomRight(self) -> Point"""
+ return _windows_.PageSetupDialogData_GetMarginBottomRight(*args, **kwargs)
+
+ def GetMinMarginTopLeft(*args, **kwargs):
+ """GetMinMarginTopLeft(self) -> Point"""
+ return _windows_.PageSetupDialogData_GetMinMarginTopLeft(*args, **kwargs)
+
+ def GetMinMarginBottomRight(*args, **kwargs):
+ """GetMinMarginBottomRight(self) -> Point"""
+ return _windows_.PageSetupDialogData_GetMinMarginBottomRight(*args, **kwargs)
+
+ def GetPaperId(*args, **kwargs):
+ """GetPaperId(self) -> int"""
+ return _windows_.PageSetupDialogData_GetPaperId(*args, **kwargs)
+
+ def GetPaperSize(*args, **kwargs):
+ """GetPaperSize(self) -> Size"""
+ return _windows_.PageSetupDialogData_GetPaperSize(*args, **kwargs)
+
+ def GetPrintData(*args, **kwargs):
+ """GetPrintData(self) -> PrintData"""
+ return _windows_.PageSetupDialogData_GetPrintData(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _windows_.PageSetupDialogData_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def SetDefaultInfo(*args, **kwargs):
+ """SetDefaultInfo(self, bool flag)"""
+ return _windows_.PageSetupDialogData_SetDefaultInfo(*args, **kwargs)
+
+ def SetDefaultMinMargins(*args, **kwargs):
+ """SetDefaultMinMargins(self, bool flag)"""
+ return _windows_.PageSetupDialogData_SetDefaultMinMargins(*args, **kwargs)
+
+ def SetMarginTopLeft(*args, **kwargs):
+ """SetMarginTopLeft(self, Point pt)"""
+ return _windows_.PageSetupDialogData_SetMarginTopLeft(*args, **kwargs)
+
+ def SetMarginBottomRight(*args, **kwargs):
+ """SetMarginBottomRight(self, Point pt)"""
+ return _windows_.PageSetupDialogData_SetMarginBottomRight(*args, **kwargs)
+
+ def SetMinMarginTopLeft(*args, **kwargs):
+ """SetMinMarginTopLeft(self, Point pt)"""
+ return _windows_.PageSetupDialogData_SetMinMarginTopLeft(*args, **kwargs)
+
+ def SetMinMarginBottomRight(*args, **kwargs):
+ """SetMinMarginBottomRight(self, Point pt)"""
+ return _windows_.PageSetupDialogData_SetMinMarginBottomRight(*args, **kwargs)
+
+ def SetPaperId(*args, **kwargs):
+ """SetPaperId(self, int id)"""
+ return _windows_.PageSetupDialogData_SetPaperId(*args, **kwargs)
+
+ def SetPaperSize(*args, **kwargs):
+ """SetPaperSize(self, Size size)"""
+ return _windows_.PageSetupDialogData_SetPaperSize(*args, **kwargs)
+
+ def SetPrintData(*args, **kwargs):
+ """SetPrintData(self, PrintData printData)"""
+ return _windows_.PageSetupDialogData_SetPrintData(*args, **kwargs)
+
+ def CalculateIdFromPaperSize(*args, **kwargs):
+ """CalculateIdFromPaperSize(self)"""
+ return _windows_.PageSetupDialogData_CalculateIdFromPaperSize(*args, **kwargs)
+
+ def CalculatePaperSizeFromId(*args, **kwargs):
+ """CalculatePaperSizeFromId(self)"""
+ return _windows_.PageSetupDialogData_CalculatePaperSizeFromId(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ DefaultInfo = property(GetDefaultInfo,SetDefaultInfo,doc="See `GetDefaultInfo` and `SetDefaultInfo`")
+ DefaultMinMargins = property(GetDefaultMinMargins,SetDefaultMinMargins,doc="See `GetDefaultMinMargins` and `SetDefaultMinMargins`")
+ MarginBottomRight = property(GetMarginBottomRight,SetMarginBottomRight,doc="See `GetMarginBottomRight` and `SetMarginBottomRight`")
+ MarginTopLeft = property(GetMarginTopLeft,SetMarginTopLeft,doc="See `GetMarginTopLeft` and `SetMarginTopLeft`")
+ MinMarginBottomRight = property(GetMinMarginBottomRight,SetMinMarginBottomRight,doc="See `GetMinMarginBottomRight` and `SetMinMarginBottomRight`")
+ MinMarginTopLeft = property(GetMinMarginTopLeft,SetMinMarginTopLeft,doc="See `GetMinMarginTopLeft` and `SetMinMarginTopLeft`")
+ PaperId = property(GetPaperId,SetPaperId,doc="See `GetPaperId` and `SetPaperId`")
+ PaperSize = property(GetPaperSize,SetPaperSize,doc="See `GetPaperSize` and `SetPaperSize`")
+ PrintData = property(GetPrintData,SetPrintData,doc="See `GetPrintData` and `SetPrintData`")
+_windows_.PageSetupDialogData_swigregister(PageSetupDialogData)
+
+class PageSetupDialog(_core.Object):
+ """Proxy of C++ PageSetupDialog class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window parent, PageSetupDialogData data=None) -> PageSetupDialog"""
+ _windows_.PageSetupDialog_swiginit(self,_windows_.new_PageSetupDialog(*args, **kwargs))
+ __swig_destroy__ = _windows_.delete_PageSetupDialog
+ __del__ = lambda self : None;
+ def GetPageSetupData(*args, **kwargs):
+ """GetPageSetupData(self) -> PageSetupDialogData"""
+ return _windows_.PageSetupDialog_GetPageSetupData(*args, **kwargs)
+
+ def GetPageSetupDialogData(*args, **kwargs):
+ """GetPageSetupDialogData(self) -> PageSetupDialogData"""
+ return _windows_.PageSetupDialog_GetPageSetupDialogData(*args, **kwargs)
+
+ def ShowModal(*args, **kwargs):
+ """ShowModal(self) -> int"""
+ return _windows_.PageSetupDialog_ShowModal(*args, **kwargs)
+
+ def Destroy(self): pass
+ PageSetupData = property(GetPageSetupData,doc="See `GetPageSetupData`")
+ PageSetupDialogData = property(GetPageSetupDialogData,doc="See `GetPageSetupDialogData`")
+_windows_.PageSetupDialog_swigregister(PageSetupDialog)
+
+class PrintDialogData(_core.Object):
+ """Proxy of C++ PrintDialogData class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> PrintDialogData
+ __init__(self, PrintData printData) -> PrintDialogData
+ __init__(self, PrintDialogData printData) -> PrintDialogData
+ """
+ _windows_.PrintDialogData_swiginit(self,_windows_.new_PrintDialogData(*args))
+ __swig_destroy__ = _windows_.delete_PrintDialogData
+ __del__ = lambda self : None;
+ def GetFromPage(*args, **kwargs):
+ """GetFromPage(self) -> int"""
+ return _windows_.PrintDialogData_GetFromPage(*args, **kwargs)
+
+ def GetToPage(*args, **kwargs):
+ """GetToPage(self) -> int"""
+ return _windows_.PrintDialogData_GetToPage(*args, **kwargs)
+
+ def GetMinPage(*args, **kwargs):
+ """GetMinPage(self) -> int"""
+ return _windows_.PrintDialogData_GetMinPage(*args, **kwargs)
+
+ def GetMaxPage(*args, **kwargs):
+ """GetMaxPage(self) -> int"""
+ return _windows_.PrintDialogData_GetMaxPage(*args, **kwargs)
+
+ def GetNoCopies(*args, **kwargs):
+ """GetNoCopies(self) -> int"""
+ return _windows_.PrintDialogData_GetNoCopies(*args, **kwargs)
+
+ def GetAllPages(*args, **kwargs):
+ """GetAllPages(self) -> bool"""
+ return _windows_.PrintDialogData_GetAllPages(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> bool"""
+ return _windows_.PrintDialogData_GetSelection(*args, **kwargs)
+
+ def GetCollate(*args, **kwargs):
+ """GetCollate(self) -> bool"""
+ return _windows_.PrintDialogData_GetCollate(*args, **kwargs)
+
+ def GetPrintToFile(*args, **kwargs):
+ """GetPrintToFile(self) -> bool"""
+ return _windows_.PrintDialogData_GetPrintToFile(*args, **kwargs)
+
+ def SetFromPage(*args, **kwargs):
+ """SetFromPage(self, int v)"""
+ return _windows_.PrintDialogData_SetFromPage(*args, **kwargs)
+
+ def SetToPage(*args, **kwargs):
+ """SetToPage(self, int v)"""
+ return _windows_.PrintDialogData_SetToPage(*args, **kwargs)
+
+ def SetMinPage(*args, **kwargs):
+ """SetMinPage(self, int v)"""
+ return _windows_.PrintDialogData_SetMinPage(*args, **kwargs)
+
+ def SetMaxPage(*args, **kwargs):
+ """SetMaxPage(self, int v)"""
+ return _windows_.PrintDialogData_SetMaxPage(*args, **kwargs)
+
+ def SetNoCopies(*args, **kwargs):
+ """SetNoCopies(self, int v)"""
+ return _windows_.PrintDialogData_SetNoCopies(*args, **kwargs)
+
+ def SetAllPages(*args, **kwargs):
+ """SetAllPages(self, bool flag)"""
+ return _windows_.PrintDialogData_SetAllPages(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """SetSelection(self, bool flag)"""
+ return _windows_.PrintDialogData_SetSelection(*args, **kwargs)
+
+ def SetCollate(*args, **kwargs):
+ """SetCollate(self, bool flag)"""
+ return _windows_.PrintDialogData_SetCollate(*args, **kwargs)
+
+ def SetPrintToFile(*args, **kwargs):
+ """SetPrintToFile(self, bool flag)"""
+ return _windows_.PrintDialogData_SetPrintToFile(*args, **kwargs)
+
+ def EnablePrintToFile(*args, **kwargs):
+ """EnablePrintToFile(self, bool flag)"""
+ return _windows_.PrintDialogData_EnablePrintToFile(*args, **kwargs)
+
+ def EnableSelection(*args, **kwargs):
+ """EnableSelection(self, bool flag)"""
+ return _windows_.PrintDialogData_EnableSelection(*args, **kwargs)
+
+ def EnablePageNumbers(*args, **kwargs):
+ """EnablePageNumbers(self, bool flag)"""
+ return _windows_.PrintDialogData_EnablePageNumbers(*args, **kwargs)
+
+ def EnableHelp(*args, **kwargs):
+ """EnableHelp(self, bool flag)"""
+ return _windows_.PrintDialogData_EnableHelp(*args, **kwargs)
+
+ def GetEnablePrintToFile(*args, **kwargs):
+ """GetEnablePrintToFile(self) -> bool"""
+ return _windows_.PrintDialogData_GetEnablePrintToFile(*args, **kwargs)
+
+ def GetEnableSelection(*args, **kwargs):
+ """GetEnableSelection(self) -> bool"""
+ return _windows_.PrintDialogData_GetEnableSelection(*args, **kwargs)
+
+ def GetEnablePageNumbers(*args, **kwargs):
+ """GetEnablePageNumbers(self) -> bool"""
+ return _windows_.PrintDialogData_GetEnablePageNumbers(*args, **kwargs)
+
+ def GetEnableHelp(*args, **kwargs):
+ """GetEnableHelp(self) -> bool"""
+ return _windows_.PrintDialogData_GetEnableHelp(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _windows_.PrintDialogData_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def GetPrintData(*args, **kwargs):
+ """GetPrintData(self) -> PrintData"""
+ return _windows_.PrintDialogData_GetPrintData(*args, **kwargs)
+
+ def SetPrintData(*args, **kwargs):
+ """SetPrintData(self, PrintData printData)"""
+ return _windows_.PrintDialogData_SetPrintData(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ AllPages = property(GetAllPages,SetAllPages,doc="See `GetAllPages` and `SetAllPages`")
+ Collate = property(GetCollate,SetCollate,doc="See `GetCollate` and `SetCollate`")
+ FromPage = property(GetFromPage,SetFromPage,doc="See `GetFromPage` and `SetFromPage`")
+ MaxPage = property(GetMaxPage,SetMaxPage,doc="See `GetMaxPage` and `SetMaxPage`")
+ MinPage = property(GetMinPage,SetMinPage,doc="See `GetMinPage` and `SetMinPage`")
+ NoCopies = property(GetNoCopies,SetNoCopies,doc="See `GetNoCopies` and `SetNoCopies`")
+ PrintData = property(GetPrintData,SetPrintData,doc="See `GetPrintData` and `SetPrintData`")
+ PrintToFile = property(GetPrintToFile,SetPrintToFile,doc="See `GetPrintToFile` and `SetPrintToFile`")
+ Selection = property(GetSelection,SetSelection,doc="See `GetSelection` and `SetSelection`")
+ ToPage = property(GetToPage,SetToPage,doc="See `GetToPage` and `SetToPage`")
+_windows_.PrintDialogData_swigregister(PrintDialogData)
+
+class PrintDialog(_core.Object):
+ """Proxy of C++ PrintDialog class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window parent, PrintDialogData data=None) -> PrintDialog"""
+ _windows_.PrintDialog_swiginit(self,_windows_.new_PrintDialog(*args, **kwargs))
+ __swig_destroy__ = _windows_.delete_PrintDialog
+ __del__ = lambda self : None;
+ def ShowModal(*args, **kwargs):
+ """ShowModal(self) -> int"""
+ return _windows_.PrintDialog_ShowModal(*args, **kwargs)
+
+ def GetPrintDialogData(*args, **kwargs):
+ """GetPrintDialogData(self) -> PrintDialogData"""
+ return _windows_.PrintDialog_GetPrintDialogData(*args, **kwargs)
+
+ def GetPrintData(*args, **kwargs):
+ """GetPrintData(self) -> PrintData"""
+ return _windows_.PrintDialog_GetPrintData(*args, **kwargs)
+
+ def GetPrintDC(*args, **kwargs):
+ """GetPrintDC(self) -> DC"""
+ return _windows_.PrintDialog_GetPrintDC(*args, **kwargs)
+
+ def Destroy(self): pass
+ PrintDC = property(GetPrintDC,doc="See `GetPrintDC`")
+ PrintData = property(GetPrintData,doc="See `GetPrintData`")
+ PrintDialogData = property(GetPrintDialogData,doc="See `GetPrintDialogData`")
+_windows_.PrintDialog_swigregister(PrintDialog)
+
+PRINTER_NO_ERROR = _windows_.PRINTER_NO_ERROR
+PRINTER_CANCELLED = _windows_.PRINTER_CANCELLED
+PRINTER_ERROR = _windows_.PRINTER_ERROR
+class Printer(_core.Object):
+ """Proxy of C++ Printer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, PrintDialogData data=None) -> Printer"""
+ _windows_.Printer_swiginit(self,_windows_.new_Printer(*args, **kwargs))
+ __swig_destroy__ = _windows_.delete_Printer
+ __del__ = lambda self : None;
+ def CreateAbortWindow(*args, **kwargs):
+ """CreateAbortWindow(self, Window parent, Printout printout) -> Window"""
+ return _windows_.Printer_CreateAbortWindow(*args, **kwargs)
+
+ def ReportError(*args, **kwargs):
+ """ReportError(self, Window parent, Printout printout, String message)"""
+ return _windows_.Printer_ReportError(*args, **kwargs)
+
+ def Setup(*args, **kwargs):
+ """Setup(self, Window parent) -> bool"""
+ return _windows_.Printer_Setup(*args, **kwargs)
+
+ def Print(*args, **kwargs):
+ """Print(self, Window parent, Printout printout, bool prompt=True) -> bool"""
+ return _windows_.Printer_Print(*args, **kwargs)
+
+ def PrintDialog(*args, **kwargs):
+ """PrintDialog(self, Window parent) -> DC"""
+ return _windows_.Printer_PrintDialog(*args, **kwargs)
+
+ def GetPrintDialogData(*args, **kwargs):
+ """GetPrintDialogData(self) -> PrintDialogData"""
+ return _windows_.Printer_GetPrintDialogData(*args, **kwargs)
+
+ def GetAbort(*args, **kwargs):
+ """GetAbort(self) -> bool"""
+ return _windows_.Printer_GetAbort(*args, **kwargs)
+
+ def GetLastError(*args, **kwargs):
+ """GetLastError() -> int"""
+ return _windows_.Printer_GetLastError(*args, **kwargs)
+
+ GetLastError = staticmethod(GetLastError)
+ Abort = property(GetAbort,doc="See `GetAbort`")
+ PrintDialogData = property(GetPrintDialogData,doc="See `GetPrintDialogData`")
+_windows_.Printer_swigregister(Printer)
+
+def Printer_GetLastError(*args):
+ """Printer_GetLastError() -> int"""
+ return _windows_.Printer_GetLastError(*args)
+
+class Printout(_core.Object):
+ """Proxy of C++ Printout class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String title=PrintoutTitleStr) -> Printout"""
+ _windows_.Printout_swiginit(self,_windows_.new_Printout(*args, **kwargs))
+ Printout._setCallbackInfo(self, self, Printout)
+
+ __swig_destroy__ = _windows_.delete_Printout
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.Printout__setCallbackInfo(*args, **kwargs)
+
+ def GetTitle(*args, **kwargs):
+ """GetTitle(self) -> String"""
+ return _windows_.Printout_GetTitle(*args, **kwargs)
+
+ def GetDC(*args, **kwargs):
+ """GetDC(self) -> DC"""
+ return _windows_.Printout_GetDC(*args, **kwargs)
+
+ def SetDC(*args, **kwargs):
+ """SetDC(self, DC dc)"""
+ return _windows_.Printout_SetDC(*args, **kwargs)
+
+ def FitThisSizeToPaper(*args, **kwargs):
+ """FitThisSizeToPaper(self, Size imageSize)"""
+ return _windows_.Printout_FitThisSizeToPaper(*args, **kwargs)
+
+ def FitThisSizeToPage(*args, **kwargs):
+ """FitThisSizeToPage(self, Size imageSize)"""
+ return _windows_.Printout_FitThisSizeToPage(*args, **kwargs)
+
+ def FitThisSizeToPageMargins(*args, **kwargs):
+ """FitThisSizeToPageMargins(self, Size imageSize, PageSetupDialogData pageSetupData)"""
+ return _windows_.Printout_FitThisSizeToPageMargins(*args, **kwargs)
+
+ def MapScreenSizeToPaper(*args, **kwargs):
+ """MapScreenSizeToPaper(self)"""
+ return _windows_.Printout_MapScreenSizeToPaper(*args, **kwargs)
+
+ def MapScreenSizeToPage(*args, **kwargs):
+ """MapScreenSizeToPage(self)"""
+ return _windows_.Printout_MapScreenSizeToPage(*args, **kwargs)
+
+ def MapScreenSizeToPageMargins(*args, **kwargs):
+ """MapScreenSizeToPageMargins(self, PageSetupDialogData pageSetupData)"""
+ return _windows_.Printout_MapScreenSizeToPageMargins(*args, **kwargs)
+
+ def MapScreenSizeToDevice(*args, **kwargs):
+ """MapScreenSizeToDevice(self)"""
+ return _windows_.Printout_MapScreenSizeToDevice(*args, **kwargs)
+
+ def GetLogicalPaperRect(*args, **kwargs):
+ """GetLogicalPaperRect(self) -> Rect"""
+ return _windows_.Printout_GetLogicalPaperRect(*args, **kwargs)
+
+ def GetLogicalPageRect(*args, **kwargs):
+ """GetLogicalPageRect(self) -> Rect"""
+ return _windows_.Printout_GetLogicalPageRect(*args, **kwargs)
+
+ def GetLogicalPageMarginsRect(*args, **kwargs):
+ """GetLogicalPageMarginsRect(self, PageSetupDialogData pageSetupData) -> Rect"""
+ return _windows_.Printout_GetLogicalPageMarginsRect(*args, **kwargs)
+
+ def SetLogicalOrigin(*args, **kwargs):
+ """SetLogicalOrigin(self, int x, int y)"""
+ return _windows_.Printout_SetLogicalOrigin(*args, **kwargs)
+
+ def OffsetLogicalOrigin(*args, **kwargs):
+ """OffsetLogicalOrigin(self, int xoff, int yoff)"""
+ return _windows_.Printout_OffsetLogicalOrigin(*args, **kwargs)
+
+ def SetPageSizePixels(*args, **kwargs):
+ """SetPageSizePixels(self, int w, int h)"""
+ return _windows_.Printout_SetPageSizePixels(*args, **kwargs)
+
+ def GetPageSizePixels(*args, **kwargs):
+ """GetPageSizePixels() -> (w, h)"""
+ return _windows_.Printout_GetPageSizePixels(*args, **kwargs)
+
+ def SetPageSizeMM(*args, **kwargs):
+ """SetPageSizeMM(self, int w, int h)"""
+ return _windows_.Printout_SetPageSizeMM(*args, **kwargs)
+
+ def GetPageSizeMM(*args, **kwargs):
+ """GetPageSizeMM() -> (w, h)"""
+ return _windows_.Printout_GetPageSizeMM(*args, **kwargs)
+
+ def SetPPIScreen(*args, **kwargs):
+ """SetPPIScreen(self, int x, int y)"""
+ return _windows_.Printout_SetPPIScreen(*args, **kwargs)
+
+ def GetPPIScreen(*args, **kwargs):
+ """GetPPIScreen() -> (x,y)"""
+ return _windows_.Printout_GetPPIScreen(*args, **kwargs)
+
+ def SetPPIPrinter(*args, **kwargs):
+ """SetPPIPrinter(self, int x, int y)"""
+ return _windows_.Printout_SetPPIPrinter(*args, **kwargs)
+
+ def GetPPIPrinter(*args, **kwargs):
+ """GetPPIPrinter() -> (x,y)"""
+ return _windows_.Printout_GetPPIPrinter(*args, **kwargs)
+
+ def SetPaperRectPixels(*args, **kwargs):
+ """SetPaperRectPixels(self, Rect paperRectPixels)"""
+ return _windows_.Printout_SetPaperRectPixels(*args, **kwargs)
+
+ def GetPaperRectPixels(*args, **kwargs):
+ """GetPaperRectPixels(self) -> Rect"""
+ return _windows_.Printout_GetPaperRectPixels(*args, **kwargs)
+
+ def SetPreview(*args, **kwargs):
+ """SetPreview(self, PrintPreview preview)"""
+ return _windows_.Printout_SetPreview(*args, **kwargs)
+
+ def GetPreview(*args, **kwargs):
+ """GetPreview(self) -> PrintPreview"""
+ return _windows_.Printout_GetPreview(*args, **kwargs)
+
+ def IsPreview(*args, **kwargs):
+ """IsPreview(self) -> bool"""
+ return _windows_.Printout_IsPreview(*args, **kwargs)
+
+ def OnBeginDocument(*args, **kwargs):
+ """OnBeginDocument(self, int startPage, int endPage) -> bool"""
+ return _windows_.Printout_OnBeginDocument(*args, **kwargs)
+
+ def OnEndDocument(*args, **kwargs):
+ """OnEndDocument(self)"""
+ return _windows_.Printout_OnEndDocument(*args, **kwargs)
+
+ def OnBeginPrinting(*args, **kwargs):
+ """OnBeginPrinting(self)"""
+ return _windows_.Printout_OnBeginPrinting(*args, **kwargs)
+
+ def OnEndPrinting(*args, **kwargs):
+ """OnEndPrinting(self)"""
+ return _windows_.Printout_OnEndPrinting(*args, **kwargs)
+
+ def OnPreparePrinting(*args, **kwargs):
+ """OnPreparePrinting(self)"""
+ return _windows_.Printout_OnPreparePrinting(*args, **kwargs)
+
+ def HasPage(*args, **kwargs):
+ """HasPage(self, int page) -> bool"""
+ return _windows_.Printout_HasPage(*args, **kwargs)
+
+ def GetPageInfo(*args, **kwargs):
+ """GetPageInfo() -> (minPage, maxPage, pageFrom, pageTo)"""
+ return _windows_.Printout_GetPageInfo(*args, **kwargs)
+
+ def base_OnBeginDocument(*args, **kw):
+ return Printout.OnBeginDocument(*args, **kw)
+ base_OnBeginDocument = wx.deprecated(base_OnBeginDocument,
+ "Please use Printout.OnBeginDocument instead.")
+
+ def base_OnEndDocument(*args, **kw):
+ return Printout.OnEndDocument(*args, **kw)
+ base_OnEndDocument = wx.deprecated(base_OnEndDocument,
+ "Please use Printout.OnEndDocument instead.")
+
+ def base_OnBeginPrinting(*args, **kw):
+ return Printout.OnBeginPrinting(*args, **kw)
+ base_OnBeginPrinting = wx.deprecated(base_OnBeginPrinting,
+ "Please use Printout.OnBeginPrinting instead.")
+
+ def base_OnEndPrinting(*args, **kw):
+ return Printout.OnEndPrinting(*args, **kw)
+ base_OnEndPrinting = wx.deprecated(base_OnEndPrinting,
+ "Please use Printout.OnEndPrinting instead.")
+
+ def base_OnPreparePrinting(*args, **kw):
+ return Printout.OnPreparePrinting(*args, **kw)
+ base_OnPreparePrinting = wx.deprecated(base_OnPreparePrinting,
+ "Please use Printout.OnPreparePrinting instead.")
+
+ def base_GetPageInfo(*args, **kw):
+ return Printout.GetPageInfo(*args, **kw)
+ base_GetPageInfo = wx.deprecated(base_GetPageInfo,
+ "Please use Printout.GetPageInfo instead.")
+
+ DC = property(GetDC,SetDC,doc="See `GetDC` and `SetDC`")
+ PPIPrinter = property(GetPPIPrinter,SetPPIPrinter,doc="See `GetPPIPrinter` and `SetPPIPrinter`")
+ PPIScreen = property(GetPPIScreen,SetPPIScreen,doc="See `GetPPIScreen` and `SetPPIScreen`")
+ PageSizeMM = property(GetPageSizeMM,SetPageSizeMM,doc="See `GetPageSizeMM` and `SetPageSizeMM`")
+ PageSizePixels = property(GetPageSizePixels,SetPageSizePixels,doc="See `GetPageSizePixels` and `SetPageSizePixels`")
+ Title = property(GetTitle,doc="See `GetTitle`")
+_windows_.Printout_swigregister(Printout)
+
+class PreviewCanvas(ScrolledWindow):
+ """Proxy of C++ PreviewCanvas class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, PrintPreview preview, Window parent, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0,
+ String name=PreviewCanvasNameStr) -> PreviewCanvas
+ """
+ _windows_.PreviewCanvas_swiginit(self,_windows_.new_PreviewCanvas(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def SetPreview(*args, **kwargs):
+ """SetPreview(self, wxPrintPreviewBase preview)"""
+ return _windows_.PreviewCanvas_SetPreview(*args, **kwargs)
+
+_windows_.PreviewCanvas_swigregister(PreviewCanvas)
+
+class PreviewFrame(Frame):
+ """Proxy of C++ PreviewFrame class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, PrintPreview preview, Frame parent, String title, Point pos=DefaultPosition,
+ Size size=DefaultSize,
+ long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> PreviewFrame
+ """
+ _windows_.PreviewFrame_swiginit(self,_windows_.new_PreviewFrame(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Initialize(*args, **kwargs):
+ """Initialize(self)"""
+ return _windows_.PreviewFrame_Initialize(*args, **kwargs)
+
+ def InitializeWithModality(*args, **kwargs):
+ """InitializeWithModality(self, int kind)"""
+ return _windows_.PreviewFrame_InitializeWithModality(*args, **kwargs)
+
+ def CreateControlBar(*args, **kwargs):
+ """CreateControlBar(self)"""
+ return _windows_.PreviewFrame_CreateControlBar(*args, **kwargs)
+
+ def CreateCanvas(*args, **kwargs):
+ """CreateCanvas(self)"""
+ return _windows_.PreviewFrame_CreateCanvas(*args, **kwargs)
+
+ def GetControlBar(*args, **kwargs):
+ """GetControlBar(self) -> PreviewControlBar"""
+ return _windows_.PreviewFrame_GetControlBar(*args, **kwargs)
+
+ ControlBar = property(GetControlBar,doc="See `GetControlBar`")
+_windows_.PreviewFrame_swigregister(PreviewFrame)
+
+PREVIEW_PRINT = _windows_.PREVIEW_PRINT
+PREVIEW_PREVIOUS = _windows_.PREVIEW_PREVIOUS
+PREVIEW_NEXT = _windows_.PREVIEW_NEXT
+PREVIEW_ZOOM = _windows_.PREVIEW_ZOOM
+PREVIEW_FIRST = _windows_.PREVIEW_FIRST
+PREVIEW_LAST = _windows_.PREVIEW_LAST
+PREVIEW_GOTO = _windows_.PREVIEW_GOTO
+PREVIEW_DEFAULT = _windows_.PREVIEW_DEFAULT
+ID_PREVIEW_CLOSE = _windows_.ID_PREVIEW_CLOSE
+ID_PREVIEW_NEXT = _windows_.ID_PREVIEW_NEXT
+ID_PREVIEW_PREVIOUS = _windows_.ID_PREVIEW_PREVIOUS
+ID_PREVIEW_PRINT = _windows_.ID_PREVIEW_PRINT
+ID_PREVIEW_ZOOM = _windows_.ID_PREVIEW_ZOOM
+ID_PREVIEW_FIRST = _windows_.ID_PREVIEW_FIRST
+ID_PREVIEW_LAST = _windows_.ID_PREVIEW_LAST
+ID_PREVIEW_GOTO = _windows_.ID_PREVIEW_GOTO
+class PreviewControlBar(Panel):
+ """Proxy of C++ PreviewControlBar class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, PrintPreview preview, long buttons, Window parent,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=TAB_TRAVERSAL, String name=PanelNameStr) -> PreviewControlBar
+ """
+ _windows_.PreviewControlBar_swiginit(self,_windows_.new_PreviewControlBar(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def SetPageInfo(*args, **kwargs):
+ """SetPageInfo(self, int minPage, int maxPage)"""
+ return _windows_.PreviewControlBar_SetPageInfo(*args, **kwargs)
+
+ def GetZoomControl(*args, **kwargs):
+ """GetZoomControl(self) -> int"""
+ return _windows_.PreviewControlBar_GetZoomControl(*args, **kwargs)
+
+ def SetZoomControl(*args, **kwargs):
+ """SetZoomControl(self, int zoom)"""
+ return _windows_.PreviewControlBar_SetZoomControl(*args, **kwargs)
+
+ def GetPrintPreview(*args, **kwargs):
+ """GetPrintPreview(self) -> PrintPreview"""
+ return _windows_.PreviewControlBar_GetPrintPreview(*args, **kwargs)
+
+ PrintPreview = property(GetPrintPreview,doc="See `GetPrintPreview`")
+ ZoomControl = property(GetZoomControl,SetZoomControl,doc="See `GetZoomControl` and `SetZoomControl`")
+_windows_.PreviewControlBar_swigregister(PreviewControlBar)
+
+class PrintPreview(_core.Object):
+ """Proxy of C++ PrintPreview class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, Printout printout, Printout printoutForPrinting, PrintDialogData data=None) -> PrintPreview
+ __init__(self, Printout printout, Printout printoutForPrinting, PrintData data) -> PrintPreview
+ """
+ _windows_.PrintPreview_swiginit(self,_windows_.new_PrintPreview(*args))
+ __swig_destroy__ = _windows_.delete_PrintPreview
+ __del__ = lambda self : None;
+ def SetCurrentPage(*args, **kwargs):
+ """SetCurrentPage(self, int pageNum) -> bool"""
+ return _windows_.PrintPreview_SetCurrentPage(*args, **kwargs)
+
+ def GetCurrentPage(*args, **kwargs):
+ """GetCurrentPage(self) -> int"""
+ return _windows_.PrintPreview_GetCurrentPage(*args, **kwargs)
+
+ def SetPrintout(*args, **kwargs):
+ """SetPrintout(self, Printout printout)"""
+ return _windows_.PrintPreview_SetPrintout(*args, **kwargs)
+
+ def GetPrintout(*args, **kwargs):
+ """GetPrintout(self) -> Printout"""
+ return _windows_.PrintPreview_GetPrintout(*args, **kwargs)
+
+ def GetPrintoutForPrinting(*args, **kwargs):
+ """GetPrintoutForPrinting(self) -> Printout"""
+ return _windows_.PrintPreview_GetPrintoutForPrinting(*args, **kwargs)
+
+ def SetFrame(*args, **kwargs):
+ """SetFrame(self, Frame frame)"""
+ return _windows_.PrintPreview_SetFrame(*args, **kwargs)
+
+ def SetCanvas(*args, **kwargs):
+ """SetCanvas(self, PreviewCanvas canvas)"""
+ return _windows_.PrintPreview_SetCanvas(*args, **kwargs)
+
+ def GetFrame(*args, **kwargs):
+ """GetFrame(self) -> Frame"""
+ return _windows_.PrintPreview_GetFrame(*args, **kwargs)
+
+ def GetCanvas(*args, **kwargs):
+ """GetCanvas(self) -> PreviewCanvas"""
+ return _windows_.PrintPreview_GetCanvas(*args, **kwargs)
+
+ def PaintPage(*args, **kwargs):
+ """PaintPage(self, PreviewCanvas canvas, DC dc) -> bool"""
+ return _windows_.PrintPreview_PaintPage(*args, **kwargs)
+
+ def UpdatePageRendering(*args, **kwargs):
+ """UpdatePageRendering(self) -> bool"""
+ return _windows_.PrintPreview_UpdatePageRendering(*args, **kwargs)
+
+ def DrawBlankPage(*args, **kwargs):
+ """DrawBlankPage(self, PreviewCanvas canvas, DC dc) -> bool"""
+ return _windows_.PrintPreview_DrawBlankPage(*args, **kwargs)
+
+ def RenderPage(*args, **kwargs):
+ """RenderPage(self, int pageNum) -> bool"""
+ return _windows_.PrintPreview_RenderPage(*args, **kwargs)
+
+ def AdjustScrollbars(*args, **kwargs):
+ """AdjustScrollbars(self, PreviewCanvas canvas)"""
+ return _windows_.PrintPreview_AdjustScrollbars(*args, **kwargs)
+
+ def GetPrintDialogData(*args, **kwargs):
+ """GetPrintDialogData(self) -> PrintDialogData"""
+ return _windows_.PrintPreview_GetPrintDialogData(*args, **kwargs)
+
+ def SetZoom(*args, **kwargs):
+ """SetZoom(self, int percent)"""
+ return _windows_.PrintPreview_SetZoom(*args, **kwargs)
+
+ def GetZoom(*args, **kwargs):
+ """GetZoom(self) -> int"""
+ return _windows_.PrintPreview_GetZoom(*args, **kwargs)
+
+ def GetMaxPage(*args, **kwargs):
+ """GetMaxPage(self) -> int"""
+ return _windows_.PrintPreview_GetMaxPage(*args, **kwargs)
+
+ def GetMinPage(*args, **kwargs):
+ """GetMinPage(self) -> int"""
+ return _windows_.PrintPreview_GetMinPage(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _windows_.PrintPreview_IsOk(*args, **kwargs)
+
+ Ok = IsOk
+ def SetOk(*args, **kwargs):
+ """SetOk(self, bool ok)"""
+ return _windows_.PrintPreview_SetOk(*args, **kwargs)
+
+ def Print(*args, **kwargs):
+ """Print(self, bool interactive) -> bool"""
+ return _windows_.PrintPreview_Print(*args, **kwargs)
+
+ def DetermineScaling(*args, **kwargs):
+ """DetermineScaling(self)"""
+ return _windows_.PrintPreview_DetermineScaling(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ Canvas = property(GetCanvas,SetCanvas,doc="See `GetCanvas` and `SetCanvas`")
+ CurrentPage = property(GetCurrentPage,SetCurrentPage,doc="See `GetCurrentPage` and `SetCurrentPage`")
+ Frame = property(GetFrame,SetFrame,doc="See `GetFrame` and `SetFrame`")
+ MaxPage = property(GetMaxPage,doc="See `GetMaxPage`")
+ MinPage = property(GetMinPage,doc="See `GetMinPage`")
+ PrintDialogData = property(GetPrintDialogData,doc="See `GetPrintDialogData`")
+ Printout = property(GetPrintout,SetPrintout,doc="See `GetPrintout` and `SetPrintout`")
+ PrintoutForPrinting = property(GetPrintoutForPrinting,doc="See `GetPrintoutForPrinting`")
+ Zoom = property(GetZoom,SetZoom,doc="See `GetZoom` and `SetZoom`")
+_windows_.PrintPreview_swigregister(PrintPreview)
+
+class PyPrintPreview(PrintPreview):
+ """Proxy of C++ PyPrintPreview class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, Printout printout, Printout printoutForPrinting, PrintDialogData data=None) -> PyPrintPreview
+ __init__(self, Printout printout, Printout printoutForPrinting, PrintData data) -> PyPrintPreview
+ """
+ _windows_.PyPrintPreview_swiginit(self,_windows_.new_PyPrintPreview(*args))
+ PyPrintPreview._setCallbackInfo(self, self, PyPrintPreview)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.PyPrintPreview__setCallbackInfo(*args, **kwargs)
+
+ def base_SetCurrentPage(*args, **kw):
+ return PyPrintPreview.SetCurrentPage(*args, **kw)
+ base_SetCurrentPage = wx.deprecated(base_SetCurrentPage,
+ "Please use PyPrintPreview.SetCurrentPage instead.")
+
+ def base_PaintPage(*args, **kw):
+ return PyPrintPreview.PaintPage(*args, **kw)
+ base_PaintPage = wx.deprecated(base_PaintPage,
+ "Please use PyPrintPreview.PaintPage instead.")
+
+ def base_DrawBlankPage(*args, **kw):
+ return PyPrintPreview.DrawBlankPage(*args, **kw)
+ base_DrawBlankPage = wx.deprecated(base_DrawBlankPage,
+ "Please use PyPrintPreview.DrawBlankPage instead.")
+
+ def base_RenderPage(*args, **kw):
+ return PyPrintPreview.RenderPage(*args, **kw)
+ base_RenderPage = wx.deprecated(base_RenderPage,
+ "Please use PyPrintPreview.RenderPage instead.")
+
+ def base_SetZoom(*args, **kw):
+ return PyPrintPreview.SetZoom(*args, **kw)
+ base_SetZoom = wx.deprecated(base_SetZoom,
+ "Please use PyPrintPreview.SetZoom instead.")
+
+ def base_Print(*args, **kw):
+ return PyPrintPreview.Print(*args, **kw)
+ base_Print = wx.deprecated(base_Print,
+ "Please use PyPrintPreview.Print instead.")
+
+ def base_DetermineScaling(*args, **kw):
+ return PyPrintPreview.DetermineScaling(*args, **kw)
+ base_DetermineScaling = wx.deprecated(base_DetermineScaling,
+ "Please use PyPrintPreview.DetermineScaling instead.")
+
+_windows_.PyPrintPreview_swigregister(PyPrintPreview)
+
+class PyPreviewFrame(PreviewFrame):
+ """Proxy of C++ PyPreviewFrame class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, PrintPreview preview, Frame parent, String title, Point pos=DefaultPosition,
+ Size size=DefaultSize,
+ long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> PyPreviewFrame
+ """
+ _windows_.PyPreviewFrame_swiginit(self,_windows_.new_PyPreviewFrame(*args, **kwargs))
+ self._setOORInfo(self);PyPreviewFrame._setCallbackInfo(self, self, PyPreviewFrame)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.PyPreviewFrame__setCallbackInfo(*args, **kwargs)
+
+ def SetPreviewCanvas(*args, **kwargs):
+ """SetPreviewCanvas(self, PreviewCanvas canvas)"""
+ return _windows_.PyPreviewFrame_SetPreviewCanvas(*args, **kwargs)
+
+ def SetControlBar(*args, **kwargs):
+ """SetControlBar(self, PreviewControlBar bar)"""
+ return _windows_.PyPreviewFrame_SetControlBar(*args, **kwargs)
+
+ def Initialize(*args, **kwargs):
+ """Initialize(self)"""
+ return _windows_.PyPreviewFrame_Initialize(*args, **kwargs)
+
+ def InitializeWithModality(*args, **kwargs):
+ """InitializeWithModality(self, int kind)"""
+ return _windows_.PyPreviewFrame_InitializeWithModality(*args, **kwargs)
+
+ def CreateCanvas(*args, **kwargs):
+ """CreateCanvas(self)"""
+ return _windows_.PyPreviewFrame_CreateCanvas(*args, **kwargs)
+
+ def CreateControlBar(*args, **kwargs):
+ """CreateControlBar(self)"""
+ return _windows_.PyPreviewFrame_CreateControlBar(*args, **kwargs)
+
+ def base_Initialize(*args, **kw):
+ return PyPreviewFrame.Initialize(*args, **kw)
+ base_Initialize = wx.deprecated(base_Initialize,
+ "Please use PyPreviewFrame.Initialize instead.")
+
+ def base_CreateCanvas(*args, **kw):
+ return PyPreviewFrame.CreateCanvas(*args, **kw)
+ base_CreateCanvas = wx.deprecated(base_CreateCanvas,
+ "Please use PyPreviewFrame.CreateCanvas instead.")
+
+ def base_CreateControlBar(*args, **kw):
+ return PyPreviewFrame.CreateControlBar(*args, **kw)
+ base_CreateControlBar = wx.deprecated(base_CreateControlBar,
+ "Please use PyPreviewFrame.CreateControlBar instead.")
+
+_windows_.PyPreviewFrame_swigregister(PyPreviewFrame)
+
+class PyPreviewControlBar(PreviewControlBar):
+ """Proxy of C++ PyPreviewControlBar class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, PrintPreview preview, long buttons, Window parent,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=PanelNameStr) -> PyPreviewControlBar
+ """
+ _windows_.PyPreviewControlBar_swiginit(self,_windows_.new_PyPreviewControlBar(*args, **kwargs))
+ self._setOORInfo(self);PyPreviewControlBar._setCallbackInfo(self, self, PyPreviewControlBar)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _windows_.PyPreviewControlBar__setCallbackInfo(*args, **kwargs)
+
+ def SetPrintPreview(*args, **kwargs):
+ """SetPrintPreview(self, PrintPreview preview)"""
+ return _windows_.PyPreviewControlBar_SetPrintPreview(*args, **kwargs)
+
+ def CreateButtons(*args, **kwargs):
+ """CreateButtons(self)"""
+ return _windows_.PyPreviewControlBar_CreateButtons(*args, **kwargs)
+
+ def SetZoomControl(*args, **kwargs):
+ """SetZoomControl(self, int zoom)"""
+ return _windows_.PyPreviewControlBar_SetZoomControl(*args, **kwargs)
+
+ def base_CreateButtons(*args, **kw):
+ return PreviewControlBar.CreateButtons(*args, **kw)
+ base_CreateButtons = wx.deprecated(base_CreateButtons,
+ "Please use PreviewControlBar.CreateButtons instead.")
+
+ def base_SetZoomControl(*args, **kw):
+ return PreviewControlBar.SetZoomControl(*args, **kw)
+ base_SetZoomControl = wx.deprecated(base_SetZoomControl,
+ "Please use PreviewControlBar.SetZoomControl instead.")
+
+_windows_.PyPreviewControlBar_swigregister(PyPreviewControlBar)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_windows_.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_windows_.pyd
new file mode 100644
index 0000000..f8003ea
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_windows_.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_wizard.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_wizard.pyd
new file mode 100644
index 0000000..561be53
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_wizard.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/_xrc.pyd b/lib/python2.7/site-packages/wx-3.0-msw/wx/_xrc.pyd
new file mode 100644
index 0000000..98aa6ca
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/_xrc.pyd
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/animate.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/animate.py
new file mode 100644
index 0000000..19ed6f3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/animate.py
@@ -0,0 +1,251 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+Simple animation player classes, including `GIFAnimationCtrl` for displaying
+animated GIF files
+
+"""
+
+import _animate
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+import wx
+__docfilter__ = wx._core.__DocFilter(globals())
+ANIM_UNSPECIFIED = _animate.ANIM_UNSPECIFIED
+ANIM_DONOTREMOVE = _animate.ANIM_DONOTREMOVE
+ANIM_TOBACKGROUND = _animate.ANIM_TOBACKGROUND
+ANIM_TOPREVIOUS = _animate.ANIM_TOPREVIOUS
+ANIMATION_TYPE_INVALID = _animate.ANIMATION_TYPE_INVALID
+ANIMATION_TYPE_GIF = _animate.ANIMATION_TYPE_GIF
+ANIMATION_TYPE_ANI = _animate.ANIMATION_TYPE_ANI
+ANIMATION_TYPE_ANY = _animate.ANIMATION_TYPE_ANY
+class AnimationBase(_core.Object):
+ """Proxy of C++ AnimationBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _animate.delete_AnimationBase
+ __del__ = lambda self : None;
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _animate.AnimationBase_IsOk(*args, **kwargs)
+
+ def GetDelay(*args, **kwargs):
+ """GetDelay(self, int i) -> int"""
+ return _animate.AnimationBase_GetDelay(*args, **kwargs)
+
+ def GetFrameCount(*args, **kwargs):
+ """GetFrameCount(self) -> int"""
+ return _animate.AnimationBase_GetFrameCount(*args, **kwargs)
+
+ def GetFrame(*args, **kwargs):
+ """GetFrame(self, int i) -> Image"""
+ return _animate.AnimationBase_GetFrame(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(self) -> Size"""
+ return _animate.AnimationBase_GetSize(*args, **kwargs)
+
+ def LoadFile(*args, **kwargs):
+ """LoadFile(self, String name, int type=ANIMATION_TYPE_ANY) -> bool"""
+ return _animate.AnimationBase_LoadFile(*args, **kwargs)
+
+ def Load(*args, **kwargs):
+ """Load(self, InputStream stream, int type=ANIMATION_TYPE_ANY) -> bool"""
+ return _animate.AnimationBase_Load(*args, **kwargs)
+
+_animate.AnimationBase_swigregister(AnimationBase)
+cvar = _animate.cvar
+AnimationCtrlNameStr = cvar.AnimationCtrlNameStr
+
+class Animation(AnimationBase):
+ """Proxy of C++ Animation class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> Animation
+ __init__(self, String name, int type=ANIMATION_TYPE_ANY) -> Animation
+ """
+ _animate.Animation_swiginit(self,_animate.new_Animation(*args))
+ __swig_destroy__ = _animate.delete_Animation
+ __del__ = lambda self : None;
+ def GetFramePosition(*args, **kwargs):
+ """GetFramePosition(self, int frame) -> Point"""
+ return _animate.Animation_GetFramePosition(*args, **kwargs)
+
+ def GetFrameSize(*args, **kwargs):
+ """GetFrameSize(self, int frame) -> Size"""
+ return _animate.Animation_GetFrameSize(*args, **kwargs)
+
+ def GetDisposalMethod(*args, **kwargs):
+ """GetDisposalMethod(self, int frame) -> int"""
+ return _animate.Animation_GetDisposalMethod(*args, **kwargs)
+
+ def GetTransparentColour(*args, **kwargs):
+ """GetTransparentColour(self, int frame) -> Colour"""
+ return _animate.Animation_GetTransparentColour(*args, **kwargs)
+
+ def GetBackgroundColour(*args, **kwargs):
+ """GetBackgroundColour(self) -> Colour"""
+ return _animate.Animation_GetBackgroundColour(*args, **kwargs)
+
+_animate.Animation_swigregister(Animation)
+
+AC_NO_AUTORESIZE = _animate.AC_NO_AUTORESIZE
+AC_DEFAULT_STYLE = _animate.AC_DEFAULT_STYLE
+AN_FIT_ANIMATION = _animate.AN_FIT_ANIMATION
+class AnimationCtrlBase(_core.Control):
+ """Proxy of C++ AnimationCtrlBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def LoadFile(*args, **kwargs):
+ """LoadFile(self, String filename, int type=ANIMATION_TYPE_ANY) -> bool"""
+ return _animate.AnimationCtrlBase_LoadFile(*args, **kwargs)
+
+ def SetAnimation(*args, **kwargs):
+ """SetAnimation(self, Animation anim)"""
+ return _animate.AnimationCtrlBase_SetAnimation(*args, **kwargs)
+
+ def GetAnimation(*args, **kwargs):
+ """GetAnimation(self) -> Animation"""
+ return _animate.AnimationCtrlBase_GetAnimation(*args, **kwargs)
+
+ Animation = property(GetAnimation,SetAnimation)
+ def Play(*args, **kwargs):
+ """Play(self) -> bool"""
+ return _animate.AnimationCtrlBase_Play(*args, **kwargs)
+
+ def Stop(*args, **kwargs):
+ """Stop(self)"""
+ return _animate.AnimationCtrlBase_Stop(*args, **kwargs)
+
+ def IsPlaying(*args, **kwargs):
+ """IsPlaying(self) -> bool"""
+ return _animate.AnimationCtrlBase_IsPlaying(*args, **kwargs)
+
+ def SetInactiveBitmap(*args, **kwargs):
+ """SetInactiveBitmap(self, Bitmap bmp)"""
+ return _animate.AnimationCtrlBase_SetInactiveBitmap(*args, **kwargs)
+
+ def GetInactiveBitmap(*args, **kwargs):
+ """GetInactiveBitmap(self) -> Bitmap"""
+ return _animate.AnimationCtrlBase_GetInactiveBitmap(*args, **kwargs)
+
+ InactiveBitmap = property(GetInactiveBitmap,SetInactiveBitmap)
+_animate.AnimationCtrlBase_swigregister(AnimationCtrlBase)
+NullAnimation = cvar.NullAnimation
+
+class AnimationCtrl(AnimationCtrlBase):
+ """Proxy of C++ AnimationCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Animation anim=NullAnimation,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=AC_DEFAULT_STYLE, String name=AnimationCtrlNameStr) -> AnimationCtrl
+ """
+ _animate.AnimationCtrl_swiginit(self,_animate.new_AnimationCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id, Animation anim=NullAnimation,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=AC_DEFAULT_STYLE, String name=AnimationCtrlNameStr) -> bool
+ """
+ return _animate.AnimationCtrl_Create(*args, **kwargs)
+
+ def SetUseWindowBackgroundColour(*args, **kwargs):
+ """SetUseWindowBackgroundColour(self, bool useWinBackground=True)"""
+ return _animate.AnimationCtrl_SetUseWindowBackgroundColour(*args, **kwargs)
+
+ def IsUsingWindowBackgroundColour(*args, **kwargs):
+ """IsUsingWindowBackgroundColour(self) -> bool"""
+ return _animate.AnimationCtrl_IsUsingWindowBackgroundColour(*args, **kwargs)
+
+ def DrawCurrentFrame(*args, **kwargs):
+ """DrawCurrentFrame(self, DC dc)"""
+ return _animate.AnimationCtrl_DrawCurrentFrame(*args, **kwargs)
+
+ def GetBackingStore(*args, **kwargs):
+ """GetBackingStore(self) -> Bitmap"""
+ return _animate.AnimationCtrl_GetBackingStore(*args, **kwargs)
+
+_animate.AnimationCtrl_swigregister(AnimationCtrl)
+
+def PreAnimationCtrl(*args, **kwargs):
+ """PreAnimationCtrl() -> AnimationCtrl"""
+ val = _animate.new_PreAnimationCtrl(*args, **kwargs)
+ return val
+
+class GIFAnimationCtrl(AnimationCtrl):
+ """
+ Backwards compatibility class for AnimationCtrl.
+ """
+ def __init__(self, parent, id=-1, filename="",
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=AC_DEFAULT_STYLE,
+ name="gifAnimation"):
+ AnimationCtrl.__init__(self, parent, id, NullAnimation, pos, size, style, name)
+ self.LoadFile(filename)
+
+ def GetPlayer(self):
+ return self
+
+ def UseBackgroundColour(self, useBackground=True):
+ self.SetUseWindowBackgroundColour(useBackground)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/aui.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/aui.py
new file mode 100644
index 0000000..a3cdcf0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/aui.py
@@ -0,0 +1,2454 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+The wx.aui module is an Advanced User Interface library that aims to
+implement "cutting-edge" interface usability and design features so
+developers can quickly and easily create beautiful and usable
+application interfaces.
+
+**Vision and Design Principles**
+
+wx.aui attempts to encapsulate the following aspects of the user
+interface:
+
+ * Frame Management: Frame management provides the means to open,
+ move and hide common controls that are needed to interact with the
+ document, and allow these configurations to be saved into
+ different perspectives and loaded at a later time.
+
+ * Toolbars: Toolbars are a specialized subset of the frame
+ management system and should behave similarly to other docked
+ components. However, they also require additional functionality,
+ such as "spring-loaded" rebar support, "chevron" buttons and
+ end-user customizability.
+
+ * Modeless Controls: Modeless controls expose a tool palette or set
+ of options that float above the application content while allowing
+ it to be accessed. Usually accessed by the toolbar, these controls
+ disappear when an option is selected, but may also be "torn off"
+ the toolbar into a floating frame of their own.
+
+ * Look and Feel: Look and feel encompasses the way controls are
+ drawn, both when shown statically as well as when they are being
+ moved. This aspect of user interface design incorporates "special
+ effects" such as transparent window dragging as well as frame
+ animation.
+
+**wx.aui adheres to the following principles**
+
+ - Use native floating frames to obtain a native look and feel for
+ all platforms;
+
+ - Use existing wxPython code where possible, such as sizer
+ implementation for frame management;
+
+ - Use standard wxPython coding conventions.
+
+
+**Usage**
+
+The following example shows a simple implementation that utilizes
+`wx.aui.AuiManager` to manage three text controls in a frame window::
+
+ import wx
+ import wx.aui
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent, id=-1, title='wx.aui Test',
+ pos=wx.DefaultPosition, size=(800, 600),
+ style=wx.DEFAULT_FRAME_STYLE):
+ wx.Frame.__init__(self, parent, id, title, pos, size, style)
+
+ self._mgr = wx.aui.AuiManager(self)
+
+ # create several text controls
+ text1 = wx.TextCtrl(self, -1, 'Pane 1 - sample text',
+ wx.DefaultPosition, wx.Size(200,150),
+ wx.NO_BORDER | wx.TE_MULTILINE)
+
+ text2 = wx.TextCtrl(self, -1, 'Pane 2 - sample text',
+ wx.DefaultPosition, wx.Size(200,150),
+ wx.NO_BORDER | wx.TE_MULTILINE)
+
+ text3 = wx.TextCtrl(self, -1, 'Main content window',
+ wx.DefaultPosition, wx.Size(200,150),
+ wx.NO_BORDER | wx.TE_MULTILINE)
+
+ # add the panes to the manager
+ self._mgr.AddPane(text1, wx.LEFT, 'Pane Number One')
+ self._mgr.AddPane(text2, wx.BOTTOM, 'Pane Number Two')
+ self._mgr.AddPane(text3, wx.CENTER)
+
+ # tell the manager to 'commit' all the changes just made
+ self._mgr.Update()
+
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+
+ def OnClose(self, event):
+ # deinitialize the frame manager
+ self._mgr.UnInit()
+ # delete the frame
+ self.Destroy()
+
+
+ app = wx.App()
+ frame = MyFrame(None)
+ frame.Show()
+ app.MainLoop()
+
+"""
+
+import _aui
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+import _windows
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+class wxNavigationEnabled_BookCtrlBase(_core.BookCtrlBase):
+ """Proxy of C++ wxNavigationEnabled_BookCtrlBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+_aui.wxNavigationEnabled_BookCtrlBase_swigregister(wxNavigationEnabled_BookCtrlBase)
+
+AUI_DOCK_NONE = _aui.AUI_DOCK_NONE
+AUI_DOCK_TOP = _aui.AUI_DOCK_TOP
+AUI_DOCK_RIGHT = _aui.AUI_DOCK_RIGHT
+AUI_DOCK_BOTTOM = _aui.AUI_DOCK_BOTTOM
+AUI_DOCK_LEFT = _aui.AUI_DOCK_LEFT
+AUI_DOCK_CENTER = _aui.AUI_DOCK_CENTER
+AUI_DOCK_CENTRE = _aui.AUI_DOCK_CENTRE
+AUI_MGR_ALLOW_FLOATING = _aui.AUI_MGR_ALLOW_FLOATING
+AUI_MGR_ALLOW_ACTIVE_PANE = _aui.AUI_MGR_ALLOW_ACTIVE_PANE
+AUI_MGR_TRANSPARENT_DRAG = _aui.AUI_MGR_TRANSPARENT_DRAG
+AUI_MGR_TRANSPARENT_HINT = _aui.AUI_MGR_TRANSPARENT_HINT
+AUI_MGR_VENETIAN_BLINDS_HINT = _aui.AUI_MGR_VENETIAN_BLINDS_HINT
+AUI_MGR_RECTANGLE_HINT = _aui.AUI_MGR_RECTANGLE_HINT
+AUI_MGR_HINT_FADE = _aui.AUI_MGR_HINT_FADE
+AUI_MGR_NO_VENETIAN_BLINDS_FADE = _aui.AUI_MGR_NO_VENETIAN_BLINDS_FADE
+AUI_MGR_LIVE_RESIZE = _aui.AUI_MGR_LIVE_RESIZE
+AUI_MGR_DEFAULT = _aui.AUI_MGR_DEFAULT
+AUI_DOCKART_SASH_SIZE = _aui.AUI_DOCKART_SASH_SIZE
+AUI_DOCKART_CAPTION_SIZE = _aui.AUI_DOCKART_CAPTION_SIZE
+AUI_DOCKART_GRIPPER_SIZE = _aui.AUI_DOCKART_GRIPPER_SIZE
+AUI_DOCKART_PANE_BORDER_SIZE = _aui.AUI_DOCKART_PANE_BORDER_SIZE
+AUI_DOCKART_PANE_BUTTON_SIZE = _aui.AUI_DOCKART_PANE_BUTTON_SIZE
+AUI_DOCKART_BACKGROUND_COLOUR = _aui.AUI_DOCKART_BACKGROUND_COLOUR
+AUI_DOCKART_SASH_COLOUR = _aui.AUI_DOCKART_SASH_COLOUR
+AUI_DOCKART_ACTIVE_CAPTION_COLOUR = _aui.AUI_DOCKART_ACTIVE_CAPTION_COLOUR
+AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR = _aui.AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR
+AUI_DOCKART_INACTIVE_CAPTION_COLOUR = _aui.AUI_DOCKART_INACTIVE_CAPTION_COLOUR
+AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR = _aui.AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR
+AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR = _aui.AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR
+AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR = _aui.AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR
+AUI_DOCKART_BORDER_COLOUR = _aui.AUI_DOCKART_BORDER_COLOUR
+AUI_DOCKART_GRIPPER_COLOUR = _aui.AUI_DOCKART_GRIPPER_COLOUR
+AUI_DOCKART_CAPTION_FONT = _aui.AUI_DOCKART_CAPTION_FONT
+AUI_DOCKART_GRADIENT_TYPE = _aui.AUI_DOCKART_GRADIENT_TYPE
+AUI_GRADIENT_NONE = _aui.AUI_GRADIENT_NONE
+AUI_GRADIENT_VERTICAL = _aui.AUI_GRADIENT_VERTICAL
+AUI_GRADIENT_HORIZONTAL = _aui.AUI_GRADIENT_HORIZONTAL
+AUI_BUTTON_STATE_NORMAL = _aui.AUI_BUTTON_STATE_NORMAL
+AUI_BUTTON_STATE_HOVER = _aui.AUI_BUTTON_STATE_HOVER
+AUI_BUTTON_STATE_PRESSED = _aui.AUI_BUTTON_STATE_PRESSED
+AUI_BUTTON_STATE_DISABLED = _aui.AUI_BUTTON_STATE_DISABLED
+AUI_BUTTON_STATE_HIDDEN = _aui.AUI_BUTTON_STATE_HIDDEN
+AUI_BUTTON_STATE_CHECKED = _aui.AUI_BUTTON_STATE_CHECKED
+AUI_BUTTON_CLOSE = _aui.AUI_BUTTON_CLOSE
+AUI_BUTTON_MAXIMIZE_RESTORE = _aui.AUI_BUTTON_MAXIMIZE_RESTORE
+AUI_BUTTON_MINIMIZE = _aui.AUI_BUTTON_MINIMIZE
+AUI_BUTTON_PIN = _aui.AUI_BUTTON_PIN
+AUI_BUTTON_OPTIONS = _aui.AUI_BUTTON_OPTIONS
+AUI_BUTTON_WINDOWLIST = _aui.AUI_BUTTON_WINDOWLIST
+AUI_BUTTON_LEFT = _aui.AUI_BUTTON_LEFT
+AUI_BUTTON_RIGHT = _aui.AUI_BUTTON_RIGHT
+AUI_BUTTON_UP = _aui.AUI_BUTTON_UP
+AUI_BUTTON_DOWN = _aui.AUI_BUTTON_DOWN
+AUI_BUTTON_CUSTOM1 = _aui.AUI_BUTTON_CUSTOM1
+AUI_BUTTON_CUSTOM2 = _aui.AUI_BUTTON_CUSTOM2
+AUI_BUTTON_CUSTOM3 = _aui.AUI_BUTTON_CUSTOM3
+AUI_INSERT_PANE = _aui.AUI_INSERT_PANE
+AUI_INSERT_ROW = _aui.AUI_INSERT_ROW
+AUI_INSERT_DOCK = _aui.AUI_INSERT_DOCK
+class AuiPaneInfo(object):
+ """Proxy of C++ AuiPaneInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> AuiPaneInfo"""
+ _aui.AuiPaneInfo_swiginit(self,_aui.new_AuiPaneInfo(*args, **kwargs))
+ __swig_destroy__ = _aui.delete_AuiPaneInfo
+ __del__ = lambda self : None;
+ def SafeSet(*args, **kwargs):
+ """SafeSet(self, AuiPaneInfo source)"""
+ return _aui.AuiPaneInfo_SafeSet(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _aui.AuiPaneInfo_IsOk(*args, **kwargs)
+
+ def IsFixed(*args, **kwargs):
+ """IsFixed(self) -> bool"""
+ return _aui.AuiPaneInfo_IsFixed(*args, **kwargs)
+
+ def IsResizable(*args, **kwargs):
+ """IsResizable(self) -> bool"""
+ return _aui.AuiPaneInfo_IsResizable(*args, **kwargs)
+
+ def IsShown(*args, **kwargs):
+ """IsShown(self) -> bool"""
+ return _aui.AuiPaneInfo_IsShown(*args, **kwargs)
+
+ def IsFloating(*args, **kwargs):
+ """IsFloating(self) -> bool"""
+ return _aui.AuiPaneInfo_IsFloating(*args, **kwargs)
+
+ def IsDocked(*args, **kwargs):
+ """IsDocked(self) -> bool"""
+ return _aui.AuiPaneInfo_IsDocked(*args, **kwargs)
+
+ def IsToolbar(*args, **kwargs):
+ """IsToolbar(self) -> bool"""
+ return _aui.AuiPaneInfo_IsToolbar(*args, **kwargs)
+
+ def IsTopDockable(*args, **kwargs):
+ """IsTopDockable(self) -> bool"""
+ return _aui.AuiPaneInfo_IsTopDockable(*args, **kwargs)
+
+ def IsBottomDockable(*args, **kwargs):
+ """IsBottomDockable(self) -> bool"""
+ return _aui.AuiPaneInfo_IsBottomDockable(*args, **kwargs)
+
+ def IsLeftDockable(*args, **kwargs):
+ """IsLeftDockable(self) -> bool"""
+ return _aui.AuiPaneInfo_IsLeftDockable(*args, **kwargs)
+
+ def IsRightDockable(*args, **kwargs):
+ """IsRightDockable(self) -> bool"""
+ return _aui.AuiPaneInfo_IsRightDockable(*args, **kwargs)
+
+ def IsDockable(*args, **kwargs):
+ """IsDockable(self) -> bool"""
+ return _aui.AuiPaneInfo_IsDockable(*args, **kwargs)
+
+ def IsFloatable(*args, **kwargs):
+ """IsFloatable(self) -> bool"""
+ return _aui.AuiPaneInfo_IsFloatable(*args, **kwargs)
+
+ def IsMovable(*args, **kwargs):
+ """IsMovable(self) -> bool"""
+ return _aui.AuiPaneInfo_IsMovable(*args, **kwargs)
+
+ def IsDestroyOnClose(*args, **kwargs):
+ """IsDestroyOnClose(self) -> bool"""
+ return _aui.AuiPaneInfo_IsDestroyOnClose(*args, **kwargs)
+
+ def IsMaximized(*args, **kwargs):
+ """IsMaximized(self) -> bool"""
+ return _aui.AuiPaneInfo_IsMaximized(*args, **kwargs)
+
+ def HasCaption(*args, **kwargs):
+ """HasCaption(self) -> bool"""
+ return _aui.AuiPaneInfo_HasCaption(*args, **kwargs)
+
+ def HasGripper(*args, **kwargs):
+ """HasGripper(self) -> bool"""
+ return _aui.AuiPaneInfo_HasGripper(*args, **kwargs)
+
+ def HasBorder(*args, **kwargs):
+ """HasBorder(self) -> bool"""
+ return _aui.AuiPaneInfo_HasBorder(*args, **kwargs)
+
+ def HasCloseButton(*args, **kwargs):
+ """HasCloseButton(self) -> bool"""
+ return _aui.AuiPaneInfo_HasCloseButton(*args, **kwargs)
+
+ def HasMaximizeButton(*args, **kwargs):
+ """HasMaximizeButton(self) -> bool"""
+ return _aui.AuiPaneInfo_HasMaximizeButton(*args, **kwargs)
+
+ def HasMinimizeButton(*args, **kwargs):
+ """HasMinimizeButton(self) -> bool"""
+ return _aui.AuiPaneInfo_HasMinimizeButton(*args, **kwargs)
+
+ def HasPinButton(*args, **kwargs):
+ """HasPinButton(self) -> bool"""
+ return _aui.AuiPaneInfo_HasPinButton(*args, **kwargs)
+
+ def HasGripperTop(*args, **kwargs):
+ """HasGripperTop(self) -> bool"""
+ return _aui.AuiPaneInfo_HasGripperTop(*args, **kwargs)
+
+ def Window(*args, **kwargs):
+ """Window(self, Window w) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Window(*args, **kwargs)
+
+ def Name(*args, **kwargs):
+ """Name(self, String n) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Name(*args, **kwargs)
+
+ def Caption(*args, **kwargs):
+ """Caption(self, String c) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Caption(*args, **kwargs)
+
+ def Icon(*args, **kwargs):
+ """Icon(self, Bitmap b) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Icon(*args, **kwargs)
+
+ def Left(*args, **kwargs):
+ """Left(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Left(*args, **kwargs)
+
+ def Right(*args, **kwargs):
+ """Right(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Right(*args, **kwargs)
+
+ def Top(*args, **kwargs):
+ """Top(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Top(*args, **kwargs)
+
+ def Bottom(*args, **kwargs):
+ """Bottom(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Bottom(*args, **kwargs)
+
+ def Center(*args, **kwargs):
+ """Center(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Center(*args, **kwargs)
+
+ def Centre(*args, **kwargs):
+ """Centre(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Centre(*args, **kwargs)
+
+ def Direction(*args, **kwargs):
+ """Direction(self, int direction) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Direction(*args, **kwargs)
+
+ def Layer(*args, **kwargs):
+ """Layer(self, int layer) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Layer(*args, **kwargs)
+
+ def Row(*args, **kwargs):
+ """Row(self, int row) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Row(*args, **kwargs)
+
+ def Position(*args, **kwargs):
+ """Position(self, int pos) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Position(*args, **kwargs)
+
+ def BestSize(*args, **kwargs):
+ """BestSize(self, Size size) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_BestSize(*args, **kwargs)
+
+ def MinSize(*args, **kwargs):
+ """MinSize(self, Size size) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_MinSize(*args, **kwargs)
+
+ def MaxSize(*args, **kwargs):
+ """MaxSize(self, Size size) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_MaxSize(*args, **kwargs)
+
+ def FloatingPosition(*args, **kwargs):
+ """FloatingPosition(self, Point pos) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_FloatingPosition(*args, **kwargs)
+
+ def FloatingSize(*args, **kwargs):
+ """FloatingSize(self, Size size) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_FloatingSize(*args, **kwargs)
+
+ def Fixed(*args, **kwargs):
+ """Fixed(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Fixed(*args, **kwargs)
+
+ def Resizable(*args, **kwargs):
+ """Resizable(self, bool resizable=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Resizable(*args, **kwargs)
+
+ def Dock(*args, **kwargs):
+ """Dock(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Dock(*args, **kwargs)
+
+ def Float(*args, **kwargs):
+ """Float(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Float(*args, **kwargs)
+
+ def Hide(*args, **kwargs):
+ """Hide(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Hide(*args, **kwargs)
+
+ def Show(*args, **kwargs):
+ """Show(self, bool show=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Show(*args, **kwargs)
+
+ def CaptionVisible(*args, **kwargs):
+ """CaptionVisible(self, bool visible=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_CaptionVisible(*args, **kwargs)
+
+ def Maximize(*args, **kwargs):
+ """Maximize(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Maximize(*args, **kwargs)
+
+ def Restore(*args, **kwargs):
+ """Restore(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Restore(*args, **kwargs)
+
+ def PaneBorder(*args, **kwargs):
+ """PaneBorder(self, bool visible=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_PaneBorder(*args, **kwargs)
+
+ def Gripper(*args, **kwargs):
+ """Gripper(self, bool visible=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Gripper(*args, **kwargs)
+
+ def GripperTop(*args, **kwargs):
+ """GripperTop(self, bool attop=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_GripperTop(*args, **kwargs)
+
+ def CloseButton(*args, **kwargs):
+ """CloseButton(self, bool visible=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_CloseButton(*args, **kwargs)
+
+ def MaximizeButton(*args, **kwargs):
+ """MaximizeButton(self, bool visible=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_MaximizeButton(*args, **kwargs)
+
+ def MinimizeButton(*args, **kwargs):
+ """MinimizeButton(self, bool visible=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_MinimizeButton(*args, **kwargs)
+
+ def PinButton(*args, **kwargs):
+ """PinButton(self, bool visible=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_PinButton(*args, **kwargs)
+
+ def DestroyOnClose(*args, **kwargs):
+ """DestroyOnClose(self, bool b=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_DestroyOnClose(*args, **kwargs)
+
+ def TopDockable(*args, **kwargs):
+ """TopDockable(self, bool b=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_TopDockable(*args, **kwargs)
+
+ def BottomDockable(*args, **kwargs):
+ """BottomDockable(self, bool b=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_BottomDockable(*args, **kwargs)
+
+ def LeftDockable(*args, **kwargs):
+ """LeftDockable(self, bool b=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_LeftDockable(*args, **kwargs)
+
+ def RightDockable(*args, **kwargs):
+ """RightDockable(self, bool b=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_RightDockable(*args, **kwargs)
+
+ def Floatable(*args, **kwargs):
+ """Floatable(self, bool b=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Floatable(*args, **kwargs)
+
+ def Movable(*args, **kwargs):
+ """Movable(self, bool b=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Movable(*args, **kwargs)
+
+ def DockFixed(*args, **kwargs):
+ """DockFixed(self, bool b=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_DockFixed(*args, **kwargs)
+
+ def Dockable(*args, **kwargs):
+ """Dockable(self, bool b=True) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_Dockable(*args, **kwargs)
+
+ def DefaultPane(*args, **kwargs):
+ """DefaultPane(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_DefaultPane(*args, **kwargs)
+
+ def CentrePane(*args, **kwargs):
+ """CentrePane(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_CentrePane(*args, **kwargs)
+
+ def CenterPane(*args, **kwargs):
+ """CenterPane(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_CenterPane(*args, **kwargs)
+
+ def ToolbarPane(*args, **kwargs):
+ """ToolbarPane(self) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_ToolbarPane(*args, **kwargs)
+
+ def SetFlag(*args, **kwargs):
+ """SetFlag(self, int flag, bool option_state) -> AuiPaneInfo"""
+ return _aui.AuiPaneInfo_SetFlag(*args, **kwargs)
+
+ def HasFlag(*args, **kwargs):
+ """HasFlag(self, int flag) -> bool"""
+ return _aui.AuiPaneInfo_HasFlag(*args, **kwargs)
+
+ optionFloating = _aui.AuiPaneInfo_optionFloating
+ optionHidden = _aui.AuiPaneInfo_optionHidden
+ optionLeftDockable = _aui.AuiPaneInfo_optionLeftDockable
+ optionRightDockable = _aui.AuiPaneInfo_optionRightDockable
+ optionTopDockable = _aui.AuiPaneInfo_optionTopDockable
+ optionBottomDockable = _aui.AuiPaneInfo_optionBottomDockable
+ optionFloatable = _aui.AuiPaneInfo_optionFloatable
+ optionMovable = _aui.AuiPaneInfo_optionMovable
+ optionResizable = _aui.AuiPaneInfo_optionResizable
+ optionPaneBorder = _aui.AuiPaneInfo_optionPaneBorder
+ optionCaption = _aui.AuiPaneInfo_optionCaption
+ optionGripper = _aui.AuiPaneInfo_optionGripper
+ optionDestroyOnClose = _aui.AuiPaneInfo_optionDestroyOnClose
+ optionToolbar = _aui.AuiPaneInfo_optionToolbar
+ optionActive = _aui.AuiPaneInfo_optionActive
+ optionGripperTop = _aui.AuiPaneInfo_optionGripperTop
+ optionMaximized = _aui.AuiPaneInfo_optionMaximized
+ optionDockFixed = _aui.AuiPaneInfo_optionDockFixed
+ buttonClose = _aui.AuiPaneInfo_buttonClose
+ buttonMaximize = _aui.AuiPaneInfo_buttonMaximize
+ buttonMinimize = _aui.AuiPaneInfo_buttonMinimize
+ buttonPin = _aui.AuiPaneInfo_buttonPin
+ buttonCustom1 = _aui.AuiPaneInfo_buttonCustom1
+ buttonCustom2 = _aui.AuiPaneInfo_buttonCustom2
+ buttonCustom3 = _aui.AuiPaneInfo_buttonCustom3
+ savedHiddenState = _aui.AuiPaneInfo_savedHiddenState
+ actionPane = _aui.AuiPaneInfo_actionPane
+ name = property(_aui.AuiPaneInfo_name_get, _aui.AuiPaneInfo_name_set)
+ caption = property(_aui.AuiPaneInfo_caption_get, _aui.AuiPaneInfo_caption_set)
+ icon = property(_aui.AuiPaneInfo_icon_get, _aui.AuiPaneInfo_icon_set)
+ window = property(_aui.AuiPaneInfo_window_get, _aui.AuiPaneInfo_window_set)
+ frame = property(_aui.AuiPaneInfo_frame_get, _aui.AuiPaneInfo_frame_set)
+ state = property(_aui.AuiPaneInfo_state_get, _aui.AuiPaneInfo_state_set)
+ dock_direction = property(_aui.AuiPaneInfo_dock_direction_get, _aui.AuiPaneInfo_dock_direction_set)
+ dock_layer = property(_aui.AuiPaneInfo_dock_layer_get, _aui.AuiPaneInfo_dock_layer_set)
+ dock_row = property(_aui.AuiPaneInfo_dock_row_get, _aui.AuiPaneInfo_dock_row_set)
+ dock_pos = property(_aui.AuiPaneInfo_dock_pos_get, _aui.AuiPaneInfo_dock_pos_set)
+ best_size = property(_aui.AuiPaneInfo_best_size_get, _aui.AuiPaneInfo_best_size_set)
+ min_size = property(_aui.AuiPaneInfo_min_size_get, _aui.AuiPaneInfo_min_size_set)
+ max_size = property(_aui.AuiPaneInfo_max_size_get, _aui.AuiPaneInfo_max_size_set)
+ floating_pos = property(_aui.AuiPaneInfo_floating_pos_get, _aui.AuiPaneInfo_floating_pos_set)
+ floating_size = property(_aui.AuiPaneInfo_floating_size_get, _aui.AuiPaneInfo_floating_size_set)
+ dock_proportion = property(_aui.AuiPaneInfo_dock_proportion_get, _aui.AuiPaneInfo_dock_proportion_set)
+ buttons = property(_aui.AuiPaneInfo_buttons_get, _aui.AuiPaneInfo_buttons_set)
+ rect = property(_aui.AuiPaneInfo_rect_get, _aui.AuiPaneInfo_rect_set)
+ def IsValid(*args, **kwargs):
+ """IsValid(self) -> bool"""
+ return _aui.AuiPaneInfo_IsValid(*args, **kwargs)
+
+_aui.AuiPaneInfo_swigregister(AuiPaneInfo)
+cvar = _aui.cvar
+
+class AuiManager(_core.EvtHandler):
+ """Proxy of C++ AuiManager class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window managedWnd=None, int flags=AUI_MGR_DEFAULT) -> AuiManager"""
+ _aui.AuiManager_swiginit(self,_aui.new_AuiManager(*args, **kwargs))
+ __swig_destroy__ = _aui.delete_AuiManager
+ __del__ = lambda self : None;
+ def UnInit(*args, **kwargs):
+ """UnInit(self)"""
+ return _aui.AuiManager_UnInit(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _aui.AuiManager_SetFlags(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _aui.AuiManager_GetFlags(*args, **kwargs)
+
+ def SetManagedWindow(*args, **kwargs):
+ """SetManagedWindow(self, Window managedWnd)"""
+ return _aui.AuiManager_SetManagedWindow(*args, **kwargs)
+
+ def GetManagedWindow(*args, **kwargs):
+ """GetManagedWindow(self) -> Window"""
+ return _aui.AuiManager_GetManagedWindow(*args, **kwargs)
+
+ def GetManager(*args, **kwargs):
+ """GetManager(Window window) -> AuiManager"""
+ return _aui.AuiManager_GetManager(*args, **kwargs)
+
+ GetManager = staticmethod(GetManager)
+ def SetArtProvider(*args, **kwargs):
+ """SetArtProvider(self, AuiDockArt artProvider)"""
+ return _aui.AuiManager_SetArtProvider(*args, **kwargs)
+
+ def GetArtProvider(*args, **kwargs):
+ """GetArtProvider(self) -> AuiDockArt"""
+ return _aui.AuiManager_GetArtProvider(*args, **kwargs)
+
+ def _GetPaneByWidget(*args, **kwargs):
+ """_GetPaneByWidget(self, Window window) -> AuiPaneInfo"""
+ return _aui.AuiManager__GetPaneByWidget(*args, **kwargs)
+
+ def _GetPaneByName(*args, **kwargs):
+ """_GetPaneByName(self, String name) -> AuiPaneInfo"""
+ return _aui.AuiManager__GetPaneByName(*args, **kwargs)
+
+ def GetAllPanes(*args, **kwargs):
+ """GetAllPanes(self) -> wxAuiPaneInfoArray"""
+ return _aui.AuiManager_GetAllPanes(*args, **kwargs)
+
+ def _AddPane1(*args, **kwargs):
+ """_AddPane1(self, Window window, AuiPaneInfo paneInfo) -> bool"""
+ return _aui.AuiManager__AddPane1(*args, **kwargs)
+
+ def AddPane(*args, **kwargs):
+ """AddPane(self, Window window, AuiPaneInfo paneInfo, Point dropPos) -> bool"""
+ return _aui.AuiManager_AddPane(*args, **kwargs)
+
+ def _AddPane2(*args, **kwargs):
+ """_AddPane2(self, Window window, int direction=LEFT, String caption=wxEmptyString) -> bool"""
+ return _aui.AuiManager__AddPane2(*args, **kwargs)
+
+ def InsertPane(*args, **kwargs):
+ """InsertPane(self, Window window, AuiPaneInfo insertLocation, int insertLevel=AUI_INSERT_PANE) -> bool"""
+ return _aui.AuiManager_InsertPane(*args, **kwargs)
+
+ def DetachPane(*args, **kwargs):
+ """DetachPane(self, Window window) -> bool"""
+ return _aui.AuiManager_DetachPane(*args, **kwargs)
+
+ def Update(*args, **kwargs):
+ """Update(self)"""
+ return _aui.AuiManager_Update(*args, **kwargs)
+
+ def SavePaneInfo(*args, **kwargs):
+ """SavePaneInfo(self, AuiPaneInfo pane) -> String"""
+ return _aui.AuiManager_SavePaneInfo(*args, **kwargs)
+
+ def LoadPaneInfo(*args, **kwargs):
+ """LoadPaneInfo(self, String panePart, AuiPaneInfo pane)"""
+ return _aui.AuiManager_LoadPaneInfo(*args, **kwargs)
+
+ def SavePerspective(*args, **kwargs):
+ """SavePerspective(self) -> String"""
+ return _aui.AuiManager_SavePerspective(*args, **kwargs)
+
+ def LoadPerspective(*args, **kwargs):
+ """LoadPerspective(self, String perspective, bool update=True) -> bool"""
+ return _aui.AuiManager_LoadPerspective(*args, **kwargs)
+
+ def SetDockSizeConstraint(*args, **kwargs):
+ """SetDockSizeConstraint(self, double widthPct, double heightPct)"""
+ return _aui.AuiManager_SetDockSizeConstraint(*args, **kwargs)
+
+ def GetDockSizeConstraint(*args, **kwargs):
+ """GetDockSizeConstraint(self, double widthPct, double heightPct)"""
+ return _aui.AuiManager_GetDockSizeConstraint(*args, **kwargs)
+
+ def ClosePane(*args, **kwargs):
+ """ClosePane(self, AuiPaneInfo paneInfo)"""
+ return _aui.AuiManager_ClosePane(*args, **kwargs)
+
+ def MaximizePane(*args, **kwargs):
+ """MaximizePane(self, AuiPaneInfo paneInfo)"""
+ return _aui.AuiManager_MaximizePane(*args, **kwargs)
+
+ def RestorePane(*args, **kwargs):
+ """RestorePane(self, AuiPaneInfo paneInfo)"""
+ return _aui.AuiManager_RestorePane(*args, **kwargs)
+
+ def RestoreMaximizedPane(*args, **kwargs):
+ """RestoreMaximizedPane(self)"""
+ return _aui.AuiManager_RestoreMaximizedPane(*args, **kwargs)
+
+ def CreateFloatingFrame(*args, **kwargs):
+ """CreateFloatingFrame(self, Window parent, AuiPaneInfo p) -> AuiFloatingFrame"""
+ return _aui.AuiManager_CreateFloatingFrame(*args, **kwargs)
+
+ def CanDockPanel(*args, **kwargs):
+ """CanDockPanel(self, AuiPaneInfo p) -> bool"""
+ return _aui.AuiManager_CanDockPanel(*args, **kwargs)
+
+ def StartPaneDrag(*args, **kwargs):
+ """StartPaneDrag(self, Window paneWindow, Point offset)"""
+ return _aui.AuiManager_StartPaneDrag(*args, **kwargs)
+
+ def CalculateHintRect(*args, **kwargs):
+ """CalculateHintRect(self, Window paneWindow, Point pt, Point offset) -> Rect"""
+ return _aui.AuiManager_CalculateHintRect(*args, **kwargs)
+
+ def DrawHintRect(*args, **kwargs):
+ """DrawHintRect(self, Window paneWindow, Point pt, Point offset)"""
+ return _aui.AuiManager_DrawHintRect(*args, **kwargs)
+
+ def ShowHint(*args, **kwargs):
+ """ShowHint(self, Rect rect)"""
+ return _aui.AuiManager_ShowHint(*args, **kwargs)
+
+ def HideHint(*args, **kwargs):
+ """HideHint(self)"""
+ return _aui.AuiManager_HideHint(*args, **kwargs)
+
+ def OnHintActivate(*args, **kwargs):
+ """OnHintActivate(self, ActivateEvent event)"""
+ return _aui.AuiManager_OnHintActivate(*args, **kwargs)
+
+ def OnRender(*args, **kwargs):
+ """OnRender(self, AuiManagerEvent evt)"""
+ return _aui.AuiManager_OnRender(*args, **kwargs)
+
+ def OnPaneButton(*args, **kwargs):
+ """OnPaneButton(self, AuiManagerEvent evt)"""
+ return _aui.AuiManager_OnPaneButton(*args, **kwargs)
+
+ def GetPane(self, item):
+ """
+ GetPane(self, window_or_info item) -> PaneInfo
+
+ GetPane is used to search for a `PaneInfo` object either by
+ widget reference or by pane name, which acts as a unique id
+ for a window pane. The returned `PaneInfo` object may then be
+ modified to change a pane's look, state or position. After one
+ or more modifications to the `PaneInfo`, `AuiManager.Update`
+ should be called to realize the changes to the user interface.
+
+ If the lookup failed (meaning the pane could not be found in
+ the manager) GetPane returns an empty `PaneInfo`, a condition
+ which can be checked by calling `PaneInfo.IsOk`.
+ """
+ if isinstance(item, wx.Window):
+ return self._GetPaneByWidget(item)
+ else:
+ return self._GetPaneByName(item)
+
+ def AddPane(self, window, info=None, caption=None):
+ """
+ AddPane(self, window, info=None, caption=None) -> bool
+
+ AddPane tells the frame manager to start managing a child
+ window. There are two versions of this function. The first
+ verison accepts a `PaneInfo` object for the ``info`` parameter
+ and allows the full spectrum of pane parameter
+ possibilities. (Say that 3 times fast!)
+
+ The second version is used for simpler user interfaces which
+ do not require as much configuration. In this case the
+ ``info`` parameter specifies the direction property of the
+ pane info, and defaults to ``wx.LEFT``. The pane caption may
+ also be specified as an extra parameter in this form.
+ """
+ if type(info) == AuiPaneInfo:
+ return self._AddPane1(window, info)
+ else:
+
+ if info is None:
+ info = wx.LEFT
+ if caption is None:
+ caption = ""
+ return self._AddPane2(window, info, caption)
+
+ SetFrame = wx.deprecated(SetManagedWindow,
+ "SetFrame is deprecated, use `SetManagedWindow` instead.")
+ GetFrame = wx.deprecated(GetManagedWindow,
+ "GetFrame is deprecated, use `GetManagedWindow` instead.")
+
+ AllPanes = property(GetAllPanes,doc="See `GetAllPanes`")
+ ArtProvider = property(GetArtProvider,SetArtProvider,doc="See `GetArtProvider` and `SetArtProvider`")
+ Flags = property(GetFlags,SetFlags,doc="See `GetFlags` and `SetFlags`")
+ ManagedWindow = property(GetManagedWindow,SetManagedWindow,doc="See `GetManagedWindow` and `SetManagedWindow`")
+_aui.AuiManager_swigregister(AuiManager)
+
+def AuiManager_GetManager(*args, **kwargs):
+ """AuiManager_GetManager(Window window) -> AuiManager"""
+ return _aui.AuiManager_GetManager(*args, **kwargs)
+
+class AuiManagerEvent(_core.Event):
+ """Proxy of C++ AuiManagerEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType type=wxEVT_NULL) -> AuiManagerEvent"""
+ _aui.AuiManagerEvent_swiginit(self,_aui.new_AuiManagerEvent(*args, **kwargs))
+ def Clone(*args, **kwargs):
+ """Clone(self) -> Event"""
+ return _aui.AuiManagerEvent_Clone(*args, **kwargs)
+
+ def SetManager(*args, **kwargs):
+ """SetManager(self, AuiManager mgr)"""
+ return _aui.AuiManagerEvent_SetManager(*args, **kwargs)
+
+ def SetPane(*args, **kwargs):
+ """SetPane(self, AuiPaneInfo p)"""
+ return _aui.AuiManagerEvent_SetPane(*args, **kwargs)
+
+ def SetButton(*args, **kwargs):
+ """SetButton(self, int b)"""
+ return _aui.AuiManagerEvent_SetButton(*args, **kwargs)
+
+ def SetDC(*args, **kwargs):
+ """SetDC(self, DC pdc)"""
+ return _aui.AuiManagerEvent_SetDC(*args, **kwargs)
+
+ def GetManager(*args, **kwargs):
+ """GetManager(self) -> AuiManager"""
+ return _aui.AuiManagerEvent_GetManager(*args, **kwargs)
+
+ def GetPane(*args, **kwargs):
+ """GetPane(self) -> AuiPaneInfo"""
+ return _aui.AuiManagerEvent_GetPane(*args, **kwargs)
+
+ def GetButton(*args, **kwargs):
+ """GetButton(self) -> int"""
+ return _aui.AuiManagerEvent_GetButton(*args, **kwargs)
+
+ def GetDC(*args, **kwargs):
+ """GetDC(self) -> DC"""
+ return _aui.AuiManagerEvent_GetDC(*args, **kwargs)
+
+ def Veto(*args, **kwargs):
+ """Veto(self, bool veto=True)"""
+ return _aui.AuiManagerEvent_Veto(*args, **kwargs)
+
+ def GetVeto(*args, **kwargs):
+ """GetVeto(self) -> bool"""
+ return _aui.AuiManagerEvent_GetVeto(*args, **kwargs)
+
+ def SetCanVeto(*args, **kwargs):
+ """SetCanVeto(self, bool can_veto)"""
+ return _aui.AuiManagerEvent_SetCanVeto(*args, **kwargs)
+
+ def CanVeto(*args, **kwargs):
+ """CanVeto(self) -> bool"""
+ return _aui.AuiManagerEvent_CanVeto(*args, **kwargs)
+
+ manager = property(_aui.AuiManagerEvent_manager_get, _aui.AuiManagerEvent_manager_set)
+ pane = property(_aui.AuiManagerEvent_pane_get, _aui.AuiManagerEvent_pane_set)
+ button = property(_aui.AuiManagerEvent_button_get, _aui.AuiManagerEvent_button_set)
+ veto_flag = property(_aui.AuiManagerEvent_veto_flag_get, _aui.AuiManagerEvent_veto_flag_set)
+ canveto_flag = property(_aui.AuiManagerEvent_canveto_flag_get, _aui.AuiManagerEvent_canveto_flag_set)
+ dc = property(_aui.AuiManagerEvent_dc_get, _aui.AuiManagerEvent_dc_set)
+ Button = property(GetButton,SetButton,doc="See `GetButton` and `SetButton`")
+ DC = property(GetDC,SetDC,doc="See `GetDC` and `SetDC`")
+ Pane = property(GetPane,SetPane,doc="See `GetPane` and `SetPane`")
+_aui.AuiManagerEvent_swigregister(AuiManagerEvent)
+
+class AuiDockInfo(object):
+ """Proxy of C++ AuiDockInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> AuiDockInfo"""
+ _aui.AuiDockInfo_swiginit(self,_aui.new_AuiDockInfo(*args, **kwargs))
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _aui.AuiDockInfo_IsOk(*args, **kwargs)
+
+ def IsHorizontal(*args, **kwargs):
+ """IsHorizontal(self) -> bool"""
+ return _aui.AuiDockInfo_IsHorizontal(*args, **kwargs)
+
+ def IsVertical(*args, **kwargs):
+ """IsVertical(self) -> bool"""
+ return _aui.AuiDockInfo_IsVertical(*args, **kwargs)
+
+ panes = property(_aui.AuiDockInfo_panes_get, _aui.AuiDockInfo_panes_set)
+ rect = property(_aui.AuiDockInfo_rect_get, _aui.AuiDockInfo_rect_set)
+ dock_direction = property(_aui.AuiDockInfo_dock_direction_get, _aui.AuiDockInfo_dock_direction_set)
+ dock_layer = property(_aui.AuiDockInfo_dock_layer_get, _aui.AuiDockInfo_dock_layer_set)
+ dock_row = property(_aui.AuiDockInfo_dock_row_get, _aui.AuiDockInfo_dock_row_set)
+ size = property(_aui.AuiDockInfo_size_get, _aui.AuiDockInfo_size_set)
+ min_size = property(_aui.AuiDockInfo_min_size_get, _aui.AuiDockInfo_min_size_set)
+ resizable = property(_aui.AuiDockInfo_resizable_get, _aui.AuiDockInfo_resizable_set)
+ toolbar = property(_aui.AuiDockInfo_toolbar_get, _aui.AuiDockInfo_toolbar_set)
+ fixed = property(_aui.AuiDockInfo_fixed_get, _aui.AuiDockInfo_fixed_set)
+ reserved1 = property(_aui.AuiDockInfo_reserved1_get, _aui.AuiDockInfo_reserved1_set)
+ __swig_destroy__ = _aui.delete_AuiDockInfo
+ __del__ = lambda self : None;
+_aui.AuiDockInfo_swigregister(AuiDockInfo)
+
+class AuiDockUIPart(object):
+ """Proxy of C++ AuiDockUIPart class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ typeCaption = _aui.AuiDockUIPart_typeCaption
+ typeGripper = _aui.AuiDockUIPart_typeGripper
+ typeDock = _aui.AuiDockUIPart_typeDock
+ typeDockSizer = _aui.AuiDockUIPart_typeDockSizer
+ typePane = _aui.AuiDockUIPart_typePane
+ typePaneSizer = _aui.AuiDockUIPart_typePaneSizer
+ typeBackground = _aui.AuiDockUIPart_typeBackground
+ typePaneBorder = _aui.AuiDockUIPart_typePaneBorder
+ typePaneButton = _aui.AuiDockUIPart_typePaneButton
+ type = property(_aui.AuiDockUIPart_type_get, _aui.AuiDockUIPart_type_set)
+ orientation = property(_aui.AuiDockUIPart_orientation_get, _aui.AuiDockUIPart_orientation_set)
+ dock = property(_aui.AuiDockUIPart_dock_get, _aui.AuiDockUIPart_dock_set)
+ pane = property(_aui.AuiDockUIPart_pane_get, _aui.AuiDockUIPart_pane_set)
+ button = property(_aui.AuiDockUIPart_button_get, _aui.AuiDockUIPart_button_set)
+ cont_sizer = property(_aui.AuiDockUIPart_cont_sizer_get, _aui.AuiDockUIPart_cont_sizer_set)
+ sizer_item = property(_aui.AuiDockUIPart_sizer_item_get, _aui.AuiDockUIPart_sizer_item_set)
+ rect = property(_aui.AuiDockUIPart_rect_get, _aui.AuiDockUIPart_rect_set)
+ __swig_destroy__ = _aui.delete_AuiDockUIPart
+ __del__ = lambda self : None;
+_aui.AuiDockUIPart_swigregister(AuiDockUIPart)
+
+class AuiPaneButton(object):
+ """Proxy of C++ AuiPaneButton class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ button_id = property(_aui.AuiPaneButton_button_id_get, _aui.AuiPaneButton_button_id_set)
+ __swig_destroy__ = _aui.delete_AuiPaneButton
+ __del__ = lambda self : None;
+_aui.AuiPaneButton_swigregister(AuiPaneButton)
+
+wxEVT_AUI_PANE_BUTTON = _aui.wxEVT_AUI_PANE_BUTTON
+wxEVT_AUI_PANE_CLOSE = _aui.wxEVT_AUI_PANE_CLOSE
+wxEVT_AUI_PANE_MAXIMIZE = _aui.wxEVT_AUI_PANE_MAXIMIZE
+wxEVT_AUI_PANE_RESTORE = _aui.wxEVT_AUI_PANE_RESTORE
+wxEVT_AUI_PANE_ACTIVATED = _aui.wxEVT_AUI_PANE_ACTIVATED
+wxEVT_AUI_RENDER = _aui.wxEVT_AUI_RENDER
+wxEVT_AUI_FIND_MANAGER = _aui.wxEVT_AUI_FIND_MANAGER
+EVT_AUI_PANE_BUTTON = wx.PyEventBinder( wxEVT_AUI_PANE_BUTTON )
+EVT_AUI_PANE_CLOSE = wx.PyEventBinder( wxEVT_AUI_PANE_CLOSE )
+EVT_AUI_PANE_MAXIMIZE = wx.PyEventBinder( wxEVT_AUI_PANE_MAXIMIZE )
+EVT_AUI_PANE_RESTORE = wx.PyEventBinder( wxEVT_AUI_PANE_RESTORE )
+EVT_AUI_PANE_ACTIVATED = wx.PyEventBinder( wxEVT_AUI_PANE_ACTIVATED )
+EVT_AUI_RENDER = wx.PyEventBinder( wxEVT_AUI_RENDER )
+EVT_AUI_FIND_MANAGER = wx.PyEventBinder( wxEVT_AUI_FIND_MANAGER )
+
+class AuiDockArt(object):
+ """Proxy of C++ AuiDockArt class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _aui.delete_AuiDockArt
+ __del__ = lambda self : None;
+ def GetMetric(*args, **kwargs):
+ """GetMetric(self, int id) -> int"""
+ return _aui.AuiDockArt_GetMetric(*args, **kwargs)
+
+ def SetMetric(*args, **kwargs):
+ """SetMetric(self, int id, int newVal)"""
+ return _aui.AuiDockArt_SetMetric(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """SetFont(self, int id, Font font)"""
+ return _aui.AuiDockArt_SetFont(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """GetFont(self, int id) -> Font"""
+ return _aui.AuiDockArt_GetFont(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """GetColour(self, int id) -> Colour"""
+ return _aui.AuiDockArt_GetColour(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """SetColour(self, int id, Colour colour)"""
+ return _aui.AuiDockArt_SetColour(*args, **kwargs)
+
+ def GetColor(*args, **kwargs):
+ """GetColor(self, int id) -> Colour"""
+ return _aui.AuiDockArt_GetColor(*args, **kwargs)
+
+ def SetColor(*args, **kwargs):
+ """SetColor(self, int id, Colour color)"""
+ return _aui.AuiDockArt_SetColor(*args, **kwargs)
+
+ def DrawSash(*args, **kwargs):
+ """DrawSash(self, DC dc, Window window, int orientation, Rect rect)"""
+ return _aui.AuiDockArt_DrawSash(*args, **kwargs)
+
+ def DrawBackground(*args, **kwargs):
+ """DrawBackground(self, DC dc, Window window, int orientation, Rect rect)"""
+ return _aui.AuiDockArt_DrawBackground(*args, **kwargs)
+
+ def DrawCaption(*args, **kwargs):
+ """DrawCaption(self, DC dc, Window window, String text, Rect rect, AuiPaneInfo pane)"""
+ return _aui.AuiDockArt_DrawCaption(*args, **kwargs)
+
+ def DrawGripper(*args, **kwargs):
+ """DrawGripper(self, DC dc, Window window, Rect rect, AuiPaneInfo pane)"""
+ return _aui.AuiDockArt_DrawGripper(*args, **kwargs)
+
+ def DrawBorder(*args, **kwargs):
+ """DrawBorder(self, DC dc, Window window, Rect rect, AuiPaneInfo pane)"""
+ return _aui.AuiDockArt_DrawBorder(*args, **kwargs)
+
+ def DrawPaneButton(*args, **kwargs):
+ """
+ DrawPaneButton(self, DC dc, Window window, int button, int buttonState,
+ Rect rect, AuiPaneInfo pane)
+ """
+ return _aui.AuiDockArt_DrawPaneButton(*args, **kwargs)
+
+_aui.AuiDockArt_swigregister(AuiDockArt)
+
+class AuiDefaultDockArt(AuiDockArt):
+ """Proxy of C++ AuiDefaultDockArt class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> AuiDefaultDockArt"""
+ _aui.AuiDefaultDockArt_swiginit(self,_aui.new_AuiDefaultDockArt(*args, **kwargs))
+ def DrawIcon(*args, **kwargs):
+ """DrawIcon(self, DC dc, Rect rect, AuiPaneInfo pane)"""
+ return _aui.AuiDefaultDockArt_DrawIcon(*args, **kwargs)
+
+_aui.AuiDefaultDockArt_swigregister(AuiDefaultDockArt)
+
+class AuiFloatingFrame(_windows.Frame):
+ """Proxy of C++ AuiFloatingFrame class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, AuiManager ownerMgr, AuiPaneInfo pane,
+ int id=ID_ANY, long style=wxRESIZE_BORDER|wxSYSTEM_MENU|wxCAPTION|wxFRAME_NO_TASKBAR|wxFRAME_FLOAT_ON_PARENT|wxCLIP_CHILDREN) -> AuiFloatingFrame
+ """
+ _aui.AuiFloatingFrame_swiginit(self,_aui.new_AuiFloatingFrame(*args, **kwargs))
+ __swig_destroy__ = _aui.delete_AuiFloatingFrame
+ __del__ = lambda self : None;
+ def SetPaneWindow(*args, **kwargs):
+ """SetPaneWindow(self, AuiPaneInfo pane)"""
+ return _aui.AuiFloatingFrame_SetPaneWindow(*args, **kwargs)
+
+ def GetOwnerManager(*args, **kwargs):
+ """GetOwnerManager(self) -> AuiManager"""
+ return _aui.AuiFloatingFrame_GetOwnerManager(*args, **kwargs)
+
+_aui.AuiFloatingFrame_swigregister(AuiFloatingFrame)
+
+AUI_NB_TOP = _aui.AUI_NB_TOP
+AUI_NB_LEFT = _aui.AUI_NB_LEFT
+AUI_NB_RIGHT = _aui.AUI_NB_RIGHT
+AUI_NB_BOTTOM = _aui.AUI_NB_BOTTOM
+AUI_NB_TAB_SPLIT = _aui.AUI_NB_TAB_SPLIT
+AUI_NB_TAB_MOVE = _aui.AUI_NB_TAB_MOVE
+AUI_NB_TAB_EXTERNAL_MOVE = _aui.AUI_NB_TAB_EXTERNAL_MOVE
+AUI_NB_TAB_FIXED_WIDTH = _aui.AUI_NB_TAB_FIXED_WIDTH
+AUI_NB_SCROLL_BUTTONS = _aui.AUI_NB_SCROLL_BUTTONS
+AUI_NB_WINDOWLIST_BUTTON = _aui.AUI_NB_WINDOWLIST_BUTTON
+AUI_NB_CLOSE_BUTTON = _aui.AUI_NB_CLOSE_BUTTON
+AUI_NB_CLOSE_ON_ACTIVE_TAB = _aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
+AUI_NB_CLOSE_ON_ALL_TABS = _aui.AUI_NB_CLOSE_ON_ALL_TABS
+AUI_NB_MIDDLE_CLICK_CLOSE = _aui.AUI_NB_MIDDLE_CLICK_CLOSE
+AUI_NB_DEFAULT_STYLE = _aui.AUI_NB_DEFAULT_STYLE
+class AuiNotebookEvent(_core.BookCtrlEvent):
+ """Proxy of C++ AuiNotebookEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=wxEVT_NULL, int winId=0) -> AuiNotebookEvent"""
+ _aui.AuiNotebookEvent_swiginit(self,_aui.new_AuiNotebookEvent(*args, **kwargs))
+ def SetDragSource(*args, **kwargs):
+ """SetDragSource(self, AuiNotebook s)"""
+ return _aui.AuiNotebookEvent_SetDragSource(*args, **kwargs)
+
+ def GetDragSource(*args, **kwargs):
+ """GetDragSource(self) -> AuiNotebook"""
+ return _aui.AuiNotebookEvent_GetDragSource(*args, **kwargs)
+
+_aui.AuiNotebookEvent_swigregister(AuiNotebookEvent)
+
+class AuiNotebookPage(object):
+ """Proxy of C++ AuiNotebookPage class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ window = property(_aui.AuiNotebookPage_window_get, _aui.AuiNotebookPage_window_set)
+ caption = property(_aui.AuiNotebookPage_caption_get, _aui.AuiNotebookPage_caption_set)
+ tooltip = property(_aui.AuiNotebookPage_tooltip_get, _aui.AuiNotebookPage_tooltip_set)
+ bitmap = property(_aui.AuiNotebookPage_bitmap_get, _aui.AuiNotebookPage_bitmap_set)
+ rect = property(_aui.AuiNotebookPage_rect_get, _aui.AuiNotebookPage_rect_set)
+ active = property(_aui.AuiNotebookPage_active_get, _aui.AuiNotebookPage_active_set)
+_aui.AuiNotebookPage_swigregister(AuiNotebookPage)
+
+class AuiTabContainerButton(object):
+ """Proxy of C++ AuiTabContainerButton class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ id = property(_aui.AuiTabContainerButton_id_get, _aui.AuiTabContainerButton_id_set)
+ curState = property(_aui.AuiTabContainerButton_curState_get, _aui.AuiTabContainerButton_curState_set)
+ location = property(_aui.AuiTabContainerButton_location_get, _aui.AuiTabContainerButton_location_set)
+ bitmap = property(_aui.AuiTabContainerButton_bitmap_get, _aui.AuiTabContainerButton_bitmap_set)
+ disBitmap = property(_aui.AuiTabContainerButton_disBitmap_get, _aui.AuiTabContainerButton_disBitmap_set)
+ rect = property(_aui.AuiTabContainerButton_rect_get, _aui.AuiTabContainerButton_rect_set)
+_aui.AuiTabContainerButton_swigregister(AuiTabContainerButton)
+
+class AuiTabContainer(object):
+ """Proxy of C++ AuiTabContainer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> AuiTabContainer"""
+ _aui.AuiTabContainer_swiginit(self,_aui.new_AuiTabContainer(*args, **kwargs))
+ __swig_destroy__ = _aui.delete_AuiTabContainer
+ __del__ = lambda self : None;
+ def SetArtProvider(*args, **kwargs):
+ """SetArtProvider(self, AuiTabArt art)"""
+ return _aui.AuiTabContainer_SetArtProvider(*args, **kwargs)
+
+ def GetArtProvider(*args, **kwargs):
+ """GetArtProvider(self) -> AuiTabArt"""
+ return _aui.AuiTabContainer_GetArtProvider(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _aui.AuiTabContainer_SetFlags(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _aui.AuiTabContainer_GetFlags(*args, **kwargs)
+
+ def AddPage(*args, **kwargs):
+ """AddPage(self, Window page, AuiNotebookPage info) -> bool"""
+ return _aui.AuiTabContainer_AddPage(*args, **kwargs)
+
+ def InsertPage(*args, **kwargs):
+ """InsertPage(self, Window page, AuiNotebookPage info, size_t idx) -> bool"""
+ return _aui.AuiTabContainer_InsertPage(*args, **kwargs)
+
+ def MovePage(*args, **kwargs):
+ """MovePage(self, Window page, size_t newIdx) -> bool"""
+ return _aui.AuiTabContainer_MovePage(*args, **kwargs)
+
+ def RemovePage(*args, **kwargs):
+ """RemovePage(self, Window page) -> bool"""
+ return _aui.AuiTabContainer_RemovePage(*args, **kwargs)
+
+ def SetActivePage(*args):
+ """
+ SetActivePage(self, Window page) -> bool
+ SetActivePage(self, size_t page) -> bool
+ """
+ return _aui.AuiTabContainer_SetActivePage(*args)
+
+ def SetNoneActive(*args, **kwargs):
+ """SetNoneActive(self)"""
+ return _aui.AuiTabContainer_SetNoneActive(*args, **kwargs)
+
+ def GetActivePage(*args, **kwargs):
+ """GetActivePage(self) -> int"""
+ return _aui.AuiTabContainer_GetActivePage(*args, **kwargs)
+
+ def TabHitTest(*args, **kwargs):
+ """TabHitTest(self, int x, int y, Window hit) -> bool"""
+ return _aui.AuiTabContainer_TabHitTest(*args, **kwargs)
+
+ def ButtonHitTest(*args, **kwargs):
+ """ButtonHitTest(self, int x, int y, AuiTabContainerButton hit) -> bool"""
+ return _aui.AuiTabContainer_ButtonHitTest(*args, **kwargs)
+
+ def GetWindowFromIdx(*args, **kwargs):
+ """GetWindowFromIdx(self, size_t idx) -> Window"""
+ return _aui.AuiTabContainer_GetWindowFromIdx(*args, **kwargs)
+
+ def GetIdxFromWindow(*args, **kwargs):
+ """GetIdxFromWindow(self, Window page) -> int"""
+ return _aui.AuiTabContainer_GetIdxFromWindow(*args, **kwargs)
+
+ def GetPageCount(*args, **kwargs):
+ """GetPageCount(self) -> size_t"""
+ return _aui.AuiTabContainer_GetPageCount(*args, **kwargs)
+
+ def GetPage(*args, **kwargs):
+ """GetPage(self, size_t idx) -> AuiNotebookPage"""
+ return _aui.AuiTabContainer_GetPage(*args, **kwargs)
+
+ def GetPages(*args, **kwargs):
+ """GetPages(self) -> AuiNotebookPageArray"""
+ return _aui.AuiTabContainer_GetPages(*args, **kwargs)
+
+ def SetNormalFont(*args, **kwargs):
+ """SetNormalFont(self, Font normalFont)"""
+ return _aui.AuiTabContainer_SetNormalFont(*args, **kwargs)
+
+ def SetSelectedFont(*args, **kwargs):
+ """SetSelectedFont(self, Font selectedFont)"""
+ return _aui.AuiTabContainer_SetSelectedFont(*args, **kwargs)
+
+ def SetMeasuringFont(*args, **kwargs):
+ """SetMeasuringFont(self, Font measuringFont)"""
+ return _aui.AuiTabContainer_SetMeasuringFont(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """SetColour(self, Colour colour)"""
+ return _aui.AuiTabContainer_SetColour(*args, **kwargs)
+
+ def SetActiveColour(*args, **kwargs):
+ """SetActiveColour(self, Colour colour)"""
+ return _aui.AuiTabContainer_SetActiveColour(*args, **kwargs)
+
+ def DoShowHide(*args, **kwargs):
+ """DoShowHide(self)"""
+ return _aui.AuiTabContainer_DoShowHide(*args, **kwargs)
+
+ def SetRect(*args, **kwargs):
+ """SetRect(self, Rect rect)"""
+ return _aui.AuiTabContainer_SetRect(*args, **kwargs)
+
+ def RemoveButton(*args, **kwargs):
+ """RemoveButton(self, int id)"""
+ return _aui.AuiTabContainer_RemoveButton(*args, **kwargs)
+
+ def AddButton(*args, **kwargs):
+ """
+ AddButton(self, int id, int location, Bitmap normalBitmap=wxNullBitmap,
+ Bitmap disabledBitmap=wxNullBitmap)
+ """
+ return _aui.AuiTabContainer_AddButton(*args, **kwargs)
+
+ def GetTabOffset(*args, **kwargs):
+ """GetTabOffset(self) -> size_t"""
+ return _aui.AuiTabContainer_GetTabOffset(*args, **kwargs)
+
+ def SetTabOffset(*args, **kwargs):
+ """SetTabOffset(self, size_t offset)"""
+ return _aui.AuiTabContainer_SetTabOffset(*args, **kwargs)
+
+ def IsTabVisible(*args, **kwargs):
+ """IsTabVisible(self, int tabPage, int tabOffset, DC dc, Window wnd) -> bool"""
+ return _aui.AuiTabContainer_IsTabVisible(*args, **kwargs)
+
+ def MakeTabVisible(*args, **kwargs):
+ """MakeTabVisible(self, int tabPage, Window win)"""
+ return _aui.AuiTabContainer_MakeTabVisible(*args, **kwargs)
+
+ ActivePage = property(GetActivePage,SetActivePage,doc="See `GetActivePage` and `SetActivePage`")
+ PageCount = property(GetPageCount,doc="See `GetPageCount`")
+ Pages = property(GetPages,doc="See `GetPages`")
+_aui.AuiTabContainer_swigregister(AuiTabContainer)
+
+class AuiTabCtrl(_core.Control,AuiTabContainer):
+ """Proxy of C++ AuiTabCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0) -> AuiTabCtrl
+ """
+ _aui.AuiTabCtrl_swiginit(self,_aui.new_AuiTabCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ __swig_destroy__ = _aui.delete_AuiTabCtrl
+ __del__ = lambda self : None;
+ def IsDragging(*args, **kwargs):
+ """IsDragging(self) -> bool"""
+ return _aui.AuiTabCtrl_IsDragging(*args, **kwargs)
+
+_aui.AuiTabCtrl_swigregister(AuiTabCtrl)
+
+class AuiNotebook(wxNavigationEnabled_BookCtrlBase):
+ """Proxy of C++ AuiNotebook class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=AUI_NB_DEFAULT_STYLE) -> AuiNotebook
+ """
+ _aui.AuiNotebook_swiginit(self,_aui.new_AuiNotebook(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _aui.AuiNotebook_Create(*args, **kwargs)
+
+ def SetArtProvider(*args, **kwargs):
+ """SetArtProvider(self, AuiTabArt art)"""
+ return _aui.AuiNotebook_SetArtProvider(*args, **kwargs)
+
+ def GetArtProvider(*args, **kwargs):
+ """GetArtProvider(self) -> AuiTabArt"""
+ return _aui.AuiNotebook_GetArtProvider(*args, **kwargs)
+
+ def SetUniformBitmapSize(*args, **kwargs):
+ """SetUniformBitmapSize(self, Size size)"""
+ return _aui.AuiNotebook_SetUniformBitmapSize(*args, **kwargs)
+
+ def SetTabCtrlHeight(*args, **kwargs):
+ """SetTabCtrlHeight(self, int height)"""
+ return _aui.AuiNotebook_SetTabCtrlHeight(*args, **kwargs)
+
+ def GetPage(*args, **kwargs):
+ """GetPage(self, size_t pageIdx) -> Window"""
+ return _aui.AuiNotebook_GetPage(*args, **kwargs)
+
+ def GetPageIndex(*args, **kwargs):
+ """GetPageIndex(self, Window pageWnd) -> int"""
+ return _aui.AuiNotebook_GetPageIndex(*args, **kwargs)
+
+ def SetPageToolTip(*args, **kwargs):
+ """SetPageToolTip(self, size_t page, String text) -> bool"""
+ return _aui.AuiNotebook_SetPageToolTip(*args, **kwargs)
+
+ def GetPageToolTip(*args, **kwargs):
+ """GetPageToolTip(self, size_t pageIdx) -> String"""
+ return _aui.AuiNotebook_GetPageToolTip(*args, **kwargs)
+
+ def SetPageBitmap(*args, **kwargs):
+ """SetPageBitmap(self, size_t page, Bitmap bitmap) -> bool"""
+ return _aui.AuiNotebook_SetPageBitmap(*args, **kwargs)
+
+ def GetPageBitmap(*args, **kwargs):
+ """GetPageBitmap(self, size_t pageIdx) -> Bitmap"""
+ return _aui.AuiNotebook_GetPageBitmap(*args, **kwargs)
+
+ def Split(*args, **kwargs):
+ """Split(self, size_t page, int direction)"""
+ return _aui.AuiNotebook_Split(*args, **kwargs)
+
+ def GetAuiManager(*args, **kwargs):
+ """GetAuiManager(self) -> AuiManager"""
+ return _aui.AuiNotebook_GetAuiManager(*args, **kwargs)
+
+ def SetNormalFont(*args, **kwargs):
+ """SetNormalFont(self, Font font)"""
+ return _aui.AuiNotebook_SetNormalFont(*args, **kwargs)
+
+ def SetSelectedFont(*args, **kwargs):
+ """SetSelectedFont(self, Font font)"""
+ return _aui.AuiNotebook_SetSelectedFont(*args, **kwargs)
+
+ def SetMeasuringFont(*args, **kwargs):
+ """SetMeasuringFont(self, Font font)"""
+ return _aui.AuiNotebook_SetMeasuringFont(*args, **kwargs)
+
+ def GetTabCtrlHeight(*args, **kwargs):
+ """GetTabCtrlHeight(self) -> int"""
+ return _aui.AuiNotebook_GetTabCtrlHeight(*args, **kwargs)
+
+ def GetHeightForPageHeight(*args, **kwargs):
+ """GetHeightForPageHeight(self, int pageHeight) -> int"""
+ return _aui.AuiNotebook_GetHeightForPageHeight(*args, **kwargs)
+
+ def ShowWindowMenu(*args, **kwargs):
+ """ShowWindowMenu(self) -> bool"""
+ return _aui.AuiNotebook_ShowWindowMenu(*args, **kwargs)
+
+_aui.AuiNotebook_swigregister(AuiNotebook)
+
+def PreAuiNotebook(*args, **kwargs):
+ """PreAuiNotebook() -> AuiNotebook"""
+ val = _aui.new_PreAuiNotebook(*args, **kwargs)
+ val._setOORInfo(val)
+ return val
+
+wxEVT_AUINOTEBOOK_PAGE_CLOSE = _aui.wxEVT_AUINOTEBOOK_PAGE_CLOSE
+wxEVT_AUINOTEBOOK_PAGE_CLOSED = _aui.wxEVT_AUINOTEBOOK_PAGE_CLOSED
+wxEVT_AUINOTEBOOK_PAGE_CHANGED = _aui.wxEVT_AUINOTEBOOK_PAGE_CHANGED
+wxEVT_AUINOTEBOOK_PAGE_CHANGING = _aui.wxEVT_AUINOTEBOOK_PAGE_CHANGING
+wxEVT_AUINOTEBOOK_BUTTON = _aui.wxEVT_AUINOTEBOOK_BUTTON
+wxEVT_AUINOTEBOOK_BEGIN_DRAG = _aui.wxEVT_AUINOTEBOOK_BEGIN_DRAG
+wxEVT_AUINOTEBOOK_END_DRAG = _aui.wxEVT_AUINOTEBOOK_END_DRAG
+wxEVT_AUINOTEBOOK_DRAG_MOTION = _aui.wxEVT_AUINOTEBOOK_DRAG_MOTION
+wxEVT_AUINOTEBOOK_ALLOW_DND = _aui.wxEVT_AUINOTEBOOK_ALLOW_DND
+wxEVT_AUINOTEBOOK_DRAG_DONE = _aui.wxEVT_AUINOTEBOOK_DRAG_DONE
+wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN = _aui.wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN
+wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP = _aui.wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP
+wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN = _aui.wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN
+wxEVT_AUINOTEBOOK_TAB_RIGHT_UP = _aui.wxEVT_AUINOTEBOOK_TAB_RIGHT_UP
+wxEVT_AUINOTEBOOK_BG_DCLICK = _aui.wxEVT_AUINOTEBOOK_BG_DCLICK
+EVT_AUINOTEBOOK_PAGE_CLOSE = wx.PyEventBinder( wxEVT_AUINOTEBOOK_PAGE_CLOSE, 1 )
+EVT_AUINOTEBOOK_PAGE_CLOSED = wx.PyEventBinder( wxEVT_AUINOTEBOOK_PAGE_CLOSED, 1 )
+EVT_AUINOTEBOOK_PAGE_CHANGED = wx.PyEventBinder( wxEVT_AUINOTEBOOK_PAGE_CHANGED, 1 )
+EVT_AUINOTEBOOK_PAGE_CHANGING = wx.PyEventBinder( wxEVT_AUINOTEBOOK_PAGE_CHANGING, 1 )
+EVT_AUINOTEBOOK_BUTTON = wx.PyEventBinder( wxEVT_AUINOTEBOOK_BUTTON, 1 )
+EVT_AUINOTEBOOK_BEGIN_DRAG = wx.PyEventBinder( wxEVT_AUINOTEBOOK_BEGIN_DRAG, 1 )
+EVT_AUINOTEBOOK_END_DRAG = wx.PyEventBinder( wxEVT_AUINOTEBOOK_END_DRAG, 1 )
+EVT_AUINOTEBOOK_DRAG_MOTION = wx.PyEventBinder( wxEVT_AUINOTEBOOK_DRAG_MOTION, 1 )
+EVT_AUINOTEBOOK_ALLOW_DND = wx.PyEventBinder( wxEVT_AUINOTEBOOK_ALLOW_DND, 1 )
+EVT_AUINOTEBOOK_DRAG_DONE = wx.PyEventBinder( wxEVT_AUINOTEBOOK_DRAG_DONE, 1 )
+EVT__AUINOTEBOOK_TAB_MIDDLE_DOWN = wx.PyEventBinder( wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, 1 )
+EVT__AUINOTEBOOK_TAB_MIDDLE_UP = wx.PyEventBinder( wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP, 1 )
+EVT__AUINOTEBOOK_TAB_RIGHT_DOWN = wx.PyEventBinder( wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN, 1 )
+EVT__AUINOTEBOOK_TAB_RIGHT_UP = wx.PyEventBinder( wxEVT_AUINOTEBOOK_TAB_RIGHT_UP, 1 )
+EVT_AUINOTEBOOK_BG_DCLICK = wx.PyEventBinder( wxEVT_AUINOTEBOOK_BG_DCLICK, 1 )
+
+class AuiMDIParentFrame(_windows.Frame):
+ """Proxy of C++ AuiMDIParentFrame class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int winid, String title, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxDEFAULT_FRAME_STYLE|wxVSCROLL|wxHSCROLL,
+ String name=wxFrameNameStr) -> AuiMDIParentFrame
+ """
+ _aui.AuiMDIParentFrame_swiginit(self,_aui.new_AuiMDIParentFrame(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int winid, String title, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxDEFAULT_FRAME_STYLE|wxVSCROLL|wxHSCROLL,
+ String name=wxFrameNameStr) -> bool
+ """
+ return _aui.AuiMDIParentFrame_Create(*args, **kwargs)
+
+ def SetArtProvider(*args, **kwargs):
+ """SetArtProvider(self, AuiTabArt provider)"""
+ return _aui.AuiMDIParentFrame_SetArtProvider(*args, **kwargs)
+
+ def GetArtProvider(*args, **kwargs):
+ """GetArtProvider(self) -> AuiTabArt"""
+ return _aui.AuiMDIParentFrame_GetArtProvider(*args, **kwargs)
+
+ def GetWindowMenu(*args, **kwargs):
+ """GetWindowMenu(self) -> Menu"""
+ return _aui.AuiMDIParentFrame_GetWindowMenu(*args, **kwargs)
+
+ def SetWindowMenu(*args, **kwargs):
+ """SetWindowMenu(self, Menu pMenu)"""
+ return _aui.AuiMDIParentFrame_SetWindowMenu(*args, **kwargs)
+
+ def SetChildMenuBar(*args, **kwargs):
+ """SetChildMenuBar(self, AuiMDIChildFrame pChild)"""
+ return _aui.AuiMDIParentFrame_SetChildMenuBar(*args, **kwargs)
+
+ def SetActiveChild(*args, **kwargs):
+ """SetActiveChild(self, AuiMDIChildFrame pChildFrame)"""
+ return _aui.AuiMDIParentFrame_SetActiveChild(*args, **kwargs)
+
+ def OnCreateClient(*args, **kwargs):
+ """OnCreateClient(self) -> AuiMDIClientWindow"""
+ return _aui.AuiMDIParentFrame_OnCreateClient(*args, **kwargs)
+
+ def Cascade(*args, **kwargs):
+ """Cascade(self)"""
+ return _aui.AuiMDIParentFrame_Cascade(*args, **kwargs)
+
+ def Tile(*args, **kwargs):
+ """Tile(self, int orient=HORIZONTAL)"""
+ return _aui.AuiMDIParentFrame_Tile(*args, **kwargs)
+
+ def ArrangeIcons(*args, **kwargs):
+ """ArrangeIcons(self)"""
+ return _aui.AuiMDIParentFrame_ArrangeIcons(*args, **kwargs)
+
+ def ActivateNext(*args, **kwargs):
+ """ActivateNext(self)"""
+ return _aui.AuiMDIParentFrame_ActivateNext(*args, **kwargs)
+
+ def ActivatePrevious(*args, **kwargs):
+ """ActivatePrevious(self)"""
+ return _aui.AuiMDIParentFrame_ActivatePrevious(*args, **kwargs)
+
+ def GetNotebook(*args, **kwargs):
+ """GetNotebook(self) -> AuiNotebook"""
+ return _aui.AuiMDIParentFrame_GetNotebook(*args, **kwargs)
+
+ def GetActiveChild(*args, **kwargs):
+ """GetActiveChild(self) -> AuiMDIChildFrame"""
+ return _aui.AuiMDIParentFrame_GetActiveChild(*args, **kwargs)
+
+ def GetClientWindow(*args, **kwargs):
+ """GetClientWindow(self) -> AuiMDIClientWindow"""
+ return _aui.AuiMDIParentFrame_GetClientWindow(*args, **kwargs)
+
+_aui.AuiMDIParentFrame_swigregister(AuiMDIParentFrame)
+
+def PreAuiMDIParentFrame(*args, **kwargs):
+ """PreAuiMDIParentFrame() -> AuiMDIParentFrame"""
+ val = _aui.new_PreAuiMDIParentFrame(*args, **kwargs)
+ val._setOORInfo(val)
+ return val
+
+class AuiMDIChildFrame(_windows.Panel):
+ """Proxy of C++ AuiMDIChildFrame class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, AuiMDIParentFrame parent, int winid, String title,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DEFAULT_FRAME_STYLE, String name=wxFrameNameStr) -> AuiMDIChildFrame
+ """
+ _aui.AuiMDIChildFrame_swiginit(self,_aui.new_AuiMDIChildFrame(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, AuiMDIParentFrame parent, int winid, String title,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=DEFAULT_FRAME_STYLE, String name=wxFrameNameStr) -> bool
+ """
+ return _aui.AuiMDIChildFrame_Create(*args, **kwargs)
+
+ def SetMenuBar(*args, **kwargs):
+ """SetMenuBar(self, MenuBar menuBar)"""
+ return _aui.AuiMDIChildFrame_SetMenuBar(*args, **kwargs)
+
+ def GetMenuBar(*args, **kwargs):
+ """GetMenuBar(self) -> MenuBar"""
+ return _aui.AuiMDIChildFrame_GetMenuBar(*args, **kwargs)
+
+ def SetTitle(*args, **kwargs):
+ """SetTitle(self, String title)"""
+ return _aui.AuiMDIChildFrame_SetTitle(*args, **kwargs)
+
+ def GetTitle(*args, **kwargs):
+ """GetTitle(self) -> String"""
+ return _aui.AuiMDIChildFrame_GetTitle(*args, **kwargs)
+
+ def SetIcons(*args, **kwargs):
+ """SetIcons(self, wxIconBundle icons)"""
+ return _aui.AuiMDIChildFrame_SetIcons(*args, **kwargs)
+
+ def GetIcons(*args, **kwargs):
+ """GetIcons(self) -> wxIconBundle"""
+ return _aui.AuiMDIChildFrame_GetIcons(*args, **kwargs)
+
+ def SetIcon(*args, **kwargs):
+ """SetIcon(self, Icon icon)"""
+ return _aui.AuiMDIChildFrame_SetIcon(*args, **kwargs)
+
+ def GetIcon(*args, **kwargs):
+ """GetIcon(self) -> Icon"""
+ return _aui.AuiMDIChildFrame_GetIcon(*args, **kwargs)
+
+ def Activate(*args, **kwargs):
+ """Activate(self)"""
+ return _aui.AuiMDIChildFrame_Activate(*args, **kwargs)
+
+ def Maximize(*args, **kwargs):
+ """Maximize(self, bool maximize=True)"""
+ return _aui.AuiMDIChildFrame_Maximize(*args, **kwargs)
+
+ def Restore(*args, **kwargs):
+ """Restore(self)"""
+ return _aui.AuiMDIChildFrame_Restore(*args, **kwargs)
+
+ def Iconize(*args, **kwargs):
+ """Iconize(self, bool iconize=True)"""
+ return _aui.AuiMDIChildFrame_Iconize(*args, **kwargs)
+
+ def IsMaximized(*args, **kwargs):
+ """IsMaximized(self) -> bool"""
+ return _aui.AuiMDIChildFrame_IsMaximized(*args, **kwargs)
+
+ def IsIconized(*args, **kwargs):
+ """IsIconized(self) -> bool"""
+ return _aui.AuiMDIChildFrame_IsIconized(*args, **kwargs)
+
+ def ShowFullScreen(*args, **kwargs):
+ """ShowFullScreen(self, bool show, long style) -> bool"""
+ return _aui.AuiMDIChildFrame_ShowFullScreen(*args, **kwargs)
+
+ def IsFullScreen(*args, **kwargs):
+ """IsFullScreen(self) -> bool"""
+ return _aui.AuiMDIChildFrame_IsFullScreen(*args, **kwargs)
+
+ def OnMenuHighlight(*args, **kwargs):
+ """OnMenuHighlight(self, MenuEvent evt)"""
+ return _aui.AuiMDIChildFrame_OnMenuHighlight(*args, **kwargs)
+
+ def OnActivate(*args, **kwargs):
+ """OnActivate(self, ActivateEvent evt)"""
+ return _aui.AuiMDIChildFrame_OnActivate(*args, **kwargs)
+
+ def OnCloseWindow(*args, **kwargs):
+ """OnCloseWindow(self, CloseEvent evt)"""
+ return _aui.AuiMDIChildFrame_OnCloseWindow(*args, **kwargs)
+
+ def SetMDIParentFrame(*args, **kwargs):
+ """SetMDIParentFrame(self, AuiMDIParentFrame parent)"""
+ return _aui.AuiMDIChildFrame_SetMDIParentFrame(*args, **kwargs)
+
+ def GetMDIParentFrame(*args, **kwargs):
+ """GetMDIParentFrame(self) -> AuiMDIParentFrame"""
+ return _aui.AuiMDIChildFrame_GetMDIParentFrame(*args, **kwargs)
+
+ def ApplyMDIChildFrameRect(*args, **kwargs):
+ """ApplyMDIChildFrameRect(self)"""
+ return _aui.AuiMDIChildFrame_ApplyMDIChildFrameRect(*args, **kwargs)
+
+ def DoShow(*args, **kwargs):
+ """DoShow(self, bool show)"""
+ return _aui.AuiMDIChildFrame_DoShow(*args, **kwargs)
+
+_aui.AuiMDIChildFrame_swigregister(AuiMDIChildFrame)
+
+def PreAuiMDIChildFrame(*args, **kwargs):
+ """PreAuiMDIChildFrame() -> AuiMDIChildFrame"""
+ val = _aui.new_PreAuiMDIChildFrame(*args, **kwargs)
+ val._setOORInfo(val)
+ return val
+
+class AuiMDIClientWindow(AuiNotebook):
+ """Proxy of C++ AuiMDIClientWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, AuiMDIParentFrame parent, long style=0) -> AuiMDIClientWindow"""
+ _aui.AuiMDIClientWindow_swiginit(self,_aui.new_AuiMDIClientWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def CreateClient(*args, **kwargs):
+ """CreateClient(self, AuiMDIParentFrame parent, long style=wxVSCROLL|wxHSCROLL) -> bool"""
+ return _aui.AuiMDIClientWindow_CreateClient(*args, **kwargs)
+
+ def GetActiveChild(*args, **kwargs):
+ """GetActiveChild(self) -> AuiMDIChildFrame"""
+ return _aui.AuiMDIClientWindow_GetActiveChild(*args, **kwargs)
+
+ def SetActiveChild(*args, **kwargs):
+ """SetActiveChild(self, AuiMDIChildFrame pChildFrame)"""
+ return _aui.AuiMDIClientWindow_SetActiveChild(*args, **kwargs)
+
+_aui.AuiMDIClientWindow_swigregister(AuiMDIClientWindow)
+
+def PreAuiMDIClientWindow(*args, **kwargs):
+ """PreAuiMDIClientWindow() -> AuiMDIClientWindow"""
+ val = _aui.new_PreAuiMDIClientWindow(*args, **kwargs)
+ val._setOORInfo(val)
+ return val
+
+AUI_TB_TEXT = _aui.AUI_TB_TEXT
+AUI_TB_NO_TOOLTIPS = _aui.AUI_TB_NO_TOOLTIPS
+AUI_TB_NO_AUTORESIZE = _aui.AUI_TB_NO_AUTORESIZE
+AUI_TB_GRIPPER = _aui.AUI_TB_GRIPPER
+AUI_TB_OVERFLOW = _aui.AUI_TB_OVERFLOW
+AUI_TB_VERTICAL = _aui.AUI_TB_VERTICAL
+AUI_TB_HORZ_LAYOUT = _aui.AUI_TB_HORZ_LAYOUT
+AUI_TB_HORIZONTAL = _aui.AUI_TB_HORIZONTAL
+AUI_TB_PLAIN_BACKGROUND = _aui.AUI_TB_PLAIN_BACKGROUND
+AUI_TB_HORZ_TEXT = _aui.AUI_TB_HORZ_TEXT
+AUI_ORIENTATION_MASK = _aui.AUI_ORIENTATION_MASK
+AUI_TB_DEFAULT_STYLE = _aui.AUI_TB_DEFAULT_STYLE
+AUI_TBART_SEPARATOR_SIZE = _aui.AUI_TBART_SEPARATOR_SIZE
+AUI_TBART_GRIPPER_SIZE = _aui.AUI_TBART_GRIPPER_SIZE
+AUI_TBART_OVERFLOW_SIZE = _aui.AUI_TBART_OVERFLOW_SIZE
+AUI_TBTOOL_TEXT_LEFT = _aui.AUI_TBTOOL_TEXT_LEFT
+AUI_TBTOOL_TEXT_RIGHT = _aui.AUI_TBTOOL_TEXT_RIGHT
+AUI_TBTOOL_TEXT_TOP = _aui.AUI_TBTOOL_TEXT_TOP
+AUI_TBTOOL_TEXT_BOTTOM = _aui.AUI_TBTOOL_TEXT_BOTTOM
+class AuiToolBarEvent(_core.NotifyEvent):
+ """Proxy of C++ AuiToolBarEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=wxEVT_NULL, int winId=0) -> AuiToolBarEvent"""
+ _aui.AuiToolBarEvent_swiginit(self,_aui.new_AuiToolBarEvent(*args, **kwargs))
+ def IsDropDownClicked(*args, **kwargs):
+ """IsDropDownClicked(self) -> bool"""
+ return _aui.AuiToolBarEvent_IsDropDownClicked(*args, **kwargs)
+
+ def SetDropDownClicked(*args, **kwargs):
+ """SetDropDownClicked(self, bool c)"""
+ return _aui.AuiToolBarEvent_SetDropDownClicked(*args, **kwargs)
+
+ def GetClickPoint(*args, **kwargs):
+ """GetClickPoint(self) -> Point"""
+ return _aui.AuiToolBarEvent_GetClickPoint(*args, **kwargs)
+
+ def SetClickPoint(*args, **kwargs):
+ """SetClickPoint(self, Point p)"""
+ return _aui.AuiToolBarEvent_SetClickPoint(*args, **kwargs)
+
+ def GetItemRect(*args, **kwargs):
+ """GetItemRect(self) -> Rect"""
+ return _aui.AuiToolBarEvent_GetItemRect(*args, **kwargs)
+
+ def SetItemRect(*args, **kwargs):
+ """SetItemRect(self, Rect r)"""
+ return _aui.AuiToolBarEvent_SetItemRect(*args, **kwargs)
+
+ def GetToolId(*args, **kwargs):
+ """GetToolId(self) -> int"""
+ return _aui.AuiToolBarEvent_GetToolId(*args, **kwargs)
+
+ def SetToolId(*args, **kwargs):
+ """SetToolId(self, int toolId)"""
+ return _aui.AuiToolBarEvent_SetToolId(*args, **kwargs)
+
+_aui.AuiToolBarEvent_swigregister(AuiToolBarEvent)
+
+class AuiToolBarItem(object):
+ """Proxy of C++ AuiToolBarItem class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> AuiToolBarItem
+ __init__(self, AuiToolBarItem c) -> AuiToolBarItem
+ """
+ _aui.AuiToolBarItem_swiginit(self,_aui.new_AuiToolBarItem(*args))
+ def Assign(*args, **kwargs):
+ """Assign(self, AuiToolBarItem c)"""
+ return _aui.AuiToolBarItem_Assign(*args, **kwargs)
+
+ def SetWindow(*args, **kwargs):
+ """SetWindow(self, Window w)"""
+ return _aui.AuiToolBarItem_SetWindow(*args, **kwargs)
+
+ def GetWindow(*args, **kwargs):
+ """GetWindow(self) -> Window"""
+ return _aui.AuiToolBarItem_GetWindow(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """SetId(self, int newId)"""
+ return _aui.AuiToolBarItem_SetId(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """GetId(self) -> int"""
+ return _aui.AuiToolBarItem_GetId(*args, **kwargs)
+
+ def SetKind(*args, **kwargs):
+ """SetKind(self, int newKind)"""
+ return _aui.AuiToolBarItem_SetKind(*args, **kwargs)
+
+ def GetKind(*args, **kwargs):
+ """GetKind(self) -> int"""
+ return _aui.AuiToolBarItem_GetKind(*args, **kwargs)
+
+ def SetState(*args, **kwargs):
+ """SetState(self, int newState)"""
+ return _aui.AuiToolBarItem_SetState(*args, **kwargs)
+
+ def GetState(*args, **kwargs):
+ """GetState(self) -> int"""
+ return _aui.AuiToolBarItem_GetState(*args, **kwargs)
+
+ def SetSizerItem(*args, **kwargs):
+ """SetSizerItem(self, SizerItem s)"""
+ return _aui.AuiToolBarItem_SetSizerItem(*args, **kwargs)
+
+ def GetSizerItem(*args, **kwargs):
+ """GetSizerItem(self) -> SizerItem"""
+ return _aui.AuiToolBarItem_GetSizerItem(*args, **kwargs)
+
+ def SetLabel(*args, **kwargs):
+ """SetLabel(self, String s)"""
+ return _aui.AuiToolBarItem_SetLabel(*args, **kwargs)
+
+ def GetLabel(*args, **kwargs):
+ """GetLabel(self) -> String"""
+ return _aui.AuiToolBarItem_GetLabel(*args, **kwargs)
+
+ def SetBitmap(*args, **kwargs):
+ """SetBitmap(self, Bitmap bmp)"""
+ return _aui.AuiToolBarItem_SetBitmap(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self) -> Bitmap"""
+ return _aui.AuiToolBarItem_GetBitmap(*args, **kwargs)
+
+ def SetDisabledBitmap(*args, **kwargs):
+ """SetDisabledBitmap(self, Bitmap bmp)"""
+ return _aui.AuiToolBarItem_SetDisabledBitmap(*args, **kwargs)
+
+ def GetDisabledBitmap(*args, **kwargs):
+ """GetDisabledBitmap(self) -> Bitmap"""
+ return _aui.AuiToolBarItem_GetDisabledBitmap(*args, **kwargs)
+
+ def SetHoverBitmap(*args, **kwargs):
+ """SetHoverBitmap(self, Bitmap bmp)"""
+ return _aui.AuiToolBarItem_SetHoverBitmap(*args, **kwargs)
+
+ def GetHoverBitmap(*args, **kwargs):
+ """GetHoverBitmap(self) -> Bitmap"""
+ return _aui.AuiToolBarItem_GetHoverBitmap(*args, **kwargs)
+
+ def SetShortHelp(*args, **kwargs):
+ """SetShortHelp(self, String s)"""
+ return _aui.AuiToolBarItem_SetShortHelp(*args, **kwargs)
+
+ def GetShortHelp(*args, **kwargs):
+ """GetShortHelp(self) -> String"""
+ return _aui.AuiToolBarItem_GetShortHelp(*args, **kwargs)
+
+ def SetLongHelp(*args, **kwargs):
+ """SetLongHelp(self, String s)"""
+ return _aui.AuiToolBarItem_SetLongHelp(*args, **kwargs)
+
+ def GetLongHelp(*args, **kwargs):
+ """GetLongHelp(self) -> String"""
+ return _aui.AuiToolBarItem_GetLongHelp(*args, **kwargs)
+
+ def SetMinSize(*args, **kwargs):
+ """SetMinSize(self, Size s)"""
+ return _aui.AuiToolBarItem_SetMinSize(*args, **kwargs)
+
+ def GetMinSize(*args, **kwargs):
+ """GetMinSize(self) -> Size"""
+ return _aui.AuiToolBarItem_GetMinSize(*args, **kwargs)
+
+ def SetSpacerPixels(*args, **kwargs):
+ """SetSpacerPixels(self, int s)"""
+ return _aui.AuiToolBarItem_SetSpacerPixels(*args, **kwargs)
+
+ def GetSpacerPixels(*args, **kwargs):
+ """GetSpacerPixels(self) -> int"""
+ return _aui.AuiToolBarItem_GetSpacerPixels(*args, **kwargs)
+
+ def SetProportion(*args, **kwargs):
+ """SetProportion(self, int p)"""
+ return _aui.AuiToolBarItem_SetProportion(*args, **kwargs)
+
+ def GetProportion(*args, **kwargs):
+ """GetProportion(self) -> int"""
+ return _aui.AuiToolBarItem_GetProportion(*args, **kwargs)
+
+ def SetActive(*args, **kwargs):
+ """SetActive(self, bool b)"""
+ return _aui.AuiToolBarItem_SetActive(*args, **kwargs)
+
+ def IsActive(*args, **kwargs):
+ """IsActive(self) -> bool"""
+ return _aui.AuiToolBarItem_IsActive(*args, **kwargs)
+
+ def SetHasDropDown(*args, **kwargs):
+ """SetHasDropDown(self, bool b)"""
+ return _aui.AuiToolBarItem_SetHasDropDown(*args, **kwargs)
+
+ def HasDropDown(*args, **kwargs):
+ """HasDropDown(self) -> bool"""
+ return _aui.AuiToolBarItem_HasDropDown(*args, **kwargs)
+
+ def SetSticky(*args, **kwargs):
+ """SetSticky(self, bool b)"""
+ return _aui.AuiToolBarItem_SetSticky(*args, **kwargs)
+
+ def IsSticky(*args, **kwargs):
+ """IsSticky(self) -> bool"""
+ return _aui.AuiToolBarItem_IsSticky(*args, **kwargs)
+
+ def SetUserData(*args, **kwargs):
+ """SetUserData(self, long l)"""
+ return _aui.AuiToolBarItem_SetUserData(*args, **kwargs)
+
+ def GetUserData(*args, **kwargs):
+ """GetUserData(self) -> long"""
+ return _aui.AuiToolBarItem_GetUserData(*args, **kwargs)
+
+ def SetAlignment(*args, **kwargs):
+ """SetAlignment(self, int l)"""
+ return _aui.AuiToolBarItem_SetAlignment(*args, **kwargs)
+
+ def GetAlignment(*args, **kwargs):
+ """GetAlignment(self) -> int"""
+ return _aui.AuiToolBarItem_GetAlignment(*args, **kwargs)
+
+_aui.AuiToolBarItem_swigregister(AuiToolBarItem)
+
+class AuiToolBarArt(object):
+ """Proxy of C++ AuiToolBarArt class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _aui.delete_AuiToolBarArt
+ __del__ = lambda self : None;
+ def Clone(*args, **kwargs):
+ """Clone(self) -> AuiToolBarArt"""
+ return _aui.AuiToolBarArt_Clone(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _aui.AuiToolBarArt_SetFlags(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _aui.AuiToolBarArt_GetFlags(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """SetFont(self, Font font)"""
+ return _aui.AuiToolBarArt_SetFont(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """GetFont(self) -> Font"""
+ return _aui.AuiToolBarArt_GetFont(*args, **kwargs)
+
+ def SetTextOrientation(*args, **kwargs):
+ """SetTextOrientation(self, int orientation)"""
+ return _aui.AuiToolBarArt_SetTextOrientation(*args, **kwargs)
+
+ def GetTextOrientation(*args, **kwargs):
+ """GetTextOrientation(self) -> int"""
+ return _aui.AuiToolBarArt_GetTextOrientation(*args, **kwargs)
+
+ def DrawBackground(*args, **kwargs):
+ """DrawBackground(self, DC dc, Window wnd, Rect rect)"""
+ return _aui.AuiToolBarArt_DrawBackground(*args, **kwargs)
+
+ def DrawPlainBackground(*args, **kwargs):
+ """DrawPlainBackground(self, DC dc, Window wnd, Rect rect)"""
+ return _aui.AuiToolBarArt_DrawPlainBackground(*args, **kwargs)
+
+ def DrawLabel(*args, **kwargs):
+ """DrawLabel(self, DC dc, Window wnd, AuiToolBarItem item, Rect rect)"""
+ return _aui.AuiToolBarArt_DrawLabel(*args, **kwargs)
+
+ def DrawButton(*args, **kwargs):
+ """DrawButton(self, DC dc, Window wnd, AuiToolBarItem item, Rect rect)"""
+ return _aui.AuiToolBarArt_DrawButton(*args, **kwargs)
+
+ def DrawDropDownButton(*args, **kwargs):
+ """DrawDropDownButton(self, DC dc, Window wnd, AuiToolBarItem item, Rect rect)"""
+ return _aui.AuiToolBarArt_DrawDropDownButton(*args, **kwargs)
+
+ def DrawControlLabel(*args, **kwargs):
+ """DrawControlLabel(self, DC dc, Window wnd, AuiToolBarItem item, Rect rect)"""
+ return _aui.AuiToolBarArt_DrawControlLabel(*args, **kwargs)
+
+ def DrawSeparator(*args, **kwargs):
+ """DrawSeparator(self, DC dc, Window wnd, Rect rect)"""
+ return _aui.AuiToolBarArt_DrawSeparator(*args, **kwargs)
+
+ def DrawGripper(*args, **kwargs):
+ """DrawGripper(self, DC dc, Window wnd, Rect rect)"""
+ return _aui.AuiToolBarArt_DrawGripper(*args, **kwargs)
+
+ def DrawOverflowButton(*args, **kwargs):
+ """DrawOverflowButton(self, DC dc, Window wnd, Rect rect, int state)"""
+ return _aui.AuiToolBarArt_DrawOverflowButton(*args, **kwargs)
+
+ def GetLabelSize(*args, **kwargs):
+ """GetLabelSize(self, DC dc, Window wnd, AuiToolBarItem item) -> Size"""
+ return _aui.AuiToolBarArt_GetLabelSize(*args, **kwargs)
+
+ def GetToolSize(*args, **kwargs):
+ """GetToolSize(self, DC dc, Window wnd, AuiToolBarItem item) -> Size"""
+ return _aui.AuiToolBarArt_GetToolSize(*args, **kwargs)
+
+ def GetElementSize(*args, **kwargs):
+ """GetElementSize(self, int elementId) -> int"""
+ return _aui.AuiToolBarArt_GetElementSize(*args, **kwargs)
+
+ def SetElementSize(*args, **kwargs):
+ """SetElementSize(self, int elementId, int size)"""
+ return _aui.AuiToolBarArt_SetElementSize(*args, **kwargs)
+
+ def ShowDropDown(*args, **kwargs):
+ """ShowDropDown(self, Window wnd, wxAuiToolBarItemArray items) -> int"""
+ return _aui.AuiToolBarArt_ShowDropDown(*args, **kwargs)
+
+_aui.AuiToolBarArt_swigregister(AuiToolBarArt)
+
+class AuiDefaultToolBarArt(AuiToolBarArt):
+ """Proxy of C++ AuiDefaultToolBarArt class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> AuiDefaultToolBarArt"""
+ _aui.AuiDefaultToolBarArt_swiginit(self,_aui.new_AuiDefaultToolBarArt(*args, **kwargs))
+ __swig_destroy__ = _aui.delete_AuiDefaultToolBarArt
+ __del__ = lambda self : None;
+_aui.AuiDefaultToolBarArt_swigregister(AuiDefaultToolBarArt)
+
+class AuiToolBar(_core.Control):
+ """Proxy of C++ AuiToolBar class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> AuiToolBar
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=AUI_TB_DEFAULT_STYLE) -> AuiToolBar
+ """
+ _aui.AuiToolBar_swiginit(self,_aui.new_AuiToolBar(*args))
+ __swig_destroy__ = _aui.delete_AuiToolBar
+ __del__ = lambda self : None;
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=AUI_TB_DEFAULT_STYLE) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _aui.AuiToolBar_Create(*args, **kwargs)
+
+ def SetArtProvider(*args, **kwargs):
+ """SetArtProvider(self, AuiToolBarArt art)"""
+ return _aui.AuiToolBar_SetArtProvider(*args, **kwargs)
+
+ def GetArtProvider(*args, **kwargs):
+ """GetArtProvider(self) -> AuiToolBarArt"""
+ return _aui.AuiToolBar_GetArtProvider(*args, **kwargs)
+
+ def AddTool(*args):
+ """
+ AddTool(self, int toolId, String label, Bitmap bitmap, String shortHelpString=wxEmptyString,
+ int kind=ITEM_NORMAL) -> AuiToolBarItem
+ AddTool(self, int toolId, String label, Bitmap bitmap, Bitmap disabledBitmap,
+ int kind, String shortHelpString,
+ String longHelpString, Object clientData) -> AuiToolBarItem
+ AddTool(self, int toolId, Bitmap bitmap, Bitmap disabledBitmap, bool toggle=False,
+ Object clientData=None, String shortHelpString=wxEmptyString,
+ String longHelpString=wxEmptyString) -> AuiToolBarItem
+ """
+ return _aui.AuiToolBar_AddTool(*args)
+
+ def AddLabel(*args, **kwargs):
+ """AddLabel(self, int toolId, String label=wxEmptyString, int width=-1) -> AuiToolBarItem"""
+ return _aui.AuiToolBar_AddLabel(*args, **kwargs)
+
+ def AddControl(*args, **kwargs):
+ """AddControl(self, Control control, String label=wxEmptyString) -> AuiToolBarItem"""
+ return _aui.AuiToolBar_AddControl(*args, **kwargs)
+
+ def AddSeparator(*args, **kwargs):
+ """AddSeparator(self) -> AuiToolBarItem"""
+ return _aui.AuiToolBar_AddSeparator(*args, **kwargs)
+
+ def AddSpacer(*args, **kwargs):
+ """AddSpacer(self, int pixels) -> AuiToolBarItem"""
+ return _aui.AuiToolBar_AddSpacer(*args, **kwargs)
+
+ def AddStretchSpacer(*args, **kwargs):
+ """AddStretchSpacer(self, int proportion=1) -> AuiToolBarItem"""
+ return _aui.AuiToolBar_AddStretchSpacer(*args, **kwargs)
+
+ def Realize(*args, **kwargs):
+ """Realize(self) -> bool"""
+ return _aui.AuiToolBar_Realize(*args, **kwargs)
+
+ def FindControl(*args, **kwargs):
+ """FindControl(self, int windowId) -> Control"""
+ return _aui.AuiToolBar_FindControl(*args, **kwargs)
+
+ def FindToolByPosition(*args, **kwargs):
+ """FindToolByPosition(self, int x, int y) -> AuiToolBarItem"""
+ return _aui.AuiToolBar_FindToolByPosition(*args, **kwargs)
+
+ def FindToolByIndex(*args, **kwargs):
+ """FindToolByIndex(self, int idx) -> AuiToolBarItem"""
+ return _aui.AuiToolBar_FindToolByIndex(*args, **kwargs)
+
+ def FindTool(*args, **kwargs):
+ """FindTool(self, int toolId) -> AuiToolBarItem"""
+ return _aui.AuiToolBar_FindTool(*args, **kwargs)
+
+ def ClearTools(*args, **kwargs):
+ """ClearTools(self)"""
+ return _aui.AuiToolBar_ClearTools(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """Clear(self)"""
+ return _aui.AuiToolBar_Clear(*args, **kwargs)
+
+ def DeleteTool(*args, **kwargs):
+ """DeleteTool(self, int toolId) -> bool"""
+ return _aui.AuiToolBar_DeleteTool(*args, **kwargs)
+
+ def DeleteByIndex(*args, **kwargs):
+ """DeleteByIndex(self, int toolId) -> bool"""
+ return _aui.AuiToolBar_DeleteByIndex(*args, **kwargs)
+
+ def GetToolCount(*args, **kwargs):
+ """GetToolCount(self) -> size_t"""
+ return _aui.AuiToolBar_GetToolCount(*args, **kwargs)
+
+ def GetToolPos(*args, **kwargs):
+ """GetToolPos(self, int toolId) -> int"""
+ return _aui.AuiToolBar_GetToolPos(*args, **kwargs)
+
+ def GetToolIndex(*args, **kwargs):
+ """GetToolIndex(self, int toolId) -> int"""
+ return _aui.AuiToolBar_GetToolIndex(*args, **kwargs)
+
+ def GetToolFits(*args, **kwargs):
+ """GetToolFits(self, int toolId) -> bool"""
+ return _aui.AuiToolBar_GetToolFits(*args, **kwargs)
+
+ def GetToolRect(*args, **kwargs):
+ """GetToolRect(self, int toolId) -> Rect"""
+ return _aui.AuiToolBar_GetToolRect(*args, **kwargs)
+
+ def GetToolFitsByIndex(*args, **kwargs):
+ """GetToolFitsByIndex(self, int toolId) -> bool"""
+ return _aui.AuiToolBar_GetToolFitsByIndex(*args, **kwargs)
+
+ def GetToolBarFits(*args, **kwargs):
+ """GetToolBarFits(self) -> bool"""
+ return _aui.AuiToolBar_GetToolBarFits(*args, **kwargs)
+
+ def SetMargins(*args):
+ """
+ SetMargins(self, Size size)
+ SetMargins(self, int x, int y)
+ SetMargins(self, int left, int right, int top, int bottom)
+ """
+ return _aui.AuiToolBar_SetMargins(*args)
+
+ def SetToolBitmapSize(*args, **kwargs):
+ """SetToolBitmapSize(self, Size size)"""
+ return _aui.AuiToolBar_SetToolBitmapSize(*args, **kwargs)
+
+ def GetToolBitmapSize(*args, **kwargs):
+ """GetToolBitmapSize(self) -> Size"""
+ return _aui.AuiToolBar_GetToolBitmapSize(*args, **kwargs)
+
+ def GetOverflowVisible(*args, **kwargs):
+ """GetOverflowVisible(self) -> bool"""
+ return _aui.AuiToolBar_GetOverflowVisible(*args, **kwargs)
+
+ def SetOverflowVisible(*args, **kwargs):
+ """SetOverflowVisible(self, bool visible)"""
+ return _aui.AuiToolBar_SetOverflowVisible(*args, **kwargs)
+
+ def GetGripperVisible(*args, **kwargs):
+ """GetGripperVisible(self) -> bool"""
+ return _aui.AuiToolBar_GetGripperVisible(*args, **kwargs)
+
+ def SetGripperVisible(*args, **kwargs):
+ """SetGripperVisible(self, bool visible)"""
+ return _aui.AuiToolBar_SetGripperVisible(*args, **kwargs)
+
+ def ToggleTool(*args, **kwargs):
+ """ToggleTool(self, int toolId, bool state)"""
+ return _aui.AuiToolBar_ToggleTool(*args, **kwargs)
+
+ def GetToolToggled(*args, **kwargs):
+ """GetToolToggled(self, int toolId) -> bool"""
+ return _aui.AuiToolBar_GetToolToggled(*args, **kwargs)
+
+ def EnableTool(*args, **kwargs):
+ """EnableTool(self, int toolId, bool state)"""
+ return _aui.AuiToolBar_EnableTool(*args, **kwargs)
+
+ def GetToolEnabled(*args, **kwargs):
+ """GetToolEnabled(self, int toolId) -> bool"""
+ return _aui.AuiToolBar_GetToolEnabled(*args, **kwargs)
+
+ def SetToolDropDown(*args, **kwargs):
+ """SetToolDropDown(self, int toolId, bool dropdown)"""
+ return _aui.AuiToolBar_SetToolDropDown(*args, **kwargs)
+
+ def GetToolDropDown(*args, **kwargs):
+ """GetToolDropDown(self, int toolId) -> bool"""
+ return _aui.AuiToolBar_GetToolDropDown(*args, **kwargs)
+
+ def SetToolBorderPadding(*args, **kwargs):
+ """SetToolBorderPadding(self, int padding)"""
+ return _aui.AuiToolBar_SetToolBorderPadding(*args, **kwargs)
+
+ def GetToolBorderPadding(*args, **kwargs):
+ """GetToolBorderPadding(self) -> int"""
+ return _aui.AuiToolBar_GetToolBorderPadding(*args, **kwargs)
+
+ def SetToolTextOrientation(*args, **kwargs):
+ """SetToolTextOrientation(self, int orientation)"""
+ return _aui.AuiToolBar_SetToolTextOrientation(*args, **kwargs)
+
+ def GetToolTextOrientation(*args, **kwargs):
+ """GetToolTextOrientation(self) -> int"""
+ return _aui.AuiToolBar_GetToolTextOrientation(*args, **kwargs)
+
+ def SetToolPacking(*args, **kwargs):
+ """SetToolPacking(self, int packing)"""
+ return _aui.AuiToolBar_SetToolPacking(*args, **kwargs)
+
+ def GetToolPacking(*args, **kwargs):
+ """GetToolPacking(self) -> int"""
+ return _aui.AuiToolBar_GetToolPacking(*args, **kwargs)
+
+ def SetToolProportion(*args, **kwargs):
+ """SetToolProportion(self, int toolId, int proportion)"""
+ return _aui.AuiToolBar_SetToolProportion(*args, **kwargs)
+
+ def GetToolProportion(*args, **kwargs):
+ """GetToolProportion(self, int toolId) -> int"""
+ return _aui.AuiToolBar_GetToolProportion(*args, **kwargs)
+
+ def SetToolSeparation(*args, **kwargs):
+ """SetToolSeparation(self, int separation)"""
+ return _aui.AuiToolBar_SetToolSeparation(*args, **kwargs)
+
+ def GetToolSeparation(*args, **kwargs):
+ """GetToolSeparation(self) -> int"""
+ return _aui.AuiToolBar_GetToolSeparation(*args, **kwargs)
+
+ def SetToolSticky(*args, **kwargs):
+ """SetToolSticky(self, int toolId, bool sticky)"""
+ return _aui.AuiToolBar_SetToolSticky(*args, **kwargs)
+
+ def GetToolSticky(*args, **kwargs):
+ """GetToolSticky(self, int toolId) -> bool"""
+ return _aui.AuiToolBar_GetToolSticky(*args, **kwargs)
+
+ def GetToolLabel(*args, **kwargs):
+ """GetToolLabel(self, int toolId) -> String"""
+ return _aui.AuiToolBar_GetToolLabel(*args, **kwargs)
+
+ def SetToolLabel(*args, **kwargs):
+ """SetToolLabel(self, int toolId, String label)"""
+ return _aui.AuiToolBar_SetToolLabel(*args, **kwargs)
+
+ def GetToolBitmap(*args, **kwargs):
+ """GetToolBitmap(self, int toolId) -> Bitmap"""
+ return _aui.AuiToolBar_GetToolBitmap(*args, **kwargs)
+
+ def SetToolBitmap(*args, **kwargs):
+ """SetToolBitmap(self, int toolId, Bitmap bitmap)"""
+ return _aui.AuiToolBar_SetToolBitmap(*args, **kwargs)
+
+ def GetToolShortHelp(*args, **kwargs):
+ """GetToolShortHelp(self, int toolId) -> String"""
+ return _aui.AuiToolBar_GetToolShortHelp(*args, **kwargs)
+
+ def SetToolShortHelp(*args, **kwargs):
+ """SetToolShortHelp(self, int toolId, String helpString)"""
+ return _aui.AuiToolBar_SetToolShortHelp(*args, **kwargs)
+
+ def GetToolLongHelp(*args, **kwargs):
+ """GetToolLongHelp(self, int toolId) -> String"""
+ return _aui.AuiToolBar_GetToolLongHelp(*args, **kwargs)
+
+ def SetToolLongHelp(*args, **kwargs):
+ """SetToolLongHelp(self, int toolId, String helpString)"""
+ return _aui.AuiToolBar_SetToolLongHelp(*args, **kwargs)
+
+ def SetCustomOverflowItems(*args, **kwargs):
+ """SetCustomOverflowItems(self, wxAuiToolBarItemArray prepend, wxAuiToolBarItemArray append)"""
+ return _aui.AuiToolBar_SetCustomOverflowItems(*args, **kwargs)
+
+ def GetHintSize(*args, **kwargs):
+ """GetHintSize(self, int dockDirection) -> Size"""
+ return _aui.AuiToolBar_GetHintSize(*args, **kwargs)
+
+ def IsPaneValid(*args, **kwargs):
+ """IsPaneValid(self, AuiPaneInfo pane) -> bool"""
+ return _aui.AuiToolBar_IsPaneValid(*args, **kwargs)
+
+_aui.AuiToolBar_swigregister(AuiToolBar)
+
+wxEVT_AUITOOLBAR_TOOL_DROPDOWN = _aui.wxEVT_AUITOOLBAR_TOOL_DROPDOWN
+wxEVT_AUITOOLBAR_OVERFLOW_CLICK = _aui.wxEVT_AUITOOLBAR_OVERFLOW_CLICK
+wxEVT_AUITOOLBAR_RIGHT_CLICK = _aui.wxEVT_AUITOOLBAR_RIGHT_CLICK
+wxEVT_AUITOOLBAR_MIDDLE_CLICK = _aui.wxEVT_AUITOOLBAR_MIDDLE_CLICK
+wxEVT_AUITOOLBAR_BEGIN_DRAG = _aui.wxEVT_AUITOOLBAR_BEGIN_DRAG
+EVT_AUITOOLBAR_TOOL_DROPDOWN = wx.PyEventBinder( wxEVT_AUITOOLBAR_TOOL_DROPDOWN, 1 )
+EVT_AUITOOLBAR_OVERFLOW_CLICK = wx.PyEventBinder( wxEVT_AUITOOLBAR_OVERFLOW_CLICK, 1 )
+EVT_AUITOOLBAR_RIGHT_CLICK = wx.PyEventBinder( wxEVT_AUITOOLBAR_RIGHT_CLICK, 1 )
+EVT_AUITOOLBAR_MIDDLE_CLICK = wx.PyEventBinder( wxEVT_AUITOOLBAR_MIDDLE_CLICK, 1 )
+EVT_AUITOOLBAR_BEGIN_DRAG = wx.PyEventBinder( wxEVT_AUITOOLBAR_BEGIN_DRAG, 1 )
+
+class AuiTabArt(object):
+ """Proxy of C++ AuiTabArt class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _aui.delete_AuiTabArt
+ __del__ = lambda self : None;
+ def Clone(*args, **kwargs):
+ """Clone(self) -> AuiTabArt"""
+ return _aui.AuiTabArt_Clone(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _aui.AuiTabArt_SetFlags(*args, **kwargs)
+
+ def SetSizingInfo(*args, **kwargs):
+ """SetSizingInfo(self, Size tabCtrlSize, size_t tabCount)"""
+ return _aui.AuiTabArt_SetSizingInfo(*args, **kwargs)
+
+ def SetNormalFont(*args, **kwargs):
+ """SetNormalFont(self, Font font)"""
+ return _aui.AuiTabArt_SetNormalFont(*args, **kwargs)
+
+ def SetSelectedFont(*args, **kwargs):
+ """SetSelectedFont(self, Font font)"""
+ return _aui.AuiTabArt_SetSelectedFont(*args, **kwargs)
+
+ def SetMeasuringFont(*args, **kwargs):
+ """SetMeasuringFont(self, Font font)"""
+ return _aui.AuiTabArt_SetMeasuringFont(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """SetColour(self, Colour colour)"""
+ return _aui.AuiTabArt_SetColour(*args, **kwargs)
+
+ def SetActiveColour(*args, **kwargs):
+ """SetActiveColour(self, Colour colour)"""
+ return _aui.AuiTabArt_SetActiveColour(*args, **kwargs)
+
+ def DrawBorder(*args, **kwargs):
+ """DrawBorder(self, DC dc, Window wnd, Rect rect)"""
+ return _aui.AuiTabArt_DrawBorder(*args, **kwargs)
+
+ def DrawBackground(*args, **kwargs):
+ """DrawBackground(self, DC dc, Window wnd, Rect rect)"""
+ return _aui.AuiTabArt_DrawBackground(*args, **kwargs)
+
+ def ShowDropDown(*args, **kwargs):
+ """ShowDropDown(self, Window wnd, AuiNotebookPageArray items, int activeIdx) -> int"""
+ return _aui.AuiTabArt_ShowDropDown(*args, **kwargs)
+
+ def GetIndentSize(*args, **kwargs):
+ """GetIndentSize(self) -> int"""
+ return _aui.AuiTabArt_GetIndentSize(*args, **kwargs)
+
+ def GetBorderWidth(*args, **kwargs):
+ """GetBorderWidth(self, Window wnd) -> int"""
+ return _aui.AuiTabArt_GetBorderWidth(*args, **kwargs)
+
+ def GetAdditionalBorderSpace(*args, **kwargs):
+ """GetAdditionalBorderSpace(self, Window wnd) -> int"""
+ return _aui.AuiTabArt_GetAdditionalBorderSpace(*args, **kwargs)
+
+ def GetBestTabCtrlSize(*args, **kwargs):
+ """GetBestTabCtrlSize(self, Window wnd, AuiNotebookPageArray pages, Size requiredBmpSize) -> int"""
+ return _aui.AuiTabArt_GetBestTabCtrlSize(*args, **kwargs)
+
+ def DrawTab(*args, **kwargs):
+ """
+ DrawTab(self, DC dc, Window wnd, AuiNotebookPage pane, Rect in_rect,
+ int close_button_state) -> PyObject
+ """
+ return _aui.AuiTabArt_DrawTab(*args, **kwargs)
+
+ def DrawButton(*args, **kwargs):
+ """
+ DrawButton(self, DC dc, Window wnd, Rect in_rect, int bitmap_id, int button_state,
+ int orientation) -> PyObject
+ """
+ return _aui.AuiTabArt_DrawButton(*args, **kwargs)
+
+ def GetTabSize(*args, **kwargs):
+ """
+ GetTabSize(self, DC dc, Window wnd, String caption, Bitmap bitmap, bool active,
+ int close_button_state) -> PyObject
+ """
+ return _aui.AuiTabArt_GetTabSize(*args, **kwargs)
+
+_aui.AuiTabArt_swigregister(AuiTabArt)
+
+class AuiGenericTabArt(AuiTabArt):
+ """Proxy of C++ AuiGenericTabArt class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> AuiGenericTabArt"""
+ _aui.AuiGenericTabArt_swiginit(self,_aui.new_AuiGenericTabArt(*args, **kwargs))
+ __swig_destroy__ = _aui.delete_AuiGenericTabArt
+ __del__ = lambda self : None;
+_aui.AuiGenericTabArt_swigregister(AuiGenericTabArt)
+
+class AuiSimpleTabArt(AuiTabArt):
+ """Proxy of C++ AuiSimpleTabArt class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> AuiSimpleTabArt"""
+ _aui.AuiSimpleTabArt_swiginit(self,_aui.new_AuiSimpleTabArt(*args, **kwargs))
+ __swig_destroy__ = _aui.delete_AuiSimpleTabArt
+ __del__ = lambda self : None;
+_aui.AuiSimpleTabArt_swigregister(AuiSimpleTabArt)
+
+class PyAuiDockArt(AuiDefaultDockArt):
+ """
+ This version of the `AuiDockArt` class has been instrumented to be
+ subclassable in Python and to reflect all calls to the C++ base class
+ methods to the Python methods implemented in the derived class.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PyAuiDockArt
+
+ This version of the `AuiDockArt` class has been instrumented to be
+ subclassable in Python and to reflect all calls to the C++ base class
+ methods to the Python methods implemented in the derived class.
+ """
+ _aui.PyAuiDockArt_swiginit(self,_aui.new_PyAuiDockArt(*args, **kwargs))
+ PyAuiDockArt._setCallbackInfo(self, self, PyAuiDockArt)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _aui.PyAuiDockArt__setCallbackInfo(*args, **kwargs)
+
+_aui.PyAuiDockArt_swigregister(PyAuiDockArt)
+
+class PyAuiTabArt(AuiGenericTabArt):
+ """
+ This version of the `TabArt` class has been instrumented to be
+ subclassable in Python and to reflect all calls to the C++ base class
+ methods to the Python methods implemented in the derived class.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PyAuiTabArt
+
+ This version of the `TabArt` class has been instrumented to be
+ subclassable in Python and to reflect all calls to the C++ base class
+ methods to the Python methods implemented in the derived class.
+ """
+ _aui.PyAuiTabArt_swiginit(self,_aui.new_PyAuiTabArt(*args, **kwargs))
+ PyAuiTabArt._setCallbackInfo(self, self, PyAuiTabArt)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _aui.PyAuiTabArt__setCallbackInfo(*args, **kwargs)
+
+ def GetNormalFont(*args, **kwargs):
+ """GetNormalFont(self) -> Font"""
+ return _aui.PyAuiTabArt_GetNormalFont(*args, **kwargs)
+
+ def GetSelectedFont(*args, **kwargs):
+ """GetSelectedFont(self) -> Font"""
+ return _aui.PyAuiTabArt_GetSelectedFont(*args, **kwargs)
+
+ def GetMeasuringFont(*args, **kwargs):
+ """GetMeasuringFont(self) -> Font"""
+ return _aui.PyAuiTabArt_GetMeasuringFont(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _aui.PyAuiTabArt_GetFlags(*args, **kwargs)
+
+_aui.PyAuiTabArt_swigregister(PyAuiTabArt)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/build/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/build/__init__.py
new file mode 100644
index 0000000..4bf06ac
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/build/__init__.py
@@ -0,0 +1,20 @@
+# A Python package
+"""
+This package provides the config module, which is used by wxPython's
+setup.py distutils script. It was moved here so it would be installed
+with the rest of wxPython and could therefore be used by the setup.py
+for other projects that needed this same info and functionality (most
+likely in order to be compatible with wxPython.)
+
+See config.py and wxPython's setup.py for more details.
+
+"""
+
+
+# Exclude config from the epydoc docs because it will currently cause
+# a lot of noise. Once it has been refactored then add "config" to
+# the list below.
+
+__all__ = []
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/build/build_options.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/build/build_options.py
new file mode 100644
index 0000000..eb0e02a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/build/build_options.py
@@ -0,0 +1,10 @@
+
+UNICODE=1
+UNDEF_NDEBUG=1
+INSTALL_MULTIVERSION=1
+FLAVOUR=""
+EP_ADD_OPTS=1
+EP_FULL_VER=0
+WX_CONFIG="C:/msys64/mingw32/bin/wx-config --toolkit=msw --unicode=yes --version=3.0"
+WXPORT="msw"
+MONOLITHIC=0
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/build/cfg_version.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/build/cfg_version.py
new file mode 100644
index 0000000..677c636
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/build/cfg_version.py
@@ -0,0 +1,8 @@
+
+# wxPython version numbers used in build
+
+VER_MAJOR = 3 # The first three must match wxWidgets
+VER_MINOR = 0
+VER_RELEASE = 2
+VER_SUBREL = 0 # wxPython release num for x.y.z release of wxWidgets
+VER_FLAGS = "" # release flags, such as prerelease or RC num, etc.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/build/config.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/build/config.py
new file mode 100644
index 0000000..08f8d6a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/build/config.py
@@ -0,0 +1,1258 @@
+#----------------------------------------------------------------------
+# Name: wx.build.config
+# Purpose: Most of the contents of this module used to be located
+# in wxPython's setup.py script. It was moved here so
+# it would be installed with the rest of wxPython and
+# could therefore be used by the setup.py for other
+# projects that needed this same info and functionality
+# (most likely in order to be compatible with wxPython.)
+#
+# This split from setup.py is still fairly rough, and
+# some things may still get shuffled back and forth,
+# refactored, etc. Please send me any comments and
+# suggestions about this.
+#
+# Author: Robin Dunn
+#
+# Created: 23-March-2004
+# RCS-ID: $Id$
+# Copyright: (c) 2004 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import sys, os, glob, fnmatch, tempfile
+import subprocess
+import re
+
+EGGing = 'bdist_egg' in sys.argv or 'egg_info' in sys.argv
+if not EGGing:
+ from distutils.core import setup, Extension
+else:
+ # EXPERIMENTAL Egg support...
+ try:
+ import ez_setup
+ ez_setup.use_setuptools()
+ from setuptools import setup, Extension
+ except ImportError:
+ print "Setuptools must be installed to build an egg"
+ sys.exit(1)
+
+from distutils.file_util import copy_file
+from distutils.dir_util import mkpath
+from distutils.dep_util import newer
+from distutils.spawn import spawn
+
+import distutils.command.install
+import distutils.command.install_data
+import distutils.command.install_headers
+import distutils.command.clean
+
+from cfg_version import *
+
+#----------------------------------------------------------------------
+# flags and values that affect this script
+#----------------------------------------------------------------------
+
+DESCRIPTION = "Cross platform GUI toolkit for Python"
+AUTHOR = "Robin Dunn"
+AUTHOR_EMAIL = "Robin Dunn <robin@alldunn.com>"
+URL = "http://wxPython.org/"
+DOWNLOAD_URL = "http://wxPython.org/download.php"
+LICENSE = "wxWidgets Library License (LGPL derivative)"
+PLATFORMS = "WIN32,OSX,POSIX"
+KEYWORDS = "GUI,wx,wxWindows,wxWidgets,cross-platform,awesome"
+
+LONG_DESCRIPTION = """\
+wxPython is a GUI toolkit for Python that is a wrapper around the
+wxWidgets C++ GUI library. wxPython provides a large variety of
+window types and controls, all implemented with a native look and
+feel (by using the native widgets) on the platforms upon which it is
+supported.
+"""
+
+CLASSIFIERS = """\
+Development Status :: 6 - Mature
+Environment :: MacOS X :: Carbon
+Environment :: Win32 (MS Windows)
+Environment :: X11 Applications :: GTK
+Intended Audience :: Developers
+License :: OSI Approved
+Operating System :: MacOS :: MacOS X
+Operating System :: Microsoft :: Windows :: Windows 98/2000/XP/Vista
+Operating System :: POSIX
+Programming Language :: Python
+Topic :: Software Development :: User Interfaces
+"""
+
+## License :: OSI Approved :: wxWidgets Library Licence
+
+
+# Config values below this point can be reset on the setup.py command line.
+
+BUILD_GLCANVAS = 1 # If true, build the contrib/glcanvas extension module
+BUILD_STC = 1 # If true, build the contrib/stc extension module
+BUILD_GIZMOS = 1 # Build a module for the gizmos contrib library
+BUILD_DLLWIDGET = 0# Build a module that enables unknown wx widgets
+ # to be loaded from a DLL and to be used from Python.
+
+ # Internet Explorer wrapper (experimental)
+BUILD_ACTIVEX = (os.name == 'nt')
+
+
+CORE_ONLY = 0 # if true, don't build any of the above
+
+PREP_ONLY = 0 # Only run the prepatory steps, not the actual build.
+
+USE_SWIG = 0 # Should we actually execute SWIG, or just use the
+ # files already in the distribution?
+
+SWIG = "swig" # The swig executable to use.
+
+BUILD_RENAMERS = 0 # Should we build the renamer modules too?
+
+FULL_DOCS = 0 # Some docstrings are split into a basic docstring and a
+ # details string. Setting this flag to 1 will
+ # cause the two strings to be combined and output
+ # as the full docstring.
+
+UNICODE = 1 # This will pass the 'wxUSE_UNICODE' flag to SWIG and
+ # will ensure that the right headers are found and the
+ # right libs are linked.
+
+UNDEF_NDEBUG = 1 # Python 2.2 on Unix/Linux by default defines NDEBUG,
+ # and distutils will pick this up and use it on the
+ # compile command-line for the extensions. This could
+ # conflict with how wxWidgets was built. If NDEBUG is
+ # set then wxWidgets' __WXDEBUG__ setting will be turned
+ # off. If wxWidgets was actually built with it turned
+ # on then you end up with mismatched class structures,
+ # and wxPython will crash.
+
+NO_SCRIPTS = 0 # Don't install the tool scripts
+NO_HEADERS = 0 # Don't install the wxPython *.h and *.i files
+
+INSTALL_MULTIVERSION = 1 # Install the packages such that multiple versions
+ # can co-exist. When turned on the wx and wxPython
+ # pacakges will be installed in a versioned subdir
+ # of site-packages, and a *.pth file will be
+ # created that adds that dir to the sys.path. In
+ # addition, a wxselect.py module will be installed
+ # to site-pacakges that will allow applications to
+ # choose a specific version if more than one is
+ # installed.
+
+FLAVOUR = "" # Optional flavour string to be appended to VERSION
+ # in MULTIVERSION installs
+
+EP_ADD_OPTS = 1 # When doing MULTIVERSION installs the wx port and
+ # ansi/unicode settings can optionally be added to the
+ # subdir path used in site-packages
+
+EP_FULL_VER = 0 # When doing MULTIVERSION installs the default is to
+ # put only 2 or 3 (depending on stable/unstable) of
+ # the version compnonents into the "extra path"
+ # subdir of site-packages. Setting this option to
+ # 1 will cause the full 4 components of the version
+ # number to be used instead.
+
+WX_CONFIG = None # Usually you shouldn't need to touch this, but you can set
+ # it to pass an alternate version of wx-config or alternate
+ # flags, eg. as required by the .deb in-tree build. By
+ # default a wx-config command will be assembled based on
+ # version, port, etc. and it will be looked for on the
+ # default $PATH.
+
+SYS_WX_CONFIG = None # When installing an in tree build, setup.py uses wx-config
+ # for two different purposes. First, to determine the prefix
+ # where files will be installed, and secondly, to initialise
+ # build_options.py with the correct options for it.
+ # WX_CONFIG is used for the first task. SYS_WX_CONFIG may
+ # be set independently, to the value that should appear in
+ # build_options.py, if it is different to that. The default
+ # is to use the value of WX_CONFIG.
+
+WXPORT = 'gtk2' # On Linux/Unix there are several ports of wxWidgets available.
+ # Setting this value lets you select which will be used for
+ # the wxPython build. Possibilities are 'gtk', 'gtk2',
+ # 'gtk3', and 'x11'. Currently only gtk2, and gtk3 work.
+
+BUILD_BASE = "build" # Directory to use for temporary build files.
+ # This name will be appended to if the WXPORT or
+ # the UNICODE flags are set to non-standard
+ # values. See below.
+
+
+CONTRIBS_INC = "" # A dir to add as an -I flag when compiling the contribs
+
+
+# Some MSW build settings
+
+MONOLITHIC = 0 # The core wxWidgets lib can be built as either a
+ # single monolithic DLL or as a collection of DLLs.
+ # This flag controls which set of libs will be used
+ # on Windows. (For other platforms it is automatic
+ # via using wx-config.)
+
+ # Version part of wxWidgets LIB/DLL names
+WXDLLVER = '%d%d' % (VER_MAJOR, VER_MINOR)
+
+
+COMPILER = 'msvc' # Used to select which compiler will be used on
+ # Windows. This not only affects distutils, but
+ # also some of the default flags and other
+ # assumptions in this script. Current supported
+ # values are 'msvc' and 'mingw32'
+
+WXPY_SRC = '.' # Assume we're in the source tree already, but allow the
+ # user to change it, particularly for extension building.
+
+ARCH = '' # If this is set, add an -arch XXX flag to cflags
+ # Only tested (and presumably, needed) for OS X universal
+ # binary builds created using lipo.
+
+
+#----------------------------------------------------------------------
+
+def msg(text):
+ if hasattr(sys, 'setup_is_main') and sys.setup_is_main:
+ print text
+
+
+def opj(*args):
+ path = os.path.join(*args)
+ return os.path.normpath(path)
+
+
+def libFlag():
+ if not debug:
+ rv = ''
+ else:
+ rv = 'd'
+ if UNICODE:
+ rv = 'u' + rv
+ return rv
+
+
+#----------------------------------------------------------------------
+# Some other globals
+#----------------------------------------------------------------------
+
+PKGDIR = 'wx'
+wxpExtensions = []
+DATA_FILES = []
+CLEANUP = []
+
+force = '--force' in sys.argv or '-f' in sys.argv
+debug = '--debug' in sys.argv or '-g' in sys.argv
+cleaning = 'clean' in sys.argv
+
+
+# change the PORT default for wxMac
+if sys.platform[:6] == "darwin":
+ WXPORT = 'osx_carbon'
+
+# and do the same for wxMSW, just for consistency
+if os.name == 'nt':
+ WXPORT = 'msw'
+
+WXPYTHON_TYPE_TABLE = '_wxPython_table'
+
+#----------------------------------------------------------------------
+# Check for build flags on the command line
+#----------------------------------------------------------------------
+
+# Boolean (int) flags
+for flag in [ 'BUILD_ACTIVEX', 'BUILD_DLLWIDGET',
+ 'BUILD_GIZMOS', 'BUILD_GLCANVAS', 'BUILD_STC',
+ 'CORE_ONLY', 'PREP_ONLY', 'USE_SWIG', 'UNICODE',
+ 'UNDEF_NDEBUG', 'NO_SCRIPTS', 'NO_HEADERS', 'BUILD_RENAMERS',
+ 'FULL_DOCS', 'INSTALL_MULTIVERSION', 'EP_ADD_OPTS', 'EP_FULL_VER',
+ 'MONOLITHIC', ]:
+ for x in range(len(sys.argv)):
+ if sys.argv[x].find(flag) == 0:
+ pos = sys.argv[x].find('=') + 1
+ if pos > 0:
+ vars()[flag] = eval(sys.argv[x][pos:])
+ sys.argv[x] = ''
+
+# String options
+for option in ['WX_CONFIG', 'SYS_WX_CONFIG', 'WXDLLVER', 'BUILD_BASE',
+ 'WXPORT', 'SWIG', 'CONTRIBS_INC', 'WXPY_SRC', 'FLAVOUR',
+ 'VER_FLAGS', 'ARCH', 'COMPILER',
+ ]:
+ for x in range(len(sys.argv)):
+ if sys.argv[x].find(option) == 0:
+ pos = sys.argv[x].find('=') + 1
+ if pos > 0:
+ vars()[option] = sys.argv[x][pos:]
+ sys.argv[x] = ''
+
+sys.argv = filter(None, sys.argv)
+
+
+#----------------------------------------------------------------------
+# some helper functions
+#----------------------------------------------------------------------
+
+def Verify_WX_CONFIG():
+ """ Called below for the builds that need wx-config, if WX_CONFIG
+ is not set then determines the flags needed based on build
+ options and searches for wx-config on the PATH.
+ """
+ # if WX_CONFIG hasn't been set to an explicit value then construct one.
+ global WX_CONFIG
+ if WX_CONFIG is None:
+ WX_CONFIG='wx-config'
+ port = WXPORT
+ if port == "x11":
+ port = "x11univ"
+ flags = ' --toolkit=%s' % port
+ flags += ' --unicode=%s' % (UNICODE and 'yes' or 'no')
+ flags += ' --version=%s.%s' % (VER_MAJOR, VER_MINOR)
+
+ searchpath = os.environ["PATH"]
+ for p in searchpath.split(':'):
+ fp = os.path.join(p, 'wx-config')
+ if os.path.exists(fp) and os.access(fp, os.X_OK):
+ # success
+ msg("Found wx-config: " + fp)
+ msg(" Using flags: " + flags)
+ WX_CONFIG = fp + flags
+ if hasattr(sys, 'setup_is_main') and not sys.setup_is_main:
+ WX_CONFIG += " 2>/dev/null "
+ break
+ else:
+ msg("ERROR: WX_CONFIG not specified and wx-config not found on the $PATH")
+ # should we exit?
+
+ # TODO: execute WX_CONFIG --list and verify a matching config is found
+
+
+
+def getWxConfigValue(flag):
+ cmd = "%s --version=%s.%s %s" % (WX_CONFIG, VER_MAJOR, VER_MINOR, flag)
+ value = os.popen(cmd, 'r').read()[:-1]
+ return value
+
+
+def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args,
+ swig_deps=[], add_under=False):
+ """Run SWIG the way I want it done"""
+
+ if USE_SWIG and not os.path.exists(os.path.join(dir, gendir)):
+ os.mkdir(os.path.join(dir, gendir))
+
+ sources = []
+
+ if add_under: pre = '_'
+ else: pre = ''
+
+ for file in files:
+ basefile = os.path.splitext(file)[0]
+ i_file = os.path.join(dir, file)
+ py_file = os.path.join(dir, gendir, pre+basefile+'.py')
+ cpp_file = os.path.join(dir, gendir, pre+basefile+'_wrap.cpp')
+
+ if add_under:
+ interface = ['-interface', '_'+basefile+'_']
+ else:
+ interface = []
+
+ sources.append(cpp_file)
+
+ if not cleaning and USE_SWIG:
+ for dep in swig_deps:
+ # this may fail for external builds, but it's not
+ # a fatal error, so keep going.
+ try:
+ if newer(dep, py_file) or newer(dep, cpp_file):
+ force = 1
+ break
+ except:
+ pass
+
+ if force or newer(i_file, py_file) or newer(i_file, cpp_file):
+ ## we need forward slashes here, even on win32
+ #cpp_file = opj(cpp_file) #'/'.join(cpp_file.split('\\'))
+ #i_file = opj(i_file) #'/'.join(i_file.split('\\'))
+
+ if BUILD_RENAMERS:
+ xmltemp = tempfile.mktemp('.xml')
+
+ # First run swig to produce the XML file, adding
+ # an extra -D that prevents the old rename
+ # directives from being used
+ cmd = [ swig_cmd ] + swig_args + \
+ [ '-DBUILDING_RENAMERS', '-xmlout', xmltemp ] + \
+ ['-I'+dir, '-o', cpp_file, i_file]
+ msg(' '.join(cmd))
+ spawn(cmd)
+
+ # Next run build_renamers to process the XML
+ myRenamer = BuildRenamers()
+ myRenamer.run(dir, pre+basefile, xmltemp)
+ os.remove(xmltemp)
+
+ # Then run swig for real
+ cmd = [ swig_cmd ] + swig_args + interface + \
+ ['-I'+dir, '-o', cpp_file, i_file]
+ msg(' '.join(cmd))
+ spawn(cmd)
+
+
+ # copy the generated python file to the package directory
+ copy_file(py_file, package, update=not force, verbose=0)
+ CLEANUP.append(opj(package, os.path.basename(py_file)))
+
+ return sources
+
+
+def swig_version():
+ # It may come on either stdout or stderr, depending on the
+ # version, so read both.
+ p = subprocess.Popen(SWIG + ' -version', shell=True, universal_newlines=True,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stext = p.stdout.read() + p.stderr.read()
+ import re
+ match = re.search(r'[0-9]+\.[0-9]+\.[0-9]+$', stext, re.MULTILINE)
+ if not match:
+ raise RuntimeError('SWIG version not found')
+ SVER = match.group(0)
+ return SVER
+
+
+# Specializations of some distutils command classes
+class wx_smart_install_data(distutils.command.install_data.install_data):
+ """need to change self.install_dir to the actual library dir"""
+ def run(self):
+ install_cmd = self.get_finalized_command('install')
+ self.install_dir = getattr(install_cmd, 'install_lib')
+ return distutils.command.install_data.install_data.run(self)
+
+
+class wx_extra_clean(distutils.command.clean.clean):
+ """
+ Also cleans stuff that this setup.py copies itself. If the
+ --all flag was used also searches for .pyc, .pyd, .so files
+ """
+ def run(self):
+ from distutils import log
+ from distutils.filelist import FileList
+ global CLEANUP
+
+ distutils.command.clean.clean.run(self)
+
+ if self.all:
+ fl = FileList()
+ fl.include_pattern("*.pyc", 0)
+ fl.include_pattern("*.pyd", 0)
+ fl.include_pattern("*.so", 0)
+ CLEANUP += fl.files
+
+ for f in CLEANUP:
+ if os.path.isdir(f):
+ try:
+ if not self.dry_run and os.path.exists(f):
+ os.rmdir(f)
+ log.info("removing '%s'", f)
+ except IOError:
+ log.warn("unable to remove '%s'", f)
+
+ else:
+ try:
+ if not self.dry_run and os.path.exists(f):
+ os.remove(f)
+ log.info("removing '%s'", f)
+ except IOError:
+ log.warn("unable to remove '%s'", f)
+
+
+
+# The Ubuntu Python adds a --install-layout option to distutils that
+# is used in our package build. If we detect that the current
+# distutils does not have it then make sure that it is removed from
+# the command-line options, otherwise the build will fail.
+for item in distutils.command.install.install.user_options:
+ if item[0] == 'install-layout=':
+ break
+else:
+ for arg in sys.argv:
+ if arg.startswith('--install-layout'):
+ sys.argv.remove(arg)
+ break
+
+
+
+class wx_install(distutils.command.install.install):
+ """
+ Turns off install_path_file
+ """
+ def initialize_options(self):
+ distutils.command.install.install.initialize_options(self)
+ self.install_path_file = 0
+
+
+class wx_install_headers(distutils.command.install_headers.install_headers):
+ """
+ Install the header files to the WXPREFIX, with an extra dir per
+ filename too
+ """
+ def initialize_options(self):
+ self.root = None
+ distutils.command.install_headers.install_headers.initialize_options(self)
+
+ def finalize_options(self):
+ self.set_undefined_options('install', ('root', 'root'))
+ distutils.command.install_headers.install_headers.finalize_options(self)
+
+ def run(self):
+ if os.name == 'nt':
+ return
+ headers = self.distribution.headers
+ if not headers:
+ return
+
+ root = self.root
+ #print "WXPREFIX is %s, root is %s" % (WXPREFIX, root)
+ # hack for universal builds, which append i386/ppc
+ # to the root
+ if root is None or WXPREFIX.startswith(os.path.dirname(root)):
+ root = ''
+ for header, location in headers:
+ install_dir = os.path.normpath(root +
+ WXPREFIX +
+ '/include/wx-%d.%d/wx' % (VER_MAJOR, VER_MINOR) +
+ location)
+ self.mkpath(install_dir)
+ (out, _) = self.copy_file(header, install_dir)
+ self.outfiles.append(out)
+
+
+
+def build_locale_dir(destdir, verbose=1):
+ """Build a locale dir under the wxPython package for MSW"""
+ moFiles = glob.glob(opj(WXDIR, 'locale', '*.mo'))
+ for src in moFiles:
+ lang = os.path.splitext(os.path.basename(src))[0]
+ #dest = opj(destdir, lang)
+ dest = opj(destdir, lang, 'LC_MESSAGES')
+ mkpath(dest, verbose=verbose)
+ copy_file(src, opj(dest, 'wxstd.mo'), update=1, verbose=verbose)
+ CLEANUP.append(opj(dest, 'wxstd.mo'))
+ CLEANUP.append(dest)
+
+
+def build_locale_list(srcdir):
+ # get a list of all files under the srcdir, to be used for install_data
+ def walk_helper(lst, dirname, files):
+ for f in files:
+ filename = opj(dirname, f)
+ if not os.path.isdir(filename):
+ lst.append( (dirname, [filename]) )
+ file_list = []
+ os.path.walk(srcdir, walk_helper, file_list)
+ return file_list
+
+
+def find_data_files(srcdir, *wildcards, **kw):
+ # get a list of all files under the srcdir matching wildcards,
+ # returned in a format to be used for install_data
+
+ def walk_helper(arg, dirname, files):
+ if '.svn' in dirname:
+ return
+ names = []
+ lst, wildcards = arg
+ for wc in wildcards:
+ wc_name = opj(dirname, wc)
+ for f in files:
+ filename = opj(dirname, f)
+
+ if fnmatch.fnmatch(filename, wc_name) and not os.path.isdir(filename):
+ names.append(filename)
+ if names:
+ lst.append( (dirname, names ) )
+
+ file_list = []
+ recursive = kw.get('recursive', True)
+ if recursive:
+ os.path.walk(srcdir, walk_helper, (file_list, wildcards))
+ else:
+ walk_helper((file_list, wildcards),
+ srcdir,
+ [os.path.basename(f) for f in glob.glob(opj(srcdir, '*'))])
+ return file_list
+
+
+def makeLibName(name):
+ if os.name == 'posix' or COMPILER == 'mingw32':
+ libname = '%s_%s-%s' % (WXBASENAME, name, WXRELEASE)
+ elif name:
+ libname = 'wxmsw%s%s_%s' % (WXDLLVER, libFlag(), name)
+ else:
+ libname = 'wxmsw%s%s' % (WXDLLVER, libFlag())
+ return [libname]
+
+
+def findLib(name, libdirs):
+ name = makeLibName(name)[0]
+ if os.name == 'posix' or COMPILER == 'mingw32':
+ lflags = getWxConfigValue('--libs')
+ lflags = lflags.split()
+
+ # if wx-config --libs output does not start with -L, wx is
+ # installed with a standard prefix and wx-config does not
+ # output these libdirs because they are already searched by
+ # default by the compiler and linker.
+ if lflags[0][:2] != '-L':
+ dirs = libdirs + ['/usr/lib', '/usr/local/lib']
+ else:
+ dirs = libdirs
+ name = 'lib'+name
+ else:
+ dirs = libdirs[:]
+ for d in dirs:
+ p = os.path.join(d, name)
+ if glob.glob(p+'*') != []:
+ return True
+ return False
+
+
+def removeDuplicates(seq):
+ # This code causes problems on OS X as we do need some duplicates
+ # there... TODO: are there actually times when having duplicates hurts us?
+## seen = {}
+## result = []
+## for item in seq:
+## if item in seen:
+## continue
+## seen[item] = 1
+## result.append(item)
+## return result
+ return seq
+
+
+def adjustCFLAGS(cflags, defines, includes):
+ '''Extract the raw -I, -D, and -U flags and put them into
+ defines and includes as needed.'''
+ newCFLAGS = []
+ for flag in cflags:
+ if flag[:2] == '-I':
+ includes.append(flag[2:])
+ elif flag[:2] == '-D':
+ flag = flag[2:]
+ if flag.find('=') == -1:
+ defines.append( (flag, None) )
+ else:
+ defines.append( tuple(flag.split('=')) )
+ elif flag[:2] == '-U':
+ defines.append( (flag[2:], ) )
+ else:
+ newCFLAGS.append(flag)
+ return removeDuplicates(newCFLAGS)
+
+
+
+def adjustLFLAGS(lflags, libdirs, libs):
+ '''Extract the -L and -l flags and put them in libdirs and libs as needed'''
+ newLFLAGS = []
+ for flag in lflags:
+ if flag[:2] == '-L':
+ libdirs.append(flag[2:])
+ elif flag[:2] == '-l':
+ libs.append(flag[2:])
+ else:
+ newLFLAGS.append(flag)
+ return removeDuplicates(newLFLAGS)
+
+
+
+def getExtraPath(shortVer=True, addOpts=False, addRelease=True):
+ """Get the dirname that wxPython will be installed under."""
+
+ if shortVer:
+ # short version, just Major.Minor
+ ep = "wx-%d.%d" % (VER_MAJOR, VER_MINOR)
+
+ # plus release if minor is odd
+ if addRelease and VER_MINOR % 2 == 1:
+ ep += ".%d" % VER_RELEASE
+
+ else:
+ # long version, full version
+ ep = "wx-%d.%d.%d.%d" % (VER_MAJOR, VER_MINOR, VER_RELEASE, VER_SUBREL)
+
+ if addOpts:
+ port = WXPORT
+ if port == "msw": port = "win32"
+ #ep += "-%s-%s" % (WXPORT, (UNICODE and 'unicode' or 'ansi'))
+ # no more ansi builds, so no need to include chartype in the path any more
+ ep += '-' + WXPORT
+
+ if FLAVOUR:
+ ep += "-" + FLAVOUR
+
+ return ep
+
+
+def getoutput(cmd):
+ sp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ output = None
+ output = sp.stdout.read()
+ if sys.version_info > (3,):
+ output = output.decode('utf-8') # TODO: is utf-8 okay here?
+ output = output.rstrip()
+ rval = sp.wait()
+ if rval:
+ # Failed!
+ print("Command '%s' failed with exit code %d." % (cmd, rval))
+ sys.exit(rval)
+ return output
+
+def getVisCVersion():
+ text = getoutput("cl.exe")
+ if 'Version 13' in text:
+ return '71'
+ if 'Version 15' in text:
+ return '90'
+ # TODO: Add more tests to get the other versions...
+ else:
+ return 'UNKNOWN'
+
+#----------------------------------------------------------------------
+# These functions and class are copied from distutils in Python 2.5
+# and then grafted back into the distutils modules so we can change
+# how the -arch and -isysroot compiler args are handled. Basically if
+# -arch is specified in our compiler args then we need to strip all of
+# the -arch and -isysroot args provided by Python.
+
+import distutils.unixccompiler
+import distutils.sysconfig
+from distutils.errors import DistutilsExecError, CompileError
+
+def _darwin_compiler_fixup(compiler_so, cc_args):
+ """
+ This function will strip '-isysroot PATH' and '-arch ARCH' from the
+ compile flags if the user has specified one of them in extra_compile_flags.
+
+ This is needed because '-arch ARCH' adds another architecture to the
+ build, without a way to remove an architecture. Furthermore GCC will
+ barf if multiple '-isysroot' arguments are present.
+
+ Robin: I've further modified our copy of this function to check if there
+ is a -isysroot flag in the CC/CXX values in the environment. If so then we
+ want to make sure that we keep that one and strip the others, instead of
+ stripping it and leaving Python's.
+ """
+
+ ccHasSysroot = '-isysroot' in os.environ.get('CC', '') \
+ or '-isysroot' in os.environ.get('CXX', '')
+
+ stripArch = stripSysroot = 0
+
+ compiler_so = list(compiler_so)
+ kernel_version = os.uname()[2] # 8.4.3
+ major_version = int(kernel_version.split('.')[0])
+
+ if major_version < 8:
+ # OSX before 10.4.0, these don't support -arch and -isysroot at
+ # all.
+ stripArch = stripSysroot = True
+ else:
+ stripArch = '-arch' in cc_args
+ stripSysroot = '-isysroot' in cc_args or stripArch or ccHasSysroot
+
+ if stripArch:
+ while 1:
+ try:
+ index = compiler_so.index('-arch')
+ # Strip this argument and the next one:
+ del compiler_so[index:index+2]
+ except ValueError:
+ break
+
+ if stripSysroot:
+ try:
+ index = 0
+ if ccHasSysroot:
+ index = compiler_so.index('-isysroot') + 1
+ index = compiler_so.index('-isysroot', index)
+ # Strip this argument and the next one:
+ del compiler_so[index:index+2]
+ except ValueError:
+ pass
+
+ # Check if the SDK that is used during compilation actually exists,
+ # the universal build requires the usage of a universal SDK and not all
+ # users have that installed by default.
+ sysroot = None
+ if '-isysroot' in cc_args:
+ idx = cc_args.index('-isysroot')
+ sysroot = cc_args[idx+1]
+ elif '-isysroot' in compiler_so:
+ idx = compiler_so.index('-isysroot')
+ sysroot = compiler_so[idx+1]
+
+ if sysroot and not os.path.isdir(sysroot):
+ from distutils import log
+ log.warn("Compiling with an SDK that doesn't seem to exist: %s",
+ sysroot)
+ log.warn("Please check your Xcode installation")
+
+ return compiler_so
+
+
+def _darwin_compiler_fixup_24(compiler_so, cc_args):
+ compiler_so = _darwin_compiler_fixup(compiler_so, cc_args)
+ return compiler_so, cc_args
+
+
+class MyUnixCCompiler(distutils.unixccompiler.UnixCCompiler):
+ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+ compiler_so = self.compiler_so
+ if sys.platform == 'darwin':
+ compiler_so = _darwin_compiler_fixup(compiler_so, cc_args + extra_postargs)
+ # Mandriva / Mageia Hack ------------------------------------
+ #self.linker_so = [el for el in self.linker_so if el != '-Wl,--no-undefined']
+ #compiler_so = [el for el in compiler_so if el != '-Werror=format-security']
+ # Mandriva / Mageia Hack ------------------------------------
+ try:
+ self.spawn(compiler_so + cc_args + [src, '-o', obj] +
+ extra_postargs)
+ except DistutilsExecError, msg:
+ raise CompileError, msg
+
+
+_orig_parse_makefile = distutils.sysconfig.parse_makefile
+def _parse_makefile(filename, g=None):
+ rv = _orig_parse_makefile(filename, g)
+
+ # If a different deployment target is specified in the
+ # environment then make sure it is put in the global
+ # config dict.
+ if os.getenv('MACOSX_DEPLOYMENT_TARGET'):
+ val = os.getenv('MACOSX_DEPLOYMENT_TARGET')
+ rv['MACOSX_DEPLOYMENT_TARGET'] = val
+ rv['CONFIGURE_MACOSX_DEPLOYMENT_TARGET'] = val
+
+ return rv
+
+
+distutils.unixccompiler.UnixCCompiler = MyUnixCCompiler
+distutils.unixccompiler._darwin_compiler_fixup = _darwin_compiler_fixup
+distutils.unixccompiler._darwin_compiler = _darwin_compiler_fixup_24
+distutils.sysconfig.parse_makefile = _parse_makefile
+
+
+#----------------------------------------------------------------------
+# Another hack-job for the CygwinCCompiler class, this time replacing
+# the _compile function with one that will pass the -I flags to windres.
+
+import distutils.cygwinccompiler
+from distutils.errors import DistutilsExecError, CompileError
+
+def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+ if ext == '.rc' or ext == '.res':
+ # gcc needs '.res' and '.rc' compiled to object files !!!
+ try:
+ #self.spawn(["windres", "-i", src, "-o", obj])
+ self.spawn(["windres", "-i", src, "-o", obj] +
+ [arg for arg in cc_args if arg.startswith("-I")] )
+ except DistutilsExecError, msg:
+ raise CompileError, msg
+ else: # for other files use the C-compiler
+ try:
+ self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
+ extra_postargs)
+ except DistutilsExecError, msg:
+ raise CompileError, msg
+
+distutils.cygwinccompiler.CygwinCCompiler._compile = _compile
+
+
+#----------------------------------------------------------------------
+# Yet another distutils hack, this time for the msvc9compiler. There
+# is a bug in at least version distributed with Python 2.6 where it
+# adds '/pdb:None' to the linker command-line, but that just results
+# in a 'None' file being created instead of putting the debug info
+# into the .pyd files as expected. So we'll strip out that option via
+# a monkey-patch of the msvc9compiler.MSVCCompiler.initialize method.
+
+if os.name == 'nt' and COMPILER == 'msvc' and sys.version_info >= (2,6):
+ import distutils.msvc9compiler
+ _orig_initialize = distutils.msvc9compiler.MSVCCompiler.initialize
+
+ def _initialize(self, *args, **kw):
+ rv = _orig_initialize(self, *args, **kw)
+ try:
+ self.ldflags_shared_debug.remove('/pdb:None')
+ except ValueError:
+ pass
+ return rv
+
+ distutils.msvc9compiler.MSVCCompiler.initialize = _initialize
+
+
+#----------------------------------------------------------------------
+# sanity checks
+
+if CORE_ONLY:
+ BUILD_GLCANVAS = 0
+ BUILD_STC = 0
+ BUILD_GIZMOS = 0
+ BUILD_DLLWIDGET = 0
+ BUILD_ACTIVEX = 0
+
+
+if UNICODE and WXPORT not in ['msw', 'gtk2', 'gtk3', 'osx_carbon', 'osx_cocoa']:
+ raise SystemExit, "UNICODE mode not currently supported on this WXPORT: "+WXPORT
+
+
+if CONTRIBS_INC:
+ CONTRIBS_INC = [ CONTRIBS_INC ]
+else:
+ CONTRIBS_INC = []
+
+if WXPORT != 'msw':
+ # make sure we only use the compiler value on MSW builds
+ COMPILER=None
+
+WXPLAT2 = None
+
+#----------------------------------------------------------------------
+# Setup some platform specific stuff
+#----------------------------------------------------------------------
+
+if os.name == 'nt' and COMPILER == 'msvc':
+ # Set compile flags and such for MSVC. These values are derived
+ # from the wxWidgets makefiles for MSVC, other compilers settings
+ # will probably vary...
+ if os.environ.has_key('WXWIN'):
+ WXDIR = os.environ['WXWIN']
+ else:
+ if os.path.exists('..\\wxWidgets'):
+ WXDIR = '..\\wxWidgets' # assumes in parallel SVN tree
+ else:
+ WXDIR = '..' # assumes wxPython is subdir
+ msg("WARNING: WXWIN not set in environment. Assuming '%s'" % WXDIR)
+ WXPLAT = '__WXMSW__'
+ GENDIR = 'msw'
+
+ if os.environ.get('CPU', None) in ['AMD64', 'X64']:
+ VCDLL = 'vc%s_x64_dll' % getVisCVersion()
+ else:
+ VCDLL = 'vc%s_dll' % getVisCVersion()
+
+ includes = ['include', 'src',
+ opj(WXDIR, 'lib', VCDLL, 'msw' + libFlag()),
+ opj(WXDIR, 'include'),
+ opj(WXDIR, 'contrib', 'include'),
+ ]
+
+ defines = [ ('WIN32', None),
+ ('_WINDOWS', None),
+
+ (WXPLAT, None),
+ ('WXUSINGDLL', '1'),
+
+ ('SWIG_TYPE_TABLE', WXPYTHON_TYPE_TABLE),
+ ('SWIG_PYTHON_OUTPUT_TUPLE', None),
+ ('SWIG_PYTHON_SILENT_MEMLEAK', None),
+ ('WXP_USE_THREAD', '1'),
+ ('ISOLATION_AWARE_ENABLED', None),
+ ]
+
+ if UNDEF_NDEBUG:
+ defines.append( ('NDEBUG',) ) # using a 1-tuple makes it do an undef
+
+ if UNICODE:
+ defines.append( ('wxUSE_UNICODE', 1) )
+
+ libs = []
+ libdirs = [ opj(WXDIR, 'lib', VCDLL) ]
+ if MONOLITHIC:
+ libs += makeLibName('')
+ else:
+ libs += [ 'wxbase' + WXDLLVER + libFlag(),
+ 'wxbase' + WXDLLVER + libFlag() + '_net',
+ 'wxbase' + WXDLLVER + libFlag() + '_xml',
+ makeLibName('core')[0],
+ makeLibName('adv')[0],
+ makeLibName('html')[0],
+ ]
+
+ libs += ['kernel32', 'user32', 'gdi32', 'comdlg32',
+ 'winspool', 'winmm', 'shell32', 'oldnames', 'comctl32',
+ 'odbc32', 'ole32', 'oleaut32', 'uuid', 'rpcrt4',
+ 'advapi32', 'wsock32']
+
+ cflags = [ '/Gy',
+ '/EHsc',
+ # '/GX-' # workaround for internal compiler error in MSVC on some machines
+ ]
+ lflags = None
+
+ # Other MSVC flags...
+ # Uncomment these to have debug info for all kinds of builds
+ #cflags += ['/Od', '/Z7']
+ #lflags = ['/DEBUG', ]
+
+
+#----------------------------------------------------------------------
+
+elif os.name == 'posix' or COMPILER == 'mingw32':
+ if os.environ.has_key('WXWIN'):
+ WXDIR = os.environ['WXWIN']
+ else:
+ if os.path.exists('../wxWidgets'):
+ WXDIR = '../wxWidgets' # assumes in parallel SVN tree
+ else:
+ WXDIR = '..' # assumes wxPython is subdir
+ msg("WARNING: WXWIN not set in environment. Assuming '%s'" % WXDIR)
+ includes = ['include', 'src']
+ defines = [('SWIG_TYPE_TABLE', WXPYTHON_TYPE_TABLE),
+ ('SWIG_PYTHON_OUTPUT_TUPLE', None),
+ ('SWIG_PYTHON_SILENT_MEMLEAK', None),
+ ('WXP_USE_THREAD', '1'),
+ ]
+ if UNDEF_NDEBUG:
+ defines.append( ('NDEBUG',) ) # using a 1-tuple makes it do an undef
+
+ Verify_WX_CONFIG()
+
+ libdirs = []
+ libs = []
+
+ # If you get unresolved symbol errors on Solaris and are using gcc, then
+ # uncomment this block to add the right flags to the link step and build
+ # again.
+ ## if os.uname()[0] == 'SunOS':
+ ## import commands
+ ## libs.append('gcc')
+ ## libdirs.append(commands.getoutput("gcc -print-search-dirs | grep '^install' | awk '{print $2}'")[:-1])
+
+ cflags = getWxConfigValue('--cxxflags')
+ cflags = cflags.split()
+ if debug:
+ cflags.append('-ggdb')
+ cflags.append('-O0')
+ else:
+ cflags.append('-O3')
+
+ lflags = getWxConfigValue('--libs')
+ MONOLITHIC = (lflags.find("_xrc") == -1)
+ lflags = lflags.split()
+
+ WXBASENAME = getWxConfigValue('--basename')
+ WXRELEASE = getWxConfigValue('--release')
+ WXPREFIX = getWxConfigValue('--prefix')
+
+
+ if sys.platform[:6] == "darwin":
+ WXPLAT = '__WXMAC__'
+
+ if WXPORT == 'osx_carbon':
+ # Flags and such for a Darwin (Max OS X) build of Python
+ GENDIR = 'osx_carbon'
+ WXPLAT2 = '__WXOSX_CARBON__'
+ else:
+ GENDIR = 'osx_cocoa'
+ WXPLAT2 = '__WXOSX_COCOA__'
+
+ libs = ['stdc++']
+ NO_SCRIPTS = 1
+ if ARCH != "":
+ splitArch = "-arch " + re.sub(","," -arch ",ARCH)
+ cflags.extend(splitArch.split(' '))
+ lflags.extend(splitArch.split(' '))
+
+ if not os.environ.get('CC') or not os.environ.get('CXX'):
+ os.environ["CXX"] = getWxConfigValue('--cxx')
+ os.environ["CC"] = getWxConfigValue('--cc')
+
+ # We want to use the linker command from wx to make sure
+ # we get the right sysroot, but we also need to ensure that
+ # the other linker flags that distutils wants to use are
+ # included as well.
+ LDSHARED = distutils.sysconfig.get_config_var('LDSHARED').split()
+ # remove the compiler command
+ del LDSHARED[0]
+ # remove any -sysroot flags and their arg
+ while 1:
+ try:
+ index = LDSHARED.index('-isysroot')
+ # Strip this argument and the next one:
+ del LDSHARED[index:index+2]
+ except ValueError:
+ break
+ LDSHARED = ' '.join(LDSHARED)
+ # Combine with wx's ld command and stash it in the env
+ # where distutils will get it later.
+ LDSHARED = getWxConfigValue('--ld').replace(' -o', '') + ' ' + LDSHARED
+ os.environ["LDSHARED"] = LDSHARED
+
+ else:
+ # Set flags for other Unix type platforms
+ GENDIR = WXPORT
+
+ if WXPORT == 'gtk':
+ WXPLAT = '__WXGTK__'
+ portcfg = os.popen('gtk-config --cflags', 'r').read()[:-1]
+ BUILD_BASE = BUILD_BASE + '-' + WXPORT
+ elif WXPORT == 'gtk2':
+ WXPLAT = '__WXGTK__'
+ GENDIR = 'gtk' # no code differences so use the same generated sources
+ portcfg = os.popen('pkg-config gtk+-2.0 --cflags', 'r').read()[:-1]
+ elif WXPORT == 'gtk3':
+ WXPLAT = '__WXGTK__'
+ GENDIR = 'gtk' # no code differences so use the same generated sources
+ portcfg = os.popen('pkg-config gtk+-3.0 --cflags', 'r').read()[:-1]
+ elif WXPORT == 'x11':
+ WXPLAT = '__WXX11__'
+ portcfg = ''
+ BUILD_BASE = BUILD_BASE + '-' + WXPORT
+ elif WXPORT == 'msw':
+ WXPLAT = '__WXMSW__'
+ GENDIR = 'msw'
+ portcfg = ''
+ else:
+ raise SystemExit, "Unknown WXPORT value: " + WXPORT
+
+ cflags += portcfg.split()
+
+ # Some distros (e.g. Mandrake) put libGLU in /usr/X11R6/lib, but
+ # wx-config doesn't output that for some reason. For now, just
+ # add it unconditionally but we should really check if the lib is
+ # really found there or wx-config should be fixed.
+ if WXPORT != 'msw':
+ libdirs.append("/usr/X11R6/lib")
+
+
+ # Move the various -I, -D, etc. flags we got from the *config scripts
+ # into the distutils lists.
+ cflags = adjustCFLAGS(cflags, defines, includes)
+ lflags = adjustLFLAGS(lflags, libdirs, libs)
+
+ if debug and WXPORT == 'msw' and COMPILER != 'mingw32':
+ defines.append( ('_DEBUG', None) )
+
+## from pprint import pprint
+## print 'cflags:',; pprint(cflags)
+## print 'defines:',; pprint(defines)
+## print 'includes:',; pprint(includes)
+## print
+## print 'lflags:',; pprint(lflags)
+## print 'libdirs:',; pprint(libdirs)
+## print 'libs:',; pprint(libs)
+## print
+## sys.exit()
+
+#----------------------------------------------------------------------
+else:
+ raise Exception('Sorry, platform not supported...')
+
+
+#----------------------------------------------------------------------
+# build options file
+#----------------------------------------------------------------------
+
+if SYS_WX_CONFIG is None:
+ SYS_WX_CONFIG = WX_CONFIG
+
+build_options_template = """
+UNICODE=%d
+UNDEF_NDEBUG=%d
+INSTALL_MULTIVERSION=%d
+FLAVOUR="%s"
+EP_ADD_OPTS=%d
+EP_FULL_VER=%d
+WX_CONFIG="%s"
+WXPORT="%s"
+MONOLITHIC=%d
+""" % (UNICODE, UNDEF_NDEBUG, INSTALL_MULTIVERSION, FLAVOUR, EP_ADD_OPTS,
+ EP_FULL_VER, SYS_WX_CONFIG, WXPORT, MONOLITHIC)
+
+try:
+ from build_options import *
+except:
+ build_options_file = os.path.join(os.path.dirname(__file__), "build_options.py")
+ if not os.path.exists(build_options_file):
+ try:
+ myfile = open(build_options_file, "w")
+ myfile.write(build_options_template)
+ myfile.close()
+ except:
+ print "WARNING: Unable to create build_options.py."
+
+
+#----------------------------------------------------------------------
+# post platform setup checks and tweaks, create the full version string
+#----------------------------------------------------------------------
+
+if os.path.exists('DAILY_BUILD'):
+ VER_FLAGS += '.b' + open('DAILY_BUILD').read().strip()
+
+VERSION = "%s.%s.%s.%s%s" % (VER_MAJOR, VER_MINOR, VER_RELEASE,
+ VER_SUBREL, VER_FLAGS)
+
+
+#----------------------------------------------------------------------
+# SWIG defaults
+#----------------------------------------------------------------------
+
+# *.i files could live in the wxWidgets/wxPython/src dir, or in
+# a subdirectory of the devel package. Let's specify both
+# dirs as includes so we don't have to guess which is correct.
+
+wxfilesdir = ""
+i_subdir = opj("include", getExtraPath(addRelease=False), "wx", "wxPython", "i_files")
+if os.name != "nt":
+ wxfilesdir = opj(WXPREFIX, i_subdir)
+else:
+ wxfilesdir = opj(WXPY_SRC, i_subdir)
+
+i_files_includes = [ '-I' + opj(WXPY_SRC, 'src'),
+ '-I' + wxfilesdir ]
+
+swig_cmd = SWIG
+swig_force = force
+swig_args = ['-c++',
+ #'-Wall',
+ '-python',
+ '-new_repr',
+ '-modern',
+ '-D'+WXPLAT,
+ ]
+if WXPLAT2:
+ swig_args.append('-D' + WXPLAT2)
+
+swig_args += i_files_includes
+
+if USE_SWIG:
+ SVER = swig_version()
+ if int(SVER[-2:]) >= 29:
+ swig_args += [ '-fastdispatch',
+ '-fvirtual',
+ '-fastinit',
+ '-fastunpack',
+ #'-outputtuple', Currently setting this with a -D define above
+ ]
+
+if UNICODE:
+ swig_args.append('-DwxUSE_UNICODE')
+
+if FULL_DOCS:
+ swig_args.append('-D_DO_FULL_DOCS')
+
+
+swig_deps = [ opj(WXPY_SRC, 'src/my_typemaps.i'),
+ opj(WXPY_SRC, 'src/pyfragments.swg'),
+ ]
+
+depends = [ #'include/wx/wxPython/wxPython.h',
+ #'include/wx/wxPython/wxPython_int.h',
+ #'src/pyclasses.h',
+ ]
+
+#----------------------------------------------------------------------
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/calendar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/calendar.py
new file mode 100644
index 0000000..a46abc5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/calendar.py
@@ -0,0 +1,683 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+Classes for an interactive Calendar control.
+"""
+
+import _calendar
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _misc
+import _core
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+CAL_SUNDAY_FIRST = _calendar.CAL_SUNDAY_FIRST
+CAL_MONDAY_FIRST = _calendar.CAL_MONDAY_FIRST
+CAL_SHOW_HOLIDAYS = _calendar.CAL_SHOW_HOLIDAYS
+CAL_NO_YEAR_CHANGE = _calendar.CAL_NO_YEAR_CHANGE
+CAL_NO_MONTH_CHANGE = _calendar.CAL_NO_MONTH_CHANGE
+CAL_SEQUENTIAL_MONTH_SELECTION = _calendar.CAL_SEQUENTIAL_MONTH_SELECTION
+CAL_SHOW_SURROUNDING_WEEKS = _calendar.CAL_SHOW_SURROUNDING_WEEKS
+CAL_SHOW_WEEK_NUMBERS = _calendar.CAL_SHOW_WEEK_NUMBERS
+CAL_HITTEST_NOWHERE = _calendar.CAL_HITTEST_NOWHERE
+CAL_HITTEST_HEADER = _calendar.CAL_HITTEST_HEADER
+CAL_HITTEST_DAY = _calendar.CAL_HITTEST_DAY
+CAL_HITTEST_INCMONTH = _calendar.CAL_HITTEST_INCMONTH
+CAL_HITTEST_DECMONTH = _calendar.CAL_HITTEST_DECMONTH
+CAL_HITTEST_SURROUNDING_WEEK = _calendar.CAL_HITTEST_SURROUNDING_WEEK
+CAL_HITTEST_WEEK = _calendar.CAL_HITTEST_WEEK
+CAL_BORDER_NONE = _calendar.CAL_BORDER_NONE
+CAL_BORDER_SQUARE = _calendar.CAL_BORDER_SQUARE
+CAL_BORDER_ROUND = _calendar.CAL_BORDER_ROUND
+class CalendarDateAttr(object):
+ """
+ A set of customization attributes for a calendar date, which can be
+ used to control the look of the Calendar object.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Colour colText=wxNullColour, Colour colBack=wxNullColour,
+ Colour colBorder=wxNullColour, Font font=wxNullFont,
+ int border=CAL_BORDER_NONE) -> CalendarDateAttr
+
+ Create a CalendarDateAttr.
+ """
+ _calendar.CalendarDateAttr_swiginit(self,_calendar.new_CalendarDateAttr(*args, **kwargs))
+ __swig_destroy__ = _calendar.delete_CalendarDateAttr
+ __del__ = lambda self : None;
+ def SetTextColour(*args, **kwargs):
+ """SetTextColour(self, Colour colText)"""
+ return _calendar.CalendarDateAttr_SetTextColour(*args, **kwargs)
+
+ def SetBackgroundColour(*args, **kwargs):
+ """SetBackgroundColour(self, Colour colBack)"""
+ return _calendar.CalendarDateAttr_SetBackgroundColour(*args, **kwargs)
+
+ def SetBorderColour(*args, **kwargs):
+ """SetBorderColour(self, Colour col)"""
+ return _calendar.CalendarDateAttr_SetBorderColour(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """SetFont(self, Font font)"""
+ return _calendar.CalendarDateAttr_SetFont(*args, **kwargs)
+
+ def SetBorder(*args, **kwargs):
+ """SetBorder(self, int border)"""
+ return _calendar.CalendarDateAttr_SetBorder(*args, **kwargs)
+
+ def SetHoliday(*args, **kwargs):
+ """SetHoliday(self, bool holiday)"""
+ return _calendar.CalendarDateAttr_SetHoliday(*args, **kwargs)
+
+ def HasTextColour(*args, **kwargs):
+ """HasTextColour(self) -> bool"""
+ return _calendar.CalendarDateAttr_HasTextColour(*args, **kwargs)
+
+ def HasBackgroundColour(*args, **kwargs):
+ """HasBackgroundColour(self) -> bool"""
+ return _calendar.CalendarDateAttr_HasBackgroundColour(*args, **kwargs)
+
+ def HasBorderColour(*args, **kwargs):
+ """HasBorderColour(self) -> bool"""
+ return _calendar.CalendarDateAttr_HasBorderColour(*args, **kwargs)
+
+ def HasFont(*args, **kwargs):
+ """HasFont(self) -> bool"""
+ return _calendar.CalendarDateAttr_HasFont(*args, **kwargs)
+
+ def HasBorder(*args, **kwargs):
+ """HasBorder(self) -> bool"""
+ return _calendar.CalendarDateAttr_HasBorder(*args, **kwargs)
+
+ def IsHoliday(*args, **kwargs):
+ """IsHoliday(self) -> bool"""
+ return _calendar.CalendarDateAttr_IsHoliday(*args, **kwargs)
+
+ def GetTextColour(*args, **kwargs):
+ """GetTextColour(self) -> Colour"""
+ return _calendar.CalendarDateAttr_GetTextColour(*args, **kwargs)
+
+ def GetBackgroundColour(*args, **kwargs):
+ """GetBackgroundColour(self) -> Colour"""
+ return _calendar.CalendarDateAttr_GetBackgroundColour(*args, **kwargs)
+
+ def GetBorderColour(*args, **kwargs):
+ """GetBorderColour(self) -> Colour"""
+ return _calendar.CalendarDateAttr_GetBorderColour(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """GetFont(self) -> Font"""
+ return _calendar.CalendarDateAttr_GetFont(*args, **kwargs)
+
+ def GetBorder(*args, **kwargs):
+ """GetBorder(self) -> int"""
+ return _calendar.CalendarDateAttr_GetBorder(*args, **kwargs)
+
+ def GetMark(*args, **kwargs):
+ """GetMark() -> CalendarDateAttr"""
+ return _calendar.CalendarDateAttr_GetMark(*args, **kwargs)
+
+ GetMark = staticmethod(GetMark)
+ def SetMark(*args, **kwargs):
+ """SetMark(CalendarDateAttr m)"""
+ return _calendar.CalendarDateAttr_SetMark(*args, **kwargs)
+
+ SetMark = staticmethod(SetMark)
+ BackgroundColour = property(GetBackgroundColour,SetBackgroundColour,doc="See `GetBackgroundColour` and `SetBackgroundColour`")
+ Border = property(GetBorder,SetBorder,doc="See `GetBorder` and `SetBorder`")
+ BorderColour = property(GetBorderColour,SetBorderColour,doc="See `GetBorderColour` and `SetBorderColour`")
+ Font = property(GetFont,SetFont,doc="See `GetFont` and `SetFont`")
+ TextColour = property(GetTextColour,SetTextColour,doc="See `GetTextColour` and `SetTextColour`")
+_calendar.CalendarDateAttr_swigregister(CalendarDateAttr)
+
+def CalendarDateAttr_GetMark(*args):
+ """CalendarDateAttr_GetMark() -> CalendarDateAttr"""
+ return _calendar.CalendarDateAttr_GetMark(*args)
+
+def CalendarDateAttr_SetMark(*args, **kwargs):
+ """CalendarDateAttr_SetMark(CalendarDateAttr m)"""
+ return _calendar.CalendarDateAttr_SetMark(*args, **kwargs)
+
+class CalendarEvent(_core.DateEvent):
+ """Proxy of C++ CalendarEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window win, DateTime dt, EventType type) -> CalendarEvent"""
+ _calendar.CalendarEvent_swiginit(self,_calendar.new_CalendarEvent(*args, **kwargs))
+ def SetWeekDay(*args, **kwargs):
+ """SetWeekDay(self, int wd)"""
+ return _calendar.CalendarEvent_SetWeekDay(*args, **kwargs)
+
+ def GetWeekDay(*args, **kwargs):
+ """GetWeekDay(self) -> int"""
+ return _calendar.CalendarEvent_GetWeekDay(*args, **kwargs)
+
+ def PySetDate(self, date):
+ """takes datetime.datetime or datetime.date object"""
+ self.SetDate(_pydate2wxdate(date))
+
+ def PyGetDate(self):
+ """returns datetime.date object"""
+ return _wxdate2pydate(self.GetDate())
+
+ WeekDay = property(GetWeekDay,SetWeekDay,doc="See `GetWeekDay` and `SetWeekDay`")
+_calendar.CalendarEvent_swigregister(CalendarEvent)
+
+wxEVT_CALENDAR_DOUBLECLICKED = _calendar.wxEVT_CALENDAR_DOUBLECLICKED
+wxEVT_CALENDAR_SEL_CHANGED = _calendar.wxEVT_CALENDAR_SEL_CHANGED
+wxEVT_CALENDAR_WEEKDAY_CLICKED = _calendar.wxEVT_CALENDAR_WEEKDAY_CLICKED
+wxEVT_CALENDAR_PAGE_CHANGED = _calendar.wxEVT_CALENDAR_PAGE_CHANGED
+wxEVT_CALENDAR_DAY_CHANGED = _calendar.wxEVT_CALENDAR_DAY_CHANGED
+wxEVT_CALENDAR_MONTH_CHANGED = _calendar.wxEVT_CALENDAR_MONTH_CHANGED
+wxEVT_CALENDAR_YEAR_CHANGED = _calendar.wxEVT_CALENDAR_YEAR_CHANGED
+EVT_CALENDAR = wx.PyEventBinder( wxEVT_CALENDAR_DOUBLECLICKED, 1)
+EVT_CALENDAR_SEL_CHANGED = wx.PyEventBinder( wxEVT_CALENDAR_SEL_CHANGED, 1)
+EVT_CALENDAR_WEEKDAY_CLICKED = wx.PyEventBinder( wxEVT_CALENDAR_WEEKDAY_CLICKED, 1)
+EVT_CALENDAR_PAGE_CHANGED = wx.PyEventBinder( wxEVT_CALENDAR_PAGE_CHANGED, 1)
+
+EVT_CALENDAR_DAY = wx.PyEventBinder( wxEVT_CALENDAR_DAY_CHANGED, 1)
+EVT_CALENDAR_MONTH = wx.PyEventBinder( wxEVT_CALENDAR_MONTH_CHANGED, 1)
+EVT_CALENDAR_YEAR = wx.PyEventBinder( wxEVT_CALENDAR_YEAR_CHANGED, 1)
+
+class CalendarCtrlBase(_core.Control):
+ """
+ Common base class for `CalendarCtrl` and `GenericCalendarCtrl`.
+
+ The calendar control allows the user to pick a date interactively.
+
+ The CalendarCtrl displays a window containing several parts: the
+ control to pick the month and the year at the top (either or both of
+ them may be disabled) and a month area below them which shows all the
+ days in the month. The user can move the current selection using the
+ keyboard and select the date (generating EVT_CALENDAR event) by
+ pressing <Return> or double clicking it.
+
+ It has advanced possibilities for the customization of its
+ display. All global settings (such as colours and fonts used) can, of
+ course, be changed. But also, the display style for each day in the
+ month can be set independently using CalendarDateAttr class.
+
+ An item without custom attributes is drawn with the default colours
+ and font and without border, but setting custom attributes with
+ `SetAttr` allows to modify its appearance. Just create a custom
+ attribute object and set it for the day you want to be displayed
+ specially A day may be marked as being a holiday, (even if it is not
+ recognized as one by `wx.DateTime`) by using the SetHoliday method.
+
+ As the attributes are specified for each day, they may change when the
+ month is changed, so you will often want to update them in an
+ EVT_CALENDAR_MONTH event handler.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def AllowMonthChange(*args, **kwargs):
+ """AllowMonthChange(self) -> bool"""
+ return _calendar.CalendarCtrlBase_AllowMonthChange(*args, **kwargs)
+
+ def SetDate(*args, **kwargs):
+ """
+ SetDate(self, DateTime date) -> bool
+
+ Sets the current date.
+ """
+ return _calendar.CalendarCtrlBase_SetDate(*args, **kwargs)
+
+ def GetDate(*args, **kwargs):
+ """
+ GetDate(self) -> DateTime
+
+ Gets the currently selected date.
+ """
+ return _calendar.CalendarCtrlBase_GetDate(*args, **kwargs)
+
+ def SetDateRange(*args, **kwargs):
+ """
+ SetDateRange(self, DateTime lowerdate=DefaultDateTime, DateTime upperdate=DefaultDateTime) -> bool
+
+ set the range in which selection can occur
+ """
+ return _calendar.CalendarCtrlBase_SetDateRange(*args, **kwargs)
+
+ def GetDateRange(*args, **kwargs):
+ """GetDateRange(self) -> PyObject"""
+ return _calendar.CalendarCtrlBase_GetDateRange(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(Point pos) -> (result, date, weekday)
+
+ Returns 3-tuple with information about the given position on the
+ calendar control. The first value of the tuple is a result code and
+ determines the validity of the remaining two values.
+ """
+ return _calendar.CalendarCtrlBase_HitTest(*args, **kwargs)
+
+ def EnableMonthChange(*args, **kwargs):
+ """
+ EnableMonthChange(self, bool enable=True)
+
+ This function should be used instead of changing CAL_NO_MONTH_CHANGE
+ style bit. It allows or disallows the user to change the month
+ interactively. Note that if the month can not be changed, the year can
+ not be changed either.
+ """
+ return _calendar.CalendarCtrlBase_EnableMonthChange(*args, **kwargs)
+
+ def Mark(*args, **kwargs):
+ """Mark(self, size_t day, bool mark)"""
+ return _calendar.CalendarCtrlBase_Mark(*args, **kwargs)
+
+ def GetAttr(*args, **kwargs):
+ """
+ GetAttr(self, size_t day) -> CalendarDateAttr
+
+ Returns the attribute for the given date (should be in the range
+ 1...31). The returned value may be None
+ """
+ return _calendar.CalendarCtrlBase_GetAttr(*args, **kwargs)
+
+ def SetAttr(*args, **kwargs):
+ """
+ SetAttr(self, size_t day, CalendarDateAttr attr)
+
+ Associates the attribute with the specified date (in the range
+ 1...31). If the attribute passed is None, the items attribute is
+ cleared.
+ """
+ return _calendar.CalendarCtrlBase_SetAttr(*args, **kwargs)
+
+ def ResetAttr(*args, **kwargs):
+ """
+ ResetAttr(self, size_t day)
+
+ Clears any attributes associated with the given day (in the range
+ 1...31).
+ """
+ return _calendar.CalendarCtrlBase_ResetAttr(*args, **kwargs)
+
+ def EnableHolidayDisplay(*args, **kwargs):
+ """
+ EnableHolidayDisplay(self, bool display=True)
+
+ This function should be used instead of changing CAL_SHOW_HOLIDAYS
+ style bit directly. It enables or disables the special highlighting of
+ the holidays.
+ """
+ return _calendar.CalendarCtrlBase_EnableHolidayDisplay(*args, **kwargs)
+
+ def SetHolidayColours(*args, **kwargs):
+ """
+ SetHolidayColours(self, Colour colFg, Colour colBg)
+
+ Holiday colour is used for the holidays (if CAL_SHOW_HOLIDAYS style is
+ used).
+ """
+ return _calendar.CalendarCtrlBase_SetHolidayColours(*args, **kwargs)
+
+ def GetHolidayColourFg(*args, **kwargs):
+ """
+ GetHolidayColourFg(self) -> Colour
+
+ Holiday colour is used for the holidays (if CAL_SHOW_HOLIDAYS style is
+ used).
+ """
+ return _calendar.CalendarCtrlBase_GetHolidayColourFg(*args, **kwargs)
+
+ def GetHolidayColourBg(*args, **kwargs):
+ """
+ GetHolidayColourBg(self) -> Colour
+
+ Holiday colour is used for the holidays (if CAL_SHOW_HOLIDAYS style is
+ used).
+ """
+ return _calendar.CalendarCtrlBase_GetHolidayColourBg(*args, **kwargs)
+
+ def SetHoliday(*args, **kwargs):
+ """
+ SetHoliday(self, size_t day)
+
+ Marks the specified day as being a holiday in the current month.
+ """
+ return _calendar.CalendarCtrlBase_SetHoliday(*args, **kwargs)
+
+ def SetHeaderColours(*args, **kwargs):
+ """
+ SetHeaderColours(self, Colour colFg, Colour colBg)
+
+ Header colours are used for painting the weekdays at the top.
+ """
+ return _calendar.CalendarCtrlBase_SetHeaderColours(*args, **kwargs)
+
+ def GetHeaderColourFg(*args, **kwargs):
+ """
+ GetHeaderColourFg(self) -> Colour
+
+ Header colours are used for painting the weekdays at the top.
+ """
+ return _calendar.CalendarCtrlBase_GetHeaderColourFg(*args, **kwargs)
+
+ def GetHeaderColourBg(*args, **kwargs):
+ """
+ GetHeaderColourBg(self) -> Colour
+
+ Header colours are used for painting the weekdays at the top.
+ """
+ return _calendar.CalendarCtrlBase_GetHeaderColourBg(*args, **kwargs)
+
+ def SetHighlightColours(*args, **kwargs):
+ """
+ SetHighlightColours(self, Colour colFg, Colour colBg)
+
+ Highlight colour is used for the currently selected date.
+ """
+ return _calendar.CalendarCtrlBase_SetHighlightColours(*args, **kwargs)
+
+ def GetHighlightColourFg(*args, **kwargs):
+ """
+ GetHighlightColourFg(self) -> Colour
+
+ Highlight colour is used for the currently selected date.
+ """
+ return _calendar.CalendarCtrlBase_GetHighlightColourFg(*args, **kwargs)
+
+ def GetHighlightColourBg(*args, **kwargs):
+ """
+ GetHighlightColourBg(self) -> Colour
+
+ Highlight colour is used for the currently selected date.
+ """
+ return _calendar.CalendarCtrlBase_GetHighlightColourBg(*args, **kwargs)
+
+ def PySetDate(self, date):
+ """takes datetime.datetime or datetime.date object"""
+ self.SetDate(_pydate2wxdate(date))
+
+ def PyGetDate(self):
+ """returns datetime.date object"""
+ return _wxdate2pydate(self.GetDate())
+
+ def PySetLowerDateLimit(self, date):
+ """takes datetime.datetime or datetime.date object"""
+ self.SetLowerDateLimit(_pydate2wxdate(date))
+
+ def PySetUpperDateLimit(self, date):
+ """takes datetime.datetime or datetime.date object"""
+ self.SetUpperDateLimit(_pydate2wxdate(date))
+
+ def PySetDateRange(self, lowerdate, upperdate):
+ """takes datetime.datetime or datetime.date objects"""
+ self.PySetLowerDateLimit(lowerdate)
+ self.PySetUpperDateLimit(upperdate)
+
+ def PyGetLowerDateLimit(self):
+ """returns datetime.date object"""
+ return _wxdate2pydate(self.GetLowerDateLimit())
+
+ def PyGetUpperDateLimit(self):
+ """returns datetime.date object"""
+ return _wxdate2pydate(self.GetUpperDateLimit())
+
+ Date = property(GetDate,SetDate,doc="See `GetDate` and `SetDate`")
+ HeaderColourBg = property(GetHeaderColourBg,doc="See `GetHeaderColourBg`")
+ HeaderColourFg = property(GetHeaderColourFg,doc="See `GetHeaderColourFg`")
+ HighlightColourBg = property(GetHighlightColourBg,doc="See `GetHighlightColourBg`")
+ HighlightColourFg = property(GetHighlightColourFg,doc="See `GetHighlightColourFg`")
+ HolidayColourBg = property(GetHolidayColourBg,doc="See `GetHolidayColourBg`")
+ HolidayColourFg = property(GetHolidayColourFg,doc="See `GetHolidayColourFg`")
+_calendar.CalendarCtrlBase_swigregister(CalendarCtrlBase)
+cvar = _calendar.cvar
+CalendarNameStr = cvar.CalendarNameStr
+
+class GenericCalendarCtrl(CalendarCtrlBase):
+ """
+ A generic implementation of the Calendar Control which, depending on
+ platform, may offer more functionality and configurability then the
+ native `CalendarCtrl` at the cost of losing the native look and feel.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, DateTime date=DefaultDateTime,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxCAL_SHOW_HOLIDAYS|wxWANTS_CHARS,
+ String name=CalendarNameStr) -> GenericCalendarCtrl
+
+ Create and show a calendar control.
+ """
+ _calendar.GenericCalendarCtrl_swiginit(self,_calendar.new_GenericCalendarCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id, DateTime date=DefaultDateTime,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxCAL_SHOW_HOLIDAYS|wxWANTS_CHARS,
+ String name=CalendarNameStr) -> bool
+
+ Acutally create the GUI portion of the CalendarCtrl for 2-phase
+ creation.
+ """
+ return _calendar.GenericCalendarCtrl_Create(*args, **kwargs)
+
+ def SetLowerDateLimit(*args, **kwargs):
+ """
+ SetLowerDateLimit(self, DateTime date=DefaultDateTime) -> bool
+
+ set the range in which selection can occur
+ """
+ return _calendar.GenericCalendarCtrl_SetLowerDateLimit(*args, **kwargs)
+
+ def SetUpperDateLimit(*args, **kwargs):
+ """
+ SetUpperDateLimit(self, DateTime date=DefaultDateTime) -> bool
+
+ set the range in which selection can occur
+ """
+ return _calendar.GenericCalendarCtrl_SetUpperDateLimit(*args, **kwargs)
+
+ def GetLowerDateLimit(*args, **kwargs):
+ """
+ GetLowerDateLimit(self) -> DateTime
+
+ get the range in which selection can occur
+ """
+ return _calendar.GenericCalendarCtrl_GetLowerDateLimit(*args, **kwargs)
+
+ def GetUpperDateLimit(*args, **kwargs):
+ """
+ GetUpperDateLimit(self) -> DateTime
+
+ get the range in which selection can occur
+ """
+ return _calendar.GenericCalendarCtrl_GetUpperDateLimit(*args, **kwargs)
+
+ def EnableYearChange(*args, **kwargs):
+ """
+ EnableYearChange(self, bool enable=True)
+
+ This function should be used instead of changing CAL_NO_YEAR_CHANGE
+ style bit directly. It allows or disallows the user to change the year
+ interactively.
+ """
+ return _calendar.GenericCalendarCtrl_EnableYearChange(*args, **kwargs)
+
+ def GetMonthControl(*args, **kwargs):
+ """
+ GetMonthControl(self) -> Control
+
+ Get the currently shown control for month.
+ """
+ return _calendar.GenericCalendarCtrl_GetMonthControl(*args, **kwargs)
+
+ def GetYearControl(*args, **kwargs):
+ """
+ GetYearControl(self) -> Control
+
+ Get the currently shown control for year.
+ """
+ return _calendar.GenericCalendarCtrl_GetYearControl(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _calendar.GenericCalendarCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ LowerDateLimit = property(GetLowerDateLimit,SetLowerDateLimit,doc="See `GetLowerDateLimit` and `SetLowerDateLimit`")
+ MonthControl = property(GetMonthControl,doc="See `GetMonthControl`")
+ UpperDateLimit = property(GetUpperDateLimit,SetUpperDateLimit,doc="See `GetUpperDateLimit` and `SetUpperDateLimit`")
+ YearControl = property(GetYearControl,doc="See `GetYearControl`")
+_calendar.GenericCalendarCtrl_swigregister(GenericCalendarCtrl)
+
+def PreGenericCalendarCtrl(*args, **kwargs):
+ """
+ PreGenericCalendarCtrl() -> GenericCalendarCtrl
+
+ Precreate a GenericCalendarCtrl for 2-phase creation.
+ """
+ val = _calendar.new_PreGenericCalendarCtrl(*args, **kwargs)
+ return val
+
+def GenericCalendarCtrl_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GenericCalendarCtrl_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _calendar.GenericCalendarCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+def _pydate2wxdate(date):
+ import datetime
+ assert isinstance(date, (datetime.datetime, datetime.date))
+ tt = date.timetuple()
+ dmy = (tt[2], tt[1]-1, tt[0])
+ return wx.DateTimeFromDMY(*dmy)
+
+def _wxdate2pydate(date):
+ import datetime
+ assert isinstance(date, wx.DateTime)
+ if date.IsValid():
+ ymd = map(int, date.FormatISODate().split('-'))
+ return datetime.date(*ymd)
+ else:
+ return None
+
+class CalendarCtrl(CalendarCtrlBase):
+ """
+ If the platform has a native calendar widget then this class will
+ provide a way to use it, otherwise the `GenericCalendarCtrl` will
+ be used.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, DateTime date=DefaultDateTime,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxCAL_SHOW_HOLIDAYS|wxWANTS_CHARS,
+ String name=CalendarNameStr) -> CalendarCtrl
+
+ Create and show a calendar control.
+ """
+ _calendar.CalendarCtrl_swiginit(self,_calendar.new_CalendarCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id, DateTime date=DefaultDateTime,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=wxCAL_SHOW_HOLIDAYS|wxWANTS_CHARS,
+ String name=CalendarNameStr) -> bool
+
+ Acutally create the GUI portion of the CalendarCtrl for 2-phase
+ creation.
+ """
+ return _calendar.CalendarCtrl_Create(*args, **kwargs)
+
+_calendar.CalendarCtrl_swigregister(CalendarCtrl)
+
+def PreCalendarCtrl(*args, **kwargs):
+ """
+ PreCalendarCtrl() -> CalendarCtrl
+
+ Precreate a CalendarCtrl for 2-phase creation.
+ """
+ val = _calendar.new_PreCalendarCtrl(*args, **kwargs)
+ return val
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/combo.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/combo.py
new file mode 100644
index 0000000..9298999
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/combo.py
@@ -0,0 +1,1025 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+ComboCtrl class that can have any type of popup widget, and also an
+owner-drawn combobox control.
+"""
+
+import _combo
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _windows
+import _core
+import _controls
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+#---------------------------------------------------------------------------
+
+CC_SPECIAL_DCLICK = _combo.CC_SPECIAL_DCLICK
+CC_STD_BUTTON = _combo.CC_STD_BUTTON
+CC_BUTTON_OUTSIDE_BORDER = _combo.CC_BUTTON_OUTSIDE_BORDER
+CC_POPUP_ON_MOUSE_UP = _combo.CC_POPUP_ON_MOUSE_UP
+CC_NO_TEXT_AUTO_SELECT = _combo.CC_NO_TEXT_AUTO_SELECT
+CC_BUTTON_STAYS_DOWN = _combo.CC_BUTTON_STAYS_DOWN
+CC_FULL_BUTTON = _combo.CC_FULL_BUTTON
+CC_BUTTON_COVERS_BORDER = _combo.CC_BUTTON_COVERS_BORDER
+CC_MF_ON_BUTTON = _combo.CC_MF_ON_BUTTON
+CC_MF_ON_CLICK_AREA = _combo.CC_MF_ON_CLICK_AREA
+class ComboCtrlFeatures(object):
+ """
+ Namespace for `wx.combo.ComboCtrl` feature flags. See
+ `wx.combo.ComboCtrl.GetFeatures`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ MovableButton = _combo.ComboCtrlFeatures_MovableButton
+ BitmapButton = _combo.ComboCtrlFeatures_BitmapButton
+ ButtonSpacing = _combo.ComboCtrlFeatures_ButtonSpacing
+ TextIndent = _combo.ComboCtrlFeatures_TextIndent
+ PaintControl = _combo.ComboCtrlFeatures_PaintControl
+ PaintWritable = _combo.ComboCtrlFeatures_PaintWritable
+ Borderless = _combo.ComboCtrlFeatures_Borderless
+ All = _combo.ComboCtrlFeatures_All
+_combo.ComboCtrlFeatures_swigregister(ComboCtrlFeatures)
+
+class ComboCtrl(_core.Control,_core.TextEntry):
+ """
+ A combo control is a generic combobox that allows for a totally custom
+ popup. In addition it has other customization features. For instance,
+ position and size of the dropdown button can be changed.
+
+ To specify what to use for the popup control you need to derive a
+ class from `wx.combo.ComboPopup` and pass it to the ComboCtrl with
+ `SetPopupControl`. It doesn't derive from any widget class so it can
+ be used either as a mixin class combined with some standard or custom
+ widget, or you can use the derived ComboPopup to create and hold an
+ independent reference to the widget to be used for the popup.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, String value=wxEmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ComboBoxNameStr) -> ComboCtrl
+ """
+ _combo.ComboCtrl_swiginit(self,_combo.new_ComboCtrl(*args, **kwargs))
+ self._setOORInfo(self);ComboCtrl._setCallbackInfo(self, self, ComboCtrl)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _combo.ComboCtrl__setCallbackInfo(*args, **kwargs)
+
+ def Popup(*args, **kwargs):
+ """Popup(self)"""
+ return _combo.ComboCtrl_Popup(*args, **kwargs)
+
+ def Dismiss(*args, **kwargs):
+ """Dismiss(self)"""
+ return _combo.ComboCtrl_Dismiss(*args, **kwargs)
+
+ def ShowPopup(*args, **kwargs):
+ """
+ ShowPopup(self)
+
+ Show the popup window.
+ """
+ return _combo.ComboCtrl_ShowPopup(*args, **kwargs)
+
+ def HidePopup(*args, **kwargs):
+ """
+ HidePopup(self)
+
+ Dismisses the popup window.
+ """
+ return _combo.ComboCtrl_HidePopup(*args, **kwargs)
+
+ def OnButtonClick(*args, **kwargs):
+ """
+ OnButtonClick(self)
+
+ Implement in a derived class to define what happens on dropdown button
+ click. Default action is to show the popup.
+ """
+ return _combo.ComboCtrl_OnButtonClick(*args, **kwargs)
+
+ def IsPopupShown(*args, **kwargs):
+ """
+ IsPopupShown(self) -> bool
+
+ Returns true if the popup is currently shown.
+ """
+ return _combo.ComboCtrl_IsPopupShown(*args, **kwargs)
+
+ def SetPopupControl(*args, **kwargs):
+ """
+ SetPopupControl(self, ComboPopup popup)
+
+ Set popup interface class derived from `wx.combo.ComboPopup`. This
+ method should be called as soon as possible after the control has been
+ created, unless `OnButtonClick` has been overridden.
+ """
+ return _combo.ComboCtrl_SetPopupControl(*args, **kwargs)
+
+ def GetPopupControl(*args, **kwargs):
+ """
+ GetPopupControl(self) -> ComboPopup
+
+ Returns the current popup interface that has been set with
+ `SetPopupControl`.
+ """
+ return _combo.ComboCtrl_GetPopupControl(*args, **kwargs)
+
+ def GetPopupWindow(*args, **kwargs):
+ """
+ GetPopupWindow(self) -> Window
+
+ Returns the popup window containing the popup control.
+ """
+ return _combo.ComboCtrl_GetPopupWindow(*args, **kwargs)
+
+ def GetTextCtrl(*args, **kwargs):
+ """
+ GetTextCtrl(self) -> TextCtrl
+
+ Get the text control which is part of the combo control.
+ """
+ return _combo.ComboCtrl_GetTextCtrl(*args, **kwargs)
+
+ def GetButton(*args, **kwargs):
+ """
+ GetButton(self) -> Window
+
+ Get the dropdown button which is part of the combobox. Note: it's not
+ necessarily a wx.Button or wx.BitmapButton.
+ """
+ return _combo.ComboCtrl_GetButton(*args, **kwargs)
+
+ def SetMargins(*args):
+ """
+ SetMargins(self, Point pt) -> bool
+ SetMargins(self, int left, int top=-1) -> bool
+ """
+ return _combo.ComboCtrl_SetMargins(*args)
+
+ def GetMargins(*args, **kwargs):
+ """GetMargins(self) -> Point"""
+ return _combo.ComboCtrl_GetMargins(*args, **kwargs)
+
+ def SetTextCtrlStyle(*args, **kwargs):
+ """
+ SetTextCtrlStyle(self, int style)
+
+ Set a custom window style for the embedded wxTextCtrl. Usually you
+ will need to use this during two-step creation, just before Create().
+ For example::
+
+ class MyComboCtrl(wx.combo.ComboCtrl):
+ def __init__(self, *args, **kwargs):
+ pre = wx.combo.PreComboCtrl()
+ # Let's make the text right-aligned
+ pre.SetTextCtrlStyle(wx.TE_RIGHT)
+ pre.Create(*args, **kwargs);
+ self.PostCreate(pre)
+
+ """
+ return _combo.ComboCtrl_SetTextCtrlStyle(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """
+ GetValue(self) -> String
+
+ Returns text representation of the current value. For writable combo
+ control it always returns the value in the text field.
+ """
+ return _combo.ComboCtrl_GetValue(*args, **kwargs)
+
+ GetMark = wx.TextEntry.GetSelection
+ SetMark = wx.TextEntry.SetSelection
+
+ def SetText(*args, **kwargs):
+ """
+ SetText(self, String value)
+
+ Sets the text for the text field without affecting the popup. Thus,
+ unlike `SetValue`, it works equally well with combo control using
+ wx.CB_READONLY style.
+ """
+ return _combo.ComboCtrl_SetText(*args, **kwargs)
+
+ def SetValueWithEvent(*args, **kwargs):
+ """
+ SetValueWithEvent(self, String value, bool withEvent=True)
+
+ Same as `SetValue`, but also sends a EVT_TEXT event if withEvent is true.
+ """
+ return _combo.ComboCtrl_SetValueWithEvent(*args, **kwargs)
+
+ def SetValueByUser(*args, **kwargs):
+ """SetValueByUser(self, String value)"""
+ return _combo.ComboCtrl_SetValueByUser(*args, **kwargs)
+
+ def SetPopupMinWidth(*args, **kwargs):
+ """
+ SetPopupMinWidth(self, int width)
+
+ Sets minimum width of the popup. If wider than combo control, it will
+ extend to the left. A value of -1 indicates to use the default. The
+ popup implementation may choose to ignore this.
+ """
+ return _combo.ComboCtrl_SetPopupMinWidth(*args, **kwargs)
+
+ def SetPopupMaxHeight(*args, **kwargs):
+ """
+ SetPopupMaxHeight(self, int height)
+
+ Sets preferred maximum height of the popup. A value of -1 indicates to
+ use the default. The popup implementation may choose to ignore this.
+ """
+ return _combo.ComboCtrl_SetPopupMaxHeight(*args, **kwargs)
+
+ def SetPopupExtents(*args, **kwargs):
+ """
+ SetPopupExtents(self, int extLeft, int extRight)
+
+ Extends popup size horizontally, relative to the edges of the combo
+ control. Values are given in pixels, and the defaults are zero. It
+ is up to the popup to fully take these values into account.
+ """
+ return _combo.ComboCtrl_SetPopupExtents(*args, **kwargs)
+
+ def SetCustomPaintWidth(*args, **kwargs):
+ """
+ SetCustomPaintWidth(self, int width)
+
+ Set width, in pixels, of custom painted area in control without
+ wx.CB_READONLY style. In read-only OwnerDrawnComboBox, this is used
+ to indicate the area that is not covered by the focus rectangle.
+ """
+ return _combo.ComboCtrl_SetCustomPaintWidth(*args, **kwargs)
+
+ def GetCustomPaintWidth(*args, **kwargs):
+ """GetCustomPaintWidth(self) -> int"""
+ return _combo.ComboCtrl_GetCustomPaintWidth(*args, **kwargs)
+
+ def SetPopupAnchor(*args, **kwargs):
+ """
+ SetPopupAnchor(self, int anchorSide)
+
+ Set side of the control to which the popup will align itself. Valid
+ values are wx.LEFT, wx.RIGHT and 0. The default value 0 means that the
+ most appropriate side is used (which, currently, is always wx.LEFT).
+ """
+ return _combo.ComboCtrl_SetPopupAnchor(*args, **kwargs)
+
+ def SetButtonPosition(*args, **kwargs):
+ """
+ SetButtonPosition(self, int width=-1, int height=-1, int side=RIGHT, int spacingX=0)
+
+ Set the position of the dropdown button.
+ """
+ return _combo.ComboCtrl_SetButtonPosition(*args, **kwargs)
+
+ def GetButtonSize(*args, **kwargs):
+ """
+ GetButtonSize(self) -> Size
+
+ Returns current size of the dropdown button.
+ """
+ return _combo.ComboCtrl_GetButtonSize(*args, **kwargs)
+
+ def SetButtonBitmaps(*args, **kwargs):
+ """
+ SetButtonBitmaps(self, Bitmap bmpNormal, bool pushButtonBg=False, Bitmap bmpPressed=wxNullBitmap,
+ Bitmap bmpHover=wxNullBitmap,
+ Bitmap bmpDisabled=wxNullBitmap)
+
+ Sets custom dropdown button graphics.
+
+ :param bmpNormal: Default button image
+ :param pushButtonBg: If ``True``, blank push button background is painted below the image.
+ :param bmpPressed: Depressed button image.
+ :param bmpHover: Button image to use when the mouse hovers over it.
+ :param bmpDisabled: Disabled button image.
+
+ """
+ return _combo.ComboCtrl_SetButtonBitmaps(*args, **kwargs)
+
+ def SetTextIndent(*args, **kwargs):
+ """
+ SetTextIndent(self, int indent)
+
+ This will set the space in pixels between left edge of the control and
+ the text, regardless whether control is read-only or not. A value of -1 can
+ be given to indicate platform default.
+ """
+ return _combo.ComboCtrl_SetTextIndent(*args, **kwargs)
+
+ def GetTextIndent(*args, **kwargs):
+ """
+ GetTextIndent(self) -> int
+
+ Returns actual indentation in pixels.
+ """
+ return _combo.ComboCtrl_GetTextIndent(*args, **kwargs)
+
+ def GetTextRect(*args, **kwargs):
+ """
+ GetTextRect(self) -> Rect
+
+ Returns area covered by the text field (includes everything except
+ borders and the dropdown button).
+ """
+ return _combo.ComboCtrl_GetTextRect(*args, **kwargs)
+
+ def UseAltPopupWindow(*args, **kwargs):
+ """
+ UseAltPopupWindow(self, bool enable=True)
+
+ Enable or disable usage of an alternative popup window, which
+ guarantees ability to focus the popup control, and allows common
+ native controls to function normally. This alternative popup window is
+ usually a wxDialog, and as such, when it is shown, its parent
+ top-level window will appear as if the focus has been lost from it.
+ """
+ return _combo.ComboCtrl_UseAltPopupWindow(*args, **kwargs)
+
+ def EnablePopupAnimation(*args, **kwargs):
+ """
+ EnablePopupAnimation(self, bool enable=True)
+
+ Enables or disables popup animation, if any, depending on the value of
+ the argument.
+ """
+ return _combo.ComboCtrl_EnablePopupAnimation(*args, **kwargs)
+
+ def IsKeyPopupToggle(*args, **kwargs):
+ """
+ IsKeyPopupToggle(self, KeyEvent event) -> bool
+
+ Returns true if given key combination should toggle the popup.
+ """
+ return _combo.ComboCtrl_IsKeyPopupToggle(*args, **kwargs)
+
+ def PrepareBackground(*args, **kwargs):
+ """
+ PrepareBackground(self, DC dc, Rect rect, int flags)
+
+ Prepare background of combo control or an item in a dropdown list in a
+ way typical on platform. This includes painting the focus/disabled
+ background and setting the clipping region. Unless you plan to paint
+ your own focus indicator, you should always call this in your
+ wxComboPopup::PaintComboControl implementation. In addition, it sets
+ pen and text colour to what looks good and proper against the
+ background.
+
+ flags are the same as wx.RendererNative flags:
+
+ ====================== ============================================
+ wx.CONTROL_ISSUBMENU drawing a list item instead of combo control
+ wx.CONTROL_SELECTED list item is selected
+ wx.CONTROL_DISABLED control/item is disabled
+ ====================== ============================================
+
+ """
+ return _combo.ComboCtrl_PrepareBackground(*args, **kwargs)
+
+ def ShouldDrawFocus(*args, **kwargs):
+ """
+ ShouldDrawFocus(self) -> bool
+
+ Returns true if focus indicator should be drawn in the control.
+ """
+ return _combo.ComboCtrl_ShouldDrawFocus(*args, **kwargs)
+
+ def GetBitmapNormal(*args, **kwargs):
+ """GetBitmapNormal(self) -> Bitmap"""
+ return _combo.ComboCtrl_GetBitmapNormal(*args, **kwargs)
+
+ def GetBitmapPressed(*args, **kwargs):
+ """GetBitmapPressed(self) -> Bitmap"""
+ return _combo.ComboCtrl_GetBitmapPressed(*args, **kwargs)
+
+ def GetBitmapHover(*args, **kwargs):
+ """GetBitmapHover(self) -> Bitmap"""
+ return _combo.ComboCtrl_GetBitmapHover(*args, **kwargs)
+
+ def GetBitmapDisabled(*args, **kwargs):
+ """GetBitmapDisabled(self) -> Bitmap"""
+ return _combo.ComboCtrl_GetBitmapDisabled(*args, **kwargs)
+
+ def GetInternalFlags(*args, **kwargs):
+ """GetInternalFlags(self) -> unsigned int"""
+ return _combo.ComboCtrl_GetInternalFlags(*args, **kwargs)
+
+ def IsCreated(*args, **kwargs):
+ """
+ IsCreated(self) -> bool
+
+ Return true if Create has finished
+ """
+ return _combo.ComboCtrl_IsCreated(*args, **kwargs)
+
+ def GetBackgroundColour(*args, **kwargs):
+ """
+ GetBackgroundColour(self) -> Colour
+
+ Returns the background colour of the window.
+ """
+ return _combo.ComboCtrl_GetBackgroundColour(*args, **kwargs)
+
+ def OnPopupDismiss(*args, **kwargs):
+ """
+ OnPopupDismiss(self, bool generateEvent)
+
+ Common code to be called on popup hide/dismiss
+ """
+ return _combo.ComboCtrl_OnPopupDismiss(*args, **kwargs)
+
+ Hidden = _combo.ComboCtrl_Hidden
+ Animating = _combo.ComboCtrl_Animating
+ Visible = _combo.ComboCtrl_Visible
+ def IsPopupWindowState(*args, **kwargs):
+ """IsPopupWindowState(self, int state) -> bool"""
+ return _combo.ComboCtrl_IsPopupWindowState(*args, **kwargs)
+
+ def GetPopupWindowState(*args, **kwargs):
+ """GetPopupWindowState(self) -> int"""
+ return _combo.ComboCtrl_GetPopupWindowState(*args, **kwargs)
+
+ def SetCtrlMainWnd(*args, **kwargs):
+ """SetCtrlMainWnd(self, Window wnd)"""
+ return _combo.ComboCtrl_SetCtrlMainWnd(*args, **kwargs)
+
+ def DestroyPopup(*args, **kwargs):
+ """DestroyPopup(self)"""
+ return _combo.ComboCtrl_DestroyPopup(*args, **kwargs)
+
+ def GetFeatures(*args, **kwargs):
+ """
+ GetFeatures() -> int
+
+ Returns a bit-list of flags indicating which features of the ComboCtrl
+ functionality are implemented by this implemetation. See
+ `wx.combo.ComboCtrlFeatures`.
+ """
+ return _combo.ComboCtrl_GetFeatures(*args, **kwargs)
+
+ GetFeatures = staticmethod(GetFeatures)
+ ShowBelow = _combo.ComboCtrl_ShowBelow
+ ShowAbove = _combo.ComboCtrl_ShowAbove
+ CanDeferShow = _combo.ComboCtrl_CanDeferShow
+ def DoShowPopup(*args, **kwargs):
+ """
+ DoShowPopup(self, Rect rect, int flags)
+
+ Shows and positions the popup.
+
+ Flags:
+ ============ =====================================================
+ ShowBelow Showing popup below the control
+ ShowAbove Showing popup above the control
+ CanDeferShow Can only return true from AnimateShow if this is set
+ ============ =====================================================
+
+ """
+ return _combo.ComboCtrl_DoShowPopup(*args, **kwargs)
+
+ def AnimateShow(*args, **kwargs):
+ """
+ AnimateShow(self, Rect rect, int flags) -> bool
+
+ Implement in derived class to create a drop-down animation. Return
+ ``True`` if finished immediately. Otherwise the popup is only shown when the
+ derived class calls `DoShowPopup`. Flags are same as for `DoShowPopup`.
+
+ """
+ return _combo.ComboCtrl_AnimateShow(*args, **kwargs)
+
+ PopupControl = property(GetPopupControl,SetPopupControl)
+ PopupWindow = property(GetPopupWindow)
+ TextCtrl = property(GetTextCtrl)
+ Button = property(GetButton)
+ CustomPaintWidth = property(GetCustomPaintWidth,SetCustomPaintWidth)
+ ButtonSize = property(GetButtonSize)
+ TextIndent = property(GetTextIndent,SetTextIndent)
+ TextRect = property(GetTextRect)
+ BitmapNormal = property(GetBitmapNormal)
+ BitmapPressed = property(GetBitmapPressed)
+ BitmapHover = property(GetBitmapHover)
+ BitmapDisabled = property(GetBitmapDisabled)
+ PopupWindowState = property(GetPopupWindowState)
+_combo.ComboCtrl_swigregister(ComboCtrl)
+
+def PreComboCtrl(*args, **kwargs):
+ """PreComboCtrl() -> ComboCtrl"""
+ val = _combo.new_PreComboCtrl(*args, **kwargs)
+ return val
+
+def ComboCtrl_GetFeatures(*args):
+ """
+ ComboCtrl_GetFeatures() -> int
+
+ Returns a bit-list of flags indicating which features of the ComboCtrl
+ functionality are implemented by this implemetation. See
+ `wx.combo.ComboCtrlFeatures`.
+ """
+ return _combo.ComboCtrl_GetFeatures(*args)
+
+#---------------------------------------------------------------------------
+
+class ComboPopup(object):
+ """
+ In order to use a custom popup with `wx.combo.ComboCtrl` an interface
+ class derived from wx.combo.ComboPopup is used to manage the interface
+ between the popup control and the popup. You can either derive a new
+ class from both the widget class and this ComboPopup class, or the
+ derived class can have a reference to the widget used for the popup.
+ In either case you simply need to return the widget from the
+ `GetControl` method to allow the ComboCtrl to interact with it.
+
+ Nearly all of the methods of this class are overridable in Python.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> ComboPopup
+
+ Constructor
+ """
+ _combo.ComboPopup_swiginit(self,_combo.new_ComboPopup(*args, **kwargs))
+ ComboPopup._setCallbackInfo(self, self, ComboPopup)
+
+ __swig_destroy__ = _combo.delete_ComboPopup
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _combo.ComboPopup__setCallbackInfo(*args, **kwargs)
+
+ def Init(*args, **kwargs):
+ """
+ Init(self)
+
+ This method is called after the popup is contructed and has been
+ assigned to the ComboCtrl. Derived classes can override this to do
+ extra inialization or whatever.
+ """
+ return _combo.ComboPopup_Init(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent) -> bool
+
+ The derived class must implement this method to create the popup
+ control. It should be a child of the ``parent`` passed in, but other
+ than that there is much flexibility in what the widget can be, its
+ style, etc. Return ``True`` for success, ``False`` otherwise. (NOTE:
+ this return value is not currently checked...)
+ """
+ return _combo.ComboPopup_Create(*args, **kwargs)
+
+ def DestroyPopup(*args, **kwargs):
+ """DestroyPopup(self)"""
+ return _combo.ComboPopup_DestroyPopup(*args, **kwargs)
+
+ def GetControl(*args, **kwargs):
+ """
+ GetControl(self) -> Window
+
+ The derived class must implement this method and it should return a
+ reference to the widget created in the `Create` method. If the
+ derived class inherits from both the widget class and ComboPopup then
+ the return value is probably just ``self``.
+ """
+ return _combo.ComboPopup_GetControl(*args, **kwargs)
+
+ def OnPopup(*args, **kwargs):
+ """
+ OnPopup(self)
+
+ The derived class may implement this to do special processing when
+ popup is shown.
+ """
+ return _combo.ComboPopup_OnPopup(*args, **kwargs)
+
+ def OnDismiss(*args, **kwargs):
+ """
+ OnDismiss(self)
+
+ The derived class may implement this to do special processing when
+ popup is hidden.
+ """
+ return _combo.ComboPopup_OnDismiss(*args, **kwargs)
+
+ def SetStringValue(*args, **kwargs):
+ """
+ SetStringValue(self, String value)
+
+ Called just prior to displaying the popup. The derived class can
+ implement this to "select" the item in the popup that coresponds to
+ the passed in string value, if appropriate. The default
+ implementation does nothing.
+ """
+ return _combo.ComboPopup_SetStringValue(*args, **kwargs)
+
+ def GetStringValue(*args, **kwargs):
+ """
+ GetStringValue(self) -> String
+
+ Gets the string representation of the currently selected value to be
+ used to display in the combo widget.
+ """
+ return _combo.ComboPopup_GetStringValue(*args, **kwargs)
+
+ def PaintComboControl(*args, **kwargs):
+ """
+ PaintComboControl(self, DC dc, Rect rect)
+
+ This is called to custom paint in the combo control itself (ie. not
+ the popup). Default implementation draws the current value as string.
+ """
+ return _combo.ComboPopup_PaintComboControl(*args, **kwargs)
+
+ def FindItem(*args, **kwargs):
+ """FindItem(self, String item) -> bool"""
+ return _combo.ComboPopup_FindItem(*args, **kwargs)
+
+ def OnComboKeyEvent(*args, **kwargs):
+ """
+ OnComboKeyEvent(self, KeyEvent event)
+
+ Receives key events from the parent ComboCtrl. Events not handled
+ should be skipped, as usual.
+ """
+ return _combo.ComboPopup_OnComboKeyEvent(*args, **kwargs)
+
+ def OnComboCharEvent(*args, **kwargs):
+ """OnComboCharEvent(self, KeyEvent event)"""
+ return _combo.ComboPopup_OnComboCharEvent(*args, **kwargs)
+
+ def OnComboDoubleClick(*args, **kwargs):
+ """
+ OnComboDoubleClick(self)
+
+ Implement this method in the derived class if you need to support
+ special actions when the user double-clicks on the parent ComboCtrl.
+ """
+ return _combo.ComboPopup_OnComboDoubleClick(*args, **kwargs)
+
+ def GetAdjustedSize(*args, **kwargs):
+ """
+ GetAdjustedSize(self, int minWidth, int prefHeight, int maxHeight) -> Size
+
+ The derived class may implement this method to return adjusted size
+ for the popup control, according to the variables given. It is called
+ on every popup, just prior to `OnPopup`.
+
+ :param minWidth: Preferred minimum width.
+ :param prefHeight: Preferred height. May be -1 to indicate no preference.
+ :maxWidth: Max height for window, as limited by screen size, and
+ should only be rounded down, if necessary.
+
+ """
+ return _combo.ComboPopup_GetAdjustedSize(*args, **kwargs)
+
+ def LazyCreate(*args, **kwargs):
+ """
+ LazyCreate(self) -> bool
+
+ The derived class may implement this to return ``True`` if it wants to
+ delay the call to `Create` until the popup is shown for the first
+ time. It is more efficient, but on the other hand it is often more
+ convenient to have the control created immediately. The default
+ implementation returns ``False``.
+ """
+ return _combo.ComboPopup_LazyCreate(*args, **kwargs)
+
+ def Dismiss(*args, **kwargs):
+ """
+ Dismiss(self)
+
+ Hides the popup
+ """
+ return _combo.ComboPopup_Dismiss(*args, **kwargs)
+
+ def IsCreated(*args, **kwargs):
+ """
+ IsCreated(self) -> bool
+
+ Returns true if `Create` has been called.
+ """
+ return _combo.ComboPopup_IsCreated(*args, **kwargs)
+
+ def GetComboCtrl(*args, **kwargs):
+ """
+ GetComboCtrl(self) -> wxComboCtrl
+
+ Returns the associated parent ComboCtrl.
+ """
+ return _combo.ComboPopup_GetComboCtrl(*args, **kwargs)
+
+ def DefaultPaintComboControl(*args, **kwargs):
+ """
+ DefaultPaintComboControl(wxComboCtrlBase combo, DC dc, Rect rect)
+
+ Default PaintComboControl behaviour
+ """
+ return _combo.ComboPopup_DefaultPaintComboControl(*args, **kwargs)
+
+ DefaultPaintComboControl = staticmethod(DefaultPaintComboControl)
+ def GetCombo(*args, **kwargs):
+ """
+ GetCombo(self) -> ComboCtrl
+
+ Returns a reference to the `wx.combo.ComboCtrl` this ComboPopup object
+ is associated with.
+ """
+ return _combo.ComboPopup_GetCombo(*args, **kwargs)
+
+_combo.ComboPopup_swigregister(ComboPopup)
+
+def ComboPopup_DefaultPaintComboControl(*args, **kwargs):
+ """
+ ComboPopup_DefaultPaintComboControl(wxComboCtrlBase combo, DC dc, Rect rect)
+
+ Default PaintComboControl behaviour
+ """
+ return _combo.ComboPopup_DefaultPaintComboControl(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+ODCB_DCLICK_CYCLES = _combo.ODCB_DCLICK_CYCLES
+ODCB_STD_CONTROL_PAINT = _combo.ODCB_STD_CONTROL_PAINT
+ODCB_PAINTING_CONTROL = _combo.ODCB_PAINTING_CONTROL
+ODCB_PAINTING_SELECTED = _combo.ODCB_PAINTING_SELECTED
+class OwnerDrawnComboBox(ComboCtrl,_core.ItemContainer):
+ """
+ wx.combo.OwnerDrawnComboBox is a combobox with owner-drawn list
+ items. In essence, it is a `wx.combo.ComboCtrl` with a `wx.VListBox`
+ popup and a `wx.ControlWithItems` API.
+
+ Implementing item drawing and measuring is similar to wx.VListBox.
+ The application needs to subclass wx.combo.OwnerDrawnComboBox and
+ implement the `OnDrawItem`, `OnMeasureItem` and `OnMeasureItemWidth`
+ methods.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ wxArrayString choices=wxPyEmptyStringArray,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ComboBoxNameStr) -> OwnerDrawnComboBox
+
+ Standard constructor.
+ """
+ _combo.OwnerDrawnComboBox_swiginit(self,_combo.new_OwnerDrawnComboBox(*args, **kwargs))
+ self._setOORInfo(self);OwnerDrawnComboBox._setCallbackInfo(self, self, OwnerDrawnComboBox)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _combo.OwnerDrawnComboBox__setCallbackInfo(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ wxArrayString choices=wxPyEmptyStringArray,
+ long style=0, Validator validator=DefaultValidator,
+ String name=ComboBoxNameStr) -> bool
+
+ Create the UI object, and other initialization.
+ """
+ return _combo.OwnerDrawnComboBox_Create(*args, **kwargs)
+
+ def GetWidestItemWidth(*args, **kwargs):
+ """
+ GetWidestItemWidth(self) -> int
+
+ Return the widest item width (recalculating it if necessary.)
+ """
+ return _combo.OwnerDrawnComboBox_GetWidestItemWidth(*args, **kwargs)
+
+ def GetWidestItem(*args, **kwargs):
+ """
+ GetWidestItem(self) -> int
+
+ Return the index of the widest item (recalculating it if necessary.)
+ """
+ return _combo.OwnerDrawnComboBox_GetWidestItem(*args, **kwargs)
+
+ GetString = wx.ItemContainer.GetString
+ GetSelection = wx.ItemContainer.GetSelection
+ SetSelection = wx.ItemContainer.SetSelection
+
+ def OnDrawItem(*args, **kwargs):
+ """
+ OnDrawItem(self, DC dc, Rect rect, int item, int flags)
+
+ The derived class may implement this function to actually draw the
+ item with the given index on the provided DC. If this method is not
+ overridden, the item text is simply drawn as if the control was a
+ normal combobox.
+
+ :param dc: The device context to use for drawing.
+ :param rect: The bounding rectangle for the item being drawn, the
+ DC's clipping region is set to this rectangle before
+ calling this method.
+ :param item: The index of the item to be drawn.
+
+ :param flags: ``wx.combo.ODCB_PAINTING_CONTROL`` (The Combo control itself
+ is being painted, instead of a list item. The ``item``
+ parameter may be ``wx.NOT_FOUND`` in this case.
+ ``wx.combo.ODCB_PAINTING_SELECTED`` (An item with
+ selection background is being painted. The DC's text colour
+ should already be correct.
+
+ """
+ return _combo.OwnerDrawnComboBox_OnDrawItem(*args, **kwargs)
+
+ def OnMeasureItem(*args, **kwargs):
+ """
+ OnMeasureItem(self, size_t item) -> int
+
+ The derived class may implement this method to return the height of
+ the specified item (in pixels). The default implementation returns
+ text height, as if this control was a normal combobox.
+ """
+ return _combo.OwnerDrawnComboBox_OnMeasureItem(*args, **kwargs)
+
+ def OnMeasureItemWidth(*args, **kwargs):
+ """
+ OnMeasureItemWidth(self, size_t item) -> int
+
+ The derived class may implement this method to return the width of the
+ specified item (in pixels). If -1 is returned, then the item text
+ width is used. The default implementation returns -1.
+ """
+ return _combo.OwnerDrawnComboBox_OnMeasureItemWidth(*args, **kwargs)
+
+ def OnDrawBackground(*args, **kwargs):
+ """
+ OnDrawBackground(self, DC dc, Rect rect, int item, int flags)
+
+ This method is used to draw the items background and, maybe, a border
+ around it.
+
+ The base class version implements a reasonable default behaviour which
+ consists in drawing the selected item with the standard background
+ colour and drawing a border around the item if it is either selected
+ or current. ``flags`` has the sam meaning as with `OnDrawItem`.
+ """
+ return _combo.OwnerDrawnComboBox_OnDrawBackground(*args, **kwargs)
+
+_combo.OwnerDrawnComboBox_swigregister(OwnerDrawnComboBox)
+
+def PreOwnerDrawnComboBox(*args, **kwargs):
+ """
+ PreOwnerDrawnComboBox() -> OwnerDrawnComboBox
+
+ 2-phase create constructor.
+ """
+ val = _combo.new_PreOwnerDrawnComboBox(*args, **kwargs)
+ return val
+
+class BitmapComboBox(_controls.ComboBox):
+ """
+ A combobox that displays a bitmap in front of the list items. It
+ currently only allows using bitmaps of one size, and resizes itself so
+ that a bitmap can be shown next to the text field.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ wxArrayString choices=wxPyEmptyStringArray,
+ long style=0, Validator validator=DefaultValidator,
+ String name=wxBitmapComboBoxNameStr) -> BitmapComboBox
+
+ Standard constructor
+ """
+ _combo.BitmapComboBox_swiginit(self,_combo.new_BitmapComboBox(*args, **kwargs))
+ self._setOORInfo(self);
+
+ def Create(*args, **kwargs):
+ """
+ Create(Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ List choices=EmptyList, long style=0, Validator validator=DefaultValidator,
+ String name=ChoiceNameStr) -> bool
+
+ Create the UI object, and other initialization.
+ """
+ return _combo.BitmapComboBox_Create(*args, **kwargs)
+
+ def Append(*args, **kwargs):
+ """
+ Append(self, String item, Bitmap bitmap=wxNullBitmap, PyObject clientData=None) -> int
+
+ Adds the item to the control, associating the given data with the item
+ if not None. The return value is the index of the newly added item.
+ """
+ return _combo.BitmapComboBox_Append(*args, **kwargs)
+
+ def GetItemBitmap(*args, **kwargs):
+ """
+ GetItemBitmap(self, int n) -> Bitmap
+
+ Returns the image of the item with the given index.
+ """
+ return _combo.BitmapComboBox_GetItemBitmap(*args, **kwargs)
+
+ def Insert(*args, **kwargs):
+ """
+ Insert(self, String item, Bitmap bitmap, int pos, PyObject clientData=None) -> int
+
+ Insert an item into the control before the item at the ``pos`` index,
+ optionally associating some data object with the item.
+ """
+ return _combo.BitmapComboBox_Insert(*args, **kwargs)
+
+ def SetItemBitmap(*args, **kwargs):
+ """
+ SetItemBitmap(self, int n, Bitmap bitmap)
+
+ Sets the image for the given item.
+ """
+ return _combo.BitmapComboBox_SetItemBitmap(*args, **kwargs)
+
+ def GetBitmapSize(*args, **kwargs):
+ """
+ GetBitmapSize(self) -> Size
+
+ Returns size of the image used in list.
+ """
+ return _combo.BitmapComboBox_GetBitmapSize(*args, **kwargs)
+
+_combo.BitmapComboBox_swigregister(BitmapComboBox)
+
+def PreBitmapComboBox(*args, **kwargs):
+ """
+ PreBitmapComboBox() -> BitmapComboBox
+
+ 2-phase create constructor.
+ """
+ val = _combo.new_PreBitmapComboBox(*args, **kwargs)
+ return val
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/dataview.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/dataview.py
new file mode 100644
index 0000000..7637077
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/dataview.py
@@ -0,0 +1,2584 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+The `DataViewCtrl` class can display data in either a tree-like
+fashion, in a tabular form, or in a combination of the two. It is a
+native widget on the platforms that provide such a control, (currently
+OS X and GTK) and generic elsewhere.
+"""
+
+import _dataview
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+DVC_DEFAULT_RENDERER_SIZE = _dataview.DVC_DEFAULT_RENDERER_SIZE
+DVC_DEFAULT_WIDTH = _dataview.DVC_DEFAULT_WIDTH
+DVC_TOGGLE_DEFAULT_WIDTH = _dataview.DVC_TOGGLE_DEFAULT_WIDTH
+DVC_DEFAULT_MINWIDTH = _dataview.DVC_DEFAULT_MINWIDTH
+DVR_DEFAULT_ALIGNMENT = _dataview.DVR_DEFAULT_ALIGNMENT
+#---------------------------------------------------------------------------
+
+class DataViewItem(object):
+ """
+ wxDataViewItem is a small opaque class that represents an item in a
+ `DataViewCtrl` in a persistent way, i.e. indepent of the position of
+ the item in the control or changes to its contents. It contains a C
+ void pointer which is used as the internal ID value for the item. If
+ the ID is NULL then the DataViewItem is considered invalid and the
+ `IsOk` method will return False, which is used in many places in the
+ API to indicate that no item was found.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, PyLong ID=0) -> DataViewItem
+
+ wxDataViewItem is a small opaque class that represents an item in a
+ `DataViewCtrl` in a persistent way, i.e. indepent of the position of
+ the item in the control or changes to its contents. It contains a C
+ void pointer which is used as the internal ID value for the item. If
+ the ID is NULL then the DataViewItem is considered invalid and the
+ `IsOk` method will return False, which is used in many places in the
+ API to indicate that no item was found.
+ """
+ _dataview.DataViewItem_swiginit(self,_dataview.new_DataViewItem(*args, **kwargs))
+ __swig_destroy__ = _dataview.delete_DataViewItem
+ __del__ = lambda self : None;
+ def IsOk(*args, **kwargs):
+ """
+ IsOk(self) -> bool
+
+ Returns ``True`` if the object refers to an actual item in the data
+ view control.
+ """
+ return _dataview.DataViewItem_IsOk(*args, **kwargs)
+
+ def __nonzero__(self): return self.IsOk()
+ def GetID(*args, **kwargs):
+ """GetID(self) -> PyLong"""
+ return _dataview.DataViewItem_GetID(*args, **kwargs)
+
+ ID = property(GetID)
+ def __hash__(*args, **kwargs):
+ """__hash__(self) -> long"""
+ return _dataview.DataViewItem___hash__(*args, **kwargs)
+
+ def __cmp__(*args, **kwargs):
+ """__cmp__(self, DataViewItem other) -> int"""
+ return _dataview.DataViewItem___cmp__(*args, **kwargs)
+
+_dataview.DataViewItem_swigregister(DataViewItem)
+cvar = _dataview.cvar
+DataViewCtrlNameStr = cvar.DataViewCtrlNameStr
+
+class DataViewItemArray_iterator(object):
+ """This class serves as an iterator for a wxDataViewItemArray object."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _dataview.delete_DataViewItemArray_iterator
+ __del__ = lambda self : None;
+ def next(*args, **kwargs):
+ """next(self) -> DataViewItem"""
+ return _dataview.DataViewItemArray_iterator_next(*args, **kwargs)
+
+_dataview.DataViewItemArray_iterator_swigregister(DataViewItemArray_iterator)
+
+class DataViewItemArray(object):
+ """
+ This class wraps a wxArray-based class and gives it a Python
+ sequence-like interface. Sequence operations supported are length,
+ index access and iteration.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _dataview.delete_DataViewItemArray
+ __del__ = lambda self : None;
+ def __len__(*args, **kwargs):
+ """__len__(self) -> size_t"""
+ return _dataview.DataViewItemArray___len__(*args, **kwargs)
+
+ def __getitem__(*args, **kwargs):
+ """__getitem__(self, size_t index) -> DataViewItem"""
+ return _dataview.DataViewItemArray___getitem__(*args, **kwargs)
+
+ def __iter__(*args, **kwargs):
+ """__iter__(self) -> DataViewItemArray_iterator"""
+ return _dataview.DataViewItemArray___iter__(*args, **kwargs)
+
+ def append(*args, **kwargs):
+ """append(self, DataViewItem object)"""
+ return _dataview.DataViewItemArray_append(*args, **kwargs)
+
+ def insert(*args, **kwargs):
+ """insert(self, size_t index, DataViewItem object)"""
+ return _dataview.DataViewItemArray_insert(*args, **kwargs)
+
+ def __repr__(self):
+ return "wxDataViewItemArray: " + repr(list(self))
+
+_dataview.DataViewItemArray_swigregister(DataViewItemArray)
+
+NullDataViewItem = DataViewItem()
+#---------------------------------------------------------------------------
+
+class DataViewModelNotifier(object):
+ """
+ This class allows multiple entities to be notified when a change
+ happens in a `DataViewModel` instance, and it mirrors the notification
+ interface in that class. To add your own notifier object to a model,
+ derive a new class from `PyDataViewModelNotifier`, override the
+ methods you are interested in, and assign an instance of it to the
+ model with `DataViewModel.AddNotifier`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _dataview.delete_DataViewModelNotifier
+ __del__ = lambda self : None;
+ def ItemAdded(*args, **kwargs):
+ """
+ ItemAdded(self, DataViewItem parent, DataViewItem item) -> bool
+
+ Override this to be informed that an item has been added to the data
+ model.
+ """
+ return _dataview.DataViewModelNotifier_ItemAdded(*args, **kwargs)
+
+ def ItemDeleted(*args, **kwargs):
+ """
+ ItemDeleted(self, DataViewItem parent, DataViewItem item) -> bool
+
+ Override this to be informed that an item has been deleted.
+ """
+ return _dataview.DataViewModelNotifier_ItemDeleted(*args, **kwargs)
+
+ def ItemChanged(*args, **kwargs):
+ """
+ ItemChanged(self, DataViewItem item) -> bool
+
+ Override this to be informed that an item's value has changed.
+ """
+ return _dataview.DataViewModelNotifier_ItemChanged(*args, **kwargs)
+
+ def ItemsAdded(*args, **kwargs):
+ """
+ ItemsAdded(self, DataViewItem parent, DataViewItemArray items) -> bool
+
+ Override this to be informed that several items have been added to the model.
+ """
+ return _dataview.DataViewModelNotifier_ItemsAdded(*args, **kwargs)
+
+ def ItemsDeleted(*args, **kwargs):
+ """
+ ItemsDeleted(self, DataViewItem parent, DataViewItemArray items) -> bool
+
+ Override this to be informed that several items have been deleted.
+ """
+ return _dataview.DataViewModelNotifier_ItemsDeleted(*args, **kwargs)
+
+ def ItemsChanged(*args, **kwargs):
+ """
+ ItemsChanged(self, DataViewItemArray items) -> bool
+
+ Override this to be informed that several items have been changed.
+ """
+ return _dataview.DataViewModelNotifier_ItemsChanged(*args, **kwargs)
+
+ def ValueChanged(*args, **kwargs):
+ """
+ ValueChanged(self, DataViewItem item, unsigned int col) -> bool
+
+ Override this to be informed that a value has changed in the model.
+ This differs from `ItemChanged` in that this method is sensitive to
+ changes in sub-elements of an item, not just the whole item (row).
+ """
+ return _dataview.DataViewModelNotifier_ValueChanged(*args, **kwargs)
+
+ def Cleared(*args, **kwargs):
+ """
+ Cleared(self) -> bool
+
+ Override this to be informed that all data has been cleared. The
+ control will read the visible data items from the model again.
+ """
+ return _dataview.DataViewModelNotifier_Cleared(*args, **kwargs)
+
+ def BeforeReset(*args, **kwargs):
+ """BeforeReset(self) -> bool"""
+ return _dataview.DataViewModelNotifier_BeforeReset(*args, **kwargs)
+
+ def AfterReset(*args, **kwargs):
+ """AfterReset(self) -> bool"""
+ return _dataview.DataViewModelNotifier_AfterReset(*args, **kwargs)
+
+ def Resort(*args, **kwargs):
+ """
+ Resort(self)
+
+ Override this to be informed that a resort has been initiated after
+ the sort function has been changed.
+ """
+ return _dataview.DataViewModelNotifier_Resort(*args, **kwargs)
+
+ def SetOwner(*args, **kwargs):
+ """
+ SetOwner(self, DataViewModel owner)
+
+ Sets the owner (the model) of this notifier. Used internally.
+ """
+ return _dataview.DataViewModelNotifier_SetOwner(*args, **kwargs)
+
+ def GetOwner(*args, **kwargs):
+ """
+ GetOwner(self) -> DataViewModel
+
+ Returns the owner (the model) of this notifier.
+ """
+ return _dataview.DataViewModelNotifier_GetOwner(*args, **kwargs)
+
+ Owner = property(GetOwner,SetOwner)
+_dataview.DataViewModelNotifier_swigregister(DataViewModelNotifier)
+
+class PyDataViewModelNotifier(DataViewModelNotifier):
+ """
+ This class is a version of `DataViewModelNotifier` that has been
+ engineered to know how to reflect the C++ virtual method calls to
+ Python methods in the derived class. Use this class as your base
+ class instead of `DataViewModelNotifier`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PyDataViewModelNotifier
+
+ This class is a version of `DataViewModelNotifier` that has been
+ engineered to know how to reflect the C++ virtual method calls to
+ Python methods in the derived class. Use this class as your base
+ class instead of `DataViewModelNotifier`.
+ """
+ _dataview.PyDataViewModelNotifier_swiginit(self,_dataview.new_PyDataViewModelNotifier(*args, **kwargs))
+ PyDataViewModelNotifier._setCallbackInfo(self, self, PyDataViewModelNotifier)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _dataview.PyDataViewModelNotifier__setCallbackInfo(*args, **kwargs)
+
+_dataview.PyDataViewModelNotifier_swigregister(PyDataViewModelNotifier)
+
+#---------------------------------------------------------------------------
+
+class DataViewItemAttr(object):
+ """Proxy of C++ DataViewItemAttr class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> DataViewItemAttr"""
+ _dataview.DataViewItemAttr_swiginit(self,_dataview.new_DataViewItemAttr(*args, **kwargs))
+ __swig_destroy__ = _dataview.delete_DataViewItemAttr
+ __del__ = lambda self : None;
+ def SetColour(*args, **kwargs):
+ """SetColour(self, Colour colour)"""
+ return _dataview.DataViewItemAttr_SetColour(*args, **kwargs)
+
+ def SetBold(*args, **kwargs):
+ """SetBold(self, bool set)"""
+ return _dataview.DataViewItemAttr_SetBold(*args, **kwargs)
+
+ def SetItalic(*args, **kwargs):
+ """SetItalic(self, bool set)"""
+ return _dataview.DataViewItemAttr_SetItalic(*args, **kwargs)
+
+ def HasColour(*args, **kwargs):
+ """HasColour(self) -> bool"""
+ return _dataview.DataViewItemAttr_HasColour(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """GetColour(self) -> Colour"""
+ return _dataview.DataViewItemAttr_GetColour(*args, **kwargs)
+
+ def HasFont(*args, **kwargs):
+ """HasFont(self) -> bool"""
+ return _dataview.DataViewItemAttr_HasFont(*args, **kwargs)
+
+ def GetBold(*args, **kwargs):
+ """GetBold(self) -> bool"""
+ return _dataview.DataViewItemAttr_GetBold(*args, **kwargs)
+
+ def GetItalic(*args, **kwargs):
+ """GetItalic(self) -> bool"""
+ return _dataview.DataViewItemAttr_GetItalic(*args, **kwargs)
+
+ def IsDefault(*args, **kwargs):
+ """IsDefault(self) -> bool"""
+ return _dataview.DataViewItemAttr_IsDefault(*args, **kwargs)
+
+ def GetEffectiveFont(*args, **kwargs):
+ """GetEffectiveFont(self, Font font) -> Font"""
+ return _dataview.DataViewItemAttr_GetEffectiveFont(*args, **kwargs)
+
+ Colour = property(GetColour,SetColour)
+ Bold = property(GetBold,SetBold)
+ Italic = property(GetItalic,SetItalic)
+_dataview.DataViewItemAttr_swigregister(DataViewItemAttr)
+
+#---------------------------------------------------------------------------
+
+class DataViewModel(_core.RefCounter):
+ """
+ `DataViewModel` is the base class for managing all data to be
+ displayed by a `DataViewCtrl`. All other models derive from it and
+ must implement several of its methods in order to define a complete
+ data model. In detail, you need to override `IsContainer`,
+ `GetParent`, `GetChildren`, `GetColumnCount`, `GetColumnType` and
+ `GetValue` in order to define the data model which acts as an
+ interface between your actual data and the `DataViewCtrl`. Since you
+ will usually also allow the `DataViewCtrl` to change your data through
+ its graphical interface, you will also have to override `SetValue`
+ which the `DataViewCtrl` will call when a change to some data has been
+ commited. To implement a custom data model derive a new class from
+ `PyDataViewModel` and implement the required methods.
+
+ The data that is presented through this data model is expected to
+ change at run-time. You need to inform the data model when a change
+ happened. Depending on what happened you need to call one of the
+ following methods: `ValueChanged`, `ItemAdded`, `ItemDeleted`,
+ `ItemChanged`, `Cleared`. There are plural forms for notification of
+ addition, change or removal of several item at once. See `ItemsAdded`,
+ `ItemsDeleted`, `ItemsChanged`.
+
+ Note that ``DataViewModel`` does not define the position or index of
+ any item in the control because different controls might display the
+ same data differently. ``DataViewModel`` does provide a `Compare`
+ method which the `DataViewCtrl` may use to sort the data either in
+ conjunction with a column header or without (see `HasDefaultCompare`).
+
+ This class maintains a list of `DataViewModelNotifier` objects which
+ link this class to the specific implementations on the supported
+ platforms so that e.g. calling `ValueChanged` on this model will just
+ call `DataViewModelNotifier.ValueChanged` for each notifier that has
+ been added. You can also add your own notifier in order to get
+ informed about any changes to the data in the list model.
+
+ Currently wxWidgets provides the following models in addition to this
+ base class: `DataViewIndexListModel`, `DataViewVirtualListModel-, and
+ `DataViewTreeStore`. To create your own model from Python you will
+ need to use the `PyDataViewModel` as your base class.
+
+ :note: The C++ DataView classes use the wxVariant class to pass around
+ dynamically typed data values. In wxPython we have typemaps that
+ will convert variants to Python objects of appropriate types, and
+ if the type of object is not one that wxVariant will understand
+ then the raw PyObject is passed through, with appropriate
+ ref-counting. The wxVariant type names and the Python types they
+ are converted to or from are listed in this table:
+
+ ============= =======================
+ 'bool' Boolean
+ 'long' Integer
+ 'double' Float
+ 'string' String or Unicode
+ 'PyObject' any other Python type
+ ============= =======================
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetColumnCount(*args, **kwargs):
+ """
+ GetColumnCount(self) -> unsigned int
+
+ Override this to indicate the number of columns in the model.
+ """
+ return _dataview.DataViewModel_GetColumnCount(*args, **kwargs)
+
+ def GetColumnType(*args, **kwargs):
+ """
+ GetColumnType(self, unsigned int col) -> String
+
+ Override this to indicate what type of data is stored in the column
+ specified by col. This should return a string indicating the type name of the
+ data type of the column, as used by wxVariant.
+ """
+ return _dataview.DataViewModel_GetColumnType(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """
+ GetValue(self, DataViewItem item, unsigned int col) -> wxVariant
+
+ Override this and return the value to be used for the item, in the
+ given column. The type of the return value should match that given by
+ `GetColumnType`.
+ """
+ return _dataview.DataViewModel_GetValue(*args, **kwargs)
+
+ def HasValue(*args, **kwargs):
+ """
+ HasValue(self, DataViewItem item, unsigned int col) -> bool
+
+ return true if the given item has a value to display in the given
+ column: this is always true except for container items which by
+ default only show their label in the first column (but see
+ HasContainerColumns())
+ """
+ return _dataview.DataViewModel_HasValue(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """
+ SetValue(self, wxVariant variant, DataViewItem item, unsigned int col) -> bool
+
+ This gets called in order to set a value in the data model. The most
+ common scenario is that the `DataViewCtrl` calls this method after the
+ user has changed some data in the view. The model should then update
+ whatever it is using for storing the data values and then call
+ `ValueChanged` so proper notifications are performed.
+ """
+ return _dataview.DataViewModel_SetValue(*args, **kwargs)
+
+ def ChangeValue(*args, **kwargs):
+ """ChangeValue(self, wxVariant variant, DataViewItem item, unsigned int col) -> bool"""
+ return _dataview.DataViewModel_ChangeValue(*args, **kwargs)
+
+ def GetAttr(*args, **kwargs):
+ """
+ GetAttr(self, DataViewItem item, unsigned int col, DataViewItemAttr attr) -> bool
+
+ Override this to indicate that the item has special font
+ attributes. This only affects the `DataViewTextRenderer` renderer.
+ Return ``False`` if the default attributes should be used.
+ """
+ return _dataview.DataViewModel_GetAttr(*args, **kwargs)
+
+ def IsEnabled(*args, **kwargs):
+ """
+ IsEnabled(self, DataViewItem item, unsigned int col) -> bool
+
+ Override this if you want to disable specific items
+ """
+ return _dataview.DataViewModel_IsEnabled(*args, **kwargs)
+
+ def GetParent(*args, **kwargs):
+ """
+ GetParent(self, DataViewItem item) -> DataViewItem
+
+ Override this to indicate which item is the parent of the given item.
+ If the item is a child of the (hidden) root, then simply return an
+ invalid item, (one constructed with no ID.)
+ """
+ return _dataview.DataViewModel_GetParent(*args, **kwargs)
+
+ def IsContainer(*args, **kwargs):
+ """
+ IsContainer(self, DataViewItem item) -> bool
+
+ Override this to indicate whether an item is a container, in other
+ words, if it is a parent item that can have children.
+ """
+ return _dataview.DataViewModel_IsContainer(*args, **kwargs)
+
+ def HasContainerColumns(*args, **kwargs):
+ """
+ HasContainerColumns(self, DataViewItem item) -> bool
+
+ Override this method to indicate if a container item merely acts as a
+ headline (such as for categorisation) or if it also acts a normal item with
+ entries for the other columns. The default implementation returns ``False``.
+ """
+ return _dataview.DataViewModel_HasContainerColumns(*args, **kwargs)
+
+ def GetChildren(*args, **kwargs):
+ """
+ GetChildren(self, DataViewItem item, DataViewItemArray children) -> unsigned int
+
+ Override this so the control can find the children of a container
+ item. The children array should be filled with the child items of the
+ given item, and the number of children should be returned.
+ """
+ return _dataview.DataViewModel_GetChildren(*args, **kwargs)
+
+ def ItemAdded(*args, **kwargs):
+ """
+ ItemAdded(self, DataViewItem parent, DataViewItem item) -> bool
+
+ Call this to inform the registered notifiers that an item has been
+ added to the model.
+ """
+ return _dataview.DataViewModel_ItemAdded(*args, **kwargs)
+
+ def ItemsAdded(*args, **kwargs):
+ """
+ ItemsAdded(self, DataViewItem parent, DataViewItemArray items) -> bool
+
+ Call this to inform the registered notifiers that multiple items have
+ been added to the data model.
+ """
+ return _dataview.DataViewModel_ItemsAdded(*args, **kwargs)
+
+ def ItemDeleted(*args, **kwargs):
+ """
+ ItemDeleted(self, DataViewItem parent, DataViewItem item) -> bool
+
+ Call this to inform the registered notifiers that an item has been
+ deleted from the model.
+ """
+ return _dataview.DataViewModel_ItemDeleted(*args, **kwargs)
+
+ def ItemsDeleted(*args, **kwargs):
+ """
+ ItemsDeleted(self, DataViewItem parent, DataViewItemArray items) -> bool
+
+ Call this to inform the registered notifiers that multiple items have
+ been deleted from the data model.
+ """
+ return _dataview.DataViewModel_ItemsDeleted(*args, **kwargs)
+
+ def ItemChanged(*args, **kwargs):
+ """
+ ItemChanged(self, DataViewItem item) -> bool
+
+ Call this to inform the registered notifiers that an item has changed.
+ This will eventually result in a EVT_DATAVIEW_ITEM_VALUE_CHANGED
+ event, in which the column field will not be set.
+ """
+ return _dataview.DataViewModel_ItemChanged(*args, **kwargs)
+
+ def ItemsChanged(*args, **kwargs):
+ """
+ ItemsChanged(self, DataViewItemArray items) -> bool
+
+ Call this to inform the registered notifiers that multiple items have
+ changed. This will eventually result in EVT_DATAVIEW_ITEM_VALUE_CHANGED
+ events, in which the column field will not be set.
+ """
+ return _dataview.DataViewModel_ItemsChanged(*args, **kwargs)
+
+ def ValueChanged(*args, **kwargs):
+ """
+ ValueChanged(self, DataViewItem item, unsigned int col) -> bool
+
+ Call this to inform the registered notifiers that a value in the model
+ has been changed. This will eventually result in a EVT_DATAVIEW_ITEM_VALUE_CHANGED
+ event.
+ """
+ return _dataview.DataViewModel_ValueChanged(*args, **kwargs)
+
+ def Cleared(*args, **kwargs):
+ """
+ Cleared(self) -> bool
+
+ Call this to inform the registered notifiers that all data has been
+ cleared. The control will then reread the data from the model again.
+ """
+ return _dataview.DataViewModel_Cleared(*args, **kwargs)
+
+ def BeforeReset(*args, **kwargs):
+ """BeforeReset(self) -> bool"""
+ return _dataview.DataViewModel_BeforeReset(*args, **kwargs)
+
+ def AfterReset(*args, **kwargs):
+ """AfterReset(self) -> bool"""
+ return _dataview.DataViewModel_AfterReset(*args, **kwargs)
+
+ def Resort(*args, **kwargs):
+ """
+ Resort(self)
+
+ Call this to initiate a resort after the sort function has been changed.
+ """
+ return _dataview.DataViewModel_Resort(*args, **kwargs)
+
+ def AddNotifier(*args, **kwargs):
+ """AddNotifier(self, DataViewModelNotifier notifier)"""
+ return _dataview.DataViewModel_AddNotifier(*args, **kwargs)
+
+ def RemoveNotifier(*args, **kwargs):
+ """RemoveNotifier(self, DataViewModelNotifier notifier)"""
+ val = _dataview.DataViewModel_RemoveNotifier(*args, **kwargs)
+ args[1].thisown = 1
+ return val
+
+ def Compare(*args, **kwargs):
+ """
+ Compare(self, DataViewItem item1, DataViewItem item2, unsigned int column,
+ bool ascending) -> int
+
+ The compare function to be used by the control. The default compare
+ function sorts by container and other items separately and in
+ ascending order. Override this for a different sorting behaviour.
+ """
+ return _dataview.DataViewModel_Compare(*args, **kwargs)
+
+ def HasDefaultCompare(*args, **kwargs):
+ """
+ HasDefaultCompare(self) -> bool
+
+ Override this to indicate that the model provides a default compare
+ function that the control should use if no column has been chosen for
+ sorting. Usually, the user clicks on a column header for sorting and
+ the data will be sorted alphanumerically. If any other order (e.g. by
+ index or order of appearance) is required, then this should be used.
+ """
+ return _dataview.DataViewModel_HasDefaultCompare(*args, **kwargs)
+
+ def IsListModel(*args, **kwargs):
+ """IsListModel(self) -> bool"""
+ return _dataview.DataViewModel_IsListModel(*args, **kwargs)
+
+ def IsVirtualListModel(*args, **kwargs):
+ """IsVirtualListModel(self) -> bool"""
+ return _dataview.DataViewModel_IsVirtualListModel(*args, **kwargs)
+
+_dataview.DataViewModel_swigregister(DataViewModel)
+
+class DataViewItemObjectMapper(object):
+ """
+ This class provides a mechanism for mapping between Python objects and the
+ DataViewItem objects used by the DataViewModel for tracking the items in
+ the view. The ID used for the item is the id() of the Python object. Use
+ `ObjectToItem` to create a DataViewItem using a Python object as its ID,
+ and use `ItemToObject` to fetch that Python object again later for a given
+ DataViewItem.
+
+ By default a regular dictionary is used to implement the ID to object
+ mapping. Optionally a WeakValueDictionary can be useful when there will be
+ a high turnover of objects and mantaining an extra reference to the
+ objects would be unwise. If weak references are used then the objects
+ associated with data items must be weak-referenceable. (Things like
+ stock lists and dictionaries are not.) See `UseWeakRefs`.
+
+ Each `PyDataViewModel` has an instance of this class named objmapper.
+ """
+ def __init__(self):
+ self.mapper = dict()
+ self.usingWeakRefs = False
+
+ def ObjectToItem(self, obj):
+ """
+ Create a DataViewItem for the object, and remember the ID-->obj mapping.
+ """
+ oid = id(obj)
+ self.mapper[oid] = obj
+ return DataViewItem(oid)
+
+ def ItemToObject(self, item):
+ """
+ Retrieve the object that was used to create an item.
+ """
+ oid = item.GetID()
+ return self.mapper[oid]
+
+ def UseWeakRefs(self, flag):
+ """
+ Switch to or from using a weak value dictionary for keeping the ID to
+ object map.
+ """
+ if flag == self.usingWeakRefs:
+ return
+ if flag:
+ import weakref
+ newmap = weakref.WeakValueDictionary()
+ else:
+ newmap = dict()
+ newmap.update(self.mapper)
+ self.mapper = newmap
+ self.usingWeakRefs = flag
+
+
+class PyDataViewModel(DataViewModel):
+ """
+ This class is a version of `DataViewModel` that has been
+ engineered to know how to reflect the C++ virtual method calls to
+ Python methods in the derived class. Use this class as your base
+ class instead of `DataViewModel`.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> PyDataViewModel
+
+ This class is a version of `DataViewModel` that has been
+ engineered to know how to reflect the C++ virtual method calls to
+ Python methods in the derived class. Use this class as your base
+ class instead of `DataViewModel`.
+ """
+ _dataview.PyDataViewModel_swiginit(self,_dataview.new_PyDataViewModel(*args, **kwargs))
+ PyDataViewModel._setCallbackInfo(self, self, PyDataViewModel); self.objmapper = DataViewItemObjectMapper()
+
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _dataview.PyDataViewModel__setCallbackInfo(*args, **kwargs)
+
+ def ObjectToItem(self, obj):
+ "Convenience access to DataViewItemObjectMapper.ObjectToItem."
+ return self.objmapper.ObjectToItem(obj)
+
+ def ItemToObject(self, item):
+ "Convenience access to DataViewItemObjectMapper.ItemToObject."
+ return self.objmapper.ItemToObject(item)
+
+_dataview.PyDataViewModel_swigregister(PyDataViewModel)
+
+#---------------------------------------------------------------------------
+
+class DataViewIndexListModel(DataViewModel):
+ """
+ DataViewIndexListModel is a specialized data model which lets you
+ address an item by its position (row) rather than its `DataViewItem`
+ (which you can obtain from this class if needed). This model also
+ provides its own `Compare` method which sorts the model's data by the
+ index. To implement a custom list-based data model derive a new class
+ from `PyDataViewIndexListModel` and implement the required methods.
+
+ This model is not a virtual model since the control stores each
+ `DataViewItem` in memory. Use a `DataViewVirtualListModel` if you need
+ to display millions of items or have other reasons to use a virtual
+ control.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _dataview.delete_DataViewIndexListModel
+ __del__ = lambda self : None;
+ def GetValueByRow(*args, **kwargs):
+ """
+ GetValueByRow(self, unsigned int row, unsigned int col) -> wxVariant
+
+ Override this method to return the data value to be used for the item
+ at the given row and column.
+ """
+ return _dataview.DataViewIndexListModel_GetValueByRow(*args, **kwargs)
+
+ def SetValueByRow(*args, **kwargs):
+ """
+ SetValueByRow(self, wxVariant variant, unsigned int row, unsigned int col) -> bool
+
+ This is called in order to set a value in the data model.
+ """
+ return _dataview.DataViewIndexListModel_SetValueByRow(*args, **kwargs)
+
+ def GetAttrByRow(*args, **kwargs):
+ """
+ GetAttrByRow(self, unsigned int row, unsigned int col, DataViewItemAttr attr) -> bool
+
+ Override this to indicate that the item has special font
+ attributes. This only affects the `DataViewTextRenderer` renderer.
+ Return ``False`` if the default attributes should be used.
+ """
+ return _dataview.DataViewIndexListModel_GetAttrByRow(*args, **kwargs)
+
+ def IsEnabledByRow(*args, **kwargs):
+ """IsEnabledByRow(self, unsigned int row, unsigned int col) -> bool"""
+ return _dataview.DataViewIndexListModel_IsEnabledByRow(*args, **kwargs)
+
+ def RowPrepended(*args, **kwargs):
+ """
+ RowPrepended(self)
+
+ Call this after a row has been prepended to the model.
+ """
+ return _dataview.DataViewIndexListModel_RowPrepended(*args, **kwargs)
+
+ def RowInserted(*args, **kwargs):
+ """
+ RowInserted(self, unsigned int before)
+
+ Call this after a row has been inserted at the given position
+ """
+ return _dataview.DataViewIndexListModel_RowInserted(*args, **kwargs)
+
+ def RowAppended(*args, **kwargs):
+ """
+ RowAppended(self)
+
+ Call this after a row has been appended to the model.
+ """
+ return _dataview.DataViewIndexListModel_RowAppended(*args, **kwargs)
+
+ def RowDeleted(*args, **kwargs):
+ """
+ RowDeleted(self, unsigned int row)
+
+ Call this after a row has been deleted.
+ """
+ return _dataview.DataViewIndexListModel_RowDeleted(*args, **kwargs)
+
+ def RowsDeleted(*args, **kwargs):
+ """
+ RowsDeleted(self, wxArrayInt rows)
+
+ Call this after rows have been deleted. The array will internally get
+ copied and sorted in descending order so that the rows with the
+ highest position will be deleted first.
+ """
+ return _dataview.DataViewIndexListModel_RowsDeleted(*args, **kwargs)
+
+ def RowChanged(*args, **kwargs):
+ """
+ RowChanged(self, unsigned int row)
+
+ Call this after a row has been changed.
+ """
+ return _dataview.DataViewIndexListModel_RowChanged(*args, **kwargs)
+
+ def RowValueChanged(*args, **kwargs):
+ """
+ RowValueChanged(self, unsigned int row, unsigned int col)
+
+ Call this after a value has been changed.
+ """
+ return _dataview.DataViewIndexListModel_RowValueChanged(*args, **kwargs)
+
+ def Reset(*args, **kwargs):
+ """
+ Reset(self, unsigned int new_size)
+
+ Call this if the data has to be read again from the model. This is
+ useful after major changes when calling methods like `RowChanged` or
+ `RowDeleted` (possibly thousands of times) doesn't make sense.
+ """
+ return _dataview.DataViewIndexListModel_Reset(*args, **kwargs)
+
+ def GetRow(*args, **kwargs):
+ """
+ GetRow(self, DataViewItem item) -> unsigned int
+
+ Returns the row position of item.
+ """
+ return _dataview.DataViewIndexListModel_GetRow(*args, **kwargs)
+
+ def GetCount(*args, **kwargs):
+ """
+ GetCount(self) -> unsigned int
+
+ returns the number of rows
+ """
+ return _dataview.DataViewIndexListModel_GetCount(*args, **kwargs)
+
+ def GetItem(*args, **kwargs):
+ """
+ GetItem(self, unsigned int row) -> DataViewItem
+
+ Returns the DataViewItem for the item at row.
+ """
+ return _dataview.DataViewIndexListModel_GetItem(*args, **kwargs)
+
+_dataview.DataViewIndexListModel_swigregister(DataViewIndexListModel)
+
+class PyDataViewIndexListModel(DataViewIndexListModel):
+ """Proxy of C++ PyDataViewIndexListModel class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, unsigned int initial_size=0) -> PyDataViewIndexListModel"""
+ _dataview.PyDataViewIndexListModel_swiginit(self,_dataview.new_PyDataViewIndexListModel(*args, **kwargs))
+ PyDataViewIndexListModel._setCallbackInfo(self, self, PyDataViewIndexListModel)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _dataview.PyDataViewIndexListModel__setCallbackInfo(*args, **kwargs)
+
+_dataview.PyDataViewIndexListModel_swigregister(PyDataViewIndexListModel)
+
+class DataViewVirtualListModel(DataViewModel):
+ """
+ DataViewVirtualListModel is a specialized data model which lets you
+ address an item by its position (row) rather than its `DataViewItem`
+ and as such offers the exact same interface as
+ `DataViewIndexListModel`. The important difference is that under
+ platforms other than OS X, using this model will result in a truely
+ virtual control able to handle millions of items as the control
+ doesn't store any per-item data in memory (a feature not supported by
+ the Carbon API under OS X).
+
+ To implement a custom list-based data model derive a new class from
+ `PyDataViewVirtualListModel` and implement the required methods.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _dataview.delete_DataViewVirtualListModel
+ __del__ = lambda self : None;
+ def GetValueByRow(*args, **kwargs):
+ """
+ GetValueByRow(self, unsigned int row, unsigned int col) -> wxVariant
+
+ Override this method to return the data value to be used for the item
+ at the given row and column.
+ """
+ return _dataview.DataViewVirtualListModel_GetValueByRow(*args, **kwargs)
+
+ def SetValueByRow(*args, **kwargs):
+ """
+ SetValueByRow(self, wxVariant variant, unsigned int row, unsigned int col) -> bool
+
+ This is called in order to set a value in the data model.
+ """
+ return _dataview.DataViewVirtualListModel_SetValueByRow(*args, **kwargs)
+
+ def GetAttrByRow(*args, **kwargs):
+ """
+ GetAttrByRow(self, unsigned int row, unsigned int col, DataViewItemAttr attr) -> bool
+
+ Override this to indicate that the item has special font
+ attributes. This only affects the `DataViewTextRenderer` renderer.
+ Return ``False`` if the default attributes should be used.
+ """
+ return _dataview.DataViewVirtualListModel_GetAttrByRow(*args, **kwargs)
+
+ def IsEnabledByRow(*args, **kwargs):
+ """IsEnabledByRow(self, unsigned int row, unsigned int col) -> bool"""
+ return _dataview.DataViewVirtualListModel_IsEnabledByRow(*args, **kwargs)
+
+ def RowPrepended(*args, **kwargs):
+ """
+ RowPrepended(self)
+
+ Call this after a row has been prepended to the model.
+ """
+ return _dataview.DataViewVirtualListModel_RowPrepended(*args, **kwargs)
+
+ def RowInserted(*args, **kwargs):
+ """
+ RowInserted(self, unsigned int before)
+
+ Call this after a row has been inserted at the given position
+ """
+ return _dataview.DataViewVirtualListModel_RowInserted(*args, **kwargs)
+
+ def RowAppended(*args, **kwargs):
+ """
+ RowAppended(self)
+
+ Call this after a row has been appended to the model.
+ """
+ return _dataview.DataViewVirtualListModel_RowAppended(*args, **kwargs)
+
+ def RowDeleted(*args, **kwargs):
+ """
+ RowDeleted(self, unsigned int row)
+
+ Call this after a row has been deleted.
+ """
+ return _dataview.DataViewVirtualListModel_RowDeleted(*args, **kwargs)
+
+ def RowsDeleted(*args, **kwargs):
+ """
+ RowsDeleted(self, wxArrayInt rows)
+
+ Call this after rows have been deleted. The array will internally get
+ copied and sorted in descending order so that the rows with the
+ highest position will be deleted first.
+ """
+ return _dataview.DataViewVirtualListModel_RowsDeleted(*args, **kwargs)
+
+ def RowChanged(*args, **kwargs):
+ """
+ RowChanged(self, unsigned int row)
+
+ Call this after a row has been changed.
+ """
+ return _dataview.DataViewVirtualListModel_RowChanged(*args, **kwargs)
+
+ def RowValueChanged(*args, **kwargs):
+ """
+ RowValueChanged(self, unsigned int row, unsigned int col)
+
+ Call this after a value has been changed.
+ """
+ return _dataview.DataViewVirtualListModel_RowValueChanged(*args, **kwargs)
+
+ def Reset(*args, **kwargs):
+ """
+ Reset(self, unsigned int new_size)
+
+ Call this if the data has to be read again from the model. This is
+ useful after major changes when calling methods like `RowChanged` or
+ `RowDeleted` (possibly thousands of times) doesn't make sense.
+ """
+ return _dataview.DataViewVirtualListModel_Reset(*args, **kwargs)
+
+ def GetRow(*args, **kwargs):
+ """
+ GetRow(self, DataViewItem item) -> unsigned int
+
+ Returns the row position of item.
+ """
+ return _dataview.DataViewVirtualListModel_GetRow(*args, **kwargs)
+
+ def GetCount(*args, **kwargs):
+ """
+ GetCount(self) -> unsigned int
+
+ returns the number of rows
+ """
+ return _dataview.DataViewVirtualListModel_GetCount(*args, **kwargs)
+
+ def GetItem(*args, **kwargs):
+ """
+ GetItem(self, unsigned int row) -> DataViewItem
+
+ Returns the DataViewItem for the item at row.
+ """
+ return _dataview.DataViewVirtualListModel_GetItem(*args, **kwargs)
+
+_dataview.DataViewVirtualListModel_swigregister(DataViewVirtualListModel)
+
+class PyDataViewVirtualListModel(DataViewVirtualListModel):
+ """Proxy of C++ PyDataViewVirtualListModel class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, unsigned int initial_size=0) -> PyDataViewVirtualListModel"""
+ _dataview.PyDataViewVirtualListModel_swiginit(self,_dataview.new_PyDataViewVirtualListModel(*args, **kwargs))
+ PyDataViewVirtualListModel._setCallbackInfo(self, self, PyDataViewVirtualListModel)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _dataview.PyDataViewVirtualListModel__setCallbackInfo(*args, **kwargs)
+
+_dataview.PyDataViewVirtualListModel_swigregister(PyDataViewVirtualListModel)
+
+DATAVIEW_CELL_INERT = _dataview.DATAVIEW_CELL_INERT
+DATAVIEW_CELL_ACTIVATABLE = _dataview.DATAVIEW_CELL_ACTIVATABLE
+DATAVIEW_CELL_EDITABLE = _dataview.DATAVIEW_CELL_EDITABLE
+DATAVIEW_CELL_SELECTED = _dataview.DATAVIEW_CELL_SELECTED
+DATAVIEW_CELL_PRELIT = _dataview.DATAVIEW_CELL_PRELIT
+DATAVIEW_CELL_INSENSITIVE = _dataview.DATAVIEW_CELL_INSENSITIVE
+DATAVIEW_CELL_FOCUSED = _dataview.DATAVIEW_CELL_FOCUSED
+class DataViewRenderer(_core.Object):
+ """
+ This class is used by `DataViewCtrl` to render (or draw) the
+ individual cells. One instance of a renderer class is owned by each
+ `DataViewColumn`. There is a number of ready-to-use renderers
+ provided: `DataViewTextRenderer`,
+ `DataViewIconTextRenderer`, `DataViewToggleRenderer`,
+ `DataViewProgressRenderer`, `DataViewBitmapRenderer`,
+ `DataViewDateRenderer`, `DataViewSpinRenderer`,
+ `DataViewChoiceRenderer`.
+
+ To create your own custom renderer derive a new class from
+ `PyDataViewCustomRenderer`.
+
+ The mode flag controls what actions the cell data
+ allows. ``DATAVIEW_CELL_ACTIVATABLE`` indicates that the user can double
+ click the cell and something will happen (e.g. a window for editing a
+ date will pop up). ``DATAVIEW_CELL_EDITABLE`` indicates that the user
+ can edit the data in-place, i.e. an control will show up after a slow
+ click on the cell. This behaviour is best known from changing the
+ filename in most file managers etc.
+
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _dataview.delete_DataViewRenderer
+ __del__ = lambda self : None;
+ def Validate(*args, **kwargs):
+ """Validate(self, wxVariant value) -> bool"""
+ return _dataview.DataViewRenderer_Validate(*args, **kwargs)
+
+ def SetOwner(*args, **kwargs):
+ """SetOwner(self, DataViewColumn owner)"""
+ return _dataview.DataViewRenderer_SetOwner(*args, **kwargs)
+
+ def GetOwner(*args, **kwargs):
+ """GetOwner(self) -> DataViewColumn"""
+ return _dataview.DataViewRenderer_GetOwner(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, wxVariant value) -> bool"""
+ return _dataview.DataViewRenderer_SetValue(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> wxVariant"""
+ return _dataview.DataViewRenderer_GetValue(*args, **kwargs)
+
+ def SetAttr(*args, **kwargs):
+ """SetAttr(self, DataViewItemAttr attr)"""
+ return _dataview.DataViewRenderer_SetAttr(*args, **kwargs)
+
+ def SetEnabled(*args, **kwargs):
+ """SetEnabled(self, bool enabled)"""
+ return _dataview.DataViewRenderer_SetEnabled(*args, **kwargs)
+
+ def GetVariantType(*args, **kwargs):
+ """GetVariantType(self) -> String"""
+ return _dataview.DataViewRenderer_GetVariantType(*args, **kwargs)
+
+ def PrepareForItem(*args, **kwargs):
+ """PrepareForItem(self, DataViewModel model, DataViewItem item, unsigned int column)"""
+ return _dataview.DataViewRenderer_PrepareForItem(*args, **kwargs)
+
+ def SetMode(*args, **kwargs):
+ """SetMode(self, int mode)"""
+ return _dataview.DataViewRenderer_SetMode(*args, **kwargs)
+
+ def GetMode(*args, **kwargs):
+ """GetMode(self) -> int"""
+ return _dataview.DataViewRenderer_GetMode(*args, **kwargs)
+
+ def SetAlignment(*args, **kwargs):
+ """SetAlignment(self, int align)"""
+ return _dataview.DataViewRenderer_SetAlignment(*args, **kwargs)
+
+ def GetAlignment(*args, **kwargs):
+ """GetAlignment(self) -> int"""
+ return _dataview.DataViewRenderer_GetAlignment(*args, **kwargs)
+
+ def EnableEllipsize(*args, **kwargs):
+ """EnableEllipsize(self, int mode=ELLIPSIZE_MIDDLE)"""
+ return _dataview.DataViewRenderer_EnableEllipsize(*args, **kwargs)
+
+ def DisableEllipsize(*args, **kwargs):
+ """DisableEllipsize(self)"""
+ return _dataview.DataViewRenderer_DisableEllipsize(*args, **kwargs)
+
+ def GetEllipsizeMode(*args, **kwargs):
+ """GetEllipsizeMode(self) -> int"""
+ return _dataview.DataViewRenderer_GetEllipsizeMode(*args, **kwargs)
+
+ def HasEditorCtrl(*args, **kwargs):
+ """HasEditorCtrl(self) -> bool"""
+ return _dataview.DataViewRenderer_HasEditorCtrl(*args, **kwargs)
+
+ def CreateEditorCtrl(*args, **kwargs):
+ """CreateEditorCtrl(self, Window parent, Rect labelRect, wxVariant value) -> Window"""
+ return _dataview.DataViewRenderer_CreateEditorCtrl(*args, **kwargs)
+
+ def GetValueFromEditorCtrl(*args, **kwargs):
+ """GetValueFromEditorCtrl(self, Window editor) -> wxVariant"""
+ return _dataview.DataViewRenderer_GetValueFromEditorCtrl(*args, **kwargs)
+
+ def StartEditing(*args, **kwargs):
+ """StartEditing(self, DataViewItem item, Rect labelRect) -> bool"""
+ return _dataview.DataViewRenderer_StartEditing(*args, **kwargs)
+
+ def CancelEditing(*args, **kwargs):
+ """CancelEditing(self)"""
+ return _dataview.DataViewRenderer_CancelEditing(*args, **kwargs)
+
+ def FinishEditing(*args, **kwargs):
+ """FinishEditing(self) -> bool"""
+ return _dataview.DataViewRenderer_FinishEditing(*args, **kwargs)
+
+ def GetEditorCtrl(*args, **kwargs):
+ """GetEditorCtrl(self) -> Window"""
+ return _dataview.DataViewRenderer_GetEditorCtrl(*args, **kwargs)
+
+ Owner = property(GetOwner,SetOwner)
+ Value = property(GetValue,SetValue)
+ VariantType = property(GetVariantType)
+ Mode = property(GetMode,SetMode)
+ Alignment = property(GetAlignment,SetAlignment)
+ EditorCtrl = property(GetEditorCtrl)
+_dataview.DataViewRenderer_swigregister(DataViewRenderer)
+
+class DataViewTextRenderer(DataViewRenderer):
+ """
+ This class is used for rendering text. It supports in-place editing if
+ desired.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String varianttype="string", int mode=DATAVIEW_CELL_INERT,
+ int align=DVR_DEFAULT_ALIGNMENT) -> DataViewTextRenderer
+
+ This class is used for rendering text. It supports in-place editing if
+ desired.
+ """
+ _dataview.DataViewTextRenderer_swiginit(self,_dataview.new_DataViewTextRenderer(*args, **kwargs))
+_dataview.DataViewTextRenderer_swigregister(DataViewTextRenderer)
+
+class DataViewBitmapRenderer(DataViewRenderer):
+ """DataViewBitmapRenderer"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String varianttype="wxBitmap", int mode=DATAVIEW_CELL_INERT,
+ int align=DVR_DEFAULT_ALIGNMENT) -> DataViewBitmapRenderer
+
+ DataViewBitmapRenderer
+ """
+ _dataview.DataViewBitmapRenderer_swiginit(self,_dataview.new_DataViewBitmapRenderer(*args, **kwargs))
+_dataview.DataViewBitmapRenderer_swigregister(DataViewBitmapRenderer)
+
+class DataViewIconTextRenderer(DataViewRenderer):
+ """
+ The `DataViewIconTextRenderer` class is used to display text with a
+ small icon next to it as it is typically done in a file manager. This
+ class uses the `DataViewIconText` helper class to store its
+ data.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String varianttype="wxDataViewIconText", int mode=DATAVIEW_CELL_INERT,
+ int align=DVR_DEFAULT_ALIGNMENT) -> DataViewIconTextRenderer
+
+ The `DataViewIconTextRenderer` class is used to display text with a
+ small icon next to it as it is typically done in a file manager. This
+ class uses the `DataViewIconText` helper class to store its
+ data.
+ """
+ _dataview.DataViewIconTextRenderer_swiginit(self,_dataview.new_DataViewIconTextRenderer(*args, **kwargs))
+_dataview.DataViewIconTextRenderer_swigregister(DataViewIconTextRenderer)
+
+class DataViewIconText(_core.Object):
+ """
+ DataViewIconText is used to hold the data for columns using the
+ `DataViewIconTextRenderer`
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String text=wxEmptyString, Icon icon=wxNullIcon) -> DataViewIconText
+
+ DataViewIconText is used to hold the data for columns using the
+ `DataViewIconTextRenderer`
+ """
+ _dataview.DataViewIconText_swiginit(self,_dataview.new_DataViewIconText(*args, **kwargs))
+ __swig_destroy__ = _dataview.delete_DataViewIconText
+ __del__ = lambda self : None;
+ def SetText(*args, **kwargs):
+ """SetText(self, String text)"""
+ return _dataview.DataViewIconText_SetText(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self) -> String"""
+ return _dataview.DataViewIconText_GetText(*args, **kwargs)
+
+ def SetIcon(*args, **kwargs):
+ """SetIcon(self, Icon icon)"""
+ return _dataview.DataViewIconText_SetIcon(*args, **kwargs)
+
+ def GetIcon(*args, **kwargs):
+ """GetIcon(self) -> Icon"""
+ return _dataview.DataViewIconText_GetIcon(*args, **kwargs)
+
+_dataview.DataViewIconText_swigregister(DataViewIconText)
+
+class DataViewToggleRenderer(DataViewRenderer):
+ """DataViewToggleRenderer"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String varianttype="bool", int mode=DATAVIEW_CELL_INERT,
+ int align=DVR_DEFAULT_ALIGNMENT) -> DataViewToggleRenderer
+
+ DataViewToggleRenderer
+ """
+ _dataview.DataViewToggleRenderer_swiginit(self,_dataview.new_DataViewToggleRenderer(*args, **kwargs))
+_dataview.DataViewToggleRenderer_swigregister(DataViewToggleRenderer)
+
+class DataViewProgressRenderer(DataViewRenderer):
+ """DataViewProgressRenderer"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=wxEmptyString, String varianttype="long",
+ int mode=DATAVIEW_CELL_INERT, int align=DVR_DEFAULT_ALIGNMENT) -> DataViewProgressRenderer
+
+ DataViewProgressRenderer
+ """
+ _dataview.DataViewProgressRenderer_swiginit(self,_dataview.new_DataViewProgressRenderer(*args, **kwargs))
+_dataview.DataViewProgressRenderer_swigregister(DataViewProgressRenderer)
+
+class DataViewSpinRenderer(DataViewRenderer):
+ """
+ This is a specialized renderer for rendering integer values. It
+ supports modifying the values in-place by using a `wx.SpinCtrl`. The
+ renderer only support integer data items.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int min, int max, int mode=DATAVIEW_CELL_EDITABLE,
+ int alignment=DVR_DEFAULT_ALIGNMENT) -> DataViewSpinRenderer
+
+ This is a specialized renderer for rendering integer values. It
+ supports modifying the values in-place by using a `wx.SpinCtrl`. The
+ renderer only support integer data items.
+ """
+ _dataview.DataViewSpinRenderer_swiginit(self,_dataview.new_DataViewSpinRenderer(*args, **kwargs))
+_dataview.DataViewSpinRenderer_swigregister(DataViewSpinRenderer)
+
+class DataViewCustomRenderer(DataViewRenderer):
+ """See `PyDataViewCustomRenderer`."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetAttr(*args, **kwargs):
+ """GetAttr(self) -> DataViewItemAttr"""
+ return _dataview.DataViewCustomRenderer_GetAttr(*args, **kwargs)
+
+ def GetEnabled(*args, **kwargs):
+ """GetEnabled(self) -> bool"""
+ return _dataview.DataViewCustomRenderer_GetEnabled(*args, **kwargs)
+
+_dataview.DataViewCustomRenderer_swigregister(DataViewCustomRenderer)
+
+class DataViewChoiceRenderer(DataViewCustomRenderer):
+ """Proxy of C++ DataViewChoiceRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, wxArrayString choices, int mode=DATAVIEW_CELL_EDITABLE,
+ int alignment=DVR_DEFAULT_ALIGNMENT) -> DataViewChoiceRenderer
+ """
+ _dataview.DataViewChoiceRenderer_swiginit(self,_dataview.new_DataViewChoiceRenderer(*args, **kwargs))
+ def GetChoice(*args, **kwargs):
+ """GetChoice(self, size_t index) -> String"""
+ return _dataview.DataViewChoiceRenderer_GetChoice(*args, **kwargs)
+
+ def GetChoices(*args, **kwargs):
+ """GetChoices(self) -> wxArrayString"""
+ return _dataview.DataViewChoiceRenderer_GetChoices(*args, **kwargs)
+
+_dataview.DataViewChoiceRenderer_swigregister(DataViewChoiceRenderer)
+
+class DataViewChoiceByIndexRenderer(DataViewChoiceRenderer):
+ """Proxy of C++ DataViewChoiceByIndexRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, wxArrayString choices, int mode=DATAVIEW_CELL_EDITABLE,
+ int alignment=DVR_DEFAULT_ALIGNMENT) -> DataViewChoiceByIndexRenderer
+ """
+ _dataview.DataViewChoiceByIndexRenderer_swiginit(self,_dataview.new_DataViewChoiceByIndexRenderer(*args, **kwargs))
+_dataview.DataViewChoiceByIndexRenderer_swigregister(DataViewChoiceByIndexRenderer)
+
+class DataViewDateRenderer(DataViewRenderer):
+ """Proxy of C++ DataViewDateRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String varianttype="datetime", int mode=DATAVIEW_CELL_ACTIVATABLE,
+ int align=DVR_DEFAULT_ALIGNMENT) -> DataViewDateRenderer
+ """
+ _dataview.DataViewDateRenderer_swiginit(self,_dataview.new_DataViewDateRenderer(*args, **kwargs))
+_dataview.DataViewDateRenderer_swigregister(DataViewDateRenderer)
+
+class PyDataViewCustomRenderer(DataViewCustomRenderer):
+ """Proxy of C++ PyDataViewCustomRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String varianttype="string", int mode=DATAVIEW_CELL_INERT,
+ int align=DVR_DEFAULT_ALIGNMENT) -> PyDataViewCustomRenderer
+ """
+ _dataview.PyDataViewCustomRenderer_swiginit(self,_dataview.new_PyDataViewCustomRenderer(*args, **kwargs))
+ PyDataViewCustomRenderer._setCallbackInfo(self, self, PyDataViewCustomRenderer)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _dataview.PyDataViewCustomRenderer__setCallbackInfo(*args, **kwargs)
+
+ def RenderText(*args, **kwargs):
+ """
+ RenderText(self, String text, int xoffset, Rect cell, DC dc, int state)
+
+ This method should be called from within your `Render` override
+ whenever you need to render simple text. This will help ensure that the
+ correct colour, font and vertical alignment will be chosen so the text
+ will look the same as text drawn by native renderers.
+ """
+ return _dataview.PyDataViewCustomRenderer_RenderText(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """
+ GetSize(self) -> Size
+
+ Returns the size required to show content. This must be overridden in
+ derived classes.
+ """
+ return _dataview.PyDataViewCustomRenderer_GetSize(*args, **kwargs)
+
+ def Render(*args, **kwargs):
+ """
+ Render(self, Rect cell, DC dc, int state) -> bool
+
+ Override this to render the cell. Before this is called, `SetValue`
+ was called so that this instance knows what to render. This must be
+ overridden in derived classes.
+ """
+ return _dataview.PyDataViewCustomRenderer_Render(*args, **kwargs)
+
+ def Activate(*args, **kwargs):
+ """
+ Activate(self, Rect cell, DataViewModel model, DataViewItem item,
+ unsigned int col) -> bool
+
+ Override this to react to double clicks or <ENTER>.
+ """
+ return _dataview.PyDataViewCustomRenderer_Activate(*args, **kwargs)
+
+ def LeftClick(*args, **kwargs):
+ """
+ LeftClick(self, Point cursor, Rect cell, DataViewModel model, DataViewItem item,
+ unsigned int col) -> bool
+
+ Overrride this to react to a left click.
+ """
+ return _dataview.PyDataViewCustomRenderer_LeftClick(*args, **kwargs)
+
+ def StartDrag(*args, **kwargs):
+ """
+ StartDrag(self, Point cursor, Rect cell, DataViewModel model, DataViewItem item,
+ unsigned int col) -> bool
+
+ Overrride this to react to the start of a drag operation.
+ """
+ return _dataview.PyDataViewCustomRenderer_StartDrag(*args, **kwargs)
+
+ def GetDC(*args, **kwargs):
+ """GetDC(self) -> DC"""
+ return _dataview.PyDataViewCustomRenderer_GetDC(*args, **kwargs)
+
+ def GetTextExtent(*args, **kwargs):
+ """GetTextExtent(self, String str) -> Size"""
+ return _dataview.PyDataViewCustomRenderer_GetTextExtent(*args, **kwargs)
+
+ def GetView(*args, **kwargs):
+ """GetView(self) -> DataViewCtrl"""
+ return _dataview.PyDataViewCustomRenderer_GetView(*args, **kwargs)
+
+_dataview.PyDataViewCustomRenderer_swigregister(PyDataViewCustomRenderer)
+
+DATAVIEW_COL_RESIZABLE = _dataview.DATAVIEW_COL_RESIZABLE
+DATAVIEW_COL_SORTABLE = _dataview.DATAVIEW_COL_SORTABLE
+DATAVIEW_COL_REORDERABLE = _dataview.DATAVIEW_COL_REORDERABLE
+DATAVIEW_COL_HIDDEN = _dataview.DATAVIEW_COL_HIDDEN
+class DataViewColumn(_core.SettableHeaderColumn):
+ """Proxy of C++ DataViewColumn class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, PyObject title_or_bitmap, DataViewRenderer renderer,
+ unsigned int model_column, int width=80, int align=ALIGN_CENTER,
+ int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ _dataview.DataViewColumn_swiginit(self,_dataview.new_DataViewColumn(*args, **kwargs))
+ def SetOwner(*args, **kwargs):
+ """SetOwner(self, DataViewCtrl owner)"""
+ return _dataview.DataViewColumn_SetOwner(*args, **kwargs)
+
+ def GetModelColumn(*args, **kwargs):
+ """GetModelColumn(self) -> unsigned int"""
+ return _dataview.DataViewColumn_GetModelColumn(*args, **kwargs)
+
+ def GetOwner(*args, **kwargs):
+ """GetOwner(self) -> DataViewCtrl"""
+ return _dataview.DataViewColumn_GetOwner(*args, **kwargs)
+
+ def GetRenderer(*args, **kwargs):
+ """GetRenderer(self) -> DataViewRenderer"""
+ return _dataview.DataViewColumn_GetRenderer(*args, **kwargs)
+
+ ModelColumn = property(GetModelColumn)
+ Owner = property(GetOwner,SetOwner)
+ Renderer = property(GetRenderer)
+_dataview.DataViewColumn_swigregister(DataViewColumn)
+
+DV_SINGLE = _dataview.DV_SINGLE
+DV_MULTIPLE = _dataview.DV_MULTIPLE
+DV_NO_HEADER = _dataview.DV_NO_HEADER
+DV_HORIZ_RULES = _dataview.DV_HORIZ_RULES
+DV_VERT_RULES = _dataview.DV_VERT_RULES
+DV_ROW_LINES = _dataview.DV_ROW_LINES
+DV_VARIABLE_LINE_HEIGHT = _dataview.DV_VARIABLE_LINE_HEIGHT
+class DataViewCtrl(_core.Control):
+ """Proxy of C++ DataViewCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, Validator validator=DefaultValidator,
+ String name=wxDataViewCtrlNameStr) -> DataViewCtrl
+ """
+ _dataview.DataViewCtrl_swiginit(self,_dataview.new_DataViewCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, Validator validator=DefaultValidator,
+ String name=wxDataViewCtrlNameStr) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _dataview.DataViewCtrl_Create(*args, **kwargs)
+
+ def AssociateModel(*args, **kwargs):
+ """AssociateModel(self, DataViewModel model) -> bool"""
+ return _dataview.DataViewCtrl_AssociateModel(*args, **kwargs)
+
+ def GetModel(*args, **kwargs):
+ """GetModel(self) -> DataViewModel"""
+ return _dataview.DataViewCtrl_GetModel(*args, **kwargs)
+
+ def PrependTextColumn(*args, **kwargs):
+ """
+ PrependTextColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_INERT, int width=-1,
+ int align=ALIGN_NOT, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_PrependTextColumn(*args, **kwargs)
+
+ def PrependIconTextColumn(*args, **kwargs):
+ """
+ PrependIconTextColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_INERT, int width=-1,
+ int align=ALIGN_NOT, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_PrependIconTextColumn(*args, **kwargs)
+
+ def PrependToggleColumn(*args, **kwargs):
+ """
+ PrependToggleColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_INERT, int width=DVC_TOGGLE_DEFAULT_WIDTH,
+ int align=ALIGN_CENTER,
+ int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_PrependToggleColumn(*args, **kwargs)
+
+ def PrependProgressColumn(*args, **kwargs):
+ """
+ PrependProgressColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_INERT, int width=DVC_DEFAULT_WIDTH,
+ int align=ALIGN_CENTER, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_PrependProgressColumn(*args, **kwargs)
+
+ def PrependDateColumn(*args, **kwargs):
+ """
+ PrependDateColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_ACTIVATABLE, int width=-1,
+ int align=ALIGN_NOT, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_PrependDateColumn(*args, **kwargs)
+
+ def PrependBitmapColumn(*args, **kwargs):
+ """
+ PrependBitmapColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_INERT, int width=-1,
+ int align=ALIGN_CENTER, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_PrependBitmapColumn(*args, **kwargs)
+
+ def AppendTextColumn(*args, **kwargs):
+ """
+ AppendTextColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_INERT, int width=-1,
+ int align=ALIGN_NOT, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_AppendTextColumn(*args, **kwargs)
+
+ def AppendIconTextColumn(*args, **kwargs):
+ """
+ AppendIconTextColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_INERT, int width=-1,
+ int align=ALIGN_NOT, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_AppendIconTextColumn(*args, **kwargs)
+
+ def AppendToggleColumn(*args, **kwargs):
+ """
+ AppendToggleColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_INERT, int width=DVC_TOGGLE_DEFAULT_WIDTH,
+ int align=ALIGN_CENTER,
+ int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_AppendToggleColumn(*args, **kwargs)
+
+ def AppendProgressColumn(*args, **kwargs):
+ """
+ AppendProgressColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_INERT, int width=DVC_DEFAULT_WIDTH,
+ int align=ALIGN_CENTER, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_AppendProgressColumn(*args, **kwargs)
+
+ def AppendDateColumn(*args, **kwargs):
+ """
+ AppendDateColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_ACTIVATABLE, int width=-1,
+ int align=ALIGN_NOT, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_AppendDateColumn(*args, **kwargs)
+
+ def AppendBitmapColumn(*args, **kwargs):
+ """
+ AppendBitmapColumn(self, PyObject label_or_bitmap, unsigned int model_column,
+ int mode=DATAVIEW_CELL_INERT, int width=-1,
+ int align=ALIGN_CENTER, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewCtrl_AppendBitmapColumn(*args, **kwargs)
+
+ def PrependColumn(*args, **kwargs):
+ """PrependColumn(self, DataViewColumn col) -> bool"""
+ return _dataview.DataViewCtrl_PrependColumn(*args, **kwargs)
+
+ def InsertColumn(*args, **kwargs):
+ """InsertColumn(self, unsigned int pos, DataViewColumn col) -> bool"""
+ return _dataview.DataViewCtrl_InsertColumn(*args, **kwargs)
+
+ def AppendColumn(*args, **kwargs):
+ """AppendColumn(self, DataViewColumn col) -> bool"""
+ return _dataview.DataViewCtrl_AppendColumn(*args, **kwargs)
+
+ def GetColumnCount(*args, **kwargs):
+ """GetColumnCount(self) -> unsigned int"""
+ return _dataview.DataViewCtrl_GetColumnCount(*args, **kwargs)
+
+ def GetColumn(*args, **kwargs):
+ """GetColumn(self, unsigned int pos) -> DataViewColumn"""
+ return _dataview.DataViewCtrl_GetColumn(*args, **kwargs)
+
+ def GetColumns(self):
+ """Returns a list of column objects."""
+ return [self.GetColumn(i) for i in range(self.GetColumnCount())]
+
+ def GetColumnPosition(*args, **kwargs):
+ """GetColumnPosition(self, DataViewColumn column) -> int"""
+ return _dataview.DataViewCtrl_GetColumnPosition(*args, **kwargs)
+
+ def DeleteColumn(*args, **kwargs):
+ """DeleteColumn(self, DataViewColumn column) -> bool"""
+ return _dataview.DataViewCtrl_DeleteColumn(*args, **kwargs)
+
+ def ClearColumns(*args, **kwargs):
+ """ClearColumns(self) -> bool"""
+ return _dataview.DataViewCtrl_ClearColumns(*args, **kwargs)
+
+ def SetExpanderColumn(*args, **kwargs):
+ """SetExpanderColumn(self, DataViewColumn col)"""
+ return _dataview.DataViewCtrl_SetExpanderColumn(*args, **kwargs)
+
+ def GetExpanderColumn(*args, **kwargs):
+ """GetExpanderColumn(self) -> DataViewColumn"""
+ return _dataview.DataViewCtrl_GetExpanderColumn(*args, **kwargs)
+
+ def GetSortingColumn(*args, **kwargs):
+ """GetSortingColumn(self) -> DataViewColumn"""
+ return _dataview.DataViewCtrl_GetSortingColumn(*args, **kwargs)
+
+ def SetIndent(*args, **kwargs):
+ """SetIndent(self, int indent)"""
+ return _dataview.DataViewCtrl_SetIndent(*args, **kwargs)
+
+ def GetIndent(*args, **kwargs):
+ """GetIndent(self) -> int"""
+ return _dataview.DataViewCtrl_GetIndent(*args, **kwargs)
+
+ def GetCurrentItem(*args, **kwargs):
+ """GetCurrentItem(self) -> DataViewItem"""
+ return _dataview.DataViewCtrl_GetCurrentItem(*args, **kwargs)
+
+ def SetCurrentItem(*args, **kwargs):
+ """SetCurrentItem(self, DataViewItem item)"""
+ return _dataview.DataViewCtrl_SetCurrentItem(*args, **kwargs)
+
+ def GetCurrentColumn(*args, **kwargs):
+ """GetCurrentColumn(self) -> DataViewColumn"""
+ return _dataview.DataViewCtrl_GetCurrentColumn(*args, **kwargs)
+
+ def GetSelectedItemsCount(*args, **kwargs):
+ """GetSelectedItemsCount(self) -> int"""
+ return _dataview.DataViewCtrl_GetSelectedItemsCount(*args, **kwargs)
+
+ def HasSelection(*args, **kwargs):
+ """HasSelection(self) -> bool"""
+ return _dataview.DataViewCtrl_HasSelection(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> DataViewItem"""
+ return _dataview.DataViewCtrl_GetSelection(*args, **kwargs)
+
+ def GetSelections(*args, **kwargs):
+ """GetSelections(self) -> DataViewItemArray"""
+ return _dataview.DataViewCtrl_GetSelections(*args, **kwargs)
+
+ def SetSelections(*args, **kwargs):
+ """SetSelections(self, DataViewItemArray sel)"""
+ return _dataview.DataViewCtrl_SetSelections(*args, **kwargs)
+
+ def Select(*args, **kwargs):
+ """Select(self, DataViewItem item)"""
+ return _dataview.DataViewCtrl_Select(*args, **kwargs)
+
+ def Unselect(*args, **kwargs):
+ """Unselect(self, DataViewItem item)"""
+ return _dataview.DataViewCtrl_Unselect(*args, **kwargs)
+
+ def IsSelected(*args, **kwargs):
+ """IsSelected(self, DataViewItem item) -> bool"""
+ return _dataview.DataViewCtrl_IsSelected(*args, **kwargs)
+
+ def SelectAll(*args, **kwargs):
+ """SelectAll(self)"""
+ return _dataview.DataViewCtrl_SelectAll(*args, **kwargs)
+
+ def UnselectAll(*args, **kwargs):
+ """UnselectAll(self)"""
+ return _dataview.DataViewCtrl_UnselectAll(*args, **kwargs)
+
+ def Expand(*args, **kwargs):
+ """Expand(self, DataViewItem item)"""
+ return _dataview.DataViewCtrl_Expand(*args, **kwargs)
+
+ def ExpandAncestors(*args, **kwargs):
+ """ExpandAncestors(self, DataViewItem item)"""
+ return _dataview.DataViewCtrl_ExpandAncestors(*args, **kwargs)
+
+ def Collapse(*args, **kwargs):
+ """Collapse(self, DataViewItem item)"""
+ return _dataview.DataViewCtrl_Collapse(*args, **kwargs)
+
+ def IsExpanded(*args, **kwargs):
+ """IsExpanded(self, DataViewItem item) -> bool"""
+ return _dataview.DataViewCtrl_IsExpanded(*args, **kwargs)
+
+ def EnsureVisible(*args, **kwargs):
+ """EnsureVisible(self, DataViewItem item, DataViewColumn column=None)"""
+ return _dataview.DataViewCtrl_EnsureVisible(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(point) -> (item, col)
+
+ Test where the given (in client coords) point lies
+ """
+ return _dataview.DataViewCtrl_HitTest(*args, **kwargs)
+
+ def GetItemRect(*args, **kwargs):
+ """GetItemRect(self, DataViewItem item, DataViewColumn column=None) -> Rect"""
+ return _dataview.DataViewCtrl_GetItemRect(*args, **kwargs)
+
+ def SetRowHeight(*args, **kwargs):
+ """SetRowHeight(self, int rowHeight) -> bool"""
+ return _dataview.DataViewCtrl_SetRowHeight(*args, **kwargs)
+
+ def EditItem(*args, **kwargs):
+ """EditItem(self, DataViewItem item, DataViewColumn column)"""
+ return _dataview.DataViewCtrl_EditItem(*args, **kwargs)
+
+ def EnableDragSource(*args, **kwargs):
+ """EnableDragSource(self, wxDataFormat format) -> bool"""
+ return _dataview.DataViewCtrl_EnableDragSource(*args, **kwargs)
+
+ def EnableDropTarget(*args, **kwargs):
+ """EnableDropTarget(self, wxDataFormat format) -> bool"""
+ return _dataview.DataViewCtrl_EnableDropTarget(*args, **kwargs)
+
+ Model = property(GetModel,AssociateModel)
+ ColumnCount = property(GetColumnCount)
+ Columns = property(GetColumns)
+ ExpanderColumn = property(GetExpanderColumn,SetExpanderColumn)
+ SortingColumn = property(GetSortingColumn)
+ Indent = property(GetIndent,SetIndent)
+ Selection = property(GetSelection)
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _dataview.DataViewCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+_dataview.DataViewCtrl_swigregister(DataViewCtrl)
+
+def PreDataViewCtrl(*args, **kwargs):
+ """PreDataViewCtrl() -> DataViewCtrl"""
+ val = _dataview.new_PreDataViewCtrl(*args, **kwargs)
+ return val
+
+def DataViewCtrl_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ DataViewCtrl_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _dataview.DataViewCtrl_GetClassDefaultAttributes(*args, **kwargs)
+
+class DataViewEvent(_core.NotifyEvent):
+ """Proxy of C++ DataViewEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=wxEVT_NULL, int winid=0) -> DataViewEvent"""
+ _dataview.DataViewEvent_swiginit(self,_dataview.new_DataViewEvent(*args, **kwargs))
+ def GetItem(*args, **kwargs):
+ """GetItem(self) -> DataViewItem"""
+ return _dataview.DataViewEvent_GetItem(*args, **kwargs)
+
+ def SetItem(*args, **kwargs):
+ """SetItem(self, DataViewItem item)"""
+ return _dataview.DataViewEvent_SetItem(*args, **kwargs)
+
+ def GetColumn(*args, **kwargs):
+ """GetColumn(self) -> int"""
+ return _dataview.DataViewEvent_GetColumn(*args, **kwargs)
+
+ def SetColumn(*args, **kwargs):
+ """SetColumn(self, int col)"""
+ return _dataview.DataViewEvent_SetColumn(*args, **kwargs)
+
+ def GetModel(*args, **kwargs):
+ """GetModel(self) -> DataViewModel"""
+ return _dataview.DataViewEvent_GetModel(*args, **kwargs)
+
+ def SetModel(*args, **kwargs):
+ """SetModel(self, DataViewModel model)"""
+ return _dataview.DataViewEvent_SetModel(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> wxVariant"""
+ return _dataview.DataViewEvent_GetValue(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, wxVariant value)"""
+ return _dataview.DataViewEvent_SetValue(*args, **kwargs)
+
+ def IsEditCancelled(*args, **kwargs):
+ """IsEditCancelled(self) -> bool"""
+ return _dataview.DataViewEvent_IsEditCancelled(*args, **kwargs)
+
+ def SetEditCanceled(*args, **kwargs):
+ """SetEditCanceled(self, bool editCancelled)"""
+ return _dataview.DataViewEvent_SetEditCanceled(*args, **kwargs)
+
+ def SetDataViewColumn(*args, **kwargs):
+ """SetDataViewColumn(self, DataViewColumn col)"""
+ return _dataview.DataViewEvent_SetDataViewColumn(*args, **kwargs)
+
+ def GetDataViewColumn(*args, **kwargs):
+ """GetDataViewColumn(self) -> DataViewColumn"""
+ return _dataview.DataViewEvent_GetDataViewColumn(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point"""
+ return _dataview.DataViewEvent_GetPosition(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, int x, int y)"""
+ return _dataview.DataViewEvent_SetPosition(*args, **kwargs)
+
+ def GetCacheFrom(*args, **kwargs):
+ """GetCacheFrom(self) -> int"""
+ return _dataview.DataViewEvent_GetCacheFrom(*args, **kwargs)
+
+ def GetCacheTo(*args, **kwargs):
+ """GetCacheTo(self) -> int"""
+ return _dataview.DataViewEvent_GetCacheTo(*args, **kwargs)
+
+ def SetCache(*args, **kwargs):
+ """SetCache(self, int from, int to)"""
+ return _dataview.DataViewEvent_SetCache(*args, **kwargs)
+
+ def SetDataObject(*args, **kwargs):
+ """SetDataObject(self, wxDataObject obj)"""
+ return _dataview.DataViewEvent_SetDataObject(*args, **kwargs)
+
+ def GetDataObject(*args, **kwargs):
+ """GetDataObject(self) -> wxDataObject"""
+ return _dataview.DataViewEvent_GetDataObject(*args, **kwargs)
+
+ def SetDataFormat(*args, **kwargs):
+ """SetDataFormat(self, wxDataFormat format)"""
+ return _dataview.DataViewEvent_SetDataFormat(*args, **kwargs)
+
+ def GetDataFormat(*args, **kwargs):
+ """GetDataFormat(self) -> wxDataFormat"""
+ return _dataview.DataViewEvent_GetDataFormat(*args, **kwargs)
+
+ def SetDataSize(*args, **kwargs):
+ """SetDataSize(self, size_t size)"""
+ return _dataview.DataViewEvent_SetDataSize(*args, **kwargs)
+
+ def GetDataSize(*args, **kwargs):
+ """GetDataSize(self) -> size_t"""
+ return _dataview.DataViewEvent_GetDataSize(*args, **kwargs)
+
+ def SetDataBuffer(*args, **kwargs):
+ """SetDataBuffer(self, void buf)"""
+ return _dataview.DataViewEvent_SetDataBuffer(*args, **kwargs)
+
+ def GetDataBuffer(*args, **kwargs):
+ """GetDataBuffer(self) -> void"""
+ return _dataview.DataViewEvent_GetDataBuffer(*args, **kwargs)
+
+ def SetDragFlags(*args, **kwargs):
+ """SetDragFlags(self, int flags)"""
+ return _dataview.DataViewEvent_SetDragFlags(*args, **kwargs)
+
+ def GetDragFlags(*args, **kwargs):
+ """GetDragFlags(self) -> int"""
+ return _dataview.DataViewEvent_GetDragFlags(*args, **kwargs)
+
+ Column = property(GetColumn,SetColumn)
+ Model = property(GetModel,SetModel)
+ Value = property(GetValue,SetValue)
+ DataViewColumn = property(GetDataViewColumn,SetDataViewColumn)
+ Position = property(GetPosition,SetPosition)
+ DataObject = property(GetDataObject,SetDataObject)
+ DataFormat = property(GetDataFormat,SetDataFormat)
+_dataview.DataViewEvent_swigregister(DataViewEvent)
+
+wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED = _dataview.wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED
+wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
+wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED
+wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED
+wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING
+wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING
+wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING
+wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED
+wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE
+wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED
+wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU
+wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK = _dataview.wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
+wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK = _dataview.wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
+wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED = _dataview.wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED
+wxEVT_COMMAND_DATAVIEW_COLUMN_REORDERED = _dataview.wxEVT_COMMAND_DATAVIEW_COLUMN_REORDERED
+wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG
+wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE
+wxEVT_COMMAND_DATAVIEW_ITEM_DROP = _dataview.wxEVT_COMMAND_DATAVIEW_ITEM_DROP
+wxEVT_COMMAND_DATAVIEW_CACHE_HINT = _dataview.wxEVT_COMMAND_DATAVIEW_CACHE_HINT
+EVT_DATAVIEW_SELECTION_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, 1)
+EVT_DATAVIEW_ITEM_ACTIVATED = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, 1)
+EVT_DATAVIEW_ITEM_COLLAPSED = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, 1)
+EVT_DATAVIEW_ITEM_EXPANDED = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, 1)
+EVT_DATAVIEW_ITEM_COLLAPSING = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, 1)
+EVT_DATAVIEW_ITEM_EXPANDING = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, 1)
+EVT_DATAVIEW_ITEM_START_EDITING = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING, 1)
+EVT_DATAVIEW_ITEM_EDITING_STARTED = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, 1)
+EVT_DATAVIEW_ITEM_EDITING_DONE = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, 1)
+EVT_DATAVIEW_ITEM_VALUE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, 1)
+EVT_DATAVIEW_ITEM_CONTEXT_MENU = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, 1)
+EVT_DATAVIEW_COLUMN_HEADER_CLICK = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, 1)
+EVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, 1)
+EVT_DATAVIEW_COLUMN_SORTED = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, 1)
+EVT_DATAVIEW_COLUMN_REORDERED = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_COLUMN_REORDERED, 1)
+EVT_DATAVIEW_ITEM_BEGIN_DRAG = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, 1)
+EVT_DATAVIEW_ITEM_DROP_POSSIBLE = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, 1)
+EVT_DATAVIEW_ITEM_DROP = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, 1)
+EVT_DATAVIEW_CACHE_HINT = wx.PyEventBinder( wxEVT_COMMAND_DATAVIEW_CACHE_HINT, 1 )
+
+
+class DataViewListStore(DataViewIndexListModel):
+ """Proxy of C++ DataViewListStore class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> DataViewListStore"""
+ _dataview.DataViewListStore_swiginit(self,_dataview.new_DataViewListStore(*args, **kwargs))
+_dataview.DataViewListStore_swigregister(DataViewListStore)
+
+class DataViewListCtrl(DataViewCtrl):
+ """Proxy of C++ DataViewListCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=DV_ROW_LINES,
+ Validator validator=DefaultValidator) -> DataViewListCtrl
+ """
+ _dataview.DataViewListCtrl_swiginit(self,_dataview.new_DataViewListCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=DV_ROW_LINES,
+ Validator validator=DefaultValidator) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _dataview.DataViewListCtrl_Create(*args, **kwargs)
+
+ def GetStore(*args, **kwargs):
+ """GetStore(self) -> DataViewListStore"""
+ return _dataview.DataViewListCtrl_GetStore(*args, **kwargs)
+
+ def ItemToRow(*args, **kwargs):
+ """ItemToRow(self, DataViewItem item) -> int"""
+ return _dataview.DataViewListCtrl_ItemToRow(*args, **kwargs)
+
+ def RowToItem(*args, **kwargs):
+ """RowToItem(self, int row) -> DataViewItem"""
+ return _dataview.DataViewListCtrl_RowToItem(*args, **kwargs)
+
+ def GetSelectedRow(*args, **kwargs):
+ """GetSelectedRow(self) -> int"""
+ return _dataview.DataViewListCtrl_GetSelectedRow(*args, **kwargs)
+
+ def SelectRow(*args, **kwargs):
+ """SelectRow(self, unsigned int row)"""
+ return _dataview.DataViewListCtrl_SelectRow(*args, **kwargs)
+
+ def UnselectRow(*args, **kwargs):
+ """UnselectRow(self, unsigned int row)"""
+ return _dataview.DataViewListCtrl_UnselectRow(*args, **kwargs)
+
+ def IsRowSelected(*args, **kwargs):
+ """IsRowSelected(self, unsigned int row) -> bool"""
+ return _dataview.DataViewListCtrl_IsRowSelected(*args, **kwargs)
+
+ def AppendColumn(*args, **kwargs):
+ """AppendColumn(self, DataViewColumn column, String varianttype="string") -> bool"""
+ return _dataview.DataViewListCtrl_AppendColumn(*args, **kwargs)
+
+ def PrependColumn(*args, **kwargs):
+ """PrependColumn(self, DataViewColumn column, String varianttype="string") -> bool"""
+ return _dataview.DataViewListCtrl_PrependColumn(*args, **kwargs)
+
+ def InsertColumn(*args, **kwargs):
+ """InsertColumn(self, unsigned int pos, DataViewColumn column, String varianttype="string") -> bool"""
+ return _dataview.DataViewListCtrl_InsertColumn(*args, **kwargs)
+
+ def AppendTextColumn(*args, **kwargs):
+ """
+ AppendTextColumn(self, String label, int mode=DATAVIEW_CELL_INERT, int width=-1,
+ int align=ALIGN_LEFT, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewListCtrl_AppendTextColumn(*args, **kwargs)
+
+ def AppendToggleColumn(*args, **kwargs):
+ """
+ AppendToggleColumn(self, String label, int mode=DATAVIEW_CELL_ACTIVATABLE, int width=-1,
+ int align=ALIGN_LEFT, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewListCtrl_AppendToggleColumn(*args, **kwargs)
+
+ def AppendProgressColumn(*args, **kwargs):
+ """
+ AppendProgressColumn(self, String label, int mode=DATAVIEW_CELL_INERT, int width=-1,
+ int align=ALIGN_LEFT, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewListCtrl_AppendProgressColumn(*args, **kwargs)
+
+ def AppendIconTextColumn(*args, **kwargs):
+ """
+ AppendIconTextColumn(self, String label, int mode=DATAVIEW_CELL_INERT, int width=-1,
+ int align=ALIGN_LEFT, int flags=DATAVIEW_COL_RESIZABLE) -> DataViewColumn
+ """
+ return _dataview.DataViewListCtrl_AppendIconTextColumn(*args, **kwargs)
+
+ def AppendItem(*args, **kwargs):
+ """AppendItem(self, wxVariantVector values, UIntPtr data=None)"""
+ return _dataview.DataViewListCtrl_AppendItem(*args, **kwargs)
+
+ def PrependItem(*args, **kwargs):
+ """PrependItem(self, wxVariantVector values, UIntPtr data=None)"""
+ return _dataview.DataViewListCtrl_PrependItem(*args, **kwargs)
+
+ def InsertItem(*args, **kwargs):
+ """InsertItem(self, unsigned int row, wxVariantVector values, UIntPtr data=None)"""
+ return _dataview.DataViewListCtrl_InsertItem(*args, **kwargs)
+
+ def DeleteItem(*args, **kwargs):
+ """DeleteItem(self, unsigned int row)"""
+ return _dataview.DataViewListCtrl_DeleteItem(*args, **kwargs)
+
+ def DeleteAllItems(*args, **kwargs):
+ """DeleteAllItems(self)"""
+ return _dataview.DataViewListCtrl_DeleteAllItems(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, wxVariant value, unsigned int row, unsigned int col)"""
+ return _dataview.DataViewListCtrl_SetValue(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self, unsigned int row, unsigned int col) -> wxVariant"""
+ return _dataview.DataViewListCtrl_GetValue(*args, **kwargs)
+
+ def SetTextValue(*args, **kwargs):
+ """SetTextValue(self, String value, unsigned int row, unsigned int col)"""
+ return _dataview.DataViewListCtrl_SetTextValue(*args, **kwargs)
+
+ def GetTextValue(*args, **kwargs):
+ """GetTextValue(self, unsigned int row, unsigned int col) -> String"""
+ return _dataview.DataViewListCtrl_GetTextValue(*args, **kwargs)
+
+ def SetToggleValue(*args, **kwargs):
+ """SetToggleValue(self, bool value, unsigned int row, unsigned int col)"""
+ return _dataview.DataViewListCtrl_SetToggleValue(*args, **kwargs)
+
+ def GetToggleValue(*args, **kwargs):
+ """GetToggleValue(self, unsigned int row, unsigned int col) -> bool"""
+ return _dataview.DataViewListCtrl_GetToggleValue(*args, **kwargs)
+
+ def SetItemData(*args, **kwargs):
+ """SetItemData(self, DataViewItem item, UIntPtr data)"""
+ return _dataview.DataViewListCtrl_SetItemData(*args, **kwargs)
+
+ def GetItemData(*args, **kwargs):
+ """GetItemData(self, DataViewItem item) -> UIntPtr"""
+ return _dataview.DataViewListCtrl_GetItemData(*args, **kwargs)
+
+_dataview.DataViewListCtrl_swigregister(DataViewListCtrl)
+
+def PreDataViewListCtrl(*args, **kwargs):
+ """PreDataViewListCtrl() -> DataViewListCtrl"""
+ val = _dataview.new_PreDataViewListCtrl(*args, **kwargs)
+ return val
+
+class DataViewTreeStoreNode(object):
+ """Proxy of C++ DataViewTreeStoreNode class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, DataViewTreeStoreNode parent, String text, Icon icon=wxNullIcon,
+ wxClientData data=None) -> DataViewTreeStoreNode
+ """
+ _dataview.DataViewTreeStoreNode_swiginit(self,_dataview.new_DataViewTreeStoreNode(*args, **kwargs))
+ __swig_destroy__ = _dataview.delete_DataViewTreeStoreNode
+ __del__ = lambda self : None;
+ def SetText(*args, **kwargs):
+ """SetText(self, String text)"""
+ return _dataview.DataViewTreeStoreNode_SetText(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self) -> String"""
+ return _dataview.DataViewTreeStoreNode_GetText(*args, **kwargs)
+
+ def SetIcon(*args, **kwargs):
+ """SetIcon(self, Icon icon)"""
+ return _dataview.DataViewTreeStoreNode_SetIcon(*args, **kwargs)
+
+ def GetIcon(*args, **kwargs):
+ """GetIcon(self) -> Icon"""
+ return _dataview.DataViewTreeStoreNode_GetIcon(*args, **kwargs)
+
+ def SetData(*args, **kwargs):
+ """SetData(self, wxClientData data)"""
+ return _dataview.DataViewTreeStoreNode_SetData(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """GetData(self) -> wxClientData"""
+ return _dataview.DataViewTreeStoreNode_GetData(*args, **kwargs)
+
+ def GetItem(*args, **kwargs):
+ """GetItem(self) -> DataViewItem"""
+ return _dataview.DataViewTreeStoreNode_GetItem(*args, **kwargs)
+
+ def IsContainer(*args, **kwargs):
+ """IsContainer(self) -> bool"""
+ return _dataview.DataViewTreeStoreNode_IsContainer(*args, **kwargs)
+
+ def GetParent(*args, **kwargs):
+ """GetParent(self) -> DataViewTreeStoreNode"""
+ return _dataview.DataViewTreeStoreNode_GetParent(*args, **kwargs)
+
+_dataview.DataViewTreeStoreNode_swigregister(DataViewTreeStoreNode)
+
+class DataViewTreeStoreNodeList_iterator(object):
+ """This class serves as an iterator for a wxDataViewTreeStoreNodeList object."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _dataview.delete_DataViewTreeStoreNodeList_iterator
+ __del__ = lambda self : None;
+ def next(*args, **kwargs):
+ """next(self) -> DataViewTreeStoreNode"""
+ return _dataview.DataViewTreeStoreNodeList_iterator_next(*args, **kwargs)
+
+_dataview.DataViewTreeStoreNodeList_iterator_swigregister(DataViewTreeStoreNodeList_iterator)
+
+class DataViewTreeStoreNodeList(object):
+ """
+ This class wraps a wxList-based class and gives it a Python
+ sequence-like interface. Sequence operations supported are length,
+ index access and iteration.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _dataview.delete_DataViewTreeStoreNodeList
+ __del__ = lambda self : None;
+ def __len__(*args, **kwargs):
+ """__len__(self) -> size_t"""
+ return _dataview.DataViewTreeStoreNodeList___len__(*args, **kwargs)
+
+ def __getitem__(*args, **kwargs):
+ """__getitem__(self, size_t index) -> DataViewTreeStoreNode"""
+ return _dataview.DataViewTreeStoreNodeList___getitem__(*args, **kwargs)
+
+ def __contains__(*args, **kwargs):
+ """__contains__(self, DataViewTreeStoreNode obj) -> bool"""
+ return _dataview.DataViewTreeStoreNodeList___contains__(*args, **kwargs)
+
+ def __iter__(*args, **kwargs):
+ """__iter__(self) -> DataViewTreeStoreNodeList_iterator"""
+ return _dataview.DataViewTreeStoreNodeList___iter__(*args, **kwargs)
+
+ def index(*args, **kwargs):
+ """index(self, DataViewTreeStoreNode obj) -> int"""
+ return _dataview.DataViewTreeStoreNodeList_index(*args, **kwargs)
+
+ def __repr__(self):
+ return "wxDataViewTreeStoreNodeList: " + repr(list(self))
+
+_dataview.DataViewTreeStoreNodeList_swigregister(DataViewTreeStoreNodeList)
+
+class DataViewTreeStoreContainerNode(DataViewTreeStoreNode):
+ """Proxy of C++ DataViewTreeStoreContainerNode class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, DataViewTreeStoreNode parent, String text, Icon icon=wxNullIcon,
+ Icon expanded=wxNullIcon, wxClientData data=None) -> DataViewTreeStoreContainerNode
+ """
+ _dataview.DataViewTreeStoreContainerNode_swiginit(self,_dataview.new_DataViewTreeStoreContainerNode(*args, **kwargs))
+ __swig_destroy__ = _dataview.delete_DataViewTreeStoreContainerNode
+ __del__ = lambda self : None;
+ def GetChildren(*args):
+ """
+ GetChildren(self) -> DataViewTreeStoreNodeList
+ GetChildren(self) -> DataViewTreeStoreNodeList
+ """
+ return _dataview.DataViewTreeStoreContainerNode_GetChildren(*args)
+
+ def SetExpandedIcon(*args, **kwargs):
+ """SetExpandedIcon(self, Icon icon)"""
+ return _dataview.DataViewTreeStoreContainerNode_SetExpandedIcon(*args, **kwargs)
+
+ def GetExpandedIcon(*args, **kwargs):
+ """GetExpandedIcon(self) -> Icon"""
+ return _dataview.DataViewTreeStoreContainerNode_GetExpandedIcon(*args, **kwargs)
+
+ def SetExpanded(*args, **kwargs):
+ """SetExpanded(self, bool expanded=True)"""
+ return _dataview.DataViewTreeStoreContainerNode_SetExpanded(*args, **kwargs)
+
+ def IsExpanded(*args, **kwargs):
+ """IsExpanded(self) -> bool"""
+ return _dataview.DataViewTreeStoreContainerNode_IsExpanded(*args, **kwargs)
+
+_dataview.DataViewTreeStoreContainerNode_swigregister(DataViewTreeStoreContainerNode)
+
+class DataViewTreeStore(DataViewModel):
+ """Proxy of C++ DataViewTreeStore class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> DataViewTreeStore"""
+ _dataview.DataViewTreeStore_swiginit(self,_dataview.new_DataViewTreeStore(*args, **kwargs))
+ __swig_destroy__ = _dataview.delete_DataViewTreeStore
+ __del__ = lambda self : None;
+ def AppendItem(*args, **kwargs):
+ """
+ AppendItem(self, DataViewItem parent, String text, Icon icon=wxNullIcon,
+ wxClientData data=None) -> DataViewItem
+ """
+ return _dataview.DataViewTreeStore_AppendItem(*args, **kwargs)
+
+ def PrependItem(*args, **kwargs):
+ """
+ PrependItem(self, DataViewItem parent, String text, Icon icon=wxNullIcon,
+ wxClientData data=None) -> DataViewItem
+ """
+ return _dataview.DataViewTreeStore_PrependItem(*args, **kwargs)
+
+ def InsertItem(*args, **kwargs):
+ """
+ InsertItem(self, DataViewItem parent, DataViewItem previous, String text,
+ Icon icon=wxNullIcon, wxClientData data=None) -> DataViewItem
+ """
+ return _dataview.DataViewTreeStore_InsertItem(*args, **kwargs)
+
+ def PrependContainer(*args, **kwargs):
+ """
+ PrependContainer(self, DataViewItem parent, String text, Icon icon=wxNullIcon,
+ Icon expanded=wxNullIcon, wxClientData data=None) -> DataViewItem
+ """
+ return _dataview.DataViewTreeStore_PrependContainer(*args, **kwargs)
+
+ def AppendContainer(*args, **kwargs):
+ """
+ AppendContainer(self, DataViewItem parent, String text, Icon icon=wxNullIcon,
+ Icon expanded=wxNullIcon, wxClientData data=None) -> DataViewItem
+ """
+ return _dataview.DataViewTreeStore_AppendContainer(*args, **kwargs)
+
+ def InsertContainer(*args, **kwargs):
+ """
+ InsertContainer(self, DataViewItem parent, DataViewItem previous, String text,
+ Icon icon=wxNullIcon, Icon expanded=wxNullIcon,
+ wxClientData data=None) -> DataViewItem
+ """
+ return _dataview.DataViewTreeStore_InsertContainer(*args, **kwargs)
+
+ def GetNthChild(*args, **kwargs):
+ """GetNthChild(self, DataViewItem parent, unsigned int pos) -> DataViewItem"""
+ return _dataview.DataViewTreeStore_GetNthChild(*args, **kwargs)
+
+ def GetChildCount(*args, **kwargs):
+ """GetChildCount(self, DataViewItem parent) -> int"""
+ return _dataview.DataViewTreeStore_GetChildCount(*args, **kwargs)
+
+ def SetItemText(*args, **kwargs):
+ """SetItemText(self, DataViewItem item, String text)"""
+ return _dataview.DataViewTreeStore_SetItemText(*args, **kwargs)
+
+ def GetItemText(*args, **kwargs):
+ """GetItemText(self, DataViewItem item) -> String"""
+ return _dataview.DataViewTreeStore_GetItemText(*args, **kwargs)
+
+ def SetItemIcon(*args, **kwargs):
+ """SetItemIcon(self, DataViewItem item, Icon icon)"""
+ return _dataview.DataViewTreeStore_SetItemIcon(*args, **kwargs)
+
+ def GetItemIcon(*args, **kwargs):
+ """GetItemIcon(self, DataViewItem item) -> Icon"""
+ return _dataview.DataViewTreeStore_GetItemIcon(*args, **kwargs)
+
+ def SetItemExpandedIcon(*args, **kwargs):
+ """SetItemExpandedIcon(self, DataViewItem item, Icon icon)"""
+ return _dataview.DataViewTreeStore_SetItemExpandedIcon(*args, **kwargs)
+
+ def GetItemExpandedIcon(*args, **kwargs):
+ """GetItemExpandedIcon(self, DataViewItem item) -> Icon"""
+ return _dataview.DataViewTreeStore_GetItemExpandedIcon(*args, **kwargs)
+
+ def SetItemData(*args, **kwargs):
+ """SetItemData(self, DataViewItem item, wxClientData data)"""
+ return _dataview.DataViewTreeStore_SetItemData(*args, **kwargs)
+
+ def GetItemData(*args, **kwargs):
+ """GetItemData(self, DataViewItem item) -> wxClientData"""
+ return _dataview.DataViewTreeStore_GetItemData(*args, **kwargs)
+
+ def DeleteItem(*args, **kwargs):
+ """DeleteItem(self, DataViewItem item)"""
+ return _dataview.DataViewTreeStore_DeleteItem(*args, **kwargs)
+
+ def DeleteChildren(*args, **kwargs):
+ """DeleteChildren(self, DataViewItem item)"""
+ return _dataview.DataViewTreeStore_DeleteChildren(*args, **kwargs)
+
+ def DeleteAllItems(*args, **kwargs):
+ """DeleteAllItems(self)"""
+ return _dataview.DataViewTreeStore_DeleteAllItems(*args, **kwargs)
+
+_dataview.DataViewTreeStore_swigregister(DataViewTreeStore)
+
+class DataViewTreeCtrl(DataViewCtrl,_core.WithImages):
+ """Proxy of C++ DataViewTreeCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxDV_NO_HEADER|wxDV_ROW_LINES,
+ Validator validator=DefaultValidator) -> DataViewTreeCtrl
+ """
+ _dataview.DataViewTreeCtrl_swiginit(self,_dataview.new_DataViewTreeCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxDV_NO_HEADER|wxDV_ROW_LINES,
+ Validator validator=DefaultValidator) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _dataview.DataViewTreeCtrl_Create(*args, **kwargs)
+
+ def GetStore(*args, **kwargs):
+ """GetStore(self) -> DataViewTreeStore"""
+ return _dataview.DataViewTreeCtrl_GetStore(*args, **kwargs)
+
+ def IsContainer(*args, **kwargs):
+ """IsContainer(self, DataViewItem item) -> bool"""
+ return _dataview.DataViewTreeCtrl_IsContainer(*args, **kwargs)
+
+ def AppendItem(*args, **kwargs):
+ """AppendItem(self, DataViewItem parent, String text, int icon=-1, wxClientData data=None) -> DataViewItem"""
+ return _dataview.DataViewTreeCtrl_AppendItem(*args, **kwargs)
+
+ def PrependItem(*args, **kwargs):
+ """PrependItem(self, DataViewItem parent, String text, int icon=-1, wxClientData data=None) -> DataViewItem"""
+ return _dataview.DataViewTreeCtrl_PrependItem(*args, **kwargs)
+
+ def InsertItem(*args, **kwargs):
+ """
+ InsertItem(self, DataViewItem parent, DataViewItem previous, String text,
+ int icon=-1, wxClientData data=None) -> DataViewItem
+ """
+ return _dataview.DataViewTreeCtrl_InsertItem(*args, **kwargs)
+
+ def PrependContainer(*args, **kwargs):
+ """
+ PrependContainer(self, DataViewItem parent, String text, int icon=-1, int expanded=-1,
+ wxClientData data=None) -> DataViewItem
+ """
+ return _dataview.DataViewTreeCtrl_PrependContainer(*args, **kwargs)
+
+ def AppendContainer(*args, **kwargs):
+ """
+ AppendContainer(self, DataViewItem parent, String text, int icon=-1, int expanded=-1,
+ wxClientData data=None) -> DataViewItem
+ """
+ return _dataview.DataViewTreeCtrl_AppendContainer(*args, **kwargs)
+
+ def InsertContainer(*args, **kwargs):
+ """
+ InsertContainer(self, DataViewItem parent, DataViewItem previous, String text,
+ int icon=-1, int expanded=-1, wxClientData data=None) -> DataViewItem
+ """
+ return _dataview.DataViewTreeCtrl_InsertContainer(*args, **kwargs)
+
+ def GetNthChild(*args, **kwargs):
+ """GetNthChild(self, DataViewItem parent, unsigned int pos) -> DataViewItem"""
+ return _dataview.DataViewTreeCtrl_GetNthChild(*args, **kwargs)
+
+ def GetChildCount(*args, **kwargs):
+ """GetChildCount(self, DataViewItem parent) -> int"""
+ return _dataview.DataViewTreeCtrl_GetChildCount(*args, **kwargs)
+
+ def SetItemText(*args, **kwargs):
+ """SetItemText(self, DataViewItem item, String text)"""
+ return _dataview.DataViewTreeCtrl_SetItemText(*args, **kwargs)
+
+ def GetItemText(*args, **kwargs):
+ """GetItemText(self, DataViewItem item) -> String"""
+ return _dataview.DataViewTreeCtrl_GetItemText(*args, **kwargs)
+
+ def SetItemIcon(*args, **kwargs):
+ """SetItemIcon(self, DataViewItem item, Icon icon)"""
+ return _dataview.DataViewTreeCtrl_SetItemIcon(*args, **kwargs)
+
+ def GetItemIcon(*args, **kwargs):
+ """GetItemIcon(self, DataViewItem item) -> Icon"""
+ return _dataview.DataViewTreeCtrl_GetItemIcon(*args, **kwargs)
+
+ def SetItemExpandedIcon(*args, **kwargs):
+ """SetItemExpandedIcon(self, DataViewItem item, Icon icon)"""
+ return _dataview.DataViewTreeCtrl_SetItemExpandedIcon(*args, **kwargs)
+
+ def GetItemExpandedIcon(*args, **kwargs):
+ """GetItemExpandedIcon(self, DataViewItem item) -> Icon"""
+ return _dataview.DataViewTreeCtrl_GetItemExpandedIcon(*args, **kwargs)
+
+ def SetItemData(*args, **kwargs):
+ """SetItemData(self, DataViewItem item, wxClientData data)"""
+ return _dataview.DataViewTreeCtrl_SetItemData(*args, **kwargs)
+
+ def GetItemData(*args, **kwargs):
+ """GetItemData(self, DataViewItem item) -> wxClientData"""
+ return _dataview.DataViewTreeCtrl_GetItemData(*args, **kwargs)
+
+ def DeleteItem(*args, **kwargs):
+ """DeleteItem(self, DataViewItem item)"""
+ return _dataview.DataViewTreeCtrl_DeleteItem(*args, **kwargs)
+
+ def DeleteChildren(*args, **kwargs):
+ """DeleteChildren(self, DataViewItem item)"""
+ return _dataview.DataViewTreeCtrl_DeleteChildren(*args, **kwargs)
+
+ def DeleteAllItems(*args, **kwargs):
+ """DeleteAllItems(self)"""
+ return _dataview.DataViewTreeCtrl_DeleteAllItems(*args, **kwargs)
+
+_dataview.DataViewTreeCtrl_swigregister(DataViewTreeCtrl)
+
+def PreDataViewTreeCtrl(*args, **kwargs):
+ """PreDataViewTreeCtrl() -> DataViewTreeCtrl"""
+ val = _dataview.new_PreDataViewTreeCtrl(*args, **kwargs)
+ return val
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/gizmos.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/gizmos.py
new file mode 100644
index 0000000..57ff63c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/gizmos.py
@@ -0,0 +1,1051 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+Various *gizmo* classes: `DynamicSashWindow`, `EditableListBox`,
+`LEDNumberCtrl`, `TreeListCtrl`, etc.
+"""
+
+import _gizmos
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _windows
+import _core
+import _controls
+import wx
+__docfilter__ = wx._core.__DocFilter(globals())
+DS_MANAGE_SCROLLBARS = _gizmos.DS_MANAGE_SCROLLBARS
+DS_DRAG_CORNER = _gizmos.DS_DRAG_CORNER
+wxEVT_DYNAMIC_SASH_SPLIT = _gizmos.wxEVT_DYNAMIC_SASH_SPLIT
+wxEVT_DYNAMIC_SASH_UNIFY = _gizmos.wxEVT_DYNAMIC_SASH_UNIFY
+class DynamicSashSplitEvent(_core.CommandEvent):
+ """Proxy of C++ DynamicSashSplitEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Object target) -> DynamicSashSplitEvent"""
+ _gizmos.DynamicSashSplitEvent_swiginit(self,_gizmos.new_DynamicSashSplitEvent(*args, **kwargs))
+_gizmos.DynamicSashSplitEvent_swigregister(DynamicSashSplitEvent)
+cvar = _gizmos.cvar
+DynamicSashNameStr = cvar.DynamicSashNameStr
+EditableListBoxNameStr = cvar.EditableListBoxNameStr
+StaticPictureNameStr = cvar.StaticPictureNameStr
+
+class DynamicSashUnifyEvent(_core.CommandEvent):
+ """Proxy of C++ DynamicSashUnifyEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Object target) -> DynamicSashUnifyEvent"""
+ _gizmos.DynamicSashUnifyEvent_swiginit(self,_gizmos.new_DynamicSashUnifyEvent(*args, **kwargs))
+_gizmos.DynamicSashUnifyEvent_swigregister(DynamicSashUnifyEvent)
+
+class DynamicSashWindow(_core.Window):
+ """Proxy of C++ DynamicSashWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxDS_MANAGE_SCROLLBARS|wxDS_DRAG_CORNER,
+ String name=DynamicSashNameStr) -> DynamicSashWindow
+ """
+ _gizmos.DynamicSashWindow_swiginit(self,_gizmos.new_DynamicSashWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxDS_MANAGE_SCROLLBARS|wxDS_DRAG_CORNER,
+ String name=DynamicSashNameStr) -> bool
+ """
+ return _gizmos.DynamicSashWindow_Create(*args, **kwargs)
+
+ def GetHScrollBar(*args, **kwargs):
+ """GetHScrollBar(self, Window child) -> ScrollBar"""
+ return _gizmos.DynamicSashWindow_GetHScrollBar(*args, **kwargs)
+
+ def GetVScrollBar(*args, **kwargs):
+ """GetVScrollBar(self, Window child) -> ScrollBar"""
+ return _gizmos.DynamicSashWindow_GetVScrollBar(*args, **kwargs)
+
+_gizmos.DynamicSashWindow_swigregister(DynamicSashWindow)
+
+def PreDynamicSashWindow(*args, **kwargs):
+ """PreDynamicSashWindow() -> DynamicSashWindow"""
+ val = _gizmos.new_PreDynamicSashWindow(*args, **kwargs)
+ return val
+
+EVT_DYNAMIC_SASH_SPLIT = wx.PyEventBinder( wxEVT_DYNAMIC_SASH_SPLIT, 1 )
+EVT_DYNAMIC_SASH_UNIFY = wx.PyEventBinder( wxEVT_DYNAMIC_SASH_UNIFY, 1 )
+
+EL_ALLOW_NEW = _gizmos.EL_ALLOW_NEW
+EL_ALLOW_EDIT = _gizmos.EL_ALLOW_EDIT
+EL_ALLOW_DELETE = _gizmos.EL_ALLOW_DELETE
+EL_NO_REORDER = _gizmos.EL_NO_REORDER
+EL_DEFAULT_STYLE = _gizmos.EL_DEFAULT_STYLE
+class EditableListBox(_windows.Panel):
+ """Proxy of C++ EditableListBox class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String label=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=EL_DEFAULT_STYLE, String name=EditableListBoxNameStr) -> EditableListBox
+ """
+ _gizmos.EditableListBox_swiginit(self,_gizmos.new_EditableListBox(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id, String label, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=EL_DEFAULT_STYLE,
+ String name=wxEditableListBoxNameStr) -> bool
+ """
+ return _gizmos.EditableListBox_Create(*args, **kwargs)
+
+ def SetStrings(*args, **kwargs):
+ """SetStrings(self, wxArrayString strings)"""
+ return _gizmos.EditableListBox_SetStrings(*args, **kwargs)
+
+ def GetStrings(*args, **kwargs):
+ """GetStrings(self) -> PyObject"""
+ return _gizmos.EditableListBox_GetStrings(*args, **kwargs)
+
+ def GetListCtrl(*args, **kwargs):
+ """GetListCtrl(self) -> ListCtrl"""
+ return _gizmos.EditableListBox_GetListCtrl(*args, **kwargs)
+
+ def GetDelButton(*args, **kwargs):
+ """GetDelButton(self) -> BitmapButton"""
+ return _gizmos.EditableListBox_GetDelButton(*args, **kwargs)
+
+ def GetNewButton(*args, **kwargs):
+ """GetNewButton(self) -> BitmapButton"""
+ return _gizmos.EditableListBox_GetNewButton(*args, **kwargs)
+
+ def GetUpButton(*args, **kwargs):
+ """GetUpButton(self) -> BitmapButton"""
+ return _gizmos.EditableListBox_GetUpButton(*args, **kwargs)
+
+ def GetDownButton(*args, **kwargs):
+ """GetDownButton(self) -> BitmapButton"""
+ return _gizmos.EditableListBox_GetDownButton(*args, **kwargs)
+
+ def GetEditButton(*args, **kwargs):
+ """GetEditButton(self) -> BitmapButton"""
+ return _gizmos.EditableListBox_GetEditButton(*args, **kwargs)
+
+ DelButton = property(GetDelButton,doc="See `GetDelButton`")
+ DownButton = property(GetDownButton,doc="See `GetDownButton`")
+ EditButton = property(GetEditButton,doc="See `GetEditButton`")
+ ListCtrl = property(GetListCtrl,doc="See `GetListCtrl`")
+ NewButton = property(GetNewButton,doc="See `GetNewButton`")
+ Strings = property(GetStrings,SetStrings,doc="See `GetStrings` and `SetStrings`")
+ UpButton = property(GetUpButton,doc="See `GetUpButton`")
+_gizmos.EditableListBox_swigregister(EditableListBox)
+
+def PreEditableListBox(*args, **kwargs):
+ """PreEditableListBox() -> EditableListBox"""
+ val = _gizmos.new_PreEditableListBox(*args, **kwargs)
+ return val
+
+class RemotelyScrolledTreeCtrl(_controls.TreeCtrl):
+ """Proxy of C++ RemotelyScrolledTreeCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=TR_HAS_BUTTONS) -> RemotelyScrolledTreeCtrl
+ """
+ _gizmos.RemotelyScrolledTreeCtrl_swiginit(self,_gizmos.new_RemotelyScrolledTreeCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def HideVScrollbar(*args, **kwargs):
+ """HideVScrollbar(self)"""
+ return _gizmos.RemotelyScrolledTreeCtrl_HideVScrollbar(*args, **kwargs)
+
+ def AdjustRemoteScrollbars(*args, **kwargs):
+ """AdjustRemoteScrollbars(self)"""
+ return _gizmos.RemotelyScrolledTreeCtrl_AdjustRemoteScrollbars(*args, **kwargs)
+
+ def GetScrolledWindow(*args, **kwargs):
+ """GetScrolledWindow(self) -> ScrolledWindow"""
+ return _gizmos.RemotelyScrolledTreeCtrl_GetScrolledWindow(*args, **kwargs)
+
+ def ScrollToLine(*args, **kwargs):
+ """ScrollToLine(self, int posHoriz, int posVert)"""
+ return _gizmos.RemotelyScrolledTreeCtrl_ScrollToLine(*args, **kwargs)
+
+ def SetCompanionWindow(*args, **kwargs):
+ """SetCompanionWindow(self, Window companion)"""
+ return _gizmos.RemotelyScrolledTreeCtrl_SetCompanionWindow(*args, **kwargs)
+
+ def GetCompanionWindow(*args, **kwargs):
+ """GetCompanionWindow(self) -> Window"""
+ return _gizmos.RemotelyScrolledTreeCtrl_GetCompanionWindow(*args, **kwargs)
+
+ CompanionWindow = property(GetCompanionWindow,SetCompanionWindow,doc="See `GetCompanionWindow` and `SetCompanionWindow`")
+ ScrolledWindow = property(GetScrolledWindow,doc="See `GetScrolledWindow`")
+_gizmos.RemotelyScrolledTreeCtrl_swigregister(RemotelyScrolledTreeCtrl)
+
+class TreeCompanionWindow(_core.Window):
+ """Proxy of C++ TreeCompanionWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0) -> TreeCompanionWindow
+ """
+ _gizmos.TreeCompanionWindow_swiginit(self,_gizmos.new_TreeCompanionWindow(*args, **kwargs))
+ self._setOORInfo(self);TreeCompanionWindow._setCallbackInfo(self, self, TreeCompanionWindow)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _gizmos.TreeCompanionWindow__setCallbackInfo(*args, **kwargs)
+
+ def GetTreeCtrl(*args, **kwargs):
+ """GetTreeCtrl(self) -> RemotelyScrolledTreeCtrl"""
+ return _gizmos.TreeCompanionWindow_GetTreeCtrl(*args, **kwargs)
+
+ def SetTreeCtrl(*args, **kwargs):
+ """SetTreeCtrl(self, RemotelyScrolledTreeCtrl treeCtrl)"""
+ return _gizmos.TreeCompanionWindow_SetTreeCtrl(*args, **kwargs)
+
+ TreeCtrl = property(GetTreeCtrl,SetTreeCtrl,doc="See `GetTreeCtrl` and `SetTreeCtrl`")
+_gizmos.TreeCompanionWindow_swigregister(TreeCompanionWindow)
+
+class ThinSplitterWindow(_windows.SplitterWindow):
+ """Proxy of C++ ThinSplitterWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxSP_3D|wxCLIP_CHILDREN) -> ThinSplitterWindow
+ """
+ _gizmos.ThinSplitterWindow_swiginit(self,_gizmos.new_ThinSplitterWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+_gizmos.ThinSplitterWindow_swigregister(ThinSplitterWindow)
+
+class SplitterScrolledWindow(_windows.ScrolledWindow):
+ """Proxy of C++ SplitterScrolledWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0) -> SplitterScrolledWindow
+ """
+ _gizmos.SplitterScrolledWindow_swiginit(self,_gizmos.new_SplitterScrolledWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+_gizmos.SplitterScrolledWindow_swigregister(SplitterScrolledWindow)
+
+LED_ALIGN_LEFT = _gizmos.LED_ALIGN_LEFT
+LED_ALIGN_RIGHT = _gizmos.LED_ALIGN_RIGHT
+LED_ALIGN_CENTER = _gizmos.LED_ALIGN_CENTER
+LED_ALIGN_MASK = _gizmos.LED_ALIGN_MASK
+LED_DRAW_FADED = _gizmos.LED_DRAW_FADED
+class LEDNumberCtrl(_core.Control):
+ """Proxy of C++ LEDNumberCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxLED_ALIGN_LEFT|wxLED_DRAW_FADED) -> LEDNumberCtrl
+ """
+ _gizmos.LEDNumberCtrl_swiginit(self,_gizmos.new_LEDNumberCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=wxLED_ALIGN_LEFT|wxLED_DRAW_FADED) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _gizmos.LEDNumberCtrl_Create(*args, **kwargs)
+
+ def GetAlignment(*args, **kwargs):
+ """
+ GetAlignment(self) -> int
+
+ Get the control alignment (left/right/centre, top/bottom/centre)
+ """
+ return _gizmos.LEDNumberCtrl_GetAlignment(*args, **kwargs)
+
+ def GetDrawFaded(*args, **kwargs):
+ """GetDrawFaded(self) -> bool"""
+ return _gizmos.LEDNumberCtrl_GetDrawFaded(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> String"""
+ return _gizmos.LEDNumberCtrl_GetValue(*args, **kwargs)
+
+ def SetAlignment(*args, **kwargs):
+ """SetAlignment(self, int Alignment, bool Redraw=True)"""
+ return _gizmos.LEDNumberCtrl_SetAlignment(*args, **kwargs)
+
+ def SetDrawFaded(*args, **kwargs):
+ """SetDrawFaded(self, bool DrawFaded, bool Redraw=True)"""
+ return _gizmos.LEDNumberCtrl_SetDrawFaded(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, String Value, bool Redraw=True)"""
+ return _gizmos.LEDNumberCtrl_SetValue(*args, **kwargs)
+
+ Alignment = property(GetAlignment,SetAlignment,doc="See `GetAlignment` and `SetAlignment`")
+ DrawFaded = property(GetDrawFaded,SetDrawFaded,doc="See `GetDrawFaded` and `SetDrawFaded`")
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_gizmos.LEDNumberCtrl_swigregister(LEDNumberCtrl)
+
+def PreLEDNumberCtrl(*args, **kwargs):
+ """PreLEDNumberCtrl() -> LEDNumberCtrl"""
+ val = _gizmos.new_PreLEDNumberCtrl(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+DEFAULT_COL_WIDTH = _gizmos.DEFAULT_COL_WIDTH
+TL_MODE_NAV_FULLTREE = _gizmos.TL_MODE_NAV_FULLTREE
+TL_MODE_NAV_EXPANDED = _gizmos.TL_MODE_NAV_EXPANDED
+TL_MODE_NAV_VISIBLE = _gizmos.TL_MODE_NAV_VISIBLE
+TL_MODE_NAV_LEVEL = _gizmos.TL_MODE_NAV_LEVEL
+TL_MODE_FIND_EXACT = _gizmos.TL_MODE_FIND_EXACT
+TL_MODE_FIND_PARTIAL = _gizmos.TL_MODE_FIND_PARTIAL
+TL_MODE_FIND_NOCASE = _gizmos.TL_MODE_FIND_NOCASE
+TREE_HITTEST_ONITEMCOLUMN = _gizmos.TREE_HITTEST_ONITEMCOLUMN
+wx.TREE_HITTEST_ONITEMCOLUMN = TREE_HITTEST_ONITEMCOLUMN
+TR_COLUMN_LINES = _gizmos.TR_COLUMN_LINES
+TR_VIRTUAL = _gizmos.TR_VIRTUAL
+wx.TR_COLUMN_LINES = TR_COLUMN_LINES
+wx.TR_VIRTUAL = TR_VIRTUAL
+
+#// Compatibility aliases for old names/values
+TL_ALIGN_LEFT = wx.ALIGN_LEFT
+TL_ALIGN_RIGHT = wx.ALIGN_RIGHT
+TL_ALIGN_CENTER = wx.ALIGN_CENTER
+
+TL_SEARCH_VISIBLE = TL_MODE_NAV_VISIBLE
+TL_SEARCH_LEVEL = TL_MODE_NAV_LEVEL
+TL_SEARCH_FULL = TL_MODE_FIND_EXACT
+TL_SEARCH_PARTIAL = TL_MODE_FIND_PARTIAL
+TL_SEARCH_NOCASE = TL_MODE_FIND_NOCASE
+
+TR_DONT_ADJUST_MAC = 0
+wx.TR_DONT_ADJUST_MAC = TR_DONT_ADJUST_MAC
+
+class TreeListColumnInfo(_core.Object):
+ """Proxy of C++ TreeListColumnInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String text=EmptyString, int width=DEFAULT_COL_WIDTH,
+ int flag=ALIGN_LEFT, int image=-1, bool shown=True,
+ bool edit=False) -> TreeListColumnInfo
+ """
+ _gizmos.TreeListColumnInfo_swiginit(self,_gizmos.new_TreeListColumnInfo(*args, **kwargs))
+ __swig_destroy__ = _gizmos.delete_TreeListColumnInfo
+ __del__ = lambda self : None;
+ def GetAlignment(*args, **kwargs):
+ """GetAlignment(self) -> int"""
+ return _gizmos.TreeListColumnInfo_GetAlignment(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self) -> String"""
+ return _gizmos.TreeListColumnInfo_GetText(*args, **kwargs)
+
+ def GetImage(*args, **kwargs):
+ """GetImage(self) -> int"""
+ return _gizmos.TreeListColumnInfo_GetImage(*args, **kwargs)
+
+ def GetSelectedImage(*args, **kwargs):
+ """GetSelectedImage(self) -> int"""
+ return _gizmos.TreeListColumnInfo_GetSelectedImage(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> size_t"""
+ return _gizmos.TreeListColumnInfo_GetWidth(*args, **kwargs)
+
+ def IsEditable(*args, **kwargs):
+ """IsEditable(self) -> bool"""
+ return _gizmos.TreeListColumnInfo_IsEditable(*args, **kwargs)
+
+ def IsShown(*args, **kwargs):
+ """IsShown(self) -> bool"""
+ return _gizmos.TreeListColumnInfo_IsShown(*args, **kwargs)
+
+ def SetAlignment(*args, **kwargs):
+ """SetAlignment(self, int alignment)"""
+ return _gizmos.TreeListColumnInfo_SetAlignment(*args, **kwargs)
+
+ def SetText(*args, **kwargs):
+ """SetText(self, String text)"""
+ return _gizmos.TreeListColumnInfo_SetText(*args, **kwargs)
+
+ def SetImage(*args, **kwargs):
+ """SetImage(self, int image)"""
+ return _gizmos.TreeListColumnInfo_SetImage(*args, **kwargs)
+
+ def SetSelectedImage(*args, **kwargs):
+ """SetSelectedImage(self, int image)"""
+ return _gizmos.TreeListColumnInfo_SetSelectedImage(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """SetWidth(self, size_t with)"""
+ return _gizmos.TreeListColumnInfo_SetWidth(*args, **kwargs)
+
+ def SetEditable(*args, **kwargs):
+ """SetEditable(self, bool edit)"""
+ return _gizmos.TreeListColumnInfo_SetEditable(*args, **kwargs)
+
+ def SetShown(*args, **kwargs):
+ """SetShown(self, bool shown)"""
+ return _gizmos.TreeListColumnInfo_SetShown(*args, **kwargs)
+
+ Alignment = property(GetAlignment,SetAlignment,doc="See `GetAlignment` and `SetAlignment`")
+ Image = property(GetImage,SetImage,doc="See `GetImage` and `SetImage`")
+ SelectedImage = property(GetSelectedImage,SetSelectedImage,doc="See `GetSelectedImage` and `SetSelectedImage`")
+ Text = property(GetText,SetText,doc="See `GetText` and `SetText`")
+ Width = property(GetWidth,SetWidth,doc="See `GetWidth` and `SetWidth`")
+ Editable = property(IsEditable,SetEditable)
+ Shown = property(IsShown,SetShown)
+_gizmos.TreeListColumnInfo_swigregister(TreeListColumnInfo)
+TreeListCtrlNameStr = cvar.TreeListCtrlNameStr
+
+class TreeListCtrl(_core.Control):
+ """Proxy of C++ TreeListCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=TR_DEFAULT_STYLE,
+ Validator validator=DefaultValidator,
+ String name=TreeListCtrlNameStr) -> TreeListCtrl
+ """
+ _gizmos.TreeListCtrl_swiginit(self,_gizmos.new_TreeListCtrl(*args, **kwargs))
+ self._setOORInfo(self);TreeListCtrl._setCallbackInfo(self, self, TreeListCtrl)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=TR_DEFAULT_STYLE,
+ Validator validator=DefaultValidator,
+ String name=TreeListCtrlNameStr) -> bool
+
+ Do the 2nd phase and create the GUI control.
+ """
+ return _gizmos.TreeListCtrl_Create(*args, **kwargs)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _gizmos.TreeListCtrl__setCallbackInfo(*args, **kwargs)
+
+ def GetCount(*args, **kwargs):
+ """GetCount(self) -> size_t"""
+ return _gizmos.TreeListCtrl_GetCount(*args, **kwargs)
+
+ def GetIndent(*args, **kwargs):
+ """GetIndent(self) -> unsigned int"""
+ return _gizmos.TreeListCtrl_GetIndent(*args, **kwargs)
+
+ def SetIndent(*args, **kwargs):
+ """SetIndent(self, unsigned int indent)"""
+ return _gizmos.TreeListCtrl_SetIndent(*args, **kwargs)
+
+ def GetLineSpacing(*args, **kwargs):
+ """GetLineSpacing(self) -> unsigned int"""
+ return _gizmos.TreeListCtrl_GetLineSpacing(*args, **kwargs)
+
+ def SetLineSpacing(*args, **kwargs):
+ """SetLineSpacing(self, unsigned int spacing)"""
+ return _gizmos.TreeListCtrl_SetLineSpacing(*args, **kwargs)
+
+ def GetImageList(*args, **kwargs):
+ """GetImageList(self) -> ImageList"""
+ return _gizmos.TreeListCtrl_GetImageList(*args, **kwargs)
+
+ def GetStateImageList(*args, **kwargs):
+ """GetStateImageList(self) -> ImageList"""
+ return _gizmos.TreeListCtrl_GetStateImageList(*args, **kwargs)
+
+ def GetButtonsImageList(*args, **kwargs):
+ """GetButtonsImageList(self) -> ImageList"""
+ return _gizmos.TreeListCtrl_GetButtonsImageList(*args, **kwargs)
+
+ def SetImageList(*args, **kwargs):
+ """SetImageList(self, ImageList imageList)"""
+ return _gizmos.TreeListCtrl_SetImageList(*args, **kwargs)
+
+ def SetStateImageList(*args, **kwargs):
+ """SetStateImageList(self, ImageList imageList)"""
+ return _gizmos.TreeListCtrl_SetStateImageList(*args, **kwargs)
+
+ def SetButtonsImageList(*args, **kwargs):
+ """SetButtonsImageList(self, ImageList imageList)"""
+ return _gizmos.TreeListCtrl_SetButtonsImageList(*args, **kwargs)
+
+ def AssignImageList(*args, **kwargs):
+ """AssignImageList(self, ImageList imageList)"""
+ return _gizmos.TreeListCtrl_AssignImageList(*args, **kwargs)
+
+ def AssignStateImageList(*args, **kwargs):
+ """AssignStateImageList(self, ImageList imageList)"""
+ return _gizmos.TreeListCtrl_AssignStateImageList(*args, **kwargs)
+
+ def AssignButtonsImageList(*args, **kwargs):
+ """AssignButtonsImageList(self, ImageList imageList)"""
+ return _gizmos.TreeListCtrl_AssignButtonsImageList(*args, **kwargs)
+
+ def AddColumn(*args, **kwargs):
+ """
+ AddColumn(self, String text, int width=DEFAULT_COL_WIDTH, int flag=ALIGN_LEFT,
+ int image=-1, bool shown=True, bool edit=False)
+ """
+ return _gizmos.TreeListCtrl_AddColumn(*args, **kwargs)
+
+ def AddColumnInfo(*args, **kwargs):
+ """AddColumnInfo(self, TreeListColumnInfo col)"""
+ return _gizmos.TreeListCtrl_AddColumnInfo(*args, **kwargs)
+
+ def InsertColumn(*args, **kwargs):
+ """
+ InsertColumn(self, int before, String text, int width=DEFAULT_COL_WIDTH,
+ int flag=ALIGN_LEFT, int image=-1, bool shown=True,
+ bool edit=False)
+ """
+ return _gizmos.TreeListCtrl_InsertColumn(*args, **kwargs)
+
+ def InsertColumnInfo(*args, **kwargs):
+ """InsertColumnInfo(self, size_t before, TreeListColumnInfo col)"""
+ return _gizmos.TreeListCtrl_InsertColumnInfo(*args, **kwargs)
+
+ def RemoveColumn(*args, **kwargs):
+ """RemoveColumn(self, size_t column)"""
+ return _gizmos.TreeListCtrl_RemoveColumn(*args, **kwargs)
+
+ def GetColumnCount(*args, **kwargs):
+ """GetColumnCount(self) -> size_t"""
+ return _gizmos.TreeListCtrl_GetColumnCount(*args, **kwargs)
+
+ def SetMainColumn(*args, **kwargs):
+ """SetMainColumn(self, size_t column)"""
+ return _gizmos.TreeListCtrl_SetMainColumn(*args, **kwargs)
+
+ def GetMainColumn(*args, **kwargs):
+ """GetMainColumn(self) -> size_t"""
+ return _gizmos.TreeListCtrl_GetMainColumn(*args, **kwargs)
+
+ def SetColumn(*args, **kwargs):
+ """SetColumn(self, int column, TreeListColumnInfo colInfo)"""
+ return _gizmos.TreeListCtrl_SetColumn(*args, **kwargs)
+
+ def GetColumn(*args, **kwargs):
+ """GetColumn(self, int column) -> TreeListColumnInfo"""
+ return _gizmos.TreeListCtrl_GetColumn(*args, **kwargs)
+
+ def SetColumnText(*args, **kwargs):
+ """SetColumnText(self, int column, String text)"""
+ return _gizmos.TreeListCtrl_SetColumnText(*args, **kwargs)
+
+ def GetColumnText(*args, **kwargs):
+ """GetColumnText(self, int column) -> String"""
+ return _gizmos.TreeListCtrl_GetColumnText(*args, **kwargs)
+
+ def SetColumnWidth(*args, **kwargs):
+ """SetColumnWidth(self, int column, int width)"""
+ return _gizmos.TreeListCtrl_SetColumnWidth(*args, **kwargs)
+
+ def GetColumnWidth(*args, **kwargs):
+ """GetColumnWidth(self, int column) -> int"""
+ return _gizmos.TreeListCtrl_GetColumnWidth(*args, **kwargs)
+
+ def SetColumnAlignment(*args, **kwargs):
+ """SetColumnAlignment(self, int column, int flag)"""
+ return _gizmos.TreeListCtrl_SetColumnAlignment(*args, **kwargs)
+
+ def GetColumnAlignment(*args, **kwargs):
+ """GetColumnAlignment(self, int column) -> int"""
+ return _gizmos.TreeListCtrl_GetColumnAlignment(*args, **kwargs)
+
+ def SetColumnImage(*args, **kwargs):
+ """SetColumnImage(self, int column, int image)"""
+ return _gizmos.TreeListCtrl_SetColumnImage(*args, **kwargs)
+
+ def GetColumnImage(*args, **kwargs):
+ """GetColumnImage(self, int column) -> int"""
+ return _gizmos.TreeListCtrl_GetColumnImage(*args, **kwargs)
+
+ def SetColumnShown(*args, **kwargs):
+ """SetColumnShown(self, int column, bool shown=True)"""
+ return _gizmos.TreeListCtrl_SetColumnShown(*args, **kwargs)
+
+ def IsColumnShown(*args, **kwargs):
+ """IsColumnShown(self, int column) -> bool"""
+ return _gizmos.TreeListCtrl_IsColumnShown(*args, **kwargs)
+
+ ShowColumn = SetColumnShown
+ def SetColumnEditable(*args, **kwargs):
+ """SetColumnEditable(self, int column, bool edit=True)"""
+ return _gizmos.TreeListCtrl_SetColumnEditable(*args, **kwargs)
+
+ def IsColumnEditable(*args, **kwargs):
+ """IsColumnEditable(self, int column) -> bool"""
+ return _gizmos.TreeListCtrl_IsColumnEditable(*args, **kwargs)
+
+ def GetItemText(*args, **kwargs):
+ """GetItemText(self, TreeItemId item, int column=-1) -> String"""
+ return _gizmos.TreeListCtrl_GetItemText(*args, **kwargs)
+
+ def GetItemImage(*args, **kwargs):
+ """GetItemImage(self, TreeItemId item, int column=-1, int which=TreeItemIcon_Normal) -> int"""
+ return _gizmos.TreeListCtrl_GetItemImage(*args, **kwargs)
+
+ def SetItemText(*args, **kwargs):
+ """SetItemText(self, TreeItemId item, String text, int column=-1)"""
+ return _gizmos.TreeListCtrl_SetItemText(*args, **kwargs)
+
+ def SetItemImage(*args, **kwargs):
+ """SetItemImage(self, TreeItemId item, int image, int column=-1, int which=TreeItemIcon_Normal)"""
+ return _gizmos.TreeListCtrl_SetItemImage(*args, **kwargs)
+
+ def GetItemData(*args, **kwargs):
+ """GetItemData(self, TreeItemId item) -> TreeItemData"""
+ return _gizmos.TreeListCtrl_GetItemData(*args, **kwargs)
+
+ def SetItemData(*args, **kwargs):
+ """SetItemData(self, TreeItemId item, TreeItemData data)"""
+ return _gizmos.TreeListCtrl_SetItemData(*args, **kwargs)
+
+ def GetItemPyData(*args, **kwargs):
+ """GetItemPyData(self, TreeItemId item) -> PyObject"""
+ return _gizmos.TreeListCtrl_GetItemPyData(*args, **kwargs)
+
+ def SetItemPyData(*args, **kwargs):
+ """SetItemPyData(self, TreeItemId item, PyObject obj)"""
+ return _gizmos.TreeListCtrl_SetItemPyData(*args, **kwargs)
+
+ GetPyData = GetItemPyData
+ SetPyData = SetItemPyData
+ def GetItemBold(*args, **kwargs):
+ """GetItemBold(self, TreeItemId item) -> bool"""
+ return _gizmos.TreeListCtrl_GetItemBold(*args, **kwargs)
+
+ def GetItemTextColour(*args, **kwargs):
+ """GetItemTextColour(self, TreeItemId item) -> Colour"""
+ return _gizmos.TreeListCtrl_GetItemTextColour(*args, **kwargs)
+
+ def GetItemBackgroundColour(*args, **kwargs):
+ """GetItemBackgroundColour(self, TreeItemId item) -> Colour"""
+ return _gizmos.TreeListCtrl_GetItemBackgroundColour(*args, **kwargs)
+
+ def GetItemFont(*args, **kwargs):
+ """GetItemFont(self, TreeItemId item) -> Font"""
+ return _gizmos.TreeListCtrl_GetItemFont(*args, **kwargs)
+
+ def SetItemHasChildren(*args, **kwargs):
+ """SetItemHasChildren(self, TreeItemId item, bool has=True)"""
+ return _gizmos.TreeListCtrl_SetItemHasChildren(*args, **kwargs)
+
+ def SetItemBold(*args, **kwargs):
+ """SetItemBold(self, TreeItemId item, bool bold=True)"""
+ return _gizmos.TreeListCtrl_SetItemBold(*args, **kwargs)
+
+ def SetItemTextColour(*args, **kwargs):
+ """SetItemTextColour(self, TreeItemId item, Colour colour)"""
+ return _gizmos.TreeListCtrl_SetItemTextColour(*args, **kwargs)
+
+ def SetItemBackgroundColour(*args, **kwargs):
+ """SetItemBackgroundColour(self, TreeItemId item, Colour colour)"""
+ return _gizmos.TreeListCtrl_SetItemBackgroundColour(*args, **kwargs)
+
+ def SetItemFont(*args, **kwargs):
+ """SetItemFont(self, TreeItemId item, Font font)"""
+ return _gizmos.TreeListCtrl_SetItemFont(*args, **kwargs)
+
+ def IsVisible(*args, **kwargs):
+ """IsVisible(self, TreeItemId item) -> bool"""
+ return _gizmos.TreeListCtrl_IsVisible(*args, **kwargs)
+
+ def HasChildren(*args, **kwargs):
+ """HasChildren(self, TreeItemId item) -> bool"""
+ return _gizmos.TreeListCtrl_HasChildren(*args, **kwargs)
+
+ ItemHasChildren = HasChildren
+ def IsExpanded(*args, **kwargs):
+ """IsExpanded(self, TreeItemId item) -> bool"""
+ return _gizmos.TreeListCtrl_IsExpanded(*args, **kwargs)
+
+ def IsSelected(*args, **kwargs):
+ """IsSelected(self, TreeItemId item) -> bool"""
+ return _gizmos.TreeListCtrl_IsSelected(*args, **kwargs)
+
+ def IsBold(*args, **kwargs):
+ """IsBold(self, TreeItemId item) -> bool"""
+ return _gizmos.TreeListCtrl_IsBold(*args, **kwargs)
+
+ def GetChildrenCount(*args, **kwargs):
+ """GetChildrenCount(self, TreeItemId item, bool recursively=True) -> size_t"""
+ return _gizmos.TreeListCtrl_GetChildrenCount(*args, **kwargs)
+
+ def GetRootItem(*args, **kwargs):
+ """GetRootItem(self) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetRootItem(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetSelection(*args, **kwargs)
+
+ def GetSelections(*args, **kwargs):
+ """GetSelections(self) -> PyObject"""
+ return _gizmos.TreeListCtrl_GetSelections(*args, **kwargs)
+
+ def GetItemParent(*args, **kwargs):
+ """GetItemParent(self, TreeItemId item) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetItemParent(*args, **kwargs)
+
+ def GetCurrentItem(*args, **kwargs):
+ """GetCurrentItem(self) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetCurrentItem(*args, **kwargs)
+
+ def SetCurrentItem(*args, **kwargs):
+ """SetCurrentItem(self, TreeItemId newItem)"""
+ return _gizmos.TreeListCtrl_SetCurrentItem(*args, **kwargs)
+
+ def GetFirstChild(*args, **kwargs):
+ """GetFirstChild(self, TreeItemId item) -> PyObject"""
+ return _gizmos.TreeListCtrl_GetFirstChild(*args, **kwargs)
+
+ def GetNextChild(*args, **kwargs):
+ """GetNextChild(self, TreeItemId item, void cookie) -> PyObject"""
+ return _gizmos.TreeListCtrl_GetNextChild(*args, **kwargs)
+
+ def GetLastChild(*args, **kwargs):
+ """GetLastChild(self, TreeItemId item) -> PyObject"""
+ return _gizmos.TreeListCtrl_GetLastChild(*args, **kwargs)
+
+ def GetPrevChild(*args, **kwargs):
+ """GetPrevChild(self, TreeItemId item, void cookie) -> PyObject"""
+ return _gizmos.TreeListCtrl_GetPrevChild(*args, **kwargs)
+
+ def GetNextSibling(*args, **kwargs):
+ """GetNextSibling(self, TreeItemId item) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetNextSibling(*args, **kwargs)
+
+ def GetPrevSibling(*args, **kwargs):
+ """GetPrevSibling(self, TreeItemId item) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetPrevSibling(*args, **kwargs)
+
+ def GetNext(*args, **kwargs):
+ """GetNext(self, TreeItemId item) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetNext(*args, **kwargs)
+
+ def GetPrev(*args, **kwargs):
+ """GetPrev(self, TreeItemId item) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetPrev(*args, **kwargs)
+
+ def GetFirstExpandedItem(*args, **kwargs):
+ """GetFirstExpandedItem(self) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetFirstExpandedItem(*args, **kwargs)
+
+ def GetNextExpanded(*args, **kwargs):
+ """GetNextExpanded(self, TreeItemId item) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetNextExpanded(*args, **kwargs)
+
+ def GetPrevExpanded(*args, **kwargs):
+ """GetPrevExpanded(self, TreeItemId item) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetPrevExpanded(*args, **kwargs)
+
+ def GetFirstVisibleItem(*args, **kwargs):
+ """GetFirstVisibleItem(self, bool fullRow=False) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetFirstVisibleItem(*args, **kwargs)
+
+ def GetNextVisible(*args, **kwargs):
+ """GetNextVisible(self, TreeItemId item, bool fullRow=False) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetNextVisible(*args, **kwargs)
+
+ def GetPrevVisible(*args, **kwargs):
+ """GetPrevVisible(self, TreeItemId item, bool fullRow=False) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_GetPrevVisible(*args, **kwargs)
+
+ def AddRoot(*args, **kwargs):
+ """AddRoot(self, String text, int image=-1, int selectedImage=-1, TreeItemData data=None) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_AddRoot(*args, **kwargs)
+
+ def PrependItem(*args, **kwargs):
+ """
+ PrependItem(self, TreeItemId parent, String text, int image=-1, int selectedImage=-1,
+ TreeItemData data=None) -> TreeItemId
+ """
+ return _gizmos.TreeListCtrl_PrependItem(*args, **kwargs)
+
+ def InsertItem(*args, **kwargs):
+ """
+ InsertItem(self, TreeItemId parent, TreeItemId idPrevious, String text,
+ int image=-1, int selectedImage=-1, TreeItemData data=None) -> TreeItemId
+ """
+ return _gizmos.TreeListCtrl_InsertItem(*args, **kwargs)
+
+ def InsertItemBefore(*args, **kwargs):
+ """
+ InsertItemBefore(self, TreeItemId parent, size_t index, String text, int image=-1,
+ int selectedImage=-1, TreeItemData data=None) -> TreeItemId
+ """
+ return _gizmos.TreeListCtrl_InsertItemBefore(*args, **kwargs)
+
+ def AppendItem(*args, **kwargs):
+ """
+ AppendItem(self, TreeItemId parent, String text, int image=-1, int selectedImage=-1,
+ TreeItemData data=None) -> TreeItemId
+ """
+ return _gizmos.TreeListCtrl_AppendItem(*args, **kwargs)
+
+ def Delete(*args, **kwargs):
+ """Delete(self, TreeItemId item)"""
+ return _gizmos.TreeListCtrl_Delete(*args, **kwargs)
+
+ def DeleteChildren(*args, **kwargs):
+ """DeleteChildren(self, TreeItemId item)"""
+ return _gizmos.TreeListCtrl_DeleteChildren(*args, **kwargs)
+
+ def DeleteRoot(*args, **kwargs):
+ """DeleteRoot(self)"""
+ return _gizmos.TreeListCtrl_DeleteRoot(*args, **kwargs)
+
+ DeleteAllItems = DeleteRoot
+ def Expand(*args, **kwargs):
+ """Expand(self, TreeItemId item)"""
+ return _gizmos.TreeListCtrl_Expand(*args, **kwargs)
+
+ def ExpandAll(*args, **kwargs):
+ """ExpandAll(self, TreeItemId item)"""
+ return _gizmos.TreeListCtrl_ExpandAll(*args, **kwargs)
+
+ def Collapse(*args, **kwargs):
+ """Collapse(self, TreeItemId item)"""
+ return _gizmos.TreeListCtrl_Collapse(*args, **kwargs)
+
+ def CollapseAndReset(*args, **kwargs):
+ """CollapseAndReset(self, TreeItemId item)"""
+ return _gizmos.TreeListCtrl_CollapseAndReset(*args, **kwargs)
+
+ def Toggle(*args, **kwargs):
+ """Toggle(self, TreeItemId item)"""
+ return _gizmos.TreeListCtrl_Toggle(*args, **kwargs)
+
+ def Unselect(*args, **kwargs):
+ """Unselect(self)"""
+ return _gizmos.TreeListCtrl_Unselect(*args, **kwargs)
+
+ def UnselectAll(*args, **kwargs):
+ """UnselectAll(self)"""
+ return _gizmos.TreeListCtrl_UnselectAll(*args, **kwargs)
+
+ def SelectItem(*args, **kwargs):
+ """SelectItem(self, TreeItemId item, TreeItemId last=wxTreeItemId(), bool unselect_others=True)"""
+ return _gizmos.TreeListCtrl_SelectItem(*args, **kwargs)
+
+ def SelectAll(*args, **kwargs):
+ """SelectAll(self)"""
+ return _gizmos.TreeListCtrl_SelectAll(*args, **kwargs)
+
+ def EnsureVisible(*args, **kwargs):
+ """EnsureVisible(self, TreeItemId item)"""
+ return _gizmos.TreeListCtrl_EnsureVisible(*args, **kwargs)
+
+ def ScrollTo(*args, **kwargs):
+ """ScrollTo(self, TreeItemId item)"""
+ return _gizmos.TreeListCtrl_ScrollTo(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """HitTest(self, Point point, int OUTPUT, int OUTPUT) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_HitTest(*args, **kwargs)
+
+ def GetBoundingRect(*args, **kwargs):
+ """GetBoundingRect(self, TreeItemId item, bool textOnly=False) -> PyObject"""
+ return _gizmos.TreeListCtrl_GetBoundingRect(*args, **kwargs)
+
+ def EditLabel(*args, **kwargs):
+ """EditLabel(self, TreeItemId item, int column=-1)"""
+ return _gizmos.TreeListCtrl_EditLabel(*args, **kwargs)
+
+ Edit = EditLabel
+ def SortChildren(*args, **kwargs):
+ """SortChildren(self, TreeItemId item)"""
+ return _gizmos.TreeListCtrl_SortChildren(*args, **kwargs)
+
+ def FindItem(*args, **kwargs):
+ """FindItem(self, TreeItemId item, String str, int flags=0) -> TreeItemId"""
+ return _gizmos.TreeListCtrl_FindItem(*args, **kwargs)
+
+ def SetDragItem(*args, **kwargs):
+ """SetDragItem(self, TreeItemId item=(wxTreeItemId *) NULL)"""
+ return _gizmos.TreeListCtrl_SetDragItem(*args, **kwargs)
+
+ def GetHeaderWindow(*args, **kwargs):
+ """GetHeaderWindow(self) -> Window"""
+ return _gizmos.TreeListCtrl_GetHeaderWindow(*args, **kwargs)
+
+ def GetMainWindow(*args, **kwargs):
+ """GetMainWindow(self) -> ScrolledWindow"""
+ return _gizmos.TreeListCtrl_GetMainWindow(*args, **kwargs)
+
+ ButtonsImageList = property(GetButtonsImageList,SetButtonsImageList,doc="See `GetButtonsImageList` and `SetButtonsImageList`")
+ ColumnCount = property(GetColumnCount,doc="See `GetColumnCount`")
+ Count = property(GetCount,doc="See `GetCount`")
+ HeaderWindow = property(GetHeaderWindow,doc="See `GetHeaderWindow`")
+ ImageList = property(GetImageList,SetImageList,doc="See `GetImageList` and `SetImageList`")
+ Indent = property(GetIndent,SetIndent,doc="See `GetIndent` and `SetIndent`")
+ LineSpacing = property(GetLineSpacing,SetLineSpacing,doc="See `GetLineSpacing` and `SetLineSpacing`")
+ MainColumn = property(GetMainColumn,SetMainColumn,doc="See `GetMainColumn` and `SetMainColumn`")
+ MainWindow = property(GetMainWindow,doc="See `GetMainWindow`")
+ Next = property(GetNext,doc="See `GetNext`")
+ RootItem = property(GetRootItem,doc="See `GetRootItem`")
+ Selection = property(GetSelection,doc="See `GetSelection`")
+ Selections = property(GetSelections,doc="See `GetSelections`")
+ StateImageList = property(GetStateImageList,SetStateImageList,doc="See `GetStateImageList` and `SetStateImageList`")
+ CurrentItem = property(GetCurrentItem,SetCurrentItem)
+_gizmos.TreeListCtrl_swigregister(TreeListCtrl)
+
+def PreTreeListCtrl(*args, **kwargs):
+ """PreTreeListCtrl() -> TreeListCtrl"""
+ val = _gizmos.new_PreTreeListCtrl(*args, **kwargs)
+ return val
+
+SCALE_HORIZONTAL = _gizmos.SCALE_HORIZONTAL
+SCALE_VERTICAL = _gizmos.SCALE_VERTICAL
+SCALE_UNIFORM = _gizmos.SCALE_UNIFORM
+SCALE_CUSTOM = _gizmos.SCALE_CUSTOM
+class StaticPicture(_core.Control):
+ """Proxy of C++ StaticPicture class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Bitmap label=wxNullBitmap,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=StaticPictureNameStr) -> StaticPicture
+ """
+ _gizmos.StaticPicture_swiginit(self,_gizmos.new_StaticPicture(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Bitmap label=wxNullBitmap,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=StaticPictureNameStr) -> bool
+ """
+ return _gizmos.StaticPicture_Create(*args, **kwargs)
+
+ def SetBitmap(*args, **kwargs):
+ """SetBitmap(self, Bitmap bmp)"""
+ return _gizmos.StaticPicture_SetBitmap(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self) -> Bitmap"""
+ return _gizmos.StaticPicture_GetBitmap(*args, **kwargs)
+
+ def SetIcon(*args, **kwargs):
+ """SetIcon(self, Icon icon)"""
+ return _gizmos.StaticPicture_SetIcon(*args, **kwargs)
+
+ def GetIcon(*args, **kwargs):
+ """GetIcon(self) -> Icon"""
+ return _gizmos.StaticPicture_GetIcon(*args, **kwargs)
+
+ def SetAlignment(*args, **kwargs):
+ """SetAlignment(self, int align)"""
+ return _gizmos.StaticPicture_SetAlignment(*args, **kwargs)
+
+ def GetAlignment(*args, **kwargs):
+ """
+ GetAlignment(self) -> int
+
+ Get the control alignment (left/right/centre, top/bottom/centre)
+ """
+ return _gizmos.StaticPicture_GetAlignment(*args, **kwargs)
+
+ def SetScale(*args, **kwargs):
+ """SetScale(self, int scale)"""
+ return _gizmos.StaticPicture_SetScale(*args, **kwargs)
+
+ def GetScale(*args, **kwargs):
+ """GetScale(self) -> int"""
+ return _gizmos.StaticPicture_GetScale(*args, **kwargs)
+
+ def SetCustomScale(*args, **kwargs):
+ """SetCustomScale(self, float sx, float sy)"""
+ return _gizmos.StaticPicture_SetCustomScale(*args, **kwargs)
+
+ def GetCustomScale(*args, **kwargs):
+ """GetCustomScale(self, float OUTPUT, float OUTPUT)"""
+ return _gizmos.StaticPicture_GetCustomScale(*args, **kwargs)
+
+ Alignment = property(GetAlignment,SetAlignment,doc="See `GetAlignment` and `SetAlignment`")
+ Bitmap = property(GetBitmap,SetBitmap,doc="See `GetBitmap` and `SetBitmap`")
+ Icon = property(GetIcon,SetIcon,doc="See `GetIcon` and `SetIcon`")
+ Scale = property(GetScale,SetScale,doc="See `GetScale` and `SetScale`")
+_gizmos.StaticPicture_swigregister(StaticPicture)
+
+def PreStaticPicture(*args, **kwargs):
+ """PreStaticPicture() -> StaticPicture"""
+ val = _gizmos.new_PreStaticPicture(*args, **kwargs)
+ return val
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/glcanvas.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/glcanvas.py
new file mode 100644
index 0000000..ddaa4b8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/glcanvas.py
@@ -0,0 +1,183 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+`GLCanvas` provides an OpenGL Context on a `wx.Window`.
+"""
+
+import _glcanvas
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+class GLContext(_core.Object):
+ """Proxy of C++ GLContext class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, GLCanvas win, GLContext other=None) -> GLContext"""
+ _glcanvas.GLContext_swiginit(self,_glcanvas.new_GLContext(*args, **kwargs))
+ __swig_destroy__ = _glcanvas.delete_GLContext
+ __del__ = lambda self : None;
+ def SetCurrent(*args, **kwargs):
+ """SetCurrent(self, GLCanvas win) -> bool"""
+ return _glcanvas.GLContext_SetCurrent(*args, **kwargs)
+
+_glcanvas.GLContext_swigregister(GLContext)
+cvar = _glcanvas.cvar
+GLCanvasNameStr = cvar.GLCanvasNameStr
+
+WX_GL_RGBA = _glcanvas.WX_GL_RGBA
+WX_GL_BUFFER_SIZE = _glcanvas.WX_GL_BUFFER_SIZE
+WX_GL_LEVEL = _glcanvas.WX_GL_LEVEL
+WX_GL_DOUBLEBUFFER = _glcanvas.WX_GL_DOUBLEBUFFER
+WX_GL_STEREO = _glcanvas.WX_GL_STEREO
+WX_GL_AUX_BUFFERS = _glcanvas.WX_GL_AUX_BUFFERS
+WX_GL_MIN_RED = _glcanvas.WX_GL_MIN_RED
+WX_GL_MIN_GREEN = _glcanvas.WX_GL_MIN_GREEN
+WX_GL_MIN_BLUE = _glcanvas.WX_GL_MIN_BLUE
+WX_GL_MIN_ALPHA = _glcanvas.WX_GL_MIN_ALPHA
+WX_GL_DEPTH_SIZE = _glcanvas.WX_GL_DEPTH_SIZE
+WX_GL_STENCIL_SIZE = _glcanvas.WX_GL_STENCIL_SIZE
+WX_GL_MIN_ACCUM_RED = _glcanvas.WX_GL_MIN_ACCUM_RED
+WX_GL_MIN_ACCUM_GREEN = _glcanvas.WX_GL_MIN_ACCUM_GREEN
+WX_GL_MIN_ACCUM_BLUE = _glcanvas.WX_GL_MIN_ACCUM_BLUE
+WX_GL_MIN_ACCUM_ALPHA = _glcanvas.WX_GL_MIN_ACCUM_ALPHA
+WX_GL_SAMPLE_BUFFERS = _glcanvas.WX_GL_SAMPLE_BUFFERS
+WX_GL_SAMPLES = _glcanvas.WX_GL_SAMPLES
+class GLCanvas(_core.Window):
+ """Proxy of C++ GLCanvas class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, int attribList=None, Point pos=DefaultPosition,
+ Size size=DefaultSize,
+ long style=0, String name=GLCanvasNameStr, Palette palette=wxNullPalette) -> GLCanvas
+ """
+ _glcanvas.GLCanvas_swiginit(self,_glcanvas.new_GLCanvas(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=wxGLCanvasName,
+ int attribList=None,
+ Palette palette=wxNullPalette) -> bool
+ """
+ return _glcanvas.GLCanvas_Create(*args, **kwargs)
+
+ def SetColour(*args, **kwargs):
+ """SetColour(self, String colour)"""
+ return _glcanvas.GLCanvas_SetColour(*args, **kwargs)
+
+ def SwapBuffers(*args, **kwargs):
+ """SwapBuffers(self) -> bool"""
+ return _glcanvas.GLCanvas_SwapBuffers(*args, **kwargs)
+
+ def IsExtensionSupported(*args, **kwargs):
+ """IsExtensionSupported(char extension) -> bool"""
+ return _glcanvas.GLCanvas_IsExtensionSupported(*args, **kwargs)
+
+ IsExtensionSupported = staticmethod(IsExtensionSupported)
+ def GetContext(*args, **kwargs):
+ """GetContext(self) -> GLContext"""
+ return _glcanvas.GLCanvas_GetContext(*args, **kwargs)
+
+ def SetCurrent(*args):
+ """
+ SetCurrent(self, GLContext context) -> bool
+ SetCurrent(self)
+ """
+ return _glcanvas.GLCanvas_SetCurrent(*args)
+
+ def SetupPalette(*args, **kwargs):
+ """SetupPalette(self, Palette palette)"""
+ return _glcanvas.GLCanvas_SetupPalette(*args, **kwargs)
+
+ def CreateDefaultPalette(*args, **kwargs):
+ """CreateDefaultPalette(self) -> Palette"""
+ return _glcanvas.GLCanvas_CreateDefaultPalette(*args, **kwargs)
+
+ def GetPalette(*args, **kwargs):
+ """GetPalette(self) -> Palette"""
+ return _glcanvas.GLCanvas_GetPalette(*args, **kwargs)
+
+ def IsDisplaySupported(*args, **kwargs):
+ """IsDisplaySupported(int attribList) -> bool"""
+ return _glcanvas.GLCanvas_IsDisplaySupported(*args, **kwargs)
+
+ IsDisplaySupported = staticmethod(IsDisplaySupported)
+ Context = property(GetContext)
+ Palette = property(GetPalette)
+_glcanvas.GLCanvas_swigregister(GLCanvas)
+
+def GLCanvasWithContext(*args, **kwargs):
+ """
+ GLCanvasWithContext(Window parent, GLContext shared=None, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize,
+ long style=0, String name=GLCanvasNameStr,
+ int attribList=None, Palette palette=wxNullPalette) -> GLCanvas
+ """
+ val = _glcanvas.new_GLCanvasWithContext(*args, **kwargs)
+ val._setOORInfo(val)
+ return val
+
+def GLCanvas_IsExtensionSupported(*args, **kwargs):
+ """GLCanvas_IsExtensionSupported(char extension) -> bool"""
+ return _glcanvas.GLCanvas_IsExtensionSupported(*args, **kwargs)
+
+def GLCanvas_IsDisplaySupported(*args, **kwargs):
+ """GLCanvas_IsDisplaySupported(int attribList) -> bool"""
+ return _glcanvas.GLCanvas_IsDisplaySupported(*args, **kwargs)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/grid.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/grid.py
new file mode 100644
index 0000000..34ebb79
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/grid.py
@@ -0,0 +1,2564 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+Classes for implementing a spreadsheet-like control.
+"""
+
+import _grid
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _windows
+import _core
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+GRID_VALUE_STRING = _grid.GRID_VALUE_STRING
+GRID_VALUE_BOOL = _grid.GRID_VALUE_BOOL
+GRID_VALUE_NUMBER = _grid.GRID_VALUE_NUMBER
+GRID_VALUE_FLOAT = _grid.GRID_VALUE_FLOAT
+GRID_VALUE_CHOICE = _grid.GRID_VALUE_CHOICE
+GRID_VALUE_TEXT = _grid.GRID_VALUE_TEXT
+GRID_VALUE_LONG = _grid.GRID_VALUE_LONG
+GRID_VALUE_CHOICEINT = _grid.GRID_VALUE_CHOICEINT
+GRID_VALUE_DATETIME = _grid.GRID_VALUE_DATETIME
+GRID_AUTOSIZE = _grid.GRID_AUTOSIZE
+GRID_COLUMN = _grid.GRID_COLUMN
+GRID_ROW = _grid.GRID_ROW
+GRID_DEFAULT_NUMBER_ROWS = _grid.GRID_DEFAULT_NUMBER_ROWS
+GRID_DEFAULT_NUMBER_COLS = _grid.GRID_DEFAULT_NUMBER_COLS
+GRID_DEFAULT_ROW_HEIGHT = _grid.GRID_DEFAULT_ROW_HEIGHT
+GRID_DEFAULT_COL_WIDTH = _grid.GRID_DEFAULT_COL_WIDTH
+GRID_DEFAULT_COL_LABEL_HEIGHT = _grid.GRID_DEFAULT_COL_LABEL_HEIGHT
+GRID_DEFAULT_ROW_LABEL_WIDTH = _grid.GRID_DEFAULT_ROW_LABEL_WIDTH
+GRID_LABEL_EDGE_ZONE = _grid.GRID_LABEL_EDGE_ZONE
+GRID_MIN_ROW_HEIGHT = _grid.GRID_MIN_ROW_HEIGHT
+GRID_MIN_COL_WIDTH = _grid.GRID_MIN_COL_WIDTH
+GRID_DEFAULT_SCROLLBAR_WIDTH = _grid.GRID_DEFAULT_SCROLLBAR_WIDTH
+class GridCellWorker(_core.RefCounter):
+ """Proxy of C++ GridCellWorker class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def _setOORInfo(*args, **kwargs):
+ """_setOORInfo(self, PyObject _self)"""
+ return _grid.GridCellWorker__setOORInfo(*args, **kwargs)
+
+ __swig_destroy__ = _grid.delete_GridCellWorker
+ __del__ = lambda self : None;
+ def SetParameters(*args, **kwargs):
+ """SetParameters(self, String params)"""
+ return _grid.GridCellWorker_SetParameters(*args, **kwargs)
+
+_grid.GridCellWorker_swigregister(GridCellWorker)
+cvar = _grid.cvar
+GridNoCellCoords = cvar.GridNoCellCoords
+GridNoCellRect = cvar.GridNoCellRect
+
+class GridCellRenderer(GridCellWorker):
+ """Proxy of C++ GridCellRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Draw(*args, **kwargs):
+ """
+ Draw(self, Grid grid, GridCellAttr attr, DC dc, Rect rect, int row,
+ int col, bool isSelected)
+ """
+ return _grid.GridCellRenderer_Draw(*args, **kwargs)
+
+ def GetBestSize(*args, **kwargs):
+ """GetBestSize(self, Grid grid, GridCellAttr attr, DC dc, int row, int col) -> Size"""
+ return _grid.GridCellRenderer_GetBestSize(*args, **kwargs)
+
+ def Clone(*args, **kwargs):
+ """Clone(self) -> GridCellRenderer"""
+ return _grid.GridCellRenderer_Clone(*args, **kwargs)
+
+_grid.GridCellRenderer_swigregister(GridCellRenderer)
+
+class PyGridCellRenderer(GridCellRenderer):
+ """Proxy of C++ PyGridCellRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyGridCellRenderer"""
+ _grid.PyGridCellRenderer_swiginit(self,_grid.new_PyGridCellRenderer(*args, **kwargs))
+ self._setOORInfo(self);PyGridCellRenderer._setCallbackInfo(self, self, PyGridCellRenderer)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _grid.PyGridCellRenderer__setCallbackInfo(*args, **kwargs)
+
+ def SetParameters(*args, **kwargs):
+ """SetParameters(self, String params)"""
+ return _grid.PyGridCellRenderer_SetParameters(*args, **kwargs)
+
+ def base_SetParameters(*args, **kw):
+ return PyGridCellRenderer.SetParameters(*args, **kw)
+ base_SetParameters = wx.deprecated(base_SetParameters,
+ "Please use PyGridCellRenderer.SetParameters instead.")
+
+_grid.PyGridCellRenderer_swigregister(PyGridCellRenderer)
+
+class GridCellStringRenderer(GridCellRenderer):
+ """Proxy of C++ GridCellStringRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GridCellStringRenderer"""
+ _grid.GridCellStringRenderer_swiginit(self,_grid.new_GridCellStringRenderer(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellStringRenderer_swigregister(GridCellStringRenderer)
+
+class GridCellNumberRenderer(GridCellStringRenderer):
+ """Proxy of C++ GridCellNumberRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GridCellNumberRenderer"""
+ _grid.GridCellNumberRenderer_swiginit(self,_grid.new_GridCellNumberRenderer(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellNumberRenderer_swigregister(GridCellNumberRenderer)
+
+GRID_FLOAT_FORMAT_FIXED = _grid.GRID_FLOAT_FORMAT_FIXED
+GRID_FLOAT_FORMAT_SCIENTIFIC = _grid.GRID_FLOAT_FORMAT_SCIENTIFIC
+GRID_FLOAT_FORMAT_COMPACT = _grid.GRID_FLOAT_FORMAT_COMPACT
+GRID_FLOAT_FORMAT_UPPER = _grid.GRID_FLOAT_FORMAT_UPPER
+GRID_FLOAT_FORMAT_DEFAULT = _grid.GRID_FLOAT_FORMAT_DEFAULT
+GRID_FLOAT_FORMAT_MASK = _grid.GRID_FLOAT_FORMAT_MASK
+class GridCellFloatRenderer(GridCellStringRenderer):
+ """Proxy of C++ GridCellFloatRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int width=-1, int precision=-1, int format=GRID_FLOAT_FORMAT_DEFAULT) -> GridCellFloatRenderer"""
+ _grid.GridCellFloatRenderer_swiginit(self,_grid.new_GridCellFloatRenderer(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _grid.GridCellFloatRenderer_GetWidth(*args, **kwargs)
+
+ def SetWidth(*args, **kwargs):
+ """SetWidth(self, int width)"""
+ return _grid.GridCellFloatRenderer_SetWidth(*args, **kwargs)
+
+ def GetPrecision(*args, **kwargs):
+ """GetPrecision(self) -> int"""
+ return _grid.GridCellFloatRenderer_GetPrecision(*args, **kwargs)
+
+ def SetPrecision(*args, **kwargs):
+ """SetPrecision(self, int precision)"""
+ return _grid.GridCellFloatRenderer_SetPrecision(*args, **kwargs)
+
+ def GetFormat(*args, **kwargs):
+ """GetFormat(self) -> int"""
+ return _grid.GridCellFloatRenderer_GetFormat(*args, **kwargs)
+
+ def SetFormat(*args, **kwargs):
+ """SetFormat(self, int format)"""
+ return _grid.GridCellFloatRenderer_SetFormat(*args, **kwargs)
+
+ Precision = property(GetPrecision,SetPrecision,doc="See `GetPrecision` and `SetPrecision`")
+ Width = property(GetWidth,SetWidth,doc="See `GetWidth` and `SetWidth`")
+_grid.GridCellFloatRenderer_swigregister(GridCellFloatRenderer)
+
+class GridCellBoolRenderer(GridCellRenderer):
+ """Proxy of C++ GridCellBoolRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GridCellBoolRenderer"""
+ _grid.GridCellBoolRenderer_swiginit(self,_grid.new_GridCellBoolRenderer(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellBoolRenderer_swigregister(GridCellBoolRenderer)
+
+class GridCellDateTimeRenderer(GridCellStringRenderer):
+ """Proxy of C++ GridCellDateTimeRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String outformat=wxPyDefaultDateTimeFormat, String informat=wxPyDefaultDateTimeFormat) -> GridCellDateTimeRenderer"""
+ _grid.GridCellDateTimeRenderer_swiginit(self,_grid.new_GridCellDateTimeRenderer(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellDateTimeRenderer_swigregister(GridCellDateTimeRenderer)
+
+class GridCellEnumRenderer(GridCellStringRenderer):
+ """Proxy of C++ GridCellEnumRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String choices=EmptyString) -> GridCellEnumRenderer"""
+ _grid.GridCellEnumRenderer_swiginit(self,_grid.new_GridCellEnumRenderer(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellEnumRenderer_swigregister(GridCellEnumRenderer)
+
+class GridCellAutoWrapStringRenderer(GridCellStringRenderer):
+ """Proxy of C++ GridCellAutoWrapStringRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GridCellAutoWrapStringRenderer"""
+ _grid.GridCellAutoWrapStringRenderer_swiginit(self,_grid.new_GridCellAutoWrapStringRenderer(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellAutoWrapStringRenderer_swigregister(GridCellAutoWrapStringRenderer)
+
+class GridCellEditor(GridCellWorker):
+ """Proxy of C++ GridCellEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def IsCreated(*args, **kwargs):
+ """IsCreated(self) -> bool"""
+ return _grid.GridCellEditor_IsCreated(*args, **kwargs)
+
+ def GetControl(*args, **kwargs):
+ """GetControl(self) -> Control"""
+ return _grid.GridCellEditor_GetControl(*args, **kwargs)
+
+ def SetControl(*args, **kwargs):
+ """SetControl(self, Control control)"""
+ return _grid.GridCellEditor_SetControl(*args, **kwargs)
+
+ def GetCellAttr(*args, **kwargs):
+ """GetCellAttr(self) -> GridCellAttr"""
+ return _grid.GridCellEditor_GetCellAttr(*args, **kwargs)
+
+ def SetCellAttr(*args, **kwargs):
+ """SetCellAttr(self, GridCellAttr attr)"""
+ return _grid.GridCellEditor_SetCellAttr(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """Create(self, Window parent, int id, EvtHandler evtHandler)"""
+ return _grid.GridCellEditor_Create(*args, **kwargs)
+
+ def BeginEdit(*args, **kwargs):
+ """BeginEdit(self, int row, int col, Grid grid)"""
+ return _grid.GridCellEditor_BeginEdit(*args, **kwargs)
+
+ def EndEdit(*args, **kwargs):
+ """EndEdit(self, int row, int col, Grid grid, String oldval, String newval) -> bool"""
+ return _grid.GridCellEditor_EndEdit(*args, **kwargs)
+
+ def ApplyEdit(*args, **kwargs):
+ """ApplyEdit(self, int row, int col, Grid grid)"""
+ return _grid.GridCellEditor_ApplyEdit(*args, **kwargs)
+
+ def Reset(*args, **kwargs):
+ """Reset(self)"""
+ return _grid.GridCellEditor_Reset(*args, **kwargs)
+
+ def Clone(*args, **kwargs):
+ """Clone(self) -> GridCellEditor"""
+ return _grid.GridCellEditor_Clone(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, Rect rect)"""
+ return _grid.GridCellEditor_SetSize(*args, **kwargs)
+
+ def Show(*args, **kwargs):
+ """Show(self, bool show, GridCellAttr attr=None)"""
+ return _grid.GridCellEditor_Show(*args, **kwargs)
+
+ def PaintBackground(*args, **kwargs):
+ """PaintBackground(self, DC dc, Rect rectCell, GridCellAttr attr)"""
+ return _grid.GridCellEditor_PaintBackground(*args, **kwargs)
+
+ def IsAcceptedKey(*args, **kwargs):
+ """IsAcceptedKey(self, KeyEvent event) -> bool"""
+ return _grid.GridCellEditor_IsAcceptedKey(*args, **kwargs)
+
+ def StartingKey(*args, **kwargs):
+ """StartingKey(self, KeyEvent event)"""
+ return _grid.GridCellEditor_StartingKey(*args, **kwargs)
+
+ def StartingClick(*args, **kwargs):
+ """StartingClick(self)"""
+ return _grid.GridCellEditor_StartingClick(*args, **kwargs)
+
+ def HandleReturn(*args, **kwargs):
+ """HandleReturn(self, KeyEvent event)"""
+ return _grid.GridCellEditor_HandleReturn(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """Destroy(self)"""
+ args[0].this.own(False)
+ return _grid.GridCellEditor_Destroy(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> String"""
+ return _grid.GridCellEditor_GetValue(*args, **kwargs)
+
+ CellAttr = property(GetCellAttr,SetCellAttr,doc="See `GetCellAttr` and `SetCellAttr`")
+ Control = property(GetControl,SetControl,doc="See `GetControl` and `SetControl`")
+_grid.GridCellEditor_swigregister(GridCellEditor)
+
+class PyGridCellEditor(GridCellEditor):
+ """Proxy of C++ PyGridCellEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyGridCellEditor"""
+ _grid.PyGridCellEditor_swiginit(self,_grid.new_PyGridCellEditor(*args, **kwargs))
+ self._setOORInfo(self);PyGridCellEditor._setCallbackInfo(self, self, PyGridCellEditor)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _grid.PyGridCellEditor__setCallbackInfo(*args, **kwargs)
+
+ def SetParameters(*args, **kwargs):
+ """SetParameters(self, String params)"""
+ return _grid.PyGridCellEditor_SetParameters(*args, **kwargs)
+
+ def base_SetSize(*args, **kw):
+ return PyGridCellEditor.SetSize(*args, **kw)
+ base_SetSize = wx.deprecated(base_SetSize,
+ "Please use PyGridCellEditor.SetSize instead.")
+
+ def base_Show(*args, **kw):
+ return PyGridCellEditor.Show(*args, **kw)
+ base_Show = wx.deprecated(base_Show,
+ "Please use PyGridCellEditor.Show instead.")
+
+ def base_PaintBackground(*args, **kw):
+ return PyGridCellEditor.PaintBackground(*args, **kw)
+ base_PaintBackground = wx.deprecated(base_PaintBackground,
+ "Please use PyGridCellEditor.PaintBackground instead.")
+
+ def base_IsAcceptedKey(*args, **kw):
+ return PyGridCellEditor.IsAcceptedKey(*args, **kw)
+ base_IsAcceptedKey = wx.deprecated(base_IsAcceptedKey,
+ "Please use PyGridCellEditor.IsAcceptedKey instead.")
+
+ def base_StartingKey(*args, **kw):
+ return PyGridCellEditor.StartingKey(*args, **kw)
+ base_StartingKey = wx.deprecated(base_StartingKey,
+ "Please use PyGridCellEditor.StartingKey instead.")
+
+ def base_StartingClick(*args, **kw):
+ return PyGridCellEditor.StartingClick(*args, **kw)
+ base_StartingClick = wx.deprecated(base_StartingClick,
+ "Please use PyGridCellEditor.StartingClick instead.")
+
+ def base_HandleReturn(*args, **kw):
+ return PyGridCellEditor.HandleReturn(*args, **kw)
+ base_HandleReturn = wx.deprecated(base_HandleReturn,
+ "Please use PyGridCellEditor.HandleReturn instead.")
+
+ def base_Destroy(*args, **kw):
+ return PyGridCellEditor.Destroy(*args, **kw)
+ base_Destroy = wx.deprecated(base_Destroy,
+ "Please use PyGridCellEditor.Destroy instead.")
+
+ def base_SetParameters(*args, **kw):
+ return PyGridCellEditor.SetParameters(*args, **kw)
+ base_SetParameters = wx.deprecated(base_SetParameters,
+ "Please use PyGridCellEditor.SetParameters instead.")
+
+_grid.PyGridCellEditor_swigregister(PyGridCellEditor)
+
+class GridCellTextEditor(GridCellEditor):
+ """Proxy of C++ GridCellTextEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GridCellTextEditor"""
+ _grid.GridCellTextEditor_swiginit(self,_grid.new_GridCellTextEditor(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> String"""
+ return _grid.GridCellTextEditor_GetValue(*args, **kwargs)
+
+ Value = property(GetValue,doc="See `GetValue`")
+_grid.GridCellTextEditor_swigregister(GridCellTextEditor)
+
+class GridCellNumberEditor(GridCellTextEditor):
+ """Proxy of C++ GridCellNumberEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int min=-1, int max=-1) -> GridCellNumberEditor"""
+ _grid.GridCellNumberEditor_swiginit(self,_grid.new_GridCellNumberEditor(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellNumberEditor_swigregister(GridCellNumberEditor)
+
+class GridCellFloatEditor(GridCellTextEditor):
+ """Proxy of C++ GridCellFloatEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int width=-1, int precision=-1, int format=GRID_FLOAT_FORMAT_DEFAULT) -> GridCellFloatEditor"""
+ _grid.GridCellFloatEditor_swiginit(self,_grid.new_GridCellFloatEditor(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellFloatEditor_swigregister(GridCellFloatEditor)
+
+class GridCellBoolEditor(GridCellEditor):
+ """Proxy of C++ GridCellBoolEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GridCellBoolEditor"""
+ _grid.GridCellBoolEditor_swiginit(self,_grid.new_GridCellBoolEditor(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def UseStringValues(*args, **kwargs):
+ """UseStringValues(String valueTrue=OneString, String valueFalse=EmptyString)"""
+ return _grid.GridCellBoolEditor_UseStringValues(*args, **kwargs)
+
+ UseStringValues = staticmethod(UseStringValues)
+ def IsTrueValue(*args, **kwargs):
+ """IsTrueValue(String value) -> bool"""
+ return _grid.GridCellBoolEditor_IsTrueValue(*args, **kwargs)
+
+ IsTrueValue = staticmethod(IsTrueValue)
+_grid.GridCellBoolEditor_swigregister(GridCellBoolEditor)
+OneString = cvar.OneString
+
+def GridCellBoolEditor_UseStringValues(*args, **kwargs):
+ """GridCellBoolEditor_UseStringValues(String valueTrue=OneString, String valueFalse=EmptyString)"""
+ return _grid.GridCellBoolEditor_UseStringValues(*args, **kwargs)
+
+def GridCellBoolEditor_IsTrueValue(*args, **kwargs):
+ """GridCellBoolEditor_IsTrueValue(String value) -> bool"""
+ return _grid.GridCellBoolEditor_IsTrueValue(*args, **kwargs)
+
+class GridCellChoiceEditor(GridCellEditor):
+ """Proxy of C++ GridCellChoiceEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int choices=0, bool allowOthers=False) -> GridCellChoiceEditor"""
+ _grid.GridCellChoiceEditor_swiginit(self,_grid.new_GridCellChoiceEditor(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellChoiceEditor_swigregister(GridCellChoiceEditor)
+
+class GridCellEnumEditor(GridCellChoiceEditor):
+ """Proxy of C++ GridCellEnumEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String choices=EmptyString) -> GridCellEnumEditor"""
+ _grid.GridCellEnumEditor_swiginit(self,_grid.new_GridCellEnumEditor(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellEnumEditor_swigregister(GridCellEnumEditor)
+
+class GridCellAutoWrapStringEditor(GridCellTextEditor):
+ """Proxy of C++ GridCellAutoWrapStringEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GridCellAutoWrapStringEditor"""
+ _grid.GridCellAutoWrapStringEditor_swiginit(self,_grid.new_GridCellAutoWrapStringEditor(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridCellAutoWrapStringEditor_swigregister(GridCellAutoWrapStringEditor)
+
+class GridCellAttr(_core.RefCounter):
+ """Proxy of C++ GridCellAttr class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ Any = _grid.GridCellAttr_Any
+ Default = _grid.GridCellAttr_Default
+ Cell = _grid.GridCellAttr_Cell
+ Row = _grid.GridCellAttr_Row
+ Col = _grid.GridCellAttr_Col
+ Merged = _grid.GridCellAttr_Merged
+ def _setOORInfo(*args, **kwargs):
+ """_setOORInfo(self, PyObject _self)"""
+ return _grid.GridCellAttr__setOORInfo(*args, **kwargs)
+
+ def __init__(self, *args, **kwargs):
+ """__init__(self, GridCellAttr attrDefault=None) -> GridCellAttr"""
+ _grid.GridCellAttr_swiginit(self,_grid.new_GridCellAttr(*args, **kwargs))
+ self._setOORInfo(self)
+
+ __swig_destroy__ = _grid.delete_GridCellAttr
+ __del__ = lambda self : None;
+ def Clone(*args, **kwargs):
+ """Clone(self) -> GridCellAttr"""
+ return _grid.GridCellAttr_Clone(*args, **kwargs)
+
+ def MergeWith(*args, **kwargs):
+ """MergeWith(self, GridCellAttr mergefrom)"""
+ return _grid.GridCellAttr_MergeWith(*args, **kwargs)
+
+ def SetTextColour(*args, **kwargs):
+ """SetTextColour(self, Colour colText)"""
+ return _grid.GridCellAttr_SetTextColour(*args, **kwargs)
+
+ def SetBackgroundColour(*args, **kwargs):
+ """SetBackgroundColour(self, Colour colBack)"""
+ return _grid.GridCellAttr_SetBackgroundColour(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """SetFont(self, Font font)"""
+ return _grid.GridCellAttr_SetFont(*args, **kwargs)
+
+ def SetAlignment(*args, **kwargs):
+ """SetAlignment(self, int hAlign, int vAlign)"""
+ return _grid.GridCellAttr_SetAlignment(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, int num_rows, int num_cols)"""
+ return _grid.GridCellAttr_SetSize(*args, **kwargs)
+
+ def SetOverflow(*args, **kwargs):
+ """SetOverflow(self, bool allow=True)"""
+ return _grid.GridCellAttr_SetOverflow(*args, **kwargs)
+
+ def SetReadOnly(*args, **kwargs):
+ """SetReadOnly(self, bool isReadOnly=True)"""
+ return _grid.GridCellAttr_SetReadOnly(*args, **kwargs)
+
+ def SetRenderer(*args, **kwargs):
+ """SetRenderer(self, GridCellRenderer renderer)"""
+ return _grid.GridCellAttr_SetRenderer(*args, **kwargs)
+
+ def SetEditor(*args, **kwargs):
+ """SetEditor(self, GridCellEditor editor)"""
+ return _grid.GridCellAttr_SetEditor(*args, **kwargs)
+
+ def SetKind(*args, **kwargs):
+ """SetKind(self, int kind)"""
+ return _grid.GridCellAttr_SetKind(*args, **kwargs)
+
+ def HasTextColour(*args, **kwargs):
+ """HasTextColour(self) -> bool"""
+ return _grid.GridCellAttr_HasTextColour(*args, **kwargs)
+
+ def HasBackgroundColour(*args, **kwargs):
+ """HasBackgroundColour(self) -> bool"""
+ return _grid.GridCellAttr_HasBackgroundColour(*args, **kwargs)
+
+ def HasFont(*args, **kwargs):
+ """HasFont(self) -> bool"""
+ return _grid.GridCellAttr_HasFont(*args, **kwargs)
+
+ def HasAlignment(*args, **kwargs):
+ """HasAlignment(self) -> bool"""
+ return _grid.GridCellAttr_HasAlignment(*args, **kwargs)
+
+ def HasRenderer(*args, **kwargs):
+ """HasRenderer(self) -> bool"""
+ return _grid.GridCellAttr_HasRenderer(*args, **kwargs)
+
+ def HasEditor(*args, **kwargs):
+ """HasEditor(self) -> bool"""
+ return _grid.GridCellAttr_HasEditor(*args, **kwargs)
+
+ def HasReadWriteMode(*args, **kwargs):
+ """HasReadWriteMode(self) -> bool"""
+ return _grid.GridCellAttr_HasReadWriteMode(*args, **kwargs)
+
+ def HasOverflowMode(*args, **kwargs):
+ """HasOverflowMode(self) -> bool"""
+ return _grid.GridCellAttr_HasOverflowMode(*args, **kwargs)
+
+ def GetTextColour(*args, **kwargs):
+ """GetTextColour(self) -> Colour"""
+ return _grid.GridCellAttr_GetTextColour(*args, **kwargs)
+
+ def GetBackgroundColour(*args, **kwargs):
+ """GetBackgroundColour(self) -> Colour"""
+ return _grid.GridCellAttr_GetBackgroundColour(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """GetFont(self) -> Font"""
+ return _grid.GridCellAttr_GetFont(*args, **kwargs)
+
+ def GetAlignment(*args, **kwargs):
+ """GetAlignment() -> (hAlign, vAlign)"""
+ return _grid.GridCellAttr_GetAlignment(*args, **kwargs)
+
+ def GetNonDefaultAlignment(*args, **kwargs):
+ """GetNonDefaultAlignment() -> (hAlign, vAlign)"""
+ return _grid.GridCellAttr_GetNonDefaultAlignment(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize() -> (num_rows, num_cols)"""
+ return _grid.GridCellAttr_GetSize(*args, **kwargs)
+
+ def GetOverflow(*args, **kwargs):
+ """GetOverflow(self) -> bool"""
+ return _grid.GridCellAttr_GetOverflow(*args, **kwargs)
+
+ def GetRenderer(*args, **kwargs):
+ """GetRenderer(self, Grid grid, int row, int col) -> GridCellRenderer"""
+ return _grid.GridCellAttr_GetRenderer(*args, **kwargs)
+
+ def GetEditor(*args, **kwargs):
+ """GetEditor(self, Grid grid, int row, int col) -> GridCellEditor"""
+ return _grid.GridCellAttr_GetEditor(*args, **kwargs)
+
+ def IsReadOnly(*args, **kwargs):
+ """IsReadOnly(self) -> bool"""
+ return _grid.GridCellAttr_IsReadOnly(*args, **kwargs)
+
+ def GetKind(*args, **kwargs):
+ """GetKind(self) -> int"""
+ return _grid.GridCellAttr_GetKind(*args, **kwargs)
+
+ def SetDefAttr(*args, **kwargs):
+ """SetDefAttr(self, GridCellAttr defAttr)"""
+ return _grid.GridCellAttr_SetDefAttr(*args, **kwargs)
+
+ Alignment = property(GetAlignment,SetAlignment,doc="See `GetAlignment` and `SetAlignment`")
+ NonDefaultAlignment = property(GetNonDefaultAlignment)
+ BackgroundColour = property(GetBackgroundColour,SetBackgroundColour,doc="See `GetBackgroundColour` and `SetBackgroundColour`")
+ Font = property(GetFont,SetFont,doc="See `GetFont` and `SetFont`")
+ Kind = property(GetKind,SetKind,doc="See `GetKind` and `SetKind`")
+ Overflow = property(GetOverflow,SetOverflow,doc="See `GetOverflow` and `SetOverflow`")
+ Size = property(GetSize,SetSize,doc="See `GetSize` and `SetSize`")
+ TextColour = property(GetTextColour,SetTextColour,doc="See `GetTextColour` and `SetTextColour`")
+_grid.GridCellAttr_swigregister(GridCellAttr)
+
+class GridCellAttrProvider(object):
+ """Proxy of C++ GridCellAttrProvider class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> GridCellAttrProvider"""
+ _grid.GridCellAttrProvider_swiginit(self,_grid.new_GridCellAttrProvider(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def _setOORInfo(*args, **kwargs):
+ """_setOORInfo(self, PyObject _self)"""
+ return _grid.GridCellAttrProvider__setOORInfo(*args, **kwargs)
+
+ def GetAttr(*args, **kwargs):
+ """GetAttr(self, int row, int col, int kind) -> GridCellAttr"""
+ return _grid.GridCellAttrProvider_GetAttr(*args, **kwargs)
+
+ def SetAttr(*args, **kwargs):
+ """SetAttr(self, GridCellAttr attr, int row, int col)"""
+ return _grid.GridCellAttrProvider_SetAttr(*args, **kwargs)
+
+ def SetRowAttr(*args, **kwargs):
+ """SetRowAttr(self, GridCellAttr attr, int row)"""
+ return _grid.GridCellAttrProvider_SetRowAttr(*args, **kwargs)
+
+ def SetColAttr(*args, **kwargs):
+ """SetColAttr(self, GridCellAttr attr, int col)"""
+ return _grid.GridCellAttrProvider_SetColAttr(*args, **kwargs)
+
+ def UpdateAttrRows(*args, **kwargs):
+ """UpdateAttrRows(self, size_t pos, int numRows)"""
+ return _grid.GridCellAttrProvider_UpdateAttrRows(*args, **kwargs)
+
+ def UpdateAttrCols(*args, **kwargs):
+ """UpdateAttrCols(self, size_t pos, int numCols)"""
+ return _grid.GridCellAttrProvider_UpdateAttrCols(*args, **kwargs)
+
+_grid.GridCellAttrProvider_swigregister(GridCellAttrProvider)
+
+class PyGridCellAttrProvider(GridCellAttrProvider):
+ """Proxy of C++ PyGridCellAttrProvider class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyGridCellAttrProvider"""
+ _grid.PyGridCellAttrProvider_swiginit(self,_grid.new_PyGridCellAttrProvider(*args, **kwargs))
+ PyGridCellAttrProvider._setCallbackInfo(self, self, PyGridCellAttrProvider)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _grid.PyGridCellAttrProvider__setCallbackInfo(*args, **kwargs)
+
+ def GetAttr(*args, **kwargs):
+ """GetAttr(self, int row, int col, int kind) -> GridCellAttr"""
+ return _grid.PyGridCellAttrProvider_GetAttr(*args, **kwargs)
+
+ def SetAttr(*args, **kwargs):
+ """SetAttr(self, GridCellAttr attr, int row, int col)"""
+ return _grid.PyGridCellAttrProvider_SetAttr(*args, **kwargs)
+
+ def SetRowAttr(*args, **kwargs):
+ """SetRowAttr(self, GridCellAttr attr, int row)"""
+ return _grid.PyGridCellAttrProvider_SetRowAttr(*args, **kwargs)
+
+ def SetColAttr(*args, **kwargs):
+ """SetColAttr(self, GridCellAttr attr, int col)"""
+ return _grid.PyGridCellAttrProvider_SetColAttr(*args, **kwargs)
+
+ def base_GetAttr(*args, **kw):
+ return PyGridCellAttrProvider.GetAttr(*args, **kw)
+ base_GetAttr = wx.deprecated(base_GetAttr,
+ "Please use PyGridCellAttrProvider.GetAttr instead.")
+
+ def base_SetAttr(*args, **kw):
+ return PyGridCellAttrProvider.SetAttr(*args, **kw)
+ base_SetAttr = wx.deprecated(base_SetAttr,
+ "Please use PyGridCellAttrProvider.SetAttr instead.")
+
+ def base_SetRowAttr(*args, **kw):
+ return PyGridCellAttrProvider.SetRowAttr(*args, **kw)
+ base_SetRowAttr = wx.deprecated(base_SetRowAttr,
+ "Please use PyGridCellAttrProvider.SetRowAttr instead.")
+
+ def base_SetColAttr(*args, **kw):
+ return PyGridCellAttrProvider.SetColAttr(*args, **kw)
+ base_SetColAttr = wx.deprecated(base_SetColAttr,
+ "Please use PyGridCellAttrProvider.SetColAttr instead.")
+
+_grid.PyGridCellAttrProvider_swigregister(PyGridCellAttrProvider)
+
+class GridTableBase(_core.Object):
+ """Proxy of C++ GridTableBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _grid.delete_GridTableBase
+ __del__ = lambda self : None;
+ def _setOORInfo(*args, **kwargs):
+ """_setOORInfo(self, PyObject _self)"""
+ return _grid.GridTableBase__setOORInfo(*args, **kwargs)
+
+ def SetAttrProvider(*args, **kwargs):
+ """SetAttrProvider(self, GridCellAttrProvider attrProvider)"""
+ return _grid.GridTableBase_SetAttrProvider(*args, **kwargs)
+
+ def GetAttrProvider(*args, **kwargs):
+ """GetAttrProvider(self) -> GridCellAttrProvider"""
+ return _grid.GridTableBase_GetAttrProvider(*args, **kwargs)
+
+ def SetView(*args, **kwargs):
+ """SetView(self, Grid grid)"""
+ return _grid.GridTableBase_SetView(*args, **kwargs)
+
+ def GetView(*args, **kwargs):
+ """GetView(self) -> Grid"""
+ return _grid.GridTableBase_GetView(*args, **kwargs)
+
+ def GetRowsCount(*args, **kwargs):
+ """GetRowsCount(self) -> int"""
+ return _grid.GridTableBase_GetRowsCount(*args, **kwargs)
+
+ def GetColsCount(*args, **kwargs):
+ """GetColsCount(self) -> int"""
+ return _grid.GridTableBase_GetColsCount(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """IsEmpty(self, GridCellCoords coord) -> bool"""
+ return _grid.GridTableBase_IsEmpty(*args, **kwargs)
+
+ def GetNumberRows(*args, **kwargs):
+ """GetNumberRows(self) -> int"""
+ return _grid.GridTableBase_GetNumberRows(*args, **kwargs)
+
+ def GetNumberCols(*args, **kwargs):
+ """GetNumberCols(self) -> int"""
+ return _grid.GridTableBase_GetNumberCols(*args, **kwargs)
+
+ def IsEmptyCell(*args, **kwargs):
+ """IsEmptyCell(self, int row, int col) -> bool"""
+ return _grid.GridTableBase_IsEmptyCell(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self, int row, int col) -> String"""
+ return _grid.GridTableBase_GetValue(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, int row, int col, String value)"""
+ return _grid.GridTableBase_SetValue(*args, **kwargs)
+
+ def GetTypeName(*args, **kwargs):
+ """GetTypeName(self, int row, int col) -> String"""
+ return _grid.GridTableBase_GetTypeName(*args, **kwargs)
+
+ def CanGetValueAs(*args, **kwargs):
+ """CanGetValueAs(self, int row, int col, String typeName) -> bool"""
+ return _grid.GridTableBase_CanGetValueAs(*args, **kwargs)
+
+ def CanSetValueAs(*args, **kwargs):
+ """CanSetValueAs(self, int row, int col, String typeName) -> bool"""
+ return _grid.GridTableBase_CanSetValueAs(*args, **kwargs)
+
+ def GetValueAsLong(*args, **kwargs):
+ """GetValueAsLong(self, int row, int col) -> long"""
+ return _grid.GridTableBase_GetValueAsLong(*args, **kwargs)
+
+ def GetValueAsDouble(*args, **kwargs):
+ """GetValueAsDouble(self, int row, int col) -> double"""
+ return _grid.GridTableBase_GetValueAsDouble(*args, **kwargs)
+
+ def GetValueAsBool(*args, **kwargs):
+ """GetValueAsBool(self, int row, int col) -> bool"""
+ return _grid.GridTableBase_GetValueAsBool(*args, **kwargs)
+
+ def SetValueAsLong(*args, **kwargs):
+ """SetValueAsLong(self, int row, int col, long value)"""
+ return _grid.GridTableBase_SetValueAsLong(*args, **kwargs)
+
+ def SetValueAsDouble(*args, **kwargs):
+ """SetValueAsDouble(self, int row, int col, double value)"""
+ return _grid.GridTableBase_SetValueAsDouble(*args, **kwargs)
+
+ def SetValueAsBool(*args, **kwargs):
+ """SetValueAsBool(self, int row, int col, bool value)"""
+ return _grid.GridTableBase_SetValueAsBool(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """Clear(self)"""
+ return _grid.GridTableBase_Clear(*args, **kwargs)
+
+ def InsertRows(*args, **kwargs):
+ """InsertRows(self, size_t pos=0, size_t numRows=1) -> bool"""
+ return _grid.GridTableBase_InsertRows(*args, **kwargs)
+
+ def AppendRows(*args, **kwargs):
+ """AppendRows(self, size_t numRows=1) -> bool"""
+ return _grid.GridTableBase_AppendRows(*args, **kwargs)
+
+ def DeleteRows(*args, **kwargs):
+ """DeleteRows(self, size_t pos=0, size_t numRows=1) -> bool"""
+ return _grid.GridTableBase_DeleteRows(*args, **kwargs)
+
+ def InsertCols(*args, **kwargs):
+ """InsertCols(self, size_t pos=0, size_t numCols=1) -> bool"""
+ return _grid.GridTableBase_InsertCols(*args, **kwargs)
+
+ def AppendCols(*args, **kwargs):
+ """AppendCols(self, size_t numCols=1) -> bool"""
+ return _grid.GridTableBase_AppendCols(*args, **kwargs)
+
+ def DeleteCols(*args, **kwargs):
+ """DeleteCols(self, size_t pos=0, size_t numCols=1) -> bool"""
+ return _grid.GridTableBase_DeleteCols(*args, **kwargs)
+
+ def GetRowLabelValue(*args, **kwargs):
+ """GetRowLabelValue(self, int row) -> String"""
+ return _grid.GridTableBase_GetRowLabelValue(*args, **kwargs)
+
+ def GetColLabelValue(*args, **kwargs):
+ """GetColLabelValue(self, int col) -> String"""
+ return _grid.GridTableBase_GetColLabelValue(*args, **kwargs)
+
+ def SetRowLabelValue(*args, **kwargs):
+ """SetRowLabelValue(self, int row, String value)"""
+ return _grid.GridTableBase_SetRowLabelValue(*args, **kwargs)
+
+ def SetColLabelValue(*args, **kwargs):
+ """SetColLabelValue(self, int col, String value)"""
+ return _grid.GridTableBase_SetColLabelValue(*args, **kwargs)
+
+ def CanHaveAttributes(*args, **kwargs):
+ """CanHaveAttributes(self) -> bool"""
+ return _grid.GridTableBase_CanHaveAttributes(*args, **kwargs)
+
+ def GetAttr(*args, **kwargs):
+ """GetAttr(self, int row, int col, int kind) -> GridCellAttr"""
+ return _grid.GridTableBase_GetAttr(*args, **kwargs)
+
+ def SetAttr(*args, **kwargs):
+ """SetAttr(self, GridCellAttr attr, int row, int col)"""
+ return _grid.GridTableBase_SetAttr(*args, **kwargs)
+
+ def SetRowAttr(*args, **kwargs):
+ """SetRowAttr(self, GridCellAttr attr, int row)"""
+ return _grid.GridTableBase_SetRowAttr(*args, **kwargs)
+
+ def SetColAttr(*args, **kwargs):
+ """SetColAttr(self, GridCellAttr attr, int col)"""
+ return _grid.GridTableBase_SetColAttr(*args, **kwargs)
+
+ AttrProvider = property(GetAttrProvider,SetAttrProvider,doc="See `GetAttrProvider` and `SetAttrProvider`")
+ NumberCols = property(GetNumberCols,doc="See `GetNumberCols`")
+ NumberRows = property(GetNumberRows,doc="See `GetNumberRows`")
+ View = property(GetView,SetView,doc="See `GetView` and `SetView`")
+_grid.GridTableBase_swigregister(GridTableBase)
+
+class PyGridTableBase(GridTableBase):
+ """Proxy of C++ PyGridTableBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyGridTableBase"""
+ _grid.PyGridTableBase_swiginit(self,_grid.new_PyGridTableBase(*args, **kwargs))
+ self._setOORInfo(self);PyGridTableBase._setCallbackInfo(self, self, PyGridTableBase)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _grid.PyGridTableBase__setCallbackInfo(*args, **kwargs)
+
+ def Destroy(*args, **kwargs):
+ """
+ Destroy(self)
+
+ Deletes the C++ object this Python object is a proxy for.
+ """
+ args[0].this.own(False)
+ return _grid.PyGridTableBase_Destroy(*args, **kwargs)
+
+ def base_GetTypeName(*args, **kw):
+ return PyGridTableBase.GetTypeName(*args, **kw)
+ base_GetTypeName = wx.deprecated(base_GetTypeName,
+ "Please use PyGridTableBase.GetTypeName instead.")
+
+ def base_CanGetValueAs(*args, **kw):
+ return PyGridTableBase.CanGetValueAs(*args, **kw)
+ base_CanGetValueAs = wx.deprecated(base_CanGetValueAs,
+ "Please use PyGridTableBase.CanGetValueAs instead.")
+
+ def base_CanSetValueAs(*args, **kw):
+ return PyGridTableBase.CanSetValueAs(*args, **kw)
+ base_CanSetValueAs = wx.deprecated(base_CanSetValueAs,
+ "Please use PyGridTableBase.CanSetValueAs instead.")
+
+ def base_Clear(*args, **kw):
+ return PyGridTableBase.Clear(*args, **kw)
+ base_Clear = wx.deprecated(base_Clear,
+ "Please use PyGridTableBase.Clear instead.")
+
+ def base_InsertRows(*args, **kw):
+ return PyGridTableBase.InsertRows(*args, **kw)
+ base_InsertRows = wx.deprecated(base_InsertRows,
+ "Please use PyGridTableBase.InsertRows instead.")
+
+ def base_AppendRows(*args, **kw):
+ return PyGridTableBase.AppendRows(*args, **kw)
+ base_AppendRows = wx.deprecated(base_AppendRows,
+ "Please use PyGridTableBase.AppendRows instead.")
+
+ def base_DeleteRows(*args, **kw):
+ return PyGridTableBase.DeleteRows(*args, **kw)
+ base_DeleteRows = wx.deprecated(base_DeleteRows,
+ "Please use PyGridTableBase.DeleteRows instead.")
+
+ def base_InsertCols(*args, **kw):
+ return PyGridTableBase.InsertCols(*args, **kw)
+ base_InsertCols = wx.deprecated(base_InsertCols,
+ "Please use PyGridTableBase.InsertCols instead.")
+
+ def base_AppendCols(*args, **kw):
+ return PyGridTableBase.AppendCols(*args, **kw)
+ base_AppendCols = wx.deprecated(base_AppendCols,
+ "Please use PyGridTableBase.AppendCols instead.")
+
+ def base_DeleteCols(*args, **kw):
+ return PyGridTableBase.DeleteCols(*args, **kw)
+ base_DeleteCols = wx.deprecated(base_DeleteCols,
+ "Please use PyGridTableBase.DeleteCols instead.")
+
+ def base_GetRowLabelValue(*args, **kw):
+ return PyGridTableBase.GetRowLabelValue(*args, **kw)
+ base_GetRowLabelValue = wx.deprecated(base_GetRowLabelValue,
+ "Please use PyGridTableBase.GetRowLabelValue instead.")
+
+ def base_GetColLabelValue(*args, **kw):
+ return PyGridTableBase.GetColLabelValue(*args, **kw)
+ base_GetColLabelValue = wx.deprecated(base_GetColLabelValue,
+ "Please use PyGridTableBase.GetColLabelValue instead.")
+
+ def base_SetRowLabelValue(*args, **kw):
+ return PyGridTableBase.SetRowLabelValue(*args, **kw)
+ base_SetRowLabelValue = wx.deprecated(base_SetRowLabelValue,
+ "Please use PyGridTableBase.SetRowLabelValue instead.")
+
+ def base_SetColLabelValue(*args, **kw):
+ return PyGridTableBase.SetColLabelValue(*args, **kw)
+ base_SetColLabelValue = wx.deprecated(base_SetColLabelValue,
+ "Please use PyGridTableBase.SetColLabelValue instead.")
+
+ def base_CanHaveAttributes(*args, **kw):
+ return PyGridTableBase.CanHaveAttributes(*args, **kw)
+ base_CanHaveAttributes = wx.deprecated(base_CanHaveAttributes,
+ "Please use PyGridTableBase.CanHaveAttributes instead.")
+
+ def base_GetAttr(*args, **kw):
+ return PyGridTableBase.GetAttr(*args, **kw)
+ base_GetAttr = wx.deprecated(base_GetAttr,
+ "Please use PyGridTableBase.GetAttr instead.")
+
+ def base_SetAttr(*args, **kw):
+ return PyGridTableBase.SetAttr(*args, **kw)
+ base_SetAttr = wx.deprecated(base_SetAttr,
+ "Please use PyGridTableBase.SetAttr instead.")
+
+ def base_SetRowAttr(*args, **kw):
+ return PyGridTableBase.SetRowAttr(*args, **kw)
+ base_SetRowAttr = wx.deprecated(base_SetRowAttr,
+ "Please use PyGridTableBase.SetRowAttr instead.")
+
+ def base_SetColAttr(*args, **kw):
+ return PyGridTableBase.SetColAttr(*args, **kw)
+ base_SetColAttr = wx.deprecated(base_SetColAttr,
+ "Please use PyGridTableBase.SetColAttr instead.")
+
+_grid.PyGridTableBase_swigregister(PyGridTableBase)
+
+class GridStringTable(GridTableBase):
+ """Proxy of C++ GridStringTable class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int numRows=0, int numCols=0) -> GridStringTable"""
+ _grid.GridStringTable_swiginit(self,_grid.new_GridStringTable(*args, **kwargs))
+ self._setOORInfo(self)
+
+_grid.GridStringTable_swigregister(GridStringTable)
+
+GRIDTABLE_REQUEST_VIEW_GET_VALUES = _grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES
+GRIDTABLE_REQUEST_VIEW_SEND_VALUES = _grid.GRIDTABLE_REQUEST_VIEW_SEND_VALUES
+GRIDTABLE_NOTIFY_ROWS_INSERTED = _grid.GRIDTABLE_NOTIFY_ROWS_INSERTED
+GRIDTABLE_NOTIFY_ROWS_APPENDED = _grid.GRIDTABLE_NOTIFY_ROWS_APPENDED
+GRIDTABLE_NOTIFY_ROWS_DELETED = _grid.GRIDTABLE_NOTIFY_ROWS_DELETED
+GRIDTABLE_NOTIFY_COLS_INSERTED = _grid.GRIDTABLE_NOTIFY_COLS_INSERTED
+GRIDTABLE_NOTIFY_COLS_APPENDED = _grid.GRIDTABLE_NOTIFY_COLS_APPENDED
+GRIDTABLE_NOTIFY_COLS_DELETED = _grid.GRIDTABLE_NOTIFY_COLS_DELETED
+class GridTableMessage(object):
+ """Proxy of C++ GridTableMessage class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, GridTableBase table, int id, int comInt1=-1, int comInt2=-1) -> GridTableMessage"""
+ _grid.GridTableMessage_swiginit(self,_grid.new_GridTableMessage(*args, **kwargs))
+ __swig_destroy__ = _grid.delete_GridTableMessage
+ __del__ = lambda self : None;
+ def SetTableObject(*args, **kwargs):
+ """SetTableObject(self, GridTableBase table)"""
+ return _grid.GridTableMessage_SetTableObject(*args, **kwargs)
+
+ def GetTableObject(*args, **kwargs):
+ """GetTableObject(self) -> GridTableBase"""
+ return _grid.GridTableMessage_GetTableObject(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """SetId(self, int id)"""
+ return _grid.GridTableMessage_SetId(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """GetId(self) -> int"""
+ return _grid.GridTableMessage_GetId(*args, **kwargs)
+
+ def SetCommandInt(*args, **kwargs):
+ """SetCommandInt(self, int comInt1)"""
+ return _grid.GridTableMessage_SetCommandInt(*args, **kwargs)
+
+ def GetCommandInt(*args, **kwargs):
+ """GetCommandInt(self) -> int"""
+ return _grid.GridTableMessage_GetCommandInt(*args, **kwargs)
+
+ def SetCommandInt2(*args, **kwargs):
+ """SetCommandInt2(self, int comInt2)"""
+ return _grid.GridTableMessage_SetCommandInt2(*args, **kwargs)
+
+ def GetCommandInt2(*args, **kwargs):
+ """GetCommandInt2(self) -> int"""
+ return _grid.GridTableMessage_GetCommandInt2(*args, **kwargs)
+
+ CommandInt = property(GetCommandInt,SetCommandInt,doc="See `GetCommandInt` and `SetCommandInt`")
+ CommandInt2 = property(GetCommandInt2,SetCommandInt2,doc="See `GetCommandInt2` and `SetCommandInt2`")
+ Id = property(GetId,SetId,doc="See `GetId` and `SetId`")
+ TableObject = property(GetTableObject,SetTableObject,doc="See `GetTableObject` and `SetTableObject`")
+_grid.GridTableMessage_swigregister(GridTableMessage)
+
+class GridCellCoords(object):
+ """Proxy of C++ GridCellCoords class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int r=-1, int c=-1) -> GridCellCoords"""
+ _grid.GridCellCoords_swiginit(self,_grid.new_GridCellCoords(*args, **kwargs))
+ __swig_destroy__ = _grid.delete_GridCellCoords
+ __del__ = lambda self : None;
+ def GetRow(*args, **kwargs):
+ """GetRow(self) -> int"""
+ return _grid.GridCellCoords_GetRow(*args, **kwargs)
+
+ def SetRow(*args, **kwargs):
+ """SetRow(self, int n)"""
+ return _grid.GridCellCoords_SetRow(*args, **kwargs)
+
+ def GetCol(*args, **kwargs):
+ """GetCol(self) -> int"""
+ return _grid.GridCellCoords_GetCol(*args, **kwargs)
+
+ def SetCol(*args, **kwargs):
+ """SetCol(self, int n)"""
+ return _grid.GridCellCoords_SetCol(*args, **kwargs)
+
+ def Set(*args, **kwargs):
+ """Set(self, int row, int col)"""
+ return _grid.GridCellCoords_Set(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Test for equality of GridCellCoords objects.
+ """
+ return _grid.GridCellCoords___eq__(*args, **kwargs)
+
+ def __ne__(*args, **kwargs):
+ """
+ __ne__(self, PyObject other) -> bool
+
+ Test for inequality of GridCellCoords objects.
+ """
+ return _grid.GridCellCoords___ne__(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """Get(self) -> PyObject"""
+ return _grid.GridCellCoords_Get(*args, **kwargs)
+
+ asTuple = wx.deprecated(Get, "asTuple is deprecated, use `Get` instead")
+ def __str__(self): return str(self.Get())
+ def __repr__(self): return 'wxGridCellCoords'+str(self.Get())
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __setitem__(self, index, val):
+ if index == 0: self.SetRow(val)
+ elif index == 1: self.SetCol(val)
+ else: raise IndexError
+
+ Col = property(GetCol,SetCol,doc="See `GetCol` and `SetCol`")
+ Row = property(GetRow,SetRow,doc="See `GetRow` and `SetRow`")
+_grid.GridCellCoords_swigregister(GridCellCoords)
+
+class GridSizesInfo(object):
+ """Proxy of C++ GridSizesInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int defSize, wxArrayInt allSizes) -> GridSizesInfo"""
+ _grid.GridSizesInfo_swiginit(self,_grid.new_GridSizesInfo(*args, **kwargs))
+ def GetSize(*args, **kwargs):
+ """GetSize(self, unsigned int pos) -> int"""
+ return _grid.GridSizesInfo_GetSize(*args, **kwargs)
+
+ m_sizeDefault = property(_grid.GridSizesInfo_m_sizeDefault_get, _grid.GridSizesInfo_m_sizeDefault_set)
+ m_customSizes = property(_grid.GridSizesInfo_m_customSizes_get, _grid.GridSizesInfo_m_customSizes_set)
+_grid.GridSizesInfo_swigregister(GridSizesInfo)
+
+class Grid(_windows.ScrolledWindow):
+ """Proxy of C++ Grid class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=WANTS_CHARS,
+ String name=wxPyGridNameStr) -> Grid
+ """
+ _grid.Grid_swiginit(self,_grid.new_Grid(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=WANTS_CHARS,
+ String name=wxPyGridNameStr) -> bool
+ """
+ return _grid.Grid_Create(*args, **kwargs)
+
+ wxGridSelectCells = _grid.Grid_wxGridSelectCells
+ wxGridSelectRows = _grid.Grid_wxGridSelectRows
+ wxGridSelectColumns = _grid.Grid_wxGridSelectColumns
+ SelectCells = wxGridSelectCells
+ SelectRows = wxGridSelectRows
+ SelectColumns = wxGridSelectColumns
+
+ def CreateGrid(*args, **kwargs):
+ """CreateGrid(self, int numRows, int numCols, WXGRIDSELECTIONMODES selmode=wxGridSelectCells) -> bool"""
+ return _grid.Grid_CreateGrid(*args, **kwargs)
+
+ def SetSelectionMode(*args, **kwargs):
+ """SetSelectionMode(self, WXGRIDSELECTIONMODES selmode)"""
+ return _grid.Grid_SetSelectionMode(*args, **kwargs)
+
+ def GetSelectionMode(*args, **kwargs):
+ """GetSelectionMode(self) -> WXGRIDSELECTIONMODES"""
+ return _grid.Grid_GetSelectionMode(*args, **kwargs)
+
+ def GetNumberRows(*args, **kwargs):
+ """GetNumberRows(self) -> int"""
+ return _grid.Grid_GetNumberRows(*args, **kwargs)
+
+ def GetNumberCols(*args, **kwargs):
+ """GetNumberCols(self) -> int"""
+ return _grid.Grid_GetNumberCols(*args, **kwargs)
+
+ def CalcRowLabelsExposed(*args, **kwargs):
+ """CalcRowLabelsExposed(self, Region reg) -> wxArrayInt"""
+ return _grid.Grid_CalcRowLabelsExposed(*args, **kwargs)
+
+ def CalcColLabelsExposed(*args, **kwargs):
+ """CalcColLabelsExposed(self, Region reg) -> wxArrayInt"""
+ return _grid.Grid_CalcColLabelsExposed(*args, **kwargs)
+
+ def CalcCellsExposed(*args, **kwargs):
+ """CalcCellsExposed(self, Region reg) -> wxGridCellCoordsArray"""
+ return _grid.Grid_CalcCellsExposed(*args, **kwargs)
+
+ def ProcessTableMessage(*args, **kwargs):
+ """ProcessTableMessage(self, GridTableMessage ?) -> bool"""
+ return _grid.Grid_ProcessTableMessage(*args, **kwargs)
+
+ def GetTable(*args, **kwargs):
+ """GetTable(self) -> GridTableBase"""
+ return _grid.Grid_GetTable(*args, **kwargs)
+
+ def SetTable(*args, **kwargs):
+ """SetTable(self, GridTableBase table, bool takeOwnership=False, WXGRIDSELECTIONMODES selmode=wxGridSelectCells) -> bool"""
+ return _grid.Grid_SetTable(*args, **kwargs)
+
+ def ClearGrid(*args, **kwargs):
+ """ClearGrid(self)"""
+ return _grid.Grid_ClearGrid(*args, **kwargs)
+
+ def InsertRows(*args, **kwargs):
+ """InsertRows(self, int pos=0, int numRows=1, bool updateLabels=True) -> bool"""
+ return _grid.Grid_InsertRows(*args, **kwargs)
+
+ def AppendRows(*args, **kwargs):
+ """AppendRows(self, int numRows=1, bool updateLabels=True) -> bool"""
+ return _grid.Grid_AppendRows(*args, **kwargs)
+
+ def DeleteRows(*args, **kwargs):
+ """DeleteRows(self, int pos=0, int numRows=1, bool updateLabels=True) -> bool"""
+ return _grid.Grid_DeleteRows(*args, **kwargs)
+
+ def InsertCols(*args, **kwargs):
+ """InsertCols(self, int pos=0, int numCols=1, bool updateLabels=True) -> bool"""
+ return _grid.Grid_InsertCols(*args, **kwargs)
+
+ def AppendCols(*args, **kwargs):
+ """AppendCols(self, int numCols=1, bool updateLabels=True) -> bool"""
+ return _grid.Grid_AppendCols(*args, **kwargs)
+
+ def DeleteCols(*args, **kwargs):
+ """DeleteCols(self, int pos=0, int numCols=1, bool updateLabels=True) -> bool"""
+ return _grid.Grid_DeleteCols(*args, **kwargs)
+
+ def DrawCellHighlight(*args, **kwargs):
+ """DrawCellHighlight(self, DC dc, GridCellAttr attr)"""
+ return _grid.Grid_DrawCellHighlight(*args, **kwargs)
+
+ def DrawTextRectangle(*args, **kwargs):
+ """
+ DrawTextRectangle(self, DC dc, String ?, Rect ?, int horizontalAlignment=LEFT,
+ int verticalAlignment=TOP, int textOrientation=HORIZONTAL)
+ """
+ return _grid.Grid_DrawTextRectangle(*args, **kwargs)
+
+ def DrawRowLabels(*args, **kwargs):
+ """DrawRowLabels(self, DC dc, wxArrayInt rows)"""
+ return _grid.Grid_DrawRowLabels(*args, **kwargs)
+
+ def DrawRowLabel(*args, **kwargs):
+ """DrawRowLabel(self, DC dc, int row)"""
+ return _grid.Grid_DrawRowLabel(*args, **kwargs)
+
+ def DrawColLabels(*args, **kwargs):
+ """DrawColLabels(self, DC dc, wxArrayInt cols)"""
+ return _grid.Grid_DrawColLabels(*args, **kwargs)
+
+ def DrawColLabel(*args, **kwargs):
+ """DrawColLabel(self, DC dc, int col)"""
+ return _grid.Grid_DrawColLabel(*args, **kwargs)
+
+ def GetTextBoxSize(*args, **kwargs):
+ """GetTextBoxSize(DC dc, list lines) -> (width, height)"""
+ return _grid.Grid_GetTextBoxSize(*args, **kwargs)
+
+ def BeginBatch(*args, **kwargs):
+ """BeginBatch(self)"""
+ return _grid.Grid_BeginBatch(*args, **kwargs)
+
+ def EndBatch(*args, **kwargs):
+ """EndBatch(self)"""
+ return _grid.Grid_EndBatch(*args, **kwargs)
+
+ def GetBatchCount(*args, **kwargs):
+ """GetBatchCount(self) -> int"""
+ return _grid.Grid_GetBatchCount(*args, **kwargs)
+
+ def ForceRefresh(*args, **kwargs):
+ """ForceRefresh(self)"""
+ return _grid.Grid_ForceRefresh(*args, **kwargs)
+
+ def IsEditable(*args, **kwargs):
+ """IsEditable(self) -> bool"""
+ return _grid.Grid_IsEditable(*args, **kwargs)
+
+ def EnableEditing(*args, **kwargs):
+ """EnableEditing(self, bool edit)"""
+ return _grid.Grid_EnableEditing(*args, **kwargs)
+
+ def EnableCellEditControl(*args, **kwargs):
+ """EnableCellEditControl(self, bool enable=True)"""
+ return _grid.Grid_EnableCellEditControl(*args, **kwargs)
+
+ def DisableCellEditControl(*args, **kwargs):
+ """DisableCellEditControl(self)"""
+ return _grid.Grid_DisableCellEditControl(*args, **kwargs)
+
+ def CanEnableCellControl(*args, **kwargs):
+ """CanEnableCellControl(self) -> bool"""
+ return _grid.Grid_CanEnableCellControl(*args, **kwargs)
+
+ def IsCellEditControlEnabled(*args, **kwargs):
+ """IsCellEditControlEnabled(self) -> bool"""
+ return _grid.Grid_IsCellEditControlEnabled(*args, **kwargs)
+
+ def IsCellEditControlShown(*args, **kwargs):
+ """IsCellEditControlShown(self) -> bool"""
+ return _grid.Grid_IsCellEditControlShown(*args, **kwargs)
+
+ def IsCurrentCellReadOnly(*args, **kwargs):
+ """IsCurrentCellReadOnly(self) -> bool"""
+ return _grid.Grid_IsCurrentCellReadOnly(*args, **kwargs)
+
+ def ShowCellEditControl(*args, **kwargs):
+ """ShowCellEditControl(self)"""
+ return _grid.Grid_ShowCellEditControl(*args, **kwargs)
+
+ def HideCellEditControl(*args, **kwargs):
+ """HideCellEditControl(self)"""
+ return _grid.Grid_HideCellEditControl(*args, **kwargs)
+
+ def SaveEditControlValue(*args, **kwargs):
+ """SaveEditControlValue(self)"""
+ return _grid.Grid_SaveEditControlValue(*args, **kwargs)
+
+ def XYToCell(*args, **kwargs):
+ """XYToCell(self, int x, int y) -> GridCellCoords"""
+ return _grid.Grid_XYToCell(*args, **kwargs)
+
+ def YToRow(*args, **kwargs):
+ """YToRow(self, int y) -> int"""
+ return _grid.Grid_YToRow(*args, **kwargs)
+
+ def XToCol(*args, **kwargs):
+ """XToCol(self, int x, bool clipToMinMax=False) -> int"""
+ return _grid.Grid_XToCol(*args, **kwargs)
+
+ def YToEdgeOfRow(*args, **kwargs):
+ """YToEdgeOfRow(self, int y) -> int"""
+ return _grid.Grid_YToEdgeOfRow(*args, **kwargs)
+
+ def XToEdgeOfCol(*args, **kwargs):
+ """XToEdgeOfCol(self, int x) -> int"""
+ return _grid.Grid_XToEdgeOfCol(*args, **kwargs)
+
+ def CellToRect(*args, **kwargs):
+ """CellToRect(self, int row, int col) -> Rect"""
+ return _grid.Grid_CellToRect(*args, **kwargs)
+
+ def GetGridCursorRow(*args, **kwargs):
+ """GetGridCursorRow(self) -> int"""
+ return _grid.Grid_GetGridCursorRow(*args, **kwargs)
+
+ def GetGridCursorCol(*args, **kwargs):
+ """GetGridCursorCol(self) -> int"""
+ return _grid.Grid_GetGridCursorCol(*args, **kwargs)
+
+ def IsVisible(*args, **kwargs):
+ """IsVisible(self, int row, int col, bool wholeCellVisible=True) -> bool"""
+ return _grid.Grid_IsVisible(*args, **kwargs)
+
+ def MakeCellVisible(*args, **kwargs):
+ """MakeCellVisible(self, int row, int col)"""
+ return _grid.Grid_MakeCellVisible(*args, **kwargs)
+
+ def SetGridCursor(*args, **kwargs):
+ """SetGridCursor(self, int row, int col)"""
+ return _grid.Grid_SetGridCursor(*args, **kwargs)
+
+ def GoToCell(*args, **kwargs):
+ """GoToCell(self, int row, int col)"""
+ return _grid.Grid_GoToCell(*args, **kwargs)
+
+ def MoveCursorUp(*args, **kwargs):
+ """MoveCursorUp(self, bool expandSelection) -> bool"""
+ return _grid.Grid_MoveCursorUp(*args, **kwargs)
+
+ def MoveCursorDown(*args, **kwargs):
+ """MoveCursorDown(self, bool expandSelection) -> bool"""
+ return _grid.Grid_MoveCursorDown(*args, **kwargs)
+
+ def MoveCursorLeft(*args, **kwargs):
+ """MoveCursorLeft(self, bool expandSelection) -> bool"""
+ return _grid.Grid_MoveCursorLeft(*args, **kwargs)
+
+ def MoveCursorRight(*args, **kwargs):
+ """MoveCursorRight(self, bool expandSelection) -> bool"""
+ return _grid.Grid_MoveCursorRight(*args, **kwargs)
+
+ def MovePageDown(*args, **kwargs):
+ """MovePageDown(self) -> bool"""
+ return _grid.Grid_MovePageDown(*args, **kwargs)
+
+ def MovePageUp(*args, **kwargs):
+ """MovePageUp(self) -> bool"""
+ return _grid.Grid_MovePageUp(*args, **kwargs)
+
+ def MoveCursorUpBlock(*args, **kwargs):
+ """MoveCursorUpBlock(self, bool expandSelection) -> bool"""
+ return _grid.Grid_MoveCursorUpBlock(*args, **kwargs)
+
+ def MoveCursorDownBlock(*args, **kwargs):
+ """MoveCursorDownBlock(self, bool expandSelection) -> bool"""
+ return _grid.Grid_MoveCursorDownBlock(*args, **kwargs)
+
+ def MoveCursorLeftBlock(*args, **kwargs):
+ """MoveCursorLeftBlock(self, bool expandSelection) -> bool"""
+ return _grid.Grid_MoveCursorLeftBlock(*args, **kwargs)
+
+ def MoveCursorRightBlock(*args, **kwargs):
+ """MoveCursorRightBlock(self, bool expandSelection) -> bool"""
+ return _grid.Grid_MoveCursorRightBlock(*args, **kwargs)
+
+ def GetDefaultRowLabelSize(*args, **kwargs):
+ """GetDefaultRowLabelSize(self) -> int"""
+ return _grid.Grid_GetDefaultRowLabelSize(*args, **kwargs)
+
+ def GetRowLabelSize(*args, **kwargs):
+ """GetRowLabelSize(self) -> int"""
+ return _grid.Grid_GetRowLabelSize(*args, **kwargs)
+
+ def GetDefaultColLabelSize(*args, **kwargs):
+ """GetDefaultColLabelSize(self) -> int"""
+ return _grid.Grid_GetDefaultColLabelSize(*args, **kwargs)
+
+ def GetColLabelSize(*args, **kwargs):
+ """GetColLabelSize(self) -> int"""
+ return _grid.Grid_GetColLabelSize(*args, **kwargs)
+
+ def GetLabelBackgroundColour(*args, **kwargs):
+ """GetLabelBackgroundColour(self) -> Colour"""
+ return _grid.Grid_GetLabelBackgroundColour(*args, **kwargs)
+
+ def GetLabelTextColour(*args, **kwargs):
+ """GetLabelTextColour(self) -> Colour"""
+ return _grid.Grid_GetLabelTextColour(*args, **kwargs)
+
+ def GetLabelFont(*args, **kwargs):
+ """GetLabelFont(self) -> Font"""
+ return _grid.Grid_GetLabelFont(*args, **kwargs)
+
+ def GetRowLabelAlignment(*args, **kwargs):
+ """GetRowLabelAlignment() -> (horiz, vert)"""
+ return _grid.Grid_GetRowLabelAlignment(*args, **kwargs)
+
+ def GetColLabelAlignment(*args, **kwargs):
+ """GetColLabelAlignment() -> (horiz, vert)"""
+ return _grid.Grid_GetColLabelAlignment(*args, **kwargs)
+
+ def GetColLabelTextOrientation(*args, **kwargs):
+ """GetColLabelTextOrientation(self) -> int"""
+ return _grid.Grid_GetColLabelTextOrientation(*args, **kwargs)
+
+ def GetRowLabelValue(*args, **kwargs):
+ """GetRowLabelValue(self, int row) -> String"""
+ return _grid.Grid_GetRowLabelValue(*args, **kwargs)
+
+ def GetColLabelValue(*args, **kwargs):
+ """GetColLabelValue(self, int col) -> String"""
+ return _grid.Grid_GetColLabelValue(*args, **kwargs)
+
+ def GetCellHighlightColour(*args, **kwargs):
+ """GetCellHighlightColour(self) -> Colour"""
+ return _grid.Grid_GetCellHighlightColour(*args, **kwargs)
+
+ def GetCellHighlightPenWidth(*args, **kwargs):
+ """GetCellHighlightPenWidth(self) -> int"""
+ return _grid.Grid_GetCellHighlightPenWidth(*args, **kwargs)
+
+ def GetCellHighlightROPenWidth(*args, **kwargs):
+ """GetCellHighlightROPenWidth(self) -> int"""
+ return _grid.Grid_GetCellHighlightROPenWidth(*args, **kwargs)
+
+ def UseNativeColHeader(*args, **kwargs):
+ """UseNativeColHeader(self, bool native=True)"""
+ return _grid.Grid_UseNativeColHeader(*args, **kwargs)
+
+ def SetUseNativeColLabels(*args, **kwargs):
+ """SetUseNativeColLabels(self, bool native=True)"""
+ return _grid.Grid_SetUseNativeColLabels(*args, **kwargs)
+
+ def SetRowLabelSize(*args, **kwargs):
+ """SetRowLabelSize(self, int width)"""
+ return _grid.Grid_SetRowLabelSize(*args, **kwargs)
+
+ def SetColLabelSize(*args, **kwargs):
+ """SetColLabelSize(self, int height)"""
+ return _grid.Grid_SetColLabelSize(*args, **kwargs)
+
+ def HideRowLabels(*args, **kwargs):
+ """HideRowLabels(self)"""
+ return _grid.Grid_HideRowLabels(*args, **kwargs)
+
+ def HideColLabels(*args, **kwargs):
+ """HideColLabels(self)"""
+ return _grid.Grid_HideColLabels(*args, **kwargs)
+
+ def SetLabelBackgroundColour(*args, **kwargs):
+ """SetLabelBackgroundColour(self, Colour ?)"""
+ return _grid.Grid_SetLabelBackgroundColour(*args, **kwargs)
+
+ def SetLabelTextColour(*args, **kwargs):
+ """SetLabelTextColour(self, Colour ?)"""
+ return _grid.Grid_SetLabelTextColour(*args, **kwargs)
+
+ def SetLabelFont(*args, **kwargs):
+ """SetLabelFont(self, Font ?)"""
+ return _grid.Grid_SetLabelFont(*args, **kwargs)
+
+ def SetRowLabelAlignment(*args, **kwargs):
+ """SetRowLabelAlignment(self, int horiz, int vert)"""
+ return _grid.Grid_SetRowLabelAlignment(*args, **kwargs)
+
+ def SetColLabelAlignment(*args, **kwargs):
+ """SetColLabelAlignment(self, int horiz, int vert)"""
+ return _grid.Grid_SetColLabelAlignment(*args, **kwargs)
+
+ def SetColLabelTextOrientation(*args, **kwargs):
+ """SetColLabelTextOrientation(self, int textOrientation)"""
+ return _grid.Grid_SetColLabelTextOrientation(*args, **kwargs)
+
+ def SetRowLabelValue(*args, **kwargs):
+ """SetRowLabelValue(self, int row, String ?)"""
+ return _grid.Grid_SetRowLabelValue(*args, **kwargs)
+
+ def SetColLabelValue(*args, **kwargs):
+ """SetColLabelValue(self, int col, String ?)"""
+ return _grid.Grid_SetColLabelValue(*args, **kwargs)
+
+ def SetCellHighlightColour(*args, **kwargs):
+ """SetCellHighlightColour(self, Colour ?)"""
+ return _grid.Grid_SetCellHighlightColour(*args, **kwargs)
+
+ def SetCellHighlightPenWidth(*args, **kwargs):
+ """SetCellHighlightPenWidth(self, int width)"""
+ return _grid.Grid_SetCellHighlightPenWidth(*args, **kwargs)
+
+ def SetCellHighlightROPenWidth(*args, **kwargs):
+ """SetCellHighlightROPenWidth(self, int width)"""
+ return _grid.Grid_SetCellHighlightROPenWidth(*args, **kwargs)
+
+ def EnableDragRowSize(*args, **kwargs):
+ """EnableDragRowSize(self, bool enable=True)"""
+ return _grid.Grid_EnableDragRowSize(*args, **kwargs)
+
+ def DisableDragRowSize(*args, **kwargs):
+ """DisableDragRowSize(self)"""
+ return _grid.Grid_DisableDragRowSize(*args, **kwargs)
+
+ def EnableDragColSize(*args, **kwargs):
+ """EnableDragColSize(self, bool enable=True)"""
+ return _grid.Grid_EnableDragColSize(*args, **kwargs)
+
+ def DisableDragColSize(*args, **kwargs):
+ """DisableDragColSize(self)"""
+ return _grid.Grid_DisableDragColSize(*args, **kwargs)
+
+ def DisableRowResize(*args, **kwargs):
+ """DisableRowResize(self, int row)"""
+ return _grid.Grid_DisableRowResize(*args, **kwargs)
+
+ def DisableColResize(*args, **kwargs):
+ """DisableColResize(self, int col)"""
+ return _grid.Grid_DisableColResize(*args, **kwargs)
+
+ def CanDragRowSize(*args, **kwargs):
+ """CanDragRowSize(self) -> bool"""
+ return _grid.Grid_CanDragRowSize(*args, **kwargs)
+
+ def CanDragColSize(*args, **kwargs):
+ """CanDragColSize(self) -> bool"""
+ return _grid.Grid_CanDragColSize(*args, **kwargs)
+
+ def EnableDragColMove(*args, **kwargs):
+ """EnableDragColMove(self, bool enable=True)"""
+ return _grid.Grid_EnableDragColMove(*args, **kwargs)
+
+ def DisableDragColMove(*args, **kwargs):
+ """DisableDragColMove(self)"""
+ return _grid.Grid_DisableDragColMove(*args, **kwargs)
+
+ def CanDragColMove(*args, **kwargs):
+ """CanDragColMove(self) -> bool"""
+ return _grid.Grid_CanDragColMove(*args, **kwargs)
+
+ def EnableDragGridSize(*args, **kwargs):
+ """EnableDragGridSize(self, bool enable=True)"""
+ return _grid.Grid_EnableDragGridSize(*args, **kwargs)
+
+ def DisableDragGridSize(*args, **kwargs):
+ """DisableDragGridSize(self)"""
+ return _grid.Grid_DisableDragGridSize(*args, **kwargs)
+
+ def CanDragGridSize(*args, **kwargs):
+ """CanDragGridSize(self) -> bool"""
+ return _grid.Grid_CanDragGridSize(*args, **kwargs)
+
+ def EnableDragCell(*args, **kwargs):
+ """EnableDragCell(self, bool enable=True)"""
+ return _grid.Grid_EnableDragCell(*args, **kwargs)
+
+ def DisableDragCell(*args, **kwargs):
+ """DisableDragCell(self)"""
+ return _grid.Grid_DisableDragCell(*args, **kwargs)
+
+ def CanDragCell(*args, **kwargs):
+ """CanDragCell(self) -> bool"""
+ return _grid.Grid_CanDragCell(*args, **kwargs)
+
+ def EnableGridLines(*args, **kwargs):
+ """EnableGridLines(self, bool enable=True)"""
+ return _grid.Grid_EnableGridLines(*args, **kwargs)
+
+ def GridLinesEnabled(*args, **kwargs):
+ """GridLinesEnabled(self) -> bool"""
+ return _grid.Grid_GridLinesEnabled(*args, **kwargs)
+
+ def ClipHorzGridLines(*args, **kwargs):
+ """ClipHorzGridLines(self, bool clip)"""
+ return _grid.Grid_ClipHorzGridLines(*args, **kwargs)
+
+ def ClipVertGridLines(*args, **kwargs):
+ """ClipVertGridLines(self, bool clip)"""
+ return _grid.Grid_ClipVertGridLines(*args, **kwargs)
+
+ def AreHorzGridLinesClipped(*args, **kwargs):
+ """AreHorzGridLinesClipped(self) -> bool"""
+ return _grid.Grid_AreHorzGridLinesClipped(*args, **kwargs)
+
+ def AreVertGridLinesClipped(*args, **kwargs):
+ """AreVertGridLinesClipped(self) -> bool"""
+ return _grid.Grid_AreVertGridLinesClipped(*args, **kwargs)
+
+ def SetGridLineColour(*args, **kwargs):
+ """SetGridLineColour(self, Colour col)"""
+ return _grid.Grid_SetGridLineColour(*args, **kwargs)
+
+ def GetGridLineColour(*args, **kwargs):
+ """GetGridLineColour(self) -> Colour"""
+ return _grid.Grid_GetGridLineColour(*args, **kwargs)
+
+ def GetDefaultGridLinePen(*args, **kwargs):
+ """GetDefaultGridLinePen(self) -> wxPen"""
+ return _grid.Grid_GetDefaultGridLinePen(*args, **kwargs)
+
+ def GetRowGridLinePen(*args, **kwargs):
+ """GetRowGridLinePen(self, int row) -> wxPen"""
+ return _grid.Grid_GetRowGridLinePen(*args, **kwargs)
+
+ def GetColGridLinePen(*args, **kwargs):
+ """GetColGridLinePen(self, int col) -> wxPen"""
+ return _grid.Grid_GetColGridLinePen(*args, **kwargs)
+
+ def SetAttr(*args, **kwargs):
+ """SetAttr(self, int row, int col, GridCellAttr attr)"""
+ return _grid.Grid_SetAttr(*args, **kwargs)
+
+ def SetRowAttr(*args, **kwargs):
+ """SetRowAttr(self, int row, GridCellAttr attr)"""
+ return _grid.Grid_SetRowAttr(*args, **kwargs)
+
+ def SetColAttr(*args, **kwargs):
+ """SetColAttr(self, int col, GridCellAttr attr)"""
+ return _grid.Grid_SetColAttr(*args, **kwargs)
+
+ def RefreshAttr(*args, **kwargs):
+ """RefreshAttr(self, int row, int col)"""
+ return _grid.Grid_RefreshAttr(*args, **kwargs)
+
+ def GetOrCreateCellAttr(*args, **kwargs):
+ """GetOrCreateCellAttr(self, int row, int col) -> GridCellAttr"""
+ return _grid.Grid_GetOrCreateCellAttr(*args, **kwargs)
+
+ def SetColFormatBool(*args, **kwargs):
+ """SetColFormatBool(self, int col)"""
+ return _grid.Grid_SetColFormatBool(*args, **kwargs)
+
+ def SetColFormatNumber(*args, **kwargs):
+ """SetColFormatNumber(self, int col)"""
+ return _grid.Grid_SetColFormatNumber(*args, **kwargs)
+
+ def SetColFormatFloat(*args, **kwargs):
+ """SetColFormatFloat(self, int col, int width=-1, int precision=-1)"""
+ return _grid.Grid_SetColFormatFloat(*args, **kwargs)
+
+ def SetColFormatCustom(*args, **kwargs):
+ """SetColFormatCustom(self, int col, String typeName)"""
+ return _grid.Grid_SetColFormatCustom(*args, **kwargs)
+
+ def GetDefaultRowSize(*args, **kwargs):
+ """GetDefaultRowSize(self) -> int"""
+ return _grid.Grid_GetDefaultRowSize(*args, **kwargs)
+
+ def GetRowSize(*args, **kwargs):
+ """GetRowSize(self, int row) -> int"""
+ return _grid.Grid_GetRowSize(*args, **kwargs)
+
+ def IsRowShown(*args, **kwargs):
+ """IsRowShown(self, int row) -> bool"""
+ return _grid.Grid_IsRowShown(*args, **kwargs)
+
+ def GetDefaultColSize(*args, **kwargs):
+ """GetDefaultColSize(self) -> int"""
+ return _grid.Grid_GetDefaultColSize(*args, **kwargs)
+
+ def GetColSize(*args, **kwargs):
+ """GetColSize(self, int col) -> int"""
+ return _grid.Grid_GetColSize(*args, **kwargs)
+
+ def IsColShown(*args, **kwargs):
+ """IsColShown(self, int col) -> bool"""
+ return _grid.Grid_IsColShown(*args, **kwargs)
+
+ def GetDefaultCellBackgroundColour(*args, **kwargs):
+ """GetDefaultCellBackgroundColour(self) -> Colour"""
+ return _grid.Grid_GetDefaultCellBackgroundColour(*args, **kwargs)
+
+ def GetCellBackgroundColour(*args, **kwargs):
+ """GetCellBackgroundColour(self, int row, int col) -> Colour"""
+ return _grid.Grid_GetCellBackgroundColour(*args, **kwargs)
+
+ def GetDefaultCellTextColour(*args, **kwargs):
+ """GetDefaultCellTextColour(self) -> Colour"""
+ return _grid.Grid_GetDefaultCellTextColour(*args, **kwargs)
+
+ def GetCellTextColour(*args, **kwargs):
+ """GetCellTextColour(self, int row, int col) -> Colour"""
+ return _grid.Grid_GetCellTextColour(*args, **kwargs)
+
+ def GetDefaultCellFont(*args, **kwargs):
+ """GetDefaultCellFont(self) -> Font"""
+ return _grid.Grid_GetDefaultCellFont(*args, **kwargs)
+
+ def GetCellFont(*args, **kwargs):
+ """GetCellFont(self, int row, int col) -> Font"""
+ return _grid.Grid_GetCellFont(*args, **kwargs)
+
+ def GetDefaultCellAlignment(*args, **kwargs):
+ """GetDefaultCellAlignment() -> (horiz, vert)"""
+ return _grid.Grid_GetDefaultCellAlignment(*args, **kwargs)
+
+ def GetCellAlignment(*args, **kwargs):
+ """GetCellAlignment(int row, int col) -> (horiz, vert)"""
+ return _grid.Grid_GetCellAlignment(*args, **kwargs)
+
+ def GetDefaultCellOverflow(*args, **kwargs):
+ """GetDefaultCellOverflow(self) -> bool"""
+ return _grid.Grid_GetDefaultCellOverflow(*args, **kwargs)
+
+ def GetCellOverflow(*args, **kwargs):
+ """GetCellOverflow(self, int row, int col) -> bool"""
+ return _grid.Grid_GetCellOverflow(*args, **kwargs)
+
+ def GetCellSize(*args, **kwargs):
+ """GetCellSize(int row, int col) -> (num_rows, num_cols)"""
+ return _grid.Grid_GetCellSize(*args, **kwargs)
+
+ def SetDefaultRowSize(*args, **kwargs):
+ """SetDefaultRowSize(self, int height, bool resizeExistingRows=False)"""
+ return _grid.Grid_SetDefaultRowSize(*args, **kwargs)
+
+ def SetRowSize(*args, **kwargs):
+ """SetRowSize(self, int row, int height)"""
+ return _grid.Grid_SetRowSize(*args, **kwargs)
+
+ def HideRow(*args, **kwargs):
+ """HideRow(self, int row)"""
+ return _grid.Grid_HideRow(*args, **kwargs)
+
+ def ShowRow(*args, **kwargs):
+ """ShowRow(self, int row)"""
+ return _grid.Grid_ShowRow(*args, **kwargs)
+
+ def SetDefaultColSize(*args, **kwargs):
+ """SetDefaultColSize(self, int width, bool resizeExistingCols=False)"""
+ return _grid.Grid_SetDefaultColSize(*args, **kwargs)
+
+ def SetColSize(*args, **kwargs):
+ """SetColSize(self, int col, int width)"""
+ return _grid.Grid_SetColSize(*args, **kwargs)
+
+ def HideCol(*args, **kwargs):
+ """HideCol(self, int col)"""
+ return _grid.Grid_HideCol(*args, **kwargs)
+
+ def ShowCol(*args, **kwargs):
+ """ShowCol(self, int col)"""
+ return _grid.Grid_ShowCol(*args, **kwargs)
+
+ def GetColSizes(*args, **kwargs):
+ """GetColSizes(self) -> GridSizesInfo"""
+ return _grid.Grid_GetColSizes(*args, **kwargs)
+
+ def GetRowSizes(*args, **kwargs):
+ """GetRowSizes(self) -> GridSizesInfo"""
+ return _grid.Grid_GetRowSizes(*args, **kwargs)
+
+ def SetColSizes(*args, **kwargs):
+ """SetColSizes(self, GridSizesInfo sizeInfo)"""
+ return _grid.Grid_SetColSizes(*args, **kwargs)
+
+ def SetRowSizes(*args, **kwargs):
+ """SetRowSizes(self, GridSizesInfo sizeInfo)"""
+ return _grid.Grid_SetRowSizes(*args, **kwargs)
+
+ def SetColumnsOrder(*args, **kwargs):
+ """SetColumnsOrder(self, wxArrayInt order)"""
+ return _grid.Grid_SetColumnsOrder(*args, **kwargs)
+
+ def GetColAt(*args, **kwargs):
+ """GetColAt(self, int colPos) -> int"""
+ return _grid.Grid_GetColAt(*args, **kwargs)
+
+ def SetColPos(*args, **kwargs):
+ """SetColPos(self, int colID, int newPos)"""
+ return _grid.Grid_SetColPos(*args, **kwargs)
+
+ def GetColPos(*args, **kwargs):
+ """GetColPos(self, int colID) -> int"""
+ return _grid.Grid_GetColPos(*args, **kwargs)
+
+ def ResetColPos(*args, **kwargs):
+ """ResetColPos(self)"""
+ return _grid.Grid_ResetColPos(*args, **kwargs)
+
+ def AutoSizeColumn(*args, **kwargs):
+ """AutoSizeColumn(self, int col, bool setAsMin=True)"""
+ return _grid.Grid_AutoSizeColumn(*args, **kwargs)
+
+ def AutoSizeRow(*args, **kwargs):
+ """AutoSizeRow(self, int row, bool setAsMin=True)"""
+ return _grid.Grid_AutoSizeRow(*args, **kwargs)
+
+ def AutoSizeColumns(*args, **kwargs):
+ """AutoSizeColumns(self, bool setAsMin=True)"""
+ return _grid.Grid_AutoSizeColumns(*args, **kwargs)
+
+ def AutoSizeRows(*args, **kwargs):
+ """AutoSizeRows(self, bool setAsMin=True)"""
+ return _grid.Grid_AutoSizeRows(*args, **kwargs)
+
+ def AutoSize(*args, **kwargs):
+ """AutoSize(self)"""
+ return _grid.Grid_AutoSize(*args, **kwargs)
+
+ def AutoSizeRowLabelSize(*args, **kwargs):
+ """AutoSizeRowLabelSize(self, int row)"""
+ return _grid.Grid_AutoSizeRowLabelSize(*args, **kwargs)
+
+ def AutoSizeColLabelSize(*args, **kwargs):
+ """AutoSizeColLabelSize(self, int col)"""
+ return _grid.Grid_AutoSizeColLabelSize(*args, **kwargs)
+
+ def SetColMinimalWidth(*args, **kwargs):
+ """SetColMinimalWidth(self, int col, int width)"""
+ return _grid.Grid_SetColMinimalWidth(*args, **kwargs)
+
+ def SetRowMinimalHeight(*args, **kwargs):
+ """SetRowMinimalHeight(self, int row, int width)"""
+ return _grid.Grid_SetRowMinimalHeight(*args, **kwargs)
+
+ def SetColMinimalAcceptableWidth(*args, **kwargs):
+ """SetColMinimalAcceptableWidth(self, int width)"""
+ return _grid.Grid_SetColMinimalAcceptableWidth(*args, **kwargs)
+
+ def SetRowMinimalAcceptableHeight(*args, **kwargs):
+ """SetRowMinimalAcceptableHeight(self, int width)"""
+ return _grid.Grid_SetRowMinimalAcceptableHeight(*args, **kwargs)
+
+ def GetColMinimalAcceptableWidth(*args, **kwargs):
+ """GetColMinimalAcceptableWidth(self) -> int"""
+ return _grid.Grid_GetColMinimalAcceptableWidth(*args, **kwargs)
+
+ def GetRowMinimalAcceptableHeight(*args, **kwargs):
+ """GetRowMinimalAcceptableHeight(self) -> int"""
+ return _grid.Grid_GetRowMinimalAcceptableHeight(*args, **kwargs)
+
+ def SetDefaultCellBackgroundColour(*args, **kwargs):
+ """SetDefaultCellBackgroundColour(self, Colour ?)"""
+ return _grid.Grid_SetDefaultCellBackgroundColour(*args, **kwargs)
+
+ def SetCellBackgroundColour(*args, **kwargs):
+ """SetCellBackgroundColour(self, int row, int col, Colour ?)"""
+ return _grid.Grid_SetCellBackgroundColour(*args, **kwargs)
+
+ def SetDefaultCellTextColour(*args, **kwargs):
+ """SetDefaultCellTextColour(self, Colour ?)"""
+ return _grid.Grid_SetDefaultCellTextColour(*args, **kwargs)
+
+ def SetCellTextColour(*args, **kwargs):
+ """SetCellTextColour(self, int row, int col, Colour ?)"""
+ return _grid.Grid_SetCellTextColour(*args, **kwargs)
+
+ def SetDefaultCellFont(*args, **kwargs):
+ """SetDefaultCellFont(self, Font ?)"""
+ return _grid.Grid_SetDefaultCellFont(*args, **kwargs)
+
+ def SetCellFont(*args, **kwargs):
+ """SetCellFont(self, int row, int col, Font ?)"""
+ return _grid.Grid_SetCellFont(*args, **kwargs)
+
+ def SetDefaultCellAlignment(*args, **kwargs):
+ """SetDefaultCellAlignment(self, int horiz, int vert)"""
+ return _grid.Grid_SetDefaultCellAlignment(*args, **kwargs)
+
+ def SetCellAlignment(*args, **kwargs):
+ """SetCellAlignment(self, int row, int col, int horiz, int vert)"""
+ return _grid.Grid_SetCellAlignment(*args, **kwargs)
+
+ def SetDefaultCellOverflow(*args, **kwargs):
+ """SetDefaultCellOverflow(self, bool allow)"""
+ return _grid.Grid_SetDefaultCellOverflow(*args, **kwargs)
+
+ def SetCellOverflow(*args, **kwargs):
+ """SetCellOverflow(self, int row, int col, bool allow)"""
+ return _grid.Grid_SetCellOverflow(*args, **kwargs)
+
+ def SetCellSize(*args, **kwargs):
+ """SetCellSize(self, int row, int col, int num_rows, int num_cols)"""
+ return _grid.Grid_SetCellSize(*args, **kwargs)
+
+ def SetDefaultRenderer(*args, **kwargs):
+ """SetDefaultRenderer(self, GridCellRenderer renderer)"""
+ return _grid.Grid_SetDefaultRenderer(*args, **kwargs)
+
+ def SetCellRenderer(*args, **kwargs):
+ """SetCellRenderer(self, int row, int col, GridCellRenderer renderer)"""
+ return _grid.Grid_SetCellRenderer(*args, **kwargs)
+
+ def GetDefaultRenderer(*args, **kwargs):
+ """GetDefaultRenderer(self) -> GridCellRenderer"""
+ return _grid.Grid_GetDefaultRenderer(*args, **kwargs)
+
+ def GetCellRenderer(*args, **kwargs):
+ """GetCellRenderer(self, int row, int col) -> GridCellRenderer"""
+ return _grid.Grid_GetCellRenderer(*args, **kwargs)
+
+ def SetDefaultEditor(*args, **kwargs):
+ """SetDefaultEditor(self, GridCellEditor editor)"""
+ return _grid.Grid_SetDefaultEditor(*args, **kwargs)
+
+ def SetCellEditor(*args, **kwargs):
+ """SetCellEditor(self, int row, int col, GridCellEditor editor)"""
+ return _grid.Grid_SetCellEditor(*args, **kwargs)
+
+ def GetDefaultEditor(*args, **kwargs):
+ """GetDefaultEditor(self) -> GridCellEditor"""
+ return _grid.Grid_GetDefaultEditor(*args, **kwargs)
+
+ def GetCellEditor(*args, **kwargs):
+ """GetCellEditor(self, int row, int col) -> GridCellEditor"""
+ return _grid.Grid_GetCellEditor(*args, **kwargs)
+
+ def GetCellValue(*args, **kwargs):
+ """GetCellValue(self, int row, int col) -> String"""
+ return _grid.Grid_GetCellValue(*args, **kwargs)
+
+ def SetCellValue(*args, **kwargs):
+ """SetCellValue(self, int row, int col, String s)"""
+ return _grid.Grid_SetCellValue(*args, **kwargs)
+
+ def IsReadOnly(*args, **kwargs):
+ """IsReadOnly(self, int row, int col) -> bool"""
+ return _grid.Grid_IsReadOnly(*args, **kwargs)
+
+ def SetReadOnly(*args, **kwargs):
+ """SetReadOnly(self, int row, int col, bool isReadOnly=True)"""
+ return _grid.Grid_SetReadOnly(*args, **kwargs)
+
+ def SelectRow(*args, **kwargs):
+ """SelectRow(self, int row, bool addToSelected=False)"""
+ return _grid.Grid_SelectRow(*args, **kwargs)
+
+ def SelectCol(*args, **kwargs):
+ """SelectCol(self, int col, bool addToSelected=False)"""
+ return _grid.Grid_SelectCol(*args, **kwargs)
+
+ def SelectBlock(*args, **kwargs):
+ """
+ SelectBlock(self, int topRow, int leftCol, int bottomRow, int rightCol,
+ bool addToSelected=False)
+ """
+ return _grid.Grid_SelectBlock(*args, **kwargs)
+
+ def SelectAll(*args, **kwargs):
+ """SelectAll(self)"""
+ return _grid.Grid_SelectAll(*args, **kwargs)
+
+ def IsSelection(*args, **kwargs):
+ """IsSelection(self) -> bool"""
+ return _grid.Grid_IsSelection(*args, **kwargs)
+
+ def ClearSelection(*args, **kwargs):
+ """ClearSelection(self)"""
+ return _grid.Grid_ClearSelection(*args, **kwargs)
+
+ def IsInSelection(*args, **kwargs):
+ """IsInSelection(self, int row, int col) -> bool"""
+ return _grid.Grid_IsInSelection(*args, **kwargs)
+
+ def GetSelectedCells(*args, **kwargs):
+ """GetSelectedCells(self) -> wxGridCellCoordsArray"""
+ return _grid.Grid_GetSelectedCells(*args, **kwargs)
+
+ def GetSelectionBlockTopLeft(*args, **kwargs):
+ """GetSelectionBlockTopLeft(self) -> wxGridCellCoordsArray"""
+ return _grid.Grid_GetSelectionBlockTopLeft(*args, **kwargs)
+
+ def GetSelectionBlockBottomRight(*args, **kwargs):
+ """GetSelectionBlockBottomRight(self) -> wxGridCellCoordsArray"""
+ return _grid.Grid_GetSelectionBlockBottomRight(*args, **kwargs)
+
+ def GetSelectedRows(*args, **kwargs):
+ """GetSelectedRows(self) -> wxArrayInt"""
+ return _grid.Grid_GetSelectedRows(*args, **kwargs)
+
+ def GetSelectedCols(*args, **kwargs):
+ """GetSelectedCols(self) -> wxArrayInt"""
+ return _grid.Grid_GetSelectedCols(*args, **kwargs)
+
+ def DeselectRow(*args, **kwargs):
+ """DeselectRow(self, int row)"""
+ return _grid.Grid_DeselectRow(*args, **kwargs)
+
+ def DeselectCol(*args, **kwargs):
+ """DeselectCol(self, int col)"""
+ return _grid.Grid_DeselectCol(*args, **kwargs)
+
+ def DeselectCell(*args, **kwargs):
+ """DeselectCell(self, int row, int col)"""
+ return _grid.Grid_DeselectCell(*args, **kwargs)
+
+ def BlockToDeviceRect(*args, **kwargs):
+ """BlockToDeviceRect(self, GridCellCoords topLeft, GridCellCoords bottomRight) -> Rect"""
+ return _grid.Grid_BlockToDeviceRect(*args, **kwargs)
+
+ def GetSelectionBackground(*args, **kwargs):
+ """GetSelectionBackground(self) -> Colour"""
+ return _grid.Grid_GetSelectionBackground(*args, **kwargs)
+
+ def GetSelectionForeground(*args, **kwargs):
+ """GetSelectionForeground(self) -> Colour"""
+ return _grid.Grid_GetSelectionForeground(*args, **kwargs)
+
+ def SetSelectionBackground(*args, **kwargs):
+ """SetSelectionBackground(self, Colour c)"""
+ return _grid.Grid_SetSelectionBackground(*args, **kwargs)
+
+ def SetSelectionForeground(*args, **kwargs):
+ """SetSelectionForeground(self, Colour c)"""
+ return _grid.Grid_SetSelectionForeground(*args, **kwargs)
+
+ def RegisterDataType(*args, **kwargs):
+ """RegisterDataType(self, String typeName, GridCellRenderer renderer, GridCellEditor editor)"""
+ return _grid.Grid_RegisterDataType(*args, **kwargs)
+
+ def GetDefaultEditorForCell(*args, **kwargs):
+ """GetDefaultEditorForCell(self, int row, int col) -> GridCellEditor"""
+ return _grid.Grid_GetDefaultEditorForCell(*args, **kwargs)
+
+ def GetDefaultRendererForCell(*args, **kwargs):
+ """GetDefaultRendererForCell(self, int row, int col) -> GridCellRenderer"""
+ return _grid.Grid_GetDefaultRendererForCell(*args, **kwargs)
+
+ def GetDefaultEditorForType(*args, **kwargs):
+ """GetDefaultEditorForType(self, String typeName) -> GridCellEditor"""
+ return _grid.Grid_GetDefaultEditorForType(*args, **kwargs)
+
+ def GetDefaultRendererForType(*args, **kwargs):
+ """GetDefaultRendererForType(self, String typeName) -> GridCellRenderer"""
+ return _grid.Grid_GetDefaultRendererForType(*args, **kwargs)
+
+ def SetMargins(*args, **kwargs):
+ """SetMargins(self, int extraWidth, int extraHeight)"""
+ return _grid.Grid_SetMargins(*args, **kwargs)
+
+ def GetGridWindow(*args, **kwargs):
+ """GetGridWindow(self) -> Window"""
+ return _grid.Grid_GetGridWindow(*args, **kwargs)
+
+ def GetGridRowLabelWindow(*args, **kwargs):
+ """GetGridRowLabelWindow(self) -> Window"""
+ return _grid.Grid_GetGridRowLabelWindow(*args, **kwargs)
+
+ def GetGridColLabelWindow(*args, **kwargs):
+ """GetGridColLabelWindow(self) -> Window"""
+ return _grid.Grid_GetGridColLabelWindow(*args, **kwargs)
+
+ def GetGridCornerLabelWindow(*args, **kwargs):
+ """GetGridCornerLabelWindow(self) -> Window"""
+ return _grid.Grid_GetGridCornerLabelWindow(*args, **kwargs)
+
+ def GetGridColHeader(*args, **kwargs):
+ """GetGridColHeader(self) -> wxHeaderCtrl"""
+ return _grid.Grid_GetGridColHeader(*args, **kwargs)
+
+ def SetScrollLineX(*args, **kwargs):
+ """SetScrollLineX(self, int x)"""
+ return _grid.Grid_SetScrollLineX(*args, **kwargs)
+
+ def SetScrollLineY(*args, **kwargs):
+ """SetScrollLineY(self, int y)"""
+ return _grid.Grid_SetScrollLineY(*args, **kwargs)
+
+ def GetScrollLineX(*args, **kwargs):
+ """GetScrollLineX(self) -> int"""
+ return _grid.Grid_GetScrollLineX(*args, **kwargs)
+
+ def GetScrollLineY(*args, **kwargs):
+ """GetScrollLineY(self) -> int"""
+ return _grid.Grid_GetScrollLineY(*args, **kwargs)
+
+ def GetSortingColumn(*args, **kwargs):
+ """GetSortingColumn(self) -> int"""
+ return _grid.Grid_GetSortingColumn(*args, **kwargs)
+
+ def IsSortingBy(*args, **kwargs):
+ """IsSortingBy(self, int col) -> bool"""
+ return _grid.Grid_IsSortingBy(*args, **kwargs)
+
+ def IsSortOrderAscending(*args, **kwargs):
+ """IsSortOrderAscending(self) -> bool"""
+ return _grid.Grid_IsSortOrderAscending(*args, **kwargs)
+
+ def SetSortingColumn(*args, **kwargs):
+ """SetSortingColumn(self, int col, bool ascending=True)"""
+ return _grid.Grid_SetSortingColumn(*args, **kwargs)
+
+ def UnsetSortingColumn(*args, **kwargs):
+ """UnsetSortingColumn(self)"""
+ return _grid.Grid_UnsetSortingColumn(*args, **kwargs)
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _grid.Grid_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ BatchCount = property(GetBatchCount,doc="See `GetBatchCount`")
+ CellHighlightColour = property(GetCellHighlightColour,SetCellHighlightColour,doc="See `GetCellHighlightColour` and `SetCellHighlightColour`")
+ CellHighlightPenWidth = property(GetCellHighlightPenWidth,SetCellHighlightPenWidth,doc="See `GetCellHighlightPenWidth` and `SetCellHighlightPenWidth`")
+ CellHighlightROPenWidth = property(GetCellHighlightROPenWidth,SetCellHighlightROPenWidth,doc="See `GetCellHighlightROPenWidth` and `SetCellHighlightROPenWidth`")
+ CellSize = property(GetCellSize,SetCellSize,doc="See `GetCellSize` and `SetCellSize`")
+ ColLabelAlignment = property(GetColLabelAlignment,SetColLabelAlignment,doc="See `GetColLabelAlignment` and `SetColLabelAlignment`")
+ ColLabelSize = property(GetColLabelSize,SetColLabelSize,doc="See `GetColLabelSize` and `SetColLabelSize`")
+ ColLabelTextOrientation = property(GetColLabelTextOrientation,SetColLabelTextOrientation,doc="See `GetColLabelTextOrientation` and `SetColLabelTextOrientation`")
+ ColMinimalAcceptableWidth = property(GetColMinimalAcceptableWidth,SetColMinimalAcceptableWidth,doc="See `GetColMinimalAcceptableWidth` and `SetColMinimalAcceptableWidth`")
+ DefaultCellAlignment = property(GetDefaultCellAlignment,SetDefaultCellAlignment,doc="See `GetDefaultCellAlignment` and `SetDefaultCellAlignment`")
+ DefaultCellBackgroundColour = property(GetDefaultCellBackgroundColour,SetDefaultCellBackgroundColour,doc="See `GetDefaultCellBackgroundColour` and `SetDefaultCellBackgroundColour`")
+ DefaultCellFont = property(GetDefaultCellFont,SetDefaultCellFont,doc="See `GetDefaultCellFont` and `SetDefaultCellFont`")
+ DefaultCellOverflow = property(GetDefaultCellOverflow,SetDefaultCellOverflow,doc="See `GetDefaultCellOverflow` and `SetDefaultCellOverflow`")
+ DefaultCellTextColour = property(GetDefaultCellTextColour,SetDefaultCellTextColour,doc="See `GetDefaultCellTextColour` and `SetDefaultCellTextColour`")
+ DefaultColLabelSize = property(GetDefaultColLabelSize,doc="See `GetDefaultColLabelSize`")
+ DefaultColSize = property(GetDefaultColSize,SetDefaultColSize,doc="See `GetDefaultColSize` and `SetDefaultColSize`")
+ DefaultEditor = property(GetDefaultEditor,SetDefaultEditor,doc="See `GetDefaultEditor` and `SetDefaultEditor`")
+ DefaultGridLinePen = property(GetDefaultGridLinePen,doc="See `GetDefaultGridLinePen`")
+ DefaultRenderer = property(GetDefaultRenderer,SetDefaultRenderer,doc="See `GetDefaultRenderer` and `SetDefaultRenderer`")
+ DefaultRowLabelSize = property(GetDefaultRowLabelSize,doc="See `GetDefaultRowLabelSize`")
+ DefaultRowSize = property(GetDefaultRowSize,SetDefaultRowSize,doc="See `GetDefaultRowSize` and `SetDefaultRowSize`")
+ GridColLabelWindow = property(GetGridColLabelWindow,doc="See `GetGridColLabelWindow`")
+ GridCornerLabelWindow = property(GetGridCornerLabelWindow,doc="See `GetGridCornerLabelWindow`")
+ GridCursorCol = property(GetGridCursorCol,doc="See `GetGridCursorCol`")
+ GridCursorRow = property(GetGridCursorRow,doc="See `GetGridCursorRow`")
+ GridLineColour = property(GetGridLineColour,SetGridLineColour,doc="See `GetGridLineColour` and `SetGridLineColour`")
+ GridRowLabelWindow = property(GetGridRowLabelWindow,doc="See `GetGridRowLabelWindow`")
+ GridWindow = property(GetGridWindow,doc="See `GetGridWindow`")
+ LabelBackgroundColour = property(GetLabelBackgroundColour,SetLabelBackgroundColour,doc="See `GetLabelBackgroundColour` and `SetLabelBackgroundColour`")
+ LabelFont = property(GetLabelFont,SetLabelFont,doc="See `GetLabelFont` and `SetLabelFont`")
+ LabelTextColour = property(GetLabelTextColour,SetLabelTextColour,doc="See `GetLabelTextColour` and `SetLabelTextColour`")
+ NumberCols = property(GetNumberCols,doc="See `GetNumberCols`")
+ NumberRows = property(GetNumberRows,doc="See `GetNumberRows`")
+ RowLabelAlignment = property(GetRowLabelAlignment,SetRowLabelAlignment,doc="See `GetRowLabelAlignment` and `SetRowLabelAlignment`")
+ RowLabelSize = property(GetRowLabelSize,SetRowLabelSize,doc="See `GetRowLabelSize` and `SetRowLabelSize`")
+ RowMinimalAcceptableHeight = property(GetRowMinimalAcceptableHeight,SetRowMinimalAcceptableHeight,doc="See `GetRowMinimalAcceptableHeight` and `SetRowMinimalAcceptableHeight`")
+ ScrollLineX = property(GetScrollLineX,SetScrollLineX,doc="See `GetScrollLineX` and `SetScrollLineX`")
+ ScrollLineY = property(GetScrollLineY,SetScrollLineY,doc="See `GetScrollLineY` and `SetScrollLineY`")
+ SelectedCells = property(GetSelectedCells,doc="See `GetSelectedCells`")
+ SelectedCols = property(GetSelectedCols,doc="See `GetSelectedCols`")
+ SelectedRows = property(GetSelectedRows,doc="See `GetSelectedRows`")
+ SelectionBackground = property(GetSelectionBackground,SetSelectionBackground,doc="See `GetSelectionBackground` and `SetSelectionBackground`")
+ SelectionBlockBottomRight = property(GetSelectionBlockBottomRight,doc="See `GetSelectionBlockBottomRight`")
+ SelectionBlockTopLeft = property(GetSelectionBlockTopLeft,doc="See `GetSelectionBlockTopLeft`")
+ SelectionForeground = property(GetSelectionForeground,SetSelectionForeground,doc="See `GetSelectionForeground` and `SetSelectionForeground`")
+ SelectionMode = property(GetSelectionMode,SetSelectionMode,doc="See `GetSelectionMode` and `SetSelectionMode`")
+ Table = property(GetTable,SetTable,doc="See `GetTable` and `SetTable`")
+_grid.Grid_swigregister(Grid)
+
+def PreGrid(*args, **kwargs):
+ """PreGrid() -> Grid"""
+ val = _grid.new_PreGrid(*args, **kwargs)
+ return val
+
+def Grid_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ Grid_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _grid.Grid_GetClassDefaultAttributes(*args, **kwargs)
+
+class GridUpdateLocker(object):
+ """Proxy of C++ GridUpdateLocker class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Grid grid=None) -> GridUpdateLocker"""
+ _grid.GridUpdateLocker_swiginit(self,_grid.new_GridUpdateLocker(*args, **kwargs))
+ __swig_destroy__ = _grid.delete_GridUpdateLocker
+ __del__ = lambda self : None;
+ def Create(*args, **kwargs):
+ """Create(self, Grid grid)"""
+ return _grid.GridUpdateLocker_Create(*args, **kwargs)
+
+_grid.GridUpdateLocker_swigregister(GridUpdateLocker)
+
+class GridEvent(_core.NotifyEvent):
+ """Proxy of C++ GridEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int id, EventType type, Object obj, int row=-1, int col=-1,
+ int x=-1, int y=-1, bool sel=True, bool control=False,
+ bool shift=False, bool alt=False,
+ bool meta=False) -> GridEvent
+ """
+ _grid.GridEvent_swiginit(self,_grid.new_GridEvent(*args, **kwargs))
+ def GetRow(*args, **kwargs):
+ """GetRow(self) -> int"""
+ return _grid.GridEvent_GetRow(*args, **kwargs)
+
+ def GetCol(*args, **kwargs):
+ """GetCol(self) -> int"""
+ return _grid.GridEvent_GetCol(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point"""
+ return _grid.GridEvent_GetPosition(*args, **kwargs)
+
+ def Selecting(*args, **kwargs):
+ """Selecting(self) -> bool"""
+ return _grid.GridEvent_Selecting(*args, **kwargs)
+
+ def ControlDown(*args, **kwargs):
+ """ControlDown(self) -> bool"""
+ return _grid.GridEvent_ControlDown(*args, **kwargs)
+
+ def MetaDown(*args, **kwargs):
+ """MetaDown(self) -> bool"""
+ return _grid.GridEvent_MetaDown(*args, **kwargs)
+
+ def ShiftDown(*args, **kwargs):
+ """ShiftDown(self) -> bool"""
+ return _grid.GridEvent_ShiftDown(*args, **kwargs)
+
+ def AltDown(*args, **kwargs):
+ """AltDown(self) -> bool"""
+ return _grid.GridEvent_AltDown(*args, **kwargs)
+
+ def CmdDown(*args, **kwargs):
+ """CmdDown(self) -> bool"""
+ return _grid.GridEvent_CmdDown(*args, **kwargs)
+
+ Col = property(GetCol,doc="See `GetCol`")
+ Position = property(GetPosition,doc="See `GetPosition`")
+ Row = property(GetRow,doc="See `GetRow`")
+_grid.GridEvent_swigregister(GridEvent)
+
+class GridSizeEvent(_core.NotifyEvent):
+ """Proxy of C++ GridSizeEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int id, EventType type, Grid obj, int rowOrCol=-1,
+ int x=-1, int y=-1, bool control=False, bool shift=False,
+ bool alt=False, bool meta=False) -> GridSizeEvent
+ """
+ _grid.GridSizeEvent_swiginit(self,_grid.new_GridSizeEvent(*args, **kwargs))
+ def GetRowOrCol(*args, **kwargs):
+ """GetRowOrCol(self) -> int"""
+ return _grid.GridSizeEvent_GetRowOrCol(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point"""
+ return _grid.GridSizeEvent_GetPosition(*args, **kwargs)
+
+ def ControlDown(*args, **kwargs):
+ """ControlDown(self) -> bool"""
+ return _grid.GridSizeEvent_ControlDown(*args, **kwargs)
+
+ def MetaDown(*args, **kwargs):
+ """MetaDown(self) -> bool"""
+ return _grid.GridSizeEvent_MetaDown(*args, **kwargs)
+
+ def ShiftDown(*args, **kwargs):
+ """ShiftDown(self) -> bool"""
+ return _grid.GridSizeEvent_ShiftDown(*args, **kwargs)
+
+ def AltDown(*args, **kwargs):
+ """AltDown(self) -> bool"""
+ return _grid.GridSizeEvent_AltDown(*args, **kwargs)
+
+ def CmdDown(*args, **kwargs):
+ """CmdDown(self) -> bool"""
+ return _grid.GridSizeEvent_CmdDown(*args, **kwargs)
+
+ Position = property(GetPosition,doc="See `GetPosition`")
+ RowOrCol = property(GetRowOrCol,doc="See `GetRowOrCol`")
+_grid.GridSizeEvent_swigregister(GridSizeEvent)
+
+class GridRangeSelectEvent(_core.NotifyEvent):
+ """Proxy of C++ GridRangeSelectEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int id, EventType type, Grid obj, GridCellCoords topLeft,
+ GridCellCoords bottomRight, bool sel=True,
+ bool control=False, bool shift=False, bool alt=False,
+ bool meta=False) -> GridRangeSelectEvent
+ """
+ _grid.GridRangeSelectEvent_swiginit(self,_grid.new_GridRangeSelectEvent(*args, **kwargs))
+ def GetTopLeftCoords(*args, **kwargs):
+ """GetTopLeftCoords(self) -> GridCellCoords"""
+ return _grid.GridRangeSelectEvent_GetTopLeftCoords(*args, **kwargs)
+
+ def GetBottomRightCoords(*args, **kwargs):
+ """GetBottomRightCoords(self) -> GridCellCoords"""
+ return _grid.GridRangeSelectEvent_GetBottomRightCoords(*args, **kwargs)
+
+ def GetTopRow(*args, **kwargs):
+ """GetTopRow(self) -> int"""
+ return _grid.GridRangeSelectEvent_GetTopRow(*args, **kwargs)
+
+ def GetBottomRow(*args, **kwargs):
+ """GetBottomRow(self) -> int"""
+ return _grid.GridRangeSelectEvent_GetBottomRow(*args, **kwargs)
+
+ def GetLeftCol(*args, **kwargs):
+ """GetLeftCol(self) -> int"""
+ return _grid.GridRangeSelectEvent_GetLeftCol(*args, **kwargs)
+
+ def GetRightCol(*args, **kwargs):
+ """GetRightCol(self) -> int"""
+ return _grid.GridRangeSelectEvent_GetRightCol(*args, **kwargs)
+
+ def Selecting(*args, **kwargs):
+ """Selecting(self) -> bool"""
+ return _grid.GridRangeSelectEvent_Selecting(*args, **kwargs)
+
+ def ControlDown(*args, **kwargs):
+ """ControlDown(self) -> bool"""
+ return _grid.GridRangeSelectEvent_ControlDown(*args, **kwargs)
+
+ def MetaDown(*args, **kwargs):
+ """MetaDown(self) -> bool"""
+ return _grid.GridRangeSelectEvent_MetaDown(*args, **kwargs)
+
+ def ShiftDown(*args, **kwargs):
+ """ShiftDown(self) -> bool"""
+ return _grid.GridRangeSelectEvent_ShiftDown(*args, **kwargs)
+
+ def AltDown(*args, **kwargs):
+ """AltDown(self) -> bool"""
+ return _grid.GridRangeSelectEvent_AltDown(*args, **kwargs)
+
+ def CmdDown(*args, **kwargs):
+ """CmdDown(self) -> bool"""
+ return _grid.GridRangeSelectEvent_CmdDown(*args, **kwargs)
+
+ BottomRightCoords = property(GetBottomRightCoords,doc="See `GetBottomRightCoords`")
+ BottomRow = property(GetBottomRow,doc="See `GetBottomRow`")
+ LeftCol = property(GetLeftCol,doc="See `GetLeftCol`")
+ RightCol = property(GetRightCol,doc="See `GetRightCol`")
+ TopLeftCoords = property(GetTopLeftCoords,doc="See `GetTopLeftCoords`")
+ TopRow = property(GetTopRow,doc="See `GetTopRow`")
+_grid.GridRangeSelectEvent_swigregister(GridRangeSelectEvent)
+
+class GridEditorCreatedEvent(_core.CommandEvent):
+ """Proxy of C++ GridEditorCreatedEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, int id, EventType type, Object obj, int row, int col,
+ Control ctrl) -> GridEditorCreatedEvent
+ """
+ _grid.GridEditorCreatedEvent_swiginit(self,_grid.new_GridEditorCreatedEvent(*args, **kwargs))
+ def GetRow(*args, **kwargs):
+ """GetRow(self) -> int"""
+ return _grid.GridEditorCreatedEvent_GetRow(*args, **kwargs)
+
+ def GetCol(*args, **kwargs):
+ """GetCol(self) -> int"""
+ return _grid.GridEditorCreatedEvent_GetCol(*args, **kwargs)
+
+ def GetControl(*args, **kwargs):
+ """GetControl(self) -> Control"""
+ return _grid.GridEditorCreatedEvent_GetControl(*args, **kwargs)
+
+ def SetRow(*args, **kwargs):
+ """SetRow(self, int row)"""
+ return _grid.GridEditorCreatedEvent_SetRow(*args, **kwargs)
+
+ def SetCol(*args, **kwargs):
+ """SetCol(self, int col)"""
+ return _grid.GridEditorCreatedEvent_SetCol(*args, **kwargs)
+
+ def SetControl(*args, **kwargs):
+ """SetControl(self, Control ctrl)"""
+ return _grid.GridEditorCreatedEvent_SetControl(*args, **kwargs)
+
+ Col = property(GetCol,SetCol,doc="See `GetCol` and `SetCol`")
+ Control = property(GetControl,SetControl,doc="See `GetControl` and `SetControl`")
+ Row = property(GetRow,SetRow,doc="See `GetRow` and `SetRow`")
+_grid.GridEditorCreatedEvent_swigregister(GridEditorCreatedEvent)
+
+wxEVT_GRID_CELL_LEFT_CLICK = _grid.wxEVT_GRID_CELL_LEFT_CLICK
+wxEVT_GRID_CELL_RIGHT_CLICK = _grid.wxEVT_GRID_CELL_RIGHT_CLICK
+wxEVT_GRID_CELL_LEFT_DCLICK = _grid.wxEVT_GRID_CELL_LEFT_DCLICK
+wxEVT_GRID_CELL_RIGHT_DCLICK = _grid.wxEVT_GRID_CELL_RIGHT_DCLICK
+wxEVT_GRID_LABEL_LEFT_CLICK = _grid.wxEVT_GRID_LABEL_LEFT_CLICK
+wxEVT_GRID_LABEL_RIGHT_CLICK = _grid.wxEVT_GRID_LABEL_RIGHT_CLICK
+wxEVT_GRID_LABEL_LEFT_DCLICK = _grid.wxEVT_GRID_LABEL_LEFT_DCLICK
+wxEVT_GRID_LABEL_RIGHT_DCLICK = _grid.wxEVT_GRID_LABEL_RIGHT_DCLICK
+wxEVT_GRID_ROW_SIZE = _grid.wxEVT_GRID_ROW_SIZE
+wxEVT_GRID_COL_SIZE = _grid.wxEVT_GRID_COL_SIZE
+wxEVT_GRID_RANGE_SELECT = _grid.wxEVT_GRID_RANGE_SELECT
+wxEVT_GRID_CELL_CHANGING = _grid.wxEVT_GRID_CELL_CHANGING
+wxEVT_GRID_CELL_CHANGED = _grid.wxEVT_GRID_CELL_CHANGED
+wxEVT_GRID_SELECT_CELL = _grid.wxEVT_GRID_SELECT_CELL
+wxEVT_GRID_EDITOR_SHOWN = _grid.wxEVT_GRID_EDITOR_SHOWN
+wxEVT_GRID_EDITOR_HIDDEN = _grid.wxEVT_GRID_EDITOR_HIDDEN
+wxEVT_GRID_EDITOR_CREATED = _grid.wxEVT_GRID_EDITOR_CREATED
+wxEVT_GRID_CELL_BEGIN_DRAG = _grid.wxEVT_GRID_CELL_BEGIN_DRAG
+wxEVT_GRID_COL_MOVE = _grid.wxEVT_GRID_COL_MOVE
+wxEVT_GRID_COL_SORT = _grid.wxEVT_GRID_COL_SORT
+EVT_GRID_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK )
+EVT_GRID_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK )
+EVT_GRID_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK )
+EVT_GRID_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK )
+EVT_GRID_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK )
+EVT_GRID_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK )
+EVT_GRID_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK )
+EVT_GRID_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK )
+EVT_GRID_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE )
+EVT_GRID_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE )
+EVT_GRID_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT )
+EVT_GRID_CELL_CHANGING = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGING )
+EVT_GRID_CELL_CHANGED = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGED )
+EVT_GRID_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL )
+EVT_GRID_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN )
+EVT_GRID_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN )
+EVT_GRID_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED )
+EVT_GRID_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG )
+EVT_GRID_COL_MOVE = wx.PyEventBinder( wxEVT_GRID_COL_MOVE )
+EVT_GRID_COL_SORT = wx.PyEventBinder( wxEVT_GRID_COL_SORT )
+
+# The same as above but with the ability to specify an identifier
+EVT_GRID_CMD_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK, 1 )
+EVT_GRID_CMD_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK, 1 )
+EVT_GRID_CMD_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK, 1 )
+EVT_GRID_CMD_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK, 1 )
+EVT_GRID_CMD_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK, 1 )
+EVT_GRID_CMD_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK, 1 )
+EVT_GRID_CMD_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK, 1 )
+EVT_GRID_CMD_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK, 1 )
+EVT_GRID_CMD_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE, 1 )
+EVT_GRID_CMD_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE, 1 )
+EVT_GRID_CMD_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT, 1 )
+EVT_GRID_CMD_CELL_CHANGING = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGING, 1 )
+EVT_GRID_CMD_CELL_CHANGED = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGED, 1 )
+EVT_GRID_CMD_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL, 1 )
+EVT_GRID_CMD_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN, 1 )
+EVT_GRID_CMD_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN, 1 )
+EVT_GRID_CMD_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED, 1 )
+EVT_GRID_CMD_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG, 1 )
+EVT_GRID_CMD_COL_MOVE = wx.PyEventBinder( wxEVT_GRID_COL_MOVE, 1 )
+EVT_GRID_CMD_COL_SORT = wx.PyEventBinder( wxEVT_GRID_COL_SORT, 1 )
+
+EVT_GRID_CELL_CHANGE = EVT_GRID_CELL_CHANGED
+EVT_GRID_CMD_CELL_CHANGE = EVT_GRID_CMD_CELL_CHANGED
+
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/html.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/html.py
new file mode 100644
index 0000000..8460f6b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/html.py
@@ -0,0 +1,2028 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+Classes for a simple HTML rendering window, HTML Help Window, etc.
+"""
+
+import _html
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _windows
+import _core
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+#---------------------------------------------------------------------------
+
+HTML_ALIGN_LEFT = _html.HTML_ALIGN_LEFT
+HTML_ALIGN_CENTER = _html.HTML_ALIGN_CENTER
+HTML_ALIGN_RIGHT = _html.HTML_ALIGN_RIGHT
+HTML_ALIGN_BOTTOM = _html.HTML_ALIGN_BOTTOM
+HTML_ALIGN_TOP = _html.HTML_ALIGN_TOP
+HTML_CLR_FOREGROUND = _html.HTML_CLR_FOREGROUND
+HTML_CLR_BACKGROUND = _html.HTML_CLR_BACKGROUND
+HTML_UNITS_PIXELS = _html.HTML_UNITS_PIXELS
+HTML_UNITS_PERCENT = _html.HTML_UNITS_PERCENT
+HTML_INDENT_LEFT = _html.HTML_INDENT_LEFT
+HTML_INDENT_RIGHT = _html.HTML_INDENT_RIGHT
+HTML_INDENT_TOP = _html.HTML_INDENT_TOP
+HTML_INDENT_BOTTOM = _html.HTML_INDENT_BOTTOM
+HTML_INDENT_HORIZONTAL = _html.HTML_INDENT_HORIZONTAL
+HTML_INDENT_VERTICAL = _html.HTML_INDENT_VERTICAL
+HTML_INDENT_ALL = _html.HTML_INDENT_ALL
+HTML_COND_ISANCHOR = _html.HTML_COND_ISANCHOR
+HTML_COND_ISIMAGEMAP = _html.HTML_COND_ISIMAGEMAP
+HTML_COND_USER = _html.HTML_COND_USER
+HW_SCROLLBAR_NEVER = _html.HW_SCROLLBAR_NEVER
+HW_SCROLLBAR_AUTO = _html.HW_SCROLLBAR_AUTO
+HW_NO_SELECTION = _html.HW_NO_SELECTION
+HW_DEFAULT_STYLE = _html.HW_DEFAULT_STYLE
+HTML_OPEN = _html.HTML_OPEN
+HTML_BLOCK = _html.HTML_BLOCK
+HTML_REDIRECT = _html.HTML_REDIRECT
+HTML_URL_PAGE = _html.HTML_URL_PAGE
+HTML_URL_IMAGE = _html.HTML_URL_IMAGE
+HTML_URL_OTHER = _html.HTML_URL_OTHER
+class HtmlLinkInfo(_core.Object):
+ """Proxy of C++ HtmlLinkInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String href, String target=EmptyString) -> HtmlLinkInfo"""
+ _html.HtmlLinkInfo_swiginit(self,_html.new_HtmlLinkInfo(*args, **kwargs))
+ __swig_destroy__ = _html.delete_HtmlLinkInfo
+ __del__ = lambda self : None;
+ def GetHref(*args, **kwargs):
+ """GetHref(self) -> String"""
+ return _html.HtmlLinkInfo_GetHref(*args, **kwargs)
+
+ def GetTarget(*args, **kwargs):
+ """GetTarget(self) -> String"""
+ return _html.HtmlLinkInfo_GetTarget(*args, **kwargs)
+
+ def GetEvent(*args, **kwargs):
+ """GetEvent(self) -> MouseEvent"""
+ return _html.HtmlLinkInfo_GetEvent(*args, **kwargs)
+
+ def GetHtmlCell(*args, **kwargs):
+ """GetHtmlCell(self) -> HtmlCell"""
+ return _html.HtmlLinkInfo_GetHtmlCell(*args, **kwargs)
+
+ def SetEvent(*args, **kwargs):
+ """SetEvent(self, MouseEvent e)"""
+ return _html.HtmlLinkInfo_SetEvent(*args, **kwargs)
+
+ def SetHtmlCell(*args, **kwargs):
+ """SetHtmlCell(self, HtmlCell e)"""
+ return _html.HtmlLinkInfo_SetHtmlCell(*args, **kwargs)
+
+ Event = property(GetEvent,SetEvent,doc="See `GetEvent` and `SetEvent`")
+ Href = property(GetHref,doc="See `GetHref`")
+ HtmlCell = property(GetHtmlCell,SetHtmlCell,doc="See `GetHtmlCell` and `SetHtmlCell`")
+ Target = property(GetTarget,doc="See `GetTarget`")
+_html.HtmlLinkInfo_swigregister(HtmlLinkInfo)
+cvar = _html.cvar
+HtmlWindowNameStr = cvar.HtmlWindowNameStr
+HtmlPrintoutTitleStr = cvar.HtmlPrintoutTitleStr
+HtmlPrintingTitleStr = cvar.HtmlPrintingTitleStr
+
+class HtmlTag(_core.Object):
+ """Proxy of C++ HtmlTag class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _html.HtmlTag_GetName(*args, **kwargs)
+
+ def HasParam(*args, **kwargs):
+ """HasParam(self, String par) -> bool"""
+ return _html.HtmlTag_HasParam(*args, **kwargs)
+
+ def GetParam(*args, **kwargs):
+ """GetParam(self, String par, int with_commas=False) -> String"""
+ return _html.HtmlTag_GetParam(*args, **kwargs)
+
+ def GetAllParams(*args, **kwargs):
+ """GetAllParams(self) -> String"""
+ return _html.HtmlTag_GetAllParams(*args, **kwargs)
+
+ def HasEnding(*args, **kwargs):
+ """HasEnding(self) -> bool"""
+ return _html.HtmlTag_HasEnding(*args, **kwargs)
+
+ def GetBeginPos(*args, **kwargs):
+ """GetBeginPos(self) -> int"""
+ return _html.HtmlTag_GetBeginPos(*args, **kwargs)
+
+ def GetEndPos1(*args, **kwargs):
+ """GetEndPos1(self) -> int"""
+ return _html.HtmlTag_GetEndPos1(*args, **kwargs)
+
+ def GetEndPos2(*args, **kwargs):
+ """GetEndPos2(self) -> int"""
+ return _html.HtmlTag_GetEndPos2(*args, **kwargs)
+
+ AllParams = property(GetAllParams,doc="See `GetAllParams`")
+ BeginPos = property(GetBeginPos,doc="See `GetBeginPos`")
+ EndPos1 = property(GetEndPos1,doc="See `GetEndPos1`")
+ EndPos2 = property(GetEndPos2,doc="See `GetEndPos2`")
+ Name = property(GetName,doc="See `GetName`")
+_html.HtmlTag_swigregister(HtmlTag)
+
+class HtmlParser(_core.Object):
+ """Proxy of C++ HtmlParser class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def SetFS(*args, **kwargs):
+ """SetFS(self, FileSystem fs)"""
+ return _html.HtmlParser_SetFS(*args, **kwargs)
+
+ def GetFS(*args, **kwargs):
+ """GetFS(self) -> FileSystem"""
+ return _html.HtmlParser_GetFS(*args, **kwargs)
+
+ def Parse(*args, **kwargs):
+ """Parse(self, String source) -> Object"""
+ return _html.HtmlParser_Parse(*args, **kwargs)
+
+ def InitParser(*args, **kwargs):
+ """InitParser(self, String source)"""
+ return _html.HtmlParser_InitParser(*args, **kwargs)
+
+ def DoneParser(*args, **kwargs):
+ """DoneParser(self)"""
+ return _html.HtmlParser_DoneParser(*args, **kwargs)
+
+ def DoParsing(*args, **kwargs):
+ """DoParsing(self)"""
+ return _html.HtmlParser_DoParsing(*args, **kwargs)
+
+ def StopParsing(*args, **kwargs):
+ """StopParsing(self)"""
+ return _html.HtmlParser_StopParsing(*args, **kwargs)
+
+ def AddTagHandler(*args, **kwargs):
+ """AddTagHandler(self, HtmlTagHandler handler)"""
+ return _html.HtmlParser_AddTagHandler(*args, **kwargs)
+
+ def PushTagHandler(*args, **kwargs):
+ """PushTagHandler(self, HtmlTagHandler handler, String tags)"""
+ return _html.HtmlParser_PushTagHandler(*args, **kwargs)
+
+ def PopTagHandler(*args, **kwargs):
+ """PopTagHandler(self)"""
+ return _html.HtmlParser_PopTagHandler(*args, **kwargs)
+
+ def GetSource(*args, **kwargs):
+ """GetSource(self) -> String"""
+ return _html.HtmlParser_GetSource(*args, **kwargs)
+
+ def GetInnerSource(*args, **kwargs):
+ """GetInnerSource(self, HtmlTag tag) -> String"""
+ return _html.HtmlParser_GetInnerSource(*args, **kwargs)
+
+ FS = property(GetFS,SetFS,doc="See `GetFS` and `SetFS`")
+ Source = property(GetSource,doc="See `GetSource`")
+_html.HtmlParser_swigregister(HtmlParser)
+
+class HtmlWinParser(HtmlParser):
+ """Proxy of C++ HtmlWinParser class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, HtmlWindow wnd=None) -> HtmlWinParser"""
+ _html.HtmlWinParser_swiginit(self,_html.new_HtmlWinParser(*args, **kwargs))
+ def SetDC(*args, **kwargs):
+ """SetDC(self, DC dc)"""
+ return _html.HtmlWinParser_SetDC(*args, **kwargs)
+
+ def GetDC(*args, **kwargs):
+ """GetDC(self) -> DC"""
+ return _html.HtmlWinParser_GetDC(*args, **kwargs)
+
+ def GetCharHeight(*args, **kwargs):
+ """GetCharHeight(self) -> int"""
+ return _html.HtmlWinParser_GetCharHeight(*args, **kwargs)
+
+ def GetCharWidth(*args, **kwargs):
+ """GetCharWidth(self) -> int"""
+ return _html.HtmlWinParser_GetCharWidth(*args, **kwargs)
+
+ def GetWindowInterface(*args, **kwargs):
+ """GetWindowInterface(self) -> HtmlWindowInterface"""
+ return _html.HtmlWinParser_GetWindowInterface(*args, **kwargs)
+
+ def SetFonts(*args, **kwargs):
+ """SetFonts(self, String normal_face, String fixed_face, PyObject sizes=None)"""
+ return _html.HtmlWinParser_SetFonts(*args, **kwargs)
+
+ def SetStandardFonts(*args, **kwargs):
+ """SetStandardFonts(self, int size=-1, String normal_face=EmptyString, String fixed_face=EmptyString)"""
+ return _html.HtmlWinParser_SetStandardFonts(*args, **kwargs)
+
+ def GetContainer(*args, **kwargs):
+ """GetContainer(self) -> HtmlContainerCell"""
+ return _html.HtmlWinParser_GetContainer(*args, **kwargs)
+
+ def OpenContainer(*args, **kwargs):
+ """OpenContainer(self) -> HtmlContainerCell"""
+ return _html.HtmlWinParser_OpenContainer(*args, **kwargs)
+
+ def SetContainer(*args, **kwargs):
+ """SetContainer(self, HtmlContainerCell c) -> HtmlContainerCell"""
+ return _html.HtmlWinParser_SetContainer(*args, **kwargs)
+
+ def CloseContainer(*args, **kwargs):
+ """CloseContainer(self) -> HtmlContainerCell"""
+ return _html.HtmlWinParser_CloseContainer(*args, **kwargs)
+
+ def GetFontSize(*args, **kwargs):
+ """GetFontSize(self) -> int"""
+ return _html.HtmlWinParser_GetFontSize(*args, **kwargs)
+
+ def SetFontSize(*args, **kwargs):
+ """SetFontSize(self, int s)"""
+ return _html.HtmlWinParser_SetFontSize(*args, **kwargs)
+
+ def SetFontPointSize(*args, **kwargs):
+ """SetFontPointSize(self, int pt)"""
+ return _html.HtmlWinParser_SetFontPointSize(*args, **kwargs)
+
+ def GetFontBold(*args, **kwargs):
+ """GetFontBold(self) -> int"""
+ return _html.HtmlWinParser_GetFontBold(*args, **kwargs)
+
+ def SetFontBold(*args, **kwargs):
+ """SetFontBold(self, int x)"""
+ return _html.HtmlWinParser_SetFontBold(*args, **kwargs)
+
+ def GetFontItalic(*args, **kwargs):
+ """GetFontItalic(self) -> int"""
+ return _html.HtmlWinParser_GetFontItalic(*args, **kwargs)
+
+ def SetFontItalic(*args, **kwargs):
+ """SetFontItalic(self, int x)"""
+ return _html.HtmlWinParser_SetFontItalic(*args, **kwargs)
+
+ def GetFontUnderlined(*args, **kwargs):
+ """GetFontUnderlined(self) -> int"""
+ return _html.HtmlWinParser_GetFontUnderlined(*args, **kwargs)
+
+ def SetFontUnderlined(*args, **kwargs):
+ """SetFontUnderlined(self, int x)"""
+ return _html.HtmlWinParser_SetFontUnderlined(*args, **kwargs)
+
+ def GetFontFixed(*args, **kwargs):
+ """GetFontFixed(self) -> int"""
+ return _html.HtmlWinParser_GetFontFixed(*args, **kwargs)
+
+ def SetFontFixed(*args, **kwargs):
+ """SetFontFixed(self, int x)"""
+ return _html.HtmlWinParser_SetFontFixed(*args, **kwargs)
+
+ def GetAlign(*args, **kwargs):
+ """GetAlign(self) -> int"""
+ return _html.HtmlWinParser_GetAlign(*args, **kwargs)
+
+ def SetAlign(*args, **kwargs):
+ """SetAlign(self, int a)"""
+ return _html.HtmlWinParser_SetAlign(*args, **kwargs)
+
+ def GetLinkColor(*args, **kwargs):
+ """GetLinkColor(self) -> Colour"""
+ return _html.HtmlWinParser_GetLinkColor(*args, **kwargs)
+
+ def SetLinkColor(*args, **kwargs):
+ """SetLinkColor(self, Colour clr)"""
+ return _html.HtmlWinParser_SetLinkColor(*args, **kwargs)
+
+ GetLinkColour = GetLinkColor
+ SetLinkColour = SetLinkColor
+
+ def GetActualColor(*args, **kwargs):
+ """GetActualColor(self) -> Colour"""
+ return _html.HtmlWinParser_GetActualColor(*args, **kwargs)
+
+ def SetActualColor(*args, **kwargs):
+ """SetActualColor(self, Colour clr)"""
+ return _html.HtmlWinParser_SetActualColor(*args, **kwargs)
+
+ GetActualColour = GetActualColor
+ SetActualColour = SetActualColor
+
+ def SetLink(*args, **kwargs):
+ """SetLink(self, String link)"""
+ return _html.HtmlWinParser_SetLink(*args, **kwargs)
+
+ def CreateCurrentFont(*args, **kwargs):
+ """CreateCurrentFont(self) -> Font"""
+ return _html.HtmlWinParser_CreateCurrentFont(*args, **kwargs)
+
+ def GetLink(*args, **kwargs):
+ """GetLink(self) -> HtmlLinkInfo"""
+ return _html.HtmlWinParser_GetLink(*args, **kwargs)
+
+ ActualColor = property(GetActualColor,SetActualColor,doc="See `GetActualColor` and `SetActualColor`")
+ ActualColour = property(GetActualColour,SetActualColour,doc="See `GetActualColour` and `SetActualColour`")
+ Align = property(GetAlign,SetAlign,doc="See `GetAlign` and `SetAlign`")
+ CharHeight = property(GetCharHeight,doc="See `GetCharHeight`")
+ CharWidth = property(GetCharWidth,doc="See `GetCharWidth`")
+ Container = property(GetContainer,SetContainer,doc="See `GetContainer` and `SetContainer`")
+ DC = property(GetDC,SetDC,doc="See `GetDC` and `SetDC`")
+ FontBold = property(GetFontBold,SetFontBold,doc="See `GetFontBold` and `SetFontBold`")
+ FontFixed = property(GetFontFixed,SetFontFixed,doc="See `GetFontFixed` and `SetFontFixed`")
+ FontItalic = property(GetFontItalic,SetFontItalic,doc="See `GetFontItalic` and `SetFontItalic`")
+ FontSize = property(GetFontSize,SetFontSize,doc="See `GetFontSize` and `SetFontSize`")
+ FontUnderlined = property(GetFontUnderlined,SetFontUnderlined,doc="See `GetFontUnderlined` and `SetFontUnderlined`")
+ Link = property(GetLink,SetLink,doc="See `GetLink` and `SetLink`")
+ LinkColor = property(GetLinkColor,SetLinkColor,doc="See `GetLinkColor` and `SetLinkColor`")
+ LinkColour = property(GetLinkColour,SetLinkColour,doc="See `GetLinkColour` and `SetLinkColour`")
+ WindowInterface = property(GetWindowInterface,doc="See `GetWindowInterface`")
+_html.HtmlWinParser_swigregister(HtmlWinParser)
+
+class HtmlTagHandler(_core.Object):
+ """Proxy of C++ HtmlTagHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> HtmlTagHandler"""
+ _html.HtmlTagHandler_swiginit(self,_html.new_HtmlTagHandler(*args, **kwargs))
+ HtmlTagHandler._setCallbackInfo(self, self, HtmlTagHandler)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _html.HtmlTagHandler__setCallbackInfo(*args, **kwargs)
+
+ def SetParser(*args, **kwargs):
+ """SetParser(self, HtmlParser parser)"""
+ return _html.HtmlTagHandler_SetParser(*args, **kwargs)
+
+ def GetParser(*args, **kwargs):
+ """GetParser(self) -> HtmlParser"""
+ return _html.HtmlTagHandler_GetParser(*args, **kwargs)
+
+ def ParseInner(*args, **kwargs):
+ """ParseInner(self, HtmlTag tag)"""
+ return _html.HtmlTagHandler_ParseInner(*args, **kwargs)
+
+ Parser = property(GetParser,SetParser,doc="See `GetParser` and `SetParser`")
+_html.HtmlTagHandler_swigregister(HtmlTagHandler)
+
+class HtmlWinTagHandler(HtmlTagHandler):
+ """Proxy of C++ HtmlWinTagHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> HtmlWinTagHandler"""
+ _html.HtmlWinTagHandler_swiginit(self,_html.new_HtmlWinTagHandler(*args, **kwargs))
+ HtmlWinTagHandler._setCallbackInfo(self, self, HtmlWinTagHandler)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _html.HtmlWinTagHandler__setCallbackInfo(*args, **kwargs)
+
+ def SetParser(*args, **kwargs):
+ """SetParser(self, HtmlParser parser)"""
+ return _html.HtmlWinTagHandler_SetParser(*args, **kwargs)
+
+ def GetParser(*args, **kwargs):
+ """GetParser(self) -> HtmlWinParser"""
+ return _html.HtmlWinTagHandler_GetParser(*args, **kwargs)
+
+ def ParseInner(*args, **kwargs):
+ """ParseInner(self, HtmlTag tag)"""
+ return _html.HtmlWinTagHandler_ParseInner(*args, **kwargs)
+
+ Parser = property(GetParser,SetParser,doc="See `GetParser` and `SetParser`")
+_html.HtmlWinTagHandler_swigregister(HtmlWinTagHandler)
+
+
+def HtmlWinParser_AddTagHandler(*args, **kwargs):
+ """HtmlWinParser_AddTagHandler(PyObject tagHandlerClass)"""
+ return _html.HtmlWinParser_AddTagHandler(*args, **kwargs)
+#---------------------------------------------------------------------------
+
+class HtmlSelection(object):
+ """Proxy of C++ HtmlSelection class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> HtmlSelection"""
+ _html.HtmlSelection_swiginit(self,_html.new_HtmlSelection(*args, **kwargs))
+ __swig_destroy__ = _html.delete_HtmlSelection
+ __del__ = lambda self : None;
+ def Set(*args, **kwargs):
+ """Set(self, Point fromPos, HtmlCell fromCell, Point toPos, HtmlCell toCell)"""
+ return _html.HtmlSelection_Set(*args, **kwargs)
+
+ def SetCells(*args, **kwargs):
+ """SetCells(self, HtmlCell fromCell, HtmlCell toCell)"""
+ return _html.HtmlSelection_SetCells(*args, **kwargs)
+
+ def GetFromCell(*args, **kwargs):
+ """GetFromCell(self) -> HtmlCell"""
+ return _html.HtmlSelection_GetFromCell(*args, **kwargs)
+
+ def GetToCell(*args, **kwargs):
+ """GetToCell(self) -> HtmlCell"""
+ return _html.HtmlSelection_GetToCell(*args, **kwargs)
+
+ def GetFromPos(*args, **kwargs):
+ """GetFromPos(self) -> Point"""
+ return _html.HtmlSelection_GetFromPos(*args, **kwargs)
+
+ def GetToPos(*args, **kwargs):
+ """GetToPos(self) -> Point"""
+ return _html.HtmlSelection_GetToPos(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """IsEmpty(self) -> bool"""
+ return _html.HtmlSelection_IsEmpty(*args, **kwargs)
+
+ FromCell = property(GetFromCell,doc="See `GetFromCell`")
+ FromPos = property(GetFromPos,doc="See `GetFromPos`")
+ ToCell = property(GetToCell,doc="See `GetToCell`")
+ ToPos = property(GetToPos,doc="See `GetToPos`")
+_html.HtmlSelection_swigregister(HtmlSelection)
+
+HTML_SEL_OUT = _html.HTML_SEL_OUT
+HTML_SEL_IN = _html.HTML_SEL_IN
+HTML_SEL_CHANGING = _html.HTML_SEL_CHANGING
+class HtmlRenderingState(object):
+ """Proxy of C++ HtmlRenderingState class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> HtmlRenderingState"""
+ _html.HtmlRenderingState_swiginit(self,_html.new_HtmlRenderingState(*args, **kwargs))
+ __swig_destroy__ = _html.delete_HtmlRenderingState
+ __del__ = lambda self : None;
+ def SetSelectionState(*args, **kwargs):
+ """SetSelectionState(self, int s)"""
+ return _html.HtmlRenderingState_SetSelectionState(*args, **kwargs)
+
+ def GetSelectionState(*args, **kwargs):
+ """GetSelectionState(self) -> int"""
+ return _html.HtmlRenderingState_GetSelectionState(*args, **kwargs)
+
+ def SetFgColour(*args, **kwargs):
+ """SetFgColour(self, Colour c)"""
+ return _html.HtmlRenderingState_SetFgColour(*args, **kwargs)
+
+ def GetFgColour(*args, **kwargs):
+ """GetFgColour(self) -> Colour"""
+ return _html.HtmlRenderingState_GetFgColour(*args, **kwargs)
+
+ def SetBgColour(*args, **kwargs):
+ """SetBgColour(self, Colour c)"""
+ return _html.HtmlRenderingState_SetBgColour(*args, **kwargs)
+
+ def GetBgColour(*args, **kwargs):
+ """GetBgColour(self) -> Colour"""
+ return _html.HtmlRenderingState_GetBgColour(*args, **kwargs)
+
+ BgColour = property(GetBgColour,SetBgColour,doc="See `GetBgColour` and `SetBgColour`")
+ FgColour = property(GetFgColour,SetFgColour,doc="See `GetFgColour` and `SetFgColour`")
+ SelectionState = property(GetSelectionState,SetSelectionState,doc="See `GetSelectionState` and `SetSelectionState`")
+_html.HtmlRenderingState_swigregister(HtmlRenderingState)
+
+class HtmlRenderingStyle(object):
+ """Proxy of C++ HtmlRenderingStyle class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetSelectedTextColour(*args, **kwargs):
+ """GetSelectedTextColour(self, Colour clr) -> Colour"""
+ return _html.HtmlRenderingStyle_GetSelectedTextColour(*args, **kwargs)
+
+ def GetSelectedTextBgColour(*args, **kwargs):
+ """GetSelectedTextBgColour(self, Colour clr) -> Colour"""
+ return _html.HtmlRenderingStyle_GetSelectedTextBgColour(*args, **kwargs)
+
+ SelectedTextBgColour = property(GetSelectedTextBgColour,doc="See `GetSelectedTextBgColour`")
+ SelectedTextColour = property(GetSelectedTextColour,doc="See `GetSelectedTextColour`")
+_html.HtmlRenderingStyle_swigregister(HtmlRenderingStyle)
+
+class DefaultHtmlRenderingStyle(HtmlRenderingStyle):
+ """Proxy of C++ DefaultHtmlRenderingStyle class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+_html.DefaultHtmlRenderingStyle_swigregister(DefaultHtmlRenderingStyle)
+
+class HtmlRenderingInfo(object):
+ """Proxy of C++ HtmlRenderingInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> HtmlRenderingInfo"""
+ _html.HtmlRenderingInfo_swiginit(self,_html.new_HtmlRenderingInfo(*args, **kwargs))
+ __swig_destroy__ = _html.delete_HtmlRenderingInfo
+ __del__ = lambda self : None;
+ def SetSelection(*args, **kwargs):
+ """SetSelection(self, HtmlSelection s)"""
+ return _html.HtmlRenderingInfo_SetSelection(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> HtmlSelection"""
+ return _html.HtmlRenderingInfo_GetSelection(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """SetStyle(self, HtmlRenderingStyle style)"""
+ return _html.HtmlRenderingInfo_SetStyle(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self) -> HtmlRenderingStyle"""
+ return _html.HtmlRenderingInfo_GetStyle(*args, **kwargs)
+
+ def GetState(*args, **kwargs):
+ """GetState(self) -> HtmlRenderingState"""
+ return _html.HtmlRenderingInfo_GetState(*args, **kwargs)
+
+ Selection = property(GetSelection,SetSelection,doc="See `GetSelection` and `SetSelection`")
+ State = property(GetState,doc="See `GetState`")
+ Style = property(GetStyle,SetStyle,doc="See `GetStyle` and `SetStyle`")
+_html.HtmlRenderingInfo_swigregister(HtmlRenderingInfo)
+
+#---------------------------------------------------------------------------
+
+HTML_FIND_EXACT = _html.HTML_FIND_EXACT
+HTML_FIND_NEAREST_BEFORE = _html.HTML_FIND_NEAREST_BEFORE
+HTML_FIND_NEAREST_AFTER = _html.HTML_FIND_NEAREST_AFTER
+class HtmlCell(_core.Object):
+ """Proxy of C++ HtmlCell class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> HtmlCell"""
+ _html.HtmlCell_swiginit(self,_html.new_HtmlCell(*args, **kwargs))
+ __swig_destroy__ = _html.delete_HtmlCell
+ __del__ = lambda self : None;
+ def GetPosX(*args, **kwargs):
+ """GetPosX(self) -> int"""
+ return _html.HtmlCell_GetPosX(*args, **kwargs)
+
+ def GetPosY(*args, **kwargs):
+ """GetPosY(self) -> int"""
+ return _html.HtmlCell_GetPosY(*args, **kwargs)
+
+ def GetWidth(*args, **kwargs):
+ """GetWidth(self) -> int"""
+ return _html.HtmlCell_GetWidth(*args, **kwargs)
+
+ def GetHeight(*args, **kwargs):
+ """GetHeight(self) -> int"""
+ return _html.HtmlCell_GetHeight(*args, **kwargs)
+
+ def GetDescent(*args, **kwargs):
+ """GetDescent(self) -> int"""
+ return _html.HtmlCell_GetDescent(*args, **kwargs)
+
+ def GetMaxTotalWidth(*args, **kwargs):
+ """GetMaxTotalWidth(self) -> int"""
+ return _html.HtmlCell_GetMaxTotalWidth(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """GetId(self) -> String"""
+ return _html.HtmlCell_GetId(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """SetId(self, String id)"""
+ return _html.HtmlCell_SetId(*args, **kwargs)
+
+ def GetLink(*args, **kwargs):
+ """GetLink(self, int x=0, int y=0) -> HtmlLinkInfo"""
+ return _html.HtmlCell_GetLink(*args, **kwargs)
+
+ def GetNext(*args, **kwargs):
+ """GetNext(self) -> HtmlCell"""
+ return _html.HtmlCell_GetNext(*args, **kwargs)
+
+ def GetParent(*args, **kwargs):
+ """GetParent(self) -> HtmlContainerCell"""
+ return _html.HtmlCell_GetParent(*args, **kwargs)
+
+ def GetFirstChild(*args, **kwargs):
+ """GetFirstChild(self) -> HtmlCell"""
+ return _html.HtmlCell_GetFirstChild(*args, **kwargs)
+
+ def GetMouseCursor(*args, **kwargs):
+ """GetMouseCursor(self, HtmlWindowInterface window) -> Cursor"""
+ return _html.HtmlCell_GetMouseCursor(*args, **kwargs)
+
+ def IsFormattingCell(*args, **kwargs):
+ """IsFormattingCell(self) -> bool"""
+ return _html.HtmlCell_IsFormattingCell(*args, **kwargs)
+
+ def SetLink(*args, **kwargs):
+ """SetLink(self, HtmlLinkInfo link)"""
+ return _html.HtmlCell_SetLink(*args, **kwargs)
+
+ def SetNext(*args, **kwargs):
+ """SetNext(self, HtmlCell cell)"""
+ return _html.HtmlCell_SetNext(*args, **kwargs)
+
+ def SetParent(*args, **kwargs):
+ """SetParent(self, HtmlContainerCell p)"""
+ return _html.HtmlCell_SetParent(*args, **kwargs)
+
+ def SetPos(*args, **kwargs):
+ """SetPos(self, int x, int y)"""
+ return _html.HtmlCell_SetPos(*args, **kwargs)
+
+ def Layout(*args, **kwargs):
+ """Layout(self, int w)"""
+ return _html.HtmlCell_Layout(*args, **kwargs)
+
+ def Draw(*args, **kwargs):
+ """Draw(self, DC dc, int x, int y, int view_y1, int view_y2, HtmlRenderingInfo info)"""
+ return _html.HtmlCell_Draw(*args, **kwargs)
+
+ def DrawInvisible(*args, **kwargs):
+ """DrawInvisible(self, DC dc, int x, int y, HtmlRenderingInfo info)"""
+ return _html.HtmlCell_DrawInvisible(*args, **kwargs)
+
+ def Find(*args, **kwargs):
+ """Find(self, int condition, void param) -> HtmlCell"""
+ return _html.HtmlCell_Find(*args, **kwargs)
+
+ def ProcessMouseClick(*args, **kwargs):
+ """ProcessMouseClick(self, HtmlWindowInterface window, Point pos, MouseEvent event) -> bool"""
+ return _html.HtmlCell_ProcessMouseClick(*args, **kwargs)
+
+ def SetCanLiveOnPagebreak(*args, **kwargs):
+ """SetCanLiveOnPagebreak(self, bool can)"""
+ return _html.HtmlCell_SetCanLiveOnPagebreak(*args, **kwargs)
+
+ def IsLinebreakAllowed(*args, **kwargs):
+ """IsLinebreakAllowed(self) -> bool"""
+ return _html.HtmlCell_IsLinebreakAllowed(*args, **kwargs)
+
+ def IsTerminalCell(*args, **kwargs):
+ """IsTerminalCell(self) -> bool"""
+ return _html.HtmlCell_IsTerminalCell(*args, **kwargs)
+
+ def FindCellByPos(*args, **kwargs):
+ """FindCellByPos(self, int x, int y, unsigned int flags=HTML_FIND_EXACT) -> HtmlCell"""
+ return _html.HtmlCell_FindCellByPos(*args, **kwargs)
+
+ def GetAbsPos(*args, **kwargs):
+ """GetAbsPos(self, HtmlCell rootCell=None) -> Point"""
+ return _html.HtmlCell_GetAbsPos(*args, **kwargs)
+
+ def GetRootCell(*args, **kwargs):
+ """GetRootCell(self) -> HtmlCell"""
+ return _html.HtmlCell_GetRootCell(*args, **kwargs)
+
+ def GetFirstTerminal(*args, **kwargs):
+ """GetFirstTerminal(self) -> HtmlCell"""
+ return _html.HtmlCell_GetFirstTerminal(*args, **kwargs)
+
+ def GetLastTerminal(*args, **kwargs):
+ """GetLastTerminal(self) -> HtmlCell"""
+ return _html.HtmlCell_GetLastTerminal(*args, **kwargs)
+
+ def GetDepth(*args, **kwargs):
+ """GetDepth(self) -> unsigned int"""
+ return _html.HtmlCell_GetDepth(*args, **kwargs)
+
+ def IsBefore(*args, **kwargs):
+ """IsBefore(self, HtmlCell cell) -> bool"""
+ return _html.HtmlCell_IsBefore(*args, **kwargs)
+
+ def ConvertToText(*args, **kwargs):
+ """ConvertToText(self, HtmlSelection sel) -> String"""
+ return _html.HtmlCell_ConvertToText(*args, **kwargs)
+
+ Depth = property(GetDepth,doc="See `GetDepth`")
+ Descent = property(GetDescent,doc="See `GetDescent`")
+ FirstChild = property(GetFirstChild,doc="See `GetFirstChild`")
+ FirstTerminal = property(GetFirstTerminal,doc="See `GetFirstTerminal`")
+ Height = property(GetHeight,doc="See `GetHeight`")
+ Id = property(GetId,SetId,doc="See `GetId` and `SetId`")
+ LastTerminal = property(GetLastTerminal,doc="See `GetLastTerminal`")
+ Link = property(GetLink,SetLink,doc="See `GetLink` and `SetLink`")
+ MaxTotalWidth = property(GetMaxTotalWidth,doc="See `GetMaxTotalWidth`")
+ MouseCursor = property(GetMouseCursor,doc="See `GetMouseCursor`")
+ Next = property(GetNext,SetNext,doc="See `GetNext` and `SetNext`")
+ Parent = property(GetParent,SetParent,doc="See `GetParent` and `SetParent`")
+ PosX = property(GetPosX,doc="See `GetPosX`")
+ PosY = property(GetPosY,doc="See `GetPosY`")
+ RootCell = property(GetRootCell,doc="See `GetRootCell`")
+ Width = property(GetWidth,doc="See `GetWidth`")
+_html.HtmlCell_swigregister(HtmlCell)
+
+class HtmlWordCell(HtmlCell):
+ """Proxy of C++ HtmlWordCell class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String word, DC dc) -> HtmlWordCell"""
+ _html.HtmlWordCell_swiginit(self,_html.new_HtmlWordCell(*args, **kwargs))
+ def ConvertToText(*args, **kwargs):
+ """ConvertToText(self, HtmlSelection sel) -> String"""
+ return _html.HtmlWordCell_ConvertToText(*args, **kwargs)
+
+ def IsLinebreakAllowed(*args, **kwargs):
+ """IsLinebreakAllowed(self) -> bool"""
+ return _html.HtmlWordCell_IsLinebreakAllowed(*args, **kwargs)
+
+ def SetPreviousWord(*args, **kwargs):
+ """SetPreviousWord(self, HtmlWordCell cell)"""
+ return _html.HtmlWordCell_SetPreviousWord(*args, **kwargs)
+
+_html.HtmlWordCell_swigregister(HtmlWordCell)
+
+class HtmlWordWithTabsCell(HtmlWordCell):
+ """Proxy of C++ HtmlWordWithTabsCell class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String word, String wordOrig, size_t linepos, DC dc) -> HtmlWordWithTabsCell"""
+ _html.HtmlWordWithTabsCell_swiginit(self,_html.new_HtmlWordWithTabsCell(*args, **kwargs))
+_html.HtmlWordWithTabsCell_swigregister(HtmlWordWithTabsCell)
+
+class HtmlContainerCell(HtmlCell):
+ """Proxy of C++ HtmlContainerCell class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, HtmlContainerCell parent) -> HtmlContainerCell"""
+ _html.HtmlContainerCell_swiginit(self,_html.new_HtmlContainerCell(*args, **kwargs))
+ def InsertCell(*args, **kwargs):
+ """InsertCell(self, HtmlCell cell)"""
+ return _html.HtmlContainerCell_InsertCell(*args, **kwargs)
+
+ def SetAlignHor(*args, **kwargs):
+ """SetAlignHor(self, int al)"""
+ return _html.HtmlContainerCell_SetAlignHor(*args, **kwargs)
+
+ def GetAlignHor(*args, **kwargs):
+ """GetAlignHor(self) -> int"""
+ return _html.HtmlContainerCell_GetAlignHor(*args, **kwargs)
+
+ def SetAlignVer(*args, **kwargs):
+ """SetAlignVer(self, int al)"""
+ return _html.HtmlContainerCell_SetAlignVer(*args, **kwargs)
+
+ def GetAlignVer(*args, **kwargs):
+ """GetAlignVer(self) -> int"""
+ return _html.HtmlContainerCell_GetAlignVer(*args, **kwargs)
+
+ def SetIndent(*args, **kwargs):
+ """SetIndent(self, int i, int what, int units=HTML_UNITS_PIXELS)"""
+ return _html.HtmlContainerCell_SetIndent(*args, **kwargs)
+
+ def GetIndent(*args, **kwargs):
+ """GetIndent(self, int ind) -> int"""
+ return _html.HtmlContainerCell_GetIndent(*args, **kwargs)
+
+ def GetIndentUnits(*args, **kwargs):
+ """GetIndentUnits(self, int ind) -> int"""
+ return _html.HtmlContainerCell_GetIndentUnits(*args, **kwargs)
+
+ def SetAlign(*args, **kwargs):
+ """SetAlign(self, HtmlTag tag)"""
+ return _html.HtmlContainerCell_SetAlign(*args, **kwargs)
+
+ def SetWidthFloat(*args, **kwargs):
+ """SetWidthFloat(self, int w, int units)"""
+ return _html.HtmlContainerCell_SetWidthFloat(*args, **kwargs)
+
+ def SetWidthFloatFromTag(*args, **kwargs):
+ """SetWidthFloatFromTag(self, HtmlTag tag)"""
+ return _html.HtmlContainerCell_SetWidthFloatFromTag(*args, **kwargs)
+
+ def SetMinHeight(*args, **kwargs):
+ """SetMinHeight(self, int h, int align=HTML_ALIGN_TOP)"""
+ return _html.HtmlContainerCell_SetMinHeight(*args, **kwargs)
+
+ def SetBackgroundColour(*args, **kwargs):
+ """SetBackgroundColour(self, Colour clr)"""
+ return _html.HtmlContainerCell_SetBackgroundColour(*args, **kwargs)
+
+ def GetBackgroundColour(*args, **kwargs):
+ """GetBackgroundColour(self) -> Colour"""
+ return _html.HtmlContainerCell_GetBackgroundColour(*args, **kwargs)
+
+ def SetBorder(*args, **kwargs):
+ """SetBorder(self, Colour clr1, Colour clr2, int border=1)"""
+ return _html.HtmlContainerCell_SetBorder(*args, **kwargs)
+
+ def GetFirstChild(*args, **kwargs):
+ """GetFirstChild(self) -> HtmlCell"""
+ return _html.HtmlContainerCell_GetFirstChild(*args, **kwargs)
+
+ AlignHor = property(GetAlignHor,SetAlignHor,doc="See `GetAlignHor` and `SetAlignHor`")
+ AlignVer = property(GetAlignVer,SetAlignVer,doc="See `GetAlignVer` and `SetAlignVer`")
+ BackgroundColour = property(GetBackgroundColour,SetBackgroundColour,doc="See `GetBackgroundColour` and `SetBackgroundColour`")
+ FirstChild = property(GetFirstChild,doc="See `GetFirstChild`")
+ Indent = property(GetIndent,SetIndent,doc="See `GetIndent` and `SetIndent`")
+ IndentUnits = property(GetIndentUnits,doc="See `GetIndentUnits`")
+_html.HtmlContainerCell_swigregister(HtmlContainerCell)
+
+class HtmlColourCell(HtmlCell):
+ """Proxy of C++ HtmlColourCell class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Colour clr, int flags=HTML_CLR_FOREGROUND) -> HtmlColourCell"""
+ _html.HtmlColourCell_swiginit(self,_html.new_HtmlColourCell(*args, **kwargs))
+_html.HtmlColourCell_swigregister(HtmlColourCell)
+
+class HtmlFontCell(HtmlCell):
+ """Proxy of C++ HtmlFontCell class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Font font) -> HtmlFontCell"""
+ _html.HtmlFontCell_swiginit(self,_html.new_HtmlFontCell(*args, **kwargs))
+_html.HtmlFontCell_swigregister(HtmlFontCell)
+
+class HtmlWidgetCell(HtmlCell):
+ """Proxy of C++ HtmlWidgetCell class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window wnd, int w=0) -> HtmlWidgetCell"""
+ _html.HtmlWidgetCell_swiginit(self,_html.new_HtmlWidgetCell(*args, **kwargs))
+_html.HtmlWidgetCell_swigregister(HtmlWidgetCell)
+
+#---------------------------------------------------------------------------
+
+class HtmlFilter(_core.Object):
+ """Proxy of C++ HtmlFilter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> HtmlFilter"""
+ _html.HtmlFilter_swiginit(self,_html.new_HtmlFilter(*args, **kwargs))
+ HtmlFilter._setCallbackInfo(self, self, HtmlFilter)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _html.HtmlFilter__setCallbackInfo(*args, **kwargs)
+
+_html.HtmlFilter_swigregister(HtmlFilter)
+
+class HtmlWindowInterface(object):
+ """Proxy of C++ HtmlWindowInterface class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _html.delete_HtmlWindowInterface
+ __del__ = lambda self : None;
+ def SetHTMLWindowTitle(*args, **kwargs):
+ """SetHTMLWindowTitle(self, String title)"""
+ return _html.HtmlWindowInterface_SetHTMLWindowTitle(*args, **kwargs)
+
+ def HTMLCoordsToWindow(*args, **kwargs):
+ """HTMLCoordsToWindow(self, HtmlCell cell, Point pos) -> Point"""
+ return _html.HtmlWindowInterface_HTMLCoordsToWindow(*args, **kwargs)
+
+ def GetHTMLWindow(*args, **kwargs):
+ """GetHTMLWindow(self) -> Window"""
+ return _html.HtmlWindowInterface_GetHTMLWindow(*args, **kwargs)
+
+ def GetHTMLBackgroundColour(*args, **kwargs):
+ """GetHTMLBackgroundColour(self) -> Colour"""
+ return _html.HtmlWindowInterface_GetHTMLBackgroundColour(*args, **kwargs)
+
+ def SetHTMLBackgroundColour(*args, **kwargs):
+ """SetHTMLBackgroundColour(self, Colour clr)"""
+ return _html.HtmlWindowInterface_SetHTMLBackgroundColour(*args, **kwargs)
+
+ def SetHTMLBackgroundImage(*args, **kwargs):
+ """SetHTMLBackgroundImage(self, Bitmap bmpBg)"""
+ return _html.HtmlWindowInterface_SetHTMLBackgroundImage(*args, **kwargs)
+
+ def SetHTMLStatusText(*args, **kwargs):
+ """SetHTMLStatusText(self, String text)"""
+ return _html.HtmlWindowInterface_SetHTMLStatusText(*args, **kwargs)
+
+ HTMLCursor_Default = _html.HtmlWindowInterface_HTMLCursor_Default
+ HTMLCursor_Link = _html.HtmlWindowInterface_HTMLCursor_Link
+ HTMLCursor_Text = _html.HtmlWindowInterface_HTMLCursor_Text
+ HTMLBackgroundColour = property(GetHTMLBackgroundColour,SetHTMLBackgroundColour,doc="See `GetHTMLBackgroundColour` and `SetHTMLBackgroundColour`")
+ HTMLWindow = property(GetHTMLWindow,doc="See `GetHTMLWindow`")
+_html.HtmlWindowInterface_swigregister(HtmlWindowInterface)
+
+#---------------------------------------------------------------------------
+
+class HtmlWindow(_windows.ScrolledWindow):
+ """Proxy of C++ HtmlWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, int style=HW_DEFAULT_STYLE,
+ String name=HtmlWindowNameStr) -> HtmlWindow
+ """
+ _html.HtmlWindow_swiginit(self,_html.new_HtmlWindow(*args, **kwargs))
+ self._setOORInfo(self);HtmlWindow._setCallbackInfo(self, self, HtmlWindow)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, Point pos=DefaultPosition,
+ Size size=DefaultSize, int style=HW_SCROLLBAR_AUTO,
+ String name=HtmlWindowNameStr) -> bool
+ """
+ return _html.HtmlWindow_Create(*args, **kwargs)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _html.HtmlWindow__setCallbackInfo(*args, **kwargs)
+
+ def SetPage(*args, **kwargs):
+ """SetPage(self, String source) -> bool"""
+ return _html.HtmlWindow_SetPage(*args, **kwargs)
+
+ def LoadPage(*args, **kwargs):
+ """LoadPage(self, String location) -> bool"""
+ return _html.HtmlWindow_LoadPage(*args, **kwargs)
+
+ def LoadFile(*args, **kwargs):
+ """LoadFile(self, String filename) -> bool"""
+ return _html.HtmlWindow_LoadFile(*args, **kwargs)
+
+ def AppendToPage(*args, **kwargs):
+ """AppendToPage(self, String source) -> bool"""
+ return _html.HtmlWindow_AppendToPage(*args, **kwargs)
+
+ def GetOpenedPage(*args, **kwargs):
+ """GetOpenedPage(self) -> String"""
+ return _html.HtmlWindow_GetOpenedPage(*args, **kwargs)
+
+ def GetOpenedAnchor(*args, **kwargs):
+ """GetOpenedAnchor(self) -> String"""
+ return _html.HtmlWindow_GetOpenedAnchor(*args, **kwargs)
+
+ def GetOpenedPageTitle(*args, **kwargs):
+ """GetOpenedPageTitle(self) -> String"""
+ return _html.HtmlWindow_GetOpenedPageTitle(*args, **kwargs)
+
+ def SetRelatedFrame(*args, **kwargs):
+ """SetRelatedFrame(self, Frame frame, String format)"""
+ return _html.HtmlWindow_SetRelatedFrame(*args, **kwargs)
+
+ def GetRelatedFrame(*args, **kwargs):
+ """GetRelatedFrame(self) -> Frame"""
+ return _html.HtmlWindow_GetRelatedFrame(*args, **kwargs)
+
+ def SetRelatedStatusBar(*args):
+ """
+ SetRelatedStatusBar(self, int bar)
+ SetRelatedStatusBar(self, StatusBar ?, int index=0)
+ """
+ return _html.HtmlWindow_SetRelatedStatusBar(*args)
+
+ def SetFonts(*args, **kwargs):
+ """SetFonts(self, String normal_face, String fixed_face, PyObject sizes=None)"""
+ return _html.HtmlWindow_SetFonts(*args, **kwargs)
+
+ def SetStandardFonts(*args, **kwargs):
+ """SetStandardFonts(self, int size=-1, String normal_face=EmptyString, String fixed_face=EmptyString)"""
+ return _html.HtmlWindow_SetStandardFonts(*args, **kwargs)
+
+ def SetBorders(*args, **kwargs):
+ """SetBorders(self, int b)"""
+ return _html.HtmlWindow_SetBorders(*args, **kwargs)
+
+ def SetBackgroundImage(*args, **kwargs):
+ """SetBackgroundImage(self, Bitmap bmpBg)"""
+ return _html.HtmlWindow_SetBackgroundImage(*args, **kwargs)
+
+ def ReadCustomization(*args, **kwargs):
+ """ReadCustomization(self, ConfigBase cfg, String path=EmptyString)"""
+ return _html.HtmlWindow_ReadCustomization(*args, **kwargs)
+
+ def WriteCustomization(*args, **kwargs):
+ """WriteCustomization(self, ConfigBase cfg, String path=EmptyString)"""
+ return _html.HtmlWindow_WriteCustomization(*args, **kwargs)
+
+ def HistoryBack(*args, **kwargs):
+ """HistoryBack(self) -> bool"""
+ return _html.HtmlWindow_HistoryBack(*args, **kwargs)
+
+ def HistoryForward(*args, **kwargs):
+ """HistoryForward(self) -> bool"""
+ return _html.HtmlWindow_HistoryForward(*args, **kwargs)
+
+ def HistoryCanBack(*args, **kwargs):
+ """HistoryCanBack(self) -> bool"""
+ return _html.HtmlWindow_HistoryCanBack(*args, **kwargs)
+
+ def HistoryCanForward(*args, **kwargs):
+ """HistoryCanForward(self) -> bool"""
+ return _html.HtmlWindow_HistoryCanForward(*args, **kwargs)
+
+ def HistoryClear(*args, **kwargs):
+ """HistoryClear(self)"""
+ return _html.HtmlWindow_HistoryClear(*args, **kwargs)
+
+ def GetInternalRepresentation(*args, **kwargs):
+ """GetInternalRepresentation(self) -> HtmlContainerCell"""
+ return _html.HtmlWindow_GetInternalRepresentation(*args, **kwargs)
+
+ def GetParser(*args, **kwargs):
+ """GetParser(self) -> HtmlWinParser"""
+ return _html.HtmlWindow_GetParser(*args, **kwargs)
+
+ def ScrollToAnchor(*args, **kwargs):
+ """ScrollToAnchor(self, String anchor) -> bool"""
+ return _html.HtmlWindow_ScrollToAnchor(*args, **kwargs)
+
+ def HasAnchor(*args, **kwargs):
+ """HasAnchor(self, String anchor) -> bool"""
+ return _html.HtmlWindow_HasAnchor(*args, **kwargs)
+
+ def AddFilter(*args, **kwargs):
+ """AddFilter(HtmlFilter filter)"""
+ return _html.HtmlWindow_AddFilter(*args, **kwargs)
+
+ AddFilter = staticmethod(AddFilter)
+ def SelectWord(*args, **kwargs):
+ """SelectWord(self, Point pos)"""
+ return _html.HtmlWindow_SelectWord(*args, **kwargs)
+
+ def SelectLine(*args, **kwargs):
+ """SelectLine(self, Point pos)"""
+ return _html.HtmlWindow_SelectLine(*args, **kwargs)
+
+ def SelectAll(*args, **kwargs):
+ """SelectAll(self)"""
+ return _html.HtmlWindow_SelectAll(*args, **kwargs)
+
+ def SelectionToText(*args, **kwargs):
+ """SelectionToText(self) -> String"""
+ return _html.HtmlWindow_SelectionToText(*args, **kwargs)
+
+ def ToText(*args, **kwargs):
+ """ToText(self) -> String"""
+ return _html.HtmlWindow_ToText(*args, **kwargs)
+
+ def OnLinkClicked(*args, **kwargs):
+ """OnLinkClicked(self, HtmlLinkInfo link)"""
+ return _html.HtmlWindow_OnLinkClicked(*args, **kwargs)
+
+ def OnSetTitle(*args, **kwargs):
+ """OnSetTitle(self, String title)"""
+ return _html.HtmlWindow_OnSetTitle(*args, **kwargs)
+
+ def OnCellMouseHover(*args, **kwargs):
+ """OnCellMouseHover(self, HtmlCell cell, int x, int y)"""
+ return _html.HtmlWindow_OnCellMouseHover(*args, **kwargs)
+
+ def OnCellClicked(*args, **kwargs):
+ """OnCellClicked(self, HtmlCell cell, int x, int y, MouseEvent event) -> bool"""
+ return _html.HtmlWindow_OnCellClicked(*args, **kwargs)
+
+ def OnOpeningURL(*args, **kwargs):
+ """OnOpeningURL(self, int type, String url, String redirect) -> int"""
+ return _html.HtmlWindow_OnOpeningURL(*args, **kwargs)
+
+ def base_OnLinkClicked(*args, **kw):
+ return HtmlWindow.OnLinkClicked(*args, **kw)
+ base_OnLinkClicked = wx.deprecated(base_OnLinkClicked,
+ "Please use HtmlWindow.OnLinkClicked instead.")
+
+ def base_OnSetTitle(*args, **kw):
+ return HtmlWindow.OnSetTitle(*args, **kw)
+ base_OnSetTitle = wx.deprecated(base_OnSetTitle,
+ "Please use HtmlWindow.OnSetTitle instead.")
+
+ def base_OnCellMouseHover(*args, **kw):
+ return HtmlWindow.OnCellMouseHover(*args, **kw)
+ base_OnCellMouseHover = wx.deprecated(base_OnCellMouseHover,
+ "Please use HtmlWindow.OnCellMouseHover instead.")
+
+ def base_OnCellClicked(*args, **kw):
+ return HtmlWindow.OnCellClicked(*args, **kw)
+ base_OnCellClicked = wx.deprecated(base_OnCellClicked,
+ "Please use HtmlWindow.OnCellClicked instead.")
+
+ def GetClassDefaultAttributes(*args, **kwargs):
+ """
+ GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _html.HtmlWindow_GetClassDefaultAttributes(*args, **kwargs)
+
+ GetClassDefaultAttributes = staticmethod(GetClassDefaultAttributes)
+ HTMLCursor_Default = _html.HtmlWindow_HTMLCursor_Default
+ HTMLCursor_Link = _html.HtmlWindow_HTMLCursor_Link
+ HTMLCursor_Text = _html.HtmlWindow_HTMLCursor_Text
+ def GetDefaultHTMLCursor(*args, **kwargs):
+ """GetDefaultHTMLCursor(int type) -> Cursor"""
+ return _html.HtmlWindow_GetDefaultHTMLCursor(*args, **kwargs)
+
+ GetDefaultHTMLCursor = staticmethod(GetDefaultHTMLCursor)
+ InternalRepresentation = property(GetInternalRepresentation,doc="See `GetInternalRepresentation`")
+ OpenedAnchor = property(GetOpenedAnchor,doc="See `GetOpenedAnchor`")
+ OpenedPage = property(GetOpenedPage,doc="See `GetOpenedPage`")
+ OpenedPageTitle = property(GetOpenedPageTitle,doc="See `GetOpenedPageTitle`")
+ Parser = property(GetParser,doc="See `GetParser`")
+ RelatedFrame = property(GetRelatedFrame,doc="See `GetRelatedFrame`")
+_html.HtmlWindow_swigregister(HtmlWindow)
+
+def PreHtmlWindow(*args, **kwargs):
+ """PreHtmlWindow() -> HtmlWindow"""
+ val = _html.new_PreHtmlWindow(*args, **kwargs)
+ return val
+
+def HtmlWindow_AddFilter(*args, **kwargs):
+ """HtmlWindow_AddFilter(HtmlFilter filter)"""
+ return _html.HtmlWindow_AddFilter(*args, **kwargs)
+
+def HtmlWindow_GetClassDefaultAttributes(*args, **kwargs):
+ """
+ HtmlWindow_GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes
+
+ Get the default attributes for this class. This is useful if you want
+ to use the same font or colour in your own control as in a standard
+ control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the
+ user's system, especially if it uses themes.
+
+ The variant parameter is only relevant under Mac currently and is
+ ignore under other platforms. Under Mac, it will change the size of
+ the returned font. See `wx.Window.SetWindowVariant` for more about
+ this.
+ """
+ return _html.HtmlWindow_GetClassDefaultAttributes(*args, **kwargs)
+
+def HtmlWindow_GetDefaultHTMLCursor(*args, **kwargs):
+ """HtmlWindow_GetDefaultHTMLCursor(int type) -> Cursor"""
+ return _html.HtmlWindow_GetDefaultHTMLCursor(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class HtmlDCRenderer(_core.Object):
+ """Proxy of C++ HtmlDCRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> HtmlDCRenderer"""
+ _html.HtmlDCRenderer_swiginit(self,_html.new_HtmlDCRenderer(*args, **kwargs))
+ __swig_destroy__ = _html.delete_HtmlDCRenderer
+ __del__ = lambda self : None;
+ def SetDC(*args):
+ """
+ SetDC(self, DC dc, double pixel_scale=1.0)
+ SetDC(self, DC dc, double pixel_scale, double font_scale)
+ """
+ return _html.HtmlDCRenderer_SetDC(*args)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, int width, int height)"""
+ return _html.HtmlDCRenderer_SetSize(*args, **kwargs)
+
+ def SetHtmlText(*args, **kwargs):
+ """SetHtmlText(self, String html, String basepath=EmptyString, bool isdir=True)"""
+ return _html.HtmlDCRenderer_SetHtmlText(*args, **kwargs)
+
+ def SetFonts(*args, **kwargs):
+ """SetFonts(self, String normal_face, String fixed_face, PyObject sizes=None)"""
+ return _html.HtmlDCRenderer_SetFonts(*args, **kwargs)
+
+ def SetStandardFonts(*args, **kwargs):
+ """SetStandardFonts(self, int size=-1, String normal_face=EmptyString, String fixed_face=EmptyString)"""
+ return _html.HtmlDCRenderer_SetStandardFonts(*args, **kwargs)
+
+ def Render(*args, **kwargs):
+ """
+ Render(self, int x, int y, wxArrayInt known_pagebreaks, int from=0,
+ int dont_render=False, int to=INT_MAX) -> int
+ """
+ return _html.HtmlDCRenderer_Render(*args, **kwargs)
+
+ def GetTotalHeight(*args, **kwargs):
+ """GetTotalHeight(self) -> int"""
+ return _html.HtmlDCRenderer_GetTotalHeight(*args, **kwargs)
+
+ TotalHeight = property(GetTotalHeight,doc="See `GetTotalHeight`")
+_html.HtmlDCRenderer_swigregister(HtmlDCRenderer)
+
+PAGE_ODD = _html.PAGE_ODD
+PAGE_EVEN = _html.PAGE_EVEN
+PAGE_ALL = _html.PAGE_ALL
+class HtmlPrintout(_windows.Printout):
+ """Proxy of C++ HtmlPrintout class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String title=HtmlPrintoutTitleStr) -> HtmlPrintout"""
+ _html.HtmlPrintout_swiginit(self,_html.new_HtmlPrintout(*args, **kwargs))
+ def SetHtmlText(*args, **kwargs):
+ """SetHtmlText(self, String html, String basepath=EmptyString, bool isdir=True)"""
+ return _html.HtmlPrintout_SetHtmlText(*args, **kwargs)
+
+ def SetHtmlFile(*args, **kwargs):
+ """SetHtmlFile(self, String htmlfile)"""
+ return _html.HtmlPrintout_SetHtmlFile(*args, **kwargs)
+
+ def SetHeader(*args, **kwargs):
+ """SetHeader(self, String header, int pg=PAGE_ALL)"""
+ return _html.HtmlPrintout_SetHeader(*args, **kwargs)
+
+ def SetFooter(*args, **kwargs):
+ """SetFooter(self, String footer, int pg=PAGE_ALL)"""
+ return _html.HtmlPrintout_SetFooter(*args, **kwargs)
+
+ def SetFonts(*args, **kwargs):
+ """SetFonts(self, String normal_face, String fixed_face, PyObject sizes=None)"""
+ return _html.HtmlPrintout_SetFonts(*args, **kwargs)
+
+ def SetStandardFonts(*args, **kwargs):
+ """SetStandardFonts(self, int size=-1, String normal_face=EmptyString, String fixed_face=EmptyString)"""
+ return _html.HtmlPrintout_SetStandardFonts(*args, **kwargs)
+
+ def SetMargins(*args, **kwargs):
+ """
+ SetMargins(self, float top=25.2, float bottom=25.2, float left=25.2,
+ float right=25.2, float spaces=5)
+ """
+ return _html.HtmlPrintout_SetMargins(*args, **kwargs)
+
+ def AddFilter(*args, **kwargs):
+ """AddFilter(wxHtmlFilter filter)"""
+ return _html.HtmlPrintout_AddFilter(*args, **kwargs)
+
+ AddFilter = staticmethod(AddFilter)
+ def CleanUpStatics(*args, **kwargs):
+ """CleanUpStatics()"""
+ return _html.HtmlPrintout_CleanUpStatics(*args, **kwargs)
+
+ CleanUpStatics = staticmethod(CleanUpStatics)
+_html.HtmlPrintout_swigregister(HtmlPrintout)
+
+def HtmlPrintout_AddFilter(*args, **kwargs):
+ """HtmlPrintout_AddFilter(wxHtmlFilter filter)"""
+ return _html.HtmlPrintout_AddFilter(*args, **kwargs)
+
+def HtmlPrintout_CleanUpStatics(*args):
+ """HtmlPrintout_CleanUpStatics()"""
+ return _html.HtmlPrintout_CleanUpStatics(*args)
+
+class HtmlEasyPrinting(_core.Object):
+ """Proxy of C++ HtmlEasyPrinting class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String name=HtmlPrintingTitleStr, Window parentWindow=None) -> HtmlEasyPrinting"""
+ _html.HtmlEasyPrinting_swiginit(self,_html.new_HtmlEasyPrinting(*args, **kwargs))
+ __swig_destroy__ = _html.delete_HtmlEasyPrinting
+ __del__ = lambda self : None;
+ def PreviewFile(*args, **kwargs):
+ """PreviewFile(self, String htmlfile) -> bool"""
+ return _html.HtmlEasyPrinting_PreviewFile(*args, **kwargs)
+
+ def PreviewText(*args, **kwargs):
+ """PreviewText(self, String htmltext, String basepath=EmptyString) -> bool"""
+ return _html.HtmlEasyPrinting_PreviewText(*args, **kwargs)
+
+ def PrintFile(*args, **kwargs):
+ """PrintFile(self, String htmlfile) -> bool"""
+ return _html.HtmlEasyPrinting_PrintFile(*args, **kwargs)
+
+ def PrintText(*args, **kwargs):
+ """PrintText(self, String htmltext, String basepath=EmptyString) -> bool"""
+ return _html.HtmlEasyPrinting_PrintText(*args, **kwargs)
+
+ def PageSetup(*args, **kwargs):
+ """PageSetup(self)"""
+ return _html.HtmlEasyPrinting_PageSetup(*args, **kwargs)
+
+ def SetHeader(*args, **kwargs):
+ """SetHeader(self, String header, int pg=PAGE_ALL)"""
+ return _html.HtmlEasyPrinting_SetHeader(*args, **kwargs)
+
+ def SetFooter(*args, **kwargs):
+ """SetFooter(self, String footer, int pg=PAGE_ALL)"""
+ return _html.HtmlEasyPrinting_SetFooter(*args, **kwargs)
+
+ def SetFonts(*args, **kwargs):
+ """SetFonts(self, String normal_face, String fixed_face, PyObject sizes=None)"""
+ return _html.HtmlEasyPrinting_SetFonts(*args, **kwargs)
+
+ def SetStandardFonts(*args, **kwargs):
+ """SetStandardFonts(self, int size=-1, String normal_face=EmptyString, String fixed_face=EmptyString)"""
+ return _html.HtmlEasyPrinting_SetStandardFonts(*args, **kwargs)
+
+ def GetPrintData(*args, **kwargs):
+ """GetPrintData(self) -> PrintData"""
+ return _html.HtmlEasyPrinting_GetPrintData(*args, **kwargs)
+
+ def GetPageSetupData(*args, **kwargs):
+ """GetPageSetupData(self) -> PageSetupDialogData"""
+ return _html.HtmlEasyPrinting_GetPageSetupData(*args, **kwargs)
+
+ def GetParentWindow(*args, **kwargs):
+ """GetParentWindow(self) -> Window"""
+ return _html.HtmlEasyPrinting_GetParentWindow(*args, **kwargs)
+
+ def SetParentWindow(*args, **kwargs):
+ """SetParentWindow(self, Window window)"""
+ return _html.HtmlEasyPrinting_SetParentWindow(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _html.HtmlEasyPrinting_GetName(*args, **kwargs)
+
+ def SetName(*args, **kwargs):
+ """SetName(self, String name)"""
+ return _html.HtmlEasyPrinting_SetName(*args, **kwargs)
+
+ PageSetupData = property(GetPageSetupData,doc="See `GetPageSetupData`")
+ PrintData = property(GetPrintData,doc="See `GetPrintData`")
+ ParentWindow = property(GetParentWindow,SetParentWindow)
+ Name = property(GetName,SetName)
+_html.HtmlEasyPrinting_swigregister(HtmlEasyPrinting)
+
+#---------------------------------------------------------------------------
+
+class HtmlBookRecord(object):
+ """Proxy of C++ HtmlBookRecord class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String bookfile, String basepath, String title, String start) -> HtmlBookRecord"""
+ _html.HtmlBookRecord_swiginit(self,_html.new_HtmlBookRecord(*args, **kwargs))
+ def GetBookFile(*args, **kwargs):
+ """GetBookFile(self) -> String"""
+ return _html.HtmlBookRecord_GetBookFile(*args, **kwargs)
+
+ def GetTitle(*args, **kwargs):
+ """GetTitle(self) -> String"""
+ return _html.HtmlBookRecord_GetTitle(*args, **kwargs)
+
+ def GetStart(*args, **kwargs):
+ """GetStart(self) -> String"""
+ return _html.HtmlBookRecord_GetStart(*args, **kwargs)
+
+ def GetBasePath(*args, **kwargs):
+ """GetBasePath(self) -> String"""
+ return _html.HtmlBookRecord_GetBasePath(*args, **kwargs)
+
+ def SetContentsRange(*args, **kwargs):
+ """SetContentsRange(self, int start, int end)"""
+ return _html.HtmlBookRecord_SetContentsRange(*args, **kwargs)
+
+ def GetContentsStart(*args, **kwargs):
+ """GetContentsStart(self) -> int"""
+ return _html.HtmlBookRecord_GetContentsStart(*args, **kwargs)
+
+ def GetContentsEnd(*args, **kwargs):
+ """GetContentsEnd(self) -> int"""
+ return _html.HtmlBookRecord_GetContentsEnd(*args, **kwargs)
+
+ def SetTitle(*args, **kwargs):
+ """SetTitle(self, String title)"""
+ return _html.HtmlBookRecord_SetTitle(*args, **kwargs)
+
+ def SetBasePath(*args, **kwargs):
+ """SetBasePath(self, String path)"""
+ return _html.HtmlBookRecord_SetBasePath(*args, **kwargs)
+
+ def SetStart(*args, **kwargs):
+ """SetStart(self, String start)"""
+ return _html.HtmlBookRecord_SetStart(*args, **kwargs)
+
+ def GetFullPath(*args, **kwargs):
+ """GetFullPath(self, String page) -> String"""
+ return _html.HtmlBookRecord_GetFullPath(*args, **kwargs)
+
+ BasePath = property(GetBasePath,SetBasePath,doc="See `GetBasePath` and `SetBasePath`")
+ BookFile = property(GetBookFile,doc="See `GetBookFile`")
+ ContentsEnd = property(GetContentsEnd,doc="See `GetContentsEnd`")
+ ContentsStart = property(GetContentsStart,doc="See `GetContentsStart`")
+ FullPath = property(GetFullPath,doc="See `GetFullPath`")
+ Start = property(GetStart,SetStart,doc="See `GetStart` and `SetStart`")
+ Title = property(GetTitle,SetTitle,doc="See `GetTitle` and `SetTitle`")
+_html.HtmlBookRecord_swigregister(HtmlBookRecord)
+
+class HtmlSearchStatus(object):
+ """Proxy of C++ HtmlSearchStatus class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Search(*args, **kwargs):
+ """Search(self) -> bool"""
+ return _html.HtmlSearchStatus_Search(*args, **kwargs)
+
+ def IsActive(*args, **kwargs):
+ """IsActive(self) -> bool"""
+ return _html.HtmlSearchStatus_IsActive(*args, **kwargs)
+
+ def GetCurIndex(*args, **kwargs):
+ """GetCurIndex(self) -> int"""
+ return _html.HtmlSearchStatus_GetCurIndex(*args, **kwargs)
+
+ def GetMaxIndex(*args, **kwargs):
+ """GetMaxIndex(self) -> int"""
+ return _html.HtmlSearchStatus_GetMaxIndex(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _html.HtmlSearchStatus_GetName(*args, **kwargs)
+
+ CurIndex = property(GetCurIndex,doc="See `GetCurIndex`")
+ MaxIndex = property(GetMaxIndex,doc="See `GetMaxIndex`")
+ Name = property(GetName,doc="See `GetName`")
+_html.HtmlSearchStatus_swigregister(HtmlSearchStatus)
+
+class HtmlHelpData(object):
+ """Proxy of C++ HtmlHelpData class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> HtmlHelpData"""
+ _html.HtmlHelpData_swiginit(self,_html.new_HtmlHelpData(*args, **kwargs))
+ __swig_destroy__ = _html.delete_HtmlHelpData
+ __del__ = lambda self : None;
+ def SetTempDir(*args, **kwargs):
+ """SetTempDir(self, String path)"""
+ return _html.HtmlHelpData_SetTempDir(*args, **kwargs)
+
+ def AddBook(*args, **kwargs):
+ """AddBook(self, String book) -> bool"""
+ return _html.HtmlHelpData_AddBook(*args, **kwargs)
+
+ def FindPageByName(*args, **kwargs):
+ """FindPageByName(self, String page) -> String"""
+ return _html.HtmlHelpData_FindPageByName(*args, **kwargs)
+
+ def FindPageById(*args, **kwargs):
+ """FindPageById(self, int id) -> String"""
+ return _html.HtmlHelpData_FindPageById(*args, **kwargs)
+
+ def GetBookRecArray(*args, **kwargs):
+ """GetBookRecArray(self) -> wxHtmlBookRecArray"""
+ return _html.HtmlHelpData_GetBookRecArray(*args, **kwargs)
+
+ BookRecArray = property(GetBookRecArray,doc="See `GetBookRecArray`")
+_html.HtmlHelpData_swigregister(HtmlHelpData)
+
+HF_TOOLBAR = _html.HF_TOOLBAR
+HF_CONTENTS = _html.HF_CONTENTS
+HF_INDEX = _html.HF_INDEX
+HF_SEARCH = _html.HF_SEARCH
+HF_BOOKMARKS = _html.HF_BOOKMARKS
+HF_OPEN_FILES = _html.HF_OPEN_FILES
+HF_PRINT = _html.HF_PRINT
+HF_FLAT_TOOLBAR = _html.HF_FLAT_TOOLBAR
+HF_MERGE_BOOKS = _html.HF_MERGE_BOOKS
+HF_ICONS_BOOK = _html.HF_ICONS_BOOK
+HF_ICONS_BOOK_CHAPTER = _html.HF_ICONS_BOOK_CHAPTER
+HF_ICONS_FOLDER = _html.HF_ICONS_FOLDER
+HF_DEFAULT_STYLE = _html.HF_DEFAULT_STYLE
+HF_EMBEDDED = _html.HF_EMBEDDED
+HF_DIALOG = _html.HF_DIALOG
+HF_FRAME = _html.HF_FRAME
+HF_MODAL = _html.HF_MODAL
+ID_HTML_PANEL = _html.ID_HTML_PANEL
+ID_HTML_BACK = _html.ID_HTML_BACK
+ID_HTML_FORWARD = _html.ID_HTML_FORWARD
+ID_HTML_UPNODE = _html.ID_HTML_UPNODE
+ID_HTML_UP = _html.ID_HTML_UP
+ID_HTML_DOWN = _html.ID_HTML_DOWN
+ID_HTML_PRINT = _html.ID_HTML_PRINT
+ID_HTML_OPENFILE = _html.ID_HTML_OPENFILE
+ID_HTML_OPTIONS = _html.ID_HTML_OPTIONS
+ID_HTML_BOOKMARKSLIST = _html.ID_HTML_BOOKMARKSLIST
+ID_HTML_BOOKMARKSADD = _html.ID_HTML_BOOKMARKSADD
+ID_HTML_BOOKMARKSREMOVE = _html.ID_HTML_BOOKMARKSREMOVE
+ID_HTML_TREECTRL = _html.ID_HTML_TREECTRL
+ID_HTML_INDEXPAGE = _html.ID_HTML_INDEXPAGE
+ID_HTML_INDEXLIST = _html.ID_HTML_INDEXLIST
+ID_HTML_INDEXTEXT = _html.ID_HTML_INDEXTEXT
+ID_HTML_INDEXBUTTON = _html.ID_HTML_INDEXBUTTON
+ID_HTML_INDEXBUTTONALL = _html.ID_HTML_INDEXBUTTONALL
+ID_HTML_NOTEBOOK = _html.ID_HTML_NOTEBOOK
+ID_HTML_SEARCHPAGE = _html.ID_HTML_SEARCHPAGE
+ID_HTML_SEARCHTEXT = _html.ID_HTML_SEARCHTEXT
+ID_HTML_SEARCHLIST = _html.ID_HTML_SEARCHLIST
+ID_HTML_SEARCHBUTTON = _html.ID_HTML_SEARCHBUTTON
+ID_HTML_SEARCHCHOICE = _html.ID_HTML_SEARCHCHOICE
+ID_HTML_COUNTINFO = _html.ID_HTML_COUNTINFO
+class HtmlHelpWindow(_core.Window):
+ """Proxy of C++ HtmlHelpWindow class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int ?, Point pos=DefaultPosition, Size size=DefaultSize,
+ int style=wxTAB_TRAVERSAL|wxNO_BORDER,
+ int helpStyle=HF_DEFAULT_STYLE,
+ HtmlHelpData data=None) -> HtmlHelpWindow
+ """
+ _html.HtmlHelpWindow_swiginit(self,_html.new_HtmlHelpWindow(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize,
+ int style=wxTAB_TRAVERSAL|wxNO_BORDER,
+ int helpStyle=HF_DEFAULT_STYLE) -> bool
+ """
+ return _html.HtmlHelpWindow_Create(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """GetData(self) -> HtmlHelpData"""
+ return _html.HtmlHelpWindow_GetData(*args, **kwargs)
+
+ def GetController(*args, **kwargs):
+ """GetController(self) -> HtmlHelpController"""
+ return _html.HtmlHelpWindow_GetController(*args, **kwargs)
+
+ def SetController(*args, **kwargs):
+ """SetController(self, HtmlHelpController controller)"""
+ return _html.HtmlHelpWindow_SetController(*args, **kwargs)
+
+ def Display(*args, **kwargs):
+ """Display(self, String x) -> bool"""
+ return _html.HtmlHelpWindow_Display(*args, **kwargs)
+
+ def DisplayID(*args, **kwargs):
+ """DisplayID(self, int id) -> bool"""
+ return _html.HtmlHelpWindow_DisplayID(*args, **kwargs)
+
+ def DisplayContents(*args, **kwargs):
+ """DisplayContents(self) -> bool"""
+ return _html.HtmlHelpWindow_DisplayContents(*args, **kwargs)
+
+ def DisplayIndex(*args, **kwargs):
+ """DisplayIndex(self) -> bool"""
+ return _html.HtmlHelpWindow_DisplayIndex(*args, **kwargs)
+
+ def KeywordSearch(*args, **kwargs):
+ """KeywordSearch(self, String keyword, wxHelpSearchMode mode=wxHELP_SEARCH_ALL) -> bool"""
+ return _html.HtmlHelpWindow_KeywordSearch(*args, **kwargs)
+
+ def UseConfig(*args, **kwargs):
+ """UseConfig(self, ConfigBase config, String rootpath=wxEmptyString)"""
+ return _html.HtmlHelpWindow_UseConfig(*args, **kwargs)
+
+ def ReadCustomization(*args, **kwargs):
+ """ReadCustomization(self, ConfigBase cfg, String path=wxEmptyString)"""
+ return _html.HtmlHelpWindow_ReadCustomization(*args, **kwargs)
+
+ def WriteCustomization(*args, **kwargs):
+ """WriteCustomization(self, ConfigBase cfg, String path=wxEmptyString)"""
+ return _html.HtmlHelpWindow_WriteCustomization(*args, **kwargs)
+
+ def NotifyPageChanged(*args, **kwargs):
+ """NotifyPageChanged(self)"""
+ return _html.HtmlHelpWindow_NotifyPageChanged(*args, **kwargs)
+
+ def RefreshLists(*args, **kwargs):
+ """RefreshLists(self)"""
+ return _html.HtmlHelpWindow_RefreshLists(*args, **kwargs)
+
+ def GetHtmlWindow(*args, **kwargs):
+ """GetHtmlWindow(self) -> HtmlWindow"""
+ return _html.HtmlHelpWindow_GetHtmlWindow(*args, **kwargs)
+
+ def GetSplitterWindow(*args, **kwargs):
+ """GetSplitterWindow(self) -> SplitterWindow"""
+ return _html.HtmlHelpWindow_GetSplitterWindow(*args, **kwargs)
+
+ def GetToolBar(*args, **kwargs):
+ """GetToolBar(self) -> wxToolBar"""
+ return _html.HtmlHelpWindow_GetToolBar(*args, **kwargs)
+
+ def GetCfgData(*args, **kwargs):
+ """GetCfgData(self) -> wxHtmlHelpFrameCfg"""
+ return _html.HtmlHelpWindow_GetCfgData(*args, **kwargs)
+
+ def GetTreeCtrl(*args, **kwargs):
+ """GetTreeCtrl(self) -> wxPyTreeCtrl"""
+ return _html.HtmlHelpWindow_GetTreeCtrl(*args, **kwargs)
+
+ CfgData = property(GetCfgData,doc="See `GetCfgData`")
+ Controller = property(GetController,SetController,doc="See `GetController` and `SetController`")
+ Data = property(GetData,doc="See `GetData`")
+ HtmlWindow = property(GetHtmlWindow,doc="See `GetHtmlWindow`")
+ SplitterWindow = property(GetSplitterWindow,doc="See `GetSplitterWindow`")
+ ToolBar = property(GetToolBar,doc="See `GetToolBar`")
+ TreeCtrl = property(GetTreeCtrl,doc="See `GetTreeCtrl`")
+_html.HtmlHelpWindow_swigregister(HtmlHelpWindow)
+
+def PreHtmlHelpWindow(*args, **kwargs):
+ """PreHtmlHelpWindow(HtmlHelpData data=None) -> HtmlHelpWindow"""
+ val = _html.new_PreHtmlHelpWindow(*args, **kwargs)
+ self._setOORInfo(self)
+ return val
+
+wxEVT_COMMAND_HTML_CELL_CLICKED = _html.wxEVT_COMMAND_HTML_CELL_CLICKED
+wxEVT_COMMAND_HTML_CELL_HOVER = _html.wxEVT_COMMAND_HTML_CELL_HOVER
+wxEVT_COMMAND_HTML_LINK_CLICKED = _html.wxEVT_COMMAND_HTML_LINK_CLICKED
+class HtmlCellEvent(_core.CommandEvent):
+ """Proxy of C++ HtmlCellEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType commandType, int id, HtmlCell cell, Point pt,
+ MouseEvent ev) -> HtmlCellEvent
+ """
+ _html.HtmlCellEvent_swiginit(self,_html.new_HtmlCellEvent(*args, **kwargs))
+ def GetCell(*args, **kwargs):
+ """GetCell(self) -> HtmlCell"""
+ return _html.HtmlCellEvent_GetCell(*args, **kwargs)
+
+ def GetPoint(*args, **kwargs):
+ """GetPoint(self) -> Point"""
+ return _html.HtmlCellEvent_GetPoint(*args, **kwargs)
+
+ def GetMouseEvent(*args, **kwargs):
+ """GetMouseEvent(self) -> MouseEvent"""
+ return _html.HtmlCellEvent_GetMouseEvent(*args, **kwargs)
+
+ def SetLinkClicked(*args, **kwargs):
+ """SetLinkClicked(self, bool linkclicked)"""
+ return _html.HtmlCellEvent_SetLinkClicked(*args, **kwargs)
+
+ def GetLinkClicked(*args, **kwargs):
+ """GetLinkClicked(self) -> bool"""
+ return _html.HtmlCellEvent_GetLinkClicked(*args, **kwargs)
+
+_html.HtmlCellEvent_swigregister(HtmlCellEvent)
+
+class HtmlLinkEvent(_core.CommandEvent):
+ """Proxy of C++ HtmlLinkEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int id, HtmlLinkInfo linkinfo) -> HtmlLinkEvent"""
+ _html.HtmlLinkEvent_swiginit(self,_html.new_HtmlLinkEvent(*args, **kwargs))
+ def GetLinkInfo(*args, **kwargs):
+ """GetLinkInfo(self) -> HtmlLinkInfo"""
+ return _html.HtmlLinkEvent_GetLinkInfo(*args, **kwargs)
+
+_html.HtmlLinkEvent_swigregister(HtmlLinkEvent)
+
+EVT_HTML_CELL_CLICKED = wx.PyEventBinder( wxEVT_COMMAND_HTML_CELL_CLICKED, 1 )
+EVT_HTML_CELL_HOVER = wx.PyEventBinder( wxEVT_COMMAND_HTML_CELL_HOVER, 1 )
+EVT_HTML_LINK_CLICKED = wx.PyEventBinder( wxEVT_COMMAND_HTML_LINK_CLICKED, 1 )
+
+class HtmlHelpFrame(_windows.Frame):
+ """Proxy of C++ HtmlHelpFrame class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int ?, String title=EmptyString, int style=wxHF_DEFAULTSTYLE,
+ HtmlHelpData data=None,
+ ConfigBase config=None, String rootpath=EmptyString) -> HtmlHelpFrame
+ """
+ _html.HtmlHelpFrame_swiginit(self,_html.new_HtmlHelpFrame(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id, String title=EmptyString, int style=HF_DEFAULT_STYLE,
+ ConfigBase config=None,
+ String rootpath=EmptyString) -> bool
+ """
+ return _html.HtmlHelpFrame_Create(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """GetData(self) -> HtmlHelpData"""
+ return _html.HtmlHelpFrame_GetData(*args, **kwargs)
+
+ def SetTitleFormat(*args, **kwargs):
+ """SetTitleFormat(self, String format)"""
+ return _html.HtmlHelpFrame_SetTitleFormat(*args, **kwargs)
+
+ def AddGrabIfNeeded(*args, **kwargs):
+ """AddGrabIfNeeded(self)"""
+ return _html.HtmlHelpFrame_AddGrabIfNeeded(*args, **kwargs)
+
+ def SetShouldPreventAppExit(*args, **kwargs):
+ """SetShouldPreventAppExit(self, bool enable)"""
+ return _html.HtmlHelpFrame_SetShouldPreventAppExit(*args, **kwargs)
+
+ def GetController(*args, **kwargs):
+ """GetController(self) -> HtmlHelpController"""
+ return _html.HtmlHelpFrame_GetController(*args, **kwargs)
+
+ def SetController(*args, **kwargs):
+ """SetController(self, HtmlHelpController controller)"""
+ return _html.HtmlHelpFrame_SetController(*args, **kwargs)
+
+ def GetHelpWindow(*args, **kwargs):
+ """GetHelpWindow(self) -> HtmlHelpWindow"""
+ return _html.HtmlHelpFrame_GetHelpWindow(*args, **kwargs)
+
+ # For compatibility from before the refactor
+ def Display(self, x):
+ return self.GetHelpWindow().Display(x)
+ def DisplayID(self, x):
+ return self.GetHelpWindow().DisplayID(id)
+ def DisplayContents(self):
+ return self.GetHelpWindow().DisplayContents()
+ def DisplayIndex(self):
+ return self.GetHelpWindow().DisplayIndex()
+
+ def KeywordSearch(self, keyword):
+ return self.GetHelpWindow().KeywordSearch(keyword)
+
+ def UseConfig(self, config, rootpath=""):
+ return self.GetHelpWindow().UseConfig(config, rootpath)
+ def ReadCustomization(self, config, rootpath=""):
+ return self.GetHelpWindow().ReadCustomization(config, rootpath)
+ def WriteCustomization(self, config, rootpath=""):
+ return self.GetHelpWindow().WriteCustomization(config, rootpath)
+
+ Controller = property(GetController,SetController,doc="See `GetController` and `SetController`")
+ Data = property(GetData,doc="See `GetData`")
+ HelpWindow = property(GetHelpWindow,doc="See `GetHelpWindow`")
+_html.HtmlHelpFrame_swigregister(HtmlHelpFrame)
+
+def PreHtmlHelpFrame(*args, **kwargs):
+ """PreHtmlHelpFrame(HtmlHelpData data=None) -> HtmlHelpFrame"""
+ val = _html.new_PreHtmlHelpFrame(*args, **kwargs)
+ self._setOORInfo(self)
+ return val
+
+class HtmlHelpDialog(_windows.Dialog):
+ """Proxy of C++ HtmlHelpDialog class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int ?, String title=EmptyString, int style=HF_DEFAULT_STYLE,
+ HtmlHelpData data=None) -> HtmlHelpDialog
+ """
+ _html.HtmlHelpDialog_swiginit(self,_html.new_HtmlHelpDialog(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """Create(self, Window parent, int id, String title=EmptyString, int style=HF_DEFAULT_STYLE) -> bool"""
+ return _html.HtmlHelpDialog_Create(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """GetData(self) -> HtmlHelpData"""
+ return _html.HtmlHelpDialog_GetData(*args, **kwargs)
+
+ def GetController(*args, **kwargs):
+ """GetController(self) -> HtmlHelpController"""
+ return _html.HtmlHelpDialog_GetController(*args, **kwargs)
+
+ def SetController(*args, **kwargs):
+ """SetController(self, HtmlHelpController controller)"""
+ return _html.HtmlHelpDialog_SetController(*args, **kwargs)
+
+ def GetHelpWindow(*args, **kwargs):
+ """GetHelpWindow(self) -> HtmlHelpWindow"""
+ return _html.HtmlHelpDialog_GetHelpWindow(*args, **kwargs)
+
+ def SetTitleFormat(*args, **kwargs):
+ """SetTitleFormat(self, String format)"""
+ return _html.HtmlHelpDialog_SetTitleFormat(*args, **kwargs)
+
+ Controller = property(GetController,SetController,doc="See `GetController` and `SetController`")
+ Data = property(GetData,doc="See `GetData`")
+ HelpWindow = property(GetHelpWindow,doc="See `GetHelpWindow`")
+_html.HtmlHelpDialog_swigregister(HtmlHelpDialog)
+
+def PreHtmlHelpDialog(*args, **kwargs):
+ """PreHtmlHelpDialog(HtmlHelpData data=None) -> HtmlHelpDialog"""
+ val = _html.new_PreHtmlHelpDialog(*args, **kwargs)
+ self._setOORInfo(self)
+ return val
+
+class HelpControllerBase(_core.Object):
+ """Proxy of C++ HelpControllerBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Initialize(*args):
+ """
+ Initialize(self, String file, int server) -> bool
+ Initialize(self, String file) -> bool
+ """
+ return _html.HelpControllerBase_Initialize(*args)
+
+ def SetViewer(*args, **kwargs):
+ """SetViewer(self, String viewer, long flags=0)"""
+ return _html.HelpControllerBase_SetViewer(*args, **kwargs)
+
+ def LoadFile(*args, **kwargs):
+ """LoadFile(self, String file=wxEmptyString) -> bool"""
+ return _html.HelpControllerBase_LoadFile(*args, **kwargs)
+
+ def DisplayContents(*args, **kwargs):
+ """DisplayContents(self) -> bool"""
+ return _html.HelpControllerBase_DisplayContents(*args, **kwargs)
+
+ def DisplayContextPopup(*args, **kwargs):
+ """DisplayContextPopup(self, int contextId) -> bool"""
+ return _html.HelpControllerBase_DisplayContextPopup(*args, **kwargs)
+
+ def DisplayTextPopup(*args, **kwargs):
+ """DisplayTextPopup(self, String text, Point pos) -> bool"""
+ return _html.HelpControllerBase_DisplayTextPopup(*args, **kwargs)
+
+ def DisplaySection(*args):
+ """
+ DisplaySection(self, int sectionNo) -> bool
+ DisplaySection(self, String section) -> bool
+ """
+ return _html.HelpControllerBase_DisplaySection(*args)
+
+ def DisplayBlock(*args, **kwargs):
+ """DisplayBlock(self, long blockNo) -> bool"""
+ return _html.HelpControllerBase_DisplayBlock(*args, **kwargs)
+
+ def KeywordSearch(*args, **kwargs):
+ """KeywordSearch(self, String k, wxHelpSearchMode mode=wxHELP_SEARCH_ALL) -> bool"""
+ return _html.HelpControllerBase_KeywordSearch(*args, **kwargs)
+
+ def SetFrameParameters(*args, **kwargs):
+ """
+ SetFrameParameters(self, String title, Size size, Point pos=DefaultPosition,
+ bool newFrameEachTime=False)
+ """
+ return _html.HelpControllerBase_SetFrameParameters(*args, **kwargs)
+
+ def Quit(*args, **kwargs):
+ """Quit(self) -> bool"""
+ return _html.HelpControllerBase_Quit(*args, **kwargs)
+
+ def OnQuit(*args, **kwargs):
+ """OnQuit(self)"""
+ return _html.HelpControllerBase_OnQuit(*args, **kwargs)
+
+ def SetParentWindow(*args, **kwargs):
+ """SetParentWindow(self, Window win)"""
+ return _html.HelpControllerBase_SetParentWindow(*args, **kwargs)
+
+ def GetParentWindow(*args, **kwargs):
+ """GetParentWindow(self) -> Window"""
+ return _html.HelpControllerBase_GetParentWindow(*args, **kwargs)
+
+ ParentWindow = property(GetParentWindow,SetParentWindow,doc="See `GetParentWindow` and `SetParentWindow`")
+_html.HelpControllerBase_swigregister(HelpControllerBase)
+
+class HtmlHelpController(HelpControllerBase):
+ """Proxy of C++ HtmlHelpController class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int style=HF_DEFAULT_STYLE, Window parentWindow=None) -> HtmlHelpController"""
+ _html.HtmlHelpController_swiginit(self,_html.new_HtmlHelpController(*args, **kwargs))
+ __swig_destroy__ = _html.delete_HtmlHelpController
+ __del__ = lambda self : None;
+ def SetShouldPreventAppExit(*args, **kwargs):
+ """SetShouldPreventAppExit(self, bool enable)"""
+ return _html.HtmlHelpController_SetShouldPreventAppExit(*args, **kwargs)
+
+ def GetHelpWindow(*args, **kwargs):
+ """GetHelpWindow(self) -> HtmlHelpWindow"""
+ return _html.HtmlHelpController_GetHelpWindow(*args, **kwargs)
+
+ def SetHelpWindow(*args, **kwargs):
+ """SetHelpWindow(self, HtmlHelpWindow helpWindow)"""
+ return _html.HtmlHelpController_SetHelpWindow(*args, **kwargs)
+
+ def GetFrame(*args, **kwargs):
+ """GetFrame(self) -> HtmlHelpFrame"""
+ return _html.HtmlHelpController_GetFrame(*args, **kwargs)
+
+ def GetDialog(*args, **kwargs):
+ """GetDialog(self) -> HtmlHelpDialog"""
+ return _html.HtmlHelpController_GetDialog(*args, **kwargs)
+
+ def SetTitleFormat(*args, **kwargs):
+ """SetTitleFormat(self, String format)"""
+ return _html.HtmlHelpController_SetTitleFormat(*args, **kwargs)
+
+ def SetTempDir(*args, **kwargs):
+ """SetTempDir(self, String path)"""
+ return _html.HtmlHelpController_SetTempDir(*args, **kwargs)
+
+ def AddBook(*args, **kwargs):
+ """AddBook(self, String book, int show_wait_msg=False) -> bool"""
+ return _html.HtmlHelpController_AddBook(*args, **kwargs)
+
+ def Display(*args, **kwargs):
+ """Display(self, String x)"""
+ return _html.HtmlHelpController_Display(*args, **kwargs)
+
+ def DisplayID(*args, **kwargs):
+ """DisplayID(self, int id)"""
+ return _html.HtmlHelpController_DisplayID(*args, **kwargs)
+
+ def DisplayContents(*args, **kwargs):
+ """DisplayContents(self)"""
+ return _html.HtmlHelpController_DisplayContents(*args, **kwargs)
+
+ def DisplayIndex(*args, **kwargs):
+ """DisplayIndex(self)"""
+ return _html.HtmlHelpController_DisplayIndex(*args, **kwargs)
+
+ def KeywordSearch(*args, **kwargs):
+ """KeywordSearch(self, String keyword) -> bool"""
+ return _html.HtmlHelpController_KeywordSearch(*args, **kwargs)
+
+ def UseConfig(*args, **kwargs):
+ """UseConfig(self, ConfigBase config, String rootpath=EmptyString)"""
+ return _html.HtmlHelpController_UseConfig(*args, **kwargs)
+
+ def ReadCustomization(*args, **kwargs):
+ """ReadCustomization(self, ConfigBase cfg, String path=EmptyString)"""
+ return _html.HtmlHelpController_ReadCustomization(*args, **kwargs)
+
+ def WriteCustomization(*args, **kwargs):
+ """WriteCustomization(self, ConfigBase cfg, String path=EmptyString)"""
+ return _html.HtmlHelpController_WriteCustomization(*args, **kwargs)
+
+ def MakeModalIfNeeded(*args, **kwargs):
+ """MakeModalIfNeeded(self)"""
+ return _html.HtmlHelpController_MakeModalIfNeeded(*args, **kwargs)
+
+ def FindTopLevelWindow(*args, **kwargs):
+ """FindTopLevelWindow(self) -> Window"""
+ return _html.HtmlHelpController_FindTopLevelWindow(*args, **kwargs)
+
+ Dialog = property(GetDialog,doc="See `GetDialog`")
+ Frame = property(GetFrame,doc="See `GetFrame`")
+ HelpWindow = property(GetHelpWindow,SetHelpWindow,doc="See `GetHelpWindow` and `SetHelpWindow`")
+_html.HtmlHelpController_swigregister(HtmlHelpController)
+
+class HtmlModalHelp(object):
+ """Proxy of C++ HtmlModalHelp class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, String helpFile, String topic=wxEmptyString,
+ int style=wxHF_DEFAULT_STYLE|wxHF_DIALOG|wxHF_MODAL) -> HtmlModalHelp
+ """
+ _html.HtmlModalHelp_swiginit(self,_html.new_HtmlModalHelp(*args, **kwargs))
+_html.HtmlModalHelp_swigregister(HtmlModalHelp)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/html2.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/html2.py
new file mode 100644
index 0000000..1338011
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/html2.py
@@ -0,0 +1,425 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+Classes for embedding a full web browser rendering engine in a window.
+"""
+
+import _html2
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+#---------------------------------------------------------------------------
+
+WEBVIEW_ZOOM_TINY = _html2.WEBVIEW_ZOOM_TINY
+WEBVIEW_ZOOM_SMALL = _html2.WEBVIEW_ZOOM_SMALL
+WEBVIEW_ZOOM_MEDIUM = _html2.WEBVIEW_ZOOM_MEDIUM
+WEBVIEW_ZOOM_LARGE = _html2.WEBVIEW_ZOOM_LARGE
+WEBVIEW_ZOOM_LARGEST = _html2.WEBVIEW_ZOOM_LARGEST
+WEBVIEW_ZOOM_TYPE_LAYOUT = _html2.WEBVIEW_ZOOM_TYPE_LAYOUT
+WEBVIEW_ZOOM_TYPE_TEXT = _html2.WEBVIEW_ZOOM_TYPE_TEXT
+WEBVIEW_NAV_ERR_CONNECTION = _html2.WEBVIEW_NAV_ERR_CONNECTION
+WEBVIEW_NAV_ERR_CERTIFICATE = _html2.WEBVIEW_NAV_ERR_CERTIFICATE
+WEBVIEW_NAV_ERR_AUTH = _html2.WEBVIEW_NAV_ERR_AUTH
+WEBVIEW_NAV_ERR_SECURITY = _html2.WEBVIEW_NAV_ERR_SECURITY
+WEBVIEW_NAV_ERR_NOT_FOUND = _html2.WEBVIEW_NAV_ERR_NOT_FOUND
+WEBVIEW_NAV_ERR_REQUEST = _html2.WEBVIEW_NAV_ERR_REQUEST
+WEBVIEW_NAV_ERR_USER_CANCELLED = _html2.WEBVIEW_NAV_ERR_USER_CANCELLED
+WEBVIEW_NAV_ERR_OTHER = _html2.WEBVIEW_NAV_ERR_OTHER
+WEBVIEW_RELOAD_DEFAULT = _html2.WEBVIEW_RELOAD_DEFAULT
+WEBVIEW_RELOAD_NO_CACHE = _html2.WEBVIEW_RELOAD_NO_CACHE
+WEBVIEW_FIND_WRAP = _html2.WEBVIEW_FIND_WRAP
+WEBVIEW_FIND_ENTIRE_WORD = _html2.WEBVIEW_FIND_ENTIRE_WORD
+WEBVIEW_FIND_MATCH_CASE = _html2.WEBVIEW_FIND_MATCH_CASE
+WEBVIEW_FIND_HIGHLIGHT_RESULT = _html2.WEBVIEW_FIND_HIGHLIGHT_RESULT
+WEBVIEW_FIND_BACKWARDS = _html2.WEBVIEW_FIND_BACKWARDS
+WEBVIEW_FIND_DEFAULT = _html2.WEBVIEW_FIND_DEFAULT
+class WebViewHistoryItem(object):
+ """Proxy of C++ WebViewHistoryItem class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String url, String title) -> WebViewHistoryItem"""
+ _html2.WebViewHistoryItem_swiginit(self,_html2.new_WebViewHistoryItem(*args, **kwargs))
+ def GetUrl(*args, **kwargs):
+ """GetUrl(self) -> String"""
+ return _html2.WebViewHistoryItem_GetUrl(*args, **kwargs)
+
+ def GetTitle(*args, **kwargs):
+ """GetTitle(self) -> String"""
+ return _html2.WebViewHistoryItem_GetTitle(*args, **kwargs)
+
+_html2.WebViewHistoryItem_swigregister(WebViewHistoryItem)
+cvar = _html2.cvar
+WebViewBackendDefault = cvar.WebViewBackendDefault
+WebViewBackendIE = cvar.WebViewBackendIE
+WebViewBackendWebKit = cvar.WebViewBackendWebKit
+WebViewDefaultURLStr = cvar.WebViewDefaultURLStr
+WebViewNameStr = cvar.WebViewNameStr
+
+class WebViewFactory(_core.Object):
+ """Proxy of C++ WebViewFactory class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Create(*args):
+ """
+ Create(self) -> WebView
+ Create(self, Window parent, int id, String url=wxWebViewDefaultURLStr,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=wxWebViewNameStr) -> WebView
+ """
+ return _html2.WebViewFactory_Create(*args)
+
+_html2.WebViewFactory_swigregister(WebViewFactory)
+
+class WebView(_core.Control):
+ """Proxy of C++ WebView class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, String url=wxWebViewDefaultURLStr,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String name=wxWebViewNameStr) -> bool
+ """
+ return _html2.WebView_Create(*args, **kwargs)
+
+ def PreNew(*args, **kwargs):
+ """PreNew(String backend=wxWebViewBackendDefault) -> WebView"""
+ return _html2.WebView_PreNew(*args, **kwargs)
+
+ PreNew = staticmethod(PreNew)
+ def New(*args, **kwargs):
+ """
+ New(Window parent, int id=ID_ANY, String url=wxWebViewDefaultURLStr,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ String backend=wxWebViewBackendDefault,
+ long style=0, String name=wxWebViewNameStr) -> WebView
+ """
+ val = _html2.WebView_New(*args, **kwargs)
+ val._setOORInfo(val)
+ return val
+
+ New = staticmethod(New)
+ def GetCurrentTitle(*args, **kwargs):
+ """GetCurrentTitle(self) -> String"""
+ return _html2.WebView_GetCurrentTitle(*args, **kwargs)
+
+ def GetCurrentURL(*args, **kwargs):
+ """GetCurrentURL(self) -> String"""
+ return _html2.WebView_GetCurrentURL(*args, **kwargs)
+
+ def GetPageSource(*args, **kwargs):
+ """GetPageSource(self) -> String"""
+ return _html2.WebView_GetPageSource(*args, **kwargs)
+
+ def GetPageText(*args, **kwargs):
+ """GetPageText(self) -> String"""
+ return _html2.WebView_GetPageText(*args, **kwargs)
+
+ def IsBusy(*args, **kwargs):
+ """IsBusy(self) -> bool"""
+ return _html2.WebView_IsBusy(*args, **kwargs)
+
+ def IsEditable(*args, **kwargs):
+ """IsEditable(self) -> bool"""
+ return _html2.WebView_IsEditable(*args, **kwargs)
+
+ def LoadURL(*args, **kwargs):
+ """LoadURL(self, String url)"""
+ return _html2.WebView_LoadURL(*args, **kwargs)
+
+ def Print(*args, **kwargs):
+ """Print(self)"""
+ return _html2.WebView_Print(*args, **kwargs)
+
+ def RegisterHandler(*args, **kwargs):
+ """RegisterHandler(self, wxSharedPtr<(wxWebViewHandler)> handler)"""
+ return _html2.WebView_RegisterHandler(*args, **kwargs)
+
+ def Reload(*args, **kwargs):
+ """Reload(self, int flags=WEBVIEW_RELOAD_DEFAULT)"""
+ return _html2.WebView_Reload(*args, **kwargs)
+
+ def RunScript(*args, **kwargs):
+ """RunScript(self, String javascript)"""
+ return _html2.WebView_RunScript(*args, **kwargs)
+
+ def SetEditable(*args, **kwargs):
+ """SetEditable(self, bool enable=True)"""
+ return _html2.WebView_SetEditable(*args, **kwargs)
+
+ def SetPage(*args):
+ """
+ SetPage(self, String html, String baseUrl)
+ SetPage(self, InputStream html, String baseUrl)
+ """
+ return _html2.WebView_SetPage(*args)
+
+ def Stop(*args, **kwargs):
+ """Stop(self)"""
+ return _html2.WebView_Stop(*args, **kwargs)
+
+ def CanCopy(*args, **kwargs):
+ """CanCopy(self) -> bool"""
+ return _html2.WebView_CanCopy(*args, **kwargs)
+
+ def CanCut(*args, **kwargs):
+ """CanCut(self) -> bool"""
+ return _html2.WebView_CanCut(*args, **kwargs)
+
+ def CanPaste(*args, **kwargs):
+ """CanPaste(self) -> bool"""
+ return _html2.WebView_CanPaste(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self)"""
+ return _html2.WebView_Copy(*args, **kwargs)
+
+ def Cut(*args, **kwargs):
+ """Cut(self)"""
+ return _html2.WebView_Cut(*args, **kwargs)
+
+ def Paste(*args, **kwargs):
+ """Paste(self)"""
+ return _html2.WebView_Paste(*args, **kwargs)
+
+ def CanGoBack(*args, **kwargs):
+ """CanGoBack(self) -> bool"""
+ return _html2.WebView_CanGoBack(*args, **kwargs)
+
+ def CanGoForward(*args, **kwargs):
+ """CanGoForward(self) -> bool"""
+ return _html2.WebView_CanGoForward(*args, **kwargs)
+
+ def ClearHistory(*args, **kwargs):
+ """ClearHistory(self)"""
+ return _html2.WebView_ClearHistory(*args, **kwargs)
+
+ def EnableHistory(*args, **kwargs):
+ """EnableHistory(self, bool enable=True)"""
+ return _html2.WebView_EnableHistory(*args, **kwargs)
+
+ def GoBack(*args, **kwargs):
+ """GoBack(self)"""
+ return _html2.WebView_GoBack(*args, **kwargs)
+
+ def GoForward(*args, **kwargs):
+ """GoForward(self)"""
+ return _html2.WebView_GoForward(*args, **kwargs)
+
+ def LoadHistoryItem(*args, **kwargs):
+ """LoadHistoryItem(self, wxSharedPtr<(wxWebViewHistoryItem)> item)"""
+ return _html2.WebView_LoadHistoryItem(*args, **kwargs)
+
+ def ClearSelection(*args, **kwargs):
+ """ClearSelection(self)"""
+ return _html2.WebView_ClearSelection(*args, **kwargs)
+
+ def DeleteSelection(*args, **kwargs):
+ """DeleteSelection(self)"""
+ return _html2.WebView_DeleteSelection(*args, **kwargs)
+
+ def GetSelectedSource(*args, **kwargs):
+ """GetSelectedSource(self) -> String"""
+ return _html2.WebView_GetSelectedSource(*args, **kwargs)
+
+ def GetSelectedText(*args, **kwargs):
+ """GetSelectedText(self) -> String"""
+ return _html2.WebView_GetSelectedText(*args, **kwargs)
+
+ def HasSelection(*args, **kwargs):
+ """HasSelection(self) -> bool"""
+ return _html2.WebView_HasSelection(*args, **kwargs)
+
+ def SelectAll(*args, **kwargs):
+ """SelectAll(self)"""
+ return _html2.WebView_SelectAll(*args, **kwargs)
+
+ def CanRedo(*args, **kwargs):
+ """CanRedo(self) -> bool"""
+ return _html2.WebView_CanRedo(*args, **kwargs)
+
+ def CanUndo(*args, **kwargs):
+ """CanUndo(self) -> bool"""
+ return _html2.WebView_CanUndo(*args, **kwargs)
+
+ def Redo(*args, **kwargs):
+ """Redo(self)"""
+ return _html2.WebView_Redo(*args, **kwargs)
+
+ def Undo(*args, **kwargs):
+ """Undo(self)"""
+ return _html2.WebView_Undo(*args, **kwargs)
+
+ def CanSetZoomType(*args, **kwargs):
+ """CanSetZoomType(self, int type) -> bool"""
+ return _html2.WebView_CanSetZoomType(*args, **kwargs)
+
+ def GetZoom(*args, **kwargs):
+ """GetZoom(self) -> int"""
+ return _html2.WebView_GetZoom(*args, **kwargs)
+
+ def GetZoomType(*args, **kwargs):
+ """GetZoomType(self) -> int"""
+ return _html2.WebView_GetZoomType(*args, **kwargs)
+
+ def SetZoom(*args, **kwargs):
+ """SetZoom(self, int zoom)"""
+ return _html2.WebView_SetZoom(*args, **kwargs)
+
+ def SetZoomType(*args, **kwargs):
+ """SetZoomType(self, int zoomType)"""
+ return _html2.WebView_SetZoomType(*args, **kwargs)
+
+ def GetNativeBackend(*args, **kwargs):
+ """GetNativeBackend(self) -> void"""
+ return _html2.WebView_GetNativeBackend(*args, **kwargs)
+
+ def Find(*args, **kwargs):
+ """Find(self, String text, int flags=WEBVIEW_FIND_DEFAULT) -> long"""
+ return _html2.WebView_Find(*args, **kwargs)
+
+_html2.WebView_swigregister(WebView)
+
+def WebView_PreNew(*args, **kwargs):
+ """WebView_PreNew(String backend=wxWebViewBackendDefault) -> WebView"""
+ return _html2.WebView_PreNew(*args, **kwargs)
+
+def WebView_New(*args, **kwargs):
+ """
+ WebView_New(Window parent, int id=ID_ANY, String url=wxWebViewDefaultURLStr,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ String backend=wxWebViewBackendDefault,
+ long style=0, String name=wxWebViewNameStr) -> WebView
+ """
+ val = _html2.WebView_New(*args, **kwargs)
+ val._setOORInfo(val)
+ return val
+
+class WebViewEvent(_core.NotifyEvent):
+ """Proxy of C++ WebViewEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType type, int id, String href, String target) -> WebViewEvent"""
+ _html2.WebViewEvent_swiginit(self,_html2.new_WebViewEvent(*args, **kwargs))
+ def GetTarget(*args, **kwargs):
+ """GetTarget(self) -> String"""
+ return _html2.WebViewEvent_GetTarget(*args, **kwargs)
+
+ def GetURL(*args, **kwargs):
+ """GetURL(self) -> String"""
+ return _html2.WebViewEvent_GetURL(*args, **kwargs)
+
+_html2.WebViewEvent_swigregister(WebViewEvent)
+
+wxEVT_WEBVIEW_NAVIGATING = _html2.wxEVT_WEBVIEW_NAVIGATING
+wxEVT_WEBVIEW_NAVIGATED = _html2.wxEVT_WEBVIEW_NAVIGATED
+wxEVT_WEBVIEW_LOADED = _html2.wxEVT_WEBVIEW_LOADED
+wxEVT_WEBVIEW_ERROR = _html2.wxEVT_WEBVIEW_ERROR
+wxEVT_WEBVIEW_NEWWINDOW = _html2.wxEVT_WEBVIEW_NEWWINDOW
+wxEVT_WEBVIEW_TITLE_CHANGED = _html2.wxEVT_WEBVIEW_TITLE_CHANGED
+wxEVT_COMMAND_WEBVIEW_NAVIGATING = _html2.wxEVT_COMMAND_WEBVIEW_NAVIGATING
+wxEVT_COMMAND_WEBVIEW_NAVIGATED = _html2.wxEVT_COMMAND_WEBVIEW_NAVIGATED
+wxEVT_COMMAND_WEBVIEW_LOADED = _html2.wxEVT_COMMAND_WEBVIEW_LOADED
+wxEVT_COMMAND_WEBVIEW_ERROR = _html2.wxEVT_COMMAND_WEBVIEW_ERROR
+wxEVT_COMMAND_WEBVIEW_NEWWINDOW = _html2.wxEVT_COMMAND_WEBVIEW_NEWWINDOW
+wxEVT_COMMAND_WEBVIEW_TITLE_CHANGED = _html2.wxEVT_COMMAND_WEBVIEW_TITLE_CHANGED
+EVT_WEBVIEW_NAVIGATING = wx.PyEventBinder( wxEVT_WEBVIEW_NAVIGATING, 1 )
+EVT_WEBVIEW_NAVIGATED = wx.PyEventBinder( wxEVT_WEBVIEW_NAVIGATED, 1 )
+EVT_WEBVIEW_LOADED = wx.PyEventBinder( wxEVT_WEBVIEW_LOADED, 1 )
+EVT_WEBVIEW_ERROR = wx.PyEventBinder( wxEVT_WEBVIEW_ERROR, 1 )
+EVT_WEBVIEW_NEWWINDOW = wx.PyEventBinder( wxEVT_WEBVIEW_NEWWINDOW, 1 )
+EVT_WEBVIEW_TITLE_CHANGED = wx.PyEventBinder( wxEVT_WEBVIEW_TITLE_CHANGED, 1 )
+
+class WebViewHandler(object):
+ """Proxy of C++ WebViewHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def GetFile(*args, **kwargs):
+ """GetFile(self, String uri) -> FSFile"""
+ return _html2.WebViewHandler_GetFile(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _html2.WebViewHandler_GetName(*args, **kwargs)
+
+_html2.WebViewHandler_swigregister(WebViewHandler)
+
+class PyWebViewHandler(WebViewHandler):
+ """Proxy of C++ PyWebViewHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String scheme) -> PyWebViewHandler"""
+ _html2.PyWebViewHandler_swiginit(self,_html2.new_PyWebViewHandler(*args, **kwargs))
+ PyWebViewHandler._setCallbackInfo(self, self, PyWebViewHandler)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _html2.PyWebViewHandler__setCallbackInfo(*args, **kwargs)
+
+_html2.PyWebViewHandler_swigregister(PyWebViewHandler)
+
+class WebViewArchiveHandler(WebViewHandler):
+ """Proxy of C++ WebViewArchiveHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+_html2.WebViewArchiveHandler_swigregister(WebViewArchiveHandler)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/CDate.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/CDate.py
new file mode 100644
index 0000000..02ef860
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/CDate.py
@@ -0,0 +1,129 @@
+# Name: CDate.py
+# Purpose: Date and Calendar classes
+#
+# Author: Lorne White (email: lwhite1@planet.eon.net)
+#
+# Created:
+# Version 0.2 08-Nov-1999
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+# Updated: 01-Dec-2004
+# Action: Cast the year variable to an integer under the Date Class
+# Reason: When the year was compared in the isleap() function, if it was
+# in a string format, then an error was raised.
+
+import time
+
+Month = {2: 'February', 3: 'March', None: 0, 'July': 7, 11:
+ 'November', 'December': 12, 'June': 6, 'January': 1, 'September': 9,
+ 'August': 8, 'March': 3, 'November': 11, 'April': 4, 12: 'December',
+ 'May': 5, 10: 'October', 9: 'September', 8: 'August', 7: 'July', 6:
+ 'June', 5: 'May', 4: 'April', 'October': 10, 'February': 2, 1:
+ 'January', 0: None}
+
+# Number of days per month (except for February in leap years)
+mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+# Full and abbreviated names of weekdays
+day_name = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
+day_abbr = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', ]
+
+# Return number of leap years in range [y1, y2)
+# Assume y1 <= y2 and no funny (non-leap century) years
+
+def leapdays(y1, y2):
+ return (y2+3)/4 - (y1+3)/4
+
+# Return 1 for leap years, 0 for non-leap years
+def isleap(year):
+ return year % 4 == 0 and (year % 100 <> 0 or year % 400 == 0)
+
+def FillDate(val):
+ s = str(val)
+ if len(s) < 2:
+ s = '0' + s
+ return s
+
+
+def julianDay(year, month, day):
+ b = 0L
+ year, month, day = long(year), long(month), long(day)
+ if month > 12L:
+ year = year + month/12L
+ month = month%12
+ elif month < 1L:
+ month = -month
+ year = year - month/12L - 1L
+ month = 12L - month%12L
+ if year > 0L:
+ yearCorr = 0L
+ else:
+ yearCorr = 3L
+ if month < 3L:
+ year = year - 1L
+ month = month + 12L
+ if year*10000L + month*100L + day > 15821014L:
+ b = 2L - year/100L + year/400L
+ return (1461L*year - yearCorr)/4L + 306001L*(month + 1L)/10000L + day + 1720994L + b
+
+
+def TodayDay():
+ date = time.localtime(time.time())
+ year = date[0]
+ month = date[1]
+ day = date[2]
+ julian = julianDay(year, month, day)
+ daywk = dayOfWeek(julian)
+ daywk = day_name[daywk]
+ return(daywk)
+
+def FormatDay(value):
+ date = FromFormat(value)
+ daywk = DateCalc.dayOfWeek(date)
+ daywk = day_name[daywk]
+ return(daywk)
+
+def FromJulian(julian):
+ julian = long(julian)
+ if (julian < 2299160L):
+ b = julian + 1525L
+ else:
+ alpha = (4L*julian - 7468861L)/146097L
+ b = julian + 1526L + alpha - alpha/4L
+ c = (20L*b - 2442L)/7305L
+ d = 1461L*c/4L
+ e = 10000L*(b - d)/306001L
+ day = int(b - d - 306001L*e/10000L)
+ if e < 14L:
+ month = int(e - 1L)
+ else:
+ month = int(e - 13L)
+ if month > 2:
+ year = c - 4716L
+ else:
+ year = c - 4715L
+ year = int(year)
+ return year, month, day
+
+def dayOfWeek(julian):
+ return int((julian + 1L)%7L)
+
+def daysPerMonth(month, year):
+ ndays = mdays[month] + (month == 2 and isleap(year))
+ return ndays
+
+class now(object):
+ def __init__(self):
+ self.date = time.localtime(time.time())
+ self.year = self.date[0]
+ self.month = self.date[1]
+ self.day = self.date[2]
+
+class Date(object):
+ def __init__(self, year, month, day):
+ self.julian = julianDay(year, month, day)
+ self.month = month
+ self.year = int(year)
+ self.day_of_week = dayOfWeek(self.julian)
+ self.days_in_month = daysPerMonth(self.month, self.year)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ClickableHtmlWindow.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ClickableHtmlWindow.py
new file mode 100644
index 0000000..51c8126
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ClickableHtmlWindow.py
@@ -0,0 +1,57 @@
+# 12/01/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for wx namespace. Not tested though.
+#
+# 12/17/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Removed wx prefix from class name,
+# updated reverse renamer
+#
+
+"""
+sorry no documentation...
+Christopher J. Fama
+"""
+
+
+import wx
+import wx.html as html
+
+class PyClickableHtmlWindow(html.HtmlWindow):
+ """
+ Class for a wxHtmlWindow which responds to clicks on links by opening a
+ browser pointed at that link, and to shift-clicks by copying the link
+ to the clipboard.
+ """
+ def __init__(self,parent,ID,**kw):
+ apply(html.HtmlWindow.__init__,(self,parent,ID),kw)
+
+ def OnLinkClicked(self,link):
+ self.link = wx.TextDataObject(link.GetHref())
+ if link.GetEvent().ShiftDown():
+ if wx.TheClipboard.Open():
+ wx.TheClipboard.SetData(self.link)
+ wx.TheClipboard.Close()
+ else:
+ dlg = wx.MessageDialog(self,"Couldn't open clipboard!\n",wx.OK)
+ wx.Bell()
+ dlg.ShowModal()
+ dlg.Destroy()
+ else:
+ if 0: # Chris's original code...
+ if sys.platform not in ["windows",'nt'] :
+ #TODO: A MORE APPROPRIATE COMMAND LINE FOR Linux
+ #[or rather, non-Windows platforms... as of writing,
+ #this MEANS Linux, until wxPython for wxMac comes along...]
+ command = "/usr/bin/netscape"
+ else:
+ command = "start"
+ command = "%s \"%s\"" % (command,
+ self.link.GetText ())
+ os.system (command)
+
+ else: # My alternative
+ import webbrowser
+ webbrowser.open(link.GetHref())
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/__init__.py
new file mode 100644
index 0000000..54e9b26
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/__init__.py
@@ -0,0 +1,4 @@
+#
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/activex.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/activex.py
new file mode 100644
index 0000000..54370a2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/activex.py
@@ -0,0 +1,173 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.activex
+# Purpose: The 3rd (and hopefully final) implementation of an
+# ActiveX container for wxPython.
+#
+# Author: Robin Dunn
+#
+# Created: 5-June-2008
+# RCS-ID: $Id: $
+# Copyright: (c) 2008 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+
+"""
+This module provides a wx.Window that hosts ActiveX Controls using
+just the ctypes and comtypes packages. This provides a light-weight
+COM implementation with full dynamic dispatch support.
+
+The only requirements are ctypes (included with Python 2.5 and
+available separately for earlier versions of Python) and the comtypes
+package, which is available from
+http://starship.python.net/crew/theller/comtypes/. Be sure to get at
+least version 0.5, which at the time of this writing is only available
+from SVN. You can fetch it with easy_install with a command like
+this:
+
+ easy_install http://svn.python.org/projects/ctypes/trunk/comtypes
+
+"""
+
+import wx
+
+import ctypes as ct
+import ctypes.wintypes as wt
+import comtypes
+import comtypes.client as cc
+import comtypes.hresult as hr
+
+import sys, os
+if not hasattr(sys, 'frozen'):
+ f = os.path.join(os.path.dirname(__file__), 'myole4ax.tlb')
+ cc.GetModule(f)
+from comtypes.gen import myole4ax
+
+
+kernel32 = ct.windll.kernel32
+user32 = ct.windll.user32
+atl = ct.windll.atl
+
+WS_CHILD = 0x40000000
+WS_VISIBLE = 0x10000000
+WS_CLIPCHILDREN = 0x2000000
+WS_CLIPSIBLINGS = 0x4000000
+CW_USEDEFAULT = 0x80000000
+WM_KEYDOWN = 256
+WM_DESTROY = 2
+
+#------------------------------------------------------------------------------
+
+class ActiveXCtrl(wx.PyAxBaseWindow):
+ """
+ A wx.Window for hosting ActiveX controls. The COM interface of
+ the ActiveX control is accessible through the ctrl property of
+ this class, and this class is also set as the event sink for COM
+ events originating from the ActiveX control. In other words, to
+ catch the COM events you mearly have to derive from this class and
+ provide a method with the correct name. See the comtypes package
+ documentation for more details.
+ """
+
+ def __init__(self, parent, axID, wxid=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name="activeXCtrl"):
+ """
+ All parameters are like those used in normal wx.Windows with
+ the addition of axID which is a string that is either a ProgID
+ or a CLSID used to identify the ActiveX control.
+ """
+ pos = wx.Point(*pos) # in case the arg is a tuple
+ size = wx.Size(*size) # ditto
+
+ x = pos.x
+ y = pos.y
+ if x == -1: x = CW_USEDEFAULT
+ if y == -1: y = 20
+ w = size.width
+ h = size.height
+ if w == -1: w = 20
+ if h == -1: h = 20
+
+ # create the control
+ atl.AtlAxWinInit()
+ hInstance = kernel32.GetModuleHandleA(None)
+ hwnd = user32.CreateWindowExA(0, "AtlAxWin", axID,
+ WS_CHILD | WS_VISIBLE
+ | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+ x,y, w,h, parent.GetHandle(), None,
+ hInstance, 0)
+ assert hwnd != 0
+
+ # get the Interface for the Ax control
+ unknown = ct.POINTER(comtypes.IUnknown)()
+ res = atl.AtlAxGetControl(hwnd, ct.byref(unknown))
+ assert res == hr.S_OK
+ self._ax = cc.GetBestInterface(unknown)
+
+ # Fetch the interface for IOleInPlaceActiveObject. We'll use this
+ # later to call its TranslateAccelerator method so the AX Control can
+ # deal with things like tab traversal and such within itself.
+ self.ipao = self._ax.QueryInterface(myole4ax.IOleInPlaceActiveObject)
+
+ # Use this object as the event sink for the ActiveX events
+ self._evt_connections = []
+ self.AddEventSink(self)
+
+ # Turn the window handle into a wx.Window and set this object to be that window
+ win = wx.PyAxBaseWindow_FromHWND(parent, hwnd)
+ self.PostCreate(win)
+
+ # Set some wx.Window properties
+ if wxid == wx.ID_ANY:
+ wxid = wx.Window.NewControlId()
+ self.SetId(wxid)
+ self.SetName(name)
+ self.SetMinSize(size)
+
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroyWindow)
+
+ def AddEventSink(self, sink, interface=None):
+ """
+ Add a new target to search for method names that match the COM
+ Event names.
+ """
+ self._evt_connections.append(cc.GetEvents(self._ax, sink, interface))
+
+ def GetCtrl(self):
+ """Easy access to the COM interface for the ActiveX Control"""
+ return self._ax
+ # And an even easier property
+ ctrl = property(GetCtrl)
+
+
+ def MSWTranslateMessage(self, msg):
+ # Pass native messages to the IOleInPlaceActiveObject
+ # interface before wx processes them, so navigation keys and
+ # accelerators can be dealt with the way that the AXControl
+ # wants them to be done. MSWTranslateMessage is called before
+ # wxWidgets handles and eats the navigation keys itself.
+ res = self.ipao.TranslateAccelerator(msg)
+ if res == hr.S_OK:
+ return True
+ else:
+ return wx.PyAxBaseWindow.MSWTranslateMessage(self, msg)
+
+
+ # TBD: Are the focus handlers needed?
+ def OnSetFocus(self, evt):
+ self.ipao.OnFrameWindowActivate(True)
+
+ def OnKillFocus(self, evt):
+ self.ipao.OnFrameWindowActivate(False)
+
+ def OnDestroyWindow(self, evt):
+ # release our event sinks while the window still exists
+ self._evt_connections = None
+
+#------------------------------------------------------------------------------
+
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/activexwrapper.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/activexwrapper.py
new file mode 100644
index 0000000..67d09d6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/activexwrapper.py
@@ -0,0 +1,155 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.activexwrapper
+# Purpose: a wxWindow derived class that can hold an ActiveX control
+#
+# Author: Robin Dunn
+#
+# RCS-ID: $Id$
+# Copyright: (c) 2000 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 11/30/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for wx namespace
+# o Tested with updated demo
+#
+
+import wx
+
+try:
+ import win32ui
+ import pywin.mfc.activex
+ import win32com.client
+except ImportError:
+ import sys
+ if hasattr(sys, "frozen"):
+ import os, win32api
+ dllpath = os.path.join(win32api.GetSystemDirectory(), 'MFC71.DLL')
+ if sys.version[:3] >= '2.4' and not os.path.exists(dllpath):
+ message = "%s not found" % dllpath
+ else:
+ raise # original error message
+ else:
+ message = "ActiveXWrapper requires PythonWin. Please install the PyWin32 package."
+ raise ImportError(message)
+
+##from win32con import WS_TABSTOP, WS_VISIBLE
+WS_TABSTOP = 0x00010000
+WS_VISIBLE = 0x10000000
+
+#----------------------------------------------------------------------
+
+
+def MakeActiveXClass(CoClass, eventClass=None, eventObj=None):
+ """
+ Dynamically construct a new class that derives from wxWindow, the
+ ActiveX control and the appropriate COM classes. This new class
+ can be used just like the wxWindow class, but will also respond
+ appropriately to the methods and properties of the COM object. If
+ this class, a derived class or a mix-in class has method names
+ that match the COM object's event names, they will be called
+ automatically.
+
+ CoClass -- A COM control class from a module generated by
+ makepy.py from a COM TypeLibrary. Can also accept a
+ CLSID.
+
+ eventClass -- If given, this class will be added to the set of
+ base classes that the new class is drived from. It is
+ good for mix-in classes for catching events.
+
+ eventObj -- If given, this object will be searched for attributes
+ by the new class's __getattr__ method, (like a mix-in
+ object.) This is useful if you want to catch COM
+ callbacks in an existing object, (such as the parent
+ window.)
+
+ """
+
+
+ if type(CoClass) == type(""):
+ # use the CLSID to get the real class
+ CoClass = win32com.client.CLSIDToClass(CoClass)
+
+ # determine the base classes
+ axEventClass = CoClass.default_source
+ baseClasses = [pywin.mfc.activex.Control, wx.Window, CoClass, axEventClass]
+ if eventClass:
+ baseClasses.append(eventClass)
+ baseClasses = tuple(baseClasses)
+
+ # define the class attributes
+ className = 'AXControl_'+CoClass.__name__
+ classDict = { '__init__' : axw__init__,
+ '__getattr__' : axw__getattr__,
+ 'axw_OnSize' : axw_OnSize,
+ 'axw_OEB' : axw_OEB,
+ '_name' : className,
+ '_eventBase' : axEventClass,
+ '_eventObj' : eventObj,
+ 'Cleanup' : axw_Cleanup,
+ }
+
+ # make a new class object
+ import new
+ classObj = new.classobj(className, baseClasses, classDict)
+ return classObj
+
+
+
+
+# These functions will be used as methods in the new class
+def axw__init__(self, parent, ID=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
+
+ # init base classes
+ pywin.mfc.activex.Control.__init__(self)
+ wx.Window.__init__( self, parent, -1, pos, size, style|wx.NO_FULL_REPAINT_ON_RESIZE)
+ self.this.own(False) # this should be set in wx.Window.__init__ when it calls _setOORInfo, but...
+
+ win32ui.EnableControlContainer()
+ self._eventObj = self._eventObj # move from class to instance
+
+ # create a pythonwin wrapper around this wxWindow
+ handle = self.GetHandle()
+ self._wnd = win32ui.CreateWindowFromHandle(handle)
+
+ # create the control
+ sz = self.GetSize()
+ self.CreateControl(self._name, WS_TABSTOP | WS_VISIBLE,
+ (0, 0, sz.width, sz.height), self._wnd, ID)
+
+ # init the ax events part of the object
+ self._eventBase.__init__(self, self._dispobj_)
+
+ # hook some wx events
+ self.Bind(wx.EVT_SIZE, self.axw_OnSize)
+
+def axw__getattr__(self, attr):
+ try:
+ return pywin.mfc.activex.Control.__getattr__(self, attr)
+ except AttributeError:
+ try:
+ eo = self.__dict__['_eventObj']
+ return getattr(eo, attr)
+ except AttributeError:
+ raise AttributeError('Attribute not found: %s' % attr)
+
+
+def axw_OnSize(self, event):
+ sz = self.GetClientSize() # get wxWindow size
+ self.MoveWindow((0, 0, sz.width, sz.height), 1) # move the AXControl
+
+
+def axw_OEB(self, event):
+ pass
+
+
+def axw_Cleanup(self):
+ #del self._wnd
+ self.close()
+ pass
+
+
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/__init__.py
new file mode 100644
index 0000000..3cb8b41
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/__init__.py
@@ -0,0 +1,128 @@
+
+"""
+This is the Advanced Generic Widgets package (AGW). It provides many
+custom-drawn wxPython controls: some of them can be used as a replacement
+of the platform native controls, others are simply an addition to the
+already rich wxPython widgets set.
+
+
+Description:
+
+AGW contains many different modules, listed below. Items labelled with
+an asterisk were already present in :mod:`lib` before:
+
+- AdvancedSplash: reproduces the behaviour of :class:`SplashScreen`, with more
+ advanced features like custom shapes and text animations;
+- AquaButton: this is another custom-drawn button class which
+ *approximatively* mimics the behaviour of Aqua buttons on the Mac;
+- AUI: a pure-Python implementation of :mod:`~lib.agw.aui`, with many bug fixes and
+ new features like HUD docking and :class:`~lib.agw.aui.auibook.AuiNotebook` tab arts;
+- BalloonTip: allows you to display tooltips in a balloon style window
+ (actually a frame), similarly to the Windows XP balloon help;
+- ButtonPanel (*): a panel with gradient background shading with the
+ possibility to add buttons and controls still respecting the gradient
+ background;
+- CubeColourDialog: an alternative implementation of :class:`ColourDialog`, it
+ offers different functionalities like colour wheel and RGB cube;
+- CustomTreeCtrl (*): mimics the behaviour of :class:`TreeCtrl`, with almost the
+ same base functionalities plus a bunch of enhancements and goodies;
+- FlatMenu: as the name implies, it is a generic menu implementation,
+ offering the same :class:`MenuBar` / :class:`Menu` / :class:`ToolBar` capabilities and much more;
+- FlatNotebook (*): a full implementation of the :class:`Notebook`, and designed
+ to be a drop-in replacement for :class:`Notebook` with enhanced capabilities;
+- FloatSpin: this class implements a floating point spinctrl, cabable (in
+ theory) of handling infinite-precision floating point numbers;
+- FoldPanelBar (*): a control that contains multiple panels that can be
+ expanded or collapsed a la Windows Explorer/Outlook command bars;
+- FourWaySplitter: this is a layout manager which manages four children like
+ four panes in a window, similar to many CAD software interfaces;
+- GenericMessageDialog: it is a possible replacement for the standard
+ :class:`MessageDialog`, with a fancier look and extended functionalities;
+- GradientButton: another custom-drawn button class which mimics Windows CE
+ mobile gradient buttons, using a tri-vertex blended gradient background;
+- HyperLinkCtrl (*): this widget acts line an hyper link in a typical browser;
+- HyperTreeList: a class that mimics the behaviour of :class:`gizmos.TreeListCtrl`,
+ with almost the same base functionalities plus some more enhancements;
+- InfoBar: a transient window shown at top or bottom of its parent window to display
+ non-critical information to the user;
+- KnobCtrl: a widget which lets the user select a numerical value by
+ rotating it, like a slider with a wheel shape;
+- LabelBook and FlatImageBook: these are a quasi-full implementations of
+ :class:`ListBook`, with additional features;
+- MultiDirDialog: it represents a possible replacement for :class:`DirDialog`,
+ with the additional ability of selecting multiple folders at once and a
+ fancier look;
+- PeakMeter: this widget mimics the behaviour of LED equalizers that are
+ usually found in stereos and MP3 players;
+- PersistentControls: widgets which automatically save their state
+ when they are destroyed and restore it when they are recreated, even during
+ another program invocation;
+- PieCtrl and ProgressPie: these are simple classes that reproduce the
+ behavior of a pie chart, in a static or progress-gauge-like way;
+- PyBusyInfo: constructs a busy info window and displays a message in it:
+ it is similar to :class:`BusyInfo`;
+- PyCollapsiblePane: a pure Python implementation of the original wxWidgets
+ C++ code of :class:`CollapsiblePane`, with customizable buttons;
+- PyGauge: a generic :class:`Gauge` implementation, it supports the determinate
+ mode functions as :class:`Gauge`;
+- PyProgress: it is similar to :class:`ProgressDialog` in indeterminated mode, but
+ with a different gauge appearance and a different spinning behavior;
+- RibbonBar: the RibbonBar library is a set of classes for writing a ribbon
+ user interface, similar to the user interface present in recent versions
+ of Microsoft Office;
+- RulerCtrl: it implements a ruler window that can be placed on top, bottom,
+ left or right to any wxPython widget. It is somewhat similar to the rulers
+ you can find in text editors software;
+- ShapedButton: this class tries to fill the lack of "custom shaped" controls
+ in wxPython. It can be used to build round buttons or elliptic buttons;
+- ShortcutEditor: a widget that allows the user to customize and change
+ keyboard shortcuts via a dialog;
+- SpeedMeter: this widget tries to reproduce the behavior of some car
+ controls (but not only), by creating an "angular" control;
+- SuperToolTip: a class that mimics the behaviour of :class:`TipWindow` and
+ generic tooltips, with many features and highly customizable;
+- ThumbnailCtrl: a widget that can be used to display a series of images
+ in a "thumbnail" format; it mimics, for example, the Windows Explorer
+ behavior when you select the "view thumbnails" option;
+- ToasterBox: a cross-platform widget to make the creation of MSN-style
+ "toaster" popups easier;
+- UltimateListCtrl: mimics the behaviour of :class:`ListCtrl`, with almost the same
+ base functionalities plus some more enhancements;
+- XLSGrid: a class based on :class:`grid.Grid` that can be used to faithfully
+ reproduce the appearance of a Microsoft Excel spreadsheets;
+- ZoomBar: a class that *appoximatively* mimics the behaviour of the Mac Dock,
+ inside a :class:`Panel`.
+
+
+Bugs and Limitations: many, patches and fixes welcome :-D
+
+See the demos for an example of what AGW can do, and on how to use it.
+
+Copyright: Andrea Gavana
+
+License: Same as the version of wxPython you are using it with.
+
+SVN for latest code:
+http://svn.wxwidgets.org/viewvc/wx/wxPython/3rdParty/AGW/
+
+Mailing List:
+wxpython-users@lists.wxwidgets.org
+
+My personal web page:
+http://xoomer.alice.it/infinity77
+
+Please let me know if you are using AGW!
+
+You can contact me at:
+
+andrea.gavana@gmail.com
+andrea.gavana@maerskoil.com
+
+AGW version: 0.9.7
+
+Last updated: 15 February 2014, 23.00 GMT
+
+"""
+
+__version__ = "0.9.7"
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/advancedsplash.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/advancedsplash.py
new file mode 100644
index 0000000..b60d96f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/advancedsplash.py
@@ -0,0 +1,546 @@
+# --------------------------------------------------------------------------- #
+# ADVANCEDSPLASH Control wxPython IMPLEMENTATION
+# Python Code By:
+#
+# Andrea Gavana, @ 10 Oct 2005
+# Latest Revision: 17 Aug 2011, 15.00 GMT
+#
+#
+# TODO List/Caveats
+#
+# 1. Actually, Setting The Shape Of AdvancedSplash Is Done Using "SetShape"
+# Function On A Frame. This Works, AFAIK, On This Following Platforms:
+#
+# - MSW
+# - UNIX/Linux
+# - MacOS Carbon
+#
+# Obviously I May Be Wrong Here. Could Someone Verify That Lines 139-145
+# Work Correctly On Other Platforms Than Mine (MSW XP/2000)?
+# Moreover, Is There A Way To Avoid The Use Of The "SetShape" Method?
+# I Don't Know.
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+
+"""
+:class:`AdvancedSplash` tries to reproduce the behavior of :class:`SplashScreen`, with
+some enhancements.
+
+
+Description
+===========
+
+:class:`AdvancedSplash` tries to reproduce the behavior of :class:`SplashScreen`, but with
+some enhancements (in my opinion).
+
+:class:`AdvancedSplash` starts its construction from a simple frame. Then, depending on
+the options passed to it, it sets the frame shape accordingly to the image passed
+as input. :class:`AdvancedSplash` behaves somewhat like :class:`SplashScreen`, and almost
+all the methods available in :class:`SplashScreen` are available also in
+this module.
+
+
+Usage
+=====
+
+Sample usage::
+
+ import wx
+ import wx.lib.agw.advancedsplash as AS
+
+ app = wx.App(0)
+
+ frame = wx.Frame(None, -1, "AdvancedSplash Test")
+
+ imagePath = "my_splash_image.png"
+ bitmap = wx.Bitmap(imagePath, wx.BITMAP_TYPE_PNG)
+ shadow = wx.WHITE
+
+ splash = AS.AdvancedSplash(frame, bitmap=bitmap, timeout=5000,
+ agwStyle=AS.AS_TIMEOUT |
+ AS.AS_CENTER_ON_PARENT |
+ AS.AS_SHADOW_BITMAP,
+ shadowcolour=shadow)
+
+ app.MainLoop()
+
+
+None of the options are strictly required (a part of the `bitmap` parameter).
+If you use the defaults you get a very simple :class:`AdvancedSplash`.
+
+
+Methods and Settings
+====================
+
+:class:`AdvancedSplash` is customizable, and in particular you can set:
+
+- Whether you want to mask a colour or not in your input bitmap;
+- Where to center the splash screen (on screen, on parent or nowhere);
+- Whether it is a "timeout" splashscreen or not;
+- The time after which :class:`AdvancedSplash` is destroyed (if it is a timeout splashscreen);
+- The (optional) text you wish to display;
+- The font, colour and position of the displayed text (optional).
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+======================= =========== ==================================================
+Window Styles Hex Value Description
+======================= =========== ==================================================
+``AS_TIMEOUT`` 0x1 :class:`AdvancedSplash` will be destroyed after `timeout` milliseconds.
+``AS_NOTIMEOUT`` 0x2 :class:`AdvancedSplash` can be destroyed by clicking on it, pressing a key or by explicitly call the `Close()` method.
+``AS_CENTER_ON_SCREEN`` 0x4 :class:`AdvancedSplash` will be centered on screen.
+``AS_CENTER_ON_PARENT`` 0x8 :class:`AdvancedSplash` will be centered on parent.
+``AS_NO_CENTER`` 0x10 :class:`AdvancedSplash` will not be centered.
+``AS_SHADOW_BITMAP`` 0x20 If the bitmap you pass as input has no transparency, you can choose one colour that will be masked in your bitmap. the final shape of :class:`AdvancedSplash` will be defined only by non-transparent (non-masked) pixels.
+======================= =========== ==================================================
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`AdvancedSplash` control is distributed under the wxPython license.
+
+Latest revision: Andrea Gavana @ 17 Aug 2011, 15.00 GMT
+
+Version 0.4
+
+"""
+
+
+#----------------------------------------------------------------------
+# Beginning Of ADVANCEDSPLASH wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+
+# These Are Used To Declare If The AdvancedSplash Should Be Destroyed After The
+# Timeout Or Not
+
+AS_TIMEOUT = 1
+""" :class:`AdvancedSplash` will be destroyed after `timeout` milliseconds. """
+AS_NOTIMEOUT = 2
+""" :class:`AdvancedSplash` can be destroyed by clicking on it, pressing a key or by explicitly call the `Close()` method. """
+
+# These Flags Are Used To Position AdvancedSplash Correctly On Screen
+AS_CENTER_ON_SCREEN = 4
+""" :class:`AdvancedSplash` will be centered on screen. """
+AS_CENTER_ON_PARENT = 8
+""" :class:`AdvancedSplash` will be centered on parent. """
+AS_NO_CENTER = 16
+""" :class:`AdvancedSplash` will not be centered. """
+
+# This Option Allow To Mask A Colour In The Input Bitmap
+AS_SHADOW_BITMAP = 32
+""" If the bitmap you pass as input has no transparency, you can choose one colour that will be masked in your bitmap. the final shape of :class:`AdvancedSplash` will be defined only by non-transparent (non-masked) pixels. """
+
+#----------------------------------------------------------------------
+# ADVANCEDSPLASH Class
+# This Is The Main Class Implementation. See __init__() Method For
+# Details.
+#----------------------------------------------------------------------
+
+class AdvancedSplash(wx.Frame):
+ """
+ :class:`AdvancedSplash` tries to reproduce the behavior of :class:`SplashScreen`, with
+ some enhancements.
+
+ This is the main class implementation.
+ """
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.FRAME_NO_TASKBAR | wx.FRAME_SHAPED | wx.STAY_ON_TOP,
+ bitmap=None, timeout=5000,
+ agwStyle=AS_TIMEOUT | AS_CENTER_ON_SCREEN,
+ shadowcolour=wx.NullColour):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window;
+ :param integer `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param integer `style`: the underlying :class:`Frame` style;
+ :param `bitmap`: this must be a valid bitmap, that you may construct using
+ whatever image file format supported by wxPython. If the file you load
+ already supports mask/transparency (like png), the transparent areas
+ will not be drawn on screen, and the :class:`AdvancedSplash` frame will have
+ the shape defined only by *non-transparent* pixels.
+ If you use other file formats that does not supports transparency, you
+ can obtain the same effect as above by masking a specific colour in
+ your :class:`Bitmap`.
+ :param integer `timeout`: if you construct :class:`AdvancedSplash` using the style ``AS_TIMEOUT``,
+ :class:`AdvancedSplash` will be destroyed after `timeout` milliseconds;
+ :param integer `agwStyle`: this value specifies the :class:`AdvancedSplash` styles:
+
+ ======================= =========== ==================================================
+ Window Styles Hex Value Description
+ ======================= =========== ==================================================
+ ``AS_TIMEOUT`` 0x1 :class:`AdvancedSplash` will be destroyed after `timeout` milliseconds.
+ ``AS_NOTIMEOUT`` 0x2 :class:`AdvancedSplash` can be destroyed by clicking on it, pressing a key or by explicitly call the `Close()` method.
+ ``AS_CENTER_ON_SCREEN`` 0x4 :class:`AdvancedSplash` will be centered on screen.
+ ``AS_CENTER_ON_PARENT`` 0x8 :class:`AdvancedSplash` will be centered on parent.
+ ``AS_NO_CENTER`` 0x10 :class:`AdvancedSplash` will not be centered.
+ ``AS_SHADOW_BITMAP`` 0x20 If the bitmap you pass as input has no transparency, you can choose one colour that will be masked in your bitmap. the final shape of :class:`AdvancedSplash` will be defined only by non-transparent (non-masked) pixels.
+ ======================= =========== ==================================================
+
+ :param `shadowcolour`: if you construct :class:`AdvancedSplash` using the style
+ ``AS_SHADOW_BITMAP``, here you can specify the colour that will be masked on
+ your input bitmap. This has to be a valid wxPython colour.
+
+ :type parent: :class:`Window`
+ :type pos: tuple or :class:`Point`
+ :type size: tuple or :class:`Size`
+ :type bitmap: :class:`Bitmap`
+ :type shadowcolour: :class:`Colour`
+
+ :raise: `Exception` in the following cases:
+
+ - The ``AS_TIMEOUT`` style is set but `timeout` is not a positive integer;
+ - The ``AS_SHADOW_BITMAP`` style is set but `shadowcolour` is not a valid wxPython colour;
+ - The :class:`AdvancedSplash` bitmap is an invalid :class:`Bitmap`.
+
+ """
+
+ wx.Frame.__init__(self, parent, id, "", pos, size, style)
+
+ # Some Error Checking
+ if agwStyle & AS_TIMEOUT and timeout <= 0:
+ raise Exception('\nERROR: Style "AS_TIMEOUT" Used With Invalid "timeout" Parameter Value (' \
+ + str(timeout) + ')')
+
+ if agwStyle & AS_SHADOW_BITMAP and not shadowcolour.IsOk():
+ raise Exception('\nERROR: Style "AS_SHADOW_BITMAP" Used With Invalid "shadowcolour" Parameter')
+
+ if not bitmap or not bitmap.IsOk():
+ raise Exception("\nERROR: Bitmap Passed To AdvancedSplash Is Invalid.")
+
+ if agwStyle & AS_SHADOW_BITMAP:
+ # Our Bitmap Is Masked Accordingly To User Input
+ self.bmp = self.ShadowBitmap(bitmap, shadowcolour)
+ else:
+ self.bmp = bitmap
+
+ self._agwStyle = agwStyle
+
+ # Setting Initial Properties
+ self.SetText()
+ self.SetTextFont()
+ self.SetTextPosition()
+ self.SetTextColour()
+
+ # Calculate The Shape Of AdvancedSplash Using The Input-Modified Bitmap
+ self.reg = wx.RegionFromBitmap(self.bmp)
+
+ # Don't Know If It Works On Other Platforms!!
+ # Tested Only In Windows XP/2000
+
+ if wx.Platform == "__WXGTK__":
+ self.Bind(wx.EVT_WINDOW_CREATE, self.SetSplashShape)
+ else:
+ self.SetSplashShape()
+
+ w = self.bmp.GetWidth() + 1
+ h = self.bmp.GetHeight() + 1
+
+ # Set The AdvancedSplash Size To The Bitmap Size
+ self.SetClientSize((w, h))
+
+ if agwStyle & AS_CENTER_ON_SCREEN:
+ self.CenterOnScreen()
+ elif agwStyle & AS_CENTER_ON_PARENT:
+ self.CenterOnParent()
+
+ if agwStyle & AS_TIMEOUT:
+ # Starts The Timer. Once Expired, AdvancedSplash Is Destroyed
+ self._splashtimer = wx.PyTimer(self.OnNotify)
+ self._splashtimer.Start(timeout)
+
+ # Catch Some Mouse Events, To Behave Like wx.SplashScreen
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvents)
+ self.Bind(wx.EVT_CHAR, self.OnCharEvents)
+
+ self.Show()
+ if wx.Platform == "__WXMAC__":
+ wx.SafeYield(self, True)
+
+
+ def SetSplashShape(self, event=None):
+ """
+ Sets :class:`AdvancedSplash` shape using the region created from the bitmap.
+
+ :param `event`: a :class:`WindowCreateEvent` event (GTK only, as GTK supports setting
+ the window shape only during window creation).
+ """
+
+ self.SetShape(self.reg)
+
+ if event is not None:
+ event.Skip()
+
+
+ def ShadowBitmap(self, bmp, shadowcolour):
+ """
+ Applies a mask on the bitmap accordingly to user input.
+
+ :param `bmp`: the bitmap to which we want to apply the mask colour `shadowcolour`;
+ :param `shadowcolour`: the mask colour for our bitmap.
+ :type bmp: :class:`Bitmap`
+ :type shadowcolour: :class:`Colour`
+
+ :return: A masked version of the input bitmap, an instance of :class:`Bitmap`.
+ """
+
+ mask = wx.Mask(bmp, shadowcolour)
+ bmp.SetMask(mask)
+
+ return bmp
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`AdvancedSplash`.
+
+ :param `event`: a :class:`PaintEvent` to be processed.
+ """
+
+ dc = wx.PaintDC(self)
+
+ # Here We Redraw The Bitmap Over The Frame
+ dc.DrawBitmap(self.bmp, 0, 0, True)
+
+ # We Draw The Text Anyway, Wheter It Is Empty ("") Or Not
+ textcolour = self.GetTextColour()
+ textfont = self.GetTextFont()
+ textpos = self.GetTextPosition()
+ text = self.GetText()
+
+ dc.SetFont(textfont[0])
+ dc.SetTextForeground(textcolour)
+ dc.DrawText(text, textpos[0], textpos[1])
+
+
+ def OnNotify(self):
+ """ Handles the timer expiration, and calls the `Close()` method. """
+
+ self.Close()
+
+
+ def OnMouseEvents(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` events for :class:`AdvancedSplash`.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+
+ :note: This reproduces the behavior of :class:`SplashScreen`.
+ """
+
+ if event.LeftDown() or event.RightDown():
+ self.Close()
+
+ event.Skip()
+
+
+ def OnCharEvents(self, event):
+ """
+ Handles the ``wx.EVT_CHAR`` event for :class:`AdvancedSplash`.
+
+ :param `event`: a :class:`KeyEvent` to be processed.
+
+ :note: This reproduces the behavior of :class:`SplashScreen`.
+ """
+
+ self.Close()
+
+
+ def OnCloseWindow(self, event):
+ """
+ Handles the ``wx.EVT_CLOSE`` event for :class:`AdvancedSplash`.
+
+ :param `event`: a :class:`CloseEvent` to be processed.
+
+ :note: This reproduces the behavior of :class:`SplashScreen`.
+ """
+
+ if hasattr(self, "_splashtimer"):
+ self._splashtimer.Stop()
+ del self._splashtimer
+
+ self.Destroy()
+
+
+ def SetText(self, text=None):
+ """
+ Sets the text to be displayed on :class:`AdvancedSplash`.
+
+ :param `text`: the text we want to display on top of the bitmap. If `text` is
+ set to ``None``, nothing will be drawn on top of the bitmap.
+ :type text: string or ``None``
+ """
+
+ if text is None:
+ text = ""
+
+ self._text = text
+
+ self.Refresh()
+ self.Update()
+
+
+ def GetText(self):
+ """
+ Returns the text displayed on :class:`AdvancedSplash`.
+
+ :return: A string representing the text drawn on top of the :class:`AdvancedSplash` bitmap.
+ """
+
+ return self._text
+
+
+ def SetTextFont(self, font=None):
+ """
+ Sets the font for the text in :class:`AdvancedSplash`.
+
+ :param `font`: the font to use while drawing the text on top of our bitmap. If `font`
+ is ``None``, a simple generic font is generated.
+ :type font: :class:`Font` or ``None``
+ """
+
+ if font is None:
+ self._textfont = wx.Font(1, wx.SWISS, wx.NORMAL, wx.BOLD, False)
+ self._textsize = 10.0
+ self._textfont.SetPointSize(self._textsize)
+ else:
+ self._textfont = font
+ self._textsize = font.GetPointSize()
+ self._textfont.SetPointSize(self._textsize)
+
+ self.Refresh()
+ self.Update()
+
+
+ def GetTextFont(self):
+ """
+ Gets the font for the text in :class:`AdvancedSplash`.
+
+ :return: An instance of :class:`Font` to draw the text and a :class:`Size` object containing
+ the text width an height, in pixels.
+ """
+
+ return self._textfont, self._textsize
+
+
+ def SetTextColour(self, colour=None):
+ """
+ Sets the colour for the text in :class:`AdvancedSplash`.
+
+ :param `colour`: the text colour to use while drawing the text on top of our
+ bitmap. If `colour` is ``None``, then ``wx.BLACK`` is used.
+ :type colour: :class:`Colour` or ``None``
+ """
+
+ if colour is None:
+ colour = wx.BLACK
+
+ self._textcolour = colour
+ self.Refresh()
+ self.Update()
+
+
+ def GetTextColour(self):
+ """
+ Gets the colour for the text in :class:`AdvancedSplash`.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._textcolour
+
+
+ def SetTextPosition(self, position=None):
+ """
+ Sets the text position inside :class:`AdvancedSplash` frame.
+
+ :param `position`: the text position inside our bitmap. If `position` is ``None``,
+ the text will be placed at the top-left corner.
+ :type position: tuple or ``None``
+ """
+
+ if position is None:
+ position = (0, 0)
+
+ self._textpos = position
+ self.Refresh()
+ self.Update()
+
+
+ def GetTextPosition(self):
+ """
+ Returns the text position inside :class:`AdvancedSplash` frame.
+
+ :return: A tuple containing the text `x` and `y` position inside the :class:`AdvancedSplash` frame.
+ """
+
+ return self._textpos
+
+
+ def GetSplashStyle(self):
+ """
+ Returns a list of strings and a list of integers containing the styles.
+
+ :return: Two Python lists containing the style name and style values for :class:`AdvancedSplash`.
+ """
+
+ stringstyle = []
+ integerstyle = []
+
+ if self._agwStyle & AS_TIMEOUT:
+ stringstyle.append("AS_TIMEOUT")
+ integerstyle.append(AS_TIMEOUT)
+
+ if self._agwStyle & AS_NOTIMEOUT:
+ stringstyle.append("AS_NOTIMEOUT")
+ integerstyle.append(AS_NOTIMEOUT)
+
+ if self._agwStyle & AS_CENTER_ON_SCREEN:
+ stringstyle.append("AS_CENTER_ON_SCREEN")
+ integerstyle.append(AS_CENTER_ON_SCREEN)
+
+ if self._agwStyle & AS_CENTER_ON_PARENT:
+ stringstyle.append("AS_CENTER_ON_PARENT")
+ integerstyle.append(AS_CENTER_ON_PARENT)
+
+ if self._agwStyle & AS_NO_CENTER:
+ stringstyle.append("AS_NO_CENTER")
+ integerstyle.append(AS_NO_CENTER)
+
+ if self._agwStyle & AS_SHADOW_BITMAP:
+ stringstyle.append("AS_SHADOW_BITMAP")
+ integerstyle.append(AS_SHADOW_BITMAP)
+
+ return stringstyle, integerstyle
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aquabutton.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aquabutton.py
new file mode 100644
index 0000000..279082c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aquabutton.py
@@ -0,0 +1,1086 @@
+# --------------------------------------------------------------------------------- #
+# AQUABUTTON wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 07 October 2008
+# Latest Revision: 03 Dec 2012, 21.00 GMT
+#
+#
+# TODO List
+#
+# 1) Anything to do?
+#
+#
+# For all kind of problems, requests of enhancements and bug reports, please
+# write to me at:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, obviously, to the wxPython mailing list!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`AquaButton` is another custom-drawn button class which *approximatively* mimics
+the behaviour of Aqua buttons on the Mac.
+
+
+Description
+===========
+
+:class:`AquaButton` is another custom-drawn button class which *approximatively* mimics
+the behaviour of Aqua buttons on the Mac. At the moment this class supports:
+
+* Bubble and shadow effects;
+* Customizable background, foreground and hover colours;
+* Rounded-corners buttons;
+* Text-only or image+text buttons;
+* Pulse effect on gaining focus.
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+Usage
+=====
+
+Sample usage::
+
+ import wx
+ import wx.lib.agw.aquabutton as AB
+
+ app = wx.App(0)
+
+ frame = wx.Frame(None, -1, "AquaButton Test")
+
+ mainPanel = wx.Panel(frame)
+ mainPanel.SetBackgroundColour(wx.WHITE)
+
+ # Initialize AquaButton 1 (with image)
+ bitmap = wx.Bitmap("my_button_bitmap.png", wx.BITMAP_TYPE_PNG)
+ btn1 = AB.AquaButton(mainPanel, -1, bitmap, "AquaButton")
+
+ # Initialize AquaButton 2 (no image)
+ btn2 = AB.AquaButton(mainPanel, -1, None, "Hello World!")
+
+ frame.Show()
+
+ app.MainLoop()
+
+
+Supported Platforms
+===================
+
+AquaButton has been tested on the following platforms:
+ * Windows (Windows XP);
+ * Linux Ubuntu (10.10).
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================= ==================================================
+Event Name Description
+================= ==================================================
+``wx.EVT_BUTTON`` Process a `wxEVT_COMMAND_BUTTON_CLICKED` event, when the button is clicked.
+================= ==================================================
+
+
+License And Version
+===================
+
+:class:`AquaButton` control is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 03 Dec 2012, 21.00 GMT
+
+Version 0.4
+
+"""
+
+import wx
+
+# Constants for the hovering and clicking effects
+HOVER = 1
+""" Indicates that the mouse is hovering over :class:`AquaButton` """
+CLICK = 2
+""" Indicates that :class:`AquaButton` has been clicked """
+
+
+class AquaButtonEvent(wx.PyCommandEvent):
+ """ Event sent from the :class:`AquaButton` buttons when the button is activated. """
+
+ def __init__(self, eventType, eventId):
+ """
+ Default class constructor.
+
+ :param integer `eventType`: the event type;
+ :param integer `eventId`: the event identifier.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+ self.isDown = False
+ self.theButton = None
+
+
+ def SetButtonObj(self, btn):
+ """
+ Sets the event object for the event.
+
+ :param `btn`: the button object, an instance of :class:`AquaButton`.
+ """
+
+ self.theButton = btn
+
+
+ def GetButtonObj(self):
+ """
+ Returns the object associated with this event.
+
+ :return: An instance of :class:`AquaButton`.
+ """
+
+ return self.theButton
+
+
+class AquaButton(wx.PyControl):
+ """ This is the main class implementation of :class:`AquaButton`. """
+
+ def __init__(self, parent, id=wx.ID_ANY, bitmap=None, label="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.NO_BORDER, validator=wx.DefaultValidator,
+ name="aquabutton"):
+ """
+ Default class constructor.
+
+ :param Window `parent`: parent window. Must not be ``None``;
+ :param integer `id`: window identifier. A value of -1 indicates a default value;
+ :param Bitmap `bitmap`: the button bitmap (if any);
+ :param string `label`: the button text label;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :type `pos`: tuple or :class:`Point`
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :type `size`: tuple or :class:`Size`
+ :param integer `style`: the button style (unused);
+ :param Validator `validator`: the validator associated to the button;
+ :param string `name`: the button name.
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name)
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnGainFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnLoseFocus)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self.Bind(wx.EVT_TIMER, self.OnPulseTimer)
+
+ if "__WXMSW__" in wx.PlatformInfo:
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
+
+ self._mouseAction = None
+ self.SetBitmapLabel(bitmap)
+ self._hasFocus = False
+ self._saveBitmap = True
+ self._storedBitmap = wx.NullBitmap
+ self._pulseOnFocus = False
+ self._gammaFactor = 1.0
+ self._gammaIncrement = 0.1
+
+ self._timer = wx.Timer(self, wx.ID_ANY)
+
+ self.SetLabel(label)
+ self.InheritAttributes()
+ self.SetInitialSize(size)
+
+ # The following defaults are better suited to draw the text outline
+ if "__WXMAC__" in wx.PlatformInfo:
+ self._backColour = wx.Colour(147, 202, 255)
+ self._hoverColour = self.LightColour(self._backColour, 30)
+ self._disableColour = self.LightColour(self._backColour, 70)
+ self._textColour = wx.BLACK
+ self._shadowColour = wx.NamedColour("grey")
+ self._rectColour = self.GetParent().GetBackgroundColour()
+ else:
+ self._backColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self._hoverColour = self.LightColour(self._backColour, 30)
+ self._disableColour = self.LightColour(self._backColour, 70)
+ self._textColour = wx.WHITE
+ self._shadowColour = wx.NamedColour("grey")
+ self._rectColour = self.GetParent().GetBackgroundColour()
+
+
+ def SetBitmapLabel(self, bitmap):
+ """
+ Sets the bitmap label for the button.
+
+ :param `bitmap`: the bitmap label to set, an instance of :class:`Bitmap`.
+ """
+
+ self._bitmap = bitmap
+ self.Refresh()
+
+
+ def LightColour(self, colour, percent):
+ """
+ Return light contrast of `colour`. The colour returned is from the scale of
+ `colour` ==> white.
+
+ :param `colour`: the input colour to be brightened, a valid instance of :class:`Colour`;
+ :param integer `percent`: determines how light the colour will be. `percent` = ``100``
+ returns white, `percent` = ``0`` returns `colour`.
+
+ :return: A light contrast of the input `colour`, an instance of :class:`Colour`.
+ """
+
+ end_colour = wx.WHITE
+ rd = end_colour.Red() - colour.Red()
+ gd = end_colour.Green() - colour.Green()
+ bd = end_colour.Blue() - colour.Blue()
+ high = 100
+
+ # We take the percent way of the colour from colour ==> white
+ i = percent
+ r = colour.Red() + ((i*rd*100)/high)/100
+ g = colour.Green() + ((i*gd*100)/high)/100
+ b = colour.Blue() + ((i*bd*100)/high)/100
+
+ return wx.Colour(r, g, b)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+ gc = wx.GraphicsContext.Create(dc)
+
+ xpos, ypos, width, height = self.GetClientRect()
+
+ dc.SetBackground(wx.Brush(self._rectColour))
+ dc.Clear()
+ gc.SetBrush(wx.WHITE_BRUSH)
+
+ shadowOffset = 5
+ btnOffset = 0
+ clr = self._backColour
+
+ if self._mouseAction == CLICK:
+ shadowOffset = 3
+ clr = self._hoverColour
+ btnOffset = 2
+
+ elif self._mouseAction == HOVER:
+ clr = self._hoverColour
+
+ elif not self.IsEnabled():
+ clr = self._disableColour
+
+ rc1 = wx.Rect(btnOffset, btnOffset, width-8-btnOffset, height-8-btnOffset)
+ path1 = self.GetPath(gc, rc1, 10)
+ br1 = gc.CreateLinearGradientBrush(0, 0, 0, rc1.height+6, clr, wx.WHITE)
+
+ # Create shadow
+ rc2 = wx.Rect(*rc1)
+ rc2.Offset((shadowOffset, shadowOffset))
+ path2 = self.GetPath(gc, rc2, 10)
+ br2 = gc.CreateRadialGradientBrush(rc2.x, rc2.y,
+ rc2.x+rc2.width, rc2.y+rc2.height,
+ rc2.width, self._shadowColour, wx.WHITE)
+
+ # Create top water colour to give "aqua" effect
+ rc3 = wx.Rect(*rc1)
+ rc3.Inflate(-5, -5)
+ rc3.height = 15
+ path3 = self.GetPath(gc, rc3, 10)
+
+ br3 = gc.CreateLinearGradientBrush(rc3.x, rc3.y, rc3.x, rc3.y+rc3.height,
+ wx.Colour(255, 255, 255, 255), wx.Colour(255, 255, 255, 0))
+
+ # draw shapes
+ gc.SetBrush(br2)
+ gc.FillPath(path2) #draw shadow
+ gc.SetBrush(br1)
+ gc.FillPath(path1) #draw main
+ gc.SetBrush(br3)
+ gc.FillPath(path3) #draw top bubble
+
+ font = gc.CreateFont(self.GetFont(), self._textColour)
+
+ gc.SetFont(font)
+ label = self.GetLabel()
+ tw, th = gc.GetTextExtent(label)
+
+ if self._bitmap:
+ bw, bh = self._bitmap.GetWidth(), self._bitmap.GetHeight()
+ else:
+ bw = bh = 0
+
+ pos_x = (width-bw-tw)/2+btnOffset-shadowOffset # adjust for bitmap and text to centre
+ if self._bitmap:
+ pos_y = (height-bh-shadowOffset)/2+btnOffset
+ gc.DrawBitmap(self._bitmap, pos_x, pos_y, bw, bh) # draw bitmap if available
+ pos_x = pos_x + 2 # extra spacing from bitmap
+
+ # Create a Path to draw the text
+ gc.DrawText(label, pos_x + bw + btnOffset, (height-th-shadowOffset)/2+btnOffset) # draw the text
+
+ if self._saveBitmap:
+ # Save the bitmap using wx.MemoryDC for later use
+ self._saveBitmap = False
+ memory = wx.MemoryDC()
+ self._storedBitmap = wx.EmptyBitmapRGBA(max(width, 1), max(height, 1))
+ memory.SelectObject(self._storedBitmap)
+
+ gcMemory = wx.GraphicsContext.Create(memory)
+
+ gcMemory.SetBrush(br1)
+ gcMemory.FillPath(path1) #draw main
+ gcMemory.SetBrush(br3)
+ gcMemory.FillPath(path3) #draw top bubble
+
+ if self._bitmap:
+ gcMemory.DrawBitmap(self._bitmap, pos_x - 2, pos_y, bw, bh)
+
+ gcMemory.SetFont(font)
+ gcMemory.DrawText(label, pos_x + bw + btnOffset, (height-th-shadowOffset)/2+btnOffset)
+
+ memory.SelectObject(wx.NullBitmap)
+ self._storedBitmap = self._storedBitmap.ConvertToImage()
+
+
+ def GetPath(self, gc, rc, r):
+ """
+ Returns a rounded :class:`GraphicsPath` rectangle.
+
+ :param `gc`: an instance of :class:`GraphicsContext`;
+ :param Rect `rc`: a client rectangle;
+ :param float `r`: the radius of the rounded part of the rectangle.
+
+ :return: A rounded rectangle, an instance of :class:`GraphicsPath`.
+ """
+
+ x, y, w, h = rc
+ path = gc.CreatePath()
+ path.AddRoundedRectangle(x, y, w, h, r)
+ path.CloseSubpath()
+ return path
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Invalidate()
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ self._mouseAction = CLICK
+ self.CaptureMouse()
+ self.Refresh()
+ event.Skip()
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled() or not self.HasCapture():
+ return
+
+ pos = event.GetPosition()
+ rect = self.GetClientRect()
+
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+ if rect.Contains(pos):
+ self._mouseAction = HOVER
+ self.Notify()
+ else:
+ self._mouseAction = None
+
+ self.Refresh()
+ event.Skip()
+
+
+ def OnMouseEnter(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ self._mouseAction = HOVER
+ self.Refresh()
+ event.Skip()
+
+
+ def OnMouseLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self._mouseAction = None
+ self.Refresh()
+ event.Skip()
+
+
+ def OnGainFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self._hasFocus = True
+ self.Refresh()
+ self.Update()
+
+ if self._pulseOnFocus:
+ self._gammaFactor = 1.0
+ self._timer.Start(100)
+
+
+ def OnLoseFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if self._pulseOnFocus:
+ self._gammaFactor = 1.0
+ self._timer.Stop()
+
+ self._hasFocus = False
+ self.Refresh()
+ self.Update()
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if self._hasFocus and event.GetKeyCode() == ord(" "):
+ self._mouseAction = HOVER
+ self.Refresh()
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if self._hasFocus and event.GetKeyCode() == ord(" "):
+ self._mouseAction = HOVER
+ self.Notify()
+ self.Refresh()
+ event.Skip()
+
+
+ def OnPulseTimer(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`AquaButton`.
+
+ :param `event`: a :class:`TimerEvent` event to be processed.
+
+ :note: This method is only invoked when `pulseOnFocus` is ``True``.
+ """
+
+ if not self._storedBitmap.IsOk():
+ self._timer.Stop()
+ return
+
+ xpos, ypos, width, height = self.GetClientRect()
+ gamma = self._gammaFactor
+
+ if gamma >= 1.3:
+ self._gammaIncrement = -self._gammaIncrement
+ elif gamma < 0.7:
+ self._gammaIncrement = abs(self._gammaIncrement)
+
+ self._gammaFactor += self._gammaIncrement
+
+ image = self._storedBitmap.AdjustChannels(gamma, gamma, gamma, 1.0)
+ dc = wx.ClientDC(self)
+ dc.SetClippingRect(wx.Rect(xpos, ypos, width-8, height-8))
+ dc.DrawBitmap(image.ConvertToBitmap(), xpos, ypos, True)
+
+
+ def SetInitialSize(self, size=None):
+ """
+ Given the current font and bezel width settings, calculate
+ and set a good size.
+
+ :param `size`: an instance of :class:`Size` or ``None``, in which case the wxWidgets
+ :class:`DefaultSize` is used instead.
+ """
+
+ if size is None:
+ size = wx.DefaultSize
+ wx.PyControl.SetInitialSize(self, size)
+
+ SetBestSize = SetInitialSize
+
+
+ def AcceptsFocus(self):
+ """
+ Can this window be given focus by mouse click?
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self.IsShown() and self.IsEnabled()
+
+
+ def GetDefaultAttributes(self):
+ """
+ Overridden base class virtual. By default we should use
+ the same font/colour attributes as the native :class:`Button`.
+
+ :return: an instance of :class:`VisualAttributes`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return wx.Button.GetClassDefaultAttributes()
+
+
+ def ShouldInheritColours(self):
+ """
+ Overridden base class virtual. Buttons usually don't inherit
+ the parent's colours.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return False
+
+
+ def Enable(self, enable=True):
+ """
+ Enables/disables the button.
+
+ :param bool `enable`: ``True`` to enable the button, ``False`` to disable it.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ wx.PyControl.Enable(self, enable)
+ self.Refresh()
+
+
+ def SetPulseOnFocus(self, pulse):
+ """
+ Sets whether to enable the pulsing effect on gaining focus or not.
+
+ :param bool `pulse`: ``True`` to enable pulsing when the :class:`AquaButton` gains focus,
+ ``False`` to disable this effect.
+ """
+
+ if pulse == self._pulseOnFocus:
+ return
+
+ self._pulseOnFocus = pulse
+ self.Invalidate()
+
+
+ def GetPulseOnFocus(self):
+ """
+ Returns whether the pulsing effect is active.
+
+ :return: ``True`` if the pulsing effect is active, ``False`` otherwise.
+ """
+
+ return self._pulseOnFocus
+
+
+ def DoGetBestSize(self):
+ """
+ Overridden base class virtual. Determines the best size of the
+ button based on the label and bezel size.
+
+ :return: An instance of :class:`Size`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ label = self.GetLabel()
+ if not label:
+ return wx.Size(112, 48)
+
+ dc = wx.ClientDC(self)
+ dc.SetFont(self.GetFont())
+ retWidth, retHeight = dc.GetTextExtent(label)
+
+ bmpWidth = bmpHeight = 0
+ constant = 24
+ if self._bitmap:
+ bmpWidth, bmpHeight = self._bitmap.GetWidth()+10, self._bitmap.GetHeight()
+ retWidth += bmpWidth
+ retHeight = max(bmpHeight, retHeight)
+ constant = 24
+
+ return wx.Size(retWidth+constant, retHeight+constant)
+
+
+ def SetBackgroundColour(self, colour):
+ """
+ Sets the :class:`AquaButton` background colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ wx.PyControl.SetBackgroundColour(self, colour)
+ self._backColour = colour
+ self.Invalidate()
+
+
+ def GetBackgroundColour(self):
+ """
+ Returns the button colour when the mouse is not hovering on the button.
+
+ :return: An instance of :class:`Colour`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._backColour
+
+
+ def SetHoverColour(self, colour):
+ """
+ Sets the button colour when the mouse is hovering on the button.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._hoverColour = colour
+ self.Invalidate()
+
+
+ def GetHoverColour(self):
+ """
+ Returns the button colour when the mouse is hovering on the button.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._hoverColour
+
+
+ def SetDisabledColour(self, colour):
+ """
+ Sets the button colour when it is disabled.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._disableColour = colour
+ self.Invalidate()
+
+
+ def GetDisabledColour(self):
+ """
+ Returns the button colour when it is disabled.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._disableColour
+
+
+ def SetShadowColour(self, colour):
+ """
+ Sets the button shadow colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+
+ .. versionadded:: 0.9.7
+ """
+
+ self._shadowColour = colour
+ self.Invalidate()
+
+
+ def GetShadowColour(self):
+ """
+ Returns the button shadow colour.
+
+ :return: An instance of :class:`Colour`.
+
+ .. versionadded:: 0.9.7
+ """
+
+ return self._shadowColour
+
+
+ def SetRectColour(self, colour):
+ """
+ Sets the button rectangular background colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+
+ .. versionadded:: 0.9.7
+ """
+
+ self._rectColour = colour
+ self.Invalidate()
+
+
+ def GetRectColour(self):
+ """
+ Returns the button rectangular background colour.
+
+ :return: An instance of :class:`Colour`.
+
+ .. versionadded:: 0.9.7
+ """
+
+ return self._rectColour
+
+ SetBackgroundColor = SetBackgroundColour
+ SetHoverColor = SetHoverColour
+ GetHoverColor = GetHoverColour
+ SetDisabledColor = SetDisabledColour
+ GetDisabledColor = GetDisabledColour
+ SetShadowColor = SetShadowColour
+ GetShadowColor = SetShadowColour
+ SetRectColor = SetRectColour
+ GetRectColor = SetRectColour
+
+
+ def SetForegroundColour(self, colour):
+ """
+ Sets the :class:`AquaButton` foreground (text) colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ wx.PyControl.SetForegroundColour(self, colour)
+ self._textColour = colour
+ self.Invalidate()
+
+
+ def GetForegroundColour(self):
+ """
+ Returns the text colour for :class:`AquaButton`.
+
+ :return: An instance of :class:`Colour`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._textColour
+
+
+ def Invalidate(self):
+ """ Invalidate the saved bitmap and refresh the button. """
+
+ self._saveBitmap = True
+ self._storedBitmap = wx.NullBitmap
+
+ self.Refresh()
+
+
+ def SetDefault(self):
+ """
+ This sets the :class:`AquaButton` to be the default item for the panel or dialog box.
+
+ :note: Under Windows, only dialog box buttons respond to this function. As normal
+ under Windows and Motif, pressing return causes the default button to be depressed
+ when the return key is pressed. See also :meth:`Window.SetFocus` which sets the
+ keyboard focus for windows and text panel items, and :meth:`TopLevelWindow.SetDefaultItem`.
+
+ :note: Note that under Motif, calling this function immediately after creation of a button
+ and before the creation of other buttons will cause misalignment of the row of buttons,
+ since default buttons are larger. To get around this, call :meth:`~aquabutton.AquaButton.SetDefault` after you
+ have created a row of buttons: wxPython will then set the size of all buttons currently
+ on the panel to the same size.
+ """
+
+ tlw = wx.GetTopLevelParent(self)
+ if hasattr(tlw, 'SetDefaultItem'):
+ tlw.SetDefaultItem(self)
+
+
+ def Notify(self):
+ """ Actually sends a ``wx.EVT_BUTTON`` event to the listener (if any). """
+
+ evt = AquaButtonEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
+ evt.SetButtonObj(self)
+ evt.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(evt)
+
+
+class __ToggleMixin(object):
+ """
+ A mixin that allows to transform :class:`AquaButton` in the corresponding toggle button.
+ """
+
+ def SetToggle(self, flag):
+ """
+ Sets the button as toggled/not toggled.
+
+ :param bool `flag`: ``True`` to set the button as toggled, ``False`` otherwise.
+ """
+
+ self.up = not flag
+ self.Refresh()
+
+ SetValue = SetToggle
+
+
+ def GetToggle(self):
+ """
+ Returns the toggled state of a button.
+
+ :return: ``True`` is the button is toggled, ``False`` if it is not toggled.
+ """
+
+ return not self.up
+
+ GetValue = GetToggle
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`AquaButton` when used as toggle button.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ self.saveUp = self.up
+ self.up = not self.up
+ self.CaptureMouse()
+ self.SetFocus()
+ self.Refresh()
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`AquaButton` when used as toggle button.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled() or not self.HasCapture():
+ return
+ if self.HasCapture():
+ self.ReleaseMouse()
+ self.Refresh()
+ if self.up != self.saveUp:
+ self.Notify()
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`AquaButton` when used as toggle button.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ event.Skip()
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`AquaButton` when used as toggle button.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ if event.LeftIsDown() and self.HasCapture():
+ x, y = event.GetPositionTuple()
+ w, h = self.GetClientSizeTuple()
+
+ if x < w and x >= 0 and y < h and y >= 0:
+ self.up = not self.saveUp
+ self.Refresh()
+ return
+
+ if x < 0 or y < 0 or x >= w or y >= h:
+ self.up = self.saveUp
+ self.Refresh()
+ return
+
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` event for :class:`AquaButton` when used as toggle button.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if self.hasFocus and event.GetKeyCode() == ord(" "):
+ self.up = not self.up
+ self.Notify()
+ self.Refresh()
+
+ event.Skip()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`AquaButton` when used as toggle button.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+ gc = wx.GraphicsContext.Create(dc)
+
+ xpos, ypos, width, height = self.GetClientRect()
+
+ dc.SetBackground(wx.Brush(self.GetParent().GetBackgroundColour()))
+ dc.Clear()
+ gc.SetBrush(wx.WHITE_BRUSH)
+
+ shadowOffset = 5
+ btnOffset = 0
+ clr = self._backColour
+
+ if not self.up:
+ shadowOffset = 3
+ clr = self._hoverColour
+ btnOffset = 2
+
+ if self._mouseAction == HOVER:
+ clr = self._hoverColour
+
+ rc1 = wx.Rect(btnOffset, btnOffset, width-8-btnOffset, height-8-btnOffset)
+ path1 = self.GetPath(gc, rc1, 10)
+ br1 = gc.CreateLinearGradientBrush(0, 0, 0, rc1.height+6, clr, wx.WHITE)
+
+ # Create shadow
+ rc2 = wx.Rect(*rc1)
+ rc2.Offset((shadowOffset, shadowOffset))
+ path2 = self.GetPath(gc, rc2, 10)
+ br2 = gc.CreateRadialGradientBrush(rc2.x, rc2.y,
+ rc2.x+rc2.width, rc2.y+rc2.height,
+ rc2.width, wx.NamedColour("grey"), wx.WHITE)
+
+ # Create top water colour to give "aqua" effect
+ rc3 = wx.Rect(*rc1)
+ rc3.Inflate(-5, -5)
+ rc3.height = 15
+ path3 = self.GetPath(gc, rc3, 10)
+
+ br3 = gc.CreateLinearGradientBrush(rc3.x, rc3.y, rc3.x, rc3.y+rc3.height,
+ wx.Colour(255, 255, 255, 255), wx.Colour(255, 255, 255, 0))
+
+ # draw shapes
+ gc.SetBrush(br2)
+ gc.FillPath(path2) #draw shadow
+ gc.SetBrush(br1)
+ gc.FillPath(path1) #draw main
+ gc.SetBrush(br3)
+ gc.FillPath(path3) #draw top bubble
+
+ font = gc.CreateFont(self.GetFont(), self._textColour)
+
+ gc.SetFont(font)
+ label = self.GetLabel()
+ tw, th = gc.GetTextExtent(label)
+
+ if self._bitmap:
+ bw, bh = self._bitmap.GetWidth(), self._bitmap.GetHeight()
+ else:
+ bw = bh = 0
+
+ pos_x = (width-bw-tw)/2+btnOffset-shadowOffset # adjust for bitmap and text to centre
+ if self._bitmap:
+ pos_y = (height-bh-shadowOffset)/2+btnOffset
+ gc.DrawBitmap(self._bitmap, pos_x, pos_y, bw, bh) # draw bitmap if available
+ pos_x = pos_x + 2 # extra spacing from bitmap
+
+ # Create a Path to draw the text
+ gc.DrawText(label, pos_x + bw + btnOffset, (height-th-shadowOffset)/2+btnOffset) # draw the text
+
+ if self._saveBitmap:
+ # Save the bitmap using wx.MemoryDC for later use
+ self._saveBitmap = False
+ memory = wx.MemoryDC()
+ self._storedBitmap = wx.EmptyBitmapRGBA(max(width, 1), max(height, 1))
+ memory.SelectObject(self._storedBitmap)
+
+ gcMemory = wx.GraphicsContext.Create(memory)
+
+ gcMemory.SetBrush(br1)
+ gcMemory.FillPath(path1) #draw main
+ gcMemory.SetBrush(br3)
+ gcMemory.FillPath(path3) #draw top bubble
+
+ if self._bitmap:
+ gcMemory.DrawBitmap(self._bitmap, pos_x - 2, pos_y, bw, bh)
+
+ gcMemory.SetFont(font)
+ gcMemory.DrawText(label, pos_x + bw + btnOffset, (height-th-shadowOffset)/2+btnOffset)
+
+ memory.SelectObject(wx.NullBitmap)
+ self._storedBitmap = self._storedBitmap.ConvertToImage()
+
+
+class AquaToggleButton(__ToggleMixin, AquaButton):
+ """ An :class:`AquaButton` toggle button. """
+ pass
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/artmanager.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/artmanager.py
new file mode 100644
index 0000000..aa38b7f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/artmanager.py
@@ -0,0 +1,2111 @@
+"""
+This module contains drawing routines and customizations for the AGW widgets
+:class:`~lib.agw.labelbook.LabelBook` and :class:`~lib.agw.flatmenu.FlatMenu`.
+"""
+
+import wx
+import cStringIO
+import random
+
+from fmresources import *
+
+# ---------------------------------------------------------------------------- #
+# Class DCSaver
+# ---------------------------------------------------------------------------- #
+
+_ = wx.GetTranslation
+
+_libimported = None
+
+if wx.Platform == "__WXMSW__":
+ osVersion = wx.GetOsVersion()
+ # Shadows behind menus are supported only in XP
+ if osVersion[1] == 5 and osVersion[2] == 1:
+ try:
+ import win32api
+ import win32con
+ import winxpgui
+ _libimported = "MH"
+ except:
+ try:
+ import ctypes
+ _libimported = "ctypes"
+ except:
+ pass
+ else:
+ _libimported = None
+
+
+class DCSaver(object):
+ """
+ Construct a DC saver. The dc is copied as-is.
+ """
+
+ def __init__(self, pdc):
+ """
+ Default class constructor.
+
+ :param `pdc`: an instance of :class:`DC`.
+ """
+
+ self._pdc = pdc
+ self._pen = pdc.GetPen()
+ self._brush = pdc.GetBrush()
+
+
+ def __del__(self):
+ """ While destructing, restores the dc pen and brush. """
+
+ if self._pdc:
+ self._pdc.SetPen(self._pen)
+ self._pdc.SetBrush(self._brush)
+
+
+# ---------------------------------------------------------------------------- #
+# Class RendererBase
+# ---------------------------------------------------------------------------- #
+
+class RendererBase(object):
+ """ Base class for all theme renderers. """
+
+ def __init__(self):
+ """ Default class constructor. Intentionally empty. """
+
+ pass
+
+
+ def DrawButtonBorders(self, dc, rect, penColour, brushColour):
+ """
+ Draws borders for buttons.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the button's client rectangle;
+ :param `penColour`: a valid :class:`Colour` for the pen border;
+ :param `brushColour`: a valid :class:`Colour` for the brush.
+ """
+
+ # Keep old pen and brush
+ dcsaver = DCSaver(dc)
+ dc.SetPen(wx.Pen(penColour))
+ dc.SetBrush(wx.Brush(brushColour))
+ dc.DrawRectangleRect(rect)
+
+
+ def DrawBitmapArea(self, dc, xpm_name, rect, baseColour, flipSide):
+ """
+ Draws the area below a bitmap and the bitmap itself using a gradient shading.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param string `xpm_name`: a name of a XPM bitmap;
+ :param Rect `rect`: the bitmap client rectangle;
+ :param `baseColour`: a valid :class:`Colour` for the bitmap background;
+ :param bool `flipSide`: ``True`` to flip the gradient direction, ``False`` otherwise.
+ """
+
+ # draw the gradient area
+ if not flipSide:
+ ArtManager.Get().PaintDiagonalGradientBox(dc, rect, wx.WHITE,
+ ArtManager.Get().LightColour(baseColour, 20),
+ True, False)
+ else:
+ ArtManager.Get().PaintDiagonalGradientBox(dc, rect, ArtManager.Get().LightColour(baseColour, 20),
+ wx.WHITE, True, False)
+
+ # draw arrow
+ arrowDown = wx.BitmapFromXPMData(xpm_name)
+ arrowDown.SetMask(wx.Mask(arrowDown, wx.WHITE))
+ dc.DrawBitmap(arrowDown, rect.x + 1 , rect.y + 1, True)
+
+
+ def DrawBitmapBorders(self, dc, rect, penColour, bitmapBorderUpperLeftPen):
+ """
+ Draws borders for a bitmap.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the button's client rectangle;
+ :param `penColour`: a valid :class:`Colour` for the pen border;
+ :param `bitmapBorderUpperLeftPen`: a valid :class:`Colour` for the pen upper
+ left border.
+ """
+
+ # Keep old pen and brush
+ dcsaver = DCSaver(dc)
+
+ # lower right size
+ dc.SetPen(wx.Pen(penColour))
+ dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1)
+ dc.DrawLine(rect.x + rect.width - 1, rect.y, rect.x + rect.width - 1, rect.y + rect.height)
+
+ # upper left side
+ dc.SetPen(wx.Pen(bitmapBorderUpperLeftPen))
+ dc.DrawLine(rect.x, rect.y, rect.x + rect.width, rect.y)
+ dc.DrawLine(rect.x, rect.y, rect.x, rect.y + rect.height)
+
+
+ def GetMenuFaceColour(self):
+ """
+ Returns the foreground colour for the menu.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return ArtManager.Get().LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 80)
+
+
+ def GetTextColourEnable(self):
+ """
+ Returns the colour used for text colour when enabled.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return wx.BLACK
+
+
+ def GetTextColourDisable(self):
+ """
+ Returns the colour used for text colour when disabled.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return ArtManager.Get().LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT), 30)
+
+
+ def GetFont(self):
+ """
+ Returns the font used for text.
+
+ :return: An instance of :class:`Font`.
+ """
+
+ return wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+
+# ---------------------------------------------------------------------------- #
+# Class RendererXP
+# ---------------------------------------------------------------------------- #
+
+class RendererXP(RendererBase):
+ """ Xp-Style renderer. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ RendererBase.__init__(self)
+
+
+ def DrawButton(self, dc, rect, state, input=None):
+ """
+ Draws a button using the XP theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the button's client rectangle;
+ :param integer `state`: the button state;
+ :param `input`: a flag used to call the right method.
+ """
+
+ if input is None or type(input) == type(False):
+ self.DrawButtonTheme(dc, rect, state, input)
+ else:
+ self.DrawButtonColour(dc, rect, state, input)
+
+
+ def DrawButtonTheme(self, dc, rect, state, useLightColours=None):
+ """
+ Draws a button using the XP theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the button's client rectangle;
+ :param integer `state`: the button state;
+ :param bool `useLightColours`: ``True`` to use light colours, ``False`` otherwise.
+ """
+
+ # switch according to the status
+ if state == ControlFocus:
+ penColour = ArtManager.Get().FrameColour()
+ brushColour = ArtManager.Get().BackgroundColour()
+ elif state == ControlPressed:
+ penColour = ArtManager.Get().FrameColour()
+ brushColour = ArtManager.Get().HighlightBackgroundColour()
+ else:
+ penColour = ArtManager.Get().FrameColour()
+ brushColour = ArtManager.Get().BackgroundColour()
+
+ # Draw the button borders
+ self.DrawButtonBorders(dc, rect, penColour, brushColour)
+
+
+ def DrawButtonColour(self, dc, rect, state, colour):
+ """
+ Draws a button using the XP theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the button's client rectangle;
+ :param integer `state`: the button state;
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ # switch according to the status
+ if statet == ControlFocus:
+ penColour = colour
+ brushColour = ArtManager.Get().LightColour(colour, 75)
+ elif state == ControlPressed:
+ penColour = colour
+ brushColour = ArtManager.Get().LightColour(colour, 60)
+ else:
+ penColour = colour
+ brushColour = ArtManager.Get().LightColour(colour, 75)
+
+ # Draw the button borders
+ self.DrawButtonBorders(dc, rect, penColour, brushColour)
+
+
+ def DrawMenuBarBg(self, dc, rect):
+ """
+ Draws the menu bar background according to the active theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the menu bar's client rectangle.
+ """
+
+ # For office style, we simple draw a rectangle with a gradient colouring
+ artMgr = ArtManager.Get()
+ vertical = artMgr.GetMBVerticalGradient()
+
+ dcsaver = DCSaver(dc)
+
+ # fill with gradient
+ startColour = artMgr.GetMenuBarFaceColour()
+ if artMgr.IsDark(startColour):
+ startColour = artMgr.LightColour(startColour, 50)
+
+ endColour = artMgr.LightColour(startColour, 90)
+ artMgr.PaintStraightGradientBox(dc, rect, startColour, endColour, vertical)
+
+ # Draw the border
+ if artMgr.GetMenuBarBorder():
+
+ dc.SetPen(wx.Pen(startColour))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangleRect(rect)
+
+
+ def DrawToolBarBg(self, dc, rect):
+ """
+ Draws the toolbar background according to the active theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the toolbar's client rectangle.
+ """
+
+ artMgr = ArtManager.Get()
+
+ if not artMgr.GetRaiseToolbar():
+ return
+
+ # For office style, we simple draw a rectangle with a gradient colouring
+ vertical = artMgr.GetMBVerticalGradient()
+
+ dcsaver = DCSaver(dc)
+
+ # fill with gradient
+ startColour = artMgr.GetMenuBarFaceColour()
+ if artMgr.IsDark(startColour):
+ startColour = artMgr.LightColour(startColour, 50)
+
+ startColour = artMgr.LightColour(startColour, 20)
+
+ endColour = artMgr.LightColour(startColour, 90)
+ artMgr.PaintStraightGradientBox(dc, rect, startColour, endColour, vertical)
+ artMgr.DrawBitmapShadow(dc, rect)
+
+
+ def GetTextColourEnable(self):
+ """
+ Returns the colour used for text colour when enabled.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return wx.BLACK
+
+
+# ---------------------------------------------------------------------------- #
+# Class RendererMSOffice2007
+# ---------------------------------------------------------------------------- #
+
+class RendererMSOffice2007(RendererBase):
+ """ Windows MS Office 2007 style. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ RendererBase.__init__(self)
+
+
+ def GetColoursAccordingToState(self, state):
+ """
+ Returns a :class:`Colour` according to the menu item state.
+
+ :param integer `state`: one of the following bits:
+
+ ==================== ======= ==========================
+ Item State Value Description
+ ==================== ======= ==========================
+ ``ControlPressed`` 0 The item is pressed
+ ``ControlFocus`` 1 The item is focused
+ ``ControlDisabled`` 2 The item is disabled
+ ``ControlNormal`` 3 Normal state
+ ==================== ======= ==========================
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ # switch according to the status
+ if state == ControlFocus:
+ upperBoxTopPercent = 95
+ upperBoxBottomPercent = 50
+ lowerBoxTopPercent = 40
+ lowerBoxBottomPercent = 90
+ concaveUpperBox = True
+ concaveLowerBox = True
+
+ elif state == ControlPressed:
+ upperBoxTopPercent = 75
+ upperBoxBottomPercent = 90
+ lowerBoxTopPercent = 90
+ lowerBoxBottomPercent = 40
+ concaveUpperBox = True
+ concaveLowerBox = True
+
+ elif state == ControlDisabled:
+ upperBoxTopPercent = 100
+ upperBoxBottomPercent = 100
+ lowerBoxTopPercent = 70
+ lowerBoxBottomPercent = 70
+ concaveUpperBox = True
+ concaveLowerBox = True
+
+ else:
+ upperBoxTopPercent = 90
+ upperBoxBottomPercent = 50
+ lowerBoxTopPercent = 30
+ lowerBoxBottomPercent = 75
+ concaveUpperBox = True
+ concaveLowerBox = True
+
+ return upperBoxTopPercent, upperBoxBottomPercent, lowerBoxTopPercent, lowerBoxBottomPercent, \
+ concaveUpperBox, concaveLowerBox
+
+
+ def DrawButton(self, dc, rect, state, useLightColours):
+ """
+ Draws a button using the MS Office 2007 theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the button's client rectangle;
+ :param integer `state`: the button state;
+ :param bool `useLightColours`: ``True`` to use light colours, ``False`` otherwise.
+ """
+
+ self.DrawButtonColour(dc, rect, state, ArtManager.Get().GetThemeBaseColour(useLightColours))
+
+
+ def DrawButtonColour(self, dc, rect, state, colour):
+ """
+ Draws a button using the MS Office 2007 theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the button's client rectangle;
+ :param integer `state`: the button state;
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ artMgr = ArtManager.Get()
+
+ # Keep old pen and brush
+ dcsaver = DCSaver(dc)
+
+ # Define the rounded rectangle base on the given rect
+ # we need an array of 9 points for it
+ baseColour = colour
+
+ # Define the middle points
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 2))
+ rightPt = wx.Point(rect.x + rect.width-1, rect.y + (rect.height / 2))
+
+ # Define the top region
+ top = wx.RectPP((rect.GetLeft(), rect.GetTop()), rightPt)
+ bottom = wx.RectPP(leftPt, (rect.GetRight(), rect.GetBottom()))
+
+ upperBoxTopPercent, upperBoxBottomPercent, lowerBoxTopPercent, lowerBoxBottomPercent, \
+ concaveUpperBox, concaveLowerBox = self.GetColoursAccordingToState(state)
+
+ topStartColour = artMgr.LightColour(baseColour, upperBoxTopPercent)
+ topEndColour = artMgr.LightColour(baseColour, upperBoxBottomPercent)
+ bottomStartColour = artMgr.LightColour(baseColour, lowerBoxTopPercent)
+ bottomEndColour = artMgr.LightColour(baseColour, lowerBoxBottomPercent)
+
+ artMgr.PaintStraightGradientBox(dc, top, topStartColour, topEndColour)
+ artMgr.PaintStraightGradientBox(dc, bottom, bottomStartColour, bottomEndColour)
+
+ rr = wx.Rect(rect.x, rect.y, rect.width, rect.height)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ frameColour = artMgr.LightColour(baseColour, 60)
+ dc.SetPen(wx.Pen(frameColour))
+ dc.DrawRectangleRect(rr)
+
+ wc = artMgr.LightColour(baseColour, 80)
+ dc.SetPen(wx.Pen(wc))
+ rr.Deflate(1, 1)
+ dc.DrawRectangleRect(rr)
+
+
+ def DrawMenuBarBg(self, dc, rect):
+ """
+ Draws the menu bar background according to the active theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the menu bar's client rectangle.
+ """
+
+ # Keep old pen and brush
+ dcsaver = DCSaver(dc)
+ artMgr = ArtManager.Get()
+ baseColour = artMgr.GetMenuBarFaceColour()
+
+ dc.SetBrush(wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.DrawRectangleRect(rect)
+
+ # Define the rounded rectangle base on the given rect
+ # we need an array of 9 points for it
+ regPts = [wx.Point() for ii in xrange(9)]
+ radius = 2
+
+ regPts[0] = wx.Point(rect.x, rect.y + radius)
+ regPts[1] = wx.Point(rect.x+radius, rect.y)
+ regPts[2] = wx.Point(rect.x+rect.width-radius-1, rect.y)
+ regPts[3] = wx.Point(rect.x+rect.width-1, rect.y + radius)
+ regPts[4] = wx.Point(rect.x+rect.width-1, rect.y + rect.height - radius - 1)
+ regPts[5] = wx.Point(rect.x+rect.width-radius-1, rect.y + rect.height-1)
+ regPts[6] = wx.Point(rect.x+radius, rect.y + rect.height-1)
+ regPts[7] = wx.Point(rect.x, rect.y + rect.height - radius - 1)
+ regPts[8] = regPts[0]
+
+ # Define the middle points
+
+ factor = artMgr.GetMenuBgFactor()
+
+ leftPt1 = wx.Point(rect.x, rect.y + (rect.height / factor))
+ leftPt2 = wx.Point(rect.x, rect.y + (rect.height / factor)*(factor-1))
+
+ rightPt1 = wx.Point(rect.x + rect.width, rect.y + (rect.height / factor))
+ rightPt2 = wx.Point(rect.x + rect.width, rect.y + (rect.height / factor)*(factor-1))
+
+ # Define the top region
+ topReg = [wx.Point() for ii in xrange(7)]
+ topReg[0] = regPts[0]
+ topReg[1] = regPts[1]
+ topReg[2] = wx.Point(regPts[2].x+1, regPts[2].y)
+ topReg[3] = wx.Point(regPts[3].x + 1, regPts[3].y)
+ topReg[4] = wx.Point(rightPt1.x, rightPt1.y+1)
+ topReg[5] = wx.Point(leftPt1.x, leftPt1.y+1)
+ topReg[6] = topReg[0]
+
+ # Define the middle region
+ middle = wx.RectPP(leftPt1, wx.Point(rightPt2.x - 2, rightPt2.y))
+
+ # Define the bottom region
+ bottom = wx.RectPP(leftPt2, wx.Point(rect.GetRight() - 1, rect.GetBottom()))
+
+ topStartColour = artMgr.LightColour(baseColour, 90)
+ topEndColour = artMgr.LightColour(baseColour, 60)
+ bottomStartColour = artMgr.LightColour(baseColour, 40)
+ bottomEndColour = artMgr.LightColour(baseColour, 20)
+
+ topRegion = wx.RegionFromPoints(topReg)
+
+ artMgr.PaintGradientRegion(dc, topRegion, topStartColour, topEndColour)
+ artMgr.PaintStraightGradientBox(dc, bottom, bottomStartColour, bottomEndColour)
+ artMgr.PaintStraightGradientBox(dc, middle, topEndColour, bottomStartColour)
+
+
+ def DrawToolBarBg(self, dc, rect):
+ """
+ Draws the toolbar background according to the active theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the toolbar's client rectangle.
+ """
+
+ artMgr = ArtManager.Get()
+
+ if not artMgr.GetRaiseToolbar():
+ return
+
+ # Keep old pen and brush
+ dcsaver = DCSaver(dc)
+
+ baseColour = artMgr.GetMenuBarFaceColour()
+ baseColour = artMgr.LightColour(baseColour, 20)
+
+ dc.SetBrush(wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.DrawRectangleRect(rect)
+
+ radius = 2
+
+ # Define the rounded rectangle base on the given rect
+ # we need an array of 9 points for it
+ regPts = [None]*9
+
+ regPts[0] = wx.Point(rect.x, rect.y + radius)
+ regPts[1] = wx.Point(rect.x+radius, rect.y)
+ regPts[2] = wx.Point(rect.x+rect.width-radius-1, rect.y)
+ regPts[3] = wx.Point(rect.x+rect.width-1, rect.y + radius)
+ regPts[4] = wx.Point(rect.x+rect.width-1, rect.y + rect.height - radius - 1)
+ regPts[5] = wx.Point(rect.x+rect.width-radius-1, rect.y + rect.height-1)
+ regPts[6] = wx.Point(rect.x+radius, rect.y + rect.height-1)
+ regPts[7] = wx.Point(rect.x, rect.y + rect.height - radius - 1)
+ regPts[8] = regPts[0]
+
+ # Define the middle points
+ factor = artMgr.GetMenuBgFactor()
+
+ leftPt1 = wx.Point(rect.x, rect.y + (rect.height / factor))
+ rightPt1 = wx.Point(rect.x + rect.width, rect.y + (rect.height / factor))
+
+ leftPt2 = wx.Point(rect.x, rect.y + (rect.height / factor)*(factor-1))
+ rightPt2 = wx.Point(rect.x + rect.width, rect.y + (rect.height / factor)*(factor-1))
+
+ # Define the top region
+ topReg = [None]*7
+ topReg[0] = regPts[0]
+ topReg[1] = regPts[1]
+ topReg[2] = wx.Point(regPts[2].x+1, regPts[2].y)
+ topReg[3] = wx.Point(regPts[3].x + 1, regPts[3].y)
+ topReg[4] = wx.Point(rightPt1.x, rightPt1.y+1)
+ topReg[5] = wx.Point(leftPt1.x, leftPt1.y+1)
+ topReg[6] = topReg[0]
+
+ # Define the middle region
+ middle = wx.RectPP(leftPt1, wx.Point(rightPt2.x - 2, rightPt2.y))
+
+ # Define the bottom region
+ bottom = wx.RectPP(leftPt2, wx.Point(rect.GetRight() - 1, rect.GetBottom()))
+
+ topStartColour = artMgr.LightColour(baseColour, 90)
+ topEndColour = artMgr.LightColour(baseColour, 60)
+ bottomStartColour = artMgr.LightColour(baseColour, 40)
+ bottomEndColour = artMgr.LightColour(baseColour, 20)
+
+ topRegion = wx.RegionFromPoints(topReg)
+
+ artMgr.PaintGradientRegion(dc, topRegion, topStartColour, topEndColour)
+ artMgr.PaintStraightGradientBox(dc, bottom, bottomStartColour, bottomEndColour)
+ artMgr.PaintStraightGradientBox(dc, middle, topEndColour, bottomStartColour)
+
+ artMgr.DrawBitmapShadow(dc, rect)
+
+
+ def GetTextColourEnable(self):
+ """
+ Returns the colour used for text colour when enabled.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return wx.NamedColour("MIDNIGHT BLUE")
+
+
+# ---------------------------------------------------------------------------- #
+# Class ArtManager
+# ---------------------------------------------------------------------------- #
+
+class ArtManager(wx.EvtHandler):
+
+ """
+ This class provides various art utilities, such as creating shadow, providing
+ lighter / darker colours for a given colour, etc...
+ """
+
+ _alignmentBuffer = 7
+ _menuTheme = StyleXP
+ _verticalGradient = False
+ _renderers = {StyleXP: None, Style2007: None}
+ _bmpShadowEnabled = False
+ _ms2007sunken = False
+ _drowMBBorder = True
+ _menuBgFactor = 5
+ _menuBarColourScheme = _("Default")
+ _raiseTB = True
+ _bitmaps = {}
+ _transparency = 255
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ wx.EvtHandler.__init__(self)
+ self._menuBarBgColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+
+ # connect an event handler to the system colour change event
+ self.Bind(wx.EVT_SYS_COLOUR_CHANGED, self.OnSysColourChange)
+
+
+ def SetTransparency(self, amount):
+ """
+ Sets the alpha channel value for transparent windows.
+
+ :param integer `amount`: the actual transparency value (between 0 and 255).
+
+ :raise: `Exception` if the `amount` parameter is lower than ``0`` or greater than ``255``.
+ """
+
+ if self._transparency == amount:
+ return
+
+ if amount < 0 or amount > 255:
+ raise Exception("Invalid transparency value")
+
+ self._transparency = amount
+
+
+ def GetTransparency(self):
+ """
+ Returns the alpha channel value for transparent windows.
+
+ :return: An integer representing the alpha channel value.
+ """
+
+ return self._transparency
+
+
+ def ConvertToBitmap(self, xpm, alpha=None):
+ """
+ Convert the given image to a bitmap, optionally overlaying an alpha
+ channel to it.
+
+ :param `xpm`: a list of strings formatted as XPM;
+ :type `xpm`: list of strings
+ :param `alpha`: a list of alpha values, the same size as the xpm bitmap.
+ :type `alpha`: list of integers
+
+ :return: An instance of :class:`Bitmap`.
+ """
+
+ if alpha is not None:
+
+ img = wx.BitmapFromXPMData(xpm)
+ img = img.ConvertToImage()
+ x, y = img.GetWidth(), img.GetHeight()
+ img.InitAlpha()
+ for jj in xrange(y):
+ for ii in xrange(x):
+ img.SetAlpha(ii, jj, alpha[jj*x+ii])
+
+ else:
+
+ stream = cStringIO.StringIO(xpm)
+ img = wx.ImageFromStream(stream)
+
+ return wx.BitmapFromImage(img)
+
+
+ def Initialize(self):
+ """ Initializes the bitmaps and colours. """
+
+ # create wxBitmaps from the xpm's
+ self._rightBottomCorner = self.ConvertToBitmap(shadow_center_xpm, shadow_center_alpha)
+ self._bottom = self.ConvertToBitmap(shadow_bottom_xpm, shadow_bottom_alpha)
+ self._bottomLeft = self.ConvertToBitmap(shadow_bottom_left_xpm, shadow_bottom_left_alpha)
+ self._rightTop = self.ConvertToBitmap(shadow_right_top_xpm, shadow_right_top_alpha)
+ self._right = self.ConvertToBitmap(shadow_right_xpm, shadow_right_alpha)
+
+ # initialise the colour map
+ self.InitColours()
+ self.SetMenuBarColour(self._menuBarColourScheme)
+
+ # Create common bitmaps
+ self.FillStockBitmaps()
+
+
+ def FillStockBitmaps(self):
+ """ Initializes few standard bitmaps. """
+
+ bmp = self.ConvertToBitmap(arrow_down, alpha=None)
+ bmp.SetMask(wx.Mask(bmp, wx.Colour(0, 128, 128)))
+ self._bitmaps.update({"arrow_down": bmp})
+
+ bmp = self.ConvertToBitmap(arrow_up, alpha=None)
+ bmp.SetMask(wx.Mask(bmp, wx.Colour(0, 128, 128)))
+ self._bitmaps.update({"arrow_up": bmp})
+
+
+ def GetStockBitmap(self, name):
+ """
+ Returns a bitmap from a stock.
+
+ :param string `name`: the bitmap name.
+
+ :return: The stock bitmap, if `name` was found in the stock bitmap dictionary.
+ Othewise, :class:`NullBitmap` is returned.
+ """
+
+ if self._bitmaps.has_key(name):
+ return self._bitmaps[name]
+
+ return wx.NullBitmap
+
+
+ def Get(self):
+ """
+ Accessor to the unique art manager object.
+
+ :return: A unique instance of :class:`ArtManager`.
+ """
+
+ if not hasattr(self, "_instance"):
+
+ self._instance = ArtManager()
+ self._instance.Initialize()
+
+ # Initialize the renderers map
+ self._renderers[StyleXP] = RendererXP()
+ self._renderers[Style2007] = RendererMSOffice2007()
+
+ return self._instance
+
+ Get = classmethod(Get)
+
+ def Free(self):
+ """ Destructor for the unique art manager object. """
+
+ if hasattr(self, "_instance"):
+
+ del self._instance
+
+ Free = classmethod(Free)
+
+
+ def OnSysColourChange(self, event):
+ """
+ Handles the ``wx.EVT_SYS_COLOUR_CHANGED`` event for :class:`ArtManager`.
+
+ :param `event`: a :class:`SysColourChangedEvent` event to be processed.
+ """
+
+ # reinitialise the colour map
+ self.InitColours()
+
+
+ def LightColour(self, colour, percent):
+ """
+ Return light contrast of `colour`. The colour returned is from the scale of
+ `colour` ==> white.
+
+ :param `colour`: the input colour to be brightened, an instance of :class:`Colour`;
+ :param integer `percent`: determines how light the colour will be. `percent` = ``100``
+ returns white, `percent` = ``0`` returns `colour`.
+
+ :return: A light contrast of the input `colour`, an instance of :class:`Colour`.
+ """
+
+ end_colour = wx.WHITE
+ rd = end_colour.Red() - colour.Red()
+ gd = end_colour.Green() - colour.Green()
+ bd = end_colour.Blue() - colour.Blue()
+ high = 100
+
+ # We take the percent way of the colour from colour -. white
+ i = percent
+ r = colour.Red() + ((i*rd*100)/high)/100
+ g = colour.Green() + ((i*gd*100)/high)/100
+ b = colour.Blue() + ((i*bd*100)/high)/100
+
+ return wx.Colour(r, g, b)
+
+
+ def DarkColour(self, colour, percent):
+ """
+ Like the :meth:`~ArtManager.LightColour` function, but create the colour darker by `percent`.
+
+ :param `colour`: the input colour to be darkened, an instance of :class:`Colour`;
+ :param integer `percent`: determines how dark the colour will be. `percent` = ``100``
+ returns black, `percent` = ``0`` returns `colour`.
+
+ :return: A dark contrast of the input `colour`, an instance of :class:`Colour`.
+ """
+
+ end_colour = wx.BLACK
+ rd = end_colour.Red() - colour.Red()
+ gd = end_colour.Green() - colour.Green()
+ bd = end_colour.Blue() - colour.Blue()
+ high = 100
+
+ # We take the percent way of the colour from colour -. white
+ i = percent
+ r = colour.Red() + ((i*rd*100)/high)/100
+ g = colour.Green() + ((i*gd*100)/high)/100
+ b = colour.Blue() + ((i*bd*100)/high)/100
+
+ return wx.Colour(r, g, b)
+
+
+ def PaintStraightGradientBox(self, dc, rect, startColour, endColour, vertical=True):
+ """
+ Paint the rectangle with gradient colouring; the gradient lines are either
+ horizontal or vertical.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the rectangle to be filled with gradient shading;
+ :param Colour `startColour`: the first colour of the gradient shading;
+ :param Colour `endColour`: the second colour of the gradient shading;
+ :param bool `vertical`: ``True`` for gradient colouring in the vertical direction,
+ ``False`` for horizontal shading.
+ """
+
+ dcsaver = DCSaver(dc)
+
+ if vertical:
+ high = rect.GetHeight()-1
+ direction = wx.SOUTH
+ else:
+ high = rect.GetWidth()-1
+ direction = wx.EAST
+
+ if high < 1:
+ return
+
+ dc.GradientFillLinear(rect, startColour, endColour, direction)
+
+
+ def PaintGradientRegion(self, dc, region, startColour, endColour, vertical=True):
+ """
+ Paint a region with gradient colouring.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `region`: a region to be filled with gradient shading (an instance of
+ :class:`Region`);
+ :param Colour `startColour`: the first colour of the gradient shading;
+ :param Colour `endColour`: the second colour of the gradient shading;
+ :param bool `vertical`: ``True`` for gradient colouring in the vertical direction,
+ ``False`` for horizontal shading.
+
+ """
+
+ # The way to achieve non-rectangle
+ memDC = wx.MemoryDC()
+ rect = region.GetBox()
+ bitmap = wx.EmptyBitmap(rect.width, rect.height)
+ memDC.SelectObject(bitmap)
+
+ # Colour the whole rectangle with gradient
+ rr = wx.Rect(0, 0, rect.width, rect.height)
+ self.PaintStraightGradientBox(memDC, rr, startColour, endColour, vertical)
+
+ # Convert the region to a black and white bitmap with the white pixels being inside the region
+ # we draw the bitmap over the gradient coloured rectangle, with mask set to white,
+ # this will cause our region to be coloured with the gradient, while area outside the
+ # region will be painted with black. then we simply draw the bitmap to the dc with mask set to
+ # black
+ tmpRegion = wx.Region(rect.x, rect.y, rect.width, rect.height)
+ tmpRegion.Offset(-rect.x, -rect.y)
+ regionBmp = tmpRegion.ConvertToBitmap()
+ regionBmp.SetMask(wx.Mask(regionBmp, wx.WHITE))
+
+ # The function ConvertToBitmap() return a rectangle bitmap
+ # which is shorter by 1 pixl on the height and width (this is correct behavior, since
+ # DrawLine does not include the second point as part of the line)
+ # we fix this issue by drawing our own line at the bottom and left side of the rectangle
+ memDC.SetPen(wx.BLACK_PEN)
+ memDC.DrawBitmap(regionBmp, 0, 0, True)
+ memDC.DrawLine(0, rr.height - 1, rr.width, rr.height - 1)
+ memDC.DrawLine(rr.width - 1, 0, rr.width - 1, rr.height)
+
+ memDC.SelectObject(wx.NullBitmap)
+ bitmap.SetMask(wx.Mask(bitmap, wx.BLACK))
+ dc.DrawBitmap(bitmap, rect.x, rect.y, True)
+
+
+ def PaintDiagonalGradientBox(self, dc, rect, startColour, endColour,
+ startAtUpperLeft=True, trimToSquare=True):
+ """
+ Paint rectangle with gradient colouring; the gradient lines are diagonal
+ and may start from the upper left corner or from the upper right corner.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the rectangle to be filled with gradient shading;
+ :param Colour `startColour`: the first colour of the gradient shading;
+ :param Colour `endColour`: the second colour of the gradient shading;
+ :param bool `startAtUpperLeft`: ``True`` to start the gradient lines at the upper
+ left corner of the rectangle, ``False`` to start at the upper right corner;
+ :param bool `trimToSquare`: ``True`` to trim the gradient lines in a square.
+ """
+
+ # Save the current pen and brush
+ savedPen = dc.GetPen()
+ savedBrush = dc.GetBrush()
+
+ # gradient fill from colour 1 to colour 2 with top to bottom
+ if rect.height < 1 or rect.width < 1:
+ return
+
+ # calculate some basic numbers
+ size = rect.width
+ sizeX = sizeY = 0
+ proportion = 1
+
+ if rect.width > rect.height:
+
+ if trimToSquare:
+
+ size = rect.height
+ sizeX = sizeY = rect.height - 1
+
+ else:
+
+ proportion = float(rect.height)/float(rect.width)
+ size = rect.width
+ sizeX = rect.width - 1
+ sizeY = rect.height -1
+
+ else:
+
+ if trimToSquare:
+
+ size = rect.width
+ sizeX = sizeY = rect.width - 1
+
+ else:
+
+ sizeX = rect.width - 1
+ size = rect.height
+ sizeY = rect.height - 1
+ proportion = float(rect.width)/float(rect.height)
+
+ # calculate gradient coefficients
+ col2 = endColour
+ col1 = startColour
+
+ rf, gf, bf = 0, 0, 0
+ rstep = float(col2.Red() - col1.Red())/float(size)
+ gstep = float(col2.Green() - col1.Green())/float(size)
+ bstep = float(col2.Blue() - col1.Blue())/float(size)
+
+ # draw the upper triangle
+ for i in xrange(size):
+
+ currCol = wx.Colour(col1.Red() + rf, col1.Green() + gf, col1.Blue() + bf)
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.SetPen(wx.Pen(currCol))
+
+ if startAtUpperLeft:
+
+ if rect.width > rect.height:
+
+ dc.DrawLine(rect.x + i, rect.y, rect.x, int(rect.y + proportion*i))
+ dc.DrawPoint(rect.x, int(rect.y + proportion*i))
+
+ else:
+
+ dc.DrawLine(int(rect.x + proportion*i), rect.y, rect.x, rect.y + i)
+ dc.DrawPoint(rect.x, rect.y + i)
+
+ else:
+
+ if rect.width > rect.height:
+
+ dc.DrawLine(rect.x + sizeX - i, rect.y, rect.x + sizeX, int(rect.y + proportion*i))
+ dc.DrawPoint(rect.x + sizeX, int(rect.y + proportion*i))
+
+ else:
+
+ xTo = (int(rect.x + sizeX - proportion * i) > rect.x and [int(rect.x + sizeX - proportion*i)] or [rect.x])[0]
+ dc.DrawLine(xTo, rect.y, rect.x + sizeX, rect.y + i)
+ dc.DrawPoint(rect.x + sizeX, rect.y + i)
+
+ rf += rstep/2
+ gf += gstep/2
+ bf += bstep/2
+
+ # draw the lower triangle
+ for i in xrange(size):
+
+ currCol = wx.Colour(col1.Red() + rf, col1.Green() + gf, col1.Blue() + bf)
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.SetPen(wx.Pen(currCol))
+
+ if startAtUpperLeft:
+
+ if rect.width > rect.height:
+
+ dc.DrawLine(rect.x + i, rect.y + sizeY, rect.x + sizeX, int(rect.y + proportion * i))
+ dc.DrawPoint(rect.x + sizeX, int(rect.y + proportion * i))
+
+ else:
+
+ dc.DrawLine(int(rect.x + proportion * i), rect.y + sizeY, rect.x + sizeX, rect.y + i)
+ dc.DrawPoint(rect.x + sizeX, rect.y + i)
+
+ else:
+
+ if rect.width > rect.height:
+
+ dc.DrawLine(rect.x, (int)(rect.y + proportion * i), rect.x + sizeX - i, rect.y + sizeY)
+ dc.DrawPoint(rect.x + sizeX - i, rect.y + sizeY)
+
+ else:
+
+ xTo = (int(rect.x + sizeX - proportion*i) > rect.x and [int(rect.x + sizeX - proportion*i)] or [rect.x])[0]
+ dc.DrawLine(rect.x, rect.y + i, xTo, rect.y + sizeY)
+ dc.DrawPoint(xTo, rect.y + sizeY)
+
+ rf += rstep/2
+ gf += gstep/2
+ bf += bstep/2
+
+
+ # Restore the pen and brush
+ dc.SetPen( savedPen )
+ dc.SetBrush( savedBrush )
+
+
+ def PaintCrescentGradientBox(self, dc, rect, startColour, endColour, concave=True):
+ """
+ Paint a region with gradient colouring. The gradient is in crescent shape
+ which fits the 2007 style.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the rectangle to be filled with gradient shading;
+ :param Colour `startColour`: the first colour of the gradient shading;
+ :param Colour `endColour`: the second colour of the gradient shading;
+ :param bool `concave`: ``True`` for a concave effect, ``False`` for a convex one.
+ """
+
+ diagonalRectWidth = rect.GetWidth()/4
+ spare = rect.width - 4*diagonalRectWidth
+ leftRect = wx.Rect(rect.x, rect.y, diagonalRectWidth, rect.GetHeight())
+ rightRect = wx.Rect(rect.x + 3 * diagonalRectWidth + spare, rect.y, diagonalRectWidth, rect.GetHeight())
+
+ if concave:
+
+ self.PaintStraightGradientBox(dc, rect, self.MixColours(startColour, endColour, 50), endColour)
+ self.PaintDiagonalGradientBox(dc, leftRect, startColour, endColour, True, False)
+ self.PaintDiagonalGradientBox(dc, rightRect, startColour, endColour, False, False)
+
+ else:
+
+ self.PaintStraightGradientBox(dc, rect, endColour, self.MixColours(endColour, startColour, 50))
+ self.PaintDiagonalGradientBox(dc, leftRect, endColour, startColour, False, False)
+ self.PaintDiagonalGradientBox(dc, rightRect, endColour, startColour, True, False)
+
+
+ def FrameColour(self):
+ """
+ Return the surrounding colour for a control.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+
+
+ def BackgroundColour(self):
+ """
+ Returns the background colour of a control when not in focus.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self.LightColour(self.FrameColour(), 75)
+
+
+ def HighlightBackgroundColour(self):
+ """
+ Returns the background colour of a control when it is in focus.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self.LightColour(self.FrameColour(), 60)
+
+
+ def MixColours(self, firstColour, secondColour, percent):
+ """
+ Return mix of input colours.
+
+ :param `firstColour`: the first colour to be mixed, an instance of :class:`Colour`;
+ :param `secondColour`: the second colour to be mixed, an instance of :class:`Colour`;
+ :param integer `percent`: the relative percentage of `firstColour` with respect to
+ `secondColour`.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ # calculate gradient coefficients
+ redOffset = float((secondColour.Red() * (100 - percent) / 100) - (firstColour.Red() * percent / 100))
+ greenOffset = float((secondColour.Green() * (100 - percent) / 100) - (firstColour.Green() * percent / 100))
+ blueOffset = float((secondColour.Blue() * (100 - percent) / 100) - (firstColour.Blue() * percent / 100))
+
+ return wx.Colour(firstColour.Red() + redOffset, firstColour.Green() + greenOffset,
+ firstColour.Blue() + blueOffset)
+
+
+ def RandomColour():
+ """
+ Creates a random colour.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ r = random.randint(0, 255) # Random value betweem 0-255
+ g = random.randint(0, 255) # Random value betweem 0-255
+ b = random.randint(0, 255) # Random value betweem 0-255
+
+ return wx.Colour(r, g, b)
+
+
+ def IsDark(self, colour):
+ """
+ Returns whether a colour is dark or light.
+
+ :param `colour`: an instance of :class:`Colour`.
+
+ :return: ``True`` if the average RGB values are dark, ``False`` otherwise.
+ """
+
+ evg = (colour.Red() + colour.Green() + colour.Blue())/3
+
+ if evg < 127:
+ return True
+
+ return False
+
+
+ def TruncateText(self, dc, text, maxWidth):
+ """
+ Truncates a given string to fit given width size. if the text does not fit
+ into the given width it is truncated to fit. the format of the fixed text
+ is <truncate text ...>.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param string `text`: the text to be (eventually) truncated;
+ :param integer `maxWidth`: the maximum width allowed for the text.
+
+ :return: A new string containining the (possibly) truncated text.
+ """
+
+ textLen = len(text)
+ tempText = text
+ rectSize = maxWidth
+
+ fixedText = ""
+
+ textW, textH = dc.GetTextExtent(text)
+
+ if rectSize >= textW:
+ return text
+
+ # The text does not fit in the designated area,
+ # so we need to truncate it a bit
+ suffix = ".."
+ w, h = dc.GetTextExtent(suffix)
+ rectSize -= w
+
+ for i in xrange(textLen, -1, -1):
+
+ textW, textH = dc.GetTextExtent(tempText)
+ if rectSize >= textW:
+ fixedText = tempText
+ fixedText += ".."
+ return fixedText
+
+ tempText = tempText[:-1]
+
+
+ def DrawButton(self, dc, rect, theme, state, input=None):
+ """
+ Colour rectangle according to the theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the rectangle to be filled with gradient shading;
+ :param string `theme`: the theme to use to draw the button;
+ :param integer `state`: the button state;
+ :param `input`: a flag used to call the right method.
+ """
+
+ if input is None or type(input) == type(False):
+ self.DrawButtonTheme(dc, rect, theme, state, input)
+ else:
+ self.DrawButtonColour(dc, rect, theme, state, input)
+
+
+ def DrawButtonTheme(self, dc, rect, theme, state, useLightColours=True):
+ """
+ Draws a button using the appropriate theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the button's client rectangle;
+ :param string `theme`: the theme to use to draw the button;
+ :param integer `state`: the button state;
+ :param bool `useLightColours`: ``True`` to use light colours, ``False`` otherwise.
+ """
+
+ renderer = self._renderers[theme]
+
+ # Set background colour if non given by caller
+ renderer.DrawButton(dc, rect, state, useLightColours)
+
+
+ def DrawButtonColour(self, dc, rect, theme, state, colour):
+ """
+ Draws a button using the appropriate theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the button's client rectangle;
+ :param string `theme`: the theme to use to draw the button;
+ :param integer `state`: the button state;
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ renderer = self._renderers[theme]
+ renderer.DrawButton(dc, rect, state, colour)
+
+
+ def CanMakeWindowsTransparent(self):
+ """
+ Used internally.
+
+ :return: ``True`` if the system supports transparency of toplevel windows,
+ otherwise returns ``False``.
+ """
+
+ if wx.Platform == "__WXMSW__":
+
+ version = wx.GetOsDescription()
+ found = version.find("XP") >= 0 or version.find("2000") >= 0 or version.find("NT") >= 0
+ return found
+
+ elif wx.Platform == "__WXMAC__":
+ return True
+ else:
+ return False
+
+
+ # on supported windows systems (Win2000 and greater), this function
+ # will make a frame window transparent by a certain amount
+ def MakeWindowTransparent(self, wnd, amount):
+ """
+ Used internally. Makes a toplevel window transparent if the system supports it.
+
+ :param `wnd`: the toplevel window to make transparent, an instance of :class:`TopLevelWindow`;
+ :param integer `amount`: the window transparency to apply.
+ """
+
+ if wnd.GetSize() == (0, 0):
+ return
+
+ # this API call is not in all SDKs, only the newer ones, so
+ # we will runtime bind this
+ if wx.Platform == "__WXMSW__":
+ hwnd = wnd.GetHandle()
+
+ if not hasattr(self, "_winlib"):
+ if _libimported == "MH":
+ self._winlib = win32api.LoadLibrary("user32")
+ elif _libimported == "ctypes":
+ self._winlib = ctypes.windll.user32
+
+ if _libimported == "MH":
+ pSetLayeredWindowAttributes = win32api.GetProcAddress(self._winlib,
+ "SetLayeredWindowAttributes")
+
+ if pSetLayeredWindowAttributes == None:
+ return
+
+ exstyle = win32api.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
+ if 0 == (exstyle & 0x80000):
+ win32api.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, exstyle | 0x80000)
+
+ winxpgui.SetLayeredWindowAttributes(hwnd, 0, amount, 2)
+
+ elif _libimported == "ctypes":
+ style = self._winlib.GetWindowLongA(hwnd, 0xffffffecL)
+ style |= 0x00080000
+ self._winlib.SetWindowLongA(hwnd, 0xffffffecL, style)
+ self._winlib.SetLayeredWindowAttributes(hwnd, 0, amount, 2)
+ else:
+ if not wnd.CanSetTransparent():
+ return
+ wnd.SetTransparent(amount)
+ return
+
+
+ # assumption: the background was already drawn on the dc
+ def DrawBitmapShadow(self, dc, rect, where=BottomShadow|RightShadow):
+ """
+ Draws a shadow using background bitmap.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the bitmap's client rectangle;
+ :param integer `where`: where to draw the shadow. This can be any combination of the
+ following bits:
+
+ ========================== ======= ================================
+ Shadow Settings Value Description
+ ========================== ======= ================================
+ ``RightShadow`` 1 Right side shadow
+ ``BottomShadow`` 2 Not full bottom shadow
+ ``BottomShadowFull`` 4 Full bottom shadow
+ ========================== ======= ================================
+
+ """
+
+ shadowSize = 5
+
+ # the rect must be at least 5x5 pixles
+ if rect.height < 2*shadowSize or rect.width < 2*shadowSize:
+ return
+
+ # Start by drawing the right bottom corner
+ if where & BottomShadow or where & BottomShadowFull:
+ dc.DrawBitmap(self._rightBottomCorner, rect.x+rect.width, rect.y+rect.height, True)
+
+ # Draw right side shadow
+ xx = rect.x + rect.width
+ yy = rect.y + rect.height - shadowSize
+
+ if where & RightShadow:
+ while yy - rect.y > 2*shadowSize:
+ dc.DrawBitmap(self._right, xx, yy, True)
+ yy -= shadowSize
+
+ dc.DrawBitmap(self._rightTop, xx, yy - shadowSize, True)
+
+ if where & BottomShadow:
+ xx = rect.x + rect.width - shadowSize
+ yy = rect.height + rect.y
+ while xx - rect.x > 2*shadowSize:
+ dc.DrawBitmap(self._bottom, xx, yy, True)
+ xx -= shadowSize
+
+ dc.DrawBitmap(self._bottomLeft, xx - shadowSize, yy, True)
+
+ if where & BottomShadowFull:
+ xx = rect.x + rect.width - shadowSize
+ yy = rect.height + rect.y
+ while xx - rect.x >= 0:
+ dc.DrawBitmap(self._bottom, xx, yy, True)
+ xx -= shadowSize
+
+ dc.DrawBitmap(self._bottom, xx, yy, True)
+
+
+ def DropShadow(self, wnd, drop=True):
+ """
+ Adds a shadow under the window (Windows only).
+
+ :param `wnd`: the window for which we are dropping a shadow, an instance of :class:`TopLevelWindow`;
+ :param bool `drop`: ``True`` to drop a shadow, ``False`` to remove it.
+ """
+
+ if not self.CanMakeWindowsTransparent() or not _libimported:
+ return
+
+ if "__WXMSW__" in wx.Platform:
+
+ hwnd = wnd.GetHandle()
+
+ if not hasattr(self, "_winlib"):
+ if _libimported == "MH":
+ self._winlib = win32api.LoadLibrary("user32")
+ elif _libimported == "ctypes":
+ self._winlib = ctypes.windll.user32
+
+ if _libimported == "MH":
+ csstyle = win32api.GetWindowLong(hwnd, win32con.GCL_STYLE)
+ else:
+ csstyle = self._winlib.GetWindowLongA(hwnd, win32con.GCL_STYLE)
+
+ if drop:
+ if csstyle & CS_DROPSHADOW:
+ return
+ else:
+ csstyle |= CS_DROPSHADOW #Nothing to be done
+
+ else:
+
+ if csstyle & CS_DROPSHADOW:
+ csstyle &= ~(CS_DROPSHADOW)
+ else:
+ return #Nothing to be done
+
+ win32api.SetWindowLong(hwnd, win32con.GCL_STYLE, csstyle)
+
+
+ def GetBitmapStartLocation(self, dc, rect, bitmap, text="", style=0):
+ """
+ Returns the top left `x` and `y` cordinates of the bitmap drawing.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the bitmap's client rectangle;
+ :param Bitmap `bitmap`: the bitmap associated with the button;
+ :param string `text`: the button label;
+ :param integer `style`: the button style. This can be one of the following bits:
+
+ ============================== ======= ================================
+ Button style Value Description
+ ============================== ======= ================================
+ ``BU_EXT_XP_STYLE`` 1 A button with a XP style
+ ``BU_EXT_2007_STYLE`` 2 A button with a MS Office 2007 style
+ ``BU_EXT_LEFT_ALIGN_STYLE`` 4 A left-aligned button
+ ``BU_EXT_CENTER_ALIGN_STYLE`` 8 A center-aligned button
+ ``BU_EXT_RIGHT_ALIGN_STYLE`` 16 A right-aligned button
+ ``BU_EXT_RIGHT_TO_LEFT_STYLE`` 32 A button suitable for right-to-left languages
+ ============================== ======= ================================
+
+ :return: A tuple containining the top left `x` and `y` cordinates of the bitmap drawing.
+ """
+
+ alignmentBuffer = self.GetAlignBuffer()
+
+ # get the startLocationY
+ fixedTextWidth = fixedTextHeight = 0
+
+ if not text:
+ fixedTextHeight = bitmap.GetHeight()
+ else:
+ fixedTextWidth, fixedTextHeight = dc.GetTextExtent(text)
+
+ startLocationY = rect.y + (rect.height - fixedTextHeight)/2
+
+ # get the startLocationX
+ if style & BU_EXT_RIGHT_TO_LEFT_STYLE:
+
+ startLocationX = rect.x + rect.width - alignmentBuffer - bitmap.GetWidth()
+
+ else:
+
+ if style & BU_EXT_RIGHT_ALIGN_STYLE:
+
+ maxWidth = rect.x + rect.width - (2 * alignmentBuffer) - bitmap.GetWidth() # the alignment is for both sides
+
+ # get the truncated text. The text may stay as is, it is not a must that is will be trancated
+ fixedText = self.TruncateText(dc, text, maxWidth)
+
+ # get the fixed text dimentions
+ fixedTextWidth, fixedTextHeight = dc.GetTextExtent(fixedText)
+
+ # calculate the start location
+ startLocationX = maxWidth - fixedTextWidth
+
+ elif style & BU_EXT_LEFT_ALIGN_STYLE:
+
+ # calculate the start location
+ startLocationX = alignmentBuffer
+
+ else: # meaning BU_EXT_CENTER_ALIGN_STYLE
+
+ maxWidth = rect.x + rect.width - (2 * alignmentBuffer) - bitmap.GetWidth() # the alignment is for both sides
+
+ # get the truncated text. The text may stay as is, it is not a must that is will be trancated
+ fixedText = self.TruncateText(dc, text, maxWidth)
+
+ # get the fixed text dimentions
+ fixedTextWidth, fixedTextHeight = dc.GetTextExtent(fixedText)
+
+ if maxWidth > fixedTextWidth:
+
+ # calculate the start location
+ startLocationX = (maxWidth - fixedTextWidth) / 2
+
+ else:
+
+ # calculate the start location
+ startLocationX = maxWidth - fixedTextWidth
+
+ # it is very important to validate that the start location is not less than the alignment buffer
+ if startLocationX < alignmentBuffer:
+ startLocationX = alignmentBuffer
+
+ return startLocationX, startLocationY
+
+
+ def GetTextStartLocation(self, dc, rect, bitmap, text, style=0):
+ """
+ Returns the top left `x` and `y` cordinates of the text drawing.
+ In case the text is too long, the text is being fixed (the text is cut and
+ a '...' mark is added in the end).
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the text's client rectangle;
+ :param Bitmap `bitmap`: the bitmap associated with the button;
+ :param string `text`: the button label;
+ :param integer `style`: the button style.
+
+ :return: A tuple containining the top left `x` and `y` cordinates of the text drawing, plus
+ the truncated version of the input `text`.
+
+ :see: :meth:`~ArtManager.GetBitmapStartLocation` for a list of valid button styles.
+ """
+
+ alignmentBuffer = self.GetAlignBuffer()
+
+ # get the bitmap offset
+ bitmapOffset = 0
+ if bitmap != wx.NullBitmap:
+ bitmapOffset = bitmap.GetWidth()
+
+ # get the truncated text. The text may stay as is, it is not a must that is will be trancated
+ maxWidth = rect.x + rect.width - (2 * alignmentBuffer) - bitmapOffset # the alignment is for both sides
+
+ fixedText = self.TruncateText(dc, text, maxWidth)
+
+ # get the fixed text dimentions
+ fixedTextWidth, fixedTextHeight = dc.GetTextExtent(fixedText)
+ startLocationY = (rect.height - fixedTextHeight) / 2 + rect.y
+
+ # get the startLocationX
+ if style & BU_EXT_RIGHT_TO_LEFT_STYLE:
+
+ startLocationX = maxWidth - fixedTextWidth + alignmentBuffer
+
+ else:
+
+ if style & BU_EXT_LEFT_ALIGN_STYLE:
+
+ # calculate the start location
+ startLocationX = bitmapOffset + alignmentBuffer
+
+ elif style & BU_EXT_RIGHT_ALIGN_STYLE:
+
+ # calculate the start location
+ startLocationX = maxWidth - fixedTextWidth + bitmapOffset + alignmentBuffer
+
+ else: # meaning wxBU_EXT_CENTER_ALIGN_STYLE
+
+ # calculate the start location
+ startLocationX = (maxWidth - fixedTextWidth) / 2 + bitmapOffset + alignmentBuffer
+
+
+ # it is very important to validate that the start location is not less than the alignment buffer
+ if startLocationX < alignmentBuffer:
+ startLocationX = alignmentBuffer
+
+ return startLocationX, startLocationY, fixedText
+
+
+ def DrawTextAndBitmap(self, dc, rect, text, enable=True, font=wx.NullFont,
+ fontColour=wx.BLACK, bitmap=wx.NullBitmap,
+ grayBitmap=wx.NullBitmap, style=0):
+ """
+ Draws the text & bitmap on the input dc.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the text and bitmap client rectangle;
+ :param string `text`: the button label;
+ :param bool `enable`: ``True`` if the button is enabled, ``False`` otherwise;
+ :param `font`: the font to use to draw the text, an instance of :class:`Font`;
+ :param `fontColour`: the colour to use to draw the text, an instance of
+ :class:`Colour`;
+ :param `bitmap`: the bitmap associated with the button, an instance of :class:`Bitmap`;
+ :param `grayBitmap`: a greyed-out version of the input `bitmap` representing
+ a disabled bitmap, an instance of :class:`Bitmap`;
+ :param integer `style`: the button style.
+
+ :see: :meth:`~ArtManager.GetBitmapStartLocation` for a list of valid button styles.
+ """
+
+ # enable colours
+ if enable:
+ dc.SetTextForeground(fontColour)
+ else:
+ dc.SetTextForeground(wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT))
+
+ # set the font
+
+ if font == wx.NullFont:
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+ dc.SetFont(font)
+
+ startLocationX = startLocationY = 0
+
+ if bitmap != wx.NullBitmap:
+
+ # calculate the bitmap start location
+ startLocationX, startLocationY = self.GetBitmapStartLocation(dc, rect, bitmap, text, style)
+
+ # draw the bitmap
+ if enable:
+ dc.DrawBitmap(bitmap, startLocationX, startLocationY, True)
+ else:
+ dc.DrawBitmap(grayBitmap, startLocationX, startLocationY, True)
+
+ # calculate the text start location
+ location, labelOnly = self.GetAccelIndex(text)
+ startLocationX, startLocationY, fixedText = self.GetTextStartLocation(dc, rect, bitmap, labelOnly, style)
+
+ # after all the caculations are finished, it is time to draw the text
+ # underline the first letter that is marked with a '&'
+ if location == -1 or font.GetUnderlined() or location >= len(fixedText):
+ # draw the text
+ dc.DrawText(fixedText, startLocationX, startLocationY)
+
+ else:
+
+ # underline the first '&'
+ before = fixedText[0:location]
+ underlineLetter = fixedText[location]
+ after = fixedText[location+1:]
+
+ # before
+ dc.DrawText(before, startLocationX, startLocationY)
+
+ # underlineLetter
+ if "__WXGTK__" not in wx.Platform:
+ w1, h = dc.GetTextExtent(before)
+ font.SetUnderlined(True)
+ dc.SetFont(font)
+ dc.DrawText(underlineLetter, startLocationX + w1, startLocationY)
+ else:
+ w1, h = dc.GetTextExtent(before)
+ dc.DrawText(underlineLetter, startLocationX + w1, startLocationY)
+
+ # Draw the underline ourselves since using the Underline in GTK,
+ # causes the line to be too close to the letter
+ uderlineLetterW, uderlineLetterH = dc.GetTextExtent(underlineLetter)
+
+ curPen = dc.GetPen()
+ dc.SetPen(wx.BLACK_PEN)
+
+ dc.DrawLine(startLocationX + w1, startLocationY + uderlineLetterH - 2,
+ startLocationX + w1 + uderlineLetterW, startLocationY + uderlineLetterH - 2)
+ dc.SetPen(curPen)
+
+ # after
+ w2, h = dc.GetTextExtent(underlineLetter)
+ font.SetUnderlined(False)
+ dc.SetFont(font)
+ dc.DrawText(after, startLocationX + w1 + w2, startLocationY)
+
+
+ def CalcButtonBestSize(self, label, bmp):
+ """
+ Returns the best fit size for the supplied label & bitmap.
+
+ :param string `label`: the button label;
+ :param `bmp`: the bitmap associated with the button, an instance of :class:`Bitmap`.
+
+ :return: An instance of :class:`Size`, representing the best fit size for the supplied label & bitmap.
+ """
+
+ if "__WXMSW__" in wx.Platform:
+ HEIGHT = 22
+ else:
+ HEIGHT = 26
+
+ dc = wx.MemoryDC()
+ dc.SelectBitmap(wx.EmptyBitmap(1, 1))
+
+ dc.SetFont(wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT))
+ width, height, dummy = dc.GetMultiLineTextExtent(label)
+
+ width += 2*self.GetAlignBuffer()
+
+ if bmp.Ok():
+
+ # allocate extra space for the bitmap
+ heightBmp = bmp.GetHeight() + 2
+ if height < heightBmp:
+ height = heightBmp
+
+ width += bmp.GetWidth() + 2
+
+ if height < HEIGHT:
+ height = HEIGHT
+
+ dc.SelectBitmap(wx.NullBitmap)
+
+ return wx.Size(width, height)
+
+
+ def GetMenuFaceColour(self):
+ """
+ Returns the colour used for the menu foreground.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ renderer = self._renderers[self.GetMenuTheme()]
+ return renderer.GetMenuFaceColour()
+
+
+ def GetTextColourEnable(self):
+ """
+ Returns the colour used for enabled menu items.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ renderer = self._renderers[self.GetMenuTheme()]
+ return renderer.GetTextColourEnable()
+
+
+ def GetTextColourDisable(self):
+ """
+ Returns the colour used for disabled menu items.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ renderer = self._renderers[self.GetMenuTheme()]
+ return renderer.GetTextColourDisable()
+
+
+ def GetFont(self):
+ """
+ Returns the font used by this theme.
+
+ :return: An instance of :class:`Font`.
+ """
+
+ renderer = self._renderers[self.GetMenuTheme()]
+ return renderer.GetFont()
+
+
+ def GetAccelIndex(self, label):
+ """
+ Returns the mnemonic index of the label and the label stripped of the ampersand mnemonic
+ (e.g. 'lab&el' ==> will result in 3 and labelOnly = label).
+
+ :param string `label`: a string containining an ampersand.
+
+ :return: A tuple containining the mnemonic index of the label and the label
+ stripped of the ampersand mnemonic.
+ """
+
+ indexAccel = 0
+ while True:
+ indexAccel = label.find("&", indexAccel)
+ if indexAccel == -1:
+ return indexAccel, label
+ if label[indexAccel:indexAccel+2] == "&&":
+ label = label[0:indexAccel] + label[indexAccel+1:]
+ indexAccel += 1
+ else:
+ break
+
+ labelOnly = label[0:indexAccel] + label[indexAccel+1:]
+
+ return indexAccel, labelOnly
+
+
+ def GetThemeBaseColour(self, useLightColours=True):
+ """
+ Returns the theme (Blue, Silver, Green etc.) base colour, if no theme is active
+ it return the active caption colour, lighter in 30%.
+
+ :param bool `useLightColours`: ``True`` to use light colours, ``False`` otherwise.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ if not useLightColours and not self.IsDark(self.FrameColour()):
+ return wx.NamedColour("GOLD")
+ else:
+ return self.LightColour(self.FrameColour(), 30)
+
+
+ def GetAlignBuffer(self):
+ """
+ Return the padding buffer for a text or bitmap.
+
+ :return: An integer representing the padding buffer.
+ """
+
+ return self._alignmentBuffer
+
+
+ def SetMenuTheme(self, theme):
+ """
+ Set the menu theme, possible values (Style2007, StyleXP, StyleVista).
+
+ :param string `theme`: a rendering theme class, either `StyleXP`, `Style2007` or `StyleVista`.
+ """
+
+ self._menuTheme = theme
+
+
+ def GetMenuTheme(self):
+ """
+ Returns the currently used menu theme.
+
+ :return: A string containining the currently used theme for the menu.
+ """
+
+ return self._menuTheme
+
+
+ def AddMenuTheme(self, render):
+ """
+ Adds a new theme to the stock.
+
+ :param `render`: a rendering theme class, which must be derived from
+ :class:`RendererBase`.
+
+ :return: An integer representing the size of the renderers dictionary.
+ """
+
+ # Add new theme
+ lastRenderer = len(self._renderers)
+ self._renderers[lastRenderer] = render
+
+ return lastRenderer
+
+
+ def SetMS2007ButtonSunken(self, sunken):
+ """
+ Sets MS 2007 button style sunken or not.
+
+ :param bool `sunken`: ``True`` to have a sunken border effect, ``False`` otherwise.
+ """
+
+ self._ms2007sunken = sunken
+
+
+ def GetMS2007ButtonSunken(self):
+ """
+ Returns the sunken flag for MS 2007 buttons.
+
+ :return: ``True`` if the MS 2007 buttons are sunken, ``False`` otherwise.
+ """
+
+ return self._ms2007sunken
+
+
+ def GetMBVerticalGradient(self):
+ """ Returns ``True`` if the menu bar should be painted with vertical gradient. """
+
+ return self._verticalGradient
+
+
+ def SetMBVerticalGradient(self, v):
+ """
+ Sets the menu bar gradient style.
+
+ :param bool `v`: ``True`` for a vertical shaded gradient, ``False`` otherwise.
+ """
+
+ self._verticalGradient = v
+
+
+ def DrawMenuBarBorder(self, border):
+ """
+ Enables menu border drawing (XP style only).
+
+ :param bool `border`: ``True`` to draw the menubar border, ``False`` otherwise.
+ """
+
+ self._drowMBBorder = border
+
+
+ def GetMenuBarBorder(self):
+ """
+ Returns menu bar border drawing flag.
+
+ :return: ``True`` if the menu bar border is to be drawn, ``False`` otherwise.
+ """
+
+ return self._drowMBBorder
+
+
+ def GetMenuBgFactor(self):
+ """
+ Gets the visibility depth of the menu in Metallic style.
+ The higher the value, the menu bar will look more raised
+ """
+
+ return self._menuBgFactor
+
+
+ def DrawDragSash(self, rect):
+ """
+ Draws resize sash.
+
+ :param Rect `rect`: the sash client rectangle.
+ """
+
+ dc = wx.ScreenDC()
+ mem_dc = wx.MemoryDC()
+
+ bmp = wx.EmptyBitmap(rect.width, rect.height)
+ mem_dc.SelectObject(bmp)
+ mem_dc.SetBrush(wx.WHITE_BRUSH)
+ mem_dc.SetPen(wx.Pen(wx.WHITE, 1))
+ mem_dc.DrawRectangle(0, 0, rect.width, rect.height)
+
+ dc.Blit(rect.x, rect.y, rect.width, rect.height, mem_dc, 0, 0, wx.XOR)
+
+
+ def TakeScreenShot(self, rect, bmp):
+ """
+ Takes a screenshot of the screen at given position & size (rect).
+
+ :param Rect `rect`: the screen rectangle we wish to capture;
+ :param Bitmap `bmp`: currently unused.
+ """
+
+ # Create a DC for the whole screen area
+ dcScreen = wx.ScreenDC()
+
+ # Create a Bitmap that will later on hold the screenshot image
+ # Note that the Bitmap must have a size big enough to hold the screenshot
+ # -1 means using the current default colour depth
+ bmp = wx.EmptyBitmap(rect.width, rect.height)
+
+ # Create a memory DC that will be used for actually taking the screenshot
+ memDC = wx.MemoryDC()
+
+ # Tell the memory DC to use our Bitmap
+ # all drawing action on the memory DC will go to the Bitmap now
+ memDC.SelectObject(bmp)
+
+ # Blit (in this case copy) the actual screen on the memory DC
+ # and thus the Bitmap
+ memDC.Blit( 0, # Copy to this X coordinate
+ 0, # Copy to this Y coordinate
+ rect.width, # Copy this width
+ rect.height, # Copy this height
+ dcScreen, # From where do we copy?
+ rect.x, # What's the X offset in the original DC?
+ rect.y # What's the Y offset in the original DC?
+ )
+
+ # Select the Bitmap out of the memory DC by selecting a new
+ # uninitialized Bitmap
+ memDC.SelectObject(wx.NullBitmap)
+
+
+ def DrawToolBarBg(self, dc, rect):
+ """
+ Draws the toolbar background according to the active theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the toolbar's client rectangle.
+ """
+
+ renderer = self._renderers[self.GetMenuTheme()]
+
+ # Set background colour if non given by caller
+ renderer.DrawToolBarBg(dc, rect)
+
+
+ def DrawMenuBarBg(self, dc, rect):
+ """
+ Draws the menu bar background according to the active theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the menubar's client rectangle.
+ """
+
+ renderer = self._renderers[self.GetMenuTheme()]
+ # Set background colour if non given by caller
+ renderer.DrawMenuBarBg(dc, rect)
+
+
+ def SetMenuBarColour(self, scheme):
+ """
+ Sets the menu bar colour scheme to use.
+
+ :param string `scheme`: a string representing a colour scheme (i.e., 'Default',
+ 'Dark', 'Dark Olive Green', 'Generic').
+ """
+
+ self._menuBarColourScheme = scheme
+ # set default colour
+ if scheme in self._colourSchemeMap.keys():
+ self._menuBarBgColour = self._colourSchemeMap[scheme]
+
+
+ def GetMenuBarColourScheme(self):
+ """
+ Returns the current colour scheme.
+
+ :return: A string representing the current colour scheme.
+ """
+
+ return self._menuBarColourScheme
+
+
+ def GetMenuBarFaceColour(self):
+ """
+ Returns the menu bar face colour.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._menuBarBgColour
+
+
+ def GetMenuBarSelectionColour(self):
+ """
+ Returns the menu bar selection colour.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._menuBarSelColour
+
+
+ def InitColours(self):
+ """ Initialise the colour map. """
+
+ self._colourSchemeMap = {_("Default"): wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE),
+ _("Dark"): wx.BLACK,
+ _("Dark Olive Green"): wx.NamedColour("DARK OLIVE GREEN"),
+ _("Generic"): wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)}
+
+
+ def GetColourSchemes(self):
+ """
+ Returns the available colour schemes.
+
+ :return: A list of strings representing the available colour schemes.
+ """
+
+ return self._colourSchemeMap.keys()
+
+
+ def CreateGreyBitmap(self, bmp):
+ """
+ Creates a grey bitmap image from the input bitmap.
+
+ :param `bmp`: a valid :class:`Bitmap` object to be greyed out.
+
+ :return: A greyed-out representation of the input bitmap, an instance of :class:`Bitmap`.
+ """
+
+ img = bmp.ConvertToImage()
+ return wx.BitmapFromImage(img.ConvertToGreyscale())
+
+
+ def GetRaiseToolbar(self):
+ """ Returns ``True`` if we are dropping a shadow under a toolbar. """
+
+ return self._raiseTB
+
+
+ def SetRaiseToolbar(self, rais):
+ """
+ Enables/disables toobar shadow drop.
+
+ :param bool `rais`: ``True`` to drop a shadow below a toolbar, ``False`` otherwise.
+ """
+
+ self._raiseTB = rais
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/__init__.py
new file mode 100644
index 0000000..363ea99
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/__init__.py
@@ -0,0 +1,298 @@
+"""
+AUI is an Advanced User Interface library that aims to implement "cutting-edge"
+interface usability and design features so developers can quickly and easily create
+beautiful and usable application interfaces.
+
+
+Vision and Design Principles
+============================
+
+AUI attempts to encapsulate the following aspects of the user interface:
+
+* **Frame Management**: Frame management provides the means to open, move and hide common
+ controls that are needed to interact with the document, and allow these configurations
+ to be saved into different perspectives and loaded at a later time.
+
+* **Toolbars**: Toolbars are a specialized subset of the frame management system and should
+ behave similarly to other docked components. However, they also require additional
+ functionality, such as "spring-loaded" rebar support, "chevron" buttons and end-user
+ customizability.
+
+* **Modeless Controls**: Modeless controls expose a tool palette or set of options that
+ float above the application content while allowing it to be accessed. Usually accessed
+ by the toolbar, these controls disappear when an option is selected, but may also be
+ "torn off" the toolbar into a floating frame of their own.
+
+* **Look and Feel**: Look and feel encompasses the way controls are drawn, both when shown
+ statically as well as when they are being moved. This aspect of user interface design
+ incorporates "special effects" such as transparent window dragging as well as frame animation.
+
+AUI adheres to the following principles:
+
+- Use native floating frames to obtain a native look and feel for all platforms;
+- Use existing wxPython code where possible, such as sizer implementation for frame management;
+- Use standard wxPython coding conventions.
+
+
+Usage
+=====
+
+The following example shows a simple implementation that uses :class:`framemanager.AuiManager` to manage
+three text controls in a frame window::
+
+ import wx
+ import wx.lib.agw.aui as aui
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent, id=-1, title="AUI Test", pos=wx.DefaultPosition,
+ size=(800, 600), style=wx.DEFAULT_FRAME_STYLE):
+
+ wx.Frame.__init__(self, parent, id, title, pos, size, style)
+
+ self._mgr = aui.AuiManager()
+
+ # notify AUI which frame to use
+ self._mgr.SetManagedWindow(self)
+
+ # create several text controls
+ text1 = wx.TextCtrl(self, -1, "Pane 1 - sample text",
+ wx.DefaultPosition, wx.Size(200,150),
+ wx.NO_BORDER | wx.TE_MULTILINE)
+
+ text2 = wx.TextCtrl(self, -1, "Pane 2 - sample text",
+ wx.DefaultPosition, wx.Size(200,150),
+ wx.NO_BORDER | wx.TE_MULTILINE)
+
+ text3 = wx.TextCtrl(self, -1, "Main content window",
+ wx.DefaultPosition, wx.Size(200,150),
+ wx.NO_BORDER | wx.TE_MULTILINE)
+
+ # add the panes to the manager
+ self._mgr.AddPane(text1, aui.AuiPaneInfo().Left().Caption("Pane Number One"))
+ self._mgr.AddPane(text2, aui.AuiPaneInfo().Bottom().Caption("Pane Number Two"))
+ self._mgr.AddPane(text3, aui.AuiPaneInfo().CenterPane())
+
+ # tell the manager to "commit" all the changes just made
+ self._mgr.Update()
+
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+
+ def OnClose(self, event):
+
+ # deinitialize the frame manager
+ self._mgr.UnInit()
+
+ self.Destroy()
+ event.Skip()
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+What's New
+==========
+
+Current wxAUI Version Tracked: wxWidgets 2.9.4 (SVN HEAD)
+
+The wxPython AUI version fixes the following bugs or implement the following
+missing features (the list is not exhaustive):
+
+- Visual Studio 2005 style docking: http://www.kirix.com/forums/viewtopic.php?f=16&t=596
+- Dock and Pane Resizing: http://www.kirix.com/forums/viewtopic.php?f=16&t=582
+- Patch concerning dock resizing: http://www.kirix.com/forums/viewtopic.php?f=16&t=610
+- Patch to effect wxAuiToolBar orientation switch: http://www.kirix.com/forums/viewtopic.php?f=16&t=641
+- AUI: Core dump when loading a perspective in wxGTK (MSW OK): http://www.kirix.com/forums/viewtopic.php?f=15&t=627
+- wxAuiNotebook reordered AdvanceSelection(): http://www.kirix.com/forums/viewtopic.php?f=16&t=617
+- Vertical Toolbar Docking Issue: http://www.kirix.com/forums/viewtopic.php?f=16&t=181
+- Patch to show the resize hint on mouse-down in aui: http://trac.wxwidgets.org/ticket/9612
+- The Left/Right and Top/Bottom Docks over draw each other: http://trac.wxwidgets.org/ticket/3516
+- MinSize() not honoured: http://trac.wxwidgets.org/ticket/3562
+- Layout problem with wxAUI: http://trac.wxwidgets.org/ticket/3597
+- Resizing children ignores current window size: http://trac.wxwidgets.org/ticket/3908
+- Resizing panes under Vista does not repaint background: http://trac.wxwidgets.org/ticket/4325
+- Resize sash resizes in response to click: http://trac.wxwidgets.org/ticket/4547
+- "Illegal" resizing of the AuiPane? (wxPython): http://trac.wxwidgets.org/ticket/4599
+- Floating wxAUIPane Resize Event doesn't update its position: http://trac.wxwidgets.org/ticket/9773
+- Don't hide floating panels when we maximize some other panel: http://trac.wxwidgets.org/ticket/4066
+- wxAUINotebook incorrect ALLOW_ACTIVE_PANE handling: http://trac.wxwidgets.org/ticket/4361
+- Page changing veto doesn't work, (patch supplied): http://trac.wxwidgets.org/ticket/4518
+- Show and DoShow are mixed around in wxAuiMDIChildFrame: http://trac.wxwidgets.org/ticket/4567
+- wxAuiManager & wxToolBar - ToolBar Of Size Zero: http://trac.wxwidgets.org/ticket/9724
+- wxAuiNotebook doesn't behave properly like a container as far as...: http://trac.wxwidgets.org/ticket/9911
+- Serious layout bugs in wxAUI: http://trac.wxwidgets.org/ticket/10620
+- wAuiDefaultTabArt::Clone() should just use copy contructor: http://trac.wxwidgets.org/ticket/11388
+- Drop down button for check tool on wxAuiToolbar: http://trac.wxwidgets.org/ticket/11139
+
+Plus the following features:
+
+- AuiManager:
+
+ (a) Implementation of a simple minimize pane system: Clicking on this minimize button causes a new
+ AuiToolBar to be created and added to the frame manager, (currently the implementation is such
+ that panes at West will have a toolbar at the right, panes at South will have toolbars at the
+ bottom etc...) and the pane is hidden in the manager.
+ Clicking on the restore button on the newly created toolbar will result in the toolbar being
+ removed and the original pane being restored;
+ (b) Panes can be docked on top of each other to form `AuiNotebooks`; `AuiNotebooks` tabs can be torn
+ off to create floating panes;
+ (c) On Windows XP, use the nice sash drawing provided by XP while dragging the sash;
+ (d) Possibility to set an icon on docked panes;
+ (e) Possibility to draw a sash visual grip, for enhanced visualization of sashes;
+ (f) Implementation of a native docking art (`ModernDockArt`). Windows XP only, **requires** Mark Hammond's
+ pywin32 package (winxptheme);
+ (g) Possibility to set a transparency for floating panes (a la Paint .NET);
+ (h) Snapping the main frame to the screen in any positin specified by horizontal and vertical
+ alignments;
+ (i) Snapping floating panes on left/right/top/bottom or any combination of directions, a la Winamp;
+ (j) "Fly-out" floating panes, i.e. panes which show themselves only when the mouse hover them;
+ (k) Ability to set custom bitmaps for pane buttons (close, maximize, etc...);
+ (l) Implementation of the style ``AUI_MGR_ANIMATE_FRAMES``, which fade-out floating panes when
+ they are closed (all platforms which support frames transparency) and show a moving rectangle
+ when they are docked and minimized (Windows < Vista and GTK only);
+ (m) A pane switcher dialog is available to cycle through existing AUI panes;
+ (n) Some flags which allow to choose the orientation and the position of the minimized panes;
+ (o) The functions [Get]MinimizeMode() in `AuiPaneInfo` which allow to set/get the flags described above;
+ (p) Events like ``EVT_AUI_PANE_DOCKING``, ``EVT_AUI_PANE_DOCKED``, ``EVT_AUI_PANE_FLOATING`` and ``EVT_AUI_PANE_FLOATED`` are
+ available for all panes *except* toolbar panes;
+ (q) Implementation of the RequestUserAttention method for panes;
+ (r) Ability to show the caption bar of docked panes on the left instead of on the top (with caption
+ text rotated by 90 degrees then). This is similar to what `wxDockIt` did. To enable this feature on any
+ given pane, simply call `CaptionVisible(True, left=True)`;
+ (s) New Aero-style docking guides: you can enable them by using the `AuiManager` style ``AUI_MGR_AERO_DOCKING_GUIDES``;
+ (t) A slide-in/slide-out preview of minimized panes can be seen by enabling the `AuiManager` style
+ ``AUI_MGR_PREVIEW_MINIMIZED_PANES`` and by hovering with the mouse on the minimized pane toolbar tool;
+ (u) New Whidbey-style docking guides: you can enable them by using the `AuiManager` style ``AUI_MGR_WHIDBEY_DOCKING_GUIDES``;
+ (v) Native of custom-drawn mini frames can be used as floating panes, depending on the ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style;
+ (w) A "smooth docking effect" can be obtained by using the ``AUI_MGR_SMOOTH_DOCKING`` style (similar to PyQT docking style);
+ (x) Implementation of "Movable" panes, i.e. a pane that is set as `Movable()` but not `Floatable()` can be dragged and docked
+ into a new location but will not form a floating window in between.
+
+
+- AuiNotebook:
+
+ (a) Implementation of the style ``AUI_NB_HIDE_ON_SINGLE_TAB``, a la :mod:`lib.agw.flatnotebook`;
+ (b) Implementation of the style ``AUI_NB_SMART_TABS``, a la :mod:`lib.agw.flatnotebook`;
+ (c) Implementation of the style ``AUI_NB_USE_IMAGES_DROPDOWN``, which allows to show tab images
+ on the tab dropdown menu instead of bare check menu items (a la :mod:`lib.agw.flatnotebook`);
+ (d) 6 different tab arts are available, namely:
+
+ (1) Default "glossy" theme (as in :class:`~auibook.AuiNotebook`)
+ (2) Simple theme (as in :class:`~auibook.AuiNotebook`)
+ (3) Firefox 2 theme
+ (4) Visual Studio 2003 theme (VC71)
+ (5) Visual Studio 2005 theme (VC81)
+ (6) Google Chrome theme
+
+ (e) Enabling/disabling tabs;
+ (f) Setting the colour of the tab's text;
+ (g) Implementation of the style ``AUI_NB_CLOSE_ON_TAB_LEFT``, which draws the tab close button on
+ the left instead of on the right (a la Camino browser);
+ (h) Ability to save and load perspectives in `AuiNotebook` (experimental);
+ (i) Possibility to add custom buttons in the `AuiNotebook` tab area;
+ (j) Implementation of the style ``AUI_NB_TAB_FLOAT``, which allows the floating of single tabs.
+ Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far
+ enough outside of the notebook to become floating pages;
+ (k) Implementation of the style ``AUI_NB_DRAW_DND_TAB`` (on by default), which draws an image
+ representation of a tab while dragging;
+ (l) Implementation of the `AuiNotebook` unsplit functionality, which unsplit a splitted AuiNotebook
+ when double-clicking on a sash;
+ (m) Possibility to hide all the tabs by calling `HideAllTAbs`;
+ (n) wxPython controls can now be added inside page tabs by calling `AddControlToPage`, and they can be
+ removed by calling `RemoveControlFromPage`;
+ (o) Possibility to preview all the pages in a `AuiNotebook` (as thumbnails) by using the `NotebookPreview`
+ method of `AuiNotebook`;
+ (p) Tab labels can be edited by calling the `SetRenamable` method on a `AuiNotebook` page;
+ (q) Support for multi-lines tab labels in `AuiNotebook`;
+ (r) Support for setting minimum and maximum tab widths for fixed width tabs;
+ (s) Implementation of the style ``AUI_NB_ORDER_BY_ACCESS``, which orders the tabs by last access time
+ inside the Tab Navigator dialog;
+ (t) Implementation of the style ``AUI_NB_NO_TAB_FOCUS``, allowing the developer not to draw the tab
+ focus rectangle on tne `AuiNotebook` tabs.
+
+|
+
+- AuiToolBar:
+
+ (a) ``AUI_TB_PLAIN_BACKGROUND`` style that allows to easy setup a plain background to the AUI toolbar,
+ without the need to override drawing methods. This style contrasts with the default behaviour
+ of the :class:`~auibar.AuiToolBar` that draws a background gradient and this break the window design when
+ putting it within a control that has margin between the borders and the toolbar (example: put
+ :class:`~auibar.AuiToolBar` within a :class:`StaticBoxSizer` that has a plain background);
+ (b) `AuiToolBar` allow item alignment: http://trac.wxwidgets.org/ticket/10174;
+ (c) `AUIToolBar` `DrawButton()` improvement: http://trac.wxwidgets.org/ticket/10303;
+ (d) `AuiToolBar` automatically assign new id for tools: http://trac.wxwidgets.org/ticket/10173;
+ (e) `AuiToolBar` Allow right-click on any kind of button: http://trac.wxwidgets.org/ticket/10079;
+ (f) `AuiToolBar` idle update only when visible: http://trac.wxwidgets.org/ticket/10075;
+ (g) Ability of creating `AuiToolBar` tools with [counter]clockwise rotation. This allows to propose a
+ variant of the minimizing functionality with a rotated button which keeps the caption of the pane
+ as label;
+ (h) Allow setting the alignment of all tools in a toolbar that is expanded;
+ (i) Implementation of the ``AUI_MINIMIZE_POS_TOOLBAR`` flag, which allows to minimize a pane inside
+ an existing toolbar. Limitation: if the minimized icon in the toolbar ends up in the overflowing
+ items (i.e., a menu is needed to show the icon), this style will not work.
+
+
+
+TODOs
+=====
+
+- Documentation, documentation and documentation;
+- Fix `tabmdi.AuiMDIParentFrame` and friends, they do not work correctly at present;
+- Allow specification of `CaptionLeft()` to `AuiPaneInfo` to show the caption bar of docked panes
+ on the left instead of on the top (with caption text rotated by 90 degrees then). This is
+ similar to what `wxDockIt` did - DONE;
+- Make developer-created `AuiNotebooks` and automatic (framemanager-created) `AuiNotebooks` behave
+ the same way (undocking of tabs) - DONE, to some extent;
+- Find a way to dock panes in already floating panes (`AuiFloatingFrames`), as they already have
+ their own `AuiManager`;
+- Add more gripper styles (see, i.e., PlusDock 4.0);
+- Add an "AutoHide" feature to docked panes, similar to fly-out floating panes (see, i.e., PlusDock 4.0);
+- Add events for panes when they are about to float or to be docked (something like
+ ``EVT_AUI_PANE_FLOATING/ED`` and ``EVT_AUI_PANE_DOCKING/ED``) - DONE, to some extent;
+- Implement the 4-ways splitter behaviour for horizontal and vertical sashes if they intersect;
+- Extend `tabart.py` with more aui tab arts;
+- Implement ``AUI_NB_LEFT`` and ``AUI_NB_RIGHT`` tab locations in `AuiNotebook`;
+- Move `AuiDefaultToolBarArt` into a separate module (as with `tabart.py` and `dockart.py`) and
+ provide more arts for toolbars (maybe from :mod:`lib.agw.flatmenu`?)
+- Support multiple-rows/multiple columns toolbars;
+- Integrate as much as possible with :mod:`lib.agw.flatmenu`, from dropdown menus in `AuiNotebook` to
+ toolbars and menu positioning;
+- Possibly handle minimization of panes in a different way (or provide an option to switch to
+ another way of minimizing panes);
+- Clean up/speed up the code, especially time-consuming for-loops;
+- Possibly integrate `wxPyRibbon` (still on development), at least on Windows.
+
+
+License And Version
+===================
+
+AUI library is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 09 Jan 2014, 23.00 GMT
+
+Version 1.3.
+
+"""
+
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "31 March 2009"
+
+
+from aui_constants import *
+from aui_utilities import *
+from auibar import *
+from auibook import *
+from tabart import *
+from dockart import *
+from framemanager import *
+from tabmdi import *
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_constants.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_constants.py
new file mode 100644
index 0000000..e07caba
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_constants.py
@@ -0,0 +1,2594 @@
+"""
+This module contains all the constants used by wxPython-AUI.
+
+Especially important and meaningful are constants for AuiManager, AuiDockArt and
+AuiNotebook.
+"""
+
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "31 March 2009"
+
+
+import wx
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+# ------------------------- #
+# - AuiNotebook Constants - #
+# ------------------------- #
+
+# For tabart
+# --------------
+
+vertical_border_padding = 4
+""" Border padding used in drawing tabs. """
+
+if wx.Platform == "__WXMAC__":
+ nb_close_bits = "\xFF\xFF\xFF\xFF\x0F\xFE\x03\xF8\x01\xF0\x19\xF3" \
+ "\xB8\xE3\xF0\xE1\xE0\xE0\xF0\xE1\xB8\xE3\x19\xF3" \
+ "\x01\xF0\x03\xF8\x0F\xFE\xFF\xFF"
+ """ AuiNotebook close button image on wxMAC. """
+
+elif wx.Platform == "__WXGTK__":
+ nb_close_bits = "\xff\xff\xff\xff\x07\xf0\xfb\xef\xdb\xed\x8b\xe8" \
+ "\x1b\xec\x3b\xee\x1b\xec\x8b\xe8\xdb\xed\xfb\xef" \
+ "\x07\xf0\xff\xff\xff\xff\xff\xff"
+ """ AuiNotebook close button image on wxGTK. """
+
+else:
+ nb_close_bits = "\xff\xff\xff\xff\xff\xff\xff\xff\xe7\xf3\xcf\xf9" \
+ "\x9f\xfc\x3f\xfe\x3f\xfe\x9f\xfc\xcf\xf9\xe7\xf3" \
+ "\xff\xff\xff\xff\xff\xff\xff\xff"
+ """ AuiNotebook close button image on wxMSW. """
+
+nb_left_bits = "\xff\xff\xff\xff\xff\xff\xff\xfe\x7f\xfe\x3f\xfe\x1f" \
+ "\xfe\x0f\xfe\x1f\xfe\x3f\xfe\x7f\xfe\xff\xfe\xff\xff" \
+ "\xff\xff\xff\xff\xff\xff"
+""" AuiNotebook left button image. """
+
+nb_right_bits = "\xff\xff\xff\xff\xff\xff\xdf\xff\x9f\xff\x1f\xff\x1f" \
+ "\xfe\x1f\xfc\x1f\xfe\x1f\xff\x9f\xff\xdf\xff\xff\xff" \
+ "\xff\xff\xff\xff\xff\xff"
+""" AuiNotebook right button image. """
+
+nb_list_bits = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0f" \
+ "\xf8\xff\xff\x0f\xf8\x1f\xfc\x3f\xfe\x7f\xff\xff\xff" \
+ "\xff\xff\xff\xff\xff\xff"
+""" AuiNotebook windows list button image. """
+
+
+#----------------------------------------------------------------------
+tab_active_center = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAbCAYAAAC9WOV0AAAABHNCSVQICAgIfAhkiAAAADNJ"
+ "REFUCJltzMEJwDAUw9DHX6OLdP/Bop4KDc3F2EIYrsFtrZow8GnH6OD1zvRTajvY2QMHIhNx"
+ "jUhuAgAAAABJRU5ErkJggg==")
+""" Center active tab image for the Chrome tab art. """
+
+#----------------------------------------------------------------------
+tab_active_left = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAbCAYAAACjkdXHAAAABHNCSVQICAgIfAhkiAAAAglJ"
+ "REFUOI2Nkk9rE0EYh5/J7mpW06xE2iSmeFHxEoqIAc/FQ5CKgn4DP4KlIQG/QVsQbBEKgop+"
+ "Anvy4rV4bLT2JCGJPVXqwaZJd+f1kN26WTfJDrzszDLPPL/5o0jeFGAC54A0YKmEYAo4DzjA"
+ "LHAZmElqtIGrhmEsvtzcfPNtb6/V6524SWALKBiGsfhxe/uzFhGth5XEmgVubWxsvA1Az68k"
+ "1nngYbPZ7ASg69c06wxwe3V9/b3reVqHwGmwCZRs2370fX//wIuA0+CLwEKj0XilZTSu602G"
+ "FcP7vLe7+7XlRaCgPw62gGv5fP6p63raiwFdLWKOgdNArl6vV1UqpQgcYdcYbwooAPfb7c7h"
+ "mTWmUjGwCWTL5fL1K6VSLiqQyMTYyLVa/UEwe9IC0chFYKnb/XnkeiIDV+Q0UsG/qNkCnEql"
+ "crNQLDpaxpskJnYayD1bXl4S/xrDoPLHKjQOmsHwlCuHv44+ZJ2sLTrGGqzg7zEc+VK1Wl1w"
+ "HMcG0DFxw6sFsRVwAZhdWak9FoRJ+w2HCKzzwN3jXv+daVmGDkdWoMKb9fumHz0DFFfX1p5Y"
+ "lmXo6N0G48jzVEDOt97pdA9ezOXzGU+PzBmN6VuDqyoDN3Z2vjyfKxQynhYkJuJ/L02Ara3X"
+ "n3602r8HrpaTUy3HAy1/+hNq8O+r+q4WETirmFMNBwm3v+gdmytKNIUpAAAAAElFTkSuQmCC")
+""" Left active tab image for the Chrome tab art. """
+
+#----------------------------------------------------------------------
+tab_active_right = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAbCAYAAACjkdXHAAAABHNCSVQICAgIfAhkiAAAAkpJ"
+ "REFUOI2NlM1rU0EUxX9zZ5KaWq3GKKnGutC0FEWCWAWLRUOxBetK/wdp6Re6F6TFXXGhuFdw"
+ "b7dCQUUpiFt1XbB2q7Uf1iTvunjzkpe0afNgmLnDnHvOPe/OWCALtAFC+Cktfha4CRwBDnhg"
+ "BQhaSrK19bf89dv35WfPX7y01haBbiAFmH3BlUA1Gm8WFt75BFkg0TK4VAl0Y3NL5+efvgIK"
+ "wOH92EVjxRljGBi4VgTOeLDbk7kcqEZju1TWX7/Xgtm5J6+BS8ChvdilLhAhkUya4eFbxVQq"
+ "1e3ZbUtgg8GKJd/Tk70/NjYCHCPsgX1kV8K5VA70z8amfvy0tAwMAcebSRfijikY8ez5/OlM"
+ "JrOncbIjp4K1lmRb0sw8eDgCpAm7rwlz46YIzjpGb48WveyDNPhDfCOuHmNwzpHL5dK9fX3n"
+ "mkmvaxJiayOCWMvM1PSdZtJrhiloLJMYIeESDFwf7Acyu0mXGLYmX0PpYi3ZbFdnoVDoBTpp"
+ "uCxCjFob1tYKzlnGJyZHd5Mu6uVGkqvMCmCwzjE4eOMqcALoINauUic37hjhLXPWcTSdThWL"
+ "QxcJX5yqdGk4H/cP9a4755iYnLpL+M/b8e0qjafrekb9TUskuNx/5TzQ5Y1zO9yOZEd1R7OI"
+ "JdXebh/Pzt3zCToAMZv/AjU1orDWWKAGVJVSqcTqysp6X+/ZaeAL8KNac9wsVQ8yNeOsdZw8"
+ "let4/2HpEdAPXDAb20HLj7xqeHT158ra4uLbz2bdg03krmetxrH9KDAmHP8Bn0j1t/01UV0A"
+ "AAAASUVORK5CYII=")
+""" Right active tab image for the Chrome tab art. """
+
+#----------------------------------------------------------------------
+tab_close = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAI9J"
+ "REFUKJG90MEKAWEUxfEfM4rxAFIommzZzNb7v4BsLJTsiGQlYjHfME3flrO75/xvnXv5p/qY"
+ "R/wcWTUktWCKFbrYB6/AAhecmwunAI/RwQAjbLGpoFakwjLATxzqMLQjC68A3/FohkljLkKN"
+ "Ha4YKg8+VkBag3Pll9a1GikmuPk+4qMMs0jFMXoR/0d6A9JRFV/jxY+iAAAAAElFTkSuQmCC")
+""" Normal close button image for the Chrome tab art. """
+
+#----------------------------------------------------------------------
+tab_close_h = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAOlJ"
+ "REFUKJGVkiFuw0AQRd849hUS7iPUwGEllhyjYJ+gaK9Q4CsY9QTFIY4shQQucI8Q7l6h3Z0S"
+ "r7UgjdrPZvVm52k0wpJLWe4y51qgVpECQFQnYPzabN4ra2cAAbgWxZMmyavAkTtROIn33fM0"
+ "fcilLHep92+/wXHTd5K8JJlzbYD3w8C2aVZo2zTsh4FF5Zg516ZAHYBb35MbszbkxnDr+3hQ"
+ "napIIUv1eT6vYPggvAGoSJE88r6XVFQnRA7BOdYIk8IUUZ1SYAQOsXOskRsT1+P/11pZO4v3"
+ "ncLpESzed5W1c1jQn0/jBzPfck1qdmfjAAAAAElFTkSuQmCC")
+""" Hover close button image for the Chrome tab art. """
+
+#----------------------------------------------------------------------
+tab_close_p = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAASxJ"
+ "REFUKJF9kbFLQlEYxX/nvbs55OAkiJAE7k7Nibo9xf+hrTlyr3Boipb+BCGq0bApJEQcG0Ms"
+ "aQ0Lmq5+Dc+nDtbZ7uHce37fd8VSlWwh50PfRKqClWJXI8y6bu5uHj5e3wEEcJDP75txLBSx"
+ "RYbdS7QfJ5PnsJIt5BbB4hQjkrQtjxlFILOXyvQDH/qmUCSJznDAYetkFTxsndAZDggkhCIf"
+ "+qaLmWP1bu8oN+qrC+VGnd7t3bpKqrp4wBjl+ux8FUweSLwlXCnYCv2PHGgE1BLmTYykad2i"
+ "kcOsi1TbZN7EKDfq67NZV5VsIeedvzQjCv5YK8R/4bw7Cl+/P7920+kJkBEq/hWWaPem45cQ"
+ "YDybTfdSmf5CizckwHaAH9ATZldu7i560/ELwC+6RXdU6KzezAAAAABJRU5ErkJggg==")
+""" Pressed close button image for the Chrome tab art. """
+
+#----------------------------------------------------------------------
+tab_inactive_center = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAbCAYAAAC9WOV0AAAABHNCSVQICAgIfAhkiAAAAElJ"
+ "REFUCJlVyiEOgDAUBNHp3qmX5iYkyMpqBAaFILRdDGn4qybZB98yy3ZZrRu1PpABAQiDSLN+"
+ "h4NLEU8CBAfoPHZUywr3M/wCTz8c3/qQrUcAAAAASUVORK5CYII=")
+""" Center inactive tab image for the Chrome tab art. """
+
+#----------------------------------------------------------------------
+tab_inactive_left = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAbCAYAAACjkdXHAAAABHNCSVQICAgIfAhkiAAAAf5J"
+ "REFUOI2llE1rE1EUhp8bZwyhaZomk5DaD40hSWPQVkTd6KIIEUWlLqTEhTaLulBQ6sfKjeBC"
+ "ECULXQku/Alx7d6/U1EQae45LjJpJ5NOnOKBgYG5z33Px3sG/iPMIc87QAmYBZKHgdOu69a2"
+ "3/W2yrVGK5vPLTlxFV3Xrb3+8v1Ntd5oiSpWBmnEidKT972tar3R6ovSt4qoxoIdoFipNlpW"
+ "B6AVRYFEHNWn3a8dz/PK1rIHEgN2UpnMseVTK7fUGBME48CFe88+3sh5+SXr1xmMSbABvJXz"
+ "l9siYAVGWJ0Mu/OVZr5Q8CpWfFWzD2Imj2qu/fhtG4wRVUIZg0bDBsgtn15dt6qIKKBDQZ81"
+ "kWmnzly6OZ+ZzhSt7jfK6CBjFMwEk5TWOy82AVQGhzVUb5RJEkC2fLK6JgIiPhioeZJJUhev"
+ "3j2RTqdzooqge2ojCxwxqrnrG4/uq4Ida3HgAjMOJ4CZSq1+RVBUzCgQinDDstfa282jyeTU"
+ "rhUGF4CJgMPKhbXbmw9VFfG7fBA4LCao7AAzi8cXz1kF0dENMqH38KgWnnd7nSMJxxE5wI4+"
+ "MHyCaeeAYvPshQ0RJby3wVSDHxxgAVh99elb9/evndmfP3boW2FsqGNhMMCdBy8/fJ5KZ6at"
+ "qL+3Q1dEzFkNGMX82ZWh18e0/vVT/wuFmdYVv/ruKgAAAABJRU5ErkJggg==")
+""" Left inactive tab image for the Chrome tab art. """
+
+#----------------------------------------------------------------------
+tab_inactive_right = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAbCAYAAACjkdXHAAAABHNCSVQICAgIfAhkiAAAAhBJ"
+ "REFUOI2llM9rE1EQxz8zb1dSTKNuYtW01kQDRoKFWi9FEEq1IooUUWoPokWCtVqkR69KsSBU"
+ "8OJRPOhBxZNe/At6FBER/HFUPEq1IGn3ecgm2ZjdJODCHPY9vvP9fufNDPzHZ4DDQBrYBKwB"
+ "ftfoJys/Kw9ef/1y8/6rh67rHgKS3WLl6cqqtcCGD58+vn+zdPXorUql8g5Y7wTWdd+y4Vus"
+ "teQK+yfKi8/KwM5umBXAAgioCIP54gTQBzgdwTbsQZR0JpOfXXw+0w27hn9EBGMcyRcPnulJ"
+ "pbKd2JvACKgKnpcePH99+TSwvT3YEphusKsqB4ZHp4FMNWUn5loSEVSFbZ63b8eeUhpwu5Md"
+ "JBFRjHHk7LXb08CuNuAaZTgEEaFQHJoEvDjpakOYmnURUFWSvam+0ujJfqAnmlnABhG2jlTZ"
+ "j19YuEzMm7dUu34hihrDQG7vGLCViPq0VruuvdquyWSvN3xsKhclvbXaoUQiihFlfLJ8iYiq"
+ "O/EtUC2xGGF3vjAObAnI6stCsZbYCLwnEonNY+dulALvHWSH2YN2PXLq4hz/9HpjnmOs18DZ"
+ "bP9IIL0+afV5juqzRgLFcV1n9u6LGWAgWnaMBFHBOIbi0MgU1S3jAcjyyw9xqpvzWou1Pj++"
+ "f/t8b/7EAvBW5u48agU37abWs99rv1YfL81fkT8V34YxbZ696d4CfwEszZSZx6Z26wAAAABJ"
+ "RU5ErkJggg==")
+""" Right inactive tab image for the Chrome tab art. """
+
+# For auibook
+# -----------
+
+AuiBaseTabCtrlId = 5380
+""" Base window identifier for AuiTabCtrl. """
+
+AUI_NB_TOP = 1 << 0
+""" With this style, tabs are drawn along the top of the notebook. """
+AUI_NB_LEFT = 1 << 1 # not implemented yet
+""" With this style, tabs are drawn along the left of the notebook.
+Not implemented yet. """
+AUI_NB_RIGHT = 1 << 2 # not implemented yet
+""" With this style, tabs are drawn along the right of the notebook.
+Not implemented yet. """
+AUI_NB_BOTTOM = 1 << 3
+""" With this style, tabs are drawn along the bottom of the notebook. """
+AUI_NB_TAB_SPLIT = 1 << 4
+""" Allows the tab control to be split by dragging a tab. """
+AUI_NB_TAB_MOVE = 1 << 5
+""" Allows a tab to be moved horizontally by dragging. """
+AUI_NB_TAB_EXTERNAL_MOVE = 1 << 6
+""" Allows a tab to be moved to another tab control. """
+AUI_NB_TAB_FIXED_WIDTH = 1 << 7
+""" With this style, all tabs have the same width. """
+AUI_NB_SCROLL_BUTTONS = 1 << 8
+""" With this style, left and right scroll buttons are displayed. """
+AUI_NB_WINDOWLIST_BUTTON = 1 << 9
+""" With this style, a drop-down list of windows is available. """
+AUI_NB_CLOSE_BUTTON = 1 << 10
+""" With this style, a close button is available on the tab bar. """
+AUI_NB_CLOSE_ON_ACTIVE_TAB = 1 << 11
+""" With this style, a close button is available on the active tab. """
+AUI_NB_CLOSE_ON_ALL_TABS = 1 << 12
+""" With this style, a close button is available on all tabs. """
+AUI_NB_MIDDLE_CLICK_CLOSE = 1 << 13
+""" Allows to close `AuiNotebook` tabs by mouse middle button click. """
+AUI_NB_SUB_NOTEBOOK = 1 << 14
+""" This style is used by `AuiManager` to create automatic `AuiNotebooks`. """
+AUI_NB_HIDE_ON_SINGLE_TAB = 1 << 15
+""" Hides the tab window if only one tab is present. """
+AUI_NB_SMART_TABS = 1 << 16
+""" Use `Smart Tabbing`, like ``Alt`` + ``Tab`` on Windows. """
+AUI_NB_USE_IMAGES_DROPDOWN = 1 << 17
+""" Uses images on dropdown window list menu instead of check items. """
+AUI_NB_CLOSE_ON_TAB_LEFT = 1 << 18
+""" Draws the tab close button on the left instead of on the right
+(a la Camino browser). """
+AUI_NB_TAB_FLOAT = 1 << 19
+""" Allows the floating of single tabs.
+Known limitation: when the notebook is more or less full screen, tabs
+cannot be dragged far enough outside of the notebook to become
+floating pages. """
+AUI_NB_DRAW_DND_TAB = 1 << 20
+""" Draws an image representation of a tab while dragging. """
+AUI_NB_ORDER_BY_ACCESS = 1 << 21
+""" Tab navigation order by last access time. """
+AUI_NB_NO_TAB_FOCUS = 1 << 22
+""" Don't draw tab focus rectangle. """
+
+AUI_NB_DEFAULT_STYLE = AUI_NB_TOP | AUI_NB_TAB_SPLIT | AUI_NB_TAB_MOVE | \
+ AUI_NB_SCROLL_BUTTONS | AUI_NB_CLOSE_ON_ACTIVE_TAB | \
+ AUI_NB_MIDDLE_CLICK_CLOSE | AUI_NB_DRAW_DND_TAB
+""" Default `AuiNotebook` style. """
+
+#----------------------------------------------------------------------
+Mondrian = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAHFJ"
+ "REFUWIXt1jsKgDAQRdF7xY25cpcWC60kioI6Fm/ahHBCMh+BRmGMnAgEWnvPpzK8dvrFCCCA"
+ "coD8og4c5Lr6WB3Q3l1TBwLYPuF3YS1gn1HphgEEEABcKERrGy0E3B0HFJg7C1N/f/kTBBBA"
+ "+Vi+AMkgFEvBPD17AAAAAElFTkSuQmCC")
+""" Default icon for the Smart Tabbing dialog. """
+
+# -------------------------- #
+# - FrameManager Constants - #
+# -------------------------- #
+
+# Docking Styles
+AUI_DOCK_NONE = 0
+""" No docking direction. """
+AUI_DOCK_TOP = 1
+""" Top docking direction. """
+AUI_DOCK_RIGHT = 2
+""" Right docking direction. """
+AUI_DOCK_BOTTOM = 3
+""" Bottom docking direction. """
+AUI_DOCK_LEFT = 4
+""" Left docking direction. """
+AUI_DOCK_CENTER = 5
+""" Center docking direction. """
+AUI_DOCK_CENTRE = AUI_DOCK_CENTER
+""" Centre docking direction. """
+AUI_DOCK_NOTEBOOK_PAGE = 6
+""" Automatic AuiNotebooks docking style. """
+
+# Floating/Dragging Styles
+AUI_MGR_ALLOW_FLOATING = 1 << 0
+""" Allow floating of panes. """
+AUI_MGR_ALLOW_ACTIVE_PANE = 1 << 1
+""" If a pane becomes active, "highlight" it in the interface. """
+AUI_MGR_TRANSPARENT_DRAG = 1 << 2
+""" If the platform supports it, set transparency on a floating pane
+while it is dragged by the user. """
+AUI_MGR_TRANSPARENT_HINT = 1 << 3
+""" If the platform supports it, show a transparent hint window when
+the user is about to dock a floating pane. """
+AUI_MGR_VENETIAN_BLINDS_HINT = 1 << 4
+""" Show a "venetian blind" effect when the user is about to dock a
+floating pane. """
+AUI_MGR_RECTANGLE_HINT = 1 << 5
+""" Show a rectangle hint effect when the user is about to dock a
+floating pane. """
+AUI_MGR_HINT_FADE = 1 << 6
+""" If the platform supports it, the hint window will fade in and out. """
+AUI_MGR_NO_VENETIAN_BLINDS_FADE = 1 << 7
+""" Disables the "venetian blind" fade in and out. """
+AUI_MGR_LIVE_RESIZE = 1 << 8
+""" Live resize when the user drag a sash. """
+AUI_MGR_ANIMATE_FRAMES = 1 << 9
+""" Fade-out floating panes when they are closed (all platforms which support
+frames transparency) and show a moving rectangle when they are docked
+(Windows < Vista and GTK only). """
+AUI_MGR_AERO_DOCKING_GUIDES = 1 << 10
+""" Use the new Aero-style bitmaps as docking guides. """
+AUI_MGR_PREVIEW_MINIMIZED_PANES = 1 << 11
+""" Slide in and out minimized panes to preview them. """
+AUI_MGR_WHIDBEY_DOCKING_GUIDES = 1 << 12
+""" Use the new Whidbey-style bitmaps as docking guides. """
+AUI_MGR_SMOOTH_DOCKING = 1 << 13
+""" Performs a "smooth" docking of panes (a la PyQT). """
+AUI_MGR_USE_NATIVE_MINIFRAMES = 1 << 14
+""" Use miniframes with native caption bar as floating panes instead or custom
+drawn caption bars (forced on wxMac). """
+AUI_MGR_AUTONB_NO_CAPTION = 1 << 15
+""" Panes that merge into an automatic notebook will not have the pane
+caption visible. """
+
+
+AUI_MGR_DEFAULT = AUI_MGR_ALLOW_FLOATING | AUI_MGR_TRANSPARENT_HINT | \
+ AUI_MGR_HINT_FADE | AUI_MGR_NO_VENETIAN_BLINDS_FADE
+""" Default `AuiManager` style. """
+
+# Panes Customization
+AUI_DOCKART_SASH_SIZE = 0
+""" Customizes the sash size. """
+AUI_DOCKART_CAPTION_SIZE = 1
+""" Customizes the caption size. """
+AUI_DOCKART_GRIPPER_SIZE = 2
+""" Customizes the gripper size. """
+AUI_DOCKART_PANE_BORDER_SIZE = 3
+""" Customizes the pane border size. """
+AUI_DOCKART_PANE_BUTTON_SIZE = 4
+""" Customizes the pane button size. """
+AUI_DOCKART_BACKGROUND_COLOUR = 5
+""" Customizes the background colour. """
+AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR = 6
+""" Customizes the background gradient colour. """
+AUI_DOCKART_SASH_COLOUR = 7
+""" Customizes the sash colour. """
+AUI_DOCKART_ACTIVE_CAPTION_COLOUR = 8
+""" Customizes the active caption colour. """
+AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR = 9
+""" Customizes the active caption gradient colour. """
+AUI_DOCKART_INACTIVE_CAPTION_COLOUR = 10
+""" Customizes the inactive caption colour. """
+AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR = 11
+""" Customizes the inactive gradient caption colour. """
+AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR = 12
+""" Customizes the active caption text colour. """
+AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR = 13
+""" Customizes the inactive caption text colour. """
+AUI_DOCKART_BORDER_COLOUR = 14
+""" Customizes the border colour. """
+AUI_DOCKART_GRIPPER_COLOUR = 15
+""" Customizes the gripper colour. """
+AUI_DOCKART_CAPTION_FONT = 16
+""" Customizes the caption font. """
+AUI_DOCKART_GRADIENT_TYPE = 17
+""" Customizes the gradient type (no gradient, vertical or horizontal). """
+AUI_DOCKART_DRAW_SASH_GRIP = 18
+""" Draw a sash grip on the sash. """
+AUI_DOCKART_HINT_WINDOW_COLOUR = 19
+""" Customizes the hint window background colour (currently light blue). """
+
+# Caption Gradient Type
+AUI_GRADIENT_NONE = 0
+""" No gradient on the captions. """
+AUI_GRADIENT_VERTICAL = 1
+""" Vertical gradient on the captions. """
+AUI_GRADIENT_HORIZONTAL = 2
+""" Horizontal gradient on the captions. """
+
+# Pane Button State
+AUI_BUTTON_STATE_NORMAL = 0
+""" Normal button state. """
+AUI_BUTTON_STATE_HOVER = 1 << 1
+""" Hovered button state. """
+AUI_BUTTON_STATE_PRESSED = 1 << 2
+""" Pressed button state. """
+AUI_BUTTON_STATE_DISABLED = 1 << 3
+""" Disabled button state. """
+AUI_BUTTON_STATE_HIDDEN = 1 << 4
+""" Hidden button state. """
+AUI_BUTTON_STATE_CHECKED = 1 << 5
+""" Checked button state. """
+
+# Pane minimize mode
+AUI_MINIMIZE_POS_SMART = 0x01
+""" Minimizes the pane on the closest tool bar. """
+AUI_MINIMIZE_POS_TOP = 0x02
+""" Minimizes the pane on the top tool bar. """
+AUI_MINIMIZE_POS_LEFT = 0x03
+""" Minimizes the pane on its left tool bar. """
+AUI_MINIMIZE_POS_RIGHT = 0x04
+""" Minimizes the pane on its right tool bar. """
+AUI_MINIMIZE_POS_BOTTOM = 0x05
+""" Minimizes the pane on its bottom tool bar. """
+AUI_MINIMIZE_POS_TOOLBAR = 0x06
+""" Minimizes the pane on its bottom tool bar. """
+AUI_MINIMIZE_POS_MASK = 0x17
+""" Mask to filter the position flags. """
+AUI_MINIMIZE_CAPT_HIDE = 0
+""" Hides the caption of the minimized pane. """
+AUI_MINIMIZE_CAPT_SMART = 0x08
+""" Displays the caption in the best rotation (horz or clockwise). """
+AUI_MINIMIZE_CAPT_HORZ = 0x10
+""" Displays the caption horizontally. """
+AUI_MINIMIZE_CAPT_MASK = 0x18
+""" Mask to filter the caption flags. """
+
+# Button kind
+AUI_BUTTON_CLOSE = 101
+""" Shows a close button on the pane. """
+AUI_BUTTON_MAXIMIZE_RESTORE = 102
+""" Shows a maximize/restore button on the pane. """
+AUI_BUTTON_MINIMIZE = 103
+""" Shows a minimize button on the pane. """
+AUI_BUTTON_PIN = 104
+""" Shows a pin button on the pane. """
+AUI_BUTTON_OPTIONS = 105
+""" Shows an option button on the pane (not implemented). """
+AUI_BUTTON_WINDOWLIST = 106
+""" Shows a window list button on the pane (for AuiNotebook). """
+AUI_BUTTON_LEFT = 107
+""" Shows a left button on the pane (for AuiNotebook). """
+AUI_BUTTON_RIGHT = 108
+""" Shows a right button on the pane (for AuiNotebook). """
+AUI_BUTTON_UP = 109
+""" Shows an up button on the pane (not implemented). """
+AUI_BUTTON_DOWN = 110
+""" Shows a down button on the pane (not implemented). """
+AUI_BUTTON_CUSTOM1 = 201
+""" Shows a custom button on the pane. """
+AUI_BUTTON_CUSTOM2 = 202
+""" Shows a custom button on the pane. """
+AUI_BUTTON_CUSTOM3 = 203
+""" Shows a custom button on the pane. """
+AUI_BUTTON_CUSTOM4 = 204
+""" Shows a custom button on the pane. """
+AUI_BUTTON_CUSTOM5 = 205
+""" Shows a custom button on the pane. """
+AUI_BUTTON_CUSTOM6 = 206
+""" Shows a custom button on the pane. """
+AUI_BUTTON_CUSTOM7 = 207
+""" Shows a custom button on the pane. """
+AUI_BUTTON_CUSTOM8 = 208
+""" Shows a custom button on the pane. """
+AUI_BUTTON_CUSTOM9 = 209
+""" Shows a custom button on the pane. """
+
+# Pane Insert Level
+AUI_INSERT_PANE = 0
+""" Level for inserting a pane. """
+AUI_INSERT_ROW = 1
+""" Level for inserting a row. """
+AUI_INSERT_DOCK = 2
+""" Level for inserting a dock. """
+
+# Action constants
+actionNone = 0
+""" No current action. """
+actionResize = 1
+""" Resize action. """
+actionClickButton = 2
+""" Click on a pane button action. """
+actionClickCaption = 3
+""" Click on a pane caption action. """
+actionDragToolbarPane = 4
+""" Drag a floating toolbar action. """
+actionDragFloatingPane = 5
+""" Drag a floating pane action. """
+actionDragMovablePane = 6
+""" Move a pane action. """
+
+# Drop/Float constants
+auiInsertRowPixels = 10
+""" Number of pixels between rows. """
+auiNewRowPixels = 40
+""" Number of pixels for a new inserted row. """
+auiLayerInsertPixels = 40
+""" Number of pixels between layers. """
+auiLayerInsertOffset = 5
+""" Number of offset pixels between layers. """
+auiToolBarLayer = 10
+""" AUI layer for a toolbar. """
+
+# some built in bitmaps
+
+if wx.Platform == "__WXMAC__":
+
+ close_bits = "\xFF\xFF\xFF\xFF\x0F\xFE\x03\xF8\x01\xF0\x19\xF3\xB8\xE3\xF0" \
+ "\xE1\xE0\xE0\xF0\xE1\xB8\xE3\x19\xF3\x01\xF0\x03\xF8\x0F\xFE\xFF\xFF"
+ """ Close button bitmap for a pane on wxMAC. """
+
+elif wx.Platform == "__WXGTK__":
+
+ close_bits = "\xff\xff\xff\xff\x07\xf0\xfb\xef\xdb\xed\x8b\xe8\x1b\xec\x3b\xee" \
+ "\x1b\xec\x8b\xe8\xdb\xed\xfb\xef\x07\xf0\xff\xff\xff\xff\xff\xff"
+ """ Close button bitmap for a pane on wxGTK. """
+
+else:
+
+ close_bits = "\xff\xff\xff\xff\xff\xff\xff\xff\xcf\xf3\x9f\xf9\x3f\xfc\x7f\xfe" \
+ "\x3f\xfc\x9f\xf9\xcf\xf3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+ """ Close button bitmap for a pane on wxMSW. """
+
+pin_bits = '\xff\xff\xff\xff\xff\xff\x1f\xfc\xdf\xfc\xdf\xfc\xdf\xfc\xdf\xfc' \
+ '\xdf\xfc\x0f\xf8\x7f\xff\x7f\xff\x7f\xff\xff\xff\xff\xff\xff\xff'
+""" Pin button bitmap for a pane. """
+
+max_bits = '\xff\xff\xff\xff\xff\xff\x07\xf0\xf7\xf7\x07\xf0\xf7\xf7\xf7\xf7' \
+ '\xf7\xf7\xf7\xf7\xf7\xf7\x07\xf0\xff\xff\xff\xff\xff\xff\xff\xff'
+""" Maximize button bitmap for a pane. """
+
+restore_bits = '\xff\xff\xff\xff\xff\xff\x1f\xf0\x1f\xf0\xdf\xf7\x07\xf4\x07\xf4' \
+ '\xf7\xf5\xf7\xf1\xf7\xfd\xf7\xfd\x07\xfc\xff\xff\xff\xff\xff\xff'
+""" Restore/maximize button bitmap for a pane. """
+
+minimize_bits = '\xff\xff\xff\xff\xff\xff\x07\xf0\xf7\xf7\x07\xf0\xff\xff\xff\xff' \
+ '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
+""" Minimize button bitmap for a pane. """
+
+restore_xpm = ["16 15 3 1",
+ " c None",
+ ". c #000000",
+ "+ c #FFFFFF",
+ " ",
+ " .......... ",
+ " .++++++++. ",
+ " .......... ",
+ " .++++++++. ",
+ " ..........+++. ",
+ " .++++++++.+++. ",
+ " ..........+++. ",
+ " .++++++++..... ",
+ " .++++++++. ",
+ " .++++++++. ",
+ " .++++++++. ",
+ " .++++++++. ",
+ " .......... ",
+ " "]
+""" Restore/minimize button bitmap for a pane. """
+
+#----------------------------------------------------------------------
+
+down_focus_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACaUlE"
+ "QVRIib2WvWsUQRjGn5mdnWxyTaqz9q+QlLnGToSgWAYDNjbpNCAGDGIvaRPbNJGQyiAEbK+w"
+ "sAo2qexyEhbxsvt+jMXc3u3liPfhmWeXnWVm9vc+vO/M7prVzTb+gxyA7Ye/nXPWWmvtXKBb"
+ "B9YBcM5lWZam6by4QNcBsNamaeq9d87NmWutdc59+NgGoKIizCwsxMTMFI8oZmZilzomZiFm"
+ "FWERaXbv7eyueO+TJEHM79LSkvfeWnv2qftgex2ASGDmkrUkKUspiIuCy5IL4qKQgnghdQVx"
+ "ScKsxCKiaH8lIu99NOwAEFGsG4Dv5xeiQYOKBBYVUWJlFhIVVmIlEZGQJKVIYBbWoKqqwQN5"
+ "nqdpuri42OMys6rGOG/X78yW0bXWNyLqcyyAEEIIYcYK3aB5Lazb4o5fsPc3ToFaloxBwMle"
+ "6+9Pjfd7stda6HR85+dCPC86Y6ETcQEcHz32eZ7meZrnx0ePJnlk0vwenm70r/PkTgWdjjuV"
+ "rnPPfvxaa+3NcL3GMaub7XdPtNFoZFn24tmX1/trAOLuM6aaFQwQYExAMPWNaUw1FW+eHj5/"
+ "dbfZbDYajY33F7e1L4gUA5uo3fd8AWbQH70bjGqEyxLq3LoMYhKCgakCIWZoLLdkMRE43Iy0"
+ "tWi9QOP8xoIFAyBUjF7dgOizb9iMhLmByxIAHbAGKYigUPX3hqog47hSvfCHfYRaDcNg3IzO"
+ "7GmydRaGi37zMujrut/9l58nijROQ9yd3ZXLy8urq6vZWFmW9f+Yhrje++XlZR2keDpZa4f+"
+ "H/pKkiR+/f9dDsDWgQW6QHcuxKg/ZbVtCjjzINkAAAAASUVORK5CYII=")
+""" VS2005 focused docking guide window down bitmap. """
+
+#----------------------------------------------------------------------
+down_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACY0lE"
+ "QVRIib2WwWrUUBSG/3tzc5s2m0JhXPsU0u1s3Lkpui4W3PgAuhAFi2/QbesTVEphwCIU3Hbh"
+ "wk2LG1fujJQgtMk55x4Xd2aS6VAzM479JyQhufnOz3/uzcQMBgP8BzkAeZ4756y11tqlQIui"
+ "cACcc1mWpWm6ZK61Nk1T771zbilcxBxiAs659x/OAAQJIswsLMTEzBR/UczMxC51TMxCzEGE"
+ "RaR39WB3b9N7nyTJkLu2tua9t9ZefLx69GYbgIgyc82hJqlrqYiriuuaK+Kqkop4JXUVcU3C"
+ "HIhFJODsCxF57xu/RBT7BuDb958SNGgQUZYgEogDs5AE4UAcSEREk6QWUWbhoCGEENQDZVmm"
+ "abq6ujrkMnMIIdZ5t31vsUC3+l+JaMyxAFRVVRds0C1azsS6O273hH24cwq0UjIGipP9/t+f"
+ "6vZ7st9fKQpf/FqJ28+iEzoTF8Dx0RNflmlZpmV5fPR4lkdmzffwdGe8XyZ3Luh83Ll0k3vx"
+ "4/dWf3+B/Q2OGQwGGxsbeZ5nWfbi2efXB1sA4uozZjRKDaAwRqGmvTCNGQ3F26eHz1/d7/V6"
+ "eZ6fn5/f1bogCmhsonU+9AWY5nr0bjCtKS6LtrltGcQQ1MCMCiEm1MmtWUwETh6mjq1qw0Jd"
+ "fmPD1ADQEWPYNyD6HBs2U2Vu4bIoEBpWE0EE6ej68NaoSBdXRi/8SR/a6qE29830yKFmm2c6"
+ "2fTbp8FYN/0evPw0U6UuTXB39zYvLy+vr68XY2VZNv5imuB679fX10MT8Xyy1k58P4yVJEn8"
+ "9/93OQBFURRFsRTcWH8An5lwqISXsWUAAAAASUVORK5CYII=")
+""" VS2005 unfocused docking guide window down bitmap. """
+
+#----------------------------------------------------------------------
+left_focus_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACVElE"
+ "QVRIibWWvW8TQRDF3+7Ors8ShSsaSpo0dEgoFcINVChSBFRUkajpIKKgiPgP0pqGJiAhITqE"
+ "FIk2BQUVHT2VK+y7ndmhWN/5Ixcbh8tYWvtO8vvdm5mdPXPv+RmuMgjA670/RGSttdZ2q354"
+ "YgkAERVF4b3vHABMCIC11nsfQiCiqwJYa4noxbNvOw/6AJIk62ySJMLMwhI5MnPMnxzMzJHJ"
+ "E0dmicxJhEXk+uTO0fFuCME5h1yDxbh5+zEz93q+LGOv50WUmStOVZSqkjJyWXJVcRm5LKWM"
+ "3PNURq6iMKfIIpJw9n08Hg8Gg36/3wL4+eu3iHpykcWTS5pElCWJpMiJWaIk4RQ5RRERda4S"
+ "UWbhpCmllDQA0+k0pZQFVwF3bzEAZ5N3jgje+0COnPVknbUAdm5cW5/1/eGPxcuL2saoAczC"
+ "DQWAV0/fr1c/HxcBFNC8QGEMMu3NuyddAfIjG9QLjKJTB3NIHV050EZuoQI6+93q4P7B6TYA"
+ "A2gW1xlC61K0OXi492HZ6EbAnGFqEmBmhlYc7A9HutRq/wgA5plSwDT9tORgfzgCNsmv2QfQ"
+ "OvEwps7BooOPpwebxFsB83wazdWdl321BjOGWWejrciZ0+wBMwef76LPnx6trXFrivIfVOsl"
+ "P2V7FwH4MhpuCTBLX7mjckU628naTImlrdDdLDJ59OT+XDDU8SwyTX+Y2bC7hIPVA+fty6/b"
+ "SmwBODreHY/H0+n0P0WLomjegJYAIYTBYNAcp5cOa20IoQXgnMuvAh0GATg8scAEmHQrneMv"
+ "3LAo6X/e0vAAAAAASUVORK5CYII=")
+""" VS2005 focused docking guide window left bitmap. """
+
+#----------------------------------------------------------------------
+left_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACTklE"
+ "QVRIibWWPWsUURSG3/u5u8RiKxtLmzR2gqQSttFKhKBWqQL+BQXL4D9IGxsrBUGEFCIEbC0s"
+ "rOzshYHt3Jl7PizuzsduJhs3Ts7C3Z2BfZ95zzn33DGnp6e4zvAAdnZ2vPfWWmvtsOpFUXgA"
+ "3vvxeBxCuC6AtTaEEGP03g8LQE5RTo73/sXzr7sPJwCExTorLMxExMSJEhGl/MlBRJTIB0+J"
+ "iBORMBMz3/xz7+h4L8bonFsCunH77lMiGo1CWabRKDArEVUkVeKq4jJRWVJVUZmoLLlMNAq+"
+ "TFQlJpJEzCz49n0+n0+n08lk0gP4+es3swbvEnHwTlSYlViYJZEQcWJhkkSSmJnVuYpZiZhE"
+ "RUREI7BYLESkTVE37t8hAM5KcM57hBCid97Z4K2zFsDurRubk74/+9G9vKhtjBrAdG4oALw6"
+ "eLdZ/XxcBFBA8wKFMci012+fDQXIj2xQLzCKQR20kDqGcqCNXKcCuvzd6+DB4dk2AANoFtcl"
+ "QutS9Dl49Pj9qtFLAS3D1CTALA2tOdifnehKq/0jAGgzpYBp+mnFwf7sBLhMfsM+gNaJhzF1"
+ "DroOPpwdXibeC2jzaTRXty37eg2WDLPJRl+RM6fZA6YFn++iTx+fbKxxb4ryH1TrJT9lfxcB"
+ "+Hwy2xJgVr5yR+WKDLaTtZkSK1thuFlk8ujJ/dkxNPAsMk1/mOWwu4KD9QPnzcsv20psATg6"
+ "3pvP54vF4j9Fx+Nx8wa0AogxTqfT5ji9clhrY4w9AOdcfhUYMDyAoiiKohhWt4m/9Qss43IB"
+ "CBMAAAAASUVORK5CYII=")
+""" VS2005 unfocused docking guide window left bitmap. """
+
+#----------------------------------------------------------------------
+right_focus_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACWElE"
+ "QVRIibWWv2/TQBTHv3e+uyRbJwZWFv4AJNSRLjChSkhlYqrEzFZVDAwVC3PXsrAUISTExlKJ"
+ "tQMSWzcmFqaqQqT2+8VwtuMkbiBp+mzF0pPz/dzX7z373IMXp7jJCABebf8JIXjvvffrVd8/"
+ "9gFACGE4HMYY1w4AxgGA9z7GmFIKIdwUwHsfQth7/vXuoxEAFfWFV1ERZhYWYmJmykcOZmbi"
+ "EAMTsxCzirCI3BrfPzjcTCkVRYFcg27cubfDzINBLEsaDKKIMXPFWpFUlZTEZclVxSVxWUpJ"
+ "PIihJK5ImJVYRBSn387Pzzc2NkajUQ/g7McvEYuhIJYYCjUVMRYVUWJlFhIVVmIlERErikrE"
+ "mIXVVFXVEnB5eamqWXAW8Gb39uKHevbzNwARZVFirUSIlFkqEVUD8Pb71P1Lt83LZ+8BAA7O"
+ "AYABMAPcFfcvDXj97ikA5wxmHVVrf64LyA7Mau1so770uVjRQa1lzaKtSc2ZWAR4uHsyn2xq"
+ "YBnjbFp4zsRCBw6Ptz/M5GoHgLla15AfUV8F/gEwA/Bk66jPgXNwMNhkyf199F816DIaB5bx"
+ "yB2aO2qFLsp/+Xiy22YmczA1Cq4hLQlwsK56xwHgumLWln0pgPv8aWcmNdVF7TKujkWAL0db"
+ "88nagXWb0xYgVn4XWf0CymdzWQNgapJzWC7HCnPQF5M5aBhXzthqgMkcoF57Zxx6YvaDMzO3"
+ "148pwMHhJhFdXFwQ0XVEh8NhuwOaAqSUUkoxxvaLulp471NKPYC80ci7gXVFALB/7IExMF6j"
+ "bht/AXIQRaTUgkiHAAAAAElFTkSuQmCC")
+""" VS2005 focused docking guide window right bitmap. """
+
+#----------------------------------------------------------------------
+right_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACVElE"
+ "QVRIibWWv2sUQRTHvzM7M3dHmlQWtjb+AYKkTaOVCEKsrAL+CxaWwcY6bWysRAQRUtgEbC0E"
+ "u3RWNsJCCILZfb8sZvdu925zej/yveMWHnvvM9837+2OOz09xU0qANjZ2QkheO+999vNXpZl"
+ "ABBCGI/HMcabAnjvY4wppRDCdgHIJcrFCSG8eP7l7sMJABX1hVdREWYWFmJiZsqfLGZm4hAD"
+ "E7MQs4qwiNz6c//oeC+lVBRFA+jqzr0DZh6NYlXRaBRFjJlr1pqkrqUiriqua66Iq0oq4lEM"
+ "FXFNwqzEIqL4+u3i4mJ3d3cymQwAzn/8ErEYCmKJoVBTEWNRESVWZiFRYSVWEhGxoqhFjFlY"
+ "TVVVLQFXV1eqOitRV68Pby+v6fnP3wBElEWJtRYhUmapRVQNwJvvvftXbpuXz94BABycAwAD"
+ "YAa4a+5fGfDq7VMAzhnMOllt+rMpIDswa3JnG81lyMWaDppc1i7a2tCCiWWAB4dni8F2Dyxj"
+ "nPUTL5hY6sDh0eP3c7HGAWCuyWvIJRragX8AzAA82T8ZcuAcHAw2W/JwH/3XHnQZrQPLeOQO"
+ "zR21Rhflv3w4O5xGZnPQGwXXklYEOFg3e8cB4LrJbLrtKwHcp48Hc6FeF02Xcb2WAT6f7C8G"
+ "GwfWbU5bglj7WWTNAyh/28sWAL1JzrK8HWvMwZBmc9Ayrp2x9QCzOUCz9s44DGj+hTM3t5ur"
+ "Bzg63iOiy8tLItok6Xg8np6AeoCUUkopxjh9o64n731KaQCQDxr5NLAtBQBlWZZlucWkXf0F"
+ "imtJnvbT2psAAAAASUVORK5CYII=")
+""" VS2005 unfocused docking guide window right bitmap. """
+
+#----------------------------------------------------------------------
+tab_focus_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAIAAADZ8fBYAAAAA3NCSVQICAjb4U/gAAAC10lE"
+ "QVRIidWWT0gUcRTH387+ZveXZgzsbmvSsmqEfzBJSYz+gUsHCYJgISPytCQKFhJdpIN0qIUO"
+ "ezIUaU/roQ5eEzp46ZT/DhG4haCXdSUPK+Wuzvze+02HgdFmFqMtD76Bx8yb3/v8vr/3Zn4z"
+ "np6ReTgCYwAwdqfEGFMURVGU/wIdfaswAGCMcc5VVf1fXIBdBgCKoqiq+nxkobn3BABIkgBA"
+ "hIiEJFAgorAOyxARBTKVoUAkgSiJkIhO73a/nLjGOd/nWkrPXbqLiH6/CgBEJiIaKA1BhkG6"
+ "QF1Hw0BdoK6TLtCvMl2gIQhRCiQiCfPLm5ubtbW1YNXXtuzadyJTZV4AkKYkMpEkkRQoEUmQ"
+ "JJQCpSAiMr1eg8hEJJSmlFJK0wdQLBYR0cl9laj7l6LGY5/tc2ejsrmdgeGJbG5nYHgym9uJ"
+ "x9KHeGuMNd7B8fSMzCfvyerq6rHHn2bmEgPDE09G+/9WaSqZmRofisfSiadnotHoozclp94K"
+ "oGWznNxn/e8q4LqznNwXmb4KuO6s4643lZyugOvOcj8PDyrgurOOe30r05tKZv7ALavXmszt"
+ "rXZZL7EjhTmuU8lpRxNSyemZuUEAmJlLOPzU+CAAuKFluO7OWpF4LO1OPsTcejOOTcRepqXR"
+ "tngs7Y6U4bbcqNrIF6bGh6yt0prAgm7kC6E2fSNfWF9b2d7e1jStvqGlbMSmeRsuP7zZZvp8"
+ "PvCoW1s/a2qq7vddD57y3b7VZfmNfGFxadUQBgqztbWps7Pdy04uLq0WSyVJnoMRgUY45NM0"
+ "bXZZ7OvtaA8vLOdeT85mP+4eXN35K/6W5nBjxFz5tv7+w8LWF3+oTW+IBpsavStf1+xIfTTY"
+ "cNbknDPGfqsD5/xCa6AuDFe791xtEJyHIhHedTGw17tnj49EeFdH8GAkEAhwzgF+7HMZY5qm"
+ "cc6tD6rDGGOMMUS075aN2Ho9R/R/9gsXZ7dKHM+ODQAAAABJRU5ErkJggg==")
+""" VS2005 focused docking guide window center bitmap. """
+
+#----------------------------------------------------------------------
+tab_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAIAAADZ8fBYAAAAA3NCSVQICAjb4U/gAAAC1klE"
+ "QVRIidWVTWgTQRTHJ5vZZEyMLKSx1RbSImJbioeiCKIechLBU8CCtadAaaGIFC/iQTxowENO"
+ "hUohp/Tiocdce/Gk/TiIpTm0JCnmA+OaFJs2u/PerIcp27IbKsZ66Ft47P5n3m/evLc768lm"
+ "s+Q/GCWEBINBSqmiKIqinApU13VKCKGUMsZUVT1lrqIoqqq+frYyeP8cIUSgIIQgAgACcuAA"
+ "wOUlDQCAA1UpcADkAAIREPHiwa2383cYY0TWwa7AlRuPAMDvVwkhiBYAmCBMjqaJBgfDANME"
+ "g4NhoMHBr1KDg8kRQHBAREE+r1er1Z6enkOubbn8d0RLpV5CiLAEogUoEAUHAYAcBYLgIDgi"
+ "ouX1mogWAIKwhBBCWD5Cms0mADi57xKX/6Ws8dgX+97ZqFxpb3JmPlfam5x5nyvtxWPpE7yc"
+ "I+c7OJ5sNhsOh4PB4Kunn5aWE5Mz87MvJv4201QyszA3HY+lE88vRaPRYrHozLcDaNsoJ/fl"
+ "xIcOuO4oJ/dNZqwDrjvqrOebSi52wHVHud+HJx1w3VFnvb6d5ZtKZv7AbZuvXMztZbvkR+wI"
+ "oY7nVHLR0YRUcnFpeYoQsrSccPiFuSlCiBvahuvurFTisbQ7+ARz55txHCL2NmWOtsVjabfS"
+ "hjt0L1Cu1BfmpuVRKReQ0HKlHhkxypV6Ib/ZaDQ0TesfGGqr2DTv+Ph4IBDw+XzEo9Zqv0Kh"
+ "wOOxu10XfA8f3JS+XKmvrm2Z3ARuDQ9fGx297qXnV9e2mvv7Aj3HFQ5md8Snadru7u7Rua6q"
+ "6sp6aTNXzX08OL67q7f9Q4PdTP1ZKCn5Qq321R8ZMQaiXf19VuGbJ1/8IZX+aNdAnxWJRHp7"
+ "e7e3t4+4oVCo0Wjout5qtdx9YIwxxlqtlj3aVgmHw5qmbWxsHNWXUqppGmNM/lCd/aWUUgoA"
+ "9mhbhTFGKT3sm67ruq7v7Oy4cR3bb5uW079be13FAAAAAElFTkSuQmCC")
+""" VS2005 unfocused docking guide window center bitmap. """
+
+#----------------------------------------------------------------------
+up_focus_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACTUlE"
+ "QVRIic2WP28TMRjGH/85c1miqEF8CnbUgSFdukVRmZGQ+gW6Vgwd+hW60Yq1gMQMQzpHGZAg"
+ "C6JS+QIMmUju/L5+Ge6ulzoRTcMh5TmdZfv8/vT4Pcu26h2N8R9kAZwMfltrtdZa60agx5fa"
+ "ArDWpmmaJElTXGBmAWitkyRxzllrG+Zqra21bz+OAQQOzETExJ48EfniKURE5MkmljwRe6LA"
+ "TMz8ZPbs9GzXOWeMQZHfW33/NOufvALALESUU8g95zlnnrKM8pwyT1nGmadHic085Z6Jgidm"
+ "Dhh/mU6nnU6n1WrFXAA/fv7iIEECsxAH5uApELHnwBQ8Bc/MLMbkzELEFCSEEII4YD6fhxAK"
+ "Tsx9/tQDEIgqOzRggAQQQEEBguIFgKoNqDdfvy1yYq41emG4QKkSpDQAiNQfFQClpBoZcaK2"
+ "s0awEHzXVVyri1gxN7FaFuILu6qwtAyokqWWwEvcxNTTKsIK95Cqs4JJzV02vMJvHS/1cFFQ"
+ "UGV+K3tSzWlZq/5bOWGllIio0mzpX+pZSJXdVRmOuabcItRC+ZfKcn+pFRvN65fvNihj9Y7G"
+ "o9FoMplcX18f9M5lUx30zofD4WQyubm56R2Nm9oYY20B98XeRfPcAro+ei1uf/DBt9u+3c7b"
+ "7f7gfTPc/cOr7HE36+5k3Z28u5N1u/uHV/dG3X+gfb7YW8dgpC1YD1vBjfP7oEW6Lvf0bHc6"
+ "nc7n881YaZre3pjucJ1znU7n9qx+qLTWzrkVXGNMcav4d1kAx5camAGzRoiF/gCKPmudbgYP"
+ "HQAAAABJRU5ErkJggg==")
+""" VS2005 focused docking guide window up bitmap. """
+
+#----------------------------------------------------------------------
+up_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACTklE"
+ "QVRIic2WP4vUQBjGn/mTMUtgWS6yvb29XGGzzXXHwdWCcGBzH8BCweK+wnWyWKtot6DNge0V"
+ "gjYnNn4BA9vdJvO+81ok2ewmi7d3RtgnZEgm8/545skwiZrNZvgPsgCSJLHWaq211r1Asyyz"
+ "AKy1cRxHUdQzV2sdRZFzzlrbCxdlDmUC1to3Hy8BBA7MRMTEnjwR+fIoRUTkyUaWPBF7osBM"
+ "zDy+fnR2vu+cM8ZU3KV+fLo+fPUUALMQUUGh8FwUnHvKcyoKyj3lOeee7kU291R4JgqemDng"
+ "8ut8Ph+NRoPBoM0F8PPXbw4SJDALcWAOngIRew5MwVPwzMxiTMEsRExBQgghiAMWi0UIoclh"
+ "VY8fegACUVWHBgwQAQIoKEBQngBQ3wPq9bfv7XzX7o1eGS5QqgIpDQAizUMFQCmpR3bf26qc"
+ "NYKV4nVX7aumaavNjayWlfrSriotdQF1WKoD7nAj00yrLCvdQ+rOGiYNt2t4g9+mXprhoqCg"
+ "qnxre1LPqatN762asFJKRFRltvIvzSykTndTwm2uqbYItdL+5aLbX2nDRvPiyds7tC2p2WyW"
+ "pmmSJHEcP3/25cPFSXfQNjqeTE9fPhiPx0mSXF1d9bMxdrUD3OPJtH9uCd0evRX38Oi9Hw79"
+ "cFgMh4dH7/rhHpxc5PfTPN3L070i3cvT9ODk4saqmz9on6eTbQy2tAPrYSe47XxvtUi35Z6d"
+ "78/n88VicTdWHMfLP6Y1rnNuNBotv9W3ldbaObeBa4wp/yr+XRZAlmVZlvWCW+oP2FUt8NYb"
+ "g5wAAAAASUVORK5CYII=")
+""" VS2005 unfocused docking guide window up bitmap. """
+
+#----------------------------------------------------------------------
+down = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACFUlE"
+ "QVRIidWVPWvbUBSG3+tv8KKpnYtH/4DuJtCti2nntBm7depQWih0zT9w/AtSQsDQ0JIfkKFD"
+ "wRC61Iu3uBgRiKXz1eFalizb8QfxkFdCurofz3l1zhVyg8EAe1BhH9BHyC3NWkTU/XYFQEVF"
+ "mFlYiImZyR9ezMzEpXKJiVmIWUVYRJ7cPT/uHizhFgqF6+93Lz8fAhAxZo5ZY5I4log4ijiO"
+ "OSKOIomIq+VSRByTMCuxiCiufo3H4yAI8txisQjgz98bUVNTEWNRESVWZiFRYSVWEhGxYjEW"
+ "MWZhNVVVtQoQhuESrtfXw6e7JbTd+k1E6dv3+/3dQPeo3+8/3n22Si+OLgFLn52D4aLTun/V"
+ "er8XnVZ1NKqM/lX9eTNaC92IC+D87HUlDMthWA7D87NXmyzZNL+nl0ez60Nyt4Jux91Kee71"
+ "8Lbd6uxwzXFcr9drNpv+4f2bn59O2gDMAMC5ZJY5wOCcwZxlV7tkKr68PX338Vmj0cBev7f8"
+ "d0GkSG0i0576Alza7707LGqBy2JZblYOPgnm4JJA8Blay41ZnAfO3xbumWjTQOv8+oKZA2AJ"
+ "Y1o3wPucGXYLYVZwWQzQlJWmwIMs6Z8OJUHWcUU1aWZ9WKaGlo67xZlTbbbPbL7oq7fBTHm/"
+ "Jx9+bBRpnea4x92D4XA4mUx2Y9VqteVcAEEQ1Ov13bhZ5fP7IFB4v/v41f8HFQ1ap0nfm7YA"
+ "AAAASUVORK5CYII=")
+""" VS2005 unfocused docking guide window down bitmap. """
+
+#----------------------------------------------------------------------
+down_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACaUlE"
+ "QVRIib2WvWsUQRjGn5mdnWxyTaqz9q+QlLnGToSgWAYDNjbpNCAGDGIvaRPbNJGQyiAEbK+w"
+ "sAo2qexyEhbxsvt+jMXc3u3liPfhmWeXnWVm9vc+vO/M7prVzTb+gxyA7Ye/nXPWWmvtXKBb"
+ "B9YBcM5lWZam6by4QNcBsNamaeq9d87NmWutdc59+NgGoKIizCwsxMTMFI8oZmZilzomZiFm"
+ "FWERaXbv7eyueO+TJEHM79LSkvfeWnv2qftgex2ASGDmkrUkKUspiIuCy5IL4qKQgnghdQVx"
+ "ScKsxCKiaH8lIu99NOwAEFGsG4Dv5xeiQYOKBBYVUWJlFhIVVmIlEZGQJKVIYBbWoKqqwQN5"
+ "nqdpuri42OMys6rGOG/X78yW0bXWNyLqcyyAEEIIYcYK3aB5Lazb4o5fsPc3ToFaloxBwMle"
+ "6+9Pjfd7stda6HR85+dCPC86Y6ETcQEcHz32eZ7meZrnx0ePJnlk0vwenm70r/PkTgWdjjuV"
+ "rnPPfvxaa+3NcL3GMaub7XdPtNFoZFn24tmX1/trAOLuM6aaFQwQYExAMPWNaUw1FW+eHj5/"
+ "dbfZbDYajY33F7e1L4gUA5uo3fd8AWbQH70bjGqEyxLq3LoMYhKCgakCIWZoLLdkMRE43Iy0"
+ "tWi9QOP8xoIFAyBUjF7dgOizb9iMhLmByxIAHbAGKYigUPX3hqog47hSvfCHfYRaDcNg3IzO"
+ "7GmydRaGi37zMujrut/9l58nijROQ9yd3ZXLy8urq6vZWFmW9f+Yhrje++XlZR2keDpZa4f+"
+ "H/pKkiR+/f9dDsDWgQW6QHcuxKg/ZbVtCjjzINkAAAAASUVORK5CYII=")
+""" VS2005 focused docking guide window down bitmap. """
+
+#----------------------------------------------------------------------
+left = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACMElE"
+ "QVRIib2WPYsTURSG3zv3ThKJRSqblDYLwU6wFMKCViIEtbKQ/QdWgrXt/oO4hZWCIEIKUfYH"
+ "WFgIATuraewHM3PPh8XNZCaTSWI2oydwMx/kfeY959wzMbPZDC3FaDTavOi23Wgron8n/Z8A"
+ "rnry/NmXk/vXAAhLZCNhYSYiJvbkiciHTwgiIk8uduSJ2BMJMzHzjd93zi9OmwEAbt5+TETd"
+ "bpxlvtuNmZWIcpLcc55z5inLKM8p85RlnHnqxi7zlHsmEk/MLPj6LUmS4XDYDPjx8xezxs56"
+ "4thZUWFWYmEWT0LEnoVJPIlnZlZrc2YlYhIVERHtAIvFYquDu7cIgI0kttY5xHHccdbZKHaR"
+ "jSIAJ8Pru5M+GX+vnm4rslEDmMoFBYCXT9/uVt+MbQAFNCxQGINAe/XmSVuA8MgGxQKjaNVB"
+ "CSmiLQe6kqtUQJfHjQ7unV0eAjCABnFdIrQoRZODBw/frRvdCygZpiABZmmo5mAynupaq/0l"
+ "ACgzpYBZ9dOag8l4CuyT37EPoEXiYUyRg6qD95dn+8QbAWU+jYbqlmWv12DJMLtsNBU5cFZ7"
+ "wJTgzS76+OHRzho3pij8QLVYwlM2dxGAT9PxgQCz9hU6KlSktZ2sqymxthXam0UmjJ7QnxVD"
+ "Lc8is+oPsxx2V3BQf+G8fvH5UIkDAOcXp0mSVF94V4ter5emab/frwMADAaDcOOYSNO00+mE"
+ "4zrgePWaiAMwn8+PF932//MPv0Uk8OspzrYAAAAASUVORK5CYII=")
+""" VS2005 unfocused docking guide window left bitmap. """
+
+#----------------------------------------------------------------------
+left_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACVElE"
+ "QVRIibWWvW8TQRDF3+7Ors8ShSsaSpo0dEgoFcINVChSBFRUkajpIKKgiPgP0pqGJiAhITqE"
+ "FIk2BQUVHT2VK+y7ndmhWN/5Ixcbh8tYWvtO8vvdm5mdPXPv+RmuMgjA670/RGSttdZ2q354"
+ "YgkAERVF4b3vHABMCIC11nsfQiCiqwJYa4noxbNvOw/6AJIk62ySJMLMwhI5MnPMnxzMzJHJ"
+ "E0dmicxJhEXk+uTO0fFuCME5h1yDxbh5+zEz93q+LGOv50WUmStOVZSqkjJyWXJVcRm5LKWM"
+ "3PNURq6iMKfIIpJw9n08Hg8Gg36/3wL4+eu3iHpykcWTS5pElCWJpMiJWaIk4RQ5RRERda4S"
+ "UWbhpCmllDQA0+k0pZQFVwF3bzEAZ5N3jgje+0COnPVknbUAdm5cW5/1/eGPxcuL2saoAczC"
+ "DQWAV0/fr1c/HxcBFNC8QGEMMu3NuyddAfIjG9QLjKJTB3NIHV050EZuoQI6+93q4P7B6TYA"
+ "A2gW1xlC61K0OXi492HZ6EbAnGFqEmBmhlYc7A9HutRq/wgA5plSwDT9tORgfzgCNsmv2QfQ"
+ "OvEwps7BooOPpwebxFsB83wazdWdl321BjOGWWejrciZ0+wBMwef76LPnx6trXFrivIfVOsl"
+ "P2V7FwH4MhpuCTBLX7mjckU628naTImlrdDdLDJ59OT+XDDU8SwyTX+Y2bC7hIPVA+fty6/b"
+ "SmwBODreHY/H0+n0P0WLomjegJYAIYTBYNAcp5cOa20IoQXgnMuvAh0GATg8scAEmHQrneMv"
+ "3LAo6X/e0vAAAAAASUVORK5CYII=")
+""" VS2005 focused docking guide window left bitmap. """
+
+#----------------------------------------------------------------------
+right = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACMklE"
+ "QVRIibWWvY7TUBCFz83vojSuKNiShgdAol8hQYWQkJaKAuUNtqWmoeANFgoqhJAQHRLaB6BA"
+ "orC0HWnSUEURK2LPmRmKayeO4wTysydWbI+c+e7xzDgOo9EIK0rTdDW4m0Ij4FBK07R1fdmj"
+ "rh3QqZ6cPf965+ENAKbWardMTZWkUoVCUuIniiSFnW6HQqqQpkpVvfnn3uu395sBAG7fPSXZ"
+ "73ezTPr9rqqTzGm5aJ5rJswy5jkzYZZpJux3O5kwFyVNqKqGb9/H4/Hx8XEz4PLnL1XvdtpC"
+ "7Xba5qbqVFM1oZEqakoTmqiqerudqzqpNDczM+8Bs9lsrYNXw1ub7+nl+DcAVaOa0HJVESM1"
+ "VzVzAG9+LF2/dZFfPHsPAAgIAQAcgDsQ1ly/NeDlu6cAQnC4V7L6/GtfQHTgXuSONopdk4sd"
+ "HRS5vFy0l6EVE5sAD4YXq8GyBh4xwZcTr5jY6CDg0eMPtVjhAPBQ5HXEW9RUgX8A3AE8OTlv"
+ "chACAhy+WHJzH/1XDaqM0oFHPGKHxo7aoYviTz5eDOeRxRwsjUIoSVsCAryaveIACNVkPi/7"
+ "VoDw+dNpLbTURfNlrNcmwJfzk9Vg4cCrzekbEDs/i7x4AMWt3B0AsDTJUR7LscMcNGkxByVj"
+ "7YztBljMAYq1V8ahQfU/nNrc7q/6e9FkMplOpyKyT9Kjo6MkSQaDQZqmdQdJkiRJsk92AFdX"
+ "V71eLx7XAQfRYDCYH68FHOr19C8Ad0k9S0aHzwAAAABJRU5ErkJggg==")
+""" VS2005 unfocused docking guide window right bitmap. """
+
+#----------------------------------------------------------------------
+right_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACWElE"
+ "QVRIibWWv2/TQBTHv3e+uyRbJwZWFv4AJNSRLjChSkhlYqrEzFZVDAwVC3PXsrAUISTExlKJ"
+ "tQMSWzcmFqaqQqT2+8VwtuMkbiBp+mzF0pPz/dzX7z373IMXp7jJCABebf8JIXjvvffrVd8/"
+ "9gFACGE4HMYY1w4AxgGA9z7GmFIKIdwUwHsfQth7/vXuoxEAFfWFV1ERZhYWYmJmykcOZmbi"
+ "EAMTsxCzirCI3BrfPzjcTCkVRYFcg27cubfDzINBLEsaDKKIMXPFWpFUlZTEZclVxSVxWUpJ"
+ "PIihJK5ImJVYRBSn387Pzzc2NkajUQ/g7McvEYuhIJYYCjUVMRYVUWJlFhIVVmIlERErikrE"
+ "mIXVVFXVEnB5eamqWXAW8Gb39uKHevbzNwARZVFirUSIlFkqEVUD8Pb71P1Lt83LZ+8BAA7O"
+ "AYABMAPcFfcvDXj97ikA5wxmHVVrf64LyA7Mau1so770uVjRQa1lzaKtSc2ZWAR4uHsyn2xq"
+ "YBnjbFp4zsRCBw6Ptz/M5GoHgLla15AfUV8F/gEwA/Bk66jPgXNwMNhkyf199F816DIaB5bx"
+ "yB2aO2qFLsp/+Xiy22YmczA1Cq4hLQlwsK56xwHgumLWln0pgPv8aWcmNdVF7TKujkWAL0db"
+ "88nagXWb0xYgVn4XWf0CymdzWQNgapJzWC7HCnPQF5M5aBhXzthqgMkcoF57Zxx6YvaDMzO3"
+ "148pwMHhJhFdXFwQ0XVEh8NhuwOaAqSUUkoxxvaLulp471NKPYC80ci7gXVFALB/7IExMF6j"
+ "bht/AXIQRaTUgkiHAAAAAElFTkSuQmCC")
+""" VS2005 focused docking guide window right bitmap. """
+
+#----------------------------------------------------------------------
+tab = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAIAAADZ8fBYAAAAA3NCSVQICAjb4U/gAAACq0lE"
+ "QVRIidWWTWgTQRTHJ+3ETEugERrtF6QhFhKsIlgQRITm5LkBvdiDhBZKc5DiRXryoAEPPRUi"
+ "pTnVi4cee5NePAitFtFoVxSyheYDa02KCd3deW/Gw2Cy7MZaIz307TK7/Gfeb9587Nvx6LpO"
+ "TsA6TgJ6glyqHgcHB4/ub0ZvdRFCBApCCCIAICAHDgBcXcoAADhQLwUOgBxAIAIinju89iRz"
+ "gzHW5Pb09BBCImO3AcDn8xJCECUAWCAsjpaFJgfTBMsCk4NposnB56UmB4sjgOCAiIJsbJXL"
+ "5b6+PsYYtQev5b8hSi/tJIQIKRAloEAUHAQAchQIgoPgiIiys9NClAAIQgohhJBnCKnX6wDQ"
+ "jFfZ0+TA/8xpIv6+8e5cN61Qm05ltEJtOvVMK9QS8ewRpWqj2js4nsb+nbv3cnU9OZ3KzD2c"
+ "/NdIF9IrS4sziXg2+aA/FAr5/X5nvG1AW3o5ufOTL9rgur2c3Mcrd9rgur1Oe7wL6edtcN1e"
+ "7v1wtw2u2+u0z2978S6kV/7CbRmv6sxdquVSH7HTR/9tE+PLUsqp2cz27k/7PTWbkcezifHl"
+ "tbW1XC6n6zp1dONeWaUk4tnjTwtx5F81KEcSaQxzdT1p1xPxrFtpwY3d7C6WKkuLMypVqg4U"
+ "tFiqBEfNYqmi57er1WogEBgOx1oqDVoz/77e2Onu6hq7emGg/6w9imKp8ubt149a/mI0rGqV"
+ "8u7DlyuXRuzKp8/5yzG/yr9NrmEYm1uFba2svTq0c0eu+2LR88z7Qy905PW9vZwvOGqGQ73D"
+ "Q1Lf9eR3vitlONQbHpLBYHBwcJAx5rGfd6rV6v7+vmEY7nVgjDHGDMNo1LZUIpGIc34ppYFA"
+ "gDGmfqgOo5RSSgGgUdtSUSUANLmqWp0q/mTK82hFcX4Bm24GMv+uL+EAAAAASUVORK5CYII=")
+""" VS2005 unfocused docking guide window center bitmap. """
+
+#----------------------------------------------------------------------
+tab_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAIAAADZ8fBYAAAAA3NCSVQICAjb4U/gAAAC10lE"
+ "QVRIidWWT0gUcRTH387+ZveXZgzsbmvSsmqEfzBJSYz+gUsHCYJgISPytCQKFhJdpIN0qIUO"
+ "ezIUaU/roQ5eEzp46ZT/DhG4haCXdSUPK+Wuzvze+02HgdFmFqMtD76Bx8yb3/v8vr/3Zn4z"
+ "np6ReTgCYwAwdqfEGFMURVGU/wIdfaswAGCMcc5VVf1fXIBdBgCKoqiq+nxkobn3BABIkgBA"
+ "hIiEJFAgorAOyxARBTKVoUAkgSiJkIhO73a/nLjGOd/nWkrPXbqLiH6/CgBEJiIaKA1BhkG6"
+ "QF1Hw0BdoK6TLtCvMl2gIQhRCiQiCfPLm5ubtbW1YNXXtuzadyJTZV4AkKYkMpEkkRQoEUmQ"
+ "JJQCpSAiMr1eg8hEJJSmlFJK0wdQLBYR0cl9laj7l6LGY5/tc2ejsrmdgeGJbG5nYHgym9uJ"
+ "x9KHeGuMNd7B8fSMzCfvyerq6rHHn2bmEgPDE09G+/9WaSqZmRofisfSiadnotHoozclp94K"
+ "oGWznNxn/e8q4LqznNwXmb4KuO6s4643lZyugOvOcj8PDyrgurOOe30r05tKZv7ALavXmszt"
+ "rXZZL7EjhTmuU8lpRxNSyemZuUEAmJlLOPzU+CAAuKFluO7OWpF4LO1OPsTcejOOTcRepqXR"
+ "tngs7Y6U4bbcqNrIF6bGh6yt0prAgm7kC6E2fSNfWF9b2d7e1jStvqGlbMSmeRsuP7zZZvp8"
+ "PvCoW1s/a2qq7vddD57y3b7VZfmNfGFxadUQBgqztbWps7Pdy04uLq0WSyVJnoMRgUY45NM0"
+ "bXZZ7OvtaA8vLOdeT85mP+4eXN35K/6W5nBjxFz5tv7+w8LWF3+oTW+IBpsavStf1+xIfTTY"
+ "cNbknDPGfqsD5/xCa6AuDFe791xtEJyHIhHedTGw17tnj49EeFdH8GAkEAhwzgF+7HMZY5qm"
+ "cc6tD6rDGGOMMUS075aN2Ho9R/R/9gsXZ7dKHM+ODQAAAABJRU5ErkJggg==")
+""" VS2005 focused docking guide window center bitmap. """
+
+#----------------------------------------------------------------------
+up = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACHUlE"
+ "QVRIidWWP4vUQBjGn8mfcyGQYiM2W8mWsRcLm22uWw6uFpQt7WwVLPwKVsp+gFMsAwqynY2F"
+ "oLAgNu4HsEiz3E7mfee1yN9Lcueu7oo+IcPMZN4fz7yZzEQlSYIDyAMQx/F+ocvl0tkvsdKh"
+ "uF6z8eLsAwDLlpmImNiQISKTX7mIiAx5vkeGiA2RZSZmvnF++9nzO0EQ9HC/vj2fPr0PgFmI"
+ "KCObGc4y1oa0piwjbUhr1oau+Z42lBkmsoaY2eLjpzRN+7kAvn3/wVasWGYhtszWkCViw5bJ"
+ "GrKGmVlcN2MWIiYr1lpr5QjYbDb9eQBw95YBIBBVdDiAC/iAAAoKEOQ3AJRtQL38/OXS/ALw"
+ "XKcxXKBUAVIOAIjUDxUApaQcecV7A3DkuYJG8EVX7VpdtNXm+p4jjfjcrsotdQFlslQH3OH6"
+ "bj2tPCx3Dyk7S5jU3K7hHr91vNTDRUFBFfkt7Uk5p6763lsxYaWUiKjCbOFf6llImd2+DLe5"
+ "ruM0UlA5uazS7S/Usz88vnf2G2VLKkmSap989OD9m8WsO2gbnU7mD5/cHI/H+C/3yR24p5P5"
+ "/rk5dHv0VtzpyWsThiYMszCcnrzaD/d4ttDXIx0NdTTMoqGOouPZ4pdR7e+iq3fzyTYGWzrY"
+ "etj7zwOAOI7/yjmPHRfpFVKr1apqrNfrNE2bx+pOGgwGo9Eor1/wGwRB9QPwh/oH9oed9BPW"
+ "YyQlBOJt4AAAAABJRU5ErkJggg==")
+""" VS2005 unfocused docking guide window up bitmap. """
+#----------------------------------------------------------------------
+up_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACTUlE"
+ "QVRIic2WP28TMRjGH/85c1miqEF8CnbUgSFdukVRmZGQ+gW6Vgwd+hW60Yq1gMQMQzpHGZAg"
+ "C6JS+QIMmUju/L5+Ge6ulzoRTcMh5TmdZfv8/vT4Pcu26h2N8R9kAZwMfltrtdZa60agx5fa"
+ "ArDWpmmaJElTXGBmAWitkyRxzllrG+Zqra21bz+OAQQOzETExJ48EfniKURE5MkmljwRe6LA"
+ "TMz8ZPbs9GzXOWeMQZHfW33/NOufvALALESUU8g95zlnnrKM8pwyT1nGmadHic085Z6Jgidm"
+ "Dhh/mU6nnU6n1WrFXAA/fv7iIEECsxAH5uApELHnwBQ8Bc/MLMbkzELEFCSEEII4YD6fhxAK"
+ "Tsx9/tQDEIgqOzRggAQQQEEBguIFgKoNqDdfvy1yYq41emG4QKkSpDQAiNQfFQClpBoZcaK2"
+ "s0awEHzXVVyri1gxN7FaFuILu6qwtAyokqWWwEvcxNTTKsIK95Cqs4JJzV02vMJvHS/1cFFQ"
+ "UGV+K3tSzWlZq/5bOWGllIio0mzpX+pZSJXdVRmOuabcItRC+ZfKcn+pFRvN65fvNihj9Y7G"
+ "o9FoMplcX18f9M5lUx30zofD4WQyubm56R2Nm9oYY20B98XeRfPcAro+ei1uf/DBt9u+3c7b"
+ "7f7gfTPc/cOr7HE36+5k3Z28u5N1u/uHV/dG3X+gfb7YW8dgpC1YD1vBjfP7oEW6Lvf0bHc6"
+ "nc7n881YaZre3pjucJ1znU7n9qx+qLTWzrkVXGNMcav4d1kAx5camAGzRoiF/gCKPmudbgYP"
+ "HQAAAABJRU5ErkJggg==")
+""" VS2005 focused docking guide window up bitmap. """
+
+#----------------------------------------------------------------------
+aero_dock_pane = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAGcAAABlCAMAAABnVw3AAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAb3WKdHqPdnyRd3+deYGge4OifISifoallZaWgIy1g463hZC5hZG6iJO8o6Sk"
+ "pKSkpKWlpaampqenqKmpqaqqqqurq6ysrKysra6urq+vr7CwsLGxsbKysrOzs7S0tLS0tLW1"
+ "tba2tre3t7i4uLm5uru7vLy8vL29vr6+iZfLjJrNjpzPjpzQkZ7PkJ/SlKHSkaHek6Pgk6Th"
+ "labjmKjlnqzhnqzjoa/npbPov8DAwMDAwMHBwsLCwsPDw8TExMXFxsbGycnJycrKysvLzMzM"
+ "zM3Nzc7Ozs/Pz9DQ0NDQ0NHR0dLS0tPT09TU1NTU1tbW1tfX0tTY19jY1tjd2NjY2dnZ2dra"
+ "2tvb29zc29zf3Nzc3N3d3d7e3t/fxs7szNPt0NXo0dfu1djk09js2tzk3d/k3d/m2Nzv3N/r"
+ "1Nr02N713OH13OL23+X43+X54ODg4eHh4eLi4+Pj4uPm4uPn4+Tk5OTk5OXl5ubm5+fn4eLo"
+ "4uTs5eXp5efv5+jo6Ojo6enp6urq6+vr6Onv7Ozs7O3t7e7u7u/v4Ob55Oj16Ov37e/26+/9"
+ "7/D28PDw8fHx8vLy8/Pz8/P09PT09fX19vb29vf38vT89ff9+Pj4+Pj5+vr6+vr7+/v8/Pz8"
+ "/f39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAsPpcmgAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAf+SURBVGhD7Zr7d9tEGoa9UKBZCiapneBQN3bUQlgo13DbhXBrnRQnS0LJNhDbUO7s"
+ "ErCtZWWZm2Rj2YHdbWQsCSQL2/yjZkaypBlpdKH14XA4vL8kkuebx3PR6HtnHBtHkfxyZoGs"
+ "zMtR4sfjWJRi0mJRHZGlFhej1BCNs1XyocDbpa0ooEjtSfcDOHp6apyFAMzop4XfF2f0K7Vn"
+ "qpyhr0bT5AwHvhpOkzPQ/TVNjt73lT6c4jzQNV/1p8npq77SBlNsj6b4Sr1Ozmtr99xpvQpm"
+ "6LKvquyMVezOe9Ze81uDfNbRHLUtiPaqNi8KvrqqztvlRGGbypFJRM7mMoOtnPNHDV8JisOB"
+ "QczyJolE4qy/MMAX6Pl23VdNGeeMBi+sE0AEzsYl92tgXqj5ipNcnNHo0oYX5OVsnfe8beab"
+ "VVQcelHveTij895XrJdD6SGc4b+HCIglcHTK0yAPJ4dPAYOJtUd/78b3dAdE4owYz6zzcM4Q"
+ "3tEop/v18ePHv+7aICJndMbdIDdn93Iwp/vh7VAf2iAy5/KuC+TmPN0J5HQ+eNDUB51Ji8ic"
+ "zjMhnAwpIbT7TfjXU4+ZeuqfbRNE5miZEE5qGNSe2g//s/RDLYgzSoVwiKlammMmvVTjLE0w"
+ "NH+UJmV37peFe3yInM3NZp0liz/azk+NM0ptt3tkdXZSxGQ1vD3EDOpiep6s9EVSeW+y5e03"
+ "/1Qt+ie/Fseb1HnaE5AS+ieL7k+IHMwTzqDDcDofkB+6P8qfRkPtpAEkD9Bbxsa4J+RHyCgo"
+ "hZRRm/xi9sxZH61smMBUQUEiRzwyC6G3jLk8IY8PdvElWMdf/6745om9DQP0UhELxDjQW8Zc"
+ "ntDF6Z8CdXSoID/XuxtyTmlBHD0dcy0ALs4oCRLrdiBHpmDuncT7wdWenxZ+I5xhEgxMWHvg"
+ "2AW3Z+RpD4c/ChMO6WVhjZlMmRwscMjhQwo5WM9+hT8WgyQwCgIVtOLIFPQSSdyKDb7CpwXg"
+ "DLGa2b49g/W+1jc4LSrgcR1IJgdYpL5tk/o6i4YMYL/hX6TmYD76XtN0k9MPAE044Pt9/5ED"
+ "qmERQ8DBPWHNMlT6O08eaqqeBManRWn+vrEvUdAbJTVVO3zyHX0SrtXQCOAtAQd71BnVdFQ/"
+ "fvnQ6qGq9BOyLDcp1d83aj0KFJETqqIerj705Y9muMqgEcBbxhZwT1iVJSjt/dvOrR4q8oQj"
+ "+/tGtWtyFEk5XD132/saDJeVKhYxABwNFrNVMV7P2he3nDi3+oksaQkQxVMSVga7ABxYc0Lu"
+ "yZ+snjtxyxcarECqoIVUHXBUowGWSl1RFKVXbrj5xP2rH0tdNQGCeKqLlcEuZJGCFSckUfp4"
+ "9f4TN9/wigRq6JXQQjLkiC1U2xx0VOKnN91636MHQqN7EnxIL7exMthFm1+G1yeFunDw6H23"
+ "3vSpCOK5xjZaqKMCTodHtVVjgGryu5DT5ETIqWabWBnsojnhNJkm5Lwrwwpq9S20UEsBnDaW"
+ "mOWrhrOuaJ8/8MgBx1ydA8a0nOV9sjdwm6tnoXed48vcwSMPfK5VjHAmj0bwEuC0aFTrpaIp"
+ "4coTB2y1Mwe+VznLYmWwC5bNwq8+xxbZgyeuCGZwqbKOFuIgB/eEueL+RI03vq2U27Ogt4vZ"
+ "SZKLuUcrE65l4YjO1vYr377RmMQWyjm0LNsL4BQblf2yMAvaXwjhwC4CnP1Kw/qSETiFPUSA"
+ "A4x2IRPcHujFZxk0br8U2h43B8ye/RAOnKHXxykJd4Dx3AvmZOCQ33Fd7Zlwlpx+oxnXjgX3"
+ "Hyoap4XNohzWb6VWHHx62eHQbMt2WuY/teeegxXEw9qT5i2vZvAwzn6VT0CO02+McDpt6PSp"
+ "U+bf9N+MuEQF/YL4PICeL7a12UK9Wr5SclTlN1YMjv2cgqfSeHHIWm4H/lX0s/8wOCvnmbIT"
+ "WMbWA+D5NmNj3KuVOsgCyF2cMyq5i7NutjfOmtsyytkj46+wWDb7fW6DdSKFoxJi/zqXUvBc"
+ "Jr+EHCHNzMUdJWBrgJ5fNDsL6O61lFF6MWsGUevW8K4knMDZBOoXlvLecybXMmRVUrBEWnq8"
+ "98BCE+br8eUuWrWeUr95zr1JZNjQf5P3kpp8re05uXPks4F9tHOSALpGzsqu/z65sjuZlCju"
+ "GjkJMYDThUuGS+GcVIP2hsVtzP+/sfRf654Kl0CX6t2w/SqwxARx3nr8YVOPvxnAofl22P7b"
+ "0wXCu9Npj3LlL6auOD3pbQ/dpMP2E3fXsd1ps21xxc5ilbf/DPU2csfLqXXyYfuj42zL23Fx"
+ "M7k3pHx27NixzxT7WlY8HJqXlsP2e8e5Hd4DiqPJ8nev/unV75AbHg7NdvbC96/HSy3PVIhL"
+ "6Caf/LqMXbrbwzRF9ywg/S5gc80DiveABXAELYWtroRzaIbvPus9miGcl6xfEOp417k4GFTE"
+ "OTTb7G4QDmaI5z9rnQbL0A4rLl71Fcqh6RrfEZ+NeP4zHm8uXT4SeM5O+We7ARwZpsaG6nzr"
+ "qrSXiXyeBebkhcyFCmuPdkLq+qpnWD5DEkfnMhd+wfkcLArOG+20Yaaw66s92kkFfvl5I/6l"
+ "FgLPAad4TtsJOgecIifgHBB4wun9PgT3lphvrHtSKCI20u9qfJI6Yy33vjr/4Fg98Ee/hZ8H"
+ "k2bLAu4tsYRomvPN5S1RDvSEU3tOXd4S2yICnnBqHJe3RLMD6AmjKNJ64PKW6C8VoSeMop8B"
+ "XFekjMjBOHUAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+aero_dock_pane_denied = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAGcAAABlCAYAAABQif3yAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "ABh0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjM2qefiJQAAELhJREFUeF7tnfmPHNURx81v"
+ "hEsCIQQCxCnu60d+AH5BCCGBAAkEP/AHABKKkEhCCErCHcA4WGAIYJwYbOMrGHzgE9vYxvje"
+ "9drYa+99etd7zHov766PSn3avFFvu3v6dU9Pz2Q9K5Vmtt9VVd9X76zqOWtSCf4NDw9LfX39"
+ "pMbGxklHR0YKxuHvzj570tVXXz3ptttuO6tgjUykioeGhuTbRYukrr5eRkZG5OTJkwUj6qcd"
+ "2ptIOiyYLFV79khDQ0PBAPEDm/Zot2BCTZSKFy9eLGNjY6mCc+zYMaHdiaLDgsmxYOHCVIHB"
+ "kvij3YIJNVEqLoNTwkgWAxysp2w5Fp2iDI6FkoqVxYBz4sQJSYPM6q1sORaIoyRAOX78eCpE"
+ "W+VhzQIYsgAOwLC8TYvK4EQAB1DY66RBtIX1lIc1C4BQEgobHR1NhegAZXAsgDHDGgrj3CsN"
+ "ohMwjJYtxwIglITCjh49mgrRAc5YcGpqa2Xjxo2yZs0aWaiKR/m5aNonn0hLS4vodUEq1NTc"
+ "LO3t7UK7YbzBP3IgD3JZ9LXSzLJj505Zvny57Nu3T7p7eqS/v9/qzGzBggVO3h4tkwb19fU5"
+ "wyft2lxPGN6QC/mQszQR8OGqqqpKlv3wg7S2tloJ61UISjpy5IgcPnw4FaIDMITaguPlFzmR"
+ "F7lLGqRdu3bJ1q1bnTHcphf65UFJvb29cujQoVSoq6tLuHmNCw4yIC9yI39JAlRRUSH7q6tj"
+ "g5I9RlFw6M1tbW2pUEdHh3D7mg84hnfkRw8lBRC3iNu3b88bGGenruDQm5t1oo5KKDpqGSx0"
+ "cHAwEXDgHz2U1K0qEyMbx7hDmbtcXHDYSDa3tDsbyigAsVJLEhz0gD5KwnpYrcSd/IPmnKiW"
+ "MzZ2TOoaWuWPr051PvnfFqCkwUEm9FESq7jlK1YkYjHuOScKOAMDA9LRmZG/vj07S/zPcxuA"
+ "CgEOsqCXolpPtU6ABw8eLBo4AFDb0CX/+GjNacRzG4AKBQ56QT9FA2j9Tz9JJpMpCji0W12b"
+ "kQ//XRVIpJMvlwUVCpxebXfDhg3FA2fp0qWJO/7ZLAhYalfXD8nsJR3yr7ltgUT63oODzr4p"
+ "CKBCgcP5IPopmuX899tvndVREqu0KHMOe6DhoyekKxNOg5qP/GmDgzzop2jgFMIZ43t17mO/"
+ "woon13CEwskXRrmA4YC1s7PTOS6i3SQ7WdFvVwsBDmdUu5VYsbFBZNgpFBlgOMTcvXt3GRyb"
+ "3slwgMKYK9ggFopYLOzfv98Zfmz4ipqnqBd4hXRjqqisdPyX5+txTqGI+mknaResknC3KiQ4"
+ "SSsszfrK4KTkdBgX1JJYEKTpAJiWo2G+7STuqLh3715n0xR2j+5O59496nyweMkSZ2WUlsNg"
+ "Eu3AL3xHkZXNtI1fgluf6B8cxu2N4ob5sRTFfKOYPlfCtXV1zgrJT3HcSm7dtk2WLlvmHB6u"
+ "WLmyoLTmxx+dC7IgEOETfuE7ipzoxejHdpV3WhhkPmF+NB6FYXdeDciVSl0peZWybv162aO9"
+ "B2Wk4VjIMh1w/ACCP/iMI2MccAyI2TDIfML88gEHx8Hvvv9+HDjsO37QiyrbnpZUPgBatXr1"
+ "aR0F/uggaYOTDYPMZ5efDzgodv78+eP8odl0couYlNJt62EopV2vbzb8xQHGLAiiDmuG32wY"
+ "ZBmck473TRkcz95knvZM97zSE9FyRvTgs2X6dNn3zDNSdd99DvGdZ6RFtRzvHAd/xbCc7B4p"
+ "H8vhRDjungChg8AJu4Y4zssd3nxTKq64QpruvVd6nn9eMq+9Jn36rOfFF6Xp/vul4sornTzk"
+ "DQPJWE4QOHFkRAb0E9Z2ULpzLpfPEcwhbTzuPgKBAccdScAlGsNLrt46qouG3Q89JLU33yyZ"
+ "d9+VgVmzfCkzebLU3Xqrk5cyueo04HijGuAvbiAX5dBPHMsbZzlUEEfJHOUzidoseU1AFHkp"
+ "4wdOd3e3A04QL2O6vK56/HGpv/126fv4YznyxRdyZOZM6Z87Vwa0p0F85xlp5Km/4w6nDGX9"
+ "6oUPnApp1w8cd6wQfNvEDpl86CeqXo23bNZy4vYOLrJsgaltGpL+wePZ/DDttRzAYSlthPMK"
+ "1qIK//XSS6Xr9del7/PPpV979oC+t2bQQzwjjTzkpQxlgxQFOLTrB46788E/ctgChH6igjMu"
+ "0s5EksUJ8WvVxsMCnGhsT3W3zFx0SBrbT0WrUcaA447DMeAY63LzNKoK3HXTTdLy5JPS9+mn"
+ "MvjVV1ZE3tannnLKUoefnAYcb0yQmRPhF57gHzmQB/5zyU5+9BNVr77g2FiANw9XyTAYFOh0"
+ "7NhxaTuUkY9nVsknczTmRoUz+WF63rx5zjLWELefpgd72+pWT5bKSy6RHp3kB6dNi0S9b78t"
+ "lZddJtThJyebUNp188J3+DP88gn/yIE8yIV8QbKTH/1E1eu4MEgsJ26YH3f8CEHP89LIyKh6"
+ "X7bLW1NXyZQvK7PgIAxlcoFDurdXNrz3ntTcfbcMqKI7dXXWpRbRrcNWr1JGqY/5R6lfaRDS"
+ "ZwOap++555wytffcI9Th19vxbwsCB36RjU8DDvIgF/Ihp1d2+Cc/+gkbWfzSs5F2JszP22ts"
+ "/m9qavK9Qqa3tLV1yqtvfiVvfbhSpkw/BU5D22gWTPLM1Z7pFowdNUrimbf9mpdektZHHpHB"
+ "l1+WtqeflhNaPuzvpObpffhhp0zro48KdXjrRTkGHK+S4Y/8WBaf8I8cyINcyIecyOK9Sqcu"
+ "9GOjR3ceM+RnFwQ88Ov9Yc84oEMwor0MUaZqb7W89Mo/5S9vGHAqZJoDzql2KEObCO8WyoBD"
+ "urftuldekfYHHpChZ5+VVlW4LTg9N94oA7paa3/wQaEOv14O73QKr4JN5yGdcvCPHFOmVzjg"
+ "IB9yIi/pbj1QF/oJ06EfP8w7WXColMk4KuGEwUbLG+hEfc0th+TPr/1H3piyXCZ/vlM+mtUk"
+ "dS3DTuwNUWsAMOebb8a1iasSUWKcsXl5adBhqvGaa2ToscekQ0Fqf/996fjgA+nUvc5hHba6"
+ "lLqVmF8ySn3vvCNHdH7KXH+9DN51lzRee61Qh7de2qJT0K43Df7gF/n4hH/kQB7kQj7kRF63"
+ "DtAJMjohlxH1yuGvEwZpNqE8gMGotEfjclguMvG5yXH602HgYG3raeAw6cM8AnnBYYzmHoc8"
+ "Xl7ata09uiAYUksY1n3O8J13yvAtt8jwDTeE0pDmoSx1eOs1bQWBQzqy8ekFB/mQ06sD/gcs"
+ "9BNVp4DphEEacOg9cXzDKvWGEIX6RT4z3jJZNrd2y9QZFfLR142OcMZhkEDZ2XPmjIv7pB7A"
+ "QSA/fvY+8YS06Z5l5KqrIhFlKOtXp7F82vXGocIfvMAX+RxwVA7kQS7kQ06v/DwDUPQTVa+0"
+ "50TaGXBAiyElKhEDybjKhVQQMRxU/tohMxa2SG3zsMMsgGKtRnjTuww45PHjpWHTJtmhFtB5"
+ "8cUypgq3IfJShrJ+dRrlmU7h7unwRzqy8Qn/yIE8yBUkMzoBIPQTVafZMEgDTpR4GLeL7E4N"
+ "nILBWo3Jz0X0yM27uqWj62i2p2Gts2fPHjdWUxdKyuVCWztjhmw5/3ypvuACGbrwQjl+0UW+"
+ "RBp5yEuZINdeE3tKu965E/5IRzaUDf/IgTy55K3Ta206GvqxiRFy58k61qcFDkpHIAREKBin"
+ "581S4d1mj1Bh4CBInZbbfvnlsv6cc2THuedKzXnnSdNvxHeekUYe8ob5XAMA7XqHIPgz4BiA"
+ "kCOsQ5YMODBSU1MTidzguKOmcaTAAyWX5RhFN+p4Xv3CC7L9uutkkwLx02/Ed57t1zTyhPVc"
+ "t+V4I7gBh7kjqnwAydBWdMvJFxz3Kg+h/MABTNLwa8bRfceOHbJlyxbnNSfr9HUna/REYLXe"
+ "5zj02WeyVv0BCFz65ZdfnOhmXJtY1qJklOYGzA2Od9V5RoKDgpxhTe9i3BMmygsChzQUjEfM"
+ "NnWd+vnnn2W9euqsViBWqAvVMh2WKMvR/6pVq2TdunUOeOblDfiDEQpoJmsDUBYcLeudvOHv"
+ "jLOcXOAssRjWmLsMoWSUapTtVrCxhFwvnGB11KJDF6CWJDgspcPGZr90xtQ4wxrg0ObX2jPd"
+ "9dKzbcAxgDCBU09YAFWudI71N6kVQl4Z4a+oloPfGmv7sEiypMBh7qAu2uTsyguO7YIAfhka"
+ "cZNFBl/SNHzPoKB0ItoYHv3kgz8sNGoHjLsgcEfaOa/vx+OTSZYeGDWSjIkW5rEEWzLA4GH5"
+ "o7rC+oETtAl1DzvuzaPftQXPOC3GullIeA8YOSLhgBF33wMHDviCA3/bdEFBR2BRYisjeSmD"
+ "fqKcELgj7bJvoYobSVavoLDTj3K4xxBDwNIc3X379dZF333nDFNhdbKJ3aUAo9ygV7sMKwAr"
+ "NZ2YTz8vFywPP3GUGTSswycdyQyhYXyRTr20iX6iROU5kXb67oLTAn1BmfE+apQBzDM22xK3"
+ "iziPBylj8+bNjsIChyrXEIYL7QZdkSGMH9+LtB42l0EysQjYqUcsYfMt/MK3rYwswRkSo0YZ"
+ "oH9wSCQCG6HjHv2EKYQNaRiF1VGs9HFHMIloOkYlhQSnWIpNot0yODHex5aE4m3qmPDgrF27"
+ "1vFrsx3n4+SjftqxUXiUPBMaHG5I9+nylxVPId8vTf20Q3tRlB+Wd8KCw96CV2EVEhRv3bTn"
+ "3XOFAZArfcKCwxIU/4I0wcHZxHta8X8PDvsLLp/cB4/5CEVZ5g4bYDJ9w9LaMRRKPZlTDn65"
+ "CG8X7zlfPnJw0gLgRX1rFOdg5qglH2HcZW3B2b2/V+/zm2TqzPpAIn3HnlMv9U4LHHM+xglG"
+ "Ud+3xpsKORS0ubm0Bc8WHJS9Wx0t3v10eyCRHgaMSU/KcgCHjTmfRX1TIRMpxx9x3uccBJYB"
+ "x8aNFcX+Wt0qf5+87DTiufHLDquLfEmBQ0fljAy3qKK+45NDBW4gjWuVrXXkyoeSgpzj/Vxb"
+ "UWxTc4f86W9fZon/jQN6mDuscTpPAhwzpNEmTooxDl2SLcL7k9krcNydxMIAJYUp1Js+MDAo"
+ "+6rr5Pd/eM/55P8odSRhOcjO/IvVHNQr9ZJ4rzRQc5qK9SSxODDgRDlqN1EANbUN2aiAKOWx"
+ "nnwtx7jssg0o6kLAa3tcDOFMkQRAKAnFuj32bb97Ix5sypmIhrjgYDEAw8hBXRvVs7Tkfq4F"
+ "11NcloxXftwhLh9wbMDwy8MQGAccM5SxOgMYLv9K9mdaYAwLYtxlc8owR68y18s2CwaUhAJx"
+ "dE+DTOyNLThGFlZlWAuyUgcWU7LAmKEOk2YOOqCeNBwsYkkIwXLb5j6dW0R6YRrA0AaKZc7x"
+ "ugb78crOH1kYvimLxRlfu5IbynKt+xjimBj5xAnEHAaGTdQmmgyA0iD48Yuy8+MTMBw/N51n"
+ "cBwx8iW7/k2xNvevHdr4J3DvzqkDG7g0iJ6Psm3v+yfErx3GxR8Ai/KDeoRclP9yawBwmGRT"
+ "/0G9MjjhXRNw0vxBvXFhfuHsndk5ACduGGTUED/yZ39Qr2w54R0vbXerkrhSDldLaeQog1Ma"
+ "OPhyUQanDE7WFao8rEXoDGXLiaCstLOWwUlb4xHaM0tpmxPsJPKUh7UI4OQTBhkVrNPC/CLw"
+ "eUZmzScM0uZKwp3HN8zvjNR6BKHjhkGGXUd40wPD/CLwekZmjRMGaXMl4c6TaJhfAVD6HyAO"
+ "VvwtWIicAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+aero_dock_pane_bottom = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAGcAAABlCAYAAABQif3yAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzoyMTozMiArMDEwMExUiZ4AAAAHdElNRQfZAxkQJgE7q5VA"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAEFtJREFUeNrtXVtsHFcZ"
+ "/me8a+9617Ed3x3HcXNxnDhxmsShQQqEolKq0pLeVakSqA8g8YIEQvDAC0g8IB6okEAoPEBB"
+ "QEvbJKWFJqBSWpSUosYpdpzaiXN1Yju+xJfYXtu73hnOd3bPerz3uezMoPqTRrM7u3PO///f"
+ "ufz/ucxI5EKEQiH16tWrdP36dVpYXCxYPn6fj1paWmjdunVHmpub33Bab9djfn5ePX7ihHrl"
+ "6lV1cXFRVRSlYAfSRz7Ib3Bw8FmndU+G5LQAyeg5f14tCwZp06ZNtuV548YNmp2bo47du11l"
+ "D9lpAZJx/do12rBhg615NjU18XzdBteRsxQOk8fjsTVP5Id83QbXkbOGFayRw6CqqtMipMUa"
+ "OS6GvY27DthVmiXJVQ7aKriSHBBjZ1PjVoI+8eQgn6KiIqdVTotPPDmoNW51CFxJDuBWg9kJ"
+ "V5Jjd5/j1oKwRo6LUXByBi5fVm+PjNDS0hJNT09TLpOPjY3xIxqN2mIASZbJ6/HwPF997bWs"
+ "4sGnq6iooJKSEqpvaKBtW7cW1M0rCDlHjx5t29/Z2TfOFI6Ew7Rj504q9nopGAzmvPfYsWNU"
+ "Xl5OkUikkHonAE/N5/NRbU0NPfnEEzn/Pzc3x2UbHR2lkydPqjW1tdS5f39BSLKcnJ6eHvXm"
+ "rVtUX1dH+/buNZQGmjS7ao7IL1+IAlZZWUltbW00PDxMf33rLXVjUxN1dHRYSpKl5Jw7d05d"
+ "WFigLz74IMmy8ZEhEGNbs2bSlW5sbKT6+nrq6uri+u/bt88ygiwbW/voo49Uf2kpHThwwBQx"
+ "AIylKIotBwqBWecD+kJv6A87WGVTS8jB7OXy8jJtb221RChhNL0H+g+991jpGUJ/2AH2sCI9"
+ "S8gZYn3Mvffea4mCRoHZ03BE0T2LarXLDjvAHlbANDlnu7rU3bt3Ozo+VV/fQNcHR+jnR1/l"
+ "Z3x3CrAD7AG7mE3LNDnj4+O8U3QK8Jomp+boty+9R77San7Gd1x3CrAH7GIWpsjp7+9Xt2ze"
+ "7JgRQMDoxCK9+EoXlZbVJQ58x3UnCYJdYB8zaZgi5zYLxGpY8OYEysrKaGh0mf7y7gj5grUp"
+ "B67jd/zPCVQzu2DUwQxMxTlzs7Pk9/ttVzwQCNDoVDF19c2Sz1+V8X9dfUu0Z3uQGquDPLK3"
+ "VUbmVt+9e9dUGqbIwXIir9drq9LA4uIiNTdUUFWlL+d//ewvM5MztssIu5hdbmWKHMQjVk/x"
+ "FpeU8PgDgR3STwf8PjV5Oy8PcSaUebQBsovYCPlajUzy5wvXTRnc09JCo6ytbmxo4AFdtjgk"
+ "H+VBQKZFimLQc2hoiFpsXP6bL1xHzq5du+jE66/zYXyMWRUXFxcsL4wuY+Cyr7+fHn/sMadV"
+ "T4El5FgdZT925AiGQOj06dO0uLRUMOV9rCnb2NzM87NSB6uaetfVHIEOFmXj+CRjbcVnAWBV"
+ "LTRdc9bm+1NhVbOWSKW3t1fVu80PEbDeEQJ4R5tYO79z506bTGUeH3/8Md0YHOTxVb6AYcfG"
+ "x6m2tjbve8Q2SOYUSSINwra7PXv20IbGRl3eEQb3QI6emhNmgdkQ85C6u7vpy48+mvI7PKjz"
+ "vb08bbi6hV4qCze7av167iWmwxtvvklGbAO5hX2M2OaJxx+XJDPb/JB5dXW1IaNgqx+GN9rb"
+ "21ddP33mDE9z65YtpmdU8wEKw8DAAP+cTNCFCxewmdeQbYyQo7UNtkHKTmzzA/hWPyaEFhj/"
+ "whqEdtbkYfkRhkAKfZSWltK2bdtofGIiRUbI55htGC8eJ7b5AcgzzGIYbZOIz06s90cNjaYZ"
+ "jYB8TtkGvKy50i6GY0Eod8FpdUzgtEOeXHOckkfIYYocMzFONi+MN28u2tBkVEez8V+CHCMJ"
+ "qQbvy6hAUv9jN9LlaaYAGrWPKJgeIYCRuQeV3ZOv8Oh0xX+RebqaIdIxOw+i1xDZ5NfaRsid"
+ "Sz6hmxpfuKhXHnG/rDWKXugh5sZwmBbDcs77rKiNenUQ+Wb7HYD80CNX/CX0M9Qaae7zJF/Q"
+ "lRDlNiSi/P4rM3SuL0KH71tPDVWU4j5nM4idyNasoTRP3o3SmXN3WSzmpbYt5TnXcxspaNoW"
+ "xVSfI/qITPd6PF4am5il9/4zTLK3cpWy/J6kQqHmSK9QyJhvSg2QaH5hmekzTuvLi6i2uoyW"
+ "lyPZEjalS6JZM3JkWyAuSTIN3hqjF1/5kMLLikbe3AIrmr7MriMbcUIeAegDvaAf9EzWXWsf"
+ "IzYVeclaAfQemQRAhHvnzjT95g9vx2qXmihIq/+bVDBE52nnLoNkIrLJl+An9gPXD3pC33SF"
+ "1oge2hpsuuYkC4A28+LANXrhF3/UeMYqiW43uXSkK7121pxMsmivrfxnRQ9R2KAn9BVeXK6C"
+ "m488ArzPwVB12MAaKwxSzs/PpzQLLc2N9M1vPEu//PXfUkoG5kRERyq+J5oLJgPSwkixXe40"
+ "PC/kh3yT52uEfJAL0wWK4k/RB3pWlAdWLSAEUUgX9sGhB3CghDfIyTG6k0y7x0WL2dlZqq6q"
+ "pOefe4D+9Mb5FIWT23ABUXqQpl3k5NP/ZZIH+lVXldPU1NSqdETsZNSuKa60IXKyCI65jOam"
+ "evrqMwfoxN9vJjw7/B/r0bRVX2sIrUHsQKYmRfyGa5A3MTrNrnk9Mj3D9IK3Njp6O4XgxGJF"
+ "g3oIOTxmjKFkqDkCw8NDfGf04fsaeJyDvyXXnHT32rknVItMsqzITBTwF9G+fQ3sLHH90kHE"
+ "KooBPbQBrrkgNEOJ0wJVvrFmHYWW/BRkCi2FIqvinHQ1x85FI8mOSNKPCf3QLwVLJWrb7Gf6"
+ "KFyvTBBDMEb0SHGlCw3McG5tUhgxY4nnC6R3VZ2dNEjnSgtAbsgPPezasWDL0ihU7ZmZmYz3"
+ "Jz7HLtiieC5Z0umnx6u1oqA5vuIz05SB47K4AI6QkzBChrE1R5CuBXCYLMdrTjL0mEN0vGZm"
+ "TeHyRpir7ManFXqEknZD6xBor+ULEUsgckccYhTLrD/EOrGydetS8ne6kfOUMOVy7SSzEtrd"
+ "ZOm2LOZbTJAO1radef/9zM2PZtZSTlcA4+5uOSNmc5pd4ZDPKduAF0/LPffwx1Nh77wYY8oX"
+ "iJpx6BEcmcOo2LRUk2G1aD5NFQyGZ7jh/Pn7788Ypff29vKFg83NzSn3Q/Z/vPMONTSkf6gE"
+ "5Mt3l11y3sI2eta9rdpp19JCHrz54tjx46rHwE4ybGzCclU9UTCUHB4Zob6+Pjp06NCq3yAY"
+ "2n8YLpcc+A9WZEJulPB0fQbkm5iYoIMHD6bd9Y1AMhQK8cKSDlgJig1c2GVXV1eXt20EOWFW"
+ "2GGffMF32sE2/f149ttK8ezu7lYHb97UtZIeuwwqKyr4GFK+wEPxqliJbGWKp8OtW7f48w08"
+ "eXTQPmZwEIpxvHS1F2l4mUEzjQwHAwGqZUavybHe+9LAAN1hJIfzfECfIOfOnTu6dhlAl+aN"
+ "G7FwfmWXgVHgsYufO3xY97B4PsjHEMUObLPPByAGNebkqVP09FNPGbax61xpAbca3k6srZV2"
+ "MVxXcyZCsfONSz3051ulNLZYuPJT61PoSFOINrV28O/VpU5rvxquIwf4/qmbpO74Ej3wnEqb"
+ "/RLBzypmLTd8JQ87w1XIlzI4v/Alo+wDQtUldobLg3HlgZBKR/8lkXzqffrRQxudVjsFriPn"
+ "2sVukrY8TD/+dJQCKotVmDU9MshgnyUeN3IvRk8vC4LgyymY7GOxyjKIYhcOSCo9eb9M3104"
+ "yPJ9i6r37nFa/VVwXZ9z/GaAWg5JVBzNPnwiM3ZAWq5DzsIiSPJGFap8KJav22Cq5ojF6Va+"
+ "SWMqLFOrTyIlS7gFgxezdurufO48MXupsrZQyfBX1KhGv0wXwtaVU2EPs3taTZFTYnLQ0SiK"
+ "mc79A/P09r+naHImc/7ryz302c4K6thVRss2LUkQy6IQ7ZeYfG6PKXKCZWU8AEVka+WCDJRm"
+ "NcMBLLKsdrQFCdXrxWMXM6bzzIPbacfOMprX8KddtCnGFKwe0wQ5WM+nZ+gmHUyRg0fiT8/M"
+ "0IZAwFpy1JVVvPwM48mxz+hCmJ9AIWbw9vYa+lpRhF741bspaXzr65+j1rYamouoq9NSNekX"
+ "YE5ADKjemZzUNXSTNi0zN7e1tUl4wweEsXJOCGRE4h4VXGDhCic8LiV2vhtWqXV7I/3wO1+g"
+ "2akbiQPfcR2/KyoljmjSZ6QfUVZqkFmIMTUMkGJkGfYxk57pXrCuvp4/RgQCWUWQwpcjqbFz"
+ "/FAZY/wzxY/49ZmwQg11FfSD7z1NodlhfsZ3XE/cS0lpaNPla9KsIUZM/uEpHBjFNgvT5OD1"
+ "JFeuXOGCWfU4FBiLxyKa0q4t9YqoRRSrVRPLRdS+YzP97Cff5md8j9LKfxK1heI1UV1JP6Ja"
+ "M+MJvcXUxaWLFy15bYsl/iMeNIT5GZQaKwgSzZmS4VCTDlwbXiCqaNrEz+n+I/qcVWQJYkzU"
+ "HOGdgRg4Rt09PSkTe46Sg/fG4HHCeOoUJq7M9kFKvERHNCVc2+9oa4D2WIimvw5nTdTCaLxW"
+ "RuL9TTievlFixMwuZlsHLl/mjyy26j06lkVeeG8MShAef4USJEjCNb0rZBCTRKLxGqQ5lLhx"
+ "hUOQ96HEak1UWSFIOARwMvX0OUIX0b9ghhW6/re7m2di5ftzLB1bg2B48xSe/NTa2spdbQSp"
+ "Yv4937UGsT5BZWcczBCqFO9n4kUc42s6SrtKq709ni5qUHzYQEiVa75fNGEgRkyPYy3ERdbH"
+ "oClz9ZunACHg2bNn1YFLl/i6BDzWCorkG5Rh0GFZiZdsOWZYGUaVKNF7yzrMkOxOC/cczZmk"
+ "rtScXPKBHOw9QuCNKfqRkRGu3yOPPPL/8c42gc7OTi4w3nY4ODjIV8pMTU/ncWc1vTypUh1r"
+ "19aXSFTmlShQJJGvKDZs45Vjo9NFOswhRqHDjJ0ldp5nF2YjGMdTWCWU6CWW1mH2P0wr50Kl"
+ "5m2H+wv0Ij2Bgk8Z6H1d48M/fVddZDVnjhmuRJK5gEXc3ZJILYr1HXrIEU0ayFli5GDoZ4GR"
+ "E2Lexnw4FutEIrHRDTPz/YWA6+ZzgKVIbHimlElXwuzGKg9vxkRThgk3RSc53DNjaS3FD3h2"
+ "yIM7Cvbv08oLriQHrto8K+oBZjQf62iK0ZRFV1xLVSc5fJiGsRBG7Ymi9sSO0HJsSfAaOXrA"
+ "SjSatiV2hFlThqkWT7wp45zIMYLygSBHjKMlalA8D441cvRB0RzZpg9yIdO9Im03w3XT1GtY"
+ "wRo5LsYaOS7GGjkuxho5LoY7yZHtE8ydBojBda50tV+iAPNxg8VywQ3nY9oHvDKVxfN1G1xH"
+ "zvO7vfTPniLa8Jko+VlwGGTRZ9BL5GcRaElRbODTY2BsLaJI5FNUKmH3e2WViotUquHPspGo"
+ "6qREX9nrod85rXwSXEfO/o5d1P7hB/T7Cwdpx6dU2lYqUwUjJcjI8LOqVMLO2Lnj0TNCoMZm"
+ "PBfYMc9q5TQ7JhljlxaJhk4TtSkfUOeeXfklaCNcV5dVhunpafqw5wK93K/Q7fnCxfH1AZme"
+ "bZPpQEc7VVRUYL7GVfb4H1Voiukj7VWUAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+aero_dock_pane_center = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAGcAAABlCAYAAABQif3yAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzoyMTozMiArMDEwMExUiZ4AAAAHdElNRQfZAxkQKidFE1+x"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAEAxJREFUeNrtXdtvHNUZ"
+ "/2Zv3l2vb7HjWxzbcRzjJCQOcSKQiBSQEBclFAgX0VYt4qnq9blP/Qeqqi+t2gi1BaQCJYQg"
+ "oAQQD6VKHhBxwCGJc784dhzbcRzHt73O9Pxm96xnd2e9c9uZqdifdLT27syc832/c77zfec2"
+ "ArkQS0tL0pUrV+jatWu0HI2WLZ9QMEjd3d1UW1v7TGdn54dOy+16LC4uSu8fOSJdvnJFikaj"
+ "kiiKZUt4PvJBfqOjoy87LXs+BKcLkI9T330n1UQi1NXVZVue169fp/mFBdq+bZur9OFxugD5"
+ "uHb1Kq1bt87WPDs6OuR83QbXkROLx8nn89maJ/JDvm6D68ipYAUVchgkSXK6CKqokONi2Gvc"
+ "dcCu2iwIrnLQcuBKckCMnabGrQR978lBPl6v12mRVfG9Jwetxq0OgSvJAdyqMDvhSnLs7nPc"
+ "WhEq5LgYZSfn4qVL0q2JCYrFYnT37l0qpfKpqSk5pVIpWxQgeDzk9/nkPA+9996qxYNPV19f"
+ "T1VVVdTa1kabenvL6uaVhZyDBw/2D+7aNTLNBE7E47R5yxYK+P0UiURK3nv48GGqq6ujRCJR"
+ "TrmzgKcWDAapee1aev7AgZLXLywsyGWbnJyko0ePSmubm2nX4GBZSLKcnFOnTkk3xsaotaWF"
+ "dj7wgKFnwKTZ1XJ4flrBK1hDQwP19/fTzZs36d+ffCKt7+ig7du3W0qSpeScPHlSWl5epice"
+ "f5w8HuMjQyDGNrNm0pVub2+n1tZWGhoakuXfuXOnZQRZNrb2zTffSKFwmHbv3m2KGADKEkXR"
+ "loRKYNb5gLyQG/JDD1bp1BJyMHuZTCbpvr4+SwrFlaY3of/Qe4+VniHkhx6gDyueZwk546yP"
+ "2bFjhyUCGgVmT+MJUfcsqtUuO/QAfVgB0+ScGBqStm3b5uj4VGtrG10bnaA/HTwkf+J/pwA9"
+ "QB/Qi9lnmSZnenpa7hSdArymO7ML9MbbX1Iw3CR/4n987xSgD+jFLEyRc+7cOWljT49jSgAB"
+ "k7ej9Pq7QxSuackm/I/vnSQIeoF+zDzDFDm3WCC2lgVvTqCmpobGJ5P08X8mKBhpLkj4Hr/j"
+ "OifQxPSCUQczMBXnLMzPUygUsl3w6upqmpwN0NDIPAVDjUWvGxqJ0cB9EWpvisiRva1lZG71"
+ "vXv3TD3DFDlYTuT3+20VGohGo9TZVk+NDcGS14bYJXN35mwvI/RidrmVKXIQj1g9xRuoqpLj"
+ "DwR2eL4a8PvsnVuaPMS5peKjDSg7j42Qr9UoVn6tcN2UwYbubppktrq9rU0O6FaLQ7QIDwKK"
+ "LVLkg57j4+PUbePyX61wHTn3338/HfngA3kYH2NWgUCgbHlhdBkDlyPnztFzzz7rtOgFsIQc"
+ "q6PsZ595BkMgdOzYMYrGYmUTPshM2frOTjk/K2WwytS7ruVwbGdRNtL3GZUVn2WAVa3QdMup"
+ "zPcXwiqzln3K6dOnJb3b/BAB6x0hgHfUxez8li1bil7zuze/oKszMQoG/GVfjenziNRZH6Df"
+ "vvxo0WvOnj1L10dH5fhKK1Dqqelpam5u1nwP3wbJnCKBP4Ow7W5gYIDWtbfr8o4wuAdy9LSc"
+ "OAvMxpmHNDw8TD94+umC33/9189ocGsvdXa0UjjooZDPQ1U+gQIs7vEyI+xFbOKBPRZID28o"
+ "okgSpZj3nZLSnzHmit9ZiNHvX/uCHtpSr0rQhx99REZ0g0rF9WNENweee07wmd3mp9ekQUDE"
+ "Mh5W+DNnztDWrVtzfl9IEj390Ca6siBRiMWYQZb8HharMEIYR/J9HiHdWeppUygloiIRJLEy"
+ "J9mnl30RYh7bL3+ylw59/lXBPSjfAzt22LYFUqkb8OJxYpsfIG/1u3495zuMf3kzzcHOXizC"
+ "lJJIFeaI8jmmG8aLz4ltfgDyjLMYRtnynHYs8vNH+ZzSjcyLo9pYBTBBkuKTKLc16aVR7V7+"
+ "fLfCMXJkF5xya6uUSegX5I6bWTjRw/uJdB/D+xk5QNPtEKw8S5kkRZly7nFQN4ApcszEOKu5"
+ "yFBiEuR40iSJQlqJnsxvQuZTTwTNSZA/FcSkpNKtx6iMZs10lhwjD5IM3ldUgMzf8KbizM1N"
+ "sH99EnOdQYzEGwquSXtseqq20lNLZUiBxyayL8UMPWqymKmARvXDK66PF8DI3IPE7tFaeMzP"
+ "8GuRuVrL4aYua9bEXLMmtxp2m8BbgU6zpmraKNe0qZWJ64aXu5SuuGxSZuGiXmL4/R5eACPQ"
+ "Q8z1m3GKxj2a7oOy4kymRKZ2pxTmhys0Jan3H8WS2v3Z1lNCRg6UH3KUWtHK5TNkjRT3+fK/"
+ "0PUgKk0sJrTOXZ6jkyMJ2vvgGmprpJLuM5QWZcFokOkgIGBUQBF0ZrwCj85RHSVJIAR9WkJc"
+ "+b5YWZSt/c69FB0/eY+Wl/3Uv7Gu5HpuI2ZNaVFM9Tm8jyh2r8/np6nb8/TlVzfJ42/IEVbK"
+ "2Bk1oqCshCQyJQo5LcfL/k+bNkm3KyXmmbQU73vE9FCOqhwFLUCgxeUkk2ea1tR5qbmphpLJ"
+ "VbaqmBwUzpo1I2m1BeKC4KHRsSl6/d2vKZ4UFeUtXeAcsyZmPDdOEuWZKK2Jcu9P8WdrMGti"
+ "pm/lgDyQC/JBznzZlfoxolOel0dZAL2pWAEQ4c7M3KV//POLTE+crUi51+ZVDPlZlFYaq6AU"
+ "Q8qYn4SoIIonSUfK3MOfwZ+ZYGwlU7kVp1j5svykf5Dlg5yQV63SGtGrsgWb6nNEFW8Nfcz5"
+ "i1fpzbeOUlV2TZmU4aewdhSaEqJ7rMl8PBqjDREvtYY91FAlUK1foGqfIA+EBjIDoeiLtHQ9"
+ "Eq20lDhrRlFGxiJrMsgnzr6fn1yULyrW56ysMlqRg1e2P/75Lfrpj56ijRvW5/RBfPWQXr3i"
+ "Hr6qSCYHQ9VxA2ussFFqcXGxoADdne30m5+/TH/5+2cFNQNzIlwI/j+HXAYpXaNn2Z9rWMuJ"
+ "sFTlw8h0mgywwYdd9JKTENMtEeQss7SUSpvPWMau5c/X8PKhXBgxFsVQgTyQs76uOmcBIYgE"
+ "OdAPkh6AGO4NyuQY3Umm3OOixPz8PDU1NtCrP36M/vXhdwUCF6tR3JRAiXOsn11kaYmREwZB"
+ "njRBntTKyIBogJx4SkFQcsVMSkU8DL5XSC1egXxNjXU0OzubIw/fLWdUrwVmzRA5qxQcE02Y"
+ "MHvlpd105PMbWc8O12M9mtImKxUBNSXZ9/dYlV5ICDI5yymBQilBNmdeeT4H5jFt2rSSI/cz"
+ "8sgDI4cxhbTMUoI9N5GTf66S8B3Kmx2dZt/5WcYvMbngrU1O3iqoaNnFihn96AUvh4//Y+gh"
+ "RVoOx82b4/LO6L0Ptslxjhyh57UctXuz3prSAVB6XoqRA63kZO9TxDvcQRAVDkE+eOVLl5mo"
+ "OuSlnTvb2Kcgy6cGHquIBlqOMsA1F4QqvJNiQJNvX1tLS7EQRZhAsaVETpxT2HKcQ0H+Cvmw"
+ "ADESFqi/J8TkEWW5ioEPwRjRa4ErXW5ghrO3Q2TETGXPF1B3VZ2fbMt3pTlQbpQfcti1Y8GW"
+ "pVFo2nNzc0Xvz/5ti8iry7KafHq8WisqmuMzoWpTBnYjHYk7P02eD0fIySpBZWxN1KEfDH76"
+ "MytyVs2P0hN3PuZ7C6n0fJC8AgdzOX6JZlJRCvhUDotwmCzHW45RgJgwU2hjFXMyoqVNjTy2"
+ "5mGEsM84oyvKUrOXfS4t0emh07S1w/5NYKUgk+PEGZeqawjY31qnAtBimoIC/eGNo6u6q/zx"
+ "xUSs8hJtbvPQU1vWuGYNAYevKhAouZPMSih3k6ltWYR+sHiwjv0U8aN1EIV8aSUGPOnk95K8"
+ "CnRpYYnVLole+8VjqoEgAsfjx4/Lm3Y3b96c8zvkRf5vv/MO9WzYQJ3r1xeUBb87pRvw4utm"
+ "BcPxVNg7D3dRT6cI4ZH0FByZ47wybFpa29RU8PtyLE5hIUX71geoiZkstI5axkgEJHkFCmRW"
+ "gGIQ9OvhcVpTlZKfp7a+bJGZLOxa27dvn+pxYpAbY2JNKuUAUD6tu+zylcx1o2fdW85Ou+7u"
+ "dIB9+P33pc39/bp3kmGhdkN9va4oGEJO3LpFI2fP0p49ewp+/9vn39K3k0kKBkrv96xj5D3a"
+ "lqSpiTHVMqDmQ1iM9amhvq6OOru6qHfjxqJTz9jAhVbX0tKiWTecnJk7d+Rz3LQCjQPHB2Dh"
+ "/PMHDqxY4uHhYWn0xg1dK+mxy0AmR0fLwaF4jaxG9m3apPr72NiYXECfhs24wVBIVj7G8dRa"
+ "L57hZwotNjIcqa6mZqb0tUVaDseFixdp5vZtims8oC9LzsyMrl0GkAXmdWBgYGWXgVHg2MVH"
+ "9u7VPSyuBVoUEXBgm70WgJja2lo6+umn9OILLxjWsWtdabcq3k5Uth26GK5tOZcuXaJp2Pky"
+ "vnQIHTz6m97eXqfFVYUryTnGYhMcKjc4OFjWcwj4TjLkt+fhh50WuwCuI+ci84xwqq4du8mU"
+ "O8mQ76YiHqRTcF2fA1Nm9+F62L2GfN0GUy2HL0638k0aCMS0nEQVjUm0GC2dZ4gFquHg6t4s"
+ "8rPykHGuD7OnBJsiB+M/iPidwOhElIbOzNP8YvHRiZpqL22/L0Jbe8O2lYsviwLZVSb7S1Pk"
+ "RGpq5AAUka2dJ6gDfd0hIjFOn/73RtFrHtm1nvp6ShNj9SQbyMF6PgSiZmCKHByJf3dujtZV"
+ "V1tOjhaF9fXUkc+bpEMfDxf89uL+AerpqtP0HCunTEBMdlxNx9CN6rPM3Nzf3y/gDR8ojJUC"
+ "6ln03dPVSK++NEjL87eyCf/jey0Lya0EH1ODF4iRZejHzPNMe2stra3y6DQKZBVBepQGAtY0"
+ "ROiVHz5C0aUZ+RP/a53GsIogPhcjE8NiJ4xim4VpcvB6ksuXL8sFQ7KSIK0JWXZ3ttGvfvai"
+ "/In/9W69sIIceH3QwYXz5y15bYslQSgOGhoZGZHnPRB1m315g5E9qri+taVJt/doNgzgCwj5"
+ "3NG3w8PUyfRhBSwJQvHeGBwnjFOn+KykU+sS7LiHg5syyBwOh/GWLfnIYqveo2PZCAHeGwNP"
+ "BbN4qEGcJHxXbPd0Mdj1ehYj6wK4LLx/wbnakBUtBgsgrHx/jqVjaygY3jyFgcS+vj7Z1YaZ"
+ "4fPvWk+ztbvV8TxLzffzABPE4FqYMqyFOM/6GJgyV795CuAFPHHihHTxwgV5XQLOHIMgWoIy"
+ "3trsAlc4n70sdS3WIyDwxhT9xMSELN/+/fvLUpvKXkWVbzucvXu35PUQ+sknnrD9hXo49E5L"
+ "0Njw//62QyX0CoB1CViqFCvjkcVKgBx05iDGzHx/OeC6+RzA6GYuI6i8m1onjHpSRvOqkKMD"
+ "Rg9KMoIKOTph5y43txIDuG6auoIVVMhxMSrkuBgVclyMCjkuhivJcWK6wY1wHTnKbZDlRv42"
+ "P7fBdXGOmW2QepG/zc9tcKX9MLoNUi/yt/k5LXc+XFcgDiPbIPUif5uf2/A/9n+1U7cLqMYA"
+ "AAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+aero_dock_pane_left = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAGcAAABlCAYAAABQif3yAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzoyMTozMiArMDEwMExUiZ4AAAAHdElNRQfZAxkQKBW/8myz"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAD+tJREFUeNrtXWlsVNcV"
+ "Pm8Wz9iewTYYbxhjjDFmM4SloKwkipI0QiIhIU2VSlV+VVGrqlX6p5XaRpXa/kilVmqriD/N"
+ "IqWtQkjSJA2ozdJUQJMGEwwYAwZjDLaxjbHB23iW93q/O3PtWT1vmzevynzS9fO8eXOX893l"
+ "nHOXJ5ENMT09rfT09FBvby/NBAI5S6fY66XGxkZatGjRnoaGhnfzXW7bY2pqSnnr7beVSz09"
+ "SiAQUGRZzllA/EgH6fX19T2d77InQ8p3BpJx6vRpxe/z0YoVKyxL88qVKzQxOUltGzfaSh6O"
+ "fGcgGb2XL9OyZcssTbO+vp6nazfYjpzZYJBcLpelaSI9pGs32I6cAuZRIIdBUZR8ZyEtCuTY"
+ "GNZ27hpgVW2WJFspaAmwJTkgxsquxq4EfeXJQTpOpzPfRU6Lrzw5aDV2VQhsSQ5gV4FZCVuS"
+ "Y/WYY9eKUCDHxsg5Od0XLyrXBwdpdnaWxsfHKZvIh4eHeYhEIpYIQHI4yO1y8TQPvPnmgtmD"
+ "TldeXk4ej4dqamtpdXNzTtW8nJCzf//+1q3btnWNsAKHgkFau24dFbnd5PP5sv724MGDVFZW"
+ "RqFQKJflngM0Na/XS1VLl9ITe/dmfX5ycpLnbWhoiA4dOqQsraqibVu35oQk08k5deqUcvXa"
+ "NaqprqYtd9yhKw50aVa1HJGeWogKVlFRQa2trTQwMEB//+ADZXl9PbW1tZlKkqnknDhxQpmZ"
+ "maGHH3qIHA79niEQY1m3ZlCVrquro5qaGmpvb+fl37Jli2kEmeZb+/LLL5XikhLavn27IWIA"
+ "CEuWZUsCKoFR5QPlRblRfsjBLJmaQg5mL8PhMK1paTElU0JoWgPGD62/MVMzRPkhB8jDjPhM"
+ "IaefjTGbN282pYB6gdnTYEjWPItqtsoOOUAeZsAwOcfb25WNGzfm1T9VU1NLvX2D9If9B/gV"
+ "n/MFyAHygFyMxmWYnJGRET4o5gvQmm6OTdKrf/mUvCWV/IrPuJ8vQB6Qi1EYIufcuXPKqqam"
+ "vAkBBAzdCNArb7RTib96LuAz7ueTIMgF8jEShyFyrjNDbCkz3vIBv99P/UNhev9fg+T1VaUE"
+ "3Mf3eC4fqGRygdfBCAzZOZMTE1RcXGx5wUtLS2lorIjauybIW7wk43PtXbO0aY2P6ip93LK3"
+ "NI9Mrb59+7ahOAyRg+VEbrfb0kIDgUCAGmrLaUmFN+uzxeyRWzdvWZ5HyMXocitD5MAeMXuK"
+ "t8jj4fYHDDvEnw74fuzmdVUa4q3pzN4G5F3YRkjXbGTKv1rYbspgZWMjDbG+uq62lht0C9kh"
+ "agoPAjItUhROz/7+fmq0cPmvWtiOnA0bNtDb77zD3fjwWRUVFeUsLXiX4bjsOneOHn/ssXwX"
+ "PQWmkGO2lf3Ynj1wgdCRI0coMDubs8J7WVe2vKGBp2dmGczq6m3XcgTamJWN8FVGYcVnDmBW"
+ "KzTccgrz/akwq1vjsQwODv68u+fyC691hmlg0pj6lw21pRJ9a52T7t65I/dSMglnz56lK319"
+ "3L5SCwh2eGSEqqqqVP9GbINkShHnRWJWrPKNP50mpfVOum+nQqtKJILN72VfQ0+CJeGSov2f"
+ "lj4QFMO6CLNGBVMsyK4z7Hp5RqF/fiaRo+sY/e27X0v5HTSo02fOcMchVN1cL5WFmr1k8WKu"
+ "JabDu++9R5s2baJldXWaNEfkG2XQ4t4KMqO1n2mPHR0dtPfxxyXpkyPHlBdv7qBf3qeQj/Ht"
+ "dMTI4EGKXkWCGgqtiMD+RBSQpVBYjt4LsUh/+LFCzy86RvfeuTPhd0eOHqXKykpqXrXK8Iyq"
+ "GqAydHd38/+TCers7MRmXl1bIPWQIyC2QTpePh2i+nskKpKjtT3XiLBEXOzP2l0SvXo2MUX4"
+ "v7AGYf26dXz5EVwguQ4lJSW0evVqGrlxIyWvvUxIVm+BBMQ2SMcN1s1Usz7MyiEdaVV5JELa"
+ "QqEQIR/r/dFCIzFvRHwIMhvL6i2QgNgGWVClbQxeLVCT5bgrQnwNVmKftbYuJUMA5Ng/8Wp4"
+ "vhXyZJMgX/kR+eDkwH+IsSDCGHBi7HFElQA5lkMoBYqkQyFQoiQosTTwPzQ4KUupefdmow1N"
+ "eu04o/ZflBwlLkhR4c0N1bEmo1VUijLfUuRYfPwai1iZe05J/JFJBTNLmEaMbEVnOUTF5ORE"
+ "WAQhFhxytMVIjmgrigor2mQkjQTNdZNKNP5ip0RT7Aq7x0EKpfP2i4IYnQfRKoiFBCgWOIpn"
+ "EbLlTwhXiS1c1Jof8XtHVBhxLScmUEWOq+1K4nikJvCWEwtlbqbzX52hSsytSFHDNJM89NY2"
+ "vRBpKVm+BwJBB10ZCGa1v+I1Pj35SRhzImHiBqIzNuYgbUloAHo0AZrv1sqLJOrqHKaPPp+l"
+ "J79eS0WLnRRgbMtxmVlIIFZioW4Ntfnm7QgdPXGb2WJual1VlnU9t56KFj/Wxro1oqAcHfjh"
+ "rpn7OqYI8CtpVAjYDxpKJerrH6MDH/SQ01PN76MShCJxY0+accZqcjKmm9ICWNc8E6ZPPx+h"
+ "xWVOqqr0UzgcWihiQ2VxCIGFWW2OsL4sjO0XGBPmujmFjxmyhoAM1Xki1HXhKr3wm8PMoJqv"
+ "YTJLI6LMq9LpgH462SDMdViIOJEfgSAT2CtvfEF914ZZTXekLI4XceopR3xanBwIKyRHSYpQ"
+ "TLVW5v+PH3vUhMUeBw0MjtDPfvV6quApNubEtZz4jMULxIqQTERCSLknHoy2ipdf/5BGR8e5"
+ "RZ9cDiFkPflJIAfdDLo1BJAUUkRrigoyIshSEbxs4Dp78iQ994Nfp62JiB8NKZKGnHy0nPia"
+ "mq41JT6jULz6gFu//eOf6Xz35TktLpkYPfkR4GPOayMKLQmEqMIjURkbwH1MpYLq62EDkJt7"
+ "qSWuLDhUDjot6zfRS7/7MT3/01dTvuu5LdOVSZneY/WigShhjgQuc2QQnmKr1GloXkgP6SbP"
+ "1yAPuId8YbpAlotTavr3n3uaystKExYQgijECycughZgmkRog1GFgI1pE0xjK2Kf3JGo1ibF"
+ "lAHepUmkiZyu8QjdW7uUfvGTZ+jFl44kfDfLIpwOzysE8RC1B1qQVeRkG7DFXqF0+Xn2mQep"
+ "ckkZjY2NJcQjbCe9O/QSVGli5EwxgRWz4GWkFcXI4FzgOUeUILXkQH/5x3WiR1uW0ws/eoR+"
+ "/9r5ue/Qpc3ENDZR+HhBxAvECmTqUsR3uIf1c3PeaXbP7XLQU09t59ra0ND1FILnFivqLIfI"
+ "R4ycCCNHptKIgwIsriIn7B2FT7YJPlwayAEw/rxxOUQbFpfRvkebuJ3DyWHxTrO0QmlU6bnf"
+ "WrgnNJmMdHmZH0eISoudtGVLLbtKNDDQnzYeYavIOsoRb+BGyZFTFQA55gCN9xxogRxTEL4Y"
+ "CdP6+iW0IzBB5T4HjYxH5hyt/Lk0Lcfqg4mS04/7cq71YFzylUjU2lRMdUtl3pVlgnDB6ClH"
+ "iiqda3SOyVTc5KcDw2EamF5Yfc0n0qnSAiBndnqYmutly3YsWDLNN8Oa0H8YMbdCC7tqlOgN"
+ "SwqeDtm80tDagip3DphR0fK+4jPTlEHe82ID2IqcvAonXbeaZ7LyTk4ytIhDDLxGZk2h8oaY"
+ "qmzH0wqj5DisXTSNtIQo9LYcYUvAcocdohdhpupinZh/0SLbrCEQcFUyfb2UKVD+IoclBHlY"
+ "dfC7HTTBSl5RlKqgq20DIAdr244eO5a5+4mbtXSka10xdbeMEdOUZlc41rVl22VnJuJ32nlY"
+ "pXM9u9FNn5x0Uv097AYzTvyuqG+thAVvzLfm1uhbA2DjhGPebm+EeFweV3R9nJ9VCP8nRHvq"
+ "pzJmMltXBYHhDDdcH7j//oxW+pkzZ/jCwYaGhpTfw+r/6OOPqbY2/aESSysrVe+yS04bcYug"
+ "Fgk77RobydW2ds2H67/47MG/du6klTsUWsMMrXLGhJ+Rwv4ljxR157glbV0fJ4ZdZ5Wou2aS"
+ "XW8zknrYjdP/JWq99Rltf6At4TfIGPp/CC7bumQ8gxWZKDxqeLoxAxuvbty4QTt37ky76xuG"
+ "5PT0NG+B6YCVoNjAhV121dXVqtdKC3KCzDbCcl614DvtBgf5Trsn9u6NVs+bDMdPn6346zmZ"
+ "rk/ltvlWemR6dNk0rd+8kcrSNMVr167x8w1cKgZoLxM4CMWa5HTdDuJwM4Fm8gz7Skupigkd"
+ "LWQhXOjuplFGclDlAX2CnNHRUU27DFCWhuXLsXA+usvAiKBx7OKu++7T7BZXAzWCKMrDNns1"
+ "ADFoMYcOH6Z9Tz6pW8a2U6UF7Cp4K1FYK21j2LblXLx4kW/LUOvL0gMM8Bhvmpub813ctLAl"
+ "OdhAhUPltm7dmtNzCMROMqR391135bvYKbAdOdhlhlN1rXihHojHiSEwUJEuVGc7wXZjDroy"
+ "qw/Xw+61dDvb8g1DLQeGoFiqapZHGYaYmpOoAsyYnQpkT7OYWdEl3oW1WaRn5iHjQh5G97Qa"
+ "Isdj0OloBH2DAWrvnKCJqcxz9P5SJ7Wt8dH65hLL8iWWRYFsj8Hx0hA5Pr+fG6CwbK1ekNHS"
+ "WEwkB+nwv69mfGbXtuXU0pSdGLPnkUDO1NSUJtdNOhgiB0fij9+6RctKS00nR43AWprKyOUM"
+ "04H3O1K+27d7EzWtKFMVj5m76IRDdfTmTU2um7RxGflxa2urhDd8IDNmFlDL0tWmFUvo2ae2"
+ "0szE9bmAz7ivZjmsmRA+NWiB8CxDPkbiM6ytVdfU8GNEkCGzCNIiNBCwuMJH3/7mLgpMj/Ir"
+ "PqudfzGLoPjJP9hO8GIbhWFy8HqSS5cu8YyZeRyKlsXfSLKxoZa+9519/MqXEpu0BUQLOWLq"
+ "4sL586a8tsUUI3RFQwN1dXXR2rVrudVt9OUN6ZbGZgOer6mu1Kw9GjUDxMQgiIFidLKjI2Vi"
+ "Ty9MMULx3hgcJ9zb28snrsweg9RC7x5MvRBdGcqM2dbuixf5kcVmvUfHNA8B3hsDTQXHX6EG"
+ "CZJwT+sKGas2TulZFyDKIsYXzLCirGgxWMtg5vtzTPWtIWN48xQciS0tLVzVRjcj5t/VnmZr"
+ "dasTaWab7xcGJogR0+M4wPU8G2PQldn6zVOAyODx48eV7gsX+Am3ONYKBVFjlInWZhWEwMXs"
+ "ZbZnJyYmuOGNo/AHBwd5+Xbv3p2T2pTzKhr/tsOx8fGsz6PQjzz8sOUv1MOhd2qMxor/97cd"
+ "xkNrAbAuAYfhzebwyOJ4gBwM5iDGyHx/LmC7+RzAyp1thXdTa4ReTUpvWgVyNECPEaoXBXI0"
+ "Il/bDu0G201TFzCPAjk2RoEcG6NAjo1RIMfGsCU5djoZN5+wHTlYTiS2+uUaydv87Abb2TmN"
+ "K1fS0NAQX/UpjtrKFZK3+dkNtuw/Dr71lrK2tdWSF+phFx0mCLHNL9/lTobtMiTQ0dGh9F29"
+ "qumFQlqRvM3PbvgfnhklmOdyrPoAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+aero_dock_pane_right = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAGcAAABlCAYAAABQif3yAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzoyMTozMiArMDEwMExUiZ4AAAAHdElNRQfZAxkQJBxqm5sb"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAD6VJREFUeNrtXVlsVNcZ"
+ "/mc89oztGWyDd8xgjDEGgx02BSVEkKRK8kCWkkWpIjVKX6pIbdVK6UP7UFWV2r60ah8aRbw0"
+ "SdUsDSFEJAW60SQCSlIMMXYwqwEb23gBY7zNfnu+O3PG1zN3PHebe2+V+dBhPHfuPcv/nfOf"
+ "/z/bdZANMTs7K/T19dG1a9doLhDIWTrFHg81NjbSkiVLnvT7/QetLrftMTMzI3xw4IBwpa9P"
+ "CAQCQiwWy1lA/EgH6fX39z9vddlT4bA6A6k4290t+LxeWrlypWlpXr9+naamp6l940ZbycNp"
+ "dQZSce3qVVq+fLmpaTY0NIjp2g22IycYCpHL5TI1TaSHdO0G25GTxzzy5DAIgmB1FmSRJ8fG"
+ "MFe5q4BZtdnhsJWBtgC2JAfEmKlq7ErQ154cpFNQUGB1kWXxtScHrcauBoEtyQHsKjAzYUty"
+ "zO5z7FoR8uTYGDkn59Lly8LN4WEKBoN0584dyiby0dFRMUSjUVME4HA6qdDlEtPc9/77i2YP"
+ "Nl15eTm53W6qraujNc3NOTXzckLO3r17W7ds3do7xgocDoVo3fr1VFRYSF6vN+uz+/fvp7Ky"
+ "MgqHw7ksdxKw1DweD1VXVdHTe/ZkvX96elrM28jICB0+fFioqq6mrVu25IQkw8k5e/asMHDj"
+ "BtXW1NDmTZs0xQGVZlbL4ekpBa9gFRUV1NraSkNDQ/TXQ4eEFQ0N1N7ebihJhpJz+vRpYW5u"
+ "jh595BFyOrWPDIEY09SaTlO6vr6eamtrqbOzUyz/5s2bDSPIsLG1M2fOCMUlJbRt2zZdxAAQ"
+ "ViwWMyWgEug1PlBelBvlhxyMkqkh5GD2MhKJ0NqWFkMyxYWmNqD/UPuMkZYhyg85QB5GxGcI"
+ "OYOsj7nnnnsMKaBWYPY0FI6pnkU12mSHHCAPI6CbnFOdncLGjRstHZ+qra2ja/3D9Ie9+8RP"
+ "fLcKkAPkAbnojUs3OWNjY2KnaBVgNd2emKY33/mUPCWV4ie+47pVgDwgF73QRc758+eF1U1N"
+ "lgkBBIyMB+iN9zqpxFeTDPiO61YSBLlAPnri0EXOTeaIVTHnzQr4fD4aHInQx58Mk8dbnRZw"
+ "Hb/jPitQyeSCUQc90OXnTE9NUXFxsekFLy0tpZGJIursnSJP8bKM93X2BqljrZfqK72iZ29q"
+ "HplZfffuXV1x6CIHy4kKCwtNLTQQCATIX1dOyyo8We8tZrdM3p40PY+Qi97lVrrIgT9i9BRv"
+ "kdst+h9w7BC/HPD7xO2biizEydnMow3IO/eNkK7RyJR/pbDdlMGqxkYaYbq6vq5OdOgW80OU"
+ "FB4EZFqkyAc9BwcHqdHE5b9KYTtyNmzYQAc+/FAcxseYVVFRUc7SwugyBi57z5+nbz71lNVF"
+ "T4Mh5BjtZT/15JMYAqFjx45RIBjMWeE9TJWt8PvF9Iwsg1Gq3nYth6OdedkIX2fkV3zmAEa1"
+ "Qt0tJz/fnw6j1Foylp6eHkHtNj94wGpHCGAdrWR6fv369SaJSj+Onfyc/nwuSsMzua2E9V4n"
+ "fbvNRZvaN4ozriI52HbX0dFBy+vrVVlHGNwDOWpaTog5ZoPMQurq6qInHn887XdYUN09PWLc"
+ "MHVzvVQWZvaypUtFK1EOT7z6BQmt99HO7QKtLnEQxkM8LEuQErwslyPeN6jpH+AAwPOKMLHB"
+ "TQ2xzzn2eXVOoH+cdJCz9wS9+52N5NCzzQ8CrKys1CQUbPXD8EZbW9uC68eOHxfjbF69WveM"
+ "qhKgMly6dEn8O5Wgz06cpN9O3ke/3CkQ6nGBM0GGGBzxz8S9aqqQwAP7LyqALIEisfi1MIv0"
+ "R0cF+nHF5+S0YpsfIG71YwRJgfEvrEFoYyoPy48wBJLrUFJSQmvWrKGx8fG0PL55LkYNDzio"
+ "KBav7blGlCXiYv+t2+Wg17vD5LRimx+ANEPMh+EGBQ9WrPdHC40mRiOkYZypmRqmw8w0d5BW"
+ "tdshpp03pW0My5xQsXbSQp/AaoNczrDBlZjkE8GR8rtDQ96FDAGIJf7QRY4eH2cxK0xUbzbZ"
+ "0ISxVfQFUZadAvQ9zrgRIPZBQtw4EBwaDAIhToKQSAN/w4JzSMSZJEeLkAWNzy2IQ/q8tBVZ"
+ "4NjKpRkTJMERF17SOEg0GbXVSBDmW0osEZ/4mYiY58LFM6Vl7kFgzyhtPeh0k50+axVyLYPH"
+ "o3ceRA2yrfiMst/CLDhZltysyZQwW3oO9q+QUGgJwtQQlFSTQjz+aMKkht/DpJQkySkVilqo"
+ "Ieb6UIgCIWfW54xojWrLwNOVFWRC5cC/qWY6bHxgjsoLHfO1XVjYHykJgpAeeFwRYV6BJMnR"
+ "FBQ8C2LOX5mk46fv0u270QUCSU1b7poZIVO6QDRCooNYVOCgm7eidPDoLbp4bowqipwLCNIT"
+ "opLACQR09Tmc4kzPulyFNDo+RZ9+PkTOwop0MmSEozkvOrBYuhBYKBYnCMM1k9MR2ndokL5f"
+ "WUgrl1dQ/4wQ78hVpCdtcYgXrQWf4Vg8njS1piUstkDc4XBS/41ReuO9/1IoMt+HKFGFMUlf"
+ "ZnbrSYUoPCbJmGSMIBiK0s9/c4R6Lw5QvTu+3jqmMuAf+hve+vB3RIjFW0+qWtOyQp8/l1pQ"
+ "eP+3bt2h19/657xpQly/ZlaL3BAwc5dBagtKU2tCvEZHZWyUn/3qLRoaHqOlzFJQo8aSVlqK"
+ "SuNGgWBUy0kVJKyfC5eu0u9efVtiGQvEu13pc6lpW9FyMuWFXwtHE2otQ+N6+Ye/pt4vvyQP"
+ "65OiMsKWC0lVxtVZQnWGovHAK4LY52AYP6RhjRUGKWdmZtLUQqO/nn7w8vP02h//llZTseaM"
+ "L1Xi3zmQB8SFkWKzzGkYLEgP6QZk5rL+NCbQskCYCdFFHc70nuW13/+EXJW1dHFS+WYvTlKY"
+ "NZ0gK2aAfZlhhsdkSCDGMX3E2oyfk6N1J5l0j4sUU1NTVLmsgl564Rv0l4PdC36TqsRU8BqL"
+ "OM0iJ1v/Fw2z8jDBBZCdlJHIX/z0Baqvq6JPRqOqhm+4+gqLxMTDLEtjJhonJCZtOVr3YEYT"
+ "m5zkBIm5Hn9DLb343DY68PeBpGWH+7EeTaoSOfjffPOUGZDr8xaAkYNaHYxS0rZ1FxXQK688"
+ "Rn5mrX08EBGvOVWYa5wcUZXF4nGLJLGoMGcUjkrI0SqMWIaWwzE0NCjujN55bx2d7g3Hna2U"
+ "liNrvpq4J1QK2XIwSc2wjiEUi48IlHld9PDDTTTlLaN3+kLkYqzwCTil4EYG4kQfE2QXoNow"
+ "8uBMmNRAsuVoGltbrMYlMDExQfVVS2g2WEzeYgcFZ8ML/By5lmPmopFUQyQNCR9nbE6g8ion"
+ "3dvhI1ruo5OjEXE4xykda1OITA4o0gHRUam1lmtghrO5IcaIGU2eL5BphMFKLJaXG7Mxevtm"
+ "hIpW+ah7wpxWbcrSKKioycnJjM8n/45fMKXg2fIih5tzMTo2IhDTbFTsyv2UhuUrPjNNGVie"
+ "FxvAEnKSQsgwtmYJbKBWU2F5y0mFGvHweSE9s6ZYGxdmpr0dTyt08UKaDdk1BCpqLt/4hEWQ"
+ "8Ju0IsL6Q6yh8y1ZIp++09wF5UiLVxOXmxUu204yIyHdTSa3ZVFpNUE8WNt2/MSJzH0Vu4eX"
+ "ySlXAROzoGWMmCaZXeEVRTEqZY/7ipymEORmTcVX6KQpVpxK5na4GletEo+nwt55PsakFBh9"
+ "RlBDKoiBULFpqSrDalElqgqVCWe44fOhBx9MyzevBD09PeLCQb/fn/Y88v6vo0eprk7+UIk9"
+ "K2bos54CanggSm7mlPiYheZlAVPVHla9mRypEOlocEL58I2HWeWIy+2Kr4/zMVJ8/yZxzbQL"
+ "b77Y/8EHgkvDTjJsbFrCap0abx4qaGh4mHp7e2nHjh0LfsMid+h/CC5bPnAPVowi32iBcn0G"
+ "8jc+Pk7bt2+X3fUNB3l2dlasLHLYtqmD2vpO0rtfbadV9wq0tsRB5YwJH9YSMDLcWDPtAEHq"
+ "VJ9IDPsMYo00I2iafWKSuI9d6P6CqHXyJG3t2DCvRbq6uoT+gQHZkdlMwC6DivJycYxNKXAo"
+ "3jLWYlrWrJH9/caNG+L5Bi4FHbSHCRyEYhxPrvUijkJGMkbP5eAtLaXqmpqMLRhAi/zPmW46"
+ "NFhC48HcKrfaUic93+qkbe1t4omIuiwBHLu4a+fOjIXXg5CCkwqLLNhmrwRozdAoh48coWef"
+ "eUazjG1nSnPYVfBmIr9W2sawbcu5fPmyuC1DywytUsDoQH/T3NxsdXFlYUtysIEKh8pt2bIl"
+ "p+cQ8F12SG/H/fdbXew02I4c7DLDqbpmvFAPxOPEEDioSHdNBgvSKtiuz4EqM/twPezsk9vZ"
+ "ZjV0tRy+ON3IN2lglELJSVQB5rDNBLKnWcw8xRLP4tYs0jPykHEuD717WnWR49Y56KgH/cMB"
+ "6vxqiqZmMo9O+EoLqH2tl9qaS0zLF4jhy63cOvtLXeR4fT7RAYWXbvaCjJbGYqJYiI58NpDx"
+ "nl1bV1BLU3ZijJ7HATlYzwdHVA90kYMj8e9MTtLy0lLDyVEisJamMnIVRGjfx11pvz27u4Oa"
+ "VpYpisfIKRM+oHrr9m2qrq7WF5eeh1tbWx14wwcyY2QB1SylbVq5jF56bgvNTd1MBnzHdSXL"
+ "eo0EP9sNViDOcIN89MSn21qrqa2l0bExMUNGEaRGaCBgaYWXXvzWLgrM3hI/8V3pNIZRBEkn"
+ "/+A71TCtohe6ycHrSa5cuSJmzMjjUNQsRkeSjf46+t53nxU/8d2oLSBqyOFTFxcvXDDktS2G"
+ "OKE4aAjzM+vWrRO9br0vb8i2UFEOuL+2plK19ajXDeATgyAGhtGXXV1pE3taYYgTivfG4Dhh"
+ "nDqFiSuj+yCl0LpqVSu4KkOZMdt66fJl8chio96jY9gIAd4bA0vl3LlzYg3iJOGa2hUyZm2c"
+ "0rJmgpeF9y+YYUVZ0WKwlsHI9+cYOraGjOHNUxhIbGlpEU1tqBl+yq3S02zNbnU8zWxnAHEH"
+ "E8Tw6XGshbjA+hioMlu/eQrgGTx16pRw6eJFcV0CzmRDQZQ4Zby1mQUucD57me1e7D2C440p"
+ "+uHhYbF8u3fvzkltynkVlb7tcOLOnaz3o9CPPfqo6S/UO/jRR4qcxor/97cdSqG2AFiXgMPw"
+ "gjk8slgKkIPOHMTome/PBWw3nwOYubMt/25qldBqSWlNK0+OCmhxQrUiT45KWLXt0G6w3TR1"
+ "HvPIk2Nj5MmxMfLk2Bh5cmwMW5Jjl5NxrYbtyJFug8w1pFsg9S5jygVs5+fo2QapFgteqNfY"
+ "aHXR02BL/YFtkOtaW015oR520WGC8Ok9e2wnC9tliEPLNki1QKvxr1hBHR0dtpTD/wDriTgZ"
+ "SBhbDwAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+aero_dock_pane_top = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAGcAAABlCAYAAABQif3yAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzoyMTozMiArMDEwMExUiZ4AAAAHdElNRQfZAxkQKSNpU8hr"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAEFhJREFUeNrtXWlsXNUV"
+ "Pm8W22OPYzu24yXxEscxzk621kDaAGVTFVqxCoRaxJ9WlSr6j1+V2p+tVLX9U1URUlNVXdgK"
+ "EhRCgYKgSShtFpw4qx3I6iReEie2x57tvZ7vzVz7eebNzNtm3kPyJ109+828e885313Oucsb"
+ "iTyISCSiHDzyOf3peIKGp+SildMa9tH31wVoZXvbi21tbT9wW+9MSG4LkInp6Wnl8Rc/J2XN"
+ "nXRfn0JdIYlCfL+MJS3ja4Cvfr76DOancEoi8R8Jvkb5OsvXKU6DEYU+/UQi3xcHaPdj7S8x"
+ "QU+7rb8WAbcFyMR/j/STtKqPfnFHkqoUifxszYAPZPDfTIwkpWqUmVoFgtD+ZAVJoQSI4hvb"
+ "JYUeu8dHL8z00dD5z57ir3iKHKMVsGTYcyxOnTskKkumjFpMgKRgUqa6h1Lleg2eI2dsRqGm"
+ "ComKN9IsBMppDfnUcr0Gz5GziHl4bswBUJuVHAmQyFyXp+j8LcYhtbxSNVOT8GTLwcCtKGlC"
+ "cE0bT0kzZLYDUpSFSc7436vwZMsBGXE2mo+vki/loamMpK+Skr5nEHKa0KQiPLa0ay0vbEFe"
+ "gyfJgbsrswVlad6YPjajTCk/WnWlTdR4lQC1lShz+Qm3mtSy/G6rrAtvkiOn3Fw/SEmnpOZz"
+ "lRwTLUd0ZSIYVVtNOikWuslSwZPkoLtJLqjhCwNPswOldvyaD0ZTZah5erRf8yQ5MFxc03Ik"
+ "zXiDq3oxUd0XEJJulXE5lZBfwqNNx5PkJLj/iSdT82gQEC1lriuT0/9bcQjSLVJc0ULVLBdb"
+ "jnGkxgSFr0gStyApVfPF6CCZdwiSmi5NzRctSE5l4lFuik/O4NCQcvXKFYpGozQxMVFw8N1z"
+ "gY2WSNVqdezxpQyrOgWa6NNnsuVox5lk2jlIpLtM0XJefe21vOKhyNraWiovL6fmlhZa3d1d"
+ "1Fn9opCze/fu3q3btp0cHRmheCxGa9aupbJgkMLhcMFn9/z2E3rpukJN3K8tLZeoOihRlV+i"
+ "CvZ2y5iooC81O+03YRYxCx1jdqJ8neYbk3GiGzE45xL9jfPayd977NFHC+Y1NTVF8Xicrl27"
+ "Rnv37lUaly2jbVu3FoUkx8k5evSocvHSJWpuaqItmzdbymOWW84UG66cI1AI6FfdLYkUf8rj"
+ "MkOO6NJATpTJmeUmM8PkRNjjmI4paqwTjyeNZcYQFayuro56e3tpeHiY3n7nHaVtxQrauHGj"
+ "oyQ5Ss7hw4eVmZkZevCBB8jnsz4zFOVaHWGCKlm6crYbNx61GxNdGRwF2SQ58MxinFc0nWaS"
+ "qTJAdtI4N1lobW2l5uZmOnTokKr/li1bHCPIsbm1I0eOKKHKStq+fbstYlRwTZ7mqj7Do/Ys"
+ "J9T4WDKV4rL5pD7LA4varaXzRIpwGRG+2iFHNSLrC72hP+zglE0dIefosWNKgkfx23p6nJEq"
+ "keraoolUbVdTOi5BDyScBW2C9xXmJpaU9T9X3XNZ04I0ZZBNcgSgP+wAeziRnyPkXOYx5vbb"
+ "b3dGwzRkTVIKJHR33+0I0IrpS+rVJxV+Rpu/k4AdYA8nYJucg4cOKRs2bCC/353JQzgG326V"
+ "6PjJL+gnL/xaveJ/M96co/KwHWAP2MVuXrbJGR0dVQdFt7BxaYCuXJugn//yVaqsblWv+B/3"
+ "3QLsAbvYhS1yTp06pazq6nLNCJvrAzR58Sr97FfvU3Vdx1zC/7iPz90C7AL72MnDFjlXORBr"
+ "bGx0RfmeGj9dPzdOL77yBYVr27MS7uPz2/h7bvRwDWyXEQ7C7cBW1ZqanKRQKFRyxTurfRQd"
+ "jtAHn82oXVku4PNvJqepu62KTtxIlFTGKnarb926ZSsPW+REYzEKBoPOa+bL36SvRhS6t6uK"
+ "WpsqC2YVrpToo7HcvnKxNlHALrCPHdgiR+bATjIzd28ADSGJqhCzlPlyGm6Wg8qP2eAhA9LP"
+ "jKema/RQwc9XBX1UnS7Xacg21yI8t2Tw3PoAfXTMT8u/wcbnCh8OSBxcEoXYNy73pyY+A+m5"
+ "tYQB3bGVd0mZxMGnRBWyQuX8fNCnUJlfoUbmrIpJqd8r0fc2e84U3iNn51130LqDn9Kfj/fR"
+ "mq8ptLrSR7VMSpjJCLGhy/mKjjRgYm4NDSfGCZs6p5nQCU7XufWdmeUAeh9Rr/wf+taOO9xW"
+ "PQuOkKM4vPnr7ef76P1/H6CX35NpKFK8NeTVPB79tNdH9z9zp6M6ONXVe67lCNz/jTs5uS2F"
+ "u/Dkjs+vOpxqhbZbDgRxulv7qsOpbm0ul4GBAeXcuXM0Mztr+GFEwGZnCCoqKqijvZ3Wrl1b"
+ "IlPZx4kTJ+j8hQs0a8I2MOzI6CgtW7bM8DMhtk1nZyetX79eEnnQ62+8oWzatImWt7ZSWVmZ"
+ "4cwwuQdyzLScGAdml4eHqb+/n77z8MNZn2N9/tjAgJo3ZnidjqMyEQgEqH7pUhhE9/M333qL"
+ "rNgGcgv7WLHNo488IklYGKoOh6mjo8O0Yii8oaHBklHOnz+vTm+sW7duwf19+/ereXavWmV/"
+ "RdUAUBkGBwfVvzMJOn78OC1ZssSSbayQo7XN5NQU+c59+SUtX7686EbIxIoVK+gcC6EFdrZg"
+ "D8I67vKw/QhTIMVOlZWVtHr1ahodG8uSEfK5ZhvmJYD5HzTtUgNlxqLRBV0i/nZjBhktNJlI"
+ "ZHXPkM8t24CXRVfaw3AtCFVdcFoYE7jtkGe2HLfkEXLYIsdOjJPPC1O7tyJ7aWb1LOVzAnPk"
+ "WMlIsfhcTgUyxp9SQ69MOxXQqn1ExQwIAaysPSj8jFHhMeiK76JwvZYh8rG7DmLWEPnk19pG"
+ "yF1IPqEb7GNWF61tfFqjmIUZYs4Px2g25iv4nBOt0awOotx8nwOQH3oUir+EfpZ6I81zgcwb"
+ "pjKiwoZElH/q7E06fDJOO7++lFrqKct9zmeQUiJft4bafP1WkvYfvsWxWJB6V9VQssA+XisV"
+ "Tduj2BpzxBiR69lAIEgjY5P08WfD5AvWLVBWSZ9k1iOq1OTkLDerBUg0PZNgfUZpaY2fljVU"
+ "UyIRz5exLV3mujUrSU73qXpJknx04dII/fGV/1FMs55spJXKmrGsVCkfcUIeAegDvaAf9MzU"
+ "XWsfKzYVZfm0AphNuQRAhDs+PkF7/vLBgrPkipJRETIqhhg8rcpjJWUSkU++OX7SR7OhH/SE"
+ "vnqV1ooe2hZsu+VkCoA+8/Tgl/Sb3/1V4xkrJIbdzNqhV3tL2XJyyaK9N/+deT1EZYOe0Fd4"
+ "cYUqrhF5BNQxB1PVMQt7rDBJOT09ndUtdLa30vM/eop+/4d/ZtUMrImIgVT8P9ddsAyKetIs"
+ "XjJ3Gp4XykO5mes1Qj7IheUCWQ5l6QM9a2uqFmwgBFHIF/ZBMgM4UMIbVMmBsQp5HnoQz2WS"
+ "Mzk5SQ31dfTcM/fRy28ey1I4sw8XELUHeZaKHCPjXy55oF9DfQ3duHFjQT4idrJq1yxX2hI5"
+ "eQTHWkb7imZ69snt9MZ7F+c8O3wfB4y0TV9rCK1BSoFcXYr4DPcg79zsNN8LBnz0JOsFb+3a"
+ "tatZBIMctICkRT2EHAE7xpBztByB4eHLVFNTw/FNixrnKEp2y9F71mqNs4tcsszLjE2Iftqy"
+ "pUXdjAj99CBiFdmCHtoA114QmqPGaYEm39q4hCLREIVZoWgkviDO0Ws5pdw0kumIZHw4px/G"
+ "Jey77u0KsT6yqlcuiCkYK3pkudLFBlY4u1fITMyIqqQwSrar6u6igZ4rLQC5IT/0gD6lQEm2"
+ "RqFp37x5M+fzc3+nbpRE8UKy6Olnxqt1oqK5vuMz15KB67J4AK6QM2eEHHNrrkCvB3CZLNdb"
+ "TibMmEMMvHZWTeHyxtlVdus0eD4EhJKlhtYh0N4zChFLIHJHHGIVCR4PsU+sesmSrPLd7uQC"
+ "5awcBmz416WIyucCNC5T78ii0WqCfLC3bf+BA7m7H82qpU+vAqbd3RompkvnVDjkc8s24CXQ"
+ "uXKl+noqnJ0Xc0xGgagZyYzgKBxGxduWGnPsFjXSVcFgeIcbrvfec0/OKH1gYEDdONje3p71"
+ "PGT/14cfUktLi24ZkO/ayAi18ucJnX1t+YwsbGNm3xvkxV7yy5cvq3umAxs3bJD+/vrrCjLB"
+ "24/M7AeeZeNgu6qZKBhKDl+5QidPnqQdO3Ys+AyCof+H4QrJge9gRybkRg3XGzMg39jYGPX1"
+ "9eme+kYgGYlE1MqiB+wE3bdvHwW5jKamJsO2EeTEuLLDPkaBxqHa5tQpvPttvnr29/crFy5e"
+ "NLWTHqcM6mpr1Tkko8BL8eq5Rvaw4nq4dOmS+n6DgIEBuoINDkIxj6fXepFHkA2aa2Y4XFVF"
+ "y9jojQX2e58ZHKRxJjkWN/ZLIYKc8fFxU6cMoEt7Wxs2zs+fMrAKvHbx7p07TU+LG4ERQ5QV"
+ "45i9AwAxaDF7332Xnnj8ccs29pwrLeBVw5cSi3ulPQzPtpyhoSH1WIaVFVqjwACP8aa7u9tt"
+ "dXXhSXJwgAovldu6dasp79EsxEkylLfjrrvcVjsLniMHp8zwVl0rp8nMAsSv5HgCASrKXZ3D"
+ "g3QLnhtz0JWV+uV6OL2md7LNbdhqOWJzeqHN4GaAQMzIm6hmowpNzxYuM1QuUWVFfm8W5cUN"
+ "xjBGIOxh90yrLXLKbU462sGFK7N06PgkTU7nnp2orvLTxtvCtK678Ku/nILYFgWyy22Ol7bI"
+ "CVdXqwEoIttSb8jo6QwRyTF695OLOb9z97Y26ukqTIzT60ggB/v5zEzd6MEWOXgl/sTNm7S8"
+ "qspxcowYrKerhgL+BL36j/6sz57YtYm6OmoM5ePkkomYUB2/ft3U1I1uXnYe7u3tlfALHxDG"
+ "SQXNbF3t6qin557cSjOTV+cS/sd9I9thnYSYU4MXiJll2MdOfra9tabmZvU1IhDIKYLMGA0E"
+ "LK0L07NP302zkXH1iv+NLmM4RZB28Q+xE2ax7cI2Ofh5krNnz6qCOfk6FDObv1FkZ3sL/fiH"
+ "T6hX/O/UERAz5IilizOnTzvysy2OBKF40RDWZ9asWaNG3fl2gRolxuzKI77f3NRg2nu0GwaI"
+ "hUEQA8fo8/7+rIU9q3AkCMXvxlSxU4C3TmHhyukxyCis7lq1CtGVQWestg4ODamvLHbqd3Qc"
+ "myHA78bAU8Hrr1CDBEm4Z3aHTKkOTlnZFyB0EeMLVlihK1oM9jI4+fs5js6tQTD88hQmEnt6"
+ "elRXG92MWH83Ygy7W52sQJRZaL1fBJggRiyPYy/EaR5j0JV5+penACHgwYMHlcEzZ9R9CXit"
+ "FRQxEpSJ1lYqCIOL1ctC38XZIwTeWKK/wmEE9Nu1a1dRalPRq6j21w5vTEwU/D6UfujBBx2d"
+ "68oHseMFL70zEjTWfdV/7VALswpgXwJehgcySwGQg8EcxNhZ7y8GPLeeA5TyZJuTM+pOw7Pk"
+ "lOpMaK7zqV6AJ8mxEoRaxSI5JuHWsUOvwXPL1IuYxyI5HsYiOR7GIjkexiI5HoYnyfHSm3Hd"
+ "hOfI0R6DLDYyj/l5DZ6Lc+wcgzSLzGN+XoMn+w8cg1zT22v6GKRZgHycosMCIY75ua13Jjwn"
+ "kICVY5BmkXnMz2v4P+EM9joepX/9AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+aero_down = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo1MTo0MyArMDEwMMndnrAAAAAHdElNRQfZAxkQNALaVrQp"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAhJJREFUeNrtl01v2kAQ"
+ "ht81FgECjUQUyeKjBrfi0EOJktxzg0uOSaWe0lNP/Wk99lBy7A+oSiO1ORE+BChSTjGfBuPs"
+ "rATCNSkmyHtpX2ll2czOs+OdWTMMXIPBwKnVaqjX6xiORghK0UgEuVwOhmEgFosx1u/3ncrV"
+ "FYrFItKpFMLhcGBwy7LQ7nRQrVZRLpXAfl5fO4l4HLquBwb9U41GA2avB6V+e4t0Oi0NTMpk"
+ "MiCuOuavQlXVtRNGFs+NobPWLhphiO783YZ4gut3tc3OEN9/9fDQt5+0ebEbwttCHG9eR335"
+ "9A0v5LhDx0LlW+tJm6OTLAr59WDHcTaDiwXk96AqNj5/+eH57fzsEIa+t4k7KMur8TMMPYkP"
+ "744xMO8Wg+7puZ/5HrhfMI3ZbIb9ZByX708xHt6LK93Tc78+XHu+alXrlNdT+PTxgpepBtu2"
+ "fc8nu1AotB18Op1C0w7EdRMxxrwJtyn8uXOW9ezIt5ErctlwT+SUrTKkKIo7cvrUTSYTKXDK"
+ "dEo6V+RULrLkipxeuSy4p9QILmvP5yfhAi4z4VbCZZXaMkfZws/W+g//R+Hz4046fIe3R3S6"
+ "0YEftChIOtuJR1zRLvHiQ4r3afRxCbLeCRzhzWK73Rb/gNRXvGP8WqmILkLTtEAbRQqu0+3i"
+ "980NyuUyxGabpila5GarhVGALTJF/TKbFS1yIpFgj6VqglrJraorAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+aero_down_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo1NDo1OSArMDEwMEcuCiQAAAAHdElNRQfZAxkQNxVyqGIt"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAABENJREFUeNrtV02IHEUU"
+ "/qq6529nFnezLtGNEEk0O5NZI4GoQaLxoCJ4NgjBgAe9K/5c9SToQbx6UaJgQLyJXgIRDUkk"
+ "t+iS1YDgwSWHMGOyO7Mz0z/l97qqZ3vGnd0ZYb1oDY9XXT39vve+eu9VtwJHo9H4+ufrK8+f"
+ "XQ6xuh5jt8ZCReNM3Ue9uvjl3NzcKUXgH06fvX7C1B7H08cNDpQUSvxjXlGofWqPWo8JYCiR"
+ "CCchdZe6Q71OudE2uPy9gv7tEj57qXpeXbh4yXzQfAzvnTQoGwWPKL4WMM4JrERgZdwhDgh/"
+ "sRExCMURLhjOu1rjrW8M3tz3I/QnPwW4/4RCPrIPjRpaWad2Er2Nl+JELoox+xwguP6tDYOD"
+ "RYW4sz1wnjzeaW3nnh2VKQXDvYpH/FUYWShpLBPXH4fGPCNaudHC+ctNNG6HI/+35y4fTx6b"
+ "wZGlaYTRznb91BszQmR0aKhWrUDo+fSrX0YaO/XsImqHp9HK+GcyOq2jOM6CG0kGByhabmo7"
+ "ly1kHqJNg/X6PF7xAnz48Xd/A37t1adwqDqP9cAM2jIZ+0NbkVSQgAUuI6VE0lLpZ2xs9Z2e"
+ "waHFBbz7xjNYa/7eF7mWdbkfG/QlGpqL/SDeZEDbyPlQbKx2YuhRMocTt367F+PevTN45+0X"
+ "0F5bTbRcy3r/WQzZyNplJIO0x7YMPIp2ks2XpM4zJXQr9FCvHcBH77+OBw7ux83OYJmmVKcM"
+ "JlE7SbekD57SnaUs21iGu5s8vLoBzNy3P9HDI7vnm83GYqg0w7MJF2QiV8YhO52oLep2Y0Q5"
+ "DQA6VgO332IvNNnIaSSIbB/3XaR9qmN3PUF/jV3kUZrA8WbCqeFSs3tiqEXY043tUHG6O2rr"
+ "yEcNM1QtiV1hwLW9NNtt5KH1Ktl7bR9Mki6lHtv37K0iz+5zWr6h29KByM81DPaS9z0Fhemc"
+ "QpnHWdGzbTWn7enmTQCenmI9onepW1xYC4Amy1Hx9wVtnUzBO4x8nTcKSicLXpKuPCA8m7GT"
+ "gKeUC3iX4NKaNwjeZka3erbWgyDajLwb2PY5xasC1xl8QnNKtSRiPCG4ZHaPtrpOpDIEQ4KJ"
+ "ogztkuotulrmYpEbnReqo836NhOCJ22UKD2JPpLorbRDY50bAA8t9V1Kj1T3tHt9cm8xySEz"
+ "IXjax/sMOIxkDIDDlQV2Pl7HAd9KUtvZMe574a6M/8H/q+D63/Mii+Pfzc+jMmugwka+2w4U"
+ "WdjlnMY054Lrv/xQDheuedj3RIQSi7/C7lLJASV2mIJnDxb/H/T2gC2xyN5e4PM5HpF5vqnM"
+ "c71M0LlvFc4c9eEfXTq8Ur96pfr58nHUHjV4cEpjhqAVgvHDgocNHYDteOOCy6nGMwT8KEGL"
+ "rP5JadCjX/mu98dFoBpfwbGHl2z3bDab5uq1ZZxbiXGztXufyPeUNV6sajxypI7Z2Vn1F7X+"
+ "m7ZM/KBNAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+aero_down_focus_single = aero_down_focus
+
+#----------------------------------------------------------------------
+aero_down_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo1MTo0MyArMDEwMMndnrAAAAAHdElNRQfZAxkQNALaVrQp"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAhJJREFUeNrtl01v2kAQ"
+ "ht81FgECjUQUyeKjBrfi0EOJktxzg0uOSaWe0lNP/Wk99lBy7A+oSiO1ORE+BChSTjGfBuPs"
+ "rATCNSkmyHtpX2ll2czOs+OdWTMMXIPBwKnVaqjX6xiORghK0UgEuVwOhmEgFosx1u/3ncrV"
+ "FYrFItKpFMLhcGBwy7LQ7nRQrVZRLpXAfl5fO4l4HLquBwb9U41GA2avB6V+e4t0Oi0NTMpk"
+ "MiCuOuavQlXVtRNGFs+NobPWLhphiO783YZ4gut3tc3OEN9/9fDQt5+0ebEbwttCHG9eR335"
+ "9A0v5LhDx0LlW+tJm6OTLAr59WDHcTaDiwXk96AqNj5/+eH57fzsEIa+t4k7KMur8TMMPYkP"
+ "744xMO8Wg+7puZ/5HrhfMI3ZbIb9ZByX708xHt6LK93Tc78+XHu+alXrlNdT+PTxgpepBtu2"
+ "fc8nu1AotB18Op1C0w7EdRMxxrwJtyn8uXOW9ezIt5ErctlwT+SUrTKkKIo7cvrUTSYTKXDK"
+ "dEo6V+RULrLkipxeuSy4p9QILmvP5yfhAi4z4VbCZZXaMkfZws/W+g//R+Hz4046fIe3R3S6"
+ "0YEftChIOtuJR1zRLvHiQ4r3afRxCbLeCRzhzWK73Rb/gNRXvGP8WqmILkLTtEAbRQqu0+3i"
+ "980NyuUyxGabpila5GarhVGALTJF/TKbFS1yIpFgj6VqglrJraorAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+aero_left = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo0NDo0MCArMDEwMN+SkKkAAAAHdElNRQfZAxkQMBKjjWFJ"
+ "AAAACXBIWXMAAAsRAAALEQF/ZF+RAAAABGdBTUEAALGPC/xhBQAAAkJJREFUeNrtV02P0lAU"
+ "PS2lUEIlkxlHpCAEZ89Ol27M8A/czMK4duO/caeJiSZu3SgTN25M3DhBFkMmDhQJEK0apnwM"
+ "0wK1t+Z1YOqyr2w8yWuT95qcc9+97/UeAS6m06nTarWg6zrOZzPwhJJMolQqoVwuI5VKCcJk"
+ "MnFqh4eoVCrQcjnIssxVgGVZ6PX7qNfrqO7vQ/jSaDhqOo1isciV+Co6nQ5G4zFEvd2GpmmR"
+ "khPy+TyIW7xwt0SSpMgFECdxi5EzX8HGBDiOs1kBDH7ymaKoIAjCpQAiXy6XXAlFUfR4aBA5"
+ "EyBGET2R630LM+tvxpmQNQG8BpE3T8/w8cjEb3MREMe1BuLxOL4bY3z4NIAob/nzq1x+DYQt"
+ "IBaLodM18PpNA0p6Fwn5kpzqjXZmTUCYRUiR//x1hucv3yOl3lhbY4Gyd+g7QJGffG3jxau3"
+ "SCg7gXUWLH3nC6BfJI2wUC4V8OTxAZ4+qwXWiGexWPgp8J40EeYwTRM72xk8OrgfEMC+CRzD"
+ "sEUYhoFi4ToePriDuBTzBdD20zqrOWl1Mmz0ej1kMhncu3sTn5u2XwORHEOG4XAIbfcazm0F"
+ "aUXExdQO3oS8MXZbrz1t6ZL/gG3ba2uRtEKUYirMf2Hj/cB/AZ4A1hxsREDCdUKrVyNvULD0"
+ "HyBO4vackXsokXNtGR0R3t0RkSddf0iX1Hw+h3TbNYnvajXPKGSzWe7ekILsDwY4bjZRrVbh"
+ "JX80Gnnu+Fu3ixlnd0zR3yoUPHesqqrwB18A5ik1mQXQAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+aero_left_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo0NjozNCArMDEwMCXtbZ4AAAAHdElNRQfZAxkQLw561jOY"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAABAVJREFUeNrtV02IHEUY"
+ "fVXTO70/M+yOExNd4oIRkgljDIiyQZR4FD0rQlDw6E1RDwkoIqiHXLzlKK4Iwb2peFDJHgxx"
+ "dS+LcTMhhw0qJkvG7Jjsz8xOd1f5qqu6p9eNMB2Y9WLBm6+nf+p79X2vvqoSYFtdXf3ql8bl"
+ "52aWQlxbVxhkmyxJvFz3UK8dmq1Wqy8IOv/+xEzjSV17AsePaTw0KjDCF4cFUKQtEB6vJSz6"
+ "bWYYERFqoEvbpW3TXm1rfDsvIBsX8OlLte/E3PkL+vTqNN4/rlGCQEE6hzGEta5TkYOATsCf"
+ "SBtCGqGy9wJ2+vo5jbcqP0J+fDHA/qcEisqyHnSL6MTjz+GnBYxv+SdDso/x1rvgPBudvb6A"
+ "8Z0nrQNpXsJIZaxBNt/a/c8bJf0vME3pDAGlbG4ieikYLUgrPOV6MULU4i5EqK0j7XyYazMz"
+ "RGYkXsImhbAvpIJ0Q8/jHM55MmLl+out6hFMCUR8OyCksiMX0kYj7gV26CInCZVxbvofKQhs"
+ "0Jq6IPkkISKTFKQRcB9plWGtt+ujH8QRcBgfEmj+3sYe1hVTY0J3PyUQhYiLhHkQa8Hlalvo"
+ "7hITRYErl5r44txNrNyMUGQkEpKZFLBUKiu2AjKhduKLLXKKkB9MjQn89kcLs18vo+Dvi++b"
+ "gQZRTwtecjMk3UiaHAlb97VlGidfO2306dy8N+krNK5cx+kz51GamMKo77TB3Ea6Nw1lEoFA"
+ "WSKR00SaBpU/Dff4EteuN/HOB5/dUZyh01hKwITEpMDAEAl0EpV/6KIPDDPHlxYX8eprH94x"
+ "Oqb/bmT7TFMw09SodgJUWJ/HKZoSpWqmjU9BDMWrI1dJt0L20w7Wj+LMRyfxxtuf7Hi2fFvh"
+ "V+45vuTYp9IUBMAaZ8IGmW0SbaKjLLZULzr9ovFXhMn778V7p07sIGD62wyxvQ6ABDZC+6BD"
+ "bEUWXYdA5UOH33yzAhw++ADeffMZ+MVCSsD013YzIUMgIgHFkWt+TFBJW6TYpQ2IxOaB6efz"
+ "qwHWS+N4/tkDGC95lgCfbdJXkNUA1E7RKbcoZStknqacKBeaIer7q5jurGGC+8Em05Msfr0I"
+ "DLgttRRGDpQxe4Ob3s3tQ/F2g4BJ7Q90fivYuaP4z3dE/xOQye9uMjG+ksrg7RkRGKMwy0W5"
+ "KyR8yr7M+r5GPRrf3itHhjC3WODhJILPyVv27FowSgy7tWAo51pgmqkBoVtlhyPEffmePX+U"
+ "6bg8h/iM6D16pH6jvjC/9+zSMTw4rXGIZ8MJeivTMS/hmzOiMCTypSl2Trulbeldp71NIsu8"
+ "cfEnoHZrHo8dfdjuMVqtll74eQlnLyusbAz2gHbfmMSLNYnHH6mjUqmIvwGdqbciWIcx6wAA"
+ "AABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+aero_left_focus_single = aero_left_focus
+
+#----------------------------------------------------------------------
+aero_left_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo0NDo0MCArMDEwMN+SkKkAAAAHdElNRQfZAxkQMBKjjWFJ"
+ "AAAACXBIWXMAAAsRAAALEQF/ZF+RAAAABGdBTUEAALGPC/xhBQAAAkJJREFUeNrtV02P0lAU"
+ "PS2lUEIlkxlHpCAEZ89Ol27M8A/czMK4duO/caeJiSZu3SgTN25M3DhBFkMmDhQJEK0apnwM"
+ "0wK1t+Z1YOqyr2w8yWuT95qcc9+97/UeAS6m06nTarWg6zrOZzPwhJJMolQqoVwuI5VKCcJk"
+ "MnFqh4eoVCrQcjnIssxVgGVZ6PX7qNfrqO7vQ/jSaDhqOo1isciV+Co6nQ5G4zFEvd2GpmmR"
+ "khPy+TyIW7xwt0SSpMgFECdxi5EzX8HGBDiOs1kBDH7ymaKoIAjCpQAiXy6XXAlFUfR4aBA5"
+ "EyBGET2R630LM+tvxpmQNQG8BpE3T8/w8cjEb3MREMe1BuLxOL4bY3z4NIAob/nzq1x+DYQt"
+ "IBaLodM18PpNA0p6Fwn5kpzqjXZmTUCYRUiR//x1hucv3yOl3lhbY4Gyd+g7QJGffG3jxau3"
+ "SCg7gXUWLH3nC6BfJI2wUC4V8OTxAZ4+qwXWiGexWPgp8J40EeYwTRM72xk8OrgfEMC+CRzD"
+ "sEUYhoFi4ToePriDuBTzBdD20zqrOWl1Mmz0ej1kMhncu3sTn5u2XwORHEOG4XAIbfcazm0F"
+ "aUXExdQO3oS8MXZbrz1t6ZL/gG3ba2uRtEKUYirMf2Hj/cB/AZ4A1hxsREDCdUKrVyNvULD0"
+ "HyBO4vackXsokXNtGR0R3t0RkSddf0iX1Hw+h3TbNYnvajXPKGSzWe7ekILsDwY4bjZRrVbh"
+ "JX80Gnnu+Fu3ixlnd0zR3yoUPHesqqrwB18A5ik1mQXQAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+aero_right = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo0NToxOCArMDEwMEtfu5QAAAAHdElNRQfZAxkQLyM/CW/t"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAkpJREFUeNrtVz2PEkEY"
+ "fnbZQ+AgGD+R5YSAxVkRLfwF5vgH11xlbeNPsbE2Ftf4C+RiY2OijeGu8GIusEjgiJ4Ej689"
+ "YHedd8zgsBgt3Fkan+TNZnY3eZ55v2ZeDQzj8dir1+uwLAsT24ZKxGMxFAoFFItFJBIJTRuN"
+ "Rl714ADlchlmNotoNKpUwHQ6RbvTQa1WQ2VnB9rh0ZGXSiaRz+eVEvvRbDYxGA6hW40GTNMM"
+ "lZyQy+VA3PoFc4lhGKELIE7i1kNn9mFtAjzPW68AgUXwhaKwoGnaLwFE7rru4gOZWKsiFwJ0"
+ "/+7tqQ6rw7JTVxcd4hOchvyCVPXOHbz9cA57soHtUhqO4yjxgMBSDogPo4mDN+/OcCVt4Ob1"
+ "JGazmTJvLEIgu4Uwmzt48fI9mq2vPBzyP/9qlF9LZeh/KeP5/mucffuOSCTC/wnCBOcfPSDj"
+ "6bN9fDppBOYJucJ4DtARSfbzKI6vCHjyeA+X05sYstMrCJA3RZVxAZTpwvx4tPcQ166m0ev1"
+ "Ak2+lTIkctk1G0YEu7sPeBV0u91AyQmCyxALEiBUbcYjuH/vFnsC7XY7cHK5yS01Iqr3ZELH"
+ "3VIc5g0X/X4/cHKx4d+ehiTgYvwFd0w3sIT7G1auQiRCZefzY+33gf8CuAD5eAxdwCXWfqkH"
+ "qLyAyKDNUismTuLmkxErSmTZWEbZr/puSOQxNh9Sg5vP5zBKbEh8Va3yQSGTySifDWmTndNT"
+ "fDw+RqVSAQ/+YDDg0/HnVgu24umYdn97a4tPx6lUSvsBjEDOU65zEi4AAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+aero_right_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo0ODo0NiArMDEwMKZ+RR0AAAAHdElNRQfZAxkQMQU5RdXP"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAA/ZJREFUeNrtV09oVEcY"
+ "/83sy27UfZhtNLWxKNaDK6sNlJZIabHgpdB7KYiCR28W7EEPIkLbgz1481hIaSt4a6UUWkyh"
+ "Imm9hKbpSg7pIUVjotnGJG5235uZft+bmc1bk8A+NTn1W743b98bvt9vvn9vRoBkbm7uxp/V"
+ "ux8Mjce4t6ixkdJflDhZCVApH7je29v7oSDwX48PVd8x5bdx9IjB/q0CW2hitwDyNOZIA7qX"
+ "sNqp8DIUaWyAJo1NGus0/l03+GlEQFZv46sT5Z/F8K3b5vLcID49alCEQE46wESFHZ1RkYGA"
+ "8UoXZZiQQazts4iMfnzT4JPSb5BfjkV49V2BvLasN1oUgQR0OfieAGPLh+SSl8nfZhPA097p"
+ "KwgwdpawbogEnpFOjazpeBv3P6uXzDrKok2KgNY2NopQcpwL0iaedlY4EY14hiQ0Fsg4DL7n"
+ "yhCplQSeTUuFndBKSLf0LOBw4H7F2tlLRr1CsEVA0eyIVNLLAi19K9VhnWvHOOc7UllI6BQ4"
+ "21euHLkvSHrjiUgfAp7I9d9H/n44VUdPl1hhbdrzoxM1ZrV6W7FfmyegYiRNIp8TmH6k8N3N"
+ "R5j4axalvGwj8TyqUupJrhDgdqktCZb5xRjXf5jEvw9q2EutudXNMgKyPT96jVgV2kNgX1Jc"
+ "Ur2w0VS4+MWPqE5Mob+giAS9z6j84/jrVC7ERrcW0+aByJXi03Lhs69x7/4sXqLszOIBg7Xd"
+ "7xPRpD3ALklCsE6nOX3mc1RHR9FNOaLWMLiWxs5e7O4jF+amsuoXm5Th0KxB73JEEwMMyNXF"
+ "dvXKOQQ7dmFiXnVchp5IRC5oENgy/VmiZJ+n7zKtA9/T2ve0+kAELNDLZY1VH/1L54+j/5Wd"
+ "+GVGZWrF3tVRAm71CWEsKQuq0x4AEWB2DdV6gkI+h7Nn38ee3SXcmIptvDJ0Ik8gcbu2thMi"
+ "ZIr3HJFqI6CIgKaJtvNtLwY4duw1LBS349vJJgJC9puULASiBNwkMW/QAw4Dd1jpynGFgKvR"
+ "Wfo+9+yUGBwIgd0hRmbipDXL9LehQ1mvCTEOL0alq8DLP080vpmOkd8XYqzWecI9j6zakEzX"
+ "NW49iFGPs6TcCySw2fI/Aemvm8mEsXLuPtixRWAblURI3/7NIFGgwg+7JBYoxxk7OHW4C8Oj"
+ "OTqcKBSoaEMq0iIpb8u6iSbNRRedkHLP0Ih8K+6mimZbhcCeP0ICDoeRnBGDNw5XZip3Rvqu"
+ "jR/BvkGDA7QB6SG0kPeGBFjgM6JgEtnClIDT2OAzIZFYpPExEZmkB2O/A+X5Ebw5cMjuM2u1"
+ "mrnzxziu3dWYXtrYA9qubRIflSXeer2CUqkk/gNN/sDRnOMoBAAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+aero_right_focus_single = aero_right_focus
+
+#----------------------------------------------------------------------
+aero_right_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo0NToxOCArMDEwMEtfu5QAAAAHdElNRQfZAxkQLyM/CW/t"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAkpJREFUeNrtVz2PEkEY"
+ "fnbZQ+AgGD+R5YSAxVkRLfwF5vgH11xlbeNPsbE2Ftf4C+RiY2OijeGu8GIusEjgiJ4Ej689"
+ "YHedd8zgsBgt3Fkan+TNZnY3eZ55v2ZeDQzj8dir1+uwLAsT24ZKxGMxFAoFFItFJBIJTRuN"
+ "Rl714ADlchlmNotoNKpUwHQ6RbvTQa1WQ2VnB9rh0ZGXSiaRz+eVEvvRbDYxGA6hW40GTNMM"
+ "lZyQy+VA3PoFc4lhGKELIE7i1kNn9mFtAjzPW68AgUXwhaKwoGnaLwFE7rru4gOZWKsiFwJ0"
+ "/+7tqQ6rw7JTVxcd4hOchvyCVPXOHbz9cA57soHtUhqO4yjxgMBSDogPo4mDN+/OcCVt4Ob1"
+ "JGazmTJvLEIgu4Uwmzt48fI9mq2vPBzyP/9qlF9LZeh/KeP5/mucffuOSCTC/wnCBOcfPSDj"
+ "6bN9fDppBOYJucJ4DtARSfbzKI6vCHjyeA+X05sYstMrCJA3RZVxAZTpwvx4tPcQ166m0ev1"
+ "Ak2+lTIkctk1G0YEu7sPeBV0u91AyQmCyxALEiBUbcYjuH/vFnsC7XY7cHK5yS01Iqr3ZELH"
+ "3VIc5g0X/X4/cHKx4d+ehiTgYvwFd0w3sIT7G1auQiRCZefzY+33gf8CuAD5eAxdwCXWfqkH"
+ "qLyAyKDNUismTuLmkxErSmTZWEbZr/puSOQxNh9Sg5vP5zBKbEh8Va3yQSGTySifDWmTndNT"
+ "fDw+RqVSAQ/+YDDg0/HnVgu24umYdn97a4tPx6lUSvsBjEDOU65zEi4AAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+aero_tab = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAMAAACxiD++AAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFq6ysra6urq+vr7CwsLGxsbKysrOzs7S0tLS0tLW1tba2tre3t7i4uLm5uru7vL29"
+ "v8DAwMDAwsPDxMXFxsbGycrKzc3Nzc7Ozs/P09TU19fX2dnZ2tra29vb3Nzc3N3d3t7e4ODg"
+ "4uLi4+Pj4+Tk5OTk5OXl5ubm5+fn6Ojo6enp6+vr7Ozs7e3t7e7u7+/v8fHx8vLy8/Pz9PT0"
+ "9fX19vb29vf3+Pj4+fn5+vr6+/v7/Pz8/f39/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAA0PbvAwAAABh0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjM2"
+ "qefiJQAAAP9JREFUOE+t0tlSwjAUgOFjZQuxuOBSFURSSOyq0qYNEd//tUzCaIeLk9743Zyb"
+ "f5LOSUH3AC3vyEWIuIw06KvHRmGqKIJ3+u1RzaD0BpL+S3DwfIO5oqAHDxPk1LOpr9oGe0/h"
+ "ArXHmSCjLbpIpSobyBa3o5DSWqJaF+xqlPykEE/LHFWmU2AkS1GZCdYkFajkjZhAxCghCLwS"
+ "zlCcE1j1BpOeE176gqU/mMBy3F0Rb/mpZENh0QWxyJNTfD6HRXfFthgNndFgcJzDa2aCv0WZ"
+ "tUj7blLdP9nZ6PCZATtPft+qjELt/vAm/HCzCNYmuA2O5xqzmzOwAuIG0AfGfgDFvqY+8bKe"
+ "lgAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+aero_tab_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAIAAAAJNFjbAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "ABh0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjM2qefiJQAABPtJREFUSEu9ldtPI2UYxovR"
+ "jZd65Z3xxv/AO2/0wnihiZpodgV21cSsiyYbs8ZkiQQSDUaynBaIB0ACLOsegJaWlkNpObSW"
+ "XQ5dlgUqPQ3DtPRIW9pO5/DNtPGZFjeVte2F4uTtxcz3e96n7/t+802VJEkqlapx2LQXE589"
+ "80xVVRVu//319FO5F587c/Xc6yoYXOrW983vzrqOrExqPcBuRTLOQ94T5/cSApMU/EnxIFUh"
+ "wIAEDxW0jyKZRSr+Vv3d724YFYPaDn2Iyy5H5I2Y/MeR7EllaTbrz2QDXC7E5yJ8LlopwIAE"
+ "DxW0yOBOylOO8CedOlUikfio0wAD239tYPEkatu0qng8/j8ZWCPyg5i8cyS78y3y/dWicL5L"
+ "5QNMoUVQQYsMzqR8XEEsHr/QaQhksosheS0qbyVkZzJLpbP7yhgUTYjLQV8+wOQHkIMKWmTA"
+ "LJcKLSoYYDimgHw/Ij9U5qxMiU5nGTZ3AI+M4lE+wIAEDxW0yLCdkBeODWIxGDCsPOUn1jBZ"
+ "P5TyRcjelEynZaawnSoFGJDgoYIWGTZjktkTUyo4PDw832nA2iRDFoNkNSptxpXNin1GpeX9"
+ "dNaX9ygfYECChwpaZNiISXPuWM1jAyolj9NkLkCWIxJGjQLxRzwpeS9d6FWFAAMSPFTQIsPa"
+ "oTRbbADnmx5iYMhSUFqJKpPYgQdeOgw8P4/yAQYkeKigRYZ7EWnala8gGo2iRVgbdAvafdGc"
+ "L8KOSaBRCdmFOtCrVIUAAxI8VNAigzVE9LtFBljrdQpjtDjrJ5aQhEngj6BYNLTgUT6U7EcK"
+ "DxW0yLAQJLqCQTgcru00bMXk6zvCTY+oY4g5INnC0nq+Udv5OlBf+QADEjxU0CKD0U/UO48N"
+ "Ogy2kPTGdPKilW20cx3b/K9O4bZXnKDFKYYANR+Q+dKBVTAgwUMFLTK0bPENJqamVavy+Xy1"
+ "7YbFgPSKNnl2gb2ywjVv8j0OYdAl3qZEDU30DJn2kZnSgVUwIMFDBS0yNG3wXxvzBgzD1LQb"
+ "5vzSy2PJt43sJRvXYOdbt4RfdsVht3iXUpS6fTJZOrAKBiR4qKBFhqtr/JUZprp1QkXTdE27"
+ "Hv/ihd8SrxlSF5bYr1YzzQ+5rh2+3ymMeIQ7XnF8T1SXDqyCAQkeKmiR4fI9rq7YAG/A8yOJ"
+ "VydT1Qvsl/cz325wndt8764w7BJuecRRShwrHVgFAxI8VNAiw+c27jNDvgKKolDBKRp4vd7T"
+ "NfCcuoHHc0oV1GEG1yZUbrf7w7YKM8A+0dGifp/8Y2AHT9BklCI33GLvrti+JTTa+QY7V6dz"
+ "fdyhrWyALYhNvIrzi8mUiqX9zDzNGilW706P7aZGHMn+9eC7Tepv+iZVLperfIvUlLgWlc61"
+ "6j5o0TwZ7/+gQTz5vLZVU//zxO82m2JQ3aaf9ZGX7iTenEl9amXr1zMtj7gfHfwgXgKvoHwk"
+ "9pK1rdp0Op0qunDL87zJZFpZWSl+zrKsKIqDQ0MWiwXHhGLw3vdqq5//YjnTZOe6d/ght/Lq"
+ "4vAyHSjfHxyQP5kcl7vVhJDc3680yw4NDeGje+J5MBjs6u52OByKAX5N/bp3mtVnr2lLxcUu"
+ "3a1R9fWurvaOjuLo7unp6+8/8RC3AwMDJrMZh9CxwfLyslqj0ZW+jHNzFqt1XK0eHRsrDo1G"
+ "ozcYTjzE7fT0tP3BA2TH9Sf2aVnapn4zWAAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+aero_tab_focus_single = aero_tab_focus
+
+#----------------------------------------------------------------------
+aero_tab_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAMAAACxiD++AAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFq6ysra6urq+vr7CwsLGxsbKysrOzs7S0tLS0tLW1tba2tre3t7i4uLm5uru7vL29"
+ "v8DAwMDAwsPDxMXFxsbGycrKzc3Nzc7Ozs/P09TU19fX2dnZ2tra29vb3Nzc3N3d3t7e4ODg"
+ "4uLi4+Pj4+Tk5OTk5OXl5ubm5+fn6Ojo6enp6+vr7Ozs7e3t7e7u7+/v8fHx8vLy8/Pz9PT0"
+ "9fX19vb29vf3+Pj4+fn5+vr6+/v7/Pz8/f39/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAA0PbvAwAAABh0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjM2"
+ "qefiJQAAAP9JREFUOE+t0tlSwjAUgOFjZQuxuOBSFURSSOyq0qYNEd//tUzCaIeLk9743Zyb"
+ "f5LOSUH3AC3vyEWIuIw06KvHRmGqKIJ3+u1RzaD0BpL+S3DwfIO5oqAHDxPk1LOpr9oGe0/h"
+ "ArXHmSCjLbpIpSobyBa3o5DSWqJaF+xqlPykEE/LHFWmU2AkS1GZCdYkFajkjZhAxCghCLwS"
+ "zlCcE1j1BpOeE176gqU/mMBy3F0Rb/mpZENh0QWxyJNTfD6HRXfFthgNndFgcJzDa2aCv0WZ"
+ "tUj7blLdP9nZ6PCZATtPft+qjELt/vAm/HCzCNYmuA2O5xqzmzOwAuIG0AfGfgDFvqY+8bKe"
+ "lgAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+aero_up = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo1MToxNCArMDEwMESarloAAAAHdElNRQfZAxkQMyBAd2MK"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAh9JREFUeNrFl0tv2kAU"
+ "hY+NBXbAElS0QTwColKX4Q+gbvmDXXXVriq160olq7b7Rk2zICsejWyUqkmQgEIMxvWxZAti"
+ "0eCoHo40ssZj+5vrO3fmXgmuut2u4zb0+33MZjPEJU3TUKvVUK/X2SRlOp067ZMTNBoNNJtN"
+ "JJPJ2OCWZcEwTXw/OwO50o/zc0fPZFCtVmOD3tdgMMB4MoHc7/VQKpWEgalyuQxy5Tv3VyiK"
+ "IhROHrmyUOo97QXuOM7+4L4CZ/uziVuSJG3CCRYFX5+AcDg5iURiP3Ba7bOE+3xde/H5huWi"
+ "4SHLV6uVEKAsy5uW86hbLBZC4FzpoVCzbVsI3OcFcP5yUfBQqBEuyufkhFb7Y+BMubheHguX"
+ "fXiURjH7sSw7yIKivh/Ao4g+KxQK6A1MvHr9wbuyv35a7arI8Gw2i+ubCd6++4KUlveu7PN+"
+ "rPBcLoer33d48/4bDvTDoLHP+xyPop0zR13XYfxaov3VhJZ5Fhr/+NlE62UFh090jMfj/wdP"
+ "p9O4uk3itDNB6iC/9bnTjoXjFxmUnu42AQ/+0GKZz+c4KuaQz6kPflBTJYxuRrtZnnJjlbsb"
+ "N/xtsc7x2+thkIH8S6M/9tbdkkbyGxwn1yuX3OBDsVj0Dpc4j1aCVVWFYRhYLpdQnrsV46d2"
+ "26siGK9xFoo0zhwO0bm4QKvVgudsd3F4JfLPy0vPv3GJVh9VKl6J7EaP9Be4+2JJRD7+lAAA"
+ "AABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+aero_up_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo1NTo1MyArMDEwMAycPlQAAAAHdElNRQfZAxkQOBMcU9vX"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAABFhJREFUeNq1V82LHEUU"
+ "/1VNz863yWyUyCSaEPzYuGtkwY8QYwLiQfTgwYsgBPMXeDJXvYmo+Qc8KEFIULyJHhQWNcSE"
+ "3KLrLgqLoMYVkplIdmZ2PrrL36uqnulOsu50YB68ed3V3fV771fvvZpSoDSbzS9/Xll9+czy"
+ "EFc3IkxLGlWNE/MBjj17RBljPlQE/uH1MytHzcEjeOGwwYGSQokvzigqbUCbo9UTAhhqKMqL"
+ "IW2PdpN2g/pbx+DH7xX02gWcPblwWi2dv2Debz2Dd48bVIxCjiiBFjBeE1iJwumkIg4If5ER"
+ "NRiKIxxgtOhpjVNfGby15xL0xz8NsP+owkzoPpqmiBP5MEL9RUBw9bWuwe6iwvRWOi2C0yhp"
+ "CO6kSzkVCWJvzBYqopBtScwdruM8sHj+wkYuiWGMBxTrHxrvQdZcMCat0S33qcgFbMBBTau0"
+ "y3CL6K0yfmxCibzDoYkz3pdelGbA0U53Ir4RqfHLmq9FcHVmSy1D+GbEphnNF5cdLFYuAR65"
+ "MsgJqNcwMZkFzxB5THXcbGzUXk1iGS240BGmPEw3lqwlkcyfcbNxGHbOKEW7W/M4cpVYb7Em"
+ "I+0pQM/qIHIq8w1NMnLyMwhdHw98pCOqI39/NwnnGY2tMKwwLjUL7tbE0Iqyp1Ot5/HqqOwJ"
+ "FyYot/MKA5EZMTOOfOi8smuv3Yc26RLdRWeMPLnOoU++oV/SVOTnmuzv5H22oFDLK1S4nRVZ"
+ "DTN0JK/d7pbLAB7vYn2i92jbHLg5AFp9KV6Fs5zreAy+ycg3+KDADiMDOZuuCibnMjYLeEy5"
+ "gPcIvsmQuwTvMKPbfWNrfTAIx5H36FWHDpR5V+A4g7c0x1RLIkYZwSWz+5yr57UbOgwJJgwT"
+ "tEuqt+lqhYNFLvSMUB2O69tkBB/adm1IuwBL9E47ZMA6lwIfOup71D6p7mv/98m3VvHC3AIu"
+ "tzuYI//2zG27WJy8cW1bBjyGFQ8+al5RQs02Ksvxyr4Ae9t/WqvV9t8k548l858JYeOlhsLy"
+ "yhrePHXaWrnPUg13DX5oNsDf/9zAO+99jnKtYa3cy/hUwRd3Bbj5xzre/uAb1Or7Rir3Mi7P"
+ "s8jEbz+yI4fm79fxyRdrqO588LbnH322hjdezePRvbP4pRVONOdE4PtrGr2rHXx7qWup3krk"
+ "+bGwjYceqNCB4bbzOnD9//yv86Tx/IEKGrvL205YLSssXds68iROcC+PRxXmf5WNfCsHpEF8"
+ "xwlLE/DUve7a6Z2kyO8reY0arwU3OPl4HktXctjzHCenw1V2l2oeKLF2Cjm3scQNZzjByUKO"
+ "WvfwoDdgSyyytxf4fZ5b5Az/qdxHnyoE3fW1wonFAMHiwmOr85cvzn26fBgHnzZ4uKyxk6BV"
+ "gvFgwc2GDsB1vEnEdjj+cA8BDyVo0+Eb1CbZ+5Unxr/OA3PRRTz5xILrnq1Wy1y+soxzqxHW"
+ "29M7ON1f0XhtTuOpQ/Oo1+vqPxxtdiUOpmR7AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+aero_up_focus_single = aero_up_focus
+
+#----------------------------------------------------------------------
+aero_up_single = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l"
+ "AG1lciAyNSBtYXIgMjAwOSAxNzo1MToxNCArMDEwMESarloAAAAHdElNRQfZAxkQMyBAd2MK"
+ "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAh9JREFUeNrFl0tv2kAU"
+ "hY+NBXbAElS0QTwColKX4Q+gbvmDXXXVriq160olq7b7Rk2zICsejWyUqkmQgEIMxvWxZAti"
+ "0eCoHo40ssZj+5vrO3fmXgmuut2u4zb0+33MZjPEJU3TUKvVUK/X2SRlOp067ZMTNBoNNJtN"
+ "JJPJ2OCWZcEwTXw/OwO50o/zc0fPZFCtVmOD3tdgMMB4MoHc7/VQKpWEgalyuQxy5Tv3VyiK"
+ "IhROHrmyUOo97QXuOM7+4L4CZ/uziVuSJG3CCRYFX5+AcDg5iURiP3Ba7bOE+3xde/H5huWi"
+ "4SHLV6uVEKAsy5uW86hbLBZC4FzpoVCzbVsI3OcFcP5yUfBQqBEuyufkhFb7Y+BMubheHguX"
+ "fXiURjH7sSw7yIKivh/Ao4g+KxQK6A1MvHr9wbuyv35a7arI8Gw2i+ubCd6++4KUlveu7PN+"
+ "rPBcLoer33d48/4bDvTDoLHP+xyPop0zR13XYfxaov3VhJZ5Fhr/+NlE62UFh090jMfj/wdP"
+ "p9O4uk3itDNB6iC/9bnTjoXjFxmUnu42AQ/+0GKZz+c4KuaQz6kPflBTJYxuRrtZnnJjlbsb"
+ "N/xtsc7x2+thkIH8S6M/9tbdkkbyGxwn1yuX3OBDsVj0Dpc4j1aCVVWFYRhYLpdQnrsV46d2"
+ "26siGK9xFoo0zhwO0bm4QKvVgudsd3F4JfLPy0vPv3GJVh9VKl6J7EaP9Be4+2JJRD7+lAAA"
+ "AABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+aero_denied = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAADxklEQVQ4jbWUzWuUVxTGn3Pe"
+ "+955k8nMJE5m0vqRZCaUYomG0uJGjDR0UXBRUj+6Kqg7kSy6SBf5A7ropiB07aK4qIsWIYsu"
+ "ioXBQoRKqWhJ1eq0sWqSmWQyk8y8H/e+p4t8oJ2YuPHA2dzD+fHwnHMuiQheR/BroQJQOxWv"
+ "Z7N9cRB8nAA+dIEBAIiAvwPgJ04kro1Vq/Mv66XtrCgVi9osLEx1K/V57+HD6a5Dh8B9fSDH"
+ "ga1WsXr7Niq3btVrUfS1yue/HH34MNwV/HM+n1HN5vd7+/vHsmfPQu3bt60i8+wZli5fxr/l"
+ "8nXT2fnJBwsLK8/XX/B4ZnhYqWbzyv5icaz34kXwnj2IrYUoBXge4HkQpRBbC85kkL1wAfuH"
+ "hsZUs3llZnhYvRQclMvnsqnUidTp04DWoEwGnE6DEwmQ44AcB5xIgNNpUCYDaI3UqVPIplIn"
+ "gnL53LbgmULB9YCp9LFjcHM5KM8D+z6o0QD+l9RogH0fyvPg5nLIHD8OD5iaKRTcTd6W/KhS"
+ "OZJOJgc7R0ag4ngd8gqhAHSOjMArlQbrlcoRAL+8oJhFjiaLRWhmrN29ixYzfNdF6LqIXBdG"
+ "a1itEWsNaA24LoQZ5s4duAC6hobAIkfbFDOQ78jlQPU6zNIS3jh/Hqz1jmolDFE7eRIqk4GX"
+ "zYKBfDtYJGDfB9VqkNXVV7IBAOT+fYjrrs9DJGgDE/Ns+OABkExCBQHmL10CM4OMAVkLAkAb"
+ "3hEAIgJZC7YW9OgRwnodzDy7xds8kF97et70iMrFfF6T1gAzEEWAMburBvBwcTH0RQbfX15+"
+ "Cjw3vIOl0tMgiq7VVlbA9Tq4VgOvrYGDYNes1esIoujawVLpaZtiAPitu/sta8yt/o6OVI/a"
+ "8X/aimVj8E+r1XCUeu/dWu3+tmAA+D2dHvetvdqtlDrgOEgQbQsMRDBnLWrGGM9xzozU6z88"
+ "X28D29VV/LF370d+HH/bFOntIkKGCJuLFwJYEcGqCDqJKh7zZ+88efKj09WFHcFbtuTzOW61"
+ "vghEPo1EDtiNdweASzSnib6Tjo6vum/eXCwUCm39dO/ePUxMTDizs7Oq0WjoMAy1tVbHceyK"
+ "iJsFOs4wv32AqF8AzMXx3FWRP5cAn4hCZo6YOdRah8lkMhwYGDCTk5NGzc/PY21tDcYYiuOY"
+ "RIQ30gGgKiL4xpi/AJSxvsIWAIjIAaBEJBYRx1rLxhhqtVqoVqu0rRXT09N048YNPH78mKrV"
+ "KjWbTfi+TwDgeZ4kEgn09vZKX1+fjI6OYnx8vA3yHxWIwp50Lj49AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+auinotebook_preview = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0"
+ "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJXSURBVHjahFJRSBNxGP/d/+52"
+ "W66ildPKJB9EMSwjFSNoUkS+GYg9pi9R9tJeopcgC3yKYvRUMHA+VBJUmpQPQSySKINqEGSB"
+ "Np3aNjs3N8+7285d/7sxa9yw3/G777v/932/+76PP6PrOgw8D876dYImWJAEZPpW8l89nYea"
+ "i8KGgMHRYPitvgkCw0G9qaNXD4x80Qs1BknRnzaBEfX1e+G758PQaEgvnP8VULA5lCS8/T7T"
+ "NUQK4ApO4j/1l3s6N/zA8MiGTxiGgUGowGwkhqkfc5Bl1SKwlM6i90y75dzsoKX9fNPLF2Mt"
+ "sZVGuMt3YPDpK7jsDnj7uiEIfH6ClAjF5rAKHD1xcW99a927C5e6hP3luwCGwONpRjwm4tqA"
+ "H7du9pmJDG9HrsSeSE3dvmdnz512tFZVQaGjaCyBjedRubscxzva8PrNJzNR0xmsKsQq4KzY"
+ "fqDW7UY8o4KjxRzLmpYlBLUNNZj48BVRMQlWA7I5yTqCvcyuq+s0qmkQiC1/QeiTo1ajNpWS"
+ "oMoMVJVyXbZ2sDj9S5sMh2l7CjJUJGswq0HNZBCNLmEhPA0xsQpJUSHJJUZILCbuxuZF7fv8"
+ "ApbTaaysrSEpSVgURdy//RDJxAp2RvzgMgkQzbpEziVEbgQfBeuXPY1dqcMS4W08cnIWY0Pj"
+ "iIXjuNI2A0dsDmXyT3yUTtESZ5EAU3CuDvhD7ydDB1mWg6zQWelSj2ydwbE9v1Fd4TQZmHLj"
+ "yTfBzP88PsgUCZTCne4qFycID7Zt4TuqK50TFaTmZMP1x5l/c/4IMABbKBvEcRELXgAAAABJ"
+ "RU5ErkJggg==")
+
+#----------------------------------------------------------------------
+whidbey_down = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACsAAAAeCAMAAACCNBfsAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAaHWVZ3egZ3e1cYCncYa0dpC4cYXGcpDBc5fWd6Dld6Pwi5OzgJbUkJjQkqHC"
+ "hafggqfwh7Dwk6Xgl7fwoKjWp7fXsbbWoLfnoLjwpMLwscHnsMfxtdD0wMHg5eTo5/D49/f3"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAverH2wAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAF4SURBVDhPbZTpYoIwEITRGqAQ1ChqOFrx/R8y3SObq8yvsHwZhglaOdH7HZbJIp1W"
+ "YW7t7w68LOcwDaxd5+lhC3q18zwOMhTWIjtZ+3wGfFmWFYZjgJl9vWC/1x30AI2zzExzIcqz"
+ "a2RxC2Ak2n4zJmEx1TgaY8R7AtHsdgMS1IivJRZHyN5lA6PMEgwZ2JVYs23bxwuWG3PGdF3X"
+ "ImvtBO/KqAl38ytgO+WqMz1SDDz7KXaCbatU5YYARt+SbUHg61zT9/iMHsQZKHBI9A1S6njk"
+ "fpuCRTjmJVQBymfxlfuCc5IX0cMhnhvCMYO8KCdCV0L9GbMz8Fhqous1ugbWw/32k2oDtFUn"
+ "do2sz1ywqWvCElz6pq4pS3CRVxooMvjqsI2+v5LwXCVrljfrGclhqH2v5e+Nr6VnYltgBct7"
+ "iDDExm+grvm0ouL/QwrjN1CHXvczYAz0xF5Pp9w168zfAhjeH9gSle8hnWutldL6H7rHOq2P"
+ "agd1f/M7VhKuYPh3AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+whidbey_down_single = whidbey_down
+
+#----------------------------------------------------------------------
+whidbey_down_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACsAAAAeCAMAAACCNBfsAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR"
+ "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagcHiYZ3egcHilUHjRQXLwR4DwU4Pw"
+ "YIfTcYXGcIjVc5fWZpHxcJj3d6PwgJbUkJjAkJjQkqHChafggqfwh7Dgh7Dwl7fwoKjAqLDI"
+ "sLDIl8D4pMLw4Of35/D4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAQS37pgAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAGeSURBVDhPfdOLUsIwEAVQCCixFSggVfBFQWpVjKJo+f8fi3ezSZq2jDsDhHB62Wyh"
+ "o319Vctg9V2tO34p5H0bHw5D4Xe9FULK5bKhb6UcDs/cprNdMYiprhee30khaStx2NpudwCb"
+ "JHG8WAhbEkU0cZgtUge0iYrjCEUuilheOWysS2U9GpluGJJ1mKyg1LHZn6NYNNYUCWuozSjr"
+ "FVxnLGQUjZPJlLJKCk7piar0Nk2zS90RAhINVDZN5yUeNZuhbjq6BzmZomYoICr/Yr5mtcry"
+ "fL2mfnvjSd2anvkSsqBZUazN2XS/YVNLrc2Qut3yHAj/10OWFwVRtrpPvZo5cL+28A7fnxfv"
+ "G6Ps74GwsfXCsXKkMnWWko39DKukAbjUygKfskFqYLnnKvcHdQT9sA0EPdgD1ts9Vr2G/fpp"
+ "pDMeAg3gWe2fgn9V9d+0yW5edCylQurnwJejZ/7VPJpZ7V+C1PBsFrPFXAul6rSRi2S2uFmq"
+ "kdrK1frcWOq1kXrC6osHulnq963Wa3Nm9kOySrVpq1/yr5vNbtdK1foPGIxy6qmqIg0AAAAA"
+ "SUVORK5CYII=")
+
+#----------------------------------------------------------------------
+whidbey_down_focus_single = whidbey_down_focus
+
+#----------------------------------------------------------------------
+whidbey_dock_pane = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAaHWVcHiYZ3egZ3e1cHilcYCncYa0dpC4ZobHcYXGcpDBc5fWcZjgd6Dld6Pw"
+ "i5Ozl6e3q62xgIjQgpXEgJbUkJjAkJjQgJjggKDXkqHCk6TWhafggqfwh7Dwk6Xgk7Tkl7fw"
+ "oKjAoKjWqLDIp7fXsLDIsbbWoLfnoLjwsLjjl8D4pMLwscHnsMfxtdD0wMHg6tTN4Njk5eTo"
+ "4Of35/D48Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAA1jVbdgAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAdFSURBVGhDtZpxe6I4EMbtbQVXrHJuaY8KWq/XW3Sr196u8v0/GTfzThICRIh9nssf"
+ "u4rw42UyM5kJHVVXjDQah/EV51ejK05+SKMwjK/BX0Gfzu9ms2kY3PgL8qd/nc/vCB+GN/54"
+ "b/p0sVjMaRA+9Mb70hku9GvUe9IBV3TC+9rejy5wTfdX70VneJ7LHRaLu7uIPNPL9j50hp+a"
+ "w9NzPOhQfvrHHqeZn/phOmzeofvZfpA+zTFa2rNsFk2GPWeIruB5y+5En00mg1E7QNfw/CSP"
+ "oEaZ51kWDavvpxu4phOWB+hJMqi+l17DFb0sBa+eJB3KOX30xLIFeAQXvKYTvtf2PfTVbrtd"
+ "6xsonrKMoafhJAwu5/vL9NWO6Rp/iZ5OJsFlfI/2onh7oxvQYKOsaeALjTV944fK2DFn489o"
+ "ryqmA69NDrtjWPSwZyHs9RlWr+h5Qzt9UdqzPvhATTBMn/Uu4QOxut9r24vFdzSUvUh+lk37"
+ "6wMXfVNf8sF0mdrt9nGF8YbB3ppNl/WpK8eNHPTNxuCXHx/a9q+vZz3exZvW6+m5NPhi58B3"
+ "6Yfj2zYRHcuSgOI5Bi0fDgeiT/nT8oxTi2K3U1dZz9ChH5gu+GXJ9HNRvP/dgoOfyEGox/Tn"
+ "nVlo04kNm34DHPRfv7psxuujywqm4rBo41t0Vs4uvl4/PXHUNLj7/f6VRvte5RJTjxBo4Zv0"
+ "A3sDxw2d+EeTcnzd4qnIdR43zZ/EbSUjNfEN+oHppFsiEZOmxn5/ZJOBvt1uNivrNyvk2nib"
+ "fmA6W0W0Z6FGkL0sNvLYt0L/aKeLtnqLTvCD2FzRNR53VelSZ8l1IfhfdqqDbRaWcWo6nWZs"
+ "zrk1SZLVvww40oBeZTG9oDwbOm6pDy8svKHzA9Y2Z3oUgU5WOSIXdOjAv/Nv1hLJ5aZRr+lQ"
+ "XhNYevSEZye6ZJo2PZNpd9ANXtFFuYtOM0p50UnP4Dm2VeQZavVCZ6cqudziCOL/szSKYkh7"
+ "hReu62UJv/MyS8+HM2AZuUwNgwcdTlVSkasrrppOgSL0Rg2ME9l6uD8/cqmWd643T0Y90xEO"
+ "azku48RzCu0vau1z0lNEhJu++Epkoks4dOhjPPaL+Hl+gf4upmlplzaIPGdUIbewXls7OTvo"
+ "xktbdK6auNyAWz266fOHaoQ4ZKNpOl940vRXHQN99BU9XMkzqylo3+7u0nTEdkHkKzoKRUNH"
+ "tccxeoEOwxs6XQqK0GdRNFoVKkqEDo+8lk4Syq2UsDWd2ubxKHtm5dzVid1Fe5bOjCx4kUt7"
+ "mohf8QPCMg3ttGERjp4z1Yk27O5HV15r6MbuVF1S2xbHo+pRNblNf88SaN9sVIpyaSfDYhnU"
+ "dEQK7A54ELO/f6VJqC2joknF4bmfPgadw4UtY+hmo4Vj9ZanWNtd07PsRfmDuYqTgc43nAei"
+ "e8TEu4OuWh7kGcb70kViKfR7phdvVA808gw34thHkBzJ+EZHSquH5NfzN5p1ZU+S/kM3fZxE"
+ "owBnCF2lWFAivcWi8jvUYydDBujAZ0JX7XD5Q0yTMT0EnVf6emHh9FC3anptgu3nc5ueppC2"
+ "0nfT//OdqRcOA5HeoVsbFGZdFbxFJ3/7C3ShyTPoz/C4PwHnhau+rLmxVdcEwNunRdEYNcFK"
+ "8Wv6jO4cBL8DfuC1xbqssbVi1TOMN6chHoSu1Ws6ByLZBfDzObEX8yRqNvd2LaZsLzt3k8lY"
+ "1g8aDw+Ukc3gfatAzMJjapTnOdEb2yqNOtLgSdwkMHBWGEIxxmQS/iYTqvAyGSmN9rZEswZW"
+ "eJkaC0Af4/ieBrPHY6kWWniCh+0NoVb9DjzbPLhZNhH07f4+CIK4heYbT0V7d0ui3XvcSvLk"
+ "QEbXROPnz859zFGOLGptZhRDru2UTt9EeB3ISj31TQ784fBIRwVeVTQtrq2gbs93G0Vfvtg9"
+ "3/Ft92KqdXWfI1cpVCspOOMnjg3QLr0aRwpOxuGOj+i7orD6JarnqVugEE2sfnXs2khx0CsD"
+ "r6rv33U3w/3MZvNCQ/dP3EI+1c2pa5fGRbfa2e/SApohXbw6RmFk0a2rzMd+ujRclAI0XnYh"
+ "pBRH1ujfhuil6yZX6LTEmlEnl158H91uFVVtr+t7ne0o9iKXSdSxHjpvLJieqLmXar5xaPfs"
+ "Ll2mP8IMWqRzTy/PSTplzIvqe7Qndit3gc4581Paq4p23lHpYP+dH6K5lyoZSce1U3+vz0xb"
+ "dMZLgcD/AB5aode9Qb+/S5VmtEsDUNMH334MxKqpcxw+4/HWbIAuNSbXgc3RLIo+4zNyjeBR"
+ "ZdbjRKuFKec+F03qqrpCtuieb/uGLGNXyDbdR7mugXsezlUhn06D3iJED+2qvkcDpCpUvzdl"
+ "nnTVnSg6vavxfT/spb1Wz9qpnPN7Q+mrXTsmF1I+78j0PHpq13jOLR7v966mV6jS0BX0vAJq"
+ "OZ+3dlLP8UnDH+7nkUpRHMf/399CVFUcf7nu7zj+A8yummsi9EdGAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+whidbey_dock_pane_bottom = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR"
+ "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagaHWVcHiYZ3egZ3e1cHilUHjRQXLw"
+ "cYCncYa0dpC4R4DwU4PwZobHYIfTcYXGcIjVcpDBc5fWZpHxcZjgcJj3d6Dld6Pwi5Ozl6e3"
+ "q62xgIjQgpXEgJbUkJjAkJjQgJjggKDXkqHCk6TWhafggqfwh7Dgh7Dwk6Xgk7Tkl7fwoKjA"
+ "oKjWqLDIp7fXsLDIsbbWoLfnoLjwsLjjl8D4pMLwscHnsMfxtdD0wMHg6tTN4Njk5eTo4Of3"
+ "5/D48Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAaHenigAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAejSURBVGhDpZkLe9o2FIYpTVeWrG3Srmy9stk0LTPJMKMhmYM9KOuSERqydAX8//+H"
+ "dy6SLF+QRXeepwtg+9XnT+fotlqyRQRey+1vcX9S2+Lm08Bz3f42+C3ond5xt9txnRf2guzp"
+ "b3u9Y8C77gt7vDW94/t+DwLwrjXelo5wpm+j3pJOcEEHvK33dnSGS7q9eis6wqOIW/D942MP"
+ "MtPKexs6wlfZsMwcCzopX/2jx6prp76aTp4X6HbeV9I7EUVOexh2vXZ15lTRBTzK+Q70brtd"
+ "WbUVdAmPVvwKIuIoCkOvWr2ZruCSDlgMog+HleqN9BQu6HHMePEmQdWYY6IPNS+IB3DGSzrg"
+ "jd4b6KOr6XQsGxA84YyiB27bdTaP95vpoyukS/wmetBuO5vxBu2z2fU1NACBpowh6AvEGL7h"
+ "S4WYmN3W12hPEqQTXlpOvlNodNcwERpzBtULepTRDl+E9tAEr1gTVNO7xim8olbnc+k9O34F"
+ "IfwC+WHYMa8PyuiT9JHPSOeunU7PRhTXFJitYWeQ3joqaaiEPpko/ODzZ+n9xcVaxi1n03jc"
+ "WccKP7sqwRfpi5vr6ZB1DGIAcuYoNH9YLIDewU+DNd06m11diae0dyjQF0hn/CBG+no2u73M"
+ "wYk/5B9JPXV/VOiFPB3Y5Ol7ghN9uSyyES9/HSRkFZZFHp+jo3JM8fH4/ByrJsOdz+cXEPm2"
+ "4gF1PZVADp+lLzAbsG7gxt+zlJuLKb0VpM7ZJHuJ05ZHpCw+Q18gHXRzJVKniZjPb9Ayok+n"
+ "k8lIu6aVXB6v0xdIR1dYe+hKBPilsWkcez+TF/XhIq9eowN8wZ4LusRTq2K4lKPkeMb4pT7U"
+ "kTe+Zk5Kh9uU5zi2DofD0b8IuIEgvcIxOaF8UHRqUv7sa3hFxxdMPUe65xEdXLmhsaBAJ/wt"
+ "XtOmSFxuKvWSTspTAkr3zundgc4jTZ4ecreX0BVe0Fl5GR16FMbFUnpImaO7wu+Qqmc6JlWM"
+ "yy2sIPwbBp7XJ2kXlIXjdFqi6zjNwvvRHeQMPyZC4YlOSRXDIleuuFI6FArTM2tguhHdo/bx"
+ "lWMxveN6c6XUI53KYcy/c6ywT0n7RzH3ldIDqohyuv8WyEDncijQW/TaHznPow30W7Ymp523"
+ "QZA5tYTGFtSra4dkJ7rK0hwdV0243KC0Oiun906TGtUhmibp+OBK0i9kDZjoI3i5GHtWUmj7"
+ "dnwcBDX0hSpf0GmhqOi02sMa3UAn4xUdHiUK07ueVxvNRJUwnTJyWzpIiKe8hE3psG1u1cIP"
+ "qBx3dew7aw+DrpJFWVSmPRhyXuELkjMZ7XBg4dY+hGInmvHdji6yVtGV77C6hG1bv19LzsQm"
+ "N5vv4ZC0TyZiiCrTDsbSNCjpVCnkO8GdPub7W+iE1BlRTaIO12Z6i+hYLuiMoquDFqzV19jF"
+ "0ndJD8OPIh/UUzgYyPEGxwHvhGritoQutjw0ziDels4SY6afIH12DeuBzDiDG3E6R+AxEvGZ"
+ "HSnMHjy+rt9Drws/QfonuenDQdRz6A6miyGWKJ48YhHjO6mnkwwOohM+ZLrYDsef2JoQ6S7R"
+ "caZPJxYcHtKtmpybyPteT6cHAUkbydbkX2wZ9sKuw9ILdO2AQs2rjNfokG9/EZ1p/A7yM2Xc"
+ "nwTHiSt9LHuwla4JCK/f5nktWhOMBD+ld6Flx/mN4AucW7THMkcr2noG8eo2qgemS/WSjoUI"
+ "vhB8vR7qk/nQy27u9bWY8J5P7trtFs8fEKenMCKrwHMrh23B6CjlUQT0zLFKZh2p8CCu7Sg4"
+ "KnRJMUW77b7kDhV47owAIn8skV0DCzx3jQaAj/3+CQSyWy1eLeTwAHfzB0K59Tvh0XPnxSCL"
+ "gG8nJ47j9HNobLjD2otHEvm9x2sePLGQadcE8UVZrLf3hdIVKwu2Nl2oobLjlMK+CfCykIX6"
+ "ekPvAdHC5eWDOtNp3wTdUnYUVNzzvfa8V6+0PV+93mg8f56z6WWj8eDBPaSLLaXbbZccgBbp"
+ "ScsTcDBnvb5Tv7+H8cMz1cCrRr2BP+3f0/arrbKDlBJ6ouBJ8vedO/eBvr+/t/fsWV1EAwLh"
+ "+/v3ztPNadkpTRld286C8vuIgdjb24VA8u4us78HvHZvyUczXSpn/sOH5BGjkV6JN9LrqPwR"
+ "kZ5CMDP32XjKYaITXOhcZkNryTOYY6ADe3f30f7BY9S7RPFN/A/GUtGbzcPvNuM30+t1YIMt"
+ "Kb3ZfLqEfxn6IcSPG/EG7XeBffAY4gkEYDHUH3qVN28Oj47evfsa7Uly99FBlk7ecyNIB/ih"
+ "7xvg5lO3nRy9KeCCfgjKu8ZjN3O+7xidOTzy/f91preDnlPOsO8i4Bu4cuR/zZme3kuIJ3o2"
+ "oEOPQHnFgWH1/wEFPNFx6lexxGSpVC7XkaaxaKeUbqPchp6Q96n2TxArgP9RZYtaA5vHUcRn"
+ "bV9ZeJ6usM10Vt98wgmDyfJrNP2l4hm6XDF7CATiZTZih0aRFdySjup5/PqZMlEe5Vbpt9Oe"
+ "AJ7pkOewhSie+Ja3Y0tPdpgOBRrZKrf1HZV9Q3T03Fb5NvTk25+wQKPrsyq30+vWzsAjSI+i"
+ "LeC2OcNyTjudc219VP0O/wGW4JFYg7jH7QAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+whidbey_dock_pane_center = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAGDeAJUqQIEOkIkewJFKlJlayMlSiMle1K2G0LmnSNnDgR2OkQ2O1UGagUHCo"
+ "VXSzaHWVZ3egZ3e1cHilQ2TAQHDAQnLSVnfFQXfgcYCncYa0dpC4VYTTRIDjVYbgZobHYIfT"
+ "ZpPXcYXGcpDBc5fWYIjgYZHgcZjgd6Dld6Pwi5Ozq62xgIjQgJbUkJjAkJjQgJjggKDXkqHC"
+ "k6TWlrDXhafggqfwh7Dwk6Xgk7Tkl7fwoKjWqLDIp7fXsLDIsbbWoLfnoLjwsLjjpMLwscHn"
+ "sMfxtdD0wMHg6tTN4Njk5eTo4Of35/D48Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAXehG6QAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAdqSURBVGhDtZoNW9pIEMc5emrB651VUDRUpEkqb5d6SBOUXq9Q8dprke//aXLzsrvZ"
+ "hGWz+NzN87RCzP74M5mZzGyspDvYOGh4wx3OTys7nPx+HHjecBf8DnS/3wtD37t47S7InX7V"
+ "7/cA73mv3fHOdH8wGPTBAO85413pCGf6Luod6QQXdMC7+t6NznBJd1fvREd4kvAnDAa9XgCR"
+ "6eR7FzrCV3lzjBwHOilf/a3bKnRTX04nn2/Q3XxfSvcTsoL2OA6DdnnklNEFPCn4Hehhu12a"
+ "tSV0CU9W/BWErZMkjoNy9Xa6gks6YNGIHkWl6q30DC7o6zXjxTcZl9UcGz3SfEE8gDNe0gFv"
+ "9b2FPlnMZlP5AYInPKPoY6/tXWyv99vpkwXSJX4bfdxuX2zHW7TP5w8P8AFg6JQpGL0Bm8I7"
+ "/FIxBmbYeI72NEU64aXLye9kGt2z3AitMYPqBT3JaYc3Qntsg5f0BOX00HoLL8nVL1+k79nj"
+ "CzDhL5Afx769PzDR77Il35DOl3Y2u5mQPZBhtMb+KDt1YvggA/3uTuFH375J33/69CTtK0fT"
+ "dOo/rRV+vjDgN+nLx4dZxDpGawBy5Cg0v1guge7jq9ETnTqfLxZilfYdNuhLpDN+tEb603z+"
+ "9a8CnPgRHyT1dPmTjatQpAObfPo7wYn+48cmG/Hy6CglV2FaFPEFOirHEJ9Ob28xazRuFIYt"
+ "sjjOf9p6RJeeUqCAz9OXGA2YN3DiHzrjw4du66zT6VyCNZvNdzk+hy1XpDw+R18iHXRzJtJF"
+ "Y4uvrrpdgBP98vJds9vNfqmlXBGv05dIR6+w9tiThLet62tkn50h+xzs8GVL/lIvF0X1Gh3g"
+ "S/a5oEt8+PYtws/AFP2wxfgfeqkj3ww052R0OE35HGtrFEWTfxBwDUZ6NauDnSq6LNNM1/CK"
+ "jl8w8znSg4DoEcDZG0U64b9indBukdhuKvWSTsqVV+iOH9zSBe0C3Eiv/3yFJxjoCi/orNxE"
+ "73YBbqbXiS5vAJn+TD3TMajW2G5hBuHPeBwEQ1wbtjrklfuCoePrtVDgsV3QujWFJzoF1Rqa"
+ "XNlxafSOoOO1zeye6TWkf8KvvBa3d+w3V8r3SKd0mPJxthVeU9Q+adno9Rco3kwfXAEZ6JwO"
+ "G/QG6nKhg+cL2nkMgsippFRbUK+uHYKd6G/edDoUiPcmz9TrB3jSjZnef59WqLag0yQd262V"
+ "pLfedC5L6RMImzXEPK1EjTS+9XrjcQX9Qpkv6NQoKnqzc8lZZNOu6LBUo4dBUJnMRV1hOkXk"
+ "rnRIqPWMW9iMDmNzoxLfo3Kc6tjvrD0eh1Qhm5BI27XX9qt06YnOSzW673mV+1hMojm/P4+u"
+ "/A7dJYxtw2ElvRFDbj7e44i0d09F9TL5vba/f6Rrp0yhq0rwiyHG+xVc4swzIpugijnQq0TH"
+ "dEHPKLraaMFcPcEAkn6X9Dj+CAs/NM/PMedVzMhyg3Vg/6A6xhpsoIuRh+oM4rfSD/P0Q3qP"
+ "dQbolEzzB+gHcnUGB3HaR+AaifjcRAp3j3iCS3svqV5J7Z37jL63R9IFXZRYogRyi0XUd1JP"
+ "OxlsRCc8weuQTmwd/gGH9gUd7/SyjcCF+vaQvDeR7/t9nT4mZZNXzC8asKsBnrBB1zYo1H2V"
+ "8RodEvnPrfRaDei/ERwb8GxZfmMr6wkIr58WBA3qCU5Pi7qJXf2V4Eu8X2rLclsrWj+DeHUa"
+ "5QPTnwr0GhjQCQ4tQ+bzJImC/HCv92LC97xz1243qMKjvXpVq0n9NchQpRx/6SvlRM9tq+T6"
+ "SIUPcfdFwZ8mk9oLVMxksJ+OKEnZfAywOB6DFbcl8j2wwPOlydbDq/DgYG8P/6Funa3wAPeK"
+ "G0KF/p3w6POL16McHfQfHR1Uq9W9XwIKRM2GpB7gG1sSxdnjhIsnJjJNTWDfvxdo2lG8Y8Bo"
+ "E0IOmbZTNuYmwMtEFuphbjLgl8sbOMrwNPXMG1mbM99JEBwf6zPf48Pi47zAf8QuJUK6GCm9"
+ "sG3YAN2kp41AwME5OPEBfTGfa/Mq9PmPcBAmQ21ebZg2Ugz0VMHT9PNn3odAgyn57iPYjBta"
+ "bKz922w4Ne3SmOjaOPuZR0BlPMWLY5BGGl1bpV7a6TxwQXmQeN6F4FacqoZ9G8JKl0Mu0++0"
+ "75AVFyveRtdHRdHby/5eVjvIvcDkEnHMQseNBTUT5fdS1TtMbcvu0nb6TW6SM+7pJQlIh4K+"
+ "Vb1Fe6SPclvoAdiztKcp7LxTp0P77+jp/F4qVySZ10b91pjxC3TEczeF/xHc01Jv8wPs8c5d"
+ "mtLOA0BGL336UZKrqs8xxIzDU7MSOveY2AfmLd8UPSdmeA3jqcvMbAV3C9XOPS+bxKqsQ9bo"
+ "jk/7yjyjd8g63UW57IEtX87UIa9WpdHCRAftor+nAYhbl//0OZ+cTgQdntW4Ph920p6pR+XQ"
+ "zrk9oXT0jApMbKRcnpHJ6+ioXcY91haH53s701Pq0mgOtTwCKgSfs3ZQj/kJ5g53i0ihaDgc"
+ "/n9/C5Gmw+Hxbn/H8S+cD8xcYY4GnAAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+whidbey_dock_pane_left = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR"
+ "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagaHWVcHiYZ3egZ3e1cHilUHjRQXLw"
+ "cYCncYa0dpC4R4DwU4PwZobHYIfTcYXGcIjVcpDBc5fWZpHxcZjgcJj3d6Dld6Pwi5Ozl6e3"
+ "q62xgIjQgpXEgJbUkJjAkJjQgKDXkqHCk6TWhafggqfwh7Dgh7Dwk6Xgk7Tkl7fwoKjAoKjW"
+ "qLDIp7fXsLDIsbbWoLfnoLjwsLjjl8D4pMLwscHnsMfxtdD0wMHg6tTN4Njk5eTo4Of35/D4"
+ "8Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAA+wCLtAAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAeDSURBVGhDtZr/f9JGGMdprZPJnHSKm9OKI4DG0K5kWAptGIw5FGqpdQL5//+Q7Ply"
+ "d7kkR3L4ms8PWmjyzifP3T33PM+1FO1gQ6/u+DtcH5V2uPh86DmOvwt+B7p7etLpuE7jmb0g"
+ "e/qr09MTwDvOM3u8Nd3tdrunYIB3rPG2dIQzfRf1lnSCCzrgbX1vR2e4pNurt6IjfDTiJ3S7"
+ "JycezEwr39vQEb5OmuXMsaCT8vUn3dYdO/XFdPJ5hm7n+0K6OyJLaQ+CjtcsnjlFdAEfpfwO"
+ "9E6zWbhqC+gSPlrzKwgLR6Mg8IrV59MVXNIBi0b0fr9QfS49hgt6GDJevMmwKObk0fuaL4gH"
+ "cMZLOuBzfZ9Dv1xMp2P5AMETnlH0odN0Gtvj/Xb65QLpEr+NPmw2G9vxOdrn8+treAAYOmUM"
+ "Rh/AxvAJXyrAidmpf432KEI64aXLye9kGt3J2Qhz5wyqF/RRQjt8ENqDPHhBTlBM7+Ru4QVr"
+ "9epK+p49vgAT/gL5QeDm5wcm+n58y2ek89BOp4NLsmsynK2B24svvTQ8yEC/s6/wvc+fpe9n"
+ "s420W55N47G7CRV+vjDgs/Q7D+/fE/heCECeOQrNPyyXQHfxp96GNM/ni0U/oz5DP3iIdML3"
+ "QqRv5vPb9yk48fv8Jamn4R9lRiFNPzg8rCJ+j+BEX62ybMTLb3sRuQqXRRqfogP88BDo9/b2"
+ "LnDVJLhXV1czsPSzwh4NPS2BFD5JP3j0E1j1YeUeqE9SbmZTmikwdQaT5K942nJESuIT9INH"
+ "TK9WAL+n46+ubm54HqJNJpcaX1tyabxOBzjR0fWofl8ilkudTXHs7Vz+Ug8XafUaHeFEl+ol"
+ "frlcgmy5pjhKjueMX+mhjnzT1ZwT0w8eVcHwCfg/eqdc/hsBN2BMVNGeMH8pOj1Q7jNdDa/o"
+ "oDxDr/+LMw/gpDtDJ/wt/k7bIjHdVOolHd2SpFcrv9K7A50jTZoe0FrdGOgKL+jkcyMdRhTi"
+ "opEe0MzRvcLvEKtnOsJXutXQ7yRtRrNwHG9LIaVltO9xLCDPhPw1m8ITnZSv4M1XT9BqtRXS"
+ "f8ZbYaEwPZEDfxJ0ws/QaaHY3jHfXCv1SP+OmCl65elTvPWd2PuM9KGznd59BWSgf0/wtPYK"
+ "wYHO+/YW+i27JqWdyyCYOaXo5csamK79SW1V/fE+rVRc/DRXUnTMmjDduMCLBmb66XlUOm+3"
+ "k3T0vaLPbOiX8HIhjizmgOh3Kt9OTobDknt8nKCvVjiq1Qprp2wvRzs5XtEBr9E7npem07Tc"
+ "lQ4SwimnsDEdyuZ66WLUPW63flN+B+3o90qZtctlbvL7sO/58gXJMwnt0LBwgD46Pm614lHd"
+ "ge6l6MrvkF1C2eb7pWhwDeqBv/qorSapfTIRIcqkHRxL2yAODmqnzJ5GleANH+f7ACLDcbtt"
+ "pG/y6XWi44JL0FWjBddqf4r4BL1WuV8+Eo5XmjAYyHiDUcY7q+Mltwa6KHkozvTRNxl62Uhn"
+ "B4RMP8NL5teQDyTiDBbi1EfgGAnqf1+vtSBZk47fvA107R9l0RcMPc9rULBgOsVIESk92WIR"
+ "8R0KMJ45HCNrSC8/x3sDpotyOPzIrgmQ7hAd9lxtY8HwEJdqcm96MwXntFtM5m21Un5PvkE2"
+ "1DD0FPyfDdgsPUPXGhRqX33TpXmp6LhrM13ydDrNONrTl7hxyX01qVz6HX3v/onqdfqDB/8Q"
+ "XvBjegdmeqPxB8GXuLdo9ERrRctnoFWi06uVB/uYEyj1ko4LEfxC8M2mr2/mfS9Z3Ou5mBvg"
+ "qmo9Qbc/flyt3uX7N5vz875m2LdqsFvQXKV8NAJ6oq2SyCNJfatFdA2OCh1STNZsOs95QAWe"
+ "B2YIlm5LJHNgUk/0JBwwvn8Ghux6nSJjGg9wJ90QSuXvLvqG4b0kAj6dnTUaDT+Fxge7rD3b"
+ "kkjXHp0O8GHW38Xag/lfvmSeo77FlQWlTQfWkKmdkqmbmE5RQqiHusmAXy4H8C3DowiGxdQK"
+ "ytZ8r1+320dcvXHNd3O9eKeydfGcGywJIFcScMQ3DQ1QQ736uv2DLA1B/Rzpi/lcq5cgn4dq"
+ "AZZoX6tX66ZGioEe/RLXnR8+yGoG65nJ5B2YrJ+whLyILzV1aUz0+I7oA1RLXCuxcRUvvoNl"
+ "pNG1u9SP+XQuuCAESDp3ITiZp+CS34bIpcsil+mwxSqLg0suPo+ul4q08bCJ9J2kQ0bnmVwi"
+ "vsuhY2NBJkupXqrqrGLCmNNd2k4fkBtk5Db29FA7Rsyt6nO0w1Ye2xY6xsyv0g67FZ90cP+d"
+ "8oxEL5XTuSOxro36c+eMm6IjnhME/IfgTh68oKf3IqmdC4CYXnj6UbBWER97Rg0Day/qYOs5"
+ "gXngST08wXB2UKi8mB4xvps+96C0oPDMqcAz8ELs+/SJ0P90ZsP4DN1GuYVnhPpvdlYm1FMB"
+ "LTJUu5MyO+3S94IOZzW258PFo0ozVc571A7pnN0Jpa12oR5Phq3OyOTasdQu8RhbLM73dqZH"
+ "L1A3VQU5R0CpBW+tHdTj+gSzh+/0txC+73+7v4WIIt8/2u3vOP4D32mBB1S/lsMAAAAASUVO"
+ "RK5CYII=")
+
+#----------------------------------------------------------------------
+whidbey_dock_pane_right = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR"
+ "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagaHWVcHiYZ3egZ3e1cHilUHjRQXLw"
+ "cYCncYa0dpC4R4DwU4PwZobHYIfTcYXGcIjVcpDBc5fWZpHxcZjgcJj3d6Dld6Pwi5Ozl6e3"
+ "q62xgIjQgpXEgJbUkJjAkJjQgJjggKDXkqHCk6TWhafggqfwh7Dgh7Dwk6Xgk7Tkl7fwoKjA"
+ "oKjWqLDIp7fXsLDIsbbWoLfnoLjwsLjjl8D4pMLwscHnsMfxtdD0wMHg6tTN4Njk5eTo4Of3"
+ "5/D48Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAaHenigAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAe+SURBVGhDtZr/W9pWFMYtW1en67RzunWdpUvQlgWdMCoyJFkotbaRCrMryP//f2Tn"
+ "yz25N19ILn2enV8Qkn7y5s2555570414jRh4dbezxvnxxhonXww81+2sg1+D3jw7bbWarvPM"
+ "XpA9/eXZ2SngXfeZPd6a3my322cQgHet8bZ0hDN9HfWWdIIrOuBtvbejM1zo9uqt6AgPAr5C"
+ "u3166kFmWnlvQ0f4Ih2WmWNBJ+WLf8xYtOzUV9PJ8xzdzvtKejOgyGj3/ZbXqM6cKrqCBxnf"
+ "gd5qNCpHbQVd4MGCb0HFMgh836tWX05P4EIHLAbRe71K9aV0DVf05ZLx6k4GVTWnjN4zvCAe"
+ "wBkvdMCXel9CH96Mx6FcQPGUMwl94DZcZ3W9X00f3iBd8Kvog0bDWY0v0R5Ft7dwAQg0JYSg"
+ "LxAhfMOb8jExW/Uv0R7HSCe8WE6+Uxh0t2QiLM0ZVK/oQUo7fFHa/TJ4RU9QTW+VTuEVY3Uy"
+ "Ee/Z8RsI5RfI9/1meX9QRB/pf/IJ6fxox+P+kOKWArPVb3b1qT8XXKiAPhol+O6nT+L99fW9"
+ "xB1nUxg275cJ/rvjV3l8nj6d3Y57fGJ3CUDOnATNf0ynQG/iX917OjU6Pn6Vx+foU6QzvrtE"
+ "+n0U3b3PwInf4x9JfbR/cHzSzj3iLB3Y5OlrghN9Ps+zES+/duO7h/tMz+IzdFSOKR6Gl5c4"
+ "alLcyWRyDZG91rL7cBfjGPiZHErTp5gNOG5grPyVpsyux3RXkDr9UfoQw3ePgJ5J0RR9inTQ"
+ "zSORHpqKyWSGlhF9PB6NhsYxgP9IdMSn1Zv0KdLRFdbuu4IAvww21bHXkRxEONEPjtCblHqD"
+ "DvApe67ogqerqnIpVTKMGD+vPd5mY3b3ITLqNR3yOvEca2uv1xv+i4AZBOlVjsmE8gYPvnv8"
+ "eFvhmX7S/ls/2oSO4097jnTPIzq4MqNakKMT/v2mST86Anz7dxm1QiflmoDSvUu6d6BzpcnS"
+ "fXrsSGfxqB28B/xY8IrOyovo8EShLhbSfcqcXzc3t5lMgeqDQJUSpmMdX2K7hSMIP/2B53VI"
+ "+jVlYainJTqO0yzcH51RQ/pcx2LxR6AqFdGpDi6hyZWOS9OhAjM91QPTiege0jc3t7b350r7"
+ "PAw/zsEcVo90moFC7EM1HZ4pab9Sc18hfUAj4jBHh7xk9UDnCp6j1+m2rzjPgxX0O7EmpR1H"
+ "VRD0kU61BfsrUzskO9GTLM3QsWvCdoPSCo1P0Skvg9t+vEHjEEe+0PEfLoR+LWOgmn5wMIeU"
+ "Ad9D+OTMudxAX2jkKzo1igmduj0coyvoZDxrBzJgFf03rGhAH0ZqlDCdMnJd+hbSKSWFjvl/"
+ "ctLc8N+gclzVse+s3R+0SNYQnyi1v+mMJN8HPc6rGtH3Te1Cf+OrlWjKdzu6ytra1ve75Ln2"
+ "nSra8cVG3FeL3HS++z3SPhqVaG95Hk2DRFeFQPmO9BcvMN9fwgpdO0M+LGQc3pfT60R/ipVA"
+ "j9VwvkcV51seq89x70J8F7rvXynj+Rflu9QbrAPeOY2Jpzk6wb9RlYDwtnSeO5ZMP0f6T1CA"
+ "M9r39va+ljrD6lMrUpg9uL7ev4anrrV/lEUfFlHPoTOwvJs1cj4XuHTYpJ52MjiITnif6Wo5"
+ "vPzI1vhId4n+i8yrwNzDWQQ/STn7jkHen52Z9MGApA3lavKJV4a1sOuw9CK6guvVAeMNOuTb"
+ "O6Izje9B/sb9K+ctHq4n86rWLnBj7UF4TW8BvU49wVDxNR2POc6fePAtzHvKmoSewM2VDeIT"
+ "OqzlXJfpol7ocAi2ZxgOQ6n26BHyf6AwPDd9N7znnbtGo87zB8TFBVTkJHDfymFbEvzO7pMn"
+ "iq6V66dqPlqEw/5FAgdGzyXFFI2G+ys/UI4HD7T6JFvSOZPKHN5zNADwZ6dzDoHsep27BY1H"
+ "c3bIG0lFlYmZ/p0eLXruPOumEfDt/NxxnE4GjRdG9Vs7TyBMW4x8l97sOTrAOxe0aoL4/Dl3"
+ "neRXHFmwtHlQAzpYn4HnV8OAh4Sg3UalHtZNBfjptA+/MjyOIXO2dnay8IK19nPPOzzkW+E1"
+ "3+z25irp1tV1ZtilQK+k4IAH+ldiQPJZsF6tewpO6iOk30SRsV6Cfh5WCzCf94z1aq2Whxfu"
+ "EyTwOP7wQVYzuJ4Zja4gZP0Es1bzUsut5ZRn8j1//AMvAZPgVbz6DWZ7g14At9rjgBIgeN6F"
+ "4Facqkb5NoTF/gxCaKVn3INeKZTiy+jG7gxOHjKlqvadpMPY84osKR6r5plRRGsONTVJ9eSJ"
+ "Sr7h0C7ZXVqtvU9GCKZwTw+1Y8Vcqb7EmV6C1mrT+5FBgDXzi7THMey8U6dD++94E+m9VK5I"
+ "Mq4L9ZfmTDNDR7z2neCuMfTyFyjfdeMuLdFOm9fJU7V481Sxp5f0Oen9d/pm8dasgi59Tvad"
+ "Da6ZLN7bVNEVnrpMHQuAyyxQMpgs3q/qDtmgWymvrJHSiGS1Wym3ouc75MXCwvNst7TSQcmc"
+ "dlt1qHZvyuy0y+oE8h7p8K7G9v1wZc7oNgpHFdE9oJdlij5mSZe8x9pS+ZZpfbrCY22xeL8n"
+ "fFvt4D3qplVBySugjGH2dMRDrgDdznPrjFS4Tqfz//1fiDjudA7X+38c/wE5II6oZulXWgAA"
+ "AABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+whidbey_dock_pane_top = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR"
+ "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagaHWVcHiYZ3egZ3e1cHilUHjRQXLw"
+ "cYCncYa0dpC4R4DwU4PwZobHYIfTcYXGcIjVcpDBc5fWZpHxcZjgcJj3d6Dld6Pwi5Ozl6e3"
+ "q62xgIjQgpXEgJbUkJjAkJjQgJjggKDXkqHCk6TWhafggqfwh7Dgh7Dwk6Xgk7Tkl7fwoKjA"
+ "oKjWqLDIp7fXsLDIsbbWoLfnoLjwsLjjl8D4pMLwscHnsMfxtdD0wMHg6tTN4Njk5eTo4Of3"
+ "5/D48Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAaHenigAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAe1SURBVGhDpZkNexJHEMcxrTVNao3G0PoSaXmJ4l1soBhCCUdBmkaPCDFWCN//e1z/"
+ "M7O7t/fC3aHzPMqFu/3t/2ZnZmeTUrCBnZ83m2cbPB+UNni4NxweHx/9tsGIDei92bBF9B+L"
+ "44vTu6T8AFb+oTC+ML07gfIjppe/L4ovSofy1nGjIfT9oviC9O6kBZ83flf0ovhi9NccLY2y"
+ "sv39gvhC9NeT4R/HR5q+Xwa9GL4IvQmvLBcRK4gvQG/+DZcvP8JG2hYF1efTSflxY2HIdLHY"
+ "gxVwTi696VGCptLz8Xl0Ud4oR90u2vOXNodOyjlYFjoa+VPT89Rn010ol+xXdP1Bq/oI9jA7"
+ "azPprguX23T4R7QbejY+i/6q1YJXpLYwlZ0foz/4LqOkZdBfvaJgaZQzPbP3IAu/nv7rEYxi"
+ "g+xgIfVrgX+44FV99HAP7J2dra216jO0/3RULkfpPAP9p+lg37u3Hp65r/oHByE9GvDy/e4u"
+ "2Bnw7F3bD+kQbGbS1w/y4Dk9wd29vcePtc5dtp9/1rOQ8jt3MjfBnFwlPLtgd2dnG7YD291V"
+ "88Et2fBU7eNQz2fgiU3kLWVPnhBflHfCRwcpb5GifTw2+M5n4Mkf21vbh7fanvzCPoLy25XB"
+ "+9MUfJI+v55NuqKjswLw7v3729vPDVounj6ld6Grzi0/6vvTqRplvUOCPie64Dsrot9u3X//"
+ "PgbHj5VthgPP8BkGDZtx58TpYNODo7cMZ/ri3yQb3/yjv+0EN77QE/gYnZTjuclodH4OONON"
+ "XV1dXcLic606V7PZdDoaDRP4KH0O4TPaOPHgX1HK9eWE32oy6fXG0VtXRJ/QmDg+Qp8THbqZ"
+ "PmxGZF+Ty5g+mYzHA+see4X8ksTb9DnRySui3atpBPxlsQk1euvrm+JzQ4/43qIDPhefK7rG"
+ "86x4d8tGI1/wC7CnfEtpH7asyAnpeMz4fOh5XrfbHfxHgGsY61Ue05h3hs7TGrqFN3R6wdDn"
+ "RHccpsMr1ywuQWf8Dd3TZPpstUK8prPykEDSnXN+d9Dl1eN0T5Y9hW7wii7K0+hY0ekauseR"
+ "Y3tF3iFUL3Ra9tUSRhlEn17fcdos7ZIDYkQ3lNH9JSB4P36CPSPDlBk80zmoVp8+faJBZCEd"
+ "iSJ03LVM0Rl/Sa+8kmQaLpmi8UTngB3J95qONWXtFyqYU+l9zoh0euslyKBLOiToFX7tC4nz"
+ "4Rr6jbgmph3SW60TxH0p4Npi3klpR7Az3URpjL5iv7suh1UvnX5yFpQ4D8lp2jM0cKnplzoH"
+ "sugDvNyKVlZTWiewN2/6/RL5hTNf0VcR+gB+4ThfQ2fHGzqGMkXoruOUBr7KEqFzRIbai9Eh"
+ "YTXheLXorlurlLx3pByrENHu9V0ji5ciTXu/K3FFEtgzEe1us1YrvfOYbejivWJ0FbWGbvzu"
+ "wmq1drsU9Jgd0iWbvC5rH49ViUrTDsfyNqjpJptaDK+2Kd5fYhFS6JLm2fQK0yldyDOG/obg"
+ "z55xNgUvaIm131UlQAm+UPFgRlEl0MWGqoxzyjlxk0KvgS65KviidJG4Evop0f0Z+oFInXFE"
+ "uaIz3qpxqJEw2ZnfYtXVakH6R1pzolMRdar8hNBViWWKU6syXHeprB4mYynLQWe8J/ShTL76"
+ "KK7xiF5jOu304cZC5UErN3Tx/cmJTe/3WdpAz6Y/aWbPA1ukJ+jkF9XymX1V8BYd8cYt3kBo"
+ "8g76miOOe705bVzhMFt5qF1Fjv2Y41S4Jxgofkh3MXO1+ifD57S3WMMs5TadnWMe43wQulav"
+ "6ZSI8AvDb2+79mbedep1iRYxuxdTvicPuW69XpH9A3Z2hopsDMsJn5sWuGmUD4egq2hJ0vXS"
+ "EhyPGTgprLFitnq99lwWVKwpi9GHRZVHtSvfE5yCygLgst0+hRG7UpFuIYYHvBZVHqeLevJ5"
+ "9VknisBPp6fVarUdQ9PErB5wlaHpfueiIMWTloZPTbAvXxLzmG8ps3C0cZFDgJs4T1tV/g54"
+ "nchKve/zzh+z+byHbwQeBFiWuM/jMSMzvnCcw0O5ZPX+9Wx6Ybp1Ncc1dSmo0QpO+HpCecLv"
+ "xKw4Cg484ESf+r51XkI/j9MCUrRrnVcr1Wro77WewQ0DD4IPH/Rphs4z4/EFTJ+f6Ah5HhJT"
+ "4Hl/mfggR0Bj1FmZ8xPSyKInlad6xnpMjkQoARqPZnuqW3GuGokDcGSSzN9x6EOu0LHFGguL"
+ "SyY+i24f5lRvr/t7Xe2Qe06aS9R3GXT6xYI5E+neW21UFv2kth6/nt6LnOQUXW2rZi5IR8Vc"
+ "i8/Qjr/ShLaGTjXzq7QHAX5/zZ0O7eZMl0aUtnD6TyqSzutU/Zkx04zRCS8NgqKjcFmpVyxX"
+ "w6ekSzPa5QAQ0pMlNzZBzu/0TJ+TEjNwS0rhKp5NVDGlz2lFOjXq1aKtxZqoydGu8dxlhrYE"
+ "3LRzX5dNalTYIVv0QsrzqphsJ7pDtulFlBeiJzvk5TI3WuTFc/1u1PPxR3WokXbum/yu8Rz3"
+ "RO92sYVa7dw308X3mu6kbdCbVwJrhIp7qi1prcXXxrseJ3gqXPF27ts9Q4FJuvlUkLb7p09R"
+ "KGZkKHdpsOLwYhGphLXbbTqeZ3gifmsD7UHQbh/WNoEH/wMcYo64Ex2PFwAAAABJRU5ErkJg"
+ "gg==")
+
+#----------------------------------------------------------------------
+whidbey_left = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB4AAAArCAMAAABYWciOAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAaHWVZ3egZ3e1cHilcYCncYa0dpC4ZobHcYXGcpDBc5fWd6Dld6Pwi5OzgIjQ"
+ "gJbUkJjQgJjggKDXkqHCk6TWhafggqfwh7Dwk6Xgk7Tkl7fwoKjWqLDIoLfnpMLwscHnsMfx"
+ "tdD04Njk5/D49/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAQ3JLMwAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAF4SURBVDhPfdTbdoIwEAVQL6htAi0tElBaoVb+/xPTM5M7wc6LLvc6GTIJbnRel/DT"
+ "ZkUvwXOefsahdqGMJ2LvSwaO4P7d5BdMWejQ9+dzzhOiY4/quu4z44kYSebudbH4REwLm7Q6"
+ "Jr2hk+lrGR4e7Rb17ZRSdV23v55vxL4vsRCBOesXRrquBbZm0yb7jIHD/EDNKPpUjRBvbmOU"
+ "Heb7/f6g/aISJhz6R8J4MJvmbM6FGSrPmRaM09i0YZ4zDdHxTN8909I8RMtzyu3NztgwbyxK"
+ "qytlq6pK0qqROC/0vipGzx0v7ll/MAY2Y1G1SWv9UpXlCvNlpiPZlyjX2w4VJ/rlZk7+D3Oe"
+ "DsoXwqoNV5HzKHtidJlUC3eXifuXZcxNE91U4xFLIb6jm8oeWIKLcFPN/jxLKY/HhM3+TUl5"
+ "OhU48eQN9Y6VTwe6D+kLbJ0W3m5X3m926ntgXb7+eg/z2ZzJhcuusN4Lsds9/WfSuhBes94U"
+ "C6r/AM3yZVcU56/qAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+whidbey_left_single = whidbey_left
+
+#----------------------------------------------------------------------
+whidbey_left_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB4AAAArCAMAAABYWciOAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR"
+ "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagcHiYZ3egcHilUHjRQXLwR4DwU4Pw"
+ "YIfTcYXGcIjVc5fWZpHxcJj3d6PwgJbUkJjAkJjQkqHChafggqfwh7Dgh7Dwl7fwoKjAqLDI"
+ "sLDIl8D4pMLw4Of35/D4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAQS37pgAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAGNSURBVDhPfdRrW8IgFAdwLyuXZLIUy67D6dK0pd3w+38xOuewAYOMN3ue/fbnwHZG"
+ "R8ej5251Yu33nMfcHw8H1iNOxsiNh5xkGUfvmqIBg2YZ8KBrvM3J5BoGH7NBnW9xMjHMGTjl"
+ "fQYlxvKYh/V5jErc5MEdJxMOAx/BKxZI0w/LkI340aZx5jZzdmdrU92TjKr8IbB2szHKqv1+"
+ "r2Y4hFDINzWf082A2Xxu+II0TDNU4KcnAcNPz4TiV0P6pp1XKduM9R0XZdlipXBpnNXpgGl3"
+ "Hu+qdSnzZ1sb0libpab2rqrKMs/d0tqstz+QhwfUt/dabFrrbYXzy1OsNwf0Fgs2TB+ad77B"
+ "6SNOba9B/uV49D6ZqIvX3bJp1m++mEBO710rLg8wv8wNmVZj6ZdrxeWatmcZW9FjXbxj3ufR"
+ "6NPr8wLyHnM28vtc6+INX08+w9LTKednwS9I+TwnJg3+UMoTGw3/7wKndxqyXq3gAdg9ZaO0"
+ "1oab8yo+mRYLKe1p9se5tpCX/7G+dUfhL8vucupsrDz0AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+whidbey_left_focus_single = whidbey_left_focus
+
+#----------------------------------------------------------------------
+whidbey_right = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB4AAAArCAMAAABYWciOAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAaHWVcHilcYCncYa0dpC4ZobHcYXGcpDBc5fWcZjgd6Dld6Pwi5OzgJbUkJjA"
+ "kJjQgKDXk6TWhafggqfwh7Dwl7fwp7fXoLfnoLjwsLjjpMLwscHntdD0wMHg4Of35/D49/f3"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAWZqHkAAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAFySURBVDhPddPbeoIwDABglDqoFDcVGBVw8P4PyXJoQ0sxN+L3m0NDzVaJx/YoT5k8"
+ "9fbAhfve2luS77kfhq5rir077pkTZ34Ng7Vt2yRO/ELuUPeOTIWxdOrA3Fc46p/9AVobsgnm"
+ "Z0b1xRsTeLa+EV1f+jCBQ+8DlnzgsDBX2fLxYFR8WeYtxJF/u65tF95KM0/TNEv+ZzZfkElL"
+ "TbKhuDEVnJ/4Z1+cufpmfsBwC47newNV1fV6v8cMTqMx67Jkhs0s3YIRsNbqHDCePczWhVIx"
+ "S28NoVRdRyxrMaR5zZPjdcDJha+opxOf+33ACthtrR/glkY7LzmXs5npjbn3VqqcFHmE2i0E"
+ "934+fd9PjKXdvylbR7yn/q7FuVB8HOF9uMJUOsjF3retb9PcysuFZ+aA0QrJJXYzC6/Fk+IO"
+ "Eee628IOquJcx5wP6nYV9cYvGpYBKucNRqNHpfW+r9+580uS63vjD855vvXcF4fvB7r+A9+i"
+ "Xf4K/oDaAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+whidbey_right_single = whidbey_right
+
+#----------------------------------------------------------------------
+whidbey_right_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAB4AAAArCAMAAABYWciOAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR"
+ "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagcHiYZ3egcHilUHjRQXLwR4DwU4Pw"
+ "YIfTcYXGcIjVc5fWZpHxcJj3d6PwgJbUkJjAkJjQkqHChafggqfwh7Dgh7Dwl7fwoKjAqLDI"
+ "sLDIl8D4pMLw4Of35/D4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAQS37pgAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAGXSURBVDhPdZTZVoNADEDpaC2CFSqC1hVaxWoVqdv0/39szDIraF7gcHuTTCankbJx"
+ "6V7tW2TfTprVmDvcNKsxt7ismnbzOPQ1npaMh5zxNMdo4Afr0CfMNK8Bv4UcMdBzwshDHzBS"
+ "wlWN6QM/UmKecu68hBj40ed8nmrOuN28u/qR+op9XNfANw+mf8asow31ge8Mh9au4zhlRIF+"
+ "1z2zjwcTiKWL/f6p2zFHHMdJWkpty77/lpCffcQ3IwzHY5+GitkDG8fTddv/MB2v+9n6dlVJ"
+ "aBxq9/Dk/l+95IDgu8b3eD0GJ1ibTmYwzqFt12wTLn07xKc51XW16XqaF20D1jPVtRHf3XHn"
+ "Sxyqm1ovC5r+MZ97OcJEj/TULuA+B3ZRFIdm5njd/o1JaSgmvzK7Bh8LXAt8kku1/8KaAr61"
+ "u+ZsQ1X0Aauks1tsKdhCzGb4gzMKr66uTTzLFwuNnctjmUycb3t2m6om7JPtu3qZyE+yBURI"
+ "+UogvwAM5QfUYOw/ybIhtVghPuBUXrg/LiHG1NmwcSNXqV+4tHLqnJPo+QAAAABJRU5ErkJg"
+ "gg==")
+
+#----------------------------------------------------------------------
+whidbey_right_focus_single = whidbey_right_focus
+
+#----------------------------------------------------------------------
+whidbey_up = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACsAAAAeCAMAAACCNBfsAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAaHWVcHilcYCncYa0dpC4ZobHcYXGcpDBc5fWcZjgd6Dld6Pwi5OzgJbUkJjA"
+ "kJjQgKDXk6TWhafggqfwh7Dwl7fwp7fXoLfnoLjwsLjjpMLwscHntdD0wMHg4Of35/D49/f3"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAWZqHkAAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAFmSURBVDhPhdTtdoMgDAZgW3GKWjsL2i/X2vu/SJaEBBXcWf6Jz3l5i9bMpdNXR3Xa"
+ "Wc/StXNfKXXawaktm1rrUuWHJCWxX01TA1bqkODYlm3bNjCAVYwji9TbneStJcoWcNR5Yz0V"
+ "mySvLVJrvW/buq7g7NadVxbpvJ3taSyWUuef9cx6kxwsdU3sprPY0tJEucboqginwZapjfqC"
+ "1UUhT9BboXb28Twfa42pQjLZQMUCwiHbdZKMdqFsPx+PeZee3w2w3WpXugvUY7GAsXPmLvdx"
+ "HITzXe4QbK8Klbvsckcr+C/bF0WeZ+52ez6Bw+D2AwxdwAxwhRsaPDp9hA4OLWGpSn1pVlZh"
+ "X8Cg2dpNLlxwrgFKFpP/sRqZf26Ph3T2Te8w3AyijSlJ8fuA1v/Acfy+0Dxp8DyZig2dr9fw"
+ "WXj5ExoGnxpy5TSi78c0gRUacvE0XjvfsGnqwuryH3q/d6hz07L6CxOEXf5LAPv7AAAAAElF"
+ "TkSuQmCC")
+
+#----------------------------------------------------------------------
+whidbey_up_single = whidbey_up
+
+#----------------------------------------------------------------------
+whidbey_up_focus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACsAAAAeCAMAAACCNBfsAAAAAXNSR0IArs4c6QAAAARnQU1B"
+ "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR"
+ "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagcHiYZ3egcHilUHjRQXLwR4DwU4Pw"
+ "YIfTcYXGcIjVc5fWZpHxcJj3d6PwgJbUkJjAkJjQkqHChafggqfwh7Dgh7Dwl7fwoKjAqLDI"
+ "sLDIl8D4pMLw4Of35/D4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAQS37pgAAAQB0Uk5T////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn"
+ "4iUAAAGTSURBVDhPfdQNV4IwFAZgpEyCVBRZaR8OUcI0yrLw//8xuvfuy22e7jkKZz68uxtg"
+ "0Pm135fl24XxwB/bNU1VFS/+D77d/TY12lsPe3aLqTkUu3Gxa7cHSC3IsmsHOxZS64pzYTMH"
+ "23Z7qKFXvpTWwZZd0w5wJivLbHxu14fmtSqUzRhYC5/ZEuY/tVbZ2NjyA1o9/UB9qmrtZG0x"
+ "teKtdnjSplCmDWXLd7xZF63G0opUzux2Ra5eoLCYShvQqv2io7IymewGUsV9lVYdcG1TqAnd"
+ "QbSbDbR6bqETkastYbCruob5xTNAhpp27PgK7WqFG8DZvz2kY8DBQwGF68XKW/HUtPCBE1rb"
+ "dJKCjOMwDLq7gjHbkscvZUEOBiGtLc+NtTdYjCcJyFDsQ2cshOnr1PlYUmH7aTqbqYyEajRS"
+ "12Bqr6f2V2CaLInjCCqGShJ5NTRAVOQSRokulDWfozap2gLGmaMwetIv7/yeulGpxnb94TCK"
+ "Hp23fLHAedSgeS/C4fHo/y89R5qqfhF9+xJGvszoH5Xccuo6pVT3AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+whidbey_up_focus_single = whidbey_up_focus
+
+#----------------------------------------------------------------------
+
+whidbey_denied = aero_denied
+
+#----------------------------------------------------------------------
+
+# ------------------------ #
+# - AuiToolBar Constants - #
+# ------------------------ #
+
+ITEM_CONTROL = wx.ITEM_MAX
+""" The item in the AuiToolBar is a control. """
+ITEM_LABEL = ITEM_CONTROL + 1
+""" The item in the AuiToolBar is a text label. """
+ITEM_SPACER = ITEM_CONTROL + 2
+""" The item in the AuiToolBar is a spacer. """
+ITEM_SEPARATOR = wx.ITEM_SEPARATOR
+""" The item in the AuiToolBar is a separator. """
+ITEM_CHECK = wx.ITEM_CHECK
+""" The item in the AuiToolBar is a toolbar check item. """
+ITEM_NORMAL = wx.ITEM_NORMAL
+""" The item in the AuiToolBar is a standard toolbar item. """
+ITEM_RADIO = wx.ITEM_RADIO
+""" The item in the AuiToolBar is a toolbar radio item. """
+ID_RESTORE_FRAME = wx.ID_HIGHEST + 10000
+""" Identifier for restoring a minimized pane. """
+
+BUTTON_DROPDOWN_WIDTH = 10
+""" Width of the drop-down button in AuiToolBar. """
+
+DISABLED_TEXT_GREY_HUE = 153.0
+""" Hue text colour for the disabled text in AuiToolBar. """
+DISABLED_TEXT_COLOUR = wx.Colour(DISABLED_TEXT_GREY_HUE,
+ DISABLED_TEXT_GREY_HUE,
+ DISABLED_TEXT_GREY_HUE)
+""" Text colour for the disabled text in AuiToolBar. """
+
+AUI_TB_TEXT = 1 << 0
+""" Shows the text in the toolbar buttons; by default only icons are shown. """
+AUI_TB_NO_TOOLTIPS = 1 << 1
+""" Don't show tooltips on `AuiToolBar` items. """
+AUI_TB_NO_AUTORESIZE = 1 << 2
+""" Do not auto-resize the `AuiToolBar`. """
+AUI_TB_GRIPPER = 1 << 3
+""" Shows a gripper on the `AuiToolBar`. """
+AUI_TB_OVERFLOW = 1 << 4
+""" The `AuiToolBar` can contain overflow items. """
+AUI_TB_VERTICAL = 1 << 5
+""" The `AuiToolBar` is vertical. """
+AUI_TB_HORZ_LAYOUT = 1 << 6
+""" Shows the text and the icons alongside, not vertically stacked.
+This style must be used with ``AUI_TB_TEXT``. """
+AUI_TB_PLAIN_BACKGROUND = 1 << 7
+""" Don't draw a gradient background on the toolbar. """
+AUI_TB_CLOCKWISE = 1 << 8
+AUI_TB_COUNTERCLOCKWISE = 1 << 9
+
+AUI_TB_HORZ_TEXT = AUI_TB_HORZ_LAYOUT | AUI_TB_TEXT
+""" Combination of ``AUI_TB_HORZ_LAYOUT`` and ``AUI_TB_TEXT``. """
+AUI_TB_VERT_TEXT = AUI_TB_VERTICAL | AUI_TB_CLOCKWISE | AUI_TB_TEXT
+
+AUI_TB_DEFAULT_STYLE = 0
+""" `AuiToolBar` default style. """
+
+# AuiToolBar settings
+AUI_TBART_SEPARATOR_SIZE = 0
+""" Separator size in AuiToolBar. """
+AUI_TBART_GRIPPER_SIZE = 1
+""" Gripper size in AuiToolBar. """
+AUI_TBART_OVERFLOW_SIZE = 2
+""" Overflow button size in AuiToolBar. """
+
+# AuiToolBar text orientation
+AUI_TBTOOL_TEXT_LEFT = 0 # unused/unimplemented
+""" Text in AuiToolBar items is aligned left. """
+AUI_TBTOOL_TEXT_RIGHT = 1
+""" Text in AuiToolBar items is aligned right. """
+AUI_TBTOOL_TEXT_TOP = 2 # unused/unimplemented
+""" Text in AuiToolBar items is aligned top. """
+AUI_TBTOOL_TEXT_BOTTOM = 3
+""" Text in AuiToolBar items is aligned bottom. """
+
+# AuiToolBar tool orientation
+AUI_TBTOOL_HORIZONTAL = 0 # standard
+AUI_TBTOOL_VERT_CLOCKWISE = 1 # rotation of 90 on the right
+AUI_TBTOOL_VERT_COUNTERCLOCKWISE = 2 # rotation of 90 on the left
+
+
+# --------------------- #
+# - AuiMDI* Constants - #
+# --------------------- #
+
+wxWINDOWCLOSE = 4001
+""" Identifier for the AuiMDI "close window" menu. """
+wxWINDOWCLOSEALL = 4002
+""" Identifier for the AuiMDI "close all windows" menu. """
+wxWINDOWNEXT = 4003
+""" Identifier for the AuiMDI "next window" menu. """
+wxWINDOWPREV = 4004
+""" Identifier for the AuiMDI "previous window" menu. """
+
+# ----------------------------- #
+# - AuiDockingGuide Constants - #
+# ----------------------------- #
+
+colourTargetBorder = wx.Colour(180, 180, 180)
+colourTargetShade = wx.Colour(206, 206, 206)
+colourTargetBackground = wx.Colour(224, 224, 224)
+colourIconBorder = wx.Colour(82, 65, 156)
+colourIconBackground = wx.Colour(255, 255, 255)
+colourIconDockingPart1 = wx.Colour(215, 228, 243)
+colourIconDockingPart2 = wx.Colour(180, 201, 225)
+colourIconShadow = wx.Colour(198, 198, 198)
+colourIconArrow = wx.Colour(77, 79, 170)
+colourHintBackground = wx.Colour(0, 64, 255)
+guideSizeX, guideSizeY = 29, 32
+aeroguideSizeX, aeroguideSizeY = 31, 32
+whidbeySizeX, whidbeySizeY = 43, 30
+
+# ------------------------------- #
+# - AuiSwitcherDialog Constants - #
+# ------------------------------- #
+
+SWITCHER_TEXT_MARGIN_X = 4
+SWITCHER_TEXT_MARGIN_Y = 1
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_switcherdialog.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_switcherdialog.py
new file mode 100644
index 0000000..4cf3923
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_switcherdialog.py
@@ -0,0 +1,1215 @@
+"""
+Description
+===========
+
+The idea of `SwitcherDialog` is to make it easier to implement keyboard
+navigation in AUI and other applications that have multiple panes and
+tabs.
+
+A key combination with a modifier (such as ``Ctrl`` + ``Tab``) shows the
+dialog, and the user holds down the modifier whilst navigating with
+``Tab`` and arrow keys before releasing the modifier to dismiss the dialog
+and activate the selected pane.
+
+The switcher dialog is a multi-column menu with no scrolling, implemented
+by the :class:`MultiColumnListCtrl` class. You can have headings for your items
+for logical grouping, and you can force a column break if you need to.
+
+The modifier used for invoking and dismissing the dialog can be customised,
+as can the colours, number of rows, and the key used for cycling through
+the items. So you can use different keys on different platforms if
+required (especially since ``Ctrl`` + ``Tab`` is reserved on some platforms).
+
+Items are shown as names and optional 16x16 images.
+
+
+Base Functionalities
+====================
+
+To use the dialog, you set up the items in a `SwitcherItems` object,
+before passing this to the `SwitcherDialog` instance.
+
+Call :meth:`SwitcherItems.AddItem` and optionally :meth:`SwitcherItems.AddGroup`
+to add items and headings. These functions take a label (to be displayed to the user),
+an identifying name, an integer id, and a bitmap. The name and id are purely for
+application-defined identification. You may also set a description to be displayed
+when each item is selected; and you can set a window pointer for convenience when
+activating the desired window after the dialog returns.
+
+Have created the dialog, you call :meth:`~Dialog.ShowModal`, and if the return value is
+``wx.ID_OK``, retrieve the selection from the dialog and activate the pane.
+
+The sample code below shows a generic method of finding panes and notebook
+tabs within the current :class:`~lib.agw.aui.framemanager.AuiManager`, and using the pane name or notebook
+tab position to display the pane.
+
+The only other code to add is a menu item with the desired accelerator,
+whose modifier matches the one you pass to :meth:`SwitcherDialog.SetModifierKey`
+(the default being ``wx.WXK_CONTROL``).
+
+
+Usage
+=====
+
+Menu item::
+
+ if wx.Platform == "__WXMAC__":
+ switcherAccel = "Alt+Tab"
+ elif wx.Platform == "__WXGTK__":
+ switcherAccel = "Ctrl+/"
+ else:
+ switcherAccel = "Ctrl+Tab"
+
+ view_menu.Append(ID_SwitchPane, _("S&witch Window...") + "\t" + switcherAccel)
+
+
+Event handler::
+
+ def OnSwitchPane(self, event):
+
+ items = SwitcherItems()
+ items.SetRowCount(12)
+
+ # Add the main windows and toolbars, in two separate columns
+ # We'll use the item 'id' to store the notebook selection, or -1 if not a page
+
+ for k in xrange(2):
+ if k == 0:
+ items.AddGroup(_("Main Windows"), "mainwindows")
+ else:
+ items.AddGroup(_("Toolbars"), "toolbars").BreakColumn()
+
+ for pane in self._mgr.GetAllPanes():
+ name = pane.name
+ caption = pane.caption
+
+ toolbar = isinstance(info.window, wx.ToolBar) or isinstance(info.window, aui.AuiToolBar)
+ if caption and (toolBar and k == 1) or (not toolBar and k == 0):
+ items.AddItem(caption, name, -1).SetWindow(pane.window)
+
+ # Now add the wxAuiNotebook pages
+
+ items.AddGroup(_("Notebook Pages"), "pages").BreakColumn()
+
+ for pane in self._mgr.GetAllPanes():
+ nb = pane.window
+ if isinstance(nb, aui.AuiNotebook):
+ for j in xrange(nb.GetPageCount()):
+
+ name = nb.GetPageText(j)
+ win = nb.GetPage(j)
+
+ items.AddItem(name, name, j, nb.GetPageBitmap(j)).SetWindow(win)
+
+ # Select the focused window
+
+ idx = items.GetIndexForFocus()
+ if idx != wx.NOT_FOUND:
+ items.SetSelection(idx)
+
+ if wx.Platform == "__WXMAC__":
+ items.SetBackgroundColour(wx.WHITE)
+
+ # Show the switcher dialog
+
+ dlg = SwitcherDialog(items, wx.GetApp().GetTopWindow())
+
+ # In GTK+ we can't use Ctrl+Tab; we use Ctrl+/ instead and tell the switcher
+ # to treat / in the same was as tab (i.e. cycle through the names)
+
+ if wx.Platform == "__WXGTK__":
+ dlg.SetExtraNavigationKey(wxT('/'))
+
+ if wx.Platform == "__WXMAC__":
+ dlg.SetBackgroundColour(wx.WHITE)
+ dlg.SetModifierKey(wx.WXK_ALT)
+
+ ans = dlg.ShowModal()
+
+ if ans == wx.ID_OK and dlg.GetSelection() != -1:
+ item = items.GetItem(dlg.GetSelection())
+
+ if item.GetId() == -1:
+ info = self._mgr.GetPane(item.GetName())
+ info.Show()
+ self._mgr.Update()
+ info.window.SetFocus()
+
+ else:
+ nb = item.GetWindow().GetParent()
+ win = item.GetWindow();
+ if isinstance(nb, aui.AuiNotebook):
+ nb.SetSelection(item.GetId())
+ win.SetFocus()
+
+
+"""
+
+import wx
+
+import auibook
+from aui_utilities import FindFocusDescendant
+from aui_constants import SWITCHER_TEXT_MARGIN_X, SWITCHER_TEXT_MARGIN_Y
+
+
+# Define a translation function
+_ = wx.GetTranslation
+
+
+class SwitcherItem(object):
+ """ An object containing information about one item. """
+
+ def __init__(self, item=None):
+ """ Default class constructor. """
+
+ self._id = 0
+ self._isGroup = False
+ self._breakColumn = False
+ self._rowPos = 0
+ self._colPos = 0
+ self._window = None
+ self._description = ""
+
+ self._textColour = wx.NullColour
+ self._bitmap = wx.NullBitmap
+ self._font = wx.NullFont
+
+ if item:
+ self.Copy(item)
+
+
+ def Copy(self, item):
+ """
+ Copy operator between 2 :class:`SwitcherItem` instances.
+
+ :param `item`: another instance of :class:`SwitcherItem`.
+ """
+
+ self._id = item._id
+ self._name = item._name
+ self._title = item._title
+ self._isGroup = item._isGroup
+ self._breakColumn = item._breakColumn
+ self._rect = item._rect
+ self._font = item._font
+ self._textColour = item._textColour
+ self._bitmap = item._bitmap
+ self._description = item._description
+ self._rowPos = item._rowPos
+ self._colPos = item._colPos
+ self._window = item._window
+
+
+ def SetTitle(self, title):
+
+ self._title = title
+ return self
+
+
+ def GetTitle(self):
+
+ return self._title
+
+
+ def SetName(self, name):
+
+ self._name = name
+ return self
+
+
+ def GetName(self):
+
+ return self._name
+
+
+ def SetDescription(self, descr):
+
+ self._description = descr
+ return self
+
+
+ def GetDescription(self):
+
+ return self._description
+
+
+ def SetId(self, id):
+
+ self._id = id
+ return self
+
+
+ def GetId(self):
+
+ return self._id
+
+
+ def SetIsGroup(self, isGroup):
+
+ self._isGroup = isGroup
+ return self
+
+
+ def GetIsGroup(self):
+
+ return self._isGroup
+
+
+ def BreakColumn(self, breakCol=True):
+
+ self._breakColumn = breakCol
+ return self
+
+
+ def GetBreakColumn(self):
+
+ return self._breakColumn
+
+
+ def SetRect(self, rect):
+
+ self._rect = rect
+ return self
+
+
+ def GetRect(self):
+
+ return self._rect
+
+
+ def SetTextColour(self, colour):
+
+ self._textColour = colour
+ return self
+
+
+ def GetTextColour(self):
+
+ return self._textColour
+
+
+ def SetFont(self, font):
+
+ self._font = font
+ return self
+
+
+ def GetFont(self):
+
+ return self._font
+
+
+ def SetBitmap(self, bitmap):
+
+ self._bitmap = bitmap
+ return self
+
+
+ def GetBitmap(self):
+
+ return self._bitmap
+
+
+ def SetRowPos(self, pos):
+
+ self._rowPos = pos
+ return self
+
+
+ def GetRowPos(self):
+
+ return self._rowPos
+
+
+ def SetColPos(self, pos):
+
+ self._colPos = pos
+ return self
+
+
+ def GetColPos(self):
+
+ return self._colPos
+
+
+ def SetWindow(self, win):
+
+ self._window = win
+ return self
+
+
+ def GetWindow(self):
+
+ return self._window
+
+
+class SwitcherItems(object):
+ """ An object containing switcher items. """
+
+ def __init__(self, items=None):
+ """ Default class constructor. """
+
+ self._selection = -1
+ self._rowCount = 10
+ self._columnCount = 0
+
+ self._backgroundColour = wx.NullColour
+ self._textColour = wx.NullColour
+ self._selectionColour = wx.NullColour
+ self._selectionOutlineColour = wx.NullColour
+ self._itemFont = wx.NullFont
+
+ self._items = []
+
+ if wx.Platform == "__WXMSW__":
+ # If on Windows XP/Vista, use more appropriate colours
+ self.SetSelectionOutlineColour(wx.Colour(49, 106, 197))
+ self.SetSelectionColour(wx.Colour(193, 210, 238))
+
+ if items:
+ self.Copy(items)
+
+
+ def Copy(self, items):
+ """
+ Copy operator between 2 :class:`SwitcherItems`.
+
+ :param `items`: another instance of :class:`SwitcherItems`.
+ """
+
+ self.Clear()
+
+ for item in items._items:
+ self._items.append(item)
+
+ self._selection = items._selection
+ self._rowCount = items._rowCount
+ self._columnCount = items._columnCount
+
+ self._backgroundColour = items._backgroundColour
+ self._textColour = items._textColour
+ self._selectionColour = items._selectionColour
+ self._selectionOutlineColour = items._selectionOutlineColour
+ self._itemFont = items._itemFont
+
+
+ def AddItem(self, titleOrItem, name=None, id=0, bitmap=wx.NullBitmap):
+
+ if isinstance(titleOrItem, SwitcherItem):
+ self._items.append(titleOrItem)
+ return self._items[-1]
+
+ item = SwitcherItem()
+ item.SetTitle(titleOrItem)
+ item.SetName(name)
+ item.SetId(id)
+ item.SetBitmap(bitmap)
+
+ self._items.append(item)
+ return self._items[-1]
+
+
+ def AddGroup(self, title, name, id=0, bitmap=wx.NullBitmap):
+
+ item = self.AddItem(title, name, id, bitmap)
+ item.SetIsGroup(True)
+
+ return item
+
+
+ def Clear(self):
+
+ self._items = []
+
+
+ def FindItemByName(self, name):
+
+ for i in xrange(len(self._items)):
+ if self._items[i].GetName() == name:
+ return i
+
+ return wx.NOT_FOUND
+
+
+ def FindItemById(self, id):
+
+ for i in xrange(len(self._items)):
+ if self._items[i].GetId() == id:
+ return i
+
+ return wx.NOT_FOUND
+
+
+ def SetSelection(self, sel):
+
+ self._selection = sel
+
+
+ def SetSelectionByName(self, name):
+
+ idx = self.FindItemByName(name)
+ if idx != wx.NOT_FOUND:
+ self.SetSelection(idx)
+
+
+ def GetSelection(self):
+
+ return self._selection
+
+
+ def GetItem(self, i):
+
+ return self._items[i]
+
+
+ def GetItemCount(self):
+
+ return len(self._items)
+
+
+ def SetRowCount(self, rows):
+
+ self._rowCount = rows
+
+
+ def GetRowCount(self):
+
+ return self._rowCount
+
+
+ def SetColumnCount(self, cols):
+
+ self._columnCount = cols
+
+
+ def GetColumnCount(self):
+
+ return self._columnCount
+
+
+ def SetBackgroundColour(self, colour):
+
+ self._backgroundColour = colour
+
+
+ def GetBackgroundColour(self):
+
+ return self._backgroundColour
+
+
+ def SetTextColour(self, colour):
+
+ self._textColour = colour
+
+
+ def GetTextColour(self):
+
+ return self._textColour
+
+
+ def SetSelectionColour(self, colour):
+
+ self._selectionColour = colour
+
+
+ def GetSelectionColour(self):
+
+ return self._selectionColour
+
+
+ def SetSelectionOutlineColour(self, colour):
+
+ self._selectionOutlineColour = colour
+
+
+ def GetSelectionOutlineColour(self):
+
+ return self._selectionOutlineColour
+
+
+ def SetItemFont(self, font):
+
+ self._itemFont = font
+
+
+ def GetItemFont(self):
+
+ return self._itemFont
+
+
+ def PaintItems(self, dc, win):
+
+ backgroundColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
+ standardTextColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ selectionColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ selectionOutlineColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ standardFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ groupFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ groupFont.SetWeight(wx.BOLD)
+
+ if self.GetBackgroundColour().IsOk():
+ backgroundColour = self.GetBackgroundColour()
+
+ if self.GetTextColour().IsOk():
+ standardTextColour = self.GetTextColour()
+
+ if self.GetSelectionColour().IsOk():
+ selectionColour = self.GetSelectionColour()
+
+ if self.GetSelectionOutlineColour().IsOk():
+ selectionOutlineColour = self.GetSelectionOutlineColour()
+
+ if self.GetItemFont().IsOk():
+
+ standardFont = self.GetItemFont()
+ groupFont = wx.Font(standardFont.GetPointSize(), standardFont.GetFamily(), standardFont.GetStyle(),
+ wx.BOLD, standardFont.GetUnderlined(), standardFont.GetFaceName())
+
+ textMarginX = SWITCHER_TEXT_MARGIN_X
+
+ dc.SetLogicalFunction(wx.COPY)
+ dc.SetBrush(wx.Brush(backgroundColour))
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.DrawRectangleRect(win.GetClientRect())
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+
+ for i in xrange(len(self._items)):
+ item = self._items[i]
+ if i == self._selection:
+ dc.SetPen(wx.Pen(selectionOutlineColour))
+ dc.SetBrush(wx.Brush(selectionColour))
+ dc.DrawRectangleRect(item.GetRect())
+
+ clippingRect = wx.Rect(*item.GetRect())
+ clippingRect.Deflate(1, 1)
+
+ dc.SetClippingRect(clippingRect)
+
+ if item.GetTextColour().IsOk():
+ dc.SetTextForeground(item.GetTextColour())
+ else:
+ dc.SetTextForeground(standardTextColour)
+
+ if item.GetFont().IsOk():
+ dc.SetFont(item.GetFont())
+ else:
+ if item.GetIsGroup():
+ dc.SetFont(groupFont)
+ else:
+ dc.SetFont(standardFont)
+
+ w, h = dc.GetTextExtent(item.GetTitle())
+ x = item.GetRect().x
+
+ x += textMarginX
+
+ if not item.GetIsGroup():
+ if item.GetBitmap().IsOk() and item.GetBitmap().GetWidth() <= 16 \
+ and item.GetBitmap().GetHeight() <= 16:
+ x -= textMarginX
+ dc.DrawBitmap(item.GetBitmap(), x, item.GetRect().y + \
+ (item.GetRect().height - item.GetBitmap().GetHeight())/2,
+ True)
+ x += 16 + textMarginX
+ #x += textMarginX
+
+ y = item.GetRect().y + (item.GetRect().height - h)/2
+ dc.DrawText(item.GetTitle(), x, y)
+ dc.DestroyClippingRegion()
+
+
+ def CalculateItemSize(self, dc):
+
+ # Start off allowing for an icon
+ sz = wx.Size(150, 16)
+ standardFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ groupFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ groupFont.SetWeight(wx.BOLD)
+
+ textMarginX = SWITCHER_TEXT_MARGIN_X
+ textMarginY = SWITCHER_TEXT_MARGIN_Y
+ maxWidth = 300
+ maxHeight = 40
+
+ if self.GetItemFont().IsOk():
+ standardFont = self.GetItemFont()
+
+ for item in self._items:
+ if item.GetFont().IsOk():
+ dc.SetFont(item.GetFont())
+ else:
+ if item.GetIsGroup():
+ dc.SetFont(groupFont)
+ else:
+ dc.SetFont(standardFont)
+
+ w, h = dc.GetTextExtent(item.GetTitle())
+ w += 16 + 2*textMarginX
+
+ if w > sz.x:
+ sz.x = min(w, maxWidth)
+ if h > sz.y:
+ sz.y = min(h, maxHeight)
+
+ if sz == wx.Size(16, 16):
+ sz = wx.Size(100, 25)
+ else:
+ sz.x += textMarginX*2
+ sz.y += textMarginY*2
+
+ return sz
+
+
+ def GetIndexForFocus(self):
+
+ for i, item in enumerate(self._items):
+ if item.GetWindow():
+
+ if FindFocusDescendant(item.GetWindow()):
+ return i
+
+ return wx.NOT_FOUND
+
+
+class MultiColumnListCtrl(wx.PyControl):
+ """ A control for displaying several columns (not scrollable). """
+
+ def __init__(self, parent, aui_manager, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, validator=wx.DefaultValidator, name="MultiColumnListCtrl"):
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name)
+
+ self._overallSize = wx.Size(200, 100)
+ self._modifierKey = wx.WXK_CONTROL
+ self._extraNavigationKey = 0
+ self._aui_manager = aui_manager
+
+ self.SetInitialSize(size)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKey)
+ self.Bind(wx.EVT_KEY_UP, self.OnKey)
+
+
+ def __del__(self):
+
+ self._aui_manager.HideHint()
+
+
+ def DoGetBestSize(self):
+
+ return self._overallSize
+
+
+ def OnEraseBackground(self, event):
+
+ pass
+
+
+ def OnPaint(self, event):
+
+ dc = wx.AutoBufferedPaintDC(self)
+ rect = self.GetClientRect()
+
+ if self._items.GetColumnCount() == 0:
+ self.CalculateLayout(dc)
+
+ if self._items.GetColumnCount() == 0:
+ return
+
+ self._items.PaintItems(dc, self)
+
+
+ def OnMouseEvent(self, event):
+
+ if event.LeftDown():
+ self.SetFocus()
+
+
+ def OnChar(self, event):
+
+ event.Skip()
+
+
+ def OnKey(self, event):
+
+ if event.GetEventType() == wx.wxEVT_KEY_UP:
+ if event.GetKeyCode() == self.GetModifierKey():
+ topLevel = wx.GetTopLevelParent(self)
+ closeEvent = wx.CloseEvent(wx.wxEVT_CLOSE_WINDOW, topLevel.GetId())
+ closeEvent.SetEventObject(topLevel)
+ closeEvent.SetCanVeto(False)
+
+ topLevel.GetEventHandler().ProcessEvent(closeEvent)
+ return
+
+ event.Skip()
+ return
+
+ keyCode = event.GetKeyCode()
+
+ if keyCode in [wx.WXK_ESCAPE, wx.WXK_RETURN]:
+ if keyCode == wx.WXK_ESCAPE:
+ self._items.SetSelection(-1)
+
+ topLevel = wx.GetTopLevelParent(self)
+ closeEvent = wx.CloseEvent(wx.wxEVT_CLOSE_WINDOW, topLevel.GetId())
+ closeEvent.SetEventObject(topLevel)
+ closeEvent.SetCanVeto(False)
+
+ topLevel.GetEventHandler().ProcessEvent(closeEvent)
+ return
+
+ elif keyCode in [wx.WXK_TAB, self.GetExtraNavigationKey()]:
+ if event.ShiftDown():
+
+ self._items.SetSelection(self._items.GetSelection() - 1)
+ if self._items.GetSelection() < 0:
+ self._items.SetSelection(self._items.GetItemCount() - 1)
+
+ self.AdvanceToNextSelectableItem(-1)
+
+ else:
+
+ self._items.SetSelection(self._items.GetSelection() + 1)
+ if self._items.GetSelection() >= self._items.GetItemCount():
+ self._items.SetSelection(0)
+
+ self.AdvanceToNextSelectableItem(1)
+
+ self.GenerateSelectionEvent()
+ self.Refresh()
+
+ elif keyCode in [wx.WXK_DOWN, wx.WXK_NUMPAD_DOWN]:
+ self._items.SetSelection(self._items.GetSelection() + 1)
+ if self._items.GetSelection() >= self._items.GetItemCount():
+ self._items.SetSelection(0)
+
+ self.AdvanceToNextSelectableItem(1)
+ self.GenerateSelectionEvent()
+ self.Refresh()
+
+ elif keyCode in [wx.WXK_UP, wx.WXK_NUMPAD_UP]:
+ self._items.SetSelection(self._items.GetSelection() - 1)
+ if self._items.GetSelection() < 0:
+ self._items.SetSelection(self._items.GetItemCount() - 1)
+
+ self.AdvanceToNextSelectableItem(-1)
+ self.GenerateSelectionEvent()
+ self.Refresh()
+
+ elif keyCode in [wx.WXK_HOME, wx.WXK_NUMPAD_HOME]:
+ self._items.SetSelection(0)
+ self.AdvanceToNextSelectableItem(1)
+ self.GenerateSelectionEvent()
+ self.Refresh()
+
+ elif keyCode in [wx.WXK_END, wx.WXK_NUMPAD_END]:
+ self._items.SetSelection(self._items.GetItemCount() - 1)
+ self.AdvanceToNextSelectableItem(-1)
+ self.GenerateSelectionEvent()
+ self.Refresh()
+
+ elif keyCode in [wx.WXK_LEFT, wx.WXK_NUMPAD_LEFT]:
+ item = self._items.GetItem(self._items.GetSelection())
+
+ row = item.GetRowPos()
+ newCol = item.GetColPos() - 1
+ if newCol < 0:
+ newCol = self._items.GetColumnCount() - 1
+
+ # Find the first item from the end whose row matches and whose column is equal or lower
+ for i in xrange(self._items.GetItemCount()-1, -1, -1):
+ item2 = self._items.GetItem(i)
+ if item2.GetColPos() == newCol and item2.GetRowPos() <= row:
+ self._items.SetSelection(i)
+ break
+
+ self.AdvanceToNextSelectableItem(-1)
+ self.GenerateSelectionEvent()
+ self.Refresh()
+
+ elif keyCode in [wx.WXK_RIGHT, wx.WXK_NUMPAD_RIGHT]:
+ item = self._items.GetItem(self._items.GetSelection())
+
+ row = item.GetRowPos()
+ newCol = item.GetColPos() + 1
+ if newCol >= self._items.GetColumnCount():
+ newCol = 0
+
+ # Find the first item from the end whose row matches and whose column is equal or lower
+ for i in xrange(self._items.GetItemCount()-1, -1, -1):
+ item2 = self._items.GetItem(i)
+ if item2.GetColPos() == newCol and item2.GetRowPos() <= row:
+ self._items.SetSelection(i)
+ break
+
+ self.AdvanceToNextSelectableItem(1)
+ self.GenerateSelectionEvent()
+ self.Refresh()
+
+ else:
+ event.Skip()
+
+
+ def AdvanceToNextSelectableItem(self, direction):
+
+ if self._items.GetItemCount() < 2:
+ return
+
+ if self._items.GetSelection() == -1:
+ self._items.SetSelection(0)
+
+ oldSel = self._items.GetSelection()
+
+ while 1:
+
+ if self._items.GetItem(self._items.GetSelection()).GetIsGroup():
+
+ self._items.SetSelection(self._items.GetSelection() + direction)
+ if self._items.GetSelection() == -1:
+ self._items.SetSelection(self._items.GetItemCount()-1)
+ elif self._items.GetSelection() == self._items.GetItemCount():
+ self._items.SetSelection(0)
+ if self._items.GetSelection() == oldSel:
+ break
+
+ else:
+ break
+
+ self.SetTransparency()
+ selection = self._items.GetItem(self._items.GetSelection()).GetWindow()
+ pane = self._aui_manager.GetPane(selection)
+
+ if not pane.IsOk():
+ if isinstance(selection.GetParent(), auibook.AuiNotebook):
+ self.SetTransparency(selection)
+ self._aui_manager.ShowHint(selection.GetScreenRect())
+ wx.CallAfter(self.SetFocus)
+ self.SetFocus()
+ return
+ else:
+ self._aui_manager.HideHint()
+ return
+ if not pane.IsShown():
+ self._aui_manager.HideHint()
+ return
+
+ self.SetTransparency(selection)
+ self._aui_manager.ShowHint(selection.GetScreenRect())
+ # NOTE: this is odd but it is the only way for the focus to
+ # work correctly on wxMac...
+ wx.CallAfter(self.SetFocus)
+ self.SetFocus()
+
+
+ def SetTransparency(self, selection=None):
+
+ if not self.GetParent().CanSetTransparent():
+ return
+
+ if selection is not None:
+ intersects = False
+ if selection.GetScreenRect().Intersects(self.GetParent().GetScreenRect()):
+ intersects = True
+ self.GetParent().SetTransparent(200)
+ return
+
+ self.GetParent().SetTransparent(255)
+
+
+ def GenerateSelectionEvent(self):
+
+ event = wx.CommandEvent(wx.wxEVT_COMMAND_LISTBOX_SELECTED, self.GetId())
+ event.SetEventObject(self)
+ event.SetInt(self._items.GetSelection())
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def CalculateLayout(self, dc=None):
+
+ if dc is None:
+ dc = wx.ClientDC(self)
+
+ if self._items.GetSelection() == -1:
+ self._items.SetSelection(0)
+
+ columnCount = 1
+
+ # Spacing between edge of window or between columns
+ xMargin = 4
+ yMargin = 4
+
+ # Inter-row spacing
+ rowSpacing = 2
+
+ itemSize = self._items.CalculateItemSize(dc)
+ self._overallSize = wx.Size(350, 200)
+
+ currentRow = 0
+ x = xMargin
+ y = yMargin
+
+ breaking = False
+ i = 0
+
+ while 1:
+
+ oldOverallSize = self._overallSize
+ item = self._items.GetItem(i)
+
+ item.SetRect(wx.Rect(x, y, itemSize.x, itemSize.y))
+ item.SetColPos(columnCount-1)
+ item.SetRowPos(currentRow)
+
+ if item.GetRect().GetBottom() > self._overallSize.y:
+ self._overallSize.y = item.GetRect().GetBottom() + yMargin
+
+ if item.GetRect().GetRight() > self._overallSize.x:
+ self._overallSize.x = item.GetRect().GetRight() + xMargin
+
+ currentRow += 1
+
+ y += rowSpacing + itemSize.y
+ stopBreaking = breaking
+
+ if currentRow > self._items.GetRowCount() or (item.GetBreakColumn() and not breaking and currentRow != 1):
+ currentRow = 0
+ columnCount += 1
+ x += xMargin + itemSize.x
+ y = yMargin
+
+ # Make sure we don't orphan a group
+ if item.GetIsGroup() or (item.GetBreakColumn() and not breaking):
+ self._overallSize = oldOverallSize
+
+ if item.GetBreakColumn():
+ breaking = True
+
+ # Repeat the last item, in the next column
+ i -= 1
+
+ if stopBreaking:
+ breaking = False
+
+ i += 1
+
+ if i >= self._items.GetItemCount():
+ break
+
+ self._items.SetColumnCount(columnCount)
+ self.InvalidateBestSize()
+
+
+ def SetItems(self, items):
+
+ self._items = items
+
+
+ def GetItems(self):
+
+ return self._items
+
+
+ def SetExtraNavigationKey(self, keyCode):
+ """
+ Set an extra key that can be used to cycle through items,
+ in case not using the ``Ctrl`` + ``Tab`` combination.
+ """
+
+ self._extraNavigationKey = keyCode
+
+
+ def GetExtraNavigationKey(self):
+
+ return self._extraNavigationKey
+
+
+ def SetModifierKey(self, modifierKey):
+ """
+ Set the modifier used to invoke the dialog, and therefore to test for release.
+ """
+
+ self._modifierKey = modifierKey
+
+
+ def GetModifierKey(self):
+
+ return self._modifierKey
+
+
+
+class SwitcherDialog(wx.Dialog):
+ """
+ SwitcherDialog shows a :class:`Dialog` with a list of panes and tabs for the user to choose.
+ ``Ctrl`` + ``Tab`` cycles through them.
+ """
+
+ def __init__(self, items, parent, aui_manager, id=wx.ID_ANY, title=_("Pane Switcher"), pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.STAY_ON_TOP|wx.DIALOG_NO_PARENT|wx.BORDER_SIMPLE):
+ """ Default class constructor. """
+
+ self._switcherBorderStyle = (style & wx.BORDER_MASK)
+ if self._switcherBorderStyle == wx.BORDER_NONE:
+ self._switcherBorderStyle = wx.BORDER_SIMPLE
+
+ style &= wx.BORDER_MASK
+ style |= wx.BORDER_NONE
+
+ wx.Dialog.__init__(self, parent, id, title, pos, size, style)
+
+ self._listCtrl = MultiColumnListCtrl(self, aui_manager,
+ style=wx.WANTS_CHARS|wx.NO_BORDER)
+ self._listCtrl.SetItems(items)
+ self._listCtrl.CalculateLayout()
+
+ self._descriptionCtrl = wx.html.HtmlWindow(self, size=(-1, 100), style=wx.BORDER_NONE)
+ self._descriptionCtrl.SetBackgroundColour(self.GetBackgroundColour())
+
+ if wx.Platform == "__WXGTK__":
+ fontSize = 11
+ self._descriptionCtrl.SetStandardFonts(fontSize)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(sizer)
+ sizer.Add(self._listCtrl, 1, wx.ALL|wx.EXPAND, 10)
+ sizer.Add(self._descriptionCtrl, 0, wx.ALL|wx.EXPAND, 10)
+ sizer.SetSizeHints(self)
+
+ self._listCtrl.SetFocus()
+
+ self.Centre(wx.BOTH)
+
+ if self._listCtrl.GetItems().GetSelection() == -1:
+ self._listCtrl.GetItems().SetSelection(0)
+
+ self._listCtrl.AdvanceToNextSelectableItem(1)
+
+ self.ShowDescription(self._listCtrl.GetItems().GetSelection())
+
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
+ self.Bind(wx.EVT_LISTBOX, self.OnSelectItem)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+ # Attributes
+ self._closing = False
+ if wx.Platform == "__WXMSW__":
+ self._borderColour = wx.Colour(49, 106, 197)
+ else:
+ self._borderColour = wx.BLACK
+
+ self._aui_manager = aui_manager
+
+
+ def OnCloseWindow(self, event):
+
+ if self._closing:
+ return
+
+ if self.IsModal():
+ self._closing = True
+
+ if self.GetSelection() == -1:
+ self.EndModal(wx.ID_CANCEL)
+ else:
+ self.EndModal(wx.ID_OK)
+
+ self._aui_manager.HideHint()
+
+
+ def GetSelection(self):
+
+ return self._listCtrl.GetItems().GetSelection()
+
+
+ def OnActivate(self, event):
+
+ if not event.GetActive():
+ if not self._closing:
+ self._closing = True
+ self.EndModal(wx.ID_CANCEL)
+
+
+ def OnPaint(self, event):
+
+ dc = wx.PaintDC(self)
+
+ if self._switcherBorderStyle == wx.BORDER_SIMPLE:
+
+ dc.SetPen(wx.Pen(self._borderColour))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ rect = self.GetClientRect()
+ dc.DrawRectangleRect(rect)
+
+ # Draw border around the HTML control
+ rect = wx.Rect(*self._descriptionCtrl.GetRect())
+ rect.Inflate(1, 1)
+ dc.DrawRectangleRect(rect)
+
+
+ def OnSelectItem(self, event):
+
+ self.ShowDescription(event.GetSelection())
+
+
+ # Convert a colour to a 6-digit hex string
+ def ColourToHexString(self, col):
+
+ hx = '%02x%02x%02x' % tuple([int(c) for c in col])
+ return hx
+
+
+ def ShowDescription(self, i):
+
+ item = self._listCtrl.GetItems().GetItem(i)
+ colour = self._listCtrl.GetItems().GetBackgroundColour()
+
+ if not colour.IsOk():
+ colour = self.GetBackgroundColour()
+
+ backgroundColourHex = self.ColourToHexString(colour)
+ html = _("<body bgcolor=\"#") + backgroundColourHex + _("\"><b>") + item.GetTitle() + _("</b>")
+
+ if item.GetDescription():
+ html += _("<p>")
+ html += item.GetDescription()
+
+ html += _("</body>")
+ self._descriptionCtrl.SetPage(html)
+
+
+ def SetExtraNavigationKey(self, keyCode):
+
+ self._extraNavigationKey = keyCode
+ if self._listCtrl:
+ self._listCtrl.SetExtraNavigationKey(keyCode)
+
+
+ def GetExtraNavigationKey(self):
+
+ return self._extraNavigationKey
+
+
+ def SetModifierKey(self, modifierKey):
+
+ self._modifierKey = modifierKey
+ if self._listCtrl:
+ self._listCtrl.SetModifierKey(modifierKey)
+
+
+ def GetModifierKey(self):
+
+ return self._modifierKey
+
+
+ def SetBorderColour(self, colour):
+
+ self._borderColour = colour
+
+ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_utilities.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_utilities.py
new file mode 100644
index 0000000..3eec72a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/aui_utilities.py
@@ -0,0 +1,680 @@
+"""
+This module contains some common functions used by :mod:`lib.agw.aui` to
+manipulate colours, bitmaps, text, gradient shadings and custom dragging images
+for :class:`~lib.agw.aui.auibook.AuiNotebook` tabs.
+"""
+
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "31 March 2009"
+
+
+import wx
+
+from aui_constants import *
+
+
+if wx.Platform == "__WXMAC__":
+ import Carbon.Appearance
+
+
+def BlendColour(fg, bg, alpha):
+ """
+ Blends the two colour component `fg` and `bg` into one colour component, adding
+ an optional alpha channel.
+
+ :param Colour `fg`: the first colour component;
+ :param Colour `bg`: the second colour component;
+ :param integer `alpha`: an optional transparency value.
+ """
+
+ result = bg + (alpha*(fg - bg))
+
+ if result < 0.0:
+ result = 0.0
+ if result > 255:
+ result = 255
+
+ return result
+
+
+def StepColour(c, ialpha):
+ """
+ Darken/lighten the input colour `c`.
+
+ :param Colour `c`: a colour to darken/lighten;
+ :param integer `ialpha`: a transparency value.
+ """
+
+ if ialpha == 100:
+ return c
+
+ r, g, b = c.Red(), c.Green(), c.Blue()
+
+ # ialpha is 0..200 where 0 is completely black
+ # and 200 is completely white and 100 is the same
+ # convert that to normal alpha 0.0 - 1.0
+ ialpha = min(ialpha, 200)
+ ialpha = max(ialpha, 0)
+ alpha = (ialpha - 100.0)/100.0
+
+ if ialpha > 100:
+
+ # blend with white
+ bg = 255
+ alpha = 1.0 - alpha # 0 = transparent fg 1 = opaque fg
+
+ else:
+
+ # blend with black
+ bg = 0
+ alpha = 1.0 + alpha # 0 = transparent fg 1 = opaque fg
+
+ r = BlendColour(r, bg, alpha)
+ g = BlendColour(g, bg, alpha)
+ b = BlendColour(b, bg, alpha)
+
+ return wx.Colour(r, g, b)
+
+
+def LightContrastColour(c):
+ """
+ Creates a new, lighter colour based on the input colour `c`.
+
+ :param Colour `c`: the input colour to analyze.
+ """
+
+ amount = 120
+
+ # if the colour is especially dark, then
+ # make the contrast even lighter
+ if c.Red() < 128 and c.Green() < 128 and c.Blue() < 128:
+ amount = 160
+
+ return StepColour(c, amount)
+
+
+def ChopText(dc, text, max_size):
+ """
+ Chops the input `text` if its size does not fit in `max_size`, by cutting the
+ text and adding ellipsis at the end.
+
+ :param `dc`: a :class:`DC` device context;
+ :param string `text`: the text to chop;
+ :param integer `max_size`: the maximum size in which the text should fit.
+ """
+
+ # first check if the text fits with no problems
+ x, y, dummy = dc.GetMultiLineTextExtent(text)
+
+ if x <= max_size:
+ return text
+
+ textLen = len(text)
+ last_good_length = 0
+
+ for i in xrange(textLen, -1, -1):
+ s = text[0:i]
+ s += "..."
+
+ x, y = dc.GetTextExtent(s)
+ last_good_length = i
+
+ if x < max_size:
+ break
+
+ ret = text[0:last_good_length] + "..."
+ return ret
+
+
+def BitmapFromBits(bits, w, h, colour):
+ """
+ A utility function that creates a masked bitmap from raw bits (XBM format).
+
+ :param string `bits`: the raw bits of the bitmap;
+ :param integer `w`: the bitmap width;
+ :param integer `h`: the bitmap height;
+ :param Colour `colour`: the colour which will replace all white pixels in the
+ raw bitmap.
+ """
+
+ img = wx.BitmapFromBits(bits, w, h).ConvertToImage()
+ img.Replace(0, 0, 0, 123, 123, 123)
+ img.Replace(255, 255, 255, colour.Red(), colour.Green(), colour.Blue())
+ img.SetMaskColour(123, 123, 123)
+ return wx.BitmapFromImage(img)
+
+
+def IndentPressedBitmap(rect, button_state):
+ """
+ Indents the input rectangle `rect` based on the value of `button_state`.
+
+ :param Rect `rect`: the button bitmap rectangle;
+ :param integer `button_state`: the button state.
+ """
+
+ if button_state == AUI_BUTTON_STATE_PRESSED:
+ rect.x += 1
+ rect.y += 1
+
+ return rect
+
+
+def GetBaseColour():
+ """
+ Returns the face shading colour on push buttons/backgrounds,
+ mimicking as closely as possible the platform UI colours.
+ """
+
+ if wx.Platform == "__WXMAC__":
+
+ if hasattr(wx, 'MacThemeColour'):
+ base_colour = wx.MacThemeColour(Carbon.Appearance.kThemeBrushToolbarBackground)
+ else:
+ brush = wx.Brush(wx.BLACK)
+ brush.MacSetTheme(Carbon.Appearance.kThemeBrushToolbarBackground)
+ base_colour = brush.GetColour()
+
+ else:
+
+ base_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
+
+ # the base_colour is too pale to use as our base colour,
+ # so darken it a bit
+ if ((255-base_colour.Red()) +
+ (255-base_colour.Green()) +
+ (255-base_colour.Blue()) < 60):
+
+ base_colour = StepColour(base_colour, 92)
+
+ return base_colour
+
+
+def MakeDisabledBitmap(bitmap):
+ """
+ Convert the given image (in place) to a grayed-out version, appropriate for a 'disabled' appearance.
+
+ :param Bitmap `bitmap`: the bitmap to gray-out.
+ """
+
+ if wx.VERSION_STRING >= '2.9.0':
+ return bitmap.ConvertToDisabled()
+
+ anImage = bitmap.ConvertToImage()
+ factor = 0.7 # 0 < f < 1. Higher Is Grayer
+
+ if anImage.HasMask():
+ maskColour = (anImage.GetMaskRed(), anImage.GetMaskGreen(), anImage.GetMaskBlue())
+ else:
+ maskColour = None
+
+ data = map(ord, list(anImage.GetData()))
+
+ for i in range(0, len(data), 3):
+
+ pixel = (data[i], data[i+1], data[i+2])
+ pixel = MakeGray(pixel, factor, maskColour)
+
+ for x in range(3):
+ data[i+x] = pixel[x]
+
+ anImage.SetData(''.join(map(chr, data)))
+
+ return anImage.ConvertToBitmap()
+
+
+def MakeGray(rgbTuple, factor, maskColour):
+ """
+ Make a pixel grayed-out.
+
+ If the pixel matches the `maskColour`, it won't be changed.
+
+ :param tuple `rgbTuple`: a tuple representing a pixel colour;
+ :param integer `factor`: a graying-out factor;
+ :param Colour `maskColour`: a colour mask.
+ """
+
+ if rgbTuple != maskColour:
+ r, g, b = rgbTuple
+ return map(lambda x: int((230 - x) * factor) + x, (r, g, b))
+ else:
+ return rgbTuple
+
+
+def Clip(a, b, c):
+ """
+ Clips the value in `a` based on the extremes `b` and `c`.
+
+ :param `a`: the value to analyze;
+ :param `b`: a minimum value;
+ :param `c`: a maximum value.
+ """
+
+ return ((a < b and [b]) or [(a > c and [c] or [a])[0]])[0]
+
+
+def LightColour(colour, percent):
+ """
+ Brighten input `colour` by `percent`.
+
+ :param Colour `colour`: the colour to be brightened;
+ :param integer `percent`: brightening percentage.
+ """
+
+ end_colour = wx.WHITE
+
+ rd = end_colour.Red() - colour.Red()
+ gd = end_colour.Green() - colour.Green()
+ bd = end_colour.Blue() - colour.Blue()
+
+ high = 100
+
+ # We take the percent way of the colour from colour -. white
+ i = percent
+ r = colour.Red() + ((i*rd*100)/high)/100
+ g = colour.Green() + ((i*gd*100)/high)/100
+ b = colour.Blue() + ((i*bd*100)/high)/100
+ return wx.Colour(r, g, b)
+
+
+def PaneCreateStippleBitmap():
+ """
+ Creates a stipple bitmap to be used in a :class:`Brush`.
+
+ This is used to draw sash resize hints.
+ """
+
+ data = [0, 0, 0, 192, 192, 192, 192, 192, 192, 0, 0, 0]
+ img = wx.EmptyImage(2, 2)
+ counter = 0
+
+ for ii in xrange(2):
+ for jj in xrange(2):
+ img.SetRGB(ii, jj, data[counter], data[counter+1], data[counter+2])
+ counter = counter + 3
+
+ return img.ConvertToBitmap()
+
+
+def DrawMACCloseButton(colour, backColour=None):
+ """
+ Draws the wxMAC tab close button using :class:`GraphicsContext`.
+
+ :param Colour `colour`: the colour to use to draw the circle;
+ :param Colour `backColour`: the optional background colour for the circle.
+ """
+
+ bmp = wx.EmptyBitmapRGBA(16, 16)
+ dc = wx.MemoryDC()
+ dc.SelectObject(bmp)
+
+ gc = wx.GraphicsContext.Create(dc)
+ gc.SetBrush(wx.Brush(colour))
+ path = gc.CreatePath()
+ path.AddCircle(6.5, 7, 6.5)
+ path.CloseSubpath()
+ gc.FillPath(path)
+
+ path = gc.CreatePath()
+ if backColour is not None:
+ pen = wx.Pen(backColour, 2)
+ else:
+ pen = wx.Pen("white", 2)
+
+ pen.SetCap(wx.CAP_BUTT)
+ pen.SetJoin(wx.JOIN_BEVEL)
+ gc.SetPen(pen)
+ path.MoveToPoint(3.5, 4)
+ path.AddLineToPoint(9.5, 10)
+ path.MoveToPoint(3.5, 10)
+ path.AddLineToPoint(9.5, 4)
+ path.CloseSubpath()
+ gc.DrawPath(path)
+
+ dc.SelectObject(wx.NullBitmap)
+ return bmp
+
+
+def DarkenBitmap(bmp, caption_colour, new_colour):
+ """
+ Darkens the input bitmap on wxMAC using the input colour.
+
+ :param Bitmap `bmp`: the bitmap to be manipulated;
+ :param Colour `caption_colour`: the colour of the pane caption;
+ :param Colour `new_colour`: the colour used to darken the bitmap.
+ """
+
+ image = bmp.ConvertToImage()
+ red = caption_colour.Red()/float(new_colour.Red())
+ green = caption_colour.Green()/float(new_colour.Green())
+ blue = caption_colour.Blue()/float(new_colour.Blue())
+ image = image.AdjustChannels(red, green, blue)
+ return image.ConvertToBitmap()
+
+
+def DrawGradientRectangle(dc, rect, start_colour, end_colour, direction, offset=0, length=0):
+ """
+ Draws a gradient-shaded rectangle.
+
+ :param `dc`: a :class:`DC` device context;
+ :param Rect `rect`: the rectangle in which to draw the gradient;
+ :param Colour `start_colour`: the first colour of the gradient;
+ :param Colour `end_colour`: the second colour of the gradient;
+ :param integer `direction`: the gradient direction (horizontal or vertical).
+ """
+
+ if direction == AUI_GRADIENT_VERTICAL:
+ dc.GradientFillLinear(rect, start_colour, end_colour, wx.SOUTH)
+ else:
+ dc.GradientFillLinear(rect, start_colour, end_colour, wx.EAST)
+
+
+def FindFocusDescendant(ancestor):
+ """
+ Find a window with the focus, that is also a descendant of the given window.
+ This is used to determine the window to initially send commands to.
+
+ :param Window `ancestor`: the window to check for ancestry.
+ """
+
+ # Process events starting with the window with the focus, if any.
+ focusWin = wx.Window.FindFocus()
+ win = focusWin
+
+ # Check if this is a descendant of this frame.
+ # If not, win will be set to NULL.
+ while win:
+ if win == ancestor:
+ break
+ else:
+ win = win.GetParent()
+
+ if win is None:
+ focusWin = None
+
+ return focusWin
+
+
+def GetLabelSize(dc, label, vertical):
+ """
+ Returns the :class:`~lib.agw.aui.auibar.AuiToolBar` item label size.
+
+ :param string `label`: the toolbar tool label;
+ :param bool `vertical`: whether the toolbar tool orientation is vertical or not.
+ """
+
+ text_width = text_height = 0
+
+ # get the text height
+ dummy, text_height = dc.GetTextExtent("ABCDHgj")
+ # get the text width
+ if label.strip():
+ text_width, dummy = dc.GetTextExtent(label)
+
+ if vertical:
+ tmp = text_height
+ text_height = text_width
+ text_width = tmp
+
+ return wx.Size(text_width, text_height)
+
+
+#---------------------------------------------------------------------------
+# TabDragImage implementation
+# This class handles the creation of a custom image when dragging
+# AuiNotebook tabs
+#---------------------------------------------------------------------------
+
+class TabDragImage(wx.DragImage):
+ """
+ This class handles the creation of a custom image in case of drag and drop of a notebook tab.
+ """
+
+ def __init__(self, notebook, page, button_state, tabArt):
+ """
+ Default class constructor.
+
+ For internal use: do not call it in your code!
+
+ :param `notebook`: an instance of :class:`~lib.agw.aui.auibook.AuiNotebook`;
+ :param `page`: the dragged :class:`~lib.agw.aui.auibook.AuiNotebookPage` page;
+ :param integer `button_state`: the state of the close button on the tab;
+ :param `tabArt`: an instance of :class:`~lib.agw.aui.tabart.AuiDefaultTabArt` or one of its derivations.
+ """
+
+ self._backgroundColour = wx.NamedColour("pink")
+ self._bitmap = self.CreateBitmap(notebook, page, button_state, tabArt)
+ wx.DragImage.__init__(self, self._bitmap)
+
+
+ def CreateBitmap(self, notebook, page, button_state, tabArt):
+ """
+ Actually creates the drag and drop bitmap.
+
+ :param `notebook`: an instance of :class:`~lib.agw.aui.auibook.AuiNotebook`;
+ :param `page`: the dragged :class:`~lib.agw.aui.auibook.AuiNotebookPage` page;
+ :param integer `button_state`: the state of the close button on the tab;
+ :param `tabArt`: an instance of :class:`~lib.agw.aui.tabart.AuiDefaultTabArt` or one of its derivations.
+ """
+
+ control = page.control
+ memory = wx.MemoryDC(wx.EmptyBitmap(1, 1))
+
+ tab_size, x_extent = tabArt.GetTabSize(memory, notebook, page.caption, page.bitmap, page.active,
+ button_state, control)
+
+ tab_width, tab_height = tab_size
+ rect = wx.Rect(0, 0, tab_width, tab_height)
+
+ bitmap = wx.EmptyBitmap(tab_width+1, tab_height+1)
+ memory.SelectObject(bitmap)
+
+ if wx.Platform == "__WXMAC__":
+ memory.SetBackground(wx.TRANSPARENT_BRUSH)
+ else:
+ memory.SetBackground(wx.Brush(self._backgroundColour))
+
+ memory.SetBackgroundMode(wx.TRANSPARENT)
+ memory.Clear()
+
+ paint_control = wx.Platform != "__WXMAC__"
+ tabArt.DrawTab(memory, notebook, page, rect, button_state, paint_control=paint_control)
+
+ memory.SetBrush(wx.TRANSPARENT_BRUSH)
+ memory.SetPen(wx.BLACK_PEN)
+ memory.DrawRoundedRectangle(0, 0, tab_width+1, tab_height+1, 2)
+
+ memory.SelectObject(wx.NullBitmap)
+
+ # Gtk and Windows unfortunatly don't do so well with transparent
+ # drawing so this hack corrects the image to have a transparent
+ # background.
+ if wx.Platform != '__WXMAC__':
+ timg = bitmap.ConvertToImage()
+ if not timg.HasAlpha():
+ timg.InitAlpha()
+ for y in xrange(timg.GetHeight()):
+ for x in xrange(timg.GetWidth()):
+ pix = wx.Colour(timg.GetRed(x, y),
+ timg.GetGreen(x, y),
+ timg.GetBlue(x, y))
+ if pix == self._backgroundColour:
+ timg.SetAlpha(x, y, 0)
+ bitmap = timg.ConvertToBitmap()
+ return bitmap
+
+
+def GetDockingImage(direction, useAero, center):
+ """
+ Returns the correct name of the docking bitmap depending on the input parameters.
+
+ :param bool `useAero`: whether :class:`~lib.agw.aui.framemanager.AuiManager` is using
+ Aero-style or Whidbey-style docking images or not;
+ :param bool `center`: whether we are looking for the center diamond-shaped bitmap or not.
+ """
+
+ suffix = (center and [""] or ["_single"])[0]
+ prefix = ""
+ if useAero == 2:
+ # Whidbey docking guides
+ prefix = "whidbey_"
+ elif useAero == 1:
+ # Aero docking style
+ prefix = "aero_"
+
+ if direction == wx.TOP:
+ bmp_unfocus = eval("%sup%s"%(prefix, suffix)).GetBitmap()
+ bmp_focus = eval("%sup_focus%s"%(prefix, suffix)).GetBitmap()
+ elif direction == wx.BOTTOM:
+ bmp_unfocus = eval("%sdown%s"%(prefix, suffix)).GetBitmap()
+ bmp_focus = eval("%sdown_focus%s"%(prefix, suffix)).GetBitmap()
+ elif direction == wx.LEFT:
+ bmp_unfocus = eval("%sleft%s"%(prefix, suffix)).GetBitmap()
+ bmp_focus = eval("%sleft_focus%s"%(prefix, suffix)).GetBitmap()
+ elif direction == wx.RIGHT:
+ bmp_unfocus = eval("%sright%s"%(prefix, suffix)).GetBitmap()
+ bmp_focus = eval("%sright_focus%s"%(prefix, suffix)).GetBitmap()
+ else:
+ bmp_unfocus = eval("%stab%s"%(prefix, suffix)).GetBitmap()
+ bmp_focus = eval("%stab_focus%s"%(prefix, suffix)).GetBitmap()
+
+ return bmp_unfocus, bmp_focus
+
+
+def TakeScreenShot(rect):
+ """
+ Takes a screenshot of the screen at given position and size (`rect`).
+
+ :param Rect `rect`: the screen rectangle for which we want to take a screenshot.
+ """
+
+ # Create a DC for the whole screen area
+ dcScreen = wx.ScreenDC()
+
+ # Create a Bitmap that will later on hold the screenshot image
+ # Note that the Bitmap must have a size big enough to hold the screenshot
+ # -1 means using the current default colour depth
+ bmp = wx.EmptyBitmap(rect.width, rect.height)
+
+ # Create a memory DC that will be used for actually taking the screenshot
+ memDC = wx.MemoryDC()
+
+ # Tell the memory DC to use our Bitmap
+ # all drawing action on the memory DC will go to the Bitmap now
+ memDC.SelectObject(bmp)
+
+ # Blit (in this case copy) the actual screen on the memory DC
+ # and thus the Bitmap
+ memDC.Blit( 0, # Copy to this X coordinate
+ 0, # Copy to this Y coordinate
+ rect.width, # Copy this width
+ rect.height, # Copy this height
+ dcScreen, # From where do we copy?
+ rect.x, # What's the X offset in the original DC?
+ rect.y # What's the Y offset in the original DC?
+ )
+
+ # Select the Bitmap out of the memory DC by selecting a new
+ # uninitialized Bitmap
+ memDC.SelectObject(wx.NullBitmap)
+
+ return bmp
+
+
+def RescaleScreenShot(bmp, thumbnail_size=200):
+ """
+ Rescales a bitmap to be `thumbnail_size` pixels wide (or tall) at maximum.
+
+ :param Bitmap `bmp`: the bitmap to rescale;
+ :param integer `thumbnail_size`: the maximum size of every page thumbnail.
+ """
+
+ bmpW, bmpH = bmp.GetWidth(), bmp.GetHeight()
+ img = bmp.ConvertToImage()
+
+ newW, newH = bmpW, bmpH
+
+ if bmpW > bmpH:
+ if bmpW > thumbnail_size:
+ ratio = bmpW/float(thumbnail_size)
+ newW, newH = int(bmpW/ratio), int(bmpH/ratio)
+ img.Rescale(newW, newH, wx.IMAGE_QUALITY_HIGH)
+ else:
+ if bmpH > thumbnail_size:
+ ratio = bmpH/float(thumbnail_size)
+ newW, newH = int(bmpW/ratio), int(bmpH/ratio)
+ img.Rescale(newW, newH, wx.IMAGE_QUALITY_HIGH)
+
+ newBmp = img.ConvertToBitmap()
+ otherBmp = wx.EmptyBitmap(newW+5, newH+5)
+
+ memDC = wx.MemoryDC()
+ memDC.SelectObject(otherBmp)
+ memDC.SetBackground(wx.WHITE_BRUSH)
+ memDC.Clear()
+
+ memDC.SetPen(wx.TRANSPARENT_PEN)
+
+ pos = 0
+ for i in xrange(5, 0, -1):
+ brush = wx.Brush(wx.Colour(50*i, 50*i, 50*i))
+ memDC.SetBrush(brush)
+ memDC.DrawRoundedRectangle(0, 0, newW+5-pos, newH+5-pos, 2)
+ pos += 1
+
+ memDC.DrawBitmap(newBmp, 0, 0, True)
+
+ # Select the Bitmap out of the memory DC by selecting a new
+ # uninitialized Bitmap
+ memDC.SelectObject(wx.NullBitmap)
+
+ return otherBmp
+
+
+def GetSlidingPoints(rect, size, direction):
+ """
+ Returns the point at which the sliding in and out of a minimized pane begins.
+
+ :param Rect `rect`: the :class:`~lib.agw.aui.auibar.AuiToolBar` tool screen rectangle;
+ :param Size `size`: the pane window size;
+ :param integer `direction`: the pane docking direction.
+ """
+
+ if direction == AUI_DOCK_LEFT:
+ startX, startY = rect.x + rect.width + 2, rect.y
+ elif direction == AUI_DOCK_TOP:
+ startX, startY = rect.x, rect.y + rect.height + 2
+ elif direction == AUI_DOCK_RIGHT:
+ startX, startY = rect.x - size.x - 2, rect.y
+ elif direction == AUI_DOCK_BOTTOM:
+ startX, startY = rect.x, rect.y - size.y - 2
+ else:
+ raise Exception("How did we get here?")
+
+ caption_height = wx.SystemSettings.GetMetric(wx.SYS_CAPTION_Y)
+ frame_border_x = wx.SystemSettings.GetMetric(wx.SYS_FRAMESIZE_X)
+ frame_border_y = wx.SystemSettings.GetMetric(wx.SYS_FRAMESIZE_Y)
+
+ stopX = size.x + caption_height + frame_border_x
+ stopY = size.x + frame_border_y
+
+ return startX, startY, stopX, stopY
+
+
+def CopyAttributes(newArt, oldArt):
+ """
+ Copies pens, brushes, colours and fonts from the old tab art to the new one.
+
+ :param `newArt`: the new instance of :class:`~lib.agw.aui.tabart.AuiDefaultTabArt`;
+ :param `oldArt`: the old instance of :class:`~lib.agw.aui.tabart.AuiDefaultTabArt`.
+ """
+
+ attrs = dir(oldArt)
+
+ for attr in attrs:
+ if attr.startswith("_") and (attr.endswith("_colour") or attr.endswith("_font") or \
+ attr.endswith("_font") or attr.endswith("_brush") or \
+ attr.endswith("Pen") or attr.endswith("_pen")):
+ setattr(newArt, attr, getattr(oldArt, attr))
+
+ return newArt
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/auibar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/auibar.py
new file mode 100644
index 0000000..16c21fe
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/auibar.py
@@ -0,0 +1,3989 @@
+"""
+`auibar.py` contains an implementation of :class:`AuiToolBar`, which is a completely owner-drawn
+toolbar perfectly integrated with the AUI layout system. This allows drag and drop of
+toolbars, docking/floating behaviour and the possibility to define "overflow" items
+in the toolbar itself.
+
+The default theme that is used is :class:`AuiToolBar`, which provides a modern,
+glossy look and feel. The theme can be changed by calling :meth:`AuiToolBar.SetArtProvider`.
+"""
+
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "31 March 2009"
+
+
+import wx
+import types
+
+from aui_utilities import BitmapFromBits, StepColour, GetLabelSize
+from aui_utilities import GetBaseColour, MakeDisabledBitmap
+
+import framemanager
+from aui_constants import *
+
+# wxPython version string
+_VERSION_STRING = wx.VERSION_STRING
+
+# AuiToolBar events
+wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN = wx.NewEventType()
+wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK = wx.NewEventType()
+wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK = wx.NewEventType()
+wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK = wx.NewEventType()
+wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG = wx.NewEventType()
+
+EVT_AUITOOLBAR_TOOL_DROPDOWN = wx.PyEventBinder(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, 1)
+""" A dropdown `AuiToolBarItem` is being shown. """
+EVT_AUITOOLBAR_OVERFLOW_CLICK = wx.PyEventBinder(wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, 1)
+""" The user left-clicked on the overflow button in `AuiToolBar`. """
+EVT_AUITOOLBAR_RIGHT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, 1)
+""" Fires an event when the user right-clicks on a `AuiToolBarItem`. """
+EVT_AUITOOLBAR_MIDDLE_CLICK = wx.PyEventBinder(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, 1)
+""" Fires an event when the user middle-clicks on a `AuiToolBarItem`. """
+EVT_AUITOOLBAR_BEGIN_DRAG = wx.PyEventBinder(wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, 1)
+""" A drag operation involving a toolbar item has started. """
+
+# ----------------------------------------------------------------------
+
+class CommandToolBarEvent(wx.PyCommandEvent):
+ """ A specialized command event class for events sent by :class:`AuiToolBar`. """
+
+ def __init__(self, command_type, win_id):
+ """
+ Default class constructor.
+
+ :param `command_type`: the event kind or an instance of :class:`PyCommandEvent`.
+ :param integer `win_id`: the window identification number.
+ """
+
+ if type(command_type) == types.IntType:
+ wx.PyCommandEvent.__init__(self, command_type, win_id)
+ else:
+ wx.PyCommandEvent.__init__(self, command_type.GetEventType(), command_type.GetId())
+
+ self.is_dropdown_clicked = False
+ self.click_pt = wx.Point(-1, -1)
+ self.rect = wx.Rect(-1, -1, 0, 0)
+ self.tool_id = -1
+
+
+ def IsDropDownClicked(self):
+ """ Returns whether the drop down menu has been clicked. """
+
+ return self.is_dropdown_clicked
+
+
+ def SetDropDownClicked(self, c):
+ """
+ Sets whether the drop down menu has been clicked.
+
+ :param bool `c`: ``True`` to set the drop down as clicked, ``False`` otherwise.
+ """
+
+ self.is_dropdown_clicked = c
+
+
+ def GetClickPoint(self):
+ """ Returns the point where the user clicked with the mouse. """
+
+ return self.click_pt
+
+
+ def SetClickPoint(self, p):
+ """
+ Sets the clicking point.
+
+ :param Point `p`: the location of the mouse click.
+ """
+
+ self.click_pt = p
+
+
+ def GetItemRect(self):
+ """ Returns the :class:`AuiToolBarItem` rectangle. """
+
+ return self.rect
+
+
+ def SetItemRect(self, r):
+ """
+ Sets the :class:`AuiToolBarItem` rectangle.
+
+ :param Rect `r`: the toolbar item rectangle.
+ """
+
+ self.rect = r
+
+
+ def GetToolId(self):
+ """ Returns the :class:`AuiToolBarItem` identifier. """
+
+ return self.tool_id
+
+
+ def SetToolId(self, id):
+ """
+ Sets the :class:`AuiToolBarItem` identifier.
+
+ :param integer `id`: the toolbar item identifier.
+ """
+
+ self.tool_id = id
+
+
+# ----------------------------------------------------------------------
+
+class AuiToolBarEvent(CommandToolBarEvent):
+ """ A specialized command event class for events sent by :class:`AuiToolBar`. """
+
+ def __init__(self, command_type=None, win_id=0):
+ """
+ Default class constructor.
+
+ :param `command_type`: the event kind or an instance of :class:`PyCommandEvent`.
+ :param integer `win_id`: the window identification number.
+ """
+
+ CommandToolBarEvent.__init__(self, command_type, win_id)
+
+ if type(command_type) == types.IntType:
+ self.notify = wx.NotifyEvent(command_type, win_id)
+ else:
+ self.notify = wx.NotifyEvent(command_type.GetEventType(), command_type.GetId())
+
+
+ def GetNotifyEvent(self):
+ """ Returns the actual :class:`NotifyEvent`. """
+
+ return self.notify
+
+
+ def IsAllowed(self):
+ """ Returns whether the event is allowed or not. """
+
+ return self.notify.IsAllowed()
+
+
+ def Veto(self):
+ """
+ Prevents the change announced by this event from happening.
+
+ It is in general a good idea to notify the user about the reasons for
+ vetoing the change because otherwise the applications behaviour (which
+ just refuses to do what the user wants) might be quite surprising.
+ """
+
+ self.notify.Veto()
+
+
+ def Allow(self):
+ """
+ This is the opposite of :meth:`Veto`: it explicitly allows the event to be
+ processed. For most events it is not necessary to call this method as the
+ events are allowed anyhow but some are forbidden by default (this will
+ be mentioned in the corresponding event description).
+ """
+
+ self.notify.Allow()
+
+
+# ----------------------------------------------------------------------
+
+class ToolbarCommandCapture(wx.PyEvtHandler):
+ """ A class to handle the dropdown window menu. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ wx.PyEvtHandler.__init__(self)
+ self._last_id = 0
+
+
+ def GetCommandId(self):
+ """ Returns the event command identifier. """
+
+ return self._last_id
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more suitable
+ event handler function(s).
+
+ :param `event`: the event to process.
+
+ :note: Normally, your application would not call this function: it is called
+ in the wxPython implementation to dispatch incoming user interface events
+ to the framework (and application).
+ However, you might need to call it if implementing new functionality (such as
+ a new control) where you define new event types, as opposed to allowing the
+ user to override functions.
+
+ An instance where you might actually override the :meth:`ProcessEvent` function is where
+ you want to direct event processing to event handlers not normally noticed by
+ wxPython. For example, in the document/view architecture, documents and views
+ are potential event handlers. When an event reaches a frame, :meth:`ProcessEvent` will
+ need to be called on the associated document and view in case event handler
+ functions are associated with these objects.
+
+ The normal order of event table searching is as follows:
+
+ 1. If the object is disabled (via a call to :meth:`~EvtHandler.SetEvtHandlerEnabled`) the function
+ skips to step (6).
+ 2. If the object is a :class:`Window`, :meth:`ProcessEvent` is recursively called on the window's
+ :class:`Validator`. If this returns ``True``, the function exits.
+ 3. wxWidgets `SearchEventTable` is called for this event handler. If this fails, the
+ base class table is tried, and so on until no more tables exist or an appropriate
+ function was found, in which case the function exits.
+ 4. The search is applied down the entire chain of event handlers (usually the chain
+ has a length of one). If this succeeds, the function exits.
+ 5. If the object is a :class:`Window` and the event is a :class:`CommandEvent`, :meth:`ProcessEvent` is
+ recursively applied to the parent window's event handler. If this returns ``True``,
+ the function exits.
+ 6. Finally, :meth:`ProcessEvent` is called on the :class:`App` object.
+ """
+
+ if event.GetEventType() == wx.wxEVT_COMMAND_MENU_SELECTED:
+ self._last_id = event.GetId()
+ return True
+
+ if self.GetNextHandler():
+ return self.GetNextHandler().ProcessEvent(event)
+
+ return False
+
+
+# ----------------------------------------------------------------------
+
+class AuiToolBarItem(object):
+ """
+ AuiToolBarItem is a toolbar element.
+
+ It has a unique id (except for the separators which always have id = -1), the
+ style (telling whether it is a normal button, separator or a control), the
+ state (toggled or not, enabled or not) and short and long help strings. The
+ default implementations use the short help string for the tooltip text which
+ is popped up when the mouse pointer enters the tool and the long help string
+ for the applications status bar.
+ """
+
+ def __init__(self, item=None):
+ """
+ Default class constructor.
+
+ :param `item`: another instance of :class:`AuiToolBarItem`.
+ """
+
+ if item:
+ self.Assign(item)
+ return
+
+ self.window = None
+ self.clockwisebmp = wx.NullBitmap
+ self.counterclockwisebmp = wx.NullBitmap
+ self.clockwisedisbmp = wx.NullBitmap
+ self.counterclockwisedisbmp = wx.NullBitmap
+ self.sizer_item = None
+ self.spacer_pixels = 0
+ self.id = 0
+ self.kind = ITEM_NORMAL
+ self.state = 0 # normal, enabled
+ self.proportion = 0
+ self.active = True
+ self.dropdown = True
+ self.sticky = True
+ self.user_data = 0
+
+ self.label = ""
+ self.bitmap = wx.NullBitmap
+ self.disabled_bitmap = wx.NullBitmap
+ self.hover_bitmap = wx.NullBitmap
+ self.short_help = ""
+ self.long_help = ""
+ self.target = None
+ self.min_size = wx.Size(-1, -1)
+ self.alignment = wx.ALIGN_CENTER
+ self.orientation = AUI_TBTOOL_HORIZONTAL
+
+
+ def Assign(self, c):
+ """
+ Assigns the properties of the :class:`AuiToolBarItem` `c` to `self`.
+
+ :param `c`: another instance of :class:`AuiToolBarItem`.
+ """
+
+ self.window = c.window
+ self.label = c.label
+ self.bitmap = c.bitmap
+ self.disabled_bitmap = c.disabled_bitmap
+ self.hover_bitmap = c.hover_bitmap
+ self.short_help = c.short_help
+ self.long_help = c.long_help
+ self.sizer_item = c.sizer_item
+ self.min_size = c.min_size
+ self.spacer_pixels = c.spacer_pixels
+ self.id = c.id
+ self.kind = c.kind
+ self.state = c.state
+ self.proportion = c.proportion
+ self.active = c.active
+ self.dropdown = c.dropdown
+ self.sticky = c.sticky
+ self.user_data = c.user_data
+ self.alignment = c.alignment
+ self.orientation = c.orientation
+ self.target = c.target
+
+
+ def SetWindow(self, w):
+ """
+ Assigns a window to the toolbar item.
+
+ :param Window `w`: associate this window `w` to the :class:`AuiToolBarItem`.
+ """
+
+ self.window = w
+
+
+ def GetWindow(self):
+ """ Returns window associated to the toolbar item. """
+
+ return self.window
+
+
+ def SetId(self, new_id):
+ """
+ Sets the toolbar item identifier.
+
+ :param integer `new_id`: the new tool id.
+ """
+
+ self.id = new_id
+
+
+ def GetId(self):
+ """ Returns the toolbar item identifier. """
+
+ return self.id
+
+
+ def SetKind(self, new_kind):
+ """
+ Sets the :class:`AuiToolBarItem` kind.
+
+ :param integer `new_kind`: can be one of the following items:
+
+ ======================== =============================
+ Item Kind Description
+ ======================== =============================
+ ``ITEM_CONTROL`` The item in the :class:`AuiToolBar` is a control
+ ``ITEM_LABEL`` The item in the :class:`AuiToolBar` is a text label
+ ``ITEM_SPACER`` The item in the :class:`AuiToolBar` is a spacer
+ ``ITEM_SEPARATOR`` The item in the :class:`AuiToolBar` is a separator
+ ``ITEM_CHECK`` The item in the :class:`AuiToolBar` is a toolbar check item
+ ``ITEM_NORMAL`` The item in the :class:`AuiToolBar` is a standard toolbar item
+ ``ITEM_RADIO`` The item in the :class:`AuiToolBar` is a toolbar radio item
+ ======================== =============================
+ """
+
+ self.kind = new_kind
+
+
+ def GetKind(self):
+ """
+ Returns the toolbar item kind.
+
+ See :meth:`SetKind` for more details.
+ """
+
+ return self.kind
+
+
+ def SetState(self, new_state):
+ """
+ Sets the toolbar item state.
+
+ :param `new_state`: can be one of the following states:
+
+ ============================================ ======================================
+ Button State Constant Description
+ ============================================ ======================================
+ ``AUI_BUTTON_STATE_NORMAL`` Normal button state
+ ``AUI_BUTTON_STATE_HOVER`` Hovered button state
+ ``AUI_BUTTON_STATE_PRESSED`` Pressed button state
+ ``AUI_BUTTON_STATE_DISABLED`` Disabled button state
+ ``AUI_BUTTON_STATE_HIDDEN`` Hidden button state
+ ``AUI_BUTTON_STATE_CHECKED`` Checked button state
+ ============================================ ======================================
+
+ """
+
+ self.state = new_state
+
+
+ def GetState(self):
+ """
+ Returns the toolbar item state.
+
+ :see: :meth:`SetState` for more details.
+ """
+
+ return self.state
+
+
+ def SetSizerItem(self, s):
+ """
+ Associates a sizer item to this toolbar item.
+
+ :param `s`: an instance of :class:`SizerItem`.
+ """
+
+ self.sizer_item = s
+
+
+ def GetSizerItem(self):
+ """ Returns the associated sizer item. """
+
+ return self.sizer_item
+
+
+ def SetLabel(self, s):
+ """
+ Sets the toolbar item label.
+
+ :param string `s`: the toolbar item label.
+ """
+
+ self.label = s
+
+
+ def GetLabel(self):
+ """ Returns the toolbar item label. """
+
+ return self.label
+
+
+ def SetBitmap(self, bmp):
+ """
+ Sets the toolbar item bitmap.
+
+ :param Bitmap `bmp`: the image associated with this :class:`AuiToolBarItem`.
+ """
+
+ self.bitmap = bmp
+
+
+ def GetBitmap(self):
+ """ Returns the toolbar item bitmap. """
+
+ return self.GetRotatedBitmap(False)
+
+
+ def SetDisabledBitmap(self, bmp):
+ """
+ Sets the toolbar item disabled bitmap.
+
+ :param Bitmap `bmp`: the disabled image associated with this :class:`AuiToolBarItem`.
+ """
+
+ self.disabled_bitmap = bmp
+
+
+ def GetDisabledBitmap(self):
+ """ Returns the toolbar item disabled bitmap. """
+
+ return self.GetRotatedBitmap(True)
+
+
+ def SetHoverBitmap(self, bmp):
+ """
+ Sets the toolbar item hover bitmap.
+
+ :param Bitmap `bmp`: the hover image associated with this :class:`AuiToolBarItem`.
+ """
+
+ self.hover_bitmap = bmp
+
+
+ def SetOrientation(self, a):
+ """
+ Sets the toolbar tool orientation.
+
+ :param integer `a`: one of ``AUI_TBTOOL_HORIZONTAL``, ``AUI_TBTOOL_VERT_CLOCKWISE`` or
+ ``AUI_TBTOOL_VERT_COUNTERCLOCKWISE``.
+ """
+
+ self.orientation = a
+
+
+ def GetOrientation(self):
+ """ Returns the toolbar tool orientation. """
+
+ return self.orientation
+
+
+ def GetHoverBitmap(self):
+ """ Returns the toolbar item hover bitmap. """
+
+ return self.hover_bitmap
+
+
+ def GetRotatedBitmap(self, disabled):
+ """
+ Returns the correct bitmap depending on the tool orientation.
+
+ :param bool `disabled`: whether to return the disabled bitmap or not.
+ """
+
+ bitmap_to_rotate = (disabled and [self.disabled_bitmap] or [self.bitmap])[0]
+ if not bitmap_to_rotate.IsOk() or self.orientation == AUI_TBTOOL_HORIZONTAL:
+ return bitmap_to_rotate
+
+ rotated_bitmap = wx.NullBitmap
+ clockwise = True
+ if self.orientation == AUI_TBTOOL_VERT_CLOCKWISE:
+ rotated_bitmap = (disabled and [self.clockwisedisbmp] or [self.clockwisebmp])[0]
+
+ elif self.orientation == AUI_TBTOOL_VERT_COUNTERCLOCKWISE:
+ rotated_bitmap = (disabled and [self.counterclockwisedisbmp] or [self.counterclockwisebmp])[0]
+ clockwise = False
+
+ if not rotated_bitmap.IsOk():
+ rotated_bitmap = wx.BitmapFromImage(bitmap_to_rotate.ConvertToImage().Rotate90(clockwise))
+
+ return rotated_bitmap
+
+
+ def SetShortHelp(self, s):
+ """
+ Sets the short help string for the :class:`AuiToolBarItem`, to be displayed in a
+ :class:`ToolTip` when the mouse hover over the toolbar item.
+
+ :param string `s`: the tool short help string.
+ """
+
+ self.short_help = s
+
+
+ def GetShortHelp(self):
+ """ Returns the short help string for the :class:`AuiToolBarItem`. """
+
+ return self.short_help
+
+
+ def SetLongHelp(self, s):
+ """
+ Sets the long help string for the toolbar item. This string is shown in the
+ statusbar (if any) of the parent frame when the mouse pointer is inside the
+ tool.
+
+ :param string `s`: the tool long help string.
+ """
+
+ self.long_help = s
+
+
+ def GetLongHelp(self):
+ """ Returns the long help string for the :class:`AuiToolBarItem`. """
+
+ return self.long_help
+
+
+ def SetMinSize(self, s):
+ """
+ Sets the toolbar item minimum size.
+
+ :param Size `s`: the toolbar item minimum size.
+ """
+
+ self.min_size = wx.Size(*s)
+
+
+ def GetMinSize(self):
+ """ Returns the toolbar item minimum size. """
+
+ return self.min_size
+
+
+ def SetSpacerPixels(self, s):
+ """
+ Sets the number of pixels for a toolbar item with kind = ``ITEM_SEPARATOR``.
+
+ :param integer `s`: number of pixels.
+ """
+
+ self.spacer_pixels = s
+
+
+ def GetSpacerPixels(self):
+ """ Returns the number of pixels for a toolbar item with kind = ``ITEM_SEPARATOR``. """
+
+ return self.spacer_pixels
+
+
+ def SetProportion(self, p):
+ """
+ Sets the :class:`AuiToolBarItem` proportion in the toolbar.
+
+ :param integer `p`: the item proportion.
+ """
+
+ self.proportion = p
+
+
+ def GetProportion(self):
+ """ Returns the :class:`AuiToolBarItem` proportion in the toolbar. """
+
+ return self.proportion
+
+
+ def SetActive(self, b):
+ """
+ Activates/deactivates the toolbar item.
+
+ :param bool `b`: ``True`` to activate the item, ``False`` to deactivate it.
+ """
+
+ self.active = b
+
+
+ def IsActive(self):
+ """ Returns whether the toolbar item is active or not. """
+
+ return self.active
+
+
+ def SetHasDropDown(self, b):
+ """
+ Sets whether the toolbar item has an associated dropdown menu.
+
+ :param bool `b`: ``True`` to set a dropdown menu, ``False`` otherwise.
+ """
+
+ self.dropdown = b
+
+
+ def HasDropDown(self):
+ """ Returns whether the toolbar item has an associated dropdown menu or not. """
+
+ return self.dropdown
+
+
+ def SetSticky(self, b):
+ """
+ Sets whether the toolbar item is sticky (permanent highlight after mouse enter)
+ or not.
+
+ :param bool `b`: ``True`` to set the item as sticky, ``False`` otherwise.
+ """
+
+ self.sticky = b
+
+
+ def IsSticky(self):
+ """ Returns whether the toolbar item has a sticky behaviour or not. """
+
+ return self.sticky
+
+
+ def SetUserData(self, data):
+ """
+ Associates some kind of user data to the toolbar item.
+
+ :param PyObject `data`: a Python object.
+
+ :note: The user data can be any Python object.
+ """
+
+ self.user_data = data
+
+
+ def GetUserData(self):
+ """ Returns the associated user data. """
+
+ return self.user_data
+
+
+ def SetAlignment(self, align):
+ """
+ Sets the toolbar item alignment.
+
+ :param integer `align`: the item alignment, which can be one of the available :class:`Sizer`
+ alignments.
+ """
+
+ self.alignment = align
+
+
+ def GetAlignment(self):
+ """ Returns the toolbar item alignment. """
+
+ return self.alignment
+
+
+# ----------------------------------------------------------------------
+
+class AuiDefaultToolBarArt(object):
+ """
+ Toolbar art provider code - a tab provider provides all drawing functionality to the :class:`AuiToolBar`.
+ This allows the :class:`AuiToolBar` to have a plugable look-and-feel.
+
+ By default, a :class:`AuiToolBar` uses an instance of this class called :class:`AuiDefaultToolBarArt`
+ which provides bitmap art and a colour scheme that is adapted to the major platforms'
+ look. You can either derive from that class to alter its behaviour or write a
+ completely new tab art class. Call :meth:`AuiToolBar.SetArtProvider` to make use this new tab art.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ self.SetDefaultColours()
+
+ self._agwFlags = 0
+ self._text_orientation = AUI_TBTOOL_TEXT_BOTTOM
+ self._highlight_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+
+ self._separator_size = 7
+ self._orientation = AUI_TBTOOL_HORIZONTAL
+ self._gripper_size = 7
+ self._overflow_size = 16
+
+ button_dropdown_bits = "\xe0\xf1\xfb"
+ overflow_bits = "\x80\xff\x80\xc1\xe3\xf7"
+
+ self._button_dropdown_bmp = BitmapFromBits(button_dropdown_bits, 5, 3, wx.BLACK)
+ self._disabled_button_dropdown_bmp = BitmapFromBits(button_dropdown_bits, 5, 3,
+ wx.Colour(128, 128, 128))
+ self._overflow_bmp = BitmapFromBits(overflow_bits, 7, 6, wx.BLACK)
+ self._disabled_overflow_bmp = BitmapFromBits(overflow_bits, 7, 6, wx.Colour(128, 128, 128))
+
+ self._font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+
+ def SetDefaultColours(self, base_colour=None):
+ """
+ Sets the default colours, which are calculated from the given base colour.
+
+ :param `base_colour`: an instance of :class:`Colour`. If defaulted to ``None``, a colour
+ is generated accordingly to the platform and theme.
+ """
+
+ if base_colour is None:
+ self._base_colour = GetBaseColour()
+ else:
+ self._base_colour = base_colour
+
+ darker3_colour = StepColour(self._base_colour, 60)
+ darker5_colour = StepColour(self._base_colour, 40)
+
+ self._gripper_pen1 = wx.Pen(darker5_colour)
+ self._gripper_pen2 = wx.Pen(darker3_colour)
+ self._gripper_pen3 = wx.WHITE_PEN
+
+
+ def Clone(self):
+ """ Clones the :class:`AuiDefaultToolBarArt` art. """
+
+ return AuiDefaultToolBarArt()
+
+
+ def SetAGWFlags(self, agwFlags):
+ """
+ Sets the toolbar art flags.
+
+ :param integer `agwFlags`: a combination of the following values:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_TB_TEXT`` Shows the text in the toolbar buttons; by default only icons are shown
+ ``AUI_TB_NO_TOOLTIPS`` Don't show tooltips on :class:`AuiToolBar` items
+ ``AUI_TB_NO_AUTORESIZE`` Do not auto-resize the :class:`AuiToolBar`
+ ``AUI_TB_GRIPPER`` Shows a gripper on the :class:`AuiToolBar`
+ ``AUI_TB_OVERFLOW`` The :class:`AuiToolBar` can contain overflow items
+ ``AUI_TB_VERTICAL`` The :class:`AuiToolBar` is vertical
+ ``AUI_TB_HORZ_LAYOUT`` Shows the text and the icons alongside, not vertically stacked. This style
+ must be used with ``AUI_TB_TEXT``
+ ``AUI_TB_PLAIN_BACKGROUND`` Don't draw a gradient background on the toolbar
+ ``AUI_TB_HORZ_TEXT`` Combination of ``AUI_TB_HORZ_LAYOUT`` and ``AUI_TB_TEXT``
+ ==================================== ==================================
+
+ """
+
+ self._agwFlags = agwFlags
+
+
+ def GetAGWFlags(self):
+ """
+ Returns the :class:`AuiDefaultToolBarArt` flags.
+
+ :see: :meth:`~AuiDefaultToolBarArt.SetAGWFlags` for more details.
+ """
+
+ return self._agwFlags
+
+
+ def SetFont(self, font):
+ """
+ Sets the :class:`AuiDefaultToolBarArt` font.
+
+ :param Font `font`: the font used for displaying toolbar item labels.
+ """
+
+ self._font = font
+
+
+ def SetTextOrientation(self, orientation):
+ """
+ Sets the text orientation.
+
+ :param integer `orientation`: can be one of the following constants:
+
+ ==================================== ==================================
+ Orientation Switches Description
+ ==================================== ==================================
+ ``AUI_TBTOOL_TEXT_LEFT`` Text in :class:`AuiToolBar` items is aligned left
+ ``AUI_TBTOOL_TEXT_RIGHT`` Text in :class:`AuiToolBar` items is aligned right
+ ``AUI_TBTOOL_TEXT_TOP`` Text in :class:`AuiToolBar` items is aligned top
+ ``AUI_TBTOOL_TEXT_BOTTOM`` Text in :class:`AuiToolBar` items is aligned bottom
+ ==================================== ==================================
+
+ """
+
+ self._text_orientation = orientation
+
+
+ def GetFont(self):
+ """ Returns the :class:`AuiDefaultToolBarArt` font. """
+
+ return self._font
+
+
+ def GetTextOrientation(self):
+ """
+ Returns the :class:`AuiDefaultToolBarArt` text orientation.
+
+ :see: :meth:`~AuiDefaultToolBarArt.SetTextOrientation` for more details.
+ """
+
+ return self._text_orientation
+
+
+ def SetOrientation(self, orientation):
+ """
+ Sets the toolbar tool orientation.
+
+ :param integer `orientation`: one of ``AUI_TBTOOL_HORIZONTAL``, ``AUI_TBTOOL_VERT_CLOCKWISE`` or
+ ``AUI_TBTOOL_VERT_COUNTERCLOCKWISE``.
+ """
+
+ self._orientation = orientation
+
+
+ def GetOrientation(self):
+ """ Returns the toolbar orientation. """
+
+ return self._orientation
+
+
+ def DrawBackground(self, dc, wnd, _rect, horizontal=True):
+ """
+ Draws a toolbar background with a gradient shading.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param Rect `_rect`: the :class:`AuiToolBarItem` rectangle;
+ :param bool `horizontal`: ``True`` if the toolbar is horizontal, ``False`` if it is vertical.
+ """
+
+ rect = wx.Rect(*_rect)
+
+ start_colour = StepColour(self._base_colour, 180)
+ end_colour = StepColour(self._base_colour, 85)
+ reflex_colour = StepColour(self._base_colour, 95)
+
+ dc.GradientFillLinear(rect, start_colour, end_colour,
+ (horizontal and [wx.SOUTH] or [wx.EAST])[0])
+
+ left = rect.GetLeft()
+ right = rect.GetRight()
+ top = rect.GetTop()
+ bottom = rect.GetBottom()
+
+ dc.SetPen(wx.Pen(reflex_colour))
+ if horizontal:
+ dc.DrawLine(left, bottom, right+1, bottom)
+ else:
+ dc.DrawLine(right, top, right, bottom+1)
+
+
+ def DrawPlainBackground(self, dc, wnd, _rect):
+ """
+ Draws a toolbar background with a plain colour.
+
+ This method contrasts with the default behaviour of the :class:`AuiToolBar` that
+ draws a background gradient and this break the window design when putting
+ it within a control that has margin between the borders and the toolbar
+ (example: put :class:`AuiToolBar` within a :class:`StaticBoxSizer` that has a plain background).
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param Rect `_rect`: the :class:`AuiToolBarItem` rectangle.
+ """
+
+ rect = wx.Rect(*_rect)
+ rect.height += 1
+
+ dc.SetBrush(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.DrawRectangle(rect.x - 1, rect.y - 1, rect.width + 2, rect.height + 1)
+
+
+ def DrawLabel(self, dc, wnd, item, rect):
+ """
+ Draws a toolbar item label.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param `item`: an instance of :class:`AuiToolBarItem`;
+ :param Rect `rect`: the :class:`AuiToolBarItem` rectangle.
+ """
+
+ dc.SetFont(self._font)
+
+ if item.state & AUI_BUTTON_STATE_DISABLED:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+ else:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNTEXT))
+
+ orient = item.GetOrientation()
+
+ horizontal = orient == AUI_TBTOOL_HORIZONTAL
+ # we only care about the text height here since the text
+ # will get cropped based on the width of the item
+ label_size = GetLabelSize(dc, item.GetLabel(), not horizontal)
+ text_width = label_size.GetWidth()
+ text_height = label_size.GetHeight()
+
+ if orient == AUI_TBTOOL_HORIZONTAL:
+ text_x = rect.x
+ text_y = rect.y + (rect.height-text_height)/2
+ dc.DrawText(item.GetLabel(), text_x, text_y)
+
+ elif orient == AUI_TBTOOL_VERT_CLOCKWISE:
+ text_x = rect.x + (rect.width+text_width)/2
+ text_y = rect.y
+ dc.DrawRotatedText(item.GetLabel(), text_x, text_y, 270)
+
+ elif AUI_TBTOOL_VERT_COUNTERCLOCKWISE:
+ text_x = rect.x + (rect.width-text_width)/2
+ text_y = rect.y + text_height
+ dc.DrawRotatedText(item.GetLabel(), text_x, text_y, 90)
+
+
+ def DrawButton(self, dc, wnd, item, rect):
+ """
+ Draws a toolbar item button.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param `item`: an instance of :class:`AuiToolBarItem`;
+ :param Rect `rect`: the :class:`AuiToolBarItem` rectangle.
+ """
+
+ bmp_rect, text_rect = self.GetToolsPosition(dc, item, rect)
+
+ if not item.GetState() & AUI_BUTTON_STATE_DISABLED:
+
+ if item.GetState() & AUI_BUTTON_STATE_PRESSED:
+
+ dc.SetPen(wx.Pen(self._highlight_colour))
+ dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 150)))
+ dc.DrawRectangleRect(rect)
+
+ elif item.GetState() & AUI_BUTTON_STATE_HOVER or item.IsSticky():
+
+ dc.SetPen(wx.Pen(self._highlight_colour))
+ dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 170)))
+
+ # draw an even lighter background for checked item hovers (since
+ # the hover background is the same colour as the check background)
+ if item.GetState() & AUI_BUTTON_STATE_CHECKED:
+ dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 180)))
+
+ dc.DrawRectangleRect(rect)
+
+ elif item.GetState() & AUI_BUTTON_STATE_CHECKED:
+
+ # it's important to put this code in an else statment after the
+ # hover, otherwise hovers won't draw properly for checked items
+ dc.SetPen(wx.Pen(self._highlight_colour))
+ dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 170)))
+ dc.DrawRectangleRect(rect)
+
+ if item.GetState() & AUI_BUTTON_STATE_DISABLED:
+ bmp = item.GetDisabledBitmap()
+ else:
+ bmp = item.GetBitmap()
+
+ if bmp.IsOk():
+ dc.DrawBitmap(bmp, bmp_rect.x, bmp_rect.y, True)
+
+ # set the item's text colour based on if it is disabled
+ dc.SetTextForeground(wx.BLACK)
+ if item.GetState() & AUI_BUTTON_STATE_DISABLED:
+ dc.SetTextForeground(DISABLED_TEXT_COLOUR)
+
+ if self._agwFlags & AUI_TB_TEXT and item.GetLabel() != "":
+ self.DrawLabel(dc, wnd, item, text_rect)
+
+
+ def DrawDropDownButton(self, dc, wnd, item, rect):
+ """
+ Draws a toolbar dropdown button.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param `item`: an instance of :class:`AuiToolBarItem`;
+ :param Rect `rect`: the :class:`AuiToolBarItem` rectangle.
+ """
+
+ dropbmp_x = dropbmp_y = 0
+
+ button_rect = wx.Rect(rect.x, rect.y, rect.width-BUTTON_DROPDOWN_WIDTH, rect.height)
+ dropdown_rect = wx.Rect(rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1, rect.y, BUTTON_DROPDOWN_WIDTH+1, rect.height)
+
+ horizontal = item.GetOrientation() == AUI_TBTOOL_HORIZONTAL
+
+ if horizontal:
+ button_rect = wx.Rect(rect.x, rect.y, rect.width-BUTTON_DROPDOWN_WIDTH, rect.height)
+ dropdown_rect = wx.Rect(rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1, rect.y, BUTTON_DROPDOWN_WIDTH+1, rect.height)
+ else:
+ button_rect = wx.Rect(rect.x, rect.y, rect.width, rect.height-BUTTON_DROPDOWN_WIDTH)
+ dropdown_rect = wx.Rect(rect.x, rect.y+rect.height-BUTTON_DROPDOWN_WIDTH-1, rect.width, BUTTON_DROPDOWN_WIDTH+1)
+
+ dropbmp_width = self._button_dropdown_bmp.GetWidth()
+ dropbmp_height = self._button_dropdown_bmp.GetHeight()
+ if not horizontal:
+ tmp = dropbmp_width
+ dropbmp_width = dropbmp_height
+ dropbmp_height = tmp
+
+ dropbmp_x = dropdown_rect.x + (dropdown_rect.width/2) - dropbmp_width/2
+ dropbmp_y = dropdown_rect.y + (dropdown_rect.height/2) - dropbmp_height/2
+
+ bmp_rect, text_rect = self.GetToolsPosition(dc, item, button_rect)
+
+ if item.GetState() & AUI_BUTTON_STATE_PRESSED:
+
+ dc.SetPen(wx.Pen(self._highlight_colour))
+ dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 140)))
+ dc.DrawRectangleRect(button_rect)
+ dc.DrawRectangleRect(dropdown_rect)
+
+ elif item.GetState() & AUI_BUTTON_STATE_HOVER or item.IsSticky():
+
+ dc.SetPen(wx.Pen(self._highlight_colour))
+ dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 170)))
+ dc.DrawRectangleRect(button_rect)
+ dc.DrawRectangleRect(dropdown_rect)
+
+ elif item.GetState() & AUI_BUTTON_STATE_CHECKED:
+ # it's important to put this code in an else statment after the
+ # hover, otherwise hovers won't draw properly for checked items
+ dc.SetPen(wx.Pen(self._highlight_colour))
+ dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 170)))
+ dc.DrawRectangleRect(button_rect)
+ dc.DrawRectangleRect(dropdown_rect)
+
+ if item.GetState() & AUI_BUTTON_STATE_DISABLED:
+
+ bmp = item.GetDisabledBitmap()
+ dropbmp = self._disabled_button_dropdown_bmp
+
+ else:
+
+ bmp = item.GetBitmap()
+ dropbmp = self._button_dropdown_bmp
+
+ if not bmp.IsOk():
+ return
+
+ dc.DrawBitmap(bmp, bmp_rect.x, bmp_rect.y, True)
+ if horizontal:
+ dc.DrawBitmap(dropbmp, dropbmp_x, dropbmp_y, True)
+ else:
+ dc.DrawBitmap(wx.BitmapFromImage(dropbmp.ConvertToImage().Rotate90(item.GetOrientation() == AUI_TBTOOL_VERT_CLOCKWISE)),
+ dropbmp_x, dropbmp_y, True)
+
+ # set the item's text colour based on if it is disabled
+ dc.SetTextForeground(wx.BLACK)
+ if item.GetState() & AUI_BUTTON_STATE_DISABLED:
+ dc.SetTextForeground(DISABLED_TEXT_COLOUR)
+
+ if self._agwFlags & AUI_TB_TEXT and item.GetLabel() != "":
+ self.DrawLabel(dc, wnd, item, text_rect)
+
+
+ def DrawControlLabel(self, dc, wnd, item, rect):
+ """
+ Draws a label for a toolbar control.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param `item`: an instance of :class:`AuiToolBarItem`;
+ :param Rect `rect`: the :class:`AuiToolBarItem` rectangle.
+ """
+
+ label_size = GetLabelSize(dc, item.GetLabel(), item.GetOrientation() != AUI_TBTOOL_HORIZONTAL)
+ text_height = label_size.GetHeight()
+ text_width = label_size.GetWidth()
+
+ dc.SetFont(self._font)
+
+ if self._agwFlags & AUI_TB_TEXT:
+
+ tx, text_height = dc.GetTextExtent("ABCDHgj")
+
+ text_width, ty = dc.GetTextExtent(item.GetLabel())
+
+ # don't draw the label if it is wider than the item width
+ if text_width > rect.width:
+ return
+
+ # set the label's text colour
+ dc.SetTextForeground(wx.BLACK)
+
+ text_x = rect.x + (rect.width/2) - (text_width/2) + 1
+ text_y = rect.y + rect.height - text_height - 1
+
+ if self._agwFlags & AUI_TB_TEXT and item.GetLabel() != "":
+ dc.DrawText(item.GetLabel(), text_x, text_y)
+
+
+ def GetLabelSize(self, dc, wnd, item):
+ """
+ Returns the label size for a toolbar item.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param `item`: an instance of :class:`AuiToolBarItem`.
+ """
+
+ dc.SetFont(self._font)
+ label_size = GetLabelSize(dc, item.GetLabel(), self._orientation != AUI_TBTOOL_HORIZONTAL)
+
+ return wx.Size(item.GetMinSize().GetWidth(), label_size.GetHeight())
+
+
+ def GetToolSize(self, dc, wnd, item):
+ """
+ Returns the toolbar item size.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param `item`: an instance of :class:`AuiToolBarItem`.
+ """
+
+ if not item.GetBitmap().IsOk() and not self._agwFlags & AUI_TB_TEXT:
+ return wx.Size(16, 16)
+
+ width = item.GetBitmap().GetWidth()
+ height = item.GetBitmap().GetHeight()
+
+ if self._agwFlags & AUI_TB_TEXT:
+
+ dc.SetFont(self._font)
+ label_size = GetLabelSize(dc, item.GetLabel(), self.GetOrientation() != AUI_TBTOOL_HORIZONTAL)
+ padding = 6
+
+ if self._text_orientation == AUI_TBTOOL_TEXT_BOTTOM:
+
+ if self.GetOrientation() != AUI_TBTOOL_HORIZONTAL:
+ height += 3 # space between top border and bitmap
+ height += 3 # space between bitmap and text
+ padding = 0
+
+ height += label_size.GetHeight()
+
+ if item.GetLabel() != "":
+ width = max(width, label_size.GetWidth()+padding)
+
+ elif self._text_orientation == AUI_TBTOOL_TEXT_RIGHT and item.GetLabel() != "":
+
+ if self.GetOrientation() == AUI_TBTOOL_HORIZONTAL:
+
+ width += 3 # space between left border and bitmap
+ width += 3 # space between bitmap and text
+ padding = 0
+
+ width += label_size.GetWidth()
+ height = max(height, label_size.GetHeight()+padding)
+
+ # if the tool has a dropdown button, add it to the width
+ if item.HasDropDown():
+ if item.GetOrientation() == AUI_TBTOOL_HORIZONTAL:
+ width += BUTTON_DROPDOWN_WIDTH+4
+ else:
+ height += BUTTON_DROPDOWN_WIDTH+4
+
+ return wx.Size(width, height)
+
+
+ def DrawSeparator(self, dc, wnd, _rect):
+ """
+ Draws a toolbar separator.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param Rect `_rect`: the :class:`AuiToolBarItem` rectangle.
+ """
+
+ horizontal = True
+ if self._agwFlags & AUI_TB_VERTICAL:
+ horizontal = False
+
+ rect = wx.Rect(*_rect)
+
+ if horizontal:
+
+ rect.x += (rect.width/2)
+ rect.width = 1
+ new_height = (rect.height*3)/4
+ rect.y += (rect.height/2) - (new_height/2)
+ rect.height = new_height
+
+ else:
+
+ rect.y += (rect.height/2)
+ rect.height = 1
+ new_width = (rect.width*3)/4
+ rect.x += (rect.width/2) - (new_width/2)
+ rect.width = new_width
+
+ start_colour = StepColour(self._base_colour, 80)
+ end_colour = StepColour(self._base_colour, 80)
+ dc.GradientFillLinear(rect, start_colour, end_colour, (horizontal and [wx.SOUTH] or [wx.EAST])[0])
+
+
+ def DrawGripper(self, dc, wnd, rect):
+ """
+ Draws the toolbar gripper.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param Rect `rect`: the :class:`AuiToolBarItem` rectangle.
+ """
+
+ i = 0
+ while 1:
+
+ if self._agwFlags & AUI_TB_VERTICAL:
+
+ x = rect.x + (i*4) + 4
+ y = rect.y + 3
+ if x > rect.GetWidth() - 4:
+ break
+
+ else:
+
+ x = rect.x + 3
+ y = rect.y + (i*4) + 4
+ if y > rect.GetHeight() - 4:
+ break
+
+ dc.SetPen(self._gripper_pen1)
+ dc.DrawPoint(x, y)
+ dc.SetPen(self._gripper_pen2)
+ dc.DrawPoint(x, y+1)
+ dc.DrawPoint(x+1, y)
+ dc.SetPen(self._gripper_pen3)
+ dc.DrawPoint(x+2, y+1)
+ dc.DrawPoint(x+2, y+2)
+ dc.DrawPoint(x+1, y+2)
+
+ i += 1
+
+
+ def DrawOverflowButton(self, dc, wnd, rect, state):
+ """
+ Draws the overflow button for the :class:`AuiToolBar`.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` derived window;
+ :param Rect `rect`: the :class:`AuiToolBarItem` rectangle;
+ :param integer `state`: the overflow button state.
+ """
+
+ if state & AUI_BUTTON_STATE_HOVER or state & AUI_BUTTON_STATE_PRESSED:
+
+ cli_rect = wnd.GetClientRect()
+ light_gray_bg = StepColour(self._highlight_colour, 170)
+
+ if self._agwFlags & AUI_TB_VERTICAL:
+
+ dc.SetPen(wx.Pen(self._highlight_colour))
+ dc.DrawLine(rect.x, rect.y, rect.x+rect.width, rect.y)
+ dc.SetPen(wx.Pen(light_gray_bg))
+ dc.SetBrush(wx.Brush(light_gray_bg))
+ dc.DrawRectangle(rect.x, rect.y+1, rect.width, rect.height)
+
+ else:
+
+ dc.SetPen(wx.Pen(self._highlight_colour))
+ dc.DrawLine(rect.x, rect.y, rect.x, rect.y+rect.height)
+ dc.SetPen(wx.Pen(light_gray_bg))
+ dc.SetBrush(wx.Brush(light_gray_bg))
+ dc.DrawRectangle(rect.x+1, rect.y, rect.width, rect.height)
+
+ x = rect.x + 1 + (rect.width-self._overflow_bmp.GetWidth())/2
+ y = rect.y + 1 + (rect.height-self._overflow_bmp.GetHeight())/2
+ dc.DrawBitmap(self._overflow_bmp, x, y, True)
+
+
+ def GetElementSize(self, element_id):
+ """
+ Returns the size of a UI element in the :class:`AuiToolBar`.
+
+ :param integer `element_id`: can be one of the following:
+
+ ==================================== ==================================
+ Element Identifier Description
+ ==================================== ==================================
+ ``AUI_TBART_SEPARATOR_SIZE`` Separator size in :class:`AuiToolBar`
+ ``AUI_TBART_GRIPPER_SIZE`` Gripper size in :class:`AuiToolBar`
+ ``AUI_TBART_OVERFLOW_SIZE`` Overflow button size in :class:`AuiToolBar`
+ ==================================== ==================================
+ """
+
+ if element_id == AUI_TBART_SEPARATOR_SIZE:
+ return self._separator_size
+ elif element_id == AUI_TBART_GRIPPER_SIZE:
+ return self._gripper_size
+ elif element_id == AUI_TBART_OVERFLOW_SIZE:
+ return self._overflow_size
+
+ return 0
+
+
+ def SetElementSize(self, element_id, size):
+ """
+ Sets the size of a UI element in the :class:`AuiToolBar`.
+
+ :param integer `element_id`: can be one of the following:
+
+ ==================================== ==================================
+ Element Identifier Description
+ ==================================== ==================================
+ ``AUI_TBART_SEPARATOR_SIZE`` Separator size in :class:`AuiToolBar`
+ ``AUI_TBART_GRIPPER_SIZE`` Gripper size in :class:`AuiToolBar`
+ ``AUI_TBART_OVERFLOW_SIZE`` Overflow button size in :class:`AuiToolBar`
+ ==================================== ==================================
+
+ :param integer `size`: the new size of the UI element.
+ """
+
+ if element_id == AUI_TBART_SEPARATOR_SIZE:
+ self._separator_size = size
+ elif element_id == AUI_TBART_GRIPPER_SIZE:
+ self._gripper_size = size
+ elif element_id == AUI_TBART_OVERFLOW_SIZE:
+ self._overflow_size = size
+
+
+ def ShowDropDown(self, wnd, items):
+ """
+ Shows the drop down window menu for overflow items.
+
+ :param `wnd`: an instance of :class:`Window`;
+ :param list `items`: a list of the overflow toolbar items.
+ """
+
+ menuPopup = wx.Menu()
+ items_added = 0
+
+ for item in items:
+
+ if item.GetKind() not in [ITEM_SEPARATOR, ITEM_SPACER, ITEM_CONTROL]:
+
+ text = item.GetShortHelp()
+ if text == "":
+ text = item.GetLabel()
+ if text == "":
+ text = " "
+
+ kind = item.GetKind()
+ m = wx.MenuItem(menuPopup, item.GetId(), text, item.GetShortHelp(), kind)
+ orientation = item.GetOrientation()
+ item.SetOrientation(AUI_TBTOOL_HORIZONTAL)
+
+ if kind not in [ITEM_CHECK, ITEM_RADIO]:
+ m.SetBitmap(item.GetBitmap())
+
+ item.SetOrientation(orientation)
+
+ menuPopup.AppendItem(m)
+ if kind in [ITEM_CHECK, ITEM_RADIO]:
+ state = (item.state & AUI_BUTTON_STATE_CHECKED and [True] or [False])[0]
+ m.Check(state)
+
+ items_added += 1
+
+ else:
+
+ if items_added > 0 and item.GetKind() == ITEM_SEPARATOR:
+ menuPopup.AppendSeparator()
+
+ # find out where to put the popup menu of window items
+ pt = wx.GetMousePosition()
+ pt = wnd.ScreenToClient(pt)
+
+ # find out the screen coordinate at the bottom of the tab ctrl
+ cli_rect = wnd.GetClientRect()
+ pt.y = cli_rect.y + cli_rect.height
+
+ cc = ToolbarCommandCapture()
+ wnd.PushEventHandler(cc)
+
+ # Adjustments to get slightly better menu placement
+ if wx.Platform == "__WXMAC__":
+ pt.y += 5
+ pt.x -= 5
+
+ wnd.PopupMenu(menuPopup, pt)
+ command = cc.GetCommandId()
+ wnd.PopEventHandler(True)
+
+ return command
+
+
+ def GetToolsPosition(self, dc, item, rect):
+ """
+ Returns the bitmap and text rectangles for a toolbar item.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `item`: an instance of :class:`AuiToolBarItem`;
+ :param Rect `rect`: the tool rectangle.
+ """
+
+ text_width = text_height = 0
+ horizontal = self._orientation == AUI_TBTOOL_HORIZONTAL
+ text_bottom = self._text_orientation == AUI_TBTOOL_TEXT_BOTTOM
+ text_right = self._text_orientation == AUI_TBTOOL_TEXT_RIGHT
+ bmp_width = item.GetBitmap().GetWidth()
+ bmp_height = item.GetBitmap().GetHeight()
+
+ if self._agwFlags & AUI_TB_TEXT:
+ dc.SetFont(self._font)
+ label_size = GetLabelSize(dc, item.GetLabel(), not horizontal)
+ text_height = label_size.GetHeight()
+ text_width = label_size.GetWidth()
+
+ bmp_x = bmp_y = text_x = text_y = 0
+
+ if horizontal and text_bottom:
+ bmp_x = rect.x + (rect.width/2) - (bmp_width/2)
+ bmp_y = rect.y + 3
+ text_x = rect.x + (rect.width/2) - (text_width/2)
+ text_y = rect.y + ((bmp_y - rect.y) * 2) + bmp_height
+
+ elif horizontal and text_right:
+ bmp_x = rect.x + 3
+ bmp_y = rect.y + (rect.height/2) - (bmp_height / 2)
+ text_x = rect.x + ((bmp_x - rect.x) * 2) + bmp_width
+ text_y = rect.y + (rect.height/2) - (text_height/2)
+
+ elif not horizontal and text_bottom:
+ bmp_x = rect.x + (rect.width / 2) - (bmp_width / 2)
+ bmp_y = rect.y + 3
+ text_x = rect.x + (rect.width / 2) - (text_width / 2)
+ text_y = rect.y + ((bmp_y - rect.y) * 2) + bmp_height
+
+ bmp_rect = wx.Rect(bmp_x, bmp_y, bmp_width, bmp_height)
+ text_rect = wx.Rect(text_x, text_y, text_width, text_height)
+
+ return bmp_rect, text_rect
+
+
+class AuiToolBar(wx.PyControl):
+ """
+ AuiToolBar is a completely owner-drawn toolbar perfectly integrated with the AUI layout system.
+ This allows drag and drop of toolbars, docking/floating behaviour and the possibility to define
+ "overflow" items in the toolbar itself.
+
+ The default theme that is used is :class:`AuiDefaultToolBarArt`, which provides a modern,
+ glossy look and feel. The theme can be changed by calling :meth:`AuiToolBar.SetArtProvider`.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, agwStyle=AUI_TB_DEFAULT_STYLE):
+ """
+ Default class constructor.
+
+ :param Window `parent`: the :class:`AuiToolBar` parent;
+ :param integer `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param Point `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param Size `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param integer `style`: the control window style;
+ :param integer `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_TB_TEXT`` Shows the text in the toolbar buttons; by default only icons are shown
+ ``AUI_TB_NO_TOOLTIPS`` Don't show tooltips on :class:`AuiToolBar` items
+ ``AUI_TB_NO_AUTORESIZE`` Do not auto-resize the :class:`AuiToolBar`
+ ``AUI_TB_GRIPPER`` Shows a gripper on the :class:`AuiToolBar`
+ ``AUI_TB_OVERFLOW`` The :class:`AuiToolBar` can contain overflow items
+ ``AUI_TB_VERTICAL`` The :class:`AuiToolBar` is vertical
+ ``AUI_TB_HORZ_LAYOUT`` Shows the text and the icons alongside, not vertically stacked.
+ This style must be used with ``AUI_TB_TEXT``
+ ``AUI_TB_PLAIN_BACKGROUND`` Don't draw a gradient background on the toolbar
+ ``AUI_TB_HORZ_TEXT`` Combination of ``AUI_TB_HORZ_LAYOUT`` and ``AUI_TB_TEXT``
+ ==================================== ==================================
+
+ The default value for `agwStyle` is: ``AUI_TB_DEFAULT_STYLE`` = 0
+
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style|wx.BORDER_NONE)
+
+ self._sizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.SetSizer(self._sizer)
+ self._button_width = -1
+ self._button_height = -1
+ self._sizer_element_count = 0
+ self._action_pos = wx.Point(-1, -1)
+ self._action_item = None
+ self._tip_item = None
+ self._art = AuiDefaultToolBarArt()
+ self._tool_packing = 2
+ self._tool_border_padding = 3
+ self._tool_text_orientation = AUI_TBTOOL_TEXT_BOTTOM
+ self._tool_orientation = AUI_TBTOOL_HORIZONTAL
+ self._tool_alignment = wx.EXPAND
+ self._gripper_sizer_item = None
+ self._overflow_sizer_item = None
+ self._dragging = False
+
+ self._agwStyle = self._originalStyle = agwStyle
+
+ self._gripper_visible = (self._agwStyle & AUI_TB_GRIPPER and [True] or [False])[0]
+ self._overflow_visible = (self._agwStyle & AUI_TB_OVERFLOW and [True] or [False])[0]
+ self._overflow_state = 0
+ self._custom_overflow_prepend = []
+ self._custom_overflow_append = []
+
+ self._items = []
+
+ self.SetMargins(5, 5, 2, 2)
+ self.SetFont(wx.NORMAL_FONT)
+ self._art.SetAGWFlags(self._agwStyle)
+ self.SetExtraStyle(wx.WS_EX_PROCESS_IDLE)
+
+ if agwStyle & AUI_TB_HORZ_LAYOUT:
+ self.SetToolTextOrientation(AUI_TBTOOL_TEXT_RIGHT)
+ elif agwStyle & AUI_TB_VERTICAL:
+ if agwStyle & AUI_TB_CLOCKWISE:
+ self.SetToolOrientation(AUI_TBTOOL_VERT_CLOCKWISE)
+ elif agwStyle & AUI_TB_COUNTERCLOCKWISE:
+ self.SetToolOrientation(AUI_TBTOOL_VERT_COUNTERCLOCKWISE)
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
+ self.Bind(wx.EVT_RIGHT_DCLICK, self.OnRightDown)
+ self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
+ self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown)
+ self.Bind(wx.EVT_MIDDLE_DCLICK, self.OnMiddleDown)
+ self.Bind(wx.EVT_MIDDLE_UP, self.OnMiddleUp)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+ self.Bind(wx.EVT_SET_CURSOR, self.OnSetCursor)
+
+
+ def SetWindowStyleFlag(self, style):
+ """
+ Sets the style of the window.
+
+ :param integer `style`: the new window style.
+
+ :note: Please note that some styles cannot be changed after the window
+ creation and that `Refresh` might need to be be called after changing the
+ others for the change to take place immediately.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ wx.PyControl.SetWindowStyleFlag(self, style|wx.BORDER_NONE)
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the AGW-specific style of the window.
+
+ :param integer `agwStyle`: the new window style. This can be a combination of the
+ following bits:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_TB_TEXT`` Shows the text in the toolbar buttons; by default only icons are shown
+ ``AUI_TB_NO_TOOLTIPS`` Don't show tooltips on :class:`AuiToolBar` items
+ ``AUI_TB_NO_AUTORESIZE`` Do not auto-resize the :class:`AuiToolBar`
+ ``AUI_TB_GRIPPER`` Shows a gripper on the :class:`AuiToolBar`
+ ``AUI_TB_OVERFLOW`` The :class:`AuiToolBar` can contain overflow items
+ ``AUI_TB_VERTICAL`` The :class:`AuiToolBar` is vertical
+ ``AUI_TB_HORZ_LAYOUT`` Shows the text and the icons alongside, not vertically stacked.
+ This style must be used with ``AUI_TB_TEXT``
+ ``AUI_TB_PLAIN_BACKGROUND`` Don't draw a gradient background on the toolbar
+ ``AUI_TB_HORZ_TEXT`` Combination of ``AUI_TB_HORZ_LAYOUT`` and ``AUI_TB_TEXT``
+ ==================================== ==================================
+
+ :note: Please note that some styles cannot be changed after the window
+ creation and that `Refresh` might need to be be called after changing the
+ others for the change to take place immediately.
+ """
+
+ self._agwStyle = self._originalStyle = agwStyle
+
+ if self._art:
+ self._art.SetAGWFlags(self._agwStyle)
+
+ if agwStyle & AUI_TB_GRIPPER:
+ self._gripper_visible = True
+ else:
+ self._gripper_visible = False
+
+ if agwStyle & AUI_TB_OVERFLOW:
+ self._overflow_visible = True
+ else:
+ self._overflow_visible = False
+
+ if agwStyle & AUI_TB_HORZ_LAYOUT:
+ self.SetToolTextOrientation(AUI_TBTOOL_TEXT_RIGHT)
+ else:
+ self.SetToolTextOrientation(AUI_TBTOOL_TEXT_BOTTOM)
+
+ if agwStyle & AUI_TB_VERTICAL:
+ if agwStyle & AUI_TB_CLOCKWISE:
+ self.SetToolOrientation(AUI_TBTOOL_VERT_CLOCKWISE)
+ elif agwStyle & AUI_TB_COUNTERCLOCKWISE:
+ self.SetToolOrientation(AUI_TBTOOL_VERT_COUNTERCLOCKWISE)
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the AGW-specific window style flag.
+
+ :see: :meth:`SetAGWWindowStyleFlag` for an explanation of various AGW-specific style.
+ """
+
+ return self._agwStyle
+
+
+ def SetArtProvider(self, art):
+ """
+ Instructs :class:`AuiToolBar` to use art provider specified by parameter `art`
+ for all drawing calls. This allows plugable look-and-feel features.
+
+ :param `art`: an art provider.
+
+ :note: The previous art provider object, if any, will be deleted by :class:`AuiToolBar`.
+ """
+
+ del self._art
+ self._art = art
+
+ if self._art:
+ self._art.SetAGWFlags(self._agwStyle)
+ self._art.SetTextOrientation(self._tool_text_orientation)
+ self._art.SetOrientation(self._tool_orientation)
+
+
+ def GetArtProvider(self):
+ """ Returns the current art provider being used. """
+
+ return self._art
+
+
+ def AddSimpleTool(self, tool_id, label, bitmap, short_help_string="", kind=ITEM_NORMAL, target=None):
+ """
+ Adds a tool to the toolbar. This is the simplest method you can use to
+ ass an item to the :class:`AuiToolBar`.
+
+ :param integer `tool_id`: an integer by which the tool may be identified in subsequent operations;
+ :param string `label`: the toolbar tool label;
+ :param Bitmap `bitmap`: the primary tool bitmap;
+ :param string `short_help_string`: this string is used for the tools tooltip;
+ :param integer `kind`: the item kind. Can be one of the following:
+
+ ======================== =============================
+ Item Kind Description
+ ======================== =============================
+ ``ITEM_CONTROL`` The item in the :class:`AuiToolBar` is a control
+ ``ITEM_LABEL`` The item in the :class:`AuiToolBar` is a text label
+ ``ITEM_SPACER`` The item in the :class:`AuiToolBar` is a spacer
+ ``ITEM_SEPARATOR`` The item in the :class:`AuiToolBar` is a separator
+ ``ITEM_CHECK`` The item in the :class:`AuiToolBar` is a toolbar check item
+ ``ITEM_NORMAL`` The item in the :class:`AuiToolBar` is a standard toolbar item
+ ``ITEM_RADIO`` The item in the :class:`AuiToolBar` is a toolbar radio item
+ ======================== =============================
+
+ :param `target`: a custom string indicating that an instance of :class:`~lib.agw.aui.framemanager.AuiPaneInfo`
+ has been minimized into this toolbar.
+ """
+
+ return self.AddTool(tool_id, label, bitmap, wx.NullBitmap, kind, short_help_string, "", None, target)
+
+
+ def AddToggleTool(self, tool_id, bitmap, disabled_bitmap, toggle=False, client_data=None, short_help_string="", long_help_string=""):
+ """
+ Adds a toggle tool to the toolbar.
+
+ :param integer `tool_id`: an integer by which the tool may be identified in subsequent operations;
+ :param Bitmap `bitmap`: the primary tool bitmap;
+ :param Bitmap `disabled_bitmap`: the bitmap to use when the tool is disabled. If it is equal to
+ :class:`NullBitmap`, the disabled bitmap is automatically generated by greing the normal one;
+ :param PyObject `client_data`: whatever Python object to associate with the toolbar item;
+ :param string `short_help_string`: this string is used for the tools tooltip;
+ :param string `long_help_string`: this string is shown in the statusbar (if any) of the parent
+ frame when the mouse pointer is inside the tool.
+ """
+
+ kind = (toggle and [ITEM_CHECK] or [ITEM_NORMAL])[0]
+ return self.AddTool(tool_id, "", bitmap, disabled_bitmap, kind, short_help_string, long_help_string, client_data)
+
+
+ def AddTool(self, tool_id, label, bitmap, disabled_bitmap, kind, short_help_string='', long_help_string='', client_data=None, target=None):
+ """
+ Adds a tool to the toolbar. This is the full feature version of :meth:`AddTool`.
+
+ :param integer `tool_id`: an integer by which the tool may be identified in subsequent operations;
+ :param string `label`: the toolbar tool label;
+ :param Bitmap `bitmap`: the primary tool bitmap;
+ :param Bitmap `disabled_bitmap`: the bitmap to use when the tool is disabled. If it is equal to
+ :class:`NullBitmap`, the disabled bitmap is automatically generated by greing the normal one;
+ :param integer `kind`: the item kind. Can be one of the following:
+
+ ======================== =============================
+ Item Kind Description
+ ======================== =============================
+ ``ITEM_CONTROL`` The item in the :class:`AuiToolBar` is a control
+ ``ITEM_LABEL`` The item in the :class:`AuiToolBar` is a text label
+ ``ITEM_SPACER`` The item in the :class:`AuiToolBar` is a spacer
+ ``ITEM_SEPARATOR`` The item in the :class:`AuiToolBar` is a separator
+ ``ITEM_CHECK`` The item in the :class:`AuiToolBar` is a toolbar check item
+ ``ITEM_NORMAL`` The item in the :class:`AuiToolBar` is a standard toolbar item
+ ``ITEM_RADIO`` The item in the :class:`AuiToolBar` is a toolbar radio item
+ ======================== =============================
+
+ :param string `short_help_string`: this string is used for the tools tooltip;
+ :param string `long_help_string`: this string is shown in the statusbar (if any) of the parent
+ frame when the mouse pointer is inside the tool.
+ :param PyObject `client_data`: whatever Python object to associate with the toolbar item.
+ :param `target`: a custom string indicating that an instance of :class:`~lib.agw.aui.framemanager.AuiPaneInfo`
+ has been minimized into this toolbar.
+ """
+
+ item = AuiToolBarItem()
+ item.window = None
+ item.label = label
+ item.bitmap = bitmap
+ item.disabled_bitmap = disabled_bitmap
+ item.short_help = short_help_string
+ item.long_help = long_help_string
+ item.target = target
+ item.active = True
+ item.dropdown = False
+ item.spacer_pixels = 0
+
+ if tool_id == wx.ID_ANY:
+ tool_id = wx.NewId()
+
+ item.id = tool_id
+ item.state = 0
+ item.proportion = 0
+ item.kind = kind
+ item.sizer_item = None
+ item.min_size = wx.Size(-1, -1)
+ item.user_data = 0
+ item.sticky = False
+ item.orientation = self._tool_orientation
+
+ if not item.disabled_bitmap.IsOk():
+ # no disabled bitmap specified, we need to make one
+ if item.bitmap.IsOk():
+ item.disabled_bitmap = MakeDisabledBitmap(item.bitmap)
+
+ self._items.append(item)
+ return self._items[-1]
+
+
+ def AddCheckTool(self, tool_id, label, bitmap, disabled_bitmap, short_help_string="", long_help_string="", client_data=None):
+ """
+ Adds a new check (or toggle) tool to the :class:`AuiToolBar`.
+
+ :see: :meth:`AddTool` for an explanation of the input parameters.
+ """
+
+ return self.AddTool(tool_id, label, bitmap, disabled_bitmap, ITEM_CHECK, short_help_string, long_help_string, client_data)
+
+
+ def AddRadioTool(self, tool_id, label, bitmap, disabled_bitmap, short_help_string="", long_help_string="", client_data=None):
+ """
+ Adds a new radio tool to the toolbar.
+
+ Consecutive radio tools form a radio group such that exactly one button
+ in the group is pressed at any moment, in other words whenever a button
+ in the group is pressed the previously pressed button is automatically
+ released. You should avoid having the radio groups of only one element
+ as it would be impossible for the user to use such button.
+
+ :note: By default, the first button in the radio group is initially pressed,
+ the others are not.
+
+ :see: :meth:`AddTool` for an explanation of the input parameters.
+ """
+
+ return self.AddTool(tool_id, label, bitmap, disabled_bitmap, ITEM_RADIO, short_help_string, long_help_string, client_data)
+
+
+ def AddControl(self, control, label=""):
+ """
+ Adds any control to the toolbar, typically e.g. a :class:`ComboBox`.
+
+ :param Window `control`: the control to be added;
+ :param string `label`: the label which appears if the control goes into the
+ overflow items in the toolbar.
+ """
+
+ item = AuiToolBarItem()
+ item.window = control
+ item.label = label
+ item.bitmap = wx.NullBitmap
+ item.disabled_bitmap = wx.NullBitmap
+ item.active = True
+ item.dropdown = False
+ item.spacer_pixels = 0
+ item.id = control.GetId()
+ item.state = 0
+ item.proportion = 0
+ item.kind = ITEM_CONTROL
+ item.sizer_item = None
+ item.min_size = control.GetEffectiveMinSize()
+ item.user_data = 0
+ item.sticky = False
+ item.orientation = self._tool_orientation
+
+ self._items.append(item)
+ return self._items[-1]
+
+
+ def AddLabel(self, tool_id, label="", width=0):
+ """
+ Adds a label tool to the :class:`AuiToolBar`.
+
+ :param integer `tool_id`: an integer by which the tool may be identified in subsequent operations;
+ :param string `label`: the toolbar tool label;
+ :param integer `width`: the tool width.
+ """
+
+ min_size = wx.Size(-1, -1)
+
+ if width != -1:
+ min_size.x = width
+
+ item = AuiToolBarItem()
+ item.window = None
+ item.label = label
+ item.bitmap = wx.NullBitmap
+ item.disabled_bitmap = wx.NullBitmap
+ item.active = True
+ item.dropdown = False
+ item.spacer_pixels = 0
+
+ if tool_id == wx.ID_ANY:
+ tool_id = wx.NewId()
+
+ item.id = tool_id
+ item.state = 0
+ item.proportion = 0
+ item.kind = ITEM_LABEL
+ item.sizer_item = None
+ item.min_size = min_size
+ item.user_data = 0
+ item.sticky = False
+ item.orientation = self._tool_orientation
+
+ self._items.append(item)
+ return self._items[-1]
+
+
+ def AddSeparator(self):
+ """ Adds a separator for spacing groups of tools. """
+
+ item = AuiToolBarItem()
+ item.window = None
+ item.label = ""
+ item.bitmap = wx.NullBitmap
+ item.disabled_bitmap = wx.NullBitmap
+ item.active = True
+ item.dropdown = False
+ item.id = -1
+ item.state = 0
+ item.proportion = 0
+ item.kind = ITEM_SEPARATOR
+ item.sizer_item = None
+ item.min_size = wx.Size(-1, -1)
+ item.user_data = 0
+ item.sticky = False
+ item.orientation = self._tool_orientation
+
+ self._items.append(item)
+ return self._items[-1]
+
+
+ def AddSpacer(self, pixels):
+ """
+ Adds a spacer for spacing groups of tools.
+
+ :param integer `pixels`: the width of the spacer.
+ """
+
+ item = AuiToolBarItem()
+ item.window = None
+ item.label = ""
+ item.bitmap = wx.NullBitmap
+ item.disabled_bitmap = wx.NullBitmap
+ item.active = True
+ item.dropdown = False
+ item.spacer_pixels = pixels
+ item.id = -1
+ item.state = 0
+ item.proportion = 0
+ item.kind = ITEM_SPACER
+ item.sizer_item = None
+ item.min_size = wx.Size(-1, -1)
+ item.user_data = 0
+ item.sticky = False
+ item.orientation = self._tool_orientation
+
+ self._items.append(item)
+ return self._items[-1]
+
+
+ def AddStretchSpacer(self, proportion=1):
+ """
+ Adds a stretchable spacer for spacing groups of tools.
+
+ :param integer `proportion`: the stretchable spacer proportion.
+ """
+
+ item = AuiToolBarItem()
+ item.window = None
+ item.label = ""
+ item.bitmap = wx.NullBitmap
+ item.disabled_bitmap = wx.NullBitmap
+ item.active = True
+ item.dropdown = False
+ item.spacer_pixels = 0
+ item.id = -1
+ item.state = 0
+ item.proportion = proportion
+ item.kind = ITEM_SPACER
+ item.sizer_item = None
+ item.min_size = wx.Size(-1, -1)
+ item.user_data = 0
+ item.sticky = False
+ item.orientation = self._tool_orientation
+
+ self._items.append(item)
+ return self._items[-1]
+
+
+ def Clear(self):
+ """ Deletes all the tools in the :class:`AuiToolBar`. """
+
+ self._items = []
+ self._sizer_element_count = 0
+
+
+ def ClearTools(self):
+ """ Deletes all the tools in the :class:`AuiToolBar`. """
+
+ self.Clear()
+
+
+ def DeleteTool(self, tool_id):
+ """
+ Removes the specified tool from the toolbar and deletes it.
+
+ :param integer `tool_id`: the :class:`AuiToolBarItem` identifier.
+
+ :returns: ``True`` if the tool was deleted, ``False`` otherwise.
+
+ :note: Note that it is unnecessary to call :meth:`Realize` for the change to
+ take place, it will happen immediately.
+ """
+
+ idx = self.GetToolIndex(tool_id)
+
+ if idx >= 0 and idx < len(self._items):
+ self._items.pop(idx)
+ self.Realize()
+ return True
+
+ return False
+
+
+ def DeleteToolByPos(self, pos):
+ """
+ This function behaves like :meth:`DeleteTool` but it deletes the tool at the specified position and not the one with the given id.
+
+ :param integer `pos`: the tool position.
+
+ :see: :meth:`~AuiToolBar.DeleteTool`
+ """
+
+ if pos >= 0 and pos < len(self._items):
+
+ self._items.pop(pos)
+ self.Realize()
+ return True
+
+ return False
+
+
+ def FindControl(self, id):
+ """
+ Returns a pointer to the control identified by `id` or ``None`` if no corresponding control is found.
+
+ :param integer `id`: the control identifier.
+ """
+
+ wnd = self.FindWindow(id)
+ return wnd
+
+
+ def FindTool(self, tool_id):
+ """
+ Finds a tool for the given tool id.
+
+ :param integer `tool_id`: the :class:`AuiToolBarItem` identifier.
+ """
+
+ for item in self._items:
+ if item.id == tool_id:
+ return item
+
+ return None
+
+
+ def FindToolByLabel(self, label):
+ """
+ Finds a tool for the given label.
+
+ :param string `label`: the :class:`AuiToolBarItem` label.
+ """
+
+ for item in self._items:
+ if item.label == label:
+ return item
+
+ return None
+
+
+ def FindToolForPosition(self, x, y):
+ """
+ Finds a tool for the given mouse position.
+
+ :param integer `x`: mouse `x` position;
+ :param integer `y`: mouse `y` position.
+
+ :returns: a pointer to a :class:`AuiToolBarItem` if a tool is found, or ``None`` otherwise.
+ """
+
+ for i, item in enumerate(self._items):
+ if not item.sizer_item:
+ continue
+
+ rect = item.sizer_item.GetRect()
+ if rect.Contains((x,y)):
+
+ # if the item doesn't fit on the toolbar, return None
+ if not self.GetToolFitsByIndex(i):
+ return None
+
+ return item
+
+ return None
+
+
+ def HitTest(self, x, y):
+ """
+ Finds a tool for the given mouse position.
+
+ :param integer `x`: mouse `x` screen position;
+ :param integer `y`: mouse `y` screen position.
+
+ :returns: a pointer to a :class:`AuiToolBarItem` if a tool is found, or ``None`` otherwise.
+
+ :note: This method is similar to :meth:`FindToolForPosition` but it works with absolute coordinates.
+ """
+
+ return self.FindToolForPosition(*self.ScreenToClient((x,y)))
+
+
+ def FindToolForPositionWithPacking(self, x, y):
+ """
+ Finds a tool for the given mouse position, taking into account also the tool packing.
+
+ :param integer `x`: mouse `x` position;
+ :param integer `y`: mouse `y` position.
+
+ :returns: a pointer to a :class:`AuiToolBarItem` if a tool is found, or ``None`` otherwise.
+ """
+
+ count = len(self._items)
+
+ for i, item in enumerate(self._items):
+ if not item.sizer_item:
+ continue
+
+ rect = item.sizer_item.GetRect()
+
+ # apply tool packing
+ if i+1 < count:
+ rect.width += self._tool_packing
+
+ if rect.Contains((x,y)):
+
+ # if the item doesn't fit on the toolbar, return None
+ if not self.GetToolFitsByIndex(i):
+ return None
+
+ return item
+
+ return None
+
+
+ def FindToolByIndex(self, pos):
+ """
+ Finds a tool for the given tool position in the :class:`AuiToolBar`.
+
+ :param integer `pos`: the tool position in the toolbar.
+
+ :returns: a pointer to a :class:`AuiToolBarItem` if a tool is found, or ``None`` otherwise.
+ """
+
+ if pos < 0 or pos >= len(self._items):
+ return None
+
+ return self._items[pos]
+
+
+ def SetToolBitmapSize(self, size):
+ """
+ Sets the default size of each tool bitmap. The default bitmap size is 16 by 15 pixels.
+
+ :param Size `size`: the size of the bitmaps in the toolbar.
+
+ :note: This should be called to tell the toolbar what the tool bitmap
+ size is. Call it before you add tools.
+
+ :note: Note that this is the size of the bitmap you pass to :meth:`AddTool`,
+ and not the eventual size of the tool button.
+
+ .. todo::
+
+ Add :class:`ToolBar` compatibility, actually implementing this method.
+
+ """
+
+ # TODO: wx.ToolBar compatibility
+ pass
+
+
+ def GetToolBitmapSize(self):
+ """
+ Returns the size of bitmap that the toolbar expects to have. The default bitmap size is 16 by 15 pixels.
+
+ :note: Note that this is the size of the bitmap you pass to :meth:`AddTool`,
+ and not the eventual size of the tool button.
+
+ .. todo::
+
+ Add :class:`ToolBar` compatibility, actually implementing this method.
+
+ """
+
+ # TODO: wx.ToolBar compatibility
+ return wx.Size(16, 15)
+
+
+ def SetToolProportion(self, tool_id, proportion):
+ """
+ Sets the tool proportion in the toolbar.
+
+ :param integer `tool_id`: the :class:`AuiToolBarItem` identifier;
+ :param integer `proportion`: the tool proportion in the toolbar.
+ """
+
+ item = self.FindTool(tool_id)
+ if not item:
+ return
+
+ item.proportion = proportion
+
+
+ def GetToolProportion(self, tool_id):
+ """
+ Returns the tool proportion in the toolbar.
+
+ :param integer `tool_id`: the :class:`AuiToolBarItem` identifier.
+ """
+
+ item = self.FindTool(tool_id)
+ if not item:
+ return
+
+ return item.proportion
+
+
+ def SetToolSeparation(self, separation):
+ """
+ Sets the separator size for the toolbar.
+
+ :param integer `separation`: the separator size in pixels.
+ """
+
+ if self._art:
+ self._art.SetElementSize(AUI_TBART_SEPARATOR_SIZE, separation)
+
+
+ def GetToolSeparation(self):
+ """ Returns the separator size for the toolbar, in pixels. """
+
+ if self._art:
+ return self._art.GetElementSize(AUI_TBART_SEPARATOR_SIZE)
+
+ return 5
+
+
+ def SetToolDropDown(self, tool_id, dropdown):
+ """
+ Assigns a drop down window menu to the toolbar item.
+
+ :param integer `tool_id`: the :class:`AuiToolBarItem` identifier;
+ :param bool `dropdown`: whether to assign a drop down menu or not.
+ """
+
+ item = self.FindTool(tool_id)
+ if not item:
+ return
+
+ item.dropdown = dropdown
+
+
+ def GetToolDropDown(self, tool_id):
+ """
+ Returns whether the toolbar item identified by `tool_id` has an associated drop down window menu or not.
+
+ :param integer `tool_id`: the :class:`AuiToolBarItem` identifier.
+ """
+
+ item = self.FindTool(tool_id)
+ if not item:
+ return
+
+ return item.dropdown
+
+
+ def SetToolSticky(self, tool_id, sticky):
+ """
+ Sets the toolbar item as sticky or non-sticky.
+
+ :param integer `tool_id`: the :class:`AuiToolBarItem` identifier;
+ :param bool `sticky`: whether the tool should be sticky or not.
+ """
+
+ # ignore separators
+ if tool_id == -1:
+ return
+
+ item = self.FindTool(tool_id)
+ if not item:
+ return
+
+ if item.sticky == sticky:
+ return
+
+ item.sticky = sticky
+
+ self.Refresh(False)
+ self.Update()
+
+
+ def GetToolSticky(self, tool_id):
+ """
+ Returns whether the toolbar item identified by `tool_id` has a sticky behaviour or not.
+
+ :param integer `tool_id`: the :class:`AuiToolBarItem` identifier.
+ """
+
+ item = self.FindTool(tool_id)
+ if not item:
+ return
+
+ return item.sticky
+
+
+ def SetToolBorderPadding(self, padding):
+ """
+ Sets the padding between the tool border and the label.
+
+ :param integer `padding`: the padding in pixels.
+ """
+
+ self._tool_border_padding = padding
+
+
+ def GetToolBorderPadding(self):
+ """ Returns the padding between the tool border and the label, in pixels. """
+
+ return self._tool_border_padding
+
+
+ def SetToolTextOrientation(self, orientation):
+ """
+ Sets the label orientation for the toolbar items.
+
+ :param integer `orientation`: the :class:`AuiToolBarItem` label orientation.
+ """
+
+ self._tool_text_orientation = orientation
+
+ if self._art:
+ self._art.SetTextOrientation(orientation)
+
+
+ def GetToolTextOrientation(self):
+ """ Returns the label orientation for the toolbar items. """
+
+ return self._tool_text_orientation
+
+
+ def SetToolOrientation(self, orientation):
+ """
+ Sets the tool orientation for the toolbar items.
+
+ :param integer `orientation`: the :class:`AuiToolBarItem` orientation.
+ """
+
+ self._tool_orientation = orientation
+ if self._art:
+ self._art.SetOrientation(orientation)
+
+
+ def GetToolOrientation(self):
+ """ Returns the orientation for the toolbar items. """
+
+ return self._tool_orientation
+
+
+ def SetToolPacking(self, packing):
+ """
+ Sets the value used for spacing tools. The default value is 1 pixel.
+
+ :param integer `packing`: the value for packing.
+ """
+
+ self._tool_packing = packing
+
+
+ def GetToolPacking(self):
+ """ Returns the value used for spacing tools. The default value is 1 pixel. """
+
+ return self._tool_packing
+
+
+ def SetOrientation(self, orientation):
+ """
+ Sets the toolbar orientation.
+
+ :param integer `orientation`: either ``wx.VERTICAL`` or ``wx.HORIZONTAL``.
+
+ :note: This can be temporarily overridden by :class:`~lib.agw.aui.framemanager.AuiManager` when floating and
+ docking a :class:`AuiToolBar`.
+ """
+
+ pass
+
+
+ def SetMargins(self, left=-1, right=-1, top=-1, bottom=-1):
+ """
+ Set the values to be used as margins for the toolbar.
+
+ :param integer `left`: the left toolbar margin;
+ :param integer `right`: the right toolbar margin;
+ :param integer `top`: the top toolbar margin;
+ :param integer `bottom`: the bottom toolbar margin.
+ """
+
+ if left != -1:
+ self._left_padding = left
+ if right != -1:
+ self._right_padding = right
+ if top != -1:
+ self._top_padding = top
+ if bottom != -1:
+ self._bottom_padding = bottom
+
+
+ def SetMarginsSize(self, size):
+ """
+ Set the values to be used as margins for the toolbar.
+
+ :param Size `size`: the margin size (an instance of :class:`Size`).
+ """
+
+ self.SetMargins(size.x, size.x, size.y, size.y)
+
+
+ def SetMarginsXY(self, x, y):
+ """
+ Set the values to be used as margins for the toolbar.
+
+ :param integer `x`: left margin, right margin and inter-tool separation value;
+ :param integer `y`: top margin, bottom margin and inter-tool separation value.
+ """
+
+ self.SetMargins(x, x, y, y)
+
+
+ def GetGripperVisible(self):
+ """ Returns whether the toolbar gripper is visible or not. """
+
+ return self._gripper_visible
+
+
+ def SetGripperVisible(self, visible):
+ """
+ Sets whether the toolbar gripper is visible or not.
+
+ :param bool `visible`: ``True`` for a visible gripper, ``False`` otherwise.
+ """
+
+ self._gripper_visible = visible
+ if visible:
+ self._agwStyle |= AUI_TB_GRIPPER
+ else:
+ self._agwStyle &= ~AUI_TB_GRIPPER
+
+ self.Realize()
+ self.Refresh(False)
+
+
+ def GetOverflowVisible(self):
+ """ Returns whether the overflow button is visible or not. """
+
+ return self._overflow_visible
+
+
+ def SetOverflowVisible(self, visible):
+ """
+ Sets whether the overflow button is visible or not.
+
+ :param bool `visible`: ``True`` for a visible overflow button, ``False`` otherwise.
+ """
+
+ self._overflow_visible = visible
+ if visible:
+ self._agwStyle |= AUI_TB_OVERFLOW
+ else:
+ self._agwStyle &= ~AUI_TB_OVERFLOW
+
+ self.Refresh(False)
+
+
+ def SetFont(self, font):
+ """
+ Sets the :class:`AuiToolBar` font.
+
+ :param Font `font`: the new toolbar font.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ res = wx.PyControl.SetFont(self, font)
+
+ if self._art:
+ self._art.SetFont(font)
+
+ return res
+
+
+ def SetHoverItem(self, pitem):
+ """
+ Sets a toolbar item to be currently hovered by the mouse.
+
+ :param `pitem`: an instance of :class:`AuiToolBarItem`.
+ """
+
+ former_hover = None
+
+ for item in self._items:
+
+ if item.state & AUI_BUTTON_STATE_HOVER:
+ former_hover = item
+
+ item.state &= ~AUI_BUTTON_STATE_HOVER
+
+ if pitem:
+ pitem.state |= AUI_BUTTON_STATE_HOVER
+
+ if former_hover != pitem:
+ self.Refresh(False)
+ self.Update()
+
+
+ def SetPressedItem(self, pitem):
+ """
+ Sets a toolbar item to be currently in a "pressed" state.
+
+ :param `pitem`: an instance of :class:`AuiToolBarItem`.
+ """
+
+ former_item = None
+
+ for item in self._items:
+
+ if item.state & AUI_BUTTON_STATE_PRESSED:
+ former_item = item
+
+ item.state &= ~AUI_BUTTON_STATE_PRESSED
+
+ if pitem:
+ pitem.state &= ~AUI_BUTTON_STATE_HOVER
+ pitem.state |= AUI_BUTTON_STATE_PRESSED
+
+ if former_item != pitem:
+ self.Refresh(False)
+ self.Update()
+
+
+ def RefreshOverflowState(self):
+ """ Refreshes the overflow button. """
+
+ if not self._overflow_sizer_item:
+ self._overflow_state = 0
+ return
+
+ overflow_state = 0
+ overflow_rect = self.GetOverflowRect()
+
+ # find out the mouse's current position
+ pt = wx.GetMousePosition()
+ pt = self.ScreenToClient(pt)
+
+ # find out if the mouse cursor is inside the dropdown rectangle
+ if overflow_rect.Contains((pt.x, pt.y)):
+
+ if _VERSION_STRING < "2.9":
+ leftDown = wx.GetMouseState().LeftDown()
+ else:
+ leftDown = wx.GetMouseState().LeftIsDown()
+
+ if leftDown:
+ overflow_state = AUI_BUTTON_STATE_PRESSED
+ else:
+ overflow_state = AUI_BUTTON_STATE_HOVER
+
+ if overflow_state != self._overflow_state:
+ self._overflow_state = overflow_state
+ self.Refresh(False)
+ self.Update()
+
+ self._overflow_state = overflow_state
+
+
+ def ToggleTool(self, tool_id, state):
+ """
+ Toggles a tool on or off. This does not cause any event to get emitted.
+
+ :param integer `tool_id`: tool in question.
+ :param bool `state`: if ``True``, toggles the tool on, otherwise toggles it off.
+
+ :note: This only applies to a tool that has been specified as a toggle tool.
+ """
+
+ tool = self.FindTool(tool_id)
+
+ if tool:
+ if tool.kind not in [ITEM_CHECK, ITEM_RADIO]:
+ return
+
+ if tool.kind == ITEM_RADIO:
+ idx = self.GetToolIndex(tool_id)
+ if idx >= 0 and idx < len(self._items):
+ for i in xrange(idx, len(self._items)):
+ tool = self.FindToolByIndex(i)
+ if tool.kind != ITEM_RADIO:
+ break
+ tool.state &= ~AUI_BUTTON_STATE_CHECKED
+
+ for i in xrange(idx, -1, -1):
+ tool = self.FindToolByIndex(i)
+ if tool.kind != ITEM_RADIO:
+ break
+ tool.state &= ~AUI_BUTTON_STATE_CHECKED
+
+ tool = self.FindTool(tool_id)
+ tool.state |= AUI_BUTTON_STATE_CHECKED
+ else:
+ if state:
+ tool.state |= AUI_BUTTON_STATE_CHECKED
+ else:
+ tool.state &= ~AUI_BUTTON_STATE_CHECKED
+
+
+ def GetToolToggled(self, tool_id):
+ """
+ Returns whether a tool is toggled or not.
+
+ :param integer `tool_id`: the toolbar item identifier.
+
+ :note: This only applies to a tool that has been specified as a toggle tool.
+ """
+
+ tool = self.FindTool(tool_id)
+
+ if tool:
+ if tool.kind not in [ITEM_CHECK, ITEM_RADIO]:
+ return False
+
+ return (tool.state & AUI_BUTTON_STATE_CHECKED and [True] or [False])[0]
+
+ return False
+
+
+ def EnableTool(self, tool_id, state):
+ """
+ Enables or disables the tool.
+
+ :param integer `tool_id`: identifier for the tool to enable or disable.
+ :param bool `state`: if ``True``, enables the tool, otherwise disables it.
+ """
+
+ tool = self.FindTool(tool_id)
+
+ if tool:
+
+ if state:
+ tool.state &= ~AUI_BUTTON_STATE_DISABLED
+ else:
+ tool.state |= AUI_BUTTON_STATE_DISABLED
+
+
+ def GetToolEnabled(self, tool_id):
+ """
+ Returns whether the tool identified by `tool_id` is enabled or not.
+
+ :param integer `tool_id`: the tool identifier.
+ """
+
+ tool = self.FindTool(tool_id)
+
+ if tool:
+ return (tool.state & AUI_BUTTON_STATE_DISABLED and [False] or [True])[0]
+
+ return False
+
+
+ def GetToolLabel(self, tool_id):
+ """
+ Returns the tool label for the tool identified by `tool_id`.
+
+ :param integer `tool_id`: the tool identifier.
+ """
+
+ tool = self.FindTool(tool_id)
+ if not tool:
+ return ""
+
+ return tool.label
+
+
+ def SetToolLabel(self, tool_id, label):
+ """
+ Sets the tool label for the tool identified by `tool_id`.
+
+ :param integer `tool_id`: the tool identifier;
+ :param string `label`: the new toolbar item label.
+ """
+
+ tool = self.FindTool(tool_id)
+ if tool:
+ tool.label = label
+
+
+ def GetToolBitmap(self, tool_id):
+ """
+ Returns the tool bitmap for the tool identified by `tool_id`.
+
+ :param integer `tool_id`: the tool identifier.
+ """
+
+ tool = self.FindTool(tool_id)
+ if not tool:
+ return wx.NullBitmap
+
+ return tool.bitmap
+
+
+ def SetToolBitmap(self, tool_id, bitmap):
+ """
+ Sets the tool bitmap for the tool identified by `tool_id`.
+
+ :param integer `tool_id`: the tool identifier;
+ :param Bitmap `bitmap`: the new bitmap for the toolbar item.
+ """
+
+ tool = self.FindTool(tool_id)
+ if tool:
+ tool.bitmap = bitmap
+
+
+ def SetToolNormalBitmap(self, tool_id, bitmap):
+ """
+ Sets the tool bitmap for the tool identified by `tool_id`.
+
+ :param integer `tool_id`: the tool identifier;
+ :param Bitmap `bitmap`: the new bitmap for the toolbar item.
+ """
+
+ self.SetToolBitmap(tool_id, bitmap)
+
+
+ def SetToolDisabledBitmap(self, tool_id, bitmap):
+ """
+ Sets the tool disabled bitmap for the tool identified by `tool_id`.
+
+ :param integer `tool_id`: the tool identifier;
+ :param Bitmap `bitmap`: the new disabled bitmap for the toolbar item.
+ """
+
+ tool = self.FindTool(tool_id)
+ if tool:
+ tool.disabled_bitmap = bitmap
+
+
+ def GetToolShortHelp(self, tool_id):
+ """
+ Returns the short help for the given tool.
+
+ :param integer `tool_id`: the tool identifier.
+ """
+
+ tool = self.FindTool(tool_id)
+ if not tool:
+ return ""
+
+ return tool.short_help
+
+
+ def SetToolShortHelp(self, tool_id, help_string):
+ """
+ Sets the short help for the given tool.
+
+ :param integer `tool_id`: the tool identifier;
+ :param string `help_string`: the string for the short help.
+ """
+
+ tool = self.FindTool(tool_id)
+ if tool:
+ tool.short_help = help_string
+
+
+ def GetToolLongHelp(self, tool_id):
+ """
+ Returns the long help for the given tool.
+
+ :param integer `tool_id`: the tool identifier.
+ """
+
+ tool = self.FindTool(tool_id)
+ if not tool:
+ return ""
+
+ return tool.long_help
+
+
+ def SetToolAlignment(self, alignment=wx.EXPAND):
+ """
+ This sets the alignment for all of the tools within the toolbar
+ (only has an effect when the toolbar is expanded).
+
+ :param integer `alignment`: :class:`Sizer` alignment value
+ (``wx.ALIGN_CENTER_HORIZONTAL`` or ``wx.ALIGN_CENTER_VERTICAL``).
+ """
+
+ self._tool_alignment = alignment
+
+
+
+ def SetToolLongHelp(self, tool_id, help_string):
+ """
+ Sets the long help for the given tool.
+
+ :param integer `tool_id`: the tool identifier;
+ :param string `help_string`: the string for the long help.
+ """
+
+ tool = self.FindTool(tool_id)
+ if tool:
+ tool.long_help = help_string
+
+
+ def SetCustomOverflowItems(self, prepend, append):
+ """
+ Sets the two lists `prepend` and `append` as custom overflow items.
+
+ :param list `prepend`: a list of :class:`AuiToolBarItem` to be prepended;
+ :param list `append`: a list of :class:`AuiToolBarItem` to be appended.
+ """
+
+ self._custom_overflow_prepend = prepend
+ self._custom_overflow_append = append
+
+
+ def GetToolCount(self):
+ """ Returns the number of tools in the :class:`AuiToolBar`. """
+
+ return len(self._items)
+
+
+ def GetToolIndex(self, tool_id):
+ """
+ Returns the position of the tool in the toolbar given its identifier.
+
+ :param integer `tool_id`: the toolbar item identifier.
+ """
+
+ # this will prevent us from returning the index of the
+ # first separator in the toolbar since its id is equal to -1
+ if tool_id == -1:
+ return wx.NOT_FOUND
+
+ for i, item in enumerate(self._items):
+ if item.id == tool_id:
+ return i
+
+ return wx.NOT_FOUND
+
+
+ def GetToolPos(self, tool_id):
+ """
+ Returns the position of the tool in the toolbar given its identifier.
+
+ :param integer `tool_id`: the toolbar item identifier.
+ """
+
+ return self.GetToolIndex(tool_id)
+
+
+ def GetToolFitsByIndex(self, tool_id):
+ """
+ Returns whether the tool identified by `tool_id` fits into the toolbar or not.
+
+ :param integer `tool_id`: the toolbar item identifier.
+ """
+
+ if tool_id < 0 or tool_id >= len(self._items):
+ return False
+
+ if not self._items[tool_id].sizer_item:
+ return False
+
+ cli_w, cli_h = self.GetClientSize()
+ rect = self._items[tool_id].sizer_item.GetRect()
+
+ if self._agwStyle & AUI_TB_VERTICAL:
+ # take the dropdown size into account
+ if self._overflow_visible:
+ cli_h -= self._overflow_sizer_item.GetSize().y
+
+ if rect.y+rect.height < cli_h:
+ return True
+
+ else:
+
+ # take the dropdown size into account
+ if self._overflow_visible:
+ cli_w -= self._overflow_sizer_item.GetSize().x
+
+ if rect.x+rect.width < cli_w:
+ return True
+
+ return False
+
+
+ def GetToolFits(self, tool_id):
+ """
+ Returns whether the tool identified by `tool_id` fits into the toolbar or not.
+
+ :param integer `tool_id`: the toolbar item identifier.
+ """
+
+ return self.GetToolFitsByIndex(self.GetToolIndex(tool_id))
+
+
+ def GetToolRect(self, tool_id):
+ """
+ Returns the toolbar item rectangle
+
+ :param integer `tool_id`: the toolbar item identifier.
+ """
+
+ tool = self.FindTool(tool_id)
+ if tool and tool.sizer_item:
+ return tool.sizer_item.GetRect()
+
+ return wx.Rect()
+
+
+ def GetToolBarFits(self):
+ """ Returns whether the :class:`AuiToolBar` size fits in a specified size. """
+
+ if len(self._items) == 0:
+ # empty toolbar always 'fits'
+ return True
+
+ # entire toolbar content fits if the last tool fits
+ return self.GetToolFitsByIndex(len(self._items) - 1)
+
+
+ def Realize(self):
+ """ Realizes the toolbar. This function should be called after you have added tools. """
+
+ dc = wx.ClientDC(self)
+
+ if not dc.IsOk():
+ return False
+
+ horizontal = True
+ if self._agwStyle & AUI_TB_VERTICAL:
+ horizontal = False
+
+ # create the new sizer to add toolbar elements to
+ sizer = wx.BoxSizer((horizontal and [wx.HORIZONTAL] or [wx.VERTICAL])[0])
+
+ # add gripper area
+ separator_size = self._art.GetElementSize(AUI_TBART_SEPARATOR_SIZE)
+ gripper_size = self._art.GetElementSize(AUI_TBART_GRIPPER_SIZE)
+
+ if gripper_size > 0 and self._gripper_visible:
+ if horizontal:
+ self._gripper_sizer_item = sizer.Add((gripper_size, 1), 0, wx.EXPAND)
+ else:
+ self._gripper_sizer_item = sizer.Add((1, gripper_size), 0, wx.EXPAND)
+ else:
+ self._gripper_sizer_item = None
+
+ # add "left" padding
+ if self._left_padding > 0:
+ if horizontal:
+ sizer.Add((self._left_padding, 1))
+ else:
+ sizer.Add((1, self._left_padding))
+
+ count = len(self._items)
+ for i, item in enumerate(self._items):
+
+ sizer_item = None
+ kind = item.kind
+
+ if kind == ITEM_LABEL:
+
+ size = self._art.GetLabelSize(dc, self, item)
+ sizer_item = sizer.Add((size.x + (self._tool_border_padding*2),
+ size.y + (self._tool_border_padding*2)),
+ item.proportion,
+ item.alignment)
+ if i+1 < count:
+ sizer.AddSpacer(self._tool_packing)
+
+
+ elif kind in [ITEM_CHECK, ITEM_NORMAL, ITEM_RADIO]:
+
+ size = self._art.GetToolSize(dc, self, item)
+ sizer_item = sizer.Add((size.x + (self._tool_border_padding*2),
+ size.y + (self._tool_border_padding*2)),
+ 0,
+ item.alignment)
+ # add tool packing
+ if i+1 < count:
+ sizer.AddSpacer(self._tool_packing)
+
+ elif kind == ITEM_SEPARATOR:
+
+ if horizontal:
+ sizer_item = sizer.Add((separator_size, 1), 0, wx.EXPAND)
+ else:
+ sizer_item = sizer.Add((1, separator_size), 0, wx.EXPAND)
+
+ # add tool packing
+ if i+1 < count:
+ sizer.AddSpacer(self._tool_packing)
+
+ elif kind == ITEM_SPACER:
+
+ if item.proportion > 0:
+ sizer_item = sizer.AddStretchSpacer(item.proportion)
+ else:
+ sizer_item = sizer.Add((item.spacer_pixels, 1))
+
+ elif kind == ITEM_CONTROL:
+
+ vert_sizer = wx.BoxSizer(wx.VERTICAL)
+ vert_sizer.AddStretchSpacer(1)
+ ctrl_sizer_item = vert_sizer.Add(item.window, 0, wx.EXPAND)
+ vert_sizer.AddStretchSpacer(1)
+
+ if self._agwStyle & AUI_TB_TEXT and \
+ self._tool_text_orientation == AUI_TBTOOL_TEXT_BOTTOM and \
+ item.GetLabel() != "":
+
+ s = self.GetLabelSize(item.GetLabel())
+ vert_sizer.Add((1, s.y))
+
+ sizer_item = sizer.Add(vert_sizer, item.proportion, wx.EXPAND)
+ min_size = item.min_size
+
+ # proportional items will disappear from the toolbar if
+ # their min width is not set to something really small
+ if item.proportion != 0:
+ min_size.x = 1
+
+ if min_size.IsFullySpecified():
+ sizer.SetItemMinSize(vert_sizer, min_size)
+ vert_sizer.SetItemMinSize(item.window, min_size)
+
+ # add tool packing
+ if i+1 < count:
+ sizer.AddSpacer(self._tool_packing)
+
+ item.sizer_item = sizer_item
+
+
+ # add "right" padding
+ if self._right_padding > 0:
+ if horizontal:
+ sizer.Add((self._right_padding, 1))
+ else:
+ sizer.Add((1, self._right_padding))
+
+ # add drop down area
+ self._overflow_sizer_item = None
+
+ if self._agwStyle & AUI_TB_OVERFLOW:
+
+ overflow_size = self._art.GetElementSize(AUI_TBART_OVERFLOW_SIZE)
+ if overflow_size > 0 and self._overflow_visible:
+
+ if horizontal:
+ self._overflow_sizer_item = sizer.Add((overflow_size, 1), 0, wx.EXPAND)
+ else:
+ self._overflow_sizer_item = sizer.Add((1, overflow_size), 0, wx.EXPAND)
+
+ else:
+
+ self._overflow_sizer_item = None
+
+ # the outside sizer helps us apply the "top" and "bottom" padding
+ outside_sizer = wx.BoxSizer((horizontal and [wx.VERTICAL] or [wx.HORIZONTAL])[0])
+
+ # add "top" padding
+ if self._top_padding > 0:
+
+ if horizontal:
+ outside_sizer.Add((1, self._top_padding))
+ else:
+ outside_sizer.Add((self._top_padding, 1))
+
+ # add the sizer that contains all of the toolbar elements
+ outside_sizer.Add(sizer, 1, self._tool_alignment)
+
+ # add "bottom" padding
+ if self._bottom_padding > 0:
+
+ if horizontal:
+ outside_sizer.Add((1, self._bottom_padding))
+ else:
+ outside_sizer.Add((self._bottom_padding, 1))
+
+ del self._sizer # remove old sizer
+ self._sizer = outside_sizer
+ self.SetSizer(outside_sizer)
+
+ # calculate the rock-bottom minimum size
+ for item in self._items:
+
+ if item.sizer_item and item.proportion > 0 and item.min_size.IsFullySpecified():
+ item.sizer_item.SetMinSize((0, 0))
+
+ self._absolute_min_size = self._sizer.GetMinSize()
+
+ # reset the min sizes to what they were
+ for item in self._items:
+
+ if item.sizer_item and item.proportion > 0 and item.min_size.IsFullySpecified():
+ item.sizer_item.SetMinSize(item.min_size)
+
+ # set control size
+ size = self._sizer.GetMinSize()
+ self.SetMinSize(size)
+ self._minWidth = size.x
+ self._minHeight = size.y
+
+ if self._agwStyle & AUI_TB_NO_AUTORESIZE == 0:
+
+ cur_size = self.GetClientSize()
+ new_size = self.GetMinSize()
+
+ if new_size != cur_size:
+
+ self.SetClientSize(new_size)
+
+ else:
+
+ self._sizer.SetDimension(0, 0, cur_size.x, cur_size.y)
+
+ else:
+
+ cur_size = self.GetClientSize()
+ self._sizer.SetDimension(0, 0, cur_size.x, cur_size.y)
+
+ self.Refresh(False)
+ return True
+
+
+ def GetOverflowState(self):
+ """ Returns the state of the overflow button. """
+
+ return self._overflow_state
+
+
+ def GetOverflowRect(self):
+ """ Returns the rectangle of the overflow button. """
+
+ cli_rect = wx.RectPS(wx.Point(0, 0), self.GetClientSize())
+ overflow_rect = wx.Rect(*self._overflow_sizer_item.GetRect())
+ overflow_size = self._art.GetElementSize(AUI_TBART_OVERFLOW_SIZE)
+
+ if self._agwStyle & AUI_TB_VERTICAL:
+
+ overflow_rect.y = cli_rect.height - overflow_size
+ overflow_rect.x = 0
+ overflow_rect.width = cli_rect.width
+ overflow_rect.height = overflow_size
+
+ else:
+
+ overflow_rect.x = cli_rect.width - overflow_size
+ overflow_rect.y = 0
+ overflow_rect.width = overflow_size
+ overflow_rect.height = cli_rect.height
+
+ return overflow_rect
+
+
+ def GetLabelSize(self, label):
+ """
+ Returns the standard size of a toolbar item.
+
+ :param string `label`: a test label.
+ """
+
+ dc = wx.ClientDC(self)
+ dc.SetFont(self._font)
+
+ return GetLabelSize(dc, label, self._tool_orientation != AUI_TBTOOL_HORIZONTAL)
+
+
+ def GetAuiManager(self):
+ """ Returns the :class:`~lib.agw.aui.framemanager.AuiManager` which manages the toolbar. """
+
+ try:
+ return self._auiManager
+ except AttributeError:
+ return False
+
+
+ def SetAuiManager(self, auiManager):
+ """ Sets the :class:`~lib.agw.aui.framemanager.AuiManager` which manages the toolbar. """
+
+ self._auiManager = auiManager
+
+
+ def DoIdleUpdate(self):
+ """ Updates the toolbar during idle times. """
+
+ handler = self.GetEventHandler()
+ if not handler:
+ return
+
+ need_refresh = False
+
+ for item in self._items:
+
+ if item.id == -1:
+ continue
+
+ evt = wx.UpdateUIEvent(item.id)
+ evt.SetEventObject(self)
+
+ if handler.ProcessEvent(evt):
+
+ if evt.GetSetEnabled():
+
+ if item.window:
+ is_enabled = item.window.IsEnabled()
+ else:
+ is_enabled = (item.state & AUI_BUTTON_STATE_DISABLED and [False] or [True])[0]
+
+ new_enabled = evt.GetEnabled()
+ if new_enabled != is_enabled:
+
+ if item.window:
+ item.window.Enable(new_enabled)
+ else:
+ if new_enabled:
+ item.state &= ~AUI_BUTTON_STATE_DISABLED
+ else:
+ item.state |= AUI_BUTTON_STATE_DISABLED
+
+ need_refresh = True
+
+ if evt.GetSetChecked():
+
+ # make sure we aren't checking an item that can't be
+ if item.kind != ITEM_CHECK and item.kind != ITEM_RADIO:
+ continue
+
+ is_checked = (item.state & AUI_BUTTON_STATE_CHECKED and [True] or [False])[0]
+ new_checked = evt.GetChecked()
+
+ if new_checked != is_checked:
+
+ if new_checked:
+ item.state |= AUI_BUTTON_STATE_CHECKED
+ else:
+ item.state &= ~AUI_BUTTON_STATE_CHECKED
+
+ need_refresh = True
+
+ if need_refresh:
+ self.Refresh(False)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ x, y = self.GetClientSize()
+ realize = False
+
+ if x > y:
+ self.SetOrientation(wx.HORIZONTAL)
+ else:
+ self.SetOrientation(wx.VERTICAL)
+
+ if (x >= y and self._absolute_min_size.x > x) or (y > x and self._absolute_min_size.y > y):
+
+ # hide all flexible items
+ for item in self._items:
+ if item.sizer_item and item.proportion > 0 and item.sizer_item.IsShown():
+ item.sizer_item.Show(False)
+ item.sizer_item.SetProportion(0)
+
+ if self._originalStyle & AUI_TB_OVERFLOW:
+ if not self.GetOverflowVisible():
+ self.SetOverflowVisible(True)
+ realize = True
+
+ else:
+
+ if self._originalStyle & AUI_TB_OVERFLOW and not self._custom_overflow_append and \
+ not self._custom_overflow_prepend:
+ if self.GetOverflowVisible():
+ self.SetOverflowVisible(False)
+ realize = True
+
+ # show all flexible items
+ for item in self._items:
+ if item.sizer_item and item.proportion > 0 and not item.sizer_item.IsShown():
+ item.sizer_item.Show(True)
+ item.sizer_item.SetProportion(item.proportion)
+
+ self._sizer.SetDimension(0, 0, x, y)
+
+ if realize:
+ self.Realize()
+ else:
+ self.Refresh(False)
+
+ self.Update()
+
+
+ def DoSetSize(self, x, y, width, height, sizeFlags=wx.SIZE_AUTO):
+ """
+ Sets the position and size of the window in pixels. The `sizeFlags`
+ parameter indicates the interpretation of the other params if they are
+ equal to -1.
+
+ :param integer `x`: the window `x` position;
+ :param integer `y`: the window `y` position;
+ :param integer `width`: the window width;
+ :param integer `height`: the window height;
+ :param integer `sizeFlags`: may have one of this bit set:
+
+ =================================== ======================================
+ Size Flags Description
+ =================================== ======================================
+ ``wx.SIZE_AUTO`` A -1 indicates that a class-specific default should be used.
+ ``wx.SIZE_AUTO_WIDTH`` A -1 indicates that a class-specific default should be used for the width.
+ ``wx.SIZE_AUTO_HEIGHT`` A -1 indicates that a class-specific default should be used for the height.
+ ``wx.SIZE_USE_EXISTING`` Existing dimensions should be used if -1 values are supplied.
+ ``wx.SIZE_ALLOW_MINUS_ONE`` Allow dimensions of -1 and less to be interpreted as real dimensions, not default values.
+ ``wx.SIZE_FORCE`` Normally, if the position and the size of the window are already the same as the
+ parameters of this function, nothing is done. but with this flag a window resize may
+ be forced even in this case (supported in wx 2.6.2 and later and only implemented
+ for MSW and ignored elsewhere currently)
+ =================================== ======================================
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ parent_size = self.GetParent().GetClientSize()
+ if x + width > parent_size.x:
+ width = max(0, parent_size.x - x)
+ if y + height > parent_size.y:
+ height = max(0, parent_size.y - y)
+
+ wx.PyControl.DoSetSize(self, x, y, width, height, sizeFlags)
+
+
+ def OnIdle(self, event):
+ """
+ Handles the ``wx.EVT_IDLE`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`IdleEvent` event to be processed.
+ """
+
+ self.DoIdleUpdate()
+ event.Skip()
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same
+ size as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._absolute_min_size
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+ cli_rect = wx.RectPS(wx.Point(0, 0), self.GetClientSize())
+
+ horizontal = True
+ if self._agwStyle & AUI_TB_VERTICAL:
+ horizontal = False
+
+ if self._agwStyle & AUI_TB_PLAIN_BACKGROUND:
+ self._art.DrawPlainBackground(dc, self, cli_rect)
+ else:
+ self._art.DrawBackground(dc, self, cli_rect, horizontal)
+
+ gripper_size = self._art.GetElementSize(AUI_TBART_GRIPPER_SIZE)
+ dropdown_size = self._art.GetElementSize(AUI_TBART_OVERFLOW_SIZE)
+
+ # paint the gripper
+ if self._agwStyle & AUI_TB_GRIPPER and gripper_size > 0 and self._gripper_sizer_item:
+ gripper_rect = wx.Rect(*self._gripper_sizer_item.GetRect())
+ if horizontal:
+ gripper_rect.width = gripper_size
+ else:
+ gripper_rect.height = gripper_size
+
+ self._art.DrawGripper(dc, self, gripper_rect)
+
+ # calculated how far we can draw items
+ if horizontal:
+ last_extent = cli_rect.width
+ else:
+ last_extent = cli_rect.height
+
+ if self._overflow_visible:
+ last_extent -= dropdown_size
+
+ # paint each individual tool
+ for item in self._items:
+
+ if not item.sizer_item:
+ continue
+
+ item_rect = wx.Rect(*item.sizer_item.GetRect())
+
+ if (horizontal and item_rect.x + item_rect.width >= last_extent) or \
+ (not horizontal and item_rect.y + item_rect.height >= last_extent):
+
+ break
+
+ if item.kind == ITEM_SEPARATOR:
+ # draw a separator
+ self._art.DrawSeparator(dc, self, item_rect)
+
+ elif item.kind == ITEM_LABEL:
+ # draw a text label only
+ self._art.DrawLabel(dc, self, item, item_rect)
+
+ elif item.kind == ITEM_NORMAL:
+ # draw a regular button or dropdown button
+ if not item.dropdown:
+ self._art.DrawButton(dc, self, item, item_rect)
+ else:
+ self._art.DrawDropDownButton(dc, self, item, item_rect)
+
+ elif item.kind == ITEM_CHECK:
+ # draw a regular toggle button or a dropdown one
+ if not item.dropdown:
+ self._art.DrawButton(dc, self, item, item_rect)
+ else:
+ self._art.DrawDropDownButton(dc, self, item, item_rect)
+
+ elif item.kind == ITEM_RADIO:
+ # draw a toggle button
+ self._art.DrawButton(dc, self, item, item_rect)
+
+ elif item.kind == ITEM_CONTROL:
+ # draw the control's label
+ self._art.DrawControlLabel(dc, self, item, item_rect)
+
+ # fire a signal to see if the item wants to be custom-rendered
+ self.OnCustomRender(dc, item, item_rect)
+
+ # paint the overflow button
+ if dropdown_size > 0 and self._overflow_sizer_item:
+ dropdown_rect = self.GetOverflowRect()
+ self._art.DrawOverflowButton(dc, self, dropdown_rect, self._overflow_state)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This is intentionally empty, to reduce flicker.
+ """
+
+ pass
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ cli_rect = wx.RectPS(wx.Point(0, 0), self.GetClientSize())
+ self.StopPreviewTimer()
+
+ if self._gripper_sizer_item:
+
+ gripper_rect = wx.Rect(*self._gripper_sizer_item.GetRect())
+ if gripper_rect.Contains(event.GetPosition()):
+
+ # find aui manager
+ manager = self.GetAuiManager()
+ if not manager:
+ return
+
+ x_drag_offset = event.GetX() - gripper_rect.GetX()
+ y_drag_offset = event.GetY() - gripper_rect.GetY()
+
+ clientPt = wx.Point(*event.GetPosition())
+ screenPt = self.ClientToScreen(clientPt)
+ managedWindow = manager.GetManagedWindow()
+ managerClientPt = managedWindow.ScreenToClient(screenPt)
+
+ # gripper was clicked
+ manager.OnGripperClicked(self, managerClientPt, wx.Point(x_drag_offset, y_drag_offset))
+ return
+
+ if self._overflow_sizer_item:
+ overflow_rect = self.GetOverflowRect()
+
+ if self._art and self._overflow_visible and overflow_rect.Contains(event.GetPosition()):
+
+ e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, -1)
+ e.SetEventObject(self)
+ e.SetToolId(-1)
+ e.SetClickPoint(event.GetPosition())
+ processed = self.ProcessEvent(e)
+
+ if processed:
+ self.DoIdleUpdate()
+ else:
+ overflow_items = []
+
+ # add custom overflow prepend items, if any
+ count = len(self._custom_overflow_prepend)
+ for i in xrange(count):
+ overflow_items.append(self._custom_overflow_prepend[i])
+
+ # only show items that don't fit in the dropdown
+ count = len(self._items)
+ for i in xrange(count):
+
+ if not self.GetToolFitsByIndex(i):
+ overflow_items.append(self._items[i])
+
+ # add custom overflow append items, if any
+ count = len(self._custom_overflow_append)
+ for i in xrange(count):
+ overflow_items.append(self._custom_overflow_append[i])
+
+ res = self._art.ShowDropDown(self, overflow_items)
+ self._overflow_state = 0
+ self.Refresh(False)
+ if res != -1:
+ e = wx.CommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, res)
+ e.SetEventObject(self)
+ if not self.GetParent().ProcessEvent(e):
+ tool = self.FindTool(res)
+ if tool:
+ state = (tool.state & AUI_BUTTON_STATE_CHECKED and [True] or [False])[0]
+ self.ToggleTool(res, not state)
+
+ return
+
+ self._dragging = False
+ self._action_pos = wx.Point(*event.GetPosition())
+ self._action_item = self.FindToolForPosition(*event.GetPosition())
+
+ if self._action_item:
+
+ if self._action_item.state & AUI_BUTTON_STATE_DISABLED:
+
+ self._action_pos = wx.Point(-1, -1)
+ self._action_item = None
+ return
+
+ self.SetPressedItem(self._action_item)
+
+ # fire the tool dropdown event
+ e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, self._action_item.id)
+ e.SetEventObject(self)
+ e.SetToolId(self._action_item.id)
+ e.SetDropDownClicked(False)
+
+ mouse_x, mouse_y = event.GetX(), event.GetY()
+ rect = wx.Rect(*self._action_item.sizer_item.GetRect())
+
+ if self._action_item.dropdown:
+ if (self._action_item.orientation == AUI_TBTOOL_HORIZONTAL and \
+ mouse_x >= (rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1) and \
+ mouse_x < (rect.x+rect.width)) or \
+ (self._action_item.orientation != AUI_TBTOOL_HORIZONTAL and \
+ mouse_y >= (rect.y+rect.height-BUTTON_DROPDOWN_WIDTH-1) and \
+ mouse_y < (rect.y+rect.height)):
+
+ e.SetDropDownClicked(True)
+
+ e.SetClickPoint(event.GetPosition())
+ e.SetItemRect(rect)
+ self.ProcessEvent(e)
+ self.DoIdleUpdate()
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.SetPressedItem(None)
+
+ hit_item = self.FindToolForPosition(*event.GetPosition())
+
+ if hit_item and not hit_item.state & AUI_BUTTON_STATE_DISABLED:
+ self.SetHoverItem(hit_item)
+
+ if self._dragging:
+ # reset drag and drop member variables
+ self._dragging = False
+ self._action_pos = wx.Point(-1, -1)
+ self._action_item = None
+
+ else:
+
+ if self._action_item and hit_item == self._action_item:
+ self.SetToolTipString("")
+
+ if hit_item.kind in [ITEM_CHECK, ITEM_RADIO]:
+ toggle = not (self._action_item.state & AUI_BUTTON_STATE_CHECKED)
+ self.ToggleTool(self._action_item.id, toggle)
+
+ # repaint immediately
+ self.Refresh(False)
+ self.Update()
+
+ e = wx.CommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, self._action_item.id)
+ e.SetEventObject(self)
+ e.SetInt(toggle)
+ self._action_pos = wx.Point(-1, -1)
+ self._action_item = None
+
+ self.ProcessEvent(e)
+ self.DoIdleUpdate()
+
+ else:
+
+ if self._action_item.id == ID_RESTORE_FRAME:
+ # find aui manager
+ manager = self.GetAuiManager()
+
+ if not manager:
+ return
+
+ if self._action_item.target:
+ pane = manager.GetPane(self._action_item.target)
+ else:
+ pane = manager.GetPane(self)
+
+ e = framemanager.AuiManagerEvent(framemanager.wxEVT_AUI_PANE_MIN_RESTORE)
+
+ e.SetManager(manager)
+ e.SetPane(pane)
+
+ manager.ProcessEvent(e)
+ self.DoIdleUpdate()
+
+ else:
+
+ e = wx.CommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, self._action_item.id)
+ e.SetEventObject(self)
+ self.ProcessEvent(e)
+ self.DoIdleUpdate()
+
+ # reset drag and drop member variables
+ self._dragging = False
+ self._action_pos = wx.Point(-1, -1)
+ self._action_item = None
+
+
+ def OnRightDown(self, event):
+ """
+ Handles the ``wx.EVT_RIGHT_DOWN`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ cli_rect = wx.RectPS(wx.Point(0, 0), self.GetClientSize())
+
+ if self._gripper_sizer_item:
+ gripper_rect = self._gripper_sizer_item.GetRect()
+ if gripper_rect.Contains(event.GetPosition()):
+ return
+
+ if self._overflow_sizer_item:
+
+ dropdown_size = self._art.GetElementSize(AUI_TBART_OVERFLOW_SIZE)
+ if dropdown_size > 0 and event.GetX() > cli_rect.width - dropdown_size and \
+ event.GetY() >= 0 and event.GetY() < cli_rect.height and self._art:
+ return
+
+ self._action_pos = wx.Point(*event.GetPosition())
+ self._action_item = self.FindToolForPosition(*event.GetPosition())
+
+ if self._action_item:
+ if self._action_item.state & AUI_BUTTON_STATE_DISABLED:
+
+ self._action_pos = wx.Point(-1, -1)
+ self._action_item = None
+ return
+
+
+ def OnRightUp(self, event):
+ """
+ Handles the ``wx.EVT_RIGHT_UP`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ hit_item = self.FindToolForPosition(*event.GetPosition())
+
+ if self._action_item and hit_item == self._action_item:
+
+ e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, self._action_item.id)
+ e.SetEventObject(self)
+ e.SetToolId(self._action_item.id)
+ e.SetClickPoint(self._action_pos)
+ self.ProcessEvent(e)
+ self.DoIdleUpdate()
+
+ else:
+
+ # right-clicked on the invalid area of the toolbar
+ e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, -1)
+ e.SetEventObject(self)
+ e.SetToolId(-1)
+ e.SetClickPoint(self._action_pos)
+ self.ProcessEvent(e)
+ self.DoIdleUpdate()
+
+ # reset member variables
+ self._action_pos = wx.Point(-1, -1)
+ self._action_item = None
+
+
+ def OnMiddleDown(self, event):
+ """
+ Handles the ``wx.EVT_MIDDLE_DOWN`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ cli_rect = wx.RectPS(wx.Point(0, 0), self.GetClientSize())
+
+ if self._gripper_sizer_item:
+
+ gripper_rect = self._gripper_sizer_item.GetRect()
+ if gripper_rect.Contains(event.GetPosition()):
+ return
+
+ if self._overflow_sizer_item:
+
+ dropdown_size = self._art.GetElementSize(AUI_TBART_OVERFLOW_SIZE)
+ if dropdown_size > 0 and event.GetX() > cli_rect.width - dropdown_size and \
+ event.GetY() >= 0 and event.GetY() < cli_rect.height and self._art:
+ return
+
+ self._action_pos = wx.Point(*event.GetPosition())
+ self._action_item = self.FindToolForPosition(*event.GetPosition())
+
+ if self._action_item:
+ if self._action_item.state & AUI_BUTTON_STATE_DISABLED:
+
+ self._action_pos = wx.Point(-1, -1)
+ self._action_item = None
+ return
+
+
+ def OnMiddleUp(self, event):
+ """
+ Handles the ``wx.EVT_MIDDLE_UP`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ hit_item = self.FindToolForPosition(*event.GetPosition())
+
+ if self._action_item and hit_item == self._action_item:
+ if hit_item.kind == ITEM_NORMAL:
+
+ e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, self._action_item.id)
+ e.SetEventObject(self)
+ e.SetToolId(self._action_item.id)
+ e.SetClickPoint(self._action_pos)
+ self.ProcessEvent(e)
+ self.DoIdleUpdate()
+
+ # reset member variables
+ self._action_pos = wx.Point(-1, -1)
+ self._action_item = None
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # start a drag event
+ if not self._dragging and self._action_item != None and self._action_pos != wx.Point(-1, -1) and \
+ abs(event.GetX() - self._action_pos.x) + abs(event.GetY() - self._action_pos.y) > 5:
+
+ self.SetToolTipString("")
+ self._dragging = True
+
+ e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, self.GetId())
+ e.SetEventObject(self)
+ e.SetToolId(self._action_item.id)
+ self.ProcessEvent(e)
+ self.DoIdleUpdate()
+ return
+
+ hit_item = self.FindToolForPosition(*event.GetPosition())
+
+ if hit_item:
+ if not hit_item.state & AUI_BUTTON_STATE_DISABLED:
+ self.SetHoverItem(hit_item)
+ else:
+ self.SetHoverItem(None)
+
+ else:
+ # no hit item, remove any hit item
+ self.SetHoverItem(hit_item)
+
+ # figure out tooltips
+ packing_hit_item = self.FindToolForPositionWithPacking(*event.GetPosition())
+
+ if packing_hit_item:
+
+ if packing_hit_item != self._tip_item:
+ self._tip_item = packing_hit_item
+
+ if packing_hit_item.short_help != "":
+ self.StartPreviewTimer()
+ self.SetToolTipString(packing_hit_item.short_help)
+ else:
+ self.SetToolTipString("")
+ self.StopPreviewTimer()
+
+ else:
+
+ self.SetToolTipString("")
+ self._tip_item = None
+ self.StopPreviewTimer()
+
+ # if we've pressed down an item and we're hovering
+ # over it, make sure it's state is set to pressed
+ if self._action_item:
+
+ if self._action_item == hit_item:
+ self.SetPressedItem(self._action_item)
+ else:
+ self.SetPressedItem(None)
+
+ # figure out the dropdown button state (are we hovering or pressing it?)
+ self.RefreshOverflowState()
+
+
+ def OnLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.RefreshOverflowState()
+ self.SetHoverItem(None)
+ self.SetPressedItem(None)
+
+ self._tip_item = None
+ self.StopPreviewTimer()
+
+
+ def OnSetCursor(self, event):
+ """
+ Handles the ``wx.EVT_SET_CURSOR`` event for :class:`AuiToolBar`.
+
+ :param `event`: a :class:`SetCursorEvent` event to be processed.
+ """
+
+ cursor = wx.NullCursor
+
+ if self._gripper_sizer_item:
+
+ gripper_rect = self._gripper_sizer_item.GetRect()
+ if gripper_rect.Contains((event.GetX(), event.GetY())):
+ cursor = wx.StockCursor(wx.CURSOR_SIZING)
+
+ event.SetCursor(cursor)
+
+
+ def OnCustomRender(self, dc, item, rect):
+ """
+ Handles custom render for single :class:`AuiToolBar` items.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `item`: an instance of :class:`AuiToolBarItem`;
+ :param Rect `rect`: the toolbar item rect.
+
+ :note: This method must be overridden to provide custom rendering of items.
+ """
+
+ pass
+
+
+ def IsPaneMinimized(self):
+ """ Returns whether this :class:`AuiToolBar` contains a minimized pane tool. """
+
+ manager = self.GetAuiManager()
+ if not manager:
+ return False
+
+ if manager.GetAGWFlags() & AUI_MGR_PREVIEW_MINIMIZED_PANES == 0:
+ # No previews here
+ return False
+
+ self_name = manager.GetPane(self).name
+
+ if not self_name.endswith("_min"):
+ # Wrong tool name
+ return False
+
+ return self_name[0:-4]
+
+
+ def StartPreviewTimer(self):
+ """ Starts a timer in :class:`~lib.agw.aui.framemanager.AuiManager` to slide-in/slide-out the minimized pane. """
+
+ self_name = self.IsPaneMinimized()
+ if not self_name:
+ return
+
+ manager = self.GetAuiManager()
+ manager.StartPreviewTimer(self)
+
+
+ def StopPreviewTimer(self):
+ """ Stops a timer in :class:`~lib.agw.aui.framemanager.AuiManager` to slide-in/slide-out the minimized pane. """
+
+ self_name = self.IsPaneMinimized()
+ if not self_name:
+ return
+
+ manager = self.GetAuiManager()
+ manager.StopPreviewTimer()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/auibook.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/auibook.py
new file mode 100644
index 0000000..b7313ca
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/auibook.py
@@ -0,0 +1,6076 @@
+"""
+`auibook.py` contains a notebook control which implements many features common in
+applications with dockable panes. Specifically, :class:`AuiNotebook` implements functionality
+which allows the user to rearrange tab order via drag-and-drop, split the tab window
+into many different splitter configurations, and toggle through different themes to
+customize the control's look and feel.
+
+An effort has been made to try to maintain an API as similar to that of :class:`Notebook`.
+
+The default theme that is used is :class:`~lib.agw.aui.tabart.AuiDefaultTabArt`, which provides a modern, glossy
+look and feel. The theme can be changed by calling :meth:`AuiNotebook.SetArtProvider() <AuiNotebook.SetArtProvider>`.
+"""
+
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "31 March 2009"
+
+
+import wx
+import types
+import datetime
+
+from wx.lib.expando import ExpandoTextCtrl
+
+import framemanager
+import tabart as TA
+
+from aui_utilities import LightColour, MakeDisabledBitmap, TabDragImage
+from aui_utilities import TakeScreenShot, RescaleScreenShot
+
+from aui_constants import *
+
+# AuiNotebook events
+wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_BUTTON = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_END_DRAG = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_TAB_LEFT_UP = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_TAB_DCLICK = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_BG_LEFT_UP = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_DOWN = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_UP = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_DOWN = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_UP = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK = wx.NewEventType()
+
+# Define a new event for a drag cancelled
+wxEVT_COMMAND_AUINOTEBOOK_CANCEL_DRAG = wx.NewEventType()
+
+# Define events for editing a tab label
+wxEVT_COMMAND_AUINOTEBOOK_BEGIN_LABEL_EDIT = wx.NewEventType()
+wxEVT_COMMAND_AUINOTEBOOK_END_LABEL_EDIT = wx.NewEventType()
+
+# Create event binders
+EVT_AUINOTEBOOK_PAGE_CLOSE = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 1)
+""" A tab in `AuiNotebook` is being closed. Can be vetoed by calling `Veto()`. """
+EVT_AUINOTEBOOK_PAGE_CLOSED = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 1)
+""" A tab in `AuiNotebook` has been closed. """
+EVT_AUINOTEBOOK_PAGE_CHANGED = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 1)
+""" The page selection was changed. """
+EVT_AUINOTEBOOK_PAGE_CHANGING = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 1)
+""" The page selection is being changed. """
+EVT_AUINOTEBOOK_BUTTON = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 1)
+""" The user clicked on a button in the `AuiNotebook` tab area. """
+EVT_AUINOTEBOOK_BEGIN_DRAG = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 1)
+""" A drag-and-drop operation on a notebook tab has started. """
+EVT_AUINOTEBOOK_END_DRAG = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 1)
+""" A drag-and-drop operation on a notebook tab has finished. """
+EVT_AUINOTEBOOK_DRAG_MOTION = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 1)
+""" A drag-and-drop operation on a notebook tab is ongoing. """
+EVT_AUINOTEBOOK_ALLOW_DND = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 1)
+""" Fires an event asking if it is OK to drag and drop a tab. """
+EVT_AUINOTEBOOK_DRAG_DONE = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 1)
+""" A drag-and-drop operation on a notebook tab has finished. """
+EVT_AUINOTEBOOK_TAB_LEFT_UP = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_LEFT_UP, 1)
+""" The user clicked with the left mouse button on a tab. """
+EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 1)
+""" The user clicked with the middle mouse button on a tab. """
+EVT_AUINOTEBOOK_TAB_MIDDLE_UP = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 1)
+""" The user clicked with the middle mouse button on a tab. """
+EVT_AUINOTEBOOK_TAB_RIGHT_DOWN = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 1)
+""" The user clicked with the right mouse button on a tab. """
+EVT_AUINOTEBOOK_TAB_RIGHT_UP = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 1)
+""" The user clicked with the right mouse button on a tab. """
+EVT_AUINOTEBOOK_BG_LEFT_UP = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_LEFT_UP, 1)
+""" The user left-clicked in the tab area but not over a tab or a button. """
+EVT_AUINOTEBOOK_BG_MIDDLE_DOWN = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_DOWN, 1)
+""" The user middle-clicked in the tab area but not over a tab or a button. """
+EVT_AUINOTEBOOK_BG_MIDDLE_UP = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_UP, 1)
+""" The user middle-clicked in the tab area but not over a tab or a button. """
+EVT_AUINOTEBOOK_BG_RIGHT_DOWN = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_DOWN, 1)
+""" The user right-clicked in the tab area but not over a tab or a button. """
+EVT_AUINOTEBOOK_BG_RIGHT_UP = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_UP, 1)
+""" The user right-clicked in the tab area but not over a tab or a button. """
+EVT_AUINOTEBOOK_BG_DCLICK = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 1)
+""" The user left-clicked on the tab area not occupied by `AuiNotebook` tabs. """
+EVT_AUINOTEBOOK_CANCEL_DRAG = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_CANCEL_DRAG, 1)
+""" A drag and drop operation has been cancelled. """
+EVT_AUINOTEBOOK_TAB_DCLICK = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_DCLICK, 1)
+""" The user double-clicked with the left mouse button on a tab. """
+EVT_AUINOTEBOOK_BEGIN_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_LABEL_EDIT, 1)
+""" The user double-clicked with the left mouse button on a tab which text is editable. """
+EVT_AUINOTEBOOK_END_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_END_LABEL_EDIT, 1)
+""" The user finished editing a tab label. """
+
+
+# -----------------------------------------------------------------------------
+# Auxiliary class: TabTextCtrl
+# This is the temporary ExpandoTextCtrl created when you edit the text of a tab
+# -----------------------------------------------------------------------------
+
+class TabTextCtrl(ExpandoTextCtrl):
+ """ Control used for in-place edit. """
+
+ def __init__(self, owner, tab, page_index):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `owner`: the :class:`AuiNotebook` owning the tab;
+ :param `tab`: the actual :class:`AuiTabCtrl` tab;
+ :param integer `page_index`: the :class:`AuiTabContainer` page index for the tab.
+ """
+
+ self._owner = owner
+ self._tabEdited = tab
+ self._pageIndex = page_index
+ self._startValue = tab.caption
+ self._finished = False
+ self._aboutToFinish = False
+ self._currentValue = self._startValue
+
+ x, y, w, h = self._tabEdited.rect
+
+ wnd = self._tabEdited.control
+ if wnd:
+ x += wnd.GetSize()[0] + 2
+ h = 0
+
+ image_h = 0
+ image_w = 0
+
+ image = tab.bitmap
+
+ if image.IsOk():
+ image_w, image_h = image.GetWidth(), image.GetHeight()
+ image_w += 6
+
+ dc = wx.ClientDC(self._owner)
+ h = max(image_h, dc.GetMultiLineTextExtent(tab.caption)[1])
+ h = h + 2
+
+ # FIXME: what are all these hardcoded 4, 8 and 11s really?
+ x += image_w
+ w -= image_w + 4
+
+ y = (self._tabEdited.rect.height - h)/2 + 1
+
+ expandoStyle = wx.WANTS_CHARS
+ if wx.Platform in ["__WXGTK__", "__WXMAC__"]:
+ expandoStyle |= wx.SIMPLE_BORDER
+ xSize, ySize = w + 2, h
+ else:
+ expandoStyle |= wx.SUNKEN_BORDER
+ xSize, ySize = w + 2, h+2
+
+ ExpandoTextCtrl.__init__(self, self._owner, wx.ID_ANY, self._startValue,
+ wx.Point(x, y), wx.Size(xSize, ySize),
+ expandoStyle)
+
+ if wx.Platform == "__WXMAC__":
+ self.SetFont(owner.GetFont())
+ bs = self.GetBestSize()
+ self.SetSize((-1, bs.height))
+
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+
+ def AcceptChanges(self):
+ """ Accepts/refuses the changes made by the user. """
+
+ value = self.GetValue()
+ notebook = self._owner.GetParent()
+
+ if value == self._startValue:
+ # nothing changed, always accept
+ # when an item remains unchanged, the owner
+ # needs to be notified that the user decided
+ # not to change the tree item label, and that
+ # the edit has been cancelled
+ notebook.OnRenameCancelled(self._pageIndex)
+ return True
+
+ if not notebook.OnRenameAccept(self._pageIndex, value):
+ # vetoed by the user
+ return False
+
+ # accepted, do rename the item
+ notebook.SetPageText(self._pageIndex, value)
+
+ return True
+
+
+ def Finish(self):
+ """ Finish editing. """
+
+ if not self._finished:
+
+ notebook = self._owner.GetParent()
+
+ self._finished = True
+ self._owner.SetFocus()
+ notebook.ResetTextControl()
+
+
+ def OnChar(self, event):
+ """
+ Handles the ``wx.EVT_CHAR`` event for :class:`TabTextCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ keycode = event.GetKeyCode()
+ shiftDown = event.ShiftDown()
+
+ if keycode == wx.WXK_RETURN:
+ if shiftDown and self._tabEdited.IsMultiline():
+ event.Skip()
+ else:
+ self._aboutToFinish = True
+ self.SetValue(self._currentValue)
+ # Notify the owner about the changes
+ self.AcceptChanges()
+ # Even if vetoed, close the control (consistent with MSW)
+ wx.CallAfter(self.Finish)
+
+ elif keycode == wx.WXK_ESCAPE:
+ self.StopEditing()
+
+ else:
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` event for :class:`TabTextCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if not self._finished:
+
+ # auto-grow the textctrl:
+ mySize = self.GetSize()
+
+ dc = wx.ClientDC(self)
+ sx, sy, dummy = dc.GetMultiLineTextExtent(self.GetValue() + "M")
+
+ self.SetSize((sx, -1))
+ self._currentValue = self.GetValue()
+
+ event.Skip()
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`TabTextCtrl`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if not self._finished and not self._aboutToFinish:
+
+ # We must finish regardless of success, otherwise we'll get
+ # focus problems:
+ if not self.AcceptChanges():
+ self._owner.GetParent().OnRenameCancelled(self._pageIndex)
+
+ # We must let the native text control handle focus, too, otherwise
+ # it could have problems with the cursor (e.g., in wxGTK).
+ event.Skip()
+ wx.CallAfter(self._owner.GetParent().ResetTextControl)
+
+
+ def StopEditing(self):
+ """ Suddenly stops the editing. """
+
+ self._owner.GetParent().OnRenameCancelled(self._pageIndex)
+ self.Finish()
+
+
+ def item(self):
+ """ Returns the item currently edited. """
+
+ return self._tabEdited
+
+
+# ----------------------------------------------------------------------
+
+class AuiNotebookPage(object):
+ """
+ A simple class which holds information about tab captions, bitmaps and
+ colours.
+ """
+
+ def __init__(self):
+ """
+ Default class constructor.
+ Used internally, do not call it in your code!
+ """
+
+ self.window = None # page's associated window
+ self.caption = "" # caption displayed on the tab
+ self.bitmap = wx.NullBitmap # tab's bitmap
+ self.dis_bitmap = wx.NullBitmap # tab's disabled bitmap
+ self.tooltip = "" # tab's tooltip
+ self.rect = wx.Rect() # tab's hit rectangle
+ self.active = False # True if the page is currently active
+ self.enabled = True # True if the page is currently enabled
+ self.hasCloseButton = True # True if the page has a close button using the style
+ # AUI_NB_CLOSE_ON_ALL_TABS
+ self.control = None # A control can now be inside a tab
+ self.renamable = False # If True, a tab can be renamed by a left double-click
+
+ self.text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNTEXT)
+
+ self.access_time = datetime.datetime.now() # Last time this page was selected
+
+
+ def IsMultiline(self):
+ """ Returns whether the tab contains multiline text. """
+
+ return "\n" in self.caption
+
+
+# ----------------------------------------------------------------------
+
+class AuiTabContainerButton(object):
+ """
+ A simple class which holds information about tab buttons and their state.
+ """
+
+ def __init__(self):
+ """
+ Default class constructor.
+ Used internally, do not call it in your code!
+ """
+
+ self.id = -1 # button's id
+ self.name = ""
+ self.cur_state = AUI_BUTTON_STATE_NORMAL # current state (normal, hover, pressed, etc.)
+ self.location = wx.LEFT # buttons location (wxLEFT, wxRIGHT, or wxCENTER)
+ self.bitmap = wx.NullBitmap # button's hover bitmap
+ self.dis_bitmap = wx.NullBitmap # button's disabled bitmap
+ self.rect = wx.Rect() # button's hit rectangle
+
+
+# ----------------------------------------------------------------------
+
+class CommandNotebookEvent(wx.PyCommandEvent):
+ """ A specialized command event class for events sent by :class:`AuiNotebook` . """
+
+ def __init__(self, command_type=None, win_id=0):
+ """
+ Default class constructor.
+
+ :param `command_type`: the event kind or an instance of :class:`PyCommandEvent`.
+ :param integer `win_id`: the window identification number.
+ """
+
+ if type(command_type) == types.IntType:
+ wx.PyCommandEvent.__init__(self, command_type, win_id)
+ else:
+ wx.PyCommandEvent.__init__(self, command_type.GetEventType(), command_type.GetId())
+
+ self.old_selection = -1
+ self.selection = -1
+ self.drag_source = None
+ self.dispatched = 0
+ self.label = ""
+ self.editCancelled = False
+ self.page = None
+
+
+ def SetSelection(self, s):
+ """
+ Sets the selection member variable.
+
+ :param integer `s`: the new selection.
+ """
+
+ self.selection = s
+ self._commandInt = s
+
+
+ def GetSelection(self):
+ """ Returns the currently selected page, or -1 if none was selected. """
+
+ return self.selection
+
+
+ def SetOldSelection(self, s):
+ """
+ Sets the id of the page selected before the change.
+
+ :param integer `s`: the old selection.
+ """
+
+ self.old_selection = s
+
+
+ def GetOldSelection(self):
+ """
+ Returns the page that was selected before the change, or -1 if none was
+ selected.
+ """
+
+ return self.old_selection
+
+
+ def SetDragSource(self, s):
+ """
+ Sets the drag and drop source.
+
+ :param `s`: the drag source.
+ """
+
+ self.drag_source = s
+
+
+ def GetDragSource(self):
+ """ Returns the drag and drop source. """
+
+ return self.drag_source
+
+
+ def SetDispatched(self, b):
+ """
+ Sets the event as dispatched (used for automatic :class:`AuiNotebook` ).
+
+ :param `b`: whether the event was dispatched or not.
+ """
+
+ self.dispatched = b
+
+
+ def GetDispatched(self):
+ """ Returns whether the event was dispatched (used for automatic :class:`AuiNotebook` ). """
+
+ return self.dispatched
+
+
+ def IsEditCancelled(self):
+ """ Returns the edit cancel flag (for ``EVT_AUINOTEBOOK_BEGIN`` | ``END_LABEL_EDIT`` only)."""
+
+ return self.editCancelled
+
+
+ def SetEditCanceled(self, editCancelled):
+ """
+ Sets the edit cancel flag (for ``EVT_AUINOTEBOOK_BEGIN`` | ``END_LABEL_EDIT`` only).
+
+ :param bool `editCancelled`: whether the editing action has been cancelled or not.
+ """
+
+ self.editCancelled = editCancelled
+
+
+ def GetLabel(self):
+ """Returns the label-itemtext (for ``EVT_AUINOTEBOOK_BEGIN`` | ``END_LABEL_EDIT`` only)."""
+
+ return self.label
+
+
+ def SetLabel(self, label):
+ """
+ Sets the label. Useful only for ``EVT_AUINOTEBOOK_END_LABEL_EDIT``.
+
+ :param string `label`: the new label.
+ """
+
+ self.label = label
+
+
+ Page = property(lambda self: self.page,
+ lambda self, page: setattr(self, 'page', page))
+ Selection = property(lambda self: self.GetSelection(), lambda self, sel: self.SetSelection(sel))
+
+# ----------------------------------------------------------------------
+
+class AuiNotebookEvent(CommandNotebookEvent):
+ """ A specialized command event class for events sent by :class:`AuiNotebook`. """
+
+ def __init__(self, command_type=None, win_id=0):
+ """
+ Default class constructor.
+
+ :param `command_type`: the event kind or an instance of :class:`PyCommandEvent`.
+ :param integer `win_id`: the window identification number.
+ """
+
+ CommandNotebookEvent.__init__(self, command_type, win_id)
+
+ if type(command_type) == types.IntType:
+ self.notify = wx.NotifyEvent(command_type, win_id)
+ else:
+ self.notify = wx.NotifyEvent(command_type.GetEventType(), command_type.GetId())
+
+
+ def GetNotifyEvent(self):
+ """ Returns the actual :class:`NotifyEvent`. """
+
+ return self.notify
+
+
+ def IsAllowed(self):
+ """ Returns whether the event is allowed or not. """
+
+ return self.notify.IsAllowed()
+
+
+ def Veto(self):
+ """
+ Prevents the change announced by this event from happening.
+
+ It is in general a good idea to notify the user about the reasons for
+ vetoing the change because otherwise the applications behaviour (which
+ just refuses to do what the user wants) might be quite surprising.
+ """
+
+ self.notify.Veto()
+
+
+ def Allow(self):
+ """
+ This is the opposite of :meth:`Veto`: it explicitly allows the event to be
+ processed. For most events it is not necessary to call this method as the
+ events are allowed anyhow but some are forbidden by default (this will
+ be mentioned in the corresponding event description).
+ """
+
+ self.notify.Allow()
+
+
+# ---------------------------------------------------------------------------- #
+# Class TabNavigatorProps
+# ---------------------------------------------------------------------------- #
+
+class TabNavigatorProps(object):
+ """
+ Data storage class for managing and providing access to :class:`TabNavigatorWindow` properties.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ super(TabNavigatorProps, self).__init__()
+
+ # Attributes
+ self._icon = wx.NullBitmap
+ self._font = wx.NullFont
+ self._minsize = wx.DefaultSize
+
+ # Accessors
+ Icon = property(lambda self: self._icon,
+ lambda self, icon: setattr(self, '_icon', icon),
+ doc='Sets/Gets the icon for the L{TabNavigatorWindow}, an instance of :class:`Bitmap`.')
+ Font = property(lambda self: self._font,
+ lambda self, font: setattr(self, '_font', font),
+ doc='Sets/Gets the font for the L{TabNavigatorWindow}, an instance of :class:`Font`.')
+ MinSize = property(lambda self: self._minsize,
+ lambda self, size: setattr(self, '_minsize', size),
+ doc='Sets/Gets the minimum size for the L{TabNavigatorWindow}, an instance of :class:`Size`.')
+
+# ---------------------------------------------------------------------------- #
+# Class TabNavigatorWindow
+# ---------------------------------------------------------------------------- #
+
+class TabNavigatorWindow(wx.Dialog):
+ """
+ This class is used to create a modal dialog that enables "Smart Tabbing",
+ similar to what you would get by hitting ``Alt`` + ``Tab`` on Windows.
+ """
+
+ def __init__(self, parent, props):
+ """
+ Default class constructor. Used internally.
+
+ :param `parent`: the :class:`TabNavigatorWindow` parent;
+ :param `props`: the :class:`TabNavigatorProps` object.
+ """
+
+ wx.Dialog.__init__(self, parent, wx.ID_ANY, "", size=props.MinSize, style=0)
+
+ self._selectedItem = -1
+ self._indexMap = []
+ self._props = props
+
+ if not self._props.Icon.IsOk():
+ self._props.Icon = Mondrian.GetBitmap()
+
+ if props.Icon.GetSize() != (16, 16):
+ img = self._props.Icon.ConvertToImage()
+ img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH)
+ self._props.Icon = wx.BitmapFromImage(img)
+
+ if self._props.Font.IsOk():
+ self.Font = self._props.Font
+
+ sz = wx.BoxSizer(wx.VERTICAL)
+
+ self._listBox = wx.ListBox(self, wx.ID_ANY,
+ wx.DefaultPosition,
+ wx.Size(200, 150), [],
+ wx.LB_SINGLE | wx.NO_BORDER)
+
+ mem_dc = wx.MemoryDC()
+ mem_dc.SelectObject(wx.EmptyBitmap(1,1))
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetWeight(wx.BOLD)
+ mem_dc.SetFont(font)
+
+ panelHeight = mem_dc.GetCharHeight()
+ panelHeight += 4 # Place a spacer of 2 pixels
+
+ # Out signpost bitmap is 24 pixels
+ if panelHeight < 24:
+ panelHeight = 24
+
+ self._panel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition,
+ wx.Size(-1, panelHeight))
+
+ sz.Add(self._panel, 0, wx.EXPAND)
+ sz.Add(self._listBox, 1, wx.EXPAND)
+
+ self.SetSizer(sz)
+
+ # Connect events to the list box
+ self._listBox.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self._listBox.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
+ self._listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnItemSelected)
+
+ # Connect paint event to the panel
+ self._panel.Bind(wx.EVT_PAINT, self.OnPanelPaint)
+ self._panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnPanelEraseBg)
+
+ self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
+ self._listBox.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
+ self.PopulateListControl(parent)
+
+ self.SetInitialSize(props.MinSize)
+ self.Centre()
+
+ # Set focus on the list box to avoid having to click on it to change
+ # the tab selection under GTK.
+ self._listBox.SetFocus()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` for the :class:`TabNavigatorWindow`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if event.GetKeyCode() == wx.WXK_CONTROL:
+ self.CloseDialog()
+
+
+ def OnNavigationKey(self, event):
+ """
+ Handles the ``wx.EVT_NAVIGATION_KEY`` for the :class:`TabNavigatorWindow`.
+
+ :param `event`: a :class:`NavigationKeyEvent` event to be processed.
+ """
+
+ selected = self._listBox.GetSelection()
+ bk = self.GetParent()
+ maxItems = bk.GetPageCount()
+
+ if event.GetDirection():
+
+ # Select next page
+ if selected == maxItems - 1:
+ itemToSelect = 0
+ else:
+ itemToSelect = selected + 1
+
+ else:
+
+ # Previous page
+ if selected == 0:
+ itemToSelect = maxItems - 1
+ else:
+ itemToSelect = selected - 1
+
+ self._listBox.SetSelection(itemToSelect)
+
+
+ def PopulateListControl(self, book):
+ """
+ Populates the :class:`TabNavigatorWindow` listbox with a list of tabs.
+
+ :param `book`: the actual :class:`AuiNotebook`.
+ """
+ # Index of currently selected page
+ selection = book.GetSelection()
+ # Total number of pages
+ count = book.GetPageCount()
+ # List of (index, AuiNotebookPage)
+ pages = list(enumerate(book.GetTabContainer().GetPages()))
+ if book.GetAGWWindowStyleFlag() & AUI_NB_ORDER_BY_ACCESS:
+ # Sort pages using last access time. Most recently used is the
+ # first in line
+ pages.sort(
+ key = lambda element: element[1].access_time,
+ reverse = True
+ )
+ else:
+ # Manually add the current selection as first item
+ # Remaining ones are added in the next loop
+ del pages[selection]
+ self._listBox.Append(book.GetPageText(selection))
+ self._indexMap.append(selection)
+
+ for (index, page) in pages:
+ self._listBox.Append(book.GetPageText(index))
+ self._indexMap.append(index)
+
+ # Select the next entry after the current selection
+ self._listBox.SetSelection(0)
+ dummy = wx.NavigationKeyEvent()
+ dummy.SetDirection(True)
+ self.OnNavigationKey(dummy)
+
+
+ def OnItemSelected(self, event):
+ """
+ Handles the ``wx.EVT_LISTBOX_DCLICK`` event for the :class:`ListBox` inside :class:`TabNavigatorWindow`.
+
+ :param `event`: a :class:`ListEvent` event to be processed.
+ """
+
+ self.CloseDialog()
+
+
+ def CloseDialog(self):
+ """ Closes the :class:`TabNavigatorWindow` dialog, setting selection in :class:`AuiNotebook`. """
+
+ bk = self.GetParent()
+ self._selectedItem = self._listBox.GetSelection()
+ self.EndModal(wx.ID_OK)
+
+
+ def GetSelectedPage(self):
+ """ Gets the page index that was selected when the dialog was closed. """
+
+ return self._indexMap[self._selectedItem]
+
+
+ def OnPanelPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`TabNavigatorWindow` top panel.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.PaintDC(self._panel)
+ rect = self._panel.GetClientRect()
+
+ bmp = wx.EmptyBitmap(rect.width, rect.height)
+
+ mem_dc = wx.MemoryDC()
+ mem_dc.SelectObject(bmp)
+
+ endColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+ startColour = LightColour(endColour, 50)
+ mem_dc.GradientFillLinear(rect, startColour, endColour, wx.SOUTH)
+
+ # Draw the caption title and place the bitmap
+ # get the bitmap optimal position, and draw it
+ bmpPt, txtPt = wx.Point(), wx.Point()
+ bmpPt.y = (rect.height - self._props.Icon.GetHeight())/2
+ bmpPt.x = 3
+ mem_dc.DrawBitmap(self._props.Icon, bmpPt.x, bmpPt.y, True)
+
+ # get the text position, and draw it
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetWeight(wx.BOLD)
+ mem_dc.SetFont(font)
+ fontHeight = mem_dc.GetCharHeight()
+
+ txtPt.x = bmpPt.x + self._props.Icon.GetWidth() + 4
+ txtPt.y = (rect.height - fontHeight)/2
+ mem_dc.SetTextForeground(wx.WHITE)
+ mem_dc.DrawText("Opened tabs:", txtPt.x, txtPt.y)
+ mem_dc.SelectObject(wx.NullBitmap)
+
+ dc.DrawBitmap(bmp, 0, 0)
+
+
+ def OnPanelEraseBg(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`TabNavigatorWindow` top panel.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This is intentionally empty, to reduce flicker.
+ """
+
+ pass
+
+
+# ----------------------------------------------------------------------
+# -- AuiTabContainer class implementation --
+
+class AuiTabContainer(object):
+ """
+ AuiTabContainer is a class which contains information about each tab.
+ It also can render an entire tab control to a specified DC.
+ It's not a window class itself, because this code will be used by
+ the :class:`AuiNotebook`, where it is disadvantageous to have separate
+ windows for each tab control in the case of "docked tabs".
+
+ A derived class, :class:`AuiTabCtrl`, is an actual :class:`Window` - derived window
+ which can be used as a tab control in the normal sense.
+ """
+
+ def __init__(self, auiNotebook):
+ """
+ Default class constructor.
+ Used internally, do not call it in your code!
+
+ :param `auiNotebook`: the parent :class:`AuiNotebook` window.
+ """
+
+ self._tab_offset = 0
+ self._agwFlags = 0
+ self._art = TA.AuiDefaultTabArt()
+
+ self._buttons = []
+ self._pages = []
+ self._tab_close_buttons = []
+ self._click_tab = None
+
+ self._rect = wx.Rect()
+ self._auiNotebook = auiNotebook
+
+ self.AddButton(AUI_BUTTON_LEFT, wx.LEFT, name="Scroll Left")
+ self.AddButton(AUI_BUTTON_RIGHT, wx.RIGHT, name="Scroll Right")
+ self.AddButton(AUI_BUTTON_WINDOWLIST, wx.RIGHT, name="Window List")
+ self.AddButton(AUI_BUTTON_CLOSE, wx.RIGHT, name="Close")
+
+
+ def SetArtProvider(self, art):
+ """
+ Instructs :class:`AuiTabContainer` to use art provider specified by parameter `art`
+ for all drawing calls. This allows plugable look-and-feel features.
+
+ :param `art`: an art provider.
+
+ :note: The previous art provider object, if any, will be deleted by :class:`AuiTabContainer`.
+ """
+
+ del self._art
+ self._art = art
+
+ if self._art:
+ self._art.SetAGWFlags(self._agwFlags)
+
+
+ def GetArtProvider(self):
+ """ Returns the current art provider being used. """
+
+ return self._art
+
+
+ def SetAGWFlags(self, agwFlags):
+ """
+ Sets the tab art flags.
+
+ :param integer `agwFlags`: a combination of the following values:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook
+ ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet
+ ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet
+ ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook
+ ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab
+ ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging
+ ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control
+ ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width
+ ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed
+ ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available
+ ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar
+ ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab
+ ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs
+ ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close :class:`AuiNotebook` tabs by mouse middle button click
+ ``AUI_NB_SUB_NOTEBOOK`` This style is used by :class:`~lib.agw.aui.framemanager.AuiManager` to create automatic AuiNotebooks
+ ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present
+ ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
+ ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items
+ ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser)
+ ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen,
+ tabs cannot be dragged far enough outside of the notebook to become floating pages
+ ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default)
+ ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs
+ ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle
+ ==================================== ==================================
+
+ .. todo:: Implementation of flags ``AUI_NB_RIGHT`` and ``AUI_NB_LEFT``.
+
+ """
+
+ self._agwFlags = agwFlags
+
+ # check for new close button settings
+ self.RemoveButton(AUI_BUTTON_LEFT)
+ self.RemoveButton(AUI_BUTTON_RIGHT)
+ self.RemoveButton(AUI_BUTTON_WINDOWLIST)
+ self.RemoveButton(AUI_BUTTON_CLOSE)
+
+ if agwFlags & AUI_NB_SCROLL_BUTTONS:
+ self.AddButton(AUI_BUTTON_LEFT, wx.LEFT, name="Scroll Left")
+ self.AddButton(AUI_BUTTON_RIGHT, wx.RIGHT, name="Scroll Right")
+
+ if agwFlags & AUI_NB_WINDOWLIST_BUTTON:
+ self.AddButton(AUI_BUTTON_WINDOWLIST, wx.RIGHT, name="Window List")
+
+ if agwFlags & AUI_NB_CLOSE_BUTTON:
+ self.AddButton(AUI_BUTTON_CLOSE, wx.RIGHT, name="Close")
+
+ if self._art:
+ self._art.SetAGWFlags(self._agwFlags)
+
+
+ def GetAGWFlags(self):
+ """
+ Returns the tab art flags.
+
+ .. seealso:: :meth:`SetAGWFlags` for a list of possible return values.
+ """
+
+ return self._agwFlags
+
+
+ def SetNormalFont(self, font):
+ """
+ Sets the normal font for drawing tab labels.
+
+ :param Font `font`: the new font to use to draw tab labels in their normal, un-selected state.
+ """
+
+ self._art.SetNormalFont(font)
+
+
+ def SetSelectedFont(self, font):
+ """
+ Sets the selected tab font for drawing tab labels.
+
+ :param Font `font`: the new font to use to draw tab labels in their selected state.
+ """
+
+ self._art.SetSelectedFont(font)
+
+
+ def SetMeasuringFont(self, font):
+ """
+ Sets the font for calculating text measurements.
+
+ :param Font `font`: the new font to use to measure tab label text extents.
+ """
+
+ self._art.SetMeasuringFont(font)
+
+
+ def SetTabRect(self, rect):
+ """
+ Sets the tab area rectangle.
+
+ :param Rect `rect`: the available area for :class:`AuiTabContainer`.
+ """
+
+ self._rect = rect
+
+ if self._art:
+ minMaxTabWidth = self._auiNotebook.GetMinMaxTabWidth()
+ self._art.SetSizingInfo(rect.GetSize(), len(self._pages), minMaxTabWidth)
+
+
+ def AddPage(self, page, info):
+ """
+ Adds a page to the tab control.
+
+ :param Window `page`: the window associated with this tab;
+ :param `info`: an instance of :class:`AuiNotebookPage`.
+ """
+
+ page_info = info
+ page_info.window = page
+
+ self._pages.append(page_info)
+
+ # let the art provider know how many pages we have
+ if self._art:
+ minMaxTabWidth = self._auiNotebook.GetMinMaxTabWidth()
+ self._art.SetSizingInfo(self._rect.GetSize(), len(self._pages), minMaxTabWidth)
+
+ return True
+
+
+ def InsertPage(self, page, info, idx):
+ """
+ Inserts a page in the tab control in the position specified by `idx`.
+
+ :param Window `page`: the window associated with this tab;
+ :param `info`: an instance of :class:`AuiNotebookPage`;
+ :param integer `idx`: the page insertion index.
+ """
+
+ page_info = info
+ page_info.window = page
+
+ if idx >= len(self._pages):
+ self._pages.append(page_info)
+ else:
+ self._pages.insert(idx, page_info)
+
+ # let the art provider know how many pages we have
+ if self._art:
+ minMaxTabWidth = self._auiNotebook.GetMinMaxTabWidth()
+ self._art.SetSizingInfo(self._rect.GetSize(), len(self._pages), minMaxTabWidth)
+
+ return True
+
+
+ def MovePage(self, page, new_idx):
+ """
+ Moves a page in a new position specified by `new_idx`.
+
+ :param Window `page`: the window associated with this tab;
+ :param integer `new_idx`: the new page position.
+ """
+
+ idx = self.GetIdxFromWindow(page)
+ if idx == -1:
+ return False
+
+ # get page entry, make a copy of it
+ p = self.GetPage(idx)
+
+ # remove old page entry
+ self.RemovePage(page)
+
+ # insert page where it should be
+ self.InsertPage(page, p, new_idx)
+
+ return True
+
+
+ def RemovePage(self, wnd):
+ """
+ Removes a page from the tab control.
+
+ :param `wnd`: an instance of :class:`Window`, a window associated with this tab.
+ """
+
+ minMaxTabWidth = self._auiNotebook.GetMinMaxTabWidth()
+
+ for page in self._pages:
+ if page.window == wnd:
+ self._pages.remove(page)
+ self._tab_offset = min(self._tab_offset, len(self._pages) - 1)
+
+ # let the art provider know how many pages we have
+ if self._art:
+ self._art.SetSizingInfo(self._rect.GetSize(), len(self._pages), minMaxTabWidth)
+
+ return True
+
+ return False
+
+
+ def SetActivePage(self, wndOrInt):
+ """
+ Sets the :class:`AuiNotebook` active page.
+
+ :param `wndOrInt`: an instance of :class:`Window` or an integer specifying a tab index.
+ """
+
+ if type(wndOrInt) == types.IntType:
+
+ if wndOrInt >= len(self._pages):
+ return False
+
+ wnd = self._pages[wndOrInt].window
+
+ else:
+ wnd = wndOrInt
+
+ found = False
+
+ for indx, page in enumerate(self._pages):
+ if page.window == wnd:
+ page.active = True
+ found = True
+ else:
+ page.active = False
+
+ return found
+
+
+ def SetNoneActive(self):
+ """ Sets all the tabs as inactive (non-selected). """
+
+ for page in self._pages:
+ page.active = False
+
+
+ def GetActivePage(self):
+ """ Returns the current selected tab or ``wx.NOT_FOUND`` if none is selected. """
+
+ for indx, page in enumerate(self._pages):
+ if page.active:
+ return indx
+
+ return wx.NOT_FOUND
+
+
+ def GetWindowFromIdx(self, idx):
+ """
+ Returns the window associated with the tab with index `idx`.
+
+ :param integer `idx`: the tab index.
+ """
+
+ if idx >= len(self._pages):
+ return None
+
+ return self._pages[idx].window
+
+
+ def GetIdxFromWindow(self, wnd):
+ """
+ Returns the tab index based on the window `wnd` associated with it.
+
+ :param `wnd`: an instance of :class:`Window`.
+ """
+
+ for indx, page in enumerate(self._pages):
+ if page.window == wnd:
+ return indx
+
+ return wx.NOT_FOUND
+
+
+ def GetPage(self, idx):
+ """
+ Returns the page specified by the given index.
+
+ :param integer `idx`: the tab index.
+ """
+
+ if idx < 0 or idx >= len(self._pages):
+ raise Exception("Invalid Page index")
+
+ return self._pages[idx]
+
+
+ def GetPages(self):
+ """ Returns a list of all the pages in this :class:`AuiTabContainer`. """
+
+ return self._pages
+
+
+ def GetPageCount(self):
+ """ Returns the number of pages in the :class:`AuiTabContainer`. """
+
+ return len(self._pages)
+
+
+ def GetEnabled(self, idx):
+ """
+ Returns whether a tab is enabled or not.
+
+ :param integer `idx`: the tab index.
+ """
+
+ if idx < 0 or idx >= len(self._pages):
+ return False
+
+ return self._pages[idx].enabled
+
+
+ def EnableTab(self, idx, enable=True):
+ """
+ Enables/disables a tab in the :class:`AuiTabContainer`.
+
+ :param integer `idx`: the tab index;
+ :param bool `enable`: ``True`` to enable a tab, ``False`` to disable it.
+ """
+
+ if idx < 0 or idx >= len(self._pages):
+ raise Exception("Invalid Page index")
+
+ self._pages[idx].enabled = enable
+ wnd = self.GetWindowFromIdx(idx)
+ wnd.Enable(enable)
+
+
+ def AddButton(self, id, location, normal_bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap, name=""):
+ """
+ Adds a button in the tab area.
+
+ :param integer `id`: the button identifier. This can be one of the following:
+
+ ============================== =================================
+ Button Identifier Description
+ ============================== =================================
+ ``AUI_BUTTON_CLOSE`` Shows a close button on the tab area
+ ``AUI_BUTTON_WINDOWLIST`` Shows a window list button on the tab area
+ ``AUI_BUTTON_LEFT`` Shows a left button on the tab area
+ ``AUI_BUTTON_RIGHT`` Shows a right button on the tab area
+ ============================== =================================
+
+ :param integer `location`: the button location. Can be ``wx.LEFT`` or ``wx.RIGHT``;
+ :param Bitmap `normal_bitmap`: the bitmap for an enabled tab;
+ :param Bitmap `disabled_bitmap`: the bitmap for a disabled tab;
+ :param string `name`: the button name.
+ """
+
+ button = AuiTabContainerButton()
+ button.id = id
+ button.name = name
+ button.bitmap = normal_bitmap
+ button.dis_bitmap = disabled_bitmap
+ button.location = location
+ button.cur_state = AUI_BUTTON_STATE_NORMAL
+
+ self._buttons.append(button)
+
+
+ def CloneButtons(self):
+ """
+ Clones the tab area buttons when the :class:`AuiNotebook` is being split.
+
+ :see: :meth:`AddButton`
+
+ :note: Standard buttons for :class:`AuiNotebook` are not cloned, only custom ones.
+ """
+
+ singleton_list = [AUI_BUTTON_CLOSE, AUI_BUTTON_WINDOWLIST, AUI_BUTTON_LEFT, AUI_BUTTON_RIGHT]
+ clones = []
+
+ for button in self._buttons:
+ if button.id not in singleton_list:
+ new_button = AuiTabContainerButton()
+ new_button.id = button.id
+ new_button.bitmap = button.bitmap
+ new_button.dis_bitmap = button.dis_bitmap
+ new_button.location = button.location
+ clones.append(new_button)
+
+ return clones
+
+
+ def RemoveButton(self, id):
+ """
+ Removes a button from the tab area.
+
+ :param integer `id`: the button identifier. See :meth:`AddButton` for a list of button identifiers.
+
+ :see: :meth:`AddButton`
+ """
+
+ for button in self._buttons:
+ if button.id == id:
+ self._buttons.remove(button)
+ return
+
+
+ def GetTabOffset(self):
+ """ Returns the tab offset. """
+
+ return self._tab_offset
+
+
+ def SetTabOffset(self, offset):
+ """
+ Sets the tab offset.
+
+ :param integer `offset`: the tab offset.
+ """
+
+ self._tab_offset = offset
+
+
+ def Render(self, raw_dc, wnd):
+ """
+ Renders the tab catalog to the specified :class:`DC`.
+
+ It is a virtual function and can be overridden to provide custom drawing
+ capabilities.
+
+ :param `raw_dc`: a :class:`DC` device context;
+ :param `wnd`: an instance of :class:`Window`.
+ """
+
+ if not raw_dc or not raw_dc.IsOk():
+ return
+
+ dc = wx.MemoryDC()
+
+ # use the same layout direction as the window DC uses to ensure that the
+ # text is rendered correctly
+ dc.SetLayoutDirection(raw_dc.GetLayoutDirection())
+
+ page_count = len(self._pages)
+ button_count = len(self._buttons)
+
+ # create off-screen bitmap
+ bmp = wx.EmptyBitmap(self._rect.GetWidth(), self._rect.GetHeight())
+ dc.SelectObject(bmp)
+
+ if not dc.IsOk():
+ return
+
+ # prepare the tab-close-button array
+ # make sure tab button entries which aren't used are marked as hidden
+ for i in xrange(page_count, len(self._tab_close_buttons)):
+ self._tab_close_buttons[i].cur_state = AUI_BUTTON_STATE_HIDDEN
+
+ # make sure there are enough tab button entries to accommodate all tabs
+ while len(self._tab_close_buttons) < page_count:
+ tempbtn = AuiTabContainerButton()
+ tempbtn.id = AUI_BUTTON_CLOSE
+ tempbtn.location = wx.CENTER
+ tempbtn.cur_state = AUI_BUTTON_STATE_HIDDEN
+ self._tab_close_buttons.append(tempbtn)
+
+ # find out if size of tabs is larger than can be
+ # afforded on screen
+ total_width = visible_width = 0
+ tab_width = [0] * page_count
+
+ for i in xrange(page_count):
+ page = self._pages[i]
+
+ # determine if a close button is on this tab
+ close_button = False
+ if (self._agwFlags & AUI_NB_CLOSE_ON_ALL_TABS and page.hasCloseButton) or \
+ (self._agwFlags & AUI_NB_CLOSE_ON_ACTIVE_TAB and page.active and page.hasCloseButton):
+
+ close_button = True
+
+ control = page.control
+ if control:
+ try:
+ control.GetSize()
+ except wx.PyDeadObjectError:
+ page.control = None
+
+ size, x_extent = self._art.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active,
+ (close_button and [AUI_BUTTON_STATE_NORMAL] or \
+ [AUI_BUTTON_STATE_HIDDEN])[0], page.control)
+
+ if i+1 < page_count:
+ total_width += x_extent
+ tab_width[i] = x_extent
+ else:
+ total_width += size[0]
+ tab_width[i] = size[0]
+
+ if i >= self._tab_offset:
+ if i+1 < page_count:
+ visible_width += x_extent
+ else:
+ visible_width += size[0]
+
+ # Calculate the width of visible buttons
+ buttons_width = 0
+
+ for button in self._buttons:
+ if not (button.cur_state & AUI_BUTTON_STATE_HIDDEN):
+ buttons_width += button.rect.GetWidth()
+
+ total_width += buttons_width
+
+ if (total_width > self._rect.GetWidth() and page_count > 1) or self._tab_offset != 0:
+
+ # show left/right buttons
+ for button in self._buttons:
+ if button.id == AUI_BUTTON_LEFT or \
+ button.id == AUI_BUTTON_RIGHT:
+
+ button.cur_state &= ~AUI_BUTTON_STATE_HIDDEN
+
+ else:
+
+ # hide left/right buttons
+ for button in self._buttons:
+ if button.id == AUI_BUTTON_LEFT or \
+ button.id == AUI_BUTTON_RIGHT:
+
+ button.cur_state |= AUI_BUTTON_STATE_HIDDEN
+
+ # Re-calculate the width of visible buttons (may have been hidden/shown)
+ buttons_width = 0
+ for button in self._buttons:
+ if not (button.cur_state & AUI_BUTTON_STATE_HIDDEN):
+ buttons_width += button.rect.GetWidth()
+
+ # Shift the tab offset down to make use of available space
+ available_width = self._rect.GetWidth() - buttons_width
+ while self._tab_offset > 0 and visible_width + tab_width[self._tab_offset - 1] < available_width:
+ self._tab_offset -= 1
+ visible_width += tab_width[self._tab_offset]
+
+ # determine whether left button should be enabled
+ for button in self._buttons:
+ if button.id == AUI_BUTTON_LEFT:
+ if self._tab_offset == 0:
+ button.cur_state |= AUI_BUTTON_STATE_DISABLED
+ else:
+ button.cur_state &= ~AUI_BUTTON_STATE_DISABLED
+
+ if button.id == AUI_BUTTON_RIGHT:
+ if visible_width < self._rect.GetWidth() - buttons_width:
+ button.cur_state |= AUI_BUTTON_STATE_DISABLED
+ else:
+ button.cur_state &= ~AUI_BUTTON_STATE_DISABLED
+
+ # draw background
+ self._art.DrawBackground(dc, wnd, self._rect)
+
+ # draw buttons
+ left_buttons_width = 0
+ right_buttons_width = 0
+
+ # draw the buttons on the right side
+ offset = self._rect.x + self._rect.width
+
+ for i in xrange(button_count):
+ button = self._buttons[button_count - i - 1]
+
+ if button.location != wx.RIGHT:
+ continue
+ if button.cur_state & AUI_BUTTON_STATE_HIDDEN:
+ continue
+
+ button_rect = wx.Rect(*self._rect)
+ button_rect.SetY(1)
+ button_rect.SetWidth(offset)
+
+ button.rect = self._art.DrawButton(dc, wnd, button_rect, button, wx.RIGHT)
+
+ offset -= button.rect.GetWidth()
+ right_buttons_width += button.rect.GetWidth()
+
+ offset = 0
+
+ # draw the buttons on the left side
+ for i in xrange(button_count):
+ button = self._buttons[button_count - i - 1]
+
+ if button.location != wx.LEFT:
+ continue
+ if button.cur_state & AUI_BUTTON_STATE_HIDDEN:
+ continue
+
+ button_rect = wx.Rect(offset, 1, 1000, self._rect.height)
+
+ button.rect = self._art.DrawButton(dc, wnd, button_rect, button, wx.LEFT)
+
+ offset += button.rect.GetWidth()
+ left_buttons_width += button.rect.GetWidth()
+
+ if offset == 0:
+ offset += self._art.GetIndentSize()
+
+ # buttons before the tab offset must be set to hidden
+ for i in xrange(self._tab_offset):
+ self._tab_close_buttons[i].cur_state = AUI_BUTTON_STATE_HIDDEN
+ if self._pages[i].control:
+ if self._pages[i].control.IsShown():
+ self._pages[i].control.Hide()
+
+ # draw tab before tab offset
+ if self._tab_offset > 0:
+ page = self._pages[self._tab_offset - 1]
+ tab_button = self._tab_close_buttons[self._tab_offset - 1]
+ size, x_extent = self._art.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active, tab_button.cur_state, page.control)
+
+ rect = wx.Rect(offset - x_extent, 0, self._rect.width - right_buttons_width - offset - x_extent - 2, self._rect.height)
+ clip_rect = wx.Rect(*self._rect)
+ clip_rect.x = offset
+
+ dc.SetClippingRect(clip_rect)
+ self._art.DrawTab(dc, wnd, page, rect, tab_button.cur_state)
+ dc.DestroyClippingRegion()
+
+ # draw the tabs
+ active = 999
+ active_offset = 0
+
+ rect = wx.Rect(*self._rect)
+ rect.y = 0
+ rect.height = self._rect.height
+
+ for i in xrange(self._tab_offset, page_count):
+
+ page = self._pages[i]
+ tab_button = self._tab_close_buttons[i]
+
+ # determine if a close button is on this tab
+ if (self._agwFlags & AUI_NB_CLOSE_ON_ALL_TABS and page.hasCloseButton) or \
+ (self._agwFlags & AUI_NB_CLOSE_ON_ACTIVE_TAB and page.active and page.hasCloseButton):
+
+ if tab_button.cur_state == AUI_BUTTON_STATE_HIDDEN:
+
+ tab_button.id = AUI_BUTTON_CLOSE
+ tab_button.cur_state = AUI_BUTTON_STATE_NORMAL
+ tab_button.location = wx.CENTER
+
+ else:
+
+ tab_button.cur_state = AUI_BUTTON_STATE_HIDDEN
+
+ rect.x = offset
+ rect.width = self._rect.width - right_buttons_width - offset - 2
+
+ if rect.width <= 0:
+ break
+
+ page.rect, tab_button.rect, x_extent = self._art.DrawTab(dc, wnd, page, rect, tab_button.cur_state)
+
+ if page.active:
+ active = i
+ active_offset = offset
+ active_rect = wx.Rect(*rect)
+
+ offset += x_extent
+
+ lenPages = len(self._pages)
+ # make sure to deactivate buttons which are off the screen to the right
+ for j in xrange(i+1, len(self._tab_close_buttons)):
+ self._tab_close_buttons[j].cur_state = AUI_BUTTON_STATE_HIDDEN
+ if j > 0 and j <= lenPages:
+ if self._pages[j-1].control:
+ if self._pages[j-1].control.IsShown():
+ self._pages[j-1].control.Hide()
+
+ # draw the active tab again so it stands in the foreground
+ if active >= self._tab_offset and active < len(self._pages):
+
+ page = self._pages[active]
+ tab_button = self._tab_close_buttons[active]
+
+ rect.x = active_offset
+ dummy = self._art.DrawTab(dc, wnd, page, active_rect, tab_button.cur_state)
+
+ raw_dc.Blit(self._rect.x, self._rect.y, self._rect.GetWidth(), self._rect.GetHeight(), dc, 0, 0)
+
+
+ def IsTabVisible(self, tabPage, tabOffset, dc, wnd):
+ """
+ Returns whether a tab is visible or not.
+
+ :param integer `tabPage`: the tab index;
+ :param integer `tabOffset`: the tab offset;
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: an instance of :class:`Window` derived window.
+ """
+
+ if not dc or not dc.IsOk():
+ return False
+
+ page_count = len(self._pages)
+ button_count = len(self._buttons)
+ self.Render(dc, wnd)
+
+ # Hasn't been rendered yet assume it's visible
+ if len(self._tab_close_buttons) < page_count:
+ return True
+
+ if self._agwFlags & AUI_NB_SCROLL_BUTTONS:
+ # First check if both buttons are disabled - if so, there's no need to
+ # check further for visibility.
+ arrowButtonVisibleCount = 0
+ for i in xrange(button_count):
+
+ button = self._buttons[i]
+ if button.id == AUI_BUTTON_LEFT or \
+ button.id == AUI_BUTTON_RIGHT:
+
+ if button.cur_state & AUI_BUTTON_STATE_HIDDEN == 0:
+ arrowButtonVisibleCount += 1
+
+ # Tab must be visible
+ if arrowButtonVisibleCount == 0:
+ return True
+
+ # If tab is less than the given offset, it must be invisible by definition
+ if tabPage < tabOffset:
+ return False
+
+ # draw buttons
+ left_buttons_width = 0
+ right_buttons_width = 0
+
+ # calculate size of the buttons on the right side
+ for i in xrange(button_count):
+ button = self._buttons[button_count - i - 1]
+
+ if button.location != wx.RIGHT:
+ continue
+ if button.cur_state & AUI_BUTTON_STATE_HIDDEN:
+ continue
+
+ right_buttons_width += button.rect.GetWidth()
+
+ offset = 0
+
+ # calculate size of the buttons on the left side
+ for i in xrange(button_count):
+ button = self._buttons[button_count - i - 1]
+
+ if button.location != wx.LEFT:
+ continue
+ if button.cur_state & AUI_BUTTON_STATE_HIDDEN:
+ continue
+
+ offset += button.rect.GetWidth()
+ left_buttons_width += button.rect.GetWidth()
+
+ if offset == 0:
+ offset += self._art.GetIndentSize()
+
+ rect = wx.Rect(*self._rect)
+ rect.y = 0
+ rect.height = self._rect.height
+
+ # See if the given page is visible at the given tab offset (effectively scroll position)
+ for i in xrange(tabOffset, page_count):
+
+ page = self._pages[i]
+ tab_button = self._tab_close_buttons[i]
+
+ rect.x = offset
+ rect.width = self._rect.width - right_buttons_width - offset - 2
+
+ if rect.width <= 0:
+ return False # haven't found the tab, and we've run out of space, so return False
+
+ size, x_extent = self._art.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active, tab_button.cur_state, page.control)
+ offset += x_extent
+
+ if i == tabPage:
+
+ # If not all of the tab is visible, and supposing there's space to display it all,
+ # we could do better so we return False.
+ if (self._rect.width - right_buttons_width - offset - 2) <= 0 and (self._rect.width - right_buttons_width - left_buttons_width) > x_extent:
+ return False
+ else:
+ return True
+
+ # Shouldn't really get here, but if it does, assume the tab is visible to prevent
+ # further looping in calling code.
+ return True
+
+
+ def MakeTabVisible(self, tabPage, win):
+ """
+ Make the tab visible if it wasn't already.
+
+ :param integer `tabPage`: the tab index;
+ :param `win`: an instance of :class:`Window` derived window.
+ """
+
+ dc = wx.ClientDC(win)
+
+ if not self.IsTabVisible(tabPage, self.GetTabOffset(), dc, win):
+ for i in xrange(len(self._pages)):
+ if self.IsTabVisible(tabPage, i, dc, win):
+ self.SetTabOffset(i)
+ win.Refresh()
+ return
+
+
+ def TabHitTest(self, x, y):
+ """
+ TabHitTest() tests if a tab was hit, passing the window pointer
+ back if that condition was fulfilled.
+
+ :param integer `x`: the mouse `x` position;
+ :param integer `y`: the mouse `y` position.
+ """
+
+ if not self._rect.Contains((x,y)):
+ return None
+
+ btn = self.ButtonHitTest(x, y)
+ if btn:
+ if btn in self._buttons:
+ return None
+
+ for i in xrange(self._tab_offset, len(self._pages)):
+ page = self._pages[i]
+ if page.rect.Contains((x,y)):
+ return page.window
+
+ return None
+
+
+ def ButtonHitTest(self, x, y, state_flags=AUI_BUTTON_STATE_HIDDEN|AUI_BUTTON_STATE_DISABLED):
+ """
+ Tests if a button was hit.
+
+ :param integer `x`: the mouse `x` position;
+ :param integer `y`: the mouse `y` position;
+ :param integer `state_flags`: the current button state (hidden, disabled, etc...).
+
+ :returns: and instance of :class:`AuiTabContainerButton` if a button was hit, ``None`` otherwise.
+ """
+
+ if not self._rect.Contains((x,y)):
+ return None
+
+ for button in self._buttons:
+ if button.rect.Contains((x,y)) and \
+ (button.cur_state & state_flags) == 0:
+ return button
+
+ for button in self._tab_close_buttons:
+ if button.rect.Contains((x,y)) and \
+ (button.cur_state & state_flags) == 0:
+ return button
+
+ return None
+
+
+ def DoShowHide(self):
+ """
+ This function shows the active window, then hides all of the other windows
+ (in that order).
+ """
+
+ pages = self.GetPages()
+
+ # show new active page first
+ for page in pages:
+ if page.active:
+ page.window.Show(True)
+ break
+
+ # hide all other pages
+ for page in pages:
+ if not page.active:
+ page.window.Show(False)
+
+
+# ----------------------------------------------------------------------
+# -- AuiTabCtrl class implementation --
+
+class AuiTabCtrl(wx.PyControl, AuiTabContainer):
+ """
+ This is an actual :class:`Window` - derived window which can be used as a tab control in the normal sense.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.NO_BORDER|wx.WANTS_CHARS|wx.TAB_TRAVERSAL):
+ """
+ Default class constructor.
+ Used internally, do not call it in your code!
+
+ :param `parent`: the :class:`AuiNotebook` parent;
+ :param integer `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param Point `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param Size `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param integer `style`: the window style.
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style, name="AuiTabCtrl")
+ AuiTabContainer.__init__(self, parent)
+
+ self._click_pt = wx.Point(-1, -1)
+ self._is_dragging = False
+ self._hover_button = None
+ self._pressed_button = None
+ self._drag_image = None
+ self._drag_img_offset = (0, 0)
+ self._on_button = False
+ self._tooltip_timer = None
+ self._tooltip_wnd = None
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown)
+ self.Bind(wx.EVT_MIDDLE_UP, self.OnMiddleUp)
+ self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
+ self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLost)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnterWindow)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+ self.Bind(EVT_AUINOTEBOOK_BUTTON, self.OnButton)
+
+
+ def IsDragging(self):
+ """ Returns whether the user is dragging a tab with the mouse or not. """
+
+ return self._is_dragging
+
+
+ def GetDefaultBorder(self):
+ """ Returns the default border style for :class:`AuiTabCtrl`. """
+
+ return wx.BORDER_NONE
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.PaintDC(self)
+ dc.SetFont(self.GetFont())
+
+ if self.GetPageCount() > 0:
+ self.Render(dc, self)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This is intentionally empty, to reduce flicker.
+ """
+
+ pass
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same
+ size as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return wx.Size(self._rect.width, self._rect.height)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ s = event.GetSize()
+ self.SetTabRect(wx.Rect(0, 0, s.GetWidth(), s.GetHeight()))
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.StopTooltipTimer()
+
+ if not self.HasCapture():
+ self.CaptureMouse()
+
+ self._click_pt = wx.Point(-1, -1)
+ self._is_dragging = False
+ self._click_tab = None
+ self._pressed_button = None
+
+ wnd = self.TabHitTest(event.GetX(), event.GetY())
+
+ if wnd is not None:
+ new_selection = self.GetIdxFromWindow(wnd)
+
+ # AuiNotebooks always want to receive this event
+ # even if the tab is already active, because they may
+ # have multiple tab controls
+ if (new_selection != self.GetActivePage() or isinstance(self.GetParent(), AuiNotebook)) and \
+ not self._hover_button:
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId())
+ e.SetSelection(new_selection)
+ e.SetOldSelection(self.GetActivePage())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+ self._click_pt.x = event.GetX()
+ self._click_pt.y = event.GetY()
+ self._click_tab = wnd
+
+ wnd.SetFocus()
+ else:
+ page_index = self.GetActivePage()
+ if page_index != wx.NOT_FOUND:
+ self.GetWindowFromIdx(page_index).SetFocus()
+
+ self._hover_button = self.ButtonHitTest(event.GetX(), event.GetY())
+
+ if self._hover_button:
+ self._pressed_button = self._hover_button
+ self._pressed_button.cur_state = AUI_BUTTON_STATE_PRESSED
+ self._on_button = True
+
+ self.Refresh()
+ self.Update()
+
+
+ def OnCaptureLost(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_CAPTURE_LOST`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseCaptureLostEvent` event to be processed.
+ """
+
+ if self._click_tab:
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_LEFT_UP, self.GetId())
+ e.SetEventObject(self)
+ e.SetSelection(self.GetIdxFromWindow(self._click_tab))
+ self.GetEventHandler().ProcessEvent(e)
+
+ if self._is_dragging:
+ self._is_dragging = False
+ self._on_button = False
+
+ if self._drag_image:
+ self._drag_image.EndDrag()
+ del self._drag_image
+ self._drag_image = None
+
+ event = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_CANCEL_DRAG, self.GetId())
+ event.SetSelection(self.GetIdxFromWindow(self._click_tab))
+ event.SetOldSelection(event.GetSelection())
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ if self._hover_button:
+ self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL
+ self._hover_button = None
+
+ self.Refresh()
+ self.Update()
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._click_tab:
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_LEFT_UP, self.GetId())
+ e.SetEventObject(self)
+ e.SetSelection(self.GetIdxFromWindow(self._click_tab))
+ self.GetEventHandler().ProcessEvent(e)
+ elif not self.ButtonHitTest(event.GetX(), event.GetY()):
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_LEFT_UP, self.GetId())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+ self._on_button = False
+
+ if self._is_dragging:
+
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+ self._is_dragging = False
+ if self._drag_image:
+ self._drag_image.EndDrag()
+ del self._drag_image
+ self._drag_image = None
+ self.GetParent().Refresh()
+
+ evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, self.GetId())
+ evt.SetSelection(self.GetIdxFromWindow(self._click_tab))
+ evt.SetOldSelection(evt.GetSelection())
+ evt.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(evt)
+
+ return
+
+ self.GetParent()._mgr.HideHint()
+
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+ if self._hover_button:
+ self._pressed_button = self._hover_button
+ self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL
+
+ if self._pressed_button:
+
+ # make sure we're still clicking the button
+ button = self.ButtonHitTest(event.GetX(), event.GetY())
+
+ if button is None:
+ return
+
+ if button != self._pressed_button:
+ self._pressed_button = None
+ return
+
+ self.Refresh()
+ self.Update()
+
+ if self._pressed_button.cur_state & AUI_BUTTON_STATE_DISABLED == 0:
+
+ evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, self.GetId())
+ evt.SetSelection(self.GetIdxFromWindow(self._click_tab))
+ evt.SetInt(self._pressed_button.id)
+ evt.SetEventObject(self)
+ eventHandler = self.GetEventHandler()
+
+ if eventHandler is not None:
+ eventHandler.ProcessEvent(evt)
+
+ self._pressed_button = None
+
+ self._click_pt = wx.Point(-1, -1)
+ self._is_dragging = False
+ self._click_tab = None
+
+
+ def OnMiddleUp(self, event):
+ """
+ Handles the ``wx.EVT_MIDDLE_UP`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ eventHandler = self.GetEventHandler()
+ if not isinstance(eventHandler, AuiTabCtrl):
+ event.Skip()
+ return
+
+ x, y = event.GetX(), event.GetY()
+ wnd = self.TabHitTest(x, y)
+
+ if wnd:
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, self.GetId())
+ e.SetEventObject(self)
+ e.Page = wnd
+ e.SetSelection(self.GetIdxFromWindow(wnd))
+ self.GetEventHandler().ProcessEvent(e)
+ elif not self.ButtonHitTest(x, y):
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_UP, self.GetId())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def OnMiddleDown(self, event):
+ """
+ Handles the ``wx.EVT_MIDDLE_DOWN`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.StopTooltipTimer()
+
+ eventHandler = self.GetEventHandler()
+ if not isinstance(eventHandler, AuiTabCtrl):
+ event.Skip()
+ return
+
+ x, y = event.GetX(), event.GetY()
+ wnd = self.TabHitTest(x, y)
+
+ if wnd:
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, self.GetId())
+ e.SetEventObject(self)
+ e.Page = wnd
+ e.SetSelection(self.GetIdxFromWindow(wnd))
+ self.GetEventHandler().ProcessEvent(e)
+ elif not self.ButtonHitTest(x, y):
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_DOWN, self.GetId())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def OnRightUp(self, event):
+ """
+ Handles the ``wx.EVT_RIGHT_UP`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ x, y = event.GetX(), event.GetY()
+ wnd = self.TabHitTest(x, y)
+
+ if wnd:
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, self.GetId())
+ e.SetEventObject(self)
+ e.Selection = self.GetIdxFromWindow(wnd)
+ e.Page = wnd
+ self.GetEventHandler().ProcessEvent(e)
+ elif not self.ButtonHitTest(x, y):
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_UP, self.GetId())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def OnRightDown(self, event):
+ """
+ Handles the ``wx.EVT_RIGHT_DOWN`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.StopTooltipTimer()
+
+ x, y = event.GetX(), event.GetY()
+ wnd = self.TabHitTest(x, y)
+
+ if wnd:
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, self.GetId())
+ e.SetEventObject(self)
+ e.SetSelection(self.GetIdxFromWindow(wnd))
+ e.Page = wnd
+ self.GetEventHandler().ProcessEvent(e)
+ elif not self.ButtonHitTest(x, y):
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_DOWN, self.GetId())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def OnLeftDClick(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DCLICK`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ x, y = event.GetX(), event.GetY()
+ wnd = self.TabHitTest(x, y)
+
+ if wnd:
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_DCLICK, self.GetId())
+ e.SetEventObject(self)
+ e.SetSelection(self.GetIdxFromWindow(wnd))
+ e.Page = wnd
+ self.GetEventHandler().ProcessEvent(e)
+ elif not self.ButtonHitTest(x, y, state_flags=AUI_BUTTON_STATE_HIDDEN):
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, self.GetId())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ pos = event.GetPosition()
+
+ # check if the mouse is hovering above a button
+
+ button = self.ButtonHitTest(pos.x, pos.y)
+ wnd = self.TabHitTest(pos.x, pos.y)
+
+ if wnd is not None:
+ mouse_tab = self.GetIdxFromWindow(wnd)
+ if not self._pages[mouse_tab].enabled:
+ self._hover_button = None
+ return
+
+ if self._on_button:
+ return
+
+ if button:
+
+ if self._hover_button and button != self._hover_button:
+ self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL
+ self._hover_button = None
+ self.Refresh()
+ self.Update()
+
+ if button.cur_state != AUI_BUTTON_STATE_HOVER:
+ button.cur_state = AUI_BUTTON_STATE_HOVER
+ self.Refresh()
+ self.Update()
+ self._hover_button = button
+ return
+
+ else:
+
+ if self._hover_button:
+ self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL
+ self._hover_button = None
+ self.Refresh()
+ self.Update()
+
+ if not event.LeftIsDown() or self._click_pt == wx.Point(-1, -1):
+
+ # if the mouse has moved from one tab to another then restart the
+ # tooltip timer.
+ if wnd != self._tooltip_wnd or (wnd is None and self._hover_button is not None):
+ self.RestartTooltipTimer(wnd)
+
+ return
+
+ if not self.HasCapture():
+ return
+
+ wnd = self.TabHitTest(pos.x, pos.y)
+
+ if not self._is_dragging:
+
+ drag_x_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_X)
+ drag_y_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_Y)
+
+ if abs(pos.x - self._click_pt.x) > drag_x_threshold or \
+ abs(pos.y - self._click_pt.y) > drag_y_threshold:
+
+ self._is_dragging = True
+
+ if self._drag_image:
+ self._drag_image.EndDrag()
+ del self._drag_image
+ self._drag_image = None
+
+ if self._agwFlags & AUI_NB_DRAW_DND_TAB:
+ # Create the custom draw image from the icons and the text of the item
+ mouse_tab = self.GetIdxFromWindow(wnd)
+ page = self._pages[mouse_tab]
+ tab_button = self._tab_close_buttons[mouse_tab]
+ self._drag_image = TabDragImage(self, page, tab_button.cur_state, self._art)
+
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+ if self._agwFlags & AUI_NB_TAB_FLOAT:
+ self._drag_image.BeginDrag(wx.Point(0,0), self, fullScreen=True)
+ else:
+ self._drag_image.BeginDragBounded(wx.Point(0,0), self, self.GetParent())
+
+ # Capture the mouse cursor position offset relative to
+ # The tab image location
+ self._drag_img_offset = (pos[0] - page.rect.x,
+ pos[1] - page.rect.y)
+
+ self._drag_image.Show()
+
+ if not wnd:
+ evt2 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, self.GetId())
+ evt2.SetSelection(self.GetIdxFromWindow(self._click_tab))
+ evt2.SetOldSelection(evt2.GetSelection())
+ evt2.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(evt2)
+ if evt2.GetDispatched():
+ return
+
+ evt3 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, self.GetId())
+ evt3.SetSelection(self.GetIdxFromWindow(self._click_tab))
+ evt3.SetOldSelection(evt3.GetSelection())
+ evt3.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(evt3)
+
+ if self._drag_image:
+ # Apply the drag images offset
+ pos -= self._drag_img_offset
+ self._drag_image.Move(pos)
+
+
+ def GetPointedToTab(self):
+ """
+ Returns the page at which the mouse is pointing (if any).
+
+ :rtype: :class:`Window`.
+ """
+
+ screen_pt = wx.GetMousePosition()
+ client_pt = self.ScreenToClient(screen_pt)
+ return self.TabHitTest(client_pt.x, client_pt.y)
+
+
+ def RestartTooltipTimer(self, wnd):
+ """
+ Starts a timer: when it fires, a tooltip will be shown on the notebook tab
+ the mouse is pointing at.
+
+ :param Window `wnd`: the window pointed by the mouse.
+ """
+
+ self._tooltip_wnd = wnd
+ if (wnd is None and self._hover_button is None) or not wx.GetApp().IsActive():
+ self.StopTooltipTimer()
+ elif self._tooltip_timer:
+ self._tooltip_timer.Start()
+ else:
+ self._tooltip_timer = wx.CallLater(1000, self.ShowTooltip)
+
+
+ def StopTooltipTimer(self):
+ """ Stops the timer keeping track of tooltips and mouse movements on the tab area. """
+
+ if self._tooltip_timer:
+ self._tooltip_timer.Stop()
+ self._tooltip_timer = None
+
+
+ def OnEnterWindow(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event fof :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.RestartTooltipTimer(self.GetPointedToTab())
+
+
+ def ShowTooltip(self):
+ """ Shows the tooltip on the tab. """
+
+ wnd = self.GetPointedToTab()
+ if wnd != self._tooltip_wnd:
+ self.RestartTooltipTimer(wnd)
+ else:
+ idx = self.GetIdxFromWindow(wnd)
+ if idx >= 0 and idx < len(self._pages):
+ page = self._pages[idx]
+ if page.tooltip:
+ pos = self.ClientToScreen(page.rect.GetPosition())
+ rect = wx.RectPS(pos, page.rect.GetSize())
+ tooltip = wx.TipWindow(self, page.tooltip)
+ tooltip.SetBoundingRect(rect)
+ else:
+ pos = self.ScreenToClient(wx.GetMousePosition())
+ button = self.ButtonHitTest(pos.x, pos.y)
+ if button:
+ pos = self.ClientToScreen(button.rect.GetPosition())
+ rect = wx.RectPS(pos, button.rect.GetSize())
+ tooltip = wx.TipWindow(self, button.name)
+ tooltip.SetBoundingRect(rect)
+
+
+ def OnLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.StopTooltipTimer()
+
+ if self._hover_button:
+ self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL
+ self._hover_button = None
+ self.Refresh()
+ self.Update()
+
+
+ def OnButton(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_BUTTON`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ button = event.GetInt()
+
+ if button == AUI_BUTTON_LEFT or button == AUI_BUTTON_RIGHT:
+ if button == AUI_BUTTON_LEFT:
+ if self.GetTabOffset() > 0:
+
+ self.SetTabOffset(self.GetTabOffset()-1)
+ self.Refresh()
+ self.Update()
+ else:
+ self.SetTabOffset(self.GetTabOffset()+1)
+ self.Refresh()
+ self.Update()
+
+ elif button == AUI_BUTTON_WINDOWLIST:
+ idx = self.GetArtProvider().ShowDropDown(self, self._pages, self.GetActivePage())
+
+ if idx != -1:
+
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId())
+ e.SetSelection(idx)
+ e.SetOldSelection(self.GetActivePage())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+ else:
+ event.Skip()
+
+
+ def OnSetFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self.Refresh()
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self.Refresh()
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ key = event.GetKeyCode()
+ nb = self.GetParent()
+
+ if key == wx.WXK_LEFT:
+ nb.AdvanceSelection(False)
+ self.SetFocus()
+
+ elif key == wx.WXK_RIGHT:
+ nb.AdvanceSelection(True)
+ self.SetFocus()
+
+ elif key == wx.WXK_HOME:
+ newPage = 0
+ nb.SetSelection(newPage)
+ self.SetFocus()
+
+ elif key == wx.WXK_END:
+ newPage = nb.GetPageCount() - 1
+ nb.SetSelection(newPage)
+ self.SetFocus()
+
+ elif key == wx.WXK_TAB:
+ if not event.ControlDown():
+ flags = 0
+ if not event.ShiftDown(): flags |= wx.NavigationKeyEvent.IsForward
+ if event.CmdDown(): flags |= wx.NavigationKeyEvent.WinChange
+ self.Navigate(flags)
+ else:
+
+ if not nb or not isinstance(nb, AuiNotebook):
+ event.Skip()
+ return
+
+ bForward = bWindowChange = 0
+ if not event.ShiftDown(): bForward |= wx.NavigationKeyEvent.IsForward
+ if event.CmdDown(): bWindowChange |= wx.NavigationKeyEvent.WinChange
+
+ keyEvent = wx.NavigationKeyEvent()
+ keyEvent.SetDirection(bForward)
+ keyEvent.SetWindowChange(bWindowChange)
+ keyEvent.SetFromTab(True)
+ keyEvent.SetEventObject(nb)
+
+ if not nb.GetEventHandler().ProcessEvent(keyEvent):
+
+ # Not processed? Do an explicit tab into the page.
+ win = self.GetWindowFromIdx(self.GetActivePage())
+ if win:
+ win.SetFocus()
+
+ self.SetFocus()
+
+ return
+
+ else:
+ event.Skip()
+
+
+ def OnKeyDown2(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`AuiTabCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+
+ .. deprecated:: 0.6
+ This implementation is now deprecated. Refer to :meth:`OnKeyDown` for the correct one.
+ """
+
+ if self.GetActivePage() == -1:
+ event.Skip()
+ return
+
+ # We can't leave tab processing to the system on Windows, tabs and keys
+ # get eaten by the system and not processed properly if we specify both
+ # wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
+ # we don't key arrow key events.
+
+ key = event.GetKeyCode()
+
+ if key == wx.WXK_NUMPAD_PAGEUP:
+ key = wx.WXK_PAGEUP
+ if key == wx.WXK_NUMPAD_PAGEDOWN:
+ key = wx.WXK_PAGEDOWN
+ if key == wx.WXK_NUMPAD_HOME:
+ key = wx.WXK_HOME
+ if key == wx.WXK_NUMPAD_END:
+ key = wx.WXK_END
+ if key == wx.WXK_NUMPAD_LEFT:
+ key = wx.WXK_LEFT
+ if key == wx.WXK_NUMPAD_RIGHT:
+ key = wx.WXK_RIGHT
+
+ if key == wx.WXK_TAB or key == wx.WXK_PAGEUP or key == wx.WXK_PAGEDOWN:
+
+ bCtrlDown = event.ControlDown()
+ bShiftDown = event.ShiftDown()
+
+ bForward = (key == wx.WXK_TAB and not bShiftDown) or (key == wx.WXK_PAGEDOWN)
+ bWindowChange = (key == wx.WXK_PAGEUP) or (key == wx.WXK_PAGEDOWN) or bCtrlDown
+ bFromTab = (key == wx.WXK_TAB)
+
+ nb = self.GetParent()
+ if not nb or not isinstance(nb, AuiNotebook):
+ event.Skip()
+ return
+
+ keyEvent = wx.NavigationKeyEvent()
+ keyEvent.SetDirection(bForward)
+ keyEvent.SetWindowChange(bWindowChange)
+ keyEvent.SetFromTab(bFromTab)
+ keyEvent.SetEventObject(nb)
+
+ if not nb.GetEventHandler().ProcessEvent(keyEvent):
+
+ # Not processed? Do an explicit tab into the page.
+ win = self.GetWindowFromIdx(self.GetActivePage())
+ if win:
+ win.SetFocus()
+
+ return
+
+ if len(self._pages) < 2:
+ event.Skip()
+ return
+
+ newPage = -1
+
+ if self.GetLayoutDirection() == wx.Layout_RightToLeft:
+ forwardKey = wx.WXK_LEFT
+ backwardKey = wx.WXK_RIGHT
+ else:
+ forwardKey = wx.WXK_RIGHT
+ backwardKey = wx.WXK_LEFT
+
+ if key == forwardKey:
+ if self.GetActivePage() == -1:
+ newPage = 0
+ elif self.GetActivePage() < len(self._pages) - 1:
+ newPage = self.GetActivePage() + 1
+
+ elif key == backwardKey:
+ if self.GetActivePage() == -1:
+ newPage = len(self._pages) - 1
+ elif self.GetActivePage() > 0:
+ newPage = self.GetActivePage() - 1
+
+ elif key == wx.WXK_HOME:
+ newPage = 0
+
+ elif key == wx.WXK_END:
+ newPage = len(self._pages) - 1
+
+ else:
+ event.Skip()
+
+ if newPage != -1:
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId())
+ e.SetSelection(newPage)
+ e.SetOldSelection(newPage)
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+ else:
+ event.Skip()
+
+
+# ----------------------------------------------------------------------
+
+class TabFrame(wx.PyWindow):
+ """
+ TabFrame is an interesting case. It's important that all child pages
+ of the multi-notebook control are all actually children of that control
+ (and not grandchildren). TabFrame facilitates this. There is one
+ instance of TabFrame for each tab control inside the multi-notebook.
+
+ It's important to know that TabFrame is not a real window, but it merely
+ used to capture the dimensions/positioning of the internal tab control and
+ it's managed page windows.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+ Used internally, do not call it in your code!
+ """
+
+ pre = wx.PrePyWindow()
+
+ self._tabs = None
+ self._rect = wx.Rect(0, 0, 200, 200)
+ self._tab_ctrl_height = 20
+ self._tab_rect = wx.Rect()
+ self._parent = parent
+
+ self.PostCreate(pre)
+
+
+ def SetTabCtrlHeight(self, h):
+ """
+ Sets the tab control height.
+
+ :param integer `h`: the tab area height.
+ """
+
+ self._tab_ctrl_height = h
+
+
+ def DoSetSize(self, x, y, width, height, flags=wx.SIZE_AUTO):
+ """
+ Sets the position and size of the window in pixels. The `flags`
+ parameter indicates the interpretation of the other params if they are
+ equal to -1.
+
+ :param integer `x`: the window `x` position;
+ :param integer `y`: the window `y` position;
+ :param integer `width`: the window width;
+ :param integer `height`: the window height;
+ :param integer `flags`: may have one of this bit set:
+
+ =================================== ======================================
+ Size Flags Description
+ =================================== ======================================
+ ``wx.SIZE_AUTO`` A -1 indicates that a class-specific default should be used.
+ ``wx.SIZE_AUTO_WIDTH`` A -1 indicates that a class-specific default should be used for the width.
+ ``wx.SIZE_AUTO_HEIGHT`` A -1 indicates that a class-specific default should be used for the height.
+ ``wx.SIZE_USE_EXISTING`` Existing dimensions should be used if -1 values are supplied.
+ ``wx.SIZE_ALLOW_MINUS_ONE`` Allow dimensions of -1 and less to be interpreted as real dimensions, not default values.
+ ``wx.SIZE_FORCE`` Normally, if the position and the size of the window are already the same as the
+ parameters of this function, nothing is done. but with this flag a window resize
+ may be forced even in this case (supported in wx 2.6.2 and later and only implemented
+ for MSW and ignored elsewhere currently)
+ =================================== ======================================
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ self._rect = wx.Rect(x, y, max(1, width), max(1, height))
+ self.DoSizing()
+
+
+ def DoGetSize(self):
+ """
+ Returns the window size.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._rect.width, self._rect.height
+
+
+ def DoGetClientSize(self):
+ """
+ Returns the window client size.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._rect.width, self._rect.height
+
+
+ def Show(self, show=True):
+ """
+ Shows/hides the window.
+
+ :param bool `show`: ``True`` to show the window, ``False`` otherwise.
+
+ :note:
+
+ Overridden from :class:`PyControl`, this method always returns ``False`` as
+ :class:`TabFrame` should never be phisically shown on screen.
+ """
+
+ return False
+
+
+ def DoSizing(self):
+ """ Does the actual sizing of the tab control. """
+
+ if not self._tabs:
+ return
+
+ hideOnSingle = ((self._tabs.GetAGWFlags() & AUI_NB_HIDE_ON_SINGLE_TAB) and \
+ self._tabs.GetPageCount() <= 1)
+
+ if not hideOnSingle and not self._parent._hide_tabs:
+ tab_height = self._tab_ctrl_height
+
+ self._tab_rect = wx.Rect(self._rect.x, self._rect.y, self._rect.width, self._tab_ctrl_height)
+
+ if self._tabs.GetAGWFlags() & AUI_NB_BOTTOM:
+ self._tab_rect = wx.Rect(self._rect.x, self._rect.y + self._rect.height - tab_height,
+ self._rect.width, tab_height)
+ self._tabs.SetDimensions(self._rect.x, self._rect.y + self._rect.height - tab_height,
+ self._rect.width, tab_height)
+ self._tabs.SetTabRect(wx.Rect(0, 0, self._rect.width, tab_height))
+
+ else:
+
+ self._tab_rect = wx.Rect(self._rect.x, self._rect.y, self._rect.width, tab_height)
+ self._tabs.SetDimensions(self._rect.x, self._rect.y, self._rect.width, tab_height)
+ self._tabs.SetTabRect(wx.Rect(0, 0, self._rect.width, tab_height))
+
+ # TODO: elif (GetAGWFlags() & AUI_NB_LEFT)
+ # TODO: elif (GetAGWFlags() & AUI_NB_RIGHT)
+
+ self._tabs.Refresh()
+ self._tabs.Update()
+
+ else:
+
+ tab_height = 0
+ self._tabs.SetDimensions(self._rect.x, self._rect.y, self._rect.width, tab_height)
+ self._tabs.SetTabRect(wx.Rect(0, 0, self._rect.width, tab_height))
+
+ pages = self._tabs.GetPages()
+
+ for page in pages:
+
+ height = self._rect.height - tab_height
+
+ if height < 0:
+ # avoid passing negative height to wx.Window.SetSize(), this
+ # results in assert failures/GTK+ warnings
+ height = 0
+
+ if self._tabs.GetAGWFlags() & AUI_NB_BOTTOM:
+ page.window.SetDimensions(self._rect.x, self._rect.y, self._rect.width, height)
+
+ else:
+ page.window.SetDimensions(self._rect.x, self._rect.y + tab_height,
+ self._rect.width, height)
+
+ # TODO: elif (GetAGWFlags() & AUI_NB_LEFT)
+ # TODO: elif (GetAGWFlags() & AUI_NB_RIGHT)
+
+ if repr(page.window.__class__).find("AuiMDIChildFrame") >= 0:
+ page.window.ApplyMDIChildFrameRect()
+
+
+ def Update(self):
+ """
+ Calling this method immediately repaints the invalidated area of the window
+ and all of its children recursively while this would usually only happen when
+ the flow of control returns to the event loop.
+
+ :note: Notice that this function doesn't invalidate any area of the window so
+ nothing happens if nothing has been invalidated (i.e. marked as requiring a redraw).
+ Use `Refresh` first if you want to immediately redraw the window unconditionally.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ # does nothing
+ pass
+
+
+# ----------------------------------------------------------------------
+# -- AuiNotebook class implementation --
+
+class AuiNotebook(wx.PyPanel):
+ """
+ AuiNotebook is a notebook control which implements many features common in applications with dockable panes.
+ Specifically, AuiNotebook implements functionality which allows the user to rearrange tab
+ order via drag-and-drop, split the tab window into many different splitter configurations, and toggle
+ through different themes to customize the control's look and feel.
+
+ An effort has been made to try to maintain an API as similar to that of :class:`Notebook`.
+
+ The default theme that is used is :class:`~lib.agw.aui.tabart.AuiDefaultTabArt`, which provides a modern, glossy
+ look and feel. The theme can be changed by calling :meth:`AuiNotebook.SetArtProvider`.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=AUI_NB_DEFAULT_STYLE, name="AuiNotebook"):
+ """
+ Default class constructor.
+
+ :param Window `parent`: the :class:`AuiNotebook` parent;
+ :param integer `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param Point `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param Size `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param integer `style`: the underlying :class:`PyPanel` window style;
+ :param integer `agwStyle`: the AGW-specific window style. This can be a combination of the following bits:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook
+ ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet.
+ ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet.
+ ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook
+ ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab
+ ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging
+ ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control
+ ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width
+ ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed
+ ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available
+ ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar
+ ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab
+ ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs
+ ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close :class:`AuiNotebook` tabs by mouse middle button click
+ ``AUI_NB_SUB_NOTEBOOK`` This style is used by :class:`~lib.agw.aui.framemanager.AuiManager` to create automatic AuiNotebooks
+ ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present
+ ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
+ ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items
+ ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser)
+ ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen,
+ tabs cannot be dragged far enough outside of the notebook to become floating pages
+ ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default)
+ ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs
+ ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle
+ ==================================== ==================================
+
+ Default value for `agwStyle` is:
+ ``AUI_NB_DEFAULT_STYLE`` = ``AUI_NB_TOP`` | ``AUI_NB_TAB_SPLIT`` | ``AUI_NB_TAB_MOVE`` | ``AUI_NB_SCROLL_BUTTONS`` | ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` | ``AUI_NB_MIDDLE_CLICK_CLOSE`` | ``AUI_NB_DRAW_DND_TAB``
+
+ :param string `name`: the window name.
+ """
+
+ self._curpage = -1
+ self._tab_id_counter = AuiBaseTabCtrlId
+ self._dummy_wnd = None
+ self._hide_tabs = False
+ self._sash_dclick_unsplit = False
+ self._tab_ctrl_height = 20
+ self._requested_bmp_size = wx.Size(-1, -1)
+ self._requested_tabctrl_height = -1
+ self._textCtrl = None
+ self._tabBounds = (-1, -1)
+
+ wx.PyPanel.__init__(self, parent, id, pos, size, style|wx.BORDER_NONE|wx.TAB_TRAVERSAL, name=name)
+ self._mgr = framemanager.AuiManager()
+ self._tabs = AuiTabContainer(self)
+
+ self.InitNotebook(agwStyle)
+
+ NavigatorProps = property(lambda self: self._navProps)
+
+
+ def Destroy(self):
+ """
+ Destroys the window safely.
+
+ Use this function instead of the ``del`` operator, since different window
+ classes can be destroyed differently. Frames and dialogs are not destroyed
+ immediately when this function is called -- they are added to a list of
+ windows to be deleted on idle time, when all the window's events have been
+ processed. This prevents problems with events being sent to non-existent windows.
+
+ :return: ``True`` if the window has either been successfully deleted, or
+ it has been added to the list of windows pending real deletion.
+
+ .. note::
+
+ This method has been added to safely un-initialize the underlying
+ :class:`~lib.agw.aui.framemanager.AuiManager` which manages the :class:`AuiNotebook`
+ layout (i.e., tab split, re-ordering, tab floating etc...).
+
+ """
+
+ self._mgr.UnInit()
+ return wx.PyPanel.Destroy(self)
+
+
+ def __getitem__(self, index):
+ """
+ More Pythonic way to get a specific page, also useful for iterating
+ over all pages.
+
+ :param integer `index`: the page index.
+
+ .. note::
+
+ This method makes easier to iterate over all the pages in the notebook, i.e. you can
+ safely do::
+
+ for page in notebook:
+ DoSomething(page)
+
+
+ """
+
+ if index < self.GetPageCount():
+ return self.GetPage(index)
+ else:
+ raise IndexError("Invalid page index")
+
+
+ def GetTabContainer(self):
+ """ Returns the instance of :class:`AuiTabContainer`. """
+
+ return self._tabs
+
+
+ def InitNotebook(self, agwStyle):
+ """
+ Contains common initialization code called by all constructors.
+
+ :param integer `agwStyle`: the notebook style.
+
+ :see: :meth:`~AuiNotebook.__init__` for a list of available `agwStyle` bits.
+ """
+
+ self._agwFlags = agwStyle
+
+ self._popupWin = None
+ self._imageList = None
+ self._navProps = TabNavigatorProps()
+ self._last_drag_x = 0
+
+ self._normal_font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._selected_font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._selected_font.SetWeight(wx.BOLD)
+
+ self.SetArtProvider(TA.AuiDefaultTabArt())
+
+ self._dummy_wnd = wx.Window(self, wx.ID_ANY, wx.Point(0, 0), wx.Size(0, 0))
+ self._dummy_wnd.SetSize((200, 200))
+ self._dummy_wnd.Show(False)
+
+ self._mgr.SetManagedWindow(self)
+ self._mgr.SetAGWFlags(AUI_MGR_DEFAULT)
+ self._mgr.SetDockSizeConstraint(1.0, 1.0) # no dock size constraint
+
+ self._mgr.AddPane(self._dummy_wnd, framemanager.AuiPaneInfo().Name("dummy").Bottom().CaptionVisible(False).Show(False))
+ self._mgr.Update()
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocusNotebook)
+ self.Bind(EVT_AUINOTEBOOK_PAGE_CHANGING, self.OnTabClicked,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_BEGIN_DRAG, self.OnTabBeginDrag,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_END_DRAG, self.OnTabEndDrag,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_DRAG_MOTION, self.OnTabDragMotion,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_CANCEL_DRAG, self.OnTabCancelDrag,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_BUTTON, self.OnTabButton,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, self.OnTabMiddleDown,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_TAB_MIDDLE_UP, self.OnTabMiddleUp,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_TAB_RIGHT_DOWN, self.OnTabRightDown,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_TAB_RIGHT_UP, self.OnTabRightUp,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_BG_DCLICK, self.OnTabBgDClick,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+ self.Bind(EVT_AUINOTEBOOK_TAB_DCLICK, self.OnTabDClick,
+ id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
+
+ self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKeyNotebook)
+
+
+ def SetArtProvider(self, art):
+ """
+ Sets the art provider to be used by the notebook.
+
+ :param `art`: an art provider.
+ """
+
+ self._tabs.SetArtProvider(art)
+ self.UpdateTabCtrlHeight(force=True)
+
+
+ def SavePerspective(self):
+ """
+ Saves the entire user interface layout into an encoded string, which can then
+ be stored by the application (probably using :class:`Config`). When a perspective
+ is restored using :meth:`LoadPerspective`, the entire user interface will return
+ to the state it was when the perspective was saved.
+ """
+
+ # Build list of panes/tabs
+ tabs = ""
+ all_panes = self._mgr.GetAllPanes()
+
+ for pane in all_panes:
+
+ if pane.name == "dummy":
+ continue
+
+ tabframe = pane.window
+
+ if tabs:
+ tabs += "|"
+
+ tabs += pane.name + "="
+
+ # add tab id's
+ page_count = tabframe._tabs.GetPageCount()
+
+ for p in xrange(page_count):
+
+ page = tabframe._tabs.GetPage(p)
+ page_idx = self._tabs.GetIdxFromWindow(page.window)
+
+ if p:
+ tabs += ","
+
+ if p == tabframe._tabs.GetActivePage():
+ tabs += "+"
+ elif page_idx == self._curpage:
+ tabs += "*"
+
+ tabs += "%u"%page_idx
+
+ tabs += "@"
+
+ # Add frame perspective
+ tabs += self._mgr.SavePerspective()
+
+ return tabs
+
+
+ def LoadPerspective(self, layout):
+ """
+ Loads a layout which was saved with :meth:`SavePerspective`.
+
+ :param string `layout`: a string which contains a saved :class:`AuiNotebook` layout.
+ """
+
+ # Remove all tab ctrls (but still keep them in main index)
+ tab_count = self._tabs.GetPageCount()
+ for i in xrange(tab_count):
+ wnd = self._tabs.GetWindowFromIdx(i)
+
+ # find out which onscreen tab ctrl owns this tab
+ ctrl, ctrl_idx = self.FindTab(wnd)
+ if not ctrl:
+ return False
+
+ # remove the tab from ctrl
+ if not ctrl.RemovePage(wnd):
+ return False
+
+ self.RemoveEmptyTabFrames()
+
+ sel_page = 0
+ tabs = layout[0:layout.index("@")]
+ to_break1 = False
+
+ while 1:
+
+ if "|" not in tabs:
+ to_break1 = True
+ tab_part = tabs
+ else:
+ tab_part = tabs[0:tabs.index('|')]
+
+ if "=" not in tab_part:
+ # No pages in this perspective...
+ return False
+
+ # Get pane name
+ pane_name = tab_part[0:tab_part.index("=")]
+
+ # create a new tab frame
+ new_tabs = TabFrame(self)
+ self._tab_id_counter += 1
+ new_tabs._tabs = AuiTabCtrl(self, self._tab_id_counter)
+ new_tabs._tabs.SetArtProvider(self._tabs.GetArtProvider().Clone())
+ new_tabs.SetTabCtrlHeight(self._tab_ctrl_height)
+ new_tabs._tabs.SetAGWFlags(self._agwFlags)
+ dest_tabs = new_tabs._tabs
+
+ # create a pane info structure with the information
+ # about where the pane should be added
+ pane_info = framemanager.AuiPaneInfo().Name(pane_name).Bottom().CaptionVisible(False)
+ self._mgr.AddPane(new_tabs, pane_info)
+
+ # Get list of tab id's and move them to pane
+ tab_list = tab_part[tab_part.index("=")+1:]
+ to_break2, active_found = False, False
+
+ while 1:
+ if "," not in tab_list:
+ to_break2 = True
+ tab = tab_list
+ else:
+ tab = tab_list[0:tab_list.index(",")]
+ tab_list = tab_list[tab_list.index(",")+1:]
+
+ # Check if this page has an 'active' marker
+ c = tab[0]
+ if c in ['+', '*']:
+ tab = tab[1:]
+
+ tab_idx = int(tab)
+ if tab_idx >= self.GetPageCount():
+ to_break1 = True
+ break
+
+ # Move tab to pane
+ page = self._tabs.GetPage(tab_idx)
+ newpage_idx = dest_tabs.GetPageCount()
+ dest_tabs.InsertPage(page.window, page, newpage_idx)
+
+ if c == '+':
+ dest_tabs.SetActivePage(newpage_idx)
+ active_found = True
+ elif c == '*':
+ sel_page = tab_idx
+
+ if to_break2:
+ break
+
+ if not active_found:
+ dest_tabs.SetActivePage(0)
+
+ new_tabs.DoSizing()
+ dest_tabs.DoShowHide()
+ dest_tabs.Refresh()
+
+ if to_break1:
+ break
+
+ tabs = tabs[tabs.index('|')+1:]
+
+ # Load the frame perspective
+ frames = layout[layout.index('@')+1:]
+ self._mgr.LoadPerspective(frames)
+
+ # Force refresh of selection
+ self._curpage = -1
+ self.SetSelection(sel_page)
+
+ return True
+
+
+ def SetTabCtrlHeight(self, height):
+ """
+ Sets the tab height.
+
+ By default, the tab control height is calculated by measuring the text
+ height and bitmap sizes on the tab captions.
+
+ Calling this method will override that calculation and set the tab control
+ to the specified height parameter. A call to this method will override
+ any call to :meth:`SetUniformBitmapSize`. Specifying -1 as the height will
+ return the control to its default auto-sizing behaviour.
+
+ :param integer `height`: the tab control area height.
+ """
+
+ self._requested_tabctrl_height = height
+
+ # if window is already initialized, recalculate the tab height
+ if self._dummy_wnd:
+ self.UpdateTabCtrlHeight()
+
+
+ def SetUniformBitmapSize(self, size):
+ """
+ Ensures that all tabs will have the same height, even if some tabs don't have bitmaps.
+ Passing ``wx.DefaultSize`` to this method will instruct the control to use dynamic tab
+ height, which is the default behaviour. Under the default behaviour, when a tab with a
+ large bitmap is added, the tab control's height will automatically increase to accommodate
+ the larger bitmap.
+
+ :param Size `size`: the tab bitmap size.
+ """
+
+ self._requested_bmp_size = wx.Size(*size)
+
+ # if window is already initialized, recalculate the tab height
+ if self._dummy_wnd:
+ self.UpdateTabCtrlHeight()
+
+
+ def UpdateTabCtrlHeight(self, force=False):
+ """
+ :meth:`UpdateTabCtrlHeight` does the actual tab resizing. It's meant
+ to be used interally.
+
+ :param bool `force`: ``True`` to force the tab art to repaint.
+ """
+
+ # get the tab ctrl height we will use
+ height = self.CalculateTabCtrlHeight()
+
+ # if the tab control height needs to change, update
+ # all of our tab controls with the new height
+ if self._tab_ctrl_height != height or force:
+ art = self._tabs.GetArtProvider()
+
+ self._tab_ctrl_height = height
+
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+
+ if pane.name == "dummy":
+ continue
+
+ tab_frame = pane.window
+ tabctrl = tab_frame._tabs
+ tab_frame.SetTabCtrlHeight(self._tab_ctrl_height)
+ tabctrl.SetArtProvider(art.Clone())
+ tab_frame.DoSizing()
+
+
+ def UpdateHintWindowSize(self):
+ """ Updates the :class:`~lib.agw.aui.framemanager.AuiManager` hint window size. """
+
+ size = self.CalculateNewSplitSize()
+
+ # the placeholder hint window should be set to this size
+ info = self._mgr.GetPane("dummy")
+
+ if info.IsOk():
+ info.MinSize(size)
+ info.BestSize(size)
+ self._dummy_wnd.SetSize(size)
+
+
+ def CalculateNewSplitSize(self):
+ """ Calculates the size of the new split. """
+
+ # count number of tab controls
+ tab_ctrl_count = 0
+ all_panes = self._mgr.GetAllPanes()
+
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+
+ tab_ctrl_count += 1
+
+ # if there is only one tab control, the first split
+ # should happen around the middle
+ if tab_ctrl_count < 2:
+ new_split_size = self.GetClientSize()
+ new_split_size.x /= 2
+ new_split_size.y /= 2
+
+ else:
+
+ # this is in place of a more complicated calculation
+ # that needs to be implemented
+ new_split_size = wx.Size(180, 180)
+
+ return new_split_size
+
+
+ def CalculateTabCtrlHeight(self):
+ """ Calculates the tab control area height. """
+
+ # if a fixed tab ctrl height is specified,
+ # just return that instead of calculating a
+ # tab height
+ if self._requested_tabctrl_height != -1:
+ return self._requested_tabctrl_height
+
+ # find out new best tab height
+ art = self._tabs.GetArtProvider()
+
+ return art.GetBestTabCtrlSize(self, self._tabs.GetPages(), self._requested_bmp_size)
+
+
+ def GetArtProvider(self):
+ """ Returns the associated art provider. """
+
+ return self._tabs.GetArtProvider()
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the AGW-specific style of the window.
+
+ :param integer `agwStyle`: the new window style. This can be a combination of the following bits:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook
+ ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet.
+ ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet.
+ ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook
+ ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab
+ ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging
+ ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control
+ ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width
+ ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed
+ ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available
+ ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar
+ ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab
+ ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs
+ ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close :class:`AuiNotebook` tabs by mouse middle button click
+ ``AUI_NB_SUB_NOTEBOOK`` This style is used by :class:`~lib.agw.aui.framemanager.AuiManager` to create automatic AuiNotebooks
+ ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present
+ ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
+ ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items
+ ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser)
+ ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen,
+ tabs cannot be dragged far enough outside of the notebook to become floating pages
+ ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default)
+ ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs
+ ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle
+ ==================================== ==================================
+
+ :note: Please note that some styles cannot be changed after the window
+ creation and that `Refresh` might need to be be called after changing the
+ others for the change to take place immediately.
+
+ .. todo:: Implementation of flags ``AUI_NB_RIGHT`` and ``AUI_NB_LEFT``.
+ """
+
+ self._agwFlags = agwStyle
+
+ # if the control is already initialized
+ if self._mgr.GetManagedWindow() == self:
+
+ # let all of the tab children know about the new style
+
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+
+ tabframe = pane.window
+ tabctrl = tabframe._tabs
+ tabctrl.SetAGWFlags(self._agwFlags)
+ tabframe.DoSizing()
+ tabctrl.Refresh()
+ tabctrl.Update()
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the AGW-specific style of the window.
+
+ :see: :meth:`SetAGWWindowStyleFlag` for a list of possible AGW-specific window styles.
+ """
+
+ return self._agwFlags
+
+
+ def AddPage(self, page, caption, select=False, bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap, control=None, tooltip=""):
+ """
+ Adds a page. If the `select` parameter is ``True``, calling this will generate a
+ page change event.
+
+ :param Window `page`: the page to be added;
+ :param string `caption`: specifies the text for the new page;
+ :param bool `select`: specifies whether the page should be selected;
+ :param Bitmap `bitmap`: the bitmap to display in the enabled tab;
+ :param Bitmap `disabled_bitmap`: the bitmap to display in the disabled tab;
+ :param Window `control`: almost any :class:`Window` -derived instance to be located
+ inside a tab;
+ :param string `tooltip`: the tooltip to display when the mouse hovers over the tab.
+ """
+
+ return self.InsertPage(self.GetPageCount(), page, caption, select, bitmap, disabled_bitmap, control, tooltip)
+
+
+ def InsertPage(self, page_idx, page, caption, select=False, bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap,
+ control=None, tooltip=""):
+ """
+ This is similar to :meth:`AddPage`, but allows the ability to specify the insert location.
+
+ :param integer `page_idx`: specifies the position for the new page;
+ :param Window `page`: the page to be added;
+ :param string `caption`: specifies the text for the new page;
+ :param bool `select`: specifies whether the page should be selected;
+ :param Bitmap `bitmap`: the bitmap to display in the enabled tab;
+ :param Bitmap `disabled_bitmap`: the bitmap to display in the disabled tab;
+ :param Window `control`: almost any :class:`Window` -derived instance to be located
+ inside a ;
+ :param string `tooltip`: the tooltip to display when the mouse hovers over the tab.
+ """
+
+ if not page:
+ return False
+
+ page.Reparent(self)
+ info = AuiNotebookPage()
+ info.window = page
+ info.caption = caption
+ info.bitmap = bitmap
+ info.active = False
+ info.control = control
+ info.tooltip = tooltip
+
+ originalPaneMgr = framemanager.GetManager(page)
+ if originalPaneMgr:
+ originalPane = originalPaneMgr.GetPane(page)
+
+ if originalPane:
+ info.hasCloseButton = originalPane.HasCloseButton()
+
+ if bitmap.IsOk() and not disabled_bitmap.IsOk():
+ disabled_bitmap = MakeDisabledBitmap(bitmap)
+
+ info.dis_bitmap = disabled_bitmap
+
+ # if there are currently no tabs, the first added
+ # tab must be active
+ if self._tabs.GetPageCount() == 0:
+ info.active = True
+
+ self._tabs.InsertPage(page, info, page_idx)
+
+ # if that was the first page added, even if
+ # select is False, it must become the "current page"
+ # (though no select events will be fired)
+ if not select and self._tabs.GetPageCount() == 1:
+ select = True
+
+ active_tabctrl = self.GetActiveTabCtrl()
+ if page_idx >= active_tabctrl.GetPageCount():
+ active_tabctrl.AddPage(page, info)
+ else:
+ active_tabctrl.InsertPage(page, info, page_idx)
+
+ force = False
+ if control:
+ force = True
+ control.Reparent(active_tabctrl)
+ control.Show()
+
+ self.UpdateTabCtrlHeight(force=force)
+ self.DoSizing()
+ active_tabctrl.DoShowHide()
+
+ # adjust selected index
+ if self._curpage >= page_idx:
+ self._curpage += 1
+
+ if select:
+ self.SetSelectionToWindow(page)
+
+ return True
+
+
+ def DeletePage(self, page_idx):
+ """
+ Deletes a page at the given index. Calling this method will generate a page
+ change event.
+
+ :param integer `page_idx`: the page index to be deleted.
+
+ :note:
+
+ :meth:`DeletePage` removes a tab from the multi-notebook, and destroys the window as well.
+
+ :see: :meth:`RemovePage`
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ wnd = self._tabs.GetWindowFromIdx(page_idx)
+ # hide the window in advance, as this will
+ # prevent flicker
+ wnd.Show(False)
+
+ self.RemoveControlFromPage(page_idx)
+
+ if not self.RemovePage(page_idx):
+ return False
+
+ wnd.Destroy()
+
+ return True
+
+
+ def RemovePage(self, page_idx):
+ """
+ Removes a page, without deleting the window pointer.
+
+ :param integer `page_idx`: the page index to be removed.
+
+ :note:
+
+ :meth:`RemovePage` removes a tab from the multi-notebook, but does not destroy the window.
+
+ :see: :meth:`DeletePage`
+ """
+
+ # save active window pointer
+ active_wnd = None
+ if self._curpage >= 0:
+ active_wnd = self._tabs.GetWindowFromIdx(self._curpage)
+
+ # save pointer of window being deleted
+ wnd = self._tabs.GetWindowFromIdx(page_idx)
+ new_active = None
+
+ # make sure we found the page
+ if not wnd:
+ return False
+
+ # find out which onscreen tab ctrl owns this tab
+ ctrl, ctrl_idx = self.FindTab(wnd)
+ if not ctrl:
+ return False
+
+ currentPage = ctrl.GetPage(ctrl_idx)
+ is_curpage = (self._curpage == page_idx)
+ is_active_in_split = currentPage.active
+
+ # remove the tab from main catalog
+ if not self._tabs.RemovePage(wnd):
+ return False
+
+ # remove the tab from the onscreen tab ctrl
+ ctrl.RemovePage(wnd)
+
+ if is_active_in_split:
+
+ ctrl_new_page_count = ctrl.GetPageCount()
+
+ if ctrl_idx >= ctrl_new_page_count:
+ ctrl_idx = ctrl_new_page_count - 1
+
+ if ctrl_idx >= 0 and ctrl_idx < ctrl.GetPageCount():
+
+ ctrl_idx = self.FindNextActiveTab(ctrl_idx, ctrl)
+
+ # set new page as active in the tab split
+ ctrl.SetActivePage(ctrl_idx)
+
+ # if the page deleted was the current page for the
+ # entire tab control, then record the window
+ # pointer of the new active page for activation
+ if is_curpage:
+ new_active = ctrl.GetWindowFromIdx(ctrl_idx)
+
+ else:
+
+ # we are not deleting the active page, so keep it the same
+ new_active = active_wnd
+
+ if not new_active:
+
+ # we haven't yet found a new page to active,
+ # so select the next page from the main tab
+ # catalogue
+
+ if 0 <= page_idx < self._tabs.GetPageCount():
+ new_active = self._tabs.GetPage(page_idx).window
+ if not new_active and self._tabs.GetPageCount() > 0:
+ new_active = self._tabs.GetPage(0).window
+
+ self.RemoveEmptyTabFrames()
+
+ # set new active pane
+ if new_active:
+ if not self.IsBeingDeleted():
+ self._curpage = -1
+ self.SetSelectionToWindow(new_active)
+ else:
+ self._curpage = -1
+ self._tabs.SetNoneActive()
+
+ return True
+
+
+ def FindNextActiveTab(self, ctrl_idx, ctrl):
+ """
+ Finds the next active tab (used mainly when :class:`AuiNotebook` has inactive/disabled
+ tabs in it).
+
+ :param integer `ctrl_idx`: the index of the first (most obvious) tab to check for active status;
+ :param `ctrl`: an instance of :class:`AuiTabCtrl`.
+ """
+
+ if self.GetEnabled(ctrl_idx):
+ return ctrl_idx
+
+ for indx in xrange(ctrl_idx, ctrl.GetPageCount()):
+ if self.GetEnabled(indx):
+ return indx
+
+ for indx in xrange(ctrl_idx, -1, -1):
+ if self.GetEnabled(indx):
+ return indx
+
+ return 0
+
+
+ def HideAllTabs(self, hidden=True):
+ """
+ Hides all tabs on the :class:`AuiNotebook` control.
+
+ :param bool `hidden`: if ``True`` hides all tabs.
+ """
+
+ self._hide_tabs = hidden
+
+
+ def SetSashDClickUnsplit(self, unsplit=True):
+ """
+ Sets whether to unsplit a splitted :class:`AuiNotebook` when double-clicking on a sash.
+
+ :param bool `unsplit`: ``True`` to unsplit on sash double-clicking, ``False`` otherwise.
+ """
+
+ self._sash_dclick_unsplit = unsplit
+
+
+ def GetSashDClickUnsplit(self):
+ """
+ Returns whether a splitted :class:`AuiNotebook` can be unsplitted by double-clicking
+ on the splitter sash.
+ """
+
+ return self._sash_dclick_unsplit
+
+
+ def SetMinMaxTabWidth(self, minTabWidth, maxTabWidth):
+ """
+ Sets the minimum and/or the maximum tab widths for :class:`AuiNotebook` when the
+ ``AUI_NB_TAB_FIXED_WIDTH`` style is defined.
+
+ Pass -1 to either `minTabWidth` or `maxTabWidth` to reset to the default tab
+ width behaviour for :class:`AuiNotebook`.
+
+ :param integer `minTabWidth`: the minimum allowed tab width, in pixels;
+ :param integer `maxTabWidth`: the maximum allowed tab width, in pixels.
+
+ :note: Minimum and maximum tabs widths are used only when the ``AUI_NB_TAB_FIXED_WIDTH``
+ style is present.
+ """
+
+ if minTabWidth > maxTabWidth:
+ raise Exception("Minimum tab width must be less or equal than maximum tab width")
+
+ self._tabBounds = (minTabWidth, maxTabWidth)
+ self.SetAGWWindowStyleFlag(self._agwFlags)
+
+
+ def GetMinMaxTabWidth(self):
+ """
+ Returns the minimum and the maximum tab widths for :class:`AuiNotebook` when the
+ ``AUI_NB_TAB_FIXED_WIDTH`` style is defined.
+
+ :note: Minimum and maximum tabs widths are used only when the ``AUI_NB_TAB_FIXED_WIDTH``
+ style is present.
+
+ :see: :meth:`SetMinMaxTabWidth` for more information.
+ """
+
+ return self._tabBounds
+
+
+ def GetPageIndex(self, page_wnd):
+ """
+ Returns the page index for the specified window. If the window is not
+ found in the notebook, ``wx.NOT_FOUND`` is returned.
+
+ :param Window `page_wnd`: the window we are looking for.
+ """
+
+ return self._tabs.GetIdxFromWindow(page_wnd)
+
+
+ def SetPageText(self, page_idx, text):
+ """
+ Sets the tab label for the page.
+
+ :param integer `page_idx`: the page index;
+ :param string `text`: the new tab label.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ # update our own tab catalog
+ page_info = self._tabs.GetPage(page_idx)
+ should_refresh = page_info.caption != text
+ page_info.caption = text
+
+ # update what's on screen
+ ctrl, ctrl_idx = self.FindTab(page_info.window)
+ if not ctrl:
+ return False
+
+ info = ctrl.GetPage(ctrl_idx)
+ should_refresh = should_refresh or info.caption != text
+ info.caption = text
+
+ if should_refresh:
+ ctrl.Refresh()
+ ctrl.Update()
+
+ self.UpdateTabCtrlHeight(force=True)
+
+ return True
+
+
+ def GetPageText(self, page_idx):
+ """
+ Returns the tab label for the page.
+
+ :param integer `page_idx`: the page index.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return ""
+
+ # update our own tab catalog
+ page_info = self._tabs.GetPage(page_idx)
+ return page_info.caption
+
+
+ def SetPageBitmap(self, page_idx, bitmap):
+ """
+ Sets the tab bitmap for the page.
+
+ :param integer `page_idx`: the page index;
+ :param Bitmap `bitmap`: the bitmap to display on the page tab.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ # update our own tab catalog
+ page_info = self._tabs.GetPage(page_idx)
+ should_refresh = page_info.bitmap is not bitmap
+ page_info.bitmap = bitmap
+ if bitmap.IsOk() and not page_info.dis_bitmap.IsOk():
+ page_info.dis_bitmap = MakeDisabledBitmap(bitmap)
+
+ # tab height might have changed
+ self.UpdateTabCtrlHeight()
+
+ # update what's on screen
+ ctrl, ctrl_idx = self.FindTab(page_info.window)
+ if not ctrl:
+ return False
+
+ info = ctrl.GetPage(ctrl_idx)
+ should_refresh = should_refresh or info.bitmap is not bitmap
+ info.bitmap = bitmap
+ info.dis_bitmap = page_info.dis_bitmap
+ if should_refresh:
+ ctrl.Refresh()
+ ctrl.Update()
+
+ return True
+
+
+ def GetPageBitmap(self, page_idx):
+ """
+ Returns the tab bitmap for the page.
+
+ :param integer `page_idx`: the page index.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return wx.NullBitmap
+
+ # update our own tab catalog
+ page_info = self._tabs.GetPage(page_idx)
+ return page_info.bitmap
+
+
+ def SetPageTooltip(self, page_idx, tooltip):
+ """
+ Sets the tab tooltip for the page.
+
+ :param integer `page_idx`: the page index;
+ :param string `tooltip`: the new tooltip.
+
+ :returns: ``True`` if the page tooltip has been set, ``False`` otherwise
+ (for example when the input `page_idx` is greater than the number of
+ pages in the notebook.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ # update our own tab catalog
+ page_info = self._tabs.GetPage(page_idx)
+ page_info.tooltip = tooltip
+ return True
+
+
+ def GetPageTooltip(self, page_idx):
+ """
+ Returns the tab tooltip for the page.
+
+ :param integer `page_idx`: the page index.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return ""
+
+ page_info = self._tabs.GetPage(page_idx)
+ return page_info.tooltip
+
+
+ def SetImageList(self, imageList):
+ """
+ Sets the image list for the :class:`AuiNotebook` control.
+
+ :param ImageList `imageList`: the bitmap image list to associate to :class:`AuiNotebook`.
+ """
+
+ self._imageList = imageList
+
+
+ def AssignImageList(self, imageList):
+ """
+ Sets the image list for the :class:`AuiNotebook` control.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ self.SetImageList(imageList)
+
+
+ def GetImageList(self):
+ """ Returns the associated image list (if any). """
+
+ return self._imageList
+
+
+ def SetPageImage(self, page, image):
+ """
+ Sets the image index for the given page.
+
+ :param integer `page`: the page index;
+ :param integer `image`: an index into the image list which was set with :meth:`SetImageList`.
+ """
+
+ if page >= self._tabs.GetPageCount():
+ return False
+
+ if not isinstance(image, types.IntType):
+ raise Exception("The image parameter must be an integer, you passed " \
+ "%s"%repr(image))
+
+ if not self._imageList:
+ raise Exception("To use SetPageImage you need to associate an image list " \
+ "Using SetImageList or AssignImageList")
+
+ if image >= self._imageList.GetImageCount():
+ raise Exception("Invalid image index (%d), the image list contains only" \
+ " (%d) bitmaps"%(image, self._imageList.GetImageCount()))
+
+ if image == -1:
+ self.SetPageBitmap(page, wx.NullBitmap)
+ return
+
+ bitmap = self._imageList.GetBitmap(image)
+ self.SetPageBitmap(page, bitmap)
+
+
+ def GetPageImage(self, page):
+ """
+ Returns the image index for the given page.
+
+ :param integer `page`: the given page for which to retrieve the image index.
+ """
+
+ if page >= self._tabs.GetPageCount():
+ return wx.NOT_FOUND
+
+ bitmap = self.GetPageBitmap(page)
+ bmpData1 = bitmap.ConvertToImage().GetData()
+
+ for indx in xrange(self._imageList.GetImageCount()):
+ imgListBmp = self._imageList.GetBitmap(indx)
+ bmpData2 = imgListBmp.ConvertToImage().GetData()
+ if bmpData1 == bmpData2:
+ return indx
+
+ return wx.NOT_FOUND
+
+
+ def SetPageTextColour(self, page_idx, colour):
+ """
+ Sets the tab text colour for the page.
+
+ :param integer `page_idx`: the page index;
+ :param Colour `colour`: the new tab label text colour.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ # update our own tab catalog
+ page_info = self._tabs.GetPage(page_idx)
+ should_refresh = page_info.text_colour != colour
+ page_info.text_colour = colour
+
+ # update what's on screen
+ ctrl, ctrl_idx = self.FindTab(page_info.window)
+ if not ctrl:
+ return False
+
+ info = ctrl.GetPage(ctrl_idx)
+ should_refresh = should_refresh or info.text_colour != colour
+ info.text_colour = page_info.text_colour
+
+ if should_refresh:
+ ctrl.Refresh()
+ ctrl.Update()
+
+ return True
+
+
+ def GetPageTextColour(self, page_idx):
+ """
+ Returns the tab text colour for the page.
+
+ :param integer `page_idx`: the page index.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return wx.NullColour
+
+ # update our own tab catalog
+ page_info = self._tabs.GetPage(page_idx)
+ return page_info.text_colour
+
+
+ def AddControlToPage(self, page_idx, control):
+ """
+ Adds a control inside a tab (not in the tab area).
+
+ :param integer `page_idx`: the page index;
+ :param Window `control`: almost any :class:`Window` -derived instance to be located
+ inside a tab.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ # update our own tab catalog
+ page_info = self._tabs.GetPage(page_idx)
+ page_info.control = control
+
+ # tab height might have changed
+ self.UpdateTabCtrlHeight(force=True)
+
+ # update what's on screen
+ ctrl, ctrl_idx = self.FindTab(page_info.window)
+ if not ctrl:
+ return False
+
+ control.Reparent(ctrl)
+
+ info = ctrl.GetPage(ctrl_idx)
+ info.control = control
+ ctrl.Refresh()
+ ctrl.Update()
+
+ return True
+
+
+ def RemoveControlFromPage(self, page_idx):
+ """
+ Removes a control from a tab (not from the tab area).
+
+ :param integer `page_idx`: the page index.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ page_info = self._tabs.GetPage(page_idx)
+ if page_info.control is None:
+ return False
+
+ page_info.control.Destroy()
+ page_info.control = None
+
+ # tab height might have changed
+ self.UpdateTabCtrlHeight(force=True)
+
+ # update what's on screen
+ ctrl, ctrl_idx = self.FindTab(page_info.window)
+ if not ctrl:
+ return False
+
+ info = ctrl.GetPage(ctrl_idx)
+ info.control = None
+ ctrl.Refresh()
+ ctrl.Update()
+
+ return True
+
+
+ def SetCloseButton(self, page_idx, hasCloseButton):
+ """
+ Sets whether a tab should display a close button or not.
+
+ :param integer `page_idx`: the page index;
+ :param bool `hasCloseButton`: ``True`` if the page displays a close button.
+
+ :note: This can only be called if ``AUI_NB_CLOSE_ON_ALL_TABS`` is specified.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ if self._agwFlags & AUI_NB_CLOSE_ON_ALL_TABS == 0:
+ raise Exception("SetCloseButton can only be used with AUI_NB_CLOSE_ON_ALL_TABS style.")
+
+ # update our own tab catalog
+ page_info = self._tabs.GetPage(page_idx)
+ page_info.hasCloseButton = hasCloseButton
+
+ # update what's on screen
+ ctrl, ctrl_idx = self.FindTab(page_info.window)
+ if not ctrl:
+ return False
+
+ info = ctrl.GetPage(ctrl_idx)
+ info.hasCloseButton = page_info.hasCloseButton
+ ctrl.Refresh()
+ ctrl.Update()
+
+ return True
+
+
+ def HasCloseButton(self, page_idx):
+ """
+ Returns whether a tab displays a close button or not.
+
+ :param integer `page_idx`: the page index.
+
+ :note: This can only be called if ``AUI_NB_CLOSE_ON_ALL_TABS`` is specified.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ page_info = self._tabs.GetPage(page_idx)
+ return page_info.hasCloseButton
+
+
+ def GetSelection(self):
+ """ Returns the index of the currently active page, or -1 if none was selected. """
+
+ return self._curpage
+
+
+ def GetCurrentPage(self):
+ """ Returns the currently active page (not the index), or ``None`` if none was selected. """
+
+ if self._curpage >= 0 and self._curpage < self._tabs.GetPageCount():
+ return self.GetPage(self._curpage)
+
+ return None
+
+
+ def EnsureVisible(self, indx):
+ """
+ Ensures the input page index `indx` is visible.
+
+ :param integer `indx`: the page index.
+ """
+
+ self._tabs.MakeTabVisible(indx, self)
+
+
+ def SetSelection(self, new_page, force=False):
+ """
+ Sets the page selection. Calling this method will generate a page change event.
+
+ :param integer `new_page`: the index of the new selection;
+ :param bool `force`: whether to force the selection or not.
+ """
+ wnd = self._tabs.GetWindowFromIdx(new_page)
+
+ #Update page access time
+ self._tabs.GetPages()[new_page].access_time = datetime.datetime.now()
+
+ if not wnd or not self.GetEnabled(new_page):
+ return self._curpage
+
+ # don't change the page unless necessary
+ # however, clicking again on a tab should give it the focus.
+ if new_page == self._curpage and not force:
+
+ ctrl, ctrl_idx = self.FindTab(wnd)
+ if wx.Window.FindFocus() != ctrl:
+ ctrl.SetFocus()
+
+ return self._curpage
+
+ evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId())
+ evt.SetSelection(new_page)
+ evt.SetOldSelection(self._curpage)
+ evt.SetEventObject(self)
+
+ if not self.GetEventHandler().ProcessEvent(evt) or evt.IsAllowed():
+
+ old_curpage = self._curpage
+ self._curpage = new_page
+
+ # program allows the page change
+ evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED)
+ self.GetEventHandler().ProcessEvent(evt)
+
+ if not evt.IsAllowed(): # event is no longer allowed after handler
+ return self._curpage
+
+ ctrl, ctrl_idx = self.FindTab(wnd)
+
+ if ctrl:
+ self._tabs.SetActivePage(wnd)
+ ctrl.SetActivePage(ctrl_idx)
+ self.DoSizing()
+ ctrl.DoShowHide()
+ ctrl.MakeTabVisible(ctrl_idx, ctrl)
+
+ # set fonts
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+
+ tabctrl = pane.window._tabs
+ if tabctrl != ctrl:
+ tabctrl.SetSelectedFont(self._normal_font)
+ else:
+ tabctrl.SetSelectedFont(self._selected_font)
+
+ tabctrl.Refresh()
+ tabctrl.Update()
+
+ # Set the focus to the page if we're not currently focused on the tab.
+ # This is Firefox-like behaviour.
+ if wnd.IsShownOnScreen() and wx.Window.FindFocus() != ctrl:
+ wnd.SetFocus()
+
+ return old_curpage
+
+ return self._curpage
+
+
+ def SetSelectionToWindow(self, win):
+ """
+ Sets the selection based on the input window `win`.
+
+ :param `win`: a :class:`Window` derived window.
+ """
+
+ idx = self._tabs.GetIdxFromWindow(win)
+
+ if idx == wx.NOT_FOUND:
+ raise Exception("invalid notebook page")
+
+ if not self.GetEnabled(idx):
+ return
+
+ # since a tab was clicked, let the parent know that we received
+ # the focus, even if we will assign that focus immediately
+ # to the child tab in the SetSelection call below
+ # (the child focus event will also let AuiManager, if any,
+ # know that the notebook control has been activated)
+
+ parent = self.GetParent()
+ if parent:
+ eventFocus = wx.ChildFocusEvent(self)
+ parent.GetEventHandler().ProcessEvent(eventFocus)
+
+ self.SetSelection(idx)
+
+
+ def SetSelectionToPage(self, page):
+ """
+ Sets the selection based on the input page.
+
+ :param `page`: an instance of :class:`AuiNotebookPage`.
+ """
+
+ self.SetSelectionToWindow(page.window)
+
+
+ def GetPageCount(self):
+ """ Returns the number of pages in the notebook. """
+
+ return self._tabs.GetPageCount()
+
+
+ def GetPage(self, page_idx):
+ """
+ Returns the page specified by the given index.
+
+ :param integer `page_idx`: the page index.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ raise Exception("invalid notebook page")
+
+ return self._tabs.GetWindowFromIdx(page_idx)
+
+
+ def GetPageInfo(self, page_idx):
+ """
+ Returns the :class:`AuiNotebookPage` info structure specified by the given index.
+
+ :param integer `page_idx`: the page index.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ raise Exception("invalid notebook page")
+
+ return self._tabs.GetPage(page_idx)
+
+
+ def GetEnabled(self, page_idx):
+ """
+ Returns whether the page specified by the index `page_idx` is enabled.
+
+ :param integer `page_idx`: the page index.
+ """
+
+ return self._tabs.GetEnabled(page_idx)
+
+
+ def EnableTab(self, page_idx, enable=True):
+ """
+ Enables/disables a page in the notebook.
+
+ :param integer `page_idx`: the page index;
+ :param bool `enable`: ``True`` to enable the page, ``False`` to disable it.
+ """
+
+ self._tabs.EnableTab(page_idx, enable)
+ self.Refresh()
+
+
+ def DoSizing(self):
+ """ Performs all sizing operations in each tab control. """
+
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+
+ tabframe = pane.window
+ tabframe.DoSizing()
+
+
+ def GetAuiManager(self):
+ """ Returns the associated :class:`~lib.agw.aui.framemanager.AuiManager`. """
+
+ return self._mgr
+
+
+ def GetActiveTabCtrl(self):
+ """
+ Returns the active tab control. It is called to determine which control
+ gets new windows being added.
+ """
+
+ if self._curpage >= 0 and self._curpage < self._tabs.GetPageCount():
+
+ # find the tab ctrl with the current page
+ ctrl, idx = self.FindTab(self._tabs.GetPage(self._curpage).window)
+ if ctrl:
+ return ctrl
+
+ # no current page, just find the first tab ctrl
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+
+ tabframe = pane.window
+ return tabframe._tabs
+
+ # If there is no tabframe at all, create one
+ tabframe = TabFrame(self)
+ tabframe.SetTabCtrlHeight(self._tab_ctrl_height)
+ self._tab_id_counter += 1
+ tabframe._tabs = AuiTabCtrl(self, self._tab_id_counter)
+
+ tabframe._tabs.SetAGWFlags(self._agwFlags)
+ tabframe._tabs.SetArtProvider(self._tabs.GetArtProvider().Clone())
+ self._mgr.AddPane(tabframe, framemanager.AuiPaneInfo().Center().CaptionVisible(False).
+ PaneBorder((self._agwFlags & AUI_NB_SUB_NOTEBOOK) == 0))
+
+ self._mgr.Update()
+
+ return tabframe._tabs
+
+
+ def FindTab(self, page):
+ """
+ Finds the tab control that currently contains the window as well
+ as the index of the window in the tab control. It returns ``True`` if the
+ window was found, otherwise ``False``.
+
+ :param `page`: an instance of :class:`AuiNotebookPage`.
+ """
+
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+
+ tabframe = pane.window
+
+ page_idx = tabframe._tabs.GetIdxFromWindow(page)
+
+ if page_idx != -1:
+
+ ctrl = tabframe._tabs
+ idx = page_idx
+ return ctrl, idx
+
+ return None, wx.NOT_FOUND
+
+
+ def Split(self, page, direction):
+ """
+ Performs a split operation programmatically.
+
+ :param integer `page`: indicates the page that will be split off. This page will also become
+ the active page after the split.
+ :param integer `direction`: specifies where the pane should go, it should be one of the
+ following: ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, or ``wx.RIGHT``.
+ """
+
+ cli_size = self.GetClientSize()
+
+ # get the page's window pointer
+ wnd = self.GetPage(page)
+ if not wnd:
+ return
+
+ # notebooks with 1 or less pages can't be split
+ if self.GetPageCount() < 2:
+ return
+
+ # find out which tab control the page currently belongs to
+
+ src_tabs, src_idx = self.FindTab(wnd)
+ if not src_tabs:
+ return
+
+ selection = self.GetSelection()
+
+ # choose a split size
+ if self.GetPageCount() > 2:
+ split_size = self.CalculateNewSplitSize()
+ else:
+ # because there are two panes, always split them
+ # equally
+ split_size = self.GetClientSize()
+ split_size.x /= 2
+ split_size.y /= 2
+
+ # create a new tab frame
+ new_tabs = TabFrame(self)
+ new_tabs._rect = wx.RectPS(wx.Point(0, 0), split_size)
+ new_tabs.SetTabCtrlHeight(self._tab_ctrl_height)
+ self._tab_id_counter += 1
+ new_tabs._tabs = AuiTabCtrl(self, self._tab_id_counter)
+
+ new_tabs._tabs.SetArtProvider(self._tabs.GetArtProvider().Clone())
+ new_tabs._tabs.SetAGWFlags(self._agwFlags)
+ dest_tabs = new_tabs._tabs
+
+ page_info = src_tabs.GetPage(src_idx)
+ if page_info.control:
+ self.ReparentControl(page_info.control, dest_tabs)
+
+ cloned_buttons = self.CloneTabAreaButtons()
+ for clone in cloned_buttons:
+ dest_tabs.AddButton(clone.id, clone.location, clone.bitmap, clone.dis_bitmap)
+ # create a pane info structure with the information
+ # about where the pane should be added
+ pane_info = framemanager.AuiPaneInfo().Bottom().CaptionVisible(False)
+
+ if direction == wx.LEFT:
+
+ pane_info.Left()
+ mouse_pt = wx.Point(0, cli_size.y/2)
+
+ elif direction == wx.RIGHT:
+
+ pane_info.Right()
+ mouse_pt = wx.Point(cli_size.x, cli_size.y/2)
+
+ elif direction == wx.TOP:
+
+ pane_info.Top()
+ mouse_pt = wx.Point(cli_size.x/2, 0)
+
+ elif direction == wx.BOTTOM:
+
+ pane_info.Bottom()
+ mouse_pt = wx.Point(cli_size.x/2, cli_size.y)
+
+ self._mgr.AddPane(new_tabs, pane_info, mouse_pt)
+ self._mgr.Update()
+
+ # remove the page from the source tabs
+ page_info.active = False
+
+ src_tabs.RemovePage(page_info.window)
+
+ if src_tabs.GetPageCount() > 0:
+ if selection < 0 or selection == src_idx:
+ active_page = 0
+ else:
+ if selection > src_idx:
+ selection -= 1
+
+ active_page = selection
+
+ src_tabs.SetActivePage(active_page)
+ src_tabs.DoShowHide()
+ src_tabs.Refresh()
+
+ # add the page to the destination tabs
+ dest_tabs.InsertPage(page_info.window, page_info, 0)
+
+ if src_tabs.GetPageCount() == 0:
+ self.RemoveEmptyTabFrames()
+
+ self.DoSizing()
+ dest_tabs.DoShowHide()
+ dest_tabs.Refresh()
+
+ # force the set selection function reset the selection
+ self._curpage = -1
+
+ # set the active page to the one we just split off
+ self.SetSelectionToPage(page_info)
+
+ self.UpdateHintWindowSize()
+
+
+ def UnSplit(self):
+ """ Restores original view after a tab split. """
+
+ self.Freeze()
+
+ # remember the tab now selected
+ nowSelected = self.GetSelection()
+ # select first tab as destination
+ self.SetSelection(0)
+ # iterate all other tabs
+ for idx in xrange(1, self.GetPageCount()):
+ # get win reference
+ win = self.GetPage(idx)
+ # get tab title
+ title = self.GetPageText(idx)
+ # get page bitmap
+ bmp = self.GetPageBitmap(idx)
+ # remove from notebook
+ self.RemovePage(idx)
+ # re-add in the same position so it will tab
+ self.InsertPage(idx, win, title, False, bmp)
+ # restore orignial selected tab
+ self.SetSelection(nowSelected)
+
+ self.Thaw()
+
+
+ def ReparentControl(self, control, dest_tabs):
+ """
+ Reparents a control added inside a tab.
+
+ :param Window `control`: almost any :class:`Window` -derived instance to be located
+ inside a tab;
+ :param `dest_tabs`: the destination :class:`AuiTabCtrl`.
+ """
+
+ control.Hide()
+ control.Reparent(dest_tabs)
+
+
+ def UnsplitDClick(self, part, sash_size, pos):
+ """
+ Unsplit the :class:`AuiNotebook` on sash double-click.
+
+ :param `part`: an UI part representing the sash;
+ :param integer `sash_size`: the sash size;
+ :param Point `pos`: the double-click mouse position.
+
+ .. warning::
+
+ Due to a bug on MSW, for disabled pages :func:`FindWindowAtPoint`
+ returns the wrong window. See http://trac.wxwidgets.org/ticket/2942
+
+ """
+
+ if not self._sash_dclick_unsplit:
+ # Unsplit not allowed
+ return
+
+ pos1 = wx.Point(*pos)
+ pos2 = wx.Point(*pos)
+ if part.orientation == wx.HORIZONTAL:
+ pos1.y -= 2*sash_size
+ pos2.y += 2*sash_size + self.GetTabCtrlHeight()
+ elif part.orientation == wx.VERTICAL:
+ pos1.x -= 2*sash_size
+ pos2.x += 2*sash_size
+ else:
+ raise Exception("Invalid UI part orientation")
+
+ pos1, pos2 = self.ClientToScreen(pos1), self.ClientToScreen(pos2)
+ win1, win2 = wx.FindWindowAtPoint(pos1), wx.FindWindowAtPoint(pos2)
+
+ if isinstance(win1, wx.ScrollBar):
+ # Hopefully it will work
+ pos1 = wx.Point(*pos)
+ shift = wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X) + 2*(sash_size+1)
+ if part.orientation == wx.HORIZONTAL:
+ pos1.y -= shift
+ else:
+ pos1.x -= shift
+
+ pos1 = self.ClientToScreen(pos1)
+ win1 = wx.FindWindowAtPoint(pos1)
+
+ if isinstance(win2, wx.ScrollBar):
+ pos2 = wx.Point(*pos)
+ shift = wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X) + 2*(sash_size+1)
+ if part.orientation == wx.HORIZONTAL:
+ pos2.y += shift
+ else:
+ pos2.x += shift
+
+ pos2 = self.ClientToScreen(pos2)
+ win2 = wx.FindWindowAtPoint(pos2)
+
+ if not win1 or not win2:
+ # How did we get here?
+ return
+
+ if isinstance(win1, AuiNotebook) or isinstance(win2, AuiNotebook):
+ # This is a bug on MSW, for disabled pages wx.FindWindowAtPoint
+ # returns the wrong window.
+ # See http://trac.wxwidgets.org/ticket/2942
+ return
+
+ tab_frame1, tab_frame2 = self.GetTabFrameFromWindow(win1), self.GetTabFrameFromWindow(win2)
+
+ if not tab_frame1 or not tab_frame2:
+ return
+
+ tab_ctrl_1, tab_ctrl_2 = tab_frame1._tabs, tab_frame2._tabs
+
+ if tab_ctrl_1.GetPageCount() > tab_ctrl_2.GetPageCount():
+ src_tabs = tab_ctrl_2
+ dest_tabs = tab_ctrl_1
+ else:
+ src_tabs = tab_ctrl_1
+ dest_tabs = tab_ctrl_2
+
+ selection = -1
+ page_count = dest_tabs.GetPageCount()
+
+ for page in xrange(src_tabs.GetPageCount()-1, -1, -1):
+ # remove the page from the source tabs
+ page_info = src_tabs.GetPage(page)
+ if page_info.active:
+ selection = page_count + page
+ src_tabs.RemovePage(page_info.window)
+
+ # add the page to the destination tabs
+ dest_tabs.AddPage(page_info.window, page_info)
+ if page_info.control:
+ self.ReparentControl(page_info.control, dest_tabs)
+
+ self.RemoveEmptyTabFrames()
+
+ dest_tabs.DoShowHide()
+ self.DoSizing()
+ dest_tabs.Refresh()
+ self._mgr.Update()
+ if selection > 0:
+ wx.CallAfter(dest_tabs.MakeTabVisible, selection, self)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.UpdateHintWindowSize()
+ event.Skip()
+
+
+ def OnTabClicked(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_PAGE_CHANGING`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ if self._textCtrl is not None:
+ self._textCtrl.StopEditing()
+
+ ctrl = event.GetEventObject()
+ assert ctrl != None
+
+ wnd = ctrl.GetWindowFromIdx(event.GetSelection())
+ assert wnd != None
+
+ self.SetSelectionToWindow(wnd)
+
+
+ def OnTabBgDClick(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_BG_DCLICK`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ if self._textCtrl is not None:
+ self._textCtrl.StopEditing()
+
+ # notify owner that the tabbar background has been double-clicked
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, self.GetId())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def OnTabDClick(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_TAB_DCLICK`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ # notify owner that the tabbar background has been double-clicked
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_DCLICK, self.GetId())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+ tabs = event.GetEventObject()
+ if not tabs.GetEnabled(event.GetSelection()):
+ return
+
+ if not self.IsRenamable(event.GetSelection()):
+ return
+
+ self.EditTab(event.GetSelection())
+
+
+ def OnTabBeginDrag(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_BEGIN_DRAG`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ tabs = event.GetEventObject()
+ if not tabs.GetEnabled(event.GetSelection()):
+ return
+
+ self._last_drag_x = 0
+
+
+ def OnTabDragMotion(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_DRAG_MOTION`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ self._curpage = event.GetSelection()
+
+ tabs = event.GetEventObject()
+ if not tabs.GetEnabled(event.GetSelection()):
+ return
+
+ if self._textCtrl is not None:
+ self._textCtrl.StopEditing()
+
+ screen_pt = wx.GetMousePosition()
+ client_pt = self.ScreenToClient(screen_pt)
+ zero = wx.Point(0, 0)
+
+ src_tabs = event.GetEventObject()
+ dest_tabs = self.GetTabCtrlFromPoint(client_pt)
+
+ if dest_tabs == src_tabs:
+
+ # always hide the hint for inner-tabctrl drag
+ self._mgr.HideHint()
+
+ # if tab moving is not allowed, leave
+ if not self._agwFlags & AUI_NB_TAB_MOVE:
+ return
+
+ pt = dest_tabs.ScreenToClient(screen_pt)
+
+ # this is an inner-tab drag/reposition
+ dest_location_tab = dest_tabs.TabHitTest(pt.x, pt.y)
+
+ if dest_location_tab:
+
+ src_idx = event.GetSelection()
+ dest_idx = dest_tabs.GetIdxFromWindow(dest_location_tab)
+
+ # prevent jumpy drag
+ if (src_idx == dest_idx) or dest_idx == -1 or \
+ (src_idx > dest_idx and self._last_drag_x <= pt.x) or \
+ (src_idx < dest_idx and self._last_drag_x >= pt.x):
+
+ self._last_drag_x = pt.x
+ return
+
+ src_tab = dest_tabs.GetWindowFromIdx(src_idx)
+ dest_tabs.MovePage(src_tab, dest_idx)
+ self._tabs.MovePage(self._tabs.GetPage(src_idx).window, dest_idx)
+ dest_tabs.SetActivePage(dest_idx)
+ dest_tabs.DoShowHide()
+ dest_tabs.Refresh()
+ self._last_drag_x = pt.x
+
+ return
+
+ # if external drag is allowed, check if the tab is being dragged
+ # over a different AuiNotebook control
+ if self._agwFlags & AUI_NB_TAB_EXTERNAL_MOVE:
+
+ tab_ctrl = wx.FindWindowAtPoint(screen_pt)
+
+ # if we aren't over any window, stop here
+ if not tab_ctrl:
+ if self._agwFlags & AUI_NB_TAB_FLOAT:
+ if self.IsMouseWellOutsideWindow():
+ hintRect = wx.RectPS(screen_pt, (400, 300))
+ # Use CallAfter so we overwrite the hint that might be
+ # shown by our superclass:
+ wx.CallAfter(self._mgr.ShowHint, hintRect)
+ return
+
+ # make sure we are not over the hint window
+ if not isinstance(tab_ctrl, wx.Frame):
+ while tab_ctrl:
+ if isinstance(tab_ctrl, AuiTabCtrl):
+ break
+
+ tab_ctrl = tab_ctrl.GetParent()
+
+ if tab_ctrl:
+ nb = tab_ctrl.GetParent()
+
+ if nb != self:
+
+ hint_rect = tab_ctrl.GetClientRect()
+ hint_rect.x, hint_rect.y = tab_ctrl.ClientToScreenXY(hint_rect.x, hint_rect.y)
+ self._mgr.ShowHint(hint_rect)
+ return
+
+ else:
+
+ if not dest_tabs:
+ # we are either over a hint window, or not over a tab
+ # window, and there is no where to drag to, so exit
+ return
+
+ if self._agwFlags & AUI_NB_TAB_FLOAT:
+ if self.IsMouseWellOutsideWindow():
+ hintRect = wx.RectPS(screen_pt, (400, 300))
+ # Use CallAfter so we overwrite the hint that might be
+ # shown by our superclass:
+ wx.CallAfter(self._mgr.ShowHint, hintRect)
+ return
+
+ # if there are less than two panes, split can't happen, so leave
+ if self._tabs.GetPageCount() < 2:
+ return
+
+ # if tab moving is not allowed, leave
+ if not self._agwFlags & AUI_NB_TAB_SPLIT:
+ return
+
+ if dest_tabs:
+
+ hint_rect = dest_tabs.GetRect()
+ hint_rect.x, hint_rect.y = self.ClientToScreenXY(hint_rect.x, hint_rect.y)
+ self._mgr.ShowHint(hint_rect)
+
+ else:
+ rect = self._mgr.CalculateHintRect(self._dummy_wnd, client_pt, zero)
+ if rect.IsEmpty():
+ self._mgr.HideHint()
+ return
+
+ hit_wnd = wx.FindWindowAtPoint(screen_pt)
+ if hit_wnd and not isinstance(hit_wnd, AuiNotebook):
+ tab_frame = self.GetTabFrameFromWindow(hit_wnd)
+ if tab_frame:
+ hint_rect = wx.Rect(*tab_frame._rect)
+ hint_rect.x, hint_rect.y = self.ClientToScreenXY(hint_rect.x, hint_rect.y)
+ rect.Intersect(hint_rect)
+ self._mgr.ShowHint(rect)
+ else:
+ self._mgr.DrawHintRect(self._dummy_wnd, client_pt, zero)
+ else:
+ self._mgr.DrawHintRect(self._dummy_wnd, client_pt, zero)
+
+
+ def OnTabEndDrag(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_END_DRAG`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ tabs = event.GetEventObject()
+ if not tabs.GetEnabled(event.GetSelection()):
+ return
+
+ self._mgr.HideHint()
+
+ src_tabs = event.GetEventObject()
+ if not src_tabs:
+ raise Exception("no source object?")
+
+ # get the mouse position, which will be used to determine the drop point
+ mouse_screen_pt = wx.GetMousePosition()
+ mouse_client_pt = self.ScreenToClient(mouse_screen_pt)
+
+ # check for an external move
+ if self._agwFlags & AUI_NB_TAB_EXTERNAL_MOVE:
+ tab_ctrl = wx.FindWindowAtPoint(mouse_screen_pt)
+
+ while tab_ctrl:
+
+ if isinstance(tab_ctrl, AuiTabCtrl):
+ break
+
+ tab_ctrl = tab_ctrl.GetParent()
+
+ if tab_ctrl:
+
+ nb = tab_ctrl.GetParent()
+
+ if nb != self:
+
+ # find out from the destination control
+ # if it's ok to drop this tab here
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, self.GetId())
+ e.SetSelection(event.GetSelection())
+ e.SetOldSelection(event.GetSelection())
+ e.SetEventObject(self)
+ e.SetDragSource(self)
+ e.Veto() # dropping must be explicitly approved by control owner
+
+ nb.GetEventHandler().ProcessEvent(e)
+
+ if not e.IsAllowed():
+
+ # no answer or negative answer
+ self._mgr.HideHint()
+ return
+
+ # drop was allowed
+ src_idx = event.GetSelection()
+ src_page = src_tabs.GetWindowFromIdx(src_idx)
+
+ # Check that it's not an impossible parent relationship
+ p = nb
+ while p and not p.IsTopLevel():
+ if p == src_page:
+ return
+
+ p = p.GetParent()
+
+ # get main index of the page
+ main_idx = self._tabs.GetIdxFromWindow(src_page)
+ if main_idx == wx.NOT_FOUND:
+ raise Exception("no source page?")
+
+ # make a copy of the page info
+ page_info = self._tabs.GetPage(main_idx)
+
+ # remove the page from the source notebook
+ self.RemovePage(main_idx)
+
+ # reparent the page
+ src_page.Reparent(nb)
+
+ # Reparent the control in a tab (if any)
+ if page_info.control:
+ self.ReparentControl(page_info.control, tab_ctrl)
+
+ # find out the insert idx
+ dest_tabs = tab_ctrl
+ pt = dest_tabs.ScreenToClient(mouse_screen_pt)
+
+ target = dest_tabs.TabHitTest(pt.x, pt.y)
+ insert_idx = -1
+ if target:
+ insert_idx = dest_tabs.GetIdxFromWindow(target)
+
+ # add the page to the new notebook
+ if insert_idx == -1:
+ insert_idx = dest_tabs.GetPageCount()
+
+ dest_tabs.InsertPage(page_info.window, page_info, insert_idx)
+ nb._tabs.AddPage(page_info.window, page_info)
+
+ nb.DoSizing()
+ dest_tabs.DoShowHide()
+ dest_tabs.Refresh()
+
+ # set the selection in the destination tab control
+ nb.SetSelectionToPage(page_info)
+
+ # notify owner that the tab has been dragged
+ e2 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, self.GetId())
+ e2.SetSelection(event.GetSelection())
+ e2.SetOldSelection(event.GetSelection())
+ e2.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e2)
+
+ # notify the target notebook that the tab has been dragged
+ e3 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, nb.GetId())
+ e3.SetSelection(insert_idx)
+ e3.SetOldSelection(insert_idx)
+ e3.SetEventObject(nb)
+ nb.GetEventHandler().ProcessEvent(e3)
+
+ return
+
+ if self._agwFlags & AUI_NB_TAB_FLOAT:
+ self._mgr.HideHint()
+ if self.IsMouseWellOutsideWindow():
+ # Use CallAfter so we our superclass can deal with the event first
+ wx.CallAfter(self.FloatPage, self.GetSelection())
+ event.Skip()
+ return
+
+ # only perform a tab split if it's allowed
+ dest_tabs = None
+
+ if self._agwFlags & AUI_NB_TAB_SPLIT and self._tabs.GetPageCount() >= 2:
+
+ # If the pointer is in an existing tab frame, do a tab insert
+ hit_wnd = wx.FindWindowAtPoint(mouse_screen_pt)
+ tab_frame = self.GetTabFrameFromTabCtrl(hit_wnd)
+ insert_idx = -1
+
+ if tab_frame:
+
+ dest_tabs = tab_frame._tabs
+
+ if dest_tabs == src_tabs:
+ return
+
+ pt = dest_tabs.ScreenToClient(mouse_screen_pt)
+ target = dest_tabs.TabHitTest(pt.x, pt.y)
+
+ if target:
+ insert_idx = dest_tabs.GetIdxFromWindow(target)
+
+ else:
+
+ zero = wx.Point(0, 0)
+ rect = self._mgr.CalculateHintRect(self._dummy_wnd, mouse_client_pt, zero)
+
+ if rect.IsEmpty():
+ # there is no suitable drop location here, exit out
+ return
+
+ # If there is no tabframe at all, create one
+ new_tabs = TabFrame(self)
+ new_tabs._rect = wx.RectPS(wx.Point(0, 0), self.CalculateNewSplitSize())
+ new_tabs.SetTabCtrlHeight(self._tab_ctrl_height)
+ self._tab_id_counter += 1
+ new_tabs._tabs = AuiTabCtrl(self, self._tab_id_counter)
+ new_tabs._tabs.SetArtProvider(self._tabs.GetArtProvider().Clone())
+ new_tabs._tabs.SetAGWFlags(self._agwFlags)
+
+ self._mgr.AddPane(new_tabs, framemanager.AuiPaneInfo().Bottom().CaptionVisible(False), mouse_client_pt)
+ self._mgr.Update()
+ dest_tabs = new_tabs._tabs
+
+ cloned_buttons = self.CloneTabAreaButtons()
+ for clone in cloned_buttons:
+ dest_tabs.AddButton(clone.id, clone.location, clone.bitmap, clone.dis_bitmap)
+ # remove the page from the source tabs
+ page_info = src_tabs.GetPage(event.GetSelection())
+
+ if page_info.control:
+ self.ReparentControl(page_info.control, dest_tabs)
+
+ page_info.active = False
+ src_tabs.RemovePage(page_info.window)
+
+ if src_tabs.GetPageCount() > 0:
+ src_tabs.SetActivePage(0)
+ src_tabs.DoShowHide()
+ src_tabs.Refresh()
+
+ # add the page to the destination tabs
+ if insert_idx == -1:
+ insert_idx = dest_tabs.GetPageCount()
+
+ dest_tabs.InsertPage(page_info.window, page_info, insert_idx)
+
+ if src_tabs.GetPageCount() == 0:
+ self.RemoveEmptyTabFrames()
+
+ self.DoSizing()
+ dest_tabs.DoShowHide()
+ dest_tabs.Refresh()
+
+ # force the set selection function reset the selection
+ self._curpage = -1
+
+ # set the active page to the one we just split off
+ self.SetSelectionToPage(page_info)
+
+ self.UpdateHintWindowSize()
+
+ # notify owner that the tab has been dragged
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, self.GetId())
+ e.SetSelection(event.GetSelection())
+ e.SetOldSelection(event.GetSelection())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def OnTabCancelDrag(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_CANCEL_DRAG`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ tabs = event.GetEventObject()
+ if not tabs.GetEnabled(event.GetSelection()):
+ return
+
+ self._mgr.HideHint()
+
+ src_tabs = event.GetEventObject()
+ if not src_tabs:
+ raise Exception("no source object?")
+
+
+ def IsMouseWellOutsideWindow(self):
+ """ Returns whether the mouse is well outside the :class:`AuiNotebook` screen rectangle. """
+
+ screen_rect = self.GetScreenRect()
+ screen_rect.Inflate(50, 50)
+
+ return not screen_rect.Contains(wx.GetMousePosition())
+
+
+ def FloatPage(self, page_index):
+ """
+ Float the page in `page_index` by reparenting it to a floating frame.
+
+ :param integer `page_index`: the index of the page to be floated.
+
+ .. warning::
+
+ When the notebook is more or less full screen, tabs cannot be dragged far
+ enough outside of the notebook to become floating pages.
+
+ """
+
+ root_manager = framemanager.GetManager(self)
+ page_title = self.GetPageText(page_index)
+ page_contents = self.GetPage(page_index)
+ page_bitmap = self.GetPageBitmap(page_index)
+ text_colour = self.GetPageTextColour(page_index)
+ info = self.GetPageInfo(page_index)
+
+ if root_manager and root_manager != self._mgr:
+ root_manager = framemanager.GetManager(self)
+
+ if hasattr(page_contents, "__floating_size__"):
+ floating_size = wx.Size(*page_contents.__floating_size__)
+ else:
+ floating_size = page_contents.GetBestSize()
+ if floating_size == wx.DefaultSize:
+ floating_size = wx.Size(300, 200)
+
+ page_contents.__page_index__ = page_index
+ page_contents.__aui_notebook__ = self
+ page_contents.__text_colour__ = text_colour
+ page_contents.__control__ = info.control
+
+ if info.control:
+ info.control.Reparent(page_contents)
+ info.control.Hide()
+ info.control = None
+
+ self.RemovePage(page_index)
+ self.RemoveEmptyTabFrames()
+
+ pane_info = framemanager.AuiPaneInfo().Float().FloatingPosition(wx.GetMousePosition()). \
+ FloatingSize(floating_size).BestSize(floating_size).Name("__floating__%s"%page_title). \
+ Caption(page_title).Icon(page_bitmap)
+ root_manager.AddPane(page_contents, pane_info)
+ root_manager.Bind(framemanager.EVT_AUI_PANE_CLOSE, self.OnCloseFloatingPage)
+ self.GetActiveTabCtrl().DoShowHide()
+ self.DoSizing()
+ root_manager.Update()
+
+ else:
+ frame = wx.Frame(self, title=page_title,
+ style=wx.DEFAULT_FRAME_STYLE|wx.FRAME_TOOL_WINDOW|
+ wx.FRAME_FLOAT_ON_PARENT | wx.FRAME_NO_TASKBAR)
+
+ if info.control:
+ info.control.Reparent(frame)
+ info.control.Hide()
+
+ frame.bitmap = page_bitmap
+ frame.page_index = page_index
+ frame.text_colour = text_colour
+ frame.control = info.control
+ page_contents.Reparent(frame)
+ frame.Bind(wx.EVT_CLOSE, self.OnCloseFloatingPage)
+ frame.Move(wx.GetMousePosition())
+ frame.Show()
+ self.RemovePage(page_index)
+
+ self.RemoveEmptyTabFrames()
+
+ wx.CallAfter(self.RemoveEmptyTabFrames)
+
+
+ def OnCloseFloatingPage(self, event):
+ """
+ Handles the ``wx.EVT_CLOSE`` event for a floating page in :class:`AuiNotebook`.
+
+ :param `event`: a :class:`CloseEvent` event to be processed.
+ """
+
+ root_manager = framemanager.GetManager(self)
+ if root_manager and root_manager != self._mgr:
+ pane = event.pane
+ if pane.name.startswith("__floating__"):
+ self.ReDockPage(pane)
+ return
+
+ event.Skip()
+ else:
+ event.Skip()
+ frame = event.GetEventObject()
+ page_title = frame.GetTitle()
+ page_contents = list(frame.GetChildren())[-1]
+ page_contents.Reparent(self)
+ self.InsertPage(frame.page_index, page_contents, page_title, select=True, bitmap=frame.bitmap, control=frame.control)
+
+ if frame.control:
+ src_tabs, idx = self.FindTab(page_contents)
+ frame.control.Reparent(src_tabs)
+ frame.control.Hide()
+ frame.control = None
+
+ self.SetPageTextColour(frame.page_index, frame.text_colour)
+
+
+ def ReDockPage(self, pane):
+ """
+ Re-docks a floating :class:`AuiNotebook` tab in the original position, when possible.
+
+ :param `pane`: an instance of :class:`~lib.agw.aui.framemanager.AuiPaneInfo`.
+ """
+
+ root_manager = framemanager.GetManager(self)
+
+ pane.window.__floating_size__ = wx.Size(*pane.floating_size)
+ page_index = pane.window.__page_index__
+ text_colour = pane.window.__text_colour__
+ control = pane.window.__control__
+
+ root_manager.DetachPane(pane.window)
+ self.InsertPage(page_index, pane.window, pane.caption, True, pane.icon, control=control)
+
+ self.SetPageTextColour(page_index, text_colour)
+ self.GetActiveTabCtrl().DoShowHide()
+ self.DoSizing()
+ if control:
+ self.UpdateTabCtrlHeight(force=True)
+
+ self._mgr.Update()
+ root_manager.Update()
+
+
+ def GetTabCtrlFromPoint(self, pt):
+ """
+ Returns the tab control at the specified point.
+
+ :param Point `pt`: the mouse location.
+ """
+
+ # if we've just removed the last tab from the source
+ # tab set, the remove the tab control completely
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+
+ tabframe = pane.window
+ if tabframe._tab_rect.Contains(pt):
+ return tabframe._tabs
+
+ return None
+
+
+ def GetTabFrameFromTabCtrl(self, tab_ctrl):
+ """
+ Returns the tab frame associated with a tab control.
+
+ :param `tab_ctrl`: an instance of :class:`AuiTabCtrl`.
+ """
+
+ # if we've just removed the last tab from the source
+ # tab set, the remove the tab control completely
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+
+ tabframe = pane.window
+ if tabframe._tabs == tab_ctrl:
+ return tabframe
+
+ return None
+
+
+ def GetTabFrameFromWindow(self, wnd):
+ """
+ Returns the tab frame associated with a window.
+
+ :param Window `wnd`: the window for which we want to locate the :class:`TabFrame`.
+ """
+
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+
+ tabframe = pane.window
+ for page in tabframe._tabs.GetPages():
+ if wnd == page.window:
+ return tabframe
+
+ return None
+
+
+ def RemoveEmptyTabFrames(self):
+ """ Removes all the empty tab frames. """
+
+ # if we've just removed the last tab from the source
+ # tab set, the remove the tab control completely
+ all_panes = self._mgr.GetAllPanes()
+
+ for indx in xrange(len(all_panes)-1, -1, -1):
+ pane = all_panes[indx]
+ if pane.name == "dummy":
+ continue
+
+ tab_frame = pane.window
+ if tab_frame._tabs.GetPageCount() == 0:
+ self._mgr.DetachPane(tab_frame)
+ tab_frame._tabs.Destroy()
+ tab_frame._tabs = None
+ del tab_frame
+
+ # check to see if there is still a center pane
+ # if there isn't, make a frame the center pane
+ first_good = None
+ center_found = False
+
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+
+ if pane.dock_direction == AUI_DOCK_CENTRE:
+ center_found = True
+ if not first_good:
+ first_good = pane.window
+
+ if not center_found and first_good:
+ self._mgr.GetPane(first_good).Centre()
+
+ if not self.IsBeingDeleted():
+ self._mgr.Update()
+
+
+ def OnChildFocusNotebook(self, event):
+ """
+ Handles the ``wx.EVT_CHILD_FOCUS`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`ChildFocusEvent` event to be processed.
+ """
+
+ # if we're dragging a tab, don't change the current selection.
+ # This code prevents a bug that used to happen when the hint window
+ # was hidden. In the bug, the focus would return to the notebook
+ # child, which would then enter this handler and call
+ # SetSelection, which is not desired turn tab dragging.
+
+ event.Skip()
+
+ all_panes = self._mgr.GetAllPanes()
+ for pane in all_panes:
+ if pane.name == "dummy":
+ continue
+ tabframe = pane.window
+ if tabframe._tabs.IsDragging():
+ return
+
+## # change the tab selection to the child
+## # which was focused
+## idx = self._tabs.GetIdxFromWindow(event.GetWindow())
+## if idx != -1 and idx != self._curpage:
+## self.SetSelection(idx)
+
+
+ def SetNavigatorIcon(self, bmp):
+ """
+ Sets the icon used by the :class:`TabNavigatorWindow`.
+
+ :param Bitmap `bmp`: the new bitmap for the :class:`TabNavigatorWindow`.
+ """
+
+ if isinstance(bmp, wx.Bitmap) and bmp.IsOk():
+ self.NavigatorProps.Icon = bmp
+ else:
+ raise TypeError("SetNavigatorIcon requires a valid bitmap")
+
+
+ def OnNavigationKeyNotebook(self, event):
+ """
+ Handles the ``wx.EVT_NAVIGATION_KEY`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`NavigationKeyEvent` event to be processed.
+ """
+
+ if event.IsWindowChange():
+ if self._agwFlags & AUI_NB_SMART_TABS:
+ if not self._popupWin:
+ self._popupWin = TabNavigatorWindow(self, self.NavigatorProps)
+ self._popupWin.SetReturnCode(wx.ID_OK)
+ self._popupWin.ShowModal()
+ idx = self._popupWin.GetSelectedPage()
+ self._popupWin.Destroy()
+ self._popupWin = None
+ # Need to do CallAfter so that the selection and its
+ # associated events get processed outside the context of
+ # this key event. Not doing so causes odd issues with the
+ # window focus under certain use cases on Windows.
+ wx.CallAfter(self.SetSelection, idx, True)
+ else:
+ # a dialog is already opened
+ self._popupWin.OnNavigationKey(event)
+ return
+ else:
+ # change pages
+ # FIXME: the problem with this is that if we have a split notebook,
+ # we selection may go all over the place.
+ self.AdvanceSelection(event.GetDirection())
+
+ else:
+ # we get this event in 3 cases
+ #
+ # a) one of our pages might have generated it because the user TABbed
+ # out from it in which case we should propagate the event upwards and
+ # our parent will take care of setting the focus to prev/next sibling
+ #
+ # or
+ #
+ # b) the parent panel wants to give the focus to us so that we
+ # forward it to our selected page. We can't deal with this in
+ # OnSetFocus() because we don't know which direction the focus came
+ # from in this case and so can't choose between setting the focus to
+ # first or last panel child
+ #
+ # or
+ #
+ # c) we ourselves (see MSWTranslateMessage) generated the event
+ #
+ parent = self.GetParent()
+
+ # the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
+ isFromParent = event.GetEventObject() == parent
+ isFromSelf = event.GetEventObject() == self
+
+ if isFromParent or isFromSelf:
+
+ # no, it doesn't come from child, case (b) or (c): forward to a
+ # page but only if direction is backwards (TAB) or from ourselves,
+ if self.GetSelection() != wx.NOT_FOUND and (not event.GetDirection() or isFromSelf):
+
+ # so that the page knows that the event comes from it's parent
+ # and is being propagated downwards
+ event.SetEventObject(self)
+
+ page = self.GetPage(self.GetSelection())
+ if not page.GetEventHandler().ProcessEvent(event):
+ page.SetFocus()
+
+ #else: page manages focus inside it itself
+
+ else: # otherwise set the focus to the notebook itself
+
+ self.SetFocus()
+
+ else:
+
+ # send this event back for the 'wraparound' focus.
+ winFocus = event.GetCurrentFocus()
+
+ if winFocus:
+ event.SetEventObject(self)
+ winFocus.GetEventHandler().ProcessEvent(event)
+
+
+ def OnTabButton(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_BUTTON`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ tabs = event.GetEventObject()
+ button_id = event.GetInt()
+
+ if button_id == AUI_BUTTON_CLOSE:
+
+ selection = event.GetSelection()
+
+ if selection == -1:
+
+ # if the close button is to the right, use the active
+ # page selection to determine which page to close
+ selection = tabs.GetActivePage()
+
+ if selection == -1 or not tabs.GetEnabled(selection):
+ return
+
+ if selection != -1:
+
+ close_wnd = tabs.GetWindowFromIdx(selection)
+
+ if close_wnd.GetName() == "__fake__page__":
+ # This is a notebook preview
+ previous_active, page_status = close_wnd.__previousStatus
+ for page, status in zip(tabs.GetPages(), page_status):
+ page.enabled = status
+
+ main_idx = self._tabs.GetIdxFromWindow(close_wnd)
+ self.DeletePage(main_idx)
+
+ if previous_active >= 0:
+ tabs.SetActivePage(previous_active)
+ page_count = tabs.GetPageCount()
+ selection = -1
+
+ for page in xrange(page_count):
+ # remove the page from the source tabs
+ page_info = tabs.GetPage(page)
+ if page_info.active:
+ selection = page
+ break
+
+ tabs.DoShowHide()
+ self.DoSizing()
+ tabs.Refresh()
+
+ if selection >= 0:
+ wx.CallAfter(tabs.MakeTabVisible, selection, self)
+
+ # Don't fire the event
+ return
+
+ # ask owner if it's ok to close the tab
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, self.GetId())
+ idx = self._tabs.GetIdxFromWindow(close_wnd)
+ e.SetSelection(idx)
+ e.SetOldSelection(event.GetSelection())
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+ if not e.IsAllowed():
+ return
+
+ if repr(close_wnd.__class__).find("AuiMDIChildFrame") >= 0:
+ close_wnd.Close()
+
+ else:
+ main_idx = self._tabs.GetIdxFromWindow(close_wnd)
+ self.DeletePage(main_idx)
+
+ # notify owner that the tab has been closed
+ e2 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, self.GetId())
+ e2.SetSelection(idx)
+ e2.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e2)
+
+ if self.GetPageCount() == 0:
+ mgr = self.GetAuiManager()
+ win = mgr.GetManagedWindow()
+ win.SendSizeEvent()
+
+
+ def OnTabMiddleDown(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ tabs = event.GetEventObject()
+ if not tabs.GetEnabled(event.GetSelection()):
+ return
+
+ # patch event through to owner
+ wnd = tabs.GetWindowFromIdx(event.GetSelection())
+
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, self.GetId())
+ e.SetSelection(self._tabs.GetIdxFromWindow(wnd))
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def OnTabMiddleUp(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_TAB_MIDDLE_UP`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ tabs = event.GetEventObject()
+ if not tabs.GetEnabled(event.GetSelection()):
+ return
+
+ # if the AUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
+ # click should act like a tab close action. However, first
+ # give the owner an opportunity to handle the middle up event
+ # for custom action
+
+ wnd = tabs.GetWindowFromIdx(event.GetSelection())
+
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, self.GetId())
+ e.SetSelection(self._tabs.GetIdxFromWindow(wnd))
+ e.SetEventObject(self)
+ if self.GetEventHandler().ProcessEvent(e):
+ return
+ if not e.IsAllowed():
+ return
+
+ # check if we are supposed to close on middle-up
+ if self._agwFlags & AUI_NB_MIDDLE_CLICK_CLOSE == 0:
+ return
+
+ # simulate the user pressing the close button on the tab
+ event.SetInt(AUI_BUTTON_CLOSE)
+ self.OnTabButton(event)
+
+
+ def OnTabRightDown(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_TAB_RIGHT_DOWN`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ tabs = event.GetEventObject()
+ if not tabs.GetEnabled(event.GetSelection()):
+ return
+
+ # patch event through to owner
+ wnd = tabs.GetWindowFromIdx(event.GetSelection())
+
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, self.GetId())
+ e.SetSelection(self._tabs.GetIdxFromWindow(wnd))
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def OnTabRightUp(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_TAB_RIGHT_UP`` event for :class:`AuiNotebook`.
+
+ :param `event`: a :class:`AuiNotebookEvent` event to be processed.
+ """
+
+ tabs = event.GetEventObject()
+ if not tabs.GetEnabled(event.GetSelection()):
+ return
+
+ # patch event through to owner
+ wnd = tabs.GetWindowFromIdx(event.GetSelection())
+
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, self.GetId())
+ e.SetSelection(self._tabs.GetIdxFromWindow(wnd))
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def SetNormalFont(self, font):
+ """
+ Sets the normal font for drawing tab labels.
+
+ :param Font `font`: the new font to use to draw tab labels in their normal, un-selected state.
+ """
+
+ self._normal_font = font
+ self.GetArtProvider().SetNormalFont(font)
+
+
+ def SetSelectedFont(self, font):
+ """
+ Sets the selected tab font for drawing tab labels.
+
+ :param Font `font`: the new font to use to draw tab labels in their selected state.
+ """
+
+ self._selected_font = font
+ self.GetArtProvider().SetSelectedFont(font)
+
+
+ def SetMeasuringFont(self, font):
+ """
+ Sets the font for calculating text measurements.
+
+ :param Font `font`: the new font to use to measure tab label text extents.
+ """
+
+ self.GetArtProvider().SetMeasuringFont(font)
+
+
+ def SetFont(self, font):
+ """
+ Sets the tab font.
+
+ :param Font `font`: the new font to use to draw tab labels in their normal, un-selected state.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ wx.PyPanel.SetFont(self, font)
+
+ selectedFont = wx.Font(font.GetPointSize(), font.GetFamily(),
+ font.GetStyle(), wx.BOLD, font.GetUnderlined(),
+ font.GetFaceName(), font.GetEncoding())
+
+ self.SetNormalFont(font)
+ self.SetSelectedFont(selectedFont)
+ self.SetMeasuringFont(selectedFont)
+
+ # Recalculate tab container size based on new font
+ self.UpdateTabCtrlHeight(force=False)
+ self.DoSizing()
+
+ return True
+
+
+ def GetTabCtrlHeight(self):
+ """ Returns the tab control height. """
+
+ return self._tab_ctrl_height
+
+
+ def GetHeightForPageHeight(self, pageHeight):
+ """
+ Gets the height of the notebook for a given page height.
+
+ :param integer `pageHeight`: the given page height.
+ """
+
+ self.UpdateTabCtrlHeight()
+
+ tabCtrlHeight = self.GetTabCtrlHeight()
+ decorHeight = 2
+ return tabCtrlHeight + pageHeight + decorHeight
+
+
+ def AdvanceSelection(self, forward=True, wrap=True):
+ """
+ Cycles through the tabs.
+
+ :param bool `forward`: whether to advance forward or backward;
+ :param bool `wrap`: ``True`` to return to the first tab if we reach the last tab.
+
+ :note: The call to this function generates the page changing events.
+ """
+
+ tabCtrl = self.GetActiveTabCtrl()
+ newPage = -1
+
+ focusWin = wx.Window.FindFocus()
+ activePage = tabCtrl.GetActivePage()
+ lenPages = len(tabCtrl.GetPages())
+
+ if lenPages == 1:
+ return False
+
+ if forward:
+ if lenPages > 1:
+
+ if activePage == -1 or activePage == lenPages - 1:
+ if not wrap:
+ return False
+
+ newPage = 0
+
+ elif activePage < lenPages - 1:
+ newPage = activePage + 1
+
+ else:
+
+ if lenPages > 1:
+ if activePage == -1 or activePage == 0:
+ if not wrap:
+ return False
+
+ newPage = lenPages - 1
+
+ elif activePage > 0:
+ newPage = activePage - 1
+
+
+ if newPage != -1:
+ if not self.GetEnabled(newPage):
+ return False
+
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, tabCtrl.GetId())
+ e.SetSelection(newPage)
+ e.SetOldSelection(activePage)
+ e.SetEventObject(tabCtrl)
+ self.GetEventHandler().ProcessEvent(e)
+
+## if focusWin:
+## focusWin.SetFocus()
+
+ return True
+
+
+ def ShowWindowMenu(self):
+ """
+ Shows the window menu for the active tab control associated with this
+ notebook, and returns ``True`` if a selection was made.
+ """
+
+ tabCtrl = self.GetActiveTabCtrl()
+ idx = tabCtrl.GetArtProvider().ShowDropDown(tabCtrl, tabCtrl.GetPages(), tabCtrl.GetActivePage())
+
+ if not self.GetEnabled(idx):
+ return False
+
+ if idx != -1:
+ e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, tabCtrl.GetId())
+ e.SetSelection(idx)
+ e.SetOldSelection(tabCtrl.GetActivePage())
+ e.SetEventObject(tabCtrl)
+ self.GetEventHandler().ProcessEvent(e)
+
+ return True
+
+ else:
+
+ return False
+
+
+ def AddTabAreaButton(self, id, location, normal_bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap, name=""):
+ """
+ Adds a button in the tab area.
+
+ :param integer `id`: the button identifier. This can be one of the following:
+
+ ============================== =================================
+ Button Identifier Description
+ ============================== =================================
+ ``AUI_BUTTON_CLOSE`` Shows a close button on the tab area
+ ``AUI_BUTTON_WINDOWLIST`` Shows a window list button on the tab area
+ ``AUI_BUTTON_LEFT`` Shows a left button on the tab area
+ ``AUI_BUTTON_RIGHT`` Shows a right button on the tab area
+ ============================== =================================
+
+ :param integer `location`: the button location. Can be ``wx.LEFT`` or ``wx.RIGHT``;
+ :param Bitmap `normal_bitmap`: the bitmap for an enabled tab;
+ :param Bitmap `disabled_bitmap`: the bitmap for a disabled tab;
+ :param string `name`: the button name.
+ """
+
+ active_tabctrl = self.GetActiveTabCtrl()
+ active_tabctrl.AddButton(id, location, normal_bitmap, disabled_bitmap, name=name)
+
+
+ def RemoveTabAreaButton(self, id):
+ """
+ Removes a button from the tab area.
+
+ :param integer `id`: the button identifier.
+
+ :see: :meth:`AddTabAreaButton` for a list of button identifiers.
+ """
+
+ active_tabctrl = self.GetActiveTabCtrl()
+ active_tabctrl.RemoveButton(id)
+
+
+ def CloneTabAreaButtons(self):
+ """
+ Clones the tab area buttons when the :class:`AuiNotebook` is being split.
+
+ :see: :meth:`AddTabAreaButton`
+
+ :note: Standard buttons for :class:`AuiNotebook` are not cloned, only custom ones.
+ """
+
+ active_tabctrl = self.GetActiveTabCtrl()
+ clones = active_tabctrl.CloneButtons()
+
+ return clones
+
+
+ def HasMultiplePages(self):
+ """
+ This method should be overridden to return ``True`` if this window has multiple pages. All
+ standard class with multiple pages such as :class:`Notebook`, :class:`Listbook` and :class:`Treebook`
+ already override it to return ``True`` and user-defined classes with similar behaviour
+ should do it as well to allow the library to handle such windows appropriately.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ return True
+
+
+ def GetDefaultBorder(self):
+ """ Returns the default border style for :class:`AuiNotebook`. """
+
+ return wx.BORDER_NONE
+
+
+ def NotebookPreview(self, thumbnail_size=200):
+ """
+ Generates a preview of all the pages in the notebook (MSW and GTK only).
+
+ :param integer `thumbnail_size`: the maximum size of every page thumbnail
+ (default=200 pixels).
+
+ :note: this functionality is currently unavailable on wxMAC.
+ """
+
+ if wx.Platform == "__WXMAC__":
+ return False
+
+ tabCtrl = self.GetActiveTabCtrl()
+ activePage = tabCtrl.GetActivePage()
+ pages = tabCtrl.GetPages()
+
+ pageStatus, pageText = [], []
+
+ for indx, page in enumerate(pages):
+
+ pageStatus.append(page.enabled)
+
+ if not page.enabled:
+ continue
+
+ self.SetSelectionToPage(page)
+ pageText.append(page.caption)
+
+ rect = page.window.GetScreenRect()
+ bmp = RescaleScreenShot(TakeScreenShot(rect), thumbnail_size)
+
+ page.enabled = False
+ if indx == 0:
+ il = wx.ImageList(bmp.GetWidth(), bmp.GetHeight(), True)
+
+ il.Add(bmp)
+
+ # create the list control
+ listCtrl = wx.ListCtrl(self, style=wx.LC_ICON|wx.LC_AUTOARRANGE|wx.LC_HRULES|wx.LC_VRULES,
+ name="__fake__page__")
+
+ # assign the image list to it
+ listCtrl.AssignImageList(il, wx.IMAGE_LIST_NORMAL)
+ listCtrl.__previousStatus = [activePage, pageStatus]
+
+ # create some items for the list
+ for indx, text in enumerate(pageText):
+ listCtrl.InsertImageStringItem(10000, text, indx)
+
+ self.AddPage(listCtrl, "AuiNotebook Preview", True, bitmap=auinotebook_preview.GetBitmap(), disabled_bitmap=wx.NullBitmap)
+ return True
+
+
+ def SetRenamable(self, page_idx, renamable):
+ """
+ Sets whether a tab can be renamed via a left double-click or not.
+
+ :param integer `page_idx`: the page index;
+ :param bool `renamable`: ``True`` if the page can be renamed.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ # update our own tab catalog
+ page_info = self._tabs.GetPage(page_idx)
+ page_info.renamable = renamable
+
+ # update what's on screen
+ ctrl, ctrl_idx = self.FindTab(page_info.window)
+ if not ctrl:
+ return False
+
+ info = ctrl.GetPage(ctrl_idx)
+ info.renamable = page_info.renamable
+
+ return True
+
+
+ def IsRenamable(self, page_idx):
+ """
+ Returns whether a tab can be renamed or not.
+
+ :param integer `page_idx`: the page index.
+
+ :returns: ``True`` is a page can be renamed, ``False`` otherwise.
+ """
+
+ if page_idx >= self._tabs.GetPageCount():
+ return False
+
+ page_info = self._tabs.GetPage(page_idx)
+ return page_info.renamable
+
+
+ def OnRenameCancelled(self, page_index):
+ """
+ Called by :class:`TabTextCtrl`, to cancel the changes and to send the
+ ``EVT_AUINOTEBOOK_END_LABEL_EDIT`` event.
+
+ :param integer `page_index`: the page index in the notebook.
+ """
+
+ # let owner know that the edit was cancelled
+ evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_END_LABEL_EDIT, self.GetId())
+
+ evt.SetSelection(page_index)
+ evt.SetEventObject(self)
+ evt.SetLabel("")
+ evt.SetEditCanceled(True)
+ self.GetEventHandler().ProcessEvent(evt)
+
+
+ def OnRenameAccept(self, page_index, value):
+ """
+ Called by :class:`TabTextCtrl`, to accept the changes and to send the
+ ``EVT_AUINOTEBOOK_END_LABEL_EDIT`` event.
+
+ :param integer `page_index`: the page index in the notebook;
+ :param string `value`: the new label for the tab.
+ """
+
+ evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_END_LABEL_EDIT, self.GetId())
+ evt.SetSelection(page_index)
+ evt.SetEventObject(self)
+ evt.SetLabel(value)
+ evt.SetEditCanceled(False)
+
+ return not self.GetEventHandler().ProcessEvent(evt) or evt.IsAllowed()
+
+
+ def ResetTextControl(self):
+ """ Called by :class:`TabTextCtrl` when it marks itself for deletion. """
+
+ if not self._textCtrl:
+ return
+
+ self._textCtrl.Destroy()
+ self._textCtrl = None
+
+ # tab height might have changed
+ self.UpdateTabCtrlHeight(force=True)
+
+
+ def EditTab(self, page_index):
+ """
+ Starts the editing of an item label, sending a ``EVT_AUINOTEBOOK_BEGIN_LABEL_EDIT`` event.
+
+ :param integer `page_index`: the page index we want to edit.
+ """
+
+ if page_index >= self._tabs.GetPageCount():
+ return False
+
+ if not self.IsRenamable(page_index):
+ return False
+
+ page_info = self._tabs.GetPage(page_index)
+ ctrl, ctrl_idx = self.FindTab(page_info.window)
+ if not ctrl:
+ return False
+
+ evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_LABEL_EDIT, self.GetId())
+ evt.SetSelection(page_index)
+ evt.SetEventObject(self)
+ if self.GetEventHandler().ProcessEvent(evt) and not evt.IsAllowed():
+ # vetoed by user
+ return False
+
+ if self._textCtrl is not None and page_info != self._textCtrl.item():
+ self._textCtrl.StopEditing()
+
+ self._textCtrl = TabTextCtrl(ctrl, page_info, page_index)
+ self._textCtrl.SetFocus()
+
+ return True
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/dockart.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/dockart.py
new file mode 100644
index 0000000..405d8f0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/dockart.py
@@ -0,0 +1,1187 @@
+"""
+Dock art provider code - a dock provider provides all drawing functionality to
+the AUI dock manager. This allows the dock manager to have a plugable look-and-feel.
+
+By default, a :class:`~lib.agw.aui.framemanager` uses an instance of this class called :mod:`~lib.agw.aui.dockart`
+which provides bitmap art and a colour scheme that is adapted to the major platforms'
+look. You can either derive from that class to alter its behaviour or write a
+completely new dock art class. Call :meth:`AuiManager.SetArtProvider() <lib.agw.aui.framemanager.AuiManager.SetArtProvider>`
+to make use this new dock art.
+"""
+
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "31 March 2009"
+
+
+import wx
+import types
+
+from aui_utilities import BitmapFromBits, StepColour, ChopText, GetBaseColour
+from aui_utilities import DrawGradientRectangle, DrawMACCloseButton
+from aui_utilities import DarkenBitmap, LightContrastColour
+from aui_constants import *
+
+optionActive = 2**14
+""" Indicates that a pane is active and should display an active caption (if present). """
+
+_ctypes = False
+
+# Try to import winxptheme for ModernDockArt
+if wx.Platform == "__WXMSW__":
+ try:
+ import ctypes
+ import winxptheme
+ _ctypes = True
+ except ImportError:
+ pass
+
+# -- AuiDefaultDockArt class implementation --
+
+class AuiDefaultDockArt(object):
+ """
+ Dock art provider code - a dock provider provides all drawing functionality to the AUI dock manager.
+ This allows the dock manager to have a plugable look-and-feel.
+
+ By default, a :class:`~lib.agw.aui.framemanager.AuiManager` uses an instance of this class called
+ :class:`AuiDefaultDockArt` which provides bitmap art and a colour scheme that is adapted to the major
+ platforms' look. You can either derive from that class to alter its behaviour or
+ write a completely new dock art class.
+
+ Call :meth:`AuiManager.SetArtProvider() <lib.agw.aui.framemanager.AuiManager.SetArtProvider>`
+ to make use this new dock art.
+
+
+ **Metric Ordinals**
+
+ These are the possible pane dock art settings for :class:`AuiDefaultDockArt`:
+
+ ================================================ ======================================
+ Metric Ordinal Constant Description
+ ================================================ ======================================
+ ``AUI_DOCKART_SASH_SIZE`` Customizes the sash size
+ ``AUI_DOCKART_CAPTION_SIZE`` Customizes the caption size
+ ``AUI_DOCKART_GRIPPER_SIZE`` Customizes the gripper size
+ ``AUI_DOCKART_PANE_BORDER_SIZE`` Customizes the pane border size
+ ``AUI_DOCKART_PANE_BUTTON_SIZE`` Customizes the pane button size
+ ``AUI_DOCKART_BACKGROUND_COLOUR`` Customizes the background colour
+ ``AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR`` Customizes the background gradient colour
+ ``AUI_DOCKART_SASH_COLOUR`` Customizes the sash colour
+ ``AUI_DOCKART_ACTIVE_CAPTION_COLOUR`` Customizes the active caption colour
+ ``AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR`` Customizes the active caption gradient colour
+ ``AUI_DOCKART_INACTIVE_CAPTION_COLOUR`` Customizes the inactive caption colour
+ ``AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR`` Customizes the inactive gradient caption colour
+ ``AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR`` Customizes the active caption text colour
+ ``AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR`` Customizes the inactive caption text colour
+ ``AUI_DOCKART_BORDER_COLOUR`` Customizes the border colour
+ ``AUI_DOCKART_GRIPPER_COLOUR`` Customizes the gripper colour
+ ``AUI_DOCKART_CAPTION_FONT`` Customizes the caption font
+ ``AUI_DOCKART_GRADIENT_TYPE`` Customizes the gradient type (no gradient, vertical or horizontal)
+ ``AUI_DOCKART_DRAW_SASH_GRIP`` Draw a sash grip on the sash
+ ``AUI_DOCKART_HINT_WINDOW_COLOUR`` Customizes the hint window background colour (currently light blue)
+ ================================================ ======================================
+
+
+ **Gradient Types**
+
+ These are the possible gradient dock art settings for :class:`AuiDefaultDockArt`:
+
+ ============================================ ======================================
+ Gradient Constant Description
+ ============================================ ======================================
+ ``AUI_GRADIENT_NONE`` No gradient on the captions
+ ``AUI_GRADIENT_VERTICAL`` Vertical gradient on the captions
+ ``AUI_GRADIENT_HORIZONTAL`` Horizontal gradient on the captions
+ ============================================ ======================================
+
+
+ **Button States**
+
+ These are the possible pane button / :class:`~lib.agw.aui.auibook.AuiNotebook` button /
+ :class:`~lib.agw.aui.auibar.AuiToolBar` button states:
+
+ ============================================ ======================================
+ Button State Constant Description
+ ============================================ ======================================
+ ``AUI_BUTTON_STATE_NORMAL`` Normal button state
+ ``AUI_BUTTON_STATE_HOVER`` Hovered button state
+ ``AUI_BUTTON_STATE_PRESSED`` Pressed button state
+ ``AUI_BUTTON_STATE_DISABLED`` Disabled button state
+ ``AUI_BUTTON_STATE_HIDDEN`` Hidden button state
+ ``AUI_BUTTON_STATE_CHECKED`` Checked button state
+ ============================================ ======================================
+
+
+ **Button Identifiers**
+
+ These are the possible pane button / :class:`~lib.agw.aui.auibook.AuiNotebook` button /
+ :class:`~lib.agw.aui.auibar.AuiToolBar` button identifiers:
+
+ ============================================ ======================================
+ Button Identifier Description
+ ============================================ ======================================
+ ``AUI_BUTTON_CLOSE`` Shows a close button on the pane
+ ``AUI_BUTTON_MAXIMIZE_RESTORE`` Shows a maximize/restore button on the pane
+ ``AUI_BUTTON_MINIMIZE`` Shows a minimize button on the pane
+ ``AUI_BUTTON_PIN`` Shows a pin button on the pane
+ ``AUI_BUTTON_OPTIONS`` Shows an option button on the pane (not implemented)
+ ``AUI_BUTTON_WINDOWLIST`` Shows a window list button on the pane (for :class:`~lib.agw.aui.auibook.AuiNotebook`)
+ ``AUI_BUTTON_LEFT`` Shows a left button on the pane (for :class:`~lib.agw.aui.auibook.AuiNotebook`)
+ ``AUI_BUTTON_RIGHT`` Shows a right button on the pane (for :class:`~lib.agw.aui.auibook.AuiNotebook`)
+ ``AUI_BUTTON_UP`` Shows an up button on the pane (not implemented)
+ ``AUI_BUTTON_DOWN`` Shows a down button on the pane (not implemented)
+ ``AUI_BUTTON_CUSTOM1`` Shows a custom button on the pane (not implemented)
+ ``AUI_BUTTON_CUSTOM2`` Shows a custom button on the pane (not implemented)
+ ``AUI_BUTTON_CUSTOM3`` Shows a custom button on the pane (not implemented)
+ ============================================ ======================================
+
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ self.Init()
+
+ isMac = wx.Platform == "__WXMAC__"
+
+ if isMac:
+ self._caption_font = wx.SMALL_FONT
+ else:
+ self._caption_font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)
+
+ self.SetDefaultPaneBitmaps(isMac)
+ self._restore_bitmap = wx.BitmapFromXPMData(restore_xpm)
+
+ # default metric values
+ self._sash_size = 4
+
+ if isMac:
+ # This really should be implemented in wx.SystemSettings
+ # There is no way to do this that I am aware outside of using
+ # the cocoa python bindings. 8 pixels looks correct on my system
+ # so hard coding it for now.
+
+ # How do I translate this?!? Not sure of the below implementation...
+ # SInt32 height;
+ # GetThemeMetric( kThemeMetricSmallPaneSplitterHeight , &height );
+ # self._sash_size = height;
+
+ self._sash_size = 8 # Carbon.Appearance.kThemeMetricPaneSplitterHeight
+
+ elif wx.Platform == "__WXGTK__":
+ self._sash_size = wx.RendererNative.Get().GetSplitterParams(wx.GetTopLevelWindows()[0]).widthSash
+
+ else:
+ self._sash_size = 4
+
+ self._caption_size = 19
+ self._border_size = 1
+ self._button_size = 14
+ self._gripper_size = 9
+ self._gradient_type = AUI_GRADIENT_VERTICAL
+ self._draw_sash = False
+
+
+ def Init(self):
+ """ Initializes the dock art. """
+
+ self.SetDefaultColours()
+
+ isMac = wx.Platform == "__WXMAC__"
+
+ if isMac:
+ self._active_caption_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ else:
+ self._active_caption_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+
+ self._active_caption_gradient_colour = LightContrastColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT))
+ self._active_caption_text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
+ self._inactive_caption_text_colour = wx.BLACK
+
+
+ def SetDefaultColours(self, base_colour=None):
+ """
+ Sets the default colours, which are calculated from the given base colour.
+
+ :param `base_colour`: an instance of :class:`Colour`. If defaulted to ``None``, a colour
+ is generated accordingly to the platform and theme.
+ """
+
+ if base_colour is None:
+ base_colour = GetBaseColour()
+
+ darker1_colour = StepColour(base_colour, 85)
+ darker2_colour = StepColour(base_colour, 75)
+ darker3_colour = StepColour(base_colour, 60)
+ darker4_colour = StepColour(base_colour, 40)
+
+ self._background_colour = base_colour
+ self._background_gradient_colour = StepColour(base_colour, 180)
+
+ self._inactive_caption_colour = darker1_colour
+ self._inactive_caption_gradient_colour = StepColour(base_colour, 97)
+
+ self._sash_brush = wx.Brush(base_colour)
+ self._background_brush = wx.Brush(base_colour)
+ self._border_pen = wx.Pen(darker2_colour)
+ self._gripper_brush = wx.Brush(base_colour)
+ self._gripper_pen1 = wx.Pen(darker4_colour)
+ self._gripper_pen2 = wx.Pen(darker3_colour)
+ self._gripper_pen3 = wx.WHITE_PEN
+
+ self._hint_background_colour = colourHintBackground
+
+
+ def GetMetric(self, id):
+ """
+ Gets the value of a certain setting.
+
+ :param integer `id`: can be one of the size values in `Metric Ordinals`.
+ """
+
+
+ if id == AUI_DOCKART_SASH_SIZE:
+ return self._sash_size
+ elif id == AUI_DOCKART_CAPTION_SIZE:
+ return self._caption_size
+ elif id == AUI_DOCKART_GRIPPER_SIZE:
+ return self._gripper_size
+ elif id == AUI_DOCKART_PANE_BORDER_SIZE:
+ return self._border_size
+ elif id == AUI_DOCKART_PANE_BUTTON_SIZE:
+ return self._button_size
+ elif id == AUI_DOCKART_GRADIENT_TYPE:
+ return self._gradient_type
+ elif id == AUI_DOCKART_DRAW_SASH_GRIP:
+ return self._draw_sash
+ else:
+ raise Exception("Invalid Metric Ordinal.")
+
+
+ def SetMetric(self, id, new_val):
+ """
+ Sets the value of a certain setting using `new_val`
+
+ :param integer `id`: can be one of the size values in `Metric Ordinals`;
+ :param `new_val`: the new value of the setting.
+ """
+
+ if id == AUI_DOCKART_SASH_SIZE:
+ self._sash_size = new_val
+ elif id == AUI_DOCKART_CAPTION_SIZE:
+ self._caption_size = new_val
+ elif id == AUI_DOCKART_GRIPPER_SIZE:
+ self._gripper_size = new_val
+ elif id == AUI_DOCKART_PANE_BORDER_SIZE:
+ self._border_size = new_val
+ elif id == AUI_DOCKART_PANE_BUTTON_SIZE:
+ self._button_size = new_val
+ elif id == AUI_DOCKART_GRADIENT_TYPE:
+ self._gradient_type = new_val
+ elif id == AUI_DOCKART_DRAW_SASH_GRIP:
+ self._draw_sash = new_val
+ else:
+ raise Exception("Invalid Metric Ordinal.")
+
+
+ def GetColor(self, id):
+ """
+ Gets the colour of a certain setting.
+
+ :param integer `id`: can be one of the colour values in `Metric Ordinals`.
+ """
+
+ if id == AUI_DOCKART_BACKGROUND_COLOUR:
+ return self._background_brush.GetColour()
+ elif id == AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR:
+ return self._background_gradient_colour
+ elif id == AUI_DOCKART_SASH_COLOUR:
+ return self._sash_brush.GetColour()
+ elif id == AUI_DOCKART_INACTIVE_CAPTION_COLOUR:
+ return self._inactive_caption_colour
+ elif id == AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR:
+ return self._inactive_caption_gradient_colour
+ elif id == AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR:
+ return self._inactive_caption_text_colour
+ elif id == AUI_DOCKART_ACTIVE_CAPTION_COLOUR:
+ return self._active_caption_colour
+ elif id == AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR:
+ return self._active_caption_gradient_colour
+ elif id == AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR:
+ return self._active_caption_text_colour
+ elif id == AUI_DOCKART_BORDER_COLOUR:
+ return self._border_pen.GetColour()
+ elif id == AUI_DOCKART_GRIPPER_COLOUR:
+ return self._gripper_brush.GetColour()
+ elif id == AUI_DOCKART_HINT_WINDOW_COLOUR:
+ return self._hint_background_colour
+ else:
+ raise Exception("Invalid Colour Ordinal.")
+
+
+ def SetColor(self, id, colour):
+ """
+ Sets the colour of a certain setting.
+
+ :param integer `id`: can be one of the colour values in `Metric Ordinals`;
+ :param `colour`: the new value of the setting.
+ :type `colour`: :class:`Colour` or tuple or integer
+ """
+
+ if isinstance(colour, basestring):
+ colour = wx.NamedColour(colour)
+ elif isinstance(colour, types.TupleType):
+ colour = wx.Colour(*colour)
+ elif isinstance(colour, types.IntType):
+ colour = wx.ColourRGB(colour)
+
+ if id == AUI_DOCKART_BACKGROUND_COLOUR:
+ self._background_brush.SetColour(colour)
+ elif id == AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR:
+ self._background_gradient_colour = colour
+ elif id == AUI_DOCKART_SASH_COLOUR:
+ self._sash_brush.SetColour(colour)
+ elif id == AUI_DOCKART_INACTIVE_CAPTION_COLOUR:
+ self._inactive_caption_colour = colour
+ if not self._custom_pane_bitmaps and wx.Platform == "__WXMAC__":
+ # No custom bitmaps for the pane close button
+ # Change the MAC close bitmap colour
+ self._inactive_close_bitmap = DrawMACCloseButton(wx.WHITE, colour)
+
+ elif id == AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR:
+ self._inactive_caption_gradient_colour = colour
+ elif id == AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR:
+ self._inactive_caption_text_colour = colour
+ elif id == AUI_DOCKART_ACTIVE_CAPTION_COLOUR:
+ self._active_caption_colour = colour
+ if not self._custom_pane_bitmaps and wx.Platform == "__WXMAC__":
+ # No custom bitmaps for the pane close button
+ # Change the MAC close bitmap colour
+ self._active_close_bitmap = DrawMACCloseButton(wx.WHITE, colour)
+
+ elif id == AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR:
+ self._active_caption_gradient_colour = colour
+ elif id == AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR:
+ self._active_caption_text_colour = colour
+ elif id == AUI_DOCKART_BORDER_COLOUR:
+ self._border_pen.SetColour(colour)
+ elif id == AUI_DOCKART_GRIPPER_COLOUR:
+ self._gripper_brush.SetColour(colour)
+ self._gripper_pen1.SetColour(StepColour(colour, 40))
+ self._gripper_pen2.SetColour(StepColour(colour, 60))
+ elif id == AUI_DOCKART_HINT_WINDOW_COLOUR:
+ self._hint_background_colour = colour
+ else:
+ raise Exception("Invalid Colour Ordinal.")
+
+
+ GetColour = GetColor
+ SetColour = SetColor
+
+ def SetFont(self, id, font):
+ """
+ Sets a font setting.
+
+ :param integer `id`: must be ``AUI_DOCKART_CAPTION_FONT``;
+ :param `font`: an instance of :class:`Font`.
+ """
+
+ if id == AUI_DOCKART_CAPTION_FONT:
+ self._caption_font = font
+
+
+ def GetFont(self, id):
+ """
+ Gets a font setting.
+
+ :param integer `id`: must be ``AUI_DOCKART_CAPTION_FONT``, otherwise :class:`NullFont` is returned.
+ """
+
+ if id == AUI_DOCKART_CAPTION_FONT:
+ return self._caption_font
+
+ return wx.NullFont
+
+
+ def DrawSash(self, dc, window, orient, rect):
+ """
+ Draws a sash between two windows.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `window`: an instance of :class:`Window`;
+ :param integer `orient`: the sash orientation;
+ :param Rect `rect`: the sash rectangle.
+ """
+
+ # AG: How do we make this work?!?
+ # RendererNative does not use the sash_brush chosen by the user
+ # and the rect.GetSize() is ignored as the sash is always drawn
+ # 3 pixel wide
+ # wx.RendererNative.Get().DrawSplitterSash(window, dc, rect.GetSize(), pos, orient)
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._sash_brush)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ draw_sash = self.GetMetric(AUI_DOCKART_DRAW_SASH_GRIP)
+ if draw_sash:
+ self.DrawSashGripper(dc, orient, rect)
+
+
+ def DrawBackground(self, dc, window, orient, rect):
+ """
+ Draws a background.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `window`: an instance of :class:`Window`;
+ :param integer `orient`: the gradient (if any) orientation;
+ :param Rect `rect`: the background rectangle.
+ """
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ if wx.Platform == "__WXMAC__":
+ # we have to clear first, otherwise we are drawing a light striped pattern
+ # over an already darker striped background
+ dc.SetBrush(wx.WHITE_BRUSH)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ DrawGradientRectangle(dc, rect, self._background_brush.GetColour(),
+ self._background_gradient_colour,
+ AUI_GRADIENT_HORIZONTAL, rect.x, 700)
+
+
+ def DrawBorder(self, dc, window, rect, pane):
+ """
+ Draws the pane border.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `window`: an instance of :class:`Window`;
+ :param Rect `rect`: the border rectangle;
+ :param `pane`: the pane for which the border is drawn.
+ """
+
+ drect = wx.Rect(*rect)
+
+ dc.SetPen(self._border_pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ border_width = self.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
+
+ if pane.IsToolbar():
+
+ for ii in xrange(0, border_width):
+
+ dc.SetPen(wx.WHITE_PEN)
+ dc.DrawLine(drect.x, drect.y, drect.x+drect.width, drect.y)
+ dc.DrawLine(drect.x, drect.y, drect.x, drect.y+drect.height)
+ dc.SetPen(self._border_pen)
+ dc.DrawLine(drect.x, drect.y+drect.height-1,
+ drect.x+drect.width, drect.y+drect.height-1)
+ dc.DrawLine(drect.x+drect.width-1, drect.y,
+ drect.x+drect.width-1, drect.y+drect.height)
+ drect.Deflate(1, 1)
+
+ else:
+
+ for ii in xrange(0, border_width):
+
+ dc.DrawRectangle(drect.x, drect.y, drect.width, drect.height)
+ drect.Deflate(1, 1)
+
+
+ def DrawCaptionBackground(self, dc, rect, pane):
+ """
+ Draws the text caption background in the pane.
+
+ :param `dc`: a :class:`DC` device context;
+ :param Rect `rect`: the text caption rectangle;
+ :param `pane`: the pane for which the text background is drawn.
+ """
+
+ active = pane.state & optionActive
+
+ if self._gradient_type == AUI_GRADIENT_NONE:
+ if active:
+ dc.SetBrush(wx.Brush(self._active_caption_colour))
+ else:
+ dc.SetBrush(wx.Brush(self._inactive_caption_colour))
+
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ else:
+
+ switch_gradient = pane.HasCaptionLeft()
+ gradient_type = self._gradient_type
+ if switch_gradient:
+ gradient_type = (self._gradient_type == AUI_GRADIENT_HORIZONTAL and [AUI_GRADIENT_VERTICAL] or \
+ [AUI_GRADIENT_HORIZONTAL])[0]
+
+ if active:
+ if wx.Platform == "__WXMAC__":
+ DrawGradientRectangle(dc, rect, self._active_caption_colour,
+ self._active_caption_gradient_colour,
+ gradient_type)
+ else:
+ DrawGradientRectangle(dc, rect, self._active_caption_gradient_colour,
+ self._active_caption_colour,
+ gradient_type)
+ else:
+ if wx.Platform == "__WXMAC__":
+ DrawGradientRectangle(dc, rect, self._inactive_caption_gradient_colour,
+ self._inactive_caption_colour,
+ gradient_type)
+ else:
+ DrawGradientRectangle(dc, rect, self._inactive_caption_colour,
+ self._inactive_caption_gradient_colour,
+ gradient_type)
+
+
+ def DrawIcon(self, dc, rect, pane):
+ """
+ Draws the icon in the pane caption area.
+
+ :param `dc`: a :class:`DC` device context;
+ :param Rect `rect`: the pane caption rectangle;
+ :param `pane`: the pane for which the icon is drawn.
+ """
+
+ # Draw the icon centered vertically
+ if pane.icon.Ok():
+ if pane.HasCaptionLeft():
+ bmp = wx.ImageFromBitmap(pane.icon).Rotate90(clockwise=False)
+ dc.DrawBitmap(bmp.ConvertToBitmap(), rect.x+(rect.width-pane.icon.GetWidth())/2, rect.y+rect.height-2-pane.icon.GetHeight(), True)
+ else:
+ dc.DrawBitmap(pane.icon, rect.x+2, rect.y+(rect.height-pane.icon.GetHeight())/2, True)
+
+
+ def DrawCaption(self, dc, window, text, rect, pane):
+ """
+ Draws the text in the pane caption.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `window`: an instance of :class:`Window`;
+ :param string `text`: the text to be displayed;
+ :param Rect `rect`: the pane caption rectangle;
+ :param `pane`: the pane for which the text is drawn.
+ """
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetFont(self._caption_font)
+
+ self.DrawCaptionBackground(dc, rect, pane)
+
+ if pane.state & optionActive:
+ dc.SetTextForeground(self._active_caption_text_colour)
+ else:
+ dc.SetTextForeground(self._inactive_caption_text_colour)
+
+ w, h = dc.GetTextExtent("ABCDEFHXfgkj")
+
+ clip_rect = wx.Rect(*rect)
+ btns = pane.CountButtons()
+
+ captionLeft = pane.HasCaptionLeft()
+ variable = (captionLeft and [rect.height] or [rect.width])[0]
+
+ variable -= 3 # text offset
+ variable -= 2 # button padding
+
+ caption_offset = 0
+ if pane.icon:
+ if captionLeft:
+ caption_offset += pane.icon.GetHeight() + 3
+ else:
+ caption_offset += pane.icon.GetWidth() + 3
+
+ self.DrawIcon(dc, rect, pane)
+
+ variable -= caption_offset
+ variable -= btns*(self._button_size + self._border_size)
+ draw_text = ChopText(dc, text, variable)
+
+ if captionLeft:
+ dc.DrawRotatedText(draw_text, rect.x+(rect.width/2)-(h/2)-1, rect.y+rect.height-3-caption_offset, 90)
+ else:
+ dc.DrawText(draw_text, rect.x+3+caption_offset, rect.y+(rect.height/2)-(h/2)-1)
+
+
+ def RequestUserAttention(self, dc, window, text, rect, pane):
+ """
+ Requests the user attention by intermittently highlighting the pane caption.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `window`: an instance of :class:`Window`;
+ :param string `text`: the text to be displayed;
+ :param Rect `rect`: the pane caption rectangle;
+ :param `pane`: the pane for which we want to attract the user attention.
+ """
+
+ state = pane.state
+ pane.state &= ~optionActive
+
+ for indx in xrange(6):
+ active = (indx%2 == 0 and [True] or [False])[0]
+ if active:
+ pane.state |= optionActive
+ else:
+ pane.state &= ~optionActive
+
+ self.DrawCaptionBackground(dc, rect, pane)
+ self.DrawCaption(dc, window, text, rect, pane)
+ wx.SafeYield()
+ wx.MilliSleep(350)
+
+ pane.state = state
+
+
+ def DrawGripper(self, dc, window, rect, pane):
+ """
+ Draws a gripper on the pane.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `window`: an instance of :class:`Window`;
+ :param Rect `rect`: the pane caption rectangle;
+ :param `pane`: the pane for which the gripper is drawn.
+ """
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._gripper_brush)
+
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ if not pane.HasGripperTop():
+ y = 4
+ while 1:
+ dc.SetPen(self._gripper_pen1)
+ dc.DrawPoint(rect.x+3, rect.y+y)
+ dc.SetPen(self._gripper_pen2)
+ dc.DrawPoint(rect.x+3, rect.y+y+1)
+ dc.DrawPoint(rect.x+4, rect.y+y)
+ dc.SetPen(self._gripper_pen3)
+ dc.DrawPoint(rect.x+5, rect.y+y+1)
+ dc.DrawPoint(rect.x+5, rect.y+y+2)
+ dc.DrawPoint(rect.x+4, rect.y+y+2)
+ y = y + 4
+ if y > rect.GetHeight() - 4:
+ break
+ else:
+ x = 4
+ while 1:
+ dc.SetPen(self._gripper_pen1)
+ dc.DrawPoint(rect.x+x, rect.y+3)
+ dc.SetPen(self._gripper_pen2)
+ dc.DrawPoint(rect.x+x+1, rect.y+3)
+ dc.DrawPoint(rect.x+x, rect.y+4)
+ dc.SetPen(self._gripper_pen3)
+ dc.DrawPoint(rect.x+x+1, rect.y+5)
+ dc.DrawPoint(rect.x+x+2, rect.y+5)
+ dc.DrawPoint(rect.x+x+2, rect.y+4)
+ x = x + 4
+ if x > rect.GetWidth() - 4:
+ break
+
+
+ def DrawPaneButton(self, dc, window, button, button_state, _rect, pane):
+ """
+ Draws a pane button in the pane caption area.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `window`: an instance of :class:`Window`;
+ :param integer `button`: the button to be drawn;
+ :param integer `button_state`: the pane button state;
+ :param Rect `_rect`: the pane caption rectangle;
+ :param `pane`: the pane for which the button is drawn.
+ """
+
+ if not pane:
+ return
+
+ if button == AUI_BUTTON_CLOSE:
+ if pane.state & optionActive:
+ bmp = self._active_close_bitmap
+ else:
+ bmp = self._inactive_close_bitmap
+
+ elif button == AUI_BUTTON_PIN:
+ if pane.state & optionActive:
+ bmp = self._active_pin_bitmap
+ else:
+ bmp = self._inactive_pin_bitmap
+
+ elif button == AUI_BUTTON_MAXIMIZE_RESTORE:
+ if pane.IsMaximized():
+ if pane.state & optionActive:
+ bmp = self._active_restore_bitmap
+ else:
+ bmp = self._inactive_restore_bitmap
+ else:
+ if pane.state & optionActive:
+ bmp = self._active_maximize_bitmap
+ else:
+ bmp = self._inactive_maximize_bitmap
+
+ elif button == AUI_BUTTON_MINIMIZE:
+ if pane.state & optionActive:
+ bmp = self._active_minimize_bitmap
+ else:
+ bmp = self._inactive_minimize_bitmap
+
+ isVertical = pane.HasCaptionLeft()
+
+ rect = wx.Rect(*_rect)
+
+ if isVertical:
+ old_x = rect.x
+ rect.x = rect.x + (rect.width/2) - (bmp.GetWidth()/2)
+ rect.width = old_x + rect.width - rect.x - 1
+ else:
+ old_y = rect.y
+ rect.y = rect.y + (rect.height/2) - (bmp.GetHeight()/2)
+ rect.height = old_y + rect.height - rect.y - 1
+
+ if button_state == AUI_BUTTON_STATE_PRESSED:
+ rect.x += 1
+ rect.y += 1
+
+ if button_state in [AUI_BUTTON_STATE_HOVER, AUI_BUTTON_STATE_PRESSED]:
+
+ if pane.state & optionActive:
+
+ dc.SetBrush(wx.Brush(StepColour(self._active_caption_colour, 120)))
+ dc.SetPen(wx.Pen(StepColour(self._active_caption_colour, 70)))
+
+ else:
+
+ dc.SetBrush(wx.Brush(StepColour(self._inactive_caption_colour, 120)))
+ dc.SetPen(wx.Pen(StepColour(self._inactive_caption_colour, 70)))
+
+ if wx.Platform != "__WXMAC__":
+ # draw the background behind the button
+ dc.DrawRectangle(rect.x, rect.y, 15, 15)
+ else:
+ # Darker the bitmap a bit
+ bmp = DarkenBitmap(bmp, self._active_caption_colour, StepColour(self._active_caption_colour, 110))
+
+ if isVertical:
+ bmp = wx.ImageFromBitmap(bmp).Rotate90(clockwise=False).ConvertToBitmap()
+
+ # draw the button itself
+ dc.DrawBitmap(bmp, rect.x, rect.y, True)
+
+
+ def DrawSashGripper(self, dc, orient, rect):
+ """
+ Draws a sash gripper on a sash between two windows.
+
+ :param `dc`: a :class:`DC` device context;
+ :param integer `orient`: the sash orientation;
+ :param Rect `rect`: the sash rectangle.
+ """
+
+ dc.SetBrush(self._gripper_brush)
+
+ if orient == wx.HORIZONTAL: # horizontal sash
+
+ x = rect.x + int((1.0/4.0)*rect.width)
+ xend = rect.x + int((3.0/4.0)*rect.width)
+ y = rect.y + (rect.height/2) - 1
+
+ while 1:
+ dc.SetPen(self._gripper_pen3)
+ dc.DrawRectangle(x, y, 2, 2)
+ dc.SetPen(self._gripper_pen2)
+ dc.DrawPoint(x+1, y+1)
+ x = x + 5
+
+ if x >= xend:
+ break
+
+ else:
+
+ y = rect.y + int((1.0/4.0)*rect.height)
+ yend = rect.y + int((3.0/4.0)*rect.height)
+ x = rect.x + (rect.width/2) - 1
+
+ while 1:
+ dc.SetPen(self._gripper_pen3)
+ dc.DrawRectangle(x, y, 2, 2)
+ dc.SetPen(self._gripper_pen2)
+ dc.DrawPoint(x+1, y+1)
+ y = y + 5
+
+ if y >= yend:
+ break
+
+
+ def SetDefaultPaneBitmaps(self, isMac):
+ """
+ Assigns the default pane bitmaps.
+
+ :param bool `isMac`: whether we are on wxMAC or not.
+ """
+
+ if isMac:
+ self._inactive_close_bitmap = DrawMACCloseButton(wx.WHITE, self._inactive_caption_colour)
+ self._active_close_bitmap = DrawMACCloseButton(wx.WHITE, self._active_caption_colour)
+ else:
+ self._inactive_close_bitmap = BitmapFromBits(close_bits, 16, 16, self._inactive_caption_text_colour)
+ self._active_close_bitmap = BitmapFromBits(close_bits, 16, 16, self._active_caption_text_colour)
+
+ if isMac:
+ self._inactive_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, wx.WHITE)
+ self._active_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, wx.WHITE)
+ else:
+ self._inactive_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, self._inactive_caption_text_colour)
+ self._active_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, self._active_caption_text_colour)
+
+ if isMac:
+ self._inactive_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, wx.WHITE)
+ self._active_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, wx.WHITE)
+ else:
+ self._inactive_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, self._inactive_caption_text_colour)
+ self._active_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, self._active_caption_text_colour)
+
+ if isMac:
+ self._inactive_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, wx.WHITE)
+ self._active_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, wx.WHITE)
+ else:
+ self._inactive_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, self._inactive_caption_text_colour)
+ self._active_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, self._active_caption_text_colour)
+
+ self._inactive_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, self._inactive_caption_text_colour)
+ self._active_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, self._active_caption_text_colour)
+
+ self._custom_pane_bitmaps = False
+
+
+ def SetCustomPaneBitmap(self, bmp, button, active, maximize=False):
+ """
+ Sets a custom button bitmap for the pane button.
+
+ :param Bitmap `bmp`: the actual bitmap to set;
+ :param integer `button`: the button identifier;
+ :param bool `active`: whether it is the bitmap for the active button or not;
+ :param bool `maximize`: used to distinguish between the maximize and restore bitmaps.
+ """
+
+ if bmp.GetWidth() > 16 or bmp.GetHeight() > 16:
+ raise Exception("The input bitmap is too big")
+
+ if button == AUI_BUTTON_CLOSE:
+ if active:
+ self._active_close_bitmap = bmp
+ else:
+ self._inactive_close_bitmap = bmp
+
+ if wx.Platform == "__WXMAC__":
+ self._custom_pane_bitmaps = True
+
+ elif button == AUI_BUTTON_PIN:
+ if active:
+ self._active_pin_bitmap = bmp
+ else:
+ self._inactive_pin_bitmap = bmp
+
+ elif button == AUI_BUTTON_MAXIMIZE_RESTORE:
+ if maximize:
+ if active:
+ self._active_maximize_bitmap = bmp
+ else:
+ self._inactive_maximize_bitmap = bmp
+ else:
+ if active:
+ self._active_restore_bitmap = bmp
+ else:
+ self._inactive_restore_bitmap = bmp
+
+ elif button == AUI_BUTTON_MINIMIZE:
+ if active:
+ self._active_minimize_bitmap = bmp
+ else:
+ self._inactive_minimize_bitmap = bmp
+
+
+if _ctypes:
+ class RECT(ctypes.Structure):
+ """ Used to handle :class:`ModernDockArt` on Windows XP/Vista/7. """
+ _fields_ = [('left', ctypes.c_ulong),('top', ctypes.c_ulong),('right', ctypes.c_ulong),('bottom', ctypes.c_ulong)]
+
+ def dump(self):
+ """ Dumps `self` as a :class:`Rect`. """
+ return map(int, (self.left, self.top, self.right, self.bottom))
+
+
+ class SIZE(ctypes.Structure):
+ """ Used to handle :class:`ModernDockArt` on Windows XP/Vista/7. """
+ _fields_ = [('x', ctypes.c_long),('y', ctypes.c_long)]
+
+
+class ModernDockArt(AuiDefaultDockArt):
+ """
+ ModernDockArt is a custom `AuiDockArt` class, that implements a look similar to Firefox and other recents applications.
+
+ Is uses the `winxptheme <http://sourceforge.net/projects/pywin32/>`_ module and
+ XP themes whenever possible, so it should look good even if the user has a custom theme.
+
+ :note: This dock art is Windows only and will only work if you have installed
+ Mark Hammond's `pywin32` module (http://sourceforge.net/projects/pywin32/).
+ """
+
+ def __init__(self, win):
+ """
+ Default class constructor.
+
+ :param Window `win`: the window managed by :class:`~lib.agw.aui.framemanager.AuiManager`.
+ """
+
+ AuiDefaultDockArt.__init__(self)
+
+ self.win = win
+
+ # Get the size of a small close button (themed)
+ hwnd = self.win.GetHandle()
+ self.usingTheme = False
+
+ if _ctypes:
+ self.hTheme1 = winxptheme.OpenThemeData(hwnd, "Window")
+ self.usingTheme = True
+
+ if not self.hTheme1:
+ self.usingTheme = False
+
+ self._button_size = 13
+
+ self._button_border_size = 3
+ self._caption_text_indent = 6
+ self._caption_size = 22
+
+ # We only highlight the active pane with the caption text being in bold.
+ # So we do not want a special colour for active elements.
+ self._active_close_bitmap = self._inactive_close_bitmap
+
+ self.Init()
+
+
+ def Init(self):
+ """ Initializes the dock art. """
+
+ AuiDefaultDockArt.Init(self)
+
+ self._active_caption_colour = self._inactive_caption_colour
+ self._active_caption_text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_CAPTIONTEXT)
+ self._inactive_caption_text_colour = self._active_caption_text_colour
+
+
+ def DrawCaption(self, dc, window, text, rect, pane):
+ """
+ Draws the text in the pane caption.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `window`: an instance of :class:`Window`;
+ :param string `text`: the text to be displayed;
+ :param Rect `rect`: the pane caption rectangle;
+ :param `pane`: the pane for which the text is drawn.
+ """
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ self.DrawCaptionBackground(dc, rect, pane)
+
+ active = ((pane.state & optionActive) and [True] or [False])[0]
+
+ self._caption_font.SetWeight(wx.FONTWEIGHT_BOLD)
+ dc.SetFont(self._caption_font)
+
+ if active:
+ dc.SetTextForeground(self._active_caption_text_colour)
+ else:
+ dc.SetTextForeground(self._inactive_caption_text_colour)
+
+ w, h = dc.GetTextExtent("ABCDEFHXfgkj")
+
+ clip_rect = wx.Rect(*rect)
+ btns = pane.CountButtons()
+
+ captionLeft = pane.HasCaptionLeft()
+ variable = (captionLeft and [rect.height] or [rect.width])[0]
+
+ variable -= 3 # text offset
+ variable -= 2 # button padding
+
+ caption_offset = 0
+ if pane.icon:
+ if captionLeft:
+ caption_offset += pane.icon.GetHeight() + 3
+ else:
+ caption_offset += pane.icon.GetWidth() + 3
+
+ self.DrawIcon(dc, rect, pane)
+
+ diff = -2
+ if self.usingTheme:
+ diff = -1
+
+ variable -= caption_offset
+ variable -= btns*(self._button_size + self._button_border_size)
+ draw_text = ChopText(dc, text, variable)
+
+ if captionLeft:
+ dc.DrawRotatedText(draw_text, rect.x+(rect.width/2)-(h/2)-diff, rect.y+rect.height-3-caption_offset, 90)
+ else:
+ dc.DrawText(draw_text, rect.x+3+caption_offset, rect.y+(rect.height/2)-(h/2)-diff)
+
+
+ def DrawCaptionBackground(self, dc, rect, pane):
+ """
+ Draws the text caption background in the pane.
+
+ :param `dc`: a :class:`DC` device context;
+ :param Rect `rect`: the text caption rectangle;
+ :param `pane`: the pane for which we are drawing the caption background.
+ """
+
+ dc.SetBrush(self._background_brush)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ active = ((pane.state & optionActive) and [True] or [False])[0]
+
+ if self.usingTheme:
+
+ rectangle = wx.Rect()
+
+ rc = RECT(rectangle.x, rectangle.y, rectangle.width, rectangle.height)
+
+ # If rect x/y values are negative rc.right/bottom values will overflow and winxptheme.DrawThemeBackground
+ # will raise a TypeError. Ensure they are never negative.
+ rect.x = max(0, rect.x)
+ rect.y = max(0, rect.y)
+
+ rc.top = rect.x
+ rc.left = rect.y
+ rc.right = rect.x + rect.width
+ rc.bottom = rect.y + rect.height
+
+ if active:
+ winxptheme.DrawThemeBackground(self.hTheme1, dc.GetHDC(), 5, 1, (rc.top, rc.left, rc.right, rc.bottom), None)
+ else:
+ winxptheme.DrawThemeBackground(self.hTheme1, dc.GetHDC(), 5, 2, (rc.top, rc.left, rc.right, rc.bottom), None)
+
+ else:
+
+ AuiDefaultDockArt.DrawCaptionBackground(self, dc, rect, pane)
+
+
+ def RequestUserAttention(self, dc, window, text, rect, pane):
+ """
+ Requests the user attention by intermittently highlighting the pane caption.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `window`: an instance of :class:`Window`;
+ :param string `text`: the text to be displayed;
+ :param Rect `rect`: the pane caption rectangle;
+ :param `pane`: the pane for which the text is drawn.
+ """
+
+ state = pane.state
+ pane.state &= ~optionActive
+
+ for indx in xrange(6):
+ active = (indx%2 == 0 and [True] or [False])[0]
+ if active:
+ pane.state |= optionActive
+ else:
+ pane.state &= ~optionActive
+
+ self.DrawCaptionBackground(dc, rect, pane)
+ self.DrawCaption(dc, window, text, rect, pane)
+ wx.SafeYield()
+ wx.MilliSleep(350)
+
+ pane.state = state
+
+
+ def DrawPaneButton(self, dc, window, button, button_state, rect, pane):
+ """
+ Draws a pane button in the pane caption area.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `window`: an instance of :class:`Window`;
+ :param integer `button`: the button to be drawn;
+ :param integer `button_state`: the pane button state;
+ :param Rect `rect`: the pane caption rectangle;
+ :param `pane`: the pane for which the button is drawn.
+ """
+
+ if self.usingTheme:
+
+ hTheme = self.hTheme1
+
+ # Get the real button position (compensating for borders)
+ drect = wx.Rect(rect.x, rect.y, self._button_size, self._button_size)
+
+ # Draw the themed close button
+ rc = RECT(0, 0, 0, 0)
+ if pane.HasCaptionLeft():
+ rc.top = rect.x + self._button_border_size
+ rc.left = int(rect.y + 1.5*self._button_border_size)
+ rc.right = rect.x + self._button_size + self._button_border_size
+ rc.bottom = int(rect.y + self._button_size + 1.5*self._button_border_size)
+ else:
+ rc.top = rect.x - self._button_border_size
+ rc.left = int(rect.y + 1.5*self._button_border_size)
+ rc.right = rect.x + self._button_size- self._button_border_size
+ rc.bottom = int(rect.y + self._button_size + 1.5*self._button_border_size)
+
+ if button == AUI_BUTTON_CLOSE:
+ btntype = 19
+
+ elif button == AUI_BUTTON_PIN:
+ btntype = 23
+
+ elif button == AUI_BUTTON_MAXIMIZE_RESTORE:
+ if not pane.IsMaximized():
+ btntype = 17
+ else:
+ btntype = 21
+ else:
+ btntype = 15
+
+ state = 4 # CBS_DISABLED
+
+ if pane.state & optionActive:
+
+ if button_state == AUI_BUTTON_STATE_NORMAL:
+ state = 1 # CBS_NORMAL
+
+ elif button_state == AUI_BUTTON_STATE_HOVER:
+ state = 2 # CBS_HOT
+
+ elif button_state == AUI_BUTTON_STATE_PRESSED:
+ state = 3 # CBS_PUSHED
+
+ else:
+ raise Exception("ERROR: Unknown State.")
+
+ else: # inactive pane
+
+ if button_state == AUI_BUTTON_STATE_NORMAL:
+ state = 5 # CBS_NORMAL
+
+ elif button_state == AUI_BUTTON_STATE_HOVER:
+ state = 6 # CBS_HOT
+
+ elif button_state == AUI_BUTTON_STATE_PRESSED:
+ state = 7 # CBS_PUSHED
+
+ else:
+ raise Exception("ERROR: Unknown State.")
+
+ try:
+ winxptheme.DrawThemeBackground(hTheme, dc.GetHDC(), btntype, state, (rc.top, rc.left, rc.right, rc.bottom), None)
+ except TypeError:
+ return
+
+ else:
+
+ # Fallback to default closebutton if themes are not enabled
+ rect2 = wx.Rect(rect.x-4, rect.y+2, rect.width, rect.height)
+ AuiDefaultDockArt.DrawPaneButton(self, dc, window, button, button_state, rect2, pane)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/framemanager.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/framemanager.py
new file mode 100644
index 0000000..a173cb0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/framemanager.py
@@ -0,0 +1,10697 @@
+# --------------------------------------------------------------------------- #
+# AUI Library wxPython IMPLEMENTATION
+#
+# Original C++ Code From Kirix (wxAUI). You Can Find It At:
+#
+# License: wxWidgets license
+#
+# http:#www.kirix.com/en/community/opensource/wxaui/about_wxaui.html
+#
+# Current wxAUI Version Tracked: wxWidgets 2.9.4 SVN HEAD
+#
+#
+# Python Code By:
+#
+# Andrea Gavana, @ 23 Dec 2005
+# Latest Revision: 09 Jan 2014, 23.00 GMT
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+Description
+===========
+
+`framemanager.py` is the central module of the AUI class framework.
+
+:class:`AuiManager` manages the panes associated with it for a particular :class:`Frame`, using
+a pane's :class:`AuiPaneInfo` information to determine each pane's docking and floating
+behavior. AuiManager uses wxPython' sizer mechanism to plan the layout of each frame.
+It uses a replaceable dock art class to do all drawing, so all drawing is localized
+in one area, and may be customized depending on an application's specific needs.
+
+AuiManager works as follows: the programmer adds panes to the class, or makes
+changes to existing pane properties (dock position, floating state, show state, etc...).
+To apply these changes, AuiManager's :meth:`AuiManager.Update() <AuiManager.Update>` function is called. This batch
+processing can be used to avoid flicker, by modifying more than one pane at a time,
+and then "committing" all of the changes at once by calling `Update()`.
+
+Panes can be added quite easily::
+
+ text1 = wx.TextCtrl(self, -1)
+ text2 = wx.TextCtrl(self, -1)
+ self._mgr.AddPane(text1, AuiPaneInfo().Left().Caption("Pane Number One"))
+ self._mgr.AddPane(text2, AuiPaneInfo().Bottom().Caption("Pane Number Two"))
+
+ self._mgr.Update()
+
+
+Later on, the positions can be modified easily. The following will float an
+existing pane in a tool window::
+
+ self._mgr.GetPane(text1).Float()
+
+
+Layers, Rows and Directions, Positions
+======================================
+
+Inside AUI, the docking layout is figured out by checking several pane parameters.
+Four of these are important for determining where a pane will end up.
+
+**Direction** - Each docked pane has a direction, `Top`, `Bottom`, `Left`, `Right`, or `Center`.
+This is fairly self-explanatory. The pane will be placed in the location specified
+by this variable.
+
+**Position** - More than one pane can be placed inside of a "dock". Imagine two panes
+being docked on the left side of a window. One pane can be placed over another.
+In proportionally managed docks, the pane position indicates it's sequential position,
+starting with zero. So, in our scenario with two panes docked on the left side, the
+top pane in the dock would have position 0, and the second one would occupy position 1.
+
+**Row** - A row can allow for two docks to be placed next to each other. One of the most
+common places for this to happen is in the toolbar. Multiple toolbar rows are allowed,
+the first row being in row 0, and the second in row 1. Rows can also be used on
+vertically docked panes.
+
+**Layer** - A layer is akin to an onion. Layer 0 is the very center of the managed pane.
+Thus, if a pane is in layer 0, it will be closest to the center window (also sometimes
+known as the "content window"). Increasing layers "swallow up" all layers of a lower
+value. This can look very similar to multiple rows, but is different because all panes
+in a lower level yield to panes in higher levels. The best way to understand layers
+is by running the AUI sample (`AUI.py`).
+"""
+
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "31 March 2009"
+
+
+import wx
+# just for isinstance
+import wx.lib.sized_controls as sc
+import time
+import types
+import warnings
+
+import auibar
+import auibook
+import tabmdi
+import dockart
+import tabart
+
+from aui_utilities import Clip, PaneCreateStippleBitmap, GetDockingImage, GetSlidingPoints
+
+from aui_constants import *
+
+# Define this as a translation function
+_ = wx.GetTranslation
+
+_winxptheme = False
+if wx.Platform == "__WXMSW__":
+ try:
+ import winxptheme
+ _winxptheme = True
+ except ImportError:
+ pass
+
+# wxPython version string
+_VERSION_STRING = wx.VERSION_STRING
+
+# AUI Events
+wxEVT_AUI_PANE_BUTTON = wx.NewEventType()
+wxEVT_AUI_PANE_CLOSE = wx.NewEventType()
+wxEVT_AUI_PANE_MAXIMIZE = wx.NewEventType()
+wxEVT_AUI_PANE_RESTORE = wx.NewEventType()
+wxEVT_AUI_RENDER = wx.NewEventType()
+wxEVT_AUI_FIND_MANAGER = wx.NewEventType()
+wxEVT_AUI_PANE_MINIMIZE = wx.NewEventType()
+wxEVT_AUI_PANE_MIN_RESTORE = wx.NewEventType()
+wxEVT_AUI_PANE_FLOATING = wx.NewEventType()
+wxEVT_AUI_PANE_FLOATED = wx.NewEventType()
+wxEVT_AUI_PANE_DOCKING = wx.NewEventType()
+wxEVT_AUI_PANE_DOCKED = wx.NewEventType()
+wxEVT_AUI_PANE_ACTIVATED = wx.NewEventType()
+wxEVT_AUI_PERSPECTIVE_CHANGED = wx.NewEventType()
+
+EVT_AUI_PANE_BUTTON = wx.PyEventBinder(wxEVT_AUI_PANE_BUTTON, 0)
+""" Fires an event when the user left-clicks on a pane button. """
+EVT_AUI_PANE_CLOSE = wx.PyEventBinder(wxEVT_AUI_PANE_CLOSE, 0)
+""" A pane in `AuiManager` has been closed. """
+EVT_AUI_PANE_MAXIMIZE = wx.PyEventBinder(wxEVT_AUI_PANE_MAXIMIZE, 0)
+""" A pane in `AuiManager` has been maximized. """
+EVT_AUI_PANE_RESTORE = wx.PyEventBinder(wxEVT_AUI_PANE_RESTORE, 0)
+""" A pane in `AuiManager` has been restored from a maximized state. """
+EVT_AUI_RENDER = wx.PyEventBinder(wxEVT_AUI_RENDER, 0)
+""" Fires an event every time the AUI frame is being repainted. """
+EVT_AUI_FIND_MANAGER = wx.PyEventBinder(wxEVT_AUI_FIND_MANAGER, 0)
+""" Used to find which AUI manager is controlling a certain pane. """
+EVT_AUI_PANE_MINIMIZE = wx.PyEventBinder(wxEVT_AUI_PANE_MINIMIZE, 0)
+""" A pane in `AuiManager` has been minimized. """
+EVT_AUI_PANE_MIN_RESTORE = wx.PyEventBinder(wxEVT_AUI_PANE_MIN_RESTORE, 0)
+""" A pane in `AuiManager` has been restored from a minimized state. """
+EVT_AUI_PANE_FLOATING = wx.PyEventBinder(wxEVT_AUI_PANE_FLOATING, 0)
+""" A pane in `AuiManager` is about to be floated. """
+EVT_AUI_PANE_FLOATED = wx.PyEventBinder(wxEVT_AUI_PANE_FLOATED, 0)
+""" A pane in `AuiManager` has been floated. """
+EVT_AUI_PANE_DOCKING = wx.PyEventBinder(wxEVT_AUI_PANE_DOCKING, 0)
+""" A pane in `AuiManager` is about to be docked. """
+EVT_AUI_PANE_DOCKED = wx.PyEventBinder(wxEVT_AUI_PANE_DOCKED, 0)
+""" A pane in `AuiManager` has been docked. """
+EVT_AUI_PANE_ACTIVATED = wx.PyEventBinder(wxEVT_AUI_PANE_ACTIVATED, 0)
+""" A pane in `AuiManager` has been activated. """
+EVT_AUI_PERSPECTIVE_CHANGED = wx.PyEventBinder(wxEVT_AUI_PERSPECTIVE_CHANGED, 0)
+""" The layout in `AuiManager` has been changed. """
+
+# ---------------------------------------------------------------------------- #
+
+class AuiDockInfo(object):
+ """ A class to store all properties of a dock. """
+
+ def __init__(self):
+ """
+ Default class constructor.
+ Used internally, do not call it in your code!
+ """
+
+ object.__init__(self)
+
+ self.dock_direction = 0
+ self.dock_layer = 0
+ self.dock_row = 0
+ self.size = 0
+ self.min_size = 0
+ self.resizable = True
+ self.fixed = False
+ self.toolbar = False
+ self.rect = wx.Rect()
+ self.panes = []
+
+
+ def IsOk(self):
+ """
+ Returns whether a dock is valid or not.
+
+ In order to be valid, a dock needs to have a non-zero `dock_direction`.
+ """
+
+ return self.dock_direction != 0
+
+
+ def IsHorizontal(self):
+ """ Returns whether the dock is horizontal or not. """
+
+ return self.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]
+
+
+ def IsVertical(self):
+ """ Returns whether the dock is vertical or not. """
+
+ return self.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER]
+
+
+# ---------------------------------------------------------------------------- #
+
+class AuiDockingGuideInfo(object):
+ """ A class which holds information about VS2005 docking guide windows. """
+
+ def __init__(self, other=None):
+ """
+ Default class constructor.
+ Used internally, do not call it in your code!
+
+ :param `other`: another instance of :class:`AuiDockingGuideInfo`.
+ """
+
+ if other:
+ self.Assign(other)
+ else:
+ # window representing the docking target
+ self.host = None
+ # dock direction (top, bottom, left, right, center)
+ self.dock_direction = AUI_DOCK_NONE
+
+
+ def Assign(self, other):
+ """
+ Assigns the properties of the `other` :class:`AuiDockingGuideInfo` to `self`.
+
+ :param `other`: another instance of :class:`AuiDockingGuideInfo`.
+ """
+
+ self.host = other.host
+ self.dock_direction = other.dock_direction
+
+
+ def Host(self, h):
+ """
+ Hosts a docking guide window.
+
+ :param `h`: an instance of :class:`AuiDockingGuideWindow` or :class:`AuiDockingHintWindow`.
+ """
+
+ self.host = h
+ return self
+
+
+ def Left(self):
+ """ Sets the guide window to left docking. """
+
+ self.dock_direction = AUI_DOCK_LEFT
+ return self
+
+
+ def Right(self):
+ """ Sets the guide window to right docking. """
+
+ self.dock_direction = AUI_DOCK_RIGHT
+ return self
+
+
+ def Top(self):
+ """ Sets the guide window to top docking. """
+
+ self.dock_direction = AUI_DOCK_TOP
+ return self
+
+
+ def Bottom(self):
+ """ Sets the guide window to bottom docking. """
+
+ self.dock_direction = AUI_DOCK_BOTTOM
+ return self
+
+
+ def Center(self):
+ """ Sets the guide window to center docking. """
+
+ self.dock_direction = AUI_DOCK_CENTER
+ return self
+
+
+ def Centre(self):
+ """ Sets the guide window to centre docking. """
+
+ self.dock_direction = AUI_DOCK_CENTRE
+ return self
+
+
+# ---------------------------------------------------------------------------- #
+
+class AuiDockUIPart(object):
+ """ A class which holds attributes for a UI part in the interface. """
+
+ typeCaption = 0
+ typeGripper = 1
+ typeDock = 2
+ typeDockSizer = 3
+ typePane = 4
+ typePaneSizer = 5
+ typeBackground = 6
+ typePaneBorder = 7
+ typePaneButton = 8
+
+ def __init__(self):
+ """
+ Default class constructor.
+ Used internally, do not call it in your code!
+ """
+
+ self.orientation = wx.VERTICAL
+ self.type = 0
+ self.rect = wx.Rect()
+
+
+# ---------------------------------------------------------------------------- #
+
+class AuiPaneButton(object):
+ """ A simple class which describes the caption pane button attributes. """
+
+ def __init__(self, button_id):
+ """
+ Default class constructor.
+ Used internally, do not call it in your code!
+
+ :param integer `button_id`: the pane button identifier.
+ """
+
+ self.button_id = button_id
+
+
+# ---------------------------------------------------------------------------- #
+
+# event declarations/classes
+
+class AuiManagerEvent(wx.PyCommandEvent):
+ """ A specialized command event class for events sent by :class:`AuiManager`. """
+
+ def __init__(self, eventType, id=1):
+ """
+ Default class constructor.
+
+ :param integer `eventType`: the event kind;
+ :param integer `id`: the event identification number.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, id)
+
+ self.manager = None
+ self.pane = None
+ self.button = 0
+ self.veto_flag = False
+ self.canveto_flag = True
+ self.dc = None
+
+
+ def SetManager(self, mgr):
+ """
+ Associates a :class:`AuiManager` to the current event.
+
+ :param `mgr`: an instance of :class:`AuiManager`.
+ """
+
+ self.manager = mgr
+
+
+ def SetDC(self, pdc):
+ """
+ Associates a :class:`DC` device context to this event.
+
+ :param `pdc`: a :class:`DC` device context object.
+ """
+
+ self.dc = pdc
+
+
+ def SetPane(self, p):
+ """
+ Associates a :class:`AuiPaneInfo` instance to this event.
+
+ :param `p`: a :class:`AuiPaneInfo` instance.
+ """
+
+ self.pane = p
+
+
+ def SetButton(self, b):
+ """
+ Associates a :class:`AuiPaneButton` instance to this event.
+
+ :param `b`: a :class:`AuiPaneButton` instance.
+ """
+
+ self.button = b
+
+
+ def GetManager(self):
+ """ Returns the associated :class:`AuiManager` (if any). """
+
+ return self.manager
+
+
+ def GetDC(self):
+ """ Returns the associated :class:`DC` device context (if any). """
+
+ return self.dc
+
+
+ def GetPane(self):
+ """ Returns the associated :class:`AuiPaneInfo` structure (if any). """
+
+ return self.pane
+
+
+ def GetButton(self):
+ """ Returns the associated :class:`AuiPaneButton` instance (if any). """
+
+ return self.button
+
+
+ def Veto(self, veto=True):
+ """
+ Prevents the change announced by this event from happening.
+
+ It is in general a good idea to notify the user about the reasons for
+ vetoing the change because otherwise the applications behaviour (which
+ just refuses to do what the user wants) might be quite surprising.
+
+ :param bool `veto`: ``True`` to veto the event, ``False`` otherwise.
+ """
+
+ self.veto_flag = veto
+
+
+ def GetVeto(self):
+ """ Returns whether the event has been vetoed or not. """
+
+ return self.veto_flag
+
+
+ def SetCanVeto(self, can_veto):
+ """
+ Sets whether the event can be vetoed or not.
+
+ :param bool `can_veto`: ``True`` if the event can be vetoed, ``False`` otherwise.
+ """
+
+ self.canveto_flag = can_veto
+
+
+ def CanVeto(self):
+ """ Returns whether the event can be vetoed and has been vetoed. """
+
+ return self.canveto_flag and self.veto_flag
+
+
+# ---------------------------------------------------------------------------- #
+
+class AuiPaneInfo(object):
+ """
+ AuiPaneInfo specifies all the parameters for a pane. These parameters specify where
+ the pane is on the screen, whether it is docked or floating, or hidden. In addition,
+ these parameters specify the pane's docked position, floating position, preferred
+ size, minimum size, caption text among many other parameters.
+ """
+
+ optionFloating = 2**0
+ optionHidden = 2**1
+ optionLeftDockable = 2**2
+ optionRightDockable = 2**3
+ optionTopDockable = 2**4
+ optionBottomDockable = 2**5
+ optionFloatable = 2**6
+ optionMovable = 2**7
+ optionResizable = 2**8
+ optionPaneBorder = 2**9
+ optionCaption = 2**10
+ optionGripper = 2**11
+ optionDestroyOnClose = 2**12
+ optionToolbar = 2**13
+ optionActive = 2**14
+ optionGripperTop = 2**15
+ optionMaximized = 2**16
+ optionDockFixed = 2**17
+ optionNotebookDockable = 2**18
+ optionMinimized = 2**19
+ optionLeftSnapped = 2**20
+ optionRightSnapped = 2**21
+ optionTopSnapped = 2**22
+ optionBottomSnapped = 2**23
+ optionFlyOut = 2**24
+ optionCaptionLeft = 2**25
+
+ buttonClose = 2**26
+ buttonMaximize = 2**27
+ buttonMinimize = 2**28
+ buttonPin = 2**29
+
+ buttonCustom1 = 2**30
+ buttonCustom2 = 2**31
+ buttonCustom3 = 2**32
+
+ savedHiddenState = 2**33 # used internally
+ actionPane = 2**34 # used internally
+ wasMaximized = 2**35 # used internally
+ needsRestore = 2**36 # used internally
+
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ self.window = None
+ self.frame = None
+ self.state = 0
+ self.dock_direction = AUI_DOCK_LEFT
+ self.dock_layer = 0
+ self.dock_row = 0
+ self.dock_pos = 0
+ self.minimize_mode = AUI_MINIMIZE_POS_SMART
+ self.floating_pos = wx.Point(-1, -1)
+ self.floating_size = wx.Size(-1, -1)
+ self.best_size = wx.Size(-1, -1)
+ self.min_size = wx.Size(-1, -1)
+ self.max_size = wx.Size(-1, -1)
+ self.dock_proportion = 0
+ self.caption = ""
+ self.buttons = []
+ self.name = ""
+ self.icon = wx.NullIcon
+ self.rect = wx.Rect()
+ self.notebook_id = -1
+ self.transparent = 255
+ self.needsTransparency = False
+ self.previousDockPos = None
+ self.previousDockSize = 0
+ self.snapped = 0
+ self.minimize_target = None
+
+ self.DefaultPane()
+
+
+ def dock_direction_get(self):
+ """
+ Getter for the `dock_direction`.
+
+ :see: :meth:`~AuiPaneInfo.dock_direction_set` for a set of valid docking directions.
+ """
+
+ if self.IsMaximized():
+ return AUI_DOCK_CENTER
+ else:
+ return self._dock_direction
+
+
+ def dock_direction_set(self, value):
+ """
+ Setter for the `dock_direction`.
+
+ :param integer `value`: the docking direction. This can be one of the following bits:
+
+ ============================ ======= =============================================
+ Dock Flag Value Description
+ ============================ ======= =============================================
+ ``AUI_DOCK_NONE`` 0 No docking direction.
+ ``AUI_DOCK_TOP`` 1 Top docking direction.
+ ``AUI_DOCK_RIGHT`` 2 Right docking direction.
+ ``AUI_DOCK_BOTTOM`` 3 Bottom docking direction.
+ ``AUI_DOCK_LEFT`` 4 Left docking direction.
+ ``AUI_DOCK_CENTER`` 5 Center docking direction.
+ ``AUI_DOCK_CENTRE`` 5 Centre docking direction.
+ ``AUI_DOCK_NOTEBOOK_PAGE`` 6 Automatic AuiNotebooks docking style.
+ ============================ ======= =============================================
+
+ """
+
+ self._dock_direction = value
+
+ dock_direction = property(dock_direction_get, dock_direction_set)
+
+ def IsOk(self):
+ """
+ Returns ``True`` if the :class:`AuiPaneInfo` structure is valid.
+
+ :note: A pane structure is valid if it has an associated window.
+ """
+
+ return self.window != None
+
+
+ def IsMaximized(self):
+ """ Returns ``True`` if the pane is maximized. """
+
+ return self.HasFlag(self.optionMaximized)
+
+
+ def IsMinimized(self):
+ """ Returns ``True`` if the pane is minimized. """
+
+ return self.HasFlag(self.optionMinimized)
+
+
+ def IsFixed(self):
+ """ Returns ``True`` if the pane cannot be resized. """
+
+ return not self.HasFlag(self.optionResizable)
+
+
+ def IsResizeable(self):
+ """ Returns ``True`` if the pane can be resized. """
+
+ return self.HasFlag(self.optionResizable)
+
+
+ def IsShown(self):
+ """ Returns ``True`` if the pane is currently shown. """
+
+ return not self.HasFlag(self.optionHidden)
+
+
+ def IsFloating(self):
+ """ Returns ``True`` if the pane is floating. """
+
+ return self.HasFlag(self.optionFloating)
+
+
+ def IsDocked(self):
+ """ Returns ``True`` if the pane is docked. """
+
+ return not self.HasFlag(self.optionFloating)
+
+
+ def IsToolbar(self):
+ """ Returns ``True`` if the pane contains a toolbar. """
+
+ return self.HasFlag(self.optionToolbar)
+
+
+ def IsTopDockable(self):
+ """
+ Returns ``True`` if the pane can be docked at the top
+ of the managed frame.
+ """
+
+ return self.HasFlag(self.optionTopDockable)
+
+
+ def IsBottomDockable(self):
+ """
+ Returns ``True`` if the pane can be docked at the bottom
+ of the managed frame.
+ """
+
+ return self.HasFlag(self.optionBottomDockable)
+
+
+ def IsLeftDockable(self):
+ """
+ Returns ``True`` if the pane can be docked at the left
+ of the managed frame.
+ """
+
+ return self.HasFlag(self.optionLeftDockable)
+
+
+ def IsRightDockable(self):
+ """
+ Returns ``True`` if the pane can be docked at the right
+ of the managed frame.
+ """
+
+ return self.HasFlag(self.optionRightDockable)
+
+
+ def IsDockable(self):
+ """ Returns ``True`` if the pane can be docked. """
+
+ return self.IsTopDockable() or self.IsBottomDockable() or self.IsLeftDockable() or \
+ self.IsRightDockable() or self.IsNotebookDockable()
+
+
+ def IsFloatable(self):
+ """
+ Returns ``True`` if the pane can be undocked and displayed as a
+ floating window.
+ """
+
+ return self.HasFlag(self.optionFloatable)
+
+
+ def IsMovable(self):
+ """
+ Returns ``True`` if the docked frame can be undocked or moved to
+ another dock position.
+ """
+
+ return self.HasFlag(self.optionMovable)
+
+
+ def IsDestroyOnClose(self):
+ """
+ Returns ``True`` if the pane should be destroyed when it is closed.
+
+ Normally a pane is simply hidden when the close button is clicked. Calling :meth:`~AuiPaneInfo.DestroyOnClose`
+ with a ``True`` input parameter will cause the window to be destroyed when the user clicks
+ the pane's close button.
+ """
+
+ return self.HasFlag(self.optionDestroyOnClose)
+
+
+ def IsNotebookDockable(self):
+ """
+ Returns ``True`` if a pane can be docked on top to another to create a
+ :class:`~lib.agw.aui.auibook.AuiNotebook`.
+ """
+
+ return self.HasFlag(self.optionNotebookDockable)
+
+
+ def IsTopSnappable(self):
+ """ Returns ``True`` if the pane can be snapped at the top of the managed frame. """
+
+ return self.HasFlag(self.optionTopSnapped)
+
+
+ def IsBottomSnappable(self):
+ """ Returns ``True`` if the pane can be snapped at the bottom of the managed frame. """
+
+ return self.HasFlag(self.optionBottomSnapped)
+
+
+ def IsLeftSnappable(self):
+ """ Returns ``True`` if the pane can be snapped on the left of the managed frame. """
+
+ return self.HasFlag(self.optionLeftSnapped)
+
+
+ def IsRightSnappable(self):
+ """ Returns ``True`` if the pane can be snapped on the right of the managed frame. """
+
+ return self.HasFlag(self.optionRightSnapped)
+
+
+ def IsSnappable(self):
+ """ Returns ``True`` if the pane can be snapped. """
+
+ return self.IsTopSnappable() or self.IsBottomSnappable() or self.IsLeftSnappable() or \
+ self.IsRightSnappable()
+
+
+ def IsFlyOut(self):
+ """ Returns ``True`` if the floating pane has a "fly-out" effect. """
+
+ return self.HasFlag(self.optionFlyOut)
+
+
+ def HasCaption(self):
+ """ Returns ``True`` if the pane displays a caption. """
+
+ return self.HasFlag(self.optionCaption)
+
+
+ def HasCaptionLeft(self):
+ """ Returns ``True`` if the pane displays a caption on the left (rotated by 90 degrees). """
+
+ return self.HasFlag(self.optionCaptionLeft)
+
+
+ def HasGripper(self):
+ """ Returns ``True`` if the pane displays a gripper. """
+
+ return self.HasFlag(self.optionGripper)
+
+
+ def HasBorder(self):
+ """ Returns ``True`` if the pane displays a border. """
+
+ return self.HasFlag(self.optionPaneBorder)
+
+
+ def HasCloseButton(self):
+ """ Returns ``True`` if the pane displays a button to close the pane. """
+
+ return self.HasFlag(self.buttonClose)
+
+
+ def HasMaximizeButton(self):
+ """ Returns ``True`` if the pane displays a button to maximize the pane. """
+
+ return self.HasFlag(self.buttonMaximize)
+
+
+ def HasMinimizeButton(self):
+ """ Returns ``True`` if the pane displays a button to minimize the pane. """
+
+ return self.HasFlag(self.buttonMinimize)
+
+
+ def GetMinimizeMode(self):
+ """
+ Returns the minimization style for this pane.
+
+ Possible return values are:
+
+ ============================== ========= ==============================
+ Minimize Mode Flag Hex Value Description
+ ============================== ========= ==============================
+ ``AUI_MINIMIZE_POS_SMART`` 0x01 Minimizes the pane on the closest tool bar
+ ``AUI_MINIMIZE_POS_TOP`` 0x02 Minimizes the pane on the top tool bar
+ ``AUI_MINIMIZE_POS_LEFT`` 0x03 Minimizes the pane on its left tool bar
+ ``AUI_MINIMIZE_POS_RIGHT`` 0x04 Minimizes the pane on its right tool bar
+ ``AUI_MINIMIZE_POS_BOTTOM`` 0x05 Minimizes the pane on its bottom tool bar
+ ``AUI_MINIMIZE_POS_TOOLBAR`` 0x06 Minimizes the pane on a target :class:`~lib.agw.aui.auibar.AuiToolBar`
+ ``AUI_MINIMIZE_POS_MASK`` 0x17 Mask to filter the position flags
+ ``AUI_MINIMIZE_CAPT_HIDE`` 0x0 Hides the caption of the minimized pane
+ ``AUI_MINIMIZE_CAPT_SMART`` 0x08 Displays the caption in the best rotation (horizontal or clockwise)
+ ``AUI_MINIMIZE_CAPT_HORZ`` 0x10 Displays the caption horizontally
+ ``AUI_MINIMIZE_CAPT_MASK`` 0x18 Mask to filter the caption flags
+ ============================== ========= ==============================
+
+ The flags can be filtered with the following masks:
+
+ ============================== ========= ==============================
+ Minimize Mask Flag Hex Value Description
+ ============================== ========= ==============================
+ ``AUI_MINIMIZE_POS_MASK`` 0x17 Filters the position flags
+ ``AUI_MINIMIZE_CAPT_MASK`` 0x18 Filters the caption flags
+ ============================== ========= ==============================
+
+ """
+
+ return self.minimize_mode
+
+
+ def HasPinButton(self):
+ """ Returns ``True`` if the pane displays a button to float the pane. """
+
+ return self.HasFlag(self.buttonPin)
+
+
+ def HasGripperTop(self):
+ """ Returns ``True`` if the pane displays a gripper at the top. """
+
+ return self.HasFlag(self.optionGripperTop)
+
+
+ def Window(self, w):
+ """
+ Associate a :class:`Window` derived window to this pane.
+
+ This normally does not need to be specified, as the window pointer is
+ automatically assigned to the :class:`AuiPaneInfo` structure as soon as it is
+ added to the manager.
+
+ :param `w`: a :class:`Window` derived window.
+ """
+
+ self.window = w
+ return self
+
+
+ def Name(self, name):
+ """
+ Sets the name of the pane so it can be referenced in lookup functions.
+
+ If a name is not specified by the user, a random name is assigned to the pane
+ when it is added to the manager.
+
+ :param `name`: a string specifying the pane name.
+
+ .. warning::
+
+ If you are using :meth:`AuiManager.SavePerspective` and :meth:`AuiManager.LoadPerspective`,
+ you will have to specify a name for your pane using :meth:`~AuiPaneInfo.Name`, as perspectives
+ containing randomly generated names can not be properly restored.
+ """
+
+ self.name = name
+ return self
+
+
+ def Caption(self, caption):
+ """
+ Sets the caption of the pane.
+
+ :param string `caption`: a string specifying the pane caption.
+ """
+
+ self.caption = caption
+ return self
+
+
+ def Left(self):
+ """
+ Sets the pane dock position to the left side of the frame.
+
+ :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_LEFT`` as
+ parameter.
+ """
+
+ self.dock_direction = AUI_DOCK_LEFT
+ return self
+
+
+ def Right(self):
+ """
+ Sets the pane dock position to the right side of the frame.
+
+ :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_RIGHT`` as
+ parameter.
+ """
+
+ self.dock_direction = AUI_DOCK_RIGHT
+ return self
+
+
+ def Top(self):
+ """
+ Sets the pane dock position to the top of the frame.
+
+ :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_TOP`` as
+ parameter.
+ """
+
+ self.dock_direction = AUI_DOCK_TOP
+ return self
+
+
+ def Bottom(self):
+ """
+ Sets the pane dock position to the bottom of the frame.
+
+ :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_BOTTOM`` as
+ parameter.
+ """
+
+ self.dock_direction = AUI_DOCK_BOTTOM
+ return self
+
+
+ def Center(self):
+ """
+ Sets the pane to the center position of the frame.
+
+ The centre pane is the space in the middle after all border panes (left, top,
+ right, bottom) are subtracted from the layout.
+
+ :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_CENTER`` as
+ parameter.
+ """
+
+ self.dock_direction = AUI_DOCK_CENTER
+ return self
+
+
+ def Centre(self):
+ """
+ Sets the pane to the center position of the frame.
+
+ The centre pane is the space in the middle after all border panes (left, top,
+ right, bottom) are subtracted from the layout.
+
+ :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_CENTRE`` as
+ parameter.
+ """
+
+ self.dock_direction = AUI_DOCK_CENTRE
+ return self
+
+
+ def Direction(self, direction):
+ """
+ Determines the direction of the docked pane. It is functionally the
+ same as calling :meth:`Left`, :meth:`Right`, :meth:`Top` or :meth:`Bottom`,
+ except that docking direction may be specified programmatically via the parameter `direction`.
+
+ :param integer `direction`: the direction of the docked pane.
+
+ :see: :meth:`dock_direction_set` for a list of valid docking directions.
+ """
+
+ self.dock_direction = direction
+ return self
+
+
+ def Layer(self, layer):
+ """
+ Determines the layer of the docked pane.
+
+ The dock layer is similar to an onion, the inner-most layer being layer 0. Each
+ shell moving in the outward direction has a higher layer number. This allows for
+ more complex docking layout formation.
+
+ :param integer `layer`: the layer of the docked pane.
+ """
+
+ self.dock_layer = layer
+ return self
+
+
+ def Row(self, row):
+ """
+ Determines the row of the docked pane.
+
+ :param integer `row`: the row of the docked pane.
+ """
+
+ self.dock_row = row
+ return self
+
+
+ def Position(self, pos):
+ """
+ Determines the position of the docked pane.
+
+ :param integer `pos`: the position of the docked pane.
+ """
+
+ self.dock_pos = pos
+ return self
+
+
+ def MinSize(self, arg1=None, arg2=None):
+ """
+ Sets the minimum size of the pane.
+
+ This method is split in 2 versions depending on the input type. If `arg1` is
+ a :class:`Size` object, then :meth:`~AuiPaneInfo.MinSize1` is called. Otherwise, :meth:`~AuiPaneInfo.MinSize2` is called.
+
+ :param `arg1`: a :class:`Size` object, a (x, y) tuple or or a `x` coordinate.
+ :param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused).
+ """
+
+ if isinstance(arg1, wx.Size):
+ ret = self.MinSize1(arg1)
+ elif isinstance(arg1, types.TupleType):
+ ret = self.MinSize1(wx.Size(*arg1))
+ elif isinstance(arg1, types.IntType) and arg2 is not None:
+ ret = self.MinSize2(arg1, arg2)
+ else:
+ raise Exception("Invalid argument passed to `MinSize`: arg1=%s, arg2=%s"%(repr(arg1), repr(arg2)))
+
+ return ret
+
+
+ def MinSize1(self, size):
+ """
+ Sets the minimum size of the pane.
+
+ :see: :meth:`MinSize` for an explanation of input parameters.
+ """
+ self.min_size = size
+ return self
+
+
+ def MinSize2(self, x, y):
+ """
+ Sets the minimum size of the pane.
+
+ :see: :meth:`MinSize` for an explanation of input parameters.
+ """
+
+ self.min_size = wx.Size(x, y)
+ return self
+
+
+ def MaxSize(self, arg1=None, arg2=None):
+ """
+ Sets the maximum size of the pane.
+
+ This method is split in 2 versions depending on the input type. If `arg1` is
+ a :class:`Size` object, then :meth:`~AuiPaneInfo.MaxSize1` is called. Otherwise, :meth:`~AuiPaneInfo.MaxSize2` is called.
+
+ :param `arg1`: a :class:`Size` object, a (x, y) tuple or a `x` coordinate.
+ :param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused).
+ """
+
+ if isinstance(arg1, wx.Size):
+ ret = self.MaxSize1(arg1)
+ elif isinstance(arg1, types.TupleType):
+ ret = self.MaxSize1(wx.Size(*arg1))
+ elif isinstance(arg1, types.IntType) and arg2 is not None:
+ ret = self.MaxSize2(arg1, arg2)
+ else:
+ raise Exception("Invalid argument passed to `MaxSize`: arg1=%s, arg2=%s"%(repr(arg1), repr(arg2)))
+
+ return ret
+
+
+ def MaxSize1(self, size):
+ """
+ Sets the maximum size of the pane.
+
+ :see: :meth:`MaxSize` for an explanation of input parameters.
+ """
+
+ self.max_size = size
+ return self
+
+
+ def MaxSize2(self, x, y):
+ """
+ Sets the maximum size of the pane.
+
+ :see: :meth:`MaxSize` for an explanation of input parameters.
+ """
+
+ self.max_size.Set(x,y)
+ return self
+
+
+ def BestSize(self, arg1=None, arg2=None):
+ """
+ Sets the ideal size for the pane. The docking manager will attempt to use
+ this size as much as possible when docking or floating the pane.
+
+ This method is split in 2 versions depending on the input type. If `arg1` is
+ a :class:`Size` object, then :meth:`BestSize1` is called. Otherwise, :meth:`BestSize2` is called.
+
+ :param `arg1`: a :class:`Size` object, a (x, y) tuple or a `x` coordinate.
+ :param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused).
+ """
+
+ if isinstance(arg1, wx.Size):
+ ret = self.BestSize1(arg1)
+ elif isinstance(arg1, types.TupleType):
+ ret = self.BestSize1(wx.Size(*arg1))
+ elif isinstance(arg1, types.IntType) and arg2 is not None:
+ ret = self.BestSize2(arg1, arg2)
+ else:
+ raise Exception("Invalid argument passed to `BestSize`: arg1=%s, arg2=%s"%(repr(arg1), repr(arg2)))
+
+ return ret
+
+
+ def BestSize1(self, size):
+ """
+ Sets the best size of the pane.
+
+ :see: :meth:`BestSize` for an explanation of input parameters.
+ """
+
+ self.best_size = size
+ return self
+
+
+ def BestSize2(self, x, y):
+ """
+ Sets the best size of the pane.
+
+ :see: :meth:`BestSize` for an explanation of input parameters.
+ """
+
+ self.best_size.Set(x,y)
+ return self
+
+
+ def FloatingPosition(self, pos):
+ """
+ Sets the position of the floating pane.
+
+ :param `pos`: a :class:`Point` or a tuple indicating the pane floating position.
+ """
+
+ self.floating_pos = wx.Point(*pos)
+ return self
+
+
+ def FloatingSize(self, size):
+ """
+ Sets the size of the floating pane.
+
+ :param `size`: a :class:`Size` or a tuple indicating the pane floating size.
+ """
+
+ self.floating_size = wx.Size(*size)
+ return self
+
+
+ def Maximize(self):
+ """ Makes the pane take up the full area."""
+
+ return self.SetFlag(self.optionMaximized, True)
+
+
+ def Minimize(self):
+ """
+ Makes the pane minimized in a :class:`~lib.agw.aui.auibar.AuiToolBar`.
+
+ Clicking on the minimize button causes a new :class:`~lib.agw.aui.auibar.AuiToolBar` to be created
+ and added to the frame manager, (currently the implementation is such that
+ panes at West will have a toolbar at the right, panes at South will have
+ toolbars at the bottom etc...) and the pane is hidden in the manager.
+
+ Clicking on the restore button on the newly created toolbar will result in the
+ toolbar being removed and the original pane being restored.
+ """
+
+ return self.SetFlag(self.optionMinimized, True)
+
+
+ def MinimizeMode(self, mode):
+ """
+ Sets the expected minimized mode if the minimize button is visible.
+
+ :param integer `mode`: the minimized pane can have a specific position in the work space:
+
+ ============================== ========= ==============================
+ Minimize Mode Flag Hex Value Description
+ ============================== ========= ==============================
+ ``AUI_MINIMIZE_POS_SMART`` 0x01 Minimizes the pane on the closest tool bar
+ ``AUI_MINIMIZE_POS_TOP`` 0x02 Minimizes the pane on the top tool bar
+ ``AUI_MINIMIZE_POS_LEFT`` 0x03 Minimizes the pane on its left tool bar
+ ``AUI_MINIMIZE_POS_RIGHT`` 0x04 Minimizes the pane on its right tool bar
+ ``AUI_MINIMIZE_POS_BOTTOM`` 0x05 Minimizes the pane on its bottom tool bar
+ ``AUI_MINIMIZE_POS_TOOLBAR`` 0x06 Minimizes the pane on a target :class:`~lib.agw.aui.auibar.AuiToolBar`
+ ============================== ========= ==============================
+
+ The caption of the minimized pane can be displayed in different modes:
+
+ ============================== ========= ==============================
+ Caption Mode Flag Hex Value Description
+ ============================== ========= ==============================
+ ``AUI_MINIMIZE_CAPT_HIDE`` 0x0 Hides the caption of the minimized pane
+ ``AUI_MINIMIZE_CAPT_SMART`` 0x08 Displays the caption in the best rotation (horizontal in the top and in
+ the bottom tool bar or clockwise in the right and in the left tool bar)
+ ``AUI_MINIMIZE_CAPT_HORZ`` 0x10 Displays the caption horizontally
+ ============================== ========= ==============================
+
+ .. note::
+
+ In order to use the ``AUI_MINIMIZE_POS_TOOLBAR`` flag, the instance of :class:`AuiManager`
+ you pass as an input for :meth:`MinimizeTarget` **must** have a real name and not the randomly
+ generated one. Remember to set the :meth:`Name` property of the toolbar pane before calling this method.
+
+ """
+
+ self.minimize_mode = mode
+ return self
+
+
+ def MinimizeTarget(self, toolbarPane):
+ """
+ Minimizes the panes using a :class:`AuiPaneInfo` as a target. As :class:`AuiPaneInfo` properties
+ need to be copied back and forth every time the perspective has changed, we
+ only store the toobar **name**.
+
+ :param `toolbarPane`: an instance of :class:`AuiPaneInfo`, containing a :class:`~lib.agw.aui.auibar.AuiToolBar`.
+
+ .. note::
+
+ In order to use this functionality (and with the ``AUI_MINIMIZE_POS_TOOLBAR``
+ flag set), the instance of :class:`AuiPaneInfo` you pass as an input **must** have a real
+ name and not the randomly generated one. Remember to set the :meth:`Name` property of
+ the toolbar pane before calling this method.
+
+ """
+
+ self.minimize_target = toolbarPane.name
+ return self
+
+
+ def Restore(self):
+ """ Is the reverse of :meth:`Maximize` and :meth:`Minimize`."""
+
+ return self.SetFlag(self.optionMaximized or self.optionMinimized, False)
+
+
+ def Fixed(self):
+ """
+ Forces a pane to be fixed size so that it cannot be resized.
+ After calling :meth:`Fixed`, :meth:`IsFixed` will return ``True``.
+ """
+
+ return self.SetFlag(self.optionResizable, False)
+
+
+ def Resizable(self, resizable=True):
+ """
+ Allows a pane to be resizable if `resizable` is ``True``, and forces
+ it to be a fixed size if `resizeable` is ``False``.
+
+ If `resizable` is ``False``, this is simply an antonym for :meth:`Fixed`.
+
+ :param bool `resizable`: whether the pane will be resizeable or not.
+ """
+
+ return self.SetFlag(self.optionResizable, resizable)
+
+
+ def Transparent(self, alpha):
+ """
+ Makes the pane transparent when floating.
+
+ :param integer `alpha`: a value between 0 and 255 for pane transparency.
+ """
+
+ if alpha < 0 or alpha > 255:
+ raise Exception("Invalid transparency value (%s)"%repr(alpha))
+
+ self.transparent = alpha
+ self.needsTransparency = True
+
+
+ def Dock(self):
+ """ Indicates that a pane should be docked. It is the opposite of :meth:`Float`. """
+
+ if self.IsNotebookPage():
+ self.notebook_id = -1
+ self.dock_direction = AUI_DOCK_NONE
+
+ return self.SetFlag(self.optionFloating, False)
+
+
+ def Float(self):
+ """ Indicates that a pane should be floated. It is the opposite of :meth:`Dock`. """
+
+ if self.IsNotebookPage():
+ self.notebook_id = -1
+ self.dock_direction = AUI_DOCK_NONE
+
+ return self.SetFlag(self.optionFloating, True)
+
+
+ def Hide(self):
+ """
+ Indicates that a pane should be hidden.
+
+ Calling :meth:`Show(False) <Show>` achieve the same effect.
+ """
+
+ return self.SetFlag(self.optionHidden, True)
+
+
+ def Show(self, show=True):
+ """
+ Indicates that a pane should be shown.
+
+ :param bool `show`: whether the pane should be shown or not.
+ """
+
+ return self.SetFlag(self.optionHidden, not show)
+
+
+ # By defaulting to 1000, the tab will get placed at the end
+ def NotebookPage(self, id, tab_position=1000):
+ """
+ Forces a pane to be a notebook page, so that the pane can be
+ docked on top to another to create a :class:`~lib.agw.aui.auibook.AuiNotebook`.
+
+ :param integer `id`: the notebook id;
+ :param integer `tab_position`: the tab number of the pane once docked in a notebook.
+ """
+
+ # Remove any floating frame
+ self.Dock()
+ self.notebook_id = id
+ self.dock_pos = tab_position
+ self.dock_row = 0
+ self.dock_layer = 0
+ self.dock_direction = AUI_DOCK_NOTEBOOK_PAGE
+
+ return self
+
+
+ def NotebookControl(self, id):
+ """
+ Forces a pane to be a notebook control (:class:`~lib.agw.aui.auibook.AuiNotebook`).
+
+ :param integer `id`: the notebook id.
+ """
+
+ self.notebook_id = id
+ self.window = None
+ self.buttons = []
+
+ if self.dock_direction == AUI_DOCK_NOTEBOOK_PAGE:
+ self.dock_direction = AUI_DOCK_NONE
+
+ return self
+
+
+ def HasNotebook(self):
+ """ Returns whether a pane has a :class:`~lib.agw.aui.auibook.AuiNotebook` or not. """
+
+ return self.notebook_id >= 0
+
+
+ def IsNotebookPage(self):
+ """ Returns whether the pane is a notebook page in a :class:`~lib.agw.aui.auibook.AuiNotebook`. """
+
+ return self.notebook_id >= 0 and self.dock_direction == AUI_DOCK_NOTEBOOK_PAGE
+
+
+ def IsNotebookControl(self):
+ """ Returns whether the pane is a notebook control (:class:`~lib.agw.aui.auibook.AuiNotebook`). """
+
+ return not self.IsNotebookPage() and self.HasNotebook()
+
+
+ def SetNameFromNotebookId(self):
+ """ Sets the pane name once docked in a :class:`~lib.agw.aui.auibook.AuiNotebook` using the notebook id. """
+
+ if self.notebook_id >= 0:
+ self.name = "__notebook_%d"%self.notebook_id
+
+ return self
+
+
+ def CaptionVisible(self, visible=True, left=False):
+ """
+ Indicates that a pane caption should be visible. If `visible` is ``False``, no pane
+ caption is drawn.
+
+ :param bool `visible`: whether the caption should be visible or not;
+ :param bool `left`: whether the caption should be drawn on the left (rotated by 90 degrees) or not.
+ """
+
+ if left:
+ self.SetFlag(self.optionCaption, False)
+ return self.SetFlag(self.optionCaptionLeft, visible)
+
+ self.SetFlag(self.optionCaptionLeft, False)
+ return self.SetFlag(self.optionCaption, visible)
+
+
+ def PaneBorder(self, visible=True):
+ """
+ Indicates that a border should be drawn for the pane.
+
+ :param bool `visible`: whether the pane border should be visible or not.
+ """
+
+ return self.SetFlag(self.optionPaneBorder, visible)
+
+
+ def Gripper(self, visible=True):
+ """
+ Indicates that a gripper should be drawn for the pane.
+
+ :param bool `visible`: whether the gripper should be visible or not.
+ """
+
+ return self.SetFlag(self.optionGripper, visible)
+
+
+ def GripperTop(self, attop=True):
+ """
+ Indicates that a gripper should be drawn at the top of the pane.
+
+ :param bool `attop`: whether the gripper should be drawn at the top or not.
+ """
+
+ return self.SetFlag(self.optionGripperTop, attop)
+
+
+ def CloseButton(self, visible=True):
+ """
+ Indicates that a close button should be drawn for the pane.
+
+ :param bool `visible`: whether the close button should be visible or not.
+ """
+
+ return self.SetFlag(self.buttonClose, visible)
+
+
+ def MaximizeButton(self, visible=True):
+ """
+ Indicates that a maximize button should be drawn for the pane.
+
+ :param bool `visible`: whether the maximize button should be visible or not.
+ """
+
+ return self.SetFlag(self.buttonMaximize, visible)
+
+
+ def MinimizeButton(self, visible=True):
+ """
+ Indicates that a minimize button should be drawn for the pane.
+
+ :param bool `visible`: whether the minimize button should be visible or not.
+ """
+
+ return self.SetFlag(self.buttonMinimize, visible)
+
+
+ def PinButton(self, visible=True):
+ """
+ Indicates that a pin button should be drawn for the pane.
+
+ :param bool `visible`: whether the pin button should be visible or not.
+ """
+
+ return self.SetFlag(self.buttonPin, visible)
+
+
+ def DestroyOnClose(self, b=True):
+ """
+ Indicates whether a pane should be destroyed when it is closed.
+
+ Normally a pane is simply hidden when the close button is clicked. Setting
+ `b` to ``True`` will cause the window to be destroyed when the user clicks
+ the pane's close button.
+
+ :param bool `b`: whether the pane should be destroyed when it is closed or not.
+ """
+
+ return self.SetFlag(self.optionDestroyOnClose, b)
+
+
+ def TopDockable(self, b=True):
+ """
+ Indicates whether a pane can be docked at the top of the frame.
+
+ :param bool `b`: whether the pane can be docked at the top or not.
+ """
+
+ return self.SetFlag(self.optionTopDockable, b)
+
+
+ def BottomDockable(self, b=True):
+ """
+ Indicates whether a pane can be docked at the bottom of the frame.
+
+ :param bool `b`: whether the pane can be docked at the bottom or not.
+ """
+
+ return self.SetFlag(self.optionBottomDockable, b)
+
+
+ def LeftDockable(self, b=True):
+ """
+ Indicates whether a pane can be docked on the left of the frame.
+
+ :param bool `b`: whether the pane can be docked at the left or not.
+ """
+
+ return self.SetFlag(self.optionLeftDockable, b)
+
+
+ def RightDockable(self, b=True):
+ """
+ Indicates whether a pane can be docked on the right of the frame.
+
+ :param bool `b`: whether the pane can be docked at the right or not.
+ """
+
+ return self.SetFlag(self.optionRightDockable, b)
+
+
+ def Floatable(self, b=True):
+ """
+ Sets whether the user will be able to undock a pane and turn it
+ into a floating window.
+
+ :param bool `b`: whether the pane can be floated or not.
+ """
+
+ return self.SetFlag(self.optionFloatable, b)
+
+
+ def Movable(self, b=True):
+ """
+ Indicates whether a pane can be moved.
+
+ :param bool `b`: whether the pane can be moved or not.
+ """
+
+ return self.SetFlag(self.optionMovable, b)
+
+
+ def NotebookDockable(self, b=True):
+ """
+ Indicates whether a pane can be docked in an automatic :class:`~lib.agw.aui.auibook.AuiNotebook`.
+
+ :param bool `b`: whether the pane can be docked in a notebook or not.
+ """
+
+ return self.SetFlag(self.optionNotebookDockable, b)
+
+
+ def DockFixed(self, b=True):
+ """
+ Causes the containing dock to have no resize sash. This is useful
+ for creating panes that span the entire width or height of a dock, but should
+ not be resizable in the other direction.
+
+ :param bool `b`: whether the pane will have a resize sash or not.
+ """
+
+ return self.SetFlag(self.optionDockFixed, b)
+
+
+ def Dockable(self, b=True):
+ """
+ Specifies whether a frame can be docked or not. It is the same as specifying
+ :meth:`TopDockable` . :meth:`BottomDockable` . :meth:`LeftDockable` . :meth:`RightDockable` .
+
+ :param bool `b`: whether the frame can be docked or not.
+ """
+
+ return self.TopDockable(b).BottomDockable(b).LeftDockable(b).RightDockable(b)
+
+
+ def TopSnappable(self, b=True):
+ """
+ Indicates whether a pane can be snapped at the top of the main frame.
+
+ :param bool `b`: whether the pane can be snapped at the top of the main frame or not.
+ """
+
+ return self.SetFlag(self.optionTopSnapped, b)
+
+
+ def BottomSnappable(self, b=True):
+ """
+ Indicates whether a pane can be snapped at the bottom of the main frame.
+
+ :param bool `b`: whether the pane can be snapped at the bottom of the main frame or not.
+ """
+
+ return self.SetFlag(self.optionBottomSnapped, b)
+
+
+ def LeftSnappable(self, b=True):
+ """
+ Indicates whether a pane can be snapped on the left of the main frame.
+
+ :param bool `b`: whether the pane can be snapped at the left of the main frame or not.
+ """
+
+ return self.SetFlag(self.optionLeftSnapped, b)
+
+
+ def RightSnappable(self, b=True):
+ """
+ Indicates whether a pane can be snapped on the right of the main frame.
+
+ :param bool `b`: whether the pane can be snapped at the right of the main frame or not.
+ """
+
+ return self.SetFlag(self.optionRightSnapped, b)
+
+
+ def Snappable(self, b=True):
+ """
+ Indicates whether a pane can be snapped on the main frame. This is
+ equivalent as calling :meth:`TopSnappable` . :meth:`BottomSnappable` . :meth:`LeftSnappable` . :meth:`RightSnappable` .
+
+ :param bool `b`: whether the pane can be snapped on the main frame or not.
+ """
+
+ return self.TopSnappable(b).BottomSnappable(b).LeftSnappable(b).RightSnappable(b)
+
+
+ def FlyOut(self, b=True):
+ """
+ Indicates whether a pane, when floating, has a "fly-out" effect
+ (i.e., floating panes which only show themselves when moused over).
+
+ :param bool `b`: whether the pane can be snapped on the main frame or not.
+ """
+
+ return self.SetFlag(self.optionFlyOut, b)
+
+
+ # Copy over the members that pertain to docking position
+ def SetDockPos(self, source):
+ """
+ Copies the `source` pane members that pertain to docking position to `self`.
+
+ :param AuiPaneInfo `source`: the source pane from where to copy the attributes.
+ """
+
+ self.dock_direction = source.dock_direction
+ self.dock_layer = source.dock_layer
+ self.dock_row = source.dock_row
+ self.dock_pos = source.dock_pos
+ self.dock_proportion = source.dock_proportion
+ self.floating_pos = wx.Point(*source.floating_pos)
+ self.floating_size = wx.Size(*source.floating_size)
+ self.rect = wx.Rect(*source.rect)
+
+ return self
+
+
+ def DefaultPane(self):
+ """ Specifies that the pane should adopt the default pane settings. """
+
+ state = self.state
+ state |= self.optionTopDockable | self.optionBottomDockable | \
+ self.optionLeftDockable | self.optionRightDockable | \
+ self.optionNotebookDockable | \
+ self.optionFloatable | self.optionMovable | self.optionResizable | \
+ self.optionCaption | self.optionPaneBorder | self.buttonClose
+
+ self.state = state
+ return self
+
+
+ def CentrePane(self):
+ """
+ Specifies that the pane should adopt the default center pane settings.
+
+ Centre panes usually do not have caption bars. This function provides an easy way of
+ preparing a pane to be displayed in the center dock position.
+ """
+
+ return self.CenterPane()
+
+
+ def CenterPane(self):
+ """
+ Specifies that the pane should adopt the default center pane settings.
+
+ Centre panes usually do not have caption bars. This function provides an easy way of
+ preparing a pane to be displayed in the center dock position.
+ """
+
+ self.state = 0
+ return self.Center().PaneBorder().Resizable()
+
+
+ def ToolbarPane(self):
+ """ Specifies that the pane should adopt the default toolbar pane settings. """
+
+ self.DefaultPane()
+ state = self.state
+
+ state |= (self.optionToolbar | self.optionGripper)
+ state &= ~(self.optionResizable | self.optionCaption | self.optionCaptionLeft)
+
+ if self.dock_layer == 0:
+ self.dock_layer = 10
+
+ self.state = state
+
+ return self
+
+
+ def Icon(self, icon):
+ """
+ Specifies whether an icon is drawn on the left of the caption text when
+ the pane is docked. If `icon` is ``None`` or :class:`NullIcon`, no icon is drawn on
+ the caption space.
+
+ :param icon: an icon to draw on the caption space, or ``None``.
+ :type `icon`: :class:`Icon` or ``None``
+ """
+
+ if icon is None:
+ icon = wx.NullIcon
+
+ self.icon = icon
+ return self
+
+
+ def SetFlag(self, flag, option_state):
+ """
+ Turns the property given by `flag` on or off with the `option_state`
+ parameter.
+
+ :param integer `flag`: the property to set;
+ :param bool `option_state`: either ``True`` or ``False``.
+ """
+
+ state = self.state
+
+ if option_state:
+ state |= flag
+ else:
+ state &= ~flag
+
+ self.state = state
+
+ if flag in [self.buttonClose, self.buttonMaximize, self.buttonMinimize, self.buttonPin]:
+ self.ResetButtons()
+
+ return self
+
+
+ def HasFlag(self, flag):
+ """
+ Returns ``True`` if the the property specified by flag is active for the pane.
+
+ :param integer `flag`: the property to check for activity.
+ """
+
+ return (self.state & flag and [True] or [False])[0]
+
+
+ def ResetButtons(self):
+ """
+ Resets all the buttons and recreates them from scratch depending on the
+ :class:`AuiManager` flags.
+ """
+
+ floating = self.HasFlag(self.optionFloating)
+ self.buttons = []
+
+ if not floating and self.HasMinimizeButton():
+ button = AuiPaneButton(AUI_BUTTON_MINIMIZE)
+ self.buttons.append(button)
+
+ if not floating and self.HasMaximizeButton():
+ button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE)
+ self.buttons.append(button)
+
+ if not floating and self.HasPinButton():
+ button = AuiPaneButton(AUI_BUTTON_PIN)
+ self.buttons.append(button)
+
+ if self.HasCloseButton():
+ button = AuiPaneButton(AUI_BUTTON_CLOSE)
+ self.buttons.append(button)
+
+
+ def CountButtons(self):
+ """ Returns the number of visible buttons in the docked pane. """
+
+ n = 0
+
+ if self.HasCaption() or self.HasCaptionLeft():
+ if isinstance(wx.GetTopLevelParent(self.window), AuiFloatingFrame):
+ return 1
+
+ if self.HasCloseButton():
+ n += 1
+ if self.HasMaximizeButton():
+ n += 1
+ if self.HasMinimizeButton():
+ n += 1
+ if self.HasPinButton():
+ n += 1
+
+ return n
+
+
+ def IsHorizontal(self):
+ """ Returns ``True`` if the pane `dock_direction` is horizontal. """
+
+ return self.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]
+
+ def IsVertical(self):
+ """ Returns ``True`` if the pane `dock_direction` is vertical. """
+
+ return self.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT]
+
+
+# Null AuiPaneInfo reference
+NonePaneInfo = AuiPaneInfo()
+""" Null :class:`AuiPaneInfo` reference, an invalid instance of :class:`AuiPaneInfo`. """
+
+
+# ---------------------------------------------------------------------------- #
+
+class AuiDockingGuide(wx.Frame):
+ """ Base class for :class:`AuiSingleDockingGuide` and :class:`AuiCenterDockingGuide`."""
+
+ def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP |
+ wx.FRAME_NO_TASKBAR | wx.NO_BORDER, name="AuiDockingGuide"):
+ """
+ Default class constructor. Used internally, do not call it in your code!
+
+ :param `parent`: the :class:`AuiManager` parent;
+ :param integer `id`: the window identifier. It may take a value of -1 to indicate a default value.
+ :param string `title`: the caption to be displayed on the frame's title bar.
+ :param Point `pos`: the window position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform.
+ :param Size `size`: the window size. A value of (-1, -1) indicates a default size, chosen by
+ either the windowing system or wxPython, depending on platform.
+ :param integer `style`: the window style.
+ :param string `name`: the name of the window. This parameter is used to associate a name with the
+ item, allowing the application user to set Motif resource values for individual windows.
+ """
+
+ wx.Frame.__init__(self, parent, id, title, pos, size, style, name=name)
+
+
+ def HitTest(self, x, y):
+ """
+ To be overridden by parent classes.
+
+ :param integer `x`: the `x` mouse position;
+ :param integer `y`: the `y` mouse position.
+ """
+
+ return 0
+
+
+ def ValidateNotebookDocking(self, valid):
+ """
+ To be overridden by parent classes.
+
+ :param bool `valid`: whether a pane can be docked on top to another to form an automatic
+ :class:`~lib.agw.aui.auibook.AuiNotebook`.
+ """
+
+ return 0
+
+# ============================================================================
+# implementation
+# ============================================================================
+
+# ---------------------------------------------------------------------------
+# AuiDockingGuideWindow
+# ---------------------------------------------------------------------------
+
+class AuiDockingGuideWindow(wx.Window):
+ """ Target class for :class:`AuiDockingGuide` and :class:`AuiCenterDockingGuide`. """
+
+ def __init__(self, parent, rect, direction=0, center=False, useAero=False):
+ """
+ Default class constructor. Used internally, do not call it in your code!
+
+ :param `parent`: the :class:`AuiManager` parent;
+ :param Rect `rect`: the window rect;
+ :param integer `direction`: one of ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, ``wx.RIGHT``,
+ ``wx.CENTER``;
+ :param bool `center`: whether the calling class is a :class:`AuiCenterDockingGuide`;
+ :param bool `useAero`: whether to use the new Aero-style bitmaps or Whidbey-style bitmaps
+ for the docking guide.
+ """
+
+ wx.Window.__init__(self, parent, -1, rect.GetPosition(), rect.GetSize(), wx.NO_BORDER)
+
+ self._direction = direction
+ self._center = center
+ self._valid = True
+ self._useAero = useAero
+
+ self._bmp_unfocus, self._bmp_focus = GetDockingImage(direction, useAero, center)
+
+ self._currentImage = self._bmp_unfocus
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def SetValid(self, valid):
+ """
+ Sets the docking direction as valid or invalid.
+
+ :param bool `valid`: whether the docking direction is allowed or not.
+ """
+
+ self._valid = valid
+
+
+ def IsValid(self):
+ """ Returns whether the docking direction is valid. """
+
+ return self._valid
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiDockingGuideWindow`.
+
+ :param `event`: a :class:`EraseEvent` to be processed.
+
+ :note: This is intentionally empty to reduce flickering while drawing.
+ """
+
+ pass
+
+
+ def DrawBackground(self, dc):
+ """
+ Draws the docking guide background.
+
+ :param `dc`: a :class:`DC` device context object.
+ """
+
+ rect = self.GetClientRect()
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(wx.Brush(colourTargetBackground))
+ dc.DrawRectangleRect(rect)
+
+ dc.SetPen(wx.Pen(colourTargetBorder))
+
+ left = rect.GetLeft()
+ top = rect.GetTop()
+ right = rect.GetRight()
+ bottom = rect.GetBottom()
+
+ if self._direction != wx.CENTER:
+
+ if not self._center or self._direction != wx.BOTTOM:
+ dc.DrawLine(left, top, right+1, top)
+ if not self._center or self._direction != wx.RIGHT:
+ dc.DrawLine(left, top, left, bottom+1)
+ if not self._center or self._direction != wx.LEFT:
+ dc.DrawLine(right, top, right, bottom+1)
+ if not self._center or self._direction != wx.TOP:
+ dc.DrawLine(left, bottom, right+1, bottom)
+
+ dc.SetPen(wx.Pen(colourTargetShade))
+
+ if self._direction != wx.RIGHT:
+ dc.DrawLine(left + 1, top + 1, left + 1, bottom)
+ if self._direction != wx.BOTTOM:
+ dc.DrawLine(left + 1, top + 1, right, top + 1)
+
+
+ def DrawDottedLine(self, dc, point, length, vertical):
+ """
+ Draws a dotted line (not used if the docking guide images are ok).
+
+ :param `dc`: a :class:`DC` device context object;
+ :param `point`: a :class:`Point` where to start drawing the dotted line;
+ :param integer `length`: the length of the dotted line;
+ :param bool `vertical`: whether it is a vertical docking guide window or not.
+ """
+
+ for i in xrange(0, length, 2):
+ dc.DrawPoint(point.x, point.y)
+ if vertical:
+ point.y += 2
+ else:
+ point.x += 2
+
+
+ def DrawIcon(self, dc):
+ """
+ Draws the docking guide icon (not used if the docking guide images are ok).
+
+ :param `dc`: a :class:`DC` device context object.
+ """
+
+ rect = wx.Rect(*self.GetClientRect())
+ point = wx.Point()
+ length = 0
+
+ rect.Deflate(4, 4)
+ dc.SetPen(wx.Pen(colourIconBorder))
+ dc.SetBrush(wx.Brush(colourIconBackground))
+ dc.DrawRectangleRect(rect)
+
+ right1 = rect.GetRight() + 1
+ bottom1 = rect.GetBottom() + 1
+
+ dc.SetPen(wx.Pen(colourIconShadow))
+ dc.DrawLine(rect.x + 1, bottom1, right1 + 1, bottom1)
+ dc.DrawLine(right1, rect.y + 1, right1, bottom1 + 1)
+
+ rect.Deflate(1, 1)
+
+ if self._direction == wx.TOP:
+ rect.height -= rect.height / 2
+ point = rect.GetBottomLeft()
+ length = rect.width
+
+ elif self._direction == wx.LEFT:
+ rect.width -= rect.width / 2
+ point = rect.GetTopRight()
+ length = rect.height
+
+ elif self._direction == wx.RIGHT:
+ rect.x += rect.width / 2
+ rect.width -= rect.width / 2
+ point = rect.GetTopLeft()
+ length = rect.height
+
+ elif self._direction == wx.BOTTOM:
+ rect.y += rect.height / 2
+ rect.height -= rect.height / 2
+ point = rect.GetTopLeft()
+ length = rect.width
+
+ elif self._direction == wx.CENTER:
+ rect.Deflate(1, 1)
+ point = rect.GetTopLeft()
+ length = rect.width
+
+ dc.GradientFillLinear(rect, colourIconDockingPart1,
+ colourIconDockingPart2, self._direction)
+
+ dc.SetPen(wx.Pen(colourIconBorder))
+
+ if self._direction == wx.CENTER:
+ self.DrawDottedLine(dc, rect.GetTopLeft(), rect.width, False)
+ self.DrawDottedLine(dc, rect.GetTopLeft(), rect.height, True)
+ self.DrawDottedLine(dc, rect.GetBottomLeft(), rect.width, False)
+ self.DrawDottedLine(dc, rect.GetTopRight(), rect.height, True)
+
+ elif self._direction in [wx.TOP, wx.BOTTOM]:
+ self.DrawDottedLine(dc, point, length, False)
+
+ else:
+ self.DrawDottedLine(dc, point, length, True)
+
+
+ def DrawArrow(self, dc):
+ """
+ Draws the docking guide arrow icon (not used if the docking guide images are ok).
+
+ :param `dc`: a :class:`DC` device context object.
+ """
+
+ rect = self.GetClientRect()
+ point = wx.Point()
+
+ point.x = (rect.GetLeft() + rect.GetRight()) / 2
+ point.y = (rect.GetTop() + rect.GetBottom()) / 2
+ rx, ry = wx.Size(), wx.Size()
+
+ if self._direction == wx.TOP:
+ rx = wx.Size(1, 0)
+ ry = wx.Size(0, 1)
+
+ elif self._direction == wx.LEFT:
+ rx = wx.Size(0, -1)
+ ry = wx.Size(1, 0)
+
+ elif self._direction == wx.RIGHT:
+ rx = wx.Size(0, 1)
+ ry = wx.Size(-1, 0)
+
+ elif self._direction == wx.BOTTOM:
+ rx = wx.Size(-1, 0)
+ ry = wx.Size(0, -1)
+
+ point.x += ry.x*3
+ point.y += ry.y*3
+
+ dc.SetPen(wx.Pen(colourIconArrow))
+
+ for i in xrange(4):
+ pt1 = wx.Point(point.x - rx.x*i, point.y - rx.y*i)
+ pt2 = wx.Point(point.x + rx.x*(i+1), point.y + rx.y*(i+1))
+ dc.DrawLinePoint(pt1, pt2)
+ point.x += ry.x
+ point.y += ry.y
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`AuiDockingGuideWindow`.
+
+ :param `event`: a :class:`PaintEvent` to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+ if self._currentImage.IsOk() and self._valid:
+ dc.DrawBitmap(self._currentImage, 0, 0, True)
+ else:
+ self.Draw(dc)
+
+
+ def Draw(self, dc):
+ """
+ Draws the whole docking guide window (not used if the docking guide images are ok).
+
+ :param `dc`: a :class:`DC` device context object.
+ """
+
+ self.DrawBackground(dc)
+
+ if self._valid:
+ self.DrawIcon(dc)
+ self.DrawArrow(dc)
+
+
+ def UpdateDockGuide(self, pos):
+ """
+ Updates the docking guide images depending on the mouse position, using focused
+ images if the mouse is inside the docking guide or unfocused images if it is
+ outside.
+
+ :param `pos`: a :class:`Point` mouse position.
+ """
+
+ inside = self.GetScreenRect().Contains(pos)
+
+ if inside:
+ image = self._bmp_focus
+ else:
+ image = self._bmp_unfocus
+
+ if image != self._currentImage:
+ self._currentImage = image
+ self.Refresh()
+ self.Update()
+
+
+# ---------------------------------------------------------------------------
+# AuiSingleDockingGuide
+# ---------------------------------------------------------------------------
+
+class AuiSingleDockingGuide(AuiDockingGuide):
+ """ A docking guide window for single docking hint (not diamond-shaped HUD). """
+
+ def __init__(self, parent, direction=0):
+ """
+ Default class constructor. Used internally, do not call it in your code!
+
+ :param `parent`: the :class:`AuiManager` parent;
+ :param integer `direction`: one of ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, ``wx.RIGHT``.
+ """
+
+ self._direction = direction
+
+ style = wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP | \
+ wx.FRAME_NO_TASKBAR | wx.NO_BORDER
+
+ # Use of FRAME_SHAPED on wxMac causes the frame to be visible
+ # breaking the docking hints.
+ if wx.Platform != '__WXMAC__':
+ style |= wx.FRAME_SHAPED
+
+ AuiDockingGuide.__init__(self, parent, style=style, name="auiSingleDockTarget")
+
+ self.Hide()
+
+ useAero = GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_AERO_DOCKING_GUIDES
+ useWhidbey = GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES
+
+ self._useAero = useAero or useWhidbey
+ self._valid = True
+
+ if useAero:
+ sizeX, sizeY = aeroguideSizeX, aeroguideSizeY
+ elif useWhidbey:
+ sizeX, sizeY = whidbeySizeX, whidbeySizeY
+ else:
+ sizeX, sizeY = guideSizeX, guideSizeY
+
+ if direction not in [wx.TOP, wx.BOTTOM]:
+ sizeX, sizeY = sizeY, sizeX
+
+ if self._useAero:
+ self.CreateShapesWithStyle(useWhidbey)
+
+ if wx.Platform == "__WXGTK__":
+ self.Bind(wx.EVT_WINDOW_CREATE, self.SetGuideShape)
+ else:
+ self.SetGuideShape()
+
+ self.SetSize(self.region.GetBox().GetSize())
+ else:
+ self.SetSize((sizeX, sizeY))
+
+ self.rect = wx.Rect(0, 0, sizeX, sizeY)
+
+ if self._useAero:
+ useAero = (useWhidbey and [2] or [1])[0]
+ else:
+ useAero = 0
+
+ self.target = AuiDockingGuideWindow(self, self.rect, direction, False, useAero)
+
+
+ def CreateShapesWithStyle(self, useWhidbey):
+ """
+ Creates the docking guide window shape based on which docking bitmaps are used.
+
+ :param bool `useWhidbey`: if ``True``, use Whidbey-style bitmaps; if ``False``, use the
+ Aero-style bitmaps.
+ """
+
+ sizeX, sizeY = aeroguideSizeX, aeroguideSizeY
+ if useWhidbey:
+ sizeX, sizeY = whidbeySizeX, whidbeySizeY
+
+ if self._direction not in [wx.TOP, wx.BOTTOM]:
+ sizeX, sizeY = sizeY, sizeX
+
+ useAero = (useWhidbey and [2] or [1])[0]
+ bmp, dummy = GetDockingImage(self._direction, useAero, False)
+ region = wx.RegionFromBitmap(bmp)
+
+ self.region = region
+
+
+ def AeroMove(self, pos):
+ """
+ Moves the docking window to the new position. Overridden in children classes.
+
+ :param Point `pos`: the new docking guide position.
+ """
+
+ pass
+
+
+ def SetGuideShape(self, event=None):
+ """
+ Sets the correct shape for the docking guide window.
+
+ :param `event`: on wxGTK, a :class:`WindowCreateEvent` event to process.
+ """
+
+ self.SetShape(self.region)
+
+ if event is not None:
+ # Skip the event on wxGTK
+ event.Skip()
+ wx.CallAfter(wx.SafeYield, self, True)
+
+
+ def SetShape(self, region):
+ """
+ If the platform supports it, sets the shape of the window to that depicted by `region`.
+ The system will not display or respond to any mouse event for the pixels that lie
+ outside of the region. To reset the window to the normal rectangular shape simply call
+ :meth:`SetShape` again with an empty region.
+
+ :param Region `region`: the shape of the frame.
+
+ :note: Overridden for wxMAC.
+ """
+
+ if wx.Platform == '__WXMAC__':
+ # HACK so we don't crash when SetShape is called
+ return
+ else:
+ super(AuiSingleDockingGuide, self).SetShape(region)
+
+
+ def SetValid(self, valid):
+ """
+ Sets the docking direction as valid or invalid.
+
+ :param bool `valid`: whether the docking direction is allowed or not.
+ """
+
+ self._valid = valid
+
+
+ def IsValid(self):
+ """ Returns whether the docking direction is valid. """
+
+ return self._valid
+
+
+ def UpdateDockGuide(self, pos):
+ """
+ Updates the docking guide images depending on the mouse position, using focused
+ images if the mouse is inside the docking guide or unfocused images if it is
+ outside.
+
+ :param Point `pos`: the mouse position.
+ """
+
+ self.target.UpdateDockGuide(pos)
+
+
+ def HitTest(self, x, y):
+ """
+ Checks if the mouse position is inside the target window rect.
+
+ :param integer `x`: the `x` mouse position;
+ :param integer `y`: the `y` mouse position.
+ """
+
+ if self.target.GetScreenRect().Contains((x, y)):
+ return wx.ALL
+
+ return -1
+
+
+# ---------------------------------------------------------------------------
+# AuiCenterDockingGuide
+# ---------------------------------------------------------------------------
+
+class AuiCenterDockingGuide(AuiDockingGuide):
+ """ A docking guide window for multiple docking hint (diamond-shaped HUD). """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+ Used internally, do not call it in your code!
+
+ :param `parent`: the :class:`AuiManager` parent.
+ """
+
+ AuiDockingGuide.__init__(self, parent, style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP |
+ wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.FRAME_SHAPED,
+ name="auiCenterDockTarget")
+
+ self.Hide()
+
+ self.CreateShapesWithStyle()
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ if wx.Platform == "__WXGTK__":
+ self.Bind(wx.EVT_WINDOW_CREATE, self.SetGuideShape)
+ else:
+ self.SetGuideShape()
+
+ self.SetSize(self.region.GetBox().GetSize())
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def CreateShapesWithStyle(self):
+ """ Creates the docking guide window shape based on which docking bitmaps are used. """
+
+ useAero = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_AERO_DOCKING_GUIDES) != 0
+ useWhidbey = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES) != 0
+
+ self._useAero = 0
+ if useAero:
+ self._useAero = 1
+ elif useWhidbey:
+ self._useAero = 2
+
+ if useAero:
+ sizeX, sizeY = aeroguideSizeX, aeroguideSizeY
+ elif useWhidbey:
+ sizeX, sizeY = whidbeySizeX, whidbeySizeY
+ else:
+ sizeX, sizeY = guideSizeX, guideSizeY
+
+ rectLeft = wx.Rect(0, sizeY, sizeY, sizeX)
+ rectTop = wx.Rect(sizeY, 0, sizeX, sizeY)
+ rectRight = wx.Rect(sizeY+sizeX, sizeY, sizeY, sizeX)
+ rectBottom = wx.Rect(sizeY, sizeX + sizeY, sizeX, sizeY)
+ rectCenter = wx.Rect(sizeY, sizeY, sizeX, sizeX)
+
+ if not self._useAero:
+
+ self.targetLeft = AuiDockingGuideWindow(self, rectLeft, wx.LEFT, True, useAero)
+ self.targetTop = AuiDockingGuideWindow(self, rectTop, wx.TOP, True, useAero)
+ self.targetRight = AuiDockingGuideWindow(self, rectRight, wx.RIGHT, True, useAero)
+ self.targetBottom = AuiDockingGuideWindow(self, rectBottom, wx.BOTTOM, True, useAero)
+ self.targetCenter = AuiDockingGuideWindow(self, rectCenter, wx.CENTER, True, useAero)
+
+
+ # top-left diamond
+ tld = [wx.Point(rectTop.x, rectTop.y+rectTop.height-8),
+ wx.Point(rectLeft.x+rectLeft.width-8, rectLeft.y),
+ rectTop.GetBottomLeft()]
+ # bottom-left diamond
+ bld = [wx.Point(rectLeft.x+rectLeft.width-8, rectLeft.y+rectLeft.height),
+ wx.Point(rectBottom.x, rectBottom.y+8),
+ rectBottom.GetTopLeft()]
+ # top-right diamond
+ trd = [wx.Point(rectTop.x+rectTop.width, rectTop.y+rectTop.height-8),
+ wx.Point(rectRight.x+8, rectRight.y),
+ rectRight.GetTopLeft()]
+ # bottom-right diamond
+ brd = [wx.Point(rectRight.x+8, rectRight.y+rectRight.height),
+ wx.Point(rectBottom.x+rectBottom.width, rectBottom.y+8),
+ rectBottom.GetTopRight()]
+
+ self._triangles = [tld[0:2], bld[0:2],
+ [wx.Point(rectTop.x+rectTop.width-1, rectTop.y+rectTop.height-8),
+ wx.Point(rectRight.x+7, rectRight.y)],
+ [wx.Point(rectRight.x+7, rectRight.y+rectRight.height),
+ wx.Point(rectBottom.x+rectBottom.width-1, rectBottom.y+8)]]
+
+ region = wx.Region()
+ region.UnionRect(rectLeft)
+ region.UnionRect(rectTop)
+ region.UnionRect(rectRight)
+ region.UnionRect(rectBottom)
+ region.UnionRect(rectCenter)
+ region.UnionRegion(wx.RegionFromPoints(tld))
+ region.UnionRegion(wx.RegionFromPoints(bld))
+ region.UnionRegion(wx.RegionFromPoints(trd))
+ region.UnionRegion(wx.RegionFromPoints(brd))
+
+ elif useAero:
+
+ self._aeroBmp = aero_dock_pane.GetBitmap()
+ region = wx.RegionFromBitmap(self._aeroBmp)
+
+ self._allAeroBmps = [aero_dock_pane_left.GetBitmap(), aero_dock_pane_top.GetBitmap(),
+ aero_dock_pane_right.GetBitmap(), aero_dock_pane_bottom.GetBitmap(),
+ aero_dock_pane_center.GetBitmap(), aero_dock_pane.GetBitmap()]
+ self._deniedBitmap = aero_denied.GetBitmap()
+ self._aeroRects = [rectLeft, rectTop, rectRight, rectBottom, rectCenter]
+ self._valid = True
+
+ elif useWhidbey:
+
+ self._aeroBmp = whidbey_dock_pane.GetBitmap()
+ region = wx.RegionFromBitmap(self._aeroBmp)
+
+ self._allAeroBmps = [whidbey_dock_pane_left.GetBitmap(), whidbey_dock_pane_top.GetBitmap(),
+ whidbey_dock_pane_right.GetBitmap(), whidbey_dock_pane_bottom.GetBitmap(),
+ whidbey_dock_pane_center.GetBitmap(), whidbey_dock_pane.GetBitmap()]
+ self._deniedBitmap = whidbey_denied.GetBitmap()
+ self._aeroRects = [rectLeft, rectTop, rectRight, rectBottom, rectCenter]
+ self._valid = True
+
+
+ self.region = region
+
+
+ def SetGuideShape(self, event=None):
+ """
+ Sets the correct shape for the docking guide window.
+
+ :param `event`: on wxGTK, a :class:`WindowCreateEvent` event to process.
+ """
+
+ self.SetShape(self.region)
+
+ if event is not None:
+ # Skip the event on wxGTK
+ event.Skip()
+ wx.CallAfter(wx.SafeYield, self, True)
+
+
+ def UpdateDockGuide(self, pos):
+ """
+ Updates the docking guides images depending on the mouse position, using focused
+ images if the mouse is inside the docking guide or unfocused images if it is
+ outside.
+
+ :param Point `pos`: the mouse position.
+ """
+
+ if not self._useAero:
+ for target in self.GetChildren():
+ target.UpdateDockGuide(pos)
+ else:
+ lenRects = len(self._aeroRects)
+ for indx, rect in enumerate(self._aeroRects):
+ if rect.Contains(pos):
+ if self._allAeroBmps[indx] != self._aeroBmp:
+ if indx < lenRects - 1 or (indx == lenRects - 1 and self._valid):
+ self._aeroBmp = self._allAeroBmps[indx]
+ self.Refresh()
+ else:
+ self._aeroBmp = self._allAeroBmps[-1]
+ self.Refresh()
+
+ return
+
+ if self._aeroBmp != self._allAeroBmps[-1]:
+ self._aeroBmp = self._allAeroBmps[-1]
+ self.Refresh()
+
+
+ def HitTest(self, x, y):
+ """
+ Checks if the mouse position is inside the target windows rect.
+
+ :param integer `x`: the `x` mouse position;
+ :param integer `y`: the `y` mouse position.
+ """
+
+ if not self._useAero:
+ if self.targetLeft.GetScreenRect().Contains((x, y)):
+ return wx.LEFT
+ if self.targetTop.GetScreenRect().Contains((x, y)):
+ return wx.UP
+ if self.targetRight.GetScreenRect().Contains((x, y)):
+ return wx.RIGHT
+ if self.targetBottom.GetScreenRect().Contains((x, y)):
+ return wx.DOWN
+ if self.targetCenter.IsValid() and self.targetCenter.GetScreenRect().Contains((x, y)):
+ return wx.CENTER
+ else:
+ constants = [wx.LEFT, wx.UP, wx.RIGHT, wx.DOWN, wx.CENTER]
+ lenRects = len(self._aeroRects)
+ for indx, rect in enumerate(self._aeroRects):
+ if rect.Contains((x, y)):
+ if indx < lenRects or (indx == lenRects-1 and self._valid):
+ return constants[indx]
+
+ return -1
+
+
+ def ValidateNotebookDocking(self, valid):
+ """
+ Sets whether a pane can be docked on top of another to create an automatic
+ :class:`~lib.agw.aui.auibook.AuiNotebook`.
+
+ :param bool `valid`: whether a pane can be docked on top to another to form an automatic
+ :class:`~lib.agw.aui.auibook.AuiNotebook`.
+ """
+
+ if not self._useAero:
+ if self.targetCenter.IsValid() != valid:
+ self.targetCenter.SetValid(valid)
+ self.targetCenter.Refresh()
+ else:
+ if self._valid != valid:
+ self._valid = valid
+ self.Refresh()
+
+
+ def AeroMove(self, pos):
+ """
+ Moves the docking guide window to the new position.
+
+ :param Point `pos`: the new docking guide position.
+ """
+
+ if not self._useAero:
+ return
+
+ useWhidbey = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES) != 0
+
+ if useWhidbey:
+ sizeX, sizeY = whidbeySizeX, whidbeySizeY
+ else:
+ sizeX, sizeY = aeroguideSizeX, aeroguideSizeY
+
+ size = self.GetSize()
+
+ leftRect, topRect, rightRect, bottomRect, centerRect = self._aeroRects
+ thePos = pos + wx.Point((size.x-sizeY)/2, (size.y-sizeX)/2)
+
+ centerRect.SetPosition(thePos)
+
+ leftRect.SetPosition(thePos + wx.Point(-sizeY, 0))
+ topRect.SetPosition(thePos + wx.Point(0, -sizeY))
+ rightRect.SetPosition(thePos + wx.Point(sizeX, 0))
+ bottomRect.SetPosition(thePos + wx.Point(0, sizeX))
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiCenterDockingGuide`.
+
+ :param `event`: :class:`EraseEvent` to be processed.
+
+ :note: This is intentionally empty to reduce flickering while drawing.
+ """
+
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`AuiCenterDockingGuide`.
+
+ :param `event`: a :class:`PaintEvent` to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+
+ if self._useAero:
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ else:
+ dc.SetBrush(wx.Brush(colourTargetBackground))
+ dc.SetPen(wx.Pen(colourTargetBorder))
+
+ rect = self.GetClientRect()
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ if self._useAero:
+ dc.DrawBitmap(self._aeroBmp, 0, 0, True)
+ if not self._valid:
+ diff = (self._useAero == 2 and [1] or [0])[0]
+ bmpX, bmpY = self._deniedBitmap.GetWidth(), self._deniedBitmap.GetHeight()
+ xPos, yPos = (rect.x + (rect.width)/2 - bmpX/2), (rect.y + (rect.height)/2 - bmpY/2)
+ dc.DrawBitmap(self._deniedBitmap, xPos+1, yPos+diff, True)
+
+ return
+
+ dc.SetPen(wx.Pen(colourTargetBorder, 2))
+ for pts in self._triangles:
+ dc.DrawLinePoint(pts[0], pts[1])
+
+
+# ----------------------------------------------------------------------------
+# AuiDockingHintWindow
+# ----------------------------------------------------------------------------
+
+class AuiDockingHintWindow(wx.Frame):
+ """ The original wxAUI docking window hint. """
+
+ def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
+ size=wx.Size(1, 1), style=wx.FRAME_TOOL_WINDOW | wx.FRAME_FLOAT_ON_PARENT |
+ wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.FRAME_SHAPED,
+ name="auiHintWindow"):
+ """
+ Default class constructor. Used internally, do not call it in your code!
+
+ :param `parent`: the :class:`AuiManager` parent;
+ :param integer `id`: the window identifier. It may take a value of -1 to indicate a default value.
+ :param string `title`: the caption to be displayed on the frame's title bar;
+ :param Point `pos`: the window position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param Size `size`: the window size. A value of (-1, -1) indicates a default size, chosen by
+ either the windowing system or wxPython, depending on platform;
+ :param integer `style`: the window style;
+ :param string `name`: the name of the window. This parameter is used to associate a name with the
+ item, allowing the application user to set Motif resource values for individual windows.
+ """
+ if wx.Platform == '__WXMAC__' and style & wx.FRAME_SHAPED:
+ # Having the shaped frame causes the frame to not be visible
+ # with the transparent style hints.
+ style -= wx.FRAME_SHAPED
+
+ wx.Frame.__init__(self, parent, id, title, pos, size, style, name=name)
+
+ self._blindMode = False
+
+ self._art = parent.GetEventHandler().GetArtProvider()
+ background = self._art.GetColour(AUI_DOCKART_HINT_WINDOW_COLOUR)
+ self.SetBackgroundColour(background)
+
+ # Can't set background colour on a frame on wxMac
+ # so add a panel to set the colour on.
+ if wx.Platform == '__WXMAC__':
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.panel = wx.Panel(self)
+ sizer.Add(self.panel, 1, wx.EXPAND)
+ self.SetSizer(sizer)
+ self.panel.SetBackgroundColour(background)
+ else:
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def MakeVenetianBlinds(self):
+ """
+ Creates the "venetian blind" effect if :class:`AuiManager` has the ``AUI_MGR_VENETIAN_BLINDS_HINT``
+ flag set.
+ """
+
+ amount = 128
+ size = self.GetClientSize()
+ region = wx.Region(0, 0, size.x, 1)
+
+ for y in xrange(size.y):
+
+ # Reverse the order of the bottom 4 bits
+ j = (y & 8 and [1] or [0])[0] | (y & 4 and [2] or [0])[0] | \
+ (y & 2 and [4] or [0])[0] | (y & 1 and [8] or [0])[0]
+
+ if 16*j+8 < amount:
+ region.Union(0, y, size.x, 1)
+
+ self.SetShape(region)
+
+
+ def SetBlindMode(self, agwFlags):
+ """
+ Sets whether venetian blinds or transparent hints will be shown as docking hint.
+ This depends on the :class:`AuiManager` flags.
+
+ :param integer `agwFlags`: the :class:`AuiManager` flags.
+ """
+
+ self._blindMode = (agwFlags & AUI_MGR_VENETIAN_BLINDS_HINT) != 0
+
+ if self._blindMode or not self.CanSetTransparent():
+ self.MakeVenetianBlinds()
+ self.SetTransparent(255)
+
+ else:
+ self.SetShape(wx.Region())
+ if agwFlags & AUI_MGR_HINT_FADE == 0:
+ self.SetTransparent(80)
+ else:
+ self.SetTransparent(0)
+
+
+ def SetShape(self, region):
+ """
+ If the platform supports it, sets the shape of the window to that depicted by `region`.
+ The system will not display or respond to any mouse event for the pixels that lie
+ outside of the region. To reset the window to the normal rectangular shape simply call
+ :meth:`SetShape` again with an empty region.
+
+ :param Region `region`: the shape of the frame.
+
+ :note: Overridden for wxMAC.
+ """
+
+ if wx.Platform == '__WXMAC__':
+ # HACK so we don't crash when SetShape is called
+ return
+ else:
+ super(AuiDockingHintWindow, self).SetShape(region)
+
+
+ def Show(self, show=True):
+ """
+ Show the hint window.
+
+ :param bool `show`: whether to show or hide the hint docking window.
+ """
+
+ background = self._art.GetColour(AUI_DOCKART_HINT_WINDOW_COLOUR)
+
+ if wx.Platform == '__WXMAC__':
+ self.panel.SetBackgroundColour(background)
+ else:
+ self.SetBackgroundColour(background)
+
+ super(AuiDockingHintWindow, self).Show(show)
+ self.Refresh()
+
+ if wx.Platform == '__WXMAC__':
+ # Need to manually do layout since its a borderless frame.
+ self.Layout()
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`AuiDockingHintWindow`.
+
+ :param `event`: a :class:`SizeEvent` to be processed.
+ """
+
+ if self._blindMode or not self.CanSetTransparent():
+ self.MakeVenetianBlinds()
+
+ self.Refresh()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`AuiDockingHintWindow`.
+
+ :param `event`: an instance of :class:`PaintEvent` to be processed.
+ """
+
+ rect = wx.RectPS(wx.Point(0, 0), self.GetSize())
+
+ dc = wx.PaintDC(self)
+ event.Skip()
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(wx.Colour(60, 60, 60), 5))
+ rect.Deflate(1, 1)
+ dc.DrawRectangleRect(rect)
+
+
+# ---------------------------------------------------------------------------- #
+
+# -- AuiFloatingFrame class implementation --
+
+class AuiFloatingFrame(wx.MiniFrame):
+ """ AuiFloatingFrame is the frame class that holds floating panes. """
+
+ def __init__(self, parent, owner_mgr, pane=None, id=wx.ID_ANY, title="",
+ style=wx.FRAME_TOOL_WINDOW | wx.FRAME_FLOAT_ON_PARENT |
+ wx.FRAME_NO_TASKBAR | wx.CLIP_CHILDREN):
+ """
+ Default class constructor. Used internally, do not call it in your code!
+
+ :param `parent`: the :class:`AuiManager` parent;
+ :param `owner_mgr`: the :class:`AuiManager` that manages the floating pane;
+ :param `pane`: the :class:`AuiPaneInfo` pane that is about to float;
+ :param integer `id`: the window identifier. It may take a value of -1 to indicate a default value.
+ :param string `title`: the caption to be displayed on the frame's title bar.
+ :param integer `style`: the window style.
+ """
+
+ if pane and pane.IsResizeable():
+ style += wx.RESIZE_BORDER
+ if pane:
+ self._is_toolbar = pane.IsToolbar()
+
+ self._useNativeMiniframes = False
+ if AuiManager_UseNativeMiniframes(owner_mgr):
+ # On wxMac we always use native miniframes
+ self._useNativeMiniframes = True
+ style += wx.CAPTION + wx.SYSTEM_MENU
+ if pane.HasCloseButton():
+ style += wx.CLOSE_BOX
+ if pane.HasMaximizeButton():
+ style += wx.MAXIMIZE_BOX
+ if pane.HasMinimizeButton():
+ style += wx.MINIMIZE_BOX
+
+ wx.MiniFrame.__init__(self, parent, id, title, pos=pane.floating_pos,
+ size=pane.floating_size, style=style, name="auiFloatingFrame")
+
+ self._fly_timer = wx.Timer(self, wx.ID_ANY)
+ self._check_fly_timer = wx.Timer(self, wx.ID_ANY)
+
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
+ self.Bind(wx.EVT_TIMER, self.OnCheckFlyTimer, self._check_fly_timer)
+ self.Bind(wx.EVT_TIMER, self.OnFlyTimer, self._fly_timer)
+ self.Bind(EVT_AUI_FIND_MANAGER, self.OnFindManager)
+
+ if self._useNativeMiniframes:
+ self.Bind(wx.EVT_MOVE, self.OnMoveEvent)
+ self.Bind(wx.EVT_MOVING, self.OnMoveEvent)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+ self._useNativeMiniframes = True
+ self.SetExtraStyle(wx.WS_EX_PROCESS_IDLE)
+ else:
+ self.Bind(wx.EVT_MOVE, self.OnMove)
+
+ self._fly = False
+ self._send_size = True
+ self._alpha_amount = 255
+
+ self._owner_mgr = owner_mgr
+ self._moving = False
+ self._lastDirection = None
+ self._transparent = 255
+
+ self._last_rect = wx.Rect()
+ self._last2_rect = wx.Rect()
+ self._last3_rect = wx.Rect()
+
+ self._mgr = AuiManager()
+ self._mgr.SetManagedWindow(self)
+ self._mgr.SetArtProvider(owner_mgr.GetArtProvider())
+ self._mgr.SetAGWFlags(owner_mgr.GetAGWFlags())
+
+
+ def CopyAttributes(self, pane):
+ """
+ Copies all the attributes of the input `pane` into another :class:`AuiPaneInfo`.
+
+ :param `pane`: the source :class:`AuiPaneInfo` from where to copy attributes.
+ """
+
+ contained_pane = AuiPaneInfo()
+
+ contained_pane.name = pane.name
+ contained_pane.caption = pane.caption
+ contained_pane.window = pane.window
+ contained_pane.frame = pane.frame
+ contained_pane.state = pane.state
+ contained_pane.dock_direction = pane.dock_direction
+ contained_pane.dock_layer = pane.dock_layer
+ contained_pane.dock_row = pane.dock_row
+ contained_pane.dock_pos = pane.dock_pos
+ contained_pane.best_size = wx.Size(*pane.best_size)
+ contained_pane.min_size = wx.Size(*pane.min_size)
+ contained_pane.max_size = wx.Size(*pane.max_size)
+ contained_pane.floating_pos = wx.Point(*pane.floating_pos)
+ contained_pane.floating_size = wx.Size(*pane.floating_size)
+ contained_pane.dock_proportion = pane.dock_proportion
+ contained_pane.buttons = pane.buttons
+ contained_pane.rect = wx.Rect(*pane.rect)
+ contained_pane.icon = pane.icon
+ contained_pane.notebook_id = pane.notebook_id
+ contained_pane.transparent = pane.transparent
+ contained_pane.snapped = pane.snapped
+ contained_pane.minimize_mode = pane.minimize_mode
+ contained_pane.minimize_target = pane.minimize_target
+
+ return contained_pane
+
+
+ def SetPaneWindow(self, pane):
+ """
+ Sets all the properties of a pane.
+
+ :param `pane`: the :class:`AuiPaneInfo` to analyze.
+ """
+
+ self._is_toolbar = pane.IsToolbar()
+ self._pane_window = pane.window
+
+ if isinstance(pane.window, auibar.AuiToolBar):
+ pane.window.SetAuiManager(self._mgr)
+
+ self._pane_window.Reparent(self)
+
+ contained_pane = self.CopyAttributes(pane)
+
+ contained_pane.Dock().Center().Show(). \
+ CaptionVisible(False). \
+ PaneBorder(False). \
+ Layer(0).Row(0).Position(0)
+
+ if not contained_pane.HasGripper() and not self._useNativeMiniframes:
+ contained_pane.CaptionVisible(True)
+
+ indx = self._owner_mgr._panes.index(pane)
+
+ # Carry over the minimum size
+ pane_min_size = pane.window.GetMinSize()
+
+ # if the best size is smaller than the min size
+ # then set the min size to the best size as well
+ pane_best_size = contained_pane.best_size
+ if pane_best_size.IsFullySpecified() and (pane_best_size.x < pane_min_size.x or \
+ pane_best_size.y < pane_min_size.y):
+
+ pane_min_size = pane_best_size
+ self._pane_window.SetMinSize(pane_min_size)
+
+ # if the frame window's max size is greater than the min size
+ # then set the max size to the min size as well
+ cur_max_size = self.GetMaxSize()
+ if cur_max_size.IsFullySpecified() and (cur_max_size.x < pane_min_size.x or \
+ cur_max_size.y < pane_min_size.y):
+ self.SetMaxSize(pane_min_size)
+
+ art_provider = self._mgr.GetArtProvider()
+ caption_size = art_provider.GetMetric(AUI_DOCKART_CAPTION_SIZE)
+ button_size = art_provider.GetMetric(AUI_DOCKART_PANE_BUTTON_SIZE) + \
+ 4*art_provider.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
+
+ min_size = pane.window.GetMinSize()
+
+ if min_size.y < caption_size or min_size.x < button_size:
+ new_x, new_y = min_size.x, min_size.y
+ if min_size.y < caption_size:
+ new_y = (pane.IsResizeable() and [2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y)+caption_size] or [1])[0]
+ if min_size.x < button_size:
+ new_x = (pane.IsResizeable() and [2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_X)+button_size] or [1])[0]
+
+ self.SetMinSize((new_x, new_y))
+ else:
+ self.SetMinSize(min_size)
+
+ self._mgr.AddPane(self._pane_window, contained_pane)
+ self._mgr.Update()
+
+ if pane.min_size.IsFullySpecified():
+ # because SetSizeHints() calls Fit() too (which sets the window
+ # size to its minimum allowed), we keep the size before calling
+ # SetSizeHints() and reset it afterwards...
+ tmp = self.GetSize()
+ self.GetSizer().SetSizeHints(self)
+ self.SetSize(tmp)
+
+ self.SetTitle(pane.caption)
+
+ if pane.floating_size != wx.Size(-1, -1):
+ self.SetSize(pane.floating_size)
+ else:
+ size = pane.best_size
+ if size == wx.Size(-1, -1):
+ size = pane.min_size
+ if size == wx.Size(-1, -1):
+ size = self._pane_window.GetSize()
+ if self._owner_mgr and pane.HasGripper():
+ if pane.HasGripperTop():
+ size.y += self._owner_mgr._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE)
+ else:
+ size.x += self._owner_mgr._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE)
+
+ if not self._useNativeMiniframes:
+ size.y += self._owner_mgr._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
+
+ pane.floating_size = size
+
+ self.SetClientSize(size)
+
+ self._owner_mgr._panes[indx] = pane
+
+ self._fly_step = abs(pane.floating_size.y - \
+ (caption_size + 2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y)))/10
+
+ self._floating_size = wx.Size(*self.GetSize())
+
+ if pane.IsFlyOut():
+ self._check_fly_timer.Start(50)
+
+
+ def GetOwnerManager(self):
+ """ Returns the :class:`AuiManager` that manages the pane. """
+
+ return self._owner_mgr
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`AuiFloatingFrame`.
+
+ :param `event`: a :class:`SizeEvent` to be processed.
+ """
+
+ if self._owner_mgr and self._send_size:
+ self._owner_mgr.OnFloatingPaneResized(self._pane_window, event.GetSize())
+
+
+ def OnClose(self, event):
+ """
+ Handles the ``wx.EVT_CLOSE`` event for :class:`AuiFloatingFrame`.
+
+ :param `event`: a :class:`CloseEvent` to be processed.
+ """
+
+ if self._owner_mgr:
+ self._owner_mgr.OnFloatingPaneClosed(self._pane_window, event)
+
+ if not event.GetVeto():
+ self._mgr.DetachPane(self._pane_window)
+
+ if isinstance(self._pane_window, auibar.AuiToolBar):
+ self._pane_window.SetAuiManager(self._owner_mgr)
+
+ # if we do not do this, then we can crash...
+ if self._owner_mgr and self._owner_mgr._action_window == self:
+ self._owner_mgr._action_window = None
+
+ self._mgr.UnInit()
+ self.Destroy()
+
+
+ def OnActivate(self, event):
+ """
+ Handles the ``wx.EVT_ACTIVATE`` event for :class:`AuiFloatingFrame`.
+
+ :param `event`: a :class:`ActivateEvent` to be processed.
+ """
+
+ if self._owner_mgr and event.GetActive():
+ self._owner_mgr.OnFloatingPaneActivated(self._pane_window)
+
+
+ def OnMove(self, event):
+ """
+ Handles the ``wx.EVT_MOVE`` event for :class:`AuiFloatingFrame`.
+
+ :param `event`: a :class:`MoveEvent` to be processed.
+
+ .. note::
+
+ This event is not processed on wxMAC or if :class:`AuiManager` is not using the
+ ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
+
+ """
+
+ if self._owner_mgr:
+ self._owner_mgr.OnFloatingPaneMoved(self._pane_window, event)
+
+
+ def OnMoveEvent(self, event):
+ """
+ Handles the ``wx.EVT_MOVE`` and ``wx.EVT_MOVING`` events for :class:`AuiFloatingFrame`.
+
+ :param `event`: a :class:`MoveEvent` to be processed.
+
+ .. note::
+
+ This event is only processed on wxMAC or if :class:`AuiManager` is using the
+ ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
+ """
+
+ win_rect = self.GetRect()
+
+ if win_rect == self._last_rect:
+ return
+
+ # skip the first move event
+ if self._last_rect.IsEmpty():
+ self._last_rect = wx.Rect(*win_rect)
+ return
+
+ # As on OSX moving windows are not getting all move events, only sporadically, this difference
+ # is almost always big on OSX, so avoid this early exit opportunity
+ if wx.Platform != '__WXMAC__':
+ # skip if moving too fast to avoid massive redraws and
+ # jumping hint windows
+ if abs(win_rect.x - self._last_rect.x) > 3 or abs(win_rect.y - self._last_rect.y) > 3:
+ self._last3_rect = wx.Rect(*self._last2_rect)
+ self._last2_rect = wx.Rect(*self._last_rect)
+ self._last_rect = wx.Rect(*win_rect)
+
+ # However still update the internally stored position to avoid
+ # snapping back to the old one later.
+ if self._owner_mgr:
+ self._owner_mgr.GetPane(self._pane_window).floating_pos = win_rect.GetPosition()
+
+ return
+
+ # prevent frame redocking during resize
+ if self._last_rect.GetSize() != win_rect.GetSize():
+ self._last3_rect = wx.Rect(*self._last2_rect)
+ self._last2_rect = wx.Rect(*self._last_rect)
+ self._last_rect = wx.Rect(*win_rect)
+ return
+
+ dir = wx.ALL
+
+ horiz_dist = abs(win_rect.x - self._last3_rect.x)
+ vert_dist = abs(win_rect.y - self._last3_rect.y)
+
+ if vert_dist >= horiz_dist:
+ if win_rect.y < self._last3_rect.y:
+ dir = wx.NORTH
+ else:
+ dir = wx.SOUTH
+ else:
+ if win_rect.x < self._last3_rect.x:
+ dir = wx.WEST
+ else:
+ dir = wx.EAST
+
+ self._last3_rect = wx.Rect(*self._last2_rect)
+ self._last2_rect = wx.Rect(*self._last_rect)
+ self._last_rect = wx.Rect(*win_rect)
+
+ if _VERSION_STRING < "2.9":
+ leftDown = wx.GetMouseState().LeftDown()
+ else:
+ leftDown = wx.GetMouseState().LeftIsDown()
+
+ if not leftDown:
+ return
+
+ if not self._moving:
+ self.OnMoveStart(event)
+ self._moving = True
+
+ if self._last3_rect.IsEmpty():
+ return
+
+ if event.GetEventType() == wx.wxEVT_MOVING:
+ self.OnMoving(event.GetRect(), dir)
+ else:
+ self.OnMoving(wx.RectPS(event.GetPosition(), self.GetSize()), dir)
+
+
+ def OnIdle(self, event):
+ """
+ Handles the ``wx.EVT_IDLE`` event for :class:`AuiFloatingFrame`.
+
+ :param `event`: a :class:`IdleEvent` event to be processed.
+
+ .. note::
+
+ This event is only processed on wxMAC if :class:`AuiManager` is using the
+ ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
+
+ """
+
+ if self._moving:
+ if _VERSION_STRING < "2.9":
+ leftDown = wx.GetMouseState().LeftDown()
+ else:
+ leftDown = wx.GetMouseState().LeftIsDown()
+
+ if not leftDown:
+ self._moving = False
+ self.OnMoveFinished()
+ else:
+ event.RequestMore()
+
+
+ def OnMoveStart(self, event):
+ """
+ The user has just started moving the floating pane.
+
+ :param `event`: an instance of :class:`MouseEvent`.
+
+ .. note::
+
+ This event is only processed on wxMAC if :class:`AuiManager` is using the
+ ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
+
+ """
+
+ # notify the owner manager that the pane has started to move
+ if self._owner_mgr:
+ if self._owner_mgr._from_move:
+ return
+ self._owner_mgr._action_window = self._pane_window
+ point = wx.GetMousePosition()
+ action_offset = point - self.GetPosition()
+
+ if self._is_toolbar:
+ self._owner_mgr._toolbar_action_offset = action_offset
+ self._owner_mgr.OnMotion_DragToolbarPane(point)
+ else:
+ self._owner_mgr._action_offset = action_offset
+ self._owner_mgr.OnMotion_DragFloatingPane(point)
+
+
+ def OnMoving(self, rect, direction):
+ """
+ The user is moving the floating pane.
+
+ :param Rect `rect`: the pane client rectangle;
+ :param integer `direction`: the direction in which the pane is moving, can be one of
+ ``wx.NORTH``, ``wx.SOUTH``, ``wx.EAST`` or ``wx.WEST``.
+
+ .. note::
+
+ This event is only processed on wxMAC if :class:`AuiManager` is using the
+ ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
+ """
+
+ # notify the owner manager that the pane is moving
+ self.OnMoveStart(None)
+ self._lastDirection = direction
+
+
+ def OnMoveFinished(self):
+ """
+ The user has just finished moving the floating pane.
+
+ .. note::
+
+ This method is used only on wxMAC if :class:`AuiManager` is using the
+ ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
+
+ """
+
+ # notify the owner manager that the pane has finished moving
+ if self._owner_mgr:
+ self._owner_mgr._action_window = self._pane_window
+ point = wx.GetMousePosition()
+ if self._is_toolbar:
+ self._owner_mgr.OnLeftUp_DragToolbarPane(point)
+ else:
+ self._owner_mgr.OnLeftUp_DragFloatingPane(point)
+
+ self._owner_mgr.OnFloatingPaneMoved(self._pane_window, point)
+
+
+ def OnCheckFlyTimer(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`AuiFloatingFrame`.
+
+ :param `event`: a :class:`TimerEvent` to be processed.
+
+ :note: This is used solely for "fly-out" panes.
+ """
+
+ if self._owner_mgr:
+ pane = self._mgr.GetPane(self._pane_window)
+ if pane.IsFlyOut():
+ if self.IsShownOnScreen():
+ self.FlyOut()
+
+
+ def OnFindManager(self, event):
+ """
+ Handles the ``EVT_AUI_FIND_MANAGER`` event for :class:`AuiFloatingFrame`.
+
+ :param `event`: a :class:`AuiManagerEvent` event to be processed.
+ """
+
+ event.SetManager(self._owner_mgr)
+
+
+ def FlyOut(self):
+ """ Starts the flying in and out of a floating pane. """
+
+ if self._fly_timer.IsRunning():
+ return
+
+ if _VERSION_STRING < "2.9":
+ leftDown = wx.GetMouseState().LeftDown()
+ else:
+ leftDown = wx.GetMouseState().LeftIsDown()
+
+ if leftDown:
+ return
+
+ rect = wx.Rect(*self.GetScreenRect())
+ rect.Inflate(10, 10)
+
+ if rect.Contains(wx.GetMousePosition()):
+ if not self._fly:
+ return
+ self._send_size = False
+ self._fly_timer.Start(5)
+ else:
+ if self._fly:
+ return
+ self._send_size = False
+ self._fly_timer.Start(5)
+
+
+ def OnFlyTimer(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`AuiFloatingFrame`.
+
+ :param `event`: a :class:`TimerEvent` to be processed.
+ """
+
+ current_size = self.GetClientSize()
+ floating_size = wx.Size(*self._owner_mgr.GetPane(self._pane_window).floating_size)
+
+ if floating_size.y == -1:
+ floating_size = self._floating_size
+
+ if not self._fly:
+ min_size = self._mgr.GetArtProvider().GetMetric(AUI_DOCKART_CAPTION_SIZE)
+
+ if wx.Platform != "__WXMSW__":
+ min_size += 2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y)
+
+ if current_size.y - self._fly_step <= min_size:
+ self.SetClientSize((current_size.x, min_size))
+ self._fly = True
+ self._fly_timer.Stop()
+ self._send_size = True
+ else:
+ self.SetClientSize((current_size.x, current_size.y-self._fly_step))
+
+ else:
+ if current_size.y + self._fly_step >= floating_size.y:
+ self.SetClientSize((current_size.x, floating_size.y))
+ self._fly = False
+ self._fly_timer.Stop()
+ self._send_size = True
+ else:
+ self.SetClientSize((current_size.x, current_size.y+self._fly_step))
+
+ self.Update()
+ self.Refresh()
+
+
+ def FadeOut(self):
+ """ Actually starts the fading out of the floating pane. """
+
+ while 1:
+ self._alpha_amount -= 10
+ if self._alpha_amount <= 0:
+ self._alpha_amount = 255
+ return
+
+ self.SetTransparent(self._alpha_amount)
+ wx.SafeYield()
+ wx.MilliSleep(15)
+
+
+# -- static utility functions --
+
+def DrawResizeHint(dc, rect):
+ """
+ Draws a resize hint while a sash is dragged.
+
+ :param Rect `rect`: a rectangle which specifies the sash dimensions.
+ """
+
+ if wx.Platform == "__WXMSW__" and wx.App.GetComCtl32Version() >= 600:
+ if wx.GetOsVersion()[1] > 5:
+ # Windows Vista
+ dc.SetPen(wx.Pen("black", 2, wx.SOLID))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ else:
+ # Draw the nice XP style splitter
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(wx.BLACK_BRUSH)
+ dc.SetLogicalFunction(wx.INVERT)
+ dc.DrawRectangleRect(rect)
+ dc.SetLogicalFunction(wx.COPY)
+ else:
+ stipple = PaneCreateStippleBitmap()
+ brush = wx.BrushFromBitmap(stipple)
+ dc.SetBrush(brush)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ dc.SetLogicalFunction(wx.XOR)
+ dc.DrawRectangleRect(rect)
+
+
+def CopyDocksAndPanes(src_docks, src_panes):
+ """
+ This utility function creates shallow copies of
+ the dock and pane info. :class:`AuiManager` usually contain pointers
+ to :class:`AuiPaneInfo` classes, thus this function is necessary to reliably
+ reconstruct that relationship in the new dock info and pane info arrays.
+
+ :param `src_docks`: a list of :class:`AuiDockInfo` classes;
+ :param `src_panes`: a list of :class:`AuiPaneInfo` classes.
+ """
+
+ dest_docks = src_docks
+ dest_panes = src_panes
+
+ for ii in xrange(len(dest_docks)):
+ dock = dest_docks[ii]
+ for jj in xrange(len(dock.panes)):
+ for kk in xrange(len(src_panes)):
+ if dock.panes[jj] == src_panes[kk]:
+ dock.panes[jj] = dest_panes[kk]
+
+ return dest_docks, dest_panes
+
+
+def CopyDocksAndPanes2(src_docks, src_panes):
+ """
+ This utility function creates full copies of
+ the dock and pane info. :class:`AuiManager` usually contain pointers
+ to :class:`AuiPaneInfo` classes, thus this function is necessary to reliably
+ reconstruct that relationship in the new dock info and pane info arrays.
+
+ :param `src_docks`: a list of :class:`AuiDockInfo` classes;
+ :param `src_panes`: a list of :class:`AuiPaneInfo` classes.
+ """
+
+ dest_docks = []
+
+ for ii in xrange(len(src_docks)):
+ dest_docks.append(AuiDockInfo())
+ dest_docks[ii].dock_direction = src_docks[ii].dock_direction
+ dest_docks[ii].dock_layer = src_docks[ii].dock_layer
+ dest_docks[ii].dock_row = src_docks[ii].dock_row
+ dest_docks[ii].size = src_docks[ii].size
+ dest_docks[ii].min_size = src_docks[ii].min_size
+ dest_docks[ii].resizable = src_docks[ii].resizable
+ dest_docks[ii].fixed = src_docks[ii].fixed
+ dest_docks[ii].toolbar = src_docks[ii].toolbar
+ dest_docks[ii].panes = src_docks[ii].panes
+ dest_docks[ii].rect = wx.Rect(*src_docks[ii].rect)
+
+ dest_panes = []
+
+ for ii in xrange(len(src_panes)):
+ dest_panes.append(AuiPaneInfo())
+ dest_panes[ii].name = src_panes[ii].name
+ dest_panes[ii].caption = src_panes[ii].caption
+ dest_panes[ii].window = src_panes[ii].window
+ dest_panes[ii].frame = src_panes[ii].frame
+ dest_panes[ii].state = src_panes[ii].state
+ dest_panes[ii].dock_direction = src_panes[ii].dock_direction
+ dest_panes[ii].dock_layer = src_panes[ii].dock_layer
+ dest_panes[ii].dock_row = src_panes[ii].dock_row
+ dest_panes[ii].dock_pos = src_panes[ii].dock_pos
+ dest_panes[ii].best_size = wx.Size(*src_panes[ii].best_size)
+ dest_panes[ii].min_size = wx.Size(*src_panes[ii].min_size)
+ dest_panes[ii].max_size = wx.Size(*src_panes[ii].max_size)
+ dest_panes[ii].floating_pos = wx.Point(*src_panes[ii].floating_pos)
+ dest_panes[ii].floating_size = wx.Size(*src_panes[ii].floating_size)
+ dest_panes[ii].dock_proportion = src_panes[ii].dock_proportion
+ dest_panes[ii].buttons = src_panes[ii].buttons
+ dest_panes[ii].rect = wx.Rect(*src_panes[ii].rect)
+ dest_panes[ii].icon = src_panes[ii].icon
+ dest_panes[ii].notebook_id = src_panes[ii].notebook_id
+ dest_panes[ii].transparent = src_panes[ii].transparent
+ dest_panes[ii].snapped = src_panes[ii].snapped
+ dest_panes[ii].minimize_mode = src_panes[ii].minimize_mode
+ dest_panes[ii].minimize_target = src_panes[ii].minimize_target
+
+ for ii in xrange(len(dest_docks)):
+ dock = dest_docks[ii]
+ for jj in xrange(len(dock.panes)):
+ for kk in xrange(len(src_panes)):
+ if dock.panes[jj] == src_panes[kk]:
+ dock.panes[jj] = dest_panes[kk]
+
+ dest_docks[ii] = dock
+
+ return dest_docks, dest_panes
+
+
+def GetMaxLayer(docks, dock_direction):
+ """
+ This is an internal function which returns
+ the highest layer inside the specified dock.
+
+ :param `docks`: a list of :class:`AuiDockInfo`;
+ :param `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze.
+ """
+
+ max_layer = 0
+
+ for dock in docks:
+ if dock.dock_direction == dock_direction and dock.dock_layer > max_layer and not dock.fixed:
+ max_layer = dock.dock_layer
+
+ return max_layer
+
+
+def GetMaxRow(panes, dock_direction, dock_layer):
+ """
+ This is an internal function which returns
+ the highest layer inside the specified dock.
+
+ :param `panes`: a list of :class:`AuiPaneInfo`;
+ :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
+ :param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze.
+ """
+
+ max_row = 0
+
+ for pane in panes:
+ if pane.dock_direction == dock_direction and pane.dock_layer == dock_layer and \
+ pane.dock_row > max_row:
+ max_row = pane.dock_row
+
+ return max_row
+
+
+def DoInsertDockLayer(panes, dock_direction, dock_layer):
+ """
+ This is an internal function that inserts a new dock
+ layer by incrementing all existing dock layer values by one.
+
+ :param `panes`: a list of :class:`AuiPaneInfo`;
+ :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
+ :param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze.
+ """
+
+ for ii in xrange(len(panes)):
+ pane = panes[ii]
+ if not pane.IsFloating() and pane.dock_direction == dock_direction and pane.dock_layer >= dock_layer:
+ pane.dock_layer = pane.dock_layer + 1
+
+ panes[ii] = pane
+
+ return panes
+
+
+def DoInsertDockRow(panes, dock_direction, dock_layer, dock_row):
+ """
+ This is an internal function that inserts a new dock
+ row by incrementing all existing dock row values by one.
+
+ :param `panes`: a list of :class:`AuiPaneInfo`;
+ :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
+ :param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze;
+ :param integer `dock_row`: the :class:`AuiDockInfo` row to analyze.
+ """
+
+ for pane in panes:
+ if not pane.IsFloating() and pane.dock_direction == dock_direction and \
+ pane.dock_layer == dock_layer and pane.dock_row >= dock_row:
+ pane.dock_row += 1
+
+ return panes
+
+
+def DoInsertPane(panes, dock_direction, dock_layer, dock_row, dock_pos):
+ """
+ This is an internal function that inserts a new pane
+ by incrementing all existing dock position values by one.
+
+ :param `panes`: a list of :class:`AuiPaneInfo`;
+ :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
+ :param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze.
+ :param integer `dock_row`: the :class:`AuiDockInfo` row to analyze;
+ :param integer `dock_pos`: the :class:`AuiDockInfo` position to analyze.
+ """
+
+ for ii in xrange(len(panes)):
+ pane = panes[ii]
+ if not pane.IsFloating() and pane.dock_direction == dock_direction and \
+ pane.dock_layer == dock_layer and pane.dock_row == dock_row and \
+ pane.dock_pos >= dock_pos:
+ pane.dock_pos = pane.dock_pos + 1
+
+ panes[ii] = pane
+
+ return panes
+
+
+def FindDocks(docks, dock_direction, dock_layer=-1, dock_row=-1, reverse=False):
+ """
+ This is an internal function that returns a list of docks which meet
+ the specified conditions in the parameters and returns a sorted array
+ (sorted by layer and then row).
+
+ :param `docks`: a list of :class:`AuiDockInfo`;
+ :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
+ :param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze.
+ :param integer `dock_row`: the :class:`AuiDockInfo` row to analyze;
+ """
+
+ matchDocks = [(d.dock_layer, d.dock_row, d.dock_direction, d) for d in docks if \
+ (dock_direction == -1 or dock_direction == d.dock_direction) and \
+ ((dock_layer == -1 or dock_layer == d.dock_layer) and \
+ (dock_row == -1 or dock_row == d.dock_row))]
+
+ arr = [x[-1] for x in sorted(matchDocks, reverse=reverse)]
+
+ return arr
+
+
+def FindOppositeDocks(docks, dock_direction):
+ """
+ This is an internal function that returns a list of docks
+ which is related to the opposite direction.
+
+ :param `docks`: a list of :class:`AuiDockInfo`;
+ :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
+ """
+
+ if dock_direction == AUI_DOCK_LEFT:
+ arr = FindDocks(docks, AUI_DOCK_RIGHT, -1, -1)
+ elif dock_direction == AUI_DOCK_TOP:
+ arr = FindDocks(docks, AUI_DOCK_BOTTOM, -1, -1)
+ elif dock_direction == AUI_DOCK_RIGHT:
+ arr = FindDocks(docks, AUI_DOCK_LEFT, -1, -1)
+ elif dock_direction == AUI_DOCK_BOTTOM:
+ arr = FindDocks(docks, AUI_DOCK_TOP, -1, -1)
+
+ return arr
+
+
+def FindPaneInDock(dock, window):
+ """
+ This method looks up a specified window pointer inside a dock.
+ If found, the corresponding :class:`AuiDockInfo` pointer is returned, otherwise ``None``.
+
+ :param `dock`: a :class:`AuiDockInfo` structure;
+ :param Window `window`: the window associated to the pane we are seeking.
+ """
+
+ for p in dock.panes:
+ if p.window == window:
+ return p
+
+ return None
+
+
+def GetToolBarDockOffsets(docks):
+ """
+ Returns the toolbar dock offsets (top-left and bottom-right).
+
+ :param `docks`: a list of :class:`AuiDockInfo` to analyze.
+ """
+
+ top_left = wx.Size(0, 0)
+ bottom_right = wx.Size(0, 0)
+
+ for dock in docks:
+ if dock.toolbar:
+ dock_direction = dock.dock_direction
+ if dock_direction == AUI_DOCK_LEFT:
+ top_left.x += dock.rect.width
+ bottom_right.x += dock.rect.width
+
+ elif dock_direction == AUI_DOCK_TOP:
+ top_left.y += dock.rect.height
+ bottom_right.y += dock.rect.height
+
+ elif dock_direction == AUI_DOCK_RIGHT:
+ bottom_right.x += dock.rect.width
+
+ elif dock_direction == AUI_DOCK_BOTTOM:
+ bottom_right.y += dock.rect.height
+
+ return top_left, bottom_right
+
+
+def GetInternalFrameRect(window, docks):
+ """
+ Returns the window rectangle excluding toolbars.
+
+ :param `window`: a :class:`Window` derived window;
+ :param `docks`: a list of :class:`AuiDockInfo` structures.
+ """
+
+ frameRect = wx.Rect()
+
+ frameRect.SetTopLeft(window.ClientToScreen(window.GetClientAreaOrigin()))
+ frameRect.SetSize(window.GetClientSize())
+
+ top_left, bottom_right = GetToolBarDockOffsets(docks)
+
+ # make adjustments for toolbars
+ frameRect.x += top_left.x
+ frameRect.y += top_left.y
+ frameRect.width -= bottom_right.x
+ frameRect.height -= bottom_right.y
+
+ return frameRect
+
+
+def CheckOutOfWindow(window, pt):
+ """
+ Checks if a point is outside the window rectangle.
+
+ :param `window`: a :class:`Window` derived window;
+ :param `pt`: a :class:`Point` object.
+ """
+
+ auiWindowMargin = 30
+ marginRect = wx.Rect(*window.GetClientRect())
+ marginRect.Inflate(auiWindowMargin, auiWindowMargin)
+
+ return not marginRect.Contains(pt)
+
+
+def CheckEdgeDrop(window, docks, pt):
+ """
+ Checks on which edge of a window the drop action has taken place.
+
+ :param `window`: a :class:`Window` derived window;
+ :param `docks`: a list of :class:`AuiDockInfo` structures;
+ :param `pt`: a :class:`Point` object.
+ """
+
+ screenPt = window.ClientToScreen(pt)
+ clientSize = window.GetClientSize()
+ frameRect = GetInternalFrameRect(window, docks)
+
+ if screenPt.y >= frameRect.GetTop() and screenPt.y < frameRect.GetBottom():
+ if pt.x < auiLayerInsertOffset and pt.x > auiLayerInsertOffset - auiLayerInsertPixels:
+ return wx.LEFT
+
+ if pt.x >= clientSize.x - auiLayerInsertOffset and \
+ pt.x < clientSize.x - auiLayerInsertOffset + auiLayerInsertPixels:
+ return wx.RIGHT
+
+ if screenPt.x >= frameRect.GetLeft() and screenPt.x < frameRect.GetRight():
+ if pt.y < auiLayerInsertOffset and pt.y > auiLayerInsertOffset - auiLayerInsertPixels:
+ return wx.TOP
+
+ if pt.y >= clientSize.y - auiLayerInsertOffset and \
+ pt.y < clientSize.y - auiLayerInsertOffset + auiLayerInsertPixels:
+ return wx.BOTTOM
+
+ return -1
+
+
+def RemovePaneFromDocks(docks, pane, exc=None):
+ """
+ Removes a pane window from all docks
+ with a possible exception specified by parameter `exc`.
+
+ :param `docks`: a list of :class:`AuiDockInfo` structures;
+ :param AuiPaneInfo `pane`: the pane to be removed;
+ :param AuiPaneInfo `exc`: the possible pane exception.
+ """
+
+ for ii in xrange(len(docks)):
+ d = docks[ii]
+ if d == exc:
+ continue
+ pi = FindPaneInDock(d, pane.window)
+ if pi:
+ d.panes.remove(pi)
+
+ docks[ii] = d
+
+ return docks
+
+
+def RenumberDockRows(docks):
+ """
+ Takes a dock and assigns sequential numbers
+ to existing rows. Basically it takes out the gaps so if a
+ dock has rows with numbers 0, 2, 5, they will become 0, 1, 2.
+
+ :param `docks`: a list of :class:`AuiDockInfo` structures.
+ """
+
+ for ii in xrange(len(docks)):
+ dock = docks[ii]
+ dock.dock_row = ii
+ for jj in xrange(len(dock.panes)):
+ dock.panes[jj].dock_row = ii
+
+ docks[ii] = dock
+
+ return docks
+
+
+def SetActivePane(panes, active_pane):
+ """
+ Sets the active pane, as well as cycles through
+ every other pane and makes sure that all others' active flags
+ are turned off.
+
+ :param `panes`: a list of :class:`AuiPaneInfo` structures;
+ :param AuiPaneInfo `active_pane`: the pane to be made active (if found).
+ """
+
+ for pane in panes:
+ pane.state &= ~AuiPaneInfo.optionActive
+
+ for pane in panes:
+ if pane.window == active_pane and not pane.IsNotebookPage():
+ pane.state |= AuiPaneInfo.optionActive
+ return True, panes
+
+ return False, panes
+
+
+def ShowDockingGuides(guides, show):
+ """
+ Shows or hide the docking guide windows.
+
+ :param `guides`: a list of :class:`AuiDockingGuide` classes;
+ :param bool `show`: whether to show or hide the docking guide windows.
+ """
+
+ for target in guides:
+
+ if show and not target.host.IsShown():
+ target.host.Show()
+ target.host.Update()
+
+ elif not show and target.host.IsShown():
+ target.host.Hide()
+
+
+def RefreshDockingGuides(guides):
+ """
+ Refreshes the docking guide windows.
+
+ :param `guides`: a list of :class:`AuiDockingGuide` classes;
+ """
+
+ for target in guides:
+ if target.host.IsShown():
+ target.host.Refresh()
+
+
+def PaneSortFunc(p1, p2):
+ """
+ This function is used to sort panes by dock position.
+
+ :param AuiPaneInfo `p1`: the first pane instance to compare;
+ :param AuiPaneInfo `p2`: the second pane instance to compare.
+ """
+
+ return (p1.dock_pos < p2.dock_pos and [-1] or [1])[0]
+
+
+def GetNotebookRoot(panes, notebook_id):
+ """
+ Returns the :class:`~lib.agw.aui.auibook.AuiNotebook` which has the specified `notebook_id`.
+
+ :param `panes`: a list of :class:`AuiPaneInfo` instances;
+ :param integer `notebook_id`: the target notebook id.
+ """
+
+ for paneInfo in panes:
+ if paneInfo.IsNotebookControl() and paneInfo.notebook_id == notebook_id:
+ return paneInfo
+
+ return None
+
+
+def EscapeDelimiters(s):
+ """
+ Changes ``;`` into ``\`` and ``|`` into ``\|`` in the input string.
+
+ :param string `s`: the string to be analyzed.
+
+ :note: This is an internal functions which is used for saving perspectives.
+ """
+
+ result = s.replace(";", "\\")
+ result = result.replace("|", "|\\")
+
+ return result
+
+
+def IsDifferentDockingPosition(pane1, pane2):
+ """
+ Returns whether `pane1` and `pane2` are in a different docking position
+ based on pane status, docking direction, docking layer and docking row.
+
+ :param `pane1`: a :class:`AuiPaneInfo` instance;
+ :param `pane2`: another :class:`AuiPaneInfo` instance.
+ """
+
+ return pane1.IsFloating() != pane2.IsFloating() or \
+ pane1.dock_direction != pane2.dock_direction or \
+ pane1.dock_layer != pane2.dock_layer or \
+ pane1.dock_row != pane2.dock_row
+
+
+# Convenience function
+def AuiManager_HasLiveResize(manager):
+ """
+ Static function which returns if the input `manager` should have "live resize"
+ behaviour.
+
+ :param `manager`: an instance of :class:`AuiManager`.
+
+ .. note::
+
+ This method always returns ``True`` on wxMAC as this platform doesn't have
+ the ability to use :class:`ScreenDC` to draw sashes.
+
+ """
+
+ # With Core Graphics on Mac, it's not possible to show sash feedback,
+ # so we'll always use live update instead.
+
+ if wx.Platform == "__WXMAC__":
+ return True
+ else:
+ return (manager.GetAGWFlags() & AUI_MGR_LIVE_RESIZE) == AUI_MGR_LIVE_RESIZE
+
+
+# Convenience function
+def AuiManager_UseNativeMiniframes(manager):
+ """
+ Static function which returns if the input `manager` should use native :class:`MiniFrame` as
+ floating panes.
+
+ :param `manager`: an instance of :class:`AuiManager`.
+
+ .. note::
+
+ This method always returns ``True`` on wxMAC as this platform doesn't have
+ the ability to use custom drawn miniframes.
+
+ """
+
+ # With Core Graphics on Mac, it's not possible to show sash feedback,
+ # so we'll always use live update instead.
+
+ if wx.Platform == "__WXMAC__":
+ return True
+ else:
+ return (manager.GetAGWFlags() & AUI_MGR_USE_NATIVE_MINIFRAMES) == AUI_MGR_USE_NATIVE_MINIFRAMES
+
+
+def GetManager(window):
+ """
+ This function will return the aui manager for a given window.
+
+ :param Window `window`: this parameter should be any child window or grand-child
+ window (and so on) of the frame/window managed by :class:`AuiManager`. The window
+ does not need to be managed by the manager itself, nor does it even need
+ to be a child or sub-child of a managed window. It must however be inside
+ the window hierarchy underneath the managed window.
+ """
+
+ if not isinstance(wx.GetTopLevelParent(window), AuiFloatingFrame):
+ if isinstance(window, auibar.AuiToolBar):
+ return window.GetAuiManager()
+
+ evt = AuiManagerEvent(wxEVT_AUI_FIND_MANAGER)
+ evt.SetManager(None)
+ evt.ResumePropagation(wx.EVENT_PROPAGATE_MAX)
+
+ if not window.GetEventHandler().ProcessEvent(evt):
+ return None
+
+ return evt.GetManager()
+
+
+# ---------------------------------------------------------------------------- #
+
+class AuiManager(wx.EvtHandler):
+ """
+ AuiManager manages the panes associated with it for a particular :class:`Frame`,
+ using a pane's :class:`AuiManager` information to determine each pane's docking and
+ floating behavior. :class:`AuiManager` uses wxPython's sizer mechanism to plan the
+ layout of each frame. It uses a replaceable dock art class to do all drawing,
+ so all drawing is localized in one area, and may be customized depending on an
+ applications' specific needs.
+
+ :class:`AuiManager` works as follows: the programmer adds panes to the class, or makes
+ changes to existing pane properties (dock position, floating state, show state, etc...).
+ To apply these changes, the :meth:`AuiManager.Update() <AuiManager.Update>` function is called. This batch
+ processing can be used to avoid flicker, by modifying more than one pane at a time,
+ and then "committing" all of the changes at once by calling `Update()`.
+
+ Panes can be added quite easily::
+
+ text1 = wx.TextCtrl(self, -1)
+ text2 = wx.TextCtrl(self, -1)
+ self._mgr.AddPane(text1, AuiPaneInfo().Left().Caption("Pane Number One"))
+ self._mgr.AddPane(text2, AuiPaneInfo().Bottom().Caption("Pane Number Two"))
+
+ self._mgr.Update()
+
+
+ Later on, the positions can be modified easily. The following will float an
+ existing pane in a tool window::
+
+ self._mgr.GetPane(text1).Float()
+
+
+ **Layers, Rows and Directions, Positions:**
+
+ Inside AUI, the docking layout is figured out by checking several pane parameters.
+ Four of these are important for determining where a pane will end up.
+
+ **Direction** - Each docked pane has a direction, `Top`, `Bottom`, `Left`, `Right`, or `Center`.
+ This is fairly self-explanatory. The pane will be placed in the location specified
+ by this variable.
+
+ **Position** - More than one pane can be placed inside of a "dock". Imagine two panes
+ being docked on the left side of a window. One pane can be placed over another.
+ In proportionally managed docks, the pane position indicates it's sequential position,
+ starting with zero. So, in our scenario with two panes docked on the left side, the
+ top pane in the dock would have position 0, and the second one would occupy position 1.
+
+ **Row** - A row can allow for two docks to be placed next to each other. One of the most
+ common places for this to happen is in the toolbar. Multiple toolbar rows are allowed,
+ the first row being in row 0, and the second in row 1. Rows can also be used on
+ vertically docked panes.
+
+ **Layer** - A layer is akin to an onion. Layer 0 is the very center of the managed pane.
+ Thus, if a pane is in layer 0, it will be closest to the center window (also sometimes
+ known as the "content window"). Increasing layers "swallow up" all layers of a lower
+ value. This can look very similar to multiple rows, but is different because all panes
+ in a lower level yield to panes in higher levels. The best way to understand layers
+ is by running the AUI sample (`AUI.py`).
+ """
+
+ def __init__(self, managed_window=None, agwFlags=None):
+ """
+ Default class constructor.
+
+ :param Window `managed_window`: specifies the window which should be managed;
+ :param integer `agwFlags`: specifies options which allow the frame management behavior to be
+ modified. `agwFlags` can be a combination of the following style bits:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_MGR_ALLOW_FLOATING`` Allow floating of panes
+ ``AUI_MGR_ALLOW_ACTIVE_PANE`` If a pane becomes active, "highlight" it in the interface
+ ``AUI_MGR_TRANSPARENT_DRAG`` If the platform supports it, set transparency on a floating pane while it is dragged by the user
+ ``AUI_MGR_TRANSPARENT_HINT`` If the platform supports it, show a transparent hint window when the user is about to dock a floating pane
+ ``AUI_MGR_VENETIAN_BLINDS_HINT`` Show a "venetian blind" effect when the user is about to dock a floating pane
+ ``AUI_MGR_RECTANGLE_HINT`` Show a rectangle hint effect when the user is about to dock a floating pane
+ ``AUI_MGR_HINT_FADE`` If the platform supports it, the hint window will fade in and out
+ ``AUI_MGR_NO_VENETIAN_BLINDS_FADE`` Disables the "venetian blind" fade in and out
+ ``AUI_MGR_LIVE_RESIZE`` Live resize when the user drag a sash
+ ``AUI_MGR_ANIMATE_FRAMES`` Fade-out floating panes when they are closed (all platforms which support frames transparency)
+ and show a moving rectangle when they are docked (Windows < Vista and GTK only)
+ ``AUI_MGR_AERO_DOCKING_GUIDES`` Use the new Aero-style bitmaps as docking guides
+ ``AUI_MGR_PREVIEW_MINIMIZED_PANES`` Slide in and out minimized panes to preview them
+ ``AUI_MGR_WHIDBEY_DOCKING_GUIDES`` Use the new Whidbey-style bitmaps as docking guides
+ ``AUI_MGR_SMOOTH_DOCKING`` Performs a "smooth" docking of panes (a la PyQT)
+ ``AUI_MGR_USE_NATIVE_MINIFRAMES`` Use miniframes with native caption bar as floating panes instead or custom drawn caption bars (forced on wxMAC)
+ ``AUI_MGR_AUTONB_NO_CAPTION`` Panes that merge into an automatic notebook will not have the pane caption visible
+ ==================================== ==================================
+
+ Default value for `agwFlags` is:
+ ``AUI_MGR_DEFAULT`` = ``AUI_MGR_ALLOW_FLOATING`` | ``AUI_MGR_TRANSPARENT_HINT`` | ``AUI_MGR_HINT_FADE`` | ``AUI_MGR_NO_VENETIAN_BLINDS_FADE``
+
+ .. note::
+
+ If using the ``AUI_MGR_USE_NATIVE_MINIFRAMES``, double-clicking on a
+ floating pane caption will not re-dock the pane, but simply maximize it (if
+ :meth:`AuiPaneInfo.MaximizeButton` has been set to ``True``) or do nothing.
+
+ """
+
+ wx.EvtHandler.__init__(self)
+
+ self._action = actionNone
+ self._action_window = None
+ self._hover_button = None
+ self._art = dockart.AuiDefaultDockArt()
+ self._hint_window = None
+ self._active_pane = None
+ self._has_maximized = False
+ self._has_minimized = False
+
+ self._frame = None
+ self._dock_constraint_x = 0.3
+ self._dock_constraint_y = 0.3
+ self._reserved = None
+
+ self._panes = []
+ self._docks = []
+ self._uiparts = []
+
+ self._guides = []
+ self._notebooks = []
+
+ self._masterManager = None
+ self._currentDragItem = -1
+ self._lastknowndocks = {}
+
+ self._hint_fadetimer = wx.Timer(self, wx.ID_ANY)
+ self._hint_fademax = 50
+ self._last_hint = wx.Rect()
+
+ self._from_move = False
+ self._last_rect = wx.Rect()
+
+ if agwFlags is None:
+ agwFlags = AUI_MGR_DEFAULT
+
+ self._agwFlags = agwFlags
+ self._is_docked = (False, wx.RIGHT, wx.TOP, 0)
+ self._snap_limits = (15, 15)
+
+ if wx.Platform == "__WXMSW__":
+ self._animation_step = 30.0
+ else:
+ self._animation_step = 5.0
+
+ self._hint_rect = wx.Rect()
+
+ self._preview_timer = wx.Timer(self, wx.ID_ANY)
+ self._sliding_frame = None
+
+ self._autoNBTabArt = tabart.AuiDefaultTabArt()
+ self._autoNBStyle = AUI_NB_DEFAULT_STYLE | AUI_NB_BOTTOM | \
+ AUI_NB_SUB_NOTEBOOK | AUI_NB_TAB_EXTERNAL_MOVE
+ self._autoNBStyle -= AUI_NB_DRAW_DND_TAB
+
+ if managed_window:
+ self.SetManagedWindow(managed_window)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_SET_CURSOR, self.OnSetCursor)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+ self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus)
+ self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLost)
+ self.Bind(wx.EVT_TIMER, self.OnHintFadeTimer, self._hint_fadetimer)
+ self.Bind(wx.EVT_TIMER, self.SlideIn, self._preview_timer)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+
+ self.Bind(wx.EVT_MOVE, self.OnMove)
+ self.Bind(wx.EVT_SYS_COLOUR_CHANGED, self.OnSysColourChanged)
+
+ self.Bind(EVT_AUI_PANE_BUTTON, self.OnPaneButton)
+ self.Bind(EVT_AUI_RENDER, self.OnRender)
+ self.Bind(EVT_AUI_FIND_MANAGER, self.OnFindManager)
+ self.Bind(EVT_AUI_PANE_MIN_RESTORE, self.OnRestoreMinimizedPane)
+ self.Bind(EVT_AUI_PANE_DOCKED, self.OnPaneDocked)
+
+ self.Bind(auibook.EVT_AUINOTEBOOK_BEGIN_DRAG, self.OnTabBeginDrag)
+ self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnTabPageClose)
+ self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnTabSelected)
+
+
+ def CreateFloatingFrame(self, parent, pane_info):
+ """
+ Creates a floating frame for the windows.
+
+ :param Window `parent`: the floating frame parent;
+ :param `pane_info`: the :class:`AuiPaneInfo` class with all the pane's information.
+ """
+
+ return AuiFloatingFrame(parent, self, pane_info)
+
+
+ def CanDockPanel(self, p):
+ """
+ Returns whether a pane can be docked or not.
+
+ :param `p`: the :class:`AuiPaneInfo` class with all the pane's information.
+ """
+
+ # is the pane dockable?
+ if not p.IsDockable():
+ return False
+
+ # if a key modifier is pressed while dragging the frame,
+ # don't dock the window
+ return not (wx.GetKeyState(wx.WXK_CONTROL) or wx.GetKeyState(wx.WXK_ALT))
+
+
+ def GetPaneByWidget(self, window):
+ """
+ This version of :meth:`GetPane` looks up a pane based on a 'pane window'.
+
+ :param `window`: a :class:`Window` derived window.
+
+ :see: :meth:`~AuiManager.GetPane`
+ """
+
+ for p in self._panes:
+ if p.window == window:
+ return p
+
+ return NonePaneInfo
+
+
+ def GetPaneByName(self, name):
+ """
+ This version of :meth:`GetPane` looks up a pane based on a 'pane name'.
+
+ :param string `name`: the pane name.
+
+ :see: :meth:`GetPane`
+ """
+
+ for p in self._panes:
+ if p.name == name:
+ return p
+
+ return NonePaneInfo
+
+
+ def GetPane(self, item):
+ """
+ Looks up a :class:`AuiPaneInfo` structure based on the supplied window pointer. Upon failure,
+ :meth:`GetPane` returns an empty :class:`AuiPaneInfo`, a condition which can be checked
+ by calling :meth:`AuiPaneInfo.IsOk() <AuiPaneInfo.IsOk>`.
+
+ The pane info's structure may then be modified. Once a pane's info is modified, :meth:`Update`
+ must be called to realize the changes in the UI.
+
+ :param `item`: either a pane name or a :class:`Window`.
+ """
+
+ if isinstance(item, basestring):
+ return self.GetPaneByName(item)
+ else:
+ return self.GetPaneByWidget(item)
+
+
+ def GetAllPanes(self):
+ """ Returns a reference to all the pane info structures. """
+
+ return self._panes
+
+
+ def ShowPane(self, window, show):
+ """
+ Shows or hides a pane based on the window passed as input.
+
+ :param Window `window`: any subclass or derivation of :class:`Window`;
+ :param bool `show`: ``True`` to show the pane, ``False`` otherwise.
+ """
+
+ p = self.GetPane(window)
+
+ if p.IsOk():
+ if p.IsNotebookPage():
+ if show:
+
+ notebook = self._notebooks[p.notebook_id]
+ id = notebook.GetPageIndex(p.window)
+ if id >= 0:
+ notebook.SetSelection(id)
+ self.ShowPane(notebook, True)
+
+ else:
+ p.Show(show)
+
+ if p.frame:
+ p.frame.Raise()
+
+ self.Update()
+
+
+ def HitTest(self, x, y):
+ """
+ This is an internal function which determines
+ which UI item the specified coordinates are over.
+
+ :param integer `x`: specifies a x position in client coordinates;
+ :param integer `y`: specifies a y position in client coordinates.
+ """
+
+ result = None
+
+ for item in self._uiparts:
+ # we are not interested in typeDock, because this space
+ # isn't used to draw anything, just for measurements
+ # besides, the entire dock area is covered with other
+ # rectangles, which we are interested in.
+ if item.type == AuiDockUIPart.typeDock:
+ continue
+
+ # if we already have a hit on a more specific item, we are not
+ # interested in a pane hit. If, however, we don't already have
+ # a hit, returning a pane hit is necessary for some operations
+ if item.type in [AuiDockUIPart.typePane, AuiDockUIPart.typePaneBorder] and result:
+ continue
+
+ # if the point is inside the rectangle, we have a hit
+ if item.rect.Contains((x, y)):
+ result = item
+
+ return result
+
+
+ def PaneHitTest(self, panes, pt):
+ """
+ Similar to :meth:`HitTest`, but it checks in which :class:`AuiManager` rectangle the
+ input point belongs to.
+
+ :param `panes`: a list of :class:`AuiPaneInfo` instances;
+ :param Point `pt`: the mouse position.
+ """
+
+ for paneInfo in panes:
+ if paneInfo.IsDocked() and paneInfo.IsShown() and paneInfo.rect.Contains(pt):
+ return paneInfo
+
+ return NonePaneInfo
+
+
+ # SetAGWFlags() and GetAGWFlags() allow the owner to set various
+ # options which are global to AuiManager
+
+ def SetAGWFlags(self, agwFlags):
+ """
+ This method is used to specify :class:`AuiManager` 's settings flags.
+
+ :param integer `agwFlags`: specifies options which allow the frame management behavior
+ to be modified. `agwFlags` can be one of the following style bits:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_MGR_ALLOW_FLOATING`` Allow floating of panes
+ ``AUI_MGR_ALLOW_ACTIVE_PANE`` If a pane becomes active, "highlight" it in the interface
+ ``AUI_MGR_TRANSPARENT_DRAG`` If the platform supports it, set transparency on a floating pane while it is dragged by the user
+ ``AUI_MGR_TRANSPARENT_HINT`` If the platform supports it, show a transparent hint window when the user is about to dock a floating pane
+ ``AUI_MGR_VENETIAN_BLINDS_HINT`` Show a "venetian blind" effect when the user is about to dock a floating pane
+ ``AUI_MGR_RECTANGLE_HINT`` Show a rectangle hint effect when the user is about to dock a floating pane
+ ``AUI_MGR_HINT_FADE`` If the platform supports it, the hint window will fade in and out
+ ``AUI_MGR_NO_VENETIAN_BLINDS_FADE`` Disables the "venetian blind" fade in and out
+ ``AUI_MGR_LIVE_RESIZE`` Live resize when the user drag a sash
+ ``AUI_MGR_ANIMATE_FRAMES`` Fade-out floating panes when they are closed (all platforms which support frames transparency)
+ and show a moving rectangle when they are docked (Windows < Vista and GTK only)
+ ``AUI_MGR_AERO_DOCKING_GUIDES`` Use the new Aero-style bitmaps as docking guides
+ ``AUI_MGR_PREVIEW_MINIMIZED_PANES`` Slide in and out minimized panes to preview them
+ ``AUI_MGR_WHIDBEY_DOCKING_GUIDES`` Use the new Whidbey-style bitmaps as docking guides
+ ``AUI_MGR_SMOOTH_DOCKING`` Performs a "smooth" docking of panes (a la PyQT)
+ ``AUI_MGR_USE_NATIVE_MINIFRAMES`` Use miniframes with native caption bar as floating panes instead or custom drawn caption bars (forced on wxMAC)
+ ``AUI_MGR_AUTONB_NO_CAPTION`` Panes that merge into an automatic notebook will not have the pane caption visible
+ ==================================== ==================================
+
+ .. note::
+
+ If using the ``AUI_MGR_USE_NATIVE_MINIFRAMES``, double-clicking on a
+ floating pane caption will not re-dock the pane, but simply maximize it (if
+ :meth:`AuiPaneInfo.MaximizeButton` has been set to ``True``) or do nothing.
+
+ """
+
+ self._agwFlags = agwFlags
+
+ if len(self._guides) > 0:
+ self.CreateGuideWindows()
+
+ if self._hint_window and agwFlags & AUI_MGR_RECTANGLE_HINT == 0:
+ self.CreateHintWindow()
+
+
+ def GetAGWFlags(self):
+ """
+ Returns the current manager's flags.
+
+ :see: :meth:`SetAGWFlags` for a list of possible :class:`AuiManager` flags.
+ """
+
+ return self._agwFlags
+
+
+ def SetManagedWindow(self, managed_window):
+ """
+ Called to specify the frame or window which is to be managed by :class:`AuiManager`.
+ Frame management is not restricted to just frames. Child windows or custom
+ controls are also allowed.
+
+ :param Window `managed_window`: specifies the window which should be managed by
+ the AUI manager.
+ """
+
+ if not managed_window:
+ raise Exception("Specified managed window must be non-null. ")
+ if isinstance(managed_window, sc.SizedParent):
+ raise Exception("Do not use wx.lib.sized_control for managed window. ")
+
+ self.UnInit()
+
+ self._frame = managed_window
+ self._frame.PushEventHandler(self)
+
+ # if the owner is going to manage an MDI parent frame,
+ # we need to add the MDI client window as the default
+ # center pane
+
+ if isinstance(self._frame, wx.MDIParentFrame):
+ mdi_frame = self._frame
+ client_window = mdi_frame.GetClientWindow()
+
+ if not client_window:
+ raise Exception("Client window is None!")
+
+ self.AddPane(client_window, AuiPaneInfo().Name("mdiclient").
+ CenterPane().PaneBorder(False))
+
+ elif isinstance(self._frame, tabmdi.AuiMDIParentFrame):
+
+ mdi_frame = self._frame
+ client_window = mdi_frame.GetClientWindow()
+
+ if not client_window:
+ raise Exception("Client window is None!")
+
+ self.AddPane(client_window, AuiPaneInfo().Name("mdiclient").
+ CenterPane().PaneBorder(False))
+
+
+ def GetManagedWindow(self):
+ """ Returns the window being managed by :class:`AuiManager`. """
+
+ return self._frame
+
+
+ def SetFrame(self, managed_window):
+ """
+ Called to specify the frame or window which is to be managed by :class:`AuiManager`.
+ Frame management is not restricted to just frames. Child windows or custom
+ controls are also allowed.
+
+ :param Window `managed_window`: specifies the window which should be managed by
+ the AUI manager.
+
+ .. deprecated:: 0.6
+ This method is now deprecated, use :meth:`SetManagedWindow` instead.
+ """
+
+ DeprecationWarning("This method is deprecated, use SetManagedWindow instead.")
+ return self.SetManagedWindow(managed_window)
+
+
+ def GetFrame(self):
+ """
+ Returns the window being managed by :class:`AuiManager`.
+
+ .. deprecated:: 0.6
+ This method is now deprecated, use :meth:`GetManagedWindow` instead.
+ """
+
+ DeprecationWarning("This method is deprecated, use GetManagedWindow instead.")
+ return self._frame
+
+
+ def CreateGuideWindows(self):
+ """ Creates the VS2005 HUD guide windows. """
+
+ self.DestroyGuideWindows()
+
+ self._guides.append(AuiDockingGuideInfo().Left().
+ Host(AuiSingleDockingGuide(self._frame, wx.LEFT)))
+ self._guides.append(AuiDockingGuideInfo().Top().
+ Host(AuiSingleDockingGuide(self._frame, wx.TOP)))
+ self._guides.append(AuiDockingGuideInfo().Right().
+ Host(AuiSingleDockingGuide(self._frame, wx.RIGHT)))
+ self._guides.append(AuiDockingGuideInfo().Bottom().
+ Host(AuiSingleDockingGuide(self._frame, wx.BOTTOM)))
+ self._guides.append(AuiDockingGuideInfo().Centre().
+ Host(AuiCenterDockingGuide(self._frame)))
+
+
+ def DestroyGuideWindows(self):
+ """ Destroys the VS2005 HUD guide windows. """
+
+ for guide in self._guides:
+ if guide.host:
+ guide.host.Destroy()
+
+ self._guides = []
+
+
+ def CreateHintWindow(self):
+ """ Creates the standard wxAUI hint window. """
+
+ self.DestroyHintWindow()
+
+ self._hint_window = AuiDockingHintWindow(self._frame)
+ self._hint_window.SetBlindMode(self._agwFlags)
+
+
+ def DestroyHintWindow(self):
+ """ Destroys the standard wxAUI hint window. """
+
+ if self._hint_window:
+
+ self._hint_window.Destroy()
+ self._hint_window = None
+
+
+ def UnInit(self):
+ """
+ Uninitializes the framework and should be called before a managed frame or
+ window is destroyed. :meth:`UnInit` is usually called in the managed :class:`Frame` / :class:`Window`
+ destructor.
+
+ It is necessary to call this function before the managed frame or window is
+ destroyed, otherwise the manager cannot remove its custom event handlers
+ from a window.
+ """
+
+ if not self._frame:
+ return
+
+ for klass in [self._frame] + list(self._frame.GetChildren()):
+ handler = klass.GetEventHandler()
+ if klass is not handler:
+ if isinstance(handler, AuiManager):
+ klass.RemoveEventHandler(handler)
+
+
+ def OnDestroy(self, event) :
+
+ if self._frame == event.GetEventObject():
+ self.UnInit();
+
+
+ def GetArtProvider(self):
+ """ Returns the current art provider being used. """
+
+ return self._art
+
+
+ def ProcessMgrEvent(self, event):
+ """
+ Process the AUI events sent to the manager.
+
+ :param `event`: the event to process, an instance of :class:`AuiManagerEvent`.
+ """
+
+ # first, give the owner frame a chance to override
+ if self._frame:
+ if self._frame.GetEventHandler().ProcessEvent(event):
+ return
+
+ self.ProcessEvent(event)
+
+
+ def FireEvent(self, evtType, pane, canVeto=False):
+ """
+ Fires one of the ``EVT_AUI_PANE_FLOATED`` / ``FLOATING`` / ``DOCKING`` / ``DOCKED`` / ``ACTIVATED`` event.
+
+ :param integer `evtType`: one of the aforementioned events;
+ :param `pane`: the :class:`AuiPaneInfo` instance associated to this event;
+ :param bool `canVeto`: whether the event can be vetoed or not.
+ """
+
+ event = AuiManagerEvent(evtType)
+ event.SetPane(pane)
+ event.SetCanVeto(canVeto)
+ self.ProcessMgrEvent(event)
+
+ return event
+
+
+ def CanUseModernDockArt(self):
+ """
+ Returns whether :class:`dockart` can be used (Windows XP / Vista / 7 only,
+ requires Mark Hammonds's `pywin32 <http://sourceforge.net/projects/pywin32/>`_ package).
+ """
+
+ if not _winxptheme:
+ return False
+
+ # Get the size of a small close button (themed)
+ hwnd = self._frame.GetHandle()
+ hTheme = winxptheme.OpenThemeData(hwnd, "Window")
+
+ if not hTheme:
+ return False
+
+ return True
+
+
+ def SetArtProvider(self, art_provider):
+ """
+ Instructs :class:`AuiManager` to use art provider specified by the parameter
+ `art_provider` for all drawing calls. This allows plugable look-and-feel
+ features.
+
+ :param `art_provider`: a AUI dock art provider.
+
+ :note: The previous art provider object, if any, will be deleted by :class:`AuiManager`.
+ """
+
+ # delete the last art provider, if any
+ del self._art
+
+ # assign the new art provider
+ self._art = art_provider
+
+ for pane in self.GetAllPanes():
+ if pane.IsFloating() and pane.frame:
+ pane.frame._mgr.SetArtProvider(art_provider)
+ pane.frame._mgr.Update()
+
+
+ def AddPane(self, window, arg1=None, arg2=None, target=None):
+ """
+ Tells the frame manager to start managing a child window. There
+ are four versions of this function. The first verison allows the full spectrum
+ of pane parameter possibilities (:meth:`AddPane1`). The second version is used for
+ simpler user interfaces which do not require as much configuration (:meth:`AddPane2`).
+ The :meth:`AddPane3` version allows a drop position to be specified, which will determine
+ where the pane will be added. The :meth:`AddPane4` version allows to turn the target
+ :class:`AuiPaneInfo` pane into a notebook and the added pane into a page.
+
+ In your code, simply call :meth:`AddPane`.
+
+ :param Window `window`: the child window to manage;
+ :param `arg1`: a :class:`AuiPaneInfo` or an integer value (direction);
+ :param `arg2`: a :class:`AuiPaneInfo` or a :class:`Point` (drop position);
+ :param `target`: a :class:`AuiPaneInfo` to be turned into a notebook
+ and new pane added to it as a page. (additionally, target can be any pane in
+ an existing notebook)
+ """
+
+ if target in self._panes:
+ return self.AddPane4(window, arg1, target)
+
+ if type(arg1) == type(1):
+ # This Is Addpane2
+ if arg1 is None:
+ arg1 = wx.LEFT
+ if arg2 is None:
+ arg2 = ""
+ return self.AddPane2(window, arg1, arg2)
+ else:
+ if isinstance(arg2, wx.Point):
+ return self.AddPane3(window, arg1, arg2)
+ else:
+ return self.AddPane1(window, arg1)
+
+
+ def AddPane1(self, window, pane_info):
+ """ See comments on :meth:`AddPane`. """
+
+ # check if the pane has a valid window
+ if not window:
+ return False
+
+ # check if the pane already exists
+ if self.GetPane(pane_info.window).IsOk():
+ return False
+
+ # check if the pane name already exists, this could reveal a
+ # bug in the library user's application
+ already_exists = False
+ if pane_info.name != "" and self.GetPane(pane_info.name).IsOk():
+ warnings.warn("A pane with the name '%s' already exists in the manager!"%pane_info.name)
+ already_exists = True
+
+ # if the new pane is docked then we should undo maximize
+ if pane_info.IsDocked():
+ self.RestoreMaximizedPane()
+
+ self._panes.append(pane_info)
+ pinfo = self._panes[-1]
+
+ # set the pane window
+ pinfo.window = window
+
+ # if the pane's name identifier is blank, create a random string
+ if pinfo.name == "" or already_exists:
+ pinfo.name = ("%s%08x%08x%08x")%(pinfo.window.GetName(), time.time(),
+ time.clock(), len(self._panes))
+
+ # set initial proportion (if not already set)
+ if pinfo.dock_proportion == 0:
+ pinfo.dock_proportion = 100000
+
+ floating = isinstance(self._frame, AuiFloatingFrame)
+
+ pinfo.buttons = []
+
+ if not floating and pinfo.HasMinimizeButton():
+ button = AuiPaneButton(AUI_BUTTON_MINIMIZE)
+ pinfo.buttons.append(button)
+
+ if not floating and pinfo.HasMaximizeButton():
+ button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE)
+ pinfo.buttons.append(button)
+
+ if not floating and pinfo.HasPinButton():
+ button = AuiPaneButton(AUI_BUTTON_PIN)
+ pinfo.buttons.append(button)
+
+ if pinfo.HasCloseButton():
+ button = AuiPaneButton(AUI_BUTTON_CLOSE)
+ pinfo.buttons.append(button)
+
+ if pinfo.HasGripper():
+ if isinstance(pinfo.window, auibar.AuiToolBar):
+ # prevent duplicate gripper -- both AuiManager and AuiToolBar
+ # have a gripper control. The toolbar's built-in gripper
+ # meshes better with the look and feel of the control than ours,
+ # so turn AuiManager's gripper off, and the toolbar's on.
+
+ tb = pinfo.window
+ pinfo.SetFlag(AuiPaneInfo.optionGripper, False)
+ tb.SetGripperVisible(True)
+
+ if pinfo.window:
+ if pinfo.best_size == wx.Size(-1, -1):
+ pinfo.best_size = pinfo.window.GetClientSize()
+
+ if isinstance(pinfo.window, wx.ToolBar):
+ # GetClientSize() doesn't get the best size for
+ # a toolbar under some newer versions of wxWidgets,
+ # so use GetBestSize()
+ pinfo.best_size = pinfo.window.GetBestSize()
+
+ # this is needed for Win2000 to correctly fill toolbar backround
+ # it should probably be repeated once system colour change happens
+ if wx.Platform == "__WXMSW__" and pinfo.window.UseBgCol():
+ pinfo.window.SetBackgroundColour(self.GetArtProvider().GetColour(AUI_DOCKART_BACKGROUND_COLOUR))
+
+ if pinfo.min_size != wx.Size(-1, -1):
+ if pinfo.best_size.x < pinfo.min_size.x:
+ pinfo.best_size.x = pinfo.min_size.x
+ if pinfo.best_size.y < pinfo.min_size.y:
+ pinfo.best_size.y = pinfo.min_size.y
+
+ self._panes[-1] = pinfo
+ if isinstance(window, auibar.AuiToolBar):
+ window.SetAuiManager(self)
+
+ return True
+
+
+ def AddPane2(self, window, direction, caption):
+ """ See comments on :meth:`AddPane`. """
+
+ pinfo = AuiPaneInfo()
+ pinfo.Caption(caption)
+
+ if direction == wx.TOP:
+ pinfo.Top()
+ elif direction == wx.BOTTOM:
+ pinfo.Bottom()
+ elif direction == wx.LEFT:
+ pinfo.Left()
+ elif direction == wx.RIGHT:
+ pinfo.Right()
+ elif direction == wx.CENTER:
+ pinfo.CenterPane()
+
+ return self.AddPane(window, pinfo)
+
+
+ def AddPane3(self, window, pane_info, drop_pos):
+ """ See comments on :meth:`AddPane`. """
+
+ if not self.AddPane(window, pane_info):
+ return False
+
+ pane = self.GetPane(window)
+ indx = self._panes.index(pane)
+
+ ret, pane = self.DoDrop(self._docks, self._panes, pane, drop_pos, wx.Point(0, 0))
+ self._panes[indx] = pane
+
+ return True
+
+
+ def AddPane4(self, window, pane_info, target):
+ """ See comments on :meth:`AddPane`. """
+
+ if not self.AddPane(window, pane_info):
+ return False
+
+ paneInfo = self.GetPane(window)
+
+ if not paneInfo.IsNotebookDockable():
+ return self.AddPane1(window, pane_info)
+ if not target.IsNotebookDockable() and not target.IsNotebookControl():
+ return self.AddPane1(window, pane_info)
+
+ if not target.HasNotebook():
+ self.CreateNotebookBase(self._panes, target)
+
+ # Add new item to notebook
+ paneInfo.NotebookPage(target.notebook_id)
+
+ # we also want to remove our captions sometimes
+ self.RemoveAutoNBCaption(paneInfo)
+ self.UpdateNotebook()
+
+ return True
+
+
+ def InsertPane(self, window, pane_info, insert_level=AUI_INSERT_PANE):
+ """
+ This method is used to insert either a previously unmanaged pane window
+ into the frame manager, or to insert a currently managed pane somewhere else.
+ :meth:`InsertPane` will push all panes, rows, or docks aside and insert the window
+ into the position specified by `pane_info`.
+
+ Because `pane_info` can specify either a pane, dock row, or dock layer, the
+ `insert_level` parameter is used to disambiguate this. The parameter `insert_level`
+ can take a value of ``AUI_INSERT_PANE``, ``AUI_INSERT_ROW`` or ``AUI_INSERT_DOCK``.
+
+ :param Window `window`: the window to be inserted and managed;
+ :param `pane_info`: the insert location for the new window;
+ :param integer `insert_level`: the insertion level of the new pane.
+ """
+
+ if not window:
+ raise Exception("Invalid window passed to InsertPane.")
+
+ # shift the panes around, depending on the insert level
+ if insert_level == AUI_INSERT_PANE:
+ self._panes = DoInsertPane(self._panes, pane_info.dock_direction,
+ pane_info.dock_layer, pane_info.dock_row,
+ pane_info.dock_pos)
+
+ elif insert_level == AUI_INSERT_ROW:
+ self._panes = DoInsertDockRow(self._panes, pane_info.dock_direction,
+ pane_info.dock_layer, pane_info.dock_row)
+
+ elif insert_level == AUI_INSERT_DOCK:
+ self._panes = DoInsertDockLayer(self._panes, pane_info.dock_direction,
+ pane_info.dock_layer)
+
+ # if the window already exists, we are basically just moving/inserting the
+ # existing window. If it doesn't exist, we need to add it and insert it
+ existing_pane = self.GetPane(window)
+ indx = self._panes.index(existing_pane)
+
+ if not existing_pane.IsOk():
+
+ return self.AddPane(window, pane_info)
+
+ else:
+
+ if pane_info.IsFloating():
+ existing_pane.Float()
+ if pane_info.floating_pos != wx.Point(-1, -1):
+ existing_pane.FloatingPosition(pane_info.floating_pos)
+ if pane_info.floating_size != wx.Size(-1, -1):
+ existing_pane.FloatingSize(pane_info.floating_size)
+ else:
+ # if the new pane is docked then we should undo maximize
+ self.RestoreMaximizedPane()
+
+ existing_pane.Direction(pane_info.dock_direction)
+ existing_pane.Layer(pane_info.dock_layer)
+ existing_pane.Row(pane_info.dock_row)
+ existing_pane.Position(pane_info.dock_pos)
+
+ self._panes[indx] = existing_pane
+
+ return True
+
+
+ def DetachPane(self, window):
+ """
+ Tells the :class:`AuiManager` to stop managing the pane specified
+ by `window`. The window, if in a floated frame, is reparented to the frame
+ managed by :class:`AuiManager`.
+
+ :param Window `window`: the window to be un-managed.
+ """
+
+ for p in self._panes:
+ if p.window == window:
+ if p.frame:
+ # we have a floating frame which is being detached. We need to
+ # reparent it to self._frame and destroy the floating frame
+
+ # reduce flicker
+ p.window.SetSize((1, 1))
+ if p.frame.IsShown():
+ p.frame.Show(False)
+
+ if self._action_window == p.frame:
+ self._action_window = None
+
+ # reparent to self._frame and destroy the pane
+ p.window.Reparent(self._frame)
+ p.frame.SetSizer(None)
+ p.frame.Destroy()
+ p.frame = None
+
+ elif p.IsNotebookPage():
+ notebook = self._notebooks[p.notebook_id]
+ id = notebook.GetPageIndex(p.window)
+ notebook.RemovePage(id)
+ p.window.Reparent(self._frame)
+
+ # make sure there are no references to this pane in our uiparts,
+ # just in case the caller doesn't call Update() immediately after
+ # the DetachPane() call. This prevets obscure crashes which would
+ # happen at window repaint if the caller forgets to call Update()
+ counter = 0
+ for pi in xrange(len(self._uiparts)):
+ part = self._uiparts[counter]
+ if part.pane == p:
+ self._uiparts.pop(counter)
+ counter -= 1
+
+ counter += 1
+
+ self._panes.remove(p)
+ return True
+
+ return False
+
+
+ def ClosePane(self, pane_info):
+ """
+ Destroys or hides the pane depending on its flags.
+
+ :param `pane_info`: a :class:`AuiPaneInfo` instance.
+ """
+
+ # if we were maximized, restore
+ if pane_info.IsMaximized():
+ self.RestorePane(pane_info)
+
+ if pane_info.frame:
+ if self._agwFlags & AUI_MGR_ANIMATE_FRAMES:
+ pane_info.frame.FadeOut()
+
+ # first, hide the window
+ if pane_info.window and pane_info.window.IsShown():
+ pane_info.window.Show(False)
+
+ # make sure that we are the parent of this window
+ if pane_info.window and pane_info.window.GetParent() != self._frame:
+ pane_info.window.Reparent(self._frame)
+
+ # if we have a frame, destroy it
+ if pane_info.frame:
+ pane_info.frame.Destroy()
+ pane_info.frame = None
+
+ elif pane_info.IsNotebookPage():
+ # if we are a notebook page, remove ourselves...
+ # the code would index out of bounds
+ # if the last page of a sub-notebook was closed
+ # because the notebook would be deleted, before this
+ # code is executed.
+ # This code just prevents an out-of bounds error.
+ if self._notebooks:
+ nid = pane_info.notebook_id
+ if nid >= 0 and nid < len(self._notebooks):
+ notebook = self._notebooks[nid]
+ page_idx = notebook.GetPageIndex(pane_info.window)
+ if page_idx >= 0:
+ notebook.RemovePage(page_idx)
+
+ # now we need to either destroy or hide the pane
+ to_destroy = 0
+ if pane_info.IsDestroyOnClose():
+ to_destroy = pane_info.window
+ self.DetachPane(to_destroy)
+ else:
+ if isinstance(pane_info.window, auibar.AuiToolBar) and pane_info.IsFloating():
+ tb = pane_info.window
+ if pane_info.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT]:
+ tb.SetAGWWindowStyleFlag(tb.GetAGWWindowStyleFlag() | AUI_TB_VERTICAL)
+
+ pane_info.Dock().Hide()
+
+ if pane_info.IsNotebookControl():
+
+ notebook = self._notebooks[pane_info.notebook_id]
+ while notebook.GetPageCount():
+ window = notebook.GetPage(0)
+ notebook.RemovePage(0)
+ info = self.GetPane(window)
+ if info.IsOk():
+ info.notebook_id = -1
+ info.dock_direction = AUI_DOCK_NONE
+ # Note: this could change our paneInfo reference ...
+ self.ClosePane(info)
+
+ if to_destroy:
+ to_destroy.Destroy()
+
+
+ def MaximizePane(self, pane_info, savesizes=True):
+ """
+ Maximizes the input pane.
+
+ :param `pane_info`: a :class:`AuiPaneInfo` instance.
+ :param bool `savesizes`: whether to save previous dock sizes.
+ """
+
+ if savesizes:
+ self.SavePreviousDockSizes(pane_info)
+
+ for p in self._panes:
+
+ # save hidden state
+ p.SetFlag(p.savedHiddenState, p.HasFlag(p.optionHidden))
+
+ if not p.IsToolbar() and not p.IsFloating():
+ p.Restore()
+
+ # hide the pane, because only the newly
+ # maximized pane should show
+ p.Hide()
+
+ pane_info.previousDockPos = pane_info.dock_pos
+
+ # mark ourselves maximized
+ pane_info.Maximize()
+ pane_info.Show()
+ self._has_maximized = True
+
+ # last, show the window
+ if pane_info.window and not pane_info.window.IsShown():
+ pane_info.window.Show(True)
+
+
+ def SavePreviousDockSizes(self, pane_info):
+ """
+ Stores the previous dock sizes, to be used in a "restore" action later.
+
+ :param `pane_info`: a :class:`AuiPaneInfo` instance.
+ """
+
+ for d in self._docks:
+ if not d.toolbar:
+ for p in d.panes:
+ p.previousDockSize = d.size
+ if pane_info is not p:
+ p.SetFlag(p.needsRestore, True)
+
+
+ def RestorePane(self, pane_info):
+ """
+ Restores the input pane from a previous maximized or minimized state.
+
+ :param `pane_info`: a :class:`AuiPaneInfo` instance.
+ """
+
+ # restore all the panes
+ for p in self._panes:
+ if not p.IsToolbar():
+ p.SetFlag(p.optionHidden, p.HasFlag(p.savedHiddenState))
+
+ pane_info.SetFlag(pane_info.needsRestore, True)
+
+ # mark ourselves non-maximized
+ pane_info.Restore()
+ self._has_maximized = False
+ self._has_minimized = False
+
+ # last, show the window
+ if pane_info.window and not pane_info.window.IsShown():
+ pane_info.window.Show(True)
+
+
+ def RestoreMaximizedPane(self):
+ """ Restores the current maximized pane (if any). """
+
+ # restore all the panes
+ for p in self._panes:
+ if p.IsMaximized():
+ self.RestorePane(p)
+ break
+
+
+ def ActivatePane(self, window):
+ """
+ Activates the pane to which `window` is associated.
+
+ :param `window`: a :class:`Window` derived window.
+ """
+
+ if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE:
+ while window:
+ ret, self._panes = SetActivePane(self._panes, window)
+ if ret:
+ break
+
+ window = window.GetParent()
+
+ self.RefreshCaptions()
+ self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, window, canVeto=False)
+
+
+ def CreateNotebook(self):
+ """
+ Creates an automatic :class:`~lib.agw.aui.auibook.AuiNotebook` when a pane is docked on
+ top of another pane.
+ """
+
+ notebook = auibook.AuiNotebook(self._frame, -1, wx.Point(0, 0), wx.Size(0, 0), agwStyle=self._autoNBStyle)
+
+ # This is so we can get the tab-drag event.
+ notebook.GetAuiManager().SetMasterManager(self)
+ notebook.SetArtProvider(self._autoNBTabArt.Clone())
+ self._notebooks.append(notebook)
+
+ return notebook
+
+
+ def SetAutoNotebookTabArt(self, art):
+ """
+ Sets the default tab art provider for automatic notebooks.
+
+ :param `art`: a tab art provider.
+ """
+
+ for nb in self._notebooks:
+ nb.SetArtProvider(art.Clone())
+ nb.Refresh()
+ nb.Update()
+
+ self._autoNBTabArt = art
+
+
+ def GetAutoNotebookTabArt(self):
+ """ Returns the default tab art provider for automatic notebooks. """
+
+ return self._autoNBTabArt
+
+
+ def SetAutoNotebookStyle(self, agwStyle):
+ """
+ Sets the default AGW-specific window style for automatic notebooks.
+
+ :param integer `agwStyle`: the underlying :class:`~lib.agw.aui.auibook.AuiNotebook` window style.
+ This can be a combination of the following bits:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook
+ ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet.
+ ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet.
+ ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook
+ ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab
+ ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging
+ ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control
+ ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width
+ ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed
+ ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available
+ ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar
+ ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab
+ ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs
+ ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close :class:`~lib.agw.aui.auibook.AuiNotebook` tabs by mouse middle button click
+ ``AUI_NB_SUB_NOTEBOOK`` This style is used by :class:`AuiManager` to create automatic AuiNotebooks
+ ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present
+ ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
+ ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items
+ ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser)
+ ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less
+ full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages
+ ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default)
+ ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs
+ ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle
+ ==================================== ==================================
+
+ """
+
+ for nb in self._notebooks:
+ nb.SetAGWWindowStyleFlag(agwStyle)
+ nb.Refresh()
+ nb.Update()
+
+ self._autoNBStyle = agwStyle
+
+
+ def GetAutoNotebookStyle(self):
+ """
+ Returns the default AGW-specific window style for automatic notebooks.
+
+ :see: :meth:`SetAutoNotebookStyle` method for a list of possible styles.
+ """
+
+ return self._autoNBStyle
+
+
+ def SavePaneInfo(self, pane):
+ """
+ This method is similar to :meth:`SavePerspective`, with the exception
+ that it only saves information about a single pane. It is used in
+ combination with :meth:`LoadPaneInfo`.
+
+ :param `pane`: a :class:`AuiPaneInfo` instance to save.
+ """
+
+ result = "name=" + EscapeDelimiters(pane.name) + ";"
+ result += "caption=" + EscapeDelimiters(pane.caption) + ";"
+
+ result += "state=%u;"%pane.state
+ result += "dir=%d;"%pane.dock_direction
+ result += "layer=%d;"%pane.dock_layer
+ result += "row=%d;"%pane.dock_row
+ result += "pos=%d;"%pane.dock_pos
+ result += "prop=%d;"%pane.dock_proportion
+ result += "bestw=%d;"%pane.best_size.x
+ result += "besth=%d;"%pane.best_size.y
+ result += "minw=%d;"%pane.min_size.x
+ result += "minh=%d;"%pane.min_size.y
+ result += "maxw=%d;"%pane.max_size.x
+ result += "maxh=%d;"%pane.max_size.y
+ result += "floatx=%d;"%pane.floating_pos.x
+ result += "floaty=%d;"%pane.floating_pos.y
+ result += "floatw=%d;"%pane.floating_size.x
+ result += "floath=%d;"%pane.floating_size.y
+ result += "notebookid=%d;"%pane.notebook_id
+ result += "transparent=%d"%pane.transparent
+
+ return result
+
+
+ def LoadPaneInfo(self, pane_part, pane):
+ """
+ This method is similar to to :meth:`LoadPerspective`, with the exception that
+ it only loads information about a single pane. It is used in combination
+ with :meth:`SavePaneInfo`.
+
+ :param string `pane_part`: the string to analyze;
+ :param `pane`: the :class:`AuiPaneInfo` structure in which to load `pane_part`.
+ """
+
+ # replace escaped characters so we can
+ # split up the string easily
+ pane_part = pane_part.replace("\\|", "\a")
+ pane_part = pane_part.replace("\\;", "\b")
+
+ options = pane_part.split(";")
+ for items in options:
+
+ val_name, value = items.split("=")
+ val_name = val_name.strip()
+
+ if val_name == "name":
+ pane.name = value
+ elif val_name == "caption":
+ pane.caption = value
+ elif val_name == "state":
+ pane.state = int(value)
+ elif val_name == "dir":
+ pane.dock_direction = int(value)
+ elif val_name == "layer":
+ pane.dock_layer = int(value)
+ elif val_name == "row":
+ pane.dock_row = int(value)
+ elif val_name == "pos":
+ pane.dock_pos = int(value)
+ elif val_name == "prop":
+ pane.dock_proportion = int(value)
+ elif val_name == "bestw":
+ pane.best_size.x = int(value)
+ elif val_name == "besth":
+ pane.best_size.y = int(value)
+ pane.best_size = wx.Size(pane.best_size.x, pane.best_size.y)
+ elif val_name == "minw":
+ pane.min_size.x = int(value)
+ elif val_name == "minh":
+ pane.min_size.y = int(value)
+ pane.min_size = wx.Size(pane.min_size.x, pane.min_size.y)
+ elif val_name == "maxw":
+ pane.max_size.x = int(value)
+ elif val_name == "maxh":
+ pane.max_size.y = int(value)
+ pane.max_size = wx.Size(pane.max_size.x, pane.max_size.y)
+ elif val_name == "floatx":
+ pane.floating_pos.x = int(value)
+ elif val_name == "floaty":
+ pane.floating_pos.y = int(value)
+ pane.floating_pos = wx.Point(pane.floating_pos.x, pane.floating_pos.y)
+ elif val_name == "floatw":
+ pane.floating_size.x = int(value)
+ elif val_name == "floath":
+ pane.floating_size.y = int(value)
+ pane.floating_size = wx.Size(pane.floating_size.x, pane.floating_size.y)
+ elif val_name == "notebookid":
+ pane.notebook_id = int(value)
+ elif val_name == "transparent":
+ pane.transparent = int(value)
+ else:
+ raise Exception("Bad perspective string")
+
+ # replace escaped characters so we can
+ # split up the string easily
+ pane.name = pane.name.replace("\a", "|")
+ pane.name = pane.name.replace("\b", ";")
+ pane.caption = pane.caption.replace("\a", "|")
+ pane.caption = pane.caption.replace("\b", ";")
+ pane_part = pane_part.replace("\a", "|")
+ pane_part = pane_part.replace("\b", ";")
+
+ return pane
+
+
+ def SavePerspective(self):
+ """
+ Saves the entire user interface layout into an encoded string, which can then
+ be stored by the application (probably using :class:`Config`).
+
+ When a perspective is restored using :meth:`LoadPerspective`, the entire user
+ interface will return to the state it was when the perspective was saved.
+ """
+
+ result = "layout2|"
+
+ for pane in self._panes:
+ result += self.SavePaneInfo(pane) + "|"
+
+ for dock in self._docks:
+ result = result + ("dock_size(%d,%d,%d)=%d|")%(dock.dock_direction,
+ dock.dock_layer,
+ dock.dock_row,
+ dock.size)
+ return result
+
+
+ def LoadPerspective(self, layout, update=True, restorecaption=False):
+ """
+ Loads a layout which was saved with :meth:`SavePerspective`.
+
+ If the `update` flag parameter is ``True``, :meth:`Update` will be
+ automatically invoked, thus realizing the saved perspective on screen.
+
+ :param string `layout`: a string which contains a saved AUI layout;
+ :param bool `update`: whether to update immediately the window or not;
+ :param bool `restorecaption`: ``False``, restore from persist storage,
+ otherwise use the caption defined in code.
+ """
+
+ input = layout
+
+ # check layout string version
+ # 'layout1' = wxAUI 0.9.0 - wxAUI 0.9.2
+ # 'layout2' = wxAUI 0.9.2 (wxWidgets 2.8)
+ index = input.find("|")
+ part = input[0:index].strip()
+ input = input[index+1:]
+
+ if part != "layout2":
+ return False
+
+ # mark all panes currently managed as docked and hidden
+ saveCapt = {} # see restorecaption param
+ for pane in self._panes:
+ pane.Dock().Hide()
+ saveCapt[pane.name] = pane.caption
+
+ # clear out the dock array; this will be reconstructed
+ self._docks = []
+
+ # replace escaped characters so we can
+ # split up the string easily
+ input = input.replace("\\|", "\a")
+ input = input.replace("\\;", "\b")
+
+ while 1:
+
+ pane = AuiPaneInfo()
+ index = input.find("|")
+ pane_part = input[0:index].strip()
+ input = input[index+1:]
+
+ # if the string is empty, we're done parsing
+ if pane_part == "":
+ break
+
+ if pane_part[0:9] == "dock_size":
+ index = pane_part.find("=")
+ val_name = pane_part[0:index]
+ value = pane_part[index+1:]
+
+ index = val_name.find("(")
+ piece = val_name[index+1:]
+ index = piece.find(")")
+ piece = piece[0:index]
+
+ vals = piece.split(",")
+ dir = int(vals[0])
+ layer = int(vals[1])
+ row = int(vals[2])
+ size = int(value)
+
+ dock = AuiDockInfo()
+ dock.dock_direction = dir
+ dock.dock_layer = layer
+ dock.dock_row = row
+ dock.size = size
+ self._docks.append(dock)
+
+ continue
+
+ # Undo our escaping as LoadPaneInfo needs to take an unescaped
+ # name so it can be called by external callers
+ pane_part = pane_part.replace("\a", "|")
+ pane_part = pane_part.replace("\b", ";")
+
+ pane = self.LoadPaneInfo(pane_part, pane)
+
+ p = self.GetPane(pane.name)
+ # restore pane caption from code
+ if restorecaption:
+ if pane.name in saveCapt:
+ pane.Caption(saveCapt[pane.name])
+
+ if not p.IsOk():
+ if pane.IsNotebookControl():
+ # notebook controls - auto add...
+ self._panes.append(pane)
+ indx = self._panes.index(pane)
+ else:
+ # the pane window couldn't be found
+ # in the existing layout -- skip it
+ continue
+
+ else:
+ indx = self._panes.index(p)
+ pane.window = p.window
+ pane.frame = p.frame
+ pane.buttons = p.buttons
+ self._panes[indx] = pane
+
+ if isinstance(pane.window, auibar.AuiToolBar) and (pane.IsFloatable() or pane.IsDockable()):
+ pane.window.SetGripperVisible(True)
+
+ for p in self._panes:
+ if p.IsMinimized():
+ self.MinimizePane(p, False)
+
+ if update:
+ self.Update()
+
+ return True
+
+
+ def GetPanePositionsAndSizes(self, dock):
+ """
+ Returns all the panes positions and sizes in a dock.
+
+ :param `dock`: a :class:`AuiDockInfo` instance.
+ """
+
+ caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
+ pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
+ gripper_size = self._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE)
+
+ positions = []
+ sizes = []
+
+ action_pane = -1
+ pane_count = len(dock.panes)
+
+ # find the pane marked as our action pane
+ for pane_i in xrange(pane_count):
+ pane = dock.panes[pane_i]
+ if pane.HasFlag(AuiPaneInfo.actionPane):
+ if action_pane != -1:
+ raise Exception("Too many action panes!")
+ action_pane = pane_i
+
+ # set up each panes default position, and
+ # determine the size (width or height, depending
+ # on the dock's orientation) of each pane
+ for pane in dock.panes:
+ positions.append(pane.dock_pos)
+ size = 0
+
+ if pane.HasBorder():
+ size += pane_border_size*2
+
+ if dock.IsHorizontal():
+ if pane.HasGripper() and not pane.HasGripperTop():
+ size += gripper_size
+
+ if pane.HasCaptionLeft():
+ size += caption_size
+
+ size += pane.best_size.x
+
+ else:
+ if pane.HasGripper() and pane.HasGripperTop():
+ size += gripper_size
+
+ if pane.HasCaption() and not pane.HasCaptionLeft():
+ size += caption_size
+
+ size += pane.best_size.y
+
+ sizes.append(size)
+
+ # if there is no action pane, just return the default
+ # positions (as specified in pane.pane_pos)
+ if action_pane == -1:
+ return positions, sizes
+
+ offset = 0
+ for pane_i in xrange(action_pane-1, -1, -1):
+ amount = positions[pane_i+1] - (positions[pane_i] + sizes[pane_i])
+ if amount >= 0:
+ offset += amount
+ else:
+ positions[pane_i] -= -amount
+
+ offset += sizes[pane_i]
+
+ # if the dock mode is fixed, make sure none of the panes
+ # overlap we will bump panes that overlap
+ offset = 0
+ for pane_i in xrange(action_pane, pane_count):
+ amount = positions[pane_i] - offset
+ if amount >= 0:
+ offset += amount
+ else:
+ positions[pane_i] += -amount
+
+ offset += sizes[pane_i]
+
+ return positions, sizes
+
+
+ def LayoutAddPane(self, cont, dock, pane, uiparts, spacer_only):
+ """
+ Adds a pane into the existing layout (in an existing dock).
+
+ :param `cont`: a :class:`Sizer` object;
+ :param `dock`: the :class:`AuiDockInfo` structure in which to add the pane;
+ :param `pane`: the :class:`AuiPaneInfo` instance to add to the dock;
+ :param `uiparts`: a list of UI parts in the interface;
+ :param bool `spacer_only`: whether to add a simple spacer or a real window.
+ """
+
+ sizer_item = wx.SizerItem()
+ caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
+ gripper_size = self._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE)
+ pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
+ pane_button_size = self._art.GetMetric(AUI_DOCKART_PANE_BUTTON_SIZE)
+
+ # find out the orientation of the item (orientation for panes
+ # is the same as the dock's orientation)
+
+ if dock.IsHorizontal():
+ orientation = wx.HORIZONTAL
+ else:
+ orientation = wx.VERTICAL
+
+ # this variable will store the proportion
+ # value that the pane will receive
+ pane_proportion = pane.dock_proportion
+
+ horz_pane_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ vert_pane_sizer = wx.BoxSizer(wx.VERTICAL)
+
+ if pane.HasGripper():
+
+ part = AuiDockUIPart()
+ if pane.HasGripperTop():
+ sizer_item = vert_pane_sizer.Add((1, gripper_size), 0, wx.EXPAND)
+ else:
+ sizer_item = horz_pane_sizer.Add((gripper_size, 1), 0, wx.EXPAND)
+
+ part.type = AuiDockUIPart.typeGripper
+ part.dock = dock
+ part.pane = pane
+ part.button = None
+ part.orientation = orientation
+ part.cont_sizer = horz_pane_sizer
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+
+ button_count = len(pane.buttons)
+ button_width_total = button_count*pane_button_size
+ if button_count >= 1:
+ button_width_total += 3
+
+ caption, captionLeft = pane.HasCaption(), pane.HasCaptionLeft()
+ button_count = len(pane.buttons)
+
+ if captionLeft:
+ caption_sizer = wx.BoxSizer(wx.VERTICAL)
+
+ # add pane buttons to the caption
+ dummy_parts = []
+ for btn_id in xrange(len(pane.buttons)-1, -1, -1):
+ sizer_item = caption_sizer.Add((caption_size, pane_button_size), 0, wx.EXPAND)
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typePaneButton
+ part.dock = dock
+ part.pane = pane
+ part.button = pane.buttons[btn_id]
+ part.orientation = orientation
+ part.cont_sizer = caption_sizer
+ part.sizer_item = sizer_item
+ dummy_parts.append(part)
+
+ sizer_item = caption_sizer.Add((caption_size, 1), 1, wx.EXPAND)
+ vert_pane_sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ # create the caption sizer
+ part = AuiDockUIPart()
+
+ part.type = AuiDockUIPart.typeCaption
+ part.dock = dock
+ part.pane = pane
+ part.button = None
+ part.orientation = orientation
+ part.cont_sizer = vert_pane_sizer
+ part.sizer_item = sizer_item
+ caption_part_idx = len(uiparts)
+ uiparts.append(part)
+ uiparts.extend(dummy_parts)
+
+ elif caption:
+
+ caption_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer_item = caption_sizer.Add((1, caption_size), 1, wx.EXPAND)
+
+ # create the caption sizer
+ part = AuiDockUIPart()
+
+ part.type = AuiDockUIPart.typeCaption
+ part.dock = dock
+ part.pane = pane
+ part.button = None
+ part.orientation = orientation
+ part.cont_sizer = vert_pane_sizer
+ part.sizer_item = sizer_item
+ caption_part_idx = len(uiparts)
+ uiparts.append(part)
+
+ # add pane buttons to the caption
+ for button in pane.buttons:
+ sizer_item = caption_sizer.Add((pane_button_size, caption_size), 0, wx.EXPAND)
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typePaneButton
+ part.dock = dock
+ part.pane = pane
+ part.button = button
+ part.orientation = orientation
+ part.cont_sizer = caption_sizer
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+
+ if caption or captionLeft:
+ # if we have buttons, add a little space to the right
+ # of them to ease visual crowding
+ if button_count >= 1:
+ if captionLeft:
+ caption_sizer.Add((caption_size, 3), 0, wx.EXPAND)
+ else:
+ caption_sizer.Add((3, caption_size), 0, wx.EXPAND)
+
+ # add the caption sizer
+ sizer_item = vert_pane_sizer.Add(caption_sizer, 0, wx.EXPAND)
+ uiparts[caption_part_idx].sizer_item = sizer_item
+
+ # add the pane window itself
+ if spacer_only or not pane.window:
+ sizer_item = vert_pane_sizer.Add((1, 1), 1, wx.EXPAND)
+ else:
+ sizer_item = vert_pane_sizer.Add(pane.window, 1, wx.EXPAND)
+ vert_pane_sizer.SetItemMinSize(pane.window, (1, 1))
+
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typePane
+ part.dock = dock
+ part.pane = pane
+ part.button = None
+ part.orientation = orientation
+ part.cont_sizer = vert_pane_sizer
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+
+ # determine if the pane should have a minimum size if the pane is
+ # non-resizable (fixed) then we must set a minimum size. Alternatively,
+ # if the pane.min_size is set, we must use that value as well
+
+ min_size = pane.min_size
+ if pane.IsFixed():
+ if min_size == wx.Size(-1, -1):
+ min_size = pane.best_size
+ pane_proportion = 0
+
+ if min_size != wx.Size(-1, -1):
+ vert_pane_sizer.SetItemMinSize(len(vert_pane_sizer.GetChildren())-1, (min_size.x, min_size.y))
+
+ # add the vertical/horizontal sizer (caption, pane window) to the
+ # horizontal sizer (gripper, vertical sizer)
+ horz_pane_sizer.Add(vert_pane_sizer, 1, wx.EXPAND)
+
+ # finally, add the pane sizer to the dock sizer
+ if pane.HasBorder():
+ # allowing space for the pane's border
+ sizer_item = cont.Add(horz_pane_sizer, pane_proportion,
+ wx.EXPAND | wx.ALL, pane_border_size)
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typePaneBorder
+ part.dock = dock
+ part.pane = pane
+ part.button = None
+ part.orientation = orientation
+ part.cont_sizer = cont
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+ else:
+ sizer_item = cont.Add(horz_pane_sizer, pane_proportion, wx.EXPAND)
+
+ return uiparts
+
+
+ def LayoutAddDock(self, cont, dock, uiparts, spacer_only):
+ """
+ Adds a dock into the existing layout.
+
+ :param `cont`: a :class:`Sizer` object;
+ :param `dock`: the :class:`AuiDockInfo` structure to add to the layout;
+ :param `uiparts`: a list of UI parts in the interface;
+ :param bool `spacer_only`: whether to add a simple spacer or a real window.
+ """
+
+ sizer_item = wx.SizerItem()
+ part = AuiDockUIPart()
+
+ sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
+ orientation = (dock.IsHorizontal() and [wx.HORIZONTAL] or [wx.VERTICAL])[0]
+
+ # resizable bottom and right docks have a sash before them
+ if not self._has_maximized and not dock.fixed and \
+ dock.dock_direction in [AUI_DOCK_BOTTOM, AUI_DOCK_RIGHT]:
+
+ sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND)
+
+ part.type = AuiDockUIPart.typeDockSizer
+ part.orientation = orientation
+ part.dock = dock
+ part.pane = None
+ part.button = None
+ part.cont_sizer = cont
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+
+ # create the sizer for the dock
+ dock_sizer = wx.BoxSizer(orientation)
+
+ # add each pane to the dock
+ has_maximized_pane = False
+ pane_count = len(dock.panes)
+
+ if dock.fixed:
+
+ # figure out the real pane positions we will
+ # use, without modifying the each pane's pane_pos member
+ pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock)
+
+ offset = 0
+ for pane_i in xrange(pane_count):
+
+ pane = dock.panes[pane_i]
+ pane_pos = pane_positions[pane_i]
+
+ if pane.IsMaximized():
+ has_maximized_pane = True
+
+ amount = pane_pos - offset
+ if amount > 0:
+
+ if dock.IsVertical():
+ sizer_item = dock_sizer.Add((1, amount), 0, wx.EXPAND)
+ else:
+ sizer_item = dock_sizer.Add((amount, 1), 0, wx.EXPAND)
+
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typeBackground
+ part.dock = dock
+ part.pane = None
+ part.button = None
+ part.orientation = (orientation==wx.HORIZONTAL and \
+ [wx.VERTICAL] or [wx.HORIZONTAL])[0]
+ part.cont_sizer = dock_sizer
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+
+ offset = offset + amount
+
+ uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only)
+
+ offset = offset + pane_sizes[pane_i]
+
+ # at the end add a very small stretchable background area
+ sizer_item = dock_sizer.Add((0, 0), 1, wx.EXPAND)
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typeBackground
+ part.dock = dock
+ part.pane = None
+ part.button = None
+ part.orientation = orientation
+ part.cont_sizer = dock_sizer
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+
+ else:
+
+ for pane_i in xrange(pane_count):
+
+ pane = dock.panes[pane_i]
+
+ if pane.IsMaximized():
+ has_maximized_pane = True
+
+ # if this is not the first pane being added,
+ # we need to add a pane sizer
+ if not self._has_maximized and pane_i > 0:
+ sizer_item = dock_sizer.Add((sash_size, sash_size), 0, wx.EXPAND)
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typePaneSizer
+ part.dock = dock
+ part.pane = dock.panes[pane_i-1]
+ part.button = None
+ part.orientation = (orientation==wx.HORIZONTAL and \
+ [wx.VERTICAL] or [wx.HORIZONTAL])[0]
+ part.cont_sizer = dock_sizer
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+
+ uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only)
+
+ if dock.dock_direction == AUI_DOCK_CENTER or has_maximized_pane:
+ sizer_item = cont.Add(dock_sizer, 1, wx.EXPAND)
+ else:
+ sizer_item = cont.Add(dock_sizer, 0, wx.EXPAND)
+
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typeDock
+ part.dock = dock
+ part.pane = None
+ part.button = None
+ part.orientation = orientation
+ part.cont_sizer = cont
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+
+ if dock.IsHorizontal():
+ cont.SetItemMinSize(dock_sizer, (0, dock.size))
+ else:
+ cont.SetItemMinSize(dock_sizer, (dock.size, 0))
+
+ # top and left docks have a sash after them
+ if not self._has_maximized and not dock.fixed and \
+ dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]:
+
+ sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND)
+
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typeDockSizer
+ part.dock = dock
+ part.pane = None
+ part.button = None
+ part.orientation = orientation
+ part.cont_sizer = cont
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+
+ return uiparts
+
+
+ def LayoutAll(self, panes, docks, uiparts, spacer_only=False, oncheck=True):
+ """
+ Layouts all the UI structures in the interface.
+
+ :param `panes`: a list of :class:`AuiPaneInfo` instances;
+ :param `docks`: a list of :class:`AuiDockInfo` classes;
+ :param `uiparts`: a list of UI parts in the interface;
+ :param bool `spacer_only`: whether to add a simple spacer or a real window;
+ :param bool `oncheck`: whether to store the results in a class member or not.
+ """
+
+ container = wx.BoxSizer(wx.VERTICAL)
+
+ pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
+ caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
+ cli_size = self._frame.GetClientSize()
+
+ # empty all docks out
+ for dock in docks:
+ dock.panes = []
+ if dock.fixed:
+ # always reset fixed docks' sizes, because
+ # the contained windows may have been resized
+ dock.size = 0
+
+ dock_count = len(docks)
+
+ # iterate through all known panes, filing each
+ # of them into the appropriate dock. If the
+ # pane does not exist in the dock, add it
+ for p in panes:
+
+ # don't layout hidden panes.
+ if p.IsShown():
+
+ # find any docks with the same dock direction, dock layer, and
+ # dock row as the pane we are working on
+ arr = FindDocks(docks, p.dock_direction, p.dock_layer, p.dock_row)
+
+ if arr:
+ dock = arr[0]
+
+ else:
+ # dock was not found, so we need to create a new one
+ d = AuiDockInfo()
+ d.dock_direction = p.dock_direction
+ d.dock_layer = p.dock_layer
+ d.dock_row = p.dock_row
+ docks.append(d)
+ dock = docks[-1]
+
+ if p.HasFlag(p.needsRestore) and not p.HasFlag(p.wasMaximized):
+
+ isHor = dock.IsHorizontal()
+ sashSize = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
+
+ # get the sizes of any docks that might
+ # overlap with our restored dock
+
+ # make list of widths or heights from the size in the dock rects
+ sizes = [d.rect[2:][isHor] for \
+ d in docks if d.IsOk() and \
+ (d.IsHorizontal() == isHor) and \
+ not d.toolbar and \
+ d.dock_direction != AUI_DOCK_CENTER]
+
+ frameRect = GetInternalFrameRect(self._frame, self._docks)
+
+ # set max size allowing for sashes and absolute minimum
+ maxsize = frameRect[2:][isHor] - sum(sizes) - (len(sizes)*10) - (sashSize*len(sizes))
+ dock.size = min(p.previousDockSize,maxsize)
+
+ else:
+ dock.size = 0
+
+ if p.HasFlag(p.wasMaximized):
+ self.MaximizePane(p, savesizes=False)
+ p.SetFlag(p.wasMaximized, False)
+
+ if p.HasFlag(p.needsRestore):
+ if p.previousDockPos is not None:
+ DoInsertPane(dock.panes, dock.dock_direction, dock.dock_layer, dock.dock_row, p.previousDockPos)
+ p.dock_pos = p.previousDockPos
+ p.previousDockPos = None
+ p.SetFlag(p.needsRestore, False)
+
+ if p.IsDocked():
+ # remove the pane from any existing docks except this one
+ docks = RemovePaneFromDocks(docks, p, dock)
+
+ # pane needs to be added to the dock,
+ # if it doesn't already exist
+ if not FindPaneInDock(dock, p.window):
+ dock.panes.append(p)
+ else:
+ # remove the pane from any existing docks
+ docks = RemovePaneFromDocks(docks, p)
+
+ # remove any empty docks
+ docks = [dock for dock in docks if dock.panes]
+
+ dock_count = len(docks)
+ # configure the docks further
+ for ii, dock in enumerate(docks):
+ # sort the dock pane array by the pane's
+ # dock position (dock_pos), in ascending order
+ dock.panes.sort(PaneSortFunc)
+ dock_pane_count = len(dock.panes)
+
+ # for newly created docks, set up their initial size
+ if dock.size == 0:
+ size = 0
+ for pane in dock.panes:
+ pane_size = pane.best_size
+ if pane_size == wx.Size(-1, -1):
+ pane_size = pane.min_size
+ if pane_size == wx.Size(-1, -1) and pane.window:
+ pane_size = pane.window.GetSize()
+ if dock.IsHorizontal():
+ size = max(pane_size.y, size)
+ else:
+ size = max(pane_size.x, size)
+
+ # add space for the border (two times), but only
+ # if at least one pane inside the dock has a pane border
+ for pane in dock.panes:
+ if pane.HasBorder():
+ size = size + pane_border_size*2
+ break
+
+ # if pane is on the top or bottom, add the caption height,
+ # but only if at least one pane inside the dock has a caption
+ if dock.IsHorizontal():
+ for pane in dock.panes:
+ if pane.HasCaption() and not pane.HasCaptionLeft():
+ size = size + caption_size
+ break
+ else:
+ for pane in dock.panes:
+ if pane.HasCaptionLeft() and not pane.HasCaption():
+ size = size + caption_size
+ break
+
+ # new dock's size may not be more than the dock constraint
+ # parameter specifies. See SetDockSizeConstraint()
+ max_dock_x_size = int(self._dock_constraint_x*float(cli_size.x))
+ max_dock_y_size = int(self._dock_constraint_y*float(cli_size.y))
+ if cli_size <= wx.Size(20, 20):
+ max_dock_x_size = 10000
+ max_dock_y_size = 10000
+
+ if dock.IsHorizontal():
+ size = min(size, max_dock_y_size)
+ else:
+ size = min(size, max_dock_x_size)
+
+ # absolute minimum size for a dock is 10 pixels
+ if size < 10:
+ size = 10
+
+ dock.size = size
+
+ # determine the dock's minimum size
+ plus_border = False
+ plus_caption = False
+ plus_caption_left = False
+ dock_min_size = 0
+ for pane in dock.panes:
+ if pane.min_size != wx.Size(-1, -1):
+ if pane.HasBorder():
+ plus_border = True
+ if pane.HasCaption():
+ plus_caption = True
+ if pane.HasCaptionLeft():
+ plus_caption_left = True
+ if dock.IsHorizontal():
+ if pane.min_size.y > dock_min_size:
+ dock_min_size = pane.min_size.y
+ else:
+ if pane.min_size.x > dock_min_size:
+ dock_min_size = pane.min_size.x
+
+ if plus_border:
+ dock_min_size += pane_border_size*2
+ if plus_caption and dock.IsHorizontal():
+ dock_min_size += caption_size
+ if plus_caption_left and dock.IsVertical():
+ dock_min_size += caption_size
+
+ dock.min_size = dock_min_size
+
+ # if the pane's current size is less than it's
+ # minimum, increase the dock's size to it's minimum
+ if dock.size < dock.min_size:
+ dock.size = dock.min_size
+
+ # determine the dock's mode (fixed or proportional)
+ # determine whether the dock has only toolbars
+ action_pane_marked = False
+ dock.fixed = True
+ dock.toolbar = True
+ for pane in dock.panes:
+ if not pane.IsFixed():
+ dock.fixed = False
+ if not pane.IsToolbar():
+ dock.toolbar = False
+ if pane.HasFlag(AuiPaneInfo.optionDockFixed):
+ dock.fixed = True
+ if pane.HasFlag(AuiPaneInfo.actionPane):
+ action_pane_marked = True
+
+ # if the dock mode is proportional and not fixed-pixel,
+ # reassign the dock_pos to the sequential 0, 1, 2, 3
+ # e.g. remove gaps like 1, 2, 30, 500
+ if not dock.fixed:
+ for jj in xrange(dock_pane_count):
+ pane = dock.panes[jj]
+ pane.dock_pos = jj
+
+ # if the dock mode is fixed, and none of the panes
+ # are being moved right now, make sure the panes
+ # do not overlap each other. If they do, we will
+ # adjust the panes' positions
+ if dock.fixed and not action_pane_marked:
+ pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock)
+ offset = 0
+ for jj in xrange(dock_pane_count):
+ pane = dock.panes[jj]
+ pane.dock_pos = pane_positions[jj]
+ amount = pane.dock_pos - offset
+ if amount >= 0:
+ offset += amount
+ else:
+ pane.dock_pos += -amount
+
+ offset += pane_sizes[jj]
+ dock.panes[jj] = pane
+
+ if oncheck:
+ self._docks[ii] = dock
+
+ # shrink docks if needed
+## docks = self.SmartShrink(docks, AUI_DOCK_TOP)
+## docks = self.SmartShrink(docks, AUI_DOCK_LEFT)
+
+ if oncheck:
+ self._docks = docks
+
+ # discover the maximum dock layer
+ max_layer = 0
+ dock_count = len(docks)
+
+ for ii in xrange(dock_count):
+ max_layer = max(max_layer, docks[ii].dock_layer)
+
+ # clear out uiparts
+ uiparts = []
+
+ # create a bunch of box sizers,
+ # from the innermost level outwards.
+ cont = None
+ middle = None
+
+ if oncheck:
+ docks = self._docks
+
+ for layer in xrange(max_layer+1):
+ # find any docks in this layer
+ arr = FindDocks(docks, -1, layer, -1)
+ # if there aren't any, skip to the next layer
+ if not arr:
+ continue
+
+ old_cont = cont
+
+ # create a container which will hold this layer's
+ # docks (top, bottom, left, right)
+ cont = wx.BoxSizer(wx.VERTICAL)
+
+ # find any top docks in this layer
+ arr = FindDocks(docks, AUI_DOCK_TOP, layer, -1)
+ for row in arr:
+ uiparts = self.LayoutAddDock(cont, row, uiparts, spacer_only)
+
+ # fill out the middle layer (which consists
+ # of left docks, content area and right docks)
+
+ middle = wx.BoxSizer(wx.HORIZONTAL)
+
+ # find any left docks in this layer
+ arr = FindDocks(docks, AUI_DOCK_LEFT, layer, -1)
+ for row in arr:
+ uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only)
+
+ # add content dock (or previous layer's sizer
+ # to the middle
+ if not old_cont:
+ # find any center docks
+ arr = FindDocks(docks, AUI_DOCK_CENTER, -1, -1)
+ if arr:
+ for row in arr:
+ uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only)
+
+ elif not self._has_maximized:
+ # there are no center docks, add a background area
+ sizer_item = middle.Add((1, 1), 1, wx.EXPAND)
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typeBackground
+ part.pane = None
+ part.dock = None
+ part.button = None
+ part.cont_sizer = middle
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+ else:
+ middle.Add(old_cont, 1, wx.EXPAND)
+
+ # find any right docks in this layer
+ arr = FindDocks(docks, AUI_DOCK_RIGHT, layer, -1, reverse=True)
+ for row in arr:
+ uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only)
+
+ if len(middle.GetChildren()) > 0:
+ cont.Add(middle, 1, wx.EXPAND)
+
+ # find any bottom docks in this layer
+ arr = FindDocks(docks, AUI_DOCK_BOTTOM, layer, -1, reverse=True)
+ for row in arr:
+ uiparts = self.LayoutAddDock(cont, row, uiparts, spacer_only)
+
+ if not cont:
+ # no sizer available, because there are no docks,
+ # therefore we will create a simple background area
+ cont = wx.BoxSizer(wx.VERTICAL)
+ sizer_item = cont.Add((1, 1), 1, wx.EXPAND)
+ part = AuiDockUIPart()
+ part.type = AuiDockUIPart.typeBackground
+ part.pane = None
+ part.dock = None
+ part.button = None
+ part.cont_sizer = middle
+ part.sizer_item = sizer_item
+ uiparts.append(part)
+
+ if oncheck:
+ self._uiparts = uiparts
+ self._docks = docks
+
+ container.Add(cont, 1, wx.EXPAND)
+
+ if oncheck:
+ return container
+ else:
+ return container, panes, docks, uiparts
+
+
+ def SetDockSizeConstraint(self, width_pct, height_pct):
+ """
+ When a user creates a new dock by dragging a window into a docked position,
+ often times the large size of the window will create a dock that is unwieldly
+ large.
+
+ :class:`AuiManager` by default limits the size of any new dock to 1/3 of the window
+ size. For horizontal docks, this would be 1/3 of the window height. For vertical
+ docks, 1/3 of the width. Calling this function will adjust this constraint value.
+
+ The numbers must be between 0.0 and 1.0. For instance, calling :meth:`SetDockSizeConstraint`
+ with (0.5, 0.5) will cause new docks to be limited to half of the size of the entire
+ managed window.
+
+ :param float `width_pct`: a number representing the `x` dock size constraint;
+ :param float `width_pct`: a number representing the `y` dock size constraint.
+ """
+
+ self._dock_constraint_x = max(0.0, min(1.0, width_pct))
+ self._dock_constraint_y = max(0.0, min(1.0, height_pct))
+
+
+ def GetDockSizeConstraint(self):
+ """
+ Returns the current dock constraint values.
+
+ :see: :meth:`SetDockSizeConstraint`
+ """
+
+ return self._dock_constraint_x, self._dock_constraint_y
+
+
+ def Update(self):
+ """
+ This method is called after any number of changes are made to any of the
+ managed panes. :meth:`Update` must be invoked after :meth:`AddPane`
+ or :meth:`InsertPane` are called in order to "realize" or "commit" the changes.
+
+ In addition, any number of changes may be made to :class:`AuiManager` structures
+ (retrieved with :meth:`GetPane`), but to realize the changes, :meth:`Update`
+ must be called. This construction allows pane flicker to be avoided by updating
+ the whole layout at one time.
+ """
+
+ self._hover_button = None
+ self._action_part = None
+
+ # destroy floating panes which have been
+ # redocked or are becoming non-floating
+ for p in self._panes:
+ if p.IsFloating() or not p.frame:
+ continue
+
+ # because the pane is no longer in a floating, we need to
+ # reparent it to self._frame and destroy the floating frame
+ # reduce flicker
+ p.window.SetSize((1, 1))
+
+ # the following block is a workaround for bug #1531361
+ # (see wxWidgets sourceforge page). On wxGTK (only), when
+ # a frame is shown/hidden, a move event unfortunately
+ # also gets fired. Because we may be dragging around
+ # a pane, we need to cancel that action here to prevent
+ # a spurious crash.
+ if self._action_window == p.frame:
+ if self._frame.HasCapture():
+ self._frame.ReleaseMouse()
+ self._action = actionNone
+ self._action_window = None
+
+ # hide the frame
+ if p.frame.IsShown():
+ p.frame.Show(False)
+
+ if self._action_window == p.frame:
+ self._action_window = None
+
+ # reparent to self._frame and destroy the pane
+ p.window.Reparent(self._frame)
+ if isinstance(p.window, auibar.AuiToolBar):
+ p.window.SetAuiManager(self)
+
+ if p.frame:
+ p.frame.SetSizer(None)
+ p.frame.Destroy()
+ p.frame = None
+
+ # Only the master manager should create/destroy notebooks...
+ if not self._masterManager:
+ self.UpdateNotebook()
+
+ # delete old sizer first
+ self._frame.SetSizer(None)
+
+ # create a layout for all of the panes
+ sizer = self.LayoutAll(self._panes, self._docks, self._uiparts, False)
+
+ # hide or show panes as necessary,
+ # and float panes as necessary
+
+ pane_count = len(self._panes)
+
+ for ii in xrange(pane_count):
+ p = self._panes[ii]
+ pFrame = p.frame
+
+ if p.IsFloating():
+ if pFrame is None:
+ # we need to create a frame for this
+ # pane, which has recently been floated
+ frame = self.CreateFloatingFrame(self._frame, p)
+
+ # on MSW and Mac, if the owner desires transparent dragging, and
+ # the dragging is happening right now, then the floating
+ # window should have this style by default
+ if self._action in [actionDragFloatingPane, actionDragToolbarPane] and \
+ self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
+ frame.SetTransparent(150)
+
+ if p.IsToolbar():
+ bar = p.window
+ if isinstance(bar, auibar.AuiToolBar):
+ bar.SetGripperVisible(False)
+ agwStyle = bar.GetAGWWindowStyleFlag()
+ bar.SetAGWWindowStyleFlag(agwStyle & ~AUI_TB_VERTICAL)
+ bar.Realize()
+
+ s = p.window.GetMinSize()
+ p.BestSize(s)
+ p.FloatingSize(wx.DefaultSize)
+
+ frame.SetPaneWindow(p)
+ p.needsTransparency = True
+ p.frame = pFrame = frame
+ if p.IsShown() and not frame.IsShown():
+ frame.Show()
+ frame.Update()
+ else:
+
+ # frame already exists, make sure it's position
+ # and size reflect the information in AuiPaneInfo
+ if pFrame.GetPosition() != p.floating_pos or pFrame.GetSize() != p.floating_size:
+ pFrame.SetDimensions(p.floating_pos.x, p.floating_pos.y,
+ p.floating_size.x, p.floating_size.y, wx.SIZE_USE_EXISTING)
+
+ # update whether the pane is resizable or not
+ style = p.frame.GetWindowStyleFlag()
+ if p.IsFixed():
+ style &= ~wx.RESIZE_BORDER
+ else:
+ style |= wx.RESIZE_BORDER
+
+ p.frame.SetWindowStyleFlag(style)
+
+ if pFrame.IsShown() != p.IsShown():
+ p.needsTransparency = True
+ pFrame.Show(p.IsShown())
+
+ if pFrame.GetTitle() != p.caption:
+ pFrame.SetTitle(p.caption)
+ if p.icon.IsOk():
+ pFrame.SetIcon(wx.IconFromBitmap(p.icon))
+
+ else:
+
+ if p.IsToolbar():
+# self.SwitchToolBarOrientation(p)
+ p.best_size = p.window.GetBestSize()
+
+ if p.window and not p.IsNotebookPage() and p.window.IsShown() != p.IsShown():
+ p.window.Show(p.IsShown())
+
+ if pFrame and p.needsTransparency:
+ if pFrame.IsShown() and pFrame._transparent != p.transparent:
+ pFrame.SetTransparent(p.transparent)
+ pFrame._transparent = p.transparent
+
+ p.needsTransparency = False
+
+ # if "active panes" are no longer allowed, clear
+ # any optionActive values from the pane states
+ if self._agwFlags & AUI_MGR_ALLOW_ACTIVE_PANE == 0:
+ p.state &= ~AuiPaneInfo.optionActive
+
+ self._panes[ii] = p
+
+ old_pane_rects = []
+ pane_count = len(self._panes)
+
+ for p in self._panes:
+ r = wx.Rect()
+ if p.window and p.IsShown() and p.IsDocked():
+ r = p.rect
+
+ old_pane_rects.append(r)
+
+ # apply the new sizer
+ self._frame.SetSizer(sizer)
+ self._frame.SetAutoLayout(False)
+ self.DoFrameLayout()
+
+ # now that the frame layout is done, we need to check
+ # the new pane rectangles against the old rectangles that
+ # we saved a few lines above here. If the rectangles have
+ # changed, the corresponding panes must also be updated
+ for ii in xrange(pane_count):
+ p = self._panes[ii]
+ if p.window and p.IsShown() and p.IsDocked():
+ if p.rect != old_pane_rects[ii]:
+ p.window.Refresh()
+ p.window.Update()
+
+ if wx.Platform == "__WXMAC__":
+ self._frame.Refresh()
+ else:
+ self.Repaint()
+
+ if not self._masterManager:
+ e = self.FireEvent(wxEVT_AUI_PERSPECTIVE_CHANGED, None, canVeto=False)
+
+
+ def UpdateNotebook(self):
+ """ Updates the automatic :class:`~lib.agw.aui.auibook.AuiNotebook` in the layout (if any exists). """
+
+ # Workout how many notebooks we need.
+ max_notebook = -1
+
+ # destroy floating panes which have been
+ # redocked or are becoming non-floating
+ for paneInfo in self._panes:
+ if max_notebook < paneInfo.notebook_id:
+ max_notebook = paneInfo.notebook_id
+
+ # We are the master of our domain
+ extra_notebook = len(self._notebooks)
+ max_notebook += 1
+
+ for i in xrange(extra_notebook, max_notebook):
+ self.CreateNotebook()
+
+ # Remove pages from notebooks that no-longer belong there ...
+ for nb, notebook in enumerate(self._notebooks):
+ pages = notebook.GetPageCount()
+ pageCounter, allPages = 0, pages
+
+ # Check each tab ...
+ for page in xrange(pages):
+
+ if page >= allPages:
+ break
+
+ window = notebook.GetPage(pageCounter)
+ paneInfo = self.GetPane(window)
+ if paneInfo.IsOk() and paneInfo.notebook_id != nb:
+ notebook.RemovePage(pageCounter)
+ window.Hide()
+ window.Reparent(self._frame)
+ pageCounter -= 1
+ allPages -= 1
+
+ pageCounter += 1
+
+ notebook.DoSizing()
+
+ # Add notebook pages that aren't there already...
+ for paneInfo in self._panes:
+ if paneInfo.IsNotebookPage():
+
+ title = (paneInfo.caption == "" and [paneInfo.name] or [paneInfo.caption])[0]
+
+ notebook = self._notebooks[paneInfo.notebook_id]
+ page_id = notebook.GetPageIndex(paneInfo.window)
+
+ if page_id < 0:
+
+ paneInfo.window.Reparent(notebook)
+ notebook.AddPage(paneInfo.window, title, True, paneInfo.icon)
+
+ # Update title and icon ...
+ else:
+
+ notebook.SetPageText(page_id, title)
+ notebook.SetPageBitmap(page_id, paneInfo.icon)
+
+ notebook.DoSizing()
+
+ # Wire-up newly created notebooks
+ elif paneInfo.IsNotebookControl() and not paneInfo.window:
+ paneInfo.window = self._notebooks[paneInfo.notebook_id]
+
+ # Delete empty notebooks, and convert notebooks with 1 page to
+ # normal panes...
+ remap_ids = [-1]*len(self._notebooks)
+ nb_idx = 0
+
+ for nb, notebook in enumerate(self._notebooks):
+ if notebook.GetPageCount() == 1:
+
+ # Convert notebook page to pane...
+ window = notebook.GetPage(0)
+ child_pane = self.GetPane(window)
+ notebook_pane = self.GetPane(notebook)
+ if child_pane.IsOk() and notebook_pane.IsOk():
+
+ child_pane.SetDockPos(notebook_pane)
+ child_pane.window.Hide()
+ child_pane.window.Reparent(self._frame)
+ child_pane.frame = None
+ child_pane.notebook_id = -1
+ if notebook_pane.IsFloating():
+ child_pane.Float()
+
+ self.DetachPane(notebook)
+
+ notebook.RemovePage(0)
+ notebook.Destroy()
+
+ else:
+
+ raise Exception("Odd notebook docking")
+
+ elif notebook.GetPageCount() == 0:
+
+ self.DetachPane(notebook)
+ notebook.Destroy()
+
+ else:
+
+ # Correct page ordering. The original wxPython code
+ # for this did not work properly, and would misplace
+ # windows causing errors.
+ notebook.Freeze()
+ self._notebooks[nb_idx] = notebook
+ pages = notebook.GetPageCount()
+ selected = notebook.GetPage(notebook.GetSelection())
+
+ # Take each page out of the notebook, group it with
+ # its current pane, and sort the list by pane.dock_pos
+ # order
+ pages_and_panes = []
+ for idx in reversed(range(pages)):
+ page = notebook.GetPage(idx)
+ pane = self.GetPane(page)
+ pages_and_panes.append((page, pane))
+ notebook.RemovePage(idx)
+ sorted_pnp = sorted(pages_and_panes, key=lambda tup: tup[1].dock_pos)
+
+ # Grab the attributes from the panes which are ordered
+ # correctly, and copy those attributes to the original
+ # panes. (This avoids having to change the ordering
+ # of self._panes) Then, add the page back into the notebook
+ sorted_attributes = [self.GetAttributes(tup[1])
+ for tup in sorted_pnp]
+ for attrs, tup in zip(sorted_attributes, pages_and_panes):
+ pane = tup[1]
+ self.SetAttributes(pane, attrs)
+ notebook.AddPage(pane.window, pane.caption)
+
+ notebook.SetSelection(notebook.GetPageIndex(selected), True)
+ notebook.DoSizing()
+ notebook.Thaw()
+
+ # It's a keeper.
+ remap_ids[nb] = nb_idx
+ nb_idx += 1
+
+ # Apply remap...
+ nb_count = len(self._notebooks)
+
+ if nb_count != nb_idx:
+
+ self._notebooks = self._notebooks[0:nb_idx]
+ for p in self._panes:
+ if p.notebook_id >= 0:
+ p.notebook_id = remap_ids[p.notebook_id]
+ if p.IsNotebookControl():
+ p.SetNameFromNotebookId()
+
+ # Make sure buttons are correct ...
+ for notebook in self._notebooks:
+ want_max = True
+ want_min = True
+ want_close = True
+
+ pages = notebook.GetPageCount()
+ for page in xrange(pages):
+
+ win = notebook.GetPage(page)
+ pane = self.GetPane(win)
+ if pane.IsOk():
+
+ if not pane.HasCloseButton():
+ want_close = False
+ if not pane.HasMaximizeButton():
+ want_max = False
+ if not pane.HasMinimizeButton():
+ want_min = False
+
+ notebook_pane = self.GetPane(notebook)
+ if notebook_pane.IsOk():
+ if notebook_pane.HasMinimizeButton() != want_min:
+ if want_min:
+ button = AuiPaneButton(AUI_BUTTON_MINIMIZE)
+ notebook_pane.state |= AuiPaneInfo.buttonMinimize
+ notebook_pane.buttons.append(button)
+
+ # todo: remove min/max
+
+ if notebook_pane.HasMaximizeButton() != want_max:
+ if want_max:
+ button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE)
+ notebook_pane.state |= AuiPaneInfo.buttonMaximize
+ notebook_pane.buttons.append(button)
+
+ # todo: remove min/max
+
+ if notebook_pane.HasCloseButton() != want_close:
+ if want_close:
+ button = AuiPaneButton(AUI_BUTTON_CLOSE)
+ notebook_pane.state |= AuiPaneInfo.buttonClose
+ notebook_pane.buttons.append(button)
+
+ # todo: remove close
+
+
+ def SmartShrink(self, docks, direction):
+ """
+ Used to intelligently shrink the docks' size (if needed).
+
+ :param `docks`: a list of :class:`AuiDockInfo` instances;
+ :param integer `direction`: the direction in which to shrink.
+ """
+
+ sashSize = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
+ caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
+ clientSize = self._frame.GetClientSize()
+ ourDocks = FindDocks(docks, direction, -1, -1)
+ oppositeDocks = FindOppositeDocks(docks, direction)
+ oppositeSize = self.GetOppositeDockTotalSize(docks, direction)
+ ourSize = 0
+
+ for dock in ourDocks:
+ ourSize += dock.size
+
+ if not dock.toolbar:
+ ourSize += sashSize
+
+ shrinkSize = ourSize + oppositeSize
+
+ if direction == AUI_DOCK_TOP or direction == AUI_DOCK_BOTTOM:
+ shrinkSize -= clientSize.y
+ else:
+ shrinkSize -= clientSize.x
+
+ if shrinkSize <= 0:
+ return docks
+
+ # Combine arrays
+ for dock in oppositeDocks:
+ ourDocks.append(dock)
+
+ oppositeDocks = []
+
+ for dock in ourDocks:
+ if dock.toolbar or not dock.resizable:
+ continue
+
+ dockRange = dock.size - dock.min_size
+
+ if dock.min_size == 0:
+ dockRange -= sashSize
+ if direction == AUI_DOCK_TOP or direction == AUI_DOCK_BOTTOM:
+ dockRange -= caption_size
+
+ if dockRange >= shrinkSize:
+
+ dock.size -= shrinkSize
+ return docks
+
+ else:
+
+ dock.size -= dockRange
+ shrinkSize -= dockRange
+
+ return docks
+
+
+ def UpdateDockingGuides(self, paneInfo):
+ """
+ Updates the docking guide windows positions and appearance.
+
+ :param `paneInfo`: a :class:`AuiPaneInfo` instance.
+ """
+
+ if len(self._guides) == 0:
+ self.CreateGuideWindows()
+
+ captionSize = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
+ frameRect = GetInternalFrameRect(self._frame, self._docks)
+ mousePos = wx.GetMousePosition()
+
+ for indx, guide in enumerate(self._guides):
+
+ pt = wx.Point()
+ guide_size = guide.host.GetSize()
+ if not guide.host:
+ raise Exception("Invalid docking host")
+
+ direction = guide.dock_direction
+
+ if direction == AUI_DOCK_LEFT:
+ pt.x = frameRect.x + guide_size.x / 2 + 16
+ pt.y = frameRect.y + frameRect.height / 2
+
+ elif direction == AUI_DOCK_TOP:
+ pt.x = frameRect.x + frameRect.width / 2
+ pt.y = frameRect.y + guide_size.y / 2 + 16
+
+ elif direction == AUI_DOCK_RIGHT:
+ pt.x = frameRect.x + frameRect.width - guide_size.x / 2 - 16
+ pt.y = frameRect.y + frameRect.height / 2
+
+ elif direction == AUI_DOCK_BOTTOM:
+ pt.x = frameRect.x + frameRect.width / 2
+ pt.y = frameRect.y + frameRect.height - guide_size.y / 2 - 16
+
+ elif direction == AUI_DOCK_CENTER:
+ rc = paneInfo.window.GetScreenRect()
+ pt.x = rc.x + rc.width / 2
+ pt.y = rc.y + rc.height / 2
+ if paneInfo.HasCaption():
+ pt.y -= captionSize / 2
+ elif paneInfo.HasCaptionLeft():
+ pt.x -= captionSize / 2
+
+ # guide will be centered around point 'pt'
+ targetPosition = wx.Point(pt.x - guide_size.x / 2, pt.y - guide_size.y / 2)
+
+ if guide.host.GetPosition() != targetPosition:
+ guide.host.Move(targetPosition)
+
+ guide.host.AeroMove(targetPosition)
+
+ if guide.dock_direction == AUI_DOCK_CENTER:
+ guide.host.ValidateNotebookDocking(paneInfo.IsNotebookDockable())
+
+ guide.host.UpdateDockGuide(mousePos)
+
+ paneInfo.window.Lower()
+
+
+ def DoFrameLayout(self):
+ """
+ This is an internal function which invokes :meth:`Sizer.Layout() <Sizer.Layout>`
+ on the frame's main sizer, then measures all the various UI items
+ and updates their internal rectangles.
+
+ :note: This should always be called instead of calling
+ `self._managed_window.Layout()` directly.
+ """
+
+ self._frame.Layout()
+
+ for part in self._uiparts:
+ # get the rectangle of the UI part
+ # originally, this code looked like this:
+ # part.rect = wx.Rect(part.sizer_item.GetPosition(),
+ # part.sizer_item.GetSize())
+ # this worked quite well, with one exception: the mdi
+ # client window had a "deferred" size variable
+ # that returned the wrong size. It looks like
+ # a bug in wx, because the former size of the window
+ # was being returned. So, we will retrieve the part's
+ # rectangle via other means
+
+ part.rect = part.sizer_item.GetRect()
+ flag = part.sizer_item.GetFlag()
+ border = part.sizer_item.GetBorder()
+
+ if flag & wx.TOP:
+ part.rect.y -= border
+ part.rect.height += border
+ if flag & wx.LEFT:
+ part.rect.x -= border
+ part.rect.width += border
+ if flag & wx.BOTTOM:
+ part.rect.height += border
+ if flag & wx.RIGHT:
+ part.rect.width += border
+
+ if part.type == AuiDockUIPart.typeDock:
+ part.dock.rect = part.rect
+ if part.type == AuiDockUIPart.typePane:
+ part.pane.rect = part.rect
+
+
+ def GetPanePart(self, wnd):
+ """
+ Looks up the pane border UI part of the
+ pane specified. This allows the caller to get the exact rectangle
+ of the pane in question, including decorations like caption and border.
+
+ :param Window `wnd`: the window to which the pane border belongs to.
+ """
+
+ for part in self._uiparts:
+ if part.type == AuiDockUIPart.typePaneBorder and \
+ part.pane and part.pane.window == wnd:
+ return part
+
+ for part in self._uiparts:
+ if part.type == AuiDockUIPart.typePane and \
+ part.pane and part.pane.window == wnd:
+ return part
+
+ return None
+
+
+ def GetDockPixelOffset(self, test):
+ """
+ This is an internal function which returns a dock's offset in pixels from
+ the left side of the window (for horizontal docks) or from the top of the
+ window (for vertical docks).
+
+ This value is necessary for calculating fixed-pane/toolbar offsets
+ when they are dragged.
+
+ :param `test`: a fake :class:`AuiPaneInfo` for testing purposes.
+ """
+
+ # the only way to accurately calculate the dock's
+ # offset is to actually run a theoretical layout
+ docks, panes = CopyDocksAndPanes2(self._docks, self._panes)
+ panes.append(test)
+
+ sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False)
+ client_size = self._frame.GetClientSize()
+ sizer.SetDimension(0, 0, client_size.x, client_size.y)
+ sizer.Layout()
+
+ for part in uiparts:
+ pos = part.sizer_item.GetPosition()
+ size = part.sizer_item.GetSize()
+ part.rect = wx.RectPS(pos, size)
+ if part.type == AuiDockUIPart.typeDock:
+ part.dock.rect = part.rect
+
+ sizer.Destroy()
+
+ for dock in docks:
+ if test.dock_direction == dock.dock_direction and \
+ test.dock_layer == dock.dock_layer and \
+ test.dock_row == dock.dock_row:
+
+ if dock.IsVertical():
+ return dock.rect.y
+ else:
+ return dock.rect.x
+
+ return 0
+
+
+ def GetPartnerDock(self, dock):
+ """
+ Returns the partner dock for the input dock.
+
+ :param `dock`: a :class:`AuiDockInfo` instance.
+ """
+
+ for layer in xrange(dock.dock_layer, -1, -1):
+
+ bestDock = None
+
+ for tmpDock in self._docks:
+
+ if tmpDock.dock_layer != layer:
+ continue
+
+ if tmpDock.dock_direction != dock.dock_direction:
+ continue
+
+ if tmpDock.dock_layer < dock.dock_layer:
+
+ if not bestDock or tmpDock.dock_row < bestDock.dock_row:
+ bestDock = tmpDock
+
+ elif tmpDock.dock_row > dock.dock_row:
+
+ if not bestDock or tmpDock.dock_row > bestDock.dock_row:
+ bestDock = tmpDock
+
+ if bestDock:
+ return bestDock
+
+ return None
+
+
+ def GetPartnerPane(self, dock, pane):
+ """
+ Returns the partner pane for the input pane. They both need to live
+ in the same :class:`AuiDockInfo`.
+
+ :param `dock`: a :class:`AuiDockInfo` instance;
+ :param `pane`: a :class:`AuiPaneInfo` class.
+ """
+
+ panePosition = -1
+
+ for i, tmpPane in enumerate(dock.panes):
+ if tmpPane.window == pane.window:
+ panePosition = i
+ elif not tmpPane.IsFixed() and panePosition != -1:
+ return tmpPane
+
+ return None
+
+
+ def GetTotalPixSizeAndProportion(self, dock):
+ """
+ Returns the dimensions and proportion of the input dock.
+
+ :param `dock`: the :class:`AuiDockInfo` structure to analyze.
+ """
+
+ totalPixsize = 0
+ totalProportion = 0
+
+ # determine the total proportion of all resizable panes,
+ # and the total size of the dock minus the size of all
+ # the fixed panes
+ for tmpPane in dock.panes:
+
+ if tmpPane.IsFixed():
+ continue
+
+ totalProportion += tmpPane.dock_proportion
+
+ if dock.IsHorizontal():
+ totalPixsize += tmpPane.rect.width
+ else:
+ totalPixsize += tmpPane.rect.height
+
+## if tmpPane.min_size.IsFullySpecified():
+##
+## if dock.IsHorizontal():
+## totalPixsize -= tmpPane.min_size.x
+## else:
+## totalPixsize -= tmpPane.min_size.y
+
+ return totalPixsize, totalProportion
+
+
+ def GetOppositeDockTotalSize(self, docks, direction):
+ """
+ Returns the dimensions of the dock which lives opposite of the input dock.
+
+ :param `docks`: a list of :class:`AuiDockInfo` structures to analyze;
+ :param integer `direction`: the direction in which to look for the opposite dock.
+ """
+
+ sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
+ caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
+ pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
+ minSizeMax = 0
+ result = sash_size
+ vertical = False
+
+ if direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]:
+ vertical = True
+
+ # Get minimum size of the most inner area
+ for tmpDock in docks:
+
+ if tmpDock.dock_layer != 0:
+ continue
+
+ if tmpDock.dock_direction != AUI_DOCK_CENTER and tmpDock.IsVertical() != vertical:
+ continue
+
+ for tmpPane in tmpDock.panes:
+
+ minSize = pane_border_size*2 - sash_size
+
+ if vertical:
+ minSize += tmpPane.min_size.y + caption_size
+ else:
+ minSize += tmpPane.min_size.x
+
+ if minSize > minSizeMax:
+ minSizeMax = minSize
+
+ result += minSizeMax
+
+ # Get opposite docks
+ oppositeDocks = FindOppositeDocks(docks, direction)
+
+ # Sum size of the opposite docks and their sashes
+ for dock in oppositeDocks:
+ result += dock.size
+ # if it's not a toolbar add the sash_size too
+ if not dock.toolbar:
+ result += sash_size
+
+ return result
+
+
+ def CalculateDockSizerLimits(self, dock):
+ """
+ Calculates the minimum and maximum sizes allowed for the input dock.
+
+ :param `dock`: the :class:`AuiDockInfo` structure to analyze.
+ """
+
+ docks, panes = CopyDocksAndPanes2(self._docks, self._panes)
+
+ sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
+ caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
+ opposite_size = self.GetOppositeDockTotalSize(docks, dock.dock_direction)
+
+ for tmpDock in docks:
+
+ if tmpDock.dock_direction == dock.dock_direction and \
+ tmpDock.dock_layer == dock.dock_layer and \
+ tmpDock.dock_row == dock.dock_row:
+
+ tmpDock.size = 1
+ break
+
+ sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False)
+ client_size = self._frame.GetClientSize()
+ sizer.SetDimension(0, 0, client_size.x, client_size.y)
+ sizer.Layout()
+
+ for part in uiparts:
+
+ part.rect = wx.RectPS(part.sizer_item.GetPosition(), part.sizer_item.GetSize())
+ if part.type == AuiDockUIPart.typeDock:
+ part.dock.rect = part.rect
+
+ sizer.Destroy()
+ new_dock = None
+
+ for tmpDock in docks:
+ if tmpDock.dock_direction == dock.dock_direction and \
+ tmpDock.dock_layer == dock.dock_layer and \
+ tmpDock.dock_row == dock.dock_row:
+
+ new_dock = tmpDock
+ break
+
+ partnerDock = self.GetPartnerDock(dock)
+
+ if partnerDock:
+ partnerRange = partnerDock.size - partnerDock.min_size
+ if partnerDock.min_size == 0:
+ partnerRange -= sash_size
+ if dock.IsHorizontal():
+ partnerRange -= caption_size
+
+ direction = dock.dock_direction
+
+ if direction == AUI_DOCK_LEFT:
+ minPix = new_dock.rect.x + new_dock.rect.width
+ maxPix = dock.rect.x + dock.rect.width
+ maxPix += partnerRange
+
+ elif direction == AUI_DOCK_TOP:
+ minPix = new_dock.rect.y + new_dock.rect.height
+ maxPix = dock.rect.y + dock.rect.height
+ maxPix += partnerRange
+
+ elif direction == AUI_DOCK_RIGHT:
+ minPix = dock.rect.x - partnerRange - sash_size
+ maxPix = new_dock.rect.x - sash_size
+
+ elif direction == AUI_DOCK_BOTTOM:
+ minPix = dock.rect.y - partnerRange - sash_size
+ maxPix = new_dock.rect.y - sash_size
+
+ return minPix, maxPix
+
+ direction = new_dock.dock_direction
+
+ if direction == AUI_DOCK_LEFT:
+ minPix = new_dock.rect.x + new_dock.rect.width
+ maxPix = client_size.x - opposite_size - sash_size
+
+ elif direction == AUI_DOCK_TOP:
+ minPix = new_dock.rect.y + new_dock.rect.height
+ maxPix = client_size.y - opposite_size - sash_size
+
+ elif direction == AUI_DOCK_RIGHT:
+ minPix = opposite_size
+ maxPix = new_dock.rect.x - sash_size
+
+ elif direction == AUI_DOCK_BOTTOM:
+ minPix = opposite_size
+ maxPix = new_dock.rect.y - sash_size
+
+ return minPix, maxPix
+
+
+ def CalculatePaneSizerLimits(self, dock, pane):
+ """
+ Calculates the minimum and maximum sizes allowed for the input pane.
+
+ :param `dock`: the :class:`AuiDockInfo` structure to which `pane` belongs to;
+ :param `pane`: a :class:`AuiPaneInfo` class for which calculation are requested.
+ """
+
+ if pane.IsFixed():
+ if dock.IsHorizontal():
+ minPix = maxPix = pane.rect.x + 1 + pane.rect.width
+ else:
+ minPix = maxPix = pane.rect.y + 1 + pane.rect.height
+
+ return minPix, maxPix
+
+ totalPixsize, totalProportion = self.GetTotalPixSizeAndProportion(dock)
+ partnerPane = self.GetPartnerPane(dock, pane)
+
+ if dock.IsHorizontal():
+
+ minPix = pane.rect.x + 1
+ maxPix = pane.rect.x + 1 + pane.rect.width
+
+ if pane.min_size.IsFullySpecified():
+ minPix += pane.min_size.x
+ else:
+ minPix += 1
+
+ if partnerPane:
+ maxPix += partnerPane.rect.width
+
+ if partnerPane.min_size.IsFullySpecified():
+ maxPix -= partnerPane.min_size.x - 1
+
+ else:
+ minPix = maxPix
+
+ else:
+
+ minPix = pane.rect.y + 1
+ maxPix = pane.rect.y + 1 + pane.rect.height
+
+ if pane.min_size.IsFullySpecified():
+ minPix += pane.min_size.y
+ else:
+ minPix += 1
+
+ if partnerPane:
+ maxPix += partnerPane.rect.height
+
+ if partnerPane.min_size.IsFullySpecified():
+ maxPix -= partnerPane.min_size.y - 1
+
+ else:
+ minPix = maxPix
+
+ return minPix, maxPix
+
+
+ def CheckMovableSizer(self, part):
+ """
+ Checks if a UI part can be actually resized.
+
+ :param AuiDockUIPart `part`: a UI part.
+ """
+
+ # a dock may not be resized if it has a single
+ # pane which is not resizable
+ if part.type == AuiDockUIPart.typeDockSizer and part.dock and \
+ len(part.dock.panes) == 1 and part.dock.panes[0].IsFixed():
+
+ return False
+
+ if part.pane:
+
+ # panes that may not be resized should be ignored here
+ minPix, maxPix = self.CalculatePaneSizerLimits(part.dock, part.pane)
+
+ if minPix == maxPix:
+ return False
+
+ return True
+
+
+ def PaneFromTabEvent(self, event):
+ """
+ Returns a :class:`AuiPaneInfo` from a :class:`~lib.agw.aui.auibook.AuiNotebook` event.
+
+ :param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event.
+ """
+
+ obj = event.GetEventObject()
+
+ if obj and isinstance(obj, auibook.AuiTabCtrl):
+
+ page_idx = obj.GetActivePage()
+
+ if page_idx >= 0:
+ page = obj.GetPage(page_idx)
+ window = page.window
+ if window:
+ return self.GetPane(window)
+
+ elif obj and isinstance(obj, auibook.AuiNotebook):
+
+ page_idx = event.GetSelection()
+
+ if page_idx >= 0:
+ window = obj.GetPage(page_idx)
+ if window:
+ return self.GetPane(window)
+
+ return NonePaneInfo
+
+
+ def OnTabBeginDrag(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_BEGIN_DRAG`` event.
+
+ :param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event to be processed.
+ """
+
+ if self._masterManager:
+ self._masterManager.OnTabBeginDrag(event)
+
+ else:
+ paneInfo = self.PaneFromTabEvent(event)
+
+ if paneInfo.IsOk():
+
+ # It's one of ours!
+ self._action = actionDragFloatingPane
+ mouse = wx.GetMousePosition()
+
+ # set initial float position - may have to think about this
+ # offset a bit more later ...
+ self._action_offset = wx.Point(20, 10)
+ self._toolbar_action_offset = wx.Point(20, 10)
+
+ paneInfo.floating_pos = mouse - self._action_offset
+ paneInfo.dock_pos = AUI_DOCK_NONE
+ paneInfo.notebook_id = -1
+
+ tab = event.GetEventObject()
+
+ if tab.HasCapture():
+ tab.ReleaseMouse()
+
+ # float the window
+ if paneInfo.IsMaximized():
+ self.RestorePane(paneInfo)
+ paneInfo.Float()
+ self.Update()
+
+ self._action_window = paneInfo.window
+
+ self._frame.CaptureMouse()
+ event.SetDispatched(True)
+
+ else:
+
+ # not our window
+ event.Skip()
+
+
+ def OnTabPageClose(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_PAGE_CLOSE`` event.
+
+ :param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event to be processed.
+ """
+
+ if self._masterManager:
+ self._masterManager.OnTabPageClose(event)
+
+ else:
+
+ p = self.PaneFromTabEvent(event)
+ if p.IsOk():
+
+ # veto it because we will call "RemovePage" ourselves
+ event.Veto()
+
+ # Now ask the app if they really want to close...
+ # fire pane close event
+ e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE)
+ e.SetPane(p)
+ e.SetCanVeto(True)
+ self.ProcessMgrEvent(e)
+
+ if e.GetVeto():
+ return
+
+ self.ClosePane(p)
+ self.Update()
+ else:
+ event.Skip()
+
+
+ def OnTabSelected(self, event):
+ """
+ Handles the ``EVT_AUINOTEBOOK_PAGE_CHANGED`` event.
+
+ :param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event to be processed.
+ """
+
+ if self._masterManager:
+ self._masterManager.OnTabSelected(event)
+ return
+
+ obj = event.GetEventObject()
+
+ if obj and isinstance(obj, auibook.AuiNotebook):
+
+ notebook = obj
+ page = notebook.GetPage(event.GetSelection())
+ paneInfo = self.GetPane(page)
+
+ if paneInfo.IsOk():
+ notebookRoot = GetNotebookRoot(self._panes, paneInfo.notebook_id)
+ if notebookRoot:
+
+ notebookRoot.Caption(paneInfo.caption)
+ self.RefreshCaptions()
+
+ event.Skip()
+
+
+ def GetNotebooks(self):
+ """ Returns all the automatic :class:`~lib.agw.aui.auibook.AuiNotebook` in the :class:`AuiManager`. """
+
+ if self._masterManager:
+ return self._masterManager.GetNotebooks()
+
+ return self._notebooks
+
+
+ def SetMasterManager(self, manager):
+ """
+ Sets the master manager for an automatic :class:`~lib.agw.aui.auibook.AuiNotebook`.
+
+ :param `manager`: an instance of :class:`AuiManager`.
+ """
+
+ self._masterManager = manager
+
+
+ def ProcessDockResult(self, target, new_pos):
+ """
+ This is a utility function used by :meth:`DoDrop` - it checks
+ if a dock operation is allowed, the new dock position is copied into
+ the target info. If the operation was allowed, the function returns ``True``.
+
+ :param `target`: the :class:`AuiPaneInfo` instance to be docked;
+ :param integer `new_pos`: the new docking position if the docking operation is allowed.
+ """
+
+ allowed = False
+ direction = new_pos.dock_direction
+
+ if direction == AUI_DOCK_TOP:
+ allowed = target.IsTopDockable()
+ elif direction == AUI_DOCK_BOTTOM:
+ allowed = target.IsBottomDockable()
+ elif direction == AUI_DOCK_LEFT:
+ allowed = target.IsLeftDockable()
+ elif direction == AUI_DOCK_RIGHT:
+ allowed = target.IsRightDockable()
+
+ if allowed:
+ target = new_pos
+
+ if target.IsToolbar():
+ self.SwitchToolBarOrientation(target)
+
+ return allowed, target
+
+
+ def SwitchToolBarOrientation(self, pane):
+ """
+ Switches the toolbar orientation from vertical to horizontal and vice-versa.
+ This is especially useful for vertical docked toolbars once they float.
+
+ :param `pane`: an instance of :class:`AuiPaneInfo`, which may have a :class:`~lib.agw.aui.auibar.AuiToolBar`
+ window associated with it.
+ """
+
+ if not isinstance(pane.window, auibar.AuiToolBar):
+ return pane
+
+ if pane.IsFloating():
+ return pane
+
+ toolBar = pane.window
+ direction = pane.dock_direction
+ vertical = direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT]
+
+ agwStyle = toolBar.GetAGWWindowStyleFlag()
+ new_agwStyle = agwStyle
+
+ if vertical:
+ new_agwStyle |= AUI_TB_VERTICAL
+ else:
+ new_agwStyle &= ~(AUI_TB_VERTICAL)
+
+ if agwStyle != new_agwStyle:
+ toolBar.SetAGWWindowStyleFlag(new_agwStyle)
+ if not toolBar.GetGripperVisible():
+ toolBar.SetGripperVisible(True)
+
+ s = pane.window.GetMinSize()
+ pane.BestSize(s)
+
+ if new_agwStyle != agwStyle:
+ toolBar.Realize()
+
+ return pane
+
+
+ def DoDrop(self, docks, panes, target, pt, offset=wx.Point(0, 0)):
+ """
+ This is an important function. It basically takes a mouse position,
+ and determines where the panes new position would be. If the pane is to be
+ dropped, it performs the drop operation using the specified dock and pane
+ arrays. By specifying copy dock and pane arrays when calling, a "what-if"
+ scenario can be performed, giving precise coordinates for drop hints.
+
+ :param `docks`: a list of :class:`AuiDockInfo` classes;
+ :param `panes`: a list of :class:`AuiPaneInfo` instances;
+ :param Point `pt`: a mouse position to check for a drop operation;
+ :param Point `offset`: a possible offset from the input point `pt`.
+ """
+
+ if target.IsToolbar():
+ return self.DoDropToolbar(docks, panes, target, pt, offset)
+ elif target.IsFloating():
+ return self.DoDropFloatingPane(docks, panes, target, pt)
+ else:
+ return self.DoDropNonFloatingPane(docks, panes, target, pt)
+
+
+ def CopyTarget(self, target):
+ """
+ Copies all the attributes of the input `target` into another :class:`AuiPaneInfo`.
+
+ :param `target`: the source :class:`AuiPaneInfo` from where to copy attributes.
+ """
+
+ drop = AuiPaneInfo()
+ drop.name = target.name
+ drop.caption = target.caption
+ drop.window = target.window
+ drop.frame = target.frame
+ drop.state = target.state
+ drop.dock_direction = target.dock_direction
+ drop.dock_layer = target.dock_layer
+ drop.dock_row = target.dock_row
+ drop.dock_pos = target.dock_pos
+ drop.best_size = wx.Size(*target.best_size)
+ drop.min_size = wx.Size(*target.min_size)
+ drop.max_size = wx.Size(*target.max_size)
+ drop.floating_pos = wx.Point(*target.floating_pos)
+ drop.floating_size = wx.Size(*target.floating_size)
+ drop.dock_proportion = target.dock_proportion
+ drop.buttons = target.buttons
+ drop.rect = wx.Rect(*target.rect)
+ drop.icon = target.icon
+ drop.notebook_id = target.notebook_id
+ drop.transparent = target.transparent
+ drop.snapped = target.snapped
+ drop.minimize_mode = target.minimize_mode
+ drop.minimize_target = target.minimize_target
+
+ return drop
+
+
+ def DoDropToolbar(self, docks, panes, target, pt, offset):
+ """
+ Handles the situation in which the dropped pane contains a toolbar.
+
+ :param `docks`: a list of :class:`AuiDockInfo` classes;
+ :param `panes`: a list of :class:`AuiPaneInfo` instances;
+ :param AuiPaneInfo `target`: the target pane containing the toolbar;
+ :param Point `pt`: a mouse position to check for a drop operation;
+ :param Point `offset`: a possible offset from the input point `pt`.
+ """
+
+ drop = self.CopyTarget(target)
+
+ # The result should always be shown
+ drop.Show()
+
+ # Check to see if the toolbar has been dragged out of the window
+ if CheckOutOfWindow(self._frame, pt):
+ if self._agwFlags & AUI_MGR_ALLOW_FLOATING and drop.IsFloatable():
+ drop.Float()
+
+ return self.ProcessDockResult(target, drop)
+
+ # Allow directional change when the cursor leaves this rect
+ safeRect = wx.Rect(*target.rect)
+ if target.IsHorizontal():
+ safeRect.Inflate(100, 50)
+ else:
+ safeRect.Inflate(50, 100)
+
+ # Check to see if the toolbar has been dragged to edge of the frame
+ dropDir = CheckEdgeDrop(self._frame, docks, pt)
+
+ if dropDir != -1:
+
+ if dropDir == wx.LEFT:
+ drop.Dock().Left().Layer(auiToolBarLayer).Row(0). \
+ Position(pt.y - self.GetDockPixelOffset(drop) - offset.y)
+
+ elif dropDir == wx.RIGHT:
+ drop.Dock().Right().Layer(auiToolBarLayer).Row(0). \
+ Position(pt.y - self.GetDockPixelOffset(drop) - offset.y)
+
+ elif dropDir == wx.TOP:
+ drop.Dock().Top().Layer(auiToolBarLayer).Row(0). \
+ Position(pt.x - self.GetDockPixelOffset(drop) - offset.x)
+
+ elif dropDir == wx.BOTTOM:
+ drop.Dock().Bottom().Layer(auiToolBarLayer).Row(0). \
+ Position(pt.x - self.GetDockPixelOffset(drop) - offset.x)
+
+ if not target.IsFloating() and safeRect.Contains(pt) and \
+ target.dock_direction != drop.dock_direction:
+ return False, target
+
+ return self.ProcessDockResult(target, drop)
+
+ # If the windows is floating and out of the client area, do nothing
+ if drop.IsFloating() and not self._frame.GetClientRect().Contains(pt):
+ return False, target
+
+ # Ok, can't drop on edge - check internals ...
+
+ clientSize = self._frame.GetClientSize()
+ x = Clip(pt.x, 0, clientSize.x - 1)
+ y = Clip(pt.y, 0, clientSize.y - 1)
+ part = self.HitTest(x, y)
+
+ if not part or not part.dock:
+ return False, target
+
+ dock = part.dock
+
+ # toolbars may only be moved in and to fixed-pane docks,
+ # otherwise we will try to float the pane. Also, the pane
+ # should float if being dragged over center pane windows
+ if not dock.fixed or dock.dock_direction == AUI_DOCK_CENTER:
+
+ if (self._agwFlags & AUI_MGR_ALLOW_FLOATING and drop.IsFloatable()) or \
+ dock.dock_direction not in [AUI_DOCK_CENTER, AUI_DOCK_NONE]:
+ if drop.IsFloatable():
+ drop.Float()
+
+ return self.ProcessDockResult(target, drop)
+
+ # calculate the offset from where the dock begins
+ # to the point where the user dropped the pane
+ dockDropOffset = 0
+ if dock.IsHorizontal():
+ dockDropOffset = pt.x - dock.rect.x - offset.x
+ else:
+ dockDropOffset = pt.y - dock.rect.y - offset.y
+
+ drop.Dock().Direction(dock.dock_direction).Layer(dock.dock_layer). \
+ Row(dock.dock_row).Position(dockDropOffset)
+
+ if (pt.y <= dock.rect.GetTop() + 2 and dock.IsHorizontal()) or \
+ (pt.x <= dock.rect.GetLeft() + 2 and dock.IsVertical()):
+
+ if dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]:
+ row = drop.dock_row
+ panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row)
+ drop.dock_row = row
+
+ else:
+ panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row+1)
+ drop.dock_row = dock.dock_row + 1
+
+ if (pt.y >= dock.rect.GetBottom() - 2 and dock.IsHorizontal()) or \
+ (pt.x >= dock.rect.GetRight() - 2 and dock.IsVertical()):
+
+ if dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]:
+ panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row+1)
+ drop.dock_row = dock.dock_row+1
+
+ else:
+ row = drop.dock_row
+ panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row)
+ drop.dock_row = row
+
+ if not target.IsFloating() and safeRect.Contains(pt) and \
+ target.dock_direction != drop.dock_direction:
+ return False, target
+
+ return self.ProcessDockResult(target, drop)
+
+
+ def DoDropFloatingPane(self, docks, panes, target, pt):
+ """
+ Handles the situation in which the dropped pane contains a normal window.
+
+ :param `docks`: a list of :class:`AuiDockInfo` classes;
+ :param `panes`: a list of :class:`AuiPaneInfo` instances;
+ :param AuiPaneInfo `target`: the target pane containing the window;
+ :param Point `pt`: a mouse position to check for a drop operation.
+ """
+
+ screenPt = self._frame.ClientToScreen(pt)
+ paneInfo = self.PaneHitTest(panes, pt)
+
+ if paneInfo.IsMaximized():
+ return False, target
+
+ if paneInfo.window is None:
+ return False, target
+
+ # search the dock guides.
+ # reverse order to handle the center first.
+ for i in xrange(len(self._guides)-1, -1, -1):
+ guide = self._guides[i]
+
+ # do hit testing on the guide
+ dir = guide.host.HitTest(screenPt.x, screenPt.y)
+
+ if dir == -1: # point was outside of the dock guide
+ continue
+
+ if dir == wx.ALL: # target is a single dock guide
+ return self.DoDropLayer(docks, target, guide.dock_direction)
+
+ elif dir == wx.CENTER:
+
+ if not target.IsNotebookDockable():
+ continue
+ if not paneInfo.IsNotebookDockable() and not paneInfo.IsNotebookControl():
+ continue
+
+ if not paneInfo.HasNotebook():
+
+ # Add a new notebook pane with the original as a tab...
+ self.CreateNotebookBase(panes, paneInfo)
+
+ # Add new item to notebook
+ target.NotebookPage(paneInfo.notebook_id)
+
+ else:
+
+ drop_pane = False
+ drop_row = False
+
+ insert_dir = paneInfo.dock_direction
+ insert_layer = paneInfo.dock_layer
+ insert_row = paneInfo.dock_row
+ insert_pos = paneInfo.dock_pos
+
+ if insert_dir == AUI_DOCK_CENTER:
+
+ insert_layer = 0
+ if dir == wx.LEFT:
+ insert_dir = AUI_DOCK_LEFT
+ elif dir == wx.UP:
+ insert_dir = AUI_DOCK_TOP
+ elif dir == wx.RIGHT:
+ insert_dir = AUI_DOCK_RIGHT
+ elif dir == wx.DOWN:
+ insert_dir = AUI_DOCK_BOTTOM
+
+ if insert_dir == AUI_DOCK_LEFT:
+
+ drop_pane = (dir == wx.UP or dir == wx.DOWN)
+ drop_row = (dir == wx.LEFT or dir == wx.RIGHT)
+ if dir == wx.RIGHT:
+ insert_row += 1
+ elif dir == wx.DOWN:
+ insert_pos += 1
+
+ elif insert_dir == AUI_DOCK_RIGHT:
+
+ drop_pane = (dir == wx.UP or dir == wx.DOWN)
+ drop_row = (dir == wx.LEFT or dir == wx.RIGHT)
+ if dir == wx.LEFT:
+ insert_row += 1
+ elif dir == wx.DOWN:
+ insert_pos += 1
+
+ elif insert_dir == AUI_DOCK_TOP:
+
+ drop_pane = (dir == wx.LEFT or dir == wx.RIGHT)
+ drop_row = (dir == wx.UP or dir == wx.DOWN)
+ if dir == wx.DOWN:
+ insert_row += 1
+ elif dir == wx.RIGHT:
+ insert_pos += 1
+
+ elif insert_dir == AUI_DOCK_BOTTOM:
+
+ drop_pane = (dir == wx.LEFT or dir == wx.RIGHT)
+ drop_row = (dir == wx.UP or dir == wx.DOWN)
+ if dir == wx.UP:
+ insert_row += 1
+ elif dir == wx.RIGHT:
+ insert_pos += 1
+
+ if paneInfo.dock_direction == AUI_DOCK_CENTER:
+ insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1
+
+ if drop_pane:
+ return self.DoDropPane(panes, target, insert_dir, insert_layer, insert_row, insert_pos)
+
+ if drop_row:
+ return self.DoDropRow(panes, target, insert_dir, insert_layer, insert_row)
+
+ return True, target
+
+ return False, target
+
+
+ def DoDropNonFloatingPane(self, docks, panes, target, pt):
+ """
+ Handles the situation in which the dropped pane is not floating.
+
+ :param `docks`: a list of :class:`AuiDockInfo` classes;
+ :param `panes`: a list of :class:`AuiPaneInfo` instances;
+ :param AuiPaneInfo `target`: the target pane containing the toolbar;
+ :param Point `pt`: a mouse position to check for a drop operation.
+ """
+
+ screenPt = self._frame.ClientToScreen(pt)
+ clientSize = self._frame.GetClientSize()
+ frameRect = GetInternalFrameRect(self._frame, self._docks)
+
+ drop = self.CopyTarget(target)
+
+ # The result should always be shown
+ drop.Show()
+
+ part = self.HitTest(pt.x, pt.y)
+
+ if not part:
+ return False, target
+
+ if part.type == AuiDockUIPart.typeDockSizer:
+
+ if len(part.dock.panes) != 1:
+ return False, target
+
+ part = self.GetPanePart(part.dock.panes[0].window)
+ if not part:
+ return False, target
+
+ if not part.pane:
+ return False, target
+
+ part = self.GetPanePart(part.pane.window)
+ if not part:
+ return False, target
+
+ insert_dock_row = False
+ insert_row = part.pane.dock_row
+ insert_dir = part.pane.dock_direction
+ insert_layer = part.pane.dock_layer
+
+ direction = part.pane.dock_direction
+
+ if direction == AUI_DOCK_TOP:
+ if pt.y >= part.rect.y and pt.y < part.rect.y+auiInsertRowPixels:
+ insert_dock_row = True
+
+ elif direction == AUI_DOCK_BOTTOM:
+ if pt.y > part.rect.y+part.rect.height-auiInsertRowPixels and \
+ pt.y <= part.rect.y + part.rect.height:
+ insert_dock_row = True
+
+ elif direction == AUI_DOCK_LEFT:
+ if pt.x >= part.rect.x and pt.x < part.rect.x+auiInsertRowPixels:
+ insert_dock_row = True
+
+ elif direction == AUI_DOCK_RIGHT:
+ if pt.x > part.rect.x+part.rect.width-auiInsertRowPixels and \
+ pt.x <= part.rect.x+part.rect.width:
+ insert_dock_row = True
+
+ elif direction == AUI_DOCK_CENTER:
+
+ # "new row pixels" will be set to the default, but
+ # must never exceed 20% of the window size
+ new_row_pixels_x = auiNewRowPixels
+ new_row_pixels_y = auiNewRowPixels
+
+ if new_row_pixels_x > (part.rect.width*20)/100:
+ new_row_pixels_x = (part.rect.width*20)/100
+
+ if new_row_pixels_y > (part.rect.height*20)/100:
+ new_row_pixels_y = (part.rect.height*20)/100
+
+ # determine if the mouse pointer is in a location that
+ # will cause a new row to be inserted. The hot spot positions
+ # are along the borders of the center pane
+
+ insert_layer = 0
+ insert_dock_row = True
+ pr = part.rect
+
+ if pt.x >= pr.x and pt.x < pr.x + new_row_pixels_x:
+ insert_dir = AUI_DOCK_LEFT
+ elif pt.y >= pr.y and pt.y < pr.y + new_row_pixels_y:
+ insert_dir = AUI_DOCK_TOP
+ elif pt.x >= pr.x + pr.width - new_row_pixels_x and pt.x < pr.x + pr.width:
+ insert_dir = AUI_DOCK_RIGHT
+ elif pt.y >= pr.y+ pr.height - new_row_pixels_y and pt.y < pr.y + pr.height:
+ insert_dir = AUI_DOCK_BOTTOM
+ else:
+ return False, target
+
+ insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1
+
+ if insert_dock_row:
+
+ panes = DoInsertDockRow(panes, insert_dir, insert_layer, insert_row)
+ drop.Dock().Direction(insert_dir).Layer(insert_layer). \
+ Row(insert_row).Position(0)
+
+ return self.ProcessDockResult(target, drop)
+
+ # determine the mouse offset and the pane size, both in the
+ # direction of the dock itself, and perpendicular to the dock
+
+ if part.orientation == wx.VERTICAL:
+
+ offset = pt.y - part.rect.y
+ size = part.rect.GetHeight()
+
+ else:
+
+ offset = pt.x - part.rect.x
+ size = part.rect.GetWidth()
+
+ drop_position = part.pane.dock_pos
+
+ # if we are in the top/left part of the pane,
+ # insert the pane before the pane being hovered over
+ if offset <= size/2:
+
+ drop_position = part.pane.dock_pos
+ panes = DoInsertPane(panes,
+ part.pane.dock_direction,
+ part.pane.dock_layer,
+ part.pane.dock_row,
+ part.pane.dock_pos)
+
+ # if we are in the bottom/right part of the pane,
+ # insert the pane before the pane being hovered over
+ if offset > size/2:
+
+ drop_position = part.pane.dock_pos+1
+ panes = DoInsertPane(panes,
+ part.pane.dock_direction,
+ part.pane.dock_layer,
+ part.pane.dock_row,
+ part.pane.dock_pos+1)
+
+
+ drop.Dock(). \
+ Direction(part.dock.dock_direction). \
+ Layer(part.dock.dock_layer).Row(part.dock.dock_row). \
+ Position(drop_position)
+
+ return self.ProcessDockResult(target, drop)
+
+
+ def DoDropLayer(self, docks, target, dock_direction):
+ """
+ Handles the situation in which `target` is a single dock guide.
+
+ :param `docks`: a list of :class:`AuiDockInfo` classes;
+ :param AuiPaneInfo `target`: the target pane;
+ :param integer `dock_direction`: the docking direction.
+ """
+
+ drop = self.CopyTarget(target)
+
+ if dock_direction == AUI_DOCK_LEFT:
+ drop.Dock().Left()
+ drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_LEFT),
+ GetMaxLayer(docks, AUI_DOCK_BOTTOM)),
+ GetMaxLayer(docks, AUI_DOCK_TOP)) + 1
+
+ elif dock_direction == AUI_DOCK_TOP:
+ drop.Dock().Top()
+ drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_TOP),
+ GetMaxLayer(docks, AUI_DOCK_LEFT)),
+ GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1
+
+ elif dock_direction == AUI_DOCK_RIGHT:
+ drop.Dock().Right()
+ drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_RIGHT),
+ GetMaxLayer(docks, AUI_DOCK_TOP)),
+ GetMaxLayer(docks, AUI_DOCK_BOTTOM)) + 1
+
+ elif dock_direction == AUI_DOCK_BOTTOM:
+ drop.Dock().Bottom()
+ drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_BOTTOM),
+ GetMaxLayer(docks, AUI_DOCK_LEFT)),
+ GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1
+
+ else:
+ return False, target
+
+
+ drop.Dock().Layer(drop_new_layer)
+ return self.ProcessDockResult(target, drop)
+
+
+ def DoDropPane(self, panes, target, dock_direction, dock_layer, dock_row, dock_pos):
+ """
+ Drop a pane in the interface.
+
+ :param `panes`: a list of :class:`AuiPaneInfo` classes;
+ :param AuiPaneInfo `target`: the target pane;
+ :param integer `dock_direction`: the docking direction;
+ :param integer `dock_layer`: the docking layer;
+ :param integer `dock_row`: the docking row;
+ :param integer `dock_pos`: the docking position.
+ """
+
+ drop = self.CopyTarget(target)
+ panes = DoInsertPane(panes, dock_direction, dock_layer, dock_row, dock_pos)
+
+ drop.Dock().Direction(dock_direction).Layer(dock_layer).Row(dock_row).Position(dock_pos)
+ return self.ProcessDockResult(target, drop)
+
+
+ def DoDropRow(self, panes, target, dock_direction, dock_layer, dock_row):
+ """
+ Insert a row in the interface before dropping.
+
+ :param `panes`: a list of :class:`AuiPaneInfo` classes;
+ :param AuiPaneInfo `target`: the target pane;
+ :param integer `dock_direction`: the docking direction;
+ :param integer `dock_layer`: the docking layer;
+ :param integer `dock_row`: the docking row.
+ """
+
+ drop = self.CopyTarget(target)
+ panes = DoInsertDockRow(panes, dock_direction, dock_layer, dock_row)
+
+ drop.Dock().Direction(dock_direction).Layer(dock_layer).Row(dock_row).Position(0)
+ return self.ProcessDockResult(target, drop)
+
+
+ def ShowHint(self, rect):
+ """
+ Shows the AUI hint window.
+
+ :param Rect `rect`: the hint rect calculated in advance.
+ """
+
+ if rect == self._last_hint:
+ return
+
+ if self._agwFlags & AUI_MGR_RECTANGLE_HINT and wx.Platform != "__WXMAC__":
+
+ if self._last_hint != rect:
+ # remove the last hint rectangle
+ self._last_hint = wx.Rect(*rect)
+ self._frame.Refresh()
+ self._frame.Update()
+
+ screendc = wx.ScreenDC()
+ clip = wx.Region(1, 1, 10000, 10000)
+
+ # clip all floating windows, so we don't draw over them
+ for pane in self._panes:
+ if pane.IsFloating() and pane.frame.IsShown():
+
+ rect2 = wx.Rect(*pane.frame.GetRect())
+ if wx.Platform == "__WXGTK__":
+ # wxGTK returns the client size, not the whole frame size
+ rect2.width += 15
+ rect2.height += 35
+ rect2.Inflate(5, 5)
+
+ clip.SubtractRect(rect2)
+
+ # As we can only hide the hint by redrawing the managed window, we
+ # need to clip the region to the managed window too or we get
+ # nasty redrawn problems.
+ clip.IntersectRect(self._frame.GetRect())
+ screendc.SetClippingRegionAsRegion(clip)
+
+ stipple = PaneCreateStippleBitmap()
+ brush = wx.BrushFromBitmap(stipple)
+ screendc.SetBrush(brush)
+ screendc.SetPen(wx.TRANSPARENT_PEN)
+ screendc.DrawRectangle(rect.x, rect.y, 5, rect.height)
+ screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5)
+ screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height)
+ screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5)
+ RefreshDockingGuides(self._guides)
+
+ return
+
+ if not self._hint_window:
+ self.CreateHintWindow()
+
+ if self._hint_window:
+ self._hint_window.SetRect(rect)
+ self._hint_window.Show()
+
+ self._hint_fadeamt = self._hint_fademax
+
+ if self._agwFlags & AUI_MGR_HINT_FADE:
+ self._hint_fadeamt = 0
+ self._hint_window.SetTransparent(self._hint_fadeamt)
+
+ if self._action == actionDragFloatingPane and self._action_window:
+ self._action_window.SetFocus()
+
+ if self._hint_fadeamt != self._hint_fademax: # Only fade if we need to
+ # start fade in timer
+ self._hint_fadetimer.Start(5)
+
+ self._last_hint = wx.Rect(*rect)
+
+
+ def HideHint(self):
+ """ Hides a transparent window hint if there is one. """
+
+ # hides a transparent window hint if there is one
+ if self._hint_window:
+ self._hint_window.Hide()
+
+ self._hint_fadetimer.Stop()
+ self._last_hint = wx.Rect()
+
+
+ def IsPaneButtonVisible(self, part):
+ """
+ Returns whether a pane button in the pane caption is visible.
+
+ :param AuiDockUIPart `part`: the UI part to analyze.
+ """
+
+ captionRect = wx.Rect()
+
+ for temp_part in self._uiparts:
+ if temp_part.pane == part.pane and \
+ temp_part.type == AuiDockUIPart.typeCaption:
+ captionRect = temp_part.rect
+ break
+
+ return captionRect.ContainsRect(part.rect)
+
+
+ def DrawPaneButton(self, dc, part, pt):
+ """
+ Draws a pane button in the caption (convenience function).
+
+ :param `dc`: a :class:`DC` device context object;
+ :param AuiDockUIPart `part`: the UI part to analyze;
+ :param Point `pt`: the mouse location.
+ """
+
+ if not self.IsPaneButtonVisible(part):
+ return
+
+ state = AUI_BUTTON_STATE_NORMAL
+
+ if part.rect.Contains(pt):
+
+ if _VERSION_STRING < "2.9":
+ leftDown = wx.GetMouseState().LeftDown()
+ else:
+ leftDown = wx.GetMouseState().LeftIsDown()
+
+ if leftDown:
+ state = AUI_BUTTON_STATE_PRESSED
+ else:
+ state = AUI_BUTTON_STATE_HOVER
+
+ self._art.DrawPaneButton(dc, self._frame, part.button.button_id,
+ state, part.rect, part.pane)
+
+
+ def RefreshButton(self, part):
+ """
+ Refreshes a pane button in the caption.
+
+ :param AuiDockUIPart `part`: the UI part to analyze.
+ """
+
+ rect = wx.Rect(*part.rect)
+ rect.Inflate(2, 2)
+ self._frame.Refresh(True, rect)
+ self._frame.Update()
+
+
+ def RefreshCaptions(self):
+ """ Refreshes all pane captions. """
+
+ for part in self._uiparts:
+ if part.type == AuiDockUIPart.typeCaption:
+ self._frame.Refresh(True, part.rect)
+ self._frame.Update()
+
+
+ def CalculateHintRect(self, pane_window, pt, offset):
+ """
+ Calculates the drop hint rectangle.
+
+ The method first calls :meth:`DoDrop` to determine the exact position the pane would
+ be at were if dropped. If the pane would indeed become docked at the
+ specified drop point, the the rectangle hint will be returned in
+ screen coordinates. Otherwise, an empty rectangle is returned.
+
+ :param Window `pane_window`: it is the window pointer of the pane being dragged;
+ :param Point `pt`: is the mouse position, in client coordinates;
+ :param Point `offset`: describes the offset that the mouse is from the upper-left
+ corner of the item being dragged.
+ """
+
+ # we need to paint a hint rectangle to find out the exact hint rectangle,
+ # we will create a new temporary layout and then measure the resulting
+ # rectangle we will create a copy of the docking structures (self._docks)
+ # so that we don't modify the real thing on screen
+
+ rect = wx.Rect()
+ pane = self.GetPane(pane_window)
+
+ attrs = self.GetAttributes(pane)
+ hint = AuiPaneInfo()
+ hint = self.SetAttributes(hint, attrs)
+
+ if hint.name != "__HINT__":
+ self._oldname = hint.name
+
+ hint.name = "__HINT__"
+ hint.PaneBorder(True)
+ hint.Show()
+
+ if not hint.IsOk():
+ hint.name = self._oldname
+ return rect
+
+ docks, panes = CopyDocksAndPanes2(self._docks, self._panes)
+
+ # remove any pane already there which bears the same window
+ # this happens when you are moving a pane around in a dock
+ for ii in xrange(len(panes)):
+ if panes[ii].window == pane_window:
+ docks = RemovePaneFromDocks(docks, panes[ii])
+ panes.pop(ii)
+ break
+
+ # find out where the new pane would be
+ allow, hint = self.DoDrop(docks, panes, hint, pt, offset)
+
+ if not allow:
+ return rect
+
+ panes.append(hint)
+
+ sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False)
+
+ client_size = self._frame.GetClientSize()
+ sizer.SetDimension(0, 0, client_size.x, client_size.y)
+ sizer.Layout()
+
+ sought = "__HINT__"
+
+ # For a notebook page, actually look for the notebook itself.
+ if hint.IsNotebookPage():
+ id = hint.notebook_id
+ for pane in panes:
+ if pane.IsNotebookControl() and pane.notebook_id==id:
+ sought = pane.name
+ break
+
+ for part in uiparts:
+ if part.pane and part.pane.name == sought:
+ rect.Union(wx.RectPS(part.sizer_item.GetPosition(),
+ part.sizer_item.GetSize()))
+
+ sizer.Destroy()
+
+ # check for floating frame ...
+ if rect.IsEmpty():
+ for p in panes:
+ if p.name == sought and p.IsFloating():
+ return wx.RectPS(p.floating_pos, p.floating_size)
+
+ if rect.IsEmpty():
+ return rect
+
+ # actually show the hint rectangle on the screen
+ rect.x, rect.y = self._frame.ClientToScreen((rect.x, rect.y))
+ if self._frame.GetLayoutDirection() == wx.Layout_RightToLeft:
+ # Mirror rectangle in RTL mode
+ rect.x -= rect.GetWidth()
+
+ return rect
+
+
+ def DrawHintRect(self, pane_window, pt, offset):
+ """
+ Calculates the hint rectangle by calling :meth:`CalculateHintRect`. If there is a
+ rectangle, it shows it by calling :meth:`ShowHint`, otherwise it hides any hint
+ rectangle currently shown.
+
+ :param Window `pane_window`: it is the window pointer of the pane being dragged;
+ :param Point `pt`: is the mouse position, in client coordinates;
+ :param Point `offset`: describes the offset that the mouse is from the upper-left
+ corner of the item being dragged.
+ """
+
+ rect = self.CalculateHintRect(pane_window, pt, offset)
+
+ if rect.IsEmpty():
+ self.HideHint()
+ self._hint_rect = wx.Rect()
+ else:
+ self.ShowHint(rect)
+ self._hint_rect = wx.Rect(*rect)
+
+
+ def GetPartSizerRect(self, uiparts):
+ """
+ Returns the rectangle surrounding the specified UI parts.
+
+ :param list `uiparts`: list of :class:`AuiDockUIPart` parts.
+ """
+
+ rect = wx.Rect()
+
+ for part in self._uiparts:
+ if part.pane and part.pane.name == "__HINT__":
+ rect.Union(wx.RectPS(part.sizer_item.GetPosition(),
+ part.sizer_item.GetSize()))
+
+ return rect
+
+
+ def GetAttributes(self, pane):
+ """
+ Returns all the attributes of a :class:`AuiPaneInfo`.
+
+ :param `pane`: a :class:`AuiPaneInfo` instance.
+ """
+
+ attrs = []
+ attrs.extend([pane.window, pane.frame, pane.state, pane.dock_direction,
+ pane.dock_layer, pane.dock_pos, pane.dock_row, pane.dock_proportion,
+ pane.floating_pos, pane.floating_size, pane.best_size,
+ pane.min_size, pane.max_size, pane.caption, pane.name,
+ pane.buttons, pane.rect, pane.icon, pane.notebook_id,
+ pane.transparent, pane.snapped, pane.minimize_mode, pane.minimize_target])
+
+ return attrs
+
+
+ def SetAttributes(self, pane, attrs):
+ """
+ Sets all the attributes contained in `attrs` to a :class:`AuiPaneInfo`.
+
+ :param `pane`: a :class:`AuiPaneInfo` instance;
+ :param list `attrs`: a list of attributes.
+ """
+
+ pane.window = attrs[0]
+ pane.frame = attrs[1]
+ pane.state = attrs[2]
+ pane.dock_direction = attrs[3]
+ pane.dock_layer = attrs[4]
+ pane.dock_pos = attrs[5]
+ pane.dock_row = attrs[6]
+ pane.dock_proportion = attrs[7]
+ pane.floating_pos = attrs[8]
+ pane.floating_size = attrs[9]
+ pane.best_size = attrs[10]
+ pane.min_size = attrs[11]
+ pane.max_size = attrs[12]
+ pane.caption = attrs[13]
+ pane.name = attrs[14]
+ pane.buttons = attrs[15]
+ pane.rect = attrs[16]
+ pane.icon = attrs[17]
+ pane.notebook_id = attrs[18]
+ pane.transparent = attrs[19]
+ pane.snapped = attrs[20]
+ pane.minimize_mode = attrs[21]
+ pane.minimize_target = attrs[22]
+
+ return pane
+
+
+ def OnFloatingPaneResized(self, wnd, size):
+ """
+ Handles the resizing of a floating pane.
+
+ :param Window `wnd`: the window managed by the pane;
+ :param Size `size`: the new pane floating size.
+ """
+
+ # try to find the pane
+ pane = self.GetPane(wnd)
+ if not pane.IsOk():
+ raise Exception("Pane window not found")
+
+ if pane.frame:
+ indx = self._panes.index(pane)
+ pane.floating_pos = pane.frame.GetPosition()
+ pane.floating_size = size
+ self._panes[indx] = pane
+ if pane.IsSnappable():
+ self.SnapPane(pane, pane.floating_pos, pane.floating_size, True)
+
+
+ def OnFloatingPaneClosed(self, wnd, event):
+ """
+ Handles the close event of a floating pane.
+
+ :param Window `wnd`: the window managed by the pane;
+ :param `event`: a :class:`CloseEvent` to be processed.
+ """
+
+ # try to find the pane
+ pane = self.GetPane(wnd)
+ if not pane.IsOk():
+ raise Exception("Pane window not found")
+
+ # fire pane close event
+ e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE)
+ e.SetPane(pane)
+ e.SetCanVeto(event.CanVeto())
+ self.ProcessMgrEvent(e)
+
+ if e.GetVeto():
+ event.Veto()
+ return
+ else:
+ # close the pane, but check that it
+ # still exists in our pane array first
+ # (the event handler above might have removed it)
+
+ check = self.GetPane(wnd)
+ if check.IsOk():
+ self.ClosePane(pane)
+
+
+ def OnFloatingPaneActivated(self, wnd):
+ """
+ Handles the activation event of a floating pane.
+
+ :param Window `wnd`: the window managed by the pane.
+ """
+
+ pane = self.GetPane(wnd)
+ if not pane.IsOk():
+ raise Exception("Pane window not found")
+
+ if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE:
+ ret, self._panes = SetActivePane(self._panes, wnd)
+ self.RefreshCaptions()
+ self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, wnd, canVeto=False)
+
+
+ def OnFloatingPaneMoved(self, wnd, eventOrPt):
+ """
+ Handles the move event of a floating pane.
+
+ :param Window `wnd`: the window managed by the pane;
+ :param `eventOrPt`: a :class:`MoveEvent` to be processed or an instance of :class:`Point`.
+ """
+
+ pane = self.GetPane(wnd)
+ if not pane.IsOk():
+ raise Exception("Pane window not found")
+
+ if not pane.IsSnappable():
+ return
+
+ if isinstance(eventOrPt, wx.Point):
+ pane_pos = wx.Point(*eventOrPt)
+ else:
+ pane_pos = eventOrPt.GetPosition()
+
+ pane_size = pane.floating_size
+
+ self.SnapPane(pane, pane_pos, pane_size, False)
+
+
+ def SnapPane(self, pane, pane_pos, pane_size, toSnap=False):
+ """
+ Snaps a floating pane to one of the main frame sides.
+
+ :param `pane`: a :class:`AuiPaneInfo` instance;
+ :param Point `pane_pos`: the new pane floating position;
+ :param Size `pane_size`: the new pane floating size;
+ :param bool `toSnap`: a bool variable to check if :meth:`SnapPane` was called from
+ a move event.
+ """
+
+ if self._from_move:
+ return
+
+ managed_window = self.GetManagedWindow()
+ wnd_pos = managed_window.GetPosition()
+ wnd_size = managed_window.GetSize()
+ snapX, snapY = self._snap_limits
+
+ if not toSnap:
+ pane.snapped = 0
+ if pane.IsLeftSnappable():
+ # Check if we can snap to the left
+ diff = wnd_pos.x - (pane_pos.x + pane_size.x)
+ if -snapX <= diff <= snapX:
+ pane.snapped = wx.LEFT
+ pane.floating_pos = wx.Point(wnd_pos.x-pane_size.x, pane_pos.y)
+ elif pane.IsTopSnappable():
+ # Check if we can snap to the top
+ diff = wnd_pos.y - (pane_pos.y + pane_size.y)
+ if -snapY <= diff <= snapY:
+ pane.snapped = wx.TOP
+ pane.floating_pos = wx.Point(pane_pos.x, wnd_pos.y-pane_size.y)
+ elif pane.IsRightSnappable():
+ # Check if we can snap to the right
+ diff = pane_pos.x - (wnd_pos.x + wnd_size.x)
+ if -snapX <= diff <= snapX:
+ pane.snapped = wx.RIGHT
+ pane.floating_pos = wx.Point(wnd_pos.x + wnd_size.x, pane_pos.y)
+ elif pane.IsBottomSnappable():
+ # Check if we can snap to the bottom
+ diff = pane_pos.y - (wnd_pos.y + wnd_size.y)
+ if -snapY <= diff <= snapY:
+ pane.snapped = wx.BOTTOM
+ pane.floating_pos = wx.Point(pane_pos.x, wnd_pos.y + wnd_size.y)
+
+ self.RepositionPane(pane, wnd_pos, wnd_size)
+
+
+ def RepositionPane(self, pane, wnd_pos, wnd_size):
+ """
+ Repositions a pane after the main frame has been moved/resized.
+
+ :param `pane`: a :class:`AuiPaneInfo` instance;
+ :param Point `wnd_pos`: the main frame position;
+ :param Size `wnd_size`: the main frame size.
+ """
+
+ pane_pos = pane.floating_pos
+ pane_size = pane.floating_size
+
+ snap = pane.snapped
+ if snap == wx.LEFT:
+ floating_pos = wx.Point(wnd_pos.x - pane_size.x, pane_pos.y)
+ elif snap == wx.TOP:
+ floating_pos = wx.Point(pane_pos.x, wnd_pos.y - pane_size.y)
+ elif snap == wx.RIGHT:
+ floating_pos = wx.Point(wnd_pos.x + wnd_size.x, pane_pos.y)
+ elif snap == wx.BOTTOM:
+ floating_pos = wx.Point(pane_pos.x, wnd_pos.y + wnd_size.y)
+
+ if snap:
+ if pane_pos != floating_pos:
+ pane.floating_pos = floating_pos
+ self._from_move = True
+ pane.frame.SetPosition(pane.floating_pos)
+ self._from_move = False
+
+
+ def OnGripperClicked(self, pane_window, start, offset):
+ """
+ Handles the mouse click on the pane gripper.
+
+ :param Window `pane_window`: the window managed by the pane;
+ :param Point `start`: the mouse-click position;
+ :param Point `offset`: an offset point from the `start` position.
+ """
+
+ # try to find the pane
+ paneInfo = self.GetPane(pane_window)
+
+ if not paneInfo.IsOk():
+ raise Exception("Pane window not found")
+
+ if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE:
+ # set the caption as active
+ ret, self._panes = SetActivePane(self._panes, pane_window)
+ self.RefreshCaptions()
+ self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, pane_window, canVeto=False)
+
+ self._action_part = None
+ self._action_pane = paneInfo
+ self._action_window = pane_window
+ self._action_start = start
+ self._action_offset = offset
+ self._toolbar_action_offset = wx.Point(*self._action_offset)
+
+ self._frame.CaptureMouse()
+
+ if paneInfo.IsDocked():
+ self._action = actionClickCaption
+ else:
+ if paneInfo.IsToolbar():
+ self._action = actionDragToolbarPane
+ else:
+ self._action = actionDragFloatingPane
+
+ if paneInfo.frame:
+
+ windowPt = paneInfo.frame.GetRect().GetTopLeft()
+ originPt = paneInfo.frame.ClientToScreen(wx.Point())
+ self._action_offset += originPt - windowPt
+ self._toolbar_action_offset = wx.Point(*self._action_offset)
+
+ if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
+ paneInfo.frame.SetTransparent(150)
+
+ if paneInfo.IsToolbar():
+ self._frame.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
+
+
+ def OnRender(self, event):
+ """
+ Draws all of the pane captions, sashes, backgrounds, captions, grippers, pane borders and buttons.
+ It renders the entire user interface. It binds the ``EVT_AUI_RENDER`` event.
+
+ :param `event`: an instance of :class:`AuiManagerEvent`.
+ """
+
+ # if the frame is about to be deleted, don't bother
+ if not self._frame or self._frame.IsBeingDeleted():
+ return
+
+ if not self._frame.GetSizer():
+ return
+
+ mouse = wx.GetMouseState()
+ mousePos = wx.Point(mouse.GetX(), mouse.GetY())
+ point = self._frame.ScreenToClient(mousePos)
+ art = self._art
+
+ dc = event.GetDC()
+
+ for part in self._uiparts:
+
+ # don't draw hidden pane items or items that aren't windows
+ if part.sizer_item and ((not part.sizer_item.IsWindow() and \
+ not part.sizer_item.IsSpacer() and \
+ not part.sizer_item.IsSizer()) or \
+ not part.sizer_item.IsShown()):
+
+ continue
+
+ ptype = part.type
+
+ if ptype in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]:
+ art.DrawSash(dc, self._frame, part.orientation, part.rect)
+
+ elif ptype == AuiDockUIPart.typeBackground:
+ art.DrawBackground(dc, self._frame, part.orientation, part.rect)
+
+ elif ptype == AuiDockUIPart.typeCaption:
+ art.DrawCaption(dc, self._frame, part.pane.caption, part.rect, part.pane)
+
+ elif ptype == AuiDockUIPart.typeGripper:
+ art.DrawGripper(dc, self._frame, part.rect, part.pane)
+
+ elif ptype == AuiDockUIPart.typePaneBorder:
+ art.DrawBorder(dc, self._frame, part.rect, part.pane)
+
+ elif ptype == AuiDockUIPart.typePaneButton:
+ self.DrawPaneButton(dc, part, point)
+
+
+ def Repaint(self, dc=None):
+ """
+ Repaints the entire frame decorations (sashes, borders, buttons and so on).
+ It renders the entire user interface.
+
+ :param `dc`: if not ``None``, an instance of :class:`PaintDC`.
+ """
+
+ w, h = self._frame.GetClientSize()
+
+ # Figure out which dc to use; if one
+ # has been specified, use it, otherwise
+ # make a client dc
+ if dc is None:
+ client_dc = wx.ClientDC(self._frame)
+ dc = client_dc
+
+ # If the frame has a toolbar, the client area
+ # origin will not be (0, 0).
+ pt = self._frame.GetClientAreaOrigin()
+ if pt.x != 0 or pt.y != 0:
+ dc.SetDeviceOrigin(pt.x, pt.y)
+
+ # Render all the items
+ self.Render(dc)
+
+
+ def Render(self, dc):
+ """
+ Fires a render event, which is normally handled by :meth:`OnRender`. This allows the
+ render function to be overridden via the render event.
+
+ This can be useful for painting custom graphics in the main window.
+ Default behavior can be invoked in the overridden function by calling
+ :meth:`OnRender`.
+
+ :param `dc`: a :class:`DC` device context object.
+ """
+
+ e = AuiManagerEvent(wxEVT_AUI_RENDER)
+ e.SetManager(self)
+ e.SetDC(dc)
+ self.ProcessMgrEvent(e)
+
+
+ def OnCaptionDoubleClicked(self, pane_window):
+ """
+ Handles the mouse double click on the pane caption.
+
+ :param Window `pane_window`: the window managed by the pane.
+ """
+
+ # try to find the pane
+ paneInfo = self.GetPane(pane_window)
+ if not paneInfo.IsOk():
+ raise Exception("Pane window not found")
+
+ if not paneInfo.IsFloatable() or not paneInfo.IsDockable() or \
+ self._agwFlags & AUI_MGR_ALLOW_FLOATING == 0:
+ return
+
+ indx = self._panes.index(paneInfo)
+ win_rect = None
+
+ if paneInfo.IsFloating():
+ if paneInfo.name.startswith("__floating__"):
+ # It's a floating tab from a AuiNotebook
+ notebook = paneInfo.window.__aui_notebook__
+ notebook.ReDockPage(paneInfo)
+ self.Update()
+ return
+ else:
+
+ e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True)
+ if e.GetVeto():
+ self.HideHint()
+ ShowDockingGuides(self._guides, False)
+ return
+
+ win_rect = paneInfo.frame.GetRect()
+ paneInfo.Dock()
+ if paneInfo.IsToolbar():
+ paneInfo = self.SwitchToolBarOrientation(paneInfo)
+
+ e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False)
+
+ else:
+
+ e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, paneInfo, canVeto=True)
+ if e.GetVeto():
+ return
+
+ # float the window
+ if paneInfo.IsMaximized():
+ self.RestorePane(paneInfo)
+
+ if paneInfo.floating_pos == wx.Point(-1, -1):
+ captionSize = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
+ paneInfo.floating_pos = pane_window.GetScreenPosition()
+ paneInfo.floating_pos.y -= captionSize
+
+ paneInfo.Float()
+ e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, paneInfo, canVeto=False)
+
+ self._panes[indx] = paneInfo
+ self.Update()
+
+ if win_rect and self._agwFlags & AUI_MGR_ANIMATE_FRAMES:
+ paneInfo = self.GetPane(pane_window)
+ pane_rect = paneInfo.window.GetScreenRect()
+ self.AnimateDocking(win_rect, pane_rect)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`AuiManager`.
+
+ :param `event`: an instance of :class:`PaintEvent` to be processed.
+ """
+
+ dc = wx.PaintDC(self._frame)
+ self.Repaint(dc)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiManager`.
+
+ :param `event`: :class:`EraseEvent` to be processed.
+
+ :note: This is intentionally empty (excluding wxMAC) to reduce
+ flickering while drawing.
+ """
+
+ if wx.Platform == "__WXMAC__":
+ event.Skip()
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`SizeEvent` to be processed.
+ """
+
+ skipped = False
+ if isinstance(self._frame, AuiFloatingFrame) and self._frame.IsShownOnScreen():
+ skipped = True
+ event.Skip()
+
+ if self._frame:
+
+ self.DoFrameLayout()
+ if wx.Platform == "__WXMAC__":
+ self._frame.Refresh()
+ else:
+ self.Repaint()
+
+ if isinstance(self._frame, wx.MDIParentFrame) or isinstance(self._frame, tabmdi.AuiMDIClientWindow) \
+ or isinstance(self._frame, tabmdi.AuiMDIParentFrame):
+ # for MDI parent frames, this event must not
+ # be "skipped". In other words, the parent frame
+ # must not be allowed to resize the client window
+ # after we are finished processing sizing changes
+ return
+
+ if not skipped:
+ event.Skip()
+
+ # For the snap to screen...
+ self.OnMove(None)
+
+
+ def OnFindManager(self, event):
+ """
+ Handles the ``EVT_AUI_FIND_MANAGER`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`AuiManagerEvent` event to be processed.
+ """
+
+ # Initialize to None
+ event.SetManager(None)
+
+ if not self._frame:
+ return
+
+ # See it this window wants to overwrite
+ self._frame.ProcessEvent(event)
+
+ # if no, it must be us
+ if not event.GetManager():
+ event.SetManager(self)
+
+
+ def OnSetCursor(self, event):
+ """
+ Handles the ``wx.EVT_SET_CURSOR`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`SetCursorEvent` to be processed.
+ """
+
+ # determine cursor
+ part = self.HitTest(event.GetX(), event.GetY())
+ cursor = wx.NullCursor
+
+ if part:
+ if part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]:
+
+ if not self.CheckMovableSizer(part):
+ return
+
+ if part.orientation == wx.VERTICAL:
+ cursor = wx.StockCursor(wx.CURSOR_SIZEWE)
+ else:
+ cursor = wx.StockCursor(wx.CURSOR_SIZENS)
+
+ elif part.type == AuiDockUIPart.typeGripper:
+ cursor = wx.StockCursor(wx.CURSOR_SIZING)
+
+ event.SetCursor(cursor)
+
+
+ def UpdateButtonOnScreen(self, button_ui_part, event):
+ """
+ Updates/redraws the UI part containing a pane button.
+
+ :param AuiDockUIPart `button_ui_part`: the UI part the button belongs to;
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ hit_test = self.HitTest(*event.GetPosition())
+
+ if not hit_test or not button_ui_part:
+ return
+
+ state = AUI_BUTTON_STATE_NORMAL
+
+ if hit_test == button_ui_part:
+ if event.LeftDown():
+ state = AUI_BUTTON_STATE_PRESSED
+ else:
+ state = AUI_BUTTON_STATE_HOVER
+ else:
+ if event.LeftDown():
+ state = AUI_BUTTON_STATE_HOVER
+
+ # now repaint the button with hover state
+ cdc = wx.ClientDC(self._frame)
+
+ # if the frame has a toolbar, the client area
+ # origin will not be (0,0).
+ pt = self._frame.GetClientAreaOrigin()
+ if pt.x != 0 or pt.y != 0:
+ cdc.SetDeviceOrigin(pt.x, pt.y)
+
+ if hit_test.pane:
+ self._art.DrawPaneButton(cdc, self._frame,
+ button_ui_part.button.button_id,
+ state,
+ button_ui_part.rect, hit_test.pane)
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ part = self.HitTest(*event.GetPosition())
+
+ if not part:
+ event.Skip()
+ return
+
+ self._currentDragItem = -1
+
+ if part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]:
+
+ if not self.CheckMovableSizer(part):
+ return
+
+ self._action = actionResize
+ self._action_part = part
+ self._action_pane = None
+ self._action_rect = wx.Rect()
+ self._action_start = wx.Point(event.GetX(), event.GetY())
+ self._action_offset = wx.Point(event.GetX() - part.rect.x,
+ event.GetY() - part.rect.y)
+
+ # draw the resize hint
+ rect = wx.RectPS(self._frame.ClientToScreen(part.rect.GetPosition()),
+ part.rect.GetSize())
+
+ self._action_rect = wx.Rect(*rect)
+
+ if not AuiManager_HasLiveResize(self):
+ if wx.Platform == "__WXMAC__":
+ dc = wx.ClientDC(self._frame)
+ else:
+ dc = wx.ScreenDC()
+
+ DrawResizeHint(dc, rect)
+
+ self._frame.CaptureMouse()
+
+ elif part.type == AuiDockUIPart.typePaneButton:
+ if self.IsPaneButtonVisible(part):
+ self._action = actionClickButton
+ self._action_part = part
+ self._action_pane = None
+ self._action_start = wx.Point(*event.GetPosition())
+ self._frame.CaptureMouse()
+
+ self.RefreshButton(part)
+
+ elif part.type in [AuiDockUIPart.typeCaption, AuiDockUIPart.typeGripper]:
+
+ # if we are managing a AuiFloatingFrame window, then
+ # we are an embedded AuiManager inside the AuiFloatingFrame.
+ # We want to initiate a toolbar drag in our owner manager
+ if isinstance(part.pane.window.GetParent(), AuiFloatingFrame):
+ rootManager = GetManager(part.pane.window)
+ else:
+ rootManager = self
+
+ offset = wx.Point(event.GetX() - part.rect.x, event.GetY() - part.rect.y)
+ rootManager.OnGripperClicked(part.pane.window, event.GetPosition(), offset)
+
+ if wx.Platform != "__WXMAC__":
+ event.Skip()
+
+
+ def OnLeftDClick(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DCLICK`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ part = self.HitTest(event.GetX(), event.GetY())
+
+ if part and part.type == AuiDockUIPart.typeCaption:
+ if isinstance(part.pane.window.GetParent(), AuiFloatingFrame):
+ rootManager = GetManager(part.pane.window)
+ else:
+ rootManager = self
+
+ rootManager.OnCaptionDoubleClicked(part.pane.window)
+
+ elif part and part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]:
+ # Handles double click on AuiNotebook sashes to unsplit
+ sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
+ for child in part.cont_sizer.GetChildren():
+ if child.IsSizer():
+ win = child.GetSizer().GetContainingWindow()
+ if isinstance(win, auibook.AuiNotebook):
+ win.UnsplitDClick(part, sash_size, event.GetPosition())
+ break
+
+ event.Skip()
+
+
+ def DoEndResizeAction(self, event):
+ """
+ Ends a resize action, or for live update, resizes the sash.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ clientPt = event.GetPosition()
+ screenPt = self._frame.ClientToScreen(clientPt)
+
+ return self.RestrictResize(clientPt, screenPt, createDC=False)
+
+
+ def RestrictResize(self, clientPt, screenPt, createDC):
+ """ Common method between :meth:`DoEndResizeAction` and :meth:`OnLeftUp_Resize`. """
+
+ dock = self._action_part.dock
+ pane = self._action_part.pane
+
+ if createDC:
+ if wx.Platform == "__WXMAC__":
+ dc = wx.ClientDC(self._frame)
+ else:
+ dc = wx.ScreenDC()
+
+ DrawResizeHint(dc, self._action_rect)
+ self._action_rect = wx.Rect()
+
+ newPos = clientPt - self._action_offset
+
+ if self._action_part.type == AuiDockUIPart.typeDockSizer:
+ minPix, maxPix = self.CalculateDockSizerLimits(dock)
+ else:
+ if not self._action_part.pane:
+ return
+ minPix, maxPix = self.CalculatePaneSizerLimits(dock, pane)
+
+ if self._action_part.orientation == wx.HORIZONTAL:
+ newPos.y = Clip(newPos.y, minPix, maxPix)
+ else:
+ newPos.x = Clip(newPos.x, minPix, maxPix)
+
+ if self._action_part.type == AuiDockUIPart.typeDockSizer:
+
+ partnerDock = self.GetPartnerDock(dock)
+ sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
+ new_dock_size = 0
+ direction = dock.dock_direction
+
+ if direction == AUI_DOCK_LEFT:
+ new_dock_size = newPos.x - dock.rect.x
+
+ elif direction == AUI_DOCK_TOP:
+ new_dock_size = newPos.y - dock.rect.y
+
+ elif direction == AUI_DOCK_RIGHT:
+ new_dock_size = dock.rect.x + dock.rect.width - newPos.x - sash_size
+
+ elif direction == AUI_DOCK_BOTTOM:
+ new_dock_size = dock.rect.y + dock.rect.height - newPos.y - sash_size
+
+ deltaDockSize = new_dock_size - dock.size
+
+ if partnerDock:
+ if deltaDockSize > partnerDock.size - sash_size:
+ deltaDockSize = partnerDock.size - sash_size
+
+ partnerDock.size -= deltaDockSize
+
+ dock.size += deltaDockSize
+ self.Update()
+
+ else:
+
+ # determine the new pixel size that the user wants
+ # this will help us recalculate the pane's proportion
+ if dock.IsHorizontal():
+ oldPixsize = pane.rect.width
+ newPixsize = oldPixsize + newPos.x - self._action_part.rect.x
+
+ else:
+ oldPixsize = pane.rect.height
+ newPixsize = oldPixsize + newPos.y - self._action_part.rect.y
+
+ totalPixsize, totalProportion = self.GetTotalPixSizeAndProportion(dock)
+ partnerPane = self.GetPartnerPane(dock, pane)
+
+ # prevent division by zero
+ if totalPixsize <= 0 or totalProportion <= 0 or not partnerPane:
+ return
+
+ # adjust for the surplus
+ while (oldPixsize > 0 and totalPixsize > 10 and \
+ oldPixsize*totalProportion/totalPixsize < pane.dock_proportion):
+
+ totalPixsize -= 1
+
+ # calculate the new proportion of the pane
+
+ newProportion = newPixsize*totalProportion/totalPixsize
+ newProportion = Clip(newProportion, 1, totalProportion)
+ deltaProp = newProportion - pane.dock_proportion
+
+ if partnerPane.dock_proportion - deltaProp < 1:
+ deltaProp = partnerPane.dock_proportion - 1
+ newProportion = pane.dock_proportion + deltaProp
+
+ # borrow the space from our neighbor pane to the
+ # right or bottom (depending on orientation)
+ partnerPane.dock_proportion -= deltaProp
+ pane.dock_proportion = newProportion
+
+ self.Update()
+
+ return True
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ if self._action == actionResize:
+## self._frame.Freeze()
+ self.OnLeftUp_Resize(event)
+## self._frame.Thaw()
+
+ elif self._action == actionClickButton:
+ self.OnLeftUp_ClickButton(event)
+
+ elif self._action == actionDragFloatingPane:
+ self.OnLeftUp_DragFloatingPane(event)
+
+ elif self._action == actionDragToolbarPane:
+ self.OnLeftUp_DragToolbarPane(event)
+
+ elif self._action == actionDragMovablePane:
+ self.OnLeftUp_DragMovablePane(event)
+
+ else:
+ event.Skip()
+
+ try:
+ if self._frame.HasCapture():
+ self._frame.ReleaseMouse()
+ except wx.PyDeadObjectError:
+ pass
+
+ self._action = actionNone
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ if self._action == actionResize:
+ self.OnMotion_Resize(event)
+
+ elif self._action == actionClickCaption:
+ self.OnMotion_ClickCaption(event)
+
+ elif self._action == actionDragFloatingPane:
+ self.OnMotion_DragFloatingPane(event)
+
+ elif self._action == actionDragToolbarPane:
+ self.OnMotion_DragToolbarPane(event)
+
+ elif self._action == actionDragMovablePane:
+ self.OnMotion_DragMovablePane(event)
+
+ else:
+ self.OnMotion_Other(event)
+
+
+ def OnLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ if self._hover_button:
+ self.RefreshButton(self._hover_button)
+ self._hover_button = None
+
+
+ def OnCaptureLost(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_CAPTURE_LOST`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`MouseCaptureLostEvent` to be processed.
+ """
+
+ # cancel the operation in progress, if any
+ if self._action != actionNone:
+ self._action = actionNone
+ self.HideHint()
+
+
+ def OnHintFadeTimer(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`TimerEvent` to be processed.
+ """
+
+ if not self._hint_window or self._hint_fadeamt >= self._hint_fademax:
+ self._hint_fadetimer.Stop()
+ return
+
+ self._hint_fadeamt += 4
+ self._hint_window.SetTransparent(self._hint_fadeamt)
+
+
+ def OnMove(self, event):
+ """
+ Handles the ``wx.EVT_MOVE`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`MoveEvent` to be processed.
+ """
+
+ if event is not None:
+ event.Skip()
+
+ if isinstance(self._frame, AuiFloatingFrame) and self._frame.IsShownOnScreen():
+ return
+
+ docked, hAlign, vAlign, monitor = self._is_docked
+ if docked:
+ self.Snap()
+
+ for pane in self._panes:
+ if pane.IsSnappable():
+ if pane.IsFloating() and pane.IsShown():
+ self.SnapPane(pane, pane.floating_pos, pane.floating_size, True)
+
+
+ def OnSysColourChanged(self, event):
+ """
+ Handles the ``wx.EVT_SYS_COLOUR_CHANGED`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`SysColourChangedEvent` to be processed.
+ """
+
+ # This event is probably triggered by a theme change
+ # so we have to re-init the art provider.
+ if self._art:
+ self._art.Init()
+
+ if self._frame:
+ self.Update()
+ self._frame.Refresh()
+
+
+ def OnChildFocus(self, event):
+ """
+ Handles the ``wx.EVT_CHILD_FOCUS`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`ChildFocusEvent` to be processed.
+ """
+
+ # when a child pane has it's focus set, we should change the
+ # pane's active state to reflect this. (this is only true if
+ # active panes are allowed by the owner)
+
+ window = event.GetWindow()
+ if isinstance(window, wx.Dialog):
+ # Ignore EVT_CHILD_FOCUS events originating from dialogs not
+ # managed by AUI
+ rootManager = None
+ elif isinstance(window.GetParent(), AuiFloatingFrame):
+ rootManager = GetManager(window)
+ else:
+ rootManager = self
+
+ if rootManager:
+ rootManager.ActivatePane(window)
+
+ event.Skip()
+
+
+ def OnMotion_ClickCaption(self, event):
+ """
+ Sub-handler for the :meth:`OnMotion` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ clientPt = event.GetPosition()
+ screenPt = self._frame.ClientToScreen(clientPt)
+
+ drag_x_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_X)
+ drag_y_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_Y)
+
+ if not self._action_pane:
+ return
+
+ # we need to check if the mouse is now being dragged
+ if not (abs(clientPt.x - self._action_start.x) > drag_x_threshold or \
+ abs(clientPt.y - self._action_start.y) > drag_y_threshold):
+
+ return
+
+ # dragged -- we need to change the mouse action to 'drag'
+ if self._action_pane.IsToolbar():
+ self._action = actionDragToolbarPane
+ self._action_window = self._action_pane.window
+
+ elif self._action_pane.IsFloatable() and self._agwFlags & AUI_MGR_ALLOW_FLOATING:
+
+ e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, self._action_pane, canVeto=True)
+ if e.GetVeto():
+ return
+
+ self._action = actionDragFloatingPane
+
+ # set initial float position
+ self._action_pane.floating_pos = screenPt - self._action_offset
+
+ # float the window
+ if self._action_pane.IsMaximized():
+ self.RestorePane(self._action_pane)
+
+ self._action_pane.Hide()
+ self._action_pane.Float()
+ if wx.Platform == "__WXGTK__":
+ self._action_pane.Show()
+
+ e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, self._action_pane, canVeto=False)
+
+ if not self._action_pane.frame:
+ self.Update()
+
+ self._action_window = self._action_pane.window
+
+ # adjust action offset for window frame
+ windowPt = self._action_pane.frame.GetRect().GetTopLeft()
+ originPt = self._action_pane.frame.ClientToScreen(wx.Point())
+ self._toolbar_action_offset = originPt - windowPt
+
+ if self._agwFlags & AUI_MGR_USE_NATIVE_MINIFRAMES:
+ originPt = windowPt + wx.Point(3, 3)
+
+ self._action_offset += originPt - windowPt
+
+ # action offset is used here to make it feel "natural" to the user
+ # to drag a docked pane and suddenly have it become a floating frame.
+ # Sometimes, however, the offset where the user clicked on the docked
+ # caption is bigger than the width of the floating frame itself, so
+ # in that case we need to set the action offset to a sensible value
+ frame_size = self._action_pane.frame.GetSize()
+ if self._action_offset.x > frame_size.x * 2 / 3:
+ self._action_offset.x = frame_size.x / 2
+ if self._action_offset.y > frame_size.y * 2 / 3:
+ self._action_offset.y = frame_size.y / 2
+
+ self.OnMotion_DragFloatingPane(event)
+ if wx.Platform != "__WXGTK__":
+ self._action_pane.Show()
+
+ self.Update()
+
+ elif self._action_pane.IsMovable():
+ self._action = actionDragMovablePane
+ self._action_window = self._action_pane.window
+
+
+ def OnMotion_Resize(self, event):
+ """
+ Sub-handler for the :meth:`OnMotion` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ if AuiManager_HasLiveResize(self):
+ if self._currentDragItem != -1:
+ self._action_part = self._uiparts[self._currentDragItem]
+ else:
+ self._currentDragItem = self._uiparts.index(self._action_part)
+
+ if self._frame.HasCapture():
+ self._frame.ReleaseMouse()
+
+ self.DoEndResizeAction(event)
+ self._frame.CaptureMouse()
+ return
+
+ if not self._action_part or not self._action_part.dock or not self._action_part.orientation:
+ return
+
+ clientPt = event.GetPosition()
+ screenPt = self._frame.ClientToScreen(clientPt)
+
+ dock = self._action_part.dock
+ pos = self._action_part.rect.GetPosition()
+
+ if self._action_part.type == AuiDockUIPart.typeDockSizer:
+ minPix, maxPix = self.CalculateDockSizerLimits(dock)
+ else:
+ if not self._action_part.pane:
+ return
+
+ pane = self._action_part.pane
+ minPix, maxPix = self.CalculatePaneSizerLimits(dock, pane)
+
+ if self._action_part.orientation == wx.HORIZONTAL:
+ pos.y = Clip(clientPt.y - self._action_offset.y, minPix, maxPix)
+ else:
+ pos.x = Clip(clientPt.x - self._action_offset.x, minPix, maxPix)
+
+ hintrect = wx.RectPS(self._frame.ClientToScreen(pos), self._action_part.rect.GetSize())
+
+ if hintrect != self._action_rect:
+
+ if wx.Platform == "__WXMAC__":
+ dc = wx.ClientDC(self._frame)
+ else:
+ dc = wx.ScreenDC()
+
+ DrawResizeHint(dc, self._action_rect)
+ DrawResizeHint(dc, hintrect)
+ self._action_rect = wx.Rect(*hintrect)
+
+
+ def OnLeftUp_Resize(self, event):
+ """
+ Sub-handler for the :meth:`OnLeftUp` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ if self._currentDragItem != -1 and AuiManager_HasLiveResize(self):
+ self._action_part = self._uiparts[self._currentDragItem]
+
+ if self._frame.HasCapture():
+ self._frame.ReleaseMouse()
+
+ self.DoEndResizeAction(event)
+ self._currentDragItem = -1
+ return
+
+ if not self._action_part or not self._action_part.dock:
+ return
+
+ clientPt = event.GetPosition()
+ screenPt = self._frame.ClientToScreen(clientPt)
+
+ return self.RestrictResize(clientPt, screenPt, createDC=True)
+
+
+ def OnLeftUp_ClickButton(self, event):
+ """
+ Sub-handler for the :meth:`OnLeftUp` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ self._hover_button = None
+
+ if self._action_part:
+ self.RefreshButton(self._action_part)
+
+ # make sure we're still over the item that was originally clicked
+ if self._action_part == self.HitTest(*event.GetPosition()):
+
+ # fire button-click event
+ e = AuiManagerEvent(wxEVT_AUI_PANE_BUTTON)
+ e.SetManager(self)
+ e.SetPane(self._action_part.pane)
+ e.SetButton(self._action_part.button.button_id)
+ self.ProcessMgrEvent(e)
+
+
+ def CheckPaneMove(self, pane):
+ """
+ Checks if a pane has moved by a visible amount.
+
+ :param `pane`: an instance of :class:`AuiPaneInfo`.
+ """
+
+ win_rect = pane.frame.GetRect()
+ win_rect.x, win_rect.y = pane.floating_pos
+
+ if win_rect == self._last_rect:
+ return False
+
+ # skip the first move event
+ if self._last_rect.IsEmpty():
+ self._last_rect = wx.Rect(*win_rect)
+ return False
+
+ # skip if moving too fast to avoid massive redraws and
+ # jumping hint windows
+ if abs(win_rect.x - self._last_rect.x) > 10 or \
+ abs(win_rect.y - self._last_rect.y) > 10:
+ self._last_rect = wx.Rect(*win_rect)
+ return False
+
+ return True
+
+
+ def OnMotion_DragFloatingPane(self, eventOrPt):
+ """
+ Sub-handler for the :meth:`OnMotion` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ isPoint = False
+ if isinstance(eventOrPt, wx.Point):
+ clientPt = self._frame.ScreenToClient(eventOrPt)
+ screenPt = wx.Point(*eventOrPt)
+ isPoint = True
+ else:
+ clientPt = eventOrPt.GetPosition()
+ screenPt = self._frame.ClientToScreen(clientPt)
+
+ framePos = wx.Point()
+
+ # try to find the pane
+ pane = self.GetPane(self._action_window)
+ if not pane.IsOk():
+ raise Exception("Pane window not found")
+
+ # update floating position
+ if pane.IsFloating():
+ diff = pane.floating_pos - (screenPt - self._action_offset)
+ pane.floating_pos = screenPt - self._action_offset
+
+ framePos = pane.floating_pos
+
+ # Move the pane window
+ if pane.frame:
+
+ if diff.x != 0 or diff.y != 0:
+ if wx.Platform == "__WXMSW__" and (self._agwFlags & AUI_MGR_TRANSPARENT_DRAG) == 0: # and not self.CheckPaneMove(pane):
+ # return
+ # HACK: Terrible hack on wxMSW (!)
+ pane.frame.SetTransparent(254)
+
+ self._from_move = True
+ pane.frame.Move(pane.floating_pos)
+ self._from_move = False
+
+ if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
+ pane.frame.SetTransparent(150)
+
+ # calculate the offset from the upper left-hand corner
+ # of the frame to the mouse pointer
+ action_offset = screenPt - framePos
+
+ # is the pane dockable?
+ if not self.CanDockPanel(pane):
+ self.HideHint()
+ ShowDockingGuides(self._guides, False)
+ return
+
+ for paneInfo in self._panes:
+
+ if not paneInfo.IsDocked() or not paneInfo.IsShown():
+ continue
+ if paneInfo.IsToolbar() or paneInfo.IsNotebookControl():
+ continue
+ if paneInfo.IsMaximized():
+ continue
+
+ if paneInfo.IsNotebookPage():
+
+ notebookRoot = GetNotebookRoot(self._panes, paneInfo.notebook_id)
+
+ if not notebookRoot or not notebookRoot.IsDocked():
+ continue
+
+ rc = paneInfo.window.GetScreenRect()
+ if rc.Contains(screenPt):
+ if rc.height < 20 or rc.width < 20:
+ return
+
+ self.UpdateDockingGuides(paneInfo)
+ ShowDockingGuides(self._guides, True)
+ break
+
+ self.DrawHintRect(pane.window, clientPt, action_offset)
+
+
+ def OnMotion_DragMovablePane(self, eventOrPt):
+ """
+ Sub-handler for the :meth:`OnMotion` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ # Try to find the pane.
+ pane = self.GetPane(self._action_window)
+ if not pane.IsOk():
+ raise Exception("Pane window not found")
+
+ # Draw a hint for where the window will be moved.
+ if isinstance(eventOrPt, wx.Point):
+ pt = wx.Point(*eventOrPt)
+ else:
+ pt = eventOrPt.GetPosition()
+
+ self.DrawHintRect(self._action_window, pt, wx.Point(0, 0))
+
+ # Reduces flicker.
+ self._frame.Update()
+
+
+ def OnLeftUp_DragFloatingPane(self, eventOrPt):
+ """
+ Sub-handler for the :meth:`OnLeftUp` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ if isinstance(eventOrPt, wx.Point):
+ clientPt = self._frame.ScreenToClient(eventOrPt)
+ screenPt = wx.Point(*eventOrPt)
+ else:
+ clientPt = eventOrPt.GetPosition()
+ screenPt = self._frame.ClientToScreen(clientPt)
+
+ # try to find the pane
+ paneInfo = self.GetPane(self._action_window)
+ if not paneInfo.IsOk():
+ raise Exception("Pane window not found")
+
+ ret = False
+
+ if paneInfo.frame:
+
+ # calculate the offset from the upper left-hand corner
+ # of the frame to the mouse pointer
+ framePos = paneInfo.frame.GetPosition()
+ action_offset = screenPt - framePos
+
+ # is the pane dockable?
+ if self.CanDockPanel(paneInfo):
+ # do the drop calculation
+ indx = self._panes.index(paneInfo)
+ ret, paneInfo = self.DoDrop(self._docks, self._panes, paneInfo, clientPt, action_offset)
+
+ if ret:
+ e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True)
+ if e.GetVeto():
+ self.HideHint()
+ ShowDockingGuides(self._guides, False)
+ return
+
+ e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False)
+
+ if self._agwFlags & AUI_MGR_SMOOTH_DOCKING:
+ self.SmoothDock(paneInfo)
+
+ self._panes[indx] = paneInfo
+
+ # if the pane is still floating, update it's floating
+ # position (that we store)
+ if paneInfo.IsFloating():
+ paneInfo.floating_pos = paneInfo.frame.GetPosition()
+ if paneInfo.frame._transparent != paneInfo.transparent or self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
+ paneInfo.frame.SetTransparent(paneInfo.transparent)
+ paneInfo.frame._transparent = paneInfo.transparent
+
+ elif self._has_maximized:
+ self.RestoreMaximizedPane()
+
+ # reorder for dropping to a new notebook
+ # (caution: this code breaks the reference!)
+ tempPaneInfo = self.CopyTarget(paneInfo)
+ self._panes.remove(paneInfo)
+ self._panes.append(tempPaneInfo)
+
+ if ret:
+ self.Update()
+
+ if tempPaneInfo.IsFloating():
+ self.SnapPane(tempPaneInfo, tempPaneInfo.floating_pos, tempPaneInfo.floating_size, False)
+
+ self.HideHint()
+ ShowDockingGuides(self._guides, False)
+
+
+ def OnLeftUp_DragMovablePane(self, event):
+ """
+ Sub-handler for the :meth:`OnLeftUp` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ # Try to find the pane.
+ paneInfo = self.GetPane(self._action_window)
+ if not paneInfo.IsOk():
+ raise Exception("Pane window not found")
+
+ # Hide the hint as it is no longer needed.
+ self.HideHint()
+
+ # is the pane dockable?
+ if self.CanDockPanel(paneInfo):
+ # Move the pane to new position.
+ pt = event.GetPosition()
+ # do the drop calculation
+ indx = self._panes.index(paneInfo)
+ ret, paneInfo = self.DoDrop(self._docks, self._panes, paneInfo, pt, wx.Point(0,0))
+
+ if ret:
+ e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True)
+ if e.GetVeto():
+ self.HideHint()
+ ShowDockingGuides(self._guides, False)
+ return
+
+ e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False)
+
+ if self._agwFlags & AUI_MGR_SMOOTH_DOCKING:
+ self.SmoothDock(paneInfo)
+
+ self._panes[indx] = paneInfo
+
+ if ret:
+ # Update the layout to realize new position and e.g. form notebooks if needed.
+ self.Update()
+
+ if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE:
+ # Ensure active before doing actual display.
+ ret, self._panes = SetActivePane(self._panes, paneInfo.window)
+
+ # Make changes visible to user.
+ self.Repaint()
+
+ # Cancel the action and release the mouse.
+ self._action = actionNone
+ self._frame.ReleaseMouse()
+ self._action_window = None
+
+
+ def OnMotion_DragToolbarPane(self, eventOrPt):
+ """
+ Sub-handler for the :meth:`OnMotion` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ isPoint = False
+ if isinstance(eventOrPt, wx.Point):
+ clientPt = self._frame.ScreenToClient(eventOrPt)
+ screenPt = wx.Point(*eventOrPt)
+ isPoint = True
+ else:
+ clientPt = eventOrPt.GetPosition()
+ screenPt = self._frame.ClientToScreen(clientPt)
+
+ pane = self.GetPane(self._action_window)
+ if not pane.IsOk():
+ raise Exception("Pane window not found")
+
+ pane.state |= AuiPaneInfo.actionPane
+ indx = self._panes.index(pane)
+
+ ret = False
+ wasFloating = pane.IsFloating()
+ # is the pane dockable?
+ if self.CanDockPanel(pane):
+ # do the drop calculation
+ ret, pane = self.DoDrop(self._docks, self._panes, pane, clientPt, self._action_offset)
+
+ # update floating position
+ if pane.IsFloating():
+ pane.floating_pos = screenPt - self._toolbar_action_offset
+
+ # move the pane window
+ if pane.frame:
+ if wx.Platform == "__WXMSW__" and (self._agwFlags & AUI_MGR_TRANSPARENT_DRAG) == 0: # and not self.CheckPaneMove(pane):
+ # return
+ # HACK: Terrible hack on wxMSW (!)
+ pane.frame.SetTransparent(254)
+
+ self._from_move = True
+ pane.frame.Move(pane.floating_pos)
+ self._from_move = False
+
+ if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
+ pane.frame.SetTransparent(150)
+
+ self._panes[indx] = pane
+ if ret and wasFloating != pane.IsFloating() or (ret and not wasFloating):
+ wx.CallAfter(self.Update)
+
+ # when release the button out of the window.
+ # TODO: a better fix is needed.
+
+ if _VERSION_STRING < "2.9":
+ leftDown = wx.GetMouseState().LeftDown()
+ else:
+ leftDown = wx.GetMouseState().LeftIsDown()
+
+ if not leftDown:
+ self._action = actionNone
+ self.OnLeftUp_DragToolbarPane(eventOrPt)
+
+
+ def OnMotion_Other(self, event):
+ """
+ Sub-handler for the :meth:`OnMotion` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ part = self.HitTest(*event.GetPosition())
+
+ if part and part.type == AuiDockUIPart.typePaneButton \
+ and self.IsPaneButtonVisible(part):
+ if part != self._hover_button:
+
+ if self._hover_button:
+ self.RefreshButton(self._hover_button)
+
+ self._hover_button = part
+ self.RefreshButton(part)
+
+ else:
+
+ if self._hover_button:
+ self.RefreshButton(self._hover_button)
+ else:
+ event.Skip()
+
+ self._hover_button = None
+
+
+ def OnLeftUp_DragToolbarPane(self, eventOrPt):
+ """
+ Sub-handler for the :meth:`OnLeftUp` event.
+
+ :param `event`: a :class:`MouseEvent` to be processed.
+ """
+
+ isPoint = False
+ if isinstance(eventOrPt, wx.Point):
+ clientPt = self._frame.ScreenToClient(eventOrPt)
+ screenPt = wx.Point(*eventOrPt)
+ isPoint = True
+ else:
+ clientPt = eventOrPt.GetPosition()
+ screenPt = self._frame.ClientToScreen(clientPt)
+
+ # try to find the pane
+ pane = self.GetPane(self._action_window)
+ if not pane.IsOk():
+ raise Exception("Pane window not found")
+
+ if pane.IsFloating():
+ pane.floating_pos = pane.frame.GetPosition()
+ if pane.frame._transparent != pane.transparent or self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
+ pane.frame.SetTransparent(pane.transparent)
+ pane.frame._transparent = pane.transparent
+
+ # save the new positions
+ docks = FindDocks(self._docks, pane.dock_direction, pane.dock_layer, pane.dock_row)
+ if len(docks) == 1:
+ dock = docks[0]
+ pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock)
+
+ for i in xrange(len(dock.panes)):
+ dock.panes[i].dock_pos = pane_positions[i]
+
+ pane.state &= ~AuiPaneInfo.actionPane
+ self.Update()
+
+
+ def OnPaneButton(self, event):
+ """
+ Handles the ``EVT_AUI_PANE_BUTTON`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`AuiManagerEvent` event to be processed.
+ """
+
+ if not event.pane:
+ raise Exception("Pane Info passed to AuiManager.OnPaneButton must be non-null")
+
+ pane = event.pane
+
+ if event.button == AUI_BUTTON_CLOSE:
+
+ if isinstance(pane.window.GetParent(), AuiFloatingFrame):
+ rootManager = GetManager(pane.window)
+ else:
+ rootManager = self
+
+ if rootManager != self:
+ self._frame.Close()
+ return
+
+ # fire pane close event
+ e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE)
+ e.SetManager(self)
+ e.SetPane(event.pane)
+ self.ProcessMgrEvent(e)
+
+ if not e.GetVeto():
+
+ # close the pane, but check that it
+ # still exists in our pane array first
+ # (the event handler above might have removed it)
+
+ check = self.GetPane(pane.window)
+ if check.IsOk():
+ self.ClosePane(pane)
+
+ self.Update()
+
+ # mn this performs the minimizing of a pane
+ elif event.button == AUI_BUTTON_MINIMIZE:
+ e = AuiManagerEvent(wxEVT_AUI_PANE_MINIMIZE)
+ e.SetManager(self)
+ e.SetPane(event.pane)
+ self.ProcessMgrEvent(e)
+
+ if not e.GetVeto():
+ self.MinimizePane(pane)
+
+ elif event.button == AUI_BUTTON_MAXIMIZE_RESTORE and not pane.IsMaximized():
+
+ # fire pane close event
+ e = AuiManagerEvent(wxEVT_AUI_PANE_MAXIMIZE)
+ e.SetManager(self)
+ e.SetPane(event.pane)
+ self.ProcessMgrEvent(e)
+
+ if not e.GetVeto():
+
+ self.MaximizePane(pane)
+ self.Update()
+
+ elif event.button == AUI_BUTTON_MAXIMIZE_RESTORE and pane.IsMaximized():
+
+ # fire pane close event
+ e = AuiManagerEvent(wxEVT_AUI_PANE_RESTORE)
+ e.SetManager(self)
+ e.SetPane(event.pane)
+ self.ProcessMgrEvent(e)
+
+ if not e.GetVeto():
+
+ self.RestorePane(pane)
+ self.Update()
+
+ elif event.button == AUI_BUTTON_PIN:
+
+ if self._agwFlags & AUI_MGR_ALLOW_FLOATING and pane.IsFloatable():
+ e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, pane, canVeto=True)
+ if e.GetVeto():
+ return
+
+ pane.Float()
+ e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, pane, canVeto=False)
+
+ self.Update()
+
+
+ def MinimizePane(self, paneInfo, mgrUpdate=True):
+ """
+ Minimizes a pane in a newly and automatically created :class:`~lib.agw.aui.auibar.AuiToolBar`.
+
+ Clicking on the minimize button causes a new :class:`~lib.agw.aui.auibar.AuiToolBar` to be created
+ and added to the frame manager (currently the implementation is such that
+ panes at West will have a toolbar at the right, panes at South will have
+ toolbars at the bottom etc...) and the pane is hidden in the manager.
+
+ Clicking on the restore button on the newly created toolbar will result in the
+ toolbar being removed and the original pane being restored.
+
+ :param `paneInfo`: a :class:`AuiPaneInfo` instance for the pane to be minimized;
+ :param bool `mgrUpdate`: ``True`` to call :meth:`Update` to realize the new layout,
+ ``False`` otherwise.
+
+ .. note::
+
+ The `mgrUpdate` parameter is currently only used while loading perspectives using
+ :meth:`LoadPerspective`, as minimized panes were not correctly taken into account before.
+
+ """
+
+ if not paneInfo.IsToolbar():
+
+ if paneInfo.IsMinimized() and mgrUpdate:
+ # We are already minimized
+ return
+
+ # Basically the idea is this.
+ #
+ # 1) create a toolbar, with a restore button
+ #
+ # 2) place the new toolbar in the toolbar area representative of the location of the pane
+ # (NORTH/SOUTH/EAST/WEST, central area always to the right)
+ #
+ # 3) Hide the minimizing pane
+
+ # personalize the toolbar style
+
+ tbStyle = AUI_TB_DEFAULT_STYLE
+ posMask = paneInfo.minimize_mode & AUI_MINIMIZE_POS_MASK
+ captMask = paneInfo.minimize_mode & AUI_MINIMIZE_CAPT_MASK
+ dockDirection = paneInfo.dock_direction
+ if captMask != 0:
+ tbStyle |= AUI_TB_TEXT
+
+ if posMask == AUI_MINIMIZE_POS_TOOLBAR:
+ minimize_toolbar = self.GetPane(paneInfo.minimize_target)
+ if not minimize_toolbar.IsOk():
+ posMask = AUI_MINIMIZE_POS_SMART
+ if paneInfo.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]:
+ tbStyle |= AUI_TB_HORZ_LAYOUT
+
+ elif paneInfo.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER]:
+ tbStyle |= AUI_TB_VERTICAL
+ if captMask == AUI_MINIMIZE_CAPT_SMART:
+ tbStyle |= AUI_TB_CLOCKWISE
+ else:
+ minimize_toolbar = minimize_toolbar.window
+
+ elif posMask == AUI_MINIMIZE_POS_SMART:
+ if paneInfo.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]:
+ tbStyle |= AUI_TB_HORZ_LAYOUT
+
+ elif paneInfo.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER]:
+ tbStyle |= AUI_TB_VERTICAL
+ if captMask == AUI_MINIMIZE_CAPT_SMART:
+ tbStyle |= AUI_TB_CLOCKWISE
+
+ elif posMask in [AUI_MINIMIZE_POS_TOP, AUI_MINIMIZE_POS_BOTTOM]:
+ tbStyle |= AUI_TB_HORZ_LAYOUT
+ if posMask == AUI_MINIMIZE_POS_TOP:
+ dockDirection = AUI_DOCK_TOP
+ else:
+ dockDirection = AUI_DOCK_BOTTOM
+
+ else:
+ tbStyle |= AUI_TB_VERTICAL
+ if captMask == AUI_MINIMIZE_CAPT_SMART:
+ tbStyle |= AUI_TB_CLOCKWISE
+ if posMask == AUI_MINIMIZE_POS_LEFT:
+ dockDirection = AUI_DOCK_LEFT
+ elif posMask == AUI_MINIMIZE_POS_RIGHT:
+ dockDirection = AUI_DOCK_RIGHT
+ elif posMask == AUI_MINIMIZE_POS_BOTTOM:
+ dockDirection = AUI_DOCK_BOTTOM
+
+ # Create a new toolbar
+ # give it the same name as the minimized pane with _min appended
+
+ win_rect = paneInfo.window.GetScreenRect()
+
+ if posMask != AUI_MINIMIZE_POS_TOOLBAR:
+ minimize_toolbar = auibar.AuiToolBar(self.GetManagedWindow(), agwStyle=tbStyle)
+ minimize_toolbar.Hide()
+ minimize_toolbar.SetToolBitmapSize(wx.Size(16, 16))
+
+ if paneInfo.icon and paneInfo.icon.IsOk():
+ restore_bitmap = paneInfo.icon
+ else:
+ restore_bitmap = self._art._restore_bitmap
+
+ if posMask == AUI_MINIMIZE_POS_TOOLBAR:
+ xsize, ysize = minimize_toolbar.GetToolBitmapSize()
+ if xsize != restore_bitmap.GetWidth():
+ img = restore_bitmap.ConvertToImage()
+ img.Rescale(xsize, ysize, wx.IMAGE_QUALITY_HIGH)
+ restore_bitmap = img.ConvertToBitmap()
+
+ target = None
+ if posMask == AUI_MINIMIZE_POS_TOOLBAR:
+ target = paneInfo.name
+
+ minimize_toolbar.AddSimpleTool(ID_RESTORE_FRAME, paneInfo.caption, restore_bitmap,
+ _(u"Restore %s")%paneInfo.caption, target=target)
+ minimize_toolbar.SetAuiManager(self)
+ minimize_toolbar.Realize()
+ toolpanelname = paneInfo.name + "_min"
+
+ if paneInfo.IsMaximized():
+ paneInfo.SetFlag(paneInfo.wasMaximized, True)
+
+ if posMask != AUI_MINIMIZE_POS_TOOLBAR:
+
+ if dockDirection == AUI_DOCK_TOP:
+ self.AddPane(minimize_toolbar, AuiPaneInfo(). \
+ Name(toolpanelname).Caption(paneInfo.caption). \
+ ToolbarPane().Top().BottomDockable(False). \
+ LeftDockable(False).RightDockable(False).DestroyOnClose())
+
+ elif dockDirection == AUI_DOCK_BOTTOM:
+ self.AddPane(minimize_toolbar, AuiPaneInfo(). \
+ Name(toolpanelname).Caption(paneInfo.caption). \
+ ToolbarPane().Bottom().TopDockable(False). \
+ LeftDockable(False).RightDockable(False).DestroyOnClose())
+
+ elif dockDirection == AUI_DOCK_LEFT:
+ self.AddPane(minimize_toolbar, AuiPaneInfo(). \
+ Name(toolpanelname).Caption(paneInfo.caption). \
+ ToolbarPane().Left().TopDockable(False). \
+ BottomDockable(False).RightDockable(False).DestroyOnClose())
+
+ elif dockDirection in [AUI_DOCK_RIGHT, AUI_DOCK_CENTER]:
+ self.AddPane(minimize_toolbar, AuiPaneInfo(). \
+ Name(toolpanelname).Caption(paneInfo.caption). \
+ ToolbarPane().Right().TopDockable(False). \
+ LeftDockable(False).BottomDockable(False).DestroyOnClose())
+
+ arr = FindDocks(self._docks, paneInfo.dock_direction, paneInfo.dock_layer, paneInfo.dock_row)
+
+ if arr:
+ dock = arr[0]
+ paneInfo.previousDockSize = dock.size
+
+ paneInfo.previousDockPos = paneInfo.dock_pos
+
+ # mark ourselves minimized
+ paneInfo.Minimize()
+ paneInfo.Show(False)
+ self._has_minimized = True
+ # last, hide the window
+ if paneInfo.window and paneInfo.window.IsShown():
+ paneInfo.window.Show(False)
+
+ minimize_toolbar.Show()
+
+ if mgrUpdate:
+ self.Update()
+ if self._agwFlags & AUI_MGR_ANIMATE_FRAMES:
+ self.AnimateDocking(win_rect, minimize_toolbar.GetScreenRect())
+
+
+ def OnRestoreMinimizedPane(self, event):
+ """
+ Handles the ``EVT_AUI_PANE_MIN_RESTORE`` event for :class:`AuiManager`.
+
+ :param `event`: an instance of :class:`AuiManagerEvent` to be processed.
+ """
+
+ self.RestoreMinimizedPane(event.pane)
+
+
+ def OnPaneDocked(self, event):
+ """
+ Handles the ``EVT_AUI_PANE_DOCKED`` event for :class:`AuiManager`.
+
+ :param `event`: an instance of :class:`AuiManagerEvent` to be processed.
+ """
+
+ event.Skip()
+ self.RemoveAutoNBCaption(event.GetPane())
+
+
+ def CreateNotebookBase(self, panes, paneInfo):
+ """
+ Creates an auto-notebook base from a pane, and then add that pane as a page.
+
+ :param list `panes`: set of panes to append new notebook base pane to
+ :param AuiPaneInfo `paneInfo`: the pane to be converted to a new notebook.
+ """
+
+ # Create base notebook pane ...
+ nbid = len(self._notebooks)
+
+ baseInfo = AuiPaneInfo()
+ baseInfo.SetDockPos(paneInfo).NotebookControl(nbid). \
+ CloseButton(False).SetNameFromNotebookId(). \
+ NotebookDockable(False).Floatable(paneInfo.IsFloatable())
+ baseInfo.best_size = paneInfo.best_size
+ panes.append(baseInfo)
+
+ # add original pane as tab ...
+ paneInfo.NotebookPage(nbid)
+
+
+ def RemoveAutoNBCaption(self, pane):
+ """
+ Removes the caption on newly created automatic notebooks.
+
+ :param `pane`: an instance of :class:`AuiPaneInfo` (the target notebook).
+ """
+
+ if self._agwFlags & AUI_MGR_AUTONB_NO_CAPTION == 0:
+ return False
+
+ def RemoveCaption():
+ """ Sub-function used to remove the pane caption on automatic notebooks. """
+
+ if pane.HasNotebook():
+ notebook = self._notebooks[pane.notebook_id]
+ self.GetPane(notebook).CaptionVisible(False).PaneBorder(False)
+ self.Update()
+
+ # it seems the notebook isnt created by this stage, so remove
+ # the caption a moment later
+ wx.CallAfter(RemoveCaption)
+ return True
+
+
+ def RestoreMinimizedPane(self, paneInfo):
+ """
+ Restores a previously minimized pane.
+
+ :param `paneInfo`: a :class:`AuiPaneInfo` instance for the pane to be restored.
+ """
+
+ panename = paneInfo.name
+
+ if paneInfo.minimize_mode & AUI_MINIMIZE_POS_TOOLBAR:
+ pane = self.GetPane(panename)
+ hasTarget = True
+ else:
+ panename = panename[0:-4]
+ hasTarget = False
+
+ pane = self.GetPane(panename)
+ pane.SetFlag(pane.needsRestore, True)
+
+ if not pane.IsOk():
+ panename = paneInfo.name
+ pane = self.GetPane(panename)
+ paneInfo = self.GetPane(panename + "_min")
+ if not paneInfo.IsOk():
+ # Already minimized
+ return
+
+ if pane.IsOk():
+ if not pane.IsMinimized():
+ return
+
+
+ if pane.HasFlag(pane.wasMaximized):
+ self.SavePreviousDockSizes(pane)
+
+ self.ShowPane(pane.window, True)
+ pane.Show(True)
+ self._has_minimized = False
+ pane.SetFlag(pane.optionMinimized, False)
+
+ if hasTarget:
+ targetName = pane.minimize_target
+ toolbarPane = self.GetPane(targetName)
+ toolbar = toolbarPane.window
+ item = toolbar.FindToolByLabel(pane.caption)
+ toolbar.DeleteTool(item.id)
+ else:
+ paneInfo.window.Show(False)
+ self.DetachPane(paneInfo.window)
+ paneInfo.Show(False)
+ paneInfo.Hide()
+
+ self.Update()
+
+
+ def AnimateDocking(self, win_rect, pane_rect):
+ """
+ Animates the minimization/docking of a pane a la Eclipse, using a :class:`ScreenDC`
+ to draw a "moving docking rectangle" on the screen.
+
+ :param Rect `win_rect`: the original pane screen rectangle;
+ :param Rect `pane_rect`: the newly created toolbar/pane screen rectangle.
+
+ :note: This functionality is not available on wxMAC as this platform doesn't have
+ the ability to use :class:`ScreenDC` to draw on-screen and on Windows > Vista.
+ """
+
+ if wx.Platform == "__WXMAC__":
+ # No wx.ScreenDC on the Mac...
+ return
+ if wx.Platform == "__WXMSW__" and wx.GetOsVersion()[1] > 5:
+ # No easy way to handle this on Vista...
+ return
+
+ xstart, ystart = win_rect.x, win_rect.y
+ xend, yend = pane_rect.x, pane_rect.y
+
+ step = self.GetAnimationStep()
+
+ wstep = int(abs(win_rect.width - pane_rect.width)/step)
+ hstep = int(abs(win_rect.height - pane_rect.height)/step)
+ xstep = int(win_rect.x - pane_rect.x)/step
+ ystep = int(win_rect.y - pane_rect.y)/step
+
+ dc = wx.ScreenDC()
+ dc.SetLogicalFunction(wx.INVERT)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.LIGHT_GREY_PEN)
+
+ for i in xrange(int(step)):
+ width, height = win_rect.width - i*wstep, win_rect.height - i*hstep
+ x, y = xstart - i*xstep, ystart - i*ystep
+ new_rect = wx.Rect(x, y, width, height)
+ dc.DrawRoundedRectangleRect(new_rect, 3)
+ wx.SafeYield()
+ wx.MilliSleep(10)
+ dc.DrawRoundedRectangleRect(new_rect, 3)
+
+
+ def SmoothDock(self, paneInfo):
+ """
+ This method implements a smooth docking effect for floating panes, similar to
+ what the PyQT library does with its floating windows.
+
+ :param `paneInfo`: an instance of :class:`AuiPaneInfo`.
+
+ :note: The smooth docking effect can only be used if you set the ``AUI_MGR_SMOOTH_DOCKING``
+ style to :class:`AuiManager`.
+ """
+
+ if paneInfo.IsToolbar():
+ return
+
+ if not paneInfo.frame or self._hint_rect.IsEmpty():
+ return
+
+ hint_rect = self._hint_rect
+ win_rect = paneInfo.frame.GetScreenRect()
+
+ xstart, ystart = win_rect.x, win_rect.y
+ xend, yend = hint_rect.x, hint_rect.y
+
+ step = self.GetAnimationStep()/3
+
+ wstep = int((win_rect.width - hint_rect.width)/step)
+ hstep = int((win_rect.height - hint_rect.height)/step)
+ xstep = int((win_rect.x - hint_rect.x))/step
+ ystep = int((win_rect.y - hint_rect.y))/step
+
+ for i in xrange(int(step)):
+ width, height = win_rect.width - i*wstep, win_rect.height - i*hstep
+ x, y = xstart - i*xstep, ystart - i*ystep
+ new_rect = wx.Rect(x, y, width, height)
+ paneInfo.frame.SetRect(new_rect)
+ wx.MilliSleep(10)
+
+
+ def SetSnapLimits(self, x, y):
+ """
+ Modifies the snap limits used when snapping the `managed_window` to the screen
+ (using :meth:`SnapToScreen`) or when snapping the floating panes to one side of the
+ `managed_window` (using :meth:`SnapPane`).
+
+ To change the limit after which the `managed_window` or the floating panes are
+ automatically stickled to the screen border (or to the `managed_window` side),
+ set these two variables. Default values are 15 pixels.
+
+ :param integer `x`: the minimum horizontal distance below which the snap occurs;
+ :param integer `y`: the minimum vertical distance below which the snap occurs.
+ """
+
+ self._snap_limits = (x, y)
+ self.Snap()
+
+
+ def Snap(self):
+ """
+ Snaps the main frame to specified position on the screen.
+
+ :see: :meth:`SnapToScreen`
+ """
+
+ snap, hAlign, vAlign, monitor = self._is_docked
+ if not snap:
+ return
+
+ managed_window = self.GetManagedWindow()
+ snap_pos = self.GetSnapPosition()
+ wnd_pos = managed_window.GetPosition()
+ snapX, snapY = self._snap_limits
+
+ if abs(snap_pos.x - wnd_pos.x) < snapX and abs(snap_pos.y - wnd_pos.y) < snapY:
+ managed_window.SetPosition(snap_pos)
+
+
+ def SnapToScreen(self, snap=True, monitor=0, hAlign=wx.RIGHT, vAlign=wx.TOP):
+ """
+ Snaps the main frame to specified position on the screen.
+
+ :param bool `snap`: whether to snap the main frame or not;
+ :param integer `monitor`: the monitor display in which snapping the window;
+ :param integer `hAlign`: the horizontal alignment of the snapping position;
+ :param integer `vAlign`: the vertical alignment of the snapping position.
+ """
+
+ if not snap:
+ self._is_docked = (False, wx.RIGHT, wx.TOP, 0)
+ return
+
+ displayCount = wx.Display.GetCount()
+ if monitor > displayCount:
+ raise Exception("Invalid monitor selected: you only have %d monitors"%displayCount)
+
+ self._is_docked = (True, hAlign, vAlign, monitor)
+ self.GetManagedWindow().SetPosition(self.GetSnapPosition())
+
+
+ def GetSnapPosition(self):
+ """ Returns the main frame snapping position. """
+
+ snap, hAlign, vAlign, monitor = self._is_docked
+
+ display = wx.Display(monitor)
+ area = display.GetClientArea()
+ size = self.GetManagedWindow().GetSize()
+
+ pos = wx.Point()
+ if hAlign == wx.LEFT:
+ pos.x = area.x
+ elif hAlign == wx.CENTER:
+ pos.x = area.x + (area.width - size.x)/2
+ else:
+ pos.x = area.x + area.width - size.x
+
+ if vAlign == wx.TOP:
+ pos.y = area.y
+ elif vAlign == wx.CENTER:
+ pos.y = area.y + (area.height - size.y)/2
+ else:
+ pos.y = area.y + area.height - size.y
+
+ return pos
+
+
+ def GetAnimationStep(self):
+ """ Returns the animation step speed (a float) to use in :meth:`AnimateDocking`. """
+
+ return self._animation_step
+
+
+ def SetAnimationStep(self, step):
+ """
+ Sets the animation step speed (a float) to use in :meth:`AnimateDocking`.
+
+ :param float `step`: the animation speed.
+ """
+
+ self._animation_step = float(step)
+
+
+ def RequestUserAttention(self, pane_window):
+ """
+ Requests the user attention by intermittently highlighting the pane caption.
+
+ :param Window `pane_window`: the window managed by the pane;
+ """
+
+ # try to find the pane
+ paneInfo = self.GetPane(pane_window)
+ if not paneInfo.IsOk():
+ raise Exception("Pane window not found")
+
+ dc = wx.ClientDC(self._frame)
+
+ # if the frame is about to be deleted, don't bother
+ if not self._frame or self._frame.IsBeingDeleted():
+ return
+
+ if not self._frame.GetSizer():
+ return
+
+ for part in self._uiparts:
+ if part.pane == paneInfo:
+ self._art.RequestUserAttention(dc, self._frame, part.pane.caption, part.rect, part.pane)
+ self._frame.RefreshRect(part.rect, True)
+ break
+
+
+ def StartPreviewTimer(self, toolbar):
+ """
+ Starts a timer for sliding in and out a minimized pane.
+
+ :param `toolbar`: the :class:`~lib.agw.aui.auibar.AuiToolBar` containing the minimized pane tool.
+ """
+
+ toolbar_pane = self.GetPane(toolbar)
+ toolbar_name = toolbar_pane.name
+
+ pane_name = toolbar_name[0:-4]
+
+ self._sliding_pane = self.GetPane(pane_name)
+ self._sliding_rect = toolbar.GetScreenRect()
+ self._sliding_direction = toolbar_pane.dock_direction
+ self._sliding_frame = None
+
+ self._preview_timer.Start(1000, wx.TIMER_ONE_SHOT)
+
+
+ def StopPreviewTimer(self):
+ """ Stops a timer for sliding in and out a minimized pane. """
+
+ if self._preview_timer.IsRunning():
+ self._preview_timer.Stop()
+
+ self.SlideOut()
+ self._sliding_pane = None
+
+
+ def SlideIn(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`AuiManager`.
+
+ :param `event`: a :class:`TimerEvent` to be processed.
+
+ :note: This is used solely for sliding in and out minimized panes.
+ """
+
+ window = self._sliding_pane.window
+ self._sliding_frame = wx.MiniFrame(None, -1, title=_("Pane Preview"),
+ style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP |
+ wx.FRAME_NO_TASKBAR | wx.CAPTION)
+ window.Reparent(self._sliding_frame)
+ self._sliding_frame.SetSize((0, 0))
+ window.Show()
+ self._sliding_frame.Show()
+
+ size = window.GetBestSize()
+
+ startX, startY, stopX, stopY = GetSlidingPoints(self._sliding_rect, size, self._sliding_direction)
+
+ step = stopX/10
+ window_size = 0
+
+ for i in xrange(0, stopX, step):
+ window_size = i
+ self._sliding_frame.SetDimensions(startX, startY, window_size, stopY)
+ self._sliding_frame.Refresh()
+ self._sliding_frame.Update()
+ wx.MilliSleep(10)
+
+ self._sliding_frame.SetDimensions(startX, startY, stopX, stopY)
+ self._sliding_frame.Refresh()
+ self._sliding_frame.Update()
+
+
+ def SlideOut(self):
+ """
+ Slides out a preview of a minimized pane.
+
+ :note: This is used solely for sliding in and out minimized panes.
+ """
+
+ if not self._sliding_frame:
+ return
+
+ window = self._sliding_frame.GetChildren()[0]
+ size = window.GetBestSize()
+
+ startX, startY, stopX, stopY = GetSlidingPoints(self._sliding_rect, size, self._sliding_direction)
+
+ step = stopX/10
+ window_size = 0
+
+ for i in xrange(stopX, 0, -step):
+ window_size = i
+ self._sliding_frame.SetDimensions(startX, startY, window_size, stopY)
+ self._sliding_frame.Refresh()
+ self._sliding_frame.Update()
+ self._frame.RefreshRect(wx.Rect(startX+window_size, startY, step, stopY))
+ self._frame.Update()
+ wx.MilliSleep(10)
+
+ self._sliding_frame.SetDimensions(startX, startY, 0, stopY)
+
+ window.Hide()
+ window.Reparent(self._frame)
+
+ self._sliding_frame.Hide()
+ self._sliding_frame.Destroy()
+ self._sliding_frame = None
+ self._sliding_pane = None
+
+
+class AuiManager_DCP(AuiManager):
+ """
+ A class similar to :class:`AuiManager` but with a Dummy Center Pane (**DCP**).
+ The code for this class is still flickery due to the call to :func:`CallAfter`
+ and the double-update call.
+ """
+
+ def __init__(self, *args, **keys):
+ """ See :meth:`AuiManager.__init__` for the class construction. """
+
+ AuiManager.__init__(self, *args, **keys)
+ self.hasDummyPane = False
+
+
+ def _createDummyPane(self):
+ """ Creates a Dummy Center Pane (**DCP**). """
+
+ if self.hasDummyPane:
+ return
+
+ self.hasDummyPane = True
+ dummy = wx.Panel(self.GetManagedWindow())
+ info = AuiPaneInfo().CenterPane().NotebookDockable(True).Name('dummyCenterPane').DestroyOnClose(True)
+ self.AddPane(dummy, info)
+
+
+ def _destroyDummyPane(self):
+ """ Destroys the Dummy Center Pane (**DCP**). """
+
+ if not self.hasDummyPane:
+ return
+
+ self.hasDummyPane = False
+ self.ClosePane(self.GetPane('dummyCenterPane'))
+
+
+ def Update(self):
+ """
+ This method is called after any number of changes are made to any of the
+ managed panes. :meth:`Update` must be invoked after :meth:`AuiManager.AddPane` or
+ :meth:`AuiManager.InsertPane` are called in order to "realize" or "commit" the changes.
+
+ In addition, any number of changes may be made to :class:`AuiManager` structures
+ (retrieved with :meth:`AuiManager.GetPane`), but to realize the changes,
+ :meth:`Update` must be called. This construction allows pane flicker to
+ be avoided by updating the whole layout at one time.
+ """
+
+ AuiManager.Update(self)
+
+ # check if there's already a center pane (except our dummy pane)
+ dummyCenterPane = self.GetPane('dummyCenterPane')
+ haveCenterPane = any((pane != dummyCenterPane) and (pane.dock_direction == AUI_DOCK_CENTER) and
+ not pane.IsFloating() and pane.IsShown() for pane in self.GetAllPanes())
+ if haveCenterPane:
+ if self.hasDummyPane:
+ # there's our dummy pane and also another center pane, therefor let's remove our dummy
+ def do():
+ self._destroyDummyPane()
+ self.Update()
+ wx.CallAfter(do)
+ else:
+ # if we get here, there's no center pane, create our dummy
+ if not self.hasDummyPane:
+ self._createDummyPane()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/tabart.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/tabart.py
new file mode 100644
index 0000000..f3a1dd1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/tabart.py
@@ -0,0 +1,2809 @@
+"""
+Tab art provider code - a tab provider provides all drawing functionality to
+the :class:`~lib.agw.aui.auibook.AuiNotebook`. This allows the
+:class:`~lib.agw.aui.auibook.AuiNotebook` to have a plugable look-and-feel.
+
+By default, a :class:`~lib.agw.aui.auibook.AuiNotebook` uses an instance of this class
+called :class:`AuiDefaultTabArt` which provides bitmap art and a colour scheme that is
+adapted to the major platforms' look. You can either derive from that class to alter its
+behaviour or write a completely new tab art class.
+Call :meth:`AuiNotebook.SetArtProvider() <lib.agw.aui.auibook.AuiNotebook.SetArtProvider>`
+to make use this new tab art.
+"""
+
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "31 March 2009"
+
+
+import wx
+
+if wx.Platform == '__WXMAC__':
+ import Carbon.Appearance
+
+from aui_utilities import BitmapFromBits, StepColour, IndentPressedBitmap, ChopText
+from aui_utilities import GetBaseColour, DrawMACCloseButton, LightColour, TakeScreenShot
+from aui_utilities import CopyAttributes
+
+from aui_constants import *
+
+
+# -- GUI helper classes and functions --
+class AuiCommandCapture(wx.PyEvtHandler):
+ """ A class to handle the dropdown window menu. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ wx.PyEvtHandler.__init__(self)
+ self._last_id = 0
+
+
+ def GetCommandId(self):
+ """ Returns the event command identifier. """
+
+ return self._last_id
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more suitable
+ event handler function(s).
+
+ :param `event`: the event to process.
+
+ :note: Normally, your application would not call this function: it is called
+ in the wxPython implementation to dispatch incoming user interface events
+ to the framework (and application).
+ However, you might need to call it if implementing new functionality (such as
+ a new control) where you define new event types, as opposed to allowing the
+ user to override functions.
+
+ An instance where you might actually override the :meth:`ProcessEvent` function is where
+ you want to direct event processing to event handlers not normally noticed by
+ wxPython. For example, in the document/view architecture, documents and views
+ are potential event handlers. When an event reaches a frame, :meth:`ProcessEvent` will
+ need to be called on the associated document and view in case event handler
+ functions are associated with these objects.
+
+ The normal order of event table searching is as follows:
+
+ 1. If the object is disabled (via a call to :meth:`EvtHandler.SetEvtHandlerEnabled`) the function
+ skips to step (6).
+ 2. If the object is a :class:`Window`, :meth:`ProcessEvent` is recursively called on the window's
+ :class:`Validator`. If this returns ``True``, the function exits.
+ 3. wxWidgets `SearchEventTable` is called for this event handler. If this fails, the
+ base class table is tried, and so on until no more tables exist or an appropriate
+ function was found, in which case the function exits.
+ 4. The search is applied down the entire chain of event handlers (usually the chain
+ has a length of one). If this succeeds, the function exits.
+ 5. If the object is a :class:`Window` and the event is a :class:`CommandEvent`, :meth:`ProcessEvent` is
+ recursively applied to the parent window's event handler. If this returns ``True``,
+ the function exits.
+ 6. Finally, :meth:`ProcessEvent` is called on the :class:`App` object.
+ """
+
+ if event.GetEventType() == wx.wxEVT_COMMAND_MENU_SELECTED:
+ self._last_id = event.GetId()
+ return True
+
+ if self.GetNextHandler():
+ return self.GetNextHandler().ProcessEvent(event)
+
+ return False
+
+
+class AuiDefaultTabArt(object):
+ """
+ Tab art provider code - a tab provider provides all drawing functionality to the :class:`~lib.agw.aui.auibook.AuiNotebook`.
+ This allows the :class:`~lib.agw.aui.auibook.AuiNotebook` to have a plugable look-and-feel.
+
+ By default, a :class:`~lib.agw.aui.auibook.AuiNotebook` uses an instance of this class called
+ :class:`AuiDefaultTabArt` which provides bitmap art and a colour scheme that is adapted to the major platforms'
+ look. You can either derive from that class to alter its behaviour or write a
+ completely new tab art class. Call :meth:`AuiNotebook.SetArtProvider() <lib.agw.aui.auibook.AuiNotebook.SetArtProvider>` to make use this
+ new tab art.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ self._normal_font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._selected_font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._selected_font.SetWeight(wx.BOLD)
+ self._measuring_font = self._selected_font
+
+ self._fixed_tab_width = 100
+ self._tab_ctrl_height = 0
+ self._buttonRect = wx.Rect()
+
+ self.SetDefaultColours()
+
+ if wx.Platform == "__WXMAC__":
+ bmp_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DDKSHADOW)
+ self._active_close_bmp = DrawMACCloseButton(bmp_colour)
+ self._disabled_close_bmp = DrawMACCloseButton(wx.Colour(128, 128, 128))
+ else:
+ self._active_close_bmp = BitmapFromBits(nb_close_bits, 16, 16, wx.BLACK)
+ self._disabled_close_bmp = BitmapFromBits(nb_close_bits, 16, 16, wx.Colour(128, 128, 128))
+
+ self._hover_close_bmp = self._active_close_bmp
+ self._pressed_close_bmp = self._active_close_bmp
+
+ self._active_left_bmp = BitmapFromBits(nb_left_bits, 16, 16, wx.BLACK)
+ self._disabled_left_bmp = BitmapFromBits(nb_left_bits, 16, 16, wx.Colour(128, 128, 128))
+
+ self._active_right_bmp = BitmapFromBits(nb_right_bits, 16, 16, wx.BLACK)
+ self._disabled_right_bmp = BitmapFromBits(nb_right_bits, 16, 16, wx.Colour(128, 128, 128))
+
+ self._active_windowlist_bmp = BitmapFromBits(nb_list_bits, 16, 16, wx.BLACK)
+ self._disabled_windowlist_bmp = BitmapFromBits(nb_list_bits, 16, 16, wx.Colour(128, 128, 128))
+
+ if wx.Platform == "__WXMAC__":
+ # Get proper highlight colour for focus rectangle from the
+ # current Mac theme. kThemeBrushFocusHighlight is
+ # available on Mac OS 8.5 and higher
+ if hasattr(wx, 'MacThemeColour'):
+ c = wx.MacThemeColour(Carbon.Appearance.kThemeBrushFocusHighlight)
+ else:
+ brush = wx.Brush(wx.BLACK)
+ brush.MacSetTheme(Carbon.Appearance.kThemeBrushFocusHighlight)
+ c = brush.GetColour()
+ self._focusPen = wx.Pen(c, 2, wx.SOLID)
+ else:
+ self._focusPen = wx.Pen(wx.BLACK, 1, wx.USER_DASH)
+ self._focusPen.SetDashes([1, 1])
+ self._focusPen.SetCap(wx.CAP_BUTT)
+
+
+ def SetBaseColour(self, base_colour):
+ """
+ Sets a new base colour.
+
+ :param `base_colour`: an instance of :class:`Colour`.
+ """
+
+ self._base_colour = base_colour
+ self._base_colour_pen = wx.Pen(self._base_colour)
+ self._base_colour_brush = wx.Brush(self._base_colour)
+
+
+ def SetDefaultColours(self, base_colour=None):
+ """
+ Sets the default colours, which are calculated from the given base colour.
+
+ :param `base_colour`: an instance of :class:`Colour`. If defaulted to ``None``, a colour
+ is generated accordingly to the platform and theme.
+ """
+
+ if base_colour is None:
+ base_colour = GetBaseColour()
+
+ self.SetBaseColour( base_colour )
+ self._border_colour = StepColour(base_colour, 75)
+ self._border_pen = wx.Pen(self._border_colour)
+
+ self._background_top_colour = StepColour(self._base_colour, 90)
+ self._background_bottom_colour = StepColour(self._base_colour, 170)
+
+ self._tab_top_colour = self._base_colour
+ self._tab_bottom_colour = wx.WHITE
+ self._tab_gradient_highlight_colour = wx.WHITE
+
+ self._tab_inactive_top_colour = self._base_colour
+ self._tab_inactive_bottom_colour = StepColour(self._tab_inactive_top_colour, 160)
+
+ self._tab_text_colour = lambda page: page.text_colour
+ self._tab_disabled_text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)
+
+
+ def Clone(self):
+ """ Clones the art object. """
+
+ art = type(self)()
+ art.SetNormalFont(self.GetNormalFont())
+ art.SetSelectedFont(self.GetSelectedFont())
+ art.SetMeasuringFont(self.GetMeasuringFont())
+
+ art = CopyAttributes(art, self)
+ return art
+
+
+ def SetAGWFlags(self, agwFlags):
+ """
+ Sets the tab art flags.
+
+ :param integer `agwFlags`: a combination of the following values:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook
+ ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet.
+ ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet.
+ ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook
+ ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab
+ ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging
+ ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control
+ ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width
+ ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed
+ ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available
+ ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar
+ ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab
+ ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs
+ ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close :class:`~lib.agw.aui.auibook.AuiNotebook` tabs by mouse middle button click
+ ``AUI_NB_SUB_NOTEBOOK`` This style is used by :class:`~lib.agw.aui.framemanager.AuiManager` to create automatic AuiNotebooks
+ ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present
+ ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
+ ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items
+ ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser)
+ ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less
+ full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages
+ ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default)
+ ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs
+ ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle
+ ==================================== ==================================
+
+ """
+
+ self._agwFlags = agwFlags
+
+
+ def GetAGWFlags(self):
+ """
+ Returns the tab art flags.
+
+ :see: :meth:`~AuiDefaultTabArt.SetAGWFlags` for a list of possible return values.
+ """
+
+ return self._agwFlags
+
+
+ def SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth):
+ """
+ Sets the tab sizing information.
+
+ :param Size `tab_ctrl_size`: the size of the tab control area;
+ :param integer `tab_count`: the number of tabs;
+ :param tuple `minMaxTabWidth`: a tuple containing the minimum and maximum tab widths
+ to be used when the ``AUI_NB_TAB_FIXED_WIDTH`` style is active.
+ """
+
+ self._fixed_tab_width = 100
+ minTabWidth, maxTabWidth = minMaxTabWidth
+
+ tot_width = tab_ctrl_size.x - self.GetIndentSize() - 4
+ agwFlags = self.GetAGWFlags()
+
+ if agwFlags & AUI_NB_CLOSE_BUTTON:
+ tot_width -= self._active_close_bmp.GetWidth()
+ if agwFlags & AUI_NB_WINDOWLIST_BUTTON:
+ tot_width -= self._active_windowlist_bmp.GetWidth()
+
+ if tab_count > 0:
+ self._fixed_tab_width = tot_width/tab_count
+
+ if self._fixed_tab_width < 100:
+ self._fixed_tab_width = 100
+
+ if self._fixed_tab_width > tot_width/2:
+ self._fixed_tab_width = tot_width/2
+
+ if self._fixed_tab_width > 220:
+ self._fixed_tab_width = 220
+
+ if minTabWidth > -1:
+ self._fixed_tab_width = max(self._fixed_tab_width, minTabWidth)
+ if maxTabWidth > -1:
+ self._fixed_tab_width = min(self._fixed_tab_width, maxTabWidth)
+
+ self._tab_ctrl_height = tab_ctrl_size.y
+
+
+ def DrawBackground(self, dc, wnd, rect):
+ """
+ Draws the tab area background.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param Rect `rect`: the tab control rectangle.
+ """
+
+ self._buttonRect = wx.Rect()
+
+ # draw background
+ agwFlags = self.GetAGWFlags()
+ if agwFlags & AUI_NB_BOTTOM:
+ r = wx.Rect(rect.x, rect.y, rect.width+2, rect.height)
+
+ # TODO: else if (agwFlags & AUI_NB_LEFT)
+ # TODO: else if (agwFlags & AUI_NB_RIGHT)
+ else: #for AUI_NB_TOP
+ r = wx.Rect(rect.x, rect.y, rect.width+2, rect.height-3)
+
+ dc.GradientFillLinear(r, self._background_top_colour, self._background_bottom_colour, wx.SOUTH)
+
+ # draw base lines
+
+ dc.SetPen(self._border_pen)
+ y = rect.GetHeight()
+ w = rect.GetWidth()
+
+ if agwFlags & AUI_NB_BOTTOM:
+ dc.SetBrush(wx.Brush(self._background_bottom_colour))
+ dc.DrawRectangle(-1, 0, w+2, 4)
+
+ # TODO: else if (agwFlags & AUI_NB_LEFT)
+ # TODO: else if (agwFlags & AUI_NB_RIGHT)
+
+ else: # for AUI_NB_TOP
+ dc.SetBrush(self._base_colour_brush)
+ dc.DrawRectangle(-1, y-4, w+2, 4)
+
+
+ def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False):
+ """
+ Draws a single tab.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param `page`: the tab control page associated with the tab;
+ :param Rect `in_rect`: rectangle the tab should be confined to;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param bool `paint_control`: whether to draw the control inside a tab (if any) on a :class:`MemoryDC`.
+ """
+
+ # if the caption is empty, measure some temporary text
+ caption = page.caption
+ if not caption:
+ caption = "Xj"
+
+ dc.SetFont(self._selected_font)
+ selected_textx, selected_texty, dummy = dc.GetMultiLineTextExtent(caption)
+
+ dc.SetFont(self._normal_font)
+ normal_textx, normal_texty, dummy = dc.GetMultiLineTextExtent(caption)
+
+ control = page.control
+
+ # figure out the size of the tab
+ tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap,
+ page.active, close_button_state, control)
+
+ tab_height = self._tab_ctrl_height - 3
+ tab_width = tab_size[0]
+ tab_x = in_rect.x
+ tab_y = in_rect.y + in_rect.height - tab_height
+
+ caption = page.caption
+
+ # select pen, brush and font for the tab to be drawn
+
+ if page.active:
+
+ dc.SetFont(self._selected_font)
+ textx, texty = selected_textx, selected_texty
+
+ else:
+
+ dc.SetFont(self._normal_font)
+ textx, texty = normal_textx, normal_texty
+
+ if not page.enabled:
+ dc.SetTextForeground(self._tab_disabled_text_colour)
+ pagebitmap = page.dis_bitmap
+ else:
+ dc.SetTextForeground(self._tab_text_colour(page))
+ pagebitmap = page.bitmap
+
+ # create points that will make the tab outline
+
+ clip_width = tab_width
+ if tab_x + clip_width > in_rect.x + in_rect.width:
+ clip_width = in_rect.x + in_rect.width - tab_x
+
+ # since the above code above doesn't play well with WXDFB or WXCOCOA,
+ # we'll just use a rectangle for the clipping region for now --
+ dc.SetClippingRegion(tab_x, tab_y, clip_width+1, tab_height-3)
+
+ border_points = [wx.Point() for i in xrange(6)]
+ agwFlags = self.GetAGWFlags()
+
+ if agwFlags & AUI_NB_BOTTOM:
+
+ border_points[0] = wx.Point(tab_x, tab_y)
+ border_points[1] = wx.Point(tab_x, tab_y+tab_height-6)
+ border_points[2] = wx.Point(tab_x+2, tab_y+tab_height-4)
+ border_points[3] = wx.Point(tab_x+tab_width-2, tab_y+tab_height-4)
+ border_points[4] = wx.Point(tab_x+tab_width, tab_y+tab_height-6)
+ border_points[5] = wx.Point(tab_x+tab_width, tab_y)
+
+ else: #if (agwFlags & AUI_NB_TOP)
+
+ border_points[0] = wx.Point(tab_x, tab_y+tab_height-4)
+ border_points[1] = wx.Point(tab_x, tab_y+2)
+ border_points[2] = wx.Point(tab_x+2, tab_y)
+ border_points[3] = wx.Point(tab_x+tab_width-2, tab_y)
+ border_points[4] = wx.Point(tab_x+tab_width, tab_y+2)
+ border_points[5] = wx.Point(tab_x+tab_width, tab_y+tab_height-4)
+
+ # TODO: else if (agwFlags & AUI_NB_LEFT)
+ # TODO: else if (agwFlags & AUI_NB_RIGHT)
+
+ drawn_tab_yoff = border_points[1].y
+ drawn_tab_height = border_points[0].y - border_points[1].y
+
+ if page.active:
+
+ # draw active tab
+
+ # draw base background colour
+ r = wx.Rect(tab_x, tab_y, tab_width, tab_height)
+ dc.SetPen(self._base_colour_pen)
+ dc.SetBrush(self._base_colour_brush)
+ dc.DrawRectangle(r.x+1, r.y+1, r.width-1, r.height-4)
+
+ # this white helps fill out the gradient at the top of the tab
+ dc.SetPen( wx.Pen(self._tab_gradient_highlight_colour) )
+ dc.SetBrush( wx.Brush(self._tab_gradient_highlight_colour) )
+ dc.DrawRectangle(r.x+2, r.y+1, r.width-3, r.height-4)
+
+ # these two points help the rounded corners appear more antialiased
+ dc.SetPen(self._base_colour_pen)
+ dc.DrawPoint(r.x+2, r.y+1)
+ dc.DrawPoint(r.x+r.width-2, r.y+1)
+
+ # set rectangle down a bit for gradient drawing
+ r.SetHeight(r.GetHeight()/2)
+ r.x += 2
+ r.width -= 2
+ r.y += r.height
+ r.y -= 2
+
+ # draw gradient background
+ top_colour = self._tab_bottom_colour
+ bottom_colour = self._tab_top_colour
+ dc.GradientFillLinear(r, bottom_colour, top_colour, wx.NORTH)
+
+ else:
+
+ # draw inactive tab
+
+ r = wx.Rect(tab_x, tab_y+1, tab_width, tab_height-3)
+
+ # start the gradent up a bit and leave the inside border inset
+ # by a pixel for a 3D look. Only the top half of the inactive
+ # tab will have a slight gradient
+ r.x += 3
+ r.y += 1
+ r.width -= 4
+ r.height /= 2
+ r.height -= 1
+
+ # -- draw top gradient fill for glossy look
+ top_colour = self._tab_inactive_top_colour
+ bottom_colour = self._tab_inactive_bottom_colour
+ dc.GradientFillLinear(r, bottom_colour, top_colour, wx.NORTH)
+
+ r.y += r.height
+ r.y -= 1
+
+ # -- draw bottom fill for glossy look
+ top_colour = self._tab_inactive_bottom_colour
+ bottom_colour = self._tab_inactive_bottom_colour
+ dc.GradientFillLinear(r, top_colour, bottom_colour, wx.SOUTH)
+
+ # draw tab outline
+ dc.SetPen(self._border_pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawPolygon(border_points)
+
+ # there are two horizontal grey lines at the bottom of the tab control,
+ # this gets rid of the top one of those lines in the tab control
+ if page.active:
+
+ if agwFlags & AUI_NB_BOTTOM:
+ dc.SetPen(wx.Pen(self._background_bottom_colour))
+
+ # TODO: else if (agwFlags & AUI_NB_LEFT)
+ # TODO: else if (agwFlags & AUI_NB_RIGHT)
+ else: # for AUI_NB_TOP
+ dc.SetPen(self._base_colour_pen)
+
+ dc.DrawLine(border_points[0].x+1,
+ border_points[0].y,
+ border_points[5].x,
+ border_points[5].y)
+
+ text_offset = tab_x + 8
+ close_button_width = 0
+
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+ close_button_width = self._active_close_bmp.GetWidth()
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ text_offset += close_button_width - 5
+
+ bitmap_offset = 0
+
+ if pagebitmap.IsOk():
+
+ bitmap_offset = tab_x + 8
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT and close_button_width:
+ bitmap_offset += close_button_width - 5
+
+ # draw bitmap
+ dc.DrawBitmap(pagebitmap,
+ bitmap_offset,
+ drawn_tab_yoff + (drawn_tab_height/2) - (pagebitmap.GetHeight()/2),
+ True)
+
+ text_offset = bitmap_offset + pagebitmap.GetWidth()
+ text_offset += 3 # bitmap padding
+
+ else:
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT == 0 or not close_button_width:
+ text_offset = tab_x + 8
+
+ draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width)
+
+ ypos = drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1
+
+ offset_focus = text_offset
+
+ if control is not None:
+ try:
+ if control.GetPosition() != wx.Point(text_offset+1, ypos):
+ control.SetPosition(wx.Point(text_offset+1, ypos))
+
+ if not control.IsShown():
+ control.Show()
+
+ if paint_control:
+ bmp = TakeScreenShot(control.GetScreenRect())
+ dc.DrawBitmap(bmp, text_offset+1, ypos, True)
+
+ controlW, controlH = control.GetSize()
+ text_offset += controlW + 4
+ textx += controlW + 4
+ except wx.PyDeadObjectError:
+ pass
+
+ # draw tab text
+ rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text)
+ dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty))
+
+ # draw focus rectangle
+ if (agwFlags & AUI_NB_NO_TAB_FOCUS) == 0:
+ self.DrawFocusRectangle(dc, page, wnd, draw_text, offset_focus, bitmap_offset, drawn_tab_yoff, drawn_tab_height, rectx, recty)
+
+ out_button_rect = wx.Rect()
+
+ # draw close button if necessary
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+
+ bmp = self._disabled_close_bmp
+
+ if close_button_state == AUI_BUTTON_STATE_HOVER:
+ bmp = self._hover_close_bmp
+ elif close_button_state == AUI_BUTTON_STATE_PRESSED:
+ bmp = self._pressed_close_bmp
+
+ shift = (agwFlags & AUI_NB_BOTTOM and [1] or [0])[0]
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ rect = wx.Rect(tab_x + 4, tab_y + (tab_height - bmp.GetHeight())/2 - shift,
+ close_button_width, tab_height)
+ else:
+ rect = wx.Rect(tab_x + tab_width - close_button_width - 1,
+ tab_y + (tab_height - bmp.GetHeight())/2 - shift,
+ close_button_width, tab_height)
+
+ rect = IndentPressedBitmap(rect, close_button_state)
+ dc.DrawBitmap(bmp, rect.x, rect.y, True)
+
+ out_button_rect = rect
+
+ out_tab_rect = wx.Rect(tab_x, tab_y, tab_width, tab_height)
+
+ dc.DestroyClippingRegion()
+
+ return out_tab_rect, out_button_rect, x_extent
+
+
+ def SetCustomButton(self, bitmap_id, button_state, bmp):
+ """
+ Sets a custom bitmap for the close, left, right and window list buttons.
+
+ :param integer `bitmap_id`: the button identifier;
+ :param integer `button_state`: the button state;
+ :param Bitmap `bmp`: the custom bitmap to use for the button.
+ """
+
+ if bitmap_id == AUI_BUTTON_CLOSE:
+ if button_state == AUI_BUTTON_STATE_NORMAL:
+ self._active_close_bmp = bmp
+ self._hover_close_bmp = self._active_close_bmp
+ self._pressed_close_bmp = self._active_close_bmp
+ self._disabled_close_bmp = self._active_close_bmp
+
+ elif button_state == AUI_BUTTON_STATE_HOVER:
+ self._hover_close_bmp = bmp
+ elif button_state == AUI_BUTTON_STATE_PRESSED:
+ self._pressed_close_bmp = bmp
+ else:
+ self._disabled_close_bmp = bmp
+
+ elif bitmap_id == AUI_BUTTON_LEFT:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ self._disabled_left_bmp = bmp
+ else:
+ self._active_left_bmp = bmp
+
+ elif bitmap_id == AUI_BUTTON_RIGHT:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ self._disabled_right_bmp = bmp
+ else:
+ self._active_right_bmp = bmp
+
+ elif bitmap_id == AUI_BUTTON_WINDOWLIST:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ self._disabled_windowlist_bmp = bmp
+ else:
+ self._active_windowlist_bmp = bmp
+
+
+ def GetIndentSize(self):
+ """ Returns the tabs indent size. """
+
+ return 5
+
+
+ def GetTabSize(self, dc, wnd, caption, bitmap, active, close_button_state, control=None):
+ """
+ Returns the tab size for the given caption, bitmap and button state.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param string `caption`: the tab text caption;
+ :param Bitmap `bitmap`: the bitmap displayed on the tab;
+ :param bool `active`: whether the tab is selected or not;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param Window `control`: a :class:`Window` instance inside a tab (or ``None``).
+ """
+
+ dc.SetFont(self._measuring_font)
+ measured_textx, measured_texty, dummy = dc.GetMultiLineTextExtent(caption)
+
+ # add padding around the text
+ tab_width = measured_textx
+ tab_height = measured_texty
+
+ # if the close button is showing, add space for it
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+ tab_width += self._active_close_bmp.GetWidth() + 3
+
+ # if there's a bitmap, add space for it
+ if bitmap.IsOk():
+ tab_width += bitmap.GetWidth()
+ tab_width += 3 # right side bitmap padding
+ tab_height = max(tab_height, bitmap.GetHeight())
+
+ # add padding
+ tab_width += 16
+ tab_height += 10
+
+ agwFlags = self.GetAGWFlags()
+ if agwFlags & AUI_NB_TAB_FIXED_WIDTH:
+ tab_width = self._fixed_tab_width
+
+ if control is not None:
+ try:
+ tab_width += control.GetSize().GetWidth() + 4
+ except wx.PyDeadObjectError:
+ pass
+
+ x_extent = tab_width
+
+ return (tab_width, tab_height), x_extent
+
+
+ def DrawButton(self, dc, wnd, in_rect, button, orientation):
+ """
+ Draws a button on the tab or on the tab area, depending on the button identifier.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param Rect `in_rect`: rectangle the tab should be confined to;
+ :param `button`: an instance of the button class;
+ :param integer `orientation`: the tab orientation.
+ """
+
+ bitmap_id, button_state = button.id, button.cur_state
+
+ if bitmap_id == AUI_BUTTON_CLOSE:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ bmp = self._disabled_close_bmp
+ elif button_state & AUI_BUTTON_STATE_HOVER:
+ bmp = self._hover_close_bmp
+ elif button_state & AUI_BUTTON_STATE_PRESSED:
+ bmp = self._pressed_close_bmp
+ else:
+ bmp = self._active_close_bmp
+
+ elif bitmap_id == AUI_BUTTON_LEFT:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ bmp = self._disabled_left_bmp
+ else:
+ bmp = self._active_left_bmp
+
+ elif bitmap_id == AUI_BUTTON_RIGHT:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ bmp = self._disabled_right_bmp
+ else:
+ bmp = self._active_right_bmp
+
+ elif bitmap_id == AUI_BUTTON_WINDOWLIST:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ bmp = self._disabled_windowlist_bmp
+ else:
+ bmp = self._active_windowlist_bmp
+
+ else:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ bmp = button.dis_bitmap
+ else:
+ bmp = button.bitmap
+
+ if not bmp.IsOk():
+ return
+
+ rect = wx.Rect(*in_rect)
+
+ if orientation == wx.LEFT:
+
+ rect.SetX(in_rect.x)
+ rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2))
+ rect.SetWidth(bmp.GetWidth())
+ rect.SetHeight(bmp.GetHeight())
+
+ else:
+
+ rect = wx.Rect(in_rect.x + in_rect.width - bmp.GetWidth(),
+ ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
+ bmp.GetWidth(), bmp.GetHeight())
+
+ rect = IndentPressedBitmap(rect, button_state)
+ dc.DrawBitmap(bmp, rect.x, rect.y, True)
+
+ out_rect = rect
+
+ if bitmap_id == AUI_BUTTON_RIGHT:
+ self._buttonRect = wx.Rect(rect.x, rect.y, 30, rect.height)
+
+ return out_rect
+
+
+ def DrawFocusRectangle(self, dc, page, wnd, draw_text, text_offset, bitmap_offset, drawn_tab_yoff, drawn_tab_height, textx, texty):
+ """
+ Draws the focus rectangle on a tab.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `page`: the page associated with the tab;
+ :param `wnd`: a :class:`Window` instance object;
+ :param string `draw_text`: the text that has been drawn on the tab;
+ :param integer `text_offset`: the text offset on the tab;
+ :param integer `bitmap_offset`: the bitmap offset on the tab;
+ :param integer `drawn_tab_yoff`: the y offset of the tab text;
+ :param integer `drawn_tab_height`: the height of the tab;
+ :param integer `textx`: the x text extent;
+ :param integer `texty`: the y text extent.
+ """
+
+ if self.GetAGWFlags() & AUI_NB_NO_TAB_FOCUS:
+ return
+
+ if page.active and wx.Window.FindFocus() == wnd:
+
+ focusRectText = wx.Rect(text_offset, (drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2)),
+ textx, texty)
+
+ if page.bitmap.IsOk():
+ focusRectBitmap = wx.Rect(bitmap_offset, drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
+ page.bitmap.GetWidth(), page.bitmap.GetHeight())
+
+ if page.bitmap.IsOk() and draw_text == "":
+ focusRect = wx.Rect(*focusRectBitmap)
+ elif not page.bitmap.IsOk() and draw_text != "":
+ focusRect = wx.Rect(*focusRectText)
+ elif page.bitmap.IsOk() and draw_text != "":
+ focusRect = focusRectText.Union(focusRectBitmap)
+
+ focusRect.Inflate(2, 2)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(self._focusPen)
+ dc.DrawRoundedRectangleRect(focusRect, 2)
+
+
+ def GetBestTabCtrlSize(self, wnd, pages, required_bmp_size):
+ """
+ Returns the best tab control size.
+
+ :param `wnd`: a :class:`Window` instance object;
+ :param list `pages`: the pages associated with the tabs;
+ :param Size `required_bmp_size`: the size of the bitmap on the tabs.
+ """
+
+ dc = wx.ClientDC(wnd)
+ dc.SetFont(self._measuring_font)
+
+ # sometimes a standard bitmap size needs to be enforced, especially
+ # if some tabs have bitmaps and others don't. This is important because
+ # it prevents the tab control from resizing when tabs are added.
+
+ measure_bmp = wx.NullBitmap
+
+ if required_bmp_size.IsFullySpecified():
+ measure_bmp = wx.EmptyBitmap(required_bmp_size.x,
+ required_bmp_size.y)
+
+ max_y = 0
+
+ for page in pages:
+
+ if measure_bmp.IsOk():
+ bmp = measure_bmp
+ else:
+ bmp = page.bitmap
+
+ # we don't use the caption text because we don't
+ # want tab heights to be different in the case
+ # of a very short piece of text on one tab and a very
+ # tall piece of text on another tab
+ s, x_ext = self.GetTabSize(dc, wnd, page.caption, bmp, True, AUI_BUTTON_STATE_HIDDEN, None)
+ max_y = max(max_y, s[1])
+
+ if page.control:
+ controlW, controlH = page.control.GetSize()
+ max_y = max(max_y, controlH+4)
+
+ return max_y + 2
+
+
+ def SetNormalFont(self, font):
+ """
+ Sets the normal font for drawing tab labels.
+
+ :param Font `font`: the new font to use to draw tab labels in their normal, un-selected state.
+ """
+
+ self._normal_font = font
+
+
+ def SetSelectedFont(self, font):
+ """
+ Sets the selected tab font for drawing tab labels.
+
+ :param Font `font`: the new font to use to draw tab labels in their selected state.
+ """
+
+ self._selected_font = font
+
+
+ def SetMeasuringFont(self, font):
+ """
+ Sets the font for calculating text measurements.
+
+ :param Font `font`: the new font to use to measure tab labels text extents.
+ """
+
+ self._measuring_font = font
+
+
+ def GetNormalFont(self):
+ """ Returns the normal font for drawing tab labels. """
+
+ return self._normal_font
+
+
+ def GetSelectedFont(self):
+ """ Returns the selected tab font for drawing tab labels. """
+
+ return self._selected_font
+
+
+ def GetMeasuringFont(self):
+ """ Returns the font for calculating text measurements. """
+
+ return self._measuring_font
+
+
+ def ShowDropDown(self, wnd, pages, active_idx):
+ """
+ Shows the drop-down window menu on the tab area.
+
+ :param `wnd`: a :class:`Window` derived window instance;
+ :param list `pages`: the pages associated with the tabs;
+ :param integer `active_idx`: the active tab index.
+ """
+
+ useImages = self.GetAGWFlags() & AUI_NB_USE_IMAGES_DROPDOWN
+ menuPopup = wx.Menu()
+
+ longest = 0
+ for i, page in enumerate(pages):
+
+ caption = page.caption
+
+ # if there is no caption, make it a space. This will prevent
+ # an assert in the menu code.
+ if caption == "":
+ caption = " "
+
+ # Save longest caption width for calculating menu width with
+ width = wnd.GetTextExtent(caption)[0]
+ if width > longest:
+ longest = width
+
+ if useImages:
+ menuItem = wx.MenuItem(menuPopup, 1000+i, caption)
+ if page.bitmap:
+ menuItem.SetBitmap(page.bitmap)
+
+ menuPopup.AppendItem(menuItem)
+
+ else:
+
+ menuPopup.AppendCheckItem(1000+i, caption)
+
+ menuPopup.Enable(1000+i, page.enabled)
+
+ if active_idx != -1 and not useImages:
+
+ menuPopup.Check(1000+active_idx, True)
+
+ # find out the screen coordinate at the bottom of the tab ctrl
+ cli_rect = wnd.GetClientRect()
+
+ # Calculate the approximate size of the popupmenu for setting the
+ # position of the menu when its shown.
+ # Account for extra padding on left/right of text on mac menus
+ if wx.Platform in ['__WXMAC__', '__WXMSW__']:
+ longest += 32
+
+ # Bitmap/Checkmark width + padding
+ longest += 20
+
+ if self.GetAGWFlags() & AUI_NB_CLOSE_BUTTON:
+ longest += 16
+
+ pt = wx.Point(cli_rect.x + cli_rect.GetWidth() - longest,
+ cli_rect.y + cli_rect.height)
+
+ cc = AuiCommandCapture()
+ wnd.PushEventHandler(cc)
+ wnd.PopupMenu(menuPopup, pt)
+ command = cc.GetCommandId()
+ wnd.PopEventHandler(True)
+
+ if command >= 1000:
+ return command - 1000
+
+ return -1
+
+
+class AuiSimpleTabArt(object):
+ """ A simple-looking implementation of a tab art. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ self._normal_font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._selected_font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._selected_font.SetWeight(wx.BOLD)
+ self._measuring_font = self._selected_font
+
+ self._agwFlags = 0
+ self._fixed_tab_width = 100
+
+ base_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
+
+ background_colour = base_colour
+ normaltab_colour = base_colour
+ selectedtab_colour = wx.WHITE
+
+ self._bkbrush = wx.Brush(background_colour)
+ self._normal_bkbrush = wx.Brush(normaltab_colour)
+ self._normal_bkpen = wx.Pen(normaltab_colour)
+ self._selected_bkbrush = wx.Brush(selectedtab_colour)
+ self._selected_bkpen = wx.Pen(selectedtab_colour)
+
+ self._active_close_bmp = BitmapFromBits(nb_close_bits, 16, 16, wx.BLACK)
+ self._disabled_close_bmp = BitmapFromBits(nb_close_bits, 16, 16, wx.Colour(128, 128, 128))
+
+ self._active_left_bmp = BitmapFromBits(nb_left_bits, 16, 16, wx.BLACK)
+ self._disabled_left_bmp = BitmapFromBits(nb_left_bits, 16, 16, wx.Colour(128, 128, 128))
+
+ self._active_right_bmp = BitmapFromBits(nb_right_bits, 16, 16, wx.BLACK)
+ self._disabled_right_bmp = BitmapFromBits(nb_right_bits, 16, 16, wx.Colour(128, 128, 128))
+
+ self._active_windowlist_bmp = BitmapFromBits(nb_list_bits, 16, 16, wx.BLACK)
+ self._disabled_windowlist_bmp = BitmapFromBits(nb_list_bits, 16, 16, wx.Colour(128, 128, 128))
+
+
+ def Clone(self):
+ """ Clones the art object. """
+
+ art = type(self)()
+ art.SetNormalFont(self.GetNormalFont())
+ art.SetSelectedFont(self.GetSelectedFont())
+ art.SetMeasuringFont(self.GetMeasuringFont())
+
+ art = CopyAttributes(art, self)
+ return art
+
+
+ def SetAGWFlags(self, agwFlags):
+ """
+ Sets the tab art flags.
+
+ :param integer `agwFlags`: a combination of the following values:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook
+ ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet.
+ ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet.
+ ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook
+ ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab
+ ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging
+ ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control
+ ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width
+ ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed
+ ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available
+ ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar
+ ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab
+ ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs
+ ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close :class:`~lib.agw.aui.auibook.AuiNotebook` tabs by mouse middle button click
+ ``AUI_NB_SUB_NOTEBOOK`` This style is used by :class:`~lib.agw.aui.framemanager.AuiManager` to create automatic AuiNotebooks
+ ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present
+ ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
+ ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items
+ ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser)
+ ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full
+ screen, tabs cannot be dragged far enough outside of the notebook to become floating pages
+ ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default)
+ ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs
+ ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle
+ ==================================== ==================================
+
+ """
+
+ self._agwFlags = agwFlags
+
+
+ def GetAGWFlags(self):
+ """
+ Returns the tab art flags.
+
+ :see: :meth:`~AuiSimpleTabArt.SetAGWFlags` for a list of possible return values.
+ """
+
+ return self._agwFlags
+
+
+ def SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth):
+ """
+ Sets the tab sizing information.
+
+ :param Size `tab_ctrl_size`: the size of the tab control area;
+ :param integer `tab_count`: the number of tabs;
+ :param tuple `minMaxTabWidth`: a tuple containing the minimum and maximum tab widths
+ to be used when the ``AUI_NB_TAB_FIXED_WIDTH`` style is active.
+ """
+
+ self._fixed_tab_width = 100
+ minTabWidth, maxTabWidth = minMaxTabWidth
+
+ tot_width = tab_ctrl_size.x - self.GetIndentSize() - 4
+
+ if self._agwFlags & AUI_NB_CLOSE_BUTTON:
+ tot_width -= self._active_close_bmp.GetWidth()
+ if self._agwFlags & AUI_NB_WINDOWLIST_BUTTON:
+ tot_width -= self._active_windowlist_bmp.GetWidth()
+
+ if tab_count > 0:
+ self._fixed_tab_width = tot_width/tab_count
+
+ if self._fixed_tab_width < 100:
+ self._fixed_tab_width = 100
+
+ if self._fixed_tab_width > tot_width/2:
+ self._fixed_tab_width = tot_width/2
+
+ if self._fixed_tab_width > 220:
+ self._fixed_tab_width = 220
+
+ if minTabWidth > -1:
+ self._fixed_tab_width = max(self._fixed_tab_width, minTabWidth)
+ if maxTabWidth > -1:
+ self._fixed_tab_width = min(self._fixed_tab_width, maxTabWidth)
+
+ self._tab_ctrl_height = tab_ctrl_size.y
+
+
+ def DrawBackground(self, dc, wnd, rect):
+ """
+ Draws the tab area background.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param Rect `rect`: the tab control rectangle.
+ """
+
+ # draw background
+ dc.SetBrush(self._bkbrush)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2)
+
+ # draw base line
+ dc.SetPen(wx.GREY_PEN)
+ dc.DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1)
+
+
+ def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False):
+ """
+ Draws a single tab.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param `page`: the tab control page associated with the tab;
+ :param Rect `in_rect`: rectangle the tab should be confined to;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param bool `paint_control`: whether to draw the control inside a tab (if any) on a :class:`MemoryDC`.
+ """
+
+ # if the caption is empty, measure some temporary text
+ caption = page.caption
+ if caption == "":
+ caption = "Xj"
+
+ agwFlags = self.GetAGWFlags()
+
+ dc.SetFont(self._selected_font)
+ selected_textx, selected_texty, dummy = dc.GetMultiLineTextExtent(caption)
+
+ dc.SetFont(self._normal_font)
+ normal_textx, normal_texty, dummy = dc.GetMultiLineTextExtent(caption)
+
+ control = page.control
+
+ # figure out the size of the tab
+ tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap,
+ page.active, close_button_state, control)
+
+ tab_height = tab_size[1]
+ tab_width = tab_size[0]
+ tab_x = in_rect.x
+ tab_y = in_rect.y + in_rect.height - tab_height
+
+ caption = page.caption
+ # select pen, brush and font for the tab to be drawn
+
+ if page.active:
+
+ dc.SetPen(self._selected_bkpen)
+ dc.SetBrush(self._selected_bkbrush)
+ dc.SetFont(self._selected_font)
+ textx = selected_textx
+ texty = selected_texty
+
+ else:
+
+ dc.SetPen(self._normal_bkpen)
+ dc.SetBrush(self._normal_bkbrush)
+ dc.SetFont(self._normal_font)
+ textx = normal_textx
+ texty = normal_texty
+
+ if not page.enabled:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+ else:
+ dc.SetTextForeground(page.text_colour)
+
+ # -- draw line --
+
+ points = [wx.Point() for i in xrange(7)]
+ points[0].x = tab_x
+ points[0].y = tab_y + tab_height - 1
+ points[1].x = tab_x + tab_height - 3
+ points[1].y = tab_y + 2
+ points[2].x = tab_x + tab_height + 3
+ points[2].y = tab_y
+ points[3].x = tab_x + tab_width - 2
+ points[3].y = tab_y
+ points[4].x = tab_x + tab_width
+ points[4].y = tab_y + 2
+ points[5].x = tab_x + tab_width
+ points[5].y = tab_y + tab_height - 1
+ points[6] = points[0]
+
+ dc.SetClippingRect(in_rect)
+ dc.DrawPolygon(points)
+
+ dc.SetPen(wx.GREY_PEN)
+ dc.DrawLines(points)
+
+ close_button_width = 0
+
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+
+ close_button_width = self._active_close_bmp.GetWidth()
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ if control:
+ text_offset = tab_x + (tab_height/2) + close_button_width - (textx/2) - 2
+ else:
+ text_offset = tab_x + (tab_height/2) + ((tab_width+close_button_width)/2) - (textx/2) - 2
+ else:
+ if control:
+ text_offset = tab_x + (tab_height/2) + close_button_width - (textx/2)
+ else:
+ text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2)
+
+ else:
+
+ text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2)
+ if control:
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ text_offset = tab_x + (tab_height/3) - (textx/2) + close_button_width + 2
+ else:
+ text_offset = tab_x + (tab_height/3) - (textx/2)
+
+ # set minimum text offset
+ if text_offset < tab_x + tab_height:
+ text_offset = tab_x + tab_height
+
+ # chop text if necessary
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x))
+ else:
+ draw_text = ChopText(dc, caption,
+ tab_width - (text_offset-tab_x) - close_button_width)
+
+ ypos = (tab_y + tab_height)/2 - (texty/2) + 1
+
+ if control is not None:
+ try:
+ if control.GetPosition() != wx.Point(text_offset+1, ypos):
+ control.SetPosition(wx.Point(text_offset+1, ypos))
+
+ if not control.IsShown():
+ control.Show()
+
+ if paint_control:
+ bmp = TakeScreenShot(control.GetScreenRect())
+ dc.DrawBitmap(bmp, text_offset+1, ypos, True)
+
+ controlW, controlH = control.GetSize()
+ text_offset += controlW + 4
+ except wx.PyDeadObjectError:
+ pass
+
+ # draw tab text
+ rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text)
+ dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty))
+
+ # draw focus rectangle
+ if page.active and wx.Window.FindFocus() == wnd and (agwFlags & AUI_NB_NO_TAB_FOCUS) == 0:
+
+ focusRect = wx.Rect(text_offset, ((tab_y + tab_height)/2 - (texty/2) + 1),
+ selected_textx, selected_texty)
+
+ focusRect.Inflate(2, 2)
+ # TODO:
+ # This should be uncommented when DrawFocusRect will become
+ # available in wxPython
+ # wx.RendererNative.Get().DrawFocusRect(wnd, dc, focusRect, 0)
+
+ out_button_rect = wx.Rect()
+ # draw close button if necessary
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+
+ if page.active:
+ bmp = self._active_close_bmp
+ else:
+ bmp = self._disabled_close_bmp
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ rect = wx.Rect(tab_x + tab_height - 2,
+ tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1,
+ close_button_width, tab_height - 1)
+ else:
+ rect = wx.Rect(tab_x + tab_width - close_button_width - 1,
+ tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1,
+ close_button_width, tab_height - 1)
+
+ self.DrawButtons(dc, rect, bmp, wx.WHITE, close_button_state)
+ out_button_rect = wx.Rect(*rect)
+
+ out_tab_rect = wx.Rect(tab_x, tab_y, tab_width, tab_height)
+ dc.DestroyClippingRegion()
+
+ return out_tab_rect, out_button_rect, x_extent
+
+
+ def DrawButtons(self, dc, _rect, bmp, bkcolour, button_state):
+ """
+ Convenience method to draw tab buttons.
+
+ :param `dc`: a :class:`DC` device context;
+ :param Rect `_rect`: the tab rectangle;
+ :param Bitmap `bmp`: the tab bitmap;
+ :param Colour `bkcolour`: the tab background colour;
+ :param integer `button_state`: the state of the tab button.
+ """
+
+ rect = wx.Rect(*_rect)
+
+ if button_state == AUI_BUTTON_STATE_PRESSED:
+ rect.x += 1
+ rect.y += 1
+
+ if button_state in [AUI_BUTTON_STATE_HOVER, AUI_BUTTON_STATE_PRESSED]:
+ dc.SetBrush(wx.Brush(StepColour(bkcolour, 120)))
+ dc.SetPen(wx.Pen(StepColour(bkcolour, 75)))
+
+ # draw the background behind the button
+ dc.DrawRectangle(rect.x, rect.y, 15, 15)
+
+ # draw the button itself
+ dc.DrawBitmap(bmp, rect.x, rect.y, True)
+
+
+ def GetIndentSize(self):
+ """ Returns the tabs indent size. """
+
+ return 0
+
+
+ def GetTabSize(self, dc, wnd, caption, bitmap, active, close_button_state, control=None):
+ """
+ Returns the tab size for the given caption, bitmap and button state.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param string `caption`: the tab text caption;
+ :param Bitmap `bitmap`: the bitmap displayed on the tab;
+ :param bool `active`: whether the tab is selected or not;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param Window `control`: a :class:`Window` instance inside a tab (or ``None``).
+ """
+
+ dc.SetFont(self._measuring_font)
+ measured_textx, measured_texty, dummy = dc.GetMultiLineTextExtent(caption)
+
+ tab_height = measured_texty + 4
+ tab_width = measured_textx + tab_height + 5
+
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+ tab_width += self._active_close_bmp.GetWidth()
+
+ if self._agwFlags & AUI_NB_TAB_FIXED_WIDTH:
+ tab_width = self._fixed_tab_width
+
+ if control is not None:
+ try:
+ controlW, controlH = control.GetSize()
+ tab_width += controlW + 4
+ except wx.PyDeadObjectError:
+ pass
+
+ x_extent = tab_width - (tab_height/2) - 1
+
+ return (tab_width, tab_height), x_extent
+
+
+ def DrawButton(self, dc, wnd, in_rect, button, orientation):
+ """
+ Draws a button on the tab or on the tab area, depending on the button identifier.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param Rect `in_rect`: rectangle the tab should be confined to;
+ :param `button`: an instance of the button class;
+ :param integer `orientation`: the tab orientation.
+ """
+
+ bitmap_id, button_state = button.id, button.cur_state
+
+ if bitmap_id == AUI_BUTTON_CLOSE:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ bmp = self._disabled_close_bmp
+ else:
+ bmp = self._active_close_bmp
+
+ elif bitmap_id == AUI_BUTTON_LEFT:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ bmp = self._disabled_left_bmp
+ else:
+ bmp = self._active_left_bmp
+
+ elif bitmap_id == AUI_BUTTON_RIGHT:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ bmp = self._disabled_right_bmp
+ else:
+ bmp = self._active_right_bmp
+
+ elif bitmap_id == AUI_BUTTON_WINDOWLIST:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ bmp = self._disabled_windowlist_bmp
+ else:
+ bmp = self._active_windowlist_bmp
+
+ else:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ bmp = button.dis_bitmap
+ else:
+ bmp = button.bitmap
+
+ if not bmp.IsOk():
+ return
+
+ rect = wx.Rect(*in_rect)
+
+ if orientation == wx.LEFT:
+
+ rect.SetX(in_rect.x)
+ rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2))
+ rect.SetWidth(bmp.GetWidth())
+ rect.SetHeight(bmp.GetHeight())
+
+ else:
+
+ rect = wx.Rect(in_rect.x + in_rect.width - bmp.GetWidth(),
+ ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
+ bmp.GetWidth(), bmp.GetHeight())
+
+ self.DrawButtons(dc, rect, bmp, wx.WHITE, button_state)
+
+ out_rect = wx.Rect(*rect)
+ return out_rect
+
+
+ def ShowDropDown(self, wnd, pages, active_idx):
+ """
+ Shows the drop-down window menu on the tab area.
+
+ :param `wnd`: a :class:`Window` derived window instance;
+ :param list `pages`: the pages associated with the tabs;
+ :param integer `active_idx`: the active tab index.
+ """
+
+ menuPopup = wx.Menu()
+ useImages = self.GetAGWFlags() & AUI_NB_USE_IMAGES_DROPDOWN
+
+ for i, page in enumerate(pages):
+
+ if useImages:
+ menuItem = wx.MenuItem(menuPopup, 1000+i, page.caption)
+ if page.bitmap:
+ menuItem.SetBitmap(page.bitmap)
+
+ menuPopup.AppendItem(menuItem)
+
+ else:
+
+ menuPopup.AppendCheckItem(1000+i, page.caption)
+
+ menuPopup.Enable(1000+i, page.enabled)
+
+ if active_idx != -1 and not useImages:
+ menuPopup.Check(1000+active_idx, True)
+
+ # find out where to put the popup menu of window
+ # items. Subtract 100 for now to center the menu
+ # a bit, until a better mechanism can be implemented
+ pt = wx.GetMousePosition()
+ pt = wnd.ScreenToClient(pt)
+
+ if pt.x < 100:
+ pt.x = 0
+ else:
+ pt.x -= 100
+
+ # find out the screen coordinate at the bottom of the tab ctrl
+ cli_rect = wnd.GetClientRect()
+ pt.y = cli_rect.y + cli_rect.height
+
+ cc = AuiCommandCapture()
+ wnd.PushEventHandler(cc)
+ wnd.PopupMenu(menuPopup, pt)
+ command = cc.GetCommandId()
+ wnd.PopEventHandler(True)
+
+ if command >= 1000:
+ return command-1000
+
+ return -1
+
+
+ def GetBestTabCtrlSize(self, wnd, pages, required_bmp_size):
+ """
+ Returns the best tab control size.
+
+ :param `wnd`: a :class:`Window` instance object;
+ :param list `pages`: the pages associated with the tabs;
+ :param Size `required_bmp_size`: the size of the bitmap on the tabs.
+ """
+
+ dc = wx.ClientDC(wnd)
+ dc.SetFont(self._measuring_font)
+ s, x_extent = self.GetTabSize(dc, wnd, "ABCDEFGHIj", wx.NullBitmap, True,
+ AUI_BUTTON_STATE_HIDDEN, None)
+
+ max_y = s[1]
+
+ for page in pages:
+ if page.control:
+ controlW, controlH = page.control.GetSize()
+ max_y = max(max_y, controlH+4)
+
+ textx, texty, dummy = dc.GetMultiLineTextExtent(page.caption)
+ max_y = max(max_y, texty)
+
+ return max_y + 3
+
+
+ def SetNormalFont(self, font):
+ """
+ Sets the normal font for drawing tab labels.
+
+ :param Font `font`: the new font to use to draw tab labels in their normal, un-selected state.
+ """
+
+ self._normal_font = font
+
+
+ def SetSelectedFont(self, font):
+ """
+ Sets the selected tab font for drawing tab labels.
+
+ :param Font `font`: the new font to use to draw tab labels in their selected state.
+ """
+
+ self._selected_font = font
+
+
+ def SetMeasuringFont(self, font):
+ """
+ Sets the font for calculating text measurements.
+
+ :param Font `font`: the new font to use to measure tab labels text extents.
+ """
+
+ self._measuring_font = font
+
+
+ def GetNormalFont(self):
+ """ Returns the normal font for drawing tab labels. """
+
+ return self._normal_font
+
+
+ def GetSelectedFont(self):
+ """ Returns the selected tab font for drawing tab labels. """
+
+ return self._selected_font
+
+
+ def GetMeasuringFont(self):
+ """ Returns the font for calculating text measurements. """
+
+ return self._measuring_font
+
+
+ def SetCustomButton(self, bitmap_id, button_state, bmp):
+ """
+ Sets a custom bitmap for the close, left, right and window list buttons.
+
+ :param integer `bitmap_id`: the button identifier;
+ :param integer `button_state`: the button state;
+ :param Bitmap `bmp`: the custom bitmap to use for the button.
+ """
+
+ if bitmap_id == AUI_BUTTON_CLOSE:
+ if button_state == AUI_BUTTON_STATE_NORMAL:
+ self._active_close_bmp = bmp
+ self._hover_close_bmp = self._active_close_bmp
+ self._pressed_close_bmp = self._active_close_bmp
+ self._disabled_close_bmp = self._active_close_bmp
+
+ elif button_state == AUI_BUTTON_STATE_HOVER:
+ self._hover_close_bmp = bmp
+ elif button_state == AUI_BUTTON_STATE_PRESSED:
+ self._pressed_close_bmp = bmp
+ else:
+ self._disabled_close_bmp = bmp
+
+ elif bitmap_id == AUI_BUTTON_LEFT:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ self._disabled_left_bmp = bmp
+ else:
+ self._active_left_bmp = bmp
+
+ elif bitmap_id == AUI_BUTTON_RIGHT:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ self._disabled_right_bmp = bmp
+ else:
+ self._active_right_bmp = bmp
+
+ elif bitmap_id == AUI_BUTTON_WINDOWLIST:
+ if button_state & AUI_BUTTON_STATE_DISABLED:
+ self._disabled_windowlist_bmp = bmp
+ else:
+ self._active_windowlist_bmp = bmp
+
+
+class VC71TabArt(AuiDefaultTabArt):
+ """ A class to draw tabs using the Visual Studio 2003 (VC71) style. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ AuiDefaultTabArt.__init__(self)
+
+
+ def Clone(self):
+ """ Clones the art object. """
+
+ art = type(self)()
+ art.SetNormalFont(self.GetNormalFont())
+ art.SetSelectedFont(self.GetSelectedFont())
+ art.SetMeasuringFont(self.GetMeasuringFont())
+
+ art = CopyAttributes(art, self)
+ return art
+
+
+ def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False):
+ """
+ Draws a single tab.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param `page`: the tab control page associated with the tab;
+ :param Rect `in_rect`: rectangle the tab should be confined to;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param bool `paint_control`: whether to draw the control inside a tab (if any) on a :class:`MemoryDC`.
+ """
+
+ # Visual studio 7.1 style
+ # This code is based on the renderer included in FlatNotebook
+
+ # figure out the size of the tab
+
+ control = page.control
+ tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active,
+ close_button_state, control)
+
+ tab_height = self._tab_ctrl_height - 3
+ tab_width = tab_size[0]
+ tab_x = in_rect.x
+ tab_y = in_rect.y + in_rect.height - tab_height
+ clip_width = tab_width
+
+ if tab_x + clip_width > in_rect.x + in_rect.width - 4:
+ clip_width = (in_rect.x + in_rect.width) - tab_x - 4
+
+ dc.SetClippingRegion(tab_x, tab_y, clip_width + 1, tab_height - 3)
+ agwFlags = self.GetAGWFlags()
+
+ if agwFlags & AUI_NB_BOTTOM:
+ tab_y -= 1
+
+ dc.SetPen((page.active and [wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DHIGHLIGHT))] or \
+ [wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DSHADOW))])[0])
+ dc.SetBrush((page.active and [wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE))] or \
+ [wx.TRANSPARENT_BRUSH])[0])
+
+ if page.active:
+
+ tabH = tab_height - 2
+ dc.DrawRectangle(tab_x, tab_y, tab_width, tabH)
+
+ rightLineY1 = (agwFlags & AUI_NB_BOTTOM and [vertical_border_padding - 2] or \
+ [vertical_border_padding - 1])[0]
+ rightLineY2 = tabH + 3
+ dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DSHADOW)))
+ dc.DrawLine(tab_x + tab_width - 1, rightLineY1 + 1, tab_x + tab_width - 1, rightLineY2)
+
+ if agwFlags & AUI_NB_BOTTOM:
+ dc.DrawLine(tab_x + 1, rightLineY2 - 3 , tab_x + tab_width - 1, rightLineY2 - 3)
+
+ dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DDKSHADOW)))
+ dc.DrawLine(tab_x + tab_width, rightLineY1, tab_x + tab_width, rightLineY2)
+
+ if agwFlags & AUI_NB_BOTTOM:
+ dc.DrawLine(tab_x, rightLineY2 - 2, tab_x + tab_width, rightLineY2 - 2)
+
+ else:
+
+ # We dont draw a rectangle for non selected tabs, but only
+ # vertical line on the right
+ blackLineY1 = (agwFlags & AUI_NB_BOTTOM and [vertical_border_padding + 2] or \
+ [vertical_border_padding + 1])[0]
+ blackLineY2 = tab_height - 5
+ dc.DrawLine(tab_x + tab_width, blackLineY1, tab_x + tab_width, blackLineY2)
+
+ border_points = [0, 0]
+
+ if agwFlags & AUI_NB_BOTTOM:
+
+ border_points[0] = wx.Point(tab_x, tab_y)
+ border_points[1] = wx.Point(tab_x, tab_y + tab_height - 6)
+
+ else: # if (agwFlags & AUI_NB_TOP)
+
+ border_points[0] = wx.Point(tab_x, tab_y + tab_height - 4)
+ border_points[1] = wx.Point(tab_x, tab_y + 2)
+
+ drawn_tab_yoff = border_points[1].y
+ drawn_tab_height = border_points[0].y - border_points[1].y
+
+ text_offset = tab_x + 8
+ close_button_width = 0
+
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+ close_button_width = self._active_close_bmp.GetWidth()
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ text_offset += close_button_width - 5
+
+ if not page.enabled:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+ pagebitmap = page.dis_bitmap
+ else:
+ dc.SetTextForeground(page.text_colour)
+ pagebitmap = page.bitmap
+
+ shift = 0
+ if agwFlags & AUI_NB_BOTTOM:
+ shift = (page.active and [1] or [2])[0]
+
+ bitmap_offset = 0
+ if pagebitmap.IsOk():
+ bitmap_offset = tab_x + 8
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT and close_button_width:
+ bitmap_offset += close_button_width - 5
+
+ # draw bitmap
+ dc.DrawBitmap(pagebitmap, bitmap_offset,
+ drawn_tab_yoff + (drawn_tab_height/2) - (pagebitmap.GetHeight()/2) + shift,
+ True)
+
+ text_offset = bitmap_offset + pagebitmap.GetWidth()
+ text_offset += 3 # bitmap padding
+
+ else:
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT == 0 or not close_button_width:
+ text_offset = tab_x + 8
+
+ # if the caption is empty, measure some temporary text
+ caption = page.caption
+
+ if caption == "":
+ caption = "Xj"
+
+ if page.active:
+ dc.SetFont(self._selected_font)
+ textx, texty, dummy = dc.GetMultiLineTextExtent(caption)
+ else:
+ dc.SetFont(self._normal_font)
+ textx, texty, dummy = dc.GetMultiLineTextExtent(caption)
+
+ draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width)
+
+ ypos = drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1 + shift
+
+ offset_focus = text_offset
+
+ if control is not None:
+ try:
+ if control.GetPosition() != wx.Point(text_offset+1, ypos):
+ control.SetPosition(wx.Point(text_offset+1, ypos))
+
+ if not control.IsShown():
+ control.Show()
+
+ if paint_control:
+ bmp = TakeScreenShot(control.GetScreenRect())
+ dc.DrawBitmap(bmp, text_offset+1, ypos, True)
+
+ controlW, controlH = control.GetSize()
+ text_offset += controlW + 4
+ textx += controlW + 4
+ except wx.PyDeadObjectError:
+ pass
+
+ # draw tab text
+ rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text)
+ dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty))
+
+ out_button_rect = wx.Rect()
+
+ # draw focus rectangle
+ if (agwFlags & AUI_NB_NO_TAB_FOCUS) == 0:
+ self.DrawFocusRectangle(dc, page, wnd, draw_text, offset_focus, bitmap_offset, drawn_tab_yoff+shift,
+ drawn_tab_height+shift, rectx, recty)
+
+ # draw 'x' on tab (if enabled)
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+ close_button_width = self._active_close_bmp.GetWidth()
+
+ bmp = self._disabled_close_bmp
+
+ if close_button_state == AUI_BUTTON_STATE_HOVER:
+ bmp = self._hover_close_bmp
+ elif close_button_state == AUI_BUTTON_STATE_PRESSED:
+ bmp = self._pressed_close_bmp
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ rect = wx.Rect(tab_x + 4,
+ drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift,
+ close_button_width, tab_height)
+ else:
+ rect = wx.Rect(tab_x + tab_width - close_button_width - 3,
+ drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift,
+ close_button_width, tab_height)
+
+ # Indent the button if it is pressed down:
+ rect = IndentPressedBitmap(rect, close_button_state)
+ dc.DrawBitmap(bmp, rect.x, rect.y, True)
+
+ out_button_rect = rect
+
+ out_tab_rect = wx.Rect(tab_x, tab_y, tab_width, tab_height)
+ dc.DestroyClippingRegion()
+
+ return out_tab_rect, out_button_rect, x_extent
+
+
+class FF2TabArt(AuiDefaultTabArt):
+ """ A class to draw tabs using the Firefox 2 (FF2) style. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ AuiDefaultTabArt.__init__(self)
+
+
+ def Clone(self):
+ """ Clones the art object. """
+
+ art = type(self)()
+ art.SetNormalFont(self.GetNormalFont())
+ art.SetSelectedFont(self.GetSelectedFont())
+ art.SetMeasuringFont(self.GetMeasuringFont())
+
+ art = CopyAttributes(art, self)
+ return art
+
+
+ def GetTabSize(self, dc, wnd, caption, bitmap, active, close_button_state, control=None):
+ """
+ Returns the tab size for the given caption, bitmap and button state.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param string `caption`: the tab text caption;
+ :param Bitmap `bitmap`: the bitmap displayed on the tab;
+ :param bool `active`: whether the tab is selected or not;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param Window `control`: a :class:`Window` instance inside a tab (or ``None``).
+ """
+
+ tab_size, x_extent = AuiDefaultTabArt.GetTabSize(self, dc, wnd, caption, bitmap,
+ active, close_button_state, control)
+
+ tab_width, tab_height = tab_size
+
+ # add some vertical padding
+ tab_height += 2
+
+ return (tab_width, tab_height), x_extent
+
+
+ def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False):
+ """
+ Draws a single tab.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param `page`: the tab control page associated with the tab;
+ :param Rect `in_rect`: rectangle the tab should be confined to;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param bool `paint_control`: whether to draw the control inside a tab (if any) on a :class:`MemoryDC`.
+ """
+
+ # Firefox 2 style
+
+ control = page.control
+
+ # figure out the size of the tab
+ tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap,
+ page.active, close_button_state, control)
+
+ tab_height = self._tab_ctrl_height - 2
+ tab_width = tab_size[0]
+ tab_x = in_rect.x
+ tab_y = in_rect.y + in_rect.height - tab_height
+
+ clip_width = tab_width
+ if tab_x + clip_width > in_rect.x + in_rect.width - 4:
+ clip_width = (in_rect.x + in_rect.width) - tab_x - 4
+
+ dc.SetClippingRegion(tab_x, tab_y, clip_width + 1, tab_height - 3)
+
+ tabPoints = [wx.Point() for i in xrange(7)]
+
+ adjust = 0
+ if not page.active:
+ adjust = 1
+
+ agwFlags = self.GetAGWFlags()
+
+ tabPoints[0].x = tab_x + 3
+ tabPoints[0].y = (agwFlags & AUI_NB_BOTTOM and [3] or [tab_height - 2])[0]
+
+ tabPoints[1].x = tabPoints[0].x
+ tabPoints[1].y = (agwFlags & AUI_NB_BOTTOM and [tab_height - (vertical_border_padding + 2) - adjust] or \
+ [(vertical_border_padding + 2) + adjust])[0]
+
+ tabPoints[2].x = tabPoints[1].x+2
+ tabPoints[2].y = (agwFlags & AUI_NB_BOTTOM and [tab_height - vertical_border_padding - adjust] or \
+ [vertical_border_padding + adjust])[0]
+
+ tabPoints[3].x = tab_x + tab_width - 2
+ tabPoints[3].y = tabPoints[2].y
+
+ tabPoints[4].x = tabPoints[3].x + 2
+ tabPoints[4].y = tabPoints[1].y
+
+ tabPoints[5].x = tabPoints[4].x
+ tabPoints[5].y = tabPoints[0].y
+
+ tabPoints[6].x = tabPoints[0].x
+ tabPoints[6].y = tabPoints[0].y
+
+ rr = wx.RectPP(tabPoints[2], tabPoints[5])
+ self.DrawTabBackground(dc, rr, page.active, (agwFlags & AUI_NB_BOTTOM) == 0)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+
+ # Draw the tab as rounded rectangle
+ dc.DrawPolygon(tabPoints)
+
+ if page.active:
+ dc.DrawLine(tabPoints[0].x + 1, tabPoints[0].y, tabPoints[5].x , tabPoints[0].y)
+
+ drawn_tab_yoff = tabPoints[1].y
+ drawn_tab_height = tabPoints[0].y - tabPoints[2].y
+
+ text_offset = tab_x + 8
+ close_button_width = 0
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+ close_button_width = self._active_close_bmp.GetWidth()
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ text_offset += close_button_width - 4
+
+ if not page.enabled:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+ pagebitmap = page.dis_bitmap
+ else:
+ dc.SetTextForeground(page.text_colour)
+ pagebitmap = page.bitmap
+
+ shift = -1
+ if agwFlags & AUI_NB_BOTTOM:
+ shift = 2
+
+ bitmap_offset = 0
+ if pagebitmap.IsOk():
+ bitmap_offset = tab_x + 8
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT and close_button_width:
+ bitmap_offset += close_button_width - 4
+
+ # draw bitmap
+ dc.DrawBitmap(pagebitmap, bitmap_offset,
+ drawn_tab_yoff + (drawn_tab_height/2) - (pagebitmap.GetHeight()/2) + shift,
+ True)
+
+ text_offset = bitmap_offset + pagebitmap.GetWidth()
+ text_offset += 3 # bitmap padding
+
+ else:
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT == 0 or not close_button_width:
+ text_offset = tab_x + 8
+
+ # if the caption is empty, measure some temporary text
+ caption = page.caption
+ if caption == "":
+ caption = "Xj"
+
+ if page.active:
+ dc.SetFont(self._selected_font)
+ textx, texty, dummy = dc.GetMultiLineTextExtent(caption)
+ else:
+ dc.SetFont(self._normal_font)
+ textx, texty, dummy = dc.GetMultiLineTextExtent(caption)
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width + 1)
+ else:
+ draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width)
+
+ ypos = drawn_tab_yoff + drawn_tab_height/2 - texty/2 - 1 + shift
+
+ offset_focus = text_offset
+
+ if control is not None:
+ try:
+ if control.GetPosition() != wx.Point(text_offset+1, ypos):
+ control.SetPosition(wx.Point(text_offset+1, ypos))
+
+ if not control.IsShown():
+ control.Show()
+
+ if paint_control:
+ bmp = TakeScreenShot(control.GetScreenRect())
+ dc.DrawBitmap(bmp, text_offset+1, ypos, True)
+
+ controlW, controlH = control.GetSize()
+ text_offset += controlW + 4
+ textx += controlW + 4
+ except wx.PyDeadObjectError:
+ pass
+
+ # draw tab text
+ rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text)
+ dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty))
+
+ # draw focus rectangle
+ if (agwFlags & AUI_NB_NO_TAB_FOCUS) == 0:
+ self.DrawFocusRectangle(dc, page, wnd, draw_text, offset_focus, bitmap_offset, drawn_tab_yoff+shift,
+ drawn_tab_height, rectx, recty)
+
+ out_button_rect = wx.Rect()
+ # draw 'x' on tab (if enabled)
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+
+ close_button_width = self._active_close_bmp.GetWidth()
+ bmp = self._disabled_close_bmp
+
+ if close_button_state == AUI_BUTTON_STATE_HOVER:
+ bmp = self._hover_close_bmp
+ elif close_button_state == AUI_BUTTON_STATE_PRESSED:
+ bmp = self._pressed_close_bmp
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ rect = wx.Rect(tab_x + 5,
+ drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift,
+ close_button_width, tab_height)
+ else:
+ rect = wx.Rect(tab_x + tab_width - close_button_width - 3,
+ drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift,
+ close_button_width, tab_height)
+
+ # Indent the button if it is pressed down:
+ rect = IndentPressedBitmap(rect, close_button_state)
+ dc.DrawBitmap(bmp, rect.x, rect.y, True)
+ out_button_rect = rect
+
+ out_tab_rect = wx.Rect(tab_x, tab_y, tab_width, tab_height)
+ dc.DestroyClippingRegion()
+
+ return out_tab_rect, out_button_rect, x_extent
+
+
+ def DrawTabBackground(self, dc, rect, focus, upperTabs):
+ """
+ Draws the tab background for the Firefox 2 style.
+ This is more consistent with :class:`~lib.agw.flatnotebook.FlatNotebook` than before.
+
+ :param `dc`: a :class:`DC` device context;
+ :param Rect `rect`: rectangle the tab should be confined to;
+ :param bool `focus`: whether the tab has focus or not;
+ :param bool `upperTabs`: whether the style is ``AUI_NB_TOP`` or ``AUI_NB_BOTTOM``.
+ """
+
+ # Define the rounded rectangle base on the given rect
+ # we need an array of 9 points for it
+ regPts = [wx.Point() for indx in xrange(9)]
+
+ if focus:
+ if upperTabs:
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*8)
+ rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*8)
+ else:
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*5)
+ rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*5)
+ else:
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 2))
+ rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 2))
+
+ # Define the top region
+ top = wx.RectPP(rect.GetTopLeft(), rightPt)
+ bottom = wx.RectPP(leftPt, rect.GetBottomRight())
+
+ topStartColour = wx.WHITE
+
+ if not focus:
+ topStartColour = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 50)
+
+ topEndColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+ bottomStartColour = topEndColour
+ bottomEndColour = topEndColour
+
+ # Incase we use bottom tabs, switch the colours
+ if upperTabs:
+ if focus:
+ dc.GradientFillLinear(top, topStartColour, topEndColour, wx.SOUTH)
+ dc.GradientFillLinear(bottom, bottomStartColour, bottomEndColour, wx.SOUTH)
+ else:
+ dc.GradientFillLinear(top, topEndColour , topStartColour, wx.SOUTH)
+ dc.GradientFillLinear(bottom, bottomStartColour, bottomEndColour, wx.SOUTH)
+
+ else:
+ if focus:
+ dc.GradientFillLinear(bottom, topEndColour, bottomEndColour, wx.SOUTH)
+ dc.GradientFillLinear(top, topStartColour, topStartColour, wx.SOUTH)
+ else:
+ dc.GradientFillLinear(bottom, bottomStartColour, bottomEndColour, wx.SOUTH)
+ dc.GradientFillLinear(top, topEndColour, topStartColour, wx.SOUTH)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+
+class VC8TabArt(AuiDefaultTabArt):
+ """ A class to draw tabs using the Visual Studio 2005 (VC8) style. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ AuiDefaultTabArt.__init__(self)
+
+
+ def Clone(self):
+ """ Clones the art object. """
+
+ art = type(self)()
+ art.SetNormalFont(self.GetNormalFont())
+ art.SetSelectedFont(self.GetSelectedFont())
+ art.SetMeasuringFont(self.GetMeasuringFont())
+
+ art = CopyAttributes(art, self)
+ return art
+
+
+ def SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth):
+ """
+ Sets the tab sizing information.
+
+ :param Size `tab_ctrl_size`: the size of the tab control area;
+ :param integer `tab_count`: the number of tabs;
+ :param tuple `minMaxTabWidth`: a tuple containing the minimum and maximum tab widths
+ to be used when the ``AUI_NB_TAB_FIXED_WIDTH`` style is active.
+ """
+
+ AuiDefaultTabArt.SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth)
+
+ minTabWidth, maxTabWidth = minMaxTabWidth
+ if minTabWidth > -1:
+ self._fixed_tab_width = max(self._fixed_tab_width, minTabWidth)
+ if maxTabWidth > -1:
+ self._fixed_tab_width = min(self._fixed_tab_width, maxTabWidth)
+
+ self._fixed_tab_width -= 5
+
+
+ def GetTabSize(self, dc, wnd, caption, bitmap, active, close_button_state, control=None):
+ """
+ Returns the tab size for the given caption, bitmap and button state.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param string `caption`: the tab text caption;
+ :param Bitmap `bitmap`: the bitmap displayed on the tab;
+ :param bool `active`: whether the tab is selected or not;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param Window `control`: a :class:`Window` instance inside a tab (or ``None``).
+ """
+
+ tab_size, x_extent = AuiDefaultTabArt.GetTabSize(self, dc, wnd, caption, bitmap,
+ active, close_button_state, control)
+
+ tab_width, tab_height = tab_size
+
+ # add some padding
+ tab_width += 10
+
+ if not bitmap.IsOk():
+ tab_width += 5
+
+ tab_height += 2
+
+ return (tab_width, tab_height), x_extent
+
+
+ def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False):
+ """
+ Draws a single tab.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param `page`: the tab control page associated with the tab;
+ :param Rect `in_rect`: rectangle the tab should be confined to;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param bool `paint_control`: whether to draw the control inside a tab (if any) on a :class:`MemoryDC`.
+ """
+
+ # Visual Studio 8 style
+
+ control = page.control
+
+ # figure out the size of the tab
+ tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap,
+ page.active, close_button_state, control)
+
+ tab_height = self._tab_ctrl_height - 1
+ tab_width = tab_size[0]
+ tab_x = in_rect.x
+ tab_y = in_rect.y + in_rect.height - tab_height
+
+ clip_width = tab_width + 3
+ if tab_x + clip_width > in_rect.x + in_rect.width - 4:
+ clip_width = (in_rect.x + in_rect.width) - tab_x - 4
+
+ tabPoints = [wx.Point() for i in xrange(8)]
+
+ # If we draw the first tab or the active tab,
+ # we draw a full tab, else we draw a truncated tab
+ #
+ # X(2) X(3)
+ # X(1) X(4)
+ #
+ # X(5)
+ #
+ # X(0),(7) X(6)
+ #
+ #
+
+ adjust = 0
+ if not page.active:
+ adjust = 1
+
+ agwFlags = self.GetAGWFlags()
+ tabPoints[0].x = (agwFlags & AUI_NB_BOTTOM and [tab_x] or [tab_x + adjust])[0]
+ tabPoints[0].y = (agwFlags & AUI_NB_BOTTOM and [2] or [tab_height - 3])[0]
+
+ tabPoints[1].x = tabPoints[0].x + tab_height - vertical_border_padding - 3 - adjust
+ tabPoints[1].y = (agwFlags & AUI_NB_BOTTOM and [tab_height - (vertical_border_padding+2)] or \
+ [(vertical_border_padding+2)])[0]
+
+ tabPoints[2].x = tabPoints[1].x + 4
+ tabPoints[2].y = (agwFlags & AUI_NB_BOTTOM and [tab_height - vertical_border_padding] or \
+ [vertical_border_padding])[0]
+
+ tabPoints[3].x = tabPoints[2].x + tab_width - tab_height + vertical_border_padding
+ tabPoints[3].y = (agwFlags & AUI_NB_BOTTOM and [tab_height - vertical_border_padding] or \
+ [vertical_border_padding])[0]
+
+ tabPoints[4].x = tabPoints[3].x + 1
+ tabPoints[4].y = (agwFlags & AUI_NB_BOTTOM and [tabPoints[3].y - 1] or [tabPoints[3].y + 1])[0]
+
+ tabPoints[5].x = tabPoints[4].x + 1
+ tabPoints[5].y = (agwFlags & AUI_NB_BOTTOM and [(tabPoints[4].y - 1)] or [tabPoints[4].y + 1])[0]
+
+ tabPoints[6].x = tabPoints[2].x + tab_width - tab_height + 2 + vertical_border_padding
+ tabPoints[6].y = tabPoints[0].y
+
+ tabPoints[7].x = tabPoints[0].x
+ tabPoints[7].y = tabPoints[0].y
+
+ self.FillVC8GradientColour(dc, tabPoints, page.active)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+ dc.DrawPolygon(tabPoints)
+
+ if page.active:
+ # Delete the bottom line (or the upper one, incase we use wxBOTTOM)
+ dc.SetPen(wx.WHITE_PEN)
+ dc.DrawLine(tabPoints[0].x, tabPoints[0].y, tabPoints[6].x, tabPoints[6].y)
+
+ dc.SetClippingRegion(tab_x, tab_y, clip_width + 2, tab_height - 3)
+
+ drawn_tab_yoff = tabPoints[1].y
+ drawn_tab_height = tabPoints[0].y - tabPoints[2].y
+
+ text_offset = tab_x + 20
+ close_button_width = 0
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+ close_button_width = self._active_close_bmp.GetWidth()
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ text_offset += close_button_width
+
+ if not page.enabled:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+ pagebitmap = page.dis_bitmap
+ else:
+ dc.SetTextForeground(page.text_colour)
+ pagebitmap = page.bitmap
+
+ shift = 0
+ if agwFlags & AUI_NB_BOTTOM:
+ shift = (page.active and [1] or [2])[0]
+
+ bitmap_offset = 0
+ if pagebitmap.IsOk():
+ bitmap_offset = tab_x + 20
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT and close_button_width:
+ bitmap_offset += close_button_width
+
+ # draw bitmap
+ dc.DrawBitmap(pagebitmap, bitmap_offset,
+ drawn_tab_yoff + (drawn_tab_height/2) - (pagebitmap.GetHeight()/2) + shift,
+ True)
+
+ text_offset = bitmap_offset + pagebitmap.GetWidth()
+ text_offset += 3 # bitmap padding
+
+ else:
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT == 0 or not close_button_width:
+ text_offset = tab_x + tab_height
+
+ # if the caption is empty, measure some temporary text
+ caption = page.caption
+ if caption == "":
+ caption = "Xj"
+
+ if page.active:
+ dc.SetFont(self._selected_font)
+ textx, texty, dummy = dc.GetMultiLineTextExtent(caption)
+ else:
+ dc.SetFont(self._normal_font)
+ textx, texty, dummy = dc.GetMultiLineTextExtent(caption)
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x))
+ else:
+ draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width)
+
+ ypos = drawn_tab_yoff + drawn_tab_height/2 - texty/2 - 1 + shift
+
+ offset_focus = text_offset
+
+ if control is not None:
+ try:
+ if control.GetPosition() != wx.Point(text_offset+1, ypos):
+ control.SetPosition(wx.Point(text_offset+1, ypos))
+
+ if not control.IsShown():
+ control.Show()
+
+ if paint_control:
+ bmp = TakeScreenShot(control.GetScreenRect())
+ dc.DrawBitmap(bmp, text_offset+1, ypos, True)
+
+ controlW, controlH = control.GetSize()
+ text_offset += controlW + 4
+ textx += controlW + 4
+ except wx.PyDeadObjectError:
+ pass
+
+ # draw tab text
+ rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text)
+ dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty))
+
+ # draw focus rectangle
+ if (agwFlags & AUI_NB_NO_TAB_FOCUS) == 0:
+ self.DrawFocusRectangle(dc, page, wnd, draw_text, offset_focus, bitmap_offset, drawn_tab_yoff+shift,
+ drawn_tab_height+shift, rectx, recty)
+
+ out_button_rect = wx.Rect()
+ # draw 'x' on tab (if enabled)
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+
+ close_button_width = self._active_close_bmp.GetWidth()
+ bmp = self._disabled_close_bmp
+
+ if close_button_state == AUI_BUTTON_STATE_HOVER:
+ bmp = self._hover_close_bmp
+ elif close_button_state == AUI_BUTTON_STATE_PRESSED:
+ bmp = self._pressed_close_bmp
+
+ if page.active:
+ xpos = tab_x + tab_width - close_button_width + 3
+ else:
+ xpos = tab_x + tab_width - close_button_width - 5
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ rect = wx.Rect(tab_x + 20,
+ drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift,
+ close_button_width, tab_height)
+ else:
+ rect = wx.Rect(xpos,
+ drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift,
+ close_button_width, tab_height)
+
+ # Indent the button if it is pressed down:
+ rect = IndentPressedBitmap(rect, close_button_state)
+ dc.DrawBitmap(bmp, rect.x, rect.y, True)
+ out_button_rect = rect
+
+ out_tab_rect = wx.Rect(tab_x, tab_y, x_extent, tab_height)
+ dc.DestroyClippingRegion()
+
+ return out_tab_rect, out_button_rect, x_extent
+
+
+ def FillVC8GradientColour(self, dc, tabPoints, active):
+ """
+ Fills the tab with the Visual Studio 2005 gradient background.
+
+ :param `dc`: a :class:`DC` device context;
+ :param list `tabPoints`: a list of :class:`Point` objects describing the tab shape;
+ :param bool `active`: whether the tab is selected or not.
+ """
+
+ xList = [pt.x for pt in tabPoints]
+ yList = [pt.y for pt in tabPoints]
+
+ minx, maxx = min(xList), max(xList)
+ miny, maxy = min(yList), max(yList)
+
+ rect = wx.Rect(minx, maxy, maxx-minx, miny-maxy+1)
+ region = wx.RegionFromPoints(tabPoints)
+
+ if self._buttonRect.width > 0:
+ buttonRegion = wx.Region(*self._buttonRect)
+ region.XorRegion(buttonRegion)
+
+ dc.SetClippingRegionAsRegion(region)
+
+ if active:
+ bottom_colour = top_colour = wx.WHITE
+ else:
+ bottom_colour = StepColour(self._base_colour, 90)
+ top_colour = StepColour(self._base_colour, 170)
+
+ dc.GradientFillLinear(rect, top_colour, bottom_colour, wx.SOUTH)
+ dc.DestroyClippingRegion()
+
+
+class ChromeTabArt(AuiDefaultTabArt):
+ """
+ A class to draw tabs using the Google Chrome browser style.
+ It uses custom bitmap to render the tabs, so that the look and feel is as close
+ as possible to the Chrome style.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ AuiDefaultTabArt.__init__(self)
+
+ self.SetBitmaps(mirror=False)
+
+ closeBmp = tab_close.GetBitmap()
+ closeHBmp = tab_close_h.GetBitmap()
+ closePBmp = tab_close_p.GetBitmap()
+
+ self.SetCustomButton(AUI_BUTTON_CLOSE, AUI_BUTTON_STATE_NORMAL, closeBmp)
+ self.SetCustomButton(AUI_BUTTON_CLOSE, AUI_BUTTON_STATE_HOVER, closeHBmp)
+ self.SetCustomButton(AUI_BUTTON_CLOSE, AUI_BUTTON_STATE_PRESSED, closePBmp)
+
+
+ def SetAGWFlags(self, agwFlags):
+ """
+ Sets the tab art flags.
+
+ :param integer `agwFlags`: a combination of the following values:
+
+ ==================================== ==================================
+ Flag name Description
+ ==================================== ==================================
+ ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook
+ ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet.
+ ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet.
+ ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook
+ ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab
+ ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging
+ ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control
+ ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width
+ ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed
+ ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available
+ ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar
+ ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab
+ ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs
+ ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close :class:`~lib.agw.aui.auibook.AuiNotebook` tabs by mouse middle button click
+ ``AUI_NB_SUB_NOTEBOOK`` This style is used by :class:`~lib.agw.aui.framemanager.AuiManager` to create automatic AuiNotebooks
+ ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present
+ ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
+ ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items
+ ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser)
+ ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full
+ screen, tabs cannot be dragged far enough outside of the notebook to become floating pages
+ ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default)
+ ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs
+ ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle
+ ==================================== ==================================
+
+ :note: Overridden from :class:`AuiDefaultTabArt`.
+ """
+
+ if agwFlags & AUI_NB_TOP:
+ self.SetBitmaps(mirror=False)
+ elif agwFlags & AUI_NB_BOTTOM:
+ self.SetBitmaps(mirror=True)
+
+ AuiDefaultTabArt.SetAGWFlags(self, agwFlags)
+
+
+ def SetBitmaps(self, mirror):
+ """
+ Assigns the tab custom bitmaps
+
+ :param bool `mirror`: whether to vertically mirror the bitmap or not.
+ """
+
+ bmps = [tab_active_left.GetBitmap(), tab_active_center.GetBitmap(),
+ tab_active_right.GetBitmap(), tab_inactive_left.GetBitmap(),
+ tab_inactive_center.GetBitmap(), tab_inactive_right.GetBitmap()]
+
+ if mirror:
+ for indx, bmp in enumerate(bmps):
+ img = bmp.ConvertToImage()
+ img = img.Mirror(horizontally=False)
+ bmps[indx] = img.ConvertToBitmap()
+
+ self._leftActiveBmp = bmps[0]
+ self._centerActiveBmp = bmps[1]
+ self._rightActiveBmp = bmps[2]
+ self._leftInactiveBmp = bmps[3]
+ self._centerInactiveBmp = bmps[4]
+ self._rightInactiveBmp = bmps[5]
+
+
+ def Clone(self):
+ """ Clones the art object. """
+
+ art = type(self)()
+ art.SetNormalFont(self.GetNormalFont())
+ art.SetSelectedFont(self.GetSelectedFont())
+ art.SetMeasuringFont(self.GetMeasuringFont())
+
+ art = CopyAttributes(art, self)
+ return art
+
+
+ def SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth):
+ """
+ Sets the tab sizing information.
+
+ :param Size `tab_ctrl_size`: the size of the tab control area;
+ :param integer `tab_count`: the number of tabs;
+ :param tuple `minMaxTabWidth`: a tuple containing the minimum and maximum tab widths
+ to be used when the ``AUI_NB_TAB_FIXED_WIDTH`` style is active.
+ """
+
+ AuiDefaultTabArt.SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth)
+
+ minTabWidth, maxTabWidth = minMaxTabWidth
+ if minTabWidth > -1:
+ self._fixed_tab_width = max(self._fixed_tab_width, minTabWidth)
+ if maxTabWidth > -1:
+ self._fixed_tab_width = min(self._fixed_tab_width, maxTabWidth)
+
+ self._fixed_tab_width -= 5
+
+
+ def GetTabSize(self, dc, wnd, caption, bitmap, active, close_button_state, control=None):
+ """
+ Returns the tab size for the given caption, bitmap and button state.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param string `caption`: the tab text caption;
+ :param Bitmap `bitmap`: the bitmap displayed on the tab;
+ :param bool `active`: whether the tab is selected or not;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param Window `control`: a :class:`Window` instance inside a tab (or ``None``).
+ """
+
+ tab_size, x_extent = AuiDefaultTabArt.GetTabSize(self, dc, wnd, caption, bitmap,
+ active, close_button_state, control)
+
+ tab_width, tab_height = tab_size
+
+ # add some padding
+ tab_width += self._leftActiveBmp.GetWidth()
+ tab_height += 2
+
+ tab_height = max(tab_height, self._centerActiveBmp.GetHeight())
+
+ return (tab_width, tab_height), x_extent
+
+
+ def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False):
+ """
+ Draws a single tab.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `wnd`: a :class:`Window` instance object;
+ :param `page`: the tab control page associated with the tab;
+ :param Rect `in_rect`: rectangle the tab should be confined to;
+ :param integer `close_button_state`: the state of the close button on the tab;
+ :param bool `paint_control`: whether to draw the control inside a tab (if any) on a :class:`MemoryDC`.
+ """
+
+ # Chrome tab style
+
+ control = page.control
+ # figure out the size of the tab
+ tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active,
+ close_button_state, control)
+
+ agwFlags = self.GetAGWFlags()
+
+ tab_height = self._tab_ctrl_height - 1
+ tab_width = tab_size[0]
+ tab_x = in_rect.x
+ tab_y = in_rect.y + in_rect.height - tab_height
+ clip_width = tab_width
+
+ if tab_x + clip_width > in_rect.x + in_rect.width - 4:
+ clip_width = (in_rect.x + in_rect.width) - tab_x - 4
+
+ dc.SetClippingRegion(tab_x, tab_y, clip_width + 1, tab_height - 3)
+ drawn_tab_yoff = 1
+
+ if page.active:
+ left = self._leftActiveBmp
+ center = self._centerActiveBmp
+ right = self._rightActiveBmp
+ else:
+ left = self._leftInactiveBmp
+ center = self._centerInactiveBmp
+ right = self._rightInactiveBmp
+
+ dc.DrawBitmap(left, tab_x, tab_y)
+ leftw = left.GetWidth()
+ centerw = center.GetWidth()
+ rightw = right.GetWidth()
+
+ available = tab_x + tab_width - rightw
+ posx = tab_x + leftw
+
+ while 1:
+ if posx >= available:
+ break
+ dc.DrawBitmap(center, posx, tab_y)
+ posx += centerw
+
+ dc.DrawBitmap(right, posx, tab_y)
+
+ drawn_tab_height = center.GetHeight()
+ text_offset = tab_x + leftw
+
+ close_button_width = 0
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+ close_button_width = self._active_close_bmp.GetWidth()
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ text_offset += close_button_width
+
+ if not page.enabled:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+ pagebitmap = page.dis_bitmap
+ else:
+ dc.SetTextForeground(page.text_colour)
+ pagebitmap = page.bitmap
+
+ bitmap_offset = 0
+ if pagebitmap.IsOk():
+ bitmap_offset = tab_x + leftw
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT and close_button_width:
+ bitmap_offset += close_button_width
+
+ # draw bitmap
+ dc.DrawBitmap(pagebitmap, bitmap_offset,
+ drawn_tab_yoff + (drawn_tab_height/2) - (pagebitmap.GetHeight()/2),
+ True)
+
+ text_offset = bitmap_offset + pagebitmap.GetWidth()
+ text_offset += 3 # bitmap padding
+
+ else:
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT == 0 or not close_button_width:
+ text_offset = tab_x + leftw
+
+ # if the caption is empty, measure some temporary text
+ caption = page.caption
+ if caption == "":
+ caption = "Xj"
+
+ if page.active:
+ dc.SetFont(self._selected_font)
+ textx, texty, dummy = dc.GetMultiLineTextExtent(caption)
+ else:
+ dc.SetFont(self._normal_font)
+ textx, texty, dummy = dc.GetMultiLineTextExtent(caption)
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - leftw)
+ else:
+ draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width - leftw)
+
+ ypos = drawn_tab_yoff + drawn_tab_height/2 - texty/2 - 1
+
+ if control is not None:
+ try:
+ if control.GetPosition() != wx.Point(text_offset+1, ypos):
+ control.SetPosition(wx.Point(text_offset+1, ypos))
+
+ if not control.IsShown():
+ control.Show()
+
+ if paint_control:
+ bmp = TakeScreenShot(control.GetScreenRect())
+ dc.DrawBitmap(bmp, text_offset+1, ypos, True)
+
+ controlW, controlH = control.GetSize()
+ text_offset += controlW + 4
+ except wx.PyDeadObjectError:
+ pass
+
+ # draw tab text
+ rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text)
+ dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty))
+
+ out_button_rect = wx.Rect()
+ # draw 'x' on tab (if enabled)
+ if close_button_state != AUI_BUTTON_STATE_HIDDEN:
+
+ close_button_width = self._active_close_bmp.GetWidth()
+ bmp = self._disabled_close_bmp
+
+ if close_button_state == AUI_BUTTON_STATE_HOVER:
+ bmp = self._hover_close_bmp
+ elif close_button_state == AUI_BUTTON_STATE_PRESSED:
+ bmp = self._pressed_close_bmp
+
+ if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT:
+ rect = wx.Rect(tab_x + leftw - 2,
+ drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + 1,
+ close_button_width, tab_height)
+ else:
+ rect = wx.Rect(tab_x + tab_width - close_button_width - rightw + 2,
+ drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + 1,
+ close_button_width, tab_height)
+
+ if agwFlags & AUI_NB_BOTTOM:
+ rect.y -= 1
+
+ # Indent the button if it is pressed down:
+ rect = IndentPressedBitmap(rect, close_button_state)
+ dc.DrawBitmap(bmp, rect.x, rect.y, True)
+ out_button_rect = rect
+
+ out_tab_rect = wx.Rect(tab_x, tab_y, tab_width, tab_height)
+ dc.DestroyClippingRegion()
+
+ return out_tab_rect, out_button_rect, x_extent
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/tabmdi.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/tabmdi.py
new file mode 100644
index 0000000..ef09e9f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/aui/tabmdi.py
@@ -0,0 +1,666 @@
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "31 March 2009"
+
+
+import wx
+
+import auibook
+from aui_constants import *
+
+_ = wx.GetTranslation
+
+#-----------------------------------------------------------------------------
+# AuiMDIParentFrame
+#-----------------------------------------------------------------------------
+
+class AuiMDIParentFrame(wx.Frame):
+
+ def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE|wx.VSCROLL|wx.HSCROLL,
+ name="AuiMDIParentFrame"):
+
+ wx.Frame.__init__(self, parent, id, title, pos, size, style, name=name)
+ self.Init()
+
+ self.Bind(wx.EVT_MENU, self.DoHandleMenu, id=wx.ID_ANY)
+
+ # this style can be used to prevent a window from having the standard MDI
+ # "Window" menu
+ if not style & wx.FRAME_NO_WINDOW_MENU:
+
+ self._pWindowMenu = wx.Menu()
+ self._pWindowMenu.Append(wxWINDOWCLOSE, _("Cl&ose"))
+ self._pWindowMenu.Append(wxWINDOWCLOSEALL, _("Close All"))
+ self._pWindowMenu.AppendSeparator()
+ self._pWindowMenu.Append(wxWINDOWNEXT, _("&Next"))
+ self._pWindowMenu.Append(wxWINDOWPREV, _("&Previous"))
+
+ self._pClientWindow = self.OnCreateClient()
+
+
+ def SetArtProvider(self, provider):
+
+ if self._pClientWindow:
+ self._pClientWindow.SetArtProvider(provider)
+
+
+ def GetArtProvider(self):
+
+ if not self._pClientWindow:
+ return None
+
+ return self._pClientWindow.GetArtProvider()
+
+
+ def GetNotebook(self):
+
+ return self._pClientWindow
+
+
+ def SetWindowMenu(self, pMenu):
+
+ # Replace the window menu from the currently loaded menu bar.
+ pMenuBar = self.GetMenuBar()
+
+ if self._pWindowMenu:
+ self.RemoveWindowMenu(pMenuBar)
+ del self._pWindowMenu
+ self._pWindowMenu = None
+
+ if pMenu:
+ self._pWindowMenu = pMenu
+ self.AddWindowMenu(pMenuBar)
+
+
+ def GetWindowMenu(self):
+
+ return self._pWindowMenu
+
+
+ def SetMenuBar(self, pMenuBar):
+
+ # Remove the Window menu from the old menu bar
+ self.RemoveWindowMenu(self.GetMenuBar())
+
+ # Add the Window menu to the new menu bar.
+ self.AddWindowMenu(pMenuBar)
+
+ wx.Frame.SetMenuBar(self, pMenuBar)
+
+
+ def SetChildMenuBar(self, pChild):
+
+ if not pChild:
+
+ # No Child, set Our menu bar back.
+ if self._pMyMenuBar:
+ self.SetMenuBar(self._pMyMenuBar)
+ else:
+ self.SetMenuBar(self.GetMenuBar())
+
+ # Make sure we know our menu bar is in use
+ self._pMyMenuBar = None
+
+ else:
+
+ if pChild.GetMenuBar() == None:
+ return
+
+ # Do we need to save the current bar?
+ if self._pMyMenuBar == None:
+ self._pMyMenuBar = self.GetMenuBar()
+
+ self.SetMenuBar(pChild.GetMenuBar())
+
+
+ def ProcessEvent(self, event):
+
+ # stops the same event being processed repeatedly
+ if self._pLastEvt == event:
+ return False
+
+ self._pLastEvt = event
+
+ # let the active child (if any) process the event first.
+ res = False
+ if self._pActiveChild and event.IsCommandEvent() and \
+ event.GetEventObject() != self._pClientWindow and \
+ event.GetEventType() not in [wx.wxEVT_ACTIVATE, wx.wxEVT_SET_FOCUS,
+ wx.wxEVT_KILL_FOCUS, wx.wxEVT_CHILD_FOCUS,
+ wx.wxEVT_COMMAND_SET_FOCUS, wx.wxEVT_COMMAND_KILL_FOCUS]:
+
+ res = self._pActiveChild.GetEventHandler().ProcessEvent(event)
+
+ if not res:
+
+ # if the event was not handled this frame will handle it,
+ # which is why we need the protection code at the beginning
+ # of this method
+ res = self.GetEventHandler().ProcessEvent(event)
+
+ self._pLastEvt = None
+
+ return res
+
+
+ def GetActiveChild(self):
+
+ return self._pActiveChild
+
+
+ def SetActiveChild(self, pChildFrame):
+
+ self._pActiveChild = pChildFrame
+
+
+ def GetClientWindow(self):
+
+ return self._pClientWindow
+
+
+ def OnCreateClient(self):
+
+ return AuiMDIClientWindow(self)
+
+
+ def ActivateNext(self):
+
+ if self._pClientWindow and self._pClientWindow.GetSelection() != wx.NOT_FOUND:
+
+ active = self._pClientWindow.GetSelection() + 1
+ if active >= self._pClientWindow.GetPageCount():
+ active = 0
+
+ self._pClientWindow.SetSelection(active)
+
+
+ def ActivatePrevious(self):
+
+ if self._pClientWindow and self._pClientWindow.GetSelection() != wx.NOT_FOUND:
+
+ active = self._pClientWindow.GetSelection() - 1
+ if active < 0:
+ active = self._pClientWindow.GetPageCount() - 1
+
+ self._pClientWindow.SetSelection(active)
+
+
+ def Init(self):
+
+ self._pLastEvt = None
+
+ self._pClientWindow = None
+ self._pActiveChild = None
+ self._pWindowMenu = None
+ self._pMyMenuBar = None
+
+
+ def RemoveWindowMenu(self, pMenuBar):
+
+ if pMenuBar and self._pWindowMenu:
+
+ # Remove old window menu
+ pos = pMenuBar.FindMenu(_("&Window"))
+ if pos != wx.NOT_FOUND:
+ pMenuBar.Remove(pos)
+
+
+ def AddWindowMenu(self, pMenuBar):
+
+ if pMenuBar and self._pWindowMenu:
+
+ pos = pMenuBar.FindMenu(wx.GetStockLabel(wx.ID_HELP, wx.STOCK_NOFLAGS))
+ if pos == wx.NOT_FOUND:
+ pMenuBar.Append(self._pWindowMenu, _("&Window"))
+ else:
+ pMenuBar.Insert(pos, self._pWindowMenu, _("&Window"))
+
+
+ def DoHandleMenu(self, event):
+
+ evId = event.GetId()
+
+ if evId == wxWINDOWCLOSE:
+ if self._pActiveChild:
+ self._pActiveChild.Close()
+
+ elif evId == wxWINDOWCLOSEALL:
+
+ while self._pActiveChild:
+ if not self._pActiveChild.Close():
+ return # failure
+
+ elif evId == wxWINDOWNEXT:
+ self.ActivateNext()
+
+ elif evId == wxWINDOWPREV:
+ self.ActivatePrevious()
+
+ else:
+ event.Skip()
+
+
+ def Tile(self, orient=wx.HORIZONTAL):
+
+ client_window = self.GetClientWindow()
+ if not client_window:
+ raise Exception("Missing MDI Client Window")
+
+ cur_idx = client_window.GetSelection()
+ if cur_idx == -1:
+ return
+
+ if orient == wx.VERTICAL:
+
+ client_window.Split(cur_idx, wx.LEFT)
+
+ elif orient == wx.HORIZONTAL:
+
+ client_window.Split(cur_idx, wx.TOP)
+
+
+#-----------------------------------------------------------------------------
+# AuiMDIChildFrame
+#-----------------------------------------------------------------------------
+
+class AuiMDIChildFrame(wx.PyPanel):
+
+ def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="AuiMDIChildFrame"):
+
+ pClientWindow = parent.GetClientWindow()
+ if pClientWindow is None:
+ raise Exception("Missing MDI client window.")
+
+ self.Init()
+
+ # see comment in constructor
+ if style & wx.MINIMIZE:
+ self._activate_on_create = False
+
+ cli_size = pClientWindow.GetClientSize()
+
+ # create the window off-screen to prevent flicker
+ wx.PyPanel.__init__(self, pClientWindow, id, wx.Point(cli_size.x+1, cli_size.y+1),
+ size, wx.NO_BORDER, name=name)
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+ self.Show(False)
+ self.SetMDIParentFrame(parent)
+
+ # this is the currently active child
+ parent.SetActiveChild(self)
+ self._title = title
+
+ pClientWindow.AddPage(self, title, self._activate_on_create)
+ pClientWindow.Refresh()
+
+ self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnMenuHighlight)
+ self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+
+ def Init(self):
+
+ # There are two ways to create an tabbed mdi child fram without
+ # making it the active document. Either Show(False) can be called
+ # before Create() (as is customary on some ports with wxFrame-type
+ # windows), or wx.MINIMIZE can be passed in the style flags. Note that
+ # AuiMDIChildFrame is not really derived from wxFrame, as MDIChildFrame
+ # is, but those are the expected symantics. No style flag is passed
+ # onto the panel underneath.
+
+ self._activate_on_create = True
+
+ self._pMDIParentFrame = None
+ self._pMenuBar = None
+
+ self._mdi_currect = None
+ self._mdi_newrect = wx.Rect()
+ self._icon = None
+ self._icon_bundle = None
+
+
+ def Destroy(self):
+
+ pParentFrame = self.GetMDIParentFrame()
+ if not pParentFrame:
+ raise Exception("Missing MDI Parent Frame")
+
+ pClientWindow = pParentFrame.GetClientWindow()
+ if not pClientWindow:
+ raise Exception("Missing MDI Client Window")
+
+ if pParentFrame.GetActiveChild() == self:
+
+ # deactivate ourself
+ event = wx.ActivateEvent(wx.wxEVT_ACTIVATE, False, self.GetId())
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ pParentFrame.SetActiveChild(None)
+ pParentFrame.SetChildMenuBar(None)
+
+ for pos in xrange(pClientWindow.GetPageCount()):
+ if pClientWindow.GetPage(pos) == self:
+ return pClientWindow.DeletePage(pos)
+
+ return False
+
+
+ def SetMenuBar(self, menu_bar):
+
+ pOldMenuBar = self._pMenuBar
+ self._pMenuBar = menu_bar
+
+ if self._pMenuBar:
+
+ pParentFrame = self.GetMDIParentFrame()
+ if not pParentFrame:
+ raise Exception("Missing MDI Parent Frame")
+
+ self._pMenuBar.Reparent(pParentFrame)
+ if pParentFrame.GetActiveChild() == self:
+
+ # replace current menu bars
+ if pOldMenuBar:
+ pParentFrame.SetChildMenuBar(None)
+
+ pParentFrame.SetChildMenuBar(self)
+
+
+ def GetMenuBar(self):
+
+ return self._pMenuBar
+
+
+ def SetTitle(self, title):
+
+ self._title = title
+
+ pParentFrame = self.GetMDIParentFrame()
+ if not pParentFrame:
+ raise Exception("Missing MDI Parent Frame")
+
+ pClientWindow = pParentFrame.GetClientWindow()
+ if pClientWindow is not None:
+
+ for pos in xrange(pClientWindow.GetPageCount()):
+ if pClientWindow.GetPage(pos) == self:
+ pClientWindow.SetPageText(pos, self._title)
+ break
+
+
+ def GetTitle(self):
+
+ return self._title
+
+
+ def SetIcons(self, icons):
+
+ # get icon with the system icon size
+ self.SetIcon(icons.GetIcon(-1))
+ self._icon_bundle = icons
+
+
+ def GetIcons(self):
+
+ return self._icon_bundle
+
+
+ def SetIcon(self, icon):
+
+ pParentFrame = self.GetMDIParentFrame()
+ if not pParentFrame:
+ raise Exception("Missing MDI Parent Frame")
+
+ self._icon = icon
+
+ bmp = wx.BitmapFromIcon(self._icon)
+
+ pClientWindow = pParentFrame.GetClientWindow()
+ if pClientWindow is not None:
+ idx = pClientWindow.GetPageIndex(self)
+ if idx != -1:
+ pClientWindow.SetPageBitmap(idx, bmp)
+
+
+ def GetIcon(self):
+
+ return self._icon
+
+
+ def Activate(self):
+
+ pParentFrame = self.GetMDIParentFrame()
+ if not pParentFrame:
+ raise Exception("Missing MDI Parent Frame")
+
+ pClientWindow = pParentFrame.GetClientWindow()
+ if pClientWindow is not None:
+
+ for pos in xrange(pClientWindow.GetPageCount()):
+ if pClientWindow.GetPage(pos) == self:
+ pClientWindow.SetSelection(pos)
+ break
+
+
+ def OnMenuHighlight(self, event):
+
+ if self._pMDIParentFrame:
+
+ # we don't have any help text for this item,
+ # but may be the MDI frame does?
+ self._pMDIParentFrame.OnMenuHighlight(event)
+
+
+ def OnActivate(self, event):
+
+ # do nothing
+ pass
+
+
+ def OnCloseWindow(self, event):
+
+ pParentFrame = self.GetMDIParentFrame()
+ if pParentFrame:
+ if pParentFrame.GetActiveChild() == self:
+
+ pParentFrame.SetActiveChild(None)
+ pParentFrame.SetChildMenuBar(None)
+
+ pClientWindow = pParentFrame.GetClientWindow()
+ idx = pClientWindow.GetPageIndex(self)
+
+ if idx != wx.NOT_FOUND:
+ pClientWindow.RemovePage(idx)
+
+ self.Destroy()
+
+
+ def SetMDIParentFrame(self, parentFrame):
+
+ self._pMDIParentFrame = parentFrame
+
+
+ def GetMDIParentFrame(self):
+
+ return self._pMDIParentFrame
+
+
+ def CreateStatusBar(self, number=1, style=1, winid=1, name=""):
+
+ return None
+
+
+ def GetStatusBar(self):
+
+ return None
+
+
+ def SetStatusText(self, text, number=0):
+
+ pass
+
+
+ def SetStatusWidths(self, widths_field):
+
+ pass
+
+
+ # no toolbar bars
+ def CreateToolBar(self, style=1, winid=-1, name=""):
+
+ return None
+
+
+ def GetToolBar(self):
+
+ return None
+
+
+ # no maximize etc
+ def Maximize(self, maximize=True):
+
+ pass
+
+
+ def Restore(self):
+
+ pass
+
+
+ def Iconize(self, iconize=True):
+
+ pass
+
+
+ def IsMaximized(self):
+
+ return True
+
+
+ def IsIconized(self):
+
+ return False
+
+
+ def ShowFullScreen(self, show=True, style=0):
+
+ return False
+
+
+ def IsFullScreen(self):
+
+ return False
+
+
+ def IsTopLevel(self):
+
+ return False
+
+
+ # renamed from Show().
+ def ActivateOnCreate(self, activate_on_create):
+
+ self._activate_on_create = activate_on_create
+ return True
+
+
+ def Show(self, show=True):
+
+ wx.PyPanel.Show(self, show)
+
+
+ def ApplyMDIChildFrameRect(self):
+
+ if self._mdi_currect != self._mdi_newrect:
+ self.SetDimensions(*self._mdi_newrect)
+ self._mdi_currect = wx.Rect(*self._mdi_newrect)
+
+
+#-----------------------------------------------------------------------------
+# AuiMDIClientWindow
+#-----------------------------------------------------------------------------
+
+class AuiMDIClientWindow(auibook.AuiNotebook):
+
+ def __init__(self, parent, agwStyle=0):
+
+ auibook.AuiNotebook.__init__(self, parent, wx.ID_ANY, wx.Point(0, 0), wx.Size(100, 100),
+ agwStyle=AUI_NB_DEFAULT_STYLE|wx.NO_BORDER)
+
+ caption_icon_size = wx.Size(wx.SystemSettings.GetMetric(wx.SYS_SMALLICON_X),
+ wx.SystemSettings.GetMetric(wx.SYS_SMALLICON_Y))
+ self.SetUniformBitmapSize(caption_icon_size)
+
+ bkcolour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_APPWORKSPACE)
+ self.SetOwnBackgroundColour(bkcolour)
+
+ self._mgr.GetArtProvider().SetColour(AUI_DOCKART_BACKGROUND_COLOUR, bkcolour)
+
+ self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
+ self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnPageClose)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def SetSelection(self, nPage):
+
+ return auibook.AuiNotebook.SetSelection(self, nPage)
+
+
+ def PageChanged(self, old_selection, new_selection):
+
+ # don't do anything if the page doesn't actually change
+ if old_selection == new_selection:
+ return
+
+ # notify old active child that it has been deactivated
+ if old_selection != -1 and old_selection < self.GetPageCount():
+
+ old_child = self.GetPage(old_selection)
+ if not old_child:
+ raise Exception("AuiMDIClientWindow.PageChanged - null page pointer")
+
+ event = wx.ActivateEvent(wx.wxEVT_ACTIVATE, False, old_child.GetId())
+ event.SetEventObject(old_child)
+ old_child.GetEventHandler().ProcessEvent(event)
+
+ # notify new active child that it has been activated
+ if new_selection != -1:
+
+ active_child = self.GetPage(new_selection)
+ if not active_child:
+ raise Exception("AuiMDIClientWindow.PageChanged - null page pointer")
+
+ event = wx.ActivateEvent(wx.wxEVT_ACTIVATE, True, active_child.GetId())
+ event.SetEventObject(active_child)
+ active_child.GetEventHandler().ProcessEvent(event)
+
+ if active_child.GetMDIParentFrame():
+ active_child.GetMDIParentFrame().SetActiveChild(active_child)
+ active_child.GetMDIParentFrame().SetChildMenuBar(active_child)
+
+
+ def OnPageClose(self, event):
+
+ wnd = self.GetPage(event.GetSelection())
+ wnd.Close()
+
+ # regardless of the result of wnd.Close(), we've
+ # already taken care of the close operations, so
+ # suppress further processing
+ event.Veto()
+
+
+ def OnPageChanged(self, event):
+
+ self.PageChanged(event.GetOldSelection(), event.GetSelection())
+
+
+ def OnSize(self, event):
+
+ auibook.AuiNotebook.OnSize(self, event)
+
+ for pos in xrange(self.GetPageCount()):
+ self.GetPage(pos).ApplyMDIChildFrameRect()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/balloontip.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/balloontip.py
new file mode 100644
index 0000000..30a2b6c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/balloontip.py
@@ -0,0 +1,1092 @@
+# --------------------------------------------------------------------------- #
+# BALLOONTIP wxPython IMPLEMENTATION
+# Python Code By:
+#
+# Andrea Gavana, @ 29 May 2005
+# Latest Revision: 17 Aug 2011, 15.00 GMT
+#
+#
+# TODO List/Caveats
+#
+# 1. With wx.ListBox (And Probably Other Controls), The BalloonTip Sometimes
+# Flashes (It Is Created And Suddenly Destroyed). I Don't Know What Is
+# Happening. Probably I Don't Handle Correctly The wx.EVT_ENTER_WINDOW
+# wx.EVT_LEAVE_WINDOW?
+#
+# 2. wx.RadioBox Seems Not To Receive The wx.EVT_ENTER_WINDOW Event
+#
+# 3. wx.SpinCtrl (And Probably Other Controls), When Put In A Sizer, Does Not
+# Return The Correct Size/Position. Probably Is Something I Am Missing.
+#
+# 4. Other Issues?
+#
+#
+# FIXED Problems
+#
+# 1. Now BalloonTip Control Works Also For TaskBarIcon (Thanks To Everyone
+# For The Suggetions I Read In The wxPython Mailing List)
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+:class:`BalloonTip` is a class that allows you to display tooltips in a balloon style
+window.
+
+
+Description
+===========
+
+:class:`BalloonTip` is a class that allows you to display tooltips in a balloon style
+window (actually a frame), similarly to the windows XP balloon help. There is
+also an arrow that points to the center of the control designed as a "target"
+for the :class:`BalloonTip`.
+
+What it can do:
+
+- Set the balloon shape as a rectangle or a rounded rectangle;
+- Set an icon to the top-left of the :class:`BalloonTip` frame;
+- Set a title at the top of the :class:`BalloonTip` frame;
+- Automatic "best" placement of :class:`BalloonTip` frame depending on the target
+ control/window position;
+- Runtime customization of title/tip fonts and foreground colours;
+- Runtime change of :class:`BalloonTip` frame shape;
+- Set the balloon background colour;
+- Possibility to set the delay after which the :class:`BalloonTip` is displayed;
+- Possibility to set the delay after which the :class:`BalloonTip` is destroyed;
+- Three different behaviors for the :class:`BalloonTip` window (regardless the delay
+ destruction time set):
+
+ a) Destroy by leave: the :class:`BalloonTip` is destroyed when the mouse leaves the
+ target control/window;
+ b) Destroy by click: the :class:`BalloonTip` is destroyed when you click on any area
+ of the target control/window;
+ c) Destroy by button: the :class:`BalloonTip` is destroyed when you click on the
+ top-right close button;
+- Possibility to enable/disable globally the :class:`BalloonTip` on you application;
+- Set the :class:`BalloonTip` also for the taskbar icon.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.balloontip as BT
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init(self, parent, -1, "BalloonTip Demo")
+
+ panel = wx.Panel(self)
+
+ # Let's suppose that in your application you have a wx.TextCtrl defined as:
+ mytextctrl = wx.TextCtrl(panel, -1, "I am a textctrl", pos=(100, 100))
+
+ # You can define your BalloonTip as follows:
+ tipballoon = BT.BalloonTip(topicon=None, toptitle="textctrl",
+ message="this is a textctrl",
+ shape=BT.BT_ROUNDED,
+ tipstyle=BT.BT_LEAVE)
+
+ # Set the BalloonTip target
+ tipballoon.SetTarget(mytextctrl)
+ # Set the BalloonTip background colour
+ tipballoon.SetBalloonColour(wx.WHITE)
+ # Set the font for the balloon title
+ tipballoon.SetTitleFont(wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD, False))
+ # Set the colour for the balloon title
+ tipballoon.SetTitleColour(wx.BLACK)
+ # Leave the message font as default
+ tipballoon.SetMessageFont()
+ # Set the message (tip) foreground colour
+ tipballoon.SetMessageColour(wx.LIGHT_GREY)
+ # Set the start delay for the BalloonTip
+ tipballoon.SetStartDelay(1000)
+ # Set the time after which the BalloonTip is destroyed
+ tipballoon.SetEndDelay(3000)
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+================ =========== ==================================================
+Window Styles Hex Value Description
+================ =========== ==================================================
+``BT_ROUNDED`` 0x1 :class:`BalloonTip` will have a rounded rectangular shape.
+``BT_RECTANGLE`` 0x2 :class:`BalloonTip` will have a rectangular shape.
+``BT_LEAVE`` 0x3 :class:`BalloonTip` will be destroyed when the user moves the mouse outside the target window.
+``BT_CLICK`` 0x4 :class:`BalloonTip` will be destroyed when the user click on :class:`BalloonTip`.
+``BT_BUTTON`` 0x5 :class:`BalloonTip` will be destroyed when the user click on the close button.
+================ =========== ==================================================
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+BalloonTip is distributed under the wxPython license.
+
+Latest revision: Andrea Gavana @ 17 Aug 2011, 15.00 GMT
+
+Version 0.2
+
+"""
+
+
+import wx
+import time
+from wx.lib.buttons import GenButton
+
+# Define The Values For The BalloonTip Frame Shape
+BT_ROUNDED = 1
+""" :class:`BalloonTip` will have a rounded rectangular shape. """
+BT_RECTANGLE = 2
+""" :class:`BalloonTip` will have a rectangular shape. """
+
+# Define The Value For The BalloonTip Destruction Behavior
+BT_LEAVE = 3
+""" :class:`BalloonTip` will be destroyed when the user moves the mouse outside the target window. """
+BT_CLICK = 4
+""" :class:`BalloonTip` will be destroyed when the user click on :class:`BalloonTip`. """
+BT_BUTTON = 5
+""" :class:`BalloonTip` will be destroyed when the user click on the close button. """
+
+
+# ---------------------------------------------------------------
+# Class BalloonFrame
+# ---------------------------------------------------------------
+# This Class Is Called By The Main BalloonTip Class, And It Is
+# Responsible For The Frame Creation/Positioning On Screen
+# Depending On Target Control/Window, The Frame Can Position
+# Itself To NW (Default), NE, SW, SE. The Switch On Positioning
+# Is Done By Calculating The Absolute Position Of The Target
+# Control/Window Plus/Minus The BalloonTip Size. The Pointing
+# Arrow Is Positioned Accordingly.
+# ---------------------------------------------------------------
+
+class BalloonFrame(wx.Frame):
+ """
+ This class is called by the main :class:`BalloonTip` class, and it is
+ responsible for the frame creation/positioning on screen
+ depending on target control/window, the frame can position
+ itself to NW (default), NE, SW, SE. The switch on positioning
+ is done by calculating the absolute position of the target
+ control/window plus/minus the balloontip size. The pointing
+ arrow is positioned accordingly.
+ """
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, classparent=None):
+ """
+ Default class constructor.
+
+ Used internally. Do not call directly this class in your application!
+ """
+
+ wx.Frame.__init__(self, None, -1, "BalloonTip", pos, size,
+ style=wx.FRAME_SHAPED |
+ wx.SIMPLE_BORDER |
+ wx.FRAME_NO_TASKBAR |
+ wx.STAY_ON_TOP)
+
+ self._parent = classparent
+ self._toptitle = self._parent._toptitle
+ self._topicon = self._parent._topicon
+ self._message = self._parent._message
+ self._shape = self._parent._shape
+ self._tipstyle = self._parent._tipstyle
+
+ self._ballooncolour = self._parent._ballooncolour
+ self._balloonmsgcolour = self._parent._balloonmsgcolour
+ self._balloonmsgfont = self._parent._balloonmsgfont
+
+ if self._toptitle != "":
+ self._balloontitlecolour = self._parent._balloontitlecolour
+ self._balloontitlefont = self._parent._balloontitlefont
+
+ panel = wx.Panel(self, -1)
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ self.panel = panel
+
+ subsizer = wx.BoxSizer(wx.VERTICAL)
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+ subsizer.Add((0,20), 0, wx.EXPAND)
+
+ if self._topicon is not None:
+ stb = wx.StaticBitmap(panel, -1, self._topicon)
+ hsizer.Add(stb, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 10)
+ self._balloonbmp = stb
+
+ if self._toptitle != "":
+ stt = wx.StaticText(panel, -1, self._toptitle)
+ stt.SetFont(wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD, False))
+ if self._topicon is None:
+ hsizer.Add((10,0), 0, wx.EXPAND)
+
+ hsizer.Add(stt, 1, wx.EXPAND | wx.TOP, 10)
+
+ self._balloontitle = stt
+ self._balloontitle.SetForegroundColour(self._balloontitlecolour)
+ self._balloontitle.SetFont(self._balloontitlefont)
+
+ if self._tipstyle == BT_BUTTON:
+ self._closebutton = GenButton(panel, -1, "X", style=wx.NO_BORDER)
+ self._closebutton.SetMinSize((16,16))
+ self._closebutton.SetFont(wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD, False))
+ self._closebutton.Bind(wx.EVT_ENTER_WINDOW, self.OnEnterButton)
+ self._closebutton.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveButton)
+ self._closebutton.SetUseFocusIndicator(False)
+ if self._toptitle != "":
+ hsizer.Add(self._closebutton, 0, wx.TOP | wx.RIGHT, 5)
+ else:
+ hsizer.Add((10,0), 1, wx.EXPAND)
+ hsizer.Add(self._closebutton, 0, wx.ALIGN_RIGHT | wx.TOP
+ | wx.RIGHT, 5)
+
+ if self._topicon is not None or self._toptitle != "" \
+ or self._tipstyle == BT_BUTTON:
+
+ subsizer.Add(hsizer, 0, wx.EXPAND | wx.BOTTOM, 5)
+
+ self._firstline = line = wx.StaticLine(panel, -1, style=wx.LI_HORIZONTAL)
+
+ if self._topicon is not None or self._toptitle != "" \
+ or self._tipstyle == BT_BUTTON:
+ subsizer.Add(self._firstline, 0, wx.EXPAND | wx.LEFT | wx.RIGHT
+ | wx.BOTTOM, 10)
+ else:
+ subsizer.Add(self._firstline, 0, wx.EXPAND | wx.LEFT | wx.RIGHT
+ | wx.BOTTOM | wx.TOP, 10)
+
+ mainstt = wx.StaticText(panel, -1, self._message)
+
+ self._balloonmsg = mainstt
+ self._balloonmsg.SetForegroundColour(self._balloonmsgcolour)
+ self._balloonmsg.SetFont(self._balloonmsgfont)
+
+ subsizer.Add(self._balloonmsg, 1, wx.EXPAND | wx.LEFT | wx.RIGHT |
+ wx.BOTTOM, 10)
+ self._secondline = wx.StaticLine(panel, -1, style=wx.LI_HORIZONTAL)
+ subsizer.Add(self._secondline, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 10)
+ subsizer.Add((0,0),1)
+ panel.SetSizer(subsizer)
+
+ sizer.Add(panel, 1, wx.EXPAND)
+ self.SetSizerAndFit(sizer)
+ sizer.Layout()
+
+ if self._tipstyle == BT_CLICK:
+ if self._toptitle != "":
+ self._balloontitle.Bind(wx.EVT_LEFT_DOWN, self.OnClose)
+
+ if self._topicon is not None:
+ self._balloonbmp.Bind(wx.EVT_LEFT_DOWN, self.OnClose)
+
+ self._balloonmsg.Bind(wx.EVT_LEFT_DOWN, self.OnClose)
+ self.panel.Bind(wx.EVT_LEFT_DOWN, self.OnClose)
+
+ elif self._tipstyle == BT_BUTTON:
+ self._closebutton.Bind(wx.EVT_BUTTON, self.OnClose)
+
+ self.panel.SetBackgroundColour(self._ballooncolour)
+
+ if wx.Platform == "__WXGTK__":
+ self.Bind(wx.EVT_WINDOW_CREATE, self.SetBalloonShape)
+ else:
+ self.SetBalloonShape()
+
+ self.Show(True)
+
+
+ def SetBalloonShape(self, event=None):
+ """
+ Sets the balloon shape.
+
+ :param `event`: on wxGTK, a :class:`WindowCreateEvent` event to process.
+ """
+
+ size = self.GetSize()
+ pos = self.GetPosition()
+
+ dc = wx.MemoryDC(wx.EmptyBitmap(1,1))
+ textlabel = self._balloonmsg.GetLabel()
+ textfont = self._balloonmsg.GetFont()
+ textextent = dc.GetFullTextExtent(textlabel, textfont)
+
+ boxheight = size.y - textextent[1]*len(textlabel.split("\n"))
+ boxwidth = size.x
+
+ position = wx.GetMousePosition()
+
+ xpos = position[0]
+ ypos = position[1]
+
+ if xpos > 20 and ypos > 20:
+
+ # This Is NW Positioning
+ positioning = "NW"
+ xpos = position[0] - boxwidth + 20
+ ypos = position[1] - boxheight - 20
+
+ elif xpos <= 20 and ypos <= 20:
+
+ # This Is SE Positioning
+ positioning = "SE"
+ xpos = position[0] - 20
+ ypos = position[1]
+
+ elif xpos > 20 and ypos <= 20:
+
+ # This Is SW Positioning
+ positioning = "SW"
+ xpos = position[0] - boxwidth + 20
+ ypos = position[1]
+
+ else:
+
+ # This Is NE Positioning
+ positioning = "NE"
+ xpos = position[0]
+ ypos = position[1] - boxheight + 20
+
+ bmp = wx.EmptyBitmap(size.x,size.y)
+ dc = wx.BufferedDC(None, bmp)
+ dc.BeginDrawing()
+ dc.SetBackground(wx.Brush(wx.Colour(0,0,0), wx.SOLID))
+ dc.Clear()
+ dc.SetPen(wx.Pen(wx.Colour(0,0,0), 1, wx.TRANSPARENT))
+
+ if self._shape == BT_ROUNDED:
+ dc.DrawRoundedRectangle(0, 20, boxwidth, boxheight-20, 12)
+
+ elif self._shape == BT_RECTANGLE:
+ dc.DrawRectangle(0, 20, boxwidth, boxheight-20)
+
+ if positioning == "NW":
+ dc.DrawPolygon(((boxwidth-40, boxheight), (boxwidth-20, boxheight+20),
+ (boxwidth-20, boxheight)))
+ elif positioning == "SE":
+ dc.DrawPolygon(((20, 20), (20, 0), (40, 20)))
+
+ elif positioning == "SW":
+ dc.DrawPolygon(((boxwidth-40, 20), (boxwidth-20, 0), (boxwidth-20, 20)))
+
+ else:
+ dc.DrawPolygon(((20, boxheight), (20, boxheight+20), (40, boxheight)))
+
+ dc.EndDrawing()
+
+ r = wx.RegionFromBitmapColour(bmp, wx.Colour(0,0,0))
+ self.hasShape = self.SetShape(r)
+
+ if self._tipstyle == BT_BUTTON:
+ colour = self.panel.GetBackgroundColour()
+ self._closebutton.SetBackgroundColour(colour)
+
+ self.SetPosition((xpos, ypos))
+
+
+ def OnEnterButton(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` for the :class:`BalloonTip` button.
+
+ When the :class:`BalloonTip` is created with the `tipstyle` = ``BT_BUTTON``, this event
+ provide some kind of 3D effect when the mouse enters the button area.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ button = event.GetEventObject()
+ colour = button.GetBackgroundColour()
+ red = colour.Red()
+ green = colour.Green()
+ blue = colour.Blue()
+
+ if red < 30:
+ red = red + 30
+ if green < 30:
+ green = green + 30
+ if blue < 30:
+ blue = blue + 30
+
+ colour = wx.Colour(red-30, green-30, blue-30)
+ button.SetBackgroundColour(colour)
+ button.SetForegroundColour(wx.WHITE)
+ button.Refresh()
+ event.Skip()
+
+
+ def OnLeaveButton(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` for the :class:`BalloonTip` button.
+
+ When the :class:`BalloonTip` is created with the `tipstyle` = ``BT_BUTTON``, this event
+ provide some kind of 3D effect when the mouse enters the button area.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ button = event.GetEventObject()
+ colour = self.panel.GetBackgroundColour()
+ button.SetBackgroundColour(colour)
+ button.SetForegroundColour(wx.BLACK)
+ button.Refresh()
+ event.Skip()
+
+
+ def OnClose(self, event):
+ """
+ Handles the ``wx.EVT_CLOSE`` event for :class:`BalloonTip`.
+
+ :param `event`: a :class:`CloseEvent` event to be processed.
+ """
+
+ if isinstance(self._parent._widget, wx.TaskBarIcon):
+ self._parent.taskbarcreation = 0
+ self._parent.taskbartime.Stop()
+ del self._parent.taskbartime
+ del self._parent.BalloonFrame
+
+ self.Destroy()
+
+
+# ---------------------------------------------------------------
+# Class BalloonTip
+# ---------------------------------------------------------------
+# This Is The Main BalloonTip Implementation
+# ---------------------------------------------------------------
+
+class BalloonTip(object):
+ """
+ :class:`BalloonTip` is a class that allows you to display tooltips in a balloon style
+ window.
+
+ This is the main class implementation.
+ """
+ def __init__(self, topicon=None, toptitle="",
+ message="", shape=BT_ROUNDED, tipstyle=BT_LEAVE):
+ """
+ Default class constructor.
+
+ :param `topicon`: an icon that will be displayed on the top-left part of the
+ :class:`BalloonTip` frame. If set to ``None``, no icon will be displayed;
+ :type `topicon`: :class:`Bitmap` or ``None``
+ :param string `toptitle`: a title that will be displayed on the top part of the
+ :class:`BalloonTip` frame. If set to an empty string, no title will be displayed;
+ :param string `message`: the tip message that will be displayed. It can not be set to
+ an empty string;
+ :param integer `shape`: the :class:`BalloonTip` shape. It can be one of the following:
+
+ ======================= ========= ====================================
+ Shape Flag Hex Value Description
+ ======================= ========= ====================================
+ ``BT_ROUNDED`` 0x1 :class:`BalloonTip` will have a rounded rectangular shape.
+ ``BT_RECTANGLE`` 0x2 :class:`BalloonTip` will have a rectangular shape.
+ ======================= ========= ====================================
+
+ :param integer `tipstyle`: the :class:`BalloonTip` destruction behavior. It can be one of:
+
+ ======================= ========= ====================================
+ Tip Flag Hex Value Description
+ ======================= ========= ====================================
+ ``BT_LEAVE`` 0x3 :class:`BalloonTip` will be destroyed when the user moves the mouse outside the target window.
+ ``BT_CLICK`` 0x4 :class:`BalloonTip` will be destroyed when the user click on :class:`BalloonTip`.
+ ``BT_BUTTON`` 0x5 :class:`BalloonTip` will be destroyed when the user click on the close button.
+ ======================= ========= ====================================
+
+ :raise: `Exception` in the following cases:
+
+ - The `message` parameter is an empty string;
+ - The `shape` parameter has an invalid value (i.e., it's not one of ``BT_ROUNDED``, ``BT_RECTANGLE``);
+ - The `tipstyle` parameter has an invalid value (i.e., it's not one of ``BT_LEAVE``, ``BT_CLICK``, ``BT_BUTTON``).
+
+ """
+
+ self._shape = shape
+ self._topicon = topicon
+ self._toptitle = toptitle
+ self._message = message
+ self._tipstyle = tipstyle
+
+ app = wx.GetApp()
+ self._runningapp = app
+ self._runningapp.__tooltipenabled__ = True
+
+ if self._message == "":
+ raise Exception("\nERROR: You Should At Least Set The Message For The BalloonTip")
+
+ if self._shape not in [BT_ROUNDED, BT_RECTANGLE]:
+ raise Exception('\nERROR: BalloonTip Shape Should Be One Of "BT_ROUNDED", "BT_RECTANGLE"')
+
+ if self._tipstyle not in [BT_LEAVE, BT_CLICK, BT_BUTTON]:
+ raise Exception('\nERROR: BalloonTip TipStyle Should Be One Of "BT_LEAVE", '\
+ '"BT_CLICK", "BT_BUTTON"')
+
+ self.SetStartDelay()
+ self.SetEndDelay()
+ self.SetBalloonColour()
+
+ if toptitle != "":
+ self.SetTitleFont()
+ self.SetTitleColour()
+
+ if topicon is not None:
+ self.SetBalloonIcon(topicon)
+
+ self.SetMessageFont()
+ self.SetMessageColour()
+
+
+ def SetTarget(self, widget):
+ """
+ Sets the target control/window for the :class:`BalloonTip`.
+
+ :param `widget`: any subclass of :class:`Window`.
+ """
+
+ self._widget = widget
+
+ if isinstance(widget, wx.TaskBarIcon):
+ self._widget.Bind(wx.EVT_TASKBAR_MOVE, self.OnTaskBarMove)
+ self._widget.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+ self.taskbarcreation = 0
+ else:
+ self._widget.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
+ self._widget.Bind(wx.EVT_LEAVE_WINDOW, self.OnWidgetLeave)
+ self._widget.Bind(wx.EVT_MOTION, self.OnWidgetMotion)
+ self._widget.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+
+
+ def GetTarget(self):
+ """
+ Returns the target window for the :class:`BalloonTip`.
+
+ :return: An instance of :class:`Window`.
+
+ :raise: `Exception` if the :meth:`~BalloonTip.SetTarget` method has not previously called.
+ """
+
+ if not hasattr(self, "_widget"):
+ raise Exception("\nERROR: BalloonTip Target Has Not Been Set")
+
+ return self._widget
+
+
+ def SetStartDelay(self, delay=1):
+ """
+ Sets the delay time after which the :class:`BalloonTip` is created.
+
+ :param integer `delay`: the number of milliseconds after which :class:`BalloonTip` is created.
+
+ :raise: `Exception` if `delay` is less than ``1`` milliseconds.
+ """
+
+ if delay < 1:
+ raise Exception("\nERROR: Delay Time For BalloonTip Creation Should Be Greater Than 1 ms")
+
+ self._startdelaytime = float(delay)
+
+
+ def GetStartDelay(self):
+ """
+ Returns the delay time after which the :class:`BalloonTip` is created.
+
+ :return: the delay time, in milliseconds.
+ """
+
+ return self._startdelaytime
+
+
+ def SetEndDelay(self, delay=1e6):
+ """
+ Sets the delay time after which the BalloonTip is destroyed.
+
+ :param integer `delay`: the number of milliseconds after which :class:`BalloonTip` is destroyed.
+
+ :raise: `Exception` if `delay` is less than ``1`` milliseconds.
+ """
+
+ if delay < 1:
+ raise Exception("\nERROR: Delay Time For BalloonTip Destruction Should Be Greater Than 1 ms")
+
+ self._enddelaytime = float(delay)
+
+
+ def GetEndDelay(self):
+ """
+ Returns the delay time after which the :class:`BalloonTip` is destroyed.
+
+ :return: the delay time, in milliseconds.
+ """
+
+ return self._enddelaytime
+
+
+ def OnWidgetEnter(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` for the target control/window and
+ starts the :class:`BalloonTip` timer for creation.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if hasattr(self, "BalloonFrame"):
+ if self.BalloonFrame:
+ return
+
+ if not self._runningapp.__tooltipenabled__:
+ return
+
+ self.showtime = wx.PyTimer(self.NotifyTimer)
+ self.showtime.Start(self._startdelaytime)
+
+ event.Skip()
+
+
+ def OnWidgetLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` for the target control/window.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+
+ :note: If the BalloonTip `tipstyle` is set to ``BT_LEAVE``, the :class:`BalloonTip` is destroyed.
+ """
+
+ if hasattr(self, "showtime"):
+ if self.showtime:
+ self.showtime.Stop()
+ del self.showtime
+
+ if hasattr(self, "BalloonFrame"):
+ if self.BalloonFrame:
+ if self._tipstyle == BT_LEAVE:
+ endtime = time.time()
+ if endtime - self.starttime > 0.1:
+ try:
+ self.BalloonFrame.Destroy()
+ except:
+ pass
+ else:
+ event.Skip()
+ else:
+ event.Skip()
+ else:
+ event.Skip()
+
+
+ def OnTaskBarMove(self, event):
+ """
+ Handles the mouse motion inside the taskbar icon area.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not hasattr(self, "BalloonFrame"):
+ if self.taskbarcreation == 0:
+ self.mousepos = wx.GetMousePosition()
+ self.currentmousepos = self.mousepos
+ self.taskbartime = wx.PyTimer(self.TaskBarTimer)
+ self.taskbartime.Start(100)
+ self.showtime = wx.PyTimer(self.NotifyTimer)
+ self.showtime.Start(self._startdelaytime)
+
+ if self.taskbarcreation == 0:
+ self.taskbarcreation = 1
+
+ return
+
+ event.Skip()
+
+
+ def OnWidgetMotion(self, event):
+ """
+ Handle the mouse motion inside the target.
+
+ This prevents the annoying behavior of :class:`BalloonTip` to display when the
+ user does something else inside the window. The :class:`BalloonTip` window is
+ displayed only when the mouse does *not* move for the start delay time.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if hasattr(self, "BalloonFrame"):
+ if self.BalloonFrame:
+ return
+
+ if hasattr(self, "showtime"):
+ if self.showtime:
+ self.showtime.Start(self._startdelaytime)
+
+ event.Skip()
+
+
+ def NotifyTimer(self):
+ """ The creation timer has expired. Creates the :class:`BalloonTip` frame."""
+
+ self.BalloonFrame = BalloonFrame(self._widget, classparent=self)
+ self.BalloonFrame.Show(True)
+ self.starttime = time.time()
+
+ self.showtime.Stop()
+ del self.showtime
+
+ self.destroytime = wx.PyTimer(self.DestroyTimer)
+ self.destroytime.Start(self._enddelaytime)
+
+
+ def TaskBarTimer(self):
+ """
+ This timer check periodically the mouse position.
+
+ If the current mouse position is sufficiently far from the coordinates
+ it had when entered the taskbar icon and the :class:`BalloonTip` style is
+ ``BT_LEAVE``, the :class:`BalloonTip` frame is destroyed.
+ """
+
+ self.currentmousepos = wx.GetMousePosition()
+ mousepos = self.mousepos
+
+ if abs(self.currentmousepos[0] - mousepos[0]) > 30 or \
+ abs(self.currentmousepos[1] - mousepos[1]) > 30:
+ if hasattr(self, "BalloonFrame"):
+ if self._tipstyle == BT_LEAVE:
+ try:
+ self.BalloonFrame.Destroy()
+ self.taskbartime.Stop()
+ del self.taskbartime
+ del self.BalloonFrame
+ self.taskbarcreation = 0
+ except:
+ pass
+
+
+ def DestroyTimer(self):
+ """ The destruction timer has expired. Destroys the :class:`BalloonTip` frame."""
+
+ self.destroytime.Stop()
+ del self.destroytime
+
+ try:
+ self.BalloonFrame.Destroy()
+ except:
+ pass
+
+
+ def SetBalloonShape(self, shape=BT_ROUNDED):
+ """
+ Sets the :class:`BalloonTip` frame shape.
+
+ :param integer `shape`: should be one of ``BT_ROUNDED`` or ``BT_RECTANGLE``.
+
+ :raise: `Exception` if the `shape` parameter is not a valid value
+ (i.e., it's not one of ``BT_ROUNDED``, ``BT_RECTANGLE``);
+ """
+
+ if shape not in [BT_ROUNDED, BT_RECTANGLE]:
+ raise Exception('\nERROR: BalloonTip Shape Should Be One Of "BT_ROUNDED", "BT_RECTANGLE"')
+
+ self._shape = shape
+
+
+ def GetBalloonShape(self):
+ """
+ Returns the :class:`BalloonTip` frame shape.
+
+ :return: An integer, one of ``BT_ROUNDED``, ``BT_RECTANGLE``.
+ """
+
+ return self._shape
+
+
+ def SetBalloonIcon(self, icon):
+ """
+ Sets the :class:`BalloonTip` top-left icon.
+
+ :param `icon`: an instance of :class:`Bitmap`.
+
+ :raise: `Exception` if the `icon` bitmap is not a valid :class:`Bitmap`.
+ """
+
+ if icon.Ok():
+ self._topicon = icon
+ else:
+ raise Exception("\nERROR: Invalid Image Passed To BalloonTip")
+
+
+ def GetBalloonIcon(self):
+ """
+ Returns the :class:`BalloonTip` top-left icon.
+
+ :return: An instance of :class:`Bitmap`.
+ """
+
+ return self._topicon
+
+
+ def SetBalloonTitle(self, title=""):
+ """
+ Sets the :class:`BalloonTip` top title.
+
+ :param string `title`: a string to use as a :class:`BalloonTip` title.
+ """
+
+ self._toptitle = title
+
+
+ def GetBalloonTitle(self):
+ """
+ Returns the :class:`BalloonTip` top title.
+
+ :return: A string containing the top title.
+ """
+
+ return self._toptitle
+
+
+ def SetBalloonMessage(self, message):
+ """
+ Sets the :class:`BalloonTip` tip message.
+
+ :param string `message`: a string identifying the main message body of :class:`BalloonTip`.
+
+ :raise: `Exception` if the message is an empty string.
+
+ :note: The :class:`BalloonTip` message should never be empty.
+ """
+
+ if len(message.strip()) < 1:
+ raise Exception("\nERROR: BalloonTip Message Can Not Be Empty")
+
+ self._message = message
+
+
+ def GetBalloonMessage(self):
+ """
+ Returns the :class:`BalloonTip` tip message.
+
+ :return: A string containing the main message.
+ """
+
+ return self._message
+
+
+ def SetBalloonTipStyle(self, tipstyle=BT_LEAVE):
+ """
+ Sets the :class:`BalloonTip` `tipstyle` parameter.
+
+ :param integer `tipstyle`: one of the following bit set:
+
+ ============== ========== =====================================
+ Tip Style Hex Value Description
+ ============== ========== =====================================
+ ``BT_LEAVE`` 0x3 :class:`BalloonTip` will be destroyed when the user moves the mouse outside the target window.
+ ``BT_CLICK`` 0x4 :class:`BalloonTip` will be destroyed when the user click on :class:`BalloonTip`.
+ ``BT_BUTTON`` 0x5 :class:`BalloonTip` will be destroyed when the user click on the close button.
+ ============== ========== =====================================
+
+ :raise: `Exception` if the `tipstyle` parameter has an invalid value
+ (i.e., it's not one of ``BT_LEAVE``, ``BT_CLICK``, ``BT_BUTTON``).
+ """
+
+ if tipstyle not in [BT_LEAVE, BT_CLICK, BT_BUTTON]:
+ raise Exception('\nERROR: BalloonTip TipStyle Should Be One Of "BT_LEAVE", '\
+ '"BT_CLICK", "BT_BUTTON"')
+
+ self._tipstyle = tipstyle
+
+
+ def GetBalloonTipStyle(self):
+ """
+ Returns the :class:`BalloonTip` `tipstyle` parameter.
+
+ :return: An integer representing the style.
+
+ :see: :meth:`~BalloonTip.SetBalloonTipStyle`
+ """
+
+ return self._tipstyle
+
+
+ def SetBalloonColour(self, colour=None):
+ """
+ Sets the :class:`BalloonTip` background colour.
+
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ if colour is None:
+ colour = wx.Colour(255, 250, 205)
+
+ self._ballooncolour = colour
+
+
+ def GetBalloonColour(self):
+ """
+ Returns the :class:`BalloonTip` background colour.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._ballooncolour
+
+
+ def SetTitleFont(self, font=None):
+ """
+ Sets the font for the top title.
+
+ :param `font`: a valid :class:`Font` instance.
+ """
+
+ if font is None:
+ font = wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD, False)
+
+ self._balloontitlefont = font
+
+
+ def GetTitleFont(self):
+ """
+ Returns the font for the top title.
+
+ :return: An instance of :class:`Font`.
+ """
+
+ return self._balloontitlefont
+
+
+ def SetMessageFont(self, font=None):
+ """
+ Sets the font for the tip message.
+
+ :param `font`: a valid :class:`Font` instance.
+ """
+
+ if font is None:
+ font = wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False)
+
+ self._balloonmsgfont = font
+
+
+ def GetMessageFont(self):
+ """
+ Returns the font for the tip message.
+
+ :return: An instance of :class:`Font`.
+ """
+
+ return self._balloonmsgfont
+
+
+ def SetTitleColour(self, colour=None):
+ """
+ Sets the colour for the top title.
+
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ if colour is None:
+ colour = wx.BLACK
+
+ self._balloontitlecolour = colour
+
+
+ def GetTitleColour(self):
+ """
+ Returns the colour for the top title.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._balloontitlecolour
+
+
+ def SetMessageColour(self, colour=None):
+ """
+ Sets the colour for the tip message.
+
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ if colour is None:
+ colour = wx.BLACK
+
+ self._balloonmsgcolour = colour
+
+
+ def GetMessageColour(self):
+ """
+ Returns the colour for the tip message.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._balloonmsgcolour
+
+
+ def OnDestroy(self, event):
+ """
+ Handles the target destruction, specifically handling the ``wx.EVT_WINDOW_DESTROY``
+ event.
+
+ :param `event`: a :class:`WindowDestroyEvent` event to be processed.
+ """
+
+ if hasattr(self, "BalloonFrame"):
+ if self.BalloonFrame:
+ try:
+ if isinstance(self._widget, wx.TaskBarIcon):
+ self._widget.Unbind(wx.EVT_TASKBAR_MOVE)
+ self.taskbartime.Stop()
+ del self.taskbartime
+ else:
+ self._widget.Unbind(wx.EVT_MOTION)
+ self._widget.Unbind(wx.EVT_LEAVE_WINDOW)
+ self._widget.Unbind(wx.EVT_ENTER_WINDOW)
+
+ self.BalloonFrame.Destroy()
+
+ except:
+ pass
+
+ del self.BalloonFrame
+
+
+ def EnableTip(self, enable=True):
+ """
+ Enable/disable globally the :class:`BalloonTip`.
+
+ :param bool `enable`: ``True`` to enable :class:`BalloonTip`, ``False`` otherwise.
+ """
+
+ self._runningapp.__tooltipenabled__ = enable
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/buttonpanel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/buttonpanel.py
new file mode 100644
index 0000000..4aaee46
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/buttonpanel.py
@@ -0,0 +1,2767 @@
+# --------------------------------------------------------------------------- #
+# BUTTONPANEL Widget wxPython IMPLEMENTATION
+#
+# Original C++ Code From Eran. You Can Find It At:
+#
+# http://wxforum.shadonet.com/viewtopic.php?t=6619
+#
+# License: wxWidgets license
+#
+#
+# Python Code By:
+#
+# Andrea Gavana, @ 02 Oct 2006
+# Latest Revision: 17 Aug 2011, 15.00 GMT
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+A custom panel class with gradient background shading with the possibility to
+add buttons and controls still respecting the gradient background.
+
+
+Description
+===========
+
+With :class:`ButtonPanel` class you have a panel with gradient colouring
+on it and with the possibility to place some buttons on it. Using a
+standard panel with normal :class:`Buttons` leads to an ugly result: the
+buttons are placed correctly on the panel - but with grey area around
+them. Gradient colouring is kept behind the images - this was achieved
+due to the PNG format and the transparency of the bitmaps.
+
+The image are functioning like a buttons and can be caught in your
+code using the usual::
+
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+
+method.
+
+The control is generic, and support theming (well, I tested it under
+Windows with the three defauls themes: grey, blue, silver and the
+classic look).
+
+
+Usage
+=====
+
+:class:`ButtonPanel` supports 4 alignments: left, right, top, bottom, which have a
+different meaning and behavior with respect to :class:`Toolbar`. The easiest
+thing is to try the demo to understand, but I'll try to explain how it works.
+
+**CASE 1**: :class:`ButtonPanel` has a main caption text.
+
+- Left alignment means :class:`ButtonPanel` is horizontal, with the text aligned to the
+ left. When you shrink the demo frame, if there is not enough room for all
+ the controls to be shown, the controls closest to the text are hidden;
+
+- Right alignment means :class:`ButtonPanel` is horizontal, with the text aligned to the
+ right. Item layout as above;
+
+- Top alignment means :class:`ButtonPanel` is vertical, with the text aligned to the top.
+ Item layout as above;
+
+- Bottom alignment means :class:`ButtonPanel` is vertical, with the text aligned to the
+ bottom. Item layout as above.
+
+
+**CASE 2**: :class:`ButtonPanel` has **no** main caption text.
+
+- In this case, left and right alignment are the same (as top and bottom are the same),
+ but the layout strategy changes: now if there is not enough room for all the controls
+ to be shown, the last added items are hidden ("last" means on the far right for an
+ horizontal :class:`ButtonPanel` and far bottom for a vertical :class:`ButtonPanel`).
+
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.buttonpanel as BP
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent, id=-1, title="ButtonPanel", pos=wx.DefaultPosition,
+ size=(800, 600), style=wx.DEFAULT_FRAME_STYLE):
+
+ wx.Frame.__init__(self, parent, id, title, pos, size, style)
+
+ mainPanel = wx.Panel(self, -1)
+ self.logtext = wx.TextCtrl(mainPanel, -1, "", style=wx.TE_MULTILINE)
+
+ vSizer = wx.BoxSizer(wx.VERTICAL)
+ mainPanel.SetSizer(vSizer)
+
+ titleBar = BP.ButtonPanel(mainPanel, -1, "A Simple Test & Demo")
+
+ btn1 = BP.ButtonInfo(titleBar, wx.NewId(), wx.Bitmap("png4.png", wx.BITMAP_TYPE_PNG))
+ titleBar.AddButton(btn1)
+ self.Bind(wx.EVT_BUTTON, self.OnButton, btn1)
+
+ btn2 = BP.ButtonInfo(titleBar, wx.NewId(), wx.Bitmap("png3.png", wx.BITMAP_TYPE_PNG))
+ titleBar.AddButton(btn2)
+ self.Bind(wx.EVT_BUTTON, self.OnButton, btn2)
+
+ btn3 = BP.ButtonInfo(titleBar, wx.NewId(), wx.Bitmap("png2.png", wx.BITMAP_TYPE_PNG))
+ titleBar.AddButton(btn3)
+ self.Bind(wx.EVT_BUTTON, self.OnButton, btn3)
+
+ btn4 = BP.ButtonInfo(titleBar, wx.NewId(), wx.Bitmap("png1.png", wx.BITMAP_TYPE_PNG))
+ titleBar.AddButton(btn4)
+ self.Bind(wx.EVT_BUTTON, self.OnButton, btn4)
+
+ vSizer.Add(titleBar, 0, wx.EXPAND)
+ vSizer.Add((20, 20))
+ vSizer.Add(self.logtext, 1, wx.EXPAND|wx.ALL, 5)
+
+ titleBar.DoLayout()
+ vSizer.Layout()
+
+
+ def OnButton(self, event):
+ ''' Handler for the ``wx.EVT_BUTTON`` event. '''
+
+ obj = event.GetEventObject()
+
+ # This will print the button label
+ print obj.GetText()
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+==================== =========== ==================================================
+Window Styles Hex Value Description
+==================== =========== ==================================================
+``BP_DEFAULT_STYLE`` 0x1 :class:`ButtonPanel` has a plain solid background.
+``BP_USE_GRADIENT`` 0x2 :class:`ButtonPanel` has a gradient shading background.
+==================== =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================= ==================================================
+Event Name Description
+================= ==================================================
+``wx.EVT_BUTTON`` Process a `wxEVT_COMMAND_BUTTON_CLICKED` event, when a button is clicked.
+================= ==================================================
+
+
+License And Version
+===================
+
+:class:`ButtonPanel` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 17 Aug 2011, 15.00 GMT
+
+Version 0.6.
+
+"""
+
+
+import wx
+
+# Some constants to tune the BPArt class
+BP_BACKGROUND_COLOUR = 0
+""" Background brush colour when no gradient shading exists. """
+BP_GRADIENT_COLOUR_FROM = 1
+""" Starting gradient colour, used only when ``BP_USE_GRADIENT`` style is applied. """
+BP_GRADIENT_COLOUR_TO = 2
+""" Ending gradient colour, used only when ``BP_USE_GRADIENT`` style is applied. """
+BP_BORDER_COLOUR = 3
+""" Pen colour to paint the border of :class:`ButtonPanel`. """
+BP_TEXT_COLOUR = 4
+""" Main :class:`ButtonPanel` caption colour. """
+BP_BUTTONTEXT_COLOUR = 5
+""" Text colour for buttons with text. """
+BP_BUTTONTEXT_INACTIVE_COLOUR = 6
+""" Text colour for inactive buttons with text. """
+BP_SELECTION_BRUSH_COLOUR = 7
+""" Brush colour to be used when hovering or selecting a button. """
+BP_SELECTION_PEN_COLOUR = 8
+""" Pen colour to be used when hovering or selecting a button. """
+BP_SEPARATOR_COLOUR = 9
+""" Pen colour used to paint the separators. """
+BP_TEXT_FONT = 10
+""" Font of the :class:`ButtonPanel` main caption. """
+BP_BUTTONTEXT_FONT = 11
+""" Text font for the buttons with text. """
+
+BP_BUTTONTEXT_ALIGN_BOTTOM = 12
+""" Flag that indicates the image and text in buttons is stacked. """
+BP_BUTTONTEXT_ALIGN_RIGHT = 13
+""" Flag that indicates the text is shown alongside the image in buttons with text. """
+
+BP_SEPARATOR_SIZE = 14
+""" Separator size. NB: This is not the line width, but the sum of the space before and after the separator line plus the width of the line. """
+BP_MARGINS_SIZE = 15
+""" Size of the left/right margins in :class:`ButtonPanel` (top/bottom for vertically aligned :class:`ButtonPanel`)."""
+BP_BORDER_SIZE = 16
+""" Size of the border. """
+BP_PADDING_SIZE = 17
+""" Inter-tool separator size. """
+
+# Caption Gradient Type
+BP_GRADIENT_NONE = 0
+""" No gradient shading should be used to paint the background. """
+BP_GRADIENT_VERTICAL = 1
+""" Vertical gradient shading should be used to paint the background. """
+BP_GRADIENT_HORIZONTAL = 2
+""" Horizontal gradient shading should be used to paint the background. """
+
+# Flags for HitTest() method
+BP_HT_BUTTON = 200
+""" This flag indicates that the user has hit a button inside :class:`ButtonPanel`. """
+BP_HT_NONE = 201
+""" This flag indicates that no buttons were hit inside :class:`ButtonPanel`. """
+
+# Alignment of buttons in the panel
+BP_ALIGN_RIGHT = 1
+""" Aligns the buttons to the right (for an horizontal :class:`ButtonPanel`). """
+BP_ALIGN_LEFT = 2
+""" Aligns the buttons to the left (for an horizontal :class:`ButtonPanel`). """
+BP_ALIGN_TOP = 4
+""" Aligns the buttons at the top (for a vertical :class:`ButtonPanel`). """
+BP_ALIGN_BOTTOM = 8
+""" Aligns the buttons at the bottom (for a vertical :class:`ButtonPanel`). """
+
+# ButtonPanel styles
+BP_DEFAULT_STYLE = 1
+""" :class:`ButtonPanel` has a plain solid background. """
+BP_USE_GRADIENT = 2
+""" :class:`ButtonPanel` has a gradient shading background. """
+
+# Delay used to cancel the longHelp in the statusbar field
+_DELAY = 3000
+
+
+# Check for the new method in 2.7 (not present in 2.6.3.3)
+if wx.VERSION_STRING < "2.7":
+ wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point)
+
+
+def BrightenColour(colour, factor):
+ """
+ Brighten the input colour by a factor.
+
+ :param `colour`: a valid :class:`Colour` instance;
+ :param integer `factor`: the factor by which the input colour should be brightened.
+
+ :return: An instance of :class:`Colour`, a brightened version of the input `colour`.
+ """
+
+ val = colour.Red()*factor
+ if val > 255:
+ red = 255
+ else:
+ red = val
+
+ val = colour.Green()*factor
+ if val > 255:
+ green = 255
+ else:
+ green = val
+
+ val = colour.Blue()*factor
+ if val > 255:
+ blue = 255
+ else:
+ blue = val
+
+ return wx.Colour(red, green, blue)
+
+
+# ----------------------------------------------------------------------------
+
+def MakeDisabledBitmap(original):
+ """
+ Creates a disabled-looking bitmap starting from the input one.
+
+ :param `original`: an instance of :class:`Bitmap` to be greyed-out.
+
+ :return: A greyed-out representation of the input bitmap, an instance of :class:`Bitmap`.
+ """
+
+ img = original.ConvertToImage()
+ return wx.BitmapFromImage(img.ConvertToGreyscale())
+
+
+# ---------------------------------------------------------------------------- #
+# Class BPArt
+# Handles all the drawings for buttons, separators and text and allows the
+# programmer to set colours, sizes and gradient shadings for ButtonPanel
+# ---------------------------------------------------------------------------- #
+
+class BPArt(object):
+ """
+ :class:`BPArt` is an art provider class which does all of the drawing for :class:`ButtonPanel`.
+ This allows the library caller to customize the :class:`BPArt` or to completely replace
+ all drawing with custom BPArts.
+ """
+
+ def __init__(self, parentStyle):
+ """
+ Default class constructor.
+
+ :param integer `parentStyle`: the window style for :class:`ButtonPanel`.
+ """
+
+ base_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+
+ self._background_brush = wx.Brush(base_colour, wx.SOLID)
+ self._gradient_colour_to = wx.WHITE
+ self._gradient_colour_from = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+
+ if parentStyle & BP_USE_GRADIENT:
+ self._border_pen = wx.Pen(wx.WHITE, 3)
+ self._caption_text_colour = wx.WHITE
+ self._buttontext_colour = wx.Colour(70, 143, 255)
+ self._separator_pen = wx.Pen(BrightenColour(self._gradient_colour_from, 1.4))
+ self._gradient_type = BP_GRADIENT_VERTICAL
+ else:
+ self._border_pen = wx.Pen(BrightenColour(base_colour, 0.9), 3)
+ self._caption_text_colour = wx.BLACK
+ self._buttontext_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT)
+ self._separator_pen = wx.Pen(BrightenColour(base_colour, 0.9))
+ self._gradient_type = BP_GRADIENT_NONE
+
+ self._buttontext_inactive_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT)
+ self._selection_brush = wx.Brush(wx.Colour(225, 225, 255))
+ self._selection_pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION))
+
+ sysfont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._caption_font = wx.Font(sysfont.GetPointSize(), wx.DEFAULT, wx.NORMAL, wx.BOLD,
+ False, sysfont.GetFaceName())
+ self._buttontext_font = wx.Font(sysfont.GetPointSize(), wx.DEFAULT, wx.NORMAL, wx.NORMAL,
+ False, sysfont.GetFaceName())
+
+ self._separator_size = 7
+ self._margins_size = wx.Size(6, 6)
+ self._caption_border_size = 3
+ self._padding_size = wx.Size(6, 6)
+
+
+ def GetMetric(self, id):
+ """
+ Returns the option value for the specified size `id`.
+
+ :param integer `id`: the identification bit for the size value. This can be one of the
+ following bits:
+
+ ============================== ======= =====================================
+ Size Id Value Description
+ ============================== ======= =====================================
+ ``BP_SEPARATOR_SIZE`` 14 Separator size. Note: This is not the line width, but the sum of the space before and after the separator line plus the width of the line
+ ``BP_MARGINS_SIZE`` 15 Size of the left/right margins in :class:`ButtonPanel` (top/bottom for vertically aligned :class:`ButtonPanel`)
+ ``BP_BORDER_SIZE`` 16 Size of the border
+ ``BP_PADDING_SIZE`` 17 Inter-tool separator size
+ ============================== ======= =====================================
+
+ :return: An integer representing the option value for the input `id`.
+
+ :raise: `Exception` if the `id` is not recognized.
+ """
+
+ if id == BP_SEPARATOR_SIZE:
+ return self._separator_size
+ elif id == BP_MARGINS_SIZE:
+ return self._margins_size
+ elif id == BP_BORDER_SIZE:
+ return self._caption_border_size
+ elif id == BP_PADDING_SIZE:
+ return self._padding_size
+ else:
+ raise Exception("\nERROR: Invalid Metric Ordinal. ")
+
+
+ def SetMetric(self, id, new_val):
+ """
+ Sets the option value for the specified size `id`.
+
+ :param integer `id`: the identification bit for the size value;
+ :param input`new_val`: the new value for the size.
+
+ :raise: `Exception` if the `id` is not recognized.
+
+ :see: :meth:`~BPArt.GetMetric` for a list of meaningful size ids.
+ """
+
+ if id == BP_SEPARATOR_SIZE:
+ self._separator_size = new_val
+ elif id == BP_MARGINS_SIZE:
+ self._margins_size = new_val
+ elif id == BP_BORDER_SIZE:
+ self._caption_border_size = new_val
+ self._border_pen.SetWidth(new_val)
+ elif id == BP_PADDING_SIZE:
+ self._padding_size = new_val
+ else:
+ raise Exception("\nERROR: Invalid Metric Ordinal. ")
+
+
+ def GetColour(self, id):
+ """
+ Returns the option value for the specified colour `id`.
+
+ :param internal`id`: the identification bit for the colour value. This can be one of the
+ following bits:
+
+ ================================== ======= =====================================
+ Colour Id Value Description
+ ================================== ======= =====================================
+ ``BP_BACKGROUND_COLOUR`` 0 Background brush colour when no gradient shading exists
+ ``BP_GRADIENT_COLOUR_FROM`` 1 Starting gradient colour, used only when ``BP_USE_GRADIENT`` style is applied
+ ``BP_GRADIENT_COLOUR_TO`` 2 Ending gradient colour, used only when ``BP_USE_GRADIENT`` style is applied
+ ``BP_BORDER_COLOUR`` 3 Pen colour to paint the border of :class:`ButtonPanel`
+ ``BP_TEXT_COLOUR`` 4 Main :class:`ButtonPanel` caption colour
+ ``BP_BUTTONTEXT_COLOUR`` 5 Text colour for buttons with text
+ ``BP_BUTTONTEXT_INACTIVE_COLOUR`` 6 Text colour for inactive buttons with text
+ ``BP_SELECTION_BRUSH_COLOUR`` 7 Brush colour to be used when hovering or selecting a button
+ ``BP_SELECTION_PEN_COLOUR`` 8 Pen colour to be used when hovering or selecting a button
+ ``BP_SEPARATOR_COLOUR`` 9 Pen colour used to paint the separators
+ ================================== ======= =====================================
+
+ :return: An instance of :class:`Colour` for the input `id`.
+
+ :raise: `Exception` if the `id` is not recognized.
+ """
+
+ if id == BP_BACKGROUND_COLOUR:
+ return self._background_brush.GetColour()
+ elif id == BP_GRADIENT_COLOUR_FROM:
+ return self._gradient_colour_from
+ elif id == BP_GRADIENT_COLOUR_TO:
+ return self._gradient_colour_to
+ elif id == BP_BORDER_COLOUR:
+ return self._border_pen.GetColour()
+ elif id == BP_TEXT_COLOUR:
+ return self._caption_text_colour
+ elif id == BP_BUTTONTEXT_COLOUR:
+ return self._buttontext_colour
+ elif id == BP_BUTTONTEXT_INACTIVE_COLOUR:
+ return self._buttontext_inactive_colour
+ elif id == BP_SELECTION_BRUSH_COLOUR:
+ return self._selection_brush.GetColour()
+ elif id == BP_SELECTION_PEN_COLOUR:
+ return self._selection_pen.GetColour()
+ elif id == BP_SEPARATOR_COLOUR:
+ return self._separator_pen.GetColour()
+ else:
+ raise Exception("\nERROR: Invalid Colour Ordinal. ")
+
+
+ def SetColour(self, id, colour):
+ """
+ Sets the option value for the specified colour `id`.
+
+ :param integer `id`: the identification bit for the colour value;
+ :param `colour`: the new value for the colour (a valid :class:`Colour` instance).
+
+ :raise: `Exception` if the `id` is not recognized.
+
+ :see: :meth:`~BPArt.GetColour` for a list of meaningful colour ids.
+ """
+
+ if id == BP_BACKGROUND_COLOUR:
+ self._background_brush.SetColour(colour)
+ elif id == BP_GRADIENT_COLOUR_FROM:
+ self._gradient_colour_from = colour
+ elif id == BP_GRADIENT_COLOUR_TO:
+ self._gradient_colour_to = colour
+ elif id == BP_BORDER_COLOUR:
+ self._border_pen.SetColour(colour)
+ elif id == BP_TEXT_COLOUR:
+ self._caption_text_colour = colour
+ elif id == BP_BUTTONTEXT_COLOUR:
+ self._buttontext_colour = colour
+ elif id == BP_BUTTONTEXT_INACTIVE_COLOUR:
+ self._buttontext_inactive_colour = colour
+ elif id == BP_SELECTION_BRUSH_COLOUR:
+ self._selection_brush.SetColour(colour)
+ elif id == BP_SELECTION_PEN_COLOUR:
+ self._selection_pen.SetColour(colour)
+ elif id == BP_SEPARATOR_COLOUR:
+ self._separator_pen.SetColour(colour)
+ else:
+ raise Exception("\nERROR: Invalid Colour Ordinal. ")
+
+
+ GetColor = GetColour
+ SetColor = SetColour
+
+
+ def GetFont(self, id):
+ """
+ Returns the option value for the specified font `id`.
+
+ :param integer `id`: the identification bit for the font value. This can be one of the
+ following bits:
+
+ ============================== ======= =====================================
+ Size Id Value Description
+ ============================== ======= =====================================
+ ``BP_TEXT_FONT`` 10 Font of the :class:`ButtonPanel` main caption
+ ``BP_BUTTONTEXT_FONT`` 11 Text font for the buttons with text
+ ============================== ======= =====================================
+
+ :return: An instance of :class:`Font` for the input `id`.
+
+ :raise: `Exception` if the `id` is not recognized.
+ """
+
+ if id == BP_TEXT_FONT:
+ return self._caption_font
+ elif id == BP_BUTTONTEXT_FONT:
+ return self._buttontext_font
+
+ return wx.NoneFont
+
+
+ def SetFont(self, id, font):
+ """
+ Sets the option value for the specified font `id`.
+
+ :param integer `id`: the identification bit for the font value;
+ :param `colour`: the new value for the font (a valid :class:`Font` instance).
+
+ :raise: `Exception` if the `id` is not recognized.
+
+ :see: :meth:`~BPArt.GetFont` for a list of meaningful font ids.
+ """
+
+ if id == BP_TEXT_FONT:
+ self._caption_font = font
+ elif id == BP_BUTTONTEXT_FONT:
+ self._buttontext_font = font
+
+
+ def SetGradientType(self, gradient):
+ """
+ Sets the gradient type for :class:`BPArt` drawings.
+
+ :param integer `gradient`: can be one of the following bits:
+
+ ============================ ======= ============================
+ Gradient Type Value Description
+ ============================ ======= ============================
+ ``BP_GRADIENT_NONE`` 0 No gradient shading should be used to paint the background
+ ``BP_GRADIENT_VERTICAL`` 1 Vertical gradient shading should be used to paint the background
+ ``BP_GRADIENT_HORIZONTAL`` 2 Horizontal gradient shading should be used to paint the background
+ ============================ ======= ============================
+
+ """
+
+ self._gradient_type = gradient
+
+
+ def GetGradientType(self):
+ """
+ Returns the gradient type for :class:`BPArt` drawings.
+
+ :return: An integer representing the gradient type.
+
+ :see: :meth:`~BPArt.SetGradientType` for a list of possible gradient types.
+ """
+
+ return self._gradient_type
+
+
+ def DrawSeparator(self, dc, rect, isVertical):
+ """
+ Draws a separator in :class:`ButtonPanel`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the separator client rectangle;
+ :param bool `isVertical`: ``True`` if :class:`ButtonPanel` is in vertical orientation,
+ ``False`` otherwise.
+ """
+
+ dc.SetPen(self._separator_pen)
+
+ if isVertical:
+ ystart = yend = rect.y + rect.height/2
+ xstart = int(rect.x + 1.5*self._caption_border_size)
+ xend = int(rect.x + rect.width - 1.5*self._caption_border_size)
+ dc.DrawLine(xstart, ystart, xend, yend)
+ else:
+ xstart = xend = rect.x + rect.width/2
+ ystart = int(rect.y + 1.5*self._caption_border_size)
+ yend = int(rect.y + rect.height - 1.5*self._caption_border_size)
+ dc.DrawLine(xstart, ystart, xend, yend)
+
+
+ def DrawCaption(self, dc, rect, captionText):
+ """
+ Draws the main caption text in :class:`ButtonPanel`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the main caption text rectangle;
+ :param string `captionText`: the caption text string.
+ """
+
+ textColour = self._caption_text_colour
+ textFont = self._caption_font
+ padding = self._padding_size
+
+ dc.SetTextForeground(textColour)
+ dc.SetFont(textFont)
+
+ dc.DrawText(captionText, rect.x + padding.x, rect.y+padding.y)
+
+
+ def DrawButton(self, dc, rect, buttonBitmap, isVertical, buttonStatus,
+ isToggled, textAlignment, text=""):
+ """
+ Draws a button in :class:`ButtonPanel`, together with its text (if any).
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the button client rectangle;
+ :param Bitmap `buttonBitmap`: the bitmap associated with the button;
+ :param bool `isVertical`: ``True`` if :class:`ButtonPanel` is in vertical orientation,
+ ``False`` otherwise;
+ :param string `buttonStatus`: one of "Normal", "Toggled", "Pressed", "Disabled" or "Hover";
+ :param bool `isToggled`: whether the button is toggled or not;
+ :param integer `textAlignment`: the text alignment inside the button;
+ :param string `text`: the button label.
+ """
+
+ bmpxsize, bmpysize = buttonBitmap.GetWidth(), buttonBitmap.GetHeight()
+ dx = dy = focus = 0
+
+ borderw = self._caption_border_size
+ padding = self._padding_size
+
+ buttonFont = self._buttontext_font
+ dc.SetFont(buttonFont)
+
+ if isVertical:
+
+ rect = wx.Rect(borderw, rect.y, rect.width-2*borderw, rect.height)
+
+ if text != "":
+
+ textW, textH = dc.GetTextExtent(text)
+
+ if textAlignment == BP_BUTTONTEXT_ALIGN_RIGHT:
+ fullExtent = bmpxsize + padding.x/2 + textW
+ bmpypos = rect.y + (rect.height - bmpysize)/2
+ bmpxpos = rect.x + (rect.width - fullExtent)/2
+ textxpos = bmpxpos + padding.x/2 + bmpxsize
+ textypos = bmpypos + (bmpysize - textH)/2
+ else:
+ bmpxpos = rect.x + (rect.width - bmpxsize)/2
+ bmpypos = rect.y + padding.y
+ textxpos = rect.x + (rect.width - textW)/2
+ textypos = bmpypos + bmpysize + padding.y/2
+ else:
+ bmpxpos = rect.x + (rect.width - bmpxsize)/2
+ bmpypos = rect.y + (rect.height - bmpysize)/2
+
+
+ else:
+
+ rect = wx.Rect(rect.x, borderw, rect.width, rect.height-2*borderw)
+
+ if text != "":
+
+ textW, textH = dc.GetTextExtent(text)
+
+ if textAlignment == BP_BUTTONTEXT_ALIGN_RIGHT:
+ fullExtent = bmpxsize + padding.x/2 + textW
+ bmpypos = rect.y + (rect.height - bmpysize)/2
+ bmpxpos = rect.x + (rect.width - fullExtent)/2
+ textxpos = bmpxpos + padding.x/2 + bmpxsize
+ textypos = bmpypos + (bmpysize - textH)/2
+ else:
+ fullExtent = bmpysize + padding.y/2 + textH
+ bmpxpos = rect.x + (rect.width - bmpxsize)/2
+ bmpypos = rect.y + (rect.height - fullExtent)/2
+ textxpos = rect.x + (rect.width - textW)/2
+ textypos = bmpypos + bmpysize + padding.y/2
+ else:
+ bmpxpos = rect.x + (rect.width - bmpxsize)/2
+ bmpypos = rect.y + (rect.height - bmpysize)/2
+
+ # Draw a button
+ # [ Padding | Text | .. Buttons .. | Padding ]
+
+ if buttonStatus in ["Pressed", "Toggled", "Hover"]:
+ dc.SetBrush(self._selection_brush)
+ dc.SetPen(self._selection_pen)
+ dc.DrawRoundedRectangleRect(rect, 4)
+
+ if buttonStatus == "Pressed" or isToggled:
+ dx = dy = 1
+
+ if buttonBitmap:
+ dc.DrawBitmap(buttonBitmap, bmpxpos+dx, bmpypos+dy, True)
+
+ if text != "":
+ isEnabled = buttonStatus != "Disabled"
+ self.DrawLabel(dc, text, isEnabled, textxpos+dx, textypos+dy)
+
+
+ def DrawLabel(self, dc, text, isEnabled, xpos, ypos):
+ """
+ Draws the label for a button.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param string `text`: the button label;
+ :param bool `isEnabled`: ``True`` if the button is enabled, ``False`` otherwise;
+ :param integer `xpos`: the text `x` position inside the button;
+ :param integer `ypos`: the text `y` position inside the button.
+ """
+
+ if not isEnabled:
+ dc.SetTextForeground(self._buttontext_inactive_colour)
+ else:
+ dc.SetTextForeground(self._buttontext_colour)
+
+ dc.DrawText(text, xpos, ypos)
+
+
+ def DrawButtonPanel(self, dc, rect, style):
+ """
+ Paint the :class:`ButtonPanel`'s background.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the :class:`ButtonPanel` client rectangle;
+ :param integer `style`: the :class:`ButtonPanel` window style.
+ """
+
+ if style & BP_USE_GRADIENT:
+ # Draw gradient colour in the backgroud of the panel
+ self.FillGradientColour(dc, rect)
+
+ # Draw a rectangle around the panel
+ backBrush = (style & BP_USE_GRADIENT and [wx.TRANSPARENT_BRUSH] or \
+ [self._background_brush])[0]
+
+ dc.SetBrush(backBrush)
+ dc.SetPen(self._border_pen)
+ dc.DrawRectangleRect(rect)
+
+
+ def FillGradientColour(self, dc, rect):
+ """
+ Gradient fill from colour 1 to colour 2 with top to bottom or left to right.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the :class:`ButtonPanel` client rectangle.
+ """
+
+ if rect.height < 1 or rect.width < 1:
+ return
+
+ isVertical = self._gradient_type == BP_GRADIENT_VERTICAL
+ size = (isVertical and [rect.height] or [rect.width])[0]
+ start = (isVertical and [rect.y] or [rect.x])[0]
+
+ # calculate gradient coefficients
+
+ col2 = self._gradient_colour_from
+ col1 = self._gradient_colour_to
+
+ rf, gf, bf = 0, 0, 0
+ rstep = float((col2.Red() - col1.Red()))/float(size)
+ gstep = float((col2.Green() - col1.Green()))/float(size)
+ bstep = float((col2.Blue() - col1.Blue()))/float(size)
+
+ for coord in xrange(start, start + size):
+
+ currCol = wx.Colour(col1.Red() + rf, col1.Green() + gf, col1.Blue() + bf)
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.SetPen(wx.Pen(currCol))
+ if isVertical:
+ dc.DrawLine(rect.x, coord, rect.x + rect.width, coord)
+ else:
+ dc.DrawLine(coord, rect.y, coord, rect.y + rect.height)
+
+ rf += rstep
+ gf += gstep
+ bf += bstep
+
+
+class StatusBarTimer(wx.Timer):
+ """ Timer used for deleting :class:`StatusBar` long help after ``_DELAY`` seconds."""
+
+ def __init__(self, owner):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `owner`: an instance of :class:`ButtonPanel`.
+ """
+
+ wx.Timer.__init__(self)
+ self._owner = owner
+
+
+ def Notify(self):
+ """ The timer has expired. """
+
+ self._owner.OnStatusBarTimer()
+
+
+class Control(wx.EvtHandler):
+ """
+ This class represents a base class for all pseudo controls used in
+ :class:`ButtonPanel`.
+ """
+
+ def __init__(self, parent, size=wx.Size(-1, -1), id=wx.ID_ANY):
+ """
+ Default class constructor.
+
+ :param Window `parent`: the control parent object. Must not be ``None``;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :type `size`: tuple or :class:`Size`
+ :param integer `id`: window identifier. A value of -1 indicates a default value.
+ """
+
+ wx.EvtHandler.__init__(self)
+
+ self._parent = parent
+
+ if id == wx.ID_ANY:
+ self._id = wx.NewId()
+ else:
+ self._id = id
+
+ self._size = size
+ self._isshown = True
+ self._focus = False
+
+
+ def Show(self, show=True):
+ """
+ Shows or hide the control.
+
+ :param bool `show`: If ``True`` displays the window. Otherwise, it hides it.
+ """
+
+ self._isshown = show
+
+
+ def Hide(self):
+ """
+ Hides the control.
+
+ :note: This is functionally equivalent of calling :meth:`~Control.Show` with a ``False`` input.
+ """
+
+ self.Show(False)
+
+
+ def IsShown(self):
+ """ Returns ``True`` if the window is shown, ``False`` if it has been hidden. """
+
+ return self._isshown
+
+
+ def GetId(self):
+ """
+ Returns the identifier of the window.
+
+ :return: An integer representing the identifier of the window.
+
+ :note: Each window has an integer identifier. If the application has not provided
+ one (or the default ``wx.ID_ANY``) an unique identifier with a negative value will
+ be generated.
+ """
+
+ return self._id
+
+
+ def GetBestSize(self):
+ """
+ This functions returns the best acceptable minimal size for the window. For
+ example, for a static control, it will be the minimal size such that the control
+ label is not truncated. For windows containing subwindows (typically :class:`Panel`),
+ the size returned by this function will be the same as the size the window would
+ have had after calling `Fit()`.
+
+ :return: An instance of :class:`Size`.
+ """
+
+ return self._size
+
+
+ def Disable(self):
+ """
+ Disables the control.
+
+ :returns: ``True`` if the window has been disabled, ``False`` if it had been
+ already disabled before the call to this function.
+
+ :note: This is functionally equivalent of calling :meth:`~Control.Enable` with a ``False`` flag.
+ """
+
+ return self.Enable(False)
+
+
+ def Enable(self, value=True):
+ """
+ Enable or disable the window for user input.
+
+ :param bool `enable`: If ``True``, enables the window for input. If ``False``, disables the window.
+
+ :returns: ``True`` if the window has been enabled or disabled, ``False`` if nothing was
+ done, i.e. if the window had already been in the specified state.
+
+ :note: Note that when a parent window is disabled, all of its children are disabled as
+ well and they are reenabled again when the parent is.
+ """
+
+ self.disabled = not value
+ return True
+
+
+ def SetFocus(self, focus=True):
+ """
+ Sets or kills the focus on the control.
+
+ :param bool `focus`: whether the control can receive keyboard inputs or not.
+ """
+
+ self._focus = focus
+
+
+ def HasFocus(self):
+ """
+ Returns whether the control has the focus or not.
+
+ :return: ``True`` if the control has the focus, ``False`` otherwise.
+ """
+
+ return self._focus
+
+
+ def OnMouseEvent(self, x, y, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` events for the control.
+
+ :param integer `x`: the mouse `x` position;
+ :param integer `y`: the mouse `y` position;
+ :param `event`: the :class:`MouseEvent` event to be processed.
+ """
+
+ pass
+
+
+ def Draw(self, rect):
+ """
+ Handles the drawing of the control.
+
+ :param Rect `rect`: the control client rectangle.
+ """
+
+ pass
+
+
+class Sizer(object):
+ """
+ This is a mix-in class to add pseudo support to :class:`Sizer`. Just create
+ a new class that derives from this class and :class:`Sizer` and intercepts
+ any methods that add to the wx sizer.
+ """
+
+ def __init__(self):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+ """
+
+ self.children = [] # list of child Pseudo Controls
+
+ # Sizer doesn't use the x1,y1,x2,y2 so allow it to
+ # be called with or without the coordinates
+ def Draw(self, dc, x1=0, y1=0, x2=0, y2=0):
+ """ Draws all the children of the sizer. """
+
+ for item in self.children:
+ # use sizer coordinates rather than
+ # what is passed in
+ c = item.GetUserData()
+ c.Draw(dc, item.GetRect())
+
+
+ def GetBestSize(self):
+ """
+ This functions returns the best acceptable minimal size for the sizer object.
+
+ :return: An instance of :class:`Size`.
+ """
+
+ # this should be handled by the wx.Sizer based class
+ return self.GetMinSize()
+
+
+# Pseudo BoxSizer
+class BoxSizer(Sizer, wx.BoxSizer):
+ """ Pseudo-class that imitates :class:`BoxSizer`. """
+
+ def __init__(self, orient=wx.HORIZONTAL):
+ """
+ Constructor for :class:`BoxSizer`.
+
+ :param integer `orient`: may be one of ``wx.VERTICAL`` or ``wx.HORIZONTAL`` for creating
+ either a column sizer or a row sizer.
+ """
+
+ wx.BoxSizer.__init__(self, orient)
+ Sizer.__init__(self)
+
+ #-------------------------------------------
+ # sizer overrides (only called from Python)
+ #-------------------------------------------
+ # no support for user data if it's a pseudocontrol
+ # since that is already used
+ def Add(self, item, proportion=0, flag=0, border=0, userData=None):
+ """
+ Appends a child item to the sizer.
+
+ :param `item`: the item to be added to :class:`BoxSizer`. Can be an instance of :class:`Window`,
+ :class:`Sizer` or a spacer;
+ :param integer `proportion`: this parameter is used in :class:`BoxSizer` to indicate if a child of
+ a sizer can change its size in the main orientation of the :class:`BoxSizer` - where 0
+ stands for not changeable and a value of more than zero is interpreted relative
+ to the value of other children of the same :class:`BoxSizer`. For example, you might have
+ a horizontal :class:`BoxSizer` with three children, two of which are supposed to change their
+ size with the sizer. Then the two stretchable windows would get a value of 1 each to
+ make them grow and shrink equally with the sizer's horizontal dimension.
+ :param integer `flag`: this parameter can be used to set a number of flags which can be combined using the binary OR operator ``|``.
+ Two main behaviours are defined using these flags. One is the border around a window: the border parameter determines the border
+ width whereas the flags given here determine which side(s) of the item that the border will be added. The other flags determine
+ how the sizer item behaves when the space allotted to the sizer changes, and is somewhat dependent on the specific kind of sizer used:
+
+ +---------------------------------------------------------------------+-----------------------------------------------------------------------------+
+ | Sizer Flag | Description |
+ +=====================================================================+=============================================================================+
+ | ``wx.TOP`` | These flags are used to specify which side(s) of the sizer |
+ +---------------------------------------------------------------------+ item the border width will apply to. |
+ | ``wx.BOTTOM`` | |
+ +---------------------------------------------------------------------+ |
+ | ``wx.LEFT`` | |
+ +---------------------------------------------------------------------+ |
+ | ``wx.RIGHT`` | |
+ +---------------------------------------------------------------------+ |
+ | ``wx.ALL`` | |
+ +---------------------------------------------------------------------+-----------------------------------------------------------------------------+
+ | ``wx.EXPAND`` | The item will be expanded to fill the space assigned to |
+ | | the item. |
+ +---------------------------------------------------------------------+-----------------------------------------------------------------------------+
+ | ``wx.SHAPED`` | The item will be expanded as much as possible while also |
+ | | maintaining its aspect ratio |
+ +---------------------------------------------------------------------+-----------------------------------------------------------------------------+
+ | ``wx.FIXED_MINSIZE`` | Normally :class:`Sizer` will use |
+ | | :meth:`Window.GetAdjustedBestSize` to |
+ | | determine what the minimal size of window items should be, and will use that|
+ | | size to calculate the layout. This allows layouts to adjust when an item |
+ | | changes and its best size becomes different. If you would rather have a |
+ | | window item stay the size it started with then use ``wx.FIXED_MINSIZE``. |
+ +---------------------------------------------------------------------+-----------------------------------------------------------------------------+
+ | ``wx.RESERVE_SPACE_EVEN_IF_HIDDEN`` | Normally `Sizers` don't allocate space for hidden windows or other items. |
+ | | This flag overrides this behavior so that sufficient space is allocated for |
+ | | the window even if it isn't visible. This makes it possible to dynamically |
+ | | show and hide controls without resizing parent dialog, for example. This |
+ | | function is new since wxWidgets version 2.8.8 |
+ +---------------------------------------------------------------------+-----------------------------------------------------------------------------+
+ | ``wx.ALIGN_CENTER`` **or** ``wx.ALIGN_CENTRE`` | The ``wx.ALIGN*`` flags allow you to specify the alignment of the item |
+ +---------------------------------------------------------------------+ within the space allotted to it by the sizer, adjusted for the border if |
+ | ``wx.ALIGN_LEFT`` | any. |
+ +---------------------------------------------------------------------+ |
+ | ``wx.ALIGN_RIGHT`` | |
+ +---------------------------------------------------------------------+ |
+ | ``wx.ALIGN_TOP`` | |
+ +---------------------------------------------------------------------+ |
+ | ``wx.ALIGN_BOTTOM`` | |
+ +---------------------------------------------------------------------+ |
+ | ``wx.ALIGN_CENTER_VERTICAL`` **or** ``wx.ALIGN_CENTRE_VERTICAL`` | |
+ +---------------------------------------------------------------------+ |
+ | ``wx.ALIGN_CENTER_HORIZONTAL`` **or** ``wx.ALIGN_CENTRE_HORIZONTAL``| |
+ +---------------------------------------------------------------------+-----------------------------------------------------------------------------+
+
+ :param integer `border`: determines the border width, if the flag parameter is set
+ to include any border flag.
+ :param object `userData`: Allows an extra object to be attached to the sizer item,
+ for use in derived classes when sizing information is more complex than the
+ proportion and flag will allow for.
+
+ :note: there is no support for `userData` parameter if `item` is a pseudocontrol,
+ since that is already used.
+ """
+
+ # check to see if it's a pseudo object or sizer
+ if isinstance(item, Sizer):
+ szitem = wx.BoxSizer.Add(self, item, proportion, flag, border, item)
+ self.children.append(szitem)
+ elif isinstance(item, Control): # Control should be what ever class your controls come from
+ sz = item.GetBestSize()
+ # add a spacer to track this object
+ szitem = wx.BoxSizer.Add(self, sz, proportion, flag, border, item)
+ self.children.append(szitem)
+ else:
+ wx.BoxSizer.Add(self, item, proportion, flag, border, userData)
+
+
+ def Prepend(self, item, proportion=0, flag=0, border=0, userData=None):
+ """
+ Prepends a child item to the sizer.
+
+ :see: :meth:`BoxSizer.Add` method for an explanation of the input parameters.
+ """
+
+ # check to see if it's a pseudo object or sizer
+ if isinstance(item, Sizer):
+ szitem = wx.BoxSizer.Prepend(self, item, proportion, flag, border, item)
+ self.children.append(szitem)
+ elif isinstance(item, Control): # Control should be what ever class your controls come from
+ sz = item.GetBestSize()
+ # add a spacer to track this object
+ szitem = wx.BoxSizer.Prepend(self, sz, proportion, flag, border, item)
+ self.children.insert(0,szitem)
+ else:
+ wx.BoxSizer.Prepend(self, item, proportion, flag, border, userData)
+
+
+ def Insert(self, before, item, proportion=0, flag=0, border=0, userData=None, realIndex=None):
+ """
+ Inserts a child item into the sizer.
+
+ :see: :meth:`BoxSizer.Add` method for an explanation of the input parameters.
+ """
+
+ # check to see if it's a pseudo object or sizer
+ if isinstance(item, Sizer):
+ szitem = wx.BoxSizer.Insert(self, before, item, proportion, flag, border, item)
+ self.children.append(szitem)
+ elif isinstance(item, Control): # Control should be what ever class your controls come from
+ sz = item.GetBestSize()
+ # add a spacer to track this object
+ szitem = wx.BoxSizer.Insert(self, before, sz, proportion, flag, border, item)
+ if realIndex is not None:
+ self.children.insert(realIndex,szitem)
+ else:
+ self.children.insert(before,szitem)
+
+ else:
+ wx.BoxSizer.Insert(self, before, item, proportion, flag, border, userData)
+
+
+ def Remove(self, indx, pop=-1):
+ """
+ Removes an item from the sizer and destroys it.
+
+ This method does not cause any layout or resizing to take place, call
+ :meth:`BoxSizer.Layout() <BoxSizer.Layout>` to update the layout on screen after removing a child from
+ the sizer.
+
+ :param integer `indx`: the zero-based index of an item to remove;
+ :param bool `pop`: whether to remove the sizer item from the list of children.
+ """
+
+ if pop >= 0:
+ self.children.pop(pop)
+
+ wx.BoxSizer.Remove(self, indx)
+
+
+ def Layout(self):
+ """
+ Call this to force layout of the children anew, e.g. after having added a
+ child to or removed a child (window, other sizer or space) from the sizer
+ while keeping the current dimension.
+ """
+
+ for ii, child in enumerate(self.GetChildren()):
+ item = child.GetUserData()
+ if item and child.IsShown():
+ self.SetItemMinSize(ii, *item.GetBestSize())
+
+ wx.BoxSizer.Layout(self)
+
+
+ def Show(self, item, show=True):
+ """
+ Shows or hides the sizer item.
+
+ :param `item`: the sizer item we want to show/hide;
+ :param bool `show`: ``True`` to show the item, ``False`` to hide it.
+ """
+
+ child = self.GetChildren()[item]
+ if child and child.GetUserData():
+ child.GetUserData().Show(show)
+
+ wx.BoxSizer.Show(self, item, show)
+
+
+# ---------------------------------------------------------------------------- #
+# Class Separator
+# This class holds all the information to size and draw a separator inside
+# ButtonPanel
+# ---------------------------------------------------------------------------- #
+
+class Separator(Control):
+ """
+ This class holds all the information to size and draw a separator inside
+ :class:`ButtonPanel`.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+
+ :param `parent`: the separator parent object, an instance of :class:`ButtonPanel`.
+ """
+
+ self._isshown = True
+ self._parent = parent
+ Control.__init__(self, parent)
+
+
+ def GetBestSize(self):
+ """
+ Returns the separator best size.
+
+ :return: An instance of :class:`Size`.
+ """
+
+ # 10 is completely arbitrary, but it works anyhow
+ if self._parent.IsVertical():
+ return wx.Size(10, self._parent._art.GetMetric(BP_SEPARATOR_SIZE))
+ else:
+ return wx.Size(self._parent._art.GetMetric(BP_SEPARATOR_SIZE), 10)
+
+
+ def Draw(self, dc, rect):
+ """
+ Draws the separator. Actually the drawing is done in :class:`BPArt`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the separator client rectangle.
+ """
+
+ if not self.IsShown():
+ return
+
+ isVertical = self._parent.IsVertical()
+ self._parent._art.DrawSeparator(dc, rect, isVertical)
+
+
+# ---------------------------------------------------------------------------- #
+# Class ButtonPanelText
+# This class is used to hold data about the main caption in ButtonPanel
+# ---------------------------------------------------------------------------- #
+
+class ButtonPanelText(Control):
+ """ This class is used to hold data about the main caption in :class:`ButtonPanel`. """
+
+ def __init__(self, parent, text=""):
+ """
+ Default class constructor.
+
+ :param `parent`: the text parent object, an instance of :class:`ButtonPanel`;
+ :param string `text`: the actual main caption string.
+ """
+
+ self._text = text
+ self._isshown = True
+ self._parent = parent
+
+ Control.__init__(self, parent)
+
+
+ def GetText(self):
+ """
+ Returns the caption text.
+
+ :return: A string representing the caption text.
+ """
+
+ return self._text
+
+
+ def SetText(self, text=""):
+ """
+ Sets the caption text.
+
+ :param string `text`: the main caption string.
+ """
+
+ self._text = text
+
+
+ def CreateDC(self):
+ """ Convenience function to create a :class:`DC`. """
+
+ dc = wx.ClientDC(self._parent)
+ textFont = self._parent._art.GetFont(BP_TEXT_FONT)
+ dc.SetFont(textFont)
+
+ return dc
+
+
+ def GetBestSize(self):
+ """
+ Returns the best size for the main caption in :class:`ButtonPanel`.
+
+ :return: An instance of :class:`Size`.
+ """
+
+ if self._text == "":
+ return wx.Size(0, 0)
+
+ dc = self.CreateDC()
+ rect = self._parent.GetClientRect()
+
+ tw, th = dc.GetTextExtent(self._text)
+ padding = self._parent._art.GetMetric(BP_PADDING_SIZE)
+ self._size = wx.Size(tw+2*padding.x, th+2*padding.y)
+
+ return self._size
+
+
+ def Draw(self, dc, rect):
+ """
+ Draws the main caption. Actually the drawing is done in :class:`BPArt`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the main caption text client rectangle.
+ """
+
+ if not self.IsShown():
+ return
+
+ captionText = self.GetText()
+ self._parent._art.DrawCaption(dc, rect, captionText)
+
+
+# -- ButtonInfo class implementation ----------------------------------------
+# This class holds information about every button that is added to
+# ButtonPanel. It is an auxiliary class that you should use
+# every time you add a button.
+
+class ButtonInfo(Control):
+ """
+ This class holds information about every button that is added to
+ :class:`ButtonPanel`. It is an auxiliary class that you should use
+ every time you add a button.
+ """
+ def __init__(self, parent, id=wx.ID_ANY, bmp=wx.NullBitmap,
+ status="Normal", text="", kind=wx.ITEM_NORMAL,
+ shortHelp="", longHelp=""):
+ """
+ Default class constructor.
+
+ :param `parent`: the parent window (:class:`ButtonPanel`);
+ :param integer `id`: the button id;
+ :param Bitmap `bmp`: the associated bitmap;
+ :param string `status`: button status ("Pressed", "Hover", "Normal", "Toggled", "Disabled");
+ :param string `text`: text to be displayed either below of to the right of the button;
+ :param integer `kind`: button kind, may be ``wx.ITEM_NORMAL`` for standard buttons or
+ ``wx.ITEM_CHECK`` for toggle buttons;
+ :param string `shortHelp`: a short help to be shown in the button tooltip;
+ :param string `longHelp`: this string is shown in the statusbar (if any) of the parent
+ frame when the mouse pointer is inside the button.
+ """
+
+ if id == wx.ID_ANY:
+ id = wx.NewId()
+
+ self._status = status
+ self._rect = wx.Rect()
+ self._text = text
+ self._kind = kind
+ self._toggle = False
+ self._textAlignment = BP_BUTTONTEXT_ALIGN_BOTTOM
+ self._shortHelp = shortHelp
+ self._longHelp = longHelp
+
+ if bmp and bmp.IsOk():
+ disabledbmp = MakeDisabledBitmap(bmp)
+ else:
+ disabledbmp = wx.NullBitmap
+
+ self._bitmaps = {"Normal": bmp, "Toggled": None, "Disabled": disabledbmp,
+ "Hover": None, "Pressed": None}
+
+ Control.__init__(self, parent, id=id)
+
+
+ def GetBestSize(self):
+ """
+ Returns the best size for the button.
+
+ :return: An instance of :class:`Size`.
+ """
+
+ xsize = self.GetBitmap().GetWidth()
+ ysize = self.GetBitmap().GetHeight()
+
+ if self.HasText():
+ # We have text in the button
+ dc = wx.ClientDC(self._parent)
+ normalFont = self._parent._art.GetFont(BP_BUTTONTEXT_FONT)
+ dc.SetFont(normalFont)
+ tw, th = dc.GetTextExtent(self.GetText())
+
+ if self.GetTextAlignment() == BP_BUTTONTEXT_ALIGN_BOTTOM:
+ xsize = max(xsize, tw)
+ ysize = ysize + th
+ else:
+ xsize = xsize + tw
+ ysize = max(ysize, th)
+
+ border = self._parent._art.GetMetric(BP_BORDER_SIZE)
+ padding = self._parent._art.GetMetric(BP_PADDING_SIZE)
+
+ if self._parent.IsVertical():
+ xsize = xsize + 2*border
+ else:
+ ysize = ysize + 2*border
+
+ self._size = wx.Size(xsize+2*padding.x, ysize+2*padding.y)
+
+ return self._size
+
+
+ def Draw(self, dc, rect):
+ """
+ Draws the button on :class:`ButtonPanel`. Actually the drawing is done in :class:`BPArt`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the main caption text client rectangle.
+ """
+
+ if not self.IsShown():
+ return
+
+ buttonBitmap = self.GetBitmap()
+ isVertical = self._parent.IsVertical()
+ text = self.GetText()
+ buttonStatus = self.GetStatus()
+ isToggled = self.GetToggled()
+ textAlignment = self.GetTextAlignment()
+
+ self._parent._art.DrawButton(dc, rect, buttonBitmap, isVertical,
+ buttonStatus, isToggled, textAlignment, text)
+
+ self.SetRect(rect)
+
+
+ def CheckRefresh(self, status):
+ """
+ Checks whether a :class:`ButtonPanel` repaint is needed or not. This is a convenience function.
+
+ :param bool `status`: the status of a newly added :class:`ButtonInfo` or a change in the
+ :class:`ButtonInfo` status.
+ """
+
+ if status == self._status:
+ self._parent.RefreshRect(self.GetRect())
+
+
+ def SetBitmap(self, bmp, status="Normal"):
+ """
+ Sets the bitmap associated with this instance of :class:`ButtonInfo`.
+
+ :param `bmp`: a valid :class:`Bitmap` object;
+ :param string `status`: the :class:`ButtonInfo` status ("Pressed", "Hover", "Normal",
+ "Toggled", "Disabled").
+ """
+
+ self._bitmaps[status] = bmp
+ self.CheckRefresh(status)
+
+
+ def GetBitmap(self, status=None):
+ """
+ Returns the bitmap associated with this instance of :class:`ButtonInfo`.
+
+ :param string `status`: the :class:`ButtonInfo` status ("Pressed", "Hover", "Normal",
+ "Toggled", "Disabled").
+
+ :return: An instance of :class:`Bitmap`.
+ """
+
+ if status is None:
+ status = self._status
+
+ if not self.IsEnabled():
+ status = "Disabled"
+
+ if self._bitmaps[status] is None:
+ if self.GetToggled():
+ if self._bitmaps["Toggled"] is not None:
+ return self._bitmaps["Toggled"]
+ return self._bitmaps["Normal"]
+
+ return self._bitmaps[status]
+
+
+ def GetRect(self):
+ """
+ Returns the :class:`ButtonInfo` client rectangle.
+
+ :return: An instance of :class:`Rect`.
+ """
+
+ return self._rect
+
+
+ def GetStatus(self):
+ """
+ Returns the :class:`ButtonInfo` status.
+
+ :return: A string containing the :class:`ButtonInfo` status (one of "Pressed", "Hover", "Normal",
+ "Toggled", "Disabled").
+ """
+
+ return self._status
+
+
+ def GetId(self):
+ """
+ Returns the :class:`ButtonInfo` id.
+
+ :return: An integer representing the button id.
+ """
+
+ return self._id
+
+
+ def SetRect(self, rect):
+ """
+ Sets the :class:`ButtonInfo` client rectangle.
+
+ :param `rect`: an instance of :class:`Rect`.
+ """
+
+ self._rect = rect
+
+
+ def SetStatus(self, status):
+ """
+ Sets the :class:`ButtonInfo` status.
+
+ :param string `status`: one of "Pressed", "Hover", "Normal", "Toggled", "Disabled".
+ """
+
+ if status == self._status:
+ return
+
+ if self.GetToggled() and status == "Normal":
+ status = "Toggled"
+
+ self._status = status
+ self._parent.RefreshRect(self.GetRect())
+
+
+ def GetTextAlignment(self):
+ """
+ Returns the text alignment in the button (bottom or right).
+
+ :return: An integer representing the :class:`ButtonInfo` text alignment.
+ """
+
+ return self._textAlignment
+
+
+ def SetTextAlignment(self, alignment):
+ """
+ Sets the text alignment in the button (bottom or right).
+
+ :param integer `alignment`: the text alignment in this :class:`ButtonInfo` instance.
+ """
+
+ if alignment == self._textAlignment:
+ return
+
+ self._textAlignment = alignment
+
+
+ def GetToggled(self):
+ """
+ Returns whether a ``wx.ITEM_CHECK`` button is toggled or not.
+
+ :return: ``True`` if the button is toggled, ``False`` otherwise.
+ """
+
+ if self._kind == wx.ITEM_NORMAL:
+ return False
+
+ return self._toggle
+
+
+ def SetToggled(self, toggle=True):
+ """
+ Sets a ``wx.ITEM_CHECK`` button toggled/not toggled.
+
+ :param bool `toggle`: ``True`` to toggle the button, ``False`` otherwise.
+ """
+
+ if self._kind == wx.ITEM_NORMAL:
+ return
+
+ self._toggle = toggle
+
+
+ def SetId(self, id):
+ """
+ Sets the :class:`ButtonInfo` identifier.
+
+ :param integer `id`: the identifier of the window.
+ """
+
+ self._id = id
+
+
+ def AddStatus(self, name="Custom", bmp=wx.NullBitmap):
+ """
+ Add a programmer-defined status in addition to the 5 default status:
+
+ - Normal;
+ - Disabled;
+ - Hover;
+ - Pressed;
+ - Toggled.
+
+ :param string `name`: the new status name;
+ :param Bitmap `bmp`: the bitmap associated with the new status.
+ """
+
+ self._bitmaps.update({name: bmp})
+
+
+ def Enable(self, enable=True):
+ """
+ Enables/disables this instance of :class:`ButtonInfo`.
+
+ :param bool `enable`: ``True`` to enable the button, ``False`` otherwise.
+ """
+
+ if enable:
+ self._status = "Normal"
+ else:
+ self._status = "Disabled"
+
+
+ def IsEnabled(self):
+ """
+ Returns ``True`` if this instance of :class:`ButtonInfo` is enabled for input,
+ ``False`` otherwise.
+ """
+
+ return self._status != "Disabled"
+
+
+ def SetText(self, text=""):
+ """
+ Sets the button label text.
+
+ :param string `text`: the button label string.
+ """
+
+ self._text = text
+
+
+ def GetText(self):
+ """
+ Returns the text associated to the button.
+
+ :return: A string containing the :class:`ButtonInfo` text.
+ """
+
+ return self._text
+
+
+ def HasText(self):
+ """
+ Returns whether the button has text or not.
+
+ :return: ``True`` if this :class:`ButtonInfo` instance has a label, ``False`` otherwise.
+ """
+
+ return self._text != ""
+
+
+ def SetKind(self, kind=wx.ITEM_NORMAL):
+ """
+ Sets the button type (standard or toggle).
+
+ :param integer `kind`: one of ``wx.ITEM_NORMAL``, ``wx.ITEM_CHECK``.
+ """
+
+ self._kind = kind
+
+
+ def GetKind(self):
+ """
+ Returns the button type (standard or toggle).
+
+ :return: An integer representing the button type, one of ``wx.ITEM_NORMAL``, ``wx.ITEM_CHECK``.
+ """
+
+ return self._kind
+
+
+ def SetShortHelp(self, help=""):
+ """
+ Sets the help string to be shown in a tooltip.
+
+ :param string `help`: the string for the short help.
+ """
+
+ self._shortHelp = help
+
+
+ def GetShortHelp(self):
+ """
+ Returns the help string shown in a tooltip.
+
+ :return: A string containing the :class:`ButtonInfo` short help string.
+ """
+
+ return self._shortHelp
+
+
+ def SetLongHelp(self, help=""):
+ """
+ Sets the help string to be shown in the statusbar.
+
+ :param string `help`: the string for the long help.
+ """
+
+ self._longHelp = help
+
+
+ def GetLongHelp(self):
+ """
+ Returns the help string shown in the statusbar.
+
+ :return: A string containing the :class:`ButtonInfo` long help string.
+ """
+
+ return self._longHelp
+
+
+ Bitmap = property(GetBitmap, SetBitmap)
+ Id = property(GetId, SetId)
+ Rect = property(GetRect, SetRect)
+ Status = property(GetStatus, SetStatus)
+
+
+# -- ButtonPanel class implementation ----------------------------------
+# This is the main class.
+
+class ButtonPanel(wx.PyPanel):
+ """
+ A custom panel class with gradient background shading with the possibility to
+ add buttons and controls still respecting the gradient background.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, text="", agwStyle=BP_DEFAULT_STYLE,
+ alignment=BP_ALIGN_LEFT, name="buttonPanel"):
+ """
+ Default class constructor.
+
+ :param Window `parent`: the parent window. Must not be ``None``;
+ :param integer `id`: window identifier. If ``wx.ID_ANY``, will automatically create an identifier;
+ :param string `text`: the main caption text for :class:`ButtonPanel`;
+ :param integer `agwStyle`: the AGW-specific window style (one of ``BP_DEFAULT_STYLE``, ``BP_USE_GRADIENT``);
+ :param integer `alignment`: alignment of buttons (left or right);
+ :param string `name`: window class name.
+ """
+
+ wx.PyPanel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize,
+ wx.NO_BORDER, name=name)
+
+ self._vButtons = []
+ self._vSeparators = []
+
+ self._agwStyle = agwStyle
+ self._alignment = alignment
+ self._statusTimer = None
+ self._useHelp = True
+ self._freezeCount = 0
+ self._currentButton = -1
+ self._haveTip = False
+
+ self._art = BPArt(agwStyle)
+
+ self._controlCreated = False
+
+ direction = (self.IsVertical() and [wx.VERTICAL] or [wx.HORIZONTAL])[0]
+ self._mainsizer = BoxSizer(direction)
+ self.SetSizer(self._mainsizer)
+
+ margins = self._art.GetMetric(BP_MARGINS_SIZE)
+
+ # First spacer to create some room before the first text/button/control
+ self._mainsizer.Add((margins.x, margins.y), 0)
+
+ # Last spacer to create some room before the last text/button/control
+ self._mainsizer.Add((margins.x, margins.y), 0)
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow)
+
+ self.SetBarText(text)
+ self.LayoutItems()
+
+
+ def SetBarText(self, text):
+ """
+ Sets the main caption text.
+
+ :param string `text`: the main caption text label. An empty string erases the
+ main caption text.
+ """
+
+ self.Freeze()
+
+ text = text.strip()
+
+ if self._controlCreated:
+ self.RemoveText()
+
+ self._text = ButtonPanelText(self, text)
+ lenChildren = len(self._mainsizer.GetChildren())
+
+ if text == "":
+ # Even if we have no text, we insert it an empty spacer anyway
+ # it is easier to handle if you have to recreate the sizer after.
+ if self.IsStandard():
+ self._mainsizer.Insert(1, self._text, 0, wx.ALIGN_CENTER,
+ userData=self._text, realIndex=0)
+ else:
+ self._mainsizer.Insert(lenChildren-1, self._text, 0, wx.ALIGN_CENTER,
+ userData=self._text, realIndex=lenChildren)
+
+ return
+
+ # We have text, so insert the text and an expandable spacer
+ # alongside it. "Standard" ButtonPanel are left or top aligned.
+ if self.IsStandard():
+ self._mainsizer.Insert(1, self._text, 0, wx.ALIGN_CENTER,
+ userData=self._text, realIndex=0)
+ self._mainsizer.Insert(2, (0, 0), 1, wx.EXPAND)
+
+ else:
+ self._mainsizer.Insert(lenChildren-1, self._text, 0, wx.ALIGN_CENTER,
+ userData=self._text, realIndex=lenChildren)
+ self._mainsizer.Insert(lenChildren-1, (0, 0), 1, wx.EXPAND)
+
+
+ def RemoveText(self):
+ """ Removes the main caption text. """
+
+ lenChildren = len(self._mainsizer.GetChildren())
+ lenCustom = len(self._vButtons) + len(self._vSeparators) + 1
+
+ if self.IsStandard():
+ # Detach the text
+ self._mainsizer.Remove(1, 0)
+ if self.HasBarText():
+ # Detach the expandable spacer
+ self._mainsizer.Remove(1, -1)
+ else:
+ # Detach the text
+ self._mainsizer.Remove(lenChildren-2, lenCustom-1)
+ if self.HasBarText():
+ # Detach the expandable spacer
+ self._mainsizer.Remove(lenChildren-3, -1)
+
+
+ def GetBarText(self):
+ """
+ Returns the main caption text.
+
+ :return: A string representing the caption text.
+ """
+
+ return self._text.GetText()
+
+
+ def HasBarText(self):
+ """
+ Returns whether :class:`ButtonPanel` has a main caption text or not.
+
+ :return: ``True`` if :class:`ButtonPanel` has a main caption text, ``False`` otherwise.
+ """
+
+ return hasattr(self, "_text") and self._text.GetText() != ""
+
+
+ def AddButton(self, btnInfo):
+ """
+ Adds a button to :class:`ButtonPanel`.
+
+ :param `btnInfo`: an instance of :class:`ButtonInfo`.
+
+ :note: Remember to pass a :class:`ButtonInfo` instance to this method, and not a
+ standard :class:`Button` or a :class:`ToolBar` tool.
+ """
+
+ lenChildren = len(self._mainsizer.GetChildren())
+ self._mainsizer.Insert(lenChildren-1, btnInfo, 0, wx.ALIGN_CENTER|wx.EXPAND, userData=btnInfo)
+
+ self._vButtons.append(btnInfo)
+
+
+ def AddSpacer(self, size=(0, 0), proportion=1, flag=wx.EXPAND):
+ """
+ Adds a spacer (stretchable or fixed-size) to :class:`ButtonPanel`.
+
+ :param tuple `size`: the spacer size as a tuple;
+ :param integer `proportion`: the spacer proportion (0 for fixed-size, 1 or more for a
+ stretchable one);
+ :param integer `flag`: one of the :class:`BoxSizer` flags.
+ """
+
+ lenChildren = len(self._mainsizer.GetChildren())
+ self._mainsizer.Insert(lenChildren-1, size, proportion, flag)
+
+
+ def AddControl(self, control, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=None):
+ """
+ Adds a wxPython control to :class:`ButtonPanel`.
+
+ :param `control`: an instance of :class:`Window`;
+ :param integer `proportion`: the control proportion (0 for fixed-size, 1 or more for a
+ stretchable one);
+ :param integer `flag`: one of the :class:`BoxSizer` flags;
+ :param integer `border`: the control border width (in pixels), if the `flag` parameter
+ is set to include any border flag.
+ """
+
+ lenChildren = len(self._mainsizer.GetChildren())
+
+ if border is None:
+ border = self._art.GetMetric(BP_PADDING_SIZE)
+ border = max(border.x, border.y)
+
+ self._mainsizer.Insert(lenChildren-1, control, proportion, flag, border)
+
+
+ def AddSeparator(self):
+ """ Adds a separator line to :class:`ButtonPanel`. """
+
+ lenChildren = len(self._mainsizer.GetChildren())
+ separator = Separator(self)
+
+ self._mainsizer.Insert(lenChildren-1, separator, 0, wx.EXPAND)
+ self._vSeparators.append(separator)
+
+
+ def RemoveAllButtons(self):
+ """
+ Remove all the buttons from :class:`ButtonPanel`.
+
+ :note: This function is for internal use only. If you are interested in
+ manipulating a :class:`ButtonPanel` in real time (ie. removing things on it)
+ have a look at the :meth:`~ButtonPanel.Clear` method.
+ """
+
+ self._vButtons = []
+
+
+ def RemoveAllSeparators(self):
+ """
+ Remove all the separators from :class:`ButtonPanel`.
+
+ :note: This function is for internal use only. If you are interested in
+ manipulating a :class:`ButtonPanel` in real time (ie. removing things on it)
+ have a look at the :meth:`~ButtonPanel.Clear` method.
+ """
+
+ self._vSeparators = []
+
+
+ def Clear(self):
+ """
+ Clears the :class:`ButtonPanel`.
+
+ Can be used to reset the :class:`ButtonPanel` if you'd like have a new set of
+ buttons on the panel.
+ """
+
+ if self.HasBarText():
+ bartext = self.GetBarText()
+ else:
+ bartext = None
+
+ self.Freeze()
+
+ self._currentButton = -1
+ self._mainsizer.Clear()
+ self.ReCreateSizer(bartext)
+
+
+ def GetAlignment(self):
+ """
+ Returns the buttons alignment.
+
+ :return: An integer specifying the buttons alignment.
+
+ :see: :meth:`~ButtonPanel.SetAlignment` for a set of valid alignment bits.
+ """
+
+ return self._alignment
+
+
+ def SetAlignment(self, alignment):
+ """
+ Sets the buttons alignment.
+
+ :param integer `alignment`: can be one of the following bits:
+
+ ====================== ======= ==========================
+ Alignment Flag Value Description
+ ====================== ======= ==========================
+ ``BP_ALIGN_RIGHT`` 1 Buttons are aligned on the right
+ ``BP_ALIGN_LEFT`` 2 Buttons are aligned on the left
+ ``BP_ALIGN_TOP`` 4 Buttons are aligned at the top
+ ``BP_ALIGN_BOTTOM`` 8 Buttons are aligned at the bottom
+ ====================== ======= ==========================
+ """
+
+ if alignment == self._alignment:
+ return
+
+ self.Freeze()
+
+ text = self.GetBarText()
+
+ # Remove the text in any case
+ self.RemoveText()
+
+ # Remove the first and last spacers
+ self._mainsizer.Remove(0, -1)
+ self._mainsizer.Remove(len(self._mainsizer.GetChildren())-1, -1)
+
+ self._alignment = alignment
+
+ # Recreate the sizer accordingly to the new alignment
+ self.ReCreateSizer(text)
+
+
+ def IsVertical(self):
+ """
+ Returns whether :class:`ButtonPanel` is vertically aligned or not.
+
+ :return: ``True`` if :class:`ButtonPanel` is vertically aligned, ``False`` otherwise.
+ """
+
+ return self._alignment not in [BP_ALIGN_RIGHT, BP_ALIGN_LEFT]
+
+
+ def IsStandard(self):
+ """
+ Returns whether :class:`ButtonPanel` is aligned "Standard" (left/top) or not.
+
+ :return: ``True`` if :class:`ButtonPanel` is aligned "standard", ``False`` otherwise.
+ """
+
+ return self._alignment in [BP_ALIGN_LEFT, BP_ALIGN_TOP]
+
+
+ def DoLayout(self):
+ """
+ Do the Layout for :class:`ButtonPanel`.
+
+ :note: Call this method every time you make a modification to the layout
+ or to the customizable sizes of the pseudo controls.
+ """
+
+ margins = self._art.GetMetric(BP_MARGINS_SIZE)
+ lenChildren = len(self._mainsizer.GetChildren())
+
+ self._mainsizer.SetItemMinSize(0, (margins.x, margins.y))
+ self._mainsizer.SetItemMinSize(lenChildren-1, (margins.x, margins.y))
+
+ self._controlCreated = True
+ self.LayoutItems()
+
+ # *VERY* WEIRD: the sizer seems not to respond to any layout until I
+ # change the ButtonPanel size and restore it back
+ size = self.GetSize()
+ self.SetSize((size.x+1, size.y+1))
+ self.SetSize((size.x, size.y))
+
+ if self.IsFrozen():
+ self.Thaw()
+
+
+ def ReCreateSizer(self, text=None):
+ """
+ Recreates the :class:`ButtonPanel` sizer accordingly to the alignment specified.
+
+ :param string `text`: the text to display as main caption. If `text` is set to ``None``,
+ the main caption will not be displayed.
+ """
+
+ children = self._mainsizer.GetChildren()
+ self.RemoveAllButtons()
+ self.RemoveAllSeparators()
+
+ # Create a new sizer depending on the alignment chosen
+ direction = (self.IsVertical() and [wx.VERTICAL] or [wx.HORIZONTAL])[0]
+ self._mainsizer = BoxSizer(direction)
+
+ margins = self._art.GetMetric(BP_MARGINS_SIZE)
+ # First spacer to create some room before the first text/button/control
+ self._mainsizer.Add((margins.x, margins.y), 0)
+
+ # Last spacer to create some room before the last text/button/control
+ self._mainsizer.Add((margins.x, margins.y), 0)
+
+ # This is needed otherwise SetBarText goes mad
+ self._controlCreated = False
+
+ for child in children:
+ userData = child.GetUserData()
+ if userData:
+ if isinstance(userData, ButtonInfo):
+ # It is a ButtonInfo, can't be anything else
+ self.AddButton(child.GetUserData())
+ elif isinstance(userData, Separator):
+ self.AddSeparator()
+
+ else:
+ if child.IsSpacer():
+ # This is a spacer, expandable or not
+ self.AddSpacer(child.GetSize(), child.GetProportion(),
+ child.GetFlag())
+ else:
+ # This is a wxPython control
+ self.AddControl(child.GetWindow(), child.GetProportion(),
+ child.GetFlag(), child.GetBorder())
+
+ self.SetSizer(self._mainsizer)
+
+ if text is not None:
+ self.SetBarText(text)
+
+ self.DoLayout()
+
+ self.Thaw()
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits :class:`ButtonPanel`: for a control, it would be
+ the minimal size which doesn't truncate the control, for a panel - the
+ same size as it would have after a call to `Fit()`.
+
+ :return: An instance of :class:`Size`.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ w = h = btnWidth = btnHeight = 0
+ isVertical = self.IsVertical()
+
+ padding = self._art.GetMetric(BP_PADDING_SIZE)
+ border = self._art.GetMetric(BP_BORDER_SIZE)
+ margins = self._art.GetMetric(BP_MARGINS_SIZE)
+ separator_size = self._art.GetMetric(BP_SEPARATOR_SIZE)
+
+ # Add the space required for the main caption
+ if self.HasBarText():
+ w, h = self._text.GetBestSize()
+ if isVertical:
+ h += padding.y
+ else:
+ w += padding.x
+ else:
+ w = h = border
+
+ # Add the button's sizes
+ for btn in self._vButtons:
+
+ bw, bh = btn.GetBestSize()
+ btnWidth = max(btnWidth, bw)
+ btnHeight = max(btnHeight, bh)
+
+ if isVertical:
+ w = max(w, btnWidth)
+ h += bh
+ else:
+ h = max(h, btnHeight)
+ w += bw
+
+ # Add the control's sizes
+ for control in self.GetControls():
+ cw, ch = control.GetSize()
+ if isVertical:
+ h += ch
+ w = max(w, cw)
+ else:
+ w += cw
+ h = max(h, ch)
+
+ # Add the separator's sizes and the 2 SizerItems at the beginning
+ # and at the end
+ if self.IsVertical():
+ h += 2*margins.y + len(self._vSeparators)*separator_size
+ else:
+ w += 2*margins.x + len(self._vSeparators)*separator_size
+
+ return wx.Size(w, h)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`ButtonPanel`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+ rect = self.GetClientRect()
+
+ self._art.DrawButtonPanel(dc, rect, self._agwStyle)
+ self._mainsizer.Draw(dc)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`ButtonPanel`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`ButtonPanel`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+
+ .. todo::
+
+ Improve the chain of methods :meth:`~ButtonPanel.OnSize` ==> :meth:`~ButtonPanel.DoLayout` ==> :meth:`~ButtonPanel.LayoutItems`
+ to avoid multiple calls to :meth:`~ButtonPanel.LayoutItems`.
+ """
+
+ # NOTE: It seems like LayoutItems number of calls can be optimized in some way.
+ # Currently every DoLayout (or every parent Layout()) calls about 3 times
+ # the LayoutItems method. Any idea on how to improve it?
+ self.LayoutItems()
+ self.Refresh()
+
+ event.Skip()
+
+
+ def LayoutItems(self):
+ """
+ Layout the items using a different algorithms depending on the existance
+ of the main caption.
+ """
+
+ nonspacers, allchildren = self.GetNonFlexibleChildren()
+
+ if self.HasBarText():
+ self.FlexibleLayout(nonspacers, allchildren)
+ else:
+ self.SizeLayout(nonspacers, allchildren)
+
+ self._mainsizer.Layout()
+
+
+ def SizeLayout(self, nonspacers, children):
+ """
+ Layout the items when no main caption exists.
+
+ :param list `nonspacers`: a list of items which are not spacers;
+ :param list `children`: a list of all the children of :class:`ButtonPanel`.
+ """
+
+ size = self.GetSize()
+ isVertical = self.IsVertical()
+
+ corner = 0
+ indx1 = len(nonspacers)
+
+ for item in nonspacers:
+ corner += self.GetItemSize(item, isVertical)
+ if corner > size[isVertical]:
+ indx1 = nonspacers.index(item)
+ break
+
+ # Leave out the last spacer, it has to be there always
+ for ii in xrange(len(nonspacers)-1):
+ indx = children.index(nonspacers[ii])
+ self._mainsizer.Show(indx, ii < indx1)
+
+
+ def GetItemSize(self, item, isVertical):
+ """
+ Returns the size of an item in the main :class:`ButtonPanel` sizer.
+
+ :param `item`: an instance of :class:`ButtonInfo`;
+ :param bool `isVertical`: ``True`` if :class:`ButtonPanel` is in vertical orientation,
+ ``False`` otherwise.
+
+ :return: An instance of :class:`Size`.
+ """
+
+ if item.GetUserData():
+ return item.GetUserData().GetBestSize()[isVertical]
+ else:
+ return item.GetSize()[isVertical]
+
+
+ def FlexibleLayout(self, nonspacers, allchildren):
+ """
+ Layout the items when the main caption exists.
+
+ :param list `nonspacers`: a list of items which are not spacers;
+ :param list `allchildren`: a list of all the children of :class:`ButtonPanel`.
+ """
+
+ if len(nonspacers) < 2:
+ return
+
+ isVertical = self.IsVertical()
+ isStandard = self.IsStandard()
+
+ size = self.GetSize()[isVertical]
+ padding = self._art.GetMetric(BP_PADDING_SIZE)
+
+ fixed = (isStandard and [nonspacers[1]] or [nonspacers[-2]])[0]
+
+ if isStandard:
+ nonspacers.reverse()
+ leftendx = fixed.GetSize()[isVertical] + padding.x
+ else:
+ rightstartx = size - fixed.GetSize()[isVertical]
+ size = 0
+
+ count = lennonspacers = len(nonspacers)
+
+ for item in nonspacers:
+ if isStandard:
+ size -= self.GetItemSize(item, isVertical)
+ if size < leftendx:
+ break
+ else:
+ size += self.GetItemSize(item, isVertical)
+ if size > rightstartx:
+ break
+
+ count = count - 1
+
+ nonspacers.reverse()
+
+ for jj in xrange(2, lennonspacers):
+ indx = allchildren.index(nonspacers[jj])
+ self._mainsizer.Show(indx, jj >= count)
+
+
+ def GetNonFlexibleChildren(self):
+ """
+ Returns all the :class:`ButtonPanel` main sizer's children that are not
+ flexible spacers.
+
+ :return: A list of items inside :class:`ButtonPanel` that are not flexible spacers.
+ """
+
+ children1 = []
+ children2 = list(self._mainsizer.GetChildren())
+
+ for child in children2:
+ if child.IsSpacer():
+ if child.GetUserData() or child.GetProportion() == 0:
+ children1.append(child)
+ else:
+ children1.append(child)
+
+ return children1, children2
+
+
+ def GetControls(self):
+ """
+ Returns the wxPython controls that belongs to :class:`ButtonPanel`.
+
+ :return: A list of items inside :class:`ButtonPanel` that are wxPython controls.
+ """
+
+ children2 = self._mainsizer.GetChildren()
+ children1 = [child for child in children2 if not child.IsSpacer()]
+
+ return children1
+
+
+ def SetStyle(self, agwStyle):
+ """
+ Sets the :class:`ButtonPanel` window style.
+
+ :param integer `agwStyle`: one of the following bits:
+
+ ==================== =========== ==================================================
+ Window Styles Hex Value Description
+ ==================== =========== ==================================================
+ ``BP_DEFAULT_STYLE`` 0x1 :class:`ButtonPanel` has a plain solid background.
+ ``BP_USE_GRADIENT`` 0x2 :class:`ButtonPanel` has a gradient shading background.
+ ==================== =========== ==================================================
+
+ """
+
+ if agwStyle == self._agwStyle:
+ return
+
+ self._agwStyle = agwStyle
+ self.Refresh()
+
+
+ def GetStyle(self):
+ """
+ Returns the :class:`ButtonPanel` window style.
+
+ :see: :meth:`~ButtonPanel.SetStyle` for a list of valid window styles.
+ """
+
+ return self._agwStyle
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`ButtonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # Check to see if we are hovering a button
+ tabId, flags = self.HitTest(event.GetPosition())
+
+ if flags != BP_HT_BUTTON:
+ self.RemoveHelp()
+ self.RepaintOldSelection()
+ self._currentButton = -1
+ return
+
+ btn = self._vButtons[tabId]
+
+ if not btn.IsEnabled():
+ self.RemoveHelp()
+ self.RepaintOldSelection()
+ return
+
+ if tabId != self._currentButton:
+ self.RepaintOldSelection()
+
+ if btn.GetRect().Contains(event.GetPosition()):
+ if btn.GetStatus() != "Pressed":
+ btn.SetStatus("Hover")
+ else:
+ btn.SetStatus("Normal")
+
+ if tabId != self._currentButton:
+ self.RemoveHelp()
+ self.DoGiveHelp(btn)
+
+ self._currentButton = tabId
+
+ event.Skip()
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`ButtonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ tabId, hit = self.HitTest(event.GetPosition())
+
+ if hit == BP_HT_BUTTON:
+ btn = self._vButtons[tabId]
+ if btn.IsEnabled():
+ btn.SetStatus("Pressed")
+ self._currentButton = tabId
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`ButtonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ tabId, flags = self.HitTest(event.GetPosition())
+
+ if flags != BP_HT_BUTTON:
+ return
+
+ hit = self._vButtons[tabId]
+
+ if hit.GetStatus() == "Disabled":
+ return
+
+ for btn in self._vButtons:
+ if btn != hit:
+ btn.SetFocus(False)
+
+ if hit.GetStatus() == "Pressed":
+ hit.SetToggled(not hit.GetToggled())
+
+ # Update the button status to be hovered
+ hit.SetStatus("Hover")
+ hit.SetFocus()
+ self._currentButton = tabId
+
+ # Fire a button click event
+ btnEvent = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, hit.GetId())
+ btnEvent.SetEventObject(hit)
+ self.GetEventHandler().ProcessEvent(btnEvent)
+
+
+ def OnMouseLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`ButtonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # Reset all buttons statuses
+ for btn in self._vButtons:
+ if not btn.IsEnabled():
+ continue
+ btn.SetStatus("Normal")
+
+ self.RemoveHelp()
+
+ event.Skip()
+
+
+ def OnMouseEnterWindow(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`ButtonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ tabId, flags = self.HitTest(event.GetPosition())
+
+ if flags == BP_HT_BUTTON:
+
+ hit = self._vButtons[tabId]
+
+ if hit.GetStatus() == "Disabled":
+ event.Skip()
+ return
+
+ self.DoGiveHelp(hit)
+ self._currentButton = tabId
+
+ event.Skip()
+
+
+ def DoGiveHelp(self, hit):
+ """
+ Shows tooltips and long help strings in :class:`StatusBar`.
+
+ :param `hit`: an instance of :class:`ButtonInfo` where the mouse is hovering.
+ """
+
+ if not self.GetUseHelp():
+ return
+
+ shortHelp = hit.GetShortHelp()
+ if shortHelp:
+ self.SetToolTipString(shortHelp)
+ self._haveTip = True
+
+ longHelp = hit.GetLongHelp()
+ if not longHelp:
+ return
+
+ topLevel = wx.GetTopLevelParent(self)
+
+ if isinstance(topLevel, wx.Frame) and topLevel.GetStatusBar():
+ statusBar = topLevel.GetStatusBar()
+
+ if self._statusTimer and self._statusTimer.IsRunning():
+ self._statusTimer.Stop()
+ statusBar.PopStatusText(0)
+
+ statusBar.PushStatusText(longHelp, 0)
+ self._statusTimer = StatusBarTimer(self)
+ self._statusTimer.Start(_DELAY, wx.TIMER_ONE_SHOT)
+
+
+ def RemoveHelp(self):
+ """ Removes the tooltips and statusbar help (if any) for a button. """
+
+ if not self.GetUseHelp():
+ return
+
+ if self._haveTip:
+ self.SetToolTipString("")
+ self._haveTip = False
+
+ if self._statusTimer and self._statusTimer.IsRunning():
+ topLevel = wx.GetTopLevelParent(self)
+ statusBar = topLevel.GetStatusBar()
+ self._statusTimer.Stop()
+ statusBar.PopStatusText(0)
+ self._statusTimer = None
+
+
+ def RepaintOldSelection(self):
+ """ Repaints the old selected/hovered button. """
+
+ current = self._currentButton
+
+ if current == -1:
+ return
+
+ btn = self._vButtons[current]
+ if not btn.IsEnabled():
+ return
+
+ btn.SetStatus("Normal")
+
+
+ def OnStatusBarTimer(self):
+ """ Handles the timer expiring to delete the long help string in :class:`StatusBar`. """
+
+ topLevel = wx.GetTopLevelParent(self)
+ statusBar = topLevel.GetStatusBar()
+ statusBar.PopStatusText(0)
+
+
+ def SetUseHelp(self, useHelp=True):
+ """
+ Sets whether or not short and long help strings should be displayed as tooltips
+ and :class:`StatusBar` items respectively.
+
+ :param bool `useHelp`: ``True`` to display short and long help strings as tooltips
+ and :class:`StatusBar` items respectively, ``False`` otherwise.
+ """
+
+ self._useHelp = useHelp
+
+
+ def GetUseHelp(self):
+ """
+ Returns whether or not short and long help strings should be displayed as tooltips
+ and :class:`StatusBar` items respectively.
+
+ :return: ``True`` if the short and long help strings should be displayed as tooltips
+ and :class:`StatusBar` items respectively, ``False`` otherwise.
+ """
+
+ return self._useHelp
+
+
+ def HitTest(self, pt):
+ """
+ HitTest method for :class:`ButtonPanel`.
+
+ :param `pt`: the mouse position, an instance of :class:`Point`.
+
+ :returns: an instance of :class:`ButtonInfo` and the hit flag ``BP_HT_BUTTON`` if a button
+ client rectangle contains the input point `pt`, or ``wx.NOT_FOUND`` and ``BP_HT_NONE``.
+ """
+
+ for ii in xrange(len(self._vButtons)):
+ if not self._vButtons[ii].IsEnabled():
+ continue
+ if self._vButtons[ii].GetRect().Contains(pt):
+ return ii, BP_HT_BUTTON
+
+ return wx.NOT_FOUND, BP_HT_NONE
+
+
+ def GetBPArt(self):
+ """ Returns the associated :class:`BPArt` art provider. """
+
+ return self._art
+
+
+ def SetBPArt(self, art):
+ """
+ Sets a new :class:`BPArt` art provider to :class:`ButtonPanel`.
+
+ :param `art`: an instance of :class:`BPArt`.
+ """
+
+ self._art = art
+ self.Refresh()
+
+
+ if wx.VERSION < (2,7,1,1):
+ def Freeze(self):
+ """
+ Freezes the window or, in other words, prevents any updates from taking place
+ on screen, the window is not redrawn at all. :meth:`~ButtonPanel.Thaw` must be called to reenable
+ window redrawing. Calls to these two functions may be nested.
+
+ :note: This method is useful for visual appearance optimization.
+ """
+
+ self._freezeCount = self._freezeCount + 1
+ wx.PyPanel.Freeze(self)
+
+
+ def Thaw(self):
+ """
+ Reenables window updating after a previous call to :meth:`~ButtonPanel.Freeze`. To really thaw the
+ control, it must be called exactly the same number of times as :meth:`~ButtonPanel.Freeze`.
+ """
+
+ if self._freezeCount == 0:
+ raise Exception("\nERROR: Thawing Unfrozen ButtonPanel?")
+
+ self._freezeCount = self._freezeCount - 1
+ wx.PyPanel.Thaw(self)
+
+
+ def IsFrozen(self):
+ """ Returns ``True`` if the window is currently frozen by a call to :meth:`~ButtonPanel.Freeze`. """
+
+ return self._freezeCount != 0
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/cubecolourdialog.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/cubecolourdialog.py
new file mode 100644
index 0000000..3be5964
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/cubecolourdialog.py
@@ -0,0 +1,3494 @@
+# --------------------------------------------------------------------------- #
+# CUBECOLOURDIALOG Widget wxPython IMPLEMENTATION
+#
+# Python Code By:
+#
+# Andrea Gavana, @ 16 Aug 2007
+# Latest Revision: 26 Feb 2012, 15.00 GMT
+#
+#
+# TODO List
+#
+# 1. Find A Way To Reduce Flickering On The 2 ColourPanels;
+#
+# 2. See Why wx.GCDC Doesn't Work As I Thought (!). It Looks Slow As A Turtle,
+# But Probably I Am Doing Something Wrong While Painting The Alpha Textures.
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+:class:`CubeColourDialog` is an alternative implementation of :class:`ColourDialog`.
+
+
+Description
+===========
+
+The :class:`CubeColourDialog` is an alternative implementation of :class:`ColourDialog`, and it
+offers different functionalities with respect to the default wxPython one. It
+can be used as a replacement of :class:`ColourDialog` with exactly the same syntax and
+methods.
+
+Some features:
+
+- RGB components may be controlled using spin controls or with mouse gestures
+ on a 3D RGB cube, with the 3 components laying on the X, Y, Z axes;
+- HSB components may be controlled using spin controls or with mouse gestures
+ on a 2D colour wheel;
+- Brightness has its own vertical slider to play with;
+- The colour alpha channel can be controlled using another vertical slider, or
+ via spin control;
+- The colour alpha channel controls can be completely hidden at startup or the
+ choice to use the alpha channel can be left to the user while playing with the
+ dialog, via a simple :class:`CheckBox`;
+- The "old colour" and "new colour" are displayed in two small custom panel,
+ which support alpha transparency and texture;
+- :class:`CubeColourDialog` displays also the HTML colour code in hexadecimal format;
+- When available, a corresponding "Web Safe" colour is generated using a 500
+ web colours "database" (a dictionary inside the widget source code). Web Safe
+ colours are recognized by all the browsers;
+- When available, a corresponding "HTML name" for the selected colour is displayed,
+ by using the same 500 web colours "database";
+- When available, a corresponding "Microsoft Access Code" for the selected colour
+ is displayed, by using the same 500 web colours "database".
+
+And much more.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.cubecolourdialog as CCD
+
+ # Our normal wxApp-derived class, as usual
+ app = wx.App(0)
+
+ colourData = wx.ColourData()
+ dlg = CCD.CubeColourDialog(None, colourData)
+
+ if dlg.ShowModal() == wx.ID_OK:
+
+ # If the user selected OK, then the dialog's wx.ColourData will
+ # contain valid information. Fetch the data ...
+ colourData = dlg.GetColourData()
+ h, s, v, a = dlg.GetHSVAColour()
+
+ # ... then do something with it. The actual colour data will be
+ # returned as a three-tuple (r, g, b) in this particular case.
+ colour = colourData.GetColour()
+ r, g, b, alpha = colour.Red(), colour.Green(), colour.Blue(), colour.Alpha()
+ print "You selected (RGBA): %d, %d, %d, %d"%(r, g, b, alpha)
+ print "You selected (HSVA): %d, %d, %d, %d"%(h, s, v, a)
+
+ # Once the dialog is destroyed, Mr. wx.ColourData is no longer your
+ # friend. Don't use it again!
+ dlg.Destroy()
+
+ app.MainLoop()
+
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+================== =========== ==================================================
+Window Styles Hex Value Description
+================== =========== ==================================================
+``CCD_SHOW_ALPHA`` 0x1 Show the widget used to control colour alpha channels in :class:`CubeColourDialog`.
+================== =========== ==================================================
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`CubeColourDialog` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 26 Feb 2012, 15.00 GMT
+
+Version 0.4.
+
+"""
+
+__docformat__ = "epytext"
+
+
+#----------------------------------------------------------------------
+# Beginning Of CUBECOLOURDIALOG wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+import colorsys
+
+from math import pi, sin, cos, sqrt, atan2
+
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+# Define a translation string
+_ = wx.GetTranslation
+
+# Show the alpha control in the dialog
+CCD_SHOW_ALPHA = 1
+""" Show the widget used to control colour alpha channels in :class:`CubeColourDialog`. """
+
+# Radius of the HSB colour wheel
+RADIUS = 100
+""" Radius of the HSB colour wheel. """
+
+# Width of the mouse-controlled colour pointer
+RECT_WIDTH = 5
+""" Width of the mouse-controlled colour pointer. """
+
+# Dictionary keys for the RGB colour cube
+RED, GREEN, BLUE = 0, 1, 2
+""" Dictionary keys for the RGB colour cube. """
+
+Vertex = wx.Point(95, 109)
+Top = wx.Point(95, 10)
+Left = wx.Point(16, 148)
+Right = wx.Point(174, 148)
+
+colourAttributes = ["r", "g", "b", "h", "s", "v"]
+colourMaxValues = [255, 255, 255, 359, 255, 255]
+checkColour = wx.Colour(200, 200, 200)
+
+HTMLCodes = {'#B0171F': ['Indian red', '2037680', ''],
+ '#DC143C': ['Crimson', '3937500', '#CC0033'],
+ '#FFB6C1': ['Lightpink', '12695295', '#FFCCCC'],
+ '#FFAEB9': ['Lightpink 1', '12168959', ''],
+ '#EEA2AD': ['Lightpink 2', '11379438', ''],
+ '#CD8C95': ['Lightpink 3', '9800909', ''],
+ '#8B5F65': ['Lightpink 4', '6643595', ''],
+ '#FFC0CB': ['Pink', '13353215', '#FFCCCC'],
+ '#FFB5C5': ['Pink 1', '12957183', ''],
+ '#EEA9B8': ['Pink 2', '12102126', ''],
+ '#CD919E': ['Pink 3', '10392013', ''],
+ '#8B636C': ['Pink 4', '7103371', ''],
+ '#DB7093': ['Palevioletred', '9662683', '#CC6699'],
+ '#FF82AB': ['Palevioletred 1', '11240191', ''],
+ '#EE799F': ['Palevioletred 2', '10451438', ''],
+ '#CD6889': ['Palevioletred 3', '9005261', ''],
+ '#8B475D': ['Palevioletred 4', '6113163', ''],
+ '#FFF0F5': ['Lavenderblush 1 (lavenderblush)', '16118015', '#FFFFFF'],
+ '#EEE0E5': ['Lavenderblush 2', '15065326', ''],
+ '#CDC1C5': ['Lavenderblush 3', '12960205', ''],
+ '#8B8386': ['Lavenderblush 4', '8815499', ''],
+ '#FF3E96': ['Violetred 1', '9846527', ''],
+ '#EE3A8C': ['Violetred 2', '9190126', ''],
+ '#CD3278': ['Violetred 3', '7877325', ''],
+ '#8B2252': ['Violetred 4', '5382795', ''],
+ '#FF69B4': ['Hotpink', '11823615', '#FF66CC'],
+ '#FF6EB4': ['Hotpink 1', '11824895', ''],
+ '#EE6AA7': ['Hotpink 2', '10971886', ''],
+ '#CD6090': ['Hotpink 3', '9461965', ''],
+ '#8B3A62': ['Hotpink 4', '6437515', ''],
+ '#872657': ['Raspberry', '5711495', ''],
+ '#FF1493': ['Deeppink 1 (deeppink)', '9639167', '#FF0099'],
+ '#EE1289': ['Deeppink 2', '8983278', ''],
+ '#CD1076': ['Deeppink 3', '7737549', ''],
+ '#8B0A50': ['Deeppink 4', '5245579', ''],
+ '#FF34B3': ['Maroon 1', '11744511', ''],
+ '#EE30A7': ['Maroon 2', '10957038', ''],
+ '#CD2990': ['Maroon 3', '9447885', ''],
+ '#8B1C62': ['Maroon 4', '6429835', ''],
+ '#C71585': ['Mediumvioletred', '8721863', '#CC0066'],
+ '#D02090': ['Violetred', '9445584', ''],
+ '#DA70D6': ['Orchid', '14053594', '#CC66CC'],
+ '#FF83FA': ['Orchid 1', '16417791', ''],
+ '#EE7AE9': ['Orchid 2', '15301358', ''],
+ '#CD69C9': ['Orchid 3', '13199821', ''],
+ '#8B4789': ['Orchid 4', '8996747', ''],
+ '#D8BFD8': ['Thistle', '14204888', '#CCCCCC'],
+ '#FFE1FF': ['Thistle 1', '16769535', ''],
+ '#EED2EE': ['Thistle 2', '15651566', ''],
+ '#CDB5CD': ['Thistle 3', '13481421', ''],
+ '#8B7B8B': ['Thistle 4', '9141131', ''],
+ '#FFBBFF': ['Plum 1', '16759807', ''],
+ '#EEAEEE': ['Plum 2', '15642350', ''],
+ '#CD96CD': ['Plum 3', '13473485', ''],
+ '#8B668B': ['Plum 4', '9135755', ''],
+ '#DDA0DD': ['Plum', '14524637', '#CC99CC'],
+ '#EE82EE': ['Violet', '15631086', '#FF99FF'],
+ '#FF00FF': ['Magenta (fuchsia)', '16711935', '#FF00FF'],
+ '#EE00EE': ['Magenta 2', '15597806', ''],
+ '#CD00CD': ['Magenta 3', '13435085', ''],
+ '#8B008B': ['Magenta 4 (darkmagenta)', '9109643', '#990099'],
+ '#800080': ['Purple', '8388736', '#990099'],
+ '#BA55D3': ['Mediumorchid', '13850042', '#CC66CC'],
+ '#E066FF': ['Mediumorchid 1', '16738016', ''],
+ '#D15FEE': ['Mediumorchid 2', '15622097', ''],
+ '#B452CD': ['Mediumorchid 3', '13456052', ''],
+ '#7A378B': ['Mediumorchid 4', '9123706', ''],
+ '#9400D3': ['Darkviolet', '13828244', '#9900CC'],
+ '#9932CC': ['Darkorchid', '13382297', '#9933CC'],
+ '#BF3EFF': ['Darkorchid 1', '16727743', ''],
+ '#B23AEE': ['Darkorchid 2', '15612594', ''],
+ '#9A32CD': ['Darkorchid 3', '13447834', ''],
+ '#68228B': ['Darkorchid 4', '9118312', ''],
+ '#4B0082': ['Indigo', '8519755', '#330099'],
+ '#8A2BE2': ['Blueviolet', '14822282', '#9933FF'],
+ '#9B30FF': ['Purple 1', '16724123', ''],
+ '#912CEE': ['Purple 2', '15608977', ''],
+ '#7D26CD': ['Purple 3', '13444733', ''],
+ '#551A8B': ['Purple 4', '9116245', ''],
+ '#9370DB': ['Mediumpurple', '14381203', '#9966CC'],
+ '#AB82FF': ['Mediumpurple 1', '16745131', ''],
+ '#9F79EE': ['Mediumpurple 2', '15628703', ''],
+ '#8968CD': ['Mediumpurple 3', '13461641', ''],
+ '#5D478B': ['Mediumpurple 4', '9127773', ''],
+ '#483D8B': ['Darkslateblue', '9125192', '#333399'],
+ '#8470FF': ['Lightslateblue', '16740484', ''],
+ '#7B68EE': ['Mediumslateblue', '15624315', '#6666FF'],
+ '#6A5ACD': ['Slateblue', '13458026', '#6666CC'],
+ '#836FFF': ['Slateblue 1', '16740227', ''],
+ '#7A67EE': ['Slateblue 2', '15624058', ''],
+ '#6959CD': ['Slateblue 3', '13457769', ''],
+ '#473C8B': ['Slateblue 4', '9124935', ''],
+ '#F8F8FF': ['Ghostwhite', '16775416', '#FFFFFF'],
+ '#E6E6FA': ['Lavender', '16443110', '#FFFFFF'],
+ '#0000FF': ['Blue', '16711680', '#0000FF'],
+ '#0000EE': ['Blue 2', '15597568', ''],
+ '#0000CD': ['Blue 3 (mediumblue)', '13434880', '#0000CC'],
+ '#00008B': ['Blue 4 (darkblue)', '9109504', '#000099'],
+ '#000080': ['Navy', '8388608', '#000099'],
+ '#191970': ['Midnightblue', '7346457', '#000066'],
+ '#3D59AB': ['Cobalt', '11229501', ''],
+ '#4169E1': ['Royalblue', '14772545', '#3366CC'],
+ '#4876FF': ['Royalblue 1', '16741960', ''],
+ '#436EEE': ['Royalblue 2', '15625795', ''],
+ '#3A5FCD': ['Royalblue 3', '13459258', ''],
+ '#27408B': ['Royalblue 4', '9125927', ''],
+ '#6495ED': ['Cornflowerblue', '15570276', '#6699FF'],
+ '#B0C4DE': ['Lightsteelblue', '14599344', '#99CCCC'],
+ '#CAE1FF': ['Lightsteelblue 1', '16769482', ''],
+ '#BCD2EE': ['Lightsteelblue 2', '15651516', ''],
+ '#A2B5CD': ['Lightsteelblue 3', '13481378', ''],
+ '#6E7B8B': ['Lightsteelblue 4', '9141102', ''],
+ '#778899': ['Lightslategray', '10061943', '#669999'],
+ '#708090': ['Slategray', '9470064', '#669999'],
+ '#C6E2FF': ['Slategray 1', '16769734', ''],
+ '#B9D3EE': ['Slategray 2', '15651769', ''],
+ '#9FB6CD': ['Slategray 3', '13481631', ''],
+ '#6C7B8B': ['Slategray 4', '9141100', ''],
+ '#1E90FF': ['Dodgerblue 1 (dodgerblue)', '16748574', '#3399FF'],
+ '#1C86EE': ['Dodgerblue 2', '15631900', ''],
+ '#1874CD': ['Dodgerblue 3', '13464600', ''],
+ '#104E8B': ['Dodgerblue 4', '9129488', ''],
+ '#F0F8FF': ['Aliceblue', '16775408', '#FFFFFF'],
+ '#4682B4': ['Steelblue', '11829830', '#3399CC'],
+ '#63B8FF': ['Steelblue 1', '16758883', ''],
+ '#5CACEE': ['Steelblue 2', '15641692', ''],
+ '#4F94CD': ['Steelblue 3', '13472847', ''],
+ '#36648B': ['Steelblue 4', '9135158', ''],
+ '#87CEFA': ['Lightskyblue', '16436871', '#99CCFF'],
+ '#B0E2FF': ['Lightskyblue 1', '16769712', ''],
+ '#A4D3EE': ['Lightskyblue 2', '15651748', ''],
+ '#8DB6CD': ['Lightskyblue 3', '13481613', ''],
+ '#607B8B': ['Lightskyblue 4', '9141088', ''],
+ '#87CEFF': ['Skyblue 1', '16764551', ''],
+ '#7EC0EE': ['Skyblue 2', '15646846', ''],
+ '#6CA6CD': ['Skyblue 3', '13477484', ''],
+ '#4A708B': ['Skyblue 4', '9138250', ''],
+ '#87CEEB': ['Skyblue', '15453831', '#99CCFF'],
+ '#00BFFF': ['Deepskyblue 1 (deepskyblue)', '16760576', '#00CCFF'],
+ '#00B2EE': ['Deepskyblue 2', '15643136', ''],
+ '#009ACD': ['Deepskyblue 3', '13474304', ''],
+ '#00688B': ['Deepskyblue 4', '9136128', ''],
+ '#33A1C9': ['Peacock', '13214003', ''],
+ '#ADD8E6': ['Lightblue', '15128749', '#99CCFF'],
+ '#BFEFFF': ['Lightblue 1', '16773055', ''],
+ '#B2DFEE': ['Lightblue 2', '15654834', ''],
+ '#9AC0CD': ['Lightblue 3', '13484186', ''],
+ '#68838B': ['Lightblue 4', '9143144', ''],
+ '#B0E0E6': ['Powderblue', '15130800', '#CCCCFF'],
+ '#98F5FF': ['Cadetblue 1', '16774552', ''],
+ '#8EE5EE': ['Cadetblue 2', '15656334', ''],
+ '#7AC5CD': ['Cadetblue 3', '13485434', ''],
+ '#53868B': ['Cadetblue 4', '9143891', ''],
+ '#00F5FF': ['Turquoise 1', '16774400', ''],
+ '#00E5EE': ['Turquoise 2', '15656192', ''],
+ '#00C5CD': ['Turquoise 3', '13485312', ''],
+ '#00868B': ['Turquoise 4', '9143808', ''],
+ '#5F9EA0': ['Cadetblue', '10526303', '#669999'],
+ '#00CED1': ['Darkturquoise', '13749760', '#00CCCC'],
+ '#F0FFFF': ['Azure 1 (azure)', '16777200', '#FFFFFF'],
+ '#E0EEEE': ['Azure 2', '15658720', ''],
+ '#C1CDCD': ['Azure 3', '13487553', ''],
+ '#838B8B': ['Azure 4', '9145219', ''],
+ '#E0FFFF': ['Lightcyan 1 (lightcyan)', '16777184', '#CCFFFF'],
+ '#D1EEEE': ['Lightcyan 2', '15658705', ''],
+ '#B4CDCD': ['Lightcyan 3', '13487540', ''],
+ '#7A8B8B': ['Lightcyan 4', '9145210', ''],
+ '#BBFFFF': ['Paleturquoise 1', '16777147', ''],
+ '#AEEEEE': ['Paleturquoise 2 (paleturquoise)', '15658670', ''],
+ '#96CDCD': ['Paleturquoise 3', '13487510', ''],
+ '#668B8B': ['Paleturquoise 4', '9145190', ''],
+ '#2F4F4F': ['Darkslategray', '5197615', '#336666'],
+ '#97FFFF': ['Darkslategray 1', '16777111', ''],
+ '#8DEEEE': ['Darkslategray 2', '15658637', ''],
+ '#79CDCD': ['Darkslategray 3', '13487481', ''],
+ '#528B8B': ['Darkslategray 4', '9145170', ''],
+ '#00FFFF': ['Cyan / aqua', '16776960', '#00FFFF'],
+ '#00EEEE': ['Cyan 2', '15658496', ''],
+ '#00CDCD': ['Cyan 3', '13487360', ''],
+ '#008B8B': ['Cyan 4 (darkcyan)', '9145088', '#009999'],
+ '#008080': ['Teal', '8421376', '#009999'],
+ '#48D1CC': ['Mediumturquoise', '13422920', '#33CCCC'],
+ '#20B2AA': ['Lightseagreen', '11186720', '#339999'],
+ '#03A89E': ['Manganeseblue', '10397699', ''],
+ '#40E0D0': ['Turquoise', '13688896', '#33CCCC'],
+ '#808A87': ['Coldgrey', '8882816', ''],
+ '#00C78C': ['Turquoiseblue', '9225984', ''],
+ '#7FFFD4': ['Aquamarine 1 (aquamarine)', '13959039', '#66FFCC'],
+ '#76EEC6': ['Aquamarine 2', '13037174', ''],
+ '#66CDAA': ['Aquamarine 3 (mediumaquamarine)', '11193702', '#66CC99'],
+ '#458B74': ['Aquamarine 4', '7637829', ''],
+ '#00FA9A': ['Mediumspringgreen', '10156544', '#00FF99'],
+ '#F5FFFA': ['Mintcream', '16449525', '#FFFFFF'],
+ '#00FF7F': ['Springgreen', '8388352', '#00FF66'],
+ '#00EE76': ['Springgreen 1', '7794176', ''],
+ '#00CD66': ['Springgreen 2', '6737152', ''],
+ '#008B45': ['Springgreen 3', '4557568', ''],
+ '#3CB371': ['Mediumseagreen', '7451452', '#33CC66'],
+ '#54FF9F': ['Seagreen 1', '10485588', ''],
+ '#4EEE94': ['Seagreen 2', '9760334', ''],
+ '#43CD80': ['Seagreen 3', '8441155', ''],
+ '#2E8B57': ['Seagreen 4 (seagreen)', '5737262', '#339966'],
+ '#00C957': ['Emeraldgreen', '5753088', ''],
+ '#BDFCC9': ['Mint', '13237437', ''],
+ '#3D9140': ['Cobaltgreen', '4231485', ''],
+ '#F0FFF0': ['Honeydew 1 (honeydew)', '15794160', '#FFFFFF'],
+ '#E0EEE0': ['Honeydew 2', '14741216', ''],
+ '#C1CDC1': ['Honeydew 3', '12701121', ''],
+ '#838B83': ['Honeydew 4', '8620931', ''],
+ '#8FBC8F': ['Darkseagreen', '9419919', '#99CC99'],
+ '#C1FFC1': ['Darkseagreen 1', '12713921', ''],
+ '#B4EEB4': ['Darkseagreen 2', '11857588', ''],
+ '#9BCD9B': ['Darkseagreen 3', '10210715', ''],
+ '#698B69': ['Darkseagreen 4', '6916969', ''],
+ '#98FB98': ['Palegreen', '10025880', '#99FF99'],
+ '#9AFF9A': ['Palegreen 1', '10157978', ''],
+ '#90EE90': ['Palegreen 2 (lightgreen)', '9498256', '#99FF99'],
+ '#7CCD7C': ['Palegreen 3', '8179068', ''],
+ '#548B54': ['Palegreen 4', '5540692', ''],
+ '#32CD32': ['Limegreen', '3329330', '#33CC33'],
+ '#228B22': ['Forestgreen', '2263842', '#339933'],
+ '#00FF00': ['Green 1 (lime)', '65280', '#00FF00'],
+ '#00EE00': ['Green 2', '60928', ''],
+ '#00CD00': ['Green 3', '52480', ''],
+ '#008B00': ['Green 4', '35584', ''],
+ '#008000': ['Green', '32768', '#009900'],
+ '#006400': ['Darkgreen', '25600', '#006600'],
+ '#308014': ['Sapgreen', '1343536', ''],
+ '#7CFC00': ['Lawngreen', '64636', '#66FF00'],
+ '#7FFF00': ['Chartreuse 1 (chartreuse)', '65407', '#66FF00'],
+ '#76EE00': ['Chartreuse 2', '61046', ''],
+ '#66CD00': ['Chartreuse 3', '52582', ''],
+ '#458B00': ['Chartreuse 4', '35653', ''],
+ '#ADFF2F': ['Greenyellow', '3145645', '#99FF33'],
+ '#CAFF70': ['Darkolivegreen 1', '7405514', ''],
+ '#BCEE68': ['Darkolivegreen 2', '6876860', ''],
+ '#A2CD5A': ['Darkolivegreen 3', '5950882', ''],
+ '#6E8B3D': ['Darkolivegreen 4', '4033390', ''],
+ '#556B2F': ['Darkolivegreen', '3107669', '#666633'],
+ '#6B8E23': ['Olivedrab', '2330219', '#669933'],
+ '#C0FF3E': ['Olivedrab 1', '4128704', ''],
+ '#B3EE3A': ['Olivedrab 2', '3862195', ''],
+ '#9ACD32': ['Olivedrab 3 (yellowgreen)', '3329434', '#99CC33'],
+ '#698B22': ['Olivedrab 4', '2263913', ''],
+ '#FFFFF0': ['Ivory 1 (ivory)', '15794175', '#FFFFFF'],
+ '#EEEEE0': ['Ivory 2', '14741230', ''],
+ '#CDCDC1': ['Ivory 3', '12701133', ''],
+ '#8B8B83': ['Ivory 4', '8620939', ''],
+ '#F5F5DC': ['Beige', '14480885', '#FFFFCC'],
+ '#FFFFE0': ['Lightyellow 1 (lightyellow)', '14745599', '#FFFFFF'],
+ '#EEEED1': ['Lightyellow 2', '13758190', ''],
+ '#CDCDB4': ['Lightyellow 3', '11849165', ''],
+ '#8B8B7A': ['Lightyellow 4', '8031115', ''],
+ '#FAFAD2': ['Lightgoldenrodyellow', '13826810', '#FFFFCC'],
+ '#FFFF00': ['Yellow 1 (yellow)', '65535', '#FFFF00'],
+ '#EEEE00': ['Yellow 2', '61166', ''],
+ '#CDCD00': ['Yellow 3', '52685', ''],
+ '#8B8B00': ['Yellow 4', '35723', ''],
+ '#808069': ['Warmgrey', '6914176', ''],
+ '#808000': ['Olive', '32896', '#999900'],
+ '#BDB76B': ['Darkkhaki', '7059389', '#CCCC66'],
+ '#FFF68F': ['Khaki 1', '9434879', ''],
+ '#EEE685': ['Khaki 2', '8775406', ''],
+ '#CDC673': ['Khaki 3', '7587533', ''],
+ '#8B864E': ['Khaki 4', '5146251', ''],
+ '#F0E68C': ['Khaki', '9234160', ''],
+ '#EEE8AA': ['Palegoldenrod', '11200750', '#FFFF99'],
+ '#FFFACD': ['Lemonchiffon 1 (lemonchiffon)', '13499135', '#FFFFCC'],
+ '#EEE9BF': ['Lemonchiffon 2', '12577262', ''],
+ '#CDC9A5': ['Lemonchiffon 3', '10865101', ''],
+ '#8B8970': ['Lemonchiffon 4', '7375243', ''],
+ '#FFEC8B': ['Lightgoldenrod 1', '9170175', ''],
+ '#EEDC82': ['Lightgoldenrod 2', '8576238', ''],
+ '#CDBE70': ['Lightgoldenrod 3', '7388877', ''],
+ '#8B814C': ['Lightgoldenrod 4', '5013899', ''],
+ '#E3CF57': ['Banana', '5754851', ''],
+ '#FFD700': ['Gold 1 (gold)', '55295', '#FFCC00'],
+ '#EEC900': ['Gold 2', '51694', ''],
+ '#CDAD00': ['Gold 3', '44493', ''],
+ '#8B7500': ['Gold 4', '30091', ''],
+ '#FFF8DC': ['Cornsilk 1 (cornsilk)', '14481663', '#FFFFCC'],
+ '#EEE8CD': ['Cornsilk 2', '13494510', ''],
+ '#CDC8B1': ['Cornsilk 3', '11651277', ''],
+ '#8B8878': ['Cornsilk 4', '7899275', ''],
+ '#DAA520': ['Goldenrod', '2139610', '#CC9933'],
+ '#FFC125': ['Goldenrod 1', '2474495', ''],
+ '#EEB422': ['Goldenrod 2', '2274542', ''],
+ '#CD9B1D': ['Goldenrod 3', '1940429', ''],
+ '#8B6914': ['Goldenrod 4', '1337739', ''],
+ '#B8860B': ['Darkgoldenrod', '755384', '#CC9900'],
+ '#FFB90F': ['Darkgoldenrod 1', '1030655', ''],
+ '#EEAD0E': ['Darkgoldenrod 2', '962030', ''],
+ '#CD950C': ['Darkgoldenrod 3', '824781', ''],
+ '#8B6508': ['Darkgoldenrod 4', '550283', ''],
+ '#FFA500': ['Orange 1 (orange)', '42495', '#FF9900'],
+ '#EE9A00': ['Orange 2', '39662', ''],
+ '#CD8500': ['Orange 3', '34253', ''],
+ '#8B5A00': ['Orange 4', '23179', ''],
+ '#FFFAF0': ['Floralwhite', '15792895', '#FFFFFF'],
+ '#FDF5E6': ['Oldlace', '15136253', '#FFFFFF'],
+ '#F5DEB3': ['Wheat', '11788021', '#FFCCCC'],
+ '#FFE7BA': ['Wheat 1', '12249087', ''],
+ '#EED8AE': ['Wheat 2', '11458798', ''],
+ '#CDBA96': ['Wheat 3', '9878221', ''],
+ '#8B7E66': ['Wheat 4', '6717067', ''],
+ '#FFE4B5': ['Moccasin', '11920639', '#FFCCCC'],
+ '#FFEFD5': ['Papayawhip', '14020607', '#FFFFCC'],
+ '#FFEBCD': ['Blanchedalmond', '13495295', '#FFFFCC'],
+ '#FFDEAD': ['Navajowhite 1 (navajowhite)', '11394815', '#FFCC99'],
+ '#EECFA1': ['Navajowhite 2', '10604526', ''],
+ '#CDB38B': ['Navajowhite 3', '9155533', ''],
+ '#8B795E': ['Navajowhite 4', '6191499', ''],
+ '#FCE6C9': ['Eggshell', '13231868', ''],
+ '#D2B48C': ['Tan', '9221330', '#CCCC99'],
+ '#9C661F': ['Brick', '2057884', ''],
+ '#FF9912': ['Cadmiumyellow', '1219071', ''],
+ '#FAEBD7': ['Antiquewhite', '14150650', '#FFFFCC'],
+ '#FFEFDB': ['Antiquewhite 1', '14413823', ''],
+ '#EEDFCC': ['Antiquewhite 2', '13426670', ''],
+ '#CDC0B0': ['Antiquewhite 3', '11583693', ''],
+ '#8B8378': ['Antiquewhite 4', '7897995', ''],
+ '#DEB887': ['Burlywood', '8894686', '#CCCC99'],
+ '#FFD39B': ['Burlywood 1', '10212351', ''],
+ '#EEC591': ['Burlywood 2', '9553390', ''],
+ '#CDAA7D': ['Burlywood 3', '8235725', ''],
+ '#8B7355': ['Burlywood 4', '5600139', ''],
+ '#FFE4C4': ['Bisque 1 (bisque)', '12903679', '#FFFFCC'],
+ '#EED5B7': ['Bisque 2', '12047854', ''],
+ '#CDB79E': ['Bisque 3', '10401741', ''],
+ '#8B7D6B': ['Bisque 4', '7044491', ''],
+ '#E3A869': ['Melon', '6924515', ''],
+ '#ED9121': ['Carrot', '2200045', ''],
+ '#FF8C00': ['Darkorange', '36095', '#FF9900'],
+ '#FF7F00': ['Darkorange 1', '32767', ''],
+ '#EE7600': ['Darkorange 2', '30446', ''],
+ '#CD6600': ['Darkorange 3', '26317', ''],
+ '#8B4500': ['Darkorange 4', '17803', ''],
+ '#FF8000': ['Orange', '33023', ''],
+ '#FFA54F': ['Tan 1', '5219839', ''],
+ '#EE9A49': ['Tan 2', '4823790', ''],
+ '#CD853F': ['Tan 3 (peru)', '4163021', '#CC9933'],
+ '#8B5A2B': ['Tan 4', '2841227', ''],
+ '#FAF0E6': ['Linen', '15134970', '#FFFFFF'],
+ '#FFDAB9': ['Peachpuff 1 (peachpuff)', '12180223', '#FFCCCC'],
+ '#EECBAD': ['Peachpuff 2', '11389934', ''],
+ '#CDAF95': ['Peachpuff 3', '9809869', ''],
+ '#8B7765': ['Peachpuff 4', '6649739', ''],
+ '#FFF5EE': ['Seashell 1 (seashell)', '15660543', '#FFFFFF'],
+ '#EEE5DE': ['Seashell 2', '14607854', ''],
+ '#CDC5BF': ['Seashell 3', '12568013', ''],
+ '#8B8682': ['Seashell 4', '8554123', ''],
+ '#F4A460': ['Sandybrown', '6333684', '#FF9966'],
+ '#C76114': ['Rawsienna', '1335751', ''],
+ '#D2691E': ['Chocolate', '1993170', '#CC6633'],
+ '#FF7F24': ['Chocolate 1', '2392063', ''],
+ '#EE7621': ['Chocolate 2', '2193134', ''],
+ '#CD661D': ['Chocolate 3', '1926861', ''],
+ '#8B4513': ['Chocolate 4 (saddlebrown)', '1262987', '#993300'],
+ '#292421': ['Ivoryblack', '2171945', ''],
+ '#FF7D40': ['Flesh', '4226559', ''],
+ '#FF6103': ['Cadmiumorange', '221695', ''],
+ '#8A360F': ['Burntsienna', '997002', ''],
+ '#A0522D': ['Sienna', '2970272', '#996633'],
+ '#FF8247': ['Sienna 1', '4686591', ''],
+ '#EE7942': ['Sienna 2', '4356590', ''],
+ '#CD6839': ['Sienna 3', '3762381', ''],
+ '#8B4726': ['Sienna 4', '2508683', ''],
+ '#FFA07A': ['Lightsalmon 1 (lightsalmon)', '8036607', '#FF9966'],
+ '#EE9572': ['Lightsalmon 2', '7509486', ''],
+ '#CD8162': ['Lightsalmon 3', '6455757', ''],
+ '#8B5742': ['Lightsalmon 4', '4347787', ''],
+ '#FF7F50': ['Coral', '5275647', '#FF6666'],
+ '#FF4500': ['Orangered 1 (orangered)', '17919', '#FF3300'],
+ '#EE4000': ['Orangered 2', '16622', ''],
+ '#CD3700': ['Orangered 3', '14285', ''],
+ '#8B2500': ['Orangered 4', '9611', ''],
+ '#5E2612': ['Sepia', '1189470', ''],
+ '#E9967A': ['Darksalmon', '8034025', '#FF9966'],
+ '#FF8C69': ['Salmon 1', '6917375', ''],
+ '#EE8262': ['Salmon 2', '6456046', ''],
+ '#CD7054': ['Salmon 3', '5533901', ''],
+ '#8B4C39': ['Salmon 4', '3755147', ''],
+ '#FF7256': ['Coral 1', '5665535', ''],
+ '#EE6A50': ['Coral 2', '5270254', ''],
+ '#CD5B45': ['Coral 3', '4545485', ''],
+ '#8B3E2F': ['Coral 4', '3096203', ''],
+ '#8A3324': ['Burntumber', '2372490', ''],
+ '#FF6347': ['Tomato 1 (tomato)', '4678655', '#FF6633'],
+ '#EE5C42': ['Tomato 2', '4349166', ''],
+ '#CD4F39': ['Tomato 3', '3755981', ''],
+ '#8B3626': ['Tomato 4', '2504331', ''],
+ '#FA8072': ['Salmon', '7504122', '#FF9966'],
+ '#FFE4E1': ['Mistyrose 1 (mistyrose)', '14804223', '#FFCCFF'],
+ '#EED5D2': ['Mistyrose 2', '13817326', ''],
+ '#CDB7B5': ['Mistyrose 3', '11909069', ''],
+ '#8B7D7B': ['Mistyrose 4', '8093067', ''],
+ '#FFFAFA': ['Snow 1 (snow)', '16448255', '#FFFFFF'],
+ '#EEE9E9': ['Snow 2', '15329774', ''],
+ '#CDC9C9': ['Snow 3', '13224397', ''],
+ '#8B8989': ['Snow 4', '9013643', ''],
+ '#BC8F8F': ['Rosybrown', '9408444', '#CC9999'],
+ '#FFC1C1': ['Rosybrown 1', '12698111', ''],
+ '#EEB4B4': ['Rosybrown 2', '11842798', ''],
+ '#CD9B9B': ['Rosybrown 3', '10197965', ''],
+ '#8B6969': ['Rosybrown 4', '6908299', ''],
+ '#F08080': ['Lightcoral', '8421616', '#FF9999'],
+ '#CD5C5C': ['Indianred', '6053069', '#CC6666'],
+ '#FF6A6A': ['Indianred 1', '6974207', ''],
+ '#EE6363': ['Indianred 2', '6513646', ''],
+ '#8B3A3A': ['Indianred 4', '3816075', ''],
+ '#CD5555': ['Indianred 3', '5592525', ''],
+ '#A52A2A': ['Brown', '2763429', '#993333'],
+ '#FF4040': ['Brown 1', '4210943', ''],
+ '#EE3B3B': ['Brown 2', '3881966', ''],
+ '#CD3333': ['Brown 3', '3355597', ''],
+ '#8B2323': ['Brown 4', '2302859', ''],
+ '#B22222': ['Firebrick', '2237106', '#993333'],
+ '#FF3030': ['Firebrick 1', '3158271', ''],
+ '#EE2C2C': ['Firebrick 2', '2895086', ''],
+ '#CD2626': ['Firebrick 3', '2500301', ''],
+ '#8B1A1A': ['Firebrick 4', '1710731', ''],
+ '#FF0000': ['Red 1 (red)', '255', '#FF0000'],
+ '#EE0000': ['Red 2', '238', ''],
+ '#CD0000': ['Red 3', '205', ''],
+ '#8B0000': ['Red 4 (darkred)', '139', '#990000'],
+ '#800000': ['Maroon', '128', '#990000'],
+ '#8E388E': ['Sgi beet', '9320590', ''],
+ '#7171C6': ['Sgi slateblue', '13005169', ''],
+ '#7D9EC0': ['Sgi lightblue', '12623485', ''],
+ '#388E8E': ['Sgi teal', '9342520', ''],
+ '#71C671': ['Sgi chartreuse', '7456369', ''],
+ '#8E8E38': ['Sgi olivedrab', '3706510', ''],
+ '#C5C1AA': ['Sgi brightgray', '11190725', ''],
+ '#C67171': ['Sgi salmon', '7434694', ''],
+ '#555555': ['Sgi darkgray', '5592405', ''],
+ '#1E1E1E': ['Sgi gray 12', '1973790', ''],
+ '#282828': ['Sgi gray 16', '2631720', ''],
+ '#515151': ['Sgi gray 32', '5329233', ''],
+ '#5B5B5B': ['Sgi gray 36', '5987163', ''],
+ '#848484': ['Sgi gray 52', '8684676', ''],
+ '#8E8E8E': ['Sgi gray 56', '9342606', ''],
+ '#AAAAAA': ['Sgi lightgray', '11184810', ''],
+ '#B7B7B7': ['Sgi gray 72', '12040119', ''],
+ '#C1C1C1': ['Sgi gray 76', '12698049', ''],
+ '#EAEAEA': ['Sgi gray 92', '15395562', ''],
+ '#F4F4F4': ['Sgi gray 96', '16053492', ''],
+ '#FFFFFF': ['White', '16777215', '#FFFFFF'],
+ '#F5F5F5': ['White smoke (gray)', '16119285', '#FFFFFF'],
+ '#DCDCDC': ['Gainsboro', '14474460', '#CCCCCC'],
+ '#D3D3D3': ['Lightgrey', '13882323', '#CCCCCC'],
+ '#C0C0C0': ['Silver', '12632256', '#CCCCCC'],
+ '#A9A9A9': ['Darkgray', '11119017', '#999999'],
+ '#808080': ['Gray', '8421504', ''],
+ '#696969': ['Dimgray (gray 42)', '6908265', '#666666'],
+ '#000000': ['Black', '0', '#000000'],
+ '#FCFCFC': ['Gray 99', '16579836', ''],
+ '#FAFAFA': ['Gray 98', '16448250', ''],
+ '#F7F7F7': ['Gray 97', '16250871', ''],
+ '#F2F2F2': ['Gray 95', '15921906', ''],
+ '#F0F0F0': ['Gray 94', '15790320', ''],
+ '#EDEDED': ['Gray 93', '15592941', ''],
+ '#EBEBEB': ['Gray 92', '15461355', ''],
+ '#E8E8E8': ['Gray 91', '15263976', ''],
+ '#E5E5E5': ['Gray 90', '15066597', ''],
+ '#E3E3E3': ['Gray 89', '14935011', ''],
+ '#E0E0E0': ['Gray 88', '14737632', ''],
+ '#DEDEDE': ['Gray 87', '14606046', ''],
+ '#DBDBDB': ['Gray 86', '14408667', ''],
+ '#D9D9D9': ['Gray 85', '14277081', ''],
+ '#D6D6D6': ['Gray 84', '14079702', ''],
+ '#D4D4D4': ['Gray 83', '13948116', ''],
+ '#D1D1D1': ['Gray 82', '13750737', ''],
+ '#CFCFCF': ['Gray 81', '13619151', ''],
+ '#CCCCCC': ['Gray 80', '13421772', ''],
+ '#C9C9C9': ['Gray 79', '13224393', ''],
+ '#C7C7C7': ['Gray 78', '13092807', ''],
+ '#C4C4C4': ['Gray 77', '12895428', ''],
+ '#C2C2C2': ['Gray 76', '12763842', ''],
+ '#BFBFBF': ['Gray 75', '12566463', ''],
+ '#BDBDBD': ['Gray 74', '12434877', ''],
+ '#BABABA': ['Gray 73', '12237498', ''],
+ '#B8B8B8': ['Gray 72', '12105912', ''],
+ '#B5B5B5': ['Gray 71', '11908533', ''],
+ '#B3B3B3': ['Gray 70', '11776947', ''],
+ '#B0B0B0': ['Gray 69', '11579568', ''],
+ '#ADADAD': ['Gray 68', '11382189', ''],
+ '#ABABAB': ['Gray 67', '11250603', ''],
+ '#A8A8A8': ['Gray 66', '11053224', ''],
+ '#A6A6A6': ['Gray 65', '10921638', ''],
+ '#A3A3A3': ['Gray 64', '10724259', ''],
+ '#A1A1A1': ['Gray 63', '10592673', ''],
+ '#9E9E9E': ['Gray 62', '10395294', ''],
+ '#9C9C9C': ['Gray 61', '10263708', ''],
+ '#999999': ['Gray 60', '10066329', ''],
+ '#969696': ['Gray 59', '9868950', ''],
+ '#949494': ['Gray 58', '9737364', ''],
+ '#919191': ['Gray 57', '9539985', ''],
+ '#8F8F8F': ['Gray 56', '9408399', ''],
+ '#8C8C8C': ['Gray 55', '9211020', ''],
+ '#8A8A8A': ['Gray 54', '9079434', ''],
+ '#878787': ['Gray 53', '8882055', ''],
+ '#858585': ['Gray 52', '8750469', ''],
+ '#828282': ['Gray 51', '8553090', ''],
+ '#7F7F7F': ['Gray 50', '8355711', ''],
+ '#7D7D7D': ['Gray 49', '8224125', ''],
+ '#7A7A7A': ['Gray 48', '8026746', ''],
+ '#787878': ['Gray 47', '7895160', ''],
+ '#757575': ['Gray 46', '7697781', ''],
+ '#737373': ['Gray 45', '7566195', ''],
+ '#707070': ['Gray 44', '7368816', ''],
+ '#6E6E6E': ['Gray 43', '7237230', ''],
+ '#6B6B6B': ['Gray 42', '7039851', ''],
+ '#696969': ['Dimgray (gray 42)', '6908265', '#666666'],
+ '#666666': ['Gray 40', '6710886', ''],
+ '#636363': ['Gray 39', '6513507', ''],
+ '#616161': ['Gray 38', '6381921', ''],
+ '#5E5E5E': ['Gray 37', '6184542', ''],
+ '#5C5C5C': ['Gray 36', '6052956', ''],
+ '#595959': ['Gray 35', '5855577', ''],
+ '#575757': ['Gray 34', '5723991', ''],
+ '#545454': ['Gray 33', '5526612', ''],
+ '#525252': ['Gray 32', '5395026', ''],
+ '#4F4F4F': ['Gray 31', '5197647', ''],
+ '#4D4D4D': ['Gray 30', '5066061', ''],
+ '#4A4A4A': ['Gray 29', '4868682', ''],
+ '#474747': ['Gray 28', '4671303', ''],
+ '#454545': ['Gray 27', '4539717', ''],
+ '#424242': ['Gray 26', '4342338', ''],
+ '#404040': ['Gray 25', '4210752', ''],
+ '#3D3D3D': ['Gray 24', '4013373', ''],
+ '#3B3B3B': ['Gray 23', '3881787', ''],
+ '#383838': ['Gray 22', '3684408', ''],
+ '#363636': ['Gray 21', '3552822', ''],
+ '#333333': ['Gray 20', '3355443', ''],
+ '#303030': ['Gray 19', '3158064', ''],
+ '#2E2E2E': ['Gray 18', '3026478', ''],
+ '#2B2B2B': ['Gray 17', '2829099', ''],
+ '#292929': ['Gray 16', '2697513', ''],
+ '#262626': ['Gray 15', '2500134', ''],
+ '#242424': ['Gray 14', '2368548', ''],
+ '#212121': ['Gray 13', '2171169', ''],
+ '#1F1F1F': ['Gray 12', '2039583', ''],
+ '#1C1C1C': ['Gray 11', '1842204', ''],
+ '#1A1A1A': ['Gray 10', '1710618', ''],
+ '#171717': ['Gray 9', '1513239', ''],
+ '#141414': ['Gray 8', '1315860', ''],
+ '#121212': ['Gray 7', '1184274', ''],
+ '#0F0F0F': ['Gray 6', '986895', ''],
+ '#0D0D0D': ['Gray 5', '855309', ''],
+ '#0A0A0A': ['Gray 4', '657930', ''],
+ '#080808': ['Gray 3', '526344', ''],
+ '#050505': ['Gray 2', '328965', ''],
+ '#030303': ['Gray 1', '197379', ''],
+ }
+
+
+HSVWheelImage = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAMoAAADJCAIAAADtkzpRAAAAA3NCSVQICAjb4U/gAAAgAElE"
+ "QVR4nO2decgsz3fWn6q5MWLcgsaoqAiKRBM14gJuNCj0T9SIuEVRiEIwSDSCElFJBPegKGqI"
+ "a1QigiYuqFHQEeU3RtSgRjQ/0ASXgBqXuGBihPh7u45/VJ1znnOqet737vd+vzZz5/b09PQs"
+ "/ennPPVUdb/lox/9KP7/NE1/ddsrUIELwDPLhz/qdn3bn/cdnZ697Q/wNqcv3/YSWCkVYg+B"
+ "Akhfs9zdzse2/YzC7/fhJu/DhdcfIJ4uKBWlQApQUAtQgIJyQa2QAikoFejrF5qpNKPLRV/e"
+ "bx1KKcB/3XZm7rt+yGj74OP1O+MOrkQSEVONGABAqQMjQw3pVlczypkogvZCKQAg/4c/zIcA"
+ "tQ8mXl+07cUlysWps6U7/lJdbAroWSMGSmGZFCuyFTBK8xFQ0XsBofYdH1DUPlB4fWHwUh2p"
+ "XgGdrV4K6yQ/3WwV4mmpVcuHzBlp2HhISJnCSULtuyhq/+uDxdkHAa8v2HYMrapa1IrVO8SC"
+ "aPMYDzscJULDy2Wug5OeSYJskjShNZk2CXoG+WRtJfzXDwRn7zdenzcO+nJBKa49Nm8qVVS9"
+ "2G+xShUlrJj8KCt9axmyOnGWwJpkbKYtsGVSB0iBfL9tvwD/4T2H7L3E61eQXFE5qxGvoVDk"
+ "t4wnLoKdp6KK1TDm+wsby9iZA5u9fPL1NepZHUsWbPFTQPtBKmb/5v3k7D3D65cOz97lyg3W"
+ "dDPpKlC/VRQROFgueBXA8PulogINQMWFKHnUk61FS99FCKzCYJGS+ZIyVhti9sO2/QL8y/cN"
+ "svcGr1+odbAGfeoy47e5RCaGdE2k0AuQilrHHkXFpasXF9NYNOeayA/npuLa1BfHsUUxk1nM"
+ "Pn3bL8C/eH8gew/w+rnaP6MKFG59JxZNrBSRZMKG/CAs7I7KoGy6/VZRFbJnBU1V5FTAuNn4"
+ "mPcKNbEGti4EFrQuG3NjBaB95rZfgH/6PkD2TuP1szS+wgSWOqpagysflisVyhpnVLeKalXR"
+ "GKybrWcF0msrRn1c+K1owpK1ytlEnUQrJhSt4KLS2FTPSvH7PAO0n7DtF+AfvtuQvaN47dsO"
+ "4JkSoykDsxWqJLkrhsmNv+UU+vBiu0pTDClOZyWGvNlYI2RpPvn38yqZwrAOetawdKs0o35O"
+ "gPaTt/0C/L13FbL6+CpvfNq3nwnUilr8Vgou/VbxrISn+u1CM12HLiXf14JL9flaUCs+wdaB"
+ "vkv1V10KatW3ps+QHvJbX+ztani7S0WtY2v8kWz7NX02XTiW18VvMpzA9lP3t73T1tO7pV77"
+ "9nMwpKVC7Y7mVW62pgyiFpccbzYWFz9vKvbmoYqc0Ba6KoyaeHHjHwRsKovB4MdsIgRdNeuZ"
+ "mffQhGSDX9FUZU3Vmq7jVRIQQLaftKPh9o/eLRl7V/Dat58PoAzfw7EQusTa8VqASFiNuZf3"
+ "/Bhn9HKptNocpery7utr9bJ152bNSV/znC2HCQu2rFAK2a95BloiW0VFA1qDCKRtP37HgdvX"
+ "vSuQvRN47dtnY3QwLw9os1k1YpSNF2kVNx5BAuZUEYh93lSnGh9wrxa817KbiIdLMEyRvGZa"
+ "GK29ffd0dLXkwLrxwlCy0qmCVIhACqQBsv3o/fbP3wnC3j5e+/ZLVflhyXVsohsoNeZbhXDp"
+ "hc/vuXrGyL6S6+fuSFgfpb324t1KbdatabhEkqi5A7u3T/n4AbUw/Itzi9JqYkUrmrLWEaMI"
+ "RCCAiN4wZOwz9tvH3j5hbxOvffscaCOOG1NxB/QffSgWAljcYGQZQySsL0kRvzGUZkL3UZ8i"
+ "lC0JGHNWc1lEiSTN6Vd1sFizuUUplAAPyIbxkjZEqzU0QWuQijZkbPvhOw7cvvFtQvbW8Nq3"
+ "zyWnFX76pGEFwCCsQxPMFht/NvIIUT6rFEsaqFb6vMX6FaWqbqUY7MRmGW3By9OSJGbLh4tI"
+ "gqyYrWw1UYACaYMzljG07Yfut3/91gh7O3jt2+dp4y7gpYep/bLdZduu6h6/wCELYFGzcR2x"
+ "1iBOVUcomLvySgr3XhdiJcgVx2Ap96KvVsqKrQrUIYSJJ3SBrKMCZvulkDW0ApGgW2a/3I0B"
+ "TbYfvN++6e0Q9qbx2rfPRyyI6cieHiaPXzGk6H7LMekZyLE5ScUlyrsUi4pWRblot2MsgukW"
+ "4JvHpnLho29nvgoUN3TmLojtxAmyVlAhgmZmq6jHF7VnHbthy7YfuOPA7ZvfNGRvFK99+7Xw"
+ "3o9gfvngnrwX1PEUKGEUKt65mVANwWOJ6u0v3VSXutbDiJ6N9c9c8ayiUbCeG48TZ6lWSuRs"
+ "yVb3+8UqYPT4nrpVtNFybAyTUPtR7dcAC/4U2vap++2/vFHC3hxe+/bry0q0av7p54dCVqlY"
+ "0FoHNJxZLAnz1iW1IosNkbAt0zqiLv6iKJwKWDxOWLQWSqZCZfGV9TaG4mhyZcYfzrdMYUR/"
+ "CLf5XiURsJO2fe/99t/eHGFvCK99+w32O841MaIWCoq+5KK1w6GBO30wYamFWL16mhsbq1Hf"
+ "diWfVIoOl9Amxbo/e1q+8F7ktJJoDbdOvY0uZvaSHsrryjpowmEi1BrQuFy2geUolC5m2yfv"
+ "t//5hgh7E3jt22/up+VEmBZ+i/jzp5S5WnzGyhnbdnf0dl8BOJFppiivtnGup50SHk54lqmy"
+ "95qzCW7rJbb4KWvTFBpyaBUzhRF1iFYXqg7WkCshxRrWfkDWmqdi332/feubIOy147VvX0xj"
+ "3sdBOctYfGitKnsqeRGjJ6DGtBUALmkWTNj5jJU2BSWpf4AaEekGn8vc2Y1zYK/yKeuqC7aG"
+ "blUSnHiDKZwSo0KVwSJr38kD+zCbadsn7bdvf+2EvV689u23UiNxeHZOuWqEjFDz2IIFjwhb"
+ "jABTrRpmizTM8zCyXyABM0Gyl7tWwV+VpYvzCBp4PXsvifxlerj3WstodvcFgAhaGa1Codxr"
+ "VqwG4o/xamijkm6fuN++4/US9hrx2rffUcfYhGY/t3GmS1oUrcRTWshHc4ETVnXX+kzJ914u"
+ "CSzudkQfYq9G3kIyHw89e69Zq2YfdiJjpljD4EeSRrilLkIqWhmJ/HkY0TSMACPFLcru5XzJ"
+ "9mzHgZu8LsheC1779iUYfnyETFQTTRi6klkQxd6r6C/r9ZSPZjXFxbQKFFJMwwxDuxKOGqDG"
+ "33C5aIksgK7ZXaN3B02Q2Sf0b0EJRWiyRMWyGLnwt2PRYuNFMNl8h6YLEiG1Viwz+1Nz8thv"
+ "l9dC2GtSLwu3kpsx72W/uw1PSNbehix7GY14AdRHFJFahhQsYF4l4YUStKYUX6eUcdYQD2Fd"
+ "GHy6P6uPrs1PCSPo2RRGyPBVLmMnYUSrOiSMlQwQDCgtEvu/++07vXrCXj1e+/b7Uyif7HzN"
+ "cjXfz63IFveWiZzfVMlGbDGd0LFuP5KCdjlsZvu06dAqPsGy+5WAcQVMhVKIV4nLGTsLI7wm"
+ "khmwBqOKVjdevag2NvWsTzLqYCfMlKxplTRVU8JeOQl45Xjt2x/koKgueAqcxZkZL08lJncP"
+ "OrenEE+euJ4M/2I7z0+J1VkNBSrQKp5hnDt0Fnd5WYzqlewXZxYtMmdhhEcS7O4nF2/OnYug"
+ "BHosj/CQDEoYzZPObf9nv32XVyxgrxKvffuylG9xdbCHE1U5D2Plm70XYefjCjFm7OEcgM08"
+ "gQLYsMTCsN5QmEdJ3PFe0weG1jtDzbRqroPBeBlkaGX0W3tvT3FTH5xW17OZKlFfH1ELGla2"
+ "b9tv3+1VEvbK8Nq3P8pj5eoJT2dVkvHih7S3Go+nSCHF1PlYAaQwbB5jCBczQ00uI8EHRpFN"
+ "hS97LzZbVM1nsEzGiq6WNCyFEeMlqlKUO5iMNfZYsvJYMrzXwtebmPGStv3P/fbJr4ywV4PX"
+ "vv0JeCOfdct2SeIpiZatYKaqRchCIyBKHdJQaR7RWkfcgBSGmbUn5vrHuERcSskYZQGj3Iut"
+ "2Lo+EnDzOWcmV9Cuaynmt7J/l9Edb1qVW4sUfc1UtYZW0Io6M2tdCkS2b9lvn/JqCHsFeO3b"
+ "n8KoiQ7W7L1mGSM+OLYYMKlisXgkMRh7C45XmW6I2oZJybhiQuts1qc6cCx1FYNFhuwYC/GE"
+ "fdkIk6Tv0nuBoKsthtKvx0Sk+6nxKMuyqO3HNmnYf95v3/cVEPayeO3bV1gMoT9rmaCxheua"
+ "SGyxtpmj9w6iyeCbZrivT1WSC6IhBWfOJK1/jEKfLY0D6ze7piEY/fveK1pGbpr0bzdzZq1F"
+ "lqsuSNRa9B6hyFOLhInFEy0q1qpW6sLtP+y3H/CyhL28el1mTeKfft4NBJ+YwvFeiUomego1"
+ "athbYVchMMSnEiGd/3ju9MVCV4OsoABSRo9TOJvjzHstNaxmmwUe5lUgddUX5DZrjIZI9msK"
+ "IzjKahRDBMKIp0FnVez0Nn7gVxBVvBRe+/bn9JRU8x+FKuOiOE6O6pGiqd0mQe1ID7hWMl7r"
+ "Kkn3gHZTcipB5JmYCXcWzVSxl6/hGOD5kpTM5DzWSih5RFXoBVrFpx5l2XItgrDyxxSq99JS"
+ "uFCv1tDK9k377Qe/lIC9OF779lWg8SqxQGSkzr18bkuWvGaNbIUWJXN2UhxzPME1kQWs0rzp"
+ "GYB+vriegJ/DVZoxa5XKoj+s4dMub06hF75GMpYUy+zX3AsklZKIqGHzzXSxS5eR147tX++3"
+ "H/rihL2Mel0iIpgfxsLBbM3MneEVXAt7OHIqtiQR5qcSVdUt5OKIBBy8kvb3HaMgoe3K2XvN"
+ "9ZFom9niKhlO1qj6O6jRTqZ+ik+z/RLSJ85RqdvR0ZHhwxhBwKtqewUl8gXx2re/Es9yXv7Q"
+ "C/KibuWyuJKxUGVi63LWMGPFQ4qpFYm4pCh8oHFpUEtktHm39+y9uCDGh/yxWdKCXOk7NrVc"
+ "hYZtyQSWjDro8Sl1+GRfbyUyNAz195szMBkPoeW41e1f7bdPe0EBexG89u2rEa7dLXqyTS6L"
+ "CbUSOLOf3imcZSxCFsriKqQwGuZ+7mzCqBPJeLKGpC1p1YVNElWkx3w4zWwlpPgDd/IKvyr3"
+ "Xjf4mIg7YcQikVcFalMj0eqm+bCmNdEeSrVnt4/tt894EcJeTL3sWlmwtk88ppN6Zb+VFCsK"
+ "m69cwsvTfRCGSN4gCYu2JCbUQmCRGpJk3Vq8DgVW3zd4L/7kRJuFETA3zko2DbkRwDx79Pgm"
+ "SK2FdDQD1MbHCVXPPJbWypHE2kOJUisvxMnz47Vvf9POnGGPVc8f1gVns7W3JS5U6dniW/AO"
+ "IqKN99OyFZkIQ42c0bDVXrM4rXhGVWzhvayyp/nEVqUwQkXrJIyQpFhssGIYwbY9jJKYwq2G"
+ "abnWSrE8jHBsWjFb3f7Zfvsxzy1gz4fXvv1tuL0Va+lQyQhSz8IWbS+XgyRswYFNVbI/G5qT"
+ "0ZMZYU86C7JGzth4Ff2bMdW/y+Pei+s+s0VUpVsxJVG73XuvU2txiuPlbnwaHNW0sLFQnT/0"
+ "5Q1Stn+833788xH2vOrFSeDsQnLoRZYrAMRH+VL22FotOUveK3ImKlT38WLCWLegnHEAZlbs"
+ "nveKVZLBmqlC1C0UGyfo5wKtxnI1c/fnGmbGq/GbDEpC4tU4hphcl7Vbx/LnLpHPgde+3bi1"
+ "yId1jbQtTf0sVCfeKwjVrF7xYWCLF04kjZCCBw/etV+ITzV4bV0YfP7wDNmqzWhhRG8e6YnX"
+ "PL55cKYFsSWPRf3W3OibdSsnpVXbhkLVUF0XyHXZbTRFR76//YP99pOeQ8Ceite+/X3kJCKg"
+ "w45kablmB5bqJm+K9OyOeq2VzGolFvbLrDqKN1C4Iem6pSJdAGHvFQ8wPoQSRksHNswDDUy1"
+ "y3TNYYTxtBrF1fd6zk5TPMHR11xYG/1g2gjw1zJnpmfYbvtteyphT1evuvxZJ9TckHHRnMrH"
+ "rF5SJhyXMkZe3ncqiRYXypmqfEv5Kp1aUvTTWg99JXeVBCzVRCuICSzhQlnJeGWbxbUphxEc"
+ "n8qkT1QErajNvoq9fxMdki+hXNtqvLzV5wpan4TXvn0twmDwkESwo4qtKl+Symj13eAvrycw"
+ "EXyL+lhoR04GH4wRiRlOmpDAwKh/PJM3P1qW3osONgY9lOx4AiPYE5F5L9QLlMbRk2g1yYrl"
+ "+nRWH6PNkph1SQsWza39lPJLgZTt7+y3n/4kAXuievlF4WM5SIfvApdJ25YSyK1CWyGXRWo3"
+ "BK+zgsx2KhO2Dils4KFSyN9uwHcZQJxCVsJhM7OVjsym725jnfUyXX3c6RycWinMALWsTyGG"
+ "0ALnpo2qoT+bKqDyNJ6Fr/OcHv9xvPbt67Doa/PdPNULscpiyyMcS3PGo8RkekkooJG2cB9p"
+ "M1jvtCJhV8ckEyZkwqSgAFJ1pFd0manoS6RteYG4ABlEgBRrpSESFJ8yVcKd1mqkbGygpakh"
+ "3LK25xRuCVt+az/qiJ3EXCvb39xvP+NxAXuKel0qAIdmWQTTDHuUXEz52bn0JLzOauK0JEPG"
+ "C58SUlQqkUm6IjqLGzkt+3aMERdr7r0uRfQEjbMwIg8lncdyreLT5KtafGhNRf5o1uEdlqsE"
+ "+kiKovr6JAF7BK99+xjoIhGrupBtFpyMwntltmgrQ8Z7kc2ZC1sqiyxmtl9JyWw3B+O1OjvN"
+ "YILO+HUlqi9sq28t8QM3OqJ4IKGl9tZ7neogdfjw2MDg6FOgyt7o3Fflh73RQKZq2QLw0lmp"
+ "y2hscPvq/fZZjwjYo+plf3Zgvok22hNqWa4SWJMhSwimoomJpOXCpG18ABrrJZ0FqTeDDMxc"
+ "P6tWn2p65Cwu98V+CxC+0JIJ2BRGIHcj6p8+CHFUaCfykAeWqNRg5Jf3H4AechuQnTumxCt4"
+ "/IMgg5bRxwXsHl779g3Rdcn0sz5uyOI+YCWYYVrwRBVWrLfgzHglvKLvcZVCaEjmeILv9a86"
+ "diu2GA8dayKTDaJKathvFkbUABbm8H0aEDG3GeduxEZplg9MjYFWqw7TkC7QvPkthUwiZH2m"
+ "le0v7beff0/A7qvXRaVrYTvqhI6JVkStzFxOdTDjSxVndvRggJYyRqix72GYels4XDynz5Oe"
+ "2QcrBQJdfz5sGHcGa6qPyzDibBSXgZUGRFg15DRBY6qFzeIuRQXFTzdiMSOFawUCNCNJaXNz"
+ "VsfFEF9Mvfbt3wIV/d8pT65DE3xZw6K7Yh0KRXPCaGztRN4WJixBlgij0x5z43E6v8PZquPv"
+ "djf+OgQT/yYz3FYT7U9scNf18gQNxCTiLD6dfT03Hpp/9WTCeChOslkeQOhLEGvioO3oh8n2"
+ "5/bbLzkVsDvqNUbdYFSljJTNc6My1ousVSvUwvKEJmnDndKZ3dhdDStYj6RgwrzBSOMpAA+r"
+ "0jHDkAnJGGNtZr//kanUC7SKT4VD+TSyeaqPfs4PtwpPAtJFy5EHR+iYVS+OhzIXX3VgIPgC"
+ "6oWphxFBexyFGb4zuXpsodio1yVS8U1Z2IQsWrZlETJMYC0SihhP2MN6oZbj9JWXYA22qvde"
+ "l9ClOOvWMpRPA0oFHm4FHWpxhXTGR9QnQ8qliLIJJozX51eNr1CeG699+2YeM2gzGCYX1mCE"
+ "/75BkM5TiSxapG3ZuvHDGTtaOJszUdoYMitVj4QU+gGKvsU4fwRj/fng4WMsWK74Nxmt95pT"
+ "U3P3J+NqchGcKiOHW6FLUTIc5ugbidMIVOGne4BJQlTBA1IU7m4WsX3FfvucdX08Uy8/w8wA"
+ "gv6gWDGXDujZjREuYVjY8oVLQ2YUTjVxbfaT9yIN4/NsC84H59RHvtfsvYQWFmvZmFTHExXN"
+ "1HOUFcOtfPURxMRLf1F7iOrPckY6h14BMm08Qt0VKo5jrHMQUkIKOvK5csfgL/Dat2/B8L/5"
+ "B40kZXVZ8eQqdf/ZGvQgvWrsKq6Sk4bdx4sNvkzVcEEYCVghcU2ZapBP3tsURoB3sqqF9TPG"
+ "OH6dcqWklKshsmcKPYO8MDYbA3mqUlYlm37Rxt+AWpqD+wLpeGH74/vtVy4EbKlefDkrAdFg"
+ "PytcusISWi1bsfOjP+wtY+vckC2anAzT7PFZ7YwwupTXCCkqWXu7VyvWD+10oa+kW6aOiGHE"
+ "6L1Wd8zGy6x9jCGWJ5MtGo9FRS6dFMT5woSU56LUTkza1mnzdmIE19e35HZt8Jd42WnyGZ0k"
+ "ab1RqYZM5tVWPOVAPy1PLo3lai5J9PLQFIjqBSuOHFJAQ/xVv9CYIe6fJelK3qvQW9PXsZk2"
+ "eq+NoWzqDTIsvFc8q4Iaj2abKHBvxSkZ/LUoPyva3Gal7NQ9lgb9tJqxeCzpmvDat28DXR3Z"
+ "ftAkV0zS0pDRFgpXt7k4cgY21c1g9u+qV3L9iyppB7KicNZ4zBqm756akwl0ro9cUfqNdWsV"
+ "RuQhpnT9rXZis4J5is7dqq1lFsmHtahDh7Uc2blzFW7jWWiaag1M3fL2pfvt1+T6OKuXjU5x"
+ "jJYMFV/HMEolI/m2oEn3C2jyVWWxMitWKJ0lzMx4QX8zxCbkMp6wY6N/jKd4r8GWXj2gldFa"
+ "PIkhzrLTWcmWNktStdJaFgpftFlcH9lmDZ+ubzGexcKWia0MHFZqFwZ/xsvTVJ0pEbjMRDJk"
+ "y5kSeVqhliQhg1gDTFnDZuaiFXNJIw0Turbq4s8skLu3YdA1frzZe81hxPxHpjiViB3V5p+4"
+ "J3F12jRZey2R8aSxmG+tXH87lDCs3JUWxHGvbcYDKmB2tMLL6H289u3/9gKYdnBaArqPrHil"
+ "w6ReSyLTflqVSNMefgsnqUTUmKcYf7j3IockS/vFlwRTv28vYUNmn9zuz8KI6gWxaRiRTq32"
+ "UVwsNuc2KzT94uB6lh+jxG2W8SdhRkjbWsVBWsgdAxbii6rXuC/b791vXxjqY1Kv8bN2tw6g"
+ "QKwgIvysvmTJX3pJxCK4+yV/hUC5I2YqS/5UjFt5O08KKaY+IhOwQrWV2eK3e1oY4SXvfnwa"
+ "wy2ZbVZy9DFKXSYU7sl0yweXTnsX0zZY36LVeb8/uD524c71MeHlDW9M9/PDBBNjBD2msUIk"
+ "vUsSgzOqmCSWveTPIlvZfiUl0+1YQQyneJDZ768qWv74A8g006z3GqKm3oekxvh0vrSp++XJ"
+ "deUKSObd65rNk7syX+UGKyIYHJVpGLcZ9dKbwtVTE5tO4dR+zOoFMrNlaJjoD+24nAE3K9xM"
+ "Ekvasr+SeU0kLTVMGfLoNTUqywoyDinKGM41UtaTq391D3yp4fMzpqyIUpH+yBRbe2swJvMe"
+ "O3zYdbmYTdaeQbECZ6xYTQxpFsVavjL0vcTLqBm1A8QoW7Te8OxF8xyvfXuWFAsrONKSSuvr"
+ "ci+s3Jys00tOJC24KyxIdYcXXxu0bWpL5qiCUFuUyIkw2HWEE+LRfnkYUVCo9zqGET7WeVkZ"
+ "hR6SKxqC1CbVqWvaHDWKHoSGPyRirMaNhzIajLyaIAihqJofR29Cbr9tv/0Wt1+sXuPifYZI"
+ "gSDcL1DDk72/gYIARKF1cu2bmHPLlWhLKYaVUa6eyyqpePUvXpYDDOl7yXTheym+taeFEevQ"
+ "IZ1pyAzF6KtR4Ztt1kxbyC/g9/ZeoiMZoQrUJjm222FbjpB1i34cyX0xXhfa05mSM2ISN4SF"
+ "7TOpsbAutTAaMjNwkpLV9JK6XoGRSjKWNYwgS83GNPzL2F14L2OLi6PWMm0t5sE2y/IXbdbY"
+ "/WSz8nB4QpBtVoCJ/RYPueGqF+tdM+dODUNR0A+xrsaxkePwnu9ov4J6wdt0BRGImYlHsTt7"
+ "4WpNCzltly/WXyUCjNqCpxrICI3HhFeBnPcR2WdrJauXea/C+9x1qxXNt2b1usNZHxXDwJFE"
+ "jXmyWRJtVovuyp464OwaSdCHBxZEWp3tyjS+VPOXC903oybitW/fPeFyBhbOn2UiFZfTwvpo"
+ "ulEyT4G8+96fX1LotWTLPLYgyLBK8KFLpE7n5MX2QdN7PvMnjQ08GZGM2WbNEqUr54yUaqXn"
+ "UmazLFOwtzsGB0fMTrlheMDf+lD1OpShIwZmBtYBCLbfuN++5JrUy/uCQDPz/R3sztQOdx/2"
+ "Qx+uSd4a4JewbzMiST8WzCX1ipGY1dNFSJEG3ds5jwjX92LRAs9DZGhVDiNOwi0vVdzbzTaL"
+ "Ay0E2lyHSHWkZFZSo8+SrQbyW6Z2ALT3OqBTcVh+axvUca39VUdj+2V4XUiYHmFL24ZC0WuI"
+ "TGcdwurhff6iMi1UDSdiVsNeDxp2FlWQhvUt1xhPLC4LPTUbtcEoRalixbI+nKkPcXnadHJa"
+ "ByvQFD1kJZtubPa5r7AhbsEclerZoV2KI9ZqqmFF6y+0jakQ9/bBhFcehDPP38Hu/grzBk2o"
+ "kg4RYc7ufVITc1PxuqNhoTJySEHXwmQZs5SOkSWwhus6j09zFk9pVj5pLDkt6qVm527N0sSH"
+ "YzqXP3NIdXg+M+8HYjqvuJhnz7rV30WIVG27THhd4DuysJDYlFx/slYg3Xph7OYbphmmR3+n"
+ "vAWqs0HD4om4uS1p8xjfLp2dJglfBQvKQmeFwwj19TmGsC6apZFaqg7ZrGZDmXnQFb3qONzI"
+ "h35G+DYDoFaOjVTxTRlbHaOuxweVb1iDVFFjvPbt+zMKEamw59I8r3a25hlbS+xMt7ic4VTh"
+ "5iAtMMc4xjzC255zHqYUcs+j1Uc+z1HU87kJm+LTk1FcQ5Dma4AX2tMnNsv5m0QraFUa+te7"
+ "qJVICxeoQ1qNWgv6xJrX1zkkADq08AJgvPbA9vn77cuuUPUy4yX3gVhSdR/BO8+eSdqdhcxN"
+ "vLlKnbcuQwugrmSM7NQ8/AtTxiZ8ozCC8y0aHvOozWIBW9qsAFPJEJiKjDJX9QQke0gRvJU/"
+ "az+ywzvU1yc7b6JlR8WD4GijUxVVR30NBet41eVOPZteCYLwFkDoJ6CaC6rXa1jTU+dVMmjY"
+ "iSFLGob5b0FarEqwNr0XrSk0cH5uJJrlarPNshpHLbhkswwyLmdi8sFkG4cAACAASURBVNZc"
+ "TlzeSKXYkD0oebDzHLk6K3wP4vP9h2x6hDw0HN1pXcb+PB4GglofB14vQ9ISxEdXfnm1myWt"
+ "tyXvojZ0a5a9KaSQ1EekuFeSz6Z/dB1jiPDihB+yWXNXtJc8GkflQhXP4clyNd/PRc2aeKo9"
+ "BqL36ojDd0jcSBnwjQIqOGQE96OyA60AFNIewsH9KI6rPS3UISjnICWeRv4e5+3l0u8LwPpE"
+ "Ly+mWE/EbgZuaciYpEnMhB5aJMYlEjqSwv1WHQuldt2SOYyYbFZbIXXHZnkcdfi+dBuEsHDR"
+ "uCPBc/07cEiom6FF2S1aPOEMFw9++721Bga1DaDmZ9Md/qh6MT1ne33e3+fw3bt/ysqznsUl"
+ "woDOt7piLrJlS3JIQYplSmmu6058al2H8czV+zbL7rPZAi1JM/AWXzLjfZ3eq3NoEfeV9eN1"
+ "fRofCf6OB8lSEzxIOD2kqYC5q6s4Dsbrwu013VvFIfT9Lqt5pkISAXfmnwvBO8CljS/bmDOI"
+ "CbWkYbRCPq2jEIjq6GlEV7P4lJ37+SmEs81aO/c0r2RYWOAJlg2914euTA8eW3TzxOsw5fZe"
+ "nIoNU1UhgoeHEMUdOtAIdTgwwmutXk8H5Q40d6YnbE1sq+fYiQV1PJ9KISJ5JS+RVbk0B1aI"
+ "M8smTLrUaQ2qprEPPjqPzvfKzUAaDsrCdsDv7VkrW0FCOP1ibqiRONjitxbKJmSEDod6LNGa"
+ "29lCRRMcB442WqnWkCw6Nt++7KN4vdj0vDjeh/L+FnD3nh/WvBGZB8rWCS+KZ/mPWzFb2rfY"
+ "zsIt62BufqyHZhrIXVlh0hkpOk7hcMKcNl2hWcTQW3B2X0YjsZHMNGWoce6FcRaQdSr0D2CJ"
+ "PC44HnAIcIGIX3hC1H6NdxQcsKsyPdu3z4w7hsUg64TWxMK6Qk/hZMn87MzQaAfoPIcUmBoZ"
+ "/sI7CN4Bjm81qpoxR61ITH96F+PnbzqW61Gb5dozOfdG6HAz0LuiuYuQ7FcXlYMSCg5I+2c4"
+ "qGd6ABQHjTmaBcehGwRBI4ObBwAVDw+jSo572j690faL9ttXXZ89XboeVYvnun/h6SmKeGfN"
+ "c+AMqWUeBvtDySpvJXZdFzVeNl5+OejqLE04uU/q0iwypXEyQvz1cIFHzoQ6yy7KGOripBuE"
+ "9vkModWW4AGUio8/qJeveqmmlr/XkEAAeNZ9Pe2Ref7OzPyq56Dkhe+fsvE7hTgtmRMyUrUU"
+ "Uri80Tmx5rTioCspoahx4UuZgomHS5ruWpYZt1zAAw20agUPBxU+2qZ5qX74mIVCj6+0I3K0"
+ "FTDEiYMxMYltY53DhE3fl/keHm7siOdQr3dnehkcl9hpT+XitCXuqVQHRmGEO3EeKpiCAytb"
+ "cwOQVxBv5QUFAhWj4r00Pa3t5czVi9J8TuofDsBqq+Ch+THATPSmycPHx0v6EnNUjbbcQezb"
+ "fziILTtUBO8pXs87PRFEnqmRsOqEoQA0MkItV2LlLFOw7CDlDp4vCI2y6h2IlE4dHx+xp7fs"
+ "ONqoOB5oVBYgXY3UffsSXd7lx0Tx0EilZxZu7cUpbNPW2Bfa+lQceeLiiKc9tVyegv47D5fz"
+ "KejHqmFxv2Q/33QGXHHvbyMp+GQyZULIU3t1O5uvIz032RA1VRZB9R35YL2BID+kKRfU2g+O"
+ "+wY1eTIIgvsmP26yZ3wMLqflASChhbHdwBqmeH3w1etlJrZoI3b2v1vG7b4oYKlY+D4TPIia"
+ "J2h/sw46EKuMbazTmXtogPotL2SKo5WwxvNTg8DkJ1slZkicsyRIrq/H9KoViAMvWdjlmoz7"
+ "S+yYl5yewv6dN6qr+dQ8nJfcubmxbcrEU+8l1LVhulukoZGRaqHlH+55nWkfe/1NS4reN5o/"
+ "uz9b53jCa4FjVJJnZvJ5alPJfHRHzvv1TthVnjDPn4QMeLjnglonFvtnMDIEuKx4vU+w6Mco"
+ "wOqvPb8XNzzP/dOnx7fzDO2R3zr5qXkXLueNrTo9u7RIjAvP8/r87k0DFQtFGbLy/D+VvYVE"
+ "pHq9qjLi8dKHBEJewua9jkleaP7+krNpdthn90m9eM+XUSKF5gG0gos66SJjN1d96lk02aXv"
+ "mwKIvrBABKUAQjgWNMEz3bhYH04Z+5G9PQoKUAS13FM+tuf2nWSFkSAEWFBjfVG2IChlQFbQ"
+ "PZa1GXumIfn+paZ5C4s9d3fJ0+fPltyfnrJ+L47tVHW4RDbgE3S+xJULrckogPTGXsK9y/aq"
+ "Eoup6H79hChF/SW2Zn95o1fxs4JADH/BGbK098YHkHFc9YZ/758SQbE2oJ2L0dMB1AhcvXt/"
+ "ie8Z9kqcP9uXb1g/XwTcZ2hoGLrCU4tuppwbMvup5qLWt/Ms+rCqKFxoC0IYgaitUXuYwvRG"
+ "6SsuiVmuYLXOsHY6RSErA6QCFO6Q9pvqGaCjzlUVIf6UTwekapG1+3kJ3b+did+XpeNR99HV"
+ "6wAmR5XUAnGXsFYZK8/icpCKsD23VyV7NPPHK/NqEmfmeX6j+T59kUIzojar0esLUApa8RXQ"
+ "UEF9iByuijqzxtgyJfrQR34+sZ7Sy8M966UBWvPyoAxnAvliUnpv/Wf9Jz+o63G5/+YNszjZ"
+ "TIk7uGjhM73hHdzoNEvEp8r07ne+2Z1faKlhplIXzUftILEP2frOkjGW3sgbL2+lCPVVdzfW"
+ "CDJACyXdS1xolRTi63ORzfPzz3A2P/1IcsTSjGl+vj9/9vE3HdOz67+4feRHbIj2WYBSIBK8"
+ "EU5aZELttbY6TGy3HVELMZW/MRVAsoez5cuvNbPFnkxIn2xJWC4Rsv7uggpIUWbsVaIOTOwc"
+ "RqESmS5AEg3Z3BTAuZ7Nqha0sNI88vyrn+jXdTG2e4n41tv1K9Hlo7TFxlicGvlokOTM++lC"
+ "r7XdfCH1AsmbxIfz97gvTvNqEt9U4kKDg2tijcttu6Xf+7jBIWmFACjGEHcgskqJGX/aJebM"
+ "HAUOO1IlRVjTVrb59TQXYgnu0E7HSMvDHpjn50gC07PBGD8D0NpAp8aXGgQXqnr8DvNAvOlb"
+ "+m62JWZink1FU+Iun7cGJsZERXx9IbZA22GkLHGoNkBcv07TFxQJbA3v1ZuQOhKnCCE1ekLE"
+ "G5W9+wV0TkdfE3oqhExFENE2AdPCKW+zjbue6Wo2n+2r3U+/Lhfi9XwlZEGIzwc+MJQoBvdc"
+ "U6xeFIXszDgzHxfalMT1G9VZrkfP6K2DqEzbn5ekjwH6JNy2yBUQLkWmW0ZYwfgTCaK+vgFV"
+ "TRhkQOYhhY0ObaDzzJQ50dGK4+9rmmDYedst7kt91dIA2X4980lpcgSR4ZBpy887+bFOCOr0"
+ "rO/PRgY87d07OXja07YRdlSJ50ov4WOqxSRMIuUzRuBfTNPXRFW6ndksmG7BCXO2rET24lhG"
+ "YWld4TikCPVRwE8Je/9YPZMzy/teZ2z/wXbn8h6PrTD3N4j/f69hUf0TLiSwz+ewaOAF8We4"
+ "RM4ykFazdZZBgyhtz3RhstgtyiFjMX8Jfnjm3JOMDbc0HTO23B6OPKL3GQhKHaJVKu3oQuVY"
+ "NKTwEXzMGV1xPvyJg2jIzIdxVMYe2QTMta1/Sls5acacTaQSKavVkOcfmVJjouZ53cIojkzG"
+ "MXkX0xKGk/foWUruu3nl3yXOy7QCpo9hW7Nil9qDiAdDpeNf2GbxVaiondhEXVd/YYXoiM6C"
+ "YaiK4jU226AhhTYb56y1MVicwZJF6wHuMG3n3p8lJDUeYV9V8rz/lLK+T9O9lWP7dz2NX5fU"
+ "q4zZbnhR9DjuzkN/dFuTP0o/pvkde3se3QjH3d83DlrOX2oubbPgXeLWeJ0mQaUYqRKNPL99"
+ "x0tkWEwPI6z10N+iEXnit2KDoedC2aZ2pbmxRuVmoEYwheoZd/Zy39vHcuzIfQSx0U+PuAIk"
+ "3jPWcWXWirCyvYSLo6Dpr171vmCxnyrNpLdK+5uViRmaNQ/xXVJmsVQv+63u2CzjKS2stJDb"
+ "if1+BF2cR1BkLxh4QHTjejmc4g1G3bSnX9M1w9mQOWoJqZOAo+/LVvK+N0YzduoFs5HinzIl"
+ "vayLtPfG250UX+H9LI7X9T/d9k/ZCJjsVCx3SJTw3l2mCemhDUNggBIiZ2zZzNJmjUJZ6DAm"
+ "hkpczd7DHH0xy1W0hbhkq6C18S4NRJiPpEhG3lqRChA3KtmNpQKKSgyxA1MJBGK6oTt+FiHH"
+ "It2DXsjzUfZstSc2NgUAbtcvdbyAYL/STp3np62NGdsNBh+3HzmO4vn0FrwFxKpXoAVrhZrf"
+ "otPyVmF/qBa+31XTrd6iLMMVBLYKHU5FP4Nt5zSkSM3JqVEpBBxoOdR+ITYCgiEjLLj7PLRD"
+ "7SUMhNHD2jMR4/zN2kY7LX2SIGCA4xWDe2YilUh7NrXdViSPdRahPBuyMkzP/C5LmxWoWpU/"
+ "UAABWjP7enX0NmNhxJAJiiT8TSkltR3aBGi4YKIqyJhVTMrGDLgz78/OLC0Je72Eh6ZwSRch"
+ "Cwph25fhevLCGT4rsjxv/PkOd7yaBEfV4oAZkD7ZPDPEq83Kx8SUM9WZSEKUokVNfILNCuGW"
+ "zctoxJiRAsZfJrK4qy7rY9ca814M2VlIkTQsNSrNnDWaN0PWf4LwR7Jpxhyb7WZGIaWybsL4"
+ "uJzqox/9U5F1Gu6uQPOkXhJ2YTLsBsdc1JitFrHDJH4hG2MNi9A8glSnYVrTY09ajb/yHJ+a"
+ "qe9Nwm68Olt9CGGwbiZpvHeEIBshhYb1c9zKumWjXpdgCW0BEbUEEzcw01AzUyzrm/KHxl+E"
+ "DPat7hdZTKUWvjDhdf3ft498543BGzRQ5WLzPssPouBZ69KQWioWE5nC22XhC1uYVsg2K60T"
+ "FWtQJRDRvzXV96w4W4Eqro9s7SXcCkvU4gITJdbX82GJbZKoYOqjIeMKldKNxt7faqgCMWa4"
+ "AUjreAk27OZGaMKu3q6/O+MF2DVzsiU32hoN7ZrrJssYJxe878dnYIGhDubnslkGXKfkzGaF"
+ "L2ABBMYxXE/CiFa1GVHym46g1dSxH3t2HRMQYc2SsBVk4TapWi6CjzkzjtBgO54Nmf2CLEvx"
+ "oS0MuNg9r5OaBbpwGsFB4/nCH4MZb9Srw6BNKwXXzWV2Jb5J3+vzOrzQn5W1zvkenXNX/YQW"
+ "OlQl2MWM8dJ7UbtZ+y4rBFDnrEfKhaSLUda3KKI1tIcUIdyq+tep9bPOVKWGpEcbBBa7NJM9"
+ "6DGBElFbwkTFzr2/fgdulqYhQ6ZkYSGUYJNAGZSc4QVxFbEfFKRMupvWoCC+JKSvk81KDJ0i"
+ "dUJb4izVU6OKzVbAq4+J0DDCA/rEVlSvpoMmbL/Y3qmiYiZKGFt7fzj95dhE3jIS8xYoG3zq"
+ "I+enDCYTFQs+bAamRpSysv5ZDxUL1cCIK2k7T1YjXtd222WzAQuG1LCA2uxK4ercsc0MIT5k"
+ "m2U1cbZZa9qIMyvfC4z6Q4pP7SnBOO2nQjnoYyRrjiQCWyV8ntZQUnAfHVgPKaroaOlFK5Iu"
+ "Dd8mCnOaP6mX0ZYxmuJZBm4O0oKRUm4YoGaytNRCrIwXbtcvXuMFjIFfEnehIcKTwZT8OBIc"
+ "FKa/vM2qar2xslmWvgbCSLTmMKICUoGmspSSCE0onOm+X2bvpZWBr+JbBK5bi7h1/iMuyYFF"
+ "CoMbM4y62qkIheQiNiOMkjk/a6ZkESBEOXSq+GEM1aYp4tV8j/qeLqOVNOihtjqTx6wsyxym"
+ "mUdsFnTnRYjzEFMJ61d2YFZDJSwZ9cu4L6gV7fAGo9XEVB97j1CjAau+nARMb6X4X0GLJAmn"
+ "EojlMjqw5OhDGNvf0oxdtE2BJDKCWYSstWhognjVly/HCM2hWk7QE17ihPGyJR+Ixa6eyI9u"
+ "1VdYRAz2I0h+iqFZxhb3wq1JsURbi0X8D1/nMMI0DB6G+VvT+bT2AS4nhBWGJkjRSZdRSMhY"
+ "hMpEFTMq/k0Whiw6fRZCaPABJdW4aRLqoOGLO97fuDjB6/qJt/3bt3R2q72Qf+UOwTyAYlaj"
+ "pv1CTQdpSdz4MtA6816I4TumcKuDNVfG1FocYQS8wTjCiDrY8kiCCEPVv4sN3Zq+aYWOOmne"
+ "hBRYSJEgo6jC41ZSMiMsq445M0MnXUA/tQlqRCo6tkd6Ng1BZIWzYWr2RhCg3q6//h5eAHDQ"
+ "r0mZglmxxKfQCkXCOmkmMYfJ1KcK2Ohd2Fd5a1HoQ+hkYKXK6Ol8f3HRMMIu8XcEa+8ZGL/j"
+ "gRIzUXddqli4E1KEqGLSrVCh2I0ZczwClnUreX9qhJ4hNZjgGdIzJ5g2yxIVFAv+zadpwkt9"
+ "SVhStMhOqBkZ8wDXpD1pV83Asakq0wuxcl05PlX+lroFtfNN+3yq7RG9BqA3GzEG57gP6xrc"
+ "xvhKYXdIkHFI0d/xJKSYR+ywx5eJOQTBCGeLrFqLNtNOkDqrnsLRCzmwuVcKCFCupozX9Xvc"
+ "9v++BU0iaDCO/AAB7MPMDukMqUhSI31icNnd+6ZiSQpKdoKXcBihJ15bJBmsi7LF9dG/QtH9"
+ "Qjra6F1Yxka7quESEodlEkachWZjXBgwtaoXwWpT2QqKyM/SzCx1lpBxy3GdbgzCbtdf/The"
+ "gyl9CxOMS/yh4XszIBhApMLHxNhescAiaCHLFUGGO+HWymwhxaf6VA8jejsxJPWM1In3cgHT"
+ "5aZbIQmzPqL+1BhJMWlVvp8S1xSGLRuVXklPyqtrUsRuvobUbMjA9VTOiynmNuM5XjJ+QUQy"
+ "AiV6+DJ59WzlqUUZVo4lr9jBw7ol4ePZDNv8JFqGF4cR/RQgkZFID8hUwELDUNOvrL62m8xj"
+ "sW5Bl0cNk9zVHZUsRxXcwEz2axmPUR0Mzin68fmEpUcNWSN3L5SQpSIrvFcew+v6fW77f9yg"
+ "fitBxgJmS2YszpqQSRSxIg+zzWIt5KfIwvtMHC0oFEaU4udbFB4/aDaLHf259+LDzOu1auQl"
+ "EdYgmAbjy0lIwSWMy2KwWYlUClo5jM0FNFq3eaEVfn8qpf9cT/VbAABu1899Kl59t5mA5Taj"
+ "jJmzmsg4NspFK+0k5smpumOzELe+GhsIa5FMY7mGbln3ItXEpgO8ZrYW3gtD2Ibg6SHt30i0"
+ "3GvvkIcUi65uqKjMBotEK9e+uIIBFAKwqElr7594iiWY1e7eULMyXNrJtMbr+gNu+zdtEoUK"
+ "9EM3uzKg6KhOyTvDkYqQhb1FaRZjtAi3piQidyyu4lObgRBb9HfvalEXmIyXccNaRR1ciLlX"
+ "IsxRE4D7uZPf8pCCFCvpFsetQZxmQxbHU8jK5jfmKUpUI2WVSNLakHVJw+36Oc+HV0fJKwL8"
+ "MqoMxxI72+sJskVp6xsXnzeGluHW3E4M3mt1X9UhoTPE1eAApqTeqqSVRTb142FVZS3hxCFM"
+ "Z6dlyJoStoZs2dVtKmXCM9uvFInNYytmm6+/I4dnoFeF5IxmwnDFe6b+MbxkXDmHa5+xAiWJ"
+ "NQlRlnLtsxXmsQ+ptchNwhg6jIVn7cSTMKIYW9Z7rb/5ki0rgo6amYEKOfQYKN7jaWVxTVg/"
+ "VsdICiIshxS2a1cVM91Sy3FpyFrUpLUhm5NYylfXEkgvfzG8rj/ktn/DJp2zSbFaGoqjjakZ"
+ "qbJCrUYlK/Ehk2Si5ctV3k7xojBCZHRejQGG/fCzVAJxp8Cbjf0eCJ9cgHbkQWCOEZywtgwp"
+ "Rom0/Y1QEIUVq5GEJImKhixU1WjIgvww0KmeTja/xbZkqq3WqEQBLrfrZ78IXv2nlUY00G9i"
+ "rj83D2NpSy9htpJtMm6YPNthYPulq6UGY1IsaGuxdiEvoxRW0UCVHS1UyaCqBl0YD4yiDgyF"
+ "+h/tW0drP8cTg7BmmrnK7gNn9Czrlpc/qnpz9BUMGdXEBFZYQUZs4zwlyDphl0kJnhOv66fd"
+ "9q/frBRagbA9vaiJyklo9E1WPXeqJH2KH5stfOGNCABCKo7lstZiKXoZkhqSiMxWqo+xJlpl"
+ "HJlqVTtVQ4MxnZ3WhJTMqqR7/Kod0lhY+2zzT8ZQcGYWDFnsWVo4+tQU4GQfoeVoL/HaWvvw"
+ "itv15704Xn2Pdmfai4s1JIPhjZUx2CxuVaUKuLJZQecItVmrgGC2kOJTrpL2k/KwwRIiCSOm"
+ "TPUxSFfDpTtgHVEoh37xBtiPIIE5CylAnD0+Hp/N2bpczolr1K0W3RKPgF0Or0g84axEUhPy"
+ "sekRvK4/6rZ/nQtY352Wiwbh0WclLqyxMuY0i5v3Rkl/IbcxhRqkkSfTRaH41HTOB3XZ4arD"
+ "BnMkcQBs6kv4dv75j3GBoNBgpMK9PDvNadNf59K0WudAa0ofUkNSCClXI2R0kiFzZWJPUBxZ"
+ "sD5hkjqupMPD3q6f9bJ49R1pDgzJZpXAU7JZYWFEx/hglUoFdHgs7QnAFG5B542nTpj5ng6B"
+ "yZVBNthS0ZJUFslytRIPjE5e09NrVa7CfAMs3z/hDDJakbnYJci6osy27F5zcmKulYBFcGDV"
+ "L7q5tvx1/Ild3mDPJu42GJ8Dr+uPve1fuxk3eIJzZ6v+qM0q9DCUS8NOwgqNroAqGAYLpFsu"
+ "Y6mdGGVimC3J1j55r/k4qeq3gnSRte8/yMWak1NI0aSfVFJKMD0zbdX/dmRmq4aaaLFWzsPI"
+ "hEk0Z7JyY0HtkvenAgrcrh95NXgBQHPj1eYxM08ZqjUJFa+Q/hDGOj41HK32nYQRfOL1cI2U"
+ "1EtUrMSWmy19GCojhj5ZNgGu9S1k9+OQEFKyFjRMRkjB+rGEzNCJ3ZRz4sqceTVs8cBKz6rC"
+ "BTfGNdHAIoP/BNf1HHhdf+Jt/5qt/4gsNinONu0pjFoizx5KeItEGGuVUzUj1QUMOq+QVXG5"
+ "ajZs0LRK7rIV62OojNDGI1+HnAlbnZ2mWrWOKmJXN1GyLJecaflqmJaklmbsDp8NWaDKOK6Z"
+ "tla0F+invUq8+tSORcq1GIQjMdwiQUpZV7L5VcsKiLMcn1oPjyLFuZf1AoFGokLNlqQbYpUk"
+ "1PyYmXOvhkvRPEGGQIIiCa+YdtpVC+XSIVue0j0KnFWiOQ+rpzKW4UsDyLhRWVTGJVMV1lz1"
+ "iK//cNnL4XX9qbf9724mTgmyPp3arKl5iPOxgakXKImWyKCwX/bNuhRFUUMKIw60ohe94Ugi"
+ "OTCsHp7nXgBK1a+pehy8V0OBfzYzZGgYJ32chRSuWGqrZ++VIgw29cHdJzWKMtbrZm4WrEaP"
+ "ccsUl9v1p7x6vABcf9pt/9tbnXhi0cKJzTqjyksk6xAtT3h1npZhhPUCXczIjxa0hg566CKx"
+ "pS7N2YqFkqWrYhgPP5m2xSak/Rp6JNwPKYrEPx6TZ+i8D7539UpNy1UYlvOICR1vVLZFVfU1"
+ "5Xb9yU8HBs+FFzA8PutWsFkEWVGXw5EYtwMMyhk+RjBfSZAUi72XmfoKja+IGwu6fCEo8Yok"
+ "NbpsSfJefeY4gOLidCnu5QNPCtlZPOGcPSmkiHGXs9Xc+DN58/VRWtpCLHwmh0HDFNnh6J+j"
+ "LL4IXteP3Pa/sS3t1x2bldec1MsTr/NwK1+XCy5dEC+Ohb08uXv7m4x9OE0a4NU46Fp5r+Tu"
+ "ezsUTWWv+FE3NImQ4ibkvZAihewLyMqapKBbbLYmo8ZLEjr57RRoa1cCt+uPe714Abj+rNv+"
+ "17bERyGkgs3SFXgm1Ee1WTUC2qwvxZ61wc0965IgdT7qhn4ihwxjDJwnFMxWCrqi95J0q2gf"
+ "R6ldcryvCUJnb3PcBXXxVjqnMRTuwEIrElFCpqgiRPOcSsy5F8JCKYHOkHrElbUmQsoLsIUX"
+ "wAvIJdKkazni1GN97l6cslOkmohxWLeIFOAF0dxxoRzVElQYQ9q+K2S/ZraS0+IVwB6/oVa0"
+ "B/0kQj8FKZOt7K1jJQxzPze3Ir2fe1YaFqoW8oWlG8sLDcc4sMfey7RTYmFt9YkZ/Ty9CF7X"
+ "n3vb/+LmcsUWKj7MY5qJqjk7BaUPgLsrWx7GoGLMm6m/KFJAaCeGG3uyQlWS6+DkvdLtOOi0"
+ "PPb1COUvW7EI2cWsPYlZ/ivdASAeBhgVa55JGWkuo1woMbE4DfxCvV0//QU4wQuqF3D9Bbf9"
+ "K7dgs+ZOaGLLWgBBt2QEVHO7kgMIvgfl9WLDuTBAKdpRPf6yeoIMq3n2XiZmhn70XiOeUIj5"
+ "zw15K2cOI5LOKWG1ARRStD5aGisOzkKK4LrOZIwlkBKynHJZTK/dUIrg7fppLwYJXhgvABDv"
+ "BuFKl/sQ7VCmmZydim+Vxzv0+1Qo2dRzGIHqBbHpeWZN1oFq48GDXB8JO0YqeK8DAEpFbeO1"
+ "TfyKZd2KMWGi/e5zas+Bftezy5NCihVkzYop26+paZluYbWoYe35+n+W04vjdf3Ft/3Pbuy6"
+ "mCSuidlgcdc1ixbXRHhlRLT2hXqEgGG8zF2lmgj+JaF/77NMfmtVH5MbC3aKZrq961ctdPtV"
+ "glaNnyVe4XcVT3TgWLTmgmjpFAJkHFWkDu9EYUgu5vDCmgu9tfhDXpgQvJR6Addfdtu/YmPP"
+ "Ptss6wi3ZxfxqZY80WJXWefI2osNkeCRg0oSjIY6fiL+q582wKsg9mpPXp6zCZkEzB8WJanv"
+ "6EM/VaHUPtqvplsJIUVuS/aQQjykCIUyyZX+vhmj2Im5rIxJqIJM9tbiS7GFl8QLAATtiD2P"
+ "5uspMs2NSo6yoEu48ZgUK5p6VzUKIwZMQnu9umK5jBEWTR1bU/eW5SrlXqpPHVZvDKpjg2gT"
+ "1c5RUGXyJqRyNrQwyVg/pdto8E9DoATjNaUPwcufpBK5/zF2FkmD1Nv1B70sGy+P1/WX3/Yv"
+ "31qjRVGibElY+IT41BQLcN2y4iiKWjjxOioWRxLjZooVK6PJXqNuR0zSNa7vJQB9u+T9vbUI"
+ "xyhY+5XxAtsyDymST6qnkAXa5hGIsep5cUypB436ejnLZdNLqxdw/dzb/sc2NyUEk9fNSBUj"
+ "yMwVtl+GlBqs1iAIpt7GOkNrIhJhRWslwp5ikkZC8Vg2wd4raEHFGQAAC5JJREFURDAkeBal"
+ "el8Q5fhu18iEBciaczaFFGq5TMlmDRsi1PLyNkuUEiapVlZNIj715cHAK8ELwPXzbvuXbS3p"
+ "lj5M3itbLupPTFo1llsYoSXGrh9e9OSfLlG9nYg6sTUn9ekiXma2ovdKjccUT0CL4PhDvjbi"
+ "stFpKdR4HC3NFFKcPFx0RLLMWAtxrWE1a5UQUi0CannHOFIvt+v3eiVU4FXhBeD6+bf9Dylh"
+ "VPL6VCJwLeLFY7ZgWsVhBNVK7wXqokWaBK6JpmFqs7zZmNJUdvcsRTxPNyhhRbsKhgiV0IE9"
+ "miZtfKNHQwoGaxxXS6flhTJeNyCL2dS9E1CLfUfUVrhdv+erQgKvEC8A1y+47b9/k1TykGsi"
+ "NFkAgm5JjE8rHf3WdW1pKv+RKesF4rK4iCT0z23YwpI0jNxYromxIdmH5bSGi252VMDipdBt"
+ "VjT1nTC7SFM448NSDAspwslhE2eZpDkPO0lcF09VCG7X7/YKecCrxQvA9dfd9t+75YZhqokT"
+ "Xr3SnfUzJkNmQZffZPxcRQnzvN6cu0TdMrtGqDlMPK4w3Yo6ql4B2+DpUgFttGJCahxarG1m"
+ "HxHAWnR1Z9Fa0db0a8yG7A5nEdZXzhZeOV4Arl9423/3tmgYcmvL8KJ7TGEEYxd6gcri5J/+"
+ "m8PGRxzh2UZghbIoka3ovWbLNVbWV3Wd7m1Jbi3a1xSVMVAeEUqhYdfO+7n9lIrmRXPWsBS3"
+ "PnqKETUIbtfv/MpJwOvAq0/tiNEogLOxgaswwmag61vvtUALnyJSJ8j48K6JrWjtja25LLrf"
+ "nwulEmZ10IJiUaQgXtyFhKpZphpjMFg/d6MwdhFSWJRKrivLVV+nBYx8Jg74aeV2/U6vCYPX"
+ "gtf1N93237H1uDVVybluptEQHSwulCZaYx3zWCZXrFKab41hg3XBFpOEEkg6K4vLxuPAqCtl"
+ "HRkpaM3K/Y9wqfNM1dKK1M9tkEn/80TxG5ogJ2u/rIxrDfNKers+9xjUp0+vS72uX3QDsH/x"
+ "NodbaUnCy8MIgWgrkjsZK3VdQ8MIP4Gx6Az/GYRJt/xs7OKC5AzNf8Zx6hrS8j6Y4K6LRpAZ"
+ "WHNqX7Xch1Siu7ppUOvqunM6MmzR/0NCxWnZoia2vOde6fS68OrT9bff9t+8pQqICSm+5zCC"
+ "YwhwCqDOPaUPDtNEVXZgFEl4fYS/PDUVA1i0gr9WL3XjBkm8hrqMMTeqUuAwLNky7Req3hEZ"
+ "NSwXRAStSqjFqOJ2fXitex+vKvu/M11/160d6DfRmXQ7HtAOtAdd8oDjwHGgtbCONEhDO4A2"
+ "5u3WpiXjdtA6hy6JM4irjeVH2GzTe0C30yBC30s30h4gAjkAoXfk950+G+bPbyuLL1REuiYp"
+ "VUfCCDgqWh3LDyqI3oSskHq7fsfr3vV4A3gBuP6eWwfroHsjKWD3oM8+QPrDhwHf4MP2us0r"
+ "IrxOO/Lu9D0tg1rbiy2u0OI+9k0dkAPHxx2XPiTa15lpfoiwEoUSvwL0QPLPIPFIaBAhwg66"
+ "DxhVmqm6cobsdv32N7Df8WbwAnD9fbd+ZBtSxwMd+kvgHvJCjJ+Y1Et3TFcLUWFDIobY4n3W"
+ "lNSwJuNyIpCDaahWKStdYpseD13eOGXgLyvTBg1B8Kci1DJMpkbLKCtw5jX0dv3WN7PT8cbw"
+ "AnD9A7dRLyJVVhmPuTg++J5GcwJa3OtoURWshgoJxiROLVXPI1co060kYE7Jx30hoCr4EF8u"
+ "Ua4kvGmbIObvCPGHsUSWIV0sWkd1MVvcqrL1P97YHsebxAvA9UsDYUGfzpwZFUdzKog7hqub"
+ "3QfrI3GXq+x5eZ28V4veK2D3EN+XZNhXk3g8PKyqp8kV66vJlSpZN/i2QpSuSbTaamG/x+V2"
+ "/ZY3ubvxuluO83T9wzcA++duheJToUvu2pgI7t4GnZ3V7O+1YGQQiGGEjZ4oaXlqNlrQFduP"
+ "bXWOUJuGExY9w7FAoy8LHaBDVQtdTU7TijsDWXNIEUZPeFpWc5uRW5Hr9uPt+s1veEf36Y2q"
+ "l03XL7+Z+TWnZZZfVA+OBxwrgTFhyNYqlhgWDFe7aJZzfeQiGC1X60KVNOyI87OjEq1x9FG9"
+ "8Rs/efeCi4rJ6tsg3X71FiI3IdnCH5UK4r9/K3sZbwsvANc/PQplyiOYsxat+rK4hN0ZV3N3"
+ "dYSZgNoKX9/N0Xv1mrt8bXKETHmb3zTRHDmzL7t4iR9g3WbhtEqO+8vt+u/e1i7Gmy+OPF3/"
+ "zA3A/ou3o9EYVM0Y7bLhtaBV6gXS2lS19jWs/wwCYjSf0lTveUSomCE+nTuFNOUuOsSIB6/m"
+ "Pko6regSs/sxMK6ddnKj91HaClYudSZ2dadhzb0gfuPb2KthemvqZdP1z0e/H6XLwgj2wi4e"
+ "FEZke95IUU4euuqwRLVJXeiWloyPJ7TQ/P4D0Ovmg3/s8OFj+zGUePrASE+5gM1twwqxgvgv"
+ "3/aOBd4FvABc/8INgtY0jHjIv3iLVcNL4UnD3v0N7UWva8nfTNWKa2UOMngHQw2ZNVR5C2ab"
+ "xFuvoCYhw+RbMH3SD+/0y3i4aEVyJIHL7fr1b3uXjultFkeern/5BmD/rK0dsMvdVL6ch7YT"
+ "rdMahYYN6nwvlK34yC17eW4k0riJBq+evOSsM3tcpvBA7cMSGxpwKWiHXjynF99GI6Sb1kTB"
+ "BQB3L+owinBNihb6ucXGLYq+tk1nE6Herv/kre7GPL0rePXp+tU3APtHNuFT+OlSg+OermrZ"
+ "QwfRIak2Jif4MEaHxqkm78VmC2UBllHYHnTErF0HoKEU1DZyhIFv049kVzqh5EImwiye4PtE"
+ "W4P3c0NQu/2C3K5f+zb33Mn0ThTHNF3/1k3PZdCakmoTuZbG9Su2EL3kxVZYaBhSv1Aj75U8"
+ "Fj8ctVs8j2gP/qb2Ru3j9Bms81u/UUuNzTMrRluYg9nuTYF6u/6Dt73T1tO7pV42/a3rDcDP"
+ "3rdx1NIYr+Wt2SguoSFfLFE0IKefRhbkqpA+Fbo/EzBLR1WHoJXRFEuEAl6TXmTFskFvOVmN"
+ "YoY2tR+BA/ia6+3t7qn70zuKV5/++vUG4OftWy8KlUcLluGB7D6Uwum8oPXMufeabyOgNy+F"
+ "SGQb3Q/jeLBSaH8Xp1HogPFiG3LY4xg03Wzze9ty0/frWH/tuw1Wn95pvPr0l683AJ9NSmZ+"
+ "K/T/TGwNreJeoKhhUggsU5cJuxRrVTVnTc/vHTNFL9YFUi/rm4qyBABCJC3Ps13egH/yPoDV"
+ "p/cArz595fUG4JcZZKk46sUmml5SlZuNzJD3LSp8btgBKHnLoc8MXAEu2u3o7cROQB2c2ch6"
+ "QEXL6qDNE2EpVs1xK/Cx9wesPr03ePXpz15vAH7FvtkvzhfAGWOjLYNQ7MDixPVRvJGYG4wl"
+ "8LQul3RNr85EtUvem7XiRiIAkEaqVnn3dou0wT3WN7xvYPXpPcOrT39af+tfRWLW6Jwzi7VQ"
+ "opKB2LJ44uQcoVNTD/qjaP1KheOfP/RSyDxBYwuip8H7i8IZ24IGfNP7SZVN7yVeNv2R6w3A"
+ "F+xb75lJOWquhtb5OEWs3FQETjlLPY9Fzw0S6n8UxMInQeeaXfaMrpZjCz19Bb75PQerT+83"
+ "Xn36Q7onfsO+QagIElue3Sdfn7KJ2GycwQoO7Bg49qlIhqzPHA3PKtpD4OnChKlWCfDfPxBU"
+ "2fRBwMum36P75reoOfMKqEhhqo88UKLRaY93wEoP+zSsVcvr9Ey4ml3D8Gp2xYMGfPsHiyqb"
+ "ykc/+tG3/Rle7/Ql+9YvVHHpt4Jq90AtY3mfGfe6ctXbJd0XXApqC8/aq/pftrKVi+gKLayM"
+ "DyhSPH3w8eLpD+5bBmUGjilc4lVRWgbuUpyqS0E5dJviqxXgkz4ESPH04cIrTX8y0rZQqZOn"
+ "GLXKVElYoQCf+iHjKU0farzuTF+9b/cJs4UF+JEfbobuTP8PvRhXFuF66lUAAAAASUVORK5C"
+ "YII=")
+
+#----------------------------------------------------------------------
+RGBCubeImage = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAL4AAAC+CAIAAAAEFiLKAAAAA3NCSVQICAjb4U/gAAAWGUlE"
+ "QVR4nO1df+g0xXn/zD5qWzR/qBQlRZQSSSumIbZUli4y0L6lNAqNaUkiIRpItSVSKi+0Fpsm"
+ "oCmSWtJYIUmbxgZepMGS2hQ0JU0zhA3S8KbBJBClQQzBUg1Jg00wUfemf8zt7jO/du/ue3c7"
+ "ezcfRJ7v3N7s7MxnPvM8z8zeK5RSyMhYH8XUDciYKzJ1MjZEpk7GhsjUydgQmTpDkFJO3YR0"
+ "kakThZRSZ/bEkakThuENgMyeGDJ1Auh4Y5DZE0SmjgvDEmH/h8weDyJnk4OoTkk0oEY3gmr1"
+ "71M3J0WcM3UDkkN1vcTLaAAABDRAKU8Rilr968QtSwyZOj2qN0kslqRZtIWdUcrrCVSrf56g"
+ "ZUkiUwcAqrf1SmO40rQfNfaVpXwTgWr1j/trXKo4dupU73CVJqY6HKV8G4FqdWbn7UsYx0ud"
+ "6taw0gyrDkcp30GgWj24qyamjWOkTvVuiWaENMOqw1HKWwlFrT6y5VYmj+OiTnVa4qWVSLOK"
+ "6nCU8t2EolZ/vZ2GzgHHQp3qzlWVZl3V4SjlaUJRq784UVtngsOnTvXecZ/m5KrDUco7CUWt"
+ "/nyT5s4Hh0yd6p6h6GnYPgl1DEr5XgLV6s82rSB1HCZ1qvs2V5qTLFg+SnkPgWr1JyerJkUc"
+ "GnWqD51UaU6+YPko5X0EqtUd26gsFRwOdaqPbkdptqs6HKX8EIFqdfv2qpwSh0Cd6uObRE/D"
+ "pNmu6nCU8qOEola/u+2K9415U6d6aL08zeqk2YXqcJTy44SiVrfspvp9YK7UqR7eldLsWnU4"
+ "SvkQoajVW3d5k11hftSpPr19n2b/qsNRyocJRa3evPtbbRNzok712DajpxRUh6OUnyZQrd64"
+ "rxueFPOgTvX5/SnN/lWHo5SPEahWv77f226C1KlT1ftWmqlUh6OUnydQra6b4uarIl3qVGen"
+ "UZptbUScHKWsCVSrcromDCFF6lRP7CN62s9GxMlRyrOEolbXTN0QF2lRp3pqt3maqTYiTo5S"
+ "PkEoavW6qRvSIxXqVE+nojSpqQ5HKZ8iFLW6cuqGAClQp3p2ep8mNTd5GKV8mlDU6oppmzEl"
+ "darnp4ye0gzOV0cpnyVQrS6dqgHTUKd6IV2lSV91OEr5PIFqdfH+b71v6lQvpq40c1EdjlK+"
+ "QKBanb/Pm+6POpWeh9LMS3U4SvkigWp13n5utw/qVOdINGg0MB/SzJE6BqXUhKJWevzSk2G3"
+ "1KkukHgJzQKYG2nmtWD5KOU5hKJWL+3uFruiTnWhRDNj0sxXdThKeQGhqNULu6h8+9SpLpV4"
+ "efakmbvqcJTyQkJRq+9ut9ptUqe6TGKBpgHmT5rDUB2OUl5KoFo9u60Kt0Od6kqJlw+KNIek"
+ "OhylvIxAtXrm5FWdlDrVVYemNIeqOhylvJJAtXryJJVsTp3qmsNUmsNWHY5SXkWgWn1ts69v"
+ "Qp3q2kOIno5ZdThKeQ2hqNXZdb+4NnWqUh4DaY5BdThKeS2hqNXjq39lbeo0x0Ga41GdjbE2"
+ "dRbHQZpMnVHsSnXmTppjW7A2wPZV5zBIk1VnFNtUnUMiTVadUWxHdQ6PNFl1RnFS1TlU0mTV"
+ "GcXmqnPYpMmqM4pNVOcYSJNVZxT7SAnOkTRZdUax25TgfEmTqTOKdDciUlgWuZHhIMWNiBRI"
+ "k1VnFGltRKRDmqw6o0hlIyI10mTVGcX0GxFpkiarziim3IhImTRZdUYxzUZE+qTJqjOKfW9E"
+ "zIU0WXVGsb+NiHmRJqvOKNJNCaawLHIjw0GKKcEUSJOpM4q0UoLpkCYvWKNIJSWYGmmOU3XE"
+ "OhdPnxJMkzTHqTprsSGfTR76lBsZDvLZ5CGbGxkO8tnkIZsbGQ7y2eQhmxsZDvLZ5CGbGxkO"
+ "8tnkoW8hUyeOdDciUlgWuZHhIMWNiBRIk1VnFGltRKRDmqw6o0hlIyI10mTVGcX0GxFpkiar"
+ "zijy2eQhmxsZDvLZ5CGbGxkO8tnkIZsbGQ7y2eQhmxsZDtJNCaawLHIjw0GKKcEUSJOpM4q0"
+ "UoLpkCYvWKNIJSWYGmmy6oxi+pRgmqTJqjOKfDZ56FNuZDjIZ5OHbG5kOMhnk4dsbmQ4yGeT"
+ "h2xuZDjIZ5OHbG5kOMhnk4e+hUydONLdiEhhWeRGhoMUNyJSIE1WnVGktRGRDmmy6owilY2I"
+ "1EiTVWcU029EpEmarDqjyGeTh2xuZDjIZ5OHbG5kOMhnk4dsbmQ4yGeTo7ZuNIBGN0KchwwP"
+ "6aYEpyTNjzQAcZ5AUwDQugEgxKvcvjhupJgSnJI039cAxPkCTYGiAAiAoJ8EoPWPAAhxkd8n"
+ "x4m0UoJTkuY7GoC4SGBRoChQEBYAFWgIAFAIehVAWn8fgBCvDvXNcSGVlOCUpPm2BiAuEUAB"
+ "KgBCUWABEKEBUCyNosACgn4aKLR+DoAQl0e76QgwfUpwStI8rQGIywUWLWlQoAAWS6UBCATj"
+ "8fBPBb0aIK2/DUCI10a66sBxpGeT9Tc0APGauNKYBQtLdwdUoAFAyz+XCvSzQKH1NwEIcXW0"
+ "yw4UR3c2WX9VAxBXCzQFzi2wGFAaQgEsChDQUFyBfh6A1t8AIMQvDfXdYeGIzibrL2kA4g0C"
+ "6BzhAkAvMI5r7ChNoLz7eiHoFwDS+isAhCij3XdAOIqzyfqLGoAobaUBel3hBgD4SuOUM6Ov"
+ "hwT9MgCtvwRACDnQjQeAAz+brD+nAQjJQ+5eKtrhN74LM7pyS2nYgkXEjI52nQL9CkBafwGA"
+ "EKeGenPOONizyfozGoA4xaIn4whzA+hj79419so7AwCoX7Cccrt+Qb8KQOvPARDihmiHzhbp"
+ "bkRsTppHNABxg0BTgIqlQiwdYeYRd0rTu8axcltpQPFy90aCfgMotH4UgBA3DvftvJDiRsTm"
+ "pHlYAxA3spA74NLCir2XrrEnMH1wjojS2C7z4I0E/RZQaP0pAELcNNrJs0BaGxGbk+aMBiBu"
+ "CobczKeB7RHHYvKR4NyL0l3fmd+IK9BbAGj9SQBC3LxGpyeJVDYiNifNgxqAuLkNue2YuTVg"
+ "7yeQVR7I/q0WnDtKY/nOiLVE0NsB0voTAIS4bbi3U8b0GxGbk+bDGoC4rVWaaMzsx96h8o2D"
+ "c+eOQ9F7fyNB7wKg9ccACHH7GgOQDGZ5NlnfrwGI273knjPvnZAbTADglHOjDbnhBedASGD4"
+ "HYMtCd7RhPG/D5DWDwAQ4nSsz9PEzM4m6w9oAOK0wIIpDWDFxo5OdCF3HzzbAtOvXMY1iQfn"
+ "rsB0KxciLeEXcM2zWiLoDgBafxCAEHeuMgopYDZnk/X7NQBxlx1yA3bszaZ1rxORmLzP/nWO"
+ "yGrB+XpROpeuyAVFgQUJ+iOg0Ppe088k7h4YhRQwg7PJ+j0agHifmfrnggoAy1HvfNumQMEW"
+ "FDDxWP7pG+zrA9G7+dRxjYtWaRxdMd9qPCUzuhUo7wwYH1+cd5fRJ63fB4DEvWMDMhnSTQku"
+ "AH2nBiDe36ZeePRrprLr5GJECQJftwUAdm2Wb8Rj71WCf6ZkjoCtENILuhsotL4LAIkPrjo8"
+ "e0SKKcEFoO/QAMRfEhqA2FznYXanGb3rENn6NobruwwojVMtP8oTz/65rRrdkOeRfLhVgj4A"
+ "kNanAZB4YK2R2jXSSgkuAH27BiDub3u/m5R+FL1cI1rfNhxdjwXPsSi9u8z1ncdi71i1a7XK"
+ "rlbQ/QC0/gMAJD627pDtCKmkBBeAfpcGIP6G0ADnOuk1rgS2JETLR4Pn4Wq7y1ao1lKaWPA/"
+ "8PXRao0f/WGAtL4VAIlPDI7SPjB9SnAB6Js1APEgUxrAimm5EwpPafqNJ9t3GQ+eg2F8XGkC"
+ "1XKlWTH4755ulZifh/RGgR4EoPU7AZD45LrDt0VMfDZZv0UDEA8RFp7SBMLsgSiaTVln6o9m"
+ "5yyP26t/3OOOJf3s5lnbEaFmO/WEQ/pOgc4AhdY3ASDxKXeQ9oLJzibrGzUA8XDbO+Gpxqbs"
+ "cmb7W9+OErRGrNwVMDsIXzE475QgXL6L+gPdIuhhAFr/DgASj64+iFvBBGeT9W9qAOJfWp9m"
+ "4cXMnRGLckeD5+GYPFzPXOsX9AhAWt8AgMRnx4dwS9jr2WR9SgMQn7VD7t6liJzKi87g4Km/"
+ "uBIcdP2CPgOQ1qcAkPjC2DBuAXs6m6yv0wCEYo6wE446HvFAlBsLnp3yo6xfkAKgtQRA4vGN"
+ "KLEqdn42WZcagHicsGDRUywKtXxDVr6t4Pk46hf0RaDQugRA4iujY7oZdqg6+g0agPhy+6gj"
+ "wS3b4g6X+7G3F9y60a83U4fK/fPL3Uqx6/q95MKynkiUPhpSFMCCBH0ZgNa/CIDE19cd6FHs"
+ "RHX01RqA+LofcgeDT77FPRyTrxbcBhL/bKb69fe7HHb9MSVwg/9IFB0767N2cuFE9Qv6KlBo"
+ "fTUAEt/E9rBl1dGv0QDEU+2jxmJjf+PGFRg7Jg+4nKtMUK9+f4KOurSuUvLgn9c/3AB27BCh"
+ "+v0H6ZwY9wGHfWe/fuNEPwVA69cCIPGtdQc9iK2pjr5cAxDfYiE3sJyyFIktY+V+7Bp6U643"
+ "/HqcwzqjN+p8jlgDovVEyp3kgn/scMUbjTdgjZ4U9DRAWl8OgMRzwfGVUiqlgh852ILq6Es0"
+ "APFcu0kU3nD25oc/76NvxI3GtLZH6ShBtAFe/YOv5IWUbHgPvPNhI0/q1x+L0mPvHAa2wIIN"
+ "cN4t/G+AtL4EAInvrUuADqtSpyMjVx19kQYgvtdSIeBRtg9geY7+tPDy/U7ICm/+uS4nv5E9"
+ "QQMN6OoJnfixGhC8kf2kQzcafNLYg4SV5oRP6napoO8ApPVFAEj8sBvlFfmAtVTHsMeojj5f"
+ "AxA/bEPuXmBs+rse69i0CPyMTWDeuB5xfyOvAYHg1txoteDZfSMn/qTujQae1G5JwLcdvFH/"
+ "dvPokzo3CjypoP8DCq3PB0DiJQCAllKssmats2BpSCG11gDES+ZRz0UBgE1TAlD0RncSzynv"
+ "j4eyr4OWua9AeWsgVL9f7tTfVxgrt+vvDKd+/0ZOPf2VTjmLjHg93doULo/X7zjXndFJjlN/"
+ "uLwL4w1pfgLQWBlr+joaQgj8uHDLqV3GouXF8n8LWMZyirSXGaN3+rgBtni1iVfA8kZ5eec+"
+ "F+wymPgOyzMSvNx8zQRNYPU45c64dvVYvFmZQN2i41zgjLT/UodVztUdlngbKQqmIZx8xI/P"
+ "WYs32MBNhgbEAq+cC2pPkvvt4AmSbsXtoiHjFS2Y0YkT7GDYPwRDZqQLLFoHq/OFrXJumE/b"
+ "zi2YnhOsdcHc2ve0zAA3rG2uwZra2GtNFxA0hdUGfzEie303t+57pn0oYkbTdoi/g+EfsCen"
+ "P5eNVI/WANZxcjamzpI9LyulZHW9u4L2C7C94loeHIKOWz+ZnF6IHUiIhXKjDlDA7VjhLLqp"
+ "x2lbd0GQ+rzNHfV5uSUA6F2W2NvNQ8E/6/muPztWWVmMZSPVP9VmPKWUtuSs5O6sQx1h/dXF"
+ "XLL67WVHBzw4NmbhN6Qcxy0eIAwPVS/1o+d17KFyhmSNoYrRbngLkwuDd6rQoVcvmbw8Etub"
+ "JjVOfzqjUKAAiNSZmo9jYHRXocOK+Z9RyOrtQDvqi3bUzaA2zFh+Gitvv25cVMtoO46Xo10u"
+ "0a6STasZDbtgWd4a3SqJdlHgTe2/RWhCBm+qadKiM0w7fcNuatc5vdHW4zYVaIr+iZxe6jvZ"
+ "aaHdt6yT1d/1pDkhNlqwQlD1GQCyeudS58NrkOdIxrJwlkcZTL4FYxbb5ey8bMt1dXxYr6kx"
+ "J9dZ71bxgle6IHhlpM1d/qxrvCn3I1ayKlQf2RpjOmxNdRzI6ve8SUkBAeD6EZhejjB4AjAw"
+ "7bgSdCIHYioVlwowSeg1z5eK7u6OyJE36WOa4clYWHGZXHUyNiK9S0P91fZJY7Ar6hjI6g/Z"
+ "WLLFIqzqsJenYVVn8u6MUGCobCoEhiq2tjL9t2jnDxXYHIiUL3wjRjtuOItsfG7Y/anu3RVp"
+ "DHZLHQNZ3QmEpt3wUC2CUuEpAefZNocq1FRrCIPUJ8uh4VNiwKGJSq8zc+w2x7zJBam7d0sa"
+ "g31Qx0BW7wkPai/vITEPTjtfzDnPwmMWGqqojAVp1349MGYhAbBWSc5Cu4XBRdZdhvymwp4w"
+ "7fL0p/sgjcHW3ORRqPpuALK6Z+m+FZHdxK7EGMTzql46NeBuEwB34ybmJlvudtz5LZysP69n"
+ "LS8Ytks76JibtN7ABWipSaT+eH+M6bA/1XEgq/viYh4JbpvItFsElSCmEEHXNbg4rp8sCLuu"
+ "3ioZyxoElsvQKsmWS3X7BKQxmIw6BrJ6AIi5QRRW9YHgwhmqfszaC+BlTfyIyU/8uP5QaCUK"
+ "Lz0hVg0sPdyhia2SraFum4w0BhNTx0BWfwv4YzYoFQNDFZYKrBfchiPwsbyiI2M+9WNZO8eh"
+ "GcgaNKRumZg0BklQx0BWf9+vTQOqzsfMCdFXGrPBDJAzVK6MwVaIYNbAy/cM54LXSRaotyZB"
+ "GoP9ucmjUPUtAGT1D0uvMPybfo7DGH9hZXlB527baWsnPR1zcp0XeP0LfC94wIjlgp2HWni5"
+ "4DcnxJgOCamOA1k9Eglu7bRhLK9jrUfxvGLAoYG1ETbk0MQ0I5QK8r1+30vzHZo3pkgag3Sp"
+ "YyCrx4BYXieSAo7l6AZSwLFkHUIJntX3SZwEj5UBiueCzdr0a+mSxiB16hjI6t8ibpAjFcx7"
+ "iA3hgD/kyNhwLnhke8T3h3wZi+SCr0udNAbzoI6BrGpb1REaM08hYltaASVwFGI0F8wuWCWv"
+ "M5YsUNfOgzQGc6KOgazOhtN3vusTyOuPDSoGEjxrJQvieyaOc2Mye6+fE2kMEoqwVoSql/+q"
+ "r6y+BjIxSysM/hk/ft6bKHBUuelOASPyUunqv0Lq734gEMQ1/Ul4ddX8GNNhftTpoOrXAZDV"
+ "fwEARl+R5PF2qDxwLtNc32pV7KcFnXcOnQu6ZIEx2pPw6soZk8ZgxtQxUPWVAGT1zHJaO3md"
+ "LusTUwgKyVWMf7Ef8w7+cmVExtRlsyeNweypY6DqKwDI6n+W5LDevY0rAbV+jNEeXyGC9HJ+"
+ "vGL4ZSi2SqqLD4Q0BgdCHQNVXwpAVv/brkHtoMJeehx6BX9Gw3FoOnenM4LlLqtaL/jCgyKN"
+ "wUFRx0DVFxpDVi+2fnQb8vhv2TkCE3wBBbBXQ0fVorsf6rwDZEyHA6ROB1X/FABZveIO8JIu"
+ "nr9spGLo1S3mR/s8Y56N0odMGoNDpo6Bqs8BICuyHRq4u6qdYT5yFyzHj46+5aleOXzSGBw+"
+ "dQxU/QoAWV0Q8qMx8pan6+iE/SH1g2MhjcGxUMdA1T8AIKuLAdipoI4oYJke28uOv5Crnj8u"
+ "0hgcF3UMVP1dY8jqZ0Aw/3KilY9mwVH0x5pA6tljZEyHY6ROB1U/C0BWV4TzOl4KuHdonjlq"
+ "0hgcNXUMVP0MAFn9nKsrQYfmyUyaJTJ1llD1kwBk9Xrm2YC7Qeo/M2ksZOpYUPUTAGR1LYBu"
+ "wVJnM2kCyNQJQNX/MXUTZoBi6gZkzBWZOhkbIlMnY0Nk6mRsiP8H0trOAD1A8ycAAAAASUVO"
+ "RK5CYII=")
+
+
+def rad2deg(x):
+ """
+ Transforms radians into degrees.
+
+ :param `x`: a float representing an angle in radians.
+ """
+
+ return 180.0*x/pi
+
+
+def deg2rad(x):
+ """
+ Transforms degrees into radians.
+
+ :param `x`: a float representing an angle in degrees.
+ """
+
+ return x*pi/180.0
+
+
+def toscale(x):
+ """
+ Normalize a value as a function of the radius.
+
+ :param `x`: a float value to normalize
+ """
+
+ return x*RADIUS/255.0
+
+
+def scaletomax(x):
+ """
+ Normalize a value as a function of the radius.
+
+ :param `x`: a float value to normalize
+ """
+
+ return x*255.0/RADIUS
+
+
+def rgb2html(colour):
+ """
+ Transforms a RGB triplet into an html hex string.
+
+ :param `colour`: a tuple of red, green, blue integers.
+ """
+
+ hexColour = "#%02x%02x%02x"%(colour.r, colour.g, colour.b)
+ return hexColour.upper()
+
+
+def Slope(pt1, pt2):
+ """
+ Calculates the slope of the line connecting 2 points.
+
+ :param `pt1`: an instance of :class:`Point`;
+ :param `pt2`: another instance of :class:`Point`.
+ """
+
+ y = float(pt2.y - pt1.y)
+ x = float(pt2.x - pt1.x)
+
+ if x:
+ return y/x
+ else:
+ return None
+
+
+def Intersection(line1, line2):
+ """
+ Calculates the intersection point between 2 lines.
+
+ :param `line1`: an instance of :class:`LineDescription`;
+ :param `line2`: another instance of :class:`LineDescription`.
+ """
+
+ if line1.slope == line2.slope:
+
+ # Parallel lines, no intersection
+ return wx.Point(0, 0)
+
+ elif line1.slope is None:
+
+ # First Line is vertical, eqn is x=0
+ # Put x = 0 in second line eqn to get y
+ x = line1.x
+ y = line2.slope*x + line2.c
+
+ elif line2.slope is None:
+
+ # second line is vertical Equation of line is x=0
+ # Put x = 0 in first line eqn to get y
+ x = line2.x
+ y = line1.slope*line2.x + line1.c
+
+ else:
+
+ y = ((line1.c*line2.slope) - (line2.c*line1.slope))/(line2.slope - line1.slope)
+ x = (y - line1.c)/line1.slope
+
+
+ return wx.Point(int(x), int(y))
+
+
+def FindC(line):
+ """ Internal function. """
+
+ if line.slope is None:
+ c = line.y
+ else:
+ c = line.y - line.slope*line.x
+
+ return c
+
+
+def PointOnLine(pt1, pt2, length, maxLen):
+ """ Internal function. """
+
+ a = float(length)
+
+ if pt2.x != pt1.x:
+
+ m = float((pt2.y - pt1.y))/(pt2.x - pt1.x)
+ m2 = m*m
+ a2 = a*a
+ c = pt1.y - m*pt1.x
+ c2 = c*c
+
+ A = 1.0
+
+ x = pt1.x
+
+ B = 2.0 * pt1.x
+
+ x *= x
+ C = x - a2/(m2 + 1)
+
+ x = (B + sqrt(B*B - (4.0*A*C)))/(2.0*A)
+ y = m*x + c
+ pt = wx.Point(int(x), int(y))
+
+ if Distance(pt, pt1) > maxLen or Distance(pt, pt2) > maxLen:
+
+ x = (B - sqrt(B*B - (4.0*A*C)))/(2.0*A)
+ y = m*x + c
+ pt = wx.Point(int(x), int(y))
+
+ else:
+
+ a2 = a*a
+ y = sqrt(a2)
+ x = 0.0
+ pt = wx.Point(int(x), int(y))
+ pt.x += pt1.x
+ pt.y += pt1.y
+
+ if Distance(pt, pt1) > maxLen or Distance(pt, pt2) > maxLen:
+
+ y = -1.0*y
+ pt = wx.Point(int(x), int(y))
+ pt.x += pt1.x
+ pt.y += pt1.y
+
+ return pt
+
+
+def Distance(pt1, pt2):
+ """
+ Returns the distance between 2 points.
+
+ :param `pt1`: an instance of :class:`Point`;
+ :param `pt2`: another instance of :class:`Point`.
+ """
+
+ distance = sqrt((pt1.x - pt2.x)**2.0 + (pt1.y - pt2.y)**2.0)
+ return int(distance)
+
+
+def AngleFromPoint(pt, center):
+ """
+ Returns the angle between the x-axis and the line connecting the center and
+ the point `pt`.
+
+ :param `pt`: an instance of :class:`Point`;
+ :param `center`: a float value representing the center.
+ """
+
+ y = -1*(pt.y - center.y)
+ x = pt.x - center.x
+ if x == 0 and y == 0:
+
+ return 0.0
+
+ else:
+
+ return atan2(y, x)
+
+
+def PtFromAngle(angle, sat, center):
+ """
+ Given the angle with respect to the x-axis, returns the point based on
+ the saturation value.
+
+ :param `angle`: a float representing an angle;
+ :param `sat`: a float representing the colour saturation value;
+ :param `center`: a float value representing the center.
+ """
+
+ angle = deg2rad(angle)
+ sat = toscale(sat)
+
+ x = sat*cos(angle)
+ y = sat*sin(angle)
+
+ pt = wx.Point(int(x), -int(y))
+ pt.x += center.x
+ pt.y += center.y
+
+ return pt
+
+
+def RestoreOldDC(dc, oldPen, oldBrush, oldMode):
+ """
+ Restores the old settings for a :class:`DC`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `oldPen`: an instance of :class:`Pen`;
+ :param `oldBrush`: an instance of :class:`Brush`;
+ :param `oldMode`: the :class:`DC` drawing mode bit.
+ """
+
+ dc.SetPen(oldPen)
+ dc.SetBrush(oldBrush)
+ dc.SetLogicalFunction(oldMode)
+
+
+def DrawCheckerBoard(dc, rect, checkColour, box=5):
+ """
+ Draws a checkerboard on a :class:`DC`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the client rectangle on which to draw the checkerboard;
+ :param `checkColour`: the colour used for the dark checkerboards;
+ :param `box`: the checkerboards box sizes.
+
+ :note: Used for the Alpha channel control and the colour panels.
+ """
+
+ y = rect.y
+ checkPen = wx.Pen(checkColour)
+ checkBrush = wx.Brush(checkColour)
+
+ dc.SetPen(checkPen)
+ dc.SetBrush(checkBrush)
+ dc.SetClippingRect(rect)
+
+ while y < rect.height:
+ x = box*((y/box)%2) + 2
+ while x < rect.width:
+ dc.DrawRectangle(x, y, box, box)
+ x += box*2
+ y += box
+
+
+
+class Colour(wx.Colour):
+ """
+ This is a subclass of :class:`Colour`, which adds Hue, Saturation and Brightness
+ capability to the base class. It contains also methods to convert RGB triplets
+ into HSB triplets and vice-versa.
+ """
+
+ def __init__(self, colour):
+ """
+ Default class constructor.
+
+ :param `colour`: a standard :class:`Colour`.
+ """
+
+ wx.Colour.__init__(self)
+
+ self.r = colour.Red()
+ self.g = colour.Green()
+ self.b = colour.Blue()
+ self._alpha = colour.Alpha()
+
+ self.ToHSV()
+
+
+ def ToRGB(self):
+ """ Converts a HSV triplet into a RGB triplet. """
+
+ maxVal = self.v
+ delta = (maxVal*self.s)/255.0
+ minVal = maxVal - delta
+
+ hue = float(self.h)
+
+ if self.h > 300 or self.h <= 60:
+
+ self.r = maxVal
+
+ if self.h > 300:
+
+ self.g = int(minVal)
+ hue = (hue - 360.0)/60.0
+ self.b = int(-(hue*delta - minVal))
+
+ else:
+
+ self.b = int(minVal)
+ hue = hue/60.0
+ self.g = int(hue*delta + minVal)
+
+ elif self.h > 60 and self.h < 180:
+
+ self.g = int(maxVal)
+
+ if self.h < 120:
+
+ self.b = int(minVal)
+ hue = (hue/60.0 - 2.0)*delta
+ self.r = int(minVal - hue)
+
+ else:
+
+ self.r = int(minVal)
+ hue = (hue/60.0 - 2.0)*delta
+ self.b = int(minVal + hue)
+
+
+ else:
+
+ self.b = int(maxVal)
+
+ if self.h < 240:
+
+ self.r = int(minVal)
+ hue = (hue/60.0 - 4.0)*delta
+ self.g = int(minVal - hue)
+
+ else:
+
+ self.g = int(minVal)
+ hue = (hue/60.0 - 4.0)*delta
+ self.r = int(minVal + hue)
+
+
+ def ToHSV(self):
+ """ Converts a RGB triplet into a HSV triplet. """
+
+ minVal = float(min(self.r, min(self.g, self.b)))
+ maxVal = float(max(self.r, max(self.g, self.b)))
+ delta = maxVal - minVal
+
+ self.v = int(maxVal)
+
+ if abs(delta) < 1e-6:
+
+ self.h = self.s = 0
+
+ else:
+
+ temp = delta/maxVal
+ self.s = int(temp*255.0)
+
+ if self.r == int(maxVal):
+
+ temp = float(self.g-self.b)/delta
+
+ elif self.g == int(maxVal):
+
+ temp = 2.0 + (float(self.b-self.r)/delta)
+
+ else:
+
+ temp = 4.0 + (float(self.r-self.g)/delta)
+
+ temp *= 60
+ if temp < 0:
+
+ temp += 360
+
+ elif temp >= 360.0:
+
+ temp = 0
+
+ self.h = int(temp)
+
+
+ def GetPyColour(self):
+ """ Returns the wxPython :class:`Colour` associated with this instance. """
+
+ return wx.Colour(self.r, self.g, self.b, self._alpha)
+
+
+
+class LineDescription(object):
+ """ Simple class to store description and constants for a line in 2D space. """
+
+ def __init__(self, x=0, y=0, slope=None, c=None):
+ """
+ Default class constructor.
+
+ Used internally. Do not call it in your code!
+
+ :param `x`: the x coordinate of the first point;
+ :param `y`: the y coordinate of the first point;
+ :param `slope`: the line's slope;
+ :param `c`: a floating point constant.
+ """
+
+ self.x = x
+ self.y = y
+ self.slope = slope
+ self.c = c
+
+
+class BasePyControl(wx.PyControl):
+ """
+ Base class used to hold common code for the HSB colour wheel and the RGB
+ colour cube.
+ """
+
+ def __init__(self, parent, bitmap=None):
+ """
+ Default class constructor.
+ Used internally. Do not call it in your code!
+
+ :param `parent`: the control parent;
+ :param `bitmap`: the background bitmap for this custom control.
+ """
+
+ wx.PyControl.__init__(self, parent, style=wx.NO_BORDER)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ self._bitmap = bitmap
+ mask = wx.Mask(self._bitmap, wx.Colour(192, 192, 192))
+ self._bitmap.SetMask(mask)
+
+ self._mainDialog = wx.GetTopLevelParent(self)
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` for :class:`BasePyControl`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+ dc.SetBackground(wx.Brush(self.GetParent().GetBackgroundColour()))
+
+ dc.Clear()
+ dc.DrawBitmap(self._bitmap, 0, 0, True)
+
+ if self._mainDialog._initOver:
+ self.DrawMarkers(dc)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` for :class:`BasePyControl`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def DrawMarkers(self, dc=None):
+ """
+ Draws the markers on top of the background bitmap.
+
+ :param `dc`: an instance of :class:`DC`.
+
+ :note: This method must be overridden in derived classes.
+ """
+
+ pass
+
+
+ def DrawLines(self, dc):
+ """
+ Draws the lines connecting the markers on top of the background bitmap.
+
+ :param `dc`: an instance of :class:`DC`.
+
+ :note: This method must be overridden in derived classes.
+ """
+
+ pass
+
+
+ def AcceptsFocusFromKeyboard(self):
+ """
+ Can this window be given focus by keyboard navigation? If not, the
+ only way to give it focus (provided it accepts it at all) is to click
+ it.
+
+ :note: This method always returns ``False`` as we do not accept focus from
+ the keyboard.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return False
+
+
+ def AcceptsFocus(self):
+ """
+ Can this window be given focus by mouse click?
+
+ :note: This method always returns ``False`` as we do not accept focus from
+ mouse click.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return False
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` for :class:`BasePyControl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+
+ :note: This method must be overridden in derived classes.
+ """
+
+ pass
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` for :class:`BasePyControl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+
+ :note: This method must be overridden in derived classes.
+ """
+
+ pass
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` for :class:`BasePyControl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+
+ :note: This method must be overridden in derived classes.
+ """
+
+ pass
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` for :class:`BasePyControl`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Refresh()
+
+
+ def DoGetBestSize(self):
+ """
+ Overridden base class virtual. Determines the best size of the
+ control based on the bitmap size.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return wx.Size(self._bitmap.GetWidth(), self._bitmap.GetHeight())
+
+
+
+class RGBCube(BasePyControl):
+ """
+ Implements the drawing, mouse handling and sizing routines for the RGB
+ cube colour.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+ Used internally. Do not call it in your code!
+
+ :param `parent`: the control parent window.
+ """
+
+ BasePyControl.__init__(self, parent, bitmap=RGBCubeImage.GetBitmap())
+ self._index = -1
+
+
+ def DrawMarkers(self, dc=None):
+ """
+ Draws the markers on top of the background bitmap.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ if dc is None:
+ dc = wx.ClientDC(self)
+
+ oldPen, oldBrush, oldMode = dc.GetPen(), dc.GetBrush(), dc.GetLogicalFunction()
+ dc.SetPen(wx.WHITE_PEN)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetLogicalFunction(wx.XOR)
+
+ rects = []
+ blueLen = self._mainDialog._blueLen
+ greenLen = self._mainDialog._greenLen
+ redLen = self._mainDialog._redLen
+ colour = self._mainDialog._colour
+
+ pt = [wx.Point() for i in xrange(3)]
+ pt[0] = PointOnLine(Vertex, Top, (colour.r*redLen)/255, redLen)
+ pt[1] = PointOnLine(Vertex, Left, (colour.g*greenLen)/255, greenLen)
+ pt[2] = PointOnLine(Vertex, Right, (colour.b*blueLen)/255, blueLen)
+
+ for i in xrange(3):
+ rect = wx.Rect(pt[i].x - RECT_WIDTH, pt[i].y - RECT_WIDTH, 2*RECT_WIDTH, 2*RECT_WIDTH)
+ rects.append(rect)
+ dc.DrawRectangleRect(rect)
+
+ self.DrawLines(dc)
+ RestoreOldDC(dc, oldPen, oldBrush, oldMode)
+
+ self._rects = rects
+
+
+ def DrawLines(self, dc):
+ """
+ Draws the lines connecting the markers on top of the background bitmap.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ cuboid = self._mainDialog._cuboid
+
+ dc.DrawLinePoint(cuboid[1], cuboid[2])
+ dc.DrawLinePoint(cuboid[2], cuboid[3])
+ dc.DrawLinePoint(cuboid[3], cuboid[4])
+ dc.DrawLinePoint(cuboid[4], cuboid[5])
+ dc.DrawLinePoint(cuboid[5], cuboid[2])
+
+ dc.DrawLinePoint(cuboid[5], cuboid[6])
+ dc.DrawLinePoint(cuboid[6], cuboid[7])
+ dc.DrawLinePoint(cuboid[7], cuboid[4])
+
+ dc.DrawLinePoint(cuboid[1], cuboid[6])
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` for :class:`RGBCube`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ point = wx.Point(event.GetX(), event.GetY())
+ self._mouseIn = False
+
+ if self._rects[RED].Contains(point):
+ self.CaptureMouse()
+ self._mouseIn = True
+ self._index = RED
+
+ elif self._rects[GREEN].Contains(point):
+ self.CaptureMouse()
+ self._mouseIn = True
+ self._index = GREEN
+
+ elif self._rects[BLUE].Contains(point):
+ self.CaptureMouse()
+ self._mouseIn = True
+ self._index = BLUE
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` for :class:`RGBCube`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.GetCapture():
+ self.ReleaseMouse()
+ self._mouseIn = False
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` for :class:`RGBCube`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ point = wx.Point(event.GetX(), event.GetY())
+
+ if not (self.GetCapture() and self._mouseIn):
+ event.Skip()
+ return
+
+ bChange = False
+ mainDialog = self._mainDialog
+ colour = mainDialog._colour
+ redLen, greenLen, blueLen = mainDialog._redLen, mainDialog._greenLen, mainDialog._blueLen
+
+ dc = wx.ClientDC(self)
+ self.DrawMarkers(dc)
+
+ if self._index == RED:
+
+ if point.y > Vertex.y:
+ point.y = Vertex.y
+
+ point.x = Vertex.x
+ val = Distance(point, Vertex)
+ if val > redLen:
+ val = redLen
+
+ val = (float(val)/redLen)*255
+ colour.r = int(val)
+
+ pt = PointOnLine(Vertex, Top, (colour.r*redLen)/255, redLen)
+ self._rects[RED] = wx.Rect(pt.x - RECT_WIDTH, pt.y - RECT_WIDTH,
+ 2*RECT_WIDTH, 2*RECT_WIDTH)
+
+ bChange = True
+
+ elif self._index == GREEN:
+
+ if point.x > Vertex.x:
+ point.x = Vertex.x
+
+ point.y = self._rects[GREEN].GetTop() + RECT_WIDTH
+ val = Distance(point, Vertex)
+ if val > greenLen:
+ val = greenLen
+
+ val = (float(val)/greenLen)*255
+ colour.g = int(val)
+
+ pt = PointOnLine(Vertex, Left, (colour.g*greenLen)/255, greenLen)
+ self._rects[GREEN] = wx.Rect(pt.x - RECT_WIDTH, pt.y - RECT_WIDTH,
+ 2*RECT_WIDTH, 2*RECT_WIDTH)
+
+ bChange = True
+
+ elif self._index == BLUE:
+
+ if point.x < Vertex.x:
+ point.x = Vertex.x
+
+ point.y = self._rects[BLUE].GetTop() + RECT_WIDTH
+ val = Distance(point, Vertex)
+ if val > blueLen:
+ val = blueLen
+
+ val = (float(val)/blueLen)*255
+ colour.b = int(val)
+
+ pt = PointOnLine(Vertex, Right, (colour.b*blueLen)/255, blueLen)
+ self._rects[BLUE] = wx.Rect(pt.x - RECT_WIDTH, pt.y - RECT_WIDTH,
+ 2*RECT_WIDTH, 2*RECT_WIDTH)
+
+ bChange = True
+
+ if bChange:
+
+ mainDialog.CalcCuboid()
+ self.DrawMarkers(dc)
+
+ colour.ToHSV()
+ mainDialog.SetSpinVals()
+ mainDialog.CalcRects()
+
+ mainDialog.DrawHSB()
+ mainDialog.DrawBright()
+ mainDialog.DrawAlpha()
+
+
+class HSVWheel(BasePyControl):
+ """
+ Implements the drawing, mouse handling and sizing routines for the HSV
+ colour wheel.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+ Used internally. Do not call it in your code!
+
+ :param `parent`: the control parent window.
+ """
+
+ BasePyControl.__init__(self, parent, bitmap=HSVWheelImage.GetBitmap())
+ self._mouseIn = False
+
+
+ def DrawMarkers(self, dc=None):
+ """
+ Draws the markers on top of the background bitmap.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ if dc is None:
+ dc = wx.ClientDC(self)
+
+ oldPen, oldBrush, oldMode = dc.GetPen(), dc.GetBrush(), dc.GetLogicalFunction()
+ dc.SetPen(wx.WHITE_PEN)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetLogicalFunction(wx.XOR)
+
+ dc.DrawRectangleRect(self._mainDialog._currentRect)
+ RestoreOldDC(dc, oldPen, oldBrush, oldMode)
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` for :class:`HSVWheel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ point = wx.Point(event.GetX(), event.GetY())
+ self._mouseIn = False
+
+ if self.InCircle(point):
+ self._mouseIn = True
+
+ if self._mouseIn:
+ self.CaptureMouse()
+ self.TrackPoint(point)
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` for :class:`HSVWheel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.GetCapture():
+ self.ReleaseMouse()
+ self._mouseIn = False
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` for :class:`HSVWheel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ point = wx.Point(event.GetX(), event.GetY())
+
+ if self.GetCapture() and self._mouseIn:
+ self.TrackPoint(point)
+
+
+ def InCircle(self, pt):
+ """
+ Returns whether a point is inside the HSV wheel or not.
+
+ :param `pt`: an instance of :class:`Point`.
+ """
+
+ return Distance(pt, self._mainDialog._centre) <= RADIUS
+
+
+ def TrackPoint(self, pt):
+ """
+ Track a mouse event inside the HSV colour wheel.
+
+ :param `pt`: an instance of :class:`Point`.
+ """
+
+ if not self._mouseIn:
+ return
+
+ dc = wx.ClientDC(self)
+ self.DrawMarkers(dc)
+ mainDialog = self._mainDialog
+ colour = mainDialog._colour
+
+ colour.h = int(rad2deg(AngleFromPoint(pt, mainDialog._centre)))
+ if colour.h < 0:
+ colour.h += 360
+
+ colour.s = int(scaletomax(Distance(pt, mainDialog._centre)))
+ if colour.s > 255:
+ colour.s = 255
+
+ mainDialog.CalcRects()
+ self.DrawMarkers(dc)
+ colour.ToRGB()
+ mainDialog.SetSpinVals()
+
+ mainDialog.CalcCuboid()
+ mainDialog.DrawRGB()
+ mainDialog.DrawBright()
+ mainDialog.DrawAlpha()
+
+
+class BaseLineCtrl(wx.PyControl):
+ """
+ Base class used to hold common code for the Alpha channel control and the
+ brightness palette control.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+ Used internally. Do not call it in your code!
+
+ :param `parent`: the control parent window.
+ """
+
+ wx.PyControl.__init__(self, parent, size=(20, 200), style=wx.NO_BORDER)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ self._mainDialog = wx.GetTopLevelParent(self)
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` for :class:`BaseLineCtrl`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` for :class:`BaseLineCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ point = wx.Point(event.GetX(), event.GetY())
+ theRect = self.GetClientRect()
+
+ if not theRect.Contains(point):
+ event.Skip()
+ return
+
+ self.CaptureMouse()
+ self.TrackPoint(point)
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` for :class:`BaseLineCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.GetCapture():
+ self.ReleaseMouse()
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` for :class:`BaseLineCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ point = wx.Point(event.GetX(), event.GetY())
+
+ if self.GetCapture():
+ self.TrackPoint(point)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` for :class:`BaseLineCtrl`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Refresh()
+
+
+ def DoGetBestSize(self):
+ """
+ Overridden base class virtual. Determines the best size of the control.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return wx.Size(24, 208)
+
+
+ def BuildRect(self):
+ """ Internal method. """
+
+ brightRect = wx.Rect(*self.GetClientRect())
+ brightRect.x += 2
+ brightRect.y += 6
+ brightRect.width -= 4
+ brightRect.height -= 8
+
+ return brightRect
+
+
+ def AcceptsFocusFromKeyboard(self):
+ """
+ Can this window be given focus by keyboard navigation? If not, the
+ only way to give it focus (provided it accepts it at all) is to click
+ it.
+
+ :note: This method always returns ``False`` as we do not accept focus from
+ the keyboard.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return False
+
+
+ def AcceptsFocus(self):
+ """
+ Can this window be given focus by mouse click?
+
+ :note: This method always returns ``False`` as we do not accept focus from
+ mouse click.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return False
+
+
+
+class BrightCtrl(BaseLineCtrl):
+ """
+ Implements the drawing, mouse handling and sizing routines for the brightness
+ palette control.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+ Used internally. Do not call it in your code!
+
+ :param `parent`: the control parent window.
+ """
+
+ BaseLineCtrl.__init__(self, parent)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` for :class:`BrightCtrl`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+ dc.SetBackground(wx.Brush(self.GetParent().GetBackgroundColour()))
+ dc.Clear()
+
+ colour = self._mainDialog._colour.GetPyColour()
+ brightRect = self.BuildRect()
+
+ target_red = colour.Red()
+ target_green = colour.Green()
+ target_blue = colour.Blue()
+
+ h, s, v = colorsys.rgb_to_hsv(target_red / 255.0, target_green / 255.0,
+ target_blue / 255.0)
+ v = 1.0
+ vstep = 1.0/(brightRect.height-1)
+
+ for y_pos in range(brightRect.y, brightRect.height+brightRect.y):
+ r, g, b = [c * 255.0 for c in colorsys.hsv_to_rgb(h, s, v)]
+ colour = wx.Colour(int(r), int(g), int(b))
+ dc.SetPen(wx.Pen(colour, 1, wx.SOLID))
+ dc.DrawRectangle(brightRect.x, y_pos, brightRect.width, 1)
+ v = v - vstep
+
+ dc.SetPen(wx.BLACK_PEN)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangleRect(brightRect)
+
+ self.DrawMarkers(dc)
+
+
+ def TrackPoint(self, pt):
+ """
+ Tracks a mouse action inside the palette control.
+
+ :param `pt`: an instance of :class:`Point`.
+ """
+
+ brightRect = self.BuildRect()
+ d = brightRect.GetBottom() - pt.y
+ d *= 255
+ d /= brightRect.height
+ if d < 0:
+ d = 0
+ if d > 255:
+ d = 255;
+
+ mainDialog = self._mainDialog
+ colour = mainDialog._colour
+
+ mainDialog.DrawMarkers()
+ colour.v = int(d)
+
+ colour.ToRGB()
+ mainDialog.SetSpinVals()
+
+ mainDialog.CalcRects()
+ mainDialog.CalcCuboid()
+ mainDialog.DrawMarkers()
+ mainDialog.DrawAlpha()
+
+
+ def DrawMarkers(self, dc=None):
+ """
+ Draws square markers used with mouse gestures.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ if dc is None:
+ dc = wx.ClientDC(self)
+
+ colour = self._mainDialog._colour
+ brightRect = self.BuildRect()
+
+ y = int(colour.v/255.0*brightRect.height)
+ y = brightRect.GetBottom() - y
+ brightMark = wx.Rect(brightRect.x-2, y-4, brightRect.width+4, 8)
+
+ oldPen, oldBrush, oldMode = dc.GetPen(), dc.GetBrush(), dc.GetLogicalFunction()
+ dc.SetPen(wx.Pen(wx.WHITE, 2))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetLogicalFunction(wx.XOR)
+
+ dc.DrawRectangleRect(brightMark)
+ RestoreOldDC(dc, oldPen, oldBrush, oldMode)
+
+
+class AlphaCtrl(BaseLineCtrl):
+ """
+ Implements the drawing, mouse handling and sizing routines for the alpha
+ channel control.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+ Used internally. Do not call it in your code!
+
+ :param `parent`: the control parent window.
+ """
+
+ BaseLineCtrl.__init__(self, parent)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` for :class:`AlphaCtrl`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ pdc = wx.PaintDC(self)
+ dc = wx.GCDC(pdc)
+
+ mem_dc = wx.MemoryDC()
+ fullRect = self.GetClientRect()
+ bmp = wx.EmptyBitmap(fullRect.width, fullRect.height)
+ mem_dc.SelectObject(bmp)
+
+ rect = self.BuildRect()
+ backBrush = wx.Brush(self.GetParent().GetBackgroundColour())
+ mem_dc.SetBackground(backBrush)
+ mem_dc.Clear()
+
+ mem_dc.SetBrush(wx.WHITE_BRUSH)
+ mem_dc.DrawRectangleRect(rect)
+
+ DrawCheckerBoard(mem_dc, rect, checkColour)
+ self.DrawAlphaShading(mem_dc, rect)
+ mem_dc.DestroyClippingRegion()
+
+ self.DrawMarkers(mem_dc)
+
+ mem_dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ mem_dc.SetPen(wx.BLACK_PEN)
+ mem_dc.DrawRectangleRect(rect)
+
+ mem_dc.SelectObject(wx.NullBitmap)
+ pdc.DrawBitmap(bmp, 0, 0)
+
+
+ def DrawAlphaShading(self, dc, rect):
+ """
+ Draws the alpha shading on top of the checkerboard.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the :class:`AlphaCtrl` client rectangle.
+ """
+
+ gcdc = wx.GCDC(dc)
+
+ colour = self._mainDialog._colour.GetPyColour()
+
+ alpha = 255.0
+ vstep = 255.0*2/(rect.height-1)
+ r, g, b = colour.Red(), colour.Green(), colour.Blue()
+
+ colour_gcdc = wx.Colour(r, g, b, alpha)
+ gcdc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ for y_pos in range(rect.y, rect.height+rect.y, 2):
+ colour_gcdc = wx.Colour(r, g, b, int(alpha))
+ gcdc.SetPen(wx.Pen(colour_gcdc, 1, wx.SOLID))
+ gcdc.DrawRectangle(rect.x, y_pos, rect.width, 2)
+ alpha = alpha - vstep
+
+
+ def TrackPoint(self, pt):
+ """
+ Tracks a mouse action inside the Alpha channel control.
+
+ :param `pt`: an instance of :class:`Point`.
+ """
+
+ alphaRect = self.BuildRect()
+ d = alphaRect.GetBottom() - pt.y
+ d *= 255
+ d /= alphaRect.height
+ if d < 0:
+ d = 0
+ if d > 255:
+ d = 255
+
+ self._mainDialog._colour._alpha = int(d)
+ self.Refresh()
+ self._mainDialog.SetSpinVals()
+
+
+ def DrawMarkers(self, dc=None):
+ """
+ Draws square markers used with mouse gestures.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ if dc is None:
+ dc = wx.ClientDC(self)
+
+ colour = self._mainDialog._colour
+ alphaRect = self.BuildRect()
+
+ y = int(colour._alpha/255.0*alphaRect.height)
+ y = alphaRect.GetBottom() - y
+ alphaMark = wx.Rect(alphaRect.x-2, y-4, alphaRect.width+4, 8)
+
+ oldPen, oldBrush, oldMode = dc.GetPen(), dc.GetBrush(), dc.GetLogicalFunction()
+ dc.SetPen(wx.Pen(wx.WHITE, 2))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetLogicalFunction(wx.XOR)
+
+ dc.DrawRectangleRect(alphaMark)
+ RestoreOldDC(dc, oldPen, oldBrush, oldMode)
+
+
+class ColourPanel(wx.PyPanel):
+ """
+ Simple custom class used to display "old" and "new" colour panels, with alpha
+ blending capabilities.
+ """
+
+ def __init__(self, parent, style=wx.SIMPLE_BORDER):
+ """
+ Default class constructor.
+ Used internally. Do not call it in your code!
+
+ :param `parent`: the control parent window;
+ :param `style`: the :class:`ColourPanel` window style.
+ """
+
+ wx.PyPanel.__init__(self, parent, style=style)
+ self._mainDialog = wx.GetTopLevelParent(self)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ self._colour = Colour(wx.WHITE)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` for :class:`ColourPanel`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ pdc = wx.PaintDC(self)
+ dc = wx.GCDC(pdc)
+
+ mem_dc = wx.MemoryDC()
+ rect = self.GetClientRect()
+ bmp = wx.EmptyBitmap(rect.width, rect.height)
+ mem_dc.SelectObject(bmp)
+
+ backBrush = wx.Brush(self.GetParent().GetBackgroundColour())
+ mem_dc.SetBackground(backBrush)
+ mem_dc.Clear()
+
+ mem_dc.SetBrush(wx.WHITE_BRUSH)
+ mem_dc.DrawRectangleRect(rect)
+
+ DrawCheckerBoard(mem_dc, rect, checkColour, box=10)
+
+ gcdc = wx.GCDC(mem_dc)
+ colour_gcdc = wx.Colour(self._colour.r, self._colour.g, self._colour.b, self._colour._alpha)
+ gcdc.SetBrush(wx.Brush(colour_gcdc))
+ gcdc.SetPen(wx.Pen(colour_gcdc))
+ gcdc.DrawRectangleRect(rect)
+
+ mem_dc.SelectObject(wx.NullBitmap)
+ dc.DrawBitmap(bmp, 0, 0)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` for :class:`ColourPanel`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` for :class:`ColourPanel`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Refresh()
+
+
+ def RefreshColour(self, colour):
+ """
+ Refresh the panel after a colour/alpha change.
+
+ :param `colour`: the new background colour of :class:`ColourPanel`.
+ """
+
+ self._colour = colour
+ self.Refresh()
+
+
+ def AcceptsFocusFromKeyboard(self):
+ """
+ Can this window be given focus by keyboard navigation? If not, the
+ only way to give it focus (provided it accepts it at all) is to click
+ it.
+
+ :note: This method always returns ``False`` as we do not accept focus from
+ the keyboard.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ return False
+
+
+ def AcceptsFocus(self):
+ """
+ Can this window be given focus by mouse click?
+
+ :note: This method always returns ``False`` as we do not accept focus from
+ mouse click.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ return False
+
+
+class CustomPanel(wx.PyControl):
+ """
+ This panel displays a series of custom colours (chosen by the user) just like
+ the standard :class:`ColourDialog`.
+ """
+
+ def __init__(self, parent, colourData):
+ """
+ Default class constructor.
+ Used internally. Do not call it in your code!
+
+ :param `parent`: the control parent window;
+ :param `colourData`: an instance of :class:`ColourData`.
+ """
+
+ wx.PyControl.__init__(self, parent, style=wx.NO_BORDER)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ self._colourData = colourData
+ self._customColours = [None]*16
+ self._mainDialog = wx.GetTopLevelParent(self)
+
+ self.InitializeColours()
+
+ self._smallRectangleSize = wx.Size(20, 16)
+ self._gridSpacing = 4
+ self._customColourRect = wx.Rect(2, 2, (8*self._smallRectangleSize.x) + (7*self._gridSpacing),
+ (2*self._smallRectangleSize.y) + (1*self._gridSpacing))
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+
+
+ def InitializeColours(self):
+ """ Initializes the 16 custom colours in :class:`CustomPanel`. """
+
+ curr = self._colourData.GetColour()
+ self._colourSelection = -1
+
+ for i in xrange(16):
+ c = self._colourData.GetCustomColour(i)
+ if c.Ok():
+ self._customColours[i] = self._colourData.GetCustomColour(i)
+ else:
+ self._customColours[i] = wx.Colour(255, 255, 255)
+
+ if c == curr:
+ self._colourSelection = i
+
+
+ def DoGetBestSize(self):
+ """
+ Overridden base class virtual. Determines the best size of the control.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._customColourRect.width+4, self._customColourRect.height+4
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` for :class:`CustomPanel`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+ dc.SetBackground(wx.Brush(self.GetParent().GetBackgroundColour()))
+ dc.Clear()
+
+ self.PaintCustomColours(dc)
+ self.PaintHighlight(dc, True)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` for :class:`CustomPanel`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` for :class:`CustomPanel`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Refresh()
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` for :class:`CustomPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ x, y = event.GetX(), event.GetY()
+
+ selX = (x - self._customColourRect.x)/(self._smallRectangleSize.x + self._gridSpacing)
+ selY = (y - self._customColourRect.y)/(self._smallRectangleSize.y + self._gridSpacing)
+ ptr = selX + selY*8
+
+ dc = wx.ClientDC(self)
+ self.PaintHighlight(dc, False)
+ self._colourSelection = ptr
+
+ self._mainDialog._colour = Colour(self._customColours[self._colourSelection])
+
+ self.PaintCustomColour(dc, selX, selY)
+ self.PaintHighlight(dc, True)
+ self._mainDialog.DrawAll()
+
+
+ def PaintCustomColours(self, dc):
+ """
+ Draws all the 16 subpanels with their custom colours.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ for i in xrange(2):
+ for j in xrange(8):
+
+ ptr = i*8 + j
+ x = (j*(self._smallRectangleSize.x+self._gridSpacing)) + self._customColourRect.x
+ y = (i*(self._smallRectangleSize.y+self._gridSpacing)) + self._customColourRect.y
+
+ dc.SetPen(wx.BLACK_PEN)
+
+ brush = wx.Brush(self._customColours[ptr])
+ dc.SetBrush(brush)
+
+ dc.DrawRectangle(x, y, self._smallRectangleSize.x, self._smallRectangleSize.y)
+
+
+ def PaintHighlight(self, dc, draw=True):
+ """
+ Highlight the current custom colour selection (if any).
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `draw`: whether to draw a thin black border around the selected custom
+ colour or not.
+ """
+
+ if self._colourSelection < 0:
+ return
+
+ # Number of pixels bigger than the standard rectangle size
+ # for drawing a highlight
+ deltaX = deltaY = 2
+
+ # User-defined colours
+ y = self._colourSelection/8
+ x = self._colourSelection - (y*8)
+
+ x = (x*(self._smallRectangleSize.x + self._gridSpacing) + self._customColourRect.x) - deltaX
+ y = (y*(self._smallRectangleSize.y + self._gridSpacing) + self._customColourRect.y) - deltaY
+
+ if draw:
+ dc.SetPen(wx.BLACK_PEN)
+ else:
+ dc.SetPen(wx.LIGHT_GREY_PEN)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(x, y, (self._smallRectangleSize.x + (2*deltaX)), (self._smallRectangleSize.y + (2*deltaY)))
+
+
+ def PaintCustomColour(self, dc, selX, selY):
+ """
+ Paints a newly added custom colour subpanel.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `selX`: the x coordinate of the custom colour subpanel;
+ :param `selY`: the y coordinate of the custom colour subpanel.
+ """
+
+ dc.SetPen(wx.BLACK_PEN)
+
+ brush = wx.Brush(self._customColours[self._colourSelection])
+ dc.SetBrush(brush)
+
+ ptr = selX*8 + selY
+ x = (selX*(self._smallRectangleSize.x+self._gridSpacing)) + self._customColourRect.x
+ y = (selY*(self._smallRectangleSize.y+self._gridSpacing)) + self._customColourRect.y
+
+ dc.DrawRectangle(x, y, self._smallRectangleSize.x, self._smallRectangleSize.y)
+
+ dc.SetBrush(wx.NullBrush)
+
+
+ def AddCustom(self, colour):
+ """
+ Adds a user-chosen colour to the list of custom colours.
+
+ :param `colour`: an instance of :class:`Colour`.
+ """
+
+ self._colourSelection += 1
+ self._colourSelection = self._colourSelection%16
+
+ dc = wx.ClientDC(self)
+ self._customColours[self._colourSelection] = colour.GetPyColour()
+ self._colourData.SetCustomColour(self._colourSelection, self._customColours[self._colourSelection])
+
+ self.PaintCustomColours(dc)
+
+
+class CubeColourDialog(wx.Dialog):
+ """
+ This is the CubeColourDialog main class implementation.
+ """
+
+ def __init__(self, parent, colourData=None, agwStyle=CCD_SHOW_ALPHA):
+ """
+ Default class constructor.
+
+ :param `colourData`: a standard :class:`ColourData` (as used in :class:`ColourDialog`);
+ :param `agwStyle`: can be either ``None`` or ``CCD_SHOW_ALPHA``, depending if you want
+ to hide the alpha channel control or not.
+ """
+
+ wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=_("CubeColourDialog: Choose Colour"),
+ pos=wx.DefaultPosition, size=(900, 900), style=wx.DEFAULT_DIALOG_STYLE)
+
+ if colourData:
+ self._colourData = colourData
+ else:
+ self._colourData = wx.ColourData()
+ self._colourData.SetColour(wx.Colour(128, 128, 128))
+
+ self._colour = Colour(self._colourData.GetColour())
+ self._oldColour = Colour(self._colourData.GetColour())
+
+ self._inMouse = False
+ self._initOver = False
+ self._inDrawAll = False
+ self._agwStyle = agwStyle
+
+ self.mainPanel = wx.Panel(self, -1)
+
+ self.hsvSizer_staticbox = wx.StaticBox(self.mainPanel, -1, _("HSB"))
+ self.rgbValueSizer_staticbox = wx.StaticBox(self.mainPanel, -1, _("RGB Values"))
+ self.hsvValueSizer_staticbox = wx.StaticBox(self.mainPanel, -1, _("HSB Values"))
+ self.rgbSizer_staticbox = wx.StaticBox(self.mainPanel, -1, _("RGB"))
+ self.alphaSizer_staticbox = wx.StaticBox(self.mainPanel, -1, _("Alpha"))
+ self.alphaValueSizer_staticbox = wx.StaticBox(self.mainPanel, -1, _("Alpha"))
+
+ self.rgbBitmap = RGBCube(self.mainPanel)
+ self.hsvBitmap = HSVWheel(self.mainPanel)
+ self.brightCtrl = BrightCtrl(self.mainPanel)
+ self.alphaCtrl = AlphaCtrl(self.mainPanel)
+
+ self.showAlpha = wx.CheckBox(self.mainPanel, -1, _("Show Alpha Control"))
+ self.customColours = CustomPanel(self.mainPanel, self._colourData)
+ self.addCustom = wx.Button(self.mainPanel, -1, _("Add to custom colours"))
+
+ self.okButton = wx.Button(self.mainPanel, -1, _("OK"))
+ self.cancelButton = wx.Button(self.mainPanel, -1, _("Cancel"))
+
+ self.oldColourPanel = ColourPanel(self.mainPanel, style=wx.SIMPLE_BORDER)
+ self.newColourPanel = ColourPanel(self.mainPanel, style=wx.SIMPLE_BORDER)
+
+ self.redSpin = wx.SpinCtrl(self.mainPanel, -1, "180", min=0, max=255,
+ style=wx.SP_ARROW_KEYS)
+ self.greenSpin = wx.SpinCtrl(self.mainPanel, -1, "180", min=0, max=255,
+ style=wx.SP_ARROW_KEYS)
+ self.blueSpin = wx.SpinCtrl(self.mainPanel, -1, "180", min=0, max=255,
+ style=wx.SP_ARROW_KEYS)
+ self.hueSpin = wx.SpinCtrl(self.mainPanel, -1, "0", min=0, max=359,
+ style=wx.SP_ARROW_KEYS)
+ self.saturationSpin = wx.SpinCtrl(self.mainPanel, -1, "", min=0, max=255,
+ style=wx.SP_ARROW_KEYS)
+ self.brightnessSpin = wx.SpinCtrl(self.mainPanel, -1, "", min=0, max=255,
+ style=wx.SP_ARROW_KEYS)
+ self.alphaSpin = wx.SpinCtrl(self.mainPanel, -1, "", min=0, max=255,
+ style=wx.SP_ARROW_KEYS)
+ self.accessCode = wx.TextCtrl(self.mainPanel, -1, "", style=wx.TE_READONLY)
+ self.htmlCode = wx.TextCtrl(self.mainPanel, -1, "", style=wx.TE_READONLY)
+ self.webSafe = wx.TextCtrl(self.mainPanel, -1, "", style=wx.TE_READONLY)
+ self.htmlName = wx.TextCtrl(self.mainPanel, -1, "", style=wx.TE_READONLY)
+
+ self.SetProperties()
+ self.DoLayout()
+
+ self.spinCtrls = [self.redSpin, self.greenSpin, self.blueSpin,
+ self.hueSpin, self.saturationSpin, self.brightnessSpin]
+
+ for spin in self.spinCtrls:
+ spin.Bind(wx.EVT_SPINCTRL, self.OnSpinCtrl)
+
+ self.Bind(wx.EVT_SPINCTRL, self.OnAlphaSpin, self.alphaSpin)
+
+ self.Bind(wx.EVT_BUTTON, self.OnOk, self.okButton)
+ self.Bind(wx.EVT_BUTTON, self.OnCancel, self.cancelButton)
+ self.Bind(wx.EVT_BUTTON, self.OnAddCustom, self.addCustom)
+
+ self.Bind(wx.EVT_CHECKBOX, self.OnShowAlpha)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ self.Bind(wx.EVT_CHAR_HOOK, self.OnKeyUp)
+
+ self.Centre(wx.BOTH)
+
+ wx.CallAfter(self.InitDialog)
+
+
+ def SetProperties(self):
+ """ Sets some initial properties for :class:`CubeColourDialog` (sizes, values). """
+
+ self.okButton.SetDefault()
+ self.oldColourPanel.SetMinSize((-1, 50))
+ self.newColourPanel.SetMinSize((-1, 50))
+ self.redSpin.SetMinSize((60, -1))
+ self.greenSpin.SetMinSize((60, -1))
+ self.blueSpin.SetMinSize((60, -1))
+ self.hueSpin.SetMinSize((60, -1))
+ self.saturationSpin.SetMinSize((60, -1))
+ self.brightnessSpin.SetMinSize((60, -1))
+ self.alphaSpin.SetMinSize((60, -1))
+ self.showAlpha.SetValue(1)
+ self.accessCode.SetInitialSize((80, -1))
+ self.webSafe.SetInitialSize((80, -1))
+ self.htmlCode.SetInitialSize((80, -1))
+
+
+ def DoLayout(self):
+ """ Layouts all the controls in the :class:`CubeColourDialog`. """
+
+ dialogSizer = wx.BoxSizer(wx.VERTICAL)
+ mainSizer = wx.GridBagSizer(10, 5)
+ hsvValueSizer = wx.StaticBoxSizer(self.hsvValueSizer_staticbox, wx.VERTICAL)
+ hsvGridSizer = wx.GridSizer(2, 3, 2, 10)
+ rgbValueSizer = wx.StaticBoxSizer(self.rgbValueSizer_staticbox, wx.HORIZONTAL)
+ rgbGridSizer = wx.GridSizer(2, 3, 2, 10)
+ alphaValueSizer = wx.StaticBoxSizer(self.alphaValueSizer_staticbox, wx.VERTICAL)
+ alphaGridSizer = wx.BoxSizer(wx.VERTICAL)
+ customSizer = wx.BoxSizer(wx.VERTICAL)
+ buttonSizer = wx.BoxSizer(wx.VERTICAL)
+ accessSizer = wx.BoxSizer(wx.VERTICAL)
+ panelSizer = wx.BoxSizer(wx.VERTICAL)
+ htmlSizer1 = wx.BoxSizer(wx.HORIZONTAL)
+ htmlSizer2 = wx.BoxSizer(wx.VERTICAL)
+ htmlSizer_a = wx.BoxSizer(wx.VERTICAL)
+ htmlSizer_b = wx.BoxSizer(wx.VERTICAL)
+
+ hsvSizer = wx.StaticBoxSizer(self.hsvSizer_staticbox, wx.HORIZONTAL)
+ rgbSizer = wx.StaticBoxSizer(self.rgbSizer_staticbox, wx.VERTICAL)
+ alphaSizer = wx.StaticBoxSizer(self.alphaSizer_staticbox, wx.VERTICAL)
+
+ mainSizer.Add(self.showAlpha, (0, 0), (1, 1), wx.LEFT|wx.TOP, 10)
+
+ htmlLabel1 = wx.StaticText(self.mainPanel, -1, _("HTML Code"))
+ htmlLabel2 = wx.StaticText(self.mainPanel, -1, _("Web Safe"))
+ htmlSizer_a.Add(htmlLabel1, 0, wx.TOP, 3)
+ htmlSizer_b.Add(htmlLabel2, 0, wx.TOP, 3)
+ htmlSizer_a.Add(self.htmlCode, 0, wx.TOP, 3)
+ htmlSizer_b.Add(self.webSafe, 0, wx.TOP, 3)
+
+ htmlSizer1.Add(htmlSizer_a, 0)
+ htmlSizer1.Add(htmlSizer_b, 0, wx.LEFT, 10)
+ mainSizer.Add(htmlSizer1, (1, 0), (1, 1), wx.LEFT|wx.RIGHT, 10)
+
+ htmlLabel3 = wx.StaticText(self.mainPanel, -1, _("HTML Name"))
+ htmlSizer2.Add(htmlLabel3, 0, wx.TOP|wx.BOTTOM, 3)
+ htmlSizer2.Add(self.htmlName, 0)
+
+ mainSizer.Add(htmlSizer2, (1, 1), (1, 1), wx.LEFT|wx.RIGHT, 10)
+
+ customLabel = wx.StaticText(self.mainPanel, -1, _("Custom Colours"))
+ customSizer.Add(customLabel, 0, wx.BOTTOM, 3)
+ customSizer.Add(self.customColours, 0)
+ customSizer.Add(self.addCustom, 0, wx.TOP|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 5)
+ mainSizer.Add(customSizer, (0, 2), (2, 2), wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT, 5)
+
+ rgbSizer.Add(self.rgbBitmap, 0, wx.ALL, 15)
+ mainSizer.Add(rgbSizer, (2, 0), (1, 1), wx.ALL|wx.EXPAND, 10)
+ hsvSizer.Add(self.hsvBitmap, 0, wx.ALL, 15)
+ hsvSizer.Add(self.brightCtrl, 0, wx.RIGHT|wx.TOP|wx.BOTTOM, 15)
+ mainSizer.Add(hsvSizer, (2, 1), (1, 1), wx.ALL|wx.EXPAND, 10)
+ alphaSizer.Add(self.alphaCtrl, 0, wx.TOP|wx.ALIGN_CENTER, 15)
+ mainSizer.Add(alphaSizer, (2, 2), (1, 1), wx.ALL|wx.EXPAND, 10)
+
+ oldLabel = wx.StaticText(self.mainPanel, -1, _("Old Colour"))
+ panelSizer.Add(oldLabel, 0, wx.BOTTOM, 3)
+ panelSizer.Add(self.oldColourPanel, 0, wx.BOTTOM|wx.EXPAND, 20)
+ newLabel = wx.StaticText(self.mainPanel, -1, _("New Colour"))
+ accessLabel = wx.StaticText(self.mainPanel, -1, _("MS Access Code"))
+ accessSizer.Add(accessLabel, 0, wx.BOTTOM, 3)
+ accessSizer.Add(self.accessCode, 0)
+ panelSizer.Add(newLabel, 0, wx.BOTTOM, 3)
+ panelSizer.Add(self.newColourPanel, 0, wx.EXPAND)
+ panelSizer.Add((0, 0), 1, wx.EXPAND)
+ panelSizer.Add(accessSizer, 0, wx.TOP, 5)
+ mainSizer.Add(panelSizer, (2, 3), (1, 1), wx.ALL|wx.EXPAND, 10)
+ redLabel = wx.StaticText(self.mainPanel, -1, _("Red"))
+ rgbGridSizer.Add(redLabel, 0)
+ greenLabel = wx.StaticText(self.mainPanel, -1, _("Green"))
+ rgbGridSizer.Add(greenLabel, 0)
+ blueLabel = wx.StaticText(self.mainPanel, -1, _("Blue"))
+ rgbGridSizer.Add(blueLabel, 0)
+ rgbGridSizer.Add(self.redSpin, 0, wx.EXPAND)
+ rgbGridSizer.Add(self.greenSpin, 0, wx.EXPAND)
+ rgbGridSizer.Add(self.blueSpin, 0, wx.EXPAND)
+ rgbValueSizer.Add(rgbGridSizer, 1, 0, 0)
+ mainSizer.Add(rgbValueSizer, (3, 0), (1, 1), wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, 10)
+ hueLabel = wx.StaticText(self.mainPanel, -1, _("Hue"))
+ hsvGridSizer.Add(hueLabel, 0)
+ saturationLabel = wx.StaticText(self.mainPanel, -1, _("Saturation"))
+ hsvGridSizer.Add(saturationLabel, 0)
+ brightnessLabel = wx.StaticText(self.mainPanel, -1, _("Brightness"))
+ hsvGridSizer.Add(brightnessLabel, 0)
+ hsvGridSizer.Add(self.hueSpin, 0, wx.EXPAND)
+ hsvGridSizer.Add(self.saturationSpin, 0, wx.EXPAND)
+ hsvGridSizer.Add(self.brightnessSpin, 0, wx.EXPAND)
+ hsvValueSizer.Add(hsvGridSizer, 1, wx.EXPAND)
+ mainSizer.Add(hsvValueSizer, (3, 1), (1, 1), wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, 10)
+ alphaLabel = wx.StaticText(self.mainPanel, -1, _("Alpha"))
+ alphaGridSizer.Add(alphaLabel, 0)
+ alphaGridSizer.Add(self.alphaSpin, 0, wx.EXPAND|wx.TOP, 10)
+ alphaValueSizer.Add(alphaGridSizer, 1, wx.EXPAND)
+ mainSizer.Add(alphaValueSizer, (3, 2), (1, 1), wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, 10)
+ buttonSizer.Add(self.okButton, 0, wx.BOTTOM, 3)
+ buttonSizer.Add(self.cancelButton, 0)
+ mainSizer.Add(buttonSizer, (3, 3), (1, 1), wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT, 5)
+
+ self.mainPanel.SetAutoLayout(True)
+ self.mainPanel.SetSizer(mainSizer)
+ mainSizer.Fit(self.mainPanel)
+ mainSizer.SetSizeHints(self.mainPanel)
+
+ if self.GetAGWWindowStyleFlag() & CCD_SHOW_ALPHA == 0:
+ mainSizer.Hide(self.showAlpha)
+ mainSizer.Hide(alphaSizer)
+ mainSizer.Hide(alphaValueSizer)
+
+ dialogSizer.Add(self.mainPanel, 1, wx.EXPAND)
+ self.SetAutoLayout(True)
+ self.SetSizer(dialogSizer)
+ dialogSizer.Fit(self)
+ dialogSizer.SetSizeHints(self)
+ self.Layout()
+
+ self.mainSizer = mainSizer
+ self.dialogSizer = dialogSizer
+ self.alphaSizers = [alphaSizer, alphaValueSizer]
+
+
+ def InitDialog(self):
+ """ Initialize the :class:`CubeColourDialog`. """
+
+ hsvRect = self.hsvBitmap.GetClientRect()
+ self._centre = wx.Point(hsvRect.x + hsvRect.width/2, hsvRect.y + hsvRect.height/2)
+
+ self._redLen = Distance(Vertex, Top)
+ self._greenLen = Distance(Vertex, Left)
+ self._blueLen = Distance(Vertex, Right)
+
+ self.CalcSlopes()
+ self.CalcCuboid()
+ self.CalcRects()
+
+ self.SetSpinVals()
+
+ self._initOver = True
+ wx.CallAfter(self.Refresh)
+
+
+ def CalcSlopes(self):
+ """ Calculates the line slopes in the RGB colour cube. """
+
+ self._lines = {RED: LineDescription(), GREEN: LineDescription(), BLUE: LineDescription}
+
+ self._lines[RED].slope = Slope(Top, Vertex)
+ self._lines[GREEN].slope = Slope(Left, Vertex)
+ self._lines[BLUE].slope = Slope(Right, Vertex)
+
+ for i in xrange(3):
+ self._lines[i].x = Vertex.x
+ self._lines[i].y = Vertex.y
+ self._lines[i].c = FindC(self._lines[i])
+
+
+ def CalcCuboid(self):
+ """ Calculates the RGB colour cube vertices. """
+
+ rLen = (self._colour.r*self._redLen)/255.0
+ gLen = (self._colour.g*self._greenLen)/255.0
+ bLen = (self._colour.b*self._blueLen)/255.0
+
+ lines = [LineDescription() for i in xrange(12)]
+ self._cuboid = [None]*8
+
+ self._cuboid[0] = Vertex
+ self._cuboid[1] = PointOnLine(Vertex, Top, int(rLen), self._redLen)
+ self._cuboid[3] = PointOnLine(Vertex, Left, int(gLen), self._greenLen)
+ self._cuboid[7] = PointOnLine(Vertex, Right, int(bLen), self._blueLen)
+
+ lines[0] = self._lines[RED]
+ lines[1] = self._lines[GREEN]
+ lines[2] = self._lines[BLUE]
+
+ lines[3].slope = self._lines[GREEN].slope
+ lines[3].x = self._cuboid[1].x
+ lines[3].y = self._cuboid[1].y
+ lines[3].c = FindC(lines[3])
+
+ lines[4].slope = self._lines[RED].slope
+ lines[4].x = self._cuboid[3].x
+ lines[4].y = self._cuboid[3].y
+ lines[4].c = FindC(lines[4])
+
+ lines[5].slope = self._lines[BLUE].slope
+ lines[5].x = self._cuboid[3].x
+ lines[5].y = self._cuboid[3].y
+ lines[5].c = FindC(lines[5])
+
+ lines[6].slope = self._lines[GREEN].slope
+ lines[6].x = self._cuboid[7].x
+ lines[6].y = self._cuboid[7].y
+ lines[6].c = FindC(lines[6])
+
+ lines[10].slope = self._lines[BLUE].slope
+ lines[10].x = self._cuboid[1].x
+ lines[10].y = self._cuboid[1].y
+ lines[10].c = FindC(lines[10])
+
+ lines[11].slope = self._lines[RED].slope
+ lines[11].x = self._cuboid[7].x
+ lines[11].y = self._cuboid[7].y
+ lines[11].c = FindC(lines[11])
+
+ self._cuboid[2] = Intersection(lines[3], lines[4])
+ self._cuboid[4] = Intersection(lines[5], lines[6])
+ self._cuboid[6] = Intersection(lines[10], lines[11])
+
+ lines[7].slope = self._lines[RED].slope
+ lines[7].x = self._cuboid[4].x
+ lines[7].y = self._cuboid[4].y
+ lines[7].c = FindC(lines[7])
+
+ lines[8].slope = self._lines[BLUE].slope
+ lines[8].x = self._cuboid[2].x
+ lines[8].y = self._cuboid[2].y
+ lines[8].c = FindC(lines[8])
+
+ self._cuboid[5] = Intersection(lines[7], lines[8])
+
+
+ def CalcRects(self):
+ """ Calculates the brightness control user-selected rect. """
+
+ pt = PtFromAngle(self._colour.h, self._colour.s, self._centre)
+ self._currentRect = wx.Rect(pt.x - RECT_WIDTH, pt.y - RECT_WIDTH,
+ 2*RECT_WIDTH, 2*RECT_WIDTH)
+
+
+ def DrawMarkers(self, dc=None):
+ """
+ Draws the markers for all the controls.
+
+ :param `dc`: an instance of :class:`DC`. If `dc` is ``None``, a :class:`ClientDC` is
+ created on the fly.
+ """
+
+ if dc is None:
+ dc = wx.ClientDC(self)
+
+ self.hsvBitmap.DrawMarkers()
+ self.rgbBitmap.DrawMarkers()
+ self.brightCtrl.DrawMarkers()
+
+
+ def DrawRGB(self):
+ """ Refreshes the RGB colour cube. """
+
+ self.rgbBitmap.Refresh()
+
+
+ def DrawHSB(self):
+ """ Refreshes the HSB colour wheel. """
+
+ self.hsvBitmap.Refresh()
+
+
+ def DrawBright(self):
+ """ Refreshes the brightness control. """
+
+ self.brightCtrl.Refresh()
+
+
+ def DrawAlpha(self):
+ """ Refreshes the alpha channel control. """
+
+ self.alphaCtrl.Refresh()
+
+
+ def SetSpinVals(self):
+ """ Sets the values for all the spin controls. """
+
+ self.redSpin.SetValue(self._colour.r)
+ self.greenSpin.SetValue(self._colour.g)
+ self.blueSpin.SetValue(self._colour.b)
+
+ self.hueSpin.SetValue(self._colour.h)
+ self.saturationSpin.SetValue(self._colour.s)
+ self.brightnessSpin.SetValue(self._colour.v)
+
+ self.alphaSpin.SetValue(self._colour._alpha)
+
+ self.SetPanelColours()
+ self.SetCodes()
+
+
+ def SetPanelColours(self):
+ """ Assigns colours to the colour panels. """
+
+ self.oldColourPanel.RefreshColour(self._oldColour)
+ self.newColourPanel.RefreshColour(self._colour)
+
+
+ def SetCodes(self):
+ """ Sets the HTML/MS Access codes (if any) in the text controls. """
+
+ colour = rgb2html(self._colour)
+ self.htmlCode.SetValue(colour)
+ self.htmlCode.Refresh()
+
+ if colour in HTMLCodes:
+ colourName, access, webSafe = HTMLCodes[colour]
+ self.webSafe.SetValue(webSafe)
+ self.accessCode.SetValue(access)
+ self.htmlName.SetValue(colourName)
+ else:
+ self.webSafe.SetValue("")
+ self.accessCode.SetValue("")
+ self.htmlName.SetValue("")
+
+
+ def OnCloseWindow(self, event):
+ """
+ Handles the ``wx.EVT_CLOSE`` event for :class:`CubeColourDialog`.
+
+ :param `event`: a :class:`CloseEvent` event to be processed.
+ """
+
+ self.EndModal(wx.ID_CANCEL)
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_CHAR_HOOK`` event for :class:`CubeColourDialog`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if event.GetKeyCode() == wx.WXK_ESCAPE:
+ self.EndModal(wx.ID_CANCEL)
+
+ event.Skip()
+
+
+ def ShowModal(self):
+ """
+ Shows :class:`CubeColourDialog` as a modal dialog. Program flow does
+ not return until the dialog has been dismissed with `EndModal`.
+
+ :note: Overridden from :class:`Dialog`.
+ """
+
+ return wx.Dialog.ShowModal(self)
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the :class:`CubeColourDialog` window style flags.
+
+ :param `agwStyle`: can only be ``CCD_SHOW_ALPHA`` or ``None``.
+ """
+
+ show = self.GetAGWWindowStyleFlag() & CCD_SHOW_ALPHA
+ self._agwStyle = agwStyle
+
+ self.mainSizer.Show(self.alphaSizers[0], show)
+ self.mainSizer.Show(self.alphaSizers[1], show)
+
+ self.mainSizer.Fit(self.mainPanel)
+ self.mainSizer.SetSizeHints(self.mainPanel)
+ self.mainSizer.Layout()
+ self.dialogSizer.Fit(self)
+ self.dialogSizer.SetSizeHints(self)
+ self.Layout()
+
+ self.Refresh()
+ self.Update()
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`CubeColourDialog` window style flags.
+
+ :see: :meth:`~CubeColourDialog.SetAGWWindowStyleFlag` for a list of possible flags.
+ """
+
+ return self._agwStyle
+
+
+ def OnOk(self, event):
+ """
+ Handles the Ok ``wx.EVT_BUTTON`` event for :class:`CubeColourDialog`.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+ """
+
+ self.EndModal(wx.ID_OK)
+
+
+ def OnCancel(self, event):
+ """
+ Handles the Cancel ``wx.EVT_BUTTON`` event for :class:`CubeColourDialog`.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+ """
+
+ self.OnCloseWindow(event)
+
+
+ def OnAddCustom(self, event):
+ """
+ Handles the Add Custom ``wx.EVT_BUTTON`` event for :class:`CubeColourDialog`.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+ """
+
+
+ self.customColours.AddCustom(self._colour)
+
+
+ def OnShowAlpha(self, event):
+ """
+ Shows/hides the alpha channel control in :class:`CubeColourDialog`.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+ """
+
+ agwStyle = self.GetAGWWindowStyleFlag()
+ show = event.IsChecked()
+
+ if show:
+ agwStyle |= CCD_SHOW_ALPHA
+ else:
+ agwStyle &= ~CCD_SHOW_ALPHA
+
+ self.SetAGWWindowStyleFlag(agwStyle)
+
+
+ def OnSpinCtrl(self, event):
+ """
+ Handles the ``wx.EVT_SPINCTRL`` event for RGB and HSB colours.
+
+ :param `event`: a :class:`SpinEvent` event to be processed.
+ """
+
+ obj = event.GetEventObject()
+ position = self.spinCtrls.index(obj)
+ colourVal = event.GetInt()
+
+ attribute, maxVal = colourAttributes[position], colourMaxValues[position]
+
+ self.AssignColourValue(attribute, colourVal, maxVal, position)
+
+
+ def OnAlphaSpin(self, event):
+ """
+ Handles the ``wx.EVT_SPINCTRL`` event for the alpha channel.
+
+ :param `event`: a :class:`SpinEvent` event to be processed.
+ """
+
+ colourVal = event.GetInt()
+ originalVal = self._colour._alpha
+ if colourVal != originalVal and self._initOver:
+ if colourVal < 0:
+ colourVal = 0
+ if colourVal > 255:
+ colourVal = 255
+
+ self._colour._alpha = colourVal
+ self.DrawAlpha()
+
+
+ def AssignColourValue(self, attribute, colourVal, maxVal, position):
+ """ Common code to handle spin control changes. """
+
+ originalVal = getattr(self._colour, attribute)
+ if colourVal != originalVal and self._initOver:
+
+ if colourVal < 0:
+ colourVal = 0
+ if colourVal > maxVal:
+ colourVal = maxVal
+
+ setattr(self._colour, attribute, colourVal)
+ if position < 3:
+ self._colour.ToHSV()
+ else:
+ self._colour.ToRGB()
+
+ self.DrawAll()
+
+
+ def DrawAll(self):
+ """ Draws all the custom controls after a colour change. """
+
+ if self._initOver and not self._inDrawAll:
+ self._inDrawAll = True
+
+ dc1 = wx.ClientDC(self.hsvBitmap)
+ self.hsvBitmap.DrawMarkers(dc1)
+
+ dc2 = wx.ClientDC(self.rgbBitmap)
+ self.rgbBitmap.DrawMarkers(dc2)
+ self.rgbBitmap.DrawLines(dc2)
+
+ dc3 = wx.ClientDC(self.brightCtrl)
+ self.brightCtrl.DrawMarkers(dc3)
+
+ dc4 = wx.ClientDC(self.alphaCtrl)
+ self.alphaCtrl.DrawMarkers(dc4)
+
+ self.CalcCuboid()
+ self.CalcRects()
+
+ self.DrawRGB()
+ self.DrawHSB()
+ self.DrawBright()
+ self.DrawAlpha()
+
+ self.SetSpinVals()
+ self._inDrawAll = False
+
+
+ def GetColourData(self):
+ """ Returns a wxPython compatible :class:`ColourData`. """
+
+ self._colourData.SetColour(self._colour.GetPyColour())
+ return self._colourData
+
+
+ def GetRGBAColour(self):
+ """ Returns a 4-elements tuple of red, green, blue, alpha components. """
+
+ return (self._colour.r, self._colour.g, self._colour.b, self._colour._alpha)
+
+
+ def GetHSVAColour(self):
+ """ Returns a 4-elements tuple of hue, saturation, brightness, alpha components. """
+
+ return (self._colour.h, self._colour.s, self._colour.v, self._colour._alpha)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/customtreectrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/customtreectrl.py
new file mode 100644
index 0000000..776c73c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/customtreectrl.py
@@ -0,0 +1,8506 @@
+# --------------------------------------------------------------------------------- #
+# CUSTOMTREECTRL wxPython IMPLEMENTATION
+# Inspired By And Heavily Based On wxGenericTreeCtrl.
+#
+# Andrea Gavana, @ 17 May 2006
+# Latest Revision: 03 Jan 2014, 23.00 GMT
+#
+#
+# TODO List
+#
+# Almost All The Features Of wx.TreeCtrl Are Available, And There Is Practically
+# No Limit In What Could Be Added To This Class. The First Things That Comes
+# To My Mind Are:
+#
+# 1. Try To Implement A More Flicker-Free Background Image In Cases Like
+# Centered Or Stretched Image (Now CustomTreeCtrl Supports Only Tiled
+# Background Images).
+#
+# 2. Try To Mimic Windows wx.TreeCtrl Expanding/Collapsing behaviour: CustomTreeCtrl
+# Suddenly Expands/Collapses The Nodes On Mouse Click While The Native Control
+# Has Some Kind Of "Smooth" Expanding/Collapsing, Like A Wave. I Don't Even
+# Know Where To Start To Do That.
+#
+# 3. Speed Up General OnPaint Things? I Have No Idea, Here CustomTreeCtrl Is Quite
+# Fast, But We Should See On Slower Machines.
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@maerskoil.com
+# andrea.gavana@gmail.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+
+"""
+:class:`CustomTreeCtrl` is a class that mimics the behaviour of :class:`TreeCtrl`, with some more
+enhancements.
+
+
+Description
+===========
+
+:class:`CustomTreeCtrl` is a class that mimics the behaviour of :class:`TreeCtrl`, with almost the
+same base functionalities plus some more enhancements. This class does not rely on
+the native control, as it is a full owner-drawn tree control.
+Apart of the base functionalities of :class:`CustomTreeCtrl` (described below), in addition
+to the standard :class:`TreeCtrl` behaviour this class supports:
+
+* CheckBox-type items: checkboxes are easy to handle, just selected or unselected
+ state with no particular issues in handling the item's children;
+* Added support for 3-state value checkbox items;
+* RadioButton-type items: since I elected to put radiobuttons in :class:`CustomTreeCtrl`, I
+ needed some way to handle them, that made sense. So, I used the following approach:
+
+ - All peer-nodes that are radiobuttons will be mutually exclusive. In other words,
+ only one of a set of radiobuttons that share a common parent can be checked at
+ once. If a radiobutton node becomes checked, then all of its peer radiobuttons
+ must be unchecked.
+ - If a radiobutton node becomes unchecked, then all of its child nodes will become
+ inactive.
+
+* Hyperlink-type items: they look like an hyperlink, with the proper mouse cursor on
+ hovering;
+* Multiline text items (**note**: to add a newline character in a multiline item, press
+ ``Shift`` + ``Enter`` as the ``Enter`` key alone is consumed by :class:`CustomTreeCtrl` to finish
+ the editing and ``Ctrl`` + ``Enter`` is consumed by the platform for tab navigation);
+* Enabling/disabling items (together with their plain or grayed out icons);
+* Whatever non-toplevel widget can be attached next to an item;
+* Possibility to horizontally align the widgets attached to tree items on the
+ same tree level.
+* Possibility to align the widgets attached to tree items to the rightmost edge of :class:`CustomTreeCtrl`;
+* Default selection style, gradient (horizontal/vertical) selection style and Windows
+ Vista selection style;
+* Customized drag and drop images built on the fly;
+* Setting the :class:`CustomTreeCtrl` item buttons to a personalized imagelist;
+* Setting the :class:`CustomTreeCtrl` check/radio item icons to a personalized imagelist;
+* Changing the style of the lines that connect the items (in terms of :class:`Pen` styles);
+* Using an image as a :class:`CustomTreeCtrl` background (currently only in "tile" mode);
+* Adding images to any item in the leftmost area of the :class:`CustomTreeCtrl` client window.
+* Separator-type items which are simply visual indicators that are meant to set apart
+ or divide tree items, with the following caveats:
+
+ - Separator items should not have children, labels, data or an associated window;
+ - You can change the color of individual separators by using meth:~CustomTreeCtrl.SetItemTextColour`, or you can use
+ meth:~CustomTreeCtrl.SetSeparatorColour` to change the color of all separators. The default separator colour
+ is that returned by `SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)`;
+ - Separators can be selected just like any other tree item;
+ - Separators cannot have text;
+ - Separators cannot have children;
+ - Separators cannot be edited via the ``EVT_TREE_BEGIN_LABEL_EDIT`` event.
+
+* Ellipsization of long items when the horizontal space is low, via the ``TR_ELLIPSIZE_LONG_ITEMS``
+ style (`New in version 0.9.3`);
+* Tooltips on long items when the horizontal space is low, via the ``TR_TOOLTIP_ON_LONG_ITEMS``
+ style (`New in version 0.9.3`).
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+Base Functionalities
+====================
+
+:class:`CustomTreeCtrl` supports all the :class:`TreeCtrl` styles, except:
+
+- ``TR_EXTENDED``: supports for this style is on the todo list (am I sure of this?).
+
+Plus it has 3 more styles to handle checkbox-type items:
+
+- ``TR_AUTO_CHECK_CHILD``: automatically checks/unchecks the item children;
+- ``TR_AUTO_CHECK_PARENT``: automatically checks/unchecks the item parent;
+- ``TR_AUTO_TOGGLE_CHILD``: automatically toggles the item children.
+
+And two styles you can use to force the horizontal alignment of all the widgets
+attached to the tree items:
+
+- ``TR_ALIGN_WINDOWS``: aligns horizontally the windows belonging to the item on the
+ same tree level.
+- ``TR_ALIGN_WINDOWS_RIGHT``: aligns to the rightmost position the windows belonging
+ to the item on the same tree level.
+
+And two styles related to long items (with a lot of text in them), which can be
+ellipsized and/or highlighted with a tooltip:
+
+- ``TR_ELLIPSIZE_LONG_ITEMS``: ellipsizes long items when the horizontal space for
+ :class:`CustomTreeCtrl` is low (`New in version 0.9.3`);
+- ``TR_TOOLTIP_ON_LONG_ITEMS``: shows tooltips on long items when the horizontal space
+ for :class:`CustomTreeCtrl` is low (`New in version 0.9.3`);.
+
+All the methods available in :class:`TreeCtrl` are also available in :class:`CustomTreeCtrl`.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.customtreectrl as CT
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init(self, parent, -1, "CustomTreeCtrl Demo")
+
+ # Create a CustomTreeCtrl instance
+ custom_tree = CT.CustomTreeCtrl(self, agwStyle=wx.TR_DEFAULT_STYLE)
+
+ # Add a root node to it
+ root = custom_tree.AddRoot("The Root Item")
+
+ # Create an image list to add icons next to an item
+ il = wx.ImageList(16, 16)
+ fldridx = il.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, 16))
+ fldropenidx = il.Add(wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, 16))
+ fileidx = il.Add(wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, 16))
+
+ custom_tree.SetImageList(il)
+
+ custom_tree.SetItemImage(root, fldridx, wx.TreeItemIcon_Normal)
+ custom_tree.SetItemImage(root, fldropenidx, wx.TreeItemIcon_Expanded)
+
+ for x in range(15):
+ child = custom_tree.AppendItem(root, "Item %d" % x)
+ custom_tree.SetItemImage(child, fldridx, wx.TreeItemIcon_Normal)
+ custom_tree.SetItemImage(child, fldropenidx, wx.TreeItemIcon_Expanded)
+
+ for y in range(5):
+ last = custom_tree.AppendItem(child, "item %d-%s" % (x, chr(ord("a")+y)))
+ custom_tree.SetItemImage(last, fldridx, wx.TreeItemIcon_Normal)
+ custom_tree.SetItemImage(last, fldropenidx, wx.TreeItemIcon_Expanded)
+
+ for z in range(5):
+ item = custom_tree.AppendItem(last, "item %d-%s-%d" % (x, chr(ord("a")+y), z))
+ custom_tree.SetItemImage(item, fileidx, wx.TreeItemIcon_Normal)
+ custom_tree.SetItemImage(item, smileidx, wx.TreeItemIcon_Selected)
+
+ custom_tree.Expand(self.root)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Events
+======
+
+All the events supported by :class:`TreeCtrl` are also available in :class:`CustomTreeCtrl`, with
+a few exceptions:
+
+- ``EVT_TREE_GET_INFO`` (don't know what this means);
+- ``EVT_TREE_SET_INFO`` (don't know what this means);
+- ``EVT_TREE_ITEM_MIDDLE_CLICK`` (not implemented, but easy to add);
+- ``EVT_TREE_STATE_IMAGE_CLICK`` (no need for that, look at the checking events below).
+
+Plus, :class:`CustomTreeCtrl` supports the events related to the checkbutton-type items:
+
+- ``EVT_TREE_ITEM_CHECKING``: an item is being checked;
+- ``EVT_TREE_ITEM_CHECKED``: an item has been checked.
+
+And to hyperlink-type items:
+
+- ``EVT_TREE_ITEM_HYPERLINK``: an hyperlink item has been clicked (this event is sent
+ after the ``EVT_TREE_SEL_CHANGED`` event).
+
+
+Supported Platforms
+===================
+
+:class:`CustomTreeCtrl` has been tested on the following platforms:
+ * Windows (Windows XP);
+ * GTK (Thanks to Michele Petrazzo);
+ * Mac OS (Thanks to John Jackson).
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+============================== =========== ==================================================
+Window Styles Hex Value Description
+============================== =========== ==================================================
+``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn.
+``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default.
+``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items.
+``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors.
+``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set.
+``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit.
+``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons.
+``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected.
+``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases).
+``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset.
+``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control.
+``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows.
+``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes.
+``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window.
+``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well.
+``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly.
+``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful foe checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well.
+``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position.
+``TR_ALIGN_WINDOWS_RIGHT`` 0x40000 Flag used to align windows (in items with windows) to the rightmost edge of :class:`CustomTreeCtrl`.
+``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`CustomTreeCtrl` is low.
+``TR_TOOLTIP_ON_LONG_ITEMS`` 0x100000 Flag used to show tooltips on long items when the horizontal space for :class:`CustomTreeCtrl` is low.
+============================== =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+============================== ==================================================
+Event Name Description
+============================== ==================================================
+``EVT_TREE_BEGIN_DRAG`` Begin dragging with the left mouse button.
+``EVT_TREE_BEGIN_LABEL_EDIT`` Begin editing a label. This can be prevented by calling meth:~TreeEvent.Veto`.
+``EVT_TREE_BEGIN_RDRAG`` Begin dragging with the right mouse button.
+``EVT_TREE_DELETE_ITEM`` Delete an item.
+``EVT_TREE_END_DRAG`` End dragging with the left or right mouse button.
+``EVT_TREE_END_LABEL_EDIT`` End editing a label. This can be prevented by calling meth:~TreeEvent.Veto`.
+``EVT_TREE_GET_INFO`` Request information from the application (not implemented in :class:`CustomTreeCtrl`).
+``EVT_TREE_ITEM_ACTIVATED`` The item has been activated, i.e. chosen by double clicking it with mouse or from keyboard.
+``EVT_TREE_ITEM_CHECKED`` A checkbox or radiobox type item has been checked.
+``EVT_TREE_ITEM_CHECKING`` A checkbox or radiobox type item is being checked.
+``EVT_TREE_ITEM_COLLAPSED`` The item has been collapsed.
+``EVT_TREE_ITEM_COLLAPSING`` The item is being collapsed. This can be prevented by calling meth:~TreeEvent.Veto`.
+``EVT_TREE_ITEM_EXPANDED`` The item has been expanded.
+``EVT_TREE_ITEM_EXPANDING`` The item is being expanded. This can be prevented by calling meth:~TreeEvent.Veto`.
+``EVT_TREE_ITEM_GETTOOLTIP`` The opportunity to set the item tooltip is being given to the application (call `TreeEvent.SetToolTip`).
+``EVT_TREE_ITEM_HYPERLINK`` An hyperlink type item has been clicked.
+``EVT_TREE_ITEM_MENU`` The context menu for the selected item has been requested, either by a right click or by using the menu key.
+``EVT_TREE_ITEM_MIDDLE_CLICK`` The user has clicked the item with the middle mouse button (not implemented in :class:`CustomTreeCtrl`).
+``EVT_TREE_ITEM_RIGHT_CLICK`` The user has clicked the item with the right mouse button.
+``EVT_TREE_KEY_DOWN`` A key has been pressed.
+``EVT_TREE_SEL_CHANGED`` Selection has changed.
+``EVT_TREE_SEL_CHANGING`` Selection is changing. This can be prevented by calling meth:~TreeEvent.Veto`.
+``EVT_TREE_SET_INFO`` Information is being supplied to the application (not implemented in :class:`CustomTreeCtrl`).
+``EVT_TREE_STATE_IMAGE_CLICK`` The state image has been clicked (not implemented in :class:`CustomTreeCtrl`).
+============================== ==================================================
+
+
+License And Version
+===================
+
+:class:`CustomTreeCtrl` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 03 Jan 2014, 23.00 GMT
+
+Version 2.6
+
+"""
+
+# Version Info
+__version__ = "2.6"
+
+import wx
+from wx.lib.expando import ExpandoTextCtrl
+
+# ----------------------------------------------------------------------------
+# Constants
+# ----------------------------------------------------------------------------
+
+_NO_IMAGE = -1
+_PIXELS_PER_UNIT = 10
+
+# Start editing the current item after half a second (if the mouse hasn't
+# been clicked/moved)
+_DELAY = 500
+
+# wxPython version string
+_VERSION_STRING = wx.VERSION_STRING
+
+# ----------------------------------------------------------------------------
+# Constants
+# ----------------------------------------------------------------------------
+
+# Enum for different images associated with a treectrl item
+TreeItemIcon_Normal = 0 # not selected, not expanded
+""" The tree item is not selected and not expanded. """
+TreeItemIcon_Selected = 1 # selected, not expanded
+""" The tree item is selected and not expanded. """
+TreeItemIcon_Expanded = 2 # not selected, expanded
+""" The tree item is not selected but expanded. """
+TreeItemIcon_SelectedExpanded = 3 # selected, expanded
+""" The tree item is selected and expanded. """
+TreeItemIcon_Checked = 0 # check button, checked
+""" The item's check button is checked. """
+TreeItemIcon_NotChecked = 1 # check button, not checked
+""" The item's check button is not checked. """
+TreeItemIcon_Undetermined = 2 # check button, undetermined
+""" The item's check button is in undetermined state (used only for a 3-state check button). """
+TreeItemIcon_Flagged = 3 # radio button, selected
+""" The item's radio button is checked. """
+TreeItemIcon_NotFlagged = 4 # radio button, not selected
+""" The item's radio button is not checked. """
+
+# ----------------------------------------------------------------------------
+# CustomTreeCtrl flags
+# ----------------------------------------------------------------------------
+
+TR_NO_BUTTONS = wx.TR_NO_BUTTONS # for convenience
+""" For convenience to document that no buttons are to be drawn. """
+TR_HAS_BUTTONS = wx.TR_HAS_BUTTONS # draw collapsed/expanded btns
+""" Use this style to show + and - buttons to the left of parent items. """
+TR_NO_LINES = wx.TR_NO_LINES # don't draw lines at all
+""" Use this style to hide vertical level connectors. """
+TR_LINES_AT_ROOT = wx.TR_LINES_AT_ROOT # connect top-level nodes
+""" Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set. """
+TR_TWIST_BUTTONS = wx.TR_TWIST_BUTTONS # still used by wxTreeListCtrl
+""" Use old Mac-twist style buttons. """
+TR_SINGLE = wx.TR_SINGLE # for convenience
+""" For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default. """
+TR_MULTIPLE = wx.TR_MULTIPLE # can select multiple items
+""" Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected. """
+TR_EXTENDED = wx.TR_EXTENDED # TODO: allow extended selection
+""" Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases). """
+TR_HAS_VARIABLE_ROW_HEIGHT = wx.TR_HAS_VARIABLE_ROW_HEIGHT # what it says
+""" Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset. """
+TR_EDIT_LABELS = wx.TR_EDIT_LABELS # can edit item labels
+""" Use this style if you wish the user to be able to edit labels in the tree control. """
+TR_ROW_LINES = wx.TR_ROW_LINES # put border around items
+""" Use this style to draw a contrasting border between displayed rows. """
+TR_HIDE_ROOT = wx.TR_HIDE_ROOT # don't display root node
+""" Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes. """
+TR_FULL_ROW_HIGHLIGHT = wx.TR_FULL_ROW_HIGHLIGHT # highlight full horz space
+""" Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window. """
+
+TR_AUTO_CHECK_CHILD = 0x04000 # only meaningful for checkboxes
+""" Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well. """
+TR_AUTO_TOGGLE_CHILD = 0x08000 # only meaningful for checkboxes
+""" Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly. """
+TR_AUTO_CHECK_PARENT = 0x10000 # only meaningful for checkboxes
+""" Only meaningful foe checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well. """
+TR_ALIGN_WINDOWS = 0x20000 # to align windows horizontally for items at the same level
+""" Flag used to align windows (in items with windows) at the same horizontal position. """
+TR_ALIGN_WINDOWS_RIGHT = 0x40000 # to align windows to the rightmost edge of CustomTreeCtrl
+""" Flag used to align windows (in items with windows) to the rightmost edge of :class:`CustomTreeCtrl`."""
+TR_ELLIPSIZE_LONG_ITEMS = 0x80000 # to ellipsize long items when horizontal space is low
+""" Flag used to ellipsize long items when the horizontal space for :class:`CustomTreeCtrl` is low."""
+TR_TOOLTIP_ON_LONG_ITEMS = 0x100000 # to display tooltips on long items when horizontal space is low
+""" Flag used to show tooltips on long items when the horizontal space for :class:`CustomTreeCtrl` is low."""
+
+TR_DEFAULT_STYLE = wx.TR_DEFAULT_STYLE # default style for the tree control
+""" The set of flags that are closest to the defaults for the native control for a particular toolkit. """
+
+# Values for the `flags` parameter of CustomTreeCtrl.HitTest() which determine
+# where exactly the specified point is situated:
+
+TREE_HITTEST_ABOVE = wx.TREE_HITTEST_ABOVE
+""" Above the client area. """
+TREE_HITTEST_BELOW = wx.TREE_HITTEST_BELOW
+""" Below the client area. """
+TREE_HITTEST_NOWHERE = wx.TREE_HITTEST_NOWHERE
+""" No item has been hit. """
+TREE_HITTEST_ONITEMBUTTON = wx.TREE_HITTEST_ONITEMBUTTON
+""" On the button associated with an item. """
+TREE_HITTEST_ONITEMICON = wx.TREE_HITTEST_ONITEMICON
+""" On the bitmap associated with an item. """
+TREE_HITTEST_ONITEMINDENT = wx.TREE_HITTEST_ONITEMINDENT
+""" On the indent associated with an item. """
+TREE_HITTEST_ONITEMLABEL = wx.TREE_HITTEST_ONITEMLABEL
+""" On the label (string) associated with an item. """
+TREE_HITTEST_ONITEMRIGHT = wx.TREE_HITTEST_ONITEMRIGHT
+""" On the right of the label associated with an item. """
+TREE_HITTEST_ONITEMSTATEICON = wx.TREE_HITTEST_ONITEMSTATEICON
+""" On the right of the label associated with an item. """
+TREE_HITTEST_TOLEFT = wx.TREE_HITTEST_TOLEFT
+""" On the left of an item. """
+TREE_HITTEST_TORIGHT = wx.TREE_HITTEST_TORIGHT
+""" On the right of an item. """
+TREE_HITTEST_ONITEMUPPERPART = wx.TREE_HITTEST_ONITEMUPPERPART
+""" On the upper part (first half) of the item. """
+TREE_HITTEST_ONITEMLOWERPART = wx.TREE_HITTEST_ONITEMLOWERPART
+""" On the lower part (second half) of the item. """
+TREE_HITTEST_ONITEMCHECKICON = 0x4000
+""" On the check icon, if present. """
+TREE_HITTEST_ONITEM = TREE_HITTEST_ONITEMICON | TREE_HITTEST_ONITEMLABEL | TREE_HITTEST_ONITEMCHECKICON
+""" Anywhere on the item. """
+
+TREE_ITEMTYPE_NORMAL = 0
+""" A normal item. """
+TREE_ITEMTYPE_CHECK = 1
+""" A checkbox-like item. """
+TREE_ITEMTYPE_RADIO = 2
+""" A radiobutton-like item. """
+
+# Background Image Style
+_StyleTile = 0
+_StyleStretch = 1
+
+# Windows Vista Colours
+_rgbSelectOuter = wx.Colour(170, 200, 245)
+_rgbSelectInner = wx.Colour(230, 250, 250)
+_rgbSelectTop = wx.Colour(210, 240, 250)
+_rgbSelectBottom = wx.Colour(185, 215, 250)
+_rgbNoFocusTop = wx.Colour(250, 250, 250)
+_rgbNoFocusBottom = wx.Colour(235, 235, 235)
+_rgbNoFocusOuter = wx.Colour(220, 220, 220)
+_rgbNoFocusInner = wx.Colour(245, 245, 245)
+
+# Flags for wx.RendererNative
+_CONTROL_EXPANDED = 8
+_CONTROL_CURRENT = 16
+
+
+# ----------------------------------------------------------------------------
+# CustomTreeCtrl events and binding for handling them
+# ----------------------------------------------------------------------------
+
+wxEVT_TREE_BEGIN_DRAG = wx.wxEVT_COMMAND_TREE_BEGIN_DRAG
+wxEVT_TREE_BEGIN_RDRAG = wx.wxEVT_COMMAND_TREE_BEGIN_RDRAG
+wxEVT_TREE_BEGIN_LABEL_EDIT = wx.wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT
+wxEVT_TREE_END_LABEL_EDIT = wx.wxEVT_COMMAND_TREE_END_LABEL_EDIT
+wxEVT_TREE_DELETE_ITEM = wx.wxEVT_COMMAND_TREE_DELETE_ITEM
+wxEVT_TREE_GET_INFO = wx.wxEVT_COMMAND_TREE_GET_INFO
+wxEVT_TREE_SET_INFO = wx.wxEVT_COMMAND_TREE_SET_INFO
+wxEVT_TREE_ITEM_EXPANDED = wx.wxEVT_COMMAND_TREE_ITEM_EXPANDED
+wxEVT_TREE_ITEM_EXPANDING = wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING
+wxEVT_TREE_ITEM_COLLAPSED = wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED
+wxEVT_TREE_ITEM_COLLAPSING = wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSING
+wxEVT_TREE_SEL_CHANGED = wx.wxEVT_COMMAND_TREE_SEL_CHANGED
+wxEVT_TREE_SEL_CHANGING = wx.wxEVT_COMMAND_TREE_SEL_CHANGING
+wxEVT_TREE_KEY_DOWN = wx.wxEVT_COMMAND_TREE_KEY_DOWN
+wxEVT_TREE_ITEM_ACTIVATED = wx.wxEVT_COMMAND_TREE_ITEM_ACTIVATED
+wxEVT_TREE_ITEM_RIGHT_CLICK = wx.wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK
+wxEVT_TREE_ITEM_MIDDLE_CLICK = wx.wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK
+wxEVT_TREE_END_DRAG = wx.wxEVT_COMMAND_TREE_END_DRAG
+wxEVT_TREE_STATE_IMAGE_CLICK = wx.wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK
+wxEVT_TREE_ITEM_GETTOOLTIP = wx.wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP
+wxEVT_TREE_ITEM_MENU = wx.wxEVT_COMMAND_TREE_ITEM_MENU
+wxEVT_TREE_ITEM_CHECKING = wx.NewEventType()
+wxEVT_TREE_ITEM_CHECKED = wx.NewEventType()
+wxEVT_TREE_ITEM_HYPERLINK = wx.NewEventType()
+
+EVT_TREE_BEGIN_DRAG = wx.EVT_TREE_BEGIN_DRAG
+""" Begin dragging with the left mouse button. """
+EVT_TREE_BEGIN_RDRAG = wx.EVT_TREE_BEGIN_RDRAG
+""" Begin dragging with the right mouse button. """
+EVT_TREE_BEGIN_LABEL_EDIT = wx.EVT_TREE_BEGIN_LABEL_EDIT
+""" Begin editing a label. This can be prevented by calling meth:~TreeEvent.Veto`. """
+EVT_TREE_END_LABEL_EDIT = wx.EVT_TREE_END_LABEL_EDIT
+""" End editing a label. This can be prevented by calling meth:~TreeEvent.Veto`. """
+EVT_TREE_DELETE_ITEM = wx.EVT_TREE_DELETE_ITEM
+""" Delete an item. """
+EVT_TREE_GET_INFO = wx.EVT_TREE_GET_INFO
+""" Request information from the application (not implemented in :class:`CustomTreeCtrl`). """
+EVT_TREE_SET_INFO = wx.EVT_TREE_SET_INFO
+""" Information is being supplied to the application (not implemented in :class:`CustomTreeCtrl`). """
+EVT_TREE_ITEM_EXPANDED = wx.EVT_TREE_ITEM_EXPANDED
+""" The item has been expanded. """
+EVT_TREE_ITEM_EXPANDING = wx.EVT_TREE_ITEM_EXPANDING
+""" The item is being expanded. This can be prevented by calling meth:~TreeEvent.Veto`. """
+EVT_TREE_ITEM_COLLAPSED = wx.EVT_TREE_ITEM_COLLAPSED
+""" The item has been collapsed. """
+EVT_TREE_ITEM_COLLAPSING = wx.EVT_TREE_ITEM_COLLAPSING
+""" The item is being collapsed. This can be prevented by calling meth:~TreeEvent.Veto`. """
+EVT_TREE_SEL_CHANGED = wx.EVT_TREE_SEL_CHANGED
+""" Selection has changed. """
+EVT_TREE_SEL_CHANGING = wx.EVT_TREE_SEL_CHANGING
+""" Selection is changing. This can be prevented by calling meth:~TreeEvent.Veto`. """
+EVT_TREE_KEY_DOWN = wx.EVT_TREE_KEY_DOWN
+""" A key has been pressed. """
+EVT_TREE_ITEM_ACTIVATED = wx.EVT_TREE_ITEM_ACTIVATED
+""" The item has been activated, i.e. chosen by double clicking it with mouse or from keyboard. """
+EVT_TREE_ITEM_RIGHT_CLICK = wx.EVT_TREE_ITEM_RIGHT_CLICK
+""" The user has clicked the item with the right mouse button. """
+EVT_TREE_ITEM_MIDDLE_CLICK = wx.EVT_TREE_ITEM_MIDDLE_CLICK
+""" The user has clicked the item with the middle mouse button (not implemented in :class:`CustomTreeCtrl`). """
+EVT_TREE_END_DRAG = wx.EVT_TREE_END_DRAG
+""" End dragging with the left or right mouse button. """
+EVT_TREE_STATE_IMAGE_CLICK = wx.EVT_TREE_STATE_IMAGE_CLICK
+""" The state image has been clicked (not implemented in :class:`CustomTreeCtrl`). """
+EVT_TREE_ITEM_GETTOOLTIP = wx.EVT_TREE_ITEM_GETTOOLTIP
+""" The opportunity to set the item tooltip is being given to the application (call `TreeEvent.SetToolTip`). """
+EVT_TREE_ITEM_MENU = wx.EVT_TREE_ITEM_MENU
+""" The context menu for the selected item has been requested, either by a right click or by using the menu key. """
+EVT_TREE_ITEM_CHECKING = wx.PyEventBinder(wxEVT_TREE_ITEM_CHECKING, 1)
+""" A checkbox or radiobox type item is being checked. """
+EVT_TREE_ITEM_CHECKED = wx.PyEventBinder(wxEVT_TREE_ITEM_CHECKED, 1)
+""" A checkbox or radiobox type item has been checked. """
+EVT_TREE_ITEM_HYPERLINK = wx.PyEventBinder(wxEVT_TREE_ITEM_HYPERLINK, 1)
+""" An hyperlink type item has been clicked. """
+
+
+# ----------------------------------------------------------------------------
+
+def MakeDisabledBitmap(original):
+ """
+ Creates a disabled-looking bitmap starting from the input one.
+
+ :param `original`: an instance of :class:`Bitmap` to be greyed-out.
+
+ :return: An instance of :class:`Bitmap`, containing a disabled-looking
+ representation of the original item image.
+ """
+
+ img = original.ConvertToImage()
+ return wx.BitmapFromImage(img.ConvertToGreyscale())
+
+# ----------------------------------------------------------------------------
+
+def DrawTreeItemButton(win, dc, rect, flags):
+ """
+ Draw the expanded/collapsed icon for a tree control item.
+
+ :param `win`: an instance of :class:`Window`;
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the client rectangle where to draw the tree item button;
+ :param integer `flags`: contains ``wx.CONTROL_EXPANDED`` bit for expanded tree items.
+
+ :note: This is a simple replacement of :meth:`RendererNative.DrawTreeItemButton`.
+
+ :note: This method is never used in wxPython versions newer than 2.6.2.1.
+ """
+
+ # white background
+ dc.SetPen(wx.GREY_PEN)
+ dc.SetBrush(wx.WHITE_BRUSH)
+ dc.DrawRectangleRect(rect)
+
+ # black lines
+ xMiddle = rect.x + rect.width/2
+ yMiddle = rect.y + rect.height/2
+
+ # half of the length of the horz lines in "-" and "+"
+ halfWidth = rect.width/2 - 2
+ dc.SetPen(wx.BLACK_PEN)
+ dc.DrawLine(xMiddle - halfWidth, yMiddle,
+ xMiddle + halfWidth + 1, yMiddle)
+
+ if not flags & _CONTROL_EXPANDED:
+
+ # turn "-" into "+"
+ halfHeight = rect.height/2 - 2
+ dc.DrawLine(xMiddle, yMiddle - halfHeight,
+ xMiddle, yMiddle + halfHeight + 1)
+
+# ----------------------------------------------------------------------------
+
+def EventFlagsToSelType(style, shiftDown=False, ctrlDown=False):
+ """
+ Translate the key or mouse event flag to the type of selection we
+ are dealing with.
+
+ :param integer `style`: the main :class:`CustomTreeCtrl` window style flag;
+ :param bool `shiftDown`: ``True`` if the ``Shift`` key is pressed, ``False`` otherwise;
+ :param bool `ctrlDown`: ``True`` if the ``Ctrl`` key is pressed, ``False`` otherwise;
+
+ :return: A 3-elements tuple, with the following elements:
+
+ - `is_multiple`: ``True`` if :class:`CustomTreeCtrl` has the ``TR_MULTIPLE`` flag set, ``False`` otherwise;
+ - `extended_select`: ``True`` if the ``Shift`` key is pressend and if :class:`CustomTreeCtrl` has the
+ ``TR_MULTIPLE`` flag set, ``False`` otherwise;
+ - `unselect_others`: ``True`` if the ``Ctrl`` key is pressend and if :class:`CustomTreeCtrl` has the
+ ``TR_MULTIPLE`` flag set, ``False`` otherwise.
+ """
+
+ is_multiple = (style & TR_MULTIPLE) != 0
+ extended_select = shiftDown and is_multiple
+ unselect_others = not (extended_select or (ctrlDown and is_multiple))
+
+ return is_multiple, extended_select, unselect_others
+
+# ----------------------------------------------------------------------------
+
+def ChopText(dc, text, max_size):
+ """
+ Chops the input `text` if its size does not fit in `max_size`, by cutting the
+ text and adding ellipsis at the end.
+
+ :param `dc`: a :class:`DC` device context;
+ :param `text`: the text to chop;
+ :param `max_size`: the maximum size in which the text should fit.
+
+ :note: This method is used exclusively when :class:`CustomTreeCtrl` has the ``TR_ELLIPSIZE_LONG_ITEMS``
+ style set.
+
+ .. versionadded:: 0.9.3
+ """
+
+ # first check if the text fits with no problems
+ x, y, dummy = dc.GetMultiLineTextExtent(text)
+
+ if x <= max_size:
+ return text
+
+ textLen = len(text)
+ last_good_length = 0
+
+ for i in xrange(textLen, -1, -1):
+ s = text[0:i]
+ s += "..."
+
+ x, y = dc.GetTextExtent(s)
+ last_good_length = i
+
+ if x < max_size:
+ break
+
+ ret = text[0:last_good_length] + "..."
+ return ret
+
+
+#---------------------------------------------------------------------------
+# DragImage Implementation
+# This Class Handles The Creation Of A Custom Image In Case Of Item Drag
+# And Drop.
+#---------------------------------------------------------------------------
+
+class DragImage(wx.DragImage):
+ """
+ This class handles the creation of a custom image in case of item drag
+ and drop.
+ """
+
+ def __init__(self, treeCtrl, item):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `treeCtrl`: the parent :class:`CustomTreeCtrl`;
+ :param `item`: one of the tree control item (an instance of :class:`GenericTreeItem`).
+ """
+
+ text = item.GetText()
+ font = item.Attr().GetFont()
+ colour = item.Attr().GetTextColour()
+ if not colour:
+ colour = wx.BLACK
+ if not font:
+ font = treeCtrl._normalFont
+
+ backcolour = treeCtrl.GetBackgroundColour()
+ r, g, b = int(backcolour.Red()), int(backcolour.Green()), int(backcolour.Blue())
+ backcolour = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
+ backcolour = wx.Colour(backcolour[0], backcolour[1], backcolour[2])
+ self._backgroundColour = backcolour
+
+ tempdc = wx.ClientDC(treeCtrl)
+ tempdc.SetFont(font)
+ width, height, dummy = tempdc.GetMultiLineTextExtent(text + "M")
+
+ image = item.GetCurrentImage()
+
+ image_w, image_h = 0, 0
+ wcheck, hcheck = 0, 0
+ itemcheck = None
+ itemimage = None
+ ximagepos = 0
+ yimagepos = 0
+ xcheckpos = 0
+ ycheckpos = 0
+
+ if image != _NO_IMAGE:
+ if treeCtrl._imageListNormal:
+ image_w, image_h = treeCtrl._imageListNormal.GetSize(image)
+ image_w += 4
+ itemimage = treeCtrl._imageListNormal.GetBitmap(image)
+
+ checkimage = item.GetCurrentCheckedImage()
+
+ if checkimage is not None:
+ if treeCtrl._imageListCheck:
+ wcheck, hcheck = treeCtrl._imageListCheck.GetSize(checkimage)
+ wcheck += 4
+ itemcheck = treeCtrl._imageListCheck.GetBitmap(checkimage)
+
+ total_h = max(hcheck, height)
+ total_h = max(image_h, total_h)
+
+ if image_w:
+ ximagepos = wcheck
+ yimagepos = ((total_h > image_h) and [(total_h-image_h)/2] or [0])[0]
+
+ if checkimage is not None:
+ xcheckpos = 2
+ ycheckpos = ((total_h > image_h) and [(total_h-image_h)/2] or [0])[0] + 2
+
+ extraH = ((total_h > height) and [(total_h - height)/2] or [0])[0]
+
+ xtextpos = wcheck + image_w
+ ytextpos = extraH
+
+ total_h = max(image_h, hcheck)
+ total_h = max(total_h, height)
+
+ if total_h < 30:
+ total_h += 2 # at least 2 pixels
+ else:
+ total_h += total_h/10 # otherwise 10% extra spacing
+
+ total_w = image_w + wcheck + width
+
+ self._total_w = total_w
+ self._total_h = total_h
+ self._itemimage = itemimage
+ self._itemcheck = itemcheck
+ self._text = text
+ self._colour = colour
+ self._font = font
+ self._xtextpos = xtextpos
+ self._ytextpos = ytextpos
+ self._ximagepos = ximagepos
+ self._yimagepos = yimagepos
+ self._xcheckpos = xcheckpos
+ self._ycheckpos = ycheckpos
+ self._textwidth = width
+ self._textheight = height
+ self._extraH = extraH
+
+ self._bitmap = self.CreateBitmap()
+
+ wx.DragImage.__init__(self, self._bitmap)
+
+
+ def CreateBitmap(self):
+ """
+ Actually creates the drag and drop bitmap for :class:`DragImage`.
+
+ :return: An instance of :class:`DragImage`, a close representation of the item's
+ appearance (i.e., a screenshot of the item).
+ """
+
+ memory = wx.MemoryDC()
+
+ bitmap = wx.EmptyBitmap(self._total_w, self._total_h)
+ memory.SelectObject(bitmap)
+
+ if wx.Platform == '__WXMAC__':
+ memory.SetBackground(wx.TRANSPARENT_BRUSH)
+ else:
+ memory.SetBackground(wx.Brush(self._backgroundColour))
+ memory.SetBackgroundMode(wx.TRANSPARENT)
+ memory.SetFont(self._font)
+ memory.SetTextForeground(self._colour)
+ memory.Clear()
+
+ if self._itemimage:
+ memory.DrawBitmap(self._itemimage, self._ximagepos, self._yimagepos, True)
+
+ if self._itemcheck:
+ memory.DrawBitmap(self._itemcheck, self._xcheckpos, self._ycheckpos, True)
+
+ textrect = wx.Rect(self._xtextpos, self._ytextpos+self._extraH, self._textwidth, self._textheight)
+ memory.DrawLabel(self._text, textrect)
+
+ memory.SelectObject(wx.NullBitmap)
+
+ # Gtk and Windows unfortunatly don't do so well with transparent
+ # drawing so this hack corrects the image to have a transparent
+ # background.
+ if wx.Platform != '__WXMAC__':
+ timg = bitmap.ConvertToImage()
+ if not timg.HasAlpha():
+ timg.InitAlpha()
+ for y in xrange(timg.GetHeight()):
+ for x in xrange(timg.GetWidth()):
+ pix = wx.Colour(timg.GetRed(x, y),
+ timg.GetGreen(x, y),
+ timg.GetBlue(x, y))
+ if pix == self._backgroundColour:
+ timg.SetAlpha(x, y, 0)
+ bitmap = timg.ConvertToBitmap()
+ return bitmap
+
+
+# ----------------------------------------------------------------------------
+# TreeItemAttr: a structure containing the visual attributes of an item
+# ----------------------------------------------------------------------------
+
+class TreeItemAttr(object):
+ """
+ Creates the item attributes (text colour, background colour and font).
+
+ :note: This class is inspired by the wxWidgets generic implementation of :class:`TreeItemAttr`.
+ """
+
+ def __init__(self, colText=wx.NullColour, colBack=wx.NullColour, colBorder=wx.NullColour,font=wx.NullFont):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `colText`: the text colour, an instance of :class:`Colour`;
+ :param `colBack`: the tree item background colour, an instance of :class:`Colour`;
+ :param `colBorder`: the tree item border colour, an instance of :class:`Colour`;
+ :param `font`: the tree item font, an instance of :class:`Font`.
+ """
+
+ self._colText = colText
+ self._colBack = colBack
+ self._colBorder = colBorder
+ self._font = font
+
+ # setters
+ def SetTextColour(self, colText):
+ """
+ Sets the text colour attribute.
+
+ :param `colText`: an instance of :class:`Colour`.
+ """
+
+ self._colText = colText
+
+
+ def SetBackgroundColour(self, colBack):
+ """
+ Sets the item background colour attribute.
+
+ :param `colBack`: an instance of :class:`Colour`.
+ """
+
+ self._colBack = colBack
+
+
+ def SetBorderColour(self,colBorder):
+ """
+ Sets the item border colour attribute.
+
+ :param `colBack`: an instance of :class:`Colour`.
+
+ .. versionadded:: 0.9.6
+ """
+
+ self._colBorder = colBorder
+
+
+ def SetFont(self, font):
+ """
+ Sets the item font attribute.
+
+ :param `font`: an instance of :class:`Font`.
+ """
+
+ self._font = font
+
+
+ # accessors
+ def HasTextColour(self):
+ """
+ Returns whether the attribute has text colour.
+
+ :return: ``True`` if the text colour attribute has been set, ``False`` otherwise.
+ """
+
+ return self._colText != wx.NullColour
+
+
+ def HasBackgroundColour(self):
+ """
+ Returns whether the attribute has background colour.
+
+ :return: ``True`` if the background colour attribute has been set, ``False`` otherwise.
+ """
+
+ return self._colBack != wx.NullColour
+
+
+ def HasBorderColour(self):
+ """
+ Returns whether the attribute has border colour.
+
+ :return: ``True`` if the border colour attribute has been set, ``False`` otherwise.
+
+ .. versionadded:: 0.9.6
+ """
+
+ return self._colBorder != wx.NullColour
+
+
+ def HasFont(self):
+ """
+ Returns whether the attribute has font.
+
+ :return: ``True`` if the font attribute has been set, ``False`` otherwise.
+ """
+
+ return self._font != wx.NullFont
+
+
+ # getters
+ def GetTextColour(self):
+ """
+ Returns the attribute text colour.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._colText
+
+
+ def GetBackgroundColour(self):
+ """
+ Returns the attribute background colour.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._colBack
+
+
+ def GetBorderColour(self):
+ """
+ Returns the attribute border colour.
+
+ :return: An instance of :class:`Colour`.
+
+ .. versionadded:: 0.9.6
+ """
+
+ return self._colBorder
+
+
+ def GetFont(self):
+ """
+ Returns the attribute font.
+
+ :return: An instance of :class:`Font`.
+ """
+
+ return self._font
+
+
+# ----------------------------------------------------------------------------
+# CommandTreeEvent Is A Special Subclassing Of wx.PyCommandEvent
+#
+# NB: Note That Not All The Accessors Make Sense For All The Events, See The
+# Event Description Below.
+# ----------------------------------------------------------------------------
+
+class CommandTreeEvent(wx.PyCommandEvent):
+ """
+ :class:`CommandTreeEvent` is a special subclassing of :class:`PyCommandEvent`.
+
+ :note: Not all the accessors make sense for all the events, see the event description for every method in this class.
+ """
+
+ def __init__(self, evtType, evtId, item=None, evtKey=None, point=None,
+ label=None, **kwargs):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param integer `evtType`: the event type;
+ :param integer `evtId`: the event identifier;
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param integer `evtKey`: a character ordinal;
+ :param `point`: an instance of :class:`Point`;
+ :param string `label`: a :class:`GenericTreeItem` text label.
+ """
+
+ wx.PyCommandEvent.__init__(self, evtType, evtId, **kwargs)
+ self._item = item
+ self._evtKey = evtKey
+ self._pointDrag = point
+ self._label = label
+
+
+ def GetItem(self):
+ """
+ Gets the item on which the operation was performed or the newly selected
+ item for ``EVT_TREE_SEL_CHANGED`` and ``EVT_TREE_SEL_CHANGING`` events.
+
+ :return: An instance of :class:`GenericTreeItem`.
+ """
+
+ return self._item
+
+
+ def SetItem(self, item):
+ """
+ Sets the item on which the operation was performed or the newly selected
+ item for ``EVT_TREE_SEL_CHANGED`` and ``EVT_TREE_SEL_CHANGING`` events.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ self._item = item
+
+
+ def GetOldItem(self):
+ """
+ Returns the previously selected item for ``EVT_TREE_SEL_CHANGED`` and
+ ``EVT_TREE_SEL_CHANGING`` events.
+
+ :return: An instance of :class:`GenericTreeItem`.
+ """
+
+ return self._itemOld
+
+
+ def SetOldItem(self, item):
+ """
+ Returns the previously selected item for ``EVT_TREE_SEL_CHANGED`` and
+ ``EVT_TREE_SEL_CHANGING`` events.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ self._itemOld = item
+
+
+ def GetPoint(self):
+ """
+ Returns the point where the mouse was when the drag operation started
+ (for ``EVT_TREE_BEGIN_DRAG`` and ``EVT_TREE_BEGIN_RDRAG`` events only)
+ or the click position.
+
+ :return: An instance of :class:`Point`.
+ """
+
+ return self._pointDrag
+
+
+ def SetPoint(self, pt):
+ """
+ Sets the point where the mouse was when the drag operation started
+ (for ``EVT_TREE_BEGIN_DRAG`` and ``EVT_TREE_BEGIN_RDRAG`` events only)
+ or the click position.
+
+ :param `pt`: an instance of :class:`Point`.
+ """
+
+ self._pointDrag = pt
+
+
+ def GetKeyEvent(self):
+ """
+ Returns the keyboard data (for ``EVT_TREE_KEY_DOWN`` event only).
+
+ :return: An instance of :class:`KeyEvent`.
+ """
+
+ return self._evtKey
+
+
+ def GetKeyCode(self):
+ """
+ Returns the virtual key code. ASCII events return normal ASCII values, while
+ non-ASCII events return values such as ``wx.WXK_LEFT`` for the left cursor key.
+
+ This method is for ``EVT_TREE_KEY_DOWN`` events only.
+
+ :return: An integer representing the virtual key code.
+
+ :note: In Unicode build, the returned value is meaningful only if the user entered
+ a character that can be represented in current locale's default charset. You can
+ obtain the corresponding Unicode character using `GetUnicodeKey`.
+ """
+
+ return self._evtKey.GetKeyCode()
+
+
+ def SetKeyEvent(self, event):
+ """
+ Sets the keyboard data (for ``EVT_TREE_KEY_DOWN`` event only).
+
+ :param `event`: a :class:`CommandTreeEvent` event to be processed.
+ """
+
+ self._evtKey = event
+
+
+ def GetLabel(self):
+ """
+ Returns the item text (for ``EVT_TREE_BEGIN_LABEL_EDIT`` and
+ ``EVT_TREE_END_LABEL_EDIT`` events only).
+
+ :return: A string containing the item text.
+ """
+
+ return self._label
+
+
+ def SetLabel(self, label):
+ """
+ Sets the item text (for ``EVT_TREE_BEGIN_LABEL_EDIT`` and
+ ``EVT_TREE_END_LABEL_EDIT`` events only).
+
+ :param string `label`: a string containing the new item text.
+ """
+
+ self._label = label
+
+
+ def IsEditCancelled(self):
+ """
+ Returns the edit cancel flag (for ``EVT_TREE_BEGIN_LABEL_EDIT`` and
+ ``EVT_TREE_END_LABEL_EDIT`` events only).
+
+ :return: ``True`` is the item editing has been cancelled, ``False`` otherwise.
+ """
+
+ return self._editCancelled
+
+
+ def SetEditCanceled(self, editCancelled):
+ """
+ Sets the edit cancel flag (for ``EVT_TREE_BEGIN_LABEL_EDIT`` and
+ ``EVT_TREE_END_LABEL_EDIT`` events only).
+
+ :param bool `editCancelled`: ``True`` to cancel the editing, ``False`` otherwise.
+ """
+
+ self._editCancelled = editCancelled
+
+
+ def SetToolTip(self, toolTip):
+ """
+ Sets the tooltip for the item (for ``EVT_TREE_ITEM_GETTOOLTIP`` events).
+
+ :param string `tooltip`: a string representing the item tooltip.
+ """
+
+ self._label = toolTip
+
+
+ def GetToolTip(self):
+ """
+ Returns the tooltip for the item (for ``EVT_TREE_ITEM_GETTOOLTIP`` events).
+
+ :return: A string containing the item tooltip.
+ """
+
+ return self._label
+
+
+# ----------------------------------------------------------------------------
+# TreeEvent is a special class for all events associated with tree controls
+#
+# NB: note that not all accessors make sense for all events, see the event
+# descriptions below
+# ----------------------------------------------------------------------------
+
+class TreeEvent(CommandTreeEvent):
+ """
+ :class:`CommandTreeEvent` is a special class for all events associated with tree controls.
+
+ :note: Not all accessors make sense for all events, see the event descriptions below.
+ """
+ def __init__(self, evtType, evtId, item=None, evtKey=None, point=None,
+ label=None, **kwargs):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param integer `evtType`: the event type;
+ :param integer `evtId`: the event identifier;
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param integer `evtKey`: a character ordinal;
+ :param `point`: an instance of :class:`Point`;
+ :param string `label`: a :class:`GenericTreeItem` text label.
+ """
+
+ CommandTreeEvent.__init__(self, evtType, evtId, item, evtKey, point, label, **kwargs)
+ self.notify = wx.NotifyEvent(evtType, evtId)
+
+
+ def GetNotifyEvent(self):
+ """
+ Returns the actual :class:`NotifyEvent`.
+
+ :return: An instance of :class:`NotifyEvent`.
+ """
+
+ return self.notify
+
+
+ def IsAllowed(self):
+ """
+ Returns ``True`` if the change is allowed (:meth:`~TreeEvent.Veto` hasn't been called) or
+ ``False`` otherwise (if it was).
+ """
+
+ return self.notify.IsAllowed()
+
+
+ def Veto(self):
+ """
+ Prevents the change announced by this event from happening.
+
+ :note: It is in general a good idea to notify the user about the reasons
+ for vetoing the change because otherwise the applications behaviour (which
+ just refuses to do what the user wants) might be quite surprising.
+ """
+
+ self.notify.Veto()
+
+
+ def Allow(self):
+ """
+ This is the opposite of :meth:`~TreeEvent.Veto`: it explicitly allows the event to be processed.
+ For most events it is not necessary to call this method as the events are
+ allowed anyhow but some are forbidden by default (this will be mentioned
+ in the corresponding event description).
+ """
+
+ self.notify.Allow()
+
+
+# -----------------------------------------------------------------------------
+# Auxiliary Classes: TreeEditTimer
+# -----------------------------------------------------------------------------
+
+class TreeEditTimer(wx.Timer):
+ """ Timer used for enabling in-place edit."""
+
+ def __init__(self, owner):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `owner`: the :class:`Timer` owner (an instance of :class:`CustomTreeCtrl`).
+ """
+
+ wx.Timer.__init__(self)
+ self._owner = owner
+
+
+ def Notify(self):
+ """ The timer has expired, starts the item editing. """
+
+ self._owner.OnEditTimer()
+
+
+# -----------------------------------------------------------------------------
+# Auxiliary Classes: TreeTextCtrl
+# This Is The Temporary ExpandoTextCtrl Created When You Edit The Text Of An Item
+# -----------------------------------------------------------------------------
+
+class TreeTextCtrl(ExpandoTextCtrl):
+ """
+ Control used for in-place edit.
+
+ This is a subclass of :class:`lib.expando.ExpandoTextCtrl` as :class:`CustomTreeCtrl` supports multiline
+ text items.
+
+ :note: To add a newline character in a multiline item, press ``Shift`` + ``Enter`` as the ``Enter``
+ key alone is consumed by :class:`CustomTreeCtrl` to finish the editing and ``Ctrl`` + ``Enter`` is
+ consumed by the platform for tab navigation.
+ """
+
+ def __init__(self, owner, item=None):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `owner`: the control parent (an instance of :class:`CustomTreeCtrl`);
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :raise: `Exception` when the item has an associated image but the parent
+ :class:`CustomTreeCtrl` does not have a :class:`ImageList` assigned.
+ """
+
+ self._owner = owner
+ self._itemEdited = item
+ self._startValue = item.GetText()
+ self._finished = False
+ self._aboutToFinish = False
+ self._currentValue = self._startValue
+
+ w = self._itemEdited.GetWidth()
+ h = self._itemEdited.GetHeight()
+
+ wnd = self._itemEdited.GetWindow()
+ if wnd:
+ w = w - self._itemEdited.GetWindowSize()[0]
+ h = 0
+
+ x, y = self._owner.CalcScrolledPosition(item.GetX(), item.GetY())
+
+ image_h = 0
+ image_w = 0
+
+ image = item.GetCurrentImage()
+
+ if image != _NO_IMAGE:
+
+ if self._owner._imageListNormal:
+ image_w, image_h = self._owner._imageListNormal.GetSize(image)
+ image_w += 4
+
+ else:
+
+ raise Exception("\n ERROR: You Must Create An Image List To Use Images!")
+
+ checkimage = item.GetCurrentCheckedImage()
+
+ if checkimage is not None:
+ wcheck, hcheck = self._owner._imageListCheck.GetSize(checkimage)
+ wcheck += 4
+ else:
+ wcheck = hcheck = 0
+
+ if wnd:
+ h = max(hcheck, image_h)
+ dc = wx.ClientDC(self._owner)
+ h = max(h, dc.GetTextExtent("Aq")[1])
+ h = h + 2
+
+ # FIXME: what are all these hardcoded 4, 8 and 11s really?
+ x += image_w + wcheck
+ w -= image_w + 4 + wcheck
+
+ expandoStyle = wx.WANTS_CHARS
+ if wx.Platform in ["__WXGTK__", "__WXMAC__"]:
+ expandoStyle |= wx.SIMPLE_BORDER
+ xSize, ySize = w + 25, h
+ else:
+ expandoStyle |= wx.SUNKEN_BORDER
+ xSize, ySize = w + 25, h+2
+
+ ExpandoTextCtrl.__init__(self, self._owner, wx.ID_ANY, self._startValue,
+ wx.Point(x - 4, y), wx.Size(xSize, ySize),
+ expandoStyle)
+
+ if wx.Platform == "__WXMAC__":
+ self.SetFont(owner.GetFont())
+ bs = self.GetBestSize()
+ self.SetSize((-1, bs.height))
+
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+
+ def AcceptChanges(self):
+ """
+ Accepts/rejects the changes made by the user.
+
+ :return: ``True`` if the changes to the item text have been accepted, ``False``
+ if they have been rejected (i.e., vetoed by the user).
+ """
+
+ value = self.GetValue()
+
+ if value == self._startValue:
+ # nothing changed, always accept
+ # when an item remains unchanged, the owner
+ # needs to be notified that the user decided
+ # not to change the tree item label, and that
+ # the edit has been cancelled
+ self._owner.OnCancelEdit(self._itemEdited)
+ return True
+
+ if not self._owner.OnAcceptEdit(self._itemEdited, value):
+ # vetoed by the user
+ return False
+
+ # accepted, do rename the item
+ self._owner.SetItemText(self._itemEdited, value)
+
+ return True
+
+
+ def Finish(self):
+ """ Finish editing. """
+
+ if not self._finished:
+ self._finished = True
+ self._owner.SetFocusIgnoringChildren()
+ self._owner.ResetEditControl()
+
+
+ def OnChar(self, event):
+ """
+ Handles the ``wx.EVT_CHAR`` event for :class:`TreeTextCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ keycode = event.GetKeyCode()
+ shiftDown = event.ShiftDown()
+
+ if keycode in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
+ if shiftDown:
+ event.Skip()
+ else:
+ self._aboutToFinish = True
+ self.SetValue(self._currentValue)
+ # Notify the owner about the changes
+ self.AcceptChanges()
+ # Even if vetoed, close the control (consistent with MSW)
+ wx.CallAfter(self.Finish)
+
+ elif keycode == wx.WXK_ESCAPE:
+ self.StopEditing()
+
+ else:
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` event for :class:`TreeTextCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if not self._finished:
+
+ # auto-grow the textctrl:
+ parentSize = self._owner.GetSize()
+ myPos = self.GetPosition()
+ mySize = self.GetSize()
+
+ dc = wx.ClientDC(self)
+ sx, sy, dummy = dc.GetMultiLineTextExtent(self.GetValue() + "M")
+
+ if myPos.x + sx > parentSize.x:
+ sx = parentSize.x - myPos.x
+ if mySize.x > sx:
+ sx = mySize.x
+
+ self.SetSize((sx, -1))
+ self._currentValue = self.GetValue()
+
+ event.Skip()
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`TreeTextCtrl`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if not self._finished and not self._aboutToFinish:
+
+ # We must finish regardless of success, otherwise we'll get
+ # focus problems:
+
+ if not self.AcceptChanges():
+ self._owner.OnCancelEdit(self._itemEdited)
+
+ # We must let the native text control handle focus, too, otherwise
+ # it could have problems with the cursor (e.g., in wxGTK).
+ event.Skip()
+
+
+ def StopEditing(self):
+ """ Suddenly stops the editing. """
+
+ self._owner.OnCancelEdit(self._itemEdited)
+ self.Finish()
+
+
+ def item(self):
+ """
+ Returns the item currently edited.
+
+ :return: An instance of :class:`GenericTreeItem`.
+ """
+
+ return self._itemEdited
+
+
+# -----------------------------------------------------------------------------
+# Auxiliary Classes: TreeFindTimer
+# Timer Used To Clear CustomTreeCtrl._findPrefix If No Key Was Pressed For A
+# Sufficiently Long Time.
+# -----------------------------------------------------------------------------
+
+class TreeFindTimer(wx.Timer):
+ """
+ Timer used to clear the :class:`CustomTreeCtrl` `_findPrefix` attribute if no
+ key was pressed for a sufficiently long time.
+ """
+
+ def __init__(self, owner):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `owner`: the :class:`Timer` owner (an instance of :class:`CustomTreeCtrl`).
+ """
+
+ wx.Timer.__init__(self)
+ self._owner = owner
+
+
+ def Notify(self):
+ """ The timer has expired, clear the `_findPrefix` attribute in :class:`CustomTreeCtrl`. """
+
+ self._owner._findPrefix = ""
+
+
+# -----------------------------------------------------------------------------
+# GenericTreeItem Implementation.
+# This Class Holds All The Information And Methods For Every Single Item In
+# CustomTreeCtrl.
+# -----------------------------------------------------------------------------
+
+class GenericTreeItem(object):
+ """
+ This class holds all the information and methods for every single item in
+ :class:`CustomTreeCtrl`. This is a generic implementation of :class:`TreeItem`.
+ """
+
+ def __init__(self, parent, text="", ct_type=0, wnd=None, image=-1, selImage=-1, data=None, separator=False):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `parent`: the tree item parent, an instance of :class:`GenericTreeItem` (may
+ be ``None`` for root items);
+ :param string `text`: the tree item text;
+ :param integer `ct_type`: the tree item kind. May be one of the following integers:
+
+ =============== =========================================
+ `ct_type` Value Description
+ =============== =========================================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== =========================================
+
+ :param `wnd`: if not ``None``, a non-toplevel window to be displayed next to
+ the item, an instance of :class:`Window`;
+ :param integer `image`: an index within the normal image list specifying the image to
+ use for the item in unselected state;
+ :param integer `selImage`: an index within the normal image list specifying the image to
+ use for the item in selected state; if `image` > -1 and `selImage` is -1, the
+ same image is used for both selected and unselected items;
+ :param object `data`: associate the given Python object `data` with the item;
+ :param bool `separator`: ``True`` if the item is a separator, ``False`` otherwise.
+
+ :note: Regarding radiobutton-type items (with `ct_type` = 2), the following
+ approach is used:
+
+ - All peer-nodes that are radiobuttons will be mutually exclusive. In other words,
+ only one of a set of radiobuttons that share a common parent can be checked at
+ once. If a radiobutton node becomes checked, then all of its peer radiobuttons
+ must be unchecked.
+ - If a radiobutton node becomes unchecked, then all of its child nodes will become
+ inactive.
+
+
+ :note: Separator items should not have children, labels, data or an associated window.
+ Other issues/features associated to separator items:
+
+ - You can change the color of individual separators by using :meth:`CustomTreeCtrl.SetItemTextColour() <customtreectrl.CustomTreeCtrl.SetItemTextColour>`,
+ or you can use :meth:`CustomTreeCtrl.SetSeparatorColour() <customtreectrl.CustomTreeCtrl.SetSeparatorColour>` to change the color of all
+ separators. The default separator colour is that returned by `SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)`;
+ - Separators can be selected just like any other tree item;
+ - Separators cannot have text;
+ - Separators cannot have children;
+ - Separators cannot be edited via the ``EVT_TREE_BEGIN_LABEL_EDIT`` event.
+
+ """
+
+ # since there can be very many of these, we save size by chosing
+ # the smallest representation for the elements and by ordering
+ # the members to avoid padding.
+ self._text = text # label to be rendered for item
+ self._data = data # user-provided data
+
+ self._children = [] # list of children
+ self._parent = parent # parent of this item
+
+ self._attr = None # attributes???
+
+ self._separator = separator
+
+ # tree ctrl images for the normal, selected, expanded and
+ # expanded+selected states
+ self._images = [-1, -1, -1, -1]
+ self._images[TreeItemIcon_Normal] = image
+ self._images[TreeItemIcon_Selected] = selImage
+ self._images[TreeItemIcon_Expanded] = _NO_IMAGE
+ self._images[TreeItemIcon_SelectedExpanded] = _NO_IMAGE
+
+ self._checkedimages = [None, None, None, None, None]
+ self._leftimage = _NO_IMAGE
+
+ self._x = 0 # (virtual) offset from top
+ self._y = 0 # (virtual) offset from left
+ self._width = 0 # width of this item
+ self._height = 0 # height of this item
+
+ self._isCollapsed = True
+ self._hasHilight = False # same as focused
+ self._hasPlus = False # used for item which doesn't have
+ # children but has a [+] button
+ self._isBold = False # render the label in bold font
+ self._isItalic = False # render the label in italic font
+ self._ownsAttr = False # delete attribute when done
+ self._type = ct_type # item type: 0=normal, 1=check, 2=radio
+ self._is3State = False # true for 3-state checkbox items
+ self._checked = 0 # only meaningful for check and radio items
+ self._enabled = True # flag to enable/disable an item
+ self._hypertext = False # indicates if the item is hypertext
+ self._visited = False # visited state for an hypertext item
+
+ if self._type > 0:
+ # do not construct the array for normal items
+ self._checkedimages[TreeItemIcon_Checked] = 0
+ self._checkedimages[TreeItemIcon_NotChecked] = 1
+ self._checkedimages[TreeItemIcon_Undetermined] = 2
+ self._checkedimages[TreeItemIcon_Flagged] = 3
+ self._checkedimages[TreeItemIcon_NotFlagged] = 4
+
+ if parent:
+ if parent.GetType() == 2 and not parent.IsChecked():
+ # if the node parent is a radio not enabled, we are disabled
+ self._enabled = False
+
+ self._wnd = wnd # are we holding a window?
+
+ if wnd:
+ self.SetWindow(wnd)
+
+
+ def IsOk(self):
+ """
+ Returns whether the item is ok or not.
+
+ :note: This method always returns ``True``, it has been added for
+ backward compatibility with the wxWidgets C++ implementation.
+ """
+
+ return True
+
+
+ def IsSeparator(self):
+ """
+ Returns whether the item is meant to be an horizontal line separator or not.
+
+ :return: ``True`` if this item is a separator, ``False`` otherwise.
+ """
+
+ return self._separator
+
+
+ def GetChildren(self):
+ """
+ Returns the item's children.
+
+ :return: A Python list containing instances of :class:`GenericTreeItem`, representing
+ this item's children.
+ """
+
+ return self._children
+
+
+ def GetText(self):
+ """
+ Returns the item text.
+
+ :return: A string containing the item text.
+ """
+
+ return self._text
+
+
+ def GetImage(self, which=TreeItemIcon_Normal):
+ """
+ Returns the item image for a particular item state.
+
+ :param integer `which`: can be one of the following bits:
+
+ ================================= ========================
+ Item State Description
+ ================================= ========================
+ ``TreeItemIcon_Normal`` To get the normal item image
+ ``TreeItemIcon_Selected`` To get the selected item image (i.e. the image which is shown when the item is currently selected)
+ ``TreeItemIcon_Expanded`` To get the expanded image (this only makes sense for items which have children - then this image is shown when the item is expanded and the normal image is shown when it is collapsed)
+ ``TreeItemIcon_SelectedExpanded`` To get the selected expanded image (which is shown when an expanded item is currently selected)
+ ================================= ========================
+
+ :return: An integer index that can be used to retrieve the item image inside
+ a :class:`ImageList`.
+ """
+
+ return self._images[which]
+
+
+ def GetCheckedImage(self, which=TreeItemIcon_Checked):
+ """
+ Returns the item check image.
+
+ :param integer `which`: can be one of the following bits:
+
+ ================================= ========================
+ Item State Description
+ ================================= ========================
+ ``TreeItemIcon_Checked`` To get the checkbox checked item image
+ ``TreeItemIcon_NotChecked`` To get the checkbox unchecked item image
+ ``TreeItemIcon_Undetermined`` To get the checkbox undetermined state item image
+ ``TreeItemIcon_Flagged`` To get the radiobutton checked image
+ ``TreeItemIcon_NotFlagged`` To get the radiobutton unchecked image
+ ================================= ========================
+
+ :return: An integer index that can be used to retrieve the item check image inside
+ a :class:`ImageList`.
+
+ :note: This method is meaningful only for radio & check items.
+ """
+
+ return self._checkedimages[which]
+
+
+ def GetLeftImage(self):
+ """
+ Returns the leftmost image associated to this item, i.e. the image on the
+ leftmost part of the client area of :class:`CustomTreeCtrl`.
+
+ :return: An integer index that can be used to retrieve the item leftmost image inside
+ a :class:`ImageList`.
+ """
+
+ return self._leftimage
+
+
+ def GetData(self):
+ """
+ Returns the data associated to this item.
+
+ :return: A Python object representing the item data, or ``None`` if no data
+ has been assigned to this item.
+ """
+
+ return self._data
+
+
+ def SetImage(self, image, which):
+ """
+ Sets the item image.
+
+ :param integer `image`: an index within the normal image list specifying the image to use;
+ :param integer `which`: the image kind.
+
+ :see: :meth:`~GenericTreeItem.GetImage` for a description of the `which` parameter.
+ """
+
+ self._images[which] = image
+
+
+ def SetLeftImage(self, image):
+ """
+ Sets the item leftmost image, i.e. the image associated to the item on the leftmost
+ part of the :class:`CustomTreeCtrl` client area.
+
+ :param integer `image`: an index within the left image list specifying the image to
+ use for the item in the leftmost part of the client area.
+ """
+
+ self._leftimage = image
+
+
+ def SetData(self, data):
+ """
+ Sets the data associated to this item.
+
+ :param object `data`: can be any Python object.
+ """
+
+ self._data = data
+
+
+ def SetHasPlus(self, has=True):
+ """
+ Sets whether an item has the 'plus' button.
+
+ :param bool `has`: ``True`` to set the 'plus' button on the item, ``False`` otherwise.
+ """
+
+ self._hasPlus = has
+
+
+ def SetBold(self, bold):
+ """
+ Sets the item font bold.
+
+ :parameter bool `bold`: ``True`` to have a bold font item, ``False`` otherwise.
+ """
+
+ self._isBold = bold
+
+
+ def SetItalic(self, italic):
+ """
+ Sets the item font italic.
+
+ :parameter bool `italic`: ``True`` to have an italic font item, ``False`` otherwise.
+ """
+
+ self._isItalic = italic
+
+
+ def GetX(self):
+ """ Returns the `x` position on an item, in logical coordinates. """
+
+ return self._x
+
+
+ def GetY(self):
+ """ Returns the `y` position on an item, in logical coordinates. """
+
+ return self._y
+
+
+ def SetX(self, x):
+ """
+ Sets the `x` position on an item, in logical coordinates.
+
+ :param integer `x`: an integer specifying the x position of the item.
+ """
+
+ self._x = x
+
+
+ def SetY(self, y):
+ """
+ Sets the `y` position on an item, in logical coordinates.
+
+ :param integer `y`: an integer specifying the y position of the item.
+ """
+
+ self._y = y
+
+
+ def GetHeight(self):
+ """ Returns the height of the item, in pixels. """
+
+ return self._height
+
+
+ def GetWidth(self):
+ """ Returns the width of the item, in pixels. """
+
+ return self._width
+
+
+ def SetHeight(self, h):
+ """
+ Sets the item's height.
+
+ :param integer `h`: an integer specifying the item's height, in pixels.
+ """
+
+ self._height = h
+
+
+ def SetWidth(self, w):
+ """
+ Sets the item's width.
+
+ :param integer `w`: an integer specifying the item's width, in pixels.
+ """
+
+ self._width = w
+
+
+ def SetWindow(self, wnd):
+ """
+ Sets the window associated to the item.
+
+ :param `wnd`: a non-toplevel window to be displayed next to the item, any
+ subclass of :class:`Window`.
+
+ :raise: `Exception` if the input `item` is a separator and `wnd` is not ``None``.
+ """
+
+ if self.IsSeparator() and wnd is not None:
+ raise Exception("Separator items can not have an associated window")
+
+ self._wnd = wnd
+
+ if wnd.GetSizer(): # the window is a complex one hold by a sizer
+ size = wnd.GetBestSize()
+ else: # simple window, without sizers
+ size = wnd.GetSize()
+
+ # We have to bind the wx.EVT_SET_FOCUS for the associated window
+ # No other solution to handle the focus changing from an item in
+ # CustomTreeCtrl and the window associated to an item
+ # Do better strategies exist?
+ self._wnd.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+
+ self._height = size.GetHeight() + 2
+ self._width = size.GetWidth()
+ self._windowsize = size
+
+ # We don't show the window if the item is collapsed
+ if self._isCollapsed:
+ self._wnd.Show(False)
+
+ # The window is enabled only if the item is enabled
+ self._wnd.Enable(self._enabled)
+ self._windowenabled = self._enabled
+
+
+ def GetWindow(self):
+ """
+ Returns the window associated to the item (if any).
+
+ :return: An instance of any :class:`Window` derived class, excluding top-level windows.
+ """
+
+ return self._wnd
+
+
+ def DeleteWindow(self):
+ """ Deletes the window associated to the item (if any). """
+
+ if self._wnd:
+ self._wnd.Destroy()
+ self._wnd = None
+
+
+ def GetWindowEnabled(self):
+ """
+ Returns whether the associated window is enabled or not.
+
+ :return: ``True`` if the associated window is enabled, ``False`` if it is disabled.
+
+ :raise: `Exception` when the item has no associated window.
+ """
+
+ if not self._wnd:
+ raise Exception("\nERROR: This Item Has No Window Associated")
+
+ return self._windowenabled
+
+
+ def SetWindowEnabled(self, enable=True):
+ """
+ Sets whether the associated window is enabled or not.
+
+ :param bool `enable`: ``True`` to enable the associated window, ``False`` to disable it.
+
+ :raise: `Exception` when the item has no associated window.
+ """
+
+ if not self._wnd:
+ raise Exception("\nERROR: This Item Has No Window Associated")
+
+ self._windowenabled = enable
+ self._wnd.Enable(enable)
+
+
+ def GetWindowSize(self):
+ """ Returns the associated window size. """
+
+ return self._windowsize
+
+
+ def OnSetFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for the window associated with the item.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ treectrl = self._wnd.GetParent()
+ select = treectrl.GetSelection()
+
+ # If the window is associated to an item that currently is selected
+ # (has focus) we don't kill the focus. Otherwise we do it.
+ if select != self:
+ treectrl._hasFocus = False
+ else:
+ treectrl._hasFocus = True
+
+ event.Skip()
+
+
+ def GetType(self):
+ """
+ Returns the item type.
+
+ :see: :meth:`~GenericTreeItem.SetType` and :meth:`~GenericTreeItem.__init__` for a description of valid item types.
+ """
+
+ return self._type
+
+
+ def SetType(self, ct_type):
+ """
+ Sets the item type.
+
+ :param integer `ct_type`: may be one of the following integers:
+
+ =============== =========================================
+ `ct_type` Value Description
+ =============== =========================================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== =========================================
+
+ :note: Regarding radiobutton-type items (with `ct_type` = 2), the following
+ approach is used:
+
+ - All peer-nodes that are radiobuttons will be mutually exclusive. In other words,
+ only one of a set of radiobuttons that share a common parent can be checked at
+ once. If a radiobutton node becomes checked, then all of its peer radiobuttons
+ must be unchecked.
+ - If a radiobutton node becomes unchecked, then all of its child nodes will become
+ inactive.
+ """
+
+ self._type = ct_type
+
+
+ def SetHyperText(self, hyper=True):
+ """
+ Sets whether the item is hypertext or not.
+
+ :param bool `hyper`: ``True`` to set hypertext behaviour, ``False`` otherwise.
+ """
+
+ self._hypertext = hyper
+
+
+ def SetVisited(self, visited=True):
+ """
+ Sets whether an hypertext item was visited or not.
+
+ :param bool `visited`: ``True`` to set a hypertext item as visited, ``False`` otherwise.
+ """
+
+ self._visited = visited
+
+
+ def GetVisited(self):
+ """ Returns whether an hypertext item was visited or not. """
+
+ return self._visited
+
+
+ def IsHyperText(self):
+ """ Returns whether the item is hypetext or not. """
+
+ return self._hypertext
+
+
+ def GetParent(self):
+ """
+ Gets the item parent (another instance of :class:`GenericTreeItem` or ``None`` for
+ root items.
+
+ :return: An instance of :class:`GenericTreeItem` or ``None`` for root items.
+ """
+
+ return self._parent
+
+
+ def Insert(self, child, index):
+ """
+ Inserts an item in the item children list for this item.
+
+ :param `child`: an instance of :class:`GenericTreeItem`;
+ :param integer `index`: the index at which we should insert the new child.
+ """
+
+ self._children.insert(index, child)
+
+
+ def Expand(self):
+ """ Expands the item. """
+
+ self._isCollapsed = False
+
+
+ def Collapse(self):
+ """ Collapses the item. """
+
+ self._isCollapsed = True
+
+
+ def SetHilight(self, set=True):
+ """
+ Sets the item focus/unfocus.
+
+ :param bool `set`: ``True`` to set the focus to the item, ``False`` otherwise.
+ """
+
+ self._hasHilight = set
+
+
+ def HasChildren(self):
+ """
+ Returns whether the item has children or not.
+
+ :return: ``True`` if the item has children, ``False`` otherwise.
+ """
+
+ return len(self._children) > 0
+
+
+ def IsSelected(self):
+ """
+ Returns whether the item is selected or not.
+
+ :return: ``True`` if the item is selected, ``False`` otherwise.
+ """
+
+ return self._hasHilight != 0
+
+
+ def IsExpanded(self):
+ """
+ Returns whether the item is expanded or not.
+
+ :return: ``True`` if the item is expanded, ``False`` if it is collapsed.
+ """
+
+ return not self._isCollapsed
+
+
+ def GetValue(self):
+ """
+ Returns whether the item is checked or not.
+
+ :note: This is meaningful only for checkbox-like and radiobutton-like items.
+ """
+
+ if self.Is3State():
+ return self.Get3StateValue()
+
+ return self._checked
+
+
+ def Get3StateValue(self):
+ """
+ Gets the state of a 3-state checkbox item.
+
+ :return: ``wx.CHK_UNCHECKED`` when the checkbox is unchecked, ``wx.CHK_CHECKED``
+ when it is checked and ``wx.CHK_UNDETERMINED`` when it's in the undetermined
+ state.
+
+ :raise: `Exception` when the item is not a 3-state checkbox item.
+
+ :note: This method raises an exception when the function is used with a 2-state
+ checkbox item.
+
+ :note: This method is meaningful only for checkbox-like items.
+ """
+
+ if not self.Is3State():
+ raise Exception("Get3StateValue can only be used with 3-state checkbox items.")
+
+ return self._checked
+
+
+ def Is3State(self):
+ """
+ Returns whether or not the checkbox item is a 3-state checkbox.
+
+ :return: ``True`` if this checkbox is a 3-state checkbox, ``False`` if it's a
+ 2-state checkbox item.
+
+ :note: This method is meaningful only for checkbox-like items.
+ """
+
+ return self._is3State
+
+
+ def Set3StateValue(self, state):
+ """
+ Sets the checkbox item to the given `state`.
+
+ :param integer `state`: can be one of: ``wx.CHK_UNCHECKED`` (check is off), ``wx.CHK_CHECKED``
+ (check is on) or ``wx.CHK_UNDETERMINED`` (check is mixed).
+
+ :raise: `Exception` when the item is not a 3-state checkbox item.
+
+ :note: This method raises an exception when the checkbox item is a 2-state checkbox
+ and setting the state to ``wx.CHK_UNDETERMINED``.
+
+ :note: This method is meaningful only for checkbox-like items.
+ """
+
+ if not self._is3State and state == wx.CHK_UNDETERMINED:
+ raise Exception("Set3StateValue can only be used with 3-state checkbox items.")
+
+ self._checked = state
+
+
+ def Set3State(self, allow):
+ """
+ Sets whether the item has a 3-state value checkbox assigned to it or not.
+
+ :param bool `allow`: ``True`` to set an item as a 3-state checkbox, ``False`` to set it
+ to a 2-state checkbox.
+
+ :return: ``True`` if the change was successful, ``False`` otherwise.
+
+ :note: This method is meaningful only for checkbox-like items.
+ """
+
+ if self._type != 1:
+ return False
+
+ self._is3State = allow
+ return True
+
+
+ def IsChecked(self):
+ """
+ This is just a maybe more readable synonym for :meth:`~GenericTreeItem.GetValue`.
+ Returns whether the item is checked or not.
+
+ :note: This is meaningful only for checkbox-like and radiobutton-like items.
+ """
+
+ return self.GetValue()
+
+
+ def Check(self, checked=True):
+ """
+ Checks/unchecks an item.
+
+ :param bool `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This is meaningful only for checkbox-like and radiobutton-like items.
+ """
+
+ self._checked = checked
+
+
+ def HasPlus(self):
+ """
+ Returns whether the item has the plus button or not.
+
+ :return: ``True`` if the item has a 'plus' mark, ``False`` otherwise.
+ """
+
+ return self._hasPlus or self.HasChildren()
+
+
+ def IsBold(self):
+ """
+ Returns whether the item font is bold or not.
+
+ :return: ``True`` if the item has bold text, ``False`` otherwise.
+ """
+
+ return self._isBold != 0
+
+
+ def IsItalic(self):
+ """
+ Returns whether the item font is italic or not.
+
+ :return: ``True`` if the item has italic text, ``False`` otherwise.
+ """
+
+ return self._isItalic != 0
+
+
+ def Enable(self, enable=True):
+ """
+ Enables/disables the item.
+
+ :param bool `enable`: ``True`` to enable the item, ``False`` to disable it.
+ """
+
+ self._enabled = enable
+
+
+ def IsEnabled(self):
+ """
+ Returns whether the item is enabled or not.
+
+ :return: ``True`` if the item is enabled, ``False`` if it is disabled.
+ """
+
+ return self._enabled
+
+
+ def GetAttributes(self):
+ """
+ Returns the item attributes (font, colours, etc...).
+
+ :return: An instance of :class:`TreeItemAttr`.
+ """
+
+ return self._attr
+
+
+ def Attr(self):
+ """
+ Creates a new attribute (font, colours, etc...) for this item.
+
+ :return: An instance of :class:`TreeItemAttr`.
+ """
+
+ if not self._attr:
+
+ self._attr = TreeItemAttr()
+ self._ownsAttr = True
+
+ return self._attr
+
+
+ def SetAttributes(self, attr):
+ """
+ Sets the item attributes (font, colours, etc...).
+
+ :param `attr`: an instance of :class:`TreeItemAttr`.
+ """
+
+ if self._ownsAttr:
+ del self._attr
+
+ self._attr = attr
+ self._ownsAttr = False
+
+
+ def AssignAttributes(self, attr):
+ """
+ Assigns the item attributes (font, colours, etc...) for this item.
+
+ :param `attr`: an instance of :class:`TreeItemAttr`.
+ """
+
+ self.SetAttributes(attr)
+ self._ownsAttr = True
+
+
+ def DeleteChildren(self, tree):
+ """
+ Deletes the item children.
+
+ :param `tree`: the main :class:`CustomTreeCtrl` instance.
+ """
+
+ for child in self._children:
+ if tree:
+ tree.SendDeleteEvent(child)
+
+ child.DeleteChildren(tree)
+
+ if child == tree._select_me:
+ tree._select_me = None
+
+ # We have to destroy the associated window
+ wnd = child.GetWindow()
+ if wnd:
+ wnd.Destroy()
+ child._wnd = None
+
+ if child in tree._itemWithWindow:
+ tree._itemWithWindow.remove(child)
+
+ del child
+
+ self._children = []
+
+
+ def SetText(self, text):
+ """
+ Sets the item text.
+
+ :param string `text`: the new item label.
+
+ :raise: `Exception` if the item is a separator.
+ """
+
+ if self.IsSeparator():
+ raise Exception("Separator items can not have text")
+
+ self._text = text
+
+
+ def GetChildrenCount(self, recursively=True):
+ """
+ Gets the number of children of this item.
+
+ :param bool `recursively`: if ``True``, returns the total number of descendants,
+ otherwise only one level of children is counted.
+ """
+
+ count = len(self._children)
+
+ if not recursively:
+ return count
+
+ total = count
+
+ for n in xrange(count):
+ total += self._children[n].GetChildrenCount()
+
+ return total
+
+
+ def GetSize(self, x, y, theButton):
+ """
+ Returns the item size.
+
+ :param integer `x`: the current item's x position;
+ :param integer `y`: the current item's y position;
+ :param `theButton`: an instance of the main :class:`CustomTreeCtrl`.
+
+ :return: A tuple of (`x`, `y`) dimensions, in pixels, representing the
+ item's width and height.
+ """
+
+ bottomY = self._y + theButton.GetLineHeight(self)
+
+ if y < bottomY:
+ y = bottomY
+
+ width = self._x + self._width
+
+ if x < width:
+ x = width
+
+ if self.IsExpanded():
+ for child in self._children:
+ x, y = child.GetSize(x, y, theButton)
+
+ return x, y
+
+
+ def HitTest(self, point, theCtrl, flags=0, level=0):
+ """
+ :meth:`~GenericTreeItem.HitTest` method for an item. Called from the main window :meth:`CustomTreeCtrl.HitTest() <customtreectrl.CustomTreeCtrl.HitTest>`.
+
+ :param `point`: the point to test for the hit (an instance of :class:`Point`);
+ :param `theCtrl`: the main :class:`CustomTreeCtrl` tree;
+ :param integer `flags`: a bitlist of hit locations;
+ :param integer `level`: the item's level inside the tree hierarchy.
+
+ :see: :meth:`CustomTreeCtrl.HitTest() <customtreectrl.CustomTreeCtrl.HitTest>` method for the flags explanation.
+ """
+
+ # for a hidden root node, don't evaluate it, but do evaluate children
+ if not (level == 0 and theCtrl.HasAGWFlag(TR_HIDE_ROOT)):
+
+ # evaluate the item
+ h = theCtrl.GetLineHeight(self)
+
+ if point.y > self._y and point.y < self._y + h:
+
+ y_mid = self._y + h/2
+
+ if point.y < y_mid:
+ flags |= TREE_HITTEST_ONITEMUPPERPART
+ else:
+ flags |= TREE_HITTEST_ONITEMLOWERPART
+
+ xCross = self._x - theCtrl.GetSpacing()
+
+ if wx.Platform == "__WXMAC__":
+ # according to the drawing code the triangels are drawn
+ # at -4 , -4 from the position up to +10/+10 max
+ if point.x > xCross-4 and point.x < xCross+10 and point.y > y_mid-4 and \
+ point.y < y_mid+10 and self.HasPlus() and theCtrl.HasButtons():
+
+ flags |= TREE_HITTEST_ONITEMBUTTON
+ return self, flags
+ else:
+ # 5 is the size of the plus sign
+ if point.x > xCross-6 and point.x < xCross+6 and point.y > y_mid-6 and \
+ point.y < y_mid+6 and self.HasPlus() and theCtrl.HasButtons():
+
+ flags |= TREE_HITTEST_ONITEMBUTTON
+ return self, flags
+
+ if point.x >= self._x and point.x <= self._x + self._width:
+
+ image_w = -1
+ wcheck = 0
+
+ # assuming every image (normal and selected) has the same size!
+ if self.GetImage() != _NO_IMAGE and theCtrl._imageListNormal:
+ image_w, image_h = theCtrl._imageListNormal.GetSize(self.GetImage())
+
+ if self.GetCheckedImage() is not None:
+ wcheck, hcheck = theCtrl._imageListCheck.GetSize(self.GetCheckedImage())
+
+ if wcheck and point.x <= self._x + wcheck + 1:
+ flags |= TREE_HITTEST_ONITEMCHECKICON
+ return self, flags
+
+ if image_w != -1 and point.x <= self._x + wcheck + image_w + 1:
+ flags |= TREE_HITTEST_ONITEMICON
+ else:
+ flags |= TREE_HITTEST_ONITEMLABEL
+
+ return self, flags
+
+ if point.x < self._x:
+ if theCtrl.HasAGWFlag(TR_FULL_ROW_HIGHLIGHT):
+ flags |= TREE_HITTEST_ONITEM
+ else:
+ flags |= TREE_HITTEST_ONITEMINDENT
+ if point.x > self._x + self._width:
+ if theCtrl.HasAGWFlag(TR_FULL_ROW_HIGHLIGHT):
+ flags |= TREE_HITTEST_ONITEM
+ else:
+ flags |= TREE_HITTEST_ONITEMRIGHT
+
+ return self, flags
+
+ # if children are expanded, fall through to evaluate them
+ if self._isCollapsed:
+ return None, 0
+
+ # evaluate children
+ for child in self._children:
+ res, flags = child.HitTest(point, theCtrl, flags, level + 1)
+ if res != None:
+ return res, flags
+
+ return None, 0
+
+
+ def GetCurrentImage(self):
+ """
+ Returns the current item image.
+
+ :return: An integer index that can be used to retrieve the item image inside
+ a :class:`ImageList`.
+ """
+
+ image = _NO_IMAGE
+
+ if self.IsExpanded():
+
+ if self.IsSelected():
+
+ image = self._images[TreeItemIcon_SelectedExpanded]
+
+ if image == _NO_IMAGE:
+
+ # we usually fall back to the normal item, but try just the
+ # expanded one (and not selected) first in this case
+ image = self._images[TreeItemIcon_Expanded]
+
+ else: # not expanded
+
+ if self.IsSelected():
+ image = self._images[TreeItemIcon_Selected]
+
+ # maybe it doesn't have the specific image we want,
+ # try the default one instead
+ if image == _NO_IMAGE:
+ image = self._images[TreeItemIcon_Normal]
+
+ return image
+
+
+ def GetCurrentCheckedImage(self):
+ """
+ Returns the current item check image.
+
+ :return: An integer index that can be used to retrieve the item check image inside
+ a :class:`ImageList`.
+ """
+
+ if self._type == 0:
+ return None
+
+ checked = self.IsChecked()
+
+ if checked > 0:
+ if self._type == 1: # Checkbox
+ if checked == wx.CHK_CHECKED:
+ return self._checkedimages[TreeItemIcon_Checked]
+ else:
+ return self._checkedimages[TreeItemIcon_Undetermined]
+ else: # Radiobutton
+ return self._checkedimages[TreeItemIcon_Flagged]
+ else:
+ if self._type == 1: # Checkbox
+ return self._checkedimages[TreeItemIcon_NotChecked]
+ else: # Radiobutton
+ return self._checkedimages[TreeItemIcon_NotFlagged]
+
+
+# -----------------------------------------------------------------------------
+# CustomTreeCtrl Main Implementation.
+# This Is The Main Class.
+# -----------------------------------------------------------------------------
+
+class CustomTreeCtrl(wx.PyScrolledWindow):
+ """
+ :class:`CustomTreeCtrl` is a class that mimics the behaviour of :class:`TreeCtrl`, with almost the
+ same base functionalities plus some more enhancements. This class does not rely on
+ the native control, as it is a full owner-drawn tree control.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=TR_DEFAULT_STYLE, validator=wx.DefaultValidator,
+ name="CustomTreeCtrl"):
+ """
+ Default class constructor.
+
+ :param Window `parent`: parent window. Must not be ``None``;
+ :param integer `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :type `pos`: tuple or :class:`Point`
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :type `size`: tuple or :class:`Size`
+ :param integer `style`: the underlying :class:`PyScrolledWindow` style;
+ :param integer `agwStyle`: the AGW-specific window style for :class:`CustomTreeCtrl`. It can be a
+ combination of the following bits:
+
+ ============================== =========== ==================================================
+ Window Styles Hex Value Description
+ ============================== =========== ==================================================
+ ``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn.
+ ``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default.
+ ``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items.
+ ``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors.
+ ``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set.
+ ``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit.
+ ``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons.
+ ``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected.
+ ``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases).
+ ``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset.
+ ``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control.
+ ``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows.
+ ``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes.
+ ``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window.
+ ``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well.
+ ``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly.
+ ``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful foe checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well.
+ ``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position.
+ ``TR_ALIGN_WINDOWS_RIGHT`` 0x40000 Flag used to align windows (in items with windows) to the rightmost edge of :class:`CustomTreeCtrl`.
+ ``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`CustomTreeCtrl` is low.
+ ``TR_TOOLTIP_ON_LONG_ITEMS`` 0x100000 Flag used to show tooltips on long items when the horizontal space for :class:`CustomTreeCtrl` is low.
+ ============================== =========== ==================================================
+
+ :param Validator `validator`: window validator;
+ :param string `name`: window name.
+ """
+
+ self._current = self._key_current = self._anchor = self._select_me = None
+ self._hasFocus = False
+ self._dirty = False
+
+ # Default line height: it will soon be changed
+ self._lineHeight = 10
+ # Item indent wrt parent
+ self._indent = 15
+ # item horizontal spacing between the start and the text
+ self._spacing = 18
+
+ # Brushes for focused/unfocused items (also gradient type)
+ self._hilightBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
+ btnshadow = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+ self._hilightUnfocusedBrush = wx.Brush(btnshadow)
+ r, g, b = btnshadow.Red(), btnshadow.Green(), btnshadow.Blue()
+ backcolour = (max((r >> 1) - 20, 0),
+ max((g >> 1) - 20, 0),
+ max((b >> 1) - 20, 0))
+ backcolour = wx.Colour(backcolour[0], backcolour[1], backcolour[2])
+ self._hilightUnfocusedBrush2 = wx.Brush(backcolour)
+
+ # image list for icons
+ self._imageListNormal = self._imageListButtons = self._imageListState = self._imageListCheck = self._imageListLeft = None
+ self._ownsImageListNormal = self._ownsImageListButtons = self._ownsImageListState = self._ownsImageListLeft = False
+
+ # Drag and drop initial settings
+ self._dragCount = 0
+ self._countDrag = 0
+ self._isDragging = False
+ self._dropTarget = self._oldSelection = None
+ self._dragImage = None
+ self._underMouse = None
+
+ # EditCtrl initial settings for editable items
+ self._editCtrl = None
+ self._editTimer = None
+
+ # This one allows us to handle Freeze() and Thaw() calls
+ self._freezeCount = 0
+
+ self._findPrefix = ""
+ self._findTimer = None
+
+ self._dropEffectAboveItem = False
+ self._lastOnSame = False
+
+ # Default normal and bold fonts for an item
+ self._hasFont = True
+ self._normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ family = self._normalFont.GetFamily()
+ if family == wx.FONTFAMILY_UNKNOWN:
+ family = wx.FONTFAMILY_SWISS
+ self._boldFont = wx.Font(self._normalFont.GetPointSize(), family,
+ self._normalFont.GetStyle(), wx.BOLD, self._normalFont.GetUnderlined(),
+ self._normalFont.GetFaceName(), self._normalFont.GetEncoding())
+ self._italicFont = wx.Font(self._normalFont.GetPointSize(), family,
+ wx.FONTSTYLE_ITALIC, wx.NORMAL, self._normalFont.GetUnderlined(),
+ self._normalFont.GetFaceName(), self._normalFont.GetEncoding())
+
+ # Hyperlinks things
+ self._hypertextfont = wx.Font(self._normalFont.GetPointSize(), family,
+ self._normalFont.GetStyle(), wx.NORMAL, True,
+ self._normalFont.GetFaceName(), self._normalFont.GetEncoding())
+ self._hypertextnewcolour = wx.BLUE
+ self._hypertextvisitedcolour = wx.Colour(200, 47, 200)
+ self._isonhyperlink = False
+
+ # Default CustomTreeCtrl background colour.
+ self._backgroundColour = wx.WHITE
+
+ # Background image settings
+ self._backgroundImage = None
+ self._imageStretchStyle = _StyleTile
+
+ # Disabled items colour
+ self._disabledColour = wx.Colour(180, 180, 180)
+
+ # Gradient selection colours
+ self._firstcolour = colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self._secondcolour = wx.WHITE
+ self._usegradients = False
+ self._gradientstyle = 0 # Horizontal Gradient
+
+ # Vista Selection Styles
+ self._vistaselection = False
+
+ # To speed up ExpandAll and SelectAll
+ self._sendEvent = True
+
+ # Connection lines style
+ grey = (160,160,160)
+ if wx.Platform != "__WXMAC__":
+ self._dottedPen = wx.Pen(grey, 1, wx.USER_DASH)
+ self._dottedPen.SetDashes([1,1])
+ self._dottedPen.SetCap(wx.CAP_BUTT)
+ else:
+ self._dottedPen = wx.Pen(grey, 1)
+
+ # Pen Used To Draw The Border Around Selected Items
+ self._borderPen = wx.BLACK_PEN
+ self._cursor = wx.StockCursor(wx.CURSOR_ARROW)
+
+ # For Appended Windows
+ self._hasWindows = False
+ self._itemWithWindow = []
+
+ if wx.Platform == "__WXMAC__":
+ agwStyle &= ~TR_LINES_AT_ROOT
+ agwStyle |= TR_NO_LINES
+
+ platform, major, minor = wx.GetOsVersion()
+ if major < 10:
+ agwStyle |= TR_ROW_LINES
+
+ # A constant to use my translation of RendererNative.DrawTreeItemButton
+ # if the wxPython version is less than 2.6.2.1.
+ if _VERSION_STRING < "2.6.2.1":
+ self._drawingfunction = DrawTreeItemButton
+ else:
+ self._drawingfunction = wx.RendererNative.Get().DrawTreeItemButton
+
+ # Set the separator pen default colour
+ self._separatorPen = wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+
+ # Create our container... at last!
+ wx.PyScrolledWindow.__init__(self, parent, id, pos, size, style|wx.HSCROLL|wx.VSCROLL, name)
+
+ self._agwStyle = agwStyle
+
+ # Create the default check image list
+ self.SetImageListCheck(16, 16)
+
+ # If the tree display has no buttons, but does have
+ # connecting lines, we can use a narrower layout.
+ # It may not be a good idea to force this...
+ if not self.HasButtons() and not self.HasAGWFlag(TR_NO_LINES):
+ self._indent= 10
+ self._spacing = 10
+
+ self.SetValidator(validator)
+
+ attr = self.GetDefaultAttributes()
+ self.SetOwnForegroundColour(attr.colFg)
+ self.SetOwnBackgroundColour(attr.colBg)
+
+ if not self._hasFont:
+ self.SetOwnFont(attr.font)
+
+ self.SetSize(size)
+
+ # Bind the events
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(EVT_TREE_ITEM_GETTOOLTIP, self.OnGetToolTip)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+
+ # Sets the focus to ourselves: this is useful if you have items
+ # with associated widgets.
+ self.SetFocus()
+
+
+ def AcceptsFocus(self):
+ """
+ Can this window be given focus by mouse click?
+
+ :note: This method always returns ``True`` as we always accept focus from
+ mouse click.
+
+ :note: Overridden from :class:`PyScrolledWindow`.
+ """
+
+ # overridden base class method, allows this ctrl to
+ # participate in the tab-order, etc. It's overridable because
+ # of deriving this class from wx.PyScrolledWindow...
+ return True
+
+
+ def OnDestroy(self, event):
+ """
+ Handles the ``wx.EVT_WINDOW_DESTROY`` event for :class:`CustomTreeCtrl`.
+
+ :param `event`: a :class:`WindowDestroyEvent` event to be processed.
+ """
+
+ # Here there may be something I miss... do I have to destroy
+ # something else?
+ if self._editTimer and self._editTimer.IsRunning():
+ self._editTimer.Stop()
+ del self._editTimer
+ self._editTimer = None
+
+ if self._findTimer and self._findTimer.IsRunning():
+ self._findTimer.Stop()
+ del self._findTimer
+
+ event.Skip()
+
+
+ def GetControlBmp(self, checkbox=True, checked=False, enabled=True, x=16, y=16):
+ """
+ Returns a native looking checkbox or radio button bitmap.
+
+ :param bool `checkbox`: ``True`` to get a checkbox image, ``False`` for a radiobutton one;
+ :param bool `checked`: ``True`` if the control is marked, ``False`` if it is not;
+ :param bool `enabled`: ``True`` if the control is enabled, ``False`` if it is not;
+ :param integer `x`: the width of the bitmap;
+ :param integer `y`: the height of the bitmap.
+
+ :return: An instance of :class:`Bitmap`, representing a native looking checkbox or radiobutton.
+ """
+
+ bmp = wx.EmptyBitmap(x, y)
+ mdc = wx.MemoryDC(bmp)
+ mask = wx.Colour(0xfe, 0xfe, 0xfe)
+ mdc.SetBackground(wx.Brush(mask))
+ mdc.Clear()
+
+ render = wx.RendererNative.Get()
+
+ if checked == wx.CHK_CHECKED:
+ flag = wx.CONTROL_CHECKED
+ elif checked == wx.CHK_UNDETERMINED:
+ flag = wx.CONTROL_UNDETERMINED
+ else:
+ flag = 0
+
+ if not enabled:
+ flag |= wx.CONTROL_DISABLED
+
+ if checkbox:
+ render.DrawCheckBox(self, mdc, (0, 0, x, y), flag)
+ else:
+ if _VERSION_STRING < "2.9":
+ render.DrawRadioButton(self, mdc, (0, 0, x, y), flag)
+ else:
+ render.DrawRadioBitmap(self, mdc, (0, 0, x, y), flag)
+
+ mdc.SelectObject(wx.NullBitmap)
+ bmp.SetMaskColour(mask)
+ return bmp
+
+
+ def GetCount(self):
+ """ Returns the global number of items in the tree. """
+
+ if not self._anchor:
+ # the tree is empty
+ return 0
+
+ count = self._anchor.GetChildrenCount()
+
+ if not self.HasAGWFlag(TR_HIDE_ROOT):
+ # take the root itself into account
+ count = count + 1
+
+ return count
+
+
+ def GetIndent(self):
+ """ Returns the item indentation, in pixels. """
+
+ return self._indent
+
+
+ def GetSpacing(self):
+ """ Returns the spacing between the start and the text, in pixels. """
+
+ return self._spacing
+
+
+ def GetRootItem(self):
+ """ Returns the root item, an instance of :class:`GenericTreeItem`. """
+
+ return self._anchor
+
+
+ def GetSelection(self):
+ """
+ Returns the current selection.
+
+ :return: An instance of :class:`GenericTreeItem`.
+
+ :note:
+
+ This method is valid only with the style ``TR_SINGLE`` set. Use
+ :meth:`~CustomTreeCtrl.GetSelections` for multiple-selections trees.
+ """
+
+ return self._current
+
+
+ def ToggleItemSelection(self, item):
+ """
+ Toggles the item selection.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ self.SelectItem(item, not self.IsSelected(item))
+
+
+ def EnableChildren(self, item, enable=True):
+ """
+ Enables/disables the item children.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `enable`: ``True`` to enable the children, ``False`` to disable them.
+
+ :note: This method is used internally.
+ """
+
+ torefresh = False
+ if item.IsExpanded():
+ torefresh = True
+
+ if item.GetType() == 2 and enable and not item.IsChecked():
+ # We hit a radiobutton item not checked, we don't want to
+ # enable the children
+ return
+
+ child, cookie = self.GetFirstChild(item)
+ while child:
+ self.EnableItem(child, enable, torefresh=torefresh)
+ # Recurse on tree
+ if child.GetType != 2 or (child.GetType() == 2 and item.IsChecked()):
+ self.EnableChildren(child, enable)
+ (child, cookie) = self.GetNextChild(item, cookie)
+
+
+ def EnableItem(self, item, enable=True, torefresh=True):
+ """
+ Enables/disables an item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `enable`: ``True`` to enable the item, ``False`` to disable it;
+ :param bool `torefresh`: whether to redraw the item or not.
+ """
+
+ if item.IsEnabled() == enable:
+ return
+
+ if not enable and item.IsSelected():
+ self.SelectItem(item, False)
+
+ item.Enable(enable)
+ wnd = item.GetWindow()
+
+ # Handles the eventual window associated to the item
+ if wnd:
+ wndenable = item.GetWindowEnabled()
+ wnd.Enable(enable)
+
+ if torefresh:
+ # We have to refresh the item line
+ dc = wx.ClientDC(self)
+ self.CalculateSize(item, dc)
+ self.RefreshLine(item)
+
+
+ def IsItemEnabled(self, item):
+ """
+ Returns whether an item is enabled or disabled.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ return item.IsEnabled()
+
+
+ def SetDisabledColour(self, colour):
+ """
+ Sets the colour for items in a disabled state.
+
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ self._disabledColour = colour
+ self._dirty = True
+
+
+ def GetDisabledColour(self):
+ """
+ Returns the colour for items in a disabled state.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._disabledColour
+
+
+ def IsItemChecked(self, item):
+ """
+ Returns whether an item is checked or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if the item is in a 'checked' state, ``False`` otherwise.
+
+ :note: This method is meaningful only for checkbox-like and radiobutton-like items.
+ """
+
+ return item.IsChecked()
+
+
+ def GetItem3StateValue(self, item):
+ """
+ Gets the state of a 3-state checkbox item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``wx.CHK_UNCHECKED`` when the checkbox is unchecked, ``wx.CHK_CHECKED``
+ when it is checked and ``wx.CHK_UNDETERMINED`` when it's in the undetermined
+ state.
+
+ :note: This method raises an exception when the function is used with a 2-state
+ checkbox item.
+
+ :note: This method is meaningful only for checkbox-like items.
+ """
+
+ return item.Get3StateValue()
+
+
+ def IsItem3State(self, item):
+ """
+ Returns whether or not the checkbox item is a 3-state checkbox.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if this checkbox is a 3-state checkbox, ``False`` if it's a
+ 2-state checkbox item.
+
+ :note: This method is meaningful only for checkbox-like items.
+ """
+
+ return item.Is3State()
+
+
+ def SetItem3StateValue(self, item, state):
+ """
+ Sets the checkbox item to the given `state`.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param integer `state`: can be one of: ``wx.CHK_UNCHECKED`` (check is off), ``wx.CHK_CHECKED``
+ (check is on) or ``wx.CHK_UNDETERMINED`` (check is mixed).
+
+ :note: This method raises an exception when the checkbox item is a 2-state checkbox
+ and setting the state to ``wx.CHK_UNDETERMINED``.
+
+ :note: This method is meaningful only for checkbox-like items.
+ """
+
+ item.Set3StateValue(state)
+
+
+ def SetItem3State(self, item, allow):
+ """
+ Sets whether the item has a 3-state value checkbox assigned to it or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `allow`: ``True`` to set an item as a 3-state checkbox, ``False`` to set it
+ to a 2-state checkbox.
+
+ :return: ``True`` if the change was successful, ``False`` otherwise.
+
+ :note: This method is meaningful only for checkbox-like items.
+ """
+
+ return item.Set3State(allow)
+
+
+ def CheckItem2(self, item, checked=True, torefresh=False):
+ """
+ Used internally to avoid ``EVT_TREE_ITEM_CHECKED`` events.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `checked`: ``True`` to check an item, ``False`` to uncheck it;
+ :param bool `torefresh`: whether to redraw the item or not.
+ """
+
+ if item.GetType() == 0:
+ return
+
+ item.Check(checked)
+
+ if torefresh:
+ dc = wx.ClientDC(self)
+ self.CalculateSize(item, dc)
+ self.RefreshLine(item)
+
+
+ def UnCheckRadioParent(self, item, checked=False):
+ """
+ Used internally to handle radio node parent correctly.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `checked`: ``True`` to check an item, ``False`` to uncheck it.
+ """
+
+ e = TreeEvent(wxEVT_TREE_ITEM_CHECKING, self.GetId())
+ e.SetItem(item)
+ e.SetEventObject(self)
+
+ if self.GetEventHandler().ProcessEvent(e):
+ return False
+
+ item.Check(checked)
+ self.RefreshLine(item)
+ self.EnableChildren(item, checked)
+ e = TreeEvent(wxEVT_TREE_ITEM_CHECKED, self.GetId())
+ e.SetItem(item)
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+ return True
+
+
+ def CheckItem(self, item, checked=True):
+ """
+ Actually checks/uncheks an item, sending (eventually) the two
+ events ``EVT_TREE_ITEM_CHECKING`` and ``EVT_TREE_ITEM_CHECKED``.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `checked`: for a radiobutton-type item, ``True`` to check it, ``False``
+ to uncheck it. For a checkbox-type item, it can be one of ``wx.CHK_UNCHECKED``
+ when the checkbox is unchecked, ``wx.CHK_CHECKED`` when it is checked and
+ ``wx.CHK_UNDETERMINED`` when it's in the undetermined state.
+ """
+
+ # Should we raise an error here?!?
+ if item.GetType() == 0:
+ return
+
+ if item.GetType() == 2: # it's a radio button
+ if not checked and item.IsChecked(): # Try To Unckeck?
+ return
+ else:
+ if not self.UnCheckRadioParent(item, checked):
+ return
+
+ self.CheckSameLevel(item, False)
+ return
+
+ # Radiobuttons are done, let's handle checkbuttons...
+ e = TreeEvent(wxEVT_TREE_ITEM_CHECKING, self.GetId())
+ e.SetItem(item)
+ e.SetEventObject(self)
+
+ if self.GetEventHandler().ProcessEvent(e):
+ # Blocked by user
+ return
+
+ if item.Is3State():
+ item.Set3StateValue(checked)
+ else:
+ item.Check(checked)
+
+ dc = wx.ClientDC(self)
+ self.RefreshLine(item)
+
+ if self.HasAGWFlag(TR_AUTO_CHECK_CHILD):
+ ischeck = self.IsItemChecked(item)
+ self.AutoCheckChild(item, ischeck)
+ if self.HasAGWFlag(TR_AUTO_CHECK_PARENT):
+ ischeck = self.IsItemChecked(item)
+ self.AutoCheckParent(item, ischeck)
+ elif self.HasAGWFlag(TR_AUTO_TOGGLE_CHILD):
+ self.AutoToggleChild(item)
+
+ e = TreeEvent(wxEVT_TREE_ITEM_CHECKED, self.GetId())
+ e.SetItem(item)
+ e.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(e)
+
+
+ def AutoToggleChild(self, item):
+ """
+ Transverses the tree and toggles the items.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :note: This method is meaningful only for checkbox-like and radiobutton-like items.
+ """
+
+ child, cookie = self.GetFirstChild(item)
+
+ torefresh = False
+ if item.IsExpanded():
+ torefresh = True
+
+ # Recurse on tree
+ while child:
+ if child.GetType() == 1 and child.IsEnabled():
+ self.CheckItem2(child, not child.IsChecked(), torefresh=torefresh)
+ self.AutoToggleChild(child)
+ (child, cookie) = self.GetNextChild(item, cookie)
+
+
+ def AutoCheckChild(self, item, checked):
+ """
+ Transverses the tree and checks/unchecks the items.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for checkbox-like and radiobutton-like items.
+ """
+
+ (child, cookie) = self.GetFirstChild(item)
+
+ torefresh = False
+ if item.IsExpanded():
+ torefresh = True
+
+ while child:
+ if child.GetType() == 1 and child.IsEnabled():
+ self.CheckItem2(child, checked, torefresh=torefresh)
+ self.AutoCheckChild(child, checked)
+ (child, cookie) = self.GetNextChild(item, cookie)
+
+
+ def AutoCheckParent(self, item, checked):
+ """
+ Traverses up the tree and checks/unchecks parent items.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for checkbox-like and radiobutton-like items.
+ """
+
+ parent = item.GetParent()
+ if not parent or parent.GetType() != 1:
+ return
+
+ (child, cookie) = self.GetFirstChild(parent)
+ while child:
+ if child.GetType() == 1 and child.IsEnabled():
+ if checked != child.IsChecked():
+ return
+ (child, cookie) = self.GetNextChild(parent, cookie)
+
+ self.CheckItem2(parent, checked, torefresh=True)
+ self.AutoCheckParent(parent, checked)
+
+
+ def CheckChilds(self, item, checked=True):
+ """
+ Programatically check/uncheck item children.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for checkbox-like and radiobutton-like items.
+
+ :note: This method does not generate ``EVT_TREE_ITEM_CHECKING`` and
+ ``EVT_TREE_ITEM_CHECKED`` events.
+ """
+
+ if checked == None:
+ self.AutoToggleChild(item)
+ else:
+ self.AutoCheckChild(item, checked)
+
+
+ def CheckSameLevel(self, item, checked=False):
+ """
+ Uncheck radio items which are on the same level of the checked one.
+ Used internally.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for radiobutton-like items.
+ """
+
+ parent = item.GetParent()
+
+ if not parent:
+ return
+
+ torefresh = False
+ if parent.IsExpanded():
+ torefresh = True
+
+ (child, cookie) = self.GetFirstChild(parent)
+ while child:
+ if child.GetType() == 2 and child != item:
+ self.CheckItem2(child, checked, torefresh=torefresh)
+ if child.GetType != 2 or (child.GetType() == 2 and child.IsChecked()):
+ self.EnableChildren(child, checked)
+ (child, cookie) = self.GetNextChild(parent, cookie)
+
+
+ def EditLabel(self, item):
+ """
+ Starts editing an item label.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ self.Edit(item)
+
+
+ def ShouldInheritColours(self):
+ """
+ Return ``True`` from here to allow the colours of this window to be
+ changed by `InheritAttributes`, returning ``False`` forbids inheriting them
+ from the parent window.
+
+ The base class version returns ``False``, but this method is overridden in
+ :class:`Control` where it returns ``True``.
+
+ :class:`CustomTreeCtrl` does not inherit colours from anyone.
+ """
+
+ return False
+
+
+ def SetIndent(self, indent):
+ """
+ Sets the indentation for :class:`CustomTreeCtrl`.
+
+ :param integer `indent`: an integer representing the indentation for the items in the tree.
+ """
+
+ self._indent = indent
+ self._dirty = True
+
+
+ def SetSpacing(self, spacing):
+ """
+ Sets the spacing between items in :class:`CustomTreeCtrl`.
+
+ :param integer `spacing`: an integer representing the spacing between items in the tree.
+ """
+
+ self._spacing = spacing
+ self._dirty = True
+
+
+ def HasChildren(self, item):
+ """
+ Returns whether an item has children or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ return len(item.GetChildren()) > 0
+
+
+ def GetChildrenCount(self, item, recursively=True):
+ """
+ Returns the item children count.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `recursively`: if ``True``, returns the total number of descendants,
+ otherwise only one level of children is counted.
+ """
+
+ return item.GetChildrenCount(recursively)
+
+
+ def HasAGWFlag(self, flag):
+ """
+ Returns ``True`` if :class:`CustomTreeCtrl` has the `flag` bit set.
+
+ :param integer `flag`: any possible window style for :class:`CustomTreeCtrl`.
+
+ :see: The :meth:`~CustomTreeCtrl.__init__` method for the `flag` parameter description.
+ """
+
+ return self._agwStyle & flag
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the :class:`CustomTreeCtrl` window style.
+
+ :param integer `agwStyle`: the new :class:`CustomTreeCtrl` window style.
+
+ :see: The :meth:`~CustomTreeCtrl.__init__` method for the `agwStyle` parameter description.
+ """
+
+ # Do not try to expand the root node if it hasn't been created yet
+ if self._anchor and not self.HasAGWFlag(TR_HIDE_ROOT) and agwStyle & TR_HIDE_ROOT:
+
+ # if we will hide the root, make sure children are visible
+ self._anchor.SetHasPlus()
+ self._anchor.Expand()
+ self.CalculatePositions()
+
+ # right now, just sets the styles. Eventually, we may
+ # want to update the inherited styles, but right now
+ # none of the parents has updatable styles
+
+ if self.HasAGWFlag(TR_MULTIPLE) and not (agwStyle & TR_MULTIPLE):
+ selections = self.GetSelections()
+ for select in selections[0:-1]:
+ self.SelectItem(select, False)
+
+ self._agwStyle = agwStyle
+ self._dirty = True
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`CustomTreeCtrl` style.
+
+ :see: The :meth:`~CustomTreeCtrl.__init__` method for a list of possible style flags.
+ """
+
+ return self._agwStyle
+
+
+ def HasButtons(self):
+ """
+ Returns whether :class:`CustomTreeCtrl` has the ``TR_HAS_BUTTONS`` flag set.
+
+ :return: ``True`` if :class:`CustomTreeCtrl` has the ``TR_HAS_BUTTONS`` flag set,
+ ``False`` otherwise.
+ """
+
+ return self.HasAGWFlag(TR_HAS_BUTTONS)
+
+
+# -----------------------------------------------------------------------------
+# functions to work with tree items
+# -----------------------------------------------------------------------------
+
+ def GetItemText(self, item):
+ """
+ Returns the item text.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ return item.GetText()
+
+
+ def GetItemSize(self, item):
+ """
+ Returns the horizontal space available in :class:`CustomTreeCtrl`, in pixels, to draw this item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ .. versionadded:: 0.9.3
+ """
+
+ w, h = self.GetClientSize()
+ xa, ya = self.CalcScrolledPosition((0, item.GetY()))
+
+ wcheck = image_w = 0
+
+ if item.GetType() != 0:
+ wcheck, dummy = self._imageListCheck.GetSize(item.GetType())
+ wcheck += 4
+
+ image = item.GetCurrentImage()
+
+ if image != _NO_IMAGE:
+ if self._imageListNormal:
+ image_w, dummy = self._imageListNormal.GetSize(image)
+ image_w += 4
+
+ maxsize = w - (wcheck + image_w + item.GetX()) + xa
+ return maxsize
+
+
+ def GetItemImage(self, item, which=TreeItemIcon_Normal):
+ """
+ Returns the item image.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param integer `which`: can be one of the following bits:
+
+ ================================= ========================
+ Item State Description
+ ================================= ========================
+ ``TreeItemIcon_Normal`` To get the normal item image
+ ``TreeItemIcon_Selected`` To get the selected item image (i.e. the image which is shown when the item is currently selected)
+ ``TreeItemIcon_Expanded`` To get the expanded image (this only makes sense for items which have children - then this image is shown when the item is expanded and the normal image is shown when it is collapsed)
+ ``TreeItemIcon_SelectedExpanded`` To get the selected expanded image (which is shown when an expanded item is currently selected)
+ ================================= ========================
+
+ :return: An integer index that can be used to retrieve the item image inside
+ a :class:`ImageList`.
+ """
+
+ return item.GetImage(which)
+
+
+ def GetItemLeftImage(self, item):
+ """
+ Returns the item leftmost image, i.e. the image associated to the item on the leftmost
+ part of the :class:`CustomTreeCtrl` client area.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An integer index that can be used to retrieve the item leftmost image inside
+ a :class:`ImageList`.
+ """
+
+ return item.GetLeftImage()
+
+
+ def GetPyData(self, item):
+ """
+ Returns the data associated to an item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: A Python object representing the item data, or ``None`` if no data
+ has been assigned to this item.
+ """
+
+ return item.GetData()
+
+ GetItemPyData = GetPyData
+
+
+ def GetItemTextColour(self, item):
+ """
+ Returns the item text colour or separator horizontal line colour.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return item.Attr().GetTextColour()
+
+
+ def GetItemBackgroundColour(self, item):
+ """
+ Returns the item background colour.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return item.Attr().GetBackgroundColour()
+
+
+ def GetItemFont(self, item):
+ """
+ Returns the item font.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`Font`.
+ """
+
+ font = item.Attr().GetFont()
+ if font.IsOk():
+ return font
+
+ return wx.NullFont
+
+
+ def IsItemHyperText(self, item):
+ """
+ Returns whether an item is hypertext or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if the item is hypertext-like, ``False`` otherwise.
+ """
+
+ return item.IsHyperText()
+
+
+ def SetItemText(self, item, text):
+ """
+ Sets the item text.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param string `text`: the new item label.
+
+ :raise: `Exception` if the input `item` is a separator.
+ """
+
+ if item.IsSeparator():
+ raise Exception("Separator items can not have text")
+
+ dc = wx.ClientDC(self)
+ item.SetText(text)
+ self.CalculateSize(item, dc)
+ self.RefreshLine(item)
+
+
+ def SetItemImage(self, item, image, which=TreeItemIcon_Normal):
+ """
+ Sets the item image, depending on the item state.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param integer `image`: an index within the normal image list specifying the image to
+ use for the item in the state specified by the `which` parameter;
+ :param integer `which`: the item state.
+
+ :see: :meth:`~CustomTreeCtrl.GetItemImage` for an explanation of the `which` parameter.
+ """
+
+ item.SetImage(image, which)
+
+ dc = wx.ClientDC(self)
+ self.CalculateSize(item, dc)
+ self.RefreshLine(item)
+
+
+ def SetItemLeftImage(self, item, image):
+ """
+ Sets the item leftmost image, i.e. the image associated to the item on the leftmost
+ part of the :class:`CustomTreeCtrl` client area.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param integer `image`: an index within the left image list specifying the image to
+ use for the item in the leftmost part of the client area.
+ """
+
+ item.SetLeftImage(image)
+
+ dc = wx.ClientDC(self)
+ self.CalculateSize(item, dc)
+ self.RefreshLine(item)
+
+
+ def SetPyData(self, item, data):
+ """
+ Sets the data associated to an item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param object `data`: can be any Python object.
+ """
+
+ item.SetData(data)
+
+ SetItemPyData = SetPyData
+
+
+ def SetItemHasChildren(self, item, has=True):
+ """
+ Forces the appearance/disappearance of the button next to the item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `has`: ``True`` to have a button next to an item, ``False`` otherwise.
+ """
+
+ item.SetHasPlus(has)
+ self.RefreshLine(item)
+
+
+ def SetItemBold(self, item, bold=True):
+ """
+ Sets the item font as bold/unbold.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `bold`: ``True`` to set the item font as bold, ``False`` otherwise.
+ """
+
+ # avoid redrawing the tree if no real change
+ if item.IsBold() != bold:
+ item.SetBold(bold)
+ self._dirty = True
+
+
+ def SetItemItalic(self, item, italic=True):
+ """
+ Sets the item font as italic/non-italic.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `italic`: ``True`` to set the item font as italic, ``False`` otherwise.
+ """
+
+ if item.IsItalic() != italic:
+ item.SetItalic(italic)
+ self._dirty = True
+
+
+ def SetItemDropHighlight(self, item, highlight=True):
+ """
+ Gives the item the visual feedback for drag and drop operations.
+ This is useful when something is dragged from outside the :class:`CustomTreeCtrl`.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `highlight`: ``True`` to highlight the dragged items, ``False`` otherwise.
+ """
+
+ if highlight:
+ bg = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ fg = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
+
+ item.Attr().SetTextColour(fg)
+ item.Attr.SetBackgroundColour(bg)
+ self.RefreshLine(item)
+
+
+ def SetItemTextColour(self, item, colour):
+ """
+ Sets the item text colour or separator horizontal line colour.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ item.Attr().SetTextColour(colour)
+ self.RefreshLine(item)
+
+
+ def SetItemBackgroundColour(self, item, colour):
+ """
+ Sets the item background colour.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ item.Attr().SetBackgroundColour(colour)
+ self.RefreshLine(item)
+
+
+ def SetItemHyperText(self, item, hyper=True):
+ """
+ Sets whether the item is hypertext or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `hyper`: ``True`` to have an item with hypertext behaviour, ``False`` otherwise.
+ """
+
+ item.SetHyperText(hyper)
+ self.RefreshLine(item)
+
+
+ def SetItemFont(self, item, font):
+ """
+ Sets the item font.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param `font`: a valid :class:`Font` instance.
+ """
+
+ item.Attr().SetFont(font)
+ self._dirty = True
+
+
+ def SetFont(self, font):
+ """
+ Sets the :class:`CustomTreeCtrl` font.
+
+ :param `font`: a valid :class:`Font` instance.
+
+ :note: Overridden from :class:`PyScrolledWindow`.
+ """
+
+ wx.PyScrolledWindow.SetFont(self, font)
+
+ self._normalFont = font
+ family = self._normalFont.GetFamily()
+
+ if family == wx.FONTFAMILY_UNKNOWN:
+ family = wx.FONTFAMILY_SWISS
+
+ self._boldFont = wx.Font(self._normalFont.GetPointSize(), family,
+ self._normalFont.GetStyle(), wx.BOLD, self._normalFont.GetUnderlined(),
+ self._normalFont.GetFaceName(), self._normalFont.GetEncoding())
+
+ self._italicFont = wx.Font(self._normalFont.GetPointSize(), family,
+ wx.FONTSTYLE_ITALIC, wx.NORMAL, self._normalFont.GetUnderlined(),
+ self._normalFont.GetFaceName(), self._normalFont.GetEncoding())
+
+ self.CalculatePositions()
+ self.Refresh()
+ self.AdjustMyScrollbars()
+
+ return True
+
+
+ def GetHyperTextFont(self):
+ """
+ Returns the font used to render hypertext items.
+
+ :return: An instance of :class:`Font`.
+
+ :note: This method is meaningful only for hypertext-like items.
+ """
+
+ return self._hypertextfont
+
+
+ def SetHyperTextFont(self, font):
+ """
+ Sets the font used to render hypertext items.
+
+ :param `font`: a valid :class:`Font` instance.
+
+ :note: This method is meaningful only for hypertext-like items.
+ """
+
+ self._hypertextfont = font
+ self._dirty = True
+
+
+ def SetHyperTextNewColour(self, colour):
+ """
+ Sets the colour used to render a non-visited hypertext item.
+
+ :param `colour`: a valid :class:`Colour` instance.
+
+ :note: This method is meaningful only for hypertext-like items.
+ """
+
+ self._hypertextnewcolour = colour
+ self._dirty = True
+
+
+ def GetHyperTextNewColour(self):
+ """
+ Returns the colour used to render a non-visited hypertext item.
+
+ :return: An instance of :class:`Colour`.
+
+ :note: This method is meaningful only for hypertext-like items.
+ """
+
+ return self._hypertextnewcolour
+
+
+ def SetHyperTextVisitedColour(self, colour):
+ """
+ Sets the colour used to render a visited hypertext item.
+
+ :param `colour`: a valid :class:`Colour` instance.
+
+ :note: This method is meaningful only for hypertext-like items.
+ """
+
+ self._hypertextvisitedcolour = colour
+ self._dirty = True
+
+
+ def GetHyperTextVisitedColour(self):
+ """
+ Returns the colour used to render a visited hypertext item.
+
+ :return: An instance of :class:`Colour`.
+
+ :note: This method is meaningful only for hypertext-like items.
+ """
+
+ return self._hypertextvisitedcolour
+
+
+ def SetItemVisited(self, item, visited=True):
+ """
+ Sets whether an hypertext item was visited.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `visited`: ``True`` to mark an hypertext item as visited, ``False`` otherwise.
+
+ :note: This method is meaningful only for hypertext-like items.
+ """
+
+ item.SetVisited(visited)
+ self.RefreshLine(item)
+
+
+ def GetItemVisited(self, item):
+ """
+ Returns whether an hypertext item was visited.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if the hypertext item has been visited, ``False`` otherwise.
+
+ :note: This method is meaningful only for hypertext-like items.
+ """
+
+ return item.GetVisited()
+
+
+ def SetHilightFocusColour(self, colour):
+ """
+ Sets the colour used to highlight focused selected items.
+
+ :param `colour`: a valid :class:`Colour` instance.
+
+ :note: This is applied only if gradient and Windows Vista selection
+ styles are disabled.
+ """
+
+ self._hilightBrush = wx.Brush(colour)
+ self.RefreshSelected()
+
+
+ def SetHilightNonFocusColour(self, colour):
+ """
+ Sets the colour used to highlight unfocused selected items.
+
+ :param `colour`: a valid :class:`Colour` instance.
+
+ :note: This is applied only if gradient and Windows Vista selection
+ styles are disabled.
+ """
+
+ self._hilightUnfocusedBrush = wx.Brush(colour)
+ self.RefreshSelected()
+
+
+ def GetHilightFocusColour(self):
+ """
+ Returns the colour used to highlight focused selected items.
+
+ :return: An instance of :class:`Colour`.
+
+ :note: This is used only if gradient and Windows Vista selection
+ styles are disabled.
+ """
+
+ return self._hilightBrush.GetColour()
+
+
+ def GetHilightNonFocusColour(self):
+ """
+ Returns the colour used to highlight unfocused selected items.
+
+ :return: An instance of :class:`Colour`.
+
+ :note: This is used only if gradient and Windows Vista selection
+ styles are disabled.
+ """
+
+ return self._hilightUnfocusedBrush.GetColour()
+
+
+ def SetFirstGradientColour(self, colour=None):
+ """
+ Sets the first gradient colour for gradient-style selections.
+
+ :param `colour`: if not ``None``, a valid :class:`Colour` instance. Otherwise,
+ the colour is taken from the system value ``wx.SYS_COLOUR_HIGHLIGHT``.
+ """
+
+ if colour is None:
+ colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+
+ self._firstcolour = colour
+ if self._usegradients:
+ self.RefreshSelected()
+
+
+ def SetSecondGradientColour(self, colour=None):
+ """
+ Sets the second gradient colour for gradient-style selections.
+
+ :param `colour`: if not ``None``, a valid :class:`Colour` instance. Otherwise,
+ the colour generated is a slightly darker version of the :class:`CustomTreeCtrl`
+ background colour.
+ """
+
+ if colour is None:
+ # No colour given, generate a slightly darker from the
+ # CustomTreeCtrl background colour
+ colour = self.GetBackgroundColour()
+ r, g, b = int(colour.Red()), int(colour.Green()), int(colour.Blue())
+ colour = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
+ colour = wx.Colour(colour[0], colour[1], colour[2])
+
+ self._secondcolour = colour
+
+ if self._usegradients:
+ self.RefreshSelected()
+
+
+ def GetFirstGradientColour(self):
+ """
+ Returns the first gradient colour for gradient-style selections.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._firstcolour
+
+
+ def GetSecondGradientColour(self):
+ """
+ Returns the second gradient colour for gradient-style selections.
+
+ :return: An instance of :class:`Colour`.
+ """
+
+ return self._secondcolour
+
+
+ def EnableSelectionGradient(self, enable=True):
+ """
+ Globally enables/disables drawing of gradient selections.
+
+ :param bool `enable`: ``True`` to enable gradient-style selections, ``False``
+ to disable it.
+
+ :note: Calling this method disables any Vista-style selection previously
+ enabled.
+ """
+
+ self._usegradients = enable
+ self._vistaselection = False
+ self.RefreshSelected()
+
+
+ def SetGradientStyle(self, vertical=0):
+ """
+ Sets the gradient style for gradient-style selections.
+
+ :param integer `vertical`: ``0`` for horizontal gradient-style selections, ``1`` for vertical
+ gradient-style selections.
+ """
+
+ # 0 = Horizontal, 1 = Vertical
+ self._gradientstyle = vertical
+
+ if self._usegradients:
+ self.RefreshSelected()
+
+
+ def GetGradientStyle(self):
+ """
+ Returns the gradient style for gradient-style selections.
+
+ :return: ``0`` for horizontal gradient-style selections, ``1`` for vertical
+ gradient-style selections.
+ """
+
+ return self._gradientstyle
+
+
+ def EnableSelectionVista(self, enable=True):
+ """
+ Globally enables/disables drawing of Windows Vista selections.
+
+ :param bool `enable`: ``True`` to enable Vista-style selections, ``False`` to
+ disable it.
+
+ :note: Calling this method disables any gradient-style selection previously
+ enabled.
+ """
+
+ self._usegradients = False
+ self._vistaselection = enable
+ self.RefreshSelected()
+
+
+ def SetBorderPen(self, pen):
+ """
+ Sets the pen used to draw the selected item border.
+
+ :param `pen`: an instance of :class:`Pen`.
+
+ :note: The border pen is not used if the Windows Vista selection style is applied.
+ """
+
+ self._borderPen = pen
+ self.RefreshSelected()
+
+
+ def GetBorderPen(self):
+ """
+ Returns the pen used to draw the selected item border.
+
+ :return: An instance of :class:`Pen`.
+
+ :note: The border pen is not used if the Windows Vista selection style is applied.
+ """
+
+ return self._borderPen
+
+
+ def SetConnectionPen(self, pen):
+ """
+ Sets the pen used to draw the connecting lines between items.
+
+ :param `pen`: an instance of :class:`Pen`.
+ """
+
+ self._dottedPen = pen
+ self._dirty = True
+
+
+ def GetConnectionPen(self):
+ """
+ Returns the pen used to draw the connecting lines between items.
+
+ :return: An instance of :class:`Pen`.
+ """
+
+ return self._dottedPen
+
+
+ def SetBackgroundImage(self, image):
+ """
+ Sets the :class:`CustomTreeCtrl` background image.
+
+ :param `image`: if not ``None``, an instance of :class:`Bitmap`.
+
+ :note: At present, the background image can only be used in "tile" mode.
+
+ .. todo:: Support background images also in stretch and centered modes.
+ """
+
+ self._backgroundImage = image
+ self.Refresh()
+
+
+ def GetBackgroundImage(self):
+ """
+ Returns the :class:`CustomTreeCtrl` background image (if any).
+
+ :return: An instance of :class:`Bitmap` if a background image is present, ``None`` otherwise.
+
+ :note: At present, the background image can only be used in "tile" mode.
+
+ .. todo:: Support background images also in stretch and centered modes.
+ """
+
+ return self._backgroundImage
+
+
+ def SetSeparatorColour(self, colour):
+ """
+ Sets the pen colour for separator-type items.
+
+ :param `colour`: a valid instance of :class:`Colour`.
+ """
+
+ self._separatorPen = wx.Pen(colour, 1)
+ self.Refresh()
+
+
+ def GetSeparatorColour(self, colour):
+ """
+ Returns the pen colour for separator-type items.
+
+ :return: An instance of :class:`Colour` representing the separator pen colour.
+ """
+
+ return self._separatorPen.GetColour()
+
+
+ def IsItemSeparator(self, item):
+ """
+ Returns whether an item is of separator type or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ return item.IsSeparator()
+
+
+ def GetItemWindow(self, item):
+ """
+ Returns the window associated to the item (if any).
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`Window` if the item has an associated window, ``None`` otherwise.
+ """
+
+ return item.GetWindow()
+
+
+ def SetItemWindow(self, item, wnd):
+ """
+ Sets the window for the given item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param `wnd`: if not ``None``, a non-toplevel window to be displayed next to
+ the item.
+
+ :raise: `Exception` if the input `item` is a separator and `wnd` is not ``None``.
+ """
+
+ if item.IsSeparator() and wnd is not None:
+ raise Exception("Separator items can not have an associated window")
+
+ if wnd is not None:
+ self._hasWindows = True
+ if item not in self._itemWithWindow:
+ self._itemWithWindow.append(item)
+ else:
+ self.DeleteItemWindow(item)
+ else:
+ self.DeleteItemWindow(item)
+
+ item.SetWindow(wnd)
+ self.CalculatePositions()
+ self.Refresh()
+ self.AdjustMyScrollbars()
+
+
+ def DeleteItemWindow(self, item):
+ """
+ Deletes the window associated to an item (if any).
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ if item.GetWindow() is None:
+ return
+
+ item.DeleteWindow()
+ if item in self._itemWithWindow:
+ self._itemWithWindow.remove(item)
+
+
+ def GetItemWindowEnabled(self, item):
+ """
+ Returns whether the window associated to the item is enabled.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if the item has an associated window and this window is
+ enabled, ``False`` in all other cases.
+ """
+
+ return item.GetWindowEnabled()
+
+
+ def SetItemWindowEnabled(self, item, enable=True):
+ """
+ Enables/disables the window associated to the item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `enable`: ``True`` to enable the associated window, ``False`` to
+ disable it.
+ """
+
+ item.SetWindowEnabled(enable)
+
+
+ def GetItemType(self, item):
+ """
+ Returns the item type.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An integer representing the item type.
+
+ :see: :meth:`~CustomTreeCtrl.SetItemType` for a description of valid item types.
+ """
+
+ return item.GetType()
+
+
+ def SetItemType(self, item, ct_type):
+ """
+ Sets the item type.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param integer `ct_type`: may be one of the following integers:
+
+ =============== =========================================
+ `ct_type` Value Description
+ =============== =========================================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== =========================================
+
+ :note: Regarding radiobutton-type items (with `ct_type` = 2), the following
+ approach is used:
+
+ - All peer-nodes that are radiobuttons will be mutually exclusive. In other words,
+ only one of a set of radiobuttons that share a common parent can be checked at
+ once. If a radiobutton node becomes checked, then all of its peer radiobuttons
+ must be unchecked.
+ - If a radiobutton node becomes unchecked, then all of its child nodes will become
+ inactive.
+
+ """
+
+ item.SetType(ct_type)
+ self.CalculatePositions()
+ self.Refresh()
+
+
+# -----------------------------------------------------------------------------
+# item status inquiries
+# -----------------------------------------------------------------------------
+
+ def IsVisible(self, item):
+ """
+ Returns whether the item is visible or not (i.e., its hierarchy is expanded
+ enough to show the item).
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if the item is visible, ``False`` if it is hidden.
+ """
+
+ # An item is only visible if it's not a descendant of a collapsed item
+ parent = item.GetParent()
+
+ while parent:
+
+ if not parent.IsExpanded():
+ return False
+
+ parent = parent.GetParent()
+
+ startX, startY = self.GetViewStart()
+ clientSize = self.GetClientSize()
+
+ rect = self.GetBoundingRect(item)
+
+ if not rect:
+ return False
+ if rect.GetWidth() == 0 or rect.GetHeight() == 0:
+ return False
+ if rect.GetBottom() < 0 or rect.GetTop() > clientSize.y:
+ return False
+ if rect.GetRight() < 0 or rect.GetLeft() > clientSize.x:
+ return False
+
+ return True
+
+
+ def ItemHasChildren(self, item):
+ """
+ Returns whether the item has children or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if the item has children, ``False`` otherwise.
+ """
+
+ # consider that the item does have children if it has the "+" button: it
+ # might not have them (if it had never been expanded yet) but then it
+ # could have them as well and it's better to err on this side rather than
+ # disabling some operations which are restricted to the items with
+ # children for an item which does have them
+ return item.HasPlus()
+
+
+ def IsExpanded(self, item):
+ """
+ Returns whether the item is expanded or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if the item is expanded, ``False`` if it is collapsed.
+ """
+
+ return item.IsExpanded()
+
+
+ def IsSelected(self, item):
+ """
+ Returns whether the item is selected or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if the item is selected, ``False`` otherwise.
+ """
+
+ return item.IsSelected()
+
+
+ def IsBold(self, item):
+ """
+ Returns whether the item font is bold or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if the item has bold text, ``False`` otherwise.
+ """
+
+ return item.IsBold()
+
+
+ def IsItalic(self, item):
+ """
+ Returns whether the item font is italic or not.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if the item has italic text, ``False`` otherwise.
+ """
+
+ return item.IsItalic()
+
+
+# -----------------------------------------------------------------------------
+# navigation
+# -----------------------------------------------------------------------------
+
+ def GetItemParent(self, item):
+ """
+ Returns the item parent (can be ``None`` for root items).
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`GenericTreeItem` or ``None`` for root items.
+ """
+
+ return item.GetParent()
+
+
+ def GetFirstChild(self, item):
+ """
+ Returns the item's first child and an integer value 'cookie'.
+ Call :meth:`~CustomTreeCtrl.GetNextChild` for the next child using this very 'cookie' return
+ value as an input.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: A tuple with the first value being an instance of :class:`GenericTreeItem` or ``None`` if there are no
+ further children, and as second value an integer parameter 'cookie'.
+
+ :note: This method returns ``None`` if there are no further children.
+ """
+
+ cookie = 0
+ return self.GetNextChild(item, cookie)
+
+
+ def GetNextChild(self, item, cookie):
+ """
+ Returns the item's next child.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param `cookie`: a parameter which is opaque for the application but is necessary
+ for the library to make these functions reentrant (i.e. allow more than one
+ enumeration on one and the same object simultaneously).
+
+ :return: A tuple with the first value being an instance of :class:`GenericTreeItem` or ``None`` if there are no
+ further children, and as second value an integer parameter 'cookie'.
+
+ :note: This method returns ``None`` if there are no further children.
+ """
+
+ children = item.GetChildren()
+
+ # it's ok to cast cookie to size_t, we never have indices big enough to
+ # overflow "void *"
+
+ if cookie < len(children):
+
+ return children[cookie], cookie+1
+
+ else:
+
+ # there are no more of them
+ return None, cookie
+
+
+ def GetLastChild(self, item):
+ """
+ Returns the item last child.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`GenericTreeItem` or ``None`` if there are no
+ further children.
+ """
+
+ children = item.GetChildren()
+ return (len(children) == 0 and [None] or [children[-1]])[0]
+
+
+ def GetNextSibling(self, item):
+ """
+ Returns the next sibling of an item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`GenericTreeItem` or ``None`` if there are no
+ further siblings.
+
+ :note: This method returns ``None`` if there are no further siblings.
+ """
+
+ i = item
+ parent = i.GetParent()
+
+ if parent == None:
+
+ # root item doesn't have any siblings
+ return None
+
+ siblings = parent.GetChildren()
+ index = siblings.index(i)
+
+ n = index + 1
+ return (n == len(siblings) and [None] or [siblings[n]])[0]
+
+
+ def GetPrevSibling(self, item):
+ """
+ Returns the previous sibling of an item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`GenericTreeItem` or ``None`` if there are no
+ further siblings.
+
+ :note: This method returns ``None`` if there are no further siblings.
+ """
+
+ i = item
+ parent = i.GetParent()
+
+ if parent == None:
+
+ # root item doesn't have any siblings
+ return None
+
+ siblings = parent.GetChildren()
+ index = siblings.index(i)
+
+ return (index == 0 and [None] or [siblings[index-1]])[0]
+
+
+ def GetNext(self, item):
+ """
+ Returns the next item. Only for internal use right now.
+
+ :return: An instance of :class:`GenericTreeItem` or ``None`` if there are no
+ further items.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ i = item
+
+ # First see if there are any children.
+ children = i.GetChildren()
+ if len(children) > 0:
+ return children[0]
+ else:
+ # Try a sibling of this or ancestor instead
+ p = item
+ toFind = None
+ while p and not toFind:
+ toFind = self.GetNextSibling(p)
+ p = self.GetItemParent(p)
+
+ return toFind
+
+
+ def GetPrev(self, item):
+ """
+ Returns the previous item. Only for internal use right now.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`GenericTreeItem`
+ """
+
+ # Look for a previous sibling of this item
+ prevSibling = self.GetPrevSibling(item)
+ if prevSibling:
+
+ # return it's last child or itself if has not got any children
+ if len(prevSibling.GetChildren()) > 0:
+ return self.GetLastChild(prevSibling)
+
+ return prevSibling
+
+ # item has not got a previous sibling, return it's parent
+ return self.GetItemParent(item)
+
+
+ def GetNextExpanded(self, item):
+ """
+ Returns the next expanded item after the input one.
+
+ :param `item`: an instance of :class:`TreeListItem`.
+ """
+
+ nextSibling = self.GetNextSibling(item)
+ if nextSibling:
+ if nextSibling.IsExpanded():
+ return nextSibling
+
+ return self.GetNextExpanded(prevSibling)
+
+ return None
+
+
+ def GetPrevExpanded(self, item):
+ """
+ Returns the previous expanded item before the input one.
+
+ :param `item`: an instance of :class:`TreeListItem`.
+ """
+
+ prevSibling = self.GetPrevSibling(item)
+ if prevSibling:
+ if prevSibling.IsExpanded():
+ return prevSibling
+
+ return self.GetPrevExpanded(prevSibling)
+
+ return None
+
+
+ def GetFirstVisibleItem(self):
+ """
+ Returns the first visible item.
+
+ :return: An instance of :class:`GenericTreeItem` or ``None`` if there are no
+ visible items.
+ """
+
+ id = self.GetRootItem()
+ if not id:
+ return id
+
+ while id:
+ if self.IsVisible(id):
+ return id
+ id = self.GetNext(id)
+
+ return None
+
+
+ def GetNextVisible(self, item):
+ """
+ Returns the next visible item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`GenericTreeItem` or ``None`` if there are no
+ next visible items.
+ """
+
+ id = item
+
+ while id:
+ id = self.GetNext(id)
+ if id and self.IsVisible(id):
+ return id
+
+ return None
+
+
+ def GetPrevVisible(self, item):
+ """
+ Returns the previous visible item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: An instance of :class:`GenericTreeItem` or ``None`` if there are no
+ previous visible items.
+ """
+
+ # find a previous sibling or parent which is visible
+ lastGoodItem = self.GetPrevSibling(item)
+ if not lastGoodItem or not self.IsVisible(lastGoodItem):
+ parent = self.GetItemParent(item)
+ rootHidden = self.HasAGWFlag(TR_HIDE_ROOT)
+ rootItem = self.GetRootItem()
+
+ while parent and not (rootHidden and parent == rootItem):
+ if self.IsVisible(parent):
+ lastGoodItem = parent
+ break
+ parent = self.GetItemParent(parent)
+
+ if not lastGoodItem:
+ return None
+
+ # test if found item has visible children, if so and if the found item is not the
+ # parent of the current item traverse the found item to the last visible child
+ if not self.HasChildren(lastGoodItem) or not self.IsExpanded(lastGoodItem) or \
+ (self.GetItemParent(item) == lastGoodItem):
+ return lastGoodItem
+
+ lastChild = self.GetLastChild(lastGoodItem)
+ while lastChild and self.IsVisible(lastChild):
+ lastGoodItem = lastChild
+ lastChild = self.GetLastChild(lastGoodItem)
+
+ return lastGoodItem
+
+
+ def ResetEditControl(self):
+ """ Called by :class:`TreeTextCtrl` when it marks itself for deletion. """
+
+ if self._editCtrl is not None:
+ self._editCtrl.Destroy()
+ self._editCtrl = None
+
+ self.CalculatePositions()
+ self.Refresh()
+ self.AdjustMyScrollbars()
+
+
+ def FindItem(self, idParent, prefixOrig):
+ """
+ Finds the first item starting with the given prefix after the given parent.
+
+ :param integer `idParent`: an instance of :class:`GenericTreeItem`;
+ :param string `prefixOrig`: a string containing the item text prefix.
+
+ :return: An instance of :class:`GenericTreeItem` or ``None`` if no item has been found.
+ """
+
+ # match is case insensitive as this is more convenient to the user: having
+ # to press Shift-letter to go to the item starting with a capital letter
+ # would be too bothersome
+ prefix = prefixOrig.lower()
+
+ # determine the starting point: we shouldn't take the current item (this
+ # allows to switch between two items starting with the same letter just by
+ # pressing it) but we shouldn't jump to the next one if the user is
+ # continuing to type as otherwise he might easily skip the item he wanted
+ id = idParent
+
+ if len(prefix) == 1:
+ id = self.GetNext(id)
+
+ # look for the item starting with the given prefix after it
+ while id and not self.GetItemText(id).lower().startswith(prefix):
+
+ id = self.GetNext(id)
+
+ # if we haven't found anything...
+ if not id:
+
+ # ... wrap to the beginning
+ id = self.GetRootItem()
+ if self.HasAGWFlag(TR_HIDE_ROOT):
+ # can't select virtual root
+ id = self.GetNext(id)
+ if idParent == self.GetRootItem():
+ # no tree item selected and idParent is not reachable
+ return id
+
+ # and try all the items (stop when we get to the one we started from)
+ while id != idParent and not self.GetItemText(id).lower().startswith(prefix):
+ id = self.GetNext(id)
+
+ return id
+
+
+# -----------------------------------------------------------------------------
+# operations
+# -----------------------------------------------------------------------------
+
+ def DoInsertItem(self, parentId, previous, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None, separator=False):
+ """
+ Actually inserts an item in the tree.
+
+ :param `parentId`: an instance of :class:`GenericTreeItem` representing the
+ item's parent;
+ :param integer `previous`: the index at which we should insert the item;
+ :param string `text`: the item text label;
+ :param integer `ct_type`: the item type (see :meth:`~CustomTreeCtrl.SetItemType` for a list of valid
+ item types);
+ :param `wnd`: if not ``None``, a non-toplevel window to show next to the item, any
+ subclass of :class:`Window` except top-level windows;
+ :param integer `image`: an index within the normal image list specifying the image to
+ use for the item in unselected state;
+ :param integer `selImage`: an index within the normal image list specifying the image to
+ use for the item in selected state; if `image` > -1 and `selImage` is -1, the
+ same image is used for both selected and unselected items;
+ :param object `data`: associate the given Python object `data` with the item;
+ :param bool `separator`: ``True`` if the item is a separator, ``False`` otherwise.
+
+ :return: An instance of :class:`GenericTreeItem` upon successful insertion.
+
+ :raise: `Exception` in the following cases:
+
+ - The item window is not ``None`` but the ``TR_HAS_VARIABLE_ROW_HEIGHT`` flag has not been
+ set for :class:`CustomTreeCtrl`;
+ - The item has multiline text (with line-breaks in it) but the ``TR_HAS_VARIABLE_ROW_HEIGHT``
+ flag has not been set for :class:`CustomTreeCtrl`;
+ - The `ct_type` attribute is less than ``0`` or greater than ``2``;
+ - The parent item is a separator;
+ - The item is a separator but it has text or an associated window.
+
+
+ :note: Separator items should not have children, text labels or an associated window.
+ """
+
+ if wnd is not None and not self.HasAGWFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
+ raise Exception("\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
+
+ if text.find("\n") >= 0 and not self.HasAGWFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
+ raise Exception("\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
+
+ if ct_type < 0 or ct_type > 2:
+ raise Exception("\nERROR: Item Type Should Be 0 (Normal), 1 (CheckBox) or 2 (RadioButton). ")
+
+ if separator:
+ if wnd:
+ raise Exception("Separator items can not have associated windows")
+ if text.strip():
+ raise Exception("Separator items can not text labels")
+
+ parent = parentId
+
+ if not parent:
+ # should we give a warning here?
+ return self.AddRoot(text, ct_type, wnd, image, selImage, data)
+
+ self._dirty = True # do this first so stuff below doesn't cause flicker
+
+ item = GenericTreeItem(parent, text, ct_type, wnd, image, selImage, data, separator)
+
+ if wnd is not None:
+ self._hasWindows = True
+ self._itemWithWindow.append(item)
+
+ parent.Insert(item, previous)
+
+ return item
+
+
+ def AddRoot(self, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
+ """
+ Adds a root item to the :class:`CustomTreeCtrl`.
+
+ :param string `text`: the item text label;
+ :param integer `ct_type`: the item type (see :meth:`~CustomTreeCtrl.SetItemType` for a list of valid
+ item types);
+ :param `wnd`: if not ``None``, a non-toplevel window to show next to the item,
+ any subclass of :class:`Window` except top-level windows;
+ :param integer `image`: an index within the normal image list specifying the image to
+ use for the item in unselected state;
+ :param integer `selImage`: an index within the normal image list specifying the image to
+ use for the item in selected state; if `image` > -1 and `selImage` is -1, the
+ same image is used for both selected and unselected items;
+ :param object `data`: associate the given Python object `data` with the item.
+
+ :return: An instance of :class:`GenericTreeItem` upon successful insertion.
+
+ :raise: `Exception` in the following cases:
+
+ - There already is a root item in the tree;
+ - The item window is not ``None`` but the ``TR_HAS_VARIABLE_ROW_HEIGHT`` flag has not been
+ set for :class:`CustomTreeCtrl`;
+ - The item has multiline text (with line-breaks in it) but the ``TR_HAS_VARIABLE_ROW_HEIGHT``
+ flag has not been set for :class:`CustomTreeCtrl`;
+ - The `ct_type` attribute is less than ``0`` or greater than ``2``.
+
+ .. warning::
+
+ Only one root is allowed to exist in any given instance of :class:`CustomTreeCtrl`.
+
+ """
+
+ if self._anchor:
+ raise Exception("\nERROR: Tree Can Have Only One Root")
+
+ if wnd is not None and not self.HasAGWFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
+ raise Exception("\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
+
+ if text.find("\n") >= 0 and not self.HasAGWFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
+ raise Exception("\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
+
+ if ct_type < 0 or ct_type > 2:
+ raise Exception("\nERROR: Item Type Should Be 0 (Normal), 1 (CheckBox) or 2 (RadioButton). ")
+
+ self._dirty = True # do this first so stuff below doesn't cause flicker
+
+ self._anchor = GenericTreeItem(None, text, ct_type, wnd, image, selImage, data)
+
+ if wnd is not None:
+ self._hasWindows = True
+ self._itemWithWindow.append(self._anchor)
+
+ if self.HasAGWFlag(TR_HIDE_ROOT):
+
+ # if root is hidden, make sure we can navigate
+ # into children
+ self._anchor.SetHasPlus()
+ self._anchor.Expand()
+ self.CalculatePositions()
+
+ if not self.HasAGWFlag(TR_MULTIPLE):
+
+ self._current = self._key_current = self._anchor
+ self._current.SetHilight(True)
+
+ return self._anchor
+
+
+ def PrependItem(self, parent, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None, separator=False):
+ """
+ Prepends an item as a first child of parent.
+
+ :param `parent`: an instance of :class:`GenericTreeItem` representing the
+ item's parent;
+ :param string `text`: the item text label;
+ :param integer `ct_type`: the item type (see :meth:`~CustomTreeCtrl.SetItemType` for a list of valid
+ item types);
+ :param `wnd`: if not ``None``, a non-toplevel window to show next to the item, any
+ subclass of :class:`Window` except top-level windows;
+ :param integer `image`: an index within the normal image list specifying the image to
+ use for the item in unselected state;
+ :param integer `selImage`: an index within the normal image list specifying the image to
+ use for the item in selected state; if `image` > -1 and `selImage` is -1, the
+ same image is used for both selected and unselected items;
+ :param object `data`: associate the given Python object `data` with the item;
+ :param bool `separator`: ``True`` if the item is a separator, ``False`` otherwise.
+
+ :return: An instance of :class:`GenericTreeItem` upon successful insertion.
+
+ :see: :meth:`~CustomTreeCtrl.DoInsertItem` for possible exceptions generated by this method.
+ """
+
+ return self.DoInsertItem(parent, 0, text, ct_type, wnd, image, selImage, data, separator)
+
+
+ def InsertItemByItem(self, parentId, idPrevious, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None, separator=False):
+ """
+ Inserts an item after the given previous.
+
+ :param `parentId`: an instance of :class:`GenericTreeItem` representing the
+ item's parent;
+ :param `idPrevious`: an instance of :class:`GenericTreeItem` representing the
+ previous item;
+ :param string `text`: the item text label;
+ :param integer `ct_type`: the item type (see :meth:`~CustomTreeCtrl.SetItemType` for a list of valid
+ item types);
+ :param `wnd`: if not ``None``, a non-toplevel window to show next to the item,
+ any subclass of :class:`Window`;
+ :param integer `image`: an index within the normal image list specifying the image to
+ use for the item in unselected state;
+ :param integer `selImage`: an index within the normal image list specifying the image to
+ use for the item in selected state; if `image` > -1 and `selImage` is -1, the
+ same image is used for both selected and unselected items;
+ :param object `data`: associate the given Python object `data` with the item;
+ :param bool `separator`: ``True`` if the item is a separator, ``False`` otherwise.
+
+ :return: An instance of :class:`GenericTreeItem` upon successful insertion.
+
+ :raise: `Exception` if the previous item is not a sibling.
+
+ :see: :meth:`~CustomTreeCtrl.DoInsertItem` for other possible exceptions generated by this method.
+ """
+
+ parent = parentId
+
+ if not parent:
+ # should we give a warning here?
+ return self.AddRoot(text, ct_type, wnd, image, selImage, data)
+
+ index = -1
+ if idPrevious:
+
+ try:
+ index = parent.GetChildren().index(idPrevious)
+ except:
+ raise Exception("ERROR: Previous Item In CustomTreeCtrl.InsertItem() Is Not A Sibling")
+
+ return self.DoInsertItem(parentId, index+1, text, ct_type, wnd, image, selImage, data, separator)
+
+
+ def InsertItemByIndex(self, parentId, idPrevious, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None, separator=False):
+ """
+ Inserts an item after the given previous.
+
+ :param `parentId`: an instance of :class:`GenericTreeItem` representing the
+ item's parent;
+ :param `idPrevious`: the index at which we should insert the new item;
+ :param string `text`: the item text label;
+ :param integer `ct_type`: the item type (see :meth:`~CustomTreeCtrl.SetItemType` for a list of valid
+ item types);
+ :param `wnd`: if not ``None``, a non-toplevel window to show next to the item,
+ any subclass of :class:`Window`;
+ :param integer `image`: an index within the normal image list specifying the image to
+ use for the item in unselected state;
+ :param integer `selImage`: an index within the normal image list specifying the image to
+ use for the item in selected state; if `image` > -1 and `selImage` is -1, the
+ same image is used for both selected and unselected items;
+ :param object `data`: associate the given Python object `data` with the item;
+ :param bool `separator`: ``True`` if the item is a separator, ``False`` otherwise.
+
+ :return: An instance of :class:`GenericTreeItem` upon successful insertion.
+
+ :see: :meth:`~CustomTreeCtrl.DoInsertItem` for possible exceptions generated by this method.
+ """
+
+ parent = parentId
+
+ if not parent:
+ # should we give a warning here?
+ return self.AddRoot(text, ct_type, wnd, image, selImage, data)
+
+ return self.DoInsertItem(parentId, idPrevious, text, ct_type, wnd, image, selImage, data, separator)
+
+
+ def InsertItem(self, parentId, input, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None, separator=False):
+ """
+ Inserts an item after the given previous.
+
+ :return: An instance of :class:`GenericTreeItem` upon successful insertion.
+
+ :see: :meth:`~CustomTreeCtrl.InsertItemByIndex` and :meth:`~CustomTreeCtrl.InsertItemByItem` for an explanation of
+ the input parameters.
+
+ :see: :meth:`~CustomTreeCtrl.DoInsertItem` for possible exceptions generated by this method.
+ """
+
+ if type(input) == type(1):
+ return self.InsertItemByIndex(parentId, input, text, ct_type, wnd, image, selImage, data, separator)
+ else:
+ return self.InsertItemByItem(parentId, input, text, ct_type, wnd, image, selImage, data, separator)
+
+
+ def AppendItem(self, parentId, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
+ """
+ Appends an item as a last child of its parent.
+
+ :param `parentId`: an instance of :class:`GenericTreeItem` representing the
+ item's parent;
+ :param string `text`: the item text label;
+ :param integer `ct_type`: the item type (see :meth:`~CustomTreeCtrl.SetItemType` for a list of valid
+ item types);
+ :param `wnd`: if not ``None``, a non-toplevel window to show next to the item,
+ any subclass of :class:`Window`;
+ :param integer `image`: an index within the normal image list specifying the image to
+ use for the item in unselected state;
+ :param integer `selImage`: an index within the normal image list specifying the image to
+ use for the item in selected state; if `image` > -1 and `selImage` is -1, the
+ same image is used for both selected and unselected items;
+ :param object `data`: associate the given Python object `data` with the item.
+
+ :return: An instance of :class:`GenericTreeItem` upon successful insertion.
+
+ :see: :meth:`~CustomTreeCtrl.DoInsertItem` for possible exceptions generated by this method.
+ """
+
+ parent = parentId
+
+ if not parent:
+ # should we give a warning here?
+ return self.AddRoot(text, ct_type, wnd, image, selImage, data)
+
+ return self.DoInsertItem(parent, len(parent.GetChildren()), text, ct_type, wnd, image, selImage, data)
+
+
+ def AppendSeparator(self, parentId):
+ """
+ Appends an horizontal line separator as a last child of its parent.
+
+ :param `parentId`: an instance of :class:`GenericTreeItem` representing the
+ separator's parent.
+
+ :return: An instance of :class:`GenericTreeItem` upon successful insertion.
+
+ :see: :meth:`~CustomTreeCtrl.DoInsertItem` for possible exceptions generated by this method.
+ """
+
+ parent = parentId
+ return self.DoInsertItem(parent, len(parent.GetChildren()), "", separator=True)
+
+
+ def InsertSeparator(self, parentId, input):
+ """
+ Inserts a separator item after the given previous.
+
+ :return: An instance of :class:`GenericTreeItem` upon successful insertion.
+
+ :see: :meth:`~CustomTreeCtrl.InsertItemByIndex` and :meth:`~CustomTreeCtrl.InsertItemByItem` for an explanation of
+ the input parameters.
+
+ :see: :meth:`~CustomTreeCtrl.DoInsertItem` for possible exceptions generated by this method.
+ """
+
+ return self.InsertItem(parentId, input, "", separator=True)
+
+
+ def PrependSeparator(self, parent):
+ """
+ Prepends a separator item as a first child of parent.
+
+ :param `parent`: an instance of :class:`GenericTreeItem` representing the
+ item's parent.
+
+ :return: An instance of :class:`GenericTreeItem` upon successful insertion.
+
+ :see: :meth:`~CustomTreeCtrl.DoInsertItem` for possible exceptions generated by this method.
+ """
+
+ return self.PrependItem(parent, 0, separator=True)
+
+
+ def SendDeleteEvent(self, item):
+ """
+ Actually sends the ``EVT_TREE_DELETE_ITEM`` event.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ event = TreeEvent(wxEVT_TREE_DELETE_ITEM, self.GetId())
+ event._item = item
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def IsDescendantOf(self, parent, item):
+ """
+ Checks if the given item is under another one in the tree hierarchy.
+
+ :param `parent`: an instance of :class:`GenericTreeItem`, representing the possible
+ parent of `item`;
+ :param `item`: another instance of :class:`GenericTreeItem`.
+
+ :return: ``True`` if `item` is a descendant of `parent`, ``False`` otherwise.
+ """
+
+ while item:
+
+ if item == parent:
+
+ # item is a descendant of parent
+ return True
+
+ item = item.GetParent()
+
+ return False
+
+
+ # Don't leave edit or selection on a child which is about to disappear
+ def ChildrenClosing(self, item):
+ """
+ We are about to destroy the item children.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ if self._editCtrl != None and item != self._editCtrl.item() and self.IsDescendantOf(item, self._editCtrl.item()):
+ self._editCtrl.StopEditing()
+
+ if item != self._key_current and self.IsDescendantOf(item, self._key_current):
+ self._key_current = None
+
+ if self.IsDescendantOf(item, self._select_me):
+ self._select_me = item
+
+ if item != self._current and self.IsDescendantOf(item, self._current):
+ self._current.SetHilight(False)
+ self._current = None
+ self._select_me = item
+
+
+ def DeleteChildren(self, item):
+ """
+ Delete all the item's children.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ self._dirty = True # do this first so stuff below doesn't cause flicker
+
+ self.ChildrenClosing(item)
+ item.DeleteChildren(self)
+
+
+ def Delete(self, item):
+ """
+ Deletes an item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :note: This method sends the ``EVT_TREE_DELETE_ITEM`` event.
+ """
+
+ self._dirty = True # do this first so stuff below doesn't cause flicker
+
+ if self._editCtrl != None and self.IsDescendantOf(item, self._editCtrl.item()):
+ # can't delete the item being edited, cancel editing it first
+ self._editCtrl.StopEditing()
+
+ parent = item.GetParent()
+
+ # don't keep stale pointers around!
+ if self.IsDescendantOf(item, self._key_current):
+
+ # Don't silently change the selection:
+ # do it properly in idle time, so event
+ # handlers get called.
+
+ # self._key_current = parent
+ self._key_current = None
+
+ # self._select_me records whether we need to select
+ # a different item, in idle time.
+ if self._select_me and self.IsDescendantOf(item, self._select_me):
+ self._select_me = parent
+
+ if self.IsDescendantOf(item, self._current):
+
+ # Don't silently change the selection:
+ # do it properly in idle time, so event
+ # handlers get called.
+
+ # self._current = parent
+ self._current = None
+ self._select_me = parent
+
+ # remove the item from the tree
+ if parent:
+
+ parent.GetChildren().remove(item) # remove by value
+
+ else: # deleting the root
+
+ # nothing will be left in the tree
+ self._anchor = None
+
+ # and delete all of its children and the item itself now
+ item.DeleteChildren(self)
+ self.SendDeleteEvent(item)
+
+ if item == self._select_me:
+ self._select_me = None
+
+ # Remove the item with window
+ if item in self._itemWithWindow:
+ wnd = item.GetWindow()
+ wnd.Hide()
+ wnd.Destroy()
+ item._wnd = None
+ self._itemWithWindow.remove(item)
+
+ del item
+
+
+ def DeleteAllItems(self):
+ """ Deletes all items in the :class:`CustomTreeCtrl`. """
+
+ if self._anchor:
+ self.Delete(self._anchor)
+
+
+ def Expand(self, item):
+ """
+ Expands an item, sending a ``EVT_TREE_ITEM_EXPANDING`` and
+ ``EVT_TREE_ITEM_EXPANDED`` events.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :raise: `Exception` if you try to expand a hidden root (i.e., when the ``TR_HIDE_ROOT``
+ style is set for :class:`CustomTreeCtrl`).
+ """
+
+ if self.HasAGWFlag(TR_HIDE_ROOT) and item == self.GetRootItem():
+ raise Exception("\nERROR: Can't Expand An Hidden Root. ")
+
+ if not item.HasPlus():
+ return
+
+ if item.IsExpanded():
+ return
+
+ if self._sendEvent:
+ event = TreeEvent(wxEVT_TREE_ITEM_EXPANDING, self.GetId())
+ event._item = item
+ event.SetEventObject(self)
+
+ if self.GetEventHandler().ProcessEvent(event) and not event.IsAllowed():
+ # cancelled by program
+ return
+
+ item.Expand()
+
+ if not self._sendEvent:
+ # We are in ExpandAll/ExpandAllChildren
+ return
+
+ self.CalculatePositions()
+ self.RefreshSubtree(item)
+
+ if self._hasWindows:
+ # We hide the associated window here, we may show it after
+ self.HideWindows()
+
+ event.SetEventType(wxEVT_TREE_ITEM_EXPANDED)
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def ExpandAllChildren(self, item):
+ """
+ Expands all the items children of the input item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :note: This method suppresses the ``EVT_TREE_ITEM_EXPANDING`` and
+ ``EVT_TREE_ITEM_EXPANDED`` events because expanding many items int the
+ control would be too slow then.
+ """
+
+ self._sendEvent = False
+ if not self.HasAGWFlag(TR_HIDE_ROOT) or item != self.GetRootItem():
+ self.Expand(item)
+ if not self.IsExpanded(item):
+ self._sendEvent = True
+ return
+
+ child, cookie = self.GetFirstChild(item)
+
+ while child:
+ self.ExpandAllChildren(child)
+ child, cookie = self.GetNextChild(item, cookie)
+
+ self._sendEvent = True
+ self._dirty = True
+
+
+ def ExpandAll(self):
+ """
+ Expands all :class:`CustomTreeCtrl` items.
+
+ :note: This method suppresses the ``EVT_TREE_ITEM_EXPANDING`` and
+ ``EVT_TREE_ITEM_EXPANDED`` events because expanding many items int the
+ control would be too slow then.
+ """
+
+ if self._anchor:
+ self.ExpandAllChildren(self._anchor)
+
+ self._sendEvent = True
+ self._dirty = True
+
+
+ def Collapse(self, item):
+ """
+ Collapse an item, sending a ``EVT_TREE_ITEM_COLLAPSING`` and
+ ``EVT_TREE_ITEM_COLLAPSED`` events.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :raise: `Exception` if you try to collapse a hidden root (i.e., when the ``TR_HIDE_ROOT``
+ style is set for :class:`CustomTreeCtrl`).
+ """
+
+ if self.HasAGWFlag(TR_HIDE_ROOT) and item == self.GetRootItem():
+ raise Exception("\nERROR: Can't Collapse An Hidden Root. ")
+
+ if not item.IsExpanded():
+ return
+
+ event = TreeEvent(wxEVT_TREE_ITEM_COLLAPSING, self.GetId())
+ event._item = item
+ event.SetEventObject(self)
+ if self.GetEventHandler().ProcessEvent(event) and not event.IsAllowed():
+ # cancelled by program
+ return
+
+ self.ChildrenClosing(item)
+ item.Collapse()
+
+ self.CalculatePositions()
+ self.Refresh()
+
+ if self._hasWindows:
+ self.HideWindows()
+
+ self.AdjustMyScrollbars()
+
+ event.SetEventType(wxEVT_TREE_ITEM_COLLAPSED)
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def CollapseAndReset(self, item):
+ """
+ Collapse the given item and deletes its children.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ self.Collapse(item)
+ self.DeleteChildren(item)
+
+
+ def Toggle(self, item):
+ """
+ Toggles the item state (collapsed/expanded).
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ if item.IsExpanded():
+ self.Collapse(item)
+ else:
+ self.Expand(item)
+
+
+ def HideWindows(self):
+ """ Hides the windows associated to the items. Used internally. """
+
+ for child in self._itemWithWindow:
+ if not self.IsVisible(child):
+ wnd = child.GetWindow()
+ if wnd:
+ wnd.Hide()
+
+
+ def Unselect(self):
+ """ Unselects the current selection. """
+
+ if self._current:
+ self._current.SetHilight(False)
+ self.RefreshLine(self._current)
+
+ self._current = None
+ self._select_me = None
+
+
+ def UnselectAllChildren(self, item):
+ """
+ Unselects all the children of the given item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ if item.IsSelected():
+ item.SetHilight(False)
+ self.RefreshLine(item)
+
+ if item.HasChildren():
+ for child in item.GetChildren():
+ self.UnselectAllChildren(child)
+
+
+ def SelectAllChildren(self, item):
+ """
+ Selects all the children of the given item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :raise: `Exception` if used without the ``TR_EXTENDED`` or ``TR_MULTIPLE`` style set.
+
+ :note: This method can be used only if :class:`CustomTreeCtrl` has the ``TR_MULTIPLE`` or ``TR_EXTENDED``
+ style set.
+ """
+
+ if not self.HasAGWFlag(TR_MULTIPLE) and not self.HasAGWFlag(TR_EXTENDED):
+ raise Exception("SelectAllChildren can be used only with multiple selection enabled.")
+
+ if not item.IsSelected():
+ item.SetHilight(True)
+ self.RefreshLine(item)
+
+ if item.HasChildren():
+ for child in item.GetChildren():
+ self.SelectAllChildren(child)
+
+
+ def UnselectAll(self):
+ """ Unselect all the items. """
+
+ rootItem = self.GetRootItem()
+
+ # the tree might not have the root item at all
+ if rootItem:
+ self.UnselectAllChildren(rootItem)
+
+ self.Unselect()
+
+
+ def SelectAll(self):
+ """
+ Selects all the item in the tree.
+
+ :raise: `Exception` if used without the ``TR_EXTENDED`` or ``TR_MULTIPLE`` style set.
+
+ :note: This method can be used only if :class:`CustomTreeCtrl` has the ``TR_MULTIPLE`` or ``TR_EXTENDED``
+ style set.
+ """
+
+ if not self.HasAGWFlag(TR_MULTIPLE) and not self.HasAGWFlag(TR_EXTENDED):
+ raise Exception("SelectAll can be used only with multiple selection enabled.")
+
+ rootItem = self.GetRootItem()
+
+ # the tree might not have the root item at all
+ if rootItem:
+ self.SelectAllChildren(rootItem)
+
+
+ # Recursive function !
+ # To stop we must have crt_item<last_item
+ # Algorithm :
+ # Tag all next children, when no more children,
+ # Move to parent (not to tag)
+ # Keep going... if we found last_item, we stop.
+
+ def TagNextChildren(self, crt_item, last_item, select):
+ """ Used internally. """
+
+ parent = crt_item.GetParent()
+
+ if parent == None: # This is root item
+ return self.TagAllChildrenUntilLast(crt_item, last_item, select)
+
+ children = parent.GetChildren()
+ index = children.index(crt_item)
+
+ count = len(children)
+
+ for n in xrange(index+1, count):
+ if self.TagAllChildrenUntilLast(children[n], last_item, select):
+ return True
+
+ return self.TagNextChildren(parent, last_item, select)
+
+
+ def TagAllChildrenUntilLast(self, crt_item, last_item, select):
+ """ Used internally. """
+
+ crt_item.SetHilight(select)
+ self.RefreshLine(crt_item)
+
+ if crt_item == last_item:
+ return True
+
+ if crt_item.HasChildren():
+ for child in crt_item.GetChildren():
+ if self.TagAllChildrenUntilLast(child, last_item, select):
+ return True
+
+ return False
+
+
+ def SelectItemRange(self, item1, item2):
+ """
+ Selects all the items between `item1` and `item2`.
+
+ :param `item1`: an instance of :class:`GenericTreeItem`, representing the first
+ item in the range to select;
+ :param `item2`: an instance of :class:`GenericTreeItem`, representing the last
+ item in the range to select.
+
+ :raise: `Exception` if used without the ``TR_EXTENDED`` or ``TR_MULTIPLE`` style set.
+
+ :note: This method can be used only if :class:`CustomTreeCtrl` has the ``TR_MULTIPLE`` or ``TR_EXTENDED``
+ style set.
+ """
+
+ if not self.HasAGWFlag(TR_MULTIPLE) and not self.HasAGWFlag(TR_EXTENDED):
+ raise Exception("SelectItemRange can be used only with multiple selection enabled.")
+
+ self._select_me = None
+
+ # item2 is not necessary after item1
+ # choice first' and 'last' between item1 and item2
+ first = (item1.GetY() < item2.GetY() and [item1] or [item2])[0]
+ last = (item1.GetY() < item2.GetY() and [item2] or [item1])[0]
+
+ select = self._current.IsSelected()
+
+ if self.TagAllChildrenUntilLast(first, last, select):
+ return
+
+ self.TagNextChildren(first, last, select)
+
+
+ def DoSelectItem(self, item, unselect_others=True, extended_select=False, from_key=False):
+ """
+ Actually selects/unselects an item, sending ``EVT_TREE_SEL_CHANGING`` and
+ ``EVT_TREE_SEL_CHANGED`` events.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `unselect_others`: if ``True``, all the other selected items are
+ unselected.
+ :param bool `extended_select`: ``True`` if the :class:`CustomTreeCtrl` is using the
+ ``TR_EXTENDED`` style;
+ :param bool `from_key`: ``True`` to indicate that the selection was made via a keyboard
+ key, ``False`` if it was a mouse selection.
+ """
+
+ self._select_me = None
+
+ is_single = not (self.GetAGWWindowStyleFlag() & TR_MULTIPLE)
+
+ # to keep going anyhow !!!
+ if is_single:
+ if item.IsSelected() and not from_key:
+ # Handles hypertext items
+ self.HandleHyperLink(item)
+ return # nothing else to do
+ unselect_others = True
+ extended_select = False
+
+ elif unselect_others and item.IsSelected():
+
+ # selection change if there is more than one item currently selected
+ if len(self.GetSelections()) == 1 and not from_key:
+ # Handles hypertext items
+ self.HandleHyperLink(item)
+ return
+
+ event = TreeEvent(wxEVT_TREE_SEL_CHANGING, self.GetId())
+ event._item = item
+ event._itemOld = self._current
+ event.SetEventObject(self)
+ # TODO : Here we don't send any selection mode yet !
+
+ if self.GetEventHandler().ProcessEvent(event) and not event.IsAllowed():
+ return
+
+ parent = self.GetItemParent(item)
+ while parent:
+ if not self.IsExpanded(parent):
+ self.Expand(parent)
+
+ parent = self.GetItemParent(parent)
+
+ # ctrl press
+ if unselect_others:
+ if is_single:
+ self.Unselect() # to speed up thing
+ else:
+ self.UnselectAll()
+
+ # shift press
+ if extended_select:
+ if not self._current:
+ self._current = self._key_current = self.GetRootItem()
+
+ # don't change the mark (self._current)
+ self.SelectItemRange(self._current, item)
+
+ else:
+
+ select = True # the default
+
+ # Check if we need to toggle hilight (ctrl mode)
+ if not unselect_others:
+ select = not item.IsSelected()
+
+ self._current = self._key_current = item
+ self._current.SetHilight(select)
+ self.RefreshLine(self._current)
+
+ # This can cause idle processing to select the root
+ # if no item is selected, so it must be after the
+ # selection is set
+ self.EnsureVisible(item)
+
+ event.SetEventType(wxEVT_TREE_SEL_CHANGED)
+ self.GetEventHandler().ProcessEvent(event)
+
+ if not from_key:
+ # Handles hypertext items
+ self.HandleHyperLink(item)
+
+
+ def SelectItem(self, item, select=True):
+ """
+ Selects/deselects an item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `select`: ``True`` to select an item, ``False`` to deselect it.
+ """
+
+ if select:
+
+ self.DoSelectItem(item, not self.HasAGWFlag(TR_MULTIPLE))
+
+ else: # deselect
+
+ item.SetHilight(False)
+ self.RefreshLine(item)
+
+
+ def FillArray(self, item, array=[]):
+ """
+ Internal function. Used to populate an array of selected items when
+ the style ``TR_MULTIPLE`` is used.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param list `array`: a Python list containing the selected items.
+
+ :return: A Python list containing the selected items.
+ """
+
+ if not array:
+ array = []
+
+ if item.IsSelected():
+ array.append(item)
+
+ if item.HasChildren() and item.IsExpanded():
+ for child in item.GetChildren():
+ array = self.FillArray(child, array)
+
+ return array
+
+
+ def GetSelections(self):
+ """
+ Returns a list of selected items.
+
+ :note: This method can be used only if :class:`CustomTreeCtrl` has the ``TR_MULTIPLE`` or ``TR_EXTENDED``
+ style set.
+
+ :return: A Python list containing the selected items, all instances of :class:`GenericTreeItem`.
+ """
+
+ array = []
+ idRoot = self.GetRootItem()
+ if idRoot:
+ array = self.FillArray(idRoot, array)
+
+ #else: the tree is empty, so no selections
+
+ return array
+
+
+ def HandleHyperLink(self, item):
+ """
+ Handles the hyperlink items, sending the ``EVT_TREE_ITEM_HYPERLINK`` event.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ if self.IsItemHyperText(item):
+ event = TreeEvent(wxEVT_TREE_ITEM_HYPERLINK, self.GetId())
+ event._item = item
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def EnsureVisible(self, item):
+ """
+ Scrolls and/or expands items to ensure that the given item is visible.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ # first expand all parent branches
+ parent = item.GetParent()
+
+ if self.HasAGWFlag(TR_HIDE_ROOT):
+ while parent and parent != self._anchor:
+ self.Expand(parent)
+ parent = parent.GetParent()
+ else:
+ while parent:
+ self.Expand(parent)
+ parent = parent.GetParent()
+
+ self.ScrollTo(item)
+
+
+ def ScrollTo(self, item):
+ """
+ Scrolls the specified item into view.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ if not item:
+ return
+
+ # We have to call this here because the label in
+ # question might just have been added and no screen
+ # update taken place.
+ if self._dirty:
+ if wx.Platform in ["__WXMSW__", "__WXMAC__"]:
+ self.Update()
+ else:
+ wx.YieldIfNeeded()
+
+ # now scroll to the item
+ item_y = item.GetY()
+ start_x, start_y = self.GetViewStart()
+ start_y *= _PIXELS_PER_UNIT
+
+ client_w, client_h = self.GetClientSize()
+
+ x, y = 0, 0
+
+ if item_y < start_y+3:
+
+ # going down
+ x, y = self._anchor.GetSize(x, y, self)
+ y += _PIXELS_PER_UNIT + 2 # one more scrollbar unit + 2 pixels
+ x += _PIXELS_PER_UNIT + 2 # one more scrollbar unit + 2 pixels
+ x_pos = self.GetScrollPos(wx.HORIZONTAL)
+ # Item should appear at top
+ self.SetScrollbars(_PIXELS_PER_UNIT, _PIXELS_PER_UNIT, x/_PIXELS_PER_UNIT, y/_PIXELS_PER_UNIT, x_pos, item_y/_PIXELS_PER_UNIT)
+
+ elif item_y+self.GetLineHeight(item) > start_y+client_h:
+
+ # going up
+ x, y = self._anchor.GetSize(x, y, self)
+ y += _PIXELS_PER_UNIT + 2 # one more scrollbar unit + 2 pixels
+ x += _PIXELS_PER_UNIT + 2 # one more scrollbar unit + 2 pixels
+ item_y += _PIXELS_PER_UNIT+2
+ x_pos = self.GetScrollPos(wx.HORIZONTAL)
+ # Item should appear at bottom
+ self.SetScrollbars(_PIXELS_PER_UNIT, _PIXELS_PER_UNIT, x/_PIXELS_PER_UNIT, y/_PIXELS_PER_UNIT, x_pos, (item_y+self.GetLineHeight(item)-client_h)/_PIXELS_PER_UNIT )
+
+
+ def OnCompareItems(self, item1, item2):
+ """
+ Returns whether 2 items have the same text.
+
+ Override this function in the derived class to change the sort order of the items
+ in the :class:`CustomTreeCtrl`. The function should return a negative, zero or positive
+ value if the first item is less than, equal to or greater than the second one.
+
+ :param `item1`: an instance of :class:`GenericTreeItem`;
+ :param `item2`: another instance of :class:`GenericTreeItem`.
+
+ :return: The return value is negative if `item1` < `item2`, zero if `item1` == `item2`
+ and strictly positive if `item1` < `item2`.
+
+ :note: The base class version compares items alphabetically.
+ """
+
+ return cmp(self.GetItemText(item1), self.GetItemText(item2))
+
+
+ def SortChildren(self, item):
+ """
+ Sorts the children of the given item using the :meth:`~CustomTreeCtrl.OnCompareItems` method of
+ :class:`CustomTreeCtrl`.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :note: You should override the :meth:`~CustomTreeCtrl.OnCompareItems` method in your derived class to change
+ the sort order (the default is ascending case-sensitive alphabetical order).
+ """
+
+ children = item.GetChildren()
+
+ if len(children) > 1:
+ self._dirty = True
+ children.sort(self.OnCompareItems)
+
+
+ def GetImageList(self):
+ """
+ Returns the normal image list associated with :class:`CustomTreeCtrl`.
+
+ :return: An instance of :class:`ImageList`.
+ """
+
+ return self._imageListNormal
+
+
+ def GetButtonsImageList(self):
+ """
+ Returns the buttons image list associated with :class:`CustomTreeCtrl` (from
+ which application-defined button images are taken).
+
+ :return: An instance of :class:`ImageList`.
+ """
+
+ return self._imageListButtons
+
+
+ def GetStateImageList(self):
+ """
+ Returns the state image list associated with :class:`CustomTreeCtrl` (from which
+ application-defined state images are taken).
+
+ :return: An instance of :class:`ImageList`.
+ """
+
+ return self._imageListState
+
+
+ def GetImageListCheck(self):
+ """
+ Returns the image list used to build the check/radio buttons in :class:`CustomTreeCtrl`.
+
+ :return: An instance of :class:`ImageList`.
+ """
+
+ return self._imageListCheck
+
+
+ def GetLeftImageList(self):
+ """
+ Returns the image list for :class:`CustomTreeCtrl` filled with images to be used on
+ the leftmost part of the client area. Any item can have a leftmost image associated
+ with it.
+
+ :return: An instance of :class:`ImageList`.
+ """
+
+ return self._imageListLeft
+
+
+ def CalculateLineHeight(self):
+ """ Calculates the height of a line. """
+
+ dc = wx.ClientDC(self)
+ self._lineHeight = dc.GetCharHeight()
+
+ if self._imageListNormal:
+
+ # Calculate a self._lineHeight value from the normal Image sizes.
+ # May be toggle off. Then CustomTreeCtrl will spread when
+ # necessary (which might look ugly).
+ n = self._imageListNormal.GetImageCount()
+
+ for i in xrange(n):
+
+ width, height = self._imageListNormal.GetSize(i)
+
+ if height > self._lineHeight:
+ self._lineHeight = height
+
+ if self._imageListButtons:
+
+ # Calculate a self._lineHeight value from the Button image sizes.
+ # May be toggle off. Then CustomTreeCtrl will spread when
+ # necessary (which might look ugly).
+ n = self._imageListButtons.GetImageCount()
+
+ for i in xrange(n):
+
+ width, height = self._imageListButtons.GetSize(i)
+
+ if height > self._lineHeight:
+ self._lineHeight = height
+
+ if self._imageListCheck:
+
+ # Calculate a self._lineHeight value from the check/radio image sizes.
+ # May be toggle off. Then CustomTreeCtrl will spread when
+ # necessary (which might look ugly).
+ n = self._imageListCheck.GetImageCount()
+
+ for i in xrange(n):
+
+ width, height = self._imageListCheck.GetSize(i)
+
+ if height > self._lineHeight:
+ self._lineHeight = height
+
+ if self._imageListLeft:
+
+ # Calculate a self._lineHeight value from the leftmost image sizes.
+ # May be toggle off. Then CustomTreeCtrl will spread when
+ # necessary (which might look ugly).
+ n = self._imageListLeft.GetImageCount()
+
+ for i in xrange(n):
+
+ width, height = self._imageListLeft.GetSize(i)
+
+ if height > self._lineHeight:
+ self._lineHeight = height
+
+ if self._lineHeight < 30:
+ self._lineHeight += 2 # at least 2 pixels
+ else:
+ self._lineHeight += self._lineHeight/10 # otherwise 10% extra spacing
+
+
+ def SetImageList(self, imageList):
+ """
+ Sets the normal image list for :class:`CustomTreeCtrl`.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ if self._ownsImageListNormal:
+ del self._imageListNormal
+
+ self._imageListNormal = imageList
+ self._ownsImageListNormal = False
+ self._dirty = True
+
+ # Don't do any drawing if we're setting the list to NULL,
+ # since we may be in the process of deleting the tree control.
+ if imageList:
+ self.CalculateLineHeight()
+
+ # We gray out the image list to use the grayed icons with disabled items
+ sz = imageList.GetSize(0)
+ self._grayedImageList = wx.ImageList(sz[0], sz[1], True, 0)
+
+ for ii in xrange(imageList.GetImageCount()):
+ bmp = imageList.GetBitmap(ii)
+ newbmp = MakeDisabledBitmap(bmp)
+ self._grayedImageList.Add(newbmp)
+
+
+ def SetLeftImageList(self, imageList):
+ """
+ Sets the image list for :class:`CustomTreeCtrl` filled with images to be used on
+ the leftmost part of the client area. Any item can have a leftmost image associated
+ with it.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ self._imageListLeft = imageList
+ self._ownsImageListLeft = False
+ self._dirty = True
+
+ # Don't do any drawing if we're setting the list to NULL,
+ # since we may be in the process of deleting the tree control.
+ if imageList:
+ self.CalculateLineHeight()
+
+ # We gray out the image list to use the grayed icons with disabled items
+ sz = imageList.GetSize(0)
+ self._grayedImageListLeft = wx.ImageList(sz[0], sz[1], True, 0)
+
+ for ii in xrange(imageList.GetImageCount()):
+ bmp = imageList.GetBitmap(ii)
+ newbmp = MakeDisabledBitmap(bmp)
+ self._grayedImageListLeft.Add(newbmp)
+
+
+ def SetStateImageList(self, imageList):
+ """
+ Sets the state image list for :class:`CustomTreeCtrl` (from which application-defined
+ state images are taken).
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ if self._ownsImageListState:
+ del self._imageListState
+
+ self._imageListState = imageList
+ self._ownsImageListState = False
+
+
+ def SetButtonsImageList(self, imageList):
+ """
+ Sets the buttons image list for :class:`CustomTreeCtrl` (from which application-defined
+ button images are taken).
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ if self._ownsImageListButtons:
+ del self._imageListButtons
+
+ self._imageListButtons = imageList
+ self._ownsImageListButtons = False
+ self._dirty = True
+ self.CalculateLineHeight()
+
+
+ def SetImageListCheck(self, sizex, sizey, imglist=None):
+ """
+ Sets the checkbox/radiobutton image list.
+
+ :param integer `sizex`: the width of the bitmaps in the `imglist`, in pixels;
+ :param integer `sizey`: the height of the bitmaps in the `imglist`, in pixels;
+ :param `imglist`: an instance of :class:`ImageList`.
+ """
+
+ # Image list to hold disabled versions of each control
+ self._grayedCheckList = wx.ImageList(sizex, sizey, True, 0)
+
+ if imglist is None:
+
+ self._imageListCheck = wx.ImageList(sizex, sizey)
+
+ # Get the Checkboxes
+ self._imageListCheck.Add(self.GetControlBmp(checkbox=True,
+ checked=True,
+ enabled=True,
+ x=sizex, y=sizey))
+ self._grayedCheckList.Add(self.GetControlBmp(checkbox=True,
+ checked=True,
+ enabled=False,
+ x=sizex, y=sizey))
+
+ self._imageListCheck.Add(self.GetControlBmp(checkbox=True,
+ checked=False,
+ enabled=True,
+ x=sizex, y=sizey))
+ self._grayedCheckList.Add(self.GetControlBmp(checkbox=True,
+ checked=False,
+ enabled=False,
+ x=sizex, y=sizey))
+
+ self._imageListCheck.Add(self.GetControlBmp(checkbox=True,
+ checked=2,
+ enabled=True,
+ x=sizex, y=sizey))
+ self._grayedCheckList.Add(self.GetControlBmp(checkbox=True,
+ checked=2,
+ enabled=False,
+ x=sizex, y=sizey))
+
+ # Get the Radio Buttons
+ self._imageListCheck.Add(self.GetControlBmp(checkbox=False,
+ checked=True,
+ enabled=True,
+ x=sizex, y=sizey))
+ self._grayedCheckList.Add(self.GetControlBmp(checkbox=False,
+ checked=True,
+ enabled=False,
+ x=sizex, y=sizey))
+
+ self._imageListCheck.Add(self.GetControlBmp(checkbox=False,
+ checked=False,
+ enabled=True,
+ x=sizex, y=sizey))
+ self._grayedCheckList.Add(self.GetControlBmp(checkbox=False,
+ checked=False,
+ enabled=False,
+ x=sizex, y=sizey))
+
+ else:
+
+ sizex, sizey = imglist.GetSize(0)
+ self._imageListCheck = imglist
+
+ for ii in xrange(self._imageListCheck.GetImageCount()):
+
+ bmp = self._imageListCheck.GetBitmap(ii)
+ newbmp = MakeDisabledBitmap(bmp)
+ self._grayedCheckList.Add(newbmp)
+
+ self._dirty = True
+
+ if imglist:
+ self.CalculateLineHeight()
+
+
+ def AssignImageList(self, imageList):
+ """
+ Assigns the normal image list.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ self.SetImageList(imageList)
+ self._ownsImageListNormal = True
+
+
+ def AssignStateImageList(self, imageList):
+ """
+ Assigns the state image list.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ self.SetStateImageList(imageList)
+ self._ownsImageListState = True
+
+
+ def AssignButtonsImageList(self, imageList):
+ """
+ Assigns the button image list.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ self.SetButtonsImageList(imageList)
+ self._ownsImageListButtons = True
+
+
+ def AssignLeftImageList(self, imageList):
+ """
+ Assigns the image list for :class:`CustomTreeCtrl` filled with images to be used on
+ the leftmost part of the client area. Any item can have a leftmost image associated
+ with it.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ self.SetLeftImageList(imageList)
+ self._ownsImageListLeft = True
+
+
+# -----------------------------------------------------------------------------
+# helpers
+# -----------------------------------------------------------------------------
+
+ def AdjustMyScrollbars(self):
+ """ Internal method used to adjust the :class:`PyScrolledWindow` scrollbars. """
+
+ if self._anchor:
+
+ x, y = self._anchor.GetSize(0, 0, self)
+ y += _PIXELS_PER_UNIT + 2 # one more scrollbar unit + 2 pixels
+ x += _PIXELS_PER_UNIT + 2 # one more scrollbar unit + 2 pixels
+ x_pos = self.GetScrollPos(wx.HORIZONTAL)
+ y_pos = self.GetScrollPos(wx.VERTICAL)
+ self.SetScrollbars(_PIXELS_PER_UNIT, _PIXELS_PER_UNIT, x/_PIXELS_PER_UNIT, y/_PIXELS_PER_UNIT, x_pos, y_pos)
+
+ else:
+
+ self.SetScrollbars(0, 0, 0, 0)
+
+
+ def GetLineHeight(self, item):
+ """
+ Returns the line height for the given item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ :return: the item height, in pixels.
+ """
+
+ if self.GetAGWWindowStyleFlag() & TR_HAS_VARIABLE_ROW_HEIGHT:
+ return int(item.GetHeight())
+ else:
+ return int(self._lineHeight)
+
+
+ def DrawVerticalGradient(self, dc, rect, hasfocus):
+ """
+ Gradient fill from colour 1 to colour 2 from top to bottom.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the rectangle to be filled with the gradient shading;
+ :param bool `hasfocus`: ``True`` if the main :class:`CustomTreeCtrl` has focus, ``False``
+ otherwise.
+ """
+
+ oldpen = dc.GetPen()
+ oldbrush = dc.GetBrush()
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ # calculate gradient coefficients
+ if hasfocus:
+ col2 = self._secondcolour
+ col1 = self._firstcolour
+ else:
+ col2 = self._hilightUnfocusedBrush.GetColour()
+ col1 = self._hilightUnfocusedBrush2.GetColour()
+
+ r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+ r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+ flrect = float(rect.height)
+
+ rstep = float((r2 - r1)) / flrect
+ gstep = float((g2 - g1)) / flrect
+ bstep = float((b2 - b1)) / flrect
+
+ rf, gf, bf = 0, 0, 0
+
+ for y in xrange(rect.y, rect.y + rect.height):
+ currCol = (r1 + rf, g1 + gf, b1 + bf)
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.DrawRectangle(rect.x, y, rect.width, 1)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+ dc.SetPen(oldpen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangleRect(rect)
+ dc.SetBrush(oldbrush)
+
+
+ def DrawHorizontalGradient(self, dc, rect, hasfocus):
+ """
+ Gradient fill from colour 1 to colour 2 from left to right.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the rectangle to be filled with the gradient shading;
+ :param bool `hasfocus`: ``True`` if the main :class:`CustomTreeCtrl` has focus, ``False``
+ otherwise.
+ """
+
+ oldpen = dc.GetPen()
+ oldbrush = dc.GetBrush()
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ # calculate gradient coefficients
+
+ if hasfocus:
+ col2 = self._secondcolour
+ col1 = self._firstcolour
+ else:
+ col2 = self._hilightUnfocusedBrush.GetColour()
+ col1 = self._hilightUnfocusedBrush2.GetColour()
+
+ r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+ r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+ flrect = float(rect.width)
+
+ rstep = float((r2 - r1)) / flrect
+ gstep = float((g2 - g1)) / flrect
+ bstep = float((b2 - b1)) / flrect
+
+ rf, gf, bf = 0, 0, 0
+
+ for x in xrange(rect.x, rect.x + rect.width):
+ currCol = (int(r1 + rf), int(g1 + gf), int(b1 + bf))
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.DrawRectangle(x, rect.y, 1, rect.height)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+ dc.SetPen(oldpen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangleRect(rect)
+ dc.SetBrush(oldbrush)
+
+
+ def DrawVistaRectangle(self, dc, rect, hasfocus):
+ """
+ Draws the selected item(s) with the Windows Vista style.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param Rect `rect`: the rectangle to be filled with the gradient shading;
+ :param bool `hasfocus`: ``True`` if the main :class:`CustomTreeCtrl` has focus, ``False``
+ otherwise.
+ """
+
+ if hasfocus:
+
+ outer = _rgbSelectOuter
+ inner = _rgbSelectInner
+ top = _rgbSelectTop
+ bottom = _rgbSelectBottom
+
+ else:
+
+ outer = _rgbNoFocusOuter
+ inner = _rgbNoFocusInner
+ top = _rgbNoFocusTop
+ bottom = _rgbNoFocusBottom
+
+ oldpen = dc.GetPen()
+ oldbrush = dc.GetBrush()
+
+ bdrRect = wx.Rect(*rect.Get())
+ filRect = wx.Rect(*rect.Get())
+ filRect.Deflate(1,1)
+
+ r1, g1, b1 = int(top.Red()), int(top.Green()), int(top.Blue())
+ r2, g2, b2 = int(bottom.Red()), int(bottom.Green()), int(bottom.Blue())
+
+ flrect = float(filRect.height)
+ if flrect < 1:
+ flrect = self._lineHeight
+
+ rstep = float((r2 - r1)) / flrect
+ gstep = float((g2 - g1)) / flrect
+ bstep = float((b2 - b1)) / flrect
+
+ rf, gf, bf = 0, 0, 0
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ for y in xrange(filRect.y, filRect.y + filRect.height):
+ currCol = (r1 + rf, g1 + gf, b1 + bf)
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.DrawRectangle(filRect.x, y, filRect.width, 1)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(outer))
+ dc.DrawRoundedRectangleRect(bdrRect, 3)
+ bdrRect.Deflate(1, 1)
+ dc.SetPen(wx.Pen(inner))
+ dc.DrawRoundedRectangleRect(bdrRect, 2)
+
+ dc.SetPen(oldpen)
+ dc.SetBrush(oldbrush)
+
+
+ def PaintItem(self, item, dc, level, align):
+ """
+ Actually draws an item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param `dc`: an instance of :class:`DC`;
+ :param integer `level`: the item level in the tree hierarchy;
+ :param integer `align`: an integer specifying the alignment type:
+
+ =============== =========================================
+ `align` Value Description
+ =============== =========================================
+ 0 No horizontal alignment of windows (in items with windows).
+ 1 Windows (in items with windows) are aligned at the same horizontal position.
+ 2 Windows (in items with windows) are aligned at the rightmost edge of :class:`CustomTreeCtrl`.
+ =============== =========================================
+ """
+
+ attr = item.GetAttributes()
+
+ if attr and attr.HasFont():
+ dc.SetFont(attr.GetFont())
+ else:
+ if item.IsBold():
+ dc.SetFont(self._boldFont)
+ elif item.IsItalic():
+ dc.SetFont(self._italicFont)
+ if item.IsHyperText():
+ dc.SetFont(self.GetHyperTextFont())
+ if item.GetVisited():
+ dc.SetTextForeground(self.GetHyperTextVisitedColour())
+ else:
+ dc.SetTextForeground(self.GetHyperTextNewColour())
+
+ text_w, text_h, dummy = dc.GetMultiLineTextExtent(item.GetText())
+ w, h = self.GetClientSize()
+
+ image = item.GetCurrentImage()
+ checkimage = item.GetCurrentCheckedImage()
+ leftimage = _NO_IMAGE
+ separator = item.IsSeparator()
+
+ if self._imageListLeft:
+ leftimage = item.GetLeftImage()
+
+ image_w, image_h = 0, 0
+
+ if image != _NO_IMAGE:
+
+ if self._imageListNormal:
+
+ image_w, image_h = self._imageListNormal.GetSize(image)
+ image_w += 4
+
+ else:
+
+ image = _NO_IMAGE
+
+ if item.GetType() != 0:
+ wcheck, hcheck = self._imageListCheck.GetSize(item.GetType())
+ wcheck += 4
+ else:
+ wcheck, hcheck = 0, 0
+
+ if leftimage != _NO_IMAGE:
+ l_image_w, l_image_h = self._imageListLeft.GetSize(leftimage)
+
+ total_h = self.GetLineHeight(item)
+ drawItemBackground = False
+
+ if item.IsSelected():
+
+ # under mac selections are only a rectangle in case they don't have the focus
+ if wx.Platform == "__WXMAC__":
+ if not self._hasFocus:
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT), 1, wx.SOLID))
+ else:
+ dc.SetBrush(self._hilightBrush)
+ else:
+ dc.SetBrush((self._hasFocus and [self._hilightBrush] or [self._hilightUnfocusedBrush])[0])
+ drawItemBackground = True
+ else:
+ if attr and attr.HasBackgroundColour():
+ drawItemBackground = True
+ colBg = attr.GetBackgroundColour()
+ else:
+ colBg = self._backgroundColour
+
+ dc.SetBrush(wx.Brush(colBg, wx.SOLID))
+ if attr and attr.HasBorderColour():
+ colBorder = attr.GetBorderColour()
+ dc.SetPen(wx.Pen(colBorder, 1, wx.SOLID))
+ else:
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ offset = (self.HasAGWFlag(TR_ROW_LINES) and [1] or [0])[0]
+
+ if self.HasAGWFlag(TR_FULL_ROW_HIGHLIGHT):
+ x = 0
+
+ itemrect = wx.Rect(x, item.GetY()+offset, w, total_h-offset)
+
+ if item.IsSelected():
+ if self._usegradients:
+ if self._gradientstyle == 0: # Horizontal
+ self.DrawHorizontalGradient(dc, itemrect, self._hasFocus)
+ else: # Vertical
+ self.DrawVerticalGradient(dc, itemrect, self._hasFocus)
+ elif self._vistaselection:
+ self.DrawVistaRectangle(dc, itemrect, self._hasFocus)
+ else:
+ if wx.Platform in ["__WXGTK2__", "__WXMAC__"]:
+ flags = wx.CONTROL_SELECTED
+ if self._hasFocus: flags = flags | wx.CONTROL_FOCUSED
+ wx.RendererNative.Get().DrawItemSelectionRect(self, dc, itemrect, flags)
+ else:
+ dc.DrawRectangleRect(itemrect)
+ else:
+ if drawItemBackground:
+ minusicon = wcheck + image_w - 2
+ itemrect = wx.Rect(item.GetX()+minusicon,
+ item.GetY()+offset,
+ item.GetWidth()-minusicon,
+ total_h-offset)
+ dc.DrawRectangleRect(itemrect)
+
+ else:
+
+ if item.IsSelected():
+
+ # If it's selected, and there's an image, then we should
+ # take care to leave the area under the image painted in the
+ # background colour.
+
+ wnd = item.GetWindow()
+ wndx = 0
+ if wnd:
+ wndx, wndy = item.GetWindowSize()
+
+ if separator:
+ item_width = w
+ else:
+ item_width = item.GetWidth() - image_w - wcheck + 2 - wndx
+
+ itemrect = wx.Rect(item.GetX() + wcheck + image_w - 2,
+ item.GetY()+offset,
+ item_width,
+ total_h-offset)
+
+ if self._usegradients:
+ if self._gradientstyle == 0: # Horizontal
+ self.DrawHorizontalGradient(dc, itemrect, self._hasFocus)
+ else: # Vertical
+ self.DrawVerticalGradient(dc, itemrect, self._hasFocus)
+ elif self._vistaselection:
+ self.DrawVistaRectangle(dc, itemrect, self._hasFocus)
+ else:
+ if wx.Platform in ["__WXGTK2__", "__WXMAC__"]:
+ flags = wx.CONTROL_SELECTED
+ if self._hasFocus: flags = flags | wx.CONTROL_FOCUSED
+ wx.RendererNative.Get().DrawItemSelectionRect(self, dc, itemrect, flags)
+ else:
+ dc.DrawRectangleRect(itemrect)
+
+ # On GTK+ 2, drawing a 'normal' background is wrong for themes that
+ # don't allow backgrounds to be customized. Not drawing the background,
+ # except for custom item backgrounds, works for both kinds of theme.
+ elif drawItemBackground:
+
+ minusicon = wcheck + image_w - 2
+
+ if separator:
+ item_width = w
+ else:
+ item_width = item.GetWidth()-minusicon
+
+ itemrect = wx.Rect(item.GetX()+minusicon,
+ item.GetY()+offset,
+ item_width,
+ total_h-offset)
+
+ if self._usegradients and self._hasFocus:
+ if self._gradientstyle == 0: # Horizontal
+ self.DrawHorizontalGradient(dc, itemrect, self._hasFocus)
+ else: # Vertical
+ self.DrawVerticalGradient(dc, itemrect, self._hasFocus)
+ else:
+ dc.DrawRectangleRect(itemrect)
+
+ if image != _NO_IMAGE:
+
+ dc.SetClippingRegion(item.GetX(), item.GetY(), wcheck+image_w-2, total_h)
+ if item.IsEnabled():
+ imglist = self._imageListNormal
+ else:
+ imglist = self._grayedImageList
+
+ imglist.Draw(image, dc,
+ item.GetX() + wcheck,
+ item.GetY() + ((total_h > image_h) and [(total_h-image_h)/2] or [0])[0],
+ wx.IMAGELIST_DRAW_TRANSPARENT)
+
+ dc.DestroyClippingRegion()
+
+ if wcheck:
+ if item.IsEnabled():
+ imglist = self._imageListCheck
+ else:
+ imglist = self._grayedCheckList
+
+ imglist.Draw(checkimage, dc,
+ item.GetX(),
+ item.GetY() + ((total_h > hcheck) and [(total_h-hcheck)/2] or [0])[0],
+ wx.IMAGELIST_DRAW_TRANSPARENT)
+
+ if leftimage != _NO_IMAGE:
+ if item.IsEnabled():
+ imglist = self._imageListLeft
+ else:
+ imglist = self._grayedImageListLeft
+
+ imglist.Draw(leftimage, dc,
+ 4,
+ item.GetY() + ((total_h > l_image_h) and [(total_h-l_image_h)/2] or [0])[0],
+ wx.IMAGELIST_DRAW_TRANSPARENT)
+
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ extraH = ((total_h > text_h) and [(total_h - text_h)/2] or [0])[0]
+
+ textrect = wx.Rect(wcheck + image_w + item.GetX(), item.GetY() + extraH, text_w, text_h)
+
+ itemText = item.GetText()
+ if self.HasAGWFlag(TR_ELLIPSIZE_LONG_ITEMS) and not separator:
+ xa, ya = self.CalcScrolledPosition((0, item.GetY()))
+ maxsize = w - (wcheck + image_w + item.GetX()) + xa
+ itemText = ChopText(dc, itemText, maxsize)
+
+ if not item.IsEnabled():
+ foreground = dc.GetTextForeground()
+ dc.SetTextForeground(self._disabledColour)
+ dc.DrawLabel(itemText, textrect)
+ dc.SetTextForeground(foreground)
+ else:
+ if wx.Platform == "__WXMAC__" and item.IsSelected() and self._hasFocus:
+ dc.SetTextForeground(wx.WHITE)
+ dc.DrawLabel(itemText, textrect)
+
+ wnd = item.GetWindow()
+ if wnd:
+ wndx = wcheck + image_w + item.GetX() + text_w + 4
+ xa, ya = self.CalcScrolledPosition((0, item.GetY()))
+ wndx += xa
+ if item.GetHeight() > item.GetWindowSize()[1]:
+ ya += (item.GetHeight() - item.GetWindowSize()[1])/2
+
+ if align == 1:
+ # Horizontal alignment of windows
+ if level in self.absoluteWindows:
+ wndx = self.absoluteWindows[level] + item.GetX() + 2 + xa
+
+ elif align == 2:
+ # Rightmost alignment of windows
+ wndx = w - item.GetWindowSize().x - 2 + xa
+
+ if not wnd.IsShown():
+ wnd.Show()
+ if wnd.GetPosition() != (wndx, ya):
+ wnd.SetPosition((wndx, ya))
+
+ if separator:
+ oldPen = dc.GetPen()
+
+ if item.IsEnabled():
+ if attr and attr.HasTextColour():
+ separatorPen = wx.Pen(attr.GetTextColour(), 1)
+ else:
+ separatorPen = self._separatorPen
+ else:
+ separatorPen = wx.GREY_PEN
+
+ dc.SetPen(separatorPen)
+ dc.DrawLine(item.GetX()+2, item.GetY()+total_h/2, w, item.GetY()+total_h/2)
+ dc.SetPen(oldPen)
+
+ # restore normal font
+ dc.SetFont(self._normalFont)
+
+
+ # Now y stands for the top of the item, whereas it used to stand for middle !
+ def PaintLevel(self, item, dc, level, y, align):
+ """
+ Paint a level in the hierarchy of :class:`CustomTreeCtrl`.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param `dc`: an instance of :class:`DC`;
+ :param integer `level`: the item level in the tree hierarchy;
+ :param integer `y`: the current vertical position in the :class:`PyScrolledWindow`;
+ :param integer `align`: an integer specifying the alignment type:
+
+ =============== =========================================
+ `align` Value Description
+ =============== =========================================
+ 0 No horizontal alignment of windows (in items with windows).
+ 1 Windows (in items with windows) are aligned at the same horizontal position.
+ 2 Windows (in items with windows) are aligned at the rightmost edge of :class:`CustomTreeCtrl`.
+ =============== =========================================
+
+ """
+
+ x = level*self._indent
+
+ left_image_list = 0
+ if self._imageListLeft:
+ left_image_list += self._imageListLeft.GetBitmap(0).GetWidth()
+
+ x += left_image_list
+
+ if not self.HasAGWFlag(TR_HIDE_ROOT):
+
+ x += self._indent
+
+ elif level == 0:
+
+ # always expand hidden root
+ origY = y
+ children = item.GetChildren()
+ count = len(children)
+
+ if count > 0:
+ n = 0
+ while n < count:
+ oldY = y
+ y = self.PaintLevel(children[n], dc, 1, y, align)
+ n = n + 1
+
+ if not self.HasAGWFlag(TR_NO_LINES) and self.HasAGWFlag(TR_LINES_AT_ROOT) and count > 0:
+
+ # draw line down to last child
+ origY += self.GetLineHeight(children[0])>>1
+ oldY += self.GetLineHeight(children[n-1])>>1
+ oldPen = dc.GetPen()
+ dc.SetPen(self._dottedPen)
+ dc.DrawLine(3, origY, 3, oldY)
+ dc.SetPen(oldPen)
+
+ return y
+
+ item.SetX(x+self._spacing)
+ item.SetY(y)
+
+ h = self.GetLineHeight(item)
+ y_top = y
+ y_mid = y_top + (h>>1)
+ y += h
+
+ exposed_x = dc.LogicalToDeviceX(0)
+ exposed_y = dc.LogicalToDeviceY(y_top)
+
+ if self.IsExposed(exposed_x, exposed_y, 10000, h): # 10000 = very much
+ if wx.Platform == "__WXMAC__":
+ # don't draw rect outline if we already have the
+ # background colour under Mac
+ pen = ((item.IsSelected() and self._hasFocus) and [self._borderPen] or [wx.TRANSPARENT_PEN])[0]
+ else:
+ pen = self._borderPen
+
+ if item.IsSelected():
+ if (wx.Platform == "__WXMAC__" and self._hasFocus):
+ colText = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
+ else:
+ colText = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
+
+ if self._vistaselection:
+ colText = wx.BLACK
+ attr = item.GetAttributes()
+
+ if attr and attr.HasTextColour():
+ colText = attr.GetTextColour()
+
+ else:
+ attr = item.GetAttributes()
+ if attr and attr.HasTextColour():
+ colText = attr.GetTextColour()
+ else:
+ colText = self.GetForegroundColour()
+
+ # prepare to draw
+ dc.SetTextForeground(colText)
+ dc.SetPen(pen)
+ oldpen = pen
+
+ # draw
+ self.PaintItem(item, dc, level, align)
+
+ if self.HasAGWFlag(TR_ROW_LINES):
+
+ # if the background colour is white, choose a
+ # contrasting colour for the lines
+ medium_grey = wx.Pen(wx.Colour(200, 200, 200))
+ dc.SetPen(((self.GetBackgroundColour() == wx.WHITE) and [medium_grey] or [wx.WHITE_PEN])[0])
+ dc.DrawLine(0, y_top, 10000, y_top)
+ dc.DrawLine(0, y, 10000, y)
+
+ # restore DC objects
+ dc.SetBrush(wx.WHITE_BRUSH)
+ dc.SetTextForeground(wx.BLACK)
+
+ if not self.HasAGWFlag(TR_NO_LINES):
+
+ # draw the horizontal line here
+ dc.SetPen(self._dottedPen)
+ x_start = x
+ if x > self._indent+left_image_list:
+ x_start -= self._indent
+ elif self.HasAGWFlag(TR_LINES_AT_ROOT):
+ x_start = 3
+ dc.DrawLine(x_start, y_mid, x + self._spacing, y_mid)
+ dc.SetPen(oldpen)
+
+ # should the item show a button?
+ if item.HasPlus() and self.HasButtons():
+
+ if self._imageListButtons:
+
+ # draw the image button here
+ image_h = 0
+ image_w = 0
+ image = (item.IsExpanded() and [TreeItemIcon_Expanded] or [TreeItemIcon_Normal])[0]
+ if item.IsSelected():
+ image += TreeItemIcon_Selected - TreeItemIcon_Normal
+
+ image_w, image_h = self._imageListButtons.GetSize(image)
+ xx = x - image_w/2
+ yy = y_mid - image_h/2
+
+ dc.SetClippingRegion(xx, yy, image_w, image_h)
+ self._imageListButtons.Draw(image, dc, xx, yy,
+ wx.IMAGELIST_DRAW_TRANSPARENT)
+ dc.DestroyClippingRegion()
+
+ else: # no custom buttons
+
+ if self.HasAGWFlag(TR_TWIST_BUTTONS):
+ # We draw something like the Mac twist buttons
+
+ dc.SetPen(wx.BLACK_PEN)
+ dc.SetBrush(self._hilightBrush)
+ button = [wx.Point(), wx.Point(), wx.Point()]
+
+ if item.IsExpanded():
+ button[0].x = x - 5
+ button[0].y = y_mid - 3
+ button[1].x = x + 5
+ button[1].y = button[0].y
+ button[2].x = x
+ button[2].y = button[0].y + 6
+ else:
+ button[0].x = x - 3
+ button[0].y = y_mid - 5
+ button[1].x = button[0].x
+ button[1].y = y_mid + 5
+ button[2].x = button[0].x + 5
+ button[2].y = y_mid
+
+ dc.DrawPolygon(button)
+
+ else:
+ # These are the standard wx.TreeCtrl buttons as wx.RendererNative knows
+
+ wImage = 11
+ hImage = 11
+
+ flag = 0
+
+ if item.IsExpanded():
+ flag |= _CONTROL_EXPANDED
+ if item == self._underMouse:
+ flag |= _CONTROL_CURRENT
+
+ self._drawingfunction(self, dc, wx.Rect(x - wImage/2, y_mid - hImage/2, wImage, hImage), flag)
+
+ if item.IsExpanded():
+
+ children = item.GetChildren()
+ count = len(children)
+
+ if count > 0:
+
+ n = 0
+ level = level + 1
+
+ while n < count:
+ oldY = y
+ y = self.PaintLevel(children[n], dc, level, y, align)
+ n = n + 1
+
+ if not self.HasAGWFlag(TR_NO_LINES) and count > 0:
+
+ # draw line down to last child
+ oldY += self.GetLineHeight(children[n-1])>>1
+ if self.HasButtons():
+ y_mid += 5
+
+ # Only draw the portion of the line that is visible, in case it is huge
+ xOrigin, yOrigin = dc.GetDeviceOrigin()
+ yOrigin = abs(yOrigin)
+ width, height = self.GetClientSize()
+
+ # Move end points to the begining/end of the view?
+ if y_mid < yOrigin:
+ y_mid = yOrigin
+ if oldY > yOrigin + height:
+ oldY = yOrigin + height
+
+ # after the adjustments if y_mid is larger than oldY then the line
+ # isn't visible at all so don't draw anything
+ if y_mid < oldY:
+ dc.SetPen(self._dottedPen)
+ dc.DrawLine(x, y_mid, x, oldY)
+
+ return y
+
+
+# -----------------------------------------------------------------------------
+# wxWidgets callbacks
+# -----------------------------------------------------------------------------
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`CustomTreeCtrl`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.PaintDC(self)
+ self.PrepareDC(dc)
+
+ if not self._anchor:
+ return
+
+ dc.SetFont(self._normalFont)
+ dc.SetPen(self._dottedPen)
+
+ align = 0
+
+ if self.HasAGWFlag(TR_ALIGN_WINDOWS):
+ align = 1
+ elif self.HasAGWFlag(TR_ALIGN_WINDOWS_RIGHT):
+ align = 2
+
+ y = 2
+ self.PaintLevel(self._anchor, dc, 0, y, align)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`CustomTreeCtrl`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ if self.HasAGWFlag(TR_ELLIPSIZE_LONG_ITEMS):
+ self.Refresh()
+ event.Skip()
+ return
+
+ if self.HasAGWFlag(TR_ALIGN_WINDOWS_RIGHT) and self._itemWithWindow:
+ self.RefreshItemWithWindows()
+ else:
+ self.RefreshSelected()
+
+ event.Skip()
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`CustomTreeCtrl`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+ """
+
+ # Can we actually do something here (or in OnPaint()) To Handle
+ # background images that are stretchable or always centered?
+ # I tried but I get enormous flickering...
+
+ if not self._backgroundImage:
+ event.Skip()
+ return
+
+ if self._imageStretchStyle == _StyleTile:
+ dc = event.GetDC()
+
+ if not dc:
+ dc = wx.ClientDC(self)
+ rect = self.GetUpdateRegion().GetBox()
+ dc.SetClippingRect(rect)
+
+ self.TileBackground(dc)
+
+
+ def TileBackground(self, dc):
+ """
+ Tiles the background image to fill all the available area.
+
+ :param `dc`: an instance of :class:`DC`.
+
+ .. todo:: Support background images also in stretch and centered modes.
+ """
+
+ sz = self.GetClientSize()
+ w = self._backgroundImage.GetWidth()
+ h = self._backgroundImage.GetHeight()
+
+ x = 0
+
+ while x < sz.width:
+ y = 0
+
+ while y < sz.height:
+ dc.DrawBitmap(self._backgroundImage, x, y, True)
+ y = y + h
+
+ x = x + w
+
+
+ def OnSetFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`CustomTreeCtrl`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self._hasFocus = True
+ self.RefreshSelected()
+ event.Skip()
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`CustomTreeCtrl`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self._hasFocus = False
+ self.RefreshSelected()
+ event.Skip()
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`CustomTreeCtrl`, sending a
+ ``EVT_TREE_KEY_DOWN`` event.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ te = TreeEvent(wxEVT_TREE_KEY_DOWN, self.GetId())
+ te._evtKey = event
+ te.SetEventObject(self)
+
+ if self.GetEventHandler().ProcessEvent(te):
+ # intercepted by the user code
+ return
+
+ if self._current is None or self._key_current is None:
+
+ self._current = self._key_current = self.GetFirstVisibleItem()
+
+ # how should the selection work for this event?
+ is_multiple, extended_select, unselect_others = EventFlagsToSelType(self.GetAGWWindowStyleFlag(),
+ event.ShiftDown(), event.CmdDown())
+
+ # + : Expand
+ # - : Collaspe
+ # * : Expand all/Collapse all
+ # ' ' | return : activate
+ # up : go up (not last children!)
+ # down : go down
+ # left : go to parent
+ # right : open if parent and go next
+ # home : go to root
+ # end : go to last item without opening parents
+ # alnum : start or continue searching for the item with this prefix
+
+ keyCode = event.GetKeyCode()
+
+ if keyCode in [ord("+"), wx.WXK_ADD]: # "+"
+ if self._current.HasPlus() and not self.IsExpanded(self._current) and self.IsItemEnabled(self._current):
+ self.Expand(self._current)
+
+ elif keyCode in [ord("*"), wx.WXK_MULTIPLY]: # "*"
+ if not self.IsExpanded(self._current) and self.IsItemEnabled(self._current):
+ # expand all
+ self.ExpandAll(self._current)
+
+ elif keyCode in [ord("-"), wx.WXK_SUBTRACT]: # "-"
+ if self.IsExpanded(self._current):
+ self.Collapse(self._current)
+
+ elif keyCode == wx.WXK_MENU:
+ # Use the item's bounding rectangle to determine position for the event
+ itemRect = self.GetBoundingRect(self._current, True)
+ event = TreeEvent(wxEVT_TREE_ITEM_MENU, self.GetId())
+ event._item = self._current
+ # Use the left edge, vertical middle
+ event._pointDrag = wx.Point(itemRect.GetX(), itemRect.GetY() + itemRect.GetHeight()/2)
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ elif keyCode in [wx.WXK_RETURN, wx.WXK_SPACE, wx.WXK_NUMPAD_ENTER]:
+
+ if not self.IsItemEnabled(self._current):
+ event.Skip()
+ return
+
+ if not event.HasModifiers():
+ event = TreeEvent(wxEVT_TREE_ITEM_ACTIVATED, self.GetId())
+ event._item = self._current
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ if keyCode == wx.WXK_SPACE and self.GetItemType(self._current) > 0:
+ if self.IsItem3State(self._current):
+ checked = self.GetItem3StateValue(self._current)
+ checked = (checked+1)%3
+ else:
+ checked = not self.IsItemChecked(self._current)
+
+ self.CheckItem(self._current, checked)
+
+ if self.IsItemHyperText(self._current):
+ self.HandleHyperLink(self._current)
+
+ # in any case, also generate the normal key event for this key,
+ # even if we generated the ACTIVATED event above: this is what
+ # wxMSW does and it makes sense because you might not want to
+ # process ACTIVATED event at all and handle Space and Return
+ # directly (and differently) which would be impossible otherwise
+ event.Skip()
+
+ # up goes to the previous sibling or to the last
+ # of its children if it's expanded
+ elif keyCode == wx.WXK_UP:
+ prev = self.GetPrevSibling(self._key_current)
+ if not prev:
+ prev = self.GetItemParent(self._key_current)
+ if prev == self.GetRootItem() and self.HasAGWFlag(TR_HIDE_ROOT):
+ return
+
+ if prev:
+ current = self._key_current
+ # TODO: Huh? If we get here, we'd better be the first child of our parent. How else could it be?
+ if current == self.GetFirstChild(prev)[0] and self.IsItemEnabled(prev):
+ # otherwise we return to where we came from
+ self.DoSelectItem(prev, unselect_others, extended_select, from_key=True)
+ self._key_current = prev
+
+ else:
+ current = self._key_current
+
+ # We are going to another parent node
+ while self.IsExpanded(prev) and self.HasChildren(prev):
+ child = self.GetLastChild(prev)
+ if child:
+ prev = child
+ current = prev
+
+ # Try to get the previous siblings and see if they are active
+ while prev and not self.IsItemEnabled(prev):
+ prev = self.GetPrevSibling(prev)
+
+ if not prev:
+ # No previous siblings active: go to the parent and up
+ prev = self.GetItemParent(current)
+ while prev and not self.IsItemEnabled(prev):
+ prev = self.GetItemParent(prev)
+
+ if prev:
+ self.DoSelectItem(prev, unselect_others, extended_select, from_key=True)
+ self._key_current = prev
+
+ # left arrow goes to the parent
+ elif keyCode == wx.WXK_LEFT:
+
+ prev = self.GetItemParent(self._current)
+ if prev == self.GetRootItem() and self.HasAGWFlag(TR_HIDE_ROOT):
+ # don't go to root if it is hidden
+ prev = self.GetPrevSibling(self._current)
+
+ if self.IsExpanded(self._current):
+ self.Collapse(self._current)
+ else:
+ if prev and self.IsItemEnabled(prev):
+ self.DoSelectItem(prev, unselect_others, extended_select, from_key=True)
+
+ elif keyCode == wx.WXK_RIGHT:
+ # this works the same as the down arrow except that we
+ # also expand the item if it wasn't expanded yet
+ if self.IsExpanded(self._current) and self.HasChildren(self._current):
+ child, cookie = self.GetFirstChild(self._key_current)
+ if self.IsItemEnabled(child):
+ self.DoSelectItem(child, unselect_others, extended_select, from_key=True)
+ self._key_current = child
+ else:
+ self.Expand(self._current)
+ # fall through
+
+ elif keyCode == wx.WXK_DOWN:
+ if self.IsExpanded(self._key_current) and self.HasChildren(self._key_current):
+
+ child = self.GetNextActiveItem(self._key_current)
+
+ if child:
+ self.DoSelectItem(child, unselect_others, extended_select, from_key=True)
+ self._key_current = child
+
+ else:
+
+ next = self.GetNextSibling(self._key_current)
+
+ if not next:
+ current = self._key_current
+ while current and not next:
+ current = self.GetItemParent(current)
+ if current:
+ next = self.GetNextSibling(current)
+ if not next or not self.IsItemEnabled(next):
+ next = None
+
+ else:
+ while next and not self.IsItemEnabled(next):
+ next = self.GetNext(next)
+
+ if next:
+ self.DoSelectItem(next, unselect_others, extended_select, from_key=True)
+ self._key_current = next
+
+
+ # <End> selects the last visible tree item
+ elif keyCode == wx.WXK_END:
+
+ last = self.GetRootItem()
+
+ while last and self.IsExpanded(last):
+
+ lastChild = self.GetLastChild(last)
+
+ # it may happen if the item was expanded but then all of
+ # its children have been deleted - so IsExpanded() returned
+ # true, but GetLastChild() returned invalid item
+ if not lastChild:
+ break
+
+ last = lastChild
+
+ if last and self.IsItemEnabled(last):
+
+ self.DoSelectItem(last, unselect_others, extended_select, from_key=True)
+
+ # <Home> selects the root item
+ elif keyCode == wx.WXK_HOME:
+
+ prev = self.GetRootItem()
+
+ if not prev:
+ return
+
+ if self.HasAGWFlag(TR_HIDE_ROOT):
+ prev, cookie = self.GetFirstChild(prev)
+ if not prev:
+ return
+
+ if self.IsItemEnabled(prev):
+ self.DoSelectItem(prev, unselect_others, extended_select, from_key=True)
+
+ else:
+
+ if not event.HasModifiers() and ((keyCode >= ord('0') and keyCode <= ord('9')) or \
+ (keyCode >= ord('a') and keyCode <= ord('z')) or \
+ (keyCode >= ord('A') and keyCode <= ord('Z'))):
+
+ # find the next item starting with the given prefix
+ ch = chr(keyCode)
+ id = self.FindItem(self._current, self._findPrefix + ch)
+
+ if not id:
+ # no such item
+ return
+
+ if self.IsItemEnabled(id):
+ self.SelectItem(id)
+ self._findPrefix += ch
+
+ # also start the timer to reset the current prefix if the user
+ # doesn't press any more alnum keys soon -- we wouldn't want
+ # to use this prefix for a new item search
+ if not self._findTimer:
+ self._findTimer = TreeFindTimer(self)
+
+ self._findTimer.Start(_DELAY, wx.TIMER_ONE_SHOT)
+
+ else:
+
+ event.Skip()
+
+
+ def GetNextActiveItem(self, item, down=True):
+ """
+ Returns the next active item. Used Internally at present.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `down`: ``True`` to search downwards in the hierarchy for an active item,
+ ``False`` to search upwards.
+
+ :return: An instance of :class:`GenericTreeItem` if an active item has been found or
+ ``None`` if none has been found.
+ """
+
+ if down:
+ sibling = self.GetNextSibling
+ else:
+ sibling = self.GetPrevSibling
+
+ if self.GetItemType(item) == 2 and not self.IsItemChecked(item):
+ # Is an unchecked radiobutton... all its children are inactive
+ # try to get the next/previous sibling
+ found = 0
+
+ while 1:
+ child = sibling(item)
+ if (child and self.IsItemEnabled(child)) or not child:
+ break
+ item = child
+
+ else:
+ # Tha's not a radiobutton... but some of its children can be
+ # inactive
+ child, cookie = self.GetFirstChild(item)
+ while child and not self.IsItemEnabled(child):
+ child, cookie = self.GetNextChild(item, cookie)
+
+ if child and self.IsItemEnabled(child):
+ return child
+
+ return None
+
+
+ def HitTest(self, point, flags=0):
+ """
+ Calculates which (if any) item is under the given point, returning the tree item
+ at this point plus extra information flags.
+
+ :param `point`: an instance of :class:`Point`, a point to test for hits;
+ :param integer `flags`: a bitlist of the following values:
+
+ ================================== =============== =================================
+ HitTest Flags Hex Value Description
+ ================================== =============== =================================
+ ``TREE_HITTEST_ABOVE`` 0x1 Above the client area
+ ``TREE_HITTEST_BELOW`` 0x2 Below the client area
+ ``TREE_HITTEST_NOWHERE`` 0x4 No item has been hit
+ ``TREE_HITTEST_ONITEMBUTTON`` 0x8 On the button associated to an item
+ ``TREE_HITTEST_ONITEMICON`` 0x10 On the icon associated to an item
+ ``TREE_HITTEST_ONITEMINDENT`` 0x20 On the indent associated to an item
+ ``TREE_HITTEST_ONITEMLABEL`` 0x40 On the label (string) associated to an item
+ ``TREE_HITTEST_ONITEM`` 0x50 Anywhere on the item
+ ``TREE_HITTEST_ONITEMRIGHT`` 0x80 On the right of the label associated to an item
+ ``TREE_HITTEST_TOLEFT`` 0x200 On the left of the client area
+ ``TREE_HITTEST_TORIGHT`` 0x400 On the right of the client area
+ ``TREE_HITTEST_ONITEMUPPERPART`` 0x800 On the upper part (first half) of the item
+ ``TREE_HITTEST_ONITEMLOWERPART`` 0x1000 On the lower part (second half) of the item
+ ``TREE_HITTEST_ONITEMCHECKICON`` 0x2000 On the check/radio icon, if present
+ ================================== =============== =================================
+
+ :return: A tuple with the first value being an instance of :class:`GenericTreeItem` or ``None`` if
+ no item has been hit-tested, and as second value an integer parameter `flag`.
+
+ :note: both the item (if any, ``None`` otherwise) and the `flags` are always returned as a tuple.
+ """
+
+ w, h = self.GetSize()
+ flags = 0
+
+ if point.x < 0:
+ flags |= TREE_HITTEST_TOLEFT
+ if point.x > w:
+ flags |= TREE_HITTEST_TORIGHT
+ if point.y < 0:
+ flags |= TREE_HITTEST_ABOVE
+ if point.y > h:
+ flags |= TREE_HITTEST_BELOW
+
+ if flags:
+ return None, flags
+
+ if self._anchor == None:
+ flags = TREE_HITTEST_NOWHERE
+ return None, flags
+
+ hit, flags = self._anchor.HitTest(self.CalcUnscrolledPosition(point), self, flags, 0)
+
+ if hit == None:
+ flags = TREE_HITTEST_NOWHERE
+ return None, flags
+
+ if not self.IsItemEnabled(hit):
+ return None, flags
+
+ return hit, flags
+
+
+ def GetBoundingRect(self, item, textOnly=False):
+ """
+ Retrieves the rectangle bounding the item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param bool `textOnly`: if ``True``, only the rectangle around the item's label will
+ be returned, otherwise the item's image is also taken into account.
+
+ :return: An instance of :class:`Rect`.
+
+ :note: The rectangle coordinates are logical, not physical ones. So, for example,
+ the `x` coordinate may be negative if the tree has a horizontal scrollbar and its
+ position is not ``0``.
+ """
+
+ i = item
+
+ startX, startY = self.GetViewStart()
+ rect = wx.Rect()
+
+ rect.x = i.GetX() - startX*_PIXELS_PER_UNIT
+ rect.y = i.GetY() - startY*_PIXELS_PER_UNIT
+ rect.width = i.GetWidth()
+ rect.height = self.GetLineHeight(i)
+
+ return rect
+
+
+ def Edit(self, item):
+ """
+ Internal function. Starts the editing of an item label, sending a
+ ``EVT_TREE_BEGIN_LABEL_EDIT`` event.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+
+ .. warning:: Separator-type items can not be edited.
+ """
+
+ if item.IsSeparator():
+ return
+
+ te = TreeEvent(wxEVT_TREE_BEGIN_LABEL_EDIT, self.GetId())
+ te._item = item
+ te.SetEventObject(self)
+ if self.GetEventHandler().ProcessEvent(te) and not te.IsAllowed():
+ # vetoed by user
+ return
+
+ # We have to call this here because the label in
+ # question might just have been added and no screen
+ # update taken place.
+ if self._dirty:
+ if wx.Platform in ["__WXMSW__", "__WXMAC__"]:
+ self.Update()
+ else:
+ wx.YieldIfNeeded()
+
+ if self._editCtrl != None and item != self._editCtrl.item():
+ self._editCtrl.StopEditing()
+
+ self._editCtrl = TreeTextCtrl(self, item=item)
+ self._editCtrl.SetFocus()
+
+
+ def GetEditControl(self):
+ """
+ Returns a pointer to the edit :class:`TreeTextCtrl` if the item is being edited or
+ ``None`` otherwise (it is assumed that no more than one item may be edited
+ simultaneously).
+ """
+
+ return self._editCtrl
+
+
+ def OnAcceptEdit(self, item, value):
+ """
+ Called by :class:`TreeTextCtrl`, to accept the changes and to send the
+ ``EVT_TREE_END_LABEL_EDIT`` event.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param string `value`: the new value of the item label.
+
+ :return: ``True`` if the editing has not been vetoed, ``False`` otherwise.
+ """
+
+ le = TreeEvent(wxEVT_TREE_END_LABEL_EDIT, self.GetId())
+ le._item = item
+ le.SetEventObject(self)
+ le._label = value
+ le._editCancelled = False
+
+ return not self.GetEventHandler().ProcessEvent(le) or le.IsAllowed()
+
+
+ def OnCancelEdit(self, item):
+ """
+ Called by :class:`TreeTextCtrl`, to cancel the changes and to send the
+ ``EVT_TREE_END_LABEL_EDIT`` event.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ # let owner know that the edit was cancelled
+ le = TreeEvent(wxEVT_TREE_END_LABEL_EDIT, self.GetId())
+ le._item = item
+ le.SetEventObject(self)
+ le._label = ""
+ le._editCancelled = True
+
+ self.GetEventHandler().ProcessEvent(le)
+
+
+ def OnEditTimer(self):
+ """ The timer for editing has expired. Start editing. """
+
+ self.Edit(self._current)
+
+
+ def OnMouse(self, event):
+ """
+ Handles a bunch of ``wx.EVT_MOUSE_EVENTS`` events for :class:`CustomTreeCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self._anchor:
+ return
+
+ pt = self.CalcUnscrolledPosition(event.GetPosition())
+
+ # Is the mouse over a tree item button?
+ flags = 0
+ thisItem, flags = self._anchor.HitTest(pt, self, flags, 0)
+ underMouse = thisItem
+ underMouseChanged = underMouse != self._underMouse
+
+ if underMouse and (flags & TREE_HITTEST_ONITEM) and not event.LeftIsDown() and \
+ not self._isDragging and (not self._editTimer or not self._editTimer.IsRunning()):
+ underMouse = underMouse
+ else:
+ underMouse = None
+
+ if underMouse != self._underMouse:
+ if self._underMouse:
+ # unhighlight old item
+ self._underMouse = None
+
+ self._underMouse = underMouse
+
+ # Determines what item we are hovering over and need a tooltip for
+ hoverItem = thisItem
+
+ # We do not want a tooltip if we are dragging, or if the edit timer is running
+ if underMouseChanged and not self._isDragging and (not self._editTimer or not self._editTimer.IsRunning()):
+
+ if hoverItem is not None:
+ # Ask the tree control what tooltip (if any) should be shown
+ hevent = TreeEvent(wxEVT_TREE_ITEM_GETTOOLTIP, self.GetId())
+ hevent._item = hoverItem
+ hevent.SetEventObject(self)
+
+ if self.GetEventHandler().ProcessEvent(hevent) and hevent.IsAllowed():
+ self.SetToolTip(hevent._label)
+
+ elif self.HasAGWFlag(TR_TOOLTIP_ON_LONG_ITEMS):
+
+ tip = self.GetToolTipString()
+
+ if hoverItem.IsSeparator():
+ if tip:
+ self.SetToolTipString('')
+ else:
+ maxsize = self.GetItemSize(hoverItem)
+ itemText = hoverItem.GetText()
+
+ dc = wx.ClientDC(self)
+
+ if dc.GetMultiLineTextExtent(itemText)[0] > maxsize:
+ if tip != itemText:
+ self.SetToolTipString(itemText)
+ else:
+ if tip:
+ self.SetToolTipString('')
+
+ if hoverItem.IsHyperText() and (flags & TREE_HITTEST_ONITEMLABEL) and hoverItem.IsEnabled():
+ self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+ self._isonhyperlink = True
+ else:
+ if self._isonhyperlink:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ self._isonhyperlink = False
+
+ # we process left mouse up event (enables in-place edit), right down
+ # (pass to the user code), left dbl click (activate item) and
+ # dragging/moving events for items drag-and-drop
+
+ if not (event.LeftDown() or event.LeftUp() or event.RightDown() or event.LeftDClick() or \
+ event.Dragging() or ((event.Moving() or event.RightUp()) and self._isDragging)):
+
+ event.Skip()
+ return
+
+ flags = 0
+ item, flags = self._anchor.HitTest(pt, self, flags, 0)
+
+ if event.Dragging() and not self._isDragging and ((flags & TREE_HITTEST_ONITEMICON) or (flags & TREE_HITTEST_ONITEMLABEL)):
+
+ if self._dragCount == 0:
+ self._dragStart = pt
+
+ self._countDrag = 0
+ self._dragCount = self._dragCount + 1
+
+ if self._dragCount != 3:
+ # wait until user drags a bit further...
+ return
+
+ command = (event.RightIsDown() and [wxEVT_TREE_BEGIN_RDRAG] or [wxEVT_TREE_BEGIN_DRAG])[0]
+
+ nevent = TreeEvent(command, self.GetId())
+ nevent._item = self._current
+ nevent.SetEventObject(self)
+ newpt = self.CalcScrolledPosition(pt)
+ nevent.SetPoint(newpt)
+
+ # by default the dragging is not supported, the user code must
+ # explicitly allow the event for it to take place
+ nevent.Veto()
+
+ if self.GetEventHandler().ProcessEvent(nevent) and nevent.IsAllowed():
+
+ # we're going to drag this item
+ self._isDragging = True
+
+ # remember the old cursor because we will change it while
+ # dragging
+ self._oldCursor = self._cursor
+
+ # in a single selection control, hide the selection temporarily
+ if not (self.GetAGWWindowStyleFlag() & TR_MULTIPLE):
+ self._oldSelection = self.GetSelection()
+
+ if self._oldSelection:
+
+ self._oldSelection.SetHilight(False)
+ self.RefreshLine(self._oldSelection)
+ else:
+ selections = self.GetSelections()
+ if len(selections) == 1:
+ self._oldSelection = selections[0]
+ self._oldSelection.SetHilight(False)
+ self.RefreshLine(self._oldSelection)
+
+ if self._dragImage:
+ del self._dragImage
+
+ # Create the custom draw image from the icons and the text of the item
+ self._dragImage = DragImage(self, self._current)
+ self._dragImage.BeginDrag(wx.Point(0,0), self)
+ self._dragImage.Show()
+ self._dragImage.Move(self.CalcScrolledPosition(pt))
+
+ elif event.Dragging() and self._isDragging:
+
+ self._dragImage.Move(self.CalcScrolledPosition(pt))
+
+ if self._countDrag == 0 and item:
+ self._oldItem = item
+
+ if item != self._dropTarget:
+
+ # unhighlight the previous drop target
+ if self._dropTarget:
+ self._dropTarget.SetHilight(False)
+ self.RefreshLine(self._dropTarget)
+ if item:
+ item.SetHilight(True)
+ self.RefreshLine(item)
+ self._countDrag = self._countDrag + 1
+ self._dropTarget = item
+
+ self.Update()
+
+ if self._countDrag >= 3:
+ # Here I am trying to avoid ugly repainting problems... hope it works
+ self.RefreshLine(self._oldItem)
+ self._countDrag = 0
+
+ elif (event.LeftUp() or event.RightUp()) and self._isDragging:
+
+ if self._dragImage:
+ self._dragImage.EndDrag()
+
+ if self._dropTarget:
+ self._dropTarget.SetHilight(False)
+
+ if self._oldSelection:
+
+ self._oldSelection.SetHilight(True)
+ self.RefreshLine(self._oldSelection)
+ self._oldSelection = None
+
+ # generate the drag end event
+ event = TreeEvent(wxEVT_TREE_END_DRAG, self.GetId())
+ event._item = item
+ event._pointDrag = self.CalcScrolledPosition(pt)
+ event.SetEventObject(self)
+
+ self.GetEventHandler().ProcessEvent(event)
+
+ self._isDragging = False
+ self._dropTarget = None
+
+ self.SetCursor(self._oldCursor)
+
+ if wx.Platform in ["__WXMSW__", "__WXMAC__"]:
+ self.Refresh()
+ else:
+ # Probably this is not enough on GTK. Try a Refresh() if it does not work.
+ wx.YieldIfNeeded()
+
+ else:
+
+ # If we got to this point, we are not dragging or moving the mouse.
+ # Because the code in carbon/toplevel.cpp will only set focus to the tree
+ # if we skip for EVT_LEFT_DOWN, we MUST skip this event here for focus to work.
+ # We skip even if we didn't hit an item because we still should
+ # restore focus to the tree control even if we didn't exactly hit an item.
+ if event.LeftDown():
+ self._hasFocus = True
+ self.SetFocusIgnoringChildren()
+ event.Skip()
+
+ # here we process only the messages which happen on tree items
+
+ self._dragCount = 0
+
+ if item == None:
+ if self._editCtrl != None and item != self._editCtrl.item():
+ self._editCtrl.StopEditing()
+ return # we hit the blank area
+
+ if event.RightDown():
+
+ if self._editCtrl != None and item != self._editCtrl.item():
+ self._editCtrl.StopEditing()
+
+ self._hasFocus = True
+ self.SetFocusIgnoringChildren()
+
+ # If the item is already selected, do not update the selection.
+ # Multi-selections should not be cleared if a selected item is clicked.
+ if not self.IsSelected(item):
+
+ self.DoSelectItem(item, True, False)
+
+ nevent = TreeEvent(wxEVT_TREE_ITEM_RIGHT_CLICK, self.GetId())
+ nevent._item = item
+ nevent._pointDrag = self.CalcScrolledPosition(pt)
+ nevent.SetEventObject(self)
+ event.Skip(not self.GetEventHandler().ProcessEvent(nevent))
+
+ # Consistent with MSW (for now), send the ITEM_MENU *after*
+ # the RIGHT_CLICK event. TODO: This behaviour may change.
+ nevent2 = TreeEvent(wxEVT_TREE_ITEM_MENU, self.GetId())
+ nevent2._item = item
+ nevent2._pointDrag = self.CalcScrolledPosition(pt)
+ nevent2.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(nevent2)
+
+ elif event.LeftUp():
+
+ # this facilitates multiple-item drag-and-drop
+
+ if self.HasAGWFlag(TR_MULTIPLE):
+
+ selections = self.GetSelections()
+
+ if len(selections) > 1 and not event.CmdDown() and not event.ShiftDown():
+
+ self.DoSelectItem(item, True, False)
+
+ if self._lastOnSame:
+
+ if item == self._current and (flags & TREE_HITTEST_ONITEMLABEL) and self.HasAGWFlag(TR_EDIT_LABELS):
+
+ if self._editTimer:
+
+ if self._editTimer.IsRunning():
+
+ self._editTimer.Stop()
+
+ else:
+
+ self._editTimer = TreeEditTimer(self)
+
+ self._editTimer.Start(_DELAY, True)
+
+ self._lastOnSame = False
+
+
+ else: # !RightDown() && !LeftUp() ==> LeftDown() || LeftDClick()
+
+ if not item or not item.IsEnabled():
+ if self._editCtrl != None and item != self._editCtrl.item():
+ self._editCtrl.StopEditing()
+ return
+
+ if self._editCtrl != None and item != self._editCtrl.item():
+ self._editCtrl.StopEditing()
+
+ self._hasFocus = True
+ self.SetFocusIgnoringChildren()
+
+ if event.LeftDown():
+
+ self._lastOnSame = item == self._current
+
+ if flags & TREE_HITTEST_ONITEMBUTTON:
+
+ # only toggle the item for a single click, double click on
+ # the button doesn't do anything (it toggles the item twice)
+ if event.LeftDown():
+
+ self.Toggle(item)
+
+ # don't select the item if the button was clicked
+ return
+
+ if item.GetType() > 0 and (flags & TREE_HITTEST_ONITEMCHECKICON) and (flags & TREE_HITTEST_ONITEMLABEL == 0):
+
+ if event.LeftDown():
+ if flags & TREE_HITTEST_ONITEM and self.HasAGWFlag(TR_FULL_ROW_HIGHLIGHT):
+ self.DoSelectItem(item, not self.HasAGWFlag(TR_MULTIPLE))
+
+ if self.IsItem3State(item):
+ checked = self.GetItem3StateValue(item)
+ checked = (checked+1)%3
+ else:
+ checked = not self.IsItemChecked(item)
+
+ self.CheckItem(item, checked)
+
+ return
+
+ # clear the previously selected items, if the
+ # user clicked outside of the present selection.
+ # otherwise, perform the deselection on mouse-up.
+ # this allows multiple drag and drop to work.
+ # but if Cmd is down, toggle selection of the clicked item
+ if not self.IsSelected(item) or event.CmdDown():
+
+ if flags & TREE_HITTEST_ONITEM:
+ # how should the selection work for this event?
+ if item.IsHyperText():
+ self.SetItemVisited(item, True)
+
+ is_multiple, extended_select, unselect_others = EventFlagsToSelType(self.GetAGWWindowStyleFlag(),
+ event.ShiftDown(),
+ event.CmdDown())
+
+ self.DoSelectItem(item, unselect_others, extended_select)
+
+ # Handle hyperlink items... which are a bit odd sometimes
+ elif self.IsSelected(item) and item.IsHyperText():
+ self.HandleHyperLink(item)
+
+ # For some reason, Windows isn't recognizing a left double-click,
+ # so we need to simulate it here. Allow 200 milliseconds for now.
+ if event.LeftDClick():
+
+ # double clicking should not start editing the item label
+ if self._editTimer:
+ self._editTimer.Stop()
+
+ self._lastOnSame = False
+
+ # send activate event first
+ nevent = TreeEvent(wxEVT_TREE_ITEM_ACTIVATED, self.GetId())
+ nevent._item = item
+ nevent._pointDrag = self.CalcScrolledPosition(pt)
+ nevent.SetEventObject(self)
+ if not self.GetEventHandler().ProcessEvent(nevent):
+
+ # if the user code didn't process the activate event,
+ # handle it ourselves by toggling the item when it is
+ # double clicked
+## if item.HasPlus():
+ self.Toggle(item)
+
+
+ def OnInternalIdle(self):
+ """
+ This method is normally only used internally, but sometimes an application
+ may need it to implement functionality that should not be disabled by an
+ application defining an `OnIdle` handler in a derived class.
+
+ This method may be used to do delayed painting, for example, and most
+ implementations call :meth:`Window.UpdateWindowUI` in order to send update events
+ to the window in idle time.
+ """
+
+ # Check if we need to select the root item
+ # because nothing else has been selected.
+ # Delaying it means that we can invoke event handlers
+ # as required, when a first item is selected.
+ if not self.HasAGWFlag(TR_MULTIPLE) and not self.GetSelection():
+
+ if self._select_me:
+ self.SelectItem(self._select_me)
+ elif self.GetRootItem():
+ self.SelectItem(self.GetRootItem())
+
+ # after all changes have been done to the tree control,
+ # we actually redraw the tree when everything is over
+
+ if not self._dirty:
+ return
+ if self._freezeCount:
+ return
+
+ self._dirty = False
+
+ self.CalculatePositions()
+ self.Refresh()
+ self.AdjustMyScrollbars()
+
+# event.Skip()
+
+
+ def CalculateSize(self, item, dc, level=-1, align=0):
+ """
+ Calculates overall position and size of an item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param `dc`: an instance of :class:`DC`;
+ :param integer `level`: the item level in the tree hierarchy;
+ :param integer `align`: an integer specifying the alignment type:
+
+ =============== =========================================
+ `align` Value Description
+ =============== =========================================
+ 0 No horizontal alignment of windows (in items with windows).
+ 1 Windows (in items with windows) are aligned at the same horizontal position.
+ 2 Windows (in items with windows) are aligned at the rightmost edge of :class:`CustomTreeCtrl`.
+ =============== =========================================
+
+ """
+
+ attr = item.GetAttributes()
+
+ if attr and attr.HasFont():
+ dc.SetFont(attr.GetFont())
+ else:
+ if item.IsBold():
+ dc.SetFont(self._boldFont)
+ elif item.IsItalic():
+ dc.SetFont(self._italicFont)
+ else:
+ dc.SetFont(self._normalFont)
+
+ text_w, text_h, dummy = dc.GetMultiLineTextExtent(item.GetText())
+ text_h+=2
+
+ # restore normal font
+ dc.SetFont(self._normalFont)
+
+ image_w, image_h = 0, 0
+ image = item.GetCurrentImage()
+
+ if image != _NO_IMAGE:
+
+ if self._imageListNormal:
+
+ image_w, image_h = self._imageListNormal.GetSize(image)
+ image_w += 4
+
+ total_h = ((image_h > text_h) and [image_h] or [text_h])[0]
+
+ checkimage = item.GetCurrentCheckedImage()
+ if checkimage is not None:
+ wcheck, hcheck = self._imageListCheck.GetSize(checkimage)
+ wcheck += 4
+ else:
+ wcheck = 0
+
+ if total_h < 30:
+ total_h += 2 # at least 2 pixels
+ else:
+ total_h += total_h/10 # otherwise 10% extra spacing
+
+ if total_h > self._lineHeight:
+ self._lineHeight = total_h
+
+ wnd = item.GetWindow()
+ if not wnd:
+ totalWidth = image_w+text_w+wcheck+2
+ totalHeight = total_h
+ else:
+ totalWidth = item.GetWindowSize()[0]+image_w+text_w+wcheck+2
+ totalHeight = max(total_h, item.GetWindowSize()[1])
+
+ if level >= 0 and wnd:
+ if align == 0:
+ if level in self.absoluteWindows:
+ self.absoluteWindows[level] = max(self.absoluteWindows[level], image_w+text_w+wcheck+2)
+ else:
+ self.absoluteWindows[level] = image_w+text_w+wcheck+2
+ elif align == 1:
+ self.absoluteWindows[level] = max(self.absoluteWindows[level], image_w+text_w+wcheck+2)
+
+ if item.IsSeparator():
+ totalWidth = self.GetClientSize()[0]
+ totalHeight = total_h
+
+ item.SetWidth(totalWidth)
+ item.SetHeight(totalHeight)
+
+
+ def CalculateLevel(self, item, dc, level, y, align=0):
+ """
+ Calculates the level of an item inside the tree hierarchy.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param `dc`: an instance of :class:`DC`;
+ :param integer `level`: the item level in the tree hierarchy;
+ :param integer `y`: the current vertical position inside the :class:`PyScrolledWindow`;
+ :param integer `align`: an integer specifying the alignment type:
+
+ =============== =========================================
+ `align` Value Description
+ =============== =========================================
+ 0 No horizontal alignment of windows (in items with windows).
+ 1 Windows (in items with windows) are aligned at the same horizontal position.
+ 2 Windows (in items with windows) are aligned at the rightmost edge of :class:`CustomTreeCtrl`.
+ =============== =========================================
+
+ :return: The new `y` vertical position inside the :class:`PyScrolledWindow`.
+ """
+
+ x = level*self._indent
+
+ if not self.HasAGWFlag(TR_HIDE_ROOT):
+
+ x += self._indent
+
+ elif level == 0:
+
+ # a hidden root is not evaluated, but its
+ # children are always calculated
+ children = item.GetChildren()
+ count = len(children)
+ level = level + 1
+ for n in xrange(count):
+ y = self.CalculateLevel(children[n], dc, level, y, align) # recurse
+
+ return y
+
+ self.CalculateSize(item, dc, level, align)
+
+ # set its position
+ item.SetX(x+self._spacing)
+ item.SetY(y)
+ y += self.GetLineHeight(item)
+
+ if not item.IsExpanded():
+ # we don't need to calculate collapsed branches
+ return y
+
+ children = item.GetChildren()
+ count = len(children)
+ level = level + 1
+ for n in xrange(count):
+ y = self.CalculateLevel(children[n], dc, level, y, align) # recurse
+
+ return y
+
+
+ def CalculatePositions(self):
+ """ Calculates all the positions of the visible items. """
+
+ if not self._anchor:
+ return
+
+ self.absoluteWindows = {}
+
+ dc = wx.ClientDC(self)
+ self.PrepareDC(dc)
+
+ dc.SetFont(self._normalFont)
+ dc.SetPen(self._dottedPen)
+ y = 2
+ y = self.CalculateLevel(self._anchor, dc, 0, y) # start recursion
+
+ if self.HasAGWFlag(TR_ALIGN_WINDOWS) or self.HasAGWFlag(TR_ALIGN_WINDOWS_RIGHT):
+ align = (self.HasAGWFlag(TR_ALIGN_WINDOWS) and [1] or [2])[0]
+ y = 2
+ y = self.CalculateLevel(self._anchor, dc, 0, y, align) # start recursion
+
+
+ def RefreshSubtree(self, item):
+ """
+ Refreshes a damaged subtree of an item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ if self._dirty:
+ return
+ if self._freezeCount:
+ return
+
+ client = self.GetClientSize()
+
+ rect = wx.Rect()
+ x, rect.y = self.CalcScrolledPosition(0, item.GetY())
+ rect.width = client.x
+ rect.height = client.y
+
+ self.Refresh(True, rect)
+ self.AdjustMyScrollbars()
+
+
+ def RefreshLine(self, item):
+ """
+ Refreshes a damaged item line.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ if self._dirty:
+ return
+ if self._freezeCount:
+ return
+
+ rect = wx.Rect()
+ x, rect.y = self.CalcScrolledPosition(0, item.GetY())
+ rect.width = self.GetClientSize().x
+ rect.height = self.GetLineHeight(item)
+
+ self.Refresh(True, rect)
+
+
+ def RefreshSelected(self):
+ """ Refreshes a damaged selected item line. """
+
+ if self._freezeCount:
+ return
+
+ # TODO: this is awfully inefficient, we should keep the list of all
+ # selected items internally, should be much faster
+ if self._anchor:
+ self.RefreshSelectedUnder(self._anchor)
+
+
+ def RefreshSelectedUnder(self, item):
+ """
+ Refreshes the selected items under the given item.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ if self._freezeCount:
+ return
+
+ if item.IsSelected():
+ self.RefreshLine(item)
+
+ children = item.GetChildren()
+ for child in children:
+ self.RefreshSelectedUnder(child)
+
+
+ def RefreshItemWithWindows(self, item=None):
+ """
+ Refreshes the items with which a window is associated.
+
+ :param `item`: an instance of :class:`GenericTreeItem`. If `item` is ``None``, then the
+ recursive refresh starts from the root node.
+
+ :note: This method is called only if the style ``TR_ALIGN_WINDOWS_RIGHT`` is used.
+ """
+
+ if self._freezeCount:
+ return
+
+ if item is None:
+ if self._anchor:
+ self.RefreshItemWithWindows(self._anchor)
+ return
+
+ wnd = item.GetWindow()
+ if wnd and wnd.IsShown():
+ self.RefreshLine(item)
+
+ children = item.GetChildren()
+ for child in children:
+ self.RefreshItemWithWindows(child)
+
+
+ def Freeze(self):
+ """
+ Freeze :class:`CustomTreeCtrl`.
+
+ Freezes the window or, in other words, prevents any updates from taking place
+ on screen, the window is not redrawn at all. :meth:`~Thaw` must be called to reenable
+ window redrawing. Calls to these two functions may be nested.
+
+ :note: This method is useful for visual appearance optimization (for example,
+ it is a good idea to use it before doing many large text insertions in a row
+ into a :class:`TextCtrl` under wxGTK) but is not implemented on all platforms nor
+ for all controls so it is mostly just a hint to wxWidgets and not a mandatory
+ directive.
+ """
+
+ self._freezeCount = self._freezeCount + 1
+
+
+ def Thaw(self):
+ """
+ Thaw :class:`CustomTreeCtrl`.
+
+ Reenables window updating after a previous call to :meth:`~Freeze`. To really thaw the
+ control, it must be called exactly the same number of times as :meth:`~Freeze`.
+
+ :raise: `Exception` if :meth:`~Thaw` has been called without an un-matching :meth:`~Freeze`.
+ """
+
+ if self._freezeCount == 0:
+ raise Exception("\nERROR: Thawing Unfrozen Tree Control?")
+
+ self._freezeCount = self._freezeCount - 1
+
+ if not self._freezeCount:
+ self.Refresh()
+
+
+ # ----------------------------------------------------------------------------
+ # changing colours: we need to refresh the tree control
+ # ----------------------------------------------------------------------------
+
+ def SetBackgroundColour(self, colour):
+ """
+ Changes the background colour of :class:`CustomTreeCtrl`.
+
+ :param `colour`: the colour to be used as the background colour, pass
+ :class:`NullColour` to reset to the default colour.
+
+ :return: ``False`` if the underlying :class:`PyScrolledWindow` does not accept
+ the new colour, ``True`` otherwise.
+
+ :note: The background colour is usually painted by the default :class:`EraseEvent`
+ event handler function under Windows and automatically under GTK.
+
+ :note: Setting the background colour does not cause an immediate refresh, so
+ you may wish to call :meth:`Window.ClearBackground` or :meth:`Window.Refresh` after
+ calling this function.
+
+ :note: Overridden from :class:`PyScrolledWindow`.
+ """
+
+ if not wx.PyScrolledWindow.SetBackgroundColour(self, colour):
+ return False
+
+ if self._freezeCount:
+ return True
+
+ self.Refresh()
+
+ return True
+
+
+ def SetForegroundColour(self, colour):
+ """
+ Changes the foreground colour of :class:`CustomTreeCtrl`.
+
+ :param `colour`: the colour to be used as the foreground colour, pass
+ :class:`NullColour` to reset to the default colour.
+
+ :return: ``False`` if the underlying :class:`PyScrolledWindow` does not accept
+ the new colour, ``True`` otherwise.
+
+ :note: Overridden from :class:`PyScrolledWindow`.
+ """
+
+ if not wx.PyScrolledWindow.SetForegroundColour(self, colour):
+ return False
+
+ if self._freezeCount:
+ return True
+
+ self.Refresh()
+
+ return True
+
+
+ def OnGetToolTip(self, event):
+ """
+ Process the tooltip event, to speed up event processing. Does not actually
+ get a tooltip.
+
+ :param `event`: a :class:`CommandTreeEvent` event to be processed.
+ """
+
+ event.Veto()
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :return: An instance of :class:`Size`.
+
+ :note: Overridden from :class:`PyScrolledWindow`.
+ """
+
+ # something is better than nothing...
+ # 100x80 is what the MSW version will get from the default
+ # wxControl::DoGetBestSize
+
+ return wx.Size(100, 80)
+
+
+ def GetMaxWidth(self, respect_expansion_state=True):
+ """
+ Returns the maximum width of the :class:`CustomTreeCtrl`.
+
+ :param bool `respect_expansion_state`: if ``True``, only the expanded items (and their
+ children) will be measured. Otherwise all the items are expanded and
+ their width measured.
+
+ :return: the maximum width of :class:`CustomTreeCtrl`, in pixels.
+ """
+
+ self.Freeze()
+
+ root = self.GetRootItem()
+ rect = self.GetBoundingRect(root, True)
+
+ # It looks like the space between the "+" and the node
+ # rect occupies 4 pixels approximatively
+ maxwidth = rect.x + rect.width + 4
+ lastheight = rect.y + rect.height
+
+ if not self.IsExpanded(root):
+ if respect_expansion_state:
+ return maxwidth
+
+ if not respect_expansion_state:
+ self.ExpandAll()
+
+ maxwidth, lastheight = self.RecurseOnChildren(root, maxwidth, respect_expansion_state)
+
+ self.Thaw()
+
+ return maxwidth
+
+
+ def RecurseOnChildren(self, item, maxwidth, respect_expansion_state):
+ """
+ Recurses over all the children of the spcified items, calculating their
+ maximum width.
+
+ :param `item`: an instance of :class:`GenericTreeItem`;
+ :param integer `maxwidth`: the current maximum width for :class:`CustomTreeCtrl`, in pixels;
+ :param bool `respect_expansion_state`: if ``True``, only the expanded items (and their
+ children) will be measured. Otherwise all the items are expanded and
+ their width measured.
+
+ :return: A tuple containing the maximum width and item height, in pixels.
+ """
+
+ child, cookie = self.GetFirstChild(item)
+ lastheight = 0
+
+ while child:
+
+ rect = self.GetBoundingRect(child, True)
+
+ # It looks like the space between the "+" and the node
+ # rect occupies 4 pixels approximatively
+ maxwidth = max(maxwidth, rect.x + rect.width + 4)
+ lastheight = rect.y + rect.height
+
+ if self.IsExpanded(child) or not respect_expansion_state:
+ maxwidth, lastheight = self.RecurseOnChildren(child, maxwidth, respect_expansion_state)
+
+ child, cookie = self.GetNextChild(item, cookie)
+
+ return maxwidth, lastheight
+
+
+ def GetClassDefaultAttributes(self):
+ """
+ Returns the default font and colours which are used by the control. This is
+ useful if you want to use the same font or colour in your own control as in
+ a standard control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the users system,
+ especially if it uses themes.
+
+ This static method is "overridden'' in many derived classes and so calling,
+ for example, :meth:`Button.GetClassDefaultAttributes` () will typically return the
+ values appropriate for a button which will be normally different from those
+ returned by, say, :meth:`ListCtrl.GetClassDefaultAttributes` ().
+
+ :return: An instance of :class:`VisualAttributes`.
+
+ :note: The :class:`VisualAttributes` structure has at least the fields `font`,
+ `colFg` and `colBg`. All of them may be invalid if it was not possible to
+ determine the default control appearance or, especially for the background
+ colour, if the field doesn't make sense as is the case for `colBg` for the
+ controls with themed background.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ attr = wx.VisualAttributes()
+ attr.colFg = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ attr.colBg = wx.SystemSettings_GetColour(wx.SYS_COLOUR_LISTBOX)
+ attr.font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ return attr
+
+ GetClassDefaultAttributes = classmethod(GetClassDefaultAttributes)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_1.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_1.png
new file mode 100644
index 0000000..d9a5e4d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_1.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_1_thumb.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_1_thumb.png
new file mode 100644
index 0000000..bbd1dd7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_1_thumb.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_2.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_2.png
new file mode 100644
index 0000000..6e36786
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_2.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_2_thumb.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_2_thumb.png
new file mode 100644
index 0000000..d082ac1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_2_thumb.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_3.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_3.png
new file mode 100644
index 0000000..99c8d67
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_3.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_3_thumb.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_3_thumb.png
new file mode 100644
index 0000000..4784bde
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_3_thumb.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_4.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_4.png
new file mode 100644
index 0000000..554fa1e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_4.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_4_thumb.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_4_thumb.png
new file mode 100644
index 0000000..f0457af
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/ShortcutEditor_4_thumb.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/default_help_text.html b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/default_help_text.html
new file mode 100644
index 0000000..9f32ba8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/data/default_help_text.html
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+ <META NAME="GENERATOR" CONTENT="Mozilla/4.06 [en] (X11; I; Linux 2.0.35 i686) [Netscape]">
+<TITLE>Configure Keyboard Shortcuts Help</TITLE>
+</HEAD>
+
+<h3>Configure Keyboard Shortcuts Help</h3>
+
+Keyboard shortcuts can be useful tools for speeding up your workflow when working with <YOUR
+APPLICATION>. Many tools and features have keyboard shortcuts assigned by default.
+
+<p><br>
+
+However, if you want to add a keyboard shortcut to a feature that doesn't have one, or change
+an existing shortcut to one that feels more intuitive to you, <THIS APPLICATION> offers an easy
+way to do this using the <i>Keyboard Shortcut Editor</i>. Just follow the steps below to start
+customizing the <APPLICATION> to better suit the way that you work.
+
+<p><br>
+
+
+<h5>1. Open Subsection if Necessary</h5>
+
+In the <i>Configure Keyboard Shortcuts</i> you can open sub-sections by clicking the small box
+with a + sign in it next to each section name. In the screen grab, you can see I've opened the <i>Options</i>
+sub-section as I'm going to add a keyboard shortcut to the <i>OptionsItem 1</i>.
+
+<p><br>
+
+<a href="ShortcutEditor_1.png"><img src="ShortcutEditor_1_thumb.png" alt="Open Subsections" align=center></a>
+<br>
+
+<p><br>
+
+
+<h5>2. Assign New Keyboard Shortcut</h5>
+
+Now you need to scroll to the tool or command that you want to edit and click on it to select it. When selected,
+the text for that tool in the <i>Shortcut</i> column changes to read 'New accelerator...' and you can press
+the key or combination of keys you want to assign as a shortcut.
+
+<p><br>
+
+<a href="ShortcutEditor_2.png"><img src="ShortcutEditor_2_thumb.png" alt="Assign New Keyboard Shortcut" align=center></a>
+<br>
+
+<p><br>
+
+<h5>3. Remove or Save Shortcuts</h5>
+
+I've changed the <i>OptionsItem 1</i>'s keyboard shortcut to Shift+Ctrl+F by pressing the Shift, Ctrl and F keys
+simultaneously. If you want to remove a keyboard shortcut from any tool or command, just click on it to select it
+and then when the 'New accelerator...' text displays, press the backspace key and the text will change to 'Disabled'.
+
+Once you're happy that your keyboard shortcuts are set up as you wish, simply click <i>OK</i>.
+
+<p><br>
+
+<a href="ShortcutEditor_3.png"><img src="ShortcutEditor_3_thumb.png" alt="Remove or Save Shortcuts" align=center></a>
+<br>
+
+<p><br>
+
+<h5>4. Beware of Reassigning Existing Shortcuts</h5>
+
+If you thought my choice of Shift+Ctrl+F was an odd selection, I chose it because it was a keyboard combination
+that hadn't already been assigned to any tool or command. If you try to assign a keyboard shortcut that is already
+in use, an alert will open telling you what the shortcut is currently being used for. If you want to keep the
+original shortcut, just click the <i>Cancel</i> button, otherwise click <i>Reassign shortcut</i> to make the
+shortcut apply to your new selection.
+
+<p><br>
+
+<a href="ShortcutEditor_4.png"><img src="ShortcutEditor_4_thumb.png" alt="Beware of Reassigning Existing Shortcuts" align=center></a>
+<br>
+
+<p><br>
+
+
+<h5>5. Don't Go Shortcut Crazy!</h5>
+
+Don't feel that every tool or command should have a keyboard shortcut assigned to it and that you need to memorize
+all of them. We all use applications in different ways - often using different tools and techniques to achieve
+similar results - so concentrate on the tools that you use.
+
+Taking some time to customize <YOUR APPLICATION> to work in a way that suits you can be a good investment of your time.
+A well thought out series of keyboard shortcuts can have a dramatic effect on your workflow.
+
+<p><br>
+
+
+<h5>6. Useful Tips</h5>
+
+<ul>
+<li> Try to analyze how you work and which tools you use on a regular basis, then look at assigning easily accessed
+keyboard combinations to these tools and commands only. </li>
+<li>Don't be afraid to try out different shortcuts, or to reassign default shortcuts to new tools or commands.</li>
+<li>Assigning shortcuts that are grouped together on the keyboard may mean you can select tools without moving
+your hand, but using shortcuts that are more spaced out may reduce the possibility of you selecting the incorrect
+tool. This will be down to personal preference.</li>
+</ul>
+
+<p><br>
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/flatmenu.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/flatmenu.py
new file mode 100644
index 0000000..89460dc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/flatmenu.py
@@ -0,0 +1,7304 @@
+# --------------------------------------------------------------------------------- #
+# FLATMENU wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 03 Nov 2006
+# Latest Revision: 29 Apr 2012, 23.00 GMT
+#
+# TODO List
+#
+# 1. Work is still in progress, so other functionalities may be added in the future;
+# 2. No shadows under MAC, but it may be possible to create them using Carbon.
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@maerskoil.com
+# andrea.gavana@gmail.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`FlatMenu` is a generic menu implementation.
+
+
+Description
+===========
+
+:class:`FlatMenu`, like the name implies, it is a generic menu implementation.
+I tried to provide a full functionality for menus, menubar and toolbar.
+
+
+:class:`FlatMenu` supports the following features:
+
+- Fires all the events (UI & Cmd);
+- Check items;
+- Separators;
+- Enabled / Disabled menu items;
+- Images on items;
+- Toolbar support, with images and separators;
+- Controls in toolbar (work in progress);
+- Toolbar tools tooltips (done: thanks to Peter Kort);
+- Accelerators for menus;
+- Accelerators for menubar;
+- Radio items in menus;
+- Integration with AUI;
+- Scrolling when menu is too big to fit the screen;
+- Menu navigation with keyboard;
+- Drop down arrow button to the right of the menu, it always contains the
+ "Customize" option, which will popup an options dialog. The dialog has the
+ following abilities:
+
+ (a) Ability to add/remove menus;
+ (b) Select different colour schemes for the menu bar / toolbar;
+ (c) Control various options, such as: colour for highlight menu item, draw
+ border around menus (classic look only);
+ (d) Toolbar floating appearance.
+
+- Allows user to specify grey bitmap for disabled menus/toolbar tools;
+- If no grey bitmap is provided, it generates one from the existing bitmap;
+- Hidden toolbar items / menu bar items - will appear in a small popmenu
+ to the right if they are hidden;
+- 4 different colour schemes for the menu bar (more can easily added);
+- Scrolling is available if the menu height is greater than the screen height;
+- Context menus for menu items;
+- Show/hide the drop down arrow which allows the customization of :class:`FlatMenu`;
+- Multiple columns menu window;
+- Tooltips for menus and toolbar items on a :class:`StatusBar` (if present);
+- Transparency (alpha channel) for menu windows (for platforms supporting it);
+- FileHistory support through a pure-Python :class:`FileHistory` implementation;
+- Possibility to set a background bitmap for a :class:`FlatMenu`;
+- First attempt in adding controls to FlatToolbar;
+- Added a MiniBar (thanks to Vladiuz);
+- Added :class:`ToolBar` methods AddCheckTool/AddRadioTool (thanks to Vladiuz).
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.flatmenu as FM
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "FlatMenu Demo")
+
+ self.CreateMenu()
+
+ panel = wx.Panel(self, -1)
+ btn = wx.Button(panel, -1, "Hello", (15, 12), (100, 120))
+
+ main_sizer = wx.BoxSizer(wx.VERTICAL)
+ main_sizer.Add(self.menubar, 0, wx.EXPAND)
+ main_sizer.Add(panel, 1, wx.EXPAND)
+
+ self.SetSizer(main_sizer)
+ main_sizer.Layout()
+
+
+ def CreateMenu(self):
+
+ self.menubar = FM.FlatMenuBar(self, -1)
+
+ f_menu = FM.FlatMenu()
+ e_menu = FM.FlatMenu()
+ v_menu = FM.FlatMenu()
+ t_menu = FM.FlatMenu()
+ w_menu = FM.FlatMenu()
+
+ # Append the menu items to the menus
+ f_menu.Append(-1, "Simple\tCtrl+N", "Text", None)
+ e_menu.Append(-1, "FlatMenu", "Text", None)
+ v_menu.Append(-1, "Example", "Text", None)
+ t_menu.Append(-1, "Hello", "Text", None)
+ w_menu.Append(-1, "World", "Text", None)
+
+ # Append menus to the menubar
+ self.menubar.Append(f_menu, "&File")
+ self.menubar.Append(e_menu, "&Edit")
+ self.menubar.Append(v_menu, "&View")
+ self.menubar.Append(t_menu, "&Options")
+ self.menubar.Append(w_menu, "&Help")
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`FlatMenu` has been tested on the following platforms:
+ * Windows (Windows XP, Vista);
+ * Linux Ubuntu (Dapper 6.06)
+
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+========================= =========== ==================================================
+Window Styles Hex Value Description
+========================= =========== ==================================================
+``FM_OPT_IS_LCD`` 0x1 Use this style if your computer uses a LCD screen.
+``FM_OPT_MINIBAR`` 0x2 Use this if you plan to use the toolbar only.
+``FM_OPT_SHOW_CUSTOMIZE`` 0x4 Show "customize link" in the `More` menu, you will need to write your own handler. See demo.
+``FM_OPT_SHOW_TOOLBAR`` 0x8 Set this option is you are planning to use the toolbar.
+========================= =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================================= ==================================================
+Event Name Description
+================================= ==================================================
+``EVT_FLAT_MENU_DISMISSED`` Used internally.
+``EVT_FLAT_MENU_ITEM_MOUSE_OUT`` Fires an event when the mouse leaves a :class:`FlatMenuItem`.
+``EVT_FLAT_MENU_ITEM_MOUSE_OVER`` Fires an event when the mouse enters a :class:`FlatMenuItem`.
+``EVT_FLAT_MENU_SELECTED`` Fires the :class:`EVT_MENU` event for :class:`FlatMenu`.
+================================= ==================================================
+
+
+License And Version
+===================
+
+:class:`FlatMenu` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 29 Apr 2012, 23.00 GMT
+
+Version 1.0
+
+"""
+
+__docformat__ = "epytext"
+__version__ = "1.0"
+
+import wx
+import os
+import math
+import cStringIO
+
+import wx.lib.colourutils as colourutils
+
+from fmcustomizedlg import FMCustomizeDlg
+from artmanager import ArtManager, DCSaver
+from fmresources import *
+
+# FlatMenu styles
+FM_OPT_IS_LCD = 1
+""" Use this style if your computer uses a LCD screen. """
+FM_OPT_MINIBAR = 2
+""" Use this if you plan to use the toolbar only. """
+FM_OPT_SHOW_CUSTOMIZE = 4
+""" Show "customize link" in the `More` menu, you will need to write your own handler. See demo. """
+FM_OPT_SHOW_TOOLBAR = 8
+""" Set this option is you are planning to use the toolbar. """
+
+# Some checking to see if we can draw shadows behind the popup menus
+# at least on Windows. *REQUIRES* Mark Hammond's win32all extensions
+# and ctypes, on Windows obviouly. Mac and GTK have no shadows under
+# the menus, and it has been reported that shadows don't work well
+# on Windows 2000 and previous.
+
+_libimported = None
+_DELAY = 5000
+
+# Define a translation string
+_ = wx.GetTranslation
+
+if wx.Platform == "__WXMSW__":
+ osVersion = wx.GetOsVersion()
+ # Shadows behind menus are supported only in XP
+ if osVersion[1] == 5 and osVersion[2] == 1:
+ try:
+ import win32api
+ import win32gui
+ _libimported = "MH"
+ except:
+ try:
+ import ctypes
+ _libimported = "ctypes"
+ except:
+ pass
+ else:
+ _libimported = None
+
+# Simple hack, but I don't know how to make it work on Mac
+# I don't have Mac ;-)
+#if wx.Platform == "__WXMAC__":
+# try:
+# import ctypes
+# _carbon_dll = ctypes.cdll.LoadLibrary(r'/System/Frameworks/Carbon.framework/Carbon')
+# except:
+# _carbon_dll = None
+
+
+# FIXME: No way to get shadows on Windows with the original code...
+# May anyone share some suggestion on how to make it work??
+# Right now I am using win32api to create shadows behind wx.PopupWindow,
+# but this will result in *all* the popup windows in an application
+# to have shadows behind them, even the user defined wx.PopupWindow
+# that do not derive from FlatMenu.
+
+import wx.aui as AUI
+AuiPaneInfo = AUI.AuiPaneInfo
+""" Default AuiPaneInfo as in :class:`~lib.agw.aui.AuiPaneInfo`. """
+
+try:
+ import aui as PyAUI
+ PyAuiPaneInfo = PyAUI.AuiPaneInfo
+ """ Default AuiPaneInfo as in :class:`framemanager`. """
+except ImportError:
+ pass
+
+# Check for the new method in 2.7 (not present in 2.6.3.3)
+if wx.VERSION_STRING < "2.7":
+ wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point)
+
+
+wxEVT_FLAT_MENU_DISMISSED = wx.NewEventType()
+wxEVT_FLAT_MENU_SELECTED = wx.wxEVT_COMMAND_MENU_SELECTED
+wxEVT_FLAT_MENU_ITEM_MOUSE_OVER = wx.NewEventType()
+wxEVT_FLAT_MENU_ITEM_MOUSE_OUT = wx.NewEventType()
+
+EVT_FLAT_MENU_DISMISSED = wx.PyEventBinder(wxEVT_FLAT_MENU_DISMISSED, 1)
+""" Used internally. """
+EVT_FLAT_MENU_SELECTED = wx.PyEventBinder(wxEVT_FLAT_MENU_SELECTED, 2)
+""" Fires the wx.EVT_MENU event for :class:`FlatMenu`. """
+EVT_FLAT_MENU_RANGE = wx.PyEventBinder(wxEVT_FLAT_MENU_SELECTED, 2)
+""" Fires the wx.EVT_MENU event for a series of :class:`FlatMenu`. """
+EVT_FLAT_MENU_ITEM_MOUSE_OUT = wx.PyEventBinder(wxEVT_FLAT_MENU_ITEM_MOUSE_OUT, 1)
+""" Fires an event when the mouse leaves a :class:`FlatMenuItem`. """
+EVT_FLAT_MENU_ITEM_MOUSE_OVER = wx.PyEventBinder(wxEVT_FLAT_MENU_ITEM_MOUSE_OVER, 1)
+""" Fires an event when the mouse enters a :class:`FlatMenuItem`. """
+
+
+def GetAccelIndex(label):
+ """
+ Returns the mnemonic index of the label and the label stripped of the ampersand mnemonic
+ (e.g. 'lab&el' ==> will result in 3 and labelOnly = label).
+
+ :param string `label`: a string possibly containining an ampersand.
+ """
+
+ indexAccel = 0
+ while True:
+ indexAccel = label.find("&", indexAccel)
+ if indexAccel == -1:
+ return indexAccel, label
+ if label[indexAccel:indexAccel+2] == "&&":
+ label = label[0:indexAccel] + label[indexAccel+1:]
+ indexAccel += 1
+ else:
+ break
+
+ labelOnly = label[0:indexAccel] + label[indexAccel+1:]
+
+ return indexAccel, labelOnly
+
+
+def ConvertToMonochrome(bmp):
+ """
+ Converts a bitmap to monochrome colour.
+
+ :param `bmp`: a valid :class:`Bitmap` object.
+ """
+
+ mem_dc = wx.MemoryDC()
+ shadow = wx.EmptyBitmap(bmp.GetWidth(), bmp.GetHeight())
+ mem_dc.SelectObject(shadow)
+ mem_dc.DrawBitmap(bmp, 0, 0, True)
+ mem_dc.SelectObject(wx.NullBitmap)
+ img = shadow.ConvertToImage()
+ img = img.ConvertToMono(0, 0, 0)
+
+ # we now have black where the original bmp was drawn,
+ # white elsewhere
+ shadow = wx.BitmapFromImage(img)
+ shadow.SetMask(wx.Mask(shadow, wx.BLACK))
+
+ # Convert the black to grey
+ tmp = wx.EmptyBitmap(bmp.GetWidth(), bmp.GetHeight())
+ col = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+ mem_dc.SelectObject(tmp)
+ mem_dc.SetPen(wx.Pen(col))
+ mem_dc.SetBrush(wx.Brush(col))
+ mem_dc.DrawRectangle(0, 0, bmp.GetWidth(), bmp.GetHeight())
+ mem_dc.DrawBitmap(shadow, 0, 0, True) # now contains a bitmap with grey where the image was, white elsewhere
+ mem_dc.SelectObject(wx.NullBitmap)
+ shadow = tmp
+ shadow.SetMask(wx.Mask(shadow, wx.WHITE))
+
+ return shadow
+
+
+# ---------------------------------------------------------------------------- #
+# Class FMRendererMgr
+# ---------------------------------------------------------------------------- #
+
+class FMRendererMgr(object):
+ """
+ This class represents a manager that handles all the renderers defined.
+ Every instance of this class will share the same state, so everyone can
+ instantiate their own and a call to :meth:`FMRendererMgr.SetTheme() <flatmenu.FMRendererMgr.SetTheme>` anywhere will affect everyone.
+ """
+
+ def __new__(cls, *p, **k):
+ if not '_instance' in cls.__dict__:
+ cls._instance = object.__new__(cls)
+ return cls._instance
+
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ # If we have already initialized don't do it again. There is only one
+ # FMRendererMgr process-wide.
+
+ if hasattr(self, '_alreadyInitialized'):
+ return
+
+ self._alreadyInitialized = True
+
+ self._currentTheme = StyleDefault
+ self._renderers = []
+ self._renderers.append(FMRenderer())
+ self._renderers.append(FMRendererXP())
+ self._renderers.append(FMRendererMSOffice2007())
+ self._renderers.append(FMRendererVista())
+
+
+ def GetRenderer(self):
+ """ Returns the current theme's renderer. """
+
+ return self._renderers[self._currentTheme]
+
+
+ def AddRenderer(self, renderer):
+ """
+ Adds a user defined custom renderer.
+
+ :param `renderer`: a class derived from :class:`FMRenderer`.
+ """
+
+ lastRenderer = len(self._renderers)
+ self._renderers.append(renderer)
+
+ return lastRenderer
+
+
+ def SetTheme(self, theme):
+ """
+ Sets the current theme.
+
+ :param `theme`: an integer specifying the theme to use.
+ """
+
+ if theme < 0 or theme > len(self._renderers):
+ raise ValueError("Error invalid theme specified.")
+
+ self._currentTheme = theme
+
+
+# ---------------------------------------------------------------------------- #
+# Class FMRenderer
+# ---------------------------------------------------------------------------- #
+
+class FMRenderer(object):
+ """
+ Base class for the :class:`FlatMenu` renderers. This class implements the common
+ methods of all the renderers.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ self.separatorHeight = 5
+ self.drawLeftMargin = False
+ self.highlightCheckAndRadio = False
+ self.scrollBarButtons = False # Display scrollbar buttons if the menu doesn't fit on the screen
+ # otherwise default to up and down arrow menu items
+
+ self.itemTextColourDisabled = ArtManager.Get().LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT), 30)
+
+ # Background Colours
+ self.menuFaceColour = wx.WHITE
+ self.menuBarFaceColour = ArtManager.Get().LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 80)
+
+ self.menuBarFocusFaceColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.menuBarFocusBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.menuBarPressedFaceColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.menuBarPressedBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+
+ self.menuFocusFaceColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.menuFocusBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.menuPressedFaceColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.menuPressedBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+
+ self.buttonFaceColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.buttonBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.buttonFocusFaceColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.buttonFocusBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.buttonPressedFaceColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.buttonPressedBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+
+ # create wxBitmaps from the xpm's
+ self._rightBottomCorner = self.ConvertToBitmap(shadow_center_xpm, shadow_center_alpha)
+ self._bottom = self.ConvertToBitmap(shadow_bottom_xpm, shadow_bottom_alpha)
+ self._bottomLeft = self.ConvertToBitmap(shadow_bottom_left_xpm, shadow_bottom_left_alpha)
+ self._rightTop = self.ConvertToBitmap(shadow_right_top_xpm, shadow_right_top_alpha)
+ self._right = self.ConvertToBitmap(shadow_right_xpm, shadow_right_alpha)
+
+ self._bitmaps = {}
+ bmp = self.ConvertToBitmap(arrow_down, alpha=None)
+ bmp.SetMask(wx.Mask(bmp, wx.Colour(0, 128, 128)))
+ self._bitmaps.update({"arrow_down": bmp})
+
+ bmp = self.ConvertToBitmap(arrow_up, alpha=None)
+ bmp.SetMask(wx.Mask(bmp, wx.Colour(0, 128, 128)))
+ self._bitmaps.update({"arrow_up": bmp})
+
+ self._toolbarSeparatorBitmap = wx.NullBitmap
+ self.raiseToolbar = False
+
+
+ def SetMenuBarHighlightColour(self, colour):
+ """
+ Set the colour to highlight focus on the menu bar.
+
+ :param `colour`: a valid instance of :class:`Colour`.
+ """
+
+ self.menuBarFocusFaceColour = colour
+ self.menuBarFocusBorderColour = colour
+ self.menuBarPressedFaceColour = colour
+ self.menuBarPressedBorderColour= colour
+
+
+ def SetMenuHighlightColour(self,colour):
+ """
+ Set the colour to highlight focus on the menu.
+
+ :param `colour`: a valid instance of :class:`Colour`.
+ """
+
+ self.menuFocusFaceColour = colour
+ self.menuFocusBorderColour = colour
+ self.menuPressedFaceColour = colour
+ self.menuPressedBorderColour = colour
+
+
+ def GetColoursAccordingToState(self, state):
+ """
+ Returns a :class:`Colour` according to the menu item state.
+
+ :param integer `state`: one of the following bits:
+
+ ==================== ======= ==========================
+ Item State Value Description
+ ==================== ======= ==========================
+ ``ControlPressed`` 0 The item is pressed
+ ``ControlFocus`` 1 The item is focused
+ ``ControlDisabled`` 2 The item is disabled
+ ``ControlNormal`` 3 Normal state
+ ==================== ======= ==========================
+
+ """
+
+ # switch according to the status
+ if state == ControlFocus:
+ upperBoxTopPercent = 95
+ upperBoxBottomPercent = 50
+ lowerBoxTopPercent = 40
+ lowerBoxBottomPercent = 90
+ concaveUpperBox = True
+ concaveLowerBox = True
+
+ elif state == ControlPressed:
+ upperBoxTopPercent = 75
+ upperBoxBottomPercent = 90
+ lowerBoxTopPercent = 90
+ lowerBoxBottomPercent = 40
+ concaveUpperBox = True
+ concaveLowerBox = True
+
+ elif state == ControlDisabled:
+ upperBoxTopPercent = 100
+ upperBoxBottomPercent = 100
+ lowerBoxTopPercent = 70
+ lowerBoxBottomPercent = 70
+ concaveUpperBox = True
+ concaveLowerBox = True
+
+ else:
+ upperBoxTopPercent = 90
+ upperBoxBottomPercent = 50
+ lowerBoxTopPercent = 30
+ lowerBoxBottomPercent = 75
+ concaveUpperBox = True
+ concaveLowerBox = True
+
+ return upperBoxTopPercent, upperBoxBottomPercent, lowerBoxTopPercent, lowerBoxBottomPercent, \
+ concaveUpperBox, concaveLowerBox
+
+
+ def ConvertToBitmap(self, xpm, alpha=None):
+ """
+ Convert the given image to a bitmap, optionally overlaying an alpha
+ channel to it.
+
+ :param `xpm`: a list of strings formatted as XPM;
+ :param `alpha`: a list of alpha values, the same size as the xpm bitmap.
+ """
+
+ if alpha is not None:
+
+ img = wx.BitmapFromXPMData(xpm)
+ img = img.ConvertToImage()
+ x, y = img.GetWidth(), img.GetHeight()
+ img.InitAlpha()
+ for jj in xrange(y):
+ for ii in xrange(x):
+ img.SetAlpha(ii, jj, alpha[jj*x+ii])
+
+ else:
+
+ stream = cStringIO.StringIO(xpm)
+ img = wx.ImageFromStream(stream)
+
+ return wx.BitmapFromImage(img)
+
+
+ def DrawLeftMargin(self, item, dc, menuRect):
+ """
+ Draws the menu left margin.
+
+ :param `item`: an instance of :class:`FlatMenuItem`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `menuRect`: an instance of :class:`Rect`, representing the menu client rectangle.
+ """
+
+ raise Exception("This style doesn't support Drawing a Left Margin")
+
+
+ def DrawToolbarSeparator(self, dc, rect):
+ """
+ Draws a separator inside the toolbar in :class:`FlatMenuBar`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the bitmap client rectangle.
+ """
+
+ # Place a separator bitmap
+ bmp = wx.EmptyBitmap(rect.width, rect.height)
+ mem_dc = wx.MemoryDC()
+ mem_dc.SelectObject(bmp)
+ mem_dc.SetPen(wx.BLACK_PEN)
+ mem_dc.SetBrush(wx.BLACK_BRUSH)
+
+ mem_dc.DrawRectangle(0, 0, bmp.GetWidth(), bmp.GetHeight())
+
+ col = self.menuBarFaceColour
+ col1 = ArtManager.Get().LightColour(col, 40)
+ col2 = ArtManager.Get().LightColour(col, 70)
+
+ mem_dc.SetPen(wx.Pen(col2))
+ mem_dc.DrawLine(5, 0, 5, bmp.GetHeight())
+
+ mem_dc.SetPen(wx.Pen(col1))
+ mem_dc.DrawLine(6, 0, 6, bmp.GetHeight())
+
+ mem_dc.SelectObject(wx.NullBitmap)
+ bmp.SetMask(wx.Mask(bmp, wx.BLACK))
+
+ dc.DrawBitmap(bmp, rect.x, rect.y, True)
+
+
+ # assumption: the background was already drawn on the dc
+ def DrawBitmapShadow(self, dc, rect, where=BottomShadow|RightShadow):
+ """
+ Draws a shadow using background bitmap.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the bitmap client rectangle;
+ :param integer `where`: where to draw the shadow. This can be any combination of the
+ following bits:
+
+ ========================== ======= ================================
+ Shadow Settings Value Description
+ ========================== ======= ================================
+ ``RightShadow`` 1 Right side shadow
+ ``BottomShadow`` 2 Not full bottom shadow
+ ``BottomShadowFull`` 4 Full bottom shadow
+ ========================== ======= ================================
+
+ """
+
+ shadowSize = 5
+
+ # the rect must be at least 5x5 pixles
+ if rect.height < 2*shadowSize or rect.width < 2*shadowSize:
+ return
+
+ # Start by drawing the right bottom corner
+ if where & BottomShadow or where & BottomShadowFull:
+ dc.DrawBitmap(self._rightBottomCorner, rect.x+rect.width, rect.y+rect.height, True)
+
+ # Draw right side shadow
+ xx = rect.x + rect.width
+ yy = rect.y + rect.height - shadowSize
+
+ if where & RightShadow:
+ while yy - rect.y > 2*shadowSize:
+ dc.DrawBitmap(self._right, xx, yy, True)
+ yy -= shadowSize
+
+ dc.DrawBitmap(self._rightTop, xx, yy - shadowSize, True)
+
+ if where & BottomShadow:
+ xx = rect.x + rect.width - shadowSize
+ yy = rect.height + rect.y
+ while xx - rect.x > 2*shadowSize:
+ dc.DrawBitmap(self._bottom, xx, yy, True)
+ xx -= shadowSize
+
+ dc.DrawBitmap(self._bottomLeft, xx - shadowSize, yy, True)
+
+ if where & BottomShadowFull:
+ xx = rect.x + rect.width - shadowSize
+ yy = rect.height + rect.y
+ while xx - rect.x >= 0:
+ dc.DrawBitmap(self._bottom, xx, yy, True)
+ xx -= shadowSize
+
+ dc.DrawBitmap(self._bottom, xx, yy, True)
+
+
+ def DrawToolBarBg(self, dc, rect):
+ """
+ Draws the toolbar background
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the toolbar client rectangle.
+ """
+
+ if not self.raiseToolbar:
+ return
+
+ dcsaver = DCSaver(dc)
+
+ # fill with gradient
+ colour = self.menuBarFaceColour
+
+ dc.SetPen(wx.Pen(colour))
+ dc.SetBrush(wx.Brush(colour))
+
+ dc.DrawRectangleRect(rect)
+ self.DrawBitmapShadow(dc, rect)
+
+
+ def DrawSeparator(self, dc, xCoord, yCoord, textX, sepWidth):
+ """
+ Draws a separator inside a :class:`FlatMenu`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param integer `xCoord`: the current x position where to draw the separator;
+ :param integer `yCoord`: the current y position where to draw the separator;
+ :param integer `textX`: the menu item label x position;
+ :param integer `sepWidth`: the width of the separator, in pixels.
+ """
+
+ dcsaver = DCSaver(dc)
+ sepRect1 = wx.Rect(xCoord + textX, yCoord + 1, sepWidth/2, 1)
+ sepRect2 = wx.Rect(xCoord + textX + sepWidth/2, yCoord + 1, sepWidth/2-1, 1)
+
+ artMgr = ArtManager.Get()
+ backColour = artMgr.GetMenuFaceColour()
+ lightColour = wx.NamedColour("LIGHT GREY")
+
+ artMgr.PaintStraightGradientBox(dc, sepRect1, backColour, lightColour, False)
+ artMgr.PaintStraightGradientBox(dc, sepRect2, lightColour, backColour, False)
+
+
+ def DrawMenuItem(self, item, dc, xCoord, yCoord, imageMarginX, markerMarginX, textX, rightMarginX, selected=False, backgroundImage=None):
+ """
+ Draws the menu item.
+
+ :param `item`: a :class:`FlatMenuItem` instance;
+ :param `dc`: an instance of :class:`DC`;
+ :param integer `xCoord`: the current x position where to draw the menu;
+ :param integer `yCoord`: the current y position where to draw the menu;
+ :param integer `imageMarginX`: the spacing between the image and the menu border;
+ :param integer `markerMarginX`: the spacing between the checkbox/radio marker and
+ the menu border;
+ :param integer `textX`: the menu item label x position;
+ :param integer `rightMarginX`: the right margin between the text and the menu border;
+ :param bool `selected`: ``True`` if this menu item is currentl hovered by the mouse,
+ ``False`` otherwise.
+ :param `backgroundImage`: if not ``None``, an instance of :class:`Bitmap` which will
+ become the background image for this :class:`FlatMenu`.
+ """
+
+ borderXSize = item._parentMenu.GetBorderXWidth()
+ itemHeight = item._parentMenu.GetItemHeight()
+ menuWidth = item._parentMenu.GetMenuWidth()
+
+ # Define the item actual rectangle area
+ itemRect = wx.Rect(xCoord, yCoord, menuWidth, itemHeight)
+
+ # Define the drawing area
+ rect = wx.Rect(xCoord+2, yCoord, menuWidth - 4, itemHeight)
+
+ # Draw the background
+ backColour = self.menuFaceColour
+ penColour = backColour
+ backBrush = wx.Brush(backColour)
+ leftMarginWidth = item._parentMenu.GetLeftMarginWidth()
+
+ if backgroundImage is None:
+ pen = wx.Pen(penColour)
+ dc.SetPen(pen)
+ dc.SetBrush(backBrush)
+ dc.DrawRectangleRect(rect)
+
+ # Draw the left margin gradient
+ if self.drawLeftMargin:
+ self.DrawLeftMargin(item, dc, itemRect)
+
+ # check if separator
+ if item.IsSeparator():
+ # Separator is a small grey line separating between menu items.
+ sepWidth = xCoord + menuWidth - textX - 1
+ self.DrawSeparator(dc, xCoord, yCoord, textX, sepWidth)
+ return
+
+ # Keep the item rect
+ item._rect = itemRect
+
+ # Get the bitmap base on the item state (disabled, selected ..)
+ bmp = item.GetSuitableBitmap(selected)
+
+ # First we draw the selection rectangle
+ if selected:
+ self.DrawMenuButton(dc, rect.Deflate(1,0), ControlFocus)
+ #copy.Inflate(0, menubar._spacer)
+
+ if bmp.Ok():
+
+ # Calculate the postion to place the image
+ imgHeight = bmp.GetHeight()
+ imgWidth = bmp.GetWidth()
+
+ if imageMarginX == 0:
+ xx = rect.x + (leftMarginWidth - imgWidth)/2
+ else:
+ xx = rect.x + ((leftMarginWidth - rect.height) - imgWidth)/2 + rect.height
+
+ yy = rect.y + (rect.height - imgHeight)/2
+ dc.DrawBitmap(bmp, xx, yy, True)
+
+ if item.GetKind() == wx.ITEM_CHECK:
+
+ # Checkable item
+ if item.IsChecked():
+
+ # Draw surrounding rectangle around the selection box
+ xx = rect.x + 1
+ yy = rect.y + 1
+ rr = wx.Rect(xx, yy, rect.height-2, rect.height-2)
+
+ if not selected and self.highlightCheckAndRadio:
+ self.DrawButton(dc, rr, ControlFocus)
+
+ dc.DrawBitmap(item._checkMarkBmp, rr.x + (rr.width - 16)/2, rr.y + (rr.height - 16)/2, True)
+
+ if item.GetKind() == wx.ITEM_RADIO:
+
+ # Checkable item
+ if item.IsChecked():
+
+ # Draw surrounding rectangle around the selection box
+ xx = rect.x + 1
+ yy = rect.y + 1
+ rr = wx.Rect(xx, yy, rect.height-2, rect.height-2)
+
+ if not selected and self.highlightCheckAndRadio:
+ self.DrawButton(dc, rr, ControlFocus)
+
+ dc.DrawBitmap(item._radioMarkBmp, rr.x + (rr.width - 16)/2, rr.y + (rr.height - 16)/2, True)
+
+ # Draw text - without accelerators
+ text = item.GetLabel()
+
+ if text:
+
+ font = item.GetFont()
+ if font is None:
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+ if selected:
+ enabledTxtColour = colourutils.BestLabelColour(self.menuFocusFaceColour, bw=True)
+ else:
+ enabledTxtColour = colourutils.BestLabelColour(self.menuFaceColour, bw=True)
+
+ disabledTxtColour = self.itemTextColourDisabled
+ textColour = (item.IsEnabled() and [enabledTxtColour] or [disabledTxtColour])[0]
+
+ if item.IsEnabled() and item.GetTextColour():
+ textColour = item.GetTextColour()
+
+ dc.SetFont(font)
+ w, h = dc.GetTextExtent(text)
+ dc.SetTextForeground(textColour)
+
+ if item._mnemonicIdx != wx.NOT_FOUND:
+
+ # We divide the drawing to 3 parts
+ text1 = text[0:item._mnemonicIdx]
+ text2 = text[item._mnemonicIdx]
+ text3 = text[item._mnemonicIdx+1:]
+
+ w1, dummy = dc.GetTextExtent(text1)
+ w2, dummy = dc.GetTextExtent(text2)
+ w3, dummy = dc.GetTextExtent(text3)
+
+ posx = xCoord + textX + borderXSize
+ posy = (itemHeight - h)/2 + yCoord
+
+ # Draw first part
+ dc.DrawText(text1, posx, posy)
+
+ # mnemonic
+ if "__WXGTK__" not in wx.Platform:
+ font.SetUnderlined(True)
+ dc.SetFont(font)
+
+ posx += w1
+ dc.DrawText(text2, posx, posy)
+
+ # last part
+ font.SetUnderlined(False)
+ dc.SetFont(font)
+ posx += w2
+ dc.DrawText(text3, posx, posy)
+
+ else:
+
+ w, h = dc.GetTextExtent(text)
+ dc.DrawText(text, xCoord + textX + borderXSize, (itemHeight - h)/2 + yCoord)
+
+
+ # Now draw accelerator
+ # Accelerators are aligned to the right
+ if item.GetAccelString():
+
+ accelWidth, accelHeight = dc.GetTextExtent(item.GetAccelString())
+ dc.DrawText(item.GetAccelString(), xCoord + rightMarginX - accelWidth, (itemHeight - accelHeight)/2 + yCoord)
+
+ # Check if this item has sub-menu - if it does, draw
+ # right arrow on the right margin
+ if item.GetSubMenu():
+
+ # Draw arrow
+ rightArrowBmp = wx.BitmapFromXPMData(menu_right_arrow_xpm)
+ rightArrowBmp.SetMask(wx.Mask(rightArrowBmp, wx.WHITE))
+
+ xx = xCoord + rightMarginX + borderXSize
+ rr = wx.Rect(xx, rect.y + 1, rect.height-2, rect.height-2)
+ dc.DrawBitmap(rightArrowBmp, rr.x + 4, rr.y +(rr.height-16)/2, True)
+
+
+ def DrawMenuBarButton(self, dc, rect, state):
+ """
+ Draws the highlight on a :class:`FlatMenuBar`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the button client rectangle;
+ :param integer `state`: the button state.
+ """
+
+ # switch according to the status
+ if state == ControlFocus:
+ penColour = self.menuBarFocusBorderColour
+ brushColour = self.menuBarFocusFaceColour
+ elif state == ControlPressed:
+ penColour = self.menuBarPressedBorderColour
+ brushColour = self.menuBarPressedFaceColour
+
+ dcsaver = DCSaver(dc)
+ dc.SetPen(wx.Pen(penColour))
+ dc.SetBrush(wx.Brush(brushColour))
+ dc.DrawRectangleRect(rect)
+
+
+ def DrawMenuButton(self, dc, rect, state):
+ """
+ Draws the highlight on a FlatMenu
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the button client rectangle;
+ :param integer `state`: the button state.
+ """
+
+ # switch according to the status
+ if state == ControlFocus:
+ penColour = self.menuFocusBorderColour
+ brushColour = self.menuFocusFaceColour
+ elif state == ControlPressed:
+ penColour = self.menuPressedBorderColour
+ brushColour = self.menuPressedFaceColour
+
+ dcsaver = DCSaver(dc)
+ dc.SetPen(wx.Pen(penColour))
+ dc.SetBrush(wx.Brush(brushColour))
+ dc.DrawRectangleRect(rect)
+
+
+ def DrawScrollButton(self, dc, rect, state):
+ """
+ Draws the scroll button
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the button client rectangle;
+ :param integer `state`: the button state.
+ """
+
+ if not self.scrollBarButtons:
+ return
+
+ colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ colour = ArtManager.Get().LightColour(colour, 30)
+
+ artMgr = ArtManager.Get()
+
+ # Keep old pen and brush
+ dcsaver = DCSaver(dc)
+
+ # Define the rounded rectangle base on the given rect
+ # we need an array of 9 points for it
+ baseColour = colour
+
+ # Define the middle points
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 2))
+ rightPt = wx.Point(rect.x + rect.width-1, rect.y + (rect.height / 2))
+
+ # Define the top region
+ top = wx.RectPP((rect.GetLeft(), rect.GetTop()), rightPt)
+ bottom = wx.RectPP(leftPt, (rect.GetRight(), rect.GetBottom()))
+
+ upperBoxTopPercent, upperBoxBottomPercent, lowerBoxTopPercent, lowerBoxBottomPercent, \
+ concaveUpperBox, concaveLowerBox = self.GetColoursAccordingToState(state)
+
+ topStartColour = artMgr.LightColour(baseColour, upperBoxTopPercent)
+ topEndColour = artMgr.LightColour(baseColour, upperBoxBottomPercent)
+ bottomStartColour = artMgr.LightColour(baseColour, lowerBoxTopPercent)
+ bottomEndColour = artMgr.LightColour(baseColour, lowerBoxBottomPercent)
+
+ artMgr.PaintStraightGradientBox(dc, top, topStartColour, topEndColour)
+ artMgr.PaintStraightGradientBox(dc, bottom, bottomStartColour, bottomEndColour)
+
+ rr = wx.Rect(rect.x, rect.y, rect.width, rect.height)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ frameColour = artMgr.LightColour(baseColour, 60)
+ dc.SetPen(wx.Pen(frameColour))
+ dc.DrawRectangleRect(rr)
+
+ wc = artMgr.LightColour(baseColour, 80)
+ dc.SetPen(wx.Pen(wc))
+ rr.Deflate(1, 1)
+ dc.DrawRectangleRect(rr)
+
+
+ def DrawButton(self, dc, rect, state, colour=None):
+ """
+ Draws a button.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the button client rectangle;
+ :param integer `state`: the button state;
+ :param `colour`: if not ``None``, an instance of :class:`Colour` to be used to draw
+ the :class:`FlatMenuItem` background.
+ """
+
+ # switch according to the status
+ if state == ControlFocus:
+ if colour == None:
+ penColour = self.buttonFocusBorderColour
+ brushColour = self.buttonFocusFaceColour
+ else:
+ penColour = colour
+ brushColour = ArtManager.Get().LightColour(colour, 75)
+
+ elif state == ControlPressed:
+ if colour == None:
+ penColour = self.buttonPressedBorderColour
+ brushColour = self.buttonPressedFaceColour
+ else:
+ penColour = colour
+ brushColour = ArtManager.Get().LightColour(colour, 60)
+ else:
+ if colour == None:
+ penColour = self.buttonBorderColour
+ brushColour = self.buttonFaceColour
+ else:
+ penColour = colour
+ brushColour = ArtManager.Get().LightColour(colour, 75)
+
+ dcsaver = DCSaver(dc)
+ dc.SetPen(wx.Pen(penColour))
+ dc.SetBrush(wx.Brush(brushColour))
+ dc.DrawRectangleRect(rect)
+
+
+ def DrawMenuBarBackground(self, dc, rect):
+ """
+ Draws the menu bar background colour according to the menubar.GetBackgroundColour
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the menubar client rectangle.
+ """
+
+ dcsaver = DCSaver(dc)
+
+ # fill with gradient
+ colour = self.menuBarFaceColour
+
+ dc.SetPen(wx.Pen(colour))
+ dc.SetBrush(wx.Brush(colour))
+ dc.DrawRectangleRect(rect)
+
+
+ def DrawMenuBar(self, menubar, dc):
+ """
+ Draws everything for :class:`FlatMenuBar`.
+
+ :param `menubar`: an instance of :class:`FlatMenuBar`.
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ #artMgr = ArtManager.Get()
+ fnt = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ textColour = colourutils.BestLabelColour(menubar.GetBackgroundColour(), bw=True)
+ highlightTextColour = colourutils.BestLabelColour(self.menuBarFocusFaceColour, bw=True)
+
+ dc.SetFont(fnt)
+ dc.SetTextForeground(textColour)
+
+ clientRect = menubar.GetClientRect()
+
+ self.DrawMenuBarBackground(dc, clientRect)
+
+ padding, dummy = dc.GetTextExtent("W")
+
+ posx = 0
+ posy = menubar._margin
+
+ # ---------------------------------------------------------------------------
+ # Draw as much items as we can if the screen is not wide enough, add all
+ # missing items to a drop down menu
+ # ---------------------------------------------------------------------------
+ menuBarRect = menubar.GetClientRect()
+
+ # mark all items as non-visibles at first
+ for item in menubar._items:
+ item.SetRect(wx.Rect())
+
+ for item in menubar._items:
+
+ # Handle accelerator ('&')
+ title = item.GetTitle()
+
+ fixedText = title
+ location, labelOnly = GetAccelIndex(fixedText)
+
+ # Get the menu item rect
+ textWidth, textHeight = dc.GetTextExtent(fixedText)
+ #rect = wx.Rect(posx+menubar._spacer/2, posy, textWidth, textHeight)
+ rect = wx.Rect(posx+padding/2, posy, textWidth, textHeight)
+
+ # Can we draw more??
+ # the +DROP_DOWN_ARROW_WIDTH is the width of the drop down arrow
+ if posx + rect.width + DROP_DOWN_ARROW_WIDTH >= menuBarRect.width:
+ break
+
+ # In this style the button highlight includes the menubar margin
+ button_rect = wx.Rect(*rect)
+ button_rect.height = menubar._menuBarHeight
+ #button_rect.width = rect.width + menubar._spacer
+ button_rect.width = rect.width + padding
+ button_rect.x = posx
+ button_rect.y = 0
+
+ # Keep the item rectangle, will be used later in functions such
+ # as 'OnLeftDown', 'OnMouseMove'
+ copy = wx.Rect(*button_rect)
+ #copy.Inflate(0, menubar._spacer)
+ item.SetRect(copy)
+
+ selected = False
+ if item.GetState() == ControlFocus:
+ self.DrawMenuBarButton(dc, button_rect, ControlFocus)
+ dc.SetTextForeground(highlightTextColour)
+ selected = True
+ else:
+ dc.SetTextForeground(textColour)
+
+ ww, hh = dc.GetTextExtent(labelOnly)
+ textOffset = (rect.width - ww) / 2
+
+ if not menubar._isLCD and item.GetTextBitmap().Ok() and not selected:
+ dc.DrawBitmap(item.GetTextBitmap(), rect.x, rect.y, True)
+ elif not menubar._isLCD and item.GetSelectedTextBitmap().Ok() and selected:
+ dc.DrawBitmap(item.GetSelectedTextBitmap(), rect.x, rect.y, True)
+ else:
+ if not menubar._isLCD:
+ # Draw the text on a bitmap using memory dc,
+ # so on following calls we will use this bitmap instead
+ # of calculating everything from scratch
+ bmp = wx.EmptyBitmap(rect.width, rect.height)
+ memDc = wx.MemoryDC()
+ memDc.SelectObject(bmp)
+ if selected:
+ memDc.SetTextForeground(highlightTextColour)
+ else:
+ memDc.SetTextForeground(textColour)
+
+ # Fill the bitmap with the masking colour
+ memDc.SetPen(wx.Pen(wx.Colour(255, 0, 0)) )
+ memDc.SetBrush(wx.Brush(wx.Colour(255, 0, 0)) )
+ memDc.DrawRectangle(0, 0, rect.width, rect.height)
+ memDc.SetFont(fnt)
+
+ if location == wx.NOT_FOUND or location >= len(fixedText):
+ # draw the text
+ if not menubar._isLCD:
+ memDc.DrawText(title, textOffset, 0)
+ dc.DrawText(title, rect.x + textOffset, rect.y)
+
+ else:
+
+ # underline the first '&'
+ before = labelOnly[0:location]
+ underlineLetter = labelOnly[location]
+ after = labelOnly[location+1:]
+
+ # before
+ if not menubar._isLCD:
+ memDc.DrawText(before, textOffset, 0)
+ dc.DrawText(before, rect.x + textOffset, rect.y)
+
+ # underlineLetter
+ if "__WXGTK__" not in wx.Platform:
+ w1, h = dc.GetTextExtent(before)
+ fnt.SetUnderlined(True)
+ dc.SetFont(fnt)
+ dc.DrawText(underlineLetter, rect.x + w1 + textOffset, rect.y)
+ if not menubar._isLCD:
+ memDc.SetFont(fnt)
+ memDc.DrawText(underlineLetter, textOffset + w1, 0)
+
+ else:
+ w1, h = dc.GetTextExtent(before)
+ dc.DrawText(underlineLetter, rect.x + w1 + textOffset, rect.y)
+ if not menubar._isLCD:
+ memDc.DrawText(underlineLetter, textOffset + w1, 0)
+
+ # Draw the underline ourselves since using the Underline in GTK,
+ # causes the line to be too close to the letter
+
+ uderlineLetterW, uderlineLetterH = dc.GetTextExtent(underlineLetter)
+ dc.DrawLine(rect.x + w1 + textOffset, rect.y + uderlineLetterH - 2,
+ rect.x + w1 + textOffset + uderlineLetterW, rect.y + uderlineLetterH - 2)
+
+ # after
+ w2, h = dc.GetTextExtent(underlineLetter)
+ fnt.SetUnderlined(False)
+ dc.SetFont(fnt)
+ dc.DrawText(after, rect.x + w1 + w2 + textOffset, rect.y)
+ if not menubar._isLCD:
+ memDc.SetFont(fnt)
+ memDc.DrawText(after, w1 + w2 + textOffset, 0)
+
+ if not menubar._isLCD:
+ memDc.SelectObject(wx.NullBitmap)
+ # Set masking colour to the bitmap
+ bmp.SetMask(wx.Mask(bmp, wx.Colour(255, 0, 0)))
+ if selected:
+ item.SetSelectedTextBitmap(bmp)
+ else:
+ item.SetTextBitmap(bmp)
+
+ posx += rect.width + padding # + menubar._spacer
+
+ # Get a background image of the more menu button
+ moreMenubtnBgBmpRect = wx.Rect(*menubar.GetMoreMenuButtonRect())
+ if not menubar._moreMenuBgBmp:
+ menubar._moreMenuBgBmp = wx.EmptyBitmap(moreMenubtnBgBmpRect.width, moreMenubtnBgBmpRect.height)
+
+ if menubar._showToolbar and len(menubar._tbButtons) > 0:
+ rectX = 0
+ rectWidth = clientRect.width - moreMenubtnBgBmpRect.width
+ if len(menubar._items) == 0:
+ rectHeight = clientRect.height
+ rectY = 0
+ else:
+ rectHeight = clientRect.height - menubar._menuBarHeight
+ rectY = menubar._menuBarHeight
+ rr = wx.Rect(rectX, rectY, rectWidth, rectHeight)
+ self.DrawToolBarBg(dc, rr)
+ menubar.DrawToolbar(dc, rr)
+
+ if menubar._showCustomize or menubar.GetInvisibleMenuItemCount() > 0 or menubar.GetInvisibleToolbarItemCount() > 0:
+ memDc = wx.MemoryDC()
+ memDc.SelectObject(menubar._moreMenuBgBmp)
+ try:
+ memDc.Blit(0, 0, menubar._moreMenuBgBmp.GetWidth(), menubar._moreMenuBgBmp.GetHeight(), dc,
+ moreMenubtnBgBmpRect.x, moreMenubtnBgBmpRect.y)
+ except:
+ pass
+ memDc.SelectObject(wx.NullBitmap)
+
+ # Draw the drop down arrow button
+ menubar.DrawMoreButton(dc, menubar._dropDownButtonState)
+ # Set the button rect
+ menubar._dropDownButtonArea = moreMenubtnBgBmpRect
+
+
+ def DrawMenu(self, flatmenu, dc):
+ """
+ Draws the menu.
+
+ :param `flatmenu`: the :class:`FlatMenu` instance we need to paint;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ menuRect = flatmenu.GetClientRect()
+ menuBmp = wx.EmptyBitmap(menuRect.width, menuRect.height)
+
+ mem_dc = wx.MemoryDC()
+ mem_dc.SelectObject(menuBmp)
+
+ # colour the menu face with background colour
+ backColour = self.menuFaceColour
+ penColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+
+ backBrush = wx.Brush(backColour)
+ pen = wx.Pen(penColour)
+
+ mem_dc.SetPen(pen)
+ mem_dc.SetBrush(backBrush)
+ mem_dc.DrawRectangleRect(menuRect)
+
+ backgroundImage = flatmenu._backgroundImage
+
+ if backgroundImage:
+ mem_dc.DrawBitmap(backgroundImage, flatmenu._leftMarginWidth, 0, True)
+
+ # draw items
+ posy = 3
+ nItems = len(flatmenu._itemsArr)
+
+ # make all items as non-visible first
+ for item in flatmenu._itemsArr:
+ item.Show(False)
+
+ visibleItems = 0
+ screenHeight = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_Y)
+
+ numCols = flatmenu.GetNumberColumns()
+ switch, posx, index = 1e6, 0, 0
+ if numCols > 1:
+ switch = int(math.ceil((nItems - flatmenu._first)/float(numCols)))
+
+ # If we have to scroll and are not using the scroll bar buttons we need to draw
+ # the scroll up menu item at the top.
+ if not self.scrollBarButtons and flatmenu._showScrollButtons:
+ posy += flatmenu.GetItemHeight()
+
+ for nCount in xrange(flatmenu._first, nItems):
+
+ visibleItems += 1
+ item = flatmenu._itemsArr[nCount]
+ self.DrawMenuItem(item, mem_dc, posx, posy,
+ flatmenu._imgMarginX, flatmenu._markerMarginX,
+ flatmenu._textX, flatmenu._rightMarginPosX,
+ nCount == flatmenu._selectedItem,
+ backgroundImage=backgroundImage)
+ posy += item.GetHeight()
+ item.Show()
+
+ if visibleItems >= switch:
+ posy = 2
+ index += 1
+ posx = flatmenu._menuWidth*index
+ visibleItems = 0
+
+ # make sure we draw only visible items
+ pp = flatmenu.ClientToScreen(wx.Point(0, posy))
+
+ menuBottom = (self.scrollBarButtons and [pp.y] or [pp.y + flatmenu.GetItemHeight()*2])[0]
+
+ if menuBottom > screenHeight:
+ break
+
+ if flatmenu._showScrollButtons:
+ if flatmenu._upButton:
+ flatmenu._upButton.Draw(mem_dc)
+ if flatmenu._downButton:
+ flatmenu._downButton.Draw(mem_dc)
+
+ dc.Blit(0, 0, menuBmp.GetWidth(), menuBmp.GetHeight(), mem_dc, 0, 0)
+
+
+# ---------------------------------------------------------------------------- #
+# Class FMRendererMSOffice2007
+# ---------------------------------------------------------------------------- #
+
+class FMRendererMSOffice2007(FMRenderer):
+ """ Windows Office 2007 style. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FMRenderer.__init__(self)
+
+ self.drawLeftMargin = True
+ self.separatorHeight = 3
+ self.highlightCheckAndRadio = True
+ self.scrollBarButtons = True # Display scrollbar buttons if the menu doesn't fit on the screen
+
+ self.menuBarFaceColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+
+ self.buttonBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.buttonFaceColour = ArtManager.Get().LightColour(self.buttonBorderColour, 75)
+ self.buttonFocusBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.buttonFocusFaceColour = ArtManager.Get().LightColour(self.buttonFocusBorderColour, 75)
+ self.buttonPressedBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.buttonPressedFaceColour = ArtManager.Get().LightColour(self.buttonPressedBorderColour, 60)
+
+ self.menuFocusBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.menuFocusFaceColour = ArtManager.Get().LightColour(self.buttonFocusBorderColour, 75)
+ self.menuPressedBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.menuPressedFaceColour = ArtManager.Get().LightColour(self.buttonPressedBorderColour, 60)
+
+ self.menuBarFocusBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.menuBarFocusFaceColour = ArtManager.Get().LightColour(self.buttonFocusBorderColour, 75)
+ self.menuBarPressedBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.menuBarPressedFaceColour = ArtManager.Get().LightColour(self.buttonPressedBorderColour, 60)
+
+
+ def DrawLeftMargin(self, item, dc, menuRect):
+ """
+ Draws the menu left margin.
+
+ :param `item`: the :class:`FlatMenuItem` to paint;
+ :param `dc`: an instance of :class:`DC`;
+ :param `menuRect`: an instance of :class:`Rect`, representing the menu client rectangle.
+ """
+
+ # Construct the margin rectangle
+ marginRect = wx.Rect(menuRect.x+1, menuRect.y, item._parentMenu.GetLeftMarginWidth(), menuRect.height)
+
+ # Set the gradient colours
+ artMgr = ArtManager.Get()
+ faceColour = self.menuFaceColour
+
+ dcsaver = DCSaver(dc)
+ marginColour = artMgr.DarkColour(faceColour, 5)
+ dc.SetPen(wx.Pen(marginColour))
+ dc.SetBrush(wx.Brush(marginColour))
+ dc.DrawRectangleRect(marginRect)
+
+ dc.SetPen(wx.WHITE_PEN)
+ dc.DrawLine(marginRect.x + marginRect.width, marginRect.y, marginRect.x + marginRect.width, marginRect.y + marginRect.height)
+
+ borderColour = artMgr.DarkColour(faceColour, 10)
+ dc.SetPen(wx.Pen(borderColour))
+ dc.DrawLine(marginRect.x + marginRect.width-1, marginRect.y, marginRect.x + marginRect.width-1, marginRect.y + marginRect.height)
+
+
+ def DrawMenuButton(self, dc, rect, state):
+ """
+ Draws the highlight on a :class:`FlatMenu`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the button client rectangle;
+ :param integer `state`: the button state.
+ """
+
+ self.DrawButton(dc, rect, state)
+
+
+ def DrawMenuBarButton(self, dc, rect, state):
+ """
+ Draws the highlight on a :class:`FlatMenuBar`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the button client rectangle;
+ :param integer `state`: the button state.
+ """
+
+ self.DrawButton(dc, rect, state)
+
+
+ def DrawButton(self, dc, rect, state, colour=None):
+ """
+ Draws a button using the Office 2007 theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the button client rectangle;
+ :param integer `state`: the button state;
+ :param `colour`: if not ``None``, an instance of :class:`Colour` to be used to draw
+ the :class:`FlatMenuItem` background.
+ """
+
+ colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ colour = ArtManager.Get().LightColour(colour, 30)
+ self.DrawButtonColour(dc, rect, state, colour)
+
+
+ def DrawButtonColour(self, dc, rect, state, colour):
+ """
+ Draws a button using the Office 2007 theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the button client rectangle;
+ :param integer `state`: the button state;
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ artMgr = ArtManager.Get()
+
+ # Keep old pen and brush
+ dcsaver = DCSaver(dc)
+
+ # Define the rounded rectangle base on the given rect
+ # we need an array of 9 points for it
+ baseColour = colour
+
+ # Define the middle points
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 2))
+ rightPt = wx.Point(rect.x + rect.width-1, rect.y + (rect.height / 2))
+
+ # Define the top region
+ top = wx.RectPP((rect.GetLeft(), rect.GetTop()), rightPt)
+ bottom = wx.RectPP(leftPt, (rect.GetRight(), rect.GetBottom()))
+
+ upperBoxTopPercent, upperBoxBottomPercent, lowerBoxTopPercent, lowerBoxBottomPercent, \
+ concaveUpperBox, concaveLowerBox = self.GetColoursAccordingToState(state)
+
+ topStartColour = artMgr.LightColour(baseColour, upperBoxTopPercent)
+ topEndColour = artMgr.LightColour(baseColour, upperBoxBottomPercent)
+ bottomStartColour = artMgr.LightColour(baseColour, lowerBoxTopPercent)
+ bottomEndColour = artMgr.LightColour(baseColour, lowerBoxBottomPercent)
+
+ artMgr.PaintStraightGradientBox(dc, top, topStartColour, topEndColour)
+ artMgr.PaintStraightGradientBox(dc, bottom, bottomStartColour, bottomEndColour)
+
+ rr = wx.Rect(rect.x, rect.y, rect.width, rect.height)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ frameColour = artMgr.LightColour(baseColour, 60)
+ dc.SetPen(wx.Pen(frameColour))
+ dc.DrawRectangleRect(rr)
+
+ wc = artMgr.LightColour(baseColour, 80)
+ dc.SetPen(wx.Pen(wc))
+ rr.Deflate(1, 1)
+ dc.DrawRectangleRect(rr)
+
+
+ def DrawMenuBarBackground(self, dc, rect):
+ """
+ Draws the menu bar background according to the active theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the menubar client rectangle.
+ """
+
+ # Keep old pen and brush
+ dcsaver = DCSaver(dc)
+ artMgr = ArtManager.Get()
+ baseColour = self.menuBarFaceColour
+
+ dc.SetBrush(wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.DrawRectangleRect(rect)
+
+ # Define the rounded rectangle base on the given rect
+ # we need an array of 9 points for it
+ regPts = [wx.Point() for ii in xrange(9)]
+ radius = 2
+
+ regPts[0] = wx.Point(rect.x, rect.y + radius)
+ regPts[1] = wx.Point(rect.x+radius, rect.y)
+ regPts[2] = wx.Point(rect.x+rect.width-radius-1, rect.y)
+ regPts[3] = wx.Point(rect.x+rect.width-1, rect.y + radius)
+ regPts[4] = wx.Point(rect.x+rect.width-1, rect.y + rect.height - radius - 1)
+ regPts[5] = wx.Point(rect.x+rect.width-radius-1, rect.y + rect.height-1)
+ regPts[6] = wx.Point(rect.x+radius, rect.y + rect.height-1)
+ regPts[7] = wx.Point(rect.x, rect.y + rect.height - radius - 1)
+ regPts[8] = regPts[0]
+
+ # Define the middle points
+
+ factor = artMgr.GetMenuBgFactor()
+
+ leftPt1 = wx.Point(rect.x, rect.y + (rect.height / factor))
+ leftPt2 = wx.Point(rect.x, rect.y + (rect.height / factor)*(factor-1))
+
+ rightPt1 = wx.Point(rect.x + rect.width, rect.y + (rect.height / factor))
+ rightPt2 = wx.Point(rect.x + rect.width, rect.y + (rect.height / factor)*(factor-1))
+
+ # Define the top region
+ topReg = [wx.Point() for ii in xrange(7)]
+ topReg[0] = regPts[0]
+ topReg[1] = regPts[1]
+ topReg[2] = wx.Point(regPts[2].x+1, regPts[2].y)
+ topReg[3] = wx.Point(regPts[3].x + 1, regPts[3].y)
+ topReg[4] = wx.Point(rightPt1.x, rightPt1.y+1)
+ topReg[5] = wx.Point(leftPt1.x, leftPt1.y+1)
+ topReg[6] = topReg[0]
+
+ # Define the middle region
+ middle = wx.RectPP(leftPt1, wx.Point(rightPt2.x - 2, rightPt2.y))
+
+ # Define the bottom region
+ bottom = wx.RectPP(leftPt2, wx.Point(rect.GetRight() - 1, rect.GetBottom()))
+
+ topStartColour = artMgr.LightColour(baseColour, 90)
+ topEndColour = artMgr.LightColour(baseColour, 60)
+ bottomStartColour = artMgr.LightColour(baseColour, 40)
+ bottomEndColour = artMgr.LightColour(baseColour, 20)
+
+ topRegion = wx.RegionFromPoints(topReg)
+
+ artMgr.PaintGradientRegion(dc, topRegion, topStartColour, topEndColour)
+ artMgr.PaintStraightGradientBox(dc, bottom, bottomStartColour, bottomEndColour)
+ artMgr.PaintStraightGradientBox(dc, middle, topEndColour, bottomStartColour)
+
+
+ def DrawToolBarBg(self, dc, rect):
+ """
+ Draws the toolbar background according to the active theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the toolbar client rectangle.
+ """
+
+ artMgr = ArtManager.Get()
+
+ if not artMgr.GetRaiseToolbar():
+ return
+
+ # Keep old pen and brush
+ dcsaver = DCSaver(dc)
+
+ baseColour = self.menuBarFaceColour
+ baseColour = artMgr.LightColour(baseColour, 20)
+
+ dc.SetBrush(wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.DrawRectangleRect(rect)
+
+ radius = 2
+
+ # Define the rounded rectangle base on the given rect
+ # we need an array of 9 points for it
+ regPts = [None]*9
+
+ regPts[0] = wx.Point(rect.x, rect.y + radius)
+ regPts[1] = wx.Point(rect.x+radius, rect.y)
+ regPts[2] = wx.Point(rect.x+rect.width-radius-1, rect.y)
+ regPts[3] = wx.Point(rect.x+rect.width-1, rect.y + radius)
+ regPts[4] = wx.Point(rect.x+rect.width-1, rect.y + rect.height - radius - 1)
+ regPts[5] = wx.Point(rect.x+rect.width-radius-1, rect.y + rect.height-1)
+ regPts[6] = wx.Point(rect.x+radius, rect.y + rect.height-1)
+ regPts[7] = wx.Point(rect.x, rect.y + rect.height - radius - 1)
+ regPts[8] = regPts[0]
+
+ # Define the middle points
+ factor = artMgr.GetMenuBgFactor()
+
+ leftPt1 = wx.Point(rect.x, rect.y + (rect.height / factor))
+ rightPt1 = wx.Point(rect.x + rect.width, rect.y + (rect.height / factor))
+
+ leftPt2 = wx.Point(rect.x, rect.y + (rect.height / factor)*(factor-1))
+ rightPt2 = wx.Point(rect.x + rect.width, rect.y + (rect.height / factor)*(factor-1))
+
+ # Define the top region
+ topReg = [None]*7
+ topReg[0] = regPts[0]
+ topReg[1] = regPts[1]
+ topReg[2] = wx.Point(regPts[2].x+1, regPts[2].y)
+ topReg[3] = wx.Point(regPts[3].x + 1, regPts[3].y)
+ topReg[4] = wx.Point(rightPt1.x, rightPt1.y+1)
+ topReg[5] = wx.Point(leftPt1.x, leftPt1.y+1)
+ topReg[6] = topReg[0]
+
+ # Define the middle region
+ middle = wx.RectPP(leftPt1, wx.Point(rightPt2.x - 2, rightPt2.y))
+
+ # Define the bottom region
+ bottom = wx.RectPP(leftPt2, wx.Point(rect.GetRight() - 1, rect.GetBottom()))
+
+ topStartColour = artMgr.LightColour(baseColour, 90)
+ topEndColour = artMgr.LightColour(baseColour, 60)
+ bottomStartColour = artMgr.LightColour(baseColour, 40)
+ bottomEndColour = artMgr.LightColour(baseColour, 20)
+
+ topRegion = wx.RegionFromPoints(topReg)
+
+ artMgr.PaintGradientRegion(dc, topRegion, topStartColour, topEndColour)
+ artMgr.PaintStraightGradientBox(dc, bottom, bottomStartColour, bottomEndColour)
+ artMgr.PaintStraightGradientBox(dc, middle, topEndColour, bottomStartColour)
+
+ artMgr.DrawBitmapShadow(dc, rect)
+
+
+ def GetTextColourEnable(self):
+ """ Returns the colour used for text colour when enabled. """
+
+ return wx.NamedColour("MIDNIGHT BLUE")
+
+
+# ---------------------------------------------------------------------------- #
+# Class FMRendererVista
+# ---------------------------------------------------------------------------- #
+
+class FMRendererVista(FMRendererMSOffice2007):
+ """ Windows Vista-like style. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FMRendererMSOffice2007.__init__(self)
+
+
+ def DrawButtonColour(self, dc, rect, state, colour):
+ """
+ Draws a button using the Vista theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the an instance of :class:`Rect`, representing the button client rectangle;
+ :param integer `state`: the button state;
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ artMgr = ArtManager.Get()
+
+ # Keep old pen and brush
+ dcsaver = DCSaver(dc)
+
+ outer = rgbSelectOuter
+ inner = rgbSelectInner
+ top = rgbSelectTop
+ bottom = rgbSelectBottom
+
+ bdrRect = wx.Rect(*rect)
+ filRect = wx.Rect(*rect)
+ filRect.Deflate(1,1)
+
+ r1, g1, b1 = int(top.Red()), int(top.Green()), int(top.Blue())
+ r2, g2, b2 = int(bottom.Red()), int(bottom.Green()), int(bottom.Blue())
+ dc.GradientFillLinear(filRect, top, bottom, wx.SOUTH)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(outer))
+ dc.DrawRoundedRectangleRect(bdrRect, 3)
+ bdrRect.Deflate(1, 1)
+ dc.SetPen(wx.Pen(inner))
+ dc.DrawRoundedRectangleRect(bdrRect, 2)
+
+
+# ---------------------------------------------------------------------------- #
+# Class FMRendererXP
+# ---------------------------------------------------------------------------- #
+
+class FMRendererXP(FMRenderer):
+ """ Xp-Style renderer. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FMRenderer.__init__(self)
+
+ self.drawLeftMargin = True
+ self.separatorHeight = 3
+ self.highlightCheckAndRadio = True
+ self.scrollBarButtons = True # Display scrollbar buttons if the menu doesn't fit on the screen
+
+ self.buttonBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.buttonFaceColour = ArtManager.Get().LightColour(self.buttonBorderColour, 75)
+ self.buttonFocusBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.buttonFocusFaceColour = ArtManager.Get().LightColour(self.buttonFocusBorderColour, 75)
+ self.buttonPressedBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.buttonPressedFaceColour = ArtManager.Get().LightColour(self.buttonPressedBorderColour, 60)
+
+ self.menuFocusBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.menuFocusFaceColour = ArtManager.Get().LightColour(self.buttonFocusBorderColour, 75)
+ self.menuPressedBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.menuPressedFaceColour = ArtManager.Get().LightColour(self.buttonPressedBorderColour, 60)
+
+ self.menuBarFocusBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.menuBarFocusFaceColour = ArtManager.Get().LightColour(self.buttonFocusBorderColour, 75)
+ self.menuBarPressedBorderColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self.menuBarPressedFaceColour = ArtManager.Get().LightColour(self.buttonPressedBorderColour, 60)
+
+
+ def DrawLeftMargin(self, item, dc, menuRect):
+ """
+ Draws the menu left margin.
+
+ :param `item`: the :class:`FlatMenuItem` to paint;
+ :param `dc`: an instance of :class:`DC`;
+ :param `menuRect`: an instance of :class:`Rect`, representing the menu client rectangle.
+ """
+
+ # Construct the margin rectangle
+ marginRect = wx.Rect(menuRect.x+1, menuRect.y, item._parentMenu.GetLeftMarginWidth(), menuRect.height)
+
+ # Set the gradient colours
+ artMgr = ArtManager.Get()
+ faceColour = self.menuFaceColour
+
+ startColour = artMgr.DarkColour(faceColour, 20)
+ endColour = faceColour
+ artMgr.PaintStraightGradientBox(dc, marginRect, startColour, endColour, False)
+
+
+ def DrawMenuBarBackground(self, dc, rect):
+ """
+ Draws the menu bar background according to the active theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the menubar client rectangle.
+ """
+
+ # For office style, we simple draw a rectangle with a gradient colouring
+ artMgr = ArtManager.Get()
+ vertical = artMgr.GetMBVerticalGradient()
+
+ dcsaver = DCSaver(dc)
+
+ # fill with gradient
+ startColour = artMgr.GetMenuBarFaceColour()
+ if artMgr.IsDark(startColour):
+ startColour = artMgr.LightColour(startColour, 50)
+
+ endColour = artMgr.LightColour(startColour, 90)
+ artMgr.PaintStraightGradientBox(dc, rect, startColour, endColour, vertical)
+
+ # Draw the border
+ if artMgr.GetMenuBarBorder():
+
+ dc.SetPen(wx.Pen(startColour))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangleRect(rect)
+
+
+ def DrawToolBarBg(self, dc, rect):
+ """
+ Draws the toolbar background according to the active theme.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the toolbar client rectangle.
+ """
+
+ artMgr = ArtManager.Get()
+
+ if not artMgr.GetRaiseToolbar():
+ return
+
+ # For office style, we simple draw a rectangle with a gradient colouring
+ vertical = artMgr.GetMBVerticalGradient()
+
+ dcsaver = DCSaver(dc)
+
+ # fill with gradient
+ startColour = artMgr.GetMenuBarFaceColour()
+ if artMgr.IsDark(startColour):
+ startColour = artMgr.LightColour(startColour, 50)
+
+ startColour = artMgr.LightColour(startColour, 20)
+
+ endColour = artMgr.LightColour(startColour, 90)
+ artMgr.PaintStraightGradientBox(dc, rect, startColour, endColour, vertical)
+ artMgr.DrawBitmapShadow(dc, rect)
+
+
+ def GetTextColourEnable(self):
+ """ Returns the colour used for text colour when enabled. """
+
+ return wx.BLACK
+
+
+# ----------------------------------------------------------------------------
+# File history (a.k.a. MRU, most recently used, files list)
+# ----------------------------------------------------------------------------
+
+def GetMRUEntryLabel(n, path):
+ """
+ Returns the string used for the MRU list items in the menu.
+
+ :param integer `n`: the index of the file name in the MRU list;
+ :param string `path`: the full path of the file name.
+
+ :note: The index `n` is 0-based, as usual, but the strings start from 1.
+ """
+
+ # we need to quote '&' characters which are used for mnemonics
+ pathInMenu = path.replace("&", "&&")
+ return "&%d %s"%(n + 1, pathInMenu)
+
+
+# ----------------------------------------------------------------------------
+# File history management
+# ----------------------------------------------------------------------------
+
+class FileHistory(object):
+ """
+ The :class:`FileHistory` encapsulates a user interface convenience, the list of most
+ recently visited files as shown on a menu (usually the File menu).
+
+ :class:`FileHistory` can manage one or more file menus. More than one menu may be
+ required in an MDI application, where the file history should appear on each MDI
+ child menu as well as the MDI parent frame.
+ """
+
+ def __init__(self, maxFiles=9, idBase=wx.ID_FILE1):
+ """
+ Default class constructor.
+
+ :param integer `maxFiles`: the maximum number of files that should be stored and displayed;
+ :param integer `idBase`: defaults to ``wx.ID_FILE1`` and represents the id given to the first
+ history menu item.
+
+ :note: Since menu items can't share the same ID you should change `idBase` to one of
+ your own defined IDs when using more than one :class:`FileHistory` in your application.
+ """
+
+ # The ID of the first history menu item (Doesn't have to be wxID_FILE1)
+ self._idBase = idBase
+
+ # Last n files
+ self._fileHistory = []
+
+ # Menus to maintain (may need several for an MDI app)
+ self._fileMenus = []
+
+ # Max files to maintain
+ self._fileMaxFiles = maxFiles
+
+
+ def GetMaxFiles(self):
+ """ Returns the maximum number of files that can be stored. """
+
+ return self._fileMaxFiles
+
+
+ # Accessors
+ def GetHistoryFile(self, index):
+ """
+ Returns the file at this index (zero-based).
+
+ :param integer `index`: the index at which the file is stored in the file list (zero-based).
+ """
+
+ return self._fileHistory[index]
+
+
+ def GetCount(self):
+ """ Returns the number of files currently stored in the file history. """
+
+ return len(self._fileHistory)
+
+
+ def GetMenus(self):
+ """
+ Returns the list of menus that are managed by this file history object.
+
+ :see: :meth:`~FileHistory.UseMenu`.
+ """
+
+ return self._fileMenus
+
+
+ # Set/get base id
+ def SetBaseId(self, baseId):
+ """
+ Sets the base identifier for the range used for appending items.
+
+ :param integer `baseId`: the base identifier for the range used for appending items.
+ """
+
+ self._idBase = baseId
+
+
+ def GetBaseId(self):
+ """ Returns the base identifier for the range used for appending items. """
+
+ return self._idBase
+
+
+ def GetNoHistoryFiles(self):
+ """ Returns the number of files currently stored in the file history. """
+
+ return self.GetCount()
+
+
+ def AddFileToHistory(self, fnNew):
+ """
+ Adds a file to the file history list, if the object has a pointer to an
+ appropriate file menu.
+
+ :param string `fnNew`: the file name to add to the history list.
+ """
+
+ # check if we don't already have this file
+ numFiles = len(self._fileHistory)
+
+ for index, fileH in enumerate(self._fileHistory):
+ if fnNew == fileH:
+ # we do have it, move it to the top of the history
+ self.RemoveFileFromHistory(index)
+ numFiles -= 1
+ break
+
+ # if we already have a full history, delete the one at the end
+ if numFiles == self._fileMaxFiles:
+ self.RemoveFileFromHistory(numFiles-1)
+
+ # add a new menu item to all file menus (they will be updated below)
+ for menu in self._fileMenus:
+ if numFiles == 0 and menu.GetMenuItemCount() > 0:
+ menu.AppendSeparator()
+
+ # label doesn't matter, it will be set below anyhow, but it can't
+ # be empty (this is supposed to indicate a stock item)
+ menu.Append(self._idBase + numFiles, " ")
+
+ # insert the new file in the beginning of the file history
+ self._fileHistory.insert(0, fnNew)
+ numFiles += 1
+
+ # update the labels in all menus
+ for index in xrange(numFiles):
+
+ # if in same directory just show the filename otherwise the full path
+ fnOld = self._fileHistory[index]
+ oldPath, newPath = os.path.split(fnOld)[0], os.path.split(fnNew)[0]
+
+ if oldPath == newPath:
+ pathInMenu = os.path.split(fnOld)[1]
+
+ else:
+ # file in different directory
+ # absolute path could also set relative path
+ pathInMenu = self._fileHistory[index]
+
+ for menu in self._fileMenus:
+ menu.SetLabel(self._idBase + index, GetMRUEntryLabel(index, pathInMenu))
+
+
+ def RemoveFileFromHistory(self, index):
+ """
+ Removes the specified file from the history.
+
+ :param integer `index`: the zero-based index indicating the file name position in
+ the file list.
+ """
+
+ numFiles = len(self._fileHistory)
+ if index >= numFiles:
+ raise Exception("Invalid index in RemoveFileFromHistory: %d (only %d files)"%(index, numFiles))
+
+ # delete the element from the array
+ self._fileHistory.pop(index)
+ numFiles -= 1
+
+ for menu in self._fileMenus:
+ # shift filenames up
+ for j in xrange(numFiles):
+ menu.SetLabel(self._idBase + j, GetMRUEntryLabel(j, self._fileHistory[j]))
+
+ # delete the last menu item which is unused now
+ lastItemId = self._idBase + numFiles
+ if menu.FindItem(lastItemId):
+ menu.Delete(lastItemId)
+
+ if not self._fileHistory:
+ lastMenuItem = menu.GetMenuItems()[-1]
+ if lastMenuItem.IsSeparator():
+ menu.Delete(lastMenuItem)
+
+ #else: menu is empty somehow
+
+
+ def UseMenu(self, menu):
+ """
+ Adds this menu to the list of those menus that are managed by this file history
+ object.
+
+ :param `menu`: an instance of :class:`FlatMenu`.
+
+ :see: :meth:`~FileHistory.AddFilesToMenu` for initializing the menu with filenames that are already
+ in the history when this function is called, as this is not done automatically.
+ """
+
+ if menu not in self._fileMenus:
+ self._fileMenus.append(menu)
+
+
+ def RemoveMenu(self, menu):
+ """
+ Removes this menu from the list of those managed by this object.
+
+ :param `menu`: an instance of :class:`FlatMenu`.
+ """
+
+ self._fileMenus.remove(menu)
+
+
+ def Load(self, config):
+ """
+ Loads the file history from the given `config` object.
+
+ :param `config`: an instance of :class:`Config`.
+
+ :note: This function should be called explicitly by the application.
+
+ :see: :meth:`~FileHistory.Save`.
+ """
+
+ self._fileHistory = []
+ buffer = "file%d"
+ count = 1
+
+ while 1:
+ historyFile = config.Read(buffer%count)
+ if not historyFile or len(self._fileHistory) >= self._fileMaxFiles:
+ break
+
+ self._fileHistory.append(historyFile)
+ count += 1
+
+ self.AddFilesToMenu()
+
+
+ def Save(self, config):
+ """
+ Saves the file history to the given `config` object.
+
+ :param `config`: an instance of :class:`Config`.
+
+ :note: This function should be called explicitly by the application.
+
+ :see: :meth:`~FileHistory.Load`.
+ """
+
+ buffer = "file%d"
+
+ for index in xrange(self._fileMaxFiles):
+
+ if index < len(self._fileHistory):
+ config.Write(buffer%(index+1), self._fileHistory[i])
+ else:
+ config.Write(buffer%(index+1), "")
+
+
+ def AddFilesToMenu(self, menu=None):
+ """
+ Appends the files in the history list, to all menus managed by the file history object
+ if `menu` is ``None``. Otherwise it calls the auxiliary method :meth:`~FileHistory.AddFilesToMenu2`.
+
+ :param `menu`: if not ``None``, an instance of :class:`FlatMenu`.
+ """
+
+ if not self._fileHistory:
+ return
+
+ if menu is not None:
+ self.AddFilesToMenu2(menu)
+ return
+
+ for menu in self._fileMenus:
+ self.AddFilesToMenu2(menu)
+
+
+ def AddFilesToMenu2(self, menu):
+ """
+ Appends the files in the history list, to the given menu only.
+
+ :param `menu`: an instance of :class:`FlatMenu`.
+ """
+
+ if not self._fileHistory:
+ return
+
+ if menu.GetMenuItemCount():
+ menu.AppendSeparator()
+
+ for index in xrange(len(self._fileHistory)):
+ menu.Append(self._idBase + index, GetMRUEntryLabel(index, self._fileHistory[i]))
+
+
+# ---------------------------------------------------------------------------- #
+# Class FlatMenuEvent
+# ---------------------------------------------------------------------------- #
+
+class FlatMenuEvent(wx.PyCommandEvent):
+ """
+ Event class that supports the :class:`FlatMenu`-compatible event called
+ ``EVT_FLAT_MENU_SELECTED``.
+ """
+
+ def __init__(self, eventType, eventId=1):
+ """
+ Default class constructor.
+
+ :param integer `eventType`: the event type;
+ :param integer `eventId`: the event identifier.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+ self._eventType = eventType
+
+
+# ---------------------------------------------------------------------------- #
+# Class MenuEntryInfo
+# ---------------------------------------------------------------------------- #
+
+class MenuEntryInfo(object):
+ """
+ Internal class which holds information about a menu.
+ """
+
+ def __init__(self, titleOrMenu="", menu=None, state=ControlNormal, cmd=wx.ID_ANY):
+ """
+ Default class constructor.
+
+ Used internally. Do not call it in your code!
+
+ :param `titleOrMenu`: if it is a string, it represents the new menu label,
+ otherwise it is another instance of :class:`MenuEntryInfo` from which the attributes
+ are copied;
+ :param `menu`: the associated :class:`FlatMenu` object;
+ :param integer `state`: the menu item state. This can be one of the following:
+
+ ==================== ======= ==========================
+ Item State Value Description
+ ==================== ======= ==========================
+ ``ControlPressed`` 0 The item is pressed
+ ``ControlFocus`` 1 The item is focused
+ ``ControlDisabled`` 2 The item is disabled
+ ``ControlNormal`` 3 Normal state
+ ==================== ======= ==========================
+
+ :param integer `cmd`: the menu accelerator identifier.
+ """
+
+ if isinstance(titleOrMenu, basestring):
+
+ self._title = titleOrMenu
+ self._menu = menu
+
+ self._rect = wx.Rect()
+ self._state = state
+ if cmd == wx.ID_ANY:
+ cmd = wx.NewId()
+
+ self._cmd = cmd # the menu itself accelerator id
+
+ else:
+
+ self._title = titleOrMenu._title
+ self._menu = titleOrMenu._menu
+ self._rect = titleOrMenu._rect
+ self._state = titleOrMenu._state
+ self._cmd = titleOrMenu._cmd
+
+ self._textBmp = wx.NullBitmap
+ self._textSelectedBmp = wx.NullBitmap
+
+
+ def GetTitle(self):
+ """ Returns the associated menu title. """
+
+ return self._title
+
+
+ def GetMenu(self):
+ """ Returns the associated menu. """
+
+ return self._menu
+
+
+ def SetRect(self, rect):
+ """
+ Sets the associated menu client rectangle.
+
+ :param `rect`: an instance of :class:`Rect`, representing the menu client rectangle.
+ """
+
+ self._rect = rect
+
+
+ def GetRect(self):
+ """ Returns the associated menu client rectangle. """
+
+ return self._rect
+
+
+ def SetState(self, state):
+ """
+ Sets the associated menu state.
+
+ :param integer `state`: the menu item state. This can be one of the following:
+
+ ==================== ======= ==========================
+ Item State Value Description
+ ==================== ======= ==========================
+ ``ControlPressed`` 0 The item is pressed
+ ``ControlFocus`` 1 The item is focused
+ ``ControlDisabled`` 2 The item is disabled
+ ``ControlNormal`` 3 Normal state
+ ==================== ======= ==========================
+ """
+
+ self._state = state
+
+
+ def GetState(self):
+ """
+ Returns the associated menu state.
+
+ :see: :meth:`~MenuEntryInfo.SetState` for a list of valid menu states.
+ """
+
+ return self._state
+
+
+ def SetTextBitmap(self, bmp):
+ """
+ Sets the associated menu bitmap.
+
+ :param `bmp`: a valid :class:`Bitmap` object.
+ """
+
+ self._textBmp = bmp
+
+
+ def SetSelectedTextBitmap(self, bmp):
+ """
+ Sets the associated selected menu bitmap.
+
+ :param `bmp`: a valid :class:`Bitmap` object.
+ """
+
+ self._textSelectedBmp = bmp
+
+
+ def GetTextBitmap(self):
+ """ Returns the associated menu bitmap. """
+
+ return self._textBmp
+
+
+ def GetSelectedTextBitmap(self):
+ """ Returns the associated selected menu bitmap. """
+
+ return self._textSelectedBmp
+
+
+ def GetCmdId(self):
+ """ Returns the associated menu accelerator identifier. """
+
+ return self._cmd
+
+
+# ---------------------------------------------------------------------------- #
+# Class StatusBarTimer
+# ---------------------------------------------------------------------------- #
+
+class StatusBarTimer(wx.Timer):
+ """ Timer used for deleting :class:`StatusBar` long help after ``_DELAY`` seconds. """
+
+ def __init__(self, owner):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `owner`: the :class:`Timer` owner (:class:`FlatMenuBar`).
+ """
+
+ wx.Timer.__init__(self)
+ self._owner = owner
+
+
+ def Notify(self):
+ """ The timer has expired. """
+
+ self._owner.OnStatusBarTimer()
+
+
+# ---------------------------------------------------------------------------- #
+# Class FlatMenuBar
+# ---------------------------------------------------------------------------- #
+
+class FlatMenuBar(wx.Panel):
+ """
+ Implements the generic owner-drawn menu bar for :class:`FlatMenu`.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, iconSize=SmallIcons,
+ spacer=SPACER, options=FM_OPT_SHOW_CUSTOMIZE|FM_OPT_IS_LCD):
+ """
+ Default class constructor.
+
+ :param `parent`: the menu bar parent, must not be ``None``;
+ :param integer `id`: the window identifier. If ``wx.ID_ANY``, will automatically create an identifier;
+ :param integer `iconSize`: size of the icons in the toolbar. This can be one of the
+ following values (in pixels):
+
+ ==================== ======= =============================
+ `iconSize` Bit Value Description
+ ==================== ======= =============================
+ ``LargeIcons`` 32 Use large 32x32 icons
+ ``SmallIcons`` 16 Use standard 16x16 icons
+ ==================== ======= =============================
+
+ :param integer `spacer`: the space between the menu bar text and the menu bar border;
+ :param integer `options`: a combination of the following bits:
+
+ ========================= ========= =============================
+ `options` Bit Hex Value Description
+ ========================= ========= =============================
+ ``FM_OPT_IS_LCD`` 0x1 Use this style if your computer uses a LCD screen
+ ``FM_OPT_MINIBAR`` 0x2 Use this if you plan to use toolbar only
+ ``FM_OPT_SHOW_CUSTOMIZE`` 0x4 Show "customize link" in more menus, you will need to write your own handler. See demo.
+ ``FM_OPT_SHOW_TOOLBAR`` 0x8 Set this option is you are planing to use the toolbar
+ ========================= ========= =============================
+
+ """
+
+ self._rendererMgr = FMRendererMgr()
+ self._parent = parent
+ self._curretHiliteItem = -1
+
+ self._items = []
+ self._dropDownButtonArea = wx.Rect()
+ self._tbIconSize = iconSize
+ self._tbButtons = []
+ self._interval = 20 # 20 milliseconds
+ self._showTooltip = -1
+
+ self._haveTip = False
+ self._statusTimer = None
+ self._spacer = SPACER
+ self._margin = spacer
+ self._toolbarSpacer = TOOLBAR_SPACER
+ self._toolbarMargin = TOOLBAR_MARGIN
+
+ self._showToolbar = options & FM_OPT_SHOW_TOOLBAR
+ self._showCustomize = options & FM_OPT_SHOW_CUSTOMIZE
+ self._isLCD = options & FM_OPT_IS_LCD
+ self._isMinibar = options & FM_OPT_MINIBAR
+ self._options = options
+
+ self._dropDownButtonState = ControlNormal
+ self._moreMenu = None
+ self._dlg = None
+ self._tbMenu = None
+ self._moreMenuBgBmp = None
+ self._lastRadioGroup = 0
+ self._mgr = None
+
+ self._barHeight = 0
+ self._menuBarHeight = 0
+ self.SetBarHeight()
+
+ wx.Panel.__init__(self, parent, id, size=(-1, self._barHeight), style=wx.WANTS_CHARS)
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(EVT_FLAT_MENU_DISMISSED, self.OnMenuDismissed)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveMenuBar)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+ if "__WXGTK__" in wx.Platform:
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+
+ self.SetFocus()
+
+ # start the stop watch
+ self._watch = wx.StopWatch()
+ self._watch.Start()
+
+
+ def Append(self, menu, title):
+ """
+ Adds the item to the end of the menu bar.
+
+ :param `menu`: the menu to which we are appending a new item, an instance of :class:`FlatMenu`;
+ :param string `title`: the menu item label, must not be empty.
+
+ :see: :meth:`~FlatMenuBar.Insert`.
+ """
+
+ menu._menuBarFullTitle = title
+ position, label = GetAccelIndex(title)
+ menu._menuBarLabelOnly = label
+
+ return self.Insert(len(self._items), menu, title)
+
+
+ def OnIdle(self, event):
+ """
+ Handles the ``wx.EVT_IDLE`` event for :class:`FlatMenuBar`.
+
+ :param `event`: a :class:`IdleEvent` event to be processed.
+ """
+
+ refresh = False
+
+ if self._watch.Time() > self._interval:
+
+ # it is time to process UpdateUIEvents
+ for but in self._tbButtons:
+ event = wx.UpdateUIEvent(but._tbItem.GetId())
+ event.Enable(but._tbItem.IsEnabled())
+ event.SetText(but._tbItem.GetLabel())
+ event.SetEventObject(self)
+
+ self.GetEventHandler().ProcessEvent(event)
+
+ if but._tbItem.GetLabel() != event.GetText() or but._tbItem.IsEnabled() != event.GetEnabled():
+ refresh = True
+
+ but._tbItem.SetLabel(event.GetText())
+ but._tbItem.Enable(event.GetEnabled())
+
+ self._watch.Start() # Reset the timer
+
+ # we need to update the menu bar
+ if refresh:
+ self.Refresh()
+
+
+ def SetBarHeight(self):
+ """ Recalculates the :class:`FlatMenuBar` height when its settings change. """
+
+ mem_dc = wx.MemoryDC()
+ mem_dc.SelectObject(wx.EmptyBitmap(1, 1))
+ dummy, self._barHeight = mem_dc.GetTextExtent("Tp")
+ mem_dc.SelectObject(wx.NullBitmap)
+
+ if not self._isMinibar:
+ self._barHeight += 2*self._margin # The menu bar margin
+ else:
+ self._barHeight = 0
+
+ self._menuBarHeight = self._barHeight
+
+ if self._showToolbar :
+ # add the toolbar height to the menubar height
+ self._barHeight += self._tbIconSize + 2*self._toolbarMargin
+
+ if self._mgr is None:
+ return
+
+ pn = self._mgr.GetPane("flat_menu_bar")
+ pn.MinSize(wx.Size(-1, self._barHeight))
+ self._mgr.Update()
+ self.Refresh()
+
+
+ def SetOptions(self, options):
+ """
+ Sets the :class:`FlatMenuBar` options, whether to show a toolbar, to use LCD screen settings etc...
+
+ :param integer `options`: a combination of the following bits:
+
+ ========================= ========= =============================
+ `options` Bit Hex Value Description
+ ========================= ========= =============================
+ ``FM_OPT_IS_LCD`` 0x1 Use this style if your computer uses a LCD screen
+ ``FM_OPT_MINIBAR`` 0x2 Use this if you plan to use toolbar only
+ ``FM_OPT_SHOW_CUSTOMIZE`` 0x4 Show "customize link" in more menus, you will need to write your own handler. See demo.
+ ``FM_OPT_SHOW_TOOLBAR`` 0x8 Set this option is you are planing to use the toolbar
+ ========================= ========= =============================
+
+ """
+
+ self._options = options
+
+ self._showToolbar = options & FM_OPT_SHOW_TOOLBAR
+ self._showCustomize = options & FM_OPT_SHOW_CUSTOMIZE
+ self._isLCD = options & FM_OPT_IS_LCD
+ self._isMinibar = options & FM_OPT_MINIBAR
+
+ self.SetBarHeight()
+
+ self.Refresh()
+ self.Update()
+
+
+ def GetOptions(self):
+ """
+ Returns the :class:`FlatMenuBar` options, whether to show a toolbar, to use LCD screen settings etc...
+
+ :see: :meth:`~FlatMenuBar.SetOptions` for a list of valid options.
+ """
+
+ return self._options
+
+
+ def GetRendererManager(self):
+ """
+ Returns the :class:`FlatMenuBar` renderer manager.
+ """
+
+ return self._rendererMgr
+
+
+ def GetRenderer(self):
+ """
+ Returns the renderer associated with this instance.
+ """
+
+ return self._rendererMgr.GetRenderer()
+
+
+ def UpdateItem(self, item):
+ """
+ An item was modified. This function is called by :class:`FlatMenu` in case
+ an item was modified directly and not via a :class:`UpdateUIEvent` event.
+
+ :param `item`: an instance of :class:`FlatMenu`.
+ """
+
+ if not self._showToolbar:
+ return
+
+ # search for a tool bar with id
+ refresh = False
+
+ for but in self._tbButtons:
+ if but._tbItem.GetId() == item.GetId():
+ if but._tbItem.IsEnabled() != item.IsEnabled():
+ refresh = True
+
+ but._tbItem.Enable(item.IsEnabled())
+ break
+
+ if refresh:
+ self.Refresh()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`FlatMenuBar`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ # on GTK, dont use the bitmap for drawing,
+ # draw directly on the DC
+
+ if "__WXGTK__" in wx.Platform and not self._isLCD:
+ self.ClearBitmaps(0)
+
+ dc = wx.BufferedPaintDC(self)
+ self.GetRenderer().DrawMenuBar(self, dc)
+
+
+ def DrawToolbar(self, dc, rect):
+ """
+ Draws the toolbar (if present).
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the toolbar client rectangle, an instance of :class:`Rect`.
+ """
+
+ highlight_width = self._tbIconSize + self._toolbarSpacer
+ highlight_height = self._tbIconSize + self._toolbarMargin
+
+ xx = rect.x + self._toolbarMargin
+ #yy = rect.y #+ self._toolbarMargin #+ (rect.height - height)/2
+
+ # by default set all toolbar items as invisible
+ for but in self._tbButtons:
+ but._visible = False
+
+ counter = 0
+ # Get all the toolbar items
+ for i in xrange(len(self._tbButtons)):
+
+ xx += self._toolbarSpacer
+
+ tbItem = self._tbButtons[i]._tbItem
+ # the button width depends on its type
+ if tbItem.IsSeparator():
+ hightlight_width = SEPARATOR_WIDTH
+ elif tbItem.IsCustomControl():
+ control = tbItem.GetCustomControl()
+ hightlight_width = control.GetSize().x + self._toolbarSpacer
+ else:
+ hightlight_width = self._tbIconSize + self._toolbarSpacer # normal bitmap's width
+
+ # can we keep drawing?
+ if xx + highlight_width >= rect.width:
+ break
+
+ counter += 1
+
+ # mark this item as visible
+ self._tbButtons[i]._visible = True
+
+ bmp = wx.NullBitmap
+
+ #------------------------------------------
+ # special handling for separator
+ #------------------------------------------
+ if tbItem.IsSeparator():
+
+ # draw the separator
+ buttonRect = wx.Rect(xx, rect.y+1, SEPARATOR_WIDTH, rect.height-2)
+ self.GetRenderer().DrawToolbarSeparator(dc, buttonRect)
+
+ xx += buttonRect.width
+ self._tbButtons[i]._rect = buttonRect
+ continue
+
+ elif tbItem.IsCustomControl():
+ control = tbItem.GetCustomControl()
+ ctrlSize = control.GetSize()
+ ctrlPos = wx.Point(xx, rect.y + (rect.height - ctrlSize.y)/2)
+ if control.GetPosition() != ctrlPos:
+ control.SetPosition(ctrlPos)
+
+ if not control.IsShown():
+ control.Show()
+
+ buttonRect = wx.RectPS(ctrlPos, ctrlSize)
+ xx += buttonRect.width
+ self._tbButtons[i]._rect = buttonRect
+ continue
+ else:
+ if tbItem.IsEnabled():
+ bmp = tbItem.GetBitmap()
+ else:
+ bmp = tbItem.GetDisabledBitmap()
+
+ # Draw the toolbar image
+ if bmp.Ok():
+
+ x = xx - self._toolbarSpacer/2
+ #y = rect.y + (rect.height - bmp.GetHeight())/2 - 1
+ y = rect.y + self._toolbarMargin/2
+
+ buttonRect = wx.Rect(x, y, highlight_width, highlight_height)
+
+ if i < len(self._tbButtons) and i >= 0:
+
+ if self._tbButtons[i]._tbItem.IsSelected():
+ tmpState = ControlPressed
+ else:
+ tmpState = ControlFocus
+
+ if self._tbButtons[i]._state == ControlFocus or self._tbButtons[i]._tbItem.IsSelected():
+ self.GetRenderer().DrawMenuBarButton(dc, buttonRect, tmpState) # TODO DrawToolbarButton? With separate toolbar colors
+ else:
+ self._tbButtons[i]._state = ControlNormal
+
+ imgx = buttonRect.x + (buttonRect.width - bmp.GetWidth())/2
+ imgy = buttonRect.y + (buttonRect.height - bmp.GetHeight())/2
+
+ if self._tbButtons[i]._state == ControlFocus and not self._tbButtons[i]._tbItem.IsSelected():
+
+ # in case we the button is in focus, place it
+ # once pixle up and left
+ # place a dark image under the original image to provide it
+ # with some shadow
+ # shadow = ConvertToMonochrome(bmp)
+ # dc.DrawBitmap(shadow, imgx, imgy, True)
+
+ imgx -= 1
+ imgy -= 1
+
+ dc.DrawBitmap(bmp, imgx, imgy, True)
+ xx += buttonRect.width
+
+ self._tbButtons[i]._rect = buttonRect
+ #Edited by P.Kort
+
+ if self._showTooltip == -1:
+ self.RemoveHelp()
+ else:
+ try:
+ self.DoGiveHelp(self._tbButtons[self._showTooltip]._tbItem)
+ except:
+ if _debug:
+ print "FlatMenu.py; fn : DrawToolbar; Can't create Tooltip "
+ pass
+
+ for j in xrange(counter, len(self._tbButtons)):
+ if self._tbButtons[j]._tbItem.IsCustomControl():
+ control = self._tbButtons[j]._tbItem.GetCustomControl()
+ control.Hide()
+
+
+ def GetMoreMenuButtonRect(self):
+ """ Returns a rectangle region, as an instance of :class:`Rect`, surrounding the menu button. """
+
+ clientRect = self.GetClientRect()
+ rect = wx.Rect(*clientRect)
+ rect.SetWidth(DROP_DOWN_ARROW_WIDTH)
+ rect.SetX(clientRect.GetWidth() + rect.GetX() - DROP_DOWN_ARROW_WIDTH - 3)
+ rect.SetY(2)
+ rect.SetHeight(rect.GetHeight() - self._spacer)
+
+ return rect
+
+
+ def DrawMoreButton(self, dc, state):
+ """
+ Draws 'more' button to the right side of the menu bar.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param integer `state`: the 'more' button state.
+
+ :see: :meth:`MenuEntryInfo.SetState() <flatmenu.MenuEntryInfo.SetState>` for a list of valid menu states.
+ """
+
+ if (not self._showCustomize) and self.GetInvisibleMenuItemCount() < 1 and self.GetInvisibleToolbarItemCount() < 1:
+ return
+
+ # Draw a drop down menu at the right position of the menu bar
+ # we use xpm file with 16x16 size, another 4 pixels we take as spacer
+ # from the right side of the frame, this will create a DROP_DOWN_ARROW_WIDTH pixels width
+ # of unwanted zone on the right side
+
+ rect = self.GetMoreMenuButtonRect()
+
+ # Draw the bitmap
+ if state != ControlNormal:
+ # Draw background according to state
+ self.GetRenderer().DrawButton(dc, rect, state)
+ else:
+ # Delete current image
+ if self._moreMenuBgBmp.Ok():
+ dc.DrawBitmap(self._moreMenuBgBmp, rect.x, rect.y, True)
+
+ dropArrowBmp = self.GetRenderer()._bitmaps["arrow_down"]
+
+ # Calc the image coordinates
+ xx = rect.x + (DROP_DOWN_ARROW_WIDTH - dropArrowBmp.GetWidth())/2
+ yy = rect.y + (rect.height - dropArrowBmp.GetHeight())/2
+
+ dc.DrawBitmap(dropArrowBmp, xx, yy + self._spacer, True)
+ self._dropDownButtonState = state
+
+
+ def HitTest(self, pt):
+ """
+ HitTest method for :class:`FlatMenuBar`.
+
+ :param `pt`: an instance of :class:`Point`, specifying the hit test position.
+
+ :return: A tuple representing one of the following combinations:
+
+ ========================= ==================================================
+ Return Tuple Description
+ ========================= ==================================================
+ (-1, 0) The :meth:`~FlatMenuBar.HitTest` method didn't find any item with the specified input point `pt` (``NoWhere`` = 0)
+ (`integer`, 1) A menu item has been hit, its position specified by the tuple item `integer` (``MenuItem`` = 1)
+ (`integer`, 2) A toolbar item has ben hit, its position specified by the tuple item `integer` (``ToolbarItem`` = 2)
+ (-1, 3) The drop-down area button has been hit (``DropDownArrowButton`` = 3)
+ ========================= ==================================================
+
+ """
+
+ if self._dropDownButtonArea.Contains(pt):
+ return -1, DropDownArrowButton
+
+ for ii, item in enumerate(self._items):
+ if item.GetRect().Contains(pt):
+ return ii, MenuItem
+
+ # check for tool bar items
+ if self._showToolbar:
+ for ii, but in enumerate(self._tbButtons):
+ if but._rect.Contains(pt):
+ # locate the corresponded menu item
+ enabled = but._tbItem.IsEnabled()
+ separator = but._tbItem.IsSeparator()
+ visible = but._visible
+ if enabled and not separator and visible:
+ self._showTooltip = ii
+ return ii, ToolbarItem
+
+ self._showTooltip = -1
+ return -1, NoWhere
+
+
+ def FindMenuItem(self, id):
+ """
+ Finds the menu item object associated with the given menu item identifier.
+
+ :param integer `id`: the identifier for the sought :class:`FlatMenuItem`.
+
+ :return: The found menu item object, or ``None`` if one was not found.
+ """
+
+ for item in self._items:
+ mi = item.GetMenu().FindItem(id)
+ if mi:
+ return mi
+ return None
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`FlatMenuBar`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.ClearBitmaps(0)
+ self.Refresh()
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`FlatMenuBar`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def ShowCustomize(self, show=True):
+ """
+ Shows/hides the drop-down arrow which allows customization of :class:`FlatMenu`.
+
+ :param bool `show`: ``True`` to show the customize menu, ``False`` to hide it.
+ """
+
+ if self._showCustomize == show:
+ return
+
+ self._showCustomize = show
+ self.Refresh()
+
+
+ def SetMargin(self, margin):
+ """
+ Sets the margin above and below the menu bar text.
+
+ :param integer `margin`: height in pixels of the margin.
+ """
+
+ self._margin = margin
+
+
+ def SetSpacing(self, spacer):
+ """
+ Sets the spacing between the menubar items.
+
+ :param integer `spacer`: number of pixels between each menu item.
+ """
+
+ self._spacer = spacer
+
+
+ def SetToolbarMargin(self, margin):
+ """
+ Sets the margin around the toolbar.
+
+ :param integer `margin`: width in pixels of the margin around the tools in the toolbar.
+ """
+
+ self._toolbarMargin = margin
+
+
+ def SetToolbarSpacing(self, spacer):
+ """
+ Sets the spacing between the toolbar tools.
+
+ :param integer `spacer`: number of pixels between each tool in the toolbar.
+ """
+
+ self._toolbarSpacer = spacer
+
+
+ def SetLCDMonitor(self, lcd=True):
+ """
+ Sets whether the PC monitor is an LCD or not.
+
+ :param bool `lcd`: ``True`` to use the settings appropriate for a LCD monitor,
+ ``False`` otherwise.
+ """
+
+ if self._isLCD == lcd:
+ return
+
+ self._isLCD = lcd
+ self.Refresh()
+
+
+ def ProcessMouseMoveFromMenu(self, pt):
+ """
+ This function is called from child menus, this allow a child menu to
+ pass the mouse movement event to the menu bar.
+
+ :param `pt`: an instance of :class:`Point`.
+ """
+
+ idx, where = self.HitTest(pt)
+ if where == MenuItem:
+ self.ActivateMenu(self._items[idx])
+
+
+ def DoMouseMove(self, pt, leftIsDown):
+ """
+ Handles mouse move event.
+
+ :param `pt`: an instance of :class:`Point`;
+ :param bool `leftIsDown`: ``True`` is the left mouse button is down, ``False`` otherwise.
+ """
+
+ # Reset items state
+ for item in self._items:
+ item.SetState(ControlNormal)
+
+ idx, where = self.HitTest(pt)
+
+ if where == DropDownArrowButton:
+ self.RemoveHelp()
+ if self._dropDownButtonState != ControlFocus and not leftIsDown:
+ dc = wx.ClientDC(self)
+ self.DrawMoreButton(dc, ControlFocus)
+
+ elif where == MenuItem:
+ self._dropDownButtonState = ControlNormal
+ # On Item
+ self._items[idx].SetState(ControlFocus)
+
+ # If this item is already selected, dont draw it again
+ if self._curretHiliteItem == idx:
+ return
+
+ self._curretHiliteItem = idx
+ if self._showToolbar:
+
+ # mark all toolbar items as non-hilited
+ for but in self._tbButtons:
+ but._state = ControlNormal
+
+ self.Refresh()
+
+ elif where == ToolbarItem:
+
+ if self._showToolbar:
+ if idx < len(self._tbButtons) and idx >= 0:
+ if self._tbButtons[idx]._state == ControlFocus:
+ return
+
+ # we need to refresh the toolbar
+ active = self.GetActiveToolbarItem()
+ if active != wx.NOT_FOUND:
+ self._tbButtons[active]._state = ControlNormal
+
+ for but in self._tbButtons:
+ but._state = ControlNormal
+
+ self._tbButtons[idx]._state = ControlFocus
+ self.DoGiveHelp(self._tbButtons[idx]._tbItem)
+ self.Refresh()
+
+ elif where == NoWhere:
+
+ refresh = False
+ self.RemoveHelp()
+
+ if self._dropDownButtonState != ControlNormal:
+ refresh = True
+ self._dropDownButtonState = ControlNormal
+
+ if self._showToolbar:
+ tbActiveItem = self.GetActiveToolbarItem()
+ if tbActiveItem != wx.NOT_FOUND:
+ self._tbButtons[tbActiveItem]._state = ControlNormal
+ refresh = True
+
+ if self._curretHiliteItem != -1:
+
+ self._items[self._curretHiliteItem].SetState(ControlNormal)
+ self._curretHiliteItem = -1
+ self.Refresh()
+
+ if refresh:
+ self.Refresh()
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`FlatMenuBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ pt = event.GetPosition()
+ self.DoMouseMove(pt, event.LeftIsDown())
+
+
+ def OnLeaveMenuBar(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`FlatMenuBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+
+ :note: This method is for MSW only.
+ """
+
+ pt = event.GetPosition()
+ self.DoMouseMove(pt, event.LeftIsDown())
+
+
+ def ResetToolbarItems(self):
+ """ Used internally. """
+
+ for but in self._tbButtons:
+ but._state = ControlNormal
+
+
+ def GetActiveToolbarItem(self):
+ """ Returns the active toolbar item. """
+
+ for but in self._tbButtons:
+
+ if but._state == ControlFocus or but._state == ControlPressed:
+ return self._tbButtons.index(but)
+
+ return wx.NOT_FOUND
+
+
+ def GetBackgroundColour(self):
+ """ Returns the menu bar background colour. """
+
+ return self.GetRenderer().menuBarFaceColour
+
+
+ def SetBackgroundColour(self, colour):
+ """
+ Sets the menu bar background colour.
+
+ :param `colour`: a valid :class:`Colour`.
+ """
+
+ self.GetRenderer().menuBarFaceColour = colour
+
+
+ def OnLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`FlatMenuBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+
+ :note: This method is for GTK only.
+ """
+
+ self._curretHiliteItem = -1
+ self._dropDownButtonState = ControlNormal
+
+ # Reset items state
+ for item in self._items:
+ item.SetState(ControlNormal)
+
+ for but in self._tbButtons:
+ but._state = ControlNormal
+
+ self.Refresh()
+
+
+ def OnMenuDismissed(self, event):
+ """
+ Handles the ``EVT_FLAT_MENU_DISMISSED`` event for :class:`FlatMenuBar`.
+
+ :param `event`: a :class:`FlatMenuEvent` event to be processed.
+ """
+
+ pt = wx.GetMousePosition()
+ pt = self.ScreenToClient(pt)
+
+ idx, where = self.HitTest(pt)
+ self.RemoveHelp()
+
+ if where not in [MenuItem, DropDownArrowButton]:
+ self._dropDownButtonState = ControlNormal
+ self._curretHiliteItem = -1
+ for item in self._items:
+ item.SetState(ControlNormal)
+
+ self.Refresh()
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`FlatMenuBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ pt = event.GetPosition()
+ idx, where = self.HitTest(pt)
+
+ if where == DropDownArrowButton:
+ dc = wx.ClientDC(self)
+ self.DrawMoreButton(dc, ControlPressed)
+ self.PopupMoreMenu()
+
+ elif where == MenuItem:
+ # Position the menu, the GetPosition() return the coords
+ # of the button relative to its parent, we need to translate
+ # them into the screen coords
+ self.ActivateMenu(self._items[idx])
+
+ elif where == ToolbarItem:
+ redrawAll = False
+ item = self._tbButtons[idx]._tbItem
+ # try to toggle if its a check item:
+ item.Toggle()
+ # switch is if its a unselected radio item
+ if not item.IsSelected() and item.IsRadioItem():
+ group = item.GetGroup()
+ for i in xrange(len(self._tbButtons)):
+ if self._tbButtons[i]._tbItem.GetGroup() == group and \
+ i != idx and self._tbButtons[i]._tbItem.IsSelected():
+ self._tbButtons[i]._state = ControlNormal
+ self._tbButtons[i]._tbItem.Select(False)
+ redrawAll = True
+ item.Select(True)
+ # Over a toolbar item
+ if redrawAll:
+ self.Refresh()
+ if "__WXMSW__" in wx.Platform:
+ dc = wx.BufferedDC(wx.ClientDC(self))
+ else:
+ dc = wx.ClientDC(self)
+ else:
+ dc = wx.ClientDC(self)
+ self.DrawToolbarItem(dc, idx, ControlPressed)
+
+ # TODO:: Do the action specified in this button
+ self.DoToolbarAction(idx)
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`FlatMenuBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ pt = event.GetPosition()
+ idx, where = self.HitTest(pt)
+
+ if where == ToolbarItem:
+ # Over a toolbar item
+ dc = wx.ClientDC(self)
+ self.DrawToolbarItem(dc, idx, ControlFocus)
+
+
+ def DrawToolbarItem(self, dc, idx, state):
+ """
+ Draws a toolbar item button.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param integer `idx`: the tool index in the toolbar;
+ :param integer `state`: the button state.
+
+ :see: :meth:`MenuEntryInfo.SetState() <flatmenu.MenuEntryInfo.SetState>` for a list of valid menu states.
+ """
+
+ if idx >= len(self._tbButtons) or idx < 0:
+ return
+
+ if self._tbButtons[idx]._tbItem.IsSelected():
+ state = ControlPressed
+ rect = self._tbButtons[idx]._rect
+ self.GetRenderer().DrawButton(dc, rect, state)
+
+ # draw the bitmap over the highlight
+ buttonRect = wx.Rect(*rect)
+ x = rect.x + (buttonRect.width - self._tbButtons[idx]._tbItem.GetBitmap().GetWidth())/2
+ y = rect.y + (buttonRect.height - self._tbButtons[idx]._tbItem.GetBitmap().GetHeight())/2
+
+ if state == ControlFocus:
+
+ # place a dark image under the original image to provide it
+ # with some shadow
+ # shadow = ConvertToMonochrome(self._tbButtons[idx]._tbItem.GetBitmap())
+ # dc.DrawBitmap(shadow, x, y, True)
+
+ # in case we the button is in focus, place it
+ # once pixle up and left
+ x -= 1
+ y -= 1
+ dc.DrawBitmap(self._tbButtons[idx]._tbItem.GetBitmap(), x, y, True)
+
+
+ def ActivateMenu(self, menuInfo):
+ """
+ Activates a menu.
+
+ :param `menuInfo`: an instance of :class:`MenuEntryInfo`.
+ """
+
+ # first make sure all other menus are not popedup
+ if menuInfo.GetMenu().IsShown():
+ return
+
+ idx = wx.NOT_FOUND
+
+ for item in self._items:
+ item.GetMenu().Dismiss(False, True)
+ if item.GetMenu() == menuInfo.GetMenu():
+ idx = self._items.index(item)
+
+ # Remove the popup menu as well
+ if self._moreMenu and self._moreMenu.IsShown():
+ self._moreMenu.Dismiss(False, True)
+
+ # make sure that the menu item button is highlited
+ if idx != wx.NOT_FOUND:
+ self._dropDownButtonState = ControlNormal
+ self._curretHiliteItem = idx
+ for item in self._items:
+ item.SetState(ControlNormal)
+
+ self._items[idx].SetState(ControlFocus)
+ self.Refresh()
+
+ rect = menuInfo.GetRect()
+ menuPt = self.ClientToScreen(wx.Point(rect.x, rect.y))
+ menuInfo.GetMenu().SetOwnerHeight(rect.height)
+ menuInfo.GetMenu().Popup(wx.Point(menuPt.x, menuPt.y), self)
+
+
+ def DoToolbarAction(self, idx):
+ """
+ Performs a toolbar button pressed action.
+
+ :param integer `idx`: the tool index in the toolbar.
+ """
+
+ # we handle only button clicks
+ tbItem = self._tbButtons[idx]._tbItem
+ if tbItem.IsRegularItem() or tbItem.IsCheckItem() or tbItem.IsRadioItem():
+ # Create the event
+ event = wx.CommandEvent(wxEVT_FLAT_MENU_SELECTED, tbItem.GetId())
+ event.SetEventObject(self)
+
+ # all events are handled by this control and its parents
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def FindMenu(self, title):
+ """
+ Returns the index of the menu with the given title or ``wx.NOT_FOUND`` if
+ no such menu exists in this menubar.
+
+ :param string `title`: may specify either the menu title (with accelerator characters,
+ i.e. "&File") or just the menu label ("File") indifferently.
+ """
+
+ for ii, item in enumerate(self._items):
+ accelIdx, labelOnly = GetAccelIndex(item.GetTitle())
+
+ if labelOnly == title or item.GetTitle() == title:
+ return ii
+
+ return wx.NOT_FOUND
+
+
+ def GetMenu(self, menuIdx):
+ """
+ Returns the menu at the specified index `menuIdx` (zero-based).
+
+ :param integer `menuIdx`: the index of the sought menu.
+
+ :return: The found menu item object, or ``None`` if one was not found.
+ """
+
+ if menuIdx >= len(self._items) or menuIdx < 0:
+ return None
+
+ return self._items[menuIdx].GetMenu()
+
+
+ def GetMenuCount(self):
+ """ Returns the number of menus in the menubar. """
+
+ return len(self._items)
+
+
+ def Insert(self, pos, menu, title):
+ """
+ Inserts the menu at the given position into the menu bar.
+
+ :param integer `pos`: the position of the new menu in the menu bar;
+ :param `menu`: the menu to add, an instance of :class:`FlatMenu`. :class:`FlatMenuBar` owns the menu and will free it;
+ :param string `title`: the title of the menu.
+
+ :note: Inserting menu at position 0 will insert it in the very beginning of it,
+ inserting at position :meth:`~FlatMenuBar.GetMenuCount` is the same as calling :meth:`~FlatMenuBar.Append`.
+ """
+
+ menu.SetMenuBar(self)
+ self._items.insert(pos, MenuEntryInfo(title, menu))
+ self.UpdateAcceleratorTable()
+
+ self.ClearBitmaps(pos)
+ self.Refresh()
+ return True
+
+
+ def Remove(self, pos):
+ """
+ Removes the menu from the menu bar and returns the menu object - the
+ caller is responsible for deleting it.
+
+ :param integer `pos`: the position of the menu in the menu bar.
+
+ :note: This function may be used together with :meth:`~FlatMenuBar.Insert` to change the menubar
+ dynamically.
+ """
+
+ if pos >= len(self._items):
+ return None
+
+ menu = self._items[pos].GetMenu()
+ self._items.pop(pos)
+ self.UpdateAcceleratorTable()
+
+ # Since we use bitmaps to optimize our drawings, we need
+ # to reset all bitmaps from pos and until end of vector
+ # to force size/position changes to the menu bar
+ self.ClearBitmaps(pos)
+ self.Refresh()
+
+ # remove the connection to this menubar
+ menu.SetMenuBar(None)
+ return menu
+
+
+ def UpdateAcceleratorTable(self):
+ """ Updates the parent accelerator table. """
+
+ # first get the number of items we have
+ updatedTable = []
+ parent = self.GetParent()
+
+ for item in self._items:
+
+ updatedTable = item.GetMenu().GetAccelArray() + updatedTable
+
+ # create accelerator for every menu (if it exist)
+ title = item.GetTitle()
+ mnemonic, labelOnly = GetAccelIndex(title)
+
+ if mnemonic != wx.NOT_FOUND:
+
+ # Get the accelrator character
+ accelChar = labelOnly[mnemonic]
+ accelString = "\tAlt+" + accelChar
+ title += accelString
+
+ accel = wx.GetAccelFromString(title)
+ itemId = item.GetCmdId()
+
+ if accel:
+
+ # connect an event to this cmd
+ parent.Connect(itemId, -1, wxEVT_FLAT_MENU_SELECTED, self.OnAccelCmd)
+ accel.Set(accel.GetFlags(), accel.GetKeyCode(), itemId)
+ updatedTable.append(accel)
+
+ entries = [wx.AcceleratorEntry() for ii in xrange(len(updatedTable))]
+
+ # Add the new menu items
+ for i in xrange(len(updatedTable)):
+ entries[i] = updatedTable[i]
+
+ table = wx.AcceleratorTable(entries)
+ del entries
+
+ parent.SetAcceleratorTable(table)
+
+
+ def ClearBitmaps(self, start=0):
+ """
+ Restores a :class:`NullBitmap` for all the items in the menu.
+
+ :param integer `start`: the index at which to start resetting the bitmaps.
+ """
+
+ if self._isLCD:
+ return
+
+ for item in self._items[start:]:
+ item.SetTextBitmap(wx.NullBitmap)
+ item.SetSelectedTextBitmap(wx.NullBitmap)
+
+
+ def OnAccelCmd(self, event):
+ """
+ Single function to handle any accelerator key used inside the menubar.
+
+ :param `event`: a :class:`FlatMenuEvent` event to be processed.
+ """
+
+ for item in self._items:
+ if item.GetCmdId() == event.GetId():
+ self.ActivateMenu(item)
+
+
+ def ActivateNextMenu(self):
+ """ Activates next menu and make sure all others are non-active. """
+
+ last_item = self.GetLastVisibleMenu()
+ # find the current active menu
+ for i in xrange(last_item+1):
+ if self._items[i].GetMenu().IsShown():
+ nextMenu = i + 1
+ if nextMenu >= last_item:
+ nextMenu = 0
+ self.ActivateMenu(self._items[nextMenu])
+ return
+
+
+ def GetLastVisibleMenu(self):
+ """ Returns the index of the last visible menu on the menu bar. """
+
+ last_item = 0
+
+ # find the last visible item
+ rect = wx.Rect()
+
+ for item in self._items:
+
+ if item.GetRect() == rect:
+ break
+
+ last_item += 1
+
+ return last_item
+
+
+ def ActivatePreviousMenu(self):
+ """ Activates previous menu and make sure all others are non-active. """
+
+ # find the current active menu
+ last_item = self.GetLastVisibleMenu()
+
+ for i in xrange(last_item):
+ if self._items[i].GetMenu().IsShown():
+ prevMenu = i - 1
+ if prevMenu < 0:
+ prevMenu = last_item - 1
+
+ if prevMenu < 0:
+ return
+
+ self.ActivateMenu(self._items[prevMenu])
+ return
+
+
+ def CreateMoreMenu(self):
+ """ Creates the drop down menu and populate it. """
+
+ if not self._moreMenu:
+ # first time
+ self._moreMenu = FlatMenu(self)
+ self._popupDlgCmdId = wx.NewId()
+
+ # Connect an event handler for this event
+ self.Connect(self._popupDlgCmdId, -1, wxEVT_FLAT_MENU_SELECTED, self.OnCustomizeDlg)
+
+ # Remove all items from the popup menu
+ self._moreMenu.Clear()
+
+ invM = self.GetInvisibleMenuItemCount()
+
+ for i in xrange(len(self._items) - invM, len(self._items)):
+ item = FlatMenuItem(self._moreMenu, wx.ID_ANY, self._items[i].GetTitle(),
+ "", wx.ITEM_NORMAL, self._items[i].GetMenu())
+ self._moreMenu.AppendItem(item)
+
+ # Add invisible toolbar items
+ invT = self.GetInvisibleToolbarItemCount()
+
+ if self._showToolbar and invT > 0:
+ if self.GetInvisibleMenuItemCount() > 0:
+ self._moreMenu.AppendSeparator()
+
+ for i in xrange(len(self._tbButtons) - invT, len(self._tbButtons)):
+ if self._tbButtons[i]._tbItem.IsSeparator():
+ self._moreMenu.AppendSeparator()
+ elif not self._tbButtons[i]._tbItem.IsCustomControl():
+ tbitem = self._tbButtons[i]._tbItem
+ item = FlatMenuItem(self._tbMenu, tbitem.GetId(), tbitem.GetLabel(), "", wx.ITEM_NORMAL, None, tbitem.GetBitmap(), tbitem.GetDisabledBitmap())
+ item.Enable(tbitem.IsEnabled())
+ self._moreMenu.AppendItem(item)
+
+
+ if self._showCustomize:
+ if invT + invM > 0:
+ self._moreMenu.AppendSeparator()
+ item = FlatMenuItem(self._moreMenu, self._popupDlgCmdId, _(u"Customize..."))
+ self._moreMenu.AppendItem(item)
+
+
+ def GetInvisibleMenuItemCount(self):
+ """
+ Returns the number of invisible menu items.
+
+ :note: Valid only after the :class:`PaintEvent` has been processed after a resize.
+ """
+
+ return len(self._items) - self.GetLastVisibleMenu()
+
+
+ def GetInvisibleToolbarItemCount(self):
+ """
+ Returns the number of invisible toolbar items.
+
+ :note: Valid only after the :class:`PaintEvent` has been processed after a resize.
+ """
+
+ count = 0
+ for i in xrange(len(self._tbButtons)):
+ if self._tbButtons[i]._visible == False:
+ break
+ count = i
+
+ return len(self._tbButtons) - count - 1
+
+
+ def PopupMoreMenu(self):
+ """ Pops up the 'more' menu. """
+
+ if (not self._showCustomize) and self.GetInvisibleMenuItemCount() + self.GetInvisibleToolbarItemCount() < 1:
+ return
+
+ self.CreateMoreMenu()
+
+ pt = self._dropDownButtonArea.GetTopLeft()
+ pt = self.ClientToScreen(pt)
+ pt.y += self._dropDownButtonArea.GetHeight()
+ self._moreMenu.Popup(pt, self)
+
+
+ def OnCustomizeDlg(self, event):
+ """
+ Handles the customize dialog here.
+
+ :param `event`: a :class:`FlatMenuEvent` event to be processed.
+ """
+
+ if not self._dlg:
+ self._dlg = FMCustomizeDlg(self)
+ else:
+ # intialize the dialog
+ self._dlg.Initialise()
+
+ if self._dlg.ShowModal() == wx.ID_OK:
+ # Handle customize requests here
+ pass
+
+ if "__WXGTK__" in wx.Platform:
+ # Reset the more button
+ dc = wx.ClientDC(self)
+ self.DrawMoreButton(dc, ControlNormal)
+
+
+ def AppendToolbarItem(self, item):
+ """
+ Appends a tool to the :class:`FlatMenuBar`.
+
+ .. deprecated:: This method is now deprecated.
+
+ :see: :meth:`~FlatMenuBar.AddTool`
+ """
+
+ newItem = ToolBarItem(item, wx.Rect(), ControlNormal)
+ self._tbButtons.append(newItem)
+
+
+ def AddTool(self, toolId, label="", bitmap1=wx.NullBitmap, bitmap2=wx.NullBitmap,
+ kind=wx.ITEM_NORMAL, shortHelp="", longHelp=""):
+ """
+ Adds a tool to the toolbar.
+
+ :param integer `toolId`: an integer by which the tool may be identified in subsequent
+ operations;
+ :param string `label`: the tool label string;
+ :param integer `kind`: may be ``wx.ITEM_NORMAL`` for a normal button (default),
+ ``wx.ITEM_CHECK`` for a checkable tool (such tool stays pressed after it had been
+ toggled) or ``wx.ITEM_RADIO`` for a checkable tool which makes part of a radio
+ group of tools each of which is automatically unchecked whenever another button
+ in the group is checked;
+ :param `bitmap1`: the primary tool bitmap, an instance of :class:`Bitmap`;
+ :param `bitmap2`: the bitmap used when the tool is disabled. If it is equal to
+ :class:`NullBitmap`, the disabled bitmap is automatically generated by greing out
+ the normal one;
+ :param string `shortHelp`: a string used for the tools tooltip;
+ :param string `longHelp`: this string is shown in the :class:`StatusBar` (if any) of the
+ parent frame when the mouse pointer is inside the tool.
+ """
+
+ self._tbButtons.append(ToolBarItem(FlatToolbarItem(bitmap1, toolId, label, bitmap2, kind, shortHelp, longHelp), wx.Rect(), ControlNormal))
+
+
+ def AddSeparator(self):
+ """ Adds a separator for spacing groups of tools in toolbar. """
+
+ if len(self._tbButtons) > 0 and not self._tbButtons[len(self._tbButtons)-1]._tbItem.IsSeparator():
+ self._tbButtons.append(ToolBarItem(FlatToolbarItem(), wx.Rect(), ControlNormal))
+
+
+ def AddControl(self, control):
+ """
+ Adds any control to the toolbar, typically e.g. a combobox.
+
+ :param `control`: the control to be added, a subclass of :class:`Window` (but no :class:`TopLevelWindow`).
+ """
+
+ self._tbButtons.append(ToolBarItem(FlatToolbarItem(control), wx.Rect(), ControlNormal))
+
+
+ def AddCheckTool(self, toolId, label="", bitmap1=wx.NullBitmap, bitmap2=wx.NullBitmap, shortHelp="", longHelp=""):
+ """
+ Adds a new check (or toggle) tool to the toolbar.
+
+ :see: :meth:`~FlatMenuBar.AddTool` for parameter descriptions.
+ """
+
+ self.AddTool(toolId, label, bitmap1, bitmap2, kind=wx.ITEM_CHECK, shortHelp=shortHelp, longHelp=longHelp)
+
+
+ def AddRadioTool(self, toolId, label= "", bitmap1=wx.NullBitmap, bitmap2=wx.NullBitmap, shortHelp="", longHelp=""):
+ """
+ Adds a new radio tool to the toolbar.
+
+ Consecutive radio tools form a radio group such that exactly one button in the
+ group is pressed at any moment, in other words whenever a button in the group is
+ pressed the previously pressed button is automatically released.
+
+ You should avoid having the radio groups of only one element as it would be
+ impossible for the user to use such button.
+
+ By default, the first button in the radio group is initially pressed, the others are not.
+
+ :see: :meth:`~FlatMenuBar.AddTool` for parameter descriptions.
+ """
+
+ self.AddTool(toolId, label, bitmap1, bitmap2, kind=wx.ITEM_RADIO, shortHelp=shortHelp, longHelp=longHelp)
+
+ if len(self._tbButtons)<1 or not self._tbButtons[len(self._tbButtons)-2]._tbItem.IsRadioItem():
+ self._tbButtons[len(self._tbButtons)-1]._tbItem.Select(True)
+ self._lastRadioGroup += 1
+
+ self._tbButtons[len(self._tbButtons)-1]._tbItem.SetGroup(self._lastRadioGroup)
+
+
+ def SetUpdateInterval(self, interval):
+ """
+ Sets the UpdateUI interval for toolbar items. All UpdateUI events are
+ sent from within :meth:`~FlatMenuBar.OnIdle` handler, the default is 20 milliseconds.
+
+ :param integer `interval`: the updateUI interval in milliseconds.
+ """
+
+ self._interval = interval
+
+
+ def PositionAUI(self, mgr, fixToolbar=True):
+ """
+ Positions the control inside a wxAUI / PyAUI frame manager.
+
+ :param `mgr`: an instance of :class:`~lib.agw.aui.AuiManager` or :class:`framemanager`;
+ :param bool `fixToolbar`: ``True`` if :class:`FlatMenuBar` can not be floated.
+ """
+
+ if isinstance(mgr, wx.aui.AuiManager):
+ pn = AuiPaneInfo()
+ else:
+ pn = PyAuiPaneInfo()
+
+ xx = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_X)
+
+ # We add our menu bar as a toolbar, with the following settings
+
+ pn.Name("flat_menu_bar")
+ pn.Caption("Menu Bar")
+ pn.Top()
+ pn.MinSize(wx.Size(xx/2, self._barHeight))
+ pn.LeftDockable(False)
+ pn.RightDockable(False)
+ pn.ToolbarPane()
+
+ if not fixToolbar:
+ # We add our menu bar as a toolbar, with the following settings
+ pn.BestSize(wx.Size(xx, self._barHeight))
+ pn.FloatingSize(wx.Size(300, self._barHeight))
+ pn.Floatable(True)
+ pn.MaxSize(wx.Size(xx, self._barHeight))
+ pn.Gripper(True)
+
+ else:
+ pn.BestSize(wx.Size(xx, self._barHeight))
+ pn.Gripper(False)
+
+ pn.Resizable(False)
+ pn.PaneBorder(False)
+ mgr.AddPane(self, pn)
+
+ self._mgr = mgr
+
+
+ def DoGiveHelp(self, hit):
+ """
+ Gives tooltips and help in :class:`StatusBar`.
+
+ :param `hit`: the toolbar tool currently hovered by the mouse.
+ """
+
+ shortHelp = hit.GetShortHelp()
+ if shortHelp:
+ self.SetToolTipString(shortHelp)
+ self._haveTip = True
+
+ longHelp = hit.GetLongHelp()
+ if not longHelp:
+ return
+
+ topLevel = wx.GetTopLevelParent(self)
+
+ if isinstance(topLevel, wx.Frame) and topLevel.GetStatusBar():
+ statusBar = topLevel.GetStatusBar()
+
+ if self._statusTimer and self._statusTimer.IsRunning():
+ self._statusTimer.Stop()
+ statusBar.PopStatusText(0)
+
+ statusBar.PushStatusText(longHelp, 0)
+ self._statusTimer = StatusBarTimer(self)
+ self._statusTimer.Start(_DELAY, wx.TIMER_ONE_SHOT)
+
+
+ def RemoveHelp(self):
+ """ Removes the tooltips and statusbar help (if any) for a button. """
+
+ if self._haveTip:
+ self.SetToolTipString("")
+ self._haveTip = False
+
+ if self._statusTimer and self._statusTimer.IsRunning():
+ topLevel = wx.GetTopLevelParent(self)
+ statusBar = topLevel.GetStatusBar()
+ self._statusTimer.Stop()
+ statusBar.PopStatusText(0)
+ self._statusTimer = None
+
+
+ def OnStatusBarTimer(self):
+ """ Handles the timer expiring to delete the `longHelp` string in the :class:`StatusBar`. """
+
+ topLevel = wx.GetTopLevelParent(self)
+ statusBar = topLevel.GetStatusBar()
+ statusBar.PopStatusText(0)
+
+
+
+class mcPopupWindow(wx.MiniFrame):
+ """ Since Max OS does not support :class:`PopupWindow`, this is an alternative. """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`mcPopupWindow` parent window.
+ """
+
+ wx.MiniFrame.__init__(self, parent, style = wx.POPUP_WINDOW)
+ self.SetExtraStyle(wx.WS_EX_TRANSIENT)
+ self._parent = parent
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+
+
+ def OnLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`mcPopupWindow`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ event.Skip()
+
+
+havePopupWindow = 1
+""" Flag used to indicate whether the platform supports the native :class:`PopupWindow`. """
+
+if wx.Platform == '__WXMAC__':
+ havePopupWindow = 0
+ wx.PopupWindow = mcPopupWindow
+
+
+# ---------------------------------------------------------------------------- #
+# Class ShadowPopupWindow
+# ---------------------------------------------------------------------------- #
+
+class ShadowPopupWindow(wx.PopupWindow):
+ """ Base class for generic :class:`FlatMenu` derived from :class:`PopupWindow`. """
+
+ def __init__(self, parent=None):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`ShadowPopupWindow` parent (tipically your main frame).
+ """
+
+ if not parent:
+ parent = wx.GetApp().GetTopWindow()
+
+ if not parent:
+ raise Exception("Can't create menu without parent!")
+
+ wx.PopupWindow.__init__(self, parent)
+
+ if "__WXMSW__" in wx.Platform and _libimported == "MH":
+
+ GCL_STYLE= -26
+ cstyle= win32gui.GetClassLong(self.GetHandle(), GCL_STYLE)
+ if cstyle & CS_DROPSHADOW == 0:
+ win32api.SetClassLong(self.GetHandle(),
+ GCL_STYLE, cstyle | CS_DROPSHADOW)
+
+ # popup windows are created hidden by default
+ self.Hide()
+
+
+#--------------------------------------------------------
+# Class FlatMenuButton
+#--------------------------------------------------------
+
+class FlatMenuButton(object):
+ """
+ A nice small class that functions like :class:`BitmapButton`, the reason I did
+ not used :class:`BitmapButton` is that on Linux, it has some extra margins that
+ I can't seem to be able to remove.
+ """
+
+ def __init__(self, menu, up, normalBmp, disabledBmp=wx.NullBitmap, scrollOnHover=False):
+ """
+ Default class constructor.
+
+ :param `menu`: the parent menu associated with this button, an instance of :class:`FlatMenu`;
+ :param bool `up`: ``True`` for up arrow or ``False`` for down arrow;
+ :param `normalBmp`: normal state bitmap, an instance of :class:`Bitmap`;
+ :param `disabledBmp`: disabled state bitmap, an instance of :class:`Bitmap`.
+ """
+
+ self._normalBmp = normalBmp
+ self._up = up
+ self._parent = menu
+ self._pos = wx.Point()
+ self._size = wx.Size()
+ self._timerID = wx.NewId()
+ self._scrollOnHover = scrollOnHover
+
+ if not disabledBmp.Ok():
+ self._disabledBmp = wx.BitmapFromImage(self._normalBmp.ConvertToImage().ConvertToGreyscale())
+ else:
+ self._disabledBmp = disabledBmp
+
+ self._state = ControlNormal
+ self._timer = wx.Timer(self._parent, self._timerID)
+ self._timer.Stop()
+
+
+ def __del__(self):
+ """ Used internally. """
+
+ if self._timer:
+ if self._timer.IsRunning():
+ self._timer.Stop()
+
+ del self._timer
+
+
+ def Contains(self, pt):
+ """ Used internally. """
+
+ rect = wx.RectPS(self._pos, self._size)
+ if not rect.Contains(pt):
+ return False
+
+ return True
+
+
+ def Draw(self, dc):
+ """
+ Draws self at rect using dc.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ rect = wx.RectPS(self._pos, self._size)
+ xx = rect.x + (rect.width - self._normalBmp.GetWidth())/2
+ yy = rect.y + (rect.height - self._normalBmp.GetHeight())/2
+
+ self._parent.GetRenderer().DrawScrollButton(dc, rect, self._state)
+ dc.DrawBitmap(self._normalBmp, xx, yy, True)
+
+
+ def ProcessLeftDown(self, pt):
+ """
+ Handles left down mouse events.
+
+ :param `pt`: an instance of :class:`Point` where the left mouse button was pressed.
+ """
+
+ if not self.Contains(pt):
+ return False
+
+ self._state = ControlPressed
+ self._parent.Refresh()
+
+ if self._up:
+ self._parent.ScrollUp()
+ else:
+ self._parent.ScrollDown()
+
+ self._timer.Start(100)
+ return True
+
+
+ def ProcessLeftUp(self, pt):
+ """
+ Handles left up mouse events.
+
+ :param `pt`: an instance of :class:`Point` where the left mouse button was released.
+ """
+
+ # always stop the timer
+ self._timer.Stop()
+
+ if not self.Contains(pt):
+ return False
+
+ self._state = ControlFocus
+ self._parent.Refresh()
+
+ return True
+
+
+ def ProcessMouseMove(self, pt):
+ """
+ Handles mouse motion events. This is called any time the mouse moves in the parent menu,
+ so we must check to see if the mouse is over the button.
+
+ :param `pt`: an instance of :class:`Point` where the mouse pointer was moved.
+ """
+
+ if not self.Contains(pt):
+
+ self._timer.Stop()
+ if self._state != ControlNormal:
+
+ self._state = ControlNormal
+ self._parent.Refresh()
+
+ return False
+
+ if self._scrollOnHover and not self._timer.IsRunning():
+ self._timer.Start(100)
+
+ # Process mouse move event
+ if self._state != ControlFocus:
+ if self._state != ControlPressed:
+ self._state = ControlFocus
+ self._parent.Refresh()
+
+ return True
+
+
+ def GetTimerId(self):
+ """ Returns the timer object identifier. """
+
+ return self._timerID
+
+
+ def GetTimer(self):
+ """ Returns the timer object. """
+
+ return self._timer
+
+
+ def Move(self, input1, input2=None):
+ """
+ Moves :class:`FlatMenuButton` to the specified position.
+
+ :param `input1`: if it is an instance of :class:`Point`, it represents the :class:`FlatMenuButton`
+ position and the `input2` parameter is not used. Otherwise it is an integer representing
+ the button `x` position;
+ :param `input2`: if not ``None``, it is an integer representing the button `y` position.
+ """
+
+ if type(input) == type(1):
+ self._pos = wx.Point(input1, input2)
+ else:
+ self._pos = input1
+
+
+ def SetSize(self, input1, input2=None):
+ """
+ Sets the size for :class:`FlatMenuButton`.
+
+ :param `input1`: if it is an instance of :class:`Size`, it represents the :class:`FlatMenuButton`
+ size and the `input2` parameter is not used. Otherwise it is an integer representing
+ the button width;
+ :param `input2`: if not ``None``, it is an integer representing the button height.
+ """
+
+ if type(input) == type(1):
+ self._size = wx.Size(input1, input2)
+ else:
+ self._size = input1
+
+
+ def GetClientRect(self):
+ """ Returns the client rectangle for :class:`FlatMenuButton`. """
+
+ return wx.RectPS(self._pos, self._size)
+
+
+#--------------------------------------------------------
+# Class FlatMenuItemGroup
+#--------------------------------------------------------
+
+class FlatMenuItemGroup(object):
+ """
+ A class that manages a group of radio menu items.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ self._items = []
+
+
+ def GetSelectedItem(self):
+ """ Returns the selected item. """
+
+ for item in self._items:
+ if item.IsChecked():
+ return item
+
+ return None
+
+
+ def Add(self, item):
+ """
+ Adds a new item to the group.
+
+ :param `item`: an instance of :class:`FlatMenu`.
+ """
+
+ if item.IsChecked():
+ # uncheck all other items
+ for exitem in self._items:
+ exitem._bIsChecked = False
+
+ self._items.append(item)
+
+
+ def Exist(self, item):
+ """
+ Checks if an item is in the group.
+
+ :param `item`: an instance of :class:`FlatMenu`.
+ """
+
+ if item in self._items:
+ return True
+
+ return False
+
+
+ def SetSelection(self, item):
+ """
+ Selects a particular item.
+
+ :param `item`: an instance of :class:`FlatMenu`.
+ """
+
+ # make sure this item exist in our group
+ if not self.Exist(item):
+ return
+
+ # uncheck all other items
+ for exitem in self._items:
+ exitem._bIsChecked = False
+
+ item._bIsChecked = True
+
+
+ def Remove(self, item):
+ """
+ Removes a particular item.
+
+ :param `item`: an instance of :class:`FlatMenu`.
+ """
+
+ if item not in self._items:
+ return
+
+ self._items.remove(item)
+
+ if item.IsChecked() and len(self._items) > 0:
+ #if the removed item was the selected one,
+ # select the first one in the group
+ self._items[0]._bIsChecked = True
+
+
+#--------------------------------------------------------
+# Class FlatMenuBase
+#--------------------------------------------------------
+
+class FlatMenuBase(ShadowPopupWindow):
+ """
+ Base class for generic flat menu derived from :class:`PopupWindow`.
+ """
+
+ def __init__(self, parent=None):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`ShadowPopupWindow` parent window.
+ """
+
+ self._rendererMgr = FMRendererMgr()
+ self._parentMenu = parent
+ self._openedSubMenu = None
+ self._owner = None
+ self._popupPtOffset = 0
+ self._showScrollButtons = False
+ self._upButton = None
+ self._downButton = None
+ self._is_dismiss = False
+
+ ShadowPopupWindow.__init__(self, parent)
+
+
+ def OnDismiss(self):
+ """ Fires an event ``EVT_FLAT_MENU_DISMISSED`` and handle menu dismiss. """
+
+ # Release mouse capture if needed
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+ self._is_dismiss = True
+
+ # send an event about our dismissal to the parent (unless we are a sub menu)
+ if self.IsShown() and not self._parentMenu:
+
+ event = FlatMenuEvent(wxEVT_FLAT_MENU_DISMISSED, self.GetId())
+ event.SetEventObject(self)
+
+ # Send it
+ if self.GetMenuOwner():
+ self.GetMenuOwner().GetEventHandler().ProcessEvent(event)
+ else:
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def Popup(self, pt, parent):
+ """
+ Popups menu at the specified point.
+
+ :param `pt`: an instance of :class:`Point`, assumed to be in screen coordinates. However,
+ if `parent` is not ``None``, `pt` is translated into the screen coordinates using
+ `parent.ClientToScreen()`;
+ :param `parent`: if not ``None``, an instance of :class:`Window`.
+ """
+
+ # some controls update themselves from OnIdle() call - let them do it
+ wx.GetApp().ProcessIdle()
+
+ # The mouse was pressed in the parent coordinates,
+ # e.g. pressing on the left top of a text ctrl
+ # will result in (1, 1), these coordinates needs
+ # to be converted into screen coords
+ self._parentMenu = parent
+
+ # If we are topmost menu, we use the given pt
+ # else we use the logical
+ # parent (second argument provided to this function)
+
+ if self._parentMenu:
+ pos = self._parentMenu.ClientToScreen(pt)
+ else:
+ pos = pt
+
+ # Fit the menu into screen
+ pos = self.AdjustPosition(pos)
+ if self._showScrollButtons:
+
+ sz = self.GetSize()
+ # Get the screen height
+ scrHeight = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_Y)
+
+
+ # position the scrollbar - If we are doing scroll bar buttons put them in the top right and
+ # bottom right or else place them as menu items at the top and bottom.
+ if self.GetRenderer().scrollBarButtons:
+ if not self._upButton:
+ self._upButton = FlatMenuButton(self, True, ArtManager.Get().GetStockBitmap("arrow_up"))
+
+ if not self._downButton:
+ self._downButton = FlatMenuButton(self, False, ArtManager.Get().GetStockBitmap("arrow_down"))
+
+ self._upButton.SetSize((SCROLL_BTN_HEIGHT, SCROLL_BTN_HEIGHT))
+ self._downButton.SetSize((SCROLL_BTN_HEIGHT, SCROLL_BTN_HEIGHT))
+
+ self._upButton.Move((sz.x - SCROLL_BTN_HEIGHT - 4, 4))
+ self._downButton.Move((sz.x - SCROLL_BTN_HEIGHT - 4, scrHeight - pos.y - 2 - SCROLL_BTN_HEIGHT))
+ else:
+ if not self._upButton:
+ self._upButton = FlatMenuButton(self, True, getMenuUpArrowBitmap(), scrollOnHover=True)
+
+ if not self._downButton:
+ self._downButton = FlatMenuButton(self, False, getMenuDownArrowBitmap(), scrollOnHover=True)
+
+ self._upButton.SetSize((sz.x-2, self.GetItemHeight()))
+ self._downButton.SetSize((sz.x-2, self.GetItemHeight()))
+
+ self._upButton.Move((1, 3))
+ self._downButton.Move((1, scrHeight - pos.y - 3 - self.GetItemHeight()))
+
+ self.Move(pos)
+ self.Show()
+
+ # Capture mouse event and direct them to us
+ if not self.HasCapture():
+ self.CaptureMouse()
+
+ self._is_dismiss = False
+
+
+ def AdjustPosition(self, pos):
+ """
+ Adjusts position so the menu will be fully visible on screen.
+
+ :param `pos`: an instance of :class:`Point` specifying the menu position.
+ """
+
+ # Check that the menu can fully appear in the screen
+ scrWidth = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_X)
+ scrHeight = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_Y)
+
+ scrollBarButtons = self.GetRenderer().scrollBarButtons
+ scrollBarMenuItems = not scrollBarButtons
+
+ size = self.GetSize()
+ if scrollBarMenuItems:
+ size.y += self.GetItemHeight()*2
+
+ # always assume that we have scrollbuttons on
+ self._showScrollButtons = False
+ pos.y += self._popupPtOffset
+
+ if size.y + pos.y > scrHeight:
+ # the menu will be truncated
+ if self._parentMenu is None:
+ # try to flip the menu
+ flippedPosy = pos.y - size.y
+ flippedPosy -= self._popupPtOffset
+
+ if flippedPosy >= 0 and flippedPosy + size.y < scrHeight:
+ pos.y = flippedPosy
+ return pos
+ else:
+ # We need to popup scrollbuttons!
+ self._showScrollButtons = True
+
+ else:
+ # we are a submenu
+ # try to decrease the y value of the menu position
+ newy = pos.y
+ newy -= (size.y + pos.y) - scrHeight
+
+ if newy + size.y > scrHeight:
+ # probably the menu size is too high to fit
+ # the screen, we need scrollbuttons
+ self._showScrollButtons = True
+ else:
+ pos.y = newy
+
+ menuMaxX = pos.x + size.x
+
+ if menuMaxX > scrWidth and pos.x < scrWidth:
+
+ if self._parentMenu:
+
+ # We are submenu
+ self._shiftePos = (size.x + self._parentMenu.GetSize().x)
+ pos.x -= self._shiftePos
+ pos.x += 10
+
+ else:
+
+ self._shiftePos = ((size.x + pos.x) - scrWidth)
+ pos.x -= self._shiftePos
+
+ else:
+
+ if self._parentMenu:
+ pos.x += 5
+
+ return pos
+
+
+ def Dismiss(self, dismissParent, resetOwner):
+ """
+ Dismisses the popup window.
+
+ :param bool `dismissParent`: whether to dismiss the parent menu or not;
+ :param bool `resetOwner`: ``True`` to delete the link between this menu and the
+ owner menu, ``False`` otherwise.
+ """
+
+ # Check if child menu is poped, if so, dismiss it
+ if self._openedSubMenu:
+ self._openedSubMenu.Dismiss(False, resetOwner)
+
+ self.OnDismiss()
+
+ # Reset menu owner
+ if resetOwner:
+ self._owner = None
+
+ self.Show(False)
+
+ if self._parentMenu and dismissParent:
+
+ self._parentMenu.OnChildDismiss()
+ self._parentMenu.Dismiss(dismissParent, resetOwner)
+
+ self._parentMenu = None
+
+
+ def OnChildDismiss(self):
+ """ Handles children dismiss. """
+
+ self._openedSubMenu = None
+
+
+ def GetRenderer(self):
+ """ Returns the renderer for this class. """
+
+ return self._rendererMgr.GetRenderer()
+
+
+ def GetRootMenu(self):
+ """ Returns the top level menu. """
+
+ root = self
+ while root._parentMenu:
+ root = root._parentMenu
+
+ return root
+
+
+ def SetOwnerHeight(self, height):
+ """
+ Sets the menu owner height, this will be used to position the menu below
+ or above the owner.
+
+ :param integer `height`: an integer representing the menu owner height.
+ """
+
+ self._popupPtOffset = height
+
+
+ # by default do nothing
+ def ScrollDown(self):
+ """
+ Scroll one unit down.
+ By default this function is empty, let derived class do something.
+ """
+
+ pass
+
+
+ # by default do nothing
+ def ScrollUp(self):
+ """
+ Scroll one unit up.
+ By default this function is empty, let derived class do something.
+ """
+
+ pass
+
+
+ def GetMenuOwner(self):
+ """
+ Returns the menu logical owner, the owner does not necessarly mean the
+ menu parent, it can also be the window that popped up it.
+ """
+
+ return self._owner
+
+
+#--------------------------------------------------------
+# Class ToolBarItem
+#--------------------------------------------------------
+
+class ToolBarItem(object):
+ """
+ A simple class that holds information about a toolbar item.
+ """
+
+ def __init__(self, tbItem, rect, state):
+ """
+ Default class constructor.
+
+ :param `tbItem`: an instance of :class:`FlatToolbarItem`;
+ :param `rect`: the client rectangle for the toolbar item, an instance of :class:`Rect`;
+ :param integer `state`: the toolbar item state.
+
+ :see: :meth:`MenuEntryInfo.SetState() <flatmenu.MenuEntryInfo.SetState>` for a list of valid item states.
+ """
+
+ self._tbItem = tbItem
+ self._rect = rect
+ self._state = state
+ self._visible = True
+
+
+#--------------------------------------------------------
+# Class FlatToolBarItem
+#--------------------------------------------------------
+
+class FlatToolbarItem(object):
+ """
+ This class represents a toolbar item.
+ """
+
+ def __init__(self, controlType=None, id=wx.ID_ANY, label="", disabledBmp=wx.NullBitmap, kind=wx.ITEM_NORMAL,
+ shortHelp="", longHelp=""):
+ """
+ Default class constructor.
+
+ :param `controlType`: can be ``None`` for a toolbar separator, an instance
+ of :class:`Window` for a control or an instance of :class:`Bitmap` for a standard
+ toolbar tool;
+ :param integer `id`: the toolbar tool id. If set to ``wx.ID_ANY``, a new id is
+ automatically assigned;
+ :param string `label`: the toolbar tool label;
+ :param `disabledBmp`: the bitmap used when the tool is disabled. If the tool
+ is a standard one (i.e., not a control or a separator), and `disabledBmp`
+ is equal to :class:`NullBitmap`, the disabled bitmap is automatically generated
+ by greing the normal one;
+ :param integer `kind`: may be ``wx.ITEM_NORMAL`` for a normal button (default),
+ ``wx.ITEM_CHECK`` for a checkable tool (such tool stays pressed after it had been
+ toggled) or ``wx.ITEM_RADIO`` for a checkable tool which makes part of a radio
+ group of tools each of which is automatically unchecked whenever another button
+ in the group is checked;
+ :param string `shortHelp`: a string used for the tool's tooltip;
+ :param string `longHelp`: this string is shown in the :class:`StatusBar` (if any) of the
+ parent frame when the mouse pointer is inside the tool.
+ """
+
+ if id == wx.ID_ANY:
+ id = wx.NewId()
+
+ if controlType is None: # Is a separator
+ self._normalBmp = wx.NullBitmap
+ self._id = wx.NewId()
+ self._label = ""
+ self._disabledImg = wx.NullBitmap
+ self._customCtrl = None
+ kind = wx.ITEM_SEPARATOR
+
+ elif isinstance(controlType, wx.Window): # is a wxControl
+ self._normalBmp = wx.NullBitmap
+ self._id = id
+ self._label = ""
+ self._disabledImg = wx.NullBitmap
+ self._customCtrl = controlType
+ kind = FTB_ITEM_CUSTOM
+
+ elif isinstance(controlType, wx.Bitmap): # Bitmap construction, simple tool
+ self._normalBmp = controlType
+ self._id = id
+ self._label = label
+ self._disabledImg = disabledBmp
+ self._customCtrl = None
+
+ if not self._disabledImg.Ok():
+ # Create a grey bitmap from the normal bitmap
+ self._disabledImg = wx.BitmapFromImage(self._normalBmp.ConvertToImage().ConvertToGreyscale())
+
+ self._kind = kind
+ self._enabled = True
+ self._selected = False
+ self._group = -1 # group id for radio items
+
+ if not shortHelp:
+ shortHelp = label
+
+ self._shortHelp = shortHelp
+ self._longHelp = longHelp
+
+
+ def GetLabel(self):
+ """ Returns the tool label. """
+
+ return self._label
+
+
+ def SetLabel(self, label):
+ """
+ Sets the tool label.
+
+ :param string `label`: the new tool string.
+ """
+
+ self._label = label
+
+
+ def GetBitmap(self):
+ """ Returns the tool bitmap. """
+
+ return self._normalBmp
+
+
+ def SetBitmap(self, bmp):
+ """
+ Sets the tool bitmap.
+
+ :param `bmp`: the new tool bitmap, a valid :class:`Bitmap` object.
+ """
+
+ self._normalBmp = bmp
+
+
+ def GetDisabledBitmap(self):
+ """ Returns the tool disabled bitmap. """
+
+ return self._disabledImg
+
+
+ def SetDisabledBitmap(self, bmp):
+ """
+ Sets the tool disabled bitmap.
+
+ :param `bmp`: the new tool disabled bitmap, a valid :class:`Bitmap` object.
+ """
+
+ self._disabledImg = bmp
+
+
+ def GetId(self):
+ """ Gets the tool id. """
+
+ return self._id
+
+
+ def IsSeparator(self):
+ """ Returns whether the tool is a separator or not. """
+
+ return self._kind == wx.ITEM_SEPARATOR
+
+
+ def IsRadioItem(self):
+ """ Returns ``True`` if the item is a radio item. """
+
+ return self._kind == wx.ITEM_RADIO
+
+
+ def IsCheckItem(self):
+ """ Returns ``True`` if the item is a radio item. """
+
+ return self._kind == wx.ITEM_CHECK
+
+
+ def IsCustomControl(self):
+ """ Returns whether the tool is a custom control or not. """
+
+ return self._kind == FTB_ITEM_CUSTOM
+
+
+ def IsRegularItem(self):
+ """ Returns whether the tool is a standard tool or not. """
+
+ return self._kind == wx.ITEM_NORMAL
+
+
+ def GetCustomControl(self):
+ """ Returns the associated custom control. """
+
+ return self._customCtrl
+
+
+ def IsSelected(self):
+ """ Returns whether the tool is selected or checked."""
+
+ return self._selected
+
+
+ def IsChecked(self):
+ """ Same as :meth:`~FlatToolbarItem.IsSelected`. More intuitive for check items though. """
+
+ return self._selected
+
+
+ def Select(self, select=True):
+ """
+ Selects or checks a radio or check item.
+
+ :param bool `select`: ``True`` to select or check a tool, ``False`` to unselect
+ or uncheck it.
+ """
+
+ self._selected = select
+
+
+ def Toggle(self):
+ """ Toggles a check item. """
+
+ if self.IsCheckItem():
+ self._selected = not self._selected
+
+
+ def SetGroup(self, group):
+ """
+ Sets group id for a radio item, for other items does nothing.
+
+ :param `group`: an instance of :class:`FlatMenuItemGroup`.
+ """
+
+ if self.IsRadioItem():
+ self._group = group
+
+
+ def GetGroup(self):
+ """ Returns group id for radio item, or -1 for other item types. """
+
+ return self._group
+
+
+ def IsEnabled(self):
+ """ Returns whether the tool is enabled or not. """
+
+ return self._enabled
+
+
+ def Enable(self, enable=True):
+ """
+ Enables or disables the tool.
+
+ :param bool `enable`: ``True`` to enable the tool, ``False`` to disable it.
+ """
+
+ self._enabled = enable
+
+
+ def GetShortHelp(self):
+ """ Returns the tool short help string (displayed in the tool's tooltip). """
+
+ if self._kind == wx.ITEM_NORMAL:
+ return self._shortHelp
+
+ return ""
+
+
+ def SetShortHelp(self, help):
+ """
+ Sets the tool short help string (displayed in the tool's tooltip).
+
+ :param string `help`: the new tool short help string.
+ """
+
+ if self._kind == wx.ITEM_NORMAL:
+ self._shortHelp = help
+
+
+ def SetLongHelp(self, help):
+ """
+ Sets the tool long help string (displayed in the parent frame :class:`StatusBar`).
+
+ :param string `help`: the new tool long help string.
+ """
+
+ if self._kind == wx.ITEM_NORMAL:
+ self._longHelp = help
+
+
+ def GetLongHelp(self):
+ """ Returns the tool long help string (displayed in the parent frame :class:`StatusBar`). """
+
+ if self._kind == wx.ITEM_NORMAL:
+ return self._longHelp
+
+ return ""
+
+
+#--------------------------------------------------------
+# Class FlatMenuItem
+#--------------------------------------------------------
+
+class FlatMenuItem(object):
+ """
+ A class that represents an item in a menu.
+ """
+
+ def __init__(self, parent, id=wx.ID_SEPARATOR, label="", helpString="",
+ kind=wx.ITEM_NORMAL, subMenu=None, normalBmp=wx.NullBitmap,
+ disabledBmp=wx.NullBitmap,
+ hotBmp=wx.NullBitmap):
+ """
+ Default class constructor.
+
+ :param `parent`: menu that the menu item belongs to, an instance of :class:`FlatMenu`;
+ :param integer `id`: the menu item identifier;
+ :param string `label`: text for the menu item, as shown on the menu. An accelerator
+ key can be specified using the ampersand '&' character. In order to embed
+ an ampersand character in the menu item text, the ampersand must be doubled;
+ :param string `helpString`: optional help string that will be shown on the status bar;
+ :param integer `kind`: may be ``wx.ITEM_SEPARATOR``, ``wx.ITEM_NORMAL``, ``wx.ITEM_CHECK``
+ or ``wx.ITEM_RADIO``;
+ :param `subMenu`: if not ``None``, the sub menu this item belongs to (an instance of :class:`FlatMenu`);
+ :param `normalBmp`: normal bitmap to draw to the side of the text, this bitmap
+ is used when the menu is enabled (an instance of :class:`Bitmap`);
+ :param `disabledBmp`: 'greyed' bitmap to draw to the side of the text, this
+ bitmap is used when the menu is disabled, if none supplied normal is used (an instance of :class:`Bitmap`);
+ :param `hotBmp`: hot bitmap to draw to the side of the text, this bitmap is
+ used when the menu is hovered, if non supplied, normal is used (an instance of :class:`Bitmap`).
+ """
+
+ self._text = label
+ self._kind = kind
+ self._helpString = helpString
+
+ if id == wx.ID_ANY:
+ id = wx.NewId()
+
+ self._id = id
+ self._parentMenu = parent
+ self._subMenu = subMenu
+ self._normalBmp = normalBmp
+ self._disabledBmp = disabledBmp
+ self._hotBmp = hotBmp
+ self._bIsChecked = False
+ self._bIsEnabled = True
+ self._mnemonicIdx = wx.NOT_FOUND
+ self._isAttachedToMenu = False
+ self._accelStr = ""
+ self._rect = wx.Rect()
+ self._groupPtr = None
+ self._visible = False
+ self._contextMenu = None
+ self._font = None
+ self._textColour = None
+
+ self.SetLabel(self._text)
+ self.SetMenuBar()
+
+ self._checkMarkBmp = wx.BitmapFromXPMData(check_mark_xpm)
+ self._checkMarkBmp.SetMask(wx.Mask(self._checkMarkBmp, wx.WHITE))
+ self._radioMarkBmp = wx.BitmapFromXPMData(radio_item_xpm)
+ self._radioMarkBmp.SetMask(wx.Mask(self._radioMarkBmp, wx.WHITE))
+
+
+ def SetLongHelp(self, help):
+ """
+ Sets the item long help string (displayed in the parent frame :class:`StatusBar`).
+
+ :param string `help`: the new item long help string.
+ """
+
+ self._helpString = help
+
+
+ def GetLongHelp(self):
+ """ Returns the item long help string (displayed in the parent frame :class:`StatusBar`). """
+
+ return self._helpString
+
+
+ def GetShortHelp(self):
+ """ Returns the item short help string (displayed in the tool's tooltip). """
+
+ return ""
+
+
+ def Enable(self, enable=True):
+ """
+ Enables or disables a menu item.
+
+ :param bool `enable`: ``True`` to enable the menu item, ``False`` to disable it.
+ """
+
+ self._bIsEnabled = enable
+ if self._parentMenu:
+ self._parentMenu.UpdateItem(self)
+
+
+ def GetBitmap(self):
+ """
+ Returns the normal bitmap associated to the menu item or :class:`NullBitmap` if
+ none has been supplied.
+ """
+
+ return self._normalBmp
+
+
+ def GetDisabledBitmap(self):
+ """
+ Returns the disabled bitmap associated to the menu item or :class:`NullBitmap`
+ if none has been supplied.
+ """
+
+ return self._disabledBmp
+
+
+ def GetHotBitmap(self):
+ """
+ Returns the hot bitmap associated to the menu item or :class:`NullBitmap` if
+ none has been supplied.
+ """
+
+ return self._hotBmp
+
+
+ def GetHelp(self):
+ """ Returns the item help string. """
+
+ return self._helpString
+
+
+ def GetId(self):
+ """ Returns the item id. """
+
+ return self._id
+
+
+ def GetKind(self):
+ """
+ Returns the menu item kind, can be one of ``wx.ITEM_SEPARATOR``, ``wx.ITEM_NORMAL``,
+ ``wx.ITEM_CHECK`` or ``wx.ITEM_RADIO``.
+ """
+
+ return self._kind
+
+
+ def GetLabel(self):
+ """ Returns the menu item label (without the accelerator if it is part of the string). """
+
+ return self._label
+
+
+ def GetMenu(self):
+ """ Returns the parent menu. """
+
+ return self._parentMenu
+
+
+ def GetContextMenu(self):
+ """ Returns the context menu associated with this item (if any). """
+
+ return self._contextMenu
+
+
+ def SetContextMenu(self, context_menu):
+ """
+ Assigns a context menu to this item.
+
+ :param `context_menu`: an instance of :class:`FlatMenu`.
+ """
+
+ self._contextMenu = context_menu
+
+
+ def GetText(self):
+ """ Returns the text associated with the menu item including the accelerator. """
+
+ return self._text
+
+
+ def GetSubMenu(self):
+ """ Returns the sub-menu of this menu item (if any). """
+
+ return self._subMenu
+
+
+ def IsCheckable(self):
+ """ Returns ``True`` if this item is of type ``wx.ITEM_CHECK``, ``False`` otherwise. """
+
+ return self._kind == wx.ITEM_CHECK
+
+
+ def IsChecked(self):
+ """
+ Returns whether an item is checked or not.
+
+ :note: This method is meaningful only for items of kind ``wx.ITEM_CHECK`` or
+ ``wx.ITEM_RADIO``.
+ """
+
+ return self._bIsChecked
+
+
+ def IsRadioItem(self):
+ """ Returns ``True`` if this item is of type ``wx.ITEM_RADIO``, ``False`` otherwise. """
+
+ return self._kind == wx.ITEM_RADIO
+
+
+ def IsEnabled(self):
+ """ Returns whether an item is enabled or not. """
+
+ return self._bIsEnabled
+
+
+ def IsSeparator(self):
+ """ Returns ``True`` if this item is of type ``wx.ITEM_SEPARATOR``, ``False`` otherwise. """
+
+ return self._id == wx.ID_SEPARATOR
+
+
+ def IsSubMenu(self):
+ """ Returns whether an item is a sub-menu or not. """
+
+ return self._subMenu != None
+
+
+ def SetNormalBitmap(self, bmp):
+ """
+ Sets the menu item normal bitmap.
+
+ :param `bmp`: an instance of :class:`Bitmap`.
+ """
+
+ self._normalBmp = bmp
+
+
+ def SetDisabledBitmap(self, bmp):
+ """
+ Sets the menu item disabled bitmap.
+
+ :param `bmp`: an instance of :class:`Bitmap`.
+ """
+
+ self._disabledBmp = bmp
+
+
+ def SetHotBitmap(self, bmp):
+ """
+ Sets the menu item hot bitmap.
+
+ :param `bmp`: an instance of :class:`Bitmap`.
+ """
+
+ self._hotBmp = bmp
+
+
+ def SetHelp(self, helpString):
+ """
+ Sets the menu item help string.
+
+ :param string `helpString`: the new menu item help string.
+ """
+
+ self._helpString = helpString
+
+
+ def SetMenu(self, menu):
+ """
+ Sets the menu item parent menu.
+
+ :param `menu`: an instance of :class:`FlatMenu`.
+ """
+
+ self._parentMenu = menu
+
+
+ def SetSubMenu(self, menu):
+ """
+ Sets the menu item sub-menu.
+
+ :param `menu`: an instance of :class:`FlatMenu`.
+ """
+
+ self._subMenu = menu
+
+ # Fix toolbar update
+ self.SetMenuBar()
+
+
+ def GetAccelString(self):
+ """ Returns the accelerator string. """
+
+ return self._accelStr
+
+
+ def SetRect(self, rect):
+ """
+ Sets the menu item client rectangle.
+
+ :param `rect`: the menu item client rectangle, an instance of :class:`Rect`.
+ """
+
+ self._rect = rect
+
+
+ def GetRect(self):
+ """ Returns the menu item client rectangle. """
+
+ return self._rect
+
+
+ def IsShown(self):
+ """ Returns whether an item is shown or not. """
+
+ return self._visible
+
+
+ def Show(self, show=True):
+ """
+ Actually shows/hides the menu item.
+
+ :param bool `show`: ``True`` to show the menu item, ``False`` to hide it.
+ """
+
+ self._visible = show
+
+
+ def GetHeight(self):
+ """ Returns the menu item height, in pixels. """
+
+ if self.IsSeparator():
+ return self._parentMenu.GetRenderer().separatorHeight
+ else:
+ return self._parentMenu._itemHeight
+
+
+ def GetSuitableBitmap(self, selected):
+ """
+ Gets the bitmap that should be used based on the item state.
+
+ :param bool `selected`: ``True`` if this menu item is currently hovered by the mouse,
+ ``False`` otherwise.
+ """
+
+ normalBmp = self._normalBmp
+ gBmp = (self._disabledBmp.Ok() and [self._disabledBmp] or [self._normalBmp])[0]
+ hotBmp = (self._hotBmp.Ok() and [self._hotBmp] or [self._normalBmp])[0]
+
+ if not self.IsEnabled():
+ return gBmp
+ elif selected:
+ return hotBmp
+ else:
+ return normalBmp
+
+
+ def SetLabel(self, text):
+ """
+ Sets the label text for this item from the text (excluding the accelerator).
+
+ :param string `text`: the new item label (excluding the accelerator).
+ """
+
+ if text:
+
+ indx = text.find("\t")
+ if indx >= 0:
+ self._accelStr = text[indx+1:]
+ label = text[0:indx]
+ else:
+ self._accelStr = ""
+ label = text
+
+ self._mnemonicIdx, self._label = GetAccelIndex(label)
+
+ else:
+
+ self._mnemonicIdx = wx.NOT_FOUND
+ self._label = ""
+
+ if self._parentMenu:
+ self._parentMenu.UpdateItem(self)
+
+
+ def SetText(self, text):
+ """
+ Sets the text for this menu item (including accelerators).
+
+ :param string `text`: the new item label (including the accelerator).
+ """
+
+ self._text = text
+ self.SetLabel(self._text)
+
+
+ def SetMenuBar(self):
+ """ Links the current menu item with the main :class:`FlatMenuBar`. """
+
+ # Fix toolbar update
+ if self._subMenu and self._parentMenu:
+ self._subMenu.SetSubMenuBar(self._parentMenu.GetMenuBarForSubMenu())
+
+
+ def GetAcceleratorEntry(self):
+ """ Returns the accelerator entry associated to this menu item. """
+
+ return wx.GetAccelFromString(self.GetText())
+
+
+ def GetMnemonicChar(self):
+ """ Returns the shortcut char for this menu item. """
+
+ if self._mnemonicIdx == wx.NOT_FOUND:
+ return 0
+
+ mnemonic = self._label[self._mnemonicIdx]
+ return mnemonic.lower()
+
+
+ def Check(self, check=True):
+ """
+ Checks or unchecks the menu item.
+
+ :param bool `check`: ``True`` to check the menu item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for menu items of ``wx.ITEM_CHECK``
+ or ``wx.ITEM_RADIO`` kind.
+ """
+
+ if self.IsRadioItem() and not self._isAttachedToMenu:
+
+ # radio items can be checked only after they are attached to menu
+ return
+
+ self._bIsChecked = check
+
+ # update group
+ if self.IsRadioItem() and check:
+ self._groupPtr.SetSelection(self)
+
+ # Our parent menu might want to do something with this change
+ if self._parentMenu:
+ self._parentMenu.UpdateItem(self)
+
+
+ def SetFont(self, font=None):
+ """
+ Sets the :class:`FlatMenuItem` font.
+
+ :param `font`: an instance of a valid :class:`Font`.
+ """
+
+ self._font = font
+
+ if self._parentMenu:
+ self._parentMenu.UpdateItem(self)
+
+
+ def GetFont(self):
+ """ Returns this :class:`FlatMenuItem` font. """
+
+ return self._font
+
+
+ def SetTextColour(self, colour=None):
+ """
+ Sets the :class:`FlatMenuItem` foreground colour for the menu label.
+
+ :param `colour`: an instance of a valid :class:`Colour`.
+ """
+
+ self._textColour = colour
+
+
+ def GetTextColour(self):
+ """ Returns this :class:`FlatMenuItem` foreground text colour. """
+
+ return self._textColour
+
+
+#--------------------------------------------------------
+# Class FlatMenu
+#--------------------------------------------------------
+
+class FlatMenu(FlatMenuBase):
+ """
+ A Flat popup menu generic implementation.
+ """
+
+ def __init__(self, parent=None):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`FlatMenu` parent window (used to initialize the
+ underlying :class:`ShadowPopupWindow`).
+ """
+
+ self._menuWidth = 2*26
+ self._leftMarginWidth = 26
+ self._rightMarginWidth = 30
+ self._borderXWidth = 1
+ self._borderYWidth = 2
+ self._activeWin = None
+ self._focusWin = None
+ self._imgMarginX = 0
+ self._markerMarginX = 0
+ self._textX = 26
+ self._rightMarginPosX = -1
+ self._itemHeight = 20
+ self._selectedItem = -1
+ self._clearCurrentSelection = True
+ self._textPadding = 8
+ self._marginHeight = 20
+ self._marginWidth = 26
+ self._accelWidth = 0
+ self._mb = None
+ self._itemsArr = []
+ self._accelArray = []
+ self._ptLast = wx.Point()
+ self._resizeMenu = True
+ self._shiftePos = 0
+ self._first = 0
+ self._mb_submenu = 0
+ self._is_dismiss = False
+ self._numCols = 1
+ self._backgroundImage = None
+ self._originalBackgroundImage = None
+
+ FlatMenuBase.__init__(self, parent)
+
+ self.SetSize(wx.Size(self._menuWidth, self._itemHeight+4))
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeaveWindow)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnMouseLeftDown)
+ self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_TIMER, self.OnTimer)
+
+
+ def SetMenuBar(self, mb):
+ """
+ Attaches this menu to a menubar.
+
+ :param `mb`: an instance of :class:`FlatMenuBar`.
+ """
+
+ self._mb = mb
+
+
+ def SetSubMenuBar(self, mb):
+ """
+ Attaches this menu to a menubar.
+
+ :param `mb`: an instance of :class:`FlatMenuBar`.
+ """
+
+ self._mb_submenu = mb
+
+
+ def GetMenuBar(self):
+ """ Returns the menubar associated with this menu item. """
+
+ if self._mb_submenu:
+ return self._mb_submenu
+
+ return self._mb
+
+
+ def GetMenuBarForSubMenu(self):
+ """ Returns the menubar associated with this menu item. """
+
+ return self._mb
+
+
+ def Popup(self, pt, owner=None, parent=None):
+ """
+ Pops up the menu.
+
+ :param `pt`: the point at which the menu should be popped up (an instance
+ of :class:`Point`);
+ :param `owner`: the owner of the menu. The owner does not necessarly mean the
+ menu parent, it can also be the window that popped up it;
+ :param `parent`: the menu parent window.
+ """
+
+ if "__WXMSW__" in wx.Platform:
+ self._mousePtAtStartup = wx.GetMousePosition()
+
+ # each time we popup, need to reset the starting index
+ self._first = 0
+
+ # Loop over self menu and send update UI event for
+ # every item in the menu
+ numEvents = len(self._itemsArr)
+ cc = 0
+ self._shiftePos = 0
+
+ # Set the owner of the menu. All events will be directed to it.
+ # If owner is None, the Default GetParent() is used as the owner
+ self._owner = owner
+
+ for cc in xrange(numEvents):
+ self.SendUIEvent(cc)
+
+ # Adjust menu position and show it
+ FlatMenuBase.Popup(self, pt, parent)
+
+ artMgr = ArtManager.Get()
+ artMgr.MakeWindowTransparent(self, artMgr.GetTransparency())
+
+ # Replace the event handler of the active window to direct
+ # all keyboard events to us and the focused window to direct char events to us
+ self._activeWin = wx.GetActiveWindow()
+ if self._activeWin:
+
+ oldHandler = self._activeWin.GetEventHandler()
+ newEvtHandler = MenuKbdRedirector(self, oldHandler)
+ self._activeWin.PushEventHandler(newEvtHandler)
+
+ if "__WXMSW__" in wx.Platform:
+ self._focusWin = wx.Window.FindFocus()
+ elif "__WXGTK__" in wx.Platform:
+ self._focusWin = self
+ else:
+ self._focusWin = None
+
+ if self._focusWin:
+ newEvtHandler = FocusHandler(self)
+ self._focusWin.PushEventHandler(newEvtHandler)
+
+
+ def Append(self, id, item, helpString="", kind=wx.ITEM_NORMAL):
+ """
+ Appends an item to this menu.
+
+ :param integer `id`: the menu item identifier;
+ :param string `item`: the string to appear on the menu item;
+ :param string `helpString`: an optional help string associated with the item. By default,
+ the handler for the ``EVT_FLAT_MENU_ITEM_MOUSE_OVER`` event displays this string
+ in the status line;
+ :param integer `kind`: may be ``wx.ITEM_NORMAL`` for a normal button (default),
+ ``wx.ITEM_CHECK`` for a checkable tool (such tool stays pressed after it had been
+ toggled) or ``wx.ITEM_RADIO`` for a checkable tool which makes part of a radio
+ group of tools each of which is automatically unchecked whenever another button
+ in the group is checked;
+ """
+
+ newItem = FlatMenuItem(self, id, item, helpString, kind)
+ return self.AppendItem(newItem)
+
+
+ def Prepend(self, id, item, helpString="", kind=wx.ITEM_NORMAL):
+ """
+ Prepends an item to this menu.
+
+ :param integer `id`: the menu item identifier;
+ :param string `item`: the string to appear on the menu item;
+ :param string `helpString`: an optional help string associated with the item. By default,
+ the handler for the ``EVT_FLAT_MENU_ITEM_MOUSE_OVER`` event displays this string
+ in the status line;
+ :param integer `kind`: may be ``wx.ITEM_NORMAL`` for a normal button (default),
+ ``wx.ITEM_CHECK`` for a checkable tool (such tool stays pressed after it had been
+ toggled) or ``wx.ITEM_RADIO`` for a checkable tool which makes part of a radio
+ group of tools each of which is automatically unchecked whenever another button
+ in the group is checked;
+ """
+
+ newItem = FlatMenuItem(self, id, item, helpString, kind)
+ return self.PrependItem(newItem)
+
+
+ def AppendSubMenu(self, subMenu, item, helpString=""):
+ """
+ Adds a pull-right submenu to the end of the menu.
+
+ This function is added to duplicate the API of :class:`Menu`.
+
+ :see: :meth:`~FlatMenu.AppendMenu` for an explanation of the input parameters.
+ """
+
+ return self.AppendMenu(wx.ID_ANY, item, subMenu, helpString)
+
+
+ def AppendMenu(self, id, item, subMenu, helpString=""):
+ """
+ Adds a pull-right submenu to the end of the menu.
+
+ :param integer `id`: the menu item identifier;
+ :param string `item`: the string to appear on the menu item;
+ :param `subMenu`: an instance of :class:`FlatMenu`, the submenu to append;
+ :param string `helpString`: an optional help string associated with the item. By default,
+ the handler for the ``EVT_FLAT_MENU_ITEM_MOUSE_OVER`` event displays this string
+ in the status line.
+ """
+
+ newItem = FlatMenuItem(self, id, item, helpString, wx.ITEM_NORMAL, subMenu)
+ return self.AppendItem(newItem)
+
+
+ def AppendItem(self, menuItem):
+ """
+ Appends an item to this menu.
+
+ :param `menuItem`: an instance of :class:`FlatMenuItem`.
+ """
+
+ self._itemsArr.append(menuItem)
+ return self.AddItem(menuItem)
+
+
+ def PrependItem(self, menuItem):
+ """
+ Prepends an item to this menu.
+
+ :param `menuItem`: an instance of :class:`FlatMenuItem`.
+ """
+
+ self._itemsArr.insert(0,menuItem)
+ return self.AddItem(menuItem)
+
+
+ def AddItem(self, menuItem):
+ """
+ Internal function to add the item to this menu. The item must
+ already be in the `self._itemsArr` attribute.
+
+ :param `menuItem`: an instance of :class:`FlatMenuItem`.
+ """
+
+ if not menuItem:
+ raise Exception("Adding None item?")
+
+ # Reparent to us
+ menuItem.SetMenu(self)
+ menuItem._isAttachedToMenu = True
+
+ # Update the menu width if necessary
+ menuItemWidth = self.GetMenuItemWidth(menuItem)
+ self._menuWidth = (self._menuWidth > menuItemWidth + self._accelWidth and \
+ [self._menuWidth] or [menuItemWidth + self._accelWidth])[0]
+
+ menuHeight = 0
+ switch = 1e6
+
+ if self._numCols > 1:
+ nItems = len(self._itemsArr)
+ switch = int(math.ceil((nItems - self._first)/float(self._numCols)))
+
+ for indx, item in enumerate(self._itemsArr):
+
+ if indx >= switch:
+ break
+
+ if item.IsSeparator():
+ menuHeight += self.GetRenderer().separatorHeight
+ else:
+ menuHeight += self._itemHeight
+
+ self.SetSize(wx.Size(self._menuWidth*self._numCols, menuHeight+4))
+
+ if self._originalBackgroundImage:
+ img = wx.ImageFromBitmap(self._originalBackgroundImage)
+ img = img.Scale(self._menuWidth*self._numCols-2-self._leftMarginWidth, menuHeight, wx.IMAGE_QUALITY_HIGH)
+ self._backgroundImage = img.ConvertToBitmap()
+
+ # Add accelerator entry to the menu if needed
+ accel = menuItem.GetAcceleratorEntry()
+
+ if accel:
+ accel.Set(accel.GetFlags(), accel.GetKeyCode(), menuItem.GetId())
+ self._accelArray.append(accel)
+
+ self.UpdateRadioGroup(menuItem)
+
+ return menuItem
+
+
+ def GetMenuItems(self):
+ """ Returns the list of menu items in the menu. """
+
+ return self._itemsArr
+
+
+ def GetMenuItemWidth(self, menuItem):
+ """
+ Returns the width of a particular item.
+
+ :param `menuItem`: an instance of :class:`FlatMenuItem`.
+ """
+
+ menuItemWidth = 0
+ text = menuItem.GetLabel() # Without accelerator
+ accel = menuItem.GetAccelString()
+
+ dc = wx.ClientDC(self)
+
+ font = menuItem.GetFont()
+ if font is None:
+ font = ArtManager.Get().GetFont()
+
+ dc.SetFont(font)
+
+ accelFiller = "XXXX" # 4 spaces betweem text and accel column
+
+ # Calc text length/height
+ dummy, itemHeight = dc.GetTextExtent("Tp")
+ width, height = dc.GetTextExtent(text)
+ accelWidth, accelHeight = dc.GetTextExtent(accel)
+ filler, dummy = dc.GetTextExtent(accelFiller)
+
+ bmpHeight = bmpWidth = 0
+
+ if menuItem.GetBitmap().Ok():
+ bmpHeight = menuItem.GetBitmap().GetHeight()
+ bmpWidth = menuItem.GetBitmap().GetWidth()
+
+ if itemHeight < self._marginHeight:
+ itemHeight = self._marginHeight
+
+ itemHeight = (bmpHeight > self._itemHeight and [bmpHeight] or [itemHeight])[0]
+ itemHeight += 2*self._borderYWidth
+
+ # Update the global menu item height if needed
+ self._itemHeight = (self._itemHeight > itemHeight and [self._itemHeight] or [itemHeight])[0]
+ self._marginWidth = (self._marginWidth > bmpWidth and [self._marginWidth] or [bmpWidth])[0]
+
+ # Update the accel width
+ accelWidth += filler
+ if accel:
+ self._accelWidth = (self._accelWidth > accelWidth and [self._accelWidth] or [accelWidth])[0]
+
+ # In case the item has image & is type radio or check, we need double size
+ # left margin
+ factor = (((menuItem.GetBitmap() != wx.NullBitmap) and \
+ (menuItem.IsCheckable() or (menuItem.GetKind() == wx.ITEM_RADIO))) and [2] or [1])[0]
+
+ if factor == 2:
+
+ self._imgMarginX = self._marginWidth + 2*self._borderXWidth
+ self._leftMarginWidth = 2 * self._marginWidth + 2*self._borderXWidth
+
+ else:
+
+ self._leftMarginWidth = ((self._leftMarginWidth > self._marginWidth + 2*self._borderXWidth) and \
+ [self._leftMarginWidth] or [self._marginWidth + 2*self._borderXWidth])[0]
+
+ menuItemWidth = self.GetLeftMarginWidth() + 2*self.GetBorderXWidth() + width + self.GetRightMarginWidth()
+ self._textX = self._imgMarginX + self._marginWidth + self._textPadding
+
+ # update the rightMargin X position
+ self._rightMarginPosX = ((self._textX + width + self._accelWidth> self._rightMarginPosX) and \
+ [self._textX + width + self._accelWidth] or [self._rightMarginPosX])[0]
+
+ return menuItemWidth
+
+
+ def GetMenuWidth(self):
+ """ Returns the menu width in pixels. """
+
+ return self._menuWidth
+
+
+ def GetLeftMarginWidth(self):
+ """ Returns the menu left margin width, in pixels. """
+
+ return self._leftMarginWidth
+
+
+ def GetRightMarginWidth(self):
+ """ Returns the menu right margin width, in pixels. """
+
+ return self._rightMarginWidth
+
+
+ def GetBorderXWidth(self):
+ """ Returns the menu border x-width, in pixels. """
+
+ return self._borderXWidth
+
+
+ def GetBorderYWidth(self):
+ """ Returns the menu border y-width, in pixels. """
+
+ return self._borderYWidth
+
+
+ def GetItemHeight(self):
+ """ Returns the height of a particular item, in pixels. """
+
+ return self._itemHeight
+
+
+ def AppendCheckItem(self, id, item, helpString=""):
+ """
+ Adds a checkable item to the end of the menu.
+
+ :see: :meth:`~FlatMenu.Append` for the explanation of the input parameters.
+ """
+
+ newItem = FlatMenuItem(self, id, item, helpString, wx.ITEM_CHECK)
+ return self.AppendItem(newItem)
+
+
+ def AppendRadioItem(self, id, item, helpString=""):
+ """
+ Adds a radio item to the end of the menu.
+
+ All consequent radio items form a group and when an item in the group is
+ checked, all the others are automatically unchecked.
+
+ :see: :meth:`~FlatMenu.Append` for the explanation of the input parameters.
+ """
+
+ newItem = FlatMenuItem(self, id, item, helpString, wx.ITEM_RADIO)
+ return self.AppendItem(newItem)
+
+
+ def AppendSeparator(self):
+ """ Appends a separator item to the end of this menu. """
+
+ newItem = FlatMenuItem(self)
+ return self.AppendItem(newItem)
+
+
+ def InsertSeparator(self, pos):
+ """
+ Inserts a separator at the given position.
+
+ :param integer `pos`: the index at which we want to insert the separator.
+ """
+
+ newItem = FlatMenuItem(self)
+ return self.InsertItem(pos, newItem)
+
+
+ def Dismiss(self, dismissParent, resetOwner):
+ """
+ Dismisses the popup window.
+
+ :param bool `dismissParent`: whether to dismiss the parent menu or not;
+ :param bool `resetOwner`: ``True`` to delete the link between this menu and the
+ owner menu, ``False`` otherwise.
+ """
+
+ if self._activeWin:
+
+ self._activeWin.PopEventHandler(True)
+ self._activeWin = None
+
+ if self._focusWin:
+
+ self._focusWin.PopEventHandler(True)
+ self._focusWin = None
+
+ self._selectedItem = -1
+
+ if self._mb:
+ self._mb.RemoveHelp()
+
+ FlatMenuBase.Dismiss(self, dismissParent, resetOwner)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.PaintDC(self)
+ self.GetRenderer().DrawMenu(self, dc)
+
+ # We need to redraw all our child menus
+ self.RefreshChilds()
+
+
+ def UpdateItem(self, item):
+ """
+ Updates an item.
+
+ :param `item`: an instance of :class:`FlatMenuItem`.
+ """
+
+ # notify menu bar that an item was modified directly
+ if item and self._mb:
+ self._mb.UpdateItem(item)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to avoid flicker.
+ """
+
+ pass
+
+
+ def DrawSelection(self, dc, oldSelection=-1):
+ """
+ Redraws the menu.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param integer `oldSelection`: if non-negative, the index representing the previous selected
+ menu item.
+ """
+
+ self.Refresh()
+
+
+ def RefreshChilds(self):
+ """
+ In some cases, we need to perform a recursive refresh for all opened submenu
+ from this.
+ """
+
+ # Draw all childs menus of self menu as well
+ child = self._openedSubMenu
+ while child:
+ dc = wx.ClientDC(child)
+ self.GetRenderer().DrawMenu(child, dc)
+ child = child._openedSubMenu
+
+
+ def GetMenuRect(self):
+ """ Returns the menu client rectangle. """
+
+ clientRect = self.GetClientRect()
+ return wx.Rect(clientRect.x, clientRect.y, clientRect.width, clientRect.height)
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ self.OnChar(event.GetKeyCode())
+
+
+ def OnChar(self, key):
+ """
+ Handles key events for :class:`FlatMenu`.
+
+ :param `key`: the keyboard key integer code.
+ """
+
+ processed = True
+
+ if key == wx.WXK_ESCAPE:
+
+ if self._parentMenu:
+ self._parentMenu.CloseSubMenu(-1)
+ else:
+ self.Dismiss(True, True)
+
+ elif key == wx.WXK_LEFT:
+
+ if self._parentMenu:
+ # We are a submenu, dismiss us.
+ self._parentMenu.CloseSubMenu(-1)
+ else:
+ # try to find our root menu, if we are attached to menubar,
+ # let it try and open the previous menu
+ root = self.GetRootMenu()
+ if root:
+ if root._mb:
+ root._mb.ActivatePreviousMenu()
+
+ elif key == wx.WXK_RIGHT:
+
+ if not self.TryOpenSubMenu(self._selectedItem, True):
+ # try to find our root menu, if we are attached to menubar,
+ # let it try and open the previous menu
+ root = self.GetRootMenu()
+ if root:
+ if root._mb:
+ root._mb.ActivateNextMenu()
+
+ elif key == wx.WXK_UP:
+ self.AdvanceSelection(False)
+
+ elif key == wx.WXK_DOWN:
+
+ self.AdvanceSelection()
+
+ elif key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
+ self.DoAction(self._selectedItem)
+
+ elif key == wx.WXK_HOME:
+
+ # Select first item of the menu
+ if self._selectedItem != 0:
+ oldSel = self._selectedItem
+ self._selectedItem = 0
+ dc = wx.ClientDC(self)
+ self.DrawSelection(dc, oldSel)
+
+ elif key == wx.WXK_END:
+
+ # Select last item of the menu
+ if self._selectedItem != len(self._itemsArr)-1:
+ oldSel = self._selectedItem
+ self._selectedItem = len(self._itemsArr)-1
+ dc = wx.ClientDC(self)
+ self.DrawSelection(dc, oldSel)
+
+ elif key in [wx.WXK_CONTROL, wx.WXK_ALT]:
+ # Alt was pressed
+ root = self.GetRootMenu()
+ root.Dismiss(False, True)
+
+ else:
+ try:
+ chrkey = chr(key)
+ except:
+ return processed
+
+ if chrkey.isalnum():
+
+ ch = chrkey.lower()
+
+ # Iterate over all the menu items
+ itemIdx = -1
+ occur = 0
+
+ for i in xrange(len(self._itemsArr)):
+
+ item = self._itemsArr[i]
+ mnemonic = item.GetMnemonicChar()
+
+ if mnemonic == ch:
+
+ if itemIdx == -1:
+
+ itemIdx = i
+ # We keep the index of only
+ # the first occurence
+
+ occur += 1
+
+ # Keep on looping until no more items for self menu
+
+ if itemIdx != -1:
+
+ if occur > 1:
+
+ # We select the first item
+ if self._selectedItem == itemIdx:
+ return processed
+
+ oldSel = self._selectedItem
+ self._selectedItem = itemIdx
+ dc = wx.ClientDC(self)
+ self.DrawSelection(dc, oldSel)
+
+ elif occur == 1:
+
+ # Activate the item, if self is a submenu item we first select it
+ item = self._itemsArr[itemIdx]
+ if item.IsSubMenu() and self._selectedItem != itemIdx:
+
+ oldSel = self._selectedItem
+ self._selectedItem = itemIdx
+ dc = wx.ClientDC(self)
+ self.DrawSelection(dc, oldSel)
+
+ self.DoAction(itemIdx)
+
+ else:
+
+ processed = False
+
+ return processed
+
+
+ def AdvanceSelection(self, down=True):
+ """
+ Advance forward or backward the current selection.
+
+ :param bool `down`: ``True`` to advance the selection forward, ``False`` otherwise.
+ """
+
+ # make sure we have at least two items in the menu (which are not
+ # separators)
+ num=0
+ singleItemIdx = -1
+
+ for i in xrange(len(self._itemsArr)):
+
+ item = self._itemsArr[i]
+ if item.IsSeparator():
+ continue
+ num += 1
+ singleItemIdx = i
+
+ if num < 1:
+ return
+
+ if num == 1:
+ # Select the current one
+ self._selectedItem = singleItemIdx
+ dc = wx.ClientDC(self)
+ self.DrawSelection(dc, -1)
+ return
+
+ oldSelection = self._selectedItem
+
+ if not down:
+
+ # find the next valid item
+ while 1:
+
+ self._selectedItem -= 1
+ if self._selectedItem < 0:
+ self._selectedItem = len(self._itemsArr)-1
+ if not self._itemsArr[self._selectedItem].IsSeparator():
+ break
+
+ else:
+
+ # find the next valid item
+ while 1:
+
+ self._selectedItem += 1
+ if self._selectedItem > len(self._itemsArr)-1:
+ self._selectedItem = 0
+ if not self._itemsArr[self._selectedItem].IsSeparator():
+ break
+
+ dc = wx.ClientDC(self)
+ self.DrawSelection(dc, oldSelection)
+
+
+ def HitTest(self, pos):
+ """
+ HitTest method for :class:`FlatMenu`.
+
+ :param `pos`: an instance of :class:`Point`, a point to test for hits.
+
+ :return: A tuple representing one of the following combinations:
+
+ ========================= ==================================================
+ Return Tuple Description
+ ========================= ==================================================
+ (0, -1) The :meth:`~FlatMenu.HitTest` method didn't find any item with the specified input point `pt` (``MENU_HT_NONE`` = 0)
+ (1, `integer`) A menu item has been hit (``MENU_HT_ITEM`` = 1)
+ (2, -1) The `Scroll Up` button has been hit (``MENU_HT_SCROLL_UP`` = 2)
+ (3, -1) The `Scroll Down` button has been hit (``MENU_HT_SCROLL_DOWN`` = 3)
+ ========================= ==================================================
+
+ """
+
+ if self._showScrollButtons:
+
+ if self._upButton and self._upButton.GetClientRect().Contains(pos):
+ return MENU_HT_SCROLL_UP, -1
+
+ if self._downButton and self._downButton.GetClientRect().Contains(pos):
+ return MENU_HT_SCROLL_DOWN, -1
+
+ for ii, item in enumerate(self._itemsArr):
+
+ if item.GetRect().Contains(pos) and item.IsEnabled() and item.IsShown():
+ return MENU_HT_ITEM, ii
+
+ return MENU_HT_NONE, -1
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if "__WXMSW__" in wx.Platform:
+ # Ignore dummy mouse move events
+ pt = wx.GetMousePosition()
+ if self._mousePtAtStartup == pt:
+ return
+
+ pos = event.GetPosition()
+
+ # we need to ignore extra mouse events: example when this happens is when
+ # the mouse is on the menu and we open a submenu from keyboard - Windows
+ # then sends us a dummy mouse move event, we (correctly) determine that it
+ # happens in the parent menu and so immediately close the just opened
+ # submenunot
+
+ if "__WXMSW__" in wx.Platform:
+
+ ptCur = self.ClientToScreen(pos)
+ if ptCur == self._ptLast:
+ return
+
+ self._ptLast = ptCur
+
+ # first let the scrollbar handle it
+ self.TryScrollButtons(event)
+ self.ProcessMouseMove(pos)
+
+
+ def OnMouseLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.TryScrollButtons(event):
+ return
+
+ pos = event.GetPosition()
+ self.ProcessMouseLClick(pos)
+
+
+ def OnMouseLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.TryScrollButtons(event):
+ return
+
+ pos = event.GetPosition()
+ rect = self.GetClientRect()
+
+ if not rect.Contains(pos):
+
+ # The event is not in our coords,
+ # so we try our parent
+ win = self._parentMenu
+
+ while win:
+
+ # we need to translate our client coords to the client coords of the
+ # window we forward this event to
+ ptScreen = self.ClientToScreen(pos)
+ p = win.ScreenToClient(ptScreen)
+
+ if win.GetClientRect().Contains(p):
+
+ event.SetX(p.x)
+ event.SetY(p.y)
+ win.OnMouseLeftUp(event)
+ return
+
+ else:
+ # try the grandparent
+ win = win._parentMenu
+
+ else:
+ self.ProcessMouseLClickEnd(pos)
+
+ if self._showScrollButtons:
+
+ if self._upButton:
+ self._upButton.ProcessLeftUp(pos)
+ if self._downButton:
+ self._downButton.ProcessLeftUp(pos)
+
+
+ def OnMouseRightDown(self, event):
+ """
+ Handles the ``wx.EVT_RIGHT_DOWN`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.TryScrollButtons(event):
+ return
+
+ pos = event.GetPosition()
+ self.ProcessMouseRClick(pos)
+
+
+ def ProcessMouseRClick(self, pos):
+ """
+ Processes mouse right clicks.
+
+ :param `pos`: the position at which the mouse right button was pressed,
+ an instance of :class:`Point`.
+ """
+
+ rect = self.GetClientRect()
+
+ if not rect.Contains(pos):
+
+ # The event is not in our coords,
+ # so we try our parent
+
+ win = self._parentMenu
+ while win:
+
+ # we need to translate our client coords to the client coords of the
+ # window we forward self event to
+ ptScreen = self.ClientToScreen(pos)
+ p = win.ScreenToClient(ptScreen)
+
+ if win.GetClientRect().Contains(p):
+ win.ProcessMouseRClick(p)
+ return
+
+ else:
+ # try the grandparent
+ win = win._parentMenu
+
+ # At this point we can assume that the event was not
+ # processed, so we dismiss the menu and its children
+ self.Dismiss(True, True)
+ return
+
+ # test if we are on a menu item
+ res, itemIdx = self.HitTest(pos)
+ if res == MENU_HT_ITEM:
+ self.OpenItemContextMenu(itemIdx)
+
+
+ def OpenItemContextMenu(self, itemIdx):
+ """
+ Open an item's context menu (if any).
+
+ :param integer `itemIdx`: the index of the item for which we want to open the context menu.
+ """
+
+ item = self._itemsArr[itemIdx]
+ context_menu = item.GetContextMenu()
+
+ # If we have a context menu, close any opened submenu
+ if context_menu:
+ self.CloseSubMenu(itemIdx, True)
+
+ if context_menu and not context_menu.IsShown():
+ # Popup child menu
+ pos = wx.Point()
+ pos.x = item.GetRect().GetWidth() + item.GetRect().GetX() - 5
+ pos.y = item.GetRect().GetY()
+ self._clearCurrentSelection = False
+ self._openedSubMenu = context_menu
+ context_menu.Popup(self.ScreenToClient(wx.GetMousePosition()), self._owner, self)
+ return True
+
+ return False
+
+
+ def ProcessMouseLClick(self, pos):
+ """
+ Processes mouse left clicks.
+
+ :param `pos`: the position at which the mouse left button was pressed,
+ an instance of :class:`Point`.
+ """
+
+ rect = self.GetClientRect()
+
+ if not rect.Contains(pos):
+
+ # The event is not in our coords,
+ # so we try our parent
+
+ win = self._parentMenu
+ while win:
+
+ # we need to translate our client coords to the client coords of the
+ # window we forward self event to
+ ptScreen = self.ClientToScreen(pos)
+ p = win.ScreenToClient(ptScreen)
+
+ if win.GetClientRect().Contains(p):
+ win.ProcessMouseLClick(p)
+ return
+
+ else:
+ # try the grandparent
+ win = win._parentMenu
+
+ # At this point we can assume that the event was not
+ # processed, so we dismiss the menu and its children
+ self.Dismiss(True, True)
+ return
+
+
+ def ProcessMouseLClickEnd(self, pos):
+ """
+ Processes mouse left clicks.
+
+ :param `pos`: the position at which the mouse left button was pressed,
+ an instance of :class:`Point`.
+ """
+
+ self.ProcessMouseLClick(pos)
+
+ # test if we are on a menu item
+ res, itemIdx = self.HitTest(pos)
+
+ if res == MENU_HT_ITEM:
+ self.DoAction(itemIdx)
+
+ elif res == MENU_HT_SCROLL_UP:
+ if self._upButton:
+ self._upButton.ProcessLeftDown(pos)
+
+ elif res == MENU_HT_SCROLL_DOWN:
+ if self._downButton:
+ self._downButton.ProcessLeftDown(pos)
+
+ else:
+ self._selectedItem = -1
+
+
+ def ProcessMouseMove(self, pos):
+ """
+ Processes mouse movements.
+
+ :param `pos`: the position at which the mouse was moved, an instance of :class:`Point`.
+ """
+
+ rect = self.GetClientRect()
+
+ if not rect.Contains(pos):
+
+ # The event is not in our coords,
+ # so we try our parent
+
+ win = self._parentMenu
+ while win:
+
+ # we need to translate our client coords to the client coords of the
+ # window we forward self event to
+ ptScreen = self.ClientToScreen(pos)
+ p = win.ScreenToClient(ptScreen)
+
+ if win.GetClientRect().Contains(p):
+ win.ProcessMouseMove(p)
+ return
+
+ else:
+ # try the grandparent
+ win = win._parentMenu
+
+ # If we are attached to a menu bar,
+ # let him process the event as well
+ if self._mb:
+
+ ptScreen = self.ClientToScreen(pos)
+ p = self._mb.ScreenToClient(ptScreen)
+
+ if self._mb.GetClientRect().Contains(p):
+
+ # let the menu bar process it
+ self._mb.ProcessMouseMoveFromMenu(p)
+ return
+
+ if self._mb_submenu:
+ ptScreen = self.ClientToScreen(pos)
+ p = self._mb_submenu.ScreenToClient(ptScreen)
+ if self._mb_submenu.GetClientRect().Contains(p):
+ # let the menu bar process it
+ self._mb_submenu.ProcessMouseMoveFromMenu(p)
+ return
+
+ return
+
+ # test if we are on a menu item
+ res, itemIdx = self.HitTest(pos)
+
+ if res == MENU_HT_SCROLL_DOWN:
+
+ if self._downButton:
+ self._downButton.ProcessMouseMove(pos)
+
+ elif res == MENU_HT_SCROLL_UP:
+
+ if self._upButton:
+ self._upButton.ProcessMouseMove(pos)
+
+ elif res == MENU_HT_ITEM:
+
+ if self._downButton:
+ self._downButton.ProcessMouseMove(pos)
+
+ if self._upButton:
+ self._upButton.ProcessMouseMove(pos)
+
+ if self._selectedItem == itemIdx:
+ return
+
+ # Message to send when out of last selected item
+ if self._selectedItem != -1:
+ self.SendOverItem(self._selectedItem, False)
+ self.SendOverItem(itemIdx, True) # Message to send when over an item
+
+ oldSelection = self._selectedItem
+ self._selectedItem = itemIdx
+ self.CloseSubMenu(self._selectedItem)
+
+ dc = wx.ClientDC(self)
+ self.DrawSelection(dc, oldSelection)
+
+ self.TryOpenSubMenu(self._selectedItem)
+
+ if self._mb:
+ self._mb.RemoveHelp()
+ if itemIdx >= 0:
+ self._mb.DoGiveHelp(self._itemsArr[itemIdx])
+
+ else:
+
+ # Message to send when out of last selected item
+ if self._selectedItem != -1:
+ item = self._itemsArr[self._selectedItem]
+ if item.IsSubMenu() and item.GetSubMenu().IsShown():
+ return
+
+ # Message to send when out of last selected item
+ if self._selectedItem != -1:
+ self.SendOverItem(self._selectedItem, False)
+
+ oldSelection = self._selectedItem
+ self._selectedItem = -1
+ dc = wx.ClientDC(self)
+ self.DrawSelection(dc, oldSelection)
+
+
+ def OnMouseLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._mb:
+ self._mb.RemoveHelp()
+
+ if self._clearCurrentSelection:
+
+ # Message to send when out of last selected item
+ if self._selectedItem != -1:
+ item = self._itemsArr[self._selectedItem]
+ if item.IsSubMenu() and item.GetSubMenu().IsShown():
+ return
+
+ # Message to send when out of last selected item
+ if self._selectedItem != -1:
+ self.SendOverItem(self._selectedItem, False)
+
+ oldSelection = self._selectedItem
+ self._selectedItem = -1
+ dc = wx.ClientDC(self)
+ self.DrawSelection(dc, oldSelection)
+
+ self._clearCurrentSelection = True
+
+ if "__WXMSW__" in wx.Platform:
+ self.SetCursor(self._oldCur)
+
+
+ def OnMouseEnterWindow(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if "__WXMSW__" in wx.Platform:
+ self._oldCur = self.GetCursor()
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+
+ event.Skip()
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self.Dismiss(True, True)
+
+
+ def CloseSubMenu(self, itemIdx, alwaysClose=False):
+ """
+ Closes a child sub-menu.
+
+ :param integer `itemIdx`: the index of the item for which we want to close the submenu;
+ :param bool `alwaysClose`: if ``True``, always close the submenu irrespectively of
+ other conditions.
+ """
+
+ item = None
+ subMenu = None
+
+ if itemIdx >= 0 and itemIdx < len(self._itemsArr):
+ item = self._itemsArr[itemIdx]
+
+ # Close sub-menu first
+ if item:
+ subMenu = item.GetSubMenu()
+
+ if self._openedSubMenu:
+ if self._openedSubMenu != subMenu or alwaysClose:
+ # We have another sub-menu open, close it
+ self._openedSubMenu.Dismiss(False, True)
+ self._openedSubMenu = None
+
+
+ def DoAction(self, itemIdx):
+ """
+ Performs an action based on user selection.
+
+ :param integer `itemIdx`: the index of the item for which we want to perform the action.
+ """
+
+ if itemIdx < 0 or itemIdx >= len(self._itemsArr):
+ raise Exception("Invalid menu item")
+ return
+
+ item = self._itemsArr[itemIdx]
+
+ if not item.IsEnabled() or item.IsSeparator():
+ return
+
+ # Close sub-menu if needed
+ self.CloseSubMenu(itemIdx)
+
+ if item.IsSubMenu() and not item.GetSubMenu().IsShown():
+
+ # Popup child menu
+ self.TryOpenSubMenu(itemIdx)
+ return
+
+ if item.IsRadioItem():
+ # if the radio item is already checked,
+ # just send command event. Else, check it, uncheck the current
+ # checked item in the radio item group, and send command event
+ if not item.IsChecked():
+ item._groupPtr.SetSelection(item)
+
+ elif item.IsCheckable():
+
+ item.Check(not item.IsChecked())
+ dc = wx.ClientDC(self)
+ self.DrawSelection(dc)
+
+ if not item.IsSubMenu():
+
+ self.Dismiss(True, False)
+
+ # Send command event
+ self.SendCmdEvent(itemIdx)
+
+
+ def TryOpenSubMenu(self, itemIdx, selectFirst=False):
+ """
+ If `itemIdx` is an item with submenu, open it.
+
+ :param integer `itemIdx`: the index of the item for which we want to open the submenu;
+ :param bool `selectFirst`: if ``True``, the first item of the submenu will be shown
+ as selected.
+ """
+
+ if itemIdx < 0 or itemIdx >= len(self._itemsArr):
+ return False
+
+ item = self._itemsArr[itemIdx]
+ if item.IsSubMenu() and not item.GetSubMenu().IsShown():
+
+ pos = wx.Point()
+
+ # Popup child menu
+ pos.x = item.GetRect().GetWidth()+ item.GetRect().GetX()-5
+ pos.y = item.GetRect().GetY()
+ self._clearCurrentSelection = False
+ self._openedSubMenu = item.GetSubMenu()
+ item.GetSubMenu().Popup(pos, self._owner, self)
+
+ # Select the first child
+ if selectFirst:
+
+ dc = wx.ClientDC(item.GetSubMenu())
+ item.GetSubMenu()._selectedItem = 0
+ item.GetSubMenu().DrawSelection(dc)
+
+ return True
+
+ return False
+
+
+ def _RemoveById(self, id):
+ """ Used internally. """
+
+ # First we search for the menu item (recursively)
+ menuParent = None
+ item = None
+ idx = wx.NOT_FOUND
+ idx, menuParent = self.FindMenuItemPos(id)
+
+ if idx != wx.NOT_FOUND:
+
+ # Remove the menu item
+ item = menuParent._itemsArr[idx]
+ menuParent._itemsArr.pop(idx)
+
+ # update group
+ if item._groupPtr and item.IsRadioItem():
+ item._groupPtr.Remove(item)
+
+ # Resize the menu
+ menuParent.ResizeMenu()
+
+ return item
+
+
+ def Remove(self, item):
+ """
+ Removes the menu item from the menu but doesn't delete the associated menu
+ object. This allows to reuse the same item later by adding it back to the
+ menu (especially useful with submenus).
+
+ :param `item`: can be either a menu item identifier or a plain :class:`FlatMenuItem`.
+ """
+
+ if type(item) != type(1):
+ item = item.GetId()
+
+ return self._RemoveById(item)
+
+ Delete = Remove
+
+
+ def _DestroyById(self, id):
+ """ Used internally. """
+
+ item = None
+ item = self.Remove(id)
+
+ if item:
+ del item
+
+
+ def Destroy(self, item):
+ """
+ Deletes the menu item from the menu. If the item is a submenu, it will be
+ deleted. Use :meth:`~FlatMenu.Remove` if you want to keep the submenu (for example, to reuse
+ it later).
+
+ :param `item`: can be either a menu item identifier or a plain :class:`FlatMenuItem`.
+ """
+
+ if type(item) != type(1):
+ item = item.GetId()
+
+ self._DestroyById(item)
+
+
+ def Insert(self, pos, id, item, helpString="", kind=wx.ITEM_NORMAL):
+ """
+ Inserts the given `item` before the position `pos`.
+
+ :param integer `pos`: the position at which to insert the new menu item;
+ :param integer `id`: the menu item identifier;
+ :param string `item`: the string to appear on the menu item;
+ :param string `helpString`: an optional help string associated with the item. By default,
+ the handler for the ``EVT_FLAT_MENU_ITEM_MOUSE_OVER`` event displays this string
+ in the status line;
+ :param integer `kind`: may be ``wx.ITEM_NORMAL`` for a normal button (default),
+ ``wx.ITEM_CHECK`` for a checkable tool (such tool stays pressed after it had been
+ toggled) or ``wx.ITEM_RADIO`` for a checkable tool which makes part of a radio
+ group of tools each of which is automatically unchecked whenever another button
+ in the group is checked;
+ """
+
+ newitem = FlatMenuItem(self, id, item, helpString, kind)
+ return self.InsertItem(pos, newitem)
+
+
+ def InsertItem(self, pos, item):
+ """
+ Inserts an item into the menu.
+
+ :param integer `pos`: the position at which to insert the new menu item;
+ :param `item`: an instance of :class:`FlatMenuItem`.
+ """
+
+ if pos == len(self._itemsArr):
+ # Append it
+ return self.AppendItem(item)
+
+ # Insert the menu item
+ self._itemsArr.insert(pos, item)
+ item._isAttachedToMenu = True
+
+ # Recalculate the menu geometry
+ self.ResizeMenu()
+
+ # Update radio groups
+ self.UpdateRadioGroup(item)
+
+ return item
+
+
+ def UpdateRadioGroup(self, item):
+ """
+ Updates a group of radio items.
+
+ :param `item`: an instance of :class:`FlatMenuItem`.
+ """
+
+ if item.IsRadioItem():
+
+ # Udpate radio groups in case this item is a radio item
+ sibling = self.GetSiblingGroupItem(item)
+ if sibling:
+
+ item._groupPtr = sibling._groupPtr
+ item._groupPtr.Add(item)
+
+ if item.IsChecked():
+
+ item._groupPtr.SetSelection(item)
+
+ else:
+
+ # first item in group
+ item._groupPtr = FlatMenuItemGroup()
+ item._groupPtr.Add(item)
+ item._groupPtr.SetSelection(item)
+
+
+ def ResizeMenu(self):
+ """ Resizes the menu to the correct size. """
+
+ # can we do the resize?
+ if not self._resizeMenu:
+ return
+
+ items = self._itemsArr
+ self._itemsArr = []
+
+ # Clear accelerator table
+ self._accelArray = []
+
+ # Reset parameters and menu size
+ self._menuWidth = 2*self._marginWidth
+ self._imgMarginX = 0
+ self._markerMarginX = 0
+ self._textX = self._marginWidth
+ self._rightMarginPosX = -1
+ self._itemHeight = self._marginHeight
+ self.SetSize(wx.Size(self._menuWidth*self._numCols, self._itemHeight+4))
+
+ # Now we simply add the items
+ for item in items:
+ self.AppendItem(item)
+
+
+ def SetNumberColumns(self, numCols):
+ """
+ Sets the number of columns for a menu window.
+
+ :param integer `numCols`: the number of columns for this :class:`FlatMenu` window.
+ """
+
+ if self._numCols == numCols:
+ return
+
+ self._numCols = numCols
+ self.ResizeMenu()
+ self.Refresh()
+
+
+ def GetNumberColumns(self):
+ """ Returns the number of columns for a menu window. """
+
+ return self._numCols
+
+
+ def FindItem(self, itemId, menu=None):
+ """
+ Finds the menu item object associated with the given menu item identifier and,
+ optionally, the (sub)menu it belongs to.
+
+ :param integer `itemId`: menu item identifier;
+ :param `menu`: if not ``None``, it will be filled with the item's parent menu
+ (if the item was found).
+
+ :return: The found menu item object, or ``None`` if one was not found.
+ """
+
+ idx = wx.NOT_FOUND
+
+ if menu:
+
+ idx, menu = self.FindMenuItemPos(itemId, menu)
+ if idx != wx.NOT_FOUND:
+ return menu._itemsArr[idx]
+ else:
+ return None
+
+ else:
+
+ idx, parentMenu = self.FindMenuItemPos(itemId, None)
+ if idx != wx.NOT_FOUND:
+ return parentMenu._itemsArr[idx]
+ else:
+ return None
+
+
+ def SetItemFont(self, itemId, font=None):
+ """
+ Sets the :class:`FlatMenuItem` font.
+
+ :param integer `itemId`: the menu item identifier;
+ :param `font`: an instance of a valid :class:`Font`.
+ """
+
+ item = self.FindItem(itemId)
+ item.SetFont(font)
+
+
+ def GetItemFont(self, itemId):
+ """
+ Returns this :class:`FlatMenuItem` font.
+
+ :param integer `itemId`: the menu item identifier.
+ """
+
+ item = self.FindItem(itemId)
+ return item.GetFont()
+
+
+ def SetItemTextColour(self, itemId, colour=None):
+ """
+ Sets the :class:`FlatMenuItem` foreground text colour.
+
+ :param integer `itemId`: the menu item identifier;
+ :param `colour`: an instance of a valid :class:`Colour`.
+ """
+
+ item = self.FindItem(itemId)
+ item.SetTextColour(colour)
+
+
+ def GetItemTextColour(self, itemId):
+ """
+ Returns this :class:`FlatMenuItem` foreground text colour.
+
+ :param integer `itemId`: the menu item identifier.
+ """
+
+ item = self.FindItem(itemId)
+ return item.GetTextColour()
+
+
+ def SetLabel(self, itemId, label):
+ """
+ Sets the label of a :class:`FlatMenuItem`.
+
+ :param integer `itemId`: the menu item identifier;
+ :param string `label`: the menu item label to set.
+
+ :see: :meth:`~FlatMenu.GetLabel`.
+ """
+
+ item = self.FindItem(itemId)
+ item.SetLabel(label)
+ item.SetText(label)
+
+ self.ResizeMenu()
+
+
+ def GetLabel(self, itemId):
+ """
+ Returns the label of a :class:`FlatMenuItem`.
+
+ :param integer `id`: the menu item identifier;
+
+ :see: :meth:`~FlatMenu.SetLabel`.
+ """
+
+ item = self.FindItem(itemId)
+ return item.GetText()
+
+
+ def FindMenuItemPos(self, itemId, menu=None):
+ """
+ Finds an item and its position inside the menu based on its id.
+
+ :param integer `itemId`: menu item identifier;
+ :param `menu`: if not ``None``, it will be filled with the item's parent menu
+ (if the item was found).
+
+ :return: The found menu item object, or ``None`` if one was not found.
+ """
+
+ menu = None
+ item = None
+
+ idx = wx.NOT_FOUND
+
+ for i in xrange(len(self._itemsArr)):
+
+ item = self._itemsArr[i]
+
+ if item.GetId() == itemId:
+
+ menu = self
+ idx = i
+ break
+
+ elif item.IsSubMenu():
+
+ idx, menu = item.GetSubMenu().FindMenuItemPos(itemId, menu)
+ if idx != wx.NOT_FOUND:
+ break
+
+ else:
+
+ item = None
+
+ return idx, menu
+
+
+ def GetAccelTable(self):
+ """ Returns the menu accelerator table, an instance of :class:`AcceleratorTable`. """
+
+ n = len(self._accelArray)
+ if n == 0:
+ return wx.NullAcceleratorTable
+
+ entries = [wx.AcceleratorEntry() for ii in xrange(n)]
+
+ for counter in len(entries):
+ entries[counter] = self._accelArray[counter]
+
+ table = wx.AcceleratorTable(entries)
+ del entries
+
+ return table
+
+
+ def GetMenuItemCount(self):
+ """ Returns the number of items in the :class:`FlatMenu`. """
+
+ return len(self._itemsArr)
+
+
+ def GetAccelArray(self):
+ """ Returns a list filled with the accelerator entries for the menu. """
+
+ return self._accelArray
+
+
+ # events
+ def SendCmdEvent(self, itemIdx):
+ """
+ Actually sends menu command events.
+
+ :param integer `itemIdx`: the menu item index for which we want to send a command event.
+ """
+
+ if itemIdx < 0 or itemIdx >= len(self._itemsArr):
+ raise Exception("Invalid menu item")
+ return
+
+ item = self._itemsArr[itemIdx]
+
+ # Create the event
+ event = wx.CommandEvent(wxEVT_FLAT_MENU_SELECTED, item.GetId())
+
+ # For checkable item, set the IsChecked() value
+ if item.IsCheckable():
+ event.SetInt((item.IsChecked() and [1] or [0])[0])
+
+ event.SetEventObject(self)
+
+ if self._owner:
+ self._owner.GetEventHandler().ProcessEvent(event)
+ else:
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def SendOverItem(self, itemIdx, over):
+ """
+ Sends the ``EVT_FLAT_MENU_ITEM_MOUSE_OVER`` and ``EVT_FLAT_MENU_ITEM_MOUSE_OUT``
+ events.
+
+ :param integer `itemIdx`: the menu item index for which we want to send an event;
+ :param bool `over`: ``True`` to send a ``EVT_FLAT_MENU_ITEM_MOUSE_OVER`` event, ``False`` to
+ send a ``EVT_FLAT_MENU_ITEM_MOUSE_OUT`` event.
+ """
+
+ item = self._itemsArr[itemIdx]
+
+ # Create the event
+ event = FlatMenuEvent((over and [wxEVT_FLAT_MENU_ITEM_MOUSE_OVER] or [wxEVT_FLAT_MENU_ITEM_MOUSE_OUT])[0], item.GetId())
+
+ # For checkable item, set the IsChecked() value
+ if item.IsCheckable():
+ event.SetInt((item.IsChecked() and [1] or [0])[0])
+
+ event.SetEventObject(self)
+
+ if self._owner:
+ self._owner.GetEventHandler().ProcessEvent(event)
+ else:
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def SendUIEvent(self, itemIdx):
+ """
+ Actually sends menu UI events.
+
+ :param integer `itemIdx`: the menu item index for which we want to send a UI event.
+ """
+
+ if itemIdx < 0 or itemIdx >= len(self._itemsArr):
+ raise Exception("Invalid menu item")
+ return
+
+ item = self._itemsArr[itemIdx]
+ event = wx.UpdateUIEvent(item.GetId())
+
+ event.Check(item.IsChecked())
+ event.Enable(item.IsEnabled())
+ event.SetText(item.GetText())
+ event.SetEventObject(self)
+
+ if self._owner:
+ self._owner.GetEventHandler().ProcessEvent(event)
+ else:
+ self.GetEventHandler().ProcessEvent(event)
+
+ item.Check(event.GetChecked())
+ item.SetLabel(event.GetText())
+ item.Enable(event.GetEnabled())
+
+
+ def Clear(self):
+ """ Clears the menu items. """
+
+ # since Destroy() call ResizeMenu(), we turn this flag on
+ # to avoid resizing the menu for every item removed
+ self._resizeMenu = False
+
+ lenItems = len(self._itemsArr)
+ for ii in xrange(lenItems):
+ self.Destroy(self._itemsArr[0].GetId())
+
+ # Now we can resize the menu
+ self._resizeMenu = True
+ self.ResizeMenu()
+
+
+ def FindMenuItemPosSimple(self, item):
+ """
+ Finds an item and its position inside the menu based on its id.
+
+ :param `item`: an instance of :class:`FlatMenuItem`.
+
+ :return: An integer specifying the index found menu item object, or
+ ``wx.NOT_FOUND`` if one was not found.
+ """
+
+ if item == None or len(self._itemsArr) == 0:
+ return wx.NOT_FOUND
+
+ for i in xrange(len(self._itemsArr)):
+ if self._itemsArr[i] == item:
+ return i
+
+ return wx.NOT_FOUND
+
+
+ def SetBackgroundBitmap(self, bitmap=None):
+ """
+ Sets a background bitmap for this particular :class:`FlatMenu`.
+
+ :param `bitmap`: an instance of :class:`Bitmap`. Set `bitmap` to ``None`` if you
+ wish to remove the background bitmap altogether.
+
+ :note: the bitmap is rescaled to fit the menu width and height.
+ """
+
+ self._originalBackgroundImage = bitmap
+ # Now we can resize the menu
+ self._resizeMenu = True
+ self.ResizeMenu()
+
+
+ def GetBackgroundBitmap(self):
+ """ Returns the background bitmap for this particular :class:`FlatMenu`, if any. """
+
+ return self._originalBackgroundImage
+
+
+ def GetAllItems(self, menu=None, items=[]):
+ """
+ Internal function to help recurse through all the menu items.
+
+ :param `menu`: the menu from which we start accumulating items;
+ :param list `items`: the array which is recursively filled with menu items.
+
+ :return: a list of :class:`FlatMenuItem`.
+ """
+
+ # first copy the current menu items
+ newitems = [item for item in items]
+
+ if not menu:
+ return newitems
+
+ # if any item in this menu has sub-menu, copy them as well
+ for i in xrange(len(menu._itemsArr)):
+ if menu._itemsArr[i].IsSubMenu():
+ newitems = self.GetAllItems(menu._itemsArr[i].GetSubMenu(), newitems)
+
+ return newitems
+
+
+ def GetSiblingGroupItem(self, item):
+ """
+ Used internally.
+
+ :param `item`: an instance of :class:`FlatMenuItem`.
+ """
+
+ pos = self.FindMenuItemPosSimple(item)
+ if pos in [wx.NOT_FOUND, 0]:
+ return None
+
+ if self._itemsArr[pos-1].IsRadioItem():
+ return self._itemsArr[pos-1]
+
+ return None
+
+
+ def ScrollDown(self):
+ """ Scrolls the menu down (for very tall menus). """
+
+ # increase the self._from index
+ if not self._itemsArr[-1].IsShown():
+ self._first += 1
+ self.Refresh()
+
+ return True
+
+ else:
+ if self._downButton:
+ self._downButton.GetTimer().Stop()
+
+ return False
+
+
+ def ScrollUp(self):
+ """ Scrolls the menu up (for very tall menus). """
+
+ if self._first == 0:
+ if self._upButton:
+ self._upButton.GetTimer().Stop()
+
+ return False
+
+ else:
+
+ self._first -= 1
+ self.Refresh()
+ return True
+
+
+ # Not used anymore
+ def TryScrollButtons(self, event):
+ """ Used internally. """
+
+ return False
+
+
+ def OnTimer(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`FlatMenu`.
+
+ :param `event`: a :class:`TimerEvent` event to be processed.
+ """
+
+ if self._upButton and self._upButton.GetTimerId() == event.GetId():
+
+ self.ScrollUp()
+
+ elif self._downButton and self._downButton.GetTimerId() == event.GetId():
+
+ self.ScrollDown()
+
+ else:
+
+ event.Skip()
+
+
+#--------------------------------------------------------
+# Class MenuKbdRedirector
+#--------------------------------------------------------
+
+class MenuKbdRedirector(wx.EvtHandler):
+ """ A keyboard event handler. """
+
+ def __init__(self, menu, oldHandler):
+ """
+ Default class constructor.
+
+ :param `menu`: an instance of :class:`FlatMenu` for which we want to redirect
+ keyboard inputs;
+ :param `oldHandler`: a previous (if any) :class:`EvtHandler` associated with
+ the menu.
+ """
+
+ self._oldHandler = oldHandler
+ self.SetMenu(menu)
+ wx.EvtHandler.__init__(self)
+
+
+ def SetMenu(self, menu):
+ """
+ Sets the listener menu.
+
+ :param `menu`: an instance of :class:`FlatMenu`.
+ """
+
+ self._menu = menu
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes the inout event.
+
+ :param `event`: any kind of keyboard-generated events.
+ """
+
+ if event.GetEventType() in [wx.EVT_KEY_DOWN, wx.EVT_CHAR, wx.EVT_CHAR_HOOK]:
+ return self._menu.OnChar(event.GetKeyCode())
+ else:
+ return self._oldHandler.ProcessEvent(event)
+
+
+#--------------------------------------------------------
+# Class FocusHandler
+#--------------------------------------------------------
+
+class FocusHandler(wx.EvtHandler):
+ """ A focus event handler. """
+
+ def __init__(self, menu):
+ """
+ Default class constructor.
+
+ :param `menu`: an instance of :class:`FlatMenu` for which we want to redirect
+ focus inputs.
+ """
+
+ wx.EvtHandler.__init__(self)
+ self.SetMenu(menu)
+
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+
+ def SetMenu(self, menu):
+ """
+ Sets the listener menu.
+
+ :param `menu`: an instance of :class:`FlatMenu`.
+ """
+
+ self._menu = menu
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`FocusHandler`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ # Let parent process it
+ self._menu.OnKeyDown(event)
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`FocusHandler`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ wx.PostEvent(self._menu, event)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/flatnotebook.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/flatnotebook.py
new file mode 100644
index 0000000..276d6c8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/flatnotebook.py
@@ -0,0 +1,6673 @@
+# --------------------------------------------------------------------------- #
+# FLATNOTEBOOK Widget wxPython IMPLEMENTATION
+#
+# Original C++ Code From Eran. You Can Find It At:
+#
+# http://wxforum.shadonet.com/viewtopic.php?t=5761&start=0
+#
+# License: wxWidgets license
+#
+#
+# Python Code By:
+#
+# Andrea Gavana, @ 02 Oct 2006
+# Latest Revision: 15 Feb 2014, 23.00 GMT
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+:class:`FlatNotebook` is a full, generic and owner-drawn implementation of :class:`Notebook`.
+
+
+Description
+===========
+
+:class:`FlatNotebook` is a full implementation of the :class:`Notebook`, and designed to be
+a drop-in replacement for :class:`Notebook`. The API functions are similar so one can
+expect the function to behave in the same way.
+
+Some features:
+
+- The buttons are highlighted a la Firefox style;
+- The scrolling is done for bulks of tabs (so, the scrolling is faster and better);
+- The buttons area is never overdrawn by tabs (unlike many other implementations I saw);
+- It is a generic control;
+- Currently there are 6 different styles - VC8, VC 71, Standard, Fancy, Firefox 2 and Ribbon;
+- Mouse middle click can be used to close tabs;
+- A function to add right click menu for tabs (simple as meth:~FlatNotebook.SetRightClickMenu`);
+- All styles has bottom style as well (they can be drawn in the bottom of screen);
+- An option to hide 'X' button or navigation buttons (separately);
+- Gradient colouring of the selected tabs and border;
+- Support for drag 'n' drop of tabs, both in the same notebook or to another notebook;
+- Possibility to have closing button on the active tab directly;
+- Support for disabled tabs;
+- Colours for active/inactive tabs, and captions;
+- Background of tab area can be painted in gradient (VC8 style only);
+- Colourful tabs - a random gentle colour is generated for each new tab (very cool, VC8 style only);
+- Support for showing pages in "column/row mode", which means that all the pages will be
+ shown in "tile" mode while the tabs are hidden;
+- Possibility to add a custom panel to show a logo or HTML documentation or
+ whatever you like when there are no pages left in :class:`FlatNotebook`;
+- Try setting the tab area colour for the Ribbon Style.
+
+
+And much more.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.flatnotebook as fnb
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init(self, parent, -1, "FlatNotebook Demo")
+
+ panel = wx.Panel(self)
+
+ notebook = fnb.FlatNotebook(panel, -1)
+
+ for i in xrange(3):
+ caption = "Page %d"%(i+1)
+ notebook.AddPage(self.CreatePage(notebook, caption), caption)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(notebook, 1, wx.ALL|wx.EXPAND, 5)
+ panel.SetSizer(sizer)
+
+
+ def CreatePage(self, notebook, caption):
+ '''
+ Creates a simple :class:`Panel` containing a :class:`TextCtrl`.
+
+ :param `notebook`: an instance of `FlatNotebook`;
+ :param `caption`: a simple label.
+ '''
+
+ p = wx.Panel(notebook)
+ wx.StaticText(p, -1, caption, (20,20))
+ wx.TextCtrl(p, -1, "", (20,40), (150,-1))
+ return p
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+================================ =========== ==================================================
+Window Styles Hex Value Description
+================================ =========== ==================================================
+``FNB_VC71`` 0x1 Use Visual Studio 2003 (VC7.1) style for tabs.
+``FNB_FANCY_TABS`` 0x2 Use fancy style - square tabs filled with gradient colouring.
+``FNB_TABS_BORDER_SIMPLE`` 0x4 Draw thin border around the page.
+``FNB_NO_X_BUTTON`` 0x8 Do not display the 'X' button.
+``FNB_NO_NAV_BUTTONS`` 0x10 Do not display the right/left arrows.
+``FNB_MOUSE_MIDDLE_CLOSES_TABS`` 0x20 Use the mouse middle button for cloing tabs.
+``FNB_BOTTOM`` 0x40 Place tabs at bottom - the default is to place them at top.
+``FNB_NODRAG`` 0x80 Disable dragging of tabs.
+``FNB_VC8`` 0x100 Use Visual Studio 2005 (VC8) style for tabs.
+``FNB_X_ON_TAB`` 0x200 Place 'X' close button on the active tab.
+``FNB_BACKGROUND_GRADIENT`` 0x400 Use gradients to paint the tabs background.
+``FNB_COLOURFUL_TABS`` 0x800 Use colourful tabs (VC8 style only).
+``FNB_DCLICK_CLOSES_TABS`` 0x1000 Style to close tab using double click.
+``FNB_SMART_TABS`` 0x2000 Use `Smart Tabbing`, like ``Alt`` + ``Tab`` on Windows.
+``FNB_DROPDOWN_TABS_LIST`` 0x4000 Use a dropdown menu on the left in place of the arrows.
+``FNB_ALLOW_FOREIGN_DND`` 0x8000 Allows drag 'n' drop operations between different :class:`FlatNotebook`.
+``FNB_HIDE_ON_SINGLE_TAB`` 0x10000 Hides the Page Container when there is one or fewer tabs.
+``FNB_DEFAULT_STYLE`` 0x10020 :class:`FlatNotebook` default style.
+``FNB_FF2`` 0x20000 Use Firefox 2 style for tabs.
+``FNB_NO_TAB_FOCUS`` 0x40000 Does not allow tabs to have focus.
+``FNB_RIBBON_TABS`` 0x80000 Use the Ribbon Tabs style
+``FNB_HIDE_TABS`` 0x100000 Hides the Page Container allowing only keyboard navigation
+``FNB_NAV_BUTTONS_WHEN_NEEDED`` 0x200000 Hides the navigation left/right arrows if all tabs fit
+================================ =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+========================================= ==================================================
+Event Name Description
+========================================= ==================================================
+``EVT_FLATNOTEBOOK_PAGE_CHANGED`` Notify client objects when the active page in :class:`FlatNotebook` has changed.
+``EVT_FLATNOTEBOOK_PAGE_CHANGING`` Notify client objects when the active page in :class:`FlatNotebook` is about to change.
+``EVT_FLATNOTEBOOK_PAGE_CLOSED`` Notify client objects when a page in :class:`FlatNotebook` has been closed.
+``EVT_FLATNOTEBOOK_PAGE_CLOSING`` Notify client objects when a page in :class:`FlatNotebook` is closing.
+``EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU`` Notify client objects when a pop-up menu should appear next to a tab.
+``EVT_FLATNOTEBOOK_PAGE_DROPPED`` Notify client objects when a tab has been dropped and re-arranged (on the *same* notebook)
+``EVT_FLATNOTEBOOK_PAGE_DROPPED_FOREIGN`` Notify client objects when a tab has been dropped and re-arranged (from a foreign notebook)
+========================================= ==================================================
+
+
+License And Version
+===================
+
+:class:`FlatNotebook` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 15 Feb 2014, 23.00 GMT
+
+Version 3.2
+"""
+
+__docformat__ = "epytext"
+
+
+#----------------------------------------------------------------------
+# Beginning Of FLATNOTEBOOK wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+import random
+import math
+import weakref
+import cPickle
+
+# Used on OSX to get access to carbon api constants
+if wx.Platform == '__WXMAC__':
+ import Carbon.Appearance
+
+# Check for the new method in 2.7 (not present in 2.6.3.3)
+if wx.VERSION_STRING < "2.7":
+ wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point)
+
+FNB_HEIGHT_SPACER = 10
+""" Padding for the tab widths/heights, in pixels. """
+
+# Use Visual Studio 2003 (VC7.1) style for tabs
+FNB_VC71 = 1
+"""Use Visual Studio 2003 (VC7.1) style for tabs"""
+
+# Use fancy style - square tabs filled with gradient colouring
+FNB_FANCY_TABS = 2
+"""Use fancy style - square tabs filled with gradient colouring"""
+
+# Draw thin border around the page
+FNB_TABS_BORDER_SIMPLE = 4
+"""Draw thin border around the page"""
+
+# Do not display the 'X' button
+FNB_NO_X_BUTTON = 8
+"""Do not display the 'X' button"""
+
+# Do not display the Right / Left arrows
+FNB_NO_NAV_BUTTONS = 16
+"""Do not display the right/left arrows"""
+
+# Use the mouse middle button for cloing tabs
+FNB_MOUSE_MIDDLE_CLOSES_TABS = 32
+"""Use the mouse middle button for cloing tabs"""
+
+# Place tabs at bottom - the default is to place them
+# at top
+FNB_BOTTOM = 64
+"""Place tabs at bottom - the default is to place them at top"""
+
+# Disable dragging of tabs
+FNB_NODRAG = 128
+"""Disable dragging of tabs"""
+
+# Use Visual Studio 2005 (VC8) style for tabs
+FNB_VC8 = 256
+"""Use Visual Studio 2005 (VC8) style for tabs"""
+
+# Firefox 2 tabs style
+FNB_FF2 = 131072
+"""Use Firefox 2 style for tabs"""
+
+# Place 'X' on a tab
+FNB_X_ON_TAB = 512
+"""Place 'X' close button on the active tab"""
+
+FNB_BACKGROUND_GRADIENT = 1024
+"""Use gradients to paint the tabs background"""
+
+FNB_COLOURFUL_TABS = 2048
+"""Use colourful tabs (VC8 style only)"""
+
+# Style to close tab using double click - styles 1024, 2048 are reserved
+FNB_DCLICK_CLOSES_TABS = 4096
+"""Style to close tab using double click"""
+
+FNB_SMART_TABS = 8192
+"""Use `Smart Tabbing`, like ``Alt`` + ``Tab`` on Windows"""
+
+FNB_DROPDOWN_TABS_LIST = 16384
+"""Use a dropdown menu on the left in place of the arrows"""
+
+FNB_ALLOW_FOREIGN_DND = 32768
+"""Allows drag and drop operations between different :class:`FlatNotebook`"""
+
+FNB_HIDE_ON_SINGLE_TAB = 65536
+"""Hides the :class:`PageContainer` when there is one or fewer tabs"""
+
+FNB_NO_TAB_FOCUS = 262144
+""" Does not allow tabs to have focus"""
+
+FNB_RIBBON_TABS = 0x80000
+"""Use Ribbon style for tabs"""
+
+FNB_HIDE_TABS = 0x100000
+"""Hides the tabs allowing only keyboard navigation between pages"""
+
+FNB_NAV_BUTTONS_WHEN_NEEDED = 0x200000
+""" Hides the navigation left/right arrows if all tabs fit. """
+
+VERTICAL_BORDER_PADDING = 4
+""" Padding between the text and the tab border. """
+
+# Button size is a 16x16 xpm bitmap
+BUTTON_SPACE = 16
+"""Button size is a 16x16 xpm bitmap"""
+
+MASK_COLOUR = wx.Colour(0, 128, 128)
+"""Mask colour for the arrow bitmaps"""
+
+# Button status
+FNB_BTN_PRESSED = 2
+"""Navigation button is pressed"""
+FNB_BTN_HOVER = 1
+"""Navigation button is hovered"""
+FNB_BTN_NONE = 0
+"""No navigation"""
+
+# Hit Test results
+FNB_TAB = 1 # On a tab
+"""Indicates mouse coordinates inside a tab"""
+FNB_X = 2 # On the X button
+"""Indicates mouse coordinates inside the X region"""
+FNB_TAB_X = 3 # On the 'X' button (tab's X button)
+"""Indicates mouse coordinates inside the X region in a tab"""
+FNB_LEFT_ARROW = 4 # On the rotate left arrow button
+"""Indicates mouse coordinates inside the left arrow region"""
+FNB_RIGHT_ARROW = 5 # On the rotate right arrow button
+"""Indicates mouse coordinates inside the right arrow region"""
+FNB_DROP_DOWN_ARROW = 6 # On the drop down arrow button
+"""Indicates mouse coordinates inside the drop down arrow region"""
+FNB_NOWHERE = 0 # Anywhere else
+"""Indicates mouse coordinates not on any tab of the notebook"""
+
+FNB_DEFAULT_STYLE = FNB_MOUSE_MIDDLE_CLOSES_TABS | FNB_HIDE_ON_SINGLE_TAB
+""":class:`FlatNotebook` default style"""
+
+# FlatNotebook Events:
+# wxEVT_FLATNOTEBOOK_PAGE_CHANGED: Event Fired When You Switch Page;
+# wxEVT_FLATNOTEBOOK_PAGE_CHANGING: Event Fired When You Are About To Switch
+# Pages, But You Can Still "Veto" The Page Changing By Avoiding To Call
+# event.Skip() In Your Event Handler;
+# wxEVT_FLATNOTEBOOK_PAGE_CLOSING: Event Fired When A Page Is Closing, But
+# You Can Still "Veto" The Page Changing By Avoiding To Call event.Skip()
+# In Your Event Handler;
+# wxEVT_FLATNOTEBOOK_PAGE_CLOSED: Event Fired When A Page Is Closed.
+# wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU: Event Fired When A Menu Pops-up In A Tab.
+# wxEVT_FLATNOTEBOOK_PAGE_DROPPED: Event Fired When A Tab Is Dropped On The Same Notebook
+
+wxEVT_FLATNOTEBOOK_PAGE_CHANGED = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
+wxEVT_FLATNOTEBOOK_PAGE_CHANGING = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
+wxEVT_FLATNOTEBOOK_PAGE_CLOSING = wx.NewEventType()
+wxEVT_FLATNOTEBOOK_PAGE_CLOSED = wx.NewEventType()
+wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.NewEventType()
+wxEVT_FLATNOTEBOOK_PAGE_DROPPED = wx.NewEventType()
+wxEVT_FLATNOTEBOOK_PAGE_DROPPED_FOREIGN = wx.NewEventType()
+
+#-----------------------------------#
+# FlatNotebookEvent
+#-----------------------------------#
+
+EVT_FLATNOTEBOOK_PAGE_CHANGED = wx.EVT_NOTEBOOK_PAGE_CHANGED
+""" Notify client objects when the active page in :class:`FlatNotebook` has changed."""
+EVT_FLATNOTEBOOK_PAGE_CHANGING = wx.EVT_NOTEBOOK_PAGE_CHANGING
+""" Notify client objects when the active page in :class:`FlatNotebook` is about to change."""
+EVT_FLATNOTEBOOK_PAGE_CLOSING = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, 1)
+""" Notify client objects when a page in :class:`FlatNotebook` is closing."""
+EVT_FLATNOTEBOOK_PAGE_CLOSED = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, 1)
+""" Notify client objects when a page in :class:`FlatNotebook` has been closed."""
+EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, 1)
+""" Notify client objects when a pop-up menu should appear next to a tab."""
+EVT_FLATNOTEBOOK_PAGE_DROPPED = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_DROPPED, 1)
+""" Notify client objects when a tab has been dropped and re-arranged (on the *same* notebook)."""
+EVT_FLATNOTEBOOK_PAGE_DROPPED_FOREIGN = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_DROPPED_FOREIGN, 1)
+""" Notify client objects when a tab has been dropped and re-arranged (from a foreign notebook)."""
+
+# Some icons in XPM format
+
+left_arrow_disabled_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #555555",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````.```````",
+ "```````..```````",
+ "``````.`.```````",
+ "`````.``.```````",
+ "````.```.```````",
+ "`````.``.```````",
+ "``````.`.```````",
+ "```````..```````",
+ "````````.```````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+x_button_pressed_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #9e9ede",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.############.`",
+ "`.############.`",
+ "`.###aa####aa#.`",
+ "`.####aa##aa##.`",
+ "`.#####aaaa###.`",
+ "`.######aa####.`",
+ "`.#####aaaa###.`",
+ "`.####aa##aa##.`",
+ "`.###aa####aa#.`",
+ "`.############.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+
+left_arrow_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #555555",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````.```````",
+ "```````..```````",
+ "``````...```````",
+ "`````....```````",
+ "````.....```````",
+ "`````....```````",
+ "``````...```````",
+ "```````..```````",
+ "````````.```````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+x_button_hilite_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #c9dafb",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.############.`",
+ "`.##aa####aa##.`",
+ "`.###aa##aa###.`",
+ "`.####aaaa####.`",
+ "`.#####aa#####.`",
+ "`.####aaaa####.`",
+ "`.###aa##aa###.`",
+ "`.##aa####aa##.`",
+ "`.############.`",
+ "`.############.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+x_button_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #555555",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````..````..````",
+ "`````..``..`````",
+ "``````....``````",
+ "```````..```````",
+ "``````....``````",
+ "`````..``..`````",
+ "````..````..````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+left_arrow_pressed_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #9e9ede",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.############.`",
+ "`.#######a####.`",
+ "`.######aa####.`",
+ "`.#####aaa####.`",
+ "`.####aaaa####.`",
+ "`.###aaaaa####.`",
+ "`.####aaaa####.`",
+ "`.#####aaa####.`",
+ "`.######aa####.`",
+ "`.#######a####.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+left_arrow_hilite_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #c9dafb",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.######a#####.`",
+ "`.#####aa#####.`",
+ "`.####aaa#####.`",
+ "`.###aaaa#####.`",
+ "`.##aaaaa#####.`",
+ "`.###aaaa#####.`",
+ "`.####aaa#####.`",
+ "`.#####aa#####.`",
+ "`.######a#####.`",
+ "`.############.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+right_arrow_disabled_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #555555",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "```````.````````",
+ "```````..```````",
+ "```````.`.``````",
+ "```````.``.`````",
+ "```````.```.````",
+ "```````.``.`````",
+ "```````.`.``````",
+ "```````..```````",
+ "```````.````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+right_arrow_hilite_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #c9dafb",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.####a#######.`",
+ "`.####aa######.`",
+ "`.####aaa#####.`",
+ "`.####aaaa####.`",
+ "`.####aaaaa###.`",
+ "`.####aaaa####.`",
+ "`.####aaa#####.`",
+ "`.####aa######.`",
+ "`.####a#######.`",
+ "`.############.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+right_arrow_pressed_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #9e9ede",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.############.`",
+ "`.#####a######.`",
+ "`.#####aa#####.`",
+ "`.#####aaa####.`",
+ "`.#####aaaa###.`",
+ "`.#####aaaaa##.`",
+ "`.#####aaaa###.`",
+ "`.#####aaa####.`",
+ "`.#####aa#####.`",
+ "`.#####a######.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+
+right_arrow_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #555555",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "```````.````````",
+ "```````..```````",
+ "```````...``````",
+ "```````....`````",
+ "```````.....````",
+ "```````....`````",
+ "```````...``````",
+ "```````..```````",
+ "```````.````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+down_arrow_hilite_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #c9dafb",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "``.............`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.#aaaaaaaaa#.`",
+ "``.##aaaaaaa##.`",
+ "``.###aaaaa###.`",
+ "``.####aaa####.`",
+ "``.#####a#####.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+down_arrow_pressed_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #9e9ede",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "``.............`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.#aaaaaaaaa#.`",
+ "``.##aaaaaaa##.`",
+ "``.###aaaaa###.`",
+ "``.####aaa####.`",
+ "``.#####a#####.`",
+ "``.###########.`",
+ "``.............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+
+down_arrow_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #000000",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````.........```",
+ "`````.......````",
+ "``````.....`````",
+ "```````...``````",
+ "````````.```````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+
+#----------------------------------------------------------------------
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+Mondrian = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAHFJ"
+ "REFUWIXt1jsKgDAQRdF7xY25cpcWC60kioI6Fm/ahHBCMh+BRmGMnAgEWnvPpzK8dvrFCCCA"
+ "coD8og4c5Lr6WB3Q3l1TBwLYPuF3YS1gn1HphgEEEABcKERrGy0E3B0HFJg7C1N/f/kTBBBA"
+ "+Vi+AMkgFEvBPD17AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+
+
+def LightColour(colour, percent):
+ """
+ Brighten the input colour by a percentage.
+
+ :param `colour`: a valid :class:`Colour` instance;
+ :param `percent`: the percentage by which the input colour should be brightened.
+ """
+
+ end_colour = wx.WHITE
+
+ rd = end_colour.Red() - colour.Red()
+ gd = end_colour.Green() - colour.Green()
+ bd = end_colour.Blue() - colour.Blue()
+
+ high = 100
+
+ # We take the percent way of the colour from colour -. white
+ i = percent
+ r = colour.Red() + ((i*rd*100)/high)/100
+ g = colour.Green() + ((i*gd*100)/high)/100
+ b = colour.Blue() + ((i*bd*100)/high)/100
+ return wx.Colour(r, g, b)
+
+
+def FormatColour(colour):
+ """
+ Convert the input `colour` into a valid :class:`Colour` instance, using whatever typemap
+ accepted by wxWidgets/wxPython.
+
+ :param `colour`: can be an instance of :class:`Colour`, a 3 or 4 integer tuple, a hex
+ string, a string representing the colour name or ``None``.
+
+ :returns: a valid instance of :class:`Colour` or ``None`` if the input `colour` was ``None``
+ in the first place.
+ """
+
+ if isinstance(colour, (list, tuple)):
+ colour = wx.Colour(*colour)
+ elif isinstance(colour, basestring):
+ colour = wx.NamedColour(colour)
+
+ return colour
+
+
+def RandomColour():
+ """ Creates a random colour. """
+
+ r = random.randint(0, 255) # Random value betweem 0-255
+ g = random.randint(0, 255) # Random value betweem 0-255
+ b = random.randint(0, 255) # Random value betweem 0-255
+
+ return wx.Colour(r, g, b)
+
+
+def PaintStraightGradientBox(dc, rect, startColour, endColour, vertical=True):
+ """
+ Draws a gradient coloured box from `startColour` to `endColour`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the rectangle to fill with the gradient shading;
+ :param `startColour`: the first colour in the gradient shading;
+ :param `endColour`: the last colour in the gradient shading;
+ :param `vertical`: ``True`` if the gradient shading is north to south, ``False``
+ if it is east to west.
+ """
+
+ rd = endColour.Red() - startColour.Red()
+ gd = endColour.Green() - startColour.Green()
+ bd = endColour.Blue() - startColour.Blue()
+
+ # Save the current pen and brush
+ savedPen = dc.GetPen()
+ savedBrush = dc.GetBrush()
+
+ if vertical:
+ high = rect.GetHeight()-1
+ else:
+ high = rect.GetWidth()-1
+
+ if high < 1:
+ return
+
+ for i in xrange(high+1):
+
+ r = startColour.Red() + ((i*rd*100)/high)/100
+ g = startColour.Green() + ((i*gd*100)/high)/100
+ b = startColour.Blue() + ((i*bd*100)/high)/100
+
+ p = wx.Pen(wx.Colour(r, g, b))
+ dc.SetPen(p)
+
+ if vertical:
+ dc.DrawLine(rect.x, rect.y+i, rect.x+rect.width, rect.y+i)
+ else:
+ dc.DrawLine(rect.x+i, rect.y, rect.x+i, rect.y+rect.height)
+
+ # Restore the pen and brush
+ dc.SetPen(savedPen)
+ dc.SetBrush(savedBrush)
+
+
+def AdjustColour(colour, percent, alpha=wx.ALPHA_OPAQUE):
+ """
+ Brighten/darken input colour by `percent` and adjust `alpha` channel if needed.
+
+ :param `colour`: colour object to adjust, an instance of :class:`Colour`;
+ :param `percent`: percent to adjust ``+`` (brighten) or ``-`` (darken);
+ :param `alpha`: amount to adjust the alpha channel.
+
+ :return: The modified colour.
+
+ """
+
+ radj, gadj, badj = [int(val * (abs(percent) / 100.)) for val in colour.Get()]
+
+ if percent < 0:
+ radj, gadj, badj = [val * -1 for val in [radj, gadj, badj]]
+ else:
+ radj, gadj, badj = [val or 255 for val in [radj, gadj, badj]]
+
+ red = min(colour.Red() + radj, 255)
+ green = min(colour.Green() + gadj, 255)
+ blue = min(colour.Blue() + badj, 255)
+ return wx.Colour(red, green, blue, alpha)
+
+
+if wx.VERSION_STRING < "2.8.9.2":
+ adjust_colour = AdjustColour
+else:
+ from wx.lib.colourutils import AdjustColour as adjust_colour
+
+
+# -----------------------------------------------------------------------------
+# Util functions
+# -----------------------------------------------------------------------------
+
+def DrawButton(dc, rect, focus, upperTabs):
+ """
+ Draws a :class:`FlatNotebook` tab.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the tab's client rectangle;
+ :param `focus`: ``True`` if the tab has focus, ``False`` otherwise;
+ :param `upperTabs`: ``True`` if the tabs are at the top, ``False`` if they are
+ at the bottom.
+ """
+
+ # Define the rounded rectangle base on the given rect
+ # we need an array of 9 points for it
+ regPts = [wx.Point() for indx in xrange(9)]
+
+ if focus:
+ if upperTabs:
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*8)
+ rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*8)
+ else:
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*5)
+ rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*5)
+ else:
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 2))
+ rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 2))
+
+ # Define the top region
+ top = wx.RectPP(rect.GetTopLeft(), rightPt)
+ bottom = wx.RectPP(leftPt, rect.GetBottomRight())
+
+ topStartColour = wx.WHITE
+
+ if not focus:
+ topStartColour = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 50)
+
+ topEndColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+ bottomStartColour = topEndColour
+ bottomEndColour = topEndColour
+
+ # Incase we use bottom tabs, switch the colours
+ if upperTabs:
+ if focus:
+ PaintStraightGradientBox(dc, top, topStartColour, topEndColour)
+ PaintStraightGradientBox(dc, bottom, bottomStartColour, bottomEndColour)
+ else:
+ PaintStraightGradientBox(dc, top, topEndColour , topStartColour)
+ PaintStraightGradientBox(dc, bottom, bottomStartColour, bottomEndColour)
+
+ else:
+ if focus:
+ PaintStraightGradientBox(dc, bottom, topEndColour, bottomEndColour)
+ PaintStraightGradientBox(dc, top,topStartColour, topStartColour)
+ else:
+ PaintStraightGradientBox(dc, bottom, bottomStartColour, bottomEndColour)
+ PaintStraightGradientBox(dc, top, topEndColour, topStartColour)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBDropSource
+# Gives Some Custom UI Feedback during the DnD Operations
+# ---------------------------------------------------------------------------- #
+
+class FNBDropSource(wx.DropSource):
+ """
+ Give some custom UI feedback during the drag and drop operation in this
+ function. It is called on each mouse move, so your implementation must
+ not be too slow.
+ """
+
+ def __init__(self, win):
+ """
+ Default class constructor.
+ Used internally.
+
+ :param `win`: the source window for which we wish to provide UI feedback
+ during drag and drop operations.
+ """
+
+ wx.DropSource.__init__(self, win)
+ self._win = win
+
+
+ def GiveFeedback(self, effect):
+ """
+ You may give some custom UI feedback during the drag and drop operation
+ in this function. It is called on each mouse move, so your implementation
+ must not be too slow.
+
+ :param `effect`: the effect to implement. One of ``wx.DragCopy``, ``wx.DragMove``,
+ ``wx.DragLink`` and ``wx.DragNone``.
+
+ :return: Return ``False`` if you want default feedback, or ``True`` if you
+ implement your own feedback. The return values is ignored under GTK.
+
+ :note: To show your own custom drag and drop UI feedback, you must override
+ this method.
+ """
+
+ self._win.DrawDragHint()
+ return False
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBDragInfo
+# Stores All The Information To Allow Drag And Drop Between Different
+# FlatNotebooks.
+# ---------------------------------------------------------------------------- #
+
+class FNBDragInfo(object):
+ """
+ Stores all the information to allow drag and drop between different
+ :class:`FlatNotebook` instances.
+ """
+
+ _map = weakref.WeakValueDictionary()
+
+ def __init__(self, container, pageindex):
+ """
+ Default class constructor.
+
+ :param `container`: the drag and drop container, a page in :class:`FlatNotebook`;
+ :param `pageindex`: the index of the tab that is actually being dragged.
+ """
+
+ self._id = id(container)
+ FNBDragInfo._map[self._id] = container
+ self._pageindex = pageindex
+
+
+ def GetContainer(self):
+ """ Returns the :class:`FlatNotebook` page (usually a panel). """
+
+ return FNBDragInfo._map.get(self._id, None)
+
+
+ def GetPageIndex(self):
+ """ Returns the page index associated with a page. """
+
+ return self._pageindex
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBDropTarget
+# Simply Used To Handle The OnDrop() Method When Dragging And Dropping Between
+# Different FlatNotebooks.
+# ---------------------------------------------------------------------------- #
+
+class FNBDropTarget(wx.DropTarget):
+ """
+ Class used to handle the :meth:`FlatNotebook.OnDropTarget() <FlatNotebook.OnDropTarget>` method when dragging and
+ dropping between different :class:`FlatNotebook` instances.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+
+ :param `parent`: the window handling the drag and drop, an instance of
+ :class:`FlatNotebook`.
+ """
+
+ wx.DropTarget.__init__(self)
+
+ self._parent = parent
+ self._dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook"))
+ self.SetDataObject(self._dataobject)
+
+
+ def OnData(self, x, y, dragres):
+ """
+ Called after `OnDrop` returns ``True``.
+
+ By default this will usually call `GetData` and will return the suggested default value `dragres`.
+
+ :param `x`: the current x position of the mouse while dragging and dropping;
+ :param `y`: the current y position of the mouse while dragging and dropping;
+ :param `dragres`: an optional default return value.
+ """
+
+ if not self.GetData():
+ return wx.DragNone
+
+ draginfo = self._dataobject.GetData()
+ drginfo = cPickle.loads(draginfo)
+
+ return self._parent.OnDropTarget(x, y, drginfo.GetPageIndex(), drginfo.GetContainer())
+
+
+# ---------------------------------------------------------------------------- #
+# Class PageInfo
+# Contains parameters for every FlatNotebook page
+# ---------------------------------------------------------------------------- #
+
+class PageInfo(object):
+ """
+ This class holds all the information (caption, image, etc...) belonging to a
+ single tab in :class:`FlatNotebook`.
+ """
+
+ def __init__(self, caption="", imageindex=-1, tabangle=0, enabled=True):
+ """
+ Default Class Constructor.
+
+ :param `caption`: the tab caption;
+ :param `imageindex`: the tab image index based on the assigned (set)
+ :class:`ImageList` (if any);
+ :param `tabangle`: the tab angle (only on standard tabs, from 0 to 15
+ degrees);
+ :param `enabled`: sets the tab as enabled or disabled.
+ """
+
+ self._strCaption = caption
+ self._TabAngle = tabangle
+ self._ImageIndex = imageindex
+ self._bEnabled = enabled
+ self._pos = wx.Point(-1, -1)
+ self._size = wx.Size(-1, -1)
+ self._region = wx.Region()
+ self._xRect = wx.Rect()
+ self._colour = None
+ self._hasFocus = False
+ self._pageTextColour = None
+
+
+ def SetCaption(self, value):
+ """
+ Sets the tab caption.
+
+ :param `value`: the new tab caption string.
+ """
+
+ self._strCaption = value
+
+
+ def GetCaption(self):
+ """ Returns the tab caption. """
+
+ return self._strCaption
+
+
+ def SetPosition(self, value):
+ """
+ Sets the tab position.
+
+ :param `value`: an instance of :class:`Point`.
+ """
+
+ self._pos = value
+
+
+ def GetPosition(self):
+ """ Returns the tab position. """
+
+ return self._pos
+
+
+ def SetSize(self, value):
+ """
+ Sets the tab size.
+
+ :param `value`: an instance of :class:`Size`.
+ """
+
+ self._size = value
+
+
+ def GetSize(self):
+ """ Returns the tab size. """
+
+ return self._size
+
+
+ def SetTabAngle(self, value):
+ """
+ Sets the tab header angle.
+
+ :param `value`: the tab header angle (0 <= value <= 15 degrees).
+ """
+
+ self._TabAngle = min(45, value)
+
+
+ def GetTabAngle(self):
+ """ Returns the tab angle. """
+
+ return self._TabAngle
+
+
+ def SetImageIndex(self, value):
+ """
+ Sets the tab image index.
+
+ :param `value`: an index within the :class:`FlatNotebook` image list specifying
+ the image to use for this tab.
+ """
+
+ self._ImageIndex = value
+
+
+ def GetImageIndex(self):
+ """ Returns the tab image index. """
+
+ return self._ImageIndex
+
+
+ def GetPageTextColour(self):
+ """
+ Returns the tab text colour if it has been set previously, or ``None``
+ otherwise.
+ """
+
+ return self._pageTextColour
+
+
+ def SetPageTextColour(self, colour):
+ """
+ Sets the tab text colour for this tab.
+
+ :param `colour`: an instance of :class:`Colour`. You can pass ``None`` or
+ :class:`NullColour` to return to the default page text colour.
+ """
+
+ colour = FormatColour(colour)
+
+ if colour is None or not colour.IsOk():
+ self._pageTextColour = None
+ else:
+ self._pageTextColour = colour
+
+
+ def GetEnabled(self):
+ """ Returns whether the tab is enabled or not. """
+
+ return self._bEnabled
+
+
+ def EnableTab(self, enabled):
+ """
+ Sets the tab enabled or disabled.
+
+ :param `enabled`: ``True`` to enable a tab, ``False`` to disable it.
+ """
+
+ self._bEnabled = enabled
+
+
+ def SetRegion(self, points=[]):
+ """
+ Sets the tab region.
+
+ :param `points`: a Python list of :class:`Point`
+ """
+
+ self._region = wx.RegionFromPoints(points)
+
+
+ def GetRegion(self):
+ """ Returns the tab region. """
+
+ return self._region
+
+
+ def SetXRect(self, xrect):
+ """
+ Sets the button 'X' area rect.
+
+ :param `xrect`: an instance of :class:`Rect`, specifying the client rectangle
+ of the 'X' button.
+ """
+
+ self._xRect = xrect
+
+
+ def GetXRect(self):
+ """ Returns the button 'X' area rect. """
+
+ return self._xRect
+
+
+ def GetColour(self):
+ """ Returns the tab colour. """
+
+ return self._colour
+
+
+ def SetColour(self, colour):
+ """
+ Sets the tab colour.
+
+ :param `colour`: a valid :class:`Colour` object or any typemap supported by wxWidgets/wxPython
+ to generate a colour (i.e., a hex string, a colour name, a 3 or 4 integer tuple).
+ """
+
+ self._colour = FormatColour(colour)
+
+
+# ---------------------------------------------------------------------------- #
+# Class FlatNotebookEvent
+# ---------------------------------------------------------------------------- #
+
+class FlatNotebookEvent(wx.PyCommandEvent):
+ """
+ This events will be sent when a ``EVT_FLATNOTEBOOK_PAGE_CHANGED``,
+ ``EVT_FLATNOTEBOOK_PAGE_CHANGING``, ``EVT_FLATNOTEBOOK_PAGE_CLOSING``,
+ ``EVT_FLATNOTEBOOK_PAGE_CLOSED`` and ``EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU`` is
+ mapped in the parent.
+ """
+
+ def __init__(self, eventType, eventId=1, nSel=-1, nOldSel=-1):
+ """
+ Default class constructor.
+
+ :param `eventType`: the event type;
+ :param `eventId`: the event identifier;
+ :param `nSel`: the current selection;
+ :param `nOldSel`: the old selection.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+ self._eventType = eventType
+
+ self.notify = wx.NotifyEvent(eventType, eventId)
+
+
+ def GetNotifyEvent(self):
+ """ Returns the actual :class:`NotifyEvent`. """
+
+ return self.notify
+
+
+ def IsAllowed(self):
+ """
+ Returns ``True`` if the change is allowed (:meth:`~FlatNotebookEvent.Veto` hasn't been called) or
+ ``False`` otherwise (if it was).
+ """
+
+ return self.notify.IsAllowed()
+
+
+ def Veto(self):
+ """
+ Prevents the change announced by this event from happening.
+
+ :note: It is in general a good idea to notify the user about the reasons
+ for vetoing the change because otherwise the applications behaviour (which
+ just refuses to do what the user wants) might be quite surprising.
+ """
+
+ self.notify.Veto()
+
+
+ def Allow(self):
+ """
+ This is the opposite of :meth:`~FlatNotebookEvent.Veto`: it explicitly allows the event to be processed.
+ For most events it is not necessary to call this method as the events are
+ allowed anyhow but some are forbidden by default (this will be mentioned
+ in the corresponding event description).
+ """
+
+ self.notify.Allow()
+
+
+ def SetSelection(self, nSel):
+ """
+ Sets the event selection.
+
+ :param `nSel`: an integer specifying the new selection.
+ """
+
+ self._selection = nSel
+
+
+ def SetOldSelection(self, nOldSel):
+ """
+ Sets the id of the page selected before the change.
+
+ :param `nOldSel`: an integer specifying the old selection.
+ """
+
+ self._oldselection = nOldSel
+
+
+ def GetSelection(self):
+ """ Returns the currently selected page, or -1 if none was selected. """
+
+ return self._selection
+
+
+ def GetOldSelection(self):
+ """ Returns the page that was selected before the change, -1 if none was selected. """
+
+ return self._oldselection
+
+
+# ---------------------------------------------------------------------------- #
+# Class TabNavigatorWindow
+# ---------------------------------------------------------------------------- #
+
+class FlatNotebookDragEvent(FlatNotebookEvent):
+ """
+ This event will be sent when a ``EVT_FLATNOTEBOOK_PAGE_DRAGGED_FOREIGN`` is
+ mapped in the parent.
+ """
+
+ def __init__(self, eventType, eventId=1, nSel=-1, nOldSel=-1):
+ """
+ Default class constructor.
+
+ :param `eventType`: the event type;
+ :param `eventId`: the event identifier;
+ :param `nSel`: the current selection;
+ :param `nOldSel`: the old selection.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+ self._eventType = eventType
+
+ self.notify = wx.NotifyEvent(eventType, eventId)
+ self._oldnotebook = -1
+ self._newnotebook = -1
+
+
+ def GetNotebook(self):
+ """ Returns the new notebook. """
+
+ return self._newnotebook
+
+
+ def GetOldNotebook(self):
+ """ Returns the old notebook. """
+
+ return self._oldnotebook
+
+
+ def SetNotebook(self, notebook):
+ """
+ Sets the new notebook.
+
+ :param `notebook`: an instance of :class:`FlatNotebook`.
+ """
+
+ self._newnotebook = notebook
+
+
+ def SetOldNotebook(self, old):
+ """
+ Sets the old notebook.
+
+ :param `notebook`: an instance of :class:`FlatNotebook`.
+ """
+
+ self._oldnotebook = old
+
+# ---------------------------------------------------------------------------- #
+# Class TabNavigatorWindow
+# ---------------------------------------------------------------------------- #
+
+class TabNavigatorWindow(wx.Dialog):
+ """
+ This class is used to create a modal dialog that enables `Smart Tabbing`,
+ similar to what you would get by hitting ``Alt`` + ``Tab`` on Windows.
+ """
+
+ def __init__(self, parent=None, icon=None):
+ """
+ Default class constructor.
+ Used internally.
+
+ :param `parent`: the :class:`TabNavigatorWindow` parent window;
+ :param `icon`: a valid :class:`Bitmap` object representing the icon to be displayed
+ in the :class:`TabNavigatorWindow`.
+ """
+
+ wx.Dialog.__init__(self, parent, wx.ID_ANY, "", style=0)
+
+ self._selectedItem = -1
+ self._indexMap = []
+
+ if icon is None:
+ self._bmp = Mondrian.GetBitmap()
+ else:
+ self._bmp = icon
+
+ sz = wx.BoxSizer(wx.VERTICAL)
+
+ self._listBox = wx.ListBox(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, 150), [], wx.LB_SINGLE | wx.NO_BORDER)
+
+ mem_dc = wx.MemoryDC()
+ mem_dc.SelectObject(wx.EmptyBitmap(1,1))
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetWeight(wx.BOLD)
+ mem_dc.SetFont(font)
+
+ panelHeight = mem_dc.GetCharHeight()
+ panelHeight += 4 # Place a spacer of 2 pixels
+
+ # Out signpost bitmap is 24 pixels
+ if panelHeight < 24:
+ panelHeight = 24
+
+ self._panel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, panelHeight))
+
+ sz.Add(self._panel)
+ sz.Add(self._listBox, 1, wx.EXPAND)
+
+ self.SetSizer(sz)
+
+ # Connect events to the list box
+ self._listBox.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self._listBox.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
+ self._listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnItemSelected)
+
+ # Connect paint event to the panel
+ self._panel.Bind(wx.EVT_PAINT, self.OnPanelPaint)
+ self._panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnPanelEraseBg)
+
+ self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
+ self._listBox.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
+ self.PopulateListControl(parent)
+
+ self.GetSizer().Fit(self)
+ self.GetSizer().SetSizeHints(self)
+ self.GetSizer().Layout()
+ self.Centre()
+
+ # Set focus on the list box to avoid having to click on it to change
+ # the tab selection under GTK.
+ self._listBox.SetFocus()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` for the :class:`TabNavigatorWindow`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if event.GetKeyCode() == wx.WXK_CONTROL:
+ self.CloseDialog()
+
+
+ def OnNavigationKey(self, event):
+ """
+ Handles the ``wx.EVT_NAVIGATION_KEY`` for the :class:`TabNavigatorWindow`.
+
+ :param `event`: a :class:`NavigationKeyEvent` event to be processed.
+ """
+
+ selected = self._listBox.GetSelection()
+ bk = self.GetParent()
+ maxItems = bk.GetPageCount()
+
+ if event.GetDirection():
+
+ # Select next page
+ if selected == maxItems - 1:
+ itemToSelect = 0
+ else:
+ itemToSelect = selected + 1
+
+ else:
+
+ # Previous page
+ if selected == 0:
+ itemToSelect = maxItems - 1
+ else:
+ itemToSelect = selected - 1
+
+ self._listBox.SetSelection(itemToSelect)
+
+
+ def PopulateListControl(self, book):
+ """
+ Populates the :class:`TabNavigatorWindow` listbox with a list of tabs.
+
+ :param `book`: an instance of :class:`FlatNotebook` containing the tabs to be
+ displayed in the listbox.
+ """
+
+ selection = book.GetSelection()
+ count = book.GetPageCount()
+
+ self._listBox.Append(book.GetPageText(selection))
+ self._indexMap.append(selection)
+
+ prevSel = book.GetPreviousSelection()
+
+ if prevSel != wx.NOT_FOUND:
+
+ # Insert the previous selection as second entry
+ self._listBox.Append(book.GetPageText(prevSel))
+ self._indexMap.append(prevSel)
+
+ for c in xrange(count):
+
+ # Skip selected page
+ if c == selection:
+ continue
+
+ # Skip previous selected page as well
+ if c == prevSel:
+ continue
+
+ self._listBox.Append(book.GetPageText(c))
+ self._indexMap.append(c)
+
+ # Select the next entry after the current selection
+ self._listBox.SetSelection(0)
+ dummy = wx.NavigationKeyEvent()
+ dummy.SetDirection(True)
+ self.OnNavigationKey(dummy)
+
+
+ def OnItemSelected(self, event):
+ """
+ Handles the ``wx.EVT_LISTBOX_DCLICK`` for the :class:`TabNavigatorWindow`.
+
+ :param `event`: a :class:`ListEvent` event to be processed.
+ """
+
+ self.CloseDialog()
+
+
+ def CloseDialog(self):
+ """
+ Closes the :class:`TabNavigatorWindow` dialog, setting the new selection in
+ :class:`FlatNotebook`.
+ """
+
+ bk = self.GetParent()
+ self._selectedItem = self._listBox.GetSelection()
+ iter = self._indexMap[self._selectedItem]
+ bk._pages.FireEvent(iter)
+ self.EndModal(wx.ID_OK)
+
+
+ def OnPanelPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` for the :class:`TabNavigatorWindow` top panel.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.PaintDC(self._panel)
+ rect = self._panel.GetClientRect()
+
+ bmp = wx.EmptyBitmap(rect.width, rect.height)
+
+ mem_dc = wx.MemoryDC()
+ mem_dc.SelectObject(bmp)
+
+ endColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+ startColour = LightColour(endColour, 50)
+ PaintStraightGradientBox(mem_dc, rect, startColour, endColour)
+
+ # Draw the caption title and place the bitmap
+ # get the bitmap optimal position, and draw it
+ bmpPt, txtPt = wx.Point(), wx.Point()
+ bmpPt.y = (rect.height - self._bmp.GetHeight())/2
+ bmpPt.x = 3
+ mem_dc.DrawBitmap(self._bmp, bmpPt.x, bmpPt.y, True)
+
+ # get the text position, and draw it
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetWeight(wx.BOLD)
+ mem_dc.SetFont(font)
+ fontHeight = mem_dc.GetCharHeight()
+
+ txtPt.x = bmpPt.x + self._bmp.GetWidth() + 4
+ txtPt.y = (rect.height - fontHeight)/2
+ mem_dc.SetTextForeground(wx.WHITE)
+ mem_dc.DrawText("Opened tabs:", txtPt.x, txtPt.y)
+ mem_dc.SelectObject(wx.NullBitmap)
+
+ dc.DrawBitmap(bmp, 0, 0)
+
+
+ def OnPanelEraseBg(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` for the :class:`TabNavigatorWindow` top panel.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBRenderer
+# ---------------------------------------------------------------------------- #
+
+class FNBRenderer(object):
+ """
+ Parent class for the 6 renderers defined: `Standard`, `VC71`, `Fancy`, `Firefox 2`,
+ `VC8` and `Ribbon`. This class implements the common methods of all 6 renderers.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ self._tabHeight = None
+
+ if wx.Platform == "__WXMAC__":
+ # Get proper highlight colour for focus rectangle from the
+ # current Mac theme. kThemeBrushFocusHighlight is
+ # available on Mac OS 8.5 and higher
+ if hasattr(wx, 'MacThemeColour'):
+ c = wx.MacThemeColour(Carbon.Appearance.kThemeBrushFocusHighlight)
+ else:
+ brush = wx.Brush(wx.BLACK)
+ brush.MacSetTheme(Carbon.Appearance.kThemeBrushFocusHighlight)
+ c = brush.GetColour()
+ self._focusPen = wx.Pen(c, 2, wx.SOLID)
+ else:
+ self._focusPen = wx.Pen(wx.BLACK, 1, wx.USER_DASH)
+ self._focusPen.SetDashes([1, 1])
+ self._focusPen.SetCap(wx.CAP_BUTT)
+
+
+ def GetLeftButtonPos(self, pageContainer):
+ """
+ Returns the left button position in the navigation area.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`.
+ """
+
+ pc = pageContainer
+ agwStyle = pc.GetParent().GetAGWWindowStyleFlag()
+ rect = pc.GetClientRect()
+ clientWidth = rect.width
+
+ if agwStyle & FNB_NO_X_BUTTON:
+ return clientWidth - 38
+ else:
+ return clientWidth - 54
+
+
+ def GetRightButtonPos(self, pageContainer):
+ """
+ Returns the right button position in the navigation area.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`.
+ """
+
+ pc = pageContainer
+ agwStyle = pc.GetParent().GetAGWWindowStyleFlag()
+ rect = pc.GetClientRect()
+ clientWidth = rect.width
+
+ if agwStyle & FNB_NO_X_BUTTON:
+ return clientWidth - 22
+ else:
+ return clientWidth - 38
+
+
+ def GetDropArrowButtonPos(self, pageContainer):
+ """
+ Returns the drop down button position in the navigation area.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`.
+ """
+
+ return self.GetRightButtonPos(pageContainer)
+
+
+ def GetXPos(self, pageContainer):
+ """
+ Returns the 'X' button position in the navigation area.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`.
+ """
+
+ pc = pageContainer
+ agwStyle = pc.GetParent().GetAGWWindowStyleFlag()
+ rect = pc.GetClientRect()
+ clientWidth = rect.width
+
+ if agwStyle & FNB_NO_X_BUTTON:
+ return clientWidth
+ else:
+ return clientWidth - 22
+
+
+ def GetButtonsAreaLength(self, pageContainer):
+ """
+ Returns the navigation area width.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`.
+ """
+
+ pc = pageContainer
+ agwStyle = pc.GetParent().GetAGWWindowStyleFlag()
+
+ # ''
+ if agwStyle & FNB_NO_NAV_BUTTONS and agwStyle & FNB_NO_X_BUTTON and not agwStyle & FNB_DROPDOWN_TABS_LIST:
+ return 0
+
+ # 'x'
+ elif agwStyle & FNB_NO_NAV_BUTTONS and not agwStyle & FNB_NO_X_BUTTON and not agwStyle & FNB_DROPDOWN_TABS_LIST:
+ return 22
+
+ # '<>'
+ if not agwStyle & FNB_NO_NAV_BUTTONS and agwStyle & FNB_NO_X_BUTTON and not agwStyle & FNB_DROPDOWN_TABS_LIST:
+ return 53 - 16
+
+ # 'vx'
+ if agwStyle & FNB_DROPDOWN_TABS_LIST and not agwStyle & FNB_NO_X_BUTTON:
+ return 22 + 16
+
+ # 'v'
+ if agwStyle & FNB_DROPDOWN_TABS_LIST and agwStyle & FNB_NO_X_BUTTON:
+ return 22
+
+ # '<>x'
+ return 53
+
+
+ def DrawArrowAccordingToState(self, dc, pc, rect):
+ """
+ Draws the left and right scrolling arrows.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `pc`: an instance of :class:`FlatNotebook`;
+ :param `rect`: the client rectangle containing the scrolling arrows.
+ """
+
+ lightFactor = (pc.HasAGWFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
+ PaintStraightGradientBox(dc, rect, pc._tabAreaColour, LightColour(pc._tabAreaColour, lightFactor))
+
+
+ def DrawLeftArrow(self, pageContainer, dc):
+ """
+ Draws the left navigation arrow.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ pc = pageContainer
+
+ agwStyle = pc.GetParent().GetAGWWindowStyleFlag()
+ if agwStyle & FNB_NO_NAV_BUTTONS:
+ return
+
+ # Make sure that there are pages in the container
+ if not pc._pagesInfoVec:
+ return
+
+ if agwStyle & FNB_NAV_BUTTONS_WHEN_NEEDED:
+ if pc._pagesInfoVec[-1].GetPosition() != wx.Point(-1, -1) and pc._nFrom == 0:
+ return
+
+ # Set the bitmap according to the button status
+ if pc._nLeftButtonStatus == FNB_BTN_HOVER:
+ arrowBmp = wx.BitmapFromXPMData(left_arrow_hilite_xpm)
+ elif pc._nLeftButtonStatus == FNB_BTN_PRESSED:
+ arrowBmp = wx.BitmapFromXPMData(left_arrow_pressed_xpm)
+ else:
+ arrowBmp = wx.BitmapFromXPMData(left_arrow_xpm)
+
+ if pc._nFrom == 0:
+ # Handle disabled arrow
+ arrowBmp = wx.BitmapFromXPMData(left_arrow_disabled_xpm)
+
+ arrowBmp.SetMask(wx.Mask(arrowBmp, MASK_COLOUR))
+
+ # Erase old bitmap
+ posx = self.GetLeftButtonPos(pc)
+ self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(arrowBmp, posx, 6, True)
+
+
+ def DrawRightArrow(self, pageContainer, dc):
+ """
+ Draws the right navigation arrow.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ pc = pageContainer
+
+ agwStyle = pc.GetParent().GetAGWWindowStyleFlag()
+ if agwStyle & FNB_NO_NAV_BUTTONS:
+ return
+
+ # Make sure that there are pages in the container
+ if not pc._pagesInfoVec:
+ return
+
+ if agwStyle & FNB_NAV_BUTTONS_WHEN_NEEDED:
+ if pc._pagesInfoVec[-1].GetPosition() != wx.Point(-1, -1) and pc._nFrom == 0:
+ return
+
+ # Set the bitmap according to the button status
+ if pc._nRightButtonStatus == FNB_BTN_HOVER:
+ arrowBmp = wx.BitmapFromXPMData(right_arrow_hilite_xpm)
+ elif pc._nRightButtonStatus == FNB_BTN_PRESSED:
+ arrowBmp = wx.BitmapFromXPMData(right_arrow_pressed_xpm)
+ else:
+ arrowBmp = wx.BitmapFromXPMData(right_arrow_xpm)
+
+ # Check if the right most tab is visible, if it is
+ # don't rotate right anymore
+ if pc._pagesInfoVec[-1].GetPosition() != wx.Point(-1, -1):
+ arrowBmp = wx.BitmapFromXPMData(right_arrow_disabled_xpm)
+
+ arrowBmp.SetMask(wx.Mask(arrowBmp, MASK_COLOUR))
+
+ # erase old bitmap
+ posx = self.GetRightButtonPos(pc)
+ self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(arrowBmp, posx, 6, True)
+
+
+ def DrawDropDownArrow(self, pageContainer, dc):
+ """
+ Draws the drop-down arrow in the navigation area.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ pc = pageContainer
+
+ # Check if this style is enabled
+ agwStyle = pc.GetParent().GetAGWWindowStyleFlag()
+ if not agwStyle & FNB_DROPDOWN_TABS_LIST:
+ return
+
+ # Make sure that there are pages in the container
+ if not pc._pagesInfoVec:
+ return
+
+ if pc._nArrowDownButtonStatus == FNB_BTN_HOVER:
+ downBmp = wx.BitmapFromXPMData(down_arrow_hilite_xpm)
+ elif pc._nArrowDownButtonStatus == FNB_BTN_PRESSED:
+ downBmp = wx.BitmapFromXPMData(down_arrow_pressed_xpm)
+ else:
+ downBmp = wx.BitmapFromXPMData(down_arrow_xpm)
+
+ downBmp.SetMask(wx.Mask(downBmp, MASK_COLOUR))
+
+ # erase old bitmap
+ posx = self.GetDropArrowButtonPos(pc)
+ self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(downBmp, posx, 6, True)
+
+
+ def DrawX(self, pageContainer, dc):
+ """
+ Draw the 'X' navigation button in the navigation area.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ pc = pageContainer
+
+ # Check if this style is enabled
+ agwStyle = pc.GetParent().GetAGWWindowStyleFlag()
+ if agwStyle & FNB_NO_X_BUTTON:
+ return
+
+ # Make sure that there are pages in the container
+ if not pc._pagesInfoVec:
+ return
+
+ # Set the bitmap according to the button status
+ if pc._nXButtonStatus == FNB_BTN_HOVER:
+ xbmp = wx.BitmapFromXPMData(x_button_hilite_xpm)
+ elif pc._nXButtonStatus == FNB_BTN_PRESSED:
+ xbmp = wx.BitmapFromXPMData(x_button_pressed_xpm)
+ else:
+ xbmp = wx.BitmapFromXPMData(x_button_xpm)
+
+ xbmp.SetMask(wx.Mask(xbmp, MASK_COLOUR))
+
+ # erase old bitmap
+ posx = self.GetXPos(pc)
+ self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(xbmp, posx, 6, True)
+
+
+ def DrawTabX(self, pageContainer, dc, rect, tabIdx, btnStatus):
+ """
+ Draws the 'X' in the selected tab.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the current tab client rectangle;
+ :param `tabIdx`: the index of the current tab;
+ :param `btnStatus`: the status of the 'X' button in the current tab.
+ """
+
+ pc = pageContainer
+ if not pc.HasAGWFlag(FNB_X_ON_TAB):
+ return
+
+ # We draw the 'x' on the active tab only
+ if tabIdx != pc.GetSelection() or tabIdx < 0:
+ return
+
+ # Set the bitmap according to the button status
+
+ if btnStatus == FNB_BTN_HOVER:
+ xBmp = wx.BitmapFromXPMData(x_button_hilite_xpm)
+ elif btnStatus == FNB_BTN_PRESSED:
+ xBmp = wx.BitmapFromXPMData(x_button_pressed_xpm)
+ else:
+ xBmp = wx.BitmapFromXPMData(x_button_xpm)
+
+ # Set the masking
+ xBmp.SetMask(wx.Mask(xBmp, MASK_COLOUR))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(xBmp, rect.x, rect.y, True)
+
+ # Update the vector
+ rr = wx.Rect(rect.x, rect.y, 14, 13)
+ pc._pagesInfoVec[tabIdx].SetXRect(rr)
+
+
+ def DrawTabsLine(self, pageContainer, dc, selTabX1=-1, selTabX2=-1):
+ """
+ Draws a line over the tabs.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `selTabX1`: first x coordinate of the tab line;
+ :param `selTabX2`: second x coordinate of the tab line.
+ """
+
+ pc = pageContainer
+
+ clntRect = pc.GetClientRect()
+ clientRect3 = wx.Rect(0, 0, clntRect.width, clntRect.height)
+
+ if pc.HasAGWFlag(FNB_FF2):
+ if not pc.HasAGWFlag(FNB_BOTTOM):
+ fillColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+ else:
+ fillColour = wx.WHITE
+
+ dc.SetPen(wx.Pen(fillColour))
+
+ if pc.HasAGWFlag(FNB_BOTTOM):
+
+ dc.DrawLine(1, 0, clntRect.width-1, 0)
+ dc.DrawLine(1, 1, clntRect.width-1, 1)
+
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+ dc.DrawLine(1, 2, clntRect.width-1, 2)
+
+ dc.SetPen(wx.Pen(fillColour))
+ dc.DrawLine(selTabX1 + 2, 2, selTabX2 - 1, 2)
+
+ else:
+
+ dc.DrawLine(1, clntRect.height, clntRect.width-1, clntRect.height)
+ dc.DrawLine(1, clntRect.height-1, clntRect.width-1, clntRect.height-1)
+
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+ dc.DrawLine(1, clntRect.height-2, clntRect.width-1, clntRect.height-2)
+
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.DrawLine(selTabX1 + 2, clntRect.height-2, selTabX2-1, clntRect.height-2)
+
+ else:
+
+ if pc.HasAGWFlag(FNB_BOTTOM):
+
+ clientRect = wx.Rect(0, 2, clntRect.width, clntRect.height - 2)
+ clientRect2 = wx.Rect(0, 1, clntRect.width, clntRect.height - 1)
+
+ else:
+
+ clientRect = wx.Rect(0, 0, clntRect.width, clntRect.height - 2)
+ clientRect2 = wx.Rect(0, 0, clntRect.width, clntRect.height - 1)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(pc.GetSingleLineBorderColour()))
+ dc.DrawRectangleRect(clientRect2)
+ dc.DrawRectangleRect(clientRect3)
+
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+ dc.DrawRectangleRect(clientRect)
+
+ if not pc.HasAGWFlag(FNB_TABS_BORDER_SIMPLE):
+
+ dc.SetPen(wx.Pen((pc.HasAGWFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc._tabAreaColour])[0]))
+ dc.DrawLine(0, 0, 0, clientRect.height+1)
+
+ if pc.HasAGWFlag(FNB_BOTTOM):
+
+ dc.DrawLine(0, clientRect.height+1, clientRect.width, clientRect.height+1)
+
+ else:
+
+ dc.DrawLine(0, 0, clientRect.width, 0)
+
+ dc.DrawLine(clientRect.width - 1, 0, clientRect.width - 1, clientRect.height+1)
+
+
+ def CalcTabWidth(self, pageContainer, tabIdx, tabHeight):
+ """
+ Calculates the width of the input tab.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `tabIdx`: the index of the input tab;
+ :param `tabHeight`: the height of the tab.
+ """
+
+ pc = pageContainer
+ dc = wx.MemoryDC()
+ dc.SelectObject(wx.EmptyBitmap(1,1))
+
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+
+ if pc.IsDefaultTabs():
+ shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+
+ # Calculate the text length using the bold font, so when selecting a tab
+ # its width will not change
+ dc.SetFont(boldFont)
+ width, pom = dc.GetTextExtent(pc.GetPageText(tabIdx))
+
+ # Set a minimum size to a tab
+ if width < 20:
+ width = 20
+
+ tabWidth = 2*pc._pParent.GetPadding() + width
+
+ # Style to add a small 'x' button on the top right
+ # of the tab
+ if pc.HasAGWFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+ # The xpm image that contains the 'x' button is 9 pixels
+ spacer = 9
+ if pc.HasAGWFlag(FNB_VC8):
+ spacer = 4
+
+ tabWidth += pc._pParent.GetPadding() + spacer
+
+ if pc.IsDefaultTabs():
+ # Default style
+ tabWidth += 2*shapePoints
+
+ hasImage = pc._ImageList != None and pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+
+ # For VC71 style, we only add the icon size (16 pixels)
+ if hasImage:
+
+ if not pc.IsDefaultTabs():
+ tabWidth += 16 + pc._pParent.GetPadding()
+ else:
+ # Default style
+ tabWidth += 16 + pc._pParent.GetPadding() + shapePoints/2
+
+ return tabWidth
+
+
+ def CalcTabHeight(self, pageContainer):
+ """
+ Calculates the height of the input tab.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`.
+ """
+
+ if self._tabHeight:
+ return self._tabHeight
+
+ pc = pageContainer
+ dc = wx.MemoryDC()
+ dc.SelectObject(wx.EmptyBitmap(1,1))
+
+ # For GTK it seems that we must do this steps in order
+ # for the tabs will get the proper height on initialization
+ # on MSW, preforming these steps yields wierd results
+ normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont = normalFont
+
+ if "__WXGTK__" in wx.PlatformInfo:
+ boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+ dc.SetFont(boldFont)
+
+ height = dc.GetCharHeight()
+
+ tabHeight = height + FNB_HEIGHT_SPACER # We use 8 pixels as padding
+ if "__WXGTK__" in wx.PlatformInfo:
+ # On GTK the tabs are should be larger
+ tabHeight += 6
+
+ self._tabHeight = tabHeight
+
+ return tabHeight
+
+
+ def DrawTabs(self, pageContainer, dc):
+ """
+ Actually draws the tabs in :class:`FlatNotebook`.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ pc = pageContainer
+ if "__WXMAC__" in wx.PlatformInfo:
+ # Works well on MSW & GTK, however this lines should be skipped on MAC
+ if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec):
+ pc.Hide()
+ return
+
+ # Get the text hight
+ tabHeight = self.CalcTabHeight(pageContainer)
+ agwStyle = pc.GetParent().GetAGWWindowStyleFlag()
+
+ # Calculate the number of rows required for drawing the tabs
+ rect = pc.GetClientRect()
+ clientWidth = rect.width
+
+ # Set the maximum client size
+ pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight)
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+
+ if agwStyle & FNB_VC71:
+ backBrush = wx.Brush(wx.Colour(247, 243, 233))
+ else:
+ backBrush = wx.Brush(pc._tabAreaColour)
+
+ noselBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE))
+ selBrush = wx.Brush(pc._activeTabColour)
+
+ size = pc.GetSize()
+
+ # Background
+ dc.SetTextBackground((agwStyle & FNB_VC71 and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0])
+ dc.SetTextForeground(pc._activeTextColour)
+ dc.SetBrush(backBrush)
+
+ # If border style is set, set the pen to be border pen
+ if pc.HasAGWFlag(FNB_TABS_BORDER_SIMPLE):
+ dc.SetPen(borderPen)
+ else:
+ colr = (pc.HasAGWFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0]
+ dc.SetPen(wx.Pen(colr))
+
+ if pc.HasAGWFlag(FNB_FF2):
+ lightFactor = (pc.HasAGWFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
+ PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColour, LightColour(pc._tabAreaColour, lightFactor))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ dc.DrawRectangle(0, 0, size.x, size.y)
+
+ # We always draw the bottom/upper line of the tabs
+ # regradless the style
+ dc.SetPen(borderPen)
+
+ if not pc.HasAGWFlag(FNB_FF2):
+ self.DrawTabsLine(pc, dc)
+
+ # Restore the pen
+ dc.SetPen(borderPen)
+
+ if pc.HasAGWFlag(FNB_VC71):
+
+ greyLineYVal = (pc.HasAGWFlag(FNB_BOTTOM) and [0] or [size.y - 2])[0]
+ whiteLineYVal = (pc.HasAGWFlag(FNB_BOTTOM) and [3] or [size.y - 3])[0]
+
+ pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
+ dc.SetPen(pen)
+
+ # Draw thik grey line between the windows area and
+ # the tab area
+ for num in xrange(3):
+ dc.DrawLine(0, greyLineYVal + num, size.x, greyLineYVal + num)
+
+ wbPen = (pc.HasAGWFlag(FNB_BOTTOM) and [wx.BLACK_PEN] or [wx.WHITE_PEN])[0]
+ dc.SetPen(wbPen)
+ dc.DrawLine(1, whiteLineYVal, size.x - 1, whiteLineYVal)
+
+ # Restore the pen
+ dc.SetPen(borderPen)
+
+ # Draw labels
+ normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+ dc.SetFont(boldFont)
+
+ posx = pc._pParent.GetPadding()
+
+ # Update all the tabs from 0 to 'pc._nFrom' to be non visible
+ for i in xrange(pc._nFrom):
+
+ pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ count = pc._nFrom
+
+ #----------------------------------------------------------
+ # Go over and draw the visible tabs
+ #----------------------------------------------------------
+ x1 = x2 = -1
+ for i in xrange(pc._nFrom, len(pc._pagesInfoVec)):
+
+ dc.SetPen(borderPen)
+
+ if not pc.HasAGWFlag(FNB_FF2):
+ dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0])
+
+ # Now set the font to the correct font
+ dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0])
+
+ # Add the padding to the tab width
+ # Tab width:
+ # +-----------------------------------------------------------+
+ # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
+ # +-----------------------------------------------------------+
+ tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
+
+ # Check if we can draw more
+ if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth:
+ break
+
+ count = count + 1
+
+ # By default we clean the tab region
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ # Clean the 'x' buttn on the tab.
+ # A 'Clean' rectangle, is a rectangle with width or height
+ # with values lower than or equal to 0
+ pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1))
+
+ # Draw the tab (border, text, image & 'x' on tab)
+ self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus)
+
+ if pc.GetSelection() == i:
+ x1 = posx
+ x2 = posx + tabWidth + 2
+
+ # Restore the text forground
+ dc.SetTextForeground(pc._activeTextColour)
+
+ # Update the tab position & size
+ posy = (pc.HasAGWFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0]
+
+ pc._pagesInfoVec[i].SetPosition(wx.Point(posx, posy))
+ pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
+ self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[i])
+
+ posx += tabWidth
+
+ # Update all tabs that can not fit into the screen as non-visible
+ for i in xrange(count, len(pc._pagesInfoVec)):
+ pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ # Draw the left/right/close buttons
+ # Left arrow
+ self.DrawLeftArrow(pc, dc)
+ self.DrawRightArrow(pc, dc)
+ self.DrawX(pc, dc)
+ self.DrawDropDownArrow(pc, dc)
+
+ if pc.HasAGWFlag(FNB_FF2):
+ self.DrawTabsLine(pc, dc, x1, x2)
+
+
+ def DrawFocusRectangle(self, dc, pageContainer, page):
+ """
+ Draws a focus rectangle like the native :class:`Notebook`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `page`: an instance of :class:`PageInfo`, representing a page in the notebook.
+ """
+
+ if not page._hasFocus:
+ return
+
+ tabPos = wx.Point(*page.GetPosition())
+ if pageContainer.GetParent().GetAGWWindowStyleFlag() & FNB_VC8:
+ vc8ShapeLen = self.CalcTabHeight(pageContainer) - VERTICAL_BORDER_PADDING - 2
+ tabPos.x += vc8ShapeLen
+
+ rect = wx.RectPS(tabPos, page.GetSize())
+ rect = wx.Rect(rect.x+2, rect.y+2, rect.width-4, rect.height-8)
+
+ if wx.Platform == '__WXMAC__':
+ rect.SetWidth(rect.GetWidth() + 1)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(self._focusPen)
+ dc.DrawRoundedRectangleRect(rect, 2)
+
+
+ def DrawDragHint(self, pc, tabIdx):
+ """
+ Draws tab drag hint, the default implementation is to do nothing.
+ You can override this function to provide a nice feedback to user.
+
+ :param `pc`: an instance of :class:`FlatNotebook`;
+ :param `tabIdx`: the index of the tab we are dragging.
+
+ :note: To show your own custom drag and drop UI feedback, you must override
+ this method in your derived class.
+ """
+
+ pass
+
+
+ def NumberTabsCanFit(self, pageContainer, fr=-1):
+ """
+ Calculates the number of tabs that can fit on the available space on screen.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `fr`: the current first visible tab.
+ """
+
+ pc = pageContainer
+
+ rect = pc.GetClientRect()
+ clientWidth = rect.width
+
+ vTabInfo = []
+
+ tabHeight = self.CalcTabHeight(pageContainer)
+
+ # The drawing starts from posx
+ posx = pc._pParent.GetPadding()
+
+ if fr < 0:
+ fr = pc._nFrom
+
+ for i in xrange(fr, len(pc._pagesInfoVec)):
+
+ tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
+ if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth:
+ break;
+
+ # Add a result to the returned vector
+ tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth , tabHeight)
+ vTabInfo.append(tabRect)
+
+ # Advance posx
+ posx += tabWidth + FNB_HEIGHT_SPACER
+
+ return vTabInfo
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBRendererMgr
+# A manager that handles all the renderers defined below and calls the
+# appropriate one when drawing is needed
+# ---------------------------------------------------------------------------- #
+
+class FNBRendererMgr(object):
+ """
+ This class represents a manager that handles all the 6 renderers defined
+ and calls the appropriate one when drawing is needed.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ # register renderers
+
+ self._renderers = {}
+ self._renderers.update({-1: FNBRendererDefault()})
+ self._renderers.update({FNB_VC71: FNBRendererVC71()})
+ self._renderers.update({FNB_FANCY_TABS: FNBRendererFancy()})
+ self._renderers.update({FNB_VC8: FNBRendererVC8()})
+ self._renderers.update({FNB_RIBBON_TABS: FNBRendererRibbonTabs()})
+ self._renderers.update({FNB_FF2: FNBRendererFirefox2()})
+
+
+ def GetRenderer(self, style):
+ """
+ Returns the current renderer based on the style selected.
+
+ :param `style`: represents one of the 6 implemented styles for :class:`FlatNotebook`,
+ namely one of these bits:
+
+ ===================== ========= ======================
+ Tabs style Hex Value Description
+ ===================== ========= ======================
+ ``FNB_VC71`` 0x1 Use Visual Studio 2003 (VC7.1) style for tabs
+ ``FNB_FANCY_TABS`` 0x2 Use fancy style - square tabs filled with gradient colouring
+ ``FNB_VC8`` 0x100 Use Visual Studio 2005 (VC8) style for tabs
+ ``FNB_FF2`` 0x20000 Use Firefox 2 style for tabs
+ ``FNB_RIBBON_TABS`` 0x80000 Use the Ribbon Tabs style to render the tabs
+ ===================== ========= ======================
+
+ """
+
+ if style & FNB_VC71:
+ return self._renderers[FNB_VC71]
+
+ if style & FNB_FANCY_TABS:
+ return self._renderers[FNB_FANCY_TABS]
+
+ if style & FNB_VC8:
+ return self._renderers[FNB_VC8]
+
+ if style & FNB_FF2:
+ return self._renderers[FNB_FF2]
+
+ if style & FNB_RIBBON_TABS:
+ return self._renderers[FNB_RIBBON_TABS]
+
+ # the default is to return the default renderer
+ return self._renderers[-1]
+
+
+#------------------------------------------
+# Default renderer
+#------------------------------------------
+
+class FNBRendererDefault(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the standard renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """
+ Draws a tab using the `Standard` style.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `posx`: the x position of the tab;
+ :param `tabIdx`: the index of the tab;
+ :param `tabWidth`: the tab's width;
+ :param `tabHeight`: the tab's height;
+ :param `btnStatus`: the status of the 'X' button inside this tab.
+ """
+
+ # Default style
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ pc = pageContainer
+
+ tabPoints = [wx.Point() for ii in xrange(7)]
+ tabPoints[0].x = posx
+ tabPoints[0].y = (pc.HasAGWFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
+
+ tabPoints[1].x = int(posx+(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+ tabPoints[1].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+ tabPoints[2].x = tabPoints[1].x+2
+ tabPoints[2].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[3].x = int(posx+tabWidth-(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))-2
+ tabPoints[3].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[4].x = tabPoints[3].x+2
+ tabPoints[4].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+ tabPoints[5].x = int(tabPoints[4].x+(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+ tabPoints[5].y = (pc.HasAGWFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
+
+ tabPoints[6].x = tabPoints[0].x
+ tabPoints[6].y = tabPoints[0].y
+
+ if tabIdx == pc.GetSelection():
+
+ # Draw the tab as rounded rectangle
+ dc.DrawPolygon(tabPoints)
+
+ else:
+
+ if tabIdx != pc.GetSelection() - 1:
+
+ # Draw a vertical line to the right of the text
+ pt1x = tabPoints[5].x
+ pt1y = (pc.HasAGWFlag(FNB_BOTTOM) and [4] or [tabHeight - 6])[0]
+ pt2x = tabPoints[5].x
+ pt2y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - 4] or [4])[0]
+ dc.DrawLine(pt1x, pt1y, pt2x, pt2y)
+
+ if tabIdx == pc.GetSelection():
+
+ savePen = dc.GetPen()
+ whitePen = wx.Pen(wx.WHITE)
+ whitePen.SetWidth(1)
+ dc.SetPen(whitePen)
+
+ secPt = wx.Point(tabPoints[5].x + 1, tabPoints[5].y)
+ dc.DrawLine(tabPoints[0].x, tabPoints[0].y, secPt.x, secPt.y)
+
+ # Restore the pen
+ dc.SetPen(savePen)
+
+ # -----------------------------------
+ # Text and image drawing
+ # -----------------------------------
+
+ # Text drawing offset from the left border of the
+ # rectangle
+
+ # The width of the images are 16 pixels
+ padding = pc.GetParent().GetPadding()
+ shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+ hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+ imageYCoord = (pc.HasAGWFlag(FNB_BOTTOM) and [6] or [8])[0]
+
+ if hasImage:
+ textOffset = 2*pc._pParent._nPadding + 16 + shapePoints/2
+ else:
+ textOffset = pc._pParent._nPadding + shapePoints/2
+
+ textOffset += 2
+
+ if tabIdx != pc.GetSelection():
+
+ # Set the text background to be like the vertical lines
+ dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
+
+ if hasImage:
+
+ imageXOffset = textOffset - 16 - padding
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ pageTextColour = pc._pParent.GetPageTextColour(tabIdx)
+ if pageTextColour is not None:
+ dc.SetTextForeground(pageTextColour)
+
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasAGWFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+
+#------------------------------------------
+# Firefox2 renderer
+#------------------------------------------
+class FNBRendererFirefox2(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the `Firefox 2` renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """
+ Draws a tab using the `Firefox 2` style.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `posx`: the x position of the tab;
+ :param `tabIdx`: the index of the tab;
+ :param `tabWidth`: the tab's width;
+ :param `tabHeight`: the tab's height;
+ :param `btnStatus`: the status of the 'X' button inside this tab.
+ """
+
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ pc = pageContainer
+
+ tabPoints = [wx.Point() for indx in xrange(7)]
+ tabPoints[0].x = posx + 2
+ tabPoints[0].y = (pc.HasAGWFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
+
+ tabPoints[1].x = tabPoints[0].x
+ tabPoints[1].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+ tabPoints[2].x = tabPoints[1].x+2
+ tabPoints[2].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[3].x = posx + tabWidth - 2
+ tabPoints[3].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[4].x = tabPoints[3].x + 2
+ tabPoints[4].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+ tabPoints[5].x = tabPoints[4].x
+ tabPoints[5].y = (pc.HasAGWFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
+
+ tabPoints[6].x = tabPoints[0].x
+ tabPoints[6].y = tabPoints[0].y
+
+ #------------------------------------
+ # Paint the tab with gradient
+ #------------------------------------
+ rr = wx.RectPP(tabPoints[2], tabPoints[5])
+ DrawButton(dc, rr, pc.GetSelection() == tabIdx , not pc.HasAGWFlag(FNB_BOTTOM))
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(borderPen)
+
+ # Draw the tab as rounded rectangle
+ dc.DrawPolygon(tabPoints)
+
+ # -----------------------------------
+ # Text and image drawing
+ # -----------------------------------
+
+ # The width of the images are 16 pixels
+ padding = pc.GetParent().GetPadding()
+ shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+ hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+ imageYCoord = (pc.HasAGWFlag(FNB_BOTTOM) and [6] or [8])[0]
+
+ if hasImage:
+ textOffset = 2*padding + 16 + shapePoints/2
+ else:
+ textOffset = padding + shapePoints/2
+
+ textOffset += 2
+
+ if tabIdx != pc.GetSelection():
+
+ # Set the text background to be like the vertical lines
+ dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
+
+ if hasImage:
+ imageXOffset = textOffset - 16 - padding
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ pageTextColour = pc._pParent.GetPageTextColour(tabIdx)
+ if pageTextColour is not None:
+ dc.SetTextForeground(pageTextColour)
+
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasAGWFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+
+#------------------------------------------------------------------
+# Visual studio 7.1
+#------------------------------------------------------------------
+
+class FNBRendererVC71(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the `VC71` renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """
+ Draws a tab using the `VC71` style.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `posx`: the x position of the tab;
+ :param `tabIdx`: the index of the tab;
+ :param `tabWidth`: the tab's width;
+ :param `tabHeight`: the tab's height;
+ :param `btnStatus`: the status of the 'X' button inside this tab.
+ """
+
+ # Visual studio 7.1 style
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ pc = pageContainer
+
+ dc.SetPen((tabIdx == pc.GetSelection() and [wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))] or [borderPen])[0])
+ dc.SetBrush((tabIdx == pc.GetSelection() and [wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))] or [wx.Brush(wx.Colour(247, 243, 233))])[0])
+
+ if tabIdx == pc.GetSelection():
+
+ posy = (pc.HasAGWFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0]
+ tabH = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - 5] or [tabHeight - 3])[0]
+ dc.DrawRectangle(posx, posy, tabWidth, tabH)
+
+ # Draw a black line on the left side of the
+ # rectangle
+ dc.SetPen(wx.BLACK_PEN)
+
+ blackLineY1 = VERTICAL_BORDER_PADDING
+ blackLineY2 = tabH
+ dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2)
+
+ # To give the tab more 3D look we do the following
+ # Incase the tab is on top,
+ # Draw a thik white line on topof the rectangle
+ # Otherwise, draw a thin (1 pixel) black line at the bottom
+
+ pen = wx.Pen((pc.HasAGWFlag(FNB_BOTTOM) and [wx.BLACK] or [wx.WHITE])[0])
+ dc.SetPen(pen)
+ whiteLinePosY = (pc.HasAGWFlag(FNB_BOTTOM) and [blackLineY2] or [VERTICAL_BORDER_PADDING ])[0]
+ dc.DrawLine(posx , whiteLinePosY, posx + tabWidth + 1, whiteLinePosY)
+
+ # Draw a white vertical line to the left of the tab
+ dc.SetPen(wx.WHITE_PEN)
+ if not pc.HasAGWFlag(FNB_BOTTOM):
+ blackLineY2 += 1
+
+ dc.DrawLine(posx, blackLineY1, posx, blackLineY2)
+
+ else:
+
+ # We dont draw a rectangle for non selected tabs, but only
+ # vertical line on the left
+
+ blackLineY1 = (pc.HasAGWFlag(FNB_BOTTOM) and [VERTICAL_BORDER_PADDING + 2] or [VERTICAL_BORDER_PADDING + 1])[0]
+ blackLineY2 = pc.GetSize().y - 5
+ dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2)
+
+ # -----------------------------------
+ # Text and image drawing
+ # -----------------------------------
+
+ # Text drawing offset from the left border of the
+ # rectangle
+
+ # The width of the images are 16 pixels
+ padding = pc.GetParent().GetPadding()
+ hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+ imageYCoord = (pc.HasAGWFlag(FNB_BOTTOM) and [5] or [8])[0]
+
+ if hasImage:
+ textOffset = 2*pc._pParent._nPadding + 16
+ else:
+ textOffset = pc._pParent._nPadding
+
+ if tabIdx != pc.GetSelection():
+
+ # Set the text background to be like the vertical lines
+ dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
+
+ if hasImage:
+
+ imageXOffset = textOffset - 16 - padding
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ pageTextColour = pc._pParent.GetPageTextColour(tabIdx)
+ if pageTextColour is not None:
+ dc.SetTextForeground(pageTextColour)
+
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasAGWFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+
+#------------------------------------------------------------------
+# Fancy style
+#------------------------------------------------------------------
+
+class FNBRendererFancy(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the `Fancy` renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """
+ Draws a tab using the `Fancy` style, similar to the `VC71` one but with gradients.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `posx`: the x position of the tab;
+ :param `tabIdx`: the index of the tab;
+ :param `tabWidth`: the tab's width;
+ :param `tabHeight`: the tab's height;
+ :param `btnStatus`: the status of the 'X' button inside this tab.
+ """
+
+ # Fancy tabs - like with VC71 but with the following differences:
+ # - The Selected tab is coloured with gradient colour
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ pc = pageContainer
+
+ pen = (tabIdx == pc.GetSelection() and [wx.Pen(pc._pParent.GetBorderColour())] or [wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))])[0]
+
+ if tabIdx == pc.GetSelection():
+
+ posy = (pc.HasAGWFlag(FNB_BOTTOM) and [2] or [VERTICAL_BORDER_PADDING])[0]
+ th = tabHeight - 5
+
+ rect = wx.Rect(posx, posy, tabWidth, th)
+
+ col2 = (pc.HasAGWFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourTo()] or [pc._pParent.GetGradientColourFrom()])[0]
+ col1 = (pc.HasAGWFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourFrom()] or [pc._pParent.GetGradientColourTo()])[0]
+
+ PaintStraightGradientBox(dc, rect, col1, col2)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(pen)
+ dc.DrawRectangleRect(rect)
+
+ # erase the bottom/top line of the rectangle
+ dc.SetPen(wx.Pen(pc._pParent.GetGradientColourFrom()))
+ if pc.HasAGWFlag(FNB_BOTTOM):
+ dc.DrawLine(rect.x, 2, rect.x + rect.width, 2)
+ else:
+ dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1)
+
+ else:
+
+ # We dont draw a rectangle for non selected tabs, but only
+ # vertical line on the left
+ dc.SetPen(borderPen)
+ dc.DrawLine(posx + tabWidth, VERTICAL_BORDER_PADDING + 3, posx + tabWidth, tabHeight - 4)
+
+
+ # -----------------------------------
+ # Text and image drawing
+ # -----------------------------------
+
+ # Text drawing offset from the left border of the
+ # rectangle
+
+ # The width of the images are 16 pixels
+ padding = pc.GetParent().GetPadding()
+ hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+ imageYCoord = (pc.HasAGWFlag(FNB_BOTTOM) and [6] or [8])[0]
+
+ if hasImage:
+ textOffset = 2*pc._pParent._nPadding + 16
+ else:
+ textOffset = pc._pParent._nPadding
+
+ textOffset += 2
+
+ if tabIdx != pc.GetSelection():
+
+ # Set the text background to be like the vertical lines
+ dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
+
+ if hasImage:
+
+ imageXOffset = textOffset - 16 - padding
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ pageTextColour = pc._pParent.GetPageTextColour(tabIdx)
+ if pageTextColour is not None:
+ dc.SetTextForeground(pageTextColour)
+
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasAGWFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+
+#------------------------------------------------------------------
+# Visual studio 2005 (VS8)
+#------------------------------------------------------------------
+class FNBRendererVC8(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the `VC8` renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+ self._first = True
+ self._factor = 1
+
+
+ def DrawTabs(self, pageContainer, dc):
+ """
+ Draws all the tabs using `VC8` style.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ pc = pageContainer
+
+ if "__WXMAC__" in wx.PlatformInfo:
+ # Works well on MSW & GTK, however this lines should be skipped on MAC
+ if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec):
+ pc.Hide()
+ return
+
+ # Get the text hight
+ tabHeight = self.CalcTabHeight(pageContainer)
+
+ # Set the font for measuring the tab height
+ normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+
+ # Calculate the number of rows required for drawing the tabs
+ rect = pc.GetClientRect()
+
+ # Set the maximum client size
+ pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight)
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+
+ # Create brushes
+ backBrush = wx.Brush(pc._tabAreaColour)
+ noselBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE))
+ selBrush = wx.Brush(pc._activeTabColour)
+ size = pc.GetSize()
+
+ # Background
+ dc.SetTextBackground(pc.GetBackgroundColour())
+ dc.SetTextForeground(pc._activeTextColour)
+
+ # If border style is set, set the pen to be border pen
+ if pc.HasAGWFlag(FNB_TABS_BORDER_SIMPLE):
+ dc.SetPen(borderPen)
+ else:
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ lightFactor = (pc.HasAGWFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
+
+ # For VC8 style, we colour the tab area in gradient colouring
+ lightcolour = LightColour(pc._tabAreaColour, lightFactor)
+ PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColour, lightcolour)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(0, 0, size.x, size.y)
+
+ # We always draw the bottom/upper line of the tabs
+ # regradless the style
+ dc.SetPen(borderPen)
+ self.DrawTabsLine(pc, dc)
+
+ # Restore the pen
+ dc.SetPen(borderPen)
+
+ # Draw labels
+ dc.SetFont(boldFont)
+
+ # Update all the tabs from 0 to 'pc.self._nFrom' to be non visible
+ for i in xrange(pc._nFrom):
+
+ pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ # Draw the visible tabs, in VC8 style, we draw them from right to left
+ vTabsInfo = self.NumberTabsCanFit(pc)
+
+ activeTabPosx = 0
+ activeTabWidth = 0
+ activeTabHeight = 0
+
+ for cur in xrange(len(vTabsInfo)-1, -1, -1):
+
+ # 'i' points to the index of the currently drawn tab
+ # in pc.GetPageInfoVector() vector
+ i = pc._nFrom + cur
+ dc.SetPen(borderPen)
+ dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0])
+
+ # Now set the font to the correct font
+ dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0])
+
+ # Add the padding to the tab width
+ # Tab width:
+ # +-----------------------------------------------------------+
+ # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
+ # +-----------------------------------------------------------+
+
+ tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
+ posx = vTabsInfo[cur].x
+
+ # By default we clean the tab region
+ # incase we use the VC8 style which requires
+ # the region, it will be filled by the function
+ # drawVc8Tab
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ # Clean the 'x' buttn on the tab
+ # 'Clean' rectanlge is a rectangle with width or height
+ # with values lower than or equal to 0
+ pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1))
+
+ # Draw the tab
+ # Incase we are drawing the active tab
+ # we need to redraw so it will appear on top
+ # of all other tabs
+
+ # when using the vc8 style, we keep the position of the active tab so we will draw it again later
+ if i == pc.GetSelection() and pc.HasAGWFlag(FNB_VC8):
+
+ activeTabPosx = posx
+ activeTabWidth = tabWidth
+ activeTabHeight = tabHeight
+
+ else:
+
+ self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus)
+
+ # Restore the text forground
+ dc.SetTextForeground(pc._activeTextColour)
+
+ # Update the tab position & size
+ pc._pagesInfoVec[i].SetPosition(wx.Point(posx, VERTICAL_BORDER_PADDING))
+ pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
+
+ # Incase we are in VC8 style, redraw the active tab (incase it is visible)
+ if pc.GetSelection() >= pc._nFrom and pc.GetSelection() < pc._nFrom + len(vTabsInfo):
+
+ self.DrawTab(pc, dc, activeTabPosx, pc.GetSelection(), activeTabWidth, activeTabHeight, pc._nTabXButtonStatus)
+
+ # Update all tabs that can not fit into the screen as non-visible
+ for xx in xrange(pc._nFrom + len(vTabsInfo), len(pc._pagesInfoVec)):
+
+ pc._pagesInfoVec[xx].SetPosition(wx.Point(-1, -1))
+ pc._pagesInfoVec[xx].GetRegion().Clear()
+
+ # Draw the left/right/close buttons
+ # Left arrow
+ self.DrawLeftArrow(pc, dc)
+ self.DrawRightArrow(pc, dc)
+ self.DrawX(pc, dc)
+ self.DrawDropDownArrow(pc, dc)
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """
+ Draws a tab using the `VC8` style.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `posx`: the x position of the tab;
+ :param `tabIdx`: the index of the tab;
+ :param `tabWidth`: the tab's width;
+ :param `tabHeight`: the tab's height;
+ :param `btnStatus`: the status of the 'X' button inside this tab.
+ """
+
+ pc = pageContainer
+ borderPen = wx.Pen(pc._pParent.GetBorderColour())
+ tabPoints = [wx.Point() for ii in xrange(8)]
+
+ # If we draw the first tab or the active tab,
+ # we draw a full tab, else we draw a truncated tab
+ #
+ # X(2) X(3)
+ # X(1) X(4)
+ #
+ # X(5)
+ #
+ # X(0),(7) X(6)
+ #
+ #
+
+ tabPoints[0].x = (pc.HasAGWFlag(FNB_BOTTOM) and [posx] or [posx+self._factor])[0]
+ tabPoints[0].y = (pc.HasAGWFlag(FNB_BOTTOM) and [2] or [tabHeight - 3])[0]
+
+ tabPoints[1].x = tabPoints[0].x + tabHeight - VERTICAL_BORDER_PADDING - 3 - self._factor
+ tabPoints[1].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+ tabPoints[2].x = tabPoints[1].x + 4
+ tabPoints[2].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[3].x = tabPoints[2].x + tabWidth - 2
+ tabPoints[3].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[4].x = tabPoints[3].x + 1
+ tabPoints[4].y = (pc.HasAGWFlag(FNB_BOTTOM) and [tabPoints[3].y - 1] or [tabPoints[3].y + 1])[0]
+
+ tabPoints[5].x = tabPoints[4].x + 1
+ tabPoints[5].y = (pc.HasAGWFlag(FNB_BOTTOM) and [(tabPoints[4].y - 1)] or [tabPoints[4].y + 1])[0]
+
+ tabPoints[6].x = tabPoints[2].x + tabWidth
+ tabPoints[6].y = tabPoints[0].y
+
+ tabPoints[7].x = tabPoints[0].x
+ tabPoints[7].y = tabPoints[0].y
+
+ pc._pagesInfoVec[tabIdx].SetRegion(tabPoints)
+
+ # Draw the polygon
+ br = dc.GetBrush()
+ dc.SetBrush(wx.Brush((tabIdx == pc.GetSelection() and [pc._activeTabColour] or [pc._colourTo])[0]))
+ dc.SetPen(wx.Pen((tabIdx == pc.GetSelection() and [wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)] or [pc._colourBorder])[0]))
+ dc.DrawPolygon(tabPoints)
+
+ # Restore the brush
+ dc.SetBrush(br)
+ rect = pc.GetClientRect()
+
+ if tabIdx != pc.GetSelection() and not pc.HasAGWFlag(FNB_BOTTOM):
+
+ # Top default tabs
+ dc.SetPen(wx.Pen(pc._pParent.GetBorderColour()))
+ lineY = rect.height
+ curPen = dc.GetPen()
+ curPen.SetWidth(1)
+ dc.SetPen(curPen)
+ dc.DrawLine(posx, lineY, posx+rect.width, lineY)
+
+ # Incase we are drawing the selected tab, we draw the border of it as well
+ # but without the bottom (upper line incase of wxBOTTOM)
+ if tabIdx == pc.GetSelection():
+
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ dc.SetPen(borderPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawPolygon(tabPoints)
+
+ # Delete the bottom line (or the upper one, incase we use wxBOTTOM)
+ dc.SetPen(wx.WHITE_PEN)
+ dc.DrawLine(tabPoints[0].x, tabPoints[0].y, tabPoints[6].x, tabPoints[6].y)
+
+ self.FillVC8GradientColour(pc, dc, tabPoints, tabIdx == pc.GetSelection(), tabIdx)
+
+ # Draw a thin line to the right of the non-selected tab
+ if tabIdx != pc.GetSelection():
+
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.DrawLine(tabPoints[4].x-1, tabPoints[4].y, tabPoints[5].x-1, tabPoints[5].y)
+ dc.DrawLine(tabPoints[5].x-1, tabPoints[5].y, tabPoints[6].x-1, tabPoints[6].y)
+
+ # Text drawing offset from the left border of the
+ # rectangle
+
+ # The width of the images are 16 pixels
+ vc8ShapeLen = tabHeight - VERTICAL_BORDER_PADDING - 2
+ if pc.TabHasImage(tabIdx):
+ textOffset = 2*pc._pParent.GetPadding() + 16 + vc8ShapeLen
+ else:
+ textOffset = pc._pParent.GetPadding() + vc8ShapeLen
+
+ # Draw the image for the tab if any
+ imageYCoord = (pc.HasAGWFlag(FNB_BOTTOM) and [6] or [8])[0]
+
+ if pc.TabHasImage(tabIdx):
+
+ imageXOffset = textOffset - 16 - pc._pParent.GetPadding()
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+ # if selected tab, draw text in bold
+ if tabIdx == pc.GetSelection():
+ boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+
+ dc.SetFont(boldFont)
+
+ pageTextColour = pc._pParent.GetPageTextColour(tabIdx)
+ if pageTextColour is not None:
+ dc.SetTextForeground(pageTextColour)
+
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasAGWFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+ self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[tabIdx])
+
+
+ def FillVC8GradientColour(self, pageContainer, dc, tabPoints, bSelectedTab, tabIdx):
+ """
+ Fills a tab with a gradient shading.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `tabPoints`: a Python list of :class:`Point` representing the tab outline;
+ :param `bSelectedTab`: ``True`` if the tab is selected, ``False`` otherwise;
+ :param `tabIdx`: the index of the tab;
+ """
+
+ # calculate gradient coefficients
+ pc = pageContainer
+
+ if self._first:
+ self._first = False
+ pc._colourTo = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 0)
+ pc._colourFrom = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 60)
+
+ col2 = pc._pParent.GetGradientColourTo()
+ col1 = pc._pParent.GetGradientColourFrom()
+
+ # If colourful tabs style is set, override the tab colour
+ if pc.HasAGWFlag(FNB_COLOURFUL_TABS):
+
+ if not pc._pagesInfoVec[tabIdx].GetColour():
+
+ # First time, generate colour, and keep it in the vector
+ tabColour = RandomColour()
+ pc._pagesInfoVec[tabIdx].SetColour(tabColour)
+
+ if pc.HasAGWFlag(FNB_BOTTOM):
+
+ col2 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 50)
+ col1 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 80)
+
+ else:
+
+ col1 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 50)
+ col2 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 80)
+
+ size = abs(tabPoints[2].y - tabPoints[0].y) - 1
+
+ rf, gf, bf = 0, 0, 0
+ rstep = float(col2.Red() - col1.Red())/float(size)
+ gstep = float(col2.Green() - col1.Green())/float(size)
+ bstep = float(col2.Blue() - col1.Blue())/float(size)
+
+ y = tabPoints[0].y
+
+ # If we are drawing the selected tab, we need also to draw a line
+ # from 0.tabPoints[0].x and tabPoints[6].x . end, we achieve this
+ # by drawing the rectangle with transparent brush
+ # the line under the selected tab will be deleted by the drwaing loop
+ if bSelectedTab:
+ self.DrawTabsLine(pc, dc)
+
+ while 1:
+
+ if pc.HasAGWFlag(FNB_BOTTOM):
+
+ if y > tabPoints[0].y + size:
+ break
+
+ else:
+
+ if y < tabPoints[0].y - size:
+ break
+
+ currCol = wx.Colour(col1.Red() + rf, col1.Green() + gf, col1.Blue() + bf)
+
+ dc.SetPen((bSelectedTab and [wx.Pen(pc._activeTabColour)] or [wx.Pen(currCol)])[0])
+ startX = self.GetStartX(tabPoints, y, pc.GetParent().GetAGWWindowStyleFlag())
+ endX = self.GetEndX(tabPoints, y, pc.GetParent().GetAGWWindowStyleFlag())
+ dc.DrawLine(startX, y, endX, y)
+
+ # Draw the border using the 'edge' point
+ dc.SetPen(wx.Pen((bSelectedTab and [wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)] or [pc._colourBorder])[0]))
+
+ dc.DrawPoint(startX, y)
+ dc.DrawPoint(endX, y)
+
+ # Progress the colour
+ rf += rstep
+ gf += gstep
+ bf += bstep
+
+ if pc.HasAGWFlag(FNB_BOTTOM):
+ y = y + 1
+ else:
+ y = y - 1
+
+
+ def GetStartX(self, tabPoints, y, style):
+ """
+ Returns the `x` start position of a tab.
+
+ :param `tabPoints`: a Python list of :class:`Point` representing the tab outline;
+ :param `y`: the y start position of the tab;
+ :param `style`: can be ``FNB_BOTTOM`` or the default (tabs at top).
+ """
+
+ x1, x2, y1, y2 = 0.0, 0.0, 0.0, 0.0
+
+ # We check the 3 points to the left
+
+ bBottomStyle = (style & FNB_BOTTOM and [True] or [False])[0]
+ match = False
+
+ if bBottomStyle:
+
+ for i in xrange(3):
+
+ if y >= tabPoints[i].y and y < tabPoints[i+1].y:
+
+ x1 = tabPoints[i].x
+ x2 = tabPoints[i+1].x
+ y1 = tabPoints[i].y
+ y2 = tabPoints[i+1].y
+ match = True
+ break
+
+ else:
+
+ for i in xrange(3):
+
+ if y <= tabPoints[i].y and y > tabPoints[i+1].y:
+
+ x1 = tabPoints[i].x
+ x2 = tabPoints[i+1].x
+ y1 = tabPoints[i].y
+ y2 = tabPoints[i+1].y
+ match = True
+ break
+
+ if not match:
+ return tabPoints[2].x
+
+ # According to the equation y = ax + b => x = (y-b)/a
+ # We know the first 2 points
+
+ x1, x2, y1, y2 = map(float, (x1, x2, y1, y2))
+
+ if abs(x2 - x1) < 1e-6:
+ return x2
+ else:
+ a = (y2 - y1)/(x2 - x1)
+
+ b = y1 - ((y2 - y1)/(x2 - x1))*x1
+
+ if a == 0:
+ return int(x1)
+
+ x = (y - b)/a
+
+ return int(x)
+
+
+ def GetEndX(self, tabPoints, y, style):
+ """
+ Returns the `x` end position of a tab.
+
+ :param `tabPoints`: a Python list of :class:`Point` representing the tab outline;
+ :param `y`: the y end position of the tab;
+ :param `style`: can be ``FNB_BOTTOM`` or the default (tabs at top).
+ """
+
+ x1, x2, y1, y2 = 0.0, 0.0, 0.0, 0.0
+
+ # We check the 3 points to the left
+ bBottomStyle = (style & FNB_BOTTOM and [True] or [False])[0]
+ match = False
+
+ if bBottomStyle:
+
+ for i in xrange(7, 3, -1):
+
+ if y >= tabPoints[i].y and y < tabPoints[i-1].y:
+
+ x1 = tabPoints[i].x
+ x2 = tabPoints[i-1].x
+ y1 = tabPoints[i].y
+ y2 = tabPoints[i-1].y
+ match = True
+ break
+
+ else:
+
+ for i in xrange(7, 3, -1):
+
+ if y <= tabPoints[i].y and y > tabPoints[i-1].y:
+
+ x1 = tabPoints[i].x
+ x2 = tabPoints[i-1].x
+ y1 = tabPoints[i].y
+ y2 = tabPoints[i-1].y
+ match = True
+ break
+
+ if not match:
+ return tabPoints[3].x
+
+ # According to the equation y = ax + b => x = (y-b)/a
+ # We know the first 2 points
+
+ # Vertical line
+ if x1 == x2:
+ return int(x1)
+
+ a = (y2 - y1)/(x2 - x1)
+ b = y1 - ((y2 - y1)/(x2 - x1))*x1
+
+ if a == 0:
+ return int(x1)
+
+ x = (y - b)/a
+
+ return int(x)
+
+
+ def NumberTabsCanFit(self, pageContainer, fr=-1):
+ """
+ Calculates the number of tabs that can fit on the available space on screen.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `fr`: the current first visible tab.
+ """
+
+ pc = pageContainer
+
+ rect = pc.GetClientRect()
+ clientWidth = rect.width
+
+ # Empty results
+ vTabInfo = []
+ tabHeight = self.CalcTabHeight(pageContainer)
+
+ # The drawing starts from posx
+ posx = pc._pParent.GetPadding()
+
+ if fr < 0:
+ fr = pc._nFrom
+
+ for i in xrange(fr, len(pc._pagesInfoVec)):
+
+ vc8glitch = tabHeight + FNB_HEIGHT_SPACER
+ tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
+
+ if posx + tabWidth + vc8glitch + self.GetButtonsAreaLength(pc) >= clientWidth:
+ break
+
+ # Add a result to the returned vector
+ tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth, tabHeight)
+ vTabInfo.append(tabRect)
+
+ # Advance posx
+ posx += tabWidth + FNB_HEIGHT_SPACER
+
+ return vTabInfo
+
+#------------------------------------------------------------------
+# Ribbon Tabs style
+#------------------------------------------------------------------
+class FNBRendererRibbonTabs(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the `Ribbon Tabs` renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+ self._first = True
+ self._factor = 1
+
+ # definte this because we don't want to use the bold font
+ def CalcTabWidth(self, pageContainer, tabIdx, tabHeight):
+ """
+ Calculates the width of the input tab.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `tabIdx`: the index of the input tab;
+ :param `tabHeight`: the height of the tab.
+ """
+
+ pc = pageContainer
+ dc = wx.MemoryDC()
+ dc.SelectObject(wx.EmptyBitmap(1,1))
+
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+ if pc.IsDefaultTabs():
+ shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+
+ dc.SetFont(font)
+ width, pom = dc.GetTextExtent(pc.GetPageText(tabIdx))
+
+ # Set a minimum size to a tab
+ if width < 20:
+ width = 20
+
+ tabWidth = 2*pc._pParent.GetPadding() + width
+
+ # Style to add a small 'x' button on the top right
+ # of the tab
+ if pc.HasAGWFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+ # The xpm image that contains the 'x' button is 9 pixels
+ spacer = 9
+ if pc.HasAGWFlag(FNB_VC8):
+ spacer = 4
+
+ tabWidth += pc._pParent.GetPadding() + spacer
+
+ if pc.IsDefaultTabs():
+ # Default style
+ tabWidth += 2*shapePoints
+
+ hasImage = pc._ImageList != None and pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+
+ # For VC71 style, we only add the icon size (16 pixels)
+ if hasImage:
+
+ if not pc.IsDefaultTabs():
+ tabWidth += 16 + pc._pParent.GetPadding()
+ else:
+ # Default style
+ tabWidth += 16 + pc._pParent.GetPadding() + shapePoints/2
+
+ return tabWidth
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """
+ Draws a tab using the `Ribbon Tabs` style.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `posx`: the x position of the tab;
+ :param `tabIdx`: the index of the tab;
+ :param `tabWidth`: the tab's width;
+ :param `tabHeight`: the tab's height;
+ :param `btnStatus`: the status of the 'X' button inside this tab.
+ """
+
+ pc = pageContainer
+
+ gc = wx.GraphicsContext.Create(dc)
+ gc.SetPen(dc.GetPen())
+ gc.SetBrush(dc.GetBrush())
+
+ spacer = math.ceil(float(FNB_HEIGHT_SPACER)/2/2)
+ gc.DrawRoundedRectangle(posx+1,spacer,tabWidth-1,tabHeight-spacer*2,5)
+
+ if tabIdx == pc.GetSelection():
+ pass
+ else:
+ if tabIdx != pc.GetSelection() - 1:
+ pass
+
+ # -----------------------------------
+ # Text and image drawing
+ # -----------------------------------
+
+ # Text drawing offset from the left border of the
+ # rectangle
+
+ # The width of the images are 16 pixels
+ padding = pc.GetParent().GetPadding()
+ hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+ imageYCoord = FNB_HEIGHT_SPACER/2
+
+ if hasImage:
+ textOffset = 2*pc._pParent._nPadding + 16
+ else:
+ textOffset = pc._pParent._nPadding
+
+ textOffset += 2
+
+ if tabIdx != pc.GetSelection():
+
+ # Set the text background to be like the vertical lines
+ dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
+
+ if hasImage:
+
+ imageXOffset = textOffset - 16 - padding
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ pageTextColour = pc._pParent.GetPageTextColour(tabIdx)
+ if pageTextColour is not None:
+ dc.SetTextForeground(pageTextColour)
+
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasAGWFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+
+ def DrawTabs(self, pageContainer, dc):
+ """
+ Actually draws the tabs in :class:`FlatNotebook`.
+
+ :param `pageContainer`: an instance of :class:`FlatNotebook`;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ pc = pageContainer
+ #style = pc.GetParent().GetWindowStyleFlag()
+
+ if "__WXMAC__" in wx.PlatformInfo:
+ # Works well on MSW & GTK, however this lines should be skipped on MAC
+ if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec):
+ pc.Hide()
+ return
+
+ # Get the text height
+ tabHeight = self.CalcTabHeight(pageContainer)
+
+ # Calculate the number of rows required for drawing the tabs
+ rect = pc.GetClientRect()
+ clientWidth = rect.width
+
+ # Set the maximum client size
+ pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight)
+
+ size = pc.GetSize()
+
+ # Background
+ dc.SetTextBackground(pc.GetBackgroundColour())
+ dc.SetTextForeground(pc._activeTextColour)
+
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ backBrush = wx.Brush(pc._tabAreaColour)
+
+ # If border style is set, set the pen to be border pen
+ if pc.HasAGWFlag(FNB_TABS_BORDER_SIMPLE):
+ dc.SetPen(borderPen)
+ else:
+ dc.SetPen(wx.Pen(pc._tabAreaColour))
+
+ dc.SetBrush(backBrush)
+ dc.DrawRectangle(0, 0, size.x, size.y)
+
+ # Draw labels
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ dc.SetFont(font)
+
+ posx = pc._pParent.GetPadding()
+
+ # Update all the tabs from 0 to 'pc._nFrom' to be non visible
+ for i in xrange(pc._nFrom):
+ pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
+
+ count = pc._nFrom
+
+ #----------------------------------------------------------
+ # Go over and draw the visible tabs
+ #----------------------------------------------------------
+ selPen = wx.Pen(adjust_colour(pc._tabAreaColour, -20))
+ noselPen = wx.Pen(pc._tabAreaColour)
+ noselBrush = wx.Brush(pc._tabAreaColour)
+ selBrush = wx.Brush(LightColour(pc._tabAreaColour,60))
+
+ for i in xrange(pc._nFrom, len(pc._pagesInfoVec)):
+
+ # This style highlights the selected tab and the tab the mouse is over
+ highlight = (i==pc.GetSelection()) or pc.IsMouseHovering(i)
+ dc.SetPen((highlight and [selPen] or [noselPen])[0])
+ dc.SetBrush((highlight and [selBrush] or [noselBrush])[0])
+
+ # Add the padding to the tab width
+ # Tab width:
+ # +-----------------------------------------------------------+
+ # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
+ # +-----------------------------------------------------------+
+ tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
+
+ # Check if we can draw more
+ if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth:
+ break
+
+ count = count + 1
+
+ # By default we clean the tab region
+ #pc._pagesInfoVec[i].GetRegion().Clear()
+
+ # Clean the 'x' buttn on the tab.
+ # A 'Clean' rectangle, is a rectangle with width or height
+ # with values lower than or equal to 0
+ pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1))
+
+ # Draw the tab (border, text, image & 'x' on tab)
+ self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus)
+
+ # Restore the text forground
+ dc.SetTextForeground(pc._activeTextColour)
+
+ # Update the tab position & size
+ posy = (pc.HasAGWFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0]
+
+ pc._pagesInfoVec[i].SetPosition(wx.Point(posx, posy))
+ pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
+
+ posx += tabWidth
+
+ # Update all tabs that can not fit into the screen as non-visible
+ for i in xrange(count, len(pc._pagesInfoVec)):
+ pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ # Draw the left/right/close buttons
+ # Left arrow
+ self.DrawLeftArrow(pc, dc)
+ self.DrawRightArrow(pc, dc)
+ self.DrawX(pc, dc)
+ self.DrawDropDownArrow(pc, dc)
+
+# ---------------------------------------------------------------------------- #
+# Class FlatNotebook
+# ---------------------------------------------------------------------------- #
+
+class FlatNotebook(wx.PyPanel):
+ """
+ The :class:`FlatNotebook` is a full implementation of the :class:`Notebook`, and designed to be
+ a drop-in replacement for :class:`Notebook`. The API functions are similar so one can
+ expect the function to behave in the same way.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=0, name="FlatNotebook"):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`FlatNotebook` parent;
+ :param `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`PyPanel` window style;
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ ================================ =========== ==================================================
+ Window Styles Hex Value Description
+ ================================ =========== ==================================================
+ ``FNB_VC71`` 0x1 Use Visual Studio 2003 (VC7.1) style for tabs.
+ ``FNB_FANCY_TABS`` 0x2 Use fancy style - square tabs filled with gradient colouring.
+ ``FNB_TABS_BORDER_SIMPLE`` 0x4 Draw thin border around the page.
+ ``FNB_NO_X_BUTTON`` 0x8 Do not display the 'X' button.
+ ``FNB_NO_NAV_BUTTONS`` 0x10 Do not display the right/left arrows.
+ ``FNB_MOUSE_MIDDLE_CLOSES_TABS`` 0x20 Use the mouse middle button for cloing tabs.
+ ``FNB_BOTTOM`` 0x40 Place tabs at bottom - the default is to place them at top.
+ ``FNB_NODRAG`` 0x80 Disable dragging of tabs.
+ ``FNB_VC8`` 0x100 Use Visual Studio 2005 (VC8) style for tabs.
+ ``FNB_X_ON_TAB`` 0x200 Place 'X' close button on the active tab.
+ ``FNB_BACKGROUND_GRADIENT`` 0x400 Use gradients to paint the tabs background.
+ ``FNB_COLOURFUL_TABS`` 0x800 Use colourful tabs (VC8 style only).
+ ``FNB_DCLICK_CLOSES_TABS`` 0x1000 Style to close tab using double click.
+ ``FNB_SMART_TABS`` 0x2000 Use `Smart Tabbing`, like ``Alt`` + ``Tab`` on Windows.
+ ``FNB_DROPDOWN_TABS_LIST`` 0x4000 Use a dropdown menu on the left in place of the arrows.
+ ``FNB_ALLOW_FOREIGN_DND`` 0x8000 Allows drag 'n' drop operations between different :class:`FlatNotebook`.
+ ``FNB_HIDE_ON_SINGLE_TAB`` 0x10000 Hides the Page Container when there is one or fewer tabs.
+ ``FNB_DEFAULT_STYLE`` 0x10020 :class:`FlatNotebook` default style.
+ ``FNB_FF2`` 0x20000 Use Firefox 2 style for tabs.
+ ``FNB_NO_TAB_FOCUS`` 0x40000 Does not allow tabs to have focus.
+ ``FNB_RIBBON_TABS`` 0x80000 Use the Ribbon Tabs style.
+ ``FNB_HIDE_TABS`` 0x100000 Hides the Page Container allowing only keyboard navigation
+ ``FNB_NAV_BUTTONS_WHEN_NEEDED`` 0x200000 Hides the navigation left/right arrows if all tabs fit
+ ================================ =========== ==================================================
+
+ :param `name`: the window name.
+ """
+
+ self._bForceSelection = False
+ self._nPadding = 6
+ self._nFrom = 0
+ style |= wx.TAB_TRAVERSAL
+ self._pages = None
+ self._windows = []
+ self._popupWin = None
+ self._naviIcon = None
+ self._agwStyle = agwStyle
+ self._orientation = None
+ self._customPanel = None
+
+ wx.PyPanel.__init__(self, parent, id, pos, size, style)
+ attr = self.GetDefaultAttributes()
+ self.SetOwnForegroundColour(attr.colFg)
+ self.SetOwnBackgroundColour(attr.colBg)
+
+ self._pages = PageContainer(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, style)
+
+ self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
+
+ self.Init()
+
+
+ def Init(self):
+ """ Initializes all the class attributes. """
+
+ self._pages._colourBorder = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+
+ self._mainSizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self._mainSizer)
+
+ # The child panels will inherit this bg colour, so leave it at the default value
+ #self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_APPWORKSPACE))
+
+ # Set default page height
+ dc = wx.ClientDC(self)
+
+ if "__WXGTK__" in wx.PlatformInfo:
+ # For GTK it seems that we must do this steps in order
+ # for the tabs will get the proper height on initialization
+ # on MSW, preforming these steps yields wierd results
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+ dc.SetFont(boldFont)
+
+ height = dc.GetCharHeight()
+
+ tabHeight = height + FNB_HEIGHT_SPACER # We use 8 pixels as padding
+
+ if "__WXGTK__" in wx.PlatformInfo:
+ tabHeight += 6
+
+ self._pages.SetSizeHints(-1, tabHeight)
+ # Add the tab container to the sizer
+ self._mainSizer.Insert(0, self._pages, 0, wx.EXPAND)
+ self._mainSizer.Layout()
+
+ self._pages._nFrom = self._nFrom
+ self._pDropTarget = FNBDropTarget(self)
+ self.SetDropTarget(self._pDropTarget)
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same
+ size as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ if not self._windows:
+ # Something is better than nothing... no pages!
+ return wx.Size(20, 20)
+
+ maxWidth = maxHeight = 0
+ tabHeight = self.GetPageBestSize().height
+
+ for win in self._windows:
+ # Loop over all the windows to get their best size
+ width, height = win.GetBestSize()
+ maxWidth, maxHeight = max(maxWidth, width), max(maxHeight, height)
+
+ return wx.Size(maxWidth, maxHeight+tabHeight)
+
+
+ def Tile(self, orient=None):
+ """
+ Shows pages in column/row mode (one panel after the other in columns/rows).
+
+ :param `orient`: this parameter represents the orientation of the stacked
+ panels. Pass ``wx.VERTICAL`` to get vertically stacked panels, ``wx.HORIZONTAL``
+ to get horizontally stacked panels or ``None`` to return to the default
+ :class:`FlatNotebook` behaviour with tabs.
+ """
+
+ if orient == self._orientation:
+ return
+
+ self.Freeze()
+ self._orientation = orient
+
+ self._mainSizer.Detach(self._pages)
+ for win in self._windows:
+ self._mainSizer.Detach(win)
+
+## self._mainSizer.Destroy()
+
+ if orient is not None:
+ self._mainSizer = wx.BoxSizer(orient)
+ self._mainSizer.Add(self._pages)
+
+ for win in self._windows:
+ self._mainSizer.Add(win, 1, wx.EXPAND | wx.ALL, 2)
+ win.Show()
+
+ else:
+
+ self._mainSizer = wx.BoxSizer(wx.VERTICAL)
+ # Add the tab container to the sizer
+ self._mainSizer.Insert(0, self._pages, 0, wx.EXPAND)
+
+ curr = self._pages.GetSelection()
+ for indx, win in enumerate(self._windows):
+ if indx == curr:
+ if self.GetAGWWindowStyleFlag() & FNB_BOTTOM:
+ self._mainSizer.Insert(0, win, 1, wx.EXPAND)
+ else:
+ # We leave a space of 1 pixel around the window
+ self._mainSizer.Add(win, 1, wx.EXPAND)
+ win.Show()
+
+ else:
+ win.Hide()
+
+ self.SetSizer(self._mainSizer)
+
+ self._mainSizer.Layout()
+ self.Layout()
+
+ if orient is None:
+ self.SetSelection(self._pages._iActivePage)
+ self._pages._ReShow()
+
+ self.Thaw()
+
+
+ def GetTileOrientation(self):
+ """
+ Returns the orientation when on tiling mode. This method can return
+ ``wx.VERTICAL`` when the panels are vertically stacked, ``wx.HORIZONTAL``
+ when they are horizontally stacked panels or ``None`` when there is no
+ stacking and :class:`FlatNotebook` behaves like a normal notebook.
+ """
+
+ return self._orientation
+
+
+ def SetCustomPage(self, panel):
+ """
+ Sets a custom panel to show when there are no pages left in :class:`FlatNotebook`.
+
+ :param `panel`: any subclass of :class:`Window` will do, as long as it is suitable
+ to be used as a notebook page. Examples include :class:`Panel`, :class:`ScrolledWindow`,
+ and so on.
+ """
+
+ self.Freeze()
+
+ if panel is None:
+ if self._customPanel is not None:
+ self._mainSizer.Detach(self._customPanel)
+ self._customPanel.Show(False)
+
+ else:
+ if self._customPanel is not None:
+ self._mainSizer.Detach(self._customPanel)
+ self._customPanel.Show(False)
+ self._customPanel.Destroy()
+
+ self._customPanel = panel
+ self.ShowCustomPage(True)
+
+ self._pages._ReShow()
+ self._mainSizer.Layout()
+ self.Thaw()
+
+
+ def GetCustomPage(self):
+ """ Returns a custom panel to show when there are no pages left in :class:`FlatNotebook`. """
+
+ return self._customPanel
+
+
+ def ShowCustomPage(self, show=True):
+ """ Hides the custom panel which is shown when there are no pages left in :class:`FlatNotebook`. """
+
+ if self._customPanel is None:
+ return
+
+ self.Freeze()
+ self._customPanel.Show(False)
+
+ if show:
+ if self.GetPageCount() == 0:
+ self._mainSizer.Add(self._customPanel, 1, wx.EXPAND | wx.ALL, 2)
+ self._customPanel.Show(True)
+ else:
+ if self._customPanel.GetContainingSizer() is not None:
+ self._mainSizer.Detach(self._customPanel)
+
+ self._mainSizer.Layout()
+ self.Thaw()
+
+
+ def SetActiveTabTextColour(self, textColour):
+ """
+ Sets the text colour for the active tab.
+
+ :param `textColour`: a valid :class:`Colour` object or any typemap supported by wxWidgets/wxPython
+ to generate a colour (i.e., a hex string, a colour name, a 3 or 4 integer tuple).
+ """
+
+ self._pages._activeTextColour = FormatColour(textColour)
+
+
+ def OnDropTarget(self, x, y, nTabPage, wnd_oldContainer):
+ """
+ Handles the drop action from a drag and drop operation.
+
+ :param `x`: the x position of the drop action;
+ :param `y`: the y position of the drop action;
+ :param `nTabPage`: the index of the tab being dropped;
+ :param `wnd_oldContainer`: the :class:`FlatNotebook` to which the dropped tab previously
+ belonged to.
+ """
+
+ return self._pages.OnDropTarget(x, y, nTabPage, wnd_oldContainer)
+
+
+ def GetPreviousSelection(self):
+ """ Returns the previous selection. """
+
+ return self._pages._iPreviousActivePage
+
+
+ def AddPage(self, page, text, select=False, imageId=-1):
+ """
+ Adds a page to the :class:`FlatNotebook`.
+
+ :param `page`: specifies the new page;
+ :param `text`: specifies the text for the new page;
+ :param `select`: specifies whether the page should be selected;
+ :param `imageId`: specifies the optional image index for the new page.
+
+ :return: ``True`` if successful, ``False`` otherwise.
+ """
+
+ # sanity check
+ if not page:
+ return False
+
+ min_size = page.GetMinSize()
+ if not min_size.IsFullySpecified():
+ page.SetMinSize((1, 1))
+
+ self.ShowCustomPage(False)
+
+ # reparent the window to us
+ page.Reparent(self)
+
+ # Add tab
+ bSelected = select or len(self._windows) == 0
+
+ if bSelected:
+
+ bSelected = False
+
+ # Check for selection and send events
+ oldSelection = self._pages._iActivePage
+ tabIdx = len(self._windows)
+
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetId())
+ event.SetSelection(tabIdx)
+ event.SetOldSelection(oldSelection)
+ event.SetEventObject(self)
+
+ if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0:
+ bSelected = True
+
+ curSel = self._pages.GetSelection()
+
+ if not self._pages.IsShown():
+ self._pages.Show()
+
+ self._pages.AddPage(text, bSelected, imageId)
+ self._windows.append(page)
+
+ self.Freeze()
+
+ # Check if a new selection was made
+ if bSelected:
+
+ if curSel >= 0:
+
+ # Remove the window from the main sizer
+ self._mainSizer.Detach(self._windows[curSel])
+ self._windows[curSel].Hide()
+
+ if self.GetAGWWindowStyleFlag() & FNB_BOTTOM:
+
+ self._mainSizer.Insert(0, page, 1, wx.EXPAND)
+
+ else:
+
+ # We leave a space of 1 pixel around the window
+ self._mainSizer.Add(page, 1, wx.EXPAND)
+
+ # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
+ event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
+ event.SetOldSelection(oldSelection)
+ self.GetEventHandler().ProcessEvent(event)
+
+ else:
+
+ # Hide the page
+ page.Hide()
+
+ self.Tile(self._orientation)
+ self.Thaw()
+ self._mainSizer.Layout()
+ self.Refresh()
+
+ return True
+
+
+ def SetImageList(self, imageList):
+ """
+ Sets the image list for the page control.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ self._pages.SetImageList(imageList)
+
+
+ def AssignImageList(self, imageList):
+ """
+ Assigns the image list for the page control.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ self._pages.AssignImageList(imageList)
+
+
+ def GetImageList(self):
+ """ Returns the associated image list. """
+
+ return self._pages.GetImageList()
+
+
+ def InsertPage(self, indx, page, text, select=True, imageId=-1):
+ """
+ Inserts a new page at the specified position.
+
+ :param `indx`: specifies the position of the new page;
+ :param `page`: specifies the new page;
+ :param `text`: specifies the text for the new page;
+ :param `select`: specifies whether the page should be selected;
+ :param `imageId`: specifies the optional image index for the new page.
+
+ :return: ``True`` if successful, ``False`` otherwise.
+ """
+
+ # sanity check
+ if not page:
+ return False
+
+ self.ShowCustomPage(False)
+
+ # reparent the window to us
+ page.Reparent(self)
+
+ if not self._windows:
+
+ self.AddPage(page, text, select, imageId)
+ return True
+
+ # Insert tab
+ bSelected = select or not self._windows
+ curSel = self._pages.GetSelection()
+
+ indx = max(0, min(indx, len(self._windows)))
+
+ if indx <= len(self._windows):
+
+ self._windows.insert(indx, page)
+
+ else:
+
+ self._windows.append(page)
+
+ if bSelected:
+
+ bSelected = False
+
+ # Check for selection and send events
+ oldSelection = self._pages._iActivePage
+
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetId())
+ event.SetSelection(indx)
+ event.SetOldSelection(oldSelection)
+ event.SetEventObject(self)
+
+ if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0:
+ bSelected = True
+
+ self._pages.InsertPage(indx, text, bSelected, imageId)
+
+ if indx <= curSel:
+ curSel = curSel + 1
+
+ self.Freeze()
+
+ # Check if a new selection was made
+ if bSelected:
+
+ if curSel >= 0:
+
+ # Remove the window from the main sizer
+ self._mainSizer.Detach(self._windows[curSel])
+ self._windows[curSel].Hide()
+
+ self._pages.SetSelection(indx)
+
+ # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
+ event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
+ event.SetOldSelection(oldSelection)
+ self.GetEventHandler().ProcessEvent(event)
+
+ else:
+
+ # Hide the page
+ page.Hide()
+
+ self.Tile(self._orientation)
+ self.Thaw()
+ self._mainSizer.Layout()
+ self.Refresh()
+
+ return True
+
+
+ def SetSelection(self, page):
+ """
+ Sets the selection for the given page.
+
+ :param `page`: an integer specifying the new selected page.
+
+ :note: The call to this function **does not** generate the page changing events.
+ """
+
+ if page >= len(self._windows) or not self._windows:
+ return
+
+ # Support for disabed tabs
+ if not self._pages.GetEnabled(page) and len(self._windows) > 1 and not self._bForceSelection:
+ return
+
+ if self._orientation is not None:
+ return
+
+ curSel = self._pages.GetSelection()
+
+ # program allows the page change
+ self.Freeze()
+ if curSel >= 0:
+
+ # Remove the window from the main sizer
+ self._mainSizer.Detach(self._windows[curSel])
+ self._windows[curSel].Hide()
+
+ if self.GetAGWWindowStyleFlag() & FNB_BOTTOM:
+
+ self._mainSizer.Insert(0, self._windows[page], 1, wx.EXPAND)
+
+ else:
+
+ # We leave a space of 1 pixel around the window
+ self._mainSizer.Add(self._windows[page], 1, wx.EXPAND)
+
+ self._windows[page].Show()
+ self.Thaw()
+
+ self._mainSizer.Layout()
+
+ if page != self._pages._iActivePage:
+ # there is a real page changing
+ self._pages._iPreviousActivePage = self._pages._iActivePage
+
+ self._pages._iActivePage = page
+ self._pages.DoSetSelection(page)
+
+
+ def DeletePage(self, page):
+ """
+ Deletes the specified page, and the associated window.
+
+ :param `page`: an integer specifying the new selected page.
+
+ :note: The call to this function generates the page changing events.
+ """
+
+ if page >= len(self._windows) or page < 0:
+ return
+
+ # Fire a closing event
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, self.GetId())
+ event.SetSelection(page)
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ # The event handler allows it?
+ if not event.IsAllowed():
+ return
+
+ self.Freeze()
+
+ # Delete the requested page
+ pageRemoved = self._windows[page]
+
+ # If the page is the current window, remove it from the sizer
+ # as well
+ if page == self._pages.GetSelection():
+ self._mainSizer.Detach(pageRemoved)
+
+ # Remove it from the array as well
+ self._windows.pop(page)
+
+ # Now we can destroy it in wxWidgets use Destroy instead of delete
+ pageRemoved.Destroy()
+
+ self.Thaw()
+
+ self._pages.DoDeletePage(page)
+
+ self.Tile(self._orientation)
+ self.ShowCustomPage(True)
+
+ self.Refresh()
+ self.Update()
+
+ # Fire a closed event
+ closedEvent = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, self.GetId())
+ closedEvent.SetSelection(page)
+ closedEvent.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(closedEvent)
+
+
+ def DeleteAllPages(self):
+ """ Deletes all the pages in the :class:`FlatNotebook`. """
+
+ if not self._windows:
+ return False
+
+ self.Freeze()
+
+ for page in self._windows:
+ page.Destroy()
+
+ self._windows = []
+ self.Thaw()
+
+ # Clear the container of the tabs as well
+ self._pages.DeleteAllPages()
+ self.ShowCustomPage(True)
+
+ return True
+
+
+ def GetCurrentPage(self):
+ """ Returns the currently selected notebook page or ``None`` if none is selected. """
+
+ sel = self._pages.GetSelection()
+ if sel < 0 or sel >= len(self._windows):
+ return None
+
+ return self._windows[sel]
+
+
+ def GetPage(self, page):
+ """ Returns the window at the given page position, or ``None``. """
+
+ if page >= len(self._windows):
+ return None
+
+ return self._windows[page]
+
+
+ def GetPageIndex(self, win):
+ """
+ Returns the index at which the window is found.
+
+ :param `win`: an instance of :class:`Window`.
+ """
+
+ try:
+ return self._windows.index(win)
+ except:
+ return -1
+
+
+ def GetSelection(self):
+ """ Returns the currently selected page, or -1 if none was selected. """
+
+ return self._pages.GetSelection()
+
+
+ def AdvanceSelection(self, forward=True):
+ """
+ Cycles through the tabs.
+
+ :param `forward`: if ``True``, the selection is advanced in ascending order
+ (to the right), otherwise the selection is advanced in descending order.
+
+ :note: The call to this function generates the page changing events.
+ """
+
+ self._pages.AdvanceSelection(forward)
+
+
+ def GetPageCount(self):
+ """ Returns the number of pages in the :class:`FlatNotebook` control. """
+
+ return self._pages.GetPageCount()
+
+
+ def SetNavigatorIcon(self, bmp):
+ """
+ Set the icon used by the :class:`TabNavigatorWindow`.
+
+ :param `bmp`: a valid :class:`Bitmap` object.
+ """
+
+ if isinstance(bmp, wx.Bitmap) and bmp.IsOk():
+ # Make sure image is proper size
+ if bmp.GetSize() != (16, 16):
+ img = bmp.ConvertToImage()
+ img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH)
+ bmp = wx.BitmapFromImage(img)
+ self._naviIcon = bmp
+ else:
+ raise TypeError("SetNavigatorIcon requires a valid bitmap")
+
+
+ def OnNavigationKey(self, event):
+ """
+ Handles the ``wx.EVT_NAVIGATION_KEY`` event for :class:`FlatNotebook`.
+
+ :param `event`: a :class:`NavigationKeyEvent` event to be processed.
+ """
+
+ if event.IsWindowChange():
+ if len(self._windows) == 0:
+ return
+ # change pages
+ if self.HasAGWFlag(FNB_SMART_TABS):
+ if not self._popupWin:
+ self._popupWin = TabNavigatorWindow(self, self._naviIcon)
+ self._popupWin.SetReturnCode(wx.ID_OK)
+ self._popupWin.ShowModal()
+ self._popupWin.Destroy()
+ self._popupWin = None
+ else:
+ # a dialog is already opened
+ self._popupWin.OnNavigationKey(event)
+ return
+ else:
+ # change pages
+ self.AdvanceSelection(event.GetDirection())
+
+ else:
+ event.Skip()
+
+
+ def GetPageShapeAngle(self, page_index):
+ """
+ Returns the angle associated to a tab.
+
+ :param `page_index`: the index of the tab for which we wish to get the shape angle.
+ """
+
+ if page_index < 0 or page_index >= len(self._pages._pagesInfoVec):
+ return None, False
+
+ result = self._pages._pagesInfoVec[page_index].GetTabAngle()
+ return result, True
+
+
+ def SetPageShapeAngle(self, page_index, angle):
+ """
+ Sets the angle associated to a tab.
+
+ :param `page_index`: the index of the tab for which we wish to get the shape angle;
+ :param `angle`: the new shape angle for the tab (must be less than 15 degrees).
+ """
+
+ if page_index < 0 or page_index >= len(self._pages._pagesInfoVec):
+ return
+
+ if angle > 15:
+ return
+
+ self._pages._pagesInfoVec[page_index].SetTabAngle(angle)
+
+
+ def SetAllPagesShapeAngle(self, angle):
+ """
+ Sets the angle associated to all the tab.
+
+ :param `angle`: the new shape angle for the tab (must be less than 15 degrees).
+ """
+
+ if angle > 15:
+ return
+
+ for ii in xrange(len(self._pages._pagesInfoVec)):
+ self._pages._pagesInfoVec[ii].SetTabAngle(angle)
+
+ self.Refresh()
+
+
+ def GetPageBestSize(self):
+ """ Return the page best size. """
+
+ return self._pages.GetClientSize()
+
+
+ def SetPageText(self, page, text):
+ """
+ Sets the text for the given page.
+
+ :param `page`: an integer specifying the page index;
+ :param `text`: the new tab label.
+ """
+
+ bVal = self._pages.SetPageText(page, text)
+ self._pages.Refresh()
+
+ return bVal
+
+
+ def SetPadding(self, padding):
+ """
+ Sets the amount of space around each page's icon and label, in pixels.
+
+ :param `padding`: the amount of space around each page's icon and label,
+ in pixels.
+
+ :note: Only the horizontal padding is considered.
+ """
+
+ self._nPadding = padding.GetWidth()
+
+
+ def GetTabArea(self):
+ """ Returns the associated page. """
+
+ return self._pages
+
+
+ def GetPadding(self):
+ """ Returns the amount of space around each page's icon and label, in pixels. """
+
+ return self._nPadding
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the :class:`FlatNotebook` window style flags.
+
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ ================================ =========== ==================================================
+ Window Styles Hex Value Description
+ ================================ =========== ==================================================
+ ``FNB_VC71`` 0x1 Use Visual Studio 2003 (VC7.1) style for tabs.
+ ``FNB_FANCY_TABS`` 0x2 Use fancy style - square tabs filled with gradient colouring.
+ ``FNB_TABS_BORDER_SIMPLE`` 0x4 Draw thin border around the page.
+ ``FNB_NO_X_BUTTON`` 0x8 Do not display the 'X' button.
+ ``FNB_NO_NAV_BUTTONS`` 0x10 Do not display the right/left arrows.
+ ``FNB_MOUSE_MIDDLE_CLOSES_TABS`` 0x20 Use the mouse middle button for cloing tabs.
+ ``FNB_BOTTOM`` 0x40 Place tabs at bottom - the default is to place them at top.
+ ``FNB_NODRAG`` 0x80 Disable dragging of tabs.
+ ``FNB_VC8`` 0x100 Use Visual Studio 2005 (VC8) style for tabs.
+ ``FNB_X_ON_TAB`` 0x200 Place 'X' close button on the active tab.
+ ``FNB_BACKGROUND_GRADIENT`` 0x400 Use gradients to paint the tabs background.
+ ``FNB_COLOURFUL_TABS`` 0x800 Use colourful tabs (VC8 style only).
+ ``FNB_DCLICK_CLOSES_TABS`` 0x1000 Style to close tab using double click.
+ ``FNB_SMART_TABS`` 0x2000 Use `Smart Tabbing`, like ``Alt`` + ``Tab`` on Windows.
+ ``FNB_DROPDOWN_TABS_LIST`` 0x4000 Use a dropdown menu on the left in place of the arrows.
+ ``FNB_ALLOW_FOREIGN_DND`` 0x8000 Allows drag 'n' drop operations between different :class:`FlatNotebook`.
+ ``FNB_HIDE_ON_SINGLE_TAB`` 0x10000 Hides the Page Container when there is one or fewer tabs.
+ ``FNB_DEFAULT_STYLE`` 0x10020 :class:`FlatNotebook` default style.
+ ``FNB_FF2`` 0x20000 Use Firefox 2 style for tabs.
+ ``FNB_NO_TAB_FOCUS`` 0x40000 Does not allow tabs to have focus.
+ ``FNB_RIBBON_TABS`` 0x80000 Use the Ribbon Tabs style.
+ ``FNB_HIDE_TABS`` 0x100000 Hides the Page Container allowing only keyboard navigation
+ ``FNB_NAV_BUTTONS_WHEN_NEEDED`` 0x200000 Hides the navigation left/right arrows if all tabs fit
+ ================================ =========== ==================================================
+
+ """
+
+ oldStyle = self._agwStyle
+ self._agwStyle = agwStyle
+ renderer = self._pages._mgr.GetRenderer(agwStyle)
+ renderer._tabHeight = None
+
+ if self._pages:
+ # For changing the tab position (i.e. placing them top/bottom)
+ # refreshing the tab container is not enough
+ self.SetSelection(self._pages._iActivePage)
+
+ # If we just hid the tabs we must Refresh()
+ if (not (oldStyle & FNB_HIDE_TABS) and agwStyle & FNB_HIDE_TABS) or \
+ (not (oldStyle & FNB_HIDE_ON_SINGLE_TAB) and agwStyle & FNB_HIDE_ON_SINGLE_TAB):
+ self.Refresh()
+
+ if (oldStyle & FNB_HIDE_TABS and not (agwStyle & FNB_HIDE_TABS)) or \
+ (oldStyle & FNB_HIDE_ON_SINGLE_TAB and not self.HasAGWFlag(FNB_HIDE_ON_SINGLE_TAB)):
+ #For Redrawing the Tabs once you remove the Hide tyle
+ self._pages._ReShow()
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`FlatNotebook` window style.
+
+ :see: :meth:`~FlatNotebook.SetAGWWindowStyleFlag` for a list of valid window styles.
+ """
+
+ return self._agwStyle
+
+
+ def HasAGWFlag(self, flag):
+ """
+ Returns whether a flag is present in the :class:`FlatNotebook` style.
+
+ :param `flag`: one of the possible :class:`FlatNotebook` window styles.
+
+ :see: :meth:`~FlatNotebook.SetAGWWindowStyleFlag` for a list of possible window style flags.
+ """
+
+ agwStyle = self.GetAGWWindowStyleFlag()
+ res = (agwStyle & flag and [True] or [False])[0]
+ return res
+
+
+ def HideTabs(self):
+ """ Hides the tabs. """
+
+ agwStyle = self.GetAGWWindowStyleFlag()
+ agwStyle |= FNB_HIDE_TABS
+ self.SetAGWWindowStyleFlag(agwStyle)
+
+
+ def ShowTabs(self):
+ """ Shows the tabs if hidden previously. """
+
+ agwStyle = self.GetAGWWindowStyleFlag()
+ agwStyle &= ~FNB_HIDE_TABS
+ self.SetAGWWindowStyleFlag(agwStyle)
+
+
+ def RemovePage(self, page):
+ """
+ Deletes the specified page, without deleting the associated window.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ if page >= len(self._windows):
+ return False
+
+ # Fire a closing event
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, self.GetId())
+ event.SetSelection(page)
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ # The event handler allows it?
+ if not event.IsAllowed():
+ return False
+
+ self.Freeze()
+
+ # Remove the requested page
+ pageRemoved = self._windows[page]
+
+ # If the page is the current window, remove it from the sizer
+ # as well
+ if page == self._pages.GetSelection():
+ self._mainSizer.Detach(pageRemoved)
+
+ # Remove it from the array as well
+ self._windows.pop(page)
+
+ self.Tile(self._orientation)
+ self.ShowCustomPage(True)
+
+ self.Thaw()
+
+ self._pages.DoDeletePage(page)
+
+ return True
+
+
+ def SetRightClickMenu(self, menu):
+ """
+ Sets the popup menu associated to a right click on a tab.
+
+ :param `menu`: an instance of :class:`Menu`.
+ """
+
+ self._pages._pRightClickMenu = menu
+
+
+ def GetPageText(self, page):
+ """
+ Returns the string for the given page.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ return self._pages.GetPageText(page)
+
+
+ def SetGradientColours(self, fr, to, border):
+ """
+ Sets the gradient colours for the tab.
+
+ :param `fr`: the first gradient colour, an instance of :class:`Colour`;
+ :param `to`: the second gradient colour, an instance of :class:`Colour`;
+ :param `border`: the border colour, an instance of :class:`Colour`.
+ """
+
+ self._pages._colourFrom = fr
+ self._pages._colourTo = to
+ self._pages._colourBorder = border
+
+
+ def SetGradientColourFrom(self, fr):
+ """
+ Sets the starting colour for the gradient.
+
+ :param `fr`: the first gradient colour, an instance of :class:`Colour`.
+ """
+
+ self._pages._colourFrom = fr
+
+
+ def SetGradientColourTo(self, to):
+ """
+ Sets the ending colour for the gradient.
+
+ :param `to`: the second gradient colour, an instance of :class:`Colour`;
+ """
+
+ self._pages._colourTo = to
+
+
+ def SetGradientColourBorder(self, border):
+ """
+ Sets the tab border colour.
+
+ :param `border`: the border colour, an instance of :class:`Colour`.
+ """
+
+ self._pages._colourBorder = border
+
+
+ def GetGradientColourFrom(self):
+ """ Gets first gradient colour. """
+
+ return self._pages._colourFrom
+
+
+ def GetGradientColourTo(self):
+ """ Gets second gradient colour. """
+
+ return self._pages._colourTo
+
+
+ def GetGradientColourBorder(self):
+ """ Gets the tab border colour. """
+
+ return self._pages._colourBorder
+
+
+ def GetBorderColour(self):
+ """ Returns the border colour. """
+
+ return self._pages._colourBorder
+
+
+ def GetActiveTabTextColour(self):
+ """ Get the active tab text colour. """
+
+ return self._pages._activeTextColour
+
+
+ def SetPageImage(self, page, image):
+ """
+ Sets the image index for the given page.
+
+ :param `page`: an integer specifying the page index;
+ :param `image`: an index into the image list which was set with :meth:`~FlatNotebook.SetImageList`.
+ """
+
+ self._pages.SetPageImage(page, image)
+
+
+ def GetPageImage(self, page):
+ """
+ Returns the image index for the given page.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ return self._pages.GetPageImage(page)
+
+
+ def GetEnabled(self, page):
+ """
+ Returns whether a tab is enabled or not.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ return self._pages.GetEnabled(page)
+
+
+ def EnableTab(self, page, enabled=True):
+ """
+ Enables or disables a tab.
+
+ :param `page`: an integer specifying the page index;
+ :param `enabled`: ``True`` to enable a tab, ``False`` to disable it.
+ """
+
+ if page >= len(self._windows):
+ return
+
+ self._windows[page].Enable(enabled)
+ self._pages.EnableTab(page, enabled)
+
+
+ def GetNonActiveTabTextColour(self):
+ """ Returns the non active tabs text colour. """
+
+ return self._pages._nonActiveTextColour
+
+
+ def SetNonActiveTabTextColour(self, colour):
+ """
+ Sets the non active tabs text colour.
+
+ :param `colour`: a valid :class:`Colour` object or any typemap supported by wxWidgets/wxPython
+ to generate a colour (i.e., a hex string, a colour name, a 3 or 4 integer tuple).
+ """
+
+ self._pages._nonActiveTextColour = FormatColour(colour)
+
+
+ def GetPageTextColour(self, page):
+ """
+ Returns the tab text colour if it has been set previously, or ``None`` otherwise.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ return self._pages.GetPageTextColour(page)
+
+
+ def SetPageTextColour(self, page, colour):
+ """
+ Sets the tab text colour individually.
+
+ :param `page`: an integer specifying the page index;
+ :param `colour`: a valid :class:`Colour` object or any typemap supported by wxWidgets/wxPython
+ to generate a colour (i.e., a hex string, a colour name, a 3 or 4 integer tuple). You can
+ pass ``None`` or :class:`NullColour` to return to the default page text colour.
+ """
+
+ self._pages.SetPageTextColour(page, colour)
+
+
+ def SetTabAreaColour(self, colour):
+ """
+ Sets the area behind the tabs colour.
+
+ :param `colour`: a valid :class:`Colour` object or any typemap supported by wxWidgets/wxPython
+ to generate a colour (i.e., a hex string, a colour name, a 3 or 4 integer tuple).
+ """
+
+ self._pages._tabAreaColour = FormatColour(colour)
+
+
+ def GetTabAreaColour(self):
+ """ Returns the area behind the tabs colour. """
+
+ return self._pages._tabAreaColour
+
+
+ def SetActiveTabColour(self, colour):
+ """
+ Sets the active tab colour.
+
+ :param `colour`: a valid :class:`Colour` object or any typemap supported by wxWidgets/wxPython
+ to generate a colour (i.e., a hex string, a colour name, a 3 or 4 integer tuple).
+ """
+
+ self._pages._activeTabColour = FormatColour(colour)
+
+
+ def GetActiveTabColour(self):
+ """ Returns the active tab colour. """
+
+ return self._pages._activeTabColour
+
+
+ def EnsureVisible(self, page):
+ """
+ Ensures that a tab is visible.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ self._pages.DoSetSelection(page)
+
+
+# ---------------------------------------------------------------------------- #
+# Class PageContainer
+# Acts as a container for the pages you add to FlatNotebook
+# ---------------------------------------------------------------------------- #
+
+class PageContainer(wx.PyPanel):
+ """
+ This class acts as a container for the pages you add to :class:`FlatNotebook`.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0):
+ """
+ Default class constructor.
+
+ Used internally, do not call it in your code!
+
+ :param `parent`: the :class:`PageContainer` parent;
+ :param `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style.
+ """
+
+ self._ImageList = None
+ self._iActivePage = -1
+ self._pDropTarget = None
+ self._nLeftClickZone = FNB_NOWHERE
+ self._iPreviousActivePage = -1
+
+ self._pRightClickMenu = None
+ self._nXButtonStatus = FNB_BTN_NONE
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+ self._pParent = parent
+ self._nRightButtonStatus = FNB_BTN_NONE
+ self._nLeftButtonStatus = FNB_BTN_NONE
+ self._nTabXButtonStatus = FNB_BTN_NONE
+
+ self._nHoveringOverTabIndex = -1
+ self._nHoveringOverLastTabIndex = -1
+
+ self._setCursor = False
+
+ self._pagesInfoVec = []
+
+ self._colourTo = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self._colourFrom = wx.WHITE
+ self._activeTabColour = wx.WHITE
+ self._activeTextColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT)
+ self._nonActiveTextColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT)
+ self._tabAreaColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
+
+ self._nFrom = 0
+ self._isdragging = False
+
+ # Set default page height, this is done according to the system font
+ memDc = wx.MemoryDC()
+ memDc.SelectObject(wx.EmptyBitmap(1,1))
+
+ if "__WXGTK__" in wx.PlatformInfo:
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont.SetWeight(wx.BOLD)
+ memDc.SetFont(boldFont)
+
+ height = memDc.GetCharHeight()
+ tabHeight = height + FNB_HEIGHT_SPACER # We use 10 pixels as padding
+
+ wx.PyPanel.__init__(self, parent, id, pos, wx.Size(size.x, tabHeight),
+ style|wx.NO_BORDER|wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS)
+
+ attr = self.GetDefaultAttributes()
+ self.SetOwnForegroundColour(attr.colFg)
+ self.SetOwnBackgroundColour(attr.colBg)
+
+ self._pDropTarget = FNBDropTarget(self)
+ self.SetDropTarget(self._pDropTarget)
+ self._mgr = FNBRendererMgr()
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
+ self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def _ReShow(self):
+ """
+ Handles the redraw of the tabs when the ``FNB_HIDE_ON_SINGLE_TAB`` has been removed.
+ """
+
+ self.Show()
+ self.GetParent()._mainSizer.Layout()
+ self.Refresh()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+ parent = self.GetParent()
+
+ renderer = self._mgr.GetRenderer(parent.GetAGWWindowStyleFlag())
+ renderer.DrawTabs(self, dc)
+
+ if self.HasAGWFlag(FNB_HIDE_ON_SINGLE_TAB) and len(self._pagesInfoVec) <= 1 or \
+ self.HasAGWFlag(FNB_HIDE_TABS) or parent._orientation or \
+ (parent._customPanel and len(self._pagesInfoVec) == 0):
+ self.Hide()
+ self.GetParent()._mainSizer.Layout()
+ self.Refresh()
+
+
+ def AddPage(self, caption, selected=False, imgindex=-1):
+ """
+ Adds a page to the :class:`PageContainer`.
+
+ :param `page`: specifies the new page;
+ :param `text`: specifies the text for the new page;
+ :param `select`: specifies whether the page should be selected;
+ :param `imageId`: specifies the optional image index for the new page.
+ """
+
+ if selected:
+
+ self._iPreviousActivePage = self._iActivePage
+ self._iActivePage = len(self._pagesInfoVec)
+
+ # Create page info and add it to the vector
+ pageInfo = PageInfo(caption, imgindex)
+ self._pagesInfoVec.append(pageInfo)
+ self.Refresh()
+
+
+ def InsertPage(self, indx, text, selected=True, imgindex=-1):
+ """
+ Inserts a new page at the specified position.
+
+ :param `indx`: specifies the position of the new page;
+ :param `page`: specifies the new page;
+ :param `text`: specifies the text for the new page;
+ :param `select`: specifies whether the page should be selected;
+ :param `imageId`: specifies the optional image index for the new page.
+ """
+
+ if selected:
+
+ self._iPreviousActivePage = self._iActivePage
+ self._iActivePage = len(self._pagesInfoVec)
+
+ self._pagesInfoVec.insert(indx, PageInfo(text, imgindex))
+
+ self.Refresh()
+ return True
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ # When resizing the control, try to fit to screen as many tabs as we can
+ agwStyle = self.GetParent().GetAGWWindowStyleFlag()
+ renderer = self._mgr.GetRenderer(agwStyle)
+
+ fr = 0
+ page = self.GetSelection()
+
+ for fr in xrange(self._nFrom):
+ vTabInfo = renderer.NumberTabsCanFit(self, fr)
+ if page - fr >= len(vTabInfo):
+ continue
+ break
+
+ self._nFrom = fr
+
+ self.Refresh() # Call on paint
+ event.Skip()
+
+
+ def OnMiddleDown(self, event):
+ """
+ Handles the ``wx.EVT_MIDDLE_DOWN`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # Test if this style is enabled
+ agwStyle = self.GetParent().GetAGWWindowStyleFlag()
+
+ if not agwStyle & FNB_MOUSE_MIDDLE_CLOSES_TABS:
+ return
+
+ where, tabIdx = self.HitTest(event.GetPosition())
+
+ if where == FNB_TAB:
+ self.DeletePage(tabIdx)
+
+ event.Skip()
+
+
+ def OnMouseWheel(self, event):
+ """
+ Handles the ``wx.EVT_MOUSEWHEEL`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ rotation = event.GetWheelRotation()
+ delta = event.GetWheelDelta()
+ steps = int(rotation/delta)
+
+ for tab in xrange(abs(steps)):
+ if steps > 0:
+ before = self._nLeftButtonStatus
+ self._nLeftButtonStatus = FNB_BTN_PRESSED
+ self.RotateLeft()
+ self._nLeftButtonStatus = before
+ else:
+ before = self._nRightButtonStatus
+ self._nRightButtonStatus = FNB_BTN_PRESSED
+ self.RotateRight()
+ self._nRightButtonStatus = before
+
+ event.Skip()
+
+
+ def OnRightDown(self, event):
+ """
+ Handles the ``wx.EVT_RIGHT_DOWN`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ where, tabIdx = self.HitTest(event.GetPosition())
+
+ if where in [FNB_TAB, FNB_TAB_X]:
+
+ if self._pagesInfoVec[tabIdx].GetEnabled():
+ # This shouldn't really change the selection, so it's commented out
+ # Fire events and eventually (if allowed) change selection
+ # self.FireEvent(tabIdx)
+
+ # send a message to popup a custom menu
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, self.GetParent().GetId())
+ event.SetSelection(tabIdx)
+ event.SetOldSelection(self._iActivePage)
+ event.SetEventObject(self.GetParent())
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+
+ if self._pRightClickMenu:
+ self.PopupMenu(self._pRightClickMenu)
+
+ event.Skip()
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # Reset buttons status
+ self._nXButtonStatus = FNB_BTN_NONE
+ self._nLeftButtonStatus = FNB_BTN_NONE
+ self._nRightButtonStatus = FNB_BTN_NONE
+ self._nTabXButtonStatus = FNB_BTN_NONE
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+
+ self._nLeftClickZone, tabIdx = self.HitTest(event.GetPosition())
+
+ if self._nLeftClickZone == FNB_DROP_DOWN_ARROW:
+ self._nArrowDownButtonStatus = FNB_BTN_PRESSED
+ self.Refresh()
+ elif self._nLeftClickZone == FNB_LEFT_ARROW:
+ self._nLeftButtonStatus = FNB_BTN_PRESSED
+ self.Refresh()
+ elif self._nLeftClickZone == FNB_RIGHT_ARROW:
+ self._nRightButtonStatus = FNB_BTN_PRESSED
+ self.Refresh()
+ elif self._nLeftClickZone == FNB_X:
+ self._nXButtonStatus = FNB_BTN_PRESSED
+ self.Refresh()
+ elif self._nLeftClickZone == FNB_TAB_X:
+ self._nTabXButtonStatus = FNB_BTN_PRESSED
+ self.Refresh()
+
+ elif self._nLeftClickZone == FNB_TAB:
+
+ if self._iActivePage != tabIdx:
+
+ # In case the tab is disabled, we dont allow to choose it
+ if len(self._pagesInfoVec) > tabIdx and \
+ self._pagesInfoVec[tabIdx].GetEnabled():
+ self.FireEvent(tabIdx)
+
+
+ def RotateLeft(self):
+ """ Scrolls tabs to the left by bulk of 5 tabs. """
+
+ if self._nFrom == 0:
+ return
+
+ # Make sure that the button was pressed before
+ if self._nLeftButtonStatus != FNB_BTN_PRESSED:
+ return
+
+ self._nLeftButtonStatus = FNB_BTN_HOVER
+
+ # We scroll left with bulks of 5
+ scrollLeft = self.GetNumTabsCanScrollLeft()
+
+ self._nFrom -= scrollLeft
+ if self._nFrom < 0:
+ self._nFrom = 0
+
+ self.Refresh()
+
+
+ def RotateRight(self):
+ """ Scrolls tabs to the right by bulk of 5 tabs. """
+
+ if self._nFrom >= len(self._pagesInfoVec) - 1:
+ return
+
+ # Make sure that the button was pressed before
+ if self._nRightButtonStatus != FNB_BTN_PRESSED:
+ return
+
+ self._nRightButtonStatus = FNB_BTN_HOVER
+
+ # Check if the right most tab is visible, if it is
+ # don't rotate right anymore
+ if self._pagesInfoVec[len(self._pagesInfoVec)-1].GetPosition() != wx.Point(-1, -1):
+ return
+
+ self._nFrom += 1
+ self.Refresh()
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # forget the zone that was initially clicked
+ self._nLeftClickZone = FNB_NOWHERE
+
+ where, tabIdx = self.HitTest(event.GetPosition())
+
+ if not self.HasAGWFlag(FNB_NO_TAB_FOCUS):
+ # Make sure selected tab has focus
+ self.SetFocus()
+
+ if where == FNB_LEFT_ARROW:
+ self.RotateLeft()
+
+ elif where == FNB_RIGHT_ARROW:
+ self.RotateRight()
+
+ elif where == FNB_X:
+
+ # Make sure that the button was pressed before
+ if self._nXButtonStatus != FNB_BTN_PRESSED:
+ return
+
+ self._nXButtonStatus = FNB_BTN_HOVER
+
+ self.DeletePage(self._iActivePage)
+
+ elif where == FNB_TAB_X:
+
+ # Make sure that the button was pressed before
+ if self._nTabXButtonStatus != FNB_BTN_PRESSED:
+ return
+
+ self._nTabXButtonStatus = FNB_BTN_HOVER
+
+ self.DeletePage(self._iActivePage)
+
+ elif where == FNB_DROP_DOWN_ARROW:
+
+ # Make sure that the button was pressed before
+ if self._nArrowDownButtonStatus != FNB_BTN_PRESSED:
+ return
+
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+
+ # Refresh the button status
+ renderer = self._mgr.GetRenderer(self.GetParent().GetAGWWindowStyleFlag())
+ dc = wx.ClientDC(self)
+ renderer.DrawDropDownArrow(self, dc)
+
+ self.PopupTabsMenu()
+
+ event.Skip()
+
+
+ def HitTest(self, pt):
+ """
+ HitTest method for :class:`PageContainer`.
+
+ :param `pt`: an instance of :class:`Point`, to test for hits.
+
+ :return: The hit test flag (if any) and the hit page index (if any). The return
+ value can be one of the following bits:
+
+ ========================= ======= =================================
+ HitTest Flag Value Description
+ ========================= ======= =================================
+ ``FNB_NOWHERE`` 0 Indicates mouse coordinates not on any tab of the notebook
+ ``FNB_TAB`` 1 Indicates mouse coordinates inside a tab
+ ``FNB_X`` 2 Indicates mouse coordinates inside the 'X' button region
+ ``FNB_TAB_X`` 3 Indicates mouse coordinates inside the 'X' region in a tab
+ ``FNB_LEFT_ARROW`` 4 Indicates mouse coordinates inside the left arrow region
+ ``FNB_RIGHT_ARROW`` 5 Indicates mouse coordinates inside the right arrow region
+ ``FNB_DROP_DOWN_ARROW`` 6 Indicates mouse coordinates inside the drop down arrow region
+ ========================= ======= =================================
+
+ """
+
+ agwStyle = self.GetParent().GetAGWWindowStyleFlag()
+ render = self._mgr.GetRenderer(agwStyle)
+
+ fullrect = self.GetClientRect()
+ btnLeftPos = render.GetLeftButtonPos(self)
+ btnRightPos = render.GetRightButtonPos(self)
+ btnXPos = render.GetXPos(self)
+
+ tabIdx = -1
+
+ if len(self._pagesInfoVec) == 0:
+ return FNB_NOWHERE, tabIdx
+
+ rect = wx.Rect(btnXPos, 8, 16, 16)
+ if rect.Contains(pt):
+ return (agwStyle & FNB_NO_X_BUTTON and [FNB_NOWHERE] or [FNB_X])[0], tabIdx
+
+ rect = wx.Rect(btnRightPos, 8, 16, 16)
+ if agwStyle & FNB_DROPDOWN_TABS_LIST:
+ rect = wx.Rect(render.GetDropArrowButtonPos(self), 8, 16, 16)
+ if rect.Contains(pt):
+ return FNB_DROP_DOWN_ARROW, tabIdx
+
+ if rect.Contains(pt):
+ return (agwStyle & FNB_NO_NAV_BUTTONS and [FNB_NOWHERE] or [FNB_RIGHT_ARROW])[0], tabIdx
+
+ rect = wx.Rect(btnLeftPos, 8, 16, 16)
+ if rect.Contains(pt):
+ return (agwStyle & FNB_NO_NAV_BUTTONS and [FNB_NOWHERE] or [FNB_LEFT_ARROW])[0], tabIdx
+
+ # Test whether a left click was made on a tab
+ bFoundMatch = False
+
+ for cur in xrange(self._nFrom, len(self._pagesInfoVec)):
+
+ pgInfo = self._pagesInfoVec[cur]
+
+ if pgInfo.GetPosition() == wx.Point(-1, -1):
+ continue
+
+ if agwStyle & FNB_X_ON_TAB and cur == self.GetSelection():
+ # 'x' button exists on a tab
+ if self._pagesInfoVec[cur].GetXRect().Contains(pt):
+ return FNB_TAB_X, cur
+
+ if agwStyle & FNB_VC8:
+
+ if self._pagesInfoVec[cur].GetRegion().Contains(pt.x, pt.y):
+ if bFoundMatch or cur == self.GetSelection():
+ return FNB_TAB, cur
+
+ tabIdx = cur
+ bFoundMatch = True
+
+ else:
+
+ tabRect = wx.Rect(pgInfo.GetPosition().x, pgInfo.GetPosition().y,
+ pgInfo.GetSize().x, pgInfo.GetSize().y)
+
+ if tabRect.Contains(pt):
+ # We have a match
+ return FNB_TAB, cur
+
+ if bFoundMatch:
+ return FNB_TAB, tabIdx
+
+ if self._isdragging:
+ # We are doing DND, so check also the region outside the tabs
+ # try before the first tab
+ pgInfo = self._pagesInfoVec[0]
+ tabRect = wx.Rect(0, pgInfo.GetPosition().y, pgInfo.GetPosition().x, self.GetParent().GetSize().y)
+ if tabRect.Contains(pt):
+ return FNB_TAB, 0
+
+ # try after the last tab
+ pgInfo = self._pagesInfoVec[-1]
+ startpos = pgInfo.GetPosition().x+pgInfo.GetSize().x
+ tabRect = wx.Rect(startpos, pgInfo.GetPosition().y, fullrect.width-startpos, self.GetParent().GetSize().y)
+
+ if tabRect.Contains(pt):
+ return FNB_TAB, len(self._pagesInfoVec)
+
+ # Default
+ return FNB_NOWHERE, -1
+
+
+ def SetSelection(self, page):
+ """
+ Sets the selected page.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ book = self.GetParent()
+ FlatNotebook.SetSelection(book, page)
+
+## self.DoSetSelection(page)
+
+
+ def DoSetSelection(self, page):
+ """
+ Does the actual selection of a page.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ if page < len(self._pagesInfoVec):
+ #! fix for tabfocus
+ da_page = self._pParent.GetPage(page)
+
+ if da_page != None:
+ da_page.SetFocus()
+
+ if not self.IsTabVisible(page):
+ # Try to remove one tab from start and try again
+
+ if not self.CanFitToScreen(page):
+
+ if self._nFrom > page:
+ self._nFrom = page
+ else:
+ while self._nFrom < page:
+ self._nFrom += 1
+ if self.CanFitToScreen(page):
+ break
+
+ self.Refresh()
+
+
+ def DeletePage(self, page):
+ """
+ Delete the specified page from :class:`PageContainer`.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ book = self.GetParent()
+ book.DeletePage(page)
+ book.Refresh()
+
+
+ def IsMouseHovering(self, page):
+ """
+ Returns whether or not the mouse is hovering over this page's tab
+
+ :param `page`: an integer specifying the page index.
+ """
+ return page == self._nHoveringOverTabIndex
+
+
+ def IsTabVisible(self, page):
+ """
+ Returns whether a tab is visible or not.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ iLastVisiblePage = self.GetLastVisibleTab()
+ return page <= iLastVisiblePage and page >= self._nFrom
+
+
+ def DoDeletePage(self, page):
+ """
+ Does the actual page deletion.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ # Remove the page from the vector
+ book = self.GetParent()
+ self._pagesInfoVec.pop(page)
+
+ # Thanks to Yiaanis AKA Mandrav
+ if self._iActivePage >= page:
+ self._iActivePage = self._iActivePage - 1
+ self._iPreviousActivePage = -1
+
+ # The delete page was the last first on the array,
+ # but the book still has more pages, so we set the
+ # active page to be the first one (0)
+ if self._iActivePage < 0 and len(self._pagesInfoVec) > 0:
+ self._iActivePage = 0
+ self._iPreviousActivePage = -1
+
+ # Refresh the tabs
+ if self._iActivePage >= 0:
+
+ book._bForceSelection = True
+
+ # Check for selection and send event
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
+ event.SetSelection(self._iActivePage)
+ event.SetOldSelection(self._iPreviousActivePage)
+ event.SetEventObject(self.GetParent())
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+
+ book.SetSelection(self._iActivePage)
+ book._bForceSelection = False
+
+ # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
+ event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
+ event.SetOldSelection(self._iPreviousActivePage)
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+
+ #if not self._pagesInfoVec:
+ # # Erase the page container drawings
+ # dc = wx.ClientDC(self)
+ # dc.Clear()
+
+
+ def DeleteAllPages(self):
+ """ Deletes all the pages in the :class:`PageContainer`. """
+
+ self._iActivePage = -1
+ self._iPreviousActivePage = -1
+ self._nFrom = 0
+ self._pagesInfoVec = []
+
+ # Erase the page container drawings
+ dc = wx.ClientDC(self)
+ dc.Clear()
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._pagesInfoVec and self.IsShown():
+
+ xButtonStatus = self._nXButtonStatus
+ xTabButtonStatus = self._nTabXButtonStatus
+ rightButtonStatus = self._nRightButtonStatus
+ leftButtonStatus = self._nLeftButtonStatus
+ dropDownButtonStatus = self._nArrowDownButtonStatus
+
+ agwStyle = self.GetParent().GetAGWWindowStyleFlag()
+
+ self._nXButtonStatus = FNB_BTN_NONE
+ self._nRightButtonStatus = FNB_BTN_NONE
+ self._nLeftButtonStatus = FNB_BTN_NONE
+ self._nTabXButtonStatus = FNB_BTN_NONE
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+ bRedrawTabs = False
+ self._nHoveringOverTabIndex = -1
+
+ where, tabIdx = self.HitTest(event.GetPosition())
+
+ if where == FNB_X:
+ if event.LeftIsDown():
+
+ self._nXButtonStatus = (self._nLeftClickZone==FNB_X and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
+
+ else:
+
+ self._nXButtonStatus = FNB_BTN_HOVER
+
+ elif where == FNB_DROP_DOWN_ARROW:
+ if event.LeftIsDown():
+
+ self._nArrowDownButtonStatus = (self._nLeftClickZone==FNB_DROP_DOWN_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
+
+ else:
+
+ self._nArrowDownButtonStatus = FNB_BTN_HOVER
+
+ elif where == FNB_TAB_X:
+ if event.LeftIsDown():
+
+ self._nTabXButtonStatus = (self._nLeftClickZone==FNB_TAB_X and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
+
+ else:
+
+ self._nTabXButtonStatus = FNB_BTN_HOVER
+
+ elif where == FNB_RIGHT_ARROW:
+ if event.LeftIsDown():
+
+ self._nRightButtonStatus = (self._nLeftClickZone==FNB_RIGHT_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
+
+ else:
+
+ self._nRightButtonStatus = FNB_BTN_HOVER
+
+ elif where == FNB_LEFT_ARROW:
+ if event.LeftIsDown():
+
+ self._nLeftButtonStatus = (self._nLeftClickZone==FNB_LEFT_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
+
+ else:
+
+ self._nLeftButtonStatus = FNB_BTN_HOVER
+
+ elif where == FNB_TAB:
+ # Call virtual method for showing tooltip
+ self.ShowTabTooltip(tabIdx)
+
+ if not self.GetEnabled(tabIdx):
+ # Set the cursor to be 'No-entry'
+ wx.SetCursor(wx.StockCursor(wx.CURSOR_NO_ENTRY))
+ self._setCursor = True
+ else:
+ self._nHoveringOverTabIndex = tabIdx
+ if self._setCursor:
+ wx.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ self._setCursor = False
+
+ # Support for drag and drop
+ if event.Dragging() and not (agwStyle & FNB_NODRAG):
+
+ self._isdragging = True
+ draginfo = FNBDragInfo(self, tabIdx)
+ drginfo = cPickle.dumps(draginfo)
+ dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook"))
+ dataobject.SetData(drginfo)
+ dragSource = FNBDropSource(self)
+ dragSource.SetData(dataobject)
+ dragSource.DoDragDrop(wx.Drag_DefaultMove)
+
+ if self._nHoveringOverTabIndex != self._nHoveringOverLastTabIndex:
+ self._nHoveringOverLastTabIndex = self._nHoveringOverTabIndex
+ if self._nHoveringOverTabIndex >= 0:
+ bRedrawTabs = True
+
+ bRedrawX = self._nXButtonStatus != xButtonStatus
+ bRedrawRight = self._nRightButtonStatus != rightButtonStatus
+ bRedrawLeft = self._nLeftButtonStatus != leftButtonStatus
+ bRedrawTabX = self._nTabXButtonStatus != xTabButtonStatus
+ bRedrawDropArrow = self._nArrowDownButtonStatus != dropDownButtonStatus
+
+ render = self._mgr.GetRenderer(agwStyle)
+
+ if (bRedrawX or bRedrawRight or bRedrawLeft or bRedrawTabX or bRedrawDropArrow or bRedrawTabs):
+
+ dc = wx.ClientDC(self)
+
+ if bRedrawX:
+
+ render.DrawX(self, dc)
+
+ if bRedrawLeft:
+
+ render.DrawLeftArrow(self, dc)
+
+ if bRedrawRight:
+
+ render.DrawRightArrow(self, dc)
+
+ if bRedrawTabX or bRedrawTabs:
+
+ self.Refresh()
+
+ if bRedrawDropArrow:
+
+ render.DrawDropDownArrow(self, dc)
+
+ event.Skip()
+
+
+ def GetLastVisibleTab(self):
+ """ Returns the last visible tab in the tab area. """
+
+ if self._nFrom < 0:
+ return -1
+
+ ii = 0
+
+ for ii in xrange(self._nFrom, len(self._pagesInfoVec)):
+
+ if self._pagesInfoVec[ii].GetPosition() == wx.Point(-1, -1):
+ break
+
+ return ii-1
+
+
+ def GetNumTabsCanScrollLeft(self):
+ """ Returns the number of tabs than can be scrolled left. """
+
+ if self._nFrom - 1 >= 0:
+ return 1
+
+ return 0
+
+
+ def IsDefaultTabs(self):
+ """ Returns whether a tab has a default style. """
+
+ agwStyle = self.GetParent().GetAGWWindowStyleFlag()
+ res = (agwStyle & FNB_VC71) or (agwStyle & FNB_FANCY_TABS) or (agwStyle & FNB_VC8)
+ return not res
+
+
+ def AdvanceSelection(self, forward=True):
+ """
+ Cycles through the tabs.
+
+ :param `forward`: if ``True``, the selection is advanced in ascending order
+ (to the right), otherwise the selection is advanced in descending order.
+
+ :note: The call to this function generates the page changing events.
+ """
+
+ nSel = self.GetSelection()
+
+ if nSel < 0:
+ return
+
+ nMax = self.GetPageCount() - 1
+
+ if forward:
+ newSelection = (nSel == nMax and [0] or [nSel + 1])[0]
+ else:
+ newSelection = (nSel == 0 and [nMax] or [nSel - 1])[0]
+
+ if not self._pagesInfoVec[newSelection].GetEnabled():
+ return
+
+ self.FireEvent(newSelection)
+
+
+ def OnMouseLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self._nLeftButtonStatus = FNB_BTN_NONE
+ self._nXButtonStatus = FNB_BTN_NONE
+ self._nRightButtonStatus = FNB_BTN_NONE
+ self._nTabXButtonStatus = FNB_BTN_NONE
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+ self._nHoveringOverTabIndex = -1
+ self._nHoveringOverLastTabIndex = -1
+
+ self.Refresh()
+ selection = self.GetSelection()
+
+ if selection == -1:
+ event.Skip()
+ return
+
+ if not self.IsTabVisible(selection):
+ if selection == len(self._pagesInfoVec) - 1:
+ if not self.CanFitToScreen(selection):
+ event.Skip()
+ return
+ else:
+ event.Skip()
+ return
+
+ agwStyle = self.GetParent().GetAGWWindowStyleFlag()
+ render = self._mgr.GetRenderer(agwStyle)
+ dc = wx.ClientDC(self)
+ render.DrawTabX(self, dc, self._pagesInfoVec[selection].GetXRect(), selection, self._nTabXButtonStatus)
+ if not agwStyle & FNB_RIBBON_TABS:
+ render.DrawFocusRectangle(dc, self, self._pagesInfoVec[selection])
+
+ event.Skip()
+
+
+ def OnMouseEnterWindow(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self._nLeftButtonStatus = FNB_BTN_NONE
+ self._nXButtonStatus = FNB_BTN_NONE
+ self._nRightButtonStatus = FNB_BTN_NONE
+ self._nLeftClickZone = FNB_BTN_NONE
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+
+ event.Skip()
+
+
+ def ShowTabTooltip(self, tabIdx):
+ """
+ Shows a tab tooltip.
+
+ :param `tabIdx`: an integer specifying the page index.
+ """
+
+ pWindow = self._pParent.GetPage(tabIdx)
+
+ if pWindow:
+ pToolTip = pWindow.GetToolTip()
+ if pToolTip and pToolTip.GetWindow() == pWindow:
+ self.SetToolTipString(pToolTip.GetTip())
+
+
+ def SetPageImage(self, page, image):
+ """
+ Sets the image index for the given page.
+
+ :param `page`: an integer specifying the page index;
+ :param `image`: an index into the image list which was set with :meth:`~PageContainer.SetImageList`.
+ """
+
+ if page < len(self._pagesInfoVec):
+ self._pagesInfoVec[page].SetImageIndex(image)
+ self.Refresh()
+
+
+ def GetPageImage(self, page):
+ """
+ Returns the image index associated to a page.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ if page < len(self._pagesInfoVec):
+ return self._pagesInfoVec[page].GetImageIndex()
+
+ return -1
+
+
+ def GetPageTextColour(self, page):
+ """
+ Returns the tab text colour if it has been set previously, or ``None`` otherwise.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ if page < len(self._pagesInfoVec):
+ return self._pagesInfoVec[page].GetPageTextColour()
+
+ return None
+
+
+ def SetPageTextColour(self, page, colour):
+ """
+ Sets the tab text colour individually.
+
+ :param `page`: an integer specifying the page index;
+ :param `colour`: a valid :class:`Colour` object or any typemap supported by wxWidgets/wxPython
+ to generate a colour (i.e., a hex string, a colour name, a 3 or 4 integer tuple). You can
+ pass ``None`` or :class:`NullColour` to return to the default page text colour.
+ """
+
+ if page < len(self._pagesInfoVec):
+ self._pagesInfoVec[page].SetPageTextColour(colour)
+ self.Refresh()
+
+
+ def OnDropTarget(self, x, y, nTabPage, wnd_oldContainer):
+ """
+ Handles the drop action from a drag and drop operation.
+
+ :param `x`: the x position of the drop action;
+ :param `y`: the y position of the drop action;
+ :param `nTabPage`: the index of the tab being dropped;
+ :param `wnd_oldContainer`: the :class:`FlatNotebook` to which the dropped tab previously
+ belonged to.
+ """
+
+ # Disable drag'n'drop for disabled tab
+ if len(wnd_oldContainer._pagesInfoVec) > nTabPage and \
+ not wnd_oldContainer._pagesInfoVec[nTabPage].GetEnabled():
+ return wx.DragCancel
+
+ self._isdragging = True
+ oldContainer = wnd_oldContainer
+ nIndex = -1
+
+ where, nIndex = self.HitTest(wx.Point(x, y))
+
+ oldNotebook = oldContainer.GetParent()
+ newNotebook = self.GetParent()
+
+ if oldNotebook == newNotebook:
+
+ if nTabPage >= 0:
+
+ if where == FNB_TAB:
+ self.MoveTabPage(nTabPage, nIndex)
+
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_DROPPED, self.GetParent().GetId())
+ event.SetSelection(nIndex)
+ event.SetOldSelection(nTabPage)
+ event.SetEventObject(self.GetParent())
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+
+ elif self.GetParent().GetAGWWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND:
+
+ if wx.Platform in ["__WXMSW__", "__WXGTK__", "__WXMAC__"]:
+ if nTabPage >= 0:
+
+ window = oldNotebook.GetPage(nTabPage)
+
+ if window:
+ where, nIndex = newNotebook._pages.HitTest(wx.Point(x, y))
+ caption = oldContainer.GetPageText(nTabPage)
+ imageindex = oldContainer.GetPageImage(nTabPage)
+ oldNotebook.RemovePage(nTabPage)
+ window.Reparent(newNotebook)
+
+ if imageindex >= 0:
+
+ bmp = oldNotebook.GetImageList().GetBitmap(imageindex)
+ newImageList = newNotebook.GetImageList()
+
+ if not newImageList:
+ xbmp, ybmp = bmp.GetWidth(), bmp.GetHeight()
+ newImageList = wx.ImageList(xbmp, ybmp)
+ imageindex = 0
+ else:
+ imageindex = newImageList.GetImageCount()
+
+ newImageList.Add(bmp)
+ newNotebook.SetImageList(newImageList)
+
+ newNotebook.InsertPage(nIndex, window, caption, True, imageindex)
+
+ event = FlatNotebookDragEvent(wxEVT_FLATNOTEBOOK_PAGE_DROPPED_FOREIGN, self.GetParent().GetId())
+ event.SetSelection(nIndex)
+ event.SetOldSelection(nTabPage)
+ event.SetNotebook(newNotebook)
+ event.SetOldNotebook(oldNotebook)
+ event.SetEventObject(self.GetParent())
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+
+ self._isdragging = False
+
+ return wx.DragMove
+
+
+ def MoveTabPage(self, nMove, nMoveTo):
+ """
+ Moves a tab inside the same :class:`FlatNotebook`.
+
+ :param `nMove`: the start index of the moved tab;
+ :param `nMoveTo`: the destination index of the moved tab.
+ """
+
+ if nMove == nMoveTo:
+ return
+
+ elif nMoveTo < len(self._pParent._windows):
+ nMoveTo = nMoveTo + 1
+
+ self._pParent.Freeze()
+
+ # Remove the window from the main sizer
+ nCurSel = self._pParent._pages.GetSelection()
+ self._pParent._mainSizer.Detach(self._pParent._windows[nCurSel])
+ self._pParent._windows[nCurSel].Hide()
+
+ pWindow = self._pParent._windows[nMove]
+ self._pParent._windows.pop(nMove)
+ self._pParent._windows.insert(nMoveTo-1, pWindow)
+
+ pgInfo = self._pagesInfoVec[nMove]
+
+ self._pagesInfoVec.pop(nMove)
+ self._pagesInfoVec.insert(nMoveTo - 1, pgInfo)
+
+ # Add the page according to the style
+ pSizer = self._pParent._mainSizer
+ agwStyle = self.GetParent().GetAGWWindowStyleFlag()
+
+ if agwStyle & FNB_BOTTOM:
+
+ pSizer.Insert(0, pWindow, 1, wx.EXPAND)
+
+ else:
+
+ # We leave a space of 1 pixel around the window
+ pSizer.Add(pWindow, 1, wx.EXPAND)
+
+ pWindow.Show()
+
+ pSizer.Layout()
+ self._iActivePage = nMoveTo - 1
+ self._iPreviousActivePage = -1
+ self.DoSetSelection(self._iActivePage)
+ self.Refresh()
+ self._pParent.Thaw()
+
+
+ def CanFitToScreen(self, page):
+ """
+ Returns wheter a tab can fit in the left space in the screen or not.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ # Incase the from is greater than page,
+ # we need to reset the self._nFrom, so in order
+ # to force the caller to do so, we return false
+ if self._nFrom > page:
+ return False
+
+ agwStyle = self.GetParent().GetAGWWindowStyleFlag()
+ render = self._mgr.GetRenderer(agwStyle)
+
+ vTabInfo = render.NumberTabsCanFit(self)
+
+ if page - self._nFrom >= len(vTabInfo):
+ return False
+
+ return True
+
+
+ def GetNumOfVisibleTabs(self):
+ """ Returns the number of visible tabs. """
+
+ count = 0
+ for ii in xrange(self._nFrom, len(self._pagesInfoVec)):
+ if self._pagesInfoVec[ii].GetPosition() == wx.Point(-1, -1):
+ break
+ count = count + 1
+
+ return count
+
+
+ def GetEnabled(self, page):
+ """
+ Returns whether a tab is enabled or not.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ if page >= len(self._pagesInfoVec):
+ return True # Seems strange, but this is the default
+
+ return self._pagesInfoVec[page].GetEnabled()
+
+
+ def EnableTab(self, page, enabled=True):
+ """
+ Enables or disables a tab.
+
+ :param `page`: an integer specifying the page index;
+ :param `enabled`: ``True`` to enable a tab, ``False`` to disable it.
+ """
+
+ if page >= len(self._pagesInfoVec):
+ return
+
+ self._pagesInfoVec[page].EnableTab(enabled)
+
+
+ def GetSingleLineBorderColour(self):
+ """ Returns the colour for the single line border. """
+
+ if self.HasAGWFlag(FNB_FANCY_TABS):
+ return self._colourFrom
+
+ return wx.WHITE
+
+
+ def HasAGWFlag(self, flag):
+ """
+ Returns whether a flag is present in the :class:`FlatNotebook` style.
+
+ :param `flag`: one of the possible :class:`FlatNotebook` window styles.
+
+ :see: :meth:`FlatNotebook.SetAGWWindowStyleFlag() <FlatNotebook.SetAGWWindowStyleFlag>` for a list of possible window
+ style flags.
+ """
+
+ agwStyle = self.GetParent().GetAGWWindowStyleFlag()
+ res = (agwStyle & flag and [True] or [False])[0]
+ return res
+
+
+ def ClearAGWFlag(self, flag):
+ """
+ Deletes a flag from the :class:`FlatNotebook` style.
+
+ :param `flag`: one of the possible :class:`FlatNotebook` window styles.
+
+ :see: :meth:`FlatNotebook.SetAGWWindowStyleFlag() <FlatNotebook.SetAGWWindowStyleFlag>` for a list of possible window
+ style flags.
+ """
+
+ parent = self.GetParent()
+ agwStyle = parent.GetAGWWindowStyleFlag()
+ agwStyle &= ~flag
+ parent.SetAGWWindowStyleFlag(agwStyle)
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the :class:`FlatNotebook` window style.
+
+ :param `agwStyle`: the new :class:`FlatNotebook` window style.
+
+ :see: The :meth:`FlatNotebook.__init__() <FlatNotebook.__init__>` method for the `agwStyle` parameter description.
+ """
+
+ self.GetParent().SetAGWWindowStyleFlag(agwStyle)
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`FlatNotebook` window style.
+
+ :see: The :meth:`FlatNotebook.__init__() <FlatNotebook.__init__>` method for the `agwStyle` parameter description.
+ """
+
+ return self.GetParent().GetAGWWindowStyleFlag()
+
+
+ def TabHasImage(self, tabIdx):
+ """
+ Returns whether a tab has an associated image index or not.
+
+ :param `tabIdx`: an integer specifying the page index.
+ """
+
+ if self._ImageList:
+ return self._pagesInfoVec[tabIdx].GetImageIndex() != -1
+
+ return False
+
+
+ def OnLeftDClick(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DCLICK`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ where, tabIdx = self.HitTest(event.GetPosition())
+
+ if where == FNB_RIGHT_ARROW:
+ self._nRightButtonStatus = FNB_BTN_PRESSED
+ self.RotateRight()
+
+ elif where == FNB_LEFT_ARROW:
+ self._nLeftButtonStatus = FNB_BTN_PRESSED
+ self.RotateLeft()
+
+ elif self.HasAGWFlag(FNB_DCLICK_CLOSES_TABS):
+
+ if where == FNB_TAB:
+ self.DeletePage(tabIdx)
+
+ else:
+
+ event.Skip()
+
+
+ def OnSetFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if self._iActivePage < 0:
+ event.Skip()
+ return
+
+ self.SetFocusedPage(self._iActivePage)
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self.SetFocusedPage()
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+
+ :note: When the :class:`PageContainer` has the focus tabs can be changed with
+ the left/right arrow keys.
+ """
+
+ key = event.GetKeyCode()
+ if key == wx.WXK_LEFT:
+ self.GetParent().AdvanceSelection(False)
+ self.SetFocus()
+ elif key == wx.WXK_RIGHT:
+ self.GetParent().AdvanceSelection(True)
+ self.SetFocus()
+ elif key == wx.WXK_TAB and not event.ControlDown():
+ flags = 0
+ if not event.ShiftDown(): flags |= wx.NavigationKeyEvent.IsForward
+ if event.CmdDown(): flags |= wx.NavigationKeyEvent.WinChange
+ self.Navigate(flags)
+ else:
+ event.Skip()
+
+
+ def SetFocusedPage(self, pageIndex=-1):
+ """
+ Sets/Unsets the focus on the appropriate page.
+
+ :param `pageIndex`: an integer specifying the page index. If `pageIndex`
+ is defaulted to -1, we have lost focus and no focus indicator is drawn.
+ """
+
+ for indx, page in enumerate(self._pagesInfoVec):
+ if indx == pageIndex:
+ page._hasFocus = True
+ else:
+ page._hasFocus = False
+
+ self.Refresh()
+
+
+ def PopupTabsMenu(self):
+ """ Pops up the menu activated with the drop down arrow in the navigation area. """
+
+ popupMenu = wx.Menu()
+
+ for i in xrange(len(self._pagesInfoVec)):
+ pi = self._pagesInfoVec[i]
+ item = wx.MenuItem(popupMenu, i+1, pi.GetCaption(), pi.GetCaption(), wx.ITEM_NORMAL)
+ self.Bind(wx.EVT_MENU, self.OnTabMenuSelection, item)
+
+ # There is an alignment problem with wx2.6.3 & Menus so only use
+ # images for versions above 2.6.3
+ if wx.VERSION > (2, 6, 3, 0) and self.TabHasImage(i):
+ item.SetBitmap(self.GetImageList().GetBitmap(pi.GetImageIndex()))
+
+ popupMenu.AppendItem(item)
+ item.Enable(pi.GetEnabled())
+
+ self.PopupMenu(popupMenu)
+
+
+ def OnTabMenuSelection(self, event):
+ """
+ Handles the ``wx.EVT_MENU`` event for :class:`PageContainer`.
+
+ :param `event`: a :class:`MenuEvent` event to be processed.
+ """
+
+ selection = event.GetId() - 1
+ self.FireEvent(selection)
+
+
+ def FireEvent(self, selection):
+ """
+ Fires the ``EVT_FLATNOTEBOOK_PAGE_CHANGING`` and ``EVT_FLATNOTEBOOK_PAGE_CHANGED``
+ events called from other methods (from menu selection or `Smart Tabbing`).
+
+ This is an utility function.
+
+ :param `selection`: the new selection inside :class:`FlatNotebook`.
+ """
+
+ if selection == self._iActivePage:
+ # No events for the same selection
+ return
+
+ oldSelection = self._iActivePage
+
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
+ event.SetSelection(selection)
+ event.SetOldSelection(oldSelection)
+ event.SetEventObject(self.GetParent())
+
+ if not self.GetParent().GetEventHandler().ProcessEvent(event) or event.IsAllowed():
+
+ self.SetSelection(selection)
+
+ # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
+ event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
+ event.SetOldSelection(oldSelection)
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+ if not self.HasAGWFlag(FNB_NO_TAB_FOCUS):
+ self.SetFocus()
+
+
+ def SetImageList(self, imglist):
+ """
+ Sets the image list for the :class:`PageContainer`.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ self._ImageList = imglist
+
+
+ def AssignImageList(self, imglist):
+ """
+ Assigns the image list for the :class:`PageContainer`.
+
+ :param `imageList`: an instance of :class:`ImageList`.
+ """
+
+ self._ImageList = imglist
+
+
+ def GetImageList(self):
+ """ Returns the image list for the page control. """
+
+ return self._ImageList
+
+
+ def GetSelection(self):
+ """ Returns the current selected page. """
+
+ return self._iActivePage
+
+
+ def GetPageCount(self):
+ """ Returns the number of tabs in the :class:`FlatNotebook` control. """
+
+ return len(self._pagesInfoVec)
+
+
+ def GetPageText(self, page):
+ """
+ Returns the tab caption of the page.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ if page < len(self._pagesInfoVec):
+ return self._pagesInfoVec[page].GetCaption()
+ else:
+ return u''
+
+
+ def SetPageText(self, page, text):
+ """
+ Sets the tab caption of the page.
+
+ :param `page`: an integer specifying the page index;
+ :param `text`: the new tab label.
+ """
+
+ if page < len(self._pagesInfoVec):
+ self._pagesInfoVec[page].SetCaption(text)
+ return True
+ else:
+ return False
+
+
+ def DrawDragHint(self):
+ """ Draws small arrow at the place that the tab will be placed. """
+
+ # get the index of tab that will be replaced with the dragged tab
+ pt = wx.GetMousePosition()
+ client_pt = self.ScreenToClient(pt)
+ where, tabIdx = self.HitTest(client_pt)
+ self._mgr.GetRenderer(self.GetParent().GetAGWWindowStyleFlag()).DrawDragHint(self, tabIdx)
+
+
+# ---------------------------------------------------------------------------- #
+# Class FlatNotebookCompatible
+# This class is more compatible with the wx.Notebook API.
+# ---------------------------------------------------------------------------- #
+
+class FlatNotebookCompatible(FlatNotebook):
+ """
+ This class is more compatible with the :class:`Notebook` API, especially regarding
+ page changing events. Use the :meth:`FlatNotebookCompatible.SetSelection() <FlatNotebookCompatible.SetSelection>` method if you wish to send page
+ changing events, or :meth:`FlatNotebookCompatible.ChangeSelection() <FlatNotebookCompatible.ChangeSelection>` otherwise.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=0, name="FlatNotebook"):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`FlatNotebook` parent;
+ :param `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`PyPanel` window style;
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ ================================ =========== ==================================================
+ Window Styles Hex Value Description
+ ================================ =========== ==================================================
+ ``FNB_VC71`` 0x1 Use Visual Studio 2003 (VC7.1) style for tabs.
+ ``FNB_FANCY_TABS`` 0x2 Use fancy style - square tabs filled with gradient colouring.
+ ``FNB_TABS_BORDER_SIMPLE`` 0x4 Draw thin border around the page.
+ ``FNB_NO_X_BUTTON`` 0x8 Do not display the 'X' button.
+ ``FNB_NO_NAV_BUTTONS`` 0x10 Do not display the right/left arrows.
+ ``FNB_MOUSE_MIDDLE_CLOSES_TABS`` 0x20 Use the mouse middle button for cloing tabs.
+ ``FNB_BOTTOM`` 0x40 Place tabs at bottom - the default is to place them at top.
+ ``FNB_NODRAG`` 0x80 Disable dragging of tabs.
+ ``FNB_VC8`` 0x100 Use Visual Studio 2005 (VC8) style for tabs.
+ ``FNB_X_ON_TAB`` 0x200 Place 'X' close button on the active tab.
+ ``FNB_BACKGROUND_GRADIENT`` 0x400 Use gradients to paint the tabs background.
+ ``FNB_COLOURFUL_TABS`` 0x800 Use colourful tabs (VC8 style only).
+ ``FNB_DCLICK_CLOSES_TABS`` 0x1000 Style to close tab using double click.
+ ``FNB_SMART_TABS`` 0x2000 Use `Smart Tabbing`, like ``Alt`` + ``Tab`` on Windows.
+ ``FNB_DROPDOWN_TABS_LIST`` 0x4000 Use a dropdown menu on the left in place of the arrows.
+ ``FNB_ALLOW_FOREIGN_DND`` 0x8000 Allows drag 'n' drop operations between different :class:`FlatNotebook`.
+ ``FNB_HIDE_ON_SINGLE_TAB`` 0x10000 Hides the Page Container when there is one or fewer tabs.
+ ``FNB_DEFAULT_STYLE`` 0x10020 :class:`FlatNotebook` default style.
+ ``FNB_FF2`` 0x20000 Use Firefox 2 style for tabs.
+ ``FNB_NO_TAB_FOCUS`` 0x40000 Does not allow tabs to have focus.
+ ``FNB_RIBBON_TABS`` 0x80000 Use the Ribbon Tabs style.
+ ``FNB_HIDE_TABS`` 0x100000 Hides the Page Container allowing only keyboard navigation
+ ``FNB_NAV_BUTTONS_WHEN_NEEDED`` 0x200000 Hides the navigation left/right arrows if all tabs fit
+ ================================ =========== ==================================================
+
+ :param `name`: the window name.
+ """
+
+ FlatNotebook.__init__(self, parent, id, pos, size, style, agwStyle, name)
+
+
+ def SetSelection(self, page):
+ """
+ Sets the selection for the given page.
+
+ :param `page`: an integer specifying the new selected page.
+
+ :note: The call to this function **generates** the page changing events.
+ """
+
+ if page >= len(self._windows) or not self._windows:
+ return
+
+ # Support for disabed tabs
+ if not self._pages.GetEnabled(page) and len(self._windows) > 1 and not self._bForceSelection:
+ return
+
+ self._pages.FireEvent(page)
+
+
+ def ChangeSelection(self, page):
+ """
+ Sets the selection for the given page.
+
+ :param `page`: an integer specifying the new selected page.
+
+ :note: The call to this function **does not** generate the page changing events.
+ """
+
+ FlatNotebook.SetSelection(self, page)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/floatspin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/floatspin.py
new file mode 100644
index 0000000..5111d83
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/floatspin.py
@@ -0,0 +1,1712 @@
+# --------------------------------------------------------------------------- #
+# FLOATSPIN Control wxPython IMPLEMENTATION
+# Python Code By:
+#
+# Andrea Gavana, @ 16 Nov 2005
+# Latest Revision: 03 Jan 2014, 23.00 GMT
+#
+#
+# TODO List/Caveats
+#
+# 1. Ay Idea?
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+
+"""
+:class:`FloatSpin` implements a floating point :class:`SpinCtrl`.
+
+
+Description
+===========
+
+:class:`FloatSpin` implements a floating point :class:`SpinCtrl`. It is built using a custom
+:class:`PyControl`, composed by a :class:`TextCtrl` and a :class:`SpinButton`. In order to
+correctly handle floating points numbers without rounding errors or non-exact
+floating point representations, :class:`FloatSpin` uses the great :class:`FixedPoint` class
+from Tim Peters.
+
+What you can do:
+
+- Set the number of representative digits for your floating point numbers;
+- Set the floating point format (``%f``, ``%F``, ``%e``, ``%E``, ``%g``, ``%G``);
+- Set the increment of every ``EVT_FLOATSPIN`` event;
+- Set minimum, maximum values for :class:`FloatSpin` as well as its range;
+- Change font and colour for the underline :class:`TextCtrl`.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.floatspin as FS
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "FloatSpin Demo")
+
+ panel = wx.Panel(self)
+
+ floatspin = FS.FloatSpin(panel, -1, pos=(50, 50), min_val=0, max_val=1,
+ increment=0.01, value=0.1, agwStyle=FS.FS_LEFT)
+ floatspin.SetFormat("%f")
+ floatspin.SetDigits(2)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Events
+======
+
+:class:`FloatSpin` catches 3 different types of events:
+
+1) Spin events: events generated by spinning up/down the spinbutton;
+2) Char events: playing with up/down arrows of the keyboard increase/decrease
+ the value of :class:`FloatSpin`;
+3) Mouse wheel event: using the wheel will change the value of :class:`FloatSpin`.
+
+In addition, there are some other functionalities:
+
+- It remembers the initial value as a default value, call meth:~FloatSpin.SetToDefaultValue`, or
+ press ``Esc`` to return to it;
+- ``Shift`` + arrow = 2 * increment (or ``Shift`` + mouse wheel);
+- ``Ctrl`` + arrow = 10 * increment (or ``Ctrl`` + mouse wheel);
+- ``Alt`` + arrow = 100 * increment (or ``Alt`` + mouse wheel);
+- Combinations of ``Shift``, ``Ctrl``, ``Alt`` increment the :class:`FloatSpin` value by the
+ product of the factors;
+- ``PgUp`` & ``PgDn`` = 10 * increment * the product of the ``Shift``, ``Ctrl``, ``Alt``
+ factors;
+- ``Space`` sets the control's value to it's last valid state.
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+=============== =========== ==================================================
+Window Styles Hex Value Description
+=============== =========== ==================================================
+``FS_READONLY`` 0x1 Sets :class:`FloatSpin` as read-only control.
+``FS_LEFT`` 0x2 Horizontally align the underlying :class:`TextCtrl` on the left.
+``FS_CENTRE`` 0x4 Horizontally align the underlying :class:`TextCtrl` on center.
+``FS_RIGHT`` 0x8 Horizontally align the underlying :class:`TextCtrl` on the right.
+=============== =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================= ==================================================
+Event Name Description
+================= ==================================================
+``EVT_FLOATSPIN`` Emitted when the user changes the value of :class:`FloatSpin`, either with the mouse or with the keyboard.
+================= ==================================================
+
+
+License And Version
+===================
+
+:class:`FloatSpin` control is distributed under the wxPython license.
+
+Latest revision: Andrea Gavana @ 03 Jan 2014, 23.00 GMT
+
+Version 0.9
+
+
+Backward Incompatibilities
+==========================
+
+Modifications to allow `min_val` or `max_val` to be ``None`` done by:
+
+James Bigler,
+SCI Institute, University of Utah,
+March 14, 2007
+
+:note: Note that the changes I made will break backward compatibility,
+ because I changed the contructor's parameters from `min` / `max` to
+ `min_val` / `max_val` to be consistent with the other functions and to
+ eliminate any potential confusion with the built in `min` and `max`
+ functions.
+
+You specify open ranges like this (you can equally do this in the
+constructor)::
+
+ SetRange(min_val=1, max_val=None) # [1, ]
+ SetRange(min_val=None, max_val=0) # [ , 0]
+
+or no range::
+
+ SetRange(min_val=None, max_val=None) # [ , ]
+
+"""
+
+
+#----------------------------------------------------------------------
+# Beginning Of FLOATSPIN wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+import locale
+from math import ceil, floor
+
+# Set The Styles For The Underline wx.TextCtrl
+FS_READONLY = 1
+""" Sets :class:`FloatSpin` as read-only control. """
+FS_LEFT = 2
+""" Horizontally align the underlying :class:`TextCtrl` on the left. """
+FS_CENTRE = 4
+""" Horizontally align the underlying :class:`TextCtrl` on center. """
+FS_RIGHT = 8
+""" Horizontally align the underlying :class:`TextCtrl` on the right. """
+
+# Define The FloatSpin Event
+wxEVT_FLOATSPIN = wx.NewEventType()
+
+#-----------------------------------#
+# FloatSpinEvent
+#-----------------------------------#
+
+EVT_FLOATSPIN = wx.PyEventBinder(wxEVT_FLOATSPIN, 1)
+""" Emitted when the user changes the value of :class:`FloatSpin`, either with the mouse or""" \
+""" with the keyboard. """
+
+# ---------------------------------------------------------------------------- #
+# Class FloatSpinEvent
+# ---------------------------------------------------------------------------- #
+
+class FloatSpinEvent(wx.PyCommandEvent):
+ """ This event will be sent when a ``EVT_FLOATSPIN`` event is mapped in the parent. """
+
+ def __init__(self, eventType, eventId=1, nSel=-1, nOldSel=-1):
+ """
+ Default class constructor.
+
+ :param `eventType`: the event type;
+ :param `eventId`: the event identifier;
+ :param `nSel`: the current selection;
+ :param `nOldSel`: the old selection.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+ self._eventType = eventType
+
+
+ def SetPosition(self, pos):
+ """
+ Sets event position.
+
+ :param `pos`: an integer specyfing the event position.
+ """
+
+ self._position = pos
+
+
+ def GetPosition(self):
+ """ Returns event position. """
+
+ return self._position
+
+
+#----------------------------------------------------------------------------
+# FloatTextCtrl
+#----------------------------------------------------------------------------
+
+
+class FloatTextCtrl(wx.TextCtrl):
+ """
+ A class which holds a :class:`TextCtrl`, one of the two building blocks
+ of :class:`FloatSpin`.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, value="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.TE_NOHIDESEL | wx.TE_PROCESS_ENTER,
+ validator=wx.DefaultValidator,
+ name=wx.TextCtrlNameStr):
+ """
+ Default class constructor.
+ Used internally. Do not call directly this class in your code!
+
+ :param `parent`: the :class:`FloatTextCtrl` parent;
+ :param `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param `value`: default text value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `validator`: the window validator;
+ :param `name`: the window name.
+
+ """
+
+ wx.TextCtrl.__init__(self, parent, id, value, pos, size, style, validator, name)
+
+ self._parent = parent
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+
+ def OnDestroy(self, event):
+ """
+ Handles the ``wx.EVT_WINDOW_DESTROY`` event for :class:`FloatTextCtrl`.
+
+ :param `event`: a :class:`WindowDestroyEvent` event to be processed.
+
+ :note: This method tries to correctly handle the control destruction under MSW.
+ """
+
+ if self._parent:
+ self._parent._textctrl = None
+ self._parent = None
+
+
+ def OnChar(self, event):
+ """
+ Handles the ``wx.EVT_CHAR`` event for :class:`FloatTextCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if self._parent:
+ self._parent.OnChar(event)
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`FloatTextCtrl`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+
+ :note: This method synchronizes the :class:`SpinButton` and the :class:`TextCtrl`
+ when focus is lost.
+ """
+
+ if self._parent:
+ self._parent.SyncSpinToText(True)
+
+ event.Skip()
+
+
+#---------------------------------------------------------------------------- #
+# FloatSpin
+# This Is The Main Class Implementation
+# ---------------------------------------------------------------------------- #
+
+class FloatSpin(wx.PyControl):
+ """
+ :class:`FloatSpin` implements a floating point :class:`SpinCtrl`. It is built using a custom
+ :class:`PyControl`, composed by a :class:`TextCtrl` and a :class:`SpinButton`. In order to
+ correctly handle floating points numbers without rounding errors or non-exact
+ floating point representations, :class:`FloatSpin` uses the great :class:`FixedPoint` class
+ from Tim Peters.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=(95,-1), style=0, value=0.0, min_val=None, max_val=None,
+ increment=1.0, digits=-1, agwStyle=FS_LEFT,
+ name="FloatSpin"):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`FloatSpin` parent;
+ :param `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `value`: is the current value for :class:`FloatSpin`;
+ :param `min_val`: the minimum value, ignored if ``None``;
+ :param `max_val`: the maximum value, ignored if ``None``;
+ :param `increment`: the increment for every :class:`FloatSpinEvent` event;
+ :param `digits`: number of representative digits for your floating point numbers;
+ :param `agwStyle`: one of the following bits:
+
+ =============== =========== ==================================================
+ Window Styles Hex Value Description
+ =============== =========== ==================================================
+ ``FS_READONLY`` 0x1 Sets :class:`FloatSpin` as read-only control.
+ ``FS_LEFT`` 0x2 Horizontally align the underlying :class:`TextCtrl` on the left.
+ ``FS_CENTRE`` 0x4 Horizontally align the underlying :class:`TextCtrl` on center.
+ ``FS_RIGHT`` 0x8 Horizontally align the underlying :class:`TextCtrl` on the right.
+ =============== =========== ==================================================
+
+ :param `name`: the window name.
+
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style|wx.NO_BORDER|
+ wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_CHILDREN,
+ wx.DefaultValidator, name)
+
+ # Don't call SetRange here, because it will try to modify
+ # self._value whose value doesn't exist yet.
+ self.SetRangeDontClampValue(min_val, max_val)
+ self._value = self.ClampValue(FixedPoint(str(value), 20))
+ self._defaultvalue = self._value
+ self._increment = FixedPoint(str(increment), 20)
+ self._spinmodifier = FixedPoint(str(1.0), 20)
+ self._digits = digits
+ self._snapticks = False
+ self._spinbutton = None
+ self._textctrl = None
+ self._spinctrl_bestsize = wx.Size(-999, -999)
+
+ # start Philip Semanchuk addition
+ # The textbox & spin button are drawn slightly differently
+ # depending on the platform. The difference is most pronounced
+ # under OS X.
+ if "__WXMAC__" in wx.PlatformInfo:
+ self._gap = 8
+ self._spin_top = 3
+ self._text_left = 4
+ self._text_top = 4
+ elif "__WXMSW__" in wx.PlatformInfo:
+ self._gap = 1
+ self._spin_top = 0
+ self._text_left = 0
+ self._text_top = 0
+ else:
+ # GTK
+ self._gap = -1
+ self._spin_top = 0
+ self._text_left = 0
+ self._text_top = 0
+ # end Philip Semanchuk addition
+
+ self.SetLabel(name)
+ self.SetForegroundColour(parent.GetForegroundColour())
+
+ width = size[0]
+ height = size[1]
+ best_size = self.DoGetBestSize()
+
+ if width == -1:
+ width = best_size.GetWidth()
+ if height == -1:
+ height = best_size.GetHeight()
+
+ self._validkeycode = [43, 44, 45, 46, 69, 101, 127, 314]
+ self._validkeycode.extend(range(48, 58))
+ self._validkeycode.extend([wx.WXK_RETURN, wx.WXK_TAB, wx.WXK_BACK,
+ wx.WXK_LEFT, wx.WXK_RIGHT])
+
+ self._spinbutton = wx.SpinButton(self, wx.ID_ANY, wx.DefaultPosition,
+ size=(-1, height),
+ style=wx.SP_ARROW_KEYS | wx.SP_VERTICAL |
+ wx.SP_WRAP)
+
+ txtstyle = wx.TE_NOHIDESEL | wx.TE_PROCESS_ENTER
+
+ if agwStyle & FS_RIGHT:
+ txtstyle = txtstyle | wx.TE_RIGHT
+ elif agwStyle & FS_CENTRE:
+ txtstyle = txtstyle | wx.TE_CENTER
+
+ if agwStyle & FS_READONLY:
+ txtstyle = txtstyle | wx.TE_READONLY
+
+ self._textctrl = FloatTextCtrl(self, wx.ID_ANY, str(self._value),
+ wx.DefaultPosition,
+ (width-self._spinbutton.GetSize().GetWidth(), height),
+ txtstyle)
+
+ # start Philip Semanchuk addition
+ # Setting the textctrl's size in the ctor also sets its min size.
+ # But the textctrl is entirely controlled by the parent floatspin
+ # control and should accept whatever size its parent dictates, so
+ # here we tell it to forget its min size.
+ self._textctrl.SetMinSize(wx.DefaultSize)
+ # Setting the spin buttons's size in the ctor also sets its min size.
+ # Under OS X that results in a rendering artifact because spin buttons
+ # are a little shorter than textboxes.
+ # Setting the min size to the default allows OS X to draw the spin
+ # button correctly. However, Windows and KDE take the call to
+ # SetMinSize() as a cue to size the spin button taller than the
+ # textbox, so we avoid the call there.
+ if "__WXMAC__" in wx.PlatformInfo:
+ self._spinbutton.SetMinSize(wx.DefaultSize)
+ # end Philip Semanchuk addition
+
+ self._mainsizer = wx.BoxSizer(wx.HORIZONTAL)
+ # Ensure the spin button is shown, and the text widget takes
+ # all remaining free space
+ self._mainsizer.Add(self._textctrl, 1)
+ self._mainsizer.Add(self._spinbutton, 0)
+ self.SetSizer(self._mainsizer)
+ self._mainsizer.Layout()
+
+ self.SetFormat()
+ self.SetDigits(digits)
+
+ # set the value here without generating an event
+
+ decimal = locale.localeconv()["decimal_point"]
+ strs = ("%100." + str(self._digits) + self._textformat[1])%self._value
+ strs = strs.replace(".", decimal)
+
+ strs = strs.strip()
+ strs = self.ReplaceDoubleZero(strs)
+
+ self._textctrl.SetValue(strs)
+
+ if not (agwStyle & FS_READONLY):
+ self.Bind(wx.EVT_SPIN_UP, self.OnSpinUp)
+ self.Bind(wx.EVT_SPIN_DOWN, self.OnSpinDown)
+ self._spinbutton.Bind(wx.EVT_LEFT_DOWN, self.OnSpinMouseDown)
+
+ self._textctrl.Bind(wx.EVT_TEXT_ENTER, self.OnTextEnter)
+ self._textctrl.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
+ self._spinbutton.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
+
+ self.Bind(wx.EVT_SET_FOCUS, self.OnFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ # start Philip Semanchuk move
+ self.SetBestSize((width, height))
+ # end Philip Semanchuk move
+
+
+ def OnDestroy(self, event):
+ """
+ Handles the ``wx.EVT_WINDOW_DESTROY`` event for :class:`FloatSpin`.
+
+ :param `event`: a :class:`WindowDestroyEvent` event to be processed.
+
+ :note: This method tries to correctly handle the control destruction under MSW.
+ """
+
+ # Null This Since MSW Sends KILL_FOCUS On Deletion
+ if self._textctrl:
+ self._textctrl._parent = None
+ self._textctrl.Destroy()
+ self._textctrl = None
+
+ self._spinbutton.Destroy()
+ self._spinbutton = None
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same
+ size as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ if self._spinctrl_bestsize.x == -999:
+
+ spin = wx.SpinCtrl(self, -1)
+ self._spinctrl_bestsize = spin.GetBestSize()
+
+ # oops something went wrong, set to reasonable value
+ if self._spinctrl_bestsize.GetWidth() < 20:
+ self._spinctrl_bestsize.SetWidth(95)
+ if self._spinctrl_bestsize.GetHeight() < 10:
+ self._spinctrl_bestsize.SetHeight(22)
+
+ spin.Destroy()
+
+ return self._spinctrl_bestsize
+
+
+ def DoSendEvent(self):
+ """ Send the event to the parent. """
+
+ event = wx.CommandEvent(wx.wxEVT_COMMAND_SPINCTRL_UPDATED, self.GetId())
+ event.SetEventObject(self)
+ event.SetInt(int(self._value + 0.5))
+
+ if self._textctrl:
+ event.SetString(self._textctrl.GetValue())
+
+ self.GetEventHandler().ProcessEvent(event)
+
+ eventOut = FloatSpinEvent(wxEVT_FLOATSPIN, self.GetId())
+ eventOut.SetPosition(int(self._value + 0.5))
+ eventOut.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+
+ def OnSpinMouseDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`FloatSpin`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+
+ :note: This method works on the underlying :class:`SpinButton`.
+ """
+
+ modifier = FixedPoint(str(1.0), 20)
+ if event.ShiftDown():
+ modifier = modifier*2.0
+ if event.ControlDown():
+ modifier = modifier*10.0
+ if event.AltDown():
+ modifier = modifier*100.0
+
+ self._spinmodifier = modifier
+
+ event.Skip()
+
+
+ def OnSpinUp(self, event):
+ """
+ Handles the ``wx.EVT_SPIN_UP`` event for :class:`FloatSpin`.
+
+ :param `event`: a :class:`SpinEvent` event to be processed.
+ """
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ if self.InRange(self._value + self._increment*self._spinmodifier):
+
+ self._value = self._value + self._increment*self._spinmodifier
+ self.SetValue(self._value)
+ self.DoSendEvent()
+
+
+ def OnSpinDown(self, event):
+ """
+ Handles the ``wx.EVT_SPIN_DOWN`` event for :class:`FloatSpin`.
+
+ :param `event`: a :class:`SpinEvent` event to be processed.
+ """
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ if self.InRange(self._value - self._increment*self._spinmodifier):
+
+ self._value = self._value - self._increment*self._spinmodifier
+ self.SetValue(self._value)
+ self.DoSendEvent()
+
+
+ def OnTextEnter(self, event):
+ """
+ Handles the ``wx.EVT_TEXT_ENTER`` event for :class:`FloatSpin`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+
+ :note: This method works on the underlying :class:`TextCtrl`.
+ """
+
+ self.SyncSpinToText(True)
+ event.Skip()
+
+
+ def OnChar(self, event):
+ """
+ Handles the ``wx.EVT_CHAR`` event for :class:`FloatSpin`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+
+ :note: This method works on the underlying :class:`TextCtrl`.
+ """
+
+ modifier = FixedPoint(str(1.0), 20)
+ if event.ShiftDown():
+ modifier = modifier*2.0
+ if event.ControlDown():
+ modifier = modifier*10.0
+ if event.AltDown():
+ modifier = modifier*100.0
+
+ keycode = event.GetKeyCode()
+
+ if keycode == wx.WXK_UP:
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ self.SetValue(self._value + self._increment*modifier)
+ self.DoSendEvent()
+
+ elif keycode == wx.WXK_DOWN:
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ self.SetValue(self._value - self._increment*modifier)
+ self.DoSendEvent()
+
+ elif keycode == wx.WXK_PRIOR:
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ self.SetValue(self._value + 10.0*self._increment*modifier)
+ self.DoSendEvent()
+
+ elif keycode == wx.WXK_NEXT:
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ self.SetValue(self._value - 10.0*self._increment*modifier)
+ self.DoSendEvent()
+
+ elif keycode == wx.WXK_SPACE:
+
+ self.SetValue(self._value)
+ event.Skip(False)
+
+ elif keycode == wx.WXK_ESCAPE:
+
+ self.SetToDefaultValue()
+ self.DoSendEvent()
+
+ elif keycode == wx.WXK_TAB:
+
+ new_event = wx.NavigationKeyEvent()
+ new_event.SetEventObject(self.GetParent())
+ new_event.SetDirection(not event.ShiftDown())
+ # CTRL-TAB changes the (parent) window, i.e. switch notebook page
+ new_event.SetWindowChange(event.ControlDown())
+ new_event.SetCurrentFocus(self)
+ self.GetParent().GetEventHandler().ProcessEvent(new_event)
+
+ else:
+ if keycode not in self._validkeycode:
+ return
+
+ event.Skip()
+
+
+ def OnMouseWheel(self, event):
+ """
+ Handles the ``wx.EVT_MOUSEWHEEL`` event for :class:`FloatSpin`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ modifier = FixedPoint(str(1.0), 20)
+ if event.ShiftDown():
+ modifier = modifier*2.0
+ if event.ControlDown():
+ modifier = modifier*10.0
+ if event.AltDown():
+ modifier = modifier*100.0
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ if event.GetWheelRotation() > 0:
+ self.SetValue(self._value + self._increment*modifier)
+ self.DoSendEvent()
+
+ else:
+
+ self.SetValue(self._value - self._increment*modifier)
+ self.DoSendEvent()
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`FloatSpin`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+
+ :note: This method resizes the text control and reposition the spin button when
+ resized.
+ """
+ # start Philip Semanchuk addition
+ event_width = event.GetSize().width
+
+ self._textctrl.SetPosition((self._text_left, self._text_top))
+
+ text_width, text_height = self._textctrl.GetSizeTuple()
+
+ spin_width, _ = self._spinbutton.GetSizeTuple()
+
+ text_width = event_width - (spin_width + self._gap + self._text_left)
+
+ self._textctrl.SetSize(wx.Size(text_width, event.GetSize().height))
+
+ # The spin button is always snug against the right edge of the
+ # control.
+ self._spinbutton.SetPosition((event_width - spin_width, self._spin_top))
+
+ event.Skip()
+ # end Philip Semanchuk addition
+
+
+ def ReplaceDoubleZero(self, strs):
+ """
+ Replaces the (somewhat) python ugly `+e000` with `+e00`.
+
+ :param `strs`: a string (possibly) containing a `+e00` substring.
+ """
+
+ if self._textformat not in ["%g", "%e", "%E", "%G"]:
+ return strs
+
+ if strs.find("e+00") >= 0:
+ strs = strs.replace("e+00", "e+0")
+ elif strs.find("e-00") >= 0:
+ strs = strs.replace("e-00", "e-0")
+ elif strs.find("E+00") >= 0:
+ strs = strs.replace("E+00", "E+0")
+ elif strs.find("E-00") >= 0:
+ strs = strs.replace("E-00", "E-0")
+
+ return strs
+
+
+ def SetValue(self, value):
+ """
+ Sets the :class:`FloatSpin` value.
+
+ :param `value`: the new value.
+ """
+ if not self._textctrl or not self.InRange(value):
+ return
+
+ if self._snapticks and self._increment != 0.0:
+
+ finite, snap_value = self.IsFinite(value)
+
+ if not finite: # FIXME What To Do About A Failure?
+
+ if (snap_value - floor(snap_value) < ceil(snap_value) - snap_value):
+ value = self._defaultvalue + floor(snap_value)*self._increment
+ else:
+ value = self._defaultvalue + ceil(snap_value)*self._increment
+
+ decimal = locale.localeconv()["decimal_point"]
+ strs = ("%100." + str(self._digits) + self._textformat[1])%value
+ strs = strs.replace(".", decimal)
+ strs = strs.strip()
+ strs = self.ReplaceDoubleZero(strs)
+
+ if value != self._value or strs != self._textctrl.GetValue():
+
+ self._textctrl.SetValue(strs)
+ self._textctrl.DiscardEdits()
+ self._value = value
+
+
+ def GetValue(self):
+ """ Returns the :class:`FloatSpin` value. """
+
+ return float(self._value)
+
+
+ def SetRangeDontClampValue(self, min_val, max_val):
+ """
+ Sets the allowed range.
+
+ :param `min_val`: the minimum value for :class:`FloatSpin`. If it is ``None`` it is
+ ignored;
+ :param `max_val`: the maximum value for :class:`FloatSpin`. If it is ``None`` it is
+ ignored.
+
+ :note: This method doesn't modify the current value.
+ """
+
+ if (min_val != None):
+ self._min = FixedPoint(str(min_val), 20)
+ else:
+ self._min = None
+ if (max_val != None):
+ self._max = FixedPoint(str(max_val), 20)
+ else:
+ self._max = None
+
+
+ def SetRange(self, min_val, max_val):
+ """
+ Sets the allowed range.
+
+ :param `min_val`: the minimum value for :class:`FloatSpin`. If it is ``None`` it is
+ ignored;
+ :param `max_val`: the maximum value for :class:`FloatSpin`. If it is ``None`` it is
+ ignored.
+
+ :note: This method doesn't modify the current value.
+
+ :note: You specify open ranges like this (you can equally do this in the
+ constructor)::
+
+ SetRange(min_val=1, max_val=None)
+ SetRange(min_val=None, max_val=0)
+
+
+ or no range::
+
+ SetRange(min_val=None, max_val=None)
+
+ """
+
+ self.SetRangeDontClampValue(min_val, max_val)
+
+ value = self.ClampValue(self._value)
+ if (value != self._value):
+ self.SetValue(value)
+
+
+ def ClampValue(self, var):
+ """
+ Clamps `var` between `_min` and `_max` depending if the range has
+ been specified.
+
+ :param `var`: the value to be clamped.
+
+ :return: A clamped copy of `var`.
+ """
+
+ if (self._min != None):
+ if (var < self._min):
+ var = self._min
+ return var
+
+ if (self._max != None):
+ if (var > self._max):
+ var = self._max
+
+ return var
+
+
+ def SetIncrement(self, increment):
+ """
+ Sets the increment for every ``EVT_FLOATSPIN`` event.
+
+ :param `increment`: a floating point number specifying the :class:`FloatSpin` increment.
+ """
+
+ if increment < 1./10.0**self._digits:
+ raise Exception("\nERROR: Increment Should Be Greater Or Equal To 1/(10**digits).")
+
+ self._increment = FixedPoint(str(increment), 20)
+ self.SetValue(self._value)
+
+
+ def GetIncrement(self):
+ """ Returns the increment for every ``EVT_FLOATSPIN`` event. """
+
+ return self._increment
+
+
+ def SetDigits(self, digits=-1):
+ """
+ Sets the number of digits to show.
+
+ :param `digits`: the number of digits to show. If `digits` < 0, :class:`FloatSpin`
+ tries to calculate the best number of digits based on input values passed
+ in the constructor.
+ """
+
+ if digits < 0:
+ incr = str(self._increment)
+ if incr.find(".") < 0:
+ digits = 0
+ else:
+ digits = len(incr[incr.find(".")+1:])
+
+ self._digits = digits
+
+ self.SetValue(self._value)
+
+
+ def GetDigits(self):
+ """ Returns the number of digits shown. """
+
+ return self._digits
+
+
+ def SetFormat(self, fmt="%f"):
+ """
+ Set the string format to use.
+
+ :param `fmt`: the new string format to use. One of the following strings:
+
+ ====== =================================
+ Format Description
+ ====== =================================
+ 'e' Floating point exponential format (lowercase)
+ 'E' Floating point exponential format (uppercase)
+ 'f' Floating point decimal format
+ 'F' Floating point decimal format
+ 'g' Floating point format. Uses lowercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise
+ 'G' Floating point format. Uses uppercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise
+ ====== =================================
+
+ """
+
+ if fmt not in ["%f", "%g", "%e", "%E", "%F", "%G"]:
+ raise Exception('\nERROR: Bad Float Number Format: ' + repr(fmt) + '. It Should Be ' \
+ 'One Of "%f", "%g", "%e", "%E", "%F", "%G"')
+
+ self._textformat = fmt
+
+ if self._digits < 0:
+ self.SetDigits()
+
+ self.SetValue(self._value)
+
+
+ def GetFormat(self):
+ """
+ Returns the string format in use.
+
+ :see: :meth:`~FloatSpin.SetFormat` for a list of valid string formats.
+ """
+
+ return self._textformat
+
+
+ def SetDefaultValue(self, defaultvalue):
+ """
+ Sets the :class:`FloatSpin` default value.
+
+ :param `defaultvalue`: a floating point value representing the new default
+ value for :class:`FloatSpin`.
+ """
+
+ if self.InRange(defaultvalue):
+ self._defaultvalue = FixedPoint(str(defaultvalue), 20)
+
+
+ def GetDefaultValue(self):
+ """ Returns the :class:`FloatSpin` default value. """
+
+ return self._defaultvalue
+
+
+ def IsDefaultValue(self):
+ """ Returns whether the current value is the default value or not. """
+
+ return self._value == self._defaultvalue
+
+
+ def SetToDefaultValue(self):
+ """ Sets :class:`FloatSpin` value to its default value. """
+
+ self.SetValue(self._defaultvalue)
+
+
+ def SetSnapToTicks(self, forceticks=True):
+ """
+ Force the value to always be divisible by the increment. Initially ``False``.
+
+ :param `forceticks`: ``True`` to force the snap to ticks option, ``False`` otherwise.
+
+ :note: This uses the default value as the basis, you will get strange results
+ for very large differences between the current value and default value
+ when the increment is very small.
+ """
+
+ if self._snapticks != forceticks:
+
+ self._snapticks = forceticks
+ self.SetValue(self._value)
+
+
+ def GetSnapToTicks(self):
+ """ Returns whether the snap to ticks option is active or not. """
+
+ return self._snapticks
+
+
+ def OnFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`FloatSpin`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if self._textctrl:
+ self._textctrl.SetFocus()
+
+ event.Skip()
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`FloatSpin`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self.SyncSpinToText(True)
+ event.Skip()
+
+
+ def SyncSpinToText(self, send_event=True, force_valid=True):
+ """
+ Synchronize the underlying :class:`TextCtrl` with :class:`SpinButton`.
+
+ :param `send_event`: ``True`` to send a ``EVT_FLOATSPIN`` event, ``False``
+ otherwise;
+ :param `force_valid`: ``True`` to force a valid value (i.e. inside the
+ provided range), ``False`` otherwise.
+ """
+
+ if not self._textctrl:
+ return
+
+ curr = self._textctrl.GetValue()
+ curr = curr.strip()
+ decimal = locale.localeconv()["decimal_point"]
+ curr = curr.replace(decimal, ".")
+
+ if curr:
+ try:
+ curro = float(curr)
+ curr = FixedPoint(curr, 20)
+ except:
+ self.SetValue(self._value)
+ return
+
+ if force_valid or not self.HasRange() or self.InRange(curr):
+
+ if force_valid and self.HasRange():
+
+ curr = self.ClampValue(curr)
+
+ if self._value != curr:
+ self.SetValue(curr)
+
+ if send_event:
+ self.DoSendEvent()
+
+ elif force_valid:
+
+ # textctrl is out of sync, discard and reset
+ self.SetValue(self.GetValue())
+
+
+ def SetFont(self, font=None):
+ """
+ Sets the underlying :class:`TextCtrl` font.
+
+ :param `font`: a valid instance of :class:`Font`.
+ """
+
+ if font is None:
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+ if not self._textctrl:
+ return False
+
+ return self._textctrl.SetFont(font)
+
+
+ def GetFont(self):
+ """ Returns the underlying :class:`TextCtrl` font. """
+
+ if not self._textctrl:
+ return self.GetFont()
+
+ return self._textctrl.GetFont()
+
+
+ def GetMin(self):
+ """
+ Returns the minimum value for :class:`FloatSpin`. It can be a
+ number or ``None`` if no minimum is present.
+ """
+
+ return self._min
+
+
+ def GetMax(self):
+ """
+ Returns the maximum value for :class:`FloatSpin`. It can be a
+ number or ``None`` if no minimum is present.
+ """
+
+ return self._max
+
+
+ def HasRange(self):
+ """ Returns whether :class:`FloatSpin` range has been set or not. """
+
+ return (self._min != None) or (self._max != None)
+
+
+ def InRange(self, value):
+ """
+ Returns whether a value is inside :class:`FloatSpin` range.
+
+ :param `value`: the value to test.
+ """
+
+ if (not self.HasRange()):
+ return True
+ if (self._min != None):
+ if (value < self._min):
+ return False
+ if (self._max != None):
+ if (value > self._max):
+ return False
+ return True
+
+
+ def GetTextCtrl(self):
+ """ Returns the underlying :class:`TextCtrl`. """
+
+ return self._textctrl
+
+
+ def IsFinite(self, value):
+ """
+ Tries to determine if a value is finite or infinite/NaN.
+
+ :param `value`: the value to test.
+ """
+
+ try:
+ snap_value = (value - self._defaultvalue)/self._increment
+ finite = True
+ except:
+ finite = False
+ snap_value = None
+
+ return finite, snap_value
+
+
+
+# Class FixedPoint, version 0.0.4.
+# Released to the public domain 28-Mar-2001,
+# by Tim Peters (tim.one@home.com).
+
+# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
+
+
+# 28-Mar-01 ver 0.0,4
+# Use repr() instead of str() inside __str__, because str(long) changed
+# since this was first written (used to produce trailing "L", doesn't
+# now).
+#
+# 09-May-99 ver 0,0,3
+# Repaired __sub__(FixedPoint, string); was blowing up.
+# Much more careful conversion of float (now best possible).
+# Implemented exact % and divmod.
+#
+# 14-Oct-98 ver 0,0,2
+# Added int, long, frac. Beefed up docs. Removed DECIMAL_POINT
+# and MINUS_SIGN globals to discourage bloating this class instead
+# of writing formatting wrapper classes (or subclasses)
+#
+# 11-Oct-98 ver 0,0,1
+# posted to c.l.py
+
+__version__ = 0, 0, 4
+
+# The default value for the number of decimal digits carried after the
+# decimal point. This only has effect at compile-time.
+DEFAULT_PRECISION = 2
+""" The default value for the number of decimal digits carried after the decimal point. This only has effect at compile-time. """
+
+class FixedPoint(object):
+ """
+ FixedPoint objects support decimal arithmetic with a fixed number of
+ digits (called the object's precision) after the decimal point. The
+ number of digits before the decimal point is variable & unbounded.
+
+ The precision is user-settable on a per-object basis when a FixedPoint
+ is constructed, and may vary across FixedPoint objects. The precision
+ may also be changed after construction via `FixedPoint.set_precision(p)`.
+ Note that if the precision of a FixedPoint is reduced via :meth:`FixedPoint.set_precision() <FixedPoint.set_precision>`,
+ information may be lost to rounding.
+
+ Example::
+
+ >>> x = FixedPoint("5.55") # precision defaults to 2
+ >>> print x
+ 5.55
+ >>> x.set_precision(1) # round to one fraction digit
+ >>> print x
+ 5.6
+ >>> print FixedPoint("5.55", 1) # same thing setting to 1 in constructor
+ 5.6
+ >>> repr(x) # returns constructor string that reproduces object exactly
+ "FixedPoint('5.6', 1)"
+ >>>
+
+
+ When :class:`FixedPoint` objects of different precision are combined via + - * /,
+ the result is computed to the larger of the inputs' precisions, which also
+ becomes the precision of the resulting :class:`FixedPoint` object. Example::
+
+ >>> print FixedPoint("3.42") + FixedPoint("100.005", 3)
+ 103.425
+ >>>
+
+
+ When a :class:`FixedPoint` is combined with other numeric types (ints, floats,
+ strings representing a number) via + - * /, then similarly the computation
+ is carried out using -- and the result inherits -- the :class:`FixedPoint`'s
+ precision. Example::
+
+ >>> print FixedPoint(1) / 7
+ 0.14
+ >>> print FixedPoint(1, 30) / 7
+ 0.142857142857142857142857142857
+ >>>
+
+
+ The string produced by `str(x)` (implictly invoked by `print`) always
+ contains at least one digit before the decimal point, followed by a
+ decimal point, followed by exactly `x.get_precision()` digits. If `x` is
+ negative, `str(x)[0] == "-"`.
+
+ The :class:`FixedPoint` constructor can be passed an int, long, string, float,
+ :class:`FixedPoint`, or any object convertible to a float via `float()` or to a
+ long via `long()`. Passing a precision is optional; if specified, the
+ precision must be a non-negative int. There is no inherent limit on
+ the size of the precision, but if very very large you'll probably run
+ out of memory.
+
+ Note that conversion of floats to :class:`FixedPoint` can be surprising, and
+ should be avoided whenever possible. Conversion from string is exact
+ (up to final rounding to the requested precision), so is greatly
+ preferred. Example::
+
+ >>> print FixedPoint(1.1e30)
+ 1099999999999999993725589651456.00
+ >>> print FixedPoint("1.1e30")
+ 1100000000000000000000000000000.00
+ >>>
+
+
+ """
+
+ # the exact value is self.n / 10**self.p;
+ # self.n is a long; self.p is an int
+
+ def __init__(self, value=0, precision=DEFAULT_PRECISION):
+ """
+ Default class constructor.
+
+ :param `value`: the initial value;
+ :param `precision`: must be an int >= 0, and defaults to ``DEFAULT_PRECISION``.
+ """
+
+ self.n = self.p = 0
+ self.set_precision(precision)
+ p = self.p
+
+ if isinstance(value, type("42.3e5")):
+ n, exp = _string2exact(value)
+ # exact value is n*10**exp = n*10**(exp+p)/10**p
+ effective_exp = exp + p
+ if effective_exp > 0:
+ n = n * _tento(effective_exp)
+ elif effective_exp < 0:
+ n = _roundquotient(n, _tento(-effective_exp))
+ self.n = n
+ return
+
+ if isinstance(value, type(42)) or isinstance(value, type(42L)):
+ self.n = long(value) * _tento(p)
+ return
+
+ if isinstance(value, FixedPoint):
+ temp = value.copy()
+ temp.set_precision(p)
+ self.n, self.p = temp.n, temp.p
+ return
+
+ if isinstance(value, type(42.0)):
+ # XXX ignoring infinities and NaNs and overflows for now
+ import math
+ f, e = math.frexp(abs(value))
+ assert f == 0 or 0.5 <= f < 1.0
+ # |value| = f * 2**e exactly
+
+ # Suck up CHUNK bits at a time; 28 is enough so that we suck
+ # up all bits in 2 iterations for all known binary double-
+ # precision formats, and small enough to fit in an int.
+ CHUNK = 28
+ top = 0L
+ # invariant: |value| = (top + f) * 2**e exactly
+ while f:
+ f = math.ldexp(f, CHUNK)
+ digit = int(f)
+ assert digit >> CHUNK == 0
+ top = (top << CHUNK) | digit
+ f = f - digit
+ assert 0.0 <= f < 1.0
+ e = e - CHUNK
+
+ # now |value| = top * 2**e exactly
+ # want n such that n / 10**p = top * 2**e, or
+ # n = top * 10**p * 2**e
+ top = top * _tento(p)
+ if e >= 0:
+ n = top << e
+ else:
+ n = _roundquotient(top, 1L << -e)
+ if value < 0:
+ n = -n
+ self.n = n
+ return
+
+ if isinstance(value, type(42-42j)):
+ raise TypeError("can't convert complex to FixedPoint: " +
+ `value`)
+
+ # can we coerce to a float?
+ yes = 1
+ try:
+ asfloat = float(value)
+ except:
+ yes = 0
+ if yes:
+ self.__init__(asfloat, p)
+ return
+
+ # similarly for long
+ yes = 1
+ try:
+ aslong = long(value)
+ except:
+ yes = 0
+ if yes:
+ self.__init__(aslong, p)
+ return
+
+ raise TypeError("can't convert to FixedPoint: " + `value`)
+
+
+ def get_precision(self):
+ """
+ Return the precision of this :class:`FixedPoint`.
+
+ :note: The precision is the number of decimal digits carried after
+ the decimal point, and is an int >= 0.
+ """
+
+ return self.p
+
+
+ def set_precision(self, precision=DEFAULT_PRECISION):
+ """
+ Change the precision carried by this :class:`FixedPoint` to `precision`.
+
+ :param `precision`: must be an int >= 0, and defaults to
+ ``DEFAULT_PRECISION``.
+
+ :note: If `precision` is less than this :class:`FixedPoint`'s current precision,
+ information may be lost to rounding.
+ """
+
+ try:
+ p = int(precision)
+ except:
+ raise TypeError("precision not convertable to int: " +
+ `precision`)
+ if p < 0:
+ raise ValueError("precision must be >= 0: " + `precision`)
+
+ if p > self.p:
+ self.n = self.n * _tento(p - self.p)
+ elif p < self.p:
+ self.n = _roundquotient(self.n, _tento(self.p - p))
+ self.p = p
+
+
+ def __str__(self):
+
+ n, p = self.n, self.p
+ i, f = divmod(abs(n), _tento(p))
+ if p:
+ frac = repr(f)[:-1]
+ frac = "0" * (p - len(frac)) + frac
+ else:
+ frac = ""
+ return "-"[:n<0] + \
+ repr(i)[:-1] + \
+ "." + frac
+
+
+ def __repr__(self):
+
+ return "FixedPoint" + `(str(self), self.p)`
+
+
+ def copy(self):
+ """ Create a copy of the current :class:`FixedPoint`. """
+
+ return _mkFP(self.n, self.p)
+
+ __copy__ = __deepcopy__ = copy
+
+
+ def __cmp__(self, other):
+
+ if (other == None):
+ return 1
+ xn, yn, p = _norm(self, other)
+ return cmp(xn, yn)
+
+
+ def __hash__(self):
+ # caution! == values must have equal hashes, and a FixedPoint
+ # is essentially a rational in unnormalized form. There's
+ # really no choice here but to normalize it, so hash is
+ # potentially expensive.
+ n, p = self.__reduce()
+
+ # Obscurity: if the value is an exact integer, p will be 0 now,
+ # so the hash expression reduces to hash(n). So FixedPoints
+ # that happen to be exact integers hash to the same things as
+ # their int or long equivalents. This is Good. But if a
+ # FixedPoint happens to have a value exactly representable as
+ # a float, their hashes may differ. This is a teensy bit Bad.
+ return hash(n) ^ hash(p)
+
+ def __nonzero__(self):
+ return self.n != 0
+
+ def __neg__(self):
+ return _mkFP(-self.n, self.p)
+
+ def __abs__(self):
+ if self.n >= 0:
+ return self.copy()
+ else:
+ return -self
+
+ def __add__(self, other):
+ n1, n2, p = _norm(self, other)
+ # n1/10**p + n2/10**p = (n1+n2)/10**p
+ return _mkFP(n1 + n2, p)
+
+ __radd__ = __add__
+
+ def __sub__(self, other):
+ if not isinstance(other, FixedPoint):
+ other = FixedPoint(other, self.p)
+ return self.__add__(-other)
+
+ def __rsub__(self, other):
+ return (-self) + other
+
+ def __mul__(self, other):
+ n1, n2, p = _norm(self, other)
+ # n1/10**p * n2/10**p = (n1*n2/10**p)/10**p
+ return _mkFP(_roundquotient(n1 * n2, _tento(p)), p)
+
+ __rmul__ = __mul__
+
+ def __div__(self, other):
+ n1, n2, p = _norm(self, other)
+ if n2 == 0:
+ raise ZeroDivisionError("FixedPoint division")
+ if n2 < 0:
+ n1, n2 = -n1, -n2
+ # n1/10**p / (n2/10**p) = n1/n2 = (n1*10**p/n2)/10**p
+ return _mkFP(_roundquotient(n1 * _tento(p), n2), p)
+
+ def __rdiv__(self, other):
+ n1, n2, p = _norm(self, other)
+ return _mkFP(n2, p) / self
+
+ def __divmod__(self, other):
+ n1, n2, p = _norm(self, other)
+ if n2 == 0:
+ raise ZeroDivisionError("FixedPoint modulo")
+ # floor((n1/10**p)/(n2*10**p)) = floor(n1/n2)
+ q = n1 / n2
+ # n1/10**p - q * n2/10**p = (n1 - q * n2)/10**p
+ return q, _mkFP(n1 - q * n2, p)
+
+ def __rdivmod__(self, other):
+ n1, n2, p = _norm(self, other)
+ return divmod(_mkFP(n2, p), self)
+
+ def __mod__(self, other):
+ return self.__divmod__(other)[1]
+
+ def __rmod__(self, other):
+ n1, n2, p = _norm(self, other)
+ return _mkFP(n2, p).__mod__(self)
+
+ # caution! float can lose precision
+ def __float__(self):
+ n, p = self.__reduce()
+ return float(n) / float(_tento(p))
+
+ # XXX should this round instead?
+ # XXX note e.g. long(-1.9) == -1L and long(1.9) == 1L in Python
+ # XXX note that __int__ inherits whatever __long__ does,
+ # XXX and .frac() is affected too
+ def __long__(self):
+ answer = abs(self.n) / _tento(self.p)
+ if self.n < 0:
+ answer = -answer
+ return answer
+
+ def __int__(self):
+ return int(self.__long__())
+
+ def frac(self):
+ """
+ Returns fractional portion as a :class:`FixedPoint`.
+
+ :note: In :class:`FixedPoint`,
+
+ this equality holds true::
+
+ x = x.frac() + long(x)
+
+
+ """
+ return self - long(self)
+
+ # return n, p s.t. self == n/10**p and n % 10 != 0
+ def __reduce(self):
+ n, p = self.n, self.p
+ if n == 0:
+ p = 0
+ while p and n % 10 == 0:
+ p = p - 1
+ n = n / 10
+ return n, p
+
+# return 10L**n
+
+def _tento(n, cache={}):
+ try:
+ return cache[n]
+ except KeyError:
+ answer = cache[n] = 10L ** n
+ return answer
+
+# return xn, yn, p s.t.
+# p = max(x.p, y.p)
+# x = xn / 10**p
+# y = yn / 10**p
+#
+# x must be FixedPoint to begin with; if y is not FixedPoint,
+# it inherits its precision from x.
+#
+# Note that this is called a lot, so default-arg tricks are helpful.
+
+def _norm(x, y, isinstance=isinstance, FixedPoint=FixedPoint,
+ _tento=_tento):
+ assert isinstance(x, FixedPoint)
+ if not isinstance(y, FixedPoint):
+ y = FixedPoint(y, x.p)
+ xn, yn = x.n, y.n
+ xp, yp = x.p, y.p
+ if xp > yp:
+ yn = yn * _tento(xp - yp)
+ p = xp
+ elif xp < yp:
+ xn = xn * _tento(yp - xp)
+ p = yp
+ else:
+ p = xp # same as yp
+ return xn, yn, p
+
+def _mkFP(n, p, FixedPoint=FixedPoint):
+ f = FixedPoint()
+ f.n = n
+ f.p = p
+ return f
+
+# divide x by y, rounding to int via nearest-even
+# y must be > 0
+# XXX which rounding modes are useful?
+
+def _roundquotient(x, y):
+ assert y > 0
+ n, leftover = divmod(x, y)
+ c = cmp(leftover << 1, y)
+ # c < 0 <-> leftover < y/2, etc
+ if c > 0 or (c == 0 and (n & 1) == 1):
+ n = n + 1
+ return n
+
+# crud for parsing strings
+import re
+
+# There's an optional sign at the start, and an optional exponent
+# at the end. The exponent has an optional sign and at least one
+# digit. In between, must have either at least one digit followed
+# by an optional fraction, or a decimal point followed by at least
+# one digit. Yuck.
+
+_parser = re.compile(r"""
+ \s*
+ (?P<sign>[-+])?
+ (
+ (?P<int>\d+) (\. (?P<frac>\d*))?
+ |
+ \. (?P<onlyfrac>\d+)
+ )
+ ([eE](?P<exp>[-+]? \d+))?
+ \s* $
+""", re.VERBOSE).match
+
+del re
+
+# return n, p s.t. float string value == n * 10**p exactly
+
+def _string2exact(s):
+ m = _parser(s)
+ if m is None:
+ raise ValueError("can't parse as number: " + `s`)
+
+ exp = m.group('exp')
+ if exp is None:
+ exp = 0
+ else:
+ exp = int(exp)
+
+ intpart = m.group('int')
+ if intpart is None:
+ intpart = "0"
+ fracpart = m.group('onlyfrac')
+ else:
+ fracpart = m.group('frac')
+ if fracpart is None or fracpart == "":
+ fracpart = "0"
+ assert intpart
+ assert fracpart
+
+ i, f = long(intpart), long(fracpart)
+ nfrac = len(fracpart)
+ i = i * _tento(nfrac) + f
+ exp = exp - nfrac
+
+ if m.group('sign') == "-":
+ i = -i
+
+ return i, exp
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fmcustomizedlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fmcustomizedlg.py
new file mode 100644
index 0000000..db4fc71
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fmcustomizedlg.py
@@ -0,0 +1,519 @@
+"""
+This module contains a custom dialog class used to personalize the appearance of a
+:class:`FlatMenu` on the fly, allowing also the user of your application to do the same.
+"""
+
+import wx
+from UserDict import UserDict
+
+from artmanager import ArtManager
+from fmresources import *
+from labelbook import LabelBook
+
+_ = wx.GetTranslation
+
+# ---------------------------------------------------------------------------- #
+# Class OrderedDict
+# ---------------------------------------------------------------------------- #
+
+class OrderedDict(UserDict):
+ """
+ An ordered dictionary implementation.
+ """
+
+ def __init__(self, dict = None):
+ self._keys = []
+ UserDict.__init__(self, dict)
+
+ def __delitem__(self, key):
+ UserDict.__delitem__(self, key)
+ self._keys.remove(key)
+
+ def __setitem__(self, key, item):
+ UserDict.__setitem__(self, key, item)
+ if key not in self._keys: self._keys.append(key)
+
+ def clear(self):
+ UserDict.clear(self)
+ self._keys = []
+
+ def copy(self):
+ dict = UserDict.copy(self)
+ dict._keys = self._keys[:]
+ return dict
+
+ def items(self):
+ return zip(self._keys, self.values())
+
+ def keys(self):
+ return self._keys
+
+ def popitem(self):
+ try:
+ key = self._keys[-1]
+ except IndexError:
+ raise KeyError('dictionary is empty')
+
+ val = self[key]
+ del self[key]
+
+ return (key, val)
+
+ def setdefault(self, key, failobj = None):
+ UserDict.setdefault(self, key, failobj)
+ if key not in self._keys: self._keys.append(key)
+
+ def update(self, dict):
+ UserDict.update(self, dict)
+ for key in dict.keys():
+ if key not in self._keys: self._keys.append(key)
+
+ def values(self):
+ return map(self.get, self._keys)
+
+
+# ---------------------------------------------------------------------------- #
+# Class FMTitlePanel
+# ---------------------------------------------------------------------------- #
+
+class FMTitlePanel(wx.Panel):
+ """
+ Helper class to draw gradient shadings on the dialog.
+ """
+
+ def __init__(self, parent, title):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`FMTitlePanel` parent;
+ :param `title`: the string to use as a dialog title.
+ """
+
+ wx.Panel.__init__(self, parent)
+ self._title = title
+
+ # Set the panel size
+ dc = wx.MemoryDC()
+ dc.SelectObject(wx.EmptyBitmap(1, 1))
+ dc.SetFont(wx.SystemSettings_GetFont( wx.SYS_DEFAULT_GUI_FONT ))
+
+ ww, hh = dc.GetTextExtent("Tp")
+ dc.SelectObject(wx.NullBitmap)
+
+ # Set minimum panel size
+ if ww < 250:
+ ww = 250
+
+ self.SetSize(wx.Size(ww, hh + 10))
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`FMTitlePanel`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`FMTitlePanel`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+
+ # Draw the background
+ colour1 = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+ colour2 = ArtManager.Get().LightColour(colour1, 70)
+ ArtManager.Get().PaintStraightGradientBox(dc, self.GetClientRect(), colour1, colour2, False)
+
+ # Draw the text
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetWeight(wx.BOLD)
+ dc.SetFont(font)
+ dc.SetTextForeground(wx.BLACK)
+ dc.DrawText(self._title, 5, 5)
+
+
+# ---------------------------------------------------------------------------- #
+# Class FMCustomizeDlg
+# ---------------------------------------------------------------------------- #
+
+class FMCustomizeDlg(wx.Dialog):
+ """
+ Class used to customize the appearance of :class:`FlatMenu` and :class:`FlatMenuBar`.
+ """
+
+ def __init__(self, parent=None):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`FMCustomizeDlg` parent window.
+ """
+
+ self._book = None
+
+ if not parent:
+ wx.Dialog.__init__(self)
+ return
+
+ wx.Dialog.__init__(self, parent, wx.ID_ANY, _("Customize"), wx.DefaultPosition,
+ wx.DefaultSize, wx.DEFAULT_DIALOG_STYLE)
+
+ self._visibleMenus = OrderedDict()
+ self._hiddenMenus = OrderedDict()
+
+ self.CreateDialog()
+ self.ConnectEvents()
+ self.GetSizer().Fit(self)
+ self.GetSizer().SetSizeHints(self)
+ self.GetSizer().Layout()
+ self.Centre()
+
+
+ def CreateDialog(self):
+ """ Actually creates the dialog. """
+
+ sz = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(sz)
+
+ # Create the main book and add some pages into it
+ style = INB_NO_RESIZE | INB_LEFT | INB_DRAW_SHADOW | INB_BORDER
+ self._book = LabelBook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, style)
+ sz.Add(self._book, 1, wx.EXPAND)
+
+ self._book.SetColour(INB_TAB_AREA_BACKGROUND_COLOUR, ArtManager.Get().GetMenuFaceColour())
+
+ colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+ self._book.SetColour(INB_ACTIVE_TAB_COLOUR, colour)
+
+ self.created = False
+ self.Initialise()
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ # add a separator between the book & the buttons area
+ hsizer.Add(wx.Button(self, wx.ID_OK, _("&Close")), 0, wx.EXPAND | wx.ALIGN_RIGHT)
+ sz.Add(wx.StaticLine(self), 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 3)
+ sz.Add(hsizer, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+
+
+ def Initialise(self):
+ """ Initialzes the :class:`LabelBook` pages. """
+
+ self._book.DeleteAllPages()
+ self._book.AddPage(self.CreateMenusPage(), _("Menus"), True)
+ self._book.AddPage(self.CreateOptionsPage(), _("Options"), False)
+
+
+ def CloseDialog(self):
+ """ Closes the dialog. """
+
+ self.EndModal(wx.ID_OK)
+
+
+ def ConnectEvents(self):
+ """ Does nothing at the moment. """
+
+ pass
+
+
+ def CreateMenusPage(self):
+ """ Creates the :class:`LabelBook` pages with :class:`FlatMenu` information. """
+
+ menus = wx.Panel(self._book, wx.ID_ANY, wx.DefaultPosition, wx.Size(300, 300))
+ sz = wx.BoxSizer(wx.VERTICAL)
+ menus.SetSizer(sz)
+
+ choices = []
+
+ mb = self.GetParent()
+
+ if not self.created:
+ self.order = []
+
+ # Add all the menu items that are currently visible to the list
+ for i in xrange(len(mb._items)):
+
+ dummy, lableOnly = ArtManager.Get().GetAccelIndex(mb._items[i].GetTitle())
+ choices.append(lableOnly)
+
+ # Add the menu to the visible menus map
+ self._visibleMenus.update({lableOnly: mb._items[i].GetMenu()})
+ if not self.created:
+ self.order.append(lableOnly)
+
+ # Add all hidden menus to the menu bar
+
+ for key in self._hiddenMenus.keys():
+ choices.append(key)
+
+ if self.created:
+ visible = OrderedDict()
+ hidden = OrderedDict()
+ for items in self.order:
+ if items in self._visibleMenus:
+ visible[items] = self._visibleMenus[items]
+ elif items in self._hiddenMenus:
+ hidden[items] = self._hiddenMenus[items]
+
+ self._visibleMenus = visible
+ self._hiddenMenus = hidden
+
+ self._menuListId = wx.NewId()
+ self._checkListMenus = wx.CheckListBox(menus, self._menuListId, pos=wx.DefaultPosition, size=wx.Size(250, 250),
+ choices=self.order, style=wx.BORDER_SIMPLE)
+ self._checkListMenus.Bind(wx.EVT_CHECKLISTBOX, self.OnMenuChecked)
+
+ # check all visible items
+ for indx, item in enumerate(self.order):
+ if item in self._visibleMenus:
+ self._checkListMenus.Check(indx)
+
+ # Add title panel
+ title = FMTitlePanel(menus, _("Select Menu To Add/Remove:"))
+ sz.Add(title, 0, wx.EXPAND | wx.ALL, 2)
+ sz.Add(self._checkListMenus, 1, wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT, 2)
+
+ self.created = True
+
+ return menus
+
+
+ def CreateShortcutsPage(self):
+ """ Creates the :class:`LabelBook` shorcuts page. """
+
+ shorcuts = wx.Panel(self._book, wx.ID_ANY, wx.DefaultPosition, wx.Size(300, 300))
+ return shorcuts
+
+
+ def CreateOptionsPage(self):
+ """ Creates the :class:`LabelBook` option page which holds the :class:`FlatMenu` styles. """
+
+ options = wx.Panel(self._book, wx.ID_ANY, wx.DefaultPosition, wx.Size(300, 300))
+
+ # Create some options here
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ options.SetSizer(vsizer)
+
+ #-----------------------------------------------------------
+ # options page layout
+ # - Menu Style: Default or 2007 (radio group)
+ #
+ # - Default Style Settings: (static box)
+ # + Draw vertical gradient (check box)
+ # + Draw border (check box)
+ # + Drop toolbar shadow (check box)
+ #
+ # - Colour Scheme (static box)
+ # + Menu bar background colour (combo button)
+ #-----------------------------------------------------------
+
+ self._menuStyleID = wx.NewId()
+ choices = [_("Default Style"), _("Metallic")]
+ self._menuStyle = wx.RadioBox(options, self._menuStyleID, _("Menu bar style"),
+ wx.DefaultPosition, wx.DefaultSize, choices)
+
+ # update the selection
+ theme = ArtManager.Get().GetMenuTheme()
+
+ if theme == Style2007:
+ self._menuStyle.SetSelection(1)
+ else:
+ self._menuStyle.SetSelection(0)
+
+ # connect event to the control
+ self._menuStyle.Bind(wx.EVT_RADIOBOX, self.OnChangeStyle)
+
+ vsizer.Add(self._menuStyle, 0, wx.EXPAND | wx.ALL, 5)
+
+ self._sbStyle = wx.StaticBoxSizer(wx.StaticBox(options, -1, _("Default style settings")), wx.VERTICAL)
+ self._drawVertGradID = wx.NewId()
+ self._verticalGradient = wx.CheckBox(options, self._drawVertGradID, _("Draw vertical gradient"))
+ self._verticalGradient.Bind(wx.EVT_CHECKBOX, self.OnChangeStyle)
+ self._sbStyle.Add(self._verticalGradient, 0, wx.EXPAND | wx.ALL, 3)
+ self._verticalGradient.SetValue(ArtManager.Get().GetMBVerticalGradient())
+
+ self._drawBorderID = wx.NewId()
+ self._drawBorder = wx.CheckBox(options, self._drawBorderID, _("Draw border around menu bar"))
+ self._drawBorder.Bind(wx.EVT_CHECKBOX, self.OnChangeStyle)
+ self._sbStyle.Add(self._drawBorder, 0, wx.EXPAND | wx.ALL, 3)
+ self._drawBorder.SetValue(ArtManager.Get().GetMenuBarBorder())
+
+ self._shadowUnderTBID = wx.NewId()
+ self._shadowUnderTB = wx.CheckBox(options, self._shadowUnderTBID, _("Toolbar float over menu bar"))
+ self._shadowUnderTB.Bind(wx.EVT_CHECKBOX, self.OnChangeStyle)
+ self._sbStyle.Add(self._shadowUnderTB, 0, wx.EXPAND | wx.ALL, 3)
+ self._shadowUnderTB.SetValue(ArtManager.Get().GetRaiseToolbar())
+
+ vsizer.Add(self._sbStyle, 0, wx.EXPAND | wx.ALL, 5)
+
+ # Misc
+ sb = wx.StaticBoxSizer(wx.StaticBox(options, -1, _("Colour Scheme")), wx.VERTICAL)
+ self._colourID = wx.NewId()
+
+ colourChoices = ArtManager.Get().GetColourSchemes()
+ colourChoices.sort()
+
+ self._colour = wx.ComboBox(options, self._colourID, ArtManager.Get().GetMenuBarColourScheme(), choices=colourChoices,
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
+ sb.Add(self._colour, 0, wx.EXPAND)
+ vsizer.Add(sb, 0, wx.EXPAND | wx.ALL, 5)
+ self._colour.Bind(wx.EVT_COMBOBOX, self.OnChangeStyle)
+
+ # update the dialog by sending all possible events to us
+ event = wx.CommandEvent(wx.wxEVT_COMMAND_RADIOBOX_SELECTED, self._menuStyleID)
+ event.SetEventObject(self)
+ event.SetInt(self._menuStyle.GetSelection())
+ self._menuStyle.ProcessEvent(event)
+
+ event.SetEventType(wx.wxEVT_COMMAND_CHECKBOX_CLICKED)
+ event.SetId(self._drawVertGradID)
+ event.SetInt(ArtManager.Get().GetMBVerticalGradient())
+ self._verticalGradient.ProcessEvent(event)
+
+ event.SetEventType(wx.wxEVT_COMMAND_CHECKBOX_CLICKED)
+ event.SetId(self._shadowUnderTBID)
+ event.SetInt(ArtManager.Get().GetRaiseToolbar())
+ self._shadowUnderTB.ProcessEvent(event)
+
+ event.SetEventType(wx.wxEVT_COMMAND_CHECKBOX_CLICKED)
+ event.SetId(self._drawBorderID)
+ event.SetInt(ArtManager.Get().GetMenuBarBorder())
+ self._drawBorder.ProcessEvent(event)
+
+ event.SetEventType(wx.wxEVT_COMMAND_COMBOBOX_SELECTED)
+ event.SetId(self._colourID)
+ self._colour.ProcessEvent(event)
+
+ return options
+
+
+ def OnMenuChecked(self, event):
+ """
+ Handles the ``wx.EVT_CHECKBOX`` event for :class:`FMCustomizeDlg`.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+
+ :note: This method handles the :class:`FlatMenu` menus visibility.
+ """
+
+ id = event.GetInt()
+ checked = self._checkListMenus.IsChecked(id)
+ menuName = self._checkListMenus.GetString(id)
+ menu = None
+ mb = self.GetParent()
+
+ if checked:
+
+ # remove the item from the hidden map
+ if self._hiddenMenus.has_key(menuName):
+ menu = self._hiddenMenus.pop(menuName)
+
+ # add it to the visible map
+ if menu:
+ self._visibleMenus.update({menuName: menu})
+
+ indx = self._checkListMenus.GetItems().index(menuName)
+ # update the menubar
+ mb.Insert(indx, menu, menu._menuBarFullTitle)
+ mb.Refresh()
+
+ else:
+
+ # remove the item from the visible items
+ if self._visibleMenus.has_key(menuName):
+ menu = self._visibleMenus.pop(menuName)
+
+ # add it to the hidden map
+ if menu:
+ self._hiddenMenus.update({menuName: menu})
+
+ # update the menubar
+ pos = mb.FindMenu(menuName)
+ if pos != wx.NOT_FOUND:
+ mb.Remove(pos)
+
+ mb.Refresh()
+
+ if self.created:
+ visible = OrderedDict()
+ hidden = OrderedDict()
+ for items in self.order:
+ if items in self._visibleMenus:
+ visible[items] = self._visibleMenus[items]
+ elif items in self._hiddenMenus:
+ hidden[items] = self._hiddenMenus[items]
+
+ self._visibleMenus = visible
+ self._hiddenMenus = hidden
+
+
+ def OnChangeStyle(self, event):
+ """
+ Handles the ``wx.EVT_CHECKBOX`` event for :class:`FMCustomizeDlg`.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+
+ :note: This method handles the :class:`FlatMenu` styles.
+ """
+
+ mb = self.GetParent()
+
+ if event.GetId() == self._menuStyleID:
+
+ if event.GetSelection() == 0:
+
+ # Default style
+ ArtManager.Get().SetMenuTheme(StyleXP)
+ self._drawBorder.Enable()
+ self._verticalGradient.Enable()
+ mb.Refresh()
+
+ else:
+
+ ArtManager.Get().SetMenuTheme(Style2007)
+ self._drawBorder.Enable(False)
+ self._verticalGradient.Enable(False)
+ mb.Refresh()
+
+ return
+
+ if event.GetId() == self._drawBorderID:
+
+ ArtManager.Get().DrawMenuBarBorder(event.IsChecked())
+ mb.Refresh()
+ return
+
+ if event.GetId() == self._drawVertGradID:
+
+ ArtManager.Get().SetMBVerticalGradient(event.IsChecked())
+ mb.Refresh()
+ return
+
+ if event.GetId() == self._colourID:
+
+ selection = _("Default")
+ sel = self._colour.GetSelection()
+ if sel != wx.NOT_FOUND:
+ # select new colour scheme
+ selection = self._colour.GetStringSelection()
+
+ ArtManager.Get().SetMenuBarColour(selection)
+ mb.Refresh()
+ return
+
+ if event.GetId() == self._shadowUnderTBID:
+ ArtManager.Get().SetRaiseToolbar(event.IsChecked())
+ mb.Refresh()
+ return
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fmresources.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fmresources.py
new file mode 100644
index 0000000..ea04bc8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fmresources.py
@@ -0,0 +1,407 @@
+import wx
+
+# Overall menu styles
+StyleDefault = 0
+StyleXP = 1
+Style2007 = 2
+StyleVista = 3
+
+# Menu shadows
+RightShadow = 1 # Right side shadow
+BottomShadow = 2 # Not full bottom shadow
+BottomShadowFull = 4 # Full bottom shadow
+
+# Button styles
+BU_EXT_XP_STYLE = 1
+BU_EXT_2007_STYLE = 2
+BU_EXT_LEFT_ALIGN_STYLE = 4
+BU_EXT_CENTER_ALIGN_STYLE = 8
+BU_EXT_RIGHT_ALIGN_STYLE = 16
+BU_EXT_RIGHT_TO_LEFT_STYLE = 32
+
+# Control state
+ControlPressed = 0
+ControlFocus = 1
+ControlDisabled = 2
+ControlNormal = 3
+
+# FlatMenu styles
+FM_OPT_IS_LCD = 1
+""" Use this style if your computer uses a LCD screen. """
+FM_OPT_MINIBAR = 2
+""" Use this if you plan to use the toolbar only. """
+FM_OPT_SHOW_CUSTOMIZE = 4
+""" Show "customize link" in the `More` menu, you will need to write your own handler. See demo. """
+FM_OPT_SHOW_TOOLBAR = 8
+""" Set this option is you are planning to use the toolbar. """
+
+# Control status
+ControlStatusNoFocus = 0
+ControlStatusFocus = 1
+ControlStatusPressed = 2
+
+# HitTest constants
+NoWhere = 0
+MenuItem = 1
+ToolbarItem = 2
+DropDownArrowButton = 3
+
+FTB_ITEM_TOOL = 0
+FTB_ITEM_SEPARATOR = 1
+FTB_ITEM_CHECK = 2
+FTB_ITEM_RADIO = 3
+
+FTB_ITEM_RADIO_MENU = 4
+FTB_ITEM_CUSTOM = 5
+
+LargeIcons = 32
+SmallIcons = 16
+
+MENU_HT_NONE = 0
+MENU_HT_ITEM = 1
+MENU_HT_SCROLL_UP = 2
+MENU_HT_SCROLL_DOWN = 3
+
+MENU_DEC_TOP = 0
+MENU_DEC_BOTTOM = 1
+MENU_DEC_LEFT = 2
+MENU_DEC_RIGHT = 3
+
+DROP_DOWN_ARROW_WIDTH = 16
+SPACER = 12
+MARGIN = 3
+TOOLBAR_SPACER = 4
+TOOLBAR_MARGIN = 4
+SEPARATOR_WIDTH = 12
+SCROLL_BTN_HEIGHT = 20
+
+CS_DROPSHADOW = 0x00020000
+
+INB_BOTTOM = 1
+INB_LEFT = 2
+INB_RIGHT = 4
+INB_TOP = 8
+INB_BORDER = 16
+INB_SHOW_ONLY_TEXT = 32
+INB_SHOW_ONLY_IMAGES = 64
+INB_FIT_BUTTON = 128
+INB_DRAW_SHADOW = 256
+INB_USE_PIN_BUTTON = 512
+INB_GRADIENT_BACKGROUND = 1024
+INB_WEB_HILITE = 2048
+INB_NO_RESIZE = 4096
+INB_FIT_LABELTEXT = 8192
+INB_BOLD_TAB_SELECTION = 16384
+
+INB_DEFAULT_STYLE = INB_BORDER | INB_TOP | INB_USE_PIN_BUTTON
+
+INB_TAB_AREA_BACKGROUND_COLOUR = 100
+INB_ACTIVE_TAB_COLOUR = 101
+INB_TABS_BORDER_COLOUR = 102
+INB_TEXT_COLOUR = 103
+INB_ACTIVE_TEXT_COLOUR = 104
+INB_HILITE_TAB_COLOUR = 105
+
+INB_LABEL_BOOK_DEFAULT = INB_DRAW_SHADOW | INB_BORDER | INB_USE_PIN_BUTTON | INB_LEFT
+
+# HitTest results
+IMG_OVER_IMG = 0
+IMG_OVER_PIN = 1
+IMG_OVER_EW_BORDER = 2
+IMG_NONE = 3
+
+# Pin button states
+INB_PIN_NONE = 0
+INB_PIN_HOVER = 200
+INB_PIN_PRESSED = 201
+
+# Windows Vista Colours
+rgbSelectOuter = wx.Colour(170, 200, 245)
+rgbSelectInner = wx.Colour(230, 250, 250)
+rgbSelectTop = wx.Colour(210, 240, 250)
+rgbSelectBottom = wx.Colour(185, 215, 250)
+
+check_mark_xpm = [" 16 16 16 1",
+ "` c #000000",
+ ". c #800000",
+ "# c #008000",
+ "a c #808000",
+ "b c #000080",
+ "c c #800080",
+ "d c #008080",
+ "e c #808080",
+ "f c #c0c0c0",
+ "g c #ff0000",
+ "h c #00ff00",
+ "i c #ffff00",
+ "j c #0000ff",
+ "k c #ff00ff",
+ "l c #00ffff",
+ "m c #ffffff",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmm`mmmmm",
+ "mmmmmmmmm``mmmmm",
+ "mmmm`mmm```mmmmm",
+ "mmmm``m```mmmmmm",
+ "mmmm`````mmmmmmm",
+ "mmmmm```mmmmmmmm",
+ "mmmmmm`mmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm"
+ ]
+
+radio_item_xpm = [" 16 16 16 1",
+ "` c #000000",
+ ". c #800000",
+ "# c #008000",
+ "a c #808000",
+ "b c #000080",
+ "c c #800080",
+ "d c #008080",
+ "e c #808080",
+ "f c #c0c0c0",
+ "g c #ff0000",
+ "h c #00ff00",
+ "i c #ffff00",
+ "j c #0000ff",
+ "k c #ff00ff",
+ "l c #00ffff",
+ "m c #ffffff",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmm```mmmmmmm",
+ "mmmmm`````mmmmmm",
+ "mmmmm`````mmmmmm",
+ "mmmmmm```mmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm",
+ "mmmmmmmmmmmmmmmm"]
+
+
+menu_right_arrow_xpm = [
+ " 16 16 8 1",
+ "` c #ffffff",
+ ". c #000000",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "``````.`````````",
+ "``````..````````",
+ "``````...```````",
+ "``````....``````",
+ "``````...```````",
+ "``````..````````",
+ "``````.`````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+#----------------------------------
+# Shadow images
+#----------------------------------
+
+shadow_right_xpm = ["5 5 1 1"," c Black"," "," "," "," "," "]
+
+# shadow_right.xpm 5x5
+shadow_right_alpha = [168, 145, 115, 76, 46, 168, 145, 115, 76, 46, 168, 145, 115, 76, 46,
+ 168, 145, 115, 76, 46, 168, 145, 115, 76, 46]
+
+shadow_right_top_xpm = ["5 10 1 1"," c Black"," "," "," "," ",
+ " "," "," "," "," "," "]
+
+shadow_right_top_alpha = [40, 35, 28, 18, 11, 67, 58, 46, 31, 18, 101, 87, 69, 46, 28,
+ 128, 110, 87, 58, 35, 148, 128, 101, 67, 40, 161, 139, 110, 73, 44,
+ 168, 145, 115, 76, 46, 168, 145, 115, 76, 46, 168, 145, 115, 76, 46,
+ 168, 145, 115, 76, 46]
+
+# shadow_buttom.xpm 5x5
+shadow_bottom_alpha = [184, 184, 184, 184, 184, 168, 168, 168, 168, 168, 145, 145, 145, 145, 145,
+ 115, 115, 115, 115, 115, 76, 76, 76, 76, 76]
+
+shadow_bottom_left_xpm = ["10 5 1 1"," c Black"," "," ",
+ " "," "," "]
+
+shadow_bottom_left_alpha = [22, 44, 73, 110, 139, 161, 176, 184, 184, 184,
+ 20, 40, 67, 101, 128, 148, 161, 168, 168, 168,
+ 17, 35, 58, 87, 110, 128, 139, 145, 145, 145,
+ 13, 28, 46, 69, 87, 101, 110, 115, 115, 115,
+ 9, 18, 31, 46, 58, 67, 73, 76, 76, 76]
+
+shadow_center_xpm = ["5 5 1 1"," c Black"," "," "," "," "," "]
+
+shadow_center_alpha = [161, 139, 110, 73, 44, 148, 128, 101, 67, 40,
+ 128, 110, 87, 58, 35, 101, 87, 69, 46, 28,
+ 67, 58, 46, 31, 18]
+
+shadow_bottom_xpm = ["5 5 1 1"," c Black"," "," "," "," "," "]
+
+arrow_down_xpm = ["16 16 3 1",
+ ". c Black",
+ "X c #FFFFFF",
+ " c #008080",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ....... ",
+ " XXXXXXX ",
+ " ",
+ " ....... ",
+ " X.....X ",
+ " X...X ",
+ " X.X ",
+ " X ",
+ " ",
+ " ",
+ " ",
+ " "]
+
+#---------------------------------------------
+# Pin images
+#---------------------------------------------
+pin_left_xpm = [" 16 16 8 1",
+ "` c #ffffff",
+ ". c #000000",
+ "# c #808080",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "```````.````````",
+ "```````.````````",
+ "```````.......``",
+ "```````.`````.``",
+ "`````...`````.``",
+ "``......#####.``",
+ "`````...#####.``",
+ "```````.......``",
+ "```````.......``",
+ "```````.````````",
+ "```````.````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"]
+
+pin_down_xpm = [" 16 16 8 1",
+ "` c #ffffff",
+ ". c #000000",
+ "# c #808080",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````.......`````",
+ "````.``##..`````",
+ "````.``##..`````",
+ "````.``##..`````",
+ "````.``##..`````",
+ "````.``##..`````",
+ "``...........```",
+ "``````...```````",
+ "``````...```````",
+ "```````.````````",
+ "```````.````````",
+ "```````.````````",
+ "````````````````",
+ "````````````````"]
+
+
+arrow_up = 'BM\xf6\x00\x00\x00\x00\x00\x00\x00v\x00\x00\x00(\x00\x00\x00\x10\x00\x00\
+\x00\x10\x00\x00\x00\x01\x00\x04\x00\x00\x00\x00\x00\x80\x00\x00\x00\x12\x0b\x00\x00\x12\
+\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x80\x80\x00\
+\x00w\xfcM\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00""""""""""""""""""""""""""""""""""\x00\x00\x00\x02""""\x11\x11\
+\x11\x12""""""""""""\x00\x00\x00\x02""""\x10\x00\x00\x12""""!\x00\x01""""""\x10\x12""""""!\
+""""""""""""""""""""""""""""""""""""'
+
+
+arrow_down = 'BM\xf6\x00\x00\x00\x00\x00\x00\x00v\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00\
+\x10\x00\x00\x00\x01\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x0b\x00\x00\x12\x0b\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x80\x80\x00\x00w\
+\xfcM\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00"""""""""""""""""""""""""""""""""""!"""""""\x10\x12"""""!\x00\x01\
+"""""\x10\x00\x00\x12""""\x00\x00\x00\x02""""""""""""\x11\x11\x11\x12""""\x00\x00\x00\x02\
+""""""""""""""""""""""""""""""""""'
+
+menu_up_arrow_xpm = ["16 16 2 1",
+ ". c Black",
+ " c White",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " . ",
+ " ... ",
+ " ..... ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " "]
+
+
+menu_down_arrow_xpm = ["16 16 2 1",
+ ". c Black",
+ " c White",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ..... ",
+ " ... ",
+ " . ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " "]
+
+
+def getMenuUpArrowBitmap():
+ bmp = wx.BitmapFromXPMData(menu_up_arrow_xpm)
+ bmp.SetMask(wx.Mask(bmp, wx.WHITE))
+ return bmp
+
+def getMenuDownArrowBitmap():
+ bmp = wx.BitmapFromXPMData(menu_down_arrow_xpm)
+ bmp.SetMask(wx.Mask(bmp, wx.WHITE))
+ return bmp
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/foldpanelbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/foldpanelbar.py
new file mode 100644
index 0000000..42c58cb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/foldpanelbar.py
@@ -0,0 +1,2246 @@
+# --------------------------------------------------------------------------- #
+# FOLDPANELBAR wxPython IMPLEMENTATION
+# Ported From Jorgen Bodde & Julian Smart (Extended Demo) C++ Code By:
+#
+# Andrea Gavana, @ 23 Mar 2005
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# TODO List
+#
+# All The C++ TODOs Are Still Alive. I Am Not Able to Read Jorges's Mind
+# So I Don't Really Know What Will Be The New Features/Additions He Will
+# Make On His Code. At The Moment They Are:
+#
+# 1. OnPaint Function In CaptionBar Class:
+# TODO: Maybe First A Memory Dc Should Draw All, And Then Paint It On The
+# Caption. This Way A Flickering Arrow During Resize Is Not Visible.
+#
+# 2. OnChar Function In CaptionBar Class:
+# TODO: This Is Easy To Do But I Don't Have Any Useful Idea On Which Kind
+# Of Features To Add. Does Anyone Have An Intelligent Idea?
+#
+# 3. AddFoldPanelWindow Function In FoldPanelBar Class:
+# TODO: Take Old And New Heights, And If Difference, Reposition All The
+# Lower Panels. This Is Because The User Can Add New wxWindow Controls
+# Somewhere In Between When Other Panels Are Already Present.
+# Don't Know What It Means. Probably Is My Poor English...
+#
+# 4. OnSizePanel Function In FoldPanelBar Class:
+# TODO: A Smart Way To Check Wether The Old - New Width Of The
+# Panel Changed, If So No Need To Resize The Fold Panel Items
+#
+#
+# DONE List:
+#
+# 1. Implemented Styles Like FPB_SINGLE_FOLD and FPB_EXCLUSIVE_FOLD
+# Thanks To E. A. Tacao For His Nice Suggestions.
+#
+# 2. Added Some Maquillage To FoldPanelBar: When The Mouse Enters The Icon
+# Region, It Is Changed To wx.CURSOR_HAND.
+#
+#
+# For The Original TODO List From Jorgen, Please Refer To:
+# http://www.solidsteel.nl/jorg/components/foldpanel/wxFoldPanelBar.php#todo_list
+#
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+
+"""
+:class:`FoldPanelBar` is a control that contains multiple panels, which can be expanded
+or collapsed.
+
+
+Description
+===========
+
+The :class:`FoldPanelBar` is a control that contains multiple panels (of type
+:class:`FoldPanelItem`) that can be expanded or collapsed. The captionbar of
+the :class:`FoldPanelBar` can be customized by setting it to a horizontal gradient
+style, vertical gradient style, a single colour, a rectangle or filled
+rectangle. The `FoldPanel` items can be collapsed in place or to the
+bottom of the control. :class:`Window` derived controls can be added
+dynamically, and separated by separator lines.
+
+
+How does it work
+----------------
+
+The internals of the :class:`FoldPanelBar` is a list of :class:`FoldPanelItem` objects. Through
+the reference of `FoldPanel` these panels can be controlled by adding new controls
+to a FoldPanel or adding new FoldPanels to the :class:`FoldPanelBar`.
+
+The :class:`CaptionBar` fires events to the parent (container of all panel items) when a
+sub-panel needs resizing (either folding or expanding). The fold or expand process
+is simply a resize of the panel so it looks like all controls on it are gone. All
+controls are still child of the `FoldPanel` they are located on. If they don't
+handle the event (and they won't) then the owner of the :class:`FoldPanelBar` gets the
+events.
+
+This is what you need to handle the controls. There isn't much to it just
+a lot of calculations to see what panel belongs where. There are no sizers
+involved in the panels, everything is purely x-y positioning.
+
+
+What can it do and what not?
+----------------------------
+
+a) What it can do:
+
+ * Run-time addition of panels (no deletion just yet);
+ * Run time addition of controls to the panel (it will be resized accordingly);
+ * Creating panels in collapsed mode or expanded mode;
+ * Various modes of caption behaviour and filling to make it more appealing;
+ * Panels can be folded and collapsed (or all of them) to allow more space.
+
+b) What it cannot do:
+
+ * Selection of a panel like in a listctrl;
+ * Dragging and dropping the panels;
+ * Re-ordering the panels (not yet).
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.foldpanelbar as fpb
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "FoldPanelBar Demo")
+
+ text_ctrl = wx.TextCtrl(self, -1, size=(400, 100), style=wx.TE_MULTILINE)
+
+ panel_bar = fpb.FoldPanelBar(self, -1, agwStyle=fpb.FPB_HORIZONTAL|fpb.FPB_DEFAULT_STYLE)
+
+ fold_panel = panel_bar.AddFoldPanel("Thing")
+ thing = wx.TextCtrl(fold_panel, -1, size=(400, -1), style=wx.TE_MULTILINE)
+
+ panel_bar.AddFoldPanelWindow(fold_panel, thing)
+
+ main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ main_sizer.Add(text_ctrl, 1, wx.EXPAND)
+ main_sizer.Add(panel_bar, 0, wx.EXPAND)
+ self.SetSizer(main_sizer)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`FoldPanelBar` is supported on the following platforms:
+ * Windows (Verified on Windows XP, 2000)
+ * Linux/Unix (GTK2) (Thanks to Toni Brkic and Robin Dunn)
+ * Mac OSX (Thanks to Robin Dunn for the :class:`CaptionBar` size patch)
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+========================== =========== ==================================================
+Window Styles Hex Value Description
+========================== =========== ==================================================
+``FPB_SINGLE_FOLD`` 0x1 Single fold forces other panels to close when they are open, and only opens the current panel. This will allow the open panel to gain the full size left in the client area.
+``FPB_COLLAPSE_TO_BOTTOM`` 0x2 All panels are stacked to the bottom. When they are expanded again they show up at the top.
+``FPB_EXCLUSIVE_FOLD`` 0x4 ``FPB_SINGLE_FOLD`` style plus the panels will be stacked at the bottom.
+``FPB_HORIZONTAL`` 0x8 :class:`FoldPanelBar` will be horizontal.
+``FPB_VERTICAL`` 0x10 :class:`FoldPanelBar` will be vertical.
+========================== =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================== ==================================================
+Event Name Description
+================== ==================================================
+``EVT_CAPTIONBAR`` The user has pressed the caption bar: :class:`FoldPanelBar` will either expand or collapse the underlying panel.
+================== ==================================================
+
+
+License And Version
+===================
+
+:class:`FoldPanelBar` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.5
+
+"""
+
+import wx
+
+#----------------------------------------------------------------------
+# Collapsed And Expanded Bitmap Images
+# Created With img2py.py
+#----------------------------------------------------------------------
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+CollapsedIcon = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADdJ"
+ "REFUOI1jZGRiZqAEMFGke/Ab8P/f3/8D5wKY7YRcQRsXoNuKzxXUdwEu23CJU+wCxtG8wAAA"
+ "mvUb+vltJD8AAAAASUVORK5CYII=")
+
+ExpandedIcon = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAEJJ"
+ "REFUOI1jZGRiZqAEMFGke1AYwIIu8P/f3/+4FDMyMTNS3QUYBmCzBZ84bQIR3TZcttPOBci2"
+ "4rOdKi5gHM0LDACevARXGc9htQAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+# FOLDPANELBAR Starts Here
+#----------------------------------------------------------------------
+
+# CAPTIONBAR STYLES
+#
+#- CAPTIONBAR_GRADIENT_V: Draws a vertical gradient from top to bottom
+#- CAPTIONBAR_GRADIENT_H: Draws a horizontal gradient from left to right
+#- CAPTIONBAR_SINGLE: Draws a single filled rectangle to draw the caption
+#- CAPTIONBAR_RECTANGLE: Draws a single colour with a rectangle around the caption
+#- CAPTIONBAR_FILLED_RECTANGLE: Draws a filled rectangle and a border around it
+
+CAPTIONBAR_NOSTYLE = 0
+""" The :class:`CaptionBar` has no style bit set. """
+CAPTIONBAR_GRADIENT_V = 1
+""" Draws a vertical gradient from top to bottom. """
+CAPTIONBAR_GRADIENT_H = 2
+""" Draws a vertical gradient from left to right. """
+CAPTIONBAR_SINGLE = 3
+""" Draws a single filled rectangle to draw the caption. """
+CAPTIONBAR_RECTANGLE = 4
+""" Draws a single colour with a rectangle around the caption. """
+CAPTIONBAR_FILLED_RECTANGLE = 5
+""" Draws a filled rectangle and a border around it. """
+
+FPB_EXTRA_X = 10
+""" Extra horizontal padding, in pixels. """
+FPB_EXTRA_Y = 4
+""" Extra vertical padding, in pixels. """
+
+# pixels of the bmp to be aligned from the right filled with space
+FPB_BMP_RIGHTSPACE = 2
+""" Pixels of the bmp to be aligned from the right filled with space. """
+
+# Now supported! Single fold forces
+# other panels to close when they are open, and only opens the current panel.
+# This will allow the open panel to gain the full size left in the client area
+FPB_SINGLE_FOLD = 0x0001
+""" Single fold forces other panels to close when they are open, and only opens the current panel. This will allow the open panel to gain the full size left in the client area."""
+
+# All panels are stacked to the bottom. When they are expanded again they
+# show up at the top
+FPB_COLLAPSE_TO_BOTTOM = 0x0002
+""" All panels are stacked to the bottom. When they are expanded again they show up at the top. """
+
+# Now supported! Single fold plus panels
+# will be stacked at the bottom
+FPB_EXCLUSIVE_FOLD = 0x0004
+""" ``FPB_SINGLE_FOLD`` style plus the panels will be stacked at the bottom. """
+
+# Orientation Flag
+FPB_HORIZONTAL = 0x0008
+""" :class:`FoldPanelBar` will be horizontal. """
+FPB_VERTICAL = 0x0010
+""" :class:`FoldPanelBar` will be vertical. """
+
+# FoldPanelItem default settings
+FPB_ALIGN_LEFT = 0
+""" Aligns left instead of fitting the width of the child window to be added. Use either this one or ``FPB_ALIGN_WIDTH``. """
+FPB_ALIGN_WIDTH = 1
+""" The :class:`Window` to be added will be aligned to fit the width of the FoldPanel when it is resized. Very handy for sizer items, buttons and text boxes. """
+
+FPB_DEFAULT_LEFTSPACING = 5
+FPB_DEFAULT_RIGHTSPACING = 10
+FPB_DEFAULT_SPACING = 8
+
+FPB_DEFAULT_LEFTLINESPACING = 2
+FPB_DEFAULT_RIGHTLINESPACING = 2
+
+
+# ------------------------------------------------------------------------------ #
+# class CaptionBarStyle
+# ------------------------------------------------------------------------------ #
+
+class CaptionBarStyle(object):
+ """
+ This class encapsulates the styles you wish to set for the
+ :class:`CaptionBar` (this is the part of the `FoldPanel` where the caption
+ is displayed). It can either be applied at creation time be
+ reapplied when styles need to be changed.
+
+ At construction time, all styles are set to their default
+ transparency. This means none of the styles will be applied to
+ the :class:`CaptionBar` in question, meaning it will be created using the
+ default internals. When setting i.e the colour, font or panel
+ style, these styles become active to be used.
+ """
+
+ def __init__(self):
+ """ Default constructor for this class. """
+
+ self.ResetDefaults()
+
+
+ def ResetDefaults(self):
+ """ Resets default :class:`CaptionBarStyle`. """
+ self._firstColourUsed = False
+ self._secondColourUsed = False
+ self._textColourUsed = False
+ self._captionFontUsed = False
+ self._captionStyleUsed = False
+ self._captionStyle = CAPTIONBAR_GRADIENT_V
+
+
+ # ------- CaptionBar Font -------
+
+ def SetCaptionFont(self, font):
+ """
+ Sets font for the caption bar.
+
+ :param `font`: a valid :class:`Font` object.
+
+ :note: If this is not set, the font property is undefined and will not be used.
+ Use :meth:`~CaptionBarStyle.CaptionFontUsed` to check if this style is used.
+ """
+
+ self._captionFont = font
+ self._captionFontUsed = True
+
+
+ def CaptionFontUsed(self):
+ """ Checks if the caption bar font is set. """
+
+ return self._captionFontUsed
+
+
+ def GetCaptionFont(self):
+ """
+ Returns the font for the caption bar.
+
+ :note: Please be warned this will result in an assertion failure when
+ this property is not previously set.
+
+ :see: :meth:`~CaptionBarStyle.SetCaptionFont`, :meth:`~CaptionBarStyle.CaptionFontUsed`
+ """
+
+ return self._captionFont
+
+
+ # ------- First Colour -------
+
+ def SetFirstColour(self, colour):
+ """
+ Sets first colour for the caption bar.
+
+ :param `colour`: a valid :class:`Colour` object.
+
+ :note: If this is not set, the colour property is undefined and will not be used.
+ Use :meth:`~CaptionBarStyle.FirstColourUsed` to check if this style is used.
+ """
+
+ self._firstColour = colour
+ self._firstColourUsed = True
+
+
+ def FirstColourUsed(self):
+ """ Checks if the first colour of the caption bar is set."""
+
+ return self._firstColourUsed
+
+
+ def GetFirstColour(self):
+ """
+ Returns the first colour for the caption bar.
+
+ :note: Please be warned this will result in an assertion failure when
+ this property is not previously set.
+
+ :see: :meth:`~CaptionBarStyle.SetFirstColour`, :meth:`~CaptionBarStyle.FirstColourUsed`
+ """
+
+ return self._firstColour
+
+
+ # ------- Second Colour -------
+
+ def SetSecondColour(self, colour):
+ """
+ Sets second colour for the caption bar.
+
+ :param `colour`: a valid :class:`Colour` object.
+
+ :note: If this is not set, the colour property is undefined and will not be used.
+ Use :meth:`~CaptionBarStyle.SecondColourUsed` to check if this style is used.
+ """
+
+ self._secondColour = colour
+ self._secondColourUsed = True
+
+
+ def SecondColourUsed(self):
+ """ Checks if the second colour of the caption bar is set."""
+
+ return self._secondColourUsed
+
+
+ def GetSecondColour(self):
+ """
+ Returns the second colour for the caption bar.
+
+ :note: Please be warned this will result in an assertion failure when
+ this property is not previously set.
+
+ :see: :meth:`~CaptionBarStyle.SetSecondColour`, :meth:`~CaptionBarStyle.SecondColourUsed`
+ """
+
+ return self._secondColour
+
+
+ # ------- Caption Text Colour -------
+
+ def SetCaptionColour(self, colour):
+ """
+ Sets caption colour for the caption bar.
+
+ :param `colour`: a valid :class:`Colour` object.
+
+ :note: If this is not set, the colour property is undefined and will not be used.
+ Use :meth:`~CaptionBarStyle.CaptionColourUsed` to check if this style is used.
+ """
+
+ self._textColour = colour
+ self._textColourUsed = True
+
+
+ def CaptionColourUsed(self):
+ """ Checks if the caption colour of the caption bar is set."""
+
+ return self._textColourUsed
+
+
+ def GetCaptionColour(self):
+ """
+ Returns the caption colour for the caption bar.
+
+ :note: Please be warned this will result in an assertion failure
+ when this property is not previously set.
+
+ :see: :meth:`~CaptionBarStyle.SetCaptionColour`, :meth:`~CaptionBarStyle.CaptionColourUsed`
+ """
+
+ return self._textColour
+
+
+ # ------- CaptionStyle -------
+
+ def SetCaptionStyle(self, style):
+ """
+ Sets caption style for the caption bar.
+
+ :param `style`: can be one of the following bits:
+
+ =============================== ======= =============================
+ Caption Style Value Description
+ =============================== ======= =============================
+ ``CAPTIONBAR_GRADIENT_V`` 1 Draws a vertical gradient from top to bottom
+ ``CAPTIONBAR_GRADIENT_H`` 2 Draws a horizontal gradient from left to right
+ ``CAPTIONBAR_SINGLE`` 3 Draws a single filled rectangle to draw the caption
+ ``CAPTIONBAR_RECTANGLE`` 4 Draws a single colour with a rectangle around the caption
+ ``CAPTIONBAR_FILLED_RECTANGLE`` 5 Draws a filled rectangle and a border around it
+ =============================== ======= =============================
+
+ :note: If this is not set, the property is undefined and will not be used.
+ Use :meth:`~CaptionBarStyle.CaptionStyleUsed` to check if this style is used.
+ """
+
+ self._captionStyle = style
+ self._captionStyleUsed = True
+
+
+ def CaptionStyleUsed(self):
+ """ Checks if the caption style of the caption bar is set."""
+
+ return self._captionStyleUsed
+
+
+ def GetCaptionStyle(self):
+ """
+ Returns the caption style for the caption bar.
+
+ :note: Please be warned this will result in an assertion failure
+ when this property is not previously set.
+
+ :see: :meth:`~CaptionBarStyle.SetCaptionStyle`, :meth:`~CaptionBarStyle.CaptionStyleUsed`
+ """
+
+ return self._captionStyle
+
+
+#-----------------------------------#
+# CaptionBarEvent
+#-----------------------------------#
+wxEVT_CAPTIONBAR = wx.NewEventType()
+EVT_CAPTIONBAR = wx.PyEventBinder(wxEVT_CAPTIONBAR, 0)
+""" The user has pressed the caption bar: :class:`FoldPanelBar` will either expand or""" \
+""" collapse the underlying panel. """
+
+# Define Empty CaptionBar Style
+EmptyCaptionBarStyle = CaptionBarStyle()
+
+# ---------------------------------------------------------------------------- #
+# class CaptionBarEvent
+# ---------------------------------------------------------------------------- #
+
+class CaptionBarEvent(wx.PyCommandEvent):
+ """
+ This event will be sent when a ``EVT_CAPTIONBAR`` is mapped in the parent.
+ It is to notify the parent that the bar is now in collapsed or expanded
+ state. The parent should re-arrange the associated windows accordingly
+ """
+
+ def __init__(self, evtType):
+ """
+ Default class constructor.
+
+ :param `evtType`: the event type.
+ """
+
+ wx.PyCommandEvent.__init__(self, evtType)
+
+
+ def GetFoldStatus(self):
+ """
+ Returns whether the bar is expanded or collapsed. ``True`` means
+ expanded.
+ """
+
+ return not self._bar.IsCollapsed()
+
+
+ def GetBar(self):
+ """ Returns the selected :class:`CaptionBar`. """
+
+ return self._bar
+
+
+ def SetTag(self, tag):
+ """
+ Assigns a tag to the selected :class:`CaptionBar`.
+
+ :param `tag`: an instance of :class:`FoldPanelBar`.
+ """
+
+ self._tag = tag
+
+
+ def GetTag(self):
+ """ Returns the tag assigned to the selected :class:`CaptionBar`. """
+
+ return self._tag
+
+
+ def SetBar(self, bar):
+ """
+ Sets the bar associated with this event.
+
+ :param `bar`: an instance of :class:`CaptionBar`.
+
+ :note: Should not be used by any other than the originator of the event.
+ """
+
+ self._bar = bar
+
+
+# -------------------------------------------------------------------------------- #
+# class CaptionBar
+# -------------------------------------------------------------------------------- #
+
+class CaptionBar(wx.Window):
+ """
+ This class is a graphical caption component that consists of a
+ caption and a clickable arrow.
+
+ The :class:`CaptionBar` fires an event ``EVT_CAPTIONBAR`` which is a
+ :class:`CaptionBarEvent`. This event can be caught and the parent window
+ can act upon the collapsed or expanded state of the bar (which is
+ actually just the icon which changed). The parent panel can
+ reduce size or expand again.
+ """
+
+ def __init__(self, parent, id, pos, size, caption="",
+ foldIcons=None, cbstyle=None,
+ rightIndent=FPB_BMP_RIGHTSPACE,
+ iconWidth=16, iconHeight=16, collapsed=False):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`CaptionBar` parent window;
+ :param `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `caption`: the string to be displayed in :class:`CaptionBar`;
+ :param `foldIcons`: an instance of :class:`ImageList` containing the icons to display
+ next to the caption text;
+ :param `cbstyle`: the :class:`CaptionBar` window style. Must be an instance of
+ :class:`CaptionBarStyle`;
+ :param `rightIndent`: number of pixels of the bmp to be aligned from the right filled
+ with space;
+ :param `iconWidth`: the :class:`CaptionBar` icon width;
+ :param `iconHeight`: the :class:`CaptionBar` icon height;
+ :param `collapsed`: ``True`` if the :class:`CaptionBar` should start in the collapsed state,
+ ``False`` otherwise.
+ """
+
+ wx.Window.__init__(self, parent, wx.ID_ANY, pos=pos,
+ size=(20,20), style=wx.NO_BORDER)
+
+ self._controlCreated = False
+ self._collapsed = collapsed
+ self.ApplyCaptionStyle(cbstyle, True)
+
+ if foldIcons is None:
+ foldIcons = wx.ImageList(16, 16)
+
+ bmp = ExpandedIcon.GetBitmap()
+ foldIcons.Add(bmp)
+ bmp = CollapsedIcon.GetBitmap()
+ foldIcons.Add(bmp)
+
+ # set initial size
+ if foldIcons:
+ assert foldIcons.GetImageCount() > 1
+ iconWidth, iconHeight = foldIcons.GetSize(0)
+
+ self._caption = caption
+ self._foldIcons = foldIcons
+ self._style = cbstyle
+ self._rightIndent = rightIndent
+ self._iconWidth = iconWidth
+ self._iconHeight = iconHeight
+ self._oldSize = wx.Size(20,20)
+
+ self._controlCreated = True
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+
+
+ def ApplyCaptionStyle(self, cbstyle=None, applyDefault=True):
+ """
+ Applies the style defined in `cbstyle` to the :class:`CaptionBar`.
+
+ :param `cbstyle`: an instance of :class:`CaptionBarStyle`;
+ :param `applyDefault`: if ``True``, the colours used in the :class:`CaptionBarStyle`
+ will be reset to their default values.
+ """
+
+ if cbstyle is None:
+ cbstyle = EmptyCaptionBarStyle
+
+ newstyle = cbstyle
+
+ if applyDefault:
+
+ # get first colour from style or make it default
+ if not newstyle.FirstColourUsed():
+ newstyle.SetFirstColour(wx.WHITE)
+
+ # get second colour from style or make it default
+ if not newstyle.SecondColourUsed():
+ # make the second colour slightly darker then the background
+ colour = self.GetParent().GetBackgroundColour()
+ r, g, b = int(colour.Red()), int(colour.Green()), int(colour.Blue())
+ colour = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
+ newstyle.SetSecondColour(wx.Colour(colour[0], colour[1], colour[2]))
+
+ # get text colour
+ if not newstyle.CaptionColourUsed():
+ newstyle.SetCaptionColour(wx.BLACK)
+
+ # get font colour
+ if not newstyle.CaptionFontUsed():
+ newstyle.SetCaptionFont(self.GetParent().GetFont())
+
+ # apply caption style
+ if not newstyle.CaptionStyleUsed():
+ newstyle.SetCaptionStyle(CAPTIONBAR_GRADIENT_V)
+
+ self._style = newstyle
+
+
+ def SetCaptionStyle(self, cbstyle=None, applyDefault=True):
+ """
+ Sets :class:`CaptionBar` styles with :class:`CaptionBarStyle` class.
+
+ :param `cbstyle`: an instance of :class:`CaptionBarStyle`;
+ :param `applyDefault`: if ``True``, the colours used in the :class:`CaptionBarStyle`
+ will be reset to their default values.
+
+ :note: All styles that are actually set, are applied. If you set `applyDefault`
+ to ``True``, all other (not defined) styles will be set to default. If it is
+ ``False``, the styles which are not set in the :class:`CaptionBarStyle` will be ignored.
+ """
+
+ if cbstyle is None:
+ cbstyle = EmptyCaptionBarStyle
+
+ self.ApplyCaptionStyle(cbstyle, applyDefault)
+ self.Refresh()
+
+
+ def GetCaptionStyle(self):
+ """
+ Returns the current style of the captionbar in a :class:`CaptionBarStyle` class.
+
+ :note: This can be used to change and set back the changes.
+ """
+
+ return self._style
+
+
+ def IsCollapsed(self):
+ """ Returns wether the status of the bar is expanded or collapsed. """
+
+ return self._collapsed
+
+
+ def SetRightIndent(self, pixels):
+ """
+ Sets the amount of pixels on the right from which the bitmap
+ is trailing.
+
+ :param `pixels`: the number of pixels on the right from which the bitmap
+ is trailing. If this is 0, it will be drawn all the way to the right,
+ default is equal to ``FPB_BMP_RIGHTSPACE``. Assign this before
+ assigning an image list to prevent a redraw.
+ """
+
+ assert pixels >= 0
+ self._rightIndent = pixels
+ if self._foldIcons:
+ self.Refresh()
+
+
+ def Collapse(self):
+ """
+ This sets the internal state/representation to collapsed.
+
+ :note: This does not trigger a :class:`CaptionBarEvent` to be sent to the
+ parent.
+ """
+
+ self._collapsed = True
+ self.RedrawIconBitmap()
+
+
+ def Expand(self):
+ """
+ This sets the internal state/representation to expanded.
+
+ :note: This does not trigger a :class:`CaptionBarEvent` to be sent to the
+ parent.
+ """
+
+ self._collapsed = False
+ self.RedrawIconBitmap()
+
+
+ def SetBoldFont(self):
+ """ Sets the :class:`CaptionBar` font weight to bold."""
+
+ self.GetFont().SetWeight(wx.BOLD)
+
+
+ def SetNormalFont(self):
+ """ Sets the :class:`CaptionBar` font weight to normal."""
+
+ self.GetFont().SetWeight(wx.NORMAL)
+
+
+ def IsVertical(self):
+ """
+ Returns wether the :class:`CaptionBar` has a default orientation or not.
+ Default is vertical.
+ """
+
+ fld = self.GetParent().GetGrandParent()
+ if isinstance(fld, FoldPanelBar):
+ return self.GetParent().GetGrandParent().IsVertical()
+ else:
+ raise Exception("ERROR: Wrong Parent " + repr(fld))
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`CaptionBar`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ if not self._controlCreated:
+ event.Skip()
+ return
+
+ dc = wx.PaintDC(self)
+ wndRect = self.GetRect()
+ vertical = self.IsVertical()
+
+ # TODO: Maybe first a memory DC should draw all, and then paint it on
+ # the caption. This way a flickering arrow during resize is not visible
+
+ self.FillCaptionBackground(dc)
+ dc.SetFont(self._style.GetCaptionFont())
+ dc.SetTextForeground(self._style.GetCaptionColour())
+
+ if vertical:
+ dc.DrawText(self._caption, 4, FPB_EXTRA_Y/2)
+ else:
+ dc.DrawRotatedText(self._caption, FPB_EXTRA_Y/2,
+ wndRect.GetBottom() - 4, 90)
+
+ # draw small icon, either collapsed or expanded
+ # based on the state of the bar. If we have any bmp's
+
+ if self._foldIcons:
+
+ index = self._collapsed
+
+ if vertical:
+ drw = wndRect.GetRight() - self._iconWidth - self._rightIndent
+ self._foldIcons.Draw(index, dc, drw,
+ (wndRect.GetHeight() - self._iconHeight)/2,
+ wx.IMAGELIST_DRAW_TRANSPARENT)
+ else:
+ self._foldIcons.Draw(index, dc,
+ (wndRect.GetWidth() - self._iconWidth)/2,
+ self._rightIndent, wx.IMAGELIST_DRAW_TRANSPARENT)
+
+## event.Skip()
+
+
+ def FillCaptionBackground(self, dc):
+ """
+ Fills the background of the caption with either a gradient or
+ a solid colour.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ style = self._style.GetCaptionStyle()
+
+ if style == CAPTIONBAR_GRADIENT_V:
+ if self.IsVertical():
+ self.DrawVerticalGradient(dc, self.GetRect())
+ else:
+ self.DrawHorizontalGradient(dc, self.GetRect())
+
+ elif style == CAPTIONBAR_GRADIENT_H:
+ if self.IsVertical():
+ self.DrawHorizontalGradient(dc, self.GetRect())
+ else:
+ self.DrawVerticalGradient(dc, self.GetRect())
+
+ elif style == CAPTIONBAR_SINGLE:
+ self.DrawSingleColour(dc, self.GetRect())
+ elif style == CAPTIONBAR_RECTANGLE or style == CAPTIONBAR_FILLED_RECTANGLE:
+ self.DrawSingleRectangle(dc, self.GetRect())
+ else:
+ raise Exception("STYLE Error: Undefined Style Selected: " + repr(style))
+
+
+ def OnMouseEvent(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` event for :class:`CaptionBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+
+ :note: This method catches the mouse click-double click. If clicked on
+ the arrow (single) or double on the caption we change state and an event
+ must be fired to let this panel collapse or expand.
+ """
+
+ send_event = False
+ vertical = self.IsVertical()
+
+ if event.LeftDown() and self._foldIcons:
+
+ pt = event.GetPosition()
+ rect = self.GetRect()
+
+ drw = (rect.GetWidth() - self._iconWidth - self._rightIndent)
+ if vertical and pt.x > drw or not vertical and \
+ pt.y < (self._iconHeight + self._rightIndent):
+ send_event = True
+
+ elif event.LeftDClick():
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ send_event = True
+
+ elif event.Entering() and self._foldIcons:
+ pt = event.GetPosition()
+ rect = self.GetRect()
+
+ drw = (rect.GetWidth() - self._iconWidth - self._rightIndent)
+ if vertical and pt.x > drw or not vertical and \
+ pt.y < (self._iconHeight + self._rightIndent):
+ self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+ else:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+
+ elif event.Leaving():
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+
+ elif event.Moving():
+ pt = event.GetPosition()
+ rect = self.GetRect()
+
+ drw = (rect.GetWidth() - self._iconWidth - self._rightIndent)
+ if vertical and pt.x > drw or not vertical and \
+ pt.y < (self._iconHeight + self._rightIndent):
+ self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+ else:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+
+ # send the collapse, expand event to the parent
+
+ if send_event:
+ event = CaptionBarEvent(wxEVT_CAPTIONBAR)
+ event.SetId(self.GetId())
+ event.SetEventObject(self)
+ event.SetBar(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def OnChar(self, event):
+ """
+ Handles the ``wx.EVT_CHAR`` event for :class:`CaptionBar`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+
+ :note: This method currently does nothing.
+ """
+
+ # TODO: Anything here?
+ event.Skip()
+
+
+ def DoGetBestSize(self):
+ """
+ Returns the best size for this panel, based upon the font
+ assigned to this window, and the caption string.
+
+ :note: Overridden from :class:`Window`.
+ """
+
+ if self.IsVertical():
+ x, y = self.GetTextExtent(self._caption)
+ else:
+ y, x = self.GetTextExtent(self._caption)
+
+ if x < self._iconWidth:
+ x = self._iconWidth
+
+ if y < self._iconHeight:
+ y = self._iconHeight
+
+ # TODO: The extra FPB_EXTRA_X constants should be adjustable as well
+
+ return wx.Size(x + FPB_EXTRA_X, y + FPB_EXTRA_Y)
+
+
+ def DrawVerticalGradient(self, dc, rect):
+ """
+ Gradient fill from colour 1 to colour 2 from top to bottom.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the :class:`CaptionBar` client rectangle.
+ """
+
+ if rect.height < 1 or rect.width < 1:
+ return
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ # calculate gradient coefficients
+ col2 = self._style.GetSecondColour()
+ col1 = self._style.GetFirstColour()
+
+ r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+ r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+ flrect = float(rect.height)
+
+ rstep = float((r2 - r1)) / flrect
+ gstep = float((g2 - g1)) / flrect
+ bstep = float((b2 - b1)) / flrect
+
+ rf, gf, bf = 0, 0, 0
+
+ for y in range(rect.y, rect.y + rect.height):
+ currCol = (r1 + rf, g1 + gf, b1 + bf)
+
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.DrawRectangle(rect.x, rect.y + (y - rect.y), rect.width, rect.height)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+
+ def DrawHorizontalGradient(self, dc, rect):
+ """
+ Gradient fill from colour 1 to colour 2 from left to right.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the :class:`CaptionBar` client rectangle.
+ """
+
+ if rect.height < 1 or rect.width < 1:
+ return
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ # calculate gradient coefficients
+ col2 = self._style.GetSecondColour()
+ col1 = self._style.GetFirstColour()
+
+ r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+ r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+ flrect = float(rect.width)
+
+ rstep = float((r2 - r1)) / flrect
+ gstep = float((g2 - g1)) / flrect
+ bstep = float((b2 - b1)) / flrect
+
+ rf, gf, bf = 0, 0, 0
+
+ for x in range(rect.x, rect.x + rect.width):
+ currCol = (r1 + rf, g1 + gf, b1 + bf)
+
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.DrawRectangle(rect.x + (x - rect.x), rect.y, 1, rect.height)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+
+ def DrawSingleColour(self, dc, rect):
+ """
+ Single colour fill for :class:`CaptionBar`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the :class:`CaptionBar` client rectangle.
+ """
+
+ if rect.height < 1 or rect.width < 1:
+ return
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ # draw simple rectangle
+ dc.SetBrush(wx.Brush(self._style.GetFirstColour(), wx.SOLID))
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+
+ def DrawSingleRectangle(self, dc, rect):
+ """
+ Single rectangle for :class:`CaptionBar`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the :class:`CaptionBar` client rectangle.
+ """
+
+ if rect.height < 2 or rect.width < 1:
+ return
+
+ # single frame, set up internal fill colour
+
+ if self._style.GetCaptionStyle() == CAPTIONBAR_RECTANGLE:
+ colour = self.GetParent().GetBackgroundColour()
+ br = wx.Brush(colour, wx.SOLID)
+ else:
+ colour = self._style.GetFirstColour()
+ br = wx.Brush(colour, wx.SOLID)
+
+ # setup the pen frame
+
+ pen = wx.Pen(self._style.GetSecondColour())
+ dc.SetPen(pen)
+ dc.SetBrush(br)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height - 1)
+
+ bgpen = wx.Pen(self.GetParent().GetBackgroundColour())
+ dc.SetPen(bgpen)
+ dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width,
+ rect.y + rect.height - 1)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`CaptionBar`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ if not self._controlCreated:
+ event.Skip()
+ return
+
+ size = event.GetSize()
+
+ if self._foldIcons:
+
+ # What I am doing here is simply invalidating the part of the window
+ # exposed. So when I make a rect with as width the newly exposed part,
+ # and the x,y of the old window size origin, I don't need a bitmap
+ # calculation in it, or do I ? The bitmap needs redrawing anyway.
+ # Leave it like this until I figured it out.
+
+ # set rect to redraw as old bitmap area which is entitled to redraw
+
+ rect = wx.Rect(size.GetWidth() - self._iconWidth - self._rightIndent, 0,
+ self._iconWidth + self._rightIndent,
+ self._iconWidth + self._rightIndent)
+
+ # adjust rectangle when more is slided so we need to redraw all
+ # the old stuff but not all (ugly flickering)
+
+ diffX = size.GetWidth() - self._oldSize.GetWidth()
+
+ if diffX > 1:
+
+ # adjust the rect with all the crap to redraw
+
+ rect.SetWidth(rect.GetWidth() + diffX + 10)
+ rect.SetX(rect.GetX() - diffX - 10)
+
+ self.RefreshRect(rect)
+
+ else:
+
+ rect = self.GetRect()
+ self.RefreshRect(rect)
+
+ self._oldSize = size
+
+
+ def RedrawIconBitmap(self):
+ """ Redraws the icons (if they exists). """
+
+ if self._foldIcons:
+
+ # invalidate the bitmap area and force a redraw
+
+ rect = self.GetRect()
+
+ rect.SetX(rect.GetWidth() - self._iconWidth - self._rightIndent)
+ rect.SetWidth(self._iconWidth + self._rightIndent)
+ self.RefreshRect(rect)
+
+
+# ---------------------------------------------------------------------------------- #
+# class FoldPanelBar
+# ---------------------------------------------------------------------------------- #
+
+class FoldPanelBar(wx.Panel):
+ """
+ The :class:`FoldPanelBar` is a class which can maintain a list of
+ collapsible panels. Once a panel is collapsed, only it's caption
+ bar is visible to the user. This will provide more space for the
+ other panels, or allow the user to close panels which are not used
+ often to get the most out of the work area.
+
+ This control is easy to use. Simply create it as a child for a
+ panel or sash window, and populate panels with
+ :meth:`FoldPanelBar.AddFoldPanel() <FoldPanelBar.AddFoldPanel>`. Then use the
+ :meth:`FoldPanelBar.AddFoldPanelWindow() <FoldPanelBar.AddFoldPanelWindow>` to add
+ :class:`Window` derived controls to the current fold panel. Use
+ :meth:`FoldPanelBar.AddFoldPanelSeparator() <FoldPanelBar.AddFoldPanelSeparator>` to put separators between the groups of
+ controls that need a visual separator to group them
+ together. After all is constructed, the user can fold the panels
+ by double clicking on the bar or single click on the arrow, which
+ will indicate the collapsed or expanded state.
+ """
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.TAB_TRAVERSAL|wx.NO_BORDER, agwStyle=0):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`FoldPanelBar` parent window;
+ :param `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`Panel` window style;
+ :param `agwStyle`: the AGW-specific :class:`FoldPanelBar` window style. It can be one of the
+ following bits:
+
+ ========================== =========== ==================================================
+ Window Styles Hex Value Description
+ ========================== =========== ==================================================
+ ``FPB_SINGLE_FOLD`` 0x1 Single fold forces other panels to close when they are open, and only opens the current panel. This will allow the open panel to gain the full size left in the client area.
+ ``FPB_COLLAPSE_TO_BOTTOM`` 0x2 All panels are stacked to the bottom. When they are expanded again they show up at the top.
+ ``FPB_EXCLUSIVE_FOLD`` 0x4 ``FPB_SINGLE_FOLD`` style plus the panels will be stacked at the bottom.
+ ``FPB_HORIZONTAL`` 0x4 :class:`FoldPanelBar` will be horizontal.
+ ``FPB_VERTICAL`` 0x8 :class:`FoldPanelBar` will be vertical.
+ ========================== =========== ==================================================
+ """
+
+ self._controlCreated = False
+
+ # make sure there is any orientation
+ if not agwStyle & (FPB_HORIZONTAL | FPB_VERTICAL):
+ agwStyle = agwStyle | FPB_VERTICAL
+
+ if agwStyle & FPB_HORIZONTAL:
+ self._isVertical = False
+ else:
+ self._isVertical = True
+
+ self._agwStyle = agwStyle
+
+ # create the panel (duh!). This causes a size event, which we are going
+ # to skip when we are not initialised
+
+ wx.Panel.__init__(self, parent, id, pos, size, style)
+
+ # the fold panel area
+
+ self._foldPanel = wx.Panel(self, wx.ID_ANY, pos, size,
+ wx.NO_BORDER | wx.TAB_TRAVERSAL)
+
+ self._controlCreated = True
+ self._panels = []
+
+ self.Bind(EVT_CAPTIONBAR, self.OnPressCaption)
+ self.Bind(wx.EVT_SIZE, self.OnSizePanel)
+
+
+ def AddFoldPanel(self, caption="", collapsed=False, foldIcons=None, cbstyle=None):
+ """
+ Adds a fold panel to the list of panels.
+
+ :param `caption`: the caption to be displayed in the associated :class:`CaptionBar`;
+ :param `collapsed`: if set to ``True``, the panel is collapsed initially;
+ :param `foldIcons`: an instance of :class:`ImageList` containing the icons to display
+ next to the caption text;
+ :param `cbstyle`: an instance of :class:`CaptionBarStyle`.
+
+ :note: The FoldPanel item which is returned, can be used as a reference to perform
+ actions upon the fold panel like collapsing it, expanding it, or deleting it
+ from the list. Use this foldpanel to add windows to it.
+
+ :see: :meth:`~FoldPanelBar.AddFoldPanelWindow` and :meth:`~FoldPanelBar.AddFoldPanelSeparator` to see how to add
+ items derived from :class:`Window` to the panels.
+ """
+
+ if cbstyle is None:
+ cbstyle = EmptyCaptionBarStyle
+
+ # create a fold panel item, which is first only the caption.
+ # the user can now add a panel area which will be folded in
+ # when pressed.
+
+ if foldIcons is None:
+ foldIcons = wx.ImageList(16, 16)
+
+ bmp = ExpandedIcon.GetBitmap()
+ foldIcons.Add(bmp)
+ bmp = CollapsedIcon.GetBitmap()
+ foldIcons.Add(bmp)
+
+ item = FoldPanelItem(self._foldPanel, -1, caption=caption,
+ foldIcons=foldIcons,
+ collapsed=collapsed, cbstyle=cbstyle)
+
+ pos = 0
+ if len(self._panels) > 0:
+ pos = self._panels[-1].GetItemPos() + self._panels[-1].GetPanelLength()
+
+ item.Reposition(pos)
+ self._panels.append(item)
+
+ return item
+
+
+ def AddFoldPanelWindow(self, panel, window, flags=FPB_ALIGN_WIDTH,
+ spacing=FPB_DEFAULT_SPACING,
+ leftSpacing=FPB_DEFAULT_LEFTLINESPACING,
+ rightSpacing=FPB_DEFAULT_RIGHTLINESPACING):
+ """
+ Adds a :class:`Window` derived instance to the referenced fold panel.
+
+ :param `panel`: an instance of :class:`FoldPanelItem`;
+ :param `window`: the window we wish to add to the fold panel, an instance
+ of :class:`Window`;
+ :param `flags`: can be one of the following bits:
+
+ ====================== ======= ====================================
+ Align Flag Value Description
+ ====================== ======= ====================================
+ ``FPB_ALIGN_WIDTH`` 1 The :class:`Window` to be added will be aligned to fit the width of the FoldPanel when it is resized. Very handy for sizer items, buttons and text boxes.
+ ``FPB_ALIGN_LEFT`` 0 Aligns left instead of fitting the width of the child window to be added. Use either this one or ``FPB_ALIGN_WIDTH``.
+ ====================== ======= ====================================
+
+ :param `spacing`: the :class:`Window` to be added can be slightly indented from
+ left and right so it is more visibly placed in the fold panel. Use `spacing` > 0
+ to give the control an y offset from the previous :class:`Window` added;
+ :param `leftSpacing`: give the :class:`Window` added a slight indent from the left;
+ :param `rightSpacing`: give the :class:`Window` added a slight indent from the right;
+
+ :note: Make the window be a child of the fold panel!
+
+ The following example adds a FoldPanel to the :class:`FoldPanelBar` and
+ adds two :class:`Window` derived controls to the FoldPanel::
+
+ # Create the FoldPanelBar
+ m_pnl = FoldPanelBar(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, agwStyle=0x2)
+
+ # Add a foldpanel to the control. "Test me" is the caption and it is
+ # initially not collapsed.
+ item = m_pnl.AddFoldPanel("Test me", False)
+
+ # Now add a button to the fold panel. Mind that the button should be
+ # made child of the FoldPanel and not of the main form.
+ m_pnl.AddFoldPanelWindow(item, wx.Button(item, ID_COLLAPSEME, "Collapse Me"))
+
+ # Add a separator between the two controls. This is purely a visual
+ # line that can have a certain colour and also the indents and width
+ # aligning like a control.
+ m_pnl.AddFoldPanelSeparator(item)
+
+ # Now add a text ctrl. Also very easy. Align this on width so that
+ # when the control gets wider the text control also sizes along.
+ m_pnl.AddFoldPanelWindow(item, wx.TextCtrl(item, wx.ID_ANY, "Comment"), FPB_ALIGN_WIDTH, FPB_DEFAULT_SPACING, 20)
+
+ """
+
+ try:
+ item = self._panels.index(panel)
+ except:
+ raise Exception("ERROR: Invalid Panel Passed To AddFoldPanelWindow: " + repr(panel))
+
+ panel.AddWindow(window, flags, spacing, leftSpacing, rightSpacing)
+
+ # TODO: Take old and new height, and if difference, reposition all the lower
+ # panels this is because the user can add new wxWindow controls somewhere in
+ # between when other panels are already present.
+
+ return 0
+
+
+ def AddFoldPanelSeparator(self, panel, colour=wx.BLACK,
+ spacing=FPB_DEFAULT_SPACING,
+ leftSpacing=FPB_DEFAULT_LEFTLINESPACING,
+ rightSpacing=FPB_DEFAULT_RIGHTLINESPACING):
+ """
+ Adds a separator line to the current fold panel.
+
+ The separator is a simple line which is drawn and is no real
+ component. It can be used to separate groups of controls
+ which belong to each other.
+
+ :param `colour`: the separator colour, an instance of :class:`Colour`;
+ :param `spacing`: the separator to be added can be slightly indented from
+ left and right so it is more visibly placed in the fold panel. Use `spacing` > 0
+ to give the control an y offset from the previous :class:`Window` added;
+ :param `leftSpacing`: give the added separator a slight indent from the left;
+ :param `rightSpacing`: give the added separator a slight indent from the right.
+ """
+
+ try:
+ item = self._panels.index(panel)
+ except:
+ raise Exception("ERROR: Invalid Panel Passed To AddFoldPanelSeparator: " + repr(panel))
+
+ panel.AddSeparator(colour, spacing, leftSpacing, rightSpacing)
+ return 0
+
+
+ def OnSizePanel(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`FoldPanelBar`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ # skip all stuff when we are not initialised yet
+
+ if not self._controlCreated:
+ event.Skip()
+ return
+
+ foldrect = self.GetRect()
+
+ # fold panel itself. If too little space,
+ # don't show it
+
+ foldrect.SetX(0)
+ foldrect.SetY(0)
+
+ self._foldPanel.SetSize(foldrect[2:])
+
+ if self._agwStyle & FPB_COLLAPSE_TO_BOTTOM or self._agwStyle & FPB_EXCLUSIVE_FOLD:
+ rect = self.RepositionCollapsedToBottom()
+ vertical = self.IsVertical()
+ if vertical and rect.GetHeight() > 0 or not vertical and rect.GetWidth() > 0:
+ self.RefreshRect(rect)
+
+ # TODO: A smart way to check wether the old - new width of the
+ # panel changed, if so no need to resize the fold panel items
+
+ self.RedisplayFoldPanelItems()
+
+
+ def OnPressCaption(self, event):
+ """
+ Handles the ``wx.EVT_CAPTIONBAR`` event for :class:`CaptionBar`.
+
+ :param `event`: a :class:`CaptionBarEvent` event to be processed.
+ """
+
+ # act upon the folding or expanding status of the bar
+ # to expand or collapse the panel(s)
+
+ if event.GetFoldStatus():
+ self.Collapse(event.GetTag())
+ else:
+ self.Expand(event.GetTag())
+
+
+
+ def RefreshPanelsFrom(self, item):
+ """
+ Refreshes all the panels from given one down to last one.
+
+ :param `item`: the first :class:`FoldPanelItem` to be refreshed.
+ """
+
+ try:
+ i = self._panels.index(item)
+ except:
+ raise Exception("ERROR: Invalid Panel Passed To RefreshPanelsFrom: " + repr(item))
+
+ self.Freeze()
+
+ # if collapse to bottom is on, the panels that are not expanded
+ # should be drawn at the bottom. All panels that are expanded
+ # are drawn on top. The last expanded panel gets all the extra space
+
+ if self._agwStyle & FPB_COLLAPSE_TO_BOTTOM or self._agwStyle & FPB_EXCLUSIVE_FOLD:
+
+ offset = 0
+
+ for panels in self._panels:
+
+ if panels.IsExpanded():
+ offset = offset + panels.Reposition(offset)
+
+ # put all non collapsed panels at the bottom where there is space,
+ # else put them right behind the expanded ones
+
+ self.RepositionCollapsedToBottom()
+
+ else:
+
+ pos = self._panels[i].GetItemPos() + self._panels[i].GetPanelLength()
+ for j in range(i+1, len(self._panels)):
+ pos = pos + self._panels[j].Reposition(pos)
+
+ self.Thaw()
+
+
+ def RedisplayFoldPanelItems(self):
+ """ Resizes the fold panels so they match the width. """
+
+ # resize them all. No need to reposition
+ for panels in self._panels:
+ panels.ResizePanel()
+ panels.Refresh()
+
+
+ def RepositionCollapsedToBottom(self):
+ """
+ Repositions all the collapsed panels to the bottom.
+
+ When it is not possible to align them to the bottom, stick them behind
+ the visible panels.
+ """
+
+ value = wx.Rect(0,0,0,0)
+ vertical = self.IsVertical()
+
+ # determine wether the number of panels left
+ # times the size of their captions is enough
+ # to be placed in the left over space
+
+ expanded = 0
+ collapsed = 0
+ collapsed, expanded, values = self.GetPanelsLength(collapsed, expanded)
+
+ # if no room stick them behind the normal ones, else
+ # at the bottom
+
+ if (vertical and [self.GetSize().GetHeight()] or \
+ [self.GetSize().GetWidth()])[0] - expanded - collapsed < 0:
+ offset = expanded
+ else:
+
+ # value is the region which is left unpainted
+ # I will send it back as 'slack' so it does not need to
+ # be recalculated.
+
+ value.SetHeight(self.GetSize().GetHeight())
+ value.SetWidth(self.GetSize().GetWidth())
+
+ if vertical:
+ value.SetY(expanded)
+ value.SetHeight(value.GetHeight() - expanded)
+ else:
+ value.SetX(expanded)
+ value.SetWidth(value.GetWidth() - expanded)
+
+ offset = (vertical and [self.GetSize().GetHeight()] or \
+ [self.GetSize().GetWidth()])[0] - collapsed
+
+
+ # go reposition
+
+ for panels in self._panels:
+ if not panels.IsExpanded():
+ offset = offset + panels.Reposition(offset)
+
+ return value
+
+
+ def GetPanelsLength(self, collapsed, expanded):
+ """
+ Returns the length of the panels that are expanded and
+ collapsed.
+
+ :param `collapsed`: the current value of the collapsed panels;
+ :param `expanded`: the current value of the expanded panels.
+
+ :note: This is useful to determine quickly what size is used to display,
+ and what is left at the bottom (right) to align the collapsed panels.
+ """
+
+ value = 0
+
+ # assumed here that all the panels that are expanded
+ # are positioned after each other from 0,0 to end.
+
+ for j in range(0, len(self._panels)):
+ offset = self._panels[j].GetPanelLength()
+ value = value + offset
+ if self._panels[j].IsExpanded():
+ expanded = expanded + offset
+ else:
+ collapsed = collapsed + offset
+
+ return collapsed, expanded, value
+
+
+ def Collapse(self, foldpanel):
+ """
+ Collapses the given fold panel reference, and updates the foldpanel bar.
+
+ :param `foldpanel`: an instance of :class:`FoldPanelItem`.
+
+ :note: With the ``FPB_COLLAPSE_TO_BOTTOM`` style set, all collapsed captions
+ are put at the bottom of the control. In the normal mode, they stay where
+ they are.
+ """
+
+ try:
+ item = self._panels.index(foldpanel)
+ except:
+ raise Exception("ERROR: Invalid Panel Passed To Collapse: " + repr(foldpanel))
+
+ foldpanel.Collapse()
+ self.RefreshPanelsFrom(foldpanel)
+
+
+ def Expand(self, foldpanel):
+ """
+ Expands the given fold panel reference, and updates the foldpanel bar.
+
+ :param `foldpanel`: an instance of :class:`FoldPanelItem`.
+
+ :note: With the ``FPB_COLLAPSE_TO_BOTTOM`` style set, they will be removed
+ from the bottom and the order where the panel originally was placed is
+ restored.
+ """
+
+ fpbextrastyle = 0
+
+ if self._agwStyle & FPB_SINGLE_FOLD or self._agwStyle & FPB_EXCLUSIVE_FOLD:
+ fpbextrastyle = 1
+ for panel in self._panels:
+ panel.Collapse()
+
+ foldpanel.Expand()
+
+ if fpbextrastyle:
+ if self._agwStyle & FPB_EXCLUSIVE_FOLD:
+ self.RepositionCollapsedToBottom()
+ self.RefreshPanelsFrom(self._panels[0])
+ else:
+ self.RefreshPanelsFrom(foldpanel)
+
+
+ def ApplyCaptionStyle(self, foldpanel, cbstyle):
+ """
+ Sets the style of the caption bar (:class:`CaptionBar`) of the fold panel.
+
+ :param `foldpanel`: an instance of :class:`FoldPanelItem`;
+ :param `cbstyle`: an instance of :class:`CaptionBarStyle`.
+
+ :note:
+
+ The changes are applied immediately. All styles not set in the
+ :class:`CaptionBarStyle` class are not applied. Use the :class:`CaptionBar` reference
+ to indicate what captionbar you want to apply the style to. To apply one
+ style to all :class:`CaptionBar` items, use :meth:`~FoldPanelBar.ApplyCaptionStyleAll`.
+ """
+
+ foldpanel.ApplyCaptionStyle(cbstyle)
+
+
+ def ApplyCaptionStyleAll(self, cbstyle):
+ """
+ Sets the style of all the caption bars of the fold panel.
+ The changes are applied immediately.
+
+ :param `cbstyle`: an instance of :class:`CaptionBarStyle`.
+ """
+
+ for panels in self._panels:
+ self.ApplyCaptionStyle(panels, cbstyle)
+
+
+ def GetCaptionStyle(self, foldpanel):
+ """
+ Returns the currently used caption style for the fold panel.
+
+ It is returned as a :class:`CaptionBarStyle` class. After modifying it, it can
+ be set again.
+
+ :param `foldpanel`: an instance of :class:`FoldPanelItem`.
+ """
+
+ return foldpanel.GetCaptionStyle()
+
+
+ def IsVertical(self):
+ """
+ Returns whether the :class:`CaptionBar` has default orientation or not.
+ Default is vertical.
+ """
+
+ return self._isVertical
+
+
+ def GetFoldPanel(self, item):
+ """
+ Returns the panel associated with the index `item`.
+
+ :param `item`: an integer representing the :class:`FoldPanelItem` in the list of
+ panels in this :class:`FoldPanelBar`.
+ """
+
+ try:
+ ind = self._panels[item]
+ return self._panels[item]
+ except:
+ raise Exception("ERROR: List Index Out Of Range Or Bad Item Passed: " + repr(item) + \
+ ". Item Should Be An Integer Between " + repr(0) + " And " + \
+ repr(len(self._panels)))
+
+
+ def GetCount(self):
+ """ Returns the number of panels in the :class:`FoldPanelBar`. """
+
+ try:
+ return len(self._panels)
+ except:
+ raise Exception("ERROR: No Panels Have Been Added To FoldPanelBar")
+
+
+
+# --------------------------------------------------------------------------------- #
+# class FoldPanelItem
+# --------------------------------------------------------------------------------- #
+
+class FoldPanelItem(wx.Panel):
+ """
+ This class is a child sibling of the :class:`FoldPanelBar` class. It will
+ contain a :class:`CaptionBar` class for receiving of events, and a the
+ rest of the area can be populated by a :class:`Panel` derived class.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, caption="", foldIcons=None,
+ collapsed=False, cbstyle=None):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`FoldPanelItem` parent window;
+ :param `id`: an identifier for the control: a value of -1 is taken to mean a default;
+ :param `caption`: the string to be displayed in :class:`CaptionBar`;
+ :param `foldIcons`: an instance of :class:`ImageList` containing the icons to display
+ next to the caption text;
+ :param `collapsed`: ``True`` if the :class:`CaptionBar` should start in the collapsed state,
+ ``False`` otherwise;
+ :param `cbstyle`: the :class:`CaptionBar` window style. Must be an instance of
+ :class:`CaptionBarStyle`.
+ """
+
+ wx.Panel.__init__(self, parent, id, wx.Point(0,0), style=wx.CLIP_CHILDREN)
+ self._controlCreated = False
+ self._UserSize = 0
+ self._PanelSize = 0
+ self._LastInsertPos = 0
+ self._itemPos = 0
+ self._userSized = False
+
+ if foldIcons is None:
+ foldIcons = wx.ImageList(16, 16)
+
+ bmp = ExpandedIcon.GetBitmap()
+ foldIcons.Add(bmp)
+ bmp = CollapsedIcon.GetBitmap()
+ foldIcons.Add(bmp)
+
+ self._foldIcons = foldIcons
+ if cbstyle is None:
+ cbstyle = EmptyCaptionBarStyle
+
+ # create the caption bar, in collapsed or expanded state
+
+ self._captionBar = CaptionBar(self, wx.ID_ANY, wx.Point(0,0),
+ size=wx.DefaultSize, caption=caption,
+ foldIcons=foldIcons, cbstyle=cbstyle)
+
+ if collapsed:
+ self._captionBar.Collapse()
+
+ self._controlCreated = True
+
+ # make initial size for component, if collapsed, the
+ # size is determined on the panel height and won't change
+
+ size = self._captionBar.GetSize()
+
+ self._PanelSize = (self.IsVertical() and [size.GetHeight()] or \
+ [size.GetWidth()])[0]
+
+ self._LastInsertPos = self._PanelSize
+ self._items = []
+
+ self.Bind(EVT_CAPTIONBAR, self.OnPressCaption)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def AddWindow(self, window, flags=FPB_ALIGN_WIDTH, spacing=FPB_DEFAULT_SPACING,
+ leftSpacing=FPB_DEFAULT_LEFTLINESPACING,
+ rightSpacing=FPB_DEFAULT_RIGHTLINESPACING):
+ """
+ Adds a window item to the list of items on this panel.
+
+ :param `window`: an instance of :class:`Window`;
+ :param `flags`: can be one of the following bits:
+
+ ====================== ======= ====================================
+ Align Flag Value Description
+ ====================== ======= ====================================
+ ``FPB_ALIGN_WIDTH`` 1 The :class:`Window` to be added will be aligned to fit the width of the FoldPanel when it is resized. Very handy for sizer items, buttons and text boxes.
+ ``FPB_ALIGN_LEFT`` 0 Aligns left instead of fitting the width of the child window to be added. Use either this one or ``FPB_ALIGN_WIDTH``.
+ ====================== ======= ====================================
+
+ :param `spacing`: reserves a number of pixels before the window element;
+ :param `leftSpacing`: an indent, in pixels;
+ :param `rightSpacing`: a right spacing, only relevant when the style
+ ``FPB_ALIGN_WIDTH`` is chosen.
+ """
+
+ wi = FoldWindowItem(self, window, Type="WINDOW", flags=flags, spacing=spacing,
+ leftSpacing=leftSpacing, rightSpacing=rightSpacing)
+
+ self._items.append(wi)
+
+ vertical = self.IsVertical()
+
+ self._spacing = spacing
+ self._leftSpacing = leftSpacing
+ self._rightSpacing = rightSpacing
+
+ xpos = (vertical and [leftSpacing] or [self._LastInsertPos + spacing])[0]
+ ypos = (vertical and [self._LastInsertPos + spacing] or [leftSpacing])[0]
+
+ window.SetDimensions(xpos, ypos, -1, -1, wx.SIZE_USE_EXISTING)
+
+ self._LastInsertPos = self._LastInsertPos + wi.GetWindowLength(vertical)
+ self.ResizePanel()
+
+
+ def AddSeparator(self, colour=wx.BLACK, spacing=FPB_DEFAULT_SPACING,
+ leftSpacing=FPB_DEFAULT_LEFTSPACING,
+ rightSpacing=FPB_DEFAULT_RIGHTSPACING):
+ """
+ Adds a separator item to the list of items on this panel.
+
+ :param `colour`: the separator colour, an instance of :class:`Colour`;
+ :param `spacing`: the separator to be added can be slightly indented from
+ left and right so it is more visibly placed in the fold panel. Use `spacing` > 0
+ to give the control an y offset from the previous :class:`Window` added;
+ :param `leftSpacing`: give the added separator a slight indent from the left;
+ :param `rightSpacing`: give the added separator a slight indent from the right.
+ """
+
+ wi = FoldWindowItem(self, window=None, Type="SEPARATOR",
+ flags=FPB_ALIGN_WIDTH, y=self._LastInsertPos,
+ colour=colour, spacing=spacing, leftSpacing=leftSpacing,
+ rightSpacing=rightSpacing)
+
+ self._items.append(wi)
+ self._LastInsertPos = self._LastInsertPos + \
+ wi.GetWindowLength(self.IsVertical())
+
+ self.ResizePanel()
+
+
+ def Reposition(self, pos):
+ """
+ Repositions this :class:`FoldPanelItem` and reports the length occupied
+ for the next :class:`FoldPanelItem` in the list.
+
+ :param `pos`: the new item position.
+ """
+
+ # NOTE: Call Resize before Reposition when an item is added, because the new
+ # size needed will be calculated by Resize. Of course the relative position
+ # of the controls have to be correct in respect to the caption bar
+
+ self.Freeze()
+
+ vertical = self.IsVertical()
+ xpos = (vertical and [-1] or [pos])[0]
+ ypos = (vertical and [pos] or [-1])[0]
+
+ self.SetDimensions(xpos, ypos, -1, -1, wx.SIZE_USE_EXISTING)
+ self._itemPos = pos
+
+ self.Thaw()
+
+ return self.GetPanelLength()
+
+
+ def OnPressCaption(self, event):
+ """
+ Handles the ``wx.EVT_CAPTIONBAR`` event for :class:`FoldPanelItem`.
+
+ :param `event`: a :class:`CaptionBarEvent` event to be processed.
+ """
+
+ # tell the upper container we are responsible
+ # for this event, so it can fold the panel item
+ # and do a refresh
+
+ event.SetTag(self)
+ event.Skip()
+
+
+ def ResizePanel(self):
+ """ Resizes the panel. """
+
+ # prevent unnecessary updates by blocking repaints for a sec
+
+ self.Freeze()
+
+ vertical = self.IsVertical()
+ # force this panel to take the width of the parent panel and the y of the
+ # user or calculated width (which will be recalculated by the contents here)
+
+
+ if self._captionBar.IsCollapsed():
+ size = self._captionBar.GetSize()
+ self._PanelSize = (vertical and [size.GetHeight()] or [size.GetWidth()])[0]
+ else:
+ size = self.GetBestSize()
+ self._PanelSize = (vertical and [size.GetHeight()] or [size.GetWidth()])[0]
+
+ if self._UserSize:
+ if vertical:
+ size.SetHeight(self._UserSize)
+ else:
+ size.SetWidth(self._UserSize)
+
+ pnlsize = self.GetParent().GetSize()
+
+ if vertical:
+ size.SetWidth(pnlsize.GetWidth())
+ else:
+ size.SetHeight(pnlsize.GetHeight())
+
+ # resize caption bar
+ xsize = (vertical and [size.GetWidth()] or [-1])[0]
+ ysize = (vertical and [-1] or [size.GetHeight()])[0]
+
+ self._captionBar.SetSize((xsize, ysize))
+
+ # resize the panel
+ self.SetSize(size)
+
+ # go by all the controls and call Layout
+
+ for items in self._items:
+ items.ResizeItem((vertical and [size.GetWidth()] or \
+ [size.GetHeight()])[0], vertical)
+
+ self.Thaw()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`FoldPanelItem`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ # draw all the items that are lines
+
+ dc = wx.PaintDC(self)
+ vertical = self.IsVertical()
+
+ for item in self._items:
+
+ if item.GetType() == "SEPARATOR":
+ pen = wx.Pen(item.GetLineColour(), 1, wx.SOLID)
+ dc.SetPen(pen)
+ a = item.GetLeftSpacing()
+ b = item.GetLineY() + item.GetSpacing()
+ c = item.GetLineLength()
+ d = a + c
+
+ if vertical:
+ dc.DrawLine(a, b, d, b)
+ else:
+ dc.DrawLine(b, a, b, d)
+
+ event.Skip()
+
+
+ def IsVertical(self):
+ """
+ Returns whether the :class:`CaptionBar` has default orientation or not.
+ Default is vertical.
+ """
+
+ # grandparent of FoldPanelItem is FoldPanelBar
+ # default is vertical
+
+ if isinstance(self.GetGrandParent(), FoldPanelBar):
+ return self.GetGrandParent().IsVertical()
+ else:
+ raise Exception("ERROR: Wrong Parent " + repr(self.GetGrandParent()))
+
+
+ def IsExpanded(self):
+ """
+ Returns expanded or collapsed status. If the panel is
+ expanded, ``True`` is returned.
+ """
+
+ return not self._captionBar.IsCollapsed()
+
+
+ def GetItemPos(self):
+ """ Returns item's position. """
+
+ return self._itemPos
+
+
+ def Collapse(self):
+ """
+ Internal method.
+
+ This should not be called by the user, because it doesn't trigger the
+ parent to tell it that we are collapsed or expanded, it only changes
+ visual state.
+ """
+
+ self._captionBar.Collapse()
+ self.ResizePanel()
+
+
+ def Expand(self):
+ """
+ Internal method.
+
+ This should not be called by the user, because it doesn't trigger the
+ parent to tell it that we are collapsed or expanded, it only changes
+ visual state.
+ """
+
+ self._captionBar.Expand()
+ self.ResizePanel()
+
+
+ def GetPanelLength(self):
+ """ Returns size of panel. """
+
+ if self._captionBar.IsCollapsed():
+ return self.GetCaptionLength()
+ elif self._userSized:
+ return self._UserSize
+
+ return self._PanelSize
+
+
+ def GetCaptionLength(self):
+ """ Returns height of caption only. This is for folding calculation purposes. """
+
+ size = self._captionBar.GetSize()
+ return (self.IsVertical() and [size.GetHeight()] or [size.GetWidth()])[0]
+
+
+ def ApplyCaptionStyle(self, cbstyle):
+ """ Applies the style defined in `cbstyle` to the :class:`CaptionBar`."""
+
+ self._captionBar.SetCaptionStyle(cbstyle)
+
+
+ def GetCaptionStyle(self):
+ """
+ Returns the current style of the captionbar in a :class:`CaptionBarStyle` class.
+
+ This can be used to change and set back the changes.
+ """
+
+ return self._captionBar.GetCaptionStyle()
+
+
+# ----------------------------------------------------------------------------------- #
+# class FoldWindowItem
+# ----------------------------------------------------------------------------------- #
+
+class FoldWindowItem(object):
+ """
+ This class is a child sibling of the :class:`FoldPanelItem` class. It
+ will contain :class:`Window` that can be either a separator (a coloured
+ line simulated by a :class:`Window`) or a wxPython controls (such as a
+ :class:`Button`, a :class:`ListCtrl` etc...).
+ """
+
+ def __init__(self, parent, window=None, **kw):
+ """
+ Default class constructor
+
+ :param `parent`: the :class:`FoldWindowItem` parent;
+ :param `window`: the window contained in this item.
+
+ :keyword `Type`: can be "WINDOW" or "SEPARATOR";
+ :keyword `lineColour`: the separator colour (meaningful for separators only);
+ :keyword `y`: the separator y position (meaningful for separators only);
+ :keyword `flags`: the alignment flags;
+ :keyword `spacing`: reserves a number of pixels before the window/separator element;
+ :keyword `leftSpacing`: an indent, in pixels;
+ :keyword `rightSpacing`: a right spacing, only relevant when the style
+ ``FPB_ALIGN_WIDTH`` is chosen.
+
+ :see: :meth:`FoldPanelBar.AddFoldPanelWindow() <FoldPanelBar.AddFoldPanelWindow>` for a list of valid alignment flags.
+ """
+
+ if not kw.has_key("Type"):
+ raise Exception('ERROR: Missing Window Type Information. This Should Be "WINDOW" Or "SEPARATOR"')
+
+ if kw.get("Type") == "WINDOW":
+ # Window constructor. This initialises the class as a wx.Window Type
+
+ if kw.has_key("flags"):
+ self._flags = kw.get("flags")
+ else:
+ self._flags = FPB_ALIGN_WIDTH
+ if kw.has_key("spacing"):
+ self._spacing = kw.get("spacing")
+ else:
+ self._spacing = FPB_DEFAULT_SPACING
+ if kw.has_key("leftSpacing"):
+ self._leftSpacing = kw.get("leftSpacing")
+ else:
+ self._leftSpacing = FPB_DEFAULT_LEFTSPACING
+ if kw.has_key("rightSpacing"):
+ self._rightSpacing = kw.get("rightSpacing")
+ else:
+ self._rightSpacing = FPB_DEFAULT_RIGHTSPACING
+
+ self._lineY = 0
+ self._sepLineColour = None
+ self._wnd = window
+
+
+ elif kw.get("Type") == "SEPARATOR":
+ # separator constructor. This initialises the class as a separator type
+
+ if kw.has_key("y"):
+ self._lineY = kw.get("y")
+ else:
+ raise Exception("ERROR: Undefined Y Position For The Separator")
+ if kw.has_key("lineColour"):
+ self._sepLineColour = kw.get("lineColour")
+ else:
+ self._sepLineColour = wx.BLACK
+ if kw.has_key("flags"):
+ self._flags = kw.get("flags")
+ else:
+ self._flags = FPB_ALIGN_WIDTH
+ if kw.has_key("spacing"):
+ self._spacing = kw.get("spacing")
+ else:
+ self._spacing = FPB_DEFAULT_SPACING
+ if kw.has_key("leftSpacing"):
+ self._leftSpacing = kw.get("leftSpacing")
+ else:
+ self._leftSpacing = FPB_DEFAULT_LEFTSPACING
+ if kw.has_key("rightSpacing"):
+ self._rightSpacing = kw.get("rightSpacing")
+ else:
+ self._rightSpacing = FPB_DEFAULT_RIGHTSPACING
+
+ self._wnd = window
+
+ else:
+ raise Exception("ERROR: Undefined Window Type Selected: " + repr(kw.get("Type")))
+
+ self._type = kw.get("Type")
+ self._lineLength = 0
+
+
+ def GetType(self):
+ """ Returns the :class:`FoldWindowItem` type. """
+
+ return self._type
+
+
+ def GetLineY(self):
+ """ Returns the y position of the separator. """
+
+ return self._lineY
+
+
+ def GetLineLength(self):
+ """ Returns the separator line length. """
+
+ return self._lineLength
+
+
+ def GetLineColour(self):
+ """ Returns the separator line colour. """
+
+ return self._sepLineColour
+
+
+ def GetLeftSpacing(self):
+ """ Returns the left indent of :class:`FoldWindowItem`. """
+
+ return self._leftSpacing
+
+
+ def GetRightSpacing(self):
+ """ Returns the right indent of :class:`FoldWindowItem`. """
+
+ return self._rightSpacing
+
+
+ def GetSpacing(self):
+ """ Returns the spacing of :class:`FoldWindowItem`. """
+
+ return self._spacing
+
+
+ def GetWindowLength(self, vertical=True):
+ """
+ Returns space needed by the window if type is :class:`FoldWindowItem`
+ "WINDOW" and returns the total size plus the extra spacing.
+
+ :param `vertical`: ``True`` if the parent :class:`FoldPanelBar` is in vertical
+ mode.
+ """
+
+ value = 0
+ if self._type == "WINDOW":
+ size = self._wnd.GetSize()
+ value = (vertical and [size.GetHeight()] or [size.GetWidth()])[0] + \
+ self._spacing
+
+ elif self._type == "SEPARATOR":
+ value = 1 + self._spacing
+
+ return value
+
+
+ def ResizeItem(self, size, vertical=True):
+ """
+ Resizes the element, whatever it is.
+
+ A separator or line will be always aligned by width or height
+ depending on orientation of the whole panel.
+
+ :param `size`: the maximum size available for the :class:`FoldWindowItem`;
+ :param `vertical`: ``True`` if the parent :class:`FoldPanelBar` is in vertical
+ mode.
+ """
+
+ if self._flags & FPB_ALIGN_WIDTH:
+ # align by taking full width
+ mySize = size - self._leftSpacing - self._rightSpacing
+
+ if mySize < 0:
+ mySize = 10 # can't have negative width
+
+ if self._type == "SEPARATOR":
+ self._lineLength = mySize
+ else:
+ xsize = (vertical and [mySize] or [-1])[0]
+ ysize = (vertical and [-1] or [mySize])[0]
+
+ self._wnd.SetSize((xsize, ysize))
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fourwaysplitter.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fourwaysplitter.py
new file mode 100644
index 0000000..b9000bc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/fourwaysplitter.py
@@ -0,0 +1,1101 @@
+# --------------------------------------------------------------------------------- #
+# FOURWAYSPLITTER wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 03 Nov 2006
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# TODO List
+#
+# 1. Any idea?
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@maerskoil.com
+# andrea.gavana@gmail.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`FourWaySplitter` is a layout manager which manages 4 children like 4 panes in a
+window.
+
+
+Description
+===========
+
+The :class:`FourWaySplitter` is a layout manager which manages four children like four
+panes in a window. You can use a four-way splitter for example in a CAD program
+where you may want to maintain three orthographic views, and one oblique view of
+a model.
+
+The :class:`FourWaySplitter` allows interactive repartitioning of the panes by
+means of moving the central splitter bars. When the :class:`FourWaySplitter` is itself
+resized, each child is proportionally resized, maintaining the same split-percentage.
+
+The main characteristics of :class:`FourWaySplitter` are:
+
+- Handles horizontal, vertical or four way sizing via the sashes;
+- Delayed or live update when resizing;
+- Possibility to swap windows;
+- Setting the vertical and horizontal split fractions;
+- Possibility to expand a window by hiding the onther 3.
+
+And a lot more. See the demo for a complete review of the functionalities.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.fourwaysplitter as fws
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "FourWaySplitter Demo")
+
+ splitter = fws.FourWaySplitter(self, -1, agwStyle=wx.SP_LIVE_UPDATE)
+
+ # Put in some coloured panels...
+ for colour in [wx.RED, wx.WHITE, wx.BLUE, wx.GREEN]:
+
+ panel = wx.Panel(splitter)
+ panel.SetBackgroundColour(colour)
+
+ splitter.AppendWindow(panel)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`FourWaySplitter` has been tested on the following platforms:
+ * Windows (Windows XP);
+ * Linux Ubuntu (Dapper 6.06)
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+================== =========== ==================================================
+Window Styles Hex Value Description
+================== =========== ==================================================
+``SP_NOSASH`` 0x10 No sash will be drawn on :class:`FourWaySplitter`.
+``SP_LIVE_UPDATE`` 0x80 Don't draw XOR line but resize the child windows immediately.
+``SP_3DBORDER`` 0x200 Draws a 3D effect border.
+================== =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================================== ==================================================
+Event Name Description
+================================== ==================================================
+``EVT_SPLITTER_SASH_POS_CHANGED`` The sash position was changed. This event is generated after the user releases the mouse after dragging the splitter. Processes a ``wx.wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED`` event.
+``EVT_SPLITTER_SASH_POS_CHANGING`` The sash position is in the process of being changed. You may prevent this change from happening by calling `Veto` or you may also modify the position of the tracking bar to properly reflect the position that would be set if the drag were to be completed at this point. Processes a ``wx.wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING`` event.
+================================== ==================================================
+
+
+License And Version
+===================
+
+:class:`FourWaySplitter` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.4
+
+"""
+
+__docformat__ = "epytext"
+
+
+import wx
+
+_RENDER_VER = (2,6,1,1)
+
+# Tolerance for mouse shape and sizing
+_TOLERANCE = 5
+
+# Modes
+NOWHERE = 0
+""" No sashes are changing position. """
+FLAG_CHANGED = 1
+""" Sashes are changing position. """
+FLAG_PRESSED = 2
+""" Sashes are in a pressed state. """
+
+# FourWaySplitter styles
+SP_NOSASH = wx.SP_NOSASH
+""" No sash will be drawn on :class:`FourWaySplitter`. """
+SP_LIVE_UPDATE = wx.SP_LIVE_UPDATE
+""" Don't draw XOR line but resize the child windows immediately. """
+SP_3DBORDER = wx.SP_3DBORDER
+""" Draws a 3D effect border. """
+
+# FourWaySplitter events
+EVT_SPLITTER_SASH_POS_CHANGING = wx.EVT_SPLITTER_SASH_POS_CHANGING
+""" The sash position is in the process of being changed. You may prevent this change""" \
+""" from happening by calling `Veto` or you may also modify the position of the tracking""" \
+""" bar to properly reflect the position that would be set if the drag were to be""" \
+""" completed at this point. Processes a ``wx.wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING`` event."""
+EVT_SPLITTER_SASH_POS_CHANGED = wx.EVT_SPLITTER_SASH_POS_CHANGED
+""" The sash position was changed. This event is generated after the user releases the""" \
+""" mouse after dragging the splitter. Processes a ``wx.wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED`` event. """
+
+# ---------------------------------------------------------------------------- #
+# Class FourWaySplitterEvent
+# ---------------------------------------------------------------------------- #
+
+class FourWaySplitterEvent(wx.PyCommandEvent):
+ """
+ This event class is almost the same as :class:`SplitterEvent` except
+ it adds an accessor for the sash index that is being changed. The
+ same event type IDs and event binders are used as with
+ :class:`SplitterEvent`.
+ """
+
+ def __init__(self, evtType=wx.wxEVT_NULL, splitter=None):
+ """
+ Default class constructor.
+
+ :param `evtType`: the event type;
+ :param `splitter`: the associated :class:`FourWaySplitter` window.
+ """
+
+ wx.PyCommandEvent.__init__(self, evtType)
+
+ if splitter:
+ self.SetEventObject(splitter)
+ self.SetId(splitter.GetId())
+
+ self.sashIdx = -1
+ self.sashPos = -1
+ self.isAllowed = True
+
+
+ def SetSashIdx(self, idx):
+ """
+ Sets the index of the sash currently involved in the event.
+
+ :param `idx`: an integer between 0 and 3, representing the index of the
+ sash involved in the event.
+ """
+
+ self.sashIdx = idx
+
+
+ def SetSashPosition(self, pos):
+ """
+ In the case of ``EVT_SPLITTER_SASH_POS_CHANGED`` events, sets the new sash
+ position. In the case of ``EVT_SPLITTER_SASH_POS_CHANGING`` events, sets
+ the new tracking bar position so visual feedback during dragging will represent
+ that change that will actually take place. Set to -1 from the event handler
+ code to prevent repositioning.
+
+ :param `pos`: the new sash position.
+
+ :note: May only be called while processing ``EVT_SPLITTER_SASH_POS_CHANGING``
+ and ``EVT_SPLITTER_SASH_POS_CHANGED`` events.
+ """
+
+ self.sashPos = pos
+
+
+ def GetSashIdx(self):
+ """ Returns the index of the sash currently involved in the event. """
+
+ return self.sashIdx
+
+
+ def GetSashPosition(self):
+ """
+ Returns the new sash position.
+
+ :note: May only be called while processing ``EVT_SPLITTER_SASH_POS_CHANGING``
+ and ``EVT_SPLITTER_SASH_POS_CHANGED`` events.
+ """
+
+ return self.sashPos
+
+
+ # methods from wx.NotifyEvent
+ def Veto(self):
+ """
+ Prevents the change announced by this event from happening.
+
+ :note: It is in general a good idea to notify the user about the reasons
+ for vetoing the change because otherwise the applications behaviour (which
+ just refuses to do what the user wants) might be quite surprising.
+ """
+
+ self.isAllowed = False
+
+
+ def Allow(self):
+ """
+ This is the opposite of :meth:`~FourWaySplitterEvent.Veto`: it explicitly allows the event to be processed.
+ For most events it is not necessary to call this method as the events are
+ allowed anyhow but some are forbidden by default (this will be mentioned
+ in the corresponding event description).
+ """
+
+ self.isAllowed = True
+
+
+ def IsAllowed(self):
+ """
+ Returns ``True`` if the change is allowed (:meth:`~FourWaySplitterEvent.Veto` hasn't been called) or
+ ``False`` otherwise (if it was).
+ """
+
+ return self.isAllowed
+
+
+# ---------------------------------------------------------------------------- #
+# Class FourWaySplitter
+# ---------------------------------------------------------------------------- #
+
+class FourWaySplitter(wx.PyPanel):
+ """
+ This class is very similar to :class:`SplitterWindow` except that it
+ allows for four windows and two sashes. Many of the same styles,
+ constants, and methods behave the same as in :class:`SplitterWindow`.
+ However, in addition of the ability to drag the vertical and the
+ horizontal sash, by dragging at the intersection between the two
+ sashes, it is possible to resize the four windows at the same time.
+
+ :note: These things are not yet supported:
+
+ * Minimum pane size (minimum of what? Width? Height?);
+ * Using negative sash positions to indicate a position offset from the end;
+ * User controlled unsplitting with double clicks on the sash (but supported via the
+ :meth:`FourWaySplitter.SetExpanded() <FourWaySplitter.SetExpanded>` method);
+ * Sash gravity.
+
+
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, agwStyle=0, name="FourWaySplitter"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`PyPanel` window style;
+ :param `agwStyle`: the AGW-specific window style. It can be a combination of the
+ following bits:
+
+ ================== =========== ==================================================
+ Window Styles Hex Value Description
+ ================== =========== ==================================================
+ ``SP_NOSASH`` 0x10 No sash will be drawn on :class:`FourWaySplitter`.
+ ``SP_LIVE_UPDATE`` 0x80 Don't draw XOR line but resize the child windows immediately.
+ ``SP_3DBORDER`` 0x200 Draws a 3D effect border.
+ ================== =========== ==================================================
+
+ :param `name`: the window name.
+ """
+
+ # always turn on tab traversal
+ style |= wx.TAB_TRAVERSAL
+
+ # and turn off any border styles
+ style &= ~wx.BORDER_MASK
+ style |= wx.BORDER_NONE
+
+ self._agwStyle = agwStyle
+
+ # initialize the base class
+ wx.PyPanel.__init__(self, parent, id, pos, size, style, name)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ self._windows = []
+
+ self._splitx = 0
+ self._splity = 0
+ self._expanded = -1
+ self._fhor = 5000
+ self._fver = 5000
+ self._offx = 0
+ self._offy = 0
+ self._mode = NOWHERE
+ self._flags = 0
+ self._isHot = False
+
+ self._sashTrackerPen = wx.Pen(wx.BLACK, 2, wx.SOLID)
+
+ self._sashCursorWE = wx.StockCursor(wx.CURSOR_SIZEWE)
+ self._sashCursorNS = wx.StockCursor(wx.CURSOR_SIZENS)
+ self._sashCursorSIZING = wx.StockCursor(wx.CURSOR_SIZING)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnterWindow)
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the :class:`FourWaySplitter` window style flags.
+
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ ================== =========== ==================================================
+ Window Styles Hex Value Description
+ ================== =========== ==================================================
+ ``SP_NOSASH`` 0x10 No sash will be drawn on :class:`FourWaySplitter`.
+ ``SP_LIVE_UPDATE`` 0x80 Don't draw XOR line but resize the child windows immediately.
+ ``SP_3DBORDER`` 0x200 Draws a 3D effect border.
+ ================== =========== ==================================================
+ """
+
+ self._agwStyle = agwStyle
+ self.Refresh()
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`FourWaySplitter` window style.
+
+ :see: :meth:`~FourWaySplitter.SetAGWWindowStyleFlag` for a list of possible window styles.
+ """
+
+ return self._agwStyle
+
+
+ def AppendWindow(self, window):
+ """
+ Add a new window to the splitter at the right side or bottom
+ of the window stack.
+
+ :param `window`: an instance of :class:`Window`.
+ """
+
+ self.InsertWindow(len(self._windows), window)
+
+
+ def InsertWindow(self, idx, window, sashPos=-1):
+ """
+ Insert a new window into the splitter at the position given in `idx`.
+
+ :param `idx`: the index at which the window will be inserted;
+ :param `window`: an instance of :class:`Window`;
+ :param `sashPos`: the sash position after the window insertion.
+ """
+
+ assert window not in self._windows, "A window can only be in the splitter once!"
+
+ self._windows.insert(idx, window)
+
+ self._SizeWindows()
+
+
+ def DetachWindow(self, window):
+ """
+ Removes the window from the stack of windows managed by the splitter. The
+ window will still exist so you should `Hide` or `Destroy` it as needed.
+
+ :param `window`: an instance of :class:`Window`.
+ """
+
+ assert window in self._windows, "Unknown window!"
+
+ idx = self._windows.index(window)
+ del self._windows[idx]
+
+ self._SizeWindows()
+
+
+ def ReplaceWindow(self, oldWindow, newWindow):
+ """
+ Replaces `oldWindow` (which is currently being managed by the
+ splitter) with `newWindow`. The `oldWindow` window will still
+ exist so you should `Hide` or `Destroy` it as needed.
+
+ :param `oldWindow`: an instance of :class:`Window`;
+ :param `newWindow`: another instance of :class:`Window`.
+ """
+
+ assert oldWindow in self._windows, "Unknown window!"
+
+ idx = self._windows.index(oldWindow)
+ self._windows[idx] = newWindow
+
+ self._SizeWindows()
+
+
+ def ExchangeWindows(self, window1, window2):
+ """
+ Trade the positions in the splitter of the two windows.
+
+ :param `window1`: an instance of :class:`Window`;
+ :param `window2`: another instance of :class:`Window`.
+ """
+
+ assert window1 in self._windows, "Unknown window!"
+ assert window2 in self._windows, "Unknown window!"
+
+ idx1 = self._windows.index(window1)
+ idx2 = self._windows.index(window2)
+ self._windows[idx1] = window2
+ self._windows[idx2] = window1
+
+ if "__WXMSW__" in wx.Platform:
+ self.Freeze()
+
+ self._SizeWindows()
+
+ if "__WXMSW__" in wx.Platform:
+ self.Thaw()
+
+
+ def GetWindow(self, idx):
+ """
+ Returns the window at the index `idx`.
+
+ :param `idx`: the index at which the window is located.
+ """
+
+ if len(self._windows) > idx:
+ return self._windows[idx]
+
+ return None
+
+ # Get top left child
+ def GetTopLeft(self):
+ """ Returns the top left window (window index: 0). """
+
+ return self.GetWindow(0)
+
+
+ # Get top right child
+ def GetTopRight(self):
+ """ Returns the top right window (window index: 1). """
+
+ return self.GetWindow(1)
+
+
+ # Get bottom left child
+ def GetBottomLeft(self):
+ """ Returns the bottom left window (window index: 2). """
+
+ return self.GetWindow(2)
+
+
+ # Get bottom right child
+ def GetBottomRight(self):
+ """ Returns the bottom right window (window index: 3). """
+
+ return self.GetWindow(3)
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ if not self._windows:
+ # something is better than nothing...
+ return wx.Size(10, 10)
+
+ width = height = 0
+ border = self._GetBorderSize()
+
+ tl = self.GetTopLeft()
+ tr = self.GetTopRight()
+ bl = self.GetBottomLeft()
+ br = self.GetBottomRight()
+
+ for win in self._windows:
+ w, h = win.GetEffectiveMinSize()
+ width += w
+ height += h
+
+ if tl and tr:
+ width += self._GetSashSize()
+
+ if bl and br:
+ height += self._GetSashSize()
+
+ return wx.Size(width+2*border, height+2*border)
+
+
+ # Recompute layout
+ def _SizeWindows(self):
+ """
+ Recalculate the layout based on split positions and split fractions.
+
+ :see: :meth:`~FourWaySplitter.SetHSplit` and :meth:`~FourWaySplitter.SetVSplit` for more information about split fractions.
+ """
+
+ win0 = self.GetTopLeft()
+ win1 = self.GetTopRight()
+ win2 = self.GetBottomLeft()
+ win3 = self.GetBottomRight()
+
+ width, height = self.GetSize()
+ barSize = self._GetSashSize()
+ border = self._GetBorderSize()
+
+ if self._expanded < 0:
+ totw = width - barSize - 2*border
+ toth = height - barSize - 2*border
+ self._splitx = (self._fhor*totw)/10000
+ self._splity = (self._fver*toth)/10000
+ rightw = totw - self._splitx
+ bottomh = toth - self._splity
+ if win0:
+ win0.SetDimensions(0, 0, self._splitx, self._splity)
+ win0.Show()
+ if win1:
+ win1.SetDimensions(self._splitx + barSize, 0, rightw, self._splity)
+ win1.Show()
+ if win2:
+ win2.SetDimensions(0, self._splity + barSize, self._splitx, bottomh)
+ win2.Show()
+ if win3:
+ win3.SetDimensions(self._splitx + barSize, self._splity + barSize, rightw, bottomh)
+ win3.Show()
+
+ else:
+
+ if self._expanded < len(self._windows):
+ for ii, win in enumerate(self._windows):
+ if ii == self._expanded:
+ win.SetDimensions(0, 0, width-2*border, height-2*border)
+ win.Show()
+ else:
+ win.Hide()
+
+
+ # Determine split mode
+ def GetMode(self, pt):
+ """
+ Determines the split mode for :class:`FourWaySplitter`.
+
+ :param `pt`: the point at which the mouse has been clicked, an instance of
+ :class:`Point`.
+
+ :return: One of the following 3 split modes:
+
+ ================= ==============================
+ Split Mode Description
+ ================= ==============================
+ ``wx.HORIZONTAL`` the user has clicked on the horizontal sash
+ ``wx.VERTICAL`` The user has clicked on the vertical sash
+ ``wx.BOTH`` The user has clicked at the intersection between the 2 sashes
+ ================= ==============================
+
+ """
+
+ barSize = self._GetSashSize()
+ flag = wx.BOTH
+
+ if pt.x < self._splitx - _TOLERANCE:
+ flag &= ~wx.VERTICAL
+
+ if pt.y < self._splity - _TOLERANCE:
+ flag &= ~wx.HORIZONTAL
+
+ if pt.x >= self._splitx + barSize + _TOLERANCE:
+ flag &= ~wx.VERTICAL
+
+ if pt.y >= self._splity + barSize + _TOLERANCE:
+ flag &= ~wx.HORIZONTAL
+
+ return flag
+
+
+ # Move the split intelligently
+ def MoveSplit(self, x, y):
+ """
+ Moves the split accordingly to user action.
+
+ :param `x`: the new splitter `x` coordinate;
+ :param `y`: the new splitter `y` coordinate.
+ """
+
+ width, height = self.GetSize()
+ barSize = self._GetSashSize()
+
+ if x < 0: x = 0
+ if y < 0: y = 0
+ if x > width - barSize: x = width - barSize
+ if y > height - barSize: y = height - barSize
+
+ self._splitx = x
+ self._splity = y
+
+
+ # Adjust layout
+ def AdjustLayout(self):
+ """
+ Adjust layout of :class:`FourWaySplitter`. Mainly used to recalculate the
+ correct values for split fractions.
+ """
+
+ width, height = self.GetSize()
+ barSize = self._GetSashSize()
+ border = self._GetBorderSize()
+
+ self._fhor = (width > barSize and \
+ [(10000*self._splitx+(width-barSize-1))/(width-barSize)] \
+ or [0])[0]
+
+ self._fver = (height > barSize and \
+ [(10000*self._splity+(height-barSize-1))/(height-barSize)] \
+ or [0])[0]
+
+ self._SizeWindows()
+
+
+ # Button being pressed
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`FourWaySplitter`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ pt = event.GetPosition()
+ self.CaptureMouse()
+ self._mode = self.GetMode(pt)
+
+ if self._mode:
+ self._offx = pt.x - self._splitx
+ self._offy = pt.y - self._splity
+ if not self.GetAGWWindowStyleFlag() & wx.SP_LIVE_UPDATE:
+ self.DrawSplitter(wx.ClientDC(self))
+ self.DrawTrackSplitter(self._splitx, self._splity)
+
+ self._flags |= FLAG_PRESSED
+
+
+ # Button being released
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`FourWaySplitter`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+ flgs = self._flags
+
+ self._flags &= ~FLAG_CHANGED
+ self._flags &= ~FLAG_PRESSED
+
+ if flgs & FLAG_PRESSED:
+
+ if not self.GetAGWWindowStyleFlag() & wx.SP_LIVE_UPDATE:
+ self.DrawTrackSplitter(self._splitx, self._splity)
+ self.DrawSplitter(wx.ClientDC(self))
+ self.AdjustLayout()
+
+ if flgs & FLAG_CHANGED:
+ event = FourWaySplitterEvent(wx.wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, self)
+ event.SetSashIdx(self._mode)
+ event.SetSashPosition(wx.Point(self._splitx, self._splity))
+ self.GetEventHandler().ProcessEvent(event)
+
+ self._mode = NOWHERE
+
+
+ def OnLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`FourWaySplitter`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.SetCursor(wx.STANDARD_CURSOR)
+ self._RedrawIfHotSensitive(False)
+
+
+ def OnEnterWindow(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`FourWaySplitter`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self._RedrawIfHotSensitive(True)
+
+
+ def _RedrawIfHotSensitive(self, isHot):
+ """
+ Used internally. Redraw the splitter if we are using a hot-sensitive splitter.
+
+ :param `isHot`: ``True`` if the splitter is in a hot state, ``False`` otherwise.
+ """
+
+ if not wx.VERSION >= _RENDER_VER:
+ return
+
+ if wx.RendererNative.Get().GetSplitterParams(self).isHotSensitive:
+ self._isHot = isHot
+ dc = wx.ClientDC(self)
+ self.DrawSplitter(dc)
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`FourWaySplitter`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.HasFlag(wx.SP_NOSASH):
+ return
+
+ pt = event.GetPosition()
+
+ # Moving split
+ if self._flags & FLAG_PRESSED:
+
+ oldsplitx = self._splitx
+ oldsplity = self._splity
+
+ if self._mode == wx.BOTH:
+ self.MoveSplit(pt.x - self._offx, pt.y - self._offy)
+
+ elif self._mode == wx.VERTICAL:
+ self.MoveSplit(pt.x - self._offx, self._splity)
+
+ elif self._mode == wx.HORIZONTAL:
+ self.MoveSplit(self._splitx, pt.y - self._offy)
+
+ # Send a changing event
+ if not self.DoSendChangingEvent(wx.Point(self._splitx, self._splity)):
+ self._splitx = oldsplitx
+ self._splity = oldsplity
+ return
+
+ if oldsplitx != self._splitx or oldsplity != self._splity:
+ if not self.GetAGWWindowStyleFlag() & wx.SP_LIVE_UPDATE:
+ self.DrawTrackSplitter(oldsplitx, oldsplity)
+ self.DrawTrackSplitter(self._splitx, self._splity)
+ else:
+ self.AdjustLayout()
+
+ self._flags |= FLAG_CHANGED
+
+ # Change cursor based on position
+ ff = self.GetMode(pt)
+
+ if ff == wx.BOTH:
+ self.SetCursor(self._sashCursorSIZING)
+
+ elif ff == wx.VERTICAL:
+ self.SetCursor(self._sashCursorWE)
+
+ elif ff == wx.HORIZONTAL:
+ self.SetCursor(self._sashCursorNS)
+
+ else:
+ self.SetCursor(wx.STANDARD_CURSOR)
+
+ event.Skip()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`FourWaySplitter`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.PaintDC(self)
+ self.DrawSplitter(dc)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`FourWaySplitter`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ parent = wx.GetTopLevelParent(self)
+ if parent.IsIconized():
+ event.Skip()
+ return
+
+ self._SizeWindows()
+
+
+ def DoSendChangingEvent(self, pt):
+ """
+ Sends a ``EVT_SPLITTER_SASH_POS_CHANGING`` event.
+
+ :param `pt`: the point at which the splitter is being positioned.
+ """
+
+ # send the event
+ event = FourWaySplitterEvent(wx.wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, self)
+ event.SetSashIdx(self._mode)
+ event.SetSashPosition(pt)
+
+ if self.GetEventHandler().ProcessEvent(event) and not event.IsAllowed():
+ # the event handler vetoed the change or missing event.Skip()
+ return False
+ else:
+ # or it might have changed the value
+ return True
+
+
+ def _GetSashSize(self):
+ """ Used internally. """
+
+ if self.HasFlag(wx.SP_NOSASH):
+ return 0
+
+ if wx.VERSION >= _RENDER_VER:
+ return wx.RendererNative.Get().GetSplitterParams(self).widthSash
+ else:
+ return 5
+
+
+ def _GetBorderSize(self):
+ """ Used internally. """
+
+ if wx.VERSION >= _RENDER_VER:
+ return wx.RendererNative.Get().GetSplitterParams(self).border
+ else:
+ return 0
+
+
+ # Draw the horizontal split
+ def DrawSplitter(self, dc):
+ """
+ Actually draws the sashes.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ backColour = self.GetBackgroundColour()
+ dc.SetBrush(wx.Brush(backColour, wx.SOLID))
+ dc.SetPen(wx.Pen(backColour))
+ dc.Clear()
+
+ if wx.VERSION >= _RENDER_VER:
+ if self.HasFlag(wx.SP_3DBORDER):
+ wx.RendererNative.Get().DrawSplitterBorder(
+ self, dc, self.GetClientRect())
+ else:
+ barSize = self._GetSashSize()
+
+ # if we are not supposed to use a sash then we're done.
+ if self.HasFlag(wx.SP_NOSASH):
+ return
+
+ flag = 0
+ if self._isHot:
+ flag = wx.CONTROL_CURRENT
+
+ width, height = self.GetSize()
+
+ if self._mode & wx.VERTICAL:
+ if wx.VERSION >= _RENDER_VER:
+ wx.RendererNative.Get().DrawSplitterSash(self, dc,
+ self.GetClientSize(),
+ self._splitx, wx.VERTICAL, flag)
+ else:
+ dc.DrawRectangle(self._splitx, 0, barSize, height)
+
+ if self._mode & wx.HORIZONTAL:
+ if wx.VERSION >= _RENDER_VER:
+ wx.RendererNative.Get().DrawSplitterSash(self, dc,
+ self.GetClientSize(),
+ self._splity, wx.VERTICAL, flag)
+ else:
+ dc.DrawRectangle(0, self._splity, width, barSize)
+
+
+ def DrawTrackSplitter(self, x, y):
+ """
+ Draws a fake sash in case we don't have ``wx.SP_LIVE_UPDATE`` style.
+
+ :param `x`: the `x` position of the sash;
+ :param `y`: the `y` position of the sash.
+
+ :note: This method relies on :class:`ScreenDC` which is currently unavailable on wxMac.
+ """
+
+ # Draw a line to represent the dragging sash, for when not
+ # doing live updates
+ w, h = self.GetClientSize()
+ dc = wx.ScreenDC()
+
+ dc.SetLogicalFunction(wx.INVERT)
+ dc.SetPen(self._sashTrackerPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ if self._mode == wx.VERTICAL:
+ x1 = x
+ y1 = 2
+ x2 = x
+ y2 = h-2
+ if x1 > w:
+ x1 = w
+ x2 = w
+ elif x1 < 0:
+ x1 = 0
+ x2 = 0
+
+ x1, y1 = self.ClientToScreenXY(x1, y1)
+ x2, y2 = self.ClientToScreenXY(x2, y2)
+
+ dc.DrawLine(x1, y1, x2, y2)
+ dc.SetLogicalFunction(wx.COPY)
+
+ elif self._mode == wx.HORIZONTAL:
+
+ x1 = 2
+ y1 = y
+ x2 = w-2
+ y2 = y
+ if y1 > h:
+ y1 = h
+ y2 = h
+ elif y1 < 0:
+ y1 = 0
+ y2 = 0
+
+ x1, y1 = self.ClientToScreenXY(x1, y1)
+ x2, y2 = self.ClientToScreenXY(x2, y2)
+
+ dc.DrawLine(x1, y1, x2, y2)
+ dc.SetLogicalFunction(wx.COPY)
+
+ elif self._mode == wx.BOTH:
+
+ x1 = 2
+ x2 = w-2
+ y1 = y
+ y2 = y
+
+ x1, y1 = self.ClientToScreenXY(x1, y1)
+ x2, y2 = self.ClientToScreenXY(x2, y2)
+
+ dc.DrawLine(x1, y1, x2, y2)
+
+ x1 = x
+ x2 = x
+ y1 = 2
+ y2 = h-2
+
+ x1, y1 = self.ClientToScreenXY(x1, y1)
+ x2, y2 = self.ClientToScreenXY(x2, y2)
+
+ dc.DrawLine(x1, y1, x2, y2)
+ dc.SetLogicalFunction(wx.COPY)
+
+
+ # Change horizontal split [fraction*10000]
+ def SetHSplit(self, s):
+ """
+ Change horizontal split fraction.
+
+ :param `s`: the split fraction, which is an integer value between 0 and
+ 10000 (inclusive), indicating how much space to allocate to the leftmost
+ panes. For example, to split the panes at 35 percent, use::
+
+ fourSplitter.SetHSplit(3500)
+
+ """
+
+ if s < 0: s = 0
+ if s > 10000: s =10000
+ if s != self._fhor:
+ self._fhor = s
+ self._SizeWindows()
+
+
+ # Change vertical split [fraction*10000]
+ def SetVSplit(self, s):
+ """
+ Change vertical split fraction.
+
+ :param `s`: the split fraction, which is an integer value between 0 and
+ 10000 (inclusive), indicating how much space to allocate to the topmost
+ panes. For example, to split the panes at 35 percent, use::
+
+ fourSplitter.SetVSplit(3500)
+
+ """
+
+ if s < 0: s = 0
+ if s > 10000: s =10000
+ if s != self._fver:
+ self._fver = s
+ self._SizeWindows()
+
+
+ # Expand one or all of the four panes
+ def SetExpanded(self, expanded):
+ """
+ This method is used to expand one of the four window to fill the
+ whole client size (when `expanded` >= 0) or to return to the four-window
+ view (when `expanded` < 0).
+
+ :param `expanded`: an integer >= 0 to expand a window to fill the whole
+ client size, or an integer < 0 to return to the four-window view.
+ """
+
+ if expanded >= 4:
+ raise Exception("ERROR: SetExpanded: index out of range: %d"%expanded)
+
+ if self._expanded != expanded:
+ self._expanded = expanded
+ self._SizeWindows()
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/genericmessagedialog.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/genericmessagedialog.py
new file mode 100644
index 0000000..027f11d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/genericmessagedialog.py
@@ -0,0 +1,1586 @@
+# --------------------------------------------------------------------------------- #
+# GENERICMESSAGEDIALOG wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 07 October 2008
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# TODO List
+#
+# 1) ?
+#
+#
+# For all kind of problems, requests of enhancements and bug reports, please
+# write to me at:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, obviously, to the wxPython mailing list!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+This class is a possible, fancy replacement for :class:`MessageDialog`.
+
+
+Description
+===========
+
+This class represents a dialog that shows a single or multi-line message,
+with a choice of ``OK``, ``Yes``, ``No``, ``Cancel`` and ``Help`` buttons. It is a possible
+replacement for the standard :class:`MessageDialog`, with these extra functionalities:
+
+* Possibility to modify the dialog position;
+* Custom themed generic bitmap & text buttons;
+* Support for normal and extended message (in different fonts);
+* Custom labels for the ``OK``, ``Yes``, ``No``, ``Cancel`` and ``Help`` buttons;
+* Custom icons for the ``OK``, ``Yes``, ``No``, ``Cancel`` and ``Help`` buttons;
+* Possibility to set an icon to the dialog;
+* More visibility to the button getting the focus;
+* Support for Aqua buttons or Gradient buttons instead of themed ones (see :class:`AquaButton`
+ and :class:`GradientButton`);
+* Possibility to automatically wrap long lines of text;
+* Good old Python code :-D .
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.genericmessagedialog as GMD
+
+ # Our normal wxApp-derived class, as usual
+ app = wx.App(0)
+
+ main_message = "Hello world! I am the main message."
+
+ dlg = GMD.GenericMessageDialog(None, main_message, "A Nice Message Box",
+ agwStyle=wx.ICON_INFORMATION|wx.OK)
+
+ dlg.ShowModal()
+ dlg.Destroy()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`GenericMessageDialog` has been tested on the following platforms:
+ * Windows (Windows XP).
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+=========================== =========== ==================================================
+Window Styles Hex Value Description
+=========================== =========== ==================================================
+``GMD_DEFAULT`` 0x0 Uses generic buttons.
+``GMD_USE_AQUABUTTONS`` 0x20 Uses :mod:`lib.agw.aquabutton` buttons instead of generic buttons.
+``GMD_USE_GRADIENTBUTTONS`` 0x40 Uses :mod:`lib.agw.gradientbutton` buttons instead of generic buttons.
+=========================== =========== ==================================================
+
+The styles above are mutually exclusive. The style chosen above can be combined with a
+bitlist containing flags chosen from the following:
+
+=========================== =========== ==================================================
+Window Styles Hex Value Description
+=========================== =========== ==================================================
+``wx.OK`` 0x4 Shows an ``OK`` button.
+``wx.CANCEL`` 0x10 Shows a ``Cancel`` button.
+``wx.YES_NO`` 0xA Show ``Yes`` and ``No`` buttons.
+``wx.YES_DEFAULT`` 0x0 Used with ``wx.YES_NO``, makes ``Yes`` button the default - which is the default behaviour.
+``wx.NO_DEFAULT`` 0x80 Used with ``wx.YES_NO``, makes ``No`` button the default.
+``wx.ICON_EXCLAMATION`` 0x100 Shows an exclamation mark icon.
+``wx.ICON_HAND`` 0x200 Shows an error icon.
+``wx.ICON_ERROR`` 0x200 Shows an error icon - the same as ``wx.ICON_HAND``.
+``wx.ICON_QUESTION`` 0x400 Shows a question mark icon.
+``wx.ICON_INFORMATION`` 0x800 Shows an information icon.
+=========================== =========== ==================================================
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`GenericMessageDialog` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.7
+
+"""
+
+import wx
+import wx.lib.wordwrap as wordwrap
+
+import wx.lib.buttons as buttons
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+# To use AquaButtons or GradientButtons instead of wx.lib.buttons
+import aquabutton as AB
+import gradientbutton as GB
+
+# GenericMessageDialog styles
+GMD_DEFAULT = 0
+""" Uses generic buttons. """
+GMD_USE_AQUABUTTONS = 32
+""" Uses :mod:`lib.agw.aquabutton` buttons instead of generic buttons. """
+GMD_USE_GRADIENTBUTTONS = 64
+""" Uses :mod:`lib.agw.gradientbutton` buttons instead of generic buttons. """
+
+# Avoid 2.9 errors
+BUTTON_SIZER_FLAGS = wx.OK | wx.CANCEL | wx.YES | wx.NO | wx.HELP | wx.NO_DEFAULT
+""" Flag used to mask the :class:`GenericMessageDialog` AGW-specific style. """
+
+_ = wx.GetTranslation
+
+_cancel = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAA1dJ"
+ "REFUOI11019oEwccB/Dv3eUuyZ2XpfljsmJ7JY01KZYWty6bdMwnp1X34JNS5sPAsmYruOnL"
+ "3kTGcPg6Bdkexqql4EPdBuKbVG0xLmpoWjbW0D+S1Jg24RJzuSR3l58PtpsI/l5/fB5+3x9f"
+ "AEDc7VauhMP3prq7q9+1t5/AW+aiLB+ZDocrU6HQk4tAFAC4s8Gg0uVyXTsZiw190Nsr6JnM"
+ "kZAkrd6rVtOv4wuyfLS/rW3y6Oioq2tgILiRyXy4v1yexU979yaKIyNEiQRRsUjG2Bjddrtr"
+ "532+k9v4B1kevu33l+vnzhFtbBAtL9OLS5douq9v0eZ1OPo8Xi8gSUClAls8jk+qVad148bP"
+ "33s8TcY0K32mOTV07JhsP3UKKJUAy8IORYF3584erodopaGqh7qzWYEJBgGGgW3fPrQ/eyY0"
+ "5uePewzjxIGDB0U5HgcsC1BV0MOH+GtiojF/9+433P1qNd1pGCvs5uawUijwbDAIWBZsAwPw"
+ "5nJsRyBgc8fjYLZwK5lE6uZN88Hc3LdfmeYVDgDu12oLXUSrxvPnw8r6uo3z+cAQwRGJQOzv"
+ "B0sEKhZhJRJI3rplJlKpM+OWdRkAuO2gZnQ93UO02CgUjr9bLHKCzweGZcGYJqhchp5I4NGd"
+ "O9bjpaUvxol+2Xa211/FAKolSa0XySSq+TzYYBAAYGkaUKnA5LgWA6hvmP//PKgokx9tbspq"
+ "Pg8NgL61c0gSJL8f73R04O9KRV9Mp0+PtlrX/zvhgigO749GJ4dKJVc9l0MTgAVAZBg4BQEk"
+ "SeCcTjAAOhWF5/3+w7FsdvkPogXuR7f7s/d6eycPqKqrubKC+hZ28DxydnurzHFWwG5niefB"
+ "CALYVgu7wmGe2toOfby2lrVFIpFrn9brcmNpCU0ALIAdooiMw9FI1etfkmGUbaY5EXY4JIth"
+ "YAIw1tcxODgoEcddZeua9rQqCGB5HgwA0e3GmsdjPtH1s1/Xar+ON5vTi6p6+qmm6U5JAksE"
+ "VhBQbzahl0p57n1Nm9kQxVhXINAucxzSLpeZLBTOxHX98nbAfxItxMrlVV4UD+/q7OTJ58Pc"
+ "7Ow/uVTq81c1FYTo76HQo5k9expXnc6xt9X5OsuOPIhGtZndu//9DYgBwEt1gHq0YITgmAAA"
+ "AABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_error = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAACY9J"
+ "REFUWIWVl1tsXMd9xn8zc87ZXe4ud5dc0qRIWRIp0pJtVRFr15ZFA7kURJsADWwgQJvYSRAg"
+ "gtGg6JvzIpi1nctDU8ZpYqFogMaBm5cETg0DjoM0hl0lRiJaVmxKFiRSsnWxTIqXJbncy7nM"
+ "pQ+7lGTLl3YOPpxz5szM9/0vM2dG8DHlCz//ufrisWN/WQrD2zNCOM/3UZ6HVArZbmMBaxIS"
+ "bdFJQqQUlUxm+v5vfesVhHAfNb74SPbJSfnLixe/uOe22/65u9R1k2xGTqoWuRASIQTgWpez"
+ "WGuwRuPyeTE/d+7tmbfP/cPfPv30rz6KQn3oF+fEf/74xw/sLpW+Pzw80puTKZFWGZHyciJQ"
+ "WeGrDuGrjPC9tPC9QAReIFK+L9KpQKQ9T+Qy6RKLi/feMzo6++zJk3P/Pw84J/79859/cKyv"
+ "719uu/32crrZBA3IAIQPUoGQ7d4OhAU0CAPOgnMQBNSM4eTx4xeOr69/4xvPPff8/80Dk5Ny"
+ "6tvffmBvV9fUntHRcsfqKjSboJMWTAI6Bh21EbYRQRJDkoDW0GwSWEtnuVxMFhcP3NrXN/vb"
+ "8+dv8MT7BYh/ajYf2NfVNXXHzp3lfKUCjQYYA0a3BCRRC1eJw3Zdmzy+7t5okDKGzu7uYrS0"
+ "dO9woTB7ZH5+7sMEiH8cGXnwznLP1F0jI+Xsygo0mwhj0GHIhStXCKwlcK5NFr+XtE28vrbG"
+ "wtISeSlBa3QYooyh2N1daCwujven03PTlcrcewVMTsoHT5164O7u7ql7du8qpysVTBiCMego"
+ "4vdXrnBqyxbmFxYY0LolYpP0OvLK6iovVauc6+ykfukSvUFAojVxGCKtpau7u1i7fPlAJ8ye"
+ "bDTmNgWIu44d+9KBcvn7n9m9u5xaW8OEIc4YkjjmaKVC7qtf5bOHDuEGBnj9xRfpjyIC53Bx"
+ "jEuSFvnaGr93jn2Tk9zzta9xfnWVy9PTlDyPxBjCtojunp7i0uLivc7a2QtxPKfu2blz4jO3"
+ "3PLkJ/v7bwrW1tBtch3HvF6vU/r617n7y19GKkXPjh2YgQH+9NJLlNsDWq1Z2djgj6kUeycn"
+ "2T42hlSKwbExLlarXJ6eJi8lsdaEYQjO0d/fX4izuTtDJV9RA573N/vLPfeX6nURhiHGGKzW"
+ "rFpL4aGHuPMrX0Gqa6nSs2MHdnCQN15+mVKjQbXZ5LV8nk889hjbx8auttsUsVSvE504gdOa"
+ "sC1CWsvy+nr2xPz8Ec/V62J9/l2WMhkC50gDaSFIpdNsLRSQUvL+suvTn0YIwR8OHULkctzx"
+ "+OPcfB35ZvGUYkehwDtxTMNaYudIANtooFdWCIzBywCJtSzGMSlrSQtBBkiFIc3vfAftHIP3"
+ "3QfivWvWLZ/6FP73vkfQ0cHg3r03kDutefenP+Xi4cPEUUQiBIlzJM5hAWUMAeD5QGgsl0lI"
+ "W0sGriK9tET90Ucx1nLz/ffjoLXKtWYtO+7eDzisMddNZgHGcPknP+GtH/yAKAxJgBCIgNA5"
+ "tJRo51CAJ4GmNSw7S4e15IFcGxqwKyscn5zEGcOW++7DGINzH/yDE0KicLz71FOcm5oialse"
+ "OkcNaLQRS4m2tiUAILSWVWsx7UpJa34qQArB6vIyxx95hLBep2tiAj+bvc4T1yxPNjaoPPMM"
+ "53/0I8IwJBGC2DlC52g6RwOoAaGU+O3+ngWiMGS1Vms1EoJOIWgIQVMIckKQFYJGvU7l6acZ"
+ "37OH4tatN3hBSMniuXMc/dnP8FZWcFISW0tsDA3nqDtHzTnWraWhFP2ZDAbwonZcs3GMby0S"
+ "SIA64NrPTaB7bIy7vvlNMjfdRLPZ/MAQdA4Nsevhh/njI49gZ2db/duW19vW14HY94k6OjCA"
+ "6g2C/f2eNxGEoeh0jgJQaOdAFvCBwr59HHj0UbpGR0miGKMNRhu01hitr70nmvyWLeR27uTy"
+ "iROYlZXWbqltzGZo00rhpdP6otbPqqJS+7cGwUQpDEXeOTqBPJAXggDIfmIvf3HoEKXhYZIo"
+ "whiNMRptNLlcDikljXrjWn2SkO3vJzs8zMKbb+KtrpKSkhS01hggoxRhOq3nouhZlfa8/UN+"
+ "MLElDEUW6JCypVAp5J4/Y+/DD1McGiKJIrTWbRg6s1miF17ALS7ibdtGrV7HbH5PEjr6+sgM"
+ "DbF8+jTpjQ0CKfGlJAA6lGIxCPTpJHlW5YvFu/f2909sqVaFBwS+TyAl+d5exh5/DH/bNuIw"
+ "arvcoI2h1NkJL/yKt777Xaq/+x09IyOwbRu1jdrVcCRJQn5ggMGhIeqvvIK0FiUlnpQEqRTL"
+ "ff16No7/S/WWy5JU6pNbhOgqak0gJSnPwzeGcrFIcWyMtXoDnSQYoykXS2R/+98sTE2RiiL8"
+ "MCScnqZnZIRk61aq1SpGGxCCvlRA8otf0Dx9GqUUSkqU77NQKHAqnXqjLsS/qdX19Usrtdpc"
+ "XYjxkWKxWLSWQCkyQpCcOEHBWrJ3/DmrjQY9pRI9R/6H9SeeIIgi0kqRUQo/DNHHjtEzOko4"
+ "MEAjjNiW7cA++SSV558nUApfSqTvM9/ZyW/WN2ZOriw/dHF5+Q0FECbJWef7ZzacGx8pFou9"
+ "xtAhBB1SYt58kxIwOD5O55Ej1H/4Q/w4JuV5pJRqwfNQYYh77TV6d+2ib/s25OHD1H/9awLP"
+ "u0p+KZ/nN9XqzAWdHLxYr0/D+3bFu8vlv77V8w7/XaGwfXuthuccHuBLScfgIHZxERFFKCEQ"
+ "7c6bAzjAWovI5aBYJHznHQyt5TwSkhMdGX65ujpzztqDM5XK0U3O92xKlxuNs34ud2ZB6/Fd"
+ "hUKx39rWFFIKr1olgKuWB9djM8OVQmmNrNXw2jGXnsfJXJZn1tZmLkh58PXl5aPXc96wLb9S"
+ "q531CoUz58NwfFexWNzqXCsxlSKtFCkpW+9S4rcF+O0YX3/32gn3aibDU5XKzLued/DV+fmj"
+ "7+f7wJPRlWr1LF1ds6cajQO3lkrFHdAiVgrP81pnQ99Heh6iDdk+L6pNcs/j5VSKf11enrmS"
+ "Th989dKlG8g/VADA8vr6WVsqnTler4/v7u4u3uz7CM+DILgG3wffx/k+eB7O87Ceh0mleMH3"
+ "eXxhYWY5nz8489ZbH0gOH3c4BYaHh/9qrLf3iX1Cbk/XNlyXEBSAjBAEQuAB2jlioOEcVedI"
+ "iiXxYqN+8rWVlb+fe/vt6Y8a/2MFOOfE5yYm9lbm50eDOKZHKTqVIqcUGVouNEBsDDVg3Rhk"
+ "Pu+yfX0z//Hcc2c+bvz/BZALwYu3Z1YVAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_help = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAtxJ"
+ "REFUOI2lk81LFHEYx5+ZndnWnV0bt8z2TYKpxYsdwpBWA62w2rxIdOgmdPAvCOnqMSiig2SB"
+ "lVmeAhEsJt02SNdcXZXC1HYT3SRWXLd1HHdmduf3ezqUgrjQoef08MDzeZ7v8wLwn8aUCn69"
+ "fNntWl9vsrrdR4pra2lDEN5Xf/qU/ScgMjR09PTjxw/sLS03+YYGFmw2QF0Hc2KisJXL9Sxf"
+ "uNAZDAa1koBIJHJcFMUxKZOR+EwGVhHBQIQT5eVgzedBb26GX6o6kc1mL9XV1eV389hdxzU+"
+ "/tzpdErfnU6IiaIunD+/6Gm5MhkXhLEvXm+6QAiUT02d87W1PTygY76pqT4jipjq6EBZlrfz"
+ "eW1S1/U5TdPnVFWLxuOzTz7L8s5GfT2mRZEkPB7/vg7sq6vXiKLAyswMSNKpJUIIFosUCSEM"
+ "pdQhSVJdQlXDRlUVmIrCWnO5q7sADgCAFgp+k1LQ/X4wjAKqO1qOs7B2lmVtCMBQgmYqlVo+"
+ "K0mAlAItFj37OqAMkzMBwC8IIMvvOGISq6YZRUXVthQlvzX6fnSnoqJiAbNZMAHAtFi29wEM"
+ "QYgQAODDYQj4jqfu37+3MTYeLZuNz1r7XjyHvme9ou3QoY5iNArkT8GP+4Y43dPDL9rtiW+h"
+ "EC7FYnRhYeFee3t7sLa29szw8HAg/ObNYGsohK+fPsXk9etRRNxb/54T6+0NHm5oCPMcZyt2"
+ "dQEbCCBbVbXDpNMOY2AANi9ehLsrK+Dz+e52d3d3lrzE6enpRlc8/pKV5WpEBCQEkFJASqGw"
+ "ubn4qrn5dmxm5lFlZWV/f3//HYZh8MAvDLW22k86HDfsktTEWK3H6Pb2T3V+fvRHIjEYSiYN"
+ "j8cTqKmp+WCxWG6NjIy8LfVMjNvtLlMUxWGapgMRbYhoRUT+79AJAHA8z6e8Xu8mVwKAjY2N"
+ "RiwWo6qqaqZpcoQQy65clmUJx3Gmy+Uykslk4TdmSW8/+y1ZpAAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_information = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAACINJ"
+ "REFUWIWll1uMXVUZgL+19u1c9rnPzJmZzkzb6YVSgdK7gEorWCoID0QeNWJ8gxf0RaKJMcbE"
+ "F19UQkwUiG/6QEJ8oEBoxdhqsRdAqEUovcxMO9Nz5pwz57bPvi4fzp7p6bRIiX/yZ+/s7P//"
+ "v/Vf1l5b8PlEh4eGdX1qwsilR/WEkSeEwA+X/KXWlSC4NAvVKpz0b9WhuLXXDg7nJ++8Z2j9"
+ "2gNj60Z3jI0VJ4uFTDaVMgwUdLqeX6u1W1fmFmcuX5g/dfX87OvtK+8eg0OV/xPgYLY0vf0b"
+ "63fc+b1tOzft3r51wl43niOfNjF0DRlbRwr8IKTRdvlkrsHpf8103jn50dvnT5/9fePSyT/D"
+ "oebnBrDtJ7dO7N37w737dz7+lb2b0lMjWQwpiCJQ6lOcCZASgkhxYb7B4WMfdt4+fOrlS6dP"
+ "/MJrv3jmZjbazfzkyk/t2/r1A7959Jtfffj+3ZvNjJWk5wkcD1wf3AC8m6jrQ88DzxfYySSb"
+ "p8fMwprRba3I3NOqjPzH6564+JkA+aGnv3zHwweef/ix++/eMF6m51wL7AXg+XEgH8IIghC6"
+ "3vXPXa8P4vuSkVKe4Ynymrqn724ulD5YDXEdQMb81uYtjx58bt/BfTuGs0Va7b6jQcduHGhy"
+ "GPZsho3j/TrOVKHTi4PH7zseOC7YyTSFsaGRxW60tXs+ddQL36veBOB+e3r/Iz/bc2D/Y8O5"
+ "IZrNCNdTuL6KIRQ9T9H1oJSFR/YIhrJgJ2BNCa424NwVhRsH7nngeH2bjqtIJlJYeXtNdcmx"
+ "G7ONN2HGA9CXw49uvO+hDbu2P5G3s1QrTVQEQggQAoFAiH6XKSXITxnYCWsFXUoYzQe0Oy6g"
+ "4ia98TqULzK9c9vjjdnZV+szx/44APBgbmzbnU8Oj49la5Umfs9HCEk/vkQIsaJKwXw1gR+Y"
+ "GPq1IVpY7NFsthAClOoHVSiUUqD6V6lJyhPjmfLWLd+pzxx4A16v6QAjU3fvLq1bd5/X9enU"
+ "mqhIIaVASIkUEiEFMgYAwYkzHTaMwle259A1wZnzXV47XqHV6m+AimtBo0ihVBRDKYyURXFy"
+ "6t7C6F176vOvH9IBWdiw7kEjnc1X5iv0Wm2klCsqhByA6Zek2YLfvtzk1WMJTEMys9Cj3Q3j"
+ "1bMSrK8RUaSIoogoitDaOpZtZ7NrJx6oz/O6DgfyyeHRXY7jU1+4Sui6aJoWA2hIKWIQsVIO"
+ "BBi6RrvdWtmUPD+K6x2nP151FCkiFaGiiDCMQECyWMIqDu2CBwq6bU+W9UxuammpQ6NWR4VB"
+ "H0DT0KRcKYOUfQCAcinF9799O2tGUigFjhvw/J/OcvpsFSnEtZUrhYpXPqi+ZqDbmUnbnirr"
+ "meHikLCMXHepi+M4CKXQtOXVywHtA0QKRgo59u0qk0qsDBFH3p7l7+/MoUlWMrBc/+XAYRgR"
+ "RSGi65BMJXNWbqisi1QiH7k9q335DJ3qHHqihG7ZaJpxfS/EjRgpCIJg9QZKFIZ4nosmxXXN"
+ "N1j/ZQjZc0nYKZOEldGFkCFCqaA5gzN3BKVl0FKj6MkR9EShD6Mn0HQDKTUiJfADH1Z9kIIw"
+ "xHU9NE2gouUJCInCkDD0CQOX0GsT9GooL4ud2anQDaV7ftBASldL5kEaKL9N0J4lcBZBSyH0"
+ "NEJPI40UUk+iMGg3zP6oDUiv22apfhVNKFTkE4UeUdAjCrpEfgcVtFBeE8I2CeMLQOiJyFvS"
+ "e61GFUHdygyXNTNHpDqgJUD266siD+VDFPoguhBJ3E6pv8EMiOs06dUug6boG3h9VW5874IK"
+ "EZqFaY+ghF53O+0F2bp8bj7we58kC2MY6TLIBEhr4GqBNEHoIDSIJ+EGURGwrP1tGyFjO6Pv"
+ "Q7PQrDyJwgRKRRdaly8sSDjUdBq144l8kWRxHRip/ssrEKs1BlotQh+wM29i01czO0ayNI7X"
+ "aR2HV5YkQH1u9rBuaZXM+BbM1BAI8zqjFdWWoT4N4GbZi1WYSDODPbIJPZle7FxdeBNQEqBy"
+ "/K+nndbi4cLUNOmRzQg9FUOsBknE/WFww2lO6gOAgzbXspnITZCbvA2/1/lL9cS5UwBxQd/o"
+ "VM99+IKR0iql6btJFiZiwwHVLIRmgKYhpLzhMCmkAKkhNB20ATthgjAw0iXyU3dg5TPVxtyl"
+ "38ELrQEAuHLk8FuN+QsvldaOR8X1OzAzw/3miTMhpN7fioVEIYhWTYFS/ROpiL8hyLjxpIGW"
+ "yJJbs4Xi+umoXVv4Q+WtN44s2w2ciD4Ou9H0v7OTI7fnxtZvCgMTz3EIwwghtdixxLIspGZh"
+ "p5NU6i4fX2ryztkqrxz5hMVGb+UjJIRAIdCtFPnxacq3byEIm6/NnTj1o6DyYm0lc6t7yf7S"
+ "z7duuue+5zRjZN/CR7PUZ87hNGsIFKlUimw2S9q2SSaTJEwThCAIAhynR7fbpdVq0mq1CMMI"
+ "I2WTLU8yvGGSUDWOXjx14qnu0WffHYx3w6nYu3S40k5s+mdmNLe2MDG5wUoNSSk0TEMjZ9vk"
+ "83kKhQKFfIFMNks63YcxTRNdjzNlWFi5IUrrN1HaOB56fuXVmXdPPdP927Pv3TA8qx8sS/Le"
+ "n4yv2bH96eLo+u8KL1mm7WCFLildkE4kSKdSWKaFkALfD3B6Dh3HoesFOGh4CZNA967WFy+9"
+ "dPXU+79y/vHjuZvF+d+/ZlufMEvbD9w7tm7jk7nC6NcKCXu0kEiIgmWQTZqkTAMpBD0/oNnz"
+ "qDku1a6jat3WQq02/2bl4sUXFk+cPsrHv3Y/LcSt/Zx+8ZlkdsOWO4pTU/vz+eLefCY7nUmm"
+ "iglTSwL0/NBZ6nZrS83muaV67XjtyuxbzQ9m3+fkT7uf5foW/44H5K4fpLltsmTkckVlmDmA"
+ "oNdr0G7V+XBmkfd+2fk87v4LLAgo84Gt5eYAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_no = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAelJ"
+ "REFUOI21ksFL03EYxj/fX1tuWEtxW0ZulbbpKYutIYM6CIFEimh2CUFIKKhLpxCKSPwDunSI"
+ "IOgQSh48dq5DB9EiVik/NaHBYrRm5HTG2u/pMAsTiRb0nJ735X0e3vfhhf+FC4dpT/WioWY6"
+ "/8ngfT8reoXsXtYBd1XigTDnc/frJeW18iigoSOMAOavxEehZm4QOYXHymRmVV6b1PIlFPFy"
+ "cKf5Xdsb9gD3gtdisdlcn3n+LEXm017inRniSx+iD5eY2D5vbS2uNBP8coDLnuRd46kpUiqV"
+ "8O0p4YqNETrOudONxP9ocP0Y0y13uoAyTU0W+fxXmkIWsEF4pIsHSZ4CNTsa3G4n4TvjPkTd"
+ "MPARv3+VbDZHJLIBpGFfD3Vn3Q1XW+lnS6A/iZnrw2mb7AYruRmNmJ7+TCJRC2wAa+DMsHDx"
+ "BdEJGoD8rw2W+7gRvuUCyw8sAPMUCm8ZH39NNpsC5gEbLC+hmy6enGLst/PfDSKpVdJJSR2S"
+ "OjQ1dUKRSESjo1FJbZJaJIUlBWQPIyAAwJseZuQYSQFJ+yU1SmpUWUHZi34Vv9VL8kmqleSR"
+ "tFsSetnNIuB2GbDtQcWMexWMwRgLpM3dHNKOU6FykASq1OvfSQNes3mL31vdv5tiJdl8FZqd"
+ "8QO3F9ZRFEVpTAAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_ok = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAjdJ"
+ "REFUOI2tksFLk3Ecxp+97975vmuve1dWuiUTNIy1JlsLpkZG0aXLbv0B0aVDUMfVQTp0jJpF"
+ "EHl5LxUZgZcuQjAID4KUyWwyEU3d9m7O5d733dze97dfB1siJSn1nJ/P5+ELX+Afwx6YuAMB"
+ "AVgwjcaBBdIovP2eyKMLPYNdM+7kNKZA9i3gR+ENCeF4Hx+8VigVBgrKWrXKGp/2JeCfwhsW"
+ "Q/HTQiCaVTOYUiZtDuoMQqefrc1S9+uOEGNSRzqd+4j72/c1l4OOQNwn+aOFWg5TdBJEIKbH"
+ "dI9zHLMt6H3lHrjScfU5x3DSmOXNrVUUxwFQ6S3vDdh9cZ/zTHSz8R0pMguGMKaRMuX5peQ9"
+ "ZULPW8+PnB286L78zH/M76/DwCYtjSTefaAOQZjpEDofn5J8UR0qViqLoCpLql+IXFzS72IC"
+ "eQCwssR2NFfOtNXsFZx09SLkDnfSlsYTluUy7a3Hz6mWMrLGKswiJaV0WS6Uyr9gAGC7It0L"
+ "WrWYm99K9VdcqugSD8Pd6nG6RNeJCq9ZstwqNL1CMl/z8npdiRkPd2AAYJcTy41FcSVZt+lK"
+ "na9FaLspCg4ehDew3qJgs6qStUxerhItlr+h74KB5iPNgVZuGkm6QpQWmy3i8AoiY7dA1XTy"
+ "LZuVGYHGZi8t/gbvCABgDFS7vpVEgSgS29bv5CR7XtmQjxxyxt77En+Edwt+Svpua3MbRT5T"
+ "a9QXPGL7gxc9L/eE98wwHWaG6JD1783/kB9qTvueLt8LjwAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_question = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAB/pJ"
+ "REFUWIXFl3tsVuUdxz/PubyXvu3b2hugKAobaYHJpYZLghMdEzsnbKhxGidzuMVkExedG9ni"
+ "0Jm4kGWpIsmyyz9go1lkGzC5KAFLkSJQuUwYtEBx3Au0pX1p3/c9z+W3PwoJoiCgyb7J8885"
+ "v/P7fM5znjx5DnyBFBUVlZWXlw/6Ij2uKcOHD6n60x//vGrVilWdq1e907N4UX1jVVXVuGvp"
+ "pa72gdLS0huWL3v7o492HSjZ2NRlAO6aMiAYOWpY78yZM8YdPXp039X086+meOrUqdMXLlz4"
+ "zrr3Wq873p7mhsE3+el0md/S2svJ9mOxF194ZvaJEyeOtbS07LjSnlcyA/6AAQPK5s6dWzdp"
+ "wqRH/rl8q43Fh/nxeICODFo7nHP09OQpK+0xP3z8rmDNmrUrfzn3uSe7urqOAQ6QKxVQgNTU"
+ "1IwfWDFwaM1tNbcPrxo+prJi4KSW1g7VdjDnSkoqvTD00VpjjMNoizYO64SengjoddO+Ocyb"
+ "OP4W/nvo4JZNH2z9d0PDhvVtbfsO7N27d9PnzsD8+b9/vfaeex89fPgYx46fYs/eTpPLJVR5"
+ "+fV+SUmMbDbCWosx/UNrhzUOYy1agwicOp1FXMaMHVuppt39NW/EiGEqlUrw2msLV86Z89S9"
+ "lxSYN29e7L5vfye/fMUOp6hU8XiI7wcqFlMYY9Da0NeXQxtDqiAkXZRAedDdneXY8QzZrCEM"
+ "AowRtFGcPRthjRHnYML4cnn++fu9Z599pqyurq7zPDO4UCCVSpVGUYQzcSoqi5XWEc5Z8nmL"
+ "tZZ8LuLWW6/nG3dWU1qWAsA5i9aankwfS5fupKFhP54f4izEYgrrh0qc4uNDvSgFQ4cOvRn4"
+ "bAHP89LOWfr6tDNGe8YYnHM4ZzFGE+mI6feNxvc8+vpyWOvOrQWLMYYZM0ZSXByydNkewANR"
+ "IOBEYXT/ZBcXF5ddyPyEQEVFRVopD21UoCOLsRbnLNYZrDUYo9Ha4MVDtDZ0dHSTSMRwzpLN"
+ "5ejry3LjjUl279qHMUlQAZ7n43khAwekFEAyTMYvKSAiAoJzoI3BGIOcEzBGY4zmzJkM9fXv"
+ "0rD+PxxoO4E1lhdffJgxo4eQyZwln89SVhZy8GCOWCyO8gTPU+TzWkRQVll1SYGurq6z4sA6"
+ "64yxnjEWaw0ipv8ts3lqv/Vb2k924XsQBAqtLe+8u52acUPIZDJEUYRSGsFx4RYQhB5KQS6X"
+ "y19SoLe3t8fzPQJPMMahtUWk/ztv2dLCkSMncC4iHvMRsYAjn88xacJwTrSfJpPpxRjN4SNd"
+ "BEEJguAJIEIyESBAd3d3xyUF2tvbO33PI10cqEhbnHN0nzlLw/pdRFEWpRRKeThncQ5y+Twz"
+ "ZkxkxMgBnDzVhTjD1q0HyPZ5JBICCA7BA4oKQ9XV0cnx48c/vpD5qY1o2dLlLdt2ZIZ39xRw"
+ "9PBJPtx+EBGNOI11EWIjHIZ8NsfPf3EfEyfczKlTHVhraG09yoIFTRQVVeJ5MTw/hu+HOOvz"
+ "yCOjZMqUis47p3y9/EKed7HA2nXrlg25qYgjR7rZvvM4nhcDAkQCxAUIAVEeam4bzqSJQ2hv"
+ "P40xmra2k7z66vsUpCpx0l+P+IgE9PU5xowZojZ/sHnrxbxPCTQ1vb+iumoQ27YdEoj1QyWG"
+ "SIgQIi5GX59i2rRRdHZ2o41m9+4jzJ/fQCw+4BP1TmKIBCiFfPUrxSxZsuSvnyvQ3Ny8MQjs"
+ "qZEjCqyOgnNNYogkwCUQEiiVZNCgJLlcDoXjrbd2k0hcjyKOcwlE4ojEQWJEkU9VValLxG3U"
+ "2rrnvYt5wcUXAPdh87amBx6omr59+x7xvLgS8RHRODxEfHwfPmw+QSKp0caSySRQqgARDwhB"
+ "QkQCnIREkWX242Np3NC0paenp/uKBJb8Y9kbb77x+owFC9pcR0eoxBmcBCAhTgzJZJy6Vw7g"
+ "+xZnHcUlpQR+gKgQz/MRF+JUgCc+lRW4CRNv9J988nd/A+zFsEseSBoaGg9t2do1eP780yqZ"
+ "FKxziNU4sfT2ambNGkhNTYIo8nj55f1ksyGe56GUj+cF+L5PNgs//Um5TJxYkK+tvbvwswQ+"
+ "tQbO5+mnn3rsR09MUoMGZazWBYhL4iSFMSnuuGMQ06cXUF6epKbmBub9ppoz3QqRQsSlcK4A"
+ "rQsoLTPuwQduUS+99MITnwW/rMDOnTs3rF69bl394nuUsUYghXOFOFeEUiFF6RTXXVdKuihN"
+ "KuVjdKz/vhQikkJrJXV/GCVNm7Zsa2pqeutSnMsdSqWxcf3GuXOf+7HndQZr1igViyWBkH2t"
+ "AWFoGDw4xv59Xfzq1/sRNwRIoFSc3l6fx76PTJ5c5s+Z89R3z5w5c+gynMunurr6dmu1zJ5d"
+ "H8UTDVJSsl7S6fWSSjVKLLZa4vFVUljUKEXpRikuaZREslFmznzTtLbskvHjJz18zeAL89BD"
+ "Dz8n4uQHj79tlGqSVOEOSRVuk1Thzv6R2i6FhdtFeVtl+ox/2b17d8msWbNf+VLg53PX1KlP"
+ "iHNSV7dSQ7Mkk22SSLRKItEqyYIDArvkZ8/8Xe9r3S0PPvjQy18q/HwmT77je21t+zs3NO6W"
+ "cTXrDbQ6OOCqqzfaRYsapLn5Az11au3T58qv+q/ripJOp0sXL67f2d3dJWvWbHEr3t7k9rW2"
+ "SH39m0cqKiqGXW2/a7YcPXrso7W1tfd7HsHatQ0rN29u+gtgrrXf/y3/A9AbS5RB5/OZAAAA"
+ "AElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_reassign = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAcRJ"
+ "REFUKJGdj01Ik3Ecxz///565KcvkcUwedtiWRFRUprTAxxZLq0MRzBy5IIoShF5cp6BLBF16"
+ "oU4RnQK7BC2WtEOLGLJkvdGbBzOFEqpLRXhYbZLu+XWwt3Mf+B4/H/gqFlkOnAU+AGFgDlgJ"
+ "zABBIC0ij5RSAoDH485lr52SocHdMv7giqR6e2SyeFn2JLrlWf6SWIHGj4VCoRXAAGhb17Yz"
+ "urFTFnSTevn4KYnePqamp0j17+Xzl3esWdseFJFlwFsDQGmD4KrtyvzkZf/h05w/18GOXScw"
+ "dA2UG9/tNwALADqTySQrlW/kcncYyd5ia3w9kZYaN65fpVwu43Y5gKCUUgA6mUzePHRwQIpj"
+ "BZY2NXD0eBq7qwNrySxjo/eo1Ry01vzGABhKDyjmRsCoh9nvUP2KUZnm7pMJujZv41f8r5A+"
+ "sk9ejWaVUddAIh4httrF5HuLwWMnsawWHMf5I+hSqWQXSzPqwvBzuvvPcHF4gvuvG1nReYBw"
+ "OML8/A9EBBERAMO27YexWIzohnY8dS7GX/TRuilFfEsP1WoFr7cen8+H/vcIUAmFQmKappim"
+ "Kc3NfvH7FxcIBASQfD4f5X/4CVPZn52VDH4mAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_warning = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABohJ"
+ "REFUWIXVlktsHVcZx3/nzJyZ+7RvYjs3Jtj12773xokfcV4VCgopArUisEhb8ahIg9ImAYnn"
+ "glVggRCgbtghVqxYVCwQokh0gSDQNhJSC4iIUpREbWM7iePHffnOnJlzWMy1Y9RWTdxmwZGO"
+ "ZjQ65zu/7/t/33cG/l/HTx4pZv/0s/OHfvXdR/ceA3e7duR2Ns2CGhrpuVgeUi/uL2V+f+pT"
+ "hSe2C+BsZ9NXZ51jhz4x+8PBoVSh0KHyrfV4gP/M/+61GtX7tXXfEXgMMmNTE+eGxnu7CBpI"
+ "GzC+r3/64HTX5+/X1rYAjh5KnxidKX86q1rYYB3COsUeJSZnBp++8BHGHijAWegcnqpc6H9o"
+ "Ry5er2MjDVGIiGqMT+4Zm5zp/jIgHhjA4MOFk2NT48dUvEYUaEygsUEAQYOenYK9s4Nf/OYI"
+ "Uw8E4MwuiiPTlWeLxYwfNKtEOiTWAUaHELagtcxEpdg3Xuo+y32U5T1XwRNz3WcOHj/8dE4u"
+ "S6PXEXEIUQtpQoSNEEaTyfoE1h/ouDH/0ivLvPmhAXylyODBE3PPTUwUinH9NjaKMG4ekxtE"
+ "qx6ErqFMDUxIrqsnc3Oxml56vfnC2xB9KACPH+79xpETs6fS8U1MFGBNROHo19jxse+QnjiJ"
+ "DKsw/zLCaNIZRSSyA2sLC6++cod/v5/t982BC0NMlmfLT3XnQ0zQQBiNiCOkmwEhEdIBN02s"
+ "Y2yooX6T0nguN1HadeEUdH5QAGek1PfMeLl3gPpionWsIY7Ams1FcWyIwgijI1hv0qlvMF3J"
+ "fXywzGc/EMDXxzhcmpl4vODXsbqFsBqMBhshuAtgYoMONXGzhVlagRvXKPeG/uho4dypHnZv"
+ "C+AYpEYrwxfGRnf20LidHBprpIlxrIatAFGEXq0TLq5g1lrQMuSiFWYq+bnh3fLJbQEcqTgn"
+ "StODj+WdVWwcIG2IayOU0CipkdjNtbbRwKw0sdpgaavTaFDq1XJ8NH/2qR6G7wvgC9AxPDl0"
+ "fmQglxfrK7hEKJFMT2o8GSHF3Qg4GBwJUm7pwwbS0SoHKtlS3x7nNO/Rot8VYOBA6mRlsu94"
+ "Xqzg2BAldfvwCF9ovGYNGbY21ytH4LvgSBAimQCEmtHdEaWx3JdO72HfPQGc2UVxrNR/fqhP"
+ "+VLXUCJGiRhPRCjdQC0v4a8u4zSWIA4gauFEa6Q9UC5I0fa1DeHHDQ6Us/39u9Uz7/bn9I4P"
+ "Dw3nn5zcW5zLsopE44oIGbeQa6vIejUR2AMu/xjz+vNgLfLOvxDpJOzYtltCJBBRxPCukPJI"
+ "9tTNW6u//ONbXNp63v90wnP9DM0dGnhuZm+u6JkGrtC4jTXkyi1kq5Hg+i54LutWUevcT2AV"
+ "snYVVwGuTCwKwBFJUkiJlIZ0Pp25vhBkuoX57ZXq3Ra9NQJicCh/erJSKGeoI3UDuXob2ayC"
+ "YyHlglLgKqzjIQ5dZOfss9g4RF+6CFd+nkQn0qDbZbqhR2wY6AqpjKYfXbxT+yTw63dE4Ntl"
+ "puZm9/xo34jX6awu4txZQOomQgnwPfB9SKXBTyOyXbgz5xG5jyKki2vWYOESOE57bkl4mWSl"
+ "wJDLKu/qQtTV55jf/G2N1ibAWVDj09mLR/ZmjnfU3sZZW8YRBuEBvoJUClIZ8LOQyoLyQWWg"
+ "MAbBMlx9HpoL4Kh2LbYBrAGx0S8sHVlLdV323ViMrl2+w6ubAJ/Zz7HJPr43mq6mVdRCKZBe"
+ "W28/1fY8C6kcpPLJXF+Apb/C/B+gfh1cD5x2GQjaBxswBqwFC0IaOjI41+bNnqKxL/yjRtX5"
+ "1j6yo7vFD6Z649mOlEGpxJG7oU+BnwE/B34e/A7wO5N3YUFacFPtTRve28R7a5KLK443v+VS"
+ "hmYoelea7s0/L8R/ccdmKuWZPh7e2fwnbltC4QBKJoXt+eC1I5DugFRnAqBy4PpJkhkNugGB"
+ "l+gvLBDBxuVl2hDWgrUc3VcQdnjuc7fc137hukJkTL7bW1rxcdZDXF/ieBIReBCkEE0FnpPU"
+ "vq9BtUA54MZtnRIAG7UgamJDjQ0NhBIbKgh9RGiwYYA1CYSXd8jms109O7Od7uIb16+8tLb0"
+ "07Aqh3TdxtIxsSuMkdIY6bSMFCsGgZHILX1z4yVJNmNs+2kSyQ0YDAbkjpTp7PDIxQYHkNZa"
+ "4eYbznxw6fJbbywtii0WN6za93huZ4izszhHckmyZwPESjei+iai/neC79/DP+MDH/8FsY6a"
+ "7HCEfEAAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_yes = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAjdJ"
+ "REFUOI2tksFLk3Ecxp+97975vmuve1dWuiUTNIy1JlsLpkZG0aXLbv0B0aVDUMfVQTp0jJpF"
+ "EHl5LxUZgZcuQjAID4KUyWwyEU3d9m7O5d733dze97dfB1siJSn1nJ/P5+ELX+Afwx6YuAMB"
+ "AVgwjcaBBdIovP2eyKMLPYNdM+7kNKZA9i3gR+ENCeF4Hx+8VigVBgrKWrXKGp/2JeCfwhsW"
+ "Q/HTQiCaVTOYUiZtDuoMQqefrc1S9+uOEGNSRzqd+4j72/c1l4OOQNwn+aOFWg5TdBJEIKbH"
+ "dI9zHLMt6H3lHrjScfU5x3DSmOXNrVUUxwFQ6S3vDdh9cZ/zTHSz8R0pMguGMKaRMuX5peQ9"
+ "ZULPW8+PnB286L78zH/M76/DwCYtjSTefaAOQZjpEDofn5J8UR0qViqLoCpLql+IXFzS72IC"
+ "eQCwssR2NFfOtNXsFZx09SLkDnfSlsYTluUy7a3Hz6mWMrLGKswiJaV0WS6Uyr9gAGC7It0L"
+ "WrWYm99K9VdcqugSD8Pd6nG6RNeJCq9ZstwqNL1CMl/z8npdiRkPd2AAYJcTy41FcSVZt+lK"
+ "na9FaLspCg4ehDew3qJgs6qStUxerhItlr+h74KB5iPNgVZuGkm6QpQWmy3i8AoiY7dA1XTy"
+ "LZuVGYHGZi8t/gbvCABgDFS7vpVEgSgS29bv5CR7XtmQjxxyxt77En+Edwt+Svpua3MbRT5T"
+ "a9QXPGL7gxc9L/eE98wwHWaG6JD1783/kB9qTvueLt8LjwAAAABJRU5ErkJggg==")
+
+
+class StdDialogButtonSizer(wx.BoxSizer):
+ """ wxWidgets standard dialog button sizer. """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ wx.BoxSizer.__init__(self, wx.HORIZONTAL)
+
+ self._buttonAffirmative = None
+ self._buttonApply = None
+ self._buttonNegative = None
+ self._buttonCancel = None
+ self._buttonHelp = None
+
+
+ def AddButton(self, mybutton):
+ """
+ Add a button to the sizer.
+
+ :param `mybutton`: the button to add.
+ """
+
+ buttonId = mybutton.GetId()
+
+ if buttonId in [wx.ID_OK, wx.ID_YES, wx.ID_SAVE]:
+ self._buttonAffirmative = mybutton
+
+ elif buttonId == wx.ID_APPLY:
+ self._buttonApply = mybutton
+ elif buttonId == wx.ID_NO:
+ self._buttonNegative = mybutton
+ elif buttonId in [wx.ID_CANCEL, wx.ID_CLOSE]:
+ self._buttonCancel = mybutton
+ elif buttonId in [wx.ID_HELP, wx.ID_CONTEXT_HELP]:
+ self._buttonHelp = mybutton
+
+
+ def SetAffirmativeButton(self, button):
+ """
+ Sets the affirmative button.
+
+ :param `button`: the button to set as affirmative one.
+ """
+
+ self._buttonAffirmative = button
+
+
+ def SetNegativeButton(self, button):
+ """
+ Sets the negative button.
+
+ :param `button`: the button to set as negative one.
+ """
+
+ self._buttonNegative = button
+
+
+ def SetCancelButton(self, button):
+ """
+ Sets the cancel button.
+
+ :param `button`: the button to set as cancel one.
+ """
+
+ self._buttonCancel = button
+
+
+ def Realize(self):
+ """ Realizes the sizer depending on the platform. """
+
+ if wx.Platform == "__WXMAC__":
+
+ self.Add((0, 0), 0, wx.LEFT, 6)
+ if self._buttonHelp:
+ self.Add(self._buttonHelp, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 6)
+
+ if self._buttonNegative:
+ # HIG POLICE BULLETIN - destructive buttons need extra padding
+ # 24 pixels on either side
+ self.Add(self._buttonNegative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 12)
+
+ # extra whitespace between help/negative and cancel/ok buttons
+ self.Add((0, 0), 1, wx.EXPAND, 0)
+
+ if self._buttonCancel:
+ self.Add(self._buttonCancel, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 6)
+ # Cancel or help should be default
+ # self._buttonCancel.SetDefaultButton()
+
+ # Ugh, Mac doesn't really have apply dialogs, so I'll just
+ # figure the best place is between Cancel and OK
+ if self._buttonApply:
+ self.Add(self._buttonApply, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 6)
+
+ if self._buttonAffirmative:
+ self.Add(self._buttonAffirmative, 0, wx.ALIGN_CENTRE | wx.LEFT, 6)
+ if self._buttonAffirmative.GetId() == wx.ID_SAVE:
+ # these buttons have set labels under Mac so we should use them
+ self._buttonAffirmative.SetLabel(_("Save"))
+ if self._buttonNegative:
+ self._buttonNegative.SetLabel(_("Don't Save"))
+
+ # Extra space around and at the right
+ self.Add((12, 24))
+
+ elif wx.Platform == "__WXGTK__":
+
+ self.Add((0, 0), 0, wx.LEFT, 9)
+ if self._buttonHelp:
+ self.Add(self._buttonHelp, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 3)
+
+ # extra whitespace between help and cancel/ok buttons
+ self.Add((0, 0), 1, wx.EXPAND, 0)
+
+ if self._buttonNegative:
+ self.Add(self._buttonNegative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 3)
+
+ # according to HIG, in explicit apply windows the order is:
+ # [ Help Apply Cancel OK ]
+ if self._buttonApply:
+ self.Add(self._buttonApply, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 3)
+
+ if self._buttonCancel:
+ self.Add(self._buttonCancel, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, 3)
+ # Cancel or help should be default
+ # self._buttonCancel.SetDefaultButton()
+
+ if self._buttonAffirmative:
+ self.Add(self._buttonAffirmative, 0, wx.ALIGN_CENTRE | wx.LEFT, 6)
+
+ elif wx.Platform == "__WXMSW__":
+ # Windows
+ # center-justify buttons
+ self.Add((0, 0), 1, wx.EXPAND, 0)
+
+ if self._buttonAffirmative:
+ self.Add(self._buttonAffirmative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonAffirmative.ConvertDialogSizeToPixels(wx.Size(2, 0)).x)
+
+ if self._buttonNegative:
+ self.Add(self._buttonNegative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonNegative.ConvertDialogSizeToPixels(wx.Size(2, 0)).x)
+
+ if self._buttonCancel:
+ self.Add(self._buttonCancel, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonCancel.ConvertDialogSizeToPixels(wx.Size(2, 0)).x)
+
+ if self._buttonApply:
+ self.Add(self._buttonApply, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonApply.ConvertDialogSizeToPixels(wx.Size(2, 0)).x)
+
+ if self._buttonHelp:
+ self.Add(self._buttonHelp, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonHelp.ConvertDialogSizeToPixels(wx.Size(2, 0)).x)
+
+ self.Add((0, 0), 1, wx.EXPAND, 0)
+
+ else:
+ # GTK+1 and any other platform
+
+ if self._buttonHelp:
+ self.Add(self._buttonHelp, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonHelp.ConvertDialogSizeToPixels(wx.Size(4, 0)).x)
+
+ # extra whitespace between help and cancel/ok buttons
+ self.Add((0, 0), 1, wx.EXPAND, 0)
+
+ if self._buttonApply:
+ self.Add(self._buttonApply, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonApply.ConvertDialogSizeToPixels(wx.Size(4, 0)).x)
+
+ if self._buttonAffirmative:
+ self.Add(self._buttonAffirmative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonAffirmative.ConvertDialogSizeToPixels(wx.Size(4, 0)).x)
+
+ if self._buttonNegative:
+ self.Add(self._buttonNegative, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonNegative.ConvertDialogSizeToPixels(wx.Size(4, 0)).x)
+
+ if self._buttonCancel:
+ self.Add(self._buttonCancel, 0, wx.ALIGN_CENTRE | wx.LEFT | wx.RIGHT, self._buttonCancel.ConvertDialogSizeToPixels(wx.Size(4, 0)).x)
+ # Cancel or help should be default
+ # self._buttonCancel.SetDefaultButton()
+
+
+class GenericMessageDialog(wx.Dialog):
+ """
+ Main class implementation, :class:`GenericMessageDialog` is a possible replacement
+ for the standard :class:`MessageDialog`.
+ """
+
+ def __init__(self, parent, message, caption, agwStyle,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_DIALOG_STYLE|wx.WANTS_CHARS,
+ wrap=-1):
+ """
+ Default class constructor. Use :meth:`~GenericMessageDialog.ShowModal` to show the dialog.
+
+ :param `parent`: the :class:`GenericMessageDialog` parent (if any);
+ :param `message`: the message in the main body of the dialog;
+ :param `caption`: the dialog title;
+ :param `agwStyle`: the AGW-specific dialog style; it can be one of the
+ following bits:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``GMD_DEFAULT`` 0 Uses normal generic buttons
+ ``GMD_USE_AQUABUTTONS`` 0x20 Uses :class:`AquaButton` buttons instead of generic buttons.
+ ``GMD_USE_GRADIENTBUTTONS`` 0x40 Uses :class:`GradientButton` buttons instead of generic buttons.
+ =========================== =========== ==================================================
+
+ The styles above are mutually exclusive. The style chosen above can be combined with a
+ bitlist containing flags chosen from the following:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``wx.OK`` 0x4 Shows an ``OK`` button.
+ ``wx.CANCEL`` 0x10 Shows a ``Cancel`` button.
+ ``wx.YES_NO`` 0xA Show ``Yes`` and ``No`` buttons.
+ ``wx.YES_DEFAULT`` 0x0 Used with ``wx.YES_NO``, makes ``Yes`` button the default - which is the default behaviour.
+ ``wx.NO_DEFAULT`` 0x80 Used with ``wx.YES_NO``, makes ``No`` button the default.
+ ``wx.ICON_EXCLAMATION`` 0x100 Shows an exclamation mark icon.
+ ``wx.ICON_HAND`` 0x200 Shows an error icon.
+ ``wx.ICON_ERROR`` 0x200 Shows an error icon - the same as ``wx.ICON_HAND``.
+ ``wx.ICON_QUESTION`` 0x400 Shows a question mark icon.
+ ``wx.ICON_INFORMATION`` 0x800 Shows an information icon.
+ =========================== =========== ==================================================
+
+ :param `pos`: the dialog position on screen;
+ :param `size`: the dialog size;
+ :param `style`: the underlying :class:`Dialog` style;
+ :param `wrap`: if set greater than zero, wraps the string in `message` so that
+ every line is at most `wrap` pixels long.
+
+ :note: Notice that not all styles are compatible: only one of ``wx.OK`` and ``wx.YES_NO`` may be
+ specified (and one of them must be specified) and at most one default button style can be used
+ and it is only valid if the corresponding button is shown in the message box.
+ """
+
+ wx.Dialog.__init__(self, parent, wx.ID_ANY, caption, pos, size, style)
+
+ self._message = message
+ self._agwStyle = agwStyle
+ self._wrap = wrap
+
+ # The extended message placeholder
+ self._extendedMessage = ''
+
+ # Labels for the buttons, initially empty meaning that the defaults should
+ # be used, use GetYes/No/OK/CancelLabel() to access them
+ self._yes = self._no = self._ok = self._cancel = self._help = ''
+
+ # Icons for the buttons, initially empty meaning that the defaults should
+ # be used, use GetYes/No/OK/CancelBitmap() to access them
+ self._yesBitmap = self._noBitmap = self._okBitmap = self._cancelBitmap = self._helpBitmap = None
+
+ self._created = False
+
+
+ def CreateMessageDialog(self):
+ """ Actually creates the :class:`GenericMessageDialog`, just before showing it on screen. """
+
+ message = self.GetMessage()
+
+ topsizer = wx.BoxSizer(wx.VERTICAL)
+ icon_text = wx.BoxSizer(wx.HORIZONTAL)
+
+ case = self._agwStyle & wx.ICON_MASK
+
+ if case == wx.ICON_ERROR:
+ bitmap = _error
+
+ elif case == wx.ICON_INFORMATION:
+ bitmap = _information
+
+ elif case == wx.ICON_WARNING:
+ bitmap = _warning
+
+ elif case == wx.ICON_QUESTION:
+ bitmap = _question
+
+ # Populate the sizers...
+ icon = wx.StaticBitmap(self, -1, bitmap.GetBitmap())
+ icon_text.Add(icon, 0, wx.ALIGN_CENTER_HORIZONTAL)
+
+ textsizer = wx.BoxSizer(wx.VERTICAL)
+
+ # We want to show the main message in a different font to make it stand
+ # out if the extended message is used as well. This looks better and is
+ # more consistent with the native dialogs under MSW and GTK.
+
+ if self._extendedMessage.strip():
+ boldFont = self.GetFont().Larger().MakeBold()
+ if self._wrap > 0:
+ message = self.WrapMessage(message, self._wrap, boldFont)
+
+ msgSizer = self.CreateTextSizer(message)
+
+ for index in xrange(len(msgSizer.GetChildren())):
+ msgSizer.GetItem(index).GetWindow().SetFont(boldFont)
+
+ textsizer.AddF(msgSizer, wx.SizerFlags().Border(wx.BOTTOM, 20))
+ lowerMessage = self.GetExtendedMessage()
+
+ else: # no extended message
+
+ lowerMessage = message
+
+ if self._wrap > 0:
+ lowerMessage = self.WrapMessage(lowerMessage, self._wrap)
+
+ textsizer.Add(self.CreateTextSizer(lowerMessage))
+
+ icon_text.Add(textsizer, 1, wx.ALIGN_CENTER | wx.LEFT, 10)
+ topsizer.Add(icon_text, 1, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 10)
+
+ center_flag = wx.EXPAND
+ if self._agwStyle & wx.YES_NO:
+ center_flag |= wx.ALIGN_CENTRE
+
+ sizerBtn = self.CreateSeparatedButtonSizer(self._agwStyle & BUTTON_SIZER_FLAGS)
+ if sizerBtn:
+ topsizer.Add(sizerBtn, 0, center_flag | wx.ALL, 10)
+
+ self.SetAutoLayout(True)
+ self.SetSizer(topsizer)
+
+ topsizer.SetSizeHints(self)
+ topsizer.Fit(self)
+ size = self.GetSize()
+
+ if size.x < size.y*3/2:
+ size.x = size.y*3/2
+ self.SetSize(size)
+
+ self.Layout()
+ self.Centre(wx.BOTH | wx.CENTER_FRAME)
+
+ self.Bind(wx.EVT_BUTTON, self.OnYes, id=wx.ID_YES)
+ self.Bind(wx.EVT_BUTTON, self.OnOk, id=wx.ID_OK)
+ self.Bind(wx.EVT_BUTTON, self.OnNo, id=wx.ID_NO)
+ self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
+ self.Bind(wx.EVT_BUTTON, self.OnHelp, id=wx.ID_HELP)
+
+ for child in self.GetChildren():
+ if isinstance(child, wx.lib.buttons.ThemedGenBitmapTextButton) or \
+ isinstance(child, AB.AquaButton) or isinstance(child, GB.GradientButton):
+ # Handles the key down for the buttons...
+ child.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ if isinstance(child, wx.lib.buttons.ThemedGenBitmapTextButton):
+ child.SetUseFocusIndicator(False)
+
+ self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigation)
+ self.SwitchFocus()
+
+
+ def EndDialog(self, rc):
+ """
+ Ends the :class:`GenericMessageDialog` life. This will be done differently depending on
+ the dialog modal/non-modal behaviour.
+
+ :param `rc`: one of the ``wx.ID_YES``, ``wx.ID_NO``, ``wx.ID_OK``, ``wx.ID_CANCEL`` constants.
+
+ :note: the `rc` parameter is unused if the dialog is not modal.
+ """
+
+ if self.IsModal():
+ self.EndModal(rc)
+ else:
+ self.Hide()
+
+
+ def OnYes(self, event):
+ """ :class:`GenericMessageDialog` had received a ``wx.ID_YES`` answer. """
+
+ self.EndDialog(wx.ID_YES)
+
+
+ def OnOk(self, event):
+ """ :class:`GenericMessageDialog` had received a ``wx.ID_OK`` answer. """
+
+ self.EndDialog(wx.ID_OK)
+
+
+ def OnNo(self, event):
+ """ :class:`GenericMessageDialog` had received a ``wx.ID_NO`` answer. """
+
+ self.EndDialog(wx.ID_NO)
+
+
+ def OnCancel(self, event):
+ """ :class:`GenericMessageDialog` had received a ``wx.ID_CANCEL`` answer. """
+
+ # Allow cancellation via ESC/Close button except if
+ # only YES and NO are specified.
+
+ if self._agwStyle & wx.YES_NO != wx.YES_NO or self._agwStyle & wx.CANCEL:
+ self.EndDialog(wx.ID_CANCEL)
+
+
+ def OnHelp(self, event):
+ """ :class:`GenericMessageDialog` had received a ``wx.ID_HELP`` answer. """
+
+ self.EndDialog(wx.ID_HELP)
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`GenericMessageDialog`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ key = event.GetKeyCode()
+ if key == wx.WXK_ESCAPE:
+ self.OnCancel(None)
+
+ ids = []
+ for child in self.GetChildren():
+ if isinstance(child, wx.lib.buttons.ThemedGenBitmapTextButton) or \
+ isinstance(child, AB.AquaButton) or isinstance(child, GB.GradientButton):
+ ids.append(child.GetId())
+
+ if key in [ord("y"), ord("Y")] and wx.ID_YES in ids:
+ self.OnYes(None)
+ elif key in [ord("n"), ord("N")] and wx.ID_NO in ids:
+ self.OnNo(None)
+ elif key in [ord("c"), ord("C")] and wx.ID_CANCEL in ids:
+ self.OnCancel(None)
+ elif key in [ord("o"), ord("O")] and wx.ID_OK in ids:
+ self.OnOk(None)
+ elif key in [ord("h"), ord("H")] and wx.ID_HELP in ids:
+ self.OnHelp(None)
+
+ event.Skip()
+
+
+ def OnNavigation(self, event):
+ """
+ Handles the ``wx.EVT_NAVIGATION_KEY`` event for :class:`GenericMessageDialog`.
+
+ :param `event`: a :class:`NavigationKeyEvent` event to be processed.
+ """
+
+ # Switch the focus between buttons...
+ if wx.GetKeyState(wx.WXK_LEFT) or wx.GetKeyState(wx.WXK_RIGHT) or \
+ wx.GetKeyState(wx.WXK_DOWN) or wx.GetKeyState(wx.WXK_UP) or \
+ wx.GetKeyState(wx.WXK_NUMPAD_LEFT) or wx.GetKeyState(wx.WXK_NUMPAD_RIGHT) or \
+ wx.GetKeyState(wx.WXK_NUMPAD_DOWN) or wx.GetKeyState(wx.WXK_NUMPAD_UP) or \
+ event.IsFromTab():
+ event.Skip()
+ wx.CallAfter(self.SwitchFocus)
+ return
+
+ button = wx.Window.FindFocus()
+ buttonId = button.GetId()
+ self.EndDialog(buttonId)
+
+
+ def SwitchFocus(self):
+ """ Switch focus between buttons. """
+
+ current = wx.Window.FindFocus()
+ font = self.GetFont()
+ boldFont = wx.Font(font.GetPointSize(), font.GetFamily(), font.GetStyle(), wx.BOLD,
+ font.GetUnderlined(), font.GetFaceName())
+
+ for child in self.GetChildren():
+ if isinstance(child, wx.lib.buttons.ThemedGenBitmapTextButton) or \
+ isinstance(child, AB.AquaButton) or isinstance(child, GB.GradientButton):
+ if child == current:
+ # Set a bold font for the current focused button
+ child.SetFont(boldFont)
+ else:
+ # Restore the other buttons...
+ child.SetFont(font)
+ child.Refresh()
+
+
+ def CreateButtonSizer(self, flags):
+ """
+ Creates a sizer with standard buttons.
+
+ :param `flags`: a bit list of the following flags:
+
+ ================= ========= ==========================
+ Flags Hex Value Description
+ ================= ========= ==========================
+ ``wx.YES`` 0x2 Show a ``Yes`` button
+ ``wx.OK`` 0x4 Show an ``OK`` button
+ ``wx.NO`` 0x8 Show a ``No`` button
+ ``wx.CANCEL`` 0x10 Show a ``Cancel`` button
+ ``wx.NO_DEFAULT`` 0x80 Used with ``wx.YES`` and ``wx.NO``, makes ``No`` button the default
+ ``wx.HELP`` 0x8000 Show a ``Help`` button
+ ================= ========= ==========================
+
+ :note: The sizer lays out the buttons in a manner appropriate to the platform.
+ """
+
+ sizer = self.CreateStdDialogButtonSizer(flags)
+
+ return sizer
+
+
+ def CreateSeparatedButtonSizer(self, flags):
+ """
+ Creates a sizer with standard buttons using :meth:`~GenericMessageDialog.CreateButtonSizer` separated
+ from the rest of the dialog contents by a horizontal :class:`StaticLine`.
+
+ :param `flags`: the button sizer flags.
+
+ :see: :meth:`~GenericMessageDialog.CreateButtonSizer` for a list of valid flags.
+ """
+
+ sizer = self.CreateButtonSizer(flags)
+
+ # Mac Human Interface Guidelines recommend not to use static lines as
+ # grouping elements
+ if wx.Platform != "__WXMAC__":
+ topsizer = wx.BoxSizer(wx.VERTICAL)
+ topsizer.AddF(wx.StaticLine(self), wx.SizerFlags().Expand().DoubleBorder(wx.BOTTOM))
+ topsizer.AddF(sizer, wx.SizerFlags().Expand())
+ sizer = topsizer
+
+ return sizer
+
+
+ def CreateStdDialogButtonSizer(self, flags):
+ """
+ Creates a :class:`StdDialogButtonSizer` with standard buttons.
+
+ :param `flags`: the button sizer flags.
+
+ :see: :meth:`~GenericMessageDialog.CreateButtonSizer` for a list of valid flags.
+
+ :note: The sizer lays out the buttons in a manner appropriate to the platform.
+ """
+
+ sizer = StdDialogButtonSizer()
+ no = yes = ok = None
+ if flags & wx.OK:
+ # Remove unwanted flags...
+ flags &= ~(wx.YES | wx.NO | wx.NO_DEFAULT)
+
+ if self._agwStyle & GMD_USE_AQUABUTTONS:
+ klass = AB.AquaButton
+ elif self._agwStyle & GMD_USE_GRADIENTBUTTONS:
+ klass = GB.GradientButton
+ else:
+ klass = buttons.ThemedGenBitmapTextButton
+
+ if flags & wx.OK:
+ ok = klass(self, wx.ID_OK, self.GetCustomOKBitmap(), self.GetCustomOKLabel())
+ sizer.AddButton(ok)
+
+ if flags & wx.CANCEL:
+ cancel = klass(self, wx.ID_CANCEL, self.GetCustomCancelBitmap(), self.GetCustomCancelLabel())
+ sizer.AddButton(cancel)
+
+ if flags & wx.YES:
+ yes = klass(self, wx.ID_YES, self.GetCustomYesBitmap(), self.GetCustomYesLabel())
+ sizer.AddButton(yes)
+
+ if flags & wx.NO:
+ no = klass(self, wx.ID_NO, self.GetCustomNoBitmap(), self.GetCustomNoLabel())
+ sizer.AddButton(no)
+
+ if flags & wx.HELP:
+ help = klass(self, wx.ID_HELP, self.GetCustomHelpBitmap(), self.GetCustomHelpLabel())
+ sizer.AddButton(help)
+
+ if flags & wx.NO_DEFAULT:
+ if no:
+ no.SetDefault()
+ no.SetFocus()
+ else:
+ if ok:
+ ok.SetDefault()
+ ok.SetFocus()
+ elif yes:
+ yes.SetDefault()
+ yes.SetFocus()
+
+ if flags & wx.OK:
+ self.SetAffirmativeId(wx.ID_OK)
+ elif flags & wx.YES:
+ self.SetAffirmativeId(wx.ID_YES)
+
+ sizer.Realize()
+
+ return sizer
+
+
+ def GetDefaultYesLabel(self):
+ """
+ Returns the default label for the ``Yes`` button.
+
+ :note: this method may be overridden to provide different defaults for the
+ default button labels.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return _("Yes")
+
+
+ def GetDefaultNoLabel(self):
+ """
+ Returns the default label for the ``No`` button.
+
+ :note: this method may be overridden to provide different defaults for the
+ default button labels.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return _("No")
+
+
+ def GetDefaultOKLabel(self):
+ """
+ Returns the default label for the ``OK`` button.
+
+ :note: this method may be overridden to provide different defaults for the
+ default button labels.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return _("OK")
+
+
+ def GetDefaultCancelLabel(self):
+ """
+ Returns the default label for the ``Cancel`` button.
+
+ :note: this method may be overridden to provide different defaults for the
+ default button labels.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return _("Cancel")
+
+
+ def GetDefaultHelpLabel(self):
+ """
+ Returns the default label for the ``Help`` button.
+
+ :note: this method may be overridden to provide different defaults for the
+ default button labels.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return _("Help")
+
+
+ def GetCustomOKLabel(self):
+ """
+ If a custom label has been used for the ``OK`` button, this method will return
+ it as a string. Otherwise, the default one (as defined in :meth:`~GenericMessageDialog.GetDefaultOKLabel`)
+ is returned.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return (self._ok and [self._ok] or [self.GetDefaultOKLabel()])[0]
+
+
+ def GetCustomYesLabel(self):
+ """
+ If a custom label has been used for the ``Yes`` button, this method will return
+ it as a string. Otherwise, the default one (as defined in :meth:`~GenericMessageDialog.GetDefaultYesLabel`)
+ is returned.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return (self._yes and [self._yes] or [self.GetDefaultYesLabel()])[0]
+
+
+ def GetCustomNoLabel(self):
+ """
+ If a custom label has been used for the ``No`` button, this method will return
+ it as a string. Otherwise, the default one (as defined in :meth:`~GenericMessageDialog.GetDefaultNoLabel`)
+ is returned.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return (self._no and [self._no] or [self.GetDefaultNoLabel()])[0]
+
+
+ def GetCustomCancelLabel(self):
+ """
+ If a custom label has been used for the ``Cancel`` button, this method will return
+ it as a string. Otherwise, the default one (as defined in :meth:`~GenericMessageDialog.GetDefaultCancelLabel`)
+ is returned.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return (self._cancel and [self._cancel] or [self.GetDefaultCancelLabel()])[0]
+
+
+ def GetCustomHelpLabel(self):
+ """
+ If a custom label has been used for the ``Help`` button, this method will return
+ it as a string. Otherwise, the default one (as defined in :meth:`~GenericMessageDialog.GetDefaultHelpLabel`)
+ is returned.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return (self._help and [self._help] or [self.GetDefaultHelpLabel()])[0]
+
+
+ # Customization of the message box buttons
+ def SetYesNoLabels(self, yes, no):
+ """
+ Overrides the default labels of the ``Yes`` and ``No`` buttons.
+
+ :param `yes`: the new label for the ``Yes`` button;
+ :param `no`: the new label for the ``No`` button.
+
+ Typically, if the function was used successfully, the main dialog message may need to be changed, e.g.::
+
+ main_message = "Hello world! I am the main message."
+
+ dlg = GenericMessageDialog(None, main_message, "A Nice Message Box",
+ agwStyle=wx.ICON_INFORMATION|wx.OK)
+
+ if dlg.SetYesNoLabels(_("&Quit"), _("&Don't quit")):
+ dlg.SetMessage(_("What do you want to do?"))
+
+ else: # buttons have standard "Yes"/"No" values, so rephrase the question
+ dlg.SetMessage(_("Do you really want to quit?"))
+
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._yes, self._no = yes, no
+ return True
+
+
+ def SetYesNoCancelLabels(self, yes, no, cancel):
+ """
+ Overrides the default labels of the ``Yes`` and ``No`` buttons.
+
+ :param `yes`: the new label for the ``Yes`` button;
+ :param `no`: the new label for the ``No`` button;
+ :param `cancel`: the new label for the ``Cancel`` button.
+
+ :see: The remarks in the :meth:`~GenericMessageDialog.SetYesNoLabels` documentation.
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._yes, self._no, self._cancel = yes, no, cancel
+ return True
+
+
+ def SetOKLabel(self, ok):
+ """
+ Overrides the default label of the ``OK`` button.
+
+ :param `ok`: the new label for the ``OK`` button.
+
+ :see: The remarks in the :meth:`~GenericMessageDialog.SetYesNoLabels` documentation.
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._ok = ok
+ return True
+
+
+ def SetOKCancelLabels(self, ok, cancel):
+ """
+ Overrides the default labels of the ``OK`` and ``Cancel`` buttons.
+
+ :param `ok`: the new label for the ``OK`` button;
+ :param `cancel`: the new label for the ``Cancel`` button.
+
+ :see: The remarks in the :meth:`~GenericMessageDialog.SetYesNoLabels` documentation.
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._ok, self._cancel = ok, cancel
+ return True
+
+
+ def SetHelpLabel(self, help):
+ """
+ Overrides the default label of the ``Help`` button.
+
+ :param `help`: the new label for the ``Help`` button.
+
+ :see: The remarks in the :meth:`~GenericMessageDialog.SetYesNoLabels` documentation.
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._help = help
+ return True
+
+
+ # Test if any custom labels were set
+ def HasCustomLabels(self):
+ """
+ Returns ``True`` if any of the buttons have a non-default label.
+
+ .. versionadded:: 0.9.3
+ """
+
+ for label in [self._ok, self._no, self._yes, self._cancel, self._help]:
+ if label.strip():
+ return True
+
+ return False
+
+
+ def GetDefaultYesBitmap(self):
+ """
+ Returns the default icon for the ``Yes`` button.
+
+ :note: this method may be overridden to provide different defaults for the
+ default button icons.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return _yes.GetBitmap()
+
+
+ def GetDefaultNoBitmap(self):
+ """
+ Returns the default icon for the ``No`` button.
+
+ :note: this method may be overridden to provide different defaults for the
+ default button icons.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return _no.GetBitmap()
+
+
+ def GetDefaultOKBitmap(self):
+ """
+ Returns the default icon for the ``OK`` button.
+
+ :note: this method may be overridden to provide different defaults for the
+ default button icons.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return _ok.GetBitmap()
+
+
+ def GetDefaultCancelBitmap(self):
+ """
+ Returns the default icon for the ``Cancel`` button.
+
+ :note: this method may be overridden to provide different defaults for the
+ default button icons.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return _cancel.GetBitmap()
+
+
+ def GetDefaultHelpBitmap(self):
+ """
+ Returns the default icon for the ``Help`` button.
+
+ :note: this method may be overridden to provide different defaults for the
+ default button icons.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return _help.GetBitmap()
+
+
+ def GetCustomOKBitmap(self):
+ """
+ If a custom icon has been used for the ``OK`` button, this method will return
+ it as an instance of :class:`Bitmap`. Otherwise, the default one (as defined in
+ :meth:`~GenericMessageDialog.GetDefaultOKBitmap`) is returned.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return (self._okBitmap and [self._okBitmap] or [self.GetDefaultOKBitmap()])[0]
+
+
+ def GetCustomYesBitmap(self):
+ """
+ If a custom icon has been used for the ``Yes`` button, this method will return
+ it as an instance of :class:`Bitmap`. Otherwise, the default one (as defined in
+ :meth:`~GenericMessageDialog.GetDefaultYesBitmap`) is returned.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return (self._yesBitmap and [self._yesBitmap] or [self.GetDefaultYesBitmap()])[0]
+
+
+ def GetCustomNoBitmap(self):
+ """
+ If a custom icon has been used for the ``No`` button, this method will return
+ it as an instance of :class:`Bitmap`. Otherwise, the default one (as defined in
+ :meth:`~GenericMessageDialog.GetDefaultNoBitmap`) is returned.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return (self._noBitmap and [self._noBitmap] or [self.GetDefaultNoBitmap()])[0]
+
+
+ def GetCustomCancelBitmap(self):
+ """
+ If a custom icon been used for the ``Cancel`` button, this method will return
+ it as an instance of :class:`Bitmap`. Otherwise, the default one (as defined in
+ :meth:`~GenericMessageDialog.GetDefaultCancelBitmap`) is returned.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return (self._cancelBitmap and [self._cancelBitmap] or [self.GetDefaultCancelBitmap()])[0]
+
+
+ def GetCustomHelpBitmap(self):
+ """
+ If a custom icon has been used for the ``Help`` button, this method will return
+ it as an instance of :class:`Bitmap`. Otherwise, the default one (as defined in
+ :meth:`~GenericMessageDialog.GetDefaultHelpBitmap`) is returned.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return (self._helpBitmap and [self._helpBitmap] or [self.GetDefaultHelpBitmap()])[0]
+
+
+ # Customization of the message box buttons icons
+ def SetYesNoBitmaps(self, yesBitmap, noBitmap):
+ """
+ Overrides the default icons of the ``Yes`` and ``No`` buttons.
+
+ :param `yesBitmap`: the new icon for the ``Yes`` button, an instance of :class:`Bitmap`;
+ :param `noBitmap`: the new icon for the ``No`` button, an instance of :class:`Bitmap`.
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._yesBitmap, self._noBitmap = yesBitmap, noBitmap
+ return True
+
+
+ def SetYesNoCancelBitmaps(self, yesBitmap, noBitmap, cancelBitmap):
+ """
+ Overrides the default icons of the ``Yes`` and ``No`` buttons.
+
+ :param `yesBitmap`: the new icon for the ``Yes`` button, an instance of :class:`Bitmap`;
+ :param `noBitmap`: the new icon for the ``No`` button, an instance of :class:`Bitmap`;
+ :param `cancelBitmap`: the new icon for the ``Cancel`` button, an instance of :class:`Bitmap`.
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._yesBitmap, self._noBitmap, self._cancelBitmap = yesBitmap, noBitmap, cancelBitmap
+ return True
+
+
+ def SetOKBitmap(self, okBitmap):
+ """
+ Overrides the default icon of the ``OK`` button.
+
+ :param `yesBitmap`: the new icon for the ``OK`` button, an instance of :class:`Bitmap`;
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._okBitmap = okBitmap
+ return True
+
+
+ def SetOKCancelBitmaps(self, okBitmap, cancelBitmap):
+ """
+ Overrides the default icons of the ``OK`` and ``Cancel`` buttons.
+
+ :param `okBitmap`: the new icon for the ``OK`` button, an instance of :class:`Bitmap`;
+ :param `cancelBitmap`: the new icon for the ``Cancel`` button, an instance of :class:`Bitmap`.
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._okBitmap, self._cancelBitmap = okBitmap, cancelBitmap
+ return True
+
+
+ def SetHelpBitmap(self, helpBitmap):
+ """
+ Overrides the default icon of the ``Help`` button.
+
+ :param `helpBitmap`: the new icon for the ``Help`` button, an instance of :class:`Bitmap`.
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._helpBitmap = helpBitmap
+ return True
+
+
+ # Test if any custom icons were set
+ def HasCustomBitmaps(self):
+ """
+ Returns ``True`` if any of the buttons have a non-default icons.
+
+ .. versionadded:: 0.9.3
+ """
+
+ for icon in [self._okBitmap, self._noBitmap, self._yesBitmap,
+ self._cancelBitmap, self._helpBitmap]:
+ if icon is not None:
+ return True
+
+ return False
+
+
+ def WrapMessage(self, message, wrap, font=None):
+ """
+ Wraps the input message to multi lines so that the resulting new message
+ is at most `wrap` pixels wide.
+
+ :param `message`: the original input message;
+ :param `wrap`: wraps the string in `message` so that every line is at most
+ `wrap` pixels long;
+ :param `font`: if not ``None``, it should be an instance of :class:`Font` to be
+ used to measure and then wrap the input `message`.
+
+ :return: a new message wrapped at maximum `wrap` pixels wide.
+
+ .. todo::
+
+ Estabilish if wrapping all messages by default is a better idea than
+ provide a keyword parameter to :class:`GenericMessageDialog`. A default maximum
+ line width might be the wxMac one, at 360 pixels.
+
+ """
+
+ dc = wx.ClientDC(self)
+
+ if font is None:
+ dc.SetFont(self.GetFont())
+ else:
+ dc.SetFont(font)
+
+ newMessage = wordwrap.wordwrap(message, wrap, dc, False)
+ return newMessage
+
+
+ def ShowModal(self):
+ """
+ Shows the dialog, returning one of ``wx.ID_OK``, ``wx.ID_CANCEL``, ``wx.ID_YES``,
+ ``wx.ID_NO`` or ``wx.ID_HELP``.
+
+ :note: Notice that this method returns the identifier of the button which was
+ clicked unlike the :class:`MessageBox` () function.
+
+ :note: Reimplemented from :class:`Dialog`.
+ """
+
+ if not self._created:
+
+ self._created = True
+ self.CreateMessageDialog()
+
+ return wx.Dialog.ShowModal(self)
+
+
+ def GetCaption(self):
+ """
+ Returns the main caption (the title) for :class:`GenericMessageDialog`.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return self.GetTitle()
+
+
+ def SetMessage(self, message):
+ """
+ Sets the message shown by the dialog.
+
+ :param `message`: a string representing the main :class:`GenericMessageDialog` message.
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._message = message
+
+
+ def GetMessage(self):
+ """
+ Returns a string representing the main :class:`GenericMessageDialog` message.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return self._message
+
+
+ def SetExtendedMessage(self, extendedMessage):
+ """
+ Sets the extended message for the dialog: this message is usually an extension of the
+ short message specified in the constructor or set with :meth:`~GenericMessageDialog.SetMessage`.
+
+ If it is set, the main message appears highlighted and this message appears beneath
+ it in normal font.
+
+ :param `extendedMessage`: a string representing the extended :class:`GenericMessageDialog` message.
+
+ .. versionadded:: 0.9.3
+ """
+
+ self._extendedMessage = extendedMessage
+
+
+ def GetExtendedMessage(self):
+ """
+ Returns a string representing the extended :class:`GenericMessageDialog` message.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return self._extendedMessage
+
+
+ def GetMessageDialogStyle(self):
+ """
+ Returns the AGW-specific window style for :class:`GenericMessageDialog`.
+
+ .. versionadded:: 0.9.3
+ """
+
+ return self._agwStyle
+
+
+ # To combine the separate main and extended messages in a single string
+ def GetFullMessage(self):
+ """
+ Returns a string representing the combination of the main :class:`GenericMessageDialog`
+ message and the extended message, separated by an empty line.
+
+ .. versionadded:: 0.9.3
+ """
+
+ msg = self._message
+ if self._extendedMessage.strip():
+ msg += '\n\n' + self._extendedMessage
+
+ return msg
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/gradientbutton.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/gradientbutton.py
new file mode 100644
index 0000000..22479be
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/gradientbutton.py
@@ -0,0 +1,708 @@
+# --------------------------------------------------------------------------------- #
+# GRADIENTBUTTON wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 07 October 2008
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# TODO List
+#
+# 1) Anything to do?
+#
+#
+# For all kind of problems, requests of enhancements and bug reports, please
+# write to me at:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, obviously, to the wxPython mailing list!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`GradientButton` is another custom-drawn button class which mimics Windows CE mobile
+gradient buttons.
+
+
+Description
+===========
+
+:class:`GradientButton` is another custom-drawn button class which mimics Windows CE mobile
+gradient buttons, using a tri-vertex blended gradient plus some ClearType bold
+font (best effect with Tahoma Bold). :class:`GradientButton` supports:
+
+* Triple blended gradient background, with customizable colours;
+* Custom colours for the "pressed" state;
+* Rounded-corners buttons;
+* Text-only or image+text buttons.
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.gradientbutton as GB
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "GradientButton Demo")
+
+ panel = wx.Panel(self, -1)
+
+ # One button without bitmap
+ button_1 = GB.GradientButton(panel, -1, None, "Hello World", (100, 50))
+
+ # One button with bitmap
+ my_bitmap = wx.Bitmap("my_bitmap.png", wx.BITMAP_TYPE_PNG)
+ button_2 = GB.GradientButton(panel, -1, my_bitmap, "GradientButton", (100, 150))
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`GradientButton` has been tested on the following platforms:
+ * Windows (Windows XP).
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================= ==================================================
+Event Name Description
+================= ==================================================
+``wx.EVT_BUTTON`` Process a `wxEVT_COMMAND_BUTTON_CLICKED` event, when the button is clicked.
+================= ==================================================
+
+
+License And Version
+===================
+
+:class:`GradientButton` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.3
+
+"""
+
+import wx
+
+
+HOVER = 1
+""" Flag used to indicate that the mouse is hovering on a :class:`GradientButton`. """
+CLICK = 2
+""" Flag used to indicate that the :class:`GradientButton` is on a pressed state. """
+
+
+class GradientButtonEvent(wx.PyCommandEvent):
+ """ Event sent from :class:`GradientButton` when the button is activated. """
+
+ def __init__(self, eventType, eventId):
+ """
+ Default class constructor.
+
+ :param `eventType`: the event type;
+ :param `eventId`: the event identifier.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+ self.isDown = False
+ self.theButton = None
+
+
+ def SetButtonObj(self, btn):
+ """
+ Sets the event object for the event.
+
+ :param `btn`: the button object, an instance of :class:`GradientButton`.
+ """
+
+ self.theButton = btn
+
+
+ def GetButtonObj(self):
+ """ Returns the object associated with this event. """
+
+ return self.theButton
+
+
+class GradientButton(wx.PyControl):
+ """ This is the main class implementation of :class:`GradientButton`. """
+
+ def __init__(self, parent, id=wx.ID_ANY, bitmap=None, label="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.NO_BORDER, validator=wx.DefaultValidator,
+ name="gradientbutton"):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`GradientButton` parent;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `bitmap`: the button bitmap (if any);
+ :param `label`: the button text label;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the button style (unused);
+ :param `validator`: the validator associated to the button;
+ :param `name`: the button name.
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnGainFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnLoseFocus)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
+
+ self._mouseAction = None
+ self._bitmap = bitmap
+ self._hasFocus = False
+
+ self.SetLabel(label)
+ self.InheritAttributes()
+ self.SetInitialSize(size)
+
+ self.SetBaseColours()
+
+
+ def SetBaseColours(self, startcolour=wx.BLACK, foregroundcolour=wx.WHITE):
+ """Sets the bottom, top, pressed and foreground colour
+
+ :param startcolour: based colour to be used for bottom, top and pressed
+ :param foregroundcolour: colour used for the text
+
+ """
+ self._bottomStartColour = startcolour
+ rgba = self._bottomStartColour.Red(), self._bottomStartColour.Green(), \
+ self._bottomStartColour.Blue(), self._bottomStartColour.Alpha()
+ self._bottomEndColour = self.LightColour(self._bottomStartColour, 20)
+ self._topStartColour = self.LightColour(self._bottomStartColour, 40)
+ self._topEndColour = self.LightColour(self._bottomStartColour, 25)
+ self._pressedTopColour = self.LightColour(self._bottomStartColour, 20)
+ self._pressedBottomColour = wx.Colour(*rgba)
+ self.SetForegroundColour(foregroundcolour)
+
+
+ def LightColour(self, colour, percent):
+ """
+ Return light contrast of `colour`. The colour returned is from the scale of
+ `colour` ==> white.
+
+ :param `colour`: the input colour to be brightened;
+ :param `percent`: determines how light the colour will be. `percent` = 100
+ returns white, `percent` = 0 returns `colour`.
+ """
+
+ end_colour = wx.WHITE
+ rd = end_colour.Red() - colour.Red()
+ gd = end_colour.Green() - colour.Green()
+ bd = end_colour.Blue() - colour.Blue()
+ high = 100
+
+ # We take the percent way of the colour from colour -. white
+ i = percent
+ r = colour.Red() + ((i*rd*100)/high)/100
+ g = colour.Green() + ((i*gd*100)/high)/100
+ b = colour.Blue() + ((i*bd*100)/high)/100
+
+ return wx.Colour(r, g, b)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`GradientButton`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ event.Skip()
+ self.Refresh()
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`GradientButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ self._mouseAction = CLICK
+ self.CaptureMouse()
+ self.Refresh()
+ event.Skip()
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`GradientButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled() or not self.HasCapture():
+ return
+
+ pos = event.GetPosition()
+ rect = self.GetClientRect()
+
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+ if rect.Contains(pos):
+ self._mouseAction = HOVER
+ self.Notify()
+ else:
+ self._mouseAction = None
+
+ self.Refresh()
+ event.Skip()
+
+
+ def OnMouseEnter(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`GradientButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ self._mouseAction = HOVER
+ self.Refresh()
+ event.Skip()
+
+
+ def OnMouseLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`GradientButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self._mouseAction = None
+ self.Refresh()
+ event.Skip()
+
+
+ def OnGainFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`GradientButton`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self._hasFocus = True
+ self.Refresh()
+ self.Update()
+
+
+ def OnLoseFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`GradientButton`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self._hasFocus = False
+ self.Refresh()
+ self.Update()
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`GradientButton`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if self._hasFocus and event.GetKeyCode() == ord(" "):
+ self._mouseAction = HOVER
+ self.Refresh()
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` event for :class:`GradientButton`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if self._hasFocus and event.GetKeyCode() == ord(" "):
+ self._mouseAction = HOVER
+ self.Notify()
+ self.Refresh()
+ event.Skip()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`GradientButton`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+ gc = wx.GraphicsContext.Create(dc)
+ dc.SetBackground(wx.Brush(self.GetParent().GetBackgroundColour()))
+ dc.Clear()
+
+ clientRect = self.GetClientRect()
+ gradientRect = wx.Rect(*clientRect)
+ capture = wx.Window.GetCapture()
+
+ x, y, width, height = clientRect
+
+ gradientRect.SetHeight(gradientRect.GetHeight()/2 + ((capture==self and [1] or [0])[0]))
+ if capture != self:
+ if self._mouseAction == HOVER:
+ topStart, topEnd = self.LightColour(self._topStartColour, 10), self.LightColour(self._topEndColour, 10)
+ else:
+ topStart, topEnd = self._topStartColour, self._topEndColour
+
+ rc1 = wx.Rect(x, y, width, height/2)
+ path1 = self.GetPath(gc, rc1, 8)
+ br1 = gc.CreateLinearGradientBrush(x, y, x, y+height/2, topStart, topEnd)
+ gc.SetBrush(br1)
+ gc.FillPath(path1) #draw main
+
+ path4 = gc.CreatePath()
+ path4.AddRectangle(x, y+height/2-8, width, 8)
+ path4.CloseSubpath()
+ gc.SetBrush(br1)
+ gc.FillPath(path4)
+
+ else:
+
+ rc1 = wx.Rect(x, y, width, height)
+ path1 = self.GetPath(gc, rc1, 8)
+ gc.SetPen(wx.Pen(self._pressedTopColour))
+ gc.SetBrush(wx.Brush(self._pressedTopColour))
+ gc.FillPath(path1)
+
+ gradientRect.Offset((0, gradientRect.GetHeight()))
+
+ if capture != self:
+
+ if self._mouseAction == HOVER:
+ bottomStart, bottomEnd = self.LightColour(self._bottomStartColour, 10), self.LightColour(self._bottomEndColour, 10)
+ else:
+ bottomStart, bottomEnd = self._bottomStartColour, self._bottomEndColour
+
+ rc3 = wx.Rect(x, y+height/2, width, height/2)
+ path3 = self.GetPath(gc, rc3, 8)
+ br3 = gc.CreateLinearGradientBrush(x, y+height/2, x, y+height, bottomStart, bottomEnd)
+ gc.SetBrush(br3)
+ gc.FillPath(path3) #draw main
+
+ path4 = gc.CreatePath()
+ path4.AddRectangle(x, y+height/2, width, 8)
+ path4.CloseSubpath()
+ gc.SetBrush(br3)
+ gc.FillPath(path4)
+
+ shadowOffset = 0
+ else:
+
+ rc2 = wx.Rect(x+1, gradientRect.height/2, gradientRect.width, gradientRect.height)
+ path2 = self.GetPath(gc, rc2, 8)
+ gc.SetPen(wx.Pen(self._pressedBottomColour))
+ gc.SetBrush(wx.Brush(self._pressedBottomColour))
+ gc.FillPath(path2)
+ shadowOffset = 1
+
+ font = gc.CreateFont(self.GetFont(), self.GetForegroundColour())
+ gc.SetFont(font)
+ label = self.GetLabel()
+ tw, th = gc.GetTextExtent(label)
+
+ if self._bitmap:
+ bw, bh = self._bitmap.GetWidth(), self._bitmap.GetHeight()
+ else:
+ bw = bh = 0
+
+ pos_x = (width-bw-tw)/2+shadowOffset # adjust for bitmap and text to centre
+ if self._bitmap:
+ pos_y = (height-bh)/2+shadowOffset
+ gc.DrawBitmap(self._bitmap, pos_x, pos_y, bw, bh) # draw bitmap if available
+ pos_x = pos_x + 2 # extra spacing from bitmap
+
+ gc.DrawText(label, pos_x + bw + shadowOffset, (height-th)/2+shadowOffset)
+
+
+ def GetPath(self, gc, rc, r):
+ """
+ Returns a rounded :class:`GraphicsPath` rectangle.
+
+ :param `gc`: an instance of :class:`GraphicsContext`;
+ :param `rc`: a client rectangle;
+ :param `r`: the radious of the rounded part of the rectangle.
+ """
+
+ x, y, w, h = rc
+ path = gc.CreatePath()
+ path.AddRoundedRectangle(x, y, w, h, r)
+ path.CloseSubpath()
+ return path
+
+
+ def SetInitialSize(self, size=None):
+ """
+ Given the current font and bezel width settings, calculate
+ and set a good size.
+
+ :param `size`: an instance of :class:`Size`.
+ """
+
+ if size is None:
+ size = wx.DefaultSize
+ wx.PyControl.SetInitialSize(self, size)
+
+ SetBestSize = SetInitialSize
+
+
+ def AcceptsFocus(self):
+ """
+ Can this window be given focus by mouse click?
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self.IsShown() and self.IsEnabled()
+
+
+ def GetDefaultAttributes(self):
+ """
+ Overridden base class virtual. By default we should use
+ the same font/colour attributes as the native :class:`Button`.
+ """
+
+ return wx.Button.GetClassDefaultAttributes()
+
+
+ def ShouldInheritColours(self):
+ """
+ Overridden base class virtual. Buttons usually don't inherit
+ the parent's colours.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return False
+
+
+ def Enable(self, enable=True):
+ """
+ Enables/disables the button.
+
+ :param `enable`: ``True`` to enable the button, ``False`` to disable it.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ wx.PyControl.Enable(self, enable)
+ self.Refresh()
+
+
+ def SetTopStartColour(self, colour):
+ """
+ Sets the top start colour for the gradient shading.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._topStartColour = colour
+ self.Refresh()
+
+
+ def GetTopStartColour(self):
+ """ Returns the top start colour for the gradient shading. """
+
+ return self._topStartColour
+
+
+ def SetTopEndColour(self, colour):
+ """
+ Sets the top end colour for the gradient shading.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._topEndColour = colour
+ self.Refresh()
+
+
+ def GetTopEndColour(self):
+ """ Returns the top end colour for the gradient shading. """
+
+ return self._topEndColour
+
+
+ def SetBottomStartColour(self, colour):
+ """
+ Sets the top bottom colour for the gradient shading.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._bottomStartColour = colour
+ self.Refresh()
+
+
+ def GetBottomStartColour(self):
+ """ Returns the bottom start colour for the gradient shading. """
+
+ return self._bottomStartColour
+
+
+ def SetBottomEndColour(self, colour):
+ """
+ Sets the bottom end colour for the gradient shading.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._bottomEndColour = colour
+ self.Refresh()
+
+
+ def GetBottomEndColour(self):
+ """ Returns the bottom end colour for the gradient shading. """
+
+ return self._bottomEndColour
+
+
+ def SetPressedTopColour(self, colour):
+ """
+ Sets the pressed top start colour for the gradient shading.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._pressedTopColour = colour
+ self.Refresh()
+
+
+ def GetPressedTopColour(self):
+ """ Returns the pressed top start colour for the gradient shading. """
+
+ return self._pressedTopColour
+
+
+ def SetPressedBottomColour(self, colour):
+ """
+ Sets the pressed bottom start colour for the gradient shading.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._pressedBottomColour = colour
+ self.Refresh()
+
+
+ def GetPressedBottomColour(self):
+ """ Returns the pressed bottom start colour for the gradient shading. """
+
+ return self._pressedBottomColour
+
+
+ def SetForegroundColour(self, colour):
+ """
+ Sets the :class:`GradientButton` foreground (text) colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ wx.PyControl.SetForegroundColour(self, colour)
+ self.Refresh()
+
+
+ def DoGetBestSize(self):
+ """
+ Overridden base class virtual. Determines the best size of the
+ button based on the label and bezel size.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ label = self.GetLabel()
+ if not label:
+ return wx.Size(112, 48)
+
+ dc = wx.ClientDC(self)
+ dc.SetFont(self.GetFont())
+ retWidth, retHeight = dc.GetTextExtent(label)
+
+ bmpWidth = bmpHeight = 0
+ constant = 15
+ if self._bitmap:
+ bmpWidth, bmpHeight = self._bitmap.GetWidth()+10, self._bitmap.GetHeight()
+ retWidth += bmpWidth
+ retHeight = max(bmpHeight, retHeight)
+ constant = 15
+
+ return wx.Size(retWidth+constant, retHeight+constant)
+
+
+ def SetDefault(self):
+ """ Sets the default button. """
+
+ tlw = wx.GetTopLevelParent(self)
+ if hasattr(tlw, 'SetDefaultItem'):
+ tlw.SetDefaultItem(self)
+
+
+ def Notify(self):
+ """ Actually sends a ``wx.EVT_BUTTON`` event to the listener (if any). """
+
+ evt = GradientButtonEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
+ evt.SetButtonObj(self)
+ evt.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(evt)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/hyperlink.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/hyperlink.py
new file mode 100644
index 0000000..511fac6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/hyperlink.py
@@ -0,0 +1,622 @@
+# --------------------------------------------------------------------------- #
+# HYPERLINKSCTRL wxPython IMPLEMENTATION
+# Ported From Angelo Mandato C++ Code By:
+#
+# Andrea Gavana, @ 27 Mar 2005
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# Original Web Site (For The C++ Code):
+#
+# http://www.spaceblue.com/codedetail.php?CodeID=7
+#
+#
+# Thanks to E. A. Tacao for his nice suggestions and improvements of the code.
+#
+# For all kind of problems, requests of enhancements and bug reports, please
+# write to me at:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, obviously, to the wxPython mailing list!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+:class:`HyperLinkCtrl` is a control for wxPython that acts like a hyper link
+in a typical browser.
+
+
+Description
+===========
+
+:class:`HyperLinkCtrl` is a control for wxPython that acts like a hyper link
+in a typical browser. Latest features include the ability to capture
+your own left, middle, and right click events to perform your own
+custom event handling and ability to open link in a new or current
+browser window.
+
+Special thanks to Robin Dunn for the event binder for the 3 mouse buttons.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.hyperlink as hl
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "HyperLink Demo")
+
+ panel = wx.Panel(self, -1)
+
+ # Default Web links:
+ hyper1 = hl.HyperLinkCtrl(panel, -1, "wxPython Main Page", pos=(100, 100),
+ URL="http://www.wxpython.org/")
+
+
+ # Web link with underline rollovers, opens in same window
+ hyper2 = hl.HyperLinkCtrl(panel, -1, "My Home Page", pos=(100, 150),
+ URL="http://xoomer.virgilio.it/infinity77/")
+
+ hyper2.AutoBrowse(False)
+ hyper2.SetColours("BLUE", "BLUE", "BLUE")
+ hyper2.EnableRollover(True)
+ hyper2.SetUnderlines(False, False, True)
+ hyper2.SetBold(True)
+ hyper2.OpenInSameWindow(True)
+ hyper2.SetToolTip(wx.ToolTip("Hello World!"))
+ hyper2.UpdateLink()
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+======================== ==================================================
+Event Name Description
+======================== ==================================================
+``EVT_HYPERLINK_LEFT`` Responds to a left mouse button event. Sent when the left mouse button is clicked, but only if `AutoBrowse` is set to ``False``.
+``EVT_HYPERLINK_MIDDLE`` Responds to a middle mouse button event. Sent when the middle mouse button is clicked.
+``EVT_HYPERLINK_RIGHT`` Handles a right mouse button event. Sent when the right mouse button is clicked, but only if `DoPopup` is set to ``False``.
+======================== ==================================================
+
+
+License And Version
+===================
+
+:class:`HyperLinkCtrl` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.6
+
+"""
+
+import wx
+from wx.lib.stattext import GenStaticText as StaticText
+
+# Import the useful webbrowser module for platform-independent results
+import webbrowser
+
+# Set no delay time to open the web page
+webbrowser.PROCESS_CREATION_DELAY = 0
+
+# To show a popup that copies the hyperlinks on the clipboard
+wxHYPERLINKS_POPUP_COPY = 1000
+""" Flag used to show a popup that copies the hyperlinks on the clipboard. """
+
+
+#-----------------------------------#
+# HyperLinksEvents
+#-----------------------------------#
+
+# wxEVT_HYPERLINK_LEFT: Respond To A Left Mouse Button Event
+# wxEVT_HYPERLINK_MIDDLE: Respond To A Middle Mouse Button Event
+# wxEVT_HYPERLINK_RIGHT: Respond To A Right Mouse Button Event
+
+wxEVT_HYPERLINK_LEFT = wx.NewEventType()
+wxEVT_HYPERLINK_MIDDLE = wx.NewEventType()
+wxEVT_HYPERLINK_RIGHT = wx.NewEventType()
+
+EVT_HYPERLINK_LEFT = wx.PyEventBinder(wxEVT_HYPERLINK_LEFT, 1)
+""" Responds to a left mouse button event. Sent when the left mouse button is""" \
+""" clicked, but only if `AutoBrowse` is set to ``False``. """
+EVT_HYPERLINK_MIDDLE = wx.PyEventBinder(wxEVT_HYPERLINK_MIDDLE, 1)
+""" Responds to a middle mouse button event. Sent when the middle mouse button is clicked. """
+EVT_HYPERLINK_RIGHT = wx.PyEventBinder(wxEVT_HYPERLINK_RIGHT, 1)
+""" Handles a right mouse button event. Sent when the right mouse button is""" \
+""" clicked, but only if `DoPopup` is set to ``False``. """
+
+
+# ------------------------------------------------------------
+# This class implements the event listener for the hyperlinks
+# ------------------------------------------------------------
+
+class HyperLinkEvent(wx.PyCommandEvent):
+ """
+ Event object sent in response to clicking on a :class:`HyperLinkCtrl`.
+ """
+
+ def __init__(self, eventType, eventId):
+ """
+ Default Class Constructor.
+
+ :param `eventType`: the event type;
+ :param `eventId`: the event identifier.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+ self._eventType = eventType
+
+
+ def SetPosition(self, pos):
+ """
+ Sets the event position.
+
+ :param `pos`: an instance of :class:`Point`.
+ """
+
+ self._pos = pos
+
+
+ def GetPosition(self):
+ """ Returns the event position. """
+
+ return self._pos
+
+
+# -------------------------------------------------
+# This is the main HyperLinkCtrl implementation
+# it user the StatiText from wx.lib.stattext
+# because of its "quasi-dynamic" behavior
+# -------------------------------------------------
+
+class HyperLinkCtrl(StaticText):
+ """
+ :class:`HyperLinkCtrl` is a control for wxPython that acts like a hyper
+ link in a typical browser. Latest features include the ability to
+ capture your own left, middle, and right click events to perform
+ your own custom event handling and ability to open link in a new
+ or current browser window.
+ """
+
+ def __init__(self, parent, id=-1, label="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name="staticText", URL=""):
+ """
+ Default class constructor.
+
+ :param `parent`: the window parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `label`: the control label;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `name`: the window name;
+ :param `URL`: a string specifying the url link to navigate to.
+
+ :note: Pass URL="" to use the label as the url link to navigate to.
+ """
+
+ StaticText.__init__(self, parent, id, label, pos, size,
+ style, name)
+
+ if URL.strip() == "":
+ self._URL = label
+ else:
+ self._URL = URL
+
+ # Set Tooltip
+ self.SetToolTip(wx.ToolTip(self._URL))
+
+ # Set default properties
+ # default: True
+ self.ReportErrors()
+
+ # default: True, True, True
+ self.SetUnderlines()
+
+ # default: blue, violet, blue
+ self.SetColours()
+
+ # default: False
+ self.SetVisited()
+
+ # default: False
+ self.EnableRollover()
+
+ # default: False
+ self.SetBold()
+
+ # default: wx.CURSOR_HAND
+ self.SetLinkCursor()
+
+ # default True
+ self.AutoBrowse()
+
+ # default True
+ self.DoPopup()
+
+ # default False
+ self.OpenInSameWindow()
+
+ # Set control properties and refresh
+ self.UpdateLink(True)
+
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
+ self.Bind(wx.EVT_MOTION, self.OnMouseEvent)
+
+
+ def GotoURL(self, URL, ReportErrors=True, NotSameWinIfPossible=False):
+ """
+ Goto the specified URL.
+
+ :param `URL`: the url link we wish to navigate;
+ :param `ReportErrors`: Use ``True`` to display error dialog if an error
+ occurrs navigating to the URL;
+ :param `NotSameWinIfPossible`: Use ``True`` to attempt to open the URL
+ in new browser window.
+ """
+
+ logOff = wx.LogNull()
+
+ try:
+ webbrowser.open(URL, new=NotSameWinIfPossible)
+ self.SetVisited(True)
+ self.UpdateLink(True)
+
+ return True
+
+ except:
+ self.DisplayError("Unable To Launch Browser.", ReportErrors)
+ return False
+
+
+ def OnMouseEvent(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` events for :class:`HyperLinkCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if event.Moving():
+ # Mouse Is Moving On The StaticText
+ # Set The Hand Cursor On The Link
+ self.SetCursor(self._CursorHand)
+
+ if self._EnableRollover:
+ fontTemp = self.GetFont()
+ fontTemp.SetUnderlined(self._RolloverUnderline)
+ if self._Bold:
+ fontTemp.SetWeight(wx.BOLD)
+
+ needRefresh = False
+
+ if self.GetFont() != fontTemp:
+ self.SetFont(fontTemp)
+ needRefresh = True
+
+ if self.GetForegroundColour() != self._LinkRolloverColour:
+ self.SetForegroundColour(self._LinkRolloverColour)
+ needRefresh = True
+
+ if needRefresh:
+ self.Refresh()
+
+ else:
+ # Restore The Original Cursor
+ self.SetCursor(wx.NullCursor)
+ if self._EnableRollover:
+ self.UpdateLink(True)
+
+ if event.LeftUp():
+ # Left Button Was Pressed
+ if self._AutoBrowse:
+ self.GotoURL(self._URL, self._ReportErrors,
+ self._NotSameWinIfPossible)
+
+ else:
+ eventOut = HyperLinkEvent(wxEVT_HYPERLINK_LEFT, self.GetId())
+ eventOut.SetEventObject(self)
+ eventOut.SetPosition(event.GetPosition())
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+ self.SetVisited(True)
+
+ elif event.RightUp():
+ # Right Button Was Pressed
+ if self._DoPopup:
+ # Popups A Menu With The "Copy HyperLynks" Feature
+ menuPopUp = wx.Menu("", wx.MENU_TEAROFF)
+ menuPopUp.Append(wxHYPERLINKS_POPUP_COPY, "Copy HyperLink")
+ self.Bind(wx.EVT_MENU, self.OnPopUpCopy, id=wxHYPERLINKS_POPUP_COPY)
+ self.PopupMenu(menuPopUp, wx.Point(event.X, event.Y))
+ menuPopUp.Destroy()
+ self.Unbind(wx.EVT_MENU, id=wxHYPERLINKS_POPUP_COPY)
+
+ else:
+ eventOut = HyperLinkEvent(wxEVT_HYPERLINK_RIGHT, self.GetId())
+ eventOut.SetEventObject(self)
+ eventOut.SetPosition(event.GetPosition())
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+ elif event.MiddleUp():
+ # Middle Button Was Pressed
+ eventOut = HyperLinkEvent(wxEVT_HYPERLINK_MIDDLE, self.GetId())
+ eventOut.SetEventObject(self)
+ eventOut.SetPosition(event.GetPosition())
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+ event.Skip()
+
+
+ def OnPopUpCopy(self, event):
+ """
+ Handles the ``wx.EVT_MENU`` event for :class:`HyperLinkCtrl`.
+
+ :param `event`: a :class:`MenuEvent` event to be processed.
+
+ :note: This method copies the data from the :class:`HyperLinkCtrl` to the clipboard.
+ """
+
+ wx.TheClipboard.UsePrimarySelection(False)
+ if not wx.TheClipboard.Open():
+ return
+ data = wx.TextDataObject(self._URL)
+ wx.TheClipboard.SetData(data)
+ wx.TheClipboard.Close()
+
+
+ def UpdateLink(self, OnRefresh=True):
+ """
+ Updates the link, changing text properties if:
+
+ - User specific setting;
+ - Link visited;
+ - New link;
+
+ :param `OnRefresh`: ``True`` to refresh the control, ``False`` otherwise.
+
+ """
+
+ fontTemp = self.GetFont()
+
+ if self._Visited:
+ self.SetForegroundColour(self._VisitedColour)
+ fontTemp.SetUnderlined(self._VisitedUnderline)
+
+ else:
+
+ self.SetForegroundColour(self._LinkColour)
+ fontTemp.SetUnderlined(self._LinkUnderline)
+
+ if self._Bold:
+ fontTemp.SetWeight(wx.BOLD)
+
+ if self.GetFont() != fontTemp:
+ self.SetFont(fontTemp)
+
+ self.Refresh(OnRefresh)
+
+
+ def DisplayError(self, ErrorMessage, ReportErrors=True):
+ """
+ Displays an error message (according to the `ReportErrors` parameter) in a
+ :class:`MessageBox`.
+
+ :param `ErrorMessage`: a string representing the error to display;
+ :param `ReportErrors`: ``True`` to display error dialog if an error occurrs
+ navigating to the URL.
+ """
+
+ if ReportErrors:
+ wx.MessageBox(ErrorMessage, "HyperLinks Error", wx.OK | wx.CENTRE | wx.ICON_ERROR)
+
+
+ def SetColours(self, link=wx.Colour(0, 0, 255), visited=wx.Colour(79, 47, 79),
+ rollover=wx.Colour(0, 0, 255)):
+ """
+ Sets the colours for the link, the visited link and the mouse rollover.
+
+ - Visited link: VIOLET
+ - Rollover: BLUE
+
+ :param `link`: a valid :class:`Colour` to use as text foreground for new links
+ (default=RED);
+ :param `visited`: a valid :class:`Colour` to use as text foreground for visited
+ links (default=VIOLET);
+ :param `rollover`: a valid :class:`Colour` to use as text foreground for links
+ rollovers (default=BLUE).
+ """
+
+ self._LinkColour = link
+ self._VisitedColour = visited
+ self._LinkRolloverColour = rollover
+
+
+ def GetColours(self):
+ """
+ Gets the colours for the link, the visited link and the mouse
+ rollover.
+ """
+
+ return self._LinkColour, self._VisitedColour, self._LinkRolloverColour
+
+
+ def SetUnderlines(self, link=True, visited=True, rollover=True):
+ """
+ Sets whether the text should be underlined or not for new links, visited
+ links and rollovers.
+
+ :param `link`: ``True`` to set the text of new links as underlined, ``False``
+ otherwise;
+ :param `visited`: ``True`` to set the text of visited links as underlined,
+ ``False`` otherwise;
+ :param `rollover`: ``True`` to set the text of rollovers as underlined,
+ ``False`` otherwise.
+ """
+
+ self._LinkUnderline = link
+ self._RolloverUnderline = rollover
+ self._VisitedUnderline = visited
+
+
+ def GetUnderlines(self):
+ """
+ Returns if link is underlined, if the mouse rollover is
+ underlined and if the visited link is underlined.
+ """
+
+ return self._LinkUnderline, self._RolloverUnderline, self._VisitedUnderline
+
+
+ def SetLinkCursor(self, cur=wx.CURSOR_HAND):
+ """
+ Sets link cursor properties.
+
+ :param `cur`: an integer representing a :class:`StockCursor` constant.
+ """
+
+ self._CursorHand = wx.StockCursor(cur)
+
+
+ def GetLinkCursor(self):
+ """ Gets the link cursor. """
+
+ return self._CursorHand
+
+
+ def SetVisited(self, Visited=False):
+ """
+ Sets a link as visited.
+
+ :param `Visited`: ``True`` to set a link as visited, ``False`` otherwise.
+ """
+
+ self._Visited = Visited
+
+
+ def GetVisited(self):
+ """ Returns whether a link has been visited or not. """
+
+ return self._Visited
+
+
+ def SetBold(self, Bold=False):
+ """
+ Sets the :class:`HyperLinkCtrl` label in bold text.
+
+ :param `Bold`: ``True`` to set the :class:`HyperLinkCtrl` label as bold, ``False``
+ otherwise.
+ """
+
+ self._Bold = Bold
+
+
+ def GetBold(self):
+ """ Returns whether the :class:`HyperLinkCtrl` has text in bold or not. """
+
+ return self._Bold
+
+
+ def SetURL(self, URL):
+ """
+ Sets the :class:`HyperLinkCtrl` text to the specified URL.
+
+ :param `URL`: the new URL associated with :class:`HyperLinkCtrl`.
+ """
+
+ self._URL = URL
+
+
+ def GetURL(self):
+ """ Retrieve the URL associated to the :class:`HyperLinkCtrl`. """
+
+ return self._URL
+
+
+ def OpenInSameWindow(self, NotSameWinIfPossible=False):
+ """
+ Open multiple URL in the same window (if possible).
+
+ :param `NotSameWinIfPossible`: ``True`` to open an hyperlink in a new browser
+ window, ``False`` to use an existing browser window.
+ """
+
+ self._NotSameWinIfPossible = NotSameWinIfPossible
+
+
+ def EnableRollover(self, EnableRollover=False):
+ """
+ Enable/disable rollover.
+
+ :param `EnableRollover`: ``True`` to enable text effects during rollover,
+ ``False`` to disable them.
+ """
+
+ self._EnableRollover = EnableRollover
+
+
+ def ReportErrors(self, ReportErrors=True):
+ """
+ Set whether to report browser errors or not.
+
+ :param `ReportErrors`: Use ``True`` to display error dialog if an error
+ occurrs navigating to the URL;
+ """
+
+ self._ReportErrors = ReportErrors
+
+
+ def AutoBrowse(self, AutoBrowse=True):
+ """
+ Automatically browse to URL when clicked.
+
+ :param `AutoBrowse`: ``True`` to automatically browse to an URL when clicked,
+ ``False`` otherwise.
+
+ :note: Set `AutoBrowse` to ``False`` to receive ``EVT_HYPERLINK_LEFT`` events.
+ """
+
+ self._AutoBrowse = AutoBrowse
+
+
+ def DoPopup(self, DoPopup=True):
+ """
+ Sets whether to show popup menu on right click or not.
+
+ :param `DoPopup`: ``True`` to show a popup menu on right click, ``False`` otherwise.
+ """
+
+ self._DoPopup = DoPopup
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/hypertreelist.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/hypertreelist.py
new file mode 100644
index 0000000..a74226d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/hypertreelist.py
@@ -0,0 +1,4886 @@
+# --------------------------------------------------------------------------------- #
+# HYPERTREELIST wxPython IMPLEMENTATION
+# Inspired By And Heavily Based On wx.gizmos.TreeListCtrl.
+#
+# Andrea Gavana, @ 08 May 2006
+# Latest Revision: 30 Jul 2014, 21.00 GMT
+#
+#
+# TODO List
+#
+# Almost All The Features Of wx.gizmos.TreeListCtrl Are Available, And There Is
+# Practically No Limit In What Could Be Added To This Class. The First Things
+# That Comes To My Mind Are:
+#
+# 1. Add Support For 3-State CheckBoxes (Is That Really Useful?).
+#
+# 2. Try To Implement A More Flicker-Free Background Image In Cases Like
+# Centered Or Stretched Image (Now HyperTreeList Supports Only Tiled
+# Background Images).
+#
+# 3. Try To Mimic Windows wx.TreeCtrl Expanding/Collapsing behaviour: HyperTreeList
+# Suddenly Expands/Collapses The Nodes On Mouse Click While The Native Control
+# Has Some Kind Of "Smooth" Expanding/Collapsing, Like A Wave. I Don't Even
+# Know Where To Start To Do That.
+#
+# 4. Speed Up General OnPaint Things? I Have No Idea, Here HyperTreeList Is Quite
+# Fast, But We Should See On Slower Machines.
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+
+"""
+:class:`HyperTreeList` is a class that mimics the behaviour of :class:`gizmos.TreeListCtrl`, with
+some more functionalities.
+
+
+Description
+===========
+
+:class:`HyperTreeList` is a class that mimics the behaviour of :class:`gizmos.TreeListCtrl`, with
+almost the same base functionalities plus some more enhancements. This class does
+not rely on the native control, as it is a full owner-drawn tree-list control.
+
+:class:`HyperTreeList` is somewhat an hybrid between :class:`~lib.agw.customtreectrl.CustomTreeCtrl` and :class:`gizmos.TreeListCtrl`.
+
+In addition to the standard :class:`gizmos.TreeListCtrl` behaviour this class supports:
+
+* CheckBox-type items: checkboxes are easy to handle, just selected or unselected
+ state with no particular issues in handling the item's children;
+* Added support for 3-state value checkbox items;
+* RadioButton-type items: since I elected to put radiobuttons in :class:`~lib.agw.customtreectrl.CustomTreeCtrl`, I
+ needed some way to handle them, that made sense. So, I used the following approach:
+
+ - All peer-nodes that are radiobuttons will be mutually exclusive. In other words,
+ only one of a set of radiobuttons that share a common parent can be checked at
+ once. If a radiobutton node becomes checked, then all of its peer radiobuttons
+ must be unchecked.
+ - If a radiobutton node becomes unchecked, then all of its child nodes will become
+ inactive.
+
+* Hyperlink-type items: they look like an hyperlink, with the proper mouse cursor on
+ hovering;
+* Multiline text items;
+* Enabling/disabling items (together with their plain or grayed out icons);
+* Whatever non-toplevel widget can be attached next to a tree item;
+* Whatever non-toplevel widget can be attached next to a list item;
+* Column headers are fully customizable in terms of icons, colour, font, alignment etc...;
+* Default selection style, gradient (horizontal/vertical) selection style and Windows
+ Vista selection style;
+* Customized drag and drop images built on the fly;
+* Setting the :class:`HyperTreeList` item buttons to a personalized imagelist;
+* Setting the :class:`HyperTreeList` check/radio item icons to a personalized imagelist;
+* Changing the style of the lines that connect the items (in terms of :class:`Pen` styles);
+* Using an image as a :class:`HyperTreeList` background (currently only in "tile" mode);
+* Ellipsization of long items when the horizontal space is low, via the ``TR_ELLIPSIZE_LONG_ITEMS``
+ style (`New in version 0.9.3`).
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+Base Functionalities
+====================
+
+:class:`HyperTreeList` supports all the :class:`gizmos.TreeListCtrl` styles, except:
+
+- ``TR_EXTENDED``: supports for this style is on the todo list (Am I sure of this?).
+
+Plus it has 3 more styles to handle checkbox-type items:
+
+- ``TR_AUTO_CHECK_CHILD``: automatically checks/unchecks the item children;
+- ``TR_AUTO_CHECK_PARENT``: automatically checks/unchecks the item parent;
+- ``TR_AUTO_TOGGLE_CHILD``: automatically toggles the item children.
+
+And a style useful to hide the TreeListCtrl header:
+
+- ``TR_NO_HEADER``: hides the :class:`HyperTreeList` header.
+
+And a style related to long items (with a lot of text in them), which can be
+ellipsized:
+
+- ``TR_ELLIPSIZE_LONG_ITEMS``: ellipsizes long items when the horizontal space for
+ :class:`HyperTreeList` is low (`New in version 0.9.3`).
+
+
+All the methods available in :class:`gizmos.TreeListCtrl` are also available in :class:`HyperTreeList`.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.hypertreelist as HTL
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "HyperTreeList Demo")
+
+ tree_list = HTL.HyperTreeList(self)
+
+ tree_list.AddColumn("First column")
+
+ root = tree_list.AddRoot("Root", ct_type=1)
+
+ parent = tree_list.AppendItem(root, "First child", ct_type=1)
+ child = tree_list.AppendItem(parent, "First Grandchild", ct_type=1)
+
+ tree_list.AppendItem(root, "Second child", ct_type=1)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Events
+======
+
+All the events supported by :class:`gizmos.TreeListCtrl` are also available in :class:`HyperTreeList`,
+with a few exceptions:
+
+- ``EVT_TREE_GET_INFO`` (don't know what this means);
+- ``EVT_TREE_SET_INFO`` (don't know what this means);
+- ``EVT_TREE_ITEM_MIDDLE_CLICK`` (not implemented, but easy to add);
+- ``EVT_TREE_STATE_IMAGE_CLICK`` (no need for that, look at the checking events below).
+
+Plus, :class:`HyperTreeList` supports the events related to the checkbutton-type items:
+
+- ``EVT_TREE_ITEM_CHECKING``: an item is being checked;
+- ``EVT_TREE_ITEM_CHECKED``: an item has been checked.
+
+And to hyperlink-type items:
+
+- ``EVT_TREE_ITEM_HYPERLINK``: an hyperlink item has been clicked (this event is sent
+ after the ``EVT_TREE_SEL_CHANGED`` event).
+
+
+Supported Platforms
+===================
+
+:class:`HyperTreeList` has been tested on the following platforms:
+ * Windows (Windows XP), Vista, 7;
+ * Linux
+ * Mac
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+============================== =========== ==================================================
+Window Styles Hex Value Description
+============================== =========== ==================================================
+``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn.
+``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default.
+``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items.
+``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors.
+``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set.
+``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit.
+``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons.
+``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected.
+``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases).
+``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset.
+``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control.
+``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows.
+``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes.
+``TR_COLUMN_LINES`` 0x1000 Use this style to draw a contrasting border between displayed columns.
+``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window.
+``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well.
+``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly.
+``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful foe checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well.
+``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position.
+``TR_NO_HEADER`` 0x40000 Use this style to hide the columns header.
+``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`HyperTreeList` columns is low.
+``TR_VIRTUAL`` 0x100000 :class:`HyperTreeList` will have virtual behaviour.
+============================== =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+============================== ==================================================
+Event Name Description
+============================== ==================================================
+``EVT_LIST_COL_BEGIN_DRAG`` The user started resizing a column - can be vetoed.
+``EVT_LIST_COL_CLICK`` A column has been left-clicked.
+``EVT_LIST_COL_DRAGGING`` The divider between columns is being dragged.
+``EVT_LIST_COL_END_DRAG`` A column has been resized by the user.
+``EVT_LIST_COL_RIGHT_CLICK`` A column has been right-clicked.
+``EVT_TREE_BEGIN_DRAG`` Begin dragging with the left mouse button.
+``EVT_TREE_BEGIN_LABEL_EDIT`` Begin editing a label. This can be prevented by calling :meth:`TreeEvent.Veto() <lib.agw.customtreectrl.TreeEvent.Veto>`.
+``EVT_TREE_BEGIN_RDRAG`` Begin dragging with the right mouse button.
+``EVT_TREE_DELETE_ITEM`` Delete an item.
+``EVT_TREE_END_DRAG`` End dragging with the left or right mouse button.
+``EVT_TREE_END_LABEL_EDIT`` End editing a label. This can be prevented by calling :meth:`TreeEvent.Veto() <lib.agw.customtreectrl.TreeEvent.Veto>`.
+``EVT_TREE_GET_INFO`` Request information from the application (not implemented in :class:`HyperTreeList`).
+``EVT_TREE_ITEM_ACTIVATED`` The item has been activated, i.e. chosen by double clicking it with mouse or from keyboard.
+``EVT_TREE_ITEM_CHECKED`` A checkbox or radiobox type item has been checked.
+``EVT_TREE_ITEM_CHECKING`` A checkbox or radiobox type item is being checked.
+``EVT_TREE_ITEM_COLLAPSED`` The item has been collapsed.
+``EVT_TREE_ITEM_COLLAPSING`` The item is being collapsed. This can be prevented by calling :meth:`TreeEvent.Veto() <lib.agw.customtreectrl.TreeEvent.Veto>`.
+``EVT_TREE_ITEM_EXPANDED`` The item has been expanded.s
+``EVT_TREE_ITEM_EXPANDING`` The item is being expanded. This can be prevented by calling :meth:`TreeEvent.Veto() <lib.agw.customtreectrl.TreeEvent.Veto>`.
+``EVT_TREE_ITEM_GETTOOLTIP`` The opportunity to set the item tooltip is being given to the application (call :meth:`TreeEvent.SetToolTip() <lib.agw.customtreectrl.CommandTreeEvent.SetToolTip>`).
+``EVT_TREE_ITEM_HYPERLINK`` An hyperlink type item has been clicked.
+``EVT_TREE_ITEM_MENU`` The context menu for the selected item has been requested, either by a right click or by using the menu key.
+``EVT_TREE_ITEM_MIDDLE_CLICK`` The user has clicked the item with the middle mouse button (not implemented in :class:`HyperTreeList`).
+``EVT_TREE_ITEM_RIGHT_CLICK`` The user has clicked the item with the right mouse button.
+``EVT_TREE_KEY_DOWN`` A key has been pressed.
+``EVT_TREE_SEL_CHANGED`` Selection has changed.
+``EVT_TREE_SEL_CHANGING`` Selection is changing. This can be prevented by calling :meth:`TreeEvent.Veto() <lib.agw.customtreectrl.TreeEvent.Veto>`.
+``EVT_TREE_SET_INFO`` Information is being supplied to the application (not implemented in :class:`HyperTreeList`).
+``EVT_TREE_STATE_IMAGE_CLICK`` The state image has been clicked (not implemented in :class:`HyperTreeList`).
+============================== ==================================================
+
+
+License And Version
+===================
+
+:class:`HyperTreeList` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 30 Jul 2014, 21.00 GMT
+
+Version 1.3
+
+"""
+
+import wx
+import wx.gizmos
+
+from customtreectrl import CustomTreeCtrl
+from customtreectrl import DragImage, TreeEvent, GenericTreeItem, ChopText
+from customtreectrl import TreeEditTimer as TreeListEditTimer
+from customtreectrl import EVT_TREE_ITEM_CHECKING, EVT_TREE_ITEM_CHECKED, EVT_TREE_ITEM_HYPERLINK
+
+# Version Info
+__version__ = "1.3"
+
+# --------------------------------------------------------------------------
+# Constants
+# --------------------------------------------------------------------------
+
+_NO_IMAGE = -1
+
+_DEFAULT_COL_WIDTH = 100
+_LINEHEIGHT = 10
+_LINEATROOT = 5
+_MARGIN = 2
+_MININDENT = 16
+_BTNWIDTH = 9
+_BTNHEIGHT = 9
+_EXTRA_WIDTH = 4
+_EXTRA_HEIGHT = 4
+
+_MAX_WIDTH = 30000 # pixels; used by OnPaint to redraw only exposed items
+
+_DRAG_TIMER_TICKS = 250 # minimum drag wait time in ms
+_FIND_TIMER_TICKS = 500 # minimum find wait time in ms
+_EDIT_TIMER_TICKS = 250 # minimum edit wait time in ms
+
+
+# --------------------------------------------------------------------------
+# Additional HitTest style
+# --------------------------------------------------------------------------
+TREE_HITTEST_ONITEMCHECKICON = 0x4000
+""" On the check icon, if present. """
+
+# HyperTreeList styles
+TR_NO_BUTTONS = wx.TR_NO_BUTTONS # for convenience
+""" For convenience to document that no buttons are to be drawn. """
+TR_HAS_BUTTONS = wx.TR_HAS_BUTTONS # draw collapsed/expanded btns
+""" Use this style to show + and - buttons to the left of parent items. """
+TR_NO_LINES = wx.TR_NO_LINES # don't draw lines at all
+""" Use this style to hide vertical level connectors. """
+TR_LINES_AT_ROOT = wx.TR_LINES_AT_ROOT # connect top-level nodes
+""" Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set. """
+TR_TWIST_BUTTONS = wx.TR_TWIST_BUTTONS # still used by wxTreeListCtrl
+""" Use old Mac-twist style buttons. """
+TR_SINGLE = wx.TR_SINGLE # for convenience
+""" For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default. """
+TR_MULTIPLE = wx.TR_MULTIPLE # can select multiple items
+""" Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected. """
+TR_EXTENDED = wx.TR_EXTENDED # TODO: allow extended selection
+""" Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases). """
+TR_HAS_VARIABLE_ROW_HEIGHT = wx.TR_HAS_VARIABLE_ROW_HEIGHT # what it says
+""" Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset. """
+TR_EDIT_LABELS = wx.TR_EDIT_LABELS # can edit item labels
+""" Use this style if you wish the user to be able to edit labels in the tree control. """
+TR_ROW_LINES = wx.TR_ROW_LINES # put border around items
+""" Use this style to draw a contrasting border between displayed rows. """
+TR_COLUMN_LINES = 0x1000 # put border between columns
+""" Use this style to draw a contrasting border between displayed columns. """
+TR_HIDE_ROOT = wx.TR_HIDE_ROOT # don't display root node
+""" Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes. """
+TR_FULL_ROW_HIGHLIGHT = wx.TR_FULL_ROW_HIGHLIGHT # highlight full horz space
+""" Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window. """
+
+TR_AUTO_CHECK_CHILD = 0x04000 # only meaningful for checkboxes
+""" Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well. """
+TR_AUTO_TOGGLE_CHILD = 0x08000 # only meaningful for checkboxes
+""" Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly. """
+TR_AUTO_CHECK_PARENT = 0x10000 # only meaningful for checkboxes
+""" Only meaningful foe checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well. """
+TR_ALIGN_WINDOWS = 0x20000 # to align windows horizontally for items at the same level
+""" Flag used to align windows (in items with windows) at the same horizontal position. """
+TR_ELLIPSIZE_LONG_ITEMS = 0x80000 # to ellipsize long items when horizontal space is low
+""" Flag used to ellipsize long items when the horizontal space for :class:`HyperTreeList` columns is low."""
+TR_VIRTUAL = 0x100000
+""" :class:`HyperTreeList` will have virtual behaviour. """
+
+# --------------------------------------------------------------------------
+# Additional HyperTreeList style to hide the header
+# --------------------------------------------------------------------------
+TR_NO_HEADER = 0x40000
+""" Use this style to hide the columns header. """
+# --------------------------------------------------------------------------
+
+
+# --------------------------------------------------------------------------
+# Additional HyperTreeList style autosize the columns based on the widest
+# width between column header and cells content
+# --------------------------------------------------------------------------
+LIST_AUTOSIZE_CONTENT_OR_HEADER = -3
+# --------------------------------------------------------------------------
+
+
+def IsBufferingSupported():
+ """
+ Utility function which checks if a platform handles correctly double
+ buffering for the header. Currently returns ``False`` for all platforms
+ except Windows XP.
+ """
+
+ if wx.Platform != "__WXMSW__":
+ return False
+
+ if wx.App.GetComCtl32Version() >= 600:
+ if wx.GetOsVersion()[1] > 5:
+ # Windows Vista
+ return False
+
+ return True
+
+ return False
+
+
+class TreeListColumnInfo(object):
+ """
+ Class used to store information (width, alignment flags, colours, etc...) about a
+ :class:`HyperTreeList` column header.
+ """
+
+ def __init__(self, input="", width=_DEFAULT_COL_WIDTH, flag=wx.ALIGN_LEFT,
+ image=-1, shown=True, colour=None, edit=False):
+ """
+ Default class constructor.
+
+ :param `input`: can be a string (representing the column header text) or
+ another instance of :class:`TreeListColumnInfo`. In the latter case, all the
+ other input parameters are not used;
+ :param `width`: the column width in pixels;
+ :param `flag`: the column alignment flag, one of ``wx.ALIGN_LEFT``,
+ ``wx.ALIGN_RIGHT``, ``wx.ALIGN_CENTER``;
+ :param `image`: an index within the normal image list assigned to
+ :class:`HyperTreeList` specifying the image to use for the column;
+ :param `shown`: ``True`` to show the column, ``False`` to hide it;
+ :param `colour`: a valid :class:`Colour`, representing the text foreground colour
+ for the column;
+ :param `edit`: ``True`` to set the column as editable, ``False`` otherwise.
+ """
+
+ if isinstance(input, basestring):
+ self._text = input
+ self._width = width
+ self._flag = flag
+ self._image = image
+ self._selected_image = -1
+ self._shown = shown
+ self._edit = edit
+ self._font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ if colour is None:
+ self._colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ else:
+ self._colour = colour
+
+ else:
+
+ self._text = input._text
+ self._width = input._width
+ self._flag = input._flag
+ self._image = input._image
+ self._selected_image = input._selected_image
+ self._shown = input._shown
+ self._edit = input._edit
+ self._colour = input._colour
+ self._font = input._font
+
+
+ # get/set
+ def GetText(self):
+ """ Returns the column header label. """
+
+ return self._text
+
+
+ def SetText(self, text):
+ """
+ Sets the column header label.
+
+ :param `text`: the new column header text.
+ """
+
+ self._text = text
+ return self
+
+
+ def GetWidth(self):
+ """ Returns the column header width in pixels. """
+
+ return self._width
+
+
+ def SetWidth(self, width):
+ """
+ Sets the column header width.
+
+ :param `width`: the column header width, in pixels.
+ """
+
+ self._width = width
+ return self
+
+
+ def GetAlignment(self):
+ """ Returns the column text alignment. """
+
+ return self._flag
+
+
+ def SetAlignment(self, flag):
+ """
+ Sets the column text alignment.
+
+ :param `flag`: the alignment flag, one of ``wx.ALIGN_LEFT``, ``wx.ALIGN_RIGHT``,
+ ``wx.ALIGN_CENTER``.
+ """
+
+ self._flag = flag
+ return self
+
+
+ def GetColour(self):
+ """ Returns the column text colour. """
+
+ return self._colour
+
+
+ def SetColour(self, colour):
+ """
+ Sets the column text colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._colour = colour
+ return self
+
+
+ def GetImage(self):
+ """ Returns the column image index. """
+
+ return self._image
+
+
+ def SetImage(self, image):
+ """
+ Sets the column image index.
+
+ :param `image`: an index within the normal image list assigned to
+ :class:`HyperTreeList` specifying the image to use for the column.
+ """
+
+ self._image = image
+ return self
+
+
+ def GetSelectedImage(self):
+ """ Returns the column image index in the selected state. """
+
+ return self._selected_image
+
+
+ def SetSelectedImage(self, image):
+ """
+ Sets the column image index in the selected state.
+
+ :param `image`: an index within the normal image list assigned to
+ :class:`HyperTreeList` specifying the image to use for the column when in
+ selected state.
+ """
+
+ self._selected_image = image
+ return self
+
+
+ def IsEditable(self):
+ """ Returns ``True`` if the column is editable, ``False`` otherwise. """
+
+ return self._edit
+
+
+ def SetEditable(self, edit):
+ """
+ Sets the column as editable or non-editable.
+
+ :param `edit`: ``True`` if the column should be editable, ``False`` otherwise.
+ """
+
+ self._edit = edit
+ return self
+
+
+ def IsShown(self):
+ """ Returns ``True`` if the column is shown, ``False`` if it is hidden. """
+
+ return self._shown
+
+
+ def SetShown(self, shown):
+ """
+ Sets the column as shown or hidden.
+
+ :param `shown`: ``True`` if the column should be shown, ``False`` if it
+ should be hidden.
+ """
+
+ self._shown = shown
+ return self
+
+
+ def SetFont(self, font):
+ """
+ Sets the column text font.
+
+ :param `font`: a valid :class:`Font` object.
+ """
+
+ self._font = font
+ return self
+
+
+ def GetFont(self):
+ """ Returns the column text font. """
+
+ return self._font
+
+
+#-----------------------------------------------------------------------------
+# TreeListHeaderWindow (internal)
+#-----------------------------------------------------------------------------
+
+class TreeListHeaderWindow(wx.Window):
+ """ A window which holds the header of :class:`HyperTreeList`. """
+
+ def __init__(self, parent, id=wx.ID_ANY, owner=None, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name="wxtreelistctrlcolumntitles"):
+ """
+ Default class constructor.
+
+ :param `parent`: the window parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `owner`: the window owner, in this case an instance of :class:`TreeListMainWindow`;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `name`: the window name.
+ """
+
+ wx.Window.__init__(self, parent, id, pos, size, style, name=name)
+
+ self._owner = owner
+ self._currentCursor = wx.StockCursor(wx.CURSOR_DEFAULT)
+ self._resizeCursor = wx.StockCursor(wx.CURSOR_SIZEWE)
+ self._isDragging = False
+ self._dirty = False
+ self._total_col_width = 0
+ self._hotTrackCol = -1
+ self._columns = []
+ self._headerCustomRenderer = None
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+
+ def SetBuffered(self, buffered):
+ """
+ Sets/unsets the double buffering for the header.
+
+ :param `buffered`: ``True`` to use double-buffering, ``False`` otherwise.
+
+ :note: Currently we are using double-buffering only on Windows XP.
+ """
+
+ self._buffered = buffered
+
+
+ # total width of all columns
+ def GetWidth(self):
+ """ Returns the total width of all columns. """
+
+ return self._total_col_width
+
+
+ # column manipulation
+ def GetColumnCount(self):
+ """ Returns the total number of columns. """
+
+ return len(self._columns)
+
+
+ # column information manipulation
+ def GetColumn(self, column):
+ """
+ Returns a column item, an instance of :class:`TreeListItem`.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._columns[column]
+
+
+ def GetColumnText(self, column):
+ """
+ Returns the column text label.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._columns[column].GetText()
+
+
+ def SetColumnText(self, column, text):
+ """
+ Sets the column text label.
+
+ :param `column`: an integer specifying the column index;
+ :param `text`: the new column label.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._columns[column].SetText(text)
+
+
+ def GetColumnAlignment(self, column):
+ """
+ Returns the column text alignment.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._columns[column].GetAlignment()
+
+
+ def SetColumnAlignment(self, column, flag):
+ """
+ Sets the column text alignment.
+
+ :param `column`: an integer specifying the column index;
+ :param `flag`: the new text alignment flag.
+
+ :see: :meth:`TreeListColumnInfo.SetAlignment() <TreeListColumnInfo.SetAlignment>` for a list of valid alignment
+ flags.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._columns[column].SetAlignment(flag)
+
+
+ def GetColumnWidth(self, column):
+ """
+ Returns the column width, in pixels.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._columns[column].GetWidth()
+
+
+ def GetColumnColour(self, column):
+ """
+ Returns the column text colour.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._columns[column].GetColour()
+
+
+ def SetColumnColour(self, column, colour):
+ """
+ Sets the column text colour.
+
+ :param `column`: an integer specifying the column index;
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._columns[column].SetColour(colour)
+
+
+ def IsColumnEditable(self, column):
+ """
+ Returns ``True`` if the column is editable, ``False`` otherwise.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._columns[column].IsEditable()
+
+
+ def IsColumnShown(self, column):
+ """
+ Returns ``True`` if the column is shown, ``False`` if it is hidden.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._columns[column].IsShown()
+
+
+ # shift the DC origin to match the position of the main window horz
+ # scrollbar: this allows us to always use logical coords
+ def AdjustDC(self, dc):
+ """
+ Shifts the :class:`DC` origin to match the position of the main window horizontal
+ scrollbar: this allows us to always use logical coordinates.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ xpix, dummy = self._owner.GetScrollPixelsPerUnit()
+ x, dummy = self._owner.GetViewStart()
+
+ # account for the horz scrollbar offset
+ dc.SetDeviceOrigin(-x * xpix, 0)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`TreeListHeaderWindow`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ if self._buffered:
+ dc = wx.BufferedPaintDC(self)
+ else:
+ dc = wx.PaintDC(self)
+
+ self.AdjustDC(dc)
+
+ x = 0
+
+ # width and height of the entire header window
+ w, h = self.GetClientSize()
+ w, dummy = self._owner.CalcUnscrolledPosition(w, 0)
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+
+ numColumns = self.GetColumnCount()
+
+ for i in xrange(numColumns):
+
+ if x >= w:
+ break
+
+ if not self.IsColumnShown(i):
+ continue # do next column if not shown
+
+ params = wx.HeaderButtonParams()
+
+ column = self.GetColumn(i)
+ params.m_labelColour = column.GetColour()
+ params.m_labelFont = column.GetFont()
+
+ wCol = column.GetWidth()
+ flags = 0
+ rect = wx.Rect(x, 0, wCol, h)
+ x += wCol
+
+ if i == self._hotTrackCol:
+ flags |= wx.CONTROL_CURRENT
+
+ params.m_labelText = column.GetText()
+ params.m_labelAlignment = column.GetAlignment()
+
+ image = column.GetImage()
+ imageList = self._owner.GetImageList()
+
+ if image != -1 and imageList:
+ params.m_labelBitmap = imageList.GetBitmap(image)
+
+ if self._headerCustomRenderer != None:
+ self._headerCustomRenderer.DrawHeaderButton(dc, rect, flags, params)
+ else:
+ wx.RendererNative.Get().DrawHeaderButton(self, dc, rect, flags,
+ wx.HDR_SORT_ICON_NONE, params)
+
+ # Fill up any unused space to the right of the columns
+ if x < w:
+ rect = wx.Rect(x, 0, w-x, h)
+ if self._headerCustomRenderer != None:
+ self._headerCustomRenderer.DrawHeaderButton(dc, rect)
+ else:
+ wx.RendererNative.Get().DrawHeaderButton(self, dc, rect)
+
+
+ def DrawCurrent(self):
+ """ Draws the column resize line on a :class:`ScreenDC`. """
+
+ x1, y1 = self._currentX, 0
+ x1, y1 = self.ClientToScreen((x1, y1))
+ x2 = self._currentX-1
+ if wx.Platform == "__WXMSW__":
+ x2 += 1 # but why ????
+
+ y2 = 0
+ dummy, y2 = self._owner.GetClientSize()
+ x2, y2 = self._owner.ClientToScreen((x2, y2))
+
+ dc = wx.ScreenDC()
+ dc.SetLogicalFunction(wx.INVERT)
+ dc.SetPen(wx.Pen(wx.BLACK, 2, wx.SOLID))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ self.AdjustDC(dc)
+ dc.DrawLine (x1, y1, x2, y2)
+ dc.SetLogicalFunction(wx.COPY)
+
+
+ def SetCustomRenderer(self, renderer=None):
+ """
+ Associate a custom renderer with the header - all columns will use it
+
+ :param `renderer`: a class able to correctly render header buttons
+
+ :note: the renderer class **must** implement the method `DrawHeaderButton`
+ """
+
+ self._headerCustomRenderer = renderer
+
+
+ def XToCol(self, x):
+ """
+ Returns the column that corresponds to the logical input `x` coordinate.
+
+ :param `x`: the `x` position to evaluate.
+
+ :return: The column that corresponds to the logical input `x` coordinate,
+ or ``wx.NOT_FOUND`` if there is no column at the `x` position.
+ """
+
+ colLeft = 0
+ numColumns = self.GetColumnCount()
+ for col in xrange(numColumns):
+
+ if not self.IsColumnShown(col):
+ continue
+
+ column = self.GetColumn(col)
+
+ if x < (colLeft + column.GetWidth()):
+ return col
+
+ colLeft += column.GetWidth()
+
+ return wx.NOT_FOUND
+
+
+ def RefreshColLabel(self, col):
+ """
+ Redraws the column.
+
+ :param `col`: the index of the column to redraw.
+ """
+
+ if col >= self.GetColumnCount():
+ return
+
+ x = idx = width = 0
+ while idx <= col:
+
+ if not self.IsColumnShown(idx):
+ idx += 1
+ continue
+
+ column = self.GetColumn(idx)
+ x += width
+ width = column.GetWidth()
+ idx += 1
+
+ x, dummy = self._owner.CalcScrolledPosition(x, 0)
+ self.RefreshRect(wx.Rect(x, 0, width, self.GetSize().GetHeight()))
+
+
+ def OnMouse(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` event for :class:`TreeListHeaderWindow`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # we want to work with logical coords
+ x, dummy = self._owner.CalcUnscrolledPosition(event.GetX(), 0)
+ y = event.GetY()
+
+ if event.Moving():
+
+ col = self.XToCol(x)
+ if col != self._hotTrackCol:
+
+ # Refresh the col header so it will be painted with hot tracking
+ # (if supported by the native renderer.)
+ self.RefreshColLabel(col)
+
+ # Also refresh the old hot header
+ if self._hotTrackCol >= 0:
+ self.RefreshColLabel(self._hotTrackCol)
+
+ self._hotTrackCol = col
+
+ if event.Leaving() and self._hotTrackCol >= 0:
+
+ # Leaving the window so clear any hot tracking indicator that may be present
+ self.RefreshColLabel(self._hotTrackCol)
+ self._hotTrackCol = -1
+
+ if self._isDragging:
+
+ self.SendListEvent(wx.wxEVT_COMMAND_LIST_COL_DRAGGING, event.GetPosition())
+
+ # we don't draw the line beyond our window, but we allow dragging it
+ # there
+ w, dummy = self.GetClientSize()
+ w, dummy = self._owner.CalcUnscrolledPosition(w, 0)
+ w -= 6
+
+ # erase the line if it was drawn
+ if self._currentX < w:
+ self.DrawCurrent()
+
+ if event.ButtonUp():
+ self._isDragging = False
+ if self.HasCapture():
+ self.ReleaseMouse()
+ self._dirty = True
+ self.SetColumnWidth(self._column, self._currentX - self._minX)
+ self.Refresh()
+ self.SendListEvent(wx.wxEVT_COMMAND_LIST_COL_END_DRAG, event.GetPosition())
+ else:
+ self._currentX = max(self._minX + 7, x)
+
+ # draw in the new location
+ if self._currentX < w:
+ self.DrawCurrent()
+
+ else: # not dragging
+
+ self._minX = 0
+ hit_border = False
+
+ # end of the current column
+ xpos = 0
+
+ # find the column where this event occured
+ countCol = self.GetColumnCount()
+
+ for column in xrange(countCol):
+
+ if not self.IsColumnShown(column):
+ continue # do next if not shown
+
+ xpos += self.GetColumnWidth(column)
+ self._column = column
+ if abs (x-xpos) < 3 and y < 22:
+ # near the column border
+ hit_border = True
+ break
+
+ if x < xpos:
+ # inside the column
+ break
+
+ self._minX = xpos
+
+ if event.LeftDown() or event.RightUp():
+ if hit_border and event.LeftDown():
+ self._isDragging = True
+ self.CaptureMouse()
+ self._currentX = x
+ self.DrawCurrent()
+ self.SendListEvent(wx.wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, event.GetPosition())
+ else: # click on a column
+ evt = (event.LeftDown() and [wx.wxEVT_COMMAND_LIST_COL_CLICK] or [wx.wxEVT_COMMAND_LIST_COL_RIGHT_CLICK])[0]
+ self.SendListEvent(evt, event.GetPosition())
+
+ elif event.LeftDClick() and hit_border:
+ self.SetColumnWidth(self._column, self._owner.GetBestColumnWidth(self._column))
+ self.Refresh()
+
+ elif event.Moving():
+
+ if hit_border:
+ setCursor = self._currentCursor == wx.STANDARD_CURSOR
+ self._currentCursor = self._resizeCursor
+ else:
+ setCursor = self._currentCursor != wx.STANDARD_CURSOR
+ self._currentCursor = wx.STANDARD_CURSOR
+
+ if setCursor:
+ self.SetCursor(self._currentCursor)
+
+
+ def OnSetFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`TreeListHeaderWindow`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self._owner.SetFocus()
+
+
+ def SendListEvent(self, evtType, pos):
+ """
+ Sends a :class:`ListEvent` for the parent window.
+
+ :param `evtType`: the event type;
+ :param `pos`: an instance of :class:`Point`.
+ """
+
+ parent = self.GetParent()
+ le = wx.ListEvent(evtType, parent.GetId())
+ le.SetEventObject(parent)
+ le.m_pointDrag = pos
+
+ # the position should be relative to the parent window, not
+ # this one for compatibility with MSW and common sense: the
+ # user code doesn't know anything at all about this header
+ # window, so why should it get positions relative to it?
+ le.m_pointDrag.y -= self.GetSize().y
+ le.m_col = self._column
+ parent.GetEventHandler().ProcessEvent(le)
+
+
+ def AddColumnInfo(self, colInfo):
+ """
+ Appends a column to the :class:`TreeListHeaderWindow`.
+
+ :param `colInfo`: an instance of :class:`TreeListColumnInfo`.
+ """
+
+ self._columns.append(colInfo)
+ self._total_col_width += colInfo.GetWidth()
+ self._owner.AdjustMyScrollbars()
+ self._owner._dirty = True
+
+
+ def AddColumn(self, text, width=_DEFAULT_COL_WIDTH, flag=wx.ALIGN_LEFT,
+ image=-1, shown=True, colour=None, edit=False):
+ """
+ Appends a column to the :class:`TreeListHeaderWindow`.
+
+ :param `text`: the column text label;
+ :param `width`: the column width in pixels;
+ :param `flag`: the column alignment flag, one of ``wx.ALIGN_LEFT``,
+ ``wx.ALIGN_RIGHT``, ``wx.ALIGN_CENTER``;
+ :param `image`: an index within the normal image list assigned to
+ :class:`HyperTreeList` specifying the image to use for the column;
+ :param `shown`: ``True`` to show the column, ``False`` to hide it;
+ :param `colour`: a valid :class:`Colour`, representing the text foreground colour
+ for the column;
+ :param `edit`: ``True`` to set the column as editable, ``False`` otherwise.
+ """
+
+ colInfo = TreeListColumnInfo(text, width, flag, image, shown, colour, edit)
+ self.AddColumnInfo(colInfo)
+
+
+ def SetColumnWidth(self, column, width):
+ """
+ Sets the column width, in pixels.
+
+ :param `column`: an integer specifying the column index;
+ :param `width`: the new width for the column, in pixels.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ self._total_col_width -= self._columns[column].GetWidth()
+ self._columns[column].SetWidth(width)
+ self._total_col_width += width
+ self._owner.AdjustMyScrollbars()
+ self._owner._dirty = True
+
+
+ def InsertColumnInfo(self, before, colInfo):
+ """
+ Inserts a column to the :class:`TreeListHeaderWindow` at the position specified
+ by `before`.
+
+ :param `before`: the index at which we wish to insert the new column;
+ :param `colInfo`: an instance of :class:`TreeListColumnInfo`.
+ """
+
+ if before < 0 or before >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ self._columns.insert(before, colInfo)
+ self._total_col_width += colInfo.GetWidth()
+ self._owner.AdjustMyScrollbars()
+ self._owner._dirty = True
+
+
+ def InsertColumn(self, before, text, width=_DEFAULT_COL_WIDTH,
+ flag=wx.ALIGN_LEFT, image=-1, shown=True, colour=None,
+ edit=False):
+ """
+ Inserts a column to the :class:`TreeListHeaderWindow` at the position specified
+ by `before`.
+
+ :param `before`: the index at which we wish to insert the new column;
+ :param `text`: the column text label;
+ :param `width`: the column width in pixels;
+ :param `flag`: the column alignment flag, one of ``wx.ALIGN_LEFT``,
+ ``wx.ALIGN_RIGHT``, ``wx.ALIGN_CENTER``;
+ :param `image`: an index within the normal image list assigned to
+ :class:`HyperTreeList` specifying the image to use for the column;
+ :param `shown`: ``True`` to show the column, ``False`` to hide it;
+ :param `colour`: a valid :class:`Colour`, representing the text foreground colour
+ for the column;
+ :param `edit`: ``True`` to set the column as editable, ``False`` otherwise.
+ """
+
+ colInfo = TreeListColumnInfo(text, width, flag, image, shown, colour,
+ edit)
+ self.InsertColumnInfo(before, colInfo)
+
+
+ def RemoveColumn(self, column):
+ """
+ Removes a column from the :class:`TreeListHeaderWindow`.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ self._total_col_width -= self._columns[column].GetWidth()
+ self._columns.pop(column)
+ self._owner.AdjustMyScrollbars()
+ self._owner._dirty = True
+
+
+ def SetColumn(self, column, info):
+ """
+ Sets a column using an instance of :class:`TreeListColumnInfo`.
+
+ :param `column`: an integer specifying the column index;
+ :param `info`: an instance of :class:`TreeListColumnInfo`.
+ """
+
+ if column < 0 or column >= self.GetColumnCount():
+ raise Exception("Invalid column")
+
+ w = self._columns[column].GetWidth()
+ self._columns[column] = info
+
+ if w != info.GetWidth():
+ self._total_col_width += info.GetWidth() - w
+ self._owner.AdjustMyScrollbars()
+
+ self._owner._dirty = True
+
+
+# ---------------------------------------------------------------------------
+# TreeListItem
+# ---------------------------------------------------------------------------
+class TreeListItem(GenericTreeItem):
+ """
+ This class holds all the information and methods for every single item in
+ :class:`HyperTreeList`.
+
+ :note: Subclassed from :class:`GenericTreeItem`.
+ """
+
+ def __init__(self, mainWin, parent, text=[], ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `mainWin`: the main :class:`HyperTreeList` window, in this case an instance
+ of :class:`TreeListMainWindow`;
+ :param `parent`: the tree item parent (may be ``None`` for root items);
+ :param `text`: the tree item text;
+ :param `ct_type`: the tree item kind. May be one of the following integers:
+
+ =============== ==========================
+ `ct_type` Value Description
+ =============== ==========================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== ==========================
+
+ :param `wnd`: if not ``None``, a non-toplevel window to be displayed next to
+ the item;
+ :param `image`: an index within the normal image list specifying the image to
+ use for the item in unselected state;
+ :param `selImage`: an index within the normal image list specifying the image to
+ use for the item in selected state; if `image` > -1 and `selImage` is -1, the
+ same image is used for both selected and unselected items;
+ :param `data`: associate the given Python object `data` with the item.
+
+ :note: Regarding radiobutton-type items (with `ct_type` = 2), the following
+ approach is used:
+
+ - All peer-nodes that are radiobuttons will be mutually exclusive. In other words,
+ only one of a set of radiobuttons that share a common parent can be checked at
+ once. If a radiobutton node becomes checked, then all of its peer radiobuttons
+ must be unchecked.
+ - If a radiobutton node becomes unchecked, then all of its child nodes will become
+ inactive.
+ """
+
+ self._col_images = []
+ self._owner = mainWin
+
+ # We don't know the height here yet.
+ self._text_x = 0
+
+ GenericTreeItem.__init__(self, parent, text, ct_type, wnd, image, selImage, data)
+
+ self._wnd = [None] # are we holding a window?
+ self._hidden = False
+
+ if wnd:
+ self.SetWindow(wnd)
+
+
+ def IsHidden(self):
+ """ Returns whether the item is hidden or not. """
+
+ return self._hidden
+
+
+ def Hide(self, hide):
+ """
+ Hides/shows the :class:`TreeListItem`.
+
+ :param `hide`: ``True`` to hide the item, ``False`` to show it.
+ """
+
+ self._hidden = hide
+
+
+ def DeleteChildren(self, tree):
+ """
+ Deletes the item children.
+
+ :param `tree`: the main :class:`TreeListMainWindow` instance.
+ """
+
+ for child in self._children:
+ child.DeleteChildren(tree)
+ if tree:
+ tree.Delete(child)
+
+ if child == tree._selectItem:
+ tree._selectItem = None
+
+ # We have to destroy the associated window
+ for wnd in child._wnd:
+ if wnd:
+ wnd.Hide()
+ wnd.Destroy()
+
+ child._wnd = []
+
+ if child in tree._itemWithWindow:
+ tree._itemWithWindow.remove(child)
+
+ del child
+
+ self._children = []
+
+
+ def HitTest(self, point, theCtrl, flags, column, level):
+ """
+ HitTest method for an item. Called from the main window HitTest.
+
+ :param `point`: the point to test for the hit (an instance of :class:`Point`);
+ :param `theCtrl`: the main :class:`TreeListMainWindow` tree;
+ :param `flags`: a bitlist of hit locations;
+ :param `column`: an integer specifying the column index;
+ :param `level`: the item's level inside the tree hierarchy.
+
+ :see: :meth:`TreeListMainWindow.HitTest() <TreeListMainWindow.HitTest>` method for the flags explanation.
+ """
+
+ # for a hidden root node, don't evaluate it, but do evaluate children
+ if not theCtrl.HasAGWFlag(wx.TR_HIDE_ROOT) or level > 0:
+
+ # reset any previous hit infos
+ flags = 0
+ column = -1
+ header_win = theCtrl._owner.GetHeaderWindow()
+
+ # check for right of all columns (outside)
+ if point.x > header_win.GetWidth():
+ return None, flags, wx.NOT_FOUND
+
+ # evaluate if y-pos is okay
+ h = theCtrl.GetLineHeight(self)
+
+ if point.y >= self._y and point.y <= self._y + h:
+
+ maincol = theCtrl.GetMainColumn()
+
+ # check for above/below middle
+ y_mid = self._y + h/2
+ if point.y < y_mid:
+ flags |= wx.TREE_HITTEST_ONITEMUPPERPART
+ else:
+ flags |= wx.TREE_HITTEST_ONITEMLOWERPART
+
+ # check for button hit
+ if self.HasPlus() and theCtrl.HasButtons():
+ bntX = self._x - theCtrl._btnWidth2
+ bntY = y_mid - theCtrl._btnHeight2
+ if ((point.x >= bntX) and (point.x <= (bntX + theCtrl._btnWidth)) and
+ (point.y >= bntY) and (point.y <= (bntY + theCtrl._btnHeight))):
+ flags |= wx.TREE_HITTEST_ONITEMBUTTON
+ column = maincol
+ return self, flags, column
+
+ # check for hit on the check icons
+ if self.GetType() != 0:
+ imageWidth = 0
+ numberOfMargins = 1
+ if self.GetCurrentImage() != _NO_IMAGE:
+ imageWidth = theCtrl._imgWidth
+ numberOfMargins += 1
+ chkX = self._text_x - imageWidth - numberOfMargins*_MARGIN - theCtrl._checkWidth
+ chkY = y_mid - theCtrl._checkHeight2
+ if ((point.x >= chkX) and (point.x <= (chkX + theCtrl._checkWidth)) and
+ (point.y >= chkY) and (point.y <= (chkY + theCtrl._checkHeight))):
+ flags |= TREE_HITTEST_ONITEMCHECKICON
+ return self, flags, maincol
+
+ # check for image hit
+ if self.GetCurrentImage() != _NO_IMAGE:
+ imgX = self._text_x - theCtrl._imgWidth - _MARGIN
+ imgY = y_mid - theCtrl._imgHeight2
+ if ((point.x >= imgX) and (point.x <= (imgX + theCtrl._imgWidth)) and
+ (point.y >= imgY) and (point.y <= (imgY + theCtrl._imgHeight))):
+ flags |= wx.TREE_HITTEST_ONITEMICON
+ column = maincol
+ return self, flags, column
+
+ # check for label hit
+ if ((point.x >= self._text_x) and (point.x <= (self._text_x + self._width))):
+ flags |= wx.TREE_HITTEST_ONITEMLABEL
+ column = maincol
+ return self, flags, column
+
+ # check for indent hit after button and image hit
+ if point.x < self._x:
+ flags |= wx.TREE_HITTEST_ONITEMINDENT
+ column = -1 # considered not belonging to main column
+ return self, flags, column
+
+ # check for right of label
+ end = 0
+ for i in xrange(maincol):
+ end += header_win.GetColumnWidth(i)
+ if ((point.x > (self._text_x + self._width)) and (point.x <= end)):
+ flags |= wx.TREE_HITTEST_ONITEMRIGHT
+ column = -1 # considered not belonging to main column
+ return self, flags, column
+
+ # else check for each column except main
+ x = 0
+ for j in xrange(theCtrl.GetColumnCount()):
+ if not header_win.IsColumnShown(j):
+ continue
+ w = header_win.GetColumnWidth(j)
+ if ((j != maincol) and (point.x >= x and point.x < x+w)):
+ flags |= wx.TREE_HITTEST_ONITEMCOLUMN
+ column = j
+ return self, flags, column
+
+ x += w
+
+ # no special flag or column found
+ return self, flags, column
+
+ # if children not expanded, return no item
+ if not self.IsExpanded():
+ return None, flags, wx.NOT_FOUND
+
+ # in any case evaluate children
+ for child in self._children:
+ hit, flags, column = child.HitTest(point, theCtrl, flags, column, level+1)
+ if hit:
+ return hit, flags, column
+
+ # not found
+ return None, flags, wx.NOT_FOUND
+
+
+ def GetText(self, column=None):
+ """
+ Returns the item text label.
+
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if len(self._text) > 0:
+ if self._owner.IsVirtual():
+ return self._owner.GetItemText(self._data, column)
+ else:
+ return self._text[column]
+
+ return ""
+
+
+ def GetImage(self, which=wx.TreeItemIcon_Normal, column=None):
+ """
+ Returns the item image for a particular item state.
+
+ :param `which`: can be one of the following bits:
+
+ ================================= ========================
+ Item State Description
+ ================================= ========================
+ ``TreeItemIcon_Normal`` To get the normal item image
+ ``TreeItemIcon_Selected`` To get the selected item image (i.e. the image which is shown when the item is currently selected)
+ ``TreeItemIcon_Expanded`` To get the expanded image (this only makes sense for items which have children - then this image is shown when the item is expanded and the normal image is shown when it is collapsed)
+ ``TreeItemIcon_SelectedExpanded`` To get the selected expanded image (which is shown when an expanded item is currently selected)
+ ================================= ========================
+
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if column == self._owner.GetMainColumn():
+ return self._images[which]
+
+ if column < len(self._col_images):
+ return self._col_images[column]
+
+ return _NO_IMAGE
+
+
+ def GetCurrentImage(self, column=None):
+ """
+ Returns the current item image.
+
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if column != self._owner.GetMainColumn():
+ return self.GetImage(column=column)
+
+ image = GenericTreeItem.GetCurrentImage(self)
+ return image
+
+
+ def SetText(self, column, text):
+ """
+ Sets the item text label.
+
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used;
+ :param `text`: a string specifying the new item label.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if column < len(self._text):
+ self._text[column] = text
+ elif column < self._owner.GetColumnCount():
+ self._text.extend([""] * (column - len(self._text) + 1))
+ self._text[column] = text
+
+
+ def SetImage(self, column, image, which):
+ """
+ Sets the item image for a particular item state.
+
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used;
+ :param `image`: an index within the normal image list specifying the image to use;
+ :param `which`: the item state.
+
+ :see: :meth:`~TreeListItem.GetImage` for a list of valid item states.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if column == self._owner.GetMainColumn():
+ self._images[which] = image
+ elif column < len(self._col_images):
+ self._col_images[column] = image
+ elif column < self._owner.GetColumnCount():
+ self._col_images.extend([_NO_IMAGE] * (column - len(self._col_images) + 1))
+ self._col_images[column] = image
+
+
+ def GetTextX(self):
+ """ Returns the `x` position of the item text. """
+
+ return self._text_x
+
+
+ def SetTextX(self, text_x):
+ """
+ Sets the `x` position of the item text.
+
+ :param `text_x`: the `x` position of the item text.
+ """
+
+ self._text_x = text_x
+
+
+ def SetWindow(self, wnd, column=None):
+ """
+ Sets the window associated to the item.
+
+ :param `wnd`: a non-toplevel window to be displayed next to the item;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if type(self._wnd) != type([]):
+ self._wnd = [self._wnd]
+
+ if column < len(self._wnd):
+ self._wnd[column] = wnd
+ elif column < self._owner.GetColumnCount():
+ self._wnd.extend([None] * (column - len(self._wnd) + 1))
+ self._wnd[column] = wnd
+
+ if self not in self._owner._itemWithWindow:
+ self._owner._itemWithWindow.append(self)
+
+ # We have to bind the wx.EVT_SET_FOCUS for the associated window
+ # No other solution to handle the focus changing from an item in
+ # HyperTreeList and the window associated to an item
+ # Do better strategies exist?
+ wnd.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+
+ # We don't show the window if the item is collapsed
+ if self._isCollapsed:
+ wnd.Show(False)
+
+ # The window is enabled only if the item is enabled
+ wnd.Enable(self._enabled)
+
+
+ def OnSetFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for a window associated to an item.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ treectrl = self._owner
+ select = treectrl.GetSelection()
+
+ # If the window is associated to an item that currently is selected
+ # (has focus) we don't kill the focus. Otherwise we do it.
+ if select != self:
+ treectrl._hasFocus = False
+ else:
+ treectrl._hasFocus = True
+
+ event.Skip()
+
+
+ def GetWindow(self, column=None):
+ """
+ Returns the window associated to the item.
+
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if column >= len(self._wnd):
+ return None
+
+ return self._wnd[column]
+
+
+ def DeleteWindow(self, column=None):
+ """
+ Deletes the window associated to the item (if any).
+
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if column >= len(self._wnd):
+ return
+
+ if self._wnd[column]:
+ self._wnd[column].Destroy()
+ self._wnd[column] = None
+
+
+ def GetWindowEnabled(self, column=None):
+ """
+ Returns whether the window associated with an item is enabled or not.
+
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if not self._wnd[column]:
+ raise Exception("\nERROR: This Item Has No Window Associated At Column %s"%column)
+
+ return self._wnd[column].IsEnabled()
+
+
+ def SetWindowEnabled(self, enable=True, column=None):
+ """
+ Sets whether the window associated with an item is enabled or not.
+
+ :param `enable`: ``True`` to enable the associated window, ``False`` to disable it;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if not self._wnd[column]:
+ raise Exception("\nERROR: This Item Has No Window Associated At Column %s"%column)
+
+ self._wnd[column].Enable(enable)
+
+
+ def GetWindowSize(self, column=None):
+ """
+ Returns the associated window size.
+
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ if not self._wnd[column]:
+ raise Exception("\nERROR: This Item Has No Window Associated At Column %s"%column)
+
+ return self._wnd[column].GetSize()
+
+
+#-----------------------------------------------------------------------------
+# EditTextCtrl (internal)
+#-----------------------------------------------------------------------------
+
+
+class EditCtrl(object):
+ """
+ Base class for controls used for in-place edit.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, item=None, column=None, owner=None,
+ value="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0,
+ validator=wx.DefaultValidator, name="editctrl", **kwargs):
+ """
+ Default class constructor.
+
+ :param `parent`: the window parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used;
+ :param `owner`: the window owner, in this case an instance of :class:`TreeListMainWindow`;
+ :param `value`: the initial value in the control;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `validator`: the window validator;
+ :param `name`: the window name.
+ """
+ self._owner = owner
+ self._startValue = value
+ self._itemEdited = item
+ self._finished = False
+
+ column = (column is not None and [column] or [self._owner.GetMainColumn()])[0]
+
+ self._column = column
+
+ w = self._itemEdited.GetWidth()
+ h = self._itemEdited.GetHeight()
+
+ wnd = self._itemEdited.GetWindow(column)
+ if wnd:
+ w = w - self._itemEdited.GetWindowSize(column)[0]
+ h = 0
+
+ x = item.GetX()
+
+ if column > 0:
+ x = 0
+
+ for i in xrange(column):
+ if not self._owner.GetParent()._header_win.IsColumnShown(i):
+ continue # do next column if not shown
+
+ col = self._owner.GetParent()._header_win.GetColumn(i)
+ wCol = col.GetWidth()
+ x += wCol
+
+ x, y = self._owner.CalcScrolledPosition(x+2, item.GetY())
+
+ image_w = image_h = wcheck = hcheck = 0
+ image = item.GetCurrentImage(column)
+
+ if image != _NO_IMAGE:
+
+ if self._owner._imageListNormal:
+ image_w, image_h = self._owner._imageListNormal.GetSize(image)
+ image_w += 2*_MARGIN
+
+ else:
+
+ raise Exception("\n ERROR: You Must Create An Image List To Use Images!")
+
+ if column > 0:
+ checkimage = item.GetCurrentCheckedImage()
+ if checkimage is not None:
+ wcheck, hcheck = self._owner._imageListCheck.GetSize(checkimage)
+ wcheck += 2*_MARGIN
+
+ if wnd:
+ h = max(hcheck, image_h)
+ dc = wx.ClientDC(self._owner)
+ h = max(h, dc.GetTextExtent("Aq")[1])
+ h = h + 2
+
+ # FIXME: what are all these hardcoded 4, 8 and 11s really?
+ x += image_w + wcheck
+ w -= image_w + 2*_MARGIN + wcheck
+
+ super(EditCtrl, self).__init__(parent, id, value, wx.Point(x,y),
+ wx.Size(w+15, h),
+ style=style|wx.SIMPLE_BORDER,
+ name=name, **kwargs)
+
+ if wx.Platform == "__WXMAC__":
+ self.SetFont(owner.GetFont())
+ bs = self.GetBestSize()
+ self.SetSize((-1, bs.height))
+
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+
+ def item(self):
+ """Returns the item currently edited."""
+
+ return self._itemEdited
+
+
+ def column(self):
+ """Returns the column currently edited."""
+
+ return self._column
+
+
+ def StopEditing(self):
+ """Suddenly stops the editing."""
+
+ self._owner.OnCancelEdit()
+ self.Finish()
+
+
+ def Finish(self):
+ """Finish editing."""
+
+ if not self._finished:
+
+ self._finished = True
+ self._owner.SetFocusIgnoringChildren()
+ self._owner.ResetEditControl()
+
+
+ def AcceptChanges(self):
+ """Accepts/refuses the changes made by the user."""
+
+ value = self.GetValue()
+
+ if value == self._startValue:
+ # nothing changed, always accept
+ # when an item remains unchanged, the owner
+ # needs to be notified that the user decided
+ # not to change the tree item label, and that
+ # the edit has been cancelled
+ self._owner.OnCancelEdit()
+ return True
+ else:
+ return self._owner.OnAcceptEdit(value)
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`EditCtrl`
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ # We must let the native control handle focus, too, otherwise
+ # it could have problems with the cursor (e.g., in wxGTK).
+ event.Skip()
+
+
+
+class EditTextCtrl(EditCtrl, wx.TextCtrl):
+ """
+ Text control used for in-place edit.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, item=None, column=None, owner=None,
+ value="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0,
+ validator=wx.DefaultValidator, name="edittextctrl", **kwargs):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `parent`: the window parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used;
+ :param `owner`: the window owner, in this case an instance of :class:`TreeListMainWindow`;
+ :param `value`: the initial value in the text control;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `validator`: the window validator;
+ :param `name`: the window name.
+ """
+
+ super(EditTextCtrl, self).__init__(parent, id, item, column, owner,
+ value, pos, size, style, validator,
+ name, **kwargs)
+ self.SelectAll()
+
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+
+
+ def OnChar(self, event):
+ """
+ Handles the ``wx.EVT_CHAR`` event for :class:`EditTextCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ keycode = event.GetKeyCode()
+
+ if keycode in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER] and not event.ShiftDown():
+ # Notify the owner about the changes
+ self.AcceptChanges()
+ # Even if vetoed, close the control (consistent with MSW)
+ wx.CallAfter(self.Finish)
+
+ elif keycode == wx.WXK_ESCAPE:
+ self.StopEditing()
+
+ else:
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` event for :class:`EditTextCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if not self._finished:
+
+ # auto-grow the textctrl:
+ parentSize = self._owner.GetSize()
+ myPos = self.GetPosition()
+ mySize = self.GetSize()
+
+ sx, sy = self.GetTextExtent(self.GetValue() + "M")
+ if myPos.x + sx > parentSize.x:
+ sx = parentSize.x - myPos.x
+ if mySize.x > sx:
+ sx = mySize.x
+
+ self.SetSize((sx, -1))
+
+ event.Skip()
+
+
+
+# ---------------------------------------------------------------------------
+# TreeListMainWindow implementation
+# ---------------------------------------------------------------------------
+
+class TreeListMainWindow(CustomTreeCtrl):
+ """
+ This class represents the main window (and thus the main column) in :class:`HyperTreeList`.
+
+ :note: This is a subclass of :class:`~lib.agw.customtreectrl.CustomTreeCtrl`.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=wx.TR_DEFAULT_STYLE, validator=wx.DefaultValidator,
+ name="wxtreelistmainwindow"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`PyScrolledWindow` style;
+ :param `agwStyle`: the AGW-specific :class:`TreeListMainWindow` window style. This can be a
+ combination of the following bits:
+
+ ============================== =========== ==================================================
+ Window Styles Hex Value Description
+ ============================== =========== ==================================================
+ ``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn.
+ ``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default.
+ ``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items.
+ ``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors.
+ ``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set.
+ ``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit.
+ ``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons.
+ ``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected.
+ ``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases).
+ ``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset.
+ ``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control.
+ ``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows.
+ ``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes.
+ ``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window.
+ ``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well.
+ ``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly.
+ ``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful foe checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well.
+ ``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position.
+ ``TR_NO_HEADER`` 0x40000 Use this style to hide the columns header.
+ ``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`~lib.agw.customtreectrl.CustomTreeCtrl` is low.
+ ``TR_VIRTUAL`` 0x100000 :class:`HyperTreeList` will have virtual behaviour.
+ ============================== =========== ==================================================
+
+ :param `validator`: window validator;
+ :param `name`: window name.
+ """
+
+ self._buffered = False
+
+ CustomTreeCtrl.__init__(self, parent, id, pos, size, style, agwStyle, validator, name)
+
+ self._shiftItem = None
+ self._editItem = None
+ self._selectItem = None
+
+ self._curColumn = -1 # no current column
+ self._owner = parent
+ self._main_column = 0
+ self._dragItem = None
+
+ self._imgWidth = self._imgWidth2 = 0
+ self._imgHeight = self._imgHeight2 = 0
+ self._btnWidth = self._btnWidth2 = 0
+ self._btnHeight = self._btnHeight2 = 0
+ self._checkWidth = self._checkWidth2 = 0
+ self._checkHeight = self._checkHeight2 = 0
+ self._agwStyle = agwStyle
+ self._current = None
+
+ # TextCtrl initial settings for editable items
+ self._editTimer = TreeListEditTimer(self)
+ self._left_down_selection = False
+
+ self._dragTimer = wx.Timer(self)
+ self._findTimer = wx.Timer(self)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+ self.Bind(wx.EVT_SCROLLWIN, self.OnScroll)
+
+ # Sets the focus to ourselves: this is useful if you have items
+ # with associated widgets.
+ self.SetFocus()
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+
+ def SetBuffered(self, buffered):
+ """
+ Sets/unsets the double buffering for the main window.
+
+ :param `buffered`: ``True`` to use double-buffering, ``False`` otherwise.
+
+ :note: Currently we are using double-buffering only on Windows XP.
+ """
+
+ self._buffered = buffered
+ if buffered:
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+ else:
+ self.SetBackgroundStyle(wx.BG_STYLE_SYSTEM)
+
+
+ def IsVirtual(self):
+ """ Returns ``True`` if :class:`TreeListMainWindow` has the ``TR_VIRTUAL`` flag set. """
+
+ return self.HasAGWFlag(TR_VIRTUAL)
+
+
+#-----------------------------------------------------------------------------
+# functions to work with tree items
+#-----------------------------------------------------------------------------
+
+ def GetItemImage(self, item, column=None, which=wx.TreeItemIcon_Normal):
+ """
+ Returns the item image.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used;
+ :param `which`: can be one of the following bits:
+
+ ================================= ========================
+ Item State Description
+ ================================= ========================
+ ``TreeItemIcon_Normal`` To get the normal item image
+ ``TreeItemIcon_Selected`` To get the selected item image (i.e. the image which is shown when the item is currently selected)
+ ``TreeItemIcon_Expanded`` To get the expanded image (this only makes sense for items which have children - then this image is shown when the item is expanded and the normal image is shown when it is collapsed)
+ ``TreeItemIcon_SelectedExpanded`` To get the selected expanded image (which is shown when an expanded item is currently selected)
+ ================================= ========================
+ """
+
+ column = (column is not None and [column] or [self._main_column])[0]
+
+ if column < 0:
+ return _NO_IMAGE
+
+ return item.GetImage(which, column)
+
+
+ def SetItemImage(self, item, image, column=None, which=wx.TreeItemIcon_Normal):
+ """
+ Sets the item image for a particular item state.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `image`: an index within the normal image list specifying the image to use;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used;
+ :param `which`: the item state.
+
+ :see: :meth:`~TreeListMainWindow.GetItemImage` for a list of valid item states.
+ """
+
+ column = (column is not None and [column] or [self._main_column])[0]
+
+ if column < 0:
+ return
+
+ item.SetImage(column, image, which)
+ dc = wx.ClientDC(self)
+ self.CalculateSize(item, dc)
+ self.RefreshLine(item)
+
+
+ def GetItemWindowEnabled(self, item, column=None):
+ """
+ Returns whether the window associated with an item is enabled or not.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ return item.GetWindowEnabled(column)
+
+
+ def GetItemWindow(self, item, column=None):
+ """
+ Returns the window associated with an item.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ return item.GetWindow(column)
+
+
+ def SetItemWindow(self, item, window, column=None):
+ """
+ Sets the window associated to an item.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `wnd`: a non-toplevel window to be displayed next to the item;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+
+ :note: The window parent should not be the :class:`HyperTreeList` itself, but actually
+ an instance of :class:`TreeListMainWindow`. The current solution here is to reparent
+ the window to this class.
+ """
+
+ # Reparent the window to ourselves
+ if window.GetParent() != self:
+ window.Reparent(self)
+
+ item.SetWindow(window, column)
+ if window:
+ self._hasWindows = True
+
+
+ def SetItemWindowEnabled(self, item, enable=True, column=None):
+ """
+ Sets whether the window associated with an item is enabled or not.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `enable`: ``True`` to enable the associated window, ``False`` to disable it;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ item.SetWindowEnabled(enable, column)
+
+
+# ----------------------------------------------------------------------------
+# navigation
+# ----------------------------------------------------------------------------
+
+ def IsItemVisible(self, item):
+ """
+ Returns whether the item is visible or not.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ """
+
+ # An item is only visible if it's not a descendant of a collapsed item
+ parent = item.GetParent()
+
+ while parent:
+
+ if not parent.IsExpanded():
+ return False
+
+ parent = parent.GetParent()
+
+ startX, startY = self.GetViewStart()
+ clientSize = self.GetClientSize()
+
+ rect = self.GetBoundingRect(item)
+
+ if not rect:
+ return False
+ if rect.GetWidth() == 0 or rect.GetHeight() == 0:
+ return False
+ if rect.GetBottom() < 0 or rect.GetTop() > clientSize.y:
+ return False
+ if rect.GetRight() < 0 or rect.GetLeft() > clientSize.x:
+ return False
+
+ return True
+
+
+ def GetPrevChild(self, item, cookie):
+ """
+ Returns the previous child of an item.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `cookie`: a parameter which is opaque for the application but is necessary
+ for the library to make these functions reentrant (i.e. allow more than one
+ enumeration on one and the same object simultaneously).
+
+ :note: This method returns ``None`` if there are no further siblings.
+ """
+
+ children = item.GetChildren()
+
+ if cookie >= 0:
+ return children[cookie], cookie-1
+ else:
+ # there are no more of them
+ return None, cookie
+
+
+ def GetFirstExpandedItem(self):
+ """ Returns the first item which is in the expanded state. """
+
+ return self.GetNextExpanded(self.GetRootItem())
+
+
+ def GetNextExpanded(self, item):
+ """
+ Returns the next expanded item after the input one.
+
+ :param `item`: an instance of :class:`TreeListItem`.
+ """
+
+ return CustomTreeCtrl.GetNextExpanded(self, item)
+
+
+ def GetPrevExpanded(self, item):
+ """
+ Returns the previous expanded item before the input one.
+
+ :param `item`: an instance of :class:`TreeListItem`.
+ """
+
+ return CustomTreeCtrl.GetPrevExpanded(self, item)
+
+
+ def GetFirstVisibleItem(self):
+ """ Returns the first visible item. """
+
+ return self.GetNextVisible(self.GetRootItem())
+
+
+ def GetPrevVisible(self, item):
+ """
+ Returns the previous visible item before the input one.
+
+ :param `item`: an instance of :class:`TreeListItem`.
+ """
+
+ i = self.GetPrev(item)
+ while i:
+ if self.IsItemVisible(i):
+ return i
+ i = self.GetPrev(i)
+
+ return None
+
+
+# ----------------------------------------------------------------------------
+# operations
+# ----------------------------------------------------------------------------
+
+ def DoInsertItem(self, parent, previous, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None, separator=False):
+ """
+ Actually inserts an item in the tree.
+
+ :param `parentId`: an instance of :class:`TreeListItem` representing the
+ item's parent;
+ :param `previous`: the index at which we should insert the item;
+ :param `text`: the item text label;
+ :param `ct_type`: the item type (see :meth:`CustomTreeCtrl.SetItemType() <lib.agw.customtreectrl.CustomTreeCtrl.SetItemType>` for a list of valid
+ item types);
+ :param `wnd`: if not ``None``, a non-toplevel window to show next to the item;
+ :param `image`: an index within the normal image list specifying the image to
+ use for the item in unselected state;
+ :param `selImage`: an index within the normal image list specifying the image to
+ use for the item in selected state; if `image` > -1 and `selImage` is -1, the
+ same image is used for both selected and unselected items;
+ :param `data`: associate the given Python object `data` with the item.
+ :param `separator`: unused at the moment, this parameter is present to comply with
+ :meth:`CustomTreeCtrl.DoInsertItem() <lib.agw.customtreectrl.CustomTreeCtrl.DoInsertItem>` changed API.
+ """
+
+ self._dirty = True # do this first so stuff below doesn't cause flicker
+ arr = [""]*self.GetColumnCount()
+ arr[self._main_column] = text
+
+ if not parent:
+ # should we give a warning here?
+ return self.AddRoot(text, ct_type, wnd, image, selImage, data)
+
+ self._dirty = True # do this first so stuff below doesn't cause flicker
+
+ item = TreeListItem(self, parent, arr, ct_type, wnd, image, selImage, data)
+
+ if wnd is not None:
+ self._hasWindows = True
+ self._itemWithWindow.append(item)
+
+ parent.Insert(item, previous)
+
+ return item
+
+
+ def AddRoot(self, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
+ """
+ Adds a root item to the :class:`TreeListMainWindow`.
+
+ :param `text`: the item text label;
+ :param `ct_type`: the item type (see :meth:`CustomTreeCtrl.SetItemType() <lib.agw.customtreectrl.CustomTreeCtrl.SetItemType>`
+ for a list of valid item types);
+ :param `wnd`: if not ``None``, a non-toplevel window to show next to the item;
+ :param `image`: an index within the normal image list specifying the image to
+ use for the item in unselected state;
+ :param `selImage`: an index within the normal image list specifying the image to
+ use for the item in selected state; if `image` > -1 and `selImage` is -1, the
+ same image is used for both selected and unselected items;
+ :param `data`: associate the given Python object `data` with the item.
+
+ .. warning::
+
+ Only one root is allowed to exist in any given instance of :class:`TreeListMainWindow`.
+
+ """
+
+ if self._anchor:
+ raise Exception("\nERROR: Tree Can Have Only One Root")
+
+ if wnd is not None and not (self._agwStyle & wx.TR_HAS_VARIABLE_ROW_HEIGHT):
+ raise Exception("\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
+
+ if text.find("\n") >= 0 and not (self._agwStyle & wx.TR_HAS_VARIABLE_ROW_HEIGHT):
+ raise Exception("\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
+
+ if ct_type < 0 or ct_type > 2:
+ raise Exception("\nERROR: Item Type Should Be 0 (Normal), 1 (CheckBox) or 2 (RadioButton). ")
+
+ self._dirty = True # do this first so stuff below doesn't cause flicker
+ arr = [""]*self.GetColumnCount()
+ arr[self._main_column] = text
+ self._anchor = TreeListItem(self, None, arr, ct_type, wnd, image, selImage, data)
+
+ if wnd is not None:
+ self._hasWindows = True
+ self._itemWithWindow.append(self._anchor)
+
+ if self.HasAGWFlag(wx.TR_HIDE_ROOT):
+ # if root is hidden, make sure we can navigate
+ # into children
+ self._anchor.SetHasPlus()
+ self._anchor.Expand()
+ self.CalculatePositions()
+
+ if not self.HasAGWFlag(wx.TR_MULTIPLE):
+ self._current = self._key_current = self._selectItem = self._anchor
+ self._current.SetHilight(True)
+
+ return self._anchor
+
+
+ def Delete(self, item):
+ """
+ Deletes an item.
+
+ :param `item`: an instance of :class:`TreeListItem`.
+ """
+
+ if not item:
+ raise Exception("\nERROR: Invalid Tree Item. ")
+
+ self._dirty = True # do this first so stuff below doesn't cause flicker
+
+ if self._editCtrl != None and self.IsDescendantOf(item, self._editCtrl.item()):
+ # can't delete the item being edited, cancel editing it first
+ self._editCtrl.StopEditing()
+
+ # don't stay with invalid self._shiftItem or we will crash in the next call to OnChar()
+ changeKeyCurrent = False
+ itemKey = self._shiftItem
+
+ while itemKey:
+ if itemKey == item: # self._shiftItem is a descendant of the item being deleted
+ changeKeyCurrent = True
+ break
+
+ itemKey = itemKey.GetParent()
+
+ parent = item.GetParent()
+ if parent:
+ parent.GetChildren().remove(item) # remove by value
+
+ if changeKeyCurrent:
+ self._shiftItem = parent
+
+ self.SendDeleteEvent(item)
+ if self._selectItem == item:
+ self._selectItem = None
+
+ # Remove the item with window
+ if item in self._itemWithWindow:
+ for wnd in item._wnd:
+ if wnd:
+ wnd.Hide()
+ wnd.Destroy()
+
+ item._wnd = []
+ self._itemWithWindow.remove(item)
+
+ item.DeleteChildren(self)
+ del item
+
+
+ # Don't leave edit or selection on a child which is about to disappear
+ def ChildrenClosing(self, item):
+ """
+ We are about to destroy the item's children.
+
+ :param `item`: an instance of :class:`TreeListItem`.
+ """
+
+ if self._editCtrl != None and item != self._editCtrl.item() and self.IsDescendantOf(item, self._editCtrl.item()):
+ self._editCtrl.StopEditing()
+
+ if self.IsDescendantOf(item, self._selectItem):
+ self._selectItem = item
+
+ if item != self._current and self.IsDescendantOf(item, self._current):
+ self._current.SetHilight(False)
+ self._current = None
+
+
+ def DeleteRoot(self):
+ """
+ Removes the tree root item (and subsequently all the items in
+ :class:`TreeListMainWindow`.
+ """
+
+ if self._anchor:
+
+ self._dirty = True
+
+ self._anchor.DeleteChildren(self)
+ self.Delete(self._anchor)
+
+ self.SendDeleteEvent(self._anchor)
+ self._current = None
+ self._selectItem = None
+ del self._anchor
+ self._anchor = None
+
+
+ def DeleteAllItems(self):
+ """ Delete all items in the :class:`TreeListMainWindow`. """
+
+ self.DeleteRoot()
+
+
+ def HideWindows(self):
+ """ Hides the windows associated to the items. Used internally. """
+
+ for child in self._itemWithWindow:
+ if not self.IsItemVisible(child):
+ for column in xrange(self.GetColumnCount()):
+ wnd = child.GetWindow(column)
+ if wnd and wnd.IsShown():
+ wnd.Hide()
+
+
+ def EnableItem(self, item, enable=True, torefresh=True):
+ """
+ Enables/disables an item.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `enable`: ``True`` to enable the item, ``False`` otherwise;
+ :param `torefresh`: whether to redraw the item or not.
+ """
+
+ if item.IsEnabled() == enable:
+ return
+
+ if not enable and item.IsSelected():
+ self.DoSelectItem(item, not self.HasAGWFlag(wx.TR_MULTIPLE))
+
+ item.Enable(enable)
+
+ for column in xrange(self.GetColumnCount()):
+ wnd = item.GetWindow(column)
+
+ # Handles the eventual window associated to the item
+ if wnd:
+ wnd.Enable(enable)
+
+ if torefresh:
+ # We have to refresh the item line
+ dc = wx.ClientDC(self)
+ self.CalculateSize(item, dc)
+ self.RefreshLine(item)
+
+
+ def IsItemEnabled(self, item):
+ """
+ Returns whether an item is enabled or disabled.
+
+ :param `item`: an instance of :class:`TreeListItem`.
+ """
+
+ return item.IsEnabled()
+
+
+ def GetCurrentItem(self):
+ """ Returns the current item. """
+
+ return self._current
+
+
+ def GetColumnCount(self):
+ """ Returns the total number of columns. """
+
+ return self._owner.GetHeaderWindow().GetColumnCount()
+
+
+ def SetMainColumn(self, column):
+ """
+ Sets the :class:`HyperTreeList` main column (i.e. the position of the underlying
+ :class:`~lib.agw.customtreectrl.CustomTreeCtrl`.
+
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ if column >= 0 and column < self.GetColumnCount():
+ self._main_column = column
+
+
+ def GetMainColumn(self):
+ """
+ Returns the :class:`HyperTreeList` main column (i.e. the position of the underlying
+ :class:`~lib.agw.customtreectrl.CustomTreeCtrl`.
+ """
+
+ return self._main_column
+
+
+ def ScrollTo(self, item):
+ """
+ Scrolls the specified item into view.
+
+ :param `item`: an instance of :class:`TreeListItem`.
+ """
+
+ # ensure that the position of the item it calculated in any case
+ if self._dirty:
+ self.CalculatePositions()
+
+ # now scroll to the item
+ xUnit, yUnit = self.GetScrollPixelsPerUnit()
+ start_x, start_y = self.GetViewStart()
+ start_y *= yUnit
+ client_w, client_h = self.GetClientSize ()
+
+ x, y = self._anchor.GetSize (0, 0, self)
+ x = self._owner.GetHeaderWindow().GetWidth()
+ y += yUnit + 2 # one more scrollbar unit + 2 pixels
+ x_pos = self.GetScrollPos(wx.HORIZONTAL)
+
+ if item._y < start_y+3:
+ # going down, item should appear at top
+ self.SetScrollbars(xUnit, yUnit, (xUnit and [x/xUnit] or [0])[0], (yUnit and [y/yUnit] or [0])[0],
+ x_pos, (yUnit and [item._y/yUnit] or [0])[0])
+
+ elif item._y+self.GetLineHeight(item) > start_y+client_h:
+ # going up, item should appear at bottom
+ item._y += yUnit + 2
+ self.SetScrollbars(xUnit, yUnit, (xUnit and [x/xUnit] or [0])[0], (yUnit and [y/yUnit] or [0])[0],
+ x_pos, (yUnit and [(item._y+self.GetLineHeight(item)-client_h)/yUnit] or [0])[0])
+
+
+ def SetDragItem(self, item):
+ """
+ Sets the specified item as member of a current drag and drop operation.
+
+ :param `item`: an instance of :class:`TreeListItem`.
+ """
+
+ prevItem = self._dragItem
+ self._dragItem = item
+ if prevItem:
+ self.RefreshLine(prevItem)
+ if self._dragItem:
+ self.RefreshLine(self._dragItem)
+
+
+# ----------------------------------------------------------------------------
+# helpers
+# ----------------------------------------------------------------------------
+
+ def AdjustMyScrollbars(self):
+ """ Internal method used to adjust the :class:`PyScrolledWindow` scrollbars. """
+
+ if self._anchor:
+ xUnit, yUnit = self.GetScrollPixelsPerUnit()
+ if xUnit == 0:
+ xUnit = self.GetCharWidth()
+ if yUnit == 0:
+ yUnit = self._lineHeight
+
+ x, y = self._anchor.GetSize(0, 0, self)
+ y += yUnit + 2 # one more scrollbar unit + 2 pixels
+ x_pos = self.GetScrollPos(wx.HORIZONTAL)
+ y_pos = self.GetScrollPos(wx.VERTICAL)
+ x = self._owner.GetHeaderWindow().GetWidth() + 2
+ if x < self.GetClientSize().GetWidth():
+ x_pos = 0
+
+ self.SetScrollbars(xUnit, yUnit, x/xUnit, y/yUnit, x_pos, y_pos)
+ else:
+ self.SetScrollbars(0, 0, 0, 0)
+
+
+ def PaintItem(self, item, dc):
+ """
+ Actually draws an item.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ def _paintText(text, textrect, alignment):
+ """
+ Sub-function to draw multi-lines text label aligned correctly.
+
+ :param `text`: the item text label (possibly multiline);
+ :param `textrect`: the label client rectangle;
+ :param `alignment`: the alignment for the text label, one of ``wx.ALIGN_LEFT``,
+ ``wx.ALIGN_RIGHT``, ``wx.ALIGN_CENTER``.
+ """
+
+ txt = text.splitlines()
+ if alignment != wx.ALIGN_LEFT and len(txt):
+ yorigin = textrect.Y
+ for t in txt:
+ w, h = dc.GetTextExtent(t)
+ plus = textrect.Width - w
+ if alignment == wx.ALIGN_CENTER:
+ plus /= 2
+ dc.DrawLabel(t, wx.Rect(textrect.X + plus, yorigin, w, yorigin+h))
+ yorigin += h
+ return
+ dc.DrawLabel(text, textrect)
+
+ attr = item.GetAttributes()
+
+ if attr and attr.HasFont():
+ dc.SetFont(attr.GetFont())
+ elif item.IsBold():
+ dc.SetFont(self._boldFont)
+ if item.IsHyperText():
+ dc.SetFont(self.GetHyperTextFont())
+ if item.GetVisited():
+ dc.SetTextForeground(self.GetHyperTextVisitedColour())
+ else:
+ dc.SetTextForeground(self.GetHyperTextNewColour())
+
+ colText = wx.Colour(*dc.GetTextForeground())
+
+ if item.IsSelected():
+ if (wx.Platform == "__WXMAC__" and self._hasFocus):
+ colTextHilight = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
+ else:
+ colTextHilight = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
+
+ else:
+ attr = item.GetAttributes()
+ if attr and attr.HasTextColour():
+ colText = attr.GetTextColour()
+
+ if self._vistaselection:
+ colText = colTextHilight = wx.BLACK
+
+ total_w = self._owner.GetHeaderWindow().GetWidth()
+ total_h = self.GetLineHeight(item)
+ off_h = (self.HasAGWFlag(wx.TR_ROW_LINES) and [1] or [0])[0]
+ off_w = (self.HasAGWFlag(wx.TR_COLUMN_LINES) and [1] or [0])[0]
+## clipper = wx.DCClipper(dc, 0, item.GetY(), total_w, total_h) # only within line
+
+ text_w, text_h, dummy = dc.GetMultiLineTextExtent(item.GetText(self.GetMainColumn()))
+
+ drawItemBackground = False
+ # determine background and show it
+ if attr and attr.HasBackgroundColour():
+ colBg = attr.GetBackgroundColour()
+ drawItemBackground = True
+ else:
+ colBg = self._backgroundColour
+
+ dc.SetBrush(wx.Brush(colBg, wx.SOLID))
+
+ if attr and attr.HasBorderColour():
+ colBorder = attr.GetBorderColour()
+ dc.SetPen(wx.Pen(colBorder, 1, wx.SOLID))
+ else:
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ if self.HasAGWFlag(wx.TR_FULL_ROW_HIGHLIGHT):
+
+ itemrect = wx.Rect(0, item.GetY() + off_h, total_w-1, total_h - off_h)
+
+ if item == self._dragItem:
+ dc.SetBrush(self._hilightBrush)
+ if wx.Platform == "__WXMAC__":
+ dc.SetPen((item == self._dragItem) and [wx.BLACK_PEN] or [wx.TRANSPARENT_PEN])[0]
+
+ dc.SetTextForeground(colTextHilight)
+
+ elif item.IsSelected():
+
+ wnd = item.GetWindow(self._main_column)
+ wndx = 0
+ if wnd:
+ wndx, wndy = item.GetWindowSize(self._main_column)
+
+ itemrect = wx.Rect(0, item.GetY() + off_h, total_w-1, total_h - off_h)
+
+ if self._usegradients:
+ if self._gradientstyle == 0: # Horizontal
+ self.DrawHorizontalGradient(dc, itemrect, self._hasFocus)
+ else: # Vertical
+ self.DrawVerticalGradient(dc, itemrect, self._hasFocus)
+ elif self._vistaselection:
+ self.DrawVistaRectangle(dc, itemrect, self._hasFocus)
+ else:
+ if wx.Platform in ["__WXGTK2__", "__WXMAC__"]:
+ flags = wx.CONTROL_SELECTED
+ if self._hasFocus: flags = flags | wx.CONTROL_FOCUSED
+ wx.RendererNative.Get().DrawItemSelectionRect(self._owner, dc, itemrect, flags)
+ else:
+ dc.SetBrush((self._hasFocus and [self._hilightBrush] or [self._hilightUnfocusedBrush])[0])
+ dc.SetPen((self._hasFocus and [self._borderPen] or [wx.TRANSPARENT_PEN])[0])
+ dc.DrawRectangleRect(itemrect)
+
+ dc.SetTextForeground(colTextHilight)
+
+ # On GTK+ 2, drawing a 'normal' background is wrong for themes that
+ # don't allow backgrounds to be customized. Not drawing the background,
+ # except for custom item backgrounds, works for both kinds of theme.
+ elif drawItemBackground:
+
+ itemrect = wx.Rect(0, item.GetY() + off_h, total_w-1, total_h - off_h)
+ dc.SetBrush(wx.Brush(colBg, wx.SOLID))
+ dc.DrawRectangleRect(itemrect)
+ dc.SetTextForeground(colText)
+
+ else:
+ dc.SetTextForeground(colText)
+
+ else:
+
+ dc.SetTextForeground(colText)
+
+ text_extraH = (total_h > text_h and [(total_h - text_h)/2] or [0])[0]
+ img_extraH = (total_h > self._imgHeight and [(total_h-self._imgHeight)/2] or [0])[0]
+ x_colstart = 0
+
+ for i in xrange(self.GetColumnCount()):
+ if not self._owner.GetHeaderWindow().IsColumnShown(i):
+ continue
+
+ col_w = self._owner.GetHeaderWindow().GetColumnWidth(i)
+ dc.SetClippingRegion(x_colstart, item.GetY(), col_w, total_h) # only within column
+
+ image = _NO_IMAGE
+ x = image_w = wcheck = hcheck = 0
+
+ if i == self.GetMainColumn():
+ x = item.GetX() + _MARGIN
+ if self.HasButtons():
+ x += (self._btnWidth-self._btnWidth2) + _LINEATROOT
+ else:
+ x -= self._indent/2
+
+ if self._imageListNormal:
+ image = item.GetCurrentImage(i)
+
+ if item.GetType() != 0 and self._imageListCheck:
+ checkimage = item.GetCurrentCheckedImage()
+ wcheck, hcheck = self._imageListCheck.GetSize(item.GetType())
+ else:
+ wcheck, hcheck = 0, 0
+
+ else:
+ x = x_colstart + _MARGIN
+ image = item.GetImage(column=i)
+
+ if image != _NO_IMAGE:
+ image_w = self._imgWidth + _MARGIN
+
+ # honor text alignment
+ text = item.GetText(i)
+ alignment = self._owner.GetHeaderWindow().GetColumn(i).GetAlignment()
+
+ text_w, dummy, dummy = dc.GetMultiLineTextExtent(text)
+
+ if alignment == wx.ALIGN_RIGHT:
+ w = col_w - (image_w + wcheck + text_w + off_w + _MARGIN + 1)
+ x += (w > 0 and [w] or [0])[0]
+
+ elif alignment == wx.ALIGN_CENTER:
+ w = (col_w - (image_w + wcheck + text_w + off_w + _MARGIN))/2
+ x += (w > 0 and [w] or [0])[0]
+ else:
+ if image_w == 0 and wcheck:
+ x += 2*_MARGIN
+
+ text_x = x + image_w + wcheck + 1
+
+ if i == self.GetMainColumn():
+ item.SetTextX(text_x)
+
+ if not self.HasAGWFlag(wx.TR_FULL_ROW_HIGHLIGHT):
+ dc.SetBrush((self._hasFocus and [self._hilightBrush] or [self._hilightUnfocusedBrush])[0])
+ dc.SetPen((self._hasFocus and [self._borderPen] or [wx.TRANSPARENT_PEN])[0])
+ if i == self.GetMainColumn():
+ if item == self._dragItem:
+ if wx.Platform == "__WXMAC__": # don't draw rect outline if we already have the background colour
+ dc.SetPen((item == self._dragItem and [wx.BLACK_PEN] or [wx.TRANSPARENT_PEN])[0])
+
+ dc.SetTextForeground(colTextHilight)
+
+ elif item.IsSelected():
+
+ itemrect = wx.Rect(text_x-2, item.GetY() + off_h, text_w+2*_MARGIN, total_h - off_h)
+
+ if self._usegradients:
+ if self._gradientstyle == 0: # Horizontal
+ self.DrawHorizontalGradient(dc, itemrect, self._hasFocus)
+ else: # Vertical
+ self.DrawVerticalGradient(dc, itemrect, self._hasFocus)
+ elif self._vistaselection:
+ self.DrawVistaRectangle(dc, itemrect, self._hasFocus)
+ else:
+ if wx.Platform in ["__WXGTK2__", "__WXMAC__"]:
+ flags = wx.CONTROL_SELECTED
+ if self._hasFocus: flags = flags | wx.CONTROL_FOCUSED
+ wx.RendererNative.Get().DrawItemSelectionRect(self._owner, dc, itemrect, flags)
+ else:
+ dc.DrawRectangleRect(itemrect)
+
+ dc.SetTextForeground(colTextHilight)
+
+ elif item == self._current:
+ dc.SetPen((self._hasFocus and [wx.BLACK_PEN] or [wx.TRANSPARENT_PEN])[0])
+
+ # On GTK+ 2, drawing a 'normal' background is wrong for themes that
+ # don't allow backgrounds to be customized. Not drawing the background,
+ # except for custom item backgrounds, works for both kinds of theme.
+ elif drawItemBackground:
+
+ itemrect = wx.Rect(text_x-2, item.GetY() + off_h, text_w+2*_MARGIN, total_h - off_h)
+ dc.SetBrush(wx.Brush(colBg, wx.SOLID))
+ dc.DrawRectangleRect(itemrect)
+
+ else:
+ dc.SetTextForeground(colText)
+
+ else:
+ dc.SetTextForeground(colText)
+
+ if self.HasAGWFlag(wx.TR_COLUMN_LINES): # vertical lines between columns
+ pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DLIGHT), 1, wx.SOLID)
+ dc.SetPen((self.GetBackgroundColour() == wx.WHITE and [pen] or [wx.WHITE_PEN])[0])
+ dc.DrawLine(x_colstart+col_w-1, item.GetY(), x_colstart+col_w-1, item.GetY()+total_h)
+
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+
+ if image != _NO_IMAGE:
+ y = item.GetY() + img_extraH
+ if wcheck:
+ x += wcheck
+
+ if item.IsEnabled():
+ imglist = self._imageListNormal
+ else:
+ imglist = self._grayedImageList
+
+ imglist.Draw(image, dc, x, y, wx.IMAGELIST_DRAW_TRANSPARENT)
+
+ if wcheck:
+ if item.IsEnabled():
+ imglist = self._imageListCheck
+ else:
+ imglist = self._grayedCheckList
+
+ if self.HasButtons(): # should the item show a button?
+ btnWidth = self._btnWidth
+ else:
+ btnWidth = -self._btnWidth
+
+ imglist.Draw(checkimage, dc,
+ item.GetX() + btnWidth + _MARGIN,
+ item.GetY() + ((total_h > hcheck) and [(total_h-hcheck)/2] or [0])[0]+1,
+ wx.IMAGELIST_DRAW_TRANSPARENT)
+
+ text_w, text_h, dummy = dc.GetMultiLineTextExtent(text)
+ text_extraH = (total_h > text_h and [(total_h - text_h)/2] or [0])[0]
+ text_y = item.GetY() + text_extraH
+ textrect = wx.Rect(text_x, text_y, text_w, text_h)
+
+ if self.HasAGWFlag(TR_ELLIPSIZE_LONG_ITEMS):
+ if i == self.GetMainColumn():
+ maxsize = col_w - text_x - _MARGIN
+ else:
+ maxsize = col_w - (wcheck + image_w + _MARGIN)
+
+ text = ChopText(dc, text, maxsize)
+
+ if not item.IsEnabled():
+ foreground = dc.GetTextForeground()
+ dc.SetTextForeground(self._disabledColour)
+ _paintText(text, textrect, alignment)
+ dc.SetTextForeground(foreground)
+ else:
+ if wx.Platform == "__WXMAC__" and item.IsSelected() and self._hasFocus:
+ dc.SetTextForeground(wx.WHITE)
+ _paintText(text, textrect, alignment)
+
+ wnd = item.GetWindow(i)
+ if wnd:
+ if text_w == 0:
+ wndx = text_x
+ else:
+ wndx = text_x + text_w + 2*_MARGIN
+ xa, ya = self.CalcScrolledPosition((0, item.GetY()))
+ wndx += xa
+ if item.GetHeight() > item.GetWindowSize(i)[1]:
+ ya += (item.GetHeight() - item.GetWindowSize(i)[1])/2
+
+ if not wnd.IsShown():
+ wnd.Show()
+ if wnd.GetPosition() != (wndx, ya):
+ wnd.SetPosition((wndx, ya))
+
+ x_colstart += col_w
+ dc.DestroyClippingRegion()
+
+ # restore normal font
+ dc.SetFont(self._normalFont)
+
+
+ # Now y stands for the top of the item, whereas it used to stand for middle !
+ def PaintLevel(self, item, dc, level, y, x_maincol):
+ """
+ Paint a level in the hierarchy of :class:`TreeListMainWindow`.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `level`: the item level in the tree hierarchy;
+ :param `y`: the current vertical position in the :class:`PyScrolledWindow`;
+ :param `x_maincol`: the horizontal position of the main column.
+ """
+
+ if item.IsHidden():
+ return y, x_maincol
+
+ # Handle hide root (only level 0)
+ if self.HasAGWFlag(wx.TR_HIDE_ROOT) and level == 0:
+ for child in item.GetChildren():
+ y, x_maincol = self.PaintLevel(child, dc, 1, y, x_maincol)
+
+ # end after expanding root
+ return y, x_maincol
+
+ # calculate position of vertical lines
+ x = x_maincol + _MARGIN # start of column
+
+ if self.HasAGWFlag(wx.TR_LINES_AT_ROOT):
+ x += _LINEATROOT # space for lines at root
+
+ if self.HasButtons():
+ x += (self._btnWidth-self._btnWidth2) # half button space
+ else:
+ x += (self._indent-self._indent/2)
+
+ if self.HasAGWFlag(wx.TR_HIDE_ROOT):
+ x += self._indent*(level-1) # indent but not level 1
+ else:
+ x += self._indent*level # indent according to level
+
+ # set position of vertical line
+ item.SetX(x)
+ item.SetY(y)
+
+ h = self.GetLineHeight(item)
+ y_top = y
+ y_mid = y_top + (h/2)
+ y += h
+
+ exposed_x = dc.LogicalToDeviceX(0)
+ exposed_y = dc.LogicalToDeviceY(y_top)
+
+ # horizontal lines between rows?
+ draw_row_lines = self.HasAGWFlag(wx.TR_ROW_LINES)
+
+ if self.IsExposed(exposed_x, exposed_y, _MAX_WIDTH, h + draw_row_lines):
+ if draw_row_lines:
+ total_width = self._owner.GetHeaderWindow().GetWidth()
+ # if the background colour is white, choose a
+ # contrasting colour for the lines
+ pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DLIGHT), 1, wx.SOLID)
+ dc.SetPen((self.GetBackgroundColour() == wx.WHITE and [pen] or [wx.WHITE_PEN])[0])
+ dc.DrawLine(0, y_top, total_width, y_top)
+ dc.DrawLine(0, y_top+h, total_width, y_top+h)
+
+ # draw item
+ self.PaintItem(item, dc)
+
+ # restore DC objects
+ dc.SetBrush(wx.WHITE_BRUSH)
+ dc.SetPen(self._dottedPen)
+
+ # clip to the column width
+ clip_width = self._owner.GetHeaderWindow().GetColumn(self._main_column).GetWidth()
+## clipper = wx.DCClipper(dc, x_maincol, y_top, clip_width, 10000)
+
+ if not self.HasAGWFlag(wx.TR_NO_LINES): # connection lines
+
+ # draw the horizontal line here
+ dc.SetPen(self._dottedPen)
+ x2 = x - self._indent
+ if x2 < (x_maincol + _MARGIN):
+ x2 = x_maincol + _MARGIN
+ x3 = x + (self._btnWidth-self._btnWidth2)
+ if self.HasButtons():
+ if item.HasPlus():
+ dc.DrawLine(x2, y_mid, x - self._btnWidth2, y_mid)
+ dc.DrawLine(x3, y_mid, x3 + _LINEATROOT, y_mid)
+ else:
+ dc.DrawLine(x2, y_mid, x3 + _LINEATROOT, y_mid)
+ else:
+ dc.DrawLine(x2, y_mid, x - self._indent/2, y_mid)
+
+ if item.HasPlus() and self.HasButtons(): # should the item show a button?
+
+ if self._imageListButtons:
+
+ # draw the image button here
+ image = wx.TreeItemIcon_Normal
+ if item.IsExpanded():
+ image = wx.TreeItemIcon_Expanded
+ if item.IsSelected():
+ image += wx.TreeItemIcon_Selected - wx.TreeItemIcon_Normal
+ xx = x - self._btnWidth2 + _MARGIN
+ yy = y_mid - self._btnHeight2
+ dc.SetClippingRegion(xx, yy, self._btnWidth, self._btnHeight)
+ self._imageListButtons.Draw(image, dc, xx, yy, wx.IMAGELIST_DRAW_TRANSPARENT)
+ dc.DestroyClippingRegion()
+
+ elif self.HasAGWFlag(wx.TR_TWIST_BUTTONS):
+
+ # draw the twisty button here
+ dc.SetPen(wx.BLACK_PEN)
+ dc.SetBrush(self._hilightBrush)
+ button = [wx.Point() for j in xrange(3)]
+ if item.IsExpanded():
+ button[0].x = x - (self._btnWidth2+1)
+ button[0].y = y_mid - (self._btnHeight/3)
+ button[1].x = x + (self._btnWidth2+1)
+ button[1].y = button[0].y
+ button[2].x = x
+ button[2].y = button[0].y + (self._btnHeight2+1)
+ else:
+ button[0].x = x - (self._btnWidth/3)
+ button[0].y = y_mid - (self._btnHeight2+1)
+ button[1].x = button[0].x
+ button[1].y = y_mid + (self._btnHeight2+1)
+ button[2].x = button[0].x + (self._btnWidth2+1)
+ button[2].y = y_mid
+
+ dc.SetClippingRegion(x_maincol + _MARGIN, y_top, clip_width, h)
+ dc.DrawPolygon(button)
+ dc.DestroyClippingRegion()
+
+ else: # if (HasAGWFlag(wxTR_HAS_BUTTONS))
+
+ rect = wx.Rect(x-self._btnWidth2, y_mid-self._btnHeight2, self._btnWidth, self._btnHeight)
+ flag = (item.IsExpanded() and [wx.CONTROL_EXPANDED] or [0])[0]
+ wx.RendererNative.GetDefault().DrawTreeItemButton(self, dc, rect, flag)
+
+ # restore DC objects
+ dc.SetBrush(wx.WHITE_BRUSH)
+ dc.SetPen(self._dottedPen)
+ dc.SetTextForeground(wx.BLACK)
+
+ if item.IsExpanded():
+
+ # process lower levels
+ if self._imgWidth > 0:
+ oldY = y_mid + self._imgHeight2
+ else:
+ oldY = y_mid + h/2
+
+ for child in item.GetChildren():
+
+ y, x_maincol = self.PaintLevel(child, dc, level+1, y, x_maincol)
+
+ # draw vertical line
+ if not self.HasAGWFlag(wx.TR_NO_LINES):
+ Y1 = child.GetY() + child.GetHeight()/2
+ dc.DrawLine(x, oldY, x, Y1)
+
+ return y, x_maincol
+
+
+# ----------------------------------------------------------------------------
+# wxWindows callbacks
+# ----------------------------------------------------------------------------
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`TreeListMainWindow`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+ """
+
+ # do not paint the background separately in buffered mode.
+ if not self._buffered:
+ CustomTreeCtrl.OnEraseBackground(self, event)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`TreeListMainWindow`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ if self._buffered:
+
+ # paint the background
+ dc = wx.BufferedPaintDC(self)
+ rect = self.GetUpdateRegion().GetBox()
+ dc.SetClippingRect(rect)
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ if self._backgroundImage:
+ self.TileBackground(dc)
+ else:
+ dc.Clear()
+
+ else:
+ dc = wx.PaintDC(self)
+
+ self.PrepareDC(dc)
+
+ if not self._anchor or self.GetColumnCount() <= 0:
+ return
+
+ # calculate button size
+ if self._imageListButtons:
+ self._btnWidth, self._btnHeight = self._imageListButtons.GetSize(0)
+ elif self.HasButtons():
+ self._btnWidth = _BTNWIDTH
+ self._btnHeight = _BTNHEIGHT
+
+ self._btnWidth2 = self._btnWidth/2
+ self._btnHeight2 = self._btnHeight/2
+
+ # calculate image size
+ if self._imageListNormal:
+ self._imgWidth, self._imgHeight = self._imageListNormal.GetSize(0)
+
+ self._imgWidth2 = self._imgWidth/2
+ self._imgHeight2 = self._imgHeight/2
+
+ if self._imageListCheck:
+ self._checkWidth, self._checkHeight = self._imageListCheck.GetSize(0)
+
+ self._checkWidth2 = self._checkWidth/2
+ self._checkHeight2 = self._checkHeight/2
+
+ # calculate indent size
+ if self._imageListButtons:
+ self._indent = max(_MININDENT, self._btnWidth + _MARGIN)
+ elif self.HasButtons():
+ self._indent = max(_MININDENT, self._btnWidth + _LINEATROOT)
+
+ # set default values
+ dc.SetFont(self._normalFont)
+ dc.SetPen(self._dottedPen)
+
+ # calculate column start and paint
+ x_maincol = 0
+ for i in xrange(self.GetMainColumn()):
+ if not self._owner.GetHeaderWindow().IsColumnShown(i):
+ continue
+ x_maincol += self._owner.GetHeaderWindow().GetColumnWidth(i)
+
+ y, x_maincol = self.PaintLevel(self._anchor, dc, 0, 0, x_maincol)
+
+
+ def HitTest(self, point, flags=0):
+ """
+ Calculates which (if any) item is under the given point, returning the tree item
+ at this point plus extra information flags plus the item's column.
+
+ :param `point`: an instance of :class:`Point`, a point to test for hits;
+ :param `flags`: a bitlist of the following values:
+
+ ================================== =============== =================================
+ HitTest Flags Hex Value Description
+ ================================== =============== =================================
+ ``TREE_HITTEST_ABOVE`` 0x1 Above the client area
+ ``TREE_HITTEST_BELOW`` 0x2 Below the client area
+ ``TREE_HITTEST_NOWHERE`` 0x4 No item has been hit
+ ``TREE_HITTEST_ONITEMBUTTON`` 0x8 On the button associated to an item
+ ``TREE_HITTEST_ONITEMICON`` 0x10 On the icon associated to an item
+ ``TREE_HITTEST_ONITEMINDENT`` 0x20 On the indent associated to an item
+ ``TREE_HITTEST_ONITEMLABEL`` 0x40 On the label (string) associated to an item
+ ``TREE_HITTEST_ONITEM`` 0x50 Anywhere on the item
+ ``TREE_HITTEST_ONITEMRIGHT`` 0x80 On the right of the label associated to an item
+ ``TREE_HITTEST_TOLEFT`` 0x200 On the left of the client area
+ ``TREE_HITTEST_TORIGHT`` 0x400 On the right of the client area
+ ``TREE_HITTEST_ONITEMUPPERPART`` 0x800 On the upper part (first half) of the item
+ ``TREE_HITTEST_ONITEMLOWERPART`` 0x1000 On the lower part (second half) of the item
+ ``TREE_HITTEST_ONITEMCHECKICON`` 0x2000 On the check/radio icon, if present
+ ================================== =============== =================================
+
+ :return: the item (if any, ``None`` otherwise), the `flags` and the column are always
+ returned as a tuple.
+ """
+
+ w, h = self.GetSize()
+ column = -1
+
+ if not isinstance(point, wx.Point):
+ point = wx.Point(*point)
+
+ if point.x < 0:
+ flags |= wx.TREE_HITTEST_TOLEFT
+ if point.x > w:
+ flags |= wx.TREE_HITTEST_TORIGHT
+ if point.y < 0:
+ flags |= wx.TREE_HITTEST_ABOVE
+ if point.y > h:
+ flags |= wx.TREE_HITTEST_BELOW
+ if flags:
+ return None, flags, column
+
+ if not self._anchor:
+ flags = wx.TREE_HITTEST_NOWHERE
+ column = -1
+ return None, flags, column
+
+ hit, flags, column = self._anchor.HitTest(self.CalcUnscrolledPosition(point), self, flags, column, 0)
+ if not hit:
+ flags = wx.TREE_HITTEST_NOWHERE
+ column = -1
+ return None, flags, column
+
+ return hit, flags, column
+
+
+ def EditLabel(self, item, column=None):
+ """
+ Starts editing an item label.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ if not item:
+ return
+
+ column = (column is not None and [column] or [self._main_column])[0]
+
+ if column < 0 or column >= self.GetColumnCount():
+ return
+
+ self._curColumn = column
+ self._editItem = item
+
+ te = TreeEvent(wx.wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, self._owner.GetId())
+ te.SetItem(self._editItem)
+ te.SetInt(column)
+ te.SetEventObject(self._owner)
+ self._owner.GetEventHandler().ProcessEvent(te)
+
+ if not te.IsAllowed():
+ return
+
+ # ensure that the position of the item it calculated in any case
+ if self._dirty:
+ self.CalculatePositions()
+
+ if self._editCtrl != None and (item != self._editCtrl.item() or column != self._editCtrl.column()):
+ self._editCtrl.StopEditing()
+
+ self._editCtrl = self._owner.CreateEditCtrl(item, column)
+ self._editCtrl.SetFocus()
+
+
+ def OnEditTimer(self):
+ """ The timer for editing has expired. Start editing. """
+
+ self.EditLabel(self._current, self._curColumn)
+
+
+ def OnAcceptEdit(self, value):
+ """
+ Called by :class:`EditTextCtrl`, to accept the changes and to send the
+ ``EVT_TREE_END_LABEL_EDIT`` event.
+
+ :param `value`: the new value of the item label.
+ """
+
+ # TODO if the validator fails this causes a crash
+ le = TreeEvent(wx.wxEVT_COMMAND_TREE_END_LABEL_EDIT, self._owner.GetId())
+ le.SetItem(self._editItem)
+ le.SetEventObject(self._owner)
+ le.SetLabel(value)
+ le.SetInt(self._curColumn if self._curColumn >= 0 else 0)
+ le._editCancelled = False
+ self._owner.GetEventHandler().ProcessEvent(le)
+
+ if not le.IsAllowed():
+ return
+
+ if self._curColumn == -1:
+ self._curColumn = 0
+
+ self.SetItemText(self._editItem, unicode(value), self._curColumn)
+
+
+ def OnCancelEdit(self):
+ """
+ Called by :class:`EditCtrl`, to cancel the changes and to send the
+ ``EVT_TREE_END_LABEL_EDIT`` event.
+ """
+
+ # let owner know that the edit was cancelled
+ le = TreeEvent(wx.wxEVT_COMMAND_TREE_END_LABEL_EDIT, self._owner.GetId())
+ le.SetItem(self._editItem)
+ le.SetEventObject(self._owner)
+ le.SetLabel("")
+ le._editCancelled = True
+
+ self._owner.GetEventHandler().ProcessEvent(le)
+
+
+ def OnMouse(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` event for :class:`TreeListMainWindow`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self._anchor:
+ return
+
+ # we process left mouse up event (enables in-place edit), right down
+ # (pass to the user code), left dbl click (activate item) and
+ # dragging/moving events for items drag-and-drop
+ if not (event.LeftDown() or event.LeftUp() or event.RightDown() or \
+ event.RightUp() or event.LeftDClick() or event.Dragging() or \
+ event.GetWheelRotation() != 0 or event.Moving()):
+ self._owner.GetEventHandler().ProcessEvent(event)
+ return
+
+
+ # set focus if window clicked
+ if event.LeftDown() or event.RightDown():
+ self._hasFocus = True
+ self.SetFocusIgnoringChildren()
+
+ # determine event
+ p = wx.Point(event.GetX(), event.GetY())
+ flags = 0
+ item, flags, column = self._anchor.HitTest(self.CalcUnscrolledPosition(p), self, flags, self._curColumn, 0)
+
+ underMouse = item
+ underMouseChanged = underMouse != self._underMouse
+
+ if underMouse and (flags & wx.TREE_HITTEST_ONITEM) and not event.LeftIsDown() and \
+ not self._isDragging and (not self._editTimer or not self._editTimer.IsRunning()):
+ underMouse = underMouse
+ else:
+ underMouse = None
+
+ if underMouse != self._underMouse:
+ if self._underMouse:
+ # unhighlight old item
+ self._underMouse = None
+
+ self._underMouse = underMouse
+
+ # Determines what item we are hovering over and need a tooltip for
+ hoverItem = item
+
+ if (event.LeftDown() or event.LeftUp() or event.RightDown() or \
+ event.RightUp() or event.LeftDClick() or event.Dragging()):
+ if self._editCtrl != None and (item != self._editCtrl.item() or column != self._editCtrl.column()):
+ self._editCtrl.StopEditing()
+
+ # We do not want a tooltip if we are dragging, or if the edit timer is running
+ if underMouseChanged and not self._isDragging and (not self._editTimer or not self._editTimer.IsRunning()):
+
+ if hoverItem is not None:
+ # Ask the tree control what tooltip (if any) should be shown
+ hevent = TreeEvent(wx.wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, self.GetId())
+ hevent.SetItem(hoverItem)
+ hevent.SetEventObject(self)
+
+ if self.GetEventHandler().ProcessEvent(hevent) and hevent.IsAllowed():
+ self.SetToolTip(hevent._label)
+
+ if hoverItem.IsHyperText() and (flags & wx.TREE_HITTEST_ONITEMLABEL) and hoverItem.IsEnabled():
+ self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+ self._isonhyperlink = True
+ else:
+ if self._isonhyperlink:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ self._isonhyperlink = False
+
+ # we only process dragging here
+ if event.Dragging():
+
+ if self._isDragging:
+ if not self._dragImage:
+ # Create the custom draw image from the icons and the text of the item
+ self._dragImage = DragImage(self, self._current or item)
+ self._dragImage.BeginDrag(wx.Point(0,0), self)
+ self._dragImage.Show()
+
+ self._dragImage.Move(p)
+
+ if self._countDrag == 0 and item:
+ self._oldItem = self._current
+ self._oldSelection = self._current
+
+ if item != self._dropTarget:
+
+ # unhighlight the previous drop target
+ if self._dropTarget:
+ self._dropTarget.SetHilight(False)
+ self.RefreshLine(self._dropTarget)
+ if item:
+ item.SetHilight(True)
+ self.RefreshLine(item)
+ self._countDrag = self._countDrag + 1
+ self._dropTarget = item
+
+ self.Update()
+
+ if self._countDrag >= 3 and self._oldItem is not None:
+ # Here I am trying to avoid ugly repainting problems... hope it works
+ self.RefreshLine(self._oldItem)
+ self._countDrag = 0
+
+ return # nothing to do, already done
+
+ if item == None:
+ return # we need an item to dragging
+
+ # determine drag start
+ if self._dragCount == 0:
+ self._dragTimer.Start(_DRAG_TIMER_TICKS, wx.TIMER_ONE_SHOT)
+
+ self._dragCount += 1
+ if self._dragCount < 3:
+ return # minimum drag 3 pixel
+ if self._dragTimer.IsRunning():
+ return
+
+ # we're going to drag
+ self._dragCount = 0
+
+ # send drag start event
+ command = (event.LeftIsDown() and [wx.wxEVT_COMMAND_TREE_BEGIN_DRAG] or [wx.wxEVT_COMMAND_TREE_BEGIN_RDRAG])[0]
+ nevent = TreeEvent(command, self._owner.GetId())
+ nevent.SetEventObject(self._owner)
+ nevent.SetItem(self._current) # the dragged item
+ nevent.SetPoint(p)
+ nevent.Veto() # dragging must be explicit allowed!
+
+ if self.GetEventHandler().ProcessEvent(nevent) and nevent.IsAllowed():
+
+ # we're going to drag this item
+ self._isDragging = True
+ self.CaptureMouse()
+ self.RefreshSelected()
+
+ # in a single selection control, hide the selection temporarily
+ if not (self._agwStyle & wx.TR_MULTIPLE):
+ if self._oldSelection:
+
+ self._oldSelection.SetHilight(False)
+ self.RefreshLine(self._oldSelection)
+ else:
+ selections = self.GetSelections()
+ if len(selections) == 1:
+ self._oldSelection = selections[0]
+ self._oldSelection.SetHilight(False)
+ self.RefreshLine(self._oldSelection)
+
+ elif self._isDragging: # any other event but not event.Dragging()
+
+ # end dragging
+ self._dragCount = 0
+ self._isDragging = False
+ if self.HasCapture():
+ self.ReleaseMouse()
+ self.RefreshSelected()
+
+ # send drag end event event
+ nevent = TreeEvent(wx.wxEVT_COMMAND_TREE_END_DRAG, self._owner.GetId())
+ nevent.SetEventObject(self._owner)
+ nevent.SetItem(item) # the item the drag is started
+ nevent.SetPoint(p)
+ self._owner.GetEventHandler().ProcessEvent(nevent)
+
+ if self._dragImage:
+ self._dragImage.EndDrag()
+
+ if self._dropTarget:
+ self._dropTarget.SetHilight(False)
+ self.RefreshLine(self._dropTarget)
+
+ if self._oldSelection:
+ self._oldSelection.SetHilight(True)
+ self.RefreshLine(self._oldSelection)
+ self._oldSelection = None
+
+ self._isDragging = False
+ self._dropTarget = None
+ if self._dragImage:
+ self._dragImage = None
+
+ self.Refresh()
+
+ elif self._dragCount > 0: # just in case dragging is initiated
+
+ # end dragging
+ self._dragCount = 0
+
+ # we process only the messages which happen on tree items
+ if (item == None or not self.IsItemEnabled(item)) and not event.GetWheelRotation():
+ self._owner.GetEventHandler().ProcessEvent(event)
+ return
+
+ # remember item at shift down
+ if event.ShiftDown():
+ if not self._shiftItem:
+ self._shiftItem = self._current
+ else:
+ self._shiftItem = None
+
+ if event.RightUp():
+
+ self.SetFocus()
+ nevent = TreeEvent(wx.wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, self._owner.GetId())
+ nevent.SetEventObject(self._owner)
+ nevent.SetItem(item) # the item clicked
+ nevent.SetInt(self._curColumn) # the column clicked
+ nevent.SetPoint(p)
+ self._owner.GetEventHandler().ProcessEvent(nevent)
+
+ elif event.LeftUp():
+
+ if self._lastOnSame:
+ if item == self._current and self._curColumn != -1 and \
+ self._owner.GetHeaderWindow().IsColumnEditable(self._curColumn) and \
+ flags & (wx.TREE_HITTEST_ONITEMLABEL | wx.TREE_HITTEST_ONITEMCOLUMN) and \
+ ((self._editCtrl != None and column != self._editCtrl.column()) or self._editCtrl is None):
+ self._editTimer.Start(_EDIT_TIMER_TICKS, wx.TIMER_ONE_SHOT)
+
+ self._lastOnSame = False
+
+ if (((flags & wx.TREE_HITTEST_ONITEMBUTTON) or (flags & wx.TREE_HITTEST_ONITEMICON)) and \
+ self.HasButtons() and item.HasPlus()):
+
+ # only toggle the item for a single click, double click on
+ # the button doesn't do anything (it toggles the item twice)
+ if event.LeftDown():
+ self.Toggle(item)
+
+ # don't select the item if the button was clicked
+ return
+
+ # determine the selection if not done by left down
+ if not self._left_down_selection:
+ unselect_others = not ((event.ShiftDown() or event.CmdDown()) and self.HasAGWFlag(wx.TR_MULTIPLE))
+ self.DoSelectItem(item, unselect_others, event.ShiftDown())
+ self.EnsureVisible (item)
+ self._current = self._key_current = item # make the new item the current item
+ else:
+ self._left_down_selection = False
+
+ elif event.LeftDown() or event.RightDown() or event.LeftDClick():
+
+ if column >= 0:
+ self._curColumn = column
+
+ if event.LeftDown() or event.RightDown():
+ self.SetFocus()
+ self._lastOnSame = item == self._current
+
+ if (((flags & wx.TREE_HITTEST_ONITEMBUTTON) or (flags & wx.TREE_HITTEST_ONITEMICON)) and \
+ self.HasButtons() and item.HasPlus()):
+
+ # only toggle the item for a single click, double click on
+ # the button doesn't do anything (it toggles the item twice)
+ if event.LeftDown():
+ self.Toggle(item)
+
+ # don't select the item if the button was clicked
+ return
+
+ if flags & TREE_HITTEST_ONITEMCHECKICON and event.LeftDown():
+ if item.GetType() > 0:
+ if self.IsItem3State(item):
+ checked = self.GetItem3StateValue(item)
+ checked = (checked+1)%3
+ else:
+ checked = not self.IsItemChecked(item)
+
+ self.CheckItem(item, checked)
+ return
+
+ # determine the selection if the current item is not selected
+ if not item.IsSelected():
+ unselect_others = not ((event.ShiftDown() or event.CmdDown()) and self.HasAGWFlag(wx.TR_MULTIPLE))
+ self.DoSelectItem(item, unselect_others, event.ShiftDown())
+ self.EnsureVisible(item)
+ self._current = self._key_current = item # make the new item the current item
+ self._left_down_selection = True
+
+ # For some reason, Windows isn't recognizing a left double-click,
+ # so we need to simulate it here. Allow 200 milliseconds for now.
+ if event.LeftDClick():
+
+ # double clicking should not start editing the item label
+ self._editTimer.Stop()
+ self._lastOnSame = False
+
+ # send activate event first
+ nevent = TreeEvent(wx.wxEVT_COMMAND_TREE_ITEM_ACTIVATED, self._owner.GetId())
+ nevent.SetEventObject(self._owner)
+ nevent.SetItem(item) # the item clicked
+ nevent.SetInt(self._curColumn) # the column clicked
+ nevent.SetPoint(p)
+ if not self._owner.GetEventHandler().ProcessEvent(nevent):
+
+ # if the user code didn't process the activate event,
+ # handle it ourselves by toggling the item when it is
+ # double clicked
+ if item.HasPlus():
+ self.Toggle(item)
+
+ else: # any other event skip just in case
+
+ event.Skip()
+
+
+ def OnScroll(self, event):
+ """
+ Handles the ``wx.EVT_SCROLLWIN`` event for :class:`TreeListMainWindow`.
+
+ :param `event`: a :class:`ScrollEvent` event to be processed.
+ """
+
+ def _updateHeaderWindow(header):
+ header.Refresh()
+ header.Update()
+
+ # Update the header window after this scroll event has fully finished
+ # processing, and the scoll action is complete.
+ if event.GetOrientation() == wx.HORIZONTAL:
+ wx.CallAfter(_updateHeaderWindow, self._owner.GetHeaderWindow())
+ event.Skip()
+
+
+ def CalculateSize(self, item, dc):
+ """
+ Calculates overall position and size of an item.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ attr = item.GetAttributes()
+
+ if attr and attr.HasFont():
+ dc.SetFont(attr.GetFont())
+ elif item.IsBold():
+ dc.SetFont(self._boldFont)
+ else:
+ dc.SetFont(self._normalFont)
+
+ text_w = text_h = wnd_w = wnd_h = 0
+ for column in xrange(self.GetColumnCount()):
+ w, h, dummy = dc.GetMultiLineTextExtent(item.GetText(column))
+ text_w, text_h = max(w, text_w), max(h, text_h)
+
+ wnd = item.GetWindow(column)
+ if wnd:
+ wnd_h = max(wnd_h, item.GetWindowSize(column)[1])
+ if column == self._main_column:
+ wnd_w = item.GetWindowSize(column)[0]
+
+ text_w, dummy, dummy = dc.GetMultiLineTextExtent(item.GetText(self._main_column))
+ text_h+=2
+
+ # restore normal font
+ dc.SetFont(self._normalFont)
+
+ image_w, image_h = 0, 0
+ image = item.GetCurrentImage()
+
+ if image != _NO_IMAGE:
+
+ if self._imageListNormal:
+
+ image_w, image_h = self._imageListNormal.GetSize(image)
+ image_w += 2*_MARGIN
+
+ total_h = ((image_h > text_h) and [image_h] or [text_h])[0]
+
+ checkimage = item.GetCurrentCheckedImage()
+ if checkimage is not None:
+ wcheck, hcheck = self._imageListCheck.GetSize(checkimage)
+ wcheck += 2*_MARGIN
+ else:
+ wcheck = 0
+
+ if total_h < 30:
+ total_h += 2 # at least 2 pixels
+ else:
+ total_h += total_h/10 # otherwise 10% extra spacing
+
+ if total_h > self._lineHeight:
+ self._lineHeight = max(total_h, wnd_h+2)
+
+ item.SetWidth(image_w+text_w+wcheck+2+wnd_w)
+ item.SetHeight(max(total_h, wnd_h+2))
+
+
+ def CalculateLevel(self, item, dc, level, y, x_colstart):
+ """
+ Calculates the level of an item inside the tree hierarchy.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `level`: the item level in the tree hierarchy;
+ :param `y`: the current vertical position inside the :class:`PyScrolledWindow`;
+ :param `x_colstart`: the x coordinate at which the item's column starts.
+ """
+
+ # calculate position of vertical lines
+ x = x_colstart + _MARGIN # start of column
+ if self.HasAGWFlag(wx.TR_LINES_AT_ROOT):
+ x += _LINEATROOT # space for lines at root
+ if self.HasButtons():
+ x += (self._btnWidth-self._btnWidth2) # half button space
+ else:
+ x += (self._indent-self._indent/2)
+
+ if self.HasAGWFlag(wx.TR_HIDE_ROOT):
+ x += self._indent * (level-1) # indent but not level 1
+ else:
+ x += self._indent * level # indent according to level
+
+ # a hidden root is not evaluated, but its children are always
+ if self.HasAGWFlag(wx.TR_HIDE_ROOT) and (level == 0):
+ # a hidden root is not evaluated, but its
+ # children are always calculated
+ children = item.GetChildren()
+ count = len(children)
+ level = level + 1
+ for n in xrange(count):
+ y = self.CalculateLevel(children[n], dc, level, y, x_colstart) # recurse
+
+ return y
+
+ self.CalculateSize(item, dc)
+
+ # set its position
+ item.SetX(x)
+ item.SetY(y)
+ y += self.GetLineHeight(item)
+
+ if not item.IsExpanded():
+ # we don't need to calculate collapsed branches
+ return y
+
+ children = item.GetChildren()
+ count = len(children)
+ level = level + 1
+ for n in xrange(count):
+ y = self.CalculateLevel(children[n], dc, level, y, x_colstart) # recurse
+
+ return y
+
+
+ def CalculatePositions(self):
+ """ Recalculates all the items positions. """
+
+ if not self._anchor:
+ return
+
+ dc = wx.ClientDC(self)
+ self.PrepareDC(dc)
+
+ dc.SetFont(self._normalFont)
+ dc.SetPen(self._dottedPen)
+
+ y, x_colstart = 2, 0
+ for i in xrange(self.GetMainColumn()):
+ if not self._owner.GetHeaderWindow().IsColumnShown(i):
+ continue
+ x_colstart += self._owner.GetHeaderWindow().GetColumnWidth(i)
+
+ self.CalculateLevel(self._anchor, dc, 0, y, x_colstart) # start recursion
+
+
+ def SetItemText(self, item, text, column=None):
+ """
+ Sets the item text label.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `text`: a string specifying the new item label;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ dc = wx.ClientDC(self)
+ item.SetText(column, text)
+ self.CalculateSize(item, dc)
+ self.RefreshLine(item)
+
+
+ def GetItemText(self, item, column=None):
+ """
+ Returns the item text label.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `column`: if not ``None``, an integer specifying the column index.
+ If it is ``None``, the main column index is used.
+ """
+
+ if self.IsVirtual():
+ return self._owner.OnGetItemText(item, column)
+ else:
+ return item.GetText(column)
+
+
+ def GetItemWidth(self, item, column):
+ """
+ Returns the item width.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `column`: an integer specifying the column index.
+ """
+
+ if not item:
+ return 0
+
+ # determine item width
+ font = self.GetItemFont(item)
+ if not font.IsOk():
+ if item.IsBold():
+ font = self._boldFont
+ elif item.IsItalic():
+ font = self._italicFont
+ elif item.IsHyperText():
+ font = self.GetHyperTextFont()
+ else:
+ font = self._normalFont
+
+ dc = wx.ClientDC(self)
+ dc.SetFont(font)
+ w, h, dummy = dc.GetMultiLineTextExtent(item.GetText(column))
+ w += 2*_MARGIN
+
+ # calculate width
+ width = w + 2*_MARGIN
+ if column == self.GetMainColumn():
+ width += _MARGIN
+ if self.HasAGWFlag(wx.TR_LINES_AT_ROOT):
+ width += _LINEATROOT
+ if self.HasButtons():
+ width += self._btnWidth + _LINEATROOT
+ if item.GetCurrentImage() != _NO_IMAGE:
+ width += self._imgWidth
+
+ # count indent level
+ level = 0
+ parent = item.GetParent()
+ root = self.GetRootItem()
+ while (parent and (not self.HasAGWFlag(wx.TR_HIDE_ROOT) or (parent != root))):
+ level += 1
+ parent = parent.GetParent()
+
+ if level:
+ width += level*self.GetIndent()
+
+ wnd = item.GetWindow(column)
+ if wnd:
+ width += wnd.GetSize()[0] + 2*_MARGIN
+
+ return width
+
+
+ def GetBestColumnWidth(self, column, parent=None):
+ """
+ Returns the best column's width based on the items width in this column.
+
+ :param `column`: an integer specifying the column index;
+ :param `parent`: an instance of :class:`TreeListItem`.
+ """
+
+ maxWidth, h = self.GetClientSize()
+ width = 0
+
+ if maxWidth < 5:
+ # Not shown on screen
+ maxWidth = 1000
+
+ # get root if on item
+ if not parent:
+ parent = self.GetRootItem()
+
+ # add root width
+ if not self.HasAGWFlag(wx.TR_HIDE_ROOT):
+ w = self.GetItemWidth(parent, column)
+ if width < w:
+ width = w
+ if width > maxWidth:
+ return maxWidth
+
+ item, cookie = self.GetFirstChild(parent)
+ while item:
+ w = self.GetItemWidth(item, column)
+ if width < w:
+ width = w
+ if width > maxWidth:
+ return maxWidth
+
+ # check the children of this item
+ if item.IsExpanded():
+ w = self.GetBestColumnWidth(column, item)
+ if width < w:
+ width = w
+ if width > maxWidth:
+ return maxWidth
+
+ # next sibling
+ item, cookie = self.GetNextChild(parent, cookie)
+
+ return max(10, width) # Prevent zero column width
+
+
+ def HideItem(self, item, hide=True):
+ """
+ Hides/shows an item.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `hide`: ``True`` to hide the item, ``False`` to show it.
+ """
+
+ item.Hide(hide)
+ self.Refresh()
+
+
+#----------------------------------------------------------------------------
+# TreeListCtrl - the multicolumn tree control
+#----------------------------------------------------------------------------
+
+_methods = ["GetIndent", "SetIndent", "GetSpacing", "SetSpacing", "GetImageList", "GetStateImageList",
+ "GetButtonsImageList", "AssignImageList", "AssignStateImageList", "AssignButtonsImageList",
+ "SetImageList", "SetButtonsImageList", "SetStateImageList",
+ "GetItemText", "GetItemImage", "GetItemPyData", "GetPyData", "GetItemTextColour",
+ "GetItemBackgroundColour", "GetItemFont", "SetItemText", "SetItemImage", "SetItemPyData", "SetPyData",
+ "SetItemHasChildren", "SetItemBackgroundColour", "SetItemFont", "IsItemVisible", "HasChildren",
+ "IsExpanded", "IsSelected", "IsBold", "GetChildrenCount", "GetRootItem", "GetSelection", "GetSelections",
+ "GetItemParent", "GetFirstChild", "GetNextChild", "GetPrevChild", "GetLastChild", "GetNextSibling",
+ "GetPrevSibling", "GetNext", "GetFirstExpandedItem", "GetNextExpanded", "GetPrevExpanded",
+ "GetFirstVisibleItem", "GetNextVisible", "GetPrevVisible", "AddRoot", "PrependItem", "InsertItem",
+ "AppendItem", "Delete", "DeleteChildren", "DeleteRoot", "Expand", "ExpandAll", "ExpandAllChildren",
+ "Collapse", "CollapseAndReset", "Toggle", "Unselect", "UnselectAll", "SelectItem", "SelectAll",
+ "EnsureVisible", "ScrollTo", "HitTest", "GetBoundingRect", "EditLabel", "FindItem", "SelectAllChildren",
+ "SetDragItem", "GetColumnCount", "SetMainColumn", "GetHyperTextFont", "SetHyperTextFont",
+ "SetHyperTextVisitedColour", "GetHyperTextVisitedColour", "SetHyperTextNewColour", "GetHyperTextNewColour",
+ "SetItemVisited", "GetItemVisited", "SetHilightFocusColour", "GetHilightFocusColour", "SetHilightNonFocusColour",
+ "GetHilightNonFocusColour", "SetFirstGradientColour", "GetFirstGradientColour", "SetSecondGradientColour",
+ "GetSecondGradientColour", "EnableSelectionGradient", "SetGradientStyle", "GetGradientStyle",
+ "EnableSelectionVista", "SetBorderPen", "GetBorderPen", "SetConnectionPen", "GetConnectionPen",
+ "SetBackgroundImage", "GetBackgroundImage", "SetImageListCheck", "GetImageListCheck", "EnableChildren",
+ "EnableItem", "IsItemEnabled", "GetDisabledColour", "SetDisabledColour", "IsItemChecked",
+ "UnCheckRadioParent", "CheckItem", "CheckItem2", "AutoToggleChild", "AutoCheckChild", "AutoCheckParent",
+ "CheckChilds", "CheckSameLevel", "GetItemWindowEnabled", "SetItemWindowEnabled", "GetItemType",
+ "IsDescendantOf", "SetItemHyperText", "IsItemHyperText", "SetItemBold", "SetItemDropHighlight", "SetItemItalic",
+ "GetEditControl", "ShouldInheritColours", "GetItemWindow", "SetItemWindow", "SetItemTextColour", "HideItem",
+ "DeleteAllItems", "ItemHasChildren", "ToggleItemSelection", "SetItemType", "GetCurrentItem",
+ "SetItem3State", "SetItem3StateValue", "GetItem3StateValue", "IsItem3State", "GetPrev"]
+
+
+class HyperTreeList(wx.PyControl):
+ """
+ :class:`HyperTreeList` is a class that mimics the behaviour of :class:`gizmos.TreeListCtrl`, with
+ almost the same base functionalities plus some more enhancements. This class does
+ not rely on the native control, as it is a full owner-drawn tree-list control.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=wx.TR_DEFAULT_STYLE, validator=wx.DefaultValidator,
+ name="HyperTreeList"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`PyScrolledWindow` style;
+ :param `agwStyle`: the AGW-specific :class:`HyperTreeList` window style. This can be a combination
+ of the following bits:
+
+ ============================== =========== ==================================================
+ Window Styles Hex Value Description
+ ============================== =========== ==================================================
+ ``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn.
+ ``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default.
+ ``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items.
+ ``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors.
+ ``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set.
+ ``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit.
+ ``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons.
+ ``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected.
+ ``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases).
+ ``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset.
+ ``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control.
+ ``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows.
+ ``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes.
+ ``TR_COLUMN_LINES`` 0x1000 Use this style to draw a contrasting border between displayed columns.
+ ``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window.
+ ``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well.
+ ``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly.
+ ``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful foe checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well.
+ ``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position.
+ ``TR_NO_HEADER`` 0x40000 Use this style to hide the columns header.
+ ``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`~lib.agw.customtreectrl.CustomTreeCtrl` is low.
+ ``TR_VIRTUAL`` 0x100000 :class:`HyperTreeList` will have virtual behaviour.
+ ============================== =========== ==================================================
+
+ :param `validator`: window validator;
+ :param `name`: window name.
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name)
+
+ self._header_win = None
+ self._main_win = None
+ self._headerHeight = 0
+ self._attr_set = False
+
+ main_style = style & ~(wx.SIMPLE_BORDER|wx.SUNKEN_BORDER|wx.DOUBLE_BORDER|
+ wx.RAISED_BORDER|wx.STATIC_BORDER)
+
+ self._agwStyle = agwStyle
+
+ self._main_win = TreeListMainWindow(self, -1, wx.Point(0, 0), size, main_style, agwStyle, validator)
+ self._main_win._buffered = False
+
+ self._header_win = TreeListHeaderWindow(self, -1, self._main_win, wx.Point(0, 0),
+ wx.DefaultSize, wx.TAB_TRAVERSAL)
+ self._header_win._buffered = False
+
+ self.CalculateAndSetHeaderHeight()
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ self.SetBuffered(IsBufferingSupported())
+ self._main_win.SetAGWWindowStyleFlag(agwStyle)
+
+
+ def SetBuffered(self, buffered):
+ """
+ Sets/unsets the double buffering for the header and the main window.
+
+ :param `buffered`: ``True`` to use double-buffering, ``False`` otherwise.
+
+ :note: Currently we are using double-buffering only on Windows XP.
+ """
+
+ self._main_win.SetBuffered(buffered)
+ self._header_win.SetBuffered(buffered)
+
+
+ def CalculateAndSetHeaderHeight(self):
+ """ Calculates the best header height and stores it. """
+
+ if self._header_win:
+ h = wx.RendererNative.Get().GetHeaderButtonHeight(self._header_win)
+ # only update if changed
+ if h != self._headerHeight:
+ self._headerHeight = h
+ self.DoHeaderLayout()
+
+
+ def DoHeaderLayout(self):
+ """ Layouts the header control. """
+
+ w, h = self.GetClientSize()
+ has_header = self._agwStyle & TR_NO_HEADER == 0
+
+ if self._header_win and has_header:
+ self._header_win.SetDimensions(0, 0, w, self._headerHeight)
+ self._header_win.Refresh()
+ else:
+ self._header_win.SetDimensions(0, 0, 0, 0)
+
+ if self._main_win and has_header:
+ self._main_win.SetDimensions(0, self._headerHeight + 1, w, h - self._headerHeight - 1)
+ else:
+ self._main_win.SetDimensions(0, 0, w, h)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`HyperTreeList`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.DoHeaderLayout()
+
+
+ def SetFont(self, font):
+ """
+ Sets the default font for the header window and the main window.
+
+ :param `font`: a valid :class:`Font` object.
+ """
+
+ if self._header_win:
+ self._header_win.SetFont(font)
+ self.CalculateAndSetHeaderHeight()
+ self._header_win.Refresh()
+
+ if self._main_win:
+ return self._main_win.SetFont(font)
+ else:
+ return False
+
+
+ def SetHeaderFont(self, font):
+ """
+ Sets the default font for the header window..
+
+ :param `font`: a valid :class:`Font` object.
+ """
+
+ if not self._header_win:
+ return
+
+ for column in xrange(self.GetColumnCount()):
+ self._header_win.SetColumn(column, self.GetColumn(column).SetFont(font))
+
+ self._header_win.Refresh()
+
+
+ def SetHeaderCustomRenderer(self, renderer=None):
+ """
+ Associate a custom renderer with the header - all columns will use it
+
+ :param `renderer`: a class able to correctly render header buttons
+
+ :note: the renderer class **must** implement the method `DrawHeaderButton`
+ """
+
+ self._header_win.SetCustomRenderer(renderer)
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the window style for :class:`HyperTreeList`.
+
+ :param `agwStyle`: can be a combination of the following bits:
+
+ ============================== =========== ==================================================
+ Window Styles Hex Value Description
+ ============================== =========== ==================================================
+ ``TR_NO_BUTTONS`` 0x0 For convenience to document that no buttons are to be drawn.
+ ``TR_SINGLE`` 0x0 For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default.
+ ``TR_HAS_BUTTONS`` 0x1 Use this style to show + and - buttons to the left of parent items.
+ ``TR_NO_LINES`` 0x4 Use this style to hide vertical level connectors.
+ ``TR_LINES_AT_ROOT`` 0x8 Use this style to show lines between root nodes. Only applicable if ``TR_HIDE_ROOT`` is set and ``TR_NO_LINES`` is not set.
+ ``TR_DEFAULT_STYLE`` 0x9 The set of flags that are closest to the defaults for the native control for a particular toolkit.
+ ``TR_TWIST_BUTTONS`` 0x10 Use old Mac-twist style buttons.
+ ``TR_MULTIPLE`` 0x20 Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected.
+ ``TR_EXTENDED`` 0x40 Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases).
+ ``TR_HAS_VARIABLE_ROW_HEIGHT`` 0x80 Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset.
+ ``TR_EDIT_LABELS`` 0x200 Use this style if you wish the user to be able to edit labels in the tree control.
+ ``TR_ROW_LINES`` 0x400 Use this style to draw a contrasting border between displayed rows.
+ ``TR_HIDE_ROOT`` 0x800 Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes.
+ ``TR_COLUMN_LINES`` 0x1000 Use this style to draw a contrasting border between displayed columns.
+ ``TR_FULL_ROW_HIGHLIGHT`` 0x2000 Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree control window.
+ ``TR_AUTO_CHECK_CHILD`` 0x4000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are checked/unchecked as well.
+ ``TR_AUTO_TOGGLE_CHILD`` 0x8000 Only meaningful foe checkbox-type items: when a parent item is checked/unchecked its children are toggled accordingly.
+ ``TR_AUTO_CHECK_PARENT`` 0x10000 Only meaningful foe checkbox-type items: when a child item is checked/unchecked its parent item is checked/unchecked as well.
+ ``TR_ALIGN_WINDOWS`` 0x20000 Flag used to align windows (in items with windows) at the same horizontal position.
+ ``TR_NO_HEADER`` 0x40000 Use this style to hide the columns header.
+ ``TR_ELLIPSIZE_LONG_ITEMS`` 0x80000 Flag used to ellipsize long items when the horizontal space for :class:`~lib.agw.customtreectrl.CustomTreeCtrl` is low.
+ ``TR_VIRTUAL`` 0x100000 :class:`HyperTreeList` will have virtual behaviour.
+ ============================== =========== ==================================================
+
+ :note: Please note that some styles cannot be changed after the window creation
+ and that `Refresh()` might need to be be called after changing the others for
+ the change to take place immediately.
+ """
+
+ if self._main_win:
+ self._main_win.SetAGWWindowStyleFlag(agwStyle)
+
+ tmp = self._agwStyle
+ self._agwStyle = agwStyle
+ if abs(agwStyle - tmp) & TR_NO_HEADER:
+ self.DoHeaderLayout()
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`HyperTreeList` window style flag.
+
+ :see: :meth:`~HyperTreeList.SetAGWWindowStyleFlag` for a list of valid window styles.
+ """
+
+ agwStyle = self._agwStyle
+ if self._main_win:
+ agwStyle |= self._main_win.GetAGWWindowStyleFlag()
+
+ return agwStyle
+
+
+ def HasAGWFlag(self, flag):
+ """
+ Returns whether a flag is present in the :class:`HyperTreeList` style.
+
+ :param `flag`: one of the possible :class:`HyperTreeList` window styles.
+
+ :see: :meth:`~HyperTreeList.SetAGWWindowStyleFlag` for a list of possible window style flags.
+ """
+
+ agwStyle = self.GetAGWWindowStyleFlag()
+ res = (agwStyle & flag and [True] or [False])[0]
+ return res
+
+
+ def SetBackgroundColour(self, colour):
+ """
+ Changes the background colour of :class:`HyperTreeList`.
+
+ :param `colour`: the colour to be used as the background colour, pass
+ :class:`NullColour` to reset to the default colour.
+
+ :note: The background colour is usually painted by the default :class:`EraseEvent`
+ event handler function under Windows and automatically under GTK.
+
+ :note: Setting the background colour does not cause an immediate refresh, so
+ you may wish to call :meth:`Window.ClearBackground` or :meth:`Window.Refresh` after
+ calling this function.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ if not self._main_win:
+ return False
+
+ return self._main_win.SetBackgroundColour(colour)
+
+
+ def SetForegroundColour(self, colour):
+ """
+ Changes the foreground colour of :class:`HyperTreeList`.
+
+ :param `colour`: the colour to be used as the foreground colour, pass
+ :class:`NullColour` to reset to the default colour.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ if not self._main_win:
+ return False
+
+ return self._main_win.SetForegroundColour(colour)
+
+
+ def SetColumnWidth(self, column, width):
+ """
+ Sets the column width, in pixels.
+
+ :param `column`: an integer specifying the column index;
+ :param `width`: the new column width, in pixels.
+ """
+
+ if width == wx.LIST_AUTOSIZE_USEHEADER:
+
+ font = self._header_win.GetFont()
+ dc = wx.ClientDC(self._header_win)
+ width, dummy, dummy = dc.GetMultiLineTextExtent(self._header_win.GetColumnText(column))
+ # Search TreeListHeaderWindow.OnPaint to understand this:
+ width += 2*_EXTRA_WIDTH + _MARGIN
+
+ elif width == wx.LIST_AUTOSIZE:
+
+ width = self._main_win.GetBestColumnWidth(column)
+
+ elif width == LIST_AUTOSIZE_CONTENT_OR_HEADER:
+
+ width1 = self._main_win.GetBestColumnWidth(column)
+ font = self._header_win.GetFont()
+ dc = wx.ClientDC(self._header_win)
+ width2, dummy, dummy = dc.GetMultiLineTextExtent(self._header_win.GetColumnText(column))
+
+ width2 += 2*_EXTRA_WIDTH + _MARGIN
+ width = max(width1, width2)
+
+
+ self._header_win.SetColumnWidth(column, width)
+ self._header_win.Refresh()
+
+
+ def GetColumnWidth(self, column):
+ """
+ Returns the column width, in pixels.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self._header_win.GetColumnWidth(column)
+
+
+ def SetColumnText(self, column, text):
+ """
+ Sets the column text label.
+
+ :param `column`: an integer specifying the column index;
+ :param `text`: the new column label.
+ """
+
+ self._header_win.SetColumnText(column, text)
+ self._header_win.Refresh()
+
+
+ def GetColumnText(self, column):
+ """
+ Returns the column text label.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self._header_win.GetColumnText(column)
+
+
+ def AddColumn(self, text, width=_DEFAULT_COL_WIDTH, flag=wx.ALIGN_LEFT,
+ image=-1, shown=True, colour=None, edit=False):
+ """
+ Appends a column to the :class:`HyperTreeList`.
+
+ :param `text`: the column text label;
+ :param `width`: the column width in pixels;
+ :param `flag`: the column alignment flag, one of ``wx.ALIGN_LEFT``,
+ ``wx.ALIGN_RIGHT``, ``wx.ALIGN_CENTER``;
+ :param `image`: an index within the normal image list assigned to
+ :class:`HyperTreeList` specifying the image to use for the column;
+ :param `shown`: ``True`` to show the column, ``False`` to hide it;
+ :param `colour`: a valid :class:`Colour`, representing the text foreground colour
+ for the column;
+ :param `edit`: ``True`` to set the column as editable, ``False`` otherwise.
+ """
+
+ self._header_win.AddColumn(text, width, flag, image, shown, colour, edit)
+ self.DoHeaderLayout()
+
+
+ def AddColumnInfo(self, colInfo):
+ """
+ Appends a column to the :class:`HyperTreeList`.
+
+ :param `colInfo`: an instance of :class:`TreeListColumnInfo`.
+ """
+
+ self._header_win.AddColumnInfo(colInfo)
+ self.DoHeaderLayout()
+
+
+ def InsertColumnInfo(self, before, colInfo):
+ """
+ Inserts a column to the :class:`HyperTreeList` at the position specified
+ by `before`.
+
+ :param `before`: the index at which we wish to insert the new column;
+ :param `colInfo`: an instance of :class:`TreeListColumnInfo`.
+ """
+
+ self._header_win.InsertColumnInfo(before, colInfo)
+ self._header_win.Refresh()
+
+
+ def InsertColumn(self, before, text, width=_DEFAULT_COL_WIDTH,
+ flag=wx.ALIGN_LEFT, image=-1, shown=True, colour=None,
+ edit=False):
+ """
+ Inserts a column to the :class:`HyperTreeList` at the position specified
+ by `before`.
+
+ :param `before`: the index at which we wish to insert the new column;
+ :param `text`: the column text label;
+ :param `width`: the column width in pixels;
+ :param `flag`: the column alignment flag, one of ``wx.ALIGN_LEFT``,
+ ``wx.ALIGN_RIGHT``, ``wx.ALIGN_CENTER``;
+ :param `image`: an index within the normal image list assigned to
+ :class:`HyperTreeList` specifying the image to use for the column;
+ :param `shown`: ``True`` to show the column, ``False`` to hide it;
+ :param `colour`: a valid :class:`Colour`, representing the text foreground colour
+ for the column;
+ :param `edit`: ``True`` to set the column as editable, ``False`` otherwise.
+ """
+
+ self._header_win.InsertColumn(before, text, width, flag, image,
+ shown, colour, edit)
+ self._header_win.Refresh()
+
+
+ def RemoveColumn(self, column):
+ """
+ Removes a column from the :class:`HyperTreeList`.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ self._header_win.RemoveColumn(column)
+ self._header_win.Refresh()
+
+
+ def SetColumn(self, column, colInfo):
+ """
+ Sets a column using an instance of :class:`TreeListColumnInfo`.
+
+ :param `column`: an integer specifying the column index;
+ :param `info`: an instance of :class:`TreeListColumnInfo`.
+ """
+
+ self._header_win.SetColumn(column, colInfo)
+ self._header_win.Refresh()
+
+
+ def GetColumn(self, column):
+ """
+ Returns an instance of :class:`TreeListColumnInfo` containing column information.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self._header_win.GetColumn(column)
+
+
+ def SetColumnImage(self, column, image):
+ """
+ Sets an image on the specified column.
+
+ :param `column`: an integer specifying the column index.
+ :param `image`: an index within the normal image list assigned to
+ :class:`HyperTreeList` specifying the image to use for the column.
+ """
+
+ self._header_win.SetColumn(column, self.GetColumn(column).SetImage(image))
+ self._header_win.Refresh()
+
+
+ def GetColumnImage(self, column):
+ """
+ Returns the image assigned to the specified column.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self._header_win.GetColumn(column).GetImage()
+
+
+ def SetColumnEditable(self, column, edit):
+ """
+ Sets the column as editable or non-editable.
+
+ :param `column`: an integer specifying the column index;
+ :param `edit`: ``True`` if the column should be editable, ``False`` otherwise.
+ """
+
+ self._header_win.SetColumn(column, self.GetColumn(column).SetEditable(edit))
+
+
+ def SetColumnShown(self, column, shown):
+ """
+ Sets the column as shown or hidden.
+
+ :param `column`: an integer specifying the column index;
+ :param `shown`: ``True`` if the column should be shown, ``False`` if it
+ should be hidden.
+ """
+
+ if self._main_win.GetMainColumn() == column:
+ shown = True # Main column cannot be hidden
+
+ self.SetColumn(column, self.GetColumn(column).SetShown(shown))
+
+
+ def IsColumnEditable(self, column):
+ """
+ Returns ``True`` if the column is editable, ``False`` otherwise.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self._header_win.GetColumn(column).IsEditable()
+
+
+ def IsColumnShown(self, column):
+ """
+ Returns ``True`` if the column is shown, ``False`` otherwise.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self._header_win.GetColumn(column).IsShown()
+
+
+ def SetColumnAlignment(self, column, flag):
+ """
+ Sets the column text alignment.
+
+ :param `column`: an integer specifying the column index;
+ :param `flag`: the alignment flag, one of ``wx.ALIGN_LEFT``, ``wx.ALIGN_RIGHT``,
+ ``wx.ALIGN_CENTER``.
+ """
+
+ self._header_win.SetColumn(column, self.GetColumn(column).SetAlignment(flag))
+ self._header_win.Refresh()
+
+
+ def GetColumnAlignment(self, column):
+ """
+ Returns the column text alignment.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self._header_win.GetColumn(column).GetAlignment()
+
+
+ def SetColumnColour(self, column, colour):
+ """
+ Sets the column text colour.
+
+ :param `column`: an integer specifying the column index;
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._header_win.SetColumn(column, self.GetColumn(column).SetColour(colour))
+ self._header_win.Refresh()
+
+
+ def GetColumnColour(self, column):
+ """
+ Returns the column text colour.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self._header_win.GetColumn(column).GetColour()
+
+
+ def SetColumnFont(self, column, font):
+ """
+ Sets the column text font.
+
+ :param `column`: an integer specifying the column index;
+ :param `font`: a valid :class:`Font` object.
+ """
+
+ self._header_win.SetColumn(column, self.GetColumn(column).SetFont(font))
+ self._header_win.Refresh()
+
+
+ def GetColumnFont(self, column):
+ """
+ Returns the column text font.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self._header_win.GetColumn(column).GetFont()
+
+
+ def Refresh(self, erase=True, rect=None):
+ """
+ Causes this window, and all of its children recursively (except under wxGTK1
+ where this is not implemented), to be repainted.
+
+ :param `erase`: If ``True``, the background will be erased;
+ :param `rect`: If not ``None``, only the given rectangle will be treated as damaged.
+
+ :note: Note that repainting doesn't happen immediately but only during the next
+ event loop iteration, if you need to update the window immediately you should
+ use `Update` instead.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ self._main_win.Refresh(erase, rect)
+ self._header_win.Refresh(erase, rect)
+
+
+ def SetFocus(self):
+ """ This sets the window to receive keyboard input. """
+
+ self._main_win.SetFocus()
+
+
+ def GetHeaderWindow(self):
+ """ Returns the header window, an instance of :class:`TreeListHeaderWindow`. """
+
+ return self._header_win
+
+
+ def GetMainWindow(self):
+ """ Returns the main window, an instance of :class:`TreeListMainWindow`. """
+
+ return self._main_win
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ # something is better than nothing...
+ return wx.Size(200, 200) # but it should be specified values! FIXME
+
+
+ def OnGetItemText(self, item, column):
+ """
+ This function **must** be overloaded in the derived class for a control
+ with ``TR_VIRTUAL`` style. It should return the string containing the
+ text of the given column for the specified item.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `column`: an integer specifying the column index.
+ """
+
+ return ""
+
+
+ def SortChildren(self, item):
+ """
+ Sorts the children of the given item using :meth:`~HyperTreeList.OnCompareItems` method of :class:`HyperTreeList`.
+ You should override that method to change the sort order (the default is ascending
+ case-sensitive alphabetical order).
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ """
+
+ if not self._attr_set:
+ setattr(self._main_win, "OnCompareItems", self.OnCompareItems)
+ self._attr_set = True
+
+ self._main_win.SortChildren(item)
+
+
+ def OnCompareItems(self, item1, item2):
+ """
+ Returns whether 2 items have the same text.
+
+ Override this function in the derived class to change the sort order of the items
+ in the :class:`HyperTreeList`. The function should return a negative, zero or positive
+ value if the first item is less than, equal to or greater than the second one.
+
+ :param `item1`: an instance of :class:`TreeListItem`;
+ :param `item2`: another instance of :class:`TreeListItem`.
+
+ :note: The base class version compares items alphabetically.
+ """
+
+ # do the comparison here, and not delegate to self._main_win, in order
+ # to let the user override it
+
+ return self.GetItemText(item1) == self.GetItemText(item2)
+
+
+ def CreateEditCtrl(self, item, column):
+ """
+ Create an edit control for editing a label of an item. By default, this
+ returns a text control.
+
+ Override this function in the derived class to return a different type
+ of control.
+
+ :param `item`: an instance of :class:`TreeListItem`;
+ :param `column`: an integer specifying the column index.
+ """
+
+ return EditTextCtrl(self.GetMainWindow(), -1, item, column,
+ self.GetMainWindow(), item.GetText(column),
+ style=self.GetTextCtrlStyle(column))
+
+
+ def GetTextCtrlStyle(self, column):
+ """
+ Return the style to use for the text control that is used to edit
+ labels of items.
+
+ Override this function in the derived class to support a different
+ style, e.g. ``wx.TE_MULTILINE``.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self.GetTextCtrlAlignmentStyle(column) | wx.TE_PROCESS_ENTER
+
+
+ def GetTextCtrlAlignmentStyle(self, column):
+ """
+ Return the alignment style to use for the text control that is used
+ to edit labels of items. The alignment style is derived from the
+ column alignment.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ header_win = self.GetHeaderWindow()
+ alignment = header_win.GetColumnAlignment(column)
+ return {wx.ALIGN_LEFT: wx.TE_LEFT,
+ wx.ALIGN_RIGHT: wx.TE_RIGHT,
+ wx.ALIGN_CENTER: wx.TE_CENTER}[alignment]
+
+
+ def GetClassDefaultAttributes(self):
+ """
+ Returns the default font and colours which are used by the control. This is
+ useful if you want to use the same font or colour in your own control as in
+ a standard control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the users system,
+ especially if it uses themes.
+
+ This static method is "overridden'' in many derived classes and so calling,
+ for example, :meth:`Button.GetClassDefaultAttributes` () will typically return the
+ values appropriate for a button which will be normally different from those
+ returned by, say, :meth:`ListCtrl.GetClassDefaultAttributes` ().
+
+ :note: The :class:`VisualAttributes` structure has at least the fields `font`,
+ `colFg` and `colBg`. All of them may be invalid if it was not possible to
+ determine the default control appearance or, especially for the background
+ colour, if the field doesn't make sense as is the case for `colBg` for the
+ controls with themed background.
+ """
+
+ attr = wx.VisualAttributes()
+ attr.colFg = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ attr.colBg = wx.SystemSettings_GetColour(wx.SYS_COLOUR_LISTBOX)
+ attr.font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ return attr
+
+ GetClassDefaultAttributes = classmethod(GetClassDefaultAttributes)
+
+
+def create_delegator_for(method):
+ """
+ Creates a method that forwards calls to `self._main_win` (an instance of :class:`TreeListMainWindow`).
+
+ :param `method`: one method inside the :class:`TreeListMainWindow` local scope.
+ """
+
+ def delegate(self, *args, **kwargs):
+ return getattr(self._main_win, method)(*args, **kwargs)
+ return delegate
+
+# Create methods that delegate to self._main_win. This approach allows for
+# overriding these methods in possible subclasses of HyperTreeList
+for method in _methods:
+ setattr(HyperTreeList, method, create_delegator_for(method))
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/infobar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/infobar.py
new file mode 100644
index 0000000..6987bab
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/infobar.py
@@ -0,0 +1,831 @@
+# --------------------------------------------------------------------------- #
+# INFOBAR Control wxPython IMPLEMENTATION
+# Inspired By And Heavily Based On wxInfoBar.
+#
+# Python Code By:
+#
+# Andrea Gavana, @ 12 March 2012
+# Latest Revision: 28 Sep 2012, 21.00 GMT
+#
+#
+# TODO List/Caveats
+#
+# 1. ?
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+An info bar is a transient window shown at top or bottom of its parent window to display
+non-critical information to the user.
+
+Description
+===========
+
+An info bar is a transient window shown at top or bottom of its parent window to display
+non-critical information to the user.
+
+:note:
+
+ The Python implementation of :class:`InfoBar` is a direct translation of the generic C++
+ implementation of :class:`InfoBar`.
+
+
+This class provides another way to show messages to the user, intermediate between message
+boxes and status bar messages. The message boxes are modal and thus interrupt the users work
+flow and should be used sparingly for this reason. However status bar messages are often
+too easy not to notice at all. An info bar provides a way to present the messages which has
+a much higher chance to be noticed by the user but without being annoying.
+
+Info bar may show an icon (on the left), text message and, optionally, buttons allowing the
+user to react to the information presented. It always has a close button at the right allowing
+the user to dismiss it so it isn't necessary to provide a button just to close it.
+
+:class:`InfoBar` calls its parent `Layout()` method (if its parent is **not** managed by :class:`framemanager`
+or :class:`~lib.agw.aui.AuiManager`) and assumes that it will change the parent layout appropriately depending
+on whether the info bar itself is shown or hidden. Usually this is achieved by simply using a
+sizer for the parent window layout and adding wxInfoBar to this sizer as one of the items.
+Considering the usual placement of the info bars, normally this sizer should be a vertical
+:class:`BoxSizer` and the bar its first or last element.
+
+
+Base Functionalities
+====================
+
+:class:`InfoBar` supports all the :class:`InfoBar` generic implementation functionalities, and in addition
+it using meth:~InfoBar.AddButton` it is possible to add a button with a bitmap (and not only a plain :class:`Button`).
+
+For example::
+
+ info = InfoBar(parent)
+ bitmap = wx.Bitmap('nice_bitmap.png', wx.BITMAP_TYPE_PNG)
+
+ info.AddButton(wx.NewId(), 'New Button', bitmap)
+
+
+
+Usage
+=====
+
+The simplest possible example of using this class would be::
+
+ import wx
+ import wx.lib.agw.infobar as IB
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, 'InfoBar Demo')
+
+ self._infoBar = IB.InfoBar(self)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.AddF(self._infoBar, wx.SizerFlags().Expand())
+
+ panel = wx.Panel(self)
+ sizer.Add(panel, 1, wx.EXPAND)
+
+ # ... Add other frame controls to the sizer ...
+ self.SetSizer(sizer)
+
+ wx.CallLater(2000, self.SomeMethod)
+
+
+ def SomeMethod(self):
+
+ self._infoBar.ShowMessage("Something happened", wx.ICON_INFORMATION)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`InfoBar` has been tested on the following platforms:
+ * Windows (Vista/7).
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================= ==================================================
+Event Name Description
+================= ==================================================
+``wx.EVT_BUTTON`` Process a `wx.wxEVT_COMMAND_BUTTON_CLICKED` event, when the button is clicked.
+================= ==================================================
+
+
+License And Version
+===================
+
+:class:`InfoBar` control is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 28 Sep 2012, 21.00 GMT
+
+Version 0.2
+
+"""
+
+# Version Info
+__version__ = "0.2"
+
+# Start the imports
+import wx
+
+# These two are needed only to check if the InfoBar parent
+# is managed by PyAUI or wx.aui, in which case the handling
+# of the showing/dismissing is done a bit differently
+import wx.aui
+import aui.framemanager as framemanager
+
+# These are for the AutoWrapStaticText class
+from wx.lib.wordwrap import wordwrap
+from wx.lib.stattext import GenStaticText as StaticText
+
+# Get the translation function
+_ = wx.GetTranslation
+
+
+# Determine the placement of the bar from its position in the containing
+# sizer
+BarPlacement_Unknown = 0
+""" Unknown :class:`InfoBar` placement (not good). """
+BarPlacement_Top = 1
+""" :class:`InfoBar` is placed at the top of its parent. """
+BarPlacement_Bottom = 2
+""" :class:`InfoBar` is placed at the bottom of its parent. """
+
+# This dictionary is here because wx.ArtProvider.GetMessageBoxIconId(flags)
+# doesn't do what I think it should do in wxPython
+FLAGS2ART = {wx.ICON_NONE : wx.ART_MISSING_IMAGE,
+ wx.ICON_INFORMATION : wx.ART_INFORMATION,
+ wx.ICON_QUESTION : wx.ART_QUESTION,
+ wx.ICON_WARNING : wx.ART_WARNING,
+ wx.ICON_ERROR : wx.ART_ERROR
+ }
+
+
+# ----------------------------------------------------------------------------
+# Local helpers
+# ----------------------------------------------------------------------------
+
+def GetCloseButtonBitmap(win, size, colBg, flags=0):
+ """
+ For platforms supporting it (namely wxMSW and wxMAC), this method uses :class:`RendererNative`
+ to draw a natively-looking close button on the :class:`InfoBar` itself.
+
+ :param `win`: the window in which we wish to draw the close button (an instance of
+ :class:`InfoBar`);
+ :param tuple `size`: the close button size, a tuple of `(width, height)` dimensions in pixels;
+ :param `colBg`: the background colour of the parent window, an instance of :class:`Colour`;
+ :param integer `flags`: may have the ``wx.CONTROL_PRESSED``, ``wx.CONTROL_CURRENT`` or
+ ``wx.CONTROL_ISDEFAULT`` bit set.
+ """
+
+ bmp = wx.EmptyBitmap(*size)
+ dc = wx.MemoryDC()
+ dc.SelectObject(bmp)
+ dc.SetBackground(wx.Brush(colBg))
+ dc.Clear()
+
+ wx.RendererNative.Get().DrawTitleBarBitmap(win, dc, wx.RectS(size), wx.TITLEBAR_BUTTON_CLOSE, flags)
+ dc.SelectObject(wx.NullBitmap)
+
+ return bmp
+
+
+# ----------------------------------------------------------------------------
+# Auto-wrapping static text class
+# ----------------------------------------------------------------------------
+
+class AutoWrapStaticText(StaticText):
+ """
+ A simple class derived from :mod:`lib.stattext` that implements auto-wrapping
+ behaviour depending on the parent size.
+
+ .. versionadded:: 0.9.5
+ """
+
+ def __init__(self, parent, label):
+ """
+ Defsult class constructor.
+
+ :param Window parent: a subclass of :class:`Window`, must not be ``None``;
+ :param string `label`: the :class:`AutoWrapStaticText` text label.
+ """
+
+ StaticText.__init__(self, parent, -1, label, style=wx.ST_NO_AUTORESIZE)
+
+ self.label = label
+
+ colBg = wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK)
+ self.SetBackgroundColour(colBg)
+ self.SetOwnForegroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOTEXT))
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`AutoWrapStaticText`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ event.Skip()
+ self.Wrap(event.GetSize().width)
+
+
+ def Wrap(self, width):
+ """
+ This functions wraps the controls label so that each of its lines becomes at
+ most `width` pixels wide if possible (the lines are broken at words boundaries
+ so it might not be the case if words are too long).
+
+ If `width` is negative, no wrapping is done.
+
+ :param integer `width`: the maximum available width for the text, in pixels.
+
+ :note: Note that this `width` is not necessarily the total width of the control,
+ since a few pixels for the border (depending on the controls border style) may be added.
+ """
+
+ if width < 0:
+ return
+
+ self.Freeze()
+
+ dc = wx.ClientDC(self)
+ dc.SetFont(self.GetFont())
+ text = wordwrap(self.label, width, dc)
+ self.SetLabel(text, wrapped=True)
+
+ self.Thaw()
+
+
+ def SetLabel(self, label, wrapped=False):
+ """
+ Sets the :class:`AutoWrapStaticText` label.
+
+ All "&" characters in the label are special and indicate that the following character is
+ a mnemonic for this control and can be used to activate it from the keyboard (typically
+ by using ``Alt`` key in combination with it). To insert a literal ampersand character, you
+ need to double it, i.e. use "&&". If this behaviour is undesirable, use `SetLabelText` instead.
+
+ :param string `label`: the new :class:`AutoWrapStaticText` text label;
+ :param bool `wrapped`: ``True`` if this method was called by the developer using :meth:`~AutoWrapStaticText.SetLabel`,
+ ``False`` if it comes from the :meth:`~AutoWrapStaticText.OnSize` event handler.
+
+ :note: Reimplemented from :class:`PyControl`.
+ """
+
+ if not wrapped:
+ self.label = label
+
+ StaticText.SetLabel(self, label)
+
+
+# ============================================================================
+# Implementation
+# ============================================================================
+
+class InfoBar(wx.PyControl):
+ """
+ An info bar is a transient window shown at top or bottom of its parent window to display
+ non-critical information to the user.
+
+ This is the main class implementation, plainly translated from C++.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, name='InfoBar'):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param integer `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :type `pos`: tuple or :class:`Point`
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :type `size`: tuple or :class:`Size`
+ :param integer `style`: the :class:`InfoBar` style (unused at present);
+ :param string `name`: the control name.
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style|wx.BORDER_NONE, name=name)
+
+ self.SetInitialSize(size)
+ self.Init()
+
+ # calling Hide() before Create() ensures that we're created initially
+ # hidden
+ self.Hide()
+
+ # use special, easy to notice, colours
+ colBg = wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK)
+ self.SetBackgroundColour(colBg)
+ self.SetOwnForegroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOTEXT))
+
+ # create the controls: icon,text and the button to dismiss the
+ # message.
+
+ # the icon is not shown unless it's assigned a valid bitmap
+ self._icon = wx.StaticBitmap(self, wx.ID_ANY, wx.NullBitmap)
+ self._text = AutoWrapStaticText(self, "")
+
+ if wx.Platform == '__WXGTK__':
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_CLOSE, wx.ART_BUTTON)
+ else:
+ # THIS CRASHES PYTHON ALTOGETHER!!
+ # sizeBmp = wx.ArtProvider.GetSizeHint(wx.ART_BUTTON)
+ sizeBmp = (16, 16)
+ bmp = GetCloseButtonBitmap(self, sizeBmp, colBg)
+
+ self._button = wx.BitmapButton(self, wx.ID_ANY, bmp, style=wx.BORDER_NONE)
+
+ if wx.Platform != '__WXGTK__':
+ self._button.SetBitmapPressed(GetCloseButtonBitmap(self, sizeBmp, colBg, wx.CONTROL_PRESSED))
+ self._button.SetBitmapCurrent(GetCloseButtonBitmap(self, sizeBmp, colBg, wx.CONTROL_CURRENT))
+
+ self._button.SetBackgroundColour(colBg)
+ self._button.SetToolTipString(_("Hide this notification message."))
+
+ # center the text inside the sizer with an icon to the left of it and a
+ # button at the very right
+ #
+ # NB: AddButton() relies on the button being the last control in the sizer
+ # and being preceded by a spacer
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.AddF(self._icon, wx.SizerFlags().Centre().Border())
+ sizer.Add(self._text, 2000, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddStretchSpacer()
+ sizer.AddF(self._button, wx.SizerFlags().Centre().Border())
+ self.SetSizer(sizer)
+
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+
+
+ def Init(self):
+ """ Common initialization code. """
+
+ self._icon = None
+ self._text = None
+ self._button = None
+ self._showEffect = wx.SHOW_EFFECT_MAX
+ self._hideEffect = wx.SHOW_EFFECT_MAX
+
+ # use default effect duration
+ self._effectDuration = 0
+
+
+ def SetFont(self, font):
+ """
+ Overridden base class methods changes the font of the text message.
+
+ :class:`InfoBar` overrides this method to use the font passed to it for its text
+ message part. By default a larger and bold version of the standard font is used.
+
+ :param `font`: a valid instance of :class:`Font`.
+
+ :note: Reimplemented from :class:`Window`.
+ """
+
+ if not wx.PyControl.SetFont(self, font):
+ return False
+
+ # check that we're not called before Create()
+ if self._text:
+ self._text.SetFont(font)
+
+ return True
+
+
+ def GetBarPlacement(self):
+ """
+ Determines the placement of the bar from its position in the containing
+ sizer.
+
+ :return: One of these integer bits:
+
+ ========================== =========== ==================================================
+ Placement Flag Hex Value Description
+ ========================== =========== ==================================================
+ ``BarPlacement_Unknown`` 0x0 Unknown placement of :class:`InfoBar` (not good).
+ ``BarPlacement_Top`` 0x1 :class:`InfoBar` is placed at the top of its parent.
+ ``BarPlacement_Bottom`` 0x2 :class:`InfoBar` is placed at the bottom of its parent.
+ ========================== =========== ==================================================
+
+ """
+
+ sizer = self.GetContainingSizer()
+
+ if not sizer:
+ return BarPlacement_Unknown
+
+ siblings = sizer.GetChildren()
+ lSib = len(siblings) - 1
+
+ if siblings[0].GetWindow() == self:
+ return BarPlacement_Top
+ elif siblings[lSib].GetWindow()== self:
+ return BarPlacement_Bottom
+ else:
+ return BarPlacement_Unknown
+
+
+ def GetShowEffect(self):
+ """
+ Return the effect currently used for showing the bar.
+
+ :return: One of the following integer bits:
+
+ ================================== =========== ==================================================
+ `ShowEffect` Flag Hex Value Description
+ ================================== =========== ==================================================
+ ``wx.SHOW_EFFECT_NONE`` 0x0 No effect, equivalent to normal `Show()` or `Hide()` call.
+ ``wx.SHOW_EFFECT_SLIDE_TO_TOP`` 0x7 Slide the :class:`InfoBar` window to the top.
+ ``wx.SHOW_EFFECT_SLIDE_TO_BOTTOM`` 0x8 Slide the :class:`InfoBar` window to the bottom.
+ ================================== =========== ==================================================
+
+ """
+
+ if self._showEffect != wx.SHOW_EFFECT_MAX:
+ return self._showEffect
+
+ placement = self.GetBarPlacement()
+
+ if placement == BarPlacement_Top:
+ return wx.SHOW_EFFECT_SLIDE_TO_BOTTOM
+
+ elif placement == BarPlacement_Bottom:
+ return wx.SHOW_EFFECT_SLIDE_TO_TOP
+
+ elif placement == BarPlacement_Unknown:
+ return wx.SHOW_EFFECT_NONE
+
+ else:
+ raise Exception("unknown info bar placement")
+
+
+ def GetHideEffect(self):
+ """
+ Return the effect currently used for hiding the bar.
+
+ :return: One of the following integer bits:
+
+ ================================== =========== ==================================================
+ `ShowEffect` Flag Hex Value Description
+ ================================== =========== ==================================================
+ ``wx.SHOW_EFFECT_NONE`` 0x0 No effect, equivalent to normal `Show()` or `Hide()` call.
+ ``wx.SHOW_EFFECT_SLIDE_TO_TOP`` 0x7 Slide the :class:`InfoBar` window to the top.
+ ``wx.SHOW_EFFECT_SLIDE_TO_BOTTOM`` 0x8 Slide the :class:`InfoBar` window to the bottom.
+ ================================== =========== ==================================================
+
+ """
+
+ if self._hideEffect != wx.SHOW_EFFECT_MAX:
+ return self._hideEffect
+
+ placement = self.GetBarPlacement()
+
+ if placement == BarPlacement_Top:
+ return wx.SHOW_EFFECT_SLIDE_TO_TOP
+
+ elif placement == BarPlacement_Bottom:
+ return wx.SHOW_EFFECT_SLIDE_TO_BOTTOM
+
+ elif placement == BarPlacement_Unknown:
+ return wx.SHOW_EFFECT_NONE
+
+ else:
+ raise Exception("unknown info bar placement")
+
+
+ def GetDefaultBorder(self):
+ """ Returns the default border style for :class:`InfoBar`. """
+
+ return wx.BORDER_NONE
+
+
+ def UpdateParent(self):
+ """
+ Updates the parent layout appearance, but only if this :class:`InfoBar` parent is **not** managed
+ by :class:`framemanager` or :class:`~lib.agw.aui.AuiManager`.
+ """
+
+ parent = self.GetParent()
+ parent.Layout()
+ parent.Refresh()
+
+
+ def DoHide(self):
+ """ Hides this :class:`InfoBar` with whatever hiding effect has been chosen. """
+
+ self.HideWithEffect(self.GetHideEffect(), self.GetEffectDuration())
+
+ handler = self.GetParent().GetEventHandler()
+ managers = (framemanager.AuiManager, wx.aui.AuiManager)
+
+ if not isinstance(handler, managers):
+ self.UpdateParent()
+ else:
+ pane = handler.GetPane(self)
+ pane.Show(False)
+ handler.Update()
+
+
+ def DoShow(self):
+ """ Shows this :class:`InfoBar` with whatever showing effect has been chosen. """
+
+ # re-layout the parent first so that the window expands into an already
+ # unoccupied by the other controls area: for this we need to change our
+ # internal visibility flag to force Layout() to take us into account(an
+ # alternative solution to this hack would be to temporarily set
+ # wx.RESERVE_SPACE_EVEN_IF_HIDDEN flag but it's not really better)
+
+ # just change the internal flag indicating that the window is visible,
+ # without really showing it
+ self.GetParent().Freeze()
+
+ wx.PyControl.Show(self)
+
+ # adjust the parent layout to account for us
+ self.UpdateParent()
+
+ # reset the flag back before really showing the window or it wouldn't be
+ # shown at all because it would believe itself already visible
+ wx.PyControl.Show(self, False)
+ self.GetParent().Thaw()
+
+ # finally do really show the window.
+ self.ShowWithEffect(self.GetShowEffect(), self.GetEffectDuration())
+
+ handler = self.GetParent().GetEventHandler()
+ managers = (framemanager.AuiManager, wx.aui.AuiManager)
+
+ if isinstance(handler, managers):
+ pane = handler.GetPane(self)
+ pane.Show(True)
+ handler.Update()
+
+
+ def ShowMessage(self, msg, flags=wx.ICON_INFORMATION):
+ """
+ Show a message in the bar.
+
+ If the bar is currently hidden, it will be shown. Otherwise its message will be updated in place.
+
+ :param string `msg`: the text of the message;
+ :param integer `flags`: one of ``wx.ICON_NONE``, ``wx.ICON_INFORMATION`` (default), ``wx.ICON_QUESTION``,
+ ``wx.ICON_WARNING`` or ``wx.ICON_ERROR`` values.
+
+ :note: These flags have the same meaning as in :class:`MessageDialog` for the generic version, i.e.
+ show (or not, in case of ``wx.ICON_NONE``) the corresponding icon in the bar but can be interpreted
+ by the native versions. For example, the GTK+ native implementation doesn't show icons at all but
+ uses this parameter to select the appropriate background colour for the notification.
+ """
+
+ # first update the controls
+ icon = flags & wx.ICON_MASK
+ iconSize = 0
+
+ if not icon or icon == wx.ICON_NONE:
+ self._icon.Hide()
+
+ else: # do show an icon
+ bitmap = wx.ArtProvider.GetBitmap(FLAGS2ART[flags], wx.ART_BUTTON)
+ iconSize = bitmap.GetWidth() + wx.SizerFlags().Border().GetBorderInPixels()
+ self._icon.SetBitmap(bitmap)
+ self._icon.Show()
+
+ # notice the use of EscapeMnemonics() to ensure that "&" come through
+ # correctly
+ self._text.SetLabel(wx.PyControl.EscapeMnemonics(msg))
+
+ parentSize = self.GetParent().GetSize()
+ self._text.Wrap(parentSize.x - iconSize - wx.SizerFlags().Border().GetBorderInPixels())
+
+ # then show this entire window if not done yet
+ if not self.IsShown():
+ self.DoShow()
+
+ self.Layout()
+
+
+ def Dismiss(self):
+ """
+ Hides the :class:`InfoBar` window.
+
+ This method hides the window and lays out the parent window to account for
+ its disappearance (unlike a simple `Hide()`), but only if this :class:`InfoBar`
+ parent is **not** managed by :class:`framemanager` or :class:`~lib.agw.aui.AuiManager`.
+ """
+
+ self.DoHide()
+
+
+ def AddButton(self, btnid, label, bitmap=wx.NullBitmap):
+ """
+ Adds a button to be shown in the info bar.
+
+ The button added by this method will be shown to the right of the text (in LTR layout),
+ with each successive button being added to the right of the previous one. If any buttons
+ are added to the info bar using this method, the default `Close` button is not shown
+ as it is assumed that the extra buttons already allow the user to close it.
+
+ Clicking the button will generate a normal ``wx.wxEVT_COMMAND_BUTTON_CLICKED`` event which
+ can be handled as usual. The default handler in :class:`InfoBar` itself closes the window
+ whenever a button in it is clicked so if you wish the info bar to be hidden when the button
+ is clicked, simply call `event.Skip()` in the button handler to let the base class handler
+ do it (calling :meth:`~InfoBar.Dismiss` explicitly works too, of course). On the other hand, if you don't
+ skip the event, the info bar will remain opened so make sure to do it for at least some
+ buttons to allow the user to close it.
+
+ :param integer `btnid`: id of the button. It will be used in the button message clicking
+ this button will generate;
+ :param string `label`: the label of the button. It may only be empty if `btnid` is one of
+ the stock ids in which case the corresponding stock label will be used;
+ :param `bitmap`: if not equal to :class:`NullBitmap`, a valid :class:`Bitmap` image to show beside
+ the button text.
+
+ :note:
+
+ Notice that the generic :class:`InfoBar` implementation handles the button events itself
+ and so they are not propagated to the info bar parent and you need to either inherit from
+ :class:`InfoBar` and handle them in your derived class or use `self.Bind(...)` to handle the
+ button events in the parent frame.
+
+ """
+
+ sizer = self.GetSizer()
+
+ if not sizer:
+ raise Exception("must be created first")
+
+ # user-added buttons replace the standard close button so remove it if we
+ # hadn't done it yet
+ if sizer.Detach(self._button):
+ self._button.Hide()
+
+ button = wx.Button(self, btnid, label)
+
+ if bitmap.IsOk():
+ # Add the bitmap to the button
+ button.SetBitmap(bitmap, wx.LEFT)
+ button.SetBitmapMargins((2, 2)) # default is 4 but that seems too big to me.
+
+ if wx.Platform == '__WXMAC__':
+ # smaller buttons look better in the(narrow)info bar under OS X
+ button.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+
+ sizer.AddF(button, wx.SizerFlags().Centre().DoubleBorder())
+
+ if self.IsShown():
+ self.UpdateParent()
+
+
+ def RemoveButton(self, btnid):
+ """
+ Remove a button previously added by :meth:`~InfoBar.AddButton`.
+
+ :param integer `btnid`: id of the button to remove. If more than one button with the
+ same id is used in the :class:`InfoBar` (which is in any case not recommended), the last,
+ i.e. most recently added, button with this `id` is removed.
+ """
+
+ sizer = self.GetSizer()
+
+ if not sizer:
+ raise Exception("must be created first")
+
+ # iterate over the sizer items in reverse order to find the last added
+ # button with this id(ids of all buttons should be unique anyhow but if
+ # they are repeated removing the last added one probably makes more sense)
+ items = sizer.GetChildren()
+
+ for item in items[::-1]:
+ # if we reached the spacer separating the buttons from the text
+ # preceding them without finding our button,it must mean it's not
+ # there at all
+ if item.IsSpacer():
+ raise Exception("button with id %d not found"%btnid)
+
+ # check if we found our button
+ if item.GetWindow().GetId() == btnid:
+ sizer.Detach(item)
+ item.GetWindow().Destroy()
+ break
+
+ # check if there are any custom buttons left
+ if sizer.GetChildren()[-1].IsSpacer():
+ # if the last item is the spacer,none are left so restore the
+ # standard close button
+ sizer.Add(self._button, wx.SizerFlags().Centre().DoubleBorder())
+ self._button.Show()
+
+
+ def OnButton(self, event):
+ """
+ Default event handler for the `Close` button in :class:`InfoBar`.
+
+ :param `event`: a :class:`CommandEvent` to be processed.
+
+ :note:
+
+ Notice that the generic :class:`InfoBar` implementation handles the button events itself
+ and so they are not propagated to the info bar parent and you need to either inherit from
+ :class:`InfoBar` and handle them in your derived class or use `self.Bind(...)` to handle the
+ button events in the parent frame.
+ """
+
+ self.DoHide()
+
+
+ def SetShowHideEffects(self, showEffect, hideEffect):
+ """
+ Set the effects to use when showing and hiding the bar.
+
+ Either or both of the parameters can be set to ``wx.SHOW_EFFECT_NONE`` to disable using
+ effects entirely.
+
+ By default, the info bar uses ``wx.SHOW_EFFECT_SLIDE_TO_BOTTOM`` effect for showing itself
+ and ``wx.SHOW_EFFECT_SLIDE_TO_TOP`` for hiding if it is the first element of the containing
+ sizer and reverse effects if it's the last one. If it is neither the first nor the last element,
+ no effect is used to avoid the use of an inappropriate one and this function must be called
+ if an effect is desired.
+
+ :param integer `showEffect`: the effect to use when showing the bar;
+ :param integer `hideEffect`: the effect to use when hiding the bar.
+
+ The `showEffect` and `hideEffect` parameters can take one of the following bit:
+
+ ==================================== ===========================================================
+ `ShowEffect` Flag Description
+ ==================================== ===========================================================
+ ``SHOW_EFFECT_NONE`` No effect, equivalent to normal `Show()` or `Hide()` call.
+ ``SHOW_EFFECT_ROLL_TO_LEFT`` Roll window to the left.
+ ``SHOW_EFFECT_ROLL_TO_RIGHT`` Roll window to the right.
+ ``SHOW_EFFECT_ROLL_TO_TOP`` Roll window to the top.
+ ``SHOW_EFFECT_ROLL_TO_BOTTOM`` Roll window to the bottom.
+ ``SHOW_EFFECT_SLIDE_TO_LEFT`` Slide window to the left.
+ ``SHOW_EFFECT_SLIDE_TO_RIGHT`` Slide window to the right.
+ ``SHOW_EFFECT_SLIDE_TO_TOP`` Slide window to the top.
+ ``SHOW_EFFECT_SLIDE_TO_BOTTOM`` Slide window to the bottom.
+ ``SHOW_EFFECT_BLEND`` Fade in or out effect.
+ ``SHOW_EFFECT_EXPAND`` Expanding or collapsing effect.
+ ==================================== ===========================================================
+
+ """
+
+ self._showEffect = showEffect
+ self._hideEffect = hideEffect
+
+
+ def SetEffectDuration(self, duration):
+ """
+ Sets the duration of the animation used when showing or hiding the bar.
+
+ By default, 500ms duration is used.
+
+ :param integer `duration`: duration of the animation, in milliseconds.
+ """
+
+ self._effectDuration = duration
+
+
+ def GetEffectDuration(self):
+ """ Return the effect animation duration currently used, in milliseconds. """
+
+ return self._effectDuration
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/knobctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/knobctrl.py
new file mode 100644
index 0000000..c973464
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/knobctrl.py
@@ -0,0 +1,902 @@
+# --------------------------------------------------------------------------------- #
+# KNOBCTRL wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 03 Nov 2006
+# Latest Revision: 17 Aug 2011, 15.00 GMT
+#
+#
+# TODO List
+#
+# 1. Any idea?
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@maerskoil.com
+# andrea.gavana@gmail.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`KnobCtrl` lets the user select a numerical value by rotating it.
+
+
+Description
+===========
+
+:class:`KnobCtrl` lets the user select a numerical value by rotating it. It works like a
+scrollbar: just set the ticks range property and read the value property in the
+associated ``EVT_KC_ANGLE_CHANGING``/``EVT_KC_ANGLE_CHANGED`` events. Simple but
+effective.
+
+It can be easily used if you want to simulate the volume knob of a music player
+or similar functionalities.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.knobctrl as KC
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "KnobCtrl Demo")
+
+ panel = wx.Panel(self)
+
+ knob1 = KC.KnobCtrl(panel, -1, size=(100, 100))
+ knob2 = KC.KnobCtrl(panel, -1, size=(100, 100))
+
+ knob1.SetTags(range(0, 151, 10))
+ knob1.SetAngularRange(-45, 225)
+ knob1.SetValue(45)
+
+ knob2.SetTags(range(0, 151, 10))
+ knob2.SetAngularRange(0, 270)
+ knob2.SetValue(100)
+
+ main_sizer = wx.BoxSizer(wx.VERTICAL)
+ main_sizer.Add(knob1, 0, wx.EXPAND|wx.ALL, 20)
+ main_sizer.Add(knob2, 0, wx.EXPAND|wx.ALL, 20)
+
+ panel.SetSizer(main_sizer)
+ main_sizer.Layout()
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Events
+======
+
+:class:`KnobCtrl` implements two events that can be intercepted by the user:
+
+- ``EVT_KC_ANGLE_CHANGING``;
+- ``EVT_KC_ANGLE_CHANGED``.
+
+The first one can be "vetoed" by eliminating the `event.Skip()` at the end of the
+event handler.
+
+
+Supported Platforms
+===================
+
+:class:`KnobCtrl` has been tested on the following platforms:
+ * Windows (Windows XP);
+ * Linux Ubuntu (Dapper 6.06)
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+================== =========== ==================================================
+Window Styles Hex Value Description
+================== =========== ==================================================
+``KC_BUFFERED_DC`` 0x1 Flag to use double buffering (recommendeded = 1).
+================== =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+========================= ==================================================
+Event Name Description
+========================= ==================================================
+``EVT_KC_ANGLE_CHANGED`` Notify the client that the knob has changed its value.
+``EVT_KC_ANGLE_CHANGING`` Notify the client that the knob is changing its value.
+========================= ==================================================
+
+
+License And Version
+===================
+
+:class:`KnobCtrl` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 17 Aug 2011, 15.00 GMT
+
+Version 0.3
+
+"""
+
+__docformat__ = "epytext"
+
+
+import wx
+import math
+
+# Flag to use double buffering (recommendeded = 1)
+KC_BUFFERED_DC = 1
+"""Flag to use double buffering (recommendeded = 1)"""
+
+# Events
+wxEVT_KC_ANGLE_CHANGING = wx.NewEventType()
+wxEVT_KC_ANGLE_CHANGED = wx.NewEventType()
+
+EVT_KC_ANGLE_CHANGING = wx.PyEventBinder(wxEVT_KC_ANGLE_CHANGING, 1)
+""" Notify the client that the knob is changing its value."""
+EVT_KC_ANGLE_CHANGED = wx.PyEventBinder(wxEVT_KC_ANGLE_CHANGED, 1)
+""" Notify the client that the knob has changed its value."""
+
+# ---------------------------------------------------------------------------- #
+# Class KnobCtrlEvent
+# ---------------------------------------------------------------------------- #
+
+class KnobCtrlEvent(wx.PyCommandEvent):
+ """
+ Represent details of the events that the :class:`KnobCtrl` object sends.
+ """
+
+ def __init__(self, eventType, eventId=1):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `eventType`: the event type;
+ :param `eventId`: the event identifier.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+
+
+ def SetOldValue(self, oldValue):
+ """
+ Sets the old :class:`KnobCtrl` value for this event.
+
+ :param `oldValue`: an integer representing the old value.
+ """
+
+ self._oldValue = oldValue
+
+
+ def GetOldValue(self):
+ """ Returns the old :class:`KnobCtrl` value for this event. """
+
+ return self._oldValue
+
+
+ def SetValue(self, value):
+ """
+ Sets the new :class:`KnobCtrl` value for this event.
+
+ :param `value`: an integer representing the new value.
+ """
+
+ self._value = value
+
+
+ def GetValue(self):
+ """ Returns the new :class:`KnobCtrl` value for this event. """
+
+ return self._value
+
+
+#----------------------------------------------------------------------
+# BUFFERENDWINDOW Class
+# This Class Has Been Taken From The wxPython Wiki, And Slightly
+# Adapted To Fill My Needs. See:
+#
+# http://wiki.wxpython.org/index.cgi/DoubleBufferedDrawing
+#
+# For More Info About DC And Double Buffered Drawing.
+#----------------------------------------------------------------------
+
+class BufferedWindow(wx.Window):
+ """
+ A Buffered window class.
+
+ To use it, subclass it and define a `Draw(dc)` method that takes a `dc`
+ to draw to. In that method, put the code needed to draw the picture
+ you want. The window will automatically be double buffered, and the
+ screen will be automatically updated when a Paint event is received.
+
+ When the drawing needs to change, you app needs to call the
+ :meth:`BufferedWindow.UpdateDrawing() <BufferedWindow.UpdateDrawing>` method. Since the drawing is stored in a bitmap, you
+ can also save the drawing to file by calling the
+ `SaveToFile(self, file_name, file_type)` method.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.NO_FULL_REPAINT_ON_RESIZE, agwStyle=KC_BUFFERED_DC):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `agwStyle`: if set to ``KC_BUFFERED_DC``, double-buffering will
+ be used.
+ """
+
+ wx.Window.__init__(self, parent, id, pos, size, style)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
+
+ # OnSize called to make sure the buffer is initialized.
+ # This might result in OnSize getting called twice on some
+ # platforms at initialization, but little harm done.
+ self.OnSize(None)
+
+
+ def Draw(self, dc):
+ """
+ This method should be overridden when sub-classed.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`BufferedWindow`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ # All that is needed here is to draw the buffer to screen
+ if self._agwStyle == KC_BUFFERED_DC:
+ dc = wx.BufferedPaintDC(self, self._Buffer)
+ else:
+ dc = wx.PaintDC(self)
+ dc.DrawBitmap(self._Buffer,0,0)
+
+
+ def OnSize(self,event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`BufferedWindow`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ # The Buffer init is done here, to make sure the buffer is always
+ # the same size as the Window
+ self.Width, self.Height = self.GetClientSizeTuple()
+
+ # Make new off screen bitmap: this bitmap will always have the
+ # current drawing in it, so it can be used to save the image to
+ # a file, or whatever.
+
+ # This seems required on MacOS, it doesn't like wx.EmptyBitmap with
+ # size = (0, 0)
+ # Thanks to Gerard Grazzini
+
+ if "__WXMAC__" in wx.Platform:
+ if self.Width == 0:
+ self.Width = 1
+ if self.Height == 0:
+ self.Height = 1
+
+ self._Buffer = wx.EmptyBitmap(self.Width, self.Height)
+
+ memory = wx.MemoryDC()
+ memory.SelectObject(self._Buffer)
+ memory.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ memory.SetPen(wx.TRANSPARENT_PEN)
+ memory.Clear()
+
+ minradius = min(0.9*self.Width/2, 0.9*self.Height/2)
+ memory.DrawCircle(self.Width/2, self.Height/2, minradius)
+ memory.SelectObject(wx.NullBitmap)
+ self._region = wx.RegionFromBitmapColour(self._Buffer, self.GetBackgroundColour())
+ self._minradius = minradius
+
+ self.UpdateDrawing()
+
+
+ def UpdateDrawing(self):
+ """
+ This would get called if the drawing needed to change, for whatever reason.
+
+ The idea here is that the drawing is based on some data generated
+ elsewhere in the system. If that data changes, the drawing needs to
+ be updated.
+ """
+
+ if self._agwStyle == KC_BUFFERED_DC:
+ dc = wx.BufferedDC(wx.ClientDC(self), self._Buffer)
+ self.Draw(dc)
+ else:
+ # update the buffer
+ dc = wx.MemoryDC()
+ dc.SelectObject(self._Buffer)
+
+ self.Draw(dc)
+ # update the screen
+ wx.ClientDC(self).Blit(0, 0, self.Width, self.Height, dc, 0, 0)
+
+
+# ---------------------------------------------------------------------------- #
+# Class KnobCtrl
+# ---------------------------------------------------------------------------- #
+
+class KnobCtrl(BufferedWindow):
+ """
+ This class can be used to simulate a knob volume control often found in
+ PC music players.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize,
+ agwStyle=KC_BUFFERED_DC):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `agwStyle`: if set to ``KC_BUFFERED_DC``, double-buffering will
+ be used.
+ """
+
+ self._agwStyle = agwStyle
+ self._knobcolour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+
+ self._startcolour = wx.WHITE
+ self._endcolour = wx.Colour(170, 170, 150)
+ self._tagscolour = wx.BLACK
+ self._boundingcolour = wx.WHITE
+ self._tags = []
+ self._anglestart = -45
+ self._angleend = 180
+ self._state = 0
+ self._minvalue = 0
+ self._maxvalue = 100
+ self._old_ang = 0
+ self._trackposition = 0
+ self._knobradius = 4
+
+ BufferedWindow.__init__(self, parent, id, pos, size,
+ style=wx.NO_FULL_REPAINT_ON_RESIZE,
+ agwStyle=agwStyle)
+
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvents)
+ self.SetValue(self._trackposition)
+
+
+ def OnMouseEvents(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` event for :class:`KnobCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._state == 0 and event.Entering():
+ self._state = 1
+ elif self._state >= 1 and event.Leaving():
+ self._state = 0
+ elif self._state == 1 and event.LeftDown():
+ self._state = 2
+ self._mousePosition = event.GetPosition()
+ self.SetTrackPosition()
+ elif self._state == 2 and event.LeftIsDown():
+ self._mousePosition = event.GetPosition()
+ self.SetTrackPosition()
+ elif self._state == 2 and event.LeftUp():
+ self._state = 1
+
+
+ def SetTags(self, tags):
+ """
+ Sets the tags for :class:`KnobCtrl`.
+
+ :param `tags`: a list of integers ranging from `minvalue` to `maxvalue`.
+ """
+
+ self._tags = tags
+ if min(tags) < self._minvalue:
+ self._minvalue = min(tags)
+
+ if max(tags) > self._maxvalue:
+ self._maxvalue = max(tags)
+
+ self.OnSize(None)
+
+
+ def GetMinValue(self):
+ """ Returns the minimum value for :class:`KnobCtrl`. """
+
+ return self._minvalue
+
+
+ def GetMaxValue(self):
+ """ Returns the maximum value for :class:`KnobCtrl`. """
+
+ return self._maxvalue
+
+
+ def GetKnobRadius(self):
+ """ Returns the knob radius, in pixels. """
+
+ return self._knobradius
+
+
+ def SetKnobRadius(self, radius):
+ """
+ Sets the knob radius.
+
+ :param `radius`: the knob radius, in pixels.
+ """
+
+ if radius <= 0:
+ return
+
+ self._knobradius = radius
+ self.UpdateDrawing()
+
+
+ def GetTags(self):
+ """ Returns the :class:`KnobCtrl` tags. """
+
+ return self._tags
+
+
+ def SetTagsColour(self, colour):
+ """
+ Sets the tags colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._tagscolour = colour
+ self.UpdateDrawing()
+
+
+ def GetTagsColour(self):
+ """ Returns the tags colour. """
+
+ return self._tagscolour
+
+
+ def SetBoundingColour(self, colour):
+ """
+ Sets the bounding circle colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._boundingcolour = colour
+ self.UpdateDrawing()
+
+
+ def GetBoundingColour(self):
+ """ Returns the bounding circle colour. """
+
+ return self._boundingcolour
+
+
+ def SetFirstGradientColour(self, colour):
+ """
+ Sets the first gradient colour for shading.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._startcolour = colour
+ self.UpdateDrawing()
+
+
+ def GetFirstGradientColour(self):
+ """ Returns the first gradient colour for shading. """
+
+ return self._startcolour
+
+
+ def SetSecondGradientColour(self, colour):
+ """
+ Sets the second gradient colour for shading.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._endcolour = colour
+ self.UpdateDrawing()
+
+
+ def GetSecondGradientColour(self):
+ """ Returns the second gradient colour for shading. """
+
+ return self._endcolour
+
+
+ def SetAngularRange(self, start, end):
+ """
+ Sets the angular range for :class:`KnobCtrl`.
+
+ :param `start`: the starting angle, in degrees, clockwise;
+ :param `start`: the ending angle, in degrees, clockwise.
+ """
+
+ self._anglestart = start
+ self._angleend = end
+ self.UpdateDrawing()
+
+
+ def GetAngularRange(self):
+ """
+ Returns the angular range for :class:`KnobCtrl` as a tuple. The `start` and `end`
+ angles in the returned tuple are given in degrees, clockwise.
+ """
+
+ return self._anglestart, self._angleend
+
+
+ def Draw(self, dc):
+ """
+ Draws everything on the empty bitmap.
+ Here all the chosen styles are applied.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ size = self.GetClientSize()
+
+ if size.x < 21 or size.y < 21:
+ return
+
+ dc.SetClippingRegionAsRegion(self._region)
+ self.DrawDiagonalGradient(dc, size)
+ self.DrawInsetCircle(dc, self._knobcolour)
+ dc.DestroyClippingRegion()
+ self.DrawBoundingCircle(dc, size)
+
+ if self._tags:
+ self.DrawTags(dc, size)
+
+
+ def DrawTags(self, dc, size):
+ """
+ Draws the tags.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `size`: the control size.
+ """
+
+ deltarange = abs(self._tags[-1] - self._tags[0])
+ deltaangle = self._angleend - self._anglestart
+
+ width = size.x
+ height = size.y
+
+ xshift = 0
+ yshift = 0
+
+ if width > height:
+ xshift = width - height
+ elif width < height:
+ yshift = height - width
+
+ coeff = float(deltaangle)/float(deltarange)
+
+ dcPen = wx.Pen(self._tagscolour, 1)
+
+ for tags in self._tags:
+
+ if tags == self._tags[0] or tags == self._tags[-1]:
+ # draw first and last tags bigger
+ dcPen.SetWidth(2)
+ tagLen = 8
+ else:
+ dcPen.SetWidth(1)
+ tagLen = 6
+
+ dc.SetPen(dcPen)
+
+ tg = tags - self._tags[0]
+ angle = tg*coeff + self._anglestart
+ angle = angle*math.pi/180.0
+
+ sxi = math.cos(angle)*(width - xshift + tagLen - 6)/2.0
+ syi = math.sin(angle)*(height - yshift + tagLen - 6)/2.0
+
+ dxi = math.cos(angle)*((width - xshift + tagLen - 6)/2.0 - tagLen)
+ dyi = math.sin(angle)*((height - yshift + tagLen - 6)/2.0 - tagLen)
+
+ dc.DrawLine(width/2 - sxi, height/2 - syi,
+ width/2 - dxi, height/2 - dyi)
+
+
+ def DrawDiagonalGradient(self, dc, size):
+ """
+ Draw a shading of diagonal gradient to :class:`KnobCtrl`.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `size`: the control size.
+ """
+
+ col1 = self._startcolour
+ col2 = self._endcolour
+
+ r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+ r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+ maxsize = max(size.x, size.y)
+
+ flrect = maxsize
+
+ rstep = float((r2 - r1)) / flrect
+ gstep = float((g2 - g1)) / flrect
+ bstep = float((b2 - b1)) / flrect
+
+ rf, gf, bf = 0, 0, 0
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ for ii in xrange(0, maxsize, 2):
+ currCol = (r1 + rf, g1 + gf, b1 + bf)
+ dc.SetPen(wx.Pen(currCol, 2))
+ dc.DrawLine(0, ii+2, ii+2, 0)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+ for ii in xrange(0, maxsize, 2):
+ currCol = (r1 + rf, g1 + gf, b1 + bf)
+ dc.SetPen(wx.Pen(currCol, 2))
+ dc.DrawLine(ii+2, maxsize, maxsize, ii+2)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+
+ def OffsetColour(self, colour, offset):
+ """
+ Changes the input colour by the `offset` value. Used internally.
+
+ :param `colour`: a valid :class:`Colour` object;
+ :param `offset`: an integer value for offsetting the input colour.
+ """
+
+ byRed = 0
+ byGreen = 0
+ byBlue = 0
+ offsetR = offset
+ offsetG = offset
+ offsetB = offset
+
+ if offset < -255 or offset> 255:
+ return colour
+
+ # Get RGB components of specified colour
+ byRed = colour.Red()
+ byGreen = colour.Green()
+ byBlue = colour.Blue()
+
+ # Calculate max. allowed real offset
+ if offset > 0:
+
+ if byRed + offset > 255:
+ offsetR = 255 - byRed
+ if byGreen + offset > 255:
+ offsetG = 255 - byGreen
+ if byBlue + offset > 255:
+ offsetB = 255 - byBlue
+
+ offset = min(min(offsetR, offsetG), offsetB)
+
+ else:
+
+ if byRed + offset < 0:
+ offsetR = -byRed
+ if byGreen + offset < 0:
+ offsetG = -byGreen
+ if byBlue + offset < 0:
+ offsetB = -byBlue
+
+ offset = max(max(offsetR, offsetG), offsetB)
+
+ c1 = wx.Colour(byRed + offset, byGreen + offset, byBlue + offset)
+
+ return c1
+
+
+ def DrawInsetCircle(self, dc, pencolour):
+ """
+ Draws the small knob.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `pencolour`: the colour to use for drawing the inset circle.
+ """
+
+ self._knobcenter = self.CircleCoords(self._minradius*0.8, self.GetTrackPosition(),
+ self.Width/2, self.Height/2)
+
+ cx, cy = self._knobcenter
+ r = self._knobradius
+
+ p1 = wx.Pen(self.OffsetColour(pencolour, -70), 2)
+ p2 = wx.Pen(self.OffsetColour(pencolour, 10), 1)
+
+ pt1 = wx.Point(cx-r*math.sqrt(2)/2, cy+r*math.sqrt(2)/2)
+ pt2 = wx.Point(cx+r*math.sqrt(2)/2, cy-r*math.sqrt(2)/2)
+
+ dc.SetPen(p2)
+ dc.DrawArcPoint(pt1, pt2, (cx, cy))
+ dc.SetPen(p1)
+ dc.DrawArcPoint(pt2, pt1, (cx, cy))
+
+
+ def DrawBoundingCircle(self, dc, size):
+ """
+ Draws the :class:`KnobCtrl` bounding circle.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `size`: the control size.
+ """
+
+ radius = 0.9*min(size.x, size.y)/2
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(self._boundingcolour))
+ dc.DrawCircle(self.Width/2, self.Height/2, radius)
+
+
+ def CircleCoords(self, radius, angle, centerX, centerY):
+ """
+ Converts the input values into logical `x` and `y` coordinates.
+
+ :param `radius`: the :class:`KnobCtrl` radius;
+ :param `angle`: the angular position of the mouse;
+ :param `centerX`: the `x` position of the :class:`KnobCtrl` center;
+ :param `centerX`: the `y` position of the :class:`KnobCtrl` center.
+ """
+
+ x = radius*math.cos(angle) + centerX
+ y = radius*math.sin(angle) + centerY
+
+ return x, y
+
+
+ def SetTrackPosition(self):
+ """ Used internally. """
+
+ width, height = self.GetSize()
+
+ x = self._mousePosition.x
+ y = self._mousePosition.y
+
+ ang = self.GetAngleFromCoord(x, y)
+ val = ang*180.0/math.pi
+
+ deltarange = self._maxvalue - self._minvalue
+ deltaangle = self._angleend - self._anglestart
+
+ coeff = float(deltaangle)/float(deltarange)
+
+ if self._anglestart < 0 and val >= 360.0 + self._anglestart:
+ scaledval = (val - (360.0 + self._anglestart))/coeff
+ else:
+ scaledval = (val - self._anglestart)/coeff
+
+ if scaledval > self._maxvalue or scaledval < self._minvalue:
+ ang = self._old_ang
+ else:
+ event = KnobCtrlEvent(wxEVT_KC_ANGLE_CHANGING, self.GetId())
+ event.SetEventObject(self)
+ event.SetOldValue(self.GetValue())
+ event.SetValue(int(round(scaledval)))
+
+ if self.GetEventHandler().ProcessEvent(event):
+ # the caller didn't use event.Skip()
+ return
+
+ self.SetValue(scaledval)
+ event.SetEventType(wxEVT_KC_ANGLE_CHANGED)
+ event.SetOldValue(scaledval)
+ self.GetEventHandler().ProcessEvent(event)
+
+ self._old_ang = ang
+
+
+ def SetValue(self, val):
+ """
+ Sets programmatically the value of :class:`KnobCtrl`.
+
+ :param `val`: an integer specifying the new :class:`KnobCtrl` value.
+
+ :note: This method does not send a :class:`KnobCtrlEvent`.
+ """
+
+ if val < self._minvalue or val > self._maxvalue:
+ return
+
+ width, height = self.GetSize()
+
+ deltarange = self._maxvalue - self._minvalue
+ deltaangle = self._angleend - self._anglestart
+
+ coeff = float(deltaangle)/float(deltarange)
+
+ ang = 360.0 + val*coeff + self._anglestart
+
+ ang = ang*math.pi/180.0
+ self._old_ang = ang
+
+ self._trackposition = int(round(val))
+ self.UpdateDrawing()
+
+
+ def GetValue(self):
+ """ Returns the value of :class:`KnobCtrl`. """
+
+ return self._trackposition
+
+
+ def GetTrackPosition(self):
+ """ Used internally. """
+
+ return self._old_ang - math.pi
+
+
+ def GetAngleFromCoord(self, cx, cy):
+ """
+ Returns the angular position based on the input logical coordinates.
+ Used internally.
+
+ :param `cx`: the `x` logical position;
+ :param `cy`: the `y` logical position.
+ """
+
+ width, height = self.GetSize()
+
+ ang = 0
+ y = (height/2 - float(cy))/(height/2)
+ x = (float(cx) - width/2)/(height/2)
+
+ ang = ang - math.atan2(-y, -x)
+
+ if ang < 0:
+ ang = ang + 2.0*math.pi
+
+ return ang
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/labelbook.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/labelbook.py
new file mode 100644
index 0000000..a1a9e12
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/labelbook.py
@@ -0,0 +1,3031 @@
+# --------------------------------------------------------------------------- #
+# LABELBOOK And FLATIMAGEBOOK Widgets wxPython IMPLEMENTATION
+#
+# Original C++ Code From Eran, embedded in the FlatMenu source code
+#
+#
+# License: wxWidgets license
+#
+#
+# Python Code By:
+#
+# Andrea Gavana, @ 03 Nov 2006
+# Latest Revision: 22 Jan 2013, 21.00 GMT
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+# TODO:
+# LabelBook - Support IMB_SHOW_ONLY_IMAGES
+# LabelBook - An option to only draw the border
+# between the controls and the pages so the background
+# colour can flow into the window background
+#
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+:class:`LabelBook` and :class:`FlatImageBook` are a quasi-full generic and owner-drawn
+implementations of :class:`Notebook`.
+
+
+Description
+===========
+
+:class:`LabelBook` and :class:`FlatImageBook` are quasi-full implementations of the :class:`Notebook`,
+and designed to be a drop-in replacement for :class:`Notebook`. The API functions are
+similar so one can expect the function to behave in the same way.
+:class:`LabelBook` anf :class:`FlatImageBook` share their appearance with :class:`Toolbook` and
+:class:`Listbook`, while having more options for custom drawings, label positioning,
+mouse pointing and so on. Moreover, they retain also some visual characteristics
+of the Outlook address book.
+
+Some features:
+
+- They are generic controls;
+- Supports for left, right, top (:class:`FlatImageBook` only), bottom (:class:`FlatImageBook`
+ only) book styles;
+- Possibility to draw images only, text only or both (:class:`FlatImageBook` only);
+- Support for a "pin-button", that allows the user to shrink/expand the book
+ tab area;
+- Shadows behind tabs (:class:`LabelBook` only);
+- Gradient shading of the tab area (:class:`LabelBook` only);
+- Web-like mouse pointing on tabs style (:class:`LabelBook` only);
+- Many customizable colours (tab area, active tab text, tab borders, active
+ tab, highlight) - :class:`LabelBook` only.
+
+And much more. See the demo for a quasi-complete review of all the functionalities
+of :class:`LabelBook` and :class:`FlatImageBook`.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.labelbook as LB
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "LabelBook Demo")
+
+ # Possible values for Tab placement are INB_TOP, INB_BOTTOM, INB_RIGHT, INB_LEFT
+
+ notebook = LB.LabelBook(self, -1, agwStyle=LB.INB_FIT_LABELTEXT|LB.INB_LEFT|LB.INB_DRAW_SHADOW|LB.INB_GRADIENT_BACKGROUND)
+
+ pane1 = wx.Panel(notebook)
+ pane2 = wx.Panel(notebook)
+
+ imagelist = wx.ImageList(32, 32)
+ imagelist.Add(wx.Bitmap("my_bitmap.png", wx.BITMAP_TYPE_PNG))
+ notebook.AssignImageList(imagelist)
+
+ notebook.AddPage(pane_1, "Tab1", 1, 0)
+ notebook.AddPage(pane_2, "Tab2", 0, 0)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`LabelBook` and :class:`FlatImageBook` have been tested on the following platforms:
+ * Windows (Windows XP);
+ * Linux Ubuntu (Dapper 6.06)
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+=========================== =========== ==================================================
+Window Styles Hex Value Description
+=========================== =========== ==================================================
+``INB_BOTTOM`` 0x1 Place labels below the page area. Available only for :class:`FlatImageBook`.
+``INB_LEFT`` 0x2 Place labels on the left side. Available only for :class:`FlatImageBook`.
+``INB_RIGHT`` 0x4 Place labels on the right side.
+``INB_TOP`` 0x8 Place labels above the page area.
+``INB_BORDER`` 0x10 Draws a border around :class:`LabelBook` or :class:`FlatImageBook`.
+``INB_SHOW_ONLY_TEXT`` 0x20 Shows only text labels and no images. Available only for :class:`LabelBook`.
+``INB_SHOW_ONLY_IMAGES`` 0x40 Shows only tab images and no label texts. Available only for :class:`LabelBook`.
+``INB_FIT_BUTTON`` 0x80 Displays a pin button to show/hide the book control.
+``INB_DRAW_SHADOW`` 0x100 Draw shadows below the book tabs. Available only for :class:`LabelBook`.
+``INB_USE_PIN_BUTTON`` 0x200 Displays a pin button to show/hide the book control.
+``INB_GRADIENT_BACKGROUND`` 0x400 Draws a gradient shading on the tabs background. Available only for :class:`LabelBook`.
+``INB_WEB_HILITE`` 0x800 On mouse hovering, tabs behave like html hyperlinks. Available only for :class:`LabelBook`.
+``INB_NO_RESIZE`` 0x1000 Don't allow resizing of the tab area.
+``INB_FIT_LABELTEXT`` 0x2000 Will fit the tab area to the longest text (or text+image if you have images) in all the tabs.
+``INB_BOLD_TAB_SELECTION`` 0x4000 Show the selected tab text using a bold font.
+=========================== =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+=================================== ==================================================
+Event Name Description
+=================================== ==================================================
+``EVT_IMAGENOTEBOOK_PAGE_CHANGED`` Notify client objects when the active page in :class:`FlatImageBook` or :class:`LabelBook` has changed.
+``EVT_IMAGENOTEBOOK_PAGE_CHANGING`` Notify client objects when the active page in :class:`FlatImageBook` or :class:`LabelBook` is about to change.
+``EVT_IMAGENOTEBOOK_PAGE_CLOSED`` Notify client objects when a page in :class:`FlatImageBook` or :class:`LabelBook` has been closed.
+``EVT_IMAGENOTEBOOK_PAGE_CLOSING`` Notify client objects when a page in :class:`FlatImageBook` or :class:`LabelBook` is closing.
+=================================== ==================================================
+
+
+TODOs
+=====
+
+- :class:`LabelBook`: support ``IMB_SHOW_ONLY_IMAGES``;
+- :class:`LabelBook`: an option to only draw the border between the controls and the pages so the background
+ colour can flow into the window background.
+
+
+License And Version
+===================
+
+:class:`LabelBook` and :class:`FlatImageBook` are distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 22 Jan 2013, 21.00 GMT
+
+Version 0.6.
+
+"""
+
+__docformat__ = "epytext"
+__version__ = "0.6"
+
+
+#----------------------------------------------------------------------
+# Beginning Of IMAGENOTEBOOK wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+
+from artmanager import ArtManager, DCSaver
+from fmresources import *
+
+# Check for the new method in 2.7 (not present in 2.6.3.3)
+if wx.VERSION_STRING < "2.7":
+ wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point)
+
+# FlatImageBook and LabelBook styles
+INB_BOTTOM = 1
+""" Place labels below the page area. Available only for :class:`FlatImageBook`."""
+INB_LEFT = 2
+""" Place labels on the left side. Available only for :class:`FlatImageBook`."""
+INB_RIGHT = 4
+""" Place labels on the right side. """
+INB_TOP = 8
+""" Place labels above the page area. """
+INB_BORDER = 16
+""" Draws a border around :class:`LabelBook` or :class:`FlatImageBook`. """
+INB_SHOW_ONLY_TEXT = 32
+""" Shows only text labels and no images. Available only for :class:`LabelBook`."""
+INB_SHOW_ONLY_IMAGES = 64
+""" Shows only tab images and no label texts. Available only for :class:`LabelBook`."""
+INB_FIT_BUTTON = 128
+""" Displays a pin button to show/hide the book control. """
+INB_DRAW_SHADOW = 256
+""" Draw shadows below the book tabs. Available only for :class:`LabelBook`."""
+INB_USE_PIN_BUTTON = 512
+""" Displays a pin button to show/hide the book control. """
+INB_GRADIENT_BACKGROUND = 1024
+""" Draws a gradient shading on the tabs background. Available only for :class:`LabelBook`."""
+INB_WEB_HILITE = 2048
+""" On mouse hovering, tabs behave like html hyperlinks. Available only for :class:`LabelBook`."""
+INB_NO_RESIZE = 4096
+""" Don't allow resizing of the tab area. """
+INB_FIT_LABELTEXT = 8192
+""" Will fit the tab area to the longest text (or text+image if you have images) in all the tabs. """
+INB_BOLD_TAB_SELECTION = 16384
+""" Show the selected tab text using a bold font. """
+
+wxEVT_IMAGENOTEBOOK_PAGE_CHANGED = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
+wxEVT_IMAGENOTEBOOK_PAGE_CHANGING = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
+wxEVT_IMAGENOTEBOOK_PAGE_CLOSING = wx.NewEventType()
+wxEVT_IMAGENOTEBOOK_PAGE_CLOSED = wx.NewEventType()
+
+#-----------------------------------#
+# ImageNotebookEvent
+#-----------------------------------#
+
+EVT_IMAGENOTEBOOK_PAGE_CHANGED = wx.EVT_NOTEBOOK_PAGE_CHANGED
+""" Notify client objects when the active page in :class:`FlatImageBook` or :class:`LabelBook` has changed. """
+EVT_IMAGENOTEBOOK_PAGE_CHANGING = wx.EVT_NOTEBOOK_PAGE_CHANGING
+""" Notify client objects when the active page in :class:`FlatImageBook` or :class:`LabelBook` is about to change. """
+EVT_IMAGENOTEBOOK_PAGE_CLOSING = wx.PyEventBinder(wxEVT_IMAGENOTEBOOK_PAGE_CLOSING, 1)
+""" Notify client objects when a page in :class:`FlatImageBook` or :class:`LabelBook` is closing. """
+EVT_IMAGENOTEBOOK_PAGE_CLOSED = wx.PyEventBinder(wxEVT_IMAGENOTEBOOK_PAGE_CLOSED, 1)
+""" Notify client objects when a page in :class:`FlatImageBook` or :class:`LabelBook` has been closed. """
+
+
+# ---------------------------------------------------------------------------- #
+# Class ImageNotebookEvent
+# ---------------------------------------------------------------------------- #
+
+class ImageNotebookEvent(wx.PyCommandEvent):
+ """
+ This events will be sent when a ``EVT_IMAGENOTEBOOK_PAGE_CHANGED``,
+ ``EVT_IMAGENOTEBOOK_PAGE_CHANGING``, ``EVT_IMAGENOTEBOOK_PAGE_CLOSING``,
+ ``EVT_IMAGENOTEBOOK_PAGE_CLOSED`` is mapped in the parent.
+ """
+
+ def __init__(self, eventType, eventId=1, sel=-1, oldsel=-1):
+ """
+ Default class constructor.
+
+ :param `eventType`: the event type;
+ :param `eventId`: the event identifier;
+ :param `sel`: the current selection;
+ :param `oldsel`: the old selection.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+ self._eventType = eventType
+ self._sel = sel
+ self._oldsel = oldsel
+ self._allowed = True
+
+
+ def SetSelection(self, s):
+ """
+ Sets the event selection.
+
+ :param `s`: an integer specifying the new selection.
+ """
+
+ self._sel = s
+
+
+ def SetOldSelection(self, s):
+ """
+ Sets the event old selection.
+
+ :param `s`: an integer specifying the old selection.
+ """
+
+ self._oldsel = s
+
+
+ def GetSelection(self):
+ """ Returns the event selection. """
+
+ return self._sel
+
+
+ def GetOldSelection(self):
+ """ Returns the old event selection. """
+
+ return self._oldsel
+
+
+ def Veto(self):
+ """
+ Prevents the change announced by this event from happening.
+
+ :note: It is in general a good idea to notify the user about the reasons
+ for vetoing the change because otherwise the applications behaviour (which
+ just refuses to do what the user wants) might be quite surprising.
+ """
+
+ self._allowed = False
+
+
+ def Allow(self):
+ """
+ This is the opposite of :meth:`~ImageNotebookEvent.Veto`: it explicitly allows the event to be processed.
+ For most events it is not necessary to call this method as the events are
+ allowed anyhow but some are forbidden by default (this will be mentioned
+ in the corresponding event description).
+ """
+
+ self._allowed = True
+
+
+ def IsAllowed(self):
+ """
+ Returns ``True`` if the change is allowed (:meth:`~ImageNotebookEvent.Veto` hasn't been called) or
+ ``False`` otherwise (if it was).
+ """
+
+ return self._allowed
+
+
+# ---------------------------------------------------------------------------- #
+# Class ImageInfo
+# ---------------------------------------------------------------------------- #
+
+class ImageInfo(object):
+ """
+ This class holds all the information (caption, image, etc...) belonging to a
+ single tab in :class:`LabelBook`.
+ """
+ def __init__(self, strCaption="", imageIndex=-1, enabled=True):
+ """
+ Default class constructor.
+
+ :param `strCaption`: the tab caption;
+ :param `imageIndex`: the tab image index based on the assigned (set)
+ :class:`ImageList` (if any);
+ :param `enabled`: sets the tab as enabled or disabled.
+ """
+
+ self._pos = wx.Point()
+ self._size = wx.Size()
+ self._strCaption = strCaption
+ self._ImageIndex = imageIndex
+ self._captionRect = wx.Rect()
+ self._bEnabled = enabled
+
+
+ def SetCaption(self, value):
+ """
+ Sets the tab caption.
+
+ :param `value`: the new tab caption.
+ """
+
+ self._strCaption = value
+
+
+ def GetCaption(self):
+ """ Returns the tab caption. """
+
+ return self._strCaption
+
+
+ def SetPosition(self, value):
+ """
+ Sets the tab position.
+
+ :param `value`: the new tab position, an instance of :class:`Point`.
+ """
+
+ self._pos = value
+
+
+ def GetPosition(self):
+ """ Returns the tab position. """
+
+ return self._pos
+
+
+ def SetSize(self, value):
+ """
+ Sets the tab size.
+
+ :param `value`: the new tab size, an instance of :class:`Size`.
+ """
+
+ self._size = value
+
+
+ def GetSize(self):
+ """ Returns the tab size. """
+
+ return self._size
+
+
+ def SetImageIndex(self, value):
+ """
+ Sets the tab image index.
+
+ :param `value`: an index into the image list..
+ """
+
+ self._ImageIndex = value
+
+
+ def GetImageIndex(self):
+ """ Returns the tab image index. """
+
+ return self._ImageIndex
+
+
+ def SetTextRect(self, rect):
+ """
+ Sets the client rectangle available for the tab text.
+
+ :param `rect`: the tab text client rectangle, an instance of :class:`Rect`.
+ """
+
+ self._captionRect = rect
+
+
+ def GetTextRect(self):
+ """ Returns the client rectangle available for the tab text. """
+
+ return self._captionRect
+
+
+ def GetEnabled(self):
+ """ Returns whether the tab is enabled or not. """
+
+ return self._bEnabled
+
+
+ def EnableTab(self, enabled):
+ """
+ Sets the tab enabled or disabled.
+
+ :param `enabled`: ``True`` to enable a tab, ``False`` to disable it.
+ """
+
+ self._bEnabled = enabled
+
+
+# ---------------------------------------------------------------------------- #
+# Class ImageContainerBase
+# ---------------------------------------------------------------------------- #
+
+class ImageContainerBase(wx.Panel):
+ """
+ Base class for :class:`FlatImageBook` image container.
+ """
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=0, name="ImageContainerBase"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`Panel` window style;
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``INB_BOTTOM`` 0x1 Place labels below the page area. Available only for :class:`FlatImageBook`.
+ ``INB_LEFT`` 0x2 Place labels on the left side. Available only for :class:`FlatImageBook`.
+ ``INB_RIGHT`` 0x4 Place labels on the right side.
+ ``INB_TOP`` 0x8 Place labels above the page area.
+ ``INB_BORDER`` 0x10 Draws a border around :class:`LabelBook` or :class:`FlatImageBook`.
+ ``INB_SHOW_ONLY_TEXT`` 0x20 Shows only text labels and no images. Available only for :class:`LabelBook`.
+ ``INB_SHOW_ONLY_IMAGES`` 0x40 Shows only tab images and no label texts. Available only for :class:`LabelBook`.
+ ``INB_FIT_BUTTON`` 0x80 Displays a pin button to show/hide the book control.
+ ``INB_DRAW_SHADOW`` 0x100 Draw shadows below the book tabs. Available only for :class:`LabelBook`.
+ ``INB_USE_PIN_BUTTON`` 0x200 Displays a pin button to show/hide the book control.
+ ``INB_GRADIENT_BACKGROUND`` 0x400 Draws a gradient shading on the tabs background. Available only for :class:`LabelBook`.
+ ``INB_WEB_HILITE`` 0x800 On mouse hovering, tabs behave like html hyperlinks. Available only for :class:`LabelBook`.
+ ``INB_NO_RESIZE`` 0x1000 Don't allow resizing of the tab area.
+ ``INB_FIT_LABELTEXT`` 0x2000 Will fit the tab area to the longest text (or text+image if you have images) in all the tabs.
+ ``INB_BOLD_TAB_SELECTION`` 0x4000 Show the selected tab text using a bold font.
+ =========================== =========== ==================================================
+
+ :param `name`: the window name.
+ """
+
+ self._nIndex = -1
+ self._nImgSize = 16
+ self._ImageList = None
+ self._nHoveredImgIdx = -1
+ self._bCollapsed = False
+ self._tabAreaSize = (-1, -1)
+ self._nPinButtonStatus = INB_PIN_NONE
+ self._pagesInfoVec = []
+ self._pinBtnRect = wx.Rect()
+
+ wx.Panel.__init__(self, parent, id, pos, size, style | wx.NO_BORDER | wx.NO_FULL_REPAINT_ON_RESIZE, name)
+
+
+ def HasAGWFlag(self, flag):
+ """
+ Tests for existance of flag in the style.
+
+ :param `flag`: a window style. This can be a combination of the following bits:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``INB_BOTTOM`` 0x1 Place labels below the page area. Available only for :class:`FlatImageBook`.
+ ``INB_LEFT`` 0x2 Place labels on the left side. Available only for :class:`FlatImageBook`.
+ ``INB_RIGHT`` 0x4 Place labels on the right side.
+ ``INB_TOP`` 0x8 Place labels above the page area.
+ ``INB_BORDER`` 0x10 Draws a border around :class:`LabelBook` or :class:`FlatImageBook`.
+ ``INB_SHOW_ONLY_TEXT`` 0x20 Shows only text labels and no images. Available only for :class:`LabelBook`.
+ ``INB_SHOW_ONLY_IMAGES`` 0x40 Shows only tab images and no label texts. Available only for :class:`LabelBook`.
+ ``INB_FIT_BUTTON`` 0x80 Displays a pin button to show/hide the book control.
+ ``INB_DRAW_SHADOW`` 0x100 Draw shadows below the book tabs. Available only for :class:`LabelBook`.
+ ``INB_USE_PIN_BUTTON`` 0x200 Displays a pin button to show/hide the book control.
+ ``INB_GRADIENT_BACKGROUND`` 0x400 Draws a gradient shading on the tabs background. Available only for :class:`LabelBook`.
+ ``INB_WEB_HILITE`` 0x800 On mouse hovering, tabs behave like html hyperlinks. Available only for :class:`LabelBook`.
+ ``INB_NO_RESIZE`` 0x1000 Don't allow resizing of the tab area.
+ ``INB_FIT_LABELTEXT`` 0x2000 Will fit the tab area to the longest text (or text+image if you have images) in all the tabs.
+ ``INB_BOLD_TAB_SELECTION`` 0x4000 Show the selected tab text using a bold font.
+ =========================== =========== ==================================================
+ """
+
+ style = self.GetParent().GetAGWWindowStyleFlag()
+ res = (style & flag and [True] or [False])[0]
+ return res
+
+
+ def ClearFlag(self, flag):
+ """
+ Removes flag from the style.
+
+ :param `flag`: a window style flag.
+
+ :see: :meth:`~ImageContainerBase.HasAGWFlag` for a list of possible window style flags.
+ """
+
+ parent = self.GetParent()
+ agwStyle = parent.GetAGWWindowStyleFlag()
+ agwStyle &= ~(flag)
+ parent.SetAGWWindowStyleFlag(agwStyle)
+
+
+ def AssignImageList(self, imglist):
+ """
+ Assigns an image list to the :class:`ImageContainerBase`.
+
+ :param `imglist`: an instance of :class:`ImageList`.
+ """
+
+ if imglist and imglist.GetImageCount() != 0:
+ self._nImgSize = imglist.GetBitmap(0).GetHeight()
+
+ self._ImageList = imglist
+ parent = self.GetParent()
+ agwStyle = parent.GetAGWWindowStyleFlag()
+ parent.SetAGWWindowStyleFlag(agwStyle)
+
+
+ def GetImageList(self):
+ """ Return the image list for :class:`ImageContainerBase`. """
+
+ return self._ImageList
+
+
+ def GetImageSize(self):
+ """ Returns the image size inside the :class:`ImageContainerBase` image list. """
+
+ return self._nImgSize
+
+
+ def FixTextSize(self, dc, text, maxWidth):
+ """
+ Fixes the text, to fit `maxWidth` value. If the text length exceeds
+ `maxWidth` value this function truncates it and appends two dots at
+ the end. ("Long Long Long Text" might become "Long Long...").
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `text`: the text to fix/truncate;
+ :param `maxWidth`: the maximum allowed width for the text, in pixels.
+ """
+
+ return ArtManager.Get().TruncateText(dc, text, maxWidth)
+
+
+ def CanDoBottomStyle(self):
+ """
+ Allows the parent to examine the children type. Some implementation
+ (such as :class:`LabelBook`), does not support top/bottom images, only left/right.
+ """
+
+ return False
+
+
+ def AddPage(self, caption, selected=False, imgIdx=-1):
+ """
+ Adds a page to the container.
+
+ :param `caption`: specifies the text for the new tab;
+ :param `selected`: specifies whether the page should be selected;
+ :param `imgIdx`: specifies the optional image index for the new tab.
+ """
+
+ self._pagesInfoVec.append(ImageInfo(caption, imgIdx))
+ if selected or len(self._pagesInfoVec) == 1:
+ self._nIndex = len(self._pagesInfoVec)-1
+
+ self.Refresh()
+
+
+ def InsertPage(self, page_idx, caption, selected=False, imgIdx=-1):
+ """
+ Inserts a page into the container at the specified position.
+
+ :param `page_idx`: specifies the position for the new tab;
+ :param `caption`: specifies the text for the new tab;
+ :param `selected`: specifies whether the page should be selected;
+ :param `imgIdx`: specifies the optional image index for the new tab.
+ """
+
+ self._pagesInfoVec.insert(page_idx, ImageInfo(caption, imgIdx))
+ if selected or len(self._pagesInfoVec) == 1:
+ self._nIndex = len(self._pagesInfoVec)-1
+
+ self.Refresh()
+
+
+ def SetPageImage(self, page, imgIdx):
+ """
+ Sets the image for the given page.
+
+ :param `page`: the index of the tab;
+ :param `imgIdx`: specifies the optional image index for the tab.
+ """
+
+ imgInfo = self._pagesInfoVec[page]
+ imgInfo.SetImageIndex(imgIdx)
+
+
+ def SetPageText(self, page, text):
+ """
+ Sets the tab caption for the given page.
+
+ :param `page`: the index of the tab;
+ :param `text`: the new tab caption.
+ """
+
+ imgInfo = self._pagesInfoVec[page]
+ imgInfo.SetCaption(text)
+
+
+ def GetPageImage(self, page):
+ """
+ Returns the image index for the given page.
+
+ :param `page`: the index of the tab.
+ """
+
+ imgInfo = self._pagesInfoVec[page]
+ return imgInfo.GetImageIndex()
+
+
+ def GetPageText(self, page):
+ """
+ Returns the tab caption for the given page.
+
+ :param `page`: the index of the tab.
+ """
+
+ imgInfo = self._pagesInfoVec[page]
+ return imgInfo.GetCaption()
+
+
+ def GetEnabled(self, page):
+ """
+ Returns whether a tab is enabled or not.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ if page >= len(self._pagesInfoVec):
+ return True # Adding a page - enabled by default
+
+ imgInfo = self._pagesInfoVec[page]
+ return imgInfo.GetEnabled()
+
+
+ def EnableTab(self, page, enabled=True):
+ """
+ Enables or disables a tab.
+
+ :param `page`: an integer specifying the page index;
+ :param `enabled`: ``True`` to enable a tab, ``False`` to disable it.
+ """
+
+ if page >= len(self._pagesInfoVec):
+ return
+
+ imgInfo = self._pagesInfoVec[page]
+ imgInfo.EnableTab(enabled)
+
+
+ def ClearAll(self):
+ """ Deletes all the pages in the container. """
+
+ self._pagesInfoVec = []
+ self._nIndex = wx.NOT_FOUND
+
+
+ def DoDeletePage(self, page):
+ """
+ Does the actual page deletion.
+
+ :param `page`: the index of the tab.
+ """
+
+ # Remove the page from the vector
+ book = self.GetParent()
+ self._pagesInfoVec.pop(page)
+
+ if self._nIndex >= page:
+ self._nIndex = self._nIndex - 1
+
+ # The delete page was the last first on the array,
+ # but the book still has more pages, so we set the
+ # active page to be the first one (0)
+ if self._nIndex < 0 and len(self._pagesInfoVec) > 0:
+ self._nIndex = 0
+
+ # Refresh the tabs
+ if self._nIndex >= 0:
+
+ book._bForceSelection = True
+ book.SetSelection(self._nIndex)
+ book._bForceSelection = False
+
+ if not self._pagesInfoVec:
+ # Erase the page container drawings
+ dc = wx.ClientDC(self)
+ dc.Clear()
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`ImageContainerBase`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Refresh() # Call on paint
+ event.Skip()
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`ImageContainerBase`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def HitTest(self, pt):
+ """
+ Returns the index of the tab at the specified position or ``wx.NOT_FOUND``
+ if ``None``, plus the flag style of :meth:`~ImageContainerBase.HitTest`.
+
+ :param `pt`: an instance of :class:`Point`, to test for hits.
+
+ :return: The index of the tab at the specified position plus the hit test
+ flag, which can be one of the following bits:
+
+ ====================== ======= ================================
+ HitTest Flags Value Description
+ ====================== ======= ================================
+ ``IMG_OVER_IMG`` 0 The mouse is over the tab icon
+ ``IMG_OVER_PIN`` 1 The mouse is over the pin button
+ ``IMG_OVER_EW_BORDER`` 2 The mouse is over the east-west book border
+ ``IMG_NONE`` 3 Nowhere
+ ====================== ======= ================================
+
+ """
+
+ style = self.GetParent().GetAGWWindowStyleFlag()
+
+ if style & INB_USE_PIN_BUTTON:
+ if self._pinBtnRect.Contains(pt):
+ return -1, IMG_OVER_PIN
+
+ for i in xrange(len(self._pagesInfoVec)):
+
+ if self._pagesInfoVec[i].GetPosition() == wx.Point(-1, -1):
+ break
+
+ # For Web Hover style, we test the TextRect
+ if not self.HasAGWFlag(INB_WEB_HILITE):
+ buttonRect = wx.RectPS(self._pagesInfoVec[i].GetPosition(), self._pagesInfoVec[i].GetSize())
+ else:
+ buttonRect = self._pagesInfoVec[i].GetTextRect()
+
+ if buttonRect.Contains(pt):
+ return i, IMG_OVER_IMG
+
+ if self.PointOnSash(pt):
+ return -1, IMG_OVER_EW_BORDER
+ else:
+ return -1, IMG_NONE
+
+
+ def PointOnSash(self, pt):
+ """
+ Tests whether pt is located on the sash.
+
+ :param `pt`: an instance of :class:`Point`, to test for hits.
+ """
+
+ # Check if we are on a the sash border
+ cltRect = self.GetClientRect()
+
+ if self.HasAGWFlag(INB_LEFT) or self.HasAGWFlag(INB_TOP):
+ if pt.x > cltRect.x + cltRect.width - 4:
+ return True
+
+ else:
+ if pt.x < 4:
+ return True
+
+ return False
+
+
+ def OnMouseLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`ImageContainerBase`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ newSelection = -1
+ event.Skip()
+
+ # Support for collapse/expand
+ style = self.GetParent().GetAGWWindowStyleFlag()
+ if style & INB_USE_PIN_BUTTON:
+
+ if self._pinBtnRect.Contains(event.GetPosition()):
+
+ self._nPinButtonStatus = INB_PIN_PRESSED
+ dc = wx.ClientDC(self)
+ self.DrawPin(dc, self._pinBtnRect, not self._bCollapsed)
+ return
+
+ # Incase panel is collapsed, there is nothing
+ # to check
+ if self._bCollapsed:
+ return
+
+ tabIdx, where = self.HitTest(event.GetPosition())
+
+ if where == IMG_OVER_IMG:
+ self._nHoveredImgIdx = -1
+
+ if tabIdx == -1:
+ return
+
+ self.GetParent().SetSelection(tabIdx)
+
+
+ def OnMouseLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`ImageContainerBase`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ bRepaint = self._nHoveredImgIdx != -1
+ self._nHoveredImgIdx = -1
+
+ # Make sure the pin button status is NONE
+ # incase we were in pin button style
+ style = self.GetParent().GetAGWWindowStyleFlag()
+
+ if style & INB_USE_PIN_BUTTON:
+
+ self._nPinButtonStatus = INB_PIN_NONE
+ dc = wx.ClientDC(self)
+ self.DrawPin(dc, self._pinBtnRect, not self._bCollapsed)
+
+ # Restore cursor
+ wx.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+
+ if bRepaint:
+ self.Refresh()
+
+
+ def OnMouseLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`ImageContainerBase`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ style = self.GetParent().GetAGWWindowStyleFlag()
+
+ if style & INB_USE_PIN_BUTTON:
+
+ bIsLabelContainer = not self.CanDoBottomStyle()
+
+ if self._pinBtnRect.Contains(event.GetPosition()):
+
+ self._nPinButtonStatus = INB_PIN_NONE
+ self._bCollapsed = not self._bCollapsed
+
+ if self._bCollapsed:
+
+ # Save the current tab area width
+ self._tabAreaSize = self.GetSize()
+
+ if bIsLabelContainer:
+
+ self.SetSizeHints(20, self._tabAreaSize.y)
+
+ else:
+
+ if style & INB_BOTTOM or style & INB_TOP:
+ self.SetSizeHints(self._tabAreaSize.x, 20)
+ else:
+ self.SetSizeHints(20, self._tabAreaSize.y)
+
+ else:
+
+ if bIsLabelContainer:
+
+ self.SetSizeHints(self._tabAreaSize.x, -1)
+
+ else:
+
+ # Restore the tab area size
+ if style & INB_BOTTOM or style & INB_TOP:
+ self.SetSizeHints(-1, self._tabAreaSize.y)
+ else:
+ self.SetSizeHints(self._tabAreaSize.x, -1)
+
+ self.GetParent().GetSizer().Layout()
+ self.Refresh()
+ return
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`ImageContainerBase`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ style = self.GetParent().GetAGWWindowStyleFlag()
+ if style & INB_USE_PIN_BUTTON:
+
+ # Check to see if we are in the pin button rect
+ if not self._pinBtnRect.Contains(event.GetPosition()) and self._nPinButtonStatus == INB_PIN_PRESSED:
+
+ self._nPinButtonStatus = INB_PIN_NONE
+ dc = wx.ClientDC(self)
+ self.DrawPin(dc, self._pinBtnRect, not self._bCollapsed)
+
+ imgIdx, where = self.HitTest(event.GetPosition())
+
+ # Allow hovering unless over current tab or tab is disabled
+ self._nHoveredImgIdx = -1
+
+ if imgIdx < len(self._pagesInfoVec) and self.GetEnabled(imgIdx) and imgIdx != self._nIndex:
+ self._nHoveredImgIdx = imgIdx
+
+ if not self._bCollapsed:
+
+ if self._nHoveredImgIdx >= 0 and self.HasAGWFlag(INB_WEB_HILITE):
+
+ # Change the cursor to be Hand if we have the Web hover style set
+ wx.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+
+ elif not self.PointOnSash(event.GetPosition()):
+
+ # Restore the cursor if we are not currently hovering the sash
+ wx.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+
+ self.Refresh()
+
+
+ def DrawPin(self, dc, rect, downPin):
+ """
+ Draw a pin button, that allows collapsing of the image panel.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the pin button client rectangle;
+ :param `downPin`: ``True`` if the pin button is facing downwards, ``False``
+ if it is facing leftwards.
+ """
+
+ # Set the bitmap according to the button status
+
+ if downPin:
+ pinBmp = wx.BitmapFromXPMData(pin_down_xpm)
+ else:
+ pinBmp = wx.BitmapFromXPMData(pin_left_xpm)
+
+ xx = rect.x + 2
+
+ if self._nPinButtonStatus in [INB_PIN_HOVER, INB_PIN_NONE]:
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.BLACK_PEN)
+ dc.DrawRectangle(xx, rect.y, 16, 16)
+
+ # Draw upper and left border with grey colour
+ dc.SetPen(wx.WHITE_PEN)
+ dc.DrawLine(xx, rect.y, xx + 16, rect.y)
+ dc.DrawLine(xx, rect.y, xx, rect.y + 16)
+
+ elif self._nPinButtonStatus == INB_PIN_PRESSED:
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(wx.NamedColour("LIGHT GREY")))
+ dc.DrawRectangle(xx, rect.y, 16, 16)
+
+ # Draw upper and left border with grey colour
+ dc.SetPen(wx.BLACK_PEN)
+ dc.DrawLine(xx, rect.y, xx + 16, rect.y)
+ dc.DrawLine(xx, rect.y, xx, rect.y + 16)
+
+ # Set the masking
+ pinBmp.SetMask(wx.Mask(pinBmp, wx.WHITE))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(pinBmp, xx, rect.y, True)
+
+ # Save the pin rect
+ self._pinBtnRect = rect
+
+
+# ---------------------------------------------------------------------------- #
+# Class ImageContainer
+# ---------------------------------------------------------------------------- #
+
+class ImageContainer(ImageContainerBase):
+ """
+ Base class for :class:`FlatImageBook` image container.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=0, name="ImageContainer"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`Panel` window style;
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``INB_BOTTOM`` 0x1 Place labels below the page area. Available only for :class:`FlatImageBook`.
+ ``INB_LEFT`` 0x2 Place labels on the left side. Available only for :class:`FlatImageBook`.
+ ``INB_RIGHT`` 0x4 Place labels on the right side.
+ ``INB_TOP`` 0x8 Place labels above the page area.
+ ``INB_BORDER`` 0x10 Draws a border around :class:`LabelBook` or :class:`FlatImageBook`.
+ ``INB_SHOW_ONLY_TEXT`` 0x20 Shows only text labels and no images. Available only for :class:`LabelBook`.
+ ``INB_SHOW_ONLY_IMAGES`` 0x40 Shows only tab images and no label texts. Available only for :class:`LabelBook`.
+ ``INB_FIT_BUTTON`` 0x80 Displays a pin button to show/hide the book control.
+ ``INB_DRAW_SHADOW`` 0x100 Draw shadows below the book tabs. Available only for :class:`LabelBook`.
+ ``INB_USE_PIN_BUTTON`` 0x200 Displays a pin button to show/hide the book control.
+ ``INB_GRADIENT_BACKGROUND`` 0x400 Draws a gradient shading on the tabs background. Available only for :class:`LabelBook`.
+ ``INB_WEB_HILITE`` 0x800 On mouse hovering, tabs behave like html hyperlinks. Available only for :class:`LabelBook`.
+ ``INB_NO_RESIZE`` 0x1000 Don't allow resizing of the tab area.
+ ``INB_FIT_LABELTEXT`` 0x2000 Will fit the tab area to the longest text (or text+image if you have images) in all the tabs.
+ ``INB_BOLD_TAB_SELECTION`` 0x4000 Show the selected tab text using a bold font.
+ =========================== =========== ==================================================
+
+ :param `name`: the window name.
+ """
+
+ ImageContainerBase.__init__(self, parent, id, pos, size, style, agwStyle, name)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeaveWindow)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`ImageContainer`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ ImageContainerBase.OnSize(self, event)
+ event.Skip()
+
+
+ def OnMouseLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`ImageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ ImageContainerBase.OnMouseLeftDown(self, event)
+ event.Skip()
+
+
+ def OnMouseLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`ImageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ ImageContainerBase.OnMouseLeftUp(self, event)
+ event.Skip()
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`ImageContainer`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+ """
+
+ ImageContainerBase.OnEraseBackground(self, event)
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`ImageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ ImageContainerBase.OnMouseMove(self, event)
+ event.Skip()
+
+
+ def OnMouseLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`ImageContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ ImageContainerBase.OnMouseLeaveWindow(self, event)
+ event.Skip()
+
+
+ def CanDoBottomStyle(self):
+ """
+ Allows the parent to examine the children type. Some implementation
+ (such as :class:`LabelBook`), does not support top/bottom images, only left/right.
+ """
+
+ return True
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`ImageContainer`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+ style = self.GetParent().GetAGWWindowStyleFlag()
+
+ backBrush = wx.WHITE_BRUSH
+ if style & INB_BORDER:
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DSHADOW))
+ else:
+ borderPen = wx.TRANSPARENT_PEN
+
+ size = self.GetSize()
+
+ # Background
+ dc.SetBrush(backBrush)
+
+ borderPen.SetWidth(1)
+ dc.SetPen(borderPen)
+ dc.DrawRectangle(0, 0, size.x, size.y)
+ bUsePin = (style & INB_USE_PIN_BUTTON and [True] or [False])[0]
+
+ if bUsePin:
+
+ # Draw the pin button
+ clientRect = self.GetClientRect()
+ pinRect = wx.Rect(clientRect.GetX() + clientRect.GetWidth() - 20, 2, 20, 20)
+ self.DrawPin(dc, pinRect, not self._bCollapsed)
+
+ if self._bCollapsed:
+ return
+
+ borderPen = wx.BLACK_PEN
+ borderPen.SetWidth(1)
+ dc.SetPen(borderPen)
+ dc.DrawLine(0, size.y, size.x, size.y)
+ dc.DrawPoint(0, size.y)
+
+ clientSize = 0
+ bUseYcoord = (style & INB_RIGHT or style & INB_LEFT)
+
+ if bUseYcoord:
+ clientSize = size.GetHeight()
+ else:
+ clientSize = size.GetWidth()
+
+ # We reserver 20 pixels for the 'pin' button
+
+ # The drawing of the images start position. This is
+ # depenedent of the style, especially when Pin button
+ # style is requested
+
+ if bUsePin:
+ if style & INB_TOP or style & INB_BOTTOM:
+ pos = (style & INB_BORDER and [0] or [1])[0]
+ else:
+ pos = (style & INB_BORDER and [20] or [21])[0]
+ else:
+ pos = (style & INB_BORDER and [0] or [1])[0]
+
+ nPadding = 4 # Pad text with 2 pixels on the left and right
+ nTextPaddingLeft = 2
+
+ count = 0
+ normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont.SetWeight(wx.BOLD)
+
+ for i in xrange(len(self._pagesInfoVec)):
+
+ count = count + 1
+
+ # incase the 'fit button' style is applied, we set the rectangle width to the
+ # text width plus padding
+ # Incase the style IS applied, but the style is either LEFT or RIGHT
+ # we ignore it
+ dc.SetFont(normalFont)
+
+ if style & INB_BOLD_TAB_SELECTION and self._nIndex == i:
+ dc.SetFont(boldFont)
+
+ textWidth, textHeight = dc.GetTextExtent(self._pagesInfoVec[i].GetCaption())
+
+ # Default values for the surronounding rectangle
+ # around a button
+ rectWidth = self._nImgSize * 2 # To avoid the recangle to 'touch' the borders
+ rectHeight = self._nImgSize * 2
+
+ # Incase the style requires non-fixed button (fit to text)
+ # recalc the rectangle width
+ if style & INB_FIT_BUTTON and \
+ not ((style & INB_LEFT) or (style & INB_RIGHT)) and \
+ not self._pagesInfoVec[i].GetCaption() == "" and \
+ not (style & INB_SHOW_ONLY_IMAGES):
+
+ rectWidth = ((textWidth + nPadding * 2) > rectWidth and [nPadding * 2 + textWidth] or [rectWidth])[0]
+
+ # Make the width an even number
+ if rectWidth % 2 != 0:
+ rectWidth += 1
+
+ # Check that we have enough space to draw the button
+ # If Pin button is used, consider its space as well (applicable for top/botton style)
+ # since in the left/right, its size is already considered in 'pos'
+ pinBtnSize = (bUsePin and [20] or [0])[0]
+
+ if pos + rectWidth + pinBtnSize > clientSize:
+ break
+
+ # Calculate the button rectangle
+ modRectWidth = ((style & INB_LEFT or style & INB_RIGHT) and [rectWidth - 2] or [rectWidth])[0]
+ modRectHeight = ((style & INB_LEFT or style & INB_RIGHT) and [rectHeight] or [rectHeight - 2])[0]
+
+ if bUseYcoord:
+ buttonRect = wx.Rect(1, pos, modRectWidth, modRectHeight)
+ else:
+ buttonRect = wx.Rect(pos , 1, modRectWidth, modRectHeight)
+
+ # Check if we need to draw a rectangle around the button
+ if self._nIndex == i:
+
+ # Set the colours
+ penColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ brushColour = ArtManager.Get().LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION), 75)
+
+ dc.SetPen(wx.Pen(penColour))
+ dc.SetBrush(wx.Brush(brushColour))
+
+ # Fix the surrounding of the rect if border is set
+ if style & INB_BORDER:
+
+ if style & INB_TOP or style & INB_BOTTOM:
+ buttonRect = wx.Rect(buttonRect.x + 1, buttonRect.y, buttonRect.width - 1, buttonRect.height)
+ else:
+ buttonRect = wx.Rect(buttonRect.x, buttonRect.y + 1, buttonRect.width, buttonRect.height - 1)
+
+ dc.DrawRectangleRect(buttonRect)
+
+ if self._nHoveredImgIdx == i:
+
+ # Set the colours
+ penColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ brushColour = ArtManager.Get().LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION), 90)
+
+ dc.SetPen(wx.Pen(penColour))
+ dc.SetBrush(wx.Brush(brushColour))
+
+ # Fix the surrounding of the rect if border is set
+ if style & INB_BORDER:
+
+ if style & INB_TOP or style & INB_BOTTOM:
+ buttonRect = wx.Rect(buttonRect.x + 1, buttonRect.y, buttonRect.width - 1, buttonRect.height)
+ else:
+ buttonRect = wx.Rect(buttonRect.x, buttonRect.y + 1, buttonRect.width, buttonRect.height - 1)
+
+ dc.DrawRectangleRect(buttonRect)
+
+ if bUseYcoord:
+ rect = wx.Rect(0, pos, rectWidth, rectWidth)
+ else:
+ rect = wx.Rect(pos, 0, rectWidth, rectWidth)
+
+ # Incase user set both flags:
+ # INB_SHOW_ONLY_TEXT and INB_SHOW_ONLY_IMAGES
+ # We override them to display both
+
+ if style & INB_SHOW_ONLY_TEXT and style & INB_SHOW_ONLY_IMAGES:
+
+ style ^= INB_SHOW_ONLY_TEXT
+ style ^= INB_SHOW_ONLY_IMAGES
+ self.GetParent().SetAGWWindowStyleFlag(style)
+
+ # Draw the caption and text
+ imgTopPadding = 10
+ if not style & INB_SHOW_ONLY_TEXT and self._pagesInfoVec[i].GetImageIndex() != -1:
+
+ if bUseYcoord:
+
+ imgXcoord = self._nImgSize / 2
+ imgYcoord = (style & INB_SHOW_ONLY_IMAGES and [pos + self._nImgSize / 2] or [pos + imgTopPadding])[0]
+
+ else:
+
+ imgXcoord = pos + (rectWidth / 2) - (self._nImgSize / 2)
+ imgYcoord = (style & INB_SHOW_ONLY_IMAGES and [self._nImgSize / 2] or [imgTopPadding])[0]
+
+ self._ImageList.Draw(self._pagesInfoVec[i].GetImageIndex(), dc,
+ imgXcoord, imgYcoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ # Draw the text
+ if not style & INB_SHOW_ONLY_IMAGES and not self._pagesInfoVec[i].GetCaption() == "":
+
+ if style & INB_BOLD_TAB_SELECTION and self._nIndex == i:
+ dc.SetFont(boldFont)
+ else:
+ dc.SetFont(normalFont)
+
+ # Check if the text can fit the size of the rectangle,
+ # if not truncate it
+ fixedText = self._pagesInfoVec[i].GetCaption()
+ if not style & INB_FIT_BUTTON or (style & INB_LEFT or (style & INB_RIGHT)):
+
+ fixedText = self.FixTextSize(dc, self._pagesInfoVec[i].GetCaption(), self._nImgSize *2 - 4)
+
+ # Update the length of the text
+ textWidth, textHeight = dc.GetTextExtent(fixedText)
+
+ if bUseYcoord:
+
+ textOffsetX = ((rectWidth - textWidth) / 2 )
+ textOffsetY = (not style & INB_SHOW_ONLY_TEXT and [pos + self._nImgSize + imgTopPadding + 3] or \
+ [pos + ((self._nImgSize * 2 - textHeight) / 2 )])[0]
+
+ else:
+
+ textOffsetX = (rectWidth - textWidth) / 2 + pos + nTextPaddingLeft
+ textOffsetY = (not style & INB_SHOW_ONLY_TEXT and [self._nImgSize + imgTopPadding + 3] or \
+ [((self._nImgSize * 2 - textHeight) / 2 )])[0]
+
+ dc.SetTextForeground(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT))
+ dc.DrawText(fixedText, textOffsetX, textOffsetY)
+
+ # Update the page info
+ self._pagesInfoVec[i].SetPosition(buttonRect.GetPosition())
+ self._pagesInfoVec[i].SetSize(buttonRect.GetSize())
+
+ pos += rectWidth
+
+ # Update all buttons that can not fit into the screen as non-visible
+ for ii in xrange(count, len(self._pagesInfoVec)):
+ self._pagesInfoVec[ii].SetPosition(wx.Point(-1, -1))
+
+ # Draw the pin button
+ if bUsePin:
+
+ clientRect = self.GetClientRect()
+ pinRect = wx.Rect(clientRect.GetX() + clientRect.GetWidth() - 20, 2, 20, 20)
+ self.DrawPin(dc, pinRect, not self._bCollapsed)
+
+
+# ---------------------------------------------------------------------------- #
+# Class LabelContainer
+# ---------------------------------------------------------------------------- #
+
+class LabelContainer(ImageContainerBase):
+ """ Base class for :class:`LabelBook`. """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=0, name="LabelContainer"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`Panel` window style;
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``INB_BOTTOM`` 0x1 Place labels below the page area. Available only for :class:`FlatImageBook`.
+ ``INB_LEFT`` 0x2 Place labels on the left side. Available only for :class:`FlatImageBook`.
+ ``INB_RIGHT`` 0x4 Place labels on the right side.
+ ``INB_TOP`` 0x8 Place labels above the page area.
+ ``INB_BORDER`` 0x10 Draws a border around :class:`LabelBook` or :class:`FlatImageBook`.
+ ``INB_SHOW_ONLY_TEXT`` 0x20 Shows only text labels and no images. Available only for :class:`LabelBook`.
+ ``INB_SHOW_ONLY_IMAGES`` 0x40 Shows only tab images and no label texts. Available only for :class:`LabelBook`.
+ ``INB_FIT_BUTTON`` 0x80 Displays a pin button to show/hide the book control.
+ ``INB_DRAW_SHADOW`` 0x100 Draw shadows below the book tabs. Available only for :class:`LabelBook`.
+ ``INB_USE_PIN_BUTTON`` 0x200 Displays a pin button to show/hide the book control.
+ ``INB_GRADIENT_BACKGROUND`` 0x400 Draws a gradient shading on the tabs background. Available only for :class:`LabelBook`.
+ ``INB_WEB_HILITE`` 0x800 On mouse hovering, tabs behave like html hyperlinks. Available only for :class:`LabelBook`.
+ ``INB_NO_RESIZE`` 0x1000 Don't allow resizing of the tab area.
+ ``INB_FIT_LABELTEXT`` 0x2000 Will fit the tab area to the longest text (or text+image if you have images) in all the tabs.
+ ``INB_BOLD_TAB_SELECTION`` 0x4000 Show the selected tab text using a bold font.
+ =========================== =========== ==================================================
+
+ :param `name`: the window name.
+ """
+
+ ImageContainerBase.__init__(self, parent, id, pos, size, style, agwStyle, name)
+ self._nTabAreaWidth = 100
+ self._oldCursor = wx.NullCursor
+ self._coloursMap = {}
+ self._skin = wx.NullBitmap
+ self._sashRect = wx.Rect()
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeaveWindow)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`LabelContainer`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ ImageContainerBase.OnSize(self, event)
+ event.Skip()
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`LabelContainer`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+ """
+
+ ImageContainerBase.OnEraseBackground(self, event)
+
+
+ def GetTabAreaWidth(self):
+ """ Returns the width of the tab area. """
+
+ return self._nTabAreaWidth
+
+
+ def SetTabAreaWidth(self, width):
+ """
+ Sets the width of the tab area.
+
+ :param `width`: the width of the tab area, in pixels.
+ """
+
+ self._nTabAreaWidth = width
+
+
+ def CanDoBottomStyle(self):
+ """
+ Allows the parent to examine the children type. Some implementation
+ (such as :class:`LabelBook`), does not support top/bottom images, only left/right.
+ """
+
+ return False
+
+
+ def SetBackgroundBitmap(self, bmp):
+ """
+ Sets the background bitmap for the control.
+
+ :param `bmp`: a valid :class:`Bitmap` object.
+ """
+
+ self._skin = bmp
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`LabelContainer`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ style = self.GetParent().GetAGWWindowStyleFlag()
+
+ dc = wx.BufferedPaintDC(self)
+ backBrush = wx.Brush(self._coloursMap[INB_TAB_AREA_BACKGROUND_COLOUR])
+ if self.HasAGWFlag(INB_BORDER):
+ borderPen = wx.Pen(self._coloursMap[INB_TABS_BORDER_COLOUR])
+ else:
+ borderPen = wx.TRANSPARENT_PEN
+
+ size = self.GetSize()
+
+ # Set the pen & brush
+ dc.SetBrush(backBrush)
+ dc.SetPen(borderPen)
+
+ # Incase user set both flags, we override them to display both
+ # INB_SHOW_ONLY_TEXT and INB_SHOW_ONLY_IMAGES
+ if style & INB_SHOW_ONLY_TEXT and style & INB_SHOW_ONLY_IMAGES:
+
+ style ^= INB_SHOW_ONLY_TEXT
+ style ^= INB_SHOW_ONLY_IMAGES
+ self.GetParent().SetAGWWindowStyleFlag(style)
+
+ if self.HasAGWFlag(INB_GRADIENT_BACKGROUND) and not self._skin.Ok():
+
+ # Draw graident in the background area
+ startColour = self._coloursMap[INB_TAB_AREA_BACKGROUND_COLOUR]
+ endColour = ArtManager.Get().LightColour(self._coloursMap[INB_TAB_AREA_BACKGROUND_COLOUR], 50)
+ ArtManager.Get().PaintStraightGradientBox(dc, wx.Rect(0, 0, size.x / 2, size.y), startColour, endColour, False)
+ ArtManager.Get().PaintStraightGradientBox(dc, wx.Rect(size.x / 2, 0, size.x / 2, size.y), endColour, startColour, False)
+
+ else:
+
+ # Draw the border and background
+ if self._skin.Ok():
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ self.DrawBackgroundBitmap(dc)
+
+ dc.DrawRectangleRect(wx.Rect(0, 0, size.x, size.y))
+
+ # Draw border
+ if self.HasAGWFlag(INB_BORDER) and self.HasAGWFlag(INB_GRADIENT_BACKGROUND):
+
+ # Just draw the border with transparent brush
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangleRect(wx.Rect(0, 0, size.x, size.y))
+
+ bUsePin = (self.HasAGWFlag(INB_USE_PIN_BUTTON) and [True] or [False])[0]
+
+ if bUsePin:
+
+ # Draw the pin button
+ clientRect = self.GetClientRect()
+ pinRect = wx.Rect(clientRect.GetX() + clientRect.GetWidth() - 20, 2, 20, 20)
+ self.DrawPin(dc, pinRect, not self._bCollapsed)
+
+ if self._bCollapsed:
+ return
+
+ dc.SetPen(wx.BLACK_PEN)
+ self.SetSizeHints(self._nTabAreaWidth, -1)
+
+ # We reserve 20 pixels for the pin button
+ posy = 20
+ count = 0
+
+ for i in xrange(len(self._pagesInfoVec)):
+ count = count+1
+ # Default values for the surronounding rectangle
+ # around a button
+ rectWidth = self._nTabAreaWidth
+
+ if self.HasAGWFlag(INB_SHOW_ONLY_TEXT):
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetPointSize(font.GetPointSize() * self.GetParent().GetFontSizeMultiple())
+
+ if self.GetParent().GetFontBold():
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ elif self.HasAGWFlag(INB_BOLD_TAB_SELECTION) and self._nIndex == i:
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+
+ dc.SetFont(font)
+ w, h = dc.GetTextExtent(self._pagesInfoVec[i].GetCaption())
+ rectHeight = h * 2
+ else:
+ rectHeight = self._nImgSize * 2
+
+ # Check that we have enough space to draw the button
+ if posy + rectHeight > size.GetHeight():
+ break
+
+ # Calculate the button rectangle
+ posx = 0
+
+ buttonRect = wx.Rect(posx, posy, rectWidth, rectHeight)
+ indx = self._pagesInfoVec[i].GetImageIndex()
+
+ if indx == -1:
+ bmp = wx.NullBitmap
+ else:
+ bmp = self._ImageList.GetBitmap(indx)
+
+ self.DrawLabel(dc, buttonRect, self._pagesInfoVec[i].GetCaption(), bmp,
+ self._pagesInfoVec[i], self.HasAGWFlag(INB_LEFT) or self.HasAGWFlag(INB_TOP),
+ i, self._nIndex == i, self._nHoveredImgIdx == i)
+
+ posy += rectHeight
+
+ # Update all buttons that can not fit into the screen as non-visible
+ for ii in xrange(count, len(self._pagesInfoVec)):
+ self._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
+
+ if bUsePin:
+
+ clientRect = self.GetClientRect()
+ pinRect = wx.Rect(clientRect.GetX() + clientRect.GetWidth() - 20, 2, 20, 20)
+ self.DrawPin(dc, pinRect, not self._bCollapsed)
+
+
+ def DrawBackgroundBitmap(self, dc):
+ """
+ Draws a bitmap as the background of the control.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ clientRect = self.GetClientRect()
+ width = clientRect.GetWidth()
+ height = clientRect.GetHeight()
+ coveredY = coveredX = 0
+ xstep = self._skin.GetWidth()
+ ystep = self._skin.GetHeight()
+ bmpRect = wx.Rect(0, 0, xstep, ystep)
+ if bmpRect != clientRect:
+
+ mem_dc = wx.MemoryDC()
+ bmp = wx.EmptyBitmap(width, height)
+ mem_dc.SelectObject(bmp)
+
+ while coveredY < height:
+
+ while coveredX < width:
+
+ mem_dc.DrawBitmap(self._skin, coveredX, coveredY, True)
+ coveredX += xstep
+
+ coveredX = 0
+ coveredY += ystep
+
+ mem_dc.SelectObject(wx.NullBitmap)
+ #self._skin = bmp
+ dc.DrawBitmap(bmp, 0, 0)
+
+ else:
+
+ dc.DrawBitmap(self._skin, 0, 0)
+
+
+ def OnMouseLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`LabelContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.HasAGWFlag(INB_NO_RESIZE):
+
+ ImageContainerBase.OnMouseLeftUp(self, event)
+ return
+
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+ # Sash was being dragged?
+ if not self._sashRect.IsEmpty():
+
+ # Remove sash
+ ArtManager.Get().DrawDragSash(self._sashRect)
+ self.Resize(event)
+
+ self._sashRect = wx.Rect()
+ return
+
+ self._sashRect = wx.Rect()
+
+ # Restore cursor
+ if self._oldCursor.Ok():
+
+ wx.SetCursor(self._oldCursor)
+ self._oldCursor = wx.NullCursor
+
+ ImageContainerBase.OnMouseLeftUp(self, event)
+
+
+ def Resize(self, event):
+ """
+ Actually resizes the tab area.
+
+ :param `event`: an instance of :class:`SizeEvent`.
+ """
+
+ # Resize our size
+ self._tabAreaSize = self.GetSize()
+ newWidth = self._tabAreaSize.x
+ x = event.GetX()
+
+ if self.HasAGWFlag(INB_BOTTOM) or self.HasAGWFlag(INB_RIGHT):
+
+ newWidth -= event.GetX()
+
+ else:
+
+ newWidth = x
+
+ if newWidth < 100: # Dont allow width to be lower than that
+ newWidth = 100
+
+ self.SetSizeHints(newWidth, self._tabAreaSize.y)
+
+ # Update the tab new area width
+ self._nTabAreaWidth = newWidth
+ self.GetParent().Freeze()
+ self.GetParent().GetSizer().Layout()
+ self.GetParent().Thaw()
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`LabelContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.HasAGWFlag(INB_NO_RESIZE):
+
+ ImageContainerBase.OnMouseMove(self, event)
+ return
+
+ # Remove old sash
+ if not self._sashRect.IsEmpty():
+ ArtManager.Get().DrawDragSash(self._sashRect)
+
+ if event.LeftIsDown():
+
+ if not self._sashRect.IsEmpty():
+
+ # Progress sash, and redraw it
+ clientRect = self.GetClientRect()
+ pt = self.ClientToScreen(wx.Point(event.GetX(), 0))
+ self._sashRect = wx.RectPS(pt, wx.Size(4, clientRect.height))
+ ArtManager.Get().DrawDragSash(self._sashRect)
+
+ else:
+
+ # Sash is not being dragged
+ if self._oldCursor.Ok():
+ wx.SetCursor(self._oldCursor)
+ self._oldCursor = wx.NullCursor
+
+ else:
+
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+ if self.PointOnSash(event.GetPosition()):
+
+ # Change cursor to EW cursor
+ self._oldCursor = self.GetCursor()
+ wx.SetCursor(wx.StockCursor(wx.CURSOR_SIZEWE))
+
+ elif self._oldCursor.Ok():
+
+ wx.SetCursor(self._oldCursor)
+ self._oldCursor = wx.NullCursor
+
+ self._sashRect = wx.Rect()
+ ImageContainerBase.OnMouseMove(self, event)
+
+
+ def OnMouseLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`LabelContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.HasAGWFlag(INB_NO_RESIZE):
+
+ ImageContainerBase.OnMouseLeftDown(self, event)
+ return
+
+ imgIdx, where = self.HitTest(event.GetPosition())
+
+ if IMG_OVER_EW_BORDER == where and not self._bCollapsed:
+
+ # We are over the sash
+ if not self._sashRect.IsEmpty():
+ ArtManager.Get().DrawDragSash(self._sashRect)
+ else:
+ # first time, begin drawing sash
+ self.CaptureMouse()
+
+ # Change mouse cursor
+ self._oldCursor = self.GetCursor()
+ wx.SetCursor(wx.StockCursor(wx.CURSOR_SIZEWE))
+
+ clientRect = self.GetClientRect()
+ pt = self.ClientToScreen(wx.Point(event.GetX(), 0))
+ self._sashRect = wx.RectPS(pt, wx.Size(4, clientRect.height))
+
+ ArtManager.Get().DrawDragSash(self._sashRect)
+
+ else:
+ ImageContainerBase.OnMouseLeftDown(self, event)
+
+
+ def OnMouseLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`LabelContainer`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.HasAGWFlag(INB_NO_RESIZE):
+
+ ImageContainerBase.OnMouseLeaveWindow(self, event)
+ return
+
+ # If Sash is being dragged, ignore this event
+ if not self.HasCapture():
+ ImageContainerBase.OnMouseLeaveWindow(self, event)
+
+
+ def DrawRegularHover(self, dc, rect):
+ """
+ Draws a rounded rectangle around the current tab.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the current tab client rectangle.
+ """
+
+ # The hovered tab with default border
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(wx.WHITE))
+
+ # We draw CCW
+ if self.HasAGWFlag(INB_RIGHT) or self.HasAGWFlag(INB_TOP):
+
+ # Right images
+ # Upper line
+ dc.DrawLine(rect.x + 1, rect.y, rect.x + rect.width, rect.y)
+
+ # Right line (white)
+ dc.DrawLine(rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + rect.height)
+
+ # Bottom diagnol - we change pen
+ dc.SetPen(wx.Pen(self._coloursMap[INB_TABS_BORDER_COLOUR]))
+
+ # Bottom line
+ dc.DrawLine(rect.x + rect.width, rect.y + rect.height, rect.x, rect.y + rect.height)
+
+ else:
+
+ # Left images
+ # Upper line white
+ dc.DrawLine(rect.x, rect.y, rect.x + rect.width - 1, rect.y)
+
+ # Left line
+ dc.DrawLine(rect.x, rect.y, rect.x, rect.y + rect.height)
+
+ # Bottom diagnol, we change the pen
+ dc.SetPen(wx.Pen(self._coloursMap[INB_TABS_BORDER_COLOUR]))
+
+ # Bottom line
+ dc.DrawLine(rect.x, rect.y + rect.height, rect.x + rect.width, rect.y + rect.height)
+
+
+ def DrawWebHover(self, dc, caption, xCoord, yCoord, selected):
+ """
+ Draws a web style hover effect (cursor set to hand & text is underlined).
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `caption`: the tab caption text;
+ :param `xCoord`: the x position of the tab caption;
+ :param `yCoord`: the y position of the tab caption;
+ :param `selected`: ``True`` if the tab is selected, ``False`` otherwise.
+ """
+
+ # Redraw the text with underlined font
+ underLinedFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ underLinedFont.SetPointSize(underLinedFont.GetPointSize() * self.GetParent().GetFontSizeMultiple())
+ if self.GetParent().GetFontBold():
+ underLinedFont.SetWeight(wx.FONTWEIGHT_BOLD)
+ elif self.HasAGWFlag(INB_BOLD_TAB_SELECTION) and selected:
+ underLinedFont.SetWeight(wx.FONTWEIGHT_BOLD)
+
+ underLinedFont.SetUnderlined(True)
+ dc.SetFont(underLinedFont)
+ dc.DrawText(caption, xCoord, yCoord)
+
+
+ def SetColour(self, which, colour):
+ """
+ Sets a colour for a parameter.
+
+ :param `which`: can be one of the following parameters:
+
+ ================================== ======= ==================================
+ Colour Key Value Description
+ ================================== ======= ==================================
+ ``INB_TAB_AREA_BACKGROUND_COLOUR`` 100 The tab area background colour
+ ``INB_ACTIVE_TAB_COLOUR`` 101 The active tab background colour
+ ``INB_TABS_BORDER_COLOUR`` 102 The tabs border colour
+ ``INB_TEXT_COLOUR`` 103 The tab caption text colour
+ ``INB_ACTIVE_TEXT_COLOUR`` 104 The active tab caption text colour
+ ``INB_HILITE_TAB_COLOUR`` 105 The tab caption highlight text colour
+ ================================== ======= ==================================
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._coloursMap[which] = colour
+
+
+ def GetColour(self, which):
+ """
+ Returns a colour for a parameter.
+
+ :param `which`: the colour key.
+
+ :see: :meth:`~LabelContainer.SetColour` for a list of valid colour keys.
+ """
+
+ if not self._coloursMap.has_key(which):
+ return wx.Colour()
+
+ return self._coloursMap[which]
+
+
+ def InitializeColours(self):
+ """ Initializes the colours map to be used for this control. """
+
+ # Initialize map colours
+ self._coloursMap.update({INB_TAB_AREA_BACKGROUND_COLOUR: ArtManager.Get().LightColour(ArtManager.Get().FrameColour(), 50)})
+ self._coloursMap.update({INB_ACTIVE_TAB_COLOUR: ArtManager.Get().GetMenuFaceColour()})
+ self._coloursMap.update({INB_TABS_BORDER_COLOUR: wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DSHADOW)})
+ self._coloursMap.update({INB_HILITE_TAB_COLOUR: wx.NamedColour("LIGHT BLUE")})
+ self._coloursMap.update({INB_TEXT_COLOUR: wx.WHITE})
+ self._coloursMap.update({INB_ACTIVE_TEXT_COLOUR: wx.BLACK})
+
+ # dont allow bright colour one on the other
+ if not ArtManager.Get().IsDark(self._coloursMap[INB_TAB_AREA_BACKGROUND_COLOUR]) and \
+ not ArtManager.Get().IsDark(self._coloursMap[INB_TEXT_COLOUR]):
+
+ self._coloursMap[INB_TEXT_COLOUR] = ArtManager.Get().DarkColour(self._coloursMap[INB_TEXT_COLOUR], 100)
+
+
+ def DrawLabel(self, dc, rect, text, bmp, imgInfo, orientationLeft, imgIdx, selected, hover):
+ """
+ Draws a label using the specified dc.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the text client rectangle;
+ :param `text`: the actual text string;
+ :param `bmp`: a bitmap to be drawn next to the text;
+ :param `imgInfo`: an instance of :class:`ImageInfo`;
+ :param `orientationLeft`: ``True`` if the book has the ``INB_RIGHT`` or ``INB_LEFT``
+ style set;
+ :param `imgIdx`: the tab image index;
+ :param `selected`: ``True`` if the tab is selected, ``False`` otherwise;
+ :param `hover`: ``True`` if the tab is being hovered with the mouse, ``False`` otherwise.
+ """
+
+ dcsaver = DCSaver(dc)
+ nPadding = 6
+
+ if orientationLeft:
+
+ rect.x += nPadding
+ rect.width -= nPadding
+
+ else:
+
+ rect.width -= nPadding
+
+ textRect = wx.Rect(*rect)
+ imgRect = wx.Rect(*rect)
+
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetPointSize(font.GetPointSize() * self.GetParent().GetFontSizeMultiple())
+
+ if self.GetParent().GetFontBold():
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ elif self.HasAGWFlag(INB_BOLD_TAB_SELECTION) and selected:
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+
+ dc.SetFont(font)
+
+ # First we define the rectangle for the text
+ w, h = dc.GetTextExtent(text)
+
+ #-------------------------------------------------------------------------
+ # Label layout:
+ # [ nPadding | Image | nPadding | Text | nPadding ]
+ #-------------------------------------------------------------------------
+
+ # Text bounding rectangle
+ textRect.x += nPadding
+ textRect.y = rect.y + (rect.height - h)/2
+ textRect.width = rect.width - 2 * nPadding
+
+ if bmp.Ok() and not self.HasAGWFlag(INB_SHOW_ONLY_TEXT):
+ textRect.x += (bmp.GetWidth() + nPadding)
+ textRect.width -= (bmp.GetWidth() + nPadding)
+
+ textRect.height = h
+
+ # Truncate text if needed
+ caption = ArtManager.Get().TruncateText(dc, text, textRect.width)
+
+ # Image bounding rectangle
+ if bmp.Ok() and not self.HasAGWFlag(INB_SHOW_ONLY_TEXT):
+
+ imgRect.x += nPadding
+ imgRect.width = bmp.GetWidth()
+ imgRect.y = rect.y + (rect.height - bmp.GetHeight())/2
+ imgRect.height = bmp.GetHeight()
+
+ # Draw bounding rectangle
+ if selected:
+
+ # First we colour the tab
+ dc.SetBrush(wx.Brush(self._coloursMap[INB_ACTIVE_TAB_COLOUR]))
+
+ if self.HasAGWFlag(INB_BORDER):
+ dc.SetPen(wx.Pen(self._coloursMap[INB_TABS_BORDER_COLOUR]))
+ else:
+ dc.SetPen(wx.Pen(self._coloursMap[INB_ACTIVE_TAB_COLOUR]))
+
+ labelRect = wx.Rect(*rect)
+
+ if orientationLeft:
+ labelRect.width += 3
+ else:
+ labelRect.width += 3
+ labelRect.x -= 3
+
+ dc.DrawRoundedRectangleRect(labelRect, 3)
+
+ if not orientationLeft and self.HasAGWFlag(INB_DRAW_SHADOW):
+ dc.SetPen(wx.BLACK_PEN)
+ dc.DrawPoint(labelRect.x + labelRect.width - 1, labelRect.y + labelRect.height - 1)
+
+ # Draw the text & bitmap
+ if caption != "":
+
+ if selected:
+ dc.SetTextForeground(self._coloursMap[INB_ACTIVE_TEXT_COLOUR])
+ else:
+ dc.SetTextForeground(self._coloursMap[INB_TEXT_COLOUR])
+
+ dc.DrawText(caption, textRect.x, textRect.y)
+ imgInfo.SetTextRect(textRect)
+
+ else:
+
+ imgInfo.SetTextRect(wx.Rect())
+
+ if bmp.Ok() and not self.HasAGWFlag(INB_SHOW_ONLY_TEXT):
+ dc.DrawBitmap(bmp, imgRect.x, imgRect.y, True)
+
+ # Drop shadow
+ if self.HasAGWFlag(INB_DRAW_SHADOW) and selected:
+
+ sstyle = 0
+ if orientationLeft:
+ sstyle = BottomShadow
+ else:
+ sstyle = BottomShadowFull | RightShadow
+
+ if self.HasAGWFlag(INB_WEB_HILITE):
+
+ # Always drop shadow for this style
+ ArtManager.Get().DrawBitmapShadow(dc, rect, sstyle)
+
+ else:
+
+ if imgIdx+1 != self._nHoveredImgIdx:
+ ArtManager.Get().DrawBitmapShadow(dc, rect, sstyle)
+
+ # Draw hover effect
+ if hover:
+
+ if self.HasAGWFlag(INB_WEB_HILITE) and caption != "":
+ self.DrawWebHover(dc, caption, textRect.x, textRect.y, selected)
+ else:
+ self.DrawRegularHover(dc, rect)
+
+ # Update the page information bout position and size
+ imgInfo.SetPosition(rect.GetPosition())
+ imgInfo.SetSize(rect.GetSize())
+
+
+# ---------------------------------------------------------------------------- #
+# Class FlatBookBase
+# ---------------------------------------------------------------------------- #
+
+class FlatBookBase(wx.Panel):
+ """ Base class for the containing window for :class:`LabelBook` and :class:`FlatImageBook`. """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=0, name="FlatBookBase"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`Panel` window style;
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``INB_BOTTOM`` 0x1 Place labels below the page area. Available only for :class:`FlatImageBook`.
+ ``INB_LEFT`` 0x2 Place labels on the left side. Available only for :class:`FlatImageBook`.
+ ``INB_RIGHT`` 0x4 Place labels on the right side.
+ ``INB_TOP`` 0x8 Place labels above the page area.
+ ``INB_BORDER`` 0x10 Draws a border around :class:`LabelBook` or :class:`FlatImageBook`.
+ ``INB_SHOW_ONLY_TEXT`` 0x20 Shows only text labels and no images. Available only for :class:`LabelBook`.
+ ``INB_SHOW_ONLY_IMAGES`` 0x40 Shows only tab images and no label texts. Available only for :class:`LabelBook`.
+ ``INB_FIT_BUTTON`` 0x80 Displays a pin button to show/hide the book control.
+ ``INB_DRAW_SHADOW`` 0x100 Draw shadows below the book tabs. Available only for :class:`LabelBook`.
+ ``INB_USE_PIN_BUTTON`` 0x200 Displays a pin button to show/hide the book control.
+ ``INB_GRADIENT_BACKGROUND`` 0x400 Draws a gradient shading on the tabs background. Available only for :class:`LabelBook`.
+ ``INB_WEB_HILITE`` 0x800 On mouse hovering, tabs behave like html hyperlinks. Available only for :class:`LabelBook`.
+ ``INB_NO_RESIZE`` 0x1000 Don't allow resizing of the tab area.
+ ``INB_FIT_LABELTEXT`` 0x2000 Will fit the tab area to the longest text (or text+image if you have images) in all the tabs.
+ ``INB_BOLD_TAB_SELECTION`` 0x4000 Show the selected tab text using a bold font.
+ =========================== =========== ==================================================
+
+ :param `name`: the window name.
+ """
+
+ self._pages = None
+ self._bInitializing = True
+ self._pages = None
+ self._bForceSelection = False
+ self._windows = []
+ self._fontSizeMultiple = 1.0
+ self._fontBold = False
+
+ style |= wx.TAB_TRAVERSAL
+ self._agwStyle = agwStyle
+
+ wx.Panel.__init__(self, parent, id, pos, size, style, name)
+ self._bInitializing = False
+
+ self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
+ self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, lambda evt: True)
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the window style.
+
+ :param `agwStyle`: can be a combination of the following bits:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``INB_BOTTOM`` 0x1 Place labels below the page area. Available only for :class:`FlatImageBook`.
+ ``INB_LEFT`` 0x2 Place labels on the left side. Available only for :class:`FlatImageBook`.
+ ``INB_RIGHT`` 0x4 Place labels on the right side.
+ ``INB_TOP`` 0x8 Place labels above the page area.
+ ``INB_BORDER`` 0x10 Draws a border around :class:`LabelBook` or :class:`FlatImageBook`.
+ ``INB_SHOW_ONLY_TEXT`` 0x20 Shows only text labels and no images. Available only for :class:`LabelBook`.
+ ``INB_SHOW_ONLY_IMAGES`` 0x40 Shows only tab images and no label texts. Available only for :class:`LabelBook`.
+ ``INB_FIT_BUTTON`` 0x80 Displays a pin button to show/hide the book control.
+ ``INB_DRAW_SHADOW`` 0x100 Draw shadows below the book tabs. Available only for :class:`LabelBook`.
+ ``INB_USE_PIN_BUTTON`` 0x200 Displays a pin button to show/hide the book control.
+ ``INB_GRADIENT_BACKGROUND`` 0x400 Draws a gradient shading on the tabs background. Available only for :class:`LabelBook`.
+ ``INB_WEB_HILITE`` 0x800 On mouse hovering, tabs behave like html hyperlinks. Available only for :class:`LabelBook`.
+ ``INB_NO_RESIZE`` 0x1000 Don't allow resizing of the tab area.
+ ``INB_FIT_LABELTEXT`` 0x2000 Will fit the tab area to the longest text (or text+image if you have images) in all the tabs.
+ ``INB_BOLD_TAB_SELECTION`` 0x4000 Show the selected tab text using a bold font.
+ =========================== =========== ==================================================
+
+ """
+
+ self._agwStyle = agwStyle
+
+ # Check that we are not in initialization process
+ if self._bInitializing:
+ return
+
+ if not self._pages:
+ return
+
+ # Detach the windows attached to the sizer
+ if self.GetSelection() >= 0:
+ self._mainSizer.Detach(self._windows[self.GetSelection()])
+
+ self._mainSizer.Detach(self._pages)
+
+ if isinstance(self, LabelBook):
+ self._mainSizer = wx.BoxSizer(wx.HORIZONTAL)
+ else:
+ if agwStyle & INB_LEFT or agwStyle & INB_RIGHT:
+ self._mainSizer = wx.BoxSizer(wx.HORIZONTAL)
+ else:
+ self._mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ self.SetSizer(self._mainSizer)
+
+ # Add the tab container and the separator
+ self._mainSizer.Add(self._pages, 0, wx.EXPAND)
+
+ if isinstance(self, FlatImageBook):
+ if agwStyle & INB_LEFT or agwStyle & INB_RIGHT:
+ self._pages.SetSizeHints(self._pages._nImgSize * 2, -1)
+ else:
+ self._pages.SetSizeHints(-1, self._pages._nImgSize * 2)
+
+ # Attach the windows back to the sizer to the sizer
+ if self.GetSelection() >= 0:
+ self.DoSetSelection(self._windows[self.GetSelection()])
+
+ if agwStyle & INB_FIT_LABELTEXT:
+ self.ResizeTabArea()
+
+ self._mainSizer.Layout()
+ dummy = wx.SizeEvent()
+ wx.PostEvent(self, dummy)
+ self._pages.Refresh()
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`FlatBookBase` window style.
+
+ :see: :meth:`~FlatBookBase.SetAGWWindowStyleFlag` for a list of possible window style flags.
+ """
+
+ return self._agwStyle
+
+
+ def HasAGWFlag(self, flag):
+ """
+ Returns whether a flag is present in the :class:`FlatBookBase` style.
+
+ :param `flag`: one of the possible :class:`FlatBookBase` window styles.
+
+ :see: :meth:`~FlatBookBase.SetAGWWindowStyleFlag` for a list of possible window style flags.
+ """
+
+ agwStyle = self.GetAGWWindowStyleFlag()
+ res = (agwStyle & flag and [True] or [False])[0]
+ return res
+
+
+ def AddPage(self, page, text, select=False, imageId=-1):
+ """
+ Adds a page to the book.
+
+ :param `page`: specifies the new page;
+ :param `text`: specifies the text for the new page;
+ :param `select`: specifies whether the page should be selected;
+ :param `imageId`: specifies the optional image index for the new page.
+
+ :note: The call to this function generates the page changing events.
+ """
+
+ if not page:
+ return
+
+ page.Reparent(self)
+
+ self._windows.append(page)
+
+ if select or len(self._windows) == 1:
+ self.SetSelection(len(self._windows)-1)
+ else:
+ page.Hide()
+
+ self._pages.AddPage(text, select, imageId)
+ self.ResizeTabArea()
+ self.Refresh()
+
+
+ def InsertPage(self, page_idx, page, text, select=False, imageId=-1):
+ """
+ Inserts a page into the book at the specified position.
+
+ :param `page_idx`: specifies the position for the new page;
+ :param `page`: specifies the new page;
+ :param `text`: specifies the text for the new page;
+ :param `select`: specifies whether the page should be selected;
+ :param `imageId`: specifies the optional image index for the new page.
+
+ :note: The call to this function generates the page changing events.
+ """
+
+ if not page:
+ return
+
+ page.Reparent(self)
+
+ self._windows.insert(page_idx, page)
+
+ if select or len(self._windows) == 1:
+ self.SetSelection(page_idx)
+ else:
+ page.Hide()
+
+ self._pages.InsertPage(page_idx, text, select, imageId)
+ self.ResizeTabArea()
+ self.Refresh()
+
+
+ def DeletePage(self, page):
+ """
+ Deletes the specified page, and the associated window.
+
+ :param `page`: an integer specifying the page to be deleted.
+
+ :note: The call to this function generates the page changing events.
+ """
+
+ if page >= len(self._windows) or page < 0:
+ return
+
+ # Fire a closing event
+ event = ImageNotebookEvent(wxEVT_IMAGENOTEBOOK_PAGE_CLOSING, self.GetId())
+ event.SetSelection(page)
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ # The event handler allows it?
+ if not event.IsAllowed():
+ return False
+
+ self.Freeze()
+
+ # Delete the requested page
+ pageRemoved = self._windows[page]
+
+ # If the page is the current window, remove it from the sizer
+ # as well
+ if page == self.GetSelection():
+ self._mainSizer.Detach(pageRemoved)
+
+ # Remove it from the array as well
+ self._windows.pop(page)
+
+ # Now we can destroy it in wxWidgets use Destroy instead of delete
+ pageRemoved.Destroy()
+ self._mainSizer.Layout()
+
+ self._pages.DoDeletePage(page)
+ self.ResizeTabArea()
+ self.Thaw()
+
+ # Fire a closed event
+ closedEvent = ImageNotebookEvent(wxEVT_IMAGENOTEBOOK_PAGE_CLOSED, self.GetId())
+ closedEvent.SetSelection(page)
+ closedEvent.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(closedEvent)
+
+
+ def RemovePage(self, page):
+ """
+ Deletes the specified page, without deleting the associated window.
+
+ :param `page`: an integer specifying the page to be removed.
+
+ :note: The call to this function generates the page changing events.
+ """
+
+ if page >= len(self._windows):
+ return False
+
+ # Fire a closing event
+ event = ImageNotebookEvent(wxEVT_IMAGENOTEBOOK_PAGE_CLOSING, self.GetId())
+ event.SetSelection(page)
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ # The event handler allows it?
+ if not event.IsAllowed():
+ return False
+
+ self.Freeze()
+
+ # Remove the requested page
+ pageRemoved = self._windows[page]
+
+ # If the page is the current window, remove it from the sizer
+ # as well
+ if page == self.GetSelection():
+ self._mainSizer.Detach(pageRemoved)
+
+ # Remove it from the array as well
+ self._windows.pop(page)
+ self._mainSizer.Layout()
+ self.ResizeTabArea()
+ self.Thaw()
+
+ self._pages.DoDeletePage(page)
+
+ # Fire a closed event
+ closedEvent = ImageNotebookEvent(wxEVT_IMAGENOTEBOOK_PAGE_CLOSED, self.GetId())
+ closedEvent.SetSelection(page)
+ closedEvent.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(closedEvent)
+
+ return True
+
+
+ def ResizeTabArea(self):
+ """ Resizes the tab area if the control has the ``INB_FIT_LABELTEXT`` style set. """
+
+ agwStyle = self.GetAGWWindowStyleFlag()
+
+ if agwStyle & INB_FIT_LABELTEXT == 0:
+ return
+
+ if agwStyle & INB_LEFT or agwStyle & INB_RIGHT:
+ dc = wx.MemoryDC()
+ dc.SelectObject(wx.EmptyBitmap(1, 1))
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetPointSize(font.GetPointSize()*self._fontSizeMultiple)
+ if self.GetFontBold() or agwStyle & INB_BOLD_TAB_SELECTION:
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ dc.SetFont(font)
+ maxW = 0
+
+ for page in xrange(self.GetPageCount()):
+ caption = self._pages.GetPageText(page)
+ w, h = dc.GetTextExtent(caption)
+ maxW = max(maxW, w)
+
+ maxW += 24 #TODO this is 6*4 6 is nPadding from drawlabel
+
+ if not agwStyle & INB_SHOW_ONLY_TEXT:
+ maxW += self._pages._nImgSize * 2
+
+ maxW = max(maxW, 100)
+ self._pages.SetSizeHints(maxW, -1)
+ self._pages._nTabAreaWidth = maxW
+
+
+ def DeleteAllPages(self):
+ """ Deletes all the pages in the book. """
+
+ if not self._windows:
+ return
+
+ self.Freeze()
+
+ for win in self._windows:
+ win.Destroy()
+
+ self._windows = []
+ self.Thaw()
+
+ # remove old selection
+ self._pages.ClearAll()
+ self._pages.Refresh()
+
+
+ def SetSelection(self, page):
+ """
+ Changes the selection from currently visible/selected page to the page
+ given by page.
+
+ :param `page`: an integer specifying the page to be selected.
+
+ :note: The call to this function generates the page changing events.
+ """
+
+ if page >= len(self._windows):
+ return
+
+ if not self.GetEnabled(page):
+ return
+
+ if page == self.GetSelection() and not self._bForceSelection:
+ return
+
+ oldSelection = self.GetSelection()
+
+ # Generate an event that indicates that an image is about to be selected
+ event = ImageNotebookEvent(wxEVT_IMAGENOTEBOOK_PAGE_CHANGING, self.GetId())
+ event.SetSelection(page)
+ event.SetOldSelection(oldSelection)
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ # The event handler allows it?
+ if not event.IsAllowed() and not self._bForceSelection:
+ return
+
+ self.DoSetSelection(self._windows[page])
+ # Now we can update the new selection
+ self._pages._nIndex = page
+
+ # Refresh calls the OnPaint of this class
+ self._pages.Refresh()
+
+ # Generate an event that indicates that an image was selected
+ eventChanged = ImageNotebookEvent(wxEVT_IMAGENOTEBOOK_PAGE_CHANGED, self.GetId())
+ eventChanged.SetEventObject(self)
+ eventChanged.SetOldSelection(oldSelection)
+ eventChanged.SetSelection(page)
+ self.GetEventHandler().ProcessEvent(eventChanged)
+
+
+ def AssignImageList(self, imglist):
+ """
+ Assigns an image list to the control.
+
+ :param `imglist`: an instance of :class:`ImageList`.
+ """
+
+ self._pages.AssignImageList(imglist)
+
+ # Force change
+ self.SetAGWWindowStyleFlag(self.GetAGWWindowStyleFlag())
+
+
+ def GetSelection(self):
+ """ Returns the current selection. """
+
+ if self._pages:
+ return self._pages._nIndex
+ else:
+ return -1
+
+
+ def DoSetSelection(self, window):
+ """
+ Select the window by the provided pointer.
+
+ :param `window`: an instance of :class:`Window`.
+ """
+
+ curSel = self.GetSelection()
+ agwStyle = self.GetAGWWindowStyleFlag()
+ # Replace the window in the sizer
+ self.Freeze()
+
+ # Check if a new selection was made
+ bInsertFirst = (agwStyle & INB_BOTTOM or agwStyle & INB_RIGHT)
+
+ if curSel >= 0:
+
+ # Remove the window from the main sizer
+ self._mainSizer.Detach(self._windows[curSel])
+ self._windows[curSel].Hide()
+
+ if bInsertFirst:
+ self._mainSizer.Insert(0, window, 1, wx.EXPAND)
+ else:
+ self._mainSizer.Add(window, 1, wx.EXPAND)
+
+ window.Show()
+ self._mainSizer.Layout()
+ self.Thaw()
+
+
+ def GetImageList(self):
+ """ Returns the associated image list. """
+
+ return self._pages.GetImageList()
+
+
+ def GetPageCount(self):
+ """ Returns the number of pages in the book. """
+
+ return len(self._windows)
+
+
+ def GetFontBold(self):
+ """ Gets the font bold status. """
+
+ return self._fontBold
+
+
+ def SetFontBold(self, bold):
+ """
+ Sets whether the page captions are bold or not.
+
+ :param `bold`: ``True`` or ``False``.
+ """
+
+ self._fontBold = bold
+
+
+ def GetFontSizeMultiple(self):
+ """ Gets the font size multiple for the page captions. """
+
+ return self._fontSizeMultiple
+
+
+ def SetFontSizeMultiple(self, multiple):
+ """
+ Sets the font size multiple for the page captions.
+
+ :param `multiple`: The multiple to be applied to the system font to get the our font size.
+ """
+
+ self._fontSizeMultiple = multiple
+
+
+ def SetPageImage(self, page, imageId):
+ """
+ Sets the image index for the given page.
+
+ :param `page`: an integer specifying the page index;
+ :param `image`: an index into the image list.
+ """
+
+ self._pages.SetPageImage(page, imageId)
+ self._pages.Refresh()
+
+
+ def SetPageText(self, page, text):
+ """
+ Sets the text for the given page.
+
+ :param `page`: an integer specifying the page index;
+ :param `text`: the new tab label.
+ """
+
+ self._pages.SetPageText(page, text)
+ self._pages.Refresh()
+
+
+ def GetPageText(self, page):
+ """
+ Returns the text for the given page.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ return self._pages.GetPageText(page)
+
+
+ def GetPageImage(self, page):
+ """
+ Returns the image index for the given page.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ return self._pages.GetPageImage(page)
+
+
+ def GetEnabled(self, page):
+ """
+ Returns whether a tab is enabled or not.
+
+ :param `page`: an integer specifying the page index.
+ """
+
+ return self._pages.GetEnabled(page)
+
+
+ def EnableTab(self, page, enabled=True):
+ """
+ Enables or disables a tab.
+
+ :param `page`: an integer specifying the page index;
+ :param `enabled`: ``True`` to enable a tab, ``False`` to disable it.
+ """
+
+ if page >= len(self._windows):
+ return
+
+ self._windows[page].Enable(enabled)
+ self._pages.EnableTab(page, enabled)
+
+
+ def GetPage(self, page):
+ """
+ Returns the window at the given page position.
+
+ :param `page`: an integer specifying the page to be returned.
+ """
+
+ if page >= len(self._windows):
+ return
+
+ return self._windows[page]
+
+
+ def GetCurrentPage(self):
+ """ Returns the currently selected notebook page or ``None``. """
+
+ if self.GetSelection() < 0:
+ return
+
+ return self.GetPage(self.GetSelection())
+
+
+ def OnNavigationKey(self, event):
+ """
+ Handles the ``wx.EVT_NAVIGATION_KEY`` event for :class:`FlatBookBase`.
+
+ :param `event`: a :class:`NavigationKeyEvent` event to be processed.
+ """
+
+ if event.IsWindowChange():
+ if self.GetPageCount() == 0:
+ return
+
+ # change pages
+ self.AdvanceSelection(event.GetDirection())
+
+ else:
+ event.Skip()
+
+
+ def AdvanceSelection(self, forward=True):
+ """
+ Cycles through the tabs.
+
+ :param `forward`: if ``True``, the selection is advanced in ascending order
+ (to the right), otherwise the selection is advanced in descending order.
+
+ :note: The call to this function generates the page changing events.
+ """
+
+ nSel = self.GetSelection()
+
+ if nSel < 0:
+ return
+
+ nMax = self.GetPageCount() - 1
+
+ if forward:
+ newSelection = (nSel == nMax and [0] or [nSel + 1])[0]
+ else:
+ newSelection = (nSel == 0 and [nMax] or [nSel - 1])[0]
+
+ self.SetSelection(newSelection)
+
+
+ def ChangeSelection(self, page):
+ """
+ Changes the selection for the given page, returning the previous selection.
+
+ :param `page`: an integer specifying the page to be selected.
+
+ :note: The call to this function does not generate the page changing events.
+ """
+
+ if page < 0 or page >= self.GetPageCount():
+ return
+
+ oldPage = self.GetSelection()
+ self.DoSetSelection(page)
+
+ return oldPage
+
+ CurrentPage = property(GetCurrentPage, doc="See `GetCurrentPage`")
+ Page = property(GetPage, doc="See `GetPage`")
+ PageCount = property(GetPageCount, doc="See `GetPageCount`")
+ PageImage = property(GetPageImage, SetPageImage, doc="See `GetPageImage, SetPageImage`")
+ PageText = property(GetPageText, SetPageText, doc="See `GetPageText, SetPageText`")
+ Selection = property(GetSelection, SetSelection, doc="See `GetSelection, SetSelection`")
+
+
+# ---------------------------------------------------------------------------- #
+# Class FlatImageBook
+# ---------------------------------------------------------------------------- #
+
+class FlatImageBook(FlatBookBase):
+ """
+ Default implementation of the image book, it is like a :class:`Notebook`, except that
+ images are used to control the different pages. This container is usually used
+ for configuration dialogs etc.
+
+ :note: Currently, this control works properly for images of size 32x32 and bigger.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=0, name="FlatImageBook"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`Panel` window style;
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``INB_BOTTOM`` 0x1 Place labels below the page area. Available only for :class:`FlatImageBook`.
+ ``INB_LEFT`` 0x2 Place labels on the left side. Available only for :class:`FlatImageBook`.
+ ``INB_RIGHT`` 0x4 Place labels on the right side.
+ ``INB_TOP`` 0x8 Place labels above the page area.
+ ``INB_BORDER`` 0x10 Draws a border around :class:`LabelBook` or :class:`FlatImageBook`.
+ ``INB_SHOW_ONLY_TEXT`` 0x20 Shows only text labels and no images. Available only for :class:`LabelBook`.
+ ``INB_SHOW_ONLY_IMAGES`` 0x40 Shows only tab images and no label texts. Available only for :class:`LabelBook`.
+ ``INB_FIT_BUTTON`` 0x80 Displays a pin button to show/hide the book control.
+ ``INB_DRAW_SHADOW`` 0x100 Draw shadows below the book tabs. Available only for :class:`LabelBook`.
+ ``INB_USE_PIN_BUTTON`` 0x200 Displays a pin button to show/hide the book control.
+ ``INB_GRADIENT_BACKGROUND`` 0x400 Draws a gradient shading on the tabs background. Available only for :class:`LabelBook`.
+ ``INB_WEB_HILITE`` 0x800 On mouse hovering, tabs behave like html hyperlinks. Available only for :class:`LabelBook`.
+ ``INB_NO_RESIZE`` 0x1000 Don't allow resizing of the tab area.
+ ``INB_FIT_LABELTEXT`` 0x2000 Will fit the tab area to the longest text (or text+image if you have images) in all the tabs.
+ ``INB_BOLD_TAB_SELECTION`` 0x4000 Show the selected tab text using a bold font.
+ =========================== =========== ==================================================
+
+ :param `name`: the window name.
+ """
+
+ FlatBookBase.__init__(self, parent, id, pos, size, style, agwStyle, name)
+
+ self._pages = self.CreateImageContainer()
+
+ if agwStyle & INB_LEFT or agwStyle & INB_RIGHT:
+ self._mainSizer = wx.BoxSizer(wx.HORIZONTAL)
+ else:
+ self._mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ self.SetSizer(self._mainSizer)
+
+ # Add the tab container to the sizer
+ self._mainSizer.Add(self._pages, 0, wx.EXPAND)
+
+ if agwStyle & INB_LEFT or agwStyle & INB_RIGHT:
+ self._pages.SetSizeHints(self._pages.GetImageSize() * 2, -1)
+ else:
+ self._pages.SetSizeHints(-1, self._pages.GetImageSize() * 2)
+
+ self._mainSizer.Layout()
+
+
+ def CreateImageContainer(self):
+ """ Creates the image container class for :class:`FlatImageBook`. """
+
+ return ImageContainer(self, wx.ID_ANY, agwStyle=self.GetAGWWindowStyleFlag())
+
+
+# ---------------------------------------------------------------------------- #
+# Class LabelBook
+# ---------------------------------------------------------------------------- #
+
+class LabelBook(FlatBookBase):
+ """
+ An implementation of a notebook control - except that instead of having
+ tabs to show labels, it labels to the right or left (arranged horizontally).
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=0, name="LabelBook"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`Panel` window style;
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``INB_BOTTOM`` 0x1 Place labels below the page area. Available only for :class:`FlatImageBook`.
+ ``INB_LEFT`` 0x2 Place labels on the left side. Available only for :class:`FlatImageBook`.
+ ``INB_RIGHT`` 0x4 Place labels on the right side.
+ ``INB_TOP`` 0x8 Place labels above the page area.
+ ``INB_BORDER`` 0x10 Draws a border around :class:`LabelBook` or :class:`FlatImageBook`.
+ ``INB_SHOW_ONLY_TEXT`` 0x20 Shows only text labels and no images. Available only for :class:`LabelBook`.
+ ``INB_SHOW_ONLY_IMAGES`` 0x40 Shows only tab images and no label texts. Available only for :class:`LabelBook`.
+ ``INB_FIT_BUTTON`` 0x80 Displays a pin button to show/hide the book control.
+ ``INB_DRAW_SHADOW`` 0x100 Draw shadows below the book tabs. Available only for :class:`LabelBook`.
+ ``INB_USE_PIN_BUTTON`` 0x200 Displays a pin button to show/hide the book control.
+ ``INB_GRADIENT_BACKGROUND`` 0x400 Draws a gradient shading on the tabs background. Available only for :class:`LabelBook`.
+ ``INB_WEB_HILITE`` 0x800 On mouse hovering, tabs behave like html hyperlinks. Available only for :class:`LabelBook`.
+ ``INB_NO_RESIZE`` 0x1000 Don't allow resizing of the tab area.
+ ``INB_FIT_LABELTEXT`` 0x2000 Will fit the tab area to the longest text (or text+image if you have images) in all the tabs.
+ ``INB_BOLD_TAB_SELECTION`` 0x4000 Show the selected tab text using a bold font.
+ =========================== =========== ==================================================
+
+ :param `name`: the window name.
+ """
+
+ FlatBookBase.__init__(self, parent, id, pos, size, style, agwStyle, name)
+
+ self._pages = self.CreateImageContainer()
+
+ # Label book specific initialization
+ self._mainSizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.SetSizer(self._mainSizer)
+
+ # Add the tab container to the sizer
+ self._mainSizer.Add(self._pages, 0, wx.EXPAND)
+ self._pages.SetSizeHints(self._pages.GetTabAreaWidth(), -1)
+
+ # Initialize the colours maps
+ self._pages.InitializeColours()
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def CreateImageContainer(self):
+ """ Creates the image container (LabelContainer) class for :class:`FlatImageBook`. """
+
+ return LabelContainer(self, wx.ID_ANY, agwStyle=self.GetAGWWindowStyleFlag())
+
+
+ def SetColour(self, which, colour):
+ """
+ Sets the colour for the specified parameter.
+
+ :param `which`: the colour key;
+ :param `colour`: a valid :class:`Colour` instance.
+
+ :see: :meth:`LabelContainer.SetColour() <LabelContainer.SetColour>` for a list of valid colour keys.
+ """
+
+ self._pages.SetColour(which, colour)
+
+
+ def GetColour(self, which):
+ """
+ Returns the colour for the specified parameter.
+
+ :param `which`: the colour key.
+
+ :see: :meth:`LabelContainer.SetColour() <LabelContainer.SetColour>` for a list of valid colour keys.
+ """
+
+ return self._pages.GetColour(which)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`LabelBook`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self._pages.Refresh()
+ event.Skip()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/multidirdialog.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/multidirdialog.py
new file mode 100644
index 0000000..4fa83a0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/multidirdialog.py
@@ -0,0 +1,584 @@
+# --------------------------------------------------------------------------------- #
+# MULTIDIRDIALOG wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 07 October 2008
+# Latest Revision: 28 Sep 2012, 21.00 GMT
+#
+#
+# TODO List
+#
+# 1) Implement an meaningful action for the "Make New Folder" button, but this
+# requires a strong integration with Explorer, at least on Windows;
+#
+# 2) Be more user-friendly with special folders as the Desktop, My Documents etc...
+#
+#
+# For all kind of problems, requests of enhancements and bug reports, please
+# write to me at:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, obviously, to the wxPython mailing list!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+This class represents a possible replacement for :class:`DirDialog`, with the additional
+ability of selecting multiple folders at once.
+
+
+Description
+===========
+
+This class represents a possible replacement for :class:`DirDialog`, with the additional
+ability of selecting multiple folders at once. It may be useful when you wish to
+present to the user a directory browser which allows multiple folder selections.
+:class:`MultiDirDialog` sports the following features:
+
+* Ability to select a single or mutliple folders, depending on the style passed;
+* More colourful and eye-catching buttons;
+* Good old Python code :-D .
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+Usage
+=====
+
+Usage example::
+
+ import os
+ import wx
+
+ import wx.lib.agw.multidirdialog as MDD
+
+ # Our normal wxApp-derived class, as usual
+ app = wx.App(0)
+
+ dlg = MDD.MultiDirDialog(None, title="Custom MultiDirDialog", defaultPath=os.getcwd(),
+ agwStyle=MDD.DD_MULTIPLE|MDD.DD_DIR_MUST_EXIST)
+
+ if dlg.ShowModal() != wx.ID_OK:
+ print "You Cancelled The Dialog!"
+ dlg.Destroy()
+ return
+
+ paths = dlg.GetPaths()
+ for indx, path in enumerate(paths):
+ print "Path %d: %s"%(indx+1, path)
+
+ dlg.Destroy()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`MultiDirDialog` has been tested on the following platforms:
+ * Windows (Windows XP).
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+===================== =========== ==================================================
+Window Styles Hex Value Description
+===================== =========== ==================================================
+``DD_NEW_DIR_BUTTON`` 0x000 Enable/disable the "Make new folder" button
+``DD_DIR_MUST_EXIST`` 0x200 The dialog will allow the user to choose only an existing folder. When this style is not given, a "Create new directory" button is added to the dialog (on Windows) or some other way is provided to the user to type the name of a new folder.
+``DD_MULTIPLE`` 0x400 Allows the selection of multiple folders.
+===================== =========== ==================================================
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`MultiDirDialog` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 28 Sep 2012, 21.00 GMT
+
+Version 0.3
+
+"""
+
+import os
+import wx
+import wx.lib.buttons as buttons
+
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+# MultiDirDialog styles
+DD_MULTIPLE = 1024
+""" Allows the selection of multiple folders. """
+DD_DEFAULT_STYLE = wx.DD_DEFAULT_STYLE
+""" Equivalent to a combination of ``wx.DEFAULT_DIALOG_STYLE`` and ``wx.RESIZE_BORDER``. """
+DD_DIR_MUST_EXIST = wx.DD_DIR_MUST_EXIST
+""" The dialog will allow the user to choose only an existing folder. When this style is not given, a "Create new directory" button is added to the dialog (on Windows) or some other way is provided to the user to type the name of a new folder. """
+DD_NEW_DIR_BUTTON = wx.DD_NEW_DIR_BUTTON
+""" The `Make New Folder` button will be displayed. """
+
+_ = wx.GetTranslation
+
+_cancel = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAA1dJ"
+ "REFUOI11019oEwccB/Dv3eUuyZ2XpfljsmJ7JY01KZYWty6bdMwnp1X34JNS5sPAsmYruOnL"
+ "3kTGcPg6Bdkexqql4EPdBuKbVG0xLmpoWjbW0D+S1Jg24RJzuSR3l58PtpsI/l5/fB5+3x9f"
+ "AEDc7VauhMP3prq7q9+1t5/AW+aiLB+ZDocrU6HQk4tAFAC4s8Gg0uVyXTsZiw190Nsr6JnM"
+ "kZAkrd6rVtOv4wuyfLS/rW3y6Oioq2tgILiRyXy4v1yexU979yaKIyNEiQRRsUjG2Bjddrtr"
+ "532+k9v4B1kevu33l+vnzhFtbBAtL9OLS5douq9v0eZ1OPo8Xi8gSUClAls8jk+qVad148bP"
+ "33s8TcY0K32mOTV07JhsP3UKKJUAy8IORYF3584erodopaGqh7qzWYEJBgGGgW3fPrQ/eyY0"
+ "5uePewzjxIGDB0U5HgcsC1BV0MOH+GtiojF/9+433P1qNd1pGCvs5uawUijwbDAIWBZsAwPw"
+ "5nJsRyBgc8fjYLZwK5lE6uZN88Hc3LdfmeYVDgDu12oLXUSrxvPnw8r6uo3z+cAQwRGJQOzv"
+ "B0sEKhZhJRJI3rplJlKpM+OWdRkAuO2gZnQ93UO02CgUjr9bLHKCzweGZcGYJqhchp5I4NGd"
+ "O9bjpaUvxol+2Xa211/FAKolSa0XySSq+TzYYBAAYGkaUKnA5LgWA6hvmP//PKgokx9tbspq"
+ "Pg8NgL61c0gSJL8f73R04O9KRV9Mp0+PtlrX/zvhgigO749GJ4dKJVc9l0MTgAVAZBg4BQEk"
+ "SeCcTjAAOhWF5/3+w7FsdvkPogXuR7f7s/d6eycPqKqrubKC+hZ28DxydnurzHFWwG5niefB"
+ "CALYVgu7wmGe2toOfby2lrVFIpFrn9brcmNpCU0ALIAdooiMw9FI1etfkmGUbaY5EXY4JIth"
+ "YAIw1tcxODgoEcddZeua9rQqCGB5HgwA0e3GmsdjPtH1s1/Xar+ON5vTi6p6+qmm6U5JAksE"
+ "VhBQbzahl0p57n1Nm9kQxVhXINAucxzSLpeZLBTOxHX98nbAfxItxMrlVV4UD+/q7OTJ58Pc"
+ "7Ow/uVTq81c1FYTo76HQo5k9expXnc6xt9X5OsuOPIhGtZndu//9DYgBwEt1gHq0YITgmAAA"
+ "AABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_ok = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAjdJ"
+ "REFUOI2tksFLk3Ecxp+97975vmuve1dWuiUTNIy1JlsLpkZG0aXLbv0B0aVDUMfVQTp0jJpF"
+ "EHl5LxUZgZcuQjAID4KUyWwyEU3d9m7O5d733dze97dfB1siJSn1nJ/P5+ELX+Afwx6YuAMB"
+ "AVgwjcaBBdIovP2eyKMLPYNdM+7kNKZA9i3gR+ENCeF4Hx+8VigVBgrKWrXKGp/2JeCfwhsW"
+ "Q/HTQiCaVTOYUiZtDuoMQqefrc1S9+uOEGNSRzqd+4j72/c1l4OOQNwn+aOFWg5TdBJEIKbH"
+ "dI9zHLMt6H3lHrjScfU5x3DSmOXNrVUUxwFQ6S3vDdh9cZ/zTHSz8R0pMguGMKaRMuX5peQ9"
+ "ZULPW8+PnB286L78zH/M76/DwCYtjSTefaAOQZjpEDofn5J8UR0qViqLoCpLql+IXFzS72IC"
+ "eQCwssR2NFfOtNXsFZx09SLkDnfSlsYTluUy7a3Hz6mWMrLGKswiJaV0WS6Uyr9gAGC7It0L"
+ "WrWYm99K9VdcqugSD8Pd6nG6RNeJCq9ZstwqNL1CMl/z8npdiRkPd2AAYJcTy41FcSVZt+lK"
+ "na9FaLspCg4ehDew3qJgs6qStUxerhItlr+h74KB5iPNgVZuGkm6QpQWmy3i8AoiY7dA1XTy"
+ "LZuVGYHGZi8t/gbvCABgDFS7vpVEgSgS29bv5CR7XtmQjxxyxt77En+Edwt+Svpua3MbRT5T"
+ "a9QXPGL7gxc9L/eE98wwHWaG6JD1783/kB9qTvueLt8LjwAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_cdrom = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAArRJ"
+ "REFUOI11kc9rm3Ucx1/f5/eTLV2aJ2vqVseGWzeYDAbCCq2THQqiuB3mP+DBQ3ss3rysILLb"
+ "2I5FhKHkNFmFHkrFoVDQDautI02ZWqGJ7WzWEkzy/M73u1NKbNj79Dl8Xi8+P+BQhoeHj09N"
+ "Td1aWlr6s1qtNjY3N/dLpdIvExMTHwPG4f7/ZWRk5M35+fmnqidSSqWUUlEUqdnZ2W+B3Kv4"
+ "wbm5uaeNRkO1220VRZEKw1D5vq/CMDwQTk9PfwVoffTk5ORMpVJR5XJZ1Wo1FYahCoJAtVot"
+ "laapSpJEBUGgNjY2VLFYvNblDkzj4+PvJ0kCgJSSvb09tv7eiuv/1tMgDGg2m+zu7mKaJmNj"
+ "Yx90uYOj5PP5k2ma4jgOuqbT/K/JvYd3n4+eOu9cH7s+lMiE/f19hBAUCoUzfYIkSYJ8Po+u"
+ "69i2TZIk3Hz3w1MqUtT36iRpgu/7ZDIZfN+P+1ZYXV39bWBgANd1OZo9ilfwuDB0gYunL+K4"
+ "Dq1WCyEEcRyztra22idYWFj4srxW9j3PQ0pJo9EADWzHxvM8juWO4doZln9c3llfX/+my+nd"
+ "IgzDrUpceeftS1ffcHSX+os6Ukosy8I0THJHBnn87Cduf/H5/dZO++s+AcA/V2sfbYa/nmFb"
+ "QwYamjJACWrbVVY2HvMDiyxXnvzMXyz2HRGw8ifJ+6N/sNi+QzE4jbd9Auu5g3Jh6OxrjGZP"
+ "4HgUgh6oV2B++tZngxOXr2AbBpZpYGomujIR0kTFOqmQ/P56NVfiQb8gm80640fey9nPLKI4"
+ "IkKhAKk6CDocHyqQcVyuFK8NlnhgAOnhCag36k6pdJ92u43ruliWhRACgWDmkxl27G2anVam"
+ "93uih9dv3Lh569y5s5fjuCMNQ6BpIIROp9NB13XQ0R599+j7lZUnd7rQS0kMSYjIJmZ4AAAA"
+ "AElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_computer = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAshJ"
+ "REFUOI1dk91PXGUQxn/ve979YkHXmhZ325oUa9Wlxg9q8caoCRde9Hb/Bv4KQ8J/AXdceFF6"
+ "YYJXNCYWE0xITAxt1cjXKpiYsnQpH3v2sOfMTC8WAZ2rmWSeZ56ZJ+MAzKwEXIHEQ5ELYedp"
+ "QpKcV8Vise2cOwwAnU63sdFsTx0cnpiJoipkqkiaIaa0Wh2etQ4tyxRVo1xy0eefXf0G+DoA"
+ "ZJlea/7VGRksF1B1iICIQwUyEb79boMfl/8khDy4wLVamdF3X33LzHwAUJQ47k82U1QVkX7e"
+ "3u+y2XyB9w7THkZGlnkUNYDw705HHeXgqIdZH6wqmCq/r7XZPzBCroRKSvDKrZsVIt/HnREc"
+ "x8bRcYaZoCKICCIZf2wcY65IFAIQeOdWhfdH30D1PwSeuOvYfS5wqkBEiOMeu3t6Oj2jXC4x"
+ "+l6NblfO7Al9OMSJp9V2YJwe0XhxIPSyHFEAH2Vcvz5AL4vY2z85RV1YodM1dp8bDodI34nj"
+ "Y4+LSkQuUCwYUcjz9z8ppYLiLipQlLiT0NpLCCEHOFQDIuCDxzRgTtnd6zt1+RL4KLqgQDP9"
+ "6oscI28mmPVwPiKKgoUw4CLvyLLURFKX9nqc9E4oBCUfsnMbvfff3/lgoHK50vLLPy3zbLcV"
+ "jdy48eHdjz75slAouidPnj7+7denj1wUpXc+HrPq1ZqrDlcfOec0AFQqlZ8bjcYvW1tbgyJy"
+ "d3x8/F6pOHBlsPyKS9MeWZq+liS9oZWVlYcP7j/4YWJiYn92djY9e4xGoxEBQ8Db09PTC5ub"
+ "m7a+vmZLS0u2uLhoq6urtr29bXNzc4+HhoY+BS6NjY3lgLNjMj8/Hy0sLBTb7fbtarV6r16v"
+ "387n86+LiHfOHTabzfW1tbWHuVxueXh4uDMzM5M55+yM4GJMTU35OI7LOzs7AyLiarVaUq/X"
+ "O5OTk+n/e18CKWqFGqiV9Q4AAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_folder_close = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAcBJ"
+ "REFUOI2Nk0FrE1EQx3+zL7vbmFKRQkE/gyfpISL4WYJHsQfPvXkQe6go+AnEi6dcBBEkhYgS"
+ "oQfFeqo0VJRobaspm2R339sdD9u0IclC/zAwzLz5zbzhPeFUnU5HuYDq9brMBB+/+KQXVavV"
+ "+jBZWxk79zffl3Z9dO8GQbCAiAAEM4DvvyI21m4SpyCiaK6ogqqiwN2nWzxbu0W1WpuBn00w"
+ "ih3H/YwkcbgMnFOcU5K0yKdJTLVawzk3H3D8z9GPHKqKy3QGYK0Fiqkm5Y2do77l3ec+mQhD"
+ "q+eWFgXjzr1ebzgXgBG2u0O+7A/JRYhzCjttqJrTbDb3G43G7blXyEQIlkI+dmNiPK5dqeBE"
+ "sJoXO7CGdru9VbrEXDzCyyEisPPH8XOgrCwaFgysXl/lwcttLqWjmUd0BnCeh78UYgQQiJxy"
+ "cpJj8gxcUZdbVw5Q47FYM1REESBTSJ0htYZkVCxChXKAXxGWq4bAnAPiDAbWMPCFEbD7bfew"
+ "FPD34Hfa3TuKlmth4PsVycWTQYoeDp39EXnpVVh522pvTgPGI4V3Nt7E08lJvXr+ZP3g6+uH"
+ "ZYB5EsCn+DwhEAHJ9KH/LOgEF+oT+k8AAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_folder_open = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAvdJ"
+ "REFUOI1tU01o23UYft7/75ekqXVJWsO6HaZWzDyIih4UCkJBGIroUATxWPEyLx6EDZzz5Dzr"
+ "xB3FkygoCA7ZR0A3g60zWdutbrZLTNOvJI1pmvyT/8fv4/WQFFzwgZf36zm8HzyEeyEAEAAD"
+ "gAexM/B6iEsDAwak4eZwzXk48/gTr7w5+04qlUoMkwEgnnnyuekPz372xbGXjr8GAKPp9OSL"
+ "L796/PQnn57/5Y/lv9q+tp3A8KEHM48BqcT4o888CwA49taJ04vFeqPta22s5Wtz+cL5r77/"
+ "YW3HdY213Pa1Xd5w+WK+Yr/NremzX17MLZVqrQu5m/MEgM6c+yb70btvzLR6RlmtEInGhKvg"
+ "lDcb2Nr1jR+yTSbvc6YeGHGOpOMYjZAlInEhm7sm3/7g8+/em319ZqPR061OV5Z3Amq4yhoW"
+ "eiI1JqYOJZ3JiTFxIMasNEMb0FbHU2OjI6LWaAdyYXHpTk8T1qpN+unmHo4emUT64LhzOCGd"
+ "iNM/T3VPoWZCsk6Eo8KBUobageev77Q6cnE++2O+2DwVeBCuZ3g8GYfraax4/a9FRP8ZQgDM"
+ "ISJSQAeKtN/tblabDal3ioW529XVp6fSmZqr+M62j0AzAYAjJKKOQlT2J2FmRIQBQE6n6QWl"
+ "zXpTAvAvfX3u16MnP85U29r+vNIT9a5BIi4BADEBjEQIsQgBzBBEDCK5sFT5Z+VWZUsCwFpp"
+ "9cr2bm+27QGtPUZUAnuDFYwBg4jAzIBmrZQlZlHZ5UTY9RwJAI3SQm61VPZk9P54CHCfvA/D"
+ "VimjtCUCRGiYAKJY2Eg6brEuARD83crq8o1C9KEXpgOC0caQ0YqtNk5oyQGYwm6LwvpK26tc"
+ "z7ul61ld//MytHdDDgSky7fmsgcPPz/t6Q4TWABA0Nwgv3Z7y/v7t5y/XrikGsWrAO4CsPvz"
+ "yf1k++7vl+mp2hkVdE2wkV/2y/NXe+uFK/Ba8wDqw8IaePvf4gE58cj7ELEZAKP/o859qd+D"
+ "fwFu65tDy5tMTAAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_hd = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAxlJ"
+ "REFUOI11ks1vG1UUxc+b98YzyfM4gxzSpHHttCFRbQto7YQgxRKIRRYIZRepEkQVzYJ/gAUi"
+ "i/wlSLBhFSEWZMUiQkLCSmUk0o6rNiExcvNRR/Z0xh6P5/OxqFwlfNzVWZz7u0dXh+B/Zn19"
+ "Pd1qtQpxHBeiKCoKId4aHR39dGdnx7zsY0Oxurq6FIbhZ4yxwgeVcnHuVuaarmvwPB/nL9r4"
+ "/Y+neHrQ+BLA5mUAHYp8Pr8uSdLXD+7fu/nRh5XktckpKOoIONcwNzeP998r483x8bvKSPKb"
+ "/f19Z7gnDYUsyz+nUiksLi4ioWqIBcFfBw/R/LOK1nkTCVVDpVJJLpbvfPWfCQzDON/e3v7k"
+ "9szk9Z7VwUuzA4WnoaXS6LQ7CAYD2C/bODlr3c3O3Pq2Vqt1ryQghKDb7X7XPG9BH5/ExNQN"
+ "DPo9nJ2+wMxsEfr4JPhYGkEYqrIsb/4rAQBwzp+HUfRF5no6MX1jFlOZmxAihtVuYpSnYDyq"
+ "QdUm0O323i2Xy99Xq1XzCiCZTPqcp/K247192jxA4DmI4wDPT88xMZXF7NxtPDaeIZfLUdd1"
+ "39jd3f2RXAYIIcjS0tLHy8vLP42NjUGWZTDGIEkS4jiGruuglIIQAtd1o5OTk3fYZQAhRGia"
+ "Vi0Wi0/m5+fzhFzhAwBc14VlWbAsi5qmeZ/901AqlazDw8MfSqXSZiKRgOM4sG0bpmmi0+mg"
+ "3++DUtpWFOWR53m/vT6xtbUl1et1cnR0JDUajTsrKyu/+L4/4nleGIZhw/O8x0EQPLQs69fj"
+ "4+Mnuq73NjY2PLK2tkYNw6CmaTLP85jv+wnf99O5XO7zKIrMs7OzZ77vdwkhPiHEppSaiqLY"
+ "09PTjmEYASkUCgnbtqnruiwIAjkMQyWKIkUIoQohZACyEIK+ehEJCCEOY8zmnPey2azHisVi"
+ "ZBjGq15LkqCURmEY+nEc94UQVAgxLJuQJClkjAWqqvrpdDqo1WohrdfrotVqxbZtR47jRJzz"
+ "kDEWaJrmqao64Jy7nHNX1/V+JpNxFxYWBnt7e/7FxUUEAH8DenV0NY9j5foAAAAASUVORK5C"
+ "YII=")
+
+#----------------------------------------------------------------------
+_new = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAqpJ"
+ "REFUOI1t0c1rXGUUx/Hvc+/czGtmEk1NTCYWY1BERAJVRMW4cCEIunHTnYjgQrduRHDTrX+F"
+ "u+ZvEF2IRVCRRkpt1VSTmqQ1rzNz733uc855XDSRkfHsz+ec3zmO/6mrVz9vPjHTm52e6c23"
+ "mq2lmpPFVE/6qrYUcXMON+2y7NP5Zy9/Wxtv/Gx9vXb5ynsfLczPvZnV0kfT+uycq6WdmO/V"
+ "82GaNtsPucx5NAyqoDYD8B+gc2m53mk13pluZy9DgptK8b5kZ/sPkqzH4xdmiMUeopJU4jKA"
+ "ZBwYDo4j0cRUiDESo3B8uMfmjV85Hea4GIgmqIRExJoTwGFd1LBgKpgZJp4qP6YoSqIJ0c4A"
+ "DS5xNjURwfv7Fk28acC5Gi6MsGqIqUA0iIKZYKYuOEsngKOjFZMgXlVIkgBSIOIxOwMsoBIQ"
+ "FSwGNxFhY2MjqkpQC2jwiB+gUiEqBA1UVYlIhYgSQmBiAwAViaqCaSCGHJGKO+6EnYMf+ObH"
+ "67zYW2C50aXSB701wAEZ0HzjlbWLVfArKlOgHvTBNO1FwsIBh6OK1aLNQtImRmmdAy2gD3Sf"
+ "ear/em/+ybWg+0g+4Pt7f7IzOkVmhXovoJmwuXeXraMDsE7jHPBAClwog8yS9ZJQ3qUoCm76"
+ "Q/J+TqsraDPH0iF3yl2G96B2uvxvBDmL8fAoL6crVVxZEipBNDCo/qYq95HkmMoLeQVVaNKN"
+ "uPEjeqCd+9C9+VfOonkyNS5al/Yu3J4qOJ3bJamarBw8x5R0bt0oTr4eB7aAzbIIa8lop4hp"
+ "WSPJ9p+fX71tMf3p59+3Xy1j+kISUh5L+5tvP73+Qf+196+NAwp8d+u37ft+/5evWquLmrSa"
+ "17uN/vbSpbfylz5Z+bg7eoQsNtIv/daVD9/94tr52/8BSS2agPSymFoAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_removable = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAldJ"
+ "REFUOI2lkbFOXFcQhr+Zc+7uXRZvFi2GOFHiSInA7CLFCnaRCokij0DjyElFh9K6sfwQeQEX"
+ "rngAvwBNsCyniNCChCKFSCYOkWADd/fuvfeccUEgrCU3yS+NNNN88/8z8D8l14d+v38jTdv3"
+ "fD3tqEpdRJxE1AzDYYCFoswGg8HL5eXPDwH8dYBzzR8/aM9855x778ZQC2TZ+TEwB6ATAK8r"
+ "SZLgvefP316SZed47zl902fw+hXOOZxTfKKzz5//1Jpw8OSJaZIcfyFykeqPw1+QX7f5aOEb"
+ "pP+Iqv4p1YdfUlUF3omUbtwB/r5ysLa2cztNG+nl3P36W5qzPaZ2HzL67BH15ceMxxnjYkiM"
+ "FXOt5mSEznxn0aliZoSqRFXofNzjIHnA9M0F1HvG4yFVOQag0UhnJiIkkixEixTFiBgqQqg4"
+ "G/xFdfY7+eicNG0g6nBaQ6SiVivmJgDiZKEsc8CIoSLGQNqc4cbS9zSmpvEuQZ1D1CFS4BJ/"
+ "cwJQFKPFIRGwC6Aq6mp0Zm9hplQR1AzRSFUFLFhnAvBi5+e7z549Jc9zzGzy+WYYsHinS7N7"
+ "wnyyxNIn9+evAKurqx5ke3Pzh68smkRMMDCLglz2iHOJjeKJNXw7HB0dvwCQlZWV5ODgoFkU"
+ "RTOE0DSzGpCYmf9ngQfUzFREKqAQkaH3/qTb7b5xGxsb7O3tWVmWAPGyRCQApYgUIpKLyFBV"
+ "z1X1zHs/aLfbp/v7+4X8G9NkfX1dd3d3XZZlmue5izFKjFFU1er1emi1WqHX64Wtra0oIu8c"
+ "6j/qLUda/yKP2243AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+
+
+class MultiDirDialog(wx.Dialog):
+ """
+ A different implementation of :class:`DirDialog` which allows multiple
+ folders to be selected at once.
+ """
+
+ def __init__(self, parent, message=_("Choose one or more folders:"), title=_("Browse For Folders"),
+ defaultPath="", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER, agwStyle=DD_MULTIPLE, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, name="multidirdialog"):
+ """
+ Default class constructor.
+
+ :param `parent`: the dialog parent widget;
+ :param `message`: the message to show on the dialog;
+ :param `title`: the dialog title;
+ :param `defaultPath`: the default path, or the empty string;
+ :param `style`: the underlying :class:`Dialog` window style;
+ :param `agwStyle`: the AGW-specific dialog style; this can be a combination of the
+ following bits:
+
+ ===================== =========== ==================================================
+ Window Styles Hex Value Description
+ ===================== =========== ==================================================
+ ``DD_NEW_DIR_BUTTON`` 0x000 Enable/disable the "Make new folder" button
+ ``DD_DIR_MUST_EXIST`` 0x200 The dialog will allow the user to choose only an existing folder. When this style is not given, a "Create new directory" button is added to the dialog (on Windows) or some other way is provided to the user to type the name of a new folder.
+ ``DD_MULTIPLE`` 0x400 Allows the selection of multiple folders.
+ ===================== =========== ==================================================
+
+ :param `pos`: the dialog position;
+ :param `size`: the dialog size;
+ :param `name`: the dialog name.
+ """
+
+ wx.Dialog.__init__(self, parent, pos=pos, size=size, style=style, name=name)
+
+ self.agwStyle = agwStyle
+
+ self.dirCtrl = wx.GenericDirCtrl(self, size=(300, 300), style=wx.DIRCTRL_3D_INTERNAL|wx.DIRCTRL_DIR_ONLY)
+ self.folderText = wx.TextCtrl(self, -1, defaultPath, style=wx.TE_PROCESS_ENTER)
+ self.CreateButtons()
+
+ self.SetProperties(title)
+ # Setup the layout and frame properties
+ self.SetupDirCtrl(defaultPath)
+ self.LayoutItems(message)
+ self.BindEvents()
+
+ if parent and pos == wx.DefaultPosition:
+ self.CenterOnParent()
+
+
+ def SetupDirCtrl(self, defaultPath):
+ """
+ Setup the internal :class:`GenericDirCtrl` (icons, labels, etc...).
+
+ :param `defaultPath`: the default path for :class:`MultiDirDialog`, can be an
+ empty string.
+ """
+
+ il = wx.ImageList(16, 16)
+
+ # Add images to list. You need to keep the same order in order for
+ # this to work!
+
+ # closed folder:
+ il.Add(_folder_close.GetBitmap())
+
+ # open folder:
+ il.Add(_folder_open.GetBitmap())
+
+ # root of filesystem (linux):
+ il.Add(_computer.GetBitmap())
+
+ # drive letter (windows):
+ il.Add(_hd.GetBitmap())
+
+ # cdrom drive:
+ il.Add(_cdrom.GetBitmap())
+
+ # removable drive on win98:
+ il.Add(_removable.GetBitmap())
+
+ # removable drive (floppy, flash, etc):
+ il.Add(_removable.GetBitmap())
+
+ # assign image list:
+ treeCtrl = self.dirCtrl.GetTreeCtrl()
+ treeCtrl.AssignImageList(il)
+
+ if self.agwStyle & DD_MULTIPLE:
+ treeCtrl.SetWindowStyle(treeCtrl.GetWindowStyle() | wx.TR_MULTIPLE)
+
+ if not defaultPath.strip():
+ return
+
+ # Set the wx.GenericDirCtrl default path
+ self.dirCtrl.ExpandPath(defaultPath)
+ self.dirCtrl.SetDefaultPath(defaultPath)
+ self.dirCtrl.SetPath(defaultPath)
+
+ self.folderText.SetValue(treeCtrl.GetItemText(treeCtrl.GetSelections()[0]))
+
+
+ def SetProperties(self, title):
+ """
+ Sets few properties for the dialog.
+
+ :param `title`: the dialog title.
+ """
+
+ self.SetTitle(title)
+ self.okButton.SetDefault()
+
+ if self.agwStyle & wx.DD_DIR_MUST_EXIST:
+ self.newButton.Enable(False)
+
+
+ def LayoutItems(self, message):
+ """ Layout the widgets using sizers. """
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ textSizer = wx.BoxSizer(wx.HORIZONTAL)
+ bottomSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ staticText = wx.StaticText(self, -1, message)
+ f = staticText.GetFont()
+ f.SetWeight(wx.BOLD)
+ staticText.SetFont(f)
+
+ # Add the main wx.GenericDirCtrl
+ mainSizer.Add(staticText, 0, wx.EXPAND|wx.ALL, 10)
+ mainSizer.Add(self.dirCtrl, 1, wx.EXPAND|wx.ALL, 10)
+
+ label = wx.StaticText(self, -1, _("Folder:"))
+ textSizer.Add(label, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, 10)
+ textSizer.Add(self.folderText, 1, wx.RIGHT|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 10)
+ mainSizer.Add(textSizer, 0, wx.EXPAND|wx.BOTTOM, 10)
+
+ # Add the fancy buttons
+ bottomSizer.Add(self.newButton, 0, wx.ALL, 10)
+ bottomSizer.Add((0, 0), 1, wx.EXPAND)
+ bottomSizer.Add(self.okButton, 0, wx.TOP|wx.BOTTOM, 10)
+ bottomSizer.Add(self.cancelButton, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 10)
+ mainSizer.Add(bottomSizer, 0, wx.EXPAND)
+
+ # Layout the dialog
+ self.SetSizer(mainSizer)
+ mainSizer.Layout()
+ mainSizer.Fit(self)
+ mainSizer.SetSizeHints(self)
+
+
+ def GetPaths(self):
+ """ Returns the folders selected by the user, or the default path. """
+
+ # Retrieve the tree control and the selections the
+ # user has made
+ treeCtrl = self.dirCtrl.GetTreeCtrl()
+ selections = treeCtrl.GetSelections()
+
+ folders = []
+
+ # Loop recursively over the selected folder and its sub-direcories
+ for select in selections:
+ itemText = treeCtrl.GetItemText(select)
+ # Recurse on it.
+ folder = self.RecurseTopDir(treeCtrl, select, itemText)
+ folders.append(os.path.normpath(folder))
+
+ return folders
+
+
+ def RecurseTopDir(self, treeCtrl, item, itemText):
+ """
+ Recurse a directory tree to include the parent-folder.
+
+ :param `treeCtrl`: the tree control associated with teh internal :class:`GenericDirCtrl`;
+ :param `item`: the selected tree control item;
+ :param `itemText`: the selected tree control item text.
+ """
+
+ # Get the item parent
+ parent = treeCtrl.GetItemParent(item)
+ if parent != treeCtrl.GetRootItem():
+ # Not the root item, recurse again on it
+ itemText = treeCtrl.GetItemText(parent) + "/" + itemText
+ itemText = self.RecurseTopDir(treeCtrl, parent, itemText)
+
+ return itemText
+
+
+ def BindEvents(self):
+ """ Binds the events to specific methods. """
+
+ self.Bind(wx.EVT_BUTTON, self.OnOk, self.okButton)
+ self.Bind(wx.EVT_BUTTON, self.OnCancel, self.cancelButton)
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.Bind(wx.EVT_CHAR_HOOK, self.OnKeyUp)
+ self.dirCtrl.GetTreeCtrl().Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged)
+
+
+ def CreateButtons(self):
+ """ Creates the ``OK``, ``Cancel`` and ``Make New Folder`` bitmap buttons. """
+
+ # Build a couple of fancy buttons
+ self.newButton = buttons.ThemedGenBitmapTextButton(self, wx.ID_NEW, _new.GetBitmap(),
+ _("Make New Folder"), size=(-1, 28))
+ self.okButton = buttons.ThemedGenBitmapTextButton(self, wx.ID_OK, _ok.GetBitmap(),
+ _("OK"), size=(-1, 28))
+ self.cancelButton = buttons.ThemedGenBitmapTextButton(self, wx.ID_CANCEL, _cancel.GetBitmap(),
+ _("Cancel"), size=(-1, 28))
+
+
+ def OnOk(self, event):
+ """
+ Handles the ``wx.EVT_BUTTON`` event for the dialog.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+
+ :note: This method handles the ``OK`` button press.
+ """
+
+ self.EndModal(wx.ID_OK)
+
+
+ def OnCancel(self, event):
+ """
+ Handles the ``wx.EVT_BUTTON`` event for the dialog.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+
+ :note: This method handles the ``Cancel`` button press.
+ """
+
+ self.OnClose(event)
+
+
+ def OnClose(self, event):
+ """
+ Handles the ``wx.EVT_CLOSE`` event for the dialog.
+
+ :param `event`: a :class:`CloseEvent` event to be processed.
+ """
+
+ self.EndModal(wx.ID_CANCEL)
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_CHAR_HOOK`` event for the dialog.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if event.GetKeyCode() == wx.WXK_ESCAPE:
+ # Close the dialog, no action
+ self.OnClose(event)
+ elif event.GetKeyCode() in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
+ # Close the dialog, the user wants to continue
+ self.OnOk(event)
+
+ event.Skip()
+
+
+ def OnSelChanged(self, event):
+ """
+ Handles the ``wx.EVT_TREE_SEL_CHANGED`` event for the tree control associated
+ with :class:`MultiDirDialog`.
+
+ :param `event`: a :class:`TreeEvent` event to be processed.
+ """
+
+ if self.IsBeingDeleted():
+ # We are being destroyed...
+ event.Skip()
+ return
+
+ item = event.GetItem()
+ if not item.IsOk():
+ # Bad item?
+ event.Skip()
+ return
+
+ treeCtrl = self.dirCtrl.GetTreeCtrl()
+ text = treeCtrl.GetItemText(item)
+ # Set the item name into the text control
+ self.folderText.SetValue(text)
+ self.folderText.Refresh()
+
+ event.Skip()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/peakmeter.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/peakmeter.py
new file mode 100644
index 0000000..2753b7c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/peakmeter.py
@@ -0,0 +1,957 @@
+# --------------------------------------------------------------------------------- #
+# PEAKMETERCTRL wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 07 October 2008
+# Latest Revision: 31 Jul 2014, 21.00 GMT
+#
+#
+# TODO List
+#
+# 1) Possibly some nicer drawing of bands and leds (using GraphicsContext).
+#
+#
+# For all kind of problems, requests of enhancements and bug reports, please
+# write to me at:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, obviously, to the wxPython mailing list!!!
+#
+#
+# Changes made by Mike Stover:
+# Inverted Vertical style added
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`PeakMeterCtrl` mimics the behaviour of equalizers that are usually found in stereos
+and MP3 players.
+
+
+Description
+===========
+
+:class:`PeakMeterCtrl` mimics the behaviour of equalizers that are usually found in stereos
+and MP3 players. This widgets supports:
+
+* Vertical and horizontal led bands;
+* Settings number of bands and leds per band;
+* Possibility to change the colour for low/medium/high band frequencies;
+* Falloff effects;
+* Showing a background grid for the bands.
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import random
+
+ import wx.lib.agw.peakmeter as PM
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "PeakMeterCtrl Demo")
+
+ panel = wx.Panel(self)
+
+ # Initialize Peak Meter control 1
+ self.vertPeak = PM.PeakMeterCtrl(panel, -1, style=wx.SIMPLE_BORDER, agwStyle=PM.PM_VERTICAL)
+ # Initialize Peak Meter control 2
+ self.horzPeak = PM.PeakMeterCtrl(panel, -1, style=wx.SUNKEN_BORDER, agwStyle=PM.PM_HORIZONTAL)
+
+ self.vertPeak.SetMeterBands(10, 15)
+ self.horzPeak.SetMeterBands(10, 15)
+
+ # Layout the two PeakMeterCtrl
+ mainSizer = wx.BoxSizer(wx.HORIZONTAL)
+ mainSizer.Add(self.vertPeak, 0, wx.EXPAND|wx.ALL, 15)
+ mainSizer.Add(self.horzPeak, 0, wx.EXPAND|wx.ALL, 15)
+
+ panel.SetSizer(mainSizer)
+ mainSizer.Layout()
+
+ self.timer = wx.Timer(self)
+ self.Bind(wx.EVT_TIMER, self.OnTimer)
+
+ wx.CallLater(500, self.Start)
+
+
+ def Start(self):
+ ''' Starts the PeakMeterCtrl. '''
+
+ self.timer.Start(1000/2) # 2 fps
+
+ self.vertPeak.Start(1000/18) # 18 fps
+ self.horzPeak.Start(1000/20) # 20 fps
+
+
+ def OnTimer(self, event):
+ '''
+ Handles the ``wx.EVT_TIMER`` event for :class:`PeakMeterCtrl`.
+
+ :param `event`: a :class:`TimerEvent` event to be processed.
+ '''
+
+ # Generate 15 random number and set them as data for the meter
+ nElements = 15
+ arrayData = []
+
+ for i in xrange(nElements):
+ nRandom = random.randint(0, 100)
+ arrayData.append(nRandom)
+
+ self.vertPeak.SetData(arrayData, 0, nElements)
+ self.horzPeak.SetData(arrayData, 0, nElements)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`PeakMeterCtrl` has been tested on the following platforms:
+ * Windows (Windows XP).
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+======================== =========== ========================================================
+Window Styles Hex Value Description
+======================== =========== ========================================================
+``PM_HORIZONTAL`` 0x0 Shows horizontal bands in :class:`PeakMeterCtrl`.
+``PM_VERTICAL`` 0x1 Shows vertical bands in :class:`PeakMeterCtrl`.
+``PM_VERTICAL_INVERTED`` 0x2 Shows inverted vertical bands in :class:`PeakMeterCtrl`.
+======================== =========== ========================================================
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`PeakMeterCtrl` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 31 Jul 2014, 21.00 GMT
+
+Version 0.3
+
+"""
+
+import wx
+
+# Horizontal or vertical PeakMeterCtrl
+PM_HORIZONTAL = 0
+""" Shows horizontal bands in :class:`PeakMeterCtrl`. """
+PM_VERTICAL = 1
+""" Shows vertical bands in :class:`PeakMeterCtrl`. """
+PM_VERTICAL_INVERTED = 2
+""" Shows inverted vertical bands in :class:`PeakMeterCtrl`. """
+
+# Some useful constants...
+BAND_DEFAULT = 8
+""" Number of bands in the :class:`PeakMeterCtrl`. """
+LEDS_DEFAULT = 8
+""" Number of leds per band in the :class:`PeakMeterCtrl`. """
+BAND_PERCENT = 10 # 10% of Max Range (Auto Decrease)
+""" 10% of max range (auto decrease). """
+GRID_INCREASEBY = 15 # Increase Grid colour based on Background colour
+""" Increase grid colour based on background colour. """
+FALL_INCREASEBY = 60 # Increase Falloff colour based on Background
+""" Increase falloff colour based on background colour. """
+DEFAULT_SPEED = 10
+""" Default increase/decrease speed. """
+
+
+def InRange(val, valMin, valMax):
+ """
+ Returns whether the value `val` is between `valMin` and `valMax`.
+
+ :param `val`: the value to test;
+ :param `valMin`: the minimum range value;
+ :param `valMax`: the maximum range value.
+ """
+
+ return val >= valMin and val <= valMax
+
+
+def LightenColour(crColour, byIncreaseVal):
+ """
+ Lightens a colour.
+
+ :param `crColour`: a valid :class:`Colour` object;
+ :param `byIncreaseVal`: an integer specifying the amount for which the input
+ colour should be brightened.
+ """
+
+ byRed = crColour.Red()
+ byGreen = crColour.Green()
+ byBlue = crColour.Blue()
+
+ byRed = (byRed + byIncreaseVal <= 255 and [byRed + byIncreaseVal] or [255])[0]
+ byGreen = (byGreen + byIncreaseVal <= 255 and [byGreen + byIncreaseVal] or [255])[0]
+ byBlue = (byBlue + byIncreaseVal <= 255 and [byBlue + byIncreaseVal] or [255])[0]
+
+ return wx.Colour(byRed, byGreen, byBlue)
+
+
+def DarkenColour(crColour, byReduceVal):
+ """
+ Darkens a colour.
+
+ :param `crColour`: a valid :class:`Colour` object;
+ :param `byReduceVal`: an integer specifying the amount for which the input
+ colour should be darkened.
+ """
+
+ byRed = crColour.Red()
+ byGreen = crColour.Green()
+ byBlue = crColour.Blue()
+
+ byRed = (byRed >= byReduceVal and [byRed - byReduceVal] or [0])[0]
+ byGreen = (byGreen >= byReduceVal and [byGreen - byReduceVal] or [0])[0]
+ byBlue = (byBlue >= byReduceVal and [byBlue - byReduceVal] or [0])[0]
+
+ return wx.Colour(byRed, byGreen, byBlue)
+
+
+class PeakMeterData(object):
+ """ A simple class which holds data for our :class:`PeakMeterCtrl`. """
+
+ def __init__(self, value=0, falloff=0, peak=0):
+ """
+ Default class constructor.
+
+ :param `value`: the current :class:`PeakMeterCtrl` value;
+ :param `falloff`: the falloff effect. ``True`` to enable it, ``False`` to
+ disable it;
+ :param `peak`: the peak value.
+ """
+
+ self._value = value
+ self._falloff = falloff
+ self._peak = peak
+
+
+ def IsEqual(self, pm):
+ """
+ Returns whether 2 instances of :class:`PeakMeterData` are the same.
+
+ :param `pm`: another instance of :class:`PeakMeterData`.
+ """
+
+ return self._value == pm._value
+
+
+ def IsGreater(self, pm):
+ """
+ Returns whether one :class:`PeakMeterData` is greater than another.
+
+ :param `pm`: another instance of :class:`PeakMeterData`.
+ """
+
+ return self._value > pm._value
+
+
+ def IsLower(self, pm):
+ """
+ Returns whether one :class:`PeakMeterData` is smaller than another.
+
+ :param `pm`: another instance of :class:`PeakMeterData`.
+ """
+
+ return self._value < pm._value
+
+
+class PeakMeterCtrl(wx.PyControl):
+ """ The main :class:`PeakMeterCtrl` implementation. """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=PM_VERTICAL):
+ """
+ Default class constructor.
+
+ :param parent: the :class:`PeakMeterCtrl` parent. Must not be ``None``
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`PyControl` window style;
+ :param `agwStyle`: the AGW-specific window style, which can be one of the following bits:
+
+ ======================== =========== ========================================================
+ Window Styles Hex Value Description
+ ======================== =========== ========================================================
+ ``PM_HORIZONTAL`` 0x0 Shows horizontal bands in :class:`PeakMeterCtrl`.
+ ``PM_VERTICAL`` 0x1 Shows vertical bands in :class:`PeakMeterCtrl`.
+ ``PM_VERTICAL_INVERTED`` 0x2 Shows inverted vertical bands in :class:`PeakMeterCtrl`.
+ ======================== =========== ========================================================
+
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ self._agwStyle = agwStyle
+ # Initializes all data
+ self.InitData()
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_TIMER, self.OnTimer)
+
+
+ def InitData(self):
+ """ Initializes the control. """
+
+ colLime = wx.Colour(0, 255, 0)
+ colRed = wx.Colour(255, 0, 0)
+ colYellow = wx.Colour(255, 255, 0)
+
+ self._showGrid = False
+ self._showFalloff = True
+ self._delay = 10
+ self._minValue = 60 # Min Range 0-60
+ self._medValue = 80 # Med Range 60-80
+ self._maxValue = 100 # Max Range 80-100
+ self._numBands = BAND_DEFAULT
+ self._ledBands = LEDS_DEFAULT
+ self._clrBackground = self.GetBackgroundColour()
+ self._clrNormal = colLime
+ self._clrMedium = colYellow
+ self._clrHigh = colRed
+ self._speed = DEFAULT_SPEED
+ self._timer = wx.Timer(self)
+
+ # clear vector data
+ self._meterData = []
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the :class:`PeakMeterCtrl` window style flags.
+
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ ======================== =========== ========================================================
+ Window Styles Hex Value Description
+ ======================== =========== ========================================================
+ ``PM_HORIZONTAL`` 0x0 Shows horizontal bands in :class:`PeakMeterCtrl`.
+ ``PM_VERTICAL`` 0x1 Shows vertical bands in :class:`PeakMeterCtrl`.
+ ``PM_VERTICAL_INVERTED`` 0x2 Shows inverted vertical bands in :class:`PeakMeterCtrl`.
+ ======================== =========== ========================================================
+
+ """
+
+ self._agwStyle = agwStyle
+ self.Refresh()
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`PeakMeterCtrl` window style.
+
+ :see: :meth:`PeakMeterCtrl.SetAGWWindowStyleFlag` for a list of possible window style flags.
+ """
+
+ return self._agwStyle
+
+
+ def ResetControl(self):
+ """ Resets the :class:`PeakMeterCtrl`. """
+
+ # Initialize vector
+ for i in xrange(self._numBands):
+ pm = PeakMeterData(self._maxValue, self._maxValue, self._speed)
+ self._meterData.append(pm)
+
+ self.Refresh()
+
+
+ def SetBackgroundColour(self, colourBgnd):
+ """
+ Changes the background colour of :class:`PeakMeterCtrl`.
+
+ :param `colourBgnd`: the colour to be used as the background colour, pass
+ :class:`NullColour` to reset to the default colour.
+
+ :note: The background colour is usually painted by the default :class:`EraseEvent`
+ event handler function under Windows and automatically under GTK.
+
+ :note: Setting the background colour does not cause an immediate refresh, so
+ you may wish to call :meth:`Window.ClearBackground` or :meth:`Window.Refresh` after
+ calling this function.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ wx.PyControl.SetBackgroundColour(self, colourBgnd)
+ self._clrBackground = colourBgnd
+ self.Refresh()
+
+
+ def SetBandsColour(self, colourNormal, colourMedium, colourHigh):
+ """
+ Set bands colour for :class:`PeakMeterCtrl`.
+
+ :param `colourNormal`: the colour for normal (low) bands, a valid :class:`Colour`
+ object;
+ :param `colourMedium`: the colour for medium bands, a valid :class:`Colour`
+ object;
+ :param `colourHigh`: the colour for high bands, a valid :class:`Colour`
+ object.
+ """
+
+ self._clrNormal = colourNormal
+ self._clrMedium = colourMedium
+ self._clrHigh = colourHigh
+
+ self.Refresh()
+
+
+ def SetMeterBands(self, numBands, ledBands):
+ """
+ Set number of vertical or horizontal bands to display.
+
+ :param `numBands`: number of bands to display (either vertical or horizontal);
+ :param `ledBands`: the number of leds per band.
+
+ :note: You can obtain a smooth effect by setting `nHorz` or `nVert` to "1", these
+ cannot be 0.
+ """
+
+ assert (numBands > 0 and ledBands > 0)
+
+ self._numBands = numBands
+ self._ledBands = ledBands
+
+ # Reset vector
+ self.ResetControl()
+
+
+ def SetRangeValue(self, minVal, medVal, maxVal):
+ """
+ Sets the ranges for low, medium and high bands.
+
+ :param `minVal`: the value for low bands;
+ :param `medVal`: the value for medium bands;
+ :param `maxVal`: the value for high bands.
+
+ :note: The conditions to be satisfied are:
+
+ Min: [0 - nMin[, Med: [nMin - nMed[, Max: [nMed - nMax]
+
+ """
+
+ assert (maxVal > medVal and medVal > minVal and minVal > 0)
+
+ self._minValue = minVal
+ self._medValue = medVal
+ self._maxValue = maxVal
+
+
+ def GetRangeValue(self):
+ """ Get range value of :class:`PeakMeterCtrl`. """
+
+ return self._minValue, self._medValue, self._maxValue
+
+
+ def SetFalloffDelay(self, speed):
+ """
+ Set peak value speed before falling off.
+
+ :param `speed`: the speed at which the falloff happens.
+ """
+
+ self._speed = speed
+
+
+ def SetFalloffEffect(self, falloffEffect):
+ """
+ Set falloff effect flag.
+
+ :param `falloffEffect`: ``True`` to enable the falloff effect, ``False``
+ to disable it.
+ """
+
+ if self._showFalloff != falloffEffect:
+
+ self._showFalloff = falloffEffect
+ self.Refresh()
+
+
+ def GetFalloffEffect(self):
+ """ Returns the falloff effect flag. """
+
+ return self._showFalloff
+
+
+ def ShowGrid(self, showGrid):
+ """
+ Request to have gridlines visible or not.
+
+ :param `showGrid`: ``True`` to show grid lines, ``False`` otherwise.
+ """
+
+ if self._showGrid != showGrid:
+
+ self._showGrid = showGrid
+ self.Refresh()
+
+
+ def IsGridVisible(self):
+ """ Returns if gridlines are visible. """
+
+ return self._showGrid
+
+
+ def SetData(self, arrayValue, offset, size):
+ """
+ Change data value. Use this function to change only
+ a set of values. All bands can be changed or only 1 band,
+ depending on the application.
+
+ :param `arrayValue`: a Python list containing the :class:`PeakMeterData` values;
+ :param `offset`: the (optional) offset where to start applying the new data;
+ :param `size`: the size of the input data.
+ """
+
+ assert (offset >= 0 and arrayValue != [])
+
+ isRunning = self.IsStarted()
+
+ # Stop timer if Animation is active
+ if isRunning:
+ self.Stop()
+
+ maxSize = offset + size
+
+ for i in xrange(offset, maxSize):
+
+ if i < len(self._meterData):
+
+ pm = self._meterData[i]
+ pm._value = arrayValue[i]
+
+ if pm._falloff < pm._value:
+
+ pm._falloff = pm._value
+ pm._peak = self._speed
+
+ self._meterData[i] = pm
+
+ # Auto-restart
+ if isRunning:
+ return self.Start(self._delay)
+
+ self.Refresh()
+
+ return True
+
+
+ def IsStarted(self):
+ """ Check if animation is active. """
+
+ return self._timer.IsRunning()
+
+
+ def Start(self, delay):
+ """
+ Start the timer and animation effect.
+
+ :param `delay`: the animation effect delay, in milliseconds.
+ """
+
+ if not self.IsStarted():
+ self._delay = delay
+ self._timer.Start(self._delay)
+ else:
+ return False
+
+ return True
+
+
+ def Stop(self):
+ """ Stop the timer and animation effect. """
+
+ if self.IsStarted():
+ self._timer.Stop()
+ return True
+
+ return False
+
+
+ def DoTimerProcessing(self):
+ """ :class:`PeakMeterCtrl` animation, does the ``wx.EVT_TIMER`` processing. """
+
+ self.Refresh()
+
+ decValue = self._maxValue/self._ledBands
+ noChange = True
+
+ for pm in self._meterData:
+
+ if pm._value > 0:
+
+ pm._value -= (self._ledBands > 1 and [decValue] or [self._maxValue*BAND_PERCENT/100])[0]
+ if pm._value < 0:
+ pm._value = 0
+
+ noChange = False
+
+ if pm._peak > 0:
+
+ pm._peak -= 1
+ noChange = False
+
+
+ if pm._peak == 0 and pm._falloff > 0:
+
+ pm._falloff -= (self._ledBands > 1 and [decValue >> 1] or [5])[0]
+ if pm._falloff < 0:
+ pm._falloff = 0
+
+ noChange = False
+
+ if noChange: # Stop timer if no more data
+
+ self.Stop()
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ # something is better than nothing...
+ return wx.Size(200, 150)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`PeakMeterCtrl`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+ self._clrBackground = self.GetBackgroundColour()
+ dc.SetBackground(wx.Brush(self._clrBackground))
+ dc.Clear()
+ rc = self.GetClientRect()
+
+ pen = wx.Pen(self._clrBackground)
+ dc.SetPen(pen)
+
+ if self.GetAGWWindowStyleFlag() & PM_VERTICAL:
+ self.DrawVertBand(dc, rc)
+ elif self.GetAGWWindowStyleFlag() & PM_VERTICAL_INVERTED:
+ self.DrawVertBandInverted(dc, rc)
+ else:
+ self.DrawHorzBand(dc, rc)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`PeakMeterCtrl`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ # This is intentionally empty, to reduce flicker
+ pass
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`PeakMeterCtrl`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Refresh()
+ event.Skip()
+
+
+ def OnTimer(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`PeakMeterCtrl`.
+
+ :param `event`: a :class:`TimerEvent` event to be processed.
+ """
+
+ self.DoTimerProcessing()
+
+
+ def DrawHorzBand(self, dc, rect):
+ """
+ Draws horizontal bands.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the horizontal bands client rectangle.
+
+ .. todo:: Implement falloff effect for horizontal bands.
+ """
+
+ horzBands = (self._ledBands > 1 and [self._ledBands] or [self._maxValue*BAND_PERCENT/100])[0]
+ minHorzLimit = self._minValue*horzBands/self._maxValue
+ medHorzLimit = self._medValue*horzBands/self._maxValue
+ maxHorzLimit = horzBands
+
+ size = wx.Size(rect.width/horzBands, rect.height/self._numBands)
+ rectBand = wx.RectPS(rect.GetTopLeft(), size)
+
+ # Draw band from top
+ rectBand.OffsetXY(0, rect.height-size.y*self._numBands)
+ xDecal = (self._ledBands > 1 and [1] or [0])[0]
+ yDecal = (self._numBands > 1 and [1] or [0])[0]
+
+ for vert in xrange(self._numBands):
+
+ self._value = self._meterData[vert]._value
+ horzLimit = self._value*horzBands/self._maxValue
+ rectPrev = wx.Rect(*rectBand)
+
+ for horz in xrange(horzBands):
+
+ rectBand.Deflate(0, yDecal)
+
+ # Find colour based on range value
+ colourRect = self._clrBackground
+ if self._showGrid:
+ colourRect = DarkenColour(self._clrBackground, GRID_INCREASEBY)
+
+ if self._showGrid and (horz == minHorzLimit or horz == (horzBands-1)):
+
+ points = [wx.Point() for i in xrange(2)]
+ points[0].x = rectBand.GetTopLeft().x + (rectBand.width >> 1)
+ points[0].y = rectBand.GetTopLeft().y - yDecal
+ points[1].x = points[0].x
+ points[1].y = rectBand.GetBottomRight().y + yDecal
+ dc.DrawLinePoint(points[0], points[1])
+
+ if horz < horzLimit:
+
+ if InRange(horz, 0, minHorzLimit-1):
+ colourRect = self._clrNormal
+ elif InRange(horz, minHorzLimit, medHorzLimit-1):
+ colourRect = self._clrMedium
+ elif InRange(horz, medHorzLimit, maxHorzLimit):
+ colourRect = self._clrHigh
+
+ dc.SetBrush(wx.Brush(colourRect))
+ dc.DrawRectangleRect(rectBand)
+
+ rectBand.Inflate(0, yDecal)
+ rectBand.OffsetXY(size.x, 0)
+
+ # Draw falloff effect (Seems to be working now.)
+ if self._showFalloff:
+ oldPen = dc.GetPen()
+ pen = wx.Pen(DarkenColour(self._clrBackground, FALL_INCREASEBY))
+ maxWidth = size.x*horzBands
+ points = [wx.Point() for i in xrange(2)]
+ points[0].y = rectPrev.GetTopRight().y - yDecal
+ points[0].x = rectPrev.GetBottomLeft().x + self._meterData[vert]._falloff*maxWidth/self._maxValue
+ points[1].y = rectPrev.GetBottomLeft().y + yDecal
+ points[1].x = points[0].x
+ dc.SetPen(pen)
+ dc.DrawLinePoint(points[0], points[1])
+ dc.SetPen(oldPen)
+
+ # Move to Next Vertical band
+ rectBand.OffsetXY(-size.x*horzBands, size.y)
+
+
+ def DrawVertBand(self, dc, rect):
+ """
+ Draws vertical bands.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the vertical bands client rectangle.
+ """
+
+ vertBands = (self._ledBands > 1 and [self._ledBands] or [self._maxValue*BAND_PERCENT/100])[0]
+ minVertLimit = self._minValue*vertBands/self._maxValue
+ medVertLimit = self._medValue*vertBands/self._maxValue
+ maxVertLimit = vertBands
+
+ size = wx.Size(rect.width/self._numBands, rect.height/vertBands)
+ rectBand = wx.RectPS(rect.GetTopLeft(), size)
+
+ # Draw band from bottom
+ rectBand.OffsetXY(0, rect.bottom-size.y)
+ xDecal = (self._numBands > 1 and [1] or [0])[0]
+ yDecal = (self._ledBands > 1 and [1] or [0])[0]
+
+ for horz in xrange(self._numBands):
+
+ self._value = self._meterData[horz]._value
+ vertLimit = self._value*vertBands/self._maxValue
+ rectPrev = wx.Rect(*rectBand)
+
+ for vert in xrange(vertBands):
+
+ rectBand.Deflate(xDecal, 0)
+
+ # Find colour based on range value
+ colourRect = self._clrBackground
+ if self._showGrid:
+ colourRect = DarkenColour(self._clrBackground, GRID_INCREASEBY)
+
+ # Draw grid line (level) bar
+ if self._showGrid and (vert == minVertLimit or vert == (vertBands-1)):
+
+ points = [wx.Point() for i in xrange(2)]
+ points[0].x = rectBand.GetTopLeft().x - xDecal
+ points[0].y = rectBand.GetTopLeft().y + (rectBand.height >> 1)
+ points[1].x = rectBand.GetBottomRight().x + xDecal
+ points[1].y = points[0].y
+ dc.DrawLinePoint(points[0], points[1])
+
+ if vert < vertLimit:
+
+ if InRange(vert, 0, minVertLimit-1):
+ colourRect = self._clrNormal
+ elif InRange(vert, minVertLimit, medVertLimit-1):
+ colourRect = self._clrMedium
+ elif InRange(vert, medVertLimit, maxVertLimit):
+ colourRect = self._clrHigh
+
+ dc.SetBrush(wx.Brush(colourRect))
+ dc.DrawRectangleRect(rectBand)
+
+ rectBand.Inflate(xDecal, 0)
+ rectBand.OffsetXY(0, -size.y)
+
+ # Draw falloff effect
+ if self._showFalloff:
+
+ oldPen = dc.GetPen()
+ pen = wx.Pen(DarkenColour(self._clrBackground, FALL_INCREASEBY))
+ maxHeight = size.y*vertBands
+ points = [wx.Point() for i in xrange(2)]
+ points[0].x = rectPrev.GetTopLeft().x + xDecal
+ points[0].y = rectPrev.GetBottomRight().y - self._meterData[horz]._falloff*maxHeight/self._maxValue
+ points[1].x = rectPrev.GetBottomRight().x - xDecal
+ points[1].y = points[0].y
+ dc.SetPen(pen)
+ dc.DrawLinePoint(points[0], points[1])
+ dc.SetPen(oldPen)
+
+ # Move to Next Horizontal band
+ rectBand.OffsetXY(size.x, size.y*vertBands)
+
+
+ def DrawVertBandInverted(self, dc, rect):
+ """
+ Draws vertical bands inverted.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the vertical bands client rectangle.
+ """
+
+ vertBands = (self._ledBands > 1 and [self._ledBands] or [self._maxValue*BAND_PERCENT/100])[0]
+ minVertLimit = self._minValue*vertBands/self._maxValue
+ medVertLimit = self._medValue*vertBands/self._maxValue
+ maxVertLimit = vertBands
+
+ size = wx.Size(rect.width/self._numBands, rect.height/vertBands)
+ rectBand = wx.RectPS(rect.GetTopLeft(), size)
+
+ # Draw band from top?
+ rectBand.OffsetXY(0, 0)
+ xDecal = (self._numBands > 1 and [1] or [0])[0]
+ yDecal = (self._ledBands > 1 and [1] or [0])[0]
+
+ for horz in xrange(self._numBands):
+
+ self._value = self._meterData[horz]._value
+ vertLimit = self._value*vertBands/self._maxValue
+ rectPrev = wx.Rect(*rectBand)
+
+ for vert in xrange(vertBands):
+
+ rectBand.Deflate(xDecal, 0)
+
+ # Find colour based on range value
+ colourRect = self._clrBackground
+ if self._showGrid:
+ colourRect = DarkenColour(self._clrBackground, GRID_INCREASEBY)
+
+ # Draw grid line (level) bar
+ if self._showGrid and (vert == minVertLimit or vert == (vertBands-1)):
+
+ points = [wx.Point() for i in xrange(2)]
+ points[0].x = rectBand.GetTopLeft().x - xDecal
+ points[0].y = rectBand.GetTopLeft().y + (rectBand.height >> 1)
+ points[1].x = rectBand.GetBottomRight().x + xDecal
+ points[1].y = points[0].y
+ dc.DrawLinePoint(points[0], points[1])
+
+ if vert < vertLimit:
+
+ if InRange(vert, 0, minVertLimit-1):
+ colourRect = self._clrNormal
+ elif InRange(vert, minVertLimit, medVertLimit-1):
+ colourRect = self._clrMedium
+ elif InRange(vert, medVertLimit, maxVertLimit):
+ colourRect = self._clrHigh
+
+ dc.SetBrush(wx.Brush(colourRect))
+ dc.DrawRectangleRect(rectBand)
+
+ rectBand.Inflate(xDecal, 0)
+ rectBand.OffsetXY(0, size.y)
+
+ # Draw falloff effect
+ if self._showFalloff:
+
+ oldPen = dc.GetPen()
+ pen = wx.Pen(DarkenColour(self._clrBackground, FALL_INCREASEBY))
+ maxHeight = -size.y*vertBands
+ points = [wx.Point() for i in xrange(2)]
+ points[0].x = rectPrev.GetBottomLeft().x + xDecal
+ points[0].y = rectPrev.GetTopRight().y - self._meterData[horz]._falloff*maxHeight/self._maxValue
+ points[1].x = rectPrev.GetTopRight().x - xDecal
+ points[1].y = points[0].y
+ dc.SetPen(pen)
+ dc.DrawLinePoint(points[0], points[1])
+ dc.SetPen(oldPen)
+
+ # Move to Next Horizontal band
+ rectBand.OffsetXY(size.x, -size.y*vertBands)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/__init__.py
new file mode 100644
index 0000000..9c5e70b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/__init__.py
@@ -0,0 +1,193 @@
+"""
+Introduction
+============
+
+Persistent objects are simply the objects which automatically save their state
+when they are destroyed and restore it when they are recreated, even during
+another program invocation.
+
+
+.. _persistent-overview:
+
+Persistent Object Overview
+==========================
+
+Most often, persistent objects are, in fact, persistent windows as it is especially
+convenient to automatically restore the UI state when the program is restarted but
+an object of any class can be made persistent. Moreover, persistence is implemented
+in a non-intrusive way so that the original object class doesn't need to be modified
+at all in order to add support for saving and restoring its properties.
+
+The persistence framework involves:
+
+* **PersistenceManager** which all persistent objects register themselves with. This class
+ handles actual saving and restoring of persistent data as well as various global
+ aspects of persistence, e.g. it can be used to disable restoring the saved data;
+* **PersistentObject** is the base class for all persistent objects or, rather, adaptors
+ for the persistent objects as this class main purpose is to provide the bridge between
+ the original class -- which has no special persistence support -- and PersistenceManager;
+* **PersistentHandlers** which handle different kind of saving/restoring actions depending
+ on the widget kind.
+
+
+Using Persistent Windows
+========================
+
+wxPython has built-in support for a (constantly growing) number of controls. Currently the
+following classes are supported:
+
+* wx.TopLevelWindow (and hence wx.Frame and wx.Dialog, together with their own AUI perspectives);
+* wx.MenuBar, FlatMenuBar;
+* AuiToolBar;
+* wx.Notebook, wx.Toolbook, wx.Treebook, wx.Choicebook, wx.aui.AuiNotebook,
+ AuiNotebook (together with its own AUI perspective),
+ FlatNotebook, LabelBook,
+ FlatImageBook;
+* wx.CheckBox;
+* wx.ListBox, wx.VListBox, wx.HtmlListBox, wx.SimpleHtmlListBox, wx.gizmos.EditableListBox;
+* wx.ListCtrl, wx.ListView, UltimateListCtrl;
+* wx.CheckListBox;
+* wx.Choice, wx.ComboBox, wx.combo.OwnerDrawnComboBox;
+* wx.RadioBox;
+* wx.RadioButton;
+* wx.ScrolledWindow, wx.lib.scrolledpanel.ScrolledPanel;
+* wx.Slider, KnobCtrl;
+* wx.SpinButton, wx.SpinCtrl, FloatSpin;
+* wx.SplitterWindow;
+* wx.TextCtrl, wx.SearchCtrl, wx.lib.expando.ExpandoTextCtrl, wx.lib.masked.Ctrl;
+* wx.ToggleButton, wx.lib.buttons.GenToggleButton, wx.lib.buttons.GenBitmapToggleButton,
+ wx.lib.buttons.GenBitmapTextToggleButton, SToggleButton,
+ SBitmapToggleButton, SBitmapTextToggleButton;
+* wx.TreeCtrl, wx.GenericDirCtrl, CustomTreeCtrl;
+* wx.gizmos.TreeListCtrl, HyperTreeList;
+* wx.lib.calendar.CalendarCtrl;
+* wx.CollapsiblePane, PyCollapsiblePane;
+* wx.DatePickerCtrl, wx.GenericDatePickerCtrl;
+* wx.media.MediaCtrl;
+* wx.ColourPickerCtrl, wx.lib.colourselect.ColourSelect;
+* wx.FilePickerCtrl, wx.DirPickerCtrl;
+* wx.FontPickerCtrl;
+* wx.FileHistory;
+* wx.DirDialog, wx.FileDialog;
+* wx.FindReplaceDialog;
+* wx.FontDialog;
+* wx.ColourDialog, CubeColourDialog;
+* FoldPanelBar;
+* wx.SingleChoiceDialog, wx.MultiChoiceDialog;
+* wx.TextEntryDialog, wx.PasswordEntryDialog.
+
+
+To automatically save and restore the properties of the windows of classes listed
+above you need to:
+
+* Set a unique name for the window using `SetName()`: this step is important as the
+ name is used in the configuration file and so must be unique among all windows of
+ the same class;
+* Call `PersistenceManager.Register(window)` at any moment after creating the window
+ and then `PersistenceManager.Restore(window)` when the settings may be restored
+ (which can't be always done immediately, e.g. often the window needs to be populated
+ first). If settings can be restored immediately after the window creation, as is often
+ the case for wx.TopLevelWindow, for example, then `PersistenceManager.RegisterAndRestore(window)`
+ can be used to do both at once.
+* If you want the settings for the window to be saved when your main frame is destroyed (or your app closes), simply call
+ `PersistenceManager.SaveAndUnregister(window)` with no arguments.
+
+
+Usage
+=====
+
+Example of using a notebook control which automatically remembers the last open page::
+
+ import wx, os
+ import wx.lib.agw.persist as PM
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "Persistent Controls Demo")
+
+ self.book = wx.Notebook(self, wx.ID_ANY)
+
+ # Very important step!!
+ self.book.SetName("MyBook") # Do not use the default name!!
+
+ self.book.AddPage(wx.Panel(self.book), "Hello")
+ self.book.AddPage(wx.Panel(self.book), "World")
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+ self._persistMgr = PM.PersistenceManager.Get()
+
+ _configFile = os.path.join(os.getcwd(), self.book.GetName())
+ self._persistMgr.SetPersistenceFile(_configFile)
+
+ if not self._persistMgr.RegisterAndRestoreAll(self.book):
+ # Nothing was restored, so choose the default page ourselves
+ self.book.SetSelection(0)
+
+ def OnClose(self, event):
+ self._persistMgr.SaveAndUnregister(self.book)
+ event.Skip()
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+.. _persistent-windows:
+
+Defining Custom Persistent Windows
+==================================
+
+User-defined classes can be easily integrated with PersistenceManager. To add support
+for your custom class MyWidget you just need to:
+
+* Define a MyWidgetHandler class inheriting from `AbstractHandler`;
+* Implement its `GetKind()` method returning a unique string identifying all MyWidget
+ objects, typically something like "widget";
+* Implement its `Save()` and `Restore()` methods to actually save and restore the widget
+ settings using `PersistentObject.SaveValue()` and `PersistentObject.RestoreValue()` methods.
+
+If you want to add persistence support for a class not deriving from wx.Window, you need
+to derive MyPersistentWidget directly from PersistentObject and so implement its
+`PersistentObject.GetName()` method too. Additionally, you must ensure that
+`PersistenceManager.SaveAndUnregister()` is called when your object is destroyed as this
+can be only done automatically for windows.
+
+
+TODOs
+=====
+
+* Find a way to handle :class:`ToolBar` UI settings as it has been done for :class:`~lib.agw.aui.auibar.AuiToolBar`:
+ current :class:`ToolBar` doesn't seem to have easy access to the underlying toolbar tools;
+* Implement handler(s) for :class:`grid.Grid` for row/columns sizes (possibly adding another style
+ to `PersistenceManager` as :class:`grid.Grid` sets up arrays to store individual row and column
+ sizes when non-default sizes are used. The memory requirements for this could become prohibitive
+ if the grid is very large);
+* Find a way to properly save and restore dialog data (:class:`ColourDialog`, :class:`FontDialog` etc...);
+* Add handlers for the remaining widgets not yet wrapped (mostly in :mod:`lib`).
+
+
+License And Version
+===================
+
+`PersistentObjects` library is distributed under the wxPython license.
+
+Latest revision: Andrea Gavana @ 27 Mar 2013, 21.00 GMT
+Version 0.4.
+
+"""
+
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "16 November 2009"
+
+
+from persist_constants import *
+from persistencemanager import *
+from persist_handlers import *
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persist_constants.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persist_constants.py
new file mode 100644
index 0000000..3c77145
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persist_constants.py
@@ -0,0 +1,263 @@
+"""
+This module contains all the constants used by the persistent objects.
+"""
+
+import wx
+
+# ----------------------------------------------------------------------------------- #
+# PersistenceManager styles
+
+PM_SAVE_RESTORE_AUI_PERSPECTIVES = 1 << 0
+PM_SAVE_RESTORE_TREE_LIST_SELECTIONS = 1 << 1
+PM_PERSIST_CONTROL_VALUE = 1 << 2
+PM_RESTORE_CAPTION_FROM_CODE = 1 << 3
+PM_DEFAULT_STYLE = PM_SAVE_RESTORE_AUI_PERSPECTIVES | PM_PERSIST_CONTROL_VALUE
+
+# ----------------------------------------------------------------------------------- #
+CONFIG_PATH_SEPARATOR = "/"
+
+BAD_DEFAULT_NAMES = ["widget", "wxSpinButton", "auiFloating", "AuiTabCtrl", "maskedTextCtrl",
+ "numctrl", "IpAddrCtrl", "masked.num", "time", "scrolledpanel", "cPanel"]
+
+for name in dir(wx):
+ if "NameStr" in name:
+ BAD_DEFAULT_NAMES.append(eval("wx.%s"%name))
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by BookHandler
+
+PERSIST_BOOK_KIND = "Book"
+PERSIST_BOOK_SELECTION = "Selection"
+
+# To save and restore wx.lib.agw.aui.AuiNotebook perspectives
+PERSIST_BOOK_AGW_AUI_PERSPECTIVE = "AGWAui_Notebook_Perspective"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by TreebookHandler
+
+PERSIST_TREEBOOK_KIND = "TreeBook"
+
+# this key contains the indices of all expanded nodes in the tree book
+# separated by PERSIST_SEP
+PERSIST_TREEBOOK_EXPANDED_BRANCHES = "Expanded"
+PERSIST_SEP = ','
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by TLWHandler
+
+# we use just "Window" to keep configuration files and such short, there
+# should be no confusion with wx.Window itself as we don't have persistent
+# windows, just persistent controls which have their own specific kind strings
+
+PERSIST_TLW_KIND = "Window"
+
+# Names for various persistent options
+PERSIST_TLW_X = "x"
+PERSIST_TLW_Y = "y"
+PERSIST_TLW_W = "w"
+PERSIST_TLW_H = "h"
+
+PERSIST_TLW_MAXIMIZED = "Maximized"
+PERSIST_TLW_ICONIZED = "Iconized"
+
+# To save and restore wx.aui and wx.lib.agw.aui perspectives
+PERSIST_AGW_AUI_PERSPECTIVE = "AGWAui_Perspective"
+PERSIST_AUI_PERSPECTIVE = "Aui_Perspective"
+
+PERSIST_AUIPERSPECTIVE_KIND = "AUI manager"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by CheckBoxHandler
+
+PERSIST_CHECKBOX_KIND = "CheckBox"
+PERSIST_CHECKBOX_3STATE = "3StateValue"
+PERSIST_CHECKBOX = "Value"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by ListBoxHandler
+
+PERSIST_LISTBOX_KIND = "ListBox"
+PERSIST_LISTBOX_SELECTIONS = "Selections"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by ListCtrlHandler
+
+PERSIST_LISTCTRL_KIND = "ListCtrl"
+PERSIST_LISTCTRL_COLWIDTHS = "ColWidths"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by CheckListBoxHandler
+
+PERSIST_CHECKLISTBOX_KIND = "CheckListBox"
+PERSIST_CHECKLIST_CHECKED = "Checked"
+PERSIST_CHECKLIST_SELECTIONS = "Selections"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by ChoiceComboHandler
+
+PERSIST_CHOICECOMBO_KIND = "ComboBox"
+PERSIST_CHOICECOMBO_SELECTION = "Selection"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by RadioBoxHandler
+
+PERSIST_RADIOBOX_KIND = "RadioBox"
+PERSIST_RADIOBOX_SELECTION = "Selection"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by RadioButtonHandler
+
+PERSIST_RADIOBUTTON_KIND = "RadioButton"
+PERSIST_RADIOBUTTON_VALUE = "Value"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by ScrolledWindowHandler
+
+PERSIST_SCROLLEDWINDOW_KIND = "ScrolledWindow"
+PERSIST_SCROLLEDWINDOW_POS_H = "Scroll_H"
+PERSIST_SCROLLEDWINDOW_POS_V = "Scroll_V"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by SliderHandler
+
+PERSIST_SLIDER_KIND = "Slider"
+PERSIST_SLIDER_VALUE = "Value"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by SpinHandler
+
+PERSIST_SPIN_KIND = "Spin"
+PERSIST_SPIN_VALUE = "Value"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by SplitterHandler
+
+PERSIST_SPLITTER_KIND = "Splitter"
+PERSIST_SPLITTER_POSITION = "Position"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by TextCtrlHandler
+
+PERSIST_TEXTCTRL_KIND = "TextCtrl"
+PERSIST_TEXTCTRL_VALUE = "Value"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by ToggleButtonHandler
+
+PERSIST_TOGGLEBUTTON_KIND = "ToggleButton"
+PERSIST_TOGGLEBUTTON_TOGGLED = "Toggled"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by TreeCtrlHandler
+
+PERSIST_TREECTRL_KIND = "TreeCtrl"
+PERSIST_TREECTRL_CHECKED_ITEMS = "Checked"
+PERSIST_TREECTRL_EXPANSION = "Expansion"
+PERSIST_TREECTRL_SELECTIONS = "Selections"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by TreeListCtrlHandler
+
+PERSIST_TREELISTCTRL_KIND = "TreeListCtrl"
+PERSIST_TREELISTCTRL_COLWIDTHS = "ColWidths"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by CalendarCtrlHandler
+
+PERSIST_CALENDAR_KIND = "Calendar"
+PERSIST_CALENDAR_DATE = "Date"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by CollapsiblePaneHandler
+
+PERSIST_COLLAPSIBLE_KIND = "Collapsible"
+PERSIST_COLLAPSIBLE_STATE = "Collapse"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by DatePickerHandler
+
+PERSIST_DATEPICKER_KIND = "DatePicker"
+PERSIST_DATEPICKER_DATE = "Date"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by MediaCtrlHandler
+
+PERSIST_MEDIA_KIND = "MediaCtrl"
+
+PERSIST_MEDIA_POS = "Seek"
+PERSIST_MEDIA_VOLUME = "Volume"
+PERSIST_MEDIA_RATE = "Rate"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by ColourPickerHandler
+
+PERSIST_COLOURPICKER_KIND = "ColourPicker"
+PERSIST_COLOURPICKER_COLOUR = "Colour"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by FileDirPickerHandler
+
+PERSIST_FILEDIRPICKER_KIND = "FileDirPicker"
+PERSIST_FILEDIRPICKER_PATH = "Path"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by FontPickerHandler
+
+PERSIST_FONTPICKER_KIND = "FontPicker"
+PERSIST_FONTPICKER_FONT = "Font"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by FileHistoryHandler
+
+PERSIST_FILEHISTORY_KIND = "FileHistory"
+PERSIST_FILEHISTORY_PATHS = "Paths"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by FindReplaceHandler
+
+PERSIST_FINDREPLACE_KIND = "FindReplace"
+PERSIST_FINDREPLACE_FLAGS = "Flags"
+PERSIST_FINDREPLACE_SEARCH = "Search"
+PERSIST_FINDREPLACE_REPLACE = "Replace"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by FontDialogHandler
+
+PERSIST_FONTDIALOG_KIND = "FontDialog"
+PERSIST_FONTDIALOG_EFFECTS = "Effects"
+PERSIST_FONTDIALOG_SYMBOLS = "Symbols"
+PERSIST_FONTDIALOG_COLOUR = "Colour"
+PERSIST_FONTDIALOG_FONT = "Font"
+PERSIST_FONTDIALOG_HELP = "Help"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by ColourDialogHandler
+
+PERSIST_COLOURDIALOG_KIND = "ColourDialog"
+PERSIST_COLOURDIALOG_COLOUR = "Colour"
+PERSIST_COLOURDIALOG_CHOOSEFULL = "ChooseFull"
+PERSIST_COLOURDIALOG_CUSTOMCOLOURS = "CustomColours"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by ChoiceDialogHandler
+
+PERSIST_CHOICEDIALOG_KIND = "ChoiceDialog"
+PERSIST_CHOICEDIALOG_SELECTIONS = "Selections"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by MenuBarHandler
+
+PERSIST_MENUBAR_KIND = "MenuBar"
+PERSIST_MENUBAR_CHECKRADIO_ITEMS = "Checked"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by ToolBarHandler
+
+PERSIST_TOOLBAR_KIND = "ToolBar"
+PERSIST_TOOLBAR_CHECKRADIO_ITEMS = "Checked"
+
+# ----------------------------------------------------------------------------------- #
+# String constants used by FoldPanelBarHandler
+
+PERSIST_FOLDPANELBAR_KIND = "FoldPanelBar"
+PERSIST_FOLDPANELBAR_EXPANDED = "FoldpPanelExpanded"
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persist_handlers.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persist_handlers.py
new file mode 100644
index 0000000..c6a5740
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persist_handlers.py
@@ -0,0 +1,2613 @@
+# -*- coding: utf-8 -*-#
+#!/usr/bin/env python2
+"""
+This module contains different classes which handle different kind of saving/restoring
+actions depending on the widget kind.
+"""
+
+import wx
+import types
+import datetime
+
+import wx.aui
+import wx.combo
+import wx.calendar as calendar
+import wx.gizmos
+import wx.media
+
+import wx.lib.scrolledpanel as scrolled
+import wx.lib.expando as expando
+import wx.lib.buttons as buttons
+import wx.lib.masked as masked
+import wx.lib.colourselect as csel
+
+import wx.lib.agw.aui as AUI
+import wx.lib.agw.cubecolourdialog as CCD
+import wx.lib.agw.customtreectrl as CT
+import wx.lib.agw.flatmenu as FM
+import wx.lib.agw.flatnotebook as FNB
+import wx.lib.agw.floatspin as FS
+import wx.lib.agw.foldpanelbar as FPB
+import wx.lib.agw.hypertreelist as HTL
+import wx.lib.agw.knobctrl as KC
+import wx.lib.agw.labelbook as LBK
+import wx.lib.agw.pycollapsiblepane as PCP
+
+try:
+ import wx.lib.agw.shapedbutton as SB
+ hasSB = True
+except:
+ hasSB = False
+ pass
+
+import wx.lib.agw.ultimatelistctrl as ULC
+
+import persistencemanager as PM
+
+from persist_constants import *
+
+
+def PyDate2wxDate(date):
+ """
+ Transforms a datetime.date object into a :class:`DateTime` one.
+
+ :param `date`: a `datetime.date` object.
+ """
+
+ tt = date.timetuple()
+ dmy = (tt[2], tt[1]-1, tt[0])
+ return wx.DateTimeFromDMY(*dmy)
+
+
+def wxDate2PyDate(date):
+ """
+ Transforms a :class:`DateTime` object into a `datetime.date` one.
+
+ :param date: a :class:`DateTime` object.
+ """
+
+ if date.IsValid():
+ ymd = map(int, date.FormatISODate().split('-'))
+ return datetime.date(*ymd)
+ else:
+ return None
+
+
+def CreateFont(font):
+ """
+ Creates a tuple of 7 :class:`Font` attributes from the `font` input parameter.
+
+ :param `font`: a :class:`Font` instance.
+
+ :returns: A tuple of 7 :class:`Font` attributes from the `font` input parameter.
+ """
+
+ return font.GetPointSize(), font.GetFamily(), font.GetStyle(), font.GetWeight(), \
+ font.GetUnderlined(), font.GetFaceName(), font.GetEncoding()
+
+
+# ----------------------------------------------------------------------------------- #
+
+class AbstractHandler(object):
+ """
+ Base class for persistent windows, uses the window name as persistent name by
+ default and automatically reacts to the window destruction.
+
+ .. note::
+
+ This is an abstract class. If you wish to add another (custom) handler
+ for your widgets, you should derive from :class:`AbstractHandler` and override
+ the :meth:`Save() <AbstractHandler.Save>`,
+ :meth:`Restore() <AbstractHandler.Restore>` and
+ :meth:`GetKind() <AbstractHandler.GetKind>` methods.
+
+ """
+
+ def __init__(self, pObject):
+ """
+ Default class constructor.
+
+ :param `pObject`: a :class:`~lib.agw.persist.persistencemanager.PersistentObject` containing information about the
+ persistent widget.
+ """
+
+ object.__init__(self)
+ self._pObject = pObject
+ self._window = pObject.GetWindow()
+
+
+ def Save(self):
+ """
+ Saves the widget's settings by calling :meth:`PersistentObject.SaveValue() <lib.agw.persist.persistencemanager.PersistentObject.SaveValue>`, which in
+ turns calls :meth:`PersistenceManager.SaveValue() <lib.agw.persist.persistencemanager.PersistenceManager.SaveValue>`.
+
+ :note: This method must be overridden in derived classes.
+ """
+
+ pass
+
+
+ def Restore(self):
+ """
+ Restores the widget's settings by calling :meth:`PersistentObject.RestoreValue() <lib.agw.persist.persistencemanager.PersistentObject.RestoreValue>`, which in
+ turns calls :meth:`PersistenceManager.RestoreValue() <lib.agw.persist.persistencemanager.PersistenceManager.RestoreValue>`.
+
+ :note: This method must be overridden in derived classes.
+ """
+
+ pass
+
+
+ def GetKind(self):
+ """
+ Returns a short and meaningful *string* description of your widget.
+
+ :note: This method must be overridden in derived classes.
+ """
+
+ pass
+
+
+# ----------------------------------------------------------------------------------- #
+
+class BookHandler(AbstractHandler):
+ """
+ Supports saving/restoring book control selection.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`Toolbook`;
+ - :class:`Choicebook`;
+ - :class:`Listbook`;
+ - :class:`Treebook` (except for opened tree branches, see :class:`TreebookHandler` for this);
+ - :class:`Notebook`;
+ - :class:`lib.agw.aui.auibook.AuiNotebook`;
+ - :class:`lib.agw.flatnotebook.FlatNotebook`;
+ - :class:`lib.agw.labelbook.LabelBook`;
+ - :class:`lib.agw.labelbook.FlatImageBook`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ book, obj = self._window, self._pObject
+ obj.SaveValue(PERSIST_BOOK_SELECTION, book.GetSelection())
+
+ if issubclass(book.__class__, AUI.AuiNotebook):
+ manager = PM.PersistenceManager.Get()
+ if manager.GetManagerStyle() & PM_SAVE_RESTORE_AUI_PERSPECTIVES:
+ # Allowed to save and restore perspectives
+ perspective = book.SavePerspective()
+ obj.SaveValue(PERSIST_BOOK_AGW_AUI_PERSPECTIVE, perspective)
+
+
+ def Restore(self):
+
+ book, obj = self._window, self._pObject
+ sel = obj.RestoreValue(PERSIST_BOOK_SELECTION)
+
+ retVal = True
+ if issubclass(book.__class__, AUI.AuiNotebook):
+ manager = PM.PersistenceManager.Get()
+ if manager.GetManagerStyle() & PM_SAVE_RESTORE_AUI_PERSPECTIVES:
+ retVal = False
+ # Allowed to save and restore perspectives
+ perspective = obj.RestoreValue(PERSIST_BOOK_AGW_AUI_PERSPECTIVE)
+ if perspective is not None:
+ retVal = book.LoadPerspective(perspective)
+ wx.CallAfter(book.Refresh)
+
+ if sel is not None:
+ if sel >= 0 and sel < book.GetPageCount():
+ book.SetSelection(sel)
+ return True and retVal
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_BOOK_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class TreebookHandler(BookHandler):
+ """
+ Supports saving/restoring open tree branches.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`Treebook` (except for page selection, see :class:`BookHandler` for this).
+
+ """
+
+ def __init__(self, pObject):
+
+ BookHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ book, obj = self._window, self._pObject
+
+ expanded = ""
+ for page in xrange(book.GetPageCount()):
+ if book.IsNodeExpanded(page):
+ if expanded:
+ expanded += PERSIST_SEP
+
+ expanded += "%u"%page
+
+ obj.SaveValue(PERSIST_TREEBOOK_EXPANDED_BRANCHES, expanded)
+
+ return BookHandler.Save(self)
+
+
+ def Restore(self):
+
+ book, obj = self._window, self._pObject
+
+ expanded = obj.RestoreValue(PERSIST_TREEBOOK_EXPANDED_BRANCHES)
+
+ if expanded:
+ indices = expanded.split(PERSIST_SEP)
+ pageCount = book.GetPageCount()
+
+ for indx in indices:
+ idx = int(indx)
+ if idx >= 0 and idx < pageCount:
+ book.ExpandNode(idx)
+
+ return BookHandler.Restore(self)
+
+
+ def GetKind(self):
+
+ return PERSIST_TREEBOOK_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class AUIHandler(AbstractHandler):
+ """
+ Supports saving/restoring :class:`lib.agw.aui.framemanager.AuiManager` and :class:`wx.aui.AuiManager`
+ perspectives.
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ # Save the AUI perspectives if PersistenceManager allows it
+ eventHandler = self._window.GetEventHandler()
+
+ isAGWAui = isinstance(eventHandler, AUI.AuiManager)
+ isAui = isinstance(eventHandler, wx.aui.AuiManager)
+ if not isAui and not isAGWAui:
+ return True
+
+ manager = PM.PersistenceManager.Get()
+ if manager.GetManagerStyle() & PM_SAVE_RESTORE_AUI_PERSPECTIVES:
+ # Allowed to save and restore perspectives
+ perspective = eventHandler.SavePerspective()
+ if isAGWAui:
+ name = PERSIST_AGW_AUI_PERSPECTIVE
+ else:
+ name = PERSIST_AUI_PERSPECTIVE
+
+ self._pObject.SaveValue(name, perspective)
+
+ return True
+
+
+ def Restore(self):
+
+ # Restore the AUI perspectives if PersistenceManager allows it
+ eventHandler = self._window.GetEventHandler()
+ restoreCodeCaption = False
+
+ isAGWAui = isinstance(eventHandler, AUI.AuiManager)
+ isAui = isinstance(eventHandler, wx.aui.AuiManager)
+ if not isAui and not isAGWAui:
+ return True
+
+ manager = PM.PersistenceManager.Get()
+ if manager.GetManagerStyle() & PM_SAVE_RESTORE_AUI_PERSPECTIVES:
+ # Allowed to save and restore perspectives
+ if isAGWAui:
+ name = PERSIST_AGW_AUI_PERSPECTIVE
+ restoreCodeCaption = manager.GetManagerStyle()
+ restoreCodeCaption &= ~(PM_RESTORE_CAPTION_FROM_CODE)
+ else:
+ name = PERSIST_AUI_PERSPECTIVE
+
+ perspective = self._pObject.RestoreValue(name)
+ if perspective is not None:
+ if restoreCodeCaption:
+ eventHandler.LoadPerspective(perspective,
+ restorecaption=True)
+ else:
+ eventHandler.LoadPerspective(perspective)
+ return True
+
+ return True
+
+
+ def GetKind(self):
+
+ return PERSIST_AUIPERSPECTIVE_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class TLWHandler(AUIHandler):
+ """
+ Supports saving/restoring window position and size as well as
+ maximized/iconized/restore state for toplevel windows.
+
+ This class handles the following wxPython widgets:
+
+ - All :class:`Frame` derived classes;
+ - All :class:`Dialog` derived classes.
+
+ |
+
+ In addition, if the toplevel window has an associated AuiManager (whether it is
+ :class:`~lib.agw.aui.framemanager.AuiManager` or :class:`wx.aui.AuiManager`) and
+ :class:`~lib.agw.persist.persistencemanager.PersistenceManager`
+ has the ``PM_SAVE_RESTORE_AUI_PERSPECTIVES`` style set (the default), this class
+ will also save and restore AUI perspectives using the underlying :class:`AUIHandler`
+ class.
+
+ """
+
+ def __init__(self, pObject):
+
+ AUIHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ tlw, obj = self._window, self._pObject
+
+ pos = tlw.GetScreenPosition()
+ obj.SaveValue(PERSIST_TLW_X, pos.x)
+ obj.SaveValue(PERSIST_TLW_Y, pos.y)
+
+ # Notice that we use GetSize() here and not GetClientSize() because
+ # the latter doesn't return correct results for the minimized windows
+ # (at least not under Windows)
+ #
+ # Of course, it shouldn't matter anyhow usually, the client size
+ # should be preserved as well unless the size of the decorations
+ # changed between the runs
+ size = tlw.GetSize()
+ obj.SaveValue(PERSIST_TLW_W, size.x)
+ obj.SaveValue(PERSIST_TLW_H, size.y)
+
+ obj.SaveValue(PERSIST_TLW_MAXIMIZED, tlw.IsMaximized())
+ obj.SaveValue(PERSIST_TLW_ICONIZED, tlw.IsIconized())
+
+ return AUIHandler.Save(self)
+
+
+ def Restore(self):
+
+ tlw, obj = self._window, self._pObject
+
+ x, y = obj.RestoreValue(PERSIST_TLW_X), obj.RestoreValue(PERSIST_TLW_Y)
+ w, h = obj.RestoreValue(PERSIST_TLW_W), obj.RestoreValue(PERSIST_TLW_H)
+
+ hasPos = x is not None and y is not None
+ hasSize = w is not None and h is not None
+
+ if hasPos:
+ # To avoid making the window completely invisible if it had been
+ # shown on a monitor which was disconnected since the last run
+ # (this is pretty common for notebook with external displays)
+ #
+ # NB: we should allow window position to be (slightly) off screen,
+ # it's not uncommon to position the window so that its upper
+ # left corner has slightly negative coordinate
+ if wx.Display.GetFromPoint(wx.Point(x, y)) != wx.NOT_FOUND or \
+ (hasSize and wx.Display.GetFromPoint(wx.Point(x+w, y+h)) != wx.NOT_FOUND):
+ tlw.Move(wx.Point(x, y), wx.SIZE_ALLOW_MINUS_ONE)
+
+ # else: should we try to adjust position/size somehow?
+
+ if hasSize:
+ tlw.SetSize((w, h))
+
+ # Note that the window can be both maximized and iconized
+ maximized = obj.RestoreValue(PERSIST_TLW_MAXIMIZED)
+ if maximized:
+ tlw.Maximize()
+
+ iconized = obj.RestoreValue(PERSIST_TLW_ICONIZED)
+ if iconized:
+ tlw.Iconize()
+
+ # The most important property of the window that we restore is its
+ # size, so disregard the value of hasPos here
+ return (hasSize and AUIHandler.Restore(self))
+
+
+ def GetKind(self):
+
+ return PERSIST_TLW_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class CheckBoxHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`CheckBox` state.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`CheckBox`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ check, obj = self._window, self._pObject
+
+ if check.Is3State():
+ obj.SaveCtrlValue(PERSIST_CHECKBOX_3STATE, check.Get3StateValue())
+ else:
+ obj.SaveCtrlValue(PERSIST_CHECKBOX, check.GetValue())
+
+ return True
+
+
+ def Restore(self):
+
+ check, obj = self._window, self._pObject
+
+ if check.Is3State():
+ value = obj.RestoreCtrlValue(PERSIST_CHECKBOX_3STATE)
+ if value is not None:
+ check.Set3StateValue(value)
+ return True
+ else:
+ value = obj.RestoreCtrlValue(PERSIST_CHECKBOX)
+ if value is not None:
+ check.SetValue(value)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_CHECKBOX_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class ListBoxHandler(AbstractHandler):
+ """
+ Supports saving/restoring selected items in :class:`ListBox`, :class:`ListCtrl`, :class:`ListView`,
+ :class:`VListBox`, :class:`HtmlListBox`, :class:`SimpleHtmlListBox`, :class:`gizmos.EditableListBox`.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`ListBox`;
+ - :class:`ListCtrl` (only for selected items. For column sizes see :class:`ListCtrlHandler`);
+ - :class:`ListView` (only for selected items. For column sizes see :class:`ListCtrlHandler`);
+ - :class:`VListBox`;
+ - :class:`HtmlListBox`;
+ - :class:`SimpleHtmlListBox`;
+ - :class:`gizmos.EditableListBox`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def GetSelections(self, listBox):
+ """
+ Returns a list of selected items for :class:`ListBox`, :class:`ListCtrl`, :class:`ListView`,
+ :class:`VListBox`, :class:`HtmlListBox`, :class:`SimpleHtmlListBox`, :class:`gizmos.EditableListBox`.
+
+ :param `listBox`: an instance of :class:`ListBox`, :class:`ListCtrl`, :class:`ListView`,
+ :class:`VListBox`, :class:`HtmlListBox`, :class:`SimpleHtmlListBox`, :class:`gizmos.EditableListBox`..
+ """
+
+ indices = []
+ if isinstance(listBox, (wx.HtmlListBox, wx.SimpleHtmlListBox)):
+ if listBox.GetSelectedCount() == 0:
+ return indices
+ else:
+ if listBox.GetSelectedItemCount() == 0:
+ return indices
+
+ isVirtual = issubclass(listBox.__class__, wx.VListBox)
+
+ if isVirtual:
+ # This includes wx.SimpleHtmlListBox and wx.HtmlListBox
+ if listBox.GetWindowStyleFlag() & wx.LB_SINGLE:
+ selection = listBox.GetSelection()
+ return (selection >= 0 and [selection] or [indices])[0]
+ else:
+ # wx.ListCtrl
+ if listBox.GetWindowStyleFlag() & wx.LC_SINGLE_SEL:
+ selection = listBox.GetSelection()
+ return (selection >= 0 and [selection] or [indices])[0]
+
+ if isVirtual:
+ item, cookie = listBox.GetFirstSelected()
+ while item != wx.NOT_FOUND:
+ indices.append(item)
+ item, cookie = listBox.GetNextSelected(cookie)
+
+ return indices
+
+ lastFound = -1
+ # Loop until told to stop
+ while 1:
+ index = listBox.GetNextItem(lastFound, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
+ if index == wx.NOT_FOUND:
+ # No item selected
+ break
+ else:
+ # Found one item, append to the list of condemned
+ lastFound = index
+ indices.append(index)
+
+ return indices
+
+
+ def Save(self):
+
+ manager = PM.PersistenceManager.Get()
+ if manager.GetManagerStyle() & PM_SAVE_RESTORE_TREE_LIST_SELECTIONS == 0:
+ # We don't want to save selected items
+ return True
+
+ listBox, obj = self._window, self._pObject
+
+ if issubclass(listBox.__class__, wx.ListBox):
+ selections = listBox.GetSelections()
+ else:
+ selections = self.GetSelections(listBox)
+
+ obj.SaveValue(PERSIST_LISTBOX_SELECTIONS, selections)
+ return True
+
+
+ def Restore(self):
+
+ manager = PM.PersistenceManager.Get()
+ if manager.GetManagerStyle() & PM_SAVE_RESTORE_TREE_LIST_SELECTIONS == 0:
+ # We don't want to save selected items
+ return True
+
+ listBox, obj = self._window, self._pObject
+
+ isVirtual = issubclass(listBox.__class__, wx.VListBox) or isinstance(listBox, wx.CheckListBox)
+ isHtml = isinstance(listBox, wx.HtmlListBox)
+ if isVirtual and not isHtml:
+ count = listBox.GetCount()
+ else:
+ count = listBox.GetItemCount()
+
+ selections = obj.RestoreValue(PERSIST_LISTBOX_SELECTIONS)
+
+ if selections is not None:
+ for index in selections:
+ if index < count:
+ listBox.Select(index)
+
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_LISTBOX_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class ListCtrlHandler(ListBoxHandler):
+ """
+ Supports saving/restoring selected items and column sizes in :class:`ListCtrl`.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`ListCtrl` (only for column sizes. For selected items see :class:`ListBoxHandler`);
+ - :class:`ListView` (only for column sizes. For selected items see :class:`ListBoxHandler`).
+ """
+
+ def __init__(self, pObject):
+
+ ListBoxHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ listCtrl, obj = self._window, self._pObject
+
+ retVal = ListBoxHandler.Save(self)
+
+ if not listCtrl.InReportView():
+ return retVal
+
+ colSizes = []
+ for col in xrange(listCtrl.GetColumnCount()):
+ colSizes.append(listCtrl.GetColumnWidth(col))
+
+ obj.SaveValue(PERSIST_LISTCTRL_COLWIDTHS, colSizes)
+
+ return retVal
+
+
+ def Restore(self):
+
+ listCtrl, obj = self._window, self._pObject
+
+ retVal = ListBoxHandler.Restore(self)
+
+ if not listCtrl.InReportView():
+ return retVal
+
+ colSizes = obj.RestoreValue(PERSIST_LISTCTRL_COLWIDTHS)
+ if colSizes is None:
+ return False
+
+ count = listCtrl.GetColumnCount()
+ for col, size in enumerate(colSizes):
+ if col < count:
+ listCtrl.SetColumnWidth(col, size)
+
+ return retVal
+
+
+ def GetKind(self):
+
+ return PERSIST_LISTCTRL_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class CheckListBoxHandler(ListBoxHandler):
+ """
+ Supports saving/restoring checked and selected items in :class:`CheckListBox`.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`CheckListBox` (only for checked items. For selected items see :class:`ListBoxHandler`).
+
+ """
+
+ def __init__(self, pObject):
+
+ ListBoxHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ checkList, obj = self._window, self._pObject
+
+ checked = []
+ for index in xrange(checkList.GetCount()):
+ if checkList.IsChecked(index):
+ checked.append(index)
+
+ obj.SaveValue(PERSIST_CHECKLIST_CHECKED, checked)
+
+ return ListBoxHandler.Save(self)
+
+
+ def Restore(self):
+
+ checkList, obj = self._window, self._pObject
+
+ checked = obj.RestoreValue(PERSIST_CHECKLIST_CHECKED)
+ count = checkList.GetCount()
+ if checked is not None:
+ for index in checked:
+ if index < count:
+ checkList.Check(index)
+
+ return ListBoxHandler.Restore(self)
+
+
+ def GetKind(self):
+
+ return PERSIST_CHECKLISTBOX_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class ChoiceComboHandler(AbstractHandler):
+ """
+ Supports saving/restoring :class:`Choice`, :class:`ComboBox` and :class:`combo.OwnerDrawnComboBox`
+ selection.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`Choice`;
+ - :class:`ComboBox`;
+ - :class:`combo.OwnerDrawnComboBox`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ combo, obj = self._window, self._pObject
+
+ value = combo.GetStringSelection()
+ obj.SaveCtrlValue(PERSIST_CHOICECOMBO_SELECTION, value)
+ return True
+
+
+ def Restore(self):
+
+ combo, obj = self._window, self._pObject
+
+ value = obj.RestoreCtrlValue(PERSIST_CHOICECOMBO_SELECTION)
+ if value is not None:
+ if value in combo.GetStrings():
+ combo.SetStringSelection(value)
+
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_CHOICECOMBO_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class FoldPanelBarHandler(AbstractHandler):
+ """
+ Supports saving/restoring of :class:`lib.agw.foldpanelbar.FoldPanelBar`.
+
+ This class handles the following wxPython widgets
+
+ - :class:`lib.agw.foldpanelbar.FoldPanelBar`
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ fpb, obj = self._window, self._pObject
+ expanded = [fpb.GetFoldPanel(i).IsExpanded() for i in xrange(fpb.GetCount())]
+ obj.SaveValue(PERSIST_FOLDPANELBAR_EXPANDED, expanded)
+
+ return True
+
+
+ def Restore(self):
+
+ fpb, obj = self._window, self._pObject
+ expanded = obj.RestoreValue(PERSIST_FOLDPANELBAR_EXPANDED)
+
+ if expanded is None:
+ return False
+ else:
+ for idx, expand in enumerate(expanded):
+ panel = fpb.GetFoldPanel(idx)
+ if expand:
+ fpb.Expand(panel)
+ else:
+ fpb.Collapse(panel)
+
+ return True
+
+
+ def GetKind(self):
+
+ return PERSIST_FOLDPANELBAR_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class RadioBoxHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`RadioBox` state.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`RadioBox`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ radio, obj = self._window, self._pObject
+ obj.SaveCtrlValue(PERSIST_RADIOBOX_SELECTION, radio.GetSelection())
+ return True
+
+
+ def Restore(self):
+
+ radio, obj = self._window, self._pObject
+ value = obj.RestoreCtrlValue(PERSIST_RADIOBOX_SELECTION)
+ if value is not None:
+ if value < radio.GetCount():
+ radio.SetSelection(value)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_RADIOBOX_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class RadioButtonHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`RadioButton` state.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`RadioButton`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ radio, obj = self._window, self._pObject
+ obj.SaveCtrlValue(PERSIST_RADIOBUTTON_VALUE, radio.GetValue())
+ return True
+
+
+ def Restore(self):
+
+ radio, obj = self._window, self._pObject
+ value = obj.RestoreCtrlValue(PERSIST_RADIOBUTTON_VALUE)
+ if value is not None:
+ radio.SetValue(value)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_RADIOBUTTON_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class ScrolledWindowHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`ScrolledWindow` / :class:`lib.scrolledpanel.ScrolledPanel`
+ scroll position.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`ScrolledWindow`;
+ - :class:`lib.scrolledpanel.ScrolledPanel`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ scroll, obj = self._window, self._pObject
+
+ scrollPos = scroll.GetScrollPos(wx.HORIZONTAL)
+ obj.SaveValue(PERSIST_SCROLLEDWINDOW_POS_H, scrollPos)
+ scrollPos = scroll.GetScrollPos(wx.VERTICAL)
+ obj.SaveValue(PERSIST_SCROLLEDWINDOW_POS_V, scrollPos)
+ return True
+
+
+ def Restore(self):
+
+ scroll, obj = self._window, self._pObject
+ hpos = obj.RestoreValue(PERSIST_SCROLLEDWINDOW_POS_H)
+ vpos = obj.RestoreValue(PERSIST_SCROLLEDWINDOW_POS_V)
+
+ if hpos:
+ scroll.SetScrollPos(wx.HORIZONTAL, hpos)
+ if vpos:
+ scroll.SetScrollPos(wx.VERTICAL, vpos, True)
+
+ return True
+
+
+ def GetKind(self):
+
+ return PERSIST_SCROLLEDWINDOW_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class SliderHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`Slider` / :class:`lib.agw.knobctrl.KnobCtrl` thumb position.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`Slider`;
+ - :class:`lib.agw.knobctrl.KnobCtrl`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ slider, obj = self._window, self._pObject
+ obj.SaveCtrlValue(PERSIST_SLIDER_VALUE, slider.GetValue())
+ return True
+
+
+ def Restore(self):
+
+ slider, obj = self._window, self._pObject
+ value = obj.RestoreCtrlValue(PERSIST_SLIDER_VALUE)
+
+ if issubclass(slider.__class__, wx.Slider):
+ minVal, maxVal = slider.GetMin(), slider.GetMax()
+ else:
+ # KnobCtrl
+ minVal, maxVal = slider.GetMinValue(), slider.GetMaxValue()
+
+ if value is not None:
+ if value >= minVal and value <= maxVal:
+ slider.SetValue(value)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_SLIDER_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class SpinHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`SpinButton` / :class:`SpinCtrl` value.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`SpinCtrl`;
+ - :class:`SpinButton`.
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ spin, obj = self._window, self._pObject
+ obj.SaveCtrlValue(PERSIST_SPIN_VALUE, spin.GetValue())
+ return True
+
+
+ def Restore(self):
+
+ spin, obj = self._window, self._pObject
+ value = obj.RestoreCtrlValue(PERSIST_SPIN_VALUE)
+
+ if value is not None:
+ minVal, maxVal = spin.GetMin(), spin.GetMax()
+ if value >= minVal and value <= maxVal:
+ spin.SetValue(value)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_SPIN_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class SplitterHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`SplitterWindow` splitter position.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`SplitterWindow`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ splitter, obj = self._window, self._pObject
+ obj.SaveValue(PERSIST_SPLITTER_POSITION, splitter.GetSashPosition())
+ return True
+
+
+ def Restore(self):
+
+ splitter, obj = self._window, self._pObject
+ value = obj.RestoreValue(PERSIST_SPLITTER_POSITION)
+
+ if value is None:
+ return False
+
+ if not splitter.IsSplit():
+ return False
+
+ width, height = splitter.GetClientSize()
+ minPaneSize = splitter.GetMinimumPaneSize()
+ direction = splitter.GetSplitMode()
+
+ if direction == wx.SPLIT_HORIZONTAL:
+ # Top and bottom panes
+ if value > height - minPaneSize:
+ return False
+ else:
+ # Left and right panes
+ if value > width - minPaneSize:
+ return False
+
+ splitter.SetSashPosition(value)
+ return True
+
+
+ def GetKind(self):
+
+ return PERSIST_SPLITTER_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class TextCtrlHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`TextCtrl` entered string.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`TextCtrl`;
+ - :class:`SearchCtrl`;
+ - :class:`lib.expando.ExpandoTextCtrl`;
+ - :class:`lib.masked.textctrl.TextCtrl`;
+ - :class:`lib.masked.combobox.ComboBox`;
+ - :class:`lib.masked.ipaddrctrl.IpAddrCtrl`;
+ - :class:`lib.masked.timectrl.TimeCtrl`;
+ - :class:`lib.masked.numctrl.NumCtrl`;
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ text, obj = self._window, self._pObject
+ obj.SaveCtrlValue(PERSIST_TEXTCTRL_VALUE, text.GetValue())
+ return True
+
+
+ def Restore(self):
+
+ text, obj = self._window, self._pObject
+ value = obj.RestoreCtrlValue(PERSIST_TEXTCTRL_VALUE)
+
+ if value is not None:
+ text.ChangeValue(value)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_TEXTCTRL_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class ToggleButtonHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`ToggleButton` and friends state.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`ToggleButton`;
+ - :class:`lib.buttons.GenToggleButton`;
+ - :class:`lib.buttons.GenBitmapToggleButton`;
+ - :class:`lib.buttons.GenBitmapTextToggleButton`;
+ - :class:`lib.agw.shapedbutton.SToggleButton`;
+ - :class:`lib.agw.shapedbutton.SBitmapToggleButton`;
+ - :class:`lib.agw.shapedbutton.SBitmapTextToggleButton`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ toggle, obj = self._window, self._pObject
+ obj.SaveValue(PERSIST_TOGGLEBUTTON_TOGGLED, toggle.GetValue())
+ return True
+
+
+ def Restore(self):
+
+ toggle, obj = self._window, self._pObject
+ value = obj.RestoreValue(PERSIST_TOGGLEBUTTON_TOGGLED)
+
+ if value is not None:
+ toggle.SetValue(value)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_TOGGLEBUTTON_KIND
+
+# ----------------------------------------------------------------------------------- #
+
+class TreeCtrlHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`TreeCtrl` expansion state, selections and
+ checked items state (meaningful only for :class:`lib.agw.customtreectrl.CustomTreeCtrl`).
+
+ This class handles the following wxPython widgets:
+
+ - :class:`TreeCtrl`;
+ - :class:`GenericDirCtrl`;
+ - :class:`lib.agw.customtreectrl.CustomTreeCtrl`;
+ - :class:`lib.agw.hypertreelist.HyperTreeList`;
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+ self._isTreeList = isinstance(pObject.GetWindow(), wx.gizmos.TreeListCtrl)
+
+
+ def GetItemChildren(self, item=None, recursively=False):
+ """
+ Return the children of item as a list.
+
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item;
+ :param `recursively`: whether to recurse into the item hierarchy or not.
+ """
+
+ if not item:
+ item = self._window.GetRootItem()
+ if not item:
+ return []
+
+ children = []
+ child, cookie = self._window.GetFirstChild(item)
+
+ while child and child.IsOk():
+ children.append(child)
+ if recursively:
+ children.extend(self.GetItemChildren(child, True))
+ child, cookie = self._window.GetNextChild(item, cookie)
+
+ return children
+
+
+ def GetIndexOfItem(self, item):
+ """
+ Return the index of item.
+
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item;
+ """
+
+ parent = self._window.GetItemParent(item)
+ if parent:
+ parentIndices = self.GetIndexOfItem(parent)
+ ownIndex = self.GetItemChildren(parent).index(item)
+ return parentIndices + (ownIndex,)
+ else:
+ return ()
+
+
+ def GetItemIdentity(self, item):
+ """
+ Return a hashable object that represents the identity of the
+ item. By default this returns the position of the item in the
+ tree. You may want to override this to return the item label
+ (if you know that labels are unique and don't change), or return
+ something that represents the underlying domain object, e.g.
+ a database key.
+
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item;
+ """
+
+ return self.GetIndexOfItem(item)
+
+
+ def GetExpansionState(self):
+ """
+ Returns list of expanded items. Expanded items are coded as determined by
+ the result of :meth:`TreeCtrlHandler.GetItemIdentity() <TreeCtrlHandler.GetItemIdentity>`.
+ """
+
+ root = self._window.GetRootItem()
+ if not root:
+ return []
+ if self._window.HasFlag(wx.TR_HIDE_ROOT):
+ return self.GetExpansionStateOfChildren(root)
+ else:
+ return self.GetExpansionStateOfItem(root)
+
+
+ def SetExpansionState(self, listOfExpandedItems):
+ """
+ Expands all tree items whose identity, as determined by :meth:`TreeCtrlHandler.GetItemIdentity() <TreeCtrlHandler.GetItemIdentity>`,
+ is present in the list and collapses all other tree items.
+
+ :param `listOfExpandedItems`: a list of expanded :class:`TreeCtrl` or
+ :class:`~lib.agw.customtreectrl.CustomTreeCtrl` items.
+ """
+
+ root = self._window.GetRootItem()
+ if not root:
+ return
+ if self._window.HasFlag(wx.TR_HIDE_ROOT):
+ self.SetExpansionStateOfChildren(listOfExpandedItems, root)
+ else:
+ self.SetExpansionStateOfItem(listOfExpandedItems, root)
+
+
+ def GetSelectionState(self):
+ """
+ Returns a list of selected items. Selected items are coded as determined by
+ the result of :meth:`TreeCtrlHandler.GetItemIdentity() <TreeCtrlHandler.GetItemIdentity>`.
+ """
+
+ root = self._window.GetRootItem()
+ if not root:
+ return []
+ if self._window.HasFlag(wx.TR_HIDE_ROOT):
+ return self.GeSelectionStateOfChildren(root)
+ else:
+ return self.GetSelectionStateOfItem(root)
+
+
+ def SetSelectionState(self, listOfSelectedItems):
+ """
+ Selects all tree items whose identity, as determined by :meth:`TreeCtrlHandler.GetItemIdentity() <TreeCtrlHandler.GetItemIdentity>`,
+ is present in the list and unselects all other tree items.
+
+ :param `listOfSelectedItems`: a list of selected :class:`TreeCtrl` or
+ :class:`~lib.agw.customtreectrl.CustomTreeCtrl` items.
+ """
+
+ root = self._window.GetRootItem()
+ if not root:
+ return
+ if self._window.HasFlag(wx.TR_HIDE_ROOT):
+ self.SetSelectedStateOfChildren(listOfSelectedItems, root)
+ else:
+ self.SetSelectedStateOfItem(listOfSelectedItems, root)
+
+
+ def GetCheckedState(self):
+ """
+ Returns a list of checked items. Checked items are coded as determined by
+ the result of :meth:`TreeCtrlHandler.GetItemIdentity() <TreeCtrlHandler.GetItemIdentity>`.
+
+ :note:
+
+ This is meaningful only for :class:`~lib.agw.customtreectrl.CustomTreeCtrl` and
+ :class:`~lib.agw.hypertreelist.HyperTreeList`.
+ """
+
+ root = self._window.GetRootItem()
+ if not root:
+ return []
+ if self._window.HasFlag(wx.TR_HIDE_ROOT):
+ return self.GetCheckedStateOfChildren(root)
+ else:
+ return self.GetCheckedStateOfItem(root)
+
+
+ def SetCheckedState(self, listOfCheckedItems):
+ """
+ Checks all tree items whose identity, as determined by :meth:`TreeCtrlHandler.GetItemIdentity() <TreeCtrlHandler.GetItemIdentity>`, is present
+ in the list and unchecks all other tree items.
+
+ :param `listOfCheckedItems`: a list of checked :class:`~lib.agw.customtreectrl.CustomTreeCtrl` items.
+
+ :note:
+
+ This is meaningful only for :class:`~lib.agw.customtreectrl.CustomTreeCtrl` and
+ :class:`~lib.agw.hypertreelist.HyperTreeList`.
+ """
+
+ root = self._window.GetRootItem()
+ if not root:
+ return
+ if self._window.HasFlag(wx.TR_HIDE_ROOT):
+ self.SetCheckedStateOfChildren(listOfCheckedItems, root)
+ else:
+ self.SetCheckedStateOfItem(listOfCheckedItems, root)
+
+
+ def GetExpansionStateOfItem(self, item):
+ """
+ Returns the expansion state of a tree item.
+
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ listOfExpandedItems = []
+ if self._window.IsExpanded(item):
+ listOfExpandedItems.append(self.GetItemIdentity(item))
+ listOfExpandedItems.extend(self.GetExpansionStateOfChildren(item))
+
+ return listOfExpandedItems
+
+
+ def GetExpansionStateOfChildren(self, item):
+ """
+ Returns the expansion state of the children of a tree item.
+
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ listOfExpandedItems = []
+ for child in self.GetItemChildren(item):
+ listOfExpandedItems.extend(self.GetExpansionStateOfItem(child))
+
+ return listOfExpandedItems
+
+
+ def GetCheckedStateOfItem(self, item):
+ """
+ Returns the checked/unchecked state of a tree item.
+
+ :param `item`: a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ listOfCheckedItems = []
+ if self._window.IsItemChecked(item):
+ listOfCheckedItems.append(self.GetItemIdentity(item))
+
+ listOfCheckedItems.extend(self.GetCheckedStateOfChildren(item))
+
+ return listOfCheckedItems
+
+
+ def GetCheckedStateOfChildren(self, item):
+ """
+ Returns the checked/unchecked state of the children of a tree item.
+
+ :param `item`: a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ listOfCheckedItems = []
+ for child in self.GetItemChildren(item):
+ listOfCheckedItems.extend(self.GetCheckedStateOfItem(child))
+
+ return listOfCheckedItems
+
+
+ def GetSelectionStateOfItem(self, item):
+ """
+ Returns the selection state of a tree item.
+
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ listOfSelectedItems = []
+ if self._window.IsSelected(item):
+ listOfSelectedItems.append(self.GetItemIdentity(item))
+
+ listOfSelectedItems.extend(self.GetSelectionStateOfChildren(item))
+ return listOfSelectedItems
+
+
+ def GetSelectionStateOfChildren(self, item):
+ """
+ Returns the selection state of the children of a tree item.
+
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ listOfSelectedItems = []
+ for child in self.GetItemChildren(item):
+ listOfSelectedItems.extend(self.GetSelectionStateOfItem(child))
+
+ return listOfSelectedItems
+
+
+ def SetExpansionStateOfItem(self, listOfExpandedItems, item):
+ """
+ Sets the expansion state of a tree item (expanded or collapsed).
+
+ :param `listOfExpandedItems`: a list of expanded :class:`TreeCtrl` or
+ :class:`~lib.agw.customtreectrl.CustomTreeCtrl` items;
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ if self.GetItemIdentity(item) in listOfExpandedItems:
+ self._window.Expand(item)
+ self.SetExpansionStateOfChildren(listOfExpandedItems, item)
+ else:
+ self._window.Collapse(item)
+
+
+ def SetExpansionStateOfChildren(self, listOfExpandedItems, item):
+ """
+ Sets the expansion state of the children of a tree item (expanded or collapsed).
+
+ :param `listOfExpandedItems`: a list of expanded :class:`TreeCtrl` or
+ :class:`~lib.agw.customtreectrl.CustomTreeCtrl` items;
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ for child in self.GetItemChildren(item):
+ self.SetExpansionStateOfItem(listOfExpandedItems, child)
+
+
+ def SetCheckedStateOfItem(self, listOfCheckedItems, item):
+ """
+ Sets the checked/unchecked state of a tree item.
+
+ :param `listOfCheckedItems`: a list of checked :class:`~lib.agw.customtreectrl.CustomTreeCtrl` items;
+ :param `item`: a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ if self.GetItemIdentity(item) in listOfCheckedItems:
+ self._window.CheckItem2(item, True)
+ else:
+ self._window.CheckItem2(item, False)
+
+ self.SetCheckedStateOfChildren(listOfCheckedItems, item)
+
+
+ def SetCheckedStateOfChildren(self, listOfCheckedItems, item):
+ """
+ Sets the checked/unchecked state of the children of a tree item.
+
+ :param `listOfCheckedItems`: a list of checked :class:`~lib.agw.customtreectrl.CustomTreeCtrl` items;
+ :param `item`: a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ for child in self.GetItemChildren(item):
+ self.SetCheckedStateOfItem(listOfCheckedItems, child)
+
+
+ def SetSelectedStateOfItem(self, listOfSelectedItems, item):
+ """
+ Sets the selection state of a tree item.
+
+ :param `listOfSelectedItems`: a list of selected :class:`TreeCtrl` or
+ :class:`~lib.agw.customtreectrl.CustomTreeCtrl` items;
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ if self.GetItemIdentity(item) in listOfSelectedItems:
+ if self._isTreeList:
+ self._window.SelectItem(item, unselect_others=False)
+ else:
+ self._window.SelectItem(item)
+
+ self.SetSelectedStateOfChildren(listOfSelectedItems, item)
+
+
+ def SetSelectedStateOfChildren(self, listOfSelectedItems, item):
+ """
+ Sets the selection state of the children of a tree item.
+
+ :param `listOfSelectedItems`: a list of selected :class:`TreeCtrl` or
+ :class:`~lib.agw.customtreectrl.CustomTreeCtrl` items;
+ :param `item`: a :class:`TreeCtrl` item or a :class:`~lib.agw.customtreectrl.CustomTreeCtrl` item.
+ """
+
+ for child in self.GetItemChildren(item):
+ self.SetSelectedStateOfItem(listOfSelectedItems, child)
+
+
+ def Save(self):
+
+ tree, obj = self._window, self._pObject
+
+ obj.SaveCtrlValue(PERSIST_TREECTRL_EXPANSION, self.GetExpansionState())
+
+ if issubclass(tree.__class__, (HTL.HyperTreeList, CT.CustomTreeCtrl)):
+ obj.SaveCtrlValue(PERSIST_TREECTRL_CHECKED_ITEMS, self.GetCheckedState())
+
+ manager = PM.PersistenceManager.Get()
+ if manager.GetManagerStyle() & PM_SAVE_RESTORE_TREE_LIST_SELECTIONS == 0:
+ # We don't want to save selected items
+ return True
+
+ obj.SaveCtrlValue(PERSIST_TREECTRL_SELECTIONS, self.GetSelectionState())
+ return True
+
+
+ def Restore(self):
+
+ tree, obj = self._window, self._pObject
+ expansion = obj.RestoreCtrlValue(PERSIST_TREECTRL_EXPANSION)
+ selections = obj.RestoreCtrlValue(PERSIST_TREECTRL_SELECTIONS)
+
+ if expansion is not None:
+ self.SetExpansionState(expansion)
+
+ manager = PM.PersistenceManager.Get()
+ if manager.GetManagerStyle() & PM_SAVE_RESTORE_TREE_LIST_SELECTIONS:
+ # We want to restore selected items
+ if selections is not None:
+ self.SetSelectionState(selections)
+
+ if not issubclass(tree.__class__, (HTL.HyperTreeList, CT.CustomTreeCtrl)):
+ return (expansion is not None and selections is not None)
+
+ checked = obj.RestoreCtrlValue(PERSIST_TREECTRL_CHECKED_ITEMS)
+ if checked is not None:
+ self.SetCheckedState(checked)
+
+ return (expansion is not None and selections is not None and checked is not None)
+
+
+ def GetKind(self):
+
+ return PERSIST_TREECTRL_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class TreeListCtrlHandler(TreeCtrlHandler):
+ """
+ Supports saving/restoring a :class:`gizmos.TreeListCtrl` / :class:`lib.agw.hypertreelist.HyperTreeList` expansion state,
+ selections, column widths and checked items state (meaningful only for :class:`~lib.agw.hypertreelist.HyperTreeList`).
+
+ This class handles the following wxPython widgets:
+
+ - :class:`gizmos.TreeListCtrl`;
+ - :class:`lib.agw.hypertreelist.HyperTreeList`.
+
+ """
+
+ def __init__(self, pObject):
+
+ TreeCtrlHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ treeList, obj = self._window, self._pObject
+
+ colSizes = []
+ for col in xrange(treeList.GetColumnCount()):
+ colSizes.append(treeList.GetColumnWidth(col))
+
+ obj.SaveValue(PERSIST_TREELISTCTRL_COLWIDTHS, colSizes)
+
+ return TreeCtrlHandler.Save(self)
+
+
+ def Restore(self):
+
+ treeList, obj = self._window, self._pObject
+ colSizes = obj.RestoreValue(PERSIST_TREELISTCTRL_COLWIDTHS)
+ retVal = False
+
+ count = treeList.GetColumnCount()
+ if colSizes is not None:
+ retVal = True
+ for col, size in enumerate(colSizes):
+ if col < count:
+ treeList.SetColumnWidth(col, size)
+
+ return (retVal and TreeCtrlHandler.Restore(self))
+
+
+ def GetKind(self):
+
+ return PERSIST_TREELISTCTRL_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class CalendarCtrlHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`calendar.CalendarCtrl` date.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`lib.calendar.CalendarCtrl`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ calend, obj = self._window, self._pObject
+ obj.SaveCtrlValue(PERSIST_CALENDAR_DATE, wxDate2PyDate(calend.GetDate()))
+ return True
+
+
+ def Restore(self):
+
+ calend, obj = self._window, self._pObject
+ value = obj.RestoreCtrlValue(PERSIST_CALENDAR_DATE)
+
+ if value is not None:
+ calend.SetDate(PyDate2wxDate(value))
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_CALENDAR_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class CollapsiblePaneHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`CollapsiblePane` / :class:`lib.agw.pycollapsiblepane.PyCollapsiblePane` state.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`CollapsiblePane`;
+ - :class:`lib.agw.pycollapsiblepane.PyCollapsiblePane`.
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ collPane, obj = self._window, self._pObject
+ obj.SaveValue(PERSIST_COLLAPSIBLE_STATE, collPane.IsCollapsed())
+ return True
+
+
+ def Restore(self):
+
+ collPane, obj = self._window, self._pObject
+ value = obj.RestoreValue(PERSIST_COLLAPSIBLE_STATE)
+
+ if value is not None:
+ collPane.Collapse(value)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_COLLAPSIBLE_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class DatePickerHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`DatePickerCtrl` / :class:`GenericDatePickerCtrl` date.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`DatePickerCtrl`;
+ - :class:`GenericDatePickerCtrl`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ datePicker, obj = self._window, self._pObject
+ obj.SaveCtrlValue(PERSIST_DATEPICKER_DATE, wxDate2PyDate(datePicker.GetValue()))
+ return True
+
+
+ def Restore(self):
+
+ datePicker, obj = self._window, self._pObject
+ value = obj.RestoreCtrlValue(PERSIST_DATEPICKER_DATE)
+
+ if value is not None:
+ datePicker.SetValue(PyDate2wxDate(value))
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_DATEPICKER_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class MediaCtrlHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`media.MediaCtrl` movie position, volume and playback
+ rate.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`media.MediaCtrl`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ mediaCtrl, obj = self._window, self._pObject
+ obj.SaveValue(PERSIST_MEDIA_POS, mediaCtrl.Tell())
+ obj.SaveValue(PERSIST_MEDIA_VOLUME, mediaCtrl.GetVolume())
+ obj.SaveValue(PERSIST_MEDIA_RATE, mediaCtrl.GetPlaybackRate())
+ return True
+
+
+ def Restore(self):
+
+ mediaCtrl, obj = self._window, self._pObject
+ position = obj.RestoreValue(PERSIST_MEDIA_POS)
+ volume = obj.RestoreValue(PERSIST_MEDIA_VOLUME)
+ rate = obj.RestoreValue(PERSIST_MEDIA_RATE)
+
+ if position is not None:
+ mediaCtrl.Seek(position)
+
+ if volume is not None:
+ mediaCtrl.SetVolume(volume)
+
+ if rate is not None:
+ mediaCtrl.SetPlaybackRate(rate)
+
+ return (osition is not None and volume is not None and rate is not None)
+
+
+ def GetKind(self):
+
+ return PERSIST_MEDIA_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class ColourPickerHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`ColourPickerCtrl` / :class:`lib.colourselect.ColourSelect` colour.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`ColourPickerCtrl`;
+ - :class:`lib.colourselect.ColourSelect`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ colPicker, obj = self._window, self._pObject
+ obj.SaveValue(PERSIST_COLOURPICKER_COLOUR, colPicker.GetColour().Get(includeAlpha=True))
+ return True
+
+
+ def Restore(self):
+
+ colPicker, obj = self._window, self._pObject
+ value = obj.RestoreValue(PERSIST_COLOURPICKER_COLOUR)
+
+ if value is not None:
+ colPicker.SetColour(wx.Colour(*value))
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_COLOURPICKER_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class FileDirPickerHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`FilePickerCtrl` / :class:`DirPickerCtrl` path.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`FilePickerCtrl`;
+ - :class:`DirPickerCtrl`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ picker, obj = self._window, self._pObject
+
+ path = picker.GetPath()
+ if issubclass(picker.__class__, wx.FileDialog):
+ if picker.GetWindowStyleFlag() & wx.FD_MULTIPLE:
+ path = picker.GetPaths()
+
+ obj.SaveValue(PERSIST_FILEDIRPICKER_PATH, path)
+ return True
+
+
+ def Restore(self):
+
+ picker, obj = self._window, self._pObject
+ value = obj.RestoreValue(PERSIST_FILEDIRPICKER_PATH)
+
+ if value is not None:
+ if issubclass(picker.__class__, wx.FileDialog):
+ if type(value) == types.ListType:
+ value = value[-1]
+
+ picker.SetPath(value)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_FILEDIRPICKER_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class FontPickerHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`FontPickerCtrl` font.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`FontPickerCtrl`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ picker, obj = self._window, self._pObject
+
+ font = picker.GetSelectedFont()
+ if not font.IsOk():
+ return False
+
+ fontData = CreateFont(font)
+ obj.SaveValue(PERSIST_FONTPICKER_FONT, fontData)
+ return True
+
+
+ def Restore(self):
+
+ picker, obj = self._window, self._pObject
+ value = obj.RestoreValue(PERSIST_FONTPICKER_FONT)
+
+ if value is not None:
+ font = wx.Font(*value)
+ if font.IsOk():
+ picker.SetSelectedFont(font)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_FONTPICKER_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class FileHistoryHandler(AbstractHandler):
+ """
+ Supports saving/restoring a :class:`FileHistory` list of file names.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`FileHistory`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ history, obj = self._window, self._pObject
+
+ paths = []
+ for indx in xrange(history.GetCount()):
+ paths.append(history.GetHistoryFile(indx))
+
+ obj.SaveValue(PERSIST_FILEHISTORY_PATHS, paths)
+ return True
+
+
+ def Restore(self):
+
+ history, obj = self._window, self._pObject
+ value = obj.RestoreValue(PERSIST_FILEHISTORY_PATHS)
+
+ if value is not None:
+ count = history.GetMaxFiles()
+ for indx, path in enumerate(value):
+ if indx < count:
+ history.AddFileToHistory(path)
+ return True
+
+ return False
+
+
+ def GetKind(self):
+
+ return PERSIST_FILEHISTORY_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class MenuBarHandler(AbstractHandler):
+ """
+ Supports saving/restoring the :class:`MenuBar` and :class:`lib.agw.flatmenu.FlatMenuBar` items state.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`MenuBar`;
+ - :class:`lib.agw.flatmenu.FlatMenuBar`.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ bar, obj = self._window, self._pObject
+ menuCount = bar.GetMenuCount()
+
+ if menuCount == 0:
+ # Nothing to save
+ return False
+
+ checkRadioItems = {}
+ for indx in xrange(menuCount):
+ menu = bar.GetMenu(indx)
+ for item in menu.GetMenuItems():
+ if item.GetKind() in [wx.ITEM_CHECK, wx.ITEM_RADIO]:
+ checkRadioItems[item.GetId()] = item.IsChecked()
+
+ obj.SaveValue(PERSIST_MENUBAR_CHECKRADIO_ITEMS, checkRadioItems)
+ return True
+
+
+ def Restore(self):
+
+ bar, obj = self._window, self._pObject
+ menuCount = bar.GetMenuCount()
+
+ if menuCount == 0:
+ # Nothing to restore
+ return False
+
+ checkRadioItems = obj.RestoreValue(PERSIST_MENUBAR_CHECKRADIO_ITEMS)
+
+ if checkRadioItems is None:
+ return False
+
+ retVal = True
+ for indx in xrange(menuCount):
+ menu = bar.GetMenu(indx)
+ for item in menu.GetMenuItems():
+ if item.GetKind() in [wx.ITEM_CHECK, wx.ITEM_RADIO]:
+ itemId = item.GetId()
+ if itemId in checkRadioItems:
+ item.Check(checkRadioItems[itemId])
+ else:
+ retVal = False
+
+ return retVal
+
+
+ def GetKind(self):
+
+ return PERSIST_MENUBAR_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class ToolBarHandler(AbstractHandler):
+ """
+ Supports saving/restoring the :class:`lib.agw.aui.auibar.AuiToolBar` items state.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`lib.agw.aui.auibar.AuiToolBar`.
+
+ .. todo::
+
+ Find a way to handle :class:`ToolBar` UI settings as it has been done for
+ :class:`lib.agw.aui.auibar.AuiToolBar`: currently :class:`ToolBar` doesn't seem
+ to have easy access to the underlying toolbar tools.
+
+ """
+
+ def __init__(self, pObject):
+
+ AbstractHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ bar, obj = self._window, self._pObject
+ toolCount = bar.GetToolCount()
+
+ if toolCount == 0:
+ # Nothing to save
+ return False
+
+ checkRadioItems = {}
+ for indx in xrange(toolCount):
+ tool = bar.FindToolByIndex(indx)
+ if tool is not None:
+ if tool.GetKind() in [AUI.ITEM_CHECK, AUI.ITEM_RADIO]:
+ checkRadioItems[tool.GetId()] = tool.GetState() & AUI.AUI_BUTTON_STATE_CHECKED
+
+ obj.SaveValue(PERSIST_TOOLBAR_CHECKRADIO_ITEMS, checkRadioItems)
+ return True
+
+
+ def Restore(self):
+
+ bar, obj = self._window, self._pObject
+ toolCount = bar.GetToolCount()
+
+ if toolCount == 0:
+ # Nothing to save
+ return False
+
+ checkRadioItems = obj.RestoreValue(PERSIST_TOOLBAR_CHECKRADIO_ITEMS)
+
+ if checkRadioItems is None:
+ return False
+
+ for indx in xrange(toolCount):
+ tool = bar.FindToolByIndex(indx)
+ if tool is not None:
+ toolId = tool.GetId()
+ if toolId in checkRadioItems:
+ if tool.GetKind() in [AUI.ITEM_CHECK, AUI.ITEM_RADIO]:
+ state = checkRadioItems[toolId]
+ if state & AUI.AUI_BUTTON_STATE_CHECKED:
+ tool.SetState(tool.GetState() | AUI.AUI_BUTTON_STATE_CHECKED)
+ else:
+ tool.SetState(tool.GetState() & ~AUI.AUI_BUTTON_STATE_CHECKED)
+
+ return True
+
+
+ def GetKind(self):
+
+ return PERSIST_TOOLBAR_KIND
+
+# ----------------------------------------------------------------------------------- #
+
+class FileDirDialogHandler(TLWHandler, FileDirPickerHandler):
+ """
+ Supports saving/restoring a :class:`DirDialog` / :class:`FileDialog` path.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`DirDialog`;
+ - :class:`FileDialog`.
+ """
+
+ def __init__(self, pObject):
+
+ TLWHandler.__init__(self, pObject)
+ FileDirPickerHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ tlw = TLWHandler.Save(self)
+ fdp = FileDirPickerHandler.Save(self)
+
+ return (tlw and fdp)
+
+
+ def Restore(self):
+
+ tlw = TLWHandler.Restore(self)
+ fdp = FileDirPickerHandler.Restore(self)
+ return (tlw and fdp)
+
+
+ def GetKind(self):
+
+ return PERSIST_FILEDIRPICKER_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class FindReplaceHandler(TLWHandler):
+ """
+ Supports saving/restoring a :class:`FindReplaceDialog` data (search string, replace string
+ and flags).
+
+ This class handles the following wxPython widgets:
+
+ - :class:`FindReplaceDialog`.
+
+ .. todo:: Find a way to properly save and restore dialog data (:class:`ColourDialog`, :class:`FontDialog` etc...).
+
+ """
+
+ def __init__(self, pObject):
+
+ TLWHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ findDialog, obj = self._window, self._pObject
+ data = findDialog.GetData()
+
+ obj.SaveValue(PERSIST_FINDREPLACE_FLAGS, data.GetFlags())
+ obj.SaveValue(PERSIST_FINDREPLACE_SEARCH, data.GetFindString())
+ obj.SaveValue(PERSIST_FINDREPLACE_REPLACE, data.GetReplaceString())
+
+ return TLWHandler.Save(self)
+
+
+ def Restore(self):
+
+ findDialog, obj = self._window, self._pObject
+
+ flags = obj.RestoreValue(PERSIST_FINDREPLACE_FLAGS)
+ search = obj.RestoreValue(PERSIST_FINDREPLACE_SEARCH)
+ replace = obj.RestoreValue(PERSIST_FINDREPLACE_REPLACE)
+
+ data = findDialog.GetData()
+ if flags is not None:
+ data.SetFlags(flags)
+ if search is not None:
+ data.SetFindString(search)
+ if replace is not None:
+ data.SetReplaceString(replace)
+
+ retVal = TLWHandler.Restore(self)
+
+ return (flags is not None and search is not None and replace is not None and retVal)
+
+
+ def GetKind(self):
+
+ return PERSIST_FINDREPLACE_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class FontDialogHandler(TLWHandler):
+ """
+ Supports saving/restoring a :class:`FontDialog` data (effects, symbols, colour, font, help).
+
+ This class handles the following wxPython widgets:
+
+ - :class:`FontDialog`.
+
+ .. todo:: Find a way to properly save and restore dialog data (:class:`ColourDialog`, :class:`FontDialog` etc...).
+
+ """
+
+ def __init__(self, pObject):
+
+ TLWHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ fontDialog, obj = self._window, self._pObject
+ data = fontDialog.GetFontData()
+
+ obj.SaveValue(PERSIST_FONTDIALOG_EFFECTS, data.GetEnableEffects())
+ obj.SaveValue(PERSIST_FONTDIALOG_SYMBOLS, data.GetAllowSymbols())
+ obj.SaveValue(PERSIST_FONTDIALOG_COLOUR, data.GetColour().Get(includeAlpha=True))
+ obj.SaveValue(PERSIST_FONTDIALOG_FONT, CreateFont(data.GetChosenFont()))
+ obj.SaveValue(PERSIST_FONTDIALOG_HELP, data.GetShowHelp())
+
+ return TLWHandler.Save(self)
+
+
+ def Restore(self):
+
+ fontDialog, obj = self._window, self._pObject
+ data = fontDialog.GetFontData()
+
+ effects = obj.RestoreValue(PERSIST_FONTDIALOG_EFFECTS)
+ symbols = obj.RestoreValue(PERSIST_FONTDIALOG_SYMBOLS)
+ colour = obj.RestoreValue(PERSIST_FONTDIALOG_COLOUR)
+ font = obj.RestoreValue(PERSIST_FONTDIALOG_FONT)
+ help = obj.RestoreValue(PERSIST_FONTDIALOG_HELP)
+
+ if effects is not None:
+ data.EnableEffects(effects)
+ if symbols is not None:
+ data.SetAllowSymbols(symbols)
+ if colour is not None:
+ data.SetColour(wx.Colour(*colour))
+ if font is not None:
+ data.SetInitialFont(wx.Font(*font))
+ if help is not None:
+ data.SetShowHelp(help)
+
+ return (effects is not None and symbols is not None and colour is not None and \
+ font is not None and help is not None and TLWHandler.Restore(self))
+
+
+ def GetKind(self):
+
+ return PERSIST_FONTDIALOG_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class ColourDialogHandler(TLWHandler):
+ """
+ Supports saving/restoring a :class:`ColourDialog` data (colour, custom colours and full
+ choice in the dialog).
+
+ This class handles the following wxPython widgets:
+
+ - :class:`ColourDialog`;
+ - :class:`lib.agw.cubecolourdialog.CubeColourDialog`.
+
+ .. todo:: Find a way to properly save and restore dialog data (:class:`ColourDialog`, :class:`FontDialog` etc...).
+
+ """
+
+ def __init__(self, pObject):
+
+ TLWHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ colDialog, obj = self._window, self._pObject
+ data = colDialog.GetColourData()
+
+ obj.SaveValue(PERSIST_COLOURDIALOG_COLOUR, data.GetColour().Get(includeAlpha=True))
+ obj.SaveValue(PERSIST_COLOURDIALOG_CHOOSEFULL, data.GetChooseFull())
+
+ customColours = []
+ for indx in xrange(15):
+ colour = data.GetCustomColour(indx)
+ if not colour.IsOk() or colour == wx.WHITE:
+ break
+
+ customColours.append(colour.Get(includeAlpha=True))
+
+ obj.SaveValue(PERSIST_COLOURDIALOG_CUSTOMCOLOURS, customColours)
+
+ return TLWHandler.Save(self)
+
+
+ def Restore(self):
+
+ colDialog, obj = self._window, self._pObject
+ data = colDialog.GetColourData()
+
+ colour = obj.RestoreValue(PERSIST_COLOURDIALOG_COLOUR)
+ chooseFull = obj.RestoreValue(PERSIST_COLOURDIALOG_CHOOSEFULL)
+ customColours = obj.RestoreValue(PERSIST_COLOURDIALOG_CUSTOMCOLOURS)
+
+ if colour is not None:
+ data.SetColour(wx.Colour(*colour))
+ if chooseFull is not None:
+ data.SetChooseFull(chooseFull)
+ if customColours is not None:
+ for indx, colour in enumerate(customColours):
+ data.SetCustomColour(indx, colour)
+
+ return (colour is not None and chooseFull is not None and customColours is not None \
+ and TLWHandler.Restore(self))
+
+
+ def GetKind(self):
+
+ return PERSIST_COLOURDIALOG_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class ChoiceDialogHandler(TLWHandler):
+ """
+ Supports saving/restoring a :class:`MultiChoiceDialog` / :class:`SingleChoiceDialog` choices.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`SingleChoiceDialog`;
+ - :class:`MultiChoiceDialog`.
+ """
+
+ def __init__(self, pObject):
+
+ TLWHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ dialog, obj = self._window, self._pObject
+
+ if issubclass(dialog.__class__, wx.SingleChoiceDialog):
+ selections = dialog.GetSelection()
+ selections = (selections >= 0 and [selections] or [[]])[0]
+ else:
+ selections = dialog.GetSelections()
+
+ obj.SaveValue(PERSIST_CHOICEDIALOG_SELECTIONS, selections)
+ return True
+
+
+ def Restore(self):
+
+ dialog, obj = self._window, self._pObject
+ selections = obj.RestoreValue(PERSIST_CHOICEDIALOG_SELECTIONS)
+
+ if selections is None:
+ return False
+
+ if issubclass(dialog.__class__, wx.SingleChoiceDialog):
+ if selections:
+ dialog.SetSelection(selections[-1])
+ else:
+ dialog.SetSelections(selections)
+
+ return True
+
+
+ def GetKind(self):
+
+ return PERSIST_CHOICEDIALOG_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+class TextEntryHandler(TLWHandler, TextCtrlHandler):
+ """
+ Supports saving/restoring a :class:`TextEntryDialog` string.
+
+ This class handles the following wxPython widgets:
+
+ - :class:`TextEntryDialog`;
+ - :class:`PasswordEntryDialog`.
+ """
+
+ def __init__(self, pObject):
+
+ TLWHandler.__init__(self, pObject)
+ TextCtrlHandler.__init__(self, pObject)
+
+
+ def Save(self):
+
+ tlw = TLWHandler.Save(self)
+ txt = TextCtrlHandler.Save(self)
+ return (tlw and txt)
+
+
+ def Restore(self):
+
+ tlw = TLWHandler.Restore(self)
+ txt = TextCtrlHandler.Restore(self)
+ return (tlw and txt)
+
+
+ def GetKind(self):
+
+ return PERSIST_TLW_KIND
+
+
+# ----------------------------------------------------------------------------------- #
+
+
+HANDLERS = [
+ ("BookHandler", (wx.BookCtrlBase, wx.aui.AuiNotebook, AUI.AuiNotebook, FNB.FlatNotebook,
+ LBK.LabelBook, LBK.FlatImageBook)),
+ ("TLWHandler", (wx.TopLevelWindow, )),
+ ("CheckBoxHandler", (wx.CheckBox, )),
+ ("TreeCtrlHandler", (wx.TreeCtrl, wx.GenericDirCtrl, CT.CustomTreeCtrl)),
+ ("MenuBarHandler", (wx.MenuBar, FM.FlatMenuBar)),
+ ("ToolBarHandler", (AUI.AuiToolBar, )),
+ ("ListBoxHandler", (wx.ListBox, wx.VListBox, wx.HtmlListBox, wx.SimpleHtmlListBox,
+ wx.gizmos.EditableListBox)),
+ ("ListCtrlHandler", (wx.ListCtrl, wx.ListView)), #ULC.UltimateListCtrl (later)
+ ("ChoiceComboHandler", (wx.Choice, wx.ComboBox, wx.combo.OwnerDrawnComboBox)),
+ ("RadioBoxHandler", (wx.RadioBox, )),
+ ("RadioButtonHandler", (wx.RadioButton, )),
+ ("ScrolledWindowHandler", (wx.ScrolledWindow, scrolled.ScrolledPanel)),
+ ("SliderHandler", (wx.Slider, KC.KnobCtrl)),
+ ("SpinHandler", (wx.SpinButton, wx.SpinCtrl, FS.FloatSpin)),
+ ("SplitterHandler", (wx.SplitterWindow, )),
+ ("TextCtrlHandler", (wx.TextCtrl, wx.SearchCtrl, expando.ExpandoTextCtrl, masked.TextCtrl,
+ masked.ComboBox, masked.IpAddrCtrl, masked.TimeCtrl, masked.NumCtrl)),
+ ("TreeListCtrlHandler", (HTL.HyperTreeList, wx.gizmos.TreeListCtrl)),
+ ("CalendarCtrlHandler", (calendar.CalendarCtrl, )),
+ ("CollapsiblePaneHandler", (wx.CollapsiblePane, PCP.PyCollapsiblePane)),
+ ("AUIHandler", (wx.Panel, )),
+ ("DatePickerHandler", (wx.DatePickerCtrl, wx.GenericDatePickerCtrl)),
+ ("MediaCtrlHandler", (wx.media.MediaCtrl, )),
+ ("ColourPickerHandler", (wx.ColourPickerCtrl, csel.ColourSelect)),
+ ("FileDirPickerHandler", (wx.FilePickerCtrl, wx.DirPickerCtrl)),
+ ("FontPickerHandler", (wx.FontPickerCtrl, )),
+ ("FileHistoryHandler", (wx.FileHistory, )),
+ ("ToggleButtonHandler", (wx.ToggleButton, buttons.GenToggleButton,
+ buttons.GenBitmapToggleButton, buttons.GenBitmapTextToggleButton)),
+ ]
+
+STANDALONE_HANDLERS = [
+ ("TreebookHandler", (wx.Treebook, )),
+ ("CheckListBoxHandler", (wx.CheckListBox, )),
+ ("FileDirDialogHandler", (wx.DirDialog, wx.FileDialog)),
+ ("FindReplaceHandler", (wx.FindReplaceDialog, )),
+ ("FontDialogHandler", (wx.FontDialog, )),
+ ("ColourDialogHandler", (wx.ColourDialog, CCD.CubeColourDialog)),
+ ("ChoiceDialogHandler", (wx.SingleChoiceDialog, wx.MultiChoiceDialog)),
+ ("TextEntryHandler", (wx.TextEntryDialog, wx.PasswordEntryDialog)),
+ ]
+
+if hasSB:
+ HANDLERS[-1] = ("ToggleButtonHandler", (wx.ToggleButton, buttons.GenToggleButton,
+ buttons.GenBitmapToggleButton,
+ buttons.GenBitmapTextToggleButton,
+ SB.SToggleButton, SB.SBitmapToggleButton,
+ SB.SBitmapTextToggleButton))
+
+# ----------------------------------------------------------------------------------- #
+
+def FindHandler(pObject):
+ """
+ Finds a suitable handler for the input `Persistent Object` depending on the
+ widget kind.
+
+ :param `pObject`: an instance of :class:`~lib.agw.persist.persistencemanager.PersistentObject` class.
+ """
+
+ window = pObject.GetWindow()
+ klass = window.__class__
+
+ if hasattr(window, "_persistentHandler"):
+ # if control has a handler, just return it
+ return window._persistentHandler
+
+ for handler, subclasses in STANDALONE_HANDLERS:
+ for subclass in subclasses:
+ if issubclass(klass, subclass):
+ return eval(handler)(pObject)
+
+ for handler, subclasses in HANDLERS:
+ for subclass in subclasses:
+ if issubclass(klass, subclass):
+ return eval(handler)(pObject)
+
+ raise Exception("Unsupported persistent handler (class=%s, name=%s)"%(klass, window.GetName()))
+
+# ----------------------------------------------------------------------------------- #
+
+def HasCtrlHandler(control):
+ """
+ Is there a suitable handler for this control
+
+ :param `control`: the control instance to check if a handler for it exists.
+ """
+
+ klass = control.__class__
+
+ if hasattr(control, "_persistentHandler"):
+ # if control has a handler, just return it
+ return True
+
+ for handler, subclasses in STANDALONE_HANDLERS:
+ for subclass in subclasses:
+ if issubclass(klass, subclass):
+ return True
+
+ for handler, subclasses in HANDLERS:
+ for subclass in subclasses:
+ if issubclass(klass, subclass):
+ return True
+
+ return False
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persistencemanager.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persistencemanager.py
new file mode 100644
index 0000000..9498358
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/persist/persistencemanager.py
@@ -0,0 +1,845 @@
+# -*- coding: utf-8 -*-#
+#!/usr/bin/env python2
+# --------------------------------------------------------------------------- #
+# PersistentControls Library wxPython IMPLEMENTATION
+#
+# Inspired by the wxWidgets implementation by Vadim Zeitlin.
+#
+# License: wxWidgets license
+#
+# Python Code By:
+#
+# Andrea Gavana, @ 16 Nov 2009
+# Latest Revision: 27 Mar 2013, 21.00 GMT
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+This module contains the definitions of `PersistentObject` and `PersistenceManager` objects.
+"""
+
+import wx
+import os
+import warnings
+import datetime
+
+import wx.gizmos
+
+from persist_handlers import FindHandler, HasCtrlHandler
+
+from persist_constants import BAD_DEFAULT_NAMES, CONFIG_PATH_SEPARATOR
+from persist_constants import PM_DEFAULT_STYLE, PM_PERSIST_CONTROL_VALUE
+
+# ----------------------------------------------------------------------------------- #
+
+class PersistentObject(object):
+ """
+ :class:`PersistentObject`: ABC for anything persistent.
+
+ This is the base class for persistent object adapters.
+ wxPython persistence framework is non-intrusive, i.e. can work with the
+ classes which have no relationship to nor knowledge of it. To allow this,
+ an intermediate persistence adapter is used: this is just a simple object
+ which provides the methods used by :class:`PersistenceManager` to save and restore
+ the object properties and implements them using the concrete class methods.
+
+ You may derive your own classes from :class:`PersistentObject` to implement persistence
+ support for your common classes, see :ref:`persistent-windows` in the
+ `__init__.py` file.
+ """
+
+ def __init__(self, window, persistenceHandler=None):
+ """
+ Default class constructor.
+
+ :param `window`: an instance of :class:`Window`;
+ :param `persistenceHandler`: if not ``None``, this should a custom handler derived
+ from :class:`~lib.agw.persist.persist_handlers.AbstractHandler`.
+ """
+
+ self._name = window.GetName()
+
+ if not self._name.strip():
+ raise Exception("Persistent windows should be named! (class=%s)"%window.__class__)
+
+ klass = window.__class__
+ if issubclass(klass, wx.GenericDirCtrl):
+ self._window = window.GetTreeCtrl()
+ elif issubclass(klass, wx.gizmos.EditableListBox):
+ self._window = window.GetListCtrl()
+ else:
+ self._window = window
+
+ if persistenceHandler is not None:
+ self._persistentHandler = persistenceHandler(self)
+ else:
+ self._persistentHandler = FindHandler(self)
+
+ if self._name in BAD_DEFAULT_NAMES:
+ warnings.warn("Window names should not be defaulted! (class=%s, name=%s)"%(window.__class__, window.GetName()))
+
+
+ def GetName(self):
+ """
+ Returns the string uniquely identifying the window we're associated with
+ among all the other objects of the same type.
+
+ :note: This method is used together with :meth:`~PersistentObject.GetKind` to construct the unique
+ full name of the object in e.g. a configuration file.
+ """
+
+ return self._name
+
+
+ def GetWindow(self):
+ """ Returns the actual associated window. """
+
+ return self._window
+
+
+ def GetKind(self):
+ """
+ Returns the string uniquely identifying the objects supported by this adapter.
+
+ :note: This method is called from :meth:`~PersistentObject.SaveValue` and :meth:`~PersistentObject.RestoreValue` and normally
+ returns some short (but not too cryptic) strings, e.g. "Checkbox".
+ """
+
+ return self._persistentHandler.GetKind()
+
+
+ def Save(self):
+ """
+ Saves the corresponding window settings.
+
+ .. note::
+
+ This method shouldn't be used directly as it doesn't respect the
+ global :meth:`PersistenceManager.DisableSaving() <PersistenceManager.DisableSaving>` settings, use :class:`PersistenceManager`
+ methods with the same name instead.
+
+ """
+
+ self._persistentHandler.Save()
+
+
+ def Restore(self):
+ """
+ Restores the corresponding window settings.
+
+ :note: This method shouldn't be used directly as it doesn't respect the
+ global :meth:`PersistenceManager.DisableRestoring() <PersistenceManager.DisableRestoring>` settings, use :class:`PersistenceManager`
+ methods with the same name instead.
+ """
+
+ return self._persistentHandler.Restore()
+
+
+ def SaveValue(self, name, value):
+ """
+ Save the specified value using the given name.
+
+ :param `name`: the name of the value in the configuration file;
+ :param `value`: the value to save.
+
+ :returns: ``True`` if the value was saved or ``False`` if an error occurred.
+ """
+
+ return PersistenceManager.Get().SaveValue(self, name, value)
+
+
+ def SaveCtrlValue(self, name, value):
+ """
+ Save the specified value using the given name, should be used only for
+ controls data value.
+
+ :param `name`: the name of the value in the configuration file;
+ :param `value`: the value to save.
+
+ :returns: ``True`` if the value was saved or ``False`` if an error occurred.
+ """
+
+ return PersistenceManager.Get().SaveCtrlValue(self, name, value)
+
+
+ def RestoreValue(self, name):
+ """
+ Restore the value saved by :meth:`~PersistentObject.SaveValue`.
+
+ :param `name`: the same name as was used by :meth:`~PersistentObject.SaveValue`.
+
+ :returns: ``True`` if the value was successfully read or ``False`` if
+ it was not found or an error occurred.
+ """
+
+ return PersistenceManager.Get().RestoreValue(self, name)
+
+
+ def RestoreCtrlValue(self, name):
+ """
+ Restore the value saved by :meth:`~PersistentObject.SaveCtrlValue`, should be used only for
+ controls data value.
+
+ :param `name`: the same name as was used by :meth:`~PersistentObject.SaveCtrlValue`.
+
+ :returns: ``True`` if the value was successfully read or ``False`` if
+ it was not found or an error occurred.
+ """
+
+ return PersistenceManager.Get().RestoreCtrlValue(self, name)
+
+
+# ----------------------------------------------------------------------------------- #
+
+class PersistenceManager(object):
+ """
+ :class:`PersistenceManager`: global aspects of persistent windows.
+
+ Provides support for automatically saving and restoring object properties
+ to persistent storage.
+
+ This class is the central element of wxPython persistence framework, see
+ the :ref:`persistent-overview` in the `__init__.py` file for its overview.
+
+ This is a singleton class and its unique instance can be retrieved using
+ :meth:`PersistenceManager.Get() <PersistenceManager.Get>` method.
+ """
+
+ def __init__(self):
+ """
+ Default class constructor.
+
+ This method should **not** be called directly: you should use the object
+ obtained by :meth:`PersistenceManager.Get() <PersistenceManager.Get>` and assign manager styles, custom
+ configuration files and custom configuration handlers using the appropriate
+ methods in this class.
+
+ Interesting attributes you can set for this class are:
+
+ - `configFile`: the persistent configuration file for :class:`PersistenceManager`,
+ a custom file name to which :class:`FileConfig` will access to store and
+ retrieve UI settings;
+ - `configKey`: the persistent key name inside the configuration file for
+ :class:`PersistenceManager`;
+ - `customConfigHandler`: the persistent configuration handler for :class:`PersistenceManager`;
+ this attribute is an object capable of saving/restoring UI settings. This
+ can be a cPickle object or a ConfigObj one, for example.
+ - `style`: a combination of the following values:
+
+ ======================================== ==================================
+ Flag name Description
+ ======================================== ==================================
+ ``PM_SAVE_RESTORE_AUI_PERSPECTIVES`` If a toplevel window has an AUI manager associated, the manager will save and restore its AUI perspective
+ ``PM_SAVE_RESTORE_TREE_LIST_SELECTIONS`` If set, the manager will save items selections in list and tree controls
+ ``PM_PERSIST_CONTROL_VALUE`` If set, control values will be persisted. This is handy for e.g. applications using a database, where the data (control value) is persisted in the database and persisting it with PM again would only cause confusion.
+ ``PM_DEFAULT_STYLE`` Same as ``PM_SAVE_RESTORE_AUI_PERSPECTIVES``
+ ======================================== ==================================
+
+ :note: UI settings are stored as dictionaries key <=> tuple: the tuple value
+ contains two items. The first is the value *type* (i.e., float, int, bool etc...)
+ while the second is the actual key value.
+
+ """
+
+ object.__init__(self)
+
+ # Specifies custom wx.Config object to use (i.e., custom file names)
+ self._configFile = None
+
+ # Specifies custom key in the wx.Config object to use
+ self._configKey = None
+
+ # Specifies whether a custom config handler exists, so that we will not use
+ # wx.FileConfig (i.e., ConfigObj, ConfigParser etc...)
+ self._customConfigHandler = None
+
+ # Specifies the PersistenceManager style
+ self._style = PM_DEFAULT_STYLE
+
+ # Set these values to True if we should restore/save the settings (it doesn't
+ # make much sense to use this class when both of them are False but setting
+ # one of them to False may make sense in some situations)
+ self._doSave = True
+ self._doRestore = True
+
+ # Flag set to True when PersistenceManager has restored any window
+ self._hasRestored = False
+
+ # map with the registered objects as keys and associated
+ # PersistentObjects as values
+ self._persistentObjects = {}
+
+
+ def Get(self):
+ """ Accessor to the unique persistence manager object. """
+
+ if not hasattr(self, "_instance"):
+ self._instance = PersistenceManager()
+
+ return self._instance
+
+ Get = classmethod(Get)
+
+
+ def Free(self):
+ """ Destructor for the unique persistence manager object. """
+
+ if hasattr(self, "_instance"):
+ del self._instance
+
+ Free = classmethod(Free)
+
+
+ def GetManagerStyle(self):
+ """
+ Returns the :class:`PersistenceManager` style.
+
+ :see: :meth:`~PersistenceManager.SetManagerStyle` for a list of possible styles.
+ """
+
+ return self._style
+
+
+ def SetManagerStyle(self, style):
+ """
+ Sets the :class:`PersistenceManager` style.
+
+ :param `style`: a combination of the following values:
+
+ ======================================== ==================================
+ Flag name Description
+ ======================================== ==================================
+ ``PM_SAVE_RESTORE_AUI_PERSPECTIVES`` If a toplevel window has an AUI manager associated, the manager will save and restore its AUI perspective
+ ``PM_SAVE_RESTORE_TREE_LIST_SELECTIONS`` If set, the manager will save items selections in list and tree controls
+ ``PM_PERSIST_CONTROL_VALUE`` If set, control values will be persisted. This is handy for e.g. applications using a database, where the data (control value) is persisted in the database and persisting it with PM again would only cause confusion.
+ ``PM_DEFAULT_STYLE`` Same as ``PM_SAVE_RESTORE_AUI_PERSPECTIVES``.
+ ======================================== ==================================
+ """
+
+ self._style = style
+
+
+ def SetPersistenceKey(self, key):
+ """
+ Sets the persistent key name inside the configuration file for :class:`PersistenceManager`.
+
+ :param `key`: a short meaningful name for your unique preferences key.
+
+ :note: Calling this method has no influence if you are using your own
+ custom configuration handler (i.e., by using ConfigObj/ConfigParser/cPickle etc...).
+ """
+
+ self._configKey = key
+
+
+ def GetPersistenceKey(self):
+ """
+ Returns the persistent key name inside the configuration file for :class:`PersistenceManager`.
+
+ :note: The return value of this method is not used if you are using your own
+ custom configuration handler (i.e., by using ConfigObj/ConfigParser/cPickle etc...).
+ """
+
+ return self._configKey
+
+
+ def SetPersistenceFile(self, fileName):
+ """
+ Sets the persistent configuration file for :class:`PersistenceManager`.
+
+ :param `fileName`: the file name where to store the persistent options.
+
+ :note: Calling this method has no influence if you are using your own
+ custom configuration handler (i.e., by using ConfigObj/ConfigParser/cPickle etc...).
+ """
+
+ self._configFile = fileName
+ self._persistentObjects = {}
+
+
+ def GetPersistenceFile(self):
+ """
+ Returns the persistent configuration file for :class:`PersistenceManager`.
+
+ :note: The return value of this method is not used if you are using your own
+ custom configuration handler (i.e., by using ConfigObj/ConfigParser/cPickle etc...).
+ """
+
+ if self._configFile is not None:
+ persistenceDir, fileName = os.path.split(self._configFile)
+ fileName = self._configFile
+ else:
+ persistenceDir = self.GetPersistenceDirectory()
+ fileName = "Persistence_Options"
+
+ fileName = os.path.join(persistenceDir, fileName)
+
+ if not os.path.exists(persistenceDir):
+ # Create the data folder, it still doesn't exist
+ os.makedirs(persistenceDir)
+
+ config = wx.FileConfig(localFilename=fileName)
+ return config
+
+
+ def SetConfigurationHandler(self, handler):
+ """
+ Sets the persistent configuration handler for :class:`PersistenceManager`.
+
+ :param `handler`: an object capable of saving/restoring UI settings. This
+ can be a cPickle object or a ConfigObj one, for example.
+
+ :note: UI settings are stored as dictionaries key <=> tuple: the tuple value
+ contains two items. The first is the value *type* (i.e., float, int, bool etc...)
+ while the second is the actual key value.
+ """
+
+ self._customConfigHandler = handler
+
+
+ def GetConfigurationHandler(self):
+ """
+ Returns the persistent configuration handler for :class:`PersistenceManager`.
+ """
+
+ return self._customConfigHandler
+
+
+ def GetPersistenceDirectory(self):
+ """
+ Returns a default persistent option directory for :class:`PersistenceManager`.
+
+ :note: The return value of this method is not used if you are using your own
+ custom configuration handler (i.e., by using ConfigObj/ConfigParser/cPickle etc...)
+ or if you have specified a custom configuration file to use with :class:`FileConfig`.
+ """
+
+ sp = wx.StandardPaths.Get()
+ return sp.GetUserDataDir()
+
+
+ def Find(self, window):
+ """
+ Checks if the object is registered and return the associated :class:`PersistentObject`
+ if it is or ``None`` otherwise.
+
+ :param `window`: an instance of :class:`Window`.
+ """
+
+ if window:
+ # protect for PyDeadObjectError
+ if window.GetName() in self._persistentObjects:
+ return window
+
+
+ def Register(self, window, persistenceHandler=None):
+ """
+ Register an object with the manager.
+
+ :param `window`: an instance of :class:`Window`;
+ :param `persistenceHandler`: if not ``None``, this should a custom handler derived
+ from :class:`~lib.agw.persist.persist_handlers.AbstractHandler`.
+
+ .. note::
+
+ Note that registering the object doesn't do anything except allowing to call
+ :meth:`~PersistenceManager.Restore` for it later. If you want to register the object and restore its
+ properties, use :meth:`~PersistenceManager.RegisterAndRestore`.
+
+
+ .. note::
+
+ The manager takes ownership of the :class:`PersistentObject` and will delete it when
+ it is unregistered.
+
+ """
+
+ if self.Find(window):
+ raise Exception("Object (class=%s, name=%s) is already registered"%(window.__class__, window.GetName()))
+
+ name = window.GetName()
+ self._persistentObjects[name] = PersistentObject(window, persistenceHandler)
+
+ return True
+
+
+ def Unregister(self, window):
+ """
+ Unregister the object, this is called by :class:`PersistenceManager` itself so there is
+ usually no need to do it explicitly.
+
+ :param `window`: an instance of :class:`Window`, which must have been previously
+ registered with :meth:`~PersistenceManager.Register`.
+
+ :note: For the persistent windows this is done automatically (via :meth:`~PersistenceManager.SaveAndUnregister`)
+ when the window is destroyed so you only need to call this function explicitly if you
+ are using custom persistent objects or if you want to prevent the object properties
+ from being saved.
+
+ :note: This deletes the associated :class:`PersistentObject`.
+ """
+
+ if not self.Find(window):
+ return False
+
+ name = window.GetName()
+ self._persistentObjects.pop(name)
+
+ return True
+
+
+ def Save(self, window):
+ """
+ Saves the state of an object.
+
+ :param `window`: an instance of :class:`Window`.
+
+ :note: This methods does nothing if :meth:`~PersistenceManager.DisableSaving` was called.
+ """
+
+ if not self._doSave:
+ return False
+
+ if not self.Find(window):
+ return False
+
+ name = window.GetName()
+ self._persistentObjects[name].Save()
+
+ return True
+
+
+ def Restore(self, window):
+ """
+ Restores the state of an object.
+
+ :param `window`: an instance of :class:`Window`.
+
+ :returns: ``True`` if the object properties were restored or ``False`` if nothing
+ was found to restore or the saved settings were invalid.
+
+ :note: This methods does nothing if :meth:`~PersistenceManager.DisableRestoring` was called.
+ """
+
+ if not self._doRestore:
+ return False
+
+ if not self.Find(window):
+ return False
+
+ name = window.GetName()
+ return self._persistentObjects[name].Restore()
+
+
+ def DisableSaving(self):
+ """
+ Globally disables saving the persistent properties (enabled by default).
+
+ :note: By default, saving properties in :meth:`~PersistenceManager.Save` is enabled but the program
+ may wish to disable if, for example, it detects that it is running on a
+ system which shouldn't be modified in any way and so configuration file
+ (or Windows registry) shouldn't be written to.
+ """
+
+ self._doSave = False
+
+
+ def DisableRestoring(self):
+ """
+ Globally disables restoring the persistent properties (enabled by default).
+
+ :note: By default, restoring properties in :meth:`~PersistenceManager.Restore` is enabled but this
+ function allows to disable it. This is mostly useful for testing.
+ """
+
+ self._doRestore = False
+
+
+ def EnableSaving(self):
+ """
+ Globally enables saving the persistent properties (enabled by default).
+
+ :note: By default, saving properties in :meth:`~PersistenceManager.Save` is enabled but the program
+ may wish to disable if, for example, it detects that it is running on a
+ system which shouldn't be modified in any way and so configuration file
+ (or Windows registry) shouldn't be written to.
+ """
+
+ self._doSave = True
+
+
+ def EnableRestoring(self):
+ """
+ Globally enables restoring the persistent properties (enabled by default).
+
+ :note: By default, restoring properties in :meth:`~PersistenceManager.Restore` is enabled but this
+ function allows to disable it. This is mostly useful for testing.
+ """
+
+ self._doRestore = True
+
+
+ def SaveAndUnregister(self, window=None):
+ """
+ Combines both :meth:`~PersistenceManager.Save` and :meth:`~PersistenceManager.Unregister` calls.
+
+ :param `window`: an instance of :class:`Window`. If it is ``None``, all the
+ windows previously registered are saved and then unregistered.
+ """
+
+ if window is None:
+ for name, obj in self._persistentObjects.items():
+ self.SaveAndUnregister(obj.GetWindow())
+
+ return
+
+ self.Save(window)
+ self.Unregister(window)
+
+
+ def RegisterAndRestore(self, window):
+ """
+ Combines both :meth:`~PersistenceManager.Register` and :meth:`~PersistenceManager.Restore` calls.
+
+ :param `window`: an instance of :class:`Window`.
+ """
+
+ return self.Register(window) and self.Restore(window)
+
+
+ def RegisterAndRestoreAll(self, window, children=None):
+ """
+ Recursively registers and restore the state of the input `window` and of
+ all of its children.
+
+ :param `window`: an instance of :class:`Window`;
+ :param `children`: list of children of the input `window`, on first call it is equal to ``None``.
+ """
+
+ if children is None:
+ if HasCtrlHandler(window):
+ # Control has persist support
+ self.HasRestoredProp = self.RegisterAndRestore(window)
+
+ children = window.GetChildren()
+
+ for child in children:
+ name = child.GetName()
+
+ if name not in BAD_DEFAULT_NAMES:
+ if HasCtrlHandler(child):
+ # Control has persist support
+ self.HasRestoredProp = self.RegisterAndRestore(child)
+
+ self.RegisterAndRestoreAll(window, child.GetChildren())
+
+ return self.HasRestoredProp
+
+
+ def RestoreAll(self, window, children=None):
+ """
+ Recursively restore the state of the input `window` and of
+ all of its children.
+
+ :param `window`: an instance of :class:`Window`;
+ :param `children`: list of children of the input `window`, on first call it is equal to ``None``.
+ """
+
+ if children is None:
+ if HasCtrlHandler(window):
+ # Control has persist support
+ self.HasRestoredProp = self.Restore(window)
+
+ children = window.GetChildren()
+
+ for child in children:
+ name = child.GetName()
+
+ if name not in BAD_DEFAULT_NAMES:
+ if HasCtrlHandler(child):
+ # Control has persist support
+ self.HasRestoredProp = self.Restore(child)
+
+ self.RestoreAll(window, child.GetChildren())
+
+ return self.HasRestoredProp
+
+
+ def HasRestored(self):
+ """
+ This method returns ``True`` if any of the windows managed by
+ :class:`PersistenceManager` has had its settings restored.
+
+ :returns: ``True`` if any window was restored, ``False`` otherwise.
+
+ .. versionadded:: 0.9.7
+ """
+
+ return self.HasRestoredProp
+
+
+ @property
+ def HasRestoredProp(self):
+ """
+ This property returns ``True`` if any of the windows managed by
+ :class:`PersistenceManager` has had its settings restored.
+
+ :returns: ``True`` if any window was restored, ``False`` otherwise.
+
+ .. versionadded:: 0.9.7
+ """
+
+ return self._hasRestored
+
+
+ @HasRestoredProp.setter
+ def HasRestoredProp(self, flag):
+ """
+ This property keeps track if any of the windows managed by
+ :class:`PersistenceManager` has had its settings restored.
+
+ :param boolean `flag`: True will be remembered
+ """
+
+ if flag:
+ self._hasRestored = flag
+
+
+ def GetKey(self, obj, keyName):
+ """
+ Returns a correctly formatted key name for the object `obj` and `keyName` parameters.
+
+ :param `obj`: an instance of :class:`PersistentObject`;
+ :param `keyName`: a string specifying the key name.
+ """
+
+ key = (self._configKey is None and ["Persistence_Options"] or [self._configKey])[0]
+
+ key += CONFIG_PATH_SEPARATOR + obj.GetKind()
+ key += CONFIG_PATH_SEPARATOR + obj.GetName()
+ key += CONFIG_PATH_SEPARATOR + keyName
+
+ return key
+
+
+ def SaveCtrlValue(self, obj, keyName, value):
+ """
+ Check if we persist the widget value, if so pass it to :meth:`~PersistenceManager.DoSaveValue`.
+
+ :param `obj`: an instance of :class:`PersistentObject`;
+ :param `keyName`: a string specifying the key name;
+ :param `value`: the value to store in the configuration file.
+ """
+
+ if self._style & PM_PERSIST_CONTROL_VALUE:
+ return self.DoSaveValue(obj, keyName, value)
+
+
+ def SaveValue(self, obj, keyName, value):
+ """
+ Convenience method, all the action is done in :meth:`~PersistenceManager.DoSaveValue`.
+
+ :param `obj`: an instance of :class:`PersistentObject`;
+ :param `keyName`: a string specifying the key name;
+ :param `value`: the value to store in the configuration file.
+ """
+
+ return self.DoSaveValue(obj, keyName, value)
+
+
+ def DoSaveValue(self, obj, keyName, value):
+ """
+ Method used by the persistent objects to save the data.
+
+ By default this method simply use :class:`FileConfig` but this behaviour may be
+ overridden by passing a custom configuration handler in the :class:`PersistenceManager`
+ constructor.
+
+ :param `obj`: an instance of :class:`PersistentObject`;
+ :param `keyName`: a string specifying the key name;
+ :param `value`: the value to store in the configuration file.
+ """
+
+ kind = repr(value.__class__).split("'")[1]
+
+ if self._customConfigHandler is not None:
+ result = self._customConfigHandler.SaveValue(self.GetKey(obj, keyName), repr((kind, str(value))))
+ else:
+ config = self.GetPersistenceFile()
+ result = config.Write(self.GetKey(obj, keyName), repr((kind, str(value))))
+ config.Flush()
+
+ return result
+
+
+ def RestoreCtrlValue(self, obj, keyName):
+ """
+ Check if we persist the widget value, if so pass it to :meth:`~PersistenceManager.DoRestoreValue`.
+
+ :param `obj`: an instance of :class:`PersistentObject`;
+ :param `keyName`: a string specifying the key name.
+ """
+
+ if self._style & PM_PERSIST_CONTROL_VALUE:
+ return self.DoRestoreValue(obj, keyName)
+
+
+ def RestoreValue(self, obj, keyName):
+ """
+ Convenience method, all the action is done in :meth:`~PersistenceManager.DoRestoreValue`.
+
+ :param `obj`: an instance of :class:`PersistentObject`;
+ :param `keyName`: a string specifying the key name.
+ """
+
+ return self.DoRestoreValue(obj, keyName)
+
+
+ def DoRestoreValue(self, obj, keyName):
+ """
+ Method used by the persistent objects to restore the data.
+
+ By default this method simply use :class:`FileConfig` but this behaviour may be
+ overridden by passing a custom config handler in the PersistenceManager
+ constructor.
+
+ :param `obj`: an instance of :class:`PersistentObject`;
+ :param `keyName`: a string specifying the key name.
+ """
+
+ if self._customConfigHandler is not None:
+ result = self._customConfigHandler.RestoreValue(self.GetKey(obj, keyName))
+ else:
+ config = self.GetPersistenceFile()
+ result = config.Read(self.GetKey(obj, keyName))
+
+ if result:
+ kind, result = eval(result)
+ if kind in ("unicode", "str"):
+ return result
+ elif kind == "datetime.date":
+ y, m, d = result.split("-")
+ result = datetime.date(int(y), int(m), int(d))
+ return result
+
+ return eval(result)
+
+
+ def AddBadDefaultName(self, name):
+ """
+ Adds a name to the ``BAD_DEFAULT_NAMES`` constant.
+
+ :param `name`: a string specifying the control's default name.
+ """
+
+ global BAD_DEFAULT_NAMES
+ BAD_DEFAULT_NAMES.append(name)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/piectrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/piectrl.py
new file mode 100644
index 0000000..d2fec76
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/piectrl.py
@@ -0,0 +1,988 @@
+# --------------------------------------------------------------------------- #
+# PIECTRL Control wxPython IMPLEMENTATION
+# Python Code By:
+#
+# Andrea Gavana, @ 31 Oct 2005
+# Latest Revision: 17 Aug 2011, 15.00 GMT
+#
+#
+# TODO List/Caveats
+#
+# 1. Maybe Integrate The Very Nice PyOpenGL Implementation Of A PieChart Coded
+# By Will McGugan?
+#
+# 2. Not Tested On Other Platforms, Only On Windows 2000/XP, With Python 2.4.1
+# And wxPython 2.6.1.0
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+
+"""
+:class:`PieCtrl` and :class:`ProgressPie` are simple classes that reproduce the behavior of a pie
+chart.
+
+
+Description
+===========
+
+:class:`PieCtrl` and :class:`ProgressPie` are simple classes that reproduce the behavior of a pie
+chart. They use only pure wxPython classes/methods, without external dependencies.
+:class:`PieCtrl` is somewhat a "static" control, that you may create in order to display
+a simple pie chart on a :class:`Panel` or similar. :class:`ProgressPie` tries to emulate the
+behavior of :class:`ProgressDialog`, but using a pie chart instead of a gauge.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.piectrl as PC
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "PieCtrl Demo")
+
+ panel = wx.Panel(self)
+
+ # create a simple PieCtrl with 3 sectors
+ mypie = PC.PieCtrl(panel, -1, wx.DefaultPosition, wx.Size(180,270))
+
+ part = PC.PiePart()
+
+ part.SetLabel("Label 1")
+ part.SetValue(300)
+ part.SetColour(wx.Colour(200, 50, 50))
+ mypie._series.append(part)
+
+ part = PC.PiePart()
+
+ part.SetLabel("Label 2")
+ part.SetValue(200)
+ part.SetColour(wx.Colour(50, 200, 50))
+ mypie._series.append(part)
+
+ part = PC.PiePart()
+
+ part.SetLabel("helloworld label 3")
+ part.SetValue(50)
+ part.SetColour(wx.Colour(50, 50, 200))
+ mypie._series.append(part)
+
+ # create a ProgressPie
+ progress_pie = PC.ProgressPie(panel, 100, 50, -1, wx.DefaultPosition,
+ wx.Size(180, 200), wx.SIMPLE_BORDER)
+
+ progress_pie.SetBackColour(wx.Colour(150, 200, 255))
+ progress_pie.SetFilledcolour(wx.Colour(255, 0, 0))
+ progress_pie.SetUnfilledColour(wx.WHITE)
+ progress_pie.SetHeight(20)
+
+ main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ main_sizer.Add(mypie, 1, wx.EXPAND | wx.ALL, 5)
+ main_sizer.Add(progress_pie, 1, wx.EXPAND | wx.ALL, 5)
+
+ panel.SetSizer(main_sizer)
+ main_sizer.Layout()
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Methods and Settings
+====================
+
+With :class:`PieCtrl` you can:
+
+- Create a :class:`PieCtrl` with different sectors;
+- Set the sector values, colours and labels;
+- Assign a legend to the :class:`PieCtrl`;
+- Use an image as the :class:`PieCtrl` background;
+- Change the vertical rotation (perspective) of the :class:`PieCtrl`;
+- Show/hide the segment edges.
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`PieCtrl` is distributed under the wxPython license.
+
+Latest revision: Andrea Gavana @ 17 Aug 2011, 15.00 GMT
+
+Version 0.2
+
+"""
+
+
+#----------------------------------------------------------------------
+# Beginning Of PIECTRL wxPython Code
+#----------------------------------------------------------------------
+
+
+import wx
+
+from math import pi, sin, cos
+
+#----------------------------------------------------------------------
+# Class PieCtrlLegend
+# This Class Handles The Legend For The Classic PieCtrl.
+#----------------------------------------------------------------------
+
+class PieCtrlLegend(wx.Window):
+ """
+ This class displays a legend window for the classic :class:`PieCtrl`.
+ """
+
+ def __init__(self, parent, title, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`PieCtrlLegend` parent;
+ :param `title`: the legend title;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style (unused).
+ """
+
+ wx.Window.__init__(self, parent, id, pos, size, style)
+
+ self._title = title
+ self._istransparent = False
+ self._horborder = 5
+ self._verborder = 5
+ self._titlecolour = wx.Colour(0, 0, 127)
+ self._labelcolour = wx.BLACK
+ self._backcolour = wx.Colour(255, 255, 0)
+ self._backgroundDC = wx.MemoryDC()
+ self._parent = parent
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def SetTransparent(self, value=False):
+ """
+ Toggles the legend transparency (visibility).
+
+ :param `value`: ``True`` to set the legend as transparent, ``False`` otherwise.
+ """
+
+ self._istransparent = value
+ self.Refresh()
+
+
+ def RecreateBackground(self, parentdc):
+ """
+ Recreates the legend background.
+
+ :param `parentdc`: an instance of :class:`DC`.
+ """
+
+ w, h = self.GetSize()
+ self._background = wx.EmptyBitmap(w, h)
+ self._backgroundDC.SelectObject(self._background)
+
+ if self.IsTransparent():
+
+ self._backgroundDC.Blit(0, 0, w, h, parentdc, self.GetPosition().x,
+ self.GetPosition().y)
+
+ else:
+
+ self._backgroundDC.SetBackground(wx.Brush(self._backcolour))
+ self._backgroundDC.Clear()
+
+ self.Refresh()
+
+
+ def SetHorizontalBorder(self, value):
+ """
+ Sets the legend's horizontal border.
+
+ :param `value`: the horizontal border thickness, in pixels.
+ """
+
+ self._horborder = value
+ self.Refresh()
+
+
+ def GetHorizontalBorder(self):
+ """ Returns the legend's horizontal border, in pixels. """
+
+ return self._horborder
+
+
+ def SetVerticalBorder(self, value):
+ """
+ Sets the legend's vertical border.
+
+ :param `value`: the horizontal border thickness, in pixels.
+ """
+
+ self._verborder = value
+ self.Refresh()
+
+
+ def GetVerticalBorder(self):
+ """ Returns the legend's vertical border, in pixels. """
+
+ return self._verborder
+
+
+ def SetLabelColour(self, colour):
+ """
+ Sets the legend label colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._labelcolour = colour
+ self.Refresh()
+
+
+ def GetLabelColour(self):
+ """ Returns the legend label colour. """
+
+ return self._labelcolour
+
+
+ def SetLabelFont(self, font):
+ """
+ Sets the legend label font.
+
+ :param `font`: a valid :class:`Font` object.
+ """
+
+ self._labelfont = font
+ self.Refresh()
+
+
+ def GetLabelFont(self):
+ """ Returns the legend label font. """
+
+ return self._labelfont
+
+
+ def SetBackColour(self, colour):
+ """
+ Sets the legend background colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._backcolour = colour
+ self.Refresh()
+
+
+ def GetBackColour(self):
+ """ Returns the legend background colour. """
+
+ return self._backcolour
+
+
+ def IsTransparent(self):
+ """ Returns whether the legend background is transparent or not. """
+
+ return self._istransparent
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`PieCtrlLegend`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ pdc = wx.PaintDC(self)
+
+ w, h = self.GetSize()
+ bmp = wx.EmptyBitmap(w, h)
+ mdc = wx.MemoryDC()
+ mdc.SelectObject(bmp)
+
+ if self.IsTransparent():
+
+ parentdc = wx.ClientDC(self.GetParent())
+ mdc.Blit(0, 0, w, h, self._backgroundDC, 0, 0)
+
+ else:
+
+ mdc.SetBackground(wx.Brush(self._backcolour))
+ mdc.Clear()
+
+ dy = self._verborder
+ mdc.SetFont(self._labelfont)
+ mdc.SetTextForeground(self._labelcolour)
+ maxwidth = 0
+
+ for ii in xrange(len(self._parent._series)):
+
+ tw, th = mdc.GetTextExtent(self._parent._series[ii].GetLabel())
+ mdc.SetBrush(wx.Brush(self._parent._series[ii].GetColour()))
+ mdc.DrawCircle(self._horborder+5, dy+th/2, 5)
+ mdc.DrawText(self._parent._series[ii].GetLabel(), self._horborder+15, dy)
+ dy = dy + th + 3
+ maxwidth = max(maxwidth, int(2*self._horborder+tw+15))
+
+ dy = dy + self._verborder
+ if w != maxwidth or h != dy:
+ self.SetSize((maxwidth, dy))
+
+ pdc.Blit(0, 0, w, h, mdc, 0, 0)
+
+
+#----------------------------------------------------------------------
+# Class PiePart
+# This Class Handles The Legend Segments Properties, Such As Value,
+# Colour And Label.
+#----------------------------------------------------------------------
+
+class PiePart(object):
+ """
+ This class handles the legend segments properties, such as value,
+ colour and label.
+ """
+
+ def __init__(self, value=0, colour=wx.BLACK, label=""):
+ """
+ Default class constructor.
+
+ :param `value`: the pie part value;
+ :param `colour`: the pie part colour;
+ :param `label`: the pie part text label.
+ """
+
+ self._value = value
+ self._colour = colour
+ self._label = label
+
+
+ def SetValue(self, value):
+ """
+ Sets the segment absolute value.
+
+ :param `value`: a floating point number representing the :class:`PiePart` value.
+ """
+
+ self._value = value
+
+
+ def GetValue(self):
+ """ Returns the segment absolute value. """
+
+ return self._value
+
+
+ def SetColour(self, colour):
+ """
+ Sets the segment colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._colour = colour
+
+
+ def GetColour(self):
+ """ Returns the segment colour. """
+
+ return self._colour
+
+
+ def SetLabel(self, label):
+ """
+ Sets the segment label.
+
+ :param `label`: the pie part text label.
+ """
+
+ self._label = label
+
+
+ def GetLabel(self):
+ """ Returns the segment label. """
+
+ return self._label
+
+
+#----------------------------------------------------------------------
+# Class PieCtrl
+# This Is The Main PieCtrl Implementation, Used Also By ProgressPie.
+#----------------------------------------------------------------------
+
+class PieCtrl(wx.Window):
+ """
+ :class:`PieCtrl` is somewhat a "static" control, that you may create in order to display
+ a simple pie chart on a :class:`Panel` or similar.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name="PieCtrl"):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`PieCtrl` parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style (unused);
+ :param `name`: the window name.
+ """
+
+ wx.Window.__init__(self, parent, id, pos, size, style, name)
+
+ self._angle = pi/12
+ self._rotationangle = 0
+ self._height = 10
+ self._background = wx.NullBitmap
+ self._canvasbitmap = wx.EmptyBitmap(1, 1)
+ self._canvasDC = wx.MemoryDC()
+ self._backcolour = wx.WHITE
+ self._showedges = True
+ self._series = []
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+ self.RecreateCanvas()
+ self._legend = PieCtrlLegend(self, "PieCtrl", -1, wx.Point(10,10), wx.Size(100,75))
+
+
+ def SetBackground(self, bmp):
+ """
+ Sets the :class:`PieCtrl` background image.
+
+ :param `bmp`: a valid :class:`Bitmap` object.
+ """
+
+ self._background = bmp
+ self.Refresh()
+
+
+ def GetBackground(self):
+ """ Returns the :class:`PieCtrl` background image. """
+
+ return self._background
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`PieCtrl`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.RecreateCanvas()
+ self.Refresh()
+ event.Skip()
+
+
+ def RecreateCanvas(self):
+ """ Recreates the :class:`PieCtrl` container (canvas). """
+
+ self._canvasbitmap = wx.EmptyBitmap(self.GetSize().GetWidth(),
+ self.GetSize().GetHeight())
+ self._canvasDC.SelectObject(self._canvasbitmap)
+
+
+ def GetPartAngles(self):
+ """ Returns the angles associated to all segments. """
+
+ angles = []
+ total = 0.0
+
+ for ii in xrange(len(self._series)):
+ total = total + self._series[ii].GetValue()
+
+ current = 0.0
+ angles.append(current)
+
+ for ii in xrange(len(self._series)):
+
+ current = current + self._series[ii].GetValue()
+ angles.append(360.0*current/total)
+
+ return angles
+
+
+ def SetAngle(self, angle):
+ """
+ Sets the orientation angle for :class:`PieCtrl`.
+
+ :param `angle`: the orientation angle for :class:`PieCtrl`, in radians.
+ """
+
+ if angle < 0:
+ angle = 0
+ if angle > pi/2:
+ angle = pi/2
+
+ self._angle = angle
+ self.Refresh()
+
+
+ def GetAngle(self):
+ """ Returns the orientation angle for :class:`PieCtrl`, in radians. """
+
+ return self._angle
+
+
+ def SetRotationAngle(self, angle):
+ """
+ Sets the angle at which the first sector starts.
+
+ :param `angle`: the first sector angle, in radians.
+ """
+
+ if angle < 0:
+ angle = 0
+ if angle > 2*pi:
+ angle = 2*pi
+
+ self._rotationangle = angle
+ self.Refresh()
+
+
+ def GetRotationAngle(self):
+ """ Returns the angle at which the first sector starts, in radians. """
+
+ return self._rotationangle
+
+
+ def SetShowEdges(self, value=True):
+ """
+ Sets whether the :class:`PieCtrl` edges are visible or not.
+
+ :param `value`: ``True`` to show the edges, ``False`` to hide them.
+ """
+
+ self._showedges = value
+ self.Refresh()
+
+
+ def GetShowEdges(self):
+ """ Returns whether the :class:`PieCtrl` edges are visible or not. """
+
+ return self._showedges
+
+
+ def SetBackColour(self, colour):
+ """
+ Sets the :class:`PieCtrl` background colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._backcolour = colour
+ self.Refresh()
+
+
+ def GetBackColour(self):
+ """ Returns the :class:`PieCtrl` background colour. """
+
+ return self._backcolour
+
+
+ def SetHeight(self, value):
+ """
+ Sets the height (in pixels) of the :class:`PieCtrl`.
+
+ :param `value`: the new height of the widget, in pixels.
+ """
+
+ self._height = value
+
+
+ def GetHeight(self):
+ """ Returns the height (in pixels) of the :class:`PieCtrl`. """
+
+ return self._height
+
+
+ def GetLegend(self):
+ """ Returns the :class:`PieCtrl` legend. """
+
+ return self._legend
+
+
+ def DrawParts(self, dc, cx, cy, w, h):
+ """
+ Draws the :class:`PieCtrl` external edges.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `cx`: the part `x` coordinate;
+ :param `cy`: the part `y` coordinate;
+ :param `w`: the control's width;
+ :param `h`: the control's height.
+ """
+
+ angles = self.GetPartAngles()
+ oldpen = dc.GetPen()
+
+ if self._showedges:
+ dc.SetPen(wx.BLACK_PEN)
+
+ for ii in xrange(len(angles)):
+
+ if ii > 0:
+
+ if not self._showedges:
+ dc.SetPen(wx.Pen(self._series[ii-1].GetColour()))
+
+ dc.SetBrush(wx.Brush(self._series[ii-1].GetColour()))
+
+ if angles[ii-1] != angles[ii]:
+ dc.DrawEllipticArc(0, int((1-sin(self._angle))*(h/2)+cy), w,
+ int(h*sin(self._angle)),
+ angles[ii-1]+self._rotationangle/pi*180,
+ angles[ii]+self._rotationangle/pi*180)
+
+
+ if len(self._series) == 1:
+
+ dc.SetBrush(wx.Brush(self._series[0].GetColour()))
+ dc.DrawEllipticArc(0, int((1-sin(self._angle))*(h/2)+cy), w,
+ int(h*sin(self._angle)), 0, 360)
+
+ dc.SetPen(oldpen)
+
+
+ def Draw(self, pdc):
+ """
+ Draws all the sectors of :class:`PieCtrl`.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ w, h = self.GetSize()
+
+ self._canvasDC.BeginDrawing()
+ self._canvasDC.SetBackground(wx.WHITE_BRUSH)
+ self._canvasDC.Clear()
+
+ if self._background != wx.NullBitmap:
+
+ for ii in xrange(0, w, self._background.GetWidth()):
+
+ for jj in xrange(0, h, self._background.GetHeight()):
+
+ self._canvasDC.DrawBitmap(self._background, ii, jj)
+
+ else:
+
+ self._canvasDC.SetBackground(wx.Brush(self._backcolour))
+ self._canvasDC.Clear()
+
+ if len(self._series) > 0:
+
+ if self._angle <= pi/2:
+ self.DrawParts(self._canvasDC, 0, int(self._height*cos(self._angle)), w, h)
+ else:
+ self.DrawParts(self._canvasDC, 0, 0, w, h)
+
+ points = [[0, 0]]*4
+ triangle = [[0, 0]]*3
+ self._canvasDC.SetPen(wx.Pen(wx.BLACK))
+ angles = self.GetPartAngles()
+ angleindex = 0
+ self._canvasDC.SetBrush(wx.Brush(wx.Colour(self._series[angleindex].GetColour().Red(),
+ self._series[angleindex].GetColour().Green(),
+ self._series[angleindex].GetColour().Blue())))
+ changeangle = False
+ x = 0.0
+
+ while x <= 2*pi:
+
+ changeangle = False
+
+ if angleindex < len(angles):
+
+ if x/pi*180.0 >= angles[angleindex+1]:
+
+ changeangle = True
+ x = angles[angleindex+1]*pi/180.0
+
+ points[0] = points[1]
+ px = int(w/2*(1+cos(x+self._rotationangle)))
+ py = int(h/2-sin(self._angle)*h/2*sin(x+self._rotationangle)-1)
+ points[1] = [px, py]
+ triangle[0] = [w / 2, h / 2]
+ triangle[1] = points[0]
+ triangle[2] = points[1]
+
+ if x > 0:
+
+ self._canvasDC.SetBrush(wx.Brush(self._series[angleindex].GetColour()))
+ oldPen = self._canvasDC.GetPen()
+ self._canvasDC.SetPen(wx.Pen(self._series[angleindex].GetColour()))
+ self._canvasDC.DrawPolygon([wx.Point(pts[0], pts[1]) for pts in triangle])
+ self._canvasDC.SetPen(oldPen)
+
+ if changeangle:
+
+ angleindex = angleindex + 1
+
+ x = x + 0.05
+
+ x = 2*pi
+ points[0] = points[1]
+ px = int(w/2 * (1+cos(x+self._rotationangle)))
+ py = int(h/2-sin(self._angle)*h/2*sin(x+self._rotationangle)-1)
+ points[1] = [px, py]
+ triangle[0] = [w / 2, h / 2]
+ triangle[1] = points[0]
+ triangle[2] = points[1]
+
+ self._canvasDC.SetBrush(wx.Brush(self._series[angleindex].GetColour()))
+ oldPen = self._canvasDC.GetPen()
+ self._canvasDC.SetPen(wx.Pen(self._series[angleindex].GetColour()))
+ self._canvasDC.DrawPolygon([wx.Point(pts[0], pts[1]) for pts in triangle])
+
+ self._canvasDC.SetPen(oldPen)
+ angleindex = 0
+
+ x = 0.0
+
+ while x <= 2*pi:
+
+ changeangle = False
+ if angleindex < len(angles):
+
+ if x/pi*180 >= angles[angleindex+1]:
+
+ changeangle = True
+ x = angles[angleindex+1]*pi/180
+
+ points[0] = points[1]
+ points[3] = points[2]
+ px = int(w/2 * (1+cos(x+self._rotationangle)))
+ py = int(h/2-sin(self._angle)*h/2*sin(x+self._rotationangle)-1)
+ points[1] = [px, py]
+ points[2] = [px, int(py+self._height*cos(self._angle))]
+
+ if w > 0:
+
+ curColour = wx.Colour(self._series[angleindex].GetColour().Red()*(1.0-float(px)/w),
+ self._series[angleindex].GetColour().Green()*(1.0-float(px)/w),
+ self._series[angleindex].GetColour().Blue()*(1.0-float(px)/w))
+
+ if not self._showedges:
+ self._canvasDC.SetPen(wx.Pen(curColour))
+
+ self._canvasDC.SetBrush(wx.Brush(curColour))
+
+ if sin(x+self._rotationangle) < 0 and sin(x-0.05+self._rotationangle) <= 0 and x > 0:
+ self._canvasDC.DrawPolygon([wx.Point(pts[0], pts[1]) for pts in points])
+
+ if changeangle:
+
+ angleindex = angleindex + 1
+
+ x = x + 0.05
+
+ x = 2*pi
+ points[0] = points[1]
+ points[3] = points[2]
+ px = int(w/2 * (1+cos(x+self._rotationangle)))
+ py = int(h/2-sin(self._angle)*h/2*sin(x+self._rotationangle)-1)
+ points[1] = [px, py]
+ points[2] = [px, int(py+self._height*cos(self._angle))]
+
+ if w > 0:
+
+ curColour = wx.Colour(self._series[angleindex].GetColour().Red()*(1.0-float(px)/w),
+ self._series[angleindex].GetColour().Green()*(1.0-float(px)/w),
+ self._series[angleindex].GetColour().Blue()*(1.0-float(px)/w))
+
+ if not self._showedges:
+ self._canvasDC.SetPen(wx.Pen(curColour))
+
+ self._canvasDC.SetBrush(wx.Brush(curColour))
+
+ if sin(x+self._rotationangle) < 0 and sin(x-0.05+self._rotationangle) <= 0:
+ self._canvasDC.DrawPolygon([wx.Point(pts[0], pts[1]) for pts in points])
+
+ if self._angle <= pi/2:
+ self.DrawParts(self._canvasDC, 0, 0, w, h)
+ else:
+ self.DrawParts(self._canvasDC, 0, int(self._height*cos(self._angle)), w, h)
+
+ self._canvasDC.EndDrawing()
+
+ pdc.Blit(0, 0, w, h, self._canvasDC, 0, 0)
+ self._legend.RecreateBackground(self._canvasDC)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`PieCtrl`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ pdc = wx.PaintDC(self)
+ self.Draw(pdc)
+
+
+#----------------------------------------------------------------------
+# Class ProgressPie
+# This Is The Main ProgressPie Implementation. Is Is A Subclassing Of
+# PieCtrl, With 2 Sectors.
+#----------------------------------------------------------------------
+
+class ProgressPie(PieCtrl):
+ """
+ :class:`ProgressPie` tries to emulate the behavior of :class:`ProgressDialog`, but
+ using a pie chart instead of a gauge.
+ """
+
+ def __init__(self, parent, maxvalue, value, id=wx.ID_ANY,
+ pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`PieCtrl` parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style (unused);
+ :param `name`: the window name.
+ """
+
+ PieCtrl.__init__(self, parent, id, pos, size, style)
+
+ self._maxvalue = maxvalue
+ self._value = value
+ self.GetLegend().Hide()
+
+ self._filledcolour = wx.Colour(0, 0, 127)
+ self._unfilledcolour = wx.WHITE
+ part = PiePart()
+ part.SetColour(self._filledcolour)
+ a = min(float(value), maxvalue)
+ part.SetValue(max(a, 0.0))
+ self._series.append(part)
+ part = PiePart()
+ part.SetColour(self._unfilledcolour)
+ part.SetValue(max(0.0, maxvalue-part.GetValue()))
+ self._series.append(part)
+
+
+ def SetValue(self, value):
+ """
+ Sets the :class:`ProgressPie` value.
+
+ :param `value`: a floating point number representing the new value.
+ """
+
+ self._value = min(value, self._maxvalue)
+ self._series[0].SetValue(max(self._value, 0.0))
+ self._series[1].SetValue(max(self._maxvalue-self._value, 0.0))
+ self.Refresh()
+
+
+ def GetValue(self):
+ """ Returns the :class:`ProgressPie` value. """
+
+ return self._value
+
+
+ def SetMaxValue(self, value):
+ """
+ Sets the :class:`ProgressPie` maximum value.
+
+ :param `value`: a floating point number representing the maximum value.
+ """
+
+ self._maxvalue = value
+ self._value = min(self._value, self._maxvalue)
+ self._series[0].SetValue(max(self._value, 0.0))
+ self._series[1].SetValue(max(self._maxvalue-self._value, 0.0))
+ self.Refresh()
+
+
+ def GetMaxValue(self):
+ """ Returns the :class:`ProgressPie` maximum value. """
+
+ return self._maxvalue
+
+
+ def SetFilledColour(self, colour):
+ """
+ Sets the colour that progressively fills the :class:`ProgressPie` .
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._filledcolour = colour
+ self._series[0].SetColour(self._filledcolour)
+ self.Refresh()
+
+
+ def SetUnfilledColour(self, colour):
+ """
+ Sets the colour that is filled.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._unfilledcolour= colour
+ self._series[1].SetColour(self._unfilledcolour)
+ self.Refresh()
+
+
+ def GetFilledColour(self):
+ """ Returns the colour that progressively fills the :class:`ProgressPie`. """
+
+ return self._filledcolour
+
+
+ def GetUnfilledColour(self):
+ """ Returns the colour that is filled. """
+
+ return self._unfilledcolour
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pybusyinfo.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pybusyinfo.py
new file mode 100644
index 0000000..fd7a687
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pybusyinfo.py
@@ -0,0 +1,331 @@
+"""
+:class:`PyBusyInfo` constructs a busy info window and displays a message in it.
+
+
+Description
+===========
+
+:class:`PyBusyInfo` constructs a busy info window and displays a message in it.
+
+This class makes it easy to tell your user that the program is temporarily busy.
+Just create a :class:`PyBusyInfo` object, and within the current scope, a message window
+will be shown.
+
+For example::
+
+ busy = PyBusyInfo("Please wait, working...")
+
+ for i in xrange(10000):
+ DoACalculation()
+
+ del busy
+
+
+It works by creating a window in the constructor, and deleting it in the destructor.
+You may also want to call :func:`Yield` () to refresh the window periodically (in case
+it had been obscured by other windows, for example).
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.pybusyinfo as PBI
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "PyBusyInfo Demo")
+
+ panel = wx.Panel(self)
+
+ b = wx.Button(panel, -1, "Test PyBusyInfo ", (50,50))
+ self.Bind(wx.EVT_BUTTON, self.OnButton, b)
+
+
+ def OnButton(self, event):
+
+ message = "Please wait 5 seconds, working..."
+ busy = PBI.PyBusyInfo(message, parent=self, title="Really Busy")
+
+ wx.Yield()
+
+ for indx in xrange(5):
+ wx.MilliSleep(1000)
+
+ del busy
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`PyBusyInfo` has been tested on the following platforms:
+ * Windows (Windows XP).
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`PyBusyInfo` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 20 Mar 2012, 21.00 GMT
+
+Version 0.2
+
+"""
+
+# Version Info
+__version__ = "0.2"
+
+import wx
+
+_ = wx.GetTranslation
+
+
+class PyInfoFrame(wx.Frame):
+ """ Base class for :class:`PyBusyInfo`. """
+
+ def __init__(self, parent, message, title, icon):
+ """
+ Default class constructor.
+
+ :param `parent`: the frame parent;
+ :param `message`: the message to display in the :class:`PyBusyInfo`;
+ :param `title`: the main :class:`PyBusyInfo` title;
+ :param `icon`: an icon to draw as the frame icon, an instance of :class:`Bitmap`.
+ """
+
+ wx.Frame.__init__(self, parent, wx.ID_ANY, title, wx.DefaultPosition,
+ wx.DefaultSize, wx.NO_BORDER|wx.FRAME_TOOL_WINDOW|wx.FRAME_SHAPED|wx.STAY_ON_TOP)
+
+ panel = wx.Panel(self)
+ panel.SetCursor(wx.HOURGLASS_CURSOR)
+
+ self._message = message
+ self._title = title
+ self._icon = icon
+
+ dc = wx.ClientDC(self)
+ textWidth, textHeight, dummy = dc.GetMultiLineTextExtent(self._message)
+ sizeText = wx.Size(textWidth, textHeight)
+
+ self.SetClientSize((max(sizeText.x, 340) + 60, max(sizeText.y, 40) + 60))
+ # need to size the panel correctly first so that text.Centre() works
+ panel.SetSize(self.GetClientSize())
+
+ # Bind the events to draw ourselves
+ panel.Bind(wx.EVT_PAINT, self.OnPaint)
+ panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase)
+
+ self.Centre(wx.BOTH)
+
+ # Create a non-rectangular region to set the frame shape
+ size = self.GetSize()
+ bmp = wx.EmptyBitmap(size.x, size.y)
+ dc = wx.BufferedDC(None, bmp)
+ dc.SetBackground(wx.Brush(wx.Colour(0, 0, 0), wx.SOLID))
+ dc.Clear()
+ dc.SetPen(wx.Pen(wx.Colour(0, 0, 0), 1))
+ dc.DrawRoundedRectangle(0, 0, size.x, size.y, 12)
+ r = wx.RegionFromBitmapColour(bmp, wx.Colour(0, 0, 0))
+ # Store the non-rectangular region
+ self.reg = r
+
+ if wx.Platform == "__WXGTK__":
+ self.Bind(wx.EVT_WINDOW_CREATE, self.SetBusyShape)
+ else:
+ self.SetBusyShape()
+
+ # Add a custom bitmap at the top (if any)
+
+
+ def SetBusyShape(self, event=None):
+ """
+ Sets :class:`PyInfoFrame` shape using the region created from the bitmap.
+
+ :param `event`: a :class:`WindowCreateEvent` event (GTK only, as GTK supports setting
+ the window shape only during window creation).
+ """
+
+ self.SetShape(self.reg)
+ if event:
+ # GTK only
+ event.Skip()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`PyInfoFrame`.
+
+ :param `event`: a :class:`PaintEvent` to be processed.
+ """
+
+ panel = event.GetEventObject()
+
+ dc = wx.BufferedPaintDC(panel)
+ dc.Clear()
+
+ # Fill the background with a gradient shading
+ startColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ endColour = wx.WHITE
+
+ rect = panel.GetRect()
+ dc.GradientFillLinear(rect, startColour, endColour, wx.SOUTH)
+
+ # Draw the label
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ dc.SetFont(font)
+
+ # Draw the message
+ rect2 = wx.Rect(*rect)
+ rect2.height += 20
+ dc.DrawLabel(self._message, rect2, alignment=wx.ALIGN_CENTER|wx.ALIGN_CENTER)
+
+ # Draw the top title
+ font.SetWeight(wx.BOLD)
+ dc.SetFont(font)
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_CAPTIONTEXT)))
+ dc.SetTextForeground(wx.SystemSettings_GetColour(wx.SYS_COLOUR_CAPTIONTEXT))
+
+ if self._icon.IsOk():
+ iconWidth, iconHeight = self._icon.GetWidth(), self._icon.GetHeight()
+ dummy, textHeight = dc.GetTextExtent(self._title)
+ textXPos, textYPos = iconWidth + 10, (iconHeight-textHeight)/2
+ dc.DrawBitmap(self._icon, 5, 5, True)
+ else:
+ textXPos, textYPos = 5, 0
+
+ dc.DrawText(self._title, textXPos, textYPos+5)
+ dc.DrawLine(5, 25, rect.width-5, 25)
+
+ size = self.GetSize()
+ dc.SetPen(wx.Pen(startColour, 1))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRoundedRectangle(0, 0, size.x, size.y-1, 12)
+
+
+ def OnErase(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`PyInfoFrame`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ # This is empty on purpose, to avoid flickering
+ pass
+
+
+# -------------------------------------------------------------------- #
+# The actual PyBusyInfo implementation
+# -------------------------------------------------------------------- #
+
+class PyBusyInfo(object):
+ """
+ Constructs a busy info window as child of parent and displays a message in it.
+ """
+
+ def __init__(self, message, parent=None, title=_("Busy"), icon=wx.NullBitmap):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`PyBusyInfo` parent;
+ :param `message`: the message to display in the :class:`PyBusyInfo`;
+ :param `title`: the main :class:`PyBusyInfo` title;
+ :param `icon`: an icon to draw as the frame icon, an instance of :class:`Bitmap`.
+
+ :note: If `parent` is not ``None`` you must ensure that it is not closed
+ while the busy info is shown.
+ """
+
+ self._infoFrame = PyInfoFrame(parent, message, title, icon)
+
+ if parent and parent.HasFlag(wx.STAY_ON_TOP):
+ # we must have this flag to be in front of our parent if it has it
+ self._infoFrame.SetWindowStyleFlag(wx.STAY_ON_TOP)
+
+ # Added for the screenshot-taking tool
+ self.Show()
+
+
+ def __del__(self):
+ """ Overloaded method, for compatibility with wxWidgets. """
+
+ self._infoFrame.Show(False)
+ self._infoFrame.Destroy()
+
+
+ def Show(self, show=True):
+ """
+ Shows or hides the window.
+
+ You may need to call `Raise` for a top level window if you want to bring it to
+ top, although this is not needed if :meth:`PyBusyInfo.Show` is called immediately after the frame creation.
+
+ :param bool `show`: ``True`` to show the :class:`PyBusyInfo` frame, ``False`` to hide it.
+
+ :return: ``True`` if the window has been shown or hidden or ``False`` if nothing was done
+ because it already was in the requested state.
+
+ .. note::
+
+ Notice that the default state of newly created top level windows is hidden (to allow
+ you to create their contents without flicker) unlike for all the other, not derived from
+ :class:`TopLevelWindow`, windows that are by default created in the shown state.
+
+
+ .. versionadded:: 0.9.5
+ """
+
+ retVal = self._infoFrame.Show(show)
+
+ if show:
+ self._infoFrame.Refresh()
+ self._infoFrame.Update()
+
+ return retVal
+
+
+ def Update(self):
+ """
+ Calling this method immediately repaints the invalidated area of the window and all of its
+ children recursively (this normally only happens when the flow of control returns to the
+ event loop).
+
+ :note: Notice that this function doesn't invalidate any area of the window so nothing happens
+ if nothing has been invalidated (i.e. marked as requiring a redraw). Use `Refresh` first if
+ you want to immediately redraw the window unconditionally.
+
+ .. versionadded:: 0.9.5
+ """
+
+ self._infoFrame.Update()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pycollapsiblepane.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pycollapsiblepane.py
new file mode 100644
index 0000000..59c114f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pycollapsiblepane.py
@@ -0,0 +1,861 @@
+# --------------------------------------------------------------------------------- #
+# PYCOLLAPSIBLEPANE wxPython IMPLEMENTATION
+# Generic Implementation Based On wx.CollapsiblePane.
+#
+# Andrea Gavana, @ 09 Aug 2007
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@maerskoil.com
+# andrea.gavana@gmail.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`PyCollapsiblePane` is a container with an embedded button-like control which
+can be used by the user to collapse or expand the pane's contents.
+
+
+Description
+===========
+
+A collapsible pane is a container with an embedded button-like control which
+can be used by the user to collapse or expand the pane's contents.
+Once constructed you should use the meth:~PyCollapsiblePane.GetPane` function to access the pane and
+add your controls inside it (i.e. use the window returned from meth:~PyCollapsiblePane.GetPane` as the
+parent for the controls which must go in the pane, **not** the :class:`PyCollapsiblePane`
+itself!).
+
+:note: Note that because of its nature of control which can dynamically (and drastically)
+ change its size at run-time under user-input, when putting :class:`PyCollapsiblePane`
+ inside a :class:`Sizer` you should be careful to add it with a proportion value of zero;
+ this is because otherwise all other windows with non-null proportion values would
+ automatically get resized each time the user expands or collapse the pane window
+ resulting usually in a weird, flickering effect.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.pycollapsiblepane as PCP
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "PyCollapsiblePane Demo")
+
+ panel = wx.Panel(self)
+
+ title = wx.StaticText(panel, label="PyCollapsiblePane")
+ title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
+ title.SetForegroundColour("blue")
+
+ self.cp = cp = PCP.PyCollapsiblePane(panel, label=label1,
+ style=wx.CP_DEFAULT_STYLE|wx.CP_NO_TLW_RESIZE)
+
+ self.MakePaneContent(cp.GetPane())
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(title, 0, wx.ALL, 25)
+ sizer.Add(cp, 0, wx.RIGHT|wx.LEFT|wx.EXPAND, 25)
+
+ panel.SetSizer(sizer)
+ sizer.Layout()
+
+
+ def MakePaneContent(self, pane):
+ ''' Just makes a few controls to put on `PyCollapsiblePane`. '''
+
+ nameLbl = wx.StaticText(pane, -1, "Name:")
+ name = wx.TextCtrl(pane, -1, "");
+
+ addrLbl = wx.StaticText(pane, -1, "Address:")
+ addr1 = wx.TextCtrl(pane, -1, "");
+ addr2 = wx.TextCtrl(pane, -1, "");
+
+ cstLbl = wx.StaticText(pane, -1, "City, State, Zip:")
+ city = wx.TextCtrl(pane, -1, "", size=(150,-1));
+ state = wx.TextCtrl(pane, -1, "", size=(50,-1));
+ zip = wx.TextCtrl(pane, -1, "", size=(70,-1));
+
+ addrSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
+ addrSizer.AddGrowableCol(1)
+ addrSizer.Add(nameLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ addrSizer.Add(name, 0, wx.EXPAND)
+ addrSizer.Add(addrLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ addrSizer.Add(addr1, 0, wx.EXPAND)
+ addrSizer.Add((5,5))
+ addrSizer.Add(addr2, 0, wx.EXPAND)
+
+ addrSizer.Add(cstLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+
+ cstSizer = wx.BoxSizer(wx.HORIZONTAL)
+ cstSizer.Add(city, 1)
+ cstSizer.Add(state, 0, wx.LEFT|wx.RIGHT, 5)
+ cstSizer.Add(zip)
+ addrSizer.Add(cstSizer, 0, wx.EXPAND)
+
+ border = wx.BoxSizer()
+ border.Add(addrSizer, 1, wx.EXPAND|wx.ALL, 5)
+ pane.SetSizer(border)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+==================== =========== ==================================================
+Window Styles Hex Value Description
+==================== =========== ==================================================
+``CP_NO_TLW_RESIZE`` 0x2 By default :class:`PyCollapsiblePane` resizes the top level window containing it when its own size changes. This allows to easily implement dialogs containing an optionally shown part, for example, and so is the default behaviour but can be inconvenient in some specific cases -- use this flag to disable this automatic parent resizing then.
+``CP_GTK_EXPANDER`` 0x4 Uses a GTK expander instead of a button.
+``CP_USE_STATICBOX`` 0x8 Uses a :class:`StaticBox` around :class:`PyCollapsiblePane`.
+``CP_LINE_ABOVE`` 0x10 Draws a line above :class:`PyCollapsiblePane`.
+==================== =========== ==================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+=============================== ==================================================
+Event Name Description
+=============================== ==================================================
+``EVT_COLLAPSIBLEPANE_CHANGED`` The user showed or hid the collapsible pane.
+=============================== ==================================================
+
+
+License And Version
+===================
+
+:class:`PyCollapsiblePane` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.4
+
+"""
+
+import wx
+
+CP_GTK_EXPANDER = 4
+""" Uses a GTK expander instead of a button. """
+CP_USE_STATICBOX = 8
+""" Uses a :class:`StaticBox` around :class:`PyCollapsiblePane`. """
+CP_LINE_ABOVE = 16
+""" Draws a line above :class:`PyCollapsiblePane`. """
+CP_DEFAULT_STYLE = wx.CP_DEFAULT_STYLE
+""" The default style. It includes ``wx.TAB_TRAVERSAL`` and ``wx.BORDER_NONE``. """
+CP_NO_TLW_RESIZE = wx.CP_NO_TLW_RESIZE
+""" By default :class:`PyCollapsiblePane` resizes the top level window containing it when its own size changes. This allows to easily implement dialogs containing an optionally shown part, for example, and so is the default behaviour but can be inconvenient in some specific cases -- use this flag to disable this automatic parent resizing then. """
+
+# inject into the wx namespace with the other CP_* constants
+wx.CP_GTK_EXPANDER = CP_GTK_EXPANDER
+wx.CP_USE_STATICBOX = CP_USE_STATICBOX
+wx.CP_LINE_ABOVE = CP_LINE_ABOVE
+
+# PyCollapsiblePane events
+EVT_COLLAPSIBLEPANE_CHANGED = wx.EVT_COLLAPSIBLEPANE_CHANGED
+""" The user showed or hid the collapsible pane. """
+
+#-----------------------------------------------------------------------------
+# 2.9 deprecates SetSpacer, so we'll use AssignSpacer and monkey-patch 2.8 so
+# it works there too
+
+if wx.VERSION < (2, 9):
+ wx.SizerItem.AssignSpacer = wx.SizerItem.SetSpacer
+
+#-----------------------------------------------------------------------------
+# GTKExpander widget
+#-----------------------------------------------------------------------------
+
+class GTKExpander(wx.PyControl):
+ """
+ A :class:`GTKExpander` allows the user to hide or show its child by clicking on an expander
+ triangle.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, label="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.NO_BORDER):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`GTKExpander` parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `label`: the expander text label;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the expander style.
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style)
+ self.SetLabel(label)
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+ self._parent = parent
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def OnDrawGTKExpander(self, dc):
+ """
+ Draws the :class:`GTKExpander` triangle.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ size = self.GetSize()
+ label = self._parent.GetBtnLabel()
+ triangleWidth, triangleHeight = self._parent.GetExpanderDimensions()
+ textWidth, textHeight, descent, externalLeading = dc.GetFullTextExtent(label, self.GetFont())
+
+ dc.SetBrush(wx.BLACK_BRUSH)
+ dc.SetPen(wx.BLACK_PEN)
+
+ if self._parent.IsCollapsed():
+ startX, startY = triangleWidth/2, size.y - triangleHeight - 1 - descent
+ pt1 = wx.Point(startX, startY)
+ pt2 = wx.Point(startX, size.y - 1 - descent)
+ pt3 = wx.Point(startX+triangleWidth, size.y-triangleHeight/2 - 1 - descent)
+ else:
+
+ startX, startY = 0, size.y - triangleWidth - descent - 1
+ pt1 = wx.Point(startX, startY)
+ pt2 = wx.Point(startX+triangleHeight, startY)
+ pt3 = wx.Point(startX+triangleHeight/2, size.y - descent - 1)
+
+ dc.DrawPolygon([pt1, pt2, pt3])
+
+
+ def OnDrawGTKText(self, dc):
+ """
+ Draws the :class:`GTKExpander` text label.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ size = self.GetSize()
+ label = self._parent.GetBtnLabel()
+ triangleWidth, triangleHeight = self._parent.GetExpanderDimensions()
+ textWidth, textHeight, descent, externalLeading = dc.GetFullTextExtent(label, self.GetFont())
+ dc.SetFont(self.GetFont())
+
+ startX, startY = 2*triangleHeight+1, size.y - textHeight
+ dc.DrawText(label, startX, startY)
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ triangleWidth, triangleHeight = self._parent.GetExpanderDimensions()
+ label = self._parent.GetBtnLabel()
+ dc = wx.ClientDC(self)
+ textWidth, textHeight, descent, externalLeading = dc.GetFullTextExtent(label, self.GetFont())
+
+ maxHeight = max(textHeight+descent, triangleHeight)
+ maxWidth = 2*triangleHeight+1 + textWidth
+
+ return wx.Size(maxWidth, maxHeight)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`GTKExpander`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Refresh()
+
+
+
+#-----------------------------------------------------------------------------
+# PyCollapsiblePane
+#-----------------------------------------------------------------------------
+
+class PyCollapsiblePane(wx.PyPanel):
+ """
+ :class:`PyCollapsiblePane` is a container with an embedded button-like control which
+ can be used by the user to collapse or expand the pane's contents.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, label="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, agwStyle=wx.CP_DEFAULT_STYLE,
+ validator=wx.DefaultValidator, name="PyCollapsiblePane"):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`PyCollapsiblePane` parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `label`: The initial label shown in the button which allows the
+ user to expand or collapse the pane window.
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`PyPanel` window style;
+ :param `agwStyle`: the AGW-specifi window style. This can be a combination of the
+ following bits:
+
+ ==================== =========== ==================================================
+ Window Styles Hex Value Description
+ ==================== =========== ==================================================
+ ``CP_NO_TLW_RESIZE`` 0x2 By default :class:`PyCollapsiblePane` resizes the top level window containing it when its own size changes. This allows to easily implement dialogs containing an optionally shown part, for example, and so is the default behaviour but can be inconvenient in some specific cases -- use this flag to disable this automatic parent resizing then.
+ ``CP_GTK_EXPANDER`` 0x4 Uses a GTK expander instead of a button.
+ ``CP_USE_STATICBOX`` 0x8 Uses a :class:`StaticBox` around :class:`PyCollapsiblePane`.
+ ``CP_LINE_ABOVE`` 0x10 Draws a line above :class:`PyCollapsiblePane`.
+ ==================== =========== ==================================================
+
+ :param `validator`: the validator associated to the :class:`PyCollapsiblePane`;
+ :param `name`: the widget name.
+
+ """
+
+ wx.PyPanel.__init__(self, parent, id, pos, size, style, name)
+
+ self._pButton = self._pStaticLine = self._pPane = self._sz = None
+ self._strLabel = label
+ self._bCollapsed = True
+ self._agwStyle = agwStyle
+
+ self._pPane = wx.Panel(self, style=wx.TAB_TRAVERSAL|wx.NO_BORDER)
+ self._pPane.Hide()
+
+ if self.HasAGWFlag(CP_USE_STATICBOX):
+ # Use a StaticBox instead of a StaticLine, and the button's
+ # position will be handled separately so don't put it in the sizer
+ self._pStaticBox = wx.StaticBox(self)
+ self.SetButton(wx.Button(self, wx.ID_ANY, self.GetLabel(), style=wx.BU_EXACTFIT))
+ self._sz = wx.BoxSizer(wx.VERTICAL)
+ self._sz.Add((1,1)) # spacer, size will be reset later
+ self._contentSizer = wx.StaticBoxSizer(self._pStaticBox, wx.VERTICAL)
+ self._contentSizer.Add((1,1)) # spacer, size will be reset later
+ self._contentSizer.Add(self._pPane, 1, wx.EXPAND)
+ self._sz.Add(self._contentSizer, 1, wx.EXPAND)
+
+ if self.HasAGWFlag(CP_USE_STATICBOX) and 'wxMSW' in wx.PlatformInfo:
+ # This hack is needed on Windows because wxMSW clears the
+ # CLIP_SIBLINGS style from all sibling controls that overlap the
+ # static box, so the box ends up overdrawing the button since we
+ # have the button overlapping the box. This hack will ensure that
+ # the button is refreshed after every time that the box is drawn.
+ # This adds a little flicker but it is not too bad compared to
+ # others.
+ def paint(evt):
+ def updateBtn():
+ if self and self._pButton:
+ self._pButton.Refresh()
+ self._pButton.Update()
+ wx.CallAfter(updateBtn)
+ evt.Skip()
+ self._pStaticBox.Bind(wx.EVT_PAINT, paint)
+
+ elif self.HasAGWFlag(CP_GTK_EXPANDER):
+ self._sz = wx.BoxSizer(wx.HORIZONTAL)
+ self.SetExpanderDimensions(3, 6)
+ self.SetButton(GTKExpander(self, wx.ID_ANY, self.GetLabel()))
+ self._sz.Add(self._pButton, 0, wx.LEFT|wx.TOP|wx.BOTTOM, self.GetBorder())
+
+ self._pButton.Bind(wx.EVT_PAINT, self.OnDrawGTKStyle)
+ self._pButton.Bind(wx.EVT_LEFT_DOWN, self.OnButton)
+ if wx.Platform == "__WXMSW__":
+ self._pButton.Bind(wx.EVT_LEFT_DCLICK, self.OnButton)
+
+ else:
+ # create children and lay them out using a wx.BoxSizer
+ # (so that we automatically get RTL features)
+ self.SetButton(wx.Button(self, wx.ID_ANY, self.GetLabel(), style=wx.BU_EXACTFIT))
+ self._pStaticLine = wx.StaticLine(self, wx.ID_ANY)
+
+ if self.HasAGWFlag(CP_LINE_ABOVE):
+ # put the static line above the button
+ self._sz = wx.BoxSizer(wx.VERTICAL)
+ self._sz.Add(self._pStaticLine, 0, wx.ALL|wx.GROW, self.GetBorder())
+ self._sz.Add(self._pButton, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM, self.GetBorder())
+ else:
+ # arrange the static line and the button horizontally
+ self._sz = wx.BoxSizer(wx.HORIZONTAL)
+ self._sz.Add(self._pButton, 0, wx.LEFT|wx.TOP|wx.BOTTOM, self.GetBorder())
+ self._sz.Add(self._pStaticLine, 1, wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT, self.GetBorder())
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the :class:`PyCollapsiblePane` window style flags.
+
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ ==================== =========== ==================================================
+ Window Styles Hex Value Description
+ ==================== =========== ==================================================
+ ``CP_NO_TLW_RESIZE`` 0x2 By default :class:`PyCollapsiblePane` resizes the top level window containing it when its own size changes. This allows to easily implement dialogs containing an optionally shown part, for example, and so is the default behaviour but can be inconvenient in some specific cases -- use this flag to disable this automatic parent resizing then.
+ ``CP_GTK_EXPANDER`` 0x4 Uses a GTK expander instead of a button.
+ ``CP_USE_STATICBOX`` 0x8 Uses a :class:`StaticBox` around :class:`PyCollapsiblePane`.
+ ``CP_LINE_ABOVE`` 0x10 Draws a line above :class:`PyCollapsiblePane`.
+ ==================== =========== ==================================================
+
+ """
+
+ self._agwStyle = agwStyle
+ self.Layout()
+ self.Refresh()
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`PyCollapsiblePane` window style.
+
+ :see: :meth:`~PyCollapsiblePane.SetAGWWindowStyleFlag` for a list of possible window style flags.
+ """
+
+ return self._agwStyle
+
+
+ def HasAGWFlag(self, flag):
+ """
+ Returns whether a flag is present in the :class:`PyCollapsiblePane` style.
+
+ :param `flag`: one of the possible :class:`PyCollapsiblePane` window styles.
+
+ :see: :meth:`~PyCollapsiblePane.SetAGWWindowStyleFlag` for a list of possible window style flags.
+ """
+
+ agwStyle = self.GetAGWWindowStyleFlag()
+ res = (agwStyle & flag and [True] or [False])[0]
+ return res
+
+
+ def GetBtnLabel(self):
+ """ Returns the button label. """
+
+ if self.GetAGWWindowStyleFlag() & CP_GTK_EXPANDER:
+ return self.GetLabel()
+
+ return self.GetLabel() + (self.IsCollapsed() and [" >>"] or [" <<"])[0]
+
+
+ def OnStateChange(self, sz):
+ """
+ Handles the status changes (collapsing/expanding).
+
+ :param `sz`: an instance of :class:`Size`.
+ """
+
+ self.SetSize(sz)
+
+ if self.HasAGWFlag(wx.CP_NO_TLW_RESIZE):
+ # the user asked to explicitely handle the resizing itself...
+ return
+
+ # NB: the following block of code has been accurately designed to
+ # as much flicker-free as possible be careful when modifying it!
+
+ top = wx.GetTopLevelParent(self)
+ if top:
+ # NB: don't Layout() the 'top' window as its size has not been correctly
+ # updated yet and we don't want to do an initial Layout() with the old
+ # size immediately followed by a SetClientSize/Fit call for the new
+ # size that would provoke flickering!
+
+ if top.GetSizer():
+ if (wx.Platform == "__WXGTK__" and self.IsCollapsed()) or wx.Platform != "__WXGTK__":
+ # FIXME: the SetSizeHints() call would be required also for GTK+ for
+ # the expanded.collapsed transition. Unfortunately if we
+ # enable this line, then the GTK+ top window won't always be
+ # resized by the SetClientSize() call below! As a side effect
+ # of this dirty fix, the minimal size for the pane window is
+ # not set in GTK+ and the user can hide it shrinking the "top"
+ # window...
+
+ top.GetSizer().SetSizeHints(top)
+
+
+ # we shouldn't attempt to resize a maximized window, whatever happens
+ if not top.IsMaximized():
+
+ if self.IsCollapsed():
+ # expanded . collapsed transition
+ if top.GetSizer():
+ # we have just set the size hints...
+ sz = top.GetSizer().CalcMin()
+
+ # use SetClientSize() and not SetSize() otherwise the size for
+ # e.g. a wxFrame with a menubar wouldn't be correctly set
+ top.SetClientSize(sz)
+
+ else:
+
+ top.Layout()
+
+ else:
+
+ # collapsed . expanded transition
+
+ # force our parent to "fit", i.e. expand so that it can honour
+ # our best size
+ top.Fit()
+
+
+ def Collapse(self, collapse=True):
+ """
+ Collapses or expands the pane window.
+
+ :param `collapse`: ``True`` to collapse the pane window, ``False`` to expand it.
+ """
+
+ # optimization
+ if self.IsCollapsed() == collapse:
+ return
+
+ self.Freeze()
+
+ # update our state
+ self._pPane.Show(not collapse)
+ self._bCollapsed = collapse
+ self.InvalidateBestSize()
+
+ self.Thaw()
+
+ # update button label
+ # NB: this must be done after updating our "state"
+ self._pButton.SetLabel(self.GetBtnLabel())
+
+ self.OnStateChange(self.GetBestSize())
+
+
+ def Expand(self):
+ """ Same as :meth:`~PyCollapsiblePane.Collapse` (False). """
+
+ self.Collapse(False)
+
+
+ def IsCollapsed(self):
+ """ Returns ``True`` if the pane window is currently hidden. """
+
+ return self._bCollapsed
+
+
+ def IsExpanded(self):
+ """ Returns ``True`` if the pane window is currently shown. """
+
+ return not self.IsCollapsed()
+
+
+ def GetPane(self):
+ """
+ Returns a reference to the pane window. Use the returned :class:`Window` as
+ the parent of widgets to make them part of the collapsible area.
+ """
+
+ return self._pPane
+
+
+ def SetLabel(self, label):
+ """
+ Sets the button label.
+
+ :param `label`: the new button label.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ self._strLabel = label
+ self._pButton.SetLabel(self.GetBtnLabel())
+ self._pButton.SetInitialSize()
+ self._pButton.Refresh()
+ self.InvalidateBestSize()
+
+ self.Layout()
+
+
+ def GetLabel(self):
+ """
+ Returns the button label.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ return self._strLabel
+
+
+ def SetButtonFont(self, font):
+ """
+ Sets the button font.
+
+ :param `font`: a valid :class:`Font` object.
+ """
+
+ self._pButton.SetFont(font)
+ self.InvalidateBestSize()
+ self.Layout()
+
+
+ def GetButtonFont(self):
+ """ Returns the button font. """
+
+ return self._pButton.GetFont()
+
+
+ def GetBorder(self):
+ """ Returns the :class:`PyCollapsiblePane` border in pixels (platform dependent). """
+
+ if wx.Platform == "__WXMAC__":
+ return 6
+ elif wx.Platform == "__WXGTK__":
+ return 3
+ elif wx.Platform == "__WXMSW__":
+ return self._pButton.ConvertDialogSizeToPixels(wx.Size(2, 0)).x
+ else:
+ return 5
+
+
+ def SetExpanderDimensions(self, width, height):
+ """
+ Sets the expander width and height.
+
+ :param `width`: an integer specifying the expander width in pixels;
+ :param `height`: an integer specifying the expander height in pixels.
+ """
+
+ self._expanderDimensions = width, height
+ self.InvalidateBestSize()
+ if self._sz:
+ self._sz.Layout()
+ if self._pButton:
+ self._pButton.Refresh()
+
+
+ def GetExpanderDimensions(self):
+ """
+ Returns the expander dimensions, a tuple of integers representing the
+ width and height of the expander, in pixels.
+ """
+
+ return self._expanderDimensions
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ if self.HasAGWFlag(CP_USE_STATICBOX):
+ # In this case the button is not in the sizer, and the static box
+ # is not shown when not expanded, so use the size of the button as
+ # our stating point. But first we'll make sure that it is it's
+ # best size.
+ sz = self._pButton.GetBestSize()
+ self._pButton.SetSize(sz)
+ bdr = self.GetBorder()
+ sz += (2*bdr, 2*bdr)
+
+ if self.IsExpanded():
+ # Reset the spacer sizes to be based on the button size
+ adjustment = 0
+ if 'wxMac' not in wx.PlatformInfo:
+ adjustment = -3
+ self._sz.Children[0].AssignSpacer((1, sz.height/2 + adjustment))
+ self._contentSizer.Children[0].AssignSpacer((1, sz.height/2))
+
+ ssz = self._sz.GetMinSize()
+ sz.width = max(sz.width, ssz.width)
+ sz.height = max(sz.height, ssz.height)
+
+ else:
+ # do not use GetSize() but rather GetMinSize() since it calculates
+ # the required space of the sizer
+ sz = self._sz.GetMinSize()
+
+ # when expanded, we need more space
+ if self.IsExpanded():
+ pbs = self._pPane.GetBestSize()
+ sz.width = max(sz.GetWidth(), pbs.x)
+ sz.height = sz.y + self.GetBorder() + pbs.y
+
+ return sz
+
+
+ def Layout(self):
+ """ Layout the :class:`PyCollapsiblePane`. """
+
+ if not self._pButton or not self._pPane or not self._sz:
+ return False # we need to complete the creation first!
+
+ oursz = self.GetSize()
+
+ if self.HasAGWFlag(CP_USE_STATICBOX):
+ bdr = self.GetBorder()
+ self._pButton.SetPosition((bdr, bdr))
+
+ if self.IsExpanded():
+ self._pPane.Show()
+ self._pPane.Layout()
+ self._pStaticBox.Show()
+ self._pStaticBox.Lower()
+ self._pButton.Raise()
+ self._sz.SetDimension(0, 0, oursz.width, oursz.height)
+ self._sz.Layout()
+ else:
+ if hasattr(self, '_pStaticBox'):
+ self._pStaticBox.Hide()
+
+ else:
+ # move & resize the button and the static line
+ self._sz.SetDimension(0, 0, oursz.GetWidth(), self._sz.GetMinSize().GetHeight())
+ self._sz.Layout()
+
+ if self.IsExpanded():
+
+ # move & resize the container window
+ yoffset = self._sz.GetSize().GetHeight() + self.GetBorder()
+ self._pPane.SetDimensions(0, yoffset, oursz.x, oursz.y - yoffset)
+
+ # this is very important to make the pane window layout show correctly
+ self._pPane.Show()
+ self._pPane.Layout()
+
+ return True
+
+
+ def SetButton(self, button):
+ """
+ Assign a new button to :class:`PyCollapsiblePane`.
+
+ :param `button`: can be the standard :class:`Button` or any of the generic
+ implementations which live in :mod:`lib.buttons`.
+ """
+
+ if self._pButton:
+ if not self.HasAGWFlag(CP_USE_STATICBOX):
+ self._sz.Replace(self._pButton, button)
+ self.Unbind(wx.EVT_BUTTON, self._pButton)
+ self._pButton.Destroy()
+
+ self._pButton = button
+ self.SetLabel(button.GetLabel())
+ self.Bind(wx.EVT_BUTTON, self.OnButton, self._pButton)
+
+ if self._pPane:
+ self._pButton.MoveBeforeInTabOrder(self._pPane)
+ self.InvalidateBestSize()
+ self.Layout()
+
+
+ def GetButton(self):
+ """ Returns the button associated with :class:`PyCollapsiblePane`. """
+
+ return self._pButton
+
+
+
+#-----------------------------------------------------------------------------
+# PyCollapsiblePane - event handlers
+#-----------------------------------------------------------------------------
+
+ def OnButton(self, event):
+ """
+ Handles the ``wx.EVT_BUTTON`` event for :class:`PyCollapsiblePane`.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+ """
+
+ if event.GetEventObject() != self._pButton:
+ event.Skip()
+ return
+
+ self.Collapse(not self.IsCollapsed())
+
+ # this change was generated by the user - send the event
+ ev = wx.CollapsiblePaneEvent(self, self.GetId(), self.IsCollapsed())
+ self.GetEventHandler().ProcessEvent(ev)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`PyCollapsiblePane`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Layout()
+
+
+ def OnDrawGTKStyle(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`PyCollapsiblePane`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+
+ :note: This is a drawing routine to paint the GTK-style expander.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self._pButton)
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ dc.Clear()
+
+ self.OnDrawGTKExpander(dc)
+ self.OnDrawGTKText(dc)
+
+
+ def OnDrawGTKExpander(self, dc):
+ """
+ Overridable method to draw the GTK-style expander.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ self._pButton.OnDrawGTKExpander(dc)
+
+
+ def OnDrawGTKText(self, dc):
+ """
+ Overridable method to draw the :class:`PyCollapsiblePane` text in the expander.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ self._pButton.OnDrawGTKText(dc)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pygauge.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pygauge.py
new file mode 100644
index 0000000..d9c20c2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pygauge.py
@@ -0,0 +1,516 @@
+# --------------------------------------------------------------------------------- #
+# PYGAUGE wxPython IMPLEMENTATION
+#
+# Mark Reed, @ 28 Jul 2010
+# Latest Revision: 05 Sep 2012, 21.00 GMT
+#
+# TODO List
+#
+# 1. Indeterminate mode (see wx.Gauge)
+# 2. Vertical bar
+# 3. Bitmap support (bar, background)
+# 4. UpdateFunction - Pass a function to PyGauge which will be called every X
+# milliseconds and the value will be updated to the returned value.
+# 5. Currently the full gradient is drawn from 0 to value. Perhaps the gradient
+# should be drawn from 0 to range and clipped at 0 to value.
+# 6. Add a label?
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To The:
+#
+# wxPython Mailing List!!!
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`PyGauge` is a generic :class:`Gauge` implementation.
+
+
+Description
+===========
+
+:class:`PyGauge` supports the determinate mode functions as :class:`Gauge` and adds an meth:~PyGauge.Update` function
+which takes a value and a time parameter. The `value` is added to the current value over
+a period of `time` milliseconds.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.pygauge as PG
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "PyGauge Demo")
+
+ panel = wx.Panel(self)
+
+ gauge1 = PG.PyGauge(panel, -1, size=(100, 25), style=wx.GA_HORIZONTAL)
+ gauge1.SetValue(80)
+ gauge1.SetBackgroundColour(wx.WHITE)
+ gauge1.SetBorderColor(wx.BLACK)
+
+ gauge2 = PG.PyGauge(panel, -1, size=(100, 25), style=wx.GA_HORIZONTAL)
+ gauge2.SetValue([20, 80])
+ gauge2.SetBarColor([wx.Colour(162, 255, 178), wx.Colour(159, 176, 255)])
+ gauge2.SetBackgroundColour(wx.WHITE)
+ gauge2.SetBorderColor(wx.BLACK)
+ gauge2.SetBorderPadding(2)
+ gauge2.SetDrawValue(draw=True, drawPercent=True,
+ font=wx.SMALL_FONT, colour=wx.BLUE)
+ gauge2.Update([30, 0], 2000)
+
+ gauge3 = PG.PyGauge(panel, -1, size=(100, 25), style=wx.GA_HORIZONTAL)
+ gauge3.SetValue(50)
+ gauge3.SetBarColor(wx.GREEN)
+ gauge3.SetBackgroundColour(wx.WHITE)
+ gauge3.SetBorderColor(wx.BLACK)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(gauge1, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 20)
+ sizer.Add(gauge2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 20)
+ sizer.Add(gauge3, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 20)
+
+ panel.SetSizer(sizer)
+ sizer.Layout()
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+Supported Platforms
+===================
+
+:class:`PyGauge` has been tested on the following platforms:
+ * Windows (Windows XP, Windows 7);
+
+
+License And Version
+===================
+
+:class:`PyGauge` is distributed under the wxPython license.
+
+:class:`PyGauge` has been kindly contributed to the AGW library by Mark Reed.
+
+Latest Revision: Andrea Gavana @ 05 Sep 2012, 21.00 GMT
+
+Version 0.1
+
+"""
+
+import wx
+import copy
+
+
+class PyGauge(wx.PyWindow):
+ """
+ This class provides a visual alternative for :class:`Gauge`. It currently
+ only support determinate mode (see :meth:`PyGauge.SetValue() <PyGauge.SetValue>` and
+ :meth:`PyGauge.SetRange() <PyGauge.SetRange>`).
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, range=100, pos=wx.DefaultPosition,
+ size=(-1,30), style=0):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`PyWindow` window style.
+ """
+
+ wx.PyWindow.__init__(self, parent, id, pos, size, style)
+
+ self._size = size
+
+ self._border_colour = None
+ self._barColour = self._barColourSorted = [wx.Colour(212,228,255)]
+ self._barGradient = self._barGradientSorted = None
+
+ self._border_padding = 0
+ self._range = range
+ self._value = [0]
+ self._valueSorted = [0]
+
+ self._timerId = wx.NewId()
+ self._timer = None
+
+ self._drawIndicatorText = False
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_TIMER, self.OnTimer)
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits :class:`PyGauge`: for a control, it would be
+ the minimal size which doesn't truncate the control, for a panel - the
+ same size as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyWindow`.
+ """
+
+ return wx.Size(self._size[0], self._size[1])
+
+
+ def GetBorderColour(self):
+ """ Returns the :class:`PyGauge` border colour. """
+
+ return self._border_colour
+
+
+ def SetBorderColour(self, colour):
+ """
+ Sets the :class:`PyGauge` border colour.
+
+ :param `colour`: an instance of :class:`Colour`.
+ """
+
+ self._border_colour = colour
+
+ SetBorderColor = SetBorderColour
+ GetBorderColor = GetBorderColour
+
+
+ def GetBarColour(self):
+ """ Returns the :class:`PyGauge` main bar colour. """
+
+ return self._barColour[0]
+
+
+ def SetBarColour(self, colour):
+ """
+ Sets the :class:`PyGauge` main bar colour.
+
+ :param `colour`: an instance of :class:`Colour`.
+ """
+
+ if type(colour) != type([]):
+ self._barColour = [colour]
+ else:
+ self._barColour = list(colour)
+
+ self.SortForDisplay()
+
+ SetBarColor = SetBarColour
+ GetBarColor = GetBarColour
+
+
+ def GetBarGradient(self):
+ """ Returns a tuple containing the gradient start and end colours. """
+
+ if self._barGradient == None:
+ return None
+
+ return self._barGradient[0]
+
+
+ def SetBarGradient(self, gradient):
+ """
+ Sets the bar gradient.
+
+ :param `gradient`: a tuple containing the gradient start and end colours.
+
+ :note: This overrides the bar colour previously set with :meth:`PyGauge.SetBarColour`.
+ """
+
+ if type(gradient) != type([]):
+ self._barGradient = [gradient]
+ else:
+ self._barGradient = list(gradient)
+
+ self.SortForDisplay()
+
+
+ def GetBorderPadding(self):
+ """ Gets the border padding. """
+
+ return self._border_padding
+
+
+ def SetBorderPadding(self, padding):
+ """
+ Sets the border padding.
+
+ :param `padding`: pixels between the border and the progress bar.
+ """
+
+ self._border_padding = padding
+
+
+ def GetRange(self):
+ """ Returns the maximum value of the gauge. """
+
+ return self._range
+
+
+ def SetRange(self, range):
+ """
+ Sets the range of the gauge. The gauge length is its
+ value as a proportion of the range.
+
+ :param `range`: The maximum value of the gauge.
+ """
+
+ if range <= 0:
+ raise Exception("ERROR:\n Gauge range must be greater than 0.")
+
+ self._range = range
+
+
+ def GetValue(self):
+ """ Returns the current position of the gauge. """
+
+ return self._value[0]
+
+
+ def SetValue(self, value):
+ """
+ Sets the current position of the gauge.
+
+ :param `value`: an integer specifying the current position of the gauge.
+ """
+
+ if type(value) != type([]):
+ self._value = [value]
+ else:
+ self._value = list(value)
+
+ self.SortForDisplay()
+
+ for v in self._value:
+ if v < 0 or v > self._range:
+ raise Exception("ERROR:\n Gauge value must be between 0 and its range.")
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`PyGauge`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`PyGauge`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+ rect = self.GetClientRect()
+
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ dc.Clear()
+ colour = self.GetBackgroundColour()
+ dc.SetBrush(wx.Brush(colour))
+ dc.SetPen(wx.Pen(colour))
+ dc.DrawRectangleRect(rect)
+
+
+ if self._border_colour:
+ dc.SetPen(wx.Pen(self.GetBorderColour()))
+ dc.DrawRectangleRect(rect)
+ pad = 1 + self.GetBorderPadding()
+ rect.Deflate(pad,pad)
+
+
+ if self.GetBarGradient():
+ for i, gradient in enumerate(self._barGradientSorted):
+ c1,c2 = gradient
+ w = rect.width * (float(self._valueSorted[i]) / self._range)
+ r = copy.copy(rect)
+ r.width = w
+ dc.GradientFillLinear(r, c1, c2, wx.EAST)
+ else:
+ for i, colour in enumerate(self._barColourSorted):
+ dc.SetBrush(wx.Brush(colour))
+ dc.SetPen(wx.Pen(colour))
+ w = rect.width * (float(self._valueSorted[i]) / self._range)
+ r = copy.copy(rect)
+ r.width = w
+ dc.DrawRectangleRect(r)
+
+ if self._drawIndicatorText:
+ dc.SetFont(self._drawIndicatorText_font)
+ dc.SetTextForeground(self._drawIndicatorText_colour)
+ drawValue = self._valueSorted[i]
+
+ if self._drawIndicatorText_drawPercent:
+ drawValue = (float(self._valueSorted[i]) * 100) / self._range
+
+ drawString = self._drawIndicatorText_formatString.format(drawValue)
+ rect = self.GetClientRect()
+ (textWidth, textHeight, descent, extraLeading) = dc.GetFullTextExtent(drawString)
+ textYPos = (rect.height-textHeight)/2
+
+ if textHeight > rect.height:
+ textYPos = 0-descent+extraLeading
+
+ textXPos = (rect.width-textWidth)/2
+
+ if textWidth>rect.width:
+ textXPos = 0
+
+ dc.DrawText(drawString, textXPos, textYPos)
+
+
+ def SetDrawValue(self, draw=True, drawPercent=True, font=None, colour=wx.BLACK, formatString=None):
+ """
+ Sets whether percentage or current value should be drawn on the gauge for precise indication.
+
+ :param bool `draw`: a boolean value, which if ``True`` tells to start drawing value or percentage.
+ If set to ``False`` nothing will be drawn and other parameters will be ignored;
+ :param bool `drawPercent`: a boolean value which indicates that a percent should be drawn instead
+ of value passed in :meth:`SetValue`;
+ :param Font `font`: a font with which indication should be drawn, if ``None``, then ``wx.NORMAL_FONT``
+ will be used. Usually text would be displayed centered in the control, but if the text font is too large
+ to be displayed (either in width or height) the corresponding coordinate will be set to zero;
+ :param Colour `colour`: the colour with which indication should be drawn, if ``None`` then ``wx.BLACK`` will be used;
+ :param string `formatString`: a string specifying format of the indication (should have one and only one
+ number placeholder). If set to ``None``, will use ``{:.0f}`` format string for values and ``{:.0f}%``
+ format string for percentages. As described in http://docs.python.org/library/string.html#format-specification-mini-language.
+
+ .. note:: `formatString` will override addition of percent sign (after value) even if `drawPercent` is ``True``.
+
+ .. versionadded:: 0.9.7
+ """
+
+ if not draw:
+ # Will not draw anything unless this is True
+ self._drawIndicatorText = False
+ return
+
+ self._drawIndicatorText = True
+ self._drawIndicatorText_drawPercent = drawPercent
+
+ if font is None or not isinstance(font, wx.Font):
+ self._drawIndicatorText_font = wx.NORMAL_FONT
+ else:
+ self._drawIndicatorText_font = font
+
+ if colour is None or not isinstance(colour, wx.Colour):
+ self._drawIndicatorText_colour = wx.BLACK
+ else:
+ self._drawIndicatorText_colour = colour
+
+ if formatString is not None:
+ error_occurred = True
+ try:
+ # This is to test if format string is valid. If not, it will be replaced with default one.
+ formatString.format(12.345)
+ error_occurred = False
+ except Exception as e:
+ print "We have exception:%s"%e
+
+ if error_occurred:
+ formatString = None
+
+ # Here formatString is either valid formatting string, or None in case of error or None passed
+ if formatString is None:
+ if self._drawIndicatorText_drawPercent:
+ self._drawIndicatorText_formatString = "{:.0f}%"
+ else: self._drawIndicatorText_formatString = "{:.0f}"
+ else:
+ self._drawIndicatorText_formatString = formatString
+
+
+ def OnTimer(self,event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`PyGauge`.
+
+ :param `event`: a :class:`TimerEvent` event to be processed.
+ """
+
+ if self._timerId == event.GetId():
+ stop_timer = True
+ for i, v in enumerate(self._value):
+ self._value[i] += self._update_step[i]
+
+ if self._update_step[i] > 0:
+ if self._value[i] > self._update_value[i]:
+ self._value[i] = self._update_value[i]
+ else: stop_timer = False
+ else:
+ if self._value[i] < self._update_value[i]:
+ self._value[i] = self._update_value[i]
+ else: stop_timer = False
+
+ if stop_timer:
+ self._timer.Stop()
+
+ self.SortForDisplay()
+
+ self.Refresh()
+
+
+ def Update(self, value, time=0):
+ """
+ Update the gauge by adding `value` to it over `time` milliseconds. The `time` parameter
+ **must** be a multiple of 50 milliseconds.
+
+ :param `value`: The value to be added to the gauge;
+ :param `time`: The length of time in milliseconds that it will take to move the gauge.
+ """
+
+ if type(value) != type([]):
+ value = [value]
+
+ if len(value) != len(self._value):
+ raise Exception("ERROR:\n len(value) != len(self.GetValue())")
+
+ self._update_value = []
+ self._update_step = []
+ for i, v in enumerate(self._value):
+ if value[i]+v <= 0 or value[i]+v > self._range:
+ raise Exception("ERROR:\n Gauge value must be between 0 and its range. ")
+
+ self._update_value.append(value[i] + v)
+ self._update_step.append(float(value[i])/(time/50))
+
+ #print self._update_
+
+ if not self._timer:
+ self._timer = wx.Timer(self, self._timerId)
+
+ self._timer.Start(100)
+
+
+ def SortForDisplay(self):
+ """ Internal method which sorts things so we draw the longest bar first. """
+
+ if self.GetBarGradient():
+ tmp = sorted(zip(self._value,self._barGradient)); tmp.reverse()
+ a,b = zip(*tmp)
+ self._valueSorted = list(a)
+ self._barGradientSorted = list(b)
+ else:
+ tmp = sorted(zip(self._value,self._barColour)); tmp.reverse()
+ a,b = zip(*tmp)
+ self._valueSorted = list(a)
+ self._barColourSorted = list(b)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pyprogress.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pyprogress.py
new file mode 100644
index 0000000..f66c957
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/pyprogress.py
@@ -0,0 +1,878 @@
+# --------------------------------------------------------------------------------- #
+# PYPROGRESS wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 03 Nov 2006
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# TODO List
+#
+# 1. Do we support all the styles of wx.ProgressDialog in indeterminated mode?
+#
+# 2. Other ideas?
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@maerskoil.com
+# andrea.gavana@gmail.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`PyProgress` is similar to :class:`ProgressDialog` in indeterminated mode, but with a
+different gauge appearance and a different spinning behavior.
+
+
+Description
+===========
+
+:class:`PyProgress` is similar to :class:`ProgressDialog` in indeterminated mode, but with a
+different gauge appearance and a different spinning behavior. The moving gauge
+can be drawn with a single solid colour or with a shading gradient foreground.
+The gauge background colour is user customizable.
+
+The bar does not move always from the beginning to the end as in :class:`ProgressDialog`
+in indeterminated mode, but spins cyclically forward and backward.
+
+Other options include:
+
+- Possibility to change the proportion between the spinning bar and the
+ entire gauge, so that the bar can be longer or shorter (the default is 20%);
+- Modifying the number of steps the spinning bar performs before a forward
+ (or backward) loop reverses.
+
+:class:`PyProgress` can optionally display a ``Cancel`` button, and a :class:`StaticText` which
+outputs the elapsed time from the starting of the process.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.pyprogress as PP
+
+ # Our normal wxApp-derived class, as usual
+ app = wx.App(0)
+
+ dlg = PP.PyProgress(None, -1, "PyProgress Example",
+ "An Informative Message",
+ agwStyle=wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME)
+
+ dlg.SetGaugeProportion(0.2)
+ dlg.SetGaugeSteps(50)
+ dlg.SetGaugeBackground(wx.WHITE)
+ dlg.SetFirstGradientColour(wx.WHITE)
+ dlg.SetSecondGradientColour(wx.BLUE)
+
+ max = 400
+ keepGoing = True
+ count = 0
+
+ while keepGoing and count < max:
+ count += 1
+ wx.MilliSleep(30)
+
+ if count >= max / 2:
+ keepGoing = dlg.UpdatePulse("Half-time!")
+ else:
+ keepGoing = dlg.UpdatePulse()
+
+ dlg.Destroy()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`PyProgress` has been tested on the following platforms:
+ * Windows (Windows XP);
+ * Linux Ubuntu (Dapper 6.06)
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+=================== =========== ==================================================
+Window Styles Hex Value Description
+=================== =========== ==================================================
+``PD_CAN_ABORT`` 0x1 This flag tells the dialog that it should have a ``Cancel`` button which the user may press. If this happens, the next call to `Update` will return ``False``.
+``PD_APP_MODAL`` 0x2 Make the progress dialog modal. If this flag is not given, it is only 'locally' modal - that is the input to the parent window is disabled, but not to the other ones.
+``PD_AUTO_HIDE`` 0x4 Causes the progress dialog to disappear from screen as soon as the maximum value of the progress meter has been reached.
+``PD_ELAPSED_TIME`` 0x8 This flag tells the dialog that it should show elapsed time (since creating the dialog).
+=================== =========== ==================================================
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`PyProgress` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.4
+
+"""
+
+__docformat__ = "epytext"
+
+
+import wx
+
+# Some constants, taken straight from wx.ProgressDialog
+Uncancelable = -1
+""" Classifies the :class:`PyProgress` as "uncancelable". """
+Canceled = 0
+""" :class:`PyProgress` has been canceled. """
+Continue = 1
+""" :class:`PyProgress` can continue. """
+Finished = 2
+""" :class:`PyProgress` has finished. """
+
+# Margins between gauge and text/button
+LAYOUT_MARGIN = 8
+""" Margins between gauge and text/button (in pixels). """
+
+# PyProgress styles
+PD_CAN_ABORT = wx.PD_CAN_ABORT
+""" This flag tells the dialog that it should have a "Cancel" button which the user may press. If this happens, the next call to `Update()` will return ``False``. """
+PD_APP_MODAL = wx.PD_APP_MODAL
+""" Make the progress dialog modal. If this flag is not given, it is only 'locally' modal - that is the input to the parent window is disabled, but not to the other ones. """
+PD_AUTO_HIDE = wx.PD_AUTO_HIDE
+""" Causes the progress dialog to disappear from screen as soon as the maximum value of the progress meter has been reached. """
+PD_ELAPSED_TIME = wx.PD_ELAPSED_TIME
+""" This flag tells the dialog that it should show elapsed time (since creating the dialog). """
+
+# ---------------------------------------------------------------------------- #
+# Class ProgressGauge
+# ---------------------------------------------------------------------------- #
+
+class ProgressGauge(wx.PyWindow):
+ """ This class provides a visual alternative for :class:`Gauge`."""
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=(-1,30)):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform.
+ """
+
+ wx.PyWindow.__init__(self, parent, id, pos, size, style=wx.SUNKEN_BORDER)
+
+ self._value = 0
+ self._steps = 50
+ self._pos = 0
+ self._current = 0
+ self._gaugeproportion = 0.2
+ self._firstGradient = wx.WHITE
+ self._secondGradient = wx.BLUE
+ self._background = wx.Brush(wx.WHITE, wx.SOLID)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+
+
+ def GetFirstGradientColour(self):
+ """ Returns the first gradient colour. """
+
+ return self._firstGradient
+
+
+ def SetFirstGradientColour(self, colour):
+ """
+ Sets the first gradient colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ if not isinstance(colour, wx.Colour):
+ colour = wx.NamedColour(colour)
+
+ self._firstGradient = colour
+ self.Refresh()
+
+
+ def GetSecondGradientColour(self):
+ """ Returns the second gradient colour. """
+
+ return self._secondGradient
+
+
+ def SetSecondGradientColour(self, colour):
+ """
+ Sets the second gradient colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ if not isinstance(colour, wx.Colour):
+ colour = wx.NamedColour(colour)
+
+ self._secondGradient = colour
+ self.Refresh()
+
+
+ def GetGaugeBackground(self):
+ """ Returns the gauge background colour. """
+
+ return self._background
+
+
+ def SetGaugeBackground(self, colour):
+ """
+ Sets the gauge background colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ if not isinstance(colour, wx.Colour):
+ colour = wx.NamedColour(colour)
+
+ self._background = wx.Brush(colour, wx.SOLID)
+
+
+ def SetGaugeSteps(self, steps):
+ """
+ Sets the number of steps the gauge performs before switching from
+ forward to backward (or vice-versa) movement.
+
+ :param `steps`: the number of steps the gauge performs before switching from
+ forward to backward (or vice-versa) movement.
+ """
+
+ if steps <= 0:
+ raise Exception("ERROR:\n Gauge steps must be greater than zero. ")
+
+ if steps != self._steps:
+ self._steps = steps
+
+
+ def GetGaugeSteps(self):
+ """
+ Returns the number of steps the gauge performs before switching from
+ forward to backward (or vice-versa) movement.
+ """
+
+ return self._steps
+
+
+ def GetGaugeProportion(self):
+ """
+ Returns the relative proportion between the sliding bar and the
+ whole gauge.
+ """
+
+ return self._gaugeproportion
+
+
+ def SetGaugeProportion(self, proportion):
+ """
+ Sets the relative proportion between the sliding bar and the
+ whole gauge.
+
+ :param `proportion`: a floating point number representing the relative
+ proportion between the sliding bar and the whole gauge.
+ """
+
+ if proportion <= 0 or proportion >= 1:
+ raise Exception("ERROR:\n Gauge proportion must be between 0 and 1. ")
+
+ if proportion != self._gaugeproportion:
+ self._gaugeproportion = proportion
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`ProgressGauge`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`ProgressGauge`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+ dc.SetBackground(self._background)
+
+ dc.Clear()
+
+ xsize, ysize = self.GetClientSize()
+ interval = xsize/float(self._steps)
+
+ self._pos = interval*self._value
+
+ status = self._current/(self._steps - int(self._gaugeproportion*xsize)/int(interval))
+
+ if status%2 == 0:
+ increment = 1
+ else:
+ increment = -1
+
+ self._value = self._value + increment
+ self._current = self._current + 1
+ self.DrawProgress(dc, xsize, ysize, increment)
+
+
+ def DrawProgress(self, dc, xsize, ysize, increment):
+ """
+ Actually draws the sliding bar.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `xsize`: the width of the whole progress bar;
+ :param `ysize`: the height of the whole progress bar;
+ :param `increment`: a positive value if we are spinning from left to right,
+ a negative one if we are spinning from right to left.
+ """
+
+ if increment > 0:
+ col1 = self.GetFirstGradientColour()
+ col2 = self.GetSecondGradientColour()
+ else:
+ col1 = self.GetSecondGradientColour()
+ col2 = self.GetFirstGradientColour()
+
+ interval = self._gaugeproportion*xsize
+
+ r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+ r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+ rstep = float((r2 - r1)) / interval
+ gstep = float((g2 - g1)) / interval
+ bstep = float((b2 - b1)) / interval
+
+ rf, gf, bf = 0, 0, 0
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ for ii in xrange(int(self._pos), int(self._pos+interval)):
+ currCol = (r1 + rf, g1 + gf, b1 + bf)
+ dc.SetPen(wx.Pen(currCol, 2))
+ dc.DrawLine(ii, 1, ii, ysize-2)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+
+ def Update(self):
+ """ Updates the gauge with a new value. """
+
+ self.Refresh()
+
+
+# ---------------------------------------------------------------------------- #
+# Class PyProgress
+# ---------------------------------------------------------------------------- #
+
+class PyProgress(wx.Dialog):
+ """
+ :class:`PyProgress` is similar to :class:`ProgressDialog` in indeterminated mode, but with a
+ different gauge appearance and a different spinning behavior. The moving gauge
+ can be drawn with a single solid colour or with a shading gradient foreground.
+ The gauge background colour is user customizable.
+ The bar does not move always from the beginning to the end as in :class:`ProgressDialog`
+ in indeterminated mode, but spins cyclically forward and backward.
+ """
+
+ def __init__(self, parent=None, id=-1, title="", message="",
+ agwStyle=wx.PD_APP_MODAL|wx.PD_AUTO_HIDE):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `title`: dialog title to show in titlebar;
+ :param `message`: message displayed above the progress bar;
+ :param `style`: the dialog style. This can be a combination of the following bits:
+
+ =================== =========== ==================================================
+ Window Styles Hex Value Description
+ =================== =========== ==================================================
+ ``PD_CAN_ABORT`` 0x1 This flag tells the dialog that it should have a ``Cancel`` button which the user may press. If this happens, the next call to `UpdatePulse` will return ``False``.
+ ``PD_APP_MODAL`` 0x2 Make the progress dialog modal. If this flag is not given, it is only 'locally' modal - that is the input to the parent window is disabled, but not to the other ones.
+ ``PD_AUTO_HIDE`` 0x4 Causes the progress dialog to disappear from screen as soon as the maximum value of the progress meter has been reached.
+ ``PD_ELAPSED_TIME`` 0x8 This flag tells the dialog that it should show elapsed time (since creating the dialog).
+ =================== =========== ==================================================
+
+ """
+
+ wx.Dialog.__init__(self, parent, id, title)
+
+ self._delay = 3
+ self._hasAbortButton = False
+
+ # we may disappear at any moment, let the others know about it
+ self.SetExtraStyle(self.GetExtraStyle()|wx.WS_EX_TRANSIENT)
+
+ self._hasAbortButton = (agwStyle & wx.PD_CAN_ABORT)
+
+ if wx.Platform == "__WXMSW__":
+ # we have to remove the "Close" button from the title bar then as it is
+ # confusing to have it - it doesn't work anyhow
+ # FIXME: should probably have a (extended?) window style for this
+ if not self._hasAbortButton:
+ self.EnableClose(False)
+
+ self._state = (self._hasAbortButton and [Continue] or [Uncancelable])[0]
+ self._parentTop = wx.GetTopLevelParent(parent)
+
+ dc = wx.ClientDC(self)
+ dc.SetFont(wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT))
+ widthText, dummy = dc.GetTextExtent(message)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ self._msg = wx.StaticText(self, wx.ID_ANY, message)
+ sizer.Add(self._msg, 0, wx.LEFT|wx.TOP, 2*LAYOUT_MARGIN)
+
+ sizeDlg = wx.Size()
+ sizeLabel = self._msg.GetSize()
+ sizeDlg.y = 2*LAYOUT_MARGIN + sizeLabel.y
+
+ self._gauge = ProgressGauge(self, -1)
+
+ sizer.Add(self._gauge, 0, wx.LEFT|wx.RIGHT|wx.TOP|wx.EXPAND, 2*LAYOUT_MARGIN)
+
+ sizeGauge = self._gauge.GetSize()
+ sizeDlg.y += 2*LAYOUT_MARGIN + sizeGauge.y
+
+ # create the estimated/remaining/total time zones if requested
+ self._elapsed = None
+ self._display_estimated = self._last_timeupdate = self._break = 0
+ self._ctdelay = 0
+
+ label = None
+
+ nTimeLabels = 0
+
+ if agwStyle & wx.PD_ELAPSED_TIME:
+
+ nTimeLabels += 1
+ self._elapsed = self.CreateLabel("Elapsed time : ", sizer)
+
+ if nTimeLabels > 0:
+
+ label = wx.StaticText(self, -1, "")
+ # set it to the current time
+ self._timeStart = wx.GetCurrentTime()
+ sizeDlg.y += nTimeLabels*(label.GetSize().y + LAYOUT_MARGIN)
+ label.Destroy()
+
+ sizeDlgModified = False
+
+ if wx.Platform == "__WXMSW__":
+ sizerFlags = wx.ALIGN_RIGHT|wx.ALL
+ else:
+ sizerFlags = wx.ALIGN_CENTER_HORIZONTAL|wx.BOTTOM|wx.TOP
+
+ if self._hasAbortButton:
+ buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ self._btnAbort = wx.Button(self, -1, "Cancel")
+ self._btnAbort.Bind(wx.EVT_BUTTON, self.OnCancel)
+
+ # Windows dialogs usually have buttons in the lower right corner
+ buttonSizer.Add(self._btnAbort, 0, sizerFlags, LAYOUT_MARGIN)
+
+ if not sizeDlgModified:
+ sizeDlg.y += 2*LAYOUT_MARGIN + wx.Button.GetDefaultSize().y
+
+ if self._hasAbortButton:
+ sizer.Add(buttonSizer, 0, sizerFlags, LAYOUT_MARGIN )
+
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+
+ self._agwStyle = agwStyle
+
+ self.SetSizerAndFit(sizer)
+
+ sizeDlg.y += 2*LAYOUT_MARGIN
+
+ # try to make the dialog not square but rectangular of reasonable width
+ sizeDlg.x = max(widthText, 4*sizeDlg.y/3)
+ sizeDlg.x *= 3
+ sizeDlg.x /= 2
+ self.SetClientSize(sizeDlg)
+
+ self.Centre(wx.CENTER_FRAME|wx.BOTH)
+
+ if agwStyle & wx.PD_APP_MODAL:
+ self._winDisabler = wx.WindowDisabler(self)
+ else:
+ if self._parentTop:
+ self._parentTop.Disable()
+ self._winDisabler = None
+
+ self.ShowDialog()
+ self.Enable()
+
+ # this one can be initialized even if the others are unknown for now
+ # NB: do it after calling Layout() to keep the labels correctly aligned
+ if self._elapsed:
+ self.SetTimeLabel(0, self._elapsed)
+
+ if not wx.EventLoop().GetActive():
+ self.evtloop = wx.EventLoop()
+ wx.EventLoop.SetActive(self.evtloop)
+
+ self.Update()
+
+
+ def CreateLabel(self, text, sizer):
+ """
+ Creates the :class:`StaticText` that holds the elapsed time label.
+
+ :param `text`: the dialog message to be displayed above the gauge;
+ :param `sizer`: the main :class:`BoxSizer` for :class:`PyProgress`.
+ """
+
+ locsizer = wx.BoxSizer(wx.HORIZONTAL)
+ dummy = wx.StaticText(self, wx.ID_ANY, text)
+ label = wx.StaticText(self, wx.ID_ANY, "unknown")
+
+ if wx.Platform in ["__WXMSW__", "__WXMAC__"]:
+ # label and time centered in one row
+ locsizer.Add(dummy, 1, wx.ALIGN_LEFT)
+ locsizer.Add(label, 1, wx.ALIGN_LEFT|wx.LEFT, LAYOUT_MARGIN)
+ sizer.Add(locsizer, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.TOP, LAYOUT_MARGIN)
+ else:
+ # label and time to the right in one row
+ sizer.Add(locsizer, 0, wx.ALIGN_RIGHT|wx.RIGHT|wx.TOP, LAYOUT_MARGIN)
+ locsizer.Add(dummy)
+ locsizer.Add(label, 0, wx.LEFT, LAYOUT_MARGIN)
+
+ return label
+
+
+ # ----------------------------------------------------------------------------
+ # wxProgressDialog operations
+ # ----------------------------------------------------------------------------
+
+ def UpdatePulse(self, newmsg=""):
+ """
+ Updates the dialog, setting the progress bar to the new value and, if given
+ changes the message above it. Returns ``True`` unless the ``Cancel`` button
+ has been pressed.
+
+ If ``False`` is returned, the application can either immediately destroy the
+ dialog or ask the user for the confirmation.
+
+ :param `newmsg`: The new messages for the progress dialog text, if it is
+ empty (which is the default) the message is not changed.
+ """
+
+ self._gauge.Update()
+
+ if newmsg and newmsg != self._msg.GetLabel():
+ self._msg.SetLabel(newmsg)
+ wx.YieldIfNeeded()
+
+ if self._elapsed:
+ elapsed = wx.GetCurrentTime() - self._timeStart
+ if self._last_timeupdate < elapsed:
+ self._last_timeupdate = elapsed
+
+ self.SetTimeLabel(elapsed, self._elapsed)
+
+ if self._state == Finished:
+
+ if not self._agwStyle & wx.PD_AUTO_HIDE:
+
+ self.EnableClose()
+
+ if newmsg == "":
+ # also provide the finishing message if the application didn't
+ self._msg.SetLabel("Done.")
+
+ wx.YieldIfNeeded()
+ self.ShowModal()
+ return False
+
+ else:
+ # reenable other windows before hiding this one because otherwise
+ # Windows wouldn't give the focus back to the window which had
+ # been previously focused because it would still be disabled
+ self.ReenableOtherWindows()
+ self.Hide()
+
+ # we have to yield because not only we want to update the display but
+ # also to process the clicks on the cancel and skip buttons
+ wx.YieldIfNeeded()
+
+ return self._state != Canceled
+
+
+ def GetFirstGradientColour(self):
+ """ Returns the gauge first gradient colour. """
+
+ return self._gauge.GetFirstGradientColour()
+
+
+ def SetFirstGradientColour(self, colour):
+ """
+ Sets the gauge first gradient colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._gauge.SetFirstGradientColour(colour)
+
+
+ def GetSecondGradientColour(self):
+ """ Returns the gauge second gradient colour. """
+
+ return self._gauge.GetSecondGradientColour()
+
+
+ def SetSecondGradientColour(self, colour):
+ """
+ Sets the gauge second gradient colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._gauge.SetSecondGradientColour(colour)
+
+
+ def GetGaugeBackground(self):
+ """ Returns the gauge background colour. """
+
+ return self._gauge.GetGaugeBackground()
+
+
+ def SetGaugeBackground(self, colour):
+ """
+ Sets the gauge background colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._gauge.SetGaugeBackground(colour)
+
+
+ def SetGaugeSteps(self, steps):
+ """
+ Sets the number of steps the gauge performs before switching from
+ forward to backward (or vice-versa) movement.
+
+ :param `steps`: the number of steps the gauge performs before switching from
+ forward to backward (or vice-versa) movement.
+ """
+
+ self._gauge.SetGaugeSteps(steps)
+
+
+ def GetGaugeSteps(self):
+ """
+ Returns the number of steps the gauge performs before switching from
+ forward to backward (or vice-versa) movement.
+ """
+
+ return self._gauge.GetGaugeSteps()
+
+
+ def GetGaugeProportion(self):
+ """
+ Returns the relative proportion between the sliding bar and the
+ whole gauge.
+ """
+
+ return self._gauge.GetGaugeProportion()
+
+
+ def SetGaugeProportion(self, proportion):
+ """
+ Sets the relative proportion between the sliding bar and the
+ whole gauge.
+
+ :param `proportion`: a floating point number representing the relative
+ proportion between the sliding bar and the whole gauge.
+ """
+
+ self._gauge.SetGaugeProportion(proportion)
+
+
+ def ShowDialog(self, show=True):
+ """
+ Show the dialog.
+
+ :param `show`: ``True`` to show the dialog and re-enable all the other windows,
+ ``False`` otherwise.
+ """
+
+ # reenable other windows before hiding this one because otherwise
+ # Windows wouldn't give the focus back to the window which had
+ # been previously focused because it would still be disabled
+ if not show:
+ self.ReenableOtherWindows()
+
+ return self.Show()
+
+
+ # ----------------------------------------------------------------------------
+ # event handlers
+ # ----------------------------------------------------------------------------
+
+ def OnCancel(self, event):
+ """
+ Handles the ``wx.EVT_BUTTON`` event for the dialog.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+
+ :note: This method handles the ``Cancel`` button press.
+ """
+
+ if self._state == Finished:
+
+ # this means that the count down is already finished and we're being
+ # shown as a modal dialog - so just let the default handler do the job
+ event.Skip()
+
+ else:
+
+ # request to cancel was received, the next time Update() is called we
+ # will handle it
+ self._state = Canceled
+
+ # update the buttons state immediately so that the user knows that the
+ # request has been noticed
+ self.DisableAbort()
+
+ # save the time when the dialog was stopped
+ self._timeStop = wx.GetCurrentTime()
+
+ self.ReenableOtherWindows()
+
+
+ def OnDestroy(self, event):
+ """
+ Handles the ``wx.EVT_WINDOW_DESTROY`` event for :class:`PyProgress`.
+
+ :param `event`: a :class:`WindowDestroyEvent` event to be processed.
+ """
+
+ self.ReenableOtherWindows()
+ event.Skip()
+
+
+ def OnClose(self, event):
+ """
+ Handles the ``wx.EVT_CLOSE`` event for :class:`PyProgress`.
+
+ :param `event`: a :class:`CloseEvent` event to be processed.
+ """
+
+ if self._state == Uncancelable:
+
+ # can't close this dialog
+ event.Veto()
+
+ elif self._state == Finished:
+
+ # let the default handler close the window as we already terminated
+ self.Hide()
+ event.Skip()
+
+ else:
+
+ # next Update() will notice it
+ self._state = Canceled
+ self.DisableAbort()
+
+ self._timeStop = wx.GetCurrentTime()
+
+
+ def ReenableOtherWindows(self):
+ """ Re-enables the other windows if using :class:`WindowDisabler`. """
+
+ if self._agwStyle & wx.PD_APP_MODAL:
+ if hasattr(self, "_winDisabler"):
+ del self._winDisabler
+
+ else:
+
+ if self._parentTop:
+ self._parentTop.Enable()
+
+
+ def SetTimeLabel(self, val, label=None):
+ """
+ Sets the elapsed time label.
+
+ :param `val`: the elapsed time since the dialog was shown, in seconds;
+ :param `label`: the new message to display in the elapsed time text.
+ """
+
+ if label:
+
+ hours = val/3600
+ minutes = (val%3600)/60
+ seconds = val%60
+ strs = ("%lu:%02lu:%02lu")%(hours, minutes, seconds)
+
+ if strs != label.GetLabel():
+ label.SetLabel(strs)
+
+
+ def EnableAbort(self, enable=True):
+ """
+ Enables or disables the ``Cancel`` button.
+
+ :param `enable`: ``True`` to enable the ``Cancel`` button, ``False`` to disable it.
+ """
+
+ if self._hasAbortButton:
+ if self._btnAbort:
+ self._btnAbort.Enable(enable)
+
+
+ def EnableClose(self, enable=True):
+ """
+ Enables or disables the ``Close`` button.
+
+ :param `enable`: ``True`` to enable the ``Close`` button, ``False`` to disable it.
+ """
+
+ if self._hasAbortButton:
+ if self._btnAbort:
+ self._btnAbort.Enable(enable)
+ self._btnAbort.SetLabel("Close")
+ self._btnAbort.Bind(wx.EVT_BUTTON, self.OnClose)
+
+
+ def DisableAbort(self):
+ """ Disables the ``Cancel`` button. """
+
+ self.EnableAbort(False)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/__init__.py
new file mode 100644
index 0000000..9c7d64c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/__init__.py
@@ -0,0 +1,177 @@
+"""
+The `RibbonBar` library is a set of classes for writing a ribbon user interface.
+
+Description
+===========
+
+At the most generic level, this is a combination of a tab control with a toolbar.
+At a more functional level, it is similar to the user interface present in recent
+versions of Microsoft Office.
+
+A ribbon user interface typically has a :class:`bar.RibbonBar`, which contains one or more
+:class:`page.RibbonPage`, which in turn each contains one or more :class:`panel.RibbonPanel`, which in turn
+contain controls.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.ribbon as RB
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent, id=-1, title="Ribbon Demo", pos=wx.DefaultPosition,
+ size=(800, 600), style=wx.DEFAULT_FRAME_STYLE):
+
+ wx.Frame.__init__(self, parent, id, title, pos, size, style)
+
+ self._ribbon = RB.RibbonBar(self, wx.ID_ANY)
+
+ home = RB.RibbonPage(self._ribbon, wx.ID_ANY, "Examples", CreateBitmap("ribbon"))
+ toolbar_panel = RB.RibbonPanel(home, wx.ID_ANY, "Toolbar", wx.NullBitmap, wx.DefaultPosition,
+ wx.DefaultSize, agwStyle=RB.RIBBON_PANEL_NO_AUTO_MINIMISE)
+
+ toolbar = RB.RibbonToolBar(toolbar_panel, ID_MAIN_TOOLBAR)
+ toolbar.AddTool(wx.ID_ANY, CreateBitmap("align_left"))
+ toolbar.AddTool(wx.ID_ANY, CreateBitmap("align_center"))
+ toolbar.AddTool(wx.ID_ANY, CreateBitmap("align_right"))
+ toolbar.AddSeparator()
+ toolbar.AddHybridTool(wx.ID_NEW, wx.ArtProvider.GetBitmap(wx.ART_NEW, wx.ART_OTHER, wx.Size(16, 15)))
+ toolbar.AddTool(wx.ID_ANY, wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, wx.Size(16, 15)))
+ toolbar.AddTool(wx.ID_ANY, wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_OTHER, wx.Size(16, 15)))
+ toolbar.AddTool(wx.ID_ANY, wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE_AS, wx.ART_OTHER, wx.Size(16, 15)))
+ toolbar.AddSeparator()
+ toolbar.AddDropdownTool(wx.ID_UNDO, wx.ArtProvider.GetBitmap(wx.ART_UNDO, wx.ART_OTHER, wx.Size(16, 15)))
+ toolbar.AddDropdownTool(wx.ID_REDO, wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_OTHER, wx.Size(16, 15)))
+ toolbar.AddSeparator()
+ toolbar.AddTool(wx.ID_ANY, wx.ArtProvider.GetBitmap(wx.ART_REPORT_VIEW, wx.ART_OTHER, wx.Size(16, 15)))
+ toolbar.AddTool(wx.ID_ANY, wx.ArtProvider.GetBitmap(wx.ART_LIST_VIEW, wx.ART_OTHER, wx.Size(16, 15)))
+ toolbar.AddSeparator()
+ toolbar.AddHybridTool(ID_POSITION_LEFT, CreateBitmap("position_left"),
+ "Align ribbonbar vertically on the left for demonstration purposes")
+ toolbar.AddHybridTool(ID_POSITION_TOP, CreateBitmap("position_top"),
+ "Align the ribbonbar horizontally at the top for demonstration purposes")
+ toolbar.AddSeparator()
+ toolbar.AddHybridTool(wx.ID_PRINT, wx.ArtProvider.GetBitmap(wx.ART_PRINT, wx.ART_OTHER, wx.Size(16, 15)),
+ "This is the Print button tooltip demonstrating a tooltip")
+ toolbar.SetRows(2, 3)
+
+ selection_panel = RB.RibbonPanel(home, wx.ID_ANY, "Selection", CreateBitmap("selection_panel"))
+ selection = RB.RibbonButtonBar(selection_panel)
+ selection.AddSimpleButton(ID_SELECTION_EXPAND_V, "Expand Vertically", CreateBitmap("expand_selection_v"),
+ "This is a tooltip for Expand Vertically demonstrating a tooltip")
+ selection.AddSimpleButton(ID_SELECTION_EXPAND_H, "Expand Horizontally", CreateBitmap("expand_selection_h"), "")
+ selection.AddSimpleButton(ID_SELECTION_CONTRACT, "Contract", CreateBitmap("auto_crop_selection"),
+ CreateBitmap("auto_crop_selection_small"))
+
+ shapes_panel = RB.RibbonPanel(home, wx.ID_ANY, "Shapes", CreateBitmap("circle_small"))
+ shapes = RB.RibbonButtonBar(shapes_panel)
+
+ # Show toggle buttons behaviour
+ shapes.AddButton(ID_CIRCLE, "Circle", CreateBitmap("circle"), CreateBitmap("circle_small"),
+ help_string="This is a tooltip for the circle button demonstrating another tooltip",
+ kind=RB.RIBBON_BUTTON_TOGGLE)
+
+ shapes.AddSimpleButton(ID_CROSS, "Cross", CreateBitmap("cross"), "")
+ shapes.AddHybridButton(ID_TRIANGLE, "Triangle", CreateBitmap("triangle"))
+ shapes.AddSimpleButton(ID_SQUARE, "Square", CreateBitmap("square"), "")
+ shapes.AddDropdownButton(ID_POLYGON, "Other Polygon", CreateBitmap("hexagon"), "")
+
+ sizer_panel = RB.RibbonPanel(home, wx.ID_ANY, "Panel with Sizer",
+ wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize,
+ agwStyle=RB.RIBBON_PANEL_DEFAULT_STYLE)
+
+ scheme = RB.RibbonPage(self._ribbon, wx.ID_ANY, "Appearance", CreateBitmap("eye"))
+ self._default_primary, self._default_secondary, self._default_tertiary = self._ribbon.GetArtProvider().GetColourScheme(1, 1, 1)
+
+ provider_panel = RB.RibbonPanel(scheme, wx.ID_ANY, "Art", wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize,
+ agwStyle=RB.RIBBON_PANEL_NO_AUTO_MINIMISE)
+ provider_bar = RB.RibbonButtonBar(provider_panel, wx.ID_ANY)
+ provider_bar.AddSimpleButton(ID_DEFAULT_PROVIDER, "Default Provider",
+ wx.ArtProvider.GetBitmap(wx.ART_QUESTION, wx.ART_OTHER, wx.Size(32, 32)), "")
+ provider_bar.AddSimpleButton(ID_AUI_PROVIDER, "AUI Provider", CreateBitmap("aui_style"), "")
+ provider_bar.AddSimpleButton(ID_MSW_PROVIDER, "MSW Provider", CreateBitmap("msw_style"), "")
+
+ primary_panel = RB.RibbonPanel(scheme, wx.ID_ANY, "Primary Colour", CreateBitmap("colours"))
+ self._primary_gallery = self.PopulateColoursPanel(primary_panel, self._default_primary, ID_PRIMARY_COLOUR)
+
+ secondary_panel = RB.RibbonPanel(scheme, wx.ID_ANY, "Secondary Colour", CreateBitmap("colours"))
+ self._secondary_gallery = self.PopulateColoursPanel(secondary_panel, self._default_secondary, ID_SECONDARY_COLOUR)
+
+ dummy_2 = RB.RibbonPage(self._ribbon, wx.ID_ANY, "Empty Page", CreateBitmap("empty"))
+ dummy_3 = RB.RibbonPage(self._ribbon, wx.ID_ANY, "Another Page", CreateBitmap("empty"))
+
+ self._ribbon.Realize()
+
+ self._logwindow = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, wx.DefaultSize,
+ wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_LEFT | wx.TE_BESTWRAP | wx.BORDER_NONE)
+
+ s = wx.BoxSizer(wx.VERTICAL)
+
+ s.Add(self._ribbon, 0, wx.EXPAND)
+ s.Add(self._logwindow, 1, wx.EXPAND)
+
+ self.SetSizer(s)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+What's New
+==========
+
+Current wxRibbon version tracked: wxWidgets 2.9.4 (SVN HEAD)
+
+New features recently implemented:
+
+- Possibility to hide panels in the :class:`bar.RibbonBar`;
+- Added the ``EVT_RIBBONBAR_TAB_LEFT_DCLICK`` event, which generates a special event
+ when a ribbon bar tab is double-clicked;
+- Added support for toggle buttons in the :class:`bar.RibbonBar`;
+- Improved support for ribbon panel sizers: panels with sizers should now automatically
+ minimise at small sizes, and behave properly when popping up from a minimised state;
+- Added tooltips via `SetToolTip` for those buttons which have the `help_string` attribute set.
+
+
+License And Version
+===================
+
+RIBBON library is distributed under the wxPython license.
+
+Latest revision: Andrea Gavana @ 31 Oct 2012, 21.00 GMT
+
+Version 0.3.
+
+"""
+
+__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
+__date__ = "16 October 2009"
+
+
+from art import *
+from art_aui import *
+from art_internal import *
+from art_msw import *
+from art_default import *
+
+from bar import *
+from buttonbar import *
+from control import *
+from gallery import *
+
+from page import *
+from panel import *
+from toolbar import *
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art.py
new file mode 100644
index 0000000..249f197
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art.py
@@ -0,0 +1,203 @@
+# RibbonArtSetting
+RIBBON_ART_TAB_SEPARATION_SIZE = 1
+RIBBON_ART_PAGE_BORDER_LEFT_SIZE = 2
+RIBBON_ART_PAGE_BORDER_TOP_SIZE = 3
+RIBBON_ART_PAGE_BORDER_RIGHT_SIZE = 4
+RIBBON_ART_PAGE_BORDER_BOTTOM_SIZE = 5
+RIBBON_ART_PANEL_X_SEPARATION_SIZE = 6
+RIBBON_ART_PANEL_Y_SEPARATION_SIZE = 7
+RIBBON_ART_TOOL_GROUP_SEPARATION_SIZE = 8
+RIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE = 9
+RIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE = 10
+RIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE = 11
+RIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE = 12
+RIBBON_ART_PANEL_LABEL_FONT = 13
+RIBBON_ART_BUTTON_BAR_LABEL_FONT = 14
+RIBBON_ART_TAB_LABEL_FONT = 15
+RIBBON_ART_BUTTON_BAR_LABEL_COLOUR = 16
+RIBBON_ART_BUTTON_BAR_HOVER_BORDER_COLOUR = 17
+RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_COLOUR = 18
+RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR = 19
+RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_COLOUR = 20
+RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_GRADIENT_COLOUR = 21
+RIBBON_ART_BUTTON_BAR_ACTIVE_BORDER_COLOUR = 22
+RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_COLOUR = 23
+RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR = 24
+RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_COLOUR = 25
+RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_GRADIENT_COLOUR = 26
+RIBBON_ART_GALLERY_BORDER_COLOUR = 27
+RIBBON_ART_GALLERY_HOVER_BACKGROUND_COLOUR = 28
+RIBBON_ART_GALLERY_BUTTON_BACKGROUND_COLOUR = 29
+RIBBON_ART_GALLERY_BUTTON_BACKGROUND_GRADIENT_COLOUR = 30
+RIBBON_ART_GALLERY_BUTTON_BACKGROUND_TOP_COLOUR = 31
+RIBBON_ART_GALLERY_BUTTON_FACE_COLOUR = 32
+RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_COLOUR = 33
+RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_GRADIENT_COLOUR = 34
+RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_TOP_COLOUR = 35
+RIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR = 36
+RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_COLOUR = 37
+RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_GRADIENT_COLOUR = 38
+RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_TOP_COLOUR = 39
+RIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR = 40
+RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_COLOUR = 41
+RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_GRADIENT_COLOUR = 42
+RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_TOP_COLOUR = 43
+RIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR = 44
+RIBBON_ART_GALLERY_ITEM_BORDER_COLOUR = 45
+RIBBON_ART_TAB_LABEL_COLOUR = 46
+RIBBON_ART_TAB_SEPARATOR_COLOUR = 47
+RIBBON_ART_TAB_SEPARATOR_GRADIENT_COLOUR = 48
+RIBBON_ART_TAB_CTRL_BACKGROUND_COLOUR = 49
+RIBBON_ART_TAB_CTRL_BACKGROUND_GRADIENT_COLOUR = 50
+RIBBON_ART_TAB_HOVER_BACKGROUND_TOP_COLOUR = 51
+RIBBON_ART_TAB_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR = 52
+RIBBON_ART_TAB_HOVER_BACKGROUND_COLOUR = 53
+RIBBON_ART_TAB_HOVER_BACKGROUND_GRADIENT_COLOUR = 54
+RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_COLOUR = 55
+RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR = 56
+RIBBON_ART_TAB_ACTIVE_BACKGROUND_COLOUR = 57
+RIBBON_ART_TAB_ACTIVE_BACKGROUND_GRADIENT_COLOUR = 58
+RIBBON_ART_TAB_BORDER_COLOUR = 59
+RIBBON_ART_PANEL_BORDER_COLOUR = 60
+RIBBON_ART_PANEL_BORDER_GRADIENT_COLOUR = 61
+RIBBON_ART_PANEL_MINIMISED_BORDER_COLOUR = 62
+RIBBON_ART_PANEL_MINIMISED_BORDER_GRADIENT_COLOUR = 63
+RIBBON_ART_PANEL_LABEL_BACKGROUND_COLOUR = 64
+RIBBON_ART_PANEL_LABEL_BACKGROUND_GRADIENT_COLOUR = 65
+RIBBON_ART_PANEL_LABEL_COLOUR = 66
+RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_COLOUR = 67
+RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_GRADIENT_COLOUR = 68
+RIBBON_ART_PANEL_HOVER_LABEL_COLOUR = 69
+RIBBON_ART_PANEL_MINIMISED_LABEL_COLOUR = 70
+RIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_COLOUR = 71
+RIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR = 72
+RIBBON_ART_PANEL_ACTIVE_BACKGROUND_COLOUR = 73
+RIBBON_ART_PANEL_ACTIVE_BACKGROUND_GRADIENT_COLOUR = 74
+RIBBON_ART_PANEL_BUTTON_FACE_COLOUR = 75
+RIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR = 76
+RIBBON_ART_PAGE_BORDER_COLOUR = 77
+RIBBON_ART_PAGE_BACKGROUND_TOP_COLOUR = 78
+RIBBON_ART_PAGE_BACKGROUND_TOP_GRADIENT_COLOUR = 79
+RIBBON_ART_PAGE_BACKGROUND_COLOUR = 80
+RIBBON_ART_PAGE_BACKGROUND_GRADIENT_COLOUR = 81
+RIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_COLOUR = 82
+RIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR = 83
+RIBBON_ART_PAGE_HOVER_BACKGROUND_COLOUR = 84
+RIBBON_ART_PAGE_HOVER_BACKGROUND_GRADIENT_COLOUR = 85
+RIBBON_ART_TOOLBAR_BORDER_COLOUR = 86
+RIBBON_ART_TOOLBAR_HOVER_BORDER_COLOUR = 87
+RIBBON_ART_TOOLBAR_FACE_COLOUR = 88
+RIBBON_ART_TOOL_BACKGROUND_TOP_COLOUR = 89
+RIBBON_ART_TOOL_BACKGROUND_TOP_GRADIENT_COLOUR = 90
+RIBBON_ART_TOOL_BACKGROUND_COLOUR = 91
+RIBBON_ART_TOOL_BACKGROUND_GRADIENT_COLOUR = 92
+RIBBON_ART_TOOL_HOVER_BACKGROUND_TOP_COLOUR = 93
+RIBBON_ART_TOOL_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR = 94
+RIBBON_ART_TOOL_HOVER_BACKGROUND_COLOUR = 95
+RIBBON_ART_TOOL_HOVER_BACKGROUND_GRADIENT_COLOUR = 96
+RIBBON_ART_TOOL_ACTIVE_BACKGROUND_TOP_COLOUR = 97
+RIBBON_ART_TOOL_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR = 98
+RIBBON_ART_TOOL_ACTIVE_BACKGROUND_COLOUR = 99
+RIBBON_ART_TOOL_ACTIVE_BACKGROUND_GRADIENT_COLOUR = 100
+
+
+# RibbonScrollButtonStyle
+RIBBON_SCROLL_BTN_LEFT = 0
+"""Button will scroll to the left."""
+RIBBON_SCROLL_BTN_RIGHT = 1
+"""Button will scroll to the right."""
+RIBBON_SCROLL_BTN_UP = 2
+"""Button will scroll upward."""
+RIBBON_SCROLL_BTN_DOWN = 3
+"""Button will scroll downward."""
+
+RIBBON_SCROLL_BTN_DIRECTION_MASK = 3
+"""A mask to extract direction from a combination of flags."""
+RIBBON_SCROLL_BTN_NORMAL = 0
+"""Button is not active or hovered."""
+RIBBON_SCROLL_BTN_HOVERED = 4
+"""Button has a cursor hovering over it."""
+RIBBON_SCROLL_BTN_ACTIVE = 8
+"""Button is being pressed."""
+RIBBON_SCROLL_BTN_STATE_MASK = 12
+"""A mask to extract state from a combination of flags."""
+RIBBON_SCROLL_BTN_FOR_OTHER = 0
+"""Button is not for scrolling tabs nor pages."""
+RIBBON_SCROLL_BTN_FOR_TABS = 16
+"""Button is for scrolling tabs."""
+RIBBON_SCROLL_BTN_FOR_PAGE = 32
+"""Button is for scrolling pages."""
+RIBBON_SCROLL_BTN_FOR_MASK = 48
+"""A mask to extract purpose from a combination of flags."""
+
+# RibbonButtonKind
+RIBBON_BUTTON_NORMAL = 1 << 0
+"""Normal button or tool with a clickable area which causes some generic action."""
+RIBBON_BUTTON_DROPDOWN = 1 << 1
+"""Dropdown button or tool with a clickable area which typically causes a dropdown menu."""
+RIBBON_BUTTON_HYBRID = RIBBON_BUTTON_NORMAL | RIBBON_BUTTON_DROPDOWN
+"""Button or tool with two clickable areas - one which causes a dropdown menu, and one which causes a generic action."""
+RIBBON_BUTTON_TOGGLE = 1 << 2
+"""Normal button or tool with a clickable area which toggles the button between a pressed and unpressed state."""
+
+# RibbonButtonBarButtonState
+RIBBON_BUTTONBAR_BUTTON_SMALL = 0 << 0
+RIBBON_BUTTONBAR_BUTTON_MEDIUM = 1 << 0
+RIBBON_BUTTONBAR_BUTTON_LARGE = 2 << 0
+RIBBON_BUTTONBAR_BUTTON_SIZE_MASK = 3 << 0
+
+RIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED = 1 << 3
+RIBBON_BUTTONBAR_BUTTON_DROPDOWN_HOVERED = 1 << 4
+RIBBON_BUTTONBAR_BUTTON_HOVER_MASK = RIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED | RIBBON_BUTTONBAR_BUTTON_DROPDOWN_HOVERED
+RIBBON_BUTTONBAR_BUTTON_NORMAL_ACTIVE = 1 << 5
+RIBBON_BUTTONBAR_BUTTON_DROPDOWN_ACTIVE = 1 << 6
+RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK = RIBBON_BUTTONBAR_BUTTON_NORMAL_ACTIVE | RIBBON_BUTTONBAR_BUTTON_DROPDOWN_ACTIVE
+RIBBON_BUTTONBAR_BUTTON_DISABLED = 1 << 7
+RIBBON_BUTTONBAR_BUTTON_TOGGLED = 1 << 8
+RIBBON_BUTTONBAR_BUTTON_STATE_MASK = 0x1F8
+
+
+# RibbonGalleryButtonState
+RIBBON_GALLERY_BUTTON_NORMAL = 1
+RIBBON_GALLERY_BUTTON_HOVERED = 2
+RIBBON_GALLERY_BUTTON_ACTIVE = 3
+RIBBON_GALLERY_BUTTON_DISABLED = 4
+
+
+RIBBON_BAR_SHOW_PAGE_LABELS = 1 << 0
+RIBBON_BAR_SHOW_PAGE_ICONS = 1 << 1
+RIBBON_BAR_FLOW_HORIZONTAL = 0
+RIBBON_BAR_FLOW_VERTICAL = 1 << 2
+RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS = 1 << 3
+RIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS = 1 << 4
+RIBBON_BAR_ALWAYS_SHOW_TABS = 1 << 5
+
+
+RIBBON_BAR_DEFAULT_STYLE = RIBBON_BAR_FLOW_HORIZONTAL | RIBBON_BAR_SHOW_PAGE_LABELS \
+ | RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS
+
+RIBBON_BAR_FOLDBAR_STYLE = RIBBON_BAR_FLOW_VERTICAL | RIBBON_BAR_SHOW_PAGE_ICONS \
+ | RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS \
+ | RIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS
+
+RIBBON_TOOLBAR_TOOL_FIRST = 1 << 0
+RIBBON_TOOLBAR_TOOL_LAST = 1 << 1
+RIBBON_TOOLBAR_TOOL_POSITION_MASK = RIBBON_TOOLBAR_TOOL_FIRST | RIBBON_TOOLBAR_TOOL_LAST
+
+RIBBON_TOOLBAR_TOOL_NORMAL_HOVERED = 1 << 3
+RIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED = 1 << 4
+RIBBON_TOOLBAR_TOOL_HOVER_MASK = RIBBON_TOOLBAR_TOOL_NORMAL_HOVERED | RIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED
+RIBBON_TOOLBAR_TOOL_NORMAL_ACTIVE = 1 << 5
+RIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE = 1 << 6
+RIBBON_TOOLBAR_TOOL_ACTIVE_MASK = RIBBON_TOOLBAR_TOOL_NORMAL_ACTIVE | RIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE
+RIBBON_TOOLBAR_TOOL_DISABLED = 1 << 7
+RIBBON_TOOLBAR_TOOL_TOGGLED = 1 << 8
+RIBBON_TOOLBAR_TOOL_STATE_MASK = 0x1F8
+
+RIBBON_PANEL_NO_AUTO_MINIMISE = 1 << 0
+RIBBON_PANEL_EXT_BUTTON = 1 << 3
+RIBBON_PANEL_MINIMISE_BUTTON = 1 << 4
+RIBBON_PANEL_STRETCH = 1 << 5
+RIBBON_PANEL_FLEXIBLE = 1 << 6
+
+RIBBON_PANEL_DEFAULT_STYLE = 0
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_aui.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_aui.py
new file mode 100644
index 0000000..f63459a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_aui.py
@@ -0,0 +1,1260 @@
+"""
+`art_aui` is responsible for drawing all the components of the ribbon
+interface using an AUI-compatible appearance.
+
+
+Description
+===========
+
+This allows a ribbon bar to have a pluggable look-and-feel, while retaining the same
+underlying behaviour. As a single art provider is used for all ribbon components, a
+ribbon bar usually has a consistent (though unique) appearance.
+
+By default, a :class:`~lib.agw.ribbon.bar.RibbonBar` uses an instance of a class called
+:class:`~lib.agw.ribbon.art_default.RibbonDefaultArtProvider`,
+which resolves to :class:`~lib.agw.ribbon.art_aui.RibbonAUIArtProvider`,
+:class:`~lib.agw.ribbon.art_msw.RibbonMSWArtProvider`, or
+:class:`~lib.agw.ribbon.art_osx.RibbonOSXArtProvider` - whichever is most appropriate
+to the current platform. These art providers are all
+slightly configurable with regard to colours and fonts, but for larger modifications,
+you can derive from one of these classes, or write a completely new art provider class.
+
+Call :meth:`RibbonBar.SetArtProvider() <lib.agw.ribbon.bar.RibbonBar.SetArtProvider>` to change the art provider being used.
+
+
+See Also
+========
+
+:class:`~lib.agw.ribbon.bar.RibbonBar`
+"""
+
+import wx
+
+from math import cos
+from math import pi as M_PI
+
+from art_msw import RibbonMSWArtProvider
+from art_internal import RibbonHSLColour, RibbonShiftLuminance, RibbonInterpolateColour
+
+import bar as BAR, panel as PANEL
+
+from art import *
+
+if wx.Platform == "__WXMAC__":
+ import Carbon.Appearance
+
+
+def FontFromFont(original):
+
+ newFont = wx.Font(original.GetPointSize(), original.GetFamily(),
+ original.GetStyle(), original.GetWeight(), original.GetUnderlined(),
+ original.GetFaceName(), original.GetEncoding())
+
+ return newFont
+
+
+class RibbonAUIArtProvider(RibbonMSWArtProvider):
+
+ def __init__(self):
+
+ RibbonMSWArtProvider.__init__(self)
+
+ if wx.Platform == "__WXMAC__":
+
+ if hasattr(wx, 'MacThemeColour'):
+ base_colour = wx.MacThemeColour(Carbon.Appearance.kThemeBrushToolbarBackground)
+ else:
+ brush = wx.Brush(wx.BLACK)
+ brush.MacSetTheme(Carbon.Appearance.kThemeBrushToolbarBackground)
+ base_colour = brush.GetColour()
+ else:
+
+ base_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
+
+ self.SetColourScheme(base_colour, wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT),
+ wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
+
+ self._tab_active_label_font = FontFromFont(self._tab_label_font)
+ self._tab_active_label_font.SetWeight(wx.FONTWEIGHT_BOLD)
+
+ self._page_border_left = 1
+ self._page_border_right = 1
+ self._page_border_top = 1
+ self._page_border_bottom = 2
+ self._tab_separation_size = 0
+
+ self._gallery_bitmap_padding_left_size = 3
+ self._gallery_bitmap_padding_right_size = 3
+ self._gallery_bitmap_padding_top_size = 3
+ self._gallery_bitmap_padding_bottom_size = 3
+
+
+ def Clone(self):
+ """
+ Create a new art provider which is a clone of this one.
+ """
+
+ copy = RibbonAUIArtProvider()
+ self.CloneTo(copy)
+
+ copy._tab_ctrl_background_colour = self._tab_ctrl_background_colour
+ copy._tab_ctrl_background_gradient_colour = self._tab_ctrl_background_gradient_colour
+ copy._panel_label_background_colour = self._panel_label_background_colour
+ copy._panel_label_background_gradient_colour = self._panel_label_background_gradient_colour
+ copy._panel_hover_label_background_colour = self._panel_hover_label_background_colour
+ copy._panel_hover_label_background_gradient_colour = self._panel_hover_label_background_gradient_colour
+
+ copy._background_brush = self._background_brush
+ copy._tab_active_top_background_brush = self._tab_active_top_background_brush
+ copy._tab_hover_background_brush = self._tab_hover_background_brush
+ copy._button_bar_hover_background_brush = self._button_bar_hover_background_brush
+ copy._button_bar_active_background_brush = self._button_bar_active_background_brush
+ copy._gallery_button_active_background_brush = self._gallery_button_active_background_brush
+ copy._gallery_button_hover_background_brush = self._gallery_button_hover_background_brush
+ copy._gallery_button_disabled_background_brush = self._gallery_button_disabled_background_brush
+
+ copy._toolbar_hover_borden_pen = self._toolbar_hover_borden_pen
+ copy._tool_hover_background_brush = self._tool_hover_background_brush
+ copy._tool_active_background_brush = self._tool_active_background_brush
+
+ return copy
+
+
+ def SetFont(self, id, font):
+ """
+ Set the value of a certain font setting to the value.
+
+ can be one of the font values of `RibbonArtSetting`.
+
+ :param `id`: the font id;
+ :param `font`: MISSING DESCRIPTION.
+
+ """
+
+ RibbonMSWArtProvider.SetFont(self, id, font)
+
+ if id == RIBBON_ART_TAB_LABEL_FONT:
+ self._tab_active_label_font = FontFromFont(self._tab_label_font)
+ self._tab_active_label_font.SetWeight(wx.FONTWEIGHT_BOLD)
+
+
+ def GetColour(self, id):
+ """
+ Get the value of a certain colour setting.
+
+ can be one of the colour values of `RibbonArtSetting`.
+
+ :param `id`: the colour id.
+
+ """
+
+ if id in [RIBBON_ART_PAGE_BACKGROUND_COLOUR, RIBBON_ART_PAGE_BACKGROUND_GRADIENT_COLOUR]:
+ return self._background_brush.GetColour()
+ elif id == RIBBON_ART_TAB_CTRL_BACKGROUND_COLOUR:
+ return self._tab_ctrl_background_colour
+ elif id == RIBBON_ART_TAB_CTRL_BACKGROUND_GRADIENT_COLOUR:
+ return self._tab_ctrl_background_gradient_colour
+ elif id in [RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_COLOUR, RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR]:
+ return self._tab_active_top_background_brush.GetColour()
+ elif id in [RIBBON_ART_TAB_HOVER_BACKGROUND_COLOUR, RIBBON_ART_TAB_HOVER_BACKGROUND_GRADIENT_COLOUR]:
+ return self._tab_hover_background_brush.GetColour()
+ elif id == RIBBON_ART_PANEL_LABEL_BACKGROUND_COLOUR:
+ return self._panel_label_background_colour
+ elif id == RIBBON_ART_PANEL_LABEL_BACKGROUND_GRADIENT_COLOUR:
+ return self._panel_label_background_gradient_colour
+ elif id == RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_COLOUR:
+ return self._panel_hover_label_background_colour
+ elif id == RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_GRADIENT_COLOUR:
+ return self._panel_hover_label_background_gradient_colour
+ elif id in [RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_COLOUR, RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_GRADIENT_COLOUR]:
+ return self._button_bar_hover_background_brush.GetColour()
+ elif id in [RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_COLOUR, RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_GRADIENT_COLOUR]:
+ return self._gallery_button_hover_background_brush.GetColour()
+ elif id in [RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_COLOUR, RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_GRADIENT_COLOUR]:
+ return self._gallery_button_active_background_brush.GetColour()
+ elif id in [RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_COLOUR, RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_GRADIENT_COLOUR]:
+ return self._gallery_button_disabled_background_brush.GetColour()
+ else:
+ return RibbonMSWArtProvider.GetColour(self, id)
+
+
+ def SetColour(self, id, colour):
+ """
+ Set the value of a certain colour setting to the value.
+
+ can be one of the colour values of `RibbonArtSetting`, though not all colour
+ settings will have an affect on every art provider.
+
+ :param `id`: the colour id;
+ :param `colour`: MISSING DESCRIPTION.
+
+ :see: :meth:`~RibbonAUIArtProvider.SetColourScheme`
+ """
+
+ if id in [RIBBON_ART_PAGE_BACKGROUND_COLOUR, RIBBON_ART_PAGE_BACKGROUND_GRADIENT_COLOUR]:
+ self._background_brush.SetColour(colour)
+ elif id == RIBBON_ART_TAB_CTRL_BACKGROUND_COLOUR:
+ self._tab_ctrl_background_colour = colour
+ elif id == RIBBON_ART_TAB_CTRL_BACKGROUND_GRADIENT_COLOUR:
+ self._tab_ctrl_background_gradient_colour = colour
+ elif id in [RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_COLOUR, RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR]:
+ self._tab_active_top_background_brush.SetColour(colour)
+ elif id in [RIBBON_ART_TAB_HOVER_BACKGROUND_COLOUR, RIBBON_ART_TAB_HOVER_BACKGROUND_GRADIENT_COLOUR]:
+ self._tab_hover_background_brush.SetColour(colour)
+ elif id == RIBBON_ART_PANEL_LABEL_BACKGROUND_COLOUR:
+ self._panel_label_background_colour = colour
+ elif id == RIBBON_ART_PANEL_LABEL_BACKGROUND_GRADIENT_COLOUR:
+ self._panel_label_background_gradient_colour = colour
+ elif id in [RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_COLOUR, RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_GRADIENT_COLOUR]:
+ self._button_bar_hover_background_brush.SetColour(colour)
+ elif id in [RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_COLOUR, RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_GRADIENT_COLOUR]:
+ self._gallery_button_hover_background_brush.SetColour(colour)
+ elif id in [RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_COLOUR, RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_GRADIENT_COLOUR]:
+ self._gallery_button_active_background_brush.SetColour(colour)
+ elif id in [RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_COLOUR, RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_GRADIENT_COLOUR]:
+ self._gallery_button_disabled_background_brush.SetColour(colour)
+ else:
+ RibbonMSWArtProvider.SetColour(self, id, colour)
+
+
+ def SetColourScheme(self, primary, secondary, tertiary):
+ """
+ Set all applicable colour settings from a few base colours.
+
+ Uses any or all of the three given colours to create a colour scheme, and then
+ sets all colour settings which are relevant to the art provider using that
+ scheme. Note that some art providers may not use the tertiary colour for
+ anything, and some may not use the secondary colour either.
+
+ :param `primary`: MISSING DESCRIPTION;
+ :param `secondary`: MISSING DESCRIPTION;
+ :param `tertiary`: MISSING DESCRIPTION.
+
+ :see: :meth:`~RibbonAUIArtProvider.SetColour`, :meth:`RibbonMSWArtProvider.GetColourScheme() <RibbonMSWArtProvider.GetColourScheme>`
+ """
+
+ primary_hsl = RibbonHSLColour(primary)
+ secondary_hsl = RibbonHSLColour(secondary)
+ tertiary_hsl = RibbonHSLColour(tertiary)
+
+ # Map primary & secondary luminance from [0, 1] to [0.15, 0.85]
+ primary_hsl.luminance = cos(primary_hsl.luminance * M_PI) * -0.35 + 0.5
+ secondary_hsl.luminance = cos(secondary_hsl.luminance * M_PI) * -0.35 + 0.5
+
+ # TODO: Remove next line once this provider stops piggybacking MSW
+ RibbonMSWArtProvider.SetColourScheme(self, primary, secondary, tertiary)
+
+ self._tab_ctrl_background_colour = RibbonShiftLuminance(primary_hsl, 0.9).ToRGB()
+ self._tab_ctrl_background_gradient_colour = RibbonShiftLuminance(primary_hsl, 1.7).ToRGB()
+ self._tab_border_pen = wx.Pen(RibbonShiftLuminance(primary_hsl, 0.75).ToRGB())
+ self._tab_label_colour = RibbonShiftLuminance(primary_hsl, 0.1).ToRGB()
+ self._tab_hover_background_top_colour = primary_hsl.ToRGB()
+ self._tab_hover_background_top_gradient_colour = RibbonShiftLuminance(primary_hsl, 1.6).ToRGB()
+ self._tab_hover_background_brush = wx.Brush(self._tab_hover_background_top_colour)
+ self._tab_active_background_colour = self._tab_ctrl_background_gradient_colour
+ self._tab_active_background_gradient_colour = primary_hsl.ToRGB()
+ self._tab_active_top_background_brush = wx.Brush(self._tab_active_background_colour)
+ self._panel_label_colour = self._tab_label_colour
+ self._panel_minimised_label_colour = self._panel_label_colour
+ self._panel_hover_label_colour = tertiary_hsl.ToRGB()
+ self._page_border_pen = self._tab_border_pen
+ self._panel_border_pen = self._tab_border_pen
+ self._background_brush = wx.Brush(primary_hsl.ToRGB())
+ self._page_hover_background_colour = RibbonShiftLuminance(primary_hsl, 1.5).ToRGB()
+ self._page_hover_background_gradient_colour = RibbonShiftLuminance(primary_hsl, 0.9).ToRGB()
+ self._panel_label_background_colour = RibbonShiftLuminance(primary_hsl, 0.85).ToRGB()
+ self._panel_label_background_gradient_colour = RibbonShiftLuminance(primary_hsl, 0.97).ToRGB()
+ self._panel_hover_label_background_gradient_colour = secondary_hsl.ToRGB()
+ self._panel_hover_label_background_colour = secondary_hsl.Lighter(0.2).ToRGB()
+ self._button_bar_hover_border_pen = wx.Pen(secondary_hsl.ToRGB())
+ self._button_bar_hover_background_brush = wx.Brush(RibbonShiftLuminance(secondary_hsl, 1.7).ToRGB())
+ self._button_bar_active_background_brush = wx.Brush(RibbonShiftLuminance(secondary_hsl, 1.4).ToRGB())
+ self._button_bar_label_colour = self._tab_label_colour
+ self._gallery_border_pen = self._tab_border_pen
+ self._gallery_item_border_pen = self._button_bar_hover_border_pen
+ self._gallery_hover_background_brush = wx.Brush(RibbonShiftLuminance(primary_hsl, 1.2).ToRGB())
+ self._gallery_button_background_colour = self._page_hover_background_colour
+ self._gallery_button_background_gradient_colour = self._page_hover_background_gradient_colour
+ self._gallery_button_hover_background_brush = self._button_bar_hover_background_brush
+ self._gallery_button_active_background_brush = self._button_bar_active_background_brush
+ self._gallery_button_disabled_background_brush = wx.Brush(primary_hsl.Desaturated(0.15).ToRGB())
+ self.SetColour(RIBBON_ART_GALLERY_BUTTON_FACE_COLOUR, RibbonShiftLuminance(primary_hsl, 0.1).ToRGB())
+ self.SetColour(RIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR, wx.Colour(128, 128, 128))
+ self.SetColour(RIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR, RibbonShiftLuminance(secondary_hsl, 0.1).ToRGB())
+ self.SetColour(RIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR, RibbonShiftLuminance(secondary_hsl, 0.1).ToRGB())
+ self._toolbar_border_pen = self._tab_border_pen
+ self.SetColour(RIBBON_ART_TOOLBAR_FACE_COLOUR, RibbonShiftLuminance(primary_hsl, 0.1).ToRGB())
+ self._tool_background_colour = self._page_hover_background_colour
+ self._tool_background_gradient_colour = self._page_hover_background_gradient_colour
+ self._toolbar_hover_borden_pen = self._button_bar_hover_border_pen
+ self._tool_hover_background_brush = self._button_bar_hover_background_brush
+ self._tool_active_background_brush = self._button_bar_active_background_brush
+
+
+ def DrawTabCtrlBackground(self, dc, wnd, rect):
+ """
+ Draw the background of the tab region of a ribbon bar.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto;
+ :param `rect`: The rectangle within which to draw.
+
+ """
+
+ gradient_rect = wx.Rect(*rect)
+ gradient_rect.height -= 1
+ dc.GradientFillLinear(gradient_rect, self._tab_ctrl_background_colour, self._tab_ctrl_background_gradient_colour, wx.SOUTH)
+ dc.SetPen(self._tab_border_pen)
+ dc.DrawLine(rect.x, rect.GetBottom(), rect.GetRight()+1, rect.GetBottom())
+
+
+ def GetTabCtrlHeight(self, dc, wnd, pages):
+ """
+ Calculate the height (in pixels) of the tab region of a ribbon bar.
+
+ Note that as the tab region can contain scroll buttons, the height should be
+ greater than or equal to the minimum height for a tab scroll button.
+
+ :param `dc`: A device context to use when one is required for size calculations;
+ :param `wnd`: The window onto which the tabs will eventually be drawn;
+ :param `pages`: The tabs which will acquire the returned height.
+
+ """
+
+ text_height = 0
+ icon_height = 0
+
+ if len(pages) <= 1 and (self._flags & RIBBON_BAR_ALWAYS_SHOW_TABS) == 0:
+ # To preserve space, a single tab need not be displayed. We still need
+ # one pixel of border though.
+ return 1
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS:
+ dc.SetFont(self._tab_active_label_font)
+ text_height = dc.GetTextExtent("ABCDEFXj")[1]
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS:
+ for info in pages:
+ if info.page.GetIcon().IsOk():
+ icon_height = max(icon_height, info.page.GetIcon().GetHeight())
+
+ return max(text_height, icon_height) + 10
+
+
+ def DrawTab(self, dc, wnd, tab):
+ """
+ Draw a single tab in the tab region of a ribbon bar.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto (not the :class:`~lib.agw.ribbon.page.RibbonPage`
+ associated with the tab being drawn);
+ :param `tab`: The rectangle within which to draw, and also the tab label,
+ icon, and state (active and/or hovered). The drawing rectangle will be
+ entirely within a rectangle on the same device context previously painted
+ with :meth:`~RibbonAUIArtProvider.DrawTabCtrlBackground`. The rectangle's width will be at least the
+ minimum value returned by :meth:`~RibbonAUIArtProvider.GetBarTabWidth`, and height will be the value
+ returned by :meth:`~RibbonAUIArtProvider.GetTabCtrlHeight`.
+
+ """
+
+ if tab.rect.height <= 1:
+ return
+
+ dc.SetFont(self._tab_label_font)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ if tab.active or tab.hovered:
+ if tab.active:
+ dc.SetFont(self._tab_active_label_font)
+ dc.SetBrush(self._background_brush)
+ dc.DrawRectangle(tab.rect.x, tab.rect.y + tab.rect.height - 1, tab.rect.width - 1, 1)
+
+ grad_rect = wx.Rect(*tab.rect)
+ grad_rect.height -= 4
+ grad_rect.width -= 1
+ grad_rect.height /= 2
+ grad_rect.y = grad_rect.y + tab.rect.height - grad_rect.height - 1
+ dc.SetBrush(self._tab_active_top_background_brush)
+ dc.DrawRectangle(tab.rect.x, tab.rect.y + 3, tab.rect.width - 1, grad_rect.y - tab.rect.y - 3)
+ dc.GradientFillLinear(grad_rect, self._tab_active_background_colour, self._tab_active_background_gradient_colour, wx.SOUTH)
+
+ else:
+
+ btm_rect = wx.Rect(*tab.rect)
+ btm_rect.height -= 4
+ btm_rect.width -= 1
+ btm_rect.height /= 2
+ btm_rect.y = btm_rect.y + tab.rect.height - btm_rect.height - 1
+ dc.SetBrush(self._tab_hover_background_brush)
+ dc.DrawRectangle(btm_rect.x, btm_rect.y, btm_rect.width, btm_rect.height)
+ grad_rect = wx.Rect(*tab.rect)
+ grad_rect.width -= 1
+ grad_rect.y += 3
+ grad_rect.height = btm_rect.y - grad_rect.y
+ dc.GradientFillLinear(grad_rect, self._tab_hover_background_top_colour, self._tab_hover_background_top_gradient_colour, wx.SOUTH)
+
+ border_points = [wx.Point() for i in xrange(5)]
+ border_points[0] = wx.Point(0, 3)
+ border_points[1] = wx.Point(1, 2)
+ border_points[2] = wx.Point(tab.rect.width - 3, 2)
+ border_points[3] = wx.Point(tab.rect.width - 1, 4)
+ border_points[4] = wx.Point(tab.rect.width - 1, tab.rect.height - 1)
+
+ dc.SetPen(self._tab_border_pen)
+ dc.DrawLines(border_points, tab.rect.x, tab.rect.y)
+
+ old_clip = dc.GetClippingRect()
+ is_first_tab = False
+
+ bar = tab.page.GetParent()
+ icon = wx.NullBitmap
+
+ if isinstance(bar, BAR.RibbonBar) and bar.GetPage(0) == tab.page:
+ is_first_tab = True
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS:
+ icon = tab.page.GetIcon()
+ if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS == 0:
+ if icon.IsOk():
+ x = tab.rect.x + (tab.rect.width - icon.GetWidth()) / 2
+ dc.DrawBitmap(icon, x, tab.rect.y + 1 + (tab.rect.height - 1 - icon.GetHeight()) / 2, True)
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS:
+ label = tab.page.GetLabel()
+
+ if label.strip():
+ dc.SetTextForeground(self._tab_label_colour)
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+
+ offset = 0
+
+ if icon.IsOk():
+ offset += icon.GetWidth() + 2
+
+ text_width, text_height = dc.GetTextExtent(label)
+ x = (tab.rect.width - 2 - text_width - offset) / 2
+ if x > 8:
+ x = 8
+ elif x < 1:
+ x = 1
+
+ width = tab.rect.width - x - 2
+ x += tab.rect.x + offset
+ y = tab.rect.y + (tab.rect.height - text_height) / 2
+
+ if icon.IsOk():
+ dc.DrawBitmap(icon, x - offset, tab.rect.y + (tab.rect.height - icon.GetHeight()) / 2, True)
+
+ dc.SetClippingRegion(x, tab.rect.y, width, tab.rect.height)
+ dc.DrawText(label, x, y)
+
+ # Draw the left hand edge of the tab only for the first tab (subsequent
+ # tabs use the right edge of the prior tab as their left edge). As this is
+ # outside the rectangle for the tab, only draw it if the leftmost part of
+ # the tab is within the clip rectangle (the clip region has to be cleared
+ # to draw outside the tab).
+ if is_first_tab and old_clip.x <= tab.rect.x and tab.rect.x < old_clip.x + old_clip.width:
+ dc.DestroyClippingRegion()
+ dc.DrawLine(tab.rect.x - 1, tab.rect.y + 4, tab.rect.x - 1, tab.rect.y + tab.rect.height - 1)
+
+
+ def GetBarTabWidth(self, dc, wnd, label, bitmap, ideal=None, small_begin_need_separator=None,
+ small_must_have_separator=None, minimum=None):
+ """
+ Calculate the ideal and minimum width (in pixels) of a tab in a ribbon bar.
+
+ :param `dc`: A device context to use when one is required for size calculations;
+ :param `wnd`: The window onto which the tab will eventually be drawn;
+ :param `label`: The tab's label (or an empty string if it has none);
+ :param `bitmap`: The tab's icon (or :class:`NullBitmap` if it has none);
+ :param `ideal`: The ideal width (in pixels) of the tab;
+ :param `small_begin_need_separator`: A size less than the size, at which a tab
+ separator should begin to be drawn (i.e. drawn, but still fairly transparent);
+ :param `small_must_have_separator`: A size less than the size, at which a tab
+ separator must be drawn (i.e. drawn at full opacity);
+ :param `minimum`: A size less than the size, and greater than or equal to zero,
+ which is the minimum pixel width for the tab.
+
+ """
+
+ width = mini = 0
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS and label.strip():
+ dc.SetFont(self._tab_active_label_font)
+ width += dc.GetTextExtent(label)[0]
+ mini += min(30, width) # enough for a few chars
+
+ if bitmap.IsOk():
+ # gap between label and bitmap
+ width += 4
+ mini += 2
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS and bitmap.IsOk():
+ width += bitmap.GetWidth()
+ mini += bitmap.GetWidth()
+
+ ideal = width + 16
+ small_begin_need_separator = mini
+ small_must_have_separator = mini
+ minimum = mini
+
+ return ideal, small_begin_need_separator, small_must_have_separator, minimum
+
+
+ def DrawTabSeparator(self, dc, wnd, rect, visibility):
+ """
+ Draw a separator between two tabs in a ribbon bar.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto;
+ :param `rect`: The rectangle within which to draw, which will be entirely
+ within a rectangle on the same device context previously painted with
+ :meth:`~RibbonAUIArtProvider.DrawTabCtrlBackground`;
+ :param `visibility`: The opacity with which to draw the separator. Values
+ are in the range [0, 1], with 0 being totally transparent, and 1 being totally
+ opaque.
+
+ """
+
+ # No explicit separators between tabs
+ pass
+
+
+ def DrawPageBackground(self, dc, wnd, rect):
+ """
+ Draw the background of a ribbon page.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto (which is commonly the
+ :class:`~lib.agw.ribbon.page.RibbonPage` whose background is being drawn, but doesn't have to be);
+ :param `rect`: The rectangle within which to draw.
+
+ :see: :meth:`RibbonMSWArtProvider.GetPageBackgroundRedrawArea() <RibbonMSWArtProvider.GetPageBackgroundRedrawArea>`
+ """
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._background_brush)
+ dc.DrawRectangle(rect.x + 1, rect.y, rect.width - 2, rect.height - 1)
+
+ dc.SetPen(self._page_border_pen)
+ dc.DrawLine(rect.x, rect.y, rect.x, rect.y + rect.height)
+ dc.DrawLine(rect.GetRight(), rect.y, rect.GetRight(), rect.y +rect.height)
+ dc.DrawLine(rect.x, rect.GetBottom(), rect.GetRight()+1, rect.GetBottom())
+
+
+ def GetScrollButtonMinimumSize(self, dc, wnd, style):
+ """
+ Calculate the minimum size (in pixels) of a scroll button.
+
+ :param `dc`: A device context to use when one is required for size calculations;
+ :param `wnd`: The window onto which the scroll button will eventually be drawn;
+ :param `style`: A combination of flags from `RibbonScrollButtonStyle`, including
+ a direction, and a for flag (state flags may be given too, but should be ignored,
+ as a button should retain a constant size, regardless of its state).
+
+ """
+
+ return wx.Size(11, 11)
+
+
+ def DrawScrollButton(self, dc, wnd, rect, style):
+ """
+ Draw a ribbon-style scroll button.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto;
+ :param `rect`: The rectangle within which to draw. The size of this rectangle
+ will be at least the size returned by :meth:`~RibbonAUIArtProvider.GetScrollButtonMinimumSize` for a
+ scroll button with the same style. For tab scroll buttons, this rectangle
+ will be entirely within a rectangle on the same device context previously
+ painted with :meth:`~RibbonAUIArtProvider.DrawTabCtrlBackground`, but this is not guaranteed for other
+ types of button (for example, page scroll buttons will not be painted on
+ an area previously painted with :meth:`~RibbonAUIArtProvider.DrawPageBackground`);
+ :param `style`: A combination of flags from `RibbonScrollButtonStyle`,
+ including a direction, a for flag, and one or more states.
+
+ """
+
+ true_rect = wx.Rect(*rect)
+ arrow_points = [wx.Point() for i in xrange(3)]
+
+ if style & RIBBON_SCROLL_BTN_FOR_MASK == RIBBON_SCROLL_BTN_FOR_TABS:
+ true_rect.y += 2
+ true_rect.height -= 2
+ dc.SetPen(self._tab_border_pen)
+ else:
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._background_brush)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+ dc.SetPen(self._page_border_pen)
+
+ result = style & RIBBON_SCROLL_BTN_DIRECTION_MASK
+
+ if result == RIBBON_SCROLL_BTN_LEFT:
+ dc.DrawLine(true_rect.GetRight(), true_rect.y, true_rect.GetRight(), true_rect.y + true_rect.height)
+ arrow_points[0] = wx.Point(rect.width / 2 - 2, rect.height / 2)
+ arrow_points[1] = arrow_points[0] + wx.Point(5, -5)
+ arrow_points[2] = arrow_points[0] + wx.Point(5, 5)
+
+ elif result == RIBBON_SCROLL_BTN_RIGHT:
+ dc.DrawLine(true_rect.x, true_rect.y, true_rect.x, true_rect.y + true_rect.height)
+ arrow_points[0] = wx.Point(rect.width / 2 + 3, rect.height / 2)
+ arrow_points[1] = arrow_points[0] - wx.Point(5, -5)
+ arrow_points[2] = arrow_points[0] - wx.Point(5, 5)
+
+ elif result == RIBBON_SCROLL_BTN_DOWN:
+ dc.DrawLine(true_rect.x, true_rect.y, true_rect.x + true_rect.width, true_rect.y)
+ arrow_points[0] = wx.Point(rect.width / 2, rect.height / 2 + 3)
+ arrow_points[1] = arrow_points[0] - wx.Point( 5, 5)
+ arrow_points[2] = arrow_points[0] - wx.Point(-5, 5)
+
+ elif result == RIBBON_SCROLL_BTN_UP:
+ dc.DrawLine(true_rect.x, true_rect.GetBottom(), true_rect.x + true_rect.width, true_rect.GetBottom())
+ arrow_points[0] = wx.Point(rect.width / 2, rect.height / 2 - 2)
+ arrow_points[1] = arrow_points[0] + wx.Point( 5, 5)
+ arrow_points[2] = arrow_points[0] + wx.Point(-5, 5)
+
+ else:
+ return
+
+ x = rect.x
+ y = rect.y
+
+ if style & RIBBON_SCROLL_BTN_ACTIVE:
+ x += 1
+ y += 1
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ B = wx.Brush(self._tab_label_colour)
+ dc.SetBrush(B)
+ dc.DrawPolygon(arrow_points, x, y)
+
+
+ def GetPanelSize(self, dc, wnd, client_size, client_offset=None):
+ """
+ Calculate the size of a panel for a given client size.
+
+ This should increment the given size by enough to fit the panel label and other
+ chrome.
+
+ :param `dc`: A device context to use if one is required for size calculations;
+ :param `wnd`: The ribbon panel in question;
+ :param `client_size`: The client size;
+ :param `client_offset`: The offset where the client rectangle begins within
+ the panel (may be ``None``).
+
+ :see: :meth:`~RibbonAUIArtProvider.GetPanelClientSize`
+ """
+
+ dc.SetFont(self._panel_label_font)
+ label_size = wx.Size(*dc.GetTextExtent(wnd.GetLabel()))
+ label_height = label_size.GetHeight() + 5
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ client_size.IncBy(4, label_height + 6)
+ if client_offset is not None:
+ client_offset = wx.Point(2, label_height + 3)
+
+ else:
+ client_size.IncBy(6, label_height + 4)
+ if client_offset is not None:
+ client_offset = wx.Point(3, label_height + 2)
+
+ return client_size
+
+
+ def GetPanelClientSize(self, dc, wnd, size, client_offset=None):
+ """
+ Calculate the client size of a panel for a given overall size.
+
+ This should act as the inverse to :meth:`~RibbonAUIArtProvider.GetPanelSize`, and decrement the given size
+ by enough to fit the panel label and other chrome.
+
+ :param `dc`: A device context to use if one is required for size calculations;
+ :param `wnd`: The ribbon panel in question;
+ :param `size`: The overall size to calculate client size for;
+ :param `client_offset`: The offset where the returned client size begins within
+ the given (may be ``None``).
+
+ :see: :meth:`~RibbonAUIArtProvider.GetPanelSize`
+ """
+
+ dc.SetFont(self._panel_label_font)
+ label_size = wx.Size(*dc.GetTextExtent(wnd.GetLabel()))
+ label_height = label_size.GetHeight() + 5
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ size.DecBy(4, label_height + 6)
+ if client_offset is not None:
+ client_offset = wx.Point(2, label_height + 3)
+
+ else:
+ size.DecBy(6, label_height + 4)
+ if client_offset is not None:
+ client_offset = wx.Point(3, label_height + 2)
+
+ if size.x < 0:
+ size.x = 0
+ if size.y < 0:
+ size.y = 0
+
+ return size, client_offset
+
+
+ def GetPanelExtButtonArea(self, dc, wnd, rect):
+ """
+ Retrieve the extension button area rectangle.
+
+ :param `dc`: The device context used to measure text extents;
+ :param `wnd`: The panel where the extension button resides;
+ :param `rect`: The panel client rectangle.
+ """
+
+ true_rect = wx.Rect(*rect)
+ true_rect = self.RemovePanelPadding(true_rect)
+
+ true_rect.x += 1
+ true_rect.width -= 2
+ true_rect.y += 1
+
+ dc.SetFont(self._panel_label_font)
+ label_size = dc.GetTextExtent(wnd.GetLabel())
+ label_height = label_size[1] + 5
+ label_rect = wx.Rect(*true_rect)
+ label_rect.height = label_height - 1
+
+ rect = wx.Rect(label_rect.GetRight()-13, label_rect.GetBottom()-13, 13, 13)
+ return rect
+
+
+ def DrawPanelBackground(self, dc, wnd, rect):
+ """
+ Draw the background and chrome for a ribbon panel.
+
+ This should draw the border, background, label, and any other items of a panel
+ which are outside the client area of a panel. Note that when a panel is
+ minimised, this function is not called - only :meth:`~RibbonAUIArtProvider.DrawMinimisedPanel` is called,
+ so a background should be explicitly painted by that if required.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto, which is always the panel
+ whose background and chrome is being drawn. The panel label and other panel
+ attributes can be obtained by querying this;
+ :param `rect`: The rectangle within which to draw.
+
+ """
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._background_brush)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ true_rect = wx.Rect(*rect)
+ true_rect = self.RemovePanelPadding(true_rect)
+
+ dc.SetPen(self._panel_border_pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(true_rect.x, true_rect.y, true_rect.width, true_rect.height)
+
+ true_rect.x += 1
+ true_rect.width -= 2
+ true_rect.y += 1
+
+ dc.SetFont(self._panel_label_font)
+ label_size = wx.Size(*dc.GetTextExtent(wnd.GetLabel()))
+ label_height = label_size.GetHeight() + 5
+ label_rect = wx.Rect(*true_rect)
+ label_rect.height = label_height - 1
+
+ dc.DrawLine(label_rect.x, label_rect.y + label_rect.height, label_rect.x + label_rect.width, label_rect.y + label_rect.height)
+
+ label_bg_colour = self._panel_label_background_colour
+ label_bg_grad_colour = self._panel_label_background_gradient_colour
+
+ if wnd.IsHovered():
+ label_bg_colour = self._panel_hover_label_background_colour
+ label_bg_grad_colour = self._panel_hover_label_background_gradient_colour
+ dc.SetTextForeground(self._panel_hover_label_colour)
+ else:
+ dc.SetTextForeground(self._panel_label_colour)
+
+ if wx.Platform == "__WXMAC__":
+ dc.GradientFillLinear(label_rect, label_bg_grad_colour, label_bg_colour, wx.SOUTH)
+ else:
+ dc.GradientFillLinear(label_rect, label_bg_colour, label_bg_grad_colour, wx.SOUTH)
+
+ dc.SetFont(self._panel_label_font)
+ dc.DrawText(wnd.GetLabel(), label_rect.x + 3, label_rect.y + 2)
+
+ if wnd.IsHovered():
+
+ gradient_rect = wx.Rect(*true_rect)
+ gradient_rect.y += label_rect.height + 1
+ gradient_rect.height = true_rect.height - label_rect.height - 3
+ if wx.Platform == "__WXMAC__":
+ colour = self._page_hover_background_gradient_colour
+ gradient = self._page_hover_background_colour
+ else:
+ colour = self._page_hover_background_colour
+ gradient = self._page_hover_background_gradient_colour
+
+ dc.GradientFillLinear(gradient_rect, colour, gradient, wx.SOUTH)
+
+ if wnd.HasExtButton():
+ if wnd.IsExtButtonHovered():
+ dc.SetPen(self._panel_hover_button_border_pen)
+ dc.SetBrush(self._panel_hover_button_background_brush)
+ dc.DrawRoundedRectangle(label_rect.GetRight() - 13, label_rect.GetBottom() - 13, 13, 13, 1)
+ dc.DrawBitmap(self._panel_extension_bitmap[1], label_rect.GetRight() - 10, label_rect.GetBottom() - 10, True)
+
+ else:
+ dc.DrawBitmap(self._panel_extension_bitmap[0], label_rect.GetRight() - 10, label_rect.GetBottom() - 10, True)
+
+
+ def DrawMinimisedPanel(self, dc, wnd, rect, bitmap):
+ """
+ Draw a minimised ribbon panel.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto, which is always the panel
+ which is minimised. The panel label can be obtained from this window. The
+ minimised icon obtained from querying the window may not be the size requested
+ by :meth:`RibbonMSWArtProvider.GetMinimisedPanelMinimumSize() <RibbonMSWArtProvider.GetMinimisedPanelMinimumSize>` - the argument contains the icon in the
+ requested size;
+ :param `rect`: The rectangle within which to draw. The size of the rectangle
+ will be at least the size returned by :meth:`RibbonMSWArtProvider.GetMinimisedPanelMinimumSize() <RibbonMSWArtProvider.GetMinimisedPanelMinimumSize>`;
+ :param `bitmap`: A copy of the panel's minimised bitmap rescaled to the size
+ returned by :meth:`RibbonMSWArtProvider.GetMinimisedPanelMinimumSize() <RibbonMSWArtProvider.GetMinimisedPanelMinimumSize>`.
+
+ """
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._background_brush)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ true_rect = wx.Rect(*rect)
+ true_rect = self.RemovePanelPadding(true_rect)
+
+ dc.SetPen(self._panel_border_pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(true_rect.x, true_rect.y, true_rect.width, true_rect.height)
+ true_rect.Deflate(1, 1)
+
+ if wnd.IsHovered() or wnd.GetExpandedPanel():
+ colour = self._page_hover_background_colour
+ gradient = self._page_hover_background_gradient_colour
+ if (wx.Platform == "__WXMAC__" and not wnd.GetExpandedPanel()) or \
+ (wx.Platform != "__WXMAC__" and wnd.GetExpandedPanel()):
+ temp = colour
+ colour = gradient
+ gradient = temp
+
+ dc.GradientFillLinear(true_rect, colour, gradient, wx.SOUTH)
+
+ preview = self.DrawMinimisedPanelCommon(dc, wnd, true_rect)
+
+ dc.SetPen(self._panel_border_pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(preview.x, preview.y, preview.width, preview.height)
+ preview.Deflate(1, 1)
+
+ preview_caption_rect = wx.Rect(*preview)
+ preview_caption_rect.height = 7
+ preview.y += preview_caption_rect.height
+ preview.height -= preview_caption_rect.height
+
+ if wx.Platform == "__WXMAC__":
+ dc.GradientFillLinear(preview_caption_rect, self._panel_hover_label_background_gradient_colour,
+ self._panel_hover_label_background_colour, wx.SOUTH)
+ dc.GradientFillLinear(preview, self._page_hover_background_gradient_colour,
+ self._page_hover_background_colour, wx.SOUTH)
+ else:
+ dc.GradientFillLinear(preview_caption_rect, self._panel_hover_label_background_colour,
+ self._panel_hover_label_background_gradient_colour, wx.SOUTH)
+ dc.GradientFillLinear(preview, self._page_hover_background_colour,
+ self._page_hover_background_gradient_colour, wx.SOUTH)
+
+ if bitmap.IsOk():
+ dc.DrawBitmap(bitmap, preview.x + (preview.width - bitmap.GetWidth()) / 2,
+ preview.y + (preview.height - bitmap.GetHeight()) / 2, True)
+
+
+ def DrawPartialPanelBackground(self, dc, wnd, rect):
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._background_brush)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ offset = wx.Point(*wnd.GetPosition())
+ parent = wnd.GetParent()
+ panel = None
+
+ while 1:
+ panel = parent
+ if isinstance(panel, PANEL.RibbonPanel):
+ if not panel.IsHovered():
+ return
+ break
+
+ offset += parent.GetPosition()
+ parent = panel.GetParent()
+
+ if panel is None:
+ return
+
+ background = wx.Rect(0, 0, *panel.GetSize())
+ background = self.RemovePanelPadding(background)
+
+ background.x += 1
+ background.width -= 2
+ dc.SetFont(self._panel_label_font)
+ caption_height = dc.GetTextExtent(panel.GetLabel())[1] + 7
+ background.y += caption_height - 1
+ background.height -= caption_height
+
+ paint_rect = wx.Rect(*rect)
+ paint_rect.x += offset.x
+ paint_rect.y += offset.y
+
+ if wx.Platform == "__WXMAC__":
+ bg_grad_clr = self._page_hover_background_colour
+ bg_clr = self._page_hover_background_gradient_colour
+ else:
+ bg_clr = self._page_hover_background_colour
+ bg_grad_clr = self._page_hover_background_gradient_colour
+
+ paint_rect.Intersect(background)
+
+ if not paint_rect.IsEmpty():
+ starting_colour = RibbonInterpolateColour(bg_clr, bg_grad_clr, paint_rect.y, background.y, background.y + background.height)
+ ending_colour = RibbonInterpolateColour(bg_clr, bg_grad_clr, paint_rect.y + paint_rect.height, background.y, background.y + background.height)
+ paint_rect.x -= offset.x
+ paint_rect.y -= offset.y
+ dc.GradientFillLinear(paint_rect, starting_colour, ending_colour, wx.SOUTH)
+
+
+ def DrawGalleryBackground(self, dc, wnd, rect):
+ """
+ Draw the background and chrome for a :class:`~lib.agw.ribbon.gallery.RibbonGallery` control.
+
+ This should draw the border, brackground, scroll buttons, extension button, and
+ any other UI elements which are not attached to a specific gallery item.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto, which is always the gallery
+ whose background and chrome is being drawn. Attributes used during drawing like
+ the gallery hover state and individual button states can be queried from this
+ parameter by :meth:`RibbonGallery.IsHovered() <RibbonGallery.IsHovered>`, :meth:`RibbonGallery.GetExtensionButtonState() <RibbonGallery.GetExtensionButtonState>`,
+ :meth:`RibbonGallery.GetUpButtonState() <RibbonGallery.GetUpButtonState>`, and :meth:`RibbonGallery.GetDownButtonState() <RibbonGallery.GetDownButtonState>`;
+ :param `rect`: The rectangle within which to draw. This rectangle is the entire
+ area of the gallery control, not just the client rectangle.
+
+ """
+
+ self.DrawPartialPanelBackground(dc, wnd, rect)
+
+ if wnd.IsHovered():
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._gallery_hover_background_brush)
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ dc.DrawRectangle(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 16)
+ else:
+ dc.DrawRectangle(rect.x + 1, rect.y + 1, rect.width - 16, rect.height - 2)
+
+ dc.SetPen(self._gallery_border_pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ self.DrawGalleryBackgroundCommon(dc, wnd, rect)
+
+
+ def DrawGalleryButton(self, dc, rect, state, bitmaps):
+
+ extra_height = 0
+ extra_width = 0
+ reduced_rect = wx.Rect(*rect)
+ reduced_rect.Deflate(1, 1)
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ reduced_rect.width += 1
+ extra_width = 1
+ else:
+ reduced_rect.height += 1
+ extra_height = 1
+
+ if state == RIBBON_GALLERY_BUTTON_NORMAL:
+ dc.GradientFillLinear(reduced_rect, self._gallery_button_background_colour, self._gallery_button_background_gradient_colour, wx.SOUTH)
+ btn_bitmap = bitmaps[0]
+
+ elif state == RIBBON_GALLERY_BUTTON_HOVERED:
+ dc.SetPen(self._gallery_item_border_pen)
+ dc.SetBrush(self._gallery_button_hover_background_brush)
+ dc.DrawRectangle(rect.x, rect.y, rect.width + extra_width, rect.height + extra_height)
+ btn_bitmap = bitmaps[1]
+
+ elif state == RIBBON_GALLERY_BUTTON_ACTIVE:
+ dc.SetPen(self._gallery_item_border_pen)
+ dc.SetBrush(self._gallery_button_active_background_brush)
+ dc.DrawRectangle(rect.x, rect.y, rect.width + extra_width, rect.height + extra_height)
+ btn_bitmap = bitmaps[2]
+
+ elif state == RIBBON_GALLERY_BUTTON_DISABLED:
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._gallery_button_disabled_background_brush)
+ dc.DrawRectangle(reduced_rect.x, reduced_rect.y, reduced_rect.width, reduced_rect.height)
+ btn_bitmap = bitmaps[3]
+
+ dc.DrawBitmap(btn_bitmap, reduced_rect.x + reduced_rect.width / 2 - 2, (rect.y + rect.height / 2) - 2, True)
+
+
+ def DrawGalleryItemBackground(self, dc, wnd, rect, item):
+ """
+ Draw the background of a single item in a :class:`~lib.agw.ribbon.gallery.RibbonGallery` control.
+
+ This is painted on top of a gallery background, and behind the items bitmap.
+ Unlike :meth:`~RibbonAUIArtProvider.DrawButtonBarButton` and :meth:`~RibbonAUIArtProvider.DrawTool`, it is not expected to draw the
+ item bitmap - that is done by the gallery control itself.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto, which is always the gallery
+ which contains the item being drawn;
+ :param `rect`: The rectangle within which to draw. The size of this rectangle
+ will be the size of the item's bitmap, expanded by gallery item padding values
+ (``RIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE``, ``RIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE``,
+ ``RIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE``, and ``RIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE``).
+ The drawing rectangle will be entirely within a rectangle on the same device
+ context previously painted with :meth:`~RibbonAUIArtProvider.DrawGalleryBackground`;
+ :param `item`: The item whose background is being painted. Typically the
+ background will vary if the item is hovered, active, or selected;
+ :meth:`RibbonGallery.GetSelection() <RibbonGallery.GetSelection>`, :meth:`RibbonGallery.GetActiveItem() <RibbonGallery.GetActiveItem>`, and
+ :meth:`RibbonGallery.GetHoveredItem() <RibbonGallery.GetHoveredItem>` can be called to test if the given item is in one of these states.
+
+ """
+
+ if wnd.GetHoveredItem() != item and wnd.GetActiveItem() != item and wnd.GetSelection() != item:
+ return
+
+ dc.SetPen(self._gallery_item_border_pen)
+
+ if wnd.GetActiveItem() == item or wnd.GetSelection() == item:
+ dc.SetBrush(self._gallery_button_active_background_brush)
+ else:
+ dc.SetBrush(self._gallery_button_hover_background_brush)
+
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+
+ def DrawButtonBarBackground(self, dc, wnd, rect):
+ """
+ Draw the background for a :class:`~lib.agw.ribbon.buttonbar.RibbonButtonBar` control.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto (which will typically
+ be the button bar itself, though this is not guaranteed);
+ :param `rect`: The rectangle within which to draw.
+
+ """
+
+ self.DrawPartialPanelBackground(dc, wnd, rect)
+
+
+ def DrawButtonBarButton(self, dc, wnd, rect, kind, state, label, bitmap_large, bitmap_small):
+ """
+ Draw a single button for a :class:`~lib.agw.ribbon.buttonbar.RibbonButtonBar` control.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto;
+ :param `rect`: The rectangle within which to draw. The size of this rectangle
+ will be a size previously returned by :meth:`RibbonMSWArtProvider.GetButtonBarButtonSize() <RibbonMSWArtProvider.GetButtonBarButtonSize>`, and the
+ rectangle will be entirely within a rectangle on the same device context
+ previously painted with :meth:`~RibbonAUIArtProvider.DrawButtonBarBackground`;
+ :param `kind`: The kind of button to draw (normal, dropdown or hybrid);
+ :param `state`: Combination of a size flag and state flags from the
+ `RibbonButtonBarButtonState` enumeration;
+ :param `label`: The label of the button;
+ :param `bitmap_large`: The large bitmap of the button (or the large disabled
+ bitmap when ``RIBBON_BUTTONBAR_BUTTON_DISABLED`` is set in );
+ :param `bitmap_small`: The small bitmap of the button (or the small disabled
+ bitmap when ``RIBBON_BUTTONBAR_BUTTON_DISABLED`` is set in ).
+
+ """
+
+ if kind == RIBBON_BUTTON_TOGGLE:
+ kind = RIBBON_BUTTON_NORMAL
+ if state & RIBBON_BUTTONBAR_BUTTON_TOGGLED:
+ state ^= RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK
+
+ if state & (RIBBON_BUTTONBAR_BUTTON_HOVER_MASK | RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK):
+ dc.SetPen(self._button_bar_hover_border_pen)
+ bg_rect = wx.Rect(*rect)
+ bg_rect.Deflate(1, 1)
+
+ if kind == RIBBON_BUTTON_HYBRID:
+ result = state & RIBBON_BUTTONBAR_BUTTON_SIZE_MASK
+
+ if result == RIBBON_BUTTONBAR_BUTTON_LARGE:
+ iYBorder = rect.y + bitmap_large.GetHeight() + 4
+ partial_bg = wx.Rect(*rect)
+
+ if state & RIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED:
+ partial_bg.SetBottom(iYBorder - 1)
+ else:
+ partial_bg.height -= (iYBorder - partial_bg.y + 1)
+ partial_bg.y = iYBorder + 1
+
+ dc.DrawLine(rect.x, iYBorder, rect.x + rect.width, iYBorder)
+ bg_rect.Intersect(partial_bg)
+
+ elif result == RIBBON_BUTTONBAR_BUTTON_MEDIUM:
+ iArrowWidth = 9
+
+ if state & RIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED:
+ bg_rect.width -= iArrowWidth
+ dc.DrawLine(bg_rect.x + bg_rect.width, rect.y, bg_rect.x + bg_rect.width, rect.y + rect.height)
+ else:
+ iArrowWidth -= 1
+ bg_rect.x += bg_rect.width - iArrowWidth
+ bg_rect.width = iArrowWidth
+ dc.DrawLine(bg_rect.x - 1, rect.y, bg_rect.x - 1, rect.y + rect.height)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ if state & RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK:
+ dc.SetBrush(self._button_bar_active_background_brush)
+ else:
+ dc.SetBrush(self._button_bar_hover_background_brush)
+
+ dc.DrawRectangle(bg_rect.x, bg_rect.y, bg_rect.width, bg_rect.height)
+
+ dc.SetFont(self._button_bar_label_font)
+ dc.SetTextForeground(self._button_bar_label_colour)
+ self.DrawButtonBarButtonForeground(dc, rect, kind, state, label, bitmap_large, bitmap_small)
+
+
+ def DrawToolBarBackground(self, dc, wnd, rect):
+ """
+ Draw the background for a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar` control.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The which is being drawn onto. In most cases this will be
+ a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar`, but it doesn't have to be;
+ :param `rect`: The rectangle within which to draw. Some of this rectangle
+ will later be drawn over using :meth:`~RibbonAUIArtProvider.DrawToolGroupBackground` and :meth:`~RibbonAUIArtProvider.DrawTool`,
+ but not all of it will (unless there is only a single group of tools).
+
+ """
+
+ self.DrawPartialPanelBackground(dc, wnd, rect)
+
+
+ def DrawToolGroupBackground(self, dc, wnd, rect):
+ """
+ Draw the background for a group of tools on a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar` control.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto. In most cases this will
+ be a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar`, but it doesn't have to be;
+ :param `rect`: The rectangle within which to draw. This rectangle is a union
+ of the individual tools' rectangles. As there are no gaps between tools, this
+ rectangle will be painted over exactly once by calls to :meth:`~RibbonAUIArtProvider.DrawTool`. The
+ group background could therefore be painted by :meth:`~RibbonAUIArtProvider.DrawTool`, though it can be
+ conceptually easier and more efficient to draw it all at once here. The
+ rectangle will be entirely within a rectangle on the same device context
+ previously painted with :meth:`~RibbonAUIArtProvider.DrawToolBarBackground`.
+
+ """
+
+ dc.SetPen(self._toolbar_border_pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+ bg_rect = wx.Rect(*rect)
+ bg_rect.Deflate(1, 1)
+ dc.GradientFillLinear(bg_rect, self._tool_background_colour, self._tool_background_gradient_colour, wx.SOUTH)
+
+
+ def DrawTool(self, dc, wnd, rect, bitmap, kind, state):
+ """
+ Draw a single tool (for a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar` control).
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto. In most cases this will
+ be a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar`, but it doesn't have to be;
+ :param `rect`: The rectangle within which to draw. The size of this rectangle
+ will at least the size returned by :meth:`RibbonMSWArtProvider.GetToolSize() <RibbonMSWArtProvider.GetToolSize>`, and the height of it will
+ be equal for all tools within the same group. The rectangle will be entirely
+ within a rectangle on the same device context previously painted with
+ :meth:`~RibbonAUIArtProvider.DrawToolGroupBackground`;
+ :param `bitmap`: The bitmap to use as the tool's foreground. If the tool is a
+ hybrid or dropdown tool, then the foreground should also contain a standard
+ dropdown button;
+ :param `kind`: The kind of tool to draw (normal, dropdown, or hybrid);
+ :param `state`: A combination of `RibbonToolBarToolState` flags giving the
+ state of the tool and it's relative position within a tool group.
+
+ """
+
+ if kind == RIBBON_BUTTON_TOGGLE:
+ if state & RIBBON_TOOLBAR_TOOL_TOGGLED:
+ state ^= RIBBON_TOOLBAR_TOOL_ACTIVE_MASK
+
+ bg_rect = wx.Rect(*rect)
+ bg_rect.Deflate(1, 1)
+
+ if state & RIBBON_TOOLBAR_TOOL_LAST == 0:
+ bg_rect.width += 1
+
+ is_custom_bg = (state & (RIBBON_TOOLBAR_TOOL_HOVER_MASK | RIBBON_TOOLBAR_TOOL_ACTIVE_MASK)) != 0
+ is_split_hybrid = kind == RIBBON_BUTTON_HYBRID and is_custom_bg
+
+ # Background
+ if is_custom_bg:
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._tool_hover_background_brush)
+ dc.DrawRectangle(bg_rect.x, bg_rect.y, bg_rect.width, bg_rect.height)
+
+ if state & RIBBON_TOOLBAR_TOOL_ACTIVE_MASK:
+ active_rect = wx.Rect(*bg_rect)
+
+ if kind == RIBBON_BUTTON_HYBRID:
+ active_rect.width -= 8
+
+ if state & RIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE:
+ active_rect.x += active_rect.width
+ active_rect.width = 8
+
+ dc.SetBrush(self._tool_active_background_brush)
+ dc.DrawRectangle(active_rect.x, active_rect.y, active_rect.width, active_rect.height)
+
+ # Border
+ if is_custom_bg:
+ dc.SetPen(self._toolbar_hover_borden_pen)
+ else:
+ dc.SetPen(self._toolbar_border_pen)
+
+ if state & RIBBON_TOOLBAR_TOOL_FIRST == 0:
+ existing = dc.GetPixel(rect.x, rect.y + 1)
+
+ if existing == wx.NullColour or existing != self._toolbar_hover_borden_pen.GetColour():
+ dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1)
+
+ if is_custom_bg:
+ border_rect = wx.Rect(*bg_rect)
+ border_rect.Inflate(1, 1)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(border_rect.x, border_rect.y, border_rect.width, border_rect.height)
+
+ # Foreground
+ avail_width = bg_rect.GetWidth()
+
+ if kind & RIBBON_BUTTON_DROPDOWN:
+ avail_width -= 8
+ if is_split_hybrid:
+ dc.DrawLine(rect.x + avail_width + 1, rect.y, rect.x + avail_width + 1, rect.y + rect.height)
+
+ dc.DrawBitmap(self._toolbar_drop_bitmap, bg_rect.x + avail_width + 2, bg_rect.y + (bg_rect.height / 2) - 2, True)
+
+ dc.DrawBitmap(bitmap, bg_rect.x + (avail_width - bitmap.GetWidth()) / 2, bg_rect.y + (bg_rect.height - bitmap.GetHeight()) / 2, True)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_default.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_default.py
new file mode 100644
index 0000000..516f931
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_default.py
@@ -0,0 +1,68 @@
+"""
+`art_default` is responsible for drawing all the components of the ribbon
+interface using a Windows/Mac or AUI appearance.
+
+
+Description
+===========
+
+This allows a ribbon bar to have a pluggable look-and-feel, while retaining the same
+underlying behaviour. As a single art provider is used for all ribbon components, a
+ribbon bar usually has a consistent (though unique) appearance.
+
+By default, a :class:`~lib.agw.ribbon.bar.RibbonBar` uses an instance of a class called
+:class:`~lib.agw.ribbon.art_default.RibbonDefaultArtProvider`,
+which resolves to :class:`~lib.agw.ribbon.art_aui.RibbonAUIArtProvider`,
+:class:`~lib.agw.ribbon.art_msw.RibbonMSWArtProvider`, or
+:class:`~lib.agw.ribbon.art_osx.RibbonOSXArtProvider` - whichever is most appropriate
+to the current platform. These art providers are all
+slightly configurable with regard to colours and fonts, but for larger modifications,
+you can derive from one of these classes, or write a completely new art provider class.
+
+Call :meth:`RibbonBar.SetArtProvider() <lib.agw.ribbon.bar.RibbonBar.SetArtProvider>` to change the art provider being used.
+
+
+See Also
+========
+
+:class:`~lib.agw.ribbon.bar.RibbonBar`
+"""
+
+import wx
+
+from art_msw import RibbonMSWArtProvider
+from art_aui import RibbonAUIArtProvider
+from art_osx import RibbonOSXArtProvider
+
+if wx.Platform == "__WXMSW__":
+
+ class RibbonDefaultArtProvider(RibbonMSWArtProvider):
+ """ Default art provider on MSW. """
+
+ def __init__(self, set_colour_scheme=True):
+
+ RibbonMSWArtProvider.__init__(self, set_colour_scheme)
+
+
+elif wx.Platform == "__WXGTK__":
+
+ class RibbonDefaultArtProvider(RibbonAUIArtProvider):
+ """ Default art provider on GTK. """
+
+ def __init__(self):
+
+ RibbonAUIArtProvider.__init__(self)
+
+
+else:
+ # MAC has still no art provider for a ribbon, so we'll use
+ # The AUI one. Waiting for a RibbonOSXArtProvider :-D
+
+ class RibbonDefaultArtProvider(RibbonOSXArtProvider):
+ """ Default art provider on Mac. """
+
+ def __init__(self):
+
+ RibbonOSXArtProvider.__init__(self)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_internal.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_internal.py
new file mode 100644
index 0000000..c43a9b1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_internal.py
@@ -0,0 +1,230 @@
+"""
+This module contains methods used throughout the :class:`bar` library.
+"""
+
+import wx
+import math
+
+
+def RibbonInterpolateColour(start_colour, end_colour, position, start_position, end_position):
+
+ if position <= start_position:
+ return start_colour
+
+ if position >= end_position:
+ return end_colour
+
+ position -= start_position
+ end_position -= start_position
+ r = end_colour.Red() - start_colour.Red()
+ g = end_colour.Green() - start_colour.Green()
+ b = end_colour.Blue() - start_colour.Blue()
+ r = start_colour.Red() + (((r * position * 100) / end_position) / 100)
+ g = start_colour.Green() + (((g * position * 100) / end_position) / 100)
+ b = start_colour.Blue() + (((b * position * 100) / end_position) / 100)
+
+ return wx.Colour(r, g, b)
+
+
+def RibbonShiftLuminance(colour, amount):
+
+ if amount <= 1.0:
+ return colour.Darker(colour.luminance * (1.0 - amount))
+ else:
+ return colour.Lighter((1.0 - colour.luminance) * (amount - 1.0))
+
+
+
+def RibbonCanLabelBreakAtPosition(label, pos):
+
+ return label[pos] == ' '
+
+
+def RibbonDrawParallelGradientLines(dc, nlines, line_origins, stepx, stepy, numsteps, offset_x,
+ offset_y, start_colour, end_colour):
+
+ rd = end_colour.Red() - start_colour.Red()
+ gd = end_colour.Green() - start_colour.Green()
+ bd = end_colour.Blue() - start_colour.Blue()
+
+ for step in xrange(numsteps):
+ r = start_colour.Red() + (((step*rd*100)/numsteps)/100)
+ g = start_colour.Green() + (((step*gd*100)/numsteps)/100)
+ b = start_colour.Blue() + (((step*bd*100)/numsteps)/100)
+
+ p = wx.Pen(wx.Colour(r, g, b))
+ dc.SetPen(p)
+
+ for n in xrange(nlines):
+ dc.DrawLine(offset_x + line_origins[n].x, offset_y + line_origins[n].y,
+ offset_x + line_origins[n].x + stepx, offset_y + line_origins[n].y + stepy)
+
+ offset_x += stepx
+ offset_y += stepy
+
+
+def RibbonLoadPixmap(bits, fore):
+
+ xpm = wx.BitmapFromXPMData(bits).ConvertToImage()
+ xpm.Replace(255, 0, 255, fore.Red(), fore.Green(), fore.Blue())
+ return wx.BitmapFromImage(xpm)
+
+
+class RibbonHSLColour(object):
+
+ def __init__(self, h=0.0, s=0.0, l=0.0):
+
+ if isinstance(h, wx.Colour):
+
+ red, green, blue = h.Red()/255.0, h.Green()/255.0, h.Blue()/255.0
+ Min = min(red, min(green, blue))
+ Max = max(red, max(green, blue))
+ luminance = 0.5 * (Max + Min)
+
+ if Min == Max:
+ # colour is a shade of grey
+ hue = 0.0
+ saturation = 0.0
+
+ else:
+ if luminance <= 0.5:
+ saturation = (Max - Min) / (Max + Min)
+ else:
+ saturation = (Max - Min) / (2.0 - (Max + Min))
+
+ if Max == red:
+ hue = 60.0 * (green - blue) / (Max - Min)
+ if hue < 0.0:
+ hue += 360.0
+
+ elif Max == green:
+ hue = 60.0 * (blue - red) / (Max - Min)
+ hue += 120.0
+
+ else: # Max == blue
+
+ hue = 60.0 * (red - green) / (Max - Min)
+ hue += 240.0
+
+ self.hue = hue
+ self.saturation = saturation
+ self.luminance = luminance
+
+ else:
+
+ self.hue = h
+ self.saturation = s
+ self.luminance = l
+
+
+ def ToRGB(self):
+
+ _hue = (self.hue - math.floor(self.hue / 360.0) * 360.0)
+ _saturation = self.saturation
+ _luminance = self.luminance
+
+ if _saturation > 1.0:
+ _saturation = 1.0
+ if _saturation < 0.0:
+ _saturation = 0.0
+ if _luminance > 1.0:
+ _luminance = 1.0
+ if _luminance < 0.0:
+ _luminance = 0.0
+
+ if _saturation == 0.0:
+ # colour is a shade of grey
+ red = blue = green = _luminance
+
+ else:
+
+ tmp2 = (_luminance < 0.5 and [_luminance*(1.0 + _saturation)] or [(_luminance+_saturation) - (_luminance*_saturation)])[0]
+ tmp1 = 2.0 * _luminance - tmp2
+ tmp3R = _hue + 120.0
+
+ if tmp3R > 360.0:
+ tmp3R -= 360.0
+ if tmp3R < 60.0:
+ red = tmp1 + (tmp2 - tmp1) * tmp3R / 60.0
+ elif tmp3R < 180.0:
+ red = tmp2
+ elif tmp3R < 240.0:
+ red = tmp1 + (tmp2 - tmp1) * (240.0 - tmp3R) / 60.0
+ else:
+ red = tmp1
+
+ tmp3G = _hue
+
+ if tmp3G > 360.0:
+ tmp3G -= 360.0
+ if tmp3G < 60.0:
+ green = tmp1 + (tmp2 - tmp1) * tmp3G / 60.0
+ elif tmp3G < 180.0:
+ green = tmp2
+ elif tmp3G < 240.0:
+ green = tmp1 + (tmp2 - tmp1) * (240.0 - tmp3G) / 60.0
+ else:
+ green = tmp1
+
+ tmp3B = _hue + 240.0
+
+ if tmp3B > 360.0:
+ tmp3B -= 360.0
+ if tmp3B < 60.0:
+ blue = tmp1 + (tmp2 - tmp1) * tmp3B / 60.0
+ elif tmp3B < 180.0:
+ blue = tmp2
+ elif tmp3B < 240.0:
+ blue = tmp1 + (tmp2 - tmp1) * (240.0 - tmp3B) / 60.0
+ else:
+ blue = tmp1
+
+ return wx.Colour(red * 255.0, green * 255.0, blue * 255.0)
+
+
+ def Darker(self, delta):
+
+ return self.Lighter(-delta)
+
+
+ def MakeDarker(self, delta):
+
+ self.luminance -= delta
+ return self
+
+
+ def Lighter(self, delta):
+
+ return RibbonHSLColour(self.hue, self.saturation, self.luminance + delta)
+
+
+ def Saturated(self, delta):
+
+ return RibbonHSLColour(self.hue, self.saturation + delta, self.luminance)
+
+
+ def Desaturated(self, delta):
+
+ return self.Saturated(-delta)
+
+
+ def ShiftHue(self, delta):
+
+ return RibbonHSLColour(self.hue + delta, self.saturation, self.luminance)
+
+
+class RibbonPageTabInfo(object):
+
+ def __init__(self):
+
+ self.page = -1
+ self.active = False
+ self.hovererd = False
+ self.rect = wx.Rect()
+ self.ideal_width = 0
+ self.small_begin_need_separator_width = 0
+ self.small_must_have_separator_width = 0
+ self.minimum_width = 0
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_msw.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_msw.py
new file mode 100644
index 0000000..582ede1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_msw.py
@@ -0,0 +1,2721 @@
+"""
+`art_msw` is responsible for drawing all the components of the ribbon
+interface using a Windows appearance.
+
+
+Description
+===========
+
+This allows a ribbon bar to have a pluggable look-and-feel, while retaining the same
+underlying behaviour. As a single art provider is used for all ribbon components, a
+ribbon bar usually has a consistent (though unique) appearance.
+
+By default, a :class:`~lib.agw.ribbon.bar.RibbonBar` uses an instance of a class called
+:class:`~lib.agw.ribbon.art_default.RibbonDefaultArtProvider`,
+which resolves to :class:`~lib.agw.ribbon.art_aui.RibbonAUIArtProvider`,
+:class:`~lib.agw.ribbon.art_msw.RibbonMSWArtProvider`, or
+:class:`~lib.agw.ribbon.art_osx.RibbonOSXArtProvider` - whichever is most appropriate
+to the current platform. These art providers are all
+slightly configurable with regard to colours and fonts, but for larger modifications,
+you can derive from one of these classes, or write a completely new art provider class.
+
+Call :meth:`RibbonBar.SetArtProvider() <lib.agw.ribbon.bar.RibbonBar.SetArtProvider>` to change the art provider being used.
+
+
+See Also
+========
+
+:class:`~lib.agw.ribbon.bar.RibbonBar`
+"""
+
+import wx
+import types
+
+from math import cos
+from math import pi as M_PI
+
+import panel as PANEL
+import page as PAGE
+
+from art_internal import RibbonLoadPixmap, RibbonInterpolateColour, RibbonDrawParallelGradientLines
+from art_internal import RibbonCanLabelBreakAtPosition
+from art_internal import RibbonHSLColour
+
+from art import *
+
+
+gallery_up_xpm = ["5 5 2 1", " c None", "x c #FF00FF", " ", " x ", " xxx ", "xxxxx", " "]
+gallery_down_xpm = ["5 5 2 1", " c None", "x c #FF00FF", " ", "xxxxx", " xxx ", " x ", " "]
+gallery_left_xpm = ["5 5 2 1", " c None", "x c #FF00FF", " x ", " xx ", " xxx ", " xx ", " x "]
+gallery_right_xpm = ["5 5 2 1", " c None", "x c #FF00FF", " x ", " xx ", " xxx ", " xx ", " x "]
+gallery_extension_xpm = ["5 5 2 1", " c None", "x c #FF00FF", "xxxxx", " ", "xxxxx", " xxx ", " x "]
+panel_extension_xpm = ["7 7 2 1", " c None", "x c #FF00FF", "xxxxxx ", "x ", "x ",
+ "x x x", "x xxx", "x xxx", " xxxx"]
+
+
+def LikePrimary(primary_hsl, is_gray, h, s, l):
+
+ return primary_hsl.ShiftHue(h).Saturated((is_gray and [0] or [s])[0]).Lighter(l).ToRGB()
+
+
+def LikeSecondary(secondary_hsl, is_gray, h, s, l):
+
+ return secondary_hsl.ShiftHue(h).Saturated((is_gray and [0] or [s])[0]).Lighter(l).ToRGB()
+
+
+def SingleLine(dc, rect, start, finish):
+
+ dc.DrawLine(start.x + rect.x, start.y + rect.y, finish.x + rect.x, finish.y + rect.y)
+
+
+class RibbonMSWArtProvider(object):
+
+ def __init__(self, set_colour_scheme=True):
+
+ self._flags = 0
+ self._tab_label_font = wx.NORMAL_FONT
+ self._button_bar_label_font = wx.NORMAL_FONT
+ self._panel_label_font = wx.NORMAL_FONT
+
+ self._gallery_up_bitmap = [wx.NullBitmap for i in xrange(4)]
+ self._gallery_down_bitmap = [wx.NullBitmap for i in xrange(4)]
+ self._gallery_extension_bitmap = [wx.NullBitmap for i in xrange(4)]
+ self._panel_extension_bitmap = [wx.NullBitmap for i in xrange(2)]
+
+ if set_colour_scheme:
+ self.SetColourScheme(wx.Colour(194, 216, 241), wx.Colour(255, 223, 114), wx.Colour(0, 0, 0))
+
+ self._cached_tab_separator_visibility = -10.0 # valid visibilities are in range [0, 1]
+ self._tab_separation_size = 3
+ self._page_border_left = 2
+ self._page_border_top = 1
+ self._page_border_right = 2
+ self._page_border_bottom = 3
+ self._panel_x_separation_size = 1
+ self._panel_y_separation_size = 1
+ self._tool_group_separation_size = 3
+ self._gallery_bitmap_padding_left_size = 4
+ self._gallery_bitmap_padding_right_size = 4
+ self._gallery_bitmap_padding_top_size = 4
+ self._gallery_bitmap_padding_bottom__size = 4
+ self._cached_tab_separator = wx.NullBitmap
+
+
+ def GetColourScheme(self, primary, secondary, tertiary):
+ """
+ Get the current colour scheme.
+
+ Returns three colours such that if :meth:`~RibbonMSWArtProvider.SetColourScheme` were called with them, the
+ colour scheme would be restored to what it was when :meth:`~RibbonMSWArtProvider.SetColourScheme` was last
+ called. In practice, this usually means that the returned values are the three
+ colours given in the last call to :meth:`~RibbonMSWArtProvider.SetColourScheme`, however if
+ :meth:`~RibbonMSWArtProvider.SetColourScheme` performs an idempotent operation upon the colours it is given
+ (like clamping a component of the colour), then the returned values may not be
+ the three colours given in the last call to :meth:`~RibbonMSWArtProvider.SetColourScheme`.
+
+ If :meth:`~RibbonMSWArtProvider.SetColourScheme` has not been called, then the returned values should result
+ in a colour scheme similar to, if not identical to, the default colours of the
+ art provider. Note that if :meth:`~RibbonMSWArtProvider.SetColour` is called, then :meth:`~RibbonMSWArtProvider.GetColourScheme` does
+ not try and return a colour scheme similar to colours being used - it's return
+ values are dependant upon the last values given to :meth:`~RibbonMSWArtProvider.SetColourScheme`, as
+ described above.
+
+ :param `primary`: Pointer to a location to store the primary colour, or ``None``;
+ :param `secondary`: Pointer to a location to store the secondary colour, or ``None``;
+ :param `tertiary`: Pointer to a location to store the tertiary colour, or ``None``.
+
+ """
+
+ if primary != None:
+ primary = self._primary_scheme_colour
+ if secondary != None:
+ secondary = self._secondary_scheme_colour
+ if tertiary != None:
+ tertiary = self._tertiary_scheme_colour
+
+ return primary, secondary, tertiary
+
+
+ def SetColourScheme(self, primary, secondary, tertiary):
+ """
+ Set all applicable colour settings from a few base colours.
+
+ Uses any or all of the three given colours to create a colour scheme, and then
+ sets all colour settings which are relevant to the art provider using that
+ scheme. Note that some art providers may not use the tertiary colour for
+ anything, and some may not use the secondary colour either.
+
+ :param `primary`: MISSING DESCRIPTION;
+ :param `secondary`: MISSING DESCRIPTION;
+ :param `tertiary`: MISSING DESCRIPTION.
+
+ :see: :meth:`~RibbonMSWArtProvider.SetColour`, :meth:`~RibbonMSWArtProvider.GetColourScheme`
+ """
+
+ self._primary_scheme_colour = primary
+ self._secondary_scheme_colour = secondary
+ self._tertiary_scheme_colour = tertiary
+
+ primary_hsl = RibbonHSLColour(primary)
+ secondary_hsl = RibbonHSLColour(secondary)
+ # tertiary not used for anything
+
+ # Map primary saturation from [0, 1] to [.25, .75]
+ primary_is_gray = False
+ gray_saturation_threshold = 0.01
+
+ if primary_hsl.saturation <= gray_saturation_threshold:
+ primary_is_gray = True
+ else:
+ primary_hsl.saturation = cos(primary_hsl.saturation * M_PI) * -0.25 + 0.5
+
+ # Map primary luminance from [0, 1] to [.23, .83]
+ primary_hsl.luminance = cos(primary_hsl.luminance * M_PI) * -0.3 + 0.53
+
+ # Map secondary saturation from [0, 1] to [0.16, 0.84]
+ secondary_is_gray = False
+
+ if secondary_hsl.saturation <= gray_saturation_threshold:
+ secondary_is_gray = True
+ else:
+ secondary_hsl.saturation = cos(secondary_hsl.saturation * M_PI) * -0.34 + 0.5
+
+ # Map secondary luminance from [0, 1] to [0.1, 0.9]
+ secondary_hsl.luminance = cos(secondary_hsl.luminance * M_PI) * -0.4 + 0.5
+
+ self._page_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, 1.4, 0.00, -0.08))
+ self._page_background_top_colour = LikePrimary(primary_hsl, primary_is_gray, -0.1, -0.03, 0.12)
+ self._page_hover_background_top_colour = LikePrimary(primary_hsl, primary_is_gray, -2.8, 0.27, 0.17)
+ self._page_background_top_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 0.1, -0.10, 0.08)
+ self._page_hover_background_top_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 3.2, 0.16, 0.13)
+ self._page_background_colour = LikePrimary(primary_hsl, primary_is_gray, 0.4, -0.09, 0.05)
+ self._page_hover_background_colour = LikePrimary(primary_hsl, primary_is_gray, 0.1, 0.19, 0.10)
+ self._page_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, -3.2, 0.27, 0.10)
+ self._page_hover_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.8, 0.01, 0.15)
+
+ self._tab_active_background_colour = LikePrimary(primary_hsl, primary_is_gray, -0.1, -0.31, 0.16)
+ self._tab_active_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, -0.1, -0.03, 0.12)
+ self._tab_separator_colour = LikePrimary(primary_hsl, primary_is_gray, 0.9, 0.24, 0.05)
+ self._tab_ctrl_background_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, 1.0, 0.39, 0.07))
+ self._tab_hover_background_colour = LikePrimary(primary_hsl, primary_is_gray, 1.3, 0.15, 0.10)
+ self._tab_hover_background_top_colour = LikePrimary(primary_hsl, primary_is_gray, 1.4, 0.36, 0.08)
+ self._tab_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, 1.4, 0.03, -0.05) )
+ self._tab_separator_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.7, -0.15, -0.18)
+ self._tab_hover_background_top_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.8, 0.34, 0.13)
+ self._tab_label_colour = LikePrimary(primary_hsl, primary_is_gray, 4.3, 0.13, -0.49)
+ self._tab_hover_background_gradient_colour = LikeSecondary(primary_hsl, secondary_is_gray, -1.5, -0.34, 0.01)
+
+ self._panel_minimised_border_gradient_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, -6.9, -0.17, -0.09))
+ self._panel_minimised_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, -5.3, -0.24, -0.06))
+ self._panel_border_gradient_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, -5.2, -0.15, -0.06))
+ self._panel_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, -2.8, -0.32, 0.02))
+ self._panel_label_background_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, -1.5, 0.03, 0.05))
+ self._panel_active_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 0.5, 0.34, 0.05)
+ self._panel_hover_label_background_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, 1.0, 0.30, 0.09))
+ self._panel_active_background_top_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.17, -0.13)
+ self._panel_active_background_colour = LikePrimary(primary_hsl, primary_is_gray, 1.6, -0.18, -0.18)
+ self._panel_active_background_top_colour = LikePrimary(primary_hsl, primary_is_gray, 1.7, -0.20, -0.03)
+ self._panel_label_colour = LikePrimary(primary_hsl, primary_is_gray, 2.8, -0.14, -0.35)
+ self._panel_hover_label_colour = self._panel_label_colour
+ self._panel_minimised_label_colour = self._tab_label_colour
+
+ self._panel_hover_button_background_brush = wx.Brush(LikeSecondary(secondary_hsl, secondary_is_gray, -0.9, 0.16, -0.07))
+ self._panel_hover_button_border_pen = wx.Pen(LikeSecondary(secondary_hsl, secondary_is_gray, -3.9, -0.16, -0.14))
+ self.SetColour(RIBBON_ART_PANEL_BUTTON_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.21, -0.23))
+ self.SetColour(RIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.5, -0.24, -0.29))
+
+ self._gallery_button_disabled_background_colour = LikePrimary(primary_hsl, primary_is_gray, -2.8, -0.46, 0.09)
+ self._gallery_button_disabled_background_top_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, -2.8, -0.36, 0.15))
+ self._gallery_hover_background_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, -0.8, 0.05, 0.15))
+ self._gallery_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, 0.7, -0.02, 0.03))
+ self._gallery_button_background_top_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, 0.8, 0.34, 0.13))
+ self._gallery_button_background_colour = LikePrimary(primary_hsl, primary_is_gray, 1.3, 0.10, 0.08)
+
+ # SetColour used so that the relevant bitmaps are generated
+ self.SetColour(RIBBON_ART_GALLERY_BUTTON_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.21, -0.23))
+ self.SetColour(RIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.5, -0.24, -0.29))
+ self.SetColour(RIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.5, -0.24, -0.29))
+ self.SetColour(RIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 0.0, -1.0, 0.0))
+ self._gallery_button_disabled_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.5, -0.43, 0.12)
+ self._gallery_button_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.7, 0.11, 0.09)
+ self._gallery_item_border_pen = wx.Pen(LikeSecondary(secondary_hsl, secondary_is_gray, -3.9, -0.16, -0.14))
+ self._gallery_button_hover_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -0.9, 0.16, -0.07)
+ self._gallery_button_hover_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, 0.1, 0.12, 0.03)
+ self._gallery_button_hover_background_top_brush = wx.Brush(LikeSecondary(secondary_hsl, secondary_is_gray, 4.3, 0.16, 0.17))
+
+ self._gallery_button_active_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -9.9, 0.03, -0.22)
+ self._gallery_button_active_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -9.5, 0.14, -0.11)
+ self._gallery_button_active_background_top_brush = wx.Brush(LikeSecondary(secondary_hsl, secondary_is_gray, -9.0, 0.15, -0.08))
+
+ self._button_bar_label_colour = self._tab_label_colour
+ self._button_bar_hover_border_pen = wx.Pen(LikeSecondary(secondary_hsl, secondary_is_gray, -6.2, -0.47, -0.14))
+ self._button_bar_hover_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -0.6, 0.16, 0.04)
+ self._button_bar_hover_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -0.2, 0.16, -0.10)
+ self._button_bar_hover_background_top_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, 0.2, 0.16, 0.03)
+ self._button_bar_hover_background_top_colour = LikeSecondary(secondary_hsl, secondary_is_gray, 8.8, 0.16, 0.17)
+ self._button_bar_active_border_pen = wx.Pen(LikeSecondary(secondary_hsl, secondary_is_gray, -6.2, -0.47, -0.25))
+ self._button_bar_active_background_top_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -8.4, 0.08, 0.06)
+ self._button_bar_active_background_top_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -9.7, 0.13, -0.07)
+ self._button_bar_active_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -9.9, 0.14, -0.14)
+ self._button_bar_active_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -8.7, 0.17, -0.03)
+
+ self._toolbar_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.21, -0.16))
+ self.SetColour(RIBBON_ART_TOOLBAR_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.17, -0.22))
+ self._tool_background_top_colour = LikePrimary(primary_hsl, primary_is_gray, -1.9, -0.07, 0.06)
+ self._tool_background_top_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.4, 0.12, 0.08)
+ self._tool_background_colour = LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.09, 0.03)
+ self._tool_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.9, 0.11, 0.09)
+ self._tool_hover_background_top_colour = LikeSecondary(secondary_hsl, secondary_is_gray, 3.4, 0.11, 0.16)
+ self._tool_hover_background_top_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -1.4, 0.04, 0.08)
+ self._tool_hover_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -1.8, 0.16, -0.12)
+ self._tool_hover_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -2.6, 0.16, 0.05)
+ self._tool_active_background_top_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -9.9, -0.12, -0.09)
+ self._tool_active_background_top_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -8.5, 0.16, -0.12)
+ self._tool_active_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -7.9, 0.16, -0.20)
+ self._tool_active_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -6.6, 0.16, -0.10)
+
+ # Invalidate cached tab separator
+ self._cached_tab_separator_visibility = -1.0
+
+
+ def Clone(self):
+ """
+ Create a new art provider which is a clone of this one.
+ """
+
+ copy = RibbonMSWArtProvider()
+ self.CloneTo(copy)
+ return copy
+
+
+ def CloneTo(self, copy):
+
+ for i in xrange(4):
+ copy._gallery_up_bitmap[i] = self._gallery_up_bitmap[i]
+ copy._gallery_down_bitmap[i] = self._gallery_down_bitmap[i]
+ copy._gallery_extension_bitmap[i] = self._gallery_extension_bitmap[i]
+
+ for i in xrange(2):
+ copy._panel_extension_bitmap[i] = self._panel_extension_bitmap[i]
+
+ copy._toolbar_drop_bitmap = self._toolbar_drop_bitmap
+
+ copy._primary_scheme_colour = self._primary_scheme_colour
+ copy._secondary_scheme_colour = self._secondary_scheme_colour
+ copy._tertiary_scheme_colour = self._tertiary_scheme_colour
+
+ copy._button_bar_label_colour = self._button_bar_label_colour
+ copy._tab_label_colour = self._tab_label_colour
+ copy._tab_separator_colour = self._tab_separator_colour
+ copy._tab_separator_gradient_colour = self._tab_separator_gradient_colour
+ copy._tab_active_background_colour = self._tab_hover_background_colour
+ copy._tab_active_background_gradient_colour = self._tab_hover_background_gradient_colour
+ copy._tab_hover_background_colour = self._tab_hover_background_colour
+ copy._tab_hover_background_gradient_colour = self._tab_hover_background_gradient_colour
+ copy._tab_hover_background_top_colour = self._tab_hover_background_top_colour
+ copy._tab_hover_background_top_gradient_colour = self._tab_hover_background_top_gradient_colour
+ copy._panel_label_colour = self._panel_label_colour
+ copy._panel_hover_label_colour = self._panel_hover_label_colour
+ copy._panel_minimised_label_colour = self._panel_minimised_label_colour
+ copy._panel_button_face_colour = self._panel_button_face_colour
+ copy._panel_button_hover_face_colour = self._panel_button_hover_face_colour
+ copy._panel_active_background_colour = self._panel_active_background_colour
+ copy._panel_active_background_gradient_colour = self._panel_active_background_gradient_colour
+ copy._panel_active_background_top_colour = self._panel_active_background_top_colour
+ copy._panel_active_background_top_gradient_colour = self._panel_active_background_top_gradient_colour
+ copy._page_background_colour = self._page_background_colour
+ copy._page_background_gradient_colour = self._page_background_gradient_colour
+ copy._page_background_top_colour = self._page_background_top_colour
+ copy._page_background_top_gradient_colour = self._page_background_top_gradient_colour
+ copy._page_hover_background_colour = self._page_hover_background_colour
+ copy._page_hover_background_gradient_colour = self._page_hover_background_gradient_colour
+ copy._page_hover_background_top_colour = self._page_hover_background_top_colour
+ copy._page_hover_background_top_gradient_colour = self._page_hover_background_top_gradient_colour
+ copy._button_bar_hover_background_colour = self._button_bar_hover_background_colour
+ copy._button_bar_hover_background_gradient_colour = self._button_bar_hover_background_gradient_colour
+ copy._button_bar_hover_background_top_colour = self._button_bar_hover_background_top_colour
+ copy._button_bar_hover_background_top_gradient_colour = self._button_bar_hover_background_top_gradient_colour
+ copy._button_bar_active_background_colour = self._button_bar_active_background_colour
+ copy._button_bar_active_background_gradient_colour = self._button_bar_active_background_gradient_colour
+ copy._button_bar_active_background_top_colour = self._button_bar_active_background_top_colour
+ copy._button_bar_active_background_top_gradient_colour = self._button_bar_active_background_top_gradient_colour
+ copy._gallery_button_background_colour = self._gallery_button_background_colour
+ copy._gallery_button_background_gradient_colour = self._gallery_button_background_gradient_colour
+ copy._gallery_button_hover_background_colour = self._gallery_button_hover_background_colour
+ copy._gallery_button_hover_background_gradient_colour = self._gallery_button_hover_background_gradient_colour
+ copy._gallery_button_active_background_colour = self._gallery_button_active_background_colour
+ copy._gallery_button_active_background_gradient_colour = self._gallery_button_active_background_gradient_colour
+ copy._gallery_button_disabled_background_colour = self._gallery_button_disabled_background_colour
+ copy._gallery_button_disabled_background_gradient_colour = self._gallery_button_disabled_background_gradient_colour
+ copy._gallery_button_face_colour = self._gallery_button_face_colour
+ copy._gallery_button_hover_face_colour = self._gallery_button_hover_face_colour
+ copy._gallery_button_active_face_colour = self._gallery_button_active_face_colour
+ copy._gallery_button_disabled_face_colour = self._gallery_button_disabled_face_colour
+
+ copy._tab_ctrl_background_brush = self._tab_ctrl_background_brush
+ copy._panel_label_background_brush = self._panel_label_background_brush
+ copy._panel_hover_label_background_brush = self._panel_hover_label_background_brush
+ copy._panel_hover_button_background_brush = self._panel_hover_button_background_brush
+ copy._gallery_hover_background_brush = self._gallery_hover_background_brush
+ copy._gallery_button_background_top_brush = self._gallery_button_background_top_brush
+ copy._gallery_button_hover_background_top_brush = self._gallery_button_hover_background_top_brush
+ copy._gallery_button_active_background_top_brush = self._gallery_button_active_background_top_brush
+ copy._gallery_button_disabled_background_top_brush = self._gallery_button_disabled_background_top_brush
+
+ copy._tab_label_font = self._tab_label_font
+ copy._button_bar_label_font = self._button_bar_label_font
+ copy._panel_label_font = self._panel_label_font
+
+ copy._page_border_pen = self._page_border_pen
+ copy._panel_border_pen = self._panel_border_pen
+ copy._panel_border_gradient_pen = self._panel_border_gradient_pen
+ copy._panel_hover_button_border_pen = self._panel_hover_button_border_pen
+ copy._panel_minimised_border_pen = self._panel_minimised_border_pen
+ copy._panel_minimised_border_gradient_pen = self._panel_minimised_border_gradient_pen
+ copy._tab_border_pen = self._tab_border_pen
+ copy._gallery_border_pen = self._gallery_border_pen
+ copy._button_bar_hover_border_pen = self._button_bar_hover_border_pen
+ copy._button_bar_active_border_pen = self._button_bar_active_border_pen
+ copy._gallery_item_border_pen = self._gallery_item_border_pen
+ copy._toolbar_border_pen = self._toolbar_border_pen
+
+ copy._flags = self._flags
+ copy._tab_separation_size = self._tab_separation_size
+ copy._page_border_left = self._page_border_left
+ copy._page_border_top = self._page_border_top
+ copy._page_border_right = self._page_border_right
+ copy._page_border_bottom = self._page_border_bottom
+ copy._panel_x_separation_size = self._panel_x_separation_size
+ copy._panel_y_separation_size = self._panel_y_separation_size
+ copy._gallery_bitmap_padding_left_size = self._gallery_bitmap_padding_left_size
+ copy._gallery_bitmap_padding_right_size = self._gallery_bitmap_padding_right_size
+ copy._gallery_bitmap_padding_top_size = self._gallery_bitmap_padding_top_size
+ copy._gallery_bitmap_padding_bottom__size = self._gallery_bitmap_padding_bottom__size
+
+
+ def GetFlags(self):
+ """
+ Get the previously set style flags.
+ """
+
+ return self._flags
+
+
+ def SetFlags(self, flags):
+ """
+ Set the style flags.
+
+ Normally called automatically by :meth:`RibbonBar.SetArtProvider() <RibbonBar.SetArtProvider>` with the ribbon
+ bar's style flags, so that the art provider has the same flags as the bar which
+ it is serving.
+
+ :param `flags`: MISSING DESCRIPTION.
+
+ """
+
+ if (flags ^ self._flags) & RIBBON_BAR_FLOW_VERTICAL:
+ if flags & RIBBON_BAR_FLOW_VERTICAL:
+ self._page_border_left += 1
+ self._page_border_right += 1
+ self._page_border_top -= 1
+ self._page_border_bottom -= 1
+ else:
+ self._page_border_left -= 1
+ self._page_border_right -= 1
+ self._page_border_top += 1
+ self._page_border_bottom += 1
+
+ self._flags = flags
+
+ # Need to reload some bitmaps when flags change
+ self.Reload(RIBBON_ART_GALLERY_BUTTON_FACE_COLOUR)
+ self.Reload(RIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR)
+ self.Reload(RIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR)
+ self.Reload(RIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR)
+ self.Reload(RIBBON_ART_PANEL_BUTTON_FACE_COLOUR)
+ self.Reload(RIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR)
+
+
+ def Reload(self, setting):
+
+ self.SetColour(setting, self.GetColour(setting))
+
+
+ def GetMetric(self, id):
+ """
+ Get the value of a certain integer setting.
+
+ can be one of the size values of `RibbonArtSetting`.
+
+ :param `id`: a metric id.
+
+ """
+
+ if id == RIBBON_ART_TAB_SEPARATION_SIZE:
+ return self._tab_separation_size
+ elif id == RIBBON_ART_PAGE_BORDER_LEFT_SIZE:
+ return self._page_border_left
+ elif id == RIBBON_ART_PAGE_BORDER_TOP_SIZE:
+ return self._page_border_top
+ elif id == RIBBON_ART_PAGE_BORDER_RIGHT_SIZE:
+ return self._page_border_right
+ elif id == RIBBON_ART_PAGE_BORDER_BOTTOM_SIZE:
+ return self._page_border_bottom
+ elif id == RIBBON_ART_PANEL_X_SEPARATION_SIZE:
+ return self._panel_x_separation_size
+ elif id == RIBBON_ART_PANEL_Y_SEPARATION_SIZE:
+ return self._panel_y_separation_size
+ elif id == RIBBON_ART_TOOL_GROUP_SEPARATION_SIZE:
+ return self._tool_group_separation_size
+ elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE:
+ return self._gallery_bitmap_padding_left_size
+ elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE:
+ return self._gallery_bitmap_padding_right_size
+ elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE:
+ return self._gallery_bitmap_padding_top_size
+ elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE:
+ return self._gallery_bitmap_padding_bottom__size
+ else:
+ raise Exception("Invalid Metric Ordinal")
+
+
+ def SetMetric(self, id, new_val):
+ """
+ Set the value of a certain integer setting to the value.
+
+ can be one of the size values of `RibbonArtSetting`.
+
+ :param `id`: a metric id;
+ :param `new_val`: the new value of the metric setting.
+
+ """
+
+ if id == RIBBON_ART_TAB_SEPARATION_SIZE:
+ self._tab_separation_size = new_val
+ elif id == RIBBON_ART_PAGE_BORDER_LEFT_SIZE:
+ self._page_border_left = new_val
+ elif id == RIBBON_ART_PAGE_BORDER_TOP_SIZE:
+ self._page_border_top = new_val
+ elif id == RIBBON_ART_PAGE_BORDER_RIGHT_SIZE:
+ self._page_border_right = new_val
+ elif id == RIBBON_ART_PAGE_BORDER_BOTTOM_SIZE:
+ self._page_border_bottom = new_val
+ elif id == RIBBON_ART_PANEL_X_SEPARATION_SIZE:
+ self._panel_x_separation_size = new_val
+ elif id == RIBBON_ART_PANEL_Y_SEPARATION_SIZE:
+ self._panel_y_separation_size = new_val
+ elif id == RIBBON_ART_TOOL_GROUP_SEPARATION_SIZE:
+ self._tool_group_separation_size = new_val
+ elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE:
+ self._gallery_bitmap_padding_left_size = new_val
+ elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE:
+ self._gallery_bitmap_padding_right_size = new_val
+ elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE:
+ self._gallery_bitmap_padding_top_size = new_val
+ elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE:
+ self._gallery_bitmap_padding_bottom__size = new_val
+ else:
+ raise Exception("Invalid Metric Ordinal")
+
+
+ def SetFont(self, id, font):
+ """
+ Set the value of a certain font setting to the value.
+
+ can be one of the font values of `RibbonArtSetting`.
+
+ :param `id`: a font id;
+ :param `font`: the new font.
+
+ """
+
+ if id == RIBBON_ART_TAB_LABEL_FONT:
+ self._tab_label_font = font
+ elif id == RIBBON_ART_BUTTON_BAR_LABEL_FONT:
+ self._button_bar_label_font = font
+ elif id == RIBBON_ART_PANEL_LABEL_FONT:
+ self._panel_label_font = font
+ else:
+ raise Exception("Invalid Font Ordinal")
+
+
+ def GetFont(self, id):
+ """
+ Get the value of a certain font setting.
+
+ can be one of the font values of `RibbonArtSetting`.
+
+ :param `id`: the font id.
+
+ """
+
+ if id == RIBBON_ART_TAB_LABEL_FONT:
+ return self._tab_label_font
+ elif id == RIBBON_ART_BUTTON_BAR_LABEL_FONT:
+ return self._button_bar_label_font
+ elif id == RIBBON_ART_PANEL_LABEL_FONT:
+ return self._panel_label_font
+ else:
+ raise Exception("Invalid Font Ordinal")
+
+
+ def GetColour(self, id):
+ """
+ Get the value of a certain colour setting.
+
+ can be one of the colour values of `RibbonArtSetting`.
+
+ :param `id`: the colour id.
+
+ """
+
+ if id == RIBBON_ART_BUTTON_BAR_LABEL_COLOUR:
+ return self._button_bar_label_colour
+ elif id == RIBBON_ART_BUTTON_BAR_HOVER_BORDER_COLOUR:
+ return self._button_bar_hover_border_pen.GetColour()
+ elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_COLOUR:
+ return self._button_bar_hover_background_top_colour
+ elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
+ return self._button_bar_hover_background_top_gradient_colour
+ elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_COLOUR:
+ return self._button_bar_hover_background_colour
+ elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_GRADIENT_COLOUR:
+ return self._button_bar_hover_background_gradient_colour
+ elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BORDER_COLOUR:
+ return self._button_bar_active_border_pen.GetColour()
+ elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_COLOUR:
+ return self._button_bar_active_background_top_colour
+ elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR:
+ return self._button_bar_active_background_top_gradient_colour
+ elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_COLOUR:
+ return self._button_bar_active_background_colour
+ elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
+ return self._button_bar_active_background_gradient_colour
+ elif id == RIBBON_ART_GALLERY_BORDER_COLOUR:
+ return self._gallery_border_pen.GetColour()
+ elif id == RIBBON_ART_GALLERY_HOVER_BACKGROUND_COLOUR:
+ return self._gallery_hover_background_brush.GetColour()
+ elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_COLOUR:
+ return self._gallery_button_background_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_GRADIENT_COLOUR:
+ return self._gallery_button_background_gradient_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_TOP_COLOUR:
+ return self._gallery_button_background_top_brush.GetColour()
+ elif id == RIBBON_ART_GALLERY_BUTTON_FACE_COLOUR:
+ return self._gallery_button_face_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_COLOUR:
+ return self._gallery_button_hover_background_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_GRADIENT_COLOUR:
+ return self._gallery_button_hover_background_gradient_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_TOP_COLOUR:
+ return self._gallery_button_hover_background_top_brush.GetColour()
+ elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR:
+ return self._gallery_button_face_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_COLOUR:
+ return self._gallery_button_active_background_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
+ return self._gallery_button_active_background_gradient_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_TOP_COLOUR:
+ return self._gallery_button_background_top_brush.GetColour()
+ elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR:
+ return self._gallery_button_active_face_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_COLOUR:
+ return self._gallery_button_disabled_background_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_GRADIENT_COLOUR:
+ return self._gallery_button_disabled_background_gradient_colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_TOP_COLOUR:
+ return self._gallery_button_disabled_background_top_brush.GetColour()
+ elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR:
+ return self._gallery_button_disabled_face_colour
+ elif id == RIBBON_ART_GALLERY_ITEM_BORDER_COLOUR:
+ return self._gallery_item_border_pen.GetColour()
+ elif id in [RIBBON_ART_TAB_CTRL_BACKGROUND_COLOUR, RIBBON_ART_TAB_CTRL_BACKGROUND_GRADIENT_COLOUR]:
+ return self._tab_ctrl_background_brush.GetColour()
+ elif id == RIBBON_ART_TAB_LABEL_COLOUR:
+ return self._tab_label_colour
+ elif id == RIBBON_ART_TAB_SEPARATOR_COLOUR:
+ return self._tab_separator_colour
+ elif id == RIBBON_ART_TAB_SEPARATOR_GRADIENT_COLOUR:
+ return self._tab_separator_gradient_colour
+ elif id in [RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_COLOUR, RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR]:
+ return wx.Colour(0, 0, 0)
+ elif id == RIBBON_ART_TAB_ACTIVE_BACKGROUND_COLOUR:
+ return self._tab_active_background_colour
+ elif id == RIBBON_ART_TAB_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
+ return self._tab_active_background_gradient_colour
+ elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_TOP_COLOUR:
+ return self._tab_hover_background_top_colour
+ elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
+ return self._tab_hover_background_top_gradient_colour
+ elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_COLOUR:
+ return self._tab_hover_background_colour
+ elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_GRADIENT_COLOUR:
+ return self._tab_hover_background_gradient_colour
+ elif id == RIBBON_ART_TAB_BORDER_COLOUR:
+ return self._tab_border_pen.GetColour()
+ elif id == RIBBON_ART_PANEL_BORDER_COLOUR:
+ return self._panel_border_pen.GetColour()
+ elif id == RIBBON_ART_PANEL_BORDER_GRADIENT_COLOUR:
+ return self._panel_border_gradient_pen.GetColour()
+ elif id == RIBBON_ART_PANEL_MINIMISED_BORDER_COLOUR:
+ return self._panel_minimised_border_pen.GetColour()
+ elif id == RIBBON_ART_PANEL_MINIMISED_BORDER_GRADIENT_COLOUR:
+ return self._panel_minimised_border_gradient_pen.GetColour()
+ elif id in [RIBBON_ART_PANEL_LABEL_BACKGROUND_COLOUR, RIBBON_ART_PANEL_LABEL_BACKGROUND_GRADIENT_COLOUR]:
+ return self._panel_label_background_brush.GetColour()
+ elif id == RIBBON_ART_PANEL_LABEL_COLOUR:
+ return self._panel_label_colour
+ elif id == RIBBON_ART_PANEL_MINIMISED_LABEL_COLOUR:
+ return self._panel_minimised_label_colour
+ elif id in [RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_COLOUR, RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_GRADIENT_COLOUR]:
+ return self._panel_hover_label_background_brush.GetColour()
+ elif id == RIBBON_ART_PANEL_HOVER_LABEL_COLOUR:
+ return self._panel_hover_label_colour
+ elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_COLOUR:
+ return self._panel_active_background_top_colour
+ elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR:
+ return self._panel_active_background_top_gradient_colour
+ elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_COLOUR:
+ return self._panel_active_background_colour
+ elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
+ return self._panel_active_background_gradient_colour
+ elif id == RIBBON_ART_PANEL_BUTTON_FACE_COLOUR:
+ return self._panel_button_face_colour
+ elif id == RIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR:
+ return self._panel_button_hover_face_colour
+ elif id == RIBBON_ART_PAGE_BORDER_COLOUR:
+ return self._page_border_pen.GetColour()
+ elif id == RIBBON_ART_PAGE_BACKGROUND_TOP_COLOUR:
+ return self._page_background_top_colour
+ elif id == RIBBON_ART_PAGE_BACKGROUND_TOP_GRADIENT_COLOUR:
+ return self._page_background_top_gradient_colour
+ elif id == RIBBON_ART_PAGE_BACKGROUND_COLOUR:
+ return self._page_background_colour
+ elif id == RIBBON_ART_PAGE_BACKGROUND_GRADIENT_COLOUR:
+ return self._page_background_gradient_colour
+ elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_COLOUR:
+ return self._page_hover_background_top_colour
+ elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
+ return self._page_hover_background_top_gradient_colour
+ elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_COLOUR:
+ return self._page_hover_background_colour
+ elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_GRADIENT_COLOUR:
+ return self._page_hover_background_gradient_colour
+ elif id in [RIBBON_ART_TOOLBAR_BORDER_COLOUR, RIBBON_ART_TOOLBAR_HOVER_BORDER_COLOUR]:
+ return self._toolbar_border_pen.GetColour()
+ elif id == RIBBON_ART_TOOLBAR_FACE_COLOUR:
+ return self._tool_face_colour
+ else:
+ raise Exception("Invalid Colour Ordinal")
+
+
+ def SetColour(self, id, colour):
+ """
+ Set the value of a certain colour setting to the value.
+
+ can be one of the colour values of `RibbonArtSetting`, though not all colour
+ settings will have an affect on every art provider.
+
+ :param `id`: the colour id;
+ :param `colour`: the colour.
+
+ :see: :meth:`~RibbonMSWArtProvider.SetColourScheme`
+ """
+
+ if id == RIBBON_ART_BUTTON_BAR_LABEL_COLOUR:
+ self._button_bar_label_colour = colour
+ elif id == RIBBON_ART_BUTTON_BAR_HOVER_BORDER_COLOUR:
+ self._button_bar_hover_border_pen.SetColour(colour)
+ elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_COLOUR:
+ self._button_bar_hover_background_top_colour = colour
+ elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
+ self._button_bar_hover_background_top_gradient_colour = colour
+ elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_COLOUR:
+ self._button_bar_hover_background_colour = colour
+ elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_GRADIENT_COLOUR:
+ self._button_bar_hover_background_gradient_colour = colour
+ elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BORDER_COLOUR:
+ self._button_bar_active_border_pen.SetColour(colour)
+ elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_COLOUR:
+ self._button_bar_active_background_top_colour = colour
+ elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR:
+ self._button_bar_active_background_top_gradient_colour = colour
+ elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_COLOUR:
+ self._button_bar_active_background_colour = colour
+ elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
+ self._button_bar_active_background_gradient_colour = colour
+ elif id == RIBBON_ART_GALLERY_BORDER_COLOUR:
+ self._gallery_border_pen.SetColour(colour)
+ elif id == RIBBON_ART_GALLERY_HOVER_BACKGROUND_COLOUR:
+ self._gallery_hover_background_brush.SetColour(colour)
+ elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_COLOUR:
+ self._gallery_button_background_colour = colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_GRADIENT_COLOUR:
+ self._gallery_button_background_gradient_colour = colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_TOP_COLOUR:
+ self._gallery_button_background_top_brush.SetColour(colour)
+ elif id == RIBBON_ART_GALLERY_BUTTON_FACE_COLOUR:
+ self._gallery_button_face_colour = colour
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ self._gallery_up_bitmap[0] = RibbonLoadPixmap(gallery_left_xpm, colour)
+ self._gallery_down_bitmap[0] = RibbonLoadPixmap(gallery_right_xpm, colour)
+ else:
+ self._gallery_up_bitmap[0] = RibbonLoadPixmap(gallery_up_xpm, colour)
+ self._gallery_down_bitmap[0] = RibbonLoadPixmap(gallery_down_xpm, colour)
+
+ self._gallery_extension_bitmap[0] = RibbonLoadPixmap(gallery_extension_xpm, colour)
+
+ elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_COLOUR:
+ self._gallery_button_hover_background_colour = colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_GRADIENT_COLOUR:
+ self._gallery_button_hover_background_gradient_colour = colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_TOP_COLOUR:
+ self._gallery_button_hover_background_top_brush.SetColour(colour)
+ elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR:
+ self._gallery_button_hover_face_colour = colour
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ self._gallery_up_bitmap[1] = RibbonLoadPixmap(gallery_left_xpm, colour)
+ self._gallery_down_bitmap[1] = RibbonLoadPixmap(gallery_right_xpm, colour)
+ else:
+ self._gallery_up_bitmap[1] = RibbonLoadPixmap(gallery_up_xpm, colour)
+ self._gallery_down_bitmap[1] = RibbonLoadPixmap(gallery_down_xpm, colour)
+
+ self._gallery_extension_bitmap[1] = RibbonLoadPixmap(gallery_extension_xpm, colour)
+
+ elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_COLOUR:
+ self._gallery_button_active_background_colour = colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
+ self._gallery_button_active_background_gradient_colour = colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_TOP_COLOUR:
+ self._gallery_button_background_top_brush.SetColour(colour)
+ elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR:
+ self._gallery_button_active_face_colour = colour
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ self._gallery_up_bitmap[2] = RibbonLoadPixmap(gallery_left_xpm, colour)
+ self._gallery_down_bitmap[2] = RibbonLoadPixmap(gallery_right_xpm, colour)
+ else:
+ self._gallery_up_bitmap[2] = RibbonLoadPixmap(gallery_up_xpm, colour)
+ self._gallery_down_bitmap[2] = RibbonLoadPixmap(gallery_down_xpm, colour)
+
+ self._gallery_extension_bitmap[2] = RibbonLoadPixmap(gallery_extension_xpm, colour)
+
+ elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_COLOUR:
+ self._gallery_button_disabled_background_colour = colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_GRADIENT_COLOUR:
+ self._gallery_button_disabled_background_gradient_colour = colour
+ elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_TOP_COLOUR:
+ self._gallery_button_disabled_background_top_brush.SetColour(colour)
+ elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR:
+ self._gallery_button_disabled_face_colour = colour
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ self._gallery_up_bitmap[3] = RibbonLoadPixmap(gallery_left_xpm, colour)
+ self._gallery_down_bitmap[3] = RibbonLoadPixmap(gallery_right_xpm, colour)
+ else:
+ self._gallery_up_bitmap[3] = RibbonLoadPixmap(gallery_up_xpm, colour)
+ self._gallery_down_bitmap[3] = RibbonLoadPixmap(gallery_down_xpm, colour)
+
+ self._gallery_extension_bitmap[3] = RibbonLoadPixmap(gallery_extension_xpm, colour)
+
+ elif id == RIBBON_ART_GALLERY_ITEM_BORDER_COLOUR:
+ self._gallery_item_border_pen.SetColour(colour)
+
+ elif id in [RIBBON_ART_TAB_CTRL_BACKGROUND_COLOUR, RIBBON_ART_TAB_CTRL_BACKGROUND_GRADIENT_COLOUR]:
+ self._tab_ctrl_background_brush.SetColour(colour)
+ self._cached_tab_separator_visibility = -1.0
+ elif id == RIBBON_ART_TAB_LABEL_COLOUR:
+ self._tab_label_colour = colour
+ elif id == RIBBON_ART_TAB_SEPARATOR_COLOUR:
+ self._tab_separator_colour = colour
+ self._cached_tab_separator_visibility = -1.0
+ elif id == RIBBON_ART_TAB_SEPARATOR_GRADIENT_COLOUR:
+ self._tab_separator_gradient_colour = colour
+ self._cached_tab_separator_visibility = -1.0
+ elif id in [RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_COLOUR, RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR]:
+ pass
+ elif id == RIBBON_ART_TAB_ACTIVE_BACKGROUND_COLOUR:
+ self._tab_active_background_colour = colour
+ elif id == RIBBON_ART_TAB_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
+ self._tab_active_background_gradient_colour = colour
+ elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_TOP_COLOUR:
+ self._tab_hover_background_top_colour = colour
+ elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
+ self._tab_hover_background_top_gradient_colour = colour
+ elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_COLOUR:
+ self._tab_hover_background_colour = colour
+ elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_GRADIENT_COLOUR:
+ self._tab_hover_background_gradient_colour = colour
+ elif id == RIBBON_ART_TAB_BORDER_COLOUR:
+ self._tab_border_pen.SetColour(colour)
+ elif id == RIBBON_ART_PANEL_BORDER_COLOUR:
+ self._panel_border_pen.SetColour(colour)
+ elif id == RIBBON_ART_PANEL_BORDER_GRADIENT_COLOUR:
+ self._panel_border_gradient_pen.SetColour(colour)
+ elif id == RIBBON_ART_PANEL_MINIMISED_BORDER_COLOUR:
+ self._panel_minimised_border_pen.SetColour(colour)
+ elif id == RIBBON_ART_PANEL_MINIMISED_BORDER_GRADIENT_COLOUR:
+ self._panel_minimised_border_gradient_pen.SetColour(colour)
+ elif id in [RIBBON_ART_PANEL_LABEL_BACKGROUND_COLOUR, RIBBON_ART_PANEL_LABEL_BACKGROUND_GRADIENT_COLOUR]:
+ self._panel_label_background_brush.SetColour(colour)
+ elif id == RIBBON_ART_PANEL_LABEL_COLOUR:
+ self._panel_label_colour = colour
+ elif id in [RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_COLOUR, RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_GRADIENT_COLOUR]:
+ self._panel_hover_label_background_brush.SetColour(colour)
+ elif id == RIBBON_ART_PANEL_HOVER_LABEL_COLOUR:
+ self._panel_hover_label_colour = colour
+ elif id == RIBBON_ART_PANEL_MINIMISED_LABEL_COLOUR:
+ self._panel_minimised_label_colour = colour
+ elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_COLOUR:
+ self._panel_active_background_top_colour = colour
+ elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR:
+ self._panel_active_background_top_gradient_colour = colour
+ elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_COLOUR:
+ self._panel_active_background_colour = colour
+ elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
+ self._panel_active_background_gradient_colour = colour
+ elif id == RIBBON_ART_PANEL_BUTTON_FACE_COLOUR:
+ self._panel_button_face_colour = colour
+ self._panel_extension_bitmap[0] = RibbonLoadPixmap(panel_extension_xpm, colour)
+ elif id == RIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR:
+ self._panel_button_hover_face_colour = colour
+ self._panel_extension_bitmap[1] = RibbonLoadPixmap(panel_extension_xpm, colour)
+ elif id == RIBBON_ART_PAGE_BORDER_COLOUR:
+ self._page_border_pen.SetColour(colour)
+ elif id == RIBBON_ART_PAGE_BACKGROUND_TOP_COLOUR:
+ self._page_background_top_colour = colour
+ elif id == RIBBON_ART_PAGE_BACKGROUND_TOP_GRADIENT_COLOUR:
+ self._page_background_top_gradient_colour = colour
+ elif id == RIBBON_ART_PAGE_BACKGROUND_COLOUR:
+ self._page_background_colour = colour
+ elif id == RIBBON_ART_PAGE_BACKGROUND_GRADIENT_COLOUR:
+ self._page_background_gradient_colour = colour
+ elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_COLOUR:
+ self._page_hover_background_top_colour = colour
+ elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
+ self._page_hover_background_top_gradient_colour = colour
+ elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_COLOUR:
+ self._page_hover_background_colour = colour
+ elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_GRADIENT_COLOUR:
+ self._page_hover_background_gradient_colour = colour
+ elif id in [RIBBON_ART_TOOLBAR_BORDER_COLOUR, RIBBON_ART_TOOLBAR_HOVER_BORDER_COLOUR]:
+ self._toolbar_border_pen.SetColour(colour)
+ elif id == RIBBON_ART_TOOLBAR_FACE_COLOUR:
+ self._tool_face_colour = colour
+ self._toolbar_drop_bitmap = RibbonLoadPixmap(gallery_down_xpm, colour)
+ else:
+ raise Exception("Invalid Colour Ordinal")
+
+
+ def DrawTabCtrlBackground(self, dc, wnd, rect):
+ """
+ Draw the background of the tab region of a ribbon bar.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto;
+ :param `rect`: The rectangle within which to draw.
+
+ """
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ dc.SetBrush(self._tab_ctrl_background_brush)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+ dc.SetPen(self._page_border_pen)
+
+ if rect.width > 6:
+ dc.DrawLine(rect.x + 3, rect.y + rect.height - 1, rect.x + rect.width - 3, rect.y + rect.height - 1)
+ else:
+ dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1)
+
+
+ def DrawTab(self, dc, wnd, tab):
+ """
+ Draw a single tab in the tab region of a ribbon bar.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto (not the :class:`~lib.agw.ribbon.page.RibbonPage` associated
+ with the tab being drawn);
+ :param `tab`: The rectangle within which to draw, and also the tab label, icon, and
+ state (active and/or hovered). The drawing rectangle will be entirely within a
+ rectangle on the same device context previously painted with :meth:`~RibbonMSWArtProvider.DrawTabCtrlBackground`.
+ The rectangle's width will be at least the minimum value returned by :meth:`~RibbonMSWArtProvider.GetBarTabWidth`,
+ and height will be the value returned by :meth:`~RibbonMSWArtProvider.GetTabCtrlHeight`.
+
+ """
+
+ if tab.rect.height <= 2:
+ return
+
+ if tab.active or tab.hovered:
+ if tab.active:
+ background = wx.Rect(*tab.rect)
+ background.x += 2
+ background.y += 2
+ background.width -= 4
+ background.height -= 2
+
+ dc.GradientFillLinear(background, self._tab_active_background_colour,
+ self._tab_active_background_gradient_colour, wx.SOUTH)
+
+ # TODO: active and hovered
+
+ elif tab.hovered:
+ background = wx.Rect(*tab.rect)
+ background.x += 2
+ background.y += 2
+ background.width -= 4
+ background.height -= 3
+ h = background.height
+ background.height /= 2
+ dc.GradientFillLinear(background, self._tab_hover_background_top_colour,
+ self._tab_hover_background_top_gradient_colour, wx.SOUTH)
+
+ background.y += background.height
+ background.height = h - background.height
+ dc.GradientFillLinear(background, self._tab_hover_background_colour,
+ self._tab_hover_background_gradient_colour, wx.SOUTH)
+
+ border_points = [wx.Point() for i in xrange(6)]
+ border_points[0] = wx.Point(1, tab.rect.height - 2)
+ border_points[1] = wx.Point(1, 3)
+ border_points[2] = wx.Point(3, 1)
+ border_points[3] = wx.Point(tab.rect.width - 4, 1)
+ border_points[4] = wx.Point(tab.rect.width - 2, 3)
+ border_points[5] = wx.Point(tab.rect.width - 2, tab.rect.height - 1)
+
+ dc.SetPen(self._tab_border_pen)
+ dc.DrawLines(border_points, tab.rect.x, tab.rect.y)
+
+ if tab.active:
+ # Give the tab a curved outward border at the bottom
+ dc.DrawPoint(tab.rect.x, tab.rect.y + tab.rect.height - 2)
+ dc.DrawPoint(tab.rect.x + tab.rect.width - 1, tab.rect.y + tab.rect.height - 2)
+
+ p = wx.Pen(self._tab_active_background_gradient_colour)
+ dc.SetPen(p)
+
+ # Technically the first two points are the wrong colour, but they're near enough
+ dc.DrawPoint(tab.rect.x + 1, tab.rect.y + tab.rect.height - 2)
+ dc.DrawPoint(tab.rect.x + tab.rect.width - 2, tab.rect.y + tab.rect.height - 2)
+ dc.DrawPoint(tab.rect.x + 1, tab.rect.y + tab.rect.height - 1)
+ dc.DrawPoint(tab.rect.x, tab.rect.y + tab.rect.height - 1)
+ dc.DrawPoint(tab.rect.x + tab.rect.width - 2, tab.rect.y + tab.rect.height - 1)
+ dc.DrawPoint(tab.rect.x + tab.rect.width - 1, tab.rect.y + tab.rect.height - 1)
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS:
+ icon = tab.page.GetIcon()
+
+ if icon.IsOk():
+ x = tab.rect.x + 4
+ if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS == 0:
+ x = tab.rect.x + (tab.rect.width - icon.GetWidth()) / 2
+
+ dc.DrawBitmap(icon, x, tab.rect.y + 1 + (tab.rect.height - 1 - icon.GetHeight()) / 2, True)
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS:
+ label = tab.page.GetLabel()
+ if label.strip():
+ dc.SetFont(self._tab_label_font)
+ dc.SetTextForeground(self._tab_label_colour)
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+
+ text_width, text_height = dc.GetTextExtent(label)
+ width = tab.rect.width - 5
+ x = tab.rect.x + 3
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS:
+ x += 3 + tab.page.GetIcon().GetWidth()
+ width -= 3 + tab.page.GetIcon().GetWidth()
+
+ y = tab.rect.y + (tab.rect.height - text_height) / 2
+
+ if width <= text_width:
+ dc.SetClippingRegion(x, tab.rect.y, width, tab.rect.height)
+ dc.DrawText(label, x, y)
+ else:
+ dc.DrawText(label, x + (width - text_width) / 2 + 1, y)
+
+
+ def DrawTabSeparator(self, dc, wnd, rect, visibility):
+ """
+ Draw a separator between two tabs in a ribbon bar.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto;
+ :param `rect`: The rectangle within which to draw, which will be entirely
+ within a rectangle on the same device context previously painted with
+ :meth:`~RibbonMSWArtProvider.DrawTabCtrlBackground`;
+ :param `visibility`: The opacity with which to draw the separator. Values
+ are in the range [0, 1], with 0 being totally transparent, and 1 being totally
+ opaque.
+
+ """
+
+ if visibility <= 0.0:
+ return
+
+ if visibility > 1.0:
+ visibility = 1.0
+
+ # The tab separator is relatively expensive to draw (for its size), and is
+ # usually drawn multiple times sequentially (in different positions), so it
+ # makes sense to draw it once and cache it.
+ if not self._cached_tab_separator.IsOk() or self._cached_tab_separator.GetSize() != rect.GetSize() or \
+ visibility != self._cached_tab_separator_visibility:
+
+ size = wx.Rect(0, 0, *rect.GetSize())
+ self.ReallyDrawTabSeparator(wnd, size, visibility)
+
+ dc.DrawBitmap(self._cached_tab_separator, rect.x, rect.y, False)
+
+
+ def ReallyDrawTabSeparator(self, wnd, rect, visibility):
+
+ if not self._cached_tab_separator.IsOk() or self._cached_tab_separator.GetSize() != rect.GetSize():
+ self._cached_tab_separator = wx.EmptyBitmap(*rect.GetSize())
+
+ dc = wx.MemoryDC(self._cached_tab_separator)
+ self.DrawTabCtrlBackground(dc, wnd, rect)
+
+ x = rect.x + rect.width / 2
+ h = float(rect.height - 1)
+
+ r1 = self._tab_ctrl_background_brush.GetColour().Red() * (1.0 - visibility) + 0.5
+ g1 = self._tab_ctrl_background_brush.GetColour().Green() * (1.0 - visibility) + 0.5
+ b1 = self._tab_ctrl_background_brush.GetColour().Blue() * (1.0 - visibility) + 0.5
+ r2 = self._tab_separator_colour.Red()
+ g2 = self._tab_separator_colour.Green()
+ b2 = self._tab_separator_colour.Blue()
+ r3 = self._tab_separator_gradient_colour.Red()
+ g3 = self._tab_separator_gradient_colour.Green()
+ b3 = self._tab_separator_gradient_colour.Blue()
+
+ for i in xrange(rect.height-1):
+
+ p = float(i)/h
+
+ r = (p * r3 + (1.0 - p) * r2) * visibility + r1
+ g = (p * g3 + (1.0 - p) * g2) * visibility + g1
+ b = (p * b3 + (1.0 - p) * b2) * visibility + b1
+
+ P = wx.Pen(wx.Colour(r, g, b))
+ dc.SetPen(P)
+ dc.DrawPoint(x, rect.y + i)
+
+ self._cached_tab_separator_visibility = visibility
+
+
+ def DrawPartialPageBackground(self, dc, wnd, rect, allow_hovered_or_page=True, offset=None, hovered=False):
+
+ if isinstance(allow_hovered_or_page, types.BooleanType):
+ self.DrawPartialPageBackground2(dc, wnd, rect, allow_hovered_or_page)
+ else:
+ self.DrawPartialPageBackground1(dc, wnd, rect, allow_hovered_or_page, offset, hovered)
+
+
+ def DrawPartialPageBackground1(self, dc, wnd, rect, page, offset, hovered=False):
+
+ background = wx.Rect(0, 0, *page.GetSize())
+ background = page.AdjustRectToIncludeScrollButtons(background)
+ background.height -= 2
+
+ # Page background isn't dependant upon the width of the page
+ # (at least not the part of it intended to be painted by this
+ # function). Set to wider than the page itself for when externally
+ # expanded panels need a background - the expanded panel can be wider
+ # than the bar.
+
+ background.x = 0
+ background.width = 10000
+
+ # upper_rect, lower_rect, paint_rect are all in page co-ordinates
+ upper_rect = wx.Rect(*background)
+ upper_rect.height /= 5
+
+ lower_rect = wx.Rect(*background)
+ lower_rect.y += upper_rect.height
+ lower_rect.height -= upper_rect.height
+
+ paint_rect = wx.Rect(*rect)
+ paint_rect.x += offset.x
+ paint_rect.y += offset.y
+
+ if hovered:
+ bg_top = self._page_hover_background_top_colour
+ bg_top_grad = self._page_hover_background_top_gradient_colour
+ bg_btm = self._page_hover_background_colour
+ bg_btm_grad = self._page_hover_background_gradient_colour
+ else:
+ bg_top = self._page_background_top_colour
+ bg_top_grad = self._page_background_top_gradient_colour
+ bg_btm = self._page_background_colour
+ bg_btm_grad = self._page_background_gradient_colour
+
+ if paint_rect.Intersects(upper_rect):
+ rect = wx.Rect(*upper_rect)
+ rect.Intersect(paint_rect)
+ rect.x -= offset.x
+ rect.y -= offset.y
+ starting_colour = RibbonInterpolateColour(bg_top, bg_top_grad,
+ paint_rect.y, upper_rect.y,
+ upper_rect.y + upper_rect.height)
+ ending_colour = RibbonInterpolateColour(bg_top, bg_top_grad,
+ paint_rect.y + paint_rect.height, upper_rect.y,
+ upper_rect.y + upper_rect.height)
+ dc.GradientFillLinear(rect, starting_colour, ending_colour, wx.SOUTH)
+
+
+ if paint_rect.Intersects(lower_rect):
+ rect = wx.Rect(*lower_rect)
+ rect.Intersect(paint_rect)
+ rect.x -= offset.x
+ rect.y -= offset.y
+ starting_colour = RibbonInterpolateColour(bg_btm, bg_btm_grad,
+ paint_rect.y, lower_rect.y,
+ lower_rect.y + lower_rect.height)
+ ending_colour = RibbonInterpolateColour(bg_btm, bg_btm_grad,
+ paint_rect.y + paint_rect.height,
+ lower_rect.y, lower_rect.y + lower_rect.height)
+
+ dc.GradientFillLinear(rect, starting_colour, ending_colour, wx.SOUTH)
+
+
+ def DrawPageBackground(self, dc, wnd, rect):
+ """
+ Draw the background of a ribbon page.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto (which is commonly the
+ :class:`~lib.agw.ribbon.page.RibbonPage` whose background is being drawn, but doesn't have to be);
+ :param `rect`: The rectangle within which to draw.
+
+ :see: :meth:`~RibbonMSWArtProvider.GetPageBackgroundRedrawArea`
+ """
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._tab_ctrl_background_brush)
+
+ edge = wx.Rect(*rect)
+
+ edge.width = 2
+ dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height)
+
+ edge.x += rect.width - 2
+ dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height)
+
+ edge = wx.Rect(*rect)
+ edge.height = 2
+ edge.y += (rect.height - edge.height)
+ dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height)
+
+ background = wx.Rect(*rect)
+ background.x += 2
+ background.width -= 4
+ background.height -= 2
+
+ background.height /= 5
+ dc.GradientFillLinear(background, self._page_background_top_colour,
+ self._page_background_top_gradient_colour, wx.SOUTH)
+
+ background.y += background.height
+ background.height = rect.height - 2 - background.height
+ dc.GradientFillLinear(background, self._page_background_colour,
+ self._page_background_gradient_colour, wx.SOUTH)
+
+ border_points = [wx.Point() for i in xrange(8)]
+ border_points[0] = wx.Point(2, 0)
+ border_points[1] = wx.Point(1, 1)
+ border_points[2] = wx.Point(1, rect.height - 4)
+ border_points[3] = wx.Point(3, rect.height - 2)
+ border_points[4] = wx.Point(rect.width - 4, rect.height - 2)
+ border_points[5] = wx.Point(rect.width - 2, rect.height - 4)
+ border_points[6] = wx.Point(rect.width - 2, 1)
+ border_points[7] = wx.Point(rect.width - 4, -1)
+
+ dc.SetPen(self._page_border_pen)
+ dc.DrawLines(border_points, rect.x, rect.y)
+
+
+ def DrawScrollButton(self, dc, wnd, rect_, style):
+ """
+ Draw a ribbon-style scroll button.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto;
+ :param `rect`: The rectangle within which to draw. The size of this rectangle
+ will be at least the size returned by :meth:`~RibbonMSWArtProvider.GetScrollButtonMinimumSize` for a
+ scroll button with the same style. For tab scroll buttons, this rectangle
+ will be entirely within a rectangle on the same device context previously
+ painted with :meth:`~RibbonMSWArtProvider.DrawTabCtrlBackground`, but this is not guaranteed for other
+ types of button (for example, page scroll buttons will not be painted on an
+ area previously painted with :meth:`~RibbonMSWArtProvider.DrawPageBackground` );
+ :param `style`: A combination of flags from `RibbonScrollButtonStyle`,
+ including a direction, a for flag, and one or more states.
+
+ """
+
+ rect = wx.Rect(*rect_)
+
+ if (style & RIBBON_SCROLL_BTN_FOR_MASK) == RIBBON_SCROLL_BTN_FOR_PAGE:
+
+ # Page scroll buttons do not have the luxury of rendering on top of anything
+ # else, and their size includes some padding, hence the background painting
+ # and size adjustment.
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._tab_ctrl_background_brush)
+ dc.DrawRectangleRect(rect)
+ dc.SetClippingRect(rect)
+
+ result = style & RIBBON_SCROLL_BTN_DIRECTION_MASK
+
+ if result == RIBBON_SCROLL_BTN_LEFT:
+ rect.x += 1
+ elif result == RIBBON_SCROLL_BTN_RIGHT:
+ rect.y -= 1
+ rect.width -= 1
+ elif result == RIBBON_SCROLL_BTN_UP:
+ rect.x += 1
+ rect.y -= 1
+ rect.width -= 2
+ rect.height += 1
+ elif result == RIBBON_SCROLL_BTN_DOWN:
+ rect.x += 1
+ rect.width -= 2
+ rect.height -= 1
+
+ background = wx.Rect(*rect)
+ background.x += 1
+ background.y += 1
+ background.width -= 2
+ background.height -= 2
+
+ if style & RIBBON_SCROLL_BTN_UP:
+ background.height /= 2
+ else:
+ background.height /= 5
+
+ dc.GradientFillLinear(background, self._page_background_top_colour,
+ self._page_background_top_gradient_colour, wx.SOUTH)
+
+ background.y += background.height
+ background.height = rect.height - 2 - background.height
+ dc.GradientFillLinear(background, self._page_background_colour,
+ self._page_background_gradient_colour, wx.SOUTH)
+
+ border_points = [wx.Point() for i in xrange(7)]
+ result = style & RIBBON_SCROLL_BTN_DIRECTION_MASK
+
+ if result == RIBBON_SCROLL_BTN_LEFT:
+ border_points[0] = wx.Point(2, 0)
+ border_points[1] = wx.Point(rect.width - 1, 0)
+ border_points[2] = wx.Point(rect.width - 1, rect.height - 1)
+ border_points[3] = wx.Point(2, rect.height - 1)
+ border_points[4] = wx.Point(0, rect.height - 3)
+ border_points[5] = wx.Point(0, 2)
+
+ elif result == RIBBON_SCROLL_BTN_RIGHT:
+ border_points[0] = wx.Point(0, 0)
+ border_points[1] = wx.Point(rect.width - 3, 0)
+ border_points[2] = wx.Point(rect.width - 1, 2)
+ border_points[3] = wx.Point(rect.width - 1, rect.height - 3)
+ border_points[4] = wx.Point(rect.width - 3, rect.height - 1)
+ border_points[5] = wx.Point(0, rect.height - 1)
+
+ elif result == RIBBON_SCROLL_BTN_UP:
+ border_points[0] = wx.Point(2, 0)
+ border_points[1] = wx.Point(rect.width - 3, 0)
+ border_points[2] = wx.Point(rect.width - 1, 2)
+ border_points[3] = wx.Point(rect.width - 1, rect.height - 1)
+ border_points[4] = wx.Point(0, rect.height - 1)
+ border_points[5] = wx.Point(0, 2)
+
+ elif result == RIBBON_SCROLL_BTN_DOWN:
+ border_points[0] = wx.Point(0, 0)
+ border_points[1] = wx.Point(rect.width - 1, 0)
+ border_points[2] = wx.Point(rect.width - 1, rect.height - 3)
+ border_points[3] = wx.Point(rect.width - 3, rect.height - 1)
+ border_points[4] = wx.Point(2, rect.height - 1)
+ border_points[5] = wx.Point(0, rect.height - 3)
+
+ border_points[6] = border_points[0]
+
+ dc.SetPen(self._page_border_pen)
+ dc.DrawLines(border_points, rect.x, rect.y)
+
+ # NB: Code for handling hovered/active state is temporary
+ arrow_points = [wx.Point() for i in xrange(3)]
+ result = style & RIBBON_SCROLL_BTN_DIRECTION_MASK
+
+ if result == RIBBON_SCROLL_BTN_LEFT:
+ arrow_points[0] = wx.Point(rect.width / 2 - 2, rect.height / 2)
+ if style & RIBBON_SCROLL_BTN_ACTIVE:
+ arrow_points[0].y += 1
+ arrow_points[1] = arrow_points[0] + wx.Point(3, -3)
+ arrow_points[2] = arrow_points[0] + wx.Point(3, 3)
+
+ elif result == RIBBON_SCROLL_BTN_RIGHT:
+ arrow_points[0] = wx.Point(rect.width / 2 + 2, rect.height / 2)
+ if style & RIBBON_SCROLL_BTN_ACTIVE:
+ arrow_points[0].y += 1
+ arrow_points[1] = arrow_points[0] - wx.Point(3, 3)
+ arrow_points[2] = arrow_points[0] - wx.Point(3, -3)
+
+ elif result == RIBBON_SCROLL_BTN_UP:
+ arrow_points[0] = wx.Point(rect.width / 2, rect.height / 2 - 2)
+ if style & RIBBON_SCROLL_BTN_ACTIVE:
+ arrow_points[0].y += 1
+ arrow_points[1] = arrow_points[0] + wx.Point( 3, 3)
+ arrow_points[2] = arrow_points[0] + wx.Point(-3, 3)
+
+ elif result == RIBBON_SCROLL_BTN_DOWN:
+ arrow_points[0] = wx.Point(rect.width / 2, rect.height / 2 + 2)
+ if style & RIBBON_SCROLL_BTN_ACTIVE:
+ arrow_points[0].y += 1
+ arrow_points[1] = arrow_points[0] - wx.Point( 3, 3)
+ arrow_points[2] = arrow_points[0] - wx.Point(-3, 3)
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ B = wx.Brush((style & RIBBON_SCROLL_BTN_HOVERED and [self._tab_active_background_colour] or [self._tab_label_colour])[0])
+ dc.SetBrush(B)
+ dc.DrawPolygon(arrow_points, rect.x, rect.y)
+
+
+ def DrawDropdownArrow(self, dc, x, y, colour):
+
+ arrow_points = [wx.Point() for i in xrange(3)]
+ brush = wx.Brush(colour)
+ arrow_points[0] = wx.Point(1, 2)
+ arrow_points[1] = arrow_points[0] + wx.Point(-3, -3)
+ arrow_points[2] = arrow_points[0] + wx.Point( 3, -3)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(brush)
+ dc.DrawPolygon(arrow_points, x, y)
+
+
+ def RemovePanelPadding(self, rect):
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ rect.y += 1
+ rect.height -= 2
+ else:
+ rect.x += 1
+ rect.width -= 2
+
+ return rect
+
+
+ def DrawPanelBackground(self, dc, wnd, rect):
+ """
+ Draw the background and chrome for a ribbon panel.
+
+ This should draw the border, background, label, and any other items of a panel
+ which are outside the client area of a panel. Note that when a panel is
+ minimised, this function is not called - only :meth:`~RibbonMSWArtProvider.DrawMinimisedPanel` is called,
+ so a background should be explicitly painted by that if required.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto, which is always the panel
+ whose background and chrome is being drawn. The panel label and other panel
+ attributes can be obtained by querying this;
+ :param `rect`: The rectangle within which to draw.
+
+ """
+
+ self.DrawPartialPageBackground(dc, wnd, rect, False)
+
+ true_rect = wx.Rect(*rect)
+ true_rect = self.RemovePanelPadding(true_rect)
+
+ dc.SetFont(self._panel_label_font)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ has_ext_button = wnd.HasExtButton()
+
+ if wnd.IsHovered():
+ dc.SetBrush(self._panel_hover_label_background_brush)
+ dc.SetTextForeground(self._panel_hover_label_colour)
+ else:
+ dc.SetBrush(self._panel_label_background_brush)
+ dc.SetTextForeground(self._panel_label_colour)
+
+ label_rect = wx.Rect(*true_rect)
+ label = wnd.GetLabel().strip()
+ clip_label = False
+ label_size = wx.Size(*dc.GetTextExtent(label))
+
+ label_rect.SetX(label_rect.GetX() + 1)
+ label_rect.SetWidth(label_rect.GetWidth() - 2)
+ label_rect.SetHeight(label_size.GetHeight() + 2)
+ label_rect.SetY(true_rect.GetBottom() - label_rect.GetHeight())
+ label_height = label_rect.GetHeight()
+
+ label_bg_rect = wx.Rect(*label_rect)
+
+ if has_ext_button:
+ label_rect.SetWidth(label_rect.GetWidth() - 13)
+
+ if label_size.GetWidth() > label_rect.GetWidth():
+ # Test if there is enough length for 3 letters and ...
+ new_label = label[0:3] + "..."
+ label_size = wx.Size(*dc.GetTextExtent(new_label))
+
+ if label_size.GetWidth() > label_rect.GetWidth():
+ # Not enough room for three characters and ...
+ # Display the entire label and just crop it
+ clip_label = True
+ else:
+ # Room for some characters and ...
+ # Display as many characters as possible and append ...
+ for l in xrange(len(label)-1, 3, -1):
+ new_label = label[0:l] + "..."
+ label_size = wx.Size(*dc.GetTextExtent(new_label))
+ if label_size.GetWidth() <= label_rect.GetWidth():
+ label = new_label
+ break
+
+ dc.DrawRectangleRect(label_rect)
+
+ if clip_label:
+ clip = wx.DCClipper(dc, label_rect)
+ dc.DrawText(label, label_rect.x, label_rect.y + (label_rect.GetHeight() - label_size.GetHeight()) / 2)
+ else:
+ dc.DrawText(label, label_rect.x + (label_rect.GetWidth() - label_size.GetWidth()) / 2,
+ label_rect.y + (label_rect.GetHeight() - label_size.GetHeight()) / 2)
+
+ if has_ext_button:
+ if wnd.IsExtButtonHovered():
+ dc.SetPen(self._panel_hover_button_border_pen)
+ dc.SetBrush(self._panel_hover_button_background_brush)
+ dc.DrawRoundedRectangle(label_rect.GetRight(), label_rect.GetBottom() - 13, 13, 13, 1)
+ dc.DrawBitmap(self._panel_extension_bitmap[1], label_rect.GetRight() + 3, label_rect.GetBottom() - 10, True)
+ else:
+ dc.DrawBitmap(self._panel_extension_bitmap[0], label_rect.GetRight() + 3, label_rect.GetBottom() - 10, True)
+
+ if wnd.IsHovered():
+ client_rect = wx.Rect(*true_rect)
+ client_rect.x += 1
+ client_rect.width -= 2
+ client_rect.y += 1
+ client_rect.height -= 2 + label_height
+ self.DrawPartialPageBackground(dc, wnd, client_rect, True)
+
+ self.DrawPanelBorder(dc, true_rect, self._panel_border_pen, self._panel_border_gradient_pen)
+
+
+ def GetPanelExtButtonArea(self, dc, wnd, rect):
+ """
+ Retrieve the extension button area rectangle.
+
+ :param `dc`: The device context used to measure text extents;
+ :param `wnd`: The panel where the extension button resides;
+ :param `rect`: The panel client rectangle.
+ """
+
+ true_rect = wx.Rect(*self.RemovePanelPadding(rect))
+ true_rect = wx.Rect(true_rect.GetRight()-13, true_rect.GetBottom()-13, 13, 13)
+ return true_rect
+
+
+ def DrawGalleryBackground(self, dc, wnd, rect):
+ """
+ Draw the background and chrome for a :class:`~lib.agw.ribbon.gallery.RibbonGallery` control.
+
+ This should draw the border, brackground, scroll buttons, extension button, and
+ any other UI elements which are not attached to a specific gallery item.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto, which is always the gallery
+ whose background and chrome is being drawn. Attributes used during drawing like
+ the gallery hover state and individual button states can be queried from this
+ parameter by :meth:`RibbonGallery.IsHovered() <RibbonGallery.IsHovered>`, :meth:`RibbonGallery.GetExtensionButtonState() <RibbonGallery.GetExtensionButtonState>`,
+ :meth:`RibbonGallery.GetUpButtonState() <RibbonGallery.GetUpButtonState>`, and :meth:`RibbonGallery.GetDownButtonState() <RibbonGallery.GetDownButtonState>`;
+ :param `rect`: The rectangle within which to draw. This rectangle is the entire
+ area of the gallery control, not just the client rectangle.
+
+ """
+
+ self.DrawPartialPageBackground(dc, wnd, rect)
+
+ if wnd.IsHovered():
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self._gallery_hover_background_brush)
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ dc.DrawRectangle(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 16)
+ else:
+ dc.DrawRectangle(rect.x + 1, rect.y + 1, rect.width - 16, rect.height - 2)
+
+ dc.SetPen(self._gallery_border_pen)
+ # Outline
+ dc.DrawLine(rect.x + 1, rect.y, rect.x + rect.width - 1, rect.y)
+ dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1)
+ dc.DrawLine(rect.x + 1, rect.y + rect.height - 1, rect.x + rect.width - 1, rect.y + rect.height - 1)
+ dc.DrawLine(rect.x + rect.width - 1, rect.y + 1, rect.x + rect.width - 1, rect.y + rect.height - 1)
+
+ self.DrawGalleryBackgroundCommon(dc, wnd, rect)
+
+
+ def DrawGalleryBackgroundCommon(self, dc, wnd, rect):
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ # Divider between items and buttons
+ dc.DrawLine(rect.x, rect.y + rect.height - 15, rect.x + rect.width, rect.y + rect.height - 15)
+
+ up_btn = wx.Rect(rect.x, rect.y + rect.height - 15, rect.width / 3, 15)
+ down_btn = wx.Rect(up_btn.GetRight() + 1, up_btn.GetTop(), up_btn.GetWidth(), up_btn.GetHeight())
+ dc.DrawLine(down_btn.GetLeft(), down_btn.GetTop(), down_btn.GetLeft(), down_btn.GetBottom())
+ ext_btn = wx.Rect(down_btn.GetRight() + 1, up_btn.GetTop(), rect.width - up_btn.GetWidth() - down_btn.GetWidth() - 1, up_btn.GetHeight())
+ dc.DrawLine(ext_btn.GetLeft(), ext_btn.GetTop(), ext_btn.GetLeft(), ext_btn.GetBottom())
+
+ else:
+ # Divider between items and buttons
+ dc.DrawLine(rect.x + rect.width - 15, rect.y, rect.x + rect.width - 15, rect.y + rect.height)
+
+ up_btn = wx.Rect(rect.x + rect.width - 15, rect.y, 15, rect.height / 3)
+ down_btn = wx.Rect(up_btn.GetLeft(), up_btn.GetBottom() + 1, up_btn.GetWidth(), up_btn.GetHeight())
+ dc.DrawLine(down_btn.GetLeft(), down_btn.GetTop(), down_btn.GetRight(), down_btn.GetTop())
+ ext_btn = wx.Rect(up_btn.GetLeft(), down_btn.GetBottom() + 1, up_btn.GetWidth(), rect.height - up_btn.GetHeight() - down_btn.GetHeight() - 1)
+ dc.DrawLine(ext_btn.GetLeft(), ext_btn.GetTop(), ext_btn.GetRight(), ext_btn.GetTop())
+
+ self.DrawGalleryButton(dc, up_btn, wnd.GetUpButtonState(), self._gallery_up_bitmap)
+ self.DrawGalleryButton(dc, down_btn, wnd.GetDownButtonState(), self._gallery_down_bitmap)
+ self.DrawGalleryButton(dc, ext_btn, wnd.GetExtensionButtonState(), self._gallery_extension_bitmap)
+
+
+ def DrawGalleryButton(self, dc, rect, state, bitmaps):
+
+ if state == RIBBON_GALLERY_BUTTON_NORMAL:
+ btn_top_brush = self._gallery_button_background_top_brush
+ btn_colour = self._gallery_button_background_colour
+ btn_grad_colour = self._gallery_button_background_gradient_colour
+ btn_bitmap = bitmaps[0]
+ elif state == RIBBON_GALLERY_BUTTON_HOVERED:
+ btn_top_brush = self._gallery_button_hover_background_top_brush
+ btn_colour = self._gallery_button_hover_background_colour
+ btn_grad_colour = self._gallery_button_hover_background_gradient_colour
+ btn_bitmap = bitmaps[1]
+ elif state == RIBBON_GALLERY_BUTTON_ACTIVE:
+ btn_top_brush = self._gallery_button_active_background_top_brush
+ btn_colour = self._gallery_button_active_background_colour
+ btn_grad_colour = self._gallery_button_active_background_gradient_colour
+ btn_bitmap = bitmaps[2]
+ elif state == RIBBON_GALLERY_BUTTON_DISABLED:
+ btn_top_brush = self._gallery_button_disabled_background_top_brush
+ btn_colour = self._gallery_button_disabled_background_colour
+ btn_grad_colour = self._gallery_button_disabled_background_gradient_colour
+ btn_bitmap = bitmaps[3]
+
+ rect.x += 1
+ rect.y += 1
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ rect.width -= 1
+ rect.height -= 2
+ else:
+ rect.width -= 2
+ rect.height -= 1
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(btn_top_brush)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height / 2)
+
+ lower = wx.Rect(*rect)
+ lower.height = (lower.height + 1) / 2
+ lower.y += rect.height - lower.height
+ dc.GradientFillLinear(lower, btn_colour, btn_grad_colour, wx.SOUTH)
+
+ dc.DrawBitmap(btn_bitmap, rect.x + rect.width / 2 - 2, lower.y - 2, True)
+
+
+ def DrawGalleryItemBackground(self, dc, wnd, rect, item):
+ """
+ Draw the background of a single item in a :class:`~lib.agw.ribbon.gallery.RibbonGallery` control.
+
+ This is painted on top of a gallery background, and behind the items bitmap.
+ Unlike :meth:`~RibbonMSWArtProvider.DrawButtonBarButton` and :meth:`~RibbonMSWArtProvider.DrawTool`, it is not expected to draw the
+ item bitmap - that is done by the gallery control itself.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto, which is always the gallery
+ which contains the item being drawn;
+ :param `rect`: The rectangle within which to draw. The size of this rectangle
+ will be the size of the item's bitmap, expanded by gallery item padding values
+ (``RIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE``, ``RIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE``,
+ ``RIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE``, and ``RIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE``).
+ The drawing rectangle will be entirely within a rectangle on the same device
+ context previously painted with :meth:`~RibbonMSWArtProvider.DrawGalleryBackground`;
+ :param `item`: The item whose background is being painted. Typically the background
+ will vary if the item is hovered, active, or selected; :meth:`RibbonGallery.GetSelection() <RibbonGallery.GetSelection>`,
+ :meth:`RibbonGallery.GetActiveItem() <RibbonGallery.GetActiveItem>`, and :meth:`RibbonGallery.GetHoveredItem() <RibbonGallery.GetHoveredItem>` can be
+ called to test if the given item is in one of these states.
+
+ """
+
+ if wnd.GetHoveredItem() != item and wnd.GetActiveItem() != item and \
+ wnd.GetSelection() != item:
+ return
+
+ dc.SetPen(self._gallery_item_border_pen)
+ dc.DrawLine(rect.x + 1, rect.y, rect.x + rect.width - 1, rect.y)
+ dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1)
+ dc.DrawLine(rect.x + 1, rect.y + rect.height - 1, rect.x + rect.width - 1, rect.y + rect.height - 1)
+ dc.DrawLine(rect.x + rect.width - 1, rect.y + 1, rect.x + rect.width - 1, rect.y + rect.height - 1)
+
+ if wnd.GetActiveItem() == item or wnd.GetSelection() == item:
+ top_brush = self._gallery_button_active_background_top_brush
+ bg_colour = self._gallery_button_active_background_colour
+ bg_gradient_colour = self._gallery_button_active_background_gradient_colour
+ else:
+ top_brush = self._gallery_button_hover_background_top_brush
+ bg_colour = self._gallery_button_hover_background_colour
+ bg_gradient_colour = self._gallery_button_hover_background_gradient_colour
+
+ upper = wx.Rect(*rect)
+ upper.x += 1
+ upper.width -= 2
+ upper.y += 1
+ upper.height /= 3
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(top_brush)
+ dc.DrawRectangle(upper.x, upper.y, upper.width, upper.height)
+
+ lower = wx.Rect(*upper)
+ lower.y += lower.height
+ lower.height = rect.height - 2 - lower.height
+ dc.GradientFillLinear(lower, bg_colour, bg_gradient_colour, wx.SOUTH)
+
+
+ def DrawPanelBorder(self, dc, rect, primary_colour, secondary_colour):
+
+ border_points = [wx.Point() for i in xrange(9)]
+ border_points[0] = wx.Point(2, 0)
+ border_points[1] = wx.Point(rect.width - 3, 0)
+ border_points[2] = wx.Point(rect.width - 1, 2)
+ border_points[3] = wx.Point(rect.width - 1, rect.height - 3)
+ border_points[4] = wx.Point(rect.width - 3, rect.height - 1)
+ border_points[5] = wx.Point(2, rect.height - 1)
+ border_points[6] = wx.Point(0, rect.height - 3)
+ border_points[7] = wx.Point(0, 2)
+
+ if primary_colour.GetColour() == secondary_colour.GetColour():
+ border_points[8] = border_points[0]
+ dc.SetPen(primary_colour)
+ dc.DrawLines(border_points, rect.x, rect.y)
+ else:
+ dc.SetPen(primary_colour)
+ dc.DrawLines(border_points[0:3], rect.x, rect.y)
+
+ SingleLine(dc, rect, border_points[0], border_points[7])
+ dc.SetPen(secondary_colour)
+ dc.DrawLines(border_points[4:7], rect.x, rect.y)
+ SingleLine(dc, rect, border_points[4], border_points[3])
+
+ border_points[6] = border_points[2]
+ RibbonDrawParallelGradientLines(dc, 2, border_points[6:8], 0, 1,
+ border_points[3].y - border_points[2].y + 1, rect.x, rect.y,
+ primary_colour.GetColour(), secondary_colour.GetColour())
+
+
+ def DrawMinimisedPanel(self, dc, wnd, rect, bitmap):
+ """
+ Draw a minimised ribbon panel.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto, which is always the panel
+ which is minimised. The panel label can be obtained from this window. The
+ minimised icon obtained from querying the window may not be the size requested
+ by :meth:`~RibbonMSWArtProvider.GetMinimisedPanelMinimumSize` - the argument contains the icon in the
+ requested size;
+ :param `rect`: The rectangle within which to draw. The size of the rectangle
+ will be at least the size returned by :meth:`~RibbonMSWArtProvider.GetMinimisedPanelMinimumSize`;
+ :param `bitmap`: A copy of the panel's minimised bitmap rescaled to the size
+ returned by :meth:`~RibbonMSWArtProvider.GetMinimisedPanelMinimumSize`.
+
+ """
+
+ self.DrawPartialPageBackground(dc, wnd, rect, False)
+
+ true_rect = wx.Rect(*rect)
+ true_rect = self.RemovePanelPadding(true_rect)
+
+ if wnd.GetExpandedPanel() != None:
+ client_rect = wx.Rect(*true_rect)
+ client_rect.x += 1
+ client_rect.width -= 2
+ client_rect.y += 1
+ client_rect.height = (rect.y + rect.height / 5) - client_rect.x
+ dc.GradientFillLinear(client_rect,
+ self._panel_active_background_top_colour,
+ self._panel_active_background_top_gradient_colour, wx.SOUTH)
+
+ client_rect.y += client_rect.height
+ client_rect.height = (true_rect.y + true_rect.height) - client_rect.y
+ dc.GradientFillLinear(client_rect,
+ self._panel_active_background_colour,
+ self._panel_active_background_gradient_colour, wx.SOUTH)
+
+ elif wnd.IsHovered():
+ client_rect = wx.Rect(*true_rect)
+ client_rect.x += 1
+ client_rect.width -= 2
+ client_rect.y += 1
+ client_rect.height -= 2
+ self.DrawPartialPageBackground(dc, wnd, client_rect, True)
+
+ preview = self.DrawMinimisedPanelCommon(dc, wnd, true_rect)
+
+ dc.SetBrush(self._panel_hover_label_background_brush)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.DrawRectangle(preview.x + 1, preview.y + preview.height - 8, preview.width - 2, 7)
+
+ mid_pos = rect.y + rect.height / 5 - preview.y
+
+ if mid_pos < 0 or mid_pos >= preview.height:
+ full_rect = wx.Rect(*preview)
+ full_rect.x += 1
+ full_rect.y += 1
+ full_rect.width -= 2
+ full_rect.height -= 9
+ if mid_pos < 0:
+ dc.GradientFillLinear(full_rect, self._page_hover_background_colour,
+ self._page_hover_background_gradient_colour, wx.SOUTH)
+ else:
+ dc.GradientFillLinear(full_rect, self._page_hover_background_top_colour,
+ self._page_hover_background_top_gradient_colour, wx.SOUTH)
+
+ else:
+ top_rect = wx.Rect(*preview)
+ top_rect.x += 1
+ top_rect.y += 1
+ top_rect.width -= 2
+ top_rect.height = mid_pos
+ dc.GradientFillLinear(top_rect, self._page_hover_background_top_colour,
+ self._page_hover_background_top_gradient_colour, wx.SOUTH)
+
+ btm_rect = wx.Rect(*top_rect)
+ btm_rect.y = preview.y + mid_pos
+ btm_rect.height = preview.y + preview.height - 7 - btm_rect.y
+ dc.GradientFillLinear(btm_rect, self._page_hover_background_colour,
+ self._page_hover_background_gradient_colour, wx.SOUTH)
+
+ if bitmap.IsOk():
+ dc.DrawBitmap(bitmap, preview.x + (preview.width - bitmap.GetWidth()) / 2,
+ preview.y + (preview.height - 7 - bitmap.GetHeight()) / 2, True)
+
+ self.DrawPanelBorder(dc, preview, self._panel_border_pen, self._panel_border_gradient_pen)
+ self.DrawPanelBorder(dc, true_rect, self._panel_minimised_border_pen, self._panel_minimised_border_gradient_pen)
+
+
+ def DrawMinimisedPanelCommon(self, dc, wnd, true_rect):
+
+ preview = wx.Rect(0, 0, 32, 32)
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ preview.x = true_rect.x + 4
+ preview.y = true_rect.y + (true_rect.height - preview.height) / 2
+ else:
+ preview.x = true_rect.x + (true_rect.width - preview.width) / 2
+ preview.y = true_rect.y + 4
+
+ dc.SetFont(self._panel_label_font)
+ label_width, label_height = dc.GetTextExtent(wnd.GetLabel())
+
+ xpos = true_rect.x + (true_rect.width - label_width + 1) / 2
+ ypos = preview.y + preview.height + 5
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ xpos = preview.x + preview.width + 5
+ ypos = true_rect.y + (true_rect.height - label_height) / 2
+
+ dc.SetTextForeground(self._panel_minimised_label_colour)
+ dc.DrawText(wnd.GetLabel(), xpos, ypos)
+
+ arrow_points = [wx.Point() for i in xrange(3)]
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ xpos += label_width
+ arrow_points[0] = wx.Point(xpos + 5, ypos + label_height / 2)
+ arrow_points[1] = arrow_points[0] + wx.Point(-3, 3)
+ arrow_points[2] = arrow_points[0] + wx.Point(-3, -3)
+ else:
+ ypos += label_height
+ arrow_points[0] = wx.Point(true_rect.width / 2, ypos + 5)
+ arrow_points[1] = arrow_points[0] + wx.Point(-3, -3)
+ arrow_points[2] = arrow_points[0] + wx.Point( 3, -3)
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ B = wx.Brush(self._panel_minimised_label_colour)
+ dc.SetBrush(B)
+ dc.DrawPolygon(arrow_points, true_rect.x, true_rect.y)
+
+ return preview
+
+
+ def DrawButtonBarBackground(self, dc, wnd, rect):
+ """
+ Draw the background for a :class:`~lib.agw.ribbon.buttonbar.RibbonButtonBar` control.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto (which will typically be
+ the button bar itself, though this is not guaranteed);
+ :param `rect`: The rectangle within which to draw.
+
+ """
+
+ self.DrawPartialPageBackground(dc, wnd, rect, True)
+
+
+ def DrawPartialPageBackground2(self, dc, wnd, rect, allow_hovered=True):
+
+ # Assume the window is a child of a ribbon page, and also check for a
+ # hovered panel somewhere between the window and the page, as it causes
+ # the background to change.
+ offset = wx.Point(*wnd.GetPosition())
+ page = None
+ parent = wnd.GetParent()
+ hovered = False
+ panel = None
+
+ if isinstance(wnd, PANEL.RibbonPanel):
+ panel = wnd
+ hovered = allow_hovered and panel.IsHovered()
+ if panel.GetExpandedDummy() != None:
+ offset = panel.GetExpandedDummy().GetPosition()
+ parent = panel.GetExpandedDummy().GetParent()
+
+ while 1:
+
+ if panel is None:
+ panel = parent
+ if isinstance(panel, PANEL.RibbonPanel):
+ hovered = allow_hovered and panel.IsHovered()
+ if panel.GetExpandedDummy() != None:
+ parent = panel.GetExpandedDummy()
+
+ page = parent
+ if isinstance(page, PAGE.RibbonPage):
+ break
+
+ offset += parent.GetPosition()
+ parent = parent.GetParent()
+ if parent is None:
+ break
+
+ if page != None:
+ self.DrawPartialPageBackground(dc, wnd, rect, page, offset, hovered)
+ return
+
+ # No page found - fallback to painting with a stock brush
+ dc.SetBrush(wx.WHITE_BRUSH)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+
+
+ def DrawButtonBarButton(self, dc, wnd, rect, kind, state, label, bitmap_large, bitmap_small):
+ """
+ Draw a single button for a :class:`~lib.agw.ribbon.buttonbar.RibbonButtonBar` control.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto;
+ :param `rect`: The rectangle within which to draw. The size of this rectangle
+ will be a size previously returned by :meth:`~RibbonMSWArtProvider.GetButtonBarButtonSize`, and the
+ rectangle will be entirely within a rectangle on the same device context
+ previously painted with :meth:`~RibbonMSWArtProvider.DrawButtonBarBackground`;
+ :param `kind`: The kind of button to draw (normal, dropdown or hybrid);
+ :param `state`: Combination of a size flag and state flags from the
+ `RibbonButtonBarButtonState` enumeration;
+ :param `label`: The label of the button;
+ :param `bitmap_large`: The large bitmap of the button (or the large disabled
+ bitmap when ``RIBBON_BUTTONBAR_BUTTON_DISABLED`` is set in `state`);
+ :param `bitmap_small`: The small bitmap of the button (or the small disabled
+ bitmap when ``RIBBON_BUTTONBAR_BUTTON_DISABLED`` is set in `state`).
+
+ """
+
+ if kind == RIBBON_BUTTON_TOGGLE:
+ kind = RIBBON_BUTTON_NORMAL
+ if state & RIBBON_BUTTONBAR_BUTTON_TOGGLED:
+ state ^= RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK
+
+ if state & (RIBBON_BUTTONBAR_BUTTON_HOVER_MASK | RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK):
+ if state & RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK:
+ dc.SetPen(self._button_bar_active_border_pen)
+ else:
+ dc.SetPen(self._button_bar_hover_border_pen)
+
+ bg_rect = wx.Rect(*rect)
+ bg_rect.x += 1
+ bg_rect.y += 1
+ bg_rect.width -= 2
+ bg_rect.height -= 2
+
+ bg_rect_top = wx.Rect(*bg_rect)
+ bg_rect_top.height /= 3
+ bg_rect.y += bg_rect_top.height
+ bg_rect.height -= bg_rect_top.height
+
+ if kind == RIBBON_BUTTON_HYBRID:
+
+ result = state & RIBBON_BUTTONBAR_BUTTON_SIZE_MASK
+
+ if result == RIBBON_BUTTONBAR_BUTTON_LARGE:
+ iYBorder = rect.y + bitmap_large.GetHeight() + 4
+ partial_bg = wx.Rect(*rect)
+
+ if state & RIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED:
+ partial_bg.SetBottom(iYBorder - 1)
+ else:
+ partial_bg.height -= (iYBorder - partial_bg.y + 1)
+ partial_bg.y = iYBorder + 1
+
+ dc.DrawLine(rect.x, iYBorder, rect.x + rect.width, iYBorder)
+ bg_rect.Intersect(partial_bg)
+ bg_rect_top.Intersect(partial_bg)
+
+ elif result == RIBBON_BUTTONBAR_BUTTON_MEDIUM:
+ iArrowWidth = 9
+
+ if state & RIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED:
+ bg_rect.width -= iArrowWidth
+ bg_rect_top.width -= iArrowWidth
+ dc.DrawLine(bg_rect_top.x + bg_rect_top.width, rect.y, bg_rect_top.x + bg_rect_top.width,
+ rect.y + rect.height)
+ else:
+ iArrowWidth -= 1
+ bg_rect.x += bg_rect.width - iArrowWidth
+ bg_rect_top.x += bg_rect_top.width - iArrowWidth
+ bg_rect.width = iArrowWidth
+ bg_rect_top.width = iArrowWidth
+ dc.DrawLine(bg_rect_top.x - 1, rect.y, bg_rect_top.x - 1, rect.y + rect.height)
+
+ if state & RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK:
+
+ dc.GradientFillLinear(bg_rect_top, self._button_bar_active_background_top_colour,
+ self._button_bar_active_background_top_gradient_colour, wx.SOUTH)
+ dc.GradientFillLinear(bg_rect, self._button_bar_active_background_colour,
+ self._button_bar_active_background_gradient_colour, wx.SOUTH)
+
+ else:
+ dc.GradientFillLinear(bg_rect_top, self._button_bar_hover_background_top_colour,
+ self._button_bar_hover_background_top_gradient_colour, wx.SOUTH)
+ dc.GradientFillLinear(bg_rect, self._button_bar_hover_background_colour,
+ self._button_bar_hover_background_gradient_colour, wx.SOUTH)
+
+ border_points = [wx.Point() for i in xrange(9)]
+ border_points[0] = wx.Point(2, 0)
+ border_points[1] = wx.Point(rect.width - 3, 0)
+ border_points[2] = wx.Point(rect.width - 1, 2)
+ border_points[3] = wx.Point(rect.width - 1, rect.height - 3)
+ border_points[4] = wx.Point(rect.width - 3, rect.height - 1)
+ border_points[5] = wx.Point(2, rect.height - 1)
+ border_points[6] = wx.Point(0, rect.height - 3)
+ border_points[7] = wx.Point(0, 2)
+ border_points[8] = border_points[0]
+
+ dc.DrawLines(border_points, rect.x, rect.y)
+
+ dc.SetFont(self._button_bar_label_font)
+ dc.SetTextForeground(self._button_bar_label_colour)
+ self.DrawButtonBarButtonForeground(dc, rect, kind, state, label, bitmap_large, bitmap_small)
+
+
+ def DrawButtonBarButtonForeground(self, dc, rect, kind, state, label, bitmap_large, bitmap_small):
+
+ result = state & RIBBON_BUTTONBAR_BUTTON_SIZE_MASK
+
+ if result == RIBBON_BUTTONBAR_BUTTON_LARGE:
+
+ padding = 2
+ dc.DrawBitmap(bitmap_large, rect.x + (rect.width - bitmap_large.GetWidth()) / 2,
+ rect.y + padding, True)
+ ypos = rect.y + padding + bitmap_large.GetHeight() + padding
+ arrow_width = (kind == RIBBON_BUTTON_NORMAL and [0] or [8])[0]
+
+ label_w, label_h = dc.GetTextExtent(label)
+
+ if label_w + 2 * padding <= rect.width:
+
+ dc.DrawText(label, rect.x + (rect.width - label_w) / 2, ypos)
+ if arrow_width != 0:
+ self.DrawDropdownArrow(dc, rect.x + rect.width / 2,
+ ypos + (label_h * 3) / 2,
+ self._button_bar_label_colour)
+ else:
+ breaki = len(label)
+
+ while breaki > 0:
+ breaki -= 1
+ if RibbonCanLabelBreakAtPosition(label, breaki):
+ label_top = label[0:breaki]
+ label_w, label_h = dc.GetTextExtent(label_top)
+
+ if label_w + 2 * padding <= rect.width:
+ dc.DrawText(label_top, rect.x + (rect.width - label_w) / 2, ypos)
+ ypos += label_h
+ label_bottom = label[breaki:]
+ label_w, label_h = dc.GetTextExtent(label_bottom)
+ label_w += arrow_width
+ iX = rect.x + (rect.width - label_w) / 2
+ dc.DrawText(label_bottom, iX, ypos)
+
+ if arrow_width != 0:
+ self.DrawDropdownArrow(dc, iX + 2 +label_w - arrow_width,
+ ypos + label_h / 2 + 1,
+ self._button_bar_label_colour)
+
+ break
+
+ elif result == RIBBON_BUTTONBAR_BUTTON_MEDIUM:
+
+ x_cursor = rect.x + 2
+ dc.DrawBitmap(bitmap_small, x_cursor, rect.y + (rect.height - bitmap_small.GetHeight())/2, True)
+ x_cursor += bitmap_small.GetWidth() + 2
+ label_w, label_h = dc.GetTextExtent(label)
+ dc.DrawText(label, x_cursor, rect.y + (rect.height - label_h) / 2)
+ x_cursor += label_w + 3
+
+ if kind != RIBBON_BUTTON_NORMAL:
+ self.DrawDropdownArrow(dc, x_cursor, rect.y + rect.height / 2,
+ self._button_bar_label_colour)
+
+ else:
+ # TODO
+ pass
+
+
+ def DrawToolBarBackground(self, dc, wnd, rect):
+ """
+ Draw the background for a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar` control.
+
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The which is being drawn onto. In most cases this will be a
+ :class:`~lib.agw.ribbon.toolbar.RibbonToolBar`, but it doesn't have to be;
+ :param `rect`: The rectangle within which to draw. Some of this rectangle
+ will later be drawn over using :meth:`~RibbonMSWArtProvider.DrawToolGroupBackground` and :meth:`~RibbonMSWArtProvider.DrawTool`,
+ but not all of it will (unless there is only a single group of tools).
+
+ """
+
+ self.DrawPartialPageBackground(dc, wnd, rect)
+
+
+ def DrawToolGroupBackground(self, dc, wnd, rect):
+ """
+ Draw the background for a group of tools on a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar` control.
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto. In most cases this will
+ be a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar`, but it doesn't have to be;
+ :param `rect`: The rectangle within which to draw. This rectangle is a union
+ of the individual tools' rectangles. As there are no gaps between tools,
+ this rectangle will be painted over exactly once by calls to :meth:`~RibbonMSWArtProvider.DrawTool`.
+ The group background could therefore be painted by :meth:`~RibbonMSWArtProvider.DrawTool`, though it
+ can be conceptually easier and more efficient to draw it all at once here.
+ The rectangle will be entirely within a rectangle on the same device context
+ previously painted with :meth:`~RibbonMSWArtProvider.DrawToolBarBackground`.
+
+ """
+
+ dc.SetPen(self._toolbar_border_pen)
+ outline = [wx.Point() for i in xrange(9)]
+ outline[0] = wx.Point(2, 0)
+ outline[1] = wx.Point(rect.width - 3, 0)
+ outline[2] = wx.Point(rect.width - 1, 2)
+ outline[3] = wx.Point(rect.width - 1, rect.height - 3)
+ outline[4] = wx.Point(rect.width - 3, rect.height - 1)
+ outline[5] = wx.Point(2, rect.height - 1)
+ outline[6] = wx.Point(0, rect.height - 3)
+ outline[7] = wx.Point(0, 2)
+ outline[8] = outline[0]
+
+ dc.DrawLines(outline, rect.x, rect.y)
+
+
+ def DrawTool(self, dc, wnd, rect, bitmap, kind, state):
+ """
+ Draw a single tool (for a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar` control).
+
+ :param `dc`: The device context to draw onto;
+ :param `wnd`: The window which is being drawn onto. In most cases this will
+ be a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar`, but it doesn't have to be;
+ :param `rect`: The rectangle within which to draw. The size of this rectangle
+ will at least the size returned by :meth:`~RibbonMSWArtProvider.GetToolSize`, and the height of it will
+ be equal for all tools within the same group. The rectangle will be entirely
+ within a rectangle on the same device context previously painted with
+ :meth:`~RibbonMSWArtProvider.DrawToolGroupBackground`;
+ :param `bitmap`: The bitmap to use as the tool's foreground. If the tool is a
+ hybrid or dropdown tool, then the foreground should also contain a standard
+ dropdown button;
+ :param `kind`: The kind of tool to draw (normal, dropdown, or hybrid);
+ :param `state`: A combination of `RibbonToolBarToolState` flags giving the
+ state of the tool and it's relative position within a tool group.
+
+ """
+
+ if kind == RIBBON_BUTTON_TOGGLE:
+ if state & RIBBON_TOOLBAR_TOOL_TOGGLED:
+ state ^= RIBBON_TOOLBAR_TOOL_ACTIVE_MASK
+
+ bg_rect = wx.Rect(*rect)
+ bg_rect.Deflate(1, 1)
+
+ if state & RIBBON_TOOLBAR_TOOL_LAST == 0:
+ bg_rect.width += 1
+
+ is_split_hybrid = (kind == RIBBON_BUTTON_HYBRID and (state & (RIBBON_TOOLBAR_TOOL_HOVER_MASK | RIBBON_TOOLBAR_TOOL_ACTIVE_MASK)))
+
+ # Background
+ bg_rect_top = wx.Rect(*bg_rect)
+ bg_rect_top.height = (bg_rect_top.height * 2) / 5
+ bg_rect_btm = wx.Rect(*bg_rect)
+ bg_rect_btm.y += bg_rect_top.height
+ bg_rect_btm.height -= bg_rect_top.height
+
+ bg_top_colour = self._tool_background_top_colour
+ bg_top_grad_colour = self._tool_background_top_gradient_colour
+ bg_colour = self._tool_background_colour
+ bg_grad_colour = self._tool_background_gradient_colour
+
+ if state & RIBBON_TOOLBAR_TOOL_ACTIVE_MASK:
+ bg_top_colour = self._tool_active_background_top_colour
+ bg_top_grad_colour = self._tool_active_background_top_gradient_colour
+ bg_colour = self._tool_active_background_colour
+ bg_grad_colour = self._tool_active_background_gradient_colour
+
+ elif state & RIBBON_TOOLBAR_TOOL_HOVER_MASK:
+ bg_top_colour = self._tool_hover_background_top_colour
+ bg_top_grad_colour = self._tool_hover_background_top_gradient_colour
+ bg_colour = self._tool_hover_background_colour
+ bg_grad_colour = self._tool_hover_background_gradient_colour
+
+ dc.GradientFillLinear(bg_rect_top, bg_top_colour, bg_top_grad_colour, wx.SOUTH)
+ dc.GradientFillLinear(bg_rect_btm, bg_colour, bg_grad_colour, wx.SOUTH)
+
+ if is_split_hybrid:
+ nonrect = wx.Rect(*bg_rect)
+ if state & (RIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED | RIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE):
+ nonrect.width -= 8
+ else:
+ nonrect.x += nonrect.width - 8
+ nonrect.width = 8
+
+ B = wx.Brush(self._tool_hover_background_top_colour)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(B)
+ dc.DrawRectangle(nonrect.x, nonrect.y, nonrect.width, nonrect.height)
+
+ # Border
+ dc.SetPen(self._toolbar_border_pen)
+
+ if state & RIBBON_TOOLBAR_TOOL_FIRST:
+ dc.DrawPoint(rect.x + 1, rect.y + 1)
+ dc.DrawPoint(rect.x + 1, rect.y + rect.height - 2)
+ else:
+ dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1)
+
+ if state & RIBBON_TOOLBAR_TOOL_LAST:
+ dc.DrawPoint(rect.x + rect.width - 2, rect.y + 1)
+ dc.DrawPoint(rect.x + rect.width - 2, rect.y + rect.height - 2)
+
+ # Foreground
+ avail_width = bg_rect.GetWidth()
+
+ if kind & RIBBON_BUTTON_DROPDOWN:
+ avail_width -= 8
+ if is_split_hybrid:
+ dc.DrawLine(rect.x + avail_width + 1, rect.y, rect.x + avail_width + 1, rect.y + rect.height)
+
+ dc.DrawBitmap(self._toolbar_drop_bitmap, bg_rect.x + avail_width + 2,
+ bg_rect.y + (bg_rect.height / 2) - 2, True)
+
+ dc.DrawBitmap(bitmap, bg_rect.x + (avail_width - bitmap.GetWidth()) / 2,
+ bg_rect.y + (bg_rect.height - bitmap.GetHeight()) / 2, True)
+
+
+ def GetBarTabWidth(self, dc, wnd, label, bitmap, ideal=None, small_begin_need_separator=None,
+ small_must_have_separator=None, minimum=None):
+
+ """
+ Calculate the ideal and minimum width (in pixels) of a tab in a ribbon bar.
+
+ :param `dc`: A device context to use when one is required for size calculations;
+ :param `wnd`: The window onto which the tab will eventually be drawn;
+ :param `label`: The tab's label (or "" if it has none);
+ :param `bitmap`: The tab's icon (or :class:`NullBitmap` if it has none);
+ :param `ideal`: The ideal width (in pixels) of the tab;
+ :param `small_begin_need_separator`: A size less than the size, at which a
+ tab separator should begin to be drawn (i.e. drawn, but still fairly transparent);
+ :param `small_must_have_separator`: A size less than the size, at which a
+ tab separator must be drawn (i.e. drawn at full opacity);
+ :param `minimum`: A size less than the size, and greater than or equal to
+ zero, which is the minimum pixel width for the tab.
+
+ """
+
+ width = 0
+ mini = 0
+
+ if (self._flags & RIBBON_BAR_SHOW_PAGE_LABELS) and label.strip():
+ dc.SetFont(self._tab_label_font)
+ width += dc.GetTextExtent(label)[0]
+ mini += min(25, width) # enough for a few chars
+
+ if bitmap.IsOk():
+ # gap between label and bitmap
+ width += 4
+ mini += 2
+
+ if (self._flags & RIBBON_BAR_SHOW_PAGE_ICONS) and bitmap.IsOk():
+ width += bitmap.GetWidth()
+ mini += bitmap.GetWidth()
+
+ ideal = width + 30
+ small_begin_need_separator = width + 20
+ small_must_have_separator = width + 10
+ minimum = mini
+
+ return ideal, small_begin_need_separator, small_must_have_separator, minimum
+
+
+ def GetTabCtrlHeight(self, dc, wnd, pages):
+ """
+ Calculate the height (in pixels) of the tab region of a ribbon bar.
+
+ Note that as the tab region can contain scroll buttons, the height should be
+ greater than or equal to the minimum height for a tab scroll button.
+
+ :param `dc`: A device context to use when one is required for size calculations;
+ :param `wnd`: The window onto which the tabs will eventually be drawn;
+ :param `pages`: The tabs which will acquire the returned height.
+
+ """
+
+ text_height = 0
+ icon_height = 0
+
+ if len(pages) <= 1 and (self._flags & RIBBON_BAR_ALWAYS_SHOW_TABS) == 0:
+ # To preserve space, a single tab need not be displayed. We still need
+ # two pixels of border / padding though.
+ return 2
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS:
+ dc.SetFont(self._tab_label_font)
+ text_height = dc.GetTextExtent("ABCDEFXj")[1] + 10
+
+ if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS:
+ for info in pages:
+ if info.page.GetIcon().IsOk():
+ icon_height = max(icon_height, info.page.GetIcon().GetHeight() + 4)
+
+ return max(text_height, icon_height)
+
+
+ def GetScrollButtonMinimumSize(self, dc, wnd, style):
+ """
+ Calculate the minimum size (in pixels) of a scroll button.
+
+ :param `dc`: A device context to use when one is required for size calculations;
+ :param `wnd`: The window onto which the scroll button will eventually be drawn;
+ :param `style`: A combination of flags from `RibbonScrollButtonStyle`, including
+ a direction, and a for flag (state flags may be given too, but should be ignored,
+ as a button should retain a constant size, regardless of its state).
+
+ """
+
+ return wx.Size(12, 12)
+
+
+ def GetPanelSize(self, dc, wnd, client_size, client_offset=None):
+ """
+ Calculate the size of a panel for a given client size.
+
+ This should increment the given size by enough to fit the panel label and other
+ chrome.
+
+ :param `dc`: A device context to use if one is required for size calculations;
+ :param `wnd`: The ribbon panel in question;
+ :param `client_size`: The client size;
+ :param `client_offset`: The offset where the client rectangle begins within the
+ panel (may be ``None``).
+
+ :see: :meth:`~RibbonMSWArtProvider.GetPanelClientSize`
+ """
+
+ dc.SetFont(self._panel_label_font)
+ label_size = wx.Size(*dc.GetTextExtent(wnd.GetLabel()))
+
+ client_size.IncBy(0, label_size.GetHeight())
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ client_size.IncBy(4, 8)
+ else:
+ client_size.IncBy(6, 6)
+
+ if client_offset != None:
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ client_offset = wx.Point(2, 3)
+ else:
+ client_offset = wx.Point(3, 2)
+
+ return client_size
+
+
+ def GetPanelClientSize(self, dc, wnd, size, client_offset=None):
+ """
+ Calculate the client size of a panel for a given overall size.
+
+ This should act as the inverse to :meth:`~RibbonMSWArtProvider.GetPanelSize`, and decrement the given size
+ by enough to fit the panel label and other chrome.
+
+ :param `dc`: A device context to use if one is required for size calculations;
+ :param `wnd`: The ribbon panel in question;
+ :param `size`: The overall size to calculate client size for;
+ :param `client_offset`: The offset where the returned client size begins within
+ the given (may be ``None``).
+
+ :see: :meth:`~RibbonMSWArtProvider.GetPanelSize`
+ """
+
+ dc.SetFont(self._panel_label_font)
+ label_size = wx.Size(*dc.GetTextExtent(wnd.GetLabel()))
+
+ size.DecBy(0, label_size.GetHeight())
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ size.DecBy(4, 8)
+ else:
+ size.DecBy(6, 6)
+
+ if client_offset != None:
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ client_offset = wx.Point(2, 3)
+ else:
+ client_offset = wx.Point(3, 2)
+
+ if size.x < 0:
+ size.x = 0
+ if size.y < 0:
+ size.y = 0
+
+ return size, client_offset
+
+
+ def GetGallerySize(self, dc, wnd, client_size):
+ """
+ Calculate the size of a :class:`~lib.agw.ribbon.gallery.RibbonGallery` control for a given client size.
+
+ This should increment the given size by enough to fit the gallery border,
+ buttons, and any other chrome.
+
+ :param `dc`: A device context to use if one is required for size calculations;
+ :param `wnd`: The gallery in question;
+ :param `client_size`: The client size.
+
+ :see: :meth:`~RibbonMSWArtProvider.GetGalleryClientSize`
+ """
+
+ client_size.IncBy(2, 1) # Left / top padding
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ client_size.IncBy(1, 16) # Right / bottom padding
+ else:
+ client_size.IncBy(16, 1) # Right / bottom padding
+
+ return client_size
+
+
+ def GetGalleryClientSize(self, dc, wnd, size, client_offset=None, scroll_up_button=None,
+ scroll_down_button=None, extension_button=None):
+
+ """
+ Calculate the client size of a :class:`~lib.agw.ribbon.gallery.RibbonGallery` control for a given size.
+
+ This should act as the inverse to :meth:`~RibbonMSWArtProvider.GetGallerySize`, and decrement the given
+ size by enough to fir the gallery border, buttons, and other chrome.
+
+ :param `dc`: A device context to use if one is required for size calculations;
+ :param `wnd`: The gallery in question;
+ :param `size`: The overall size to calculate the client size for;
+ :param `client_offset`: The position within the given size at which the
+ returned client size begins;
+ :param `scroll_up_button`: The rectangle within the given size which the
+ scroll up button occupies;
+ :param `scroll_down_button`: The rectangle within the given size which the
+ scroll down button occupies;
+ :param `extension_button`: The rectangle within the given size which the
+ extension button occupies.
+
+ """
+
+ scroll_up = wx.Rect()
+ scroll_down = wx.Rect()
+ extension = wx.Rect()
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ # Flow is vertical - put buttons on bottom
+ scroll_up.y = size.GetHeight() - 15
+ scroll_up.height = 15
+ scroll_up.x = 0
+ scroll_up.width = (size.GetWidth() + 2) / 3
+ scroll_down.y = scroll_up.y
+ scroll_down.height = scroll_up.height
+ scroll_down.x = scroll_up.x + scroll_up.width
+ scroll_down.width = scroll_up.width
+ extension.y = scroll_down.y
+ extension.height = scroll_down.height
+ extension.x = scroll_down.x + scroll_down.width
+ extension.width = size.GetWidth() - scroll_up.width - scroll_down.width
+ size.DecBy(1, 16)
+ size.DecBy(2, 1)
+
+ else:
+ # Flow is horizontal - put buttons on right
+ scroll_up.x = size.GetWidth() - 15
+ scroll_up.width = 15
+ scroll_up.y = 0
+ scroll_up.height = (size.GetHeight() + 2) / 3
+ scroll_down.x = scroll_up.x
+ scroll_down.width = scroll_up.width
+ scroll_down.y = scroll_up.y + scroll_up.height
+ scroll_down.height = scroll_up.height
+ extension.x = scroll_down.x
+ extension.width = scroll_down.width
+ extension.y = scroll_down.y + scroll_down.height
+ extension.height = size.GetHeight() - scroll_up.height - scroll_down.height
+ size.DecBy(16, 1)
+ size.DecBy( 2, 1)
+
+ client_offset = wx.Point(2, 1)
+ scroll_up_button = scroll_up
+ scroll_down_button = scroll_down
+ extension_button = extension
+
+ return size, client_offset, scroll_up_button, scroll_down_button, extension_button
+
+
+ def GetPageBackgroundRedrawArea(self, dc, wnd, page_old_size, page_new_size):
+ """
+ Calculate the portion of a page background which needs to be redrawn when a page
+ is resized.
+
+ To optimise the drawing of page backgrounds, as small an area as possible should
+ be returned. Of couse, if the way in which a background is drawn means that the
+ entire background needs to be repainted on resize, then the entire new size
+ should be returned.
+
+ :param `dc`: A device context to use when one is required for size calculations;
+ :param `wnd`: The page which is being resized;
+ :param `page_old_size`: The size of the page prior to the resize (which has
+ already been painted);
+ :param `page_new_size`: The size of the page after the resize.
+
+ """
+
+ if page_new_size.GetWidth() != page_old_size.GetWidth():
+ if page_new_size.GetHeight() != page_old_size.GetHeight():
+ # Width and height both changed - redraw everything
+ return wx.Rect(0, 0, *page_new_size)
+ else:
+ # Only width changed - redraw right hand side
+ right_edge_width = 4
+ new_rect = wx.Rect(page_new_size.GetWidth() - right_edge_width, 0, right_edge_width, page_new_size.GetHeight())
+ old_rect = wx.Rect(page_old_size.GetWidth() - right_edge_width, 0, right_edge_width, page_old_size.GetHeight())
+
+ else:
+ if page_new_size.GetHeight() == page_old_size.GetHeight():
+ # Nothing changed (should never happen) - redraw nothing
+ return wx.Rect(0, 0, 0, 0)
+ else:
+ # Height changed - need to redraw everything (as the background
+ # gradient is done vertically).
+ return wx.Rect(0, 0, *page_new_size)
+
+ new_rect.Union(old_rect)
+ new_rect.Intersect(wx.Rect(0, 0, *page_new_size))
+ return new_rect
+
+
+ def GetButtonBarButtonSize(self, dc, wnd, kind, size, label, bitmap_size_large, bitmap_size_small,
+ button_size=None, normal_region=None, dropdown_region=None):
+ """
+ Calculate the size of a button within a :class:`~lib.agw.ribbon.buttonbar.RibbonButtonBar`.
+
+ :param `dc`: A device context to use when one is required for size calculations;
+ :param `wnd`: The window onto which the button will eventually be drawn
+ (which is normally a :class:`~lib.agw.ribbon.buttonbar.RibbonButtonBar`, though this is not guaranteed);
+ :param `kind`: The kind of button;
+ :param `size`: The size-class to calculate the size for. Buttons on a button
+ bar can have three distinct sizes: ``RIBBON_BUTTONBAR_BUTTON_SMALL``,
+ ``RIBBON_BUTTONBAR_BUTTON_MEDIUM``, and ``RIBBON_BUTTONBAR_BUTTON_LARGE``.
+ If the requested size-class is not applicable, then ``False`` should be returned;
+ :param `label`: The label of the button;
+ :param `bitmap_size_large`: The size of all "large" bitmaps on the button bar;
+ :param `bitmap_size_small`: The size of all "small" bitmaps on the button bar;
+ :param `button_size`: The size, in pixels, of the button;
+ :param `normal_region`: The region of the button which constitutes the normal button;
+ :param `dropdown_region`: The region of the button which constitutes the dropdown button.
+
+ :returns: ``True`` if a size exists for the button, ``False`` otherwise.
+ """
+
+ drop_button_width = 8
+
+ normal_region = wx.Rect()
+ dropdown_region = wx.Rect()
+
+ dc.SetFont(self._button_bar_label_font)
+ result = size & RIBBON_BUTTONBAR_BUTTON_SIZE_MASK
+
+ if result == RIBBON_BUTTONBAR_BUTTON_SMALL:
+ # Small bitmap, no label
+ button_size = bitmap_size_small + wx.Size(6, 4)
+
+ if kind in [RIBBON_BUTTON_NORMAL, RIBBON_BUTTON_TOGGLE]:
+ normal_region = wx.Rect(0, 0, *button_size)
+ dropdown_region = wx.Rect(0, 0, 0, 0)
+
+ elif kind == RIBBON_BUTTON_DROPDOWN:
+ button_size += wx.Size(drop_button_width, 0)
+ dropdown_region = wx.Rect(0, 0, *button_size)
+ normal_region = wx.Rect(0, 0, 0, 0)
+
+ elif kind == RIBBON_BUTTON_HYBRID:
+ normal_region = wx.Rect(0, 0, *button_size)
+ dropdown_region = wx.Rect(button_size.GetWidth(), 0, drop_button_width, button_size.GetHeight())
+ button_size += wx.Size(drop_button_width, 0)
+
+ elif result == RIBBON_BUTTONBAR_BUTTON_MEDIUM:
+ # Small bitmap, with label to the right
+ is_supported, button_size, normal_region, dropdown_region = self.GetButtonBarButtonSize(dc, wnd, kind,
+ RIBBON_BUTTONBAR_BUTTON_SMALL,
+ label, bitmap_size_large,
+ bitmap_size_small)
+ text_size = dc.GetTextExtent(label)[0]
+ button_size.SetWidth(button_size.GetWidth() + text_size)
+
+ if kind == RIBBON_BUTTON_DROPDOWN:
+ dropdown_region.SetWidth(dropdown_region.GetWidth() + text_size)
+
+ elif kind == RIBBON_BUTTON_HYBRID:
+ dropdown_region.SetX(dropdown_region.GetX() + text_size)
+ normal_region.SetWidth(normal_region.GetWidth() + text_size)
+ # no break
+ elif kind in [RIBBON_BUTTON_NORMAL, RIBBON_BUTTON_TOGGLE]:
+ normal_region.SetWidth(normal_region.GetWidth() + text_size)
+
+ elif result == RIBBON_BUTTONBAR_BUTTON_LARGE:
+ # Large bitmap, with label below (possibly split over 2 lines)
+
+ icon_size = wx.Size(*bitmap_size_large)
+ icon_size += wx.Size(4, 4)
+ best_width, label_height = dc.GetTextExtent(label)
+ last_line_extra_width = 0
+
+ if kind not in [RIBBON_BUTTON_NORMAL, RIBBON_BUTTON_TOGGLE]:
+ last_line_extra_width += 8
+
+ for i in xrange(0, len(label)):
+ if RibbonCanLabelBreakAtPosition(label, i):
+
+ width = max(dc.GetTextExtent(label[0:i])[0],
+ dc.GetTextExtent(label[i+1:])[0] + last_line_extra_width)
+ if width < best_width:
+ best_width = width
+
+ label_height *= 2 # Assume two lines even when only one is used
+ # (to give all buttons a consistent height)
+ icon_size.SetWidth(max(icon_size.GetWidth(), best_width) + 6)
+ icon_size.SetHeight(icon_size.GetHeight() + label_height)
+ button_size = wx.Size(*icon_size)
+
+ if kind == RIBBON_BUTTON_DROPDOWN:
+ dropdown_region = wx.Rect(0, 0, *icon_size)
+ elif kind == RIBBON_BUTTON_HYBRID:
+ normal_region = wx.Rect(0, 0, *icon_size)
+ normal_region.height -= 2 + label_height
+ dropdown_region.x = 0
+ dropdown_region.y = normal_region.height
+ dropdown_region.width = icon_size.GetWidth()
+ dropdown_region.height = icon_size.GetHeight() - normal_region.height
+ elif kind in [RIBBON_BUTTON_NORMAL, RIBBON_BUTTON_TOGGLE]:
+ normal_region = wx.Rect(0, 0, *icon_size)
+
+ return True, button_size, normal_region, dropdown_region
+
+
+ def GetMinimisedPanelMinimumSize(self, dc, wnd, desired_bitmap_size=None, expanded_panel_direction=None):
+ """
+ Calculate the size of a minimised ribbon panel.
+
+ :param `dc`: A device context to use when one is required for size calculations;
+ :param `wnd`: The ribbon panel in question. Attributes like the panel label can
+ be queried from this;
+ :param `desired_bitmap_size`: MISSING DESCRIPTION;
+ :param `expanded_panel_direction`: MISSING DESCRIPTION.
+
+ """
+
+ if desired_bitmap_size != None:
+ desired_bitmap_size = wx.Size(16, 16)
+
+ if expanded_panel_direction != None:
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ expanded_panel_direction = wx.EAST
+ else:
+ expanded_panel_direction = wx.SOUTH
+
+ base_size = wx.Size(42, 42)
+
+ dc.SetFont(self._panel_label_font)
+ label_size = wx.Size(*dc.GetTextExtent(wnd.GetLabel()))
+ label_size.IncBy(2, 2) # Allow for differences between this DC and a paint DC
+ label_size.IncBy(6, 0) # Padding
+ label_size.y *= 2 # Second line for dropdown button
+
+ if self._flags & RIBBON_BAR_FLOW_VERTICAL:
+ # Label alongside icon
+ return wx.Size(base_size.x + label_size.x, max(base_size.y, label_size.y)), \
+ desired_bitmap_size, expanded_panel_direction
+ else:
+ # Label beneath icon
+ return wx.Size(max(base_size.x, label_size.x), base_size.y + label_size.y), \
+ desired_bitmap_size, expanded_panel_direction
+
+
+ def GetToolSize(self, dc, wnd, bitmap_size, kind, is_first, is_last, dropdown_region=None):
+ """
+ Calculate the size of a tool within a :class:`~lib.agw.ribbon.toolbar.RibbonToolBar`.
+
+ :param `dc`: A device context to use when one is required for size calculations;
+ :param `wnd`: The window onto which the tool will eventually be drawn;
+ :param `bitmap_size`: The size of the tool's foreground bitmap;
+ :param `kind`: The kind of tool (normal, dropdown, or hybrid);
+ :param `is_first`: ``True`` if the tool is the first within its group. ``False``
+ otherwise;
+ :param `is_last`: ``True`` if the tool is the last within its group. ``False``
+ otherwise;
+ :param `dropdown_region`: For dropdown and hybrid tools, the region within the
+ returned size which counts as the dropdown part.
+ """
+
+ size = wx.Size(*bitmap_size)
+ size.IncBy(7, 6)
+
+ if is_last:
+ size.IncBy(1, 0)
+
+ if kind & RIBBON_BUTTON_DROPDOWN:
+ size.IncBy(8, 0)
+ if kind == RIBBON_BUTTON_DROPDOWN:
+ dropdown_region = wx.Rect(0, 0, *size)
+ else:
+ dropdown_region = wx.Rect(size.GetWidth() - 8, 0, 8, size.GetHeight())
+ else:
+ dropdown_region = wx.Rect(0, 0, 0, 0)
+
+ return size, dropdown_region
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_osx.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_osx.py
new file mode 100644
index 0000000..8a76e09
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/art_osx.py
@@ -0,0 +1,39 @@
+"""
+`art_osx` is responsible for drawing all the components of the ribbon
+interface using an AUI-compatible appearance on Mac, because as of now there is no
+customized version of the ribbon art provider to provide a more or less native look
+on the Mac platform.
+
+
+Description
+===========
+
+This allows a ribbon bar to have a pluggable look-and-feel, while retaining the same
+underlying behaviour. As a single art provider is used for all ribbon components, a
+ribbon bar usually has a consistent (though unique) appearance.
+
+By default, a :class:`~lib.agw.ribbon.bar.RibbonBar` uses an instance of a class called
+:class:`~lib.agw.ribbon.art_default.RibbonDefaultArtProvider`,
+which resolves to :class:`~lib.agw.ribbon.art_aui.RibbonAUIArtProvider`,
+:class:`~lib.agw.ribbon.art_msw.RibbonMSWArtProvider`, or
+:class:`~lib.agw.ribbon.art_osx.RibbonOSXArtProvider` - whichever is most appropriate
+to the current platform. These art providers are all
+slightly configurable with regard to colours and fonts, but for larger modifications,
+you can derive from one of these classes, or write a completely new art provider class.
+
+Call :meth:`RibbonBar.SetArtProvider() <lib.agw.ribbon.bar.RibbonBar.SetArtProvider>` to change the art provider being used.
+
+
+See Also
+========
+
+:class:`~lib.agw.ribbon.bar.RibbonBar`
+"""
+
+import wx
+from art_aui import RibbonAUIArtProvider
+
+class RibbonOSXArtProvider(RibbonAUIArtProvider):
+
+ pass
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/bar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/bar.py
new file mode 100644
index 0000000..419cfbf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/bar.py
@@ -0,0 +1,1253 @@
+# --------------------------------------------------------------------------- #
+# RIBBONBAR Library wxPython IMPLEMENTATION
+#
+# Original C++ Code From Peter Cawley.
+#
+# Current wxRibbon Version Tracked: wxWidgets 2.9.0 SVN HEAD
+#
+#
+# Python Code By:
+#
+# Andrea Gavana, @ 15 Oct 2009
+# Latest Revision: 17 Aug 2011, 15.00 GMT
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+Top-level control in a ribbon user interface.
+
+
+Description
+===========
+
+Serves as a tabbed container for :class:`~lib.agw.ribbon.page.RibbonPage` - a ribbon user interface typically
+has a ribbon bar, which contains one or more RibbonPages, which in turn each contains
+one or more RibbonPanels, which in turn contain controls. While a :class:`RibbonBar` has
+tabs similar to a :class:`Notebook`, it does not follow the same API for adding pages.
+Containers like :class:`Notebook` can contain any type of window as a page, hence the
+normal procedure is to create the sub-window and then call :meth:`BookCtrlBase.AddPage` ().
+
+As :class:`RibbonBar` can only have :class:`~lib.agw.ribbon.page.RibbonPage` as children
+(and a :class:`~lib.agw.ribbon.page.RibbonPage` can only have a :class:`RibbonBar` as parent),
+when a page is created, it is automatically added to the bar - there is no `AddPage` equivalent to call.
+
+After all pages have been created, and all controls and panels placed on those pages,
+meth:`~RibbonBar.Realize` must be called.
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+========================================== =========== ==========================================
+Window Styles Hex Value Description
+========================================== =========== ==========================================
+``RIBBON_BAR_DEFAULT_STYLE`` 0x9 Defined as ``RIBBON_BAR_FLOW_HORIZONTAL`` | ``RIBBON_BAR_SHOW_PAGE_LABELS`` | ``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS``
+``RIBBON_BAR_FOLDBAR_STYLE`` 0x1e Defined as ``RIBBON_BAR_FLOW_VERTICAL`` | ``RIBBON_BAR_SHOW_PAGE_ICONS`` | ``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS`` | ``RIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS``
+``RIBBON_BAR_SHOW_PAGE_LABELS`` 0x1 Causes labels to be shown on the tabs in the ribbon bar.
+``RIBBON_BAR_SHOW_PAGE_ICONS`` 0x2 Causes icons to be shown on the tabs in the ribbon bar.
+``RIBBON_BAR_FLOW_HORIZONTAL`` 0x0 Causes panels within pages to stack horizontally.
+``RIBBON_BAR_FLOW_VERTICAL`` 0x4 Causes panels within pages to stack vertically.
+``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS`` 0x8 Causes extension buttons to be shown on panels (where the panel has such a button).
+``RIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS`` 0x10 Causes minimise buttons to be shown on panels (where the panel has such a button).
+``RIBBON_BAR_ALWAYS_SHOW_TABS`` 0x20 Always shows the tabs area even when only one tab is added.
+========================================== =========== ==========================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================================= =================================
+Event Name Description
+================================= =================================
+``EVT_RIBBONBAR_PAGE_CHANGED`` Triggered after the transition from one page being active to a different page being active.
+``EVT_RIBBONBAR_PAGE_CHANGING`` Triggered prior to the transition from one page being active to a different page being active, and can veto the change.
+``EVT_RIBBONBAR_TAB_MIDDLE_DOWN`` Triggered when the middle mouse button is pressed on a tab.
+``EVT_RIBBONBAR_TAB_MIDDLE_UP`` Triggered when the middle mouse button is released on a tab.
+``EVT_RIBBONBAR_TAB_RIGHT_DOWN`` Triggered when the right mouse button is pressed on a tab.
+``EVT_RIBBONBAR_TAB_RIGHT_UP`` Triggered when the right mouse button is released on a tab.
+``EVT_RIBBONBAR_TAB_LEFT_DCLICK`` Triggered when the user double-clicks on a tab.
+================================= =================================
+
+
+See Also
+========
+
+:class:`~lib.agw.ribbon.page.RibbonPage`, :class:`~lib.agw.ribbon.panel.RibbonPanel`
+"""
+
+
+import wx
+import types
+
+from control import RibbonControl
+
+from art_internal import RibbonPageTabInfo
+from art_msw import RibbonMSWArtProvider
+from art import *
+
+wxEVT_COMMAND_RIBBONBAR_PAGE_CHANGED = wx.NewEventType()
+wxEVT_COMMAND_RIBBONBAR_PAGE_CHANGING = wx.NewEventType()
+wxEVT_COMMAND_RIBBONBAR_TAB_MIDDLE_DOWN = wx.NewEventType()
+wxEVT_COMMAND_RIBBONBAR_TAB_MIDDLE_UP = wx.NewEventType()
+wxEVT_COMMAND_RIBBONBAR_TAB_RIGHT_DOWN = wx.NewEventType()
+wxEVT_COMMAND_RIBBONBAR_TAB_RIGHT_UP = wx.NewEventType()
+wxEVT_COMMAND_RIBBONBAR_TAB_LEFT_DCLICK = wx.NewEventType()
+
+EVT_RIBBONBAR_PAGE_CHANGED = wx.PyEventBinder(wxEVT_COMMAND_RIBBONBAR_PAGE_CHANGED, 1)
+EVT_RIBBONBAR_PAGE_CHANGING = wx.PyEventBinder(wxEVT_COMMAND_RIBBONBAR_PAGE_CHANGING, 1)
+EVT_RIBBONBAR_TAB_MIDDLE_DOWN = wx.PyEventBinder(wxEVT_COMMAND_RIBBONBAR_TAB_MIDDLE_DOWN, 1)
+EVT_RIBBONBAR_TAB_MIDDLE_UP = wx.PyEventBinder(wxEVT_COMMAND_RIBBONBAR_TAB_MIDDLE_UP, 1)
+EVT_RIBBONBAR_TAB_RIGHT_DOWN = wx.PyEventBinder(wxEVT_COMMAND_RIBBONBAR_TAB_RIGHT_DOWN, 1)
+EVT_RIBBONBAR_TAB_RIGHT_UP = wx.PyEventBinder(wxEVT_COMMAND_RIBBONBAR_TAB_RIGHT_UP, 1)
+EVT_RIBBONBAR_TAB_LEFT_DCLICK = wx.PyEventBinder(wxEVT_COMMAND_RIBBONBAR_TAB_LEFT_DCLICK, 1)
+
+
+def SET_FLAG(variable, flag):
+
+ refresh_tabs = False
+ if variable & flag != flag:
+ variable |= flag
+ refresh_tabs = True
+
+ return variable, refresh_tabs
+
+
+def UNSET_FLAG(variable, flag):
+
+ refresh_tabs = False
+ if variable & flag:
+ variable &= ~flag
+ refresh_tabs = True
+
+ return variable, refresh_tabs
+
+
+class RibbonBarEvent(wx.NotifyEvent):
+ """
+ Event used to indicate various actions relating to a :class:`RibbonBar`.
+
+ .. seealso:: :class:`RibbonBar` for available event types.
+ """
+
+ def __init__(self, command_type=None, win_id=0, page=None):
+ """
+ Default class constructor.
+
+ :param integer `command_type`: the event type;
+ :param integer `win_id`: the event identifier;
+ :param `page`: an instance of :class:`~lib.agw.ribbon.page.RibbonPage`.
+ """
+
+ wx.NotifyEvent.__init__(self, command_type, win_id)
+ self._page = page
+
+ self._isAllowed = True
+
+
+ def GetPage(self):
+ """
+ Returns the page being changed to, or being clicked on.
+
+ :returns: An instance of :class:`~lib.agw.ribbon.page.RibbonPage`.
+ """
+
+ return self._page
+
+
+ def SetPage(self, page):
+ """
+ Sets the page relating to this event.
+
+ :param `page`: an instance of :class:`~lib.agw.ribbon.page.RibbonPage`.
+ """
+
+ self._page = page
+
+
+ def Allow(self):
+ """
+ This is the opposite of :meth:`~RibbonBarEvent.Veto`: it explicitly allows the event to be processed.
+ For most events it is not necessary to call this method as the events are
+ allowed anyhow but some are forbidden by default (this will be mentioned
+ in the corresponding event description).
+ """
+
+ self._isAllowed = True
+
+
+ def Veto(self):
+ """
+ Prevents the change announced by this event from happening.
+
+ :note: It is in general a good idea to notify the user about the reasons
+ for vetoing the change because otherwise the applications behaviour (which
+ just refuses to do what the user wants) might be quite surprising.
+ """
+
+ self._isAllowed = False
+
+
+ def IsAllowed(self):
+ """
+ Returns ``True`` if the change is allowed (:meth:`~RibbonBarEvent.Veto` hasn't been called) or
+ ``False`` otherwise (if it was).
+ """
+
+ return self._isAllowed
+
+
+class RibbonBar(RibbonControl):
+ """ Top-level control in a ribbon user interface. """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, agwStyle=RIBBON_BAR_DEFAULT_STYLE,
+ validator=wx.DefaultValidator, name="RibbonBar"):
+ """
+ Default constructor.
+
+ :param `parent`: pointer to a parent window, must not be ``None``;
+ :type `parent`: :class:`Window`
+ :param integer `id`: window identifier. If ``wx.ID_ANY``, will automatically create
+ an identifier;
+ :param `pos`: window position. ``wx.DefaultPosition`` indicates that wxPython
+ should generate a default position for the window;
+ :type `pos`: tuple or :class:`Point`
+ :param `size`: window size. ``wx.DefaultSize`` indicates that wxPython should
+ generate a default size for the window. If no suitable size can be found, the
+ window will be sized to 20x20 pixels so that the window is visible but obviously
+ not correctly sized;
+ :type `size`: tuple or :class:`Size`
+ :param `agwStyle`: the AGW-specific window style. This can be a combination of the
+ following bits:
+
+ ========================================== =========== ==========================================
+ Window Styles Hex Value Description
+ ========================================== =========== ==========================================
+ ``RIBBON_BAR_DEFAULT_STYLE`` 0x9 Defined as ``RIBBON_BAR_FLOW_HORIZONTAL`` | ``RIBBON_BAR_SHOW_PAGE_LABELS`` | ``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS``
+ ``RIBBON_BAR_FOLDBAR_STYLE`` 0x1e Defined as ``RIBBON_BAR_FLOW_VERTICAL`` | ``RIBBON_BAR_SHOW_PAGE_ICONS`` | ``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS`` | ``RIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS``
+ ``RIBBON_BAR_SHOW_PAGE_LABELS`` 0x1 Causes labels to be shown on the tabs in the ribbon bar.
+ ``RIBBON_BAR_SHOW_PAGE_ICONS`` 0x2 Causes icons to be shown on the tabs in the ribbon bar.
+ ``RIBBON_BAR_FLOW_HORIZONTAL`` 0x0 Causes panels within pages to stack horizontally.
+ ``RIBBON_BAR_FLOW_VERTICAL`` 0x4 Causes panels within pages to stack vertically.
+ ``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS`` 0x8 Causes extension buttons to be shown on panels (where the panel has such a button).
+ ``RIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS`` 0x10 Causes minimise buttons to be shown on panels (where the panel has such a button).
+ ``RIBBON_BAR_ALWAYS_SHOW_TABS`` 0x20 Always shows the tabs area even when only one tab is added.
+ ========================================== =========== ==========================================
+
+ :param `validator`: the window validator;
+ :type `validator`: :class:`Validator`
+ :param string `name`: the window name.
+
+ """
+
+ RibbonControl.__init__(self, parent, id, pos, size, style=wx.NO_BORDER)
+
+ self._flags = 0
+ self._tabs_total_width_ideal = 0
+ self._tabs_total_width_minimum = 0
+ self._tab_margin_left = 0
+ self._tab_margin_right = 0
+ self._tab_height = 0
+ self._tab_scroll_amount = 0
+ self._current_page = -1
+ self._current_hovered_page = -1
+ self._tab_scroll_left_button_state = RIBBON_SCROLL_BTN_NORMAL
+ self._tab_scroll_right_button_state = RIBBON_SCROLL_BTN_NORMAL
+ self._tab_scroll_buttons_shown = False
+ self._arePanelsShown = True
+ self._pages = []
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnMouseDoubleClick)
+ self.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp)
+ self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMouseMiddleDown)
+ self.Bind(wx.EVT_MIDDLE_UP, self.OnMouseMiddleUp)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown)
+ self.Bind(wx.EVT_RIGHT_UP, self.OnMouseRightUp)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ self.CommonInit(agwStyle)
+
+
+ def AddPage(self, page):
+ """
+ Adds a page to the :class:`RibbonBar`.
+
+ :param `page`: an instance of :class:`~lib.agw.ribbon.page.RibbonPage`.
+ """
+
+ info = RibbonPageTabInfo()
+
+ info.page = page
+ info.active = False
+ info.hovered = False
+ # info.rect not set (intentional)
+
+ dcTemp = wx.ClientDC(self)
+ label = ""
+ if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS:
+ label = page.GetLabel()
+
+ icon = wx.NullBitmap
+ if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS:
+ icon = page.GetIcon()
+
+ info.ideal_width, info.small_begin_need_separator_width, \
+ info.small_must_have_separator_width, info.minimum_width = self._art.GetBarTabWidth(dcTemp, self, label, icon, info.ideal_width,
+ info.small_begin_need_separator_width,
+ info.small_must_have_separator_width, info.minimum_width)
+
+ if not self._pages:
+ self._tabs_total_width_ideal = info.ideal_width
+ self._tabs_total_width_minimum = info.minimum_width
+ else:
+ sep = self._art.GetMetric(RIBBON_ART_TAB_SEPARATION_SIZE)
+ self._tabs_total_width_ideal += sep + info.ideal_width
+ self._tabs_total_width_minimum += sep + info.minimum_width
+
+ self._pages.append(info)
+
+ page.Hide() # Most likely case is that self new page is not the active tab
+ page.SetArtProvider(self._art)
+
+ if len(self._pages) == 1:
+ self.SetActivePage(0)
+
+
+ def DismissExpandedPanel(self):
+ """
+ Dismiss the expanded panel of the currently active page.
+
+ Calls and returns the value from :meth:`RibbonPage.DismissExpandedPanel() <RibbonPage.DismissExpandedPanel>` for the
+ currently active page, or ``False`` if there is no active page.
+ """
+
+ if self._current_page == -1:
+ return False
+
+ return self._pages[self._current_page].page.DismissExpandedPanel()
+
+
+ def ShowPanels(self, show=True):
+ """
+ Shows or hides the panels inside :class:`RibbonBar`.
+
+ :param bool `show`: ``True`` to show the panels, ``False`` to hide them.
+ """
+
+ self._arePanelsShown = show
+ self.SetMinSize(wx.Size(self.GetSize().GetWidth(), self.DoGetBestSize().GetHeight()))
+ self.Realise()
+ self.GetParent().Layout()
+
+
+ def SetAGWWindowStyleFlag(self, agwStyle):
+ """
+ Sets the window style for :class:`RibbonBar`.
+
+ :param integer `agwStyle`: can be a combination of the following bits:
+
+ ========================================== =========== ==========================================
+ Window Styles Hex Value Description
+ ========================================== =========== ==========================================
+ ``RIBBON_BAR_DEFAULT_STYLE`` 0x9 Defined as ``RIBBON_BAR_FLOW_HORIZONTAL`` | ``RIBBON_BAR_SHOW_PAGE_LABELS`` | ``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS``
+ ``RIBBON_BAR_FOLDBAR_STYLE`` 0x1e Defined as ``RIBBON_BAR_FLOW_VERTICAL`` | ``RIBBON_BAR_SHOW_PAGE_ICONS`` | ``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS`` | ``RIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS``
+ ``RIBBON_BAR_SHOW_PAGE_LABELS`` 0x1 Causes labels to be shown on the tabs in the ribbon bar.
+ ``RIBBON_BAR_SHOW_PAGE_ICONS`` 0x2 Causes icons to be shown on the tabs in the ribbon bar.
+ ``RIBBON_BAR_FLOW_HORIZONTAL`` 0x0 Causes panels within pages to stack horizontally.
+ ``RIBBON_BAR_FLOW_VERTICAL`` 0x4 Causes panels within pages to stack vertically.
+ ``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS`` 0x8 Causes extension buttons to be shown on panels (where the panel has such a button).
+ ``RIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS`` 0x10 Causes minimise buttons to be shown on panels (where the panel has such a button).
+ ``RIBBON_BAR_ALWAYS_SHOW_TABS`` 0x20 Always shows the tabs area even when only one tab is added.
+ ========================================== =========== ==========================================
+
+ :note: Please note that some styles cannot be changed after the window creation
+ and that `Refresh()` might need to be be called after changing the others for
+ the change to take place immediately.
+ """
+
+ self._flags = agwStyle
+
+ if self._art:
+ self._art.SetFlags(agwStyle)
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`RibbonBar` window style flag.
+
+ :see: :meth:`~RibbonBar.SetAGWWindowStyleFlag` for a list of valid window styles.
+ """
+
+ return self._flags
+
+
+ def Realize(self):
+ """
+ Perform initial layout and size calculations of the bar and its children.
+
+ This must be called after all of the bar's children have been created (and their
+ children created, etc.) - if it is not, then windows may not be laid out or
+ sized correctly. Also calls :meth:`RibbonPage.Realize() <lib.agw.ribbon.page.RibbonPage.Realize>`
+ on each child page.
+
+ :note: Reimplemented from :class:`~lib.agw.ribbon.control.RibbonControl`.
+ """
+
+ status = True
+
+ dcTemp = wx.ClientDC(self)
+ sep = self._art.GetMetric(RIBBON_ART_TAB_SEPARATION_SIZE)
+ numtabs = len(self._pages)
+
+ for i, info in enumerate(self._pages):
+
+ self.RepositionPage(info.page)
+ if not info.page.Realize():
+ status = False
+
+ label = ""
+ if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS:
+ label = info.page.GetLabel()
+
+ icon = wx.NullBitmap
+ if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS:
+ icon = info.page.GetIcon()
+
+ info.ideal_width, info.small_begin_need_separator_width, \
+ info.small_must_have_separator_width, \
+ info.minimum_width = self._art.GetBarTabWidth(dcTemp, self, label, icon, info.ideal_width,
+ info.small_begin_need_separator_width, info.small_must_have_separator_width,
+ info.minimum_width)
+
+ if i == 0:
+ self._tabs_total_width_ideal = info.ideal_width
+ self._tabs_total_width_minimum = info.minimum_width
+ else:
+ self._tabs_total_width_ideal += sep + info.ideal_width
+ self._tabs_total_width_minimum += sep + info.minimum_width
+
+ self._tab_height = self._art.GetTabCtrlHeight(dcTemp, self, self._pages)
+
+ self.RecalculateMinSize()
+ self.RecalculateTabSizes()
+ self.Refresh()
+
+ return status
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ x, y = event.GetX(), event.GetY()
+ hovered_page = -1
+ refresh_tabs = False
+
+ if y < self._tab_height:
+ # It is quite likely that the mouse moved a small amount and is still over the same tab
+ if self._current_hovered_page != -1 and self._pages[self._current_hovered_page].rect.Contains((x, y)):
+ hovered_page = self._current_hovered_page
+ # But be careful, if tabs can be scrolled, then parts of the tab rect may not be valid
+ if self._tab_scroll_buttons_shown:
+ if x >= self._tab_scroll_right_button_rect.GetX() or x < self._tab_scroll_left_button_rect.GetRight():
+ hovered_page = -1
+
+ else:
+
+ hovered_page, dummy = self.HitTestTabs(event.GetPosition())
+
+ if hovered_page != self._current_hovered_page:
+ if self._current_hovered_page != -1:
+ self._pages[self._current_hovered_page].hovered = False
+
+ self._current_hovered_page = hovered_page
+ if self._current_hovered_page != -1:
+ self._pages[self._current_hovered_page].hovered = True
+
+ refresh_tabs = True
+
+ if self._tab_scroll_buttons_shown:
+ if self._tab_scroll_left_button_rect.Contains((x, y)):
+ self._tab_scroll_left_button_state, refresh_tabs = SET_FLAG(self._tab_scroll_left_button_state, RIBBON_SCROLL_BTN_HOVERED)
+ else:
+ self._tab_scroll_left_button_state, refresh_tabs = UNSET_FLAG(self._tab_scroll_left_button_state, RIBBON_SCROLL_BTN_HOVERED)
+
+ if self._tab_scroll_right_button_rect.Contains((x, y)):
+ self._tab_scroll_right_button_state, refresh_tabs = SET_FLAG(self._tab_scroll_right_button_state, RIBBON_SCROLL_BTN_HOVERED)
+ else:
+ self._tab_scroll_right_button_state, refresh_tabs = UNSET_FLAG(self._tab_scroll_right_button_state, RIBBON_SCROLL_BTN_HOVERED)
+
+ if refresh_tabs:
+ self.RefreshTabBar()
+
+
+ def OnMouseLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # The ribbon bar is (usually) at the top of a window, and at least on MSW, the mouse
+ # can leave the window quickly and leave a tab in the hovered state.
+ refresh_tabs = False
+
+ if self._current_hovered_page != -1:
+ self._pages[self._current_hovered_page].hovered = False
+ self._current_hovered_page = -1
+ refresh_tabs = True
+
+ if self._tab_scroll_left_button_state & RIBBON_SCROLL_BTN_HOVERED:
+ self._tab_scroll_left_button_state &= ~RIBBON_SCROLL_BTN_HOVERED
+ refresh_tabs = True
+
+ if self._tab_scroll_right_button_state & RIBBON_SCROLL_BTN_HOVERED:
+ self._tab_scroll_right_button_state &= ~RIBBON_SCROLL_BTN_HOVERED
+ refresh_tabs = True
+
+ if refresh_tabs:
+ self.RefreshTabBar()
+
+
+ def GetPage(self, n):
+ """
+ Get a page by index.
+
+ ``None`` will be returned if the given index is out of range.
+
+ :param integer `n`: the zero-based index indicating the page position.
+
+ """
+
+ if n < 0 or n >= len(self._pages):
+ return 0
+
+ return self._pages[n].page
+
+
+ def SetActivePageByIndex(self, page):
+ """
+ Set the active page by index, without triggering any events.
+
+ :param integer `page`: The zero-based index of the page to activate.
+
+ :returns: ``True`` if the specified page is now active, ``False`` if it could
+ not be activated (for example because the page index is invalid).
+ """
+
+ if self._current_page == page:
+ return True
+
+ if page >= len(self._pages):
+ return False
+
+ if self._current_page != -1:
+ self._pages[self._current_page].active = False
+ self._pages[self._current_page].page.Hide()
+
+ self._current_page = page
+ self._pages[page].active = True
+
+ wnd = self._pages[page].page
+ self.RepositionPage(wnd)
+ wnd.Layout()
+ wnd.Show()
+
+ self.Refresh()
+
+ return True
+
+
+ def SetActivePageByPage(self, page):
+ """
+ Set the active page, without triggering any events.
+
+ :param `page`: the page to activate, an instance of :class:`~lib.agw.ribbon.page.RibbonPage`.
+
+ :returns: ``True`` if the specified page is now active, ``False`` if it could
+ not be activated (for example because the given page is not a child of the
+ ribbon bar).
+ """
+
+ for i in xrange(len(self._pages)):
+ if self._pages[i].page == page:
+ return self.SetActivePageByIndex(i)
+
+ return False
+
+
+ def SetActivePage(self, page):
+ """ See comments on :meth:`~RibbonBar.SetActivePageByIndex` and :meth:`~RibbonBar.SetActivePageByPage`. """
+
+ if isinstance(page, types.IntType):
+ return self.SetActivePageByIndex(page)
+
+ return self.SetActivePageByPage(page)
+
+
+ def GetActivePage(self):
+ """
+ Get the index of the active page.
+
+ In the rare case of no page being active, -1 is returned.
+ """
+
+ return self._current_page
+
+
+ def SetTabCtrlMargins(self, left, right):
+ """
+ Set the margin widths (in pixels) on the left and right sides of the tab bar
+ region of the ribbon bar.
+
+ These margins will be painted with the tab background, but tabs and scroll
+ buttons will never be painted in the margins. The left margin could be used for
+ rendering something equivalent to the "Office Button", though this is not
+ currently implemented. The right margin could be used for rendering a help
+ button, and/or MDI buttons, but again, this is not currently implemented.
+
+ :param integer `left`: the left margin (in pixels);
+ :param integer `right`: the right margin (in pixels).
+ """
+
+ self._tab_margin_left = left
+ self._tab_margin_right = right
+
+ self.RecalculateTabSizes()
+
+
+ def OrderPageTabInfoBySmallWidthAsc(self, first, second):
+
+ return first.small_must_have_separator_width - second.small_must_have_separator_width
+
+
+ def RecalculateTabSizes(self):
+ """ Recalculates the :class:`RibbonBar` tab sizes. """
+
+ numtabs = len(self._pages)
+
+ if numtabs == 0:
+ return
+
+ width = self.GetSize().GetWidth() - self._tab_margin_left - self._tab_margin_right
+ tabsep = self._art.GetMetric(RIBBON_ART_TAB_SEPARATION_SIZE)
+ x = self._tab_margin_left
+ y = 0
+
+ if width >= self._tabs_total_width_ideal:
+ # Simple case: everything at ideal width
+ for info in self._pages:
+ info.rect.x = x
+ info.rect.y = y
+ info.rect.width = info.ideal_width
+ info.rect.height = self._tab_height
+ x += info.rect.width + tabsep
+
+ self._tab_scroll_buttons_shown = False
+ self._tab_scroll_left_button_rect.SetWidth(0)
+ self._tab_scroll_right_button_rect.SetWidth(0)
+
+ elif width < self._tabs_total_width_minimum:
+ # Simple case: everything minimum with scrollbar
+ for info in self._pages:
+ info.rect.x = x
+ info.rect.y = y
+ info.rect.width = info.minimum_width
+ info.rect.height = self._tab_height
+ x += info.rect.width + tabsep
+
+ if not self._tab_scroll_buttons_shown:
+ self._tab_scroll_left_button_state = RIBBON_SCROLL_BTN_NORMAL
+ self._tab_scroll_right_button_state = RIBBON_SCROLL_BTN_NORMAL
+ self._tab_scroll_buttons_shown = True
+
+ temp_dc = wx.ClientDC(self)
+ self._tab_scroll_left_button_rect.SetWidth(self._art.GetScrollButtonMinimumSize(temp_dc, self,
+ RIBBON_SCROLL_BTN_LEFT | RIBBON_SCROLL_BTN_NORMAL |
+ RIBBON_SCROLL_BTN_FOR_TABS).GetWidth())
+ self._tab_scroll_left_button_rect.SetHeight(self._tab_height)
+ self._tab_scroll_left_button_rect.SetX(self._tab_margin_left)
+ self._tab_scroll_left_button_rect.SetY(0)
+ self._tab_scroll_right_button_rect.SetWidth(self._art.GetScrollButtonMinimumSize(temp_dc, self,
+ RIBBON_SCROLL_BTN_RIGHT | RIBBON_SCROLL_BTN_NORMAL |
+ RIBBON_SCROLL_BTN_FOR_TABS).GetWidth())
+ self._tab_scroll_right_button_rect.SetHeight(self._tab_height)
+ self._tab_scroll_right_button_rect.SetX(self.GetClientSize().GetWidth() - self._tab_margin_right - self._tab_scroll_right_button_rect.GetWidth())
+ self._tab_scroll_right_button_rect.SetY(0)
+
+ if self._tab_scroll_amount == 0:
+ self._tab_scroll_left_button_rect.SetWidth(0)
+
+ elif self._tab_scroll_amount + width >= self._tabs_total_width_minimum:
+ self._tab_scroll_amount = self._tabs_total_width_minimum - width
+ self._tab_scroll_right_button_rect.SetX(self._tab_scroll_right_button_rect.GetX() + self._tab_scroll_right_button_rect.GetWidth())
+ self._tab_scroll_right_button_rect.SetWidth(0)
+
+ for info in self._pages:
+ info.rect.x -= self._tab_scroll_amount
+
+ else:
+ self._tab_scroll_buttons_shown = False
+ self._tab_scroll_left_button_rect.SetWidth(0)
+ self._tab_scroll_right_button_rect.SetWidth(0)
+ # Complex case: everything sized such that: minimum <= width < ideal
+ #
+ # Strategy:
+ # 1) Uniformly reduce all tab widths from ideal to small_must_have_separator_width
+ # 2) Reduce the largest tab by 1 pixel, repeating until all tabs are same width (or at minimum)
+ # 3) Uniformly reduce all tabs down to their minimum width
+ #
+ smallest_tab_width = 10000
+ total_small_width = tabsep * (numtabs - 1)
+
+ for info in self._pages:
+ if info.small_must_have_separator_width < smallest_tab_width:
+ smallest_tab_width = info.small_must_have_separator_width
+
+ total_small_width += info.small_must_have_separator_width
+
+ if width >= total_small_width:
+ # Do (1)
+ total_delta = self._tabs_total_width_ideal - total_small_width
+ total_small_width -= tabsep*(numtabs - 1)
+ width -= tabsep*(numtabs - 1)
+ for info in self._pages:
+ delta = info.ideal_width - info.small_must_have_separator_width
+ info.rect.x = x
+ info.rect.y = y
+ info.rect.width = info.small_must_have_separator_width + delta*(width - total_small_width)/total_delta
+ info.rect.height = self._tab_height
+
+ x += info.rect.width + tabsep
+ total_delta -= delta
+ total_small_width -= info.small_must_have_separator_width
+ width -= info.rect.width
+
+ else:
+
+ total_small_width = tabsep*(numtabs - 1)
+ for info in self._pages:
+ if info.minimum_width < smallest_tab_width:
+ total_small_width += smallest_tab_width
+ else:
+ total_small_width += info.minimum_width
+
+ if width >= total_small_width:
+ # Do (2)
+ sorted_pages = []
+ for info in self._pages:
+ # Sneaky obj array trickery to not copy the tab descriptors
+ sorted_pages.append(info)
+
+ sorted_pages.sort(self.OrderPageTabInfoBySmallWidthAsc)
+ width -= tabsep*(numtabs - 1)
+
+ for i, info in enumerate(self._pages):
+ if info.small_must_have_separator_width*(numtabs - i) <= width:
+ info.rect.width = info.small_must_have_separator_width
+ else:
+ info.rect.width = width/(numtabs - i)
+
+ width -= info.rect.width
+
+ for i, info in enumerate(self._pages):
+ info.rect.x = x
+ info.rect.y = y
+ info.rect.height = self._tab_height
+ x += info.rect.width + tabsep
+ sorted_pages.pop(numtabs - (i + 1))
+
+ else:
+
+ # Do (3)
+ total_small_width = (smallest_tab_width + tabsep)*numtabs - tabsep
+ total_delta = total_small_width - self._tabs_total_width_minimum
+ total_small_width = self._tabs_total_width_minimum - tabsep*(numtabs - 1)
+ width -= tabsep*(numtabs - 1)
+
+ for info in self._pages:
+ delta = smallest_tab_width - info.minimum_width
+ info.rect.x = x
+ info.rect.y = y
+ info.rect.width = info.minimum_width + delta*(width - total_small_width)/total_delta
+ info.rect.height = self._tab_height
+
+ x += info.rect.width + tabsep
+ total_delta -= delta
+ total_small_width -= info.minimum_width
+ width -= info.rect.width
+
+
+ def CommonInit(self, agwStyle):
+ """
+ Common initialization procedures.
+
+ :param integer `agwStyle`: the AGW-specific window style.
+
+ :see: :meth:`~RibbonBar.SetAGWWindowStyleFlag` for a list of valid window styles.
+ """
+
+ self.SetName("RibbonBar")
+
+ self._flags = agwStyle
+ self._tabs_total_width_ideal = 0
+ self._tabs_total_width_minimum = 0
+ self._tab_margin_left = 50
+ self._tab_margin_right = 20
+ self._tab_height = 20 # initial guess
+ self._tab_scroll_amount = 0
+ self._current_page = -1
+ self._current_hovered_page = -1
+ self._tab_scroll_left_button_state = RIBBON_SCROLL_BTN_NORMAL
+ self._tab_scroll_right_button_state = RIBBON_SCROLL_BTN_NORMAL
+ self._tab_scroll_buttons_shown = False
+ self._arePanelsShown = True
+ self._tab_scroll_left_button_rect = wx.Rect()
+ self._tab_scroll_right_button_rect = wx.Rect()
+
+ if not self._art:
+ self.SetArtProvider(RibbonMSWArtProvider())
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+
+ def SetArtProvider(self, art):
+ """
+ Set the art provider to be used be the ribbon bar.
+
+ Also sets the art provider on all current :class:`~lib.agw.ribbon.page.RibbonPage` children, and any
+ :class:`~lib.agw.ribbon.page.RibbonPage` children added in the future.
+
+ Note that unlike most other ribbon controls, the ribbon bar creates a default
+ art provider when initialised, so an explicit call to :meth:`~RibbonBar.SetArtProvider` is
+ not required if the default art provider is sufficient. Also unlike other
+ ribbon controls, the ribbon bar takes ownership of the given pointer, and
+ will delete it when the art provider is changed or the bar is destroyed.
+
+ If this behaviour is not desired, then clone the art provider before setting
+ it.
+
+ :param `art`: an art provider.
+
+ :note: Reimplemented from :class:`~lib.agw.ribbon.control.RibbonControl`.
+ """
+
+ self._art = art
+
+ if art:
+ art.SetFlags(self._flags)
+
+ for info in self._pages:
+ if info.page.GetArtProvider() != art:
+ info.page.SetArtProvider(art)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+
+ if not self.GetUpdateRegion().ContainsRect(wx.Rect(0, 0, self.GetClientSize().GetWidth(), self._tab_height)):
+ # Nothing to do in the tab area, and the page area is handled by the active page
+ return
+
+ self.DoEraseBackground(dc)
+
+ numtabs = len(self._pages)
+ sep_visibility = 0.0
+ draw_sep = False
+ tabs_rect = wx.Rect(self._tab_margin_left, 0, self.GetClientSize().GetWidth() - self._tab_margin_left - self._tab_margin_right, self._tab_height)
+
+ if self._tab_scroll_buttons_shown:
+ tabs_rect.x += self._tab_scroll_left_button_rect.GetWidth()
+ tabs_rect.width -= self._tab_scroll_left_button_rect.GetWidth() + self._tab_scroll_right_button_rect.GetWidth()
+
+ for info in self._pages:
+ dc.DestroyClippingRegion()
+ if self._tab_scroll_buttons_shown:
+ if not tabs_rect.Intersects(info.rect):
+ continue
+ dc.SetClippingRect(tabs_rect)
+
+ dc.SetClippingRect(info.rect)
+ self._art.DrawTab(dc, self, info)
+
+ if info.rect.width < info.small_begin_need_separator_width:
+ draw_sep = True
+ if info.rect.width < info.small_must_have_separator_width:
+ sep_visibility += 1.0
+ else:
+ sep_visibility += float(info.small_begin_need_separator_width - info.rect.width)/ \
+ float(info.small_begin_need_separator_width - info.small_must_have_separator_width)
+
+ if draw_sep:
+
+ rect = wx.Rect(*self._pages[0].rect)
+ rect.width = self._art.GetMetric(RIBBON_ART_TAB_SEPARATION_SIZE)
+ sep_visibility /= float(numtabs)
+
+ for i in xrange(0, numtabs-1):
+ info = self._pages[i]
+ rect.x = info.rect.x + info.rect.width
+
+ if self._tab_scroll_buttons_shown and not tabs_rect.Intersects(rect):
+ continue
+
+ dc.DestroyClippingRegion()
+ dc.SetClippingRect(rect)
+ self._art.DrawTabSeparator(dc, self, rect, sep_visibility)
+
+ if self._tab_scroll_buttons_shown:
+ dc.DestroyClippingRegion()
+ if self._tab_scroll_left_button_rect.GetWidth() != 0:
+ self._art.DrawScrollButton(dc, self, self._tab_scroll_left_button_rect, RIBBON_SCROLL_BTN_LEFT |
+ self._tab_scroll_left_button_state | RIBBON_SCROLL_BTN_FOR_TABS)
+
+ if self._tab_scroll_right_button_rect.GetWidth() != 0:
+ self._art.DrawScrollButton(dc, self, self._tab_scroll_right_button_rect, RIBBON_SCROLL_BTN_RIGHT |
+ self._tab_scroll_right_button_state | RIBBON_SCROLL_BTN_FOR_TABS)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+ """
+
+ # Background painting done in main paint handler to reduce screen flicker
+ pass
+
+
+ def DoEraseBackground(self, dc):
+ """
+ Does the initial painting of stuff from the :meth:`~RibbonBar.OnPaint` event.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ tabs = wx.Rect(0, 0, *self.GetSize())
+ tabs.height = self._tab_height
+ self._art.DrawTabCtrlBackground(dc, self, tabs)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.RecalculateTabSizes()
+ if self._current_page != -1:
+ self.RepositionPage(self._pages[self._current_page].page)
+
+ self.RefreshTabBar()
+ event.Skip()
+
+
+ def RepositionPage(self, page):
+
+ w, h = self.GetSize()
+ page.SetSizeWithScrollButtonAdjustment(0, self._tab_height, w, h - self._tab_height)
+
+
+ def HitTestTabs(self, position):
+ """
+ Hit test method for :class:`RibbonBar`, testing where the given (in client coordinates)
+ point lies.
+
+ :param `position`: an instance of :class:`Point` in client coordinates.
+
+ :return: a tuple containing the tab index and the :class:`~lib.agw.ribbon.page.RibbonPage` if the :meth:`~RibbonBar.HitTestTabs`
+ successfully found such combination, or a tuple `(-1, None)` if no tab has been hit.
+ """
+
+ tabs_rect = wx.Rect(self._tab_margin_left, 0, self.GetClientSize().GetWidth() - self._tab_margin_left - self._tab_margin_right, self._tab_height)
+
+ if self._tab_scroll_buttons_shown:
+ tabs_rect.SetX(tabs_rect.GetX() + self._tab_scroll_left_button_rect.GetWidth())
+ tabs_rect.SetWidth(tabs_rect.GetWidth() - self._tab_scroll_left_button_rect.GetWidth() - self._tab_scroll_right_button_rect.GetWidth())
+
+ if tabs_rect.Contains(position):
+ for i, info in enumerate(self._pages):
+ if info.rect.Contains(position):
+ return i, info
+
+ return -1, None
+
+
+ def OnMouseLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ index, tab = self.HitTestTabs(event.GetPosition())
+ if tab and tab != self._pages[self._current_page]:
+ query = RibbonBarEvent(wxEVT_COMMAND_RIBBONBAR_PAGE_CHANGING, self.GetId(), tab.page)
+ query.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(query)
+
+ if query.IsAllowed():
+ self.SetActivePage(query.GetPage())
+ notification = RibbonBarEvent(wxEVT_COMMAND_RIBBONBAR_PAGE_CHANGED, self.GetId(), self._pages[self._current_page].page)
+ notification.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(notification)
+
+ elif tab == None:
+ if self._tab_scroll_left_button_rect.Contains(event.GetPosition()):
+ self._tab_scroll_left_button_state |= RIBBON_SCROLL_BTN_ACTIVE | RIBBON_SCROLL_BTN_HOVERED
+ self.RefreshTabBar()
+
+ elif self._tab_scroll_right_button_rect.Contains(event.GetPosition()):
+ self._tab_scroll_right_button_state |= RIBBON_SCROLL_BTN_ACTIVE | RIBBON_SCROLL_BTN_HOVERED
+ self.RefreshTabBar()
+
+
+ def OnMouseDoubleClick(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DCLICK`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.DoMouseButtonCommon(event, wxEVT_COMMAND_RIBBONBAR_TAB_LEFT_DCLICK)
+
+
+ def OnMouseLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self._tab_scroll_buttons_shown:
+ return
+
+ amount = 0
+
+ if self._tab_scroll_left_button_state & RIBBON_SCROLL_BTN_ACTIVE:
+ amount = -1
+
+ elif self._tab_scroll_right_button_state & RIBBON_SCROLL_BTN_ACTIVE:
+ amount = 1
+
+ if amount != 0:
+ self._tab_scroll_left_button_state &= ~RIBBON_SCROLL_BTN_ACTIVE
+ self._tab_scroll_right_button_state &= ~RIBBON_SCROLL_BTN_ACTIVE
+ self.ScrollTabBar(amount*8)
+
+
+ def ScrollTabBar(self, amount):
+ """
+ Scrolls the tab area left/right/up/down by the specified `amount`.
+
+ :param integer `amount`: the amount by which the tab area is scrolled, in pixels.
+ """
+
+ show_left = True
+ show_right = True
+
+ if self._tab_scroll_amount + amount <= 0:
+ amount = -self._tab_scroll_amount
+ show_left = False
+
+ elif self._tab_scroll_amount + amount + (self.GetClientSize().GetWidth() - \
+ self._tab_margin_left - self._tab_margin_right) >= \
+ self._tabs_total_width_minimum:
+ amount = self._tabs_total_width_minimum - self._tab_scroll_amount - \
+ (self.GetClientSize().GetWidth() - self._tab_margin_left - self._tab_margin_right)
+ show_right = False
+
+ if amount == 0:
+ return
+
+ self._tab_scroll_amount += amount
+ for info in self._pages:
+ info.rect.SetX(info.rect.GetX() - amount)
+
+ if show_right != (self._tab_scroll_right_button_rect.GetWidth() != 0) or \
+ show_left != (self._tab_scroll_left_button_rect.GetWidth() != 0):
+
+ temp_dc = wx.ClientDC(self)
+
+ if show_left:
+ self._tab_scroll_left_button_rect.SetWidth(self._art.GetScrollButtonMinimumSize(temp_dc, self, RIBBON_SCROLL_BTN_LEFT |
+ RIBBON_SCROLL_BTN_NORMAL |
+ RIBBON_SCROLL_BTN_FOR_TABS).GetWidth())
+ else:
+ self._tab_scroll_left_button_rect.SetWidth(0)
+
+ if show_right:
+ if self._tab_scroll_right_button_rect.GetWidth() == 0:
+ self._tab_scroll_right_button_rect.SetWidth(self._art.GetScrollButtonMinimumSize(temp_dc, self,
+ RIBBON_SCROLL_BTN_RIGHT |
+ RIBBON_SCROLL_BTN_NORMAL |
+ RIBBON_SCROLL_BTN_FOR_TABS).GetWidth())
+ self._tab_scroll_right_button_rect.SetX(self._tab_scroll_right_button_rect.GetX() - self._tab_scroll_right_button_rect.GetWidth())
+ else:
+
+ if self._tab_scroll_right_button_rect.GetWidth() != 0:
+ self._tab_scroll_right_button_rect.SetX(self._tab_scroll_right_button_rect.GetX() + self._tab_scroll_right_button_rect.GetWidth())
+ self._tab_scroll_right_button_rect.SetWidth(0)
+
+ self.RefreshTabBar()
+
+
+ def RefreshTabBar(self):
+ """ Repaints the tab area in :class:`RibbonBar`. """
+
+ tab_rect = wx.Rect(0, 0, self.GetClientSize().GetWidth(), self._tab_height)
+ self.Refresh(False, tab_rect)
+
+
+ def OnMouseMiddleDown(self, event):
+ """
+ Handles the ``wx.EVT_MIDDLE_DOWN`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.DoMouseButtonCommon(event, wxEVT_COMMAND_RIBBONBAR_TAB_MIDDLE_DOWN)
+
+
+ def OnMouseMiddleUp(self, event):
+ """
+ Handles the ``wx.EVT_MIDDLE_UP`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.DoMouseButtonCommon(event, wxEVT_COMMAND_RIBBONBAR_TAB_MIDDLE_UP)
+
+
+ def OnMouseRightDown(self, event):
+ """
+ Handles the ``wx.EVT_RIGHT_DOWN`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.DoMouseButtonCommon(event, wxEVT_COMMAND_RIBBONBAR_TAB_RIGHT_DOWN)
+
+
+ def OnMouseRightUp(self, event):
+ """
+ Handles the ``wx.EVT_RIGHT_UP`` event for :class:`RibbonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.DoMouseButtonCommon(event, wxEVT_COMMAND_RIBBONBAR_TAB_RIGHT_UP)
+
+
+ def DoMouseButtonCommon(self, event, tab_event_type):
+ """
+ Common methods for all the mouse move/click events.
+
+ :param `event`: a :class:`MouseEvent` event to be processed;
+ :param integer `tab_event_type`: one of the :class:`RibbonBar` events.
+ """
+
+ index, tab = self.HitTestTabs(event.GetPosition())
+
+ if tab:
+ notification = RibbonBarEvent(tab_event_type, self.GetId(), tab.page)
+ notification.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(notification)
+
+
+ def RecalculateMinSize(self):
+ """ Recalculates the :class:`RibbonBar` minimum size. """
+
+ min_size = wx.Size(-1, -1)
+ numtabs = len(self._pages)
+
+ if numtabs != 0:
+ min_size = wx.Size(*self._pages[0].page.GetMinSize())
+
+ for info in self._pages:
+ page_min = info.page.GetMinSize()
+ min_size.x = max(min_size.x, page_min.x)
+ min_size.y = max(min_size.y, page_min.y)
+
+ if min_size.y != -1:
+ # TODO: Decide on best course of action when min height is unspecified
+ # - should we specify it to the tab minimum, or leave it unspecified?
+ min_size.IncBy(0, self._tab_height)
+
+ self._minWidth = min_size.GetWidth()
+ self._minHeight = (self._arePanelsShown and [min_size.GetHeight()] or [self._tab_height])[0]
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :return: An instance of :class:`Size`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ best = wx.Size(0, 0)
+
+ if self._current_page != -1:
+ best = wx.Size(*self._pages[self._current_page].page.GetBestSize())
+
+ if best.GetHeight() == -1:
+ best.SetHeight(self._tab_height)
+ else:
+ best.IncBy(0, self._tab_height)
+
+ if not self._arePanelsShown:
+ best.SetHeight(self._tab_height)
+
+ return best
+
+
+ def HasMultiplePages(self):
+ """
+ This method should be overridden to return true if this window has multiple pages.
+
+ All standard class with multiple pages such as :class:`Notebook`, :class:`Listbook` and :class:`Treebook`
+ already override it to return true and user-defined classes with similar behaviour should also
+ do so, to allow the library to handle such windows appropriately.
+ """
+
+ return True
+
+
+ def GetDefaultBorder(self):
+ """ Returns the default border style for :class:`RibbonBar`. """
+
+ return wx.BORDER_NONE
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/buttonbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/buttonbar.py
new file mode 100644
index 0000000..e64f125
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/buttonbar.py
@@ -0,0 +1,1314 @@
+"""
+A ribbon button bar is similar to a traditional toolbar.
+
+
+Description
+===========
+
+It contains one or more buttons (button bar buttons, not :class:`Button`), each of which
+has a label and an icon. It differs from a :class:`toolbar` in several ways:
+
+- Individual buttons can grow and contract.
+- Buttons have labels as well as bitmaps.
+- Bitmaps are typically larger (at least 32x32 pixels) on a button bar compared to
+ a tool bar (which typically has 16x15).
+- There is no grouping of buttons on a button bar
+- A button bar typically has a border around each individual button, whereas a tool
+ bar typically has a border around each group of buttons.
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+======================================== ========================================
+Event Name Description
+======================================== ========================================
+``EVT_RIBBONBUTTONBAR_CLICKED`` Triggered when the normal (non-dropdown) region of a button on the button bar is clicked.
+``EVT_RIBBONBUTTONBAR_DROPDOWN_CLICKED`` Triggered when the dropdown region of a button on the button bar is clicked. :meth:`RibbonButtonBarEvent.PopupMenu() <RibbonButtonBarEvent.PopupMenu>` should be called by the event handler if it wants to display a popup menu (which is what most dropdown buttons should be doing).
+======================================== ========================================
+
+"""
+
+import wx
+
+from control import RibbonControl
+from art import *
+
+wxEVT_COMMAND_RIBBONBUTTON_CLICKED = wx.NewEventType()
+wxEVT_COMMAND_RIBBONBUTTON_DROPDOWN_CLICKED = wx.NewEventType()
+
+EVT_RIBBONBUTTONBAR_CLICKED = wx.PyEventBinder(wxEVT_COMMAND_RIBBONBUTTON_CLICKED, 1)
+EVT_RIBBONBUTTONBAR_DROPDOWN_CLICKED = wx.PyEventBinder(wxEVT_COMMAND_RIBBONBUTTON_DROPDOWN_CLICKED, 1)
+
+
+class RibbonButtonBarButtonSizeInfo(object):
+
+ def __init__(self):
+
+ self.is_supported = True
+ self.size = wx.Size()
+ self.normal_region = wx.Rect()
+ self.dropdown_region = wx.Rect()
+
+
+class RibbonButtonBarButtonInstance(object):
+
+ def __init__(self):
+
+ self.position = wx.Point()
+ self.base = None
+ self.size = wx.Size()
+
+
+class RibbonButtonBarButtonBase(object):
+
+ def __init__(self):
+
+ self.label = ""
+ self.help_string = ""
+ self.bitmap_large = wx.NullBitmap
+ self.bitmap_large_disabled = wx.NullBitmap
+ self.bitmap_small = wx.NullBitmap
+ self.bitmap_small_disabled = wx.NullBitmap
+ self.sizes = [RibbonButtonBarButtonSizeInfo() for i in xrange(3)]
+ self.client_data = None
+ self.id = -1
+ self.kind = None
+ self.state = None
+
+
+ def NewInstance(self):
+
+ i = RibbonButtonBarButtonInstance()
+ i.base = self
+ return i
+
+
+ def GetLargestSize(self):
+
+ if self.sizes[RIBBON_BUTTONBAR_BUTTON_LARGE].is_supported:
+ return RIBBON_BUTTONBAR_BUTTON_LARGE
+ if self.sizes[RIBBON_BUTTONBAR_BUTTON_MEDIUM].is_supported:
+ return RIBBON_BUTTONBAR_BUTTON_MEDIUM
+
+ return RIBBON_BUTTONBAR_BUTTON_SMALL
+
+
+ def GetSmallerSize(self, size, n=1):
+
+ for i in xrange(n, 0, -1):
+
+ if size == RIBBON_BUTTONBAR_BUTTON_LARGE:
+ if self.sizes[RIBBON_BUTTONBAR_BUTTON_MEDIUM].is_supported:
+ return True, RIBBON_BUTTONBAR_BUTTON_MEDIUM
+
+ elif size == RIBBON_BUTTONBAR_BUTTON_MEDIUM:
+ if self.sizes[RIBBON_BUTTONBAR_BUTTON_SMALL].is_supported:
+ return True, RIBBON_BUTTONBAR_BUTTON_SMALL
+
+ else:
+ return False, None
+
+
+class RibbonButtonBarLayout(object):
+
+ def __init__(self):
+
+ self.overall_size = wx.Size()
+ self.buttons = []
+
+
+ def CalculateOverallSize(self):
+
+ self.overall_size = wx.Size(0, 0)
+
+ for instance in self.buttons:
+ size = instance.base.sizes[instance.size].size
+ right = instance.position.x + size.GetWidth()
+ bottom = instance.position.y + size.GetHeight()
+
+ if right > self.overall_size.GetWidth():
+ self.overall_size.SetWidth(right)
+ if bottom > self.overall_size.GetHeight():
+ self.overall_size.SetHeight(bottom)
+
+
+ def FindSimilarInstance(self, inst):
+
+ if inst is None:
+ return None
+
+ for instance in self.buttons:
+ if instance.base == inst.base:
+ return instance
+
+ return None
+
+
+class RibbonButtonBarEvent(wx.PyCommandEvent):
+ """
+ Event used to indicate various actions relating to a button on a :class:`RibbonButtonBar`.
+
+ .. seealso:: :class:`RibbonButtonBar` for available event types.
+ """
+
+ def __init__(self, command_type=None, win_id=0, bar=None):
+ """
+ Default class constructor.
+
+ :param integer `command_type`: the event type;
+ :param integer `win_id`: the event identifier;
+ :param `bar`: an instance of :class:`RibbonButtonBar`.
+ """
+
+ wx.PyCommandEvent.__init__(self, command_type, win_id)
+ self._bar = bar
+
+
+ def GetBar(self):
+ """
+ Returns the bar which contains the button which the event relates to.
+
+ :returns: An instance of :class:`RibbonButtonBar`.
+ """
+
+ return self._bar
+
+
+ def SetBar(self, bar):
+ """
+ Sets the button bar relating to this event.
+
+ :param `bar`: an instance of :class:`RibbonButtonBar`.
+
+ """
+
+ self._bar = bar
+
+
+ def PopupMenu(self, menu):
+ """
+ Display a popup menu as a result of this (dropdown clicked) event.
+
+ :param `menu`: an instance of :class:`Menu`.
+ """
+
+ pos = wx.Point()
+
+ if self._bar._active_button:
+ size = self._bar._active_button.base.sizes[self._bar._active_button.size]
+ btn_rect = wx.Rect()
+ btn_rect.SetTopLeft(self._bar._layout_offset + self._bar._active_button.position)
+ btn_rect.SetSize(wx.Size(*size.size))
+ pos = btn_rect.GetBottomLeft()
+ pos.y += 1
+
+ return self._bar.PopupMenu(menu, pos)
+
+
+class RibbonButtonBar(RibbonControl):
+ """ A ribbon button bar is similar to a traditional toolbar. """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, agwStyle=0):
+ """
+ Default class constructor.
+
+ :param `parent`: pointer to a parent window, typically a :class:`~lib.agw.ribbon.panel.RibbonPanel`;
+ :type `parent`: :class:`Window`
+ :param integer `id`: window identifier. If ``wx.ID_ANY``, will automatically create
+ an identifier;
+ :param `pos`: window position. ``wx.DefaultPosition`` indicates that wxPython
+ should generate a default position for the window;
+ :type `pos`: tuple or :class:`Point`
+ :param `size`: window size. ``wx.DefaultSize`` indicates that wxPython should
+ generate a default size for the window. If no suitable size can be found, the
+ window will be sized to 20x20 pixels so that the window is visible but obviously
+ not correctly sized;
+ :type `size`: tuple or :class:`Size`
+ :param integer `agwStyle`: the AGW-specific window style, currently unused.
+ """
+
+ RibbonControl.__init__(self, parent, id, pos, size, style=wx.BORDER_NONE)
+
+ self._layouts_valid = False
+ self.CommonInit(agwStyle)
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
+
+
+ def AddButton(self, button_id, label, bitmap, bitmap_small=wx.NullBitmap, bitmap_disabled=wx.NullBitmap,
+ bitmap_small_disabled=wx.NullBitmap, kind=RIBBON_BUTTON_NORMAL, help_string="", client_data=None):
+ """
+ Add a button to the button bar.
+
+ :param integer `button_id`: id of the new button (used for event callbacks);
+ :param string `label`: label of the new button;
+ :param `bitmap`: large bitmap of the new button, an instance of :class:`Bitmap`. Must be the same size as
+ all other large bitmaps used on the button bar;
+ :param `bitmap_small`: small bitmap of the new button, an instance of :class:`Bitmap`. If left as :class:`NullBitmap`,
+ then a small bitmap will be automatically generated. Must be the same size
+ as all other small bitmaps used on the button bar;
+ :param `bitmap_disabled`: large bitmap of the new button when it is disabled, an instance of :class:`Bitmap`.
+ If left as :class:`NullBitmap`, then a bitmap will be automatically generated from `bitmap`;
+ :param `bitmap_small_disabled`: small bitmap of the new button when it is disabled, an instance of :class:`Bitmap`.
+ If left as :class:`NullBitmap`, then a bitmap will be automatically generated from `bitmap_small`;
+ :param integer `kind`: the kind of button to add, one of the following values:
+
+ ========================================== =========== ==========================================
+ Button Kind Hex Value Description
+ ========================================== =========== ==========================================
+ ``RIBBON_BUTTON_NORMAL`` 0x1 Normal button or tool with a clickable area which causes some generic action.
+ ``RIBBON_BUTTON_DROPDOWN`` 0x2 Dropdown button or tool with a clickable area which typically causes a dropdown menu.
+ ``RIBBON_BUTTON_HYBRID`` 0x3 Button or tool with two clickable areas - one which causes a dropdown menu, and one which causes a generic action.
+ ``RIBBON_BUTTON_TOGGLE`` 0x4 Normal button or tool with a clickable area which toggles the button between a pressed and unpressed state.
+ ========================================== =========== ==========================================
+
+ :param string `help_string`: the UI help string to associate with the new button;
+ :param object `client_data`: client data to associate with the new button (any Python object).
+
+ :returns: An opaque pointer which can be used only with other button bar methods.
+
+ :see: :meth:`~RibbonButtonBar.InsertButton`, :meth:`~RibbonButtonBar.AddDropdownButton`, :meth:`~RibbonButtonBar.AddHybridButton`
+ """
+
+ return self.InsertButton(self.GetButtonCount(), button_id, label, bitmap,
+ bitmap_small, bitmap_disabled, bitmap_small_disabled, kind, help_string,
+ client_data)
+
+
+ def AddSimpleButton(self, button_id, label, bitmap, help_string, kind=RIBBON_BUTTON_NORMAL):
+ """
+ Add a button to the button bar (simple version).
+
+ :param integer `button_id`: id of the new button (used for event callbacks);
+ :param string `label`: label of the new button;
+ :param `bitmap`: large bitmap of the new button, an instance of :class:`Bitmap`. Must be the same size as
+ all other large bitmaps used on the button bar;
+ :param string `help_string`: the UI help string to associate with the new button;
+ :param integer `kind`: the kind of button to add.
+
+ :returns: An opaque pointer which can be used only with other button bar methods.
+
+ :see: :meth:`~RibbonButtonBar.AddButton` for a list of valid button `kind` values.
+ """
+
+ return self.AddButton(button_id, label, bitmap, wx.NullBitmap, wx.NullBitmap,
+ wx.NullBitmap, kind, help_string)
+
+
+ def InsertButton(self, pos, button_id, label, bitmap, bitmap_small=wx.NullBitmap, bitmap_disabled=wx.NullBitmap,
+ bitmap_small_disabled=wx.NullBitmap, kind=RIBBON_BUTTON_NORMAL, help_string="", client_data=None):
+
+ """
+ Inserts a button in the button bar at the position specified by `pos`.
+
+ :param integer `pos`: the position at which the new button must be inserted (zero-based);
+ :param integer `button_id`: id of the new button (used for event callbacks);
+ :param string `label`: label of the new button;
+ :param `bitmap`: large bitmap of the new button, an instance of :class:`Bitmap`. Must be the same size as
+ all other large bitmaps used on the button bar;
+ :param `bitmap_small`: small bitmap of the new button, an instance of :class:`Bitmap`. If left as :class:`NullBitmap`,
+ then a small bitmap will be automatically generated. Must be the same size
+ as all other small bitmaps used on the button bar;
+ :param `bitmap_disabled`: large bitmap of the new button when it is disabled, an instance of :class:`Bitmap`.
+ If left as :class:`NullBitmap`, then a bitmap will be automatically generated from `bitmap`;
+ :param `bitmap_small_disabled`: small bitmap of the new button when it is disabled, an instance of :class:`Bitmap`.
+ If left as :class:`NullBitmap`, then a bitmap will be automatically generated from `bitmap_small`;
+ :param integer `kind`: the kind of button to add;
+ :param string `help_string`: the UI help string to associate with the new button;
+ :param object `client_data`: client data to associate with the new button.
+
+ :returns: An opaque pointer which can be used only with other button bar methods.
+
+ :raise: `Exception` if both `bitmap` and `bitmap_small` are invalid or if the input `help_string` is not
+ a valid Python `basestring`.
+
+ :see: :meth:`~RibbonButtonBar.AddDropdownButton`, :meth:`~RibbonButtonBar.AddHybridButton` and :meth:`~RibbonButtonBar.AddButton` for a list of valid button `kind` values.
+
+ .. versionadded:: 0.9.5
+ """
+
+ if not bitmap.IsOk() and not bitmap_small.IsOk():
+ raise Exception("Invalid main bitmap")
+
+ if not isinstance(help_string, basestring):
+ raise Exception("Invalid help string parameter")
+
+ if not self._buttons:
+ if bitmap.IsOk():
+
+ self._bitmap_size_large = bitmap.GetSize()
+ if not bitmap_small.IsOk():
+ w, h = self._bitmap_size_large
+ self._bitmap_size_small = wx.Size(0.5*w, 0.5*h)
+
+ if bitmap_small.IsOk():
+
+ self._bitmap_size_small = bitmap_small.GetSize()
+ if not bitmap.IsOk():
+ w, h = self._bitmap_size_small
+ self._bitmap_size_large = wx.Size(2*w, 2*h)
+
+ base = RibbonButtonBarButtonBase()
+ base.id = button_id
+ base.label = label
+ base.bitmap_large = bitmap
+
+ if not base.bitmap_large.IsOk():
+ base.bitmap_large = self.MakeResizedBitmap(base.bitmap_small, self._bitmap_size_large)
+
+ elif base.bitmap_large.GetSize() != self._bitmap_size_large:
+ base.bitmap_large = self.MakeResizedBitmap(base.bitmap_large, self._bitmap_size_large)
+
+ base.bitmap_small = bitmap_small
+
+ if not base.bitmap_small.IsOk():
+ base.bitmap_small = self.MakeResizedBitmap(base.bitmap_large, self._bitmap_size_small)
+
+ elif base.bitmap_small.GetSize() != self._bitmap_size_small:
+ base.bitmap_small = self.MakeResizedBitmap(base.bitmap_small, self._bitmap_size_small)
+
+ base.bitmap_large_disabled = bitmap_disabled
+
+ if not base.bitmap_large_disabled.IsOk():
+ base.bitmap_large_disabled = self.MakeDisabledBitmap(base.bitmap_large)
+
+ base.bitmap_small_disabled = bitmap_small_disabled
+
+ if not base.bitmap_small_disabled.IsOk():
+ base.bitmap_small_disabled = self.MakeDisabledBitmap(base.bitmap_small)
+
+ base.kind = kind
+ base.help_string = help_string
+ base.client_data = client_data
+ base.state = 0
+
+ temp_dc = wx.ClientDC(self)
+ self.FetchButtonSizeInfo(base, RIBBON_BUTTONBAR_BUTTON_SMALL, temp_dc)
+ self.FetchButtonSizeInfo(base, RIBBON_BUTTONBAR_BUTTON_MEDIUM, temp_dc)
+ self.FetchButtonSizeInfo(base, RIBBON_BUTTONBAR_BUTTON_LARGE, temp_dc)
+
+ self._buttons.insert(pos, base)
+ self._layouts_valid = False
+
+ return base
+
+
+ def AddDropdownButton(self, button_id, label, bitmap, help_string=""):
+ """
+ Add a dropdown button to the button bar (simple version).
+
+ :param integer `button_id`: id of the new button (used for event callbacks);
+ :param string `label`: label of the new button;
+ :param `bitmap`: large bitmap of the new button, an instance of :class:`Bitmap`. Must be the same size as
+ all other large bitmaps used on the button bar;
+ :param string `help_string`: the UI help string to associate with the new button.
+
+ :returns: An opaque pointer which can be used only with other button bar methods.
+
+ :see: :meth:`~RibbonButtonBar.AddButton`, :meth:`~RibbonButtonBar.InsertDropdownButton`, :meth:`~RibbonButtonBar.InsertButton`
+ """
+
+ return self.AddSimpleButton(button_id, label, bitmap, kind=RIBBON_BUTTON_DROPDOWN, help_string=help_string)
+
+
+ def InsertDropdownButton(self, pos, button_id, label, bitmap, help_string=""):
+ """
+ Inserts a dropdown button in the button bar at the position specified by `pos`.
+
+ :param integer `pos`: the position at which the new button must be inserted (zero-based);
+ :param integer `button_id`: id of the new button (used for event callbacks);
+ :param string `label`: label of the new button;
+ :param `bitmap`: large bitmap of the new button, an instance of :class:`Bitmap`. Must be the same size as
+ all other large bitmaps used on the button bar;
+ :param string `help_string`: the UI help string to associate with the new button.
+
+ :returns: An opaque pointer which can be used only with other button bar methods.
+
+ :see: :meth:`~RibbonButtonBar.AddButton`, :meth:`~RibbonButtonBar.InsertButton`, :meth:`~RibbonButtonBar.AddDropdownButton`
+
+ .. versionadded:: 0.9.5
+ """
+
+ return self.InsertButton(pos, button_id, label, bitmap, kind=RIBBON_BUTTON_DROPDOWN, help_string=help_string)
+
+
+ def AddToggleButton(self, button_id, label, bitmap, help_string=""):
+ """
+ Add a toggle button to the button bar.
+
+ :param integer `button_id`: id of the new button (used for event callbacks);
+ :param string `label`: label of the new button;
+ :param `bitmap`: large bitmap of the new button, an instance of :class:`Bitmap`. Must be the same size as
+ all other large bitmaps used on the button bar;
+ :param string `help_string`: the UI help string to associate with the new button.
+
+ :returns: An opaque pointer which can be used only with other button bar methods.
+
+ :see: :meth:`~RibbonButtonBar.AddButton`, :meth:`~RibbonButtonBar.InsertButton`, :meth:`~RibbonButtonBar.InsertToggleButton`
+ """
+
+ return self.AddButton(button_id, label, bitmap, kind=RIBBON_BUTTON_TOGGLE, help_string=help_string)
+
+
+ def InsertToggleButton(self, pos, button_id, label, bitmap, help_string=""):
+ """
+ Inserts a toggle button in the button bar at the position specified by `pos`.
+
+ :param integer `pos`: the position at which the new button must be inserted (zero-based);
+ :param integer `button_id`: id of the new button (used for event callbacks);
+ :param string `label`: label of the new button;
+ :param `bitmap`: large bitmap of the new button, an instance of :class:`Bitmap`. Must be the same size as
+ all other large bitmaps used on the button bar;
+ :param string `help_string`: the UI help string to associate with the new button.
+
+ :returns: An opaque pointer which can be used only with other button bar methods.
+
+ :see: :meth:`~RibbonButtonBar.AddButton`, :meth:`~RibbonButtonBar.InsertButton`, :meth:`~RibbonButtonBar.AddToggleButton`
+
+ .. versionadded:: 0.9.5
+ """
+
+ return self.InsertButton(pos, button_id, label, bitmap, kind=RIBBON_BUTTON_TOGGLE, help_string=help_string)
+
+
+ def AddHybridButton(self, button_id, label, bitmap, help_string=""):
+ """
+ Add a hybrid button to the button bar (simple version).
+
+ :param integer `button_id`: id of the new button (used for event callbacks);
+ :param string `label`: label of the new button;
+ :param `bitmap`: large bitmap of the new button, an instance of :class:`Bitmap`. Must be the same size as
+ all other large bitmaps used on the button bar;
+ :param string `help_string`: the UI help string to associate with the new button.
+
+ :returns: An opaque pointer which can be used only with other button bar methods.
+
+ :see: :meth:`~RibbonButtonBar.AddButton`, :meth:`~RibbonButtonBar.InsertButton`, :meth:`~RibbonButtonBar.InsertHybridButton`
+ """
+
+ return self.AddSimpleButton(button_id, label, bitmap, kind=RIBBON_BUTTON_HYBRID, help_string=help_string)
+
+
+ def InsertHybridButton(self, pos, button_id, label, bitmap, help_string=""):
+ """
+ Inserts a hybrid button in the button bar at the position specified by `pos`.
+
+ :param integer `pos`: the position at which the new button must be inserted (zero-based);
+ :param integer `button_id`: id of the new button (used for event callbacks);
+ :param string `label`: label of the new button;
+ :param `bitmap`: large bitmap of the new button, an instance of :class:`Bitmap`. Must be the same size as
+ all other large bitmaps used on the button bar;
+ :param string `help_string`: the UI help string to associate with the new button.
+
+ :returns: An opaque pointer which can be used only with other button bar methods.
+
+ :see: :meth:`~RibbonButtonBar.AddButton`, :meth:`~RibbonButtonBar.InsertButton`, :meth:`~RibbonButtonBar.AddHybridButton`
+
+ .. versionadded:: 0.9.5
+ """
+
+ return self.InsertButton(pos, button_id, label, bitmap, kind=RIBBON_BUTTON_HYBRID, help_string=help_string)
+
+
+ def FetchButtonSizeInfo(self, button, size, dc):
+
+ info = button.sizes[size]
+
+ if self._art:
+
+ info.is_supported, info.size, info.normal_region, info.dropdown_region = \
+ self._art.GetButtonBarButtonSize(dc, self, button.kind, size, button.label,
+ self._bitmap_size_large, self._bitmap_size_small)
+
+ else:
+ info.is_supported = False
+
+
+ def MakeResizedBitmap(self, original, size):
+ """
+ Resize and scale the `original` bitmap to the dimensions specified in `size`.
+
+ :param `original`: the original bitmap, an instance of :class:`Bitmap`;
+ :param `size`: the size to which the input bitmap must be rescaled, an instance of :class:`Size`.
+
+ :return: A scaled representation of the input bitmap.
+ """
+
+ img = original.ConvertToImage()
+ img.Rescale(size.GetWidth(), size.GetHeight(), wx.IMAGE_QUALITY_HIGH)
+ return wx.BitmapFromImage(img)
+
+
+ def MakeDisabledBitmap(self, original):
+ """
+ Converts the `original` bitmap into a visually-looking disabled one.
+
+ :param `original`: the original bitmap, an instance of :class:`Bitmap`.
+
+ :return: A visually-looking disabled representation of the input bitmap.
+ """
+
+ img = original.ConvertToImage()
+ return wx.BitmapFromImage(img.ConvertToGreyscale())
+
+
+ def Realize(self):
+ """
+ Calculate button layouts and positions.
+
+ Must be called after buttons are added to the button bar, as otherwise the newly
+ added buttons will not be displayed. In normal situations, it will be called
+ automatically when :meth:`RibbonBar.Realize() <lib.agw.ribbon.bar.RibbonBar.Realize>` is called.
+
+ :note: Reimplemented from :class:`~lib.agw.ribbon.control.RibbonControl`.
+ """
+
+ if not self._layouts_valid:
+ self.MakeLayouts()
+ self._layouts_valid = True
+
+ return True
+
+
+ def ClearButtons(self):
+ """
+ Delete all buttons from the button bar.
+
+ :see: :meth:`~RibbonButtonBar.DeleteButton`
+ """
+
+ self._layouts_valid = False
+ self._buttons = []
+ self.Realize()
+
+
+ def DeleteButton(self, button_id):
+ """
+ Delete a single button from the button bar.
+
+ :param integer `button_id`: id of the button to delete.
+
+ :return: ``True`` if the button has been found and successfully deleted, ``False`` otherwise.
+
+ :see: :meth:`~RibbonButtonBar.ClearButtons`
+ """
+
+ for button in self._buttons:
+ if button.id == button_id:
+ self._layouts_valid = False
+ self._buttons.pop(button)
+ self.Realize()
+ self.Refresh()
+ return True
+
+ return False
+
+
+ def EnableButton(self, button_id, enable=True):
+ """
+ Enable or disable a single button on the bar.
+
+ :param integer `button_id`: id of the button to enable or disable;
+ :param bool `enable`: ``True`` to enable the button, ``False`` to disable it.
+
+ :raise: `Exception` when the input `button_id` could not be associated
+ with a :class:`RibbonButtonBar` button.
+ """
+
+ for button in self._buttons:
+ if button.id == button_id:
+ if enable:
+ if button.state & RIBBON_BUTTONBAR_BUTTON_DISABLED:
+ button.state &= ~RIBBON_BUTTONBAR_BUTTON_DISABLED
+ self.Refresh()
+ else:
+ if button.state & RIBBON_BUTTONBAR_BUTTON_DISABLED == 0:
+ button.state |= RIBBON_BUTTONBAR_BUTTON_DISABLED
+ self.Refresh()
+
+ return
+
+ raise Exception('Invalid button id specified.')
+
+
+ def ToggleButton(self, button_id, checked=True):
+ """
+ Toggles/untoggles a :class:`RibbonButtonBar` toggle button.
+
+ :param integer `button_id`: id of the button to be toggles/untoggled;
+ :param bool `checked`: ``True`` to toggle the button, ``False`` to untoggle it.
+
+ :raise: `Exception` when the input `button_id` could not be associated
+ with a :class:`RibbonButtonBar` button.
+ """
+
+ for button in self._buttons:
+ if button.id == button_id:
+ if checked:
+ if button.state & RIBBON_BUTTONBAR_BUTTON_TOGGLED == 0:
+ button.state |= RIBBON_BUTTONBAR_BUTTON_TOGGLED
+ self.Refresh()
+ else:
+ if button.state & RIBBON_BUTTONBAR_BUTTON_TOGGLED:
+ button.state &= ~RIBBON_BUTTONBAR_BUTTON_TOGGLED
+ self.Refresh()
+
+ return
+
+ raise Exception('Invalid button id specified.')
+
+
+ def IsButtonEnabled(self, button_id):
+ """
+ Returns whether a button in the bar is enabled or not.
+
+ :param integer `button_id`: id of the button to check.
+
+ :return: ``True`` if the button is enabled, ``False`` otherwise.
+
+ :raise: `Exception` when the input `button_id` could not be associated
+ with a :class:`RibbonButtonBar` button.
+ """
+
+ for button in self._buttons:
+ if button.id == button_id:
+ if button.state & RIBBON_BUTTONBAR_BUTTON_DISABLED:
+ return False
+ return True
+
+ raise Exception('Invalid button id specified.')
+
+
+ def GetButtonCount(self):
+ """
+ Returns the number of buttons in this :class:`RibbonButtonBar`.
+
+ .. versionadded:: 0.9.5
+ """
+
+ return len(self._buttons)
+
+
+ def SetArtProvider(self, art):
+ """
+ Set the art provider to be used.
+
+ In many cases, setting the art provider will also set the art provider on all
+ child windows which extend :class:`~lib.agw.ribbon.control.RibbonControl`. In most cases, controls will not
+ take ownership of the given pointer, with the notable exception being
+ :meth:`RibbonBar.SetArtProvider() <lib.agw.ribbon.bar.RibbonBar.SetArtProvider>`.
+
+ :param `art`: an art provider.
+ """
+
+ if art == self._art:
+ return
+
+ RibbonControl.SetArtProvider(self, art)
+
+ temp_dc = wx.ClientDC(self)
+ for base in self._buttons:
+ self.FetchButtonSizeInfo(base, RIBBON_BUTTONBAR_BUTTON_SMALL, temp_dc)
+ self.FetchButtonSizeInfo(base, RIBBON_BUTTONBAR_BUTTON_MEDIUM, temp_dc)
+ self.FetchButtonSizeInfo(base, RIBBON_BUTTONBAR_BUTTON_LARGE, temp_dc)
+
+ self._layouts_valid = False
+ self.Realize()
+
+
+ def IsSizingContinuous(self):
+ """
+ Returns ``True`` if this window can take any size (greater than its minimum size),
+ ``False`` if it can only take certain sizes.
+
+ :see: :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`,
+ :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`
+ """
+
+ return False
+
+
+ def DoGetNextSmallerSize(self, direction, _result):
+ """
+ Implementation of :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`.
+
+ Controls which have non-continuous sizing must override this virtual function
+ rather than :meth:`RibbonControl.GetNextSmallerSize() <RibbonControl.GetNextSmallerSize>`.
+
+ :return: An instance of :class:`Size`.
+ """
+
+ result = wx.Size(*_result)
+
+ for i, layout in enumerate(self._layouts):
+ size = wx.Size(*layout.overall_size)
+
+ if direction == wx.HORIZONTAL:
+ if size.x < result.x and size.y <= result.y:
+ result.x = size.x
+ break
+
+ elif direction == wx.VERTICAL:
+ if size.x <= result.x and size.y < result.y:
+ result.y = size.y
+ break
+
+ elif direction == wx.BOTH:
+ if size.x < result.x and size.y < result.y:
+ result = size
+ break
+
+ return result
+
+
+ def DoGetNextLargerSize(self, direction, _result):
+ """
+ Implementation of :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`.
+
+ Controls which have non-continuous sizing must override this virtual function
+ rather than :meth:`RibbonControl.GetNextLargerSize() <RibbonControl.GetNextLargerSize>`.
+
+ :return: An instance of :class:`Size`.
+ """
+
+ nlayouts = i = len(self._layouts)
+ result = wx.Size(*_result)
+
+ while 1:
+ i -= 1
+ layout = self._layouts[i]
+ size = wx.Size(*layout.overall_size)
+
+ if direction == wx.HORIZONTAL:
+ if size.x > result.x and size.y <= result.y:
+ result.x = size.x
+ break
+
+ elif direction == wx.VERTICAL:
+ if size.x <= result.x and size.y > result.y:
+ result.y = size.y
+ break
+
+ elif direction == wx.BOTH:
+ if size.x > result.x and size.y > result.y:
+ result = size
+ break
+
+ if i <= 0:
+ break
+
+ return result
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`RibbonButtonBar`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+ """
+
+ # All painting done in main paint handler to minimise flicker
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`RibbonButtonBar`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+ self._art.DrawButtonBarBackground(dc, self, wx.Rect(0, 0, *self.GetSize()))
+
+ layout = self._layouts[self._current_layout]
+
+ for button in layout.buttons:
+ base = button.base
+
+ bitmap = base.bitmap_large
+ bitmap_small = base.bitmap_small
+
+ if base.state & RIBBON_BUTTONBAR_BUTTON_DISABLED:
+ bitmap = base.bitmap_large_disabled
+ bitmap_small = base.bitmap_small_disabled
+
+ rect = wx.RectPS(button.position + self._layout_offset, base.sizes[button.size].size)
+ self._art.DrawButtonBarButton(dc, self, rect, base.kind, base.state | button.size, base.label, bitmap, bitmap_small)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`RibbonButtonBar`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ new_size = event.GetSize()
+ layout_count = len(self._layouts)
+ self._current_layout = layout_count - 1
+
+ for layout_i in xrange(layout_count):
+
+ layout_size = self._layouts[layout_i].overall_size
+ if layout_size.x <= new_size.x and layout_size.y <= new_size.y:
+ self._layout_offset.x = (new_size.x - layout_size.x)/2
+ self._layout_offset.y = (new_size.y - layout_size.y)/2
+ self._current_layout = layout_i
+ break
+
+ self._hovered_button = self._layouts[self._current_layout].FindSimilarInstance(self._hovered_button)
+ self.Refresh()
+
+
+ def UpdateWindowUI(self, flags):
+ """
+ This function sends one or more :class:`UpdateUIEvent` to the window.
+
+ The particular implementation depends on the window; for example a :class:`ToolBar` will
+ send an update UI event for each toolbar button, and a :class:`Frame` will send an
+ update UI event for each menubar menu item.
+
+ You can call this function from your application to ensure that your UI is up-to-date
+ at this point (as far as your :class:`UpdateUIEvent` handlers are concerned). This may be
+ necessary if you have called :meth:`UpdateUIEvent.SetMode` or :meth:`UpdateUIEvent.SetUpdateInterval`
+ to limit the overhead that wxWidgets incurs by sending update UI events in idle time.
+
+ :param integer `flags`: should be a bitlist of one or more of ``wx.UPDATE_UI_NONE``,
+ ``wx.UPDATE_UI_RECURSE`` or ``wx.UPDATE_UI_FROMIDLE``.
+
+ If you are calling this function from an `OnInternalIdle` or `OnIdle` function, make sure
+ you pass the ``wx.UPDATE_UI_FROMIDLE`` flag, since this tells the window to only update
+ the UI elements that need to be updated in idle time. Some windows update their elements
+ only when necessary, for example when a menu is about to be shown. The following is an
+ example of how to call :meth:`~RibbonButtonBar.UpdateWindowUI` from an idle function::
+
+ def OnInternalIdle(self):
+
+ if wx.UpdateUIEvent.CanUpdate(self):
+ self.UpdateWindowUI(wx.UPDATE_UI_FROMIDLE)
+
+
+
+ .. versionadded:: 0.9.5
+ """
+
+ wx.PyControl.UpdateWindowUI(self, flags)
+
+ # don't waste time updating state of tools in a hidden toolbar
+ if not self.IsShown():
+ return
+
+ rerealize = False
+
+ for button in self._buttons:
+
+ id = button.id
+ event = wx.UpdateUIEvent(id)
+ event.SetEventObject(self)
+
+ if self.ProcessWindowEvent(event):
+ if event.GetSetEnabled():
+ self.EnableButton(id, event.GetEnabled())
+ if event.GetSetChecked():
+ self.ToggleButton(id, event.GetChecked())
+ if event.GetSetText():
+ button.label = event.GetText()
+ rerealize = True
+
+ if rerealize:
+ self.Realize()
+
+
+ def CommonInit(self, agwStyle):
+ """
+ Common initialization procedures.
+
+ :param integer `agwStyle`: the AGW-specific window style, currently unused.
+ """
+
+ self._bitmap_size_large = wx.Size(32, 32)
+ self._bitmap_size_small = wx.Size(16, 16)
+
+ self._layouts = []
+ self._buttons = []
+
+ placeholder_layout = RibbonButtonBarLayout()
+ placeholder_layout.overall_size = wx.Size(20, 20)
+ self._layouts.append(placeholder_layout)
+ self._current_layout = 0
+ self._layout_offset = wx.Point(0, 0)
+ self._hovered_button = None
+ self._active_button = None
+ self._lock_active_state = False
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+
+ def GetMinSize(self):
+ """
+ Returns the minimum size of the window, an indication to the sizer layout mechanism
+ that this is the minimum required size.
+
+ This method normally just returns the value set by `SetMinSize`, but it can be
+ overridden to do the calculation on demand.
+
+ :return: An instance of :class:`Size`.
+ """
+
+ return wx.Size(*self._layouts[-1].overall_size)
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :return: An instance of :class:`Size`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return wx.Size(*self._layouts[0].overall_size)
+
+
+ def MakeLayouts(self):
+
+ if self._layouts_valid or self._art == None:
+ return
+
+ # Clear existing layouts
+ if self._hovered_button:
+ self._hovered_button.base.state &= ~RIBBON_BUTTONBAR_BUTTON_HOVER_MASK
+ self._hovered_button = None
+
+ if self._active_button:
+ self._active_button.base.state &= ~RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK
+ self._active_button = None
+
+ self._layouts = []
+
+ # Best layout : all buttons large, stacking horizontally
+ layout = RibbonButtonBarLayout()
+ cursor = wx.Point(0, 0)
+ layout.overall_size.SetHeight(0)
+
+ for button in self._buttons:
+ instance = button.NewInstance()
+ instance.position = wx.Point(*cursor)
+ instance.size = button.GetLargestSize()
+ size = wx.Size(*button.sizes[instance.size].size)
+ cursor.x += size.GetWidth()
+ layout.overall_size.SetHeight(max(layout.overall_size.GetHeight(), size.GetHeight()))
+ layout.buttons.append(instance)
+
+ layout.overall_size.SetWidth(cursor.x)
+ self._layouts.append(layout)
+
+ if len(self._buttons) >= 2:
+ # Collapse the rightmost buttons and stack them vertically
+ iLast = len(self._buttons) - 1
+ result = True
+
+ while result and iLast > 0:
+ result, iLast = self.TryCollapseLayout(self._layouts[-1], iLast)
+ iLast -= 1
+
+
+ def TryCollapseLayout(self, original, first_btn, last_button=None):
+
+ btn_count = len(self._buttons)
+ used_height = 0
+ used_width = 0
+ available_width = 0
+ available_height = 0
+
+ count = first_btn + 1
+
+ while 1:
+ count -= 1
+
+ button = self._buttons[count]
+ large_size_class = button.GetLargestSize()
+ large_size = button.sizes[large_size_class].size
+ t_available_height = max(available_height, large_size.GetHeight())
+ t_available_width = available_width + large_size.GetWidth()
+ small_size_class = large_size_class
+
+ result, small_size_class = button.GetSmallerSize(small_size_class)
+ if not result:
+ return False, count
+
+ small_size = button.sizes[small_size_class].size
+ t_used_height = used_height + small_size.GetHeight()
+ t_used_width = max(used_width, small_size.GetWidth())
+
+ if t_used_height > t_available_height:
+ count += 1
+ break
+
+ else:
+ used_height = t_used_height
+ used_width = t_used_width
+ available_width = t_available_width
+ available_height = t_available_height
+
+ if count <= 0:
+ break
+
+ if count >= first_btn or used_width >= available_width:
+ return False, count
+
+ if last_button != None:
+ last_button = count
+
+ layout = RibbonButtonBarLayout()
+ for indx, button in enumerate(original.buttons):
+ instance = RibbonButtonBarButtonInstance()
+ instance.position = wx.Point(*button.position)
+ instance.size = button.size
+ instance.base = self._buttons[indx]
+ layout.buttons.append(instance)
+
+ cursor = wx.Point(*layout.buttons[count].position)
+ preserve_height = False
+
+ if count == 0:
+ # If height isn't preserved (i.e. it is reduced), then the minimum
+ # size for the button bar will decrease, preventing the original
+ # layout from being used (in some cases).
+ # It may be a good idea to always preverse the height, but for now
+ # it is only done when the first button is involved in a collapse.
+ preserve_height = True
+
+ for btn_i in xrange(count, first_btn+1):
+ instance = layout.buttons[btn_i]
+ result, instance.size = instance.base.GetSmallerSize(instance.size)
+ instance.position = wx.Point(*cursor)
+ cursor.y += instance.base.sizes[instance.size].size.GetHeight()
+
+ x_adjust = available_width - used_width
+
+ for btn_i in xrange(first_btn+1, btn_count):
+ instance = layout.buttons[btn_i]
+ instance.position.x -= x_adjust
+
+ layout.CalculateOverallSize()
+
+## # Sanity check
+## if layout.overall_size.GetWidth() >= original.overall_size.GetWidth() or \
+## layout.overall_size.GetHeight() > original.overall_size.GetHeight():
+##
+## del layout
+## return False, count
+
+ if preserve_height:
+ layout.overall_size.SetHeight(original.overall_size.GetHeight())
+
+ self._layouts.append(layout)
+ return True, count
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`RibbonButtonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ cursor = event.GetPosition()
+ new_hovered = None
+ new_hovered_state = 0
+
+ layout = self._layouts[self._current_layout]
+
+ for instance in layout.buttons:
+ size = instance.base.sizes[instance.size]
+ btn_rect = wx.Rect()
+ btn_rect.SetTopLeft(self._layout_offset + instance.position)
+ btn_rect.SetSize(size.size)
+
+ if btn_rect.Contains(cursor) and self.IsButtonEnabled(instance.base.id):
+ new_hovered = instance
+ new_hovered_state = instance.base.state
+ new_hovered_state &= ~RIBBON_BUTTONBAR_BUTTON_HOVER_MASK
+ offset = wx.Point(*cursor)
+ offset -= btn_rect.GetTopLeft()
+ if size.normal_region.Contains(offset):
+ new_hovered_state |= RIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED
+
+ if size.dropdown_region.Contains(offset):
+ new_hovered_state |= RIBBON_BUTTONBAR_BUTTON_DROPDOWN_HOVERED
+
+ break
+
+ if new_hovered == None and self.GetToolTip():
+ self.SetToolTipString("")
+
+ if new_hovered != self._hovered_button or (self._hovered_button != None and \
+ new_hovered_state != self._hovered_button.base.state):
+
+ if self._hovered_button != None:
+ self._hovered_button.base.state &= ~RIBBON_BUTTONBAR_BUTTON_HOVER_MASK
+
+ self._hovered_button = new_hovered
+ if self._hovered_button != None:
+ self._hovered_button.base.state = new_hovered_state
+ self.SetToolTipString(self._hovered_button.base.help_string)
+
+ self.Refresh(False)
+
+ if self._active_button and not self._lock_active_state:
+
+ new_active_state = self._active_button.base.state
+ new_active_state &= ~RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK
+ size = self._active_button.base.sizes[self._active_button.size]
+ btn_rect = wx.Rect()
+ btn_rect.SetTopLeft(self._layout_offset + self._active_button.position)
+ btn_rect.SetSize(size.size)
+
+ if btn_rect.Contains(cursor):
+
+ offset = wx.Point(*cursor)
+ offset -= btn_rect.GetTopLeft()
+
+ if size.normal_region.Contains(offset):
+ new_active_state |= RIBBON_BUTTONBAR_BUTTON_NORMAL_ACTIVE
+
+ if size.dropdown_region.Contains(offset):
+ new_active_state |= RIBBON_BUTTONBAR_BUTTON_DROPDOWN_ACTIVE
+
+ if new_active_state != self._active_button.base.state:
+ self._active_button.base.state = new_active_state
+ self.Refresh(False)
+
+
+ def OnMouseDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`RibbonButtonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ cursor = event.GetPosition()
+ self._active_button = None
+
+ layout = self._layouts[self._current_layout]
+
+ for instance in layout.buttons:
+
+ size = instance.base.sizes[instance.size]
+ btn_rect = wx.Rect()
+ btn_rect.SetTopLeft(self._layout_offset + instance.position)
+ btn_rect.SetSize(size.size)
+
+ if btn_rect.Contains(cursor) and self.IsButtonEnabled(instance.base.id):
+ self._active_button = instance
+ cursor -= btn_rect.GetTopLeft()
+ state = 0
+ if size.normal_region.Contains(cursor):
+ state = RIBBON_BUTTONBAR_BUTTON_NORMAL_ACTIVE
+ elif size.dropdown_region.Contains(cursor):
+ state = RIBBON_BUTTONBAR_BUTTON_DROPDOWN_ACTIVE
+ instance.base.state |= state
+ self.Refresh(False)
+ break
+
+
+ def OnMouseUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`RibbonButtonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ cursor = event.GetPosition()
+
+ if self._active_button:
+
+ size = self._active_button.base.sizes[self._active_button.size]
+ btn_rect = wx.Rect()
+ btn_rect.SetTopLeft(self._layout_offset + self._active_button.position)
+ btn_rect.SetSize(size.size)
+
+ if btn_rect.Contains(cursor):
+ id = self._active_button.base.id
+ cursor -= btn_rect.GetTopLeft()
+
+ while 1:
+ if size.normal_region.Contains(cursor):
+ event_type = wxEVT_COMMAND_RIBBONBUTTON_CLICKED
+ elif size.dropdown_region.Contains(cursor):
+ event_type = wxEVT_COMMAND_RIBBONBUTTON_DROPDOWN_CLICKED
+ else:
+ break
+
+ notification = RibbonButtonBarEvent(event_type, id)
+
+ if self._active_button.base.kind == RIBBON_BUTTON_TOGGLE:
+ self._active_button.base.state ^= RIBBON_BUTTONBAR_BUTTON_TOGGLED
+ notification.SetInt(self._active_button.base.state & RIBBON_BUTTONBAR_BUTTON_TOGGLED)
+
+ notification.SetEventObject(self)
+ notification.SetBar(self)
+ self._lock_active_state = True
+ self.GetEventHandler().ProcessEvent(notification)
+ self._lock_active_state = False
+ break
+
+ if self._active_button: # may have been Noneed by event handler
+ self._active_button.base.state &= ~RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK
+ self._active_button = None
+
+ self.Refresh()
+
+
+ def OnMouseEnter(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`RibbonButtonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._active_button and not event.LeftIsDown():
+ self._active_button = None
+
+
+ def OnMouseLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`RibbonButtonBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ repaint = False
+ if self._hovered_button != None:
+ self._hovered_button.base.state &= ~RIBBON_BUTTONBAR_BUTTON_HOVER_MASK
+ self._hovered_button = None
+ repaint = True
+
+ if self._active_button != None and not self._lock_active_state:
+ self._active_button.base.state &= ~RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK
+ repaint = True
+
+ if repaint:
+ self.Refresh(False)
+
+
+ def GetDefaultBorder(self):
+ """ Returns the default border style for :class:`RibbonButtonBar`. """
+
+ return wx.BORDER_NONE
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/control.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/control.py
new file mode 100644
index 0000000..b46aee8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/control.py
@@ -0,0 +1,192 @@
+"""
+`RibbonControl` serves as a base class for all controls which share the ribbon
+charactertics of having a ribbon art provider, and (optionally) non-continous
+resizing.
+
+
+Description
+===========
+
+Despite what the name may imply, it is not the top-level control for creating a
+ribbon interface - that is :class:`~lib.agw.ribbon.bar.RibbonBar`. Ribbon controls often have a region which
+is "transparent", and shows the contents of the ribbon page or panel behind it.
+
+If implementing a new ribbon control, then it may be useful to realise that this
+effect is done by the art provider when painting the background of the control,
+and hence in the paint handler for the new control, you should call a draw background
+method on the art provider (:meth:`RibbonMSWArtProvider.DrawButtonBarBackground() <lib.agw.ribbon.art_msw.RibbonMSWArtProvider.DrawButtonBarBackground>` and
+:meth:`RibbonMSWArtProvider.DrawToolBarBackground() <lib.agw.ribbon.art_msw.RibbonMSWArtProvider.DrawToolBarBackground>` typically just redraw what is behind the
+rectangle being painted) if you want transparent regions.
+
+"""
+
+import wx
+
+class RibbonControl(wx.PyControl):
+ """ Base class for all the Ribbon stuff. """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0,
+ validator=wx.DefaultValidator, name="RibbonControl"):
+ """
+ Default class constructor.
+
+ :param Window `parent`: pointer to a parent window;
+ :param integer `id`: window identifier. If ``wx.ID_ANY``, will automatically create
+ an identifier;
+ :param `pos`: window position. ``wx.DefaultPosition`` indicates that wxPython
+ should generate a default position for the window;
+ :type `pos`: tuple or :class:`Point`
+ :param `size`: window size. ``wx.DefaultSize`` indicates that wxPython should
+ generate a default size for the window. If no suitable size can be found, the
+ window will be sized to 20x20 pixels so that the window is visible but obviously
+ not correctly sized;
+ :type `size`: tuple or :class:`Point`
+ :param integer `style`: the window style;
+ :param Validator `validator`: window validator;
+ :param string `name`: window name.
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name)
+ self._art = None
+
+ if isinstance(parent, RibbonControl):
+ self._art = parent.GetArtProvider()
+
+
+ def SetArtProvider(self, art):
+ """
+ Set the art provider to be used.
+
+ In many cases, setting the art provider will also set the art provider on all
+ child windows which extend :class:`RibbonControl`. In most cases, controls will not
+ take ownership of the given pointer, with the notable exception being
+ :meth:`RibbonBar.SetArtProvider() <RibbonBar.SetArtProvider>`.
+
+ :param `art`: an art provider.
+ """
+
+ self._art = art
+
+
+ def GetArtProvider(self):
+ """
+ Get the art provider to be used.
+
+ Note that until an art provider has been set in some way, this function may
+ return ``None``.
+ """
+
+ return self._art
+
+
+ def IsSizingContinuous(self):
+ """
+ Returns ``True`` if this window can take any size (greater than its minimum size),
+ ``False`` if it can only take certain sizes.
+
+ :see: :meth:`~RibbonControl.GetNextSmallerSize`, :meth:`~RibbonControl.GetNextLargerSize`
+ """
+
+ return True
+
+
+ def DoGetNextSmallerSize(self, direction, size):
+ """
+ Implementation of :meth:`~RibbonControl.GetNextSmallerSize`.
+
+ Controls which have non-continuous sizing must override this virtual function
+ rather than :meth:`~RibbonControl.GetNextSmallerSize`.
+
+ :param integer `direction`: the direction(s) in which the size should increase;
+ :param Size `size`: the size for which a larger size should be found.
+ """
+
+ # Dummy implementation for code which doesn't check for IsSizingContinuous() == true
+ minimum = self.GetMinSize()
+
+ if direction & wx.HORIZONTAL and size.x > minimum.x:
+ size.x -= 1
+ if direction & wx.VERTICAL and size.y > minimum.y:
+ size.y -= 1
+
+ return size
+
+
+ def DoGetNextLargerSize(self, direction, size):
+ """
+ Implementation of :meth:`~RibbonControl.GetNextLargerSize`.
+
+ Controls which have non-continuous sizing must override this virtual function
+ rather than :meth:`~RibbonControl.GetNextLargerSize`.
+
+ :param integer `direction`: the direction(s) in which the size should increase;
+ :param Size `size`: the size for which a larger size should be found.
+ """
+
+ # Dummy implementation for code which doesn't check for IsSizingContinuous() == true
+ if direction & wx.HORIZONTAL:
+ size.x += 1
+ if direction & wx.VERTICAL:
+ size.y += 1
+
+ return size
+
+
+ def GetNextSmallerSize(self, direction, relative_to=None):
+ """
+ If sizing is not continuous, then return a suitable size for the control which
+ is smaller than the given size.
+
+ :param integer `direction`: The direction(s) in which the size should reduce;
+ :param Size `relative_to`: The size for which a smaller size should be found.
+
+ :returns: if there is no smaller size, otherwise a suitable size which is smaller
+ in the given direction(s), and the same as in the other direction (if any).
+
+ :see: :meth:`~RibbonControl.IsSizingContinuous`, :meth:`~RibbonControl.DoGetNextSmallerSize`
+ """
+
+ if relative_to is not None:
+ return self.DoGetNextSmallerSize(direction, relative_to)
+
+ return self.DoGetNextSmallerSize(direction, self.GetSize())
+
+
+ def GetNextLargerSize(self, direction, relative_to=None):
+ """
+ If sizing is not continuous, then return a suitable size for the control which
+ is larger then the given size.
+
+ :param integer `direction`: The direction(s) in which the size should reduce;
+ :param Size `relative_to`: The size for which a smaller size should be found.
+
+ :returns: if there is no larger size, otherwise a suitable size which is larger
+ in the given direction(s), and the same as in the other direction (if any).
+
+ :see: :meth:`~RibbonControl.IsSizingContinuous`, :meth:`~RibbonControl.DoGetNextLargerSize`
+ """
+
+ if relative_to is not None:
+ return self.DoGetNextLargerSize(direction, relative_to)
+
+ return self.DoGetNextLargerSize(direction, self.GetSize())
+
+
+ def Realize(self):
+ """
+ Perform initial size and layout calculations after children have been added,
+ and/or realize children.
+ """
+
+ pass
+
+
+ def Realise(self):
+ """
+ Alias for :meth:`~RibbonControl.Realize`.
+ """
+
+ pass
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/gallery.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/gallery.py
new file mode 100644
index 0000000..8991faa
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/gallery.py
@@ -0,0 +1,960 @@
+"""
+A ribbon gallery is like a :class:`ListBox`, but for bitmaps rather than strings.
+
+
+Description
+===========
+
+It displays a collection of bitmaps arranged in a grid and allows the user to
+choose one. As there are typically more bitmaps in a gallery than can be displayed
+in the space used for a ribbon, a gallery always has scroll buttons to allow the
+user to navigate through the entire gallery.
+
+It also has an "extension" button, the behaviour of which is outside the scope of
+the gallery control itself, though it typically displays some kind of dialog related
+to the gallery.
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+=================================== ===================================
+Event Name Description
+=================================== ===================================
+``EVT_RIBBONGALLERY_SELECTED`` Triggered when the user selects an item from the gallery. Note that the ID is that of the gallery, not of the item.
+``EVT_RIBBONGALLERY_HOVER_CHANGED`` Triggered when the item being hovered over by the user changes. The item in the event will be the new item being hovered, or ``None`` if there is no longer an item being hovered. Note that the ID is that of the gallery, not of the item.
+``EVT_RIBBONGALLERY_CLICKED`` Triggered when the user clicks on an item in the gallery.
+``EVT_BUTTON`` Triggered when the "extension" button of the gallery is pressed.
+=================================== ===================================
+"""
+
+import wx
+
+from control import RibbonControl
+from art import *
+
+wxEVT_COMMAND_RIBBONGALLERY_HOVER_CHANGED = wx.NewEventType()
+wxEVT_COMMAND_RIBBONGALLERY_SELECTED = wx.NewEventType()
+wxEVT_COMMAND_RIBBONGALLERY_CLICKED = wx.NewEventType()
+
+EVT_RIBBONGALLERY_HOVER_CHANGED = wx.PyEventBinder(wxEVT_COMMAND_RIBBONGALLERY_HOVER_CHANGED, 1)
+EVT_RIBBONGALLERY_SELECTED = wx.PyEventBinder(wxEVT_COMMAND_RIBBONGALLERY_SELECTED, 1)
+EVT_RIBBONGALLERY_CLICKED = wx.PyEventBinder(wxEVT_COMMAND_RIBBONGALLERY_CLICKED, 1)
+
+
+class RibbonGalleryEvent(wx.PyCommandEvent):
+ """ Handles events related to :class:`RibbonGallery`. """
+
+ def __init__(self, command_type=None, win_id=0, gallery=None, item=None):
+ """
+ Default class constructor.
+
+ :param integer `command_type`: the event type;
+ :param integer `win_id`: the event identifier;
+ :param `gallery`: an instance of :class:`RibbonGallery`;
+ :param `item`: an instance of :class:`RibbonGalleryItem`.
+ """
+
+ wx.PyCommandEvent.__init__(self, command_type, win_id)
+ self._gallery = gallery
+ self._item = item
+
+
+ def GetGallery(self):
+ """ Returns the gallery which the event relates to. """
+
+ return self._gallery
+
+
+ def GetGalleryItem(self):
+ """ Returns the gallery item which the event relates to, or ``None`` if it does not relate to an item. """
+
+ return self._item
+
+
+ def SetGallery(self, gallery):
+ """
+ Sets the gallery relating to this event.
+
+ :param `gallery`: an instance of :class:`RibbonGallery`.
+ """
+
+ self._gallery = gallery
+
+
+ def SetGalleryItem(self, item):
+ """
+ Sets the gallery item relating to this event.
+
+ :param `item`: an instance of :class:`RibbonGalleryItem`.
+ """
+
+ self._item = item
+
+
+class RibbonGalleryItem(object):
+
+ def __init__(self):
+
+ self._id = 0
+ self._is_visible = False
+ self._client_data = None
+ self._position = wx.Rect()
+
+
+ def SetId(self, id):
+
+ self._id = id
+
+
+ def SetBitmap(self, bitmap):
+
+ self._bitmap = bitmap
+
+
+ def GetBitmap(self):
+
+ return self._bitmap
+
+
+ def SetIsVisible(self, visible):
+
+ self._is_visible = visible
+
+
+ def SetPosition(self, x, y, size):
+
+ self._position = wx.RectPS(wx.Point(x, y), size)
+
+
+ def IsVisible(self):
+
+ return self._is_visible
+
+
+ def GetPosition(self):
+
+ return self._position
+
+
+ def SetClientData(self, data):
+
+ self._client_data = data
+
+
+ def GetClientData(self):
+
+ return self._client_data
+
+
+class RibbonGallery(RibbonControl):
+ """
+ A ribbon gallery is like a :class:`ListBox`, but for bitmaps rather than strings.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, agwStyle=0,
+ name="RibbonGallery"):
+
+ """
+ Default class constructor.
+
+ :param `parent`: pointer to a parent window, typically a :class:`~lib.agw.ribbon.panel.RibbonPanel`;
+ :param `id`: window identifier. If ``wx.ID_ANY``, will automatically create an
+ identifier;
+ :param `pos`: window position. ``wx.DefaultPosition`` indicates that wxPython
+ should generate a default position for the window;
+ :param `size`: window size. ``wx.DefaultSize`` indicates that wxPython should
+ generate a default size for the window. If no suitable size can be found, the
+ window will be sized to 20x20 pixels so that the window is visible but obviously
+ not correctly sized;
+ :param `agwStyle`: the AGW-specific window style, currently unused;
+ :param `name`: the window name.
+ """
+
+ RibbonControl.__init__(self, parent, id, pos, size, style=wx.BORDER_NONE, name=name)
+
+ self.CommonInit(agwStyle)
+
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnMouseDClick)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def CommonInit(self, agwStyle):
+
+ self._selected_item = None
+ self._hovered_item = None
+ self._active_item = None
+ self._scroll_up_button_rect = wx.Rect(0, 0, 0, 0)
+ self._scroll_down_button_rect = wx.Rect(0, 0, 0, 0)
+ self._extension_button_rect = wx.Rect(0, 0, 0, 0)
+ self._mouse_active_rect = None
+ self._bitmap_size = wx.Size(64, 32)
+ self._bitmap_padded_size = self._bitmap_size
+ self._item_separation_x = 0
+ self._item_separation_y = 0
+ self._scroll_amount = 0
+ self._scroll_limit = 0
+ self._up_button_state = RIBBON_GALLERY_BUTTON_DISABLED
+ self._down_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+ self._extension_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+ self._hovered = False
+ self._items = []
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+
+ def OnMouseEnter(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`RibbonGallery`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self._hovered = True
+
+ if self._mouse_active_rect is not None and not event.LeftIsDown():
+ self._mouse_active_rect = None
+ self._active_item = None
+
+ self.Refresh(False)
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`RibbonGallery`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ refresh = False
+ pos = event.GetPosition()
+
+ result1, self._up_button_state = self.TestButtonHover(self._scroll_up_button_rect, pos, self._up_button_state)
+ result2, self._down_button_state = self.TestButtonHover(self._scroll_down_button_rect, pos, self._down_button_state)
+ result3, self._extension_button_state = self.TestButtonHover(self._extension_button_rect, pos, self._extension_button_state)
+
+ if result1 or result2 or result3:
+ refresh = True
+
+ hovered_item = active_item = None
+
+ if self._client_rect.Contains(pos):
+
+ if self._art and self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL:
+ pos.x += self._scroll_amount
+ else:
+ pos.y += self._scroll_amount
+
+ item_count = len(self._items)
+
+ for item in self._items:
+ if not item.IsVisible():
+ continue
+
+ if item.GetPosition().Contains(pos):
+ if self._mouse_active_rect == item.GetPosition():
+ active_item = item
+ hovered_item = item
+ break
+
+ if active_item != self._active_item:
+ self._active_item = active_item
+ refresh = True
+
+ if hovered_item != self._hovered_item:
+ self._hovered_item = hovered_item
+ notification = RibbonGalleryEvent(wxEVT_COMMAND_RIBBONGALLERY_HOVER_CHANGED, self.GetId())
+ notification.SetEventObject(self)
+ notification.SetGallery(self)
+ notification.SetGalleryItem(hovered_item)
+ self.GetEventHandler().ProcessEvent(notification)
+ refresh = True
+
+ if refresh:
+ self.Refresh(False)
+
+
+ def TestButtonHover(self, rect, pos, state):
+
+ if state == RIBBON_GALLERY_BUTTON_DISABLED:
+ return False, state
+
+ if rect.Contains(pos):
+ if self._mouse_active_rect == rect:
+ new_state = RIBBON_GALLERY_BUTTON_ACTIVE
+ else:
+ new_state = RIBBON_GALLERY_BUTTON_HOVERED
+ else:
+ new_state = RIBBON_GALLERY_BUTTON_NORMAL
+
+ if new_state != state:
+ return True, new_state
+ else:
+ return False, state
+
+
+ def OnMouseLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`RibbonGallery`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self._hovered = False
+ self._active_item = None
+
+ if self._up_button_state != RIBBON_GALLERY_BUTTON_DISABLED:
+ self._up_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+ if self._down_button_state != RIBBON_GALLERY_BUTTON_DISABLED:
+ self._down_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+ if self._extension_button_state != RIBBON_GALLERY_BUTTON_DISABLED:
+ self._extension_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+ if self._hovered_item != None:
+ self._hovered_item = None
+ notification = RibbonGalleryEvent(wxEVT_COMMAND_RIBBONGALLERY_HOVER_CHANGED, self.GetId())
+ notification.SetEventObject(self)
+ notification.SetGallery(self)
+ self.GetEventHandler().ProcessEvent(notification)
+
+ self.Refresh(False)
+
+
+ def OnMouseDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`RibbonGallery`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ pos = event.GetPosition()
+ self._mouse_active_rect = None
+
+ if self._client_rect.Contains(pos):
+ if self._art and self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL:
+ pos.x += self._scroll_amount
+ else:
+ pos.y += self._scroll_amount
+
+ for item in self._items:
+ if not item.IsVisible():
+ continue
+
+ rect = item.GetPosition()
+ if rect.Contains(pos):
+ self._active_item = item
+ self._mouse_active_rect = rect
+ break
+
+ elif self._scroll_up_button_rect.Contains(pos):
+ if self._up_button_state != RIBBON_GALLERY_BUTTON_DISABLED:
+ self._mouse_active_rect = wx.Rect(*self._scroll_up_button_rect)
+ self._up_button_state = RIBBON_GALLERY_BUTTON_ACTIVE
+
+ elif self._scroll_down_button_rect.Contains(pos):
+ if self._down_button_state != RIBBON_GALLERY_BUTTON_DISABLED:
+ self._mouse_active_rect = wx.Rect(*self._scroll_down_button_rect)
+ self._down_button_state = RIBBON_GALLERY_BUTTON_ACTIVE
+
+ elif self._extension_button_rect.Contains(pos):
+ if self._extension_button_state != RIBBON_GALLERY_BUTTON_DISABLED:
+ self._mouse_active_rect = wx.Rect(*self._extension_button_rect)
+ self._extension_button_state = RIBBON_GALLERY_BUTTON_ACTIVE
+
+ if self._mouse_active_rect != None:
+ self.Refresh(False)
+
+
+ def OnMouseUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`RibbonGallery`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._mouse_active_rect != None:
+ pos = event.GetPosition()
+
+ if self._active_item:
+ if self._art and self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL:
+ pos.x += self._scroll_amount
+ else:
+ pos.y += self._scroll_amount
+
+ if self._mouse_active_rect.Contains(pos):
+ if self._mouse_active_rect == self._scroll_up_button_rect:
+ self._up_button_state = RIBBON_GALLERY_BUTTON_HOVERED
+ self.ScrollLines(-1)
+
+ elif self._mouse_active_rect == self._scroll_down_button_rect:
+ self._down_button_state = RIBBON_GALLERY_BUTTON_HOVERED
+ self.ScrollLines(1)
+
+ elif self._mouse_active_rect == self._extension_button_rect:
+ self._extension_button_state = RIBBON_GALLERY_BUTTON_HOVERED
+ notification = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
+ notification.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(notification)
+
+ elif self._active_item != None:
+ if self._selected_item != self._active_item:
+ self._selected_item = self._active_item
+ notification = RibbonGalleryEvent(wxEVT_COMMAND_RIBBONGALLERY_SELECTED, self.GetId())
+ notification.SetEventObject(self)
+ notification.SetGallery(self)
+ notification.SetGalleryItem(self._selected_item)
+ self.GetEventHandler().ProcessEvent(notification)
+
+ notification = RibbonGalleryEvent(wxEVT_COMMAND_RIBBONGALLERY_CLICKED, self.GetId())
+ notification.SetEventObject(self)
+ notification.SetGallery(self)
+ notification.SetGalleryItem(self._selected_item)
+ self.GetEventHandler().ProcessEvent(notification)
+
+ self._mouse_active_rect = None
+ self._active_item = None
+ self.Refresh(False)
+
+
+ def OnMouseDClick(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DCLICK`` event for :class:`RibbonGallery`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # The 2nd click of a double-click should be handled as a click in the
+ # same way as the 1st click of the double-click. This is useful for
+ # scrolling through the gallery.
+ self.OnMouseDown(event)
+ self.OnMouseUp(event)
+
+
+ def SetItemClientData(self, item, data):
+ """
+ Set the client data associated with a gallery item.
+
+ :param `item`: an instance of :class:`RibbonGalleryItem`;
+ :param `data`: any Python object.
+
+ """
+
+ item.SetClientData(data)
+
+
+ def GetItemClientData(self, item):
+ """
+ Get the client data associated with a gallery item.
+
+ :param `item`: an instance of :class:`RibbonGalleryItem`.
+ """
+
+ return item.GetClientData()
+
+
+ def ScrollLines(self, lines):
+ """
+ Scroll the gallery contents by some amount.
+
+ :param `lines`: Positive values scroll toward the end of the gallery, while
+ negative values scroll toward the start.
+
+ :returns: ``True`` if the gallery scrolled at least one pixel in the given
+ direction, ``False`` if it did not scroll.
+
+ :note: Reimplemented from :class:`Window`.
+ """
+
+ if self._scroll_limit == 0 or self._art == None:
+ return False
+
+ line_size = self._bitmap_padded_size.GetHeight()
+ if self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL:
+ line_size = self._bitmap_padded_size.GetWidth()
+
+ if lines < 0:
+ if self._scroll_amount > 0:
+ self._scroll_amount += lines*line_size
+
+ if self._scroll_amount <= 0:
+ self._scroll_amount = 0
+ self._up_button_state = RIBBON_GALLERY_BUTTON_DISABLED
+
+ elif self._up_button_state == RIBBON_GALLERY_BUTTON_DISABLED:
+ self._up_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+
+ if self._down_button_state == RIBBON_GALLERY_BUTTON_DISABLED:
+ self._down_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+
+ return True
+
+
+ elif lines > 0:
+ if self._scroll_amount < self._scroll_limit:
+ self._scroll_amount += lines * line_size
+
+ if self._scroll_amount >= self._scroll_limit:
+ self._scroll_amount = self._scroll_limit
+ self._down_button_state = RIBBON_GALLERY_BUTTON_DISABLED
+
+ elif self._down_button_state == RIBBON_GALLERY_BUTTON_DISABLED:
+ self._down_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+
+ if self._up_button_state == RIBBON_GALLERY_BUTTON_DISABLED:
+ self._up_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+
+ return True
+
+ return False
+
+
+ def EnsureVisible(self, item):
+ """
+ Scroll the gallery to ensure that the given item is visible.
+
+ :param `item`: an instance of :class:`RibbonGalleryItem`.
+ """
+
+ if item is None or not item.IsVisible() or self.IsEmpty():
+ return
+
+ y = item.GetPosition().GetTop()
+ base_y = self._items[0].GetPosition().GetTop()
+ delta = y - base_y - self._scroll_amount
+ self.ScrollLines(delta/self._bitmap_padded_size.GetHeight())
+
+
+ def IsHovered(self):
+ """
+ Query is the mouse is currently hovered over the gallery.
+
+ :returns: ``True`` if the cursor is within the bounds of the gallery (not
+ just hovering over an item), ``False`` otherwise.
+ """
+
+ return self._hovered
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`RibbonGallery`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+ """
+
+ # All painting done in main paint handler to minimise flicker
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`RibbonGallery`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+
+ if self._art == None:
+ return
+
+ self._art.DrawGalleryBackground(dc, self, wx.Rect(0, 0, *self.GetSize()))
+
+ padding_top = self._art.GetMetric(RIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE)
+ padding_left = self._art.GetMetric(RIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE)
+
+ dc.SetClippingRect(self._client_rect)
+
+ offset_vertical = True
+
+ if self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL:
+ offset_vertical = False
+
+ for item in self._items:
+ if not item.IsVisible():
+ continue
+
+ pos = item.GetPosition()
+ offset_pos = wx.Rect(*pos)
+
+ if offset_vertical:
+ offset_pos.SetTop(offset_pos.GetTop() - self._scroll_amount)
+ else:
+ offset_pos.SetLeft(offset_pos.GetLeft() - self._scroll_amount)
+
+ self._art.DrawGalleryItemBackground(dc, self, offset_pos, item)
+ dc.DrawBitmap(item.GetBitmap(), offset_pos.GetLeft() + padding_left, offset_pos.GetTop() + padding_top)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`RibbonGallery`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Layout()
+
+
+ def Append(self, bitmap, id, clientData=None):
+ """
+ Add an item to the gallery (with complex client data).
+
+ :param `bitmap`: the bitmap to display for the item. Note that all items must
+ have equally sized bitmaps;
+ :param `id`: id number to associate with the item. Not currently used for
+ anything important;
+ :param `clientData`: an object which contains data to associate with the item.
+ The item takes ownership of this pointer, and will delete it when the item
+ client data is changed to something else, or when the item is destroyed.
+ """
+
+ if not bitmap.IsOk():
+ raise Exception("exception")
+
+ if not self._items:
+ self._bitmap_size = bitmap.GetSize()
+ self.CalculateMinSize()
+ else:
+ if bitmap.GetSize() != self._bitmap_size:
+ raise Exception("exception")
+
+ item = RibbonGalleryItem()
+ item.SetId(id)
+ item.SetBitmap(bitmap)
+ self._items.append(item)
+
+ item.SetClientData(clientData)
+
+ return item
+
+
+ def Clear(self):
+ """
+ Remove all items from the gallery.
+ """
+
+ self._items = []
+
+
+ def IsSizingContinuous(self):
+ """
+ Returns ``True`` if this window can take any size (greater than its minimum size),
+ ``False`` if it can only take certain sizes.
+
+ :see: :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`,
+ :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`
+ """
+
+ return False
+
+
+ def CalculateMinSize(self):
+
+ if self._art == None or not self._bitmap_size.IsFullySpecified():
+ self.SetMinSize(wx.Size(20, 20))
+ else:
+ self._bitmap_padded_size = wx.Size(*self._bitmap_size)
+ self._bitmap_padded_size.IncBy(self._art.GetMetric(RIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE) +
+ self._art.GetMetric(RIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE),
+ self._art.GetMetric(RIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE) +
+ self._art.GetMetric(RIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE))
+
+ dc = wx.MemoryDC()
+ self.SetMinSize(self._art.GetGallerySize(dc, self, wx.Size(*self._bitmap_padded_size)))
+
+ # The best size is displaying several items
+ self._best_size = wx.Size(*self._bitmap_padded_size)
+ self._best_size.x *= 3
+ self._best_size = self._art.GetGallerySize(dc, self, wx.Size(*self._best_size))
+
+
+ def Realize(self):
+ """
+ Perform initial size and layout calculations after children have been added,
+ and/or realize children.
+ """
+
+ self.CalculateMinSize()
+ return self.Layout()
+
+
+ def Layout(self):
+
+ if self._art == None:
+ return False
+
+ dc = wx.MemoryDC()
+ origin = wx.Point()
+
+ client_size, origin, self._scroll_up_button_rect, self._scroll_down_button_rect, self._extension_button_rect = \
+ self._art.GetGalleryClientSize(dc, self, wx.Size(*self.GetSize()))
+
+ self._client_rect = wx.RectPS(origin, client_size)
+
+ x_cursor = y_cursor = 0
+ art_flags = self._art.GetFlags()
+
+ for indx, item in enumerate(self._items):
+
+ item.SetIsVisible(True)
+
+ if art_flags & RIBBON_BAR_FLOW_VERTICAL:
+ if y_cursor + self._bitmap_padded_size.y > client_size.GetHeight():
+ if y_cursor == 0:
+ break
+
+ y_cursor = 0
+ x_cursor += self._bitmap_padded_size.x
+
+ item.SetPosition(origin.x + x_cursor, origin.y + y_cursor, self._bitmap_padded_size)
+ y_cursor += self._bitmap_padded_size.y
+
+ else:
+ if x_cursor + self._bitmap_padded_size.x > client_size.GetWidth():
+ if x_cursor == 0:
+ break
+
+ x_cursor = 0
+ y_cursor += self._bitmap_padded_size.y
+
+ item.SetPosition(origin.x + x_cursor, origin.y + y_cursor, self._bitmap_padded_size)
+ x_cursor += self._bitmap_padded_size.x
+
+ for item in self._items[indx:]:
+ item.SetIsVisible(False)
+
+ if art_flags & RIBBON_BAR_FLOW_VERTICAL:
+ self._scroll_limit = x_cursor
+ else:
+ self._scroll_limit = y_cursor
+
+ if self._scroll_amount >= self._scroll_limit:
+ self._scroll_amount = self._scroll_limit
+ self._down_button_state = RIBBON_GALLERY_BUTTON_DISABLED
+
+ elif self._down_button_state == RIBBON_GALLERY_BUTTON_DISABLED:
+ self._down_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+
+ if self._scroll_amount <= 0:
+ self._scroll_amount = 0
+ self._up_button_state = RIBBON_GALLERY_BUTTON_DISABLED
+
+ elif self._up_button_state == RIBBON_GALLERY_BUTTON_DISABLED:
+ self._up_button_state = RIBBON_GALLERY_BUTTON_NORMAL
+
+ return True
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :return: An instance of :class:`Size`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._best_size
+
+
+ def DoGetNextSmallerSize(self, direction, relative_to):
+ """
+ Implementation of :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`.
+
+ Controls which have non-continuous sizing must override this virtual function
+ rather than :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`.
+ """
+
+ if self._art == None:
+ return relative_to
+
+ dc = wx.MemoryDC()
+ client, d1, d2, d3, d4 = self._art.GetGalleryClientSize(dc, self, wx.Size(*relative_to))
+
+ if direction == wx.HORIZONTAL:
+ client.DecBy(1, 0)
+ elif direction == wx.VERTICAL:
+ client.DecBy(0, 1)
+ elif direction == wx.BOTH:
+ client.DecBy(1, 1)
+
+ if client.GetWidth() < 0 or client.GetHeight() < 0:
+ return relative_to
+
+ client.x = (client.x / self._bitmap_padded_size.x) * self._bitmap_padded_size.x
+ client.y = (client.y / self._bitmap_padded_size.y) * self._bitmap_padded_size.y
+
+ size = self._art.GetGallerySize(dc, self, wx.Size(*client))
+ minimum = self.GetMinSize()
+
+ if size.GetWidth() < minimum.GetWidth() or size.GetHeight() < minimum.GetHeight():
+ return relative_to
+
+ if direction == wx.HORIZONTAL:
+ size.SetHeight(relative_to.GetHeight())
+ elif direction == wx.VERTICAL:
+ size.SetWidth(relative_to.GetWidth())
+
+ return size
+
+
+ def DoGetNextLargerSize(self, direction, relative_to):
+ """
+ Implementation of :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`.
+
+ Controls which have non-continuous sizing must override this virtual function
+ rather than :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`.
+ """
+
+ if self._art == None:
+ return relative_to
+
+ dc = wx.MemoryDC()
+ client, d1, d2, d3, d4 = self._art.GetGalleryClientSize(dc, self, wx.Size(*relative_to))
+
+ # No need to grow if the given size can already display every item
+ nitems = (client.GetWidth()/self._bitmap_padded_size.x)*(client.GetHeight()/self._bitmap_padded_size.y)
+
+ if nitems >= len(self._items):
+ return relative_to
+
+ if direction == wx.HORIZONTAL:
+ client.IncBy(self._bitmap_padded_size.x, 0)
+ elif direction == wx.VERTICAL:
+ client.IncBy(0, self._bitmap_padded_size.y)
+ elif direction == wx.BOTH:
+ client.IncBy(self._bitmap_padded_size)
+
+ client.x = (client.x / self._bitmap_padded_size.x) * self._bitmap_padded_size.x
+ client.y = (client.y / self._bitmap_padded_size.y) * self._bitmap_padded_size.y
+
+ size = self._art.GetGallerySize(dc, self, wx.Size(*client))
+ minimum = self.GetMinSize()
+
+ if size.GetWidth() < minimum.GetWidth() or size.GetHeight() < minimum.GetHeight():
+ return relative_to
+
+ if direction == wx.HORIZONTAL:
+ size.SetHeight(relative_to.GetHeight())
+ if direction == wx.VERTICAL:
+ size.SetWidth(relative_to.GetWidth())
+
+ return size
+
+
+ def IsEmpty(self):
+ """
+ Query if the gallery has no items in it.
+ """
+
+ return len(self._items) == 0
+
+
+ def GetCount(self):
+ """
+ Get the number of items in the gallery.
+ """
+
+ return len(self._items)
+
+
+ def GetItem(self, n):
+ """
+ Get an item by index.
+
+ :param `n`: the zero-based item in the gallery, which is an instance of :class:`RibbonGalleryItem`.
+ """
+
+ if n >= self.GetCount():
+ return None
+
+ return self._items[n]
+
+
+ def SetSelection(self, item):
+ """
+ Set the selection to the given item, or removes the selection if `item` == ``None``.
+
+ Note that this not cause any events to be emitted.
+
+ :param `item`: an instance of :class:`RibbonGalleryItem`, can also be ``None`` to remove the selection.
+
+ """
+
+ if item != self._selected_item:
+ self._selected_item = item
+ self.Refresh(False)
+
+
+ def GetSelection(self):
+ """
+ Get the currently selected item, or ``None`` if there is none.
+
+ The selected item is set by :meth:`~RibbonGallery.SetSelection`, or by the user clicking on an item.
+ """
+
+ return self._selected_item
+
+
+ def GetHoveredItem(self):
+ """
+ Get the currently hovered item, or ``None`` if there is none.
+
+ The hovered item is the item underneath the mouse cursor.
+ """
+
+ return self._hovered_item
+
+
+ def GetActiveItem(self):
+ """
+ Get the currently active item, or ``None`` if there is none.
+
+ The active item is the item being pressed by the user, and will thus become the
+ selected item if the user releases the mouse button.
+ """
+
+ return self._active_item
+
+
+ def GetUpButtonState(self):
+ """
+ Get the state of the scroll up button.
+ """
+
+ return self._up_button_state
+
+
+ def GetDownButtonState(self):
+ """
+ Get the state of the scroll down button.
+ """
+
+ return self._down_button_state
+
+
+ def GetExtensionButtonState(self):
+ """
+ Get the state of the "extension" button.
+ """
+
+ return self._extension_button_state
+
+
+ def GetDefaultBorder(self):
+ """ Returns the default border style for :class:`RibbonGallery`. """
+
+ return wx.BORDER_NONE
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/page.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/page.py
new file mode 100644
index 0000000..a1fb5e8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/page.py
@@ -0,0 +1,932 @@
+"""
+Description
+===========
+
+Container for related ribbon panels, and a tab within a ribbon bar.
+
+
+See Also
+========
+
+:class:`~lib.agw.ribbon.bar.RibbonBar`, :class:`~lib.agw.ribbon.panel.RibbonPanel`
+
+"""
+
+import wx
+
+from control import RibbonControl
+from panel import RibbonPanel
+
+from art import *
+
+# As scroll buttons need to be rendered on top of a page's child windows, the
+# buttons themselves have to be proper child windows (rather than just painted
+# onto the page). In order to get proper clipping of a page's children (with
+# regard to the scroll button), the scroll buttons are created as children of
+# the ribbon bar rather than children of the page. This could not have been
+# achieved by creating buttons as children of the page and then doing some Z-order
+# manipulation, as self causes problems on win32 due to ribbon panels having the
+# transparent flag set.
+
+def GetSizeInOrientation(size, orientation):
+
+ if orientation == wx.HORIZONTAL:
+ return size.GetWidth()
+ elif orientation == wx.VERTICAL:
+ return size.GetHeight()
+ elif orientation == wx.BOTH:
+ return size.GetWidth() * size.GetHeight()
+
+ return 0
+
+
+class RibbonPageScrollButton(RibbonControl):
+
+ def __init__(self, sibling, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
+
+ RibbonControl.__init__(self, sibling.GetParent(), id, pos, size, style=wx.BORDER_NONE)
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+ self._sibling = sibling
+ self._flags = (style & RIBBON_SCROLL_BTN_DIRECTION_MASK) | RIBBON_SCROLL_BTN_FOR_PAGE
+
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def OnEraseBackground(self, event):
+
+ # Do nothing - all painting done in main paint handler
+ pass
+
+
+ def OnPaint(self, event):
+
+ dc = wx.AutoBufferedPaintDC(self)
+
+ if self._art:
+ self._art.DrawScrollButton(dc, self, wx.Rect(0, 0, *self.GetSize()), self._flags)
+
+
+ def OnMouseEnter(self, event):
+
+ self._flags |= RIBBON_SCROLL_BTN_HOVERED
+ self.Refresh(False)
+
+
+ def OnMouseLeave(self, event):
+
+ self._flags &= ~RIBBON_SCROLL_BTN_HOVERED
+ self._flags &= ~RIBBON_SCROLL_BTN_ACTIVE
+ self.Refresh(False)
+
+
+ def OnMouseDown(self, event):
+
+ self._flags |= RIBBON_SCROLL_BTN_ACTIVE
+ self.Refresh(False)
+
+
+ def OnMouseUp(self, event):
+
+ if self._flags & RIBBON_SCROLL_BTN_ACTIVE:
+
+ self._flags &= ~RIBBON_SCROLL_BTN_ACTIVE
+ self.Refresh(False)
+ result = self._flags & RIBBON_SCROLL_BTN_DIRECTION_MASK
+
+ if result in [RIBBON_SCROLL_BTN_DOWN, RIBBON_SCROLL_BTN_RIGHT]:
+ self._sibling.ScrollLines(1)
+ elif result in [RIBBON_SCROLL_BTN_UP, RIBBON_SCROLL_BTN_LEFT]:
+ self._sibling.ScrollLines(-1)
+
+
+class RibbonPage(RibbonControl):
+
+ def __init__(self, parent, id=wx.ID_ANY, label="", icon=wx.NullBitmap, style=0):
+ """
+ Default class constructor.
+
+ :param `parent`: pointer to a parent window, an instance of :class:`~lib.agw.ribbon.bar.RibbonBar`;
+ :param `id`: window identifier. If ``wx.ID_ANY``, will automatically create an identifier;
+ :param `label`: label to be used in the :class:`~lib.agw.ribbon.bar.RibbonBar`'s tab list for this page (if the
+ ribbon bar is set to display labels);
+ :param `icon`: the icon used for the page in the ribbon bar tab area (if the ribbon bar is
+ set to display icons);
+ :param `style`: window style. Currently unused, should be zero.
+ """
+
+ RibbonControl.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, wx.BORDER_NONE)
+
+ self.CommonInit(label, icon)
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def CommonInit(self, label, icon):
+
+ self.SetName(label)
+ self.SetLabel(label)
+
+ self._old_size = wx.Size(0, 0)
+ self._icon = icon
+ self._scroll_left_btn = None
+ self._scroll_right_btn = None
+ self._size_calc_array = None
+ self._size_calc_array_size = 0
+ self._scroll_amount = 0
+ self._scroll_buttons_visible = False
+ self._collapse_stack = []
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ self.GetParent().AddPage(self)
+
+
+ def SetArtProvider(self, art):
+ """
+ Set the art provider to be used.
+
+ Normally called automatically by :class:`~lib.agw.ribbon.bar.RibbonBar` when the page is created, or the
+ art provider changed on the bar. The new art provider will be propagated to the
+ children of the page.
+
+ :param `art`: an art provider.
+
+ :note: Reimplemented from :class:`~lib.agw.ribbon.control.RibbonControl`.
+ """
+
+ self._art = art
+ for child in self.GetChildren():
+ if isinstance(child, RibbonControl):
+ child.SetArtProvider(art)
+
+
+ def AdjustRectToIncludeScrollButtons(self, rect):
+ """
+ Expand a rectangle of the page to include external scroll buttons (if any).
+
+ When no scroll buttons are shown, has no effect.
+
+ :param `rect`: The rectangle to adjust. The width and height will not be
+ reduced, and the x and y will not be increased.
+ """
+
+ if self._scroll_buttons_visible:
+ if self.GetMajorAxis() == wx.VERTICAL:
+ if self._scroll_left_btn:
+ rect.SetY(rect.GetY() - self._scroll_left_btn.GetSize().GetHeight())
+ rect.SetHeight(rect.GetHeight() + self._scroll_left_btn.GetSize().GetHeight())
+
+ if self._scroll_right_btn:
+ rect.SetHeight(rect.GetHeight() + self._scroll_right_btn.GetSize().GetHeight())
+
+ else:
+ if self._scroll_left_btn:
+ rect.SetX(rect.GetX() - self._scroll_left_btn.GetSize().GetWidth())
+ rect.SetWidth(rect.GetWidth() + self._scroll_left_btn.GetSize().GetWidth())
+
+ if self._scroll_right_btn:
+ rect.SetWidth(rect.GetWidth() + self._scroll_right_btn.GetSize().GetWidth())
+
+ return rect
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`RibbonPage`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+ """
+
+ # All painting done in main paint handler to minimise flicker
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`RibbonPage`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ # No foreground painting done by the page itself, but a paint DC
+ # must be created anyway.
+ dc = wx.AutoBufferedPaintDC(self)
+ rect = wx.Rect(0, 0, *self.GetSize())
+ rect = self.AdjustRectToIncludeScrollButtons(rect)
+ self._art.DrawPageBackground(dc, self, rect)
+
+
+ def GetMajorAxis(self):
+ """
+ Get the direction in which ribbon panels are stacked within the page.
+
+ This is controlled by the style of the containing :class:`~lib.agw.ribbon.bar.RibbonBar`, meaning that all
+ pages within a bar will have the same major axis. As well as being the direction
+ in which panels are stacked, it is also the axis in which scrolling will occur
+ (when required).
+
+ :returns: ``wx.HORIZONTAL`` or ``wx.VERTICAL`` (never ``wx.BOTH``).
+ """
+
+ if self._art and (self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL):
+ return wx.VERTICAL
+ else:
+ return wx.HORIZONTAL
+
+
+ def ScrollLines(self, lines):
+ """
+ Scroll the page by some amount up / down / left / right.
+
+ When the page's children are too big to fit in the onscreen area given to the
+ page, scroll buttons will appear, and the page can be programatically scrolled.
+ Positive values of will scroll right or down, while negative values will scroll
+ up or left (depending on the direction in which panels are stacked). A line is
+ equivalent to a constant number of pixels.
+
+ :param integer `lines`: number of lines to scroll the page.
+
+ :returns: ``True`` if the page scrolled at least one pixel in the given direction,
+ ``False`` if it did not scroll.
+
+ :note: Reimplemented from :class:`Window`.
+
+ :see: :meth:`~RibbonPage.GetMajorAxis`, :meth:`~RibbonPage.ScrollPixels`
+ """
+
+ return self.ScrollPixels(lines * 8)
+
+
+ def ScrollPixels(self, pixels):
+ """
+ Scroll the page by a set number of pixels up / down / left / right.
+
+ When the page's children are too big to fit in the onscreen area given to the
+ page, scroll buttons will appear, and the page can be programatically scrolled.
+ Positive values of will scroll right or down, while negative values will scroll
+ up or left (depending on the direction in which panels are stacked).
+
+ :param integer `pixels`: number of pixels to scroll the page.
+
+ :returns: ``True`` if the page scrolled at least one pixel in the given direction,
+ ``False`` if it did not scroll.
+
+ :see: :meth:`~RibbonPage.GetMajorAxis`, :meth:`~RibbonPage.ScrollLines`
+ """
+
+ if pixels < 0:
+ if self._scroll_amount == 0:
+ return False
+
+ if self._scroll_amount < -pixels:
+ pixels = -self._scroll_amount
+
+ elif pixels > 0:
+ if self._scroll_amount == self._scroll_amount_limit:
+ return False
+
+ if self._scroll_amount + pixels > self._scroll_amount_limit:
+ pixels = self._scroll_amount_limit - self._scroll_amount
+
+ else:
+ return False
+
+ self._scroll_amount += pixels
+
+ for child in self.GetChildren():
+ x, y = child.GetPosition()
+ if self.GetMajorAxis() == wx.HORIZONTAL:
+ x -= pixels
+ else:
+ y -= pixels
+
+ child.SetPosition(wx.Point(x, y))
+
+ self.ShowScrollButtons()
+ self.Refresh()
+ return True
+
+
+ def SetSizeWithScrollButtonAdjustment(self, x, y, width, height):
+ """
+ Set the size of the page and the external scroll buttons (if any).
+
+ When a page is too small to display all of its children, scroll buttons will
+ appear (and if the page is sized up enough, they will disappear again). Slightly
+ counter-intuively, these buttons are created as siblings of the page rather than
+ children of the page (to achieve correct cropping and paint ordering of the
+ children and the buttons).
+
+ When there are no scroll buttons, this function behaves the same as `SetSize`,
+ however when there are scroll buttons, it positions them at the edges of the
+ given area, and then calls `SetSize` with the remaining area. This is provided
+ as a separate function to `SetSize` rather than within the implementation
+ of `SetSize`, as iteracting algorithms may not expect `SetSize` to also
+ set the size of siblings.
+
+ :param `x`: the page `x` position, in pixels;
+ :param `y`: the page `y` position, in pixels;
+ :param `width`: the page width, in pixels;
+ :param `height`: the page height, in pixels.
+ """
+
+ if self._scroll_buttons_visible:
+ if self.GetMajorAxis() == wx.HORIZONTAL:
+ if self._scroll_left_btn:
+ w = self._scroll_left_btn.GetSize().GetWidth()
+ self._scroll_left_btn.SetPosition(wx.Point(x, y))
+ x += w
+ width -= w
+
+ if self._scroll_right_btn:
+ w = self._scroll_right_btn.GetSize().GetWidth()
+ width -= w
+ self._scroll_right_btn.SetPosition(wx.Point(x + width, y))
+
+ else:
+ if self._scroll_left_btn:
+ h = self._scroll_left_btn.GetSize().GetHeight()
+ self._scroll_left_btn.SetPosition(wx.Point(x, y))
+ y += h
+ height -= h
+
+ if self._scroll_right_btn:
+ h = self._scroll_right_btn.GetSize().GetHeight()
+ height -= h
+ self._scroll_right_btn.SetPosition(wx.Point(x, y + height))
+
+ if width < 0:
+ width = 0
+ if height < 0:
+ height = 0
+
+ self.SetDimensions(x, y, width, height)
+
+
+ def DoSetSize(self, x, y, width, height, sizeFlags=wx.SIZE_AUTO):
+ """
+ Sets the size of the window in pixels.
+
+ :param integer `x`: required `x` position in pixels, or ``wx.DefaultCoord`` to
+ indicate that the existing value should be used;
+ :param integer `y`: required `y` position in pixels, or ``wx.DefaultCoord`` to
+ indicate that the existing value should be used;
+ :param integer `width`: required width in pixels, or ``wx.DefaultCoord`` to
+ indicate that the existing value should be used;
+ :param integer `height`: required height in pixels, or ``wx.DefaultCoord`` to
+ indicate that the existing value should be used;
+ :param integer `sizeFlags`: indicates the interpretation of other parameters.
+ It is a bit list of the following:
+
+ * ``wx.SIZE_AUTO_WIDTH``: a ``wx.DefaultCoord`` width value is taken to indicate a
+ wxPython-supplied default width.
+ * ``wx.SIZE_AUTO_HEIGHT``: a ``wx.DefaultCoord`` height value is taken to indicate a
+ wxPython-supplied default height.
+ * ``wx.SIZE_AUTO``: ``wx.DefaultCoord`` size values are taken to indicate a wxPython-supplied
+ default size.
+ * ``wx.SIZE_USE_EXISTING``: existing dimensions should be used if ``wx.DefaultCoord`` values are supplied.
+ * ``wx.SIZE_ALLOW_MINUS_ONE``: allow negative dimensions (i.e. value of ``wx.DefaultCoord``)
+ to be interpreted as real dimensions, not default values.
+ * ``wx.SIZE_FORCE``: normally, if the position and the size of the window are already
+ the same as the parameters of this function, nothing is done. but with this flag a window
+ resize may be forced even in this case (supported in wx 2.6.2 and later and only implemented
+ for MSW and ignored elsewhere currently).
+ """
+
+ # When a resize triggers the scroll buttons to become visible, the page is resized.
+ # This resize from within a resize event can cause (MSW) wxWidgets some confusion,
+ # and report the 1st size to the 2nd size event. Hence the most recent size is
+ # remembered internally and used in Layout() where appropiate.
+
+ if self.GetMajorAxis() == wx.HORIZONTAL:
+ self._size_in_major_axis_for_children = width
+
+ if self._scroll_buttons_visible:
+ if self._scroll_left_btn:
+ self._size_in_major_axis_for_children += self._scroll_left_btn.GetSize().GetWidth()
+ if self._scroll_right_btn:
+ self._size_in_major_axis_for_children += self._scroll_right_btn.GetSize().GetWidth()
+
+ else:
+ self._size_in_major_axis_for_children = height
+
+ if self._scroll_buttons_visible:
+ if self._scroll_left_btn:
+ self._size_in_major_axis_for_children += self._scroll_left_btn.GetSize().GetHeight()
+ if self._scroll_right_btn:
+ self._size_in_major_axis_for_children += self._scroll_right_btn.GetSize().GetHeight()
+
+ RibbonControl.DoSetSize(self, x, y, width, height, sizeFlags)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`RibbonPage`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ new_size = event.GetSize()
+
+ if self._art:
+ temp_dc = wx.MemoryDC()
+ invalid_rect = self._art.GetPageBackgroundRedrawArea(temp_dc, self, self._old_size, new_size)
+ self.Refresh(True, invalid_rect)
+
+ self._old_size = wx.Size(*new_size)
+ x, y = new_size
+
+ if x > 0 and y > 0:
+ self.Layout()
+ else:
+ # Simplify other calculations by pretending new size is zero in both
+ # X and Y
+ new_size = wx.Size(0, 0)
+ # When size == 0, no point in doing any layout
+
+ event.Skip()
+
+
+ def RemoveChild(self, child):
+ """ Remove all references to the child from the collapse stack. """
+
+ try:
+ self._collapse_stack.remove(child)
+ except ValueError:
+ pass
+
+ # ... and then proceed as normal
+ RibbonControl.RemoveChild(self, child)
+
+
+ def Realize(self):
+ """
+ Perform a full re-layout of all panels on the page.
+
+ Should be called after panels are added to the page, or the sizing behaviour of
+ a panel on the page changes (i.e. due to children being added to it). Usually
+ called automatically when :meth:`RibbonBar.Realize() <lib.agw.ribbon.bar.RibbonBar.Realize>` is called. Will invoke
+ :meth:`RibbonPanel.Realize() <lib.agw.ribbon.panel.RibbonPanel.Realize>` for all child panels.
+
+ :note: Reimplemented from :class:`~lib.agw.ribbon.control.RibbonControl`.
+ """
+
+ status = True
+ self._collapse_stack = []
+
+ for child in self.GetChildren():
+ if not isinstance(child, RibbonControl):
+ continue
+
+ if not child.Realize():
+ status = False
+
+ child.SetSize(wx.Size(*child.GetMinSize()))
+
+ x, y = self.GetSize()
+ if x > 0 and y > 0:
+ status = self.Layout() and status
+
+ return status
+
+
+ def Layout(self):
+
+ if len(self.GetChildren()) == 0:
+ return True
+
+ origin_ = wx.Point(self._art.GetMetric(RIBBON_ART_PAGE_BORDER_LEFT_SIZE), self._art.GetMetric(RIBBON_ART_PAGE_BORDER_TOP_SIZE))
+ major_axis = self.GetMajorAxis()
+
+ if self._scroll_buttons_visible:
+ if major_axis == wx.HORIZONTAL:
+ origin_.x -= self._scroll_amount
+ if self._scroll_left_btn:
+ origin_.x -= self._scroll_left_btn.GetSize().GetWidth()
+ else:
+ origin_.y -= self._scroll_amount
+ if self._scroll_left_btn:
+ origin_.y -= self._scroll_left_btn.GetSize().GetHeight()
+
+ origin = wx.Point(*origin_)
+
+ if major_axis == wx.HORIZONTAL:
+ gap = self._art.GetMetric(RIBBON_ART_PANEL_X_SEPARATION_SIZE)
+ minor_axis_size = self.GetSize().GetHeight() - origin.y - self._art.GetMetric(RIBBON_ART_PAGE_BORDER_BOTTOM_SIZE)
+ else:
+ gap = self._art.GetMetric(RIBBON_ART_PANEL_Y_SEPARATION_SIZE)
+ minor_axis_size = self.GetSize().GetWidth() - origin.x - self._art.GetMetric(RIBBON_ART_PAGE_BORDER_RIGHT_SIZE)
+
+ if minor_axis_size < 0:
+ minor_axis_size = 0
+
+ for iteration in xrange(1, 3):
+
+ for child in self.GetChildren():
+ w, h = child.GetSize()
+ if major_axis == wx.HORIZONTAL:
+ child.SetDimensions(origin.x, origin.y, w, minor_axis_size)
+ origin.x += w + gap
+ else:
+ child.SetDimensions(origin.x, origin.y, minor_axis_size, h)
+ origin.y += h + gap
+
+ if iteration == 1:
+ if major_axis == wx.HORIZONTAL:
+ available_space = self._size_in_major_axis_for_children - self._art.GetMetric(RIBBON_ART_PAGE_BORDER_RIGHT_SIZE) - origin.x + gap
+ else:
+ available_space = self._size_in_major_axis_for_children - self._art.GetMetric(RIBBON_ART_PAGE_BORDER_BOTTOM_SIZE) - origin.y + gap
+
+ if self._scroll_buttons_visible:
+ available_space -= self._scroll_amount
+ if self._scroll_right_btn != None:
+ available_space += GetSizeInOrientation(self._scroll_right_btn.GetSize(), major_axis)
+
+ if available_space > 0:
+ if self._scroll_buttons_visible:
+ self.HideScrollButtons()
+ break
+
+ result = self.ExpandPanels(major_axis, available_space)
+ if not result:
+ break
+
+ elif available_space < 0:
+ if self._scroll_buttons_visible:
+ # Scroll buttons already visible - not going to be able to downsize any more
+ self._scroll_amount_limit = -available_space
+ if self._scroll_amount > self._scroll_amount_limit:
+ self.ScrollPixels(self._scroll_amount_limit - self._scroll_amount)
+ else:
+ result = self.CollapsePanels(major_axis, -available_space)
+ if not result:
+ self._scroll_amount = 0
+ self._scroll_amount_limit = -available_space
+ self.ShowScrollButtons()
+ break
+
+ else:
+ break
+
+ origin = wx.Point(*origin_) # Reset the origin
+
+ return True
+
+
+ def Show(self, show=True):
+
+ if self._scroll_left_btn:
+ self._scroll_left_btn.Show(show)
+ if self._scroll_right_btn:
+ self._scroll_right_btn.Show(show)
+
+ return RibbonControl.Show(self, show)
+
+
+ def GetIcon(self):
+ """
+ Get the icon used for the page in the ribbon bar tab area (only displayed if the
+ ribbon bar is actually showing icons).
+ """
+
+ return self._icon
+
+
+ def HideScrollButtons(self):
+
+ self._scroll_amount = 0
+ self._scroll_amount_limit = 0
+ self.ShowScrollButtons()
+
+
+ def ShowScrollButtons(self):
+
+ show_left = True
+ show_right = True
+ reposition = False
+
+ if self._scroll_amount == 0:
+ show_left = False
+
+ if self._scroll_amount >= self._scroll_amount_limit:
+ show_right = False
+ self._scroll_amount = self._scroll_amount_limit
+
+ self._scroll_buttons_visible = show_left or show_right
+
+ if show_left:
+ if self._scroll_left_btn == None:
+
+ temp_dc = wx.MemoryDC()
+
+ if self.GetMajorAxis() == wx.HORIZONTAL:
+ direction = RIBBON_SCROLL_BTN_LEFT
+ size = self._art.GetScrollButtonMinimumSize(temp_dc, self.GetParent(), direction)
+ size.SetHeight(self.GetSize().GetHeight())
+ else:
+ direction = RIBBON_SCROLL_BTN_UP
+ size = self._art.GetScrollButtonMinimumSize(temp_dc, self.GetParent(), direction)
+ size.SetWidth(self.GetSize().GetWidth())
+
+ self._scroll_left_btn = RibbonPageScrollButton(self, -1, self.GetPosition(), size, direction)
+ if not self.IsShown():
+ self._scroll_left_btn.Hide()
+
+ reposition = True
+
+ else:
+ if self._scroll_left_btn != None:
+ self._scroll_left_btn.Destroy()
+ self._scroll_left_btn = None
+ reposition = True
+
+ if show_right:
+ if self._scroll_right_btn == None:
+
+ temp_dc = wx.MemoryDC()
+
+ if self.GetMajorAxis() == wx.HORIZONTAL:
+ direction = RIBBON_SCROLL_BTN_RIGHT
+ size = self._art.GetScrollButtonMinimumSize(temp_dc, self.GetParent(), direction)
+ size.SetHeight(self.GetSize().GetHeight())
+ else:
+ direction = RIBBON_SCROLL_BTN_DOWN
+ size = self._art.GetScrollButtonMinimumSize(temp_dc, self.GetParent(), direction)
+ size.SetWidth(self.GetSize().GetWidth())
+
+ initial_pos = self.GetPosition() + wx.Point(*self.GetSize()) - wx.Point(*size)
+ self._scroll_right_btn = RibbonPageScrollButton(self, -1, initial_pos, size, direction)
+ if not self.IsShown():
+ self._scroll_right_btn.Hide()
+
+ reposition = True
+
+ else:
+ if self._scroll_right_btn != None:
+ self._scroll_right_btn.Destroy()
+ self._scroll_right_btn = None
+ reposition = True
+
+ if reposition:
+ self.GetParent().RepositionPage(self)
+
+
+ def ExpandPanels(self, direction, maximum_amount):
+
+ expanded_something = False
+
+ while maximum_amount > 0:
+ smallest_size = 10000
+ smallest_panel = None
+
+ for panel in self.GetChildren():
+
+ if not isinstance(panel, RibbonPanel):
+ continue
+
+ if panel.IsSizingContinuous():
+ size = GetSizeInOrientation(panel.GetSize(), direction)
+ if size < smallest_size:
+ smallest_size = size
+ smallest_panel = panel
+ else:
+ current = panel.GetSize()
+ size = GetSizeInOrientation(current, direction)
+ if size < smallest_size:
+ larger = panel.GetNextLargerSize(direction)
+ if larger != current and GetSizeInOrientation(larger, direction) > size:
+ smallest_size = size
+ smallest_panel = panel
+
+ if smallest_panel != None:
+ if smallest_panel.IsSizingContinuous():
+ size = wx.Size(*smallest_panel.GetSize())
+ amount = maximum_amount
+
+ if amount > 32:
+ # For "large" growth, grow self panel a bit, and then re-allocate
+ # the remainder (which may come to self panel again anyway)
+ amount = 32
+
+ if direction & wx.HORIZONTAL:
+ size.x += amount
+
+ if direction & wx.VERTICAL:
+ size.y += amount
+
+ smallest_panel.SetSize(size)
+ maximum_amount -= amount
+ self._collapse_stack.append(smallest_panel)
+ expanded_something = True
+
+ else:
+ current = smallest_panel.GetSize()
+ larger = smallest_panel.GetNextLargerSize(direction)
+ delta = larger - current
+ if GetSizeInOrientation(delta, direction) <= maximum_amount:
+ smallest_panel.SetSize(wx.Size(*larger))
+ maximum_amount -= GetSizeInOrientation(delta, direction)
+ self._collapse_stack.append(smallest_panel)
+ expanded_something = True
+ else:
+ break
+
+ else:
+ break
+
+ if expanded_something:
+ self.Refresh()
+ return True
+ else:
+ return False
+
+
+ def CollapsePanels(self, direction, minimum_amount):
+
+ collapsed_something = False
+
+ while minimum_amount > 0:
+ largest_size = 0
+ largest_panel = None
+
+ if self._collapse_stack:
+ # For a more consistent panel layout, try to collapse panels which
+ # were recently expanded.
+ largest_panel = self._collapse_stack[-1]
+ self._collapse_stack.pop(len(self._collapse_stack)-1)
+ else:
+ for panel in self.GetChildren():
+ if not isinstance(panel, RibbonPanel):
+ continue
+
+ if panel.IsSizingContinuous():
+ size = GetSizeInOrientation(panel.GetSize(), direction)
+ if size > largest_size:
+ largest_size = size
+ largest_panel = panel
+ else:
+ current = panel.GetSize()
+ size = GetSizeInOrientation(current, direction)
+ if size > largest_size:
+ smaller = panel.GetNextSmallerSize(direction)
+ if smaller != current and GetSizeInOrientation(smaller, direction) < size:
+ largest_size = size
+ largest_panel = panel
+
+ if largest_panel != None:
+ if largest_panel.IsSizingContinuous():
+ size = largest_panel.GetSize()
+ amount = minimum_amount
+
+ if amount > 32:
+ # For "large" contraction, reduce self panel a bit, and
+ # then re-allocate the remainder of the quota (which may
+ # come to this panel again anyway)
+ amount = 32
+
+ if direction & wx.HORIZONTAL:
+ size.x -= amount
+
+ if direction & wx.VERTICAL:
+ size.y -= amount
+
+ largest_panel.SetSize(size)
+ minimum_amount -= amount
+ collapsed_something = True
+
+ else:
+ current = largest_panel.GetSize()
+ smaller = largest_panel.GetNextSmallerSize(direction)
+ delta = current - smaller
+ largest_panel.SetSize(smaller)
+ minimum_amount -= GetSizeInOrientation(delta, direction)
+ collapsed_something = True
+
+ else:
+ break
+
+ if collapsed_something:
+ self.Refresh()
+ return True
+ else:
+ return False
+
+
+ def DismissExpandedPanel(self):
+ """
+ Dismiss the current externally expanded panel, if there is one.
+
+ When a ribbon panel automatically minimises, it can be externally expanded into
+ a floating window. When the user clicks a button in such a panel, the panel
+ should generally re-minimise. Event handlers for buttons on ribbon panels should
+ call this method to achieve this behaviour.
+
+ :returns: ``True`` if a panel was minimised, ``False`` otherwise.
+ """
+
+ for panel in self.GetChildren():
+ if not isinstance(panel, RibbonPanel):
+ continue
+
+ if panel.GetExpandedPanel() != None:
+ return panel.HideExpanded()
+
+ return False
+
+
+ def GetMinSize(self):
+ """
+ Returns the minimum size of the window, an indication to the sizer layout mechanism
+ that this is the minimum required size.
+
+ This method normally just returns the value set by `SetMinSize`, but it can be overridden
+ to do the calculation on demand.
+ """
+
+ minSize = wx.Size(-1, -1)
+
+ for child in self.GetChildren():
+ child_min = child.GetMinSize()
+ minSize.x = max(minSize.x, child_min.x)
+ minSize.y = max(minSize.y, child_min.y)
+
+ if self.GetMajorAxis() == wx.HORIZONTAL:
+ minSize.x = -1
+ if minSize.y != -1:
+ minSize.y += self._art.GetMetric(RIBBON_ART_PAGE_BORDER_TOP_SIZE) + self._art.GetMetric(RIBBON_ART_PAGE_BORDER_BOTTOM_SIZE)
+
+ else:
+ if minSize.x != -1:
+ minSize.x += self._art.GetMetric(RIBBON_ART_PAGE_BORDER_LEFT_SIZE) + self._art.GetMetric(RIBBON_ART_PAGE_BORDER_RIGHT_SIZE)
+
+ minSize.y = -1
+
+ return minSize
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :return: An instance of :class:`Size`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ best = wx.Size(0, 0)
+ count = 0
+
+ if self.GetMajorAxis() == wx.HORIZONTAL:
+ best.y = -1
+
+ for child in self.GetChildren():
+ child_best = child.GetBestSize()
+ if child_best.x != -1:
+ best.IncBy(child_best.x, 0)
+
+ best.y = max(best.y, child_best.y)
+ count += 1
+
+ if count > 1:
+ best.IncBy((count - 1) * self._art.GetMetric(RIBBON_ART_PANEL_X_SEPARATION_SIZE), 0)
+
+ else:
+ best.x = -1
+
+ for child in self.GetChildren():
+ child_best = child.GetBestSize()
+ best.x = max(best.x, child_best.x)
+
+ if child_best.y != -1:
+ best.IncBy(0, child_best.y)
+
+ count += 1
+
+ if count > 1:
+ best.IncBy(0, (count - 1) * self._art.GetMetric(RIBBON_ART_PANEL_Y_SEPARATION_SIZE))
+
+ if best.x != -1:
+ best.x += self._art.GetMetric(RIBBON_ART_PAGE_BORDER_LEFT_SIZE) + self._art.GetMetric(RIBBON_ART_PAGE_BORDER_RIGHT_SIZE)
+
+ if best.y != -1:
+ best.y += self._art.GetMetric(RIBBON_ART_PAGE_BORDER_TOP_SIZE) + self._art.GetMetric(RIBBON_ART_PAGE_BORDER_BOTTOM_SIZE)
+
+ return best
+
+
+ def GetDefaultBorder(self):
+ """ Returns the default border style for :class:`RibbonPage`. """
+
+ return wx.BORDER_NONE
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/panel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/panel.py
new file mode 100644
index 0000000..61b5afb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/panel.py
@@ -0,0 +1,1157 @@
+"""
+Serves as a container for a group of (ribbon) controls.
+
+
+Description
+===========
+
+A :class:`RibbonPanel` will typically have panels for children, with the controls for that
+page placed on the panels. A panel adds a border and label to a group of controls,
+and can be minimised (either automatically to conserve space, or manually by the user).
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+================================= =========== =================================
+Window Styles Hex Value Description
+================================= =========== =================================
+``RIBBON_PANEL_DEFAULT_STYLE`` 0x0 Defined as no other flags set.
+``RIBBON_PANEL_NO_AUTO_MINIMISE`` 0x1 Prevents the panel from automatically minimising to conserve screen space.
+``RIBBON_PANEL_EXT_BUTTON`` 0x8 Causes an extension button to be shown in the panel's chrome (if the bar in which it is contained has ``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS`` set). The behaviour of this button is application controlled, but typically will show an extended drop-down menu relating to the panel.
+``RIBBON_PANEL_MINIMISE_BUTTON`` 0x10 Causes a (de)minimise button to be shown in the panel's chrome (if the bar in which it is contained has the ``RIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS`` style set). This flag is typically combined with ``RIBBON_PANEL_NO_AUTO_MINIMISE`` to make a panel which the user always has manual control over when it minimises.
+``RIBBON_PANEL_STRETCH`` 0x20 Allows a single panel to stretch to fill the parent page.
+``RIBBON_PANEL_FLEXIBLE`` 0x40 Allows toolbars to wrap, taking up the optimum amount of space when used in a vertical palette.
+================================= =========== =================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+======================================= ===================================
+Event Name Description
+======================================= ===================================
+``EVT_RIBBONPANEL_EXTBUTTON_ACTIVATED`` Triggered when the user activate the panel extension button.
+======================================= ===================================
+
+See Also
+========
+
+:class:`~lib.agw.ribbon.page.RibbonPage`
+
+"""
+
+import wx
+
+from control import RibbonControl
+
+from art import *
+
+
+wxEVT_COMMAND_RIBBONPANEL_EXTBUTTON_ACTIVATED = wx.NewEventType()
+EVT_RIBBONPANEL_EXTBUTTON_ACTIVATED = wx.PyEventBinder(wxEVT_COMMAND_RIBBONPANEL_EXTBUTTON_ACTIVATED, 1)
+
+
+def IsAncestorOf(ancestor, window):
+
+ while window is not None:
+ parent = window.GetParent()
+ if parent == ancestor:
+ return True
+ else:
+ window = parent
+
+ return False
+
+
+class RibbonPanelEvent(wx.PyCommandEvent):
+ """ Handles events related to :class:`RibbonPanel`. """
+
+ def __init__(self, command_type=None, win_id=0, panel=None):
+ """
+ Default class constructor.
+
+ :param integer `command_type`: the event type;
+ :param integer `win_id`: the event identifier;
+ :param `panel`: an instance of :class:`RibbonPanel`;
+ """
+
+ wx.PyCommandEvent.__init__(self, command_type, win_id)
+
+ self._panel = panel
+
+
+ def GetPanel(self):
+ """ Returns the panel which the event relates to. """
+
+ return self._panel
+
+
+ def SetPanel(self, panel):
+ """
+ Sets the panel relating to this event.
+
+ :param `panel`: an instance of :class:`RibbonPanel`.
+ """
+
+ self._panel = panel
+
+
+class RibbonPanel(RibbonControl):
+ """ This is the main implementation of :class:`RibbonPanel`. """
+
+ def __init__(self, parent, id=wx.ID_ANY, label="", minimised_icon=wx.NullBitmap,
+ pos=wx.DefaultPosition, size=wx.DefaultSize, agwStyle=RIBBON_PANEL_DEFAULT_STYLE,
+ name="RibbonPanel"):
+ """
+ Default class constructor.
+
+ :param `parent`: pointer to a parent window, typically a :class:`~lib.agw.ribbon.page.RibbonPage`, though
+ it can be any window;
+ :param `id`: window identifier. If ``wx.ID_ANY``, will automatically create
+ an identifier;
+ :param `label`: label of the new button;
+ :param `minimised_icon`: the bitmap to be used in place of the panel children
+ when it is minimised;
+ :param `pos`: window position. ``wx.DefaultPosition`` indicates that wxPython
+ should generate a default position for the window;
+ :param `size`: window size. ``wx.DefaultSize`` indicates that wxPython should
+ generate a default size for the window. If no suitable size can be found, the
+ window will be sized to 20x20 pixels so that the window is visible but obviously
+ not correctly sized;
+ :param `agwStyle`: the AGW-specific window style. This can be one of the following
+ bits:
+
+ ================================= =========== =================================
+ Window Styles Hex Value Description
+ ================================= =========== =================================
+ ``RIBBON_PANEL_DEFAULT_STYLE`` 0x0 Defined as no other flags set.
+ ``RIBBON_PANEL_NO_AUTO_MINIMISE`` 0x1 Prevents the panel from automatically minimising to conserve screen space.
+ ``RIBBON_PANEL_EXT_BUTTON`` 0x8 Causes an extension button to be shown in the panel's chrome (if the bar in which it is contained has ``RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS`` set). The behaviour of this button is application controlled, but typically will show an extended drop-down menu relating to the panel.
+ ``RIBBON_PANEL_MINIMISE_BUTTON`` 0x10 Causes a (de)minimise button to be shown in the panel's chrome (if the bar in which it is contained has the ``RIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS`` style set). This flag is typically combined with ``RIBBON_PANEL_NO_AUTO_MINIMISE`` to make a panel which the user always has manual control over when it minimises.
+ ``RIBBON_PANEL_STRETCH`` 0x20 Allows a single panel to stretch to fill the parent page.
+ ``RIBBON_PANEL_FLEXIBLE`` 0x40 Allows toolbars to wrap, taking up the optimum amount of space when used in a vertical palette.
+ ================================= =========== =================================
+
+ :param `name`: the window name.
+ """
+
+ RibbonControl.__init__(self, parent, id, pos, size, wx.BORDER_NONE, name=name)
+ self.CommonInit(label, minimised_icon, agwStyle)
+
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseClick)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+
+
+ def __del__(self):
+
+ if self._expanded_panel:
+ self._expanded_panel._expanded_dummy = None
+ self._expanded_panel.GetParent().Destroy()
+
+
+ def IsExtButtonHovered(self):
+
+ return self._ext_button_hovered
+
+
+ def SetArtProvider(self, art):
+ """
+ Set the art provider to be used.
+
+ Normally called automatically by :class:`~lib.agw.ribbon.page.RibbonPage` when the panel is created, or the
+ art provider changed on the page. The new art provider will be propagated to the
+ children of the panel.
+
+ Reimplemented from :class:`~lib.agw.ribbon.control.RibbonControl`.
+
+ :param `art`: an art provider.
+
+ """
+
+ self._art = art
+ for child in self.GetChildren():
+ if isinstance(child, RibbonControl):
+ child.SetArtProvider(art)
+
+ if self._expanded_panel:
+ self._expanded_panel.SetArtProvider(art)
+
+
+ def CommonInit(self, label, icon, agwStyle):
+
+ self.SetName(label)
+ self.SetLabel(label)
+
+ self._minimised_size = wx.Size(-1, -1) # Unknown / none
+ self._smallest_unminimised_size = wx.Size(-1, -1) # Unknown / none
+ self._preferred_expand_direction = wx.SOUTH
+ self._expanded_dummy = None
+ self._expanded_panel = None
+ self._flags = agwStyle
+ self._minimised_icon = icon
+ self._minimised = False
+ self._hovered = False
+ self._ext_button_hovered = False
+ self._ext_button_rect = wx.Rect()
+
+ if self._art == None:
+ parent = self.GetParent()
+ if isinstance(parent, RibbonControl):
+ self._art = parent.GetArtProvider()
+
+ self.SetAutoLayout(True)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+ self.SetMinSize(wx.Size(20, 20))
+
+
+ def IsMinimised(self, at_size=None):
+ """
+ Query if the panel would be minimised at a given size.
+
+ :param `at_size`: an instance of :class:`Size`, giving the size at which the
+ panel should be tested for minimisation.
+ """
+
+ if at_size is None:
+ return self.IsMinimised1()
+
+ return self.IsMinimised2(wx.Size(*at_size))
+
+
+ def IsMinimised1(self):
+ """ Query if the panel is currently minimised. """
+
+ return self._minimised
+
+
+ def IsHovered(self):
+ """
+ Query is the mouse is currently hovered over the panel.
+
+ :returns: ``True`` if the cursor is within the bounds of the panel (i.e.
+ hovered over the panel or one of its children), ``False`` otherwise.
+ """
+
+ return self._hovered
+
+
+ def OnMouseEnter(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`RibbonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.TestPositionForHover(event.GetPosition())
+
+
+ def OnMouseEnterChild(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for children of :class:`RibbonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ pos = event.GetPosition()
+ child = event.GetEventObject()
+
+ if child:
+ pos += child.GetPosition()
+ self.TestPositionForHover(pos)
+
+ event.Skip()
+
+
+ def OnMouseLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`RibbonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.TestPositionForHover(event.GetPosition())
+
+
+ def OnMouseLeaveChild(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for children of :class:`RibbonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ pos = event.GetPosition()
+ child = event.GetEventObject()
+
+ if child:
+ pos += child.GetPosition()
+ self.TestPositionForHover(pos)
+
+ event.Skip()
+
+
+ def TestPositionForHover(self, pos):
+
+ hovered = ext_button_hovered = False
+
+ if pos.x >= 0 and pos.y >= 0:
+ size = self.GetSize()
+ if pos.x < size.GetWidth() and pos.y < size.GetHeight():
+ hovered = True
+
+ if hovered:
+ if self.HasExtButton():
+ ext_button_hovered = self._ext_button_rect.Contains(pos)
+
+ if hovered != self._hovered or ext_button_hovered != self._ext_button_hovered:
+ self._hovered = hovered
+ self._ext_button_hovered = ext_button_hovered
+ self.Refresh(False)
+
+
+ def HasExtButton(self):
+
+ bar = self.GetGrandParent()
+ return (self._flags & RIBBON_PANEL_EXT_BUTTON) and (bar.GetAGWWindowStyleFlag() & RIBBON_BAR_SHOW_PANEL_EXT_BUTTONS)
+
+
+ def AddChild(self, child):
+
+ RibbonControl.AddChild(self, child)
+
+ # Window enter / leave events count for only the window in question, not
+ # for children of the window. The panel wants to be in the hovered state
+ # whenever the mouse cursor is within its boundary, so the events need to
+ # be attached to children too.
+ child.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterChild)
+ child.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeaveChild)
+
+
+ def RemoveChild(self, child):
+
+ child.Bind(wx.EVT_ENTER_WINDOW, None)
+ child.Bind(wx.EVT_LEAVE_WINDOW, None)
+
+ RibbonControl.RemoveChild(self, child)
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`RibbonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.TestPositionForHover(event.GetPosition())
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`RibbonPanel`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ if self.GetAutoLayout():
+ self.Layout()
+
+ event.Skip()
+
+
+ def DoSetSize(self, x, y, width, height, sizeFlags=wx.SIZE_AUTO):
+ """
+ Sets the size of the window in pixels.
+
+ :param integer `x`: required `x` position in pixels, or ``wx.DefaultCoord`` to
+ indicate that the existing value should be used;
+ :param integer `y`: required `y` position in pixels, or ``wx.DefaultCoord`` to
+ indicate that the existing value should be used;
+ :param integer `width`: required width in pixels, or ``wx.DefaultCoord`` to
+ indicate that the existing value should be used;
+ :param integer `height`: required height in pixels, or ``wx.DefaultCoord`` to
+ indicate that the existing value should be used;
+ :param integer `sizeFlags`: indicates the interpretation of other parameters.
+ It is a bit list of the following:
+
+ * ``wx.SIZE_AUTO_WIDTH``: a ``wx.DefaultCoord`` width value is taken to indicate a
+ wxPython-supplied default width.
+ * ``wx.SIZE_AUTO_HEIGHT``: a ``wx.DefaultCoord`` height value is taken to indicate a
+ wxPython-supplied default height.
+ * ``wx.SIZE_AUTO``: ``wx.DefaultCoord`` size values are taken to indicate a wxPython-supplied
+ default size.
+ * ``wx.SIZE_USE_EXISTING``: existing dimensions should be used if ``wx.DefaultCoord`` values are supplied.
+ * ``wx.SIZE_ALLOW_MINUS_ONE``: allow negative dimensions (i.e. value of ``wx.DefaultCoord``)
+ to be interpreted as real dimensions, not default values.
+ * ``wx.SIZE_FORCE``: normally, if the position and the size of the window are already
+ the same as the parameters of this function, nothing is done. but with this flag a window
+ resize may be forced even in this case (supported in wx 2.6.2 and later and only implemented
+ for MSW and ignored elsewhere currently).
+ """
+
+ # At least on MSW, changing the size of a window will cause GetSize() to
+ # report the new size, but a size event may not be handled immediately.
+ # If self minimised check was performed in the OnSize handler, then
+ # GetSize() could return a size much larger than the minimised size while
+ # IsMinimised() returns True. This would then affect layout, as the panel
+ # will refuse to grow any larger while in limbo between minimised and non.
+
+ minimised = (self._flags & RIBBON_PANEL_NO_AUTO_MINIMISE) == 0 and self.IsMinimised(wx.Size(width, height))
+
+ if minimised != self._minimised:
+ self._minimised = minimised
+
+ for child in self.GetChildren():
+ child.Show(not minimised)
+
+ self.Refresh()
+
+ RibbonControl.DoSetSize(self, x, y, width, height, sizeFlags)
+
+
+ def IsMinimised2(self, at_size):
+ """
+ Query if the panel would be minimised at a given size.
+
+ :param `at_size`: an instance of :class:`Size`, giving the size at which the
+ panel should be tested for minimisation.
+ """
+
+ if self.GetSizer():
+ # we have no information on size change direction
+ # so check both
+ size = self.GetMinNotMinimisedSize()
+ if size.x > at_size.x or size.y > at_size.y:
+ return True
+
+ return False
+
+ if not self._minimised_size.IsFullySpecified():
+ return False
+
+ return (at_size.x <= self._minimised_size.x and \
+ at_size.y <= self._minimised_size.y) or \
+ at_size.x < self._smallest_unminimised_size.x or \
+ at_size.y < self._smallest_unminimised_size.y
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`RibbonPanel`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+ """
+
+ # All painting done in main paint handler to minimise flicker
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`RibbonPanel`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+
+ if self._art != None:
+ if self.IsMinimised():
+ self._art.DrawMinimisedPanel(dc, self, wx.Rect(0, 0, *self.GetSize()), self._minimised_icon_resized)
+ else:
+ self._art.DrawPanelBackground(dc, self, wx.Rect(0, 0, *self.GetSize()))
+
+
+ def IsSizingContinuous(self):
+ """
+ Returns ``True`` if this window can take any size (greater than its minimum size),
+ ``False`` if it can only take certain sizes.
+
+ :see: :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`,
+ :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`
+ """
+
+ # A panel never sizes continuously, even if all of its children can,
+ # as it would appear out of place along side non-continuous panels.
+
+ # JS 2012-03-09: introducing wxRIBBON_PANEL_STRETCH to allow
+ # the panel to fill its parent page. For example we might have
+ # a list of styles in one of the pages, which should stretch to
+ # fill available space.
+ return self._flags & RIBBON_PANEL_STRETCH
+
+
+ def GetBestSizeForParentSize(self, parentSize):
+ """ Finds the best width and height given the parent's width and height. """
+
+ if len(self.GetChildren()) == 1:
+ win = self.GetChildren()[0]
+
+ if isinstance(win, RibbonControl):
+ temp_dc = wx.ClientDC(self)
+ childSize = win.GetBestSizeForParentSize(parentSize)
+ clientParentSize = self._art.GetPanelClientSize(temp_dc, self, wx.Size(*parentSize), None)
+ overallSize = self._art.GetPanelSize(temp_dc, self, wx.Size(*clientParentSize), None)
+ return overallSize
+
+ return self.GetSize()
+
+
+ def DoGetNextSmallerSize(self, direction, relative_to):
+ """
+ Implementation of :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`.
+
+ Controls which have non-continuous sizing must override this virtual function
+ rather than :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`.
+ """
+
+ if self._expanded_panel != None:
+ # Next size depends upon children, who are currently in the
+ # expanded panel
+ return self._expanded_panel.DoGetNextSmallerSize(direction, relative_to)
+
+ if self._art is not None:
+
+ dc = wx.ClientDC(self)
+ child_relative, dummy = self._art.GetPanelClientSize(dc, self, wx.Size(*relative_to), None)
+ smaller = wx.Size(-1, -1)
+ minimise = False
+
+ if self.GetSizer():
+
+ # Get smallest non minimised size
+ smaller = self.GetMinSize()
+
+ # and adjust to child_relative for parent page
+ if self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL:
+ minimise = child_relative.y <= smaller.y
+ if smaller.x < child_relative.x:
+ smaller.x = child_relative.x
+ else:
+ minimise = child_relative.x <= smaller.x
+ if smaller.y < child_relative.y:
+ smaller.y = child_relative.y
+
+ elif len(self.GetChildren()) == 1:
+
+ # Simple (and common) case of single ribbon child or Sizer
+ ribbon_child = self.GetChildren()[0]
+ if isinstance(ribbon_child, RibbonControl):
+ smaller = ribbon_child.GetNextSmallerSize(direction, child_relative)
+ minimise = smaller == child_relative
+
+ if minimise:
+ if self.CanAutoMinimise():
+ minimised = wx.Size(*self._minimised_size)
+
+ if direction == wx.HORIZONTAL:
+ minimised.SetHeight(relative_to.GetHeight())
+ elif direction == wx.VERTICAL:
+ minimised.SetWidth(relative_to.GetWidth())
+
+ return minimised
+
+ else:
+ return relative_to
+
+ elif smaller.IsFullySpecified(): # Use fallback if !(sizer/child = 1)
+ return self._art.GetPanelSize(dc, self, wx.Size(*smaller), None)
+
+ # Fallback: Decrease by 20% (or minimum size, whichever larger)
+ current = wx.Size(*relative_to)
+ minimum = wx.Size(*self.GetMinSize())
+
+ if direction & wx.HORIZONTAL:
+ current.x = (current.x * 4) / 5
+ if current.x < minimum.x:
+ current.x = minimum.x
+
+ if direction & wx.VERTICAL:
+ current.y = (current.y * 4) / 5
+ if current.y < minimum.y:
+ current.y = minimum.y
+
+ return current
+
+
+ def DoGetNextLargerSize(self, direction, relative_to):
+ """
+ Implementation of :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`.
+
+ Controls which have non-continuous sizing must override this virtual function
+ rather than :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`.
+ """
+
+ if self._expanded_panel != None:
+ # Next size depends upon children, who are currently in the
+ # expanded panel
+ return self._expanded_panel.DoGetNextLargerSize(direction, relative_to)
+
+ if self.IsMinimised(relative_to):
+ current = wx.Size(*relative_to)
+ min_size = wx.Size(*self.GetMinNotMinimisedSize())
+
+ if direction == wx.HORIZONTAL:
+ if min_size.x > current.x and min_size.y == current.y:
+ return min_size
+
+ elif direction == wx.VERTICAL:
+ if min_size.x == current.x and min_size.y > current.y:
+ return min_size
+
+ elif direction == wx.BOTH:
+ if min_size.x > current.x and min_size.y > current.y:
+ return min_size
+
+ if self._art is not None:
+
+ dc = wx.ClientDC(self)
+ child_relative, dummy = self._art.GetPanelClientSize(dc, self, wx.Size(*relative_to), None)
+ larger = wx.Size(-1, -1)
+
+ if self.GetSizer():
+
+ # We could just let the sizer expand in flow direction but see comment
+ # in IsSizingContinuous()
+ larger = self.GetPanelSizerBestSize()
+
+ # and adjust for page in non flow direction
+ if self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL:
+ if larger.x != child_relative.x:
+ larger.x = child_relative.x
+
+ elif larger.y != child_relative.y:
+ larger.y = child_relative.y
+
+ elif len(self.GetChildren()) == 1:
+
+ # Simple (and common) case of single ribbon child
+ ribbon_child = self.GetChildren()[0]
+ if isinstance(ribbon_child, RibbonControl):
+ larger = ribbon_child.GetNextLargerSize(direction, child_relative)
+
+ if larger.IsFullySpecified(): # Use fallback if !(sizer/child = 1)
+ if larger == child_relative:
+ return relative_to
+ else:
+ return self._art.GetPanelSize(dc, self, wx.Size(*larger), None)
+
+
+ # Fallback: Increase by 25% (equal to a prior or subsequent 20% decrease)
+ # Note that due to rounding errors, this increase may not exactly equal a
+ # matching decrease - an ideal solution would not have these errors, but
+ # avoiding them is non-trivial unless an increase is by 100% rather than
+ # a fractional amount. This would then be non-ideal as the resizes happen
+ # at very large intervals.
+ current = wx.Size(*relative_to)
+
+ if direction & wx.HORIZONTAL:
+ current.x = (current.x * 5 + 3) / 4
+
+ if direction & wx.VERTICAL:
+ current.y = (current.y * 5 + 3) / 4
+
+ return current
+
+
+
+ def CanAutoMinimise(self):
+ """ Query if the panel can automatically minimise itself at small sizes. """
+
+ return (self._flags & RIBBON_PANEL_NO_AUTO_MINIMISE) == 0 \
+ and self._minimised_size.IsFullySpecified()
+
+
+ def GetMinSize(self):
+ """
+ Returns the minimum size of the window, an indication to the sizer layout mechanism
+ that this is the minimum required size.
+
+ This method normally just returns the value set by `SetMinSize`, but it can be
+ overridden to do the calculation on demand.
+ """
+
+ if self._expanded_panel != None:
+ # Minimum size depends upon children, who are currently in the
+ # expanded panel
+ return self._expanded_panel.GetMinSize()
+
+ if self.CanAutoMinimise():
+ return wx.Size(*self._minimised_size)
+ else:
+ return self.GetMinNotMinimisedSize()
+
+
+ def GetMinNotMinimisedSize(self):
+
+ # Ask sizer if present
+ if self.GetSizer():
+ dc = wx.ClientDC(self)
+ return self._art.GetPanelSize(dc, self, wx.Size(*self.GetPanelSizerMinSize()), None)
+
+ # Common case of no sizer and single child taking up the entire panel
+ elif len(self.GetChildren()) == 1:
+ child = self.GetChildren()[0]
+ dc = wx.ClientDC(self)
+ return self._art.GetPanelSize(dc, self, wx.Size(*child.GetMinSize()), None)
+
+ return wx.Size(*RibbonControl.GetMinSize(self))
+
+
+ def GetPanelSizerMinSize(self):
+
+ # Called from Realize() to set self._smallest_unminimised_size and from other
+ # functions to get the minimum size.
+ # The panel will be invisible when minimised and sizer calcs will be 0
+ # Uses self._smallest_unminimised_size in preference to self.GetSizer().CalcMin()
+ # to eliminate flicker.
+
+ # Check if is visible and not previously calculated
+ if self.IsShown() and not self._smallest_unminimised_size.IsFullySpecified():
+ return self.GetSizer().CalcMin()
+
+ # else use previously calculated self._smallest_unminimised_size
+ dc = wx.ClientDC(self)
+ return self._art.GetPanelClientSize(dc, self, wx.Size(*self._smallest_unminimised_size), None)[0]
+
+
+ def GetPanelSizerBestSize(self):
+
+ size = self.GetPanelSizerMinSize()
+ # TODO allow panel to increase its size beyond minimum size
+ # by steps similarly to ribbon control panels (preferred for aesthetics)
+ # or continuously.
+ return size
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :return: An instance of :class:`Size`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ # Ask sizer if present
+ if self.GetSizer():
+ dc = wx.ClientDC(self)
+ return self._art.GetPanelSize(dc, self, wx.Size(*self.GetPanelSizerBestSize()), None)
+
+ # Common case of no sizer and single child taking up the entire panel
+ elif len(self.GetChildren()) == 1:
+ child = self.GetChildren()[0]
+ dc = wx.ClientDC(self)
+ return self._art.GetPanelSize(dc, self, wx.Size(*child.GetBestSize()), None)
+
+ return wx.Size(*RibbonControl.DoGetBestSize(self))
+
+
+ def Realize(self):
+ """
+ Realize all children of the panel.
+
+ :note: Reimplemented from :class:`~lib.agw.ribbon.control.RibbonControl`.
+ """
+
+ status = True
+ children = self.GetChildren()
+
+ for child in children:
+ if not isinstance(child, RibbonControl):
+ continue
+
+ if not child.Realize():
+ status = False
+
+ minimum_children_size = wx.Size(0, 0)
+
+ # Ask sizer if there is one present
+ if self.GetSizer():
+ minimum_children_size = wx.Size(*self.GetPanelSizerMinSize())
+ elif len(children) == 1:
+ minimum_children_size = wx.Size(*children[0].GetMinSize())
+
+ if self._art != None:
+ temp_dc = wx.ClientDC(self)
+ self._smallest_unminimised_size = self._art.GetPanelSize(temp_dc, self, wx.Size(*minimum_children_size), None)
+
+ panel_min_size = self.GetMinNotMinimisedSize()
+ self._minimised_size, bitmap_size, self._preferred_expand_direction = self._art.GetMinimisedPanelMinimumSize(temp_dc, self, 1, 1)
+
+ if self._minimised_icon.IsOk() and self._minimised_icon.GetSize() != bitmap_size:
+ img = self._minimised_icon.ConvertToImage()
+ img.Rescale(bitmap_size.GetWidth(), bitmap_size.GetHeight(), wx.IMAGE_QUALITY_HIGH)
+ self._minimised_icon_resized = wx.BitmapFromImage(img)
+ else:
+ self._minimised_icon_resized = self._minimised_icon
+
+ if self._minimised_size.x > panel_min_size.x and self._minimised_size.y > panel_min_size.y:
+ # No point in having a minimised size which is larger than the
+ # minimum size which the children can go to.
+ self._minimised_size = wx.Size(-1, -1)
+ else:
+ if self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL:
+ self._minimised_size.x = panel_min_size.x
+ else:
+ self._minimised_size.y = panel_min_size.y
+
+ else:
+ self._minimised_size = wx.Size(-1, -1)
+
+ return self.Layout() and status
+
+
+ def Layout(self):
+
+ if self.IsMinimised():
+ # Children are all invisible when minimised
+ return True
+
+ dc = wx.ClientDC(self)
+ size, position = self._art.GetPanelClientSize(dc, self, wx.Size(*self.GetSize()), wx.Point())
+
+ children = self.GetChildren()
+
+ if self.GetSizer():
+ self.GetSizer().SetDimension(position.x, position.y, size.x, size.y) # SetSize and Layout()
+ elif len(children) == 1:
+ # Common case of no sizer and single child taking up the entire panel
+ children[0].SetDimensions(position.x, position.y, size.GetWidth(), size.GetHeight())
+
+ if self.HasExtButton():
+ self._ext_button_rect = self._art.GetPanelExtButtonArea(dc, self, self.GetSize())
+
+ return True
+
+
+ def OnMouseClick(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`RibbonPanel`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.IsMinimised():
+ if self._expanded_panel != None:
+ self.HideExpanded()
+ else:
+ self.ShowExpanded()
+
+ elif self.IsExtButtonHovered():
+ notification = RibbonPanelEvent(wxEVT_COMMAND_RIBBONPANEL_EXTBUTTON_ACTIVATED, self.GetId())
+ notification.SetEventObject(self)
+ notification.SetPanel(self)
+ self.ProcessEvent(notification)
+
+
+ def GetExpandedDummy(self):
+ """
+ Get the dummy panel of an expanded panel.
+
+ :note: This should be called on an expanded panel to get the dummy associated
+ with it - it will return ``None`` when called on the dummy itself.
+
+ :see: :meth:`~RibbonPanel.ShowExpanded`, :meth:`~RibbonPanel.GetExpandedPanel`
+ """
+
+ return self._expanded_dummy
+
+
+ def GetExpandedPanel(self):
+ """
+ Get the expanded panel of a dummy panel.
+
+ :note: This should be called on a dummy panel to get the expanded panel
+ associated with it - it will return ``None`` when called on the expanded panel
+ itself.
+
+ :see: :meth:`~RibbonPanel.ShowExpanded`, :meth:`~RibbonPanel.GetExpandedDummy`
+ """
+
+ return self._expanded_panel
+
+
+ def ShowExpanded(self):
+ """
+ Show the panel externally expanded.
+
+ When a panel is minimised, it can be shown full-size in a pop-out window, which
+ is refered to as being (externally) expanded.
+
+ :returns: ``True`` if the panel was expanded, ``False`` if it was not (possibly
+ due to it not being minimised, or already being expanded).
+
+ :note: When a panel is expanded, there exist two panels - the original panel
+ (which is refered to as the dummy panel) and the expanded panel. The original
+ is termed a dummy as it sits in the ribbon bar doing nothing, while the expanded
+ panel holds the panel children.
+
+ :see: :meth:`~RibbonPanel.HideExpanded`, :meth:`~RibbonPanel.GetExpandedPanel`
+ """
+
+ if not self.IsMinimised():
+ return False
+
+ if self._expanded_dummy != None or self._expanded_panel != None:
+ return False
+
+ size = self.GetBestSize()
+ pos = self.GetExpandedPosition(wx.RectPS(self.GetScreenPosition(), self.GetSize()), size, self._preferred_expand_direction).GetTopLeft()
+
+ # Need a top-level frame to contain the expanded panel
+ container = wx.Frame(None, wx.ID_ANY, self.GetLabel(), pos, size, wx.FRAME_NO_TASKBAR | wx.BORDER_NONE)
+
+ self._expanded_panel = RibbonPanel(container, wx.ID_ANY, self.GetLabel(), self._minimised_icon, wx.Point(0, 0), size, self._flags)
+ self._expanded_panel.SetArtProvider(self._art)
+ self._expanded_panel._expanded_dummy = self
+
+ # Move all children to the new panel.
+ # Conceptually it might be simpler to reparent self entire panel to the
+ # container and create a new panel to sit in its place while expanded.
+ # This approach has a problem though - when the panel is reinserted into
+ # its original parent, it'll be at a different position in the child list
+ # and thus assume a new position.
+ # NB: Children iterators not used as behaviour is not well defined
+ # when iterating over a container which is being emptied
+
+ for child in self.GetChildren():
+ child.Reparent(self._expanded_panel)
+ child.Show()
+
+
+ # Move sizer to new panel
+ if self.GetSizer():
+ sizer = self.GetSizer()
+ self.SetSizer(None, False)
+ self._expanded_panel.SetSizer(sizer)
+
+ self._expanded_panel.Realize()
+ self.Refresh()
+ container.Show()
+ self._expanded_panel.SetFocus()
+
+ return True
+
+
+ def ShouldSendEventToDummy(self, event):
+
+ # For an expanded panel, filter events between being sent up to the
+ # floating top level window or to the dummy panel sitting in the ribbon
+ # bar.
+
+ # Child focus events should not be redirected, as the child would not be a
+ # child of the window the event is redirected to. All other command events
+ # seem to be suitable for redirecting.
+ return event.IsCommandEvent() and event.GetEventType() != wx.wxEVT_CHILD_FOCUS
+
+
+ def TryAfter(self, event):
+
+ if self._expanded_dummy and self.ShouldSendEventToDummy(event):
+ propagateOnce = wx.PropagateOnce(event)
+ return self._expanded_dummy.GetEventHandler().ProcessEvent(event)
+ else:
+ return RibbonControl.TryAfter(self, event)
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`RibbonPanel`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if self._expanded_dummy:
+ receiver = event.GetWindow()
+
+ if IsAncestorOf(self, receiver):
+ self._child_with_focus = receiver
+ receiver.Bind(wx.EVT_KILL_FOCUS, self.OnChildKillFocus)
+
+ elif receiver is None or receiver != self._expanded_dummy:
+ self.HideExpanded()
+
+
+ def OnChildKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for children of :class:`RibbonPanel`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if self._child_with_focus == None:
+ return # Should never happen, but a check can't hurt
+
+ self._child_with_focus.Bind(wx.EVT_KILL_FOCUS, None)
+ self._child_with_focus = None
+
+ receiver = event.GetWindow()
+ if receiver == self or IsAncestorOf(self, receiver):
+ self._child_with_focus = receiver
+ receiver.Bind(wx.EVT_KILL_FOCUS, self.OnChildKillFocus)
+ event.Skip()
+
+ elif receiver == None or receiver != self._expanded_dummy:
+ self.HideExpanded()
+ # Do not skip event, as the panel has been de-expanded, causing the
+ # child with focus to be reparented (and hidden). If the event
+ # continues propogation then bad things happen.
+
+ else:
+ event.Skip()
+
+
+ def HideExpanded(self):
+ """
+ Hide the panel's external expansion.
+
+ :returns: ``True`` if the panel was un-expanded, ``False`` if it was not
+ (normally due to it not being expanded in the first place).
+
+ :see: :meth:`~RibbonPanel.HideExpanded`, :meth:`~RibbonPanel.GetExpandedPanel`
+ """
+
+ if self._expanded_dummy == None:
+ if self._expanded_panel:
+ return self._expanded_panel.HideExpanded()
+ else:
+ return False
+
+ # Move children back to original panel
+ # NB: Children iterators not used as behaviour is not well defined
+ # when iterating over a container which is being emptied
+ for child in self.GetChildren():
+ child.Reparent(self._expanded_dummy)
+ child.Hide()
+
+ # TODO: Move sizer back
+ self._expanded_dummy._expanded_panel = None
+ self._expanded_dummy.Realize()
+ self._expanded_dummy.Refresh()
+ parent = self.GetParent()
+ self.Destroy()
+ parent.Destroy()
+
+ return True
+
+
+ def GetExpandedPosition(self, panel, expanded_size, direction):
+
+ # Strategy:
+ # 1) Determine primary position based on requested direction
+ # 2) Move the position so that it sits entirely within a display
+ # (for single monitor systems, this moves it into the display region,
+ # but for multiple monitors, it does so without splitting it over
+ # more than one display)
+ # 2.1) Move in the primary axis
+ # 2.2) Move in the secondary axis
+
+ primary_x = False
+ secondary_x = secondary_y = 0
+ pos = wx.Point()
+
+ if direction == wx.NORTH:
+ pos.x = panel.GetX() + (panel.GetWidth() - expanded_size.GetWidth()) / 2
+ pos.y = panel.GetY() - expanded_size.GetHeight()
+ primary_x = True
+ secondary_y = 1
+
+ elif direction == wx.EAST:
+ pos.x = panel.GetRight()
+ pos.y = panel.GetY() + (panel.GetHeight() - expanded_size.GetHeight()) / 2
+ secondary_x = -1
+
+ elif direction == wx.SOUTH:
+ pos.x = panel.GetX() + (panel.GetWidth() - expanded_size.GetWidth()) / 2
+ pos.y = panel.GetBottom()
+ primary_x = True
+ secondary_y = -1
+
+ else:
+ pos.x = panel.GetX() - expanded_size.GetWidth()
+ pos.y = panel.GetY() + (panel.GetHeight() - expanded_size.GetHeight()) / 2
+ secondary_x = 1
+
+ expanded = wx.RectPS(pos, expanded_size)
+ best = wx.Rect(*expanded)
+ best_distance = 10000
+
+ display_n = wx.Display.GetCount()
+
+ for display_i in xrange(display_n):
+ display = wx.Display(display_i).GetGeometry()
+ if display.ContainsRect(expanded):
+ return expanded
+
+ elif display.Intersects(expanded):
+ new_rect = wx.Rect(*expanded)
+ distance = 0
+
+ if primary_x:
+ if expanded.GetRight() > display.GetRight():
+ distance = expanded.GetRight() - display.GetRight()
+ new_rect.x -= distance
+
+ elif expanded.GetLeft() < display.GetLeft():
+ distance = display.GetLeft() - expanded.GetLeft()
+ new_rect.x += distance
+
+ else:
+ if expanded.GetBottom() > display.GetBottom():
+ distance = expanded.GetBottom() - display.GetBottom()
+ new_rect.y -= distance
+
+ elif expanded.GetTop() < display.GetTop():
+ distance = display.GetTop() - expanded.GetTop()
+ new_rect.y += distance
+
+ if not display.Contains(new_rect):
+ # Tried moving in primary axis, but failed.
+ # Hence try moving in the secondary axis.
+ dx = secondary_x * (panel.GetWidth() + expanded_size.GetWidth())
+ dy = secondary_y * (panel.GetHeight() + expanded_size.GetHeight())
+ new_rect.x += dx
+ new_rect.y += dy
+
+ # Squaring makes secondary moves more expensive (and also
+ # prevents a negative cost)
+ distance += dx * dx + dy * dy
+
+ if display.Contains(new_rect) and distance < best_distance:
+ best = new_rect
+ best_distance = distance
+
+ return best
+
+
+ def GetMinimisedIcon(self):
+ """
+ Get the bitmap to be used in place of the panel children when it is minimised.
+ """
+
+ return self._minimised_icon
+
+
+ def GetDefaultBorder(self):
+ """ Returns the default border style for :class:`RibbonPanel`. """
+
+ return wx.BORDER_NONE
+
+
+ def GetFlags(self):
+ """ Returns the AGW-specific window style for :class:`RibbonPanel`. """
+
+ return self._flags
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/toolbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/toolbar.py
new file mode 100644
index 0000000..33298cf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ribbon/toolbar.py
@@ -0,0 +1,1453 @@
+"""
+A ribbon tool bar is similar to a traditional toolbar which has no labels.
+
+
+Description
+===========
+
+It contains one or more tool groups, each of which contains one or more tools.
+Each tool is represented by a (generally small, i.e. 16x15) bitmap.
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+====================================== ======================================
+Event Name Description
+====================================== ======================================
+``EVT_RIBBONTOOLBAR_CLICKED`` Triggered when the normal (non-dropdown) region of a tool on the tool bar is clicked.
+``EVT_RIBBONTOOLBAR_DROPDOWN_CLICKED`` Triggered when the dropdown region of a tool on the tool bar is clicked. LRibbonToolBarEvent.PopupMenu should be called by the event handler if it wants to display a popup menu (which is what most dropdown tools should be doing).
+====================================== ======================================
+
+"""
+
+import wx
+import sys
+
+from control import RibbonControl
+from panel import RibbonPanel
+
+from art import *
+
+wxEVT_COMMAND_RIBBONTOOL_CLICKED = wx.NewEventType()
+wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED = wx.NewEventType()
+
+EVT_RIBBONTOOLBAR_CLICKED = wx.PyEventBinder(wxEVT_COMMAND_RIBBONTOOL_CLICKED, 1)
+EVT_RIBBONTOOLBAR_DROPDOWN_CLICKED = wx.PyEventBinder(wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED, 1)
+
+
+def GetSizeInOrientation(size, orientation):
+
+ if orientation == wx.HORIZONTAL:
+ return size.GetWidth()
+
+ if orientation == wx.VERTICAL:
+ return size.GetHeight()
+
+ if orientation == wx.BOTH:
+ return size.GetWidth() * size.GetHeight()
+
+ return 0
+
+
+class RibbonToolBarEvent(wx.PyCommandEvent):
+ """ Handles events related to :class:`RibbonToolBar`. """
+
+ def __init__(self, command_type=None, win_id=0, bar=None):
+ """
+ Default class constructor.
+
+ :param integer `command_type`: the event type;
+ :param integer `win_id`: the event identifier;
+ :param `bar`: an instance of :class:`RibbonToolBar`.
+ """
+
+ wx.PyCommandEvent.__init__(self, command_type, win_id)
+ self._bar = bar
+
+
+ def GetBar(self):
+ """ Returns an instance of :class:`RibbonToolBar`. """
+
+ return self._bar
+
+
+ def SetBar(self, bar):
+ """
+ Sets the current :class:`RibbonToolBar` for this event.
+
+ :param `bar`: an instance of :class:`RibbonToolBar`.
+ """
+
+ self._bar = bar
+
+
+ def PopupMenu(self, menu):
+ """
+ Pops up the given menu and returns control when the user has dismissed the menu.
+
+ If a menu item is selected, the corresponding menu event is generated and will
+ be processed as usual.
+
+ :param `menu`: the menu to pop up, an instance of :class:`Menu`.
+
+ :note: Just before the menu is popped up, :meth:`Menu.UpdateUI` is called to ensure
+ that the menu items are in the correct state. The menu does not get deleted by
+ the window.
+ """
+
+ pos = wx.Point()
+
+ if self._bar._active_tool:
+ # Find the group which contains the tool
+ group_count = len(self._bar._groups)
+ tobreak = False
+
+ for g in xrange(group_count):
+ group = self._bar._groups[g]
+ tool_count = len(group.tools)
+
+ for t in xrange(tool_count):
+ tool = group.tools[t]
+ if tool == self._bar._active_tool:
+ pos = wx.Point(*group.position)
+ pos += tool.position
+ pos.y += tool.size.GetHeight()
+ g = group_count
+ tobreak = True
+ break
+
+ if tobreak:
+ break
+
+ return self._bar.PopupMenu(menu, pos)
+
+
+class RibbonToolBarToolBase(object):
+
+ def __init__(self):
+
+ self.help_string = ""
+ self.bitmap = wx.NullBitmap
+ self.bitmap_disabled = wx.NullBitmap
+ self.dropdown = wx.Rect()
+ self.position = wx.Point()
+ self.size = wx.Size()
+ self.client_data = None
+ self.id = -1
+ self.kind = RIBBON_BUTTON_NORMAL
+ self.state = None
+
+
+class RibbonToolBarToolGroup(object):
+
+ def __init__(self):
+
+ # To identify the group as a RibbonToolBarToolBase
+ self.dummy_tool = None
+
+ self.tools = []
+ self.position = wx.Point()
+ self.size = wx.Size()
+
+
+class RibbonToolBar(RibbonControl):
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0,
+ name="RibbonToolBar"):
+
+ """
+ Default class constructor.
+
+ :param `parent`: pointer to a parent window, typically a :class:`~lib.agw.ribbon.panel.RibbonPanel`;
+ :param `id`: window identifier. If ``wx.ID_ANY``, will automatically create
+ an identifier;
+ :param `pos`: window position. ``wx.DefaultPosition`` indicates that wxPython
+ should generate a default position for the window;
+ :param `size`: window size. ``wx.DefaultSize`` indicates that wxPython should
+ generate a default size for the window. If no suitable size can be found, the
+ window will be sized to 20x20 pixels so that the window is visible but obviously
+ not correctly sized;
+ :param `style`: window style, currently unused.
+ :param `name`: the window name.
+
+ """
+
+ RibbonControl.__init__(self, parent, id, pos, size, wx.BORDER_NONE, name=name)
+
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ self.CommonInit(style)
+
+
+ def CommonInit(self, style):
+
+ self._groups = []
+
+ self.AppendGroup()
+ self._hover_tool = None
+ self._active_tool = None
+ self._nrows_min = 1
+ self._nrows_max = 1
+ self._sizes = [wx.Size(0, 0)]
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+
+ def AddSimpleTool(self, tool_id, bitmap, help_string, kind=RIBBON_BUTTON_NORMAL):
+ """
+ Add a tool to the tool bar (simple version).
+
+ :param `tool_id`: id of the new tool (used for event callbacks);
+ :param `bitmap`: large bitmap of the new button. Must be the same size as all
+ other large bitmaps used on the button bar;
+ :param `help_string`: the UI help string to associate with the new button;
+ :param `kind`: the kind of button to add.
+
+ :see: :meth:`~RibbonToolBar.AddDropdownTool`, :meth:`~RibbonToolBar.AddHybridTool`, :meth:`~RibbonToolBar.AddTool`
+
+ """
+
+ return self.AddTool(tool_id, bitmap, wx.NullBitmap, help_string, kind, None)
+
+
+ def AddDropdownTool(self, tool_id, bitmap, help_string=""):
+ """
+ Add a dropdown tool to the tool bar (simple version).
+
+ :param `tool_id`: id of the new tool (used for event callbacks);
+ :param `bitmap`: large bitmap of the new button. Must be the same size as all
+ other large bitmaps used on the button bar;
+ :param `help_string`: the UI help string to associate with the new button.
+
+ :see: :meth:`~RibbonToolBar.AddTool`
+ """
+
+ return self.AddTool(tool_id, bitmap, wx.NullBitmap, help_string, RIBBON_BUTTON_DROPDOWN, None)
+
+
+ def InsertDropdownTool(self, pos, tool_id, bitmap, help_string=""):
+ """
+ Inserts a dropdown tool in the tool bar at the position specified by `pos`.
+
+ :param `pos`: the position of the new tool in the toolbar (zero-based);
+ :param `tool_id`: id of the new tool (used for event callbacks);
+ :param `bitmap`: large bitmap of the new button. Must be the same size as all
+ other large bitmaps used on the button bar;
+ :param `help_string`: the UI help string to associate with the new button.
+
+ :see: :meth:`~RibbonToolBar.AddTool`, :meth:`~RibbonToolBar.InsertTool`
+
+ .. versionadded:: 0.9.5
+ """
+
+ return self.InsertTool(pos, tool_id, bitmap, wx.NullBitmap, help_string, RIBBON_BUTTON_DROPDOWN, None)
+
+
+ def AddHybridTool(self, tool_id, bitmap, help_string=""):
+ """
+ Add a hybrid tool to the tool bar (simple version).
+
+ :param `tool_id`: id of the new tool (used for event callbacks);
+ :param `bitmap`: large bitmap of the new button. Must be the same size as all
+ other large bitmaps used on the button bar;
+ :param `help_string`: the UI help string to associate with the new button.
+
+ :see: :meth:`~RibbonToolBar.AddTool`
+ """
+
+ return self.AddTool(tool_id, bitmap, wx.NullBitmap, help_string, RIBBON_BUTTON_HYBRID, None)
+
+
+ def InsertHybridTool(self, pos, tool_id, bitmap, help_string=""):
+ """
+ Inserts a hybrid tool in the tool bar at the position specified by `pos`.
+
+ :param `pos`: the position of the new tool in the toolbar (zero-based);
+ :param `tool_id`: id of the new tool (used for event callbacks);
+ :param `bitmap`: large bitmap of the new button. Must be the same size as all
+ other large bitmaps used on the button bar;
+ :param `help_string`: the UI help string to associate with the new button.
+
+ :see: :meth:`~RibbonToolBar.AddTool`, :meth:`~RibbonToolBar.InsertTool`
+
+ .. versionadded:: 0.9.5
+ """
+
+ return self.InsertTool(pos, tool_id, bitmap, wx.NullBitmap, help_string, RIBBON_BUTTON_HYBRID, None)
+
+
+ def AddToggleTool(self, bitmap, help_string=""):
+ """
+ Add a toggle tool to the tool bar (simple version).
+
+ :param `tool_id`: id of the new tool (used for event callbacks);
+ :param `bitmap`: large bitmap of the new button. Must be the same size as all
+ other large bitmaps used on the button bar;
+ :param `help_string`: the UI help string to associate with the new button.
+
+ :see: :meth:`~RibbonToolBar.AddTool`
+ """
+
+ return self.AddTool(tool_id, bitmap, wx.NullBitmap, help_string, RIBBON_BUTTON_TOGGLE, None)
+
+
+ def InsertToggleTool(self, pos, tool_id, bitmap, help_string=""):
+ """
+ Inserts a toggle tool in the tool bar at the position specified by `pos`.
+
+ :param `pos`: the position of the new tool in the toolbar (zero-based);
+ :param `tool_id`: id of the new tool (used for event callbacks);
+ :param `bitmap`: large bitmap of the new button. Must be the same size as all
+ other large bitmaps used on the button bar;
+ :param `help_string`: the UI help string to associate with the new button.
+
+ :see: :meth:`~RibbonToolBar.AddTool`, :meth:`~RibbonToolBar.InsertTool`
+
+ .. versionadded:: 0.9.5
+ """
+
+ return self.InsertTool(pos, tool_id, bitmap, wx.NullBitmap, help_string, RIBBON_BUTTON_TOGGLE, None)
+
+
+ def AddTool(self, tool_id, bitmap, bitmap_disabled=wx.NullBitmap, help_string="", kind=RIBBON_BUTTON_NORMAL, client_data=None):
+ """
+ Add a tool to the tool bar.
+
+ :param `tool_id`: id of the new tool (used for event callbacks);
+ :param `bitmap`: bitmap to use as the foreground for the new tool. Does not
+ have to be the same size as other tool bitmaps, but should be similar as
+ otherwise it will look visually odd;
+ :param `bitmap_disabled`: bitmap to use when the tool is disabled. If left
+ as :class:`NullBitmap`, then a bitmap will be automatically generated from `bitmap`;
+ :param `help_string`: the UI help string to associate with the new tool;
+ :param `kind`: the kind of tool to add;
+ :param `client_data`: client data to associate with the new tool.
+
+ :returns: An opaque pointer which can be used only with other tool bar methods.
+
+ :see: :meth:`~RibbonToolBar.AddDropdownTool`, :meth:`~RibbonToolBar.AddHybridTool`, :meth:`~RibbonToolBar.AddSeparator`
+ """
+
+ return self.InsertTool(self.GetToolCount(), tool_id, bitmap, bitmap_disabled,
+ help_string, kind, client_data)
+
+
+ def InsertTool(self, pos, tool_id, bitmap, bitmap_disabled=wx.NullBitmap, help_string="", kind=RIBBON_BUTTON_NORMAL, client_data=None):
+ """
+ Inserts a tool in the tool bar at the position specified by `pos`.
+
+ :param `pos`: the position of the new tool in the toolbar (zero-based);
+ :param `tool_id`: id of the new tool (used for event callbacks);
+ :param `bitmap`: bitmap to use as the foreground for the new tool. Does not
+ have to be the same size as other tool bitmaps, but should be similar as
+ otherwise it will look visually odd;
+ :param `bitmap_disabled`: bitmap to use when the tool is disabled. If left
+ as :class:`NullBitmap`, then a bitmap will be automatically generated from `bitmap`;
+ :param `help_string`: the UI help string to associate with the new tool;
+ :param `kind`: the kind of tool to add;
+ :param `client_data`: client data to associate with the new tool.
+
+ :returns: An opaque pointer which can be used only with other tool bar methods.
+
+ :see: :meth:`~RibbonToolBar.AddTool`, :meth:`~RibbonToolBar.AddDropdownTool`, :meth:`~RibbonToolBar.AddHybridTool`, :meth:`~RibbonToolBar.AddSeparator`
+
+ .. versionadded:: 0.9.5
+ """
+
+ if not bitmap.IsOk():
+ raise Exception("Exception")
+
+ tool = RibbonToolBarToolBase()
+ tool.id = tool_id
+ tool.bitmap = bitmap
+
+ if bitmap_disabled.IsOk():
+ if bitmap.GetSize() != bitmap_disabled.GetSize():
+ raise Exception("Exception")
+
+ tool.bitmap_disabled = bitmap_disabled
+ else:
+ tool.bitmap_disabled = self.MakeDisabledBitmap(bitmap)
+
+ tool.help_string = help_string
+ tool.kind = kind
+ tool.client_data = client_data
+ tool.position = wx.Point(0, 0)
+ tool.size = wx.Size(0, 0)
+ tool.state = 0
+
+ # Find the position where insert tool
+ group_count = len(self._groups)
+
+ for group in self._groups:
+ tool_count = len(group.tools)
+
+ if pos <= tool_count:
+ group.tools.insert(pos, tool)
+ return tool
+
+ pos -= tool_count + 1
+
+ raise Exception("Tool position out of toolbar bounds.")
+
+
+ def AddSeparator(self):
+ """
+ Adds a separator to the tool bar.
+
+ Separators are used to separate tools into groups. As such, a separator is not
+ explicity drawn, but is visually seen as the gap between tool groups.
+ """
+
+ if not self._groups[-1].tools:
+ return None
+
+ self.AppendGroup()
+ return self._groups[-1].dummy_tool
+
+
+ def InsertSeparator(self, pos):
+ """
+ Inserts a separator into the tool bar at the position specified by `pos`.
+
+ Separators are used to separate tools into groups. As such, a separator is not
+ explicity drawn, but is visually seen as the gap between tool groups.
+
+ :param `pos`: the position of the new tool in the toolbar (zero-based).
+
+ .. versionadded:: 0.9.5
+ """
+
+ for index, group in enumerate(self._groups):
+ if pos == 0:
+ # Prepend group
+ return self.InsertGroup(index).dummy_tool
+
+ if pos >= len(self._groups):
+ # Append group
+ return self.InsertGroup(index+1).dummy_tool
+
+ tool_count = len(group.tools)
+
+ if pos < tool_count:
+ new_group = self.InsertGroup(index+1)
+
+ for t in xrange(pos, tool_count):
+ new_group.tools.append(group.tools[t])
+
+ group.tools = group.tools[0:pos]
+ return group.dummy_tool
+
+ pos -= tool_count + 1
+
+ # Add an empty group at the end of the bar.
+ if not self._groups[-1].tools:
+ return None
+
+ self.AppendGroup()
+ return self._groups[-1].dummy_tool
+
+
+ def MakeDisabledBitmap(self, original):
+
+ img = original.ConvertToImage()
+ return wx.BitmapFromImage(img.ConvertToGreyscale())
+
+
+ def AppendGroup(self):
+
+ group = RibbonToolBarToolGroup()
+ group.position = wx.Point(0, 0)
+ group.size = wx.Size(0, 0)
+ self._groups.append(group)
+
+
+ def InsertGroup(self, pos):
+
+ group = RibbonToolBarToolGroup()
+ group.position = wx.Point(0, 0)
+ group.size = wx.Size(0, 0)
+ self._groups.insert(pos, group)
+
+ return group
+
+
+ def ClearTools(self):
+ """
+ Deletes all the tools in the toolbar.
+
+ .. versionadded:: 0.9.5
+ """
+
+ self._groups = []
+
+
+ def DeleteTool(self, tool_id):
+ """
+ Removes the specified tool from the toolbar and deletes it.
+
+ :param `tool_id`: id of the tool to delete.
+
+ :returns: ``True`` if the tool was deleted, ``False`` otherwise.
+
+ :see: :meth:`~RibbonToolBar.DeleteToolByPos`
+
+ .. versionadded:: 0.9.5
+ """
+
+ for group in self._groups:
+ for tool in group.tools:
+ if tool.id == tool_id:
+ group.tools.remove(tool)
+ return True
+
+ return False
+
+
+ def DeleteToolByPos(self, pos):
+ """
+ This function behaves like :meth:`~RibbonToolBar.DeleteTool` but it deletes the tool at the
+ specified position `pos` and not the one with the given id.
+
+ Useful to delete separators.
+
+ :param `pos`: zero-based position of the tool to delete.
+
+ :returns: ``True`` if the tool was deleted, ``False`` otherwise.
+
+ :see: :meth:`~RibbonToolBar.DeleteTool`
+
+ .. versionadded:: 0.9.5
+ """
+
+ for index, group in enumerate(self._groups):
+ tool_count = len(group.tools)
+
+ if pos < tool_count:
+ # Remove tool
+ group.tools.pop(pos)
+ return True
+
+ elif pos == tool_count:
+ # Remove separator
+ if index < len(self._groups) - 1:
+
+ next_group = self._groups[index+1]
+
+ for t in xrange(0, len(next_group.tools)):
+ group.tools.append(next_group.tools[t])
+
+ self._groups.pop(index+1)
+
+ return True
+
+ return False
+
+
+ def FindById(self, tool_id):
+ """
+ Returns a pointer to the tool opaque structure by `tool_id` or ``None`` if
+ no corresponding tool is found.
+
+ :param `tool_id`: id of the tool to find.
+
+ .. versionadded:: 0.9.5
+ """
+
+ for group in self._groups:
+ for tool in group.tools:
+ if tool.id == tool_id:
+ return tool
+
+ return None
+
+
+ def GetToolByPos(self, pos):
+ """
+ Returns a pointer to the tool opaque structure by `pos` or ``None`` if
+ no corresponding tool is found.
+
+ :param `pos`: zero-based position of the tool to retrieve.
+
+ :returns: An instance of :class:`RibbonToolBarToolBase` if the tool was found,
+ ``None`` if it was not found.
+
+ .. versionadded:: 0.9.5
+ """
+
+ for group in self._groups:
+ tool_count = len(group.tools)
+
+ if pos < tool_count:
+ return group.tools[pos]
+
+ elif pos >= tool_count:
+ return None
+
+ return None
+
+
+ def GetToolCount(self):
+ """
+ Returns the number of tools in this :class:`RibbonToolBar`.
+
+ .. versionadded:: 0.9.5
+ """
+
+ count = 0
+ for group in self._groups:
+ count += len(group.tools)
+
+ # There is a splitter in front of every group except for the first
+ # If only one group, no separator.
+ if len(self._groups) > 1:
+ count += len(self._groups) - 1
+
+ return count
+
+
+ def GetToolId(self, tool):
+ """
+ Returns the tool id for the specified input `tool`.
+
+ :param `tool`: an instance of :class:`RibbonToolBarToolBase`.
+
+ .. versionadded:: 0.9.5
+ """
+
+ return tool.id
+
+
+ def GetToolClientData(self, tool_id):
+ """
+ Get any client data associated with the tool.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`.
+
+ :return: Client data (any Python object), or ``None`` if there is none.
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ return tool.client_data
+
+
+ def GetToolEnabled(self, tool_id):
+ """
+ Called to determine whether a tool is enabled (responds to user input).
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`.
+
+ :return: ``True`` if the tool was found and it is enabled, ``False`` otherwise.
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ return (tool.state & RIBBON_TOOLBAR_TOOL_DISABLED) == 0
+
+
+ def GetToolHelpString(self, tool_id):
+ """
+ Returns the tool short help string.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`.
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ return tool.help_string
+
+
+ def GetToolKind(self, tool_id):
+ """
+ Returns the kind of the given tool.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`.
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ return tool.kind
+
+
+ def GetToolPos(self, tool_id):
+ """
+ Returns the tool position in the toolbar, or ``wx.NOT_FOUND`` if the tool is not found.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`.
+
+ .. versionadded:: 0.9.5
+ """
+
+ pos = 0
+ for group in self._groups:
+
+ for tool in group.tools:
+
+ if tool.id == tool_id:
+ return pos
+
+ pos += 1
+
+ pos += 1 # Increment pos for group separator.
+
+ return wx.NOT_FOUND
+
+
+ def GetToolState(self, tool_id):
+ """
+ Gets the on/off state of a toggle tool.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`.
+
+ :return: ``True`` if the tool is toggled on, ``False`` otherwise.
+
+ :see: :meth:`~RibbonToolBar.ToggleTool`
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ return tool.state & RIBBON_TOOLBAR_TOOL_TOGGLED
+
+
+ def SetToolClientData(self, tool_id, clientData):
+ """
+ Sets the client data associated with the tool.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`;
+ :param `clientData`: any Python object.
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ tool.client_data = clientData
+
+
+ def SetToolDisabledBitmap(self, tool_id, bitmap):
+ """
+ Sets the bitmap to be used by the tool with the given ID when the tool is in a disabled state.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`;
+ :param `bitmap`: an instance of :class:`Bitmap`.
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ tool.bitmap_disabled = bitmap
+
+
+ def SetToolHelpString(self, tool_id, helpString):
+ """
+ Sets the tool short help string.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`;
+ :param `helpString`: a string for the help.
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ tool.help_string = helpString
+
+
+ def SetToolNormalBitmap(self, tool_id, bitmap):
+ """
+ Sets the bitmap to be used by the tool with the given ID when the tool is enabled.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`;
+ :param `bitmap`: an instance of :class:`Bitmap`.
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ tool.bitmap = bitmap
+
+
+ def EnableTool(self, tool_id, enable=True):
+ """
+ Enables or disables a single tool on the bar.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`;
+ :param `enable`: ``True`` to enable the tool, ``False`` to disable it.
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ if enable:
+
+ if tool.state & RIBBON_TOOLBAR_TOOL_DISABLED:
+ tool.state &= ~RIBBON_TOOLBAR_TOOL_DISABLED
+ self.Refresh()
+
+ else:
+
+ if (tool.state & RIBBON_TOOLBAR_TOOL_DISABLED) == 0:
+ tool.state |= RIBBON_TOOLBAR_TOOL_DISABLED
+ self.Refresh()
+
+
+ def ToggleTool(self, tool_id, checked=True):
+ """
+ Toggles on or off a single tool on the bar.
+
+ :param `tool_id`: id of the tool in question, as passed to :meth:`~RibbonToolBar.AddTool`;
+ :param `checked`: ``True`` to toggle on the tool, ``False`` to toggle it off.
+
+ .. versionadded:: 0.9.5
+ """
+
+ tool = self.FindById(tool_id)
+ if tool is None:
+ raise Exception("Invalid tool id")
+
+ if checked:
+ if (tool.state & RIBBON_TOOLBAR_TOOL_TOGGLED) == 0:
+ tool.state |= RIBBON_TOOLBAR_TOOL_TOGGLED
+ self.Refresh()
+ else:
+ if tool.state & RIBBON_TOOLBAR_TOOL_TOGGLED:
+ tool.state &= ~RIBBON_TOOLBAR_TOOL_TOGGLED
+ self.Refresh()
+
+
+ def IsSizingContinuous(self):
+ """
+ Returns ``True`` if this window can take any size (greater than its minimum size),
+ ``False`` if it can only take certain sizes.
+
+ :see: :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`,
+ :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`
+ """
+
+ return False
+
+
+ def DoGetNextSmallerSize(self, direction, relative_to):
+ """
+ Implementation of :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`.
+
+ Controls which have non-continuous sizing must override this virtual function
+ rather than :meth:`RibbonControl.GetNextSmallerSize() <lib.agw.ribbon.control.RibbonControl.GetNextSmallerSize>`.
+ """
+
+ result = wx.Size(*relative_to)
+ area = 0
+ tobreak = False
+
+ for nrows in xrange(self._nrows_max, self._nrows_min-1, -1):
+
+ size = wx.Size(*self._sizes[nrows - self._nrows_min])
+ original = wx.Size(*size)
+
+ if direction == wx.HORIZONTAL:
+ if size.GetWidth() < relative_to.GetWidth() and size.GetHeight() <= relative_to.GetHeight():
+ size.SetHeight(relative_to.GetHeight())
+ tobreak = True
+
+ elif direction == wx.VERTICAL:
+ if size.GetWidth() <= relative_to.GetWidth() and size.GetHeight() < relative_to.GetHeight():
+ size.SetWidth(relative_to.GetWidth())
+ tobreak = True
+
+ elif direction == wx.BOTH:
+ if size.GetWidth() < relative_to.GetWidth() and size.GetHeight() < relative_to.GetHeight():
+ pass
+
+ if GetSizeInOrientation(original, direction) > area:
+ result = wx.Size(*size)
+ area = GetSizeInOrientation(original, direction)
+ if tobreak:
+ break
+
+ return result
+
+
+ def DoGetNextLargerSize(self, direction, relative_to):
+ """
+ Implementation of :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`.
+
+ Controls which have non-continuous sizing must override this virtual function
+ rather than :meth:`RibbonControl.GetNextLargerSize() <lib.agw.ribbon.control.RibbonControl.GetNextLargerSize>`.
+ """
+
+ # Pick the smallest of our sizes which are larger than the given size
+ result = wx.Size(*relative_to)
+ area = 10000
+ tobreak = False
+
+ for nrows in xrange(self._nrows_min, self._nrows_max+1):
+
+ size = wx.Size(*self._sizes[nrows - self._nrows_min])
+ original = wx.Size(*size)
+
+ if direction == wx.HORIZONTAL:
+ if size.GetWidth() > relative_to.GetWidth() and size.GetHeight() <= relative_to.GetHeight():
+ size.SetHeight(relative_to.GetHeight())
+ tobreak = True
+
+ elif direction == wx.VERTICAL:
+ if size.GetWidth() <= relative_to.GetWidth() and size.GetHeight() > relative_to.GetHeight():
+ size.SetWidth(relative_to.GetWidth())
+ tobreak = True
+
+ elif direction == wx.BOTH:
+ if size.GetWidth() > relative_to.GetWidth() and size.GetHeight() > relative_to.GetHeight():
+ tobreak = True
+
+ if GetSizeInOrientation(original, direction) < area:
+ result = wx.Size(*size)
+ area = GetSizeInOrientation(original, direction)
+ if tobreak:
+ break
+
+ return result
+
+
+ def SetRows(self, nMin, nMax):
+ """
+ Set the number of rows to distribute tool groups over.
+
+ Tool groups can be distributed over a variable number of rows. The way in which
+ groups are assigned to rows is not specificed, and the order of groups may
+ change, but they will be distributed in such a way as to minimise the overall
+ size of the tool bar.
+
+ :param `nMin`: the minimum number of rows to use;
+ :param `nMax`: the maximum number of rows to use (defaults to `nMin`).
+
+ """
+
+ if nMax == -1:
+ nMax = nMin
+
+ if nMin < 1:
+ raise Exception("Exception")
+ if nMin > nMax:
+ raise Exception("Exception")
+
+ self._nrows_min = nMin
+ self._nrows_max = nMax
+
+ self._sizes = []
+ self._sizes = [wx.Size(0, 0) for i in xrange(self._nrows_min, self._nrows_max + 1)]
+
+ self.Realize()
+
+
+ def Realize(self):
+ """
+ Calculates tool layouts and positions.
+
+ Must be called after tools are added to the tool bar, as otherwise the newly
+ added tools will not be displayed.
+
+ :note: Reimplemented from :class:`~lib.agw.ribbon.control.RibbonControl`.
+ """
+
+ if self._art == None:
+ return False
+
+ # Calculate the size of each group and the position/size of each tool
+ temp_dc = wx.MemoryDC()
+ group_count = len(self._groups)
+
+ for group in self._groups:
+
+ prev = None
+ tool_count = len(group.tools)
+ tallest = 0
+
+ for t, tool in enumerate(group.tools):
+
+ tool.size, tool.dropdown = self._art.GetToolSize(temp_dc, self, tool.bitmap.GetSize(), tool.kind, t==0, t==(tool_count-1))
+ tool.state = tool.state & ~RIBBON_TOOLBAR_TOOL_DISABLED
+ if t == 0:
+ tool.state |= RIBBON_TOOLBAR_TOOL_FIRST
+ if t == tool_count - 1:
+ tool.state |= RIBBON_TOOLBAR_TOOL_LAST
+ if tool.size.GetHeight() > tallest:
+ tallest = tool.size.GetHeight()
+ if prev:
+ tool.position = wx.Point(*prev.position)
+ tool.position.x += prev.size.x
+ else:
+ tool.position = wx.Point(0, 0)
+
+ prev = tool
+
+ if tool_count == 0:
+ group.size = wx.Size(0, 0)
+ else:
+ group.size = wx.Size(prev.position.x + prev.size.x, tallest)
+ for tool in group.tools:
+ tool.size.SetHeight(tallest)
+
+ # Calculate the minimum size for each possible number of rows
+ sep = self._art.GetMetric(RIBBON_ART_TOOL_GROUP_SEPARATION_SIZE)
+ smallest_area = 10000
+ row_sizes = [wx.Size(0, 0) for i in xrange(self._nrows_max)]
+ major_axis = ((self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL) and [wx.VERTICAL] or [wx.HORIZONTAL])[0]
+ self.SetMinSize(wx.Size(0, 0))
+
+ minSize = wx.Size(-1, -1)
+
+ # See if we're sizing flexibly (i.e. wrapping), and set min size differently
+ sizingFlexibly = False
+ panel = self.GetParent()
+
+ if isinstance(panel, RibbonPanel) and (panel.GetFlags() & RIBBON_PANEL_FLEXIBLE):
+ sizingFlexibly = True
+
+ # Without this, there will be redundant horizontal space because SetMinSize will
+ # use the smallest possible height (and therefore largest width).
+ if sizingFlexibly:
+ major_axis = wx.HORIZONTAL
+
+ for nrows in xrange(self._nrows_min, self._nrows_max+1):
+
+ for r in xrange(nrows):
+ row_sizes[r] = wx.Size(0, 0)
+
+ for g in xrange(group_count):
+
+ group = self._groups[g]
+ shortest_row = 0
+
+ for r in xrange(1, nrows):
+ if row_sizes[r].GetWidth() < row_sizes[shortest_row].GetWidth():
+ shortest_row = r
+
+ row_sizes[shortest_row].x += group.size.x + sep
+ if group.size.y > row_sizes[shortest_row].y:
+ row_sizes[shortest_row].y = group.size.y
+
+ size = wx.Size(0, 0)
+
+ for r in xrange(nrows):
+ if row_sizes[r].GetWidth() != 0:
+ row_sizes[r].DecBy(sep, 0)
+ if row_sizes[r].GetWidth() > size.GetWidth():
+ size.SetWidth(row_sizes[r].GetWidth())
+
+ size.IncBy(0, row_sizes[r].y)
+
+ self._sizes[nrows - self._nrows_min] = size
+
+ if GetSizeInOrientation(size, major_axis) < smallest_area:
+ smallest_area = GetSizeInOrientation(size, major_axis)
+ self.SetMinSize(size)
+
+ if sizingFlexibly:
+ if size.x < minSize.x:
+ minSize.x = size.x
+ if size.y < minSize.y:
+ minSize.y = size.y
+
+ if sizingFlexibly:
+ # Give it the min size in either direction regardless of row,
+ # so that we're able to vary the size of the panel according to
+ # the space the toolbar takes up.
+ self.SetMinSize(minSize)
+
+ # Position the groups
+ dummy_event = wx.SizeEvent(self.GetSize())
+ self.OnSize(dummy_event)
+
+ return True
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`RibbonToolBar`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ if self._art == None:
+ return
+
+ # Choose row count with largest possible area
+ size = event.GetSize()
+ row_count = self._nrows_max
+ major_axis = (self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL and [wx.VERTICAL] or [wx.HORIZONTAL])[0]
+
+ # See if we're sizing flexibly, and set min size differently
+ sizingFlexibly = False
+ panel = self.GetParent()
+
+ if isinstance(panel, RibbonPanel) and (panel.GetFlags() & RIBBON_PANEL_FLEXIBLE):
+ sizingFlexibly = True
+
+ # Without this, there will be redundant horizontal space because SetMinSize will
+ # use the smallest possible height (and therefore largest width).
+ if sizingFlexibly:
+ major_axis = wx.HORIZONTAL
+
+ bestSize = wx.Size(*self._sizes[0])
+
+ if self._nrows_max != self._nrows_min:
+ area = 0
+ for i in xrange(self._nrows_max - self._nrows_min + 1):
+ if self._sizes[i].x <= size.x and self._sizes[i].y <= size.y and \
+ GetSizeInOrientation(self._sizes[i], major_axis) > area:
+ area = GetSizeInOrientation(self._sizes[i], major_axis)
+ row_count = self._nrows_min + i
+ bestSize = wx.Size(*self._sizes[i])
+
+ # Assign groups to rows and calculate row widths
+ row_sizes = [wx.Size(0, 0) for i in xrange(row_count)]
+ sep = self._art.GetMetric(RIBBON_ART_TOOL_GROUP_SEPARATION_SIZE)
+
+ group_count = len(self._groups)
+ for group in self._groups:
+ shortest_row = 0
+ for r in xrange(1, row_count):
+ if row_sizes[r].GetWidth() < row_sizes[shortest_row].GetWidth():
+ shortest_row = r
+
+ group.position = wx.Point(row_sizes[shortest_row].x, shortest_row)
+ row_sizes[shortest_row].x += group.size.x + sep
+ if group.size.y > row_sizes[shortest_row].y:
+ row_sizes[shortest_row].y = group.size.y
+
+ # Calculate row positions
+ total_height = 0
+ for r in xrange(row_count):
+ total_height += row_sizes[r].GetHeight()
+
+ rowsep = (size.GetHeight() - total_height) / (row_count + 1)
+ rowypos = [0]*row_count
+ rowypos[0] = rowsep
+ for r in xrange(1, row_count):
+ rowypos[r] = rowypos[r - 1] + row_sizes[r - 1].GetHeight() + rowsep
+
+ # Set group y positions
+ for group in self._groups:
+ group.position.y = rowypos[group.position.y]
+
+
+ def GetBestSizeForParentSize(self, parentSize):
+ """ Finds the best width and height given the parent's width and height. """
+
+ if not self._sizes:
+ return self.GetMinSize()
+
+ # Choose row count with largest possible area
+ size = wx.Size(*parentSize)
+ row_count = self._nrows_max
+ major_axis = (self._art.GetFlags() & RIBBON_BAR_FLOW_VERTICAL and [wx.VERTICAL] or [wx.HORIZONTAL])[0]
+
+ # A toolbar should maximize its width whether vertical or horizontal, so
+ # force the major axis to be horizontal. Without this, there will be
+ # redundant horizontal space.
+ major_axis = wx.HORIZONTAL
+ bestSize = wx.Size(*self._sizes[0])
+
+ if self._nrows_max != self._nrows_min:
+ area = 0
+ for i in xrange(self._nrows_max - self._nrows_min + 1):
+
+ if self._sizes[i].x <= size.x and self._sizes[i].y <= size.y and \
+ GetSizeInOrientation(self._sizes[i], major_axis) > area:
+ area = GetSizeInOrientation(self._sizes[i], major_axis)
+ row_count = self._nrows_min + i
+ bestSize = wx.Size(*self._sizes[i])
+
+ return bestSize
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :return: An instance of :class:`Size`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self.GetMinSize()
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`RibbonToolBar`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+ """
+
+ # All painting done in main paint handler to minimise flicker
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`RibbonToolBar`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+
+ if self._art == None:
+ return
+
+ self._art.DrawToolBarBackground(dc, self, wx.Rect(0, 0, *self.GetSize()))
+
+ for group in self._groups:
+ tool_count = len(group.tools)
+
+ if tool_count != 0:
+ self._art.DrawToolGroupBackground(dc, self, wx.RectPS(group.position, group.size))
+
+ for tool in group.tools:
+ rect = wx.RectPS(group.position + tool.position, tool.size)
+
+ if tool.state & RIBBON_TOOLBAR_TOOL_DISABLED:
+ self._art.DrawTool(dc, self, rect, tool.bitmap_disabled, tool.kind, tool.state)
+ else:
+ self._art.DrawTool(dc, self, rect, tool.bitmap, tool.kind, tool.state)
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`RibbonToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ pos = event.GetPosition()
+ new_hover = None
+
+ for group in self._groups:
+
+ if group.position.x <= pos.x and pos.x < group.position.x + group.size.x \
+ and group.position.y <= pos.y and pos.y < group.position.y + group.size.y:
+ pos -= group.position
+
+ for tool in group.tools:
+ if tool.position.x <= pos.x and pos.x < tool.position.x + tool.size.x \
+ and tool.position.y <= pos.y and pos.y < tool.position.y + tool.size.y:
+ pos -= tool.position
+ new_hover = tool
+ break
+ break
+
+ if new_hover and new_hover != self._hover_tool:
+ self.SetToolTipString(new_hover.help_string)
+ elif self.GetToolTip() and new_hover != self._hover_tool:
+ self.SetToolTipString("")
+
+ if new_hover != self._hover_tool:
+ if self._hover_tool:
+ self._hover_tool.state &= ~(RIBBON_TOOLBAR_TOOL_HOVER_MASK | RIBBON_TOOLBAR_TOOL_ACTIVE_MASK)
+
+ self._hover_tool = new_hover
+
+ if new_hover:
+ what = RIBBON_TOOLBAR_TOOL_NORMAL_HOVERED
+ if new_hover.dropdown.Contains(pos):
+ what = RIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED
+
+ new_hover.state |= what
+
+ if new_hover == self._active_tool:
+
+ new_hover.state &= ~RIBBON_TOOLBAR_TOOL_ACTIVE_MASK
+ new_hover.state |= (what << 2)
+
+ self.Refresh(False)
+
+ elif self._hover_tool and self._hover_tool.kind == RIBBON_BUTTON_HYBRID:
+ newstate = self._hover_tool.state & ~RIBBON_TOOLBAR_TOOL_HOVER_MASK
+ what = RIBBON_TOOLBAR_TOOL_NORMAL_HOVERED
+
+ if self._hover_tool.dropdown.Contains(pos):
+ what = RIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED
+
+ newstate |= what
+
+ if newstate != self._hover_tool.state:
+ self._hover_tool.state = newstate
+ if self._hover_tool == self._active_tool:
+ self._hover_tool.state &= ~RIBBON_TOOLBAR_TOOL_ACTIVE_MASK
+ self._hover_tool.state |= (what << 2)
+
+ self.Refresh(False)
+
+
+ def OnMouseDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`RibbonToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.OnMouseMove(event)
+
+ if self._hover_tool:
+ self._active_tool = self._hover_tool
+ self._active_tool.state |= (self._active_tool.state & RIBBON_TOOLBAR_TOOL_HOVER_MASK) << 2
+ self.Refresh(False)
+
+
+ def OnMouseLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`RibbonToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._hover_tool:
+ self._hover_tool.state &= ~RIBBON_TOOLBAR_TOOL_HOVER_MASK
+ self._hover_tool = None
+ self.Refresh(False)
+
+
+ def OnMouseUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`RibbonToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._active_tool:
+ if self._active_tool.state & RIBBON_TOOLBAR_TOOL_ACTIVE_MASK:
+ evt_type = wxEVT_COMMAND_RIBBONTOOL_CLICKED
+ if self._active_tool.state & RIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE:
+ evt_type = wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED
+
+ notification = RibbonToolBarEvent(evt_type, self._active_tool.id)
+ notification.SetEventObject(self)
+ notification.SetBar(self)
+ self.ProcessEvent(notification)
+
+ if self._active_tool.kind == RIBBON_BUTTON_TOGGLE:
+ self._active_tool.state ^= RIBBON_BUTTONBAR_BUTTON_TOGGLED
+ notification.SetInt(self._active_tool.state & RIBBON_BUTTONBAR_BUTTON_TOGGLED)
+
+ # Notice that m_active_tool could have been reset by the event handler
+ # above so we need to test it again.
+ if self._active_tool:
+ self._active_tool.state &= ~RIBBON_TOOLBAR_TOOL_ACTIVE_MASK
+ self._active_tool = None
+ self.Refresh(False)
+
+
+ def OnMouseEnter(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`RibbonToolBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._active_tool and not event.LeftIsDown():
+ self._active_tool = None
+
+
+ def GetDefaultBorder(self):
+ """ Returns the default border style for :class:`RibbonToolBar`. """
+
+ return wx.BORDER_NONE
+
+
+ def UpdateWindowUI(self, flags):
+ """
+ This function sends one or more :class:`UpdateUIEvent` to the window.
+
+ The particular implementation depends on the window; for example a :class:`ToolBar` will
+ send an update UI event for each toolbar button, and a :class:`Frame` will send an
+ update UI event for each menubar menu item.
+
+ You can call this function from your application to ensure that your UI is up-to-date
+ at this point (as far as your :class:`UpdateUIEvent` handlers are concerned). This may be
+ necessary if you have called :meth:`UpdateUIEvent.SetMode` or :meth:`UpdateUIEvent.SetUpdateInterval`
+ to limit the overhead that wxWidgets incurs by sending update UI events in idle time.
+
+ :param integer `flags`: should be a bitlist of one or more of ``wx.UPDATE_UI_NONE``,
+ ``wx.UPDATE_UI_RECURSE`` or ``wx.UPDATE_UI_FROMIDLE``.
+
+ If you are calling this function from an `OnInternalIdle` or `OnIdle` function, make sure
+ you pass the ``wx.UPDATE_UI_FROMIDLE`` flag, since this tells the window to only update
+ the UI elements that need to be updated in idle time. Some windows update their elements
+ only when necessary, for example when a menu is about to be shown. The following is an
+ example of how to call :meth:`~RibbonToolBar.UpdateWindowUI` from an idle function::
+
+ def OnInternalIdle(self):
+
+ if wx.UpdateUIEvent.CanUpdate(self):
+ self.UpdateWindowUI(wx.UPDATE_UI_FROMIDLE)
+
+
+
+ .. versionadded:: 0.9.5
+ """
+
+ wx.PyControl.UpdateWindowUI(self, flags)
+
+ # don't waste time updating state of tools in a hidden toolbar
+ if not self.IsShown():
+ return
+
+ for group in self._groups:
+ for tool in group.tools:
+ id = tool.id
+
+ event = wx.UpdateUIEvent(id)
+ event.SetEventObject(self)
+
+ if self.ProcessWindowEvent(event):
+ if event.GetSetEnabled():
+ self.EnableTool(id, event.GetEnabled())
+ if event.GetSetChecked():
+ self.ToggleTool(id, event.GetChecked())
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/rulerctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/rulerctrl.py
new file mode 100644
index 0000000..e3c7332
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/rulerctrl.py
@@ -0,0 +1,1848 @@
+# --------------------------------------------------------------------------------- #
+# RULERCTRL wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 03 Nov 2006
+# Latest Revision: 17 Aug 2011, 15.00 GMT
+#
+#
+# TODO List
+#
+# 1. Any idea?
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@maerskoil.com
+# andrea.gavana@gmail.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`RulerCtrl` implements a ruler window that can be placed on top, bottom, left or right
+to any wxPython widget.
+
+
+Description
+===========
+
+:class:`RulerCtrl` implements a ruler window that can be placed on top, bottom, left or right
+to any wxPython widget. It is somewhat similar to the rulers you can find in text
+editors software, though not so powerful.
+
+:class:`RulerCtrl` has the following characteristics:
+
+- Can be horizontal or vertical;
+- 4 built-in formats: integer, real, time and linearDB formats;
+- Units (as ``cm``, ``dB``, ``inches``) can be displayed together with the label values;
+- Possibility to add a number of "paragraph indicators", small arrows that point at
+ the current indicator position;
+- Customizable background colour, tick colour, label colour;
+- Possibility to flip the ruler (i.e. changing the tick alignment);
+- Changing individually the indicator colour (requires PIL at the moment);
+- Different window borders are supported (``wx.STATIC_BORDER``, ``wx.SUNKEN_BORDER``,
+ ``wx.DOUBLE_BORDER``, ``wx.NO_BORDER``, ``wx.RAISED_BORDER``, ``wx.SIMPLE_BORDER``);
+- Logarithmic scale available;
+- Possibility to draw a thin line over a selected window when moving an indicator,
+ which emulates the text editors software.
+
+
+And a lot more. See the demo for a review of the functionalities.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.rulerctrl as RC
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "RulerCtrl Demo")
+
+ panel = wx.Panel(self)
+
+ text = wx.TextCtrl(panel, -1, "Hello World! wxPython rules", style=wx.TE_MULTILINE)
+
+ ruler1 = RC.RulerCtrl(panel, -1, orient=wx.HORIZONTAL, style=wx.SUNKEN_BORDER)
+ ruler2 = RC.RulerCtrl(panel, -1, orient=wx.VERTICAL, style=wx.SUNKEN_BORDER)
+
+ mainsizer = wx.BoxSizer(wx.HORIZONTAL)
+ leftsizer = wx.BoxSizer(wx.VERTICAL)
+ bottomleftsizer = wx.BoxSizer(wx.HORIZONTAL)
+ topsizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ leftsizer.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
+ topsizer.Add((39, 0), 0, wx.ADJUST_MINSIZE, 0)
+ topsizer.Add(ruler1, 1, wx.EXPAND, 0)
+ leftsizer.Add(topsizer, 0, wx.EXPAND, 0)
+
+ bottomleftsizer.Add((10, 0))
+ bottomleftsizer.Add(ruler2, 0, wx.EXPAND, 0)
+ bottomleftsizer.Add(text, 1, wx.EXPAND, 0)
+ leftsizer.Add(bottomleftsizer, 1, wx.EXPAND, 0)
+ mainsizer.Add(leftsizer, 3, wx.EXPAND, 0)
+
+ panel.SetSizer(mainsizer)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Events
+======
+
+:class:`RulerCtrl` implements the following events related to indicators:
+
+- ``EVT_INDICATOR_CHANGING``: the user is about to change the position of one indicator;
+- ``EVT_INDICATOR_CHANGED``: the user has changed the position of one indicator.
+
+
+Supported Platforms
+===================
+
+:class:`RulerCtrl` has been tested on the following platforms:
+ * Windows (Windows XP);
+ * Linux Ubuntu (Dapper 6.06)
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+========================== ==================================================
+Event Name Description
+========================== ==================================================
+``EVT_INDICATOR_CHANGED`` The user has changed the indicator value.
+``EVT_INDICATOR_CHANGING`` The user is about to change the indicator value.
+========================== ==================================================
+
+
+License And Version
+===================
+
+:class:`RulerCtrl` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 17 Aug 2011, 15.00 GMT
+
+Version 0.3
+
+"""
+
+__docformat__ = "epytext"
+
+
+import wx
+import math
+import cStringIO, zlib
+
+# Try to import PIL, if possible.
+# This is used only to change the colour for an indicator arrow.
+_hasPIL = False
+try:
+ import Image
+ _hasPIL = True
+except:
+ pass
+
+# Built-in formats
+IntFormat = 1
+""" Integer format. """
+RealFormat = 2
+""" Real format. """
+TimeFormat = 3
+""" Time format. """
+LinearDBFormat = 4
+""" Linear DB format. """
+HHMMSS_Format = 5
+""" HHMMSS format. """
+
+# Events
+wxEVT_INDICATOR_CHANGING = wx.NewEventType()
+wxEVT_INDICATOR_CHANGED = wx.NewEventType()
+
+EVT_INDICATOR_CHANGING = wx.PyEventBinder(wxEVT_INDICATOR_CHANGING, 2)
+""" The user is about to change the indicator value. """
+EVT_INDICATOR_CHANGED = wx.PyEventBinder(wxEVT_INDICATOR_CHANGED, 2)
+""" The user has changed the indicator value. """
+
+
+# Some accessor functions
+#----------------------------------------------------------------------
+
+def GetIndicatorData():
+ """ Returns the image indicator as a decompressed stream of characters. """
+
+ return zlib.decompress(
+'x\xda\x01x\x01\x87\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\n\x00\
+\x00\x00\n\x08\x06\x00\x00\x00\x8d2\xcf\xbd\x00\x00\x00\x04sBIT\x08\x08\x08\
+\x08|\x08d\x88\x00\x00\x01/IDAT\x18\x95m\xceO(\x83q\x1c\xc7\xf1\xf7\xef\xf9\
+\xcd\xf6D6\xca\x1c\xc8\x9f\x14\'J-\xc4A9(9(-\xe5 \xed\xe4\xe2\xe2\xb2\x928\
+\xb9\xec\xc2\x01\x17.\x0e\xe4\xe6B\xed\xb2\x1c\xdc$5\x97\xf9S\xb3\x14+\x0eO\
+\xdb\xccZ\x9e\xfd\xf9\xba\x98E{\x1d\xbf\xbd\xfb\xf4U\x00\x18\x9d\xc3\xad\x1d\
+\xa1+\xa7S\x15\xf8\xa1\xb5i\xbc\xc4\xd7\x0f\xca\xc5\xd82U3[\x97\xb1\x82\xc4S\
+"\x89\xb4\xc8SZ\xc4\xb2E\xfa\x06CR)\x1c\x00\xb8\x8cb"-|\x94@\x01\x0e\r\xee&\
+\xf8\x12\xc5\xdf\xd0\xd4\xf2\xf6i\x90/\x82\xe9\x82\xdb\xe72\xa7\xe7%\x92\x99\
+\xdfA\xb4j\x9b]\xa5\xaek\xbag|\xaa\xdd\xca)\xceb\x10\xbe\x87\xacm VT\xd0N\
+\x0f\xf9\xd7\x94\xd6\xde\xb1\xdd\xf9\xcdm_\x83\xdb\x81\x95W\x88\x02\xad\x159\
+\x01\xcc!U2}\xa3$\x0f\x1dZR\xd1\xfd\xbb\x9b\xc7\x89\xc99\x7f\xb7\xb7\xd1\x00\
+\xc0.B\xbe\xac\xc8\xbe?P\x8e\x8c\x1ccg\x02\xd5\x1f\x9a\x07\xf6\x82a[6.D\xfc\
+\'"\x9e\xc0\xb5\xa0\xeb\xd7\xa8\xc9\xdd\xbf\xb3pdI\xefRD\xc0\x08\xd6\x8e*\\-\
++\xa0\x17\xff\x9f\xbf\x01{\xb5t\x9e\x99]a\x97\x00\x00\x00\x00IEND\xaeB`\x82G\
+\xbf\xa8>' )
+
+
+def GetIndicatorBitmap():
+ """ Returns the image indicator as a :class:`Bitmap`. """
+
+ return wx.BitmapFromImage(GetIndicatorImage())
+
+
+def GetIndicatorImage():
+ """ Returns the image indicator as a :class:`Image`. """
+
+ stream = cStringIO.StringIO(GetIndicatorData())
+ return wx.ImageFromStream(stream)
+
+
+def MakePalette(tr, tg, tb):
+ """
+ Creates a palette to be applied on an image based on input colour.
+
+ :param `tr`: the red intensity of the input colour;
+ :param `tg`: the green intensity of the input colour;
+ :param `tb`: the blue intensity of the input colour.
+ """
+
+ l = []
+ for i in range(255):
+ l.extend([tr*i / 255, tg*i / 255, tb*i / 255])
+
+ return l
+
+
+def ConvertWXToPIL(bmp):
+ """
+ Converts a :class:`Image` into a PIL image.
+
+ :param `bmp`: an instance of :class:`Image`.
+
+ :note: Requires PIL (Python Imaging Library), which can be downloaded from
+ http://www.pythonware.com/products/pil/
+ """
+
+ width = bmp.GetWidth()
+ height = bmp.GetHeight()
+ img = Image.fromstring("RGBA", (width, height), bmp.GetData())
+
+ return img
+
+
+def ConvertPILToWX(pil, alpha=True):
+ """
+ Converts a PIL image into a :class:`Image`.
+
+ :param `pil`: a PIL image;
+ :param `alpha`: ``True`` if the image contains alpha transparency, ``False``
+ otherwise.
+
+ :note: Requires PIL (Python Imaging Library), which can be downloaded from
+ http://www.pythonware.com/products/pil/
+ """
+
+ if alpha:
+ image = apply(wx.EmptyImage, pil.size)
+ image.SetData(pil.convert("RGB").tostring())
+ image.SetAlphaData(pil.convert("RGBA").tostring()[3::4])
+ else:
+ image = wx.EmptyImage(pil.size[0], pil.size[1])
+ new_image = pil.convert('RGB')
+ data = new_image.tostring()
+ image.SetData(data)
+
+ return image
+
+# ---------------------------------------------------------------------------- #
+# Class RulerCtrlEvent
+# ---------------------------------------------------------------------------- #
+
+class RulerCtrlEvent(wx.PyCommandEvent):
+ """
+ Represent details of the events that the :class:`RulerCtrl` object sends.
+ """
+
+ def __init__(self, eventType, eventId=1):
+ """
+ Default class constructor.
+
+ :param `eventType`: the event type;
+ :param `eventId`: the event identifier.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+
+
+ def SetValue(self, value):
+ """
+ Sets the event value.
+
+ :param `value`: the new indicator position.
+ """
+
+ self._value = value
+
+
+ def GetValue(self):
+ """ Returns the event value. """
+
+ return self._value
+
+
+ def SetOldValue(self, oldValue):
+ """
+ Sets the event old value.
+
+ :param `value`: the old indicator position.
+ """
+
+ self._oldValue = oldValue
+
+
+ def GetOldValue(self):
+ """ Returns the event old value. """
+
+ return self._oldValue
+
+
+# ---------------------------------------------------------------------------- #
+# Class Label
+# ---------------------------------------------------------------------------- #
+
+class Label(object):
+ """
+ Auxilary class. Just holds information about a label in :class:`RulerCtrl`.
+ """
+
+ def __init__(self, pos=-1, lx=-1, ly=-1, text=""):
+ """
+ Default class constructor.
+
+ :param `pos`: the indicator position;
+ :param `lx`: the indicator `x` coordinate;
+ :param `ly`: the indicator `y` coordinate;
+ :param `text`: the label text.
+ """
+
+ self.pos = pos
+ self.lx = lx
+ self.ly = ly
+ self.text = text
+
+
+# ---------------------------------------------------------------------------- #
+# Class Indicator
+# ---------------------------------------------------------------------------- #
+
+class Indicator(object):
+ """
+ This class holds all the information about a single indicator inside :class:`RulerCtrl`.
+
+ You should not call this class directly. Use::
+
+ ruler.AddIndicator(id, value)
+
+
+ to add an indicator to your :class:`RulerCtrl`.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, value=0):
+ """
+ Default class constructor.
+
+ :param `parent`: the parent window, an instance of :class:`RulerCtrl`;
+ :param `id`: the indicator identifier;
+ :param `value`: the initial value of the indicator.
+ """
+
+ self._parent = parent
+ if id == wx.ID_ANY:
+ id = wx.NewId()
+
+ self._id = id
+ self._colour = None
+
+ self.RotateImage(GetIndicatorImage())
+ self.SetValue(value)
+
+
+ def GetPosition(self):
+ """ Returns the position at which we should draw the indicator bitmap. """
+
+ orient = self._parent._orientation
+ flip = self._parent._flip
+ left, top, right, bottom = self._parent.GetBounds()
+ minval = self._parent._min
+ maxval = self._parent._max
+
+ value = self._value
+
+ if self._parent._log:
+ value = math.log10(value)
+ maxval = math.log10(maxval)
+ minval = math.log10(minval)
+
+ pos = float(value-minval)/abs(maxval - minval)
+
+ if orient == wx.HORIZONTAL:
+ xpos = int(pos*right) - self._img.GetWidth()/2
+ if flip:
+ ypos = top
+ else:
+ ypos = bottom - self._img.GetHeight()
+ else:
+ ypos = int(pos*bottom) - self._img.GetHeight()/2
+ if flip:
+ xpos = left
+ else:
+ xpos = right - self._img.GetWidth()
+
+ return xpos, ypos
+
+
+ def GetImageSize(self):
+ """ Returns the indicator bitmap size. """
+
+ return self._img.GetWidth(), self._img.GetHeight()
+
+
+ def GetRect(self):
+ """ Returns the indicator client rectangle. """
+
+ return self._rect
+
+
+ def RotateImage(self, img=None):
+ """
+ Rotates the default indicator bitmap.
+
+ :param `img`: if not ``None``, the indicator image.
+ """
+
+ if img is None:
+ img = GetIndicatorImage()
+
+ orient = self._parent._orientation
+ flip = self._parent._flip
+ left, top, right, bottom = self._parent.GetBounds()
+
+ if orient == wx.HORIZONTAL:
+ if flip:
+ img = img.Rotate(math.pi, (5, 5), True)
+ else:
+ if flip:
+ img = img.Rotate(-math.pi/2, (5, 5), True)
+ else:
+ img = img.Rotate(math.pi/2, (5, 5), True)
+
+ self._img = img
+
+
+ def SetValue(self, value):
+ """
+ Sets the indicator value.
+
+ :param `value`: the new indicator value.
+ """
+
+ if value < self._parent._min:
+ value = self._parent._min
+ if value > self._parent._max:
+ value = self._parent._max
+
+ self._value = value
+ self._rect = wx.Rect()
+
+ self._parent.Refresh()
+
+
+ def GetValue(self):
+ """ Returns the indicator value. """
+
+ return self._value
+
+
+ def Draw(self, dc):
+ """
+ Actually draws the indicator.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ xpos, ypos = self.GetPosition()
+ bmp = wx.BitmapFromImage(self._img)
+ dc.DrawBitmap(bmp, xpos, ypos, True)
+ self._rect = wx.Rect(xpos, ypos, self._img.GetWidth(), self._img.GetHeight())
+
+
+ def GetId(self):
+ """ Returns the indicator id. """
+
+ return self._id
+
+
+ def SetColour(self, colour):
+ """
+ Sets the indicator colour.
+
+ :param `colour`: the new indicator colour, an instance of :class:`Colour`.
+
+ :note: Requires PIL (Python Imaging Library), which can be downloaded from
+ http://www.pythonware.com/products/pil/
+ """
+
+ if not _hasPIL:
+ return
+
+ palette = colour.Red(), colour.Green(), colour.Blue()
+
+ img = ConvertWXToPIL(GetIndicatorBitmap())
+ l = MakePalette(*palette)
+ # The Palette Can Be Applied Only To "L" And "P" Images, Not "RGBA"
+ img = img.convert("L")
+ # Apply The New Palette
+ img.putpalette(l)
+ # Convert The Image Back To RGBA
+ img = img.convert("RGBA")
+ img = ConvertPILToWX(img)
+ self.RotateImage(img)
+
+ self._parent.Refresh()
+
+
+# ---------------------------------------------------------------------------- #
+# Class RulerCtrl
+# ---------------------------------------------------------------------------- #
+
+class RulerCtrl(wx.PyPanel):
+ """
+ :class:`RulerCtrl` implements a ruler window that can be placed on top, bottom, left or right
+ to any wxPython widget. It is somewhat similar to the rulers you can find in text
+ editors software, though not so powerful.
+ """
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.STATIC_BORDER, orient=wx.HORIZONTAL):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `orient`: sets the orientation of the :class:`RulerCtrl`, and can be either
+ ``wx.HORIZONTAL`` of ``wx.VERTICAL``.
+ """
+
+ wx.PyPanel.__init__(self, parent, id, pos, size, style)
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+ width, height = size
+
+ self._min = 0.0
+ self._max = 10.0
+ self._orientation = orient
+ self._spacing = 5
+ self._hassetspacing = False
+ self._format = RealFormat
+ self._flip = False
+ self._log = False
+ self._labeledges = False
+ self._units = ""
+
+ self._drawingparent = None
+ self._drawingpen = wx.Pen(wx.BLACK, 2)
+
+ self._left = -1
+ self._top = -1
+ self._right = -1
+ self._bottom = -1
+
+ self._major = 1
+ self._minor = 1
+
+ self._indicators = []
+ self._currentIndicator = None
+
+ fontsize = 10
+ if wx.Platform == "__WXMSW__":
+ fontsize = 8
+
+ self._minorfont = wx.Font(fontsize, wx.SWISS, wx.NORMAL, wx.NORMAL)
+ self._majorfont = wx.Font(fontsize, wx.SWISS, wx.NORMAL, wx.BOLD)
+
+ if wx.Platform == "__WXMAC__":
+ self._minorfont.SetNoAntiAliasing(True)
+ self._majorfont.SetNoAntiAliasing(True)
+
+ self._bits = []
+ self._userbits = []
+ self._userbitlen = 0
+ self._tickmajor = True
+ self._tickminor = True
+ self._timeformat = IntFormat
+ self._labelmajor = True
+ self._labelminor = True
+ self._tickpen = wx.Pen(wx.BLACK)
+ self._textcolour = wx.BLACK
+ self._background = wx.WHITE
+
+ self._valid = False
+ self._state = 0
+
+ self._style = style
+ self._orientation = orient
+ wbound, hbound = self.CheckStyle()
+
+ if orient & wx.VERTICAL:
+ self.SetBestSize((28, height))
+ else:
+ self.SetBestSize((width, 28))
+
+ self.SetBounds(0, 0, wbound, hbound)
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvents)
+ self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, lambda evt: True)
+
+
+ def OnMouseEvents(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` event for :class:`RulerCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self._indicators:
+ event.Skip()
+ return
+
+ mousePos = event.GetPosition()
+
+ if event.LeftDown():
+ self.CaptureMouse()
+ self.GetIndicator(mousePos)
+ self._mousePosition = mousePos
+ self.SetIndicatorValue(sendEvent=False)
+ elif event.Dragging() and self._currentIndicator:
+ self._mousePosition = mousePos
+ self.SetIndicatorValue()
+ elif event.LeftUp():
+ if self.HasCapture():
+ self.ReleaseMouse()
+ self.SetIndicatorValue(sendEvent=False)
+ if self._drawingparent:
+ self._drawingparent.Refresh()
+ self._currentIndicator = None
+ #else:
+ # self._currentIndicator = None
+
+ event.Skip()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`RulerCtrl`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+ dc.SetBackground(wx.Brush(self._background))
+ dc.Clear()
+ self.Draw(dc)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`RulerCtrl`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ width, height = self.CheckStyle()
+ self.SetBounds(0, 0, width, height)
+
+ self.Invalidate()
+ event.Skip()
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`RulerCtrl`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def SetIndicatorValue(self, sendEvent=True):
+ """
+ Sets the indicator value.
+
+ :param `sendEvent`: ``True`` to send a :class:`RulerCtrlEvent`, ``False`` otherwise.
+ """
+
+ if self._currentIndicator is None:
+ return
+
+ left, top, right, bottom = self.GetBounds()
+
+ x = self._mousePosition.x
+ y = self._mousePosition.y
+
+ maxvalue = self._max
+ minvalue = self._min
+
+ if self._log:
+ minvalue = math.log10(minvalue)
+ maxvalue = math.log10(maxvalue)
+
+ deltarange = abs(self._max - self._min)
+
+ if self._orientation == wx.HORIZONTAL: # only x moves
+ value = deltarange*float(x)/(right - left)
+ else:
+ value = deltarange*float(y)/(bottom - top)
+
+ value += minvalue
+
+ if self._log:
+ value = 10**value
+
+ if value < self._min or value > self._max:
+ return
+
+ self.DrawOnParent(self._currentIndicator)
+
+ if sendEvent:
+ event = RulerCtrlEvent(wxEVT_INDICATOR_CHANGING, self._currentIndicator.GetId())
+ event.SetOldValue(self._currentIndicator.GetValue())
+
+ event.SetValue(value)
+ event.SetEventObject(self)
+
+ if self.GetEventHandler().ProcessEvent(event):
+ self.DrawOnParent(self._currentIndicator)
+ return
+
+ self._currentIndicator.SetValue(value)
+
+ if sendEvent:
+ event.SetEventType(wxEVT_INDICATOR_CHANGED)
+ event.SetOldValue(value)
+ self.GetEventHandler().ProcessEvent(event)
+ self.DrawOnParent(self._currentIndicator)
+
+ self.Refresh()
+
+
+ def GetIndicator(self, mousePos):
+ """
+ Returns the indicator located at the mouse position `mousePos` (if any).
+
+ :param `mousePos`: the mouse position, an instance of :class:`Point`.
+ """
+
+ for indicator in self._indicators:
+ if indicator.GetRect().Contains(mousePos):
+ self._currentIndicator = indicator
+ break
+
+
+ def CheckStyle(self):
+ """ Adjust the :class:`RulerCtrl` style accordingly to borders, units, etc..."""
+
+ width, height = self.GetSize()
+
+ if self._orientation & wx.HORIZONTAL:
+ if self._style & wx.NO_BORDER:
+ hbound = 28
+ wbound = width-1
+ elif self._style & wx.SIMPLE_BORDER:
+ hbound = 27
+ wbound = width-1
+ elif self._style & wx.STATIC_BORDER:
+ hbound = 26
+ wbound = width-3
+ elif self._style & wx.SUNKEN_BORDER:
+ hbound = 24
+ wbound = width-5
+ elif self._style & wx.RAISED_BORDER:
+ hbound = 22
+ wbound = width-7
+ elif self._style & wx.DOUBLE_BORDER:
+ hbound = 22
+ wbound = width-7
+ else:
+ if self._style & wx.NO_BORDER:
+ wbound = 28
+ hbound = height-1
+ elif self._style & wx.SIMPLE_BORDER:
+ wbound = 27
+ hbound = height-1
+ elif self._style & wx.STATIC_BORDER:
+ wbound = 26
+ hbound = height-3
+ elif self._style & wx.SUNKEN_BORDER:
+ wbound = 24
+ hbound = height-5
+ elif self._style & wx.RAISED_BORDER:
+ wbound = 22
+ hbound = height-7
+ elif self._style & wx.DOUBLE_BORDER:
+ wbound = 22
+ hbound = height-7
+
+ minText = self.LabelString(self._min, major=True)
+ maxText = self.LabelString(self._max, major=True)
+
+ dc = wx.ClientDC(self)
+ minWidth, minHeight = dc.GetTextExtent(minText)
+ maxWidth, maxHeight = dc.GetTextExtent(maxText)
+
+ maxWidth = max(maxWidth, minWidth)
+ maxHeight = max(maxHeight, minHeight)
+
+ if self._orientation == wx.HORIZONTAL:
+ if maxHeight + 4 > hbound:
+ hbound = maxHeight
+ self.SetBestSize((-1, maxHeight + 4))
+ if self.GetContainingSizer():
+ self.GetContainingSizer().Layout()
+ else:
+ if maxWidth + 4 > wbound:
+ wbound = maxWidth
+ self.SetBestSize((maxWidth + 4, -1))
+ if self.GetContainingSizer():
+ self.GetContainingSizer().Layout()
+
+ return wbound, hbound
+
+
+ def TickMajor(self, tick=True):
+ """
+ Sets whether the major ticks should be ticked or not.
+
+ :param `tick`: ``True`` to show major ticks, ``False`` otherwise.
+ """
+
+ if self._tickmajor != tick:
+ self._tickmajor = tick
+ self.Invalidate()
+
+
+ def TickMinor(self, tick=True):
+ """
+ Sets whether the minor ticks should be ticked or not.
+
+ :param `tick`: ``True`` to show minor ticks, ``False`` otherwise.
+ """
+
+ if self._tickminor != tick:
+ self._tickminor = tick
+ self.Invalidate()
+
+
+ def LabelMinor(self, label=True):
+ """
+ Sets whether the minor ticks should be labeled or not.
+
+ :param `label`: ``True`` to label minor ticks, ``False`` otherwise.
+ """
+
+ if self._labelminor != label:
+ self._labelminor = label
+ self.Invalidate()
+
+
+ def LabelMajor(self, label=True):
+ """
+ Sets whether the major ticks should be labeled or not.
+
+ :param `label`: ``True`` to label major ticks, ``False`` otherwise.
+ """
+
+ if self._labelmajor != label:
+ self._labelmajor = label
+ self.Invalidate()
+
+
+ def GetTimeFormat(self):
+ """ Returns the time format. """
+
+ return self._timeformat
+
+
+ def SetTimeFormat(self, format=TimeFormat):
+ """
+ Sets the time format.
+
+ :param `format`: the format used to display time values.
+ """
+
+ if self._timeformat != format:
+ self._timeformat = format
+ self.Invalidate()
+
+
+ def SetFormat(self, format):
+ """
+ Sets the format for :class:`RulerCtrl`.
+
+ :param `format`: the format used to display values in :class:`RulerCtrl`. This can be
+ one of the following bits:
+
+ ====================== ======= ==============================
+ Format Value Description
+ ====================== ======= ==============================
+ ``IntFormat`` 1 Integer format
+ ``RealFormat`` 2 Real format
+ ``TimeFormat`` 3 Time format
+ ``LinearDBFormat`` 4 Linear DB format
+ ``HHMMSS_Format`` 5 HHMMSS format
+ ====================== ======= ==============================
+ """
+
+ if self._format != format:
+ self._format = format
+ self.Invalidate()
+
+
+ def GetFormat(self):
+ """
+ Returns the format used to display values in :class:`RulerCtrl`.
+
+ :see: :meth:`RulerCtrl.SetFormat` for a list of possible formats.
+ """
+
+ return self._format
+
+
+ def SetLog(self, log=True):
+ """
+ Sets whether :class:`RulerCtrl` should have a logarithmic scale or not.
+
+ :param `log`: ``True`` to use a logarithmic scake, ``False`` to use a
+ linear one.
+ """
+
+ if self._log != log:
+ self._log = log
+ self.Invalidate()
+
+
+ def SetUnits(self, units):
+ """
+ Sets the units that should be displayed beside the labels.
+
+ :param `units`: the units that should be displayed beside the labels.
+ """
+
+ # Specify the name of the units (like "dB") if you
+ # want numbers like "1.6" formatted as "1.6 dB".
+
+ if self._units != units:
+ self._units = units
+ self.Invalidate()
+
+
+ def SetBackgroundColour(self, colour):
+ """
+ Sets the :class:`RulerCtrl` background colour.
+
+ :param `colour`: an instance of :class:`Colour`.
+
+ :note: Overridden from :class:`PyPanel`.
+ """
+
+ self._background = colour
+ wx.PyPanel.SetBackgroundColour(self, colour)
+ self.Refresh()
+
+
+ def SetOrientation(self, orient=None):
+ """
+ Sets the :class:`RulerCtrl` orientation.
+
+ :param `orient`: can be ``wx.HORIZONTAL`` or ``wx.VERTICAL``.
+ """
+
+ if orient is None:
+ orient = wx.HORIZONTAL
+
+ if self._orientation != orient:
+ self._orientation = orient
+
+ if self._orientation == wx.VERTICAL and not self._hassetspacing:
+ self._spacing = 2
+
+ self.Invalidate()
+
+
+ def SetRange(self, minVal, maxVal):
+ """
+ Sets the :class:`RulerCtrl` range.
+
+ :param `minVal`: the minimum value of :class:`RulerCtrl`;
+ :param `maxVal`: the maximum value of :class:`RulerCtrl`.
+ """
+
+ # For a horizontal ruler,
+ # minVal is the value in the center of pixel "left",
+ # maxVal is the value in the center of pixel "right".
+
+ if self._min != minVal or self._max != maxVal:
+ self._min = minVal
+ self._max = maxVal
+ self.Invalidate()
+
+
+ def SetSpacing(self, spacing):
+ """
+ Sets the :class:`RulerCtrl` spacing between labels.
+
+ :param `spacing`: the spacing between labels, in pixels.
+ """
+
+ self._hassetspacing = True
+
+ if self._spacing != spacing:
+ self._spacing = spacing
+ self.Invalidate()
+
+
+ def SetLabelEdges(self, labelEdges=True):
+ """
+ Sets whether the edge values should always be displayed or not.
+
+ :param `labelEdges`: ``True`` to always display edge labels, ``False`` otherwise/
+ """
+
+ # If this is True, the edges of the ruler will always
+ # receive a label. If not, the nearest round number is
+ # labeled (which may or may not be the edge).
+
+ if self._labeledges != labelEdges:
+ self._labeledges = labelEdges
+ self.Invalidate()
+
+
+ def SetFlip(self, flip=True):
+ """
+ Sets whether the orientation of the tick marks should be reversed.
+
+ :param `flip`: ``True`` to reverse the orientation of the tick marks, ``False``
+ otherwise.
+ """
+
+ # If this is True, the orientation of the tick marks
+ # is reversed from the default eg. above the line
+ # instead of below
+
+ if self._flip != flip:
+ self._flip = flip
+ self.Invalidate()
+ for indicator in self._indicators:
+ indicator.RotateImage()
+
+
+ def SetFonts(self, minorFont, majorFont):
+ """
+ Sets the fonts for minor and major tick labels.
+
+ :param `minorFont`: the font used to draw minor ticks, a valid :class:`Font` object;
+ :param `majorFont`: the font used to draw major ticks, a valid :class:`Font` object.
+ """
+
+ self._minorfont = minorFont
+ self._majorfont = majorFont
+
+ if wx.Platform == "__WXMAC__":
+ self._minorfont.SetNoAntiAliasing(True)
+ self._majorfont.SetNoAntiAliasing(True)
+
+ self.Invalidate()
+
+
+ def SetTickPenColour(self, colour=wx.BLACK):
+ """
+ Sets the pen colour to draw the ticks.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._tickpen = wx.Pen(colour)
+ self.Refresh()
+
+
+ def SetLabelColour(self, colour=wx.BLACK):
+ """
+ Sets the labels colour.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ self._textcolour = colour
+ self.Refresh()
+
+
+ def OfflimitsPixels(self, start, end):
+ """ Used internally. """
+
+ if not self._userbits:
+ if self._orientation == wx.HORIZONTAL:
+ self._length = self._right-self._left
+ else:
+ self._length = self._bottom-self._top
+
+ self._userbits = [0]*self._length
+ self._userbitlen = self._length+1
+
+ if end < start:
+ i = end
+ end = start
+ start = i
+
+ if start < 0:
+ start = 0
+ if end > self._length:
+ end = self._length
+
+ for ii in xrange(start, end+1):
+ self._userbits[ii] = 1
+
+
+ def SetBounds(self, left, top, right, bottom):
+ """
+ Sets the bounds for :class:`RulerCtrl` (its client rectangle).
+
+ :param `left`: the left corner of the client rectangle;
+ :param `top`: the top corner of the client rectangle;
+ :param `right`: the right corner of the client rectangle;
+ :param `bottom`: the bottom corner of the client rectangle.
+ """
+
+ if self._left != left or self._top != top or self._right != right or \
+ self._bottom != bottom:
+
+ self._left = left
+ self._top = top
+ self._right = right
+ self._bottom = bottom
+
+ self.Invalidate()
+
+
+ def GetBounds(self):
+ """ Returns the :class:`RulerCtrl` bounds (its client rectangle). """
+
+ return self._left, self._top, self._right, self._bottom
+
+
+ def AddIndicator(self, id, value):
+ """
+ Adds an indicator to :class:`RulerCtrl`. You should pass a unique `id` and a starting
+ `value` for the indicator.
+
+ :param `id`: the indicator identifier;
+ :param `value`: the indicator initial value.
+ """
+
+ self._indicators.append(Indicator(self, id, value))
+ self.Refresh()
+
+
+ def SetIndicatorColour(self, id, colour=None):
+ """
+ Sets the indicator colour.
+
+ :param `id`: the indicator identifier;
+ :param `colour`: a valid :class:`Colour` object.
+
+ :note: This method requires PIL to change the image palette.
+ """
+
+ if not _hasPIL:
+ return
+
+ if colour is None:
+ colour = wx.WHITE
+
+ for indicator in self._indicators:
+ if indicator.GetId() == id:
+ indicator.SetColour(colour)
+ break
+
+
+ def Invalidate(self):
+ """ Invalidates the ticks calculations. """
+
+ self._valid = False
+
+ if self._orientation == wx.HORIZONTAL:
+ self._length = self._right - self._left
+ else:
+ self._length = self._bottom - self._top
+
+ self._majorlabels = []
+ self._minorlabels = []
+ self._bits = []
+ self._userbits = []
+ self._userbitlen = 0
+ self.Refresh()
+
+
+ def FindLinearTickSizes(self, UPP):
+ """ Used internally. """
+
+ # Given the dimensions of the ruler, the range of values it
+ # has to display, and the format (i.e. Int, Real, Time),
+ # figure out how many units are in one Minor tick, and
+ # in one Major tick.
+ #
+ # The goal is to always put tick marks on nice round numbers
+ # that are easy for humans to grok. This is the most tricky
+ # with time.
+
+ # As a heuristic, we want at least 16 pixels
+ # between each minor tick
+ units = 16.0*abs(UPP)
+
+ self._digits = 0
+
+ if self._format == LinearDBFormat:
+
+ if units < 0.1:
+ self._minor = 0.1
+ self._major = 0.5
+ return
+
+ if units < 1.0:
+ self._minor = 1.0
+ self._major = 6.0
+ return
+
+ self._minor = 3.0
+ self._major = 12.0
+ return
+
+ elif self._format == IntFormat:
+
+ d = 1.0
+ while 1:
+ if units < d:
+ self._minor = d
+ self._major = d*5.0
+ return
+
+ d = d*5.0
+ if units < d:
+ self._minor = d
+ self._major = d*2.0
+ return
+
+ d = 2.0*d
+
+ elif self._format == TimeFormat:
+
+ if units > 0.5:
+ if units < 1.0: # 1 sec
+ self._minor = 1.0
+ self._major = 5.0
+ return
+
+ if units < 5.0: # 5 sec
+ self._minor = 5.0
+ self._major = 15.0
+ return
+
+ if units < 10.0:
+ self._minor = 10.0
+ self._major = 30.0
+ return
+
+ if units < 15.0:
+ self._minor = 15.0
+ self._major = 60.0
+ return
+
+ if units < 30.0:
+ self._minor = 30.0
+ self._major = 60.0
+ return
+
+ if units < 60.0: # 1 min
+ self._minor = 60.0
+ self._major = 300.0
+ return
+
+ if units < 300.0: # 5 min
+ self._minor = 300.0
+ self._major = 900.0
+ return
+
+ if units < 600.0: # 10 min
+ self._minor = 600.0
+ self._major = 1800.0
+ return
+
+ if units < 900.0: # 15 min
+ self._minor = 900.0
+ self._major = 3600.0
+ return
+
+ if units < 1800.0: # 30 min
+ self._minor = 1800.0
+ self._major = 3600.0
+ return
+
+ if units < 3600.0: # 1 hr
+ self._minor = 3600.0
+ self._major = 6*3600.0
+ return
+
+ if units < 6*3600.0: # 6 hrs
+ self._minor = 6*3600.0
+ self._major = 24*3600.0
+ return
+
+ if units < 24*3600.0: # 1 day
+ self._minor = 24*3600.0
+ self._major = 7*24*3600.0
+ return
+
+ self._minor = 24.0*7.0*3600.0 # 1 week
+ self._major = 24.0*7.0*3600.0
+
+ # Otherwise fall through to RealFormat
+ # (fractions of a second should be dealt with
+ # the same way as for RealFormat)
+
+ elif self._format == RealFormat:
+
+ d = 0.000001
+ self._digits = 6
+
+ while 1:
+ if units < d:
+ self._minor = d
+ self._major = d*5.0
+ return
+
+ d = d*5.0
+ if units < d:
+ self._minor = d
+ self._major = d*2.0
+ return
+
+ d = d*2.0
+ self._digits = self._digits - 1
+
+
+ def LabelString(self, d, major=None):
+ """ Used internally. """
+
+ # Given a value, turn it into a string according
+ # to the current ruler format. The number of digits of
+ # accuracy depends on the resolution of the ruler,
+ # i.e. how far zoomed in or out you are.
+
+ s = ""
+
+ if d < 0.0 and d + self._minor > 0.0:
+ d = 0.0
+
+ if self._format == IntFormat:
+ s = "%d"%int(math.floor(d+0.5))
+
+ elif self._format == LinearDBFormat:
+ if self._minor >= 1.0:
+ s = "%d"%int(math.floor(d+0.5))
+ else:
+ s = "%0.1f"%d
+
+ elif self._format == RealFormat:
+ if self._minor >= 1.0:
+ s = "%d"%int(math.floor(d+0.5))
+ else:
+ s = (("%." + str(self._digits) + "f")%d).strip()
+
+ elif self._format == TimeFormat:
+ if major:
+ if d < 0:
+ s = "-"
+ d = -d
+
+ if self.GetTimeFormat() == HHMMSS_Format:
+
+ secs = int(d + 0.5)
+ if self._minor >= 1.0:
+ s = ("%d:%02d:%02d")%(secs/3600, (secs/60)%60, secs%60)
+
+ else:
+ t1 = ("%d:%02d:")%(secs/3600, (secs/60)%60)
+ format = "%" + "%0d.%dlf"%(self._digits+3, self._digits)
+ t2 = format%(d%60.0)
+ s = s + t1 + t2
+
+ else:
+
+ if self._minor >= 3600.0:
+ hrs = int(d/3600.0 + 0.5)
+ h = "%d:00:00"%hrs
+ s = s + h
+
+ elif self._minor >= 60.0:
+ minutes = int(d/60.0 + 0.5)
+ if minutes >= 60:
+ m = "%d:%02d:00"%(minutes/60, minutes%60)
+ else:
+ m = "%d:00"%minutes
+
+ s = s + m
+
+ elif self._minor >= 1.0:
+ secs = int(d + 0.5)
+ if secs >= 3600:
+ t = "%d:%02d:%02d"%(secs/3600, (secs/60)%60, secs%60)
+ elif secs >= 60:
+ t = "%d:%02d"%(secs/60, secs%60)
+ else:
+ t = "%d"%secs
+
+ s = s + t
+
+ else:
+ secs = int(d)
+ if secs >= 3600:
+ t1 = "%d:%02d:"%(secs/3600, (secs/60)%60)
+ elif secs >= 60:
+ t1 = "%d:"%(secs/60)
+
+ if secs >= 60:
+ format = "%%0%d.%dlf"%(self._digits+3, self._digits)
+ else:
+ format = "%%%d.%dlf"%(self._digits+3, self._digits)
+
+ t2 = format%(d%60.0)
+
+ s = s + t1 + t2
+
+ if self._units != "":
+ s = s + " " + self._units
+
+ return s
+
+
+ def Tick(self, dc, pos, d, major):
+ """
+ Ticks a particular position.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `pos`: the label position;
+ :param `d`: the current label value;
+ :param `major`: ``True`` if it is a major ticks, ``False`` if it is a minor one.
+ """
+
+ if major:
+ label = Label()
+ self._majorlabels.append(label)
+ else:
+ label = Label()
+ self._minorlabels.append(label)
+
+ label.pos = pos
+ label.lx = self._left - 2000 # don't display
+ label.ly = self._top - 2000 # don't display
+ label.text = ""
+
+ dc.SetFont((major and [self._majorfont] or [self._minorfont])[0])
+
+ l = self.LabelString(d, major)
+ strw, strh = dc.GetTextExtent(l)
+
+ if self._orientation == wx.HORIZONTAL:
+ strlen = strw
+ strpos = pos - strw/2
+ if strpos < 0:
+ strpos = 0
+ if strpos + strw >= self._length:
+ strpos = self._length - strw
+ strleft = self._left + strpos
+ if self._flip:
+ strtop = self._top + 4
+ self._maxheight = max(self._maxheight, 4 + strh)
+ else:
+ strtop = self._bottom - strh - 6
+ self._maxheight = max(self._maxheight, strh + 6)
+
+ else:
+ strlen = strh
+ strpos = pos - strh/2
+ if strpos < 0:
+ strpos = 0
+ if strpos + strh >= self._length:
+ strpos = self._length - strh
+ strtop = self._top + strpos
+ if self._flip:
+ strleft = self._left + 5
+ self._maxwidth = max(self._maxwidth, 5 + strw)
+ else:
+ strleft = self._right - strw - 6
+ self._maxwidth = max(self._maxwidth, strw + 6)
+
+ # See if any of the pixels we need to draw this
+ # label is already covered
+
+ if major and self._labelmajor or not major and self._labelminor:
+ for ii in xrange(strlen):
+ if self._bits[strpos+ii]:
+ return
+
+ # If not, position the label and give it text
+
+ label.lx = strleft
+ label.ly = strtop
+ label.text = l
+
+ if major:
+ if self._tickmajor and not self._labelmajor:
+ label.text = ""
+ self._majorlabels[-1] = label
+
+ else:
+ if self._tickminor and not self._labelminor:
+ label.text = ""
+ label.text = label.text.replace(self._units, "")
+ self._minorlabels[-1] = label
+
+ # And mark these pixels, plus some surrounding
+ # ones (the spacing between labels), as covered
+
+ if (not major and self._labelminor) or (major and self._labelmajor):
+
+ leftmargin = self._spacing
+
+ if strpos < leftmargin:
+ leftmargin = strpos
+
+ strpos = strpos - leftmargin
+ strlen = strlen + leftmargin
+
+ rightmargin = self._spacing
+
+ if strpos + strlen > self._length - self._spacing:
+ rightmargin = self._length - strpos - strlen
+
+ strlen = strlen + rightmargin
+
+ for ii in xrange(strlen):
+ self._bits[strpos+ii] = 1
+
+
+ def Update(self, dc):
+ """
+ Updates all the ticks calculations.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ # This gets called when something has been changed
+ # (i.e. we've been invalidated). Recompute all
+ # tick positions.
+
+ if self._orientation == wx.HORIZONTAL:
+ self._maxwidth = self._length
+ self._maxheight = 0
+ else:
+ self._maxwidth = 0
+ self._maxheight = self._length
+
+ self._bits = [0]*(self._length+1)
+ self._middlepos = []
+
+ if self._userbits:
+ for ii in xrange(self._length):
+ self._bits[ii] = self._userbits[ii]
+ else:
+ for ii in xrange(self._length):
+ self._bits[ii] = 0
+
+ if not self._log:
+
+ UPP = (self._max - self._min)/float(self._length) # Units per pixel
+
+ self.FindLinearTickSizes(UPP)
+
+ # Left and Right Edges
+ if self._labeledges:
+ self.Tick(dc, 0, self._min, True)
+ self.Tick(dc, self._length, self._max, True)
+
+ # Zero (if it's in the middle somewhere)
+ if self._min*self._max < 0.0:
+ mid = int(self._length*(self._min/(self._min-self._max)) + 0.5)
+ self.Tick(dc, mid, 0.0, True)
+
+ sg = ((UPP > 0.0) and [1.0] or [-1.0])[0]
+
+ # Major ticks
+ d = self._min - UPP/2
+ lastd = d
+ majorint = int(math.floor(sg*d/self._major))
+ ii = -1
+
+ while ii <= self._length:
+ ii = ii + 1
+ lastd = d
+ d = d + UPP
+
+ if int(math.floor(sg*d/self._major)) > majorint:
+ majorint = int(math.floor(sg*d/self._major))
+ self.Tick(dc, ii, sg*majorint*self._major, True)
+
+ # Minor ticks
+ d = self._min - UPP/2
+ lastd = d
+ minorint = int(math.floor(sg*d/self._minor))
+ ii = -1
+
+ while ii <= self._length:
+ ii = ii + 1
+ lastd = d
+ d = d + UPP
+
+ if int(math.floor(sg*d/self._minor)) > minorint:
+ minorint = int(math.floor(sg*d/self._minor))
+ self.Tick(dc, ii, sg*minorint*self._minor, False)
+
+ # Left and Right Edges
+ if self._labeledges:
+ self.Tick(dc, 0, self._min, True)
+ self.Tick(dc, self._length, self._max, True)
+
+ else:
+ # log case
+
+ lolog = math.log10(self._min)
+ hilog = math.log10(self._max)
+ scale = self._length/(hilog - lolog)
+ lodecade = int(math.floor(lolog))
+ hidecade = int(math.ceil(hilog))
+
+ # Left and Right Edges
+ if self._labeledges:
+ self.Tick(dc, 0, self._min, True)
+ self.Tick(dc, self._length, self._max, True)
+
+ startdecade = 10.0**lodecade
+
+ # Major ticks are the decades
+ decade = startdecade
+ for ii in xrange(lodecade, hidecade):
+ if ii != lodecade:
+ val = decade
+ if val > self._min and val < self._max:
+ pos = int(((math.log10(val) - lolog)*scale)+0.5)
+ self.Tick(dc, pos, val, True)
+
+ decade = decade*10.0
+
+ # Minor ticks are multiples of decades
+ decade = startdecade
+
+ for ii in xrange(lodecade, hidecade):
+ for jj in xrange(2, 10):
+ val = decade*jj
+ if val >= self._min and val < self._max:
+ pos = int(((math.log10(val) - lolog)*scale)+0.5)
+ self.Tick(dc, pos, val, False)
+
+ decade = decade*10.0
+
+ self._valid = True
+
+
+ def Draw(self, dc):
+ """
+ Actually draws the whole :class:`RulerCtrl`.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ if not self._valid:
+ self.Update(dc)
+
+ dc.SetBrush(wx.Brush(self._background))
+ dc.SetPen(self._tickpen)
+ dc.SetTextForeground(self._textcolour)
+
+ dc.DrawRectangleRect(self.GetClientRect())
+
+ if self._orientation == wx.HORIZONTAL:
+ if self._flip:
+ dc.DrawLine(self._left, self._top, self._right+1, self._top)
+ else:
+ dc.DrawLine(self._left, self._bottom-1, self._right+1, self._bottom-1)
+
+ else:
+ if self._flip:
+ dc.DrawLine(self._left, self._top, self._left, self._bottom+1)
+ else:
+ dc.DrawLine(self._right-1, self._top, self._right-1, self._bottom+1)
+
+ dc.SetFont(self._majorfont)
+
+ for label in self._majorlabels:
+ pos = label.pos
+
+ if self._orientation == wx.HORIZONTAL:
+ if self._flip:
+ dc.DrawLine(self._left + pos, self._top,
+ self._left + pos, self._top + 5)
+ else:
+ dc.DrawLine(self._left + pos, self._bottom - 5,
+ self._left + pos, self._bottom)
+
+ else:
+ if self._flip:
+ dc.DrawLine(self._left, self._top + pos,
+ self._left + 5, self._top + pos)
+ else:
+ dc.DrawLine(self._right - 5, self._top + pos,
+ self._right, self._top + pos)
+
+ if label.text != "":
+ dc.DrawText(label.text, label.lx, label.ly)
+
+ dc.SetFont(self._minorfont)
+
+ for label in self._minorlabels:
+ pos = label.pos
+
+ if self._orientation == wx.HORIZONTAL:
+ if self._flip:
+ dc.DrawLine(self._left + pos, self._top,
+ self._left + pos, self._top + 3)
+ else:
+ dc.DrawLine(self._left + pos, self._bottom - 3,
+ self._left + pos, self._bottom)
+
+ else:
+ if self._flip:
+ dc.DrawLine(self._left, self._top + pos,
+ self._left + 3, self._top + pos)
+ else:
+ dc.DrawLine(self._right - 3, self._top + pos,
+ self._right, self._top + pos)
+
+ if label.text != "":
+ dc.DrawText(label.text, label.lx, label.ly)
+
+ for indicator in self._indicators:
+ indicator.Draw(dc)
+
+
+ def SetDrawingParent(self, dparent):
+ """
+ Sets the window to which :class:`RulerCtrl` draws a thin line over.
+
+ :param `dparent`: an instance of :class:`Window`, representing the window to
+ which :class:`RulerCtrl` draws a thin line over.
+ """
+
+ self._drawingparent = dparent
+
+
+ def GetDrawingParent(self):
+ """ Returns the window to which :class:`RulerCtrl` draws a thin line over. """
+
+ return self._drawingparent
+
+
+ def DrawOnParent(self, indicator):
+ """
+ Actually draws the thin line over the drawing parent window.
+
+ :param `indicator`: the current indicator, an instance of :class:`Indicator`.
+
+ :note: This method is currently not available on wxMac as it uses :class:`ScreenDC`.
+ """
+
+ if not self._drawingparent:
+ return
+
+ xpos, ypos = indicator.GetPosition()
+ parentrect = self._drawingparent.GetClientRect()
+
+ dc = wx.ScreenDC()
+ dc.SetLogicalFunction(wx.INVERT)
+ dc.SetPen(self._drawingpen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ imgx, imgy = indicator.GetImageSize()
+
+ if self._orientation == wx.HORIZONTAL:
+
+ x1 = xpos+ imgx/2
+ y1 = parentrect.y
+ x2 = x1
+ y2 = parentrect.height
+ x1, y1 = self._drawingparent.ClientToScreenXY(x1, y1)
+ x2, y2 = self._drawingparent.ClientToScreenXY(x2, y2)
+
+ elif self._orientation == wx.VERTICAL:
+
+ x1 = parentrect.x
+ y1 = ypos + imgy/2
+ x2 = parentrect.width
+ y2 = y1
+
+ x1, y1 = self._drawingparent.ClientToScreenXY(x1, y1)
+ x2, y2 = self._drawingparent.ClientToScreenXY(x2, y2)
+
+ dc.DrawLine(x1, y1, x2, y2)
+ dc.SetLogicalFunction(wx.COPY)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/shapedbutton.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/shapedbutton.py
new file mode 100644
index 0000000..2930d07
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/shapedbutton.py
@@ -0,0 +1,1779 @@
+# --------------------------------------------------------------------------- #
+# SHAPEDBUTTON Control wxPython IMPLEMENTATION
+# Python Code By:
+#
+# Andrea Gavana, @ 18 Oct 2005
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# TODO List/Caveats
+#
+# 1. Elliptic Buttons May Be Handled Better, In My Opinion. They Look Nice
+# But They Are Somewhat More Difficult To Handle When Using Sizers.
+# This Is Probably Due To Some Lack In My Implementation;
+#
+# 2. I Am Unable To Translate The 2 Files "UpButton.png" And "DownButton.png"
+# Using "img2py" (Under wx.tools) Or With PIL In Order To Embed Them In
+# A Python File. Every Translation I Made, Did Not Preserve The Alpha
+# Channel So I Ended Up With Round Buttons Inside Black Squares. Does
+# Anyone Have A Suggestion Here?
+#
+# 3. Creating *A Lot* Of ShapedButtons May Require Some Time. In The Demo,
+# I Create 23 Buttons In About 0.4 Seconds On Windows XP, 3 GHz 1 GB RAM.
+#
+# 4. Creating Buttons With Size Greater Than wx.Size(200, 200) May Display
+# Buttons With Clearly Evident Pixel Edges. This Is Due To The Size Of The
+# Image Files I Load During Initialization. If This Is Not Satisfactory,
+# Please Let Me Know And I Will Upload Bigger Files.
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+
+"""
+`ShapedButton` tries to fill the lack of "custom shaped" controls in wxPython
+and it can be used to build round or elliptic-shaped buttons.
+
+
+Description
+===========
+
+`ShapedButton` tries to fill the lack of "custom shaped" controls in wxPython
+(that depends on the same lack in wxWidgets). It can be used to build round
+buttons or elliptic buttons.
+
+I have stolen some code from :mod:`lib.buttons` in order to recreate the same
+classes (`GenButton`, `GenBitmapButton`, `GenBitmapTextButton`, `GenToggleButton`,
+`GenBitmapToggleButton`, `GenBitmapTextToggleButton`). Here you have the same
+classes (with "Gen" replaced by "S"), with the same event handling, but they
+are rounded/elliptical buttons.
+
+`ShapedButton` is based on a :class:`Window`, in which 2 images are drawn depending
+on the button state (pressed or not pressed). The 2 images have been stolen
+from Audacity (written with wxWidgets) and rearranged/reshaped/restyled
+using adobe PhotoShop.
+Changing the button colour in runtime was more difficult, but using some
+intelligent instruction from the PIL library it can be done.
+
+`ShapedButton` reacts on mouse events *only* if the mouse event occurred inside
+the circle/ellipse, even if `ShapedButton` is built on a rectangular window.
+This behavior is a lot different with respect to Audacity round buttons.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.shapedbutton as SB
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "ShapedButton Demo")
+
+ panel = wx.Panel(self)
+
+ # Create 2 bitmaps for the button
+ upbmp = wx.Bitmap("play.png", wx.BITMAP_TYPE_PNG)
+ disbmp = wx.Bitmap("playdisabled.png", wx.BITMAP_TYPE_PNG)
+
+ play = SB.SBitmapToggleButton(panel, -1, upbmp, (100, 50))
+ play.SetUseFocusIndicator(False)
+ play.SetBitmapDisabled(disbmp)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+The `ShapedButton` construction and usage is quite similar to the :mod:`lib.buttons`
+implementation.
+
+
+Methods and Settings
+====================
+
+With `ShapedButton` you can:
+
+- Create rounded/elliptical buttons/togglebuttons;
+- Set images for the enabled/disabled/focused/selected state of the button;
+- Draw the focus indicator (or disable it);
+- Set label colour and font;
+- Apply a rotation to the `ShapedButton` label;
+- Change `ShapedButton` shape and text orientation in runtime.
+
+
+:note: `ShapedButton` **requires** PIL (Python Imaging Library) library to be installed,
+ which can be downloaded from http://www.pythonware.com/products/pil/ .
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================= ==================================================
+Event Name Description
+================= ==================================================
+``wx.EVT_BUTTON`` Process a `wxEVT_COMMAND_BUTTON_CLICKED` event, when the button is clicked.
+================= ==================================================
+
+
+License And Version
+===================
+
+`ShapedButton` is distributed under the wxPython license.
+
+Latest revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.4
+
+"""
+
+
+#----------------------------------------------------------------------
+# Beginning Of SHAPEDBUTTON wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+
+# First Check If PIL Is Installed Properly
+try:
+
+ import PIL.Image as Image
+
+except ImportError:
+
+ errstr = ("\nShapedButton *Requires* PIL (Python Imaging Library).\n"
+ "You Can Get It At:\n\n"
+ "http://www.pythonware.com/products/pil/\n\n"
+ "ShapedButton Can Not Continue. Exiting...\n")
+
+ raise Exception(errstr)
+
+import os
+
+folder = os.path.split(__file__)[0]
+
+# Import Some Stuff For The Annoying Ellipsis... ;-)
+from math import sin, cos, pi
+
+#-----------------------------------------------------------------------------
+# PATH & FILE FILLING FUNCTION (OS INDEPENDENT)
+# This Is Required To Load The Pressed And Non-Pressed Images From The
+# "images" Directory.
+#-----------------------------------------------------------------------------
+
+def opj(path):
+ """
+ Convert paths to the platform-specific separator.
+
+ :param `path`: the path to convert.
+ """
+
+ strs = apply(os.path.join, tuple(path.split('/')))
+ # HACK: on Linux, a leading / gets lost...
+ if path.startswith('/'):
+ strs = '/' + strs
+
+ return strs
+
+#-----------------------------------------------------------------------------
+
+
+#----------------------------------------------------------------------
+# Class SButtonEvent
+# Code Stolen From wx.lib.buttons. This Class Handles All The Button
+# And ToggleButton Events.
+#----------------------------------------------------------------------
+
+class SButtonEvent(wx.PyCommandEvent):
+ """ Event sent from the generic buttons when the button is activated. """
+
+ def __init__(self, eventType, eventId):
+ """
+ Default class constructor.
+
+ :param `eventType`: the event type;
+ :param `eventId`: the event identifier.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+ self.isDown = False
+ self.theButton = None
+
+
+ def SetIsDown(self, isDown):
+ """
+ Sets the button event as pressed.
+
+ :param `isDown`: ``True`` to set the event as "pressed", ``False`` otherwise.
+ """
+
+ self.isDown = isDown
+
+
+ def GetIsDown(self):
+ """ Returns ``True`` if the button event is "pressed". """
+
+ return self.isDown
+
+
+ def SetButtonObj(self, btn):
+ """
+ Sets the event object for the event.
+
+ :param `btn`: the button object.
+ """
+
+ self.theButton = btn
+
+
+ def GetButtonObj(self):
+ """ Returns the object associated with this event. """
+
+ return self.theButton
+
+
+#----------------------------------------------------------------------
+# SBUTTON Class
+# This Is The Main Class Implementation. See __init__() Method For
+# Details. All The Other Button Types Depend On This Class For Event
+# Handling And Property Settings.
+#----------------------------------------------------------------------
+
+class SButton(wx.Window):
+ """ This is the main implementation of `ShapedButton`. """
+
+ _labeldelta = 1
+
+ def __init__(self, parent, id=wx.ID_ANY, label="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`SButton` parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `label`: the button text label;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform.
+ """
+
+ wx.Window.__init__(self, parent, id, pos, size)
+
+ if label is None:
+ label = ""
+
+ self._enabled = True
+ self._isup = True
+ self._hasfocus = False
+ self._usefocusind = True
+
+ # Initialize Button Properties
+ self.SetButtonColour()
+ self.SetLabel(label)
+ self.SetLabelColour()
+ self.InitColours()
+ self.SetAngleOfRotation()
+ self.SetEllipseAxis()
+
+ if size == wx.DefaultSize:
+ self.SetInitialSize(self.DoGetBestSize())
+
+ # Event Binding
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+
+ if wx.Platform == '__WXMSW__':
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
+
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnGainFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnLoseFocus)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def SetButtonColour(self, colour=None):
+ """
+ Sets the button colour, for all button states.
+
+ :param `colour`: an instance of :class:`Colour`.
+
+ :note: The original button images are greyscale with a lot of pixels with
+ different colours. Changing smoothly the button colour in order to
+ give the same 3D effect can be efficiently done only with PIL.
+ """
+
+ if colour is None:
+ colour = wx.WHITE
+
+ palette = colour.Red(), colour.Green(), colour.Blue()
+
+ self._buttoncolour = colour
+
+ self._mainbuttondown = DownButton.GetImage()
+ self._mainbuttonup = UpButton.GetImage()
+
+
+
+ def GetButtonColour(self):
+ """ Returns the button colour. """
+
+ return self._buttoncolour
+
+
+ def SetLabelColour(self, colour=None):
+ """
+ Sets the button label colour.
+
+ :param `colour`: an instance of :class:`Colour`.
+ """
+
+ if colour is None:
+ colour = wx.BLACK
+
+ self._labelcolour = colour
+
+
+ def GetLabelColour(self):
+ """ Returns the button label colour. """
+
+ return self._labelcolour
+
+
+ def SetLabel(self, label=None):
+ """
+ Sets the button label.
+
+ :param `label`: the new button label.
+ """
+
+ if label is None:
+ label = ""
+
+ self._buttonlabel = label
+
+
+ def GetLabel(self):
+ """ Returns the button label. """
+
+ return self._buttonlabel
+
+
+ def SetBestSize(self, size=None):
+ """
+ Given the current font settings, calculate and set a good size.
+
+ :param `size`: if not ``None``, an instance of :class:`Size` to pass to
+ `SetInitialSize`.
+ """
+
+ if size is None:
+ size = wx.DefaultSize
+
+ self.SetInitialSize(size)
+
+
+ def DoGetBestSize(self):
+ """
+ Overridden base class virtual. Determines the best size of the button
+ based on the label size.
+
+ :note: Overridden from :class:`Window`.
+ """
+
+ w, h, usemin = self._GetLabelSize()
+ defsize = wx.Button.GetDefaultSize()
+ width = 12 + w
+
+ if usemin and width < defsize.width:
+ width = defsize.width
+
+ height = 11 + h
+
+ if usemin and height < defsize.height:
+ height = defsize.height
+
+ return (width, height)
+
+
+ def AcceptsFocus(self):
+ """
+ Can this window be given focus by mouse click?
+
+ :note: Overridden from :class:`Window`.
+ """
+
+ return self.IsShown() and self.IsEnabled()
+
+
+ def ShouldInheritColours(self):
+ """
+ Overridden base class virtual. Buttons usually do not inherit
+ parent's colours.
+ """
+
+ return False
+
+
+ def Enable(self, enable=True):
+ """
+ Enables/disables the button.
+
+ :param `enable`: ``True`` to enable the button, ``False`` to disable it.
+
+ :note: Overridden from :class:`Window`.
+ """
+
+ self._enabled = enable
+ self.Refresh()
+
+
+ def IsEnabled(self):
+ """ Returns wheter the button is enabled or not. """
+
+ return self._enabled
+
+
+ def SetUseFocusIndicator(self, flag):
+ """
+ Specifies if a focus indicator (dotted line) should be used.
+
+ :param `flag`: ``True`` to use the focus indicator, ``False`` otherwise.
+ """
+
+ self._usefocusind = flag
+
+
+ def GetUseFocusIndicator(self):
+ """ Returns focus indicator flag. """
+
+ return self._usefocusind
+
+
+ def InitColours(self):
+ """
+ Calculates a new set of focus indicator colour and indicator pen
+ based on button colour and label colour.
+ """
+
+ textclr = self.GetLabelColour()
+ faceclr = self.GetButtonColour()
+
+ r, g, b = faceclr.Get()
+ hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64)
+ self._focusclr = wx.Colour(hr, hg, hb)
+
+ if wx.Platform == "__WXMAC__":
+ self._focusindpen = wx.Pen(textclr, 1, wx.SOLID)
+ else:
+ self._focusindpen = wx.Pen(textclr, 1, wx.USER_DASH)
+ self._focusindpen.SetDashes([1,1])
+ self._focusindpen.SetCap(wx.CAP_BUTT)
+
+
+ def SetDefault(self):
+ """ Sets the button as default item. """
+
+ self.GetParent().SetDefaultItem(self)
+
+
+ def _GetLabelSize(self):
+ """ Used internally """
+
+ w, h = self.GetTextExtent(self.GetLabel())
+ return w, h, True
+
+
+ def Notify(self):
+ """ Notifies an event and let it be processed. """
+
+ evt = SButtonEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
+ evt.SetIsDown(not self._isup)
+ evt.SetButtonObj(self)
+ evt.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(evt)
+
+
+ def DrawMainButton(self, dc, width, height):
+ """
+ Draws the main button, in whichever state it is.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `width`: the button width;
+ :param `height`: the button height.
+ """
+
+ w = min(width, height)
+
+ if w <= 2:
+ return
+
+ position = self.GetPosition()
+
+ main, secondary = self.GetEllipseAxis()
+ xc = width/2
+ yc = height/2
+
+ if abs(main - secondary) < 1e-6:
+ # In This Case The Button Is A Circle
+ if self._isup:
+ img = self._mainbuttonup.Scale(w, w)
+ else:
+ img = self._mainbuttondown.Scale(w, w)
+ else:
+ # In This Case The Button Is An Ellipse... Some Math To Do
+ rect = self.GetRect()
+
+ if main > secondary:
+ # This Is An Ellipse With Main Axis Aligned With X Axis
+ rect2 = w
+ rect3 = w*secondary/main
+
+ else:
+ # This Is An Ellipse With Main Axis Aligned With Y Axis
+ rect3 = w
+ rect2 = w*main/secondary
+
+ if self._isup:
+ img = self._mainbuttonup.Scale(rect2, rect3)
+ else:
+ img = self._mainbuttondown.Scale(rect2, rect3)
+
+ bmp = img.ConvertToBitmap()
+
+ if abs(main - secondary) < 1e-6:
+ if height > width:
+ xpos = 0
+ ypos = (height - width)/2
+ else:
+ xpos = (width - height)/2
+ ypos = 0
+ else:
+ if height > width:
+ if main > secondary:
+ xpos = 0
+ ypos = (height - rect3)/2
+ else:
+ xpos = (width - rect2)/2
+ ypos = (height - rect3)/2
+ else:
+ if main > secondary:
+ xpos = (width - rect2)/2
+ ypos = (height - rect3)/2
+ else:
+ xpos = (width - rect2)/2
+ ypos = 0
+
+ # Draw Finally The Bitmap
+ dc.DrawBitmap(bmp, xpos, ypos, True)
+
+ # Store Bitmap Position And Size To Draw An Elliptical Focus Indicator
+ self._xpos = xpos
+ self._ypos = ypos
+ self._imgx = img.GetWidth()
+ self._imgy = img.GetHeight()
+
+
+ def DrawLabel(self, dc, width, height, dw=0, dh=0):
+ """
+ Draws the label on the button.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `width`: the button width;
+ :param `height`: the button height;
+ :param `dw`: width differential, to show a 3D effect;
+ :param `dh`: height differential, to show a 3D effect.
+ """
+
+ dc.SetFont(self.GetFont())
+
+ if self.IsEnabled():
+ dc.SetTextForeground(self.GetLabelColour())
+ else:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+
+ label = self.GetLabel()
+ tw, th = dc.GetTextExtent(label)
+
+ w = min(width, height)
+
+ # labeldelta Is Used To Give The Impression Of A "3D" Click
+ if not self._isup:
+ dw = dh = self._labeldelta
+
+ angle = self.GetAngleOfRotation()*pi/180.0
+
+ # Check If There Is Any Rotation Chosen By The User
+ if angle == 0:
+ dc.DrawText(label, (width-tw)/2+dw, (height-th)/2+dh)
+ else:
+ xc, yc = (width/2, height/2)
+
+ xp = xc - (tw/2)* cos(angle) - (th/2)*sin(angle)
+ yp = yc + (tw/2)*sin(angle) - (th/2)*cos(angle)
+
+ dc.DrawRotatedText(label, xp + dw, yp + dh , angle*180/pi)
+
+
+ def DrawFocusIndicator(self, dc, width, height):
+ """
+ Draws the focus indicator. This is a circle/ellipse inside the button
+ drawn with a dotted-style pen, to let the user know which button has
+ the focus.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `width`: the button width;
+ :param `height`: the button height.
+ """
+
+ self._focusindpen.SetColour(self._focusclr)
+ dc.SetLogicalFunction(wx.INVERT)
+ dc.SetPen(self._focusindpen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ main, secondary = self.GetEllipseAxis()
+
+ if abs(main - secondary) < 1e-6:
+ # Ah, That Is A Round Button
+ if height > width:
+ dc.DrawCircle(width/2, height/2, width/2-4)
+ else:
+ dc.DrawCircle(width/2, height/2, height/2-4)
+ else:
+ # This Is An Ellipse
+ if hasattr(self, "_xpos"):
+ dc.DrawEllipse(self._xpos + 2, self._ypos + 2, self._imgx - 4, self._imgy - 4)
+
+ dc.SetLogicalFunction(wx.COPY)
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`SButton`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Refresh()
+ event.Skip()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`SButton`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ (width, height) = self.GetClientSizeTuple()
+
+ # Use A Double Buffered DC (Good Speed Up)
+ dc = wx.BufferedPaintDC(self)
+
+ # The DC Background *Must* Be The Same As The Parent Background Colour,
+ # In Order To Hide The Fact That Our "Shaped" Button Is Still Constructed
+ # Over A Rectangular Window
+ brush = wx.Brush(self.GetParent().GetBackgroundColour(), wx.SOLID)
+
+ dc.SetBackground(brush)
+ dc.Clear()
+
+ self.DrawMainButton(dc, width, height)
+ self.DrawLabel(dc, width, height)
+
+ if self._hasfocus and self._usefocusind:
+ self.DrawFocusIndicator(dc, width, height)
+
+
+ def IsOutside(self, x, y):
+ """
+ Checks if a mouse events occurred inside the circle/ellipse or not.
+
+ :param `x`: the mouse x position;
+ :param `y`: the mouse y position.
+ """
+
+ (width, height) = self.GetClientSizeTuple()
+ diam = min(width, height)
+ xc, yc = (width/2, height/2)
+
+ main, secondary = self.GetEllipseAxis()
+
+ if abs(main - secondary) < 1e-6:
+ # This Is A Circle
+ if ((x - xc)**2.0 + (y - yc)**2.0) > (diam/2.0)**2.0:
+ return True
+ else:
+ # This Is An Ellipse
+ mn = max(main, secondary)
+ main = self._imgx/2.0
+ secondary = self._imgy/2.0
+ if (((x-xc)/main)**2.0 + ((y-yc)/secondary)**2.0) > 1:
+ return True
+
+ return False
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`SButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ x, y = (event.GetX(), event.GetY())
+
+ if self.IsOutside(x,y):
+ return
+
+ self._isup = False
+
+ if not self.HasCapture():
+ self.CaptureMouse()
+
+ self.SetFocus()
+
+ self.Refresh()
+ event.Skip()
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`SButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled() or not self.HasCapture():
+ return
+
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+ if not self._isup:
+ self.Notify()
+
+ self._isup = True
+ self.Refresh()
+ event.Skip()
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`SButton`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled() or not self.HasCapture():
+ return
+
+ if event.LeftIsDown() and self.HasCapture():
+ x, y = event.GetPositionTuple()
+
+ if self._isup and not self.IsOutside(x, y):
+ self._isup = False
+ self.Refresh()
+ return
+
+ if not self._isup and self.IsOutside(x,y):
+ self._isup = True
+ self.Refresh()
+ return
+
+ event.Skip()
+
+
+ def OnGainFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`SButton`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self._hasfocus = True
+ dc = wx.ClientDC(self)
+ w, h = self.GetClientSizeTuple()
+
+ if self._usefocusind:
+ self.DrawFocusIndicator(dc, w, h)
+
+
+ def OnLoseFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`SButton`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self._hasfocus = False
+ dc = wx.ClientDC(self)
+ w, h = self.GetClientSizeTuple()
+
+ if self._usefocusind:
+ self.DrawFocusIndicator(dc, w, h)
+
+ self.Refresh()
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`SButton`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if self._hasfocus and event.GetKeyCode() == ord(" "):
+
+ self._isup = False
+ self.Refresh()
+
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` event for :class:`SButton`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if self._hasfocus and event.GetKeyCode() == ord(" "):
+
+ self._isup = True
+ self.Notify()
+ self.Refresh()
+
+ event.Skip()
+
+
+ def MakePalette(self, tr, tg, tb):
+ """
+ Creates a palette to be applied on an image based on input colour.
+
+ :param `tr`: the red intensity of the input colour;
+ :param `tg`: the green intensity of the input colour;
+ :param `tb`: the blue intensity of the input colour.
+ """
+
+ l = []
+ for i in range(255):
+ l.extend([tr*i / 255, tg*i / 255, tb*i / 255])
+
+ return l
+
+
+ def ConvertWXToPIL(self, bmp):
+ """
+ Converts a :class:`Image` into a PIL image.
+
+ :param `bmp`: an instance of :class:`Image`.
+ """
+
+ width = bmp.GetWidth()
+ height = bmp.GetHeight()
+ img = Image.fromstring("RGBA", (width, height), bmp.GetData())
+
+ return img
+
+
+ def ConvertPILToWX(self, pil, alpha=True):
+ """
+ Converts a PIL image into a :class:`Image`.
+
+ :param `pil`: a PIL image;
+ :param `alpha`: ``True`` if the image contains alpha transparency, ``False``
+ otherwise.
+ """
+
+ if alpha:
+ image = apply(wx.EmptyImage, pil.size)
+ image.SetData(pil.convert("RGB").tostring())
+ image.SetAlphaData(pil.convert("RGBA").tostring()[3::4])
+ else:
+ image = wx.EmptyImage(pil.size[0], pil.size[1])
+ new_image = pil.convert('RGB')
+ data = new_image.tostring()
+ image.SetData(data)
+
+ return image
+
+
+ def SetAngleOfRotation(self, angle=None):
+ """
+ Sets angle of button label rotation.
+
+ :param `angle`: the label rotation, in degrees.
+ """
+
+ if angle is None:
+ angle = 0
+
+ self._rotation = angle*pi/180
+
+
+ def GetAngleOfRotation(self):
+ """ Returns angle of button label rotation, in degrees. """
+
+ return self._rotation*180.0/pi
+
+
+ def SetEllipseAxis(self, main=None, secondary=None):
+ """
+ Sets the ellipse axis. What it is important is not their absolute values
+ but their ratio.
+
+ :param `main`: a floating point number representing the absolute dimension
+ of the main ellipse axis;
+ :param `secondary`: a floating point number representing the absolute dimension
+ of the secondary ellipse axis.
+ """
+
+ if main is None:
+ main = 1.0
+ secondary = 1.0
+
+ self._ellipseaxis = (main, secondary)
+
+
+ def GetEllipseAxis(self):
+ """ Returns the ellipse axes. """
+
+ return self._ellipseaxis
+
+
+#----------------------------------------------------------------------
+# SBITMAPBUTTON Class
+# It Is Derived From SButton, And It Is A Class Useful To Draw A
+# ShapedButton With An Image In The Middle. The Button Can Have 4
+# Different Bitmaps Assigned To Its Different States (Pressed, Non
+# Pressed, With Focus, Disabled).
+#----------------------------------------------------------------------
+
+
+class SBitmapButton(SButton):
+ """
+ Subclass of :class:`SButton` which displays a bitmap, acting like a
+ :class:`BitmapButton`.
+ """
+
+ def __init__(self, parent, id, bitmap, pos=wx.DefaultPosition, size=wx.DefaultSize):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`SBitmapButton` parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `bitmap`: the button bitmap (if any);
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform.
+ """
+
+ self._bmpdisabled = None
+ self._bmpfocus = None
+ self._bmpselected = None
+
+ self.SetBitmapLabel(bitmap)
+
+ SButton.__init__(self, parent, id, "", pos, size)
+
+
+ def GetBitmapLabel(self):
+ """ Returns the bitmap associated with the button in the normal state. """
+
+ return self._bmplabel
+
+
+ def GetBitmapDisabled(self):
+ """ Returns the bitmap displayed when the button is disabled. """
+
+ return self._bmpdisabled
+
+
+ def GetBitmapFocus(self):
+ """ Returns the bitmap displayed when the button has the focus. """
+
+ return self._bmpfocus
+
+
+ def GetBitmapSelected(self):
+ """ Returns the bitmap displayed when the button is selected (pressed). """
+
+ return self._bmpselected
+
+
+ def SetBitmapDisabled(self, bitmap):
+ """
+ Sets the bitmap to display when the button is disabled.
+
+ :param `bitmap`: a valid :class:`Bitmap` object.
+ """
+
+ self._bmpdisabled = bitmap
+
+
+ def SetBitmapFocus(self, bitmap):
+ """
+ Sets the bitmap to display when the button has the focus.
+
+ :param `bitmap`: a valid :class:`Bitmap` object.
+ """
+
+ self._bmpfocus = bitmap
+ self.SetUseFocusIndicator(False)
+
+
+ def SetBitmapSelected(self, bitmap):
+ """
+ Sets the bitmap to display when the button is selected (pressed).
+
+ :param `bitmap`: a valid :class:`Bitmap` object.
+ """
+
+ self._bmpselected = bitmap
+
+
+ def SetBitmapLabel(self, bitmap, createothers=True):
+ """
+ Sets the bitmap to display normally. This is the only one that is
+ required.
+
+ :param `bitmap`: a valid :class:`Bitmap` object;
+ :param `createothers`: if set to ``True``, then the other bitmaps will be
+ generated on the fly. Currently, only the disabled bitmap is generated.
+ """
+
+ self._bmplabel = bitmap
+
+ if bitmap is not None and createothers:
+ dis_bitmap = wx.BitmapFromImage(bitmap.ConvertToImage().ConvertToGreyscale())
+ self.SetBitmapDisabled(dis_bitmap)
+
+
+ def _GetLabelSize(self):
+ """ Used internally. """
+
+ if not self._bmplabel:
+ return -1, -1, False
+
+ return self._bmplabel.GetWidth() + 2, self._bmplabel.GetHeight() + 2, False
+
+
+ def DrawLabel(self, dc, width, height, dw=0, dh=0):
+ """
+ Draws the bitmap in the middle of the button.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `width`: the button width;
+ :param `height`: the button height;
+ :param `dw`: width differential, to show a 3D effect;
+ :param `dh`: height differential, to show a 3D effect.
+ """
+
+ bmp = self._bmplabel
+
+ if self._bmpdisabled and not self.IsEnabled():
+ bmp = self._bmpdisabled
+
+ if self._bmpfocus and self._hasfocus:
+ bmp = self._bmpfocus
+
+ if self._bmpselected and not self._isup:
+ bmp = self._bmpselected
+
+ bw, bh = bmp.GetWidth(), bmp.GetHeight()
+
+ if not self._isup:
+ dw = dh = self._labeldelta
+
+ hasMask = bmp.GetMask() != None
+ dc.DrawBitmap(bmp, (width - bw)/2 + dw, (height - bh)/2 + dh, hasMask)
+
+
+#----------------------------------------------------------------------
+# SBITMAPTEXTBUTTON Class
+# It Is Derived From SButton, And It Is A Class Useful To Draw A
+# ShapedButton With An Image And Some Text Ceneterd In The Middle.
+# The Button Can Have 4 Different Bitmaps Assigned To Its Different
+# States (Pressed, Non Pressed, With Focus, Disabled).
+#----------------------------------------------------------------------
+
+class SBitmapTextButton(SBitmapButton):
+ """
+ Subclass of :class:`SButton` which displays a bitmap and a label.
+ """
+
+ def __init__(self, parent, id, bitmap, label,
+ pos=wx.DefaultPosition, size=wx.DefaultSize):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`SBitmapTextButton` parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `bitmap`: the button bitmap (if any);
+ :param `label`: the button text label;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform.
+ """
+
+ SBitmapButton.__init__(self, parent, id, bitmap, pos, size)
+ self.SetLabel(label)
+
+
+ def _GetLabelSize(self):
+ """ Used internally. """
+
+ w, h = self.GetTextExtent(self.GetLabel())
+
+ if not self._bmplabel:
+ return w, h, True # if there isn't a bitmap use the size of the text
+
+ w_bmp = self._bmplabel.GetWidth() + 2
+ h_bmp = self._bmplabel.GetHeight() + 2
+ width = w + w_bmp
+
+ if h_bmp > h:
+ height = h_bmp
+ else:
+ height = h
+
+ return width, height, True
+
+
+ def DrawLabel(self, dc, width, height, dw=0, dh=0):
+ """
+ Draws the bitmap and the text label.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `width`: the button width;
+ :param `height`: the button height;
+ :param `dw`: width differential, to show a 3D effect;
+ :param `dh`: height differential, to show a 3D effect.
+ """
+
+ bmp = self._bmplabel
+
+ if bmp != None: # if the bitmap is used
+
+ if self._bmpdisabled and not self.IsEnabled():
+ bmp = self._bmpdisabled
+
+ if self._bmpfocus and self._hasfocus:
+ bmp = self._bmpfocus
+
+ if self._bmpselected and not self._isup:
+ bmp = self._bmpselected
+
+ bw, bh = bmp.GetWidth(), bmp.GetHeight()
+
+ if not self._isup:
+ dw = dh = self._labeldelta
+
+ hasMask = bmp.GetMask() != None
+
+ else:
+
+ bw = bh = 0 # no bitmap -> size is zero
+
+ dc.SetFont(self.GetFont())
+
+ if self.IsEnabled():
+ dc.SetTextForeground(self.GetLabelColour())
+ else:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+
+ label = self.GetLabel()
+ tw, th = dc.GetTextExtent(label) # size of text
+
+ if not self._isup:
+ dw = dh = self._labeldelta
+
+ w = min(width, height)
+
+ pos_x = (width - bw - tw)/2 + dw # adjust for bitmap and text to centre
+
+ rotangle = self.GetAngleOfRotation()*pi/180.0
+
+ if bmp != None:
+ if rotangle < 1.0/180.0:
+ dc.DrawBitmap(bmp, pos_x, (height - bh)/2 + dh, hasMask) # draw bitmap if available
+ pos_x = pos_x + 4 # extra spacing from bitmap
+ else:
+ pass
+
+ if rotangle < 1.0/180.0:
+ dc.DrawText(label, pos_x + dw + bw, (height-th)/2+dh) # draw the text
+ else:
+ xc, yc = (width/2, height/2)
+ xp = xc - (tw/2)* cos(rotangle) - (th/2)*sin(rotangle)
+ yp = yc + (tw/2)*sin(rotangle) - (th/2)*cos(rotangle)
+ dc.DrawRotatedText(label, xp, yp , rotangle*180.0/pi)
+
+
+#----------------------------------------------------------------------
+# __STOGGLEMIXIN Class
+# A Mixin That Allows To Transform Any Of SButton, SBitmapButton And
+# SBitmapTextButton In The Corresponding ToggleButtons.
+#----------------------------------------------------------------------
+
+class __SToggleMixin(object):
+ """
+ A mixin that allows to transform any of :class:`SButton`, :class:`SBitmapButton` and
+ :class:`SBitmapTextButton` in the corresponding toggle buttons.
+ """
+
+ def SetToggle(self, flag):
+ """
+ Sets the button as toggled/not toggled.
+
+ :param `flag`: ``True`` to set the button as toggled, ``False`` otherwise.
+ """
+
+ self._isup = not flag
+ self.Refresh()
+
+ SetValue = SetToggle
+
+
+ def GetToggle(self):
+ """ Returns the toggled state of a button. """
+
+ return not self._isup
+
+ GetValue = GetToggle
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for the button.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ x, y = (event.GetX(), event.GetY())
+
+ if self.IsOutside(x,y):
+ return
+
+ self._saveup = self._isup
+ self._isup = not self._isup
+
+ if not self.HasCapture():
+ self.CaptureMouse()
+
+ self.SetFocus()
+ self.Refresh()
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for the button.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+
+ if not self.IsEnabled() or not self.HasCapture():
+ return
+
+ if self.HasCapture():
+ if self._isup != self._saveup:
+ self.Notify()
+
+ self.ReleaseMouse()
+ self.Refresh()
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for the button.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ event.Skip()
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for the button.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self.IsEnabled():
+ return
+
+ if event.LeftIsDown() and self.HasCapture():
+
+ x,y = event.GetPositionTuple()
+ w,h = self.GetClientSizeTuple()
+
+ if not self.IsOutside(x, y):
+ self._isup = not self._saveup
+ self.Refresh()
+ return
+
+ if self.IsOutside(x,y):
+ self._isup = self._saveup
+ self.Refresh()
+ return
+
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` event for the button.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if self._hasfocus and event.GetKeyCode() == ord(" "):
+
+ self._isup = not self._isup
+ self.Notify()
+ self.Refresh()
+
+ event.Skip()
+
+
+#----------------------------------------------------------------------
+# STOGGLEBUTTON Class
+#----------------------------------------------------------------------
+
+class SToggleButton(__SToggleMixin, SButton):
+ """ A `ShapedButton` toggle button. """
+ pass
+
+
+#----------------------------------------------------------------------
+# SBITMAPTOGGLEBUTTON Class
+#----------------------------------------------------------------------
+
+class SBitmapToggleButton(__SToggleMixin, SBitmapButton):
+ """ A `ShapedButton` toggle bitmap button. """
+ pass
+
+
+#----------------------------------------------------------------------
+# SBITMAPTEXTTOGGLEBUTTON Class
+#----------------------------------------------------------------------
+
+class SBitmapTextToggleButton(__SToggleMixin, SBitmapTextButton):
+ """ A `ShapedButton` toggle bitmap button with a text label. """
+ pass
+
+
+
+#----------------------------------------------------------------------
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+UpButton = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAACXBIWXMAAA7DAAAOwwHHb6hk"
+ "AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAA"
+ "F2+SX8VGAAADAFBMVEX//////8z//5n//2b//zP//wD/zP//zMz/zJn/zGb/zDP/zAD/mf//"
+ "mcz/mZn/mWb/mTP/mQD/Zv//Zsz/Zpn/Zmb/ZjP/ZgD/M///M8z/M5n/M2b/MzP/MwD/AP//"
+ "AMz/AJn/AGb/ADP/AADM///M/8zM/5nM/2bM/zPM/wDMzP/MzMzMzJnMzGbMzDPMzADMmf/M"
+ "mczMmZnMmWbMmTPMmQDMZv/MZszMZpnMZmbMZjPMZgDMM//MM8zMM5nMM2bMMzPMMwDMAP/M"
+ "AMzMAJnMAGbMADPMAACZ//+Z/8yZ/5mZ/2aZ/zOZ/wCZzP+ZzMyZzJmZzGaZzDOZzACZmf+Z"
+ "mcyZmZmZmWaZmTOZmQCZZv+ZZsyZZpmZZmaZZjOZZgCZM/+ZM8yZM5mZM2aZMzOZMwCZAP+Z"
+ "AMyZAJmZAGaZADOZAABm//9m/8xm/5lm/2Zm/zNm/wBmzP9mzMxmzJlmzGZmzDNmzABmmf9m"
+ "mcxmmZlmmWZmmTNmmQBmZv9mZsxmZplmZmZmZjNmZgBmM/9mM8xmM5lmM2ZmMzNmMwBmAP9m"
+ "AMxmAJlmAGZmADNmAAAz//8z/8wz/5kz/2Yz/zMz/wAzzP8zzMwzzJkzzGYzzDMzzAAzmf8z"
+ "mcwzmZkzmWYzmTMzmQAzZv8zZswzZpkzZmYzZjMzZgAzM/8zM8wzM5kzM2YzMzMzMwAzAP8z"
+ "AMwzAJkzAGYzADMzAAAA//8A/8wA/5kA/2YA/zMA/wAAzP8AzMwAzJkAzGYAzDMAzAAAmf8A"
+ "mcwAmZkAmWYAmTMAmQAAZv8AZswAZpkAZmYAZjMAZgAAM/8AM8wAM5kAM2YAMzMAMwAAAP8A"
+ "AMwAAJkAAGYAADMAAADU1NTT09PS0tLR0dHQ0NDNzc3Ly8vKysrJycnIyMjHx8fGxsbFxcXC"
+ "wsLBwcH39/f09PTw8PDs7Ozo6Ojj4+Pe3t7Z2dnX19fV1dXOzs7ExMTDw8O+vr66urq1tbWw"
+ "sLCsrKyoqKikpKSgoKCcnJyUlJSPj4////+2FWUJAAABAHRSTlP/////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "//////////////////////////////8AU/cHJQAAIcNJREFUeNpi+D9MAEAAMQwXjwAE0LDx"
+ "CEAA0cIjL9+8wwreA8GHGzdvvn1FA0sBAoj6HsHhCySP3Lx54y3VrQUIIGp6BOHkt2/fAgkQ"
+ "BWKBIIpvQB76cPPmrVtUtBwggBio6o232AHYT9g8cvs21awHCCCqeOQV2LFg8AYI4Yw3EIDq"
+ "KUTUfPhw48ONGzdvvaaGGwACiAoeeQF14hv8AN03sJgB+uTWS8pdARBAlHoE2QuvXwMROgAK"
+ "Y/UNIqWBY4XiRAYQQJR55DVKVLzGBbDEDCL/gzwCipVbbyhyCkAAUeARhnfIkQEFr5AAVr9g"
+ "ZBZY8gLGyh0KXAMQQAwUJyp4enqFCRD+wOsTSO0CKsTukO0cgAAi0yMvoXEBcj/UBy/BAKdP"
+ "wKohHkHzDKSeBCYvkFfu3CGz2gcIIAayYwPuESRvQHyC8A5q0nqNvTBG88gd8mIFIIAYyPIG"
+ "PF9APIHwBlqkvMYaI2jZHV4Mg3L87Tu373z8SIajAAKIgazoQIqNl+jg1UusKes1IotAPPMO"
+ "pUKBe+Q2KFLI8AlAAJHqkVeQDA72BLLzX2CLEWw5nVCMgD1y5+NdUgtjgAAi0SMMkNhAigug"
+ "D168ePHyBdwr8Bh5/QqSpJA88vYNlsYKvO2F4pG7JLoMIIAYSM8d0KwB9sQLKECKEeQkhdZI"
+ "eYPWknyH3FRB9gfII9raJDkNIIAYSKvHkWID5PQXCIDFH8hewNLcIugR7XckOA4ggBhIiw54"
+ "3niBCtB8Ac/bb1Gd/w49f+DwyEeIR0iJFIAAIt4jqJkDiz+QMjiW5jtKF+sthjdu3ECOD6A/"
+ "IB4h3icAAcRAWu5A8sbz58+RvPEKFhuoTUMC4D0MQFvASP6AeoRorwAEEJEeeQHxCKysAnsD"
+ "2SOocYElAeH1CKTshXrjzkeEJ0CAyCYLQAAxEJ2skHPH8+cIj4C9AfUDSsEKdiEo0dy4AaE/"
+ "gGkogPoAzPhwA8Uj2nfvaWvfA3niHhDcv0+UEwECiCiPvHqDiI4XSB55DvHIKzSPvEM0ocBO"
+ "vHnzBrgpdQNMQwGSnyCKbsELLIgHYOD+faKGXAACiIHIShASHy+wRser17BGFCLBQPpKt3EA"
+ "oBTMUx8gnrx5E9o4+Qj1yH0YeAAERLgSIIAYiKs9MP2BiA00f0Dj4RY0oeAAt2/dhIAbN2AN"
+ "X6hH7mqDfAHxyEMgAHmEiEgBCCAGwtkclj+QPAH2BixzQJMUpNcKchKiJrh3TxsFQAqju3c/"
+ "fgR6BR45EIDqkfsPHiKB+/cJDk8ABBADUf6A5o7nyB4BF7pgf8DiAlip3UJUaCDnAMMSCdy7"
+ "D0ky9+4BvQKPGpBnQMQduEdA+iAeeAQEEI/cJ1R4AQQQAxHFLjA+sPkDmqjgjXFg3YyICUji"
+ "Rg5VkKdgHtHW/ggFEM8gkhxQ9z1wdDyCAVjyIuATgABiIMYfryGlFcwTkOwB8gckb0C8cQOY"
+ "Xe/AvQHyxSMUAHTOQ0iyv/8AnMjA4ONHlKzzEeaRR48eP0b1yAP8qQsggPB65DW82EWKjhdI"
+ "qQocG5BRkNug0LwHThQgRzx58gSEkQDIYZDUAk4qkMR2T/se2DcwcBfZIzB9MC/hbUMCBBAD"
+ "3nIX5BFocYWZzaGxASpqQd74CMwVD+4/hHrk0yc8HnkEKVaJ8cinT48hAOQTfI4FCCAG/PU5"
+ "tNh9jpw9oKUVJHe8f38T4gvte5DU9BjkgE9A8OQJukfArnkM9RA010ByDCyh3dWG1iHg4AAa"
+ "8xkIIGaBteFxLEAAMeDr1cKrDzSPIOXy9+9h/rhPkkdAAQz3yD3cHnn69CnQLzCP4KlOAAKI"
+ "AV97F8MbKMkKlMeBjW+IJx4+gqakT6BgfAq2/xM6ePzkMTJ49BCUo6ClGbyuQfbI56fPnj2D"
+ "+AUUMkAtOJ0LEEA4PfICVn+gegQRHeDYAFZ+4LgA+wPsWFBiwOWRJ+geQSqWtWGeQfHIM4hH"
+ "QMZBPIKzEAYIIAa83UGUYhepEgTX5MCyClRSgS0FpieoH6DegHgFDaB45BEsqwC9Am0fwuME"
+ "JUYg4CkkTh7hihOAAMLjEfSM/gI1PkDV+B1gSQUupUBpCskL2AEuj8AiBb9HID7B6RGAAGLA"
+ "X2Chxwc8e7z/cOs2MG8CMzg4c4M98QyREEj1CNAruD3yBQQgfgEZgd3FAAHEgCdhoWQQFH+A"
+ "Cl1gBwiYOSB5A+gNmEfw+AWnRxAlMdg3cI88+fQU5g+YV0D1E1YnAwQQVo+ABz9eofkD5BFY"
+ "sgL2HoCp6j44b4DLKaAznxHwCCjzI3kCpS0FihOYR2ANHFD5Ac7tX74geQVoypMb2NwMEEAM"
+ "OHu2mAkLXpuD6g5QfEDyBtgjz5AAdm8g53UMj8D9Au9MgUsQsMFfkH0CLr6wuRkggBjwllio"
+ "6QoaH8BkBWqkP3gEyRuQaoOwR5BLX2I9Ak5bED98/QpPX5+x+QQggBiwNrHQa3R4eQXyx4fb"
+ "d7TB0YGoNJ49I+wRUCsSzSOPH6FkFEgjF+SfB+BWAqiR8Bnska8g8AXmlc+fsLgaIIAYsI63"
+ "o3sEls9B+eMGMJvfv/8I4g+QC9H9gdUj4PgAtyMf48rwcI88gETKw8fApAtMW19APoB4BZq8"
+ "Pj/BbKsABBADrhLrFaJ/jpQ/gOXuzdsf74IKXWgex4gPXB55/BjSniXSI+AW8COIR2BxAvUL"
+ "0COYJRdAAGF6BNE0gXgEPNQOi4/3wNocWFxBK/KnNPfI40+QtAX3CMgrwMSFmUsAAogBd9v9"
+ "BaLgBfcGgc0ScDUIbK+DyiqwD2jqEUil+BTJI9++QT2CWXIBBBADrqrwJUpGh+Tzd8Dq4yMo"
+ "m3/+jCVrPMPlIVjRCy6qnyCXWQ9RAepYBdgnT4CJC+yRb0BPgDAkToCFMJrDAQIIq0dQcjrI"
+ "I+BuLTB/3LoDbJU8fIzcJCHKI5CiF8MjDwl65CGoiAf7AxQdYACLEzSHAwQQA9a2InLKghVY"
+ "4PrjHtAbj2G5g9YeAVUmoNz47BnQFzB/fIPk+GdP0XwCEEAMGOsA4IOKSCUWOKND8gcwPsCx"
+ "QSePgGpFUHZHipFvXyG1CerqKIAAYsCaQxAl1gt4RfgB2IkCtdmffCIlNhAeQfR4cXrkPjp4"
+ "+ADURQB5BOKP70DwDVJ2AbMJitMBAogBayPrJWwiB17yAitCYEa/B27JkeMReC8euWZHi44H"
+ "GB55gOSRrzCPfIPm96coTgcIIAa8/ngBa2EBMwgwn2s/fAwdECDTI2hNFCI8Ago5kG3QKPmG"
+ "5JNnKD4BCCAGtHEs2PDoC/hIA7jAen/j9kdg8xpcYIGrD9I8AvEKcR5BnlIAV4vAwh7ska/Q"
+ "GPkOK7ueIjseIIAYcDROYJNqkBwC7NcCK/QH9x+R5RF4dgd55AmWihApg8B6JDAfgTzy6RPM"
+ "I9AYgRXCyFECEEAMOAYcENM4kKYJsIEFSrFP0LoeRHsGtWbHEhsP4IOo2tr3kLwE9AnYI1/g"
+ "eeQ7rBB+hpzdAQKIAXVGB9q/RfgD2nS/dUcb2B8EV0/098gTYC5BLre+QwphoE/eI1wPEEAM"
+ "2AZO4D6BNLFAJdZHkEceQ3vR1PbIA3SPwABkzOwxMJdAWinf4QCcuJ49Q7geIIAYUFYvoXgE"
+ "HCHgEusDqIcO6tgS0zDBUiE+RXRzQQM6qBkd4Yn7yHOg9xADKjCPfEXxyLdvX5B9AhBADBhZ"
+ "Hckj4KIXNDAKGmqHeuQZGR7B1l/HVuyiegLqEWAj9RHMI0Cf/EB4BcUjAAHEgJmyXiKVWJAq"
+ "BNg0gRS9pMQHZhOFfI8Aszty2vrxA5K4gGJw5wMEEAPy5BTKghlowoLmdKBHnjz5/OwZeR5B"
+ "GpAnyyNPYM0UkCfAAJpLvsDHggECCO6Rd2gegUcIsAr5CGpSPyalwEKtEKEtLewNRiRfaGMB"
+ "QK8A7X4CLYC/w3wCihhwEQxzP0AAMSAv8UPyCLwqBHoE2EdHH4klwyPYW74o0YHTI/AYQY6S"
+ "7+CCC7ZkECCAGOCbJhCrTV7CIwTSK7yrDR0sGzCPPHr8FN0jsMQFixKAAIJ75C3SshnI8itI"
+ "oxeUQ+6BapDPT2nikfvEeOThI8iwENQjP2EeAeV3qAcAAogBo68OA6+hHrkN9gh4sIEEr6A2"
+ "tRDTgDBfPHoAy+dITSttrOAeqIMFHk2BeuQnEIB8guIRgABC8cgr5DWvSOOK90Ctd3CnkKzi"
+ "F1wAo3kEPqqIUQdi9wh4NAUeIzCPgHqLUA8ABBADvMxCXY8M8gh4eg1YGd67D6oKn1HoEbTR"
+ "E1iFTtgj4CUdj8GjKV+/wmLkJyyXwDIJQADBPQJelIy8mhpSh4Da7/cHgUfAQ3XIHvmJ5hGA"
+ "AGJAVCJIWQS0eAnSyrp5CzR/AOuFkFuzo/XVHyGVVjg9gJiyBmUihEe+wzzyE8UnAAEE9Qgk"
+ "RuAp6xWsdQIbWSSpDiHJI/dJ9Mg3mEd+gj0CL4ABAgjhkTcoMQLMIW9AleGdO/fAWY0Sj6As"
+ "wyDTI6DRG0jHHeyRX79+QRMXzCMAAYSatF6hZXXwFMLDweGRxxCPQDMJ0CO/UDwCEEDIHkEq"
+ "s2BzhaApBNCg+OfPz8gF0LkRij3y6MnTZ7AY+QUGP8FFMLQmAQggBpR6/RU8h0CbJ3dAzRNg"
+ "M5qcCEFMkH9GHplDH/rB5pG7yACyjA3YcAR7BJLboR75jvAIQAAxQPYJw2Lk1UuklXGw5snj"
+ "x5R6BBonZHoE1gT+DKsSYTECye5fwHuZAAKIATmvvwIvDH85hDzyA55JAAII5JFX72DdXPhW"
+ "HMiygA/gWh3UYIQvziA1o8PXK0AXnj0CDU2DpjvvIVWG2shr4e8irURD+AU0CPEJWLeDPAJK"
+ "Wb9//4Z75AuoKQ8QQAyQHehYPAJapgGdZhscHnkE8wgsRsBpC+QRUNoCCCAGSMpC8chr2Lzn"
+ "jY/alHoEufhFNBbRa3TklPQRC7gLXmYB8shXaIz8+g3LJF8hLWCAAMLpEXB1ODg9Ao6R3zCf"
+ "QD0CEEDIHoF5Bb7C4TYoSkFOgM9EP0VxJEkZHeERuCfgKQfqAbhHIIugYUtpgWIghzx8As7t"
+ "sBgB+QSWtoCeAAggLB55jeQRUAOaSh5BrgjRPIIRE+geAY+iQosteIz8hlQlUI8ABBCKR14h"
+ "e+Q9uPAFjfNR5BGUWh2xxow0j9wFj0eBGykoMYLkEYAAwowR2HJ3SN9wMHrkB6T4BZfAcI8A"
+ "BBBmjMBS1gesHsEF0DM6PGHBhq0fIryhrY3sEVgxi3uLBkgePUZ+//7zBxQn8NYWQABBPPIO"
+ "ESOv4WXWDaBHwEPIyKUWsR6B1SDwvjrS4kWwR1BigpBHwFsYwJn9GzxGEB75+hXoCYAAgnkE"
+ "2oyH7zECNuEp9Ah07hDJIzBvoJa4KPsWcHrlHtQj0KQF9MYfsE9+/oB6BCCAUDzyGr51DZi0"
+ "BrVHwD4BF8AwjwAEEGrSeo3Y9UWER55B1g3g8Aik4IUva0dZE4te76FsWoICBBvJI8+QY+Q3"
+ "cowABBAss79FOoACusAM7BHQxNeTJ9gzO3oNjuyRzzg8AtmWh15zE/YIsCKBeOQrOLNDkxZS"
+ "jAAEECJpwc7SeANdv/+BZI9gX+2A4g1oqsK7jQyPR56ieAQlRgACCOqRd0hngkD3hQxij/zC"
+ "EiMAAYQcI8h7VHF6BGnxO3jFJ6618NAlG+j5A9GWIsUjoH0dD+B55Ce2UgsggJBiBHpiDkke"
+ "eQZy8NPPWJb0w/IHcm1+D7Z1j5A/kD0E2UkGrEgQHgHXIpAogXsEIIBIjBHIWgykWAA5Fus2"
+ "C1iyQktUcG+gOBgtMnB75AvCI2FhoCiBewQggFBjBHHGxCD2yA+sHgEIIJRSiwiPQOZsoB6B"
+ "bBpC8QjKTiRQ/niA2EX1Eb4jlAoeCYN55DvEIwABhFxqgRMX3CM3buL2CHTaB80j2LZUITwC"
+ "y+TYNiET45F7D558/gLzyB+ER6AxAhBAqDECLXwhHXaQR+6hegQ8OwDdaPEZXsIic5BXwiI3"
+ "S+5+RHcs0QDFI9+gHgkDeQS51AIIIAb46XFIHnk7uD3yC5tHAAII5JH379EyCcIj0LYWbP8U"
+ "pJcE3RaGyBJI6+MeIQ3xwuYI4ZkcvsGYLI/AxrWwewQggLB6BLp4HNyxgux1efIZaYXlpyeI"
+ "XA1eKPMJfTMq8oAi1CPwndJI275vI9PIAHN/OCizY/cINLMDBBA2jyDnkfvQzaawBjksMp5A"
+ "Vy09hq1eQp3qROlGwQtdbG7GCjA9AgrSz8/QPIJcagEEEMgjHz6AG/JvkU/GweqRxzg8gjb9"
+ "QSuPPH2GUmihegQggEAeuXHjPSJGIGcsImLkATaPwNIUcnJCzhtIc+hoGf0WmR4BOQSvRwAC"
+ "COYRpBh5gxwj4GHwx5B2E8wjSKXTE/SNRrBMjt0joEMrbkKObYKd+QDn4/YISCvII5AZK5hH"
+ "/qJ6BCCAEB55+xblFEWwR+5CVoI8eoxR12FLUihrAWDL+rTvIkUIzPmEPILsIUgzHlR8QmZ1"
+ "f/78/RvkjbC/KB4BCCAkj6AeVzR4PfIL6pEwlNYvQACBPPL2xof372Dn42GNkUeYrQ80jzxE"
+ "XwsA750jGia3iPYITAzmkbughVZPEFkE6BEggHsEdL4QQACBJ3pgHsEWIw9I98hDengEkrQg"
+ "HgFtHQMIIPDU201QAYx2GBnYIx+hS1oePcaanLAUubB0BWu4IycrVIdiA+gegXgGWPiCVoyB"
+ "Gyg/gLUIMKuDIgSYtKADdCA/AAQQ2CNv0TwC2XM/+DzyFegRYIcdVPZCkhbEI/dAfgAIIMj0"
+ "9I0b75DOHX4HPXXmNvhAovv3ifUIYq8XbNgH4pHb6B65CT0uiDiPgEa1QEvfnsJSFihhgWME"
+ "OmQK9gJAAEE8chNaACMfKwXxCOTcGFiVh1ZCAfmwA2VQd6whJqM+whu8EAfCPQIHN5EOEUKu"
+ "Z9A98ukpqBaBlllggOIRgACCeOTWzffwo6wRx9feAh+4AszvuDyCc9UrYkrtI1LLHZGkcHkE"
+ "S+YHZ3XQoprPsIEHSA75C2o0QtqMYC8ABBCyR6Bn3Q1Kj4DXPcA8AsnrYdDReIhHAAII4pHb"
+ "N99DowQ5Rm7eAp8+Q5RHkFa430ee+CfPI0ieAWf1Bw+gUwo/4P6AeAQRIwABhOoRlPPhPtyE"
+ "nT/z4BHK2UoYu3EePMBYIwOZHQd105EPB8PmETSAnv3BHrkPWpwJKXxhKQvskZ8/v8M8AhBA"
+ "0KWAtz68Rz/mDnQiECi7Yx4Shc0j97F4BOUcrdtopS5ejyB8BDpY6R6sLwIss+ARAvLIL6BH"
+ "oP74DxBACI+8H7QeAc26QZrwP9E9Ak9Z/wECCLZc9gb4mD5Uj3wArTu7izgoi2KP3CLdI6Dj"
+ "f0FbosANRmAl8geRRUDVIdAjUA8ABBDCIx/QPPIe6hHIli3YeVk4PQJfhww9mRCllQXxyG28"
+ "MQIVRDqXDnIMHGj3PKydBa7V//799w9cH0Jmp6EeAAggmEduQqLkPeoxkLfAKfQ+7OwCLB55"
+ "gLwQGb3o/Yg+AnQLe8GFnMuRPAECYI88fPIJNDQHap6A4+MftIGClLL+AwQQzCPA2hYeJ6ge"
+ "gewPGhiPQMZPgA1fWDsLWqv/gzQZkT0CEEAwj7wGtRs+YPHIHegio4HxCHiKB7ya8Ru0efIX"
+ "krJA9Tp4AR3s9AeAAIJvhIF6BHFMKugkSJhH7mH1COIwAGj/4x6isYh8vhzpHrmF5BHQgnb4"
+ "dMIfcA4B+gTuEZj7AQII7pGXt24Am46oHgHXq5BFRg8wt2yjbq1FWdGHPOmMfh4j3uoQ6ido"
+ "pQ46ZQk2MPcdXBn++QuPEXB//Tt8LzhAACE2i4Fs+PAByRvQenUAPQLOIeDKEN41BOcPcBaB"
+ "eATufIAAQvPIDZRjUgfaI5BxObS++r9/GE14EAAIICSPgK1A8QjFSQsph5DgkZtIHrn/4PEn"
+ "xKwIPGHBPPIV7nyAAELa4opixU1Uj4D3Bz1APgsTzSOoa14hKxswJmpvY+vlYsn04FEHcB1y"
+ "7yGkQwXpq8NyOqzBiBQh/wECCMkjb2C2wAIFfkzqXWhNQiePwIZPgBHyALRJ4StyDoF4BNqn"
+ "QrqtCCCAkLeBI/erERNiA+URyJzIk2dIs1Rgb0DKXtDCeOQI+Q8QQNg8ApuuRHgEujMbejTG"
+ "A4wDM5A6U9DGIopH0FrAmL7B9AhkcufBY8hUAqwf8g85Qn4g5ZD//wECCOW0AcgwMyI2oCUP"
+ "4nRqSKMLwyMYK1/Rl8qgD8Pj9QikAgGdjX3vwWPQpj3QeiDwkAMiQiApC9nxAAGEcnjFR5TJ"
+ "YvhCaGSP3Id2T/B5BHPNDwkegd4MA56jevDo0xfYwDU8Qv7B+4bIEfIfIIBQjxOB+OQOymH6"
+ "8PMssXoEY58XhR4BV16QLvZ9YFsRntHh3vgHrUNQc8j//wABRIZH7mN4BDOfgzyBaGlh8Qjm"
+ "wANafNwFpqtPT8HbE8ATCQiPhGFUhiAAEECoHnmFurQTiyfg+QTLhjXkpa8YGR2nR9CrEHj+"
+ "gC3qB/cLkfwB6at//4Z6QwlAAKEdgvQRzSNIp7fTxSO34Kua7kHbWN9gjUUMj6C6HCCA0I+l"
+ "+oh0OLU2Yhct7T0CHf25A11mBl/SD+mnI+cQzDoEBAACCJdHPiJ5BOMgHMiR4/dx78Mh2SOw"
+ "MTnQXUOgMIQMkaI1TVAqdXSPAAQQxtFt0PXcd7WxnJeOs5GI6hFEoYVtwQxamYXaRQerBk2K"
+ "f0LsTPgdhih54c13dH/8BwggzMP0IO5AHDaONMhOO48gJqfAM7jgcSzINiR4mxeWsMAR8h3D"
+ "2QABhMUjd1E8gjwqSmCPF2UeuQM9Ol8bMtiAWHONHB+w8V6MCPkPEEBYjjeEegR6EDLaIAPS"
+ "FAjGpmdUj9wh0iOwDsNteBnzCFaB/ICOLP5D8gikxMI8lxUggLAdponYxgiadUOMMKKMV9+7"
+ "By/N7uGs1WHewLLkAbtHwIetQ3flwjuF/9Bz+ncsrgYIIGyHsqJ6BPVMffTBd/weuXOHoEdg"
+ "s7fQchc00fcZsSnsdxhKhIBnDX9gSVj//wMEENZjclE88vgxxuo+KnsEceUTaFUVYkvYb8gU"
+ "wj+UEgtplBQFAAQQVo+8gx8Sg1gb9Amydw1+SwJyvifHI7cQMyCwy8RA8yCgmSl4/kDK6OA2"
+ "FmS09/sDbG4GCCDsR0kjTj0HH+j8CXbI+JMnj6B7KJDzPMGWL0aFCOKjRgh0hOMxJFl9A+/a"
+ "AY9iIWUQcImFI0L+AwQQjsO9YUc6o3jkE3wP9EPI0fWUeOQ2fAIXkjkgu6DAhx1Bu7ZIFSEi"
+ "YX3H4Y//AAGE67h1VI9Ajrx+irjoALbukiKP3ILHBviAioefwIv4vyIlK4wCC1d8/P8PEEC4"
+ "PHIfzSOwjSGwFZqw9IXNI1hHHrCs+kFawa8N3ooLPcPlB9JgHIo/fuIosUAAIIBwXknwCna6"
+ "IJJHYFvZIIeDQCd4EPsQULYbYQ6hIHkIedkypBEBqs1hh+r8xOYPaA2C85pEgADCfUkE7OhK"
+ "8ImG4PPb0XYXwjd6IjwCm829i3YJDzaPwLs94PmXx+D14pBzT37BVjcg1ejQhPUdp3MBAgjP"
+ "tR1vUT3yBePYc6hvwK0w1ObKXcLbRO6ANuDCLk158gmSqr5BvIESHdBRE/B84U3crgUIIHwX"
+ "qUCP2CbkkYcPHiDvECHdI4/hhe53aLGL7A/48A/u/AECAAGE97YYuE+QPfIV5pmnzz6DffMI"
+ "tLQG+QQd5Fndj2h77D9CW7iQQT/QQWog0+HHsmHxxl9YfKCOY6EDgADCe9nQW1jaeop8Dv1X"
+ "+P0AkLs0oDeJoHpEm4BHYMd7Qq4dgJ7c8gOy6egvarkLrwjx3rMNEED4r396CfYI9LQz1MPC"
+ "vyLd3PD08xPIlRqImNG+h3r1HOo1dNCblT5BDlP/ijiS4jdqdKDEB/5r3AECiMCFXK/AJ+5i"
+ "9QjMM89AaQy6vhmxAO0+zi4y9BRf6PGuiAPZfkL3tyBnc0i5CzmkgsB19AABROiKtFcPERdo"
+ "QDzyDQy/Ih+t/wyxnwferHyA1E9G6SxDDiP+hBIb3yHe+I3uDXC7hJj4+P8fIIAIXlr3EhTG"
+ "jyFH1UKjBH7K9jdErCBOE0C6swoLgLYVYLdYQI+M/QFfJ46azcMgWw0Jx8f//wABRPgawbcP"
+ "IZ0SqN1IB59Dj3FHzf6Yp2CjAHhRDj+/F5yowN5AzuSwZAU9juY2QWcCBBAxVyaCeyVPYCka"
+ "2R9wv6B4Bt6SwQKewiMW2RvQ1e5///1F8wc0fxDhSoAAIuqqzbfQVI3shm+gA4S/w49A/4Za"
+ "mH3BdnDCly/IiRNy4iLk+Abomh+UVAXb54K3PkcAgAAi7vLTh5BbOuDZE3rONtwj0JOEkX2C"
+ "4RlobQoPBuj5fjCPoFYefyEr339hHYvDCgACiMjraF9BbqqCHBeOODAcfmQt7KhqlOSGARDa"
+ "kP0AXYEF9wWkTQI79eQbkdeCAwQQsRcEI100g8UjsKOEkbzz9RumHyB6fkBOWoQe3PAHtq4a"
+ "qcyFeQR8fhaRDgQIIOKvbIYcAwqtwr4i++QHGKJEz3fUAuE7TC3cD6BaA7Kd5S960yoMsi36"
+ "J/jcVaKdBxBAJFyi/Qjhka/QvA51G8gjP9Di5zs6gJ6lCvEGzB+QxeF/kapAcNvqN+yoPOJd"
+ "BxBApFxrfgN8zwVG6vpBGPyEHUkI8QJ0jxRkkeU/aKH79y+syP0Fi44HJDgOIIBIu2getAkU"
+ "uTZB9wfkHEgQjeR4mA9+wX0B8QfUIyj+QNQdxOcOCAAIINI88p/hyZPPn5EbK3Cf/EQFv0AQ"
+ "Dn5Dj8j5DfMDNElB4uMv3BPgEhfStvpGossAAohE5f/fPv70Ca12/vEd7hOQ85HCH+x8mB+A"
+ "vvgNjwpYbCAAuKQCZw5IYfWBRIcBBBCpHoGkL/AwF6LtivAJcixAUxH0VAOUmEDyB3jbF7T6"
+ "gzQQYXt0SAMAAUSGR/6De4xPUS4FgfoEkZx+wz3yB8Uj4M1Rf5E8A/MGOIuD8zipuQMCAAKI"
+ "HI9AMv0XRHPlO1I9hxwhGB6BhD/CA2GQjAE7vQxyqvI3spwEEEDkeeT/68+fUdriKBU2wiPI"
+ "XglD+CQsDO6PMMg5Lb+gp8US3yRBBwABRKZHgAB25yJynYIovpD8ghIvcACVg5xSCEtS5GQO"
+ "KAAIIPI98p8BmrzgNT2KV5ALXah3fv9G8gHEDxBfQK8YILnIRQYAAUSBVtCMEOKWP6S2OXKs"
+ "IMcMqg+gyQnhi1sUOQUggCjzyP//z56h9ZZQEhhycYwKYIco/4Alqm8UOgQggCj1CKivgiWz"
+ "fEdqtGABiGsFIM3k15S7AiCAqOCR///fQHqAX7H0ubA1IVH6MEAtb6nhBoAAoopHoKXYl2fw"
+ "zI8xRIHomKD2jqlmPUAAUc8joPzy7BnqfZLfcACYPBUtBwgganoEAu48RR0xwQq0qW4tQABR"
+ "3yPALHMbv0fuvqWBpQABRAuPDAgACKBh4xGAABo2HgEIMABb8EQbIiGeqQAAAABJRU5ErkJg"
+ "gg==")
+
+#----------------------------------------------------------------------
+DownButton = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAACXBIWXMAAA7DAAAOwwHHb6hk"
+ "AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAA"
+ "F2+SX8VGAAADAFBMVEX//////8z//5n//2b//zP//wD/zP//zMz/zJn/zGb/zDP/zAD/mf//"
+ "mcz/mZn/mWb/mTP/mQD/Zv//Zsz/Zpn/Zmb/ZjP/ZgD/M///M8z/M5n/M2b/MzP/MwD/AP//"
+ "AMz/AJn/AGb/ADP/AADM///M/8zM/5nM/2bM/zPM/wDMzP/MzMzMzJnMzGbMzDPMzADMmf/M"
+ "mczMmZnMmWbMmTPMmQDMZv/MZszMZpnMZmbMZjPMZgDMM//MM8zMM5nMM2bMMzPMMwDMAP/M"
+ "AMzMAJnMAGbMADPMAACZ//+Z/8yZ/5mZ/2aZ/zOZ/wCZzP+ZzMyZzJmZzGaZzDOZzACZmf+Z"
+ "mcyZmZmZmWaZmTOZmQCZZv+ZZsyZZpmZZmaZZjOZZgCZM/+ZM8yZM5mZM2aZMzOZMwCZAP+Z"
+ "AMyZAJmZAGaZADOZAABm//9m/8xm/5lm/2Zm/zNm/wBmzP9mzMxmzJlmzGZmzDNmzABmmf9m"
+ "mcxmmZlmmWZmmTNmmQBmZv9mZsxmZplmZmZmZjNmZgBmM/9mM8xmM5lmM2ZmMzNmMwBmAP9m"
+ "AMxmAJlmAGZmADNmAAAz//8z/8wz/5kz/2Yz/zMz/wAzzP8zzMwzzJkzzGYzzDMzzAAzmf8z"
+ "mcwzmZkzmWYzmTMzmQAzZv8zZswzZpkzZmYzZjMzZgAzM/8zM8wzM5kzM2YzMzMzMwAzAP8z"
+ "AMwzAJkzAGYzADMzAAAA//8A/8wA/5kA/2YA/zMA/wAAzP8AzMwAzJkAzGYAzDMAzAAAmf8A"
+ "mcwAmZkAmWYAmTMAmQAAZv8AZswAZpkAZmYAZjMAZgAAM/8AM8wAM5kAM2YAMzMAMwAAAP8A"
+ "AMwAAJkAAGYAADMAAADV1dXU1NTT09PS0tLR0dHQ0NDOzs7Nzc3Ly8vKysrJycnIyMjGxsbD"
+ "w8PCwsL39/f09PTx8fHu7u7p6enk5OTf39/Z2dnW1tbPz8/Hx8fExMS/v7+7u7u3t7e0tLSw"
+ "sLCtra2pqamlpaWhoaGdnZ2Tk5OPj4////+ZlMjzAAABAHRSTlP/////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////"
+ "//////////////////////////////8AU/cHJQAAIMRJREFUeNpi+D9MAEAAMQwXjwAE0LDx"
+ "CEAA0cIjb+9/wQE+g8GdNzSwFCCAqO8R7S+4AcQjz549+0B1awECiJoeAbr0KwR8QwNQ4a9f"
+ "viK8A/IPFS0HCCAG6nvjGy4A8Qsibp5R0ysAAUQVj7yFeeA7CPzADr5DANRHyL6hSpYBCCAq"
+ "eOQ1NBJgfviJDSB7B9Mvryl3BUAAUeoRkCcgPgA59xcY/IYBKPcXlPEL4Smwb6ApjTr5BSCA"
+ "KPPI7a+QqEDyxm/sAMUrkJhBRAzEJ+8ocgpAAFHgEQZIbEAiA+aFP1gAmm+Q/PIdyStAvzyl"
+ "wDUAAcRAYaKCxQXcD2FQgN0zEJ/8gmYaSLRACmWwTz59Its5AAFEpkfewjwBiQhkH2AArL4B"
+ "e+Yn3C9wrzz9RGbGBwgg8jwCLmrh/vjzG+6Pv38x/QH3ye8/6EkMFiuIbP/06acnZDkJIIAY"
+ "yEtU4OgA+QIRFX+hANU3KMkLwyPwAgwSJ1/AcUKeVwACiIF8f/z8hUhSf+EewZmuUPMJwiff"
+ "kYtisFc+PSHDJwABRKpH3oN9AU5TUE/8hccFqk9gSQqpCEb4AZhHEEUxwi/w4uvTk7ckOgwg"
+ "gBhILXLBsQFJVMgJCs0bEF/AowAlIqBegBbDP38gl8RfYXn+yRMSXQYQQAykZnJQdPxE9cY/"
+ "NH8g/IDi8p+/sLZdfqK0XJCS10eSnAYQQKR45AHUH6BkhYiMf3CfhCF7A7VVgtrgggHUNhi4"
+ "wQZtf4Gi5Mnj9yQ4DiCAGEiKDkgWB3kD4oV/QAAkkOMCWk0g3P0dJ0BvGyO3WUDZ5OPHx8S7"
+ "DiCAiPcIuAqEFLngDP4PCv6iegPqD2TngZ0IcymssY/mG1gTH1Z4gTP8ExJ8AhBADERHByyT"
+ "QxPVP2SPQLwB8gRSM+o7om+I6Dti6XvBOipoLWJQgwWYvIjNKQABRKRH3kBzx29o7viH7A+E"
+ "N34h1QxInQ40gOad78jRhewRcJx8JLLJAhBADMQmqx9IeRzNG6AkBU5OP38gJw945xwToHoK"
+ "s3ePVJ98fPyIKCcCBBBRHrkJblhBklUYkjdAHgHFBjQygHEBb2wgjZigAQzvYHoFphvqEaLq"
+ "RoAAIsIjDLBk9Qc1OqCJCpIzIG0mtM44sN0EA6D0DgKfPoF4yB5CpDZknyB55PHDh0S4EiCA"
+ "CCu5Ayp24f74h5bJQakKxRufEZ749AnmfBj4+BHmmWdP4V4BewSRyBCtLkh18vHjo0dERApA"
+ "ABH0yGtoskLzBiRRQWMD6At44wKcRUHWP34MdMCjx1Dw6NFDMICIIHkI4h+UYgAx+gWu4Z8A"
+ "dT98RcidAAFEyCOvv4JrD1CTBCNZwWMD0rSApgWgHz5CHf7gIRw8eKCt/QAI4J75CE9qsGQG"
+ "jhiwP5A9AiqCifEJQAAxEPIHuDaH+AM5PqB5HJKooNnzKahdAcycIGeDgPb9+/e1oeA+lA3x"
+ "DCyqQDHzCZ5jMIdXIb2Tj2AzCfgEIIAYCPkDXO6CmogYhS4oWaGkKpAvQIEHCn2Qw+/fQwUw"
+ "b4Hj5REk4YG9AvcLFq88hcQJMHBe4nUqQADh9cjtb5DaHCV/QH0Bjo1vUF+AG6tAy8Bhf+/D"
+ "h7tYwYcPSB56AE9o0BwDjhp4/v8ML75B8Qz2iDbeHA8QQAx4Ox+g/AFuW6FkD2juAGcOaPcU"
+ "6A9QTECiAe6ROwgA8woIgLxyHx43sHhB9clnRCEO8shHcDbD51iAAGLA274CxQd6sgLXHeCy"
+ "ChQfkAwJSsTALAHyA9gbd7ACRLyAE959aLQ8APkFmA+eIOeXz5+RYwRUBIMyHh7HAgQQA/76"
+ "HJQ/UMpdSFUOzh3gsgpS1kP9AQlwiEduAwEO34CTGNgrD6A+eQgrxz49hZfI6B4BlSF4EhdA"
+ "ADHgaV/B4wMlf0Cyx/fvsMwBzhv3kSPiNgzgiBdEXrkPjxpwZnkMTWEIvzxD9cgDbZzOBQgg"
+ "BtztXUj9gdJmh5ZW4OiAduQ+QiMD5I3bIE+A8K1bt+AeuY3qr9tYvAJOYw8fPn70+COibgH5"
+ "5RmGR3AWwgABxIAnf0Drc5RS9w80WX0Fd36ePIHljbsQN0OcfQvqETSAGScwz8CzPbAyRYoV"
+ "aGMNVDvBPKKNK04AAogBd8ICtq8w88fv3z/h/ngKzOQPH0CLqTsIP9zC6RFISYbNIyCvQD0C"
+ "9gqkcQlvbhL2CEAA4fAIJF39Rs0f8GQFzh6g3IFIVLehLqfEI+DyC1pPPoG1YD6hewSHTwAC"
+ "iAFnR+rXL5QKBNpIBPsDVOg+BRW52veheQPug5sgQIZHoMnrEaTKh9UsiGYz3CNA1VidDBBA"
+ "WD3yECmjY40PUO4AZg5tSN4AxwTQ9TeRPIKIHjSPwCpGFI+APXMftVn5Edkv4Kb0Q2jTB+uM"
+ "EEAAMeAYaQB5BDNhgfIHqFECKq1AbUJ4soL6AArI8sh9FI+gRspHhEdAWrC5GSCAGHDUIKCM"
+ "jlzugvseP0FNRFChCMod4MwBzhuguLhJBY8g2soPYG0XKEDzCDafAAQQA9auLaRGR4kPcN8D"
+ "lK6AzfVPjx6BcscdaJUBcvsNIMDvEUQjBbdHkDI+oq2PxSNYXA0QQAzYWibf0Uos5PzxGZKs"
+ "7t2DJ6pbEG+geQSt9AJ7A5rREQC1kY/iGVgqewjrZz4CFfWwngHm1DxAADHgLrHgHoHWHxB/"
+ "AIvdx6D4+HAXXlRh88gtDI8gSiyiPAKNFrhHwDGC6OJgOBsggDA98h0to8PKK2j++AT0hjYi"
+ "WdHQI7BOC9xDeD0CEEAYHvkKGmv4jc0j0Ph49PA+MFkBqw6QD2jrEaTOMaTfD/fIB4zlRQAB"
+ "xIC15AV10VEqQmAGAeePT6Dy6sMHSNWBWlRhAuSMjuhoIVeH2DI6LgCqDe/d/wDrK6D7BCCA"
+ "MD2C1saCNhR/gJvtkPwBKnbhtTjVPQJLTsiegMmBm3XYPQIQQAwYEYJaYkEL3h+gZvuzp48f"
+ "AePjLqxgpY9HYKMYaN3ou2g+AQggBrT1SmCPICIEWCeC+ufQgvcTqHV1F+aRm/TxCCRLwPR8"
+ "+ADrvn1A7ZoABBADZtH7+88fhDf+ghvuYH8A+wWg+hzctoJn8Zuw2hDKhtCYDWBEpx0tj9/D"
+ "VVIhxwbcI0j90Lt3UZwOEEAMmN1bpN4UrAcC6p5DK0KER27g8wjWbhVsIIUWHgEIIAbUovc7"
+ "aFQR4Q/IQAMoo3/+DOrUgrqCsMYHvT0CH9dAJFdktwMEEANKI+v7D2SPwFq830EZ/Rmocw5q"
+ "mMAqCBp55AEyQPIIbKQMXg0DTUR2PEAAMWCOYyEnLFBGB5dYT8G9c1D/A+ILRDUI9QQyG1Yj"
+ "3kZt+0LyKJo/wIN1yB6BVH2I0WO4PyBDF7eR6to7SI4HCCBsHoE236FVOmjEBFyjQzpStxGl"
+ "FYpHYHykyv3mLbRyC5y0sXkEpfkO9QiIBqcuiEfgIzI4PAIQQAyoI71Iray/0D7IN3CJ9fER"
+ "pCN1h0iPoDTnyfbIA2SPYJT6t24jNYIBAogBtTJEamWBPQKpCr8Am4qgQbh7d+8gN0zo7RFE"
+ "zwdq561bCNcDBBAD8uollI46KGGBRqpBTRNgifUA2FT8gPAHiuPRPYAIMrS+IcQjiCFT1DHg"
+ "Bw8Q00JwH92HjMRCcjnMvvdAAPbIbbjzAQKIAaW5CBoihfgDOsb7E1r0gsevQHX6rZvEewSj"
+ "Zgd5hSiPIE90ARM01CMQ295j9whAADGgDMkhWieIzhS4afIAUhUi0hW5HrlLoUfeIwFQ8Qh3"
+ "PkAAMSAmPb/B50Kgy0sgHgH20UFDP/dBVeHNQeURkE/gDS6AAGJA6YjAptKho7zg3u3nZ8Cm"
+ "yX1wZ+r2zZsEPQJlwyotcMUFrgthnSrwJArqMNAD1J4gEgCXwCAdoLyO8MY7EAAnL3iUAAQQ"
+ "A7zd+/07Yk0AzCPfIW2sx5ASC1uDF8UfSBzkLiLK4PUHLDU6Po88gLR/7+LyCGypCkAAwTzy"
+ "5Su0ZxgGS1h/oK1eoD8egUqOO7ep4pF7pHoE0sHF4hGwV+C5BCCAGFCmEf4gLRaFdW9BvXTI"
+ "YNwg8cg7BADGCcwjAAGE5JGfSCv84K1eUB0CbCwCPXIbI6Oje+QGmkduIvVKwM2su9jG5Qh4"
+ "5OGDh2CPAH1y8waaP5A9AhBAGB6BLYiD1iFfwHUIMECI9Qiemh0xcII8UoLkCUyPgL1yHzTo"
+ "APII2Cc4PAIQQFCPfIGNv4eh5JAv0FYWpIVAVY9oYxu7wuIRcMF1HzwgCOw5oHgD7JWb0DoR"
+ "IIAQHvmJWOYHnwkBeeTxQ8g476DzyFsUjwAEEAO0zEKMnsDWZwD7IV8hleF96DjvLSweQfYA"
+ "No/cQp47BNUhmLNU0LYVzOGP0QB4hh1UlyA8AvbC27dg6ga05QgQQHCP/ED1yK9fkMrw0xPE"
+ "gDWucRNSPIIx3Qavw4nxCHIOgXrkPdQjAAHEgFSLILIIZKwXPHLyGBStd2jvkYdY/IBY6gVM"
+ "FUgeeQvyBRiA0hbEIwABxABtwiNG4BGD1sBa/dPHR/dAzfdB5hG4P4A+gXoEIICQPQJb7w4b"
+ "AgJ2qIC1+r170CE5DMejd64w2l3o8yMf0DtTyHn8MU4AHodHeOQtMgBmkptgLwAEEGaMQBZc"
+ "QponcI/cun0Tt0ewdhexllqwihBzyuAR0R55i90jAAEE9oj2V+gII9Qjf2DNk6fQ5glmsqLY"
+ "I+i1+WNyY+T9DfBSG4AAYoCVvlCPQBa5w9tZ8ObJ4PEIeoy8fw/OJAABBPLIW3Dp+xvukT/I"
+ "XVxt1PbiLbTJT6weuQGfAbqJaGtBV2ppQxYHaD9E8gg+X0BmD0FDH8DgxPQIuNwC9a4AAgjk"
+ "kfvQagTNI6AuFcwjt28htWixVYqoNT2qR+7APIKeyR/AKsLHBMAj8EIqYPsXu0dAaQsggBjA"
+ "G7i/ocYIuPAFLZsBDZ7cvYuY9rxFcF4Eq0dgjXik5ZlEFLsoiQu06uXObSweAWX3G0BPAAQQ"
+ "wiNIMQJtMD4bSh4BCCAsMfIHPnoCbjDexVjChJxXiPUIYi0j1COPEEtmHxPjEaBP7iJ55A0Q"
+ "oHgEIIAwY+QP2CPg6hDa8kX2yE20vEJ4zgoxwXPvPmKRGaKRi83hH8GruSH0RyweAXnizds3"
+ "8HIL6AmAAMKMkT+IOcNPj6jmEdS1pYTqQEIeAUcINE6gHgEIICwx8hvWhB+0HgH64A3cK1CP"
+ "AAQQlhj5DW3Cg/oiMI/cQvYInE3IM7Chh7uwkSz4gnIsHvkIBY+hK2c/IglgeOQNhkcAAgji"
+ "EaQK8Q9s+QxoTgQywnjnDmKdD7JHcJZk8AVo0KoQuvpaGxYbWKLjI7K7Hz9B9ghY7CHMI8gp"
+ "C9kjAAGEyyPg6hCLR5BpfB5BDKBAWr3Ia0mxZXLEKrOPH1HZaB6BxchrIIB4BOgVoCcAAgjT"
+ "I78Ht0dQUxbQJ6AOCtATAAGE6pE/UI9A1gcAPaKN7hEYuIW2cAbDAyD6DswjiGQF8gCqR2CO"
+ "fYILfAQvYAZ55A5KjAAxNG2BPAIQQMgeAUXJHzSPgGZFsHkE1tWCiWLGBKQ3BfcI0t4E1E1L"
+ "ODyCIgL0CKhqvnPzBsgjb1BzOyRpAQQQwiO/oMdPwJf8IXnkDpbFr6gewbrWF6VpgrZMEWdM"
+ "QHeYwdYxf8LiETB4jcjtII8ABBBajAwhj7xB9QhAAFEUI7B6Atd6eFgbCzwHAsnmiCIVPfkg"
+ "9ilC1l5Dl8hj8chbSKEFiROYRwACCC2zk+IR6KYEnLLQuhA61gDfu4MUER+RowC2ghzJI5+g"
+ "HvkI9chtpBh5/RpSAMPyCEAAIccIkke+E+URzJ0VWJMVuGeLsgMRJQ6eQrZeQjyBtIsUwsXq"
+ "kddQAIwUWIwABBBGjPwmIUYGzCNwn7yGxwhAACHFyC9YHvlFcYwgFtDcgxW88GSFlIpg/kD3"
+ "yFO4BIEYQUpaAAGEkdnBu1bBY1rPnnzE9Ai6u7FHCGLi8z4Oj3zC45GnxHsEESMAAQT1CGSA"
+ "DuQVcj2CbR8V0sL9RyiJCppqPuHyCBIbxSOwJgoiQuAeAQggbB75ORQ9AhBAII98/gwdjQed"
+ "ZwTeY4/dI3eQdrUhOxtl/T582SI0k8N3T6F7A5QXYA7G8AjSRni4R+7dufX+/Vu0lAX3CEAA"
+ "MUDP84MesPEb6pHvSB75cAdthyTWnXl3kddYIwaqYQNwKHkDOeSfIgEUDtoeK6BHbt9CixBk"
+ "jwAEECxGQEucYEfj/ER45AF4OT98oSvCR1g24mLM2GImq09YnYofQD3y4P6HWzch9fprZI+8"
+ "gXoEIICQPAKPkcHtEeRaBKnUAgggqEe+wGLkF9wjoGk38OADTo98gK6ZRF+vj7xiFCV/oOwu"
+ "JMUj4G2CH24hF76vwAgRIwABhMUjP2E1+yfogswPSB5BiwSsGw/g44na0I1fSPGB1yNwSWRF"
+ "T2AeuYvskVdAgBIjAAGE6pFfkLwO37oDWgtP2CP3sGzAh+8mRs7oT6EnipDiEfDZC2B33L0J"
+ "7h++gXoD4hNIXxfoCYAAwoiRX4gYGZQegWSRV0gxAvEIQACBPHLn2ecv0JOaoCcYQTdNfgJ1"
+ "lRGrVUnyyEMkb1DBI8C8Cumxv8ESI6DFpgABBPLIm2dfMD3yBbdHkDP5PSwAl0eekuWRT6ge"
+ "AfvkFWqMgCZ6AAIIPPX2DFz+Qj3yE3zQCXQbK2xf0weMUgrP5iLYtAHk2JCP8O4T3CPIAOED"
+ "JB9ieuQ+0CNo/nj1ClIhglPWf4AAAnvk7ufPEI/8hMUIaP/n4PLIvbu336P54xU0RsCToQAB"
+ "BJmeBnrkK+REGsiZg9+huR101II2ikfQAYZHkOsPJI+A2lXkeATU2AdNvYHmQt9hegQcI2Av"
+ "AAQQzCNfvsKOwvwJPZfiC3yH9L3797DGBEGPPIZ5BKlNhc8jOKp1kEc+YPfIa7hHAAII2SPg"
+ "XIIcI89AZoAWrN7D6wH0xQyoAz/QI1xweQSrp1DbvqDp6Q/AXhWiFnkJBLBCC+oRgACCeOQZ"
+ "uCb5Djs8GeGRj4PCI8D2xd07wHod2R/oHgEIIKhHnkGj5AfsWE7w0S3PoI2D+7CNWjg8grEh"
+ "B3wQBekeeYbLI9rad27ffA9LWC/hHoEMYoO9ABBAlHgEfjwQ+mIGkEegm54hcx3U8MgNLB5B"
+ "yiMAAQRdCgjyCDS7w058BZ/rACz7IEvxsJxphH2h6APUjI44SYsYj2CkM2iDEeiRW4jCF+oP"
+ "lLz+HyCAEB75Aj4X88cPZI88HSQeuX8fmLIgHnmF7BFEFvkPEECw5bIgj0AS1w+oR75CD6IB"
+ "reqGbIMaKI+AGq6QBiMiYSE8AvUAQADh8QikSwLxiDYuj2hj2awGzSHwgV7MniEpHgFvO/8A"
+ "iRA8HgEIILhHwD5BeOQ7xCNPwR55AN20hWf3oDZmfFDBI+BDwkDNkztoOeQluD58g+QRgACC"
+ "eeQZ+Ag46PHpMI98gXjk4UB6BLSN88PtW+8wIwTiEdjZIgABBPPIG/A5YwiPQM7eBXd3YQeS"
+ "EOURlKnnj4gWI3keAWd1bfC8CKo/ECkLthMGIIDgG2HAUYIUI7DzgcAtHUyPwHZoY/MIyqwU"
+ "YtqDZI+Ahx2ALYu74MoQ3SOvUVLWf4AAQmxNguQScBEMPdkZfGDTp4/Q48zwnwUAW7eEOu0M"
+ "bTCS4xFYwnpw/wNG0QuNEZA/XsDcDxBAiM1izz5//gK98gFybO3Xr9DzzMBV0gB4BJKw7n0A"
+ "LZwD9dVfIXvkNUqZ9f8/QAAheQSR32FnbYPPAhtIjwCLXnCH6h1SifUC7BHYUBDc+QABhOIR"
+ "SDsFcd8Jske0CXsEc0UDondIokeg0z2gEV+sHnkFHp1D9ghAACFtcX0GyyWwc4TB52E+gzWk"
+ "0eMEc9Ur+loyyMwtWTU7eKAespcI3g8B++MFEMCyCLI//gMEEJJH3kF8AjkTGXZNAGiNEOQM"
+ "RnI9QkozHqnAgjZOPsDGF8EeefEC4hFYgxHpdGaAAELeBv4MESdIHoE0E0Art+jnEcisHCiH"
+ "3EZp9aJ7BMnxAAGE7JGnzyBHvH5F9chTqEe0cZ6ZAc7lmB5BrCkhzSOweV3QmTi3biJ55AWy"
+ "R96gegQggFBOG3gKOUcU5hPoOaXgsxjBuQTppBL0dfoYay3h055A+hPWkThCCQuUQ+5Cpz/B"
+ "Aw5wj8CaJ8iOBwgglMMrPqEkrq8wj0BOpkY9coVQskI5eY1Ej4C9Ackh8GFSNH+8Qo+Q/wAB"
+ "hHqcyNOnz6BxAj/vHXqsJCUe+USGR0BLzZBKrNcvX+JNWP//AwQQqkc+fYJWi9T1yFMSPPIU"
+ "mJIhxcsDRIkFL3lxewQggFA98voT7PxgxHVmEI8AI/oh5EQl2JFEaBu3sS4axTfdht0Xz6Dr"
+ "gUAZ/Q64bYIoeZ8/RymyUA8yBgggtEOQnmD1CPToVeRjV2jkEViBBa0KIbO40AzyHMkjqJUh"
+ "CAAEEPqxVJ+gGR7lQGfIwcTwoyvBB9yS4pFP2DyDuwIBzaqDlvTDRt8hNchzsEdwJKz//wEC"
+ "CN0jT548hfkEcZg9uNyCHJgOO4gM0UiE7KfFtukAZW6dCI8Aswd0rBcUH6A5XGgbC5RBniN5"
+ "5A0WjwAEEMbRbcBSHzVOYAfRQ/fRoR1zh2+tPsqSpk9ofsDwzFNY9gANQEG2WEBXB7yEZJDn"
+ "0LIXa4T8BwggzMP0sHrkGXiW4jGtPIK8Tgs8/APehgRac/0aJWGBPPL6FShCMJwNEECYHgFV"
+ "xMinuNPRI5CzPsFzIe+Rpqcg3sCbQ/7/BwggTI+8hZ8Wjri04hn8ugaERyC7ox7i2M+CvoL0"
+ "EwGPgIoEyBQC+HC4m+9QmopQf8ByCEqzFwoAAgjbYZqgxPUMfoEDFo+gHDqIiBvUMQdUb3zC"
+ "mPBE9wi04Y6oP2AFFpYSC4urAQII26GskKUW8KPosXoEtc2IzSN4khW6R57COyCPtCH1B7QC"
+ "weURLI4GCCCsx+SC55KRTz3H7hFtIj3yCY9HkNbNgFvYHz6AeiDQtTPQLggig0DXNWFzM0AA"
+ "YfXIDdgCGMzT22EtLuSDWQh65CkRHvkIObb97t1bN2FbEmBdKUQGgXgE62WpAAGE/ShpUIHz"
+ "CXFDACTyYefpa6N3rMDnjKLld2SPPMXpEfhlK+CNFfeRNk1C59hgBRahhPX/P0AA4TjcGxyk"
+ "sDiBpuInsMsacJ1mi73oxbdGCzLGAElWkNNwbkI37UAqdLg/niOVWNhdDBBAuI5bhywWQ8mO"
+ "NPAI/Jzoh5ATOUH9QXh5RUp8/P8PEEA4PfIIlDygZ+rDp/OAHnmEOpzyAFqnYHoEW+sXNlYH"
+ "W4wJ8Qd4lBx0NtFNRDWINT7weQQggHBeSfAKtLMAyRmwqftH8GtS7t+7j76gCZtX0G9OAnvg"
+ "EyJvQEZogLU5YgfVa2hDEV6jv8Ac60UHAAGE+5KIhw/h909Ai3kMj0BH5RG9RGyNlE9IAHkt"
+ "OSw2wPeWQOID7g/kcpeo+Pj/HyCA8Fzb8fYh0pH6iOPbUT2Cuk0S9xYwjH1HkCuJoLd9IMUG"
+ "0ggWvKEI9wae69IAAgjfRSpoHvkI8wjsJGT47S4oHoF5Bst5/E8QQ0SwkwPAdxogzg6ArFdE"
+ "TVa4+yDIACCA8N4Wg7JzBdx+ghy38gB65iDS+iD0zXmwiwU+YomJjx8ht0NpQ7xx+xasSfIG"
+ "rZkIbyhC/YHPsQABhPeyobfw+yeQXQD2CHjtFspqofso+z7hHsECYFcr3YdGB2JPNLwaRPMI"
+ "wYT1/z9AAOG//unVI+T9j6geQb1PCLatGFtj8hHm2V/a0BOIb99E2+yJHB+o+QN3gQUGAAFE"
+ "4EKuVw/R+k7QM8jA7riL9coaZM88xHbMH3jKHnYkBux8ENiy5JeY6Qo6WYjfH/8BAojQFWmv"
+ "cJ7TdxdlMw/y+mzktdios0FIJ3qCjsO48R4lOiBTa+jx8Qqyue0lAYcCBBDBS+teoaZ7SKMR"
+ "cUwq5kYl5L3r6AB2hPJdZG+g+OMFotkOndF5/ZqI+Pj/HyCACF8j+Bb5hNGH6B7B3KAP2dKH"
+ "9WoxxHmkkNOMEDn8NWyiE7nVjpQ/CN+3CRBAxFyZ+AAVIHvkFvaDK7Dd/ATbTHoDdpDc27co"
+ "mRw2vIvwB3yJ8lsiXAkQQERdtfkWMYANLnHug0reO/AjnmDnvULP5YQf/YK+QRz5KDw0TyCP"
+ "UsOHqokqdmEAIICIu/wUNb9CVs+CPXIT+eBaZK8gvIM4iAfVG6geeYnqEVh0vCZQnyMAQAAR"
+ "eR3tK6QuCIZH3qOfA4k42BJVHHEqyxuEJ2Cp6iXCE4g1MxiD7jgBQAARe0Ew0sUA9xC3uSE8"
+ "8o4IgPAFPDLgyeolcmzAcweukQYsACCAiL+yGeqRe7CLq2Bnx2PGB/RQNchhd2hH5MA21b9G"
+ "TlOovoAtu3xDdLICAYAAIuES7fvIZ+mjeQRxduJbzNN90FIUYo8UfG0Jki9evkLkjjck3DYP"
+ "EECkXGv+jpBHwDGB1QPIm+mhnkBe64Pii1ew2MA+7oMDAAQQaRfNwzxyF0eMYIkAlPMAXr9B"
+ "eALJHyiryeDbC9+S5DSAACLNI/8Z7kHa79ADLWAeeYd2fCIsFtCONUDxBaZHYP4AJ6q3JLoM"
+ "IIBIVP7/DbRHdQdyjjuqR3AmKKSNg69eY/cI0iYdcHS8JtFhAAFEqkcg6QveCkfxyDvs5ROK"
+ "N5DiA+yRV8h7KGAl7tt3pLsKIIDI8Mh/XB7BWkIhe+M1si/QAKzEJT13QABAAJHjEaBXwB5B"
+ "tLKwxsgbjBh5hRohyFHx+vUbSrzx/z9AAJHnkf+vkDxyg0CMoOYQHJHx+g0sWb0kz0UAAUSm"
+ "R0C7F+F3HbxHbw2iHR31GjV5gTMK6g5oxIlyZDsHIIDI98h/BmgzHrldi80foLB+jQu8eY3s"
+ "DQpcAxBAFGgFFcaIrhL6SbzYanM0P6BEBekFLioACCDKPPL/P7QFjFkpolbp8DT2BtUTSEfi"
+ "UegQgACi1CNA8BJWDKMnrzcQ/Aarp5Aj490Lyl0BEEBU8Mj//69vofVk35IAIFttKQYAAUQV"
+ "j0ASGTzjox/B/fYdZqMYctI4xQkKAQACiHoe+f8fOtSAWiBD+ihvMbuLVPXG//8AAURNj0CH"
+ "XCCjKzh78hBvUN1agACivkeAWeYtfo+8fUUDSwECiBYeGRAAEEDDxiMAATRsPAIQYAAZi6PF"
+ "fdLmvAAAAABJRU5ErkJggg==")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/shortcuteditor.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/shortcuteditor.py
new file mode 100644
index 0000000..25c8ec4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/shortcuteditor.py
@@ -0,0 +1,2631 @@
+# --------------------------------------------------------------------------------- #
+# SHORTCUTEDITOR wxPython IMPLEMENTATION
+# Inspired By the GIMP Shortcut Editor.
+#
+# Andrea Gavana, @ 05 March 2012
+# Latest Revision: 21 Jun 2012, 20.00 GMT
+#
+#
+# TODO List
+#
+# 1. Check the various IDs in the KEYMAP dictionary to try and understand if all
+# the possible shortcut combinations can be handled.
+#
+# 2. Verify that the current shortcut handling is working as advertised.
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@maerskoil.com
+# andrea.gavana@gmail.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+
+"""
+:class:`ShortcutEditor` is a widget that allows the user to customize and change keyboard
+shortcuts via a dialog. It can be used to edit :class:`MenuItem` shortcuts or accelerators
+defined in a :class:`AcceleratorTable`.
+
+.. note::
+
+ :class:`ShortcutEditor` **requires** the minimum AGW version 0.9.3 or the current
+ SVN, for the various enhancements made to the :class:`~lib.agw.hypertreelist.HyperTreeList`
+ and :class:`~lib.agw.genericmessagedialog.GenericMessageDialog`
+ widgets.
+
+
+Description
+===========
+
+:class:`ShortcutEditor` is a widget that allows the user to customize and change keyboard
+shortcuts via a dialog. It can be used to edit :class:`MenuItem` shortcuts or accelerators
+defined in a :class:`AcceleratorTable`.
+
+The interface itself is very much inpired by the GIMP shortcut editor:
+
+http://graphicssoft.about.com/od/gimptutorials/tp/keyboard-shortcut-editor.htm
+
+There are very few minor UI differences between :class:`ShortcutEditor` and the GIMP one,
+although the behaviour should be pretty much equivalent.
+
+Various features:
+
+* Shortcuts are listed in a tree-like structure, pretty much reflecting a menu
+ hierarchy (as most of the time :class:`ShortcutEditor` is used to edit :class:`MenuItem`
+ shortcuts);
+* Accelerators defined via :class:`AcceleratorTable` are handled in a similar way;
+* Support for I18N;
+* Ability to restore default shortcuts/accelerators via a UI button;
+* Possibility to send back the new/updated shortcuts to the original :class:`MenuBar` or
+ the original :class:`AcceleratorTable`;
+* Filters on the shortcuts label (case-insensitive);
+* Basic help window with instructions (customizable via meth:`~ShortcutEditor.SetHTMLHelpFile`), via
+ the ``Help`` button.
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+UI Interactions
+===============
+
+1. In the :class:`ShortcutEditor` dialog you can open sub-sections by clicking the small box
+ with a + sign in it next to each section name. In the screen grab, you can see I've
+ opened the *Options* sub-section as I'm going to add a keyboard shortcut to the
+ *OptionsItem 1* item.
+
+ .. figure:: _static/images/sphinxdocs/ShortcutEditor_1_thumb.png
+ :alt: Open Subsections
+ :figclass: floatcenter
+ :target: _static/images/sphinxdocs/ShortcutEditor_1.png
+
+ **Figure 1**
+
+
+2. Now you need to scroll to the tool or command that you want to edit and click on it
+ to select it. When selected, the text for that tool in the *Shortcut* column changes
+ to read 'New accelerator...' and you can press the key or combination of keys you
+ want to assign as a shortcut.
+
+ .. figure:: _static/images/sphinxdocs/ShortcutEditor_2_thumb.png
+ :alt: Assign Shortcut
+ :figclass: floatcenter
+ :target: _static/images/sphinxdocs/ShortcutEditor_2.png
+
+ **Figure 2**
+
+
+3. I've changed the *OptionsItem 1*'s keyboard shortcut to ``Shift+Ctrl+F`` by pressing
+ the ``Shift``, ``Ctrl`` and ``F`` keys simultaneously. If you want to remove a keyboard
+ shortcut from any tool or command, just click on it to select it and then when the
+ 'New accelerator...' text displays, press the backspace key and the text will change
+ to 'Disabled'.
+
+ Once you're happy that your keyboard shortcuts are set up as you wish, simply click
+ the ``OK`` button.
+
+ .. figure:: _static/images/sphinxdocs/ShortcutEditor_3_thumb.png
+ :alt: Remove/Save Shortcuts
+ :figclass: floatcenter
+ :target: _static/images/sphinxdocs/ShortcutEditor_3.png
+
+ **Figure 3**
+
+
+4. If you thought my choice of ``Shift+Ctrl+F`` was an odd selection, I chose it because
+ it was a keyboard combination that hadn't already been assigned to any tool or command.
+ If you try to assign a keyboard shortcut that is already in use, an alert will open
+ telling you what the shortcut is currently being used for. If you want to keep the
+ original shortcut, just click the ``Cancel`` button, otherwise click ``Reassign shortcut``
+ to make the shortcut apply to your new selection.
+
+ .. figure:: _static/images/sphinxdocs/ShortcutEditor_4_thumb.png
+ :alt: Reassigning Shortcuts
+ :figclass: floatcenter
+ :target: _static/images/sphinxdocs/ShortcutEditor_4.png
+
+ **Figure 4**
+
+
+
+Base Functionalities
+====================
+
+There are basically three ways to populate the :class:`ShortcutEditor` dialog, depending on
+your needs. These approaches can be combined if needed.
+
+1) Use the meth:`~ShortcutEditor.FromMenuBar` method: if you need to give your user the ability to edit
+ the various :class:`MenuItem` shortcuts in your application, you can create :class:`ShortcutEditor`
+ in this way::
+
+ # Build your wx.MenuBar first!!!
+ # "self" is an instance of wx.TopLevelWindow
+
+ dlg = ShortcutEditor(self)
+ dlg.FromMenuBar(self)
+
+ # Here the user will make all the various modifications
+ # to the shortcuts
+
+ if dlg.ShowModal() == wx.ID_OK:
+ # Changes accepted, send back the new shortcuts to
+ # the TLW wx.MenuBar
+ dlg.ToMenuBar(self)
+
+ dlg.Destroy()
+
+
+2) Use the meth:`~ShortcutEditor.FromAcceleratorTable` method: if you need to give your user the ability to edit
+ the various accelerators you set via :class:`AcceleratorTable` in your application, you can
+ create :class:`ShortcutEditor` in this way::
+
+ # Build your wx.AcceleratorTable first!!!
+ # "accelTable" is a list of tuples (4 elements per tuple)
+
+ accelTable = []
+
+ # Every tuple is defined in this way:
+
+ for label, flags, keyCode, cmdID in my_accelerators:
+ # label: the string used to show the accelerator into the ShortcutEditor dialog
+ # flags: a bitmask of wx.ACCEL_ALT, wx.ACCEL_SHIFT, wx.ACCEL_CTRL, wx.ACCEL_CMD,
+ # or wx.ACCEL_NORMAL used to specify which modifier keys are held down
+ # keyCode: the keycode to be detected (i.e., ord('b'), wx.WXK_F10, etc...)
+ # cmdID: the menu or control command ID to use for the accelerator event.
+
+ accel_tuple = (label, flags, keyCode, cmdID)
+ accelTable.append(accel_tuple)
+
+ dlg = ShortcutEditor(self)
+ dlg.FromAcceleratorTable(accelTable)
+
+ # Here the user will make all the various modifications
+ # to the shortcuts
+
+ if dlg.ShowModal() == wx.ID_OK:
+ # Changes accepted, send back the new shortcuts to
+ # the window with the wx.AcceleratorTable:
+ dlg.ToAcceleratorTable(self)
+
+ dlg.Destroy()
+
+
+3) Build your own hierarchy of shortcuts using meth:`~ShortcutEditor.GetShortcutManager`::
+
+ dlg = ShortcutEditor(self)
+ manager = dlg.GetShortcutManager()
+
+ for label, accelerator, bitmap, help, cmdID in my_list:
+ shortcut = Shortcut(label, accelerator, bitmap, help, accelId=cmdID)
+ manager.AppendItem(shortcut)
+
+ dlg.ShowModal()
+ dlg.Destroy()
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.shortcuteditor as SE
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "ShortcutEditor Demo")
+
+ bar = wx.MenuBar()
+ menu = wx.Menu()
+
+ menu.Append(101, "&Mercury", "This the text in the Statusbar")
+ menu.Append(102, "&Venus", "")
+ menu.Append(103, "&Earth", "You may select Earth too")
+ menu.AppendSeparator()
+ menu.Append(104, "&Close", "Close this frame")
+
+ bar.Append(menu, 'File')
+ self.SetMenuBar(bar)
+
+ dlg = SE.ShortcutEditor(self)
+ dlg.FromMenuBar(self)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ # Changes accepted, send back the new shortcuts to the TLW wx.MenuBar
+ dlg.ToMenuBar(self)
+
+ dlg.Destroy()
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+========================= ==================================================
+Event Name Description
+========================= ==================================================
+``EVT_SHORTCUT_CHANGING`` Event emitted when the user is about to change a shortcut.
+``EVT_SHORTCUT_CHANGED`` Event emitted when the user has changed a shortcut.
+========================= ==================================================
+
+
+Supported Platforms
+===================
+
+:class:`ShortcutEditor` has been tested on the following platforms:
+ * Windows (Windows Vista/7);
+
+
+License And Version
+===================
+
+:class:`ShortcutEditor` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 21 Jun 2012, 20.00 GMT
+
+Version 0.1
+
+.. versionadded:: 0.9.3
+
+"""
+
+# Version Info
+__version__ = "0.1"
+
+import wx
+import os
+import sys
+
+import wx.html
+
+import wx.lib.buttons as buttons
+from wx.lib.embeddedimage import PyEmbeddedImage
+from wx.lib.mixins import treemixin
+
+# AGW stuff
+import hypertreelist as HTL
+import genericmessagedialog as GMD
+
+# add support for I18N
+_ = wx.GetTranslation
+
+try:
+ dirName = os.path.dirname(os.path.abspath(__file__))
+except:
+ dirName = os.path.dirname(os.path.abspath(sys.argv[0]))
+
+
+# ----------------------------------------------------------------------------
+# Constants
+# ----------------------------------------------------------------------------
+
+DATA_DIR = os.path.join(dirName, 'data')
+""" The folder where the default HTML help for :class:`ShortcutEditor` lives. """
+
+# These commented out things need to be taken into account somehow, but I
+# have no idea how to treat them and even if they could be valid accelerators
+
+KEYMAP = {
+ wx.WXK_BACK : 'Back',
+ wx.WXK_TAB : 'Tab',
+ wx.WXK_RETURN : 'Enter',
+ wx.WXK_ESCAPE : 'Esc',
+ wx.WXK_SPACE : 'Space',
+ wx.WXK_DELETE : 'Delete',
+ wx.WXK_START : 'Start',
+ wx.WXK_CANCEL : 'Cancel',
+ wx.WXK_CLEAR : 'Clear',
+ wx.WXK_MENU : 'Menu',
+ wx.WXK_PAUSE : 'Pause',
+ wx.WXK_CAPITAL : 'Capital',
+
+ wx.WXK_END : 'End',
+ wx.WXK_HOME : 'Home',
+ wx.WXK_LEFT : 'Left',
+ wx.WXK_UP : 'Up',
+ wx.WXK_RIGHT : 'Right',
+ wx.WXK_DOWN : 'Down',
+ wx.WXK_SELECT : 'Select',
+ wx.WXK_PRINT : 'Print',
+ wx.WXK_EXECUTE : 'Execute',
+ wx.WXK_SNAPSHOT : 'Snapshot',
+ wx.WXK_INSERT : 'Insert',
+ wx.WXK_HELP : 'Help',
+# wx.WXK_NUMPAD0 : 'WXK_NUMPAD0',
+# wx.WXK_NUMPAD1 : 'WXK_NUMPAD1',
+# wx.WXK_NUMPAD2 : 'WXK_NUMPAD2',
+# wx.WXK_NUMPAD3 : 'WXK_NUMPAD3',
+# wx.WXK_NUMPAD4 : 'WXK_NUMPAD4',
+# wx.WXK_NUMPAD5 : 'WXK_NUMPAD5',
+# wx.WXK_NUMPAD6 : 'WXK_NUMPAD6',
+# wx.WXK_NUMPAD7 : 'WXK_NUMPAD7',
+# wx.WXK_NUMPAD8 : 'WXK_NUMPAD8',
+# wx.WXK_NUMPAD9 : 'WXK_NUMPAD9',
+ wx.WXK_MULTIPLY : '*',
+ wx.WXK_ADD : '+',
+# wx.WXK_SEPARATOR : 'WXK_SEPARATOR',
+ wx.WXK_SUBTRACT : '-',
+ wx.WXK_DECIMAL : '.',
+ wx.WXK_DIVIDE : '/',
+ wx.WXK_F1 : 'F1',
+ wx.WXK_F2 : 'F2',
+ wx.WXK_F3 : 'F3',
+ wx.WXK_F4 : 'F4',
+ wx.WXK_F5 : 'F5',
+ wx.WXK_F6 : 'F6',
+ wx.WXK_F7 : 'F7',
+ wx.WXK_F8 : 'F8',
+ wx.WXK_F9 : 'F9',
+ wx.WXK_F10 : 'F10',
+ wx.WXK_F11 : 'F11',
+ wx.WXK_F12 : 'F12',
+ wx.WXK_F13 : 'F13',
+ wx.WXK_F14 : 'F14',
+ wx.WXK_F15 : 'F15',
+ wx.WXK_F16 : 'F16',
+ wx.WXK_F17 : 'F17',
+ wx.WXK_F18 : 'F18',
+ wx.WXK_F19 : 'F19',
+ wx.WXK_F20 : 'F20',
+ wx.WXK_F21 : 'F21',
+ wx.WXK_F22 : 'F22',
+ wx.WXK_F23 : 'F23',
+ wx.WXK_F24 : 'F24',
+ wx.WXK_NUMLOCK : 'NumLock',
+ wx.WXK_SCROLL : 'Scroll',
+ wx.WXK_PAGEUP : 'PgUp',
+ wx.WXK_PAGEDOWN : 'PgDn',
+# wx.WXK_NUMPAD_SPACE : 'WXK_NUMPAD_SPACE',
+# wx.WXK_NUMPAD_TAB : 'WXK_NUMPAD_TAB',
+# wx.WXK_NUMPAD_ENTER : 'WXK_NUMPAD_ENTER',
+# wx.WXK_NUMPAD_F1 : 'WXK_NUMPAD_F1',
+# wx.WXK_NUMPAD_F2 : 'WXK_NUMPAD_F2',
+# wx.WXK_NUMPAD_F3 : 'WXK_NUMPAD_F3',
+# wx.WXK_NUMPAD_F4 : 'WXK_NUMPAD_F4',
+# wx.WXK_NUMPAD_HOME : 'WXK_NUMPAD_HOME',
+# wx.WXK_NUMPAD_LEFT : 'WXK_NUMPAD_LEFT',
+# wx.WXK_NUMPAD_UP : 'WXK_NUMPAD_UP',
+# wx.WXK_NUMPAD_RIGHT : 'WXK_NUMPAD_RIGHT',
+# wx.WXK_NUMPAD_DOWN : 'WXK_NUMPAD_DOWN',
+# wx.WXK_NUMPAD_PRIOR : 'WXK_NUMPAD_PRIOR',
+# wx.WXK_NUMPAD_PAGEUP : 'WXK_NUMPAD_PAGEUP',
+# wx.WXK_NUMPAD_NEXT : 'WXK_NUMPAD_NEXT',
+# wx.WXK_NUMPAD_PAGEDOWN : 'WXK_NUMPAD_PAGEDOWN',
+# wx.WXK_NUMPAD_END : 'WXK_NUMPAD_END',
+# wx.WXK_NUMPAD_BEGIN : 'WXK_NUMPAD_BEGIN',
+# wx.WXK_NUMPAD_INSERT : 'WXK_NUMPAD_INSERT',
+# wx.WXK_NUMPAD_DELETE : 'WXK_NUMPAD_DELETE',
+# wx.WXK_NUMPAD_EQUAL : 'WXK_NUMPAD_EQUAL',
+# wx.WXK_NUMPAD_MULTIPLY : 'WXK_NUMPAD_MULTIPLY',
+# wx.WXK_NUMPAD_ADD : 'WXK_NUMPAD_ADD',
+# wx.WXK_NUMPAD_SEPARATOR : 'WXK_NUMPAD_SEPARATOR',
+# wx.WXK_NUMPAD_SUBTRACT : 'WXK_NUMPAD_SUBTRACT',
+# wx.WXK_NUMPAD_DECIMAL : 'WXK_NUMPAD_DECIMAL',
+# wx.WXK_NUMPAD_DIVIDE : 'WXK_NUMPAD_DIVIDE',
+#
+# wx.WXK_WINDOWS_LEFT : 'WXK_WINDOWS_LEFT',
+# wx.WXK_WINDOWS_RIGHT : 'WXK_WINDOWS_RIGHT',
+# wx.WXK_WINDOWS_MENU : 'WXK_WINDOWS_MENU',
+
+# wx.WXK_SPECIAL1 : 'WXK_SPECIAL1',
+# wx.WXK_SPECIAL2 : 'WXK_SPECIAL2',
+# wx.WXK_SPECIAL3 : 'WXK_SPECIAL3',
+# wx.WXK_SPECIAL4 : 'WXK_SPECIAL4',
+# wx.WXK_SPECIAL5 : 'WXK_SPECIAL5',
+# wx.WXK_SPECIAL6 : 'WXK_SPECIAL6',
+# wx.WXK_SPECIAL7 : 'WXK_SPECIAL7',
+# wx.WXK_SPECIAL8 : 'WXK_SPECIAL8',
+# wx.WXK_SPECIAL9 : 'WXK_SPECIAL9',
+# wx.WXK_SPECIAL10 : 'WXK_SPECIAL10',
+# wx.WXK_SPECIAL11 : 'WXK_SPECIAL11',
+# wx.WXK_SPECIAL12 : 'WXK_SPECIAL12',
+# wx.WXK_SPECIAL13 : 'WXK_SPECIAL13',
+# wx.WXK_SPECIAL14 : 'WXK_SPECIAL14',
+# wx.WXK_SPECIAL15 : 'WXK_SPECIAL15',
+# wx.WXK_SPECIAL16 : 'WXK_SPECIAL16',
+# wx.WXK_SPECIAL17 : 'WXK_SPECIAL17',
+# wx.WXK_SPECIAL18 : 'WXK_SPECIAL18',
+# wx.WXK_SPECIAL19 : 'WXK_SPECIAL19',
+# wx.WXK_SPECIAL2 : 'WXK_SPECIAL2',
+}
+
+# Define a dictionary to hold the correspondence between wx.ACCEL_* and
+# human-readable names
+ACCELERATORS = {wx.ACCEL_ALT : 'Alt',
+ wx.ACCEL_CTRL : 'Ctrl',
+ wx.ACCEL_NORMAL: '',
+ wx.ACCEL_SHIFT : 'Shift'}
+
+# Define a dictionary to hold the correspondence between wx.MOD_* and
+# human-readable names (platform dependent)
+if wx.Platform == '__WXMAC__':
+ MODIFIERS = [(wx.MOD_CONTROL, 'Cmd'), (wx.MOD_ALT, 'Alt'), (wx.MOD_SHIFT, 'Shift'), (wx.MOD_META, 'Meta')]
+else:
+ MODIFIERS = [(wx.MOD_CONTROL, 'Ctrl'), (wx.MOD_ALT, 'Alt'), (wx.MOD_SHIFT, 'Shift'), (wx.MOD_WIN, 'Win')]
+
+# Define a couple of standard, default accelerators
+NEW_ACCEL_STRING = _('New accelerator...')
+""" The string to display when the user wants to enter a new accelerator (by default is `New accelerator...`). """
+DISABLED_STRING = _('Disabled')
+""" The string to display when an accelerator is disabled (by default is `Disabled`). """
+
+# Events handled by ShortcutEditor
+wxEVT_SHORTCUT_CHANGING = wx.NewEventType()
+wxEVT_SHORTCUT_CHANGED = wx.NewEventType()
+
+EVT_SHORTCUT_CHANGING = wx.PyEventBinder(wxEVT_SHORTCUT_CHANGING, 1)
+""" Event emitted when the user is about to change a shortcut. """
+EVT_SHORTCUT_CHANGED = wx.PyEventBinder(wxEVT_SHORTCUT_CHANGED, 1)
+""" Event emitted when the user has changed a shortcut. """
+
+
+# Standard images for all the buttons we use in the dialog
+#----------------------------------------------------------------------
+_cancel = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0"
+ "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAQQSURBVHjaAEEAvv8BXTIyAAL9"
+ "/UEy6Oip+fn5BqAAAHX1/f2bBP7+ACMDAwA4BQUAB/z8AAH6+hQhCQm7FAsLKpPm5qfh/f1g"
+ "4QAAAAIAQQC+/wMtGBhBLufnr1w5ORI1JycI+traR9QBAev4/v7NFQICABsDAwAB/PwUFwAA"
+ "vDdJSTA0X18DIujoL9Lm5iLZAACyAgBBAL7/A2ADA8xhKSkREoaGAAQ9PQAm398DAeDgRtP/"
+ "/+gKAgLOHQEBDBr//782NDQwIGpqAP84OAAgFBQBKOXlLr3n5wcCAEEAvv8E9fn5CAcBAQD5"
+ "3NwA+A8PAA5aWgBY+PgG/cjIlMcCAhUUAQFSMScnMB1VVQD/AAAA99HRAAj4+AAFBQUBAf//"
+ "NAKI+TEf36uvT5546N+4wczMxcXwE2gYu6Qkg8T79yxCb986KUtKSiu7ujKwAA3/9ewZA/fN"
+ "mwxX1q5lyD979sXZ//9LAAKImZeL69w5oJ//v37tqvP4MQsj0IA/wEBjBWrg+fmTUVRZmYGD"
+ "lxesmePpU4Zbx44xFF269OLQ379xQAftBgggZgFOToYvf/+ePcPA8ILl0yc35RcvWP79+sXA"
+ "9PMnAxc3NwML0LA/L14w/H79muHarVsM5TduvDj6928UUPNeIGYACCBmbXFxBkFgVPEwM597"
+ "xcn5W/DXLxexp08Zf338yPDn/XuGX0CNPz5/ZvgGNLD93r13R37/DhBkYDjMA9QMChOAAGLR"
+ "FBEBpQOG/3/+8Mn+/Bmi8OkT40eg5ncfPjB8BXqHhZ2dgRvoHVFRUQYvMTHuN48fa/xgYDjG"
+ "C9R8H4gBAohZDxhgP///55H68eOg34sXxmJAze+BEh/+/2f4DqT/sLAwsAK9ycbGxmAhJcUi"
+ "yczscfrDh9dAQ85+BcoDBBCztoyMpMz37/vCnjwxkAY69QNQ8BsQswI18EtIMHACaRBgBbqE"
+ "CYiNZGRYRP//d738/v3rF0BDAAKI2U9A4EjMw4f6il+/MnwEKvwJxCBNT4SFGab/+PGem42N"
+ "WY+bm/kvMFWyAMWZga4xVVBgkfj3z23f27cPAQKISebzZ21toOa/QI3/gJgfGKCPgZq7v317"
+ "sfPdO7+Fr19nnv/585cIUCMTKMEBY4UFmF7M5eTYBJmZkwACiPk1F5cCPyengTYwzlmBtpwG"
+ "aq7//v3F+Y8fo9gYGQ+xMzCcv/7ly0sxFhY3HSEhFkFgmvgEjJ2ms2d/7Pz6dSpAADHIAkNX"
+ "R1x80SoxsX+bxMX/6/HzPwc6xBnkbw6gjWpAF6kDaUNGxoxFSko/7lpY/E/n5//ByMBQAlID"
+ "EEAMqmJiDNJAWxX4+dsluLh2A8XcGKAAZoA+MEdqAvn6jIwx+iwse5kZGAphagACDAAeLHBa"
+ "S9SUbwAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_clear = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "B3RJTUUH1wYeFCULmGdR+AAAAnpJREFUOI2V0ktIVFEcBvDv3jveufO4jk46ZVlGNUGRLTIp"
+ "K8OCoAdBIM2ioo2LCKFsI7QJCQoiiJ60nCDBTbUpsJSh0cxw42DImA2j1vhImXFmvPM493VO"
+ "izDS6WFn/X0/+H8cDv/xHpyzXuYs/FVdVT2iVbre/CTXxq+0fP+M9ZLNId/YVd+4+tTZFo5o"
+ "rBUAVgQ8PI9VsOBmTf1JR3+wE18igyCcHAUAy0oAysSLFeuqBJFMoW7nerwZ+JzLGFLLP4FP"
+ "70r7KOOeBzqMZpeYl+KxEPqiYlbVhHt3XnwN/PUEf5tfMg3Lfrmk+tYhn3VNWXUeUYXXFogQ"
+ "GhNi1xZzwp+AxiN7H01EjtaoxCt4KmvhLMvA6priqzaTjrxFDQSDYADALS+Ov4WkWzxPDWY7"
+ "np4/IY0Ob+RHQgrc5QnsafgIQx+CrqH1WJNyuwCI9DrLqeAI2GXvlrVVp22MmdDyMYyPJvDM"
+ "TxEJ21HXMNBeXjvU5PNBWwJEu0tdpk18L5ft9pa4a0ShSIapzUGZHwEvZKCTafR2ZzXOmfP4"
+ "LiTTiz0eAGL9lTbDLnY53dWbZNd2MZuegKnHoeYnkVuIQVdnoKszcDhTBVvxAJCj2iuH7N3h"
+ "kLfapsdewlFcAY1MITU7AmokoaSmAVDoKoDkbwBK1cOi6LZPjLbD6fJCV2cQDfeAZGdBzSSS"
+ "CQrGAMPgeJBkvgAAuIZvk0HoGiBKEsKhTj0VT4IaC+AFA/E5DprKATzSvrYf4y0Bth1M9RDT"
+ "soHSosfhwdcsq5AiajBqmgbyhEdGARJxRnmOdS/foOAfAECXv9hrmuwuIeyApqL4Z5jn9vmu"
+ "KB9+zX4H1k8cy/juDWsAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_default = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlw"
+ "SFlzAAAK8AAACvABQqw0mAAAACV0RVh0U29mdHdhcmUATWFjcm9tZWRpYSBGaXJld29ya3Mg"
+ "TVggMjAwNId2rM8AAAAWdEVYdENyZWF0aW9uIFRpbWUAMDIvMTEvMDeS+i0/AAACvklEQVR4"
+ "nKWSXUjVdxjHP7/f/+W8qdPqj5rRPAsryDM2FIRBjEQotjuHsV2NCIPqoqju6iqnuYu9ZKtw"
+ "N7mKujGqDXQ3o9UQEsl8mYl1OGp5lDRt5+h5+Z/j///rIgVfops98MDDw/N8+D4vQinF/zG5"
+ "NtHU2LDn8qWL1StS1q329khj43dPZ1/P578X8Mfvdw/W1Oy9Mzo21l5bW1vjy/XKCy0tZ4LB"
+ "YHBudq6s/uC3x9YCdADchIUMzHR13du/9cOyvEgkAspp7uvpMzs7/wz9dP5nno2GldBFIWAA"
+ "2dUKhMoODju1wZ11u65fu0o0GnW2lIbse38/CMXiMR739rF722fcbrr5iZ1JhFYqEG+XOCR+"
+ "aStr/W/erNfFDAG/oYpzXtrXrh7x9j4b52T5VxyvPMHAZA+bzlZt3Fxgza0egV0qmcy+TsRB"
+ "ahYTzxFf11327jtXxmSsku0l20hfuE9qmnSgwFp1tqUl9oFAahKkAE1X2Il5csxpthdPwNg/"
+ "QAqh68IF8Q5AaY6hu7arKaQXhAZCGiB1cAS4BkJqCEN6AmQ3rb8CnhJpZ/qHHjrkF9r4/Dmg"
+ "ZcFYAkhBMp3GNfMepTHC5nqAb2TqZWJrMu4wM5lkYTHKSO4gRVUpKC1CMwMMd00ytUNMV4H7"
+ "DgWQXURJAZqhkcnAq5EIsdlpjKJxuiMbyA7v58nGoY/vHD5QveWDwti55ubHgLv8SNLjdV3d"
+ "cFhcANcRxFIJpN+DtpDgxWiaT/MsOu9fKentCv+lS42Ojo6m/oGB08uv/NGhA/qjyqr5b8pD"
+ "dnd+QZxcv4lKJzGERkxPcjLRwr/OKHbaxvR4lGVZDwFQSi15dDk2w2MTX6Qe/Ppj+PsvpzIN"
+ "5W5zdZ5Cw/X5fcmKiorrbW2/7VjuWwFY73GlyrP9N9pbT9WNf16z94emxoaja2veALFzTWMO"
+ "z/GRAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_help = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC+ElEQVR4nGWTP2xbVRjFf9+9"
+ "9/01TgwJCQkMbkMKqCkEKGoXBpiQEqkpZUL8y8BeRqYwMMBQRMWMGtQgJCSKYWCohARIVCCo"
+ "MJUgLbSipVERTuzYcexn+713L4OlirafdLZzznC+c4TbbnZxrSTIEkoeQ9S8iICob0WkevHM"
+ "C5Xb+XKLeOH08WIxXnloZqoUhSFRFDHIcmr1XerNDts7navWuTfWPz1SucNgduH0qfm58mt7"
+ "y/ezfq1LrZmR2SHFaAg9QTtLo1WnnybLv3+yuHrTYHZh7a1DT8ysFEfH+eVyh73TEa8vTvL0"
+ "o0WsdXzz6w6nzm5x5cYALdDtNMgG3aO/ffxcRWYX18pTE6W/Dj7+CN9daDM17lN5+2GsteS5"
+ "w1qLc44b9ZSXTlxHRHDOkrRqTWvzPXp837GVw0/OHl7fyOiljt2eJQ4U9VbGiTM1HLBn0iP2"
+ "hR8v92n1QGmNaB3m6eCS8QNvSZmI7XYXRECED76skTshs6C18OyBGOccm7uOTjrMLNQRottH"
+ "zOhIoVxrpsM0BPqpo9vJEa15YMLnzWNjWGs590efRg/8yABQUJB0dclYB71BjnWwvZORI3i+"
+ "RnuKd16ZIA6EK/9mnPy6QxB7KDV8XDFw1BsGM0hzBMfmdooTwfgKZRQLB+9iZtJgrePD7xNS"
+ "ZQgChdIKgJGCRZRGdZJBpd1OsM4hSlB6iKl7DM45nHNc2nQEoSGIPMLYY2TEIwxAtKkaRH3R"
+ "au8uFcNRulZQaojKzwn7pn22EjC+xgs0fuhhfE15DP5cbyFKf6Qufvb8atJPqpHOMQKIIEo4"
+ "+lTMoRmfhTmfuWmD9jReqJm+10ORs/FPv3L+/QNVBeBwy4O01QzE3uz2hesp3QFs7MDfTYdR"
+ "cN+oUPIyzv3QqIrSy7dsYf+LX82jzOe5GS3rsEgcGeKCR6FouLvkMVYybDV6XNtIqoNMnvnp"
+ "3Qebd6xx7uWzJZQ6Ltp71XhBOS7EhJEhzS27SV4VbU6ef2//6v81/wH6bjI8fK9HXAAAAABJ"
+ "RU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_info = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAAAFz"
+ "UkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA"
+ "AAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAN1gAADdYBkG95nAAAEURJREFUeNrtmmlsXNd1"
+ "x//n3Hvfm53kcEiKpERSmy3LdmwlSrwVcZM4qdE6CVB0M4p8CBL0S9ECTb61/dD0cxq3KPKp"
+ "SIK2aZAWbeo2cd0kcJp4ixfZlmxHu0RJXGaG23D2mffevacf3oxEs/JObWgecPguhrPc87tn"
+ "uefcB/zy+uX1//qiq/2DrDT56cFsZmhyfPLme3ea7MB+ERkDABLUIpazpfOHTzUWTi+210or"
+ "UdAOIHLjA/DSg35h6rZbd33k0w8PbtvzK6lsfkcilR0wmn3FUADBibjIIeoGnVanWV9uri6c"
+ "WJp95dHZFx/7YW3lQlFsJDccAGV8tW3fPQf3P/CFL+VHpu/PZtKFoTSCiSETDWWMJH0FrQgE"
+ "wDkgsA7NjqXyesDlmvNrLRvVKiuzpZPPf/fYk9/5u/XFU0VAbgwA2cLU8J2//odfnth3z+cH"
+ "c6mRnSOmPTXiR+mEEgDodCOptQIbRBYAQTEhnTCcSRo2msla0FojpFOljlesOLW2XHz16E++"
+ "9ZWzhx573Iad6LoGMLb3I3s/9Jk/eWRk+95PzRRUcPNkMkz5LGu1jl2qtqN2N5LIOondWwAQ"
+ "iAAmgmIizyjKJj0ez6e17yleqgb82oVOsrTaqp89/uQjrz729a91VhZa79tCr4Ty4zfdfetd"
+ "v/Pn3xzfPvPRO6a81t6JVNRod+2ZxWqwtN6yndAKBDCaKelrTicMp3zDvlGsmMgJEFmHZieS"
+ "1XrbtruRjA4kaKrghw7iIzNz/8Do7oHl2SPPhu16cF0BGLv57l13/faffXPb+PiHP7Qz0RwZ"
+ "MO78Ui0srjajMHJQipFLeWrP5KB/5+6x1G07C4l9U/nETTvy/p7JIX96LOeNDqa0E0EYOTgn"
+ "0gmsVBpd6xtFM2MpYbHoqNG7/PHdpnT6hWdctxVdFwBSQ+MDdz/8F1+fmJz5xIEZv5lLaXum"
+ "WA1rza5jZiSMon1T+cS9t06m927P+/lcQqcShhOeZt8oTnhaZZKeKgwkzdRozisMpHSzE7pO"
+ "aMU5Qb0VOAFkejQNEYs2Dd+lWC8unXnpZRF3bQGw9ujAQ3/8pelb7vni7VOmU8iZaLZUDZud"
+ "0GnFlPAUH7x5PHXHntFUJmlU7PEAxQmAKBb0RSumwbSvtuXTptEOXasbOgBodkJhAk2NpNHs"
+ "RF6YmDxYWTzxZHNtoXhNAYztv3f/Bz75xa/uHktmdo35wcJyPaq3A2c0k1ZMt82MJD6waySl"
+ "mIkAYgIRgZggsfa0SWI4CU/zcC6pl9dbthtZIRC1upFL+prGh3xXrkmBMxP50olnHrdhJ3zX"
+ "C7cVymsvqfbf+3t/NJTL7tg5ajrrza6ttgKrFZNiQjbl8U3bhxJKUV8/EJEwkRCod21mQEQg"
+ "ECCDaV/tnRzyPK3Y9L6jvN6yvseyf0eqnZ/c82sjuz9813uy3K0AMDhx01R++75Pbc9z4Bty"
+ "K9V2xARSTKSYaTib1OmkYQLAhFjxWLsYBt5EqJcdiTA+nDaphCGlFBnFZK2TtXrH7igko+Fc"
+ "MjP94c9+3qQG/GsCYPrOBx/M5gYmxwZUUG12bRhZKGYoxVCKKJ3UrJkvLm0v5fc3IfRmV58B"
+ "IDBKkacVa0VQKnarRjtwxCI7xxLdbGHH/Zn8jumrDkD7KTM4sffBXJJUwpCrtQLHTBgbSpk7"
+ "d40mh7IJ1QmsOBHwhtXu692zBiGiTdK3lPiKrANRHBy1YlKKSQRodyO3vZCMMun0SG5s9/6r"
+ "DiCRzedTgyO7R7IcQODCyEkhl9R33TKe2j89nLh950iiGzlpdkJHGzTnS0pfCgtvkEuGQACW"
+ "qq3IySUAcXxhanZCl/SVy6aMGd518D5Whq4ygOGCn8wUsgm2nTASZqJbpoYTAylfCYDBtK8V"
+ "Ec4Wq0EYCTiO8D3FL6v5JYljBurtwC5V2pHmvuLUczGCdQImSCapJDEw9hGdyKTflQW/XwB+"
+ "aiivWKU8w64TBJLyDRcGkqqf4JkIWhEtrbeiM8X17t7JId83iqxzsFbIOkEYOXJOAAI0E7Rm"
+ "0YqhmNBoh/ZMsRZEzolWHKcFAICDCMOJCAjIJbVjZQqsdApA46oBKMzckTeerxWj60SQ9DX7"
+ "RnOv0iLrnAgApZjmlxtRcaXJg2nfHx5Isqf5YhHUt1sB4JxQvRXgxeMlFNeabmZigIdzSdGK"
+ "BGBAABGBUgSx8efSSe0ASYjAu6oWIAKIk55zA1oxmC/Gd1QaXWudoNYI1Msnyv65Ys0MZnz5"
+ "+IemwoP7tslwLsEJL07uIoJOYGW90XXF9ZbMrTTU8XOr6qUT5eTIUMo+cHC6M5DxrAjBCce/"
+ "Lf3QEkN510H8/QJYOXd4pXv3p0PrMmyUosg6RNaJpxUHkXXl9VbUCSz96PlzqXY34vsPbA/2"
+ "7sjbwawvzW5I3TVLWjGYiACBE4h1grF8Cg/dt9t+9M7t9NKxkvrpK3NeJ4h4WCWccwInBCcE"
+ "JSTMTJVaV0eRXYdI66oGwXZ1qdRutdebXaeyKY+7oZXF1UbUaAf21EIlaLZDlzAKzITxQtoe"
+ "uHksLAwkxTeKFDP1rKVXF8S9AKPjCG8001A2Ia1uxNmU5wqDSWEiYu4JEXyjCACXKm1urRef"
+ "jrqN9asKoLG2XKouV87MLbd9o5iNYpycr3RfPFlqlyutiAhIeBp7tg9GpdWWarZDVipWVCuC"
+ "ZiajYmWNVrGo+DWtmMLI8blilffuGHK5lC/UzwA9WNmUp1arHV1arTdLp5561IYdd1UBhO3V"
+ "ZmXh0L8urHRso21VLu0pARBGTojjLMBMdNNUPrLOobzWVIqZlGKoXlrTvYKpB5D7rxnFtF7v"
+ "cK0V0L7pYesZpr4FEBP5RpPRig+dXEmsluaeq51/9eVrsBUWzB15/NHV5fLJEwuNRNI3nPQU"
+ "9dpbFze1+VxCRgZTbq5cV0CvTlCx6J4FaH0Jho4h0bFzq0oxY7yQFgKBOc4aigkDaY/nyg1z"
+ "6sJao/jaDx/p1paq16QWqJfPLq6eee4bp+ZrslYL1GDGV0oxEai3/SX4RuGh+3Z377l9IlKK"
+ "er2/nhUwo2cBF91BK0ZkHZ24UOGd4wNuMONLXD7HRFO+YetEPf1aySufP/r95RNP/uyaVYPi"
+ "LGaf/7d/WinNv/LK6UqSQJz2NfdLun4NNJZPSWEg6WIwREwU7+p6VvAGC1BM9WZAzU6IAzeN"
+ "Os+oi30CrZjSvubDp5a9sxfKS4uv/OcjUbvWumYAAKC+Mr+yePTpr51ZqLYvLDd1JumxUUz9"
+ "GE8Xd3AbisJeFzgGcSnwcZwdaK5co1zKw46xXK9tHP9J+4Ya7ZCfP1pWK+ePfKs69+rh99zJ"
+ "2rqOoGD+5e89vjp/8qmXTqwmuqGllN8vTKg//0t3emO9TwRw7BJgAqxzmFuu08xEbP6Id8qk"
+ "FJFnmA6dKJuF4vJ8+bXH/8FFXXsdAADC1npj4dX/+tpcaX19tlhXSU+RVtxbe+lZQO8u8S6y"
+ "v60VAZwTOBf/v9WJYK3g1p3DYjSj/1ZPM1qdiI6cXuHK/Ov/0iifPvm+eplb3RZfPf38s5XS"
+ "mWePnFlLtANLnmF6g7L9YV9pEXEiYp2TyMbinEil3kEmaTA6lHZO5OI212im0mqTyyu1xurJ"
+ "p77voq67rgCEnXq7eOGFb8wv11pL623u7dR6Cl8U6SkOJwJrBZEVCa2LJbSyVmujMJh0SV/D"
+ "ORGR2HREgOMX1nS9Wi2210qn33c3+0qcDFWPPvPz6kp5dnaxZkTiQCeCWGnXM3URWCdirUjU"
+ "X/3IShRZ6YQWAGR8OCNMJP33EwFBaDFbrKtOrXQobC8vX5cAgvrKcnN17tCJuXXT6oQwmhGv"
+ "NuCciHMi1vXM3jmJrEjUX33rpBNEkkwYSSeNs86JlfgzRjHKay1eXK51188f+p57D23wqwLA"
+ "2dCtnH72u6WVau18ua7i4obgnBPrBHEzxJG1lmxkKYoihFFEYWQRRlYi6ySbNI6IJLJOrHVg"
+ "JkRW6H9envNWloqv1+YOP7slx/dX6nQ46jSWspN33tty/s07x3NhNuWxiFOQ0EBCj8lqgtMg"
+ "pyCxiDglzjLEKSYhK46cgyiO9wpPHVkwT75yobnw0r9/uXrh8KHrGoANWkHUbZ1yA3s+Ue9I"
+ "YfuwUYNp5Xs6roIvnXzEuwEBSAQkkN7uQFizsFFQrU7IP35xXv3o+XPB3MuPf6X82mPfFhe5"
+ "6xoAALQr8wsS1E4hO/rJ08VwwGimgbRHCd/A0xpGKxjF0IqhFaHfB2SOW02NVkhHTq/S9352"
+ "ls+cP+NWj/3gL88+/4O/lqgdbtUc9ZUEAHFwxZ/+/Pf3lOZnzcPbfvxCHU8eyWGikMauiSxG"
+ "B5PwPYX4qJQQWUE7iLC43MK5UgPltQaCoIYPzhTxwMEn+G9e/9n8L6Io2MopXlkAABKe8I70"
+ "Gfqtj/8Ui61pvHB6BM+d2oZnD2cQWg9ONAT9I2IHpgi+7mJiqIaH7y7hjulV7MhXUDp5LBQb"
+ "VbZ6flccwIP34TdG89jv6RB3zNRx23SI3713FtWWRr3toR0oRI5BEBjtkPYiZFMBcskQKS9C"
+ "t93EhZPHcfJY6eixs3jxhgJgNOjW3fjk0OhIMpUdgJUcOPMFZDMtZFv/Adhz+L+PKVHc7QXi"
+ "xqdjOCsw2hUyaYwAKG/lHPlKAiBACGgFnTbCIADcGlzrUbjuIThbgXUMJ5uFIBdPEAV+Oo3t"
+ "e2/BcD4xOT2OA1s9xysKIIiA/34O3yoX10qzrx9Gp1UH7FkgOAyRxjt4RC0uJINuG9bayDrU"
+ "brgYUKtDiBTlx8bhJQugzB+A9BRc8zuQ7iGQ4OIh+GVTaaOGuRNHUV4Ojx2b3foYcEUtQCvg"
+ "M/fjc+PbR8YKE5NgMwryPwgye0D+PSDSb/vMpwBQxsD3kc6kkLmhABABvockENf+sCuQ7kuQ"
+ "8Cyk+yxE7Nu6QSqbw/S+2zA85O+cmcDBGwpAGAFPvIh/XCouL184fhRRUIE0/x6u9lUgOHyJ"
+ "0luagMBGIax1zkZo31AAAKDaQMU5BIl0CqwHQZnPg3NfBrwPbuiLvZX+gspSGZ1O2O4EWLmh"
+ "ABgNPPRRfG5sfHhydMc02IyAvAMgsxvk3/2OYgARYWxqBoP5XO5T9+AzRm/tnK9UFugncqUZ"
+ "Y0prECnArQDdQxC9C9J95h3FgPhQIX7AymiME5AEEAJw6Hdb4/E1rwap9326J8Y5MAHujt3t"
+ "BxTZpPEUEL4K6T4F2LlLz8dsMnmIwFmLsNtBbWUZ86eOYqW8Xvn2Y/jq8XM42/v+/m9xT+i9"
+ "TnqrFOcN94tjz8B89mP4zYcfxJcmtvkzyZSvtfGgjA9WCswKrFTcLLUW1kZwNkIUdBF0u9Jo"
+ "dLqLZTf7zz/E3z7+NB7rhuhuWHXbu28cb3xNrjSAvqJqE4Q3AGGGntqGmdv34OB9B/CrU+P6"
+ "rnSKRn0DKJberjd+4CFyhFaHUKnaC8fPhj958XW8fOoCji2tYdEJQgBRT+wGcW8ytm8HgbZI"
+ "+c0gNooB4PVdw9NIj20b+NiuPdN/OjmWTQ1mfRARBIB1jEotwGK5Fpw6ee6vlsuVnzhB0FMk"
+ "7EmwQTaDeNcQ1Ps0fX4b6QPoQ0hYB11vhKuBTQw2w/SeastTzSCJasPD4nKIxaW2XVhYe6Jc"
+ "XHrCidhNmUouE/zkLQSbxlsO4L2JSNRs1H8RheGqE8k3Wx1Vqze61Wp1YalU/Nfl0uKjztn1"
+ "3gqHmyTaIO4tRDaMr0oMuKz/b84MG+4KgNLG5I3xCgAoDINKFIbVDWZrNykcbri/le+7qxED"
+ "NrvCm2aCy7jFxjtdxqJk02raNxm/VQa4Klngci6xWXG6zHizW2yey2b/lU1mLW9j/ld1H/BO"
+ "4sObKY93AUDeJPi9o5W+2gDe6rc2mzzeBgAuE9W37PpfnmQMHSrQKjcAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_ok = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAANkE3LLaAgAAAjpJ"
+ "REFUeJy90k1IkwEcx/Hvs2evMt1KJ741Wy0zexMy0US6WHSKgii8pAUZKUEFubSgkjKRQgT1"
+ "kL0hZNChMpJCi/RQGQll0sBE09wWw5c2c5rbs+fptIgutQ59758//8MP/nNCcsWSm5ajS+8C"
+ "6qh1con5So+3W3ni6lTiS81XAe1f45QDsXV3JloVT2BC8c57lGZng6LZJVz8+Ub8fpVD0Mri"
+ "1DVqf8dpZYYLZ6pOOjJi1jDqHyIoS7xwdyMbla1qANNO7fHDx0rrZPV3WufbpOl26iM4/Yju"
+ "XEXlwdNWvZ3xuY9IssKDT23c6+0l3McjUVfEoe2Vm5vyEwuJ1yVgyRO3jflHfIFBXtvK1dUl"
+ "jt016ZpM/MFJZiUfTyfbed7/Ct9t6hmiRkzeR2Moddo6G5xBJYZJjEkiMUcoIvtrzo7iLeUp"
+ "Ohu+oJcpycPA3DPefXiP6zoN0gAOQBYRyLRslAqmtS7coSF8iguNQVFZs0yrtYIGb2iE0eBb"
+ "3OFBvMMzOBuk2oV+qgAZQFz8zMvwPGkrc3XZQlyIb4KfsNqPUYhFL6pRqWQMOjULEwJ9l3yX"
+ "Z/uojmAAEQgFhukKLsq2rLyE9XqTiiTtMuwxWaQb7Cw3ZjDjCtBx1tk41SNX/oojBwBCfidd"
+ "QUlalVtgX5tqsmHVrWCdKZfxL2M0nXrY4nksnQDCf9pL3IZy/f1m917ljXxD6fCeV+zF2ugW"
+ "B5gLHcbOFtceZVOZ4RagjwZHSrLkUwHE/guOqh90ld9+870vDgAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_reassign = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "ZSBJbWFnZVJlYWR5ccllPAAAAsZJREFUeNqck1lIVGEUx393thaXCm0qtdJrm4FlONGkWESb"
+ "tthDUA9F9dDyFhTRghI9WJpgPgSBD/UWQRvZrg6CSFk5FuJDD+nYTFCmmaDV2Cz3dr7LBEIv"
+ "0oE/937nfP/DOed/Pm1XPZMyU2AYNBom5TYNzWYDTXw2KyhRCVjff4iJWDwOv2OU1+5tYDyK"
+ "qc7qui1u8EACpnJGYtyVsxVQUP8Zs3QzHMH8JfDq0Nl3jIrycyqZKRWhldZiXt1XQSQeo6PP"
+ "j/9jP6HhgKbKm5+mmx5dx5tbKFVoAged/VXYpe7Zyfu45ruJQ93sDF4kHAXvovOkp6zmec9t"
+ "q5kdBfvJmeugI3AeK6Mq2SGQBCPhkHW2L97IoXchZqYmwc9oG0vmFZAydSHBbwE2r9LpDF0i"
+ "OAhdfeAUonuWkH/o3HvVTdNpPPZeH74+Hzdc+ZTNSGbGOG/IdS9jqtPNrVfXZdzwoptg40k2"
+ "TVnF0bSZTlreDtN8Bk95PV12kXFo6Va+PDtDiy2fw0nTscftPeS4c0hx5fL4dW+ktZL1O+vo"
+ "joYpDQ4ZWU2KfIUu1ZZNNdt4wmRzNfcPbNzuGh7RCQxA/+gTFmT8ZE9JkUtidx6elJtOvHUH"
+ "G9hUjf+vWjYjTuuWGs3cXVK8OCtzjOKiAP2SIPgVPofbUb7t3uV5G6o0c+1KGfiQyLhHZIwm"
+ "ZCy7jHn8QB7x2DSGwm8JfYIvId2a8NzMANlZkOpaRMwYs6Qc+z2AbCJuh8j4SGRU+zhivCcm"
+ "9QQ/w8sOBpsrA9tUgi0XeSJDnKNn92IkFktLyPg9IaNWWoVfc1GoVjYe5nXLBY7IYHuwZkN+"
+ "WQ2twktX5OI1IHvFyIDO07YAzWfxqPVYIkhJrP6okD9MfAuSZAVqfGLSrn9diYu29gjPEzJq"
+ "k32NysZHaXUmseHxKTzC6+I/LFdQONHxR4ABANuzKntCBWfVAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+
+_html_back = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0"
+ "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAavSURBVHjaYvz//z/DQAKAAGJi"
+ "GGAAEEAD7gCAAGJBF2Bk7IM6jRGIgTQzkGZG5wMxI0g3mNZh+PGnmoGbhZWBhSkXKPocbth/"
+ "qBd5mSFqQUJn0lDsAwgg0kMAlmQYGdgYvv3OZPr2e3dgoFqEsqJAIMOvf9YMf4EKQPgPVCE3"
+ "M8QROABAAJHuAJBH/v1XZnj/c620NO+0hbO9JNbN8WIQFmBnYPgNtPkf1AEgddxMEBoPAAgg"
+ "FhItZ2T48Tea4d+/1thEXbm6SgsGFQV+hr9//zH8+vUXET6gKAJZzoQUYjgAQAAR7wBGRh6G"
+ "Tz87BES5sjo67BjTE3XBpv/5/QfVDlBa4QD5nBFiOYEQAAggFuKCnEGN4du3OYamUrbTp7sx"
+ "mBtLAA3/y/D6838GHrb/DMzMYFv+AS3/y8AODXYiixeAAGIhaPnvvx6MDH+nxyYbKvR02DGI"
+ "inAy/Ab6evk1RobHn5gYik1/M/z/x8jw/dsfJoavv52Awc4B1McBzz2MUJqViYmBk+UskHUJ"
+ "2QqAAGIhYHksUP/Mtk5HzrISU3Dovvn6h2H6OWaG/Q8ZGSwlfjMw/vvLwMjMwqCnKcLEyciY"
+ "x8rNnAdPB8wQg5hZGYGx95vh5vMvt4ECasjWAAQQC07L//6J5uBknD1hoht7eqoeOISvv/7P"
+ "MOUMM8Ojj4wMXMDQZvz7lwFUkv8H0gt6HYA57z9S2IMkgJkCmCM42VkYjlx5wxCav0sc3SqA"
+ "AMLugP//XFlYGKdPnebBnpSgAzbs8MP/DLMuMAF9wsjAyfyH4dOPX8Co+Mvw5y8TEAMdAwyq"
+ "/wwgC/8BMwmQ/vcPaAwwkQL5jH9ZGNiY/4Ni4ze6VQABhM0BssCwn1BX78ALsfwfw9ZbjAxz"
+ "LjCDo5MD6PPfP/8wMP39w3Dr5R+Gks1/GP78ATrk1x9goAHZv3+Dc8ZfIP785ReDixY3Q5aH"
+ "ONhh2Oo9gADC4oBfma6uKlqlJWZg3r77DAxzLgLjEZi4mYHx/fPXb4a/QPwfaNlHYLw+f/0L"
+ "bPFvIPsPVO43CAP57z/9YFARYYJnCmw5EiCAsDiAMTA2VoeBg4OZ4dqrvwzzLjKDNTIBs92v"
+ "XxBLYPgf0Lcs//8AAwlYFgAxA5T9D0Qz/GFgBdJM//8x/AVFx///WHMmQABhcwAbOzs4+TJ8"
+ "/fWf4TvIXGBw/wYF769fSA6ABvcvSJCD2UBf//6NcCAoJEChAw97LEEAEEBY6oJ/O9atuwku"
+ "Xk2l/zOEqf5i+PztD8Ovn7+gFiHwb6Ajvn//DcS/oPg3Ev83sOz6BdT3G54gsQUBQABhcQDr"
+ "tJUrrz2ZM/cK0MWsDMHqfxlC1IDx/fU3w48fv8GJC+T738DQALqCgYf1LxD/A+L/DLxs/xh4"
+ "gWxetv9gzM/BwMAOrIaB9uMEAAGELQquAmO8qrR0/wI5OT4mTw8FhjiDr8CijYlhzrHfDD+B"
+ "IcEKTA9fvv5i0JdiZqjyEgPmAmDWA8Ux0JegkINkxX9gNsgB3378AacBRixRABBAOAoi5sWf"
+ "P/2Uio/f0jF/gTeDt6c8Q7TBPwYBVnaG3j3fGd5+/AlM7X8YmP8zMkjyMwPrAjZgomUFp3Ww"
+ "Q6COAcX9L5AjWJkZ2N//Bkkzo1sFEEC4i2Im1s7Xr76zRkdtapw+y50pMlSVwRtYAYpy8TG0"
+ "bXnDcPzmd4afEsBE+usfAzcPG0NV33mGOw8+MrBwAI1kBDqAEdqCAlKsbEwMrz78YPj8+993"
+ "dGsAAogFZ6sHFFysLC0fP/x+kZywvff69bd8ZSWGDBaq3Ax9Yf8Zujb/Y3gDCglwqfefYcue"
+ "h/9un3+5DJgYzgP1sqNURiBbWJhZgc22U+hWAQQQC8HmFwfLnO9//t9trj8y5/z5l0oT+u0Y"
+ "VGV5GBoCGRhuPPvO8Os3JIVzcQNTHzfragYulk3gWgvdAUzYGwYAAcREVBuQhXE/Aw+H45YN"
+ "d7a4eW1k2HHoJYOkFB+DvgI3uCL69/8fxKz/QKt+487z2ABAADGR0Bx7xMDPHnrvzoe6oPAt"
+ "Xxs6zzL8+s/MICTICY4GFAf//E9UawgEAAKIeAdAatofwDhu/vmPwaO16eQF/+gdDFdufWYQ"
+ "F+EG1xVwK0EO+v4PVI8RbB0BBBB5HRMWpiMM/GxO58687PMK2/qjqPkkMK8D62VmRhZIxcEA"
+ "KX6//SMYEgABxIjeNySqYwJjgzob//87M/z+V8PIw8L0n4kxGSh6B6NjAmohs0D0oXdMAAKI"
+ "caA7pwABNOB9Q4AAGnAHAAQYABaU9vBbRzekAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_html_forward = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0"
+ "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAbWSURBVHjaYvz//z/DQAKAAGJi"
+ "GGAAEEAD7gCAAGJBF2A0mQVlAPGPfwwMv/9D2HAFDHwMf/9PZfjyR5CBnaWZ4f//kwx/geL/"
+ "gOqAyoFyDHD+XySxfxCx/78KUewDCCDcIQBKGqxAm9FV/P6nK8zHHuPqrODN/PvvHobvf6qB"
+ "ouzkhgBAAOGPAmagAziYUcX+/mfiYGJkmNHuyLB6jjePoix/C8P7H7uAIaFLjgMAAgi/A/5D"
+ "VXCgKvsDDNI/v/8xBLorMezbEMwQm6hnx/jlz25gaBQApdlIcQBAABGXCBmBIcHKhOY2cKQy"
+ "KEjzMCyY6Mowa5qbuIggRz/D518LgelElFgHAAQQcQ74D02ULODU+B2SFoEJCpjYnn8EEkBG"
+ "SrQ2w54tIQzG5pIRDG+/bwcmOG1ijAYIIBYsYqoMP//aMPwBJllGBkgpBfLsHyDz//8/DN/+"
+ "aPzhYGUAFWCMjP8Y5l9iYpDiZWCI1PnDoK8lwrBrfTBDec0h4znTL+wB5pJ8BhamVfgcABBA"
+ "LFh8u1pJhldfkJsNmN7+Qzz/D5q1gNTv738ZRPnYGdhYmBj+//vH8AuYTRdfYWV4+JGRIcXw"
+ "L4O0ABvDrMmuDEqKAhK1VYdW/P3zX4iBlXkGAwP2EhcggDDLgb//lDpLzBm8rKQYvn7/A8wI"
+ "jAyMTEyQogCUFoAsZmDEsQNzyM8fv4Ehw8TAARQ//ZyF4elnZoY8078MOuIMDJXFpgwS4lyM"
+ "mem7J//89YedgZl5IjYHAAQQtjTwix3ou38/fwN9+4vhN9CS30D2319/GP79AQbDXwj9/ecf"
+ "hr/AqPnz5w/Dn5+/GLiY/jC8+sbA0HaMmeHgfUZwcCXGaDNMmeLCws7C2Mfw+68fNgcABBC2"
+ "NAA09C/Q5/8Zdl34wLDsxEcGbk5WBlY2VgZmVhYghtCsrMwMLGwsQEuZGZiBOe/Xr98MbMAM"
+ "+PMPC8OEM0wMX4DZ1FvtH0NKog7Dly+/mArzdk9lYGa7DjT+NrJdAAHEgjPnAfHL978YTt36"
+ "yMDLA4xzdjYGFnaIQ1hY2cCWswDZXMAEycbByPDnFySNsAHLREYmFobZF5iA6e8fg7vKf4bc"
+ "LEOGzZvuyOzb8yAHqCof2R6AAMKaDf8BE98/UMIDJn9WIAYmRwYWYFZj+fcHin/D2f9AUQD0"
+ "PQyDoosJJAc0eR4wh1x79Q8Y/YwMWdmGIG85otsFEEA4Q+Df/3/A6P4DNPAnw282RqQCAZQb"
+ "EWn6P3JhAW1bgPIOCzA6vv1lYfj8EyLGzQ0qIBkxSkmAAGLBXfiAiltgYvv2m4EV6B1Q+mMB"
+ "hgorMOExQ9l/gGwOROaAF5ogKz//YmKI1PvHYC4JEV+8+AoodZ1BtwYggPCEwH9gNfCfgYv5"
+ "HwM7MC5ZgZgZRDMCowJoCwsjMI4ZQFHAyPCbEVpi/YfUwsBAYwjRY2KI1QFWZCycDBs332NY"
+ "tvj6F2CwzEC3ByCAWHAVvZ+//WFwNxJisNISAFrMyMDEwszABKKBZQIzEINoUMj07P7AcO7J"
+ "LwY+oM+/g0pLYLDEmrIyJBoDywpODoaDRx4zpKbtAJlay8DEeATdKoAAwuIARmZ2NiYGIQFO"
+ "Bk5gCmdnA1oMCldQgQRqHgAtBjF+AsuB37/+AhPoP3A6+Qh0NScnG0O+HTdDqBEbAycvJ8OJ"
+ "0y8YoqO3Mrx+8WUaAwfbBHDwoAGAAMJwwH9mhi89S64KrN7Lw/D7DyJRMf5jBIfvn1//GIR5"
+ "2BhKU3UZQOnqBzDVv/v0i0FXHijmxcvgqMEBtnzzjgcMSUk7Gd68+DaJgYu9BJxAmRkxHAAQ"
+ "QCxYqt7kg8eeOQOD8i+8KfYXXhkBU+VfWWEhzvjUCHUGHhF2hq/ffjG4AC2t8hdm0JDhYmBk"
+ "52DomXKBoa766O/v3/+0MfCyNgL14mx6AwQQtjSwC9gK2gUKCkSKhDoAFIRMzMYsPKzxoGQH"
+ "LOMZkh2EGXTlOBmkxHkYPn7/z1BavJ9h4dwrbxk4WDIZOFlWMxBo9QMEEAtJ7SdIUucCB8o/"
+ "SGFlpsLFICjCw3D64juGvPIjDOeOPTvPwM+WBFR7AdwYJQAAAog4B8BatshCQMt5uYHamVkZ"
+ "Jsy+ztDWc/rPxzc/FjEIsFcB1b8kxnIQAAgg/A5ghMX/PwxhEWFOhudvfjPkNRxm2Lf9wTNg"
+ "cOcx8LGtBVtMQmcLIIDwOwBcqqCZBsyT/4DlQe/cKwxr19358/LZlw0MvGxlQFfdBzuWRAAQ"
+ "QCx44/sHFq+wMt1+9fHn8Wmzr/ADi8NuBl72pcAE+htbHicGAAQQ40B3TgECaMD7hgABNOAO"
+ "AAgwANtDcqAqYx6xAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_html_home = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0"
+ "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAmrSURBVHjaYvz//z/DQAKAAGJi"
+ "GGAAEECMDH5SqCL/oe76ywiWZvjHiJD7xwzEULnf/w0Yfv3tY/jPyMPAzFLOwMq2n+EfNDRB"
+ "NCMjBP9HNhjqX1CogzAjEwNAAJEXAj+++7Ax/N/QlV/pOLu205Sfk2sVw5fP8eQYBRBALGh8"
+ "biD2hdL/gBjoZYYrQHwCEmFAH335ksnLJ9QztbCFK9Y9ECwsJSImktZWNf/p40fyDDz8bUDv"
+ "/SHWAQABxMygzovMlwSG0lZg8IQBg8cfSPsBw+kPMCa2AuXYGT5+7FFX1Gxe2TyT1dfKieHb"
+ "vy8MP/5+Y9CRV2dws7RjPHP7uuOze3dUGNjYDwCD/zs4CtBiHJXLyAAQQMwMmkDPMv6HYT6g"
+ "cAKQwQtTAMS7GP79ucjw6eMCD1uvxGV10xn0lTUY3v15xTD9eQPDng8bGFTZ9BhUxVQYAh3d"
+ "GJ69f6N7+fI5awYW1pMMzMyvGf7jdwBAAAEdwAMRh2B+IE4Fsnjh6v/8+cDw80dMgl+C19yy"
+ "CQwSgiIMj3/dZZj2vJ7h0pczDK9/vmA4//k4gzSzIoOygAqDn70rw49//+ROXTjt8u/vvwsM"
+ "LCyP8DkAIICYGbS5kEOAHxh/qUB1vKAUCrQYyPyn3pRcq9ib2sDAwcrGcOHrMYYpz2sZHv+4"
+ "x8DByMXA9J+N4c2vVwyHP+wGahJg0ODRYXA1t2YQExUTOXDqeMDv71+fAUPjEi4HAAQQM4MW"
+ "F7IQMAQYgQ5g4mX49plBkE+QYV7xdIZs7wRwbOz+uJph7ssOhs+/PzGw/Odg+PPvL8NvIGb8"
+ "z8TwDZgWDr7bxfD91zcGI25LBjMdPQZDbR3OPaeOB319/46RgZ3jEAMDaoSADAUIIGYGQxZ4"
+ "+AMTIDBB/E9j+PKeV1VGlWF55SIGbxNnhr/ARL3m3QyGNW9mA9lAZf9YwJb/+fuX4e+/f2D6"
+ "P7C8+P+fkeHUx6MMj789ZNDjNAGmFU0GVwsbhtPXLzk8f3hfhoGNYz/Q0l/IDgAIIGYGI6AD"
+ "GP9BMtz//7JAy1OsDZy5lpTOZzBR0Wf4+vcTw5zXbQy7368FBzfDf2a45WAMdcBfsGP+A41i"
+ "Zjj38RTDxU/nGXTZjRm0ZNUZPG0cGO6+fG5089plfWB0HGdgYvoAKYgYGQACiJlBnx1oKND3"
+ "f/9qAYN9boRrgvrigtkM8qIykMT2so7h/JejDGzAwPkHtABm+W+opb+BBsFCAiwG5LMAVd/+"
+ "cpPhyLsDDApMygx64noMAY6uDB9+/VA9ff6MOzAizjMwMT8GOQAggCAO+PHNA2j6ivroJp0J"
+ "iR0MPOzcDNe/n2WY9qqO4dGPOwxsjNxgn4KD+88fYLz/A1uO7Hs4G0qzAIuN59+fMWx/uYVB"
+ "8L8Igw6vNoOvvRODsJCwyP7TR0P/fP/+BFh8XwIIIGYGHYZQCT7xhZNTJ4sXeGUDCztI6fzr"
+ "/0+G179eMDz4cZfh/18msM9hFoEtgWK45WD8HxEdQPz9z08GEwFLBh8xfwbO/1wMf3/9YbAz"
+ "MWPQVdVkP3nlos+HT5/eAwQQC+P/P01N0a0CCXYx8CoDlCSl2RQZlFh1GPb83cTADDT46+9v"
+ "wCD+A/cpPArAFkOj5Q9M7C8DKzAEfgIdoMGlyWAhYsXwg/EH2OCfP34y+Ns5geo4tqjyvDKA"
+ "AGL5z8JycNa+WRrbzm4GG/Drx2+GCNsQhiTHBAZOYD4HGSLOIsbgJxoHTIQsQMN/gy0BpQdQ"
+ "ovv3HxIKEBrIB3qBGQjXP1/DcPrbWaAZ3KBCnGH/qRMME1bOAUY9KwMLEzPD20+fGX4yMZwG"
+ "CCAWoEjFmTvHd535Awyj3wzfGL4y+EiJSiaCHcDMDXYUD4sAQ6RoBrDWZYLkFrw1Jaj0ZGA4"
+ "++4Mw6Hfpxn4WIBlGzCjnbxxnmHXno1bGNi55jMws3EyMLMCg4nrIEAAgQqBD8D8uY6BDWjy"
+ "X2B2ZPrG8vn3t0SQWSDXg3z98+8vhp//gXXLL2aG1SfWM3wEFlJMTCyQ+PoPKeH+A/WysbAx"
+ "BFh4MgiyCYDjHyQnwCoEpl9+eg8s4Dn3M3DwrWMA5hKw4F8GBoAAQlTHsKYZM8PXj9/eAeuf"
+ "/wzcwAIR5IA/wGBnZmZm+PjlC0P5wuqfL57e38bAxvkemH1ZIA0WYI356y8XMyefl5WmKZ+Y"
+ "hAiQ+xuYDpgYRNiEwRa9//IBZPYXYIIChhAQ/4ckdoAAQjgAVhgxMbz58vUjw8/fvxg4mbjA"
+ "raBfwMT3Hxi/oCKXi5PrCwM3VzEDM+d9cPkBw8x/Rbi4uQ0ZGRj5/oPLhD/AEOQBOkCU4d+v"
+ "fwwfgGYCwTuwPazAwvA3O7h1BRBATJBS+D8CMzF8+PT90++vv78C0wAXMLA4wCn+Pyy8mcBl"
+ "MRMD639EEQ4KvX+/mcH6wSr/g8sLbiAUYBUA6v/N8OUrOATegj3JAgwStp9ghwAEILIMVgCG"
+ "QRga3GGTUfb/H9lBy5DutkQPu0t8wYhaNf61NIK+7jli4Nwaml3pRqlPiAI1QlCEaWP6Oa+C"
+ "ort891irVXRz7HYgmIcnpsz1fAt12QThLz4BxASOIGTMxPjt/Y93H958ecPAAswyPEyCwJzw"
+ "G1GRMUJDAUSD4hOYPsDBCvMIVB0ou3IALedi5QQm2k8M779/BMY/w2eIWqh6oFqAAGICN9+Q"
+ "MdP/P79//fz06vMrsIE8THzgwuYf0GugPsR/uGX/EY6BYZAcOD3/B5cNnCycDFwsXAxvPr1l"
+ "eP/t00dgSv6GEtpADBBALOCGJioAppD/H958fQvmgNLA59+fGUAJC6wD3EyDWo7cxoCkH0hK"
+ "ATrg29/vDHzAKAQ54vWndwyfv3/+AHTAT0hbFwEAAoiFAaNhDqyvGf+/fvvlNZinAixK3/x4"
+ "DbQHVN//gzSWURzwH5GLGEGpBFQ0/2Ew4DVgEAXlAKDI2y9Az/z79ZGBhf03epsEIIBYwEGH"
+ "CkC2vPz84zOYEyuXxBAjlwhMDyzACuoPsOBkhFjGBPUJPASB2RQozgEs5FjYWRgmW0wChwQT"
+ "BxPD5x9fQOkLGAIMv+AOhgKAAGJhwNZyZmJ4dPnZZQYQBid4IASW9sAC4h3Dz3/A4pAJqb0N"
+ "YzGB1PxnuvniDlDNTwYmYO8JlG4ef3vJcP7+JZCZTxmYGX+j+xYggBgZMhmxlehqLAwss0RY"
+ "hbWAZvyG5D5GUDXM8u7np/dA2gPo3QeQsp8dFgKijIxMm4RYuFSBJeDPf/8h3Tqg41nf//jx"
+ "6Off/7lAU46jWwQQQIwD3TsGCKAB7x0DBBgAIYJYB6/AsBcAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_html_print = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "ZSBJbWFnZVJlYWR5ccllPAAABwhJREFUeJytl99vVMcVxz9n7tx7d732esHYxmBTfgVRQmg3"
+ "OBH9IRGgjUBqoBKoapDIQ9NW4qH0oVL/hPahfegD6kvCcyM1b6nUNhJS0kpNSgW0VUQsEpvy"
+ "yxCDbdZe7957585MH3bXNhRcQBzp7OydOXe+59ecc0eOHfsRK5FzbtOOHdt+v3nzhl7nnHuU"
+ "3OnTv9oGcPHiRQCq1SqP8yyvvfbGigrkuR09deoHfz94cL9aSa5arS5u/rhUrVbRIrKikIhY"
+ "Y6wB4odLeMA/MTi0vNG2amUlHk2uzRZIn2oHtbSBRymNiDyUHw7uF5WoVvc8MXi1WkXn+TTe"
+ "e7wXoqibMCzj/RKg9w8LvV8G3vn/dKRBEAFrDc3mXZwzFItDiLCoWBAED4DbBxRwT50DeulR"
+ "UEqTZfPkuWX16k2IBEC2LAT3gy4PwdPS//hXqYA0rVGr/Yf5+RuAaSgVtn3slrG/77lzrp+E"
+ "qtXqcg8skUhAltURqessM99RSoVLCiyP/zPJgRZ573HO4j3rjMl2WRus7+oq7t21a8cJrTti"
+ "HcBnnAPee+WcO1YuV04MD4/s3rp1W19//9poeHgdE+MTOJO0X5E2YGeEZ+IB793Pjxw5+stX"
+ "XjlAX18/hUIMCKFWnPvHBRI9yMD1BUzeRPBYZxHpALc88ObRA09Xio0xz+3c+cLPjh8/0U7A"
+ "JknSIAg0SSNBFbvoHtnKzEKOtCMmEiIC0j7CatmGT9yMDh06+NOTJ3/ym/37v029Po+I4D1E"
+ "Ucjs9B3+eO5TvnHwIHgB33J1IKCkZXtiweRggMx6jAPrQMKAz879jT2DEeXeARpJwke1T+mh"
+ "i73DX+GTsX/x9pnTv9alUmnnyMgI3ju0Xio4QaBI04Ssdz2XZhU4hxYQgbqB6RRqiWc+B+Pa"
+ "unnfygYBJxDYNXxd1+kqhixkDTJnWVdZQxDC2qEhyuXeL+uenvJzfX19iLRAQbDWkTUT6onh"
+ "C7WKuTpEXriTwOVZuNnwJA6Ub4Wgjbn4i0AOhHM9HM3n2RAJfb1lvlf5Jg6LE0df32oGBgaH"
+ "daVSWdvT041SglKKLMtpNlPiAGqpZ9oVUXX4523h0jTUc1qy/6eBOgHVKHBlNmd0a0DmwOMQ"
+ "hEAp4riLSqW3or2X0txck8HBIkoJ1lq0VsSh4m7dMFMv8vEETN6jlW3ymMVXwCUlJmYErVs5"
+ "1TESIMtynJNQp6nhwoXPGBhYRV9fD+VyF4VCTKngmLhX4A8fl8gSIGx7WJYA7qMHy4IH0ojx"
+ "VRXiOMCokCTJmJurc+dOjXv3mtTrCVopZQCmpmpMTc0ShiHd3QUG+0tsW9vLD7+6wJyNuJdq"
+ "ZptCrelpGDBWcO1TIUCkoRhCTwyru6ASWypBxsvruxm/do+pu3Xq9YQ0NXjviaIYEXJtrZkN"
+ "w2BToVAgz3O89zSbGTdvwfpCysnna+goJohClI4QETInbQWWzI8DiALfKul5js0z8jSlkcLN"
+ "W5bMZAAUixEiCqUCnLN1nabJTaX8i8ViAWMMWmvm5mb54IP3McZgbatHdGqACCgRlOqU5HbS"
+ "OXDed8RABFEKHQQoJYyOfo21a4cxxhAEAcZkZFlzRue5ueq9oViM0VqI4wJTU9f48MM/kSQJ"
+ "pVIXQaDx/gnqfbtKWmtpNpuAY8uWzWzduo0kaaJ1RK3WoNGo39J5nl/JsialUpEkgTiOMCah"
+ "u7uboaEhXn/9OKtWrSbPzeMrAARBQJIkvPPO75icnMRaQxxrICaOY6anE7Isvarz3Jy/e/eL"
+ "rLu7EGndenFwcIBXXz1EFBV56aVRjLFY22q9znla1xOP9w7nWm5vtfNWY3IOnPNs2dLLgQMH"
+ "mZy8yebNGykUQsJQUSgUqdVmybL0ogbOX7586d+HDx8ZrVTKGJPz4ou7KZcHCMOA9euHMcYu"
+ "AjjnlgG69lyH7eJanlvK5RL79n2LiYnb7N69nYWFBkEQoFTA2NgnV73nL8Ho6Gg2Pz83myTJ"
+ "Xq3jYpYZtbDQYGxsgtHR7QSBxlqLtXYR0FqHc7Y9dtguKtjhLDP09/dy6dLn7XxYYGpqyn70"
+ "0V9nzp8/94sgCM5qEUEp9e7Zs3++eP78uRfCMFpnrd51+PB33+jpKRWbzbRtLcu84Bc9sHyu"
+ "M+99az5Nc6yFkZEB/9Zbb7+rVPMDa93t6em7Y1EUXRKRpU+yMNTjWsfjMzOzRNHA97dv3/xm"
+ "63j5+9ztPQ8Au4coxOL8zMw8GzYMSRh2f3779s3f9vevIQzDxS9t3Ro91sbcuZOTplHXyy8/"
+ "f2rjxmENUCoVHpnprXizeESXj8vXCgXNvn17fnzmzJUzN24sjMexJo5b3USnadi2KgAsWsvq"
+ "ZrNefu+9969Za91K98aV77VLiyLI9euTYaEQfslaN57nIZ129l9hzBKSSHX0vAAAAABJRU5E"
+ "rkJggg==")
+
+#----------------------------------------------------------------------
+_html_reload = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0"
+ "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAlZSURBVHjabIvBCYBAEAOT027t"
+ "xI/VWJA/i9DkonsfwYEhw8LSNh64EP/kroxbZKnRXzaIJ+62QpMj0qVm4BqN+vN+vNsFEBMD"
+ "JeAfIxJm0mf486+D4fvXtUDjlYg1AiCAKHMAAzRkQCH048evONtYhjiHpECGL5+PMPz9E0uM"
+ "doAAotwBoCD9Dwzi3//+KosoMizMmsswMXWWJAcjywKGH1/7GRgZ2fDpBgggFiJtEWH4/0+T"
+ "4c9/VYa/DNxAH/9j+A+NAnAIMP5m+MGg+PP7b4ZPjI8YorztGcyV9zPFTUwquPXgqjYDpzAo"
+ "NF5iMxgggPA74B+DIsOv//lA2pWHm19dVliWmZuVFxLksDTwH5IGfnz7yaAkpMrwluE5w+rf"
+ "3Qx+GvkMB1t3MoS2x7oeuXhoIwOnYABQxwt0KwACiBFrLmBkYGP4zVAG9G2lm7YHV5ZtNoOJ"
+ "ihEDOycjw1+gZ7EmBSBkYmRiuPLnGMPen4vBhrjxRTDof/dlCG6KZ9h3Zu8JBk4hL4b//98j"
+ "5wKAAMLmAE5gcM6SEZKNmRE1g8FOz4rh1I+dDBe+H2X48Oc1w+//v8HW4UoPf///Abr7L1jN"
+ "9/9fGOx4fBkcGWIYvCtjGM7dvtLEwMpeD3bAtgdgHQABhB4FzECfz1cSVw7fmbOT4R3/Q4by"
+ "h9EMH36/ZvgHdOgfIMRpNxSwMXEwcDJxgh3z5e83hqM/DjIEKqczaMnpMJy7ekGFgZkdRT1A"
+ "ALGgpOY//yNFOEXC1yavY7jOcpJhyo1WBmYmFoZ///4yyHEqMejxmjKIsUowIBIBamb4++c/"
+ "w9XPFxkufjnF8PPvdwZpDjmGasVJDDNXrmJYtnP5FwZOnuno2gACCDkEhIG+r2sMbGZgFfzL"
+ "0H6lloEJaCoT41+GLPlSBjtOL4aL964xPP/wAiQKDQlotAET4u8/vxksFSwYuPgEGFY9XcLg"
+ "IOTO0KE4nWHx+i0MBTMrfwB9ngRUfwTdAQABhHDAn/+eEgISKt46XgzVN/MY3n79DLagQbWD"
+ "QeOLKUPA9BCG03dPvmD48/cOpChmYmT4zwwJjH+M/xi+/NApiqgTNPVUZPAWDmcolW5iaF8w"
+ "k6Fn9cQvDGzc6QxMzKvh8fcXUfwABBDCAT8ZnJ11XRjv/r7FsPHhNnBiC5EOYTD4Z83gPNGZ"
+ "4fnrJwsZOHiLGZj+v4XEAFLZDqLZmbf/Yfzj4SsWyKD5w5QhuauEYceJbfcZOAXSgJbvAVv+"
+ "H6r2H8IBAAHEgpSPdC0VrRh+/vnBYM1nDwx6ZoZs+QKGlYdWgCw/DgzbFKBlwFQITOEsQIN+"
+ "MUJiAGTYP1aQFCMLIwvD5qP7GQpm1TK8fPV8MwOPcDYw2z0GBxO0vEAHAAGEcAAjo8zjj08Y"
+ "lN+pMOTwFUFS8YtfDLtu7AN6lnUHMMj/MDACfcH6H2IQB9DQ30DLv3BCkz8Pw9KDmxj61899"
+ "9x9UKXHzdTMw/0ZY/B97bQsQQIhyIIX9HPM/JgWmf8C8BilewcXsn79MHMAipgxo+QwG1t+Q"
+ "sP/HJAmknwHd+J/hnQDMqD0Mv/7yMTCxZDAw/z/HwAgOZ05oGoGGFDzt/Pm/7+YPkC6AAEKK"
+ "Akbrv//+s/wFlfL//kPSC4gGBg0Qf2dg/gsKFHGGv//6gW6QBXJswWoQPstiYGZ5BqS/AC0H"
+ "qfUEql3I8P3nH6DF/+AOYGRhYWDjBEYLgzFIE0AAIWfD7wzAohQY+ZAE9h9KM/+BZrdfnkDD"
+ "enl4xDS//vh5CF4egYIZ1OD4z3QLGqYQ9b9+i8iLyQpPymoHFkxcDKCAZmT5z3DuzlWG6um9"
+ "8FQIEEAsOCIGgln+gAKAi+H79zo2Zo6y1th+RkYmVoaS2YXAtMABzLrAUg3kW2DyAAczI6zV"
+ "BMyeXz/aOmpaM/hZ2jLs+r8EmKt+MFgyuTLwsFsy/P3x+z3MKoAAwu4AJnhJJ8vw5dscdUkt"
+ "txlpsxgctK0ZZu5ZALQYGDdAh4DTCpZqieHbl2wuTv7oLP8UhgM/NzCsfjMLWEf8Y1CSNmA4"
+ "fvEeMMv/fghTDRBACAdgtPP+mzJ8/rHE2yxAbWHmfIbLrPsYzv/Zz/DvF1Dq818tBo4vK4EO"
+ "YIImLFhC+wesLpWlhaWNJxX0M0hrsDO0PpnH8O8vG4MIsAiX/KfOsGrvJGC0sR+F2QIQQMiJ"
+ "EMnu/7oM335sjHVMlpyWOoFh7ceZDCsfzmQok+9mcFJ3YKiObxJlYeEIgzdSofgfMAUrSioy"
+ "2BuZMfwWec3QfC8fWIN+ZPjx7ztDnFQRw8njtxlOXzz3CVivr4dZBRBALFgqFRlgsbo2zS1H"
+ "sj+xg6H3cSXD4Xe7gbUcJ8OpV8cZbIR4GHxDbRDBjRxzwDTw5tdzhoUfWxkuXD3NAMrRP//+"
+ "ZPCTiGAw+uPBYD01AlixMcwFqrwA0wMQQIhyIIEbmnq/TzZTss7ZUbWBofF+PsPJD4cZ+FkE"
+ "wHI/gT75+e8HohLC2iz5D66sQJAFWJNGyCQwRAvmMcTXljOs37vjFAM3jwsoEv8fh7gBIIBQ"
+ "0wBE6P3nr58Yvn76ziDAIAoMjO/AopwdmBmAQQxMSH+BDVBGfI1MYOLkZeZlMBI0ZYiWTmb4"
+ "85yXwb02leH4aaCNvPwRQPd9RlYPEECYaYCZo/v6g8v2CdMz7JZlzGNg+cfJMPfRVHC7IEIs"
+ "nsFbJJDhN7BZxoie8oEiIEeyMbIz8PzjY/j0+hfD9BnbGZZuW8vw/hMwwfIKFADVYbQJAQII"
+ "Mw38//+ZgZM/fO+5HVsDeiKMFqbPYhCWF2WoulHKIMEqxfD25k+GCVumMrCxciP1lBghDgDm"
+ "hu8/fzM8ev2S4f7zp+//fft6Bljq9TNwcG7H1ZQCCCBEGojlQ3gG3K1ilWP4/HmBhqyu4+zE"
+ "KQyP+W4Cs/9vhoenPjPUzqp4zMDOuwiRDZlhPSQmIPsHAxPbQ2A5cRqY2K6gFdcIf56ApAGA"
+ "AMLdLP///xEwJLxuPL7V59YWlNkUWs2Q7h7JMIV1CbDu573LwMFdA7EYuRxgRLDBFv/Hk2Ah"
+ "ACCACHRMgOUnO0/W91//LpTOr2k9//CKiCCPENBMViZwwxdc7v9Hy46ELUUGAAFERM8IaCAz"
+ "yywGDpbDy3avncjIyuXKwMrFimEvmQAggIjsmoFsYrrOwMHl/f8vcyWwWaUI9SbFTgAIMAAF"
+ "XnDxjsZXyQAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+
+def FontFromFont(font):
+ """
+ Creates a copy of the input `font`.
+
+ :param `font`: an instance of :class:`Font`.
+ """
+
+ new_font = wx.Font(font.GetPointSize(), font.GetFamily(), font.GetStyle(),
+ font.GetWeight(), font.GetUnderlined(),
+ font.GetFaceName(), font.GetEncoding())
+
+ return new_font
+
+
+# ----------------------------------------------------------------------------
+# HTMLHelpWindow is a frame containing the HTML help page for ShortcutEditor
+# ----------------------------------------------------------------------------
+
+class HTMLHelpWindow(wx.Frame):
+ """
+ A simple :class:`Frame` container for the basic help provided to :class:`ShortcutEditor`.
+ The help page is actually straightly derived from:
+
+ http://graphicssoft.about.com/od/gimptutorials/tp/keyboard-shortcut-editor.htm
+ """
+
+ def __init__(self, parent, htmlFile):
+ """
+ Default class constructor.
+
+ :param `parent`: an instance of :class:`ShortcutEditor`;
+ :param string `htmlFile`: a valid HTML file containing either the default help
+ or your particular definition of help.
+ """
+
+ wx.Frame.__init__(self, parent, title=_('Configure Keyboard Shortcuts Help'))
+
+ self.htmlFile = htmlFile
+
+ toolbar = self.CreateToolBar(wx.TB_HORIZONTAL|wx.TB_FLAT|wx.TB_TEXT|wx.TB_3DBUTTONS)
+ self.BuildToolBar(toolbar)
+
+ self.html = wx.html.HtmlWindow(self, style=wx.SUNKEN_BORDER)
+ self.printer = wx.html.HtmlEasyPrinting()
+
+ box = wx.BoxSizer(wx.VERTICAL)
+ box.Add(self.html, 1, wx.EXPAND)
+
+ self.SetSizer(box)
+ self.SetAutoLayout(True)
+
+ self.SetIcon(parent.GetIcon())
+ self.CreateStatusBar()
+
+ xvideo = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
+ yvideo = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
+
+ self.SetSize((xvideo/2, yvideo/2))
+
+ self.html.LoadFile(self.htmlFile)
+ self.Show()
+
+
+ def BuildToolBar(self, toolbar):
+ """
+ Creates a toolbar for :class:`HTMLHelpWindow` containing the standard browsing
+ buttons like `Back`, `Forward`, `Home`, `Refresh` and `Print`.
+
+ :param `toolbar`: an instance of :class:`ToolBar`.
+ """
+
+ w, h = _html_reload.GetBitmap().GetWidth(), _html_reload.GetBitmap().GetHeight()
+ toolbar.SetToolBitmapSize((w, h))
+
+ toolbar.AddLabelTool(wx.ID_BACKWARD, _('Back'), _html_back.GetBitmap(), shortHelp=_('Back'),
+ longHelp=_('Go to the previous page'))
+
+ toolbar.AddLabelTool(wx.ID_FORWARD, _('Forward'), _html_forward.GetBitmap(), shortHelp=_('Forward'),
+ longHelp=_('Go to the next page'))
+
+ toolbar.AddSeparator()
+
+ toolbar.AddLabelTool(wx.ID_HOME, _('Home'), _html_home.GetBitmap(), shortHelp=_('Home Page'),
+ longHelp=_('Go to the home page'))
+
+ toolbar.AddLabelTool(wx.ID_REFRESH, _('Refresh'), _html_reload.GetBitmap(), shortHelp=_('Refresh'),
+ longHelp=_('Refresh the current page'))
+
+ toolbar.AddSeparator()
+ toolbar.AddStretchableSpace()
+
+ toolbar.AddLabelTool(wx.ID_PRINT, _('Print'), _html_print.GetBitmap(), shortHelp=_('Print'),
+ longHelp=_('Print the current page'))
+
+ toolbar.Realize()
+
+ self.Bind(wx.EVT_TOOL, self.OnHTMLToolbar)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI)
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+
+ def OnHTMLToolbar(self, event):
+ """
+ Handles all the ``wx.EVT_TOOL`` events for :class:`HTMLHelpWindow`.
+
+ :param `event`: an instance of :class:`CommandEvent`.
+ """
+
+ evId = event.GetId()
+
+ if evId == wx.ID_BACKWARD:
+ self.html.HistoryBack()
+ elif evId == wx.ID_FORWARD:
+ self.html.HistoryForward()
+ elif evId == wx.ID_HOME:
+ self.html.LoadFile(self.htmlFile)
+ elif evId == wx.ID_REFRESH:
+ self.html.LoadPage(self.html.GetOpenedPage())
+ elif evId == wx.ID_PRINT:
+ self.printer.GetPrintData().SetPaperId(wx.PAPER_LETTER)
+ self.printer.PrintFile(self.html.GetOpenedPage())
+ else:
+ raise Exception('Invalid toolbar item in HTMLHelpWindow')
+
+
+ def OnUpdateUI(self, event):
+ """
+ Handles all the ``wx.EVT_UPDATE_UI`` events for :class:`HTMLHelpWindow`.
+
+ :param `event`: an instance of :class:`UpdateUIEvent`.
+ """
+
+ evId = event.GetId()
+
+ if evId == wx.ID_BACKWARD:
+ event.Enable(self.html.HistoryCanBack())
+ elif evId == wx.ID_FORWARD:
+ event.Enable(self.html.HistoryCanForward())
+ else:
+ event.Skip()
+
+
+ def OnClose(self, event):
+ """
+ Handles the ``wx.EVT_CLOSE`` event for :class:`HTMLHelpWindow`.
+
+ :param `event`: an instance of :class:`CloseEvent`.
+ """
+
+ parent = self.GetParent()
+ self.Destroy()
+
+ parent.htmlWindow = None
+ event.Skip()
+
+
+# ----------------------------------------------------------------------------
+# ShortcutEvent is a special subclassing of wx.PyCommandEvent
+# ----------------------------------------------------------------------------
+
+class ShortcutEvent(wx.PyCommandEvent):
+ """
+ :class:`ShortcutEvent` is a special subclassing of :class:`PyCommandEvent`.
+
+ This event gets emitted when the user is about to change a shortcut (via ``EVT_SHORTCUT_CHANGING``)
+ and when the user has changed a shortcut (via ``EVT_SHORTCUT_CHANGED``).
+ """
+
+ def __init__(self, evtType, evtId, **kwargs):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param integer `evtType`: the event type;
+ :param integer `evtId`: the event identifier.
+ """
+
+ wx.PyCommandEvent.__init__(self, evtType, evtId, **kwargs)
+
+
+ def GetAccelerator(self):
+ """
+ Gets the shortcut string for which the operation was performed for ``EVT_SHORTCUT_CHANGED``
+ and ``EVT_SHORTCUT_CHANGING`` events.
+
+ :return: A string representing the new shortcut string (accelerator).
+ """
+
+ return self.accelerator
+
+
+ def SetAccelerator(self, accelerator):
+ """
+ Sets the shortcut string for which the operation was performed for ``EVT_SHORTCUT_CHANGED``
+ and ``EVT_SHORTCUT_CHANGING`` events.
+
+ :param string `accelerator`: a string representing the new shortcut string (accelerator).
+ """
+
+ self.accelerator = accelerator
+
+
+ def GetOldAccelerator(self):
+ """
+ Returns the previous shortcut string for ``EVT_SHORTCUT_CHANGED`` and
+ ``EVT_SHORTCUT_CHANGING`` events.
+
+ :return: A string representing the old shortcut string (accelerator).
+ """
+
+ return self.oldAccelerator
+
+
+ def SetOldAccelerator(self, accelerator):
+ """
+ Sets the previous shortcut string for ``EVT_SHORTCUT_CHANGED`` and
+ ``EVT_SHORTCUT_CHANGING`` events.
+
+ :param string `accelerator`: a string representing the old shortcut string (accelerator).
+ """
+
+ self.oldAccelerator = accelerator
+
+
+ def SetShortcut(self, shortcut):
+ """
+ Sets the shortcut class used for ``EVT_SHORTCUT_CHANGED`` and
+ ``EVT_SHORTCUT_CHANGING`` events.
+
+ :param `shortcut`: an instance of :class:`Shortcut`.
+ """
+
+ self.shortcut = shortcut
+ self.accelerator = shortcut.accelerator
+
+
+ def GetShortcut(self):
+ """
+ Returns the shortcut class used for ``EVT_SHORTCUT_CHANGED`` and
+ ``EVT_SHORTCUT_CHANGING`` events.
+
+ :return: An instance of :class:`Shortcut`.
+ """
+
+ return self.shortcut
+
+
+# ----------------------------------------------------------------------------
+# Shortcut is a class containing the details for a shortcut, whether from
+# a menu item, an accelerator or a user-defined shortcut. It behaves like
+# a tree, with children and parents.
+# ----------------------------------------------------------------------------
+
+class Shortcut(object):
+ """
+ :class:`Shortcut` is a class containing the details for a shortcut, whether from
+ a menu item, an accelerator or a user-defined shortcut. It behaves like
+ a tree, with children and parents.
+ """
+
+ def __init__(self, label='', accelerator='', bitmap=wx.NullBitmap, help='',
+ menuItem=None, accelId=None):
+ """
+ Default class constructor.
+
+ :param string `label`: the shortcut label string;
+ :param string `accelerator`: the shortcut accelerator string;
+ :param `bitmap`: an instance of :class:`Bitmap`, to display along the shortcut `label`
+ in the interface tree;
+ :param string `help`: the help string for this shortcut, to display in the interface tree;
+ :param `menuItem`: if this :class:`Shortcut` is derived from a :class:`MenuItem`, the :class:`MenuItem`
+ to which it should be associated;
+ :param integer `accelId`: if this :class:`Shortcut` is derived from an accelerator in a :class:`AcceleratorTable`
+ or from a custom, developer-defined shortcut, it represents the ID it is associated with.
+ """
+
+ self.label = label
+ self.accelerator = accelerator
+ self.bitmap = bitmap
+ self.help = help
+ self.menuItem = menuItem
+ self.accelId = accelId
+
+ self.parent = None
+ self.topMenu = False
+ self.imageIndex = -1
+ self.changed = False
+ self.shown = True
+ self.position = None
+
+ self.originalAccelerator = accelerator
+ self.children = []
+
+
+ def AppendItem(self, item):
+ """
+ Appends a :class:`Shortcut` item as a last child of its parent.
+
+ :param `item`: an instance of :class:`Shortcut`.
+ """
+
+ item.parent = self
+ self.children.append(item)
+
+
+ def GetAccelerator(self):
+ """ Returns the string accelerator associated with this shortcut. """
+
+ return self.accelerator
+
+
+ def SetAccelerator(self, accelerator):
+ """
+ Sets the string accelerator associated with this shortcut.
+
+ :param string `accelerator`: a string representing the shortcut string (accelerator).
+ """
+
+ self.accelerator = accelerator
+ self.changed = False
+
+ if self.originalAccelerator != accelerator:
+ self.changed = True
+
+
+ def HasChanged(self):
+ """
+ Returns ``True`` if the current accelerator associated with this :class:`Shortcut` is
+ different from the original one, ``False`` otherwise.
+ """
+
+ return self.changed
+
+
+ def GetBitmap(self):
+ """
+ Returns the bitmap associated with this :class:`Shortcut`.
+
+ :note: You should always check if the returned bitmap is a valid one or not::
+
+ bitmap = shortcut.GetBitmap()
+ if bitmap.IsOk():
+ DoSomething()
+
+
+ as the default bitmap associated with a :class:`Shortcut` is :class:`NullBitmap`.
+ """
+
+ return self.bitmap
+
+
+ def SetBitmap(self, bitmap):
+ """
+ Sets the bitmap associated with this :class:`Shortcut`.
+
+ :param `bitmap`: an instance of :class:`Bitmap` (can be invalid, i.e., :class:`NullBitmap`).
+ """
+
+ self.bitmap = bitmap
+
+
+ def GetLabel(self):
+ """ Returns the string label associated with this shortcut. """
+
+ return self.label
+
+
+ def IsTop(self):
+ """
+ Returns ``True`` if this :class:`Shortcut` is associated with a top-level :class:`Menu`,
+ (i.e., in the top :class:`MenuBar` level), ``False`` otherwise.
+ """
+
+ return self.topMenu
+
+
+ def GetFirstChild(self, item):
+ """
+ Returns this :class:`Shortcut`'s first child and an integer value 'cookie'.
+ Call :meth:`~Shortcut.GetNextChild` for the next child using this very 'cookie' return
+ value as an input.
+
+ :param `item`: an instance of :class:`Shortcut`.
+
+ :return: A tuple with the first value being an instance of :class:`Shortcut` or ``None`` if there are no
+ further children, and as second value an integer parameter 'cookie'.
+
+ :note: This method returns ``None`` if there are no further children.
+ """
+
+ cookie = 0
+ return self.GetNextChild(item, cookie)
+
+
+ def GetNextChild(self, item, cookie):
+ """
+ Returns this :class:`Shortcut`'s next child.
+
+ :param `item`: an instance of :class:`Shortcut`;
+ :param integer `cookie`: a parameter which is opaque for the application but is necessary
+ for the library to make this function reentrant (i.e. allow more than one
+ enumeration on one and the same object simultaneously).
+
+ :return: A tuple with the first value being an instance of :class:`Shortcut` or ``None`` if there are no
+ further children, and as second value an integer parameter 'cookie'.
+
+ :note: This method returns ``None`` if there are no further children.
+ """
+
+ children = item.children
+ if cookie < len(children):
+ return children[cookie], cookie + 1
+
+ return None, cookie
+
+
+ def GetImageIndex(self):
+ """ Returns an integer index to be used in the :class:`ListShortcut` own :class:`ImageList`. """
+
+ return self.imageIndex
+
+
+ def CheckAccelerator(self, item, shortcut, accelerator):
+ """
+ Checks if a shortcut string entered by the user has already been taken by another entry
+ in the :class:`Shortcut` hierarchy.
+
+ :param `item`: an instance of :class:`Shortcut`;
+ :param `shortcut`: another instance of :class:`Shortcut`, to compare with the previous `item`;
+ :param string `accelerator`: the user-edited accelerator string to check.
+
+ :return: An instance of :class:`Shortcut` if the shortcut string entered by the user conflicts
+ with an existing one, ``None`` otherwise.
+ """
+
+ child, cookie = self.GetFirstChild(item)
+
+ while child:
+ existingAccel = child.accelerator.lower().split('+')
+ existingAccel.sort()
+
+ if existingAccel == accelerator and shortcut != child:
+ return child
+
+ conflict = self.CheckAccelerator(child, shortcut, accelerator)
+
+ if conflict:
+ return conflict
+
+ child, cookie = self.GetNextChild(item, cookie)
+
+ return None
+
+
+ def Match(self, filter=u'', item=None):
+ """
+ Matches this :class:`Shortcut` label string against the `filter` input variable.
+
+ :param string `filter`: a string to match;
+ :param `item`: an instance of :class:`Shortcut`: its label string is compared with
+ the `filter` string to look for a match.
+
+ :return: An instance of :class:`Shortcut` if the `filter` string is contained in
+ the `item` lable, ``None`` otherwise.
+
+ :note: The string-matching is case-insensitive.
+ """
+
+ if item is None:
+ item = self
+
+ child, cookie = self.GetFirstChild(item)
+
+ while child:
+
+ if filter in child.label.lower():
+ self.ShowHierarchy(child)
+
+ self.Match(filter, child)
+ child, cookie = self.GetNextChild(item, cookie)
+
+
+ def ShowHierarchy(self, item):
+ """
+ Set the status of this :class:`Shortcut` ans its parent as `shown` in the
+ :class:`ListShortcut` tree hierarchy.
+
+ :param `item`: an instance of :class:`Shortcut`.
+ """
+
+ item.shown = True
+ parent = item.parent
+
+ while parent:
+ parent.shown = True
+ parent = parent.parent
+
+
+ def ResetVisibility(self, item=None):
+ """
+ Set the status of this :class:`Shortcut` and its parent as `hidden` in the
+ :class:`ListShortcut` tree hierarchy.
+
+ :param `item`: an instance of :class:`Shortcut`, used only to make this function reentrant
+ (i.e. allow more than one enumeration on one and the same object simultaneously).
+ """
+
+ if item is None:
+ item = self
+
+ child, cookie = self.GetFirstChild(item)
+
+ while child:
+ child.shown = False
+ item.shown = False
+ self.ResetVisibility(child)
+ child, cookie = self.GetNextChild(item, cookie)
+
+
+ def Get(self, label, item=None):
+ """
+ Returns an instance of :class:`Shortcut` whose label matches the input `label` string.
+
+ :param string `label`: the string label to compare against this :class:`Shortcut` label;
+ :param `item`: an instance of :class:`Shortcut`, used only to make this function reentrant
+ (i.e. allow more than one enumeration on one and the same object simultaneously).
+
+ :return: An instance of :class:`Shortcut` or ``None`` if no match was found.
+ """
+
+ if item is None:
+ item = self
+
+ child, cookie = self.GetFirstChild(item)
+ retChild = None
+
+ while child:
+ if child.label.lower() == label.lower():
+ return child
+
+ retChild = self.Get(label, child)
+ child, cookie = self.GetNextChild(item, cookie)
+
+ return retChild
+
+
+ def GetById(self, id, item=None):
+ """
+ Returns an instance of :class:`Shortcut` whose ID matches the input `id`.
+
+ :param integer `id`: an integer ID to compare against this :class:`Shortcut` id;
+ :param `item`: an instance of :class:`Shortcut`, used only to make this function reentrant
+ (i.e. allow more than one enumeration on one and the same object simultaneously).
+
+ :return: An instance of :class:`Shortcut` or ``None`` if no match was found.
+ """
+
+ if item is None:
+ item = self
+
+ child, cookie = self.GetFirstChild(item)
+ retChild = None
+
+ while child:
+ if child.menuItem and child.menuItem.GetId() == id:
+ return child
+ elif child.accelId == id:
+ return child
+
+ retChild = self.GetById(id, child)
+ child, cookie = self.GetNextChild(item, cookie)
+
+ return retChild
+
+
+ def GetId(self):
+ """ Returns this :class:`Shortcut` ID. """
+
+ if self.menuItem is not None:
+ if isinstance(self.menuItem, wx.Menu):
+ return 1
+ return self.menuItem.GetId()
+
+ return self.accelId
+
+
+ def RestoreDefaults(self, item=None):
+ """
+ Restore the original shortcut string for this :class:`Shortcut`.
+
+ :param `item`: an instance of :class:`Shortcut`, used only to make this function reentrant
+ (i.e. allow more than one enumeration on one and the same object simultaneously).
+ """
+
+ if item is None:
+ item = self
+
+ child, cookie = self.GetFirstChild(item)
+
+ while child:
+ child.accelerator = child.originalAccelerator
+ child.changed = False
+ self.RestoreDefaults(child)
+ child, cookie = self.GetNextChild(item, cookie)
+
+
+ def FromMenuItem(self):
+ """
+ Constructs this :class:`Shortcut` starting from a :class:`Menu` or :class:`MenuItem`.
+
+ The attributes needed to properly construct a :class:`Shortcut` are the label,
+ the accelerator string, the help string (optional) and the bitmap associated
+ with it (optional).
+ """
+
+ if self.menuItem is None:
+ return
+
+ menuItem = self.menuItem
+
+ if isinstance(menuItem, wx.Menu):
+ label = menuItem.GetTitle()
+ accelerator = DISABLED_STRING
+ help = ''
+ bitmap = wx.NullBitmap
+ else:
+ label = menuItem.GetItemLabelText()
+ accelerator = menuItem.GetItemLabel()
+
+ if '\t' in accelerator:
+ accelerator = accelerator[accelerator.index('\t')+1:]
+ else:
+ accelerator = DISABLED_STRING
+
+ help = menuItem.GetHelp()
+ bitmap = menuItem.GetBitmap()
+
+ self.label = label
+ self.accelerator = accelerator
+ self.help = help
+ self.bitmap = bitmap
+
+ self.originalAccelerator = accelerator
+
+
+ def ToMenuItem(self, menuBar):
+ """
+ Dumps this :class:`Shortcut` into a :class:`Menu` or :class:`MenuItem`.
+
+ The attributes needed to properly dump a :class:`Shortcut` into a :class:`Menu` or :class:`MenuBar`
+ are the label and the accelerator string.
+
+ :param `menuBar`: an instance of :class:`MenuBar`.
+ """
+
+ if self.menuItem is None or not self.changed:
+ return
+
+ menuItem = self.menuItem
+
+ if isinstance(menuItem, wx.Menu):
+
+ if self.accelerator == DISABLED_STRING:
+ label = self.label
+ else:
+ label = '%s\t%s'%(self.label, self.accelerator)
+
+ menuBar.SetMenuLabel(menuItem.position, label)
+
+ else:
+
+ label = menuItem.GetItemLabel()
+ if '\t' in label:
+ label = label[0:label.index('\t')]
+
+ if self.accelerator != DISABLED_STRING:
+ label = '%s\t%s'%(label, self.accelerator)
+
+ menuBar.SetLabel(menuItem.GetId(), label)
+
+
+ def ToAcceleratorItem(self, table):
+ """
+ Dumps this :class:`Shortcut` into a tuple of 3 elements:
+
+ * **flags**: a bitmask of ``wx.ACCEL_ALT``, ``wx.ACCEL_SHIFT``, ``wx.ACCEL_CTRL``, ``wx.ACCEL_CMD``
+ or ``wx.ACCEL_NORMAL`` used to specify which modifier keys are held down;
+ * **keyCode**: the keycode to be detected (i.e., ord('b'), wx.WXK_F10, etc...);
+ * **cmdID**: the menu or control command ID to use for the accelerator event.
+
+ :param `table`: a list of tuples, with the above specifications.
+ """
+
+ if self.menuItem is not None or not self.changed:
+ return
+
+ if self.GetId() is None:
+ return
+
+ accelerator = self.accelerator
+ accelId = self.accelId
+
+ split = accelerator.split('+')
+ modifiers, keyCode = split[0:-1], split[-1]
+
+ inv_Accel = dict(zip(ACCELERATORS.values(), ACCELERATORS.keys()))
+ inv_KeyMap = dict(zip(KEYMAP.values(), KEYMAP.keys()))
+
+ base = wx.ACCEL_NORMAL
+
+ for mod in modifiers:
+ base |= inv_Accel[mod]
+
+ if keyCode in inv_KeyMap:
+ keyCode = inv_KeyMap[keyCode]
+ else:
+ keyCode = ord(keyCode)
+
+ accelItem = (base, keyCode, accelId)
+ table.append(accelItem)
+
+
+# ----------------------------------------------------------------------------
+# ConflictDialog is a subclass of GenericMessageDialog, customized to look
+# like the GIMP conflict dialog.
+# ----------------------------------------------------------------------------
+
+class ConflictDialog(GMD.GenericMessageDialog):
+ """
+ :class:`ConflictDialog` is a subclass of :class:`GenericMessageDialog`, customized to look
+ like the GIMP conflict dialog. This class is used to resolve shortcut
+ conflicts when the user assigns a shortcut that is already taken by another
+ entry in the shortcut list.
+ """
+
+ def __init__(self, parent, conflict):
+ """
+ Default class constructor.
+
+ :param `parent`: an instance of :class:`ShortcutEditor`;
+ :param `conflict`: an instance of :class:`Shortcut`, representing the conflicting
+ shortcut.
+ """
+
+ transDict = dict(shortcut=conflict.accelerator, item=conflict.label, group=conflict.parent.label)
+ message = _('Shortcut "%(shortcut)s" is already taken by\n"%(item)s" from the "%(group)s" group. ')%transDict
+
+ transDict = dict(item=conflict.label)
+ extendedMessage = _('Reassigning the shortcut will cause it to be removed from \n"%(item)s". ')%transDict
+
+ GMD.GenericMessageDialog.__init__(self, parent, message, _('Conflicting Shortcuts'),
+ wx.OK|wx.CANCEL|wx.ICON_EXCLAMATION)
+
+ self.SetOKLabel(_('Reassing shortcut '))
+ self.SetOKBitmap(_reassign.GetBitmap())
+
+ self.SetExtendedMessage(extendedMessage + '\n')
+ self.SetIcon(parent.GetParent().GetIcon())
+
+
+# ----------------------------------------------------------------------------
+# ListShortcut is a subclass of HyperTreeList, customized to look
+# like the GIMP main shortcut list.
+# ----------------------------------------------------------------------------
+
+class ListShortcut(HTL.HyperTreeList, treemixin.ExpansionState):
+ """
+ :class:`ListShortcut` is a subclass of :class:`HyperTreeList`, customized to look
+ like the GIMP main shortcut list. This class is used to display the
+ shortcut label (with an optional bitmap next to it), its accelerator and
+ the help string associated with it (if present).
+
+ This information is displayed in 3 columns inside :class:`ListShortcut`.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+
+ :param `parent`: an instance of :class:`ShortcutEditor`.
+ """
+
+ HTL.HyperTreeList.__init__(self, parent, style=wx.BORDER_THEME,
+ agwStyle=wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT|
+ wx.TR_FULL_ROW_HIGHLIGHT|HTL.TR_ELLIPSIZE_LONG_ITEMS)
+
+ self.SetBackgroundColour(wx.WHITE)
+
+ self.AddColumn(_('Action'))
+ self.AddColumn(_('Shortcut'))
+ self.AddColumn(_('Help Label'))
+ self.SetMainColumn(0) # the one with the tree in it...
+
+ self.AddRoot('')
+ self.CalculateOffset()
+
+ self.selectedItem = None
+ self.hookBound = False
+ self.filter = u''
+ self.expansionState = []
+
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged)
+ self.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnExpandCollapse)
+ self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnExpandCollapse)
+
+ mainWindow = self.GetMainWindow()
+ mainWindow.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ mainWindow.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+
+ def CalculateOffset(self):
+ """
+ Calculates an offset (in pixels) so that the :class:`Shortcut` items without
+ a bitmap look parallel to the ones with a bitmap.
+ """
+
+ dc = wx.MemoryDC()
+ dc.SelectObject(wx.EmptyBitmap(20, 20))
+ dc.SetFont(self.GetFont())
+
+ space = 0
+ text = ''
+
+ while space < 15:
+ space, dummy = dc.GetTextExtent(text)
+ text += ' '
+
+ dc.SelectObject(wx.NullBitmap)
+ self.offset = text
+
+ boldFont = FontFromFont(self.GetFont())
+ boldFont.SetWeight(wx.BOLD)
+
+ self.boldFont = boldFont
+
+
+ def Populate(self, item=None, shortcut=None):
+ """
+ Recursively populates the :class:`ListShortcut` with information from the :class:`Shortcut` tree.
+
+ :param `item`: an instance of :class:`GenericTreeItem`. If ``None``, it is defaulted to
+ the :class:`ListShortcut` root item to make this function reentrant (i.e. allow more than one
+ enumeration on one and the same object simultaneously);
+ :param `shortcut`: an instance of :class:`Shortcut`. If ``None``, it is defaulted to
+ `self.manager` to make this function reentrant (i.e. allow more than one
+ enumeration on one and the same object simultaneously).
+ """
+
+ if shortcut is None:
+ shortcut = self.manager
+ item = self.GetRootItem()
+
+ for child in shortcut.children:
+
+ if not child.shown:
+ continue
+
+ image = child.GetImageIndex()
+ label = child.label
+
+ if image < 0:
+ if not child.IsTop():
+ label = self.offset + label
+
+ newItem = self.AppendItem(item, label, data=child)
+ else:
+ newItem = self.AppendItem(item, label, image=image, data=child)
+
+ if child.IsTop():
+ self.SetItemFont(newItem, self.boldFont)
+
+ self.SetItemText(newItem, child.accelerator, 1)
+ self.SetItemText(newItem, child.help, 2)
+
+ colour = (child.HasChanged() and [wx.RED] or [wx.BLACK])[0]
+ self.SetItemTextColour(newItem, colour)
+
+ self.Populate(newItem, child)
+
+
+ def MakeImageList(self):
+ """ Builds the :class:`ListShortcut` image list based on the bitmaps in the :class:`Shortcut` hierarchy. """
+
+ self.imageList = wx.ImageList(16, 16)
+ self.BuildImageList()
+ self.AssignImageList(self.imageList)
+
+
+ def BuildImageList(self, shortcut=None, index=None):
+ """
+ Recursively builds the :class:`ListShortcut` image list based on the bitmaps in the
+ :class:`Shortcut` hierarchy.
+
+ :param `shortcut`: an instance of :class:`Shortcut`. If ``None``, it is defaulted to
+ `self.manager` to make this function reentrant (i.e. allow more than one
+ enumeration on one and the same object simultaneously);
+ :param integer `index`: the current image index inside the :class:`ListShortcut` own :class:`ImageList`.
+ """
+
+ if shortcut is None:
+ shortcut = self.manager
+ index = 0
+
+ for child in shortcut.children:
+ bitmap = child.GetBitmap()
+
+ if bitmap.IsOk():
+ self.imageList.Add(bitmap)
+ child.imageIndex = index
+ index += 1
+
+ index = self.BuildImageList(child, index)
+
+ return index
+
+
+ def GetItemIdentity(self, item):
+ """
+ Return a hashable object that represents the identity of a :class:`ListShortcut` item.
+
+ In this implementation this returns the item label.
+
+ :param `item`: an instance of :class:`GenericTreeItem`.
+ """
+
+ return self.GetItemText(item)
+
+
+ def OnSelChanged(self, event):
+ """
+ Handles the ``wx.EVT_TREE_SEL_CHANGED`` event for :class:`ListShortcut`.
+
+ :param `event`: an instance of :class:`TreeEvent`.
+ """
+
+ selectedItem = event.GetItem()
+
+ if selectedItem != self.selectedItem:
+ if self.selectedItem is not None:
+ pydata = self.GetPyData(self.selectedItem)
+ self.SetItemText(self.selectedItem, pydata.accelerator, 1)
+ else:
+ pydata = self.GetPyData(selectedItem)
+ if pydata.GetId() is not None:
+ self.SetItemText(selectedItem, NEW_ACCEL_STRING, 1)
+ else:
+
+ pydata = self.GetPyData(selectedItem)
+ self.SetItemText(selectedItem, pydata.accelerator, 1)
+
+ self.selectedItem = selectedItem
+ self.ShowShortcutText(False)
+
+
+ def OnExpandCollapse(self, event):
+ """
+ Handles the ``wx.EVT_TREE_ITEM_COLLAPSED`` / ``wx.EVT_TREE_ITEM_EXPANDED`` events for :class:`ListShortcut`.
+
+ :param `event`: an instance of :class:`TreeEvent`.
+ """
+
+ event.Skip()
+ self.expansionState = self.GetExpansionState()
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`ListShortcut`.
+
+ :param `event`: an instance of :class:`MouseEvent`.
+ """
+
+ if not self.hookBound:
+ self.GetParent().Bind(wx.EVT_CHAR_HOOK, self.OnShortcut)
+ self.hookBound = True
+
+ currentItem, flags, column = self.HitTest(event.GetPosition())
+
+ if self.selectedItem is None or not currentItem:
+ event.Skip()
+ return
+
+ pydata = self.GetPyData(currentItem)
+
+ if pydata.GetId() is None:
+ event.Skip()
+ return
+
+ if self.GetItemText(currentItem, 1) != NEW_ACCEL_STRING:
+ self.SetItemText(currentItem, NEW_ACCEL_STRING, 1)
+ else:
+ self.SetItemText(currentItem, pydata.accelerator, 1)
+
+ event.Skip()
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`ListShortcut`.
+
+ :param `event`: an instance of :class:`FocusEvent`.
+ """
+
+ self.GetParent().Unbind(wx.EVT_CHAR_HOOK)
+ self.hookBound = False
+
+ self.ShowShortcutText(False)
+
+ if self.selectedItem:
+ pydata = self.GetPyData(self.selectedItem)
+ self.SetItemText(self.selectedItem, pydata.accelerator, 1)
+
+ event.Skip()
+
+
+ def OnShortcut(self, event):
+ """
+ Handles the ``wx.EVT_CHAR_HOOK`` event for :class:`ShortcutEditor`, implemented in :class:`ListShortcut`
+ as it is easier to deal with in this class.
+
+ :param `event`: an instance of :class:`KeyEvent`.
+ """
+
+ if self.selectedItem is None:
+ # How did we get here???
+ event.Skip()
+ return
+
+ pydata = self.GetPyData(self.selectedItem)
+ currentText = self.GetItemText(self.selectedItem, 1)
+
+ if pydata.GetId() is None:
+ # Don't allow to change labels for shortcuts without an ID
+ event.Skip()
+ return
+
+ self.ShowShortcutText(True)
+ textCtrl = self.GetParent().hiddenText
+
+ keyCode = event.GetKeyCode()
+ modifiers = event.GetModifiers()
+
+ # If we press backspace with no modifers down, *and* the current text is
+ # "New accelerator..." then we reset the accelerator to "Disabled"
+ if keyCode == wx.WXK_BACK and modifiers == 0 and currentText in [NEW_ACCEL_STRING, DISABLED_STRING]:
+
+ accelerator = DISABLED_STRING
+
+ if not self.FireShortcutChanging(pydata, accelerator):
+ return
+
+ pydata.SetAccelerator(accelerator)
+ self.SetItemText(self.selectedItem, pydata.accelerator, 1)
+
+ colour = (pydata.HasChanged() and [wx.RED] or [wx.BLACK])[0]
+ self.SetItemTextColour(self.selectedItem, colour)
+
+ self.ShowShortcutText(False)
+ self.FireShortcutChanged(pydata, accelerator)
+
+ return
+
+ newContent = ''
+
+ for mod_int, mod_name in MODIFIERS:
+
+ if modifiers & mod_int == 0:
+ continue
+
+ newContent += mod_name + '+'
+
+ if newContent.strip():
+ textCtrl.ChangeValue(newContent)
+
+ accelerator = ''
+
+ if keyCode in KEYMAP:
+ accelerator = newContent + KEYMAP[keyCode]
+ else:
+ try:
+ toChar = chr(keyCode)
+ accelerator = newContent + toChar
+ except ValueError:
+ pass
+
+ if accelerator:
+
+ if not self.FireShortcutChanging(pydata, accelerator):
+ return
+
+ if self.AcceptShortcut(pydata, accelerator):
+
+ pydata.SetAccelerator(accelerator)
+ self.SetItemText(self.selectedItem, pydata.accelerator, 1)
+
+ colour = (pydata.HasChanged() and [wx.RED] or [wx.BLACK])[0]
+ self.SetItemTextColour(self.selectedItem, colour)
+
+ self.ShowShortcutText(False)
+ self.FireShortcutChanged(pydata, accelerator)
+
+
+ def AcceptShortcut(self, shortcut, accelerator):
+ """
+ Returns ``True`` if the input `accelerator` is a valid shortcut, ``False`` otherwise.
+
+ :param `shortcut`: an instance of :class:`Shortcut`;
+ :param string `accelerator`: the new accelerator to check.
+
+ :note: Conflicting shortcuts are handled inside this method by presenting the user with
+ a conflict dialog. At this point the user can decide to reassign an existing shortcut
+ or to back away, in which case this method will return ``False``.
+ """
+
+ sortedAccel = accelerator.lower().split('+')
+ sortedAccel.sort()
+
+ conflict = self.manager.CheckAccelerator(self.manager, shortcut, sortedAccel)
+
+ if conflict is None:
+ return True
+
+ dlg = ConflictDialog(self.GetParent(), conflict)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ self.DisableShortcut(conflict)
+ dlg.Destroy()
+ return True
+
+ dlg.Destroy()
+ return False
+
+
+ def DisableShortcut(self, conflict, item=None):
+ """
+ If the user decides to reassign a shortcut to another item, this method will disable
+ the conflicting shortcut (by putting a "Disabled" string as its accelerator).
+
+ :param `conflict`: an instance of :class:`Shortcut` to reset;
+ :param `item`: an instance of :class:`GenericTreeItem`. If defaulted to ``None``, it is set
+ to the :class:`ListShortcut` root item and used only to make this function reentrant
+ (i.e. allow more than one enumeration on one and the same object simultaneously).
+ """
+
+ if item is None:
+ item = self.GetRootItem()
+
+ child, cookie = self.GetFirstChild(item)
+
+ while child:
+ if child.GetData() == conflict:
+ conflict.SetAccelerator(DISABLED_STRING)
+ self.SetItemText(child, conflict.accelerator, 1)
+
+ colour = (conflict.HasChanged() and [wx.RED] or [wx.BLACK])[0]
+ self.SetItemTextColour(child, colour)
+ return
+
+ self.DisableShortcut(conflict, child)
+ child, cookie = self.GetNextChild(item, cookie)
+
+
+ def FireShortcutChanging(self, shortcut, newAccel):
+ """
+ Fires the ``EVT_SHORTCUT_CHANGING`` event for :class:`ListShortcut`.
+
+ The event propagation (and thus the shortcut renaming by the user) can be
+ interrupted by *not* calling `event.Skip()` in your handler for this event.
+
+ :param `shortcut`: an instance of :class:`Shortcut` that is about to be renamed;
+ :param string `newAccel`: the new accelerator just entered by the user.
+ """
+
+ event = ShortcutEvent(wxEVT_SHORTCUT_CHANGING, self.GetId())
+ event.SetShortcut(shortcut)
+ event.oldAccelerator = shortcut.accelerator
+ event.accelerator = newAccel
+ event.SetEventObject(self)
+
+ if self.GetEventHandler().ProcessEvent(event):
+ # the caller didn't use event.Skip()
+ return False
+
+ return True
+
+
+ def FireShortcutChanged(self, shortcut, newAccel):
+ """
+ Fires the ``EVT_SHORTCUT_CHANGED`` event for :class:`ListShortcut`.
+
+ :param `shortcut`: an instance of :class:`Shortcut` that has been renamed;
+ :param string `newAccel`: the new accelerator just entered by the user.
+ """
+
+ event = ShortcutEvent(wxEVT_SHORTCUT_CHANGED, self.GetId())
+ event.SetShortcut(shortcut)
+ event.oldAccelerator = shortcut.accelerator
+ event.accelerator = newAccel
+ event.SetEventObject(self)
+
+ self.GetEventHandler().ProcessEvent(event)
+
+ return True
+
+
+ def ShowShortcutText(self, show):
+ """
+ Shows/Hides a :class:`TextCtrl` used to display the combination of keystrokes the user
+ has entered. This :class:`TextCtrl` remains visible only for a short amount of time
+ and only when some keys are down.
+
+ :param bool `show`: ``True`` to show the :class:`TextCtrl`, ``False`` to hide it.
+ """
+
+ textCtrl = self.GetParent().hiddenText
+
+ if show and not textCtrl.IsShown():
+ textCtrl.Show()
+
+ elif not show and textCtrl.IsShown():
+ textCtrl.Hide()
+
+
+ def SetFilter(self, filter=u''):
+ """
+ Sets the `filter` string against all the shortcuts in the :class:`ListShortcut` are matched.
+
+ :param string `filter`: a string to match.
+ """
+
+ self.filter = filter
+
+ self.manager.ResetVisibility()
+ self.manager.Match(filter)
+ self.RecreateTree()
+
+
+ def RecreateTree(self):
+ """ Recreates the entire :class:`ListShortcut` (columns excluded). """
+
+ self.Freeze()
+ self.DeleteAllItems()
+ self.AddRoot(u'')
+
+ self.Populate()
+
+ if not self.expansionState:
+ # Only the root item
+ self.ExpandAll()
+ else:
+ self.SetExpansionState(self.expansionState)
+
+ self.Thaw()
+
+
+ def HasFlag(self, flag):
+ """
+ Overridden from :class:`Window` as a workaround on the conflicts between `treemixin` and
+ :class:`HyperTreeList` with the ``wx.TR_HIDE_ROOT`` `agwStyle` set.
+
+ :param integer `flag`: an integer bit flag specifying the `agwStyle` style.
+
+ :return: ``True`` if the :class:`ListShortcut` has the input `flag` set, ``False`` otherwise.
+
+ :note: Overridden from :class:`Window`.
+ """
+
+ return self.HasAGWFlag(flag)
+
+
+# ----------------------------------------------------------------------------
+# ShortcutEditor is a subclass of wx.Dialog, customized to look
+# like the GIMP main shortcut dialog.
+# ----------------------------------------------------------------------------
+
+class ShortcutEditor(wx.Dialog):
+ """
+ :class:`ShortcutEditor` is a widget that allows the user to customize and change keyboard
+ shortcuts via a dialog. It can be used to edit :class:`MenuItem` shortcuts or accelerators
+ defined in a :class:`AcceleratorTable`.
+
+ The interface itself is very much inpired by the GIMP shortcut editor:
+
+ http://graphicssoft.about.com/od/gimptutorials/tp/keyboard-shortcut-editor.htm
+
+ There are very few minor UI differences between :class:`ShortcutEditor` and the GIMP one,
+ although the behaviour should be pretty much equivalent.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+
+ :param `parent`: an instance of :class:`Window`, it can also be ``None``.
+ """
+
+ wx.Dialog.__init__(self, parent, title=_('Configure Keyboard Shortcuts'),
+ style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
+
+ self.htmlFile = os.path.join(DATA_DIR, 'default_help_text.html')
+ self.htmlWindow = None
+
+ self.CreateWidgets()
+ self.DoLayout()
+ self.BindEvents()
+
+ if parent is not None and isinstance(parent, wx.TopLevelWindow):
+ self.SetIcon(parent.GetIcon())
+
+ self.Init()
+
+
+ def CreateWidgets(self):
+ """
+ Creates all the widgets needed to populate the interface, such as buttons,
+ texts and, most importantly, :class:`ListShortcut`.
+ """
+
+ self.topStatic = wx.StaticText(self, -1, _('&Search:'))
+ self.searchText = wx.TextCtrl(self, -1, '')
+
+ clearBmp = _clear.GetBitmap()
+ self.clearButton = wx.BitmapButton(self, wx.ID_CLEAR, clearBmp, style=wx.NO_BORDER)
+
+ self.listShortcut = ListShortcut(self)
+ self.hiddenText = wx.TextCtrl(self, -1, '', style=wx.BORDER_THEME)
+
+ w, h, d, e = self.hiddenText.GetFullTextExtent('Ctrl+Shift+Alt+q+g+M', self.hiddenText.GetFont())
+ self.hiddenText.SetMinSize((w, h+d-e+1))
+
+ defaultBmp = _default.GetBitmap()
+ self.defaultButton = buttons.ThemedGenBitmapTextButton(self, wx.ID_RESET, defaultBmp,
+ _('Restore Defaults '), size=(-1, 29))
+
+ self.infoBitmap = wx.StaticBitmap(self, -1, _info.GetBitmap())
+
+ message = _('To edit a shortcut key, click on the corresponding row\n' \
+ 'and type a new accelerator, or press backspace to clear.')
+
+ italicFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ italicFont.SetStyle(wx.ITALIC)
+
+ self.infoStatic = wx.StaticText(self, -1, message)
+ self.infoStatic.SetFont(italicFont)
+
+ okBmp = _ok.GetBitmap()
+ cancelBmp = _cancel.GetBitmap()
+ helpBmp = _help.GetBitmap()
+
+ self.okButton = buttons.ThemedGenBitmapTextButton(self, wx.ID_OK, okBmp, _('OK'))
+ self.cancelButton = buttons.ThemedGenBitmapTextButton(self, wx.ID_CANCEL, cancelBmp, _('Cancel'))
+ self.helpButton = buttons.ThemedGenBitmapTextButton(self, wx.ID_HELP, helpBmp, _('Help'))
+
+ self.okButton.SetDefault()
+
+
+ def DoLayout(self):
+ """ Lays out the widgets using sizers in a platform-independent way. """
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ topSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ mainSizer.Add((0, 5))
+ topSizer.Add(self.topStatic, 0, wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, 5)
+ topSizer.Add(self.searchText, 1, wx.RIGHT, 5)
+ topSizer.Add(self.clearButton, 0, wx.ALIGN_CENTER_VERTICAL)
+
+ mainSizer.Add(topSizer, 0, wx.ALL|wx.EXPAND, 10)
+ mainSizer.Add(self.listShortcut, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
+ mainSizer.Add((0, 5))
+
+ hiddenSizer = wx.BoxSizer(wx.HORIZONTAL)
+ hiddenSizer.Add(self.hiddenText, 0, wx.LEFT|wx.RIGHT|wx.RESERVE_SPACE_EVEN_IF_HIDDEN, 10)
+ hiddenSizer.Add((1, 0), 1, wx.EXPAND)
+ hiddenSizer.Add(self.defaultButton, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
+
+ mainSizer.Add(hiddenSizer, 0, wx.EXPAND|wx.BOTTOM, 5)
+
+ centerSizer = wx.BoxSizer(wx.HORIZONTAL)
+ centerSizer.Add(self.infoBitmap, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 10)
+ centerSizer.Add(self.infoStatic, 1, wx.ALIGN_CENTER)
+
+ mainSizer.Add(centerSizer, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 10)
+
+ otherSizer = wx.BoxSizer(wx.HORIZONTAL)
+ # Add the fancy buttons
+ otherSizer.Add(self.okButton, 0, wx.ALL, 10)
+ otherSizer.Add((0, 0), 1, wx.EXPAND)
+ otherSizer.Add(self.cancelButton, 0, wx.LEFT|wx.TOP|wx.BOTTOM, 10)
+ otherSizer.Add(self.helpButton, 0, wx.ALL, 10)
+ mainSizer.Add(otherSizer, 0, wx.EXPAND|wx.TOP, 5)
+
+ self.hiddenText.Hide()
+ self.SetSizer(mainSizer)
+ mainSizer.Layout()
+
+
+ def BindEvents(self):
+ """
+ Binds a few events we will need to process:
+
+ * ``wx.EVT_TEXT`` for the label filtering;
+ * ``wx.EVT_BUTTON`` for clearing the filtering, for the HTML help window and
+ to reset all the shortcuts to their defaults.
+ """
+
+ self.searchText.Bind(wx.EVT_TEXT, self.OnSetFilter)
+ self.clearButton.Bind(wx.EVT_BUTTON, self.OnClearFilter)
+
+ self.defaultButton.Bind(wx.EVT_BUTTON, self.OnRestoreDefaults)
+ self.helpButton.Bind(wx.EVT_BUTTON, self.OnHTMLHelp)
+
+
+ def Init(self):
+ """ Common initialization procedures. """
+
+ self.manager = Shortcut()
+ self.listShortcut.manager = self.manager
+
+
+ def FromMenuBar(self, topWindow):
+ """
+ Builds the entire shortcut hierarchy starting from a :class:`MenuBar`.
+
+ :param `topWindow`: an instance of :class:`TopLevelWindow`, containing the :class:`MenuBar`
+ we wish to scan.
+ """
+
+ def MenuItemSearch(menu, item):
+
+ for menuItem in menu.GetMenuItems():
+ label = menuItem.GetLabel()
+
+ if not label:
+ # It's a separator
+ continue
+
+ shortcutItem = Shortcut(menuItem=menuItem)
+ shortcutItem.FromMenuItem()
+
+ item.AppendItem(shortcutItem)
+
+ subMenu = menuItem.GetSubMenu()
+
+ if subMenu:
+ MenuItemSearch(subMenu, shortcutItem)
+
+ position = 0
+
+ for menu, name in topWindow.GetMenuBar().GetMenus():
+
+ shortcutItem = Shortcut(menuItem=menu)
+ shortcutItem.topMenu = True
+ shortcutItem.position = position
+ shortcutItem.FromMenuItem()
+
+ position += 1
+ self.manager.AppendItem(shortcutItem)
+ MenuItemSearch(menu, item=shortcutItem)
+
+
+ def ToMenuBar(self, topWindow):
+ """
+ Dumps the entire shortcut hierarchy (for shortcuts associated with a :class:`MenuItem`), into
+ a :class:`MenuBar`, changing only the :class:`Menu` / :class:`MenuItem` labels (it does **not** rebuild
+ the :class:`MenuBar`).
+
+ :param `topWindow`: an instance of :class:`TopLevelWindow`, containing the :class:`MenuBar`
+ we wish to repopulate.
+ """
+
+ def MenuItemSet(shortcut, menuBar):
+
+ child, cookie = shortcut.GetFirstChild(shortcut)
+
+ while child:
+ child.ToMenuItem(menuBar)
+ MenuItemSet(child, menuBar)
+ child, cookie = shortcut.GetNextChild(shortcut, cookie)
+
+ manager = self.GetShortcutManager()
+ menuBar = topWindow.GetMenuBar()
+
+ MenuItemSet(manager, menuBar)
+
+
+ def FromAcceleratorTable(self, accelTable):
+ """
+ Builds the entire shortcut hierarchy starting from a modified version of a :class:`AcceleratorTable`.
+
+ :param `accelTable`: a modified version of :class:`AcceleratorTable`, is a list of tuples (4 elements per tuple),
+ populated like this::
+
+ accelTable = []
+
+ # Every tuple is defined in this way:
+
+ for label, flags, keyCode, cmdID in my_accelerators:
+ # label: the string used to show the accelerator into the ShortcutEditor dialog
+ # flags: a bitmask of wx.ACCEL_ALT, wx.ACCEL_SHIFT, wx.ACCEL_CTRL, wx.ACCEL_CMD,
+ # or wx.ACCEL_NORMAL used to specify which modifier keys are held down
+ # keyCode: the keycode to be detected (i.e., ord('b'), wx.WXK_F10, etc...)
+ # cmdID: the menu or control command ID to use for the accelerator event.
+
+ accel_tuple = (label, flags, keyCode, cmdID)
+ accelTable.append(accel_tuple)
+
+ """
+
+ parentShortcut = Shortcut(_('Accelerators'))
+
+ parentShortcut.topMenu = True
+ self.manager.AppendItem(parentShortcut)
+
+ for text, modifier, accel, ids in accelTable:
+ modifier = ACCELERATORS[modifier]
+ if accel in KEYMAP:
+ accel = KEYMAP[accel]
+ else:
+ accel = chr(accel)
+
+ shortcut = (modifier and ['%s+%s'%(modifier, accel)] or [accel])[0]
+ shortcutItem = Shortcut(text, shortcut, accelId=ids)
+ parentShortcut.AppendItem(shortcutItem)
+
+
+ def ToAcceleratorTable(self, window):
+ """
+ Dumps the entire shortcut hierarchy (for shortcuts associated with a :class:`AcceleratorTable`), into
+ a :class:`AcceleratorTable`. This method **does** rebuild the :class:`AcceleratorTable` and sets it back
+ to the input `window`.
+
+ :param `window`: an instance of :class:`Window`, to which the new :class:`AcceleratorTable` should be set.
+ """
+
+ def AccelItemSet(shortcut, table):
+
+ child, cookie = shortcut.GetFirstChild(shortcut)
+
+ while child:
+ child.ToAcceleratorItem(table)
+ table = AccelItemSet(child, table)
+ child, cookie = shortcut.GetNextChild(shortcut, cookie)
+
+ return table
+
+ manager = self.GetShortcutManager()
+ table = AccelItemSet(manager, table=[])
+
+ window.SetAcceleratorTable(wx.AcceleratorTable(table))
+
+
+ def SetColumnWidths(self):
+ """
+ Sets the :class:`ListShortcut` columns widths to acceptable and eye-pleasing
+ numbers (in pixels).
+ """
+
+ total_width = 0
+ for col in xrange(self.listShortcut.GetColumnCount()):
+ self.listShortcut.SetColumnWidth(col, wx.LIST_AUTOSIZE)
+ width = self.listShortcut.GetColumnWidth(col)
+
+ if col == 0:
+ width += 20
+ elif col == 1:
+ width += 5
+ else:
+ width = min(width, 200)
+
+ width = max(50, width)
+ self.listShortcut.SetColumnWidth(col, width)
+ total_width += width
+
+ self.listShortcut.GetMainWindow()._lineHeight += 5
+ dialogHeight = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)/2
+
+ self.SetSize((total_width+60, dialogHeight))
+
+ self.Center()
+
+
+ def OnSetFilter(self, event=None):
+ """
+ Handles the ``wx.EVT_TEXT`` event for :class:`ShortcutEditor`.
+
+ :param `event`: if not ``None``, an instance of :class:`KeyEvent`.
+ """
+
+ if event:
+ event.Skip()
+
+ filter = self.searchText.GetValue()
+ filter = filter.lower().strip()
+
+ self.listShortcut.SetFilter(filter)
+
+
+ def OnClearFilter(self, event):
+ """
+ Handles the ``wx.EVT_BUTTON`` event for :class:`ShortcutEditor` when the user clears the
+ label filter at the top of the user interface.
+
+ :param `event`: an instance of :class:`CommandEvent`.
+ """
+
+ self.searchText.SetValue(u'')
+
+
+ def OnRestoreDefaults(self, event):
+ """
+ Handles the ``wx.EVT_BUTTON`` event for :class:`ShortcutEditor` when the user restores the
+ original shortcuts.
+
+ :param `event`: an instance of :class:`CommandEvent`.
+ """
+
+ self.manager.RestoreDefaults()
+ self.listShortcut.RecreateTree()
+
+
+ def OnHTMLHelp(self, event):
+ """
+ Handles the ``wx.EVT_BUTTON`` event for :class:`ShortcutEditor` when the user presses the ``Help``
+ button.
+
+ :param `event`: an instance of :class:`CommandEvent`.
+
+ .. note::
+
+ By default, this method launches a :class:`html.HtmlWindow` containing the default
+ HTML help file. If you wish to load another help file, you should call :meth:`~ShortcutEditor.SetHTMLHelpFile`
+ with another input HTML file.
+
+ """
+
+ if self.htmlWindow:
+ self.htmlWindow.Show()
+ self.htmlWindow.Restore()
+ self.htmlWindow.Raise()
+ return
+
+ self.htmlWindow = HTMLHelpWindow(self, self.htmlFile)
+
+
+ def GetShortcutManager(self):
+ """ Returns the root :class:`Shortcut` containing the whole shortcut hierarchy. """
+
+ return self.manager
+
+
+ def SetHTMLHelpFile(self, htmlFile):
+ """
+ Sets a new HTML help file (a valid html file) to be loaded when the user seeks
+ for an explanation on how the UI works.
+
+ :param string `htmlFile`: a valid HTML file.
+ """
+
+ if not os.path.isfile(htmlFile):
+ raise Exception('Invalid HTML help file passed to ShortcutEditor')
+
+ self.htmlFile = htmlFile
+
+ if self.htmlWindow is not None:
+ self.htmlWindow.htmlFile = htmlFile
+ self.htmlWindow.LoadFile(self.htmlFile)
+
+
+ def PreShow(self):
+ """ Does some more common initialization before showing :class:`ShortcutEditor`. """
+
+ self.listShortcut.MakeImageList()
+ self.listShortcut.RecreateTree()
+
+ self.SetColumnWidths()
+
+
+ def ShowModal(self):
+ """
+ Shows the :class:`ShortcutEditor` dialog in an application-modal way.
+
+ Program flow does not return until the dialog has been dismissed with `EndModal`.
+
+ :return: The value set with `SetReturnCode`.
+
+ .. note::
+
+ Notice that it is possible to call :meth:`~ShortcutEditor.ShowModal` for a dialog which had been
+ previously shown with :meth:`~ShortcutEditor.Show`, this allows to make an existing modeless dialog
+ modal. However :meth:`~ShortcutEditor.ShowModal` can't be called twice without intervening `EndModal` calls.
+
+
+ .. note::
+
+ Note that this function creates a temporary event loop which takes precedence
+ over the application's main event loop (see :class:`EventLoopBase`) and which is
+ destroyed when the dialog is dismissed. This also results in a call to
+ :meth:`App.ProcessPendingEvents` ().
+
+ """
+
+ self.PreShow()
+ wx.Dialog.ShowModal(self)
+
+
+ def Show(self, show=True):
+ """
+ Hides or shows the :class:`ShortcutEditor` dialog.
+
+ The preferred way of dismissing a modal dialog is to use `EndModal`.
+
+ :param bool `show`: if ``True``, the dialog box is shown and brought to the front,
+ otherwise the box is hidden. If ``False`` and the dialog is modal, control is
+ returned to the calling program.
+
+ :note: Reimplemented from :class:`Window`.
+ """
+
+ self.PreShow()
+ wx.Dialog.Show(self, show)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/speedmeter.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/speedmeter.py
new file mode 100644
index 0000000..95a2fb8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/speedmeter.py
@@ -0,0 +1,1767 @@
+# --------------------------------------------------------------------------- #
+# SPEEDMETER Control wxPython IMPLEMENTATION
+# Python Code By:
+#
+# Andrea Gavana, @ 25 Sep 2005
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# TODO List/Caveats
+#
+# 1. Combination Of The Two Styles:
+#
+# SM_DRAW_PARTIAL_FILLER
+# SM_DRAW_SECTORS
+#
+# Does Not Work Very Well. It Works Well Only In Case When The Sector Colours
+# Are The Same For All Intervals.
+#
+#
+# Thanks To Gerard Grazzini That Has Tried The Demo On MacOS, I Corrected A
+# Bug On Line 246
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+
+"""
+:class:`SpeedMeter` tries to reproduce the behavior of some car controls (but not only),
+by creating an "angular" control (actually, circular).
+
+
+Description
+===========
+
+:class:`SpeedMeter` tries to reproduce the behavior of some car controls (but not only),
+by creating an "angular" control (actually, circular). I remember to have seen
+it somewhere, and i decided to implement it in wxPython.
+
+:class:`SpeedMeter` starts its construction from an empty bitmap, and it uses some
+functions of the :class:`DC` class to create the rounded effects. everything is
+processed in the `Draw()` method of :class:`SpeedMeter` class.
+
+This implementation allows you to use either directly the :class:`PaintDC`, or the
+better (for me) double buffered style with :class:`BufferedPaintDC`. the double
+buffered implementation has been adapted from the wxPython wiki example:
+
+http://wiki.wxpython.org/index.cgi/doublebuffereddrawing
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.speedmeter as SM
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "SpeedMeter Demo")
+
+ speed = SM.SpeedMeter(self, agwStyle=SM.SM_DRAW_HAND|SM.SM_DRAW_SECTORS|SM.SM_DRAW_MIDDLE_TEXT|SM.SM_DRAW_SECONDARY_TICKS)
+
+ # Set The Region Of Existence Of SpeedMeter (Always In Radians!!!!)
+ speed.SetAngleRange(-pi/6, 7*pi/6)
+
+ # Create The Intervals That Will Divide Our SpeedMeter In Sectors
+ intervals = range(0, 201, 20)
+ speed.SetIntervals(intervals)
+
+ # Assign The Same Colours To All Sectors (We Simulate A Car Control For Speed)
+ # Usually This Is Black
+ colours = [wx.BLACK]*10
+ speed.SetIntervalColours(colours)
+
+ # Assign The Ticks: Here They Are Simply The String Equivalent Of The Intervals
+ ticks = [str(interval) for interval in intervals]
+ speed.SetTicks(ticks)
+ # Set The Ticks/Tick Markers Colour
+ speed.SetTicksColour(wx.WHITE)
+ # We Want To Draw 5 Secondary Ticks Between The Principal Ticks
+ speed.SetNumberOfSecondaryTicks(5)
+
+ # Set The Font For The Ticks Markers
+ speed.SetTicksFont(wx.Font(7, wx.SWISS, wx.NORMAL, wx.NORMAL))
+
+ # Set The Text In The Center Of SpeedMeter
+ speed.SetMiddleText("Km/h")
+ # Assign The Colour To The Center Text
+ speed.SetMiddleTextColour(wx.WHITE)
+ # Assign A Font To The Center Text
+ speed.SetMiddleTextFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.BOLD))
+
+ # Set The Colour For The Hand Indicator
+ speed.SetHandColour(wx.Colour(255, 50, 0))
+
+ # Do Not Draw The External (Container) Arc. Drawing The External Arc May
+ # Sometimes Create Uglier Controls. Try To Comment This Line And See It
+ # For Yourself!
+ speed.DrawExternalArc(False)
+
+ # Set The Current Value For The SpeedMeter
+ speed.SetSpeedValue(44)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Methods and Settings
+====================
+
+:class:`SpeedMeter` is highly customizable, and in particular you can set:
+
+- The start and end angle of existence for :class:`SpeedMeter`;
+- The intervals in which you divide the :class:`SpeedMeter` (numerical values);
+- The corresponding thicks for the intervals;
+- The interval colours (different intervals may have different filling colours);
+- The ticks font and colour;
+- The background colour (outsize the :class:`SpeedMeter` region);
+- The external arc colour;
+- The hand (arrow) colour;
+- The hand's shadow colour;
+- The hand's style ("arrow" or "hand");
+- The partial filler colour;
+- The number of secondary (intermediate) ticks;
+- The direction of increasing speed ("advance" or "reverse");
+- The text to be drawn in the middle and its font;
+- The icon to be drawn in the middle;
+- The first and second gradient colours (that fills the :class:`SpeedMeter` control);
+- The current value.
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+=========================== =========== ==================================================
+Window Styles Hex Value Description
+=========================== =========== ==================================================
+``SM_ROTATE_TEXT`` 0x1 Draws the ticks rotated: the ticks are rotated accordingly to the tick marks positions.
+``SM_DRAW_SECTORS`` 0x2 Different intervals are painted in differend colours (every sector of the circle has its own colour).
+``SM_DRAW_PARTIAL_SECTORS`` 0x4 Every interval has its own colour, but only a circle corona is painted near the ticks.
+``SM_DRAW_HAND`` 0x8 The hand (arrow indicator) is drawn.
+``SM_DRAW_SHADOW`` 0x10 A shadow for the hand is drawn.
+``SM_DRAW_PARTIAL_FILLER`` 0x20 A circle corona that follows the hand position is drawn near the ticks.
+``SM_DRAW_SECONDARY_TICKS`` 0x40 Intermediate (smaller) ticks are drawn between principal ticks.
+``SM_DRAW_MIDDLE_TEXT`` 0x80 Some text is printed in the middle of the control near the center.
+``SM_DRAW_MIDDLE_ICON`` 0x100 An icon is drawn in the middle of the control near the center.
+``SM_DRAW_GRADIENT`` 0x200 A gradient of colours will fill the control.
+``SM_DRAW_FANCY_TICKS`` 0x400 With this style you can use xml tags to create some custom text and draw it at the ticks position. See :mod:`lib.fancytext` for the tags.
+=========================== =========== ==================================================
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`SpeedMeter` is distributed under the wxPython license.
+
+Latest revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.3
+
+"""
+
+#----------------------------------------------------------------------
+# Beginning Of SPEEDMETER wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+import wx.lib.colourdb
+import wx.lib.fancytext as fancytext
+
+from math import pi, sin, cos, log, sqrt, atan2
+
+#----------------------------------------------------------------------
+# DC Drawing Options
+#----------------------------------------------------------------------
+# SM_NORMAL_DC Uses The Normal wx.PaintDC
+# SM_BUFFERED_DC Uses The Double Buffered Drawing Style
+
+SM_NORMAL_DC = 0
+""" Uses the normal :class:`PaintDC`. """
+SM_BUFFERED_DC = 1
+""" Uses a double buffered drawing code. """
+
+#----------------------------------------------------------------------
+# SpeedMeter Styles
+#----------------------------------------------------------------------
+# SM_ROTATE_TEXT: Draws The Ticks Rotated: The Ticks Are Rotated
+# Accordingly To The Tick Marks Positions
+# SM_DRAW_SECTORS: Different Intervals Are Painted In Differend Colours
+# (Every Sector Of The Circle Has Its Own Colour)
+# SM_DRAW_PARTIAL_SECTORS: Every Interval Has Its Own Colour, But Only
+# A Circle Corona Is Painted Near The Ticks
+# SM_DRAW_HAND: The Hand (Arrow Indicator) Is Drawn
+# SM_DRAW_SHADOW: A Shadow For The Hand Is Drawn
+# SM_DRAW_PARTIAL_FILLER: A Circle Corona That Follows The Hand Position
+# Is Drawn Near The Ticks
+# SM_DRAW_SECONDARY_TICKS: Intermediate (Smaller) Ticks Are Drawn Between
+# Principal Ticks
+# SM_DRAW_MIDDLE_TEXT: Some Text Is Printed In The Middle Of The Control
+# Near The Center
+# SM_DRAW_MIDDLE_ICON: An Icon Is Drawn In The Middle Of The Control Near
+# The Center
+# SM_DRAW_GRADIENT: A Gradient Of Colours Will Fill The Control
+# SM_DRAW_FANCY_TICKS: With This Style You Can Use XML Tags To Create
+# Some Custom Text And Draw It At The Ticks Position.
+# See wx.lib.fancytext For The Tags.
+
+SM_ROTATE_TEXT = 1
+""" Draws the ticks rotated: the ticks are rotated accordingly to the tick marks positions. """
+SM_DRAW_SECTORS = 2
+""" Different intervals are painted in differend colours (every sector of the circle has its own colour). """
+SM_DRAW_PARTIAL_SECTORS = 4
+""" Every interval has its own colour, but only a circle corona is painted near the ticks. """
+SM_DRAW_HAND = 8
+""" The hand (arrow indicator) is drawn. """
+SM_DRAW_SHADOW = 16
+""" A shadow for the hand is drawn. """
+SM_DRAW_PARTIAL_FILLER = 32
+""" A circle corona that follows the hand position is drawn near the ticks. """
+SM_DRAW_SECONDARY_TICKS = 64
+""" Intermediate (smaller) ticks are drawn between principal ticks. """
+SM_DRAW_MIDDLE_TEXT = 128
+""" Some text is printed in the middle of the control near the center. """
+SM_DRAW_MIDDLE_ICON = 256
+""" An icon is drawn in the middle of the control near the center. """
+SM_DRAW_GRADIENT = 512
+""" A gradient of colours will fill the control. """
+SM_DRAW_FANCY_TICKS = 1024
+""" With this style you can use xml tags to create some custom text and draw it at the ticks position. See :mod:`lib.fancytext` for the tags. """
+
+#----------------------------------------------------------------------
+# Event Binding
+#----------------------------------------------------------------------
+# SM_MOUSE_TRACK: The Mouse Left Click/Drag Allow You To Change The
+# SpeedMeter Value Interactively
+
+SM_MOUSE_TRACK = 1
+""" Flag to allow the left/right click of the mouse to change the :class:`SpeedMeter` value interactively. """
+
+fontfamily = range(70, 78)
+familyname = ["default", "decorative", "roman", "script", "swiss", "modern", "teletype"]
+
+weights = range(90, 93)
+weightsname = ["normal", "light", "bold"]
+
+styles = [90, 93, 94]
+stylesname = ["normal", "italic", "slant"]
+
+#----------------------------------------------------------------------
+# BUFFERENDWINDOW Class
+# This Class Has Been Taken From The wxPython Wiki, And Slightly
+# Adapted To Fill My Needs. See:
+#
+# http://wiki.wxpython.org/index.cgi/DoubleBufferedDrawing
+#
+# For More Info About DC And Double Buffered Drawing.
+#----------------------------------------------------------------------
+
+class BufferedWindow(wx.Window):
+ """
+ A buffered window class.
+
+ To use it, subclass it and define a `Draw(dc)` method that takes a `dc`
+ to draw to. In that method, put the code needed to draw the picture
+ you want. The window will automatically be double buffered, and the
+ screen will be automatically updated when a Paint event is received.
+
+ When the drawing needs to change, you app needs to call the
+ :meth:`BufferedWindow.UpdateDrawing() <BufferedWindow.UpdateDrawing>` method. Since the drawing is stored in a bitmap, you
+ can also save the drawing to file by calling the
+ `SaveToFile(self, file_name, file_type)` method.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.NO_FULL_REPAINT_ON_RESIZE, bufferedstyle=SM_BUFFERED_DC):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `bufferedstyle`: if set to ``SM_BUFFERED_DC``, double-buffering will
+ be used.
+ """
+
+ wx.Window.__init__(self, parent, id, pos, size, style)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
+
+ # OnSize called to make sure the buffer is initialized.
+ # This might result in OnSize getting called twice on some
+ # platforms at initialization, but little harm done.
+ self.OnSize(None)
+
+
+ def Draw(self, dc):
+ """
+ This method should be overridden when sub-classed.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ pass
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`BufferedWindow`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ if self._bufferedstyle == SM_BUFFERED_DC:
+ dc = wx.BufferedPaintDC(self, self._Buffer)
+ else:
+ dc = wx.PaintDC(self)
+ dc.DrawBitmap(self._Buffer,0,0)
+
+
+ def OnSize(self,event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`BufferedWindow`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Width, self.Height = self.GetClientSizeTuple()
+
+ # Make new off screen bitmap: this bitmap will always have the
+ # current drawing in it, so it can be used to save the image to
+ # a file, or whatever.
+
+ # This seems required on MacOS, it doesn't like wx.EmptyBitmap with
+ # size = (0, 0)
+ # Thanks to Gerard Grazzini
+
+ if "__WXMAC__" in wx.Platform:
+ if self.Width == 0:
+ self.Width = 1
+ if self.Height == 0:
+ self.Height = 1
+
+ self._Buffer = wx.EmptyBitmap(self.Width, self.Height)
+ self.UpdateDrawing()
+
+
+ def UpdateDrawing(self):
+ """
+ This would get called if the drawing needed to change, for whatever reason.
+
+ The idea here is that the drawing is based on some data generated
+ elsewhere in the system. if that data changes, the drawing needs to
+ be updated.
+ """
+
+ if self._bufferedstyle == SM_BUFFERED_DC:
+ dc = wx.BufferedDC(wx.ClientDC(self), self._Buffer)
+ self.Draw(dc)
+ else:
+ # update the buffer
+ dc = wx.MemoryDC()
+ dc.SelectObject(self._Buffer)
+
+ self.Draw(dc)
+ # update the screen
+ wx.ClientDC(self).Blit(0, 0, self.Width, self.Height, dc, 0, 0)
+
+
+#----------------------------------------------------------------------
+# SPEEDMETER Class
+# This Is The Main Class Implementation. See __init__() Method For
+# Details.
+#----------------------------------------------------------------------
+
+class SpeedMeter(BufferedWindow):
+ """
+ :class:`SpeedMeter` tries to reproduce the behavior of some car controls (but not only),
+ by creating an "angular" control (actually, circular).
+
+ This is the main class implementation.
+ """
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, agwStyle=SM_DRAW_HAND,
+ bufferedstyle=SM_BUFFERED_DC,
+ mousestyle=0):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `agwStyle`: this value specifies the :class:`SpeedMeter` styles, and can be a
+ combination of the following bits:
+
+ =========================== =========== ==================================================
+ Window Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``SM_ROTATE_TEXT`` 0x1 Draws the ticks rotated: the ticks are rotated accordingly to the tick marks positions.
+ ``SM_DRAW_SECTORS`` 0x2 Different intervals are painted in differend colours (every sector of the circle has its own colour).
+ ``SM_DRAW_PARTIAL_SECTORS`` 0x4 Every interval has its own colour, but only a circle corona is painted near the ticks.
+ ``SM_DRAW_HAND`` 0x8 The hand (arrow indicator) is drawn.
+ ``SM_DRAW_SHADOW`` 0x10 A shadow for the hand is drawn.
+ ``SM_DRAW_PARTIAL_FILLER`` 0x20 A circle corona that follows the hand position is drawn near the ticks.
+ ``SM_DRAW_SECONDARY_TICKS`` 0x40 Intermediate (smaller) ticks are drawn between principal ticks.
+ ``SM_DRAW_MIDDLE_TEXT`` 0x80 Some text is printed in the middle of the control near the center.
+ ``SM_DRAW_MIDDLE_ICON`` 0x100 An icon is drawn in the middle of the control near the center.
+ ``SM_DRAW_GRADIENT`` 0x200 A gradient of colours will fill the control.
+ ``SM_DRAW_FANCY_TICKS`` 0x400 With this style you can use xml tags to create some custom text and draw it at the ticks position. See :mod:`lib.fancytext` for the tags.
+ =========================== =========== ==================================================
+
+ :param `bufferedstyle`: this value allows you to use the normal :class:`PaintDC` or the
+ double buffered drawing options:
+
+ =========================== =========== ==================================================
+ Buffered Styles Hex Value Description
+ =========================== =========== ==================================================
+ ``SM_NORMAL_DC`` 0x0 Uses the normal :class:`PaintDC`
+ ``SM_BUFFERED_DC`` 0x1 Uses the double buffered drawing style
+ =========================== =========== ==================================================
+
+ :param `mousestyle`: this value allows you to use the mouse to change the :class:`SpeedMeter`
+ value interactively with left click/drag events. If set to ``SM_MOUSE_TRACK``, the mouse
+ left click/drag allow you to change the :class:`SpeedMeter` value interactively.
+ """
+
+ self._agwStyle = agwStyle
+ self._bufferedstyle = bufferedstyle
+ self._mousestyle = mousestyle
+
+ if self._agwStyle & SM_DRAW_SECTORS and self._agwStyle & SM_DRAW_GRADIENT:
+ errstr = "\nERROR: Incompatible Options: SM_DRAW_SECTORS Can Not Be Used In "
+ errstr = errstr + "Conjunction With SM_DRAW_GRADIENT."
+ raise Exception(errstr)
+
+ if self._agwStyle & SM_DRAW_PARTIAL_SECTORS and self._agwStyle & SM_DRAW_SECTORS:
+ errstr = "\nERROR: Incompatible Options: SM_DRAW_SECTORS Can Not Be Used In "
+ errstr = errstr + "Conjunction With SM_DRAW_PARTIAL_SECTORS."
+ raise Exception(errstr)
+
+ if self._agwStyle & SM_DRAW_PARTIAL_SECTORS and self._agwStyle & SM_DRAW_PARTIAL_FILLER:
+ errstr = "\nERROR: Incompatible Options: SM_DRAW_PARTIAL_SECTORS Can Not Be Used In "
+ errstr = errstr + "Conjunction With SM_DRAW_PARTIAL_FILLER."
+ raise Exception(errstr)
+
+ if self._agwStyle & SM_DRAW_FANCY_TICKS and self._agwStyle & SM_ROTATE_TEXT:
+ errstr = "\nERROR: Incompatible Options: SM_DRAW_FANCY_TICKS Can Not Be Used In "
+ errstr = errstr + "Conjunction With SM_ROTATE_TEXT."
+ raise Exception(errstr)
+
+ if self._agwStyle & SM_DRAW_SHADOW and self._agwStyle & SM_DRAW_HAND == 0:
+ errstr = "\nERROR: Incompatible Options: SM_DRAW_SHADOW Can Be Used Only In "
+ errstr = errstr + "Conjunction With SM_DRAW_HAND."
+ raise Exception(errstr)
+
+ if self._agwStyle & SM_DRAW_FANCY_TICKS:
+ wx.lib.colourdb.updateColourDB()
+
+
+ self.SetAngleRange()
+ self.SetIntervals()
+ self.SetSpeedValue()
+ self.SetIntervalColours()
+ self.SetArcColour()
+ self.SetTicks()
+ self.SetTicksFont()
+ self.SetTicksColour()
+ self.SetSpeedBackground()
+ self.SetHandColour()
+ self.SetShadowColour()
+ self.SetFillerColour()
+ self.SetDirection()
+ self.SetNumberOfSecondaryTicks()
+ self.SetMiddleText()
+ self.SetMiddleTextFont()
+ self.SetMiddleTextColour()
+ self.SetFirstGradientColour()
+ self.SetSecondGradientColour()
+ self.SetHandStyle()
+ self.DrawExternalArc()
+
+ BufferedWindow.__init__(self, parent, id, pos, size,
+ style=wx.NO_FULL_REPAINT_ON_RESIZE,
+ bufferedstyle=bufferedstyle)
+
+ if self._mousestyle & SM_MOUSE_TRACK:
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseMotion)
+
+
+ def Draw(self, dc):
+ """
+ Draws everything on the empty bitmap.
+ Here all the chosen styles are applied.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ size = self.GetClientSize()
+
+ if size.x < 21 or size.y < 21:
+ return
+
+ new_dim = size.Get()
+
+ if not hasattr(self, "dim"):
+ self.dim = new_dim
+
+ self.scale = min([float(new_dim[0]) / self.dim[0],
+ float(new_dim[1]) / self.dim[1]])
+
+ # Create An Empty Bitmap
+ self.faceBitmap = wx.EmptyBitmap(size.width, size.height)
+
+ dc.BeginDrawing()
+
+ speedbackground = self.GetSpeedBackground()
+ # Set Background Of The Control
+ dc.SetBackground(wx.Brush(speedbackground))
+ dc.Clear()
+
+ centerX = self.faceBitmap.GetWidth()/2
+ centerY = self.faceBitmap.GetHeight()/2
+
+ self.CenterX = centerX
+ self.CenterY = centerY
+
+ # Get The Radius Of The Sector. Set It A Bit Smaller To Correct Draw After
+ radius = min(centerX, centerY) - 2
+
+ self.Radius = radius
+
+ # Get The Angle Of Existance Of The Sector
+ anglerange = self.GetAngleRange()
+ startangle = anglerange[1]
+ endangle = anglerange[0]
+
+ self.StartAngle = startangle
+ self.EndAngle = endangle
+
+ # Initialize The Colours And The Intervals - Just For Reference To The
+ # Children Functions
+ colours = None
+ intervals = None
+
+ if self._agwStyle & SM_DRAW_SECTORS or self._agwStyle & SM_DRAW_PARTIAL_SECTORS:
+ # Get The Intervals Colours
+ colours = self.GetIntervalColours()[:]
+
+ textangles = []
+ colourangles = []
+ xcoords = []
+ ycoords = []
+
+ # Get The Intervals (Partial Sectors)
+ intervals = self.GetIntervals()[:]
+
+ start = min(intervals)
+ end = max(intervals)
+ span = end - start
+
+ self.StartValue = start
+ self.EndValue = end
+
+ self.Span = span
+
+ # Get The Current Value For The SpeedMeter
+ currentvalue = self.GetSpeedValue()
+
+ # Get The Direction Of The SpeedMeter
+ direction = self.GetDirection()
+ if direction == "Reverse":
+ intervals.reverse()
+
+ if self._agwStyle & SM_DRAW_SECTORS or self._agwStyle & SM_DRAW_PARTIAL_SECTORS:
+ colours.reverse()
+
+ currentvalue = end - currentvalue
+
+ # This Because DrawArc Does Not Draw Last Point
+ offset = 0.1*self.scale/180.0
+
+ xstart, ystart = self.CircleCoords(radius+1, -endangle, centerX, centerY)
+ xend, yend = self.CircleCoords(radius+1, -startangle-offset, centerX, centerY)
+
+ # Calculate The Angle For The Current Value Of SpeedMeter
+ accelangle = (currentvalue - start)/float(span)*(startangle-endangle) - startangle
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ if self._agwStyle & SM_DRAW_PARTIAL_FILLER:
+
+ # Get Some Data For The Partial Filler
+ fillercolour = self.GetFillerColour()
+ fillerendradius = radius - 10.0*self.scale
+ fillerstartradius = radius
+
+ if direction == "Advance":
+ fillerstart = accelangle
+ fillerend = -startangle
+ else:
+ fillerstart = -endangle
+ fillerend = accelangle
+
+ xs1, ys1 = self.CircleCoords(fillerendradius, fillerstart, centerX, centerY)
+ xe1, ye1 = self.CircleCoords(fillerendradius, fillerend, centerX, centerY)
+ xs2, ys2 = self.CircleCoords(fillerstartradius, fillerstart, centerX, centerY)
+ xe2, ye2 = self.CircleCoords(fillerstartradius, fillerend, centerX, centerY)
+
+ # Get The Sector In Which The Current Value Is
+ intersection = self.GetIntersection(currentvalue, intervals)
+ sectorradius = radius - 10*self.scale
+
+ else:
+
+ sectorradius = radius
+
+ if self._agwStyle & SM_DRAW_PARTIAL_FILLER:
+ # Draw The Filler (Both In "Advance" And "Reverse" Directions)
+
+ dc.SetBrush(wx.Brush(fillercolour))
+ dc.DrawArc(xs2, ys2, xe2, ye2, centerX, centerY)
+
+ if self._agwStyle & SM_DRAW_SECTORS == 0:
+ dc.SetBrush(wx.Brush(speedbackground))
+ xclean1, yclean1 = self.CircleCoords(sectorradius, -endangle, centerX, centerY)
+ xclean2, yclean2 = self.CircleCoords(sectorradius, -startangle-offset, centerX, centerY)
+ dc.DrawArc(xclean1, yclean1, xclean2, yclean2, centerX, centerY)
+
+
+ # This Is Needed To Fill The Partial Sector Correctly
+ xold, yold = self.CircleCoords(radius, startangle+endangle, centerX, centerY)
+
+ # Draw The Sectors
+ for ii, interval in enumerate(intervals):
+
+ if direction == "Advance":
+ current = interval - start
+ else:
+ current = end - interval
+
+ angle = (current/float(span))*(startangle-endangle) - startangle
+ angletext = -((pi/2.0) + angle)*180/pi
+ textangles.append(angletext)
+ colourangles.append(angle)
+ xtick, ytick = self.CircleCoords(radius, angle, centerX, centerY)
+
+ # Keep The Coordinates, We Will Need Them After To Position The Ticks
+ xcoords.append(xtick)
+ ycoords.append(ytick)
+ x = xtick
+ y = ytick
+
+ if self._agwStyle & SM_DRAW_SECTORS:
+ if self._agwStyle & SM_DRAW_PARTIAL_FILLER:
+ if direction == "Advance":
+ if current > currentvalue:
+ x, y = self.CircleCoords(radius, angle, centerX, centerY)
+ else:
+ x, y = self.CircleCoords(sectorradius, angle, centerX, centerY)
+ else:
+ if current < end - currentvalue:
+ x, y = self.CircleCoords(radius, angle, centerX, centerY)
+ else:
+ x, y = self.CircleCoords(sectorradius, angle, centerX, centerY)
+ else:
+ x, y = self.CircleCoords(radius, angle, centerX, centerY)
+
+
+ if ii > 0:
+ if self._agwStyle & SM_DRAW_PARTIAL_FILLER and ii == intersection:
+ # We Got The Interval In Which There Is The Current Value. If We Choose
+ # A "Reverse" Direction, First We Draw The Partial Sector, Next The Filler
+
+ dc.SetBrush(wx.Brush(speedbackground))
+
+ if direction == "Reverse":
+ if self._agwStyle & SM_DRAW_SECTORS:
+ dc.SetBrush(wx.Brush(colours[ii-1]))
+
+ dc.DrawArc(xe2, ye2, xold, yold, centerX, centerY)
+
+ if self._agwStyle & SM_DRAW_SECTORS:
+ dc.SetBrush(wx.Brush(colours[ii-1]))
+ else:
+ dc.SetBrush(wx.Brush(speedbackground))
+
+
+ dc.DrawArc(xs1, ys1, xe1, ye1, centerX, centerY)
+
+ if self._agwStyle & SM_DRAW_SECTORS:
+ dc.SetBrush(wx.Brush(colours[ii-1]))
+ # Here We Draw The Rest Of The Sector In Which The Current Value Is
+ if direction == "Advance":
+ dc.DrawArc(xs1, ys1, x, y, centerX, centerY)
+ x = xs1
+ y = ys1
+ else:
+ dc.DrawArc(xe2, ye2, x, y, centerX, centerY)
+
+ elif self._agwStyle & SM_DRAW_SECTORS:
+ dc.SetBrush(wx.Brush(colours[ii-1]))
+
+ # Here We Still Use The SM_DRAW_PARTIAL_FILLER Style, But We Are Not
+ # In The Sector Where The Current Value Resides
+ if self._agwStyle & SM_DRAW_PARTIAL_FILLER and ii != intersection:
+ if direction == "Advance":
+ dc.DrawArc(x, y, xold, yold, centerX, centerY)
+ else:
+ if ii < intersection:
+ dc.DrawArc(x, y, xold, yold, centerX, centerY)
+
+ # This Is The Case Where No SM_DRAW_PARTIAL_FILLER Has Been Chosen
+ else:
+ dc.DrawArc(x, y, xold, yold, centerX, centerY)
+
+ else:
+ if self._agwStyle & SM_DRAW_PARTIAL_FILLER and self._agwStyle & SM_DRAW_SECTORS:
+ dc.SetBrush(wx.Brush(fillercolour))
+ dc.DrawArc(xs2, ys2, xe2, ye2, centerX, centerY)
+ x, y = self.CircleCoords(sectorradius, angle, centerX, centerY)
+ dc.SetBrush(wx.Brush(colours[ii]))
+ dc.DrawArc(xs1, ys1, xe1, ye1, centerX, centerY)
+ x = xs2
+ y = ys2
+
+ xold = x
+ yold = y
+
+ if self._agwStyle & SM_DRAW_PARTIAL_SECTORS:
+
+ sectorendradius = radius - 10.0*self.scale
+ sectorstartradius = radius
+
+ xps, yps = self.CircleCoords(sectorstartradius, angle, centerX, centerY)
+
+ if ii > 0:
+ dc.SetBrush(wx.Brush(colours[ii-1]))
+ dc.DrawArc(xps, yps, xpsold, ypsold, centerX, centerY)
+
+ xpsold = xps
+ ypsold = yps
+
+
+ if self._agwStyle & SM_DRAW_PARTIAL_SECTORS:
+
+ xps1, yps1 = self.CircleCoords(sectorendradius, -endangle+2*offset, centerX, centerY)
+ xps2, yps2 = self.CircleCoords(sectorendradius, -startangle-2*offset, centerX, centerY)
+
+ dc.SetBrush(wx.Brush(speedbackground))
+ dc.DrawArc(xps1, yps1, xps2, yps2, centerX, centerY)
+
+
+ if self._agwStyle & SM_DRAW_GRADIENT:
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ xcurrent, ycurrent = self.CircleCoords(radius, accelangle, centerX, centerY)
+
+ # calculate gradient coefficients
+ col2 = self.GetSecondGradientColour()
+ col1 = self.GetFirstGradientColour()
+
+ r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+ r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+ flrect = float(radius+self.scale)
+
+ numsteps = 200
+
+ rstep = float((r2 - r1)) / numsteps
+ gstep = float((g2 - g1)) / numsteps
+ bstep = float((b2 - b1)) / numsteps
+
+ rf, gf, bf = 0, 0, 0
+
+ radiusteps = flrect/numsteps
+ interface = 0
+
+ for ind in range(numsteps+1):
+ currCol = (r1 + rf, g1 + gf, b1 + bf)
+ dc.SetBrush(wx.Brush(currCol))
+
+ gradradius = flrect - radiusteps*ind
+ xst1, yst1 = self.CircleCoords(gradradius, -endangle, centerX, centerY)
+ xen1, yen1 = self.CircleCoords(gradradius, -startangle-offset, centerX, centerY)
+
+ if self._agwStyle & SM_DRAW_PARTIAL_FILLER:
+ if gradradius >= fillerendradius:
+ if direction == "Advance":
+ dc.DrawArc(xstart, ystart, xcurrent, ycurrent, centerX, centerY)
+ else:
+ dc.DrawArc(xcurrent, ycurrent, xend, yend, centerX, centerY)
+ else:
+ if interface == 0:
+ interface = 1
+ myradius = fillerendradius + 1
+ xint1, yint1 = self.CircleCoords(myradius, -endangle, centerX, centerY)
+ xint2, yint2 = self.CircleCoords(myradius, -startangle-offset, centerX, centerY)
+ dc.DrawArc(xint1, yint1, xint2, yint2, centerX, centerY)
+
+ dc.DrawArc(xst1, yst1, xen1, yen1, centerX, centerY)
+ else:
+ if self._agwStyle & SM_DRAW_PARTIAL_SECTORS:
+ if gradradius <= sectorendradius:
+ if interface == 0:
+ interface = 1
+ myradius = sectorendradius + 1
+ xint1, yint1 = self.CircleCoords(myradius, -endangle, centerX, centerY)
+ xint2, yint2 = self.CircleCoords(myradius, -startangle-offset, centerX, centerY)
+ dc.DrawArc(xint1, yint1, xint2, yint2, centerX, centerY)
+ else:
+ dc.DrawArc(xst1, yst1, xen1, yen1, centerX, centerY)
+ else:
+ dc.DrawArc(xst1, yst1, xen1, yen1, centerX, centerY)
+
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+ textheight = 0
+
+ # Get The Ticks And The Ticks Colour
+ ticks = self.GetTicks()[:]
+ tickscolour = self.GetTicksColour()
+
+ if direction == "Reverse":
+ ticks.reverse()
+
+ if self._agwStyle & SM_DRAW_SECONDARY_TICKS:
+ ticknum = self.GetNumberOfSecondaryTicks()
+ oldinterval = intervals[0]
+
+ dc.SetPen(wx.Pen(tickscolour, 1))
+ dc.SetBrush(wx.Brush(tickscolour))
+ dc.SetTextForeground(tickscolour)
+
+ # Get The Font For The Ticks
+ tfont, fontsize = self.GetTicksFont()
+ tfont = tfont[0]
+ myfamily = tfont.GetFamily()
+
+ fsize = self.scale*fontsize
+ tfont.SetPointSize(int(fsize))
+ tfont.SetFamily(myfamily)
+ dc.SetFont(tfont)
+
+ if self._agwStyle & SM_DRAW_FANCY_TICKS:
+ facename = tfont.GetFaceName()
+ ffamily = familyname[fontfamily.index(tfont.GetFamily())]
+ fweight = weightsname[weights.index(tfont.GetWeight())]
+ fstyle = stylesname[styles.index(tfont.GetStyle())]
+ fcolour = wx.TheColourDatabase.FindName(tickscolour)
+
+ textheight = 0
+
+ # Draw The Ticks And The Markers (Text Ticks)
+ for ii, angles in enumerate(textangles):
+
+ strings = ticks[ii]
+ if self._agwStyle & SM_DRAW_FANCY_TICKS == 0:
+ width, height, dummy, dummy = dc.GetFullTextExtent(strings, tfont)
+ textheight = height
+ else:
+ width, height, dummy = fancytext.GetFullExtent(strings, dc)
+ textheight = height
+
+ lX = dc.GetCharWidth()/2.0
+ lY = dc.GetCharHeight()/2.0
+
+ if self._agwStyle & SM_ROTATE_TEXT:
+ angis = colourangles[ii] - float(width)/(2.0*radius)
+ x, y = self.CircleCoords(radius-10.0*self.scale, angis, centerX, centerY)
+ dc.DrawRotatedText(strings, x, y, angles)
+ else:
+ angis = colourangles[ii]
+ if self._agwStyle & SM_DRAW_FANCY_TICKS == 0:
+ x, y = self.CircleCoords(radius-10*self.scale, angis, centerX, centerY)
+ lX = lX*len(strings)
+ x = x - lX - width*cos(angis)/2.0
+ y = y - lY - height*sin(angis)/2.0
+
+ if self._agwStyle & SM_DRAW_FANCY_TICKS:
+ fancystr = '<font family="' + ffamily + '" size="' + str(int(fsize)) + '" weight="' + fweight + '"'
+ fancystr = fancystr + ' color="' + fcolour + '"' + ' style="' + fstyle + '"> ' + strings + ' </font>'
+
+ width, height, dummy = fancytext.GetFullExtent(fancystr, dc)
+ x, y = self.CircleCoords(radius-10*self.scale, angis, centerX, centerY)
+ x = x - width/2.0 - width*cos(angis)/2.0
+ y = y - height/2.0 - height*sin(angis)/2.0
+ fancytext.RenderToDC(fancystr, dc, x, y)
+ else:
+ dc.DrawText(strings, x, y)
+
+ # This Is The Small Rectangle --> Tick Mark
+ rectangle = colourangles[ii] + pi/2.0
+
+ sinrect = sin(rectangle)
+ cosrect = cos(rectangle)
+ x1 = xcoords[ii] - self.scale*cosrect
+ y1 = ycoords[ii] - self.scale*sinrect
+ x2 = x1 + 3*self.scale*cosrect
+ y2 = y1 + 3*self.scale*sinrect
+ x3 = x1 - 10*self.scale*sinrect
+ y3 = y1 + 10*self.scale*cosrect
+ x4 = x3 + 3*self.scale*cosrect
+ y4 = y3 + 3*self.scale*sinrect
+
+ points = [(x1, y1), (x2, y2), (x4, y4), (x3, y3)]
+
+ dc.DrawPolygon(points)
+
+ if self._agwStyle & SM_DRAW_SECONDARY_TICKS:
+ if ii > 0:
+ newinterval = intervals[ii]
+ oldinterval = intervals[ii-1]
+
+ spacing = (newinterval - oldinterval)/float(ticknum+1)
+
+ for tcount in xrange(ticknum):
+ if direction == "Advance":
+ oldinterval = (oldinterval + spacing) - start
+ stint = oldinterval
+ else:
+ oldinterval = start + (oldinterval + spacing)
+ stint = end - oldinterval
+
+ angle = (stint/float(span))*(startangle-endangle) - startangle
+ rectangle = angle + pi/2.0
+ sinrect = sin(rectangle)
+ cosrect = cos(rectangle)
+ xt, yt = self.CircleCoords(radius, angle, centerX, centerY)
+ x1 = xt - self.scale*cosrect
+ y1 = yt - self.scale*sinrect
+ x2 = x1 + self.scale*cosrect
+ y2 = y1 + self.scale*sinrect
+ x3 = x1 - 6*self.scale*sinrect
+ y3 = y1 + 6*self.scale*cosrect
+ x4 = x3 + self.scale*cosrect
+ y4 = y3 + self.scale*sinrect
+
+ points = [(x1, y1), (x2, y2), (x4, y4), (x3, y3)]
+
+ dc.DrawPolygon(points)
+
+ oldinterval = newinterval
+
+ tfont.SetPointSize(fontsize)
+ tfont.SetFamily(myfamily)
+
+ self.SetTicksFont(tfont)
+
+ # Draw The External Arc
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ if self._drawarc:
+ dc.SetPen(wx.Pen(self.GetArcColour(), 2.0))
+ # If It's Not A Complete Circle, Draw The Connecting Lines And The Arc
+ if abs(abs(startangle - endangle) - 2*pi) > 1.0/180.0:
+ dc.DrawArc(xstart, ystart, xend, yend, centerX, centerY)
+ dc.DrawLine(xstart, ystart, centerX, centerY)
+ dc.DrawLine(xend, yend, centerX, centerY)
+ else:
+ # Draw A Circle, Is A 2*pi Extension Arc = Complete Circle
+ dc.DrawCircle(centerX, centerY, radius)
+
+
+ # Here We Draw The Text In The Middle, Near The Start Of The Arrow (If Present)
+ # This Is Like The "Km/h" Or "mph" Text In The Cars
+ if self._agwStyle & SM_DRAW_MIDDLE_TEXT:
+
+ middlecolour = self.GetMiddleTextColour()
+ middletext = self.GetMiddleText()
+ middleangle = (startangle + endangle)/2.0
+
+ middlefont, middlesize = self.GetMiddleTextFont()
+ middlesize = self.scale*middlesize
+ middlefont.SetPointSize(int(middlesize))
+ dc.SetFont(middlefont)
+
+ mw, mh, dummy, dummy = dc.GetFullTextExtent(middletext, middlefont)
+
+ newx = centerX + 1.5*mw*cos(middleangle) - mw/2.0
+ newy = centerY - 1.5*mh*sin(middleangle) - mh/2.0
+ dc.SetTextForeground(middlecolour)
+ dc.DrawText(middletext, newx, newy)
+
+ # Here We Draw The Icon In The Middle, Near The Start Of The Arrow (If Present)
+ # This Is Like The "Fuel" Icon In The Cars
+ if self._agwStyle & SM_DRAW_MIDDLE_ICON:
+
+ middleicon = self.GetMiddleIcon()
+ middlewidth, middleheight = self.GetMiddleIconDimens()
+ middleicon.SetWidth(middlewidth*self.scale)
+ middleicon.SetHeight(middleheight*self.scale)
+ middleangle = (startangle + endangle)/2.0
+
+ mw = middleicon.GetWidth()
+ mh = middleicon.GetHeight()
+
+ newx = centerX + 1.5*mw*cos(middleangle) - mw/2.0
+ newy = centerY - 1.5*mh*sin(middleangle) - mh/2.0
+
+ dc.DrawIcon(middleicon, newx, newy)
+
+ # Restore Icon Dimension, If Not Something Strange Happens
+ middleicon.SetWidth(middlewidth)
+ middleicon.SetHeight(middleheight)
+
+
+ # Requested To Draw The Hand
+ if self._agwStyle & SM_DRAW_HAND:
+
+ handstyle = self.GetHandStyle()
+ handcolour = self.GetHandColour()
+
+ # Calculate The Data For The Hand
+ if textheight == 0:
+ maxradius = radius-10*self.scale
+ else:
+ maxradius = radius-5*self.scale-textheight
+
+ xarr, yarr = self.CircleCoords(maxradius, accelangle, centerX, centerY)
+
+ if handstyle == "Arrow":
+ x1, y1 = self.CircleCoords(maxradius, accelangle - 4.0/180, centerX, centerY)
+ x2, y2 = self.CircleCoords(maxradius, accelangle + 4.0/180, centerX, centerY)
+ x3, y3 = self.CircleCoords(maxradius+3*(abs(xarr-x1)), accelangle, centerX, centerY)
+
+ newx = centerX + 4*cos(accelangle)*self.scale
+ newy = centerY + 4*sin(accelangle)*self.scale
+
+ else:
+
+ x1 = centerX + 4*self.scale*sin(accelangle)
+ y1 = centerY - 4*self.scale*cos(accelangle)
+ x2 = xarr
+ y2 = yarr
+ x3 = centerX - 4*self.scale*sin(accelangle)
+ y3 = centerY + 4*self.scale*cos(accelangle)
+
+ x4, y4 = self.CircleCoords(5*self.scale*sqrt(3), accelangle+pi, centerX, centerY)
+
+ if self._agwStyle & SM_DRAW_SHADOW:
+
+ if handstyle == "Arrow":
+ # Draw The Shadow
+ shadowcolour = self.GetShadowColour()
+ dc.SetPen(wx.Pen(shadowcolour, 5*log(self.scale+1)))
+ dc.SetBrush(wx.Brush(shadowcolour))
+ shadowdistance = 2.0*self.scale
+ dc.DrawLine(newx + shadowdistance, newy + shadowdistance,
+ xarr + shadowdistance, yarr + shadowdistance)
+
+ dc.DrawPolygon([(x1+shadowdistance, y1+shadowdistance),
+ (x2+shadowdistance, y2+shadowdistance),
+ (x3+shadowdistance, y3+shadowdistance)])
+ else:
+ # Draw The Shadow
+ shadowcolour = self.GetShadowColour()
+ dc.SetBrush(wx.Brush(shadowcolour))
+ dc.SetPen(wx.Pen(shadowcolour, 1.0))
+ shadowdistance = 1.5*self.scale
+
+ dc.DrawPolygon([(x1+shadowdistance, y1+shadowdistance),
+ (x2+shadowdistance, y2+shadowdistance),
+ (x3+shadowdistance, y3+shadowdistance),
+ (x4+shadowdistance, y4+shadowdistance)])
+
+ if handstyle == "Arrow":
+
+ dc.SetPen(wx.Pen(handcolour, 1.5))
+
+ # Draw The Small Circle In The Center --> The Hand "Holder"
+ dc.SetBrush(wx.Brush(speedbackground))
+ dc.DrawCircle(centerX, centerY, 4*self.scale)
+
+ dc.SetPen(wx.Pen(handcolour, 5*log(self.scale+1)))
+ # Draw The "Hand", An Arrow
+ dc.DrawLine(newx, newy, xarr, yarr)
+
+ # Draw The Arrow Pointer
+ dc.SetBrush(wx.Brush(handcolour))
+ dc.DrawPolygon([(x1, y1), (x2, y2), (x3, y3)])
+
+ else:
+
+ # Draw The Hand Pointer
+ dc.SetPen(wx.Pen(handcolour, 1.5))
+ dc.SetBrush(wx.Brush(handcolour))
+ dc.DrawPolygon([(x1, y1), (x2, y2), (x3, y3), (x4, y4)])
+
+ # Draw The Small Circle In The Center --> The Hand "Holder"
+ dc.SetBrush(wx.Brush(speedbackground))
+ dc.DrawCircle(centerX, centerY, 4*self.scale)
+
+
+ dc.EndDrawing()
+
+
+ def SetIntervals(self, intervals=None):
+ """
+ Sets the intervals for :class:`SpeedMeter` (main ticks numeric values).
+
+ :param `intervals`: a Python list of main ticks to be displayed. If defaulted
+ to ``None``, the list `[0, 50, 100]` is used.
+ """
+
+ if intervals is None:
+ intervals = [0, 50, 100]
+
+ self._intervals = intervals
+
+
+ def GetIntervals(self):
+ """ Returns the intervals for :class:`SpeedMeter`, a Python list of main ticks displayed. """
+
+ return self._intervals
+
+
+ def SetSpeedValue(self, value=None):
+ """
+ Sets the current value for :class:`SpeedMeter`.
+
+ :param `value`: a floating point number representing the current value. If defaulted
+ to ``None``, the :class:`SpeedMeter` value will be the middle point of the control range.
+ """
+
+ if value is None:
+ value = (max(self._intervals) - min(self._intervals))/2.0
+ else:
+ if value < min(self._intervals):
+ raise Exception("\nERROR: Value Is Smaller Than Minimum Element In Points List")
+ return
+ elif value > max(self._intervals):
+ raise Exception("\nERROR: Value Is Greater Than Maximum Element In Points List")
+ return
+
+ self._speedvalue = value
+ try:
+ self.UpdateDrawing()
+ except:
+ pass
+
+
+ def GetSpeedValue(self):
+ """ Returns the current value for :class:`SpeedMeter`. """
+
+ return self._speedvalue
+
+
+ def SetAngleRange(self, start=0, end=pi):
+ """
+ Sets the range of existence for :class:`SpeedMeter`.
+
+ :param `start`: the starting angle, in radians;
+ :param `end`: the ending angle, in radians.
+ """
+
+ self._anglerange = [start, end]
+
+
+ def GetAngleRange(self):
+ """
+ Returns the range of existence for :class:`SpeedMeter`.
+ The returned values are in radians.
+ """
+
+ return self._anglerange
+
+
+ def SetIntervalColours(self, colours=None):
+ """
+ Sets the colours for the intervals.
+
+ :param `colours`: a Python list of colours. The length of this list should be
+ the same as the number of circle sectors in :class:`SpeedMeter`. If defaulted to ``None``,
+ all the intervals will have a white colour.
+
+ :note: Every interval (circle sector) should have a colour.
+ """
+
+ if colours is None:
+ if not hasattr(self, "_anglerange"):
+ errstr = "\nERROR: Impossible To Set Interval Colours,"
+ errstr = errstr + " Please Define The Intervals Ranges Before."
+ raise Exception(errstr)
+ return
+
+ colours = [wx.WHITE]*len(self._intervals)
+ else:
+ if len(colours) != len(self._intervals) - 1:
+ errstr = "\nERROR: Length Of Colour List Does Not Match Length"
+ errstr = errstr + " Of Intervals Ranges List."
+ raise Exception(errstr)
+ return
+
+ self._intervalcolours = colours
+
+
+ def GetIntervalColours(self):
+ """ Returns the colours for the intervals."""
+
+ if hasattr(self, "_intervalcolours"):
+ return self._intervalcolours
+ else:
+ raise Exception("\nERROR: No Interval Colours Have Been Defined")
+
+
+ def SetTicks(self, ticks=None):
+ """
+ Sets the ticks for :class:`SpeedMeter` intervals (main ticks string values).
+
+ :param `ticks`: a Python list of strings, representing the ticks values.
+ If defaulted to ``None``, the ticks will be taken from the interval values.
+ """
+
+ if ticks is None:
+ if not hasattr(self, "_anglerange"):
+ errstr = "\nERROR: Impossible To Set Interval Ticks,"
+ errstr = errstr + " Please Define The Intervals Ranges Before."
+ raise Exception(errstr)
+ return
+
+ ticks = []
+
+ for values in self._intervals:
+ ticks.append(str(values))
+
+ else:
+ if len(ticks) != len(self._intervals):
+ errstr = "\nERROR: Length Of Ticks List Does Not Match Length"
+ errstr = errstr + " Of Intervals Ranges List."
+ raise Exception(errstr)
+ return
+
+ self._intervalticks = ticks
+
+
+ def GetTicks(self):
+ """ Returns the ticks for :class:`SpeedMeter` intervals (main ticks string values)."""
+
+ if hasattr(self, "_intervalticks"):
+ return self._intervalticks
+ else:
+ raise Exception("\nERROR: No Interval Ticks Have Been Defined")
+
+
+ def SetTicksFont(self, font=None):
+ """
+ Sets the ticks font.
+
+ :param `font`: a valid :class:`Font` object. If defaulted to ``None``, some standard
+ font will be chosen automatically.
+ """
+
+ if font is None:
+ self._originalfont = [wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, False)]
+ self._originalsize = 10
+ else:
+ self._originalfont = [font]
+ self._originalsize = font.GetPointSize()
+
+
+ def GetTicksFont(self):
+ """ Returns the ticks font."""
+
+ return self._originalfont[:], self._originalsize
+
+
+ def SetTicksColour(self, colour=None):
+ """
+ Sets the ticks colour.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, the
+ ticks colour will be set as blue.
+ """
+
+ if colour is None:
+ colour = wx.BLUE
+
+ self._tickscolour = colour
+
+
+ def GetTicksColour(self):
+ """ Returns the ticks colour."""
+
+ return self._tickscolour
+
+
+ def SetSpeedBackground(self, colour=None):
+ """
+ Sets the background colour outside the :class:`SpeedMeter` control.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, the
+ :class:`SpeedMeter` background will be taken from the system default.
+ """
+
+ if colour is None:
+ colour = wx.SystemSettings_GetColour(0)
+
+ self._speedbackground = colour
+
+
+ def GetSpeedBackground(self):
+ """ Returns the background colour outside the :class:`SpeedMeter` control."""
+
+ return self._speedbackground
+
+
+ def SetHandColour(self, colour=None):
+ """
+ Sets the hand (arrow indicator) colour.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, the arrow
+ indicator will be red.
+ """
+
+ if colour is None:
+ colour = wx.RED
+
+ self._handcolour = colour
+
+
+ def GetHandColour(self):
+ """ Returns the hand (arrow indicator) colour."""
+
+ return self._handcolour
+
+
+ def SetArcColour(self, colour=None):
+ """
+ Sets the external arc colour (thicker line).
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, the arc
+ colour will be black.
+ """
+
+ if colour is None:
+ colour = wx.BLACK
+
+ self._arccolour = colour
+
+
+ def GetArcColour(self):
+ """ Returns the external arc colour."""
+
+ return self._arccolour
+
+
+ def SetShadowColour(self, colour=None):
+ """
+ Sets the hand's shadow colour.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, the shadow
+ colour will be light grey.
+ """
+
+ if colour is None:
+ colour = wx.Colour(150, 150, 150)
+
+ self._shadowcolour = colour
+
+
+ def GetShadowColour(self):
+ """ Returns the hand's shadow colour."""
+
+ return self._shadowcolour
+
+
+ def SetFillerColour(self, colour=None):
+ """
+ Sets the partial filler colour.
+
+ A circle corona near the ticks will be filled with this colour, from
+ the starting value to the current value of :class:`SpeedMeter`.
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ if colour is None:
+ colour = wx.Colour(255, 150, 50)
+
+ self._fillercolour = colour
+
+
+ def GetFillerColour(self):
+ """ Returns the partial filler colour."""
+
+ return self._fillercolour
+
+
+ def SetDirection(self, direction=None):
+ """
+ Sets the direction of advancing :class:`SpeedMeter` value.
+
+ :param `direction`: specifying "advance" will move the hand in clock-wise direction
+ (like normal car speed control), while using "reverse" will move it counterclock-wise
+ direction. If defaulted to ``None``, then "advance" will be used.
+ """
+
+ if direction is None:
+ direction = "Advance"
+
+ if direction not in ["Advance", "Reverse"]:
+ raise Exception('\nERROR: Direction Parameter Should Be One Of "Advance" Or "Reverse".')
+
+ self._direction = direction
+
+
+ def GetDirection(self):
+ """ Returns the direction of advancing :class:`SpeedMeter` value."""
+
+ return self._direction
+
+
+ def SetNumberOfSecondaryTicks(self, ticknum=None):
+ """
+ Sets the number of secondary (intermediate) ticks.
+
+ :param `ticknum`: the number of intermediate ticks. If defaulted to ``None``,
+ 3 ticks are used.
+ """
+
+ if ticknum is None:
+ ticknum = 3
+
+ if ticknum < 1:
+ raise Exception("\nERROR: Number Of Ticks Must Be Greater Than 1.")
+
+ self._secondaryticks = ticknum
+
+
+ def GetNumberOfSecondaryTicks(self):
+ """ Returns the number of secondary (intermediate) ticks. """
+
+ return self._secondaryticks
+
+
+ def SetMiddleText(self, text=None):
+ """
+ Sets the text to be drawn near the center of :class:`SpeedMeter`.
+
+ :param `text`: the text to be drawn near the center of :class:`SpeedMeter`. If
+ defaulted to ``None``, an empty string will be used.
+ """
+
+ if text is None:
+ text = ""
+
+ self._middletext = text
+
+
+ def GetMiddleText(self):
+ """ Returns the text to be drawn near the center of :class:`SpeedMeter`. """
+
+ return self._middletext
+
+
+ def SetMiddleTextFont(self, font=None):
+ """
+ Sets the font for the text in the middle.
+
+ :param `font`: a valid :class:`Font` object. If defaulted to ``None``, some
+ standard font will be generated.
+ """
+
+ if font is None:
+ self._middletextfont = wx.Font(1, wx.SWISS, wx.NORMAL, wx.BOLD, False)
+ self._middletextsize = 10.0
+ self._middletextfont.SetPointSize(self._middletextsize)
+ else:
+ self._middletextfont = font
+ self._middletextsize = font.GetPointSize()
+ self._middletextfont.SetPointSize(self._middletextsize)
+
+
+ def GetMiddleTextFont(self):
+ """ Returns the font for the text in the middle."""
+
+ return self._middletextfont, self._middletextsize
+
+
+ def SetMiddleTextColour(self, colour=None):
+ """
+ Sets the colour for the text in the middle.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, the text
+ in the middle will be painted in blue.
+ """
+
+ if colour is None:
+ colour = wx.BLUE
+
+ self._middlecolour = colour
+
+
+ def GetMiddleTextColour(self):
+ """ Returns the colour for the text in the middle."""
+
+ return self._middlecolour
+
+
+ def SetMiddleIcon(self, icon):
+ """
+ Sets the icon to be drawn near the center of :class:`SpeedMeter`.
+
+ :param `icon`: a valid :class:`Bitmap` object.
+ """
+
+ if icon.Ok():
+ self._middleicon = icon
+ else:
+ raise Exception("\nERROR: Invalid Icon Passed To SpeedMeter.")
+
+
+ def GetMiddleIcon(self):
+ """ Returns the icon to be drawn near the center of :class:`SpeedMeter`. """
+
+ return self._middleicon
+
+
+ def GetMiddleIconDimens(self):
+ """ Used internally. """
+
+ return self._middleicon.GetWidth(), self._middleicon.GetHeight()
+
+
+ def CircleCoords(self, radius, angle, centerX, centerY):
+ """
+ Converts the input values into logical x, y coordinates.
+
+ :param `radius`: the :class:`SpeedMeter` radius;
+ :param `angle`: the angular position of the mouse;
+ :param `centerX`: the `x` position of the :class:`SpeedMeter` center;
+ :param `centerX`: the `y` position of the :class:`SpeedMeter` center.
+ """
+
+ x = radius*cos(angle) + centerX
+ y = radius*sin(angle) + centerY
+
+ return x, y
+
+
+ def GetIntersection(self, current, intervals):
+ """ Used internally. """
+
+ if self.GetDirection() == "Reverse":
+ interval = intervals[:]
+ interval.reverse()
+ else:
+ interval = intervals
+
+ indexes = range(len(intervals))
+ try:
+ intersection = [ind for ind in indexes if interval[ind] <= current <= interval[ind+1]]
+ except:
+ if self.GetDirection() == "Reverse":
+ intersection = [len(intervals) - 1]
+ else:
+ intersection = [0]
+
+ return intersection[0]
+
+
+ def SetFirstGradientColour(self, colour=None):
+ """
+ Sets the first gradient colour (near the ticks).
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ if colour is None:
+ colour = wx.Colour(145, 220, 200)
+
+ self._firstgradientcolour = colour
+
+
+ def GetFirstGradientColour(self):
+ """ Returns the first gradient colour (near the ticks). """
+
+ return self._firstgradientcolour
+
+
+ def SetSecondGradientColour(self, colour=None):
+ """
+ Sets the second gradient colour (near the center).
+
+ :param `colour`: a valid :class:`Colour` object.
+ """
+
+ if colour is None:
+ colour = wx.WHITE
+
+ self._secondgradientcolour = colour
+
+
+ def GetSecondGradientColour(self):
+ """ Returns the first gradient colour (near the center). """
+
+ return self._secondgradientcolour
+
+
+ def SetHandStyle(self, style=None):
+ """
+ Sets the style for the hand (arrow indicator).
+
+ :param `style`: by specifying "Hand", :class:`SpeedMeter` will draw a polygon
+ that simulates the car speed control indicator. Using "Arrow" will force
+ :class:`SpeedMeter` to draw a simple arrow. If defaulted to ``None``, "Hand" will
+ be used.
+ """
+
+ if style is None:
+ style = "Hand"
+
+ if style not in ["Hand", "Arrow"]:
+ raise Exception('\nERROR: Hand Style Parameter Should Be One Of "Hand" Or "Arrow".')
+ return
+
+ self._handstyle = style
+
+
+ def GetHandStyle(self):
+ """ Returns the style for the hand (arrow indicator)."""
+
+ return self._handstyle
+
+
+ def DrawExternalArc(self, draw=True):
+ """
+ Specify wheter or not you wish to draw the external (thicker) arc.
+
+ :param `draw`: ``True`` to draw the external arc, ``False`` otherwise.
+ """
+
+ self._drawarc = draw
+
+
+ def OnMouseMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` event for :class:`SpeedMeter`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+
+ :note: Here only left clicks/drags are involved. Should :class:`SpeedMeter`
+ have something more?
+ """
+
+ mousex = event.GetX()
+ mousey = event.GetY()
+
+ if event.Leaving():
+ return
+
+ pos = self.GetClientSize()
+ size = self.GetPosition()
+ centerX = self.CenterX
+ centerY = self.CenterY
+
+ direction = self.GetDirection()
+
+ if event.LeftIsDown():
+
+ angle = atan2(float(mousey) - centerY, centerX - float(mousex)) + pi - self.EndAngle
+ if angle >= 2*pi:
+ angle = angle - 2*pi
+
+ if direction == "Advance":
+ currentvalue = (self.StartAngle - self.EndAngle - angle)*float(self.Span)/(self.StartAngle - self.EndAngle) + self.StartValue
+ else:
+ currentvalue = (angle)*float(self.Span)/(self.StartAngle - self.EndAngle) + self.StartValue
+
+ if currentvalue >= self.StartValue and currentvalue <= self.EndValue:
+ self.SetSpeedValue(currentvalue)
+
+ event.Skip()
+
+
+ def GetSpeedStyle(self):
+ """ Returns a list of strings and a list of integers containing the styles. """
+
+ stringstyle = []
+ integerstyle = []
+
+ if self._agwStyle & SM_ROTATE_TEXT:
+ stringstyle.append("SM_ROTATE_TEXT")
+ integerstyle.append(SM_ROTATE_TEXT)
+
+ if self._agwStyle & SM_DRAW_SECTORS:
+ stringstyle.append("SM_DRAW_SECTORS")
+ integerstyle.append(SM_DRAW_SECTORS)
+
+ if self._agwStyle & SM_DRAW_PARTIAL_SECTORS:
+ stringstyle.append("SM_DRAW_PARTIAL_SECTORS")
+ integerstyle.append(SM_DRAW_PARTIAL_SECTORS)
+
+ if self._agwStyle & SM_DRAW_HAND:
+ stringstyle.append("SM_DRAW_HAND")
+ integerstyle.append(SM_DRAW_HAND)
+
+ if self._agwStyle & SM_DRAW_SHADOW:
+ stringstyle.append("SM_DRAW_SHADOW")
+ integerstyle.append(SM_DRAW_SHADOW)
+
+ if self._agwStyle & SM_DRAW_PARTIAL_FILLER:
+ stringstyle.append("SM_DRAW_PARTIAL_FILLER")
+ integerstyle.append(SM_DRAW_PARTIAL_FILLER)
+
+ if self._agwStyle & SM_DRAW_SECONDARY_TICKS:
+ stringstyle.append("SM_DRAW_SECONDARY_TICKS")
+ integerstyle.append(SM_DRAW_SECONDARY_TICKS)
+
+ if self._agwStyle & SM_DRAW_MIDDLE_TEXT:
+ stringstyle.append("SM_DRAW_MIDDLE_TEXT")
+ integerstyle.append(SM_DRAW_MIDDLE_TEXT)
+
+ if self._agwStyle & SM_DRAW_MIDDLE_ICON:
+ stringstyle.append("SM_DRAW_MIDDLE_ICON")
+ integerstyle.append(SM_DRAW_MIDDLE_ICON)
+
+ if self._agwStyle & SM_DRAW_GRADIENT:
+ stringstyle.append("SM_DRAW_GRADIENT")
+ integerstyle.append(SM_DRAW_GRADIENT)
+
+ if self._agwStyle & SM_DRAW_FANCY_TICKS:
+ stringstyle.append("SM_DRAW_FANCY_TICKS")
+ integerstyle.append(SM_DRAW_FANCY_TICKS)
+
+ return stringstyle, integerstyle
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/supertooltip.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/supertooltip.py
new file mode 100644
index 0000000..da6275e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/supertooltip.py
@@ -0,0 +1,1440 @@
+# --------------------------------------------------------------------------------- #
+# SUPERTOOLTIP wxPython IMPLEMENTATION
+#
+# Andrea Gavana, @ 07 October 2008
+# Latest Revision: 04 Feb 2013, 21.00 GMT
+#
+#
+# TODO List
+#
+# 1) Maybe add some more customization like multiline text
+# in the header and footer;
+# 2) Check whether it's possible to use rounded corners and
+# shadows on the Mac
+# 3) Split OnPaint() into smaller pieces to improve readability and
+# ability to redefine behaviour in subclasses
+# 4) Extend text formatting capabilities
+# 5) Make better use of links (right now it's difficult to click them without hiding tooltip)
+#
+# For all kind of problems, requests of enhancements and bug reports, please
+# write to me at:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, obviously, to the wxPython mailing list!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+"""
+:class:`SuperToolTip` is a class that mimics the behaviour of :class:`TipWindow` and generic tooltip
+windows, although it is a custom-drawn widget.
+
+
+Description
+===========
+
+:class:`SuperToolTip` is a class that mimics the behaviour of :class:`TipWindow` and generic tooltip
+windows, although it is a custom-drawn widget.
+
+This class supports:
+
+* Blended triple-gradient for the tooltip background;
+* Header text and header image, with possibility to set the header font indipendently;
+* Footer text and footer image, with possibility to set the footer font indipendently;
+* Multiline text message in the tooltip body, plus an optional image as "body image";
+* Bold lines and hyperlink lines in the tooltip body;
+* A wide set of predefined drawing styles for the tooltip background;
+* Drawing of separator lines after the header and/or before the footer;
+* Rounded corners and shadows below the tooltip window (Windows XP only);
+* Fade in/fade out effects (Windows XP only);
+* User-settable delays for the delay after which the tooltip appears and the delay
+ after which the tooltip is destroyed.
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.supertooltip as STT
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "SuperToolTip Demo")
+
+ panel = wx.Panel(self)
+ button = wx.Button(panel, -1, "I am the SuperToolTip target", pos=(100, 50))
+
+ tip = STT.SuperToolTip("A nice tooltip message")
+
+ tip.SetHeader("Hello World")
+ tip.SetTarget(button)
+ tip.SetDrawHeaderLine(True)
+
+ tip.ApplyStyle("Office 2007 Blue")
+
+ tip.SetDropShadow(True)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+:class:`SuperToolTip` has been tested on the following platforms:
+ * Windows (Windows XP).
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`SuperToolTip` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 04 Feb 2013, 21.00 GMT
+
+Version 0.5
+
+"""
+
+# Version Info
+__version__ = "0.5"
+
+import wx
+import webbrowser
+
+# Let's see if we can add few nice shadows to our tooltips (Windows only)
+_libimported = None
+
+if wx.Platform == "__WXMSW__":
+ osVersion = wx.GetOsVersion()
+ # Shadows behind menus are supported only in XP
+ if osVersion[1] > 5 or (osVersion[1] == 5 and osVersion[2] >= 1):
+ try:
+ # Try Mark Hammond's win32all extensions
+ import win32api
+ import win32con
+ import win32gui
+ import winxpgui
+ _libimported = "MH"
+ except ImportError:
+ _libimported = None
+ else:
+ _libimported = None
+
+
+# Define a bunch of predefined colour schemes...
+
+_colourSchemes = {"Beige": (wx.Colour(255,255,255), wx.Colour(242,242,223), wx.Colour(198,195,160), wx.Colour(0,0,0)),
+ "Blue": (wx.Colour(255,255,255), wx.Colour(202,220,246), wx.Colour(150,180,222), wx.Colour(0,0,0)),
+ "Blue 2": (wx.Colour(255,255,255), wx.Colour(228,236,248), wx.Colour(198,214,235), wx.Colour(0,0,0)),
+ "Blue 3": (wx.Colour(255,255,255), wx.Colour(213,233,243), wx.Colour(151,195,216), wx.Colour(0,0,0)),
+ "Blue 4": (wx.Colour(255,255,255), wx.Colour(227,235,255), wx.Colour(102,153,255), wx.Colour(0,0,0)),
+ "Blue Glass": (wx.Colour(182,226,253), wx.Colour(137,185,232), wx.Colour(188,244,253), wx.Colour(0,0,0)),
+ "Blue Glass 2": (wx.Colour(192,236,255), wx.Colour(147,195,242), wx.Colour(198,254,255), wx.Colour(0,0,0)),
+ "Blue Glass 3": (wx.Colour(212,255,255), wx.Colour(167,215,255), wx.Colour(218,255,255), wx.Colour(0,0,0)),
+ "Blue Inverted": (wx.Colour(117,160,222), wx.Colour(167,210,240), wx.Colour(233,243,255), wx.Colour(0,0,0)),
+ "Blue Shift": (wx.Colour(124,178,190), wx.Colour(13,122,153), wx.Colour(0,89,116), wx.Colour(255,255,255)),
+ "CodeProject": (wx.Colour(255,250,172), wx.Colour(255,207,157), wx.Colour(255,153,0), wx.Colour(0,0,0)),
+ "Dark Gray": (wx.Colour(195,195,195), wx.Colour(168,168,168), wx.Colour(134,134,134), wx.Colour(255,255,255)),
+ "Deep Purple": (wx.Colour(131,128,164), wx.Colour(112,110,143), wx.Colour(90,88,117), wx.Colour(255,255,255)),
+ "Electric Blue": (wx.Colour(224,233,255), wx.Colour(135,146,251), wx.Colour(99,109,233), wx.Colour(0,0,0)),
+ "Firefox": (wx.Colour(255,254,207), wx.Colour(254,248,125), wx.Colour(225,119,24), wx.Colour(0,0,0)),
+ "Gold": (wx.Colour(255,202,0), wx.Colour(255,202,0), wx.Colour(255,202,0), wx.Colour(0,0,0)),
+ "Gold Shift": (wx.Colour(178,170,107), wx.Colour(202,180,32), wx.Colour(162,139,1), wx.Colour(255,255,255)),
+ "Gray": (wx.Colour(255,255,255), wx.Colour(228,228,228), wx.Colour(194,194,194), wx.Colour(0,0,0)),
+ "Green": (wx.Colour(234,241,223), wx.Colour(211,224,180), wx.Colour(182,200,150), wx.Colour(0,0,0)),
+ "Green Shift": (wx.Colour(129,184,129), wx.Colour(13,185,15), wx.Colour(1,125,1), wx.Colour(255,255,255)),
+ "Light Green": (wx.Colour(174,251,171), wx.Colour(145,221,146), wx.Colour(90,176,89), wx.Colour(0,0,0)),
+ "NASA Blue": (wx.Colour(0,91,134), wx.Colour(0,100,150), wx.Colour(0,105,160), wx.Colour(255,255,255)),
+ "Office 2007 Blue": (wx.Colour(255,255,255), wx.Colour(242,246,251), wx.Colour(202,218,239), wx.Colour(76,76,76)),
+ "Orange Shift": (wx.Colour(179,120,80), wx.Colour(183,92,19), wx.Colour(157,73,1), wx.Colour(255,255,255)),
+ "Outlook Green": (wx.Colour(236,242,208), wx.Colour(219,230,187), wx.Colour(195,210,155), wx.Colour(0,0,0)),
+ "Pale Green": (wx.Colour(249,255,248), wx.Colour(206,246,209), wx.Colour(148,225,155), wx.Colour(0,0,0)),
+ "Pink Blush": (wx.Colour(255,254,255), wx.Colour(255,231,242), wx.Colour(255,213,233), wx.Colour(0,0,0)),
+ "Pink Shift": (wx.Colour(202,135,188), wx.Colour(186,8,158), wx.Colour(146,2,116), wx.Colour(255,255,255)),
+ "Pretty Pink": (wx.Colour(255,240,249), wx.Colour(253,205,217), wx.Colour(255,150,177), wx.Colour(0,0,0)),
+ "Red": (wx.Colour(255,183,176), wx.Colour(253,157,143), wx.Colour(206,88,78), wx.Colour(0,0,0)),
+ "Red Shift": (wx.Colour(186,102,102), wx.Colour(229,23,9), wx.Colour(182,11,1), wx.Colour(255,255,255)),
+ "Silver": (wx.Colour(255,255,255), wx.Colour(242,242,246), wx.Colour(212,212,224), wx.Colour(0,0,0)),
+ "Silver 2": (wx.Colour(255,255,255), wx.Colour(242,242,248), wx.Colour(222,222,228), wx.Colour(0,0,0)),
+ "Silver Glass": (wx.Colour(158,158,158), wx.Colour(255,255,255), wx.Colour(105,105,105), wx.Colour(0,0,0)),
+ "Silver Inverted": (wx.Colour(161,160,186), wx.Colour(199,201,213), wx.Colour(255,255,255), wx.Colour(0,0,0)),
+ "Silver Inverted 2": (wx.Colour(181,180,206), wx.Colour(219,221,233), wx.Colour(255,255,255), wx.Colour(0,0,0)),
+ "Soylent Green": (wx.Colour(134,211,131), wx.Colour(105,181,106), wx.Colour(50,136,49), wx.Colour(255,255,255)),
+ "Spring Green": (wx.Colour(154,231,151), wx.Colour(125,201,126), wx.Colour(70,156,69), wx.Colour(255,255,255)),
+ "Too Blue": (wx.Colour(255,255,255), wx.Colour(225,235,244), wx.Colour(188,209,226), wx.Colour(0,0,0)),
+ "Totally Green": (wx.Colour(190,230,160), wx.Colour(190,230,160), wx.Colour(190,230,160), wx.Colour(0,0,0)),
+ "XP Blue": (wx.Colour(119,185,236), wx.Colour(81,144,223), wx.Colour(36,76,171), wx.Colour(255,255,255)),
+ "Yellow": (wx.Colour(255,255,220), wx.Colour(255,231,161), wx.Colour(254,218,108), wx.Colour(0,0,0))}
+
+
+def GetStyleKeys():
+ """ Returns the predefined styles keywords. """
+
+ schemes = _colourSchemes.keys()
+ schemes.sort()
+ return schemes
+
+
+def MakeBold(font):
+ """
+ Makes a font bold. Utility method.
+
+ :param `font`: the font to be made bold.
+ """
+
+ newFont = wx.Font(font.GetPointSize(), font.GetFamily(), font.GetStyle(),
+ wx.BOLD, font.GetUnderlined(), font.GetFaceName())
+
+ return newFont
+
+
+def ExtractLink(line):
+ """
+ Extract the link from an hyperlink line.
+
+ :param `line`: the line of text to be processed.
+ """
+
+ line = line[4:]
+ indxStart = line.find("{")
+ indxEnd = line.find("}")
+ hl = line[indxStart+1:indxEnd].strip()
+ line = line[0:indxStart].strip()
+
+ return line, hl
+
+
+class ToolTipWindowBase(object):
+ """ Base class for the different Windows and Mac implementation. """
+
+ def __init__(self, parent, classParent):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`SuperToolTip` parent widget;
+ :param `classParent`: the :class:`SuperToolTip` class object.
+ """
+
+ self._spacing = 6
+ self._wasOnLink = False
+ self._hyperlinkRect, self._hyperlinkWeb = [], []
+
+ self._classParent = classParent
+ self._alphaTimer = wx.Timer(self, wx.ID_ANY)
+
+ # Bind the events
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
+ self.Bind(wx.EVT_TIMER, self.AlphaCycle)
+ parent.Bind(wx.EVT_KILL_FOCUS, self.OnDestroy)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnDestroy)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnDestroy)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`SuperToolTip`.
+
+ If the `event` parameter is ``None``, calculates best size and returns it.
+
+ :param `event`: a :class:`PaintEvent` event to be processed or ``None``.
+ """
+
+ maxWidth = 0
+ if event is None:
+ dc = wx.ClientDC(self)
+ else:
+ # Go with double buffering...
+ dc = wx.BufferedPaintDC(self)
+
+ frameRect = self.GetClientRect()
+ x, y, width, _height = frameRect
+ # Store the rects for the hyperlink lines
+ self._hyperlinkRect, self._hyperlinkWeb = [], []
+ classParent = self._classParent
+
+ # Retrieve the colours for the blended triple-gradient background
+ topColour, middleColour, bottomColour = classParent.GetTopGradientColour(), \
+ classParent.GetMiddleGradientColour(), \
+ classParent.GetBottomGradientColour()
+
+ # Get the user options for header, bitmaps etc...
+ drawHeader, drawFooter = classParent.GetDrawHeaderLine(), classParent.GetDrawFooterLine()
+ topRect = wx.Rect(frameRect.x, frameRect.y, frameRect.width, frameRect.height/2)
+ bottomRect = wx.Rect(frameRect.x, frameRect.y+frameRect.height/2, frameRect.width, frameRect.height/2+1)
+ # Fill the triple-gradient
+ dc.GradientFillLinear(topRect, topColour, middleColour, wx.SOUTH)
+ dc.GradientFillLinear(bottomRect, middleColour, bottomColour, wx.SOUTH)
+
+ header, headerBmp = classParent.GetHeader(), classParent.GetHeaderBitmap()
+ headerFont, messageFont, footerFont, hyperlinkFont = classParent.GetHeaderFont(), classParent.GetMessageFont(), \
+ classParent.GetFooterFont(), classParent.GetHyperlinkFont()
+
+ yPos = 0
+ bmpXPos = 0
+ bmpHeight = textHeight = bmpWidth = 0
+
+ if headerBmp and headerBmp.IsOk():
+ # We got the header bitmap
+ bmpHeight, bmpWidth = headerBmp.GetHeight(), headerBmp.GetWidth()
+ bmpXPos = self._spacing
+
+ if header:
+ # We got the header text
+ dc.SetFont(headerFont)
+ textWidth, textHeight = dc.GetTextExtent(header)
+ maxWidth = max(bmpWidth+(textWidth+self._spacing*3), maxWidth)
+ # Calculate the header height
+ height = max(textHeight, bmpHeight)
+ if header:
+ dc.DrawText(header, bmpXPos+bmpWidth+self._spacing, (height-textHeight+self._spacing)/2)
+ if headerBmp and headerBmp.IsOk():
+ dc.DrawBitmap(headerBmp, bmpXPos, (height-bmpHeight+self._spacing)/2, True)
+
+ if header or (headerBmp and headerBmp.IsOk()):
+ yPos += height
+ if drawHeader:
+ # Draw the separator line after the header
+ dc.SetPen(wx.GREY_PEN)
+ dc.DrawLine(self._spacing, yPos+self._spacing, width-self._spacing, yPos+self._spacing)
+ yPos += self._spacing
+
+ maxWidth = max(bmpXPos + bmpWidth + self._spacing, maxWidth)
+ # Get the big body image (if any)
+ embeddedImage = classParent.GetBodyImage()
+ bmpWidth = bmpHeight = -1
+ if embeddedImage and embeddedImage.IsOk():
+ bmpWidth, bmpHeight = embeddedImage.GetWidth(), embeddedImage.GetHeight()
+
+ # A bunch of calculations to draw the main body message
+ messageHeight = 0
+ lines = classParent.GetMessage().split("\n")
+ yText = yPos
+ embImgPos = yPos
+ normalText = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUTEXT)
+ hyperLinkText = wx.BLUE
+ messagePos = self._getTextExtent(dc, lines[0] if lines else "")[1] / 2 + self._spacing
+ for line in lines:
+ # Loop over all the lines in the message
+ if line.startswith("<hr>"): # draw a line
+ yText += self._spacing * 2
+ dc.DrawLine(self._spacing, yText+self._spacing, width-self._spacing, yText+self._spacing)
+ else:
+ isLink = False
+ dc.SetTextForeground(normalText)
+ if line.startswith("</b>"): # is a bold line
+ line = line[4:]
+ font = MakeBold(messageFont)
+ dc.SetFont(font)
+ elif line.startswith("</l>"): # is a link
+ dc.SetFont(hyperlinkFont)
+ isLink = True
+ line, hl = ExtractLink(line)
+ dc.SetTextForeground(hyperLinkText)
+ else:
+ # Is a normal line
+ dc.SetFont(messageFont)
+
+ textWidth, textHeight = self._getTextExtent(dc, line)
+
+ messageHeight += textHeight
+
+ xText = (bmpWidth + 2 * self._spacing) if bmpWidth > 0 else self._spacing
+ yText += textHeight / 2 + self._spacing
+ maxWidth = max(xText + textWidth + self._spacing, maxWidth)
+ dc.DrawText(line, xText, yText)
+ if isLink:
+ self._storeHyperLinkInfo(xText, yText, textWidth, textHeight, hl)
+
+ toAdd = 0
+ if bmpHeight > messageHeight:
+ yPos += 2*self._spacing + bmpHeight
+ toAdd = self._spacing
+ else:
+ yPos += messageHeight + 2*self._spacing
+
+ yText = max(messageHeight, bmpHeight+2*self._spacing)
+ if embeddedImage and embeddedImage.IsOk():
+ # Draw the main body image
+ dc.DrawBitmap(embeddedImage, self._spacing, embImgPos + (self._spacing * 2), True)
+
+ footer, footerBmp = classParent.GetFooter(), classParent.GetFooterBitmap()
+ bmpHeight = bmpWidth = textHeight = textWidth = 0
+ bmpXPos = 0
+
+ if footerBmp and footerBmp.IsOk():
+ # Got the footer bitmap
+ bmpHeight, bmpWidth = footerBmp.GetHeight(), footerBmp.GetWidth()
+ bmpXPos = self._spacing
+
+ if footer:
+ # Got the footer text
+ dc.SetFont(footerFont)
+ textWidth, textHeight = dc.GetTextExtent(footer)
+
+ if textHeight or bmpHeight:
+ if drawFooter:
+ # Draw the separator line before the footer
+ dc.SetPen(wx.GREY_PEN)
+ dc.DrawLine(self._spacing, yPos-self._spacing/2+toAdd,
+ width-self._spacing, yPos-self._spacing/2+toAdd)
+ # Draw the footer and footer bitmap (if any)
+ dc.SetTextForeground(normalText)
+ height = max(textHeight, bmpHeight)
+ yPos += toAdd
+ if footer:
+ toAdd = (height - textHeight + self._spacing) / 2
+ dc.DrawText(footer, bmpXPos + bmpWidth + self._spacing, yPos + toAdd)
+ maxWidth = max(bmpXPos + bmpWidth + (self._spacing*2) + textWidth, maxWidth)
+ if footerBmp and footerBmp.IsOk():
+ toAdd = (height - bmpHeight + self._spacing) / 2
+ dc.DrawBitmap(footerBmp, bmpXPos, yPos + toAdd, True)
+ maxWidth = max(footerBmp.GetSize().GetWidth() + bmpXPos, maxWidth)
+
+ maxHeight = yPos + height + toAdd
+ if event is None:
+ return maxWidth, maxHeight
+
+
+ @staticmethod
+ def _getTextExtent(dc, line):
+ textWidth, textHeight = dc.GetTextExtent(line)
+ if textHeight == 0:
+ _, textHeight = dc.GetTextExtent("a")
+ return textWidth, textHeight
+
+ def _storeHyperLinkInfo(self, hTextPos, vTextPos, textWidth, textHeight, linkTarget):
+ # Store the hyperlink rectangle and link
+ self._hyperlinkRect.append(wx.Rect(hTextPos, vTextPos, textWidth, textHeight))
+ self._hyperlinkWeb.append(linkTarget)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`SuperToolTip`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ # This is intentionally empty to reduce flicker
+ pass
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`SuperToolTip`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.Refresh()
+ event.Skip()
+
+
+ def OnMouseMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`SuperToolTip`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ x, y = event.GetPosition()
+ for rect in self._hyperlinkRect:
+ if rect.Contains((x, y)):
+ # We are over one hyperlink...
+ self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+ self._wasOnLink = True
+ return
+
+ if self._wasOnLink:
+ # Restore the normal cursor
+ self._wasOnLink = False
+ self.SetCursor(wx.NullCursor)
+
+
+ def OnDestroy(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN``, ``wx.EVT_LEFT_DCLICK`` and ``wx.EVT_KILL_FOCUS``
+ events for :class:`SuperToolTip`. All these events destroy the :class:`SuperToolTip`,
+ unless the user clicked on one hyperlink.
+
+ :param `event`: a :class:`MouseEvent` or a :class:`FocusEvent` event to be processed.
+ """
+
+ if not isinstance(event, wx.MouseEvent):
+ # We haven't clicked a link
+ if self: # Check if window still exists, Destroy might have been called manually (more than once)
+ self.Destroy()
+ return
+
+ x, y = event.GetPosition()
+ for indx, rect in enumerate(self._hyperlinkRect):
+ if rect.Contains((x, y)):
+ # Run the webbrowser with the clicked link
+ webbrowser.open_new_tab(self._hyperlinkWeb[indx])
+ return
+
+ if self._classParent.GetUseFade():
+ # Fade out...
+ self.StartAlpha(False)
+ else:
+ self.Destroy()
+
+
+ def StartAlpha(self, isShow):
+ """
+ Start the timer which set the alpha channel for :class:`SuperToolTip`.
+
+ :param `isShow`: whether :class:`SuperToolTip` is being shown or deleted.
+
+ :note: This method is available only on Windows and requires Mark Hammond's
+ pywin32 package.
+ """
+
+ if self._alphaTimer.IsRunning():
+ return
+
+ # Calculate starting alpha value and its step
+ self.amount = (isShow and [0] or [255])[0]
+ self.delta = (isShow and [5] or [-5])[0]
+ # Start the timer
+ self._alphaTimer.Start(30)
+
+
+ def SetFont(self, font):
+ """
+ Sets the :class:`SuperToolTip` font globally.
+
+ :param `font`: the font to set.
+ """
+
+ wx.PopupWindow.SetFont(self, font)
+ self._classParent.InitFont()
+ self.Invalidate()
+
+
+ def Invalidate(self):
+ """ Invalidate :class:`SuperToolTip` size and repaint it. """
+
+ if not self._classParent.GetMessage():
+ # No message yet...
+ return
+
+ self.CalculateBestSize()
+ self.Refresh()
+
+
+ def DropShadow(self, drop=True):
+ """
+ Adds a shadow under the window.
+
+ :param `drop`: whether to drop a shadow or not.
+
+ :note: This method is available only on Windows and requires Mark Hammond's
+ pywin32 package.
+ """
+
+ if not _libimported:
+ # No Mark Hammond's win32all extension
+ return
+
+ if wx.Platform != "__WXMSW__":
+ # This works only on Windows XP
+ return
+
+ hwnd = self.GetHandle()
+
+ # Create a rounded rectangle region
+ size = self.GetSize()
+ if drop:
+ if hasattr(win32gui, "CreateRoundRectRgn"):
+ rgn = win32gui.CreateRoundRectRgn(0, 0, size.x, size.y, 9, 9)
+ win32gui.SetWindowRgn(hwnd, rgn, True)
+
+ CS_DROPSHADOW = 0x00020000
+ # Load the user32 library
+ if not hasattr(self, "_winlib"):
+ self._winlib = win32api.LoadLibrary("user32")
+
+ csstyle = win32api.GetWindowLong(hwnd, win32con.GCL_STYLE)
+ if drop:
+ if csstyle & CS_DROPSHADOW:
+ return
+ else:
+ csstyle |= CS_DROPSHADOW #Nothing to be done
+ else:
+ csstyle &= ~CS_DROPSHADOW
+
+ # Drop the shadow underneath the window
+ GCL_STYLE= -26
+ cstyle= win32gui.GetClassLong(hwnd, GCL_STYLE)
+ if drop:
+ if cstyle & CS_DROPSHADOW == 0:
+ win32api.SetClassLong(hwnd, GCL_STYLE, cstyle | CS_DROPSHADOW)
+ else:
+ win32api.SetClassLong(hwnd, GCL_STYLE, cstyle &~ CS_DROPSHADOW)
+
+
+ def AlphaCycle(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`SuperToolTip`.
+
+ :param `event`: a :class:`TimerEvent` event to be processed.
+ """
+
+ # Increase (or decrease) the alpha channel
+ self.amount += self.delta
+
+ if self.amount > 255 or self.amount < 0:
+ # We're done, stop the timer
+ self._alphaTimer.Stop()
+ if self.amount < 0:
+ # Destroy the SuperToolTip, we are fading out
+ self.Destroy()
+ return
+
+ # Make the SuperToolTip more or less transparent
+ self.MakeWindowTransparent(self.amount)
+ if not self.IsShown():
+ self.Show()
+
+
+ def MakeWindowTransparent(self, amount):
+ """
+ Makes the :class:`SuperToolTip` window transparent.
+
+ :param `amount`: the alpha channel value.
+
+ :note: This method is available only on Windows and requires Mark Hammond's
+ pywin32 package.
+ """
+
+ if not _libimported:
+ # No way, only Windows XP with Mark Hammond's win32all
+ return
+
+ # this API call is not in all SDKs, only the newer ones, so
+ # we will runtime bind this
+ if wx.Platform != "__WXMSW__":
+ return
+
+ hwnd = self.GetHandle()
+
+ if not hasattr(self, "_winlib"):
+ self._winlib = win32api.LoadLibrary("user32")
+
+ pSetLayeredWindowAttributes = win32api.GetProcAddress(self._winlib,
+ "SetLayeredWindowAttributes")
+
+ if pSetLayeredWindowAttributes == None:
+ return
+
+ exstyle = win32api.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
+ if 0 == (exstyle & 0x80000):
+ win32api.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, exstyle | 0x80000)
+
+ winxpgui.SetLayeredWindowAttributes(hwnd, 0, amount, 2)
+
+
+ def CalculateBestSize(self):
+ """ Calculates the :class:`SuperToolTip` window best size. """
+
+ maxWidth, maxHeight = self.OnPaint(None)
+ self.SetSize((maxWidth, maxHeight))
+
+
+ def CalculateBestPosition(self, widget):
+ screen = wx.ClientDisplayRect()[2:]
+ left,top = widget.ClientToScreenXY(0,0)
+ right,bottom = widget.ClientToScreenXY(*widget.GetClientRect()[2:])
+ size = self.GetSize()
+ if right+size[0]>screen[0]:
+ xpos = left-size[0]
+ else:
+ xpos = right
+ if bottom+size[1]>screen[1]:
+ ypos = top-size[1]
+ else:
+ ypos = bottom
+ self.SetPosition((xpos,ypos))
+
+
+# Handle Mac and Windows/GTK differences...
+
+if wx.Platform == "__WXMAC__":
+
+ class ToolTipWindow(wx.Frame, ToolTipWindowBase):
+ """ Popup window that works on wxMac. """
+
+ def __init__(self, parent, classParent):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`SuperToolTip` parent widget;
+ :param `classParent`: the :class:`SuperToolTip` class object.
+ """
+
+ wx.Frame.__init__(self, parent, style=wx.NO_BORDER|wx.FRAME_FLOAT_ON_PARENT|wx.FRAME_NO_TASKBAR|wx.POPUP_WINDOW)
+ # Call the base class
+ ToolTipWindowBase.__init__(self, parent, classParent)
+
+else:
+
+ class ToolTipWindow(ToolTipWindowBase, wx.PopupWindow):
+ """
+ A simple :class:`PopupWindow` that holds fancy tooltips.
+ Not available on Mac as :class:`PopupWindow` is not implemented there.
+ """
+
+ def __init__(self, parent, classParent):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`SuperToolTip` parent widget;
+ :param `classParent`: the :class:`SuperToolTip` class object.
+ """
+
+ wx.PopupWindow.__init__(self, parent)
+ # Call the base class
+ ToolTipWindowBase.__init__(self, parent, classParent)
+
+
+class SuperToolTip(object):
+ """
+ The main class for :class:`SuperToolTip`, which holds all the methods
+ and setters/getters available to the user.
+ """
+
+ def __init__(self, message, bodyImage=wx.NullBitmap, header="", headerBmp=wx.NullBitmap,
+ footer="", footerBmp=wx.NullBitmap):
+ """
+ Default class constructor.
+
+ :param `message`: the main message in :class:`SuperToolTip` body;
+ :param `bodyImage`: the image in the :class:`SuperToolTip` body;
+ :param `header`: the header text;
+ :param `headerBmp`: the header bitmap;
+ :param `footer`: the footer text;
+ :param `footerBmp`: the footer bitmap.
+ """
+
+ self._superToolTip = None
+
+ # Set all the initial options
+ self.SetMessage(message)
+ self.SetBodyImage(bodyImage)
+ self.SetHeader(header)
+ self.SetHeaderBitmap(headerBmp)
+ self.SetFooter(footer)
+ self.SetFooterBitmap(footerBmp)
+ self._dropShadow = False
+ self._useFade = False
+
+ self._topLine = False
+ self._bottomLine = False
+
+ self.InitFont()
+
+ # Get the running applications
+ self._runningApp = wx.GetApp()
+ self._runningApp.__superToolTip = True
+
+ # Build a couple of timers...
+ self._startTimer = wx.PyTimer(self.OnStartTimer)
+ self._endTimer = wx.PyTimer(self.OnEndTimer)
+
+ self.SetStartDelay()
+ self.SetEndDelay()
+ self.ApplyStyle("XP Blue")
+
+
+ def SetTarget(self, widget):
+ """
+ Sets the target window for :class:`SuperToolTip`.
+
+ :param `widget`: the widget to which :class:`SuperToolTip` is associated.
+ """
+
+ self._widget = widget
+
+ self._widget.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
+ self._widget.Bind(wx.EVT_LEAVE_WINDOW, self.OnWidgetLeave)
+
+
+ def GetTarget(self):
+ """ Returns the target window for :class:`SuperToolTip`. """
+
+ if not hasattr(self, "_widget"):
+ raise Exception("\nError: the widget target for L{SuperToolTip} has not been set.")
+
+ return self._widget
+
+
+ def SetStartDelay(self, delay=1):
+ """
+ Sets the time delay (in seconds) after which the :class:`SuperToolTip` is created.
+
+ :param `delay`: the delay in seconds.
+ """
+
+ self._startDelayTime = float(delay)
+
+
+ def GetStartDelay(self):
+ """ Returns the tim delay (in seconds) after which the :class:`SuperToolTip` is created."""
+
+ return self._startDelayTime
+
+
+ def SetEndDelay(self, delay=1e6):
+ """
+ Sets the delay time (in seconds) after which the :class:`SuperToolTip` is destroyed.
+
+ :param `delay`: the delay in seconds.
+ """
+
+ self._endDelayTime = float(delay)
+
+
+ def GetEndDelay(self):
+ """ Returns the delay time (in seconds) after which the :class:`SuperToolTip` is destroyed."""
+
+ return self._endDelayTime
+
+
+ def OnWidgetEnter(self, event):
+ """
+ Starts the :class:`SuperToolTip` timer for creation, handles the ``wx.EVT_ENTER_WINDOW`` event.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._superToolTip:
+ # Not yet created
+ return
+
+ if not self._runningApp.__superToolTip:
+ # The running app doesn't want tooltips...
+ return
+
+ if not self._widget.GetTopLevelParent().IsActive():
+ self._startTimer.Stop()
+ return
+
+ if self._startTimer.IsRunning():
+ # We are already running
+ event.Skip()
+ return
+ self._startTimer.Start(self._startDelayTime*1000)
+ event.Skip()
+
+
+ def OnWidgetLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for the target widgets.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._superToolTip:
+ if self.GetUseFade():
+ # Fade out...
+ self._superToolTip.StartAlpha(False)
+ else:
+ self._superToolTip.Destroy()
+
+ self._startTimer.Stop()
+ self._endTimer.Stop()
+
+ event.Skip()
+
+ def GetTipWindow(self):
+ """ Return the TipWindow, will return None if not yet created """
+
+ return self._superToolTip
+
+
+ def OnStartTimer(self):
+ """ The creation time has expired, create the :class:`SuperToolTip`. """
+
+ # target widget might already be destroyed
+ if not self._widget:
+ self._startTimer.Stop()
+ return
+
+ tip = ToolTipWindow(self._widget, self)
+ self._superToolTip = tip
+ self._superToolTip.CalculateBestSize()
+ self._superToolTip.CalculateBestPosition(self._widget)
+ self._superToolTip.DropShadow(self.GetDropShadow())
+
+ if self.GetUseFade():
+ self._superToolTip.StartAlpha(True)
+ else:
+ self._superToolTip.Show()
+
+ self._startTimer.Stop()
+ self._endTimer.Start(self._endDelayTime*1000)
+
+
+ def OnEndTimer(self):
+ """ The show time for :class:`SuperToolTip` has expired, destroy the :class:`SuperToolTip`. """
+
+ if self._superToolTip:
+ if self.GetUseFade():
+ self._superToolTip.StartAlpha(False)
+ else:
+ self._superToolTip.Destroy()
+
+ self._endTimer.Stop()
+
+
+ def DoShowNow(self):
+ """ Create the :class:`SuperToolTip` immediately. """
+
+ if self._superToolTip:
+ # need to destroy it if already exists,
+ # otherwise we might end up with many of them
+ self._superToolTip.Destroy()
+
+ tip = ToolTipWindow(self._widget, self)
+ self._superToolTip = tip
+ self._superToolTip.CalculateBestSize()
+ self._superToolTip.CalculateBestPosition(self._widget)
+ self._superToolTip.DropShadow(self.GetDropShadow())
+
+ # need to stop this, otherwise we get into trouble when leaving the window
+ self._startTimer.Stop()
+
+ if self.GetUseFade():
+ self._superToolTip.StartAlpha(True)
+ else:
+ self._superToolTip.Show()
+
+ self._endTimer.Start(self._endDelayTime*1000)
+
+
+ def DoHideNow(self):
+ """
+ Dismiss the :class:`SuperToolTip` window immediately.
+
+ .. versionadded:: 0.9.6
+ """
+
+ if self._superToolTip:
+ if self.GetUseFade():
+ # Fade out...
+ self._superToolTip.StartAlpha(False)
+ else:
+ self._superToolTip.Destroy()
+
+ self._startTimer.Stop()
+ self._endTimer.Stop()
+
+
+ def Show(self, show=True):
+ """
+ Shows or hides the window.
+
+ You may need to call `Raise` for a top level window if you want to bring it to
+ top, although this is not needed if :meth:`~SuperToolTip.Show` is called immediately after the frame creation.
+
+ :param bool `show`: ``True`` to show the :class:`SuperToolTip` window, ``False`` to hide it.
+
+ :return: ``True`` if the window has been shown or hidden or ``False`` if nothing was done
+ because it already was in the requested state.
+
+ .. note::
+
+ Notice that the default state of newly created top level windows is hidden (to allow
+ you to create their contents without flicker) unlike for all the other, not derived from
+ :class:`TopLevelWindow`, windows that are by default created in the shown state.
+
+
+ .. versionadded:: 0.9.5
+ """
+
+ if show and self._superToolTip is None:
+ self.DoShowNow()
+ return True
+ elif not show and self._superToolTip is not None:
+ self.DoHideNow()
+ return True
+ return False
+
+
+ def Update(self):
+ """
+ Calling this method immediately repaints the invalidated area of the window and all of its
+ children recursively (this normally only happens when the flow of control returns to the
+ event loop).
+
+ :note: Notice that this function doesn't invalidate any area of the window so nothing happens
+ if nothing has been invalidated (i.e. marked as requiring a redraw). Use `Refresh` first if
+ you want to immediately redraw the window unconditionally.
+
+ .. versionadded:: 0.9.5
+ """
+
+ if self._superToolTip:
+ self._superToolTip.Update()
+
+
+ def OnDestroy(self, event):
+ """ Handles the :class:`SuperToolTip` target destruction. """
+
+ if self._superToolTip:
+ # Unbind the events!
+ self._widget.Unbind(wx.EVT_LEAVE_WINDOW)
+ self._widget.Unbind(wx.EVT_ENTER_WINDOW)
+
+ self._superToolTip.Destroy()
+ del self._superToolTip
+ self._superToolTip = None
+
+
+ def SetHeaderBitmap(self, bmp):
+ """
+ Sets the header bitmap for :class:`SuperToolTip`.
+
+ :param `bmp`: the header bitmap, a valid :class:`Bitmap` object.
+ """
+
+ self._headerBmp = bmp
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def GetHeaderBitmap(self):
+ """ Returns the header bitmap. """
+
+ return self._headerBmp
+
+
+ def SetHeader(self, header):
+ """
+ Sets the header text.
+
+ :param `header`: the header text to display.
+ """
+
+ self._header = header
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def GetHeader(self):
+ """ Returns the header text. """
+
+ return self._header
+
+
+ def SetDrawHeaderLine(self, draw):
+ """
+ Sets whether to draw a separator line after the header or not.
+
+ :param `draw`: ``True`` to draw a separator line after the header, ``False``
+ otherwise.
+ """
+
+ self._topLine = draw
+ if self._superToolTip:
+ self._superToolTip.Refresh()
+
+
+ def GetDrawHeaderLine(self):
+ """ Returns whether the separator line after the header is drawn or not. """
+
+ return self._topLine
+
+
+ def SetBodyImage(self, bmp):
+ """
+ Sets the main body bitmap for :class:`SuperToolTip`.
+
+ :param `bmp`: the body bitmap, a valid :class:`Bitmap` object.
+ """
+
+ self._embeddedImage = bmp
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def GetBodyImage(self):
+ """ Returns the main body bitmap used in :class:`SuperToolTip`. """
+
+ return self._embeddedImage
+
+
+ def SetDrawFooterLine(self, draw):
+ """
+ Sets whether to draw a separator line before the footer or not.
+
+ :param `draw`: ``True`` to draw a separator line before the footer, ``False``
+ otherwise.
+ """
+
+ self._bottomLine = draw
+ if self._superToolTip:
+ self._superToolTip.Refresh()
+
+
+ def GetDrawFooterLine(self):
+ """ Returns whether the separator line before the footer is drawn or not. """
+
+ return self._bottomLine
+
+
+ def SetFooterBitmap(self, bmp):
+ """
+ Sets the footer bitmap for :class:`SuperToolTip`.
+
+ :param `bmp`: the footer bitmap, a valid :class:`Bitmap` object.
+ """
+
+ self._footerBmp = bmp
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def GetFooterBitmap(self):
+ """ Returns the footer bitmap. """
+
+ return self._footerBmp
+
+
+ def SetFooter(self, footer):
+ """
+ Sets the footer text.
+
+ :param `footer`: the footer text to display.
+ """
+
+ self._footer = footer
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def GetFooter(self):
+ """ Returns the footer text. """
+
+ return self._footer
+
+
+ def SetMessage(self, message):
+ """
+ Sets the main body message for :class:`SuperToolTip`.
+
+ :param `message`: the message to display in the body.
+ """
+
+ self._message = message
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def GetMessage(self):
+ """ Returns the main body message in :class:`SuperToolTip`. """
+
+ return self._message
+
+
+ def SetTopGradientColour(self, colour):
+ """
+ Sets the top gradient colour for :class:`SuperToolTip`.
+
+ :param `colour`: the colour to use as top colour, a valid :class:`Colour` object.
+ """
+
+ self._topColour = colour
+ if self._superToolTip:
+ self._superToolTip.Refresh()
+
+
+ def SetMiddleGradientColour(self, colour):
+ """
+ Sets the middle gradient colour for :class:`SuperToolTip`.
+
+ :param `colour`: the colour to use as middle colour, a valid :class:`Colour` object.
+ """
+
+ self._middleColour = colour
+ if self._superToolTip:
+ self._superToolTip.Refresh()
+
+
+ def SetBottomGradientColour(self, colour):
+ """
+ Sets the bottom gradient colour for :class:`SuperToolTip`.
+
+ :param `colour`: the colour to use as bottom colour, a valid :class:`Colour` object.
+ """
+
+ self._bottomColour = colour
+ if self._superToolTip:
+ self._superToolTip.Refresh()
+
+
+ def SetTextColour(self, colour):
+ """
+ Sets the text colour for :class:`SuperToolTip`.
+
+ :param `colour`: the colour to use as text colour, a valid :class:`Colour` object.
+ """
+
+ self._textColour = colour
+ if self._superToolTip:
+ self._superToolTip.Refresh()
+
+
+ def GetTopGradientColour(self):
+ """ Returns the top gradient colour. """
+
+ return self._topColour
+
+
+ def GetMiddleGradientColour(self):
+ """ Returns the middle gradient colour. """
+
+ return self._middleColour
+
+
+ def GetBottomGradientColour(self):
+ """ Returns the bottom gradient colour. """
+
+ return self._bottomColour
+
+
+ def GetTextColour(self):
+ """ Returns the text colour. """
+
+ return self._textColour
+
+
+ SetTopGradientColor = SetTopGradientColour
+ SetMiddleGradientColor = SetMiddleGradientColour
+ SetBottomGradientColor = SetBottomGradientColour
+ GetTopGradientColor = GetTopGradientColour
+ GetMiddleGradientColor = GetMiddleGradientColour
+ GetBottomGradientColor = GetBottomGradientColour
+ SetTextColor = SetTextColour
+ GetTextColor = GetTextColour
+
+
+ def InitFont(self):
+ """ Initalizes the fonts for :class:`SuperToolTip`. """
+
+ self._messageFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._headerFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._headerFont.SetWeight(wx.BOLD)
+ self._footerFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._footerFont.SetWeight(wx.BOLD)
+ self._hyperlinkFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._hyperlinkFont.SetWeight(wx.BOLD)
+ self._hyperlinkFont.SetUnderlined(True)
+
+
+ def SetMessageFont(self, font):
+ """
+ Sets the font for the main body message.
+
+ :param `font`: the font to use for the main body message, a valid :class:`Font`
+ object.
+ """
+
+ self._messageFont = font
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def SetHeaderFont(self, font):
+ """
+ Sets the font for the header text.
+
+ :param `font`: the font to use for the header text, a valid :class:`Font`
+ object.
+ """
+
+ self._headerFont = font
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def SetFooterFont(self, font):
+ """
+ Sets the font for the footer text.
+
+ :param `font`: the font to use for the footer text, a valid :class:`Font`
+ object.
+ """
+
+ self._footerFont = font
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def SetHyperlinkFont(self, font):
+ """
+ Sets the font for the hyperlink text.
+
+ :param `font`: the font to use for the hyperlink text, a valid :class:`Font`
+ object.
+ """
+
+ self._hyperlinkFont = font
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def GetMessageFont(self):
+ """ Returns the font used in the main body message. """
+
+ return self._messageFont
+
+
+ def GetHeaderFont(self):
+ """ Returns the font used for the header text. """
+
+ return self._headerFont
+
+
+ def GetFooterFont(self):
+ """ Returns the font used for the footer text. """
+
+ return self._footerFont
+
+
+ def GetHyperlinkFont(self):
+ """ Returns the font used for the hyperlink text. """
+
+ return self._hyperlinkFont
+
+
+ def SetDropShadow(self, drop):
+ """
+ Whether to draw a shadow below :class:`SuperToolTip` or not.
+
+ :param `drop`: ``True`` to drop a shadow below the control, ``False`` otherwise.
+
+ :note: This method is available only on Windows and requires Mark Hammond's
+ pywin32 package.
+ """
+
+ self._dropShadow = drop
+ if self._superToolTip:
+ self._superToolTip.Invalidate()
+
+
+ def GetDropShadow(self):
+ """
+ Returns whether a shadow below :class:`SuperToolTip` is drawn or not.
+
+ :note: This method is available only on Windows and requires Mark Hammond's
+ pywin32 package.
+ """
+
+ return self._dropShadow
+
+
+ def SetUseFade(self, fade):
+ """
+ Whether to use a fade in/fade out effect or not.
+
+ :param `fade`: ``True`` to use a fade in/fade out effect, ``False`` otherwise.
+
+ :note: This method is available only on Windows and requires Mark Hammond's
+ pywin32 package.
+ """
+
+ self._useFade = fade
+
+
+ def GetUseFade(self):
+ """
+ Returns whether a fade in/fade out effect is used or not.
+
+ :note: This method is available only on Windows and requires Mark Hammond's
+ pywin32 package.
+ """
+
+ return self._useFade
+
+
+ def ApplyStyle(self, style):
+ """
+ Applies none of the predefined styles.
+
+ :param `style`: one of the predefined styles available at the
+ beginning of the module.
+ """
+
+ if style not in _colourSchemes:
+ raise Exception("Invalid style '%s' selected"%style)
+
+ top, middle, bottom, text = _colourSchemes[style]
+ self._topColour = top
+ self._middleColour = middle
+ self._bottomColour = bottom
+ self._textColour = text
+
+ if self._superToolTip:
+ self._superToolTip.Refresh()
+
+
+ def EnableTip(self, enable=True):
+ """
+ Globally (application-wide) enables/disables :class:`SuperToolTip`.
+
+ :param `enable`: ``True`` to enable :class:`SuperToolTip` globally, ``False`` otherwise.
+ """
+
+ wx.GetApp().__superToolTip = enable
+ if not enable and self._superToolTip:
+ self.DoHideNow()
+ del self._superToolTip
+ self._superToolTip = None
+
+
+ def IsEnabled(self):
+ """
+ Returns ``True`` when :class:`SuperToolTip` is globally enabled, ``False`` otherwise.
+
+ .. versionadded:: 0.9.6
+ """
+
+ return wx.GetApp().__superToolTip
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/thumbnailctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/thumbnailctrl.py
new file mode 100644
index 0000000..8ee76e2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/thumbnailctrl.py
@@ -0,0 +1,2599 @@
+# --------------------------------------------------------------------------- #
+# THUMBNAILCTRL Control wxPython IMPLEMENTATION
+# Python Code By:
+#
+# Andrea Gavana And Peter Damoc, @ 12 Dec 2005
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# TODO List/Caveats
+#
+# 1. Thumbnail Creation/Display May Be Somewhat Improved From The Execution
+# Speed Point Of View;
+#
+# 2. The Implementation For wx.HORIZONTAL Style Is Still To Be Written;
+#
+# 3. I Have No Idea On How To Implement Thumbnails For Audio, Video And Other Files.
+#
+# 4. Other Ideas?
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+
+"""
+:class:`ThumbnailCtrl` is a widget that can be used to display a series of images in
+a "thumbnail" format.
+
+
+Description
+===========
+
+:class:`ThumbnailCtrl` is a widget that can be used to display a series of images in
+a "thumbnail" format; it mimics, for example, the windows explorer behavior
+when you select the "view thumbnails" option.
+Basically, by specifying a folder that contains some image files, the files
+in the folder are displayed as miniature versions of the actual images in
+a :class:`ScrolledWindow`.
+
+The code is partly based on `wxVillaLib`, a wxWidgets implementation of this
+control. However, :class:`ThumbnailCtrl` wouldn't have been so fast and complete
+without the suggestions and hints from Peter Damoc. So, if he accepts the
+mention, this control is his as much as mine.
+
+
+Usage
+=====
+
+Usage example::
+
+ import os
+
+ import wx
+ import wx.lib.agw.thumbnailctrl as TC
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "ThumbnailCtrl Demo")
+
+ panel = wx.Panel(self)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ thumbnail = TC.ThumbnailCtrl(panel, imagehandler=TC.NativeImageHandler)
+ sizer.Add(thumbnail, 1, wx.EXPAND | wx.ALL, 10)
+
+ thumbnail.ShowDir(os.getcwd())
+ panel.SetSizer(sizer)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Methods and Settings
+====================
+
+With :class:`ThumbnailCtrl` you can:
+
+- Create different thumbnail outlines (none, images only, full, etc...);
+- Highlight thumbnails on mouse hovering;
+- Show/hide file names below thumbnails;
+- Change thumbnail caption font;
+- Zoom in/out thumbnails (done via ``Ctrl`` key + mouse wheel or with ``+`` and ``-`` chars,
+ with zoom factor value customizable);
+- Rotate thumbnails with these specifications:
+
+ a) ``d`` key rotates 90 degrees clockwise;
+ b) ``s`` key rotates 90 degrees counter-clockwise;
+ c) ``a`` key rotates 180 degrees.
+
+- Delete files/thumbnails (via the ``del`` key);
+- Drag and drop thumbnails from :class:`ThumbnailCtrl` to whatever application you want;
+- Use local (when at least one thumbnail is selected) or global (no need for
+ thumbnail selection) popup menus;
+- Show/hide a :class:`ComboBox` at the top of :class:`ThumbnailCtrl`: this combobox contains
+ working directory information and it has history entries;
+- possibility to show tooltips on thumbnails, which display file information
+ (like file name, size, last modification date and thumbnail size).
+
+
+:note: Using highlight thumbnails on mouse hovering may be slow on slower
+ computers.
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+================================== ==================================================
+Event Name Description
+================================== ==================================================
+``EVT_THUMBNAILS_CAPTION_CHANGED`` The thumbnail caption has been changed. Not used at present.
+``EVT_THUMBNAILS_DCLICK`` The user has double-clicked on a thumbnail.
+``EVT_THUMBNAILS_POINTED`` The mouse cursor is hovering over a thumbnail.
+``EVT_THUMBNAILS_SEL_CHANGED`` The user has changed the selected thumbnail.
+``EVT_THUMBNAILS_THUMB_CHANGED`` The thumbnail of an image has changed. Used internally.
+================================== ==================================================
+
+
+License And Version
+===================
+
+:class:`ThumbnailCtrl` is distributed under the wxPython license.
+
+Latest revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.9
+
+"""
+
+
+#----------------------------------------------------------------------
+# Beginning Of ThumbnailCtrl wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+import os
+import time
+import cStringIO
+import zlib
+
+import thread
+from math import pi
+
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+#----------------------------------------------------------------------
+# Get Default Icon/Data
+#----------------------------------------------------------------------
+
+def GetMondrianData():
+ """ Returns a default image placeholder as a decompressed stream of characters. """
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
+\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00qID\
+ATX\x85\xed\xd6;\n\x800\x10E\xd1{\xc5\x8d\xb9r\x97\x16\x0b\xad$\x8a\x82:\x16\
+o\xda\x84pB2\x1f\x81Fa\x8c\x9c\x08\x04Z{\xcf\xa72\xbcv\xfa\xc5\x08 \x80r\x80\
+\xfc\xa2\x0e\x1c\xe4\xba\xfaX\x1d\xd0\xde]S\x07\x02\xd8>\xe1wa-`\x9fQ\xe9\
+\x86\x01\x04\x10\x00\\(Dk\x1b-\x04\xdc\x1d\x07\x14\x98;\x0bS\x7f\x7f\xf9\x13\
+\x04\x10@\xf9X\xbe\x00\xc9 \x14K\xc1<={\x00\x00\x00\x00IEND\xaeB`\x82'
+
+
+def GetMondrianBitmap():
+ """ Returns a default image placeholder as a :class:`Bitmap`. """
+
+ return wx.BitmapFromImage(GetMondrianImage())
+
+
+def GetMondrianImage():
+ """ Returns a default image placeholder as a :class:`Image`. """
+
+ stream = cStringIO.StringIO(GetMondrianData())
+ return wx.ImageFromStream(stream)
+
+
+#----------------------------------------------------------------------
+file_broken = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAAK/INwWK6QAADU9J"
+ "REFUeJzNWn1QE2cefja7yRI+lAKiAgKCVIqegUYMFMsM4kfvzk7nmFrnvHGcOT3bq3P/OJ1p"
+ "b+zYf+r0HGxt6VVFqpYqWq9TW23RVnp6R7FXiq0UPAGhyFeQSCQJISHZ7Mf9gZuGkE02IeA9"
+ "M5k3u/vuu+/z/H7v7/297y4BPzh//vxfSJIsIgjC5a/eTIPn+UnHgiDIqisIAsUwTNfmzZtf"
+ "A8D7qk/5e3B0dPS6wsLCp/09MFTIbdO7ntR9vs5HRESgvr6+E0AlAD2AKZX8CsDzvEKtVsvq"
+ "aKjw7LggCO7jcJQqlQoMw6gBpAIYRAgCECGxCgDPTsohEopI4n+e5xXww1MRHkry4d1Zf9fk"
+ "uv90MOsCeMKfGN51pO6ZrmizKsBsWt976EjhoQ+BYMQItpSDWRNAjptPZ4xLCfl/PQTCaX2p"
+ "+wNhVgSYbet7tumdRXpj1ofAbFhfqn1fmHEBHpb1AYAgAudxMy4AQRB+LReuSB/MGsETMyqA"
+ "2WyG1WqVZQl/CDUZeuge0NvbKwwODk7bC7zryYFI/qF6QGNj42BnZ6dZ6rocQtNNhQNhxgQw"
+ "Go24fPnyDy0tLTcFQfDpBZ7/w2198RcIMyZAW1vb+KVLlxoGBwfr7927B4Vi8qO8CfnqbCjW"
+ "D4Y8MEMCCIKA77777me73d7a1tb25dDQkNXzmud/giDgdDrBsqzkuA1l7CuVSgCA0+n0y3FG"
+ "BBgYGMCVK1eub926dRFN04aBgYH/el73JKRUKjE4OIi+vj5QFDWtaVG0fGRkJHiex7lz5xyn"
+ "T59uBMBI9TWsAoidaW1tNTc1Nd1cv379zuzs7F91dHT8x+l0TooDnuju7h779ttvjdOdLlUq"
+ "FaKjo9HV1YX9+/d379q16+QXX3xxFsAAMHU7DAgggNw1tQiCIOByuXDt2rWbK1asUOfk5KxM"
+ "SUlZW19f39LX18eTJDmpbbG8cePGndra2mtDQ0NQKpUhJUPR0dHgeR6ffvqpbdeuXV+9/vrr"
+ "R4eGhs4A+ArA3ZAECAXd3d24dOnSD2VlZavy8vKQmppaUFdXN2gwGO561yVJEmazGR0dHV3n"
+ "z5//+NatW0MU5XebcgooikJMTAy6urqwb9++zp07d1ZfvXq1GsAn8+bNa6qsrEyGxJY4EGBT"
+ "lCAIhVR0ZhgGTqcTTqcTDocDDocDgiDgm2++0Y+MjNxbuXLl7wmCQFpaWtbcuXMje3p6fly9"
+ "enWyeL8gCCBJEj09PUJLS0s7z/PXWlpavigoKNhBURRYlnU/S6qMjIwEwzD47LPPbIcOHWq4"
+ "cuXKPwF8D+DHF154QV1cXFxpsVjiAGwGYIUPL/ArgNFoNNbV1dmtVqvdarW6LBaLY2xszOFw"
+ "OBiLxWKz2WxOs9lsHx0ddZhMJpvZbB7v7u7+effu3elZWVmJAJCUlBS1bt26nNbW1kaj0fj0"
+ "I4884iYHAHfu3Lnf2dnZDWC4oaHhH08++eRWrVZLe9bxJk9RFNRqNTo6OvDhhx92Hj16tG5k"
+ "ZKQBwHUAneXl5cVarfaQVqtddurUqesAUgC0BysAsWfPngOjo6ONY2NjUQzDOACMA7ADcGAi"
+ "sjoBuB6U4jFTWlp6Kj4+HjzPIzExEbm5uSuPHz9+csuWLfaEhIRIl8sFgiDA8zxu3rz585Yt"
+ "W3SpqanX9u7d+93GjRuv5eXlrRGvT+oQQUCtVsPhcODcuXO2w4cPi1ZvAnADgP3EiRN7NBrN"
+ "ntzcXDXHcXA6nREAJF9u+BNA6OnpuQ1gGAD5gCjrUXIPFOUflAIA7siRI8Xp6ekaYOI1lVKp"
+ "RGZmpqatre2QXq/v1mg0y4EJKxoMBrS1tQ2UlJQ8abPZjAD23Lhx46Pi4uI1aWlp7mEl1qdp"
+ "Grdu3UJNTU1nVVVV3cjIyDUAPwJof+WVVzJ0Ol1NQUHBbxMTEyHOOoEQKOKMP/jJxoIFC/6Q"
+ "mZlJidYTBAHp6emp2dnZCV1dXY0MwywnCAIkSUKv1zu7u7uNu3fvTh8aGtoE4Pj7779/ec2a"
+ "NZ0ZGRlZwC9Wt9vt+Pzzz22VlZUNV69eFa3+EwDTkSNHynJyct5ZtWpVikKhgMPhgEKhkJx2"
+ "gxFgSv1t27ZRUVFRFMuyZGZmZmJcXNwcpVIZT9N0tMvlWpiSklKmVConBbGkpCRq3bp1Kxsb"
+ "G69v3Lhxe3p6OgRBQHt7u2Hx4sVRycnJ9Ny5czO3bdv2VHV19XvNzc2frF69+pXY2FgoFAop"
+ "q3ds2rQp6plnnnkzLy9v99KlS8EwDDiOC2r5LSnAiRMnIubNm/dHkiSzaZqOIUkygabpGIqi"
+ "4iiKmkuSZDRJkiqVSkWRJKmkaZqMiIhAZGQkOI5zk+c4DnFxccjOztZWVVV9+eKLLw5nZGTM"
+ "YxgGzc3Ndx577LGF8fHxiI2NhU6n+111dfWZixcvnispKfmzTqebe+HCBW+rtwK4/8Ybb+Rp"
+ "NJojBQUFq2JiYuB0OgH8kgqLpdiXoAVobW2NfvbZZ/cWFhbOly3ngwf6yvczMzNzWJZV9Pb2"
+ "/lRUVLR2cHAQt2/fvrt9+3YtSZJQKBRYtmxZYXFx8ar6+vqrTU1NF7/++mtdZWXll0ajsQET"
+ "Qa4TE3HmBY1Gsz8/P3+Oy+Vyj3dP8nK9QFKA/v5+Cn7GfzBZmiAISE5OTiwqKsq4fft2k91u"
+ "X9vf3283GAyWtLS0ZNFTsrOzI0pKSsrq6+v//c477/xNr9evwMRr7ZsAhl966aUFOp3uzfz8"
+ "/C2LFi3C+Pj4JMLeAsjJYiUFYFk2oIRyReA4DikpKSgqKlpZW1t7saysjOvo6NAvXbo0NjEx"
+ "MZLneXAchzlz5kCj0TwVGxu7RK/Xt2Mihx8DwBw4cGBDbm5uRWFh4aNKpRJ2u30S8VCsD8hY"
+ "CwRzXqouz/OIiopCVlaWtrm5+X57e/tAS0uLPicnJzEhIcE9TnmeR05OTvJzzz33a0xMtyNa"
+ "rVY4fvz4a6WlpRdKSkoeFZfPYpSXIi93SyzYWWASMTmlZ/2MjIys+Pj4mI6Ojoa+vj5h/fr1"
+ "xaKrikIlJyfj8ccfLwNw7NVXX43TarV/LyoqWhsXF4fx8XF3TPFF2Pv/tPIAu93ul7g/+BJD"
+ "EAQsXLgwqrS0NLexsfE8RVHLFi1atNn7PpVKhdzc3OUvv/zyvg0bNvwmPz8/WeyPt8sHEkLO"
+ "anZaQyCYDUmO47BgwQIsX758VW1t7bc6nU5ISkpSeuYLHMeBYRhkZWWpd+zY8afCwsJklmXB"
+ "MMwUlw9EXjwOhIDL4dHRUQwMDMBms4Hn+YCuJSUKz/NQqVRYsmTJcgDzlixZsnzOnDlu1xfj"
+ "AMdxoGkaqampsNvtEATBvZ8olzxBEO57whIDxsbGMD4+DrVajaioKERGRoKiKMmdXn9IT09P"
+ "Li4ufiIxMVEHACzLThGW47gp54IhHwz8CiCSEt3P4XDA6XTCYrGApmnQNA2VSuUWwzvyescA"
+ "l8uF+fPnK59//vm/zp8/f6FoebF98VlSBOWS99WXkATwfrhnw+JmiEKhgEKhAEmSEDM6KTEI"
+ "gkBcXBwRExOTkpCQAJfLNSPkg4EsD/Algncs4Hl+ktv6+onjOS0tDTRNT1q4hJN8MCKE5AFS"
+ "nQx0DQAYhkFqaqpbrJkmH5YPJMJFXqFQTBmTM0E+LB5gt9slXTpU8t4E5JKXSnsDkfV+HReU"
+ "AJ6YLnlf1pNLXhAEmM1msCw7KSZ598/7PEEQ4DgOLMv6VSHQt8JhIS/HG/y5vV6vh9FohFqt"
+ "ducN3r8pxCgKJpMJvb29o/hlzzI4AUSEk7yUtfyJwTAMMjMzsXjxYr/zuuf7wbt376K8vLz/"
+ "7NmzlzCxpA5NgHCTl1vHFzkAPjNE774aDAaUl5f3V1RU1HAc9y9MbKr4RMA8QIr4TJP3LEU3"
+ "5zjOnTtItWUwGLB//36R/CVMbKXZQhbAV2dnk7zYD3G1KI537/oURbndvqKi4hTHcV9iYvd4"
+ "zB/HkFPh6ZL3JurvHIBJXuB9XfzG4MCBA/3vvvtujVzysgTwR2I65KVmAl/3iUtmlmUnDQGR"
+ "/P3793H48GH9A/Ki2wckH1AAzxjgS4yZJO/dD899A7EORVEYGRlBVVWV8b333vs4GMvLEsAT"
+ "oQ4Ff+Q92/YniGcMEAUQ5/ljx44Nv/XWWx9ZrdaLAJqDIR9QAO/9gHCTlxsERRFEAZRKJUwm"
+ "E6qrq4cPHjx4xmq11mLi1bglGPIBBfBF8mGQFyHmACaTCSdPnhx+++23z4yOjtZi4pWZKVjy"
+ "sgTwFiIU8v7GuVzyIsxmM06fPj188ODBjx5Y/nsAkl+jBoLsPECEryDl7ziQMHLJkyQJi8WC"
+ "mpqa4YqKCtHtmzAN8oCM9wJKpRIRERGyyAQi6CvwyeokRcFsNqOurm64oqLijMVimZbbT2pb"
+ "6gJN04TNZlNZLBYwDOOeEgNtMsqpF+y1sbEx1NbWDn/wwQdhJQ8AkmZYsWJFVEZGxtZ79+49"
+ "wbIsDa/VlBQJqS0of6QD3UMQBHp7e++YTKYrCIPbe8KfHyoALACwGIAqXA8MEQImPnO7A2Ak"
+ "nA3/D+/OyD/Ur3BPAAAAAElFTkSuQmCC")
+
+
+def getDataSH():
+ """ Return the first part of the shadow dropped behind thumbnails. """
+
+ return zlib.decompress(
+'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2_A\x98\x83\rHvl\
+\xdc\x9c\n\xa4X\x8a\x9d<C8\x80\xa0\x86#\xa5\x83\x81\x81y\x96\xa7\x8bcH\xc5\
+\x9c\xb7\xd7\xd7\xf6\x85D2\xb4^\xbc\x1b\xd0\xd0p\xa6\x85\x9d\xa1\xf1\xc0\xc7\
+\x7f\xef\x8d\x98\xf89_:p]\xaew\x0c\xe9\x16[\xbc\x8bSt\xdf\x9aT\xad\xef\xcb\
+\x8e\x98\xc5\xbf\xb3\x94\x9ePT\xf8\xff\xf7\xfbm\xf5\xdb\xfeZ<\x16{\xf01o[l\
+\xee\xee\xbd7\xbe\x95\xdd\xde\x9d+\xbf\xfdo\xf9\xb9\xd0\x03\x8be\xb7\xc7\xe6\
+Y\xcb\xbd\x8b\xdfs\xe3[\xd6\xed\xe5\x9b}\x99\xe6=:\xbd\xed\xfc\xedu|\xfcq\
+\xfb\xec/K<\xf8\xfec\xd7\xdb\xdb\x87W\xec\xcf\xfd]\xb0\xcc\xf0\xc0\xe5=\xf7^\
+\x1e\xf9\xfb\xe6\xe6\xce\xe9\x0c\xfb\xa7\xafPt\xbb"\xa0\x9c\xd5!hz\xa4C*\xc9\
+\x85\xd7pQ\x9bD\xa0s\xcf\xa8\xf0\xa8\xf0\x00\x0b\x9fyX\x7fo\xef\xdf\xc7\xda\
+\r\xcbw\xd4\xfcx\xe0\xcdk\xd8\x9e[~{\xdd\xf6\xbfw\xbe\xfd\xddS\xdc\xe0\xfec_\
+\xf0\xfe\xeb\xb7\xdf\xf1\xdd\xce\xdb&\xbb\xbdv\xe7\xff\xc3\xaf\x8dy\x99\xe5\
+\x9e?\xf7\xfb+\xb7\xfdnLN\xf5\xc6\xb7g\xfd\xca_\x9a\x7f?\x7f\xe0\xfe\xe3\xaa\
+\xe5\x0b\xf4\xb7\xcb\xea\x97\xed\n\xb7\xbf\xff\xadh\xf9\xe3\x1d\xd5f\x7fb\
+\xdf\x95Y\x15\xc6\xe7\xee\xfe\xcbz7Y\xbd\xde[\xf3y\x1f0\xd72x\xba\xfa\xb9\
+\xacsJh\x02\x00\xc4i\x8dN' )
+
+
+def getDataBL():
+ """ Return the second part of the shadow dropped behind thumbnails. """
+
+ return zlib.decompress(
+"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\xac \xcc\xc1\
+\x06${\xf3\xd5\x9e\x02)\x96b'\xcf\x10\x0e \xa8\xe1H\xe9\x00\xf2\xed=]\x1cC8f\
+\xea\x9e\xde\xcb\xd9` \xc2\xf0P\xdf~\xc9y\xaeu\x0f\xfe1\xdf\xcc\x14\x1482A\
+\xe9\xfd\x83\x1d\xaf\x84\xac\xf8\xe6\\\x8c3\xfc\x98\xf8\xa0\xb1\xa9K\xec\x9f\
+\xc4\xd1\xb4GG{\xb5\x15\x8f_|t\x8a[a\x1fWzG\xa9\xc4,\xa0Q\x0c\x9e\xae~.\xeb\
+\x9c\x12\x9a\x00\x7f1,7" )
+
+
+def getDataTR():
+ """ Return the third part of the shadow dropped behind thumbnails. """
+
+ return zlib.decompress(
+'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\xac \xcc\xc1\
+\x06${\xf3\xd5\x9e\x02)\x96b\'\xcf\x10\x0e \xa8\xe1H\xe9\x00\xf2m=]\x1cC8f\
+\xe6\x9e\xd9\xc8\xd9` \xc2p\x91\xbd\xaei\xeeL\x85\xdcUo\xf6\xf7\xd6\xb2\x88\
+\x0bp\x9a\x89i\x16=-\x94\xe16\x93\xb9!\xb8y\xcd\t\x0f\x89\n\xe6\xb7\xfcV~6\
+\x8dFo\xf5\xee\xc8\x1fOaw\xc9\x88\x0c\x16\x05\x1a\xc4\xe0\xe9\xea\xe7\xb2\
+\xce)\xa1\t\x00"\xf9$\x83' )
+
+
+def getShadow():
+ """ Creates a shadow behind every thumbnail. """
+
+ sh_tr = wx.ImageFromStream(cStringIO.StringIO(getDataTR())).ConvertToBitmap()
+ sh_bl = wx.ImageFromStream(cStringIO.StringIO(getDataBL())).ConvertToBitmap()
+ sh_sh = wx.ImageFromStream(cStringIO.StringIO(getDataSH())).Rescale(500, 500, wx.IMAGE_QUALITY_HIGH)
+ return (sh_tr, sh_bl, sh_sh.ConvertToBitmap())
+
+
+#-----------------------------------------------------------------------------
+# PATH & FILE FILLING (OS INDEPENDENT)
+#-----------------------------------------------------------------------------
+
+def opj(path):
+ """
+ Convert paths to the platform-specific separator.
+
+ :param `path`: the path to convert.
+ """
+
+ strs = apply(os.path.join, tuple(path.split('/')))
+ # HACK: on Linux, a leading / gets lost...
+ if path.startswith('/'):
+ strs = '/' + strs
+
+ return strs
+
+#-----------------------------------------------------------------------------
+
+# Different Outline On Thumb Selection:
+# THUMB_OUTLINE_NONE: No Outline Drawn On Selection
+# THUMB_OUTLINE_FULL: Full Outline Drawn On Selection
+# THUMB_OUTLINE_RECT: Only Maximum Image Rect Outlined On Selection
+# THUMB_OUTLINE_IMAGE: Only Image Rect Outlined On Selection
+
+THUMB_OUTLINE_NONE = 0
+""" No outline drawn on selection. """
+THUMB_OUTLINE_FULL = 1
+""" Full outline drawn on selection. """
+THUMB_OUTLINE_RECT = 2
+""" Only the maximum image rectangle outlined on selection. """
+THUMB_OUTLINE_IMAGE = 4
+""" Only the image rectangle outlined on selection. """
+
+# Options For Filtering Files
+THUMB_FILTER_IMAGES = 1
+""" Only load images. We dont know yet how to create thumbnails for other file types... """
+
+# THUMB_FILTER_VIDEOS = 2 Don't Know How To Create Thumbnails For Videos!!!
+
+# ThumbnailCtrl Orientation: Not Fully Implemented Till Now
+THUMB_HORIZONTAL = wx.HORIZONTAL
+""" The :class:`ThumbnailCtrl` will be horizontal. """
+THUMB_VERTICAL = wx.VERTICAL
+""" The :class:`ThumbnailCtrl` will be vertical. """
+
+# Image File Name Extensions: Am I Missing Some Extensions Here?
+extensions = [".jpeg", ".jpg", ".bmp", ".png", ".ico", ".tiff", ".ani", ".cur", ".gif",
+ ".iff", ".icon", ".pcx", ".tif", ".xpm", ".xbm", ".mpeg", ".mpg", ".mov"]
+
+# ThumbnailCtrl Events:
+# wxEVT_THUMBNAILS_SEL_CHANGED: Event Fired When You Change Thumb Selection
+# wxEVT_THUMBNAILS_POINTED: Event Fired When You Point A Thumb
+# wxEVT_THUMBNAILS_DCLICK: Event Fired When You Double-Click A Thumb
+# wxEVT_THUMBNAILS_CAPTION_CHANGED: Not Used At Present
+# wxEVT_THUMBNAILS_THUMB_CHANGED: Used Internally
+
+wxEVT_THUMBNAILS_SEL_CHANGED = wx.NewEventType()
+wxEVT_THUMBNAILS_POINTED = wx.NewEventType()
+wxEVT_THUMBNAILS_DCLICK = wx.NewEventType()
+wxEVT_THUMBNAILS_CAPTION_CHANGED = wx.NewEventType()
+wxEVT_THUMBNAILS_THUMB_CHANGED = wx.NewEventType()
+
+#-----------------------------------#
+# ThumbnailCtrlEvent
+#-----------------------------------#
+
+EVT_THUMBNAILS_SEL_CHANGED = wx.PyEventBinder(wxEVT_THUMBNAILS_SEL_CHANGED, 1)
+""" The user has changed the selected thumbnail. """
+EVT_THUMBNAILS_POINTED = wx.PyEventBinder(wxEVT_THUMBNAILS_POINTED, 1)
+""" The mouse cursor is hovering over a thumbnail. """
+EVT_THUMBNAILS_DCLICK = wx.PyEventBinder(wxEVT_THUMBNAILS_DCLICK, 1)
+""" The user has double-clicked on a thumbnail. """
+EVT_THUMBNAILS_CAPTION_CHANGED = wx.PyEventBinder(wxEVT_THUMBNAILS_CAPTION_CHANGED, 1)
+""" The thumbnail caption has been changed. Not used at present. """
+EVT_THUMBNAILS_THUMB_CHANGED = wx.PyEventBinder(wxEVT_THUMBNAILS_THUMB_CHANGED, 1)
+""" The thumbnail of an image has changed. Used internally"""
+
+TN_USE_PIL = 0
+""" If set to ``True`` or to ``1``, :class:`ThumbnailCtrl` will use PIL to load the images (much faster). """
+
+TIME_FMT = '%d %b %Y, %H:%M:%S'
+""" Time format string for the :class:`Thumb` representation on screen. """
+
+
+def CmpThumb(first, second):
+ """
+ Compares two thumbnails in terms of file names and ids.
+
+ :param `first`: an instance of :class:`Thumb`;
+ :param `second`: another instance of :class:`Thumb`.
+ """
+
+ if first.GetFileName() < second.GetFileName():
+ return -1
+ elif first.GetFullFileName() == second.GetFullFileName():
+ return first.GetId() - second.GetId()
+
+ return 1
+
+
+def SortFiles(items, sorteditems, filenames):
+ """
+ Sort files in alphabetical order.
+
+ :param `sorteditems`: a list of :class:`Thumb` objects;
+ :param `filenames`: a list of image filenames.
+ """
+
+ newfiles = []
+ for item in sorteditems:
+ newfiles.append(filenames[items.index(item)])
+
+ return newfiles
+
+# ---------------------------------------------------------------------------- #
+# Class PILImageHandler, handles loading and highlighting images with PIL
+# ---------------------------------------------------------------------------- #
+
+class PILImageHandler(object):
+ """
+ This image handler loads and manipulates the thumbnails with the help
+ of PIL (the Python Imaging Library).
+ """
+
+ def __init__(self):
+ """
+ Default class constructor.
+
+ :note: If PIL is not installed, this will raise an exception. PIL
+ can be downloaded from http://www.pythonware.com/products/pil/ .
+ """
+
+ try:
+
+ import PIL.Image as Image
+ import PIL.ImageEnhance as ImageEnhance
+
+ except ImportError:
+
+ errstr = ("\nThumbnailCtrl *requires* PIL (Python Imaging Library).\n"
+ "You can get it at:\n\n"
+ "http://www.pythonware.com/products/pil/\n\n"
+ "ThumbnailCtrl can not continue. Exiting...\n")
+
+ raise Exception(errstr)
+
+
+ def LoadThumbnail(self, filename, thumbnailsize):
+ """
+ Load the file and rescale it.
+
+ :param `filename`: a file containing an image;
+ :param `thumbnailsize`: the desired size of the thumbnail.
+ """
+
+ import PIL.Image as Image
+
+ pil = Image.open(filename)
+ originalsize = pil.size
+
+ pil.thumbnail(thumbnailsize)
+ img = wx.EmptyImage(pil.size[0], pil.size[1])
+
+ img.SetData(pil.convert("RGB").tostring())
+
+ alpha = False
+ if "A" in pil.getbands():
+ img.SetAlphaData(pil.convert("RGBA").tostring()[3::4])
+ alpha = True
+
+ return img, originalsize, alpha
+
+
+ def HighlightImage(self, img, factor):
+ """
+ Adjust overall image brightness to highlight.
+
+ :param `img`: an instance of :class:`Image`;
+ :param `factor`: unused in :class:`PILImageHandler`.
+ """
+
+ import PIL.Image as Image
+ import PIL.ImageEnhance as ImageEnhance
+
+ pil = Image.new('RGB', (img.GetWidth(), img.GetHeight()))
+ pil.fromstring(img.GetData())
+ enh = ImageEnhance.Brightness(pil)
+ enh = enh.enhance(1.5)
+ img.SetData(enh.convert('RGB').tostring())
+ return img
+
+
+# ---------------------------------------------------------------------------- #
+# Class NativeImageHandler, handles loading and highlighting images with wx
+# ---------------------------------------------------------------------------- #
+
+class NativeImageHandler(object):
+ """
+ This image handler loads and manipulates the thumbnails with the help of
+ wxPython's own image related functions.
+ """
+
+ def LoadThumbnail(self, filename, thumbnailsize):
+ """
+ Load the file and rescale it.
+
+ :param `filename`: a file containing an image;
+ :param `thumbnailsize`: the desired size of the thumbnail.
+ """
+
+ img = wx.Image(filename)
+
+ # Don't stop when a corrupt file is to be loaded, show Mondrian instead
+ try:
+ originalsize = (img.GetWidth(), img.GetHeight())
+ except:
+ img = file_broken.GetImage()
+ originalsize = (img.GetWidth(), img.GetHeight())
+
+ img.Rescale(min(thumbnailsize[0], originalsize[0]), min(thumbnailsize[1], originalsize[1]), wx.IMAGE_QUALITY_NORMAL)
+ alpha = img.HasAlpha()
+
+ return img, originalsize, alpha
+
+
+ def HighlightImage(self, img, factor):
+ """
+ Adjust overall image brightness to highlight.
+
+ :param `img`: an instance of :class:`Image`;
+ :param `factor`: a floating point number representing the highlight factor.
+ """
+
+ return img.AdjustChannels(factor, factor, factor, factor)
+
+
+
+# ---------------------------------------------------------------------------- #
+# Class ThumbnailEvent
+# ---------------------------------------------------------------------------- #
+
+class ThumbnailEvent(wx.PyCommandEvent):
+ """
+ This class is used to send events when a thumbnail is hovered, selected,
+ double-clicked or when its caption has been changed.
+ """
+ def __init__(self, evtType, evtId=-1):
+ """
+ Default class constructor.
+
+ :param `evtType`: the event type;
+ :param `evtId`: the event identifier.
+ """
+
+ wx.PyCommandEvent.__init__(self, evtType, evtId)
+ self._eventType = evtType
+
+
+# ---------------------------------------------------------------------------- #
+# Class Thumb
+# Auxiliary Class, To Handle Single Thumb Information For Every Thumb.
+# Used Internally.
+# ---------------------------------------------------------------------------- #
+
+class Thumb(object):
+ """
+ This is an auxiliary class, to handle single thumbnail information for every thumb.
+
+ Used internally.
+ """
+
+ def __init__(self, parent, folder, filename, caption="", size=0, lastmod=0):
+ """
+ Default class constructor.
+
+ :param `parent`: the main :class:`ThumbnailCtrl` window;
+ :param `folder`: the directory containing the images;
+ :param `filename`: a file containing an image;
+ :param `caption`: the thumbnail caption string;
+ :param `size`: the file size;
+ :param `lastmod`: the file last modification time.
+ """
+
+ self._filename = filename
+ self.SetCaption(caption)
+ self._id = 0
+ self._dir = folder
+ self._filesize = size
+ self._lastmod = lastmod
+ self._parent = parent
+ self._captionbreaks = []
+ self._bitmap = wx.EmptyBitmap(1,1)
+ self._image = wx.EmptyImage(1,1)
+ self._rotation = 0
+ self._alpha = None
+
+
+ def SetCaption(self, caption=""):
+ """
+ Sets the thumbnail caption.
+
+ :param `caption`: the thumbnail caption string.
+ """
+
+ self._caption = caption
+ self._captionbreaks = []
+
+
+ def GetImage(self):
+ """ Returns the thumbnail image. """
+
+ return self._image
+
+
+ def SetImage(self, image):
+ """
+ Sets the thumbnail image.
+
+ :param `image`: a :class:`Image` object.
+ """
+
+ self._image = image
+
+
+ def SetBitmap(self, bmp):
+ """
+ Sets the thumbnail bitmap.
+
+ :param `bmp`: a :class:`Bitmap` object.
+ """
+
+ self._bitmap = bmp
+
+
+ def GetFileName(self):
+ """ Returns the file name associated with this thumbnail. """
+
+ return self._filename
+
+
+ def SetFileName(self, filename):
+ """
+ Sets the file name associated with this thumbnail.
+
+ :param `filename`: the file containing the image.
+ """
+
+ self._filename = filename
+ self._bitmap = wx.EmptyBitmap(1, 1)
+
+
+ def GetId(self):
+ """ Returns the thumbnail identifier. """
+
+ return self._id
+
+
+ def SetId(self, id=-1):
+ """
+ Sets the thumbnail identifier.
+
+ :param `id`: an integer specifying the thumbnail identifier.
+ """
+
+ self._id = id
+
+
+ def SetRotatedImage(self, image):
+ """
+ Sets the image as rotated (fast).
+
+ :param `image`: the rotated image, an instance of :class:`Image`.
+ """
+
+ self._rotatedimage = image
+
+
+ def GetRotatedImage(self):
+ """ Returns a rotated image. """
+
+ return self._rotatedimage
+
+
+ def GetBitmap(self, width, height):
+ """
+ Returns the associated bitmap.
+
+ :param `width`: the associated bitmap width;
+ :param `height`: the associated bitmap height.
+ """
+
+ if self.GetRotation() % (2*pi) < 1e-6:
+ if not self._bitmap.Ok():
+ if not hasattr(self, "_threadedimage"):
+ img = GetMondrianImage()
+ else:
+ img = self._threadedimage
+
+ else:
+ if not hasattr(self, "_threadedimage"):
+ img = GetMondrianImage()
+ else:
+ img = self._threadedimage
+
+ else:
+
+ img = self.GetRotatedImage()
+
+ if hasattr(self, "_originalsize"):
+ imgwidth, imgheight = self._originalsize
+ else:
+ imgwidth, imgheight = (img.GetWidth(), img.GetHeight())
+
+ if width < imgwidth or height < imgheight:
+ scale = float(width)/imgwidth
+
+ if scale > float(height)/imgheight:
+ scale = float(height)/imgheight
+
+ newW, newH = int(imgwidth*scale), int(imgheight*scale)
+ if newW < 1:
+ newW = 1
+ if newH < 1:
+ newH = 1
+
+ img = img.Scale(newW, newH)
+
+ bmp = img.ConvertToBitmap()
+
+ self._image = img
+
+ return bmp
+
+
+ def GetOriginalImage(self):
+ """ Returns the bitmap associated to a thumbnail, as a file name. """
+
+ original = opj((self._dir + "/" + self._filename))
+
+ return original
+
+
+ def GetFullFileName(self):
+ """ Returns the full filename of the thumbnail. """
+
+ return self._dir + "/" + self._filename
+
+
+ def GetCaption(self, line):
+ """
+ Returns the caption associated to a thumbnail.
+
+ :param `line`: the caption line we wish to retrieve (useful for multilines
+ caption strings).
+ """
+
+ if line + 1 >= len(self._captionbreaks):
+ return ""
+
+ strs = self._caption
+
+ return strs
+
+
+ def GetFileSize(self):
+ """ Returns the file size associated to a thumbnail. """
+
+ return self._filesize
+
+
+ def GetCreationDate(self):
+ """ Returns the file last modification date associated to a thumbnail. """
+
+ return self._lastmod
+
+
+ def GetOriginalSize(self):
+ """ Returns a tuple containing the original image width and height, in pixels. """
+
+ if hasattr(self, "_threadedimage"):
+ img = self._threadedimage
+ else:
+ img = GetMondrianImage()
+
+ if hasattr(self, "_originalsize"):
+ imgwidth, imgheight = self._originalsize
+ else:
+ imgwidth, imgheight = (img.GetWidth(), img.GetHeight())
+
+ return imgwidth, imgheight
+
+
+ def GetCaptionLinesCount(self, width):
+ """
+ Returns the number of lines for the caption.
+
+ :param `width`: the maximum width, in pixels, available for the caption text.
+ """
+
+ self.BreakCaption(width)
+ return len(self._captionbreaks) - 1
+
+
+ def BreakCaption(self, width):
+ """
+ Breaks the caption in several lines of text (if needed).
+
+ :param `width`: the maximum width, in pixels, available for the caption text.
+ """
+
+ if len(self._captionbreaks) > 0 or width < 16:
+ return
+
+ self._captionbreaks.append(0)
+
+ if len(self._caption) == 0:
+ return
+
+ pos = width/16
+ beg = 0
+ end = 0
+
+ dc = wx.MemoryDC()
+ bmp = wx.EmptyBitmap(10,10)
+ dc.SelectObject(bmp)
+
+ while 1:
+
+ if pos >= len(self._caption):
+
+ self._captionbreaks.append(len(self._caption))
+ break
+
+ sw, sh = dc.GetTextExtent(self._caption[beg:pos-beg])
+
+ if sw > width:
+
+ if end > 0:
+
+ self._captionbreaks.append(end)
+ beg = end
+
+ else:
+
+ self._captionbreaks.append(pos)
+ beg = pos
+
+ pos = beg + width/16
+ end = 0
+
+ if pos < len(self._caption) and self._caption[pos] in [" ", "-", ",", ".", "_"]:
+ end = pos + 1
+
+ pos = pos + 1
+
+
+ dc.SelectObject(wx.NullBitmap)
+
+
+ def SetRotation(self, angle=0):
+ """
+ Sets the thumbnail rotation.
+
+ :param `angle`: the thumbnail rotation, in radians.
+ """
+
+ self._rotation = angle
+
+
+ def GetRotation(self):
+ """ Returns the thumbnail rotation, in radians. """
+
+ return self._rotation
+
+
+# ---------------------------------------------------------------------------- #
+# Class ThumbnailCtrl
+# Auxiliary Class, All Useful Methods Are Defined On ScrolledThumbnail Class.
+# ---------------------------------------------------------------------------- #
+
+class ThumbnailCtrl(wx.Panel):
+ """
+ :class:`ThumbnailCtrl` is a widget that can be used to display a series of images in
+ a "thumbnail" format.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, thumboutline=THUMB_OUTLINE_IMAGE,
+ thumbfilter=THUMB_FILTER_IMAGES, imagehandler=PILImageHandler):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `thumboutline`: outline style for :class:`ThumbnailCtrl`, which may be:
+
+ =========================== ======= ==================================
+ Outline Flag Value Description
+ =========================== ======= ==================================
+ ``THUMB_OUTLINE_NONE`` 0 No outline is drawn on selection
+ ``THUMB_OUTLINE_FULL`` 1 Full outline (image+caption) is drawn on selection
+ ``THUMB_OUTLINE_RECT`` 2 Only thumbnail bounding rectangle is drawn on selection (default)
+ ``THUMB_OUTLINE_IMAGE`` 4 Only image bounding rectangle is drawn.
+ =========================== ======= ==================================
+
+ :param `thumbfilter`: filter for image/video/audio files. Actually only
+ ``THUMB_FILTER_IMAGES`` is implemented;
+ :param `imagehandler`: can be :class:`PILImageHandler` if PIL is installed (faster), or
+ :class:`NativeImageHandler` which only uses wxPython image methods.
+ """
+
+ wx.Panel.__init__(self, parent, id, pos, size)
+
+ self._sizer = wx.BoxSizer(wx.VERTICAL)
+
+ self._combo = wx.ComboBox(self, -1, style=wx.CB_DROPDOWN | wx.CB_READONLY)
+ self._scrolled = ScrolledThumbnail(self, -1, thumboutline=thumboutline,
+ thumbfilter=thumbfilter, imagehandler = imagehandler)
+
+ subsizer = wx.BoxSizer(wx.HORIZONTAL)
+ subsizer.Add((3, 0), 0)
+ subsizer.Add(self._combo, 0, wx.EXPAND | wx.TOP, 3)
+ subsizer.Add((3, 0), 0)
+ self._sizer.Add(subsizer, 0, wx.EXPAND | wx.ALL, 3)
+ self._sizer.Add(self._scrolled, 1, wx.EXPAND)
+
+ self.SetSizer(self._sizer)
+
+ self._sizer.Show(0, False)
+ self._sizer.Layout()
+
+ methods = ["GetSelectedItem", "GetPointed", "GetHighlightPointed", "SetHighlightPointed",
+ "SetThumbOutline", "GetThumbOutline", "GetPointedItem", "GetItem",
+ "GetItemCount", "GetThumbWidth", "GetThumbHeight", "GetThumbBorder",
+ "ShowFileNames", "SetPopupMenu", "GetPopupMenu", "SetGlobalPopupMenu",
+ "GetGlobalPopupMenu", "SetSelectionColour", "GetSelectionColour",
+ "EnableDragging", "SetThumbSize", "GetThumbSize", "ShowThumbs", "ShowDir",
+ "GetShowDir", "SetSelection", "GetSelection", "SetZoomFactor",
+ "GetZoomFactor", "SetCaptionFont", "GetCaptionFont", "GetItemIndex",
+ "InsertItem", "RemoveItemAt", "IsSelected", "Rotate", "ZoomIn", "ZoomOut",
+ "EnableToolTips", "GetThumbInfo", "GetOriginalImage", "SetDropShadow", "GetDropShadow"]
+
+ for method in methods:
+ setattr(self, method, getattr(self._scrolled, method))
+
+ self._combochoices = []
+ self._showcombo = False
+ self._subsizer = subsizer
+
+ self._combo.Bind(wx.EVT_COMBOBOX, self.OnComboBox)
+
+
+ def ShowComboBox(self, show=True):
+ """
+ Shows/Hide the top folder :class:`ComboBox`.
+
+ :param `show`: ``True`` to show the combobox, ``False`` otherwise.
+ """
+
+ if show:
+ self._showcombo = True
+ self._sizer.Show(0, True)
+ self._sizer.Layout()
+ else:
+ self._showcombo = False
+ self._sizer.Show(0, False)
+ self._sizer.Layout()
+
+ self._scrolled.Refresh()
+
+
+ def GetShowComboBox(self):
+ """ Returns whether the folder combobox is shown. """
+
+ return self._showcombo
+
+
+ def OnComboBox(self, event):
+ """
+ Handles the ``wx.EVT_COMBOBOX`` for the folder combobox.
+
+ :param `event`: a :class:`CommandEvent` event to be processed.
+ """
+
+ dirs = self._combo.GetValue()
+
+ if os.path.isdir(opj(dirs)):
+ self._scrolled.ShowDir(opj(dirs))
+
+ event.Skip()
+
+
+ def RecreateComboBox(self, newdir):
+ """
+ Recreates the folder combobox every time a new directory is explored.
+
+ :param `newdir`: the new folder to be explored.
+ """
+
+ newdir = newdir.strip()
+
+ if opj(newdir) in self._combochoices:
+ return
+
+ self.Freeze()
+
+ self._sizer.Detach(0)
+ self._subsizer.Detach(1)
+ self._subsizer.Destroy()
+ self._combo.Destroy()
+
+ subsizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ self._combochoices.insert(0, opj(newdir))
+
+ self._combo = wx.ComboBox(self, -1, value=newdir, choices=self._combochoices,
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
+
+ subsizer.Add((3, 0), 0)
+ subsizer.Add(self._combo, 1, wx.EXPAND | wx.TOP, 3)
+ subsizer.Add((3, 0), 0)
+ self._sizer.Insert(0, subsizer, 0, wx.EXPAND | wx.ALL, 3)
+
+ self._subsizer = subsizer
+
+ self._subsizer.Layout()
+
+ if not self.GetShowComboBox():
+ self._sizer.Show(0, False)
+
+ self._sizer.Layout()
+
+ self._combo.Bind(wx.EVT_COMBOBOX, self.OnComboBox)
+
+ self.Thaw()
+
+
+# ---------------------------------------------------------------------------- #
+# Class ScrolledThumbnail
+# This Is The Main Class Implementation
+# ---------------------------------------------------------------------------- #
+
+class ScrolledThumbnail(wx.ScrolledWindow):
+ """ This is the main class implementation of :class:`ThumbnailCtrl`. """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, thumboutline=THUMB_OUTLINE_IMAGE,
+ thumbfilter=THUMB_FILTER_IMAGES, imagehandler=PILImageHandler):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `thumboutline`: outline style for :class:`ScrolledThumbnail`, which may be:
+
+ =========================== ======= ==================================
+ Outline Flag Value Description
+ =========================== ======= ==================================
+ ``THUMB_OUTLINE_NONE`` 0 No outline is drawn on selection
+ ``THUMB_OUTLINE_FULL`` 1 Full outline (image+caption) is drawn on selection
+ ``THUMB_OUTLINE_RECT`` 2 Only thumbnail bounding rectangle is drawn on selection (default)
+ ``THUMB_OUTLINE_IMAGE`` 4 Only image bounding rectangle is drawn.
+ =========================== ======= ==================================
+
+ :param `thumbfilter`: filter for image/video/audio files. Actually only
+ ``THUMB_FILTER_IMAGES`` is implemented;
+ :param `imagehandler`: can be :class:`PILImageHandler` if PIL is installed (faster), or
+ :class:`NativeImageHandler` which only uses wxPython image methods.
+ """
+
+ wx.ScrolledWindow.__init__(self, parent, id, pos, size)
+
+ self.SetThumbSize(96, 80)
+ self._tOutline = thumboutline
+ self._filter = thumbfilter
+ self._imageHandler = imagehandler()
+ self._selected = -1
+ self._pointed = -1
+ self._labelcontrol = None
+ self._pmenu = None
+ self._gpmenu = None
+ self._dragging = False
+ self._checktext = False
+ self._orient = THUMB_VERTICAL
+ self._dropShadow = True
+
+ self._tCaptionHeight = []
+ self._selectedarray = []
+ self._tTextHeight = 16
+ self._tCaptionBorder = 8
+ self._tOutlineNotSelected = True
+ self._mouseeventhandled = False
+ self._highlight = False
+ self._zoomfactor = 1.4
+ self.SetCaptionFont()
+ self._items = []
+
+ self._enabletooltip = False
+
+ self._parent = parent
+
+ self._selectioncolour = "#009EFF"
+ self.grayPen = wx.Pen("#A2A2D2", 1, wx.SHORT_DASH)
+ self.grayPen.SetJoin(wx.JOIN_MITER)
+ self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_LISTBOX))
+
+ t, b, s = getShadow()
+ self.shadow = wx.MemoryDC()
+ self.shadow.SelectObject(s)
+
+ self.ShowFileNames(True)
+
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnMouseDClick)
+ self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseDown)
+ self.Bind(wx.EVT_RIGHT_UP, self.OnMouseUp)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(EVT_THUMBNAILS_THUMB_CHANGED, self.OnThumbChanged)
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
+
+ self.Bind(wx.EVT_SIZE, self.OnResize)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def GetSelectedItem(self, index):
+ """
+ Returns the selected thumbnail.
+
+ :param `index`: the thumbnail index (i.e., the selection).
+ """
+
+ return self.GetItem(self.GetSelection(index))
+
+
+ def GetPointed(self):
+ """ Returns the pointed thumbnail index. """
+
+ return self._pointed
+
+
+ def GetHighlightPointed(self):
+ """
+ Returns whether the thumbnail pointed should be highlighted or not.
+
+ :note: Please be aware that this functionality may be slow on slower computers.
+ """
+
+ return self._highlight
+
+
+ def SetHighlightPointed(self, highlight=True):
+ """
+ Sets whether the thumbnail pointed should be highlighted or not.
+
+ :param `highlight`: ``True`` to enable highlight-on-point with the mouse,
+ ``False`` otherwise.
+
+ :note: Please be aware that this functionality may be slow on slower computers.
+ """
+
+ self._highlight = highlight
+
+
+ def SetThumbOutline(self, outline):
+ """
+ Sets the thumbnail outline style on selection.
+
+ :param `outline`: the outline to use on selection. This can be one of the following
+ bits:
+
+ =========================== ======= ==================================
+ Outline Flag Value Description
+ =========================== ======= ==================================
+ ``THUMB_OUTLINE_NONE`` 0 No outline is drawn on selection
+ ``THUMB_OUTLINE_FULL`` 1 Full outline (image+caption) is drawn on selection
+ ``THUMB_OUTLINE_RECT`` 2 Only thumbnail bounding rectangle is drawn on selection (default)
+ ``THUMB_OUTLINE_IMAGE`` 4 Only image bounding rectangle is drawn.
+ =========================== ======= ==================================
+
+ """
+
+ if outline not in [THUMB_OUTLINE_NONE, THUMB_OUTLINE_FULL, THUMB_OUTLINE_RECT,
+ THUMB_OUTLINE_IMAGE]:
+ return
+
+ self._tOutline = outline
+
+
+ def GetThumbOutline(self):
+ """
+ Returns the thumbnail outline style on selection.
+
+ :see: :meth:`~ScrolledThumbnail.SetThumbOutline` for a list of possible return values.
+ """
+
+ return self._tOutline
+
+
+ def SetDropShadow(self, drop):
+ """
+ Sets whether to drop a shadow behind thumbnails or not.
+
+ :param `drop`: ``True`` to drop a shadow behind each thumbnail, ``False`` otheriwise.
+ """
+
+ self._dropShadow = drop
+ self.Refresh()
+
+
+ def GetDropShadow(self):
+ """
+ Returns whether to drop a shadow behind thumbnails or not.
+ """
+
+ return self._dropShadow
+
+
+ def GetPointedItem(self):
+ """ Returns the pointed thumbnail. """
+
+ return self.GetItem(self._pointed)
+
+
+ def GetItem(self, index):
+ """
+ Returns the item at position `index`.
+
+ :param `index`: the thumbnail index position.
+ """
+
+ return index >= 0 and (index < len(self._items) and [self._items[index]] or [None])[0]
+
+
+ def GetItemCount(self):
+ """ Returns the number of thumbnails. """
+
+ return len(self._items)
+
+
+ def SortItems(self):
+ """ Sorts the items accordingly to the :func:`~CmpThumb` function. """
+
+ self._items.sort(CmpThumb)
+
+
+ def GetThumbWidth(self):
+ """ Returns the thumbnail width. """
+
+ return self._tWidth
+
+
+ def GetThumbHeight(self):
+ """ Returns the thumbnail height. """
+
+ return self._tHeight
+
+
+ def GetThumbBorder(self):
+ """ Returns the thumbnail border. """
+
+ return self._tBorder
+
+
+ def GetCaption(self):
+ """ Returns the thumbnail caption. """
+
+ return self._caption
+
+
+ def SetLabelControl(self, statictext):
+ """
+ Sets the thumbnail label as :class:`StaticText`.
+
+ :param `statictext`: an instance of :class:`StaticText`.
+ """
+
+ self._labelcontrol = statictext
+
+
+ def ShowFileNames(self, show=True):
+ """
+ Sets whether the user wants to show file names under the thumbnails or not.
+
+ :param `show`: ``True`` to show file names under the thumbnails, ``False`` otherwise.
+ """
+
+ self._showfilenames = show
+ self.Refresh()
+
+
+ def SetOrientation(self, orient=THUMB_VERTICAL):
+ """
+ Set the :class:`ThumbnailCtrl` orientation (partially implemented).
+
+ :param `orient`: one of ``THUMB_VERTICAL``, ``THUMB_HORIZONTAL``.
+
+ .. todo:: Correctly implement the ``THUMB_HORIZONTAL`` orientation.
+ """
+
+ self._orient = orient
+
+
+ def SetPopupMenu(self, menu):
+ """
+ Sets the thumbnails popup menu when at least one thumbnail is selected.
+
+ :param `menu`: an instance of :class:`Menu`.
+ """
+
+ self._pmenu = menu
+
+
+ def GetPopupMenu(self):
+ """ Returns the thumbnails popup menu when at least one thumbnail is selected. """
+
+ return self._pmenu
+
+
+ def SetGlobalPopupMenu(self, gpmenu):
+ """
+ Sets the global thumbnails popup menu (no need of thumbnail selection).
+
+ :param `gpmenu`: an instance of :class:`Menu`.
+ """
+
+ self._gpmenu = gpmenu
+
+
+ def GetGlobalPopupMenu(self):
+ """ Returns the global thumbnailss popup menu (no need of thumbnail selection). """
+
+ return self._gpmenu
+
+
+ def GetSelectionColour(self):
+ """ Returns the colour used to indicate a selected thumbnail. """
+
+ return self._selectioncolour
+
+
+ def SetSelectionColour(self, colour=None):
+ """
+ Sets the colour used to indicate a selected thumbnail.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, it
+ will be taken from the system settings.
+ """
+
+ if colour is None:
+ colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+
+ self._selectioncolour = colour
+
+
+ def EnableDragging(self, enable=True):
+ """
+ Enables/disables thumbnails drag and drop.
+
+ :param `enable`: ``True`` to enable drag and drop, ``False`` to disable it.
+ """
+
+ self._dragging = enable
+
+
+ def EnableToolTips(self, enable=True):
+ """
+ Globally enables/disables thumbnail file information.
+
+ :param `enable`: ``True`` to enable thumbnail file information, ``False`` to disable it.
+ """
+
+ self._enabletooltip = enable
+
+ if not enable and hasattr(self, "_tipwindow"):
+ self._tipwindow.Enable(False)
+
+
+ def GetThumbInfo(self, thumb=-1):
+ """
+ Returns the thumbnail information.
+
+ :param `thumb`: the index of the thumbnail for which we are collecting information.
+ """
+
+ thumbinfo = None
+
+ if thumb >= 0:
+ thumbinfo = "Name: " + self._items[thumb].GetFileName() + "\n" \
+ "Size: " + self._items[thumb].GetFileSize() + "\n" \
+ "Modified: " + self._items[thumb].GetCreationDate() + "\n" \
+ "Dimensions: " + str(self._items[thumb].GetOriginalSize()) + "\n" \
+ "Thumb: " + str(self.GetThumbSize()[0:2])
+
+ return thumbinfo
+
+
+ def SetThumbSize(self, width, height, border=6):
+ """
+ Sets the thumbnail size as width, height and border.
+
+ :param `width`: the desired thumbnail width;
+ :param `height`: the desired thumbnail height;
+ :param `border`: the spacing between thumbnails.
+ """
+
+ if width > 350 or height > 280:
+ return
+
+ self._tWidth = width
+ self._tHeight = height
+ self._tBorder = border
+ self.SetScrollRate((self._tWidth + self._tBorder)/4,
+ (self._tHeight + self._tBorder)/4)
+ self.SetSizeHints(self._tWidth + self._tBorder*2 + 16,
+ self._tHeight + self._tBorder*2 + 8)
+
+
+ def GetThumbSize(self):
+ """ Returns the thumbnail size as width, height and border. """
+
+ return self._tWidth, self._tHeight, self._tBorder
+
+
+ def Clear(self):
+ """ Clears :class:`ThumbnailCtrl`. """
+
+ self._items = []
+ self._selected = -1
+ self._selectedarray = []
+ self.UpdateProp()
+ self.Refresh()
+
+
+ def ListDirectory(self, directory, fileExtList):
+ """
+ Returns list of file info objects for files of particular extensions.
+
+ :param `directory`: the folder containing the images to thumbnail;
+ :param `fileExtList`: a Python list of file extensions to consider.
+ """
+
+ fileList = [os.path.normcase(f) for f in os.listdir(directory)]
+ fileList = [f for f in fileList \
+ if os.path.splitext(f)[1] in fileExtList]
+
+ return fileList
+
+
+ def ThreadImage(self, filenames):
+ """
+ Threaded method to load images. Used internally.
+
+ :param `filenames`: a Python list of file names containing images.
+ """
+
+ count = 0
+
+ while count < len(filenames):
+
+ if not self._isrunning:
+ self._isrunning = False
+ thread.exit()
+ return
+
+ self.LoadImages(filenames[count], count)
+ if count < 4:
+ self.Refresh()
+ elif count%4 == 0:
+ self.Refresh()
+
+ count = count + 1
+
+ self._isrunning = False
+ thread.exit()
+
+
+ def LoadImages(self, newfile, imagecount):
+ """
+ Threaded method to load images. Used internally.
+
+ :param `newfile`: a file name containing an image to thumbnail;
+ :param `imagecount`: the number of images loaded until now.
+ """
+
+ if not self._isrunning:
+ thread.exit()
+ return
+
+ img, originalsize, alpha = self._imageHandler.LoadThumbnail(newfile, (300, 240))
+ try:
+ self._items[imagecount]._threadedimage = img
+ self._items[imagecount]._originalsize = originalsize
+ self._items[imagecount]._bitmap = img
+ self._items[imagecount]._alpha = alpha
+ except:
+ return
+
+
+ def ShowThumbs(self, thumbs, caption):
+ """
+ Shows all the thumbnails.
+
+ :param `thumbs`: should be a sequence with instances of :class:`Thumb`;
+ :param `caption`: the caption text for the current selected thumbnail.
+ """
+
+ self.SetCaption(caption)
+
+ self._isrunning = False
+
+ # update items
+ self._items = thumbs
+ myfiles = [thumb.GetFullFileName() for thumb in thumbs]
+
+ items = self._items[:]
+ self._items.sort(CmpThumb)
+
+ newfiles = SortFiles(items, self._items, myfiles)
+ self._isrunning = True
+
+ thread.start_new_thread(self.ThreadImage, (newfiles,))
+ wx.MilliSleep(20)
+
+ self._selectedarray = []
+ self.UpdateProp()
+ self.Refresh()
+
+
+ def ShowDir(self, folder, filter=THUMB_FILTER_IMAGES):
+ """
+ Shows thumbnails for a particular folder.
+
+ :param `folder`: a directory containing the images to thumbnail;
+ :param `filter`: filter images, video audio (currently implemented only for
+ images).
+
+ .. todo:: Find a way to create thumbnails of video, audio and other formats.
+ """
+
+ self._dir = folder
+ if filter >= 0:
+ self._filter = filter
+
+ self._parent.RecreateComboBox(folder)
+
+ # update items
+ thumbs = []
+
+ filenames = self.ListDirectory(self._dir, extensions)
+
+ for files in filenames:
+
+ caption = (self._showfilenames and [files] or [""])[0]
+ fullfile = opj(self._dir + "/" + files)
+ if not os.path.isfile(fullfile):
+ continue
+
+ stats = os.stat(fullfile)
+ size = stats[6]
+
+ if size < 1000:
+ size = str(size) + " bytes"
+ elif size < 1000000:
+ size = str(int(round(size/1000.0))) + " Kb"
+ else:
+ size = str(round(size/1000000.0, 2)) + " Mb"
+
+ lastmod = time.strftime(TIME_FMT, time.localtime(stats[8]))
+
+ if self._filter & THUMB_FILTER_IMAGES:
+ thumbs.append(Thumb(self, folder, files, caption, size, lastmod))
+
+ return self.ShowThumbs(thumbs, caption=self._dir)
+
+
+ def GetShowDir(self):
+ """ Returns the working directory with images. """
+
+ return self._dir
+
+
+ def SetSelection(self, value=-1):
+ """
+ Sets thumbnail selection.
+
+ :param `value`: the thumbnail index to select.
+ """
+
+ self._selected = value
+
+ if value != -1:
+ self._selectedarray = [value]
+ eventOut = ThumbnailEvent(wxEVT_THUMBNAILS_SEL_CHANGED, self.GetId())
+ self.GetEventHandler().ProcessEvent(eventOut)
+ self.ScrollToSelected()
+ self.Refresh()
+
+
+ def SetZoomFactor(self, zoom=1.4):
+ """
+ Sets the zoom factor.
+
+ :param `zoom`: a floating point number representing the zoom factor. Must be
+ greater than or equal to 1.0.
+ """
+
+ if zoom <= 1.0:
+ raise Exception("\nERROR: Zoom Factor Must Be Greater Than 1.0")
+
+ self._zoomfactor = zoom
+
+
+ def GetZoomFactor(self):
+ """ Returns the zoom factor. """
+
+ return self._zoomfactor
+
+
+ def IsAudioVideo(self, fname):
+ """
+ Returns ``True`` if a file contains either audio or video data.
+ Currently unused as :class:`ThumbnailCtrl` recognizes only image files.
+
+ :param `fname`: a file name.
+
+ .. todo:: Find a way to create thumbnails of video, audio and other formats.
+ """
+
+ return os.path.splitext(fname)[1].lower() in \
+ [".mpg", ".mpeg", ".vob"]
+
+
+ def IsVideo(self, fname):
+ """
+ Returns ``True`` if a file contains video data.
+ Currently unused as :class:`ThumbnailCtrl` recognizes only image files.
+
+ :param `fname`: a file name.
+
+ .. todo:: Find a way to create thumbnails of video, audio and other formats.
+ """
+
+ return os.path.splitext(fname)[1].lower() in \
+ [".m1v", ".m2v"]
+
+
+ def IsAudio(self, fname):
+ """
+ Returns ``True`` if a file contains audio data.
+ Currently unused as :class:`ThumbnailCtrl` recognizes only image files.
+
+ :param `fname`: a file name.
+
+ .. todo:: Find a way to create thumbnails of video, audio and other formats.
+ """
+
+ return os.path.splitext(fname)[1].lower() in \
+ [".mpa", ".mp2", ".mp3", ".ac3", ".dts", ".pcm"]
+
+
+ def UpdateItems(self):
+ """ Updates thumbnail items. """
+
+ selected = self._selectedarray
+ selectedfname = []
+ selecteditemid = []
+
+ for ii in xrange(len(self._selectedarray)):
+ selectedfname.append(self.GetSelectedItem(ii).GetFileName())
+ selecteditemid.append(self.GetSelectedItem(ii).GetId())
+
+ self.UpdateShow()
+
+ if len(selected) > 0:
+ self._selectedarray = []
+ for ii in xrange(len(self._items)):
+ for jj in xrange(len(selected)):
+ if self._items[ii].GetFileName() == selectedfname[jj] and \
+ self._items[ii].GetId() == selecteditemid[jj]:
+
+ self._selectedarray.append(ii)
+ if len(self._selectedarray) == 1:
+ self.ScrollToSelected()
+
+ if len(self._selectedarray) > 0:
+ self.Refresh()
+ eventOut = ThumbnailEvent(wxEVT_THUMBNAILS_SEL_CHANGED, self.GetId())
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+
+ def SetCaption(self, caption=""):
+ """
+ Sets the current caption string.
+
+ :param `caption`: the current caption string.
+ """
+
+ self._caption = caption
+ if self._labelcontrol:
+
+ maxWidth = self._labelcontrol.GetSize().GetWidth()/8
+ if len(caption) > maxWidth:
+ caption = "..." + caption[len(caption) + 3 - maxWidth]
+
+ self._labelcontrol.SetLabel(caption)
+
+ eventOut = ThumbnailEvent(wxEVT_THUMBNAILS_CAPTION_CHANGED, self.GetId())
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+
+ def SetCaptionFont(self, font=None):
+ """
+ Sets the font for all the thumbnail captions.
+
+ :param `font`: a valid :class:`Font` object. If defaulted to ``None``, a standard
+ font will be generated.
+ """
+
+ if font is None:
+ font = wx.Font(8, wx.SWISS, wx.NORMAL, wx.BOLD, False)
+
+ self._captionfont = font
+
+
+ def GetCaptionFont(self):
+ """ Returns the font for all the thumbnail captions. """
+
+ return self._captionfont
+
+
+ def UpdateShow(self):
+ """ Updates thumbnail items. """
+
+ self.ShowThumbs(self._items)
+
+
+ def GetCaptionHeight(self, begRow, count=1):
+ """
+ Returns the height for the file name caption.
+
+ :param `begRow`: the caption line at which we start measuring the height;
+ :param `count`: the number of lines to measure.
+ """
+
+ capHeight = 0
+ for ii in xrange(begRow, begRow + count):
+ if ii < len(self._tCaptionHeight):
+ capHeight = capHeight + self._tCaptionHeight[ii]
+
+ return capHeight*self._tTextHeight
+
+
+ def GetItemIndex(self, x, y):
+ """
+ Returns the thumbnail index at position (x, y).
+
+ :param `x`: the mouse `x` position;
+ :param `y`: the mouse `y` position.
+ """
+
+ col = (x - self._tBorder)/(self._tWidth + self._tBorder)
+
+ if col >= self._cols:
+ col = self._cols - 1
+
+ row = -1
+ y = y - self._tBorder
+
+ while y > 0:
+
+ row = row + 1
+ y = y - (self._tHeight + self._tBorder + self.GetCaptionHeight(row))
+
+ if row < 0:
+ row = 0
+
+ index = row*self._cols + col
+
+ if index >= len(self._items):
+ index = -1
+
+ return index
+
+
+ def UpdateProp(self, checkSize=True):
+ """
+ Updates :class:`ThumbnailCtrl` and its visible thumbnails.
+
+ :param `checkSize`: ``True`` to update the items visibility if the window
+ size has changed.
+ """
+
+ width = self.GetClientSize().GetWidth()
+ self._cols = (width - self._tBorder)/(self._tWidth + self._tBorder)
+
+ if self._cols <= 0:
+ self._cols = 1
+
+ tmpvar = (len(self._items)%self._cols and [1] or [0])[0]
+ self._rows = len(self._items)/self._cols + tmpvar
+
+ self._tCaptionHeight = []
+
+ for row in xrange(self._rows):
+
+ capHeight = 0
+
+ for col in xrange(self._cols):
+
+ ii = row*self._cols + col
+
+ if len(self._items) > ii and \
+ self._items[ii].GetCaptionLinesCount(self._tWidth - self._tCaptionBorder) > capHeight:
+
+ capHeight = self._items[ii].GetCaptionLinesCount(self._tWidth - self._tCaptionBorder)
+
+ self._tCaptionHeight.append(capHeight)
+
+ self.SetVirtualSize((self._cols*(self._tWidth + self._tBorder) + self._tBorder,
+ self._rows*(self._tHeight + self._tBorder) + \
+ self.GetCaptionHeight(0, self._rows) + self._tBorder))
+
+ self.SetSizeHints(self._tWidth + 2*self._tBorder + 16,
+ self._tHeight + 2*self._tBorder + 8 + \
+ (self._rows and [self.GetCaptionHeight(0)] or [0])[0])
+
+ if checkSize and width != self.GetClientSize().GetWidth():
+ self.UpdateProp(False)
+
+
+ def InsertItem(self, thumb, pos):
+ """
+ Inserts a thumbnail in the specified position.
+
+ :param `pos`: the index at which we wish to insert the new thumbnail.
+ """
+
+ if pos < 0 or pos > len(self._items):
+ self._items.append(thumb)
+ else:
+ self._items.insert(pos, thumb)
+
+ self.UpdateProp()
+
+
+ def RemoveItemAt(self, pos):
+ """
+ Removes a thumbnail at the specified position.
+
+ :param `pos`: the index at which we wish to remove the thumbnail.
+ """
+
+ del self._items[pos]
+
+ self.UpdateProp()
+
+
+ def GetPaintRect(self):
+ """ Returns the paint bounding rect for the :meth:`~ScrolledThumbnail.OnPaint` method. """
+
+ size = self.GetClientSize()
+ paintRect = wx.Rect(0, 0, size.GetWidth(), size.GetHeight())
+ paintRect.x, paintRect.y = self.GetViewStart()
+ xu, yu = self.GetScrollPixelsPerUnit()
+ paintRect.x = paintRect.x*xu
+ paintRect.y = paintRect.y*yu
+
+ return paintRect
+
+
+ def IsSelected(self, indx):
+ """
+ Returns whether a thumbnail is selected or not.
+
+ :param `indx`: the index of the thumbnail to check for selection.
+ """
+
+ return self._selectedarray.count(indx) != 0
+
+
+ def GetSelection(self, selIndex=-1):
+ """
+ Returns the selected thumbnail.
+
+ :param `selIndex`: if not equal to -1, the index of the selected thumbnail.
+ """
+
+ return (selIndex == -1 and [self._selected] or \
+ [self._selectedarray[selIndex]])[0]
+
+
+ def GetOriginalImage(self, index=None):
+ """
+ Returns the original image associated to a thumbnail.
+
+ :param `index`: the index of the thumbnail. If defaulted to ``None``, the current
+ selection is used.
+ """
+
+ if index is None:
+ index = self.GetSelection()
+
+ return self._items[index].GetOriginalImage()
+
+
+ def ScrollToSelected(self):
+ """ Scrolls the :class:`ScrolledWindow` to the selected thumbnail. """
+
+ if self.GetSelection() == -1:
+ return
+
+ # get row
+ row = self.GetSelection()/self._cols
+ # calc position to scroll view
+
+ paintRect = self.GetPaintRect()
+ y1 = row*(self._tHeight + self._tBorder) + self.GetCaptionHeight(0, row)
+ y2 = y1 + self._tBorder + self._tHeight + self.GetCaptionHeight(row)
+
+ if y1 < paintRect.GetTop():
+ sy = y1 # scroll top
+ elif y2 > paintRect.GetBottom():
+ sy = y2 - paintRect.height # scroll bottom
+ else:
+ return
+
+ # scroll view
+ xu, yu = self.GetScrollPixelsPerUnit()
+ sy = sy/yu + (sy%yu and [1] or [0])[0] # convert sy to scroll units
+ x, y = self.GetViewStart()
+
+ self.Scroll(x,sy)
+
+
+ def CalculateBestCaption(self, dc, caption, sw, width):
+ """
+ Calculates the best caption string to show based on the actual zoom factor.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `caption`: the original caption string;
+ :param `sw`: the maximum width allowed for the caption string, in pixels;
+ :param `width`: the caption string width, in pixels.
+ """
+
+ caption = caption + "..."
+
+ while sw > width:
+ caption = caption[1:]
+ sw, sh = dc.GetTextExtent(caption)
+
+ return "..." + caption[0:-3]
+
+
+ def DrawThumbnail(self, bmp, thumb, index):
+ """
+ Draws a visible thumbnail.
+
+ :param `bmp`: the thumbnail version of the original image;
+ :param `thumb`: an instance of :class:`Thumb`;
+ :param `index`: the index of the thumbnail to draw.
+ """
+
+ dc = wx.MemoryDC()
+ dc.SelectObject(bmp)
+ dc.BeginDrawing()
+
+ x = self._tBorder/2
+ y = self._tBorder/2
+
+ # background
+ dc.SetPen(wx.Pen(wx.BLACK, 0, wx.TRANSPARENT))
+ dc.SetBrush(wx.Brush(self.GetBackgroundColour(), wx.SOLID))
+ dc.DrawRectangle(0, 0, bmp.GetWidth(), bmp.GetHeight())
+
+ # image
+ img = thumb.GetBitmap(self._tWidth, self._tHeight)
+ ww = img.GetWidth()
+ hh = img.GetHeight()
+
+ if index == self.GetPointed() and self.GetHighlightPointed():
+ factor = 1.5
+ img = self._imageHandler.HighlightImage(img.ConvertToImage(), factor).ConvertToBitmap()
+
+ imgRect = wx.Rect(x + (self._tWidth - img.GetWidth())/2,
+ y + (self._tHeight - img.GetHeight())/2,
+ img.GetWidth(), img.GetHeight())
+
+ if not thumb._alpha and self._dropShadow:
+ dc.Blit(imgRect.x+5, imgRect.y+5, imgRect.width, imgRect.height, self.shadow, 500-ww, 500-hh)
+ dc.DrawBitmap(img, imgRect.x, imgRect.y, True)
+
+ colour = self.GetSelectionColour()
+ selected = self.IsSelected(index)
+
+ colour = self.GetSelectionColour()
+
+ # draw caption
+ sw, sh = 0, 0
+ if self._showfilenames:
+ textWidth = 0
+ dc.SetFont(self.GetCaptionFont())
+ mycaption = thumb.GetCaption(0)
+ sw, sh = dc.GetTextExtent(mycaption)
+
+ if sw > self._tWidth:
+ mycaption = self.CalculateBestCaption(dc, mycaption, sw, self._tWidth)
+ sw = self._tWidth
+
+ textWidth = sw + 8
+ tx = x + (self._tWidth - textWidth)/2
+ ty = y + self._tHeight
+
+ txtcolour = "#7D7D7D"
+ dc.SetTextForeground(txtcolour)
+
+ tx = x + (self._tWidth - sw)/2
+ if hh >= self._tHeight:
+ ty = y + self._tHeight + (self._tTextHeight - sh)/2 + 3
+ else:
+ ty = y + hh + (self._tHeight-hh)/2 + (self._tTextHeight - sh)/2 + 3
+
+ dc.DrawText(mycaption, tx, ty)
+
+ # outline
+ if self._tOutline != THUMB_OUTLINE_NONE and (self._tOutlineNotSelected or self.IsSelected(index)):
+
+ dotrect = wx.Rect()
+ dotrect.x = x - 2
+ dotrect.y = y - 2
+ dotrect.width = bmp.GetWidth() - self._tBorder + 4
+ dotrect.height = bmp.GetHeight() - self._tBorder + 4
+
+ dc.SetPen(wx.Pen((self.IsSelected(index) and [colour] or [wx.LIGHT_GREY])[0],
+ 0, wx.SOLID))
+ dc.SetBrush(wx.Brush(wx.BLACK, wx.TRANSPARENT))
+
+ if self._tOutline == THUMB_OUTLINE_FULL or self._tOutline == THUMB_OUTLINE_RECT:
+
+ imgRect.x = x
+ imgRect.y = y
+ imgRect.width = bmp.GetWidth() - self._tBorder
+ imgRect.height = bmp.GetHeight() - self._tBorder
+
+ if self._tOutline == THUMB_OUTLINE_RECT:
+ imgRect.height = self._tHeight
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ if selected:
+
+ dc.SetPen(self.grayPen)
+ dc.DrawRoundedRectangleRect(dotrect, 2)
+
+ dc.SetPen(wx.Pen(wx.WHITE))
+ dc.DrawRectangle(imgRect.x, imgRect.y,
+ imgRect.width, imgRect.height)
+
+ pen = wx.Pen((selected and [colour] or [wx.LIGHT_GREY])[0], 2)
+ pen.SetJoin(wx.JOIN_MITER)
+ dc.SetPen(pen)
+ if self._tOutline == THUMB_OUTLINE_FULL:
+ dc.DrawRoundedRectangle(imgRect.x - 1, imgRect.y - 1,
+ imgRect.width + 3, imgRect.height + 3, 2)
+ else:
+ dc.DrawRectangle(imgRect.x - 1, imgRect.y - 1,
+ imgRect.width + 3, imgRect.height + 3)
+ else:
+ dc.SetPen(wx.Pen(wx.LIGHT_GREY))
+
+ dc.DrawRectangle(imgRect.x - 1, imgRect.y - 1,
+ imgRect.width + 2, imgRect.height + 2)
+
+
+ dc.EndDrawing()
+ dc.SelectObject(wx.NullBitmap)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`ThumbnailCtrl`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ paintRect = self.GetPaintRect()
+
+ dc = wx.BufferedPaintDC(self)
+ self.PrepareDC(dc)
+
+ dc.SetPen(wx.Pen(wx.BLACK, 0, wx.TRANSPARENT))
+ dc.SetBrush(wx.Brush(self.GetBackgroundColour(), wx.SOLID))
+
+ w, h = self.GetClientSize()
+
+ # items
+ row = -1
+ xwhite = self._tBorder
+
+ for ii in xrange(len(self._items)):
+
+ col = ii%self._cols
+ if col == 0:
+ row = row + 1
+
+ xwhite = ((w - self._cols*(self._tWidth + self._tBorder)))/(self._cols+1)
+ tx = xwhite + col*(self._tWidth + self._tBorder)
+
+ ty = self._tBorder/2 + row*(self._tHeight + self._tBorder) + \
+ self.GetCaptionHeight(0, row)
+ tw = self._tWidth + self._tBorder
+ th = self._tHeight + self.GetCaptionHeight(row) + self._tBorder
+ # visible?
+ if not paintRect.Intersects(wx.Rect(tx, ty, tw, th)):
+ continue
+
+ thmb = wx.EmptyBitmap(tw, th)
+ self.DrawThumbnail(thmb, self._items[ii], ii)
+ dc.DrawBitmap(thmb, tx, ty)
+
+ rect = wx.Rect(xwhite, self._tBorder/2,
+ self._cols*(self._tWidth + self._tBorder),
+ self._rows*(self._tHeight + self._tBorder) + \
+ self.GetCaptionHeight(0, self._rows))
+
+ w = max(self.GetClientSize().GetWidth(), rect.width)
+ h = max(self.GetClientSize().GetHeight(), rect.height)
+ dc.DrawRectangle(0, 0, w, rect.y)
+ dc.DrawRectangle(0, 0, rect.x, h)
+ dc.DrawRectangle(rect.GetRight(), 0, w - rect.GetRight(), h + 50)
+ dc.DrawRectangle(0, rect.GetBottom(), w, h - rect.GetBottom() + 50)
+
+ col = len(self._items)%self._cols
+
+ if col > 0:
+ rect.x = rect.x + col*(self._tWidth + self._tBorder)
+ rect.y = rect.y + (self._rows - 1)*(self._tHeight + self._tBorder) + \
+ self.GetCaptionHeight(0, self._rows - 1)
+ dc.DrawRectangleRect(rect)
+
+
+ def OnResize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`ThumbnailCtrl`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.UpdateProp()
+ self.ScrollToSelected()
+ self.Refresh()
+
+
+ def OnMouseDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` and ``wx.EVT_RIGHT_DOWN`` events for :class:`ThumbnailCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ x = event.GetX()
+ y = event.GetY()
+ x, y = self.CalcUnscrolledPosition(x, y)
+ # get item number to select
+ lastselected = self._selected
+ self._selected = self.GetItemIndex(x, y)
+
+ self._mouseeventhandled = False
+ update = False
+
+ if event.ControlDown():
+ if self._selected == -1:
+ self._mouseeventhandled = True
+ elif not self.IsSelected(self._selected):
+ self._selectedarray.append(self._selected)
+ update = True
+ self._mouseeventhandled = True
+
+ elif event.ShiftDown():
+ if self._selected != -1:
+ begindex = self._selected
+ endindex = lastselected
+ if lastselected < self._selected:
+ begindex = lastselected
+ endindex = self._selected
+ self._selectedarray = []
+
+ for ii in xrange(begindex, endindex+1):
+ self._selectedarray.append(ii)
+
+ update = True
+
+ self._selected = lastselected
+ self._mouseeventhandled = True
+
+ else:
+
+ if self._selected == -1:
+ update = len(self._selectedarray) > 0
+ self._selectedarray = []
+ self._mouseeventhandled = True
+ elif len(self._selectedarray) <= 1:
+ try:
+ update = len(self._selectedarray)== 0 or self._selectedarray[0] != self._selected
+ except:
+ update = True
+ self._selectedarray = []
+ self._selectedarray.append(self._selected)
+ self._mouseeventhandled = True
+
+ if update:
+ self.ScrollToSelected()
+ self.Refresh()
+ eventOut = ThumbnailEvent(wxEVT_THUMBNAILS_SEL_CHANGED, self.GetId())
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+ self.SetFocus()
+
+
+ def OnMouseUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` and ``wx.EVT_RIGHT_UP`` events for :class:`ThumbnailCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # get item number to select
+ x = event.GetX()
+ y = event.GetY()
+ x, y = self.CalcUnscrolledPosition(x, y)
+ lastselected = self._selected
+ self._selected = self.GetItemIndex(x,y)
+
+ if not self._mouseeventhandled:
+ # set new selection
+ if event.ControlDown():
+ if self._selected in self._selectedarray:
+ self._selectedarray.remove(self._selected)
+
+ self._selected = -1
+ else:
+ self._selectedarray = []
+ self._selectedarray.append(self._selected)
+
+ self.ScrollToSelected()
+ self.Refresh()
+ eventOut = ThumbnailEvent(wxEVT_THUMBNAILS_SEL_CHANGED, self.GetId())
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+ # Popup menu
+ if event.RightUp():
+ if self._selected >= 0 and self._pmenu:
+ self.PopupMenu(self._pmenu, event.GetPosition())
+ elif self._selected >= 0 and not self._pmenu and self._gpmenu:
+ self.PopupMenu(self._gpmenu, event.GetPosition())
+ elif self._selected == -1 and self._gpmenu:
+ self.PopupMenu(self._gpmenu, event.GetPosition())
+
+ if event.ShiftDown():
+ self._selected = lastselected
+
+
+ def OnMouseDClick(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DCLICK`` event for :class:`ThumbnailCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ eventOut = ThumbnailEvent(wxEVT_THUMBNAILS_DCLICK, self.GetId())
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+
+ def OnMouseMove(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`ThumbnailCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # -- drag & drop --
+ if self._dragging and event.Dragging() and len(self._selectedarray) > 0:
+
+ files = wx.FileDataObject()
+ for ii in xrange(len(self._selectedarray)):
+ files.AddFile(opj(self.GetSelectedItem(ii).GetFullFileName()))
+
+ source = wx.DropSource(self)
+ source.SetData(files)
+ source.DoDragDrop(wx.Drag_DefaultMove)
+
+ # -- light-effect --
+ x = event.GetX()
+ y = event.GetY()
+ x, y = self.CalcUnscrolledPosition(x, y)
+
+ # get item number
+ sel = self.GetItemIndex(x, y)
+
+ if sel == self._pointed:
+ if self._enabletooltip and sel >= 0:
+ if not hasattr(self, "_tipwindow"):
+ self._tipwindow = wx.ToolTip(self.GetThumbInfo(sel))
+ self._tipwindow.SetDelay(1000)
+ self.SetToolTip(self._tipwindow)
+ else:
+ self._tipwindow.SetDelay(1000)
+ self._tipwindow.SetTip(self.GetThumbInfo(sel))
+
+ event.Skip()
+ return
+
+ if self._enabletooltip:
+ if hasattr(self, "_tipwindow"):
+ self._tipwindow.Enable(False)
+
+ # update thumbnail
+ self._pointed = sel
+
+ if self._enabletooltip and sel >= 0:
+ if not hasattr(self, "_tipwindow"):
+ self._tipwindow = wx.ToolTip(self.GetThumbInfo(sel))
+ self._tipwindow.SetDelay(1000)
+ self._tipwindow.Enable(True)
+ self.SetToolTip(self._tipwindow)
+ else:
+ self._tipwindow.SetDelay(1000)
+ self._tipwindow.Enable(True)
+ self._tipwindow.SetTip(self.GetThumbInfo(sel))
+
+ self.Refresh()
+ eventOut = ThumbnailEvent(wxEVT_THUMBNAILS_POINTED, self.GetId())
+ self.GetEventHandler().ProcessEvent(eventOut)
+ event.Skip()
+
+
+ def OnMouseLeave(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`ThumbnailCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self._pointed != -1:
+
+ self._pointed = -1
+ self.Refresh()
+ eventOut = ThumbnailEvent(wxEVT_THUMBNAILS_POINTED, self.GetId())
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+
+ def OnThumbChanged(self, event):
+ """
+ Handles the ``EVT_THUMBNAILS_THUMB_CHANGED`` event for :class:`ThumbnailCtrl`.
+
+ :param `event`: a :class:`ThumbnailEvent` event to be processed.
+ """
+
+ for ii in xrange(len(self._items)):
+ if self._items[ii].GetFileName() == event.GetString():
+
+ self._items[ii].SetFilename(self._items[ii].GetFileName())
+ if event.GetClientData():
+
+ img = wx.Image(event.GetClientData())
+ self._items[ii].SetImage(img)
+
+ self.Refresh()
+
+
+ def OnChar(self, event):
+ """
+ Handles the ``wx.EVT_CHAR`` event for :class:`ThumbnailCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+
+ :note: You have these choices:
+
+ (1) ``d`` key rotates 90 degrees clockwise the selected thumbnails;
+ (2) ``s`` key rotates 90 degrees counter-clockwise the selected thumbnails;
+ (3) ``a`` key rotates 180 degrees the selected thumbnails;
+ (4) ``Del`` key deletes the selected thumbnails;
+ (5) ``+`` key zooms in;
+ (6) ``-`` key zooms out.
+ """
+
+ if event.m_keyCode == ord("s"):
+ self.Rotate()
+ elif event.m_keyCode == ord("d"):
+ self.Rotate(270)
+ elif event.m_keyCode == ord("a"):
+ self.Rotate(180)
+ elif event.m_keyCode == wx.WXK_DELETE:
+ self.DeleteFiles()
+ elif event.m_keyCode in [wx.WXK_ADD, wx.WXK_NUMPAD_ADD]:
+ self.ZoomIn()
+ elif event.m_keyCode in [wx.WXK_SUBTRACT, wx.WXK_NUMPAD_SUBTRACT]:
+ self.ZoomOut()
+
+ event.Skip()
+
+
+ def Rotate(self, angle=90):
+ """
+ Rotates the selected thumbnails by the angle specified by `angle`.
+
+ :param `angle`: the rotation angle for the thumbnail, in degrees.
+ """
+
+ wx.BeginBusyCursor()
+
+ count = 0
+ selected = []
+
+ for ii in xrange(len(self._items)):
+ if self.IsSelected(ii):
+ selected.append(self._items[ii])
+
+ dlg = wx.ProgressDialog("Thumbnail Rotation",
+ "Rotating Thumbnail... Please Wait",
+ maximum = len(selected)+1,
+ parent=None)
+
+ for thumb in selected:
+ count = count + 1
+ if TN_USE_PIL:
+ newangle = thumb.GetRotation()*180/pi + angle
+ fil = opj(thumb.GetFullFileName())
+ pil = Image.open(fil).rotate(newangle)
+ img = wx.EmptyImage(pil.size[0], pil.size[1])
+ img.SetData(pil.convert('RGB').tostring())
+ thumb.SetRotation(newangle*pi/180)
+ else:
+ img = thumb._threadedimage
+ newangle = thumb.GetRotation() + angle*pi/180
+ thumb.SetRotation(newangle)
+ img = img.Rotate(newangle, (img.GetWidth()/2, img.GetHeight()/2), True)
+
+ thumb.SetRotatedImage(img)
+ dlg.Update(count)
+
+ wx.EndBusyCursor()
+ dlg.Destroy()
+
+ if self.GetSelection() != -1:
+ self.Refresh()
+
+
+ def DeleteFiles(self):
+ """
+ Deletes the selected thumbnails and their associated files.
+
+ .. warning:: This method deletes the original files too.
+ """
+
+ dlg = wx.MessageDialog(self, 'Are you sure you want to delete the files?',
+ 'Confirmation',
+ wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
+
+ if dlg.ShowModal() == wx.ID_YES:
+ errordelete = []
+ count = 0
+
+ dlg.Destroy()
+
+ wx.BeginBusyCursor()
+
+ for ii in xrange(len(self._items)):
+ if self.IsSelected(ii):
+ thumb = self._items[ii]
+ files = self._items[ii].GetFullFileName()
+ filename = opj(files)
+ try:
+ os.remove(filename)
+ count = count + 1
+ except:
+ errordelete.append(files)
+
+ wx.EndBusyCursor()
+
+ if errordelete:
+ strs = "Unable to remove the following files:\n\n"
+ for fil in errordelete:
+ strs = strs + fil + "\n"
+ strs = strs + "\n"
+ strs = strs + "Please check your privileges and file permissions."
+ dlg = wx.MessageDialog(self, strs,
+ 'Error in removing files',
+ wx.OK | wx.ICON_ERROR)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+ if count:
+ self.UpdateShow()
+
+
+ def OnMouseWheel(self, event):
+ """
+ Handles the ``wx.EVT_MOUSEWHEEL`` event for :class:`ThumbnailCtrl`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+
+ :note: If you hold down the ``Ctrl`` key, you can zoom in/out with the mouse wheel.
+ """
+
+ if event.ControlDown():
+ if event.GetWheelRotation() > 0:
+ self.ZoomIn()
+ else:
+ self.ZoomOut()
+ else:
+ event.Skip()
+
+
+ def ZoomOut(self):
+ """ Zooms the thumbnails out. """
+
+ w, h, b = self.GetThumbSize()
+
+ if w < 40 or h < 40:
+ return
+
+ zoom = self.GetZoomFactor()
+ neww = float(w)/zoom
+ newh = float(h)/zoom
+
+ self.SetThumbSize(int(neww), int(newh))
+ self.OnResize(None)
+ self._checktext = True
+
+ self.Refresh()
+
+
+ def ZoomIn(self):
+ """ Zooms the thumbnails in. """
+
+ size = self.GetClientSize()
+ w, h, b = self.GetThumbSize()
+ zoom = self.GetZoomFactor()
+
+ if w*zoom + b > size.GetWidth() or h*zoom + b > size.GetHeight():
+ if w*zoom + b > size.GetWidth():
+ neww = size.GetWidth() - 2*self._tBorder
+ newh = (float(h)/w)*neww
+ else:
+ newh = size.GetHeight() - 2*self._tBorder
+ neww = (float(w)/h)*newh
+
+ else:
+ neww = float(w)*zoom
+ newh = float(h)*zoom
+
+ self.SetThumbSize(int(neww), int(newh))
+ self.OnResize(None)
+ self._checktext = True
+
+ self.Refresh()
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/toasterbox.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/toasterbox.py
new file mode 100644
index 0000000..a47688c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/toasterbox.py
@@ -0,0 +1,1331 @@
+# --------------------------------------------------------------------------- #
+# TOASTERBOX wxPython IMPLEMENTATION
+# Ported And Enhanced From wxWidgets Contribution (Aj Bommarito) By:
+#
+# Andrea Gavana, @ 16 September 2005
+# Latest Revision: 14 Mar 2012, 21.00 GMT
+#
+#
+# TODO/Caveats List
+#
+# 1. Any Idea?
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+
+"""
+ToasterBox is a cross-platform widget to make the creation of MSN style "toaster"
+popups easier.
+
+
+Description
+===========
+
+ToasterBox is a cross-platform widget to make the creation of MSN style "toaster"
+popups easier. The syntax is really easy especially if you are familiar with the
+syntax of wxPython.
+
+It has 2 main styles:
+
+- ``TB_SIMPLE``: using this style, you will be able to specify a background image for
+ ToasterBox, text properties as text colour, font and label;
+
+- ``TB_COMPLEX``: this style will allow you to put almost any control inside a
+ ToasterBox. You can add a panel in which you can put all the controls you like.
+
+Both styles support the setting of ToasterBox position (on screen coordinates),
+size, the time after which the ToasterBox is destroyed (linger), and the scroll
+speed of ToasterBox.
+
+
+Usage
+=====
+
+Usage example::
+
+ import wx
+ import wx.lib.agw.toasterbox as TB
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "ToasterBox Demo")
+
+ toaster = TB.ToasterBox(self, tbstyle=TB.TB_COMPLEX)
+ toaster.SetPopupPauseTime(3000)
+
+ tbpanel = toaster.GetToasterBoxWindow()
+ panel = wx.Panel(tbpanel, -1)
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ button = wx.Button(panel, wx.ID_ANY, "Simple button")
+ sizer.Add(button, 0, wx.EXPAND)
+
+ panel.SetSizer(sizer)
+ toaster.AddPanel(panel)
+
+ wx.CallLater(1000, toaster.Play)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Supported Platforms
+===================
+
+ToasterBox has been tested on the following platforms:
+
+- Windows (verified on Windows XP, 2000)
+- Linux
+- Mac
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+==================== =========== ==================================================
+Window Styles Hex Value Description
+==================== =========== ==================================================
+``TB_SIMPLE`` 0x1 A simple `ToasterBox`, with background image and text customization can be created.
+``TB_ONTIME`` 0x1 `ToasterBox` will close after a specified amount of time.
+``TB_COMPLEX`` 0x2 ToasterBoxes with different degree of complexity can be created. You can add as many controls as you want, provided that you call the meth:~ToasterBox.AddPanel` method and pass to it a dummy frame and a :class:`Panel`. See the demo for details.
+``TB_ONCLICK`` 0x2 `ToasterBox` can be closed by clicking anywhere on the `ToasterBox` frame.
+``TB_DEFAULT_STYLE`` 0x2008002 Default window style for `ToasterBox`, with no caption nor close box.
+``TB_CAPTION`` 0x22009806 `ToasterBox` will have a caption, with the possibility to set a title for the `ToasterBox` frame, and a close box.
+==================== =========== ==================================================
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+ToasterBox is distributed under the wxPython license.
+
+Latest revision: Andrea Gavana @ 14 Mar 2012, 21.00 GMT
+
+Version 0.3
+
+"""
+
+import textwrap
+import wx
+
+
+# Define Window List, We Use It Globally
+winlist = []
+""" Globally defined window list. """
+
+TB_SIMPLE = 1
+""" A simple ToasterBox, with background image and text customization can be created. """
+TB_COMPLEX = 2
+""" ToasterBoxes with different degree of complexity can be created. You can add as many controls as you want, provided that you call the AddPanel() method and pass to it a dummy frame and a wx.Panel. See the demo for details. """
+TB_DEFAULT_STYLE = wx.SIMPLE_BORDER | wx.STAY_ON_TOP | wx.FRAME_NO_TASKBAR
+""" Default window style for `ToasterBox`, with no caption nor close box. """
+TB_CAPTION = TB_DEFAULT_STYLE | wx.CAPTION | wx.SYSTEM_MENU | wx.CLOSE_BOX | wx.FRAME_NO_TASKBAR
+""" `ToasterBox` will have a caption, with the possibility to set a title for the `ToasterBox` frame, and a close box. """
+TB_ONTIME = 1
+""" `ToasterBox` will close after a specified amount of time. """
+TB_ONCLICK = 2
+""" `ToasterBox` can be closed by clicking anywhere on the `ToasterBox` frame. """
+
+# scroll from up to down
+TB_SCR_TYPE_UD = 1
+""" Scroll from up to down. """
+# scroll from down to up
+TB_SCR_TYPE_DU = 2
+""" Scroll from down to up. """
+# fade in/out
+TB_SCR_TYPE_FADE = 4
+""" Fade in and out. """
+
+
+# ------------------------------------------------------------------------------ #
+# Class ToasterBox
+# Main Class Implementation. It Is Basically A wx.Timer. It Creates And
+# Displays Popups And Handles The "Stacking".
+# ------------------------------------------------------------------------------ #
+
+class ToasterBox(wx.Timer):
+ """
+ ToasterBox is a cross-platform widget to make the creation of MSN style "toaster"
+ popups easier.
+ """
+
+ def __init__(self, parent, tbstyle=TB_SIMPLE, windowstyle=TB_DEFAULT_STYLE,
+ closingstyle=TB_ONTIME, scrollType=TB_SCR_TYPE_DU):
+ """
+ Default class constructor.
+
+ :param `parent`: the window parent;
+ :param `tbstyle`: the :class:`ToasterBox` main style. Can be one of the following
+ bits:
+
+ ====================== ======= ================================
+ `ToasterBox` Style Value Description
+ ====================== ======= ================================
+ ``TB_SIMPLE`` 0x1 A simple :class:`ToasterBox`, with background image and text customization can be created
+ ``TB_COMPLEX`` 0x2 `ToasterBoxes` with different degree of complexity can be created. You can add as many controls as you want, provided that you call the :meth:`~ToasterBox.AddPanel` method and pass to it a dummy frame and a :class:`Panel`.
+ ====================== ======= ================================
+
+ :param `windowstyle`: this parameter influences the visual appearance of
+ :class:`ToasterBox`, and can be one of the following styles:
+
+ ====================== ========== ================================
+ Window Style Hex Value Description
+ ====================== ========== ================================
+ ``TB_DEFAULT_STYLE`` 0x2008002 Default window style for :class:`ToasterBox`, with no caption nor close box.
+ ``TB_CAPTION`` 0x22009806 :class:`ToasterBox` will have a caption, with the possibility to set a title for the :class:`ToasterBox` frame, and a close box.
+ ====================== ========== ================================
+
+ :param `closingstyle`: the closing style for :class:`ToasterBox`. Can be one of the
+ following bits:
+
+ ==================== =========== ==================================================
+ Closing Styles Hex Value Description
+ ==================== =========== ==================================================
+ ``TB_ONTIME`` 0x1 :class:`ToasterBox` will close after a specified amount of time.
+ ``TB_ONCLICK`` 0x2 :class:`ToasterBox` can be closed by clicking anywhere on the :class:`ToasterBox` frame.
+ ==================== =========== ==================================================
+
+ :param `scrollType`: the scrolling direction for :class:`ToasterBox`. Can be one of the
+ following bits:
+
+ ==================== =========== ==================================================
+ Scroll Styles Hex Value Description
+ ==================== =========== ==================================================
+ ``TB_SCR_TYPE_UD`` 0x1 :class:`ToasterBox` will scroll from up to down
+ ``TB_SCR_TYPE_DU`` 0x2 :class:`ToasterBox` will scroll from down to up
+ ``TB_SCR_TYPE_FADE`` 0x4 :class:`ToasterBox` will fade in/out (without scrolling).
+ ==================== =========== ==================================================
+
+ """
+
+ self._parent = parent
+ self._sleeptime = 10
+ self._pausetime = 1700
+ self._popuptext = "default"
+ self._popupposition = wx.Point(100,100)
+ self._popuptop = wx.Point(0,0)
+ self._popupsize = wx.Size(150, 170)
+ self._usefocus = True
+ self._originalfocus = wx.Window.FindFocus()
+
+ self._backgroundcolour = wx.WHITE
+ self._foregroundcolour = wx.BLACK
+ self._textfont = wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False, "Verdana")
+
+ self._bitmap = None
+
+ self._tbstyle = tbstyle
+ self._windowstyle = windowstyle
+ self._closingstyle = closingstyle
+ self._scrollType = scrollType
+
+ self._panel = None
+
+ self._bottomright = wx.Point(wx.GetDisplaySize().GetWidth(),
+ wx.GetDisplaySize().GetHeight())
+
+ if parent is not None:
+ parent.Bind(wx.EVT_ICONIZE, lambda evt: [w.Hide() for w in winlist])
+ self._moveTimer = wx.Timer(parent, -1)
+ parent.Bind(wx.EVT_TIMER, self.OnMoveTimer, self._moveTimer)
+
+ self._tb = ToasterBoxWindow(self._parent, self, self._tbstyle, self._windowstyle,
+ self._closingstyle, scrollType=self._scrollType)
+
+
+
+ def SetPopupPosition(self, pos):
+ """
+ Sets the :class:`ToasterBox` position on screen.
+
+ :param `pos`: the widget position, an instance of :class:`Point`.
+ """
+
+ self._popupposition = pos
+
+
+ def SetPopupPositionByInt(self, pos):
+ """
+ Sets the :class:`ToasterBox` position on screen, at one of the screen corners.
+
+ :param `pos`: an integer specifying the screen corner, namely:
+
+ ============= ========================================
+ Corner Number Position
+ ============= ========================================
+ 0 Top left screen corner
+ 1 Top right screen corner
+ 2 Bottom left screen corner
+ 3 Bottom right screen corner
+ ============= ========================================
+
+ """
+
+ w, h = wx.GetDisplaySize()
+ self._bottomright = wx.Point(w, h)
+
+ # top left
+ if pos == 0:
+ popupposition = wx.Point(0,0)
+ # top right
+ elif pos == 1:
+ popupposition = wx.Point(w - self._popupsize[0], 0)
+ # bottom left
+ elif pos == 2:
+ popupposition = wx.Point(0, h - self._popupsize[1])
+ # bottom right
+ elif pos == 3:
+ popupposition = wx.Point(self._bottomright.x - self._popupsize[0],
+ self._bottomright.y - self._popupsize[1])
+
+ self._bottomright = wx.Point(popupposition.x + self._popupsize[0],
+ popupposition.y + self._popupsize[1])
+
+ self._popupposition = popupposition
+
+
+ def CenterOnParent(self, direction=wx.BOTH):
+ """
+ Centres the window on its parent (if any). If the :class:`ToasterBox` parent is ``None``,
+ it calls :meth:`~ToasterBox.CenterOnScreen`.
+
+ :param `direction`: specifies the direction for the centering. May be ``wx.HORIZONTAL``,
+ ``wx.VERTICAL`` or ``wx.BOTH``.
+
+ :note: This methods provides for a way to center :class:`ToasterBox` over their parents instead of the
+ entire screen. If there is no parent, then behaviour is the same as :meth:`~ToasterBox.CenterOnScreen`.
+
+ :see: :meth:`~ToasterBox.CenterOnScreen`.
+ """
+
+ if not self._parent:
+ self.CenterOnScreen(direction)
+ return
+
+ parent = self._parent
+ screenrect = parent.GetScreenRect()
+ toast_width, toast_height = self._popupsize
+ x, y = screenrect.GetX(), screenrect.GetY()
+ width, height = screenrect.GetWidth(), screenrect.GetHeight()
+
+ if direction == wx.VERTICAL:
+ pos = wx.Point(x, (y + (height/2) - (toast_height/2)))
+ elif direction == wx.HORIZONTAL:
+ pos = wx.Point((x + (width/2) - (toast_width/2)), y)
+ else:
+ pos = wx.Point((x + (width/2) - (toast_width/2)), (y + (height/2) - (toast_height/2)))
+
+ tb.SetPopupPosition(pos)
+
+
+ CentreOnParent = CenterOnParent
+
+
+ def CenterOnScreen(self, direction=wx.BOTH):
+ """
+ Centres the :class:`ToasterBox` on screen.
+
+ :param `direction`: specifies the direction for the centering. May be ``wx.HORIZONTAL``,
+ ``wx.VERTICAL`` or ``wx.BOTH``.
+
+ :see: :meth:`~ToasterBox.CenterOnParent`.
+ """
+
+ screenSize = wx.GetDisplaySize()
+ toast_width, toast_height = self._popupsize
+ width, height = screenSize.GetWidth(), screenSize.GetHeight()
+
+ if direction == wx.VERTICAL:
+ pos = wx.Point(0, (height/2) - (toast_height/2))
+ elif direction == wx.HORIZONTAL:
+ pos = wx.Point((width/2) - (toast_width/2), 0)
+ else:
+ pos = wx.Point((width/2) - (toast_width/2), (height/2) - (toast_height/2))
+
+ tb.SetPopupPosition(pos)
+
+
+ CentreOnScreen = CenterOnScreen
+
+
+ def SetPopupBackgroundColour(self, colour=None):
+ """
+ Sets the :class:`ToasterBox` background colour.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, then
+ the background colour will be white.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ if colour is None:
+ colour = wx.WHITE
+
+ if isinstance(colour, basestring):
+ colour = wx.NamedColour(colour)
+
+ self._backgroundcolour = colour
+ self._tb.SetPopupBackgroundColour(self._backgroundcolour)
+
+
+ def SetPopupTextColour(self, colour=None):
+ """
+ Sets the :class:`ToasterBox` foreground colour.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, then
+ the background colour will be black.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ if colour is None:
+ colour = wx.BLACK
+
+ if isinstance(colour, basestring):
+ colour = wx.NamedColour(colour)
+
+ self._foregroundcolour = colour
+
+
+ def SetPopupTextFont(self, font=None):
+ """
+ Sets the :class:`ToasterBox` text font.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, then
+ a simple generic font will be generated.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ if font is None:
+ font = wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False)
+
+ self._textfont = font
+
+
+ def SetPopupSize(self, size):
+ """
+ Sets the :class:`ToasterBox` size.
+
+ :param `size`: the new control size, an instance of :class:`Size`.
+ """
+
+ self._popupsize = size
+
+
+ def SetPopupPauseTime(self, pausetime):
+ """
+ Sets the time after which the :class:`ToasterBox` is destroyed (linger).
+
+ :param `pausetime`: the delay after which the control is destroyed, in seconds.
+ """
+
+ self._pausetime = pausetime
+
+
+ def SetPopupBitmap(self, bitmap=None):
+ """
+ Sets the :class:`ToasterBox` background image.
+
+ :param `bitmap`: a valid :class:`Bitmap` object or filename. If defaulted
+ to ``None``, then no background bitmap is used.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ if bitmap is not None:
+ if isinstance(bitmap, basestring):
+ bitmap = wx.Bitmap(bitmap)
+
+ self._bitmap = bitmap
+
+
+ def SetPopupScrollSpeed(self, speed):
+ """
+ Sets the :class:`ToasterBox` scroll speed.
+
+ :param `speed`: it is the pause time (in milliseconds) for every step in the
+ `ScrollUp` method.
+ """
+
+ self._sleeptime = speed
+
+
+ def SetPopupText(self, text):
+ """
+ Sets the :class:`ToasterBox` text label.
+
+ :param `text`: the widget label.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ self._popuptext = text
+
+
+ def AddPanel(self, panel):
+ """
+ Adds a panel to the :class:`ToasterBox`.
+
+ :param `panel`: an instance of :class:`Window`.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_COMPLEX`` style.
+ """
+
+ if not self._tbstyle & TB_COMPLEX:
+ raise Exception("\nERROR: Panel Can Not Be Added When Using TB_SIMPLE ToasterBox Style")
+
+ self._panel = panel
+
+
+ def Play(self):
+ """ Creates the :class:`ToasterBoxWindow`, that does all the job. """
+
+ # create new window
+ self._tb.SetPopupSize((self._popupsize[0], self._popupsize[1]))
+ self._tb.SetPopupPosition((self._popupposition[0], self._popupposition[1]))
+ self._tb.SetPopupPauseTime(self._pausetime)
+ self._tb.SetPopupScrollSpeed(self._sleeptime)
+ self._tb.SetUseFocus(self._usefocus, self._originalfocus)
+
+ if self._tbstyle == TB_SIMPLE:
+ self._tb.SetPopupTextColour(self._foregroundcolour)
+ self._tb.SetPopupBackgroundColour(self._backgroundcolour)
+ self._tb.SetPopupTextFont(self._textfont)
+
+ if self._bitmap is not None:
+ self._tb.SetPopupBitmap(self._bitmap)
+
+ self._tb.SetPopupText(self._popuptext)
+
+ if self._tbstyle == TB_COMPLEX:
+ if self._panel is not None:
+ self._tb.AddPanel(self._panel)
+
+ # clean up the list
+ self.CleanList()
+
+ # check to see if there is already a window displayed
+ # by looking at the linked list
+ if len(winlist) > 0:
+ # there ARE other windows displayed already
+ # reclac where it should display
+ self.MoveAbove(self._tb)
+
+ # shift new window on to the list
+ winlist.append(self._tb)
+
+ if not self._tb.Play():
+ # if we didn't show the window properly, remove it from the list
+ winlist.remove(winlist[-1])
+ # delete the object too
+ self._tb.Destroy()
+ return
+
+
+ def MoveAbove(self, tb):
+ """
+ If a :class:`ToasterBox` already exists, move the new one above the existing one.
+
+ :param `tb`: another instance of :class:`ToasterBox`.
+ """
+
+ # recalc where to place this popup
+
+ self._tb.SetPopupPosition((self._popupposition[0], self._popupposition[1] -
+ self._popupsize[1]*len(winlist)))
+
+
+ def GetToasterBoxWindow(self):
+ """ Returns the :class:`ToasterBox` frame. """
+
+ return self._tb
+
+
+ def SetTitle(self, title):
+ """
+ Sets the :class:`ToasterBox` title if it was created with ``TB_CAPTION`` window style.
+
+ :param `title`: the :class:`ToasterBox` caption title.
+ """
+
+ self._tb.SetTitle(title)
+
+
+ def SetUseFocus(self, focus):
+ """
+ If `focus` is ``True``, Instructs :class:`ToasterBox` to steal the focus from the
+ parent application, otherwise it returns the focus to the original owner.
+
+ :param `focus`: ``True`` to set the focus on :class:`ToasterBox`, ``False`` to
+ return it to the original owner.
+ """
+
+ self._usefocus = focus
+
+
+ def GetUseFocus(self):
+ """ Returns whether :class:`ToasterBox` will steal the focus from the parent application. """
+
+ return self._usefocus
+
+
+ def Notify(self):
+ """ It's time to hide a :class:`ToasterBox`. """
+
+ if len(winlist) == 0:
+ return
+
+ # clean the window list
+ self.CleanList()
+
+ # figure out how many blanks we have
+ try:
+ node = winlist[0]
+ except:
+ return
+
+ if not node:
+ return
+
+ self._startPos = node.GetPosition()[1]
+ self._moveTimer.Start(self._sleeptime)
+
+
+ def OnMoveTimer(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`ToasterBox`, moving the new window
+ on top of the last one created.
+
+ :param `event`: a :class:`TimerEvent` event to be processed.
+ """
+
+ current = self._startPos
+ if current >= self._popupposition[1]:
+ self._moveTimer.Stop()
+
+ # move windows to fill in blank space
+
+ if current > self._popupposition[1]:
+ current = self._popupposition[1]
+
+ # loop through all the windows
+ for j in xrange(0, len(winlist)):
+ ourNewHeight = current - (j*self._popupsize[1] - 8)
+ tmpTb = winlist[j]
+ # reset where the object THINKS its supposed to be
+ tmpTb.SetPopupPosition((self._popupposition[0], ourNewHeight))
+ # actually move it
+ tmpTb.SetDimensions(self._popupposition[0], ourNewHeight, tmpTb.GetSize().GetWidth(),
+ tmpTb.GetSize().GetHeight())
+
+ self._startPos += 4
+
+
+ def CleanList(self):
+ """ Cleans the window list, erasing the stack of :class:`ToasterBox` objects. """
+
+ if len(winlist) == 0:
+ return
+
+ node = winlist[0]
+ while node:
+ if not node.IsShown():
+ winlist.remove(node)
+ node.Close()
+ try:
+ node = winlist[0]
+ except:
+ node = 0
+ else:
+ indx = winlist.index(node)
+ try:
+ node = winlist[indx+1]
+ except:
+ node = 0
+
+
+# ------------------------------------------------------------------------------ #
+# Class ToasterBoxWindow
+# This Class Does All The Job, By Handling Background Images, Text Properties
+# And Panel Adding. Depending On The Style You Choose, ToasterBoxWindow Will
+# Behave Differently In Order To Handle Widgets Inside It.
+# ------------------------------------------------------------------------------ #
+
+class ToasterBoxWindow(wx.Frame):
+ """
+ This class does all the job, by handling background images, text properties
+ and panel adding. Depending on the style you choose, :class:`ToasterBoxWindow` will
+ behave differently in order to handle widgets inside it.
+ """
+
+ def __init__(self, parent, parent2, tbstyle, windowstyle, closingstyle,
+ scrollType=TB_SCR_TYPE_DU):
+ """
+ Default class constructor.
+ Used internally. Do not call directly this class in your application!
+
+ :param `parent`: the window parent;
+ :param `parent2`: the :class:`ToasterBox` calling this window;
+ :param `tbstyle`: the :class:`ToasterBoxWindow` main style. Can be one of the following
+ bits:
+
+ ====================== ======= ================================
+ `ToasterBox` Style Value Description
+ ====================== ======= ================================
+ ``TB_SIMPLE`` 0x1 A simple :class:`ToasterBox`, with background image and text customization can be created
+ ``TB_COMPLEX`` 0x2 `ToasterBoxes` with different degree of complexity can be created. You can add as many controls as you want, provided that you call the :meth:`~ToasterBoxWindow.AddPanel` method and pass to it a dummy frame and a :class:`Panel`.
+ ====================== ======= ================================
+
+ :param `windowstyle`: this parameter influences the visual appearance of
+ :class:`ToasterBoxWindow`, and can be one of the following styles:
+
+ ====================== ========== ================================
+ Window Style Hex Value Description
+ ====================== ========== ================================
+ ``TB_DEFAULT_STYLE`` 0x2008002 Default window style for :class:`ToasterBox`, with no caption nor close box.
+ ``TB_CAPTION`` 0x22009806 :class:`ToasterBox` will have a caption, with the possibility to set a title for the :class:`ToasterBox` frame, and a close box.
+ ====================== ========== ================================
+
+ :param `closingstyle`: the closing style for :class:`ToasterBoxWindow`. Can be one of the
+ following bits:
+
+ ==================== =========== ==================================================
+ Closing Styles Hex Value Description
+ ==================== =========== ==================================================
+ ``TB_ONTIME`` 0x1 :class:`ToasterBox` will close after a specified amount of time.
+ ``TB_ONCLICK`` 0x2 :class:`ToasterBox` can be closed by clicking anywhere on the :class:`ToasterBox` frame.
+ ==================== =========== ==================================================
+
+ :param `scrollType`: the scrolling direction for :class:`ToasterBoxWindow`. Can be one of the
+ following bits:
+
+ ==================== =========== ==================================================
+ Scroll Styles Hex Value Description
+ ==================== =========== ==================================================
+ ``TB_SCR_TYPE_UD`` 0x1 :class:`ToasterBox` will scroll from up to down
+ ``TB_SCR_TYPE_DU`` 0x2 :class:`ToasterBox` will scroll from down to up
+ ``TB_SCR_TYPE_FADE`` 0x4 :class:`ToasterBox` will fade in/out (without scrolling).
+ ==================== =========== ==================================================
+
+ """
+
+ wx.Frame.__init__(self, parent, wx.ID_ANY, "window", wx.DefaultPosition,
+ wx.DefaultSize, style=windowstyle | wx.CLIP_CHILDREN)
+
+ self._starttime = wx.GetLocalTime()
+ self._parent2 = parent2
+ self._parent = parent
+ self._sleeptime = 10
+ self._step = 4
+ self._pausetime = 1700
+ self._textcolour = wx.BLACK
+ self._popuptext = "Change Me!"
+ # the size we want the dialog to be
+ framesize = wx.Size(150, 170)
+ self._count = 1
+ self._tbstyle = tbstyle
+ self._windowstyle = windowstyle
+ self._closingstyle = closingstyle
+ self._backgroundcolour = wx.WHITE
+
+ if tbstyle == TB_COMPLEX:
+ self.sizer = wx.BoxSizer(wx.VERTICAL)
+ else:
+ self._staticbitmap = None
+
+ if self._windowstyle == TB_CAPTION:
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.SetTitle("")
+
+ if scrollType == TB_SCR_TYPE_FADE and not self.CanSetTransparent():
+ import warnings
+ warnings.warn("The style ``TB_SCR_TYPE_FADE`` is not supported on this platform.")
+ scrollType = TB_SCR_TYPE_DU
+
+ self._scrollType = scrollType
+
+ if self._closingstyle & TB_ONCLICK and self._windowstyle != TB_CAPTION:
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
+
+ self._bottomright = wx.Point(wx.GetDisplaySize().GetWidth(),
+ wx.GetDisplaySize().GetHeight())
+
+ self.SetDimensions(self._bottomright.x, self._bottomright.y,
+ framesize.GetWidth(), framesize.GetHeight())
+
+ self._scrollTimer = wx.Timer(self, -1)
+ self._alphaTimer = wx.Timer(self, -1)
+
+ self.Bind(wx.EVT_TIMER, self.OnScrollTimer, self._scrollTimer)
+ self.Bind(wx.EVT_TIMER, self.AlphaCycle, self._alphaTimer)
+
+ if not self._tbstyle & TB_COMPLEX:
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+
+ def OnClose(self, event):
+ """
+ Handles the ``wx.EVT_CLOSE`` event for :class:`ToasterBoxWindow`.
+
+ :param `event`: a :class:`CloseEvent` event to be processed.
+ """
+
+ self.NotifyTimer(None)
+ event.Skip()
+
+
+ def OnMouseDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`ToasterBoxWindow`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self.NotifyTimer(None)
+ event.Skip()
+
+
+ def SetPopupBitmap(self, bitmap=None):
+ """
+ Sets the :class:`ToasterBox` background image.
+
+ :param `bitmap`: a valid :class:`Bitmap` object. If defaulted to ``None``, then
+ no background bitmap is used.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ if bitmap is None:
+ self._staticbitmap = None
+ else:
+ bitmap = bitmap.ConvertToImage()
+ xsize, ysize = self.GetSize()
+ bitmap = bitmap.Scale(xsize, ysize)
+ self._staticbitmap = bitmap.ConvertToBitmap()
+
+
+ def SetPopupSize(self, size):
+ """
+ Sets the :class:`ToasterBox` size.
+
+ :param `size`: the new control size, an instance of :class:`Size`.
+ """
+
+ self.SetDimensions(self._bottomright.x, self._bottomright.y, size[0], size[1])
+
+
+ def SetPopupPosition(self, pos):
+ """
+ Sets the :class:`ToasterBox` position on screen.
+
+ :param `pos`: the widget position, an instance of :class:`Point`.
+ """
+
+ self._bottomright = wx.Point(pos[0] + self.GetSize().GetWidth(),
+ pos[1] + self.GetSize().GetHeight())
+ self._dialogtop = pos
+
+
+ def SetPopupPositionByInt(self, pos):
+ """
+ Sets the :class:`ToasterBox` position on screen, at one of the screen corners.
+
+ :param `pos`: an integer specifying the screen corner, namely:
+
+ ============= ========================================
+ Corner Number Position
+ ============= ========================================
+ 0 Top left screen corner
+ 1 Top right screen corner
+ 2 Bottom left screen corner
+ 3 Bottom right screen corner
+ ============= ========================================
+
+ """
+
+ w, h = wx.GetDisplaySize()
+ self._bottomright = wx.Point(w, h)
+
+ # top left
+ if pos == 0:
+ popupposition = wx.Point(0, 0)
+ # top right
+ elif pos == 1:
+ popupposition = wx.Point(w - self._popupsize[0], 0)
+ # bottom left
+ elif pos == 2:
+ popupposition = wx.Point(0, h - self._popupsize[1])
+ # bottom right
+ elif pos == 3:
+ popupposition = wx.Point(self._bottomright.x - self._popupsize[0],
+ self._bottomright.y - self._popupsize[1])
+
+ self._bottomright = wx.Point(popupposition.x + self._popupsize[0],
+ popupposition.y + self._popupsize[1])
+
+ self._dialogtop = popupposition
+
+
+ def SetPopupPauseTime(self, pausetime):
+ """
+ Sets the time after which the :class:`ToasterBox` is destroyed (linger).
+
+ :param `pausetime`: the delay after which the control is destroyed, in seconds.
+ """
+
+ self._pausetime = pausetime
+
+
+ def SetPopupScrollSpeed(self, speed):
+ """
+ Sets the :class:`ToasterBox` scroll speed.
+
+ :param `speed`: it is the pause time (in milliseconds) for every step in the
+ :meth:`~ToasterBoxWindow.ScrollUp` method.
+ """
+
+ self._sleeptime = speed
+
+
+ def AddPanel(self, panel):
+ """
+ Adds a panel to the :class:`ToasterBox`.
+
+ :param `panel`: an instance of :class:`Window`.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_COMPLEX`` style.
+ """
+
+ if not self._tbstyle & TB_COMPLEX:
+ raise Exception("\nERROR: Panel Can Not Be Added When Using TB_SIMPLE ToasterBox Style")
+
+ self.sizer.Add(panel, 1, wx.EXPAND)
+ self.SetSizer(self.sizer)
+ self.Layout()
+
+ if self._closingstyle & TB_ONCLICK and self._windowstyle != TB_CAPTION:
+ panel.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
+
+
+ def SetPopupText(self, text):
+ """
+ Sets the :class:`ToasterBox` text label.
+
+ :param `text`: the widget label.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ self._popuptext = text
+
+
+ def SetPopupTextFont(self, font):
+ """
+ Sets the :class:`ToasterBox` text font.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, then
+ a simple generic font will be generated.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ self._textfont = font
+
+
+ def GetPopupText(self):
+ """
+ Returns the :class:`ToasterBox` text.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ return self._popuptext
+
+
+ def Play(self):
+ """ Creates the :class:`ToasterBoxWindow`, that does all the job. """
+
+ # do some checks to make sure this window is valid
+ if self._bottomright.x < 1 or self._bottomright.y < 1:
+ return False
+
+ if self.GetSize().GetWidth() < 50 or self.GetSize().GetWidth() < 50:
+ # toasterbox launches into a endless loop for some reason
+ # when you try to make the window too small.
+ return False
+
+ self._direction = wx.UP
+ self.SetupPositions()
+ self.ScrollUp()
+ timerid = wx.NewId()
+ self.showtime = wx.Timer(self, timerid)
+ self.showtime.Start(self._pausetime)
+ self.Bind(wx.EVT_TIMER, self.NotifyTimer, id=timerid)
+
+ return True
+
+
+ def NotifyTimer(self, event):
+ """ Hides gradually the :class:`ToasterBoxWindow`. """
+
+ if self._scrollType != TB_SCR_TYPE_FADE:
+ self.showtime.Stop()
+ del self.showtime
+
+ self._direction = wx.DOWN
+ self.SetupPositions()
+
+ self.ScrollDown()
+
+
+ def SetPopupBackgroundColour(self, colour):
+ """
+ Sets the :class:`ToasterBox` background colour.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, then
+ the background colour will be white.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ self.SetBackgroundColour(colour)
+ self._backgroundcolour = colour
+
+
+ def SetPopupTextColour(self, colour):
+ """
+ Sets the :class:`ToasterBox` foreground colour.
+
+ :param `colour`: a valid :class:`Colour` object. If defaulted to ``None``, then
+ the background colour will be black.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ self._textcolour = colour
+
+
+ def SetUseFocus(self, focus, originalfocus):
+ """
+ If `focus` is ``True``, Instructs :class:`ToasterBoxWindow` to steal the focus from the
+ parent application, otherwise it returns the focus to the original owner.
+
+ :param `focus`: ``True`` to set the focus on :class:`ToasterBoxWindow`, ``False`` to
+ return it to the original owner;
+ :param `originalfocus`: an instance of :class:`Window`, representing a pointer to
+ the window which originally had the focus
+ """
+
+ self._usefocus = focus
+ self._originalfocus = originalfocus
+
+
+ def OnScrollTimer(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`ToasterBoxWindow` scrolling up/down.
+
+ :param `event`: a :class:`TimerEvent` event to be processed.
+ """
+
+ if self._direction == wx.UP:
+ self.TearUp()
+ else:
+ self.TearDown()
+
+
+ def TearUp(self):
+ """ Scrolls the :class:`ToasterBox` up, which means gradually showing it. """
+
+ self._windowsize = self._windowsize + self._step
+ step = self._currentStep
+
+ if step < self._dialogtop[1]:
+ step = self._dialogtop[1]
+
+ # checking the type of the scroll (from up to down or from down to up)
+ if self._scrollType == TB_SCR_TYPE_UD:
+ dimY = self._dialogtop[1]
+ elif self._scrollType == TB_SCR_TYPE_DU:
+ dimY = step
+
+ self.SetDimensions(self._dialogtop[0], dimY, self.GetSize().GetWidth(), self._windowsize)
+
+ self.Refresh(False)
+
+ self._currentStep += self._scrollStep
+
+ if self._currentStep not in range(self._start, self._stop, self._scrollStep):
+ self._scrollTimer.Stop()
+ self.Update()
+
+ if self._tbstyle == TB_SIMPLE:
+ self.DrawText()
+
+ if self._usefocus:
+ self.SetFocus()
+ else:
+ self._originalfocus.SetFocus()
+
+
+ def TearDown(self):
+ """ Scrolls the :class:`ToasterBox` down, which means gradually hiding it. """
+
+ self._windowsize = self._windowsize - self._step
+ step = self._currentStep
+
+ if step > self._bottomright.y:
+ step = self._bottomright.y
+
+ if self._windowsize > 0:
+ # checking the type of the scroll (from up to down or from down to up)
+ if self._scrollType == TB_SCR_TYPE_UD:
+ dimY = self._dialogtop[1]
+ elif self._scrollType == TB_SCR_TYPE_DU:
+ dimY = step
+
+ self.SetDimensions(self._dialogtop[0], dimY,
+ self.GetSize().GetWidth(), self._windowsize)
+
+ self.Update()
+ self.Refresh()
+
+ self._currentStep += self._scrollStep
+
+ else:
+ self._scrollTimer.Stop()
+ self.Hide()
+ if self._parent2:
+ self._parent2.Notify()
+
+
+ def SetupPositions(self):
+ """ Sets up the position, size and scrolling step for :class:`ToasterBoxWindow`. """
+
+ if self._scrollType == TB_SCR_TYPE_FADE:
+ self.SetPosition(wx.Point(*self._dialogtop))
+ return
+
+ if self._direction == wx.UP:
+ # walk the Y value up in a raise motion
+ self._xpos = self.GetPosition().x
+ self._ypos = self._bottomright[1]
+ self._windowsize = 0
+
+ # checking the type of the scroll (from up to down or from down to up)
+ if self._scrollType == TB_SCR_TYPE_UD:
+ self._start = self._dialogtop[1]
+ self._stop = self._ypos
+ self._scrollStep = self._step
+ elif self._scrollType == TB_SCR_TYPE_DU:
+ self._start = self._ypos
+ self._stop = self._dialogtop[1]
+ self._scrollStep = -self._step
+
+ else:
+
+ # walk down the Y value
+ self._windowsize = self.GetSize().GetHeight()
+
+ # checking the type of the scroll (from up to down or from down to up)
+ if self._scrollType == TB_SCR_TYPE_UD:
+ self._start = self._bottomright.y
+ self._stop = self._dialogtop[1]
+ self._scrollStep = -self._step
+ elif self._scrollType == TB_SCR_TYPE_DU:
+ self._start = self._dialogtop[1]
+ self._stop = self._bottomright.y
+ self._scrollStep = self._step
+
+ self._currentStep = self._start
+
+
+ def ScrollUp(self):
+ """ Scrolls the :class:`ToasterBox` up, which means gradually showing it. """
+
+ if self._scrollType == TB_SCR_TYPE_FADE:
+ self._amount = 0
+ self._delta = 5
+ self.SetSize(self.GetSize())
+ self._alphaTimer.Start(self._sleeptime)
+ else:
+ self.Show(True)
+ self._scrollTimer.Start(self._sleeptime)
+
+
+ def ScrollDown(self):
+ """ Scrolls the :class:`ToasterBox` down, which means gradually hiding it. """
+
+ if self._scrollType == TB_SCR_TYPE_FADE:
+ self._amount = 255
+ self._delta = -5
+ self._alphaTimer.Start(self._sleeptime)
+ else:
+ self._scrollTimer.Start(self._sleeptime)
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`ToasterBoxWindow`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+
+ :note: This event is handled and processed only if the style ``TB_SIMPLE`` is
+ given to :class:`ToasterBox`.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+ self.DrawText(dc)
+
+
+ def DrawText(self, dc=None):
+ """
+ Draws the text label for a :class:`ToasterBox` with ``TB_SIMPLE`` style set.
+
+ :param `dc`: an instance of :class:`DC`. If defaulted to ``None``, a :class:`ClientDC`
+ will be created on the fly.
+ """
+
+ if dc is None:
+ dc = wx.ClientDC(self)
+
+ dc.SetBackground(wx.Brush(self._backgroundcolour))
+ dc.Clear()
+
+ if self._staticbitmap:
+ dc.DrawBitmap(self._staticbitmap, 0, 0)
+ dc.SetFont(self._textfont)
+ dc.SetTextForeground(self._textcolour)
+
+ if not hasattr(self, "text_coords"):
+ self._getTextCoords(dc)
+ dc.DrawTextList(*self.text_coords)
+
+
+ def AlphaCycle(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`ToasterBoxWindow`.
+
+ :param `event`: a :class:`TimerEvent` event to be processed.
+ """
+
+ # Increase (or decrease) the alpha channel
+ self._amount += self._delta
+
+ if self._tbstyle == TB_SIMPLE:
+ self.Refresh(False)
+
+ if self._amount > 255 or self._amount < 0:
+ # We're done, stop the timer
+ self._alphaTimer.Stop()
+
+ if self._amount < 0:
+ self.Hide()
+ if self._parent2:
+ self._parent2.Notify()
+
+ elif self._amount > 255:
+ if self._usefocus:
+ self.SetFocus()
+ else:
+ self._originalfocus.SetFocus()
+
+ return
+
+ # Make the ToasterBoxWindow more or less transparent
+ self.MakeWindowTransparent(self._amount)
+ if not self.IsShown():
+ self.Show()
+
+
+ def MakeWindowTransparent(self, amount):
+ """
+ Makes the :class:`ToasterBoxWindow` window transparent.
+
+ :param `amount`: the alpha channel value.
+ """
+
+ if not self.CanSetTransparent():
+ return
+
+ self.SetTransparent(amount)
+
+
+ def _getTextCoords(self, dc):
+ """
+ Draw the user specified text.
+
+ :param `dc`: an instance of :class:`DC`.
+
+ :note: Use this method only for a :class:`ToasterBox` created with the ``TB_SIMPLE`` style.
+ """
+
+ # border from sides and top to text (in pixels)
+ border = 7
+ # how much space between text lines
+ textPadding = 2
+
+ pText = self.GetPopupText()
+
+ max_len = len(pText)
+
+ tw, th = self._parent2._popupsize
+
+ if self._windowstyle == TB_CAPTION:
+ th = th - 20
+
+ while 1:
+ lines = textwrap.wrap(pText, max_len)
+
+ for line in lines:
+ w, h = dc.GetTextExtent(line)
+ if w > tw - border * 2:
+ max_len -= 1
+ break
+ else:
+ break
+
+ fh = 0
+ for line in lines:
+ w, h = dc.GetTextExtent(line)
+ fh += h + textPadding
+ y = (th - fh) / 2; coords = []
+
+ for line in lines:
+ w, h = dc.GetTextExtent(line)
+ x = (tw - w) / 2
+ coords.append((x, y))
+ y += h + textPadding
+
+ self.text_coords = (lines, coords)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ultimatelistctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ultimatelistctrl.py
new file mode 100644
index 0000000..00a8252
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/ultimatelistctrl.py
@@ -0,0 +1,13726 @@
+# --------------------------------------------------------------------------------- #
+# ULTIMATELISTCTRL wxPython IMPLEMENTATION
+# Inspired by and heavily based on the wxWidgets C++ generic version of wxListCtrl.
+#
+# Andrea Gavana, @ 08 May 2009
+# Latest Revision: 30 Jul 2014, 21.00 GMT
+#
+#
+# TODO List
+#
+# 1) Subitem selection;
+# 2) Watermark? (almost, does not work very well :-( );
+# 3) Groups? (Maybe, check ObjectListView);
+# 4) Scrolling items as headers and footers;
+# 5) Alpha channel for text/background of items;
+# 6) Custom renderers for headers/footers (done);
+# 7) Fading in and out on mouse motion (a la Windows Vista Aero);
+# 8) Sub-text for headers/footers (grey text below the header/footer text);
+# 9) Fixing the columns to the left or right side of the control layout;
+# 10) Skins for header and scrollbars (implemented for headers/footers).
+#
+#
+# For all kind of problems, requests of enhancements and bug reports, please
+# write to me at:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, obviously, to the wxPython mailing list!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------------- #
+
+
+"""
+Description
+===========
+
+UltimateListCtrl is a class that mimics the behaviour of :class:`ListCtrl`, with almost
+the same base functionalities plus some more enhancements. This class does
+not rely on the native control, as it is a full owner-drawn list control.
+
+In addition to the standard :class:`ListCtrl` behaviour this class supports:
+
+
+Appearance
+==========
+
+* Multiple images for items/subitems;
+* Images can be of any size and not limited to a single specific pair of `width`, `height`
+ as it is the case of :class:`ImageList`. Simply use :class:`PyImageList` instead of :class:`ImageList`
+ to add your images.
+* Font, colour, background, custom renderers and formatting for items and subitems;
+* Ability to add persistent data to an item using meth:~UltimateListCtrl.SetItemPyData` and meth:~UltimateListCtrl.GetItemPyData`:
+ the data can be any Python object and not necessarily an integer as in :class:`ListCtrl`;
+* CheckBox-type items and subitems;
+* RadioButton-type items and subitems;
+* Overflowing items/subitems, a la :class:`grid.Grid`, i.e. an item/subitem may overwrite neighboring
+ items/subitems if its text would not normally fit in the space allotted to it;
+* Hyperlink-type items and subitems: they look like an hyperlink, with the proper mouse
+ cursor on hovering;
+* Multiline text items and subitems;
+* Variable row heights depending on the item/subitem kind/text/window;
+* User defined item/subitem renderers: these renderer classes **must** implement the methods
+ `DrawSubItem`, `GetLineHeight` and `GetSubItemWidth` (see the demo);
+* Enabling/disabling items (together with their plain or grayed out icons);
+* Whatever non-toplevel widget can be attached next to an item/subitem;
+* Column headers are fully customizable in terms of icons, colour, font, alignment etc...;
+* Column headers can have their own checkbox/radiobutton;
+* Column footers are fully customizable in terms of icons, colour, font, alignment etc...;
+* Column footers can have their own checkbox/radiobutton;
+* Ability to hide/show columns;
+* Default selection style, gradient (horizontal/vertical) selection style and Windows
+ Vista selection style.
+
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+Usage
+=====
+
+Usage example::
+
+ import sys
+
+ import wx
+ import wx.lib.agw.ultimatelistctrl as ULC
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self):
+
+ wx.Frame.__init__(self, parent, -1, "UltimateListCtrl Demo")
+
+ list = ULC.UltimateListCtrl(self, wx.ID_ANY, agwStyle=wx.LC_REPORT|wx.LC_VRULES|wx.LC_HRULES|wx.LC_SINGLE_SEL)
+
+ list.InsertColumn(0, "Column 1")
+ list.InsertColumn(1, "Column 2")
+
+ index = list.InsertStringItem(sys.maxint, "Item 1")
+ list.SetStringItem(index, 1, "Sub-item 1")
+
+ index = list.InsertStringItem(sys.maxint, "Item 2")
+ list.SetStringItem(index, 1, "Sub-item 2")
+
+ choice = wx.Choice(list, -1, choices=["one", "two"])
+ index = list.InsertStringItem(sys.maxint, "A widget")
+
+ list.SetItemWindow(index, 1, choice, expand=True)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(list, 1, wx.EXPAND)
+ self.SetSizer(sizer)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+
+Window Styles
+=============
+
+This class supports the following window styles:
+
+=============================== =========== ====================================================================================================
+Window Styles Hex Value Description
+=============================== =========== ====================================================================================================
+``ULC_VRULES`` 0x1 Draws light vertical rules between rows in report mode.
+``ULC_HRULES`` 0x2 Draws light horizontal rules between rows in report mode.
+``ULC_ICON`` 0x4 Large icon view, with optional labels.
+``ULC_SMALL_ICON`` 0x8 Small icon view, with optional labels.
+``ULC_LIST`` 0x10 Multicolumn list view, with optional small icons. Columns are computed automatically, i.e. you don't set columns as in ``ULC_REPORT``. In other words, the list wraps, unlike a :class:`ListBox`.
+``ULC_REPORT`` 0x20 Single or multicolumn report view, with optional header.
+``ULC_ALIGN_TOP`` 0x40 Icons align to the top. Win32 default, Win32 only.
+``ULC_ALIGN_LEFT`` 0x80 Icons align to the left.
+``ULC_AUTOARRANGE`` 0x100 Icons arrange themselves. Win32 only.
+``ULC_VIRTUAL`` 0x200 The application provides items text on demand. May only be used with ``ULC_REPORT``.
+``ULC_EDIT_LABELS`` 0x400 Labels are editable: the application will be notified when editing starts.
+``ULC_NO_HEADER`` 0x800 No header in report mode.
+``ULC_NO_SORT_HEADER`` 0x1000 No Docs.
+``ULC_SINGLE_SEL`` 0x2000 Single selection (default is multiple).
+``ULC_SORT_ASCENDING`` 0x4000 Sort in ascending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
+``ULC_SORT_DESCENDING`` 0x8000 Sort in descending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
+``ULC_TILE`` 0x10000 Each item appears as a full-sized icon with a label of one or more lines beside it (partially implemented).
+``ULC_NO_HIGHLIGHT`` 0x20000 No highlight when an item is selected.
+``ULC_STICKY_HIGHLIGHT`` 0x40000 Items are selected by simply hovering on them, with no need to click on them.
+``ULC_STICKY_NOSELEVENT`` 0x80000 Don't send a selection event when using ``ULC_STICKY_HIGHLIGHT`` style.
+``ULC_SEND_LEFTCLICK`` 0x100000 Send a left click event when an item is selected.
+``ULC_HAS_VARIABLE_ROW_HEIGHT`` 0x200000 The list has variable row heights.
+``ULC_AUTO_CHECK_CHILD`` 0x400000 When a column header has a checkbox associated, auto-check all the subitems in that column.
+``ULC_AUTO_TOGGLE_CHILD`` 0x800000 When a column header has a checkbox associated, toggle all the subitems in that column.
+``ULC_AUTO_CHECK_PARENT`` 0x1000000 Only meaningful foe checkbox-type items: when an item is checked/unchecked its column header item is checked/unchecked as well.
+``ULC_SHOW_TOOLTIPS`` 0x2000000 Show tooltips for ellipsized items/subitems (text too long to be shown in the available space) containing the full item/subitem text.
+``ULC_HOT_TRACKING`` 0x4000000 Enable hot tracking of items on mouse motion.
+``ULC_BORDER_SELECT`` 0x8000000 Changes border colour whan an item is selected, instead of highlighting the item.
+``ULC_TRACK_SELECT`` 0x10000000 Enables hot-track selection in a list control. Hot track selection means that an item is automatically selected when the cursor remains over the item for a certain period of time. The delay is retrieved on Windows using the `win32api` call `win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME)`, and is defaulted to 400ms on other platforms. This style applies to all views of `UltimateListCtrl`.
+``ULC_HEADER_IN_ALL_VIEWS`` 0x20000000 Show column headers in all view modes.
+``ULC_NO_FULL_ROW_SELECT`` 0x40000000 When an item is selected, the only the item in the first column is highlighted.
+``ULC_FOOTER`` 0x80000000 Show a footer too (only when header is present).
+``ULC_USER_ROW_HEIGHT`` 0x100000000 Allows to set a custom row height (one value for all the items, only in report mode).
+=============================== =========== ====================================================================================================
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+======================================== ====================================================================================================
+Event Name Description
+======================================== ====================================================================================================
+``EVT_LIST_BEGIN_DRAG`` Begin dragging with the left mouse button.
+``EVT_LIST_BEGIN_RDRAG`` Begin dragging with the right mouse button.
+``EVT_LIST_BEGIN_LABEL_EDIT`` Begin editing a label. This can be prevented by calling `Veto()`.
+``EVT_LIST_END_LABEL_EDIT`` Finish editing a label. This can be prevented by calling `Veto()`.
+``EVT_LIST_DELETE_ITEM`` An item was deleted.
+``EVT_LIST_DELETE_ALL_ITEMS`` All items were deleted.
+``EVT_LIST_KEY_DOWN`` A key has been pressed.
+``EVT_LIST_INSERT_ITEM`` An item has been inserted.
+``EVT_LIST_COL_CLICK`` A column (`m_col`) has been left-clicked.
+``EVT_LIST_COL_RIGHT_CLICK`` A column (`m_col`) has been right-clicked.
+``EVT_LIST_COL_BEGIN_DRAG`` The user started resizing a column - can be vetoed.
+``EVT_LIST_COL_END_DRAG`` The user finished resizing a column.
+``EVT_LIST_COL_DRAGGING`` The divider between columns is being dragged.
+``EVT_LIST_ITEM_SELECTED`` The item has been selected.
+``EVT_LIST_ITEM_DESELECTED`` The item has been deselected.
+``EVT_LIST_ITEM_RIGHT_CLICK`` The right mouse button has been clicked on an item.
+``EVT_LIST_ITEM_MIDDLE_CLICK`` The middle mouse button has been clicked on an item.
+``EVT_LIST_ITEM_ACTIVATED`` The item has been activated (``ENTER`` or double click).
+``EVT_LIST_ITEM_FOCUSED`` The currently focused item has changed.
+``EVT_LIST_CACHE_HINT`` Prepare cache for a virtual list control.
+``EVT_LIST_ITEM_CHECKING`` An item/subitem is being checked.
+``EVT_LIST_ITEM_CHECKED`` An item/subitem has been checked.
+``EVT_LIST_COL_CHECKING`` A column header is being checked.
+``EVT_LIST_COL_CHECKED`` A column header has being checked.
+``EVT_LIST_FOOTER_CHECKING`` A column footer is being checked.
+``EVT_LIST_FOOTER_CHECKED`` A column footer has being checked.
+``EVT_LIST_ITEM_HYPERLINK`` An hyperlink item has been clicked.
+``EVT_LIST_FOOTER_CLICK`` The user left-clicked on a column footer.
+``EVT_LIST_FOOTER_RIGHT_CLICK`` The user right-clicked on a column footer.
+``EVT_LIST_ITEM_LEFT_CLICK`` Send a left-click event after an item is selected.
+``EVT_LIST_END_DRAG`` Notify an end-drag operation.
+======================================== ====================================================================================================
+
+
+Supported Platforms
+===================
+
+UltimateListCtrl has been tested on the following platforms:
+ * Windows (Windows XP);
+
+
+License And Version
+===================
+
+UltimateListCtrl is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 30 Jul 2014, 21.00 GMT
+
+Version 0.8
+
+"""
+
+import wx
+import math
+import bisect
+import types
+import zlib
+import cStringIO
+
+from wx.lib.expando import ExpandoTextCtrl
+
+# Version Info
+__version__ = "0.8"
+
+# wxPython version string
+_VERSION_STRING = wx.VERSION_STRING
+
+# ----------------------------------------------------------------------------
+# UltimateListCtrl constants
+# ----------------------------------------------------------------------------
+
+# style flags
+ULC_VRULES = wx.LC_VRULES
+""" Draws light vertical rules between rows in report mode. """
+ULC_HRULES = wx.LC_HRULES
+""" Draws light horizontal rules between rows in report mode. """
+ULC_ICON = wx.LC_ICON
+ULC_SMALL_ICON = wx.LC_SMALL_ICON
+ULC_LIST = wx.LC_LIST
+ULC_REPORT = wx.LC_REPORT
+ULC_TILE = 0x10000
+
+ULC_ALIGN_TOP = wx.LC_ALIGN_TOP
+ULC_ALIGN_LEFT = wx.LC_ALIGN_LEFT
+ULC_AUTOARRANGE = wx.LC_AUTOARRANGE
+ULC_VIRTUAL = wx.LC_VIRTUAL
+ULC_EDIT_LABELS = wx.LC_EDIT_LABELS
+ULC_NO_HEADER = wx.LC_NO_HEADER
+ULC_NO_SORT_HEADER = wx.LC_NO_SORT_HEADER
+ULC_SINGLE_SEL = wx.LC_SINGLE_SEL
+ULC_SORT_ASCENDING = wx.LC_SORT_ASCENDING
+ULC_SORT_DESCENDING = wx.LC_SORT_DESCENDING
+
+ULC_NO_HIGHLIGHT = 0x20000
+ULC_STICKY_HIGHLIGHT = 0x40000
+ULC_STICKY_NOSELEVENT = 0x80000
+ULC_SEND_LEFTCLICK = 0x100000
+ULC_HAS_VARIABLE_ROW_HEIGHT = 0x200000
+
+ULC_AUTO_CHECK_CHILD = 0x400000 # only meaningful for checkboxes
+ULC_AUTO_TOGGLE_CHILD = 0x800000 # only meaningful for checkboxes
+ULC_AUTO_CHECK_PARENT = 0x1000000 # only meaningful for checkboxes
+ULC_SHOW_TOOLTIPS = 0x2000000 # shows tooltips on items with ellipsis (...)
+ULC_HOT_TRACKING = 0x4000000 # enable hot tracking on mouse motion
+ULC_BORDER_SELECT = 0x8000000 # changes border colour whan an item is selected, instead of highlighting the item
+ULC_TRACK_SELECT = 0x10000000 # Enables hot-track selection in a list control. Hot track selection means that an item
+ # is automatically selected when the cursor remains over the item for a certain period
+ # of time. The delay is retrieved on Windows using the win32api call
+ # win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME), and is defaulted to 400ms
+ # on other platforms. This style applies to all styles of UltimateListCtrl.
+ULC_HEADER_IN_ALL_VIEWS = 0x20000000 # Show column headers in all view modes
+ULC_NO_FULL_ROW_SELECT = 0x40000000 # When an item is selected, the only the item in the first column is highlighted
+ULC_FOOTER = 0x80000000 # Show a footer too (only when header is present)
+ULC_USER_ROW_HEIGHT = 0x100000000 # Allows to set a custom row height (one value for all the items, only in report mode).
+
+ULC_MASK_TYPE = ULC_ICON | ULC_SMALL_ICON | ULC_LIST | ULC_REPORT | ULC_TILE
+ULC_MASK_ALIGN = ULC_ALIGN_TOP | ULC_ALIGN_LEFT
+ULC_MASK_SORT = ULC_SORT_ASCENDING | ULC_SORT_DESCENDING
+
+# for compatibility only
+ULC_USER_TEXT = ULC_VIRTUAL
+
+# Omitted because
+# (a) too much detail
+# (b) not enough style flags
+# (c) not implemented anyhow in the generic version
+#
+# ULC_NO_SCROLL
+# ULC_NO_LABEL_WRAP
+# ULC_OWNERDRAW_FIXED
+# ULC_SHOW_SEL_ALWAYS
+
+# Mask flags to tell app/GUI what fields of UltimateListItem are valid
+ULC_MASK_STATE = wx.LIST_MASK_STATE
+ULC_MASK_TEXT = wx.LIST_MASK_TEXT
+ULC_MASK_IMAGE = wx.LIST_MASK_IMAGE
+ULC_MASK_DATA = wx.LIST_MASK_DATA
+ULC_SET_ITEM = wx.LIST_SET_ITEM
+ULC_MASK_WIDTH = wx.LIST_MASK_WIDTH
+ULC_MASK_FORMAT = wx.LIST_MASK_FORMAT
+ULC_MASK_FONTCOLOUR = 0x0080
+ULC_MASK_FONT = 0x0100
+ULC_MASK_BACKCOLOUR = 0x0200
+ULC_MASK_KIND = 0x0400
+ULC_MASK_ENABLE = 0x0800
+ULC_MASK_CHECK = 0x1000
+ULC_MASK_HYPERTEXT = 0x2000
+ULC_MASK_WINDOW = 0x4000
+ULC_MASK_PYDATA = 0x8000
+ULC_MASK_SHOWN = 0x10000
+ULC_MASK_RENDERER = 0x20000
+ULC_MASK_OVERFLOW = 0x40000
+ULC_MASK_FOOTER_TEXT = 0x80000
+ULC_MASK_FOOTER_IMAGE = 0x100000
+ULC_MASK_FOOTER_FORMAT = 0x200000
+ULC_MASK_FOOTER_FONT = 0x400000
+ULC_MASK_FOOTER_CHECK = 0x800000
+ULC_MASK_FOOTER_KIND = 0x1000000
+ULC_MASK_TOOLTIP = 0x2000000
+
+# State flags for indicating the state of an item
+ULC_STATE_DONTCARE = wx.LIST_STATE_DONTCARE
+ULC_STATE_DROPHILITED = wx.LIST_STATE_DROPHILITED # MSW only
+ULC_STATE_FOCUSED = wx.LIST_STATE_FOCUSED
+ULC_STATE_SELECTED = wx.LIST_STATE_SELECTED
+ULC_STATE_CUT = wx.LIST_STATE_CUT # MSW only
+ULC_STATE_DISABLED = wx.LIST_STATE_DISABLED # OS2 only
+ULC_STATE_FILTERED = wx.LIST_STATE_FILTERED # OS2 only
+ULC_STATE_INUSE = wx.LIST_STATE_INUSE # OS2 only
+ULC_STATE_PICKED = wx.LIST_STATE_PICKED # OS2 only
+ULC_STATE_SOURCE = wx.LIST_STATE_SOURCE # OS2 only
+
+# Hit test flags, used in HitTest
+ULC_HITTEST_ABOVE = wx.LIST_HITTEST_ABOVE # Above the client area.
+ULC_HITTEST_BELOW = wx.LIST_HITTEST_BELOW # Below the client area.
+ULC_HITTEST_NOWHERE = wx.LIST_HITTEST_NOWHERE # In the client area but below the last item.
+ULC_HITTEST_ONITEMICON = wx.LIST_HITTEST_ONITEMICON # On the bitmap associated with an item.
+ULC_HITTEST_ONITEMLABEL = wx.LIST_HITTEST_ONITEMLABEL # On the label (string) associated with an item.
+ULC_HITTEST_ONITEMRIGHT = wx.LIST_HITTEST_ONITEMRIGHT # In the area to the right of an item.
+ULC_HITTEST_ONITEMSTATEICON = wx.LIST_HITTEST_ONITEMSTATEICON # On the state icon for a tree view item that is in a user-defined state.
+ULC_HITTEST_TOLEFT = wx.LIST_HITTEST_TOLEFT # To the left of the client area.
+ULC_HITTEST_TORIGHT = wx.LIST_HITTEST_TORIGHT # To the right of the client area.
+ULC_HITTEST_ONITEMCHECK = 0x1000 # On the checkbox (if any)
+
+ULC_HITTEST_ONITEM = ULC_HITTEST_ONITEMICON | ULC_HITTEST_ONITEMLABEL | ULC_HITTEST_ONITEMSTATEICON | ULC_HITTEST_ONITEMCHECK
+
+# Flags for GetNextItem (MSW only except ULC_NEXT_ALL)
+ULC_NEXT_ABOVE = wx.LIST_NEXT_ABOVE # Searches for an item above the specified item
+ULC_NEXT_ALL = wx.LIST_NEXT_ALL # Searches for subsequent item by index
+ULC_NEXT_BELOW = wx.LIST_NEXT_BELOW # Searches for an item below the specified item
+ULC_NEXT_LEFT = wx.LIST_NEXT_LEFT # Searches for an item to the left of the specified item
+ULC_NEXT_RIGHT = wx.LIST_NEXT_RIGHT # Searches for an item to the right of the specified item
+
+# Alignment flags for Arrange (MSW only except ULC_ALIGN_LEFT)
+ULC_ALIGN_DEFAULT = wx.LIST_ALIGN_DEFAULT
+ULC_ALIGN_SNAP_TO_GRID = wx.LIST_ALIGN_SNAP_TO_GRID
+
+# Column format (MSW only except ULC_FORMAT_LEFT)
+ULC_FORMAT_LEFT = wx.LIST_FORMAT_LEFT
+ULC_FORMAT_RIGHT = wx.LIST_FORMAT_RIGHT
+ULC_FORMAT_CENTRE = wx.LIST_FORMAT_CENTRE
+ULC_FORMAT_CENTER = ULC_FORMAT_CENTRE
+
+# Autosize values for SetColumnWidth
+ULC_AUTOSIZE = wx.LIST_AUTOSIZE
+ULC_AUTOSIZE_USEHEADER = wx.LIST_AUTOSIZE_USEHEADER # partly supported by generic version
+ULC_AUTOSIZE_FILL = -3
+
+# Flag values for GetItemRect
+ULC_RECT_BOUNDS = wx.LIST_RECT_BOUNDS
+ULC_RECT_ICON = wx.LIST_RECT_ICON
+ULC_RECT_LABEL = wx.LIST_RECT_LABEL
+
+# Flag values for FindItem (MSW only)
+ULC_FIND_UP = wx.LIST_FIND_UP
+ULC_FIND_DOWN = wx.LIST_FIND_DOWN
+ULC_FIND_LEFT = wx.LIST_FIND_LEFT
+ULC_FIND_RIGHT = wx.LIST_FIND_RIGHT
+
+# Items/subitems rect
+ULC_GETSUBITEMRECT_WHOLEITEM = wx.LIST_GETSUBITEMRECT_WHOLEITEM
+
+# ----------------------------------------------------------------------------
+# UltimateListCtrl event macros
+# ----------------------------------------------------------------------------
+
+wxEVT_COMMAND_LIST_BEGIN_DRAG = wx.wxEVT_COMMAND_LIST_BEGIN_DRAG
+wxEVT_COMMAND_LIST_BEGIN_RDRAG = wx.wxEVT_COMMAND_LIST_BEGIN_RDRAG
+wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT = wx.wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
+wxEVT_COMMAND_LIST_END_LABEL_EDIT = wx.wxEVT_COMMAND_LIST_END_LABEL_EDIT
+wxEVT_COMMAND_LIST_DELETE_ITEM = wx.wxEVT_COMMAND_LIST_DELETE_ITEM
+wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS = wx.wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
+wxEVT_COMMAND_LIST_ITEM_SELECTED = wx.wxEVT_COMMAND_LIST_ITEM_SELECTED
+wxEVT_COMMAND_LIST_ITEM_DESELECTED = wx.wxEVT_COMMAND_LIST_ITEM_DESELECTED
+wxEVT_COMMAND_LIST_KEY_DOWN = wx.wxEVT_COMMAND_LIST_KEY_DOWN
+wxEVT_COMMAND_LIST_INSERT_ITEM = wx.wxEVT_COMMAND_LIST_INSERT_ITEM
+wxEVT_COMMAND_LIST_COL_CLICK = wx.wxEVT_COMMAND_LIST_COL_CLICK
+wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK = wx.wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
+wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK = wx.wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
+wxEVT_COMMAND_LIST_ITEM_ACTIVATED = wx.wxEVT_COMMAND_LIST_ITEM_ACTIVATED
+wxEVT_COMMAND_LIST_CACHE_HINT = wx.wxEVT_COMMAND_LIST_CACHE_HINT
+wxEVT_COMMAND_LIST_COL_RIGHT_CLICK = wx.wxEVT_COMMAND_LIST_COL_RIGHT_CLICK
+wxEVT_COMMAND_LIST_COL_BEGIN_DRAG = wx.wxEVT_COMMAND_LIST_COL_BEGIN_DRAG
+wxEVT_COMMAND_LIST_COL_DRAGGING = wx.wxEVT_COMMAND_LIST_COL_DRAGGING
+wxEVT_COMMAND_LIST_COL_END_DRAG = wx.wxEVT_COMMAND_LIST_COL_END_DRAG
+wxEVT_COMMAND_LIST_ITEM_FOCUSED = wx.wxEVT_COMMAND_LIST_ITEM_FOCUSED
+
+wxEVT_COMMAND_LIST_FOOTER_CLICK = wx.NewEventType()
+wxEVT_COMMAND_LIST_FOOTER_RIGHT_CLICK = wx.NewEventType()
+wxEVT_COMMAND_LIST_FOOTER_CHECKING = wx.NewEventType()
+wxEVT_COMMAND_LIST_FOOTER_CHECKED = wx.NewEventType()
+
+wxEVT_COMMAND_LIST_ITEM_LEFT_CLICK = wx.NewEventType()
+wxEVT_COMMAND_LIST_ITEM_CHECKING = wx.NewEventType()
+wxEVT_COMMAND_LIST_ITEM_CHECKED = wx.NewEventType()
+wxEVT_COMMAND_LIST_ITEM_HYPERLINK = wx.NewEventType()
+wxEVT_COMMAND_LIST_END_DRAG = wx.NewEventType()
+wxEVT_COMMAND_LIST_COL_CHECKING = wx.NewEventType()
+wxEVT_COMMAND_LIST_COL_CHECKED = wx.NewEventType()
+
+EVT_LIST_BEGIN_DRAG = wx.EVT_LIST_BEGIN_DRAG
+EVT_LIST_BEGIN_RDRAG = wx.EVT_LIST_BEGIN_RDRAG
+EVT_LIST_BEGIN_LABEL_EDIT = wx.EVT_LIST_BEGIN_LABEL_EDIT
+EVT_LIST_END_LABEL_EDIT = wx.EVT_LIST_END_LABEL_EDIT
+EVT_LIST_DELETE_ITEM = wx.EVT_LIST_DELETE_ITEM
+EVT_LIST_DELETE_ALL_ITEMS = wx.EVT_LIST_DELETE_ALL_ITEMS
+EVT_LIST_KEY_DOWN = wx.EVT_LIST_KEY_DOWN
+EVT_LIST_INSERT_ITEM = wx.EVT_LIST_INSERT_ITEM
+EVT_LIST_COL_CLICK = wx.EVT_LIST_COL_CLICK
+EVT_LIST_COL_RIGHT_CLICK = wx.EVT_LIST_COL_RIGHT_CLICK
+EVT_LIST_COL_BEGIN_DRAG = wx.EVT_LIST_COL_BEGIN_DRAG
+EVT_LIST_COL_END_DRAG = wx.EVT_LIST_COL_END_DRAG
+EVT_LIST_COL_DRAGGING = wx.EVT_LIST_COL_DRAGGING
+EVT_LIST_ITEM_SELECTED = wx.EVT_LIST_ITEM_SELECTED
+EVT_LIST_ITEM_DESELECTED = wx.EVT_LIST_ITEM_DESELECTED
+EVT_LIST_ITEM_RIGHT_CLICK = wx.EVT_LIST_ITEM_RIGHT_CLICK
+EVT_LIST_ITEM_MIDDLE_CLICK = wx.EVT_LIST_ITEM_MIDDLE_CLICK
+EVT_LIST_ITEM_ACTIVATED = wx.EVT_LIST_ITEM_ACTIVATED
+EVT_LIST_ITEM_FOCUSED = wx.EVT_LIST_ITEM_FOCUSED
+EVT_LIST_CACHE_HINT = wx.EVT_LIST_CACHE_HINT
+
+EVT_LIST_ITEM_LEFT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_LEFT_CLICK, 1)
+EVT_LIST_ITEM_CHECKING = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_CHECKING, 1)
+EVT_LIST_ITEM_CHECKED = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_CHECKED, 1)
+EVT_LIST_ITEM_HYPERLINK = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_HYPERLINK, 1)
+EVT_LIST_END_DRAG = wx.PyEventBinder(wxEVT_COMMAND_LIST_END_DRAG, 1)
+EVT_LIST_COL_CHECKING = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_CHECKING, 1)
+EVT_LIST_COL_CHECKED = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_CHECKED, 1)
+
+EVT_LIST_FOOTER_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_FOOTER_CLICK, 1)
+EVT_LIST_FOOTER_RIGHT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_FOOTER_RIGHT_CLICK, 1)
+EVT_LIST_FOOTER_CHECKING = wx.PyEventBinder(wxEVT_COMMAND_LIST_FOOTER_CHECKING, 1)
+EVT_LIST_FOOTER_CHECKED = wx.PyEventBinder(wxEVT_COMMAND_LIST_FOOTER_CHECKED, 1)
+
+# NOTE: If using the wxExtListBox visual attributes works everywhere then this can
+# be removed, as well as the #else case below.
+
+_USE_VISATTR = 0
+
+
+# ----------------------------------------------------------------------------
+# Constants
+# ----------------------------------------------------------------------------
+
+SCROLL_UNIT_X = 15
+SCROLL_UNIT_Y = 15
+
+# the spacing between the lines (in report mode)
+LINE_SPACING = 0
+
+# extra margins around the text label
+EXTRA_WIDTH = 4
+EXTRA_HEIGHT = 4
+
+if wx.Platform == "__WXGTK__":
+ EXTRA_HEIGHT = 6
+
+# margin between the window and the items
+EXTRA_BORDER_X = 2
+EXTRA_BORDER_Y = 2
+
+# offset for the header window
+HEADER_OFFSET_X = 1
+HEADER_OFFSET_Y = 1
+
+# margin between rows of icons in [small] icon view
+MARGIN_BETWEEN_ROWS = 6
+
+# when autosizing the columns, add some slack
+AUTOSIZE_COL_MARGIN = 10
+
+# default and minimal widths for the header columns
+WIDTH_COL_DEFAULT = 80
+WIDTH_COL_MIN = 10
+
+# the space between the image and the text in the report mode
+IMAGE_MARGIN_IN_REPORT_MODE = 5
+
+# the space between the image and the text in the report mode in header
+HEADER_IMAGE_MARGIN_IN_REPORT_MODE = 2
+
+# and the width of the icon, if any
+MARGIN_BETWEEN_TEXT_AND_ICON = 2
+
+# Background Image Style
+_StyleTile = 0
+_StyleStretch = 1
+
+# Windows Vista Colours
+_rgbSelectOuter = wx.Colour(170, 200, 245)
+_rgbSelectInner = wx.Colour(230, 250, 250)
+_rgbSelectTop = wx.Colour(210, 240, 250)
+_rgbSelectBottom = wx.Colour(185, 215, 250)
+_rgbNoFocusTop = wx.Colour(250, 250, 250)
+_rgbNoFocusBottom = wx.Colour(235, 235, 235)
+_rgbNoFocusOuter = wx.Colour(220, 220, 220)
+_rgbNoFocusInner = wx.Colour(245, 245, 245)
+
+# Mouse hover time for track selection
+HOVER_TIME = 400
+if wx.Platform == "__WXMSW__":
+ try:
+ import win32gui, win32con
+ HOVER_TIME = win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME)
+ except ImportError:
+ pass
+
+
+# For PyImageList
+IL_FIXED_SIZE = 0
+IL_VARIABLE_SIZE = 1
+
+# Python integers, to make long types to work with CreateListItem
+INTEGER_TYPES = [types.IntType, types.LongType]
+
+
+# ----------------------------------------------------------------------------
+# Functions
+# ----------------------------------------------------------------------------
+
+# Utility method
+def to_list(input):
+ """
+ Converts the input data into a Python list.
+
+ :param `input`: can be an integer or a Python list (in which case nothing will
+ be done to `input`.
+ """
+
+ if isinstance(input, types.ListType):
+ return input
+ elif isinstance(input, types.IntType):
+ return [input]
+ else:
+ raise Exception("Invalid parameter passed to `to_list`: only integers and list are accepted.")
+
+
+def CheckVariableRowHeight(listCtrl, text):
+ """
+ Checks whether a `text` contains multiline strings and if the `listCtrl` window
+ style is compatible with multiline strings.
+
+ :param `listCtrl`: an instance of :class:`UltimateListCtrl`;
+ :param `text`: the text to analyze.
+ """
+
+ if not listCtrl.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ if "\n" in text:
+ raise Exception("Multiline text items are not allowed without the ULC_HAS_VARIABLE_ROW_HEIGHT style.")
+
+
+def CreateListItem(itemOrId, col):
+ """
+ Creates a new instance of :class:`UltimateListItem`.
+
+ :param `itemOrId`: can be an instance of :class:`UltimateListItem` or an integer;
+ :param `col`: the item column.
+ """
+
+ if type(itemOrId) in INTEGER_TYPES:
+ item = UltimateListItem()
+ item._itemId = itemOrId
+ item._col = col
+ else:
+ item = itemOrId
+
+ return item
+
+
+# ----------------------------------------------------------------------------
+
+def MakeDisabledBitmap(original):
+ """
+ Creates a disabled-looking bitmap starting from the input one.
+
+ :param `original`: an instance of :class:`Bitmap` to be greyed-out.
+ """
+
+ img = original.ConvertToImage()
+ return wx.BitmapFromImage(img.ConvertToGreyscale())
+
+# ----------------------------------------------------------------------------
+
+
+#----------------------------------------------------------------------
+def GetdragcursorData():
+ """ Returns the drag and drop cursor image as a decompressed stream of characters. """
+
+ return zlib.decompress(
+"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\xa2@,\xcf\xc1\
+\x06$9z\xda>\x00)\xce\x02\x8f\xc8b\x06\x06na\x10fd\x985G\x02(\xd8W\xe2\x1aQ\
+\xe2\x9c\x9f\x9b\x9b\x9aW\xc2\x90\xec\x11\xe4\xab\x90\x9cQ\x9a\x97\x9d\x93\
+\x9a\xa7`l\xa4\x90\x99\x9e\x97_\x94\x9a\xc2\xeb\x18\xec\xec\xe9i\xa5\xa0\xa7\
+W\xa5\xaa\x07\x01P:7\x1eH\xe4\xe8\xe9\xd9\x808\x11\xbc\x1e\xae\x11V\n\x06@`\
+\xeehd\n\xa2-\x0c,\x8cA\xb4\x9b\t\x94o\xe2b\x08\xa2\xcd\\L\xdd@\xb4\xab\x85\
+\x993\x886v\xb6p\x02\xd1\x86N\xa6\x16\x12\xf7~\xdf\x05\xbal\xa9\xa7\x8bcH\
+\xc5\x9c3W9\xb9\x1a\x14\x04X/\xec\xfc\xbft\xed\x02\xa5\xf4\xc2m\xfa*<N\x17??\
+\x0frqy\x9c\xd3\xb2f5\xaf\x89\x8f9Gk\xbc\x08\xa7\xbf\x06\x97\x98\x06S\xd8E\
+\xbd\x9cE\xb2\x15\x9da\x89\xe2k\x0f\x9c\xb6|\x1a\xea\x14X\x1d6G\x83E\xe7\x9c\
+\x1dO\xa8\xde\xb6\x84l\x15\x9eS\xcf\xc2tf\x15\xde\xf7\xb5\xb2]\xf0\x96+\xf5@\
+D\x90\x1d\xef19_\xf5\xde5y\xb6+\xa7\xdeZ\xfbA\x9bu\x9f`\xffD\xafYn\xf6\x9eW\
+\xeb>\xb6\x7f\x98\\U\xcb\xf5\xd5\xcb\x9a'\xe7\xf4\xd7\x0b\xba\x9e\xdb\x17E\
+\xfdf\x97Z\xcb\xcc\xc0\xf0\xff?3\xc3\x92\xabN\x8arB\xc7\x8f\x03\x1d\xcc\xe0\
+\xe9\xea\xe7\xb2\xce)\xa1\t\x00B7|\x00" )
+
+
+def GetdragcursorBitmap():
+ """ Returns the drag and drop cursor image as a :class:`Bitmap`. """
+
+ return wx.BitmapFromImage(GetdragcursorImage())
+
+
+def GetdragcursorImage():
+ """ Returns the drag and drop cursor image as a :class:`Image`. """
+
+ stream = cStringIO.StringIO(GetdragcursorData())
+ return wx.ImageFromStream(stream)
+
+
+#-----------------------------------------------------------------------------
+# PyImageList
+#-----------------------------------------------------------------------------
+
+class PyImageList(object):
+ """
+ A :class:`PyImageList` contains a list of images. Images can have masks for
+ transparent drawing, and can be made from a variety of sources including
+ bitmaps and icons.
+
+ :class:`PyImageList` is used in conjunction with :class:`UltimateListCtrl`.
+
+ :note: The main improvements that :class:`PyImageList` introduces is the removal
+ of the limitation of same-size images inside the image list. If you use
+ the style ``IL_VARIABLE_SIZE`` then each image can have any size (in terms
+ of width and height).
+ """
+
+ def __init__(self, width, height, mask=True, initialCount=1, style=IL_VARIABLE_SIZE):
+ """
+ Default class constructor.
+
+ :param `width`: the width of the images in the image list, in pixels (unused
+ if you specify the ``IL_VARIABLE_SIZE`` style;
+ :param `height`: the height of the images in the image list, in pixels (unused
+ if you specify the ``IL_VARIABLE_SIZE`` style;
+ :param `mask`: ``True`` if masks should be created for all images (unused in
+ :class:`PyImageList`);
+ :param `initialCount`: the initial size of the list (unused in :class:`PyImageList`);
+ :param `style`: can be one of the following bits:
+
+ ==================== ===== =================================
+ Style Flag Value Description
+ ==================== ===== =================================
+ ``IL_FIXED_SIZE`` 0 All the images in :class:`PyImageList` have the same size (width, height)
+ ``IL_VARIABLE_SIZE`` 1 Each image can have any size (in terms of width and height)
+ ==================== ===== =================================
+
+ """
+
+ self._width = width
+ self._height = height
+ self._mask = mask
+ self._initialCount = 1
+ self._style = style
+
+ self._images = []
+
+
+ def GetImageCount(self):
+ """ Returns the number of images in the list. """
+
+ return len(self._images)
+
+
+
+ def Add(self, bitmap):
+ """
+ Adds a new image or images using a bitmap.
+
+ :param `bitmap`: a valid :class:`Bitmap` object.
+
+ :return: The new zero-based image index.
+
+ :note: If the bitmap is wider than the images in the list and you are not using
+ the ``IL_VARIABLE_SIZE`` style, then the bitmap will automatically be split
+ into smaller images, each matching the dimensions of the image list.
+ """
+
+ index = len(self._images)
+
+ # Mimic behavior of Windows ImageList_Add that automatically breaks up the added
+ # bitmap into sub-images of the correct size
+
+ if self._style & IL_FIXED_SIZE:
+
+ if self._width > 0 and bitmap.GetWidth() > self._width and \
+ bitmap.GetHeight() >= self._height:
+
+ numImages = bitmap.GetWidth()/self._width
+ for subIndex in xrange(numImages):
+ rect = wx.Rect(self._width * subIndex, 0, self._width, self._height)
+ tmpBmp = bitmap.GetSubBitmap(rect)
+ self._images.append(tmpBmp)
+
+ else:
+
+ self._images.append(bitmap)
+ else:
+
+ self._images.append(bitmap)
+
+ if self._width == 0 and self._height == 0:
+ self._width = bitmap.GetWidth()
+ self._height = bitmap.GetHeight()
+
+ return index
+
+
+ def AddIcon(self, icon):
+ """
+ Adds a new image using an icon.
+
+ :param `icon`: a valid :class:`Icon` object.
+
+ :return: The new zero-based image index.
+
+ :note: If the icon is wider than the images in the list and you are not using
+ the ``IL_VARIABLE_SIZE`` style, then the icon will automatically be split
+ into smaller images, each matching the dimensions of the image list.
+ """
+
+ return self.Add(wx.BitmapFromIcon(icon))
+
+
+ def AddWithColourMask(self, bitmap, maskColour):
+ """
+ Adds a new image or images using a bitmap and a colour mask.
+
+ :param `bitmap`: a valid :class:`Bitmap` object;
+ :param `colour`: an instance of :class:`Colour`, a colour indicating which parts
+ of the image are transparent.
+
+ :return: The new zero-based image index.
+
+ :note: If the bitmap is wider than the images in the list and you are not using
+ the ``IL_VARIABLE_SIZE`` style, then the bitmap will automatically be split
+ into smaller images, each matching the dimensions of the image list.
+ """
+
+ img = bitmap.ConvertToImage()
+ img.SetMaskColour(maskColour.Red(), maskColour.Green(), maskColour.Blue())
+
+ return self.Add(wx.BitmapFromImage(img))
+
+
+ def GetBitmap(self, index):
+ """
+ Returns the bitmap corresponding to the given `index`, or :class:`NullBitmap`
+ if the index is invalid.
+
+ :param `index`: the bitmap index.
+ """
+
+ if index >= len(self._images):
+ return wx.NullBitmap
+
+ return self._images[index]
+
+
+ def GetIcon(self, index):
+ """
+ Returns the icon corresponding to the given `index`, or :class:`NullIcon`
+ if the index is invalid.
+
+ :param `index`: the icon index.
+ """
+
+ if index >= len(self._images):
+ return wx.NullIcon
+
+ return wx.IconFromBitmap(self._images[index])
+
+
+ def Replace(self, index, bitmap):
+ """
+ Replaces the existing image with the new bitmap.
+
+ :param `index`: the index at which the image should be replaced;
+ :param `bitmap`: the new bitmap to add to the image list, an instance of
+ :class:`Bitmap`.
+ """
+
+ if index >= len(self._images):
+ raise Exception("Wrong index in image list")
+
+ self._images[index] = bitmap
+
+ return True
+
+
+ def ReplaceIcon(self, index, icon):
+ """
+ Replaces the existing image with the new icon.
+
+ :param `index`: the index at which the image should be replaced;
+ :param `icon`: the new icon to add to the image list, an instance of
+ :class:`Icon`.
+ """
+
+ return self.Replace(index, wx.BitmapFromIcon(icon))
+
+
+ def Remove(self, index):
+ """
+ Removes the image at the given position.
+
+ :param `index`: the zero-based index of the image to be removed.
+ """
+
+ if index >= len(self._images):
+ raise Exception("Wrong index in image list")
+
+ self._images.pop(index)
+ return True
+
+
+ def RemoveAll(self):
+ """ Removes all the images in the list. """
+
+ self._images = []
+ return True
+
+
+ def GetSize(self, index):
+ """
+ Retrieves the size of an image in the list.
+
+ :param `index`: the zero-based index of the image.
+
+ :return: a tuple of `(width, height)` properties of the chosen bitmap.
+ """
+
+ if index >= len(self._images):
+ raise Exception("Wrong index in image list")
+
+ bmp = self._images[index]
+ return bmp.GetWidth(), bmp.GetHeight()
+
+
+ def Draw(self, index, dc, x, y, flags, solidBackground=True):
+ """
+ Draws a specified image onto a device context.
+
+ :param `index`: the image index, starting from zero;
+ :param `dc`: an instance of :class:`DC`;
+ :param `x`: x position on the device context;
+ :param `y`: y position on the device context;
+ :param `flags`: how to draw the image. A bitlist of a selection of the following:
+
+ ================================= =======================================
+ Flag Paarameter Description
+ ================================= =======================================
+ ``wx.IMAGELIST_DRAW_NORMAL`` Draw the image normally
+ ``wx.IMAGELIST_DRAW_TRANSPARENT`` Draw the image with transparency
+ ``wx.IMAGELIST_DRAW_SELECTED`` Draw the image in selected state
+ ``wx.IMAGELIST_DRAW_FOCUSED`` Draw the image in a focused state
+ ================================= =======================================
+
+ :param `solidBackground`: currently unused.
+ """
+
+ if index >= len(self._images):
+ raise Exception("Wrong index in image list")
+
+ bmp = self._images[index]
+ dc.DrawBitmap(bmp, x, y, (flags & wx.IMAGELIST_DRAW_TRANSPARENT) > 0)
+
+ return True
+
+
+class SelectionStore(object):
+ """
+ SelectionStore is used to store the selected items in the virtual
+ controls, i.e. it is well suited for storing even when the control contains
+ a huge (practically infinite) number of items.
+
+ Of course, internally it still has to store the selected items somehow (as
+ an array currently) but the advantage is that it can handle the selection
+ of all items (common operation) efficiently and that it could be made even
+ smarter in the future (e.g. store the selections as an array of ranges +
+ individual items) without changing its API.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ # the array of items whose selection state is different from default
+ self._itemsSel = []
+ # the default state: normally, False (i.e. off) but maybe set to true if
+ # there are more selected items than non selected ones - this allows to
+ # handle selection of all items efficiently
+ self._defaultState = False
+ # the total number of items we handle
+ self._count = 0
+
+ # special case of SetItemCount(0)
+ def Clear(self):
+ """ Clears the number of selected items. """
+
+ self._itemsSel = []
+ self._count = 0
+ self._defaultState = False
+
+ # return the total number of selected items
+ def GetSelectedCount(self):
+ """ Return the total number of selected items. """
+
+ return (self._defaultState and [self._count - len(self._itemsSel)] or [len(self._itemsSel)])[0]
+
+
+ def IsSelected(self, item):
+ """
+ Returns ``True`` if the given item is selected.
+
+ :param `item`: the item to check for selection state.
+ """
+
+ isSel = item in self._itemsSel
+
+ # if the default state is to be selected, being in m_itemsSel means that
+ # the item is not selected, so we have to inverse the logic
+ return (self._defaultState and [not isSel] or [isSel])[0]
+
+
+ def SelectItem(self, item, select=True):
+ """
+ Selects the given item.
+
+ :param `item`: the item to select;
+ :param `select`: ``True`` to select the item, ``False`` otherwise.
+
+ :return: ``True`` if the items selection really changed.
+ """
+
+ # search for the item ourselves as like this we get the index where to
+ # insert it later if needed, so we do only one search in the array instead
+ # of two (adding item to a sorted array requires a search)
+ index = bisect.bisect_right(self._itemsSel, item)
+ isSel = index < len(self._itemsSel) and self._itemsSel[index] == item
+
+ if select != self._defaultState:
+
+ if item not in self._itemsSel:
+ bisect.insort_right(self._itemsSel, item)
+ return True
+
+ else: # reset to default state
+
+ if item in self._itemsSel:
+ self._itemsSel.remove(item)
+ return True
+
+ return False
+
+
+ def SelectRange(self, itemFrom, itemTo, select=True):
+ """
+ Selects a range of items.
+
+ :param `itemFrom`: the first index of the selection range;
+ :param `itemTo`: the last index of the selection range;
+ :param `select`: ``True`` to select the items, ``False`` otherwise.
+
+ :return: ``True`` and fill the `itemsChanged` array with the indices of items
+ which have changed state if "few" of them did, otherwise return ``False``
+ (meaning that too many items changed state to bother counting them individually).
+ """
+
+ # 100 is hardcoded but it shouldn't matter much: the important thing is
+ # that we don't refresh everything when really few (e.g. 1 or 2) items
+ # change state
+ MANY_ITEMS = 100
+
+ # many items (> half) changed state
+ itemsChanged = []
+
+ # are we going to have more [un]selected items than the other ones?
+ if itemTo - itemFrom > self._count/2:
+
+ if select != self._defaultState:
+
+ # the default state now becomes the same as 'select'
+ self._defaultState = select
+
+ # so all the old selections (which had state select) shouldn't be
+ # selected any more, but all the other ones should
+ selOld = self._itemsSel[:]
+ self._itemsSel = []
+
+ # TODO: it should be possible to optimize the searches a bit
+ # knowing the possible range
+
+ for item in xrange(itemFrom):
+ if item not in selOld:
+ self._itemsSel.append(item)
+
+ for item in xrange(itemTo + 1, self._count):
+ if item not in selOld:
+ self._itemsSel.append(item)
+
+ else: # select == self._defaultState
+
+ # get the inclusive range of items between itemFrom and itemTo
+ count = len(self._itemsSel)
+ start = bisect.bisect_right(self._itemsSel, itemFrom)
+ end = bisect.bisect_right(self._itemsSel, itemTo)
+
+ if itemFrom < start:
+ start = itemFrom
+
+ if start == count or self._itemsSel[start] < itemFrom:
+ start += 1
+
+ if end == count or self._itemsSel[end] > itemTo:
+ end -= 1
+
+ if start <= end:
+
+ # delete all of them (from end to avoid changing indices)
+ for i in xrange(end, start-1, -1):
+ if itemsChanged:
+ if len(itemsChanged) > MANY_ITEMS:
+ # stop counting (see comment below)
+ itemsChanged = []
+ else:
+ itemsChanged.append(self._itemsSel[i])
+
+ self._itemsSel.pop(i)
+ else:
+ self._itemsSel = []
+
+ else: # "few" items change state
+
+ if itemsChanged:
+ itemsChanged = []
+
+ # just add the items to the selection
+ for item in xrange(itemFrom, itemTo+1):
+ if self.SelectItem(item, select) and itemsChanged:
+ itemsChanged.append(item)
+ if len(itemsChanged) > MANY_ITEMS:
+ # stop counting them, we'll just eat gobs of memory
+ # for nothing at all - faster to refresh everything in
+ # this case
+ itemsChanged = []
+
+ # we set it to None if there are many items changing state
+ return itemsChanged
+
+
+ def OnItemDelete(self, item):
+ """
+ Must be called when an item is deleted.
+
+ :param `item`: the item that is being deleted.
+ """
+
+ count = len(self._itemsSel)
+ i = bisect.bisect_right(self._itemsSel, item)
+
+ if i < count and self._itemsSel[i] == item:
+ # this item itself was in m_itemsSel, remove it from there
+ self._itemsSel.pop(i)
+
+ count -= 1
+
+ # and adjust the index of all which follow it
+ while i < count:
+
+ i += 1
+ self._itemsSel[i] -= 1
+
+
+ def SetItemCount(self, count):
+ """
+ Sets the total number of items we handle.
+
+ :param `count`: the total number of items we handle.
+ """
+
+ # forget about all items whose indices are now invalid if the size
+ # decreased
+ if count < self._count:
+ for i in xrange(len(self._itemsSel), 0, -1):
+ if self._itemsSel[i - 1] >= count:
+ self._itemsSel.pop(i - 1)
+
+ # remember the new number of items
+ self._count = count
+
+
+# ----------------------------------------------------------------------------
+# UltimateListItemAttr: a structure containing the visual attributes of an item
+# ----------------------------------------------------------------------------
+
+class UltimateListItemAttr(object):
+ """
+ Represents the attributes (colour, font, ...) of a :class:`UltimateListCtrl`
+ :class:`UltimateListItem`.
+ """
+
+ def __init__(self, colText=wx.NullColour, colBack=wx.NullColour, font=wx.NullFont,
+ enabled=True, footerColText=wx.NullColour, footerColBack=wx.NullColour,
+ footerFont=wx.NullFont):
+ """
+ Default class constructor.
+
+ :param `colText`: the item text colour;
+ :param `colBack`: the item background colour;
+ :param `font`: the item font;
+ :param `enabled`: ``True`` if the item should be enabled, ``False`` if it is disabled;
+ :param `footerColText`: for footer items, the item text colour;
+ :param `footerColBack`: for footer items, the item background colour;
+ :param `footerFont`: for footer items, the item font.
+ """
+
+ self._colText = colText
+ self._colBack = colBack
+ self._font = font
+ self._enabled = enabled
+
+ self._footerColText = footerColText
+ self._footerColBack = footerColBack
+ self._footerFont = footerFont
+
+
+ # setters
+ def SetTextColour(self, colText):
+ """
+ Sets a new text colour.
+
+ :param `colText`: an instance of :class:`Colour`.
+ """
+
+ self._colText = colText
+
+
+ def SetBackgroundColour(self, colBack):
+ """
+ Sets a new background colour.
+
+ :param `colBack`: an instance of :class:`Colour`.
+ """
+
+ self._colBack = colBack
+
+
+ def SetFont(self, font):
+ """
+ Sets a new font for the item.
+
+ :param `font`: an instance of :class:`Font`.
+ """
+
+ self._font = font
+
+
+ def Enable(self, enable=True):
+ """
+ Enables or disables the item.
+
+ :param `enable`: ``True`` to enable the item, ``False`` to disable it.
+ """
+
+ self._enabled = enable
+
+
+ def SetFooterTextColour(self, colText):
+ """
+ Sets a new footer item text colour.
+
+ :param `colText`: an instance of :class:`Colour`.
+ """
+
+ self._footerColText = colText
+
+
+ def SetFooterBackgroundColour(self, colBack):
+ """
+ Sets a new footer item background colour.
+
+ :param `colBack`: an instance of :class:`Colour`.
+ """
+
+ self._footerColBack = colBack
+
+
+ def SetFooterFont(self, font):
+ """
+ Sets a new font for the footer item.
+
+ :param `font`: an instance of :class:`Font`.
+ """
+
+ self._footerFont = font
+
+
+ # accessors
+ def HasTextColour(self):
+ """ Returns ``True`` if the currently set text colour is valid. """
+
+ return self._colText.Ok()
+
+
+ def HasBackgroundColour(self):
+ """ Returns ``True`` if the currently set background colour is valid. """
+
+ return self._colBack.Ok()
+
+
+ def HasFont(self):
+ """ Returns ``True`` if the currently set font is valid. """
+
+ return self._font.Ok()
+
+
+ def HasFooterTextColour(self):
+ """
+ Returns ``True`` if the currently set text colour for the footer item
+ is valid.
+ """
+
+ return self._footerColText.Ok()
+
+
+ def HasFooterBackgroundColour(self):
+ """
+ Returns ``True`` if the currently set background colour for the footer item
+ is valid.
+ """
+
+ return self._footerColBack.Ok()
+
+
+ def HasFooterFont(self):
+ """
+ Returns ``True`` if the currently set font for the footer item
+ is valid.
+ """
+
+ return self._footerFont.Ok()
+
+
+ # getters
+ def GetTextColour(self):
+ """ Returns the currently set text colour. """
+
+ return self._colText
+
+
+ def GetBackgroundColour(self):
+ """ Returns the currently set background colour. """
+
+ return self._colBack
+
+
+ def GetFont(self):
+ """ Returns the currently set item font. """
+
+ return self._font
+
+
+ def GetFooterTextColour(self):
+ """ Returns the currently set text colour for a footer item. """
+
+ return self._footerColText
+
+
+ def GetFooterBackgroundColour(self):
+ """ Returns the currently set background colour for a footer item. """
+
+ return self._footerColBack
+
+
+ def GetFooterFont(self):
+ """ Returns the currently set font for a footer item. """
+
+ return self._footerFont
+
+
+ def IsEnabled(self):
+ """ Returns ``True`` if the item is enabled. """
+
+ return self._enabled
+
+# ----------------------------------------------------------------------------
+# UltimateListItem: the item or column info, used to exchange data with UltimateListCtrl
+# ----------------------------------------------------------------------------
+
+class UltimateListItem(wx.Object):
+ """ This class stores information about a :class:`UltimateListCtrl` item or column. """
+
+ def __init__(self, item=None):
+ """
+ Default class constructor.
+
+ :param `item`: if not ``None``, another instance of :class:`UltimateListItem`.
+ """
+
+ if not item:
+ self.Init()
+ self._attr = None
+ else:
+ self._mask = item._mask # Indicates what fields are valid
+ self._itemId = item._itemId # The zero-based item position
+ self._col = item._col # Zero-based column, if in report mode
+ self._state = item._state # The state of the item
+ self._stateMask = item._stateMask # Which flags of self._state are valid (uses same flags)
+ self._text = item._text # The label/header text
+ self._tooltip = item._tooltip # The label/header tooltip text
+ self._image = item._image[:] # The zero-based indexes into an image list
+ self._data = item._data # App-defined data
+ self._pyData = item._pyData # Python-specific data
+ self._format = item._format # left, right, centre
+ self._width = item._width # width of column
+ self._colour = item._colour # item text colour
+ self._font = item._font # item font
+ self._checked = item._checked # The checking state for the item (if kind > 0)
+ self._kind = item._kind # Whether it is a normal, checkbox-like or a radiobutton-like item
+ self._enabled = item._enabled # Whether the item is enabled or not
+ self._hypertext = item._hypertext # indicates if the item is hypertext
+ self._visited = item._visited # visited state for an hypertext item
+ self._wnd = item._wnd
+ self._windowenabled = item._windowenabled
+ self._windowsize = item._windowsize
+ self._isColumnShown = item._isColumnShown
+ self._customRenderer = item._customRenderer
+ self._overFlow = item._overFlow
+ self._footerChecked = item._footerChecked
+ self._footerFormat = item._footerFormat
+ self._footerImage = item._footerImage
+ self._footerKind = item._footerKind
+ self._footerText = item._footerText
+ self._expandWin = item._expandWin
+ self._attr = None
+
+ # copy list item attributes
+ if item.HasAttributes():
+ self._attr = item.GetAttributes()[:]
+
+ # resetting
+ def Clear(self):
+ """ Resets the item state to the default. """
+
+ self.Init()
+ self._text = ""
+ self.ClearAttributes()
+
+
+ def ClearAttributes(self):
+ """ Deletes the item attributes if they have been stored. """
+
+ if self._attr:
+ del self._attr
+ self._attr = None
+
+ # setters
+ def SetMask(self, mask):
+ """
+ Sets the mask of valid fields.
+
+ :param `mask`: any combination of the following bits:
+
+ ============================ ========= ==============================
+ Mask Bits Hex Value Description
+ ============================ ========= ==============================
+ ``ULC_MASK_STATE`` 0x1 :meth:`~UltimateListItem.GetState` is valid
+ ``ULC_MASK_TEXT`` 0x2 :meth:`~UltimateListItem.GetText` is valid
+ ``ULC_MASK_IMAGE`` 0x4 :meth:`~UltimateListItem.GetImage` is valid
+ ``ULC_MASK_DATA`` 0x8 :meth:`~UltimateListItem.GetData` is valid
+ ``ULC_MASK_WIDTH`` 0x20 :meth:`~UltimateListItem.GetWidth` is valid
+ ``ULC_MASK_FORMAT`` 0x40 :meth:`~UltimateListItem.GetFormat` is valid
+ ``ULC_MASK_FONTCOLOUR`` 0x80 :meth:`~UltimateListItem.GetTextColour` is valid
+ ``ULC_MASK_FONT`` 0x100 :meth:`~UltimateListItem.GetFont` is valid
+ ``ULC_MASK_BACKCOLOUR`` 0x200 :meth:`~UltimateListItem.GetBackgroundColour` is valid
+ ``ULC_MASK_KIND`` 0x400 :meth:`~UltimateListItem.GetKind` is valid
+ ``ULC_MASK_ENABLE`` 0x800 :meth:`~UltimateListItem.IsEnabled` is valid
+ ``ULC_MASK_CHECK`` 0x1000 :meth:`~UltimateListItem.IsChecked` is valid
+ ``ULC_MASK_HYPERTEXT`` 0x2000 :meth:`~UltimateListItem.IsHyperText` is valid
+ ``ULC_MASK_WINDOW`` 0x4000 :meth:`~UltimateListItem.GetWindow` is valid
+ ``ULC_MASK_PYDATA`` 0x8000 :meth:`~UltimateListItem.GetPyData` is valid
+ ``ULC_MASK_SHOWN`` 0x10000 :meth:`~UltimateListItem.IsShown` is valid
+ ``ULC_MASK_RENDERER`` 0x20000 :meth:`~UltimateListItem.GetCustomRenderer` is valid
+ ``ULC_MASK_OVERFLOW`` 0x40000 :meth:`~UltimateListItem.GetOverFlow` is valid
+ ``ULC_MASK_FOOTER_TEXT`` 0x80000 :meth:`~UltimateListItem.GetFooterText` is valid
+ ``ULC_MASK_FOOTER_IMAGE`` 0x100000 :meth:`~UltimateListItem.GetFooterImage` is valid
+ ``ULC_MASK_FOOTER_FORMAT`` 0x200000 :meth:`~UltimateListItem.GetFooterFormat` is valid
+ ``ULC_MASK_FOOTER_FONT`` 0x400000 :meth:`~UltimateListItem.GetFooterFont` is valid
+ ``ULC_MASK_FOOTER_CHECK`` 0x800000 :meth:`~UltimateListItem.IsFooterChecked` is valid
+ ``ULC_MASK_FOOTER_KIND`` 0x1000000 :meth:`~UltimateListItem.GetFooterKind` is valid
+ ============================ ========= ==============================
+
+ """
+
+ self._mask = mask
+
+
+ def SetId(self, id):
+ """
+ Sets the zero-based item position.
+
+ :param `id`: the zero-based item position.
+ """
+
+ self._itemId = id
+
+
+ def SetColumn(self, col):
+ """
+ Sets the zero-based column.
+
+ :param `col`: the zero-based column.
+
+ :note: This method is neaningful only in report mode.
+ """
+
+ self._col = col
+
+
+ def SetState(self, state):
+ """
+ Sets the item state flags.
+
+ :param `state`: any combination of the following bits:
+
+ ============================ ========= ==============================
+ State Bits Hex Value Description
+ ============================ ========= ==============================
+ ``ULC_STATE_DONTCARE`` 0x0 Don't care what the state is
+ ``ULC_STATE_DROPHILITED`` 0x1 The item is highlighted to receive a drop event
+ ``ULC_STATE_FOCUSED`` 0x2 The item has the focus
+ ``ULC_STATE_SELECTED`` 0x4 The item is selected
+ ``ULC_STATE_CUT`` 0x8 The item is in the cut state
+ ``ULC_STATE_DISABLED`` 0x10 The item is disabled
+ ``ULC_STATE_FILTERED`` 0x20 The item has been filtered
+ ``ULC_STATE_INUSE`` 0x40 The item is in use
+ ``ULC_STATE_PICKED`` 0x80 The item has been picked
+ ``ULC_STATE_SOURCE`` 0x100 The item is a drag and drop source
+ ============================ ========= ==============================
+
+ :note: The valid state flags are influenced by the value of the state mask.
+
+ :see: :meth:`~UltimateListItem.SetStateMask`
+ """
+
+ self._mask |= ULC_MASK_STATE
+ self._state = state
+ self._stateMask |= state
+
+
+ def SetStateMask(self, stateMask):
+ """
+ Sets the bitmask that is used to determine which of the state flags are
+ to be set.
+
+ :param `stateMask`: the state bitmask.
+
+ :see: :meth:`~UltimateListItem.SetState` for a list of valid state bits.
+ """
+
+ self._stateMask = stateMask
+
+
+ def SetText(self, text):
+ """
+ Sets the text label for the item.
+
+ :param `text`: the text label for the item.
+ """
+
+ self._mask |= ULC_MASK_TEXT
+ self._text = text
+
+
+ def SetToolTip(self, text):
+ """
+ Sets the tooltip text for the item.
+
+ :param `text`: the tooltip text for the item.
+ """
+ self._mask |= ULC_MASK_TOOLTIP
+ self._tooltip = text
+
+
+ def SetImage(self, image):
+ """
+ Sets the zero-based indexes of the images associated with the item into the
+ image list.
+
+ :param `image`: a Python list with the zero-based indexes of the images
+ associated with the item into the image list.
+ """
+
+ self._mask |= ULC_MASK_IMAGE
+ if image is None:
+ image = []
+
+ self._image = to_list(image)
+
+
+ def SetData(self, data):
+ """
+ Sets client data for the item.
+
+ :param `data`: the client data associated to the item.
+
+ :note: Please note that client data is associated with the item and not
+ with subitems.
+ """
+
+ self._mask |= ULC_MASK_DATA
+ self._data = data
+
+
+ def SetPyData(self, pyData):
+ """
+ Sets data for the item, which can be any Python object.
+
+ :param `data`: any Python object associated to the item.
+
+ :note: Please note that Python data is associated with the item and not
+ with subitems.
+ """
+
+ self._mask |= ULC_MASK_PYDATA
+ self._pyData = pyData
+
+
+ def SetWidth(self, width):
+ """
+ Sets the column width.
+
+ :param `width`: the column width.
+
+ :note: This method is meaningful only for column headers in report mode.
+ """
+
+ self._mask |= ULC_MASK_WIDTH
+ self._width = width
+
+
+ def SetAlign(self, align):
+ """
+ Sets the alignment for the item.
+
+ :param `align`: one of the following bits:
+
+ ============================ ========= ==============================
+ Alignment Bits Hex Value Description
+ ============================ ========= ==============================
+ ``ULC_FORMAT_LEFT`` 0x0 The item is left-aligned
+ ``ULC_FORMAT_RIGHT`` 0x1 The item is right-aligned
+ ``ULC_FORMAT_CENTRE`` 0x2 The item is centre-aligned
+ ``ULC_FORMAT_CENTER`` 0x2 The item is center-aligned
+ ============================ ========= ==============================
+
+ """
+
+ self._mask |= ULC_MASK_FORMAT
+ self._format = align
+
+
+ def SetTextColour(self, colText):
+ """
+ Sets the text colour for the item.
+
+ :param `colText`: a valid :class:`Colour` object.
+ """
+
+ self.Attributes().SetTextColour(colText)
+
+
+ def SetBackgroundColour(self, colBack):
+ """
+ Sets the background colour for the item.
+
+ :param `colBack`: a valid :class:`Colour` object.
+ """
+
+ self.Attributes().SetBackgroundColour(colBack)
+
+
+ def SetFont(self, font):
+ """
+ Sets the font for the item.
+
+ :param `font`: a valid :class:`Font` object.
+ """
+
+ self.Attributes().SetFont(font)
+
+
+ def SetFooterTextColour(self, colText):
+ """
+ Sets the text colour for the footer item.
+
+ :param `colText`: a valid :class:`Colour` object.
+ """
+
+ self.Attributes().SetFooterTextColour(colText)
+
+
+ def SetFooterBackgroundColour(self, colBack):
+ """
+ Sets the background colour for the footer item.
+
+ :param `colBack`: a valid :class:`Colour` object.
+ """
+
+ self.Attributes().SetFooterBackgroundColour(colBack)
+
+
+ def SetFooterFont(self, font):
+ """
+ Sets the font for the footer item.
+
+ :param `font`: a valid :class:`Font` object.
+ """
+
+ self.Attributes().SetFooterFont(font)
+
+
+ def Enable(self, enable=True):
+ """
+ Enables or disables the item.
+
+ :param `enable`: ``True`` to enable the item, ``False`` to disable it.
+ """
+
+ self.Attributes().Enable(enable)
+
+ # accessors
+ def GetMask(self):
+ """
+ Returns a bit mask indicating which fields of the structure are valid.
+
+ :see: :meth:`~UltimateListItem.SetMask` for a list of valid bit masks.
+ """
+
+ return self._mask
+
+
+ def GetId(self):
+ """ Returns the zero-based item position. """
+
+ return self._itemId
+
+
+ def GetColumn(self):
+ """
+ Returns the zero-based column.
+
+ :note: This method is meaningful only in report mode.
+ """
+
+ return self._col
+
+
+ def GetFormat(self):
+ """ Returns the header item format. """
+
+ return self._format
+
+
+ def GetState(self):
+ """
+ Returns a bit field representing the state of the item.
+
+ :see: :meth:`~UltimateListItem.SetState` for a list of valid item states.
+ """
+
+ return self._state & self._stateMask
+
+
+ def GetText(self):
+ """ Returns the label/header text. """
+
+ return self._text
+
+
+ def GetToolTip(self):
+ """ Returns the label/header tooltip. """
+
+ return self._tooltip
+
+
+ def GetImage(self):
+ """
+ Returns a Python list with the zero-based indexes of the images associated
+ with the item into the image list.
+ """
+
+ return self._image
+
+
+ def GetData(self):
+ """
+ Returns client data associated with the control.
+
+ :note: Please note that client data is associated with the item and not
+ with subitems.
+ """
+
+ return self._data
+
+
+ def GetPyData(self):
+ """
+ Returns data for the item, which can be any Python object.
+
+ :note: Please note that Python data is associated with the item and not
+ with subitems.
+ """
+
+ return self._pyData
+
+
+ def GetWidth(self):
+ """
+ Returns the column width.
+
+ :note: This method is meaningful only for column headers in report mode.
+ """
+
+ return self._width
+
+
+ def GetAlign(self):
+ """
+ Returns the alignment for the item.
+
+ :see: :meth:`~UltimateListItem.SetAlign` for a list of valid alignment bits.
+ """
+
+ return self._format
+
+
+ def GetAttributes(self):
+ """ Returns the associated :class:`UltimateListItemAttr` attributes. """
+
+ return self._attr
+
+
+ def HasAttributes(self):
+ """ Returns ``True`` if the item has attributes associated with it. """
+
+ return self._attr != None
+
+
+ def GetTextColour(self):
+ """ Returns the text colour. """
+
+ return (self.HasAttributes() and [self._attr.GetTextColour()] or [wx.NullColour])[0]
+
+
+ def GetBackgroundColour(self):
+ """ Returns the background colour. """
+
+ return (self.HasAttributes() and [self._attr.GetBackgroundColour()] or [wx.NullColour])[0]
+
+
+ def GetFont(self):
+ """ Returns the item font. """
+
+ return (self.HasAttributes() and [self._attr.GetFont()] or [wx.NullFont])[0]
+
+
+ def IsEnabled(self):
+ """ Returns ``True`` if the item is enabled. """
+
+ return (self.HasAttributes() and [self._attr.IsEnabled()] or [True])[0]
+
+ # creates self._attr if we don't have it yet
+ def Attributes(self):
+ """
+ Returns the associated attributes if they exist, or create a new :class:`UltimateListItemAttr`
+ structure and associate it with this item.
+ """
+
+ if not self._attr:
+ self._attr = UltimateListItemAttr()
+
+ return self._attr
+
+
+ def SetKind(self, kind):
+ """
+ Sets the item kind.
+
+ :param `kind`: may be one of the following integers:
+
+ =============== ==========================
+ Item Kind Description
+ =============== ==========================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== ==========================
+
+ """
+
+ self._mask |= ULC_MASK_KIND
+ self._kind = kind
+
+
+ def GetKind(self):
+ """
+ Returns the item kind.
+
+ :see: :meth:`~UltimateListItem.SetKind` for a valid list of item's kind.
+ """
+
+ return self._kind
+
+
+ def IsChecked(self):
+ """ Returns whether the item is checked or not. """
+
+ return self._checked
+
+
+ def Check(self, checked=True):
+ """
+ Checks/unchecks an item.
+
+ :param `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for check and radio items.
+ """
+
+ self._mask |= ULC_MASK_CHECK
+ self._checked = checked
+
+
+ def IsShown(self):
+ """ Returns ``True`` if the item is shown, or ``False`` if it is hidden. """
+
+ return self._isColumnShown
+
+
+ def SetShown(self, shown=True):
+ """
+ Sets an item as shown/hidden.
+
+ :param `shown`: ``True`` to show the item, ``False`` to hide it.
+ """
+
+ self._mask |= ULC_MASK_SHOWN
+ self._isColumnShown = shown
+
+
+ def SetHyperText(self, hyper=True):
+ """
+ Sets whether the item is hypertext or not.
+
+ :param `hyper`: ``True`` to set hypertext behaviour, ``False`` otherwise.
+ """
+
+ self._mask |= ULC_MASK_HYPERTEXT
+ self._hypertext = hyper
+
+
+ def SetVisited(self, visited=True):
+ """
+ Sets whether an hypertext item was visited or not.
+
+ :param `visited`: ``True`` to set a hypertext item as visited, ``False`` otherwise.
+ """
+
+ self._mask |= ULC_MASK_HYPERTEXT
+ self._visited = visited
+
+
+ def GetVisited(self):
+ """ Returns whether an hypertext item was visited or not. """
+
+ return self._visited
+
+
+ def IsHyperText(self):
+ """ Returns whether the item is hypetext or not. """
+
+ return self._hypertext
+
+
+ def SetWindow(self, wnd, expand=False):
+ """
+ Sets the window associated to the item.
+
+ :param `wnd`: a non-toplevel window to be displayed next to the item;
+ :param `expand`: ``True`` to expand the column where the item/subitem lives,
+ so that the window will be fully visible.
+ """
+
+ self._mask |= ULC_MASK_WINDOW
+ self._wnd = wnd
+
+ listCtrl = wnd.GetParent()
+ mainWin = listCtrl._mainWin
+
+ wnd.Reparent(mainWin)
+
+ if wnd.GetSizer(): # the window is a complex one hold by a sizer
+ size = wnd.GetBestSize()
+ else: # simple window, without sizers
+ size = wnd.GetSize()
+
+ # We have to bind the wx.EVT_SET_FOCUS for the associated window
+ # No other solution to handle the focus changing from an item in
+ # UltimateListCtrl and the window associated to an item
+ # Do better strategies exist?
+ self._wnd.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self._windowsize = size
+
+ # The window is enabled only if the item is enabled
+ self._wnd.Enable(self._enabled)
+ self._windowenabled = self._enabled
+ self._expandWin = expand
+
+ mainWin._hasWindows = True
+ mainWin._itemWithWindow.append(self)
+
+ # This is needed as otherwise widgets that should be invisible
+ # are shown at the top left corner of ULC
+ mainWin.HideWindows()
+ mainWin.Refresh()
+
+
+ def GetWindow(self):
+ """ Returns the window associated to the item. """
+
+ return self._wnd
+
+
+ def DeleteWindow(self):
+ """ Deletes the window associated to the item (if any). """
+
+ if self._wnd:
+ listCtrl = self._wnd.GetParent()
+ if self in listCtrl._itemWithWindow:
+ listCtrl._itemWithWindow.remove(self)
+ self._wnd.Destroy()
+ self._wnd = None
+
+
+ def GetWindowEnabled(self):
+ """ Returns whether the associated window is enabled or not. """
+
+ if not self._wnd:
+ raise Exception("\nERROR: This Item Has No Window Associated")
+
+ return self._windowenabled
+
+
+ def SetWindowEnabled(self, enable=True):
+ """
+ Sets whether the associated window is enabled or not.
+
+ :param `enable`: ``True`` to enable the associated window, ``False`` to disable it.
+ """
+
+ if not self._wnd:
+ raise Exception("\nERROR: This Item Has No Window Associated")
+
+ self._windowenabled = enable
+ self._wnd.Enable(enable)
+
+
+ def GetWindowSize(self):
+ """ Returns the associated window size. """
+
+ return self._windowsize
+
+
+ def SetCustomRenderer(self, renderer):
+ """
+ Associate a custom renderer to this item.
+
+ :param `renderer`: a class able to correctly render the item.
+
+ :note: the renderer class **must** implement the methods `DrawSubItem`,
+ `GetLineHeight` and `GetSubItemWidth`.
+ """
+
+ self._mask |= ULC_MASK_RENDERER
+ self._customRenderer = renderer
+
+
+ def GetCustomRenderer(self):
+ """ Returns the custom renderer associated with this item (if any). """
+
+ return self._customRenderer
+
+
+ def SetOverFlow(self, over=True):
+ """
+ Sets the item in the overflow/non overflow state.
+
+ An item/subitem may overwrite neighboring items/subitems if its text would
+ not normally fit in the space allotted to it.
+
+ :param `over`: ``True`` to set the item in a overflow state, ``False`` otherwise.
+ """
+
+ self._mask |= ULC_MASK_OVERFLOW
+ self._overFlow = over
+
+
+ def GetOverFlow(self):
+ """
+ Returns if the item is in the overflow state.
+
+ An item/subitem may overwrite neighboring items/subitems if its text would
+ not normally fit in the space allotted to it.
+ """
+
+ return self._overFlow
+
+
+ def Init(self):
+ """ Initializes an empty :class:`UltimateListItem`. """
+
+ self._mask = 0
+ self._itemId = 0
+ self._col = 0
+ self._state = 0
+ self._stateMask = 0
+ self._image = []
+ self._data = 0
+ self._pyData = None
+ self._text = ""
+ self._tooltip = ""
+
+ self._format = ULC_FORMAT_CENTRE
+ self._width = 0
+
+ self._colour = wx.Colour(0, 0, 0)
+ self._font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+ self._kind = 0
+ self._checked = False
+ self._enabled = True
+
+ self._hypertext = False # indicates if the item is hypertext
+ self._visited = False # visited state for an hypertext item
+
+ self._wnd = None
+ self._windowenabled = False
+ self._windowsize = wx.Size()
+ self._isColumnShown = True
+
+ self._customRenderer = None
+ self._overFlow = False
+ self._footerChecked = False
+ self._footerFormat = ULC_FORMAT_CENTRE
+ self._footerImage = []
+ self._footerKind = 0
+ self._footerText = ""
+ self._expandWin = False
+
+
+ def SetFooterKind(self, kind):
+ """
+ Sets the footer item kind.
+
+ :see: :meth:`~UltimateListItem.SetKind` for a list of valid items kind.
+ """
+
+ self._mask |= ULC_MASK_FOOTER_KIND
+ self._footerKind = kind
+
+
+ def GetFooterKind(self):
+ """
+ Returns the footer item kind.
+
+ :see: :meth:`~UltimateListItem.SetKind` for a list of valid items kind.
+ """
+
+ return self._footerKind
+
+
+ def IsFooterChecked(self):
+ """ Returns whether the footer item is checked or not. """
+
+ return self._footerChecked
+
+
+ def CheckFooter(self, checked=True):
+ """
+ Checks/unchecks a footer item.
+
+ :param `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for check and radio footer items.
+ """
+
+ self._mask |= ULC_MASK_FOOTER_CHECK
+ self._footerChecked = checked
+
+
+ def GetFooterFormat(self):
+ """ Returns the footer item format. """
+
+ return self._footerFormat
+
+
+ def SetFooterFormat(self, format):
+ """
+ Sets the footer item format.
+
+ :param `format`: the footer item format.
+ """
+
+ self._mask |= ULC_MASK_FOOTER_FORMAT
+ self._footerFormat = format
+
+
+ def GetFooterText(self):
+ """ Returns the footer text. """
+
+ return self._footerText
+
+
+ def SetFooterText(self, text):
+ """
+ Sets the text label for the footer item.
+
+ :param `text`: the text label for the footer item.
+ """
+
+ self._mask |= ULC_MASK_FOOTER_TEXT
+ self._footerText = text
+
+
+ def GetFooterImage(self):
+ """
+ Returns the zero-based index of the image associated with the footer item into
+ the image list.
+ """
+
+ return self._footerImage
+
+
+ def SetFooterImage(self, image):
+ """
+ Sets the zero-based index of the image associated with the footer item into the
+ image list.
+
+ :param `image`: the zero-based index of the image associated with the footer item
+ into the image list.
+ """
+
+ self._mask |= ULC_MASK_FOOTER_IMAGE
+ self._footerImage = to_list(image)
+
+
+ def GetFooterTextColour(self):
+ """ Returns the footer item text colour. """
+
+ return (self.HasAttributes() and [self._attr.GetFooterTextColour()] or [wx.NullColour])[0]
+
+
+ def GetFooterBackgroundColour(self):
+ """ Returns the footer item background colour. """
+
+ return (self.HasAttributes() and [self._attr.GetFooterBackgroundColour()] or [wx.NullColour])[0]
+
+
+ def GetFooterFont(self):
+ """ Returns the footer item font. """
+
+ return (self.HasAttributes() and [self._attr.GetFooterFont()] or [wx.NullFont])[0]
+
+
+ def SetFooterAlign(self, align):
+ """
+ Sets the alignment for the footer item.
+
+ :see: :meth:`~UltimateListItem.SetAlign` for a list of valid alignment flags.
+ """
+
+ self._mask |= ULC_MASK_FOOTER_FORMAT
+ self._footerFormat = align
+
+
+ def GetFooterAlign(self):
+ """
+ Returns the alignment for the footer item.
+
+ :see: :meth:`~UltimateListItem.SetAlign` for a list of valid alignment flags.
+ """
+
+ return self._footerFormat
+
+
+ def OnSetFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for the window associated to an item.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ listCtrl = self._wnd.GetParent()
+ select = listCtrl.GetItemState(self._itemId, ULC_STATE_SELECTED)
+
+ # If the window is associated to an item that currently is selected
+ # (has focus) we don't kill the focus. Otherwise we do it.
+ if not select:
+ listCtrl._hasFocus = False
+ else:
+ listCtrl._hasFocus = True
+
+ listCtrl.SetFocus()
+
+ event.Skip()
+
+# ----------------------------------------------------------------------------
+# ListEvent - the event class for the UltimateListCtrl notifications
+# ----------------------------------------------------------------------------
+
+class CommandListEvent(wx.PyCommandEvent):
+ """
+ A list event holds information about events associated with :class:`UltimateListCtrl`
+ objects.
+ """
+
+ def __init__(self, commandTypeOrEvent=None, winid=0):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `commandTypeOrEvent`: the event type or another instance of
+ :class:`PyCommandEvent`;
+ :param `winid`: the event identifier.
+ """
+
+ if type(commandTypeOrEvent) == types.IntType:
+
+ wx.PyCommandEvent.__init__(self, commandTypeOrEvent, winid)
+
+ self.m_code = 0
+ self.m_oldItemIndex = 0
+ self.m_itemIndex = 0
+ self.m_col = 0
+ self.m_pointDrag = wx.Point()
+ self.m_item = UltimateListItem()
+ self.m_editCancelled = False
+
+ else:
+
+ wx.PyCommandEvent.__init__(self, commandTypeOrEvent.GetEventType(), commandTypeOrEvent.GetId())
+ self.m_code = commandTypeOrEvent.m_code
+ self.m_oldItemIndex = commandTypeOrEvent.m_oldItemIndex
+ self.m_itemIndex = commandTypeOrEvent.m_itemIndex
+ self.m_col = commandTypeOrEvent.m_col
+ self.m_pointDrag = commandTypeOrEvent.m_pointDrag
+ self.m_item = commandTypeOrEvent.m_item
+ self.m_editCancelled = commandTypeOrEvent.m_editCancelled
+
+
+ def GetKeyCode(self):
+ """ Returns the key code if the event is a keypress event. """
+
+ return self.m_code
+
+
+ def GetIndex(self):
+ """ Returns the item index. """
+
+ return self.m_itemIndex
+
+
+ def GetColumn(self):
+ """
+ Returns the column position: it is only used with ``COL`` events.
+
+ For the column dragging events, it is the column to the left of the divider
+ being dragged, for the column click events it may be -1 if the user clicked
+ in the list control header outside any column.
+ """
+
+ return self.m_col
+
+
+ def GetPoint(self):
+ """ Returns the position of the mouse pointer if the event is a drag event. """
+
+ return self.m_pointDrag
+
+
+ def GetLabel(self):
+ """ Returns the (new) item label for ``EVT_LIST_END_LABEL_EDIT`` event. """
+
+ return self.m_item._text
+
+
+ def GetText(self):
+ """ Returns the item text. """
+
+ return self.m_item._text
+
+
+ def GetImage(self):
+ """ Returns the item image. """
+
+ return self.m_item._image
+
+
+ def GetData(self):
+ """ Returns the item data. """
+
+ return self.m_item._data
+
+
+ def GetMask(self):
+ """ Returns the item mask. """
+
+ return self.m_item._mask
+
+
+ def GetItem(self):
+ """ Returns the item itself. """
+
+ return self.m_item
+
+
+ # for wxEVT_COMMAND_LIST_CACHE_HINT only
+ def GetCacheFrom(self):
+ """
+ Returns the first item which the list control advises us to cache.
+
+ :note: This method is meaningful for ``EVT_LIST_CACHE_HINT`` event only.
+ """
+
+ return self.m_oldItemIndex
+
+
+ def GetCacheTo(self):
+ """
+ Returns the last item (inclusive) which the list control advises us to cache.
+
+ :note: This method is meaningful for ``EVT_LIST_CACHE_HINT`` event only.
+ """
+
+ return self.m_itemIndex
+
+
+ # was label editing canceled? (for wxEVT_COMMAND_LIST_END_LABEL_EDIT only)
+ def IsEditCancelled(self):
+ """
+ Returns ``True`` if it the label editing has been cancelled by the user
+ (:meth:`~CommandListEvent.GetLabel` returns an empty string in this case but it doesn't allow
+ the application to distinguish between really cancelling the edit and
+ the admittedly rare case when the user wants to rename it to an empty
+ string).
+
+ :note: This method only makes sense for ``EVT_LIST_END_LABEL_EDIT`` messages.
+ """
+
+ return self.m_editCancelled
+
+
+ def SetEditCanceled(self, editCancelled):
+ """
+ Sets the item editing as cancelled/not cancelled.
+
+ :param `editCancelled`: ``True`` to set the item editing as cancelled, ``False``
+ otherwise.
+
+ :note: This method only makes sense for ``EVT_LIST_END_LABEL_EDIT`` messages.
+ """
+
+ self.m_editCancelled = editCancelled
+
+
+
+# ----------------------------------------------------------------------------
+# UltimateListEvent is a special class for all events associated with list controls
+#
+# NB: note that not all accessors make sense for all events, see the event
+# descriptions below
+# ----------------------------------------------------------------------------
+
+class UltimateListEvent(CommandListEvent):
+ """
+ A list event holds information about events associated with :class:`UltimateListCtrl`
+ objects.
+ """
+
+ def __init__(self, commandTypeOrEvent=None, winid=0):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `commandTypeOrEvent`: the event type or another instance of
+ :class:`PyCommandEvent`;
+ :param `winid`: the event identifier.
+ """
+
+ CommandListEvent.__init__(self, commandTypeOrEvent, winid)
+
+ if type(commandTypeOrEvent) == types.IntType:
+ self.notify = wx.NotifyEvent(commandTypeOrEvent, winid)
+ else:
+ self.notify = wx.NotifyEvent(commandTypeOrEvent.GetEventType(), commandTypeOrEvent.GetId())
+
+
+ def GetNotifyEvent(self):
+ """ Returns the actual :class:`NotifyEvent`. """
+
+ return self.notify
+
+
+ def IsAllowed(self):
+ """
+ Returns ``True`` if the change is allowed (:meth:`~UltimateListEvent.Veto` hasn't been called) or
+ ``False`` otherwise (if it was).
+ """
+
+ return self.notify.IsAllowed()
+
+
+ def Veto(self):
+ """
+ Prevents the change announced by this event from happening.
+
+ :note: It is in general a good idea to notify the user about the reasons
+ for vetoing the change because otherwise the applications behaviour (which
+ just refuses to do what the user wants) might be quite surprising.
+ """
+
+ self.notify.Veto()
+
+
+ def Allow(self):
+ """
+ This is the opposite of :meth:`~UltimateListEvent.Veto`: it explicitly allows the event to be processed.
+ For most events it is not necessary to call this method as the events are
+ allowed anyhow but some are forbidden by default (this will be mentioned
+ in the corresponding event description).
+ """
+
+ self.notify.Allow()
+
+
+# ============================================================================
+# private classes
+# ============================================================================
+
+#-----------------------------------------------------------------------------
+# ColWidthInfo (internal)
+#-----------------------------------------------------------------------------
+
+class ColWidthInfo(object):
+ """ A simple class which holds information about :class:`UltimateListCtrl` columns. """
+
+ def __init__(self, w=0, needsUpdate=True):
+ """
+ Default class constructor
+
+ :param `w`: the initial width of the column;
+ :param `needsUpdate`: ``True`` if the column needs refreshing, ``False``
+ otherwise.
+ """
+
+ self._nMaxWidth = w
+ self._bNeedsUpdate = needsUpdate
+
+
+#-----------------------------------------------------------------------------
+# UltimateListItemData (internal)
+#-----------------------------------------------------------------------------
+
+class UltimateListItemData(object):
+ """
+ A simple class which holds information about :class:`UltimateListItem` visual
+ attributes (client rectangles, positions, etc...).
+ """
+
+ def __init__(self, owner):
+ """
+ Default class constructor
+
+ :param `owner`: an instance of :class:`UltimateListCtrl`.
+ """
+
+ # the list ctrl we are in
+ self._owner = owner
+ self.Init()
+
+ # the item coordinates are not used in report mode, instead this pointer
+ # is None and the owner window is used to retrieve the item position and
+ # size
+
+ if owner.InReportView():
+ self._rect = None
+ else:
+ self._rect = wx.Rect()
+
+
+ def SetImage(self, image):
+ """
+ Sets the zero-based indexes of the images associated with the item into the
+ image list.
+
+ :param `image`: a Python list with the zero-based indexes of the images
+ associated with the item into the image list.
+ """
+
+ self._image = to_list(image)
+
+
+ def SetData(self, data):
+ """
+ Sets client data for the item.
+
+ :param `data`: the client data associated to the item.
+
+ :note: Please note that client data is associated with the item and not
+ with subitems.
+ """
+
+ self._data = data
+
+
+ def HasText(self):
+ """ Returns ``True`` if the item text is not the empty string. """
+
+ return self._text != ""
+
+
+ def GetText(self):
+ """ Returns the item text. """
+
+ return self._text
+
+
+ def GetToolTip(self):
+ """ Returns the item tooltip. """
+
+ return self._tooltip
+
+
+ def GetBackgroundColour(self):
+ """ Returns the currently set background colour. """
+
+ return self._backColour
+
+
+ def GetColour(self):
+ """ Returns the currently set text colour. """
+
+ return self._colour
+
+
+ def GetFont(self):
+ """ Returns the currently set font. """
+
+ return (self._hasFont and [self._font] or [wx.NullFont])[0]
+
+
+ def SetText(self, text):
+ """
+ Sets the text label for the item.
+
+ :param `text`: the text label for the item.
+ """
+
+ self._text = text
+
+
+ def SetToolTip(self, tooltip):
+ """
+ Sets the tooltip for the item
+
+ :param `tooltip`: the tooltip text
+ """
+
+ self._tooltip = tooltip
+
+
+ def SetColour(self, colour):
+ """
+ Sets the text colour for the item.
+
+ :param `colour`: an instance of :class:`Colour`.
+ """
+
+ if colour == wx.NullColour or colour == None:
+ if self._hasColour:
+ self._hasColour = False
+ del self._colour
+ return
+
+ self._hasColour = True
+ self._colour = colour
+
+
+ def SetFont(self, font):
+ """
+ Sets the text font for the item.
+
+ :param `font`: an instance of :class:`Font`.
+ """
+
+ if font == wx.NullFont:
+ self._hasFont = False
+ del self._font
+ return
+
+ self._hasFont = True
+ self._font = font
+
+
+ def SetBackgroundColour(self, colour):
+ """
+ Sets the background colour for the item.
+
+ :param `colour`: an instance of :class:`Colour`.
+ """
+
+ if colour == wx.NullColour:
+ self._hasBackColour = False
+ del self._backColour
+ return
+
+ self._hasBackColour = True
+ self._backColour = colour
+
+
+ # we can't use empty string for measuring the string width/height, so
+ # always return something
+ def GetTextForMeasuring(self):
+ """
+ Returns the item text or a simple string if the item text is the
+ empty string.
+ """
+
+ s = self.GetText()
+ if not s.strip():
+ s = 'H'
+
+ return s
+
+
+ def GetImage(self):
+ """
+ Returns a Python list with the zero-based indexes of the images associated
+ with the item into the image list.
+ """
+
+ return self._image
+
+
+ def HasImage(self):
+ """ Returns ``True`` if the item has at least one image associated with it. """
+
+ return len(self._image) > 0
+
+
+ def SetKind(self, kind):
+ """
+ Sets the item kind.
+
+ :param `kind`: may be one of the following integers:
+
+ =============== ==========================
+ Item Kind Description
+ =============== ==========================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== ==========================
+
+ """
+
+ self._kind = kind
+
+
+ def GetKind(self):
+ """
+ Returns the item kind.
+
+ :see: :meth:`~UltimateListItemData.SetKind` for a list of valid item kinds.
+ """
+
+ return self._kind
+
+
+ def IsChecked(self):
+ """ Returns whether the item is checked or not. """
+
+ return self._checked
+
+
+ def Check(self, checked=True):
+ """
+ Checks/unchecks an item.
+
+ :param `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for check and radio items.
+ """
+
+ self._checked = checked
+
+
+ def SetHyperText(self, hyper=True):
+ """
+ Sets whether the item is hypertext or not.
+
+ :param `hyper`: ``True`` to set hypertext behaviour, ``False`` otherwise.
+ """
+
+ self._hypertext = hyper
+
+
+ def SetVisited(self, visited=True):
+ """
+ Sets whether an hypertext item was visited or not.
+
+ :param `visited`: ``True`` to set a hypertext item as visited, ``False`` otherwise.
+ """
+
+ self._visited = visited
+
+
+ def GetVisited(self):
+ """Returns whether an hypertext item was visited or not."""
+
+ return self._visited
+
+
+ def IsHyperText(self):
+ """Returns whether the item is hypetext or not."""
+
+ return self._hypertext
+
+
+ def SetWindow(self, wnd, expand=False):
+ """
+ Sets the window associated to the item.
+
+ :param `wnd`: a non-toplevel window to be displayed next to the item;
+ :param `expand`: ``True`` to expand the column where the item/subitem lives,
+ so that the window will be fully visible.
+ """
+
+ self._mask |= ULC_MASK_WINDOW
+ self._wnd = wnd
+
+ if wnd.GetSizer(): # the window is a complex one hold by a sizer
+ size = wnd.GetBestSize()
+ else: # simple window, without sizers
+ size = wnd.GetSize()
+
+ # We have to bind the wx.EVT_SET_FOCUS for the associated window
+ # No other solution to handle the focus changing from an item in
+ # UltimateListCtrl and the window associated to an item
+ # Do better strategies exist?
+ self._windowsize = size
+
+ # The window is enabled only if the item is enabled
+ self._wnd.Enable(self._enabled)
+ self._windowenabled = self._enabled
+ self._expandWin = expand
+
+
+ def GetWindow(self):
+ """ Returns the window associated to the item. """
+
+ return self._wnd
+
+
+ def DeleteWindow(self):
+ """ Deletes the window associated to the item (if any). """
+
+ if self._wnd:
+ self._wnd.Destroy()
+ self._wnd = None
+
+
+ def GetWindowEnabled(self):
+ """ Returns whether the associated window is enabled or not. """
+
+ if not self._wnd:
+ raise Exception("\nERROR: This Item Has No Window Associated")
+
+ return self._windowenabled
+
+
+ def SetWindowEnabled(self, enable=True):
+ """
+ Sets whether the associated window is enabled or not.
+
+ :param `enable`: ``True`` to enable the associated window, ``False`` to disable it.
+ """
+
+ if not self._wnd:
+ raise Exception("\nERROR: This Item Has No Window Associated")
+
+ self._windowenabled = enable
+ self._wnd.Enable(enable)
+
+
+ def GetWindowSize(self):
+ """ Returns the associated window size. """
+
+ return self._windowsize
+
+
+ def SetAttr(self, attr):
+ """
+ Sets the item attributes.
+
+ :param `attr`: an instance of :class:`UltimateListItemAttr`.
+ """
+
+ self._attr = attr
+
+
+ def GetAttr(self):
+ """ Returns the item attributes. """
+
+ return self._attr
+
+
+ def HasColour(self):
+ """ Returns ``True`` if the currently set text colour is valid. """
+
+ return self._hasColour
+
+
+ def HasFont(self):
+ """ Returns ``True`` if the currently set font is valid. """
+
+ return self._hasFont
+
+
+ def HasBackgroundColour(self):
+ """ Returns ``True`` if the currently set background colour is valid. """
+
+ return self._hasBackColour
+
+
+ def SetCustomRenderer(self, renderer):
+ """
+ Associate a custom renderer to this item.
+
+ :param `renderer`: a class able to correctly render the item.
+
+ :note: the renderer class **must** implement the methods `DrawSubItem`,
+ `GetLineHeight` and `GetSubItemWidth`.
+ """
+
+ self._mask |= ULC_MASK_RENDERER
+ self._customRenderer = renderer
+
+
+ def GetCustomRenderer(self):
+ """ Returns the custom renderer associated with this item (if any). """
+
+ return self._customRenderer
+
+
+ def SetOverFlow(self, over=True):
+ """
+ Sets the item in the overflow/non overflow state.
+
+ An item/subitem may overwrite neighboring items/subitems if its text would
+ not normally fit in the space allotted to it.
+
+ :param `over`: ``True`` to set the item in a overflow state, ``False`` otherwise.
+ """
+
+ self._mask |= ULC_MASK_OVERFLOW
+ self._overFlow = over
+
+
+ def GetOverFlow(self):
+ """
+ Returns if the item is in the overflow state.
+
+ An item/subitem may overwrite neighboring items/subitems if its text would
+ not normally fit in the space allotted to it.
+ """
+
+ return self._overFlow
+
+
+ def Init(self):
+ """ Initializes the item data structure. """
+
+ # the item image or -1
+ self._image = []
+ # user data associated with the item
+ self._data = 0
+ self._pyData = None
+ self._colour = wx.Colour(0, 0, 0)
+ self._hasColour = False
+ self._hasFont = False
+ self._hasBackColour = False
+ self._text = ""
+ self._tooltip = ""
+
+ # kind = 0: normal item
+ # kind = 1: checkbox-type item
+ self._kind = 0
+ self._checked = False
+
+ self._enabled = True
+
+ # custom attributes or None
+ self._attr = None
+
+ self._hypertext = False
+ self._visited = False
+
+ self._wnd = None
+ self._windowenabled = True
+ self._windowsize = wx.Size()
+ self._isColumnShown = True
+ self._customRenderer = None
+ self._overFlow = False
+ self._expandWin = False
+
+
+ def SetItem(self, info):
+ """
+ Sets information about the item.
+
+ :param `info`: an instance of :class:`UltimateListItemData`.
+ """
+
+ if info._mask & ULC_MASK_TEXT:
+ CheckVariableRowHeight(self._owner, info._text)
+ self.SetText(info._text)
+
+ if info._mask & ULC_MASK_TOOLTIP:
+ self.SetToolTip(info._tooltip)
+
+ if info._mask & ULC_MASK_KIND:
+ self._kind = info._kind
+
+ if info._mask & ULC_MASK_CHECK:
+ self._checked = info._checked
+
+ if info._mask & ULC_MASK_ENABLE:
+ self._enabled = info._enabled
+
+ if info._mask & ULC_MASK_IMAGE:
+ self._image = info._image[:]
+
+ if info._mask & ULC_MASK_DATA:
+ self._data = info._data
+
+ if info._mask & ULC_MASK_PYDATA:
+ self._pyData = info._pyData
+
+ if info._mask & ULC_MASK_HYPERTEXT:
+ self._hypertext = info._hypertext
+ self._visited = info._visited
+
+ if info._mask & ULC_MASK_FONTCOLOUR:
+ self.SetColour(info.GetTextColour())
+
+ if info._mask & ULC_MASK_FONT:
+ self.SetFont(info.GetFont())
+
+ if info._mask & ULC_MASK_BACKCOLOUR:
+ self.SetBackgroundColour(info.GetBackgroundColour())
+
+ if info._mask & ULC_MASK_WINDOW:
+ self._wnd = info._wnd
+ self._windowenabled = info._windowenabled
+ self._windowsize = info._windowsize
+ self._expandWin = info._expandWin
+
+ if info._mask & ULC_MASK_SHOWN:
+ self._isColumnShown = info._isColumnShown
+
+ if info._mask & ULC_MASK_RENDERER:
+ self._customRenderer = info._customRenderer
+
+ if info._mask & ULC_MASK_OVERFLOW:
+ self._overFlow = info._overFlow
+
+ if info.HasAttributes():
+
+ if self._attr:
+ self._attr = info.GetAttributes()
+ else:
+ self._attr = UltimateListItemAttr(info.GetTextColour(), info.GetBackgroundColour(),
+ info.GetFont(), info.IsEnabled(), info.GetFooterTextColour(),
+ info.GetFooterBackgroundColour(), info.GetFooterFont())
+
+ if self._rect:
+
+ self._rect.x = -1
+ self._rect.y = -1
+ self._rect.height = 0
+ self._rect.width = info._width
+
+
+ def SetPosition(self, x, y):
+ """
+ Sets the item position.
+
+ :param `x`: the item `x` position;
+ :param `y`: the item `y` position.
+ """
+
+ self._rect.x = x
+ self._rect.y = y
+
+
+ def SetSize(self, width, height):
+ """
+ Sets the item size.
+
+ :param `width`: the item width, in pixels;
+ :param `height`: the item height, in pixels.
+ """
+
+ if width != -1:
+ self._rect.width = width
+ if height != -1:
+ self._rect.height = height
+
+
+ def IsHit(self, x, y):
+ """
+ Returns ``True`` if the input position is inside the item client rectangle.
+
+ :param `x`: the `x` mouse position;
+ :param `y`: the `y` mouse position.
+ """
+
+ return wx.Rect(self.GetX(), self.GetY(), self.GetWidth(), self.GetHeight()).Contains((x, y))
+
+
+ def GetX(self):
+ """ Returns the item `x` position. """
+
+ return self._rect.x
+
+
+ def GetY(self):
+ """ Returns the item `y` position. """
+
+ return self._rect.y
+
+
+ def GetWidth(self):
+ """ Returns the item width, in pixels. """
+
+ return self._rect.width
+
+
+ def GetHeight(self):
+ """ Returns the item height, in pixels. """
+
+ return self._rect.height
+
+
+ def GetItem(self, info):
+ """
+ Returns information about the item.
+
+ :param `info`: an instance of :class:`UltimateListItemData`.
+ """
+
+ mask = info._mask
+ if not mask:
+ # by default, get everything for backwards compatibility
+ mask = -1
+
+ if mask & ULC_MASK_TEXT:
+ info._text = self._text
+ if mask & ULC_MASK_TOOLTIP:
+ info._tooltip = self._tooltip
+ if mask & ULC_MASK_IMAGE:
+ info._image = self._image[:]
+ if mask & ULC_MASK_DATA:
+ info._data = self._data
+ if mask & ULC_MASK_PYDATA:
+ info._pyData = self._pyData
+ if info._mask & ULC_MASK_FONT:
+ info.SetFont(self.GetFont())
+ if mask & ULC_MASK_KIND:
+ info._kind = self._kind
+ if mask & ULC_MASK_CHECK:
+ info._checked = self._checked
+ if mask & ULC_MASK_ENABLE:
+ info._enabled = self._enabled
+ if mask & ULC_MASK_HYPERTEXT:
+ info._hypertext = self._hypertext
+ info._visited = self._visited
+ if mask & ULC_MASK_WINDOW:
+ info._wnd = self._wnd
+ info._windowenabled = self._windowenabled
+ info._windowsize = self._windowsize
+ info._expandWin = self._expandWin
+ if mask & ULC_MASK_SHOWN:
+ info._isColumnShown = self._isColumnShown
+ if mask & ULC_MASK_RENDERER:
+ info._customRenderer = self._customRenderer
+ if mask & ULC_MASK_OVERFLOW:
+ info._overFlow = self._overFlow
+
+ if self._attr:
+
+ if self._attr.HasTextColour():
+ info.SetTextColour(self._attr.GetTextColour())
+ if self._attr.HasBackgroundColour():
+ info.SetBackgroundColour(self._attr.GetBackgroundColour())
+ if self._attr.HasFont():
+ info.SetFont(self._attr.GetFont())
+ info.Enable(self._attr.IsEnabled())
+
+ return info
+
+
+ def IsEnabled(self):
+ """ Returns ``True`` if the item is enabled, ``False`` if it is disabled. """
+
+ return self._enabled
+
+
+ def Enable(self, enable=True):
+ """
+ Enables or disables the item.
+
+ :param `enable`: ``True`` to enable the item, ``False`` to disable it.
+ """
+
+ self._enabled = enable
+
+
+#-----------------------------------------------------------------------------
+# UltimateListHeaderData (internal)
+#-----------------------------------------------------------------------------
+
+class UltimateListHeaderData(object):
+ """
+ A simple class which holds information about :class:`UltimateListItem` visual
+ attributes for the header/footer items (client rectangles, positions, etc...).
+ """
+
+ def __init__(self, item=None):
+ """
+ Default class constructor.
+
+ :param `item`: another instance of :class:`UltimateListHeaderData`.
+ """
+
+ self.Init()
+
+ if item:
+ self.SetItem(item)
+
+
+ def HasText(self):
+ """ Returns ``True`` if the currently set text colour is valid. """
+
+ return self._text != ""
+
+
+ def GetText(self):
+ """ Returns the header/footer item text. """
+
+ return self._text
+
+
+ def GetToolTip(self):
+ """ Returns the header/footer item tooltip. """
+
+ return self._tooltip
+
+
+ def SetText(self, text):
+ """
+ Sets the header/footer item text.
+
+ :param `text`: the new header/footer text.
+ """
+
+ self._text = text
+
+
+ def SetToolTip(self, tip):
+ """
+ Sets the header/footer item tooltip.
+
+ :param `tip`: the new header/footer tooltip.
+ """
+
+ self._tip = tip
+
+
+ def GetFont(self):
+ """ Returns the header/footer item font. """
+
+ return self._font
+
+
+ def Init(self):
+ """ Initializes the header/footer item. """
+
+ self._mask = 0
+ self._image = []
+ self._format = 0
+ self._width = 0
+ self._xpos = 0
+ self._ypos = 0
+ self._height = 0
+ self._text = ""
+ self._tooltip = ""
+ self._kind = 0
+ self._checked = False
+ self._font = wx.NullFont
+ self._state = 0
+ self._isColumnShown = True
+ self._customRenderer = None
+
+ self._footerImage = []
+ self._footerFormat = 0
+ self._footerText = ""
+ self._footerKind = 0
+ self._footerChecked = False
+ self._footerFont = wx.NullFont
+
+
+ def SetItem(self, item):
+ """
+ Sets information about the header/footer item.
+
+ :param `info`: an instance of :class:`UltimateListHeaderData`.
+ """
+
+ self._mask = item._mask
+
+ if self._mask & ULC_MASK_TEXT:
+ self._text = item._text
+
+ if self._mask & ULC_MASK_TOOLTIP:
+ self._tooltip = item._tooltip
+
+ if self._mask & ULC_MASK_FOOTER_TEXT:
+ self._footerText = item._footerText
+
+ if self._mask & ULC_MASK_IMAGE:
+ self._image = item._image[:]
+
+ if self._mask & ULC_MASK_FOOTER_IMAGE:
+ self._footerImage = item._footerImage[:]
+
+ if self._mask & ULC_MASK_FORMAT:
+ self._format = item._format
+
+ if self._mask & ULC_MASK_FOOTER_FORMAT:
+ self._footerFormat = item._footerFormat
+
+ if self._mask & ULC_MASK_WIDTH:
+ self.SetWidth(item._width)
+
+ if self._mask & ULC_MASK_FONT:
+ self._font = item._font
+
+ if self._mask & ULC_MASK_FOOTER_FONT:
+ self._footerFont = item._footerFont
+
+ if self._mask & ULC_MASK_FOOTER_KIND:
+ self._footerKind = item._footerKind
+ self._footerChecked = item._footerChecked
+
+ if self._mask & ULC_MASK_KIND:
+ self._kind = item._kind
+ self._checked = item._checked
+
+ if self._mask & ULC_MASK_CHECK:
+ self._kind = item._kind
+ self._checked = item._checked
+
+ if self._mask & ULC_MASK_FOOTER_CHECK:
+ self._footerKind = item._footerKind
+ self._footerChecked = item._footerChecked
+
+ if self._mask & ULC_MASK_STATE:
+ self.SetState(item._state)
+
+ if self._mask & ULC_MASK_SHOWN:
+ self._isColumnShown = item._isColumnShown
+
+ if self._mask & ULC_MASK_RENDERER:
+ self._customRenderer = item._customRenderer
+
+
+ def SetState(self, flag):
+ """
+ Sets the item state flags.
+
+ :param `state`: any combination of the following bits:
+
+ ============================ ========= ==============================
+ State Bits Hex Value Description
+ ============================ ========= ==============================
+ ``ULC_STATE_DONTCARE`` 0x0 Don't care what the state is
+ ``ULC_STATE_DROPHILITED`` 0x1 The item is highlighted to receive a drop event
+ ``ULC_STATE_FOCUSED`` 0x2 The item has the focus
+ ``ULC_STATE_SELECTED`` 0x4 The item is selected
+ ``ULC_STATE_CUT`` 0x8 The item is in the cut state
+ ``ULC_STATE_DISABLED`` 0x10 The item is disabled
+ ``ULC_STATE_FILTERED`` 0x20 The item has been filtered
+ ``ULC_STATE_INUSE`` 0x40 The item is in use
+ ``ULC_STATE_PICKED`` 0x80 The item has been picked
+ ``ULC_STATE_SOURCE`` 0x100 The item is a drag and drop source
+ ============================ ========= ==============================
+
+ """
+
+ self._state = flag
+
+
+ def SetPosition(self, x, y):
+ """
+ Sets the header/footer item position.
+
+ :param `x`: the item `x` position;
+ :param `y`: the item `y` position.
+ """
+
+ self._xpos = x
+ self._ypos = y
+
+
+ def SetHeight(self, h):
+ """
+ Sets the header/footer item height, in pixels.
+
+ :param `h`: an integer value representing the header/footer height.
+ """
+
+ self._height = h
+
+
+ def SetWidth(self, w):
+ """
+ Sets the header/footer item width, in pixels.
+
+ :param `w`: an integer value representing the header/footer width.
+ """
+
+ self._width = w
+
+ if self._width < 0:
+ self._width = WIDTH_COL_DEFAULT
+ elif self._width < WIDTH_COL_MIN:
+ self._width = WIDTH_COL_MIN
+
+
+ def SetFormat(self, format):
+ """
+ Sets the header item format.
+
+ :param `format`: the header item format.
+ """
+
+ self._format = format
+
+
+ def SetFooterFormat(self, format):
+ """
+ Sets the footer item format.
+
+ :param `format`: the footer item format.
+ """
+
+ self._footerFormat = format
+
+
+ def HasImage(self):
+ """
+ Returns ``True`` if the header item has at least one image associated
+ with it.
+ """
+
+ return len(self._image) > 0
+
+
+ def HasFooterImage(self):
+ """
+ Returns ``True`` if the footer item has at least one image associated
+ with it.
+ """
+
+ return len(self._footerImage) > 0
+
+
+ def IsHit(self, x, y):
+ """
+ Returns ``True`` if the input position is inside the item client rectangle.
+
+ :param `x`: the `x` mouse position;
+ :param `y`: the `y` mouse position.
+ """
+
+ return ((x >= self._xpos) and (x <= self._xpos+self._width) and (y >= self._ypos) and (y <= self._ypos+self._height))
+
+
+ def GetItem(self, item):
+ """
+ Returns information about the item.
+
+ :param `item`: an instance of :class:`UltimateListHeaderData`.
+ """
+
+ item._mask = self._mask
+ item._text = self._text
+ item._tooltip = self._tooltip
+ item._image = self._image[:]
+ item._format = self._format
+ item._width = self._width
+ if self._font:
+ item._font = self._font
+ item.Attributes().SetFont(self._font)
+
+ item._kind = self._kind
+ item._checked = self._checked
+ item._state = self._state
+ item._isColumnShown = self._isColumnShown
+
+ item._footerImage = self._footerImage
+ item._footerFormat = self._footerFormat
+ item._footerText = self._footerText
+ item._footerKind = self._footerKind
+ item._footerChecked = self._footerChecked
+ item._footerFont = self._footerFont
+ item._customRenderer = self._customRenderer
+
+ return item
+
+
+ def GetState(self):
+ """
+ Returns a bit field representing the state of the item.
+
+ :see: :meth:`~UltimateListHeaderData.SetState` for a list of valid item states.
+ """
+
+ return self._state
+
+
+ def GetImage(self):
+ """
+ Returns a Python list with the zero-based indexes of the images associated
+ with the header item into the image list.
+ """
+
+ return self._image
+
+
+ def GetFooterImage(self):
+ """
+ Returns a Python list with the zero-based indexes of the images associated
+ with the footer item into the image list.
+ """
+
+ return self._footerImage
+
+
+ def GetWidth(self):
+ """ Returns the header/footer item width, in pixels. """
+
+ return self._width
+
+
+ def GetFormat(self):
+ """ Returns the header item format. """
+
+ return self._format
+
+
+ def GetFooterFormat(self):
+ """ Returns the footer item format. """
+
+ return self._footerFormat
+
+
+ def SetFont(self, font):
+ """
+ Sets a new font for the header item.
+
+ :param `font`: an instance of :class:`Font`.
+ """
+
+ self._font = font
+
+
+ def SetFooterFont(self, font):
+ """
+ Sets a new font for the footer item.
+
+ :param `font`: an instance of :class:`Font`.
+ """
+
+ self._footerFont = font
+
+
+ def SetKind(self, kind):
+ """
+ Sets the header item kind.
+
+ :param `kind`: may be one of the following integers:
+
+ =============== ==========================
+ Item Kind Description
+ =============== ==========================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== ==========================
+
+ """
+
+ self._kind = kind
+
+
+ def SetFooterKind(self, kind):
+ """
+ Sets the footer item kind.
+
+ :param `kind`: the footer item kind.
+
+ :see: :meth:`~UltimateListHeaderData.SetKind` for a list of valid item kinds.
+ """
+
+ self._footerKind = kind
+
+
+ def GetKind(self):
+ """
+ Returns the header item kind.
+
+ :see: :meth:`~UltimateListHeaderData.SetKind` for a list of valid item kinds.
+ """
+
+ return self._kind
+
+
+ def GetFooterKind(self):
+ """
+ Returns the footer item kind.
+
+ :see: :meth:`~UltimateListHeaderData.SetKind` for a list of valid item kinds.
+ """
+
+ return self._footerKind
+
+
+ def IsChecked(self):
+ """ Returns whether the header item is checked or not. """
+
+ return self._checked
+
+
+ def Check(self, checked=True):
+ """
+ Checks/unchecks a header item.
+
+ :param `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for check and radio header items.
+ """
+
+ self._checked = checked
+
+
+ def IsFooterChecked(self):
+ """ Returns whether the footer item is checked or not. """
+
+ return self._footerChecked
+
+
+ def CheckFooter(self, check=True):
+ """
+ Checks/unchecks a footer item.
+
+ :param `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for check and radio footer items.
+ """
+
+ self._footerChecked = check
+
+
+ def SetCustomRenderer(self, renderer):
+ """
+ Associate a custom renderer to this item.
+
+ :param `renderer`: a class able to correctly render the item.
+
+ :note: the renderer class **must** implement the methods `DrawHeaderButton`
+ and `GetForegroundColor`.
+ """
+
+ self._mask |= ULC_MASK_RENDERER
+ self._customRenderer = renderer
+
+
+ def GetCustomRenderer(self):
+ """ Returns the custom renderer associated with this item (if any). """
+
+ return self._customRenderer
+
+
+#-----------------------------------------------------------------------------
+# GeometryInfo (internal)
+# this is not used in report view
+#-----------------------------------------------------------------------------
+
+class GeometryInfo(object):
+ """
+ A simple class which holds items geometries for :class:`UltimateListCtrl` not in
+ report mode.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ # total item rect
+ self._rectAll = wx.Rect()
+
+ # label only
+ self._rectLabel = wx.Rect()
+
+ # icon only
+ self._rectIcon = wx.Rect()
+
+ # the part to be highlighted
+ self._rectHighlight = wx.Rect()
+
+ # the checkbox/radiobutton rect (if any)
+ self._rectCheck = wx.Rect()
+
+ # extend all our rects to be centered inside the one of given width
+ def ExtendWidth(self, w):
+ """
+ Extends all our rectangles to be centered inside the one of given width.
+
+ :param `w`: the given width.
+ """
+
+ if self._rectAll.width > w:
+ raise Exception("width can only be increased")
+
+ self._rectAll.width = w
+ self._rectLabel.x = self._rectAll.x + (w - self._rectLabel.width)/2
+ self._rectIcon.x = self._rectAll.x + (w - self._rectIcon.width)/2
+ self._rectHighlight.x = self._rectAll.x + (w - self._rectHighlight.width)/2
+
+
+#-----------------------------------------------------------------------------
+# UltimateListLineData (internal)
+#-----------------------------------------------------------------------------
+
+class UltimateListLineData(object):
+ """ A simple class which holds line geometries for :class:`UltimateListCtrl`. """
+
+ def __init__(self, owner):
+ """
+ Default class constructor.
+
+ :param `owner`: an instance of :class:`UltimateListCtrl`.
+ """
+
+ # the list of subitems: only may have more than one item in report mode
+ self._items = []
+
+ # is this item selected? [NB: not used in virtual mode]
+ self._highlighted = False
+
+ # back pointer to the list ctrl
+ self._owner = owner
+ self._height = self._width = self._x = self._y = -1
+
+ if self.InReportView():
+
+ self._gi = None
+
+ else:
+
+ self._gi = GeometryInfo()
+
+ if self.GetMode() in [ULC_REPORT, ULC_TILE] or self.HasMode(ULC_HEADER_IN_ALL_VIEWS):
+ self.InitItems(self._owner.GetColumnCount())
+ else:
+ self.InitItems(1)
+
+
+ def SetReportView(self, inReportView):
+ """
+ Sets whether :class:`UltimateListLineData` is in report view or not.
+
+ :param `inReportView`: ``True`` to set :class:`UltimateListLineData` in report view, ``False``
+ otherwise.
+ """
+
+ # we only need m_gi when we're not in report view so update as needed
+ if inReportView:
+
+ del self._gi
+ self._gi = None
+
+ else:
+
+ self._gi = GeometryInfo()
+
+
+ def GetHeight(self):
+ """ Returns the line height, in pixels. """
+
+ return self._height
+
+
+ def SetHeight(self, height):
+ """
+ Sets the line height.
+
+ :param `height`: the new line height.
+ """
+
+ self._height = height
+
+
+ def GetWidth(self):
+ """ Returns the line width. """
+
+ return self._width
+
+
+ def SetWidth(self, width):
+ """
+ Sets the line width.
+
+ :param `width`: the new line width.
+ """
+
+ self._width = width
+
+
+ def GetX(self):
+ """ Returns the line `x` position. """
+
+ return self._x
+
+
+ def SetX(self, x):
+ """
+ Sets the line `x` position.
+
+ :param `x`: the new line `x` position.
+ """
+
+ self._x = x
+
+
+ def GetY(self):
+ """ Returns the line `y` position. """
+
+ return self._y
+
+
+ def SetY(self, y):
+ """
+ Sets the line `y` position.
+
+ :param `y`: the new line `y` position.
+ """
+
+ self._y = y
+
+
+ def ResetDimensions(self):
+ """ Resets the line dimensions (client rectangle). """
+
+ self._height = self._width = self._x = self._y = -1
+
+
+ def HasImage(self, col=0):
+ """
+ Returns ``True`` if the first item in the line has at least one image
+ associated with it.
+ """
+
+ return self.GetImage(col) != []
+
+
+ def HasText(self):
+ """
+ Returns ``True`` if the text of first item in the line is not the empty
+ string.
+ """
+
+ return self.GetText(0) != ""
+
+
+ def IsHighlighted(self):
+ """ Returns ``True`` if the line is highlighted. """
+
+ if self.IsVirtual():
+ raise Exception("unexpected call to IsHighlighted")
+
+ return self._highlighted
+
+
+ def GetMode(self):
+ """ Returns the current highlighting mode. """
+
+ return self._owner.GetListCtrl().GetAGWWindowStyleFlag() & ULC_MASK_TYPE
+
+
+ def HasMode(self, mode):
+ """
+ Returns ``True`` if the parent :class:`UltimateListCtrl` has the window
+ style specified by `mode`.
+
+ :param `mode`: the window style to check.
+ """
+
+ return self._owner.GetListCtrl().HasAGWFlag(mode)
+
+
+ def InReportView(self):
+ """ Returns ``True`` if the parent :class:`UltimateListCtrl` is in report view. """
+
+ return self._owner.HasAGWFlag(ULC_REPORT)
+
+
+ def IsVirtual(self):
+ """ Returns ``True`` if the parent :class:`UltimateListCtrl` has the ``ULC_VIRTUAL`` style set. """
+
+ return self._owner.IsVirtual()
+
+
+ def CalculateSize(self, dc, spacing):
+ """
+ Calculates the line size and item positions.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `spacing`: the spacing between the items, in pixels.
+ """
+
+ item = self._items[0]
+ mode = self.GetMode()
+
+ if mode in [ULC_ICON, ULC_SMALL_ICON]:
+
+ self._gi._rectAll.width = spacing
+
+ s = item.GetText()
+
+ if not s:
+
+ lh = -1
+ self._gi._rectLabel.width = 0
+ self._gi._rectLabel.height = 0
+
+ else:
+
+ lw, lh = dc.GetTextExtent(s)
+ lw += EXTRA_WIDTH
+ lh += EXTRA_HEIGHT
+
+ self._gi._rectAll.height = spacing + lh
+
+ if lw > spacing:
+ self._gi._rectAll.width = lw
+
+ self._gi._rectLabel.width = lw
+ self._gi._rectLabel.height = lh
+
+ if item.HasImage():
+
+ w, h = self._owner.GetImageSize(item.GetImage())
+ self._gi._rectIcon.width = w + 8
+ self._gi._rectIcon.height = h + 8
+
+ if self._gi._rectIcon.width > self._gi._rectAll.width:
+ self._gi._rectAll.width = self._gi._rectIcon.width
+ if self._gi._rectIcon.height + lh > self._gi._rectAll.height - 4:
+ self._gi._rectAll.height = self._gi._rectIcon.height + lh + 4
+
+ if item.HasText():
+
+ self._gi._rectHighlight.width = self._gi._rectLabel.width
+ self._gi._rectHighlight.height = self._gi._rectLabel.height
+
+ else:
+
+ self._gi._rectHighlight.width = self._gi._rectIcon.width
+ self._gi._rectHighlight.height = self._gi._rectIcon.height
+
+ elif mode == ULC_LIST:
+
+ s = item.GetTextForMeasuring()
+
+ lw, lh = dc.GetTextExtent(s)
+ lw += EXTRA_WIDTH
+ lh += EXTRA_HEIGHT
+
+ self._gi._rectLabel.width = lw
+ self._gi._rectLabel.height = lh
+
+ self._gi._rectAll.width = lw
+ self._gi._rectAll.height = lh
+
+ if item.HasImage():
+
+ w, h = self._owner.GetImageSize(item.GetImage())
+ h += 4
+ self._gi._rectIcon.width = w
+ self._gi._rectIcon.height = h
+
+ self._gi._rectAll.width += 4 + w
+
+ if h > self._gi._rectAll.height:
+ self._gi._rectAll.height = h
+
+ if item.GetKind() in [1, 2]:
+
+ w, h = self._owner.GetCheckboxImageSize()
+ h += 4
+ self._gi._rectCheck.width = w
+ self._gi._rectCheck.height = h
+
+ self._gi._rectAll.width += 4 + w
+
+ if h > self._gi._rectAll.height:
+ self._gi._rectAll.height = h
+
+ self._gi._rectHighlight.width = self._gi._rectAll.width
+ self._gi._rectHighlight.height = self._gi._rectAll.height
+
+ elif mode == ULC_REPORT:
+ raise Exception("unexpected call to SetSize")
+
+ else:
+ raise Exception("unknown mode")
+
+
+ def SetPosition(self, x, y, spacing):
+ """
+ Sets the line position.
+
+ :param `x`: the current `x` coordinate;
+ :param `y`: the current `y` coordinate;
+ :param `spacing`: the spacing between items, in pixels.
+ """
+
+ item = self._items[0]
+ mode = self.GetMode()
+
+ if mode in [ULC_ICON, ULC_SMALL_ICON]:
+
+ self._gi._rectAll.x = x
+ self._gi._rectAll.y = y
+
+ if item.HasImage():
+
+ self._gi._rectIcon.x = self._gi._rectAll.x + 4 + (self._gi._rectAll.width - self._gi._rectIcon.width)/2
+ self._gi._rectIcon.y = self._gi._rectAll.y + 4
+
+ if item.HasText():
+
+ if self._gi._rectLabel.width > spacing:
+ self._gi._rectLabel.x = self._gi._rectAll.x + 2
+ else:
+ self._gi._rectLabel.x = self._gi._rectAll.x + 2 + (spacing/2) - (self._gi._rectLabel.width/2)
+
+ self._gi._rectLabel.y = self._gi._rectAll.y + self._gi._rectAll.height + 2 - self._gi._rectLabel.height
+ self._gi._rectHighlight.x = self._gi._rectLabel.x - 2
+ self._gi._rectHighlight.y = self._gi._rectLabel.y - 2
+
+ else:
+
+ self._gi._rectHighlight.x = self._gi._rectIcon.x - 4
+ self._gi._rectHighlight.y = self._gi._rectIcon.y - 4
+
+ elif mode == ULC_LIST:
+
+ self._gi._rectAll.x = x
+ self._gi._rectAll.y = y
+
+ wcheck = hcheck = 0
+
+ if item.GetKind() in [1, 2]:
+ wcheck, hcheck = self._owner.GetCheckboxImageSize()
+ wcheck += 2
+ self._gi._rectCheck.x = self._gi._rectAll.x + 2
+ self._gi._rectCheck.y = self._gi._rectAll.y + 2
+
+ self._gi._rectHighlight.x = self._gi._rectAll.x
+ self._gi._rectHighlight.y = self._gi._rectAll.y
+ self._gi._rectLabel.y = self._gi._rectAll.y + 2
+
+ if item.HasImage():
+
+ self._gi._rectIcon.x = self._gi._rectAll.x + wcheck + 2
+ self._gi._rectIcon.y = self._gi._rectAll.y + 2
+ self._gi._rectLabel.x = self._gi._rectAll.x + 6 + self._gi._rectIcon.width + wcheck
+
+ else:
+
+ self._gi._rectLabel.x = self._gi._rectAll.x + 2 + wcheck
+
+ elif mode == ULC_REPORT:
+ raise Exception("unexpected call to SetPosition")
+
+ else:
+ raise Exception("unknown mode")
+
+
+ def InitItems(self, num):
+ """
+ Initializes the list of items.
+
+ :param `num`: the initial number of items to store.
+ """
+
+ for i in xrange(num):
+ self._items.append(UltimateListItemData(self._owner))
+
+
+ def SetItem(self, index, info):
+ """
+ Sets information about the item.
+
+ :param `index`: the index of the item;
+ :param `info`: an instance of :class:`UltimateListItem`.
+ """
+
+ item = self._items[index]
+ item.SetItem(info)
+
+
+ def GetItem(self, index, info):
+ """
+ Returns information about the item.
+
+ :param `index`: the index of the item;
+ :param `info`: an instance of :class:`UltimateListItem`.
+ """
+
+ item = self._items[index]
+ return item.GetItem(info)
+
+
+ def GetText(self, index):
+ """
+ Returns the item text at the position `index`.
+
+ :param `index`: the index of the item.
+ """
+
+ item = self._items[index]
+ return item.GetText()
+
+
+ def SetText(self, index, s):
+ """
+ Sets the item text at the position `index`.
+
+ :param `index`: the index of the item;
+ :param `s`: the new item text.
+ """
+
+ item = self._items[index]
+ item.SetText(s)
+
+
+ def GetToolTip(self, index):
+ """
+ Returns the item tooltip at the position `index`.
+
+ :param `index`: the index of the item.
+ """
+
+ item = self._items[index]
+ return item.GetToolTip()
+
+
+ def SetToolTip(self, index, s):
+ """
+ Sets the item tooltip at the position `index`.
+
+ :param `index`: the index of the item;
+ :param `s`: the new item tooltip.
+ """
+
+ item = self._items[index]
+ item.SetToolTip(s)
+
+
+ def SetImage(self, index, image):
+ """
+ Sets the zero-based indexes of the images associated with the item into the
+ image list.
+
+ :param `index`: the index of the item;
+ :param `image`: a Python list with the zero-based indexes of the images
+ associated with the item into the image list.
+ """
+
+ item = self._items[index]
+ item.SetImage(image)
+
+
+ def GetImage(self, index=0):
+ """
+ Returns a Python list with the zero-based indexes of the images associated
+ with the item into the image list.
+
+ :param `index`: the index of the item.
+ """
+
+ item = self._items[index]
+ return item.GetImage()
+
+
+ def Check(self, index, checked=True):
+ """
+ Checks/unchecks an item.
+
+ :param `index`: the index of the item;
+ :param `checked`: ``True`` to check an item, ``False`` to uncheck it.
+
+ :note: This method is meaningful only for check and radio items.
+ """
+
+ item = self._items[index]
+ item.Check(checked)
+
+
+ def SetKind(self, index, kind=0):
+ """
+ Sets the item kind.
+
+ :param `index`: the index of the item;
+ :param `kind`: may be one of the following integers:
+
+ =============== ==========================
+ Item Kind Description
+ =============== ==========================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== ==========================
+
+ """
+
+ item = self._items[index]
+ item.SetKind(kind)
+
+
+ def GetKind(self, index=0):
+ """
+ Returns the item kind.
+
+ :param `index`: the index of the item.
+
+ :see: :meth:`~UltimateListLineData.SetKind` for a list of valid item kinds.
+ """
+
+ item = self._items[index]
+ return item.GetKind()
+
+
+ def IsChecked(self, index):
+ """
+ Returns whether the item is checked or not.
+
+ :param `index`: the index of the item.
+ """
+
+ item = self._items[index]
+ return item.IsChecked()
+
+
+ def SetColour(self, index, c):
+ """
+ Sets the text colour for the item.
+
+ :param `index`: the index of the item;
+ :param `c`: an instance of :class:`Colour`.
+ """
+
+ item = self._items[index]
+ item.SetColour(c)
+
+
+ def GetAttr(self):
+ """
+ Returns an instance of :class:`UltimateListItemAttr` associated with the first item
+ in the line.
+ """
+
+ item = self._items[0]
+ return item.GetAttr()
+
+
+ def SetAttr(self, attr):
+ """
+ Sets an instance of :class:`UltimateListItemAttr` to the first item in the line.
+
+ :param `attr`: an instance of :class:`UltimateListItemAttr`.
+ """
+
+ item = self._items[0]
+ item.SetAttr(attr)
+
+
+ def SetAttributes(self, dc, attr, highlighted):
+ """
+ Sets various attributes to the input device context.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `attr`: an instance of :class:`UltimateListItemAttr`;
+ :param `highlighted`: ``True`` if the item is highlighted, ``False`` otherwise.
+ """
+
+ listctrl = self._owner.GetParent()
+
+ # fg colour
+ # don't use foreground colour for drawing highlighted items - this might
+ # make them completely invisible (and there is no way to do bit
+ # arithmetics on wxColour, unfortunately)
+
+ if not self._owner.HasAGWFlag(ULC_BORDER_SELECT) and not self._owner.HasAGWFlag(ULC_NO_FULL_ROW_SELECT):
+ if highlighted:
+ if wx.Platform == "__WXMAC__":
+ if self._owner.HasFocus():
+ colText = wx.WHITE
+ else:
+ colText = wx.BLACK
+ else:
+ colText = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
+ else:
+ if attr and attr.HasTextColour():
+ colText = attr.GetTextColour()
+ else:
+ colText = listctrl.GetForegroundColour()
+ elif attr and attr.HasTextColour():
+ colText = attr.GetTextColour()
+ else:
+ colText = listctrl.GetForegroundColour()
+
+ dc.SetTextForeground(colText)
+
+ # font
+ if attr and attr.HasFont():
+ font = attr.GetFont()
+ else:
+ font = listctrl.GetFont()
+
+ dc.SetFont(font)
+
+ # bg colour
+ hasBgCol = attr and attr.HasBackgroundColour()
+
+ if highlighted or hasBgCol:
+ if highlighted:
+ dc.SetBrush(self._owner.GetHighlightBrush())
+ else:
+ dc.SetBrush(wx.Brush(attr.GetBackgroundColour(), wx.SOLID))
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ return True
+
+ return False
+
+
+ def Draw(self, line, dc):
+ """
+ Draws the line on the specified device context.
+
+ :param `line`: an instance of :class:`UltimateListLineData`;
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ item = self._items[0]
+ highlighted = self.IsHighlighted()
+
+ attr = self.GetAttr()
+
+ useGradient, gradientStyle = self._owner._usegradients, self._owner._gradientstyle
+ useVista = self._owner._vistaselection
+ hasFocus = self._owner._hasFocus
+ borderOnly = self._owner.HasAGWFlag(ULC_BORDER_SELECT)
+ drawn = False
+
+ if self.SetAttributes(dc, attr, highlighted):
+ drawn = True
+
+ if not borderOnly:
+
+ if useGradient:
+ if gradientStyle == 0:
+ # horizontal gradient
+ self.DrawHorizontalGradient(dc, self._gi._rectAll, hasFocus)
+ else:
+ # vertical gradient
+ self.DrawVerticalGradient(dc, self._gi._rectAll, hasFocus)
+ elif useVista:
+ # Vista selection style
+ self.DrawVistaRectangle(dc, self._gi._rectAll, hasFocus)
+ else:
+ if highlighted:
+ flags = wx.CONTROL_SELECTED
+ if self._owner.HasFocus() and wx.Platform == "__WXMAC__":
+ flags |= wx.CONTROL_FOCUSED
+
+ wx.RendererNative.Get().DrawItemSelectionRect(self._owner, dc, self._gi._rectHighlight, flags)
+ else:
+ dc.DrawRectangleRect(self._gi._rectHighlight)
+
+ else:
+
+ if borderOnly:
+ dc.SetBrush(wx.WHITE_BRUSH)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.DrawRectangleRect(self._gi._rectAll)
+
+ if item.GetKind() in [1, 2]:
+ rectCheck = self._gi._rectCheck
+ self._owner.DrawCheckbox(dc, rectCheck.x, rectCheck.y, item.GetKind(), item.IsChecked(), item.IsEnabled())
+
+ if item.HasImage():
+ # centre the image inside our rectangle, this looks nicer when items
+ # ae aligned in a row
+ rectIcon = self._gi._rectIcon
+ self._owner.DrawImage(item.GetImage()[0], dc, rectIcon.x, rectIcon.y, True)
+
+ if item.HasText():
+ rectLabel = self._gi._rectLabel
+
+ dc.SetClippingRect(rectLabel)
+ dc.DrawText(item.GetText(), rectLabel.x, rectLabel.y)
+ dc.DestroyClippingRegion()
+
+ if self._owner.HasAGWFlag(ULC_HOT_TRACKING):
+ if line == self._owner._newHotCurrent and not drawn:
+ r = wx.Rect(*self._gi._rectAll)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(wx.NamedColour("orange")))
+ dc.DrawRoundedRectangleRect(r, 3)
+
+ if borderOnly and drawn:
+ dc.SetPen(wx.Pen(wx.Colour(0, 191, 255), 2))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ r = wx.Rect(*self._gi._rectAll)
+ r.x += 1
+ r.y += 1
+ r.width -= 1
+ r.height -= 1
+ dc.DrawRoundedRectangleRect(r, 4)
+
+
+ def HideItemWindow(self, item):
+ """
+ If the input item has a window associated with it, hide it.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ wnd = item.GetWindow()
+ if wnd and wnd.IsShown():
+ wnd.Hide()
+
+
+ def DrawInReportMode(self, dc, line, rect, rectHL, highlighted, current, enabled, oldPN, oldBR):
+ """
+ Draws the line on the specified device context when the parent :class:`UltimateListCtrl`
+ is in report mode.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `line`: an instance of :class:`UltimateListLineData`;
+ :param `rect`: the item client rectangle;
+ :param `rectHL`: the item client rectangle when the item is highlighted;
+ :param `highlighted`: ``True`` if the item is highlighted, ``False`` otherwise;
+ :param `current`: ``True`` if the item is the current item;
+ :param `enabled`: ``True`` if the item is enabled, ``False`` otherwise;
+ :param `oldPN`: an instance of :class:`Pen`, to save and restore at the end of
+ the drawing;
+ :param `oldBR`: an instance of :class:`Brush`, to save and restore at the end of
+ the drawing.
+ """
+
+ attr = self.GetAttr()
+
+ useGradient, gradientStyle = self._owner._usegradients, self._owner._gradientstyle
+ highlightedtextcolour = self._owner._highlightedtextcolour
+
+ useVista = self._owner._vistaselection
+ hasFocus = self._owner._hasFocus
+ borderOnly = self._owner.HasAGWFlag(ULC_BORDER_SELECT)
+ nofullRow = self._owner.HasAGWFlag(ULC_NO_FULL_ROW_SELECT)
+
+ drawn = False
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ if nofullRow:
+
+ x = rect.x + HEADER_OFFSET_X
+ y = rect.y
+ height = rect.height
+
+ for col, item in enumerate(self._items):
+
+ width = self._owner.GetColumnWidth(col)
+ if self._owner.IsColumnShown(col):
+ paintRect = wx.Rect(x, y, self._owner.GetColumnWidth(col)-2*HEADER_OFFSET_X, rect.height)
+ break
+
+ xOld = x
+ x += width
+
+ else:
+
+ paintRect = wx.Rect(*rectHL)
+
+ if self.SetAttributes(dc, attr, highlighted) and enabled:
+
+ drawn = True
+
+ if not borderOnly:
+
+ if useGradient:
+ if gradientStyle == 0:
+ # horizontal gradient
+ self.DrawHorizontalGradient(dc, paintRect, hasFocus)
+ else:
+ # vertical gradient
+ self.DrawVerticalGradient(dc, paintRect, hasFocus)
+ elif useVista:
+ # Vista selection style
+ self.DrawVistaRectangle(dc, paintRect, hasFocus)
+ else:
+ if highlighted:
+ flags = wx.CONTROL_SELECTED
+ if hasFocus:
+ flags |= wx.CONTROL_FOCUSED
+ if current:
+ flags |= wx.CONTROL_CURRENT
+
+ wx.RendererNative.Get().DrawItemSelectionRect(self._owner, dc, paintRect, flags)
+ else:
+ dc.DrawRectangleRect(paintRect)
+
+ else:
+
+ if borderOnly:
+
+ dc.SetBrush(wx.WHITE_BRUSH)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.DrawRectangleRect(paintRect)
+
+ x = rect.x + HEADER_OFFSET_X
+ y = rect.y
+ height = rect.height
+ boldFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont.SetWeight(wx.BOLD)
+
+ for col, item in enumerate(self._items):
+
+ if not self._owner.IsColumnShown(col):
+ self.HideItemWindow(item)
+ continue
+
+ width = self._owner.GetColumnWidth(col)
+ xOld = x
+ x += width
+
+ if item.GetCustomRenderer():
+ customRect = wx.Rect(xOld-HEADER_OFFSET_X, rect.y, width, rect.height)
+ item.GetCustomRenderer().DrawSubItem(dc, customRect, line, highlighted, enabled)
+ continue
+
+ overflow = item.GetOverFlow() and item.HasText()
+
+ if item.GetKind() in [1, 2]:
+
+ # We got a checkbox-type item
+ ix, iy = self._owner.GetCheckboxImageSize()
+ checked = item.IsChecked()
+ self._owner.DrawCheckbox(dc, xOld, y + (height-iy+1)/2, item.GetKind(), checked, enabled)
+ xOld += ix
+ width -= ix
+
+ if item.HasImage():
+
+ images = item.GetImage()
+
+ for img in images:
+
+ ix, iy = self._owner.GetImageSize([img])
+ self._owner.DrawImage(img, dc, xOld, y + (height-iy)/2, enabled)
+
+ xOld += ix
+ width -= ix
+
+## if images:
+## width -= IMAGE_MARGIN_IN_REPORT_MODE - MARGIN_BETWEEN_TEXT_AND_ICON
+
+ wnd = item.GetWindow()
+ xSize = 0
+ if wnd:
+ xSize, ySize = item.GetWindowSize()
+ wndx = xOld - HEADER_OFFSET_X + width - xSize - 3
+ xa, ya = self._owner.CalcScrolledPosition((0, rect.y))
+ wndx += xa
+ if rect.height > ySize and not item._expandWin:
+ ya += (rect.height - ySize)/2
+
+ itemRect = wx.Rect(xOld-2*HEADER_OFFSET_X, rect.y, width-xSize-HEADER_OFFSET_X, rect.height)
+ if overflow:
+ itemRect = wx.Rect(xOld-2*HEADER_OFFSET_X, rect.y, rectHL.width-xSize-HEADER_OFFSET_X, rect.height)
+
+ dc.SetClippingRect(itemRect)
+
+ if item.HasBackgroundColour():
+ dc.SetBrush(wx.Brush(item.GetBackgroundColour()))
+ dc.SetPen(wx.Pen(item.GetBackgroundColour()))
+ dc.DrawRectangleRect(itemRect)
+ dc.SetBrush(oldBR)
+ dc.SetPen(oldPN)
+
+ if item.HasText():
+
+ coloured = item.HasColour()
+
+ c = dc.GetTextForeground()
+ oldTF = wx.Colour(c.Red(),c.Green(),c.Blue())
+ oldFT = dc.GetFont()
+
+ font = item.HasFont()
+
+ if not enabled:
+ dc.SetTextForeground(self._owner.GetDisabledTextColour())
+ else:
+ if coloured:
+ dc.SetTextForeground(item.GetColour())
+ elif useVista and drawn:
+ dc.SetTextForeground(wx.BLACK)
+
+ if highlightedtextcolour and current:
+ dc.SetTextForeground(highlightedtextcolour)
+
+ if item.IsHyperText():
+ dc.SetFont(self._owner.GetHyperTextFont())
+ if item.GetVisited():
+ dc.SetTextForeground(self._owner.GetHyperTextVisitedColour())
+ else:
+ dc.SetTextForeground(self._owner.GetHyperTextNewColour())
+ else:
+ if font:
+ dc.SetFont(item.GetFont())
+
+ itemRect = wx.Rect(itemRect.x+MARGIN_BETWEEN_TEXT_AND_ICON, itemRect.y, itemRect.width-8, itemRect.height)
+ self.DrawTextFormatted(dc, item.GetText(), line, col, itemRect, overflow)
+
+ if coloured:
+ dc.SetTextForeground(oldTF)
+
+ if font:
+ dc.SetFont(oldFT)
+
+ dc.DestroyClippingRegion()
+
+ if wnd:
+ if not wnd.IsShown():
+ wnd.Show()
+
+ if item._expandWin:
+ wRect = wx.Rect(*itemRect)
+ wRect.x += xa + 2
+ wRect.width = width - 8
+ wRect.y = ya + 2
+ wRect.height -= 4
+ if wnd.GetRect() != wRect:
+ wnd.SetRect(wRect)
+ else:
+ if wnd.GetPosition() != (wndx, ya):
+ wnd.SetPosition((wndx, ya))
+
+ if self._owner.HasAGWFlag(ULC_HOT_TRACKING):
+ if line == self._owner._newHotCurrent and not drawn:
+ r = wx.Rect(*paintRect)
+ r.y += 1
+ r.height -= 1
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(wx.NamedColour("orange")))
+ dc.DrawRoundedRectangleRect(r, 3)
+ dc.SetPen(oldPN)
+
+ if borderOnly and drawn:
+ dc.SetPen(wx.Pen(wx.Colour(0, 191, 255), 2))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ rect = wx.Rect(*paintRect)
+ rect.y += 1
+ rect.height -= 1
+ dc.DrawRoundedRectangleRect(rect, 3)
+ dc.SetPen(oldPN)
+
+
+ def DrawTextFormatted(self, dc, text, row, col, itemRect, overflow):
+ """
+ Draws the item text, correctly formatted.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `text`: the item text;
+ :param `row`: the line number to which this item belongs to;
+ :param `col`: the column number to which this item belongs to;
+ :param `itemRect`: the item client rectangle;
+ :param `overflow`: ``True`` if the item should overflow into neighboring columns,
+ ``False`` otherwise.
+ """
+ # determine if the string can fit inside the current width
+ w, h, dummy = dc.GetMultiLineTextExtent(text)
+ width = itemRect.width
+
+ shortItems = self._owner._shortItems
+ tuples = (row, col)
+
+ # it can, draw it using the items alignment
+ item = self._owner.GetColumn(col)
+ align = item.GetAlign()
+
+ if align == ULC_FORMAT_RIGHT:
+ textAlign = wx.ALIGN_RIGHT
+ elif align == ULC_FORMAT_CENTER:
+ textAlign = wx.ALIGN_CENTER
+ else:
+ textAlign = wx.ALIGN_LEFT
+
+ if w <= width:
+
+ if tuples in shortItems:
+ shortItems.remove(tuples)
+
+ dc.DrawLabel(text, itemRect, textAlign|wx.ALIGN_CENTER_VERTICAL)
+
+ else: # otherwise, truncate and add an ellipsis if possible
+
+ if tuples not in shortItems:
+ shortItems.append(tuples)
+
+ # determine the base width
+ ellipsis = "..."
+ base_w, h = dc.GetTextExtent(ellipsis)
+
+ # continue until we have enough space or only one character left
+
+ newText = text.split("\n")
+ theText = ""
+
+ for text in newText:
+
+ lenText = len(text)
+ drawntext = text
+ w, dummy = dc.GetTextExtent(text)
+
+ while lenText > 1:
+
+ if w + base_w <= width:
+ break
+
+ w_c, h_c = dc.GetTextExtent(drawntext[-1])
+ drawntext = drawntext[0:-1]
+ lenText -= 1
+ w -= w_c
+
+ # if still not enough space, remove ellipsis characters
+ while len(ellipsis) > 0 and w + base_w > width:
+ ellipsis = ellipsis[0:-1]
+ base_w, h = dc.GetTextExtent(ellipsis)
+
+ theText += drawntext + ellipsis + "\n"
+
+ theText = theText.rstrip()
+ # now draw the text
+ dc.DrawLabel(theText, itemRect, textAlign|wx.ALIGN_CENTER_VERTICAL)
+
+
+ def DrawVerticalGradient(self, dc, rect, hasfocus):
+ """
+ Gradient fill from colour 1 to colour 2 from top to bottom.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the rectangle to be filled with the gradient shading;
+ :param `hasfocus`: ``True`` if the main :class:`UltimateListCtrl` has focus, ``False``
+ otherwise.
+ """
+
+ oldpen = dc.GetPen()
+ oldbrush = dc.GetBrush()
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ # calculate gradient coefficients
+ if hasfocus:
+ col2 = self._owner._secondcolour
+ col1 = self._owner._firstcolour
+ else:
+ col2 = self._owner._highlightUnfocusedBrush.GetColour()
+ col1 = self._owner._highlightUnfocusedBrush2.GetColour()
+
+ r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+ r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+ flrect = float(rect.height)
+
+ rstep = float((r2 - r1)) / flrect
+ gstep = float((g2 - g1)) / flrect
+ bstep = float((b2 - b1)) / flrect
+
+ rf, gf, bf = 0, 0, 0
+
+ for y in xrange(rect.y, rect.y + rect.height):
+ currCol = (r1 + rf, g1 + gf, b1 + bf)
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.DrawRectangle(rect.x, y, rect.width, 1)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+ dc.SetPen(oldpen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangleRect(rect)
+ dc.SetBrush(oldbrush)
+
+
+ def DrawHorizontalGradient(self, dc, rect, hasfocus):
+ """
+ Gradient fill from colour 1 to colour 2 from left to right.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the rectangle to be filled with the gradient shading;
+ :param `hasfocus`: ``True`` if the main :class:`UltimateListCtrl` has focus, ``False``
+ otherwise.
+ """
+
+ oldpen = dc.GetPen()
+ oldbrush = dc.GetBrush()
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ # calculate gradient coefficients
+
+ if hasfocus:
+ col2 = self._owner._secondcolour
+ col1 = self._owner._firstcolour
+ else:
+ col2 = self._owner._highlightUnfocusedBrush.GetColour()
+ col1 = self._owner._highlightUnfocusedBrush2.GetColour()
+
+ r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+ r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+ flrect = float(rect.width)
+
+ rstep = float((r2 - r1)) / flrect
+ gstep = float((g2 - g1)) / flrect
+ bstep = float((b2 - b1)) / flrect
+
+ rf, gf, bf = 0, 0, 0
+
+ for x in xrange(rect.x, rect.x + rect.width):
+ currCol = (int(r1 + rf), int(g1 + gf), int(b1 + bf))
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.DrawRectangle(x, rect.y, 1, rect.height)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+ dc.SetPen(oldpen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangleRect(rect)
+ dc.SetBrush(oldbrush)
+
+
+ def DrawVistaRectangle(self, dc, rect, hasfocus):
+ """
+ Draws the selected item(s) with the Windows Vista style.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: the rectangle to be filled with the gradient shading;
+ :param `hasfocus`: ``True`` if the main :class:`UltimateListCtrl` has focus, ``False``
+ otherwise.
+ """
+
+ if hasfocus:
+
+ outer = _rgbSelectOuter
+ inner = _rgbSelectInner
+ top = _rgbSelectTop
+ bottom = _rgbSelectBottom
+
+ else:
+
+ outer = _rgbNoFocusOuter
+ inner = _rgbNoFocusInner
+ top = _rgbNoFocusTop
+ bottom = _rgbNoFocusBottom
+
+ oldpen = dc.GetPen()
+ oldbrush = dc.GetBrush()
+
+ bdrRect = wx.Rect(*rect.Get())
+ filRect = wx.Rect(*rect.Get())
+ filRect.Deflate(1,1)
+
+ r1, g1, b1 = int(top.Red()), int(top.Green()), int(top.Blue())
+ r2, g2, b2 = int(bottom.Red()), int(bottom.Green()), int(bottom.Blue())
+
+ flrect = float(filRect.height)
+ if flrect < 1:
+ flrect = self._owner._lineHeight
+
+ rstep = float((r2 - r1)) / flrect
+ gstep = float((g2 - g1)) / flrect
+ bstep = float((b2 - b1)) / flrect
+
+ rf, gf, bf = 0, 0, 0
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ for y in xrange(filRect.y, filRect.y + filRect.height):
+ currCol = (r1 + rf, g1 + gf, b1 + bf)
+ dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+ dc.DrawRectangle(filRect.x, y, filRect.width, 1)
+ rf = rf + rstep
+ gf = gf + gstep
+ bf = bf + bstep
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(outer))
+ dc.DrawRoundedRectangleRect(bdrRect, 3)
+ bdrRect.Deflate(1, 1)
+ dc.SetPen(wx.Pen(inner))
+ dc.DrawRoundedRectangleRect(bdrRect, 2)
+
+ dc.SetPen(oldpen)
+ dc.SetBrush(oldbrush)
+
+
+ def Highlight(self, on):
+ """
+ Sets the current line as highlighted or not highlighted.
+
+ :param `on`: ``True`` to set the current line as highlighted, ``False``
+ otherwise.
+ """
+
+ if on == self._highlighted:
+ return False
+
+ self._highlighted = on
+
+ return True
+
+
+ def ReverseHighlight(self):
+ """
+ Reverses the line highlighting, switching it off if it was on and vice-versa.
+ """
+
+ self.Highlight(not self.IsHighlighted())
+
+
+
+#-----------------------------------------------------------------------------
+# UltimateListHeaderWindow (internal)
+#-----------------------------------------------------------------------------
+
+class UltimateListHeaderWindow(wx.PyControl):
+ """
+ This class holds the header window for :class:`UltimateListCtrl`.
+ """
+
+ def __init__(self, win, id, owner, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, validator=wx.DefaultValidator,
+ name="UltimateListCtrlcolumntitles", isFooter=False):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `owner`: an instance of :class:`UltimateListCtrl`;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the window style;
+ :param `validator`: the window validator;
+ :param `name`: the window name;
+ :param `isFooter`: ``True`` if the :class:`UltimateListHeaderWindow` is in a footer
+ position, ``False`` otherwise.
+ """
+
+ wx.PyControl.__init__(self, win, id, pos, size, style|wx.NO_BORDER, validator, name)
+
+ self._isFooter = isFooter
+ self._owner = owner
+ self._currentCursor = wx.NullCursor
+ self._resizeCursor = wx.StockCursor(wx.CURSOR_SIZEWE)
+ self._isDragging = False
+ self._headerHeight = None
+ self._footerHeight = None
+
+ # Custom renderer for every column
+ self._headerCustomRenderer = None
+
+ # column being resized or -1
+ self._column = -1
+
+ # divider line position in logical (unscrolled) coords
+ self._currentX = 0
+
+ # minimal position beyond which the divider line can't be dragged in
+ # logical coords
+ self._minX = 0
+
+ # needs refresh
+ self._dirty = False
+ self._hasFont = False
+ self._sendSetColumnWidth = False
+ self._colToSend = -1
+ self._widthToSend = 0
+ self._leftDown = False
+ self._enter = False
+ self._currentColumn = -1
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnterWindow)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+
+ if _USE_VISATTR:
+
+ attr = wx.Panel.GetClassDefaultAttributes()
+ self.SetOwnForegroundColour(attr.colFg)
+ self.SetOwnBackgroundColour(attr.colBg)
+ if not self._hasFont:
+ self.SetOwnFont(attr.font)
+
+ else:
+
+ self.SetOwnForegroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT))
+ self.SetOwnBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
+
+ if not self._hasFont:
+ self.SetOwnFont(wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT))
+
+
+ def SetCustomRenderer(self, renderer=None):
+ """
+ Associate a custom renderer with the header - all columns will use it
+
+ :param `renderer`: a class able to correctly render header buttons
+
+ :note: the renderer class **must** implement the methods `DrawHeaderButton`
+ and `GetForegroundColor`.
+ """
+
+ if not self._owner.HasAGWFlag(ULC_REPORT):
+ raise Exception("Custom renderers can be used on with style = ULC_REPORT")
+
+ self._headerCustomRenderer = renderer
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+ """
+
+ if not self._isFooter:
+ if self._headerHeight is not None:
+ self.GetParent()._headerHeight = self._headerHeight
+ return wx.Size(200, self._headerHeight)
+ else:
+ if self._footerHeight is not None:
+ self.GetParent()._footerHeight = self._footerHeight
+ return wx.Size(200, self._footerHeight)
+
+ w, h, d, dummy = self.GetFullTextExtent("Hg")
+ maxH = self.GetTextHeight()
+ nativeH = wx.RendererNative.Get().GetHeaderButtonHeight(self.GetParent())
+
+ if not self._isFooter:
+ maxH = max(max(h, maxH), nativeH)
+ maxH += d
+ self.GetParent()._headerHeight = maxH
+ else:
+ maxH = max(h, nativeH)
+ maxH += d
+ self.GetParent()._footerHeight = maxH
+
+ return wx.Size(200, maxH)
+
+
+ def GetWindowHeight(self):
+ """ Returns the :class:`UltimateListHeaderWindow` height, in pixels. """
+
+ return self.DoGetBestSize()
+
+
+ def IsColumnShown(self, column):
+ """
+ Returns ``True`` if the input column is shown, ``False`` if it is hidden.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ if column < 0 or column >= self._owner.GetColumnCount():
+ raise Exception("Invalid column")
+
+ return self._owner.IsColumnShown(column)
+
+
+ # shift the DC origin to match the position of the main window horz
+ # scrollbar: this allows us to always use logical coords
+ def AdjustDC(self, dc):
+ """
+ Shifts the :class:`DC` origin to match the position of the main window horizontal
+ scrollbar: this allows us to always use logical coordinates.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ xpix, dummy = self._owner.GetScrollPixelsPerUnit()
+ x, dummy = self._owner.GetViewStart()
+
+ # account for the horz scrollbar offset
+ dc.SetDeviceOrigin(-x*xpix, 0)
+
+
+ def GetTextHeight(self):
+ """ Returns the column text height, in pixels. """
+
+ maxH = 0
+ numColumns = self._owner.GetColumnCount()
+ dc = wx.ClientDC(self)
+ for i in xrange(numColumns):
+
+ if not self.IsColumnShown(i):
+ continue
+
+ item = self._owner.GetColumn(i)
+ if item.GetFont().IsOk():
+ dc.SetFont(item.GetFont())
+ else:
+ dc.SetFont(self.GetFont())
+
+ wLabel, hLabel, dummy = dc.GetMultiLineTextExtent(item.GetText())
+ maxH = max(maxH, hLabel)
+
+ return maxH
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`UltimateListHeaderWindow`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.BufferedPaintDC(self)
+ # width and height of the entire header window
+ w, h = self.GetClientSize()
+ w, dummy = self._owner.CalcUnscrolledPosition(w, 0)
+ dc.SetBrush(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)))
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.DrawRectangle(0, -1, w, h+2)
+
+ self.AdjustDC(dc)
+
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ dc.SetTextForeground(self.GetForegroundColour())
+
+ x = HEADER_OFFSET_X
+
+ numColumns = self._owner.GetColumnCount()
+ item = UltimateListItem()
+ renderer = wx.RendererNative.Get()
+ enabled = self.GetParent().IsEnabled()
+ virtual = self._owner.IsVirtual()
+ isFooter = self._isFooter
+
+ for i in xrange(numColumns):
+
+ # Reset anything in the dc that a custom renderer might have changed
+ dc.SetTextForeground(self.GetForegroundColour())
+
+ if x >= w:
+ break
+
+ if not self.IsColumnShown(i):
+ continue # do next column if not shown
+
+ item = self._owner.GetColumn(i)
+ wCol = item._width
+
+ cw = wCol
+ ch = h
+
+ flags = 0
+ if not enabled:
+ flags |= wx.CONTROL_DISABLED
+
+ # NB: The code below is not really Mac-specific, but since we are close
+ # to 2.8 release and I don't have time to test on other platforms, I
+ # defined this only for wxMac. If this behavior is desired on
+ # other platforms, please go ahead and revise or remove the #ifdef.
+
+ if "__WXMAC__" in wx.PlatformInfo:
+ if not virtual and item._mask & ULC_MASK_STATE and item._state & ULC_STATE_SELECTED:
+ flags |= wx.CONTROL_SELECTED
+
+ if i == 0:
+ flags |= wx.CONTROL_SPECIAL # mark as first column
+
+ if i == self._currentColumn:
+ if self._leftDown:
+ flags |= wx.CONTROL_PRESSED
+ else:
+ if self._enter:
+ flags |= wx.CONTROL_CURRENT
+
+ # the width of the rect to draw: make it smaller to fit entirely
+ # inside the column rect
+ header_rect = wx.Rect(x, HEADER_OFFSET_Y-1, cw, ch)
+
+ if self._headerCustomRenderer != None:
+ self._headerCustomRenderer.DrawHeaderButton(dc, header_rect, flags)
+
+ # The custom renderer will specify the color to draw the header text and buttons
+ dc.SetTextForeground(self._headerCustomRenderer.GetForegroundColour())
+
+ elif item._mask & ULC_MASK_RENDERER:
+ item.GetCustomRenderer().DrawHeaderButton(dc, header_rect, flags)
+
+ # The custom renderer will specify the color to draw the header text and buttons
+ dc.SetTextForeground(item.GetCustomRenderer().GetForegroundColour())
+ else:
+ renderer.DrawHeaderButton(self, dc, header_rect, flags)
+
+
+ # see if we have enough space for the column label
+ if isFooter:
+ if item.GetFooterFont().IsOk():
+ dc.SetFont(item.GetFooterFont())
+ else:
+ dc.SetFont(self.GetFont())
+ else:
+ if item.GetFont().IsOk():
+ dc.SetFont(item.GetFont())
+ else:
+ dc.SetFont(self.GetFont())
+
+ wcheck = hcheck = 0
+ kind = (isFooter and [item.GetFooterKind()] or [item.GetKind()])[0]
+ checked = (isFooter and [item.IsFooterChecked()] or [item.IsChecked()])[0]
+
+ if kind in [1, 2]:
+ # We got a checkbox-type item
+ ix, iy = self._owner.GetCheckboxImageSize()
+ # We draw it on the left, always
+ self._owner.DrawCheckbox(dc, x + HEADER_OFFSET_X, HEADER_OFFSET_Y + (h - 4 - iy)/2, kind, checked, enabled)
+ wcheck += ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE
+ cw -= ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE
+
+ # for this we need the width of the text
+ text = (isFooter and [item.GetFooterText()] or [item.GetText()])[0]
+ wLabel, hLabel, dummy = dc.GetMultiLineTextExtent(text)
+ wLabel += 2*EXTRA_WIDTH
+
+ # and the width of the icon, if any
+ image = (isFooter and [item._footerImage] or [item._image])[0]
+
+ if image:
+ imageList = self._owner._small_image_list
+ if imageList:
+ for img in image:
+ if img >= 0:
+ ix, iy = imageList.GetSize(img)
+ wLabel += ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE
+
+ else:
+
+ imageList = None
+
+ # ignore alignment if there is not enough space anyhow
+ align = (isFooter and [item.GetFooterAlign()] or [item.GetAlign()])[0]
+ align = (wLabel < cw and [align] or [ULC_FORMAT_LEFT])[0]
+
+ if align == ULC_FORMAT_LEFT:
+ xAligned = x + wcheck
+
+ elif align == ULC_FORMAT_RIGHT:
+ xAligned = x + cw - wLabel - HEADER_OFFSET_X
+
+ elif align == ULC_FORMAT_CENTER:
+ xAligned = x + wcheck + (cw - wLabel)/2
+
+ # if we have an image, draw it on the right of the label
+ if imageList:
+ for indx, img in enumerate(image):
+ if img >= 0:
+ imageList.Draw(img, dc,
+ xAligned + wLabel - (ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE)*(indx+1),
+ HEADER_OFFSET_Y + (h - 4 - iy)/2,
+ wx.IMAGELIST_DRAW_TRANSPARENT)
+
+ cw -= ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE
+
+ # draw the text clipping it so that it doesn't overwrite the column
+ # boundary
+ dc.SetClippingRegion(x, HEADER_OFFSET_Y, cw, h - 4)
+ self.DrawTextFormatted(dc, text, wx.Rect(xAligned+EXTRA_WIDTH, HEADER_OFFSET_Y, cw-EXTRA_WIDTH, h-4))
+
+ x += wCol
+ dc.DestroyClippingRegion()
+
+ # Fill in what's missing to the right of the columns, otherwise we will
+ # leave an unpainted area when columns are removed (and it looks better)
+ if x < w:
+ header_rect = wx.Rect(x, HEADER_OFFSET_Y, w - x, h)
+ if self._headerCustomRenderer != None:
+ # Why does the custom renderer need this adjustment??
+ header_rect.x = header_rect.x - 1
+ header_rect.y = header_rect.y - 1
+ self._headerCustomRenderer.DrawHeaderButton(dc, header_rect, wx.CONTROL_DIRTY)
+ else:
+ renderer.DrawHeaderButton(self, dc, header_rect, wx.CONTROL_DIRTY) # mark as last column
+
+
+ def DrawTextFormatted(self, dc, text, rect):
+ """
+ Draws the item text, correctly formatted.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `text`: the item text;
+ :param `rect`: the item client rectangle.
+ """
+
+ # determine if the string can fit inside the current width
+ w, h, dummy = dc.GetMultiLineTextExtent(text)
+ width = rect.width
+
+ if w <= width:
+
+ dc.DrawLabel(text, rect, wx.ALIGN_CENTER_VERTICAL)
+
+ else:
+
+ # determine the base width
+ ellipsis = "..."
+ base_w, h = dc.GetTextExtent(ellipsis)
+
+ # continue until we have enough space or only one character left
+
+ newText = text.split("\n")
+ theText = ""
+
+ for text in newText:
+
+ lenText = len(text)
+ drawntext = text
+ w, dummy = dc.GetTextExtent(text)
+
+ while lenText > 1:
+
+ if w + base_w <= width:
+ break
+
+ w_c, h_c = dc.GetTextExtent(drawntext[-1])
+ drawntext = drawntext[0:-1]
+ lenText -= 1
+ w -= w_c
+
+ # if still not enough space, remove ellipsis characters
+ while len(ellipsis) > 0 and w + base_w > width:
+ ellipsis = ellipsis[0:-1]
+ base_w, h = dc.GetTextExtent(ellipsis)
+
+ theText += drawntext + ellipsis + "\n"
+
+ theText = theText.rstrip()
+ dc.DrawLabel(theText, rect, wx.ALIGN_CENTER_VERTICAL)
+
+
+ def OnInternalIdle(self):
+ """
+ This method is normally only used internally, but sometimes an application
+ may need it to implement functionality that should not be disabled by an
+ application defining an `OnIdle` handler in a derived class.
+
+ This method may be used to do delayed painting, for example, and most
+ implementations call :meth:`Window.UpdateWindowUI` in order to send update events
+ to the window in idle time.
+ """
+
+ wx.PyControl.OnInternalIdle(self)
+
+ if self._isFooter:
+ return
+
+ if self._sendSetColumnWidth:
+ self._owner.SetColumnWidth(self._colToSend, self._widthToSend)
+ self._sendSetColumnWidth = False
+
+
+ def DrawCurrent(self):
+ """ Force the redrawing of the column window. """
+
+ self._sendSetColumnWidth = True
+ self._colToSend = self._column
+ self._widthToSend = self._currentX - self._minX
+
+
+ def OnMouse(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` event for :class:`UltimateListHeaderWindow`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # we want to work with logical coords
+ x, dummy = self._owner.CalcUnscrolledPosition(event.GetX(), 0)
+ y = event.GetY()
+
+ columnX, columnY = x, y
+
+ if self._isDragging:
+
+ self.SendListEvent(wxEVT_COMMAND_LIST_COL_DRAGGING, event.GetPosition())
+
+ # we don't draw the line beyond our window, but we allow dragging it
+ # there
+
+ w, dummy = self.GetClientSize()
+ w, dummy = self._owner.CalcUnscrolledPosition(w, 0)
+ w -= 6
+
+ # erase the line if it was drawn
+ if self._currentX < w:
+ self.DrawCurrent()
+
+ if event.ButtonUp():
+
+ self.ReleaseMouse()
+ self._isDragging = False
+ self._dirty = True
+ self._owner.SetColumnWidth(self._column, self._currentX - self._minX)
+ self.SendListEvent(wxEVT_COMMAND_LIST_COL_END_DRAG, event.GetPosition())
+
+ else:
+
+ if x > self._minX + 7:
+ self._currentX = x
+ else:
+ self._currentX = self._minX + 7
+
+ # draw in the new location
+ if self._currentX < w:
+ self.DrawCurrent()
+
+ else: # not dragging
+
+ self._minX = 0
+ hit_border = False
+
+ # end of the current column
+ xpos = 0
+
+ # find the column where this event occurred
+ countCol = self._owner.GetColumnCount()
+ broken = False
+ tipCol = -1
+
+ for col in xrange(countCol):
+
+ if not self.IsColumnShown(col):
+ continue
+
+ xpos += self._owner.GetColumnWidth(col)
+ self._column = col
+
+ if abs(x-xpos) < 3 and y < 22:
+ # near the column border
+ hit_border = True
+ broken = True
+ tipCol = col
+ break
+
+ if x < xpos:
+ # inside the column
+ broken = True
+ tipCol = col
+ break
+
+ self._minX = xpos
+
+ if not broken:
+ self._column = -1
+
+ if tipCol >= 0:
+ # First check to see if we have a tooltip to display
+ colItem = self._owner.GetColumn(col)
+ if colItem.GetToolTip() != "":
+ self.SetToolTipString(colItem.GetToolTip())
+ else:
+ self.SetToolTipString("")
+
+ if event.LeftUp():
+ self._leftDown = False
+ self.Refresh()
+
+ if event.LeftDown() or event.RightUp():
+
+ if hit_border and event.LeftDown():
+
+ if not self._isFooter:
+
+ if self.SendListEvent(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG,
+ event.GetPosition()):
+
+ self._isDragging = True
+ self._currentX = x
+ self.CaptureMouse()
+ self.DrawCurrent()
+
+ #else: column resizing was vetoed by the user code
+
+ else: # click on a column
+
+ # record the selected state of the columns
+ if event.LeftDown():
+
+ for i in xrange(self._owner.GetColumnCount()):
+
+ if not self.IsColumnShown(col):
+ continue
+
+ colItem = self._owner.GetColumn(i)
+ state = colItem.GetState()
+
+ if i == self._column:
+ colItem.SetState(state | ULC_STATE_SELECTED)
+ theX = x
+ else:
+ colItem.SetState(state & ~ULC_STATE_SELECTED)
+
+ self._leftDown = True
+ self._owner.SetColumn(i, colItem)
+ x += self._owner.GetColumnWidth(i)
+
+ if self.HandleColumnCheck(self._column, event.GetPosition()):
+ return
+
+ if not self._isFooter:
+ self.SendListEvent((event.LeftDown() and [wxEVT_COMMAND_LIST_COL_CLICK] or \
+ [wxEVT_COMMAND_LIST_COL_RIGHT_CLICK])[0], event.GetPosition())
+ else:
+ self.SendListEvent((event.LeftDown() and [wxEVT_COMMAND_LIST_FOOTER_CLICK] or \
+ [wxEVT_COMMAND_LIST_FOOTER_RIGHT_CLICK])[0], event.GetPosition())
+
+ self._leftDown = True
+ self._currentColumn = self._column
+
+ elif event.Moving():
+
+ setCursor = False
+
+ if not self._isFooter:
+ if hit_border:
+
+ setCursor = self._currentCursor == wx.STANDARD_CURSOR
+ self._currentCursor = self._resizeCursor
+
+ else:
+
+ setCursor = self._currentCursor != wx.STANDARD_CURSOR
+ self._currentCursor = wx.STANDARD_CURSOR
+
+ if setCursor:
+ self.SetCursor(self._currentCursor)
+ else:
+ column = self.HitTestColumn(columnX, columnY)
+ self._enter = True
+ self._currentColumn = column
+
+ if _VERSION_STRING < "2.9":
+ leftDown = wx.GetMouseState().LeftDown()
+ else:
+ leftDown = wx.GetMouseState().LeftIsDown()
+
+ self._leftDown = leftDown
+
+ self.Refresh()
+
+ elif event.ButtonDClick():
+
+ self.HandleColumnCheck(self._column, event.GetPosition())
+
+
+ def HandleColumnCheck(self, column, pos):
+ """
+ Handles the case in which a column contains a checkbox-like item.
+
+ :param `column`: the column index;
+ :param `pos`: the mouse position.
+ """
+
+ if column < 0 or column >= self._owner.GetColumnCount():
+ return False
+
+ colItem = self._owner.GetColumn(column)
+ # Let's see if it is a checkbox-type item
+
+ kind = (self._isFooter and [colItem.GetFooterKind()] or [colItem.GetKind()])[0]
+ if kind not in [1, 2]:
+ return False
+
+ x = HEADER_OFFSET_X
+
+ for i in xrange(self._owner.GetColumnCount()):
+
+ if not self.IsColumnShown(i):
+ continue
+
+ if i == self._column:
+ theX = x
+ break
+ x += self._owner.GetColumnWidth(i)
+
+ parent = self.GetParent()
+
+ w, h = self.GetClientSize()
+ ix, iy = self._owner.GetCheckboxImageSize()
+ rect = wx.Rect(theX + HEADER_OFFSET_X, HEADER_OFFSET_Y + (h - 4 - iy)/2, ix, iy)
+
+ if rect.Contains(pos):
+ # User clicked on the checkbox
+ evt = (self._isFooter and [wxEVT_COMMAND_LIST_FOOTER_CHECKING] or [wxEVT_COMMAND_LIST_COL_CHECKING])[0]
+ if self.SendListEvent(evt, pos):
+ # No veto for the item checking
+ if self._isFooter:
+ isChecked = colItem.IsFooterChecked()
+ colItem.CheckFooter(not isChecked)
+ else:
+ isChecked = colItem.IsChecked()
+ colItem.Check(not isChecked)
+
+ self._owner.SetColumn(column, colItem)
+ evt = (self._isFooter and [wxEVT_COMMAND_LIST_FOOTER_CHECKED] or [wxEVT_COMMAND_LIST_COL_CHECKED])[0]
+ self.SendListEvent(evt, pos)
+ self.RefreshRect(rect)
+
+ if self._isFooter:
+ return True
+
+ if parent.HasAGWFlag(ULC_AUTO_CHECK_CHILD):
+ self._owner.AutoCheckChild(isChecked, self._column)
+ elif parent.HasAGWFlag(ULC_AUTO_TOGGLE_CHILD):
+ self._owner.AutoToggleChild(self._column)
+
+ return True
+
+ return False
+
+
+ def OnEnterWindow(self, event):
+ """
+ Handles the ``wx.EVT_ENTER_WINDOW`` event for :class:`UltimateListHeaderWindow`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ x, y = self._owner.CalcUnscrolledPosition(*self.ScreenToClient(wx.GetMousePosition()))
+ column = self.HitTestColumn(x, y)
+
+ if _VERSION_STRING < "2.9":
+ leftDown = wx.GetMouseState().LeftDown()
+ else:
+ leftDown = wx.GetMouseState().LeftIsDown()
+
+ self._leftDown = leftDown
+ self._enter = column >= 0 and column < self._owner.GetColumnCount()
+ self._currentColumn = column
+ self.Refresh()
+
+
+ def OnLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`UltimateListHeaderWindow`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self._enter = False
+ self._leftDown = False
+
+ self._currentColumn = -1
+ self.Refresh()
+
+
+ def HitTestColumn(self, x, y):
+ """
+ HitTest method for column headers.
+
+ :param `x`: the mouse `x` position;
+ :param `y`: the mouse `y` position.
+
+ :return: The column index if any column client rectangle contains the mouse
+ position, ``wx.NOT_FOUND`` otherwise.
+ """
+
+ xOld = 0
+
+ for i in xrange(self._owner.GetColumnCount()):
+ if not self.IsColumnShown(i):
+ continue
+
+ xOld += self._owner.GetColumnWidth(i)
+ if x <= xOld:
+ return i
+
+ return -1
+
+
+ def OnSetFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`UltimateListHeaderWindow`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ self._owner.SetFocusIgnoringChildren()
+ self._owner.Update()
+
+
+ def SendListEvent(self, eventType, pos):
+ """
+ Sends a :class:`UltimateListEvent` for the parent window.
+
+ :param `eventType`: the event type;
+ :param `pos`: an instance of :class:`Point`.
+ """
+
+ parent = self.GetParent()
+ le = UltimateListEvent(eventType, parent.GetId())
+ le.SetEventObject(parent)
+ le.m_pointDrag = pos
+
+ # the position should be relative to the parent window, not
+ # this one for compatibility with MSW and common sense: the
+ # user code doesn't know anything at all about this header
+ # window, so why should it get positions relative to it?
+ le.m_pointDrag.y -= self.GetSize().y
+
+ le.m_col = self._column
+ return (not parent.GetEventHandler().ProcessEvent(le) or le.IsAllowed())
+
+
+ def GetOwner(self):
+ """ Returns the header window owner, an instance of :class:`UltimateListCtrl`. """
+
+ return self._owner
+
+
+
+#-----------------------------------------------------------------------------
+# UltimateListRenameTimer (internal)
+#-----------------------------------------------------------------------------
+
+class UltimateListRenameTimer(wx.Timer):
+ """ Timer used for enabling in-place edit. """
+
+ def __init__(self, owner):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `owner`: an instance of :class:`UltimateListCtrl`.
+ """
+
+ wx.Timer.__init__(self)
+ self._owner = owner
+
+
+ def Notify(self):
+ """ The timer has expired. """
+
+ self._owner.OnRenameTimer()
+
+
+#-----------------------------------------------------------------------------
+# UltimateListTextCtrl (internal)
+#-----------------------------------------------------------------------------
+
+class UltimateListTextCtrl(ExpandoTextCtrl):
+ """
+ Control used for in-place edit.
+
+ This is a subclass of `ExpandoTextCtrl` as :class:`UltimateListCtrl` supports multiline
+ text items.
+
+ :note: To add a newline character in a multiline item, press ``Shift`` + ``Enter``
+ as the ``Enter`` key alone is consumed by :class:`UltimateListCtrl` to finish
+ the editing and ``Ctrl`` + ``Enter`` is consumed by the platform for tab navigation.
+ """
+
+ def __init__(self, owner, itemEdit):
+ """
+ Default class constructor.
+ For internal use: do not call it in your code!
+
+ :param `owner`: the control parent (an instance of :class:`UltimateListCtrl` );
+ :param `itemEdit`: an instance of :class:`UltimateListItem`.
+ """
+
+ self._startValue = owner.GetItemText(itemEdit)
+ self._currentValue = self._startValue
+
+ self._itemEdited = itemEdit
+
+ self._owner = owner
+ self._finished = False
+ self._aboutToFinish = False
+
+ rectLabel = owner.GetLineLabelRect(itemEdit)
+ rectLabel.x, rectLabel.y = self._owner.CalcScrolledPosition(rectLabel.x, rectLabel.y)
+ xSize, ySize = rectLabel.width + 10, rectLabel.height
+
+ expandoStyle = wx.WANTS_CHARS
+ if wx.Platform in ["__WXGTK__", "__WXMAC__"]:
+ expandoStyle |= wx.SIMPLE_BORDER
+ else:
+ expandoStyle |= wx.SUNKEN_BORDER
+
+ ExpandoTextCtrl.__init__(self, owner, -1, self._startValue, wx.Point(rectLabel.x, rectLabel.y),
+ wx.Size(xSize, ySize), expandoStyle)
+
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+
+ def AcceptChanges(self):
+ """ Accepts/refuses the changes made by the user. """
+
+ value = self.GetValue()
+
+ if value == self._startValue:
+ # nothing changed, always accept
+ # when an item remains unchanged, the owner
+ # needs to be notified that the user decided
+ # not to change the tree item label, and that
+ # the edit has been cancelled
+ self._owner.OnRenameCancelled(self._itemEdited)
+ return True
+
+ if not self._owner.OnRenameAccept(self._itemEdited, value):
+ # vetoed by the user
+ return False
+
+ # accepted, do rename the item
+ self._owner.SetItemText(self._itemEdited, value)
+
+ if value.count("\n") != self._startValue.count("\n"):
+ self._owner.ResetLineDimensions()
+ self._owner.Refresh()
+
+ return True
+
+
+ def Finish(self):
+ """ Finish editing. """
+
+ try:
+ if not self._finished:
+ self._finished = True
+ self._owner.SetFocusIgnoringChildren()
+ self._owner.ResetTextControl()
+ except wx.PyDeadObjectError:
+ return
+
+
+ def OnChar(self, event):
+ """
+ Handles the ``wx.EVT_CHAR`` event for :class:`UltimateListTextCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ keycode = event.GetKeyCode()
+ shiftDown = event.ShiftDown()
+
+ if keycode in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
+ if shiftDown:
+ event.Skip()
+ else:
+ self._aboutToFinish = True
+ self.SetValue(self._currentValue)
+ # Notify the owner about the changes
+ self.AcceptChanges()
+ # Even if vetoed, close the control (consistent with MSW)
+ wx.CallAfter(self.Finish)
+
+ elif keycode == wx.WXK_ESCAPE:
+ self.StopEditing()
+
+ else:
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` event for :class:`UltimateListTextCtrl`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ if not self._finished:
+
+ # auto-grow the textctrl:
+ parentSize = self._owner.GetSize()
+ myPos = self.GetPosition()
+ mySize = self.GetSize()
+
+ dc = wx.ClientDC(self)
+ sx, sy, dummy = dc.GetMultiLineTextExtent(self.GetValue() + "M")
+
+ if myPos.x + sx > parentSize.x:
+ sx = parentSize.x - myPos.x
+ if mySize.x > sx:
+ sx = mySize.x
+
+ self.SetSize((sx, -1))
+ self._currentValue = self.GetValue()
+
+ event.Skip()
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`UltimateListTextCtrl`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if not self._finished and not self._aboutToFinish:
+
+ # We must finish regardless of success, otherwise we'll get
+ # focus problems:
+
+ if not self.AcceptChanges():
+ self._owner.OnRenameCancelled(self._itemEdited)
+
+ # We must let the native text control handle focus, too, otherwise
+ # it could have problems with the cursor (e.g., in wxGTK).
+ event.Skip()
+ wx.CallAfter(self.Finish)
+
+
+ def StopEditing(self):
+ """ Suddenly stops the editing. """
+
+ self._owner.OnRenameCancelled(self._itemEdited)
+ self.Finish()
+
+
+#-----------------------------------------------------------------------------
+# UltimateListMainWindow (internal)
+#-----------------------------------------------------------------------------
+
+class UltimateListMainWindow(wx.PyScrolledWindow):
+ """
+ This is the main widget implementation of :class:`UltimateListCtrl`.
+ """
+
+ def __init__(self, parent, id, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, agwStyle=0, name="listctrlmainwindow"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`PyScrolledWindow` window style;
+ :param `agwStyle`: the AGW-specific window style; can be almost any combination of the following
+ bits:
+
+ =============================== =========== ====================================================================================================
+ Window Styles Hex Value Description
+ =============================== =========== ====================================================================================================
+ ``ULC_VRULES`` 0x1 Draws light vertical rules between rows in report mode.
+ ``ULC_HRULES`` 0x2 Draws light horizontal rules between rows in report mode.
+ ``ULC_ICON`` 0x4 Large icon view, with optional labels.
+ ``ULC_SMALL_ICON`` 0x8 Small icon view, with optional labels.
+ ``ULC_LIST`` 0x10 Multicolumn list view, with optional small icons. Columns are computed automatically, i.e. you don't set columns as in ``ULC_REPORT``. In other words, the list wraps, unlike a :class:`ListBox`.
+ ``ULC_REPORT`` 0x20 Single or multicolumn report view, with optional header.
+ ``ULC_ALIGN_TOP`` 0x40 Icons align to the top. Win32 default, Win32 only.
+ ``ULC_ALIGN_LEFT`` 0x80 Icons align to the left.
+ ``ULC_AUTOARRANGE`` 0x100 Icons arrange themselves. Win32 only.
+ ``ULC_VIRTUAL`` 0x200 The application provides items text on demand. May only be used with ``ULC_REPORT``.
+ ``ULC_EDIT_LABELS`` 0x400 Labels are editable: the application will be notified when editing starts.
+ ``ULC_NO_HEADER`` 0x800 No header in report mode.
+ ``ULC_NO_SORT_HEADER`` 0x1000 No Docs.
+ ``ULC_SINGLE_SEL`` 0x2000 Single selection (default is multiple).
+ ``ULC_SORT_ASCENDING`` 0x4000 Sort in ascending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
+ ``ULC_SORT_DESCENDING`` 0x8000 Sort in descending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
+ ``ULC_TILE`` 0x10000 Each item appears as a full-sized icon with a label of one or more lines beside it (partially implemented).
+ ``ULC_NO_HIGHLIGHT`` 0x20000 No highlight when an item is selected.
+ ``ULC_STICKY_HIGHLIGHT`` 0x40000 Items are selected by simply hovering on them, with no need to click on them.
+ ``ULC_STICKY_NOSELEVENT`` 0x80000 Don't send a selection event when using ``ULC_STICKY_HIGHLIGHT`` style.
+ ``ULC_SEND_LEFTCLICK`` 0x100000 Send a left click event when an item is selected.
+ ``ULC_HAS_VARIABLE_ROW_HEIGHT`` 0x200000 The list has variable row heights.
+ ``ULC_AUTO_CHECK_CHILD`` 0x400000 When a column header has a checkbox associated, auto-check all the subitems in that column.
+ ``ULC_AUTO_TOGGLE_CHILD`` 0x800000 When a column header has a checkbox associated, toggle all the subitems in that column.
+ ``ULC_AUTO_CHECK_PARENT`` 0x1000000 Only meaningful foe checkbox-type items: when an item is checked/unchecked its column header item is checked/unchecked as well.
+ ``ULC_SHOW_TOOLTIPS`` 0x2000000 Show tooltips for ellipsized items/subitems (text too long to be shown in the available space) containing the full item/subitem text.
+ ``ULC_HOT_TRACKING`` 0x4000000 Enable hot tracking of items on mouse motion.
+ ``ULC_BORDER_SELECT`` 0x8000000 Changes border colour whan an item is selected, instead of highlighting the item.
+ ``ULC_TRACK_SELECT`` 0x10000000 Enables hot-track selection in a list control. Hot track selection means that an item is automatically selected when the cursor remains over the item for a certain period of time. The delay is retrieved on Windows using the `win32api` call `win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME)`, and is defaulted to 400ms on other platforms. This style applies to all views of `UltimateListCtrl`.
+ ``ULC_HEADER_IN_ALL_VIEWS`` 0x20000000 Show column headers in all view modes.
+ ``ULC_NO_FULL_ROW_SELECT`` 0x40000000 When an item is selected, the only the item in the first column is highlighted.
+ ``ULC_FOOTER`` 0x80000000 Show a footer too (only when header is present).
+ ``ULC_USER_ROW_HEIGHT`` 0x100000000 Allows to set a custom row height (one value for all the items, only in report mode).
+ =============================== =========== ====================================================================================================
+
+ :param `name`: the window name.
+ """
+
+ wx.PyScrolledWindow.__init__(self, parent, id, pos, size, style|wx.HSCROLL|wx.VSCROLL, name)
+
+ # the list of column objects
+ self._columns = []
+
+ # the array of all line objects for a non virtual list control (for the
+ # virtual list control we only ever use self._lines[0])
+ self._lines = []
+
+ # currently focused item or -1
+ self._current = -1
+
+ # the number of lines per page
+ self._linesPerPage = 0
+
+ # Automatically resized column - this column expands to fill the width of the window
+ self._resizeColumn = -1
+ self._resizeColMinWidth = None
+
+ # this flag is set when something which should result in the window
+ # redrawing happens (i.e. an item was added or deleted, or its appearance
+ # changed) and OnPaint() doesn't redraw the window while it is set which
+ # allows to minimize the number of repaintings when a lot of items are
+ # being added. The real repainting occurs only after the next OnIdle()
+ # call
+ self._dirty = False
+ self._parent = parent
+ self.Init()
+
+ self._highlightBrush = wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT), wx.SOLID)
+
+ btnshadow = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+ self._highlightUnfocusedBrush = wx.Brush(btnshadow, wx.SOLID)
+ r, g, b = btnshadow.Red(), btnshadow.Green(), btnshadow.Blue()
+ backcolour = (max((r >> 1) - 20, 0),
+ max((g >> 1) - 20, 0),
+ max((b >> 1) - 20, 0))
+ backcolour = wx.Colour(backcolour[0], backcolour[1], backcolour[2])
+ self._highlightUnfocusedBrush2 = wx.Brush(backcolour)
+
+ self.SetScrollbars(0, 0, 0, 0, 0, 0)
+
+ attr = wx.ListCtrl.GetClassDefaultAttributes()
+ self.SetOwnForegroundColour(attr.colFg)
+ self.SetOwnBackgroundColour(attr.colBg)
+ self.SetOwnFont(attr.font)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+ self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus)
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_SCROLLWIN, self.OnScroll)
+ self.Bind(wx.EVT_TIMER, self.OnHoverTimer, self._hoverTimer)
+
+
+ def Init(self):
+ """ Initializes the :class:`UltimateListMainWindow` widget. """
+
+ self._dirty = True
+ self._countVirt = 0
+ self._lineFrom = None
+ self._lineTo = - 1
+ self._linesPerPage = 0
+
+ self._headerWidth = 0
+ self._lineHeight = 0
+ self._userLineHeight = None
+
+ self._small_image_list = None
+ self._normal_image_list = None
+
+ self._small_spacing = 30
+ self._normal_spacing = 40
+
+ self._hasFocus = False
+ self._dragCount = 0
+ self._isCreated = False
+
+ self._lastOnSame = False
+ self._renameTimer = UltimateListRenameTimer(self)
+ self._textctrl = None
+
+ self._current = -1
+ self._lineLastClicked = -1
+ self._lineSelectSingleOnUp = -1
+ self._lineBeforeLastClicked = -1
+
+ self._dragStart = wx.Point(-1, -1)
+ self._aColWidths = []
+
+ self._selStore = SelectionStore()
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ # Background image settings
+ self._backgroundImage = None
+ self._imageStretchStyle = _StyleTile
+
+ # Disabled items colour
+ self._disabledColour = wx.Colour(180, 180, 180)
+
+ # Gradient selection colours
+ self._firstcolour = colour= wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self._secondcolour = wx.WHITE
+ self._usegradients = False
+ self._gradientstyle = 1 # Vertical Gradient
+
+ # Vista Selection Styles
+ self._vistaselection = False
+
+ # Selected/highlighted item text color. Leave unset for ForegroundColor to always apply, even for selected item
+ self._highlightedtextcolour = None
+
+ self.SetImageListCheck(16, 16)
+
+ # Disabled items colour
+ self._disabledColour = wx.Colour(180, 180, 180)
+
+ # Hyperlinks things
+ normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._hypertextfont = wx.Font(normalFont.GetPointSize(), normalFont.GetFamily(),
+ normalFont.GetStyle(), wx.NORMAL, True,
+ normalFont.GetFaceName(), normalFont.GetEncoding())
+ self._hypertextnewcolour = wx.BLUE
+ self._hypertextvisitedcolour = wx.Colour(200, 47, 200)
+ self._isonhyperlink = False
+
+ self._itemWithWindow = []
+ self._hasWindows = False
+ self._shortItems = []
+
+ self._isDragging = False
+ self._cursor = wx.STANDARD_CURSOR
+
+ image = GetdragcursorImage()
+
+ # since this image didn't come from a .cur file, tell it where the hotspot is
+ image.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 1)
+ image.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 1)
+
+ # make the image into a cursor
+ self._dragCursor = wx.CursorFromImage(image)
+ self._dragItem = None
+ self._dropTarget = None
+
+ self._oldHotCurrent = None
+ self._newHotCurrent = None
+
+ self._waterMark = None
+
+ self._hoverTimer = wx.Timer(self, wx.ID_ANY)
+ self._hoverItem = -1
+
+
+ def GetMainWindowOfCompositeControl(self):
+ """ Returns the :class:`UltimateListMainWindow` parent. """
+
+ return self.GetParent()
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+ """
+
+ return wx.Size(100, 80)
+
+
+ def HasAGWFlag(self, flag):
+ """
+ Returns ``True`` if the window has the given `flag` bit set.
+
+ :param `flag`: the bit to check.
+
+ :see: :meth:`UltimateListCtrl.SetSingleStyle() <UltimateListCtrl.SetSingleStyle>` for a list of valid flags.
+ """
+
+ return self._parent.HasAGWFlag(flag)
+
+
+ def IsColumnShown(self, column):
+ """
+ Returns ``True`` if the input column is shown, ``False`` if it is hidden.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ return self.GetColumn(column).IsShown()
+
+
+ # return True if this is a virtual list control
+ def IsVirtual(self):
+ """ Returns ``True`` if the window has the ``ULC_VIRTUAL`` style set. """
+
+ return self.HasAGWFlag(ULC_VIRTUAL)
+
+
+ # return True if the control is in report mode
+ def InReportView(self):
+ """ Returns ``True`` if the window is in report mode. """
+
+ return self.HasAGWFlag(ULC_REPORT)
+
+
+ def InTileView(self):
+ """
+ Returns ``True`` if the window is in tile mode (partially implemented).
+
+ .. todo:: Fully implement tile view for :class:`UltimateListCtrl`.
+ """
+
+ return self.HasAGWFlag(ULC_TILE)
+
+ # return True if we are in single selection mode, False if multi sel
+ def IsSingleSel(self):
+ """ Returns ``True`` if we are in single selection mode, ``False`` if multi selection. """
+
+ return self.HasAGWFlag(ULC_SINGLE_SEL)
+
+
+ def HasFocus(self):
+ """ Returns ``True`` if the window has focus. """
+
+ return self._hasFocus
+
+
+ # do we have a header window?
+ def HasHeader(self):
+ """ Returns ``True`` if the header window is shown. """
+
+ if (self.InReportView() or self.InTileView()) and not self.HasAGWFlag(ULC_NO_HEADER):
+ return True
+ if self.HasAGWFlag(ULC_HEADER_IN_ALL_VIEWS):
+ return True
+
+ return False
+
+
+ # do we have a footer window?
+ def HasFooter(self):
+ """ Returns ``True`` if the footer window is shown. """
+
+ if self.HasHeader() and self.HasAGWFlag(ULC_FOOTER):
+ return True
+
+ return False
+
+
+ # toggle the line state and refresh it
+ def ReverseHighlight(self, line):
+ """
+ Toggles the line state and refreshes it.
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+ """
+
+ self.HighlightLine(line, not self.IsHighlighted(line))
+ self.RefreshLine(line)
+
+
+ def SetUserLineHeight(self, height):
+ """
+ Sets a custom value for the :class:`UltimateListMainWindow` item height.
+
+ :param `height`: the custom height for all the items, in pixels.
+
+ :note: This method can be used only with ``ULC_REPORT`` and ``ULC_USER_ROW_HEIGHT`` styles set.
+ """
+
+ if self.HasAGWFlag(ULC_REPORT) and self.HasAGWFlag(ULC_USER_ROW_HEIGHT):
+ self._userLineHeight = height
+ return
+
+ raise Exception("SetUserLineHeight can only be used with styles ULC_REPORT and ULC_USER_ROW_HEIGHT set.")
+
+
+ def GetUserLineHeight(self):
+ """
+ Returns the custom value for the :class:`UltimateListMainWindow` item height, if previously set with
+ :meth:`~UltimateListMainWindow.SetUserLineHeight`.
+
+ :note: This method can be used only with ``ULC_REPORT`` and ``ULC_USER_ROW_HEIGHT`` styles set.
+ """
+
+ if self.HasAGWFlag(ULC_REPORT) and self.HasAGWFlag(ULC_USER_ROW_HEIGHT):
+ return self._userLineHeight
+
+ raise Exception("GetUserLineHeight can only be used with styles ULC_REPORT and ULC_USER_ROW_HEIGHT set.")
+
+
+ # get the size of the total line rect
+ def GetLineSize(self, line):
+ """
+ Returns the size of the total line client rectangle.
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+ """
+
+ return self.GetLineRect(line).GetSize()
+
+
+ # bring the current item into view
+ def MoveToFocus(self):
+ """ Brings tyhe current item into view. """
+
+ self.MoveToItem(self._current)
+
+
+ def GetColumnCount(self):
+ """ Returns the total number of columns in the :class:`UltimateListCtrl`. """
+
+ return len(self._columns)
+
+
+ def GetItemText(self, item):
+ """
+ Returns the item text.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ info = UltimateListItem()
+ info._mask = ULC_MASK_TEXT
+ info._itemId = item
+ info = self.GetItem(info)
+
+ return info._text
+
+
+ def SetItemText(self, item, value):
+ """
+ Sets the item text.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `value`: the new item text.
+ """
+
+ info = UltimateListItem()
+ info._mask = ULC_MASK_TEXT
+ info._itemId = item
+ info._text = value
+
+ self.SetItem(info)
+
+
+ def IsEmpty(self):
+ """ Returns ``True`` if the window has no items in it. """
+
+ return self.GetItemCount() == 0
+
+
+ def ResetCurrent(self):
+ """ Resets the current item to ``None``. """
+
+ self.ChangeCurrent(-1)
+
+
+ def HasCurrent(self):
+ """
+ Returns ``True`` if the current item has been set, either programmatically
+ or by user intervention.
+ """
+
+ return self._current != -1
+
+
+ # override base class virtual to reset self._lineHeight when the font changes
+ def SetFont(self, font):
+ """
+ Overridden base class virtual to reset the line height when the font changes.
+
+ :param `font`: a valid :class:`Font` object.
+
+ :note: Overridden from :class:`PyScrolledWindow`.
+ """
+
+ if not wx.PyScrolledWindow.SetFont(self, font):
+ return False
+
+ self._lineHeight = 0
+ self.ResetLineDimensions()
+
+ return True
+
+
+ def ResetLineDimensions(self, force=False):
+ """
+ Resets the line dimensions, so that client rectangles and positions are
+ recalculated.
+
+ :param `force`: ``True`` to reset all line dimensions.
+ """
+
+ if (self.HasAGWFlag(ULC_REPORT) and self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT) and not self.IsVirtual()) or force:
+ for l in xrange(self.GetItemCount()):
+ line = self.GetLine(l)
+ line.ResetDimensions()
+
+ # these are for UltimateListLineData usage only
+ # get the backpointer to the list ctrl
+ def GetListCtrl(self):
+ """ Returns the parent widget, an instance of :class:`UltimateListCtrl`. """
+
+ return self.GetParent()
+
+
+ # get the brush to use for the item highlighting
+ def GetHighlightBrush(self):
+ """ Returns the brush to use for the item highlighting. """
+
+ return (self._hasFocus and [self._highlightBrush] or [self._highlightUnfocusedBrush])[0]
+
+
+ # get the line data for the given index
+ def GetLine(self, n):
+ """
+ Returns the line data for the given index.
+
+ :param `n`: the line index.
+ """
+
+ if self.IsVirtual():
+
+ self.CacheLineData(n)
+ n = 0
+
+ return self._lines[n]
+
+
+ # force us to recalculate the range of visible lines
+ def ResetVisibleLinesRange(self, reset=False):
+ """
+ Forces us to recalculate the range of visible lines.
+
+ :param `reset`: ``True`` to reset all line dimensions, which will then be
+ recalculated.
+ """
+
+ self._lineFrom = -1
+ if self.IsShownOnScreen() and reset:
+ self.ResetLineDimensions()
+
+
+ # Called on EVT_SIZE to resize the _resizeColumn to fill the width of the window
+ def ResizeColumns(self):
+ """
+ If ``ULC_AUTOSIZE_FILL`` was passed to :meth:`UltimateListCtrl.SetColumnWidth() <UltimateListCtrl.SetColumnWidth>` then
+ that column's width will be expanded to fill the window on a resize event.
+
+ Called by :meth:`UltimateListCtrl.OnSize() <UltimateListCtrl.OnSize>` when the window is resized.
+ """
+
+ if not self: # Avoid PyDeadObjectErrors on Mac
+ return
+
+ if self._resizeColumn == -1:
+ return
+
+
+ numCols = self.GetColumnCount()
+ if numCols == 0: return # Nothing to resize.
+
+ resizeCol = self._resizeColumn
+
+ if self._resizeColMinWidth == None:
+ self._resizeColMinWidth = self.GetColumnWidth(resizeCol)
+
+ # We're showing the vertical scrollbar -> allow for scrollbar width
+ # NOTE: on GTK, the scrollbar is included in the client size, but on
+ # Windows it is not included
+ listWidth = self.GetClientSize().width
+ if wx.Platform != '__WXMSW__':
+ if self.GetItemCount() > self.GetCountPerPage():
+ scrollWidth = wx.SystemSettings_GetMetric(wx.SYS_VSCROLL_X)
+ listWidth = listWidth - scrollWidth
+
+ totColWidth = 0 # Width of all columns except last one.
+ for col in range(numCols):
+ if col != (resizeCol) and self.IsColumnShown(col):
+ totColWidth = totColWidth + self.GetColumnWidth(col)
+
+ resizeColWidth = self.GetColumnWidth(resizeCol)
+
+ if totColWidth + self._resizeColMinWidth > listWidth:
+ # We haven't got the width to show the last column at its minimum
+ # width -> set it to its minimum width and allow the horizontal
+ # scrollbar to show.
+ self.SetColumnWidth(resizeCol, self._resizeColMinWidth)
+ return
+
+ # Resize the last column to take up the remaining available space.
+ self.SetColumnWidth(resizeCol, listWidth - totColWidth)
+
+
+ # get the colour to be used for drawing the rules
+ def GetRuleColour(self):
+ """ Returns the colour to be used for drawing the horizontal and vertical rules. """
+
+ return wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT)
+
+
+ def SetReportView(self, inReportView):
+ """
+ Sets whether :class:`UltimateListCtrl` is in report view or not.
+
+ :param `inReportView`: ``True`` to set :class:`UltimateListCtrl` in report view, ``False``
+ otherwise.
+ """
+
+ for line in self._lines:
+ line.SetReportView(inReportView)
+
+
+ def CacheLineData(self, line):
+ """
+ Saves the current line attributes.
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+
+ :note: This method is used only if the :class:`UltimateListCtrl` has the ``ULC_VIRTUAL``
+ style set.
+ """
+
+ listctrl = self.GetListCtrl()
+ ld = self.GetDummyLine()
+
+ countCol = self.GetColumnCount()
+ for col in xrange(countCol):
+ ld.SetText(col, listctrl.OnGetItemText(line, col))
+ ld.SetToolTip(col, listctrl.OnGetItemToolTip(line, col))
+ ld.SetColour(col, listctrl.OnGetItemTextColour(line, col))
+ ld.SetImage(col, listctrl.OnGetItemColumnImage(line, col))
+ kind = listctrl.OnGetItemColumnKind(line, col)
+ ld.SetKind(col, kind)
+ if kind > 0:
+ ld.Check(col, listctrl.OnGetItemColumnCheck(line, col))
+
+ ld.SetAttr(listctrl.OnGetItemAttr(line))
+
+
+ def GetDummyLine(self):
+ """
+ Returns a dummy line.
+
+ :note: This method is used only if the :class:`UltimateListCtrl` has the ``ULC_VIRTUAL``
+ style set.
+ """
+
+ if self.IsEmpty():
+ raise Exception("invalid line index")
+
+ if not self.IsVirtual():
+ raise Exception("GetDummyLine() shouldn't be called")
+
+ # we need to recreate the dummy line if the number of columns in the
+ # control changed as it would have the incorrect number of fields
+ # otherwise
+ if len(self._lines) > 0 and len(self._lines[0]._items) != self.GetColumnCount():
+ self._lines = []
+
+ if not self._lines:
+ line = UltimateListLineData(self)
+ self._lines.append(line)
+
+ return self._lines[0]
+
+
+# ----------------------------------------------------------------------------
+# line geometry (report mode only)
+# ----------------------------------------------------------------------------
+
+ def GetLineHeight(self, item=None):
+ """
+ Returns the line height for a specific item.
+
+ :param `item`: if not ``None``, an instance of :class:`UltimateListItem`.
+ """
+
+ # we cache the line height as calling GetTextExtent() is slow
+
+ if self.HasAGWFlag(ULC_REPORT) and self.HasAGWFlag(ULC_USER_ROW_HEIGHT):
+ if self._userLineHeight is not None:
+ return self._userLineHeight
+
+ if item is None or not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+
+ if not self._lineHeight:
+ dc = wx.ClientDC(self)
+ dc.SetFont(self.GetFont())
+
+ dummy, y = dc.GetTextExtent("H")
+ if self._small_image_list and self._small_image_list.GetImageCount():
+ iw, ih = self._small_image_list.GetSize(0)
+ y = max(y, ih)
+
+ y += EXTRA_HEIGHT
+ self._lineHeight = y + LINE_SPACING
+
+ return self._lineHeight
+
+ else:
+
+ line = self.GetLine(item)
+ LH = line.GetHeight()
+ if LH != -1:
+ return LH
+
+ dc = wx.ClientDC(self)
+
+ allTextY = 0
+
+ for col, items in enumerate(line._items):
+
+ if items.GetCustomRenderer():
+ allTextY = max(allTextY, items.GetCustomRenderer().GetLineHeight())
+ continue
+
+ if items.HasFont():
+ dc.SetFont(items.GetFont())
+ else:
+ dc.SetFont(self.GetFont())
+
+ text_x, text_y, dummy = dc.GetMultiLineTextExtent(items.GetText())
+ allTextY = max(text_y, allTextY)
+
+ if items.GetWindow():
+ xSize, ySize = items.GetWindowSize()
+ allTextY = max(allTextY, ySize)
+
+ if self._small_image_list and self._small_image_list.GetImageCount():
+ for img in items._image:
+ iw, ih = self._small_image_list.GetSize(img)
+ allTextY = max(allTextY, ih)
+
+ allTextY += EXTRA_HEIGHT
+ line.SetHeight(allTextY)
+
+ return allTextY
+
+
+ def GetLineY(self, line):
+ """
+ Returns the line `y` position.
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+ """
+
+ if self.IsVirtual():
+ return LINE_SPACING + line*self.GetLineHeight()
+
+ lineItem = self.GetLine(line)
+ lineY = lineItem.GetY()
+ if lineY != -1:
+ return lineY
+
+ lineY = 0
+ for l in xrange(line):
+ lineY += self.GetLineHeight(l)
+
+ lineItem.SetY(LINE_SPACING + lineY)
+ return LINE_SPACING + lineY
+
+
+ def GetLineRect(self, line):
+ """
+ Returns the line client rectangle.
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+ """
+
+ if not self.InReportView():
+ return self.GetLine(line)._gi._rectAll
+
+ rect = wx.Rect(HEADER_OFFSET_X, self.GetLineY(line), self.GetHeaderWidth(), self.GetLineHeight(line))
+ return rect
+
+
+ def GetLineLabelRect(self, line, col=0):
+ """
+ Returns the line client rectangle for the item text only.
+ Note this is the full column width unless an image or
+ checkbox exists. It is not the width of the text itself
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+ """
+
+ if not self.InReportView():
+ return self.GetLine(line)._gi._rectLabel
+
+ image_x = 0
+ image_width = 0
+
+ for c in range(col):
+ image_x += self.GetColumnWidth(c)
+
+ item = self.GetLine(line)
+ if item.HasImage(col):
+ ix, iy = self.GetImageSize(item.GetImage(col))
+ image_x += ix
+ image_width = ix
+
+ if item.GetKind(col) in [1, 2]:
+ image_x += self.GetCheckboxImageSize()[0]
+ image_width += self.GetCheckboxImageSize()[0]
+
+ rect = wx.Rect(image_x + HEADER_OFFSET_X, self.GetLineY(line), self.GetColumnWidth(col) - image_width, self.GetLineHeight(line))
+ return rect
+
+
+ def GetLineIconRect(self, line):
+ """
+ Returns the line client rectangle for the item image only.
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+ """
+
+ if not self.InReportView():
+ return self.GetLine(line)._gi._rectIcon
+
+ ld = self.GetLine(line)
+
+ image_x = HEADER_OFFSET_X
+ if ld.GetKind() in [1, 2]:
+ image_x += self.GetCheckboxImageSize()[0]
+
+ rect = wx.Rect(image_x, self.GetLineY(line), *self.GetImageSize(ld.GetImage()))
+ return rect
+
+
+ def GetLineCheckboxRect(self, line):
+ """
+ Returns the line client rectangle for the item checkbox image only.
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+ """
+
+ if not self.InReportView():
+ return self.GetLine(line)._gi._rectCheck
+
+ ld = self.GetLine(line)
+ LH = self.GetLineHeight(line)
+ wcheck, hcheck = self.GetCheckboxImageSize()
+ rect = wx.Rect(HEADER_OFFSET_X, self.GetLineY(line) + LH/2 - hcheck/2, wcheck, hcheck)
+ return rect
+
+
+ def GetLineHighlightRect(self, line):
+ """
+ Returns the line client rectangle when the line is highlighted.
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+ """
+
+ return (self.InReportView() and [self.GetLineRect(line)] or [self.GetLine(line)._gi._rectHighlight])[0]
+
+
+ def HitTestLine(self, line, x, y):
+ """
+ HitTest method for a :class:`UltimateListCtrl` line.
+
+ :param `line`: an instance of :class:`UltimateListLineData`;
+ :param `x`: the mouse `x` position;
+ :param `y`: the mouse `y` position.
+
+ :return: a tuple of values, representing the item hit and a hit flag. The
+ hit flag can be one of the following bits:
+
+ =============================== ========= ================================
+ HitTest Flag Hex Value Description
+ =============================== ========= ================================
+ ``ULC_HITTEST_ABOVE`` 0x1 Above the client area
+ ``ULC_HITTEST_BELOW`` 0x2 Below the client area
+ ``ULC_HITTEST_NOWHERE`` 0x4 In the client area but below the last item
+ ``ULC_HITTEST_ONITEM`` 0x2a0 Anywhere on the item (text, icon, checkbox image)
+ ``ULC_HITTEST_ONITEMICON`` 0x20 On the bitmap associated with an item
+ ``ULC_HITTEST_ONITEMLABEL`` 0x80 On the label (string) associated with an item
+ ``ULC_HITTEST_ONITEMRIGHT`` 0x100 In the area to the right of an item
+ ``ULC_HITTEST_ONITEMSTATEICON`` 0x200 On the state icon for a list view item that is in a user-defined state
+ ``ULC_HITTEST_TOLEFT`` 0x400 To the left of the client area
+ ``ULC_HITTEST_TORIGHT`` 0x800 To the right of the client area
+ ``ULC_HITTEST_ONITEMCHECK`` 0x1000 On the item checkbox (if any)
+ =============================== ========= ================================
+
+ """
+
+ ld = self.GetLine(line)
+
+ if self.InReportView():# and not self.IsVirtual():
+
+ lineY = self.GetLineY(line)
+ xstart = HEADER_OFFSET_X
+
+ for col, item in enumerate(ld._items):
+
+ if not self.IsColumnShown(col):
+ continue
+
+ width = self.GetColumnWidth(col)
+ xOld = xstart
+ xstart += width
+ ix = 0
+
+ #if (line, col) in self._shortItems:
+ #rect = wx.Rect(xOld, lineY, width, self.GetLineHeight(line))
+ rect = self.GetLineLabelRect(line,col)
+ if rect.Contains((x, y)):
+ newItem = self.GetParent().GetItem(line, col)
+ return newItem, ULC_HITTEST_ONITEMLABEL
+
+ if item.GetKind() in [1, 2]:
+ # We got a checkbox-type item
+ ix, iy = self.GetCheckboxImageSize()
+ LH = self.GetLineHeight(line)
+ rect = wx.Rect(xOld, lineY + LH/2 - iy/2, ix, iy)
+ if rect.Contains((x, y)):
+ newItem = self.GetParent().GetItem(line, col)
+ return newItem, ULC_HITTEST_ONITEMCHECK
+
+ if item.IsHyperText():
+ start, end = self.GetItemTextSize(item)
+ rect = wx.Rect(xOld+start, lineY, end, self.GetLineHeight(line))
+ if rect.Contains((x, y)):
+ newItem = self.GetParent().GetItem(line, col)
+ return newItem, ULC_HITTEST_ONITEMLABEL
+
+ xOld += ix
+
+ if ld.HasImage() and self.GetLineIconRect(line).Contains((x, y)):
+ return self.GetParent().GetItem(line), ULC_HITTEST_ONITEMICON
+
+ # VS: Testing for "ld.HasText() || InReportView()" instead of
+ # "ld.HasText()" is needed to make empty lines in report view
+ # possible
+ if ld.HasText() or self.InReportView():
+ if self.InReportView():
+ rect = self.GetLineRect(line)
+ else:
+ checkRect = self.GetLineCheckboxRect(line)
+ if checkRect.Contains((x, y)):
+ return self.GetParent().GetItem(line), ULC_HITTEST_ONITEMCHECK
+
+ rect = self.GetLineLabelRect(line)
+
+ if rect.Contains((x, y)):
+ return self.GetParent().GetItem(line), ULC_HITTEST_ONITEMLABEL
+
+ rect = self.GetLineRect(line)
+ if rect.Contains((x, y)):
+ return self.GetParent().GetItem(line), ULC_HITTEST_ONITEM
+
+ return None, 0
+
+
+# ----------------------------------------------------------------------------
+# highlight (selection) handling
+# ----------------------------------------------------------------------------
+
+ def IsHighlighted(self, line):
+ """
+ Returns ``True`` if the input line is highlighted.
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+ """
+
+ if self.IsVirtual():
+
+ return self._selStore.IsSelected(line)
+
+ else: # !virtual
+
+ ld = self.GetLine(line)
+ return ld.IsHighlighted()
+
+
+ def HighlightLines(self, lineFrom, lineTo, highlight=True):
+ """
+ Highlights a range of lines in :class:`UltimateListCtrl`.
+
+ :param `lineFrom`: an integer representing the first line to highlight;
+ :param `lineTo`: an integer representing the last line to highlight;
+ :param `highlight`: ``True`` to highlight the lines, ``False`` otherwise.
+ """
+
+ if self.IsVirtual():
+ linesChanged = self._selStore.SelectRange(lineFrom, lineTo, highlight)
+ if not linesChanged:
+ # many items changed state, refresh everything
+ self.RefreshLines(lineFrom, lineTo)
+
+ else: # only a few items changed state, refresh only them
+
+ for n in xrange(len(linesChanged)):
+ self.RefreshLine(linesChanged[n])
+
+ else: # iterate over all items in non report view
+
+ for line in xrange(lineFrom, lineTo+1):
+ if self.HighlightLine(line, highlight):
+ self.RefreshLine(line)
+
+
+ def HighlightLine(self, line, highlight=True):
+ """
+ Highlights a line in :class:`UltimateListCtrl`.
+
+ :param `line`: an instance of :class:`UltimateListLineData`;
+ :param `highlight`: ``True`` to highlight the line, ``False`` otherwise.
+ """
+
+ changed = False
+
+ if self.IsVirtual():
+
+ changed = self._selStore.SelectItem(line, highlight)
+
+ else: # !virtual
+
+ ld = self.GetLine(line)
+ changed = ld.Highlight(highlight)
+
+ dontNotify = self.HasAGWFlag(ULC_STICKY_HIGHLIGHT) and self.HasAGWFlag(ULC_STICKY_NOSELEVENT)
+
+ if changed and not dontNotify:
+ self.SendNotify(line, (highlight and [wxEVT_COMMAND_LIST_ITEM_SELECTED] or [wxEVT_COMMAND_LIST_ITEM_DESELECTED])[0])
+
+ return changed
+
+
+ def RefreshLine(self, line):
+ """
+ Redraws the input line.
+
+ :param `line`: an instance of :class:`UltimateListLineData`.
+ """
+
+ if self.InReportView():
+
+ visibleFrom, visibleTo = self.GetVisibleLinesRange()
+ if line < visibleFrom or line > visibleTo:
+ return
+
+ rect = self.GetLineRect(line)
+ rect.x, rect.y = self.CalcScrolledPosition(rect.x, rect.y)
+ self.RefreshRect(rect)
+
+
+ def RefreshLines(self, lineFrom, lineTo):
+ """
+ Redraws a range of lines in :class:`UltimateListCtrl`.
+
+ :param `lineFrom`: an integer representing the first line to refresh;
+ :param `lineTo`: an integer representing the last line to refresh.
+ """
+
+ if self.InReportView():
+
+ visibleFrom, visibleTo = self.GetVisibleLinesRange()
+
+ if lineFrom < visibleFrom:
+ lineFrom = visibleFrom
+ if lineTo > visibleTo:
+ lineTo = visibleTo
+
+ rect = wx.Rect()
+ rect.x = 0
+ rect.y = self.GetLineY(lineFrom)
+ rect.width = self.GetClientSize().x
+ rect.height = self.GetLineY(lineTo) - rect.y + self.GetLineHeight(lineTo)
+
+ rect.x, rect.y = self.CalcScrolledPosition(rect.x, rect.y)
+ self.RefreshRect(rect)
+
+ else: # !report
+
+ # TODO: this should be optimized...
+ for line in xrange(lineFrom, lineTo+1):
+ self.RefreshLine(line)
+
+
+ def RefreshAfter(self, lineFrom):
+ """
+ Redraws all the lines after the input one.
+
+ :param `lineFrom`: an integer representing the first line to refresh.
+ """
+
+ if self.InReportView():
+
+ visibleFrom, visibleTo = self.GetVisibleLinesRange()
+
+ if lineFrom < visibleFrom:
+ lineFrom = visibleFrom
+ elif lineFrom > visibleTo:
+ return
+
+ rect = wx.Rect()
+ rect.x = 0
+ rect.y = self.GetLineY(lineFrom)
+ rect.x, rect.y = self.CalcScrolledPosition(rect.x, rect.y)
+
+ size = self.GetClientSize()
+ rect.width = size.x
+ # refresh till the bottom of the window
+ rect.height = size.y - rect.y
+
+ self.RefreshRect(rect)
+
+ else: # !report
+
+ # TODO: how to do it more efficiently?
+ self._dirty = True
+
+
+ def RefreshSelected(self):
+ """ Redraws the selected lines. """
+
+ if self.IsEmpty():
+ return
+
+ if self.InReportView():
+
+ fromm, to = self.GetVisibleLinesRange()
+
+ else: # !virtual
+
+ fromm = 0
+ to = self.GetItemCount() - 1
+
+ if self.HasCurrent() and self._current >= fromm and self._current <= to:
+ self.RefreshLine(self._current)
+
+ for line in xrange(fromm, to+1):
+ # NB: the test works as expected even if self._current == -1
+ if line != self._current and self.IsHighlighted(line):
+ self.RefreshLine(line)
+
+
+ def HideWindows(self):
+ """ Hides the windows associated to the items. Used internally. """
+
+ for child in self._itemWithWindow:
+ wnd = child.GetWindow()
+ if wnd:
+ wnd.Hide()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ # Note: a wxPaintDC must be constructed even if no drawing is
+ # done (a Windows requirement).
+ dc = wx.BufferedPaintDC(self)
+
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+
+ self.PrepareDC(dc)
+
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.Clear()
+
+ self.TileBackground(dc)
+ self.PaintWaterMark(dc)
+
+ if self.IsEmpty():
+ # nothing to draw or not the moment to draw it
+ return
+
+ if self._dirty:
+ # delay the repainting until we calculate all the items positions
+ self.RecalculatePositions(False)
+
+ useVista, useGradient = self._vistaselection, self._usegradients
+ dev_x, dev_y = self.CalcScrolledPosition(0, 0)
+
+ dc.SetFont(self.GetFont())
+
+ if self.InReportView():
+ visibleFrom, visibleTo = self.GetVisibleLinesRange()
+
+ # mrcs: draw additional items
+ if visibleFrom > 0:
+ visibleFrom -= 1
+
+ if visibleTo < self.GetItemCount() - 1:
+ visibleTo += 1
+
+ xOrig = dc.LogicalToDeviceX(0)
+ yOrig = dc.LogicalToDeviceY(0)
+
+ # tell the caller cache to cache the data
+ if self.IsVirtual():
+
+ evCache = UltimateListEvent(wxEVT_COMMAND_LIST_CACHE_HINT, self.GetParent().GetId())
+ evCache.SetEventObject(self.GetParent())
+ evCache.m_oldItemIndex = visibleFrom
+ evCache.m_itemIndex = visibleTo
+ self.GetParent().GetEventHandler().ProcessEvent(evCache)
+
+ no_highlight = self.HasAGWFlag(ULC_NO_HIGHLIGHT)
+
+ for line in xrange(visibleFrom, visibleTo+1):
+ rectLine = self.GetLineRect(line)
+
+ if not self.IsExposed(rectLine.x + xOrig, rectLine.y + yOrig, rectLine.width, rectLine.height):
+ # don't redraw unaffected lines to avoid flicker
+ continue
+
+ theLine = self.GetLine(line)
+ enabled = theLine.GetItem(0, CreateListItem(line, 0)).IsEnabled()
+ oldPN, oldBR = dc.GetPen(), dc.GetBrush()
+ theLine.DrawInReportMode(dc, line, rectLine,
+ self.GetLineHighlightRect(line),
+ self.IsHighlighted(line) and not no_highlight,
+ line==self._current, enabled, oldPN, oldBR)
+
+ if self.HasAGWFlag(ULC_HRULES):
+ pen = wx.Pen(self.GetRuleColour(), 1, wx.SOLID)
+ clientSize = self.GetClientSize()
+
+ # Don't draw the first one
+ start = (visibleFrom > 0 and [visibleFrom] or [1])[0]
+
+ dc.SetPen(pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ for i in xrange(start, visibleTo+1):
+ lineY = self.GetLineY(i)
+ dc.DrawLine(0 - dev_x, lineY, clientSize.x - dev_x, lineY)
+
+ # Draw last horizontal rule
+ if visibleTo == self.GetItemCount() - 1:
+ lineY = self.GetLineY(visibleTo) + self.GetLineHeight(visibleTo)
+ dc.SetPen(pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawLine(0 - dev_x, lineY, clientSize.x - dev_x , lineY)
+
+ # Draw vertical rules if required
+ if self.HasAGWFlag(ULC_VRULES) and not self.IsEmpty():
+ pen = wx.Pen(self.GetRuleColour(), 1, wx.SOLID)
+
+ firstItemRect = self.GetItemRect(visibleFrom)
+ lastItemRect = self.GetItemRect(visibleTo)
+ x = firstItemRect.GetX()
+ dc.SetPen(pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ for col in xrange(self.GetColumnCount()):
+
+ if not self.IsColumnShown(col):
+ continue
+
+ colWidth = self.GetColumnWidth(col)
+ x += colWidth
+
+ x_pos = x - dev_x
+ if col < self.GetColumnCount()-1:
+ x_pos -= 2
+
+ dc.DrawLine(x_pos, firstItemRect.GetY() - 1 - dev_y, x_pos, lastItemRect.GetBottom() + 1 - dev_y)
+
+
+ else: # !report
+
+ for i in xrange(self.GetItemCount()):
+ self.GetLine(i).Draw(i, dc)
+
+ if wx.Platform not in ["__WXMAC__", "__WXGTK__"]:
+ # Don't draw rect outline under Mac at all.
+ # Draw it elsewhere on GTK
+ if self.HasCurrent():
+ if self._hasFocus and not self.HasAGWFlag(ULC_NO_HIGHLIGHT) and not useVista and not useGradient \
+ and not self.HasAGWFlag(ULC_BORDER_SELECT) and not self.HasAGWFlag(ULC_NO_FULL_ROW_SELECT):
+ dc.SetPen(wx.BLACK_PEN)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangleRect(self.GetLineHighlightRect(self._current))
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to reduce flicker.
+ """
+
+ pass
+
+
+ def TileBackground(self, dc):
+ """
+ Tiles the background image to fill all the available area.
+
+ :param `dc`: an instance of :class:`DC`.
+
+ .. todo:: Support background images also in stretch and centered modes.
+ """
+
+ if not self._backgroundImage:
+ return
+
+ if self._imageStretchStyle != _StyleTile:
+ # Can we actually do something here (or in OnPaint()) To Handle
+ # background images that are stretchable or always centered?
+ # I tried but I get enormous flickering...
+ return
+
+ sz = self.GetClientSize()
+ w = self._backgroundImage.GetWidth()
+ h = self._backgroundImage.GetHeight()
+
+ x = 0
+
+ while x < sz.width:
+ y = 0
+
+ while y < sz.height:
+ dc.DrawBitmap(self._backgroundImage, x, y, True)
+ y = y + h
+
+ x = x + w
+
+
+ def PaintWaterMark(self, dc):
+ """
+ Draws a watermark at the bottom right of :class:`UltimateListCtrl`.
+
+ :param `dc`: an instance of :class:`DC`.
+
+ .. todo:: Better support for this is needed.
+ """
+
+ if not self._waterMark:
+ return
+
+ width, height = self.CalcUnscrolledPosition(*self.GetClientSize())
+
+ bitmapW = self._waterMark.GetWidth()
+ bitmapH = self._waterMark.GetHeight()
+
+ x = width - bitmapW - 5
+ y = height - bitmapH - 5
+
+ dc.DrawBitmap(self._waterMark, x, y, True)
+
+
+ def HighlightAll(self, on=True):
+ """
+ Highlights/unhighlights all the lines in :class:`UltimateListCtrl`.
+
+ :param `on`: ``True`` to highlight all the lines, ``False`` to unhighlight them.
+ """
+
+ if self.IsSingleSel():
+
+ if on:
+ raise Exception("can't do this in a single sel control")
+
+ # we just have one item to turn off
+ if self.HasCurrent() and self.IsHighlighted(self._current):
+ self.HighlightLine(self._current, False)
+ self.RefreshLine(self._current)
+
+ else: # multi sel
+ if not self.IsEmpty():
+ self.HighlightLines(0, self.GetItemCount() - 1, on)
+
+
+ def OnChildFocus(self, event):
+ """
+ Handles the ``wx.EVT_CHILD_FOCUS`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`ChildFocusEvent` event to be processed.
+
+ .. note::
+
+ This method is intentionally empty to prevent the default handler in
+ :class:`PyScrolledWindow` from needlessly scrolling the window when the edit
+ control is dismissed.
+
+ """
+
+ # Do nothing here. This prevents the default handler in wx.PyScrolledWindow
+ # from needlessly scrolling the window when the edit control is
+ # dismissed. See ticket #9563.
+
+ pass
+
+
+ def SendNotify(self, line, command, point=wx.DefaultPosition):
+ """
+ Actually sends a :class:`UltimateListEvent`.
+
+ :param `line`: an instance of :class:`UltimateListLineData`;
+ :param `command`: the event type to send;
+ :param `point`: an instance of :class:`Point`.
+ """
+
+ bRet = True
+ le = UltimateListEvent(command, self.GetParent().GetId())
+ le.SetEventObject(self.GetParent())
+ le.m_itemIndex = line
+
+ # set only for events which have position
+ if point != wx.DefaultPosition:
+ le.m_pointDrag = point
+
+ # don't try to get the line info for virtual list controls: the main
+ # program has it anyhow and if we did it would result in accessing all
+ # the lines, even those which are not visible now and this is precisely
+ # what we're trying to avoid
+ if not self.IsVirtual():
+
+ if line != -1:
+ self.GetLine(line).GetItem(0, le.m_item)
+
+ #else: this happens for wxEVT_COMMAND_LIST_ITEM_FOCUSED event
+
+ #else: there may be no more such item
+
+ self.GetParent().GetEventHandler().ProcessEvent(le)
+ bRet = le.IsAllowed()
+
+ return bRet
+
+
+ def ChangeCurrent(self, current):
+ """
+ Changes the current line to the specified one.
+
+ :param `current`: an integer specifying the index of the current line.
+ """
+
+ self._current = current
+
+ # as the current item changed, we shouldn't start editing it when the
+ # "slow click" timer expires as the click happened on another item
+ if self._renameTimer.IsRunning():
+ self._renameTimer.Stop()
+
+ self.SendNotify(current, wxEVT_COMMAND_LIST_ITEM_FOCUSED)
+
+
+ def EditLabel(self, item):
+ """
+ Starts editing an item label.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ if item < 0 or item >= self.GetItemCount():
+ raise Exception("wrong index in UltimateListCtrl.EditLabel()")
+
+ le = UltimateListEvent(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, self.GetParent().GetId())
+ le.SetEventObject(self.GetParent())
+ le.m_itemIndex = item
+ data = self.GetLine(item)
+ le.m_item = data.GetItem(0, le.m_item)
+
+ self._textctrl = UltimateListTextCtrl(self, item)
+
+ if self.GetParent().GetEventHandler().ProcessEvent(le) and not le.IsAllowed():
+ # vetoed by user code
+ return
+
+ # We have to call this here because the label in question might just have
+ # been added and no screen update taken place.
+ if self._dirty:
+ wx.SafeYield()
+ # Pending events dispatched by wx.SafeYield might have changed the item
+ # count
+ if item >= self.GetItemCount():
+ return None
+
+ # modified
+ self._textctrl.SetFocus()
+
+ return self._textctrl
+
+
+ def OnRenameTimer(self):
+ """ The timer for renaming has expired. Start editing. """
+
+ if not self.HasCurrent():
+ raise Exception("unexpected rename timer")
+
+ self.EditLabel(self._current)
+
+
+ def OnRenameAccept(self, itemEdit, value):
+ """
+ Called by :class:`UltimateListTextCtrl`, to accept the changes and to send the
+ ``EVT_LIST_END_LABEL_EDIT`` event.
+
+ :param `itemEdit`: an instance of :class:`UltimateListItem`;
+ :param `value`: the new value of the item label.
+ """
+
+ le = UltimateListEvent(wxEVT_COMMAND_LIST_END_LABEL_EDIT, self.GetParent().GetId())
+ le.SetEventObject(self.GetParent())
+ le.m_itemIndex = itemEdit
+
+ data = self.GetLine(itemEdit)
+
+ le.m_item = data.GetItem(0, le.m_item)
+ le.m_item._text = value
+
+ return not self.GetParent().GetEventHandler().ProcessEvent(le) or le.IsAllowed()
+
+
+ def OnRenameCancelled(self, itemEdit):
+ """
+ Called by :class:`UltimateListTextCtrl`, to cancel the changes and to send the
+ ``EVT_LIST_END_LABEL_EDIT`` event.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ # let owner know that the edit was cancelled
+ le = UltimateListEvent(wxEVT_COMMAND_LIST_END_LABEL_EDIT, self.GetParent().GetId())
+ le.SetEditCanceled(True)
+
+ le.SetEventObject(self.GetParent())
+ le.m_itemIndex = itemEdit
+
+ data = self.GetLine(itemEdit)
+ le.m_item = data.GetItem(0, le.m_item)
+
+ self.GetEventHandler().ProcessEvent(le)
+
+
+ def OnMouse(self, event):
+ """
+ Handles the ``wx.EVT_MOUSE_EVENTS`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if wx.Platform == "__WXMAC__":
+ # On wxMac we can't depend on the EVT_KILL_FOCUS event to properly
+ # shutdown the edit control when the mouse is clicked elsewhere on the
+ # listctrl because the order of events is different (or something like
+ # that,) so explicitly end the edit if it is active.
+ if event.LeftDown() and self._textctrl:
+ self._textctrl.AcceptChanges()
+ self._textctrl.Finish()
+
+ if event.LeftDown():
+ self.SetFocusIgnoringChildren()
+
+ event.SetEventObject(self.GetParent())
+ if self.GetParent().GetEventHandler().ProcessEvent(event):
+ return
+
+ if event.GetEventType() == wx.wxEVT_MOUSEWHEEL:
+ # let the base handle mouse wheel events.
+ self.Refresh()
+ event.Skip()
+ return
+
+ if self.IsEmpty():
+ if event.RightDown():
+ self.SendNotify(-1, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition())
+
+ evtCtx = wx.ContextMenuEvent(wx.wxEVT_CONTEXT_MENU, self.GetParent().GetId(),
+ self.ClientToScreen(event.GetPosition()))
+ evtCtx.SetEventObject(self.GetParent())
+ self.GetParent().GetEventHandler().ProcessEvent(evtCtx)
+
+ return
+
+ if self._dirty:
+ return
+
+ if not (event.Dragging() or event.ButtonDown() or event.LeftUp() or \
+ event.ButtonDClick() or event.Moving() or event.RightUp()):
+ return
+
+ x = event.GetX()
+ y = event.GetY()
+ x, y = self.CalcUnscrolledPosition(x, y)
+
+ # where did we hit it (if we did)?
+ hitResult = 0
+ newItem = None
+ count = self.GetItemCount()
+
+ if self.InReportView():
+ if not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ current = y/self.GetLineHeight()
+ if current < count:
+ newItem, hitResult = self.HitTestLine(current, x, y)
+ else:
+ return
+ else:
+ for current in xrange(count):
+ newItem, hitResult = self.HitTestLine(current, x, y)
+ if hitResult:
+ break
+ else:
+ # TODO: optimize it too! this is less simple than for report view but
+ # enumerating all items is still not a way to do it!!
+ for current in xrange(count):
+ newItem, hitResult = self.HitTestLine(current, x, y)
+ if hitResult:
+ break
+
+ theItem = None
+
+ if not self.IsVirtual():
+ theItem = CreateListItem(current, 0)
+ theItem = self.GetItem(theItem)
+
+ if event.GetEventType() == wx.wxEVT_MOTION and not event.Dragging():
+
+ if current >= 0 and current < count and self.HasAGWFlag(ULC_TRACK_SELECT) and not self._hoverTimer.IsRunning():
+ self._hoverItem = current
+ self._hoverTimer.Start(HOVER_TIME, wx.TIMER_ONE_SHOT)
+
+ if newItem and newItem.IsHyperText() and (hitResult & ULC_HITTEST_ONITEMLABEL) and theItem and theItem.IsEnabled():
+ self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+ self._isonhyperlink = True
+ else:
+ if self._isonhyperlink:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ self._isonhyperlink = False
+
+ if self.HasAGWFlag(ULC_STICKY_HIGHLIGHT) and hitResult:
+ if not self.IsHighlighted(current):
+ self.HighlightAll(False)
+ self.ChangeCurrent(current)
+ self.ReverseHighlight(self._current)
+
+ if self.HasAGWFlag(ULC_SHOW_TOOLTIPS):
+ if newItem and hitResult & ULC_HITTEST_ONITEMLABEL:
+ r,c = (newItem._itemId, newItem._col)
+ line = self.GetLine(r)
+ tt = line.GetToolTip(c)
+ if tt and not tt == "":
+ if self.GetToolTip() and self.GetToolTip().GetTip() != tt:
+ self.SetToolTipString(tt)
+ elif (r,c) in self._shortItems: # if the text didn't fit in the column
+ text = newItem.GetText()
+ if self.GetToolTip() and self.GetToolTip().GetTip() != text:
+ self.SetToolTipString(text)
+ else:
+ self.SetToolTipString("")
+ else:
+ self.SetToolTipString("")
+
+ if self.HasAGWFlag(ULC_HOT_TRACKING):
+ if hitResult:
+ if self._oldHotCurrent != current:
+ if self._oldHotCurrent is not None:
+ self.RefreshLine(self._oldHotCurrent)
+ self._newHotCurrent = current
+ self.RefreshLine(self._newHotCurrent)
+ self._oldHotCurrent = current
+
+ event.Skip()
+ return
+
+ if event.Dragging():
+
+ if not self._isDragging:
+
+ if self._lineLastClicked == -1 or not hitResult or not theItem or not theItem.IsEnabled():
+ return
+
+ if self._dragCount == 0:
+ # we have to report the raw, physical coords as we want to be
+ # able to call HitTest(event.m_pointDrag) from the user code to
+ # get the item being dragged
+ self._dragStart = event.GetPosition()
+
+ self._dragCount += 1
+
+ if self._dragCount != 3:
+ return
+
+ command = (event.RightIsDown() and [wxEVT_COMMAND_LIST_BEGIN_RDRAG] or [wxEVT_COMMAND_LIST_BEGIN_DRAG])[0]
+ le = UltimateListEvent(command, self.GetParent().GetId())
+ le.SetEventObject(self.GetParent())
+ le.m_itemIndex = self._lineLastClicked
+ le.m_pointDrag = self._dragStart
+ self.GetParent().GetEventHandler().ProcessEvent(le)
+
+ # we're going to drag this item
+ self._isDragging = True
+ self._dragItem = current
+
+ # remember the old cursor because we will change it while
+ # dragging
+ self._oldCursor = self._cursor
+ self.SetCursor(self._dragCursor)
+
+ else:
+
+ if current != self._dropTarget:
+
+ self.SetCursor(self._dragCursor)
+ # unhighlight the previous drop target
+ if self._dropTarget is not None:
+ self.RefreshLine(self._dropTarget)
+
+ move = current
+ if self._dropTarget:
+ move = (current > self._dropTarget and [current+1] or [current-1])[0]
+
+ self._dropTarget = current
+ self.MoveToItem(move)
+
+ else:
+
+ if self._dragItem == current:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_NO_ENTRY))
+
+ if self.HasAGWFlag(ULC_REPORT) and self._dragItem != current:
+ self.DrawDnDArrow()
+
+ return
+
+ else:
+
+ self._dragCount = 0
+
+ if theItem and not theItem.IsEnabled():
+ self.DragFinish(event)
+ event.Skip()
+ return
+
+ if not hitResult:
+ # outside of any item
+ if event.RightDown():
+ self.SendNotify(-1, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition())
+ evtCtx = wx.ContextMenuEvent(wx.wxEVT_CONTEXT_MENU, self.GetParent().GetId(),
+ self.ClientToScreen(event.GetPosition()))
+ evtCtx.SetEventObject(self.GetParent())
+ self.GetParent().GetEventHandler().ProcessEvent(evtCtx)
+ else:
+ self.HighlightAll(False)
+ self.DragFinish(event)
+
+ return
+
+ forceClick = False
+ if event.ButtonDClick():
+ if self._renameTimer.IsRunning():
+ self._renameTimer.Stop()
+
+ self._lastOnSame = False
+
+ if current == self._lineLastClicked:
+ self.SendNotify(current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
+
+ if newItem and newItem.GetKind() in [1, 2] and (hitResult & ULC_HITTEST_ONITEMCHECK):
+ self.CheckItem(newItem, not self.IsItemChecked(newItem))
+
+ return
+
+ else:
+
+ # The first click was on another item, so don't interpret this as
+ # a double click, but as a simple click instead
+ forceClick = True
+
+ if event.LeftUp():
+
+ if self.DragFinish(event):
+ return
+ if self._lineSelectSingleOnUp != - 1:
+ # select single line
+ self.HighlightAll(False)
+ self.ReverseHighlight(self._lineSelectSingleOnUp)
+
+ if self._lastOnSame:
+ if (current == self._current) and (hitResult == ULC_HITTEST_ONITEMLABEL) and self.HasAGWFlag(ULC_EDIT_LABELS):
+ if not self.InReportView() or self.GetLineLabelRect(current).Contains((x, y)):
+ # This wx.SYS_DCLICK_MSEC is not yet wrapped in wxPython...
+ # dclick = wx.SystemSettings.GetMetric(wx.SYS_DCLICK_MSEC)
+ # m_renameTimer->Start(dclick > 0 ? dclick : 250, True)
+ self._renameTimer.Start(250, True)
+
+ self._lastOnSame = False
+ self._lineSelectSingleOnUp = -1
+
+ elif event.RightUp():
+
+ if self.DragFinish(event):
+ return
+
+ else:
+
+ # This is necessary, because after a DnD operation in
+ # from and to ourself, the up event is swallowed by the
+ # DnD code. So on next non-up event (which means here and
+ # now) self._lineSelectSingleOnUp should be reset.
+ self._lineSelectSingleOnUp = -1
+
+ if event.RightDown():
+
+ if self.SendNotify(current, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition()):
+ self._lineBeforeLastClicked = self._lineLastClicked
+ self._lineLastClicked = current
+ # If the item is already selected, do not update the selection.
+ # Multi-selections should not be cleared if a selected item is clicked.
+
+ if not self.IsHighlighted(current):
+ self.HighlightAll(False)
+ self.ChangeCurrent(current)
+ self.ReverseHighlight(self._current)
+
+ # Allow generation of context menu event
+ event.Skip()
+
+ elif event.MiddleDown():
+ self.SendNotify(current, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
+
+ elif event.LeftDown() or forceClick:
+ self._lineBeforeLastClicked = self._lineLastClicked
+ self._lineLastClicked = current
+
+ oldCurrent = self._current
+ oldWasSelected = self.IsHighlighted(self._current)
+
+ cmdModifierDown = event.CmdDown()
+ if self.IsSingleSel() or not (cmdModifierDown or event.ShiftDown()):
+ if self.IsSingleSel() or not self.IsHighlighted(current):
+ self.HighlightAll(False)
+ self.ChangeCurrent(current)
+ self.ReverseHighlight(self._current)
+
+ else: # multi sel & current is highlighted & no mod keys
+ self._lineSelectSingleOnUp = current
+ self.ChangeCurrent(current) # change focus
+
+ else: # multi sel & either ctrl or shift is down
+ if cmdModifierDown:
+ self.ChangeCurrent(current)
+ self.ReverseHighlight(self._current)
+
+ elif event.ShiftDown():
+ self.ChangeCurrent(current)
+ lineFrom, lineTo = oldCurrent, current
+ shift = 0
+
+ if lineTo < lineFrom:
+ lineTo = lineFrom
+ lineFrom = self._current
+
+ if not self.IsHighlighted(lineFrom):
+ shift = 1
+
+ for i in xrange(lineFrom+1, lineTo+1):
+ if self.IsHighlighted(i):
+ self.HighlightLine(i, False)
+ self.RefreshLine(i)
+ lineTo -= 1
+
+ self.HighlightLines(lineFrom, lineTo+shift)
+
+ else: # !ctrl, !shift
+
+ # test in the enclosing if should make it impossible
+ raise Exception("how did we get here?")
+
+ if newItem:
+ if event.LeftDown():
+ if newItem.GetKind() in [1, 2] and (hitResult & ULC_HITTEST_ONITEMCHECK):
+ self.CheckItem(newItem, not self.IsItemChecked(newItem))
+ if newItem.IsHyperText():
+ self.SetItemVisited(newItem, True)
+ self.HandleHyperLink(newItem)
+
+ if self._current != oldCurrent:
+ self.RefreshLine(oldCurrent)
+
+ # forceClick is only set if the previous click was on another item
+ self._lastOnSame = not forceClick and (self._current == oldCurrent) and oldWasSelected
+
+ if self.HasAGWFlag(ULC_STICKY_HIGHLIGHT) and self.HasAGWFlag(ULC_STICKY_NOSELEVENT) and self.HasAGWFlag(ULC_SEND_LEFTCLICK):
+ self.SendNotify(current, wxEVT_COMMAND_LIST_ITEM_LEFT_CLICK, event.GetPosition())
+
+
+ def DrawDnDArrow(self):
+ """ Draws a drag and drop visual representation of an arrow. """
+
+ dc = wx.ClientDC(self)
+ lineY = self.GetLineY(self._dropTarget)
+ width = self.GetTotalWidth()
+
+ dc.SetPen(wx.Pen(wx.BLACK, 2))
+ x, y = self.CalcScrolledPosition(HEADER_OFFSET_X, lineY+2*HEADER_OFFSET_Y)
+
+ tri1 = [wx.Point(x+1, y-2), wx.Point(x+1, y+4), wx.Point(x+4, y+1)]
+ tri2 = [wx.Point(x+width-1, y-2), wx.Point(x+width-1, y+4), wx.Point(x+width-4, y+1)]
+ dc.DrawPolygon(tri1)
+ dc.DrawPolygon(tri2)
+
+ dc.DrawLine(x, y+1, width, y+1)
+
+
+ def DragFinish(self, event):
+ """
+ A drag and drop operation has just finished.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if not self._isDragging:
+ return False
+
+ self._isDragging = False
+ self._dragCount = 0
+ self._dragItem = None
+ self.SetCursor(self._oldCursor)
+ self.Refresh()
+
+ le = UltimateListEvent(wxEVT_COMMAND_LIST_END_DRAG, self.GetParent().GetId())
+ le.SetEventObject(self.GetParent())
+ le.m_itemIndex = self._dropTarget
+ le.m_pointDrag = event.GetPosition()
+ self.GetParent().GetEventHandler().ProcessEvent(le)
+
+ return True
+
+
+ def HandleHyperLink(self, item):
+ """
+ Handles the hyperlink items, sending the ``EVT_LIST_ITEM_HYPERLINK`` event.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ if self.IsItemHyperText(item):
+ self.SendNotify(item._itemId, wxEVT_COMMAND_LIST_ITEM_HYPERLINK)
+
+
+ def OnHoverTimer(self, event):
+ """
+ Handles the ``wx.EVT_TIMER`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`TimerEvent` event to be processed.
+ """
+
+ x, y = self.ScreenToClient(wx.GetMousePosition())
+ x, y = self.CalcUnscrolledPosition(x, y)
+ item, hitResult = self.HitTestLine(self._hoverItem, x, y)
+
+ if item and item._itemId == self._hoverItem:
+ if not self.IsHighlighted(self._hoverItem):
+
+ dontNotify = self.HasAGWFlag(ULC_STICKY_HIGHLIGHT) and self.HasAGWFlag(ULC_STICKY_NOSELEVENT)
+ if not dontNotify:
+ self.SendNotify(self._hoverItem, wxEVT_COMMAND_LIST_ITEM_SELECTED)
+
+ self.HighlightAll(False)
+ self.ChangeCurrent(self._hoverItem)
+ self.ReverseHighlight(self._current)
+
+
+ def MoveToItem(self, item):
+ """
+ Scrolls the input item into view.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ if item == -1:
+ return
+
+ if item >= self.GetItemCount():
+ item = self.GetItemCount() - 1
+
+ rect = self.GetLineRect(item)
+ client_w, client_h = self.GetClientSize()
+ hLine = self.GetLineHeight(item)
+
+ view_x = SCROLL_UNIT_X*self.GetScrollPos(wx.HORIZONTAL)
+ view_y = hLine*self.GetScrollPos(wx.VERTICAL)
+
+ if self.InReportView():
+
+ # the next we need the range of lines shown it might be different, so
+ # recalculate it
+ self.ResetVisibleLinesRange()
+
+ if not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+
+ if rect.y < view_y:
+ self.Scroll(-1, rect.y/hLine)
+ if rect.y+rect.height+5 > view_y+client_h:
+ self.Scroll(-1, (rect.y+rect.height-client_h+hLine)/hLine)
+
+ if wx.Platform == "__WXMAC__":
+ # At least on Mac the visible lines value will get reset inside of
+ # Scroll *before* it actually scrolls the window because of the
+ # Update() that happens there, so it will still have the wrong value.
+ # So let's reset it again and wait for it to be recalculated in the
+ # next paint event. I would expect this problem to show up in wxGTK
+ # too but couldn't duplicate it there. Perhaps the order of events
+ # is different... --Robin
+ self.ResetVisibleLinesRange()
+
+ else:
+
+ view_y = SCROLL_UNIT_Y*self.GetScrollPos(wx.VERTICAL)
+ start_y, height = rect.y, rect.height
+
+ if start_y < view_y:
+ while start_y > view_y:
+ start_y -= SCROLL_UNIT_Y
+
+ self.Scroll(-1, start_y/SCROLL_UNIT_Y)
+
+ if start_y + height > view_y + client_h:
+ while start_y + height < view_y + client_h:
+ start_y += SCROLL_UNIT_Y
+
+ self.Scroll(-1, (start_y+height-client_h+SCROLL_UNIT_Y)/SCROLL_UNIT_Y)
+
+ else: # !report
+
+
+ sx = sy = -1
+
+ if rect.x-view_x < 5:
+ sx = (rect.x - 5)/SCROLL_UNIT_X
+ if rect.x+rect.width-5 > view_x+client_w:
+ sx = (rect.x + rect.width - client_w + SCROLL_UNIT_X)/SCROLL_UNIT_X
+
+ if rect.y-view_y < 5:
+ sy = (rect.y - 5)/hLine
+ if rect.y + rect.height - 5 > view_y + client_h:
+ sy = (rect.y + rect.height - client_h + hLine)/hLine
+
+ self.Scroll(sx, sy)
+
+
+# ----------------------------------------------------------------------------
+# keyboard handling
+# ----------------------------------------------------------------------------
+
+ def GetNextActiveItem(self, item, down=True):
+ """
+ Returns the next active item. Used Internally at present.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `down`: ``True`` to search downwards for an active item, ``False``
+ to search upwards.
+ """
+
+ count = self.GetItemCount()
+ initialItem = item
+
+ while 1:
+ if item >= count or item < 0:
+ return initialItem
+
+ listItem = CreateListItem(item, 0)
+ listItem = self.GetItem(listItem, 0)
+ if listItem.IsEnabled():
+ return item
+
+ item = (down and [item+1] or [item-1])[0]
+
+
+ def OnArrowChar(self, newCurrent, event):
+ """
+ Handles the keyboard arrows key events.
+
+ :param `newCurrent`: an integer specifying the new current item;
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ oldCurrent = self._current
+ newCurrent = self.GetNextActiveItem(newCurrent, newCurrent > oldCurrent)
+
+ # in single selection we just ignore Shift as we can't select several
+ # items anyhow
+ if event.ShiftDown() and not self.IsSingleSel():
+
+ self.ChangeCurrent(newCurrent)
+
+ # refresh the old focus to remove it
+ self.RefreshLine(oldCurrent)
+
+ # select all the items between the old and the new one
+ if oldCurrent > newCurrent:
+ newCurrent = oldCurrent
+ oldCurrent = self._current
+
+ self.HighlightLines(oldCurrent, newCurrent)
+
+ else: # !shift
+
+ # all previously selected items are unselected unless ctrl is held
+ # in a multi-selection control
+ if not event.ControlDown() or self.IsSingleSel():
+ self.HighlightAll(False)
+
+ self.ChangeCurrent(newCurrent)
+
+ # refresh the old focus to remove it
+ self.RefreshLine(oldCurrent)
+
+ if not event.ControlDown() or self.IsSingleSel():
+ self.HighlightLine(self._current, True)
+
+ self.RefreshLine(self._current)
+ self.MoveToFocus()
+
+
+ def SetEventAttrs(self, oldEvent, newEvent):
+ """
+ Copies (almost) all of the ``m_*`` attributes from the original :class:`KeyEvent` event
+ to the copy (`newEvent`). Successfully passes the key codes to the application
+ as expected.
+
+ :param `oldEvent`: the original :class:`KeyEvent` event to be processed;
+ :param `newEvent`: the new :class:`KeyEvent` event to be processed.
+
+ .. todo::
+
+ Find out why getting `m_rawFlags` returns a Python ``long`` but the setter
+ expects to receive an ``unsigned int``.
+
+
+ .. versionadded:: 0.9.5
+ """
+
+ if _VERSION_STRING < '2.9':
+
+ attributes = ['m_altDown', 'm_controlDown', 'm_keyCode',
+ 'm_metaDown', 'm_rawCode', 'm_scanCode',
+ 'm_shiftDown', 'm_x', 'm_y']
+
+ for attr in attributes:
+ setattr(newEvent, attr, getattr(oldEvent, attr))
+
+ else:
+ # 2.9.something
+ methods = ['AltDown', 'ControlDown', 'MetaDown', 'ShiftDown']
+
+ for meth in methods:
+ eval('newEvent.Set%s(oldEvent.%s())'%(meth, meth))
+
+ attributes = ['m_keyCode', 'm_rawCode', 'm_x', 'm_y']
+
+ for attr in attributes:
+ setattr(newEvent, attr, getattr(oldEvent, attr))
+
+
+ def OnKeyDown(self, event):
+ """
+ Handles the ``wx.EVT_KEY_DOWN`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ parent = self.GetParent()
+
+ # we propagate the key event upwards
+ ke = wx.KeyEvent(event.GetEventType())
+ self.SetEventAttrs(event, ke)
+
+ ke.SetEventObject(parent)
+ if parent.GetEventHandler().ProcessEvent(ke):
+ event.Skip()
+ return
+
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ """
+ Handles the ``wx.EVT_KEY_UP`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ parent = self.GetParent()
+
+ # we propagate the key event upwards
+ ke = wx.KeyEvent(event.GetEventType())
+ self.SetEventAttrs(event, ke)
+
+ ke.SetEventObject(parent)
+ if parent.GetEventHandler().ProcessEvent(ke):
+ return
+
+ event.Skip()
+
+
+ def OnChar(self, event):
+ """
+ Handles the ``wx.EVT_CHAR`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`KeyEvent` event to be processed.
+ """
+
+ parent = self.GetParent()
+
+ if self.IsVirtual() and self.GetItemCount() == 0:
+ event.Skip()
+ return
+
+ # we send a list_key event up
+ if self.HasCurrent():
+ le = UltimateListEvent(wxEVT_COMMAND_LIST_KEY_DOWN, self.GetParent().GetId())
+ le.m_itemIndex = self._current
+ le.m_item = self.GetLine(self._current).GetItem(0, le.m_item)
+ le.m_code = event.GetKeyCode()
+ le.SetEventObject(parent)
+ parent.GetEventHandler().ProcessEvent(le)
+
+ keyCode = event.GetKeyCode()
+ if keyCode not in [wx.WXK_UP, wx.WXK_DOWN, wx.WXK_RIGHT, wx.WXK_LEFT, \
+ wx.WXK_PAGEUP, wx.WXK_PAGEDOWN, wx.WXK_END, wx.WXK_HOME]:
+
+ # propagate the char event upwards
+ ke = wx.KeyEvent(event.GetEventType())
+ self.SetEventAttrs(event, ke)
+ ke.SetEventObject(parent)
+ if parent.GetEventHandler().ProcessEvent(ke):
+ return
+
+ if event.GetKeyCode() == wx.WXK_TAB:
+ nevent = wx.NavigationKeyEvent()
+ nevent.SetWindowChange(event.ControlDown())
+ nevent.SetDirection(not event.ShiftDown())
+ nevent.SetEventObject(self.GetParent().GetParent())
+ nevent.SetCurrentFocus(self._parent)
+ if self.GetParent().GetParent().GetEventHandler().ProcessEvent(nevent):
+ return
+
+ # no item . nothing to do
+ if not self.HasCurrent():
+ event.Skip()
+ return
+
+ keyCode = event.GetKeyCode()
+
+ if keyCode == wx.WXK_UP:
+ if self._current > 0:
+ self.OnArrowChar(self._current - 1, event)
+ if self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ self._dirty = True
+
+ elif keyCode == wx.WXK_DOWN:
+ if self._current < self.GetItemCount() - 1:
+ self.OnArrowChar(self._current + 1, event)
+ if self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ self._dirty = True
+
+ elif keyCode == wx.WXK_END:
+ if not self.IsEmpty():
+ self.OnArrowChar(self.GetItemCount() - 1, event)
+ self._dirty = True
+
+ elif keyCode == wx.WXK_HOME:
+ if not self.IsEmpty():
+ self.OnArrowChar(0, event)
+ self._dirty = True
+
+ elif keyCode == wx.WXK_PRIOR:
+ steps = (self.InReportView() and [self._linesPerPage - 1] or [self._current % self._linesPerPage])[0]
+ index = self._current - steps
+
+ if index < 0:
+ index = 0
+
+ self.OnArrowChar(index, event)
+ self._dirty = True
+
+ elif keyCode == wx.WXK_NEXT:
+
+ steps = (self.InReportView() and [self._linesPerPage - 1] or [self._linesPerPage - (self._current % self._linesPerPage) - 1])[0]
+ index = self._current + steps
+ count = self.GetItemCount()
+
+ if index >= count:
+ index = count - 1
+
+ self.OnArrowChar(index, event)
+ self._dirty = True
+
+ elif keyCode == wx.WXK_LEFT:
+ if not self.InReportView():
+
+ index = self._current - self._linesPerPage
+ if index < 0:
+ index = 0
+
+ self.OnArrowChar(index, event)
+
+ elif keyCode == wx.WXK_RIGHT:
+ if not self.InReportView():
+
+ index = self._current + self._linesPerPage
+ count = self.GetItemCount()
+
+ if index >= count:
+ index = count - 1
+
+ self.OnArrowChar(index, event)
+
+ elif keyCode == wx.WXK_SPACE:
+ if self.IsSingleSel():
+
+ if event.ControlDown():
+ self.ReverseHighlight(self._current)
+ else: # normal space press
+ self.SendNotify(self._current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
+
+ else:
+ # select it in ReverseHighlight() below if unselected
+ self.ReverseHighlight(self._current)
+
+ elif keyCode in [wx.WXK_RETURN, wx.WXK_EXECUTE, wx.WXK_NUMPAD_ENTER]:
+ self.SendNotify(self._current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
+
+ else:
+ event.Skip()
+
+
+# ----------------------------------------------------------------------------
+# focus handling
+# ----------------------------------------------------------------------------
+
+ def OnSetFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if self.GetParent():
+ event = wx.FocusEvent(wx.wxEVT_SET_FOCUS, self.GetParent().GetId())
+ event.SetEventObject(self.GetParent())
+ if self.GetParent().GetEventHandler().ProcessEvent(event):
+ return
+
+ # wxGTK sends us EVT_SET_FOCUS events even if we had never got
+ # EVT_KILL_FOCUS before which means that we finish by redrawing the items
+ # which are already drawn correctly resulting in horrible flicker - avoid
+ # it
+ if not self._hasFocus:
+ self._hasFocus = True
+ self.Refresh()
+
+
+ def OnKillFocus(self, event):
+ """
+ Handles the ``wx.EVT_KILL_FOCUS`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if self.GetParent():
+ event = wx.FocusEvent(wx.wxEVT_KILL_FOCUS, self.GetParent().GetId())
+ event.SetEventObject(self.GetParent())
+ if self.GetParent().GetEventHandler().ProcessEvent(event):
+ return
+
+ self._hasFocus = False
+ self.Refresh()
+
+
+ def DrawImage(self, index, dc, x, y, enabled):
+ """
+ Draws one of the item images.
+
+ :param `index`: the index of the image inside the image list;
+ :param `dc`: an instance of :class:`DC`;
+ :param `x`: the x position where to draw the image;
+ :param `y`: the y position where to draw the image;
+ :param `enabled`: ``True`` if the item is enabled, ``False`` if it is disabled.
+ """
+
+ if self.HasAGWFlag(ULC_ICON) and self._normal_image_list:
+ imgList = (enabled and [self._normal_image_list] or [self._normal_grayed_image_list])[0]
+ imgList.Draw(index, dc, x, y, wx.IMAGELIST_DRAW_TRANSPARENT)
+
+ elif self.HasAGWFlag(ULC_SMALL_ICON) and self._small_image_list:
+ imgList = (enabled and [self._small_image_list] or [self._small_grayed_image_list])[0]
+ imgList.Draw(index, dc, x, y, wx.IMAGELIST_DRAW_TRANSPARENT)
+
+ elif self.HasAGWFlag(ULC_LIST) and self._small_image_list:
+ imgList = (enabled and [self._small_image_list] or [self._small_grayed_image_list])[0]
+ imgList.Draw(index, dc, x, y, wx.IMAGELIST_DRAW_TRANSPARENT)
+
+ elif self.InReportView() and self._small_image_list:
+ imgList = (enabled and [self._small_image_list] or [self._small_grayed_image_list])[0]
+ imgList.Draw(index, dc, x, y, wx.IMAGELIST_DRAW_TRANSPARENT)
+
+
+ def DrawCheckbox(self, dc, x, y, kind, checked, enabled):
+ """
+ Draws the item checkbox/radiobutton image.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `x`: the x position where to draw the image;
+ :param `y`: the y position where to draw the image;
+ :param `kind`: may be one of the following integers:
+
+ =============== ==========================
+ Item Kind Description
+ =============== ==========================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== ==========================
+
+ :param `checked`: ``True`` if the item is checked, ``False`` otherwise;
+ :param `enabled`: ``True`` if the item is enabled, ``False`` if it is disabled.
+ """
+
+ imgList = (enabled and [self._image_list_check] or [self._grayed_check_list])[0]
+ if kind == 1:
+ # checkbox
+ index = (checked and [0] or [1])[0]
+ else:
+ # radiobutton
+ index = (checked and [2] or [3])[0]
+
+ imgList.Draw(index, dc, x, y, wx.IMAGELIST_DRAW_TRANSPARENT)
+
+
+ def GetCheckboxImageSize(self):
+ """ Returns the checkbox/radiobutton image size. """
+
+ bmp = self._image_list_check.GetBitmap(0)
+ return bmp.GetWidth(), bmp.GetHeight()
+
+
+ def GetImageSize(self, index):
+ """
+ Returns the image size for the item.
+
+ :param `index`: the image index.
+ """
+
+ width = height = 0
+
+ if self.HasAGWFlag(ULC_ICON) and self._normal_image_list:
+
+ for indx in index:
+ w, h = self._normal_image_list.GetSize(indx)
+ width += w + MARGIN_BETWEEN_TEXT_AND_ICON
+ height = max(height, h)
+
+ elif self.HasAGWFlag(ULC_SMALL_ICON) and self._small_image_list:
+
+ for indx in index:
+ w, h = self._small_image_list.GetSize(indx)
+ width += w + MARGIN_BETWEEN_TEXT_AND_ICON
+ height = max(height, h)
+
+ elif self.HasAGWFlag(ULC_LIST) and self._small_image_list:
+
+ for indx in index:
+ w, h = self._small_image_list.GetSize(indx)
+ width += w + MARGIN_BETWEEN_TEXT_AND_ICON
+ height = max(height, h)
+
+ elif self.InReportView() and self._small_image_list:
+
+ for indx in index:
+ w, h = self._small_image_list.GetSize(indx)
+ width += w + MARGIN_BETWEEN_TEXT_AND_ICON
+ height = max(height, h)
+
+ return width, height
+
+
+ def GetTextLength(self, s):
+ """
+ Returns the text width for the input string.
+
+ :param `s`: the string to measure.
+ """
+
+ dc = wx.ClientDC(self)
+ dc.SetFont(self.GetFont())
+
+ lw, lh, dummy = dc.GetMultiLineTextExtent(s)
+
+ return lw + AUTOSIZE_COL_MARGIN
+
+
+ def SetImageList(self, imageList, which):
+ """
+ Sets the image list associated with the control.
+
+ :param `imageList`: an instance of :class:`ImageList` or an instance of :class:`PyImageList`;
+ :param `which`: one of ``wx.IMAGE_LIST_NORMAL``, ``wx.IMAGE_LIST_SMALL``,
+ ``wx.IMAGE_LIST_STATE`` (the last is unimplemented).
+
+ :note: Using :class:`PyImageList` enables you to have images of different size inside the
+ image list. In your derived class, instead of doing this::
+
+ imageList = wx.ImageList(16, 16)
+ imageList.Add(someBitmap)
+ self.SetImageList(imageList, wx.IMAGE_LIST_SMALL)
+
+ You should do this::
+
+ imageList = PyImageList(16, 16)
+ imageList.Add(someBitmap)
+ self.SetImageList(imageList, wx.IMAGE_LIST_SMALL)
+
+ """
+
+ self._dirty = True
+
+ if isinstance(imageList, PyImageList):
+ # We have a custom PyImageList with variable image sizes
+ cls = PyImageList
+ else:
+ cls = wx.ImageList
+
+ # calc the spacing from the icon size
+ width = height = 0
+ if imageList and imageList.GetImageCount():
+ width, height = imageList.GetSize(0)
+
+ if which == wx.IMAGE_LIST_NORMAL:
+ self._normal_image_list = imageList
+ self._normal_grayed_image_list = cls(width, height, True, 0)
+
+ for ii in xrange(imageList.GetImageCount()):
+ bmp = imageList.GetBitmap(ii)
+ newbmp = MakeDisabledBitmap(bmp)
+ self._normal_grayed_image_list.Add(newbmp)
+
+ self._normal_spacing = width + 8
+
+ if which == wx.IMAGE_LIST_SMALL:
+ self._small_image_list = imageList
+ self._small_spacing = width + 14
+
+ self._small_grayed_image_list = cls(width, height, True, 0)
+
+ for ii in xrange(imageList.GetImageCount()):
+ bmp = imageList.GetBitmap(ii)
+ newbmp = MakeDisabledBitmap(bmp)
+ self._small_grayed_image_list.Add(newbmp)
+
+ self._lineHeight = 0 # ensure that the line height will be recalc'd
+ self.ResetLineDimensions()
+
+
+ def SetImageListCheck(self, sizex, sizey, imglist=None):
+ """
+ Sets the checkbox/radiobutton image list.
+
+ :param `sizex`: the width of the bitmaps in the `imglist`;
+ :param `sizey`: the height of the bitmaps in the `imglist`;
+ :param `imglist`: an instance of :class:`ImageList`.
+ """
+
+ # Image list to hold disabled versions of each control
+ self._grayed_check_list = wx.ImageList(sizex, sizey, True, 0)
+
+ if imglist is None:
+
+ self._image_list_check = wx.ImageList(sizex, sizey)
+
+ # Get the Checkboxes
+ self._image_list_check.Add(self.GetControlBmp(checkbox=True,
+ checked=True,
+ enabled=True,
+ x=sizex, y=sizey))
+ self._grayed_check_list.Add(self.GetControlBmp(checkbox=True,
+ checked=True,
+ enabled=False,
+ x=sizex, y=sizey))
+
+ self._image_list_check.Add(self.GetControlBmp(checkbox=True,
+ checked=False,
+ enabled=True,
+ x=sizex, y=sizey))
+ self._grayed_check_list.Add(self.GetControlBmp(checkbox=True,
+ checked=False,
+ enabled=False,
+ x=sizex, y=sizey))
+ # Get the Radio Buttons
+ self._image_list_check.Add(self.GetControlBmp(checkbox=False,
+ checked=True,
+ enabled=True,
+ x=sizex, y=sizey))
+ self._grayed_check_list.Add(self.GetControlBmp(checkbox=False,
+ checked=True,
+ enabled=False,
+ x=sizex, y=sizey))
+
+ self._image_list_check.Add(self.GetControlBmp(checkbox=False,
+ checked=False,
+ enabled=True,
+ x=sizex, y=sizey))
+ self._grayed_check_list.Add(self.GetControlBmp(checkbox=False,
+ checked=False,
+ enabled=False,
+ x=sizex, y=sizey))
+ else:
+
+ sizex, sizey = imglist.GetSize(0)
+ self._image_list_check = imglist
+
+ for ii in xrange(self._image_list_check.GetImageCount()):
+
+ bmp = self._image_list_check.GetBitmap(ii)
+ newbmp = MakeDisabledBitmap(bmp)
+ self._grayed_check_list.Add(newbmp)
+
+ self._dirty = True
+
+ if imglist:
+ self.RecalculatePositions()
+
+
+ def GetControlBmp(self, checkbox=True, checked=False, enabled=True, x=16, y=16):
+ """
+ Returns a native looking checkbox or radio button bitmap.
+
+ :param `checkbox`: ``True`` to get a checkbox image, ``False`` for a radiobutton
+ one;
+ :param `checked`: ``True`` if the control is marked, ``False`` if it is not;
+ :param `enabled`: ``True`` if the control is enabled, ``False`` if it is not;
+ :param `x`: the width of the bitmap, in pixels;
+ :param `y`: the height of the bitmap, in pixels.
+ """
+
+ bmp = wx.EmptyBitmap(x, y)
+ mdc = wx.MemoryDC(bmp)
+ mdc.SetBrush(wx.BLACK_BRUSH)
+ mdc.Clear()
+
+ render = wx.RendererNative.Get()
+
+ if checked:
+ flag = wx.CONTROL_CHECKED
+ else:
+ flag = 0
+
+ if not enabled:
+ flag |= wx.CONTROL_DISABLED
+
+
+ if checkbox:
+ render.DrawCheckBox(self, mdc, (0, 0, x, y), flag)
+ else:
+ if _VERSION_STRING < "2.9":
+ render.DrawRadioButton(self, mdc, (0, 0, x, y), flag)
+ else:
+ render.DrawRadioBitmap(self, mdc, (0, 0, x, y), flag)
+
+ mdc.SelectObject(wx.NullBitmap)
+ return bmp
+
+
+ def SetItemSpacing(self, spacing, isSmall=False):
+ """
+ Sets the spacing between item texts and icons.
+
+ :param `spacing`: the spacing between item texts and icons, in pixels;
+ :param `isSmall`: ``True`` if using a ``wx.IMAGE_LIST_SMALL`` image list,
+ ``False`` if using a ``wx.IMAGE_LIST_NORMAL`` image list.
+ """
+
+ self._dirty = True
+
+ if isSmall:
+ self._small_spacing = spacing
+ else:
+ self._normal_spacing = spacing
+
+
+ def GetItemSpacing(self, isSmall=False):
+ """
+ Returns the spacing between item texts and icons, in pixels.
+
+ :param `isSmall`: ``True`` if using a ``wx.IMAGE_LIST_SMALL`` image list,
+ ``False`` if using a ``wx.IMAGE_LIST_NORMAL`` image list.
+ """
+
+ return (isSmall and [self._small_spacing] or [self._normal_spacing])[0]
+
+
+# ----------------------------------------------------------------------------
+# columns
+# ----------------------------------------------------------------------------
+
+ def SetColumn(self, col, item):
+ """
+ Sets information about this column.
+
+ :param `col`: an integer specifying the column index;
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ column = self._columns[col]
+
+ if item._width == ULC_AUTOSIZE_USEHEADER:
+ item._width = self.GetTextLength(item._text)
+
+ column.SetItem(item)
+
+ headerWin = self.GetListCtrl()._headerWin
+ if headerWin:
+ headerWin._dirty = True
+
+ self._dirty = True
+
+ # invalidate it as it has to be recalculated
+ self._headerWidth = 0
+
+
+ def SetColumnWidth(self, col, width):
+ """
+ Sets the column width.
+
+ :param `width`: can be a width in pixels or ``wx.LIST_AUTOSIZE`` (-1) or
+ ``wx.LIST_AUTOSIZE_USEHEADER`` (-2) or ``ULC_AUTOSIZE_FILL`` (-3).
+ ``wx.LIST_AUTOSIZE`` will resize the column to the length of its longest
+ item. ``wx.LIST_AUTOSIZE_USEHEADER`` will resize the column to the
+ length of the header (Win32) or 80 pixels (other platforms).
+ ``ULC_AUTOSIZE_FILL`` will resize the column fill the remaining width
+ of the window.
+
+ :note: In small or normal icon view, col must be -1, and the column width
+ is set for all columns.
+ """
+
+ if col < 0:
+ raise Exception("invalid column index")
+
+ if not self.InReportView() and not self.InTileView() and not self.HasAGWFlag(ULC_HEADER_IN_ALL_VIEWS):
+ raise Exception("SetColumnWidth() can only be called in report/tile modes or with the ULC_HEADER_IN_ALL_VIEWS flag set.")
+
+ self._dirty = True
+ headerWin = self.GetListCtrl()._headerWin
+ footerWin = self.GetListCtrl()._footerWin
+
+ if headerWin:
+ headerWin._dirty = True
+
+ if footerWin:
+ footerWin._dirty = True
+
+ column = self._columns[col]
+ count = self.GetItemCount()
+
+ if width == ULC_AUTOSIZE_FILL:
+
+ width = self.GetColumnWidth(col)
+ if width == 0:
+ width = WIDTH_COL_DEFAULT
+ self._resizeColumn = col
+
+ elif width == ULC_AUTOSIZE_USEHEADER:
+
+ width = self.GetTextLength(column.GetText())
+ width += 2*EXTRA_WIDTH
+
+ if column.GetKind() in [1, 2]:
+ ix, iy = self._owner.GetCheckboxImageSize()
+ width += ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE
+
+ # check for column header's image availability
+ images = column.GetImage()
+ for img in images:
+ if self._small_image_list:
+ ix, iy = self._small_image_list.GetSize(img)
+ width += ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE
+
+ elif width == ULC_AUTOSIZE:
+
+ if self.IsVirtual() or not self.InReportView():
+ # TODO: determine the max width somehow...
+ width = WIDTH_COL_DEFAULT
+
+ else: # !virtual
+
+ maxW = AUTOSIZE_COL_MARGIN
+
+ # if the cached column width isn't valid then recalculate it
+ if self._aColWidths[col]._bNeedsUpdate:
+
+ for i in xrange(count):
+
+ line = self.GetLine(i)
+ itemData = line._items[col]
+ item = UltimateListItem()
+
+ item = itemData.GetItem(item)
+ itemWidth = self.GetItemWidthWithImage(item)
+ if itemWidth > maxW and not item._overFlow:
+ maxW = itemWidth
+
+ self._aColWidths[col]._bNeedsUpdate = False
+ self._aColWidths[col]._nMaxWidth = maxW
+
+ maxW = self._aColWidths[col]._nMaxWidth
+ width = maxW + AUTOSIZE_COL_MARGIN
+
+ column.SetWidth(width)
+
+ # invalidate it as it has to be recalculated
+ self._headerWidth = 0
+ self._footerWidth = 0
+
+ if footerWin:
+ footerWin.Refresh()
+
+
+ def GetHeaderWidth(self):
+ """ Returns the header window width, in pixels. """
+
+ if not self._headerWidth:
+
+ count = self.GetColumnCount()
+ for col in xrange(count):
+
+ if not self.IsColumnShown(col):
+ continue
+
+ self._headerWidth += self.GetColumnWidth(col)
+
+ if self.HasAGWFlag(ULC_FOOTER):
+ self._footerWidth = self._headerWidth
+
+ return self._headerWidth
+
+
+ def GetColumn(self, col):
+ """
+ Returns information about this column.
+
+ :param `col`: an integer specifying the column index.
+ """
+
+ item = UltimateListItem()
+ column = self._columns[col]
+ item = column.GetItem(item)
+
+ return item
+
+
+ def GetColumnWidth(self, col):
+ """
+ Returns the column width for the input column.
+
+ :param `col`: an integer specifying the column index.
+ """
+
+ column = self._columns[col]
+ return column.GetWidth()
+
+
+ def GetTotalWidth(self):
+ """ Returns the total width of the columns in :class:`UltimateListCtrl`. """
+
+ width = 0
+ for column in self._columns:
+ width += column.GetWidth()
+
+ return width
+
+# ----------------------------------------------------------------------------
+# item state
+# ----------------------------------------------------------------------------
+
+ def SetItem(self, item):
+ """
+ Sets information about the item.
+
+ :param `item`: an instance of :class:`UltimateListItemData`.
+ """
+
+ id = item._itemId
+
+ if id < 0 or id >= self.GetItemCount():
+ raise Exception("invalid item index in SetItem")
+
+ if not self.IsVirtual():
+
+ line = self.GetLine(id)
+ line.SetItem(item._col, item)
+
+ # Set item state if user wants
+ if item._mask & ULC_MASK_STATE:
+ self.SetItemState(item._itemId, item._state, item._state)
+
+ if self.InReportView():
+
+ # update the Max Width Cache if needed
+ width = self.GetItemWidthWithImage(item)
+
+ if width > self._aColWidths[item._col]._nMaxWidth:
+ self._aColWidths[item._col]._nMaxWidth = width
+ self._aColWidths[item._col]._bNeedsUpdate = True
+
+ if self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ line.ResetDimensions()
+
+ # update the item on screen
+ if self.InReportView():
+ rectItem = self.GetItemRect(id)
+ self.RefreshRect(rectItem)
+
+
+ def SetItemStateAll(self, state, stateMask):
+ """
+ Sets the item state flags for all the items.
+
+ :param `state`: any combination of the following bits:
+
+ ============================ ========= ==============================
+ State Bits Hex Value Description
+ ============================ ========= ==============================
+ ``ULC_STATE_DONTCARE`` 0x0 Don't care what the state is
+ ``ULC_STATE_DROPHILITED`` 0x1 The item is highlighted to receive a drop event
+ ``ULC_STATE_FOCUSED`` 0x2 The item has the focus
+ ``ULC_STATE_SELECTED`` 0x4 The item is selected
+ ``ULC_STATE_CUT`` 0x8 The item is in the cut state
+ ``ULC_STATE_DISABLED`` 0x10 The item is disabled
+ ``ULC_STATE_FILTERED`` 0x20 The item has been filtered
+ ``ULC_STATE_INUSE`` 0x40 The item is in use
+ ``ULC_STATE_PICKED`` 0x80 The item has been picked
+ ``ULC_STATE_SOURCE`` 0x100 The item is a drag and drop source
+ ============================ ========= ==============================
+
+ :param `stateMask`: the bitmask for the state flag.
+
+ :note: The valid state flags are influenced by the value of the state mask.
+ """
+
+ if self.IsEmpty():
+ return
+
+ # first deal with selection
+ if stateMask & ULC_STATE_SELECTED:
+
+ # set/clear select state
+ if self.IsVirtual():
+
+ # optimized version for virtual listctrl.
+ self._selStore.SelectRange(0, self.GetItemCount() - 1, state==ULC_STATE_SELECTED)
+ self.Refresh()
+
+ elif state & ULC_STATE_SELECTED:
+
+ count = self.GetItemCount()
+ for i in xrange(count):
+ self.SetItemState(i, ULC_STATE_SELECTED, ULC_STATE_SELECTED)
+
+ else:
+
+ # clear for non virtual (somewhat optimized by using GetNextItem())
+ i = -1
+ while 1:
+ i += 1
+ if self.GetNextItem(i, ULC_NEXT_ALL, ULC_STATE_SELECTED) == -1:
+ break
+
+ self.SetItemState(i, 0, ULC_STATE_SELECTED)
+
+ if self.HasCurrent() and state == 0 and stateMask & ULC_STATE_FOCUSED:
+
+ # unfocus all: only one item can be focussed, so clearing focus for
+ # all items is simply clearing focus of the focussed item.
+ self.SetItemState(self._current, state, stateMask)
+
+ #(setting focus to all items makes no sense, so it is not handled here.)
+
+
+ def SetItemState(self, litem, state, stateMask):
+ """
+ Sets the item state flags for the input item.
+
+ :param `litem`: the index of the item; if defaulted to -1, the state flag
+ will be set for all the items;
+ :param `state`: the item state flag;
+ :param `stateMask`: the bitmask for the state flag.
+
+ :see: :meth:`~UltimateListMainWindow.SetItemStateAll` for a list of valid state flags.
+ """
+
+ if litem == -1:
+ self.SetItemStateAll(state, stateMask)
+ return
+
+ if litem < 0 or litem >= self.GetItemCount():
+ raise Exception("invalid item index in SetItemState")
+
+ oldCurrent = self._current
+ item = litem # safe because of the check above
+
+ # do we need to change the focus?
+ if stateMask & ULC_STATE_FOCUSED:
+
+ if state & ULC_STATE_FOCUSED:
+
+ # don't do anything if this item is already focused
+ if item != self._current:
+
+ self.ChangeCurrent(item)
+
+ if oldCurrent != - 1:
+
+ if self.IsSingleSel():
+
+ self.HighlightLine(oldCurrent, False)
+
+ self.RefreshLine(oldCurrent)
+
+ self.RefreshLine(self._current)
+
+ else: # unfocus
+
+ # don't do anything if this item is not focused
+ if item == self._current:
+
+ self.ResetCurrent()
+
+ if self.IsSingleSel():
+
+ # we must unselect the old current item as well or we
+ # might end up with more than one selected item in a
+ # single selection control
+ self.HighlightLine(oldCurrent, False)
+
+ self.RefreshLine(oldCurrent)
+
+ # do we need to change the selection state?
+ if stateMask & ULC_STATE_SELECTED:
+
+ on = (state & ULC_STATE_SELECTED) != 0
+
+ if self.IsSingleSel():
+
+ if on:
+
+ # selecting the item also makes it the focused one in the
+ # single sel mode
+ if self._current != item:
+
+ self.ChangeCurrent(item)
+
+ if oldCurrent != - 1:
+
+ self.HighlightLine(oldCurrent, False)
+ self.RefreshLine(oldCurrent)
+
+ else: # off
+
+ # only the current item may be selected anyhow
+ if item != self._current:
+ return
+
+ if self.HighlightLine(item, on):
+ self.RefreshLine(item)
+
+
+ def GetItemState(self, item, stateMask):
+ """
+ Returns the item state flags for the input item.
+
+ :param `item`: the index of the item;
+ :param `stateMask`: the bitmask for the state flag.
+
+ :see: :meth:`~UltimateListMainWindow.SetItemStateAll` for a list of valid state flags.
+ """
+
+ if item < 0 or item >= self.GetItemCount():
+ raise Exception("invalid item index in GetItemState")
+
+ ret = ULC_STATE_DONTCARE
+
+ if stateMask & ULC_STATE_FOCUSED:
+ if item == self._current:
+ ret |= ULC_STATE_FOCUSED
+
+ if stateMask & ULC_STATE_SELECTED:
+ if self.IsHighlighted(item):
+ ret |= ULC_STATE_SELECTED
+
+ return ret
+
+
+ def GetItem(self, item, col=0):
+ """
+ Returns the information about the input item.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `col`: the column to which the item belongs to.
+ """
+
+ if item._itemId < 0 or item._itemId >= self.GetItemCount():
+ raise Exception("invalid item index in GetItem")
+
+ line = self.GetLine(item._itemId)
+ item = line.GetItem(col, item)
+
+ # Get item state if user wants it
+ if item._mask & ULC_MASK_STATE:
+ item._state = self.GetItemState(item._itemId, ULC_STATE_SELECTED | ULC_STATE_FOCUSED)
+
+ return item
+
+
+ def CheckItem(self, item, checked=True, sendEvent=True):
+ """
+ Actually checks/uncheks an item, sending (eventually) the two
+ events ``EVT_LIST_ITEM_CHECKING`` / ``EVT_LIST_ITEM_CHECKED``.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `checked`: ``True`` to check an item, ``False`` to uncheck it;
+ :param `sendEvent`: ``True`` to send a {UltimateListEvent}, ``False`` otherwise.
+
+ :note: This method is meaningful only for checkbox-like and radiobutton-like items.
+ """
+
+ # Should we raise an error here?!?
+ if item.GetKind() == 0 or not item.IsEnabled():
+ return
+
+ if sendEvent:
+
+ parent = self.GetParent()
+ le = UltimateListEvent(wxEVT_COMMAND_LIST_ITEM_CHECKING, parent.GetId())
+ le.m_itemIndex = item._itemId
+ le.m_item = item
+ le.SetEventObject(parent)
+
+ if parent.GetEventHandler().ProcessEvent(le):
+ # Blocked by user
+ return
+
+ item.Check(checked)
+ self.SetItem(item)
+ self.RefreshLine(item._itemId)
+
+ if not sendEvent:
+ return
+
+ le = UltimateListEvent(wxEVT_COMMAND_LIST_ITEM_CHECKED, parent.GetId())
+ le.m_itemIndex = item._itemId
+ le.m_item = item
+ le.SetEventObject(parent)
+ parent.GetEventHandler().ProcessEvent(le)
+
+
+ def AutoCheckChild(self, isChecked, column):
+ """
+ Checks/unchecks all the items.
+
+ :param `isChecked`: ``True`` to check the items, ``False`` to uncheck them;
+ :param `column`: the column to which the items belongs to.
+
+ :note: This method is meaningful only for checkbox-like and radiobutton-like items.
+ """
+
+ for indx in xrange(self.GetItemCount()):
+ item = CreateListItem(indx, column)
+ newItem = self.GetItem(item, column)
+ self.CheckItem(newItem, not isChecked, False)
+
+
+ def AutoToggleChild(self, column):
+ """
+ Toggles all the items.
+
+ :param `column`: the column to which the items belongs to.
+
+ :note: This method is meaningful only for checkbox-like and radiobutton-like items.
+ """
+
+ for indx in xrange(self.GetItemCount()):
+ item = CreateListItem(indx, column)
+ newItem = self.GetItem(item, column)
+
+ if newItem.GetKind() != 1:
+ continue
+
+ self.CheckItem(newItem, not item.IsChecked(), False)
+
+
+ def IsItemChecked(self, item):
+ """
+ Returns whether an item is checked or not.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ item = self.GetItem(item, item._col)
+ return item.IsChecked()
+
+
+ def IsItemEnabled(self, item):
+ """
+ Returns whether an item is enabled or not.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ item = self.GetItem(item, item._col)
+ return item.IsEnabled()
+
+
+ def EnableItem(self, item, enable=True):
+ """
+ Enables/disables an item.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `enable`: ``True`` to enable the item, ``False`` otherwise.
+ """
+
+ item = self.GetItem(item, 0)
+ if item.IsEnabled() == enable:
+ return False
+
+ item.Enable(enable)
+
+ wnd = item.GetWindow()
+ # Handles the eventual window associated to the item
+ if wnd:
+ wnd.Enable(enable)
+
+ self.SetItem(item)
+
+ return True
+
+
+ def GetItemKind(self, item):
+ """
+ Returns the item kind.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+
+ :see: :meth:`~UltimateListMainWindow.SetItemKind` for a list of valid item kinds.
+ """
+
+ item = self.GetItem(item, item._col)
+ return item.GetKind()
+
+
+ def SetItemKind(self, item, kind):
+ """
+ Sets the item kind.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `kind`: may be one of the following integers:
+
+ =============== ==========================
+ Item Kind Description
+ =============== ==========================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== ==========================
+
+ """
+
+ item = self.GetItem(item, item._col)
+ item.SetKind(kind)
+ self.SetItem(item)
+
+ return True
+
+
+ def IsItemHyperText(self, item):
+ """
+ Returns whether an item is hypertext or not.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ item = self.GetItem(item, item._col)
+ return item.IsHyperText()
+
+
+ def SetItemHyperText(self, item, hyper=True):
+ """
+ Sets whether the item is hypertext or not.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `hyper`: ``True`` to have an item with hypertext behaviour, ``False`` otherwise.
+ """
+
+ item = self.GetItem(item, item._col)
+ item.SetHyperText(hyper)
+ self.SetItem(item)
+
+ return True
+
+
+ def GetHyperTextFont(self):
+ """Returns the font used to render an hypertext item."""
+
+ return self._hypertextfont
+
+
+ def SetHyperTextFont(self, font):
+ """
+ Sets the font used to render hypertext items.
+
+ :param `font`: a valid :class:`Font` instance.
+ """
+
+ self._hypertextfont = font
+ self._dirty = True
+
+
+ def SetHyperTextNewColour(self, colour):
+ """
+ Sets the colour used to render a non-visited hypertext item.
+
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ self._hypertextnewcolour = colour
+ self._dirty = True
+
+
+ def GetHyperTextNewColour(self):
+ """ Returns the colour used to render a non-visited hypertext item. """
+
+ return self._hypertextnewcolour
+
+
+ def SetHyperTextVisitedColour(self, colour):
+ """
+ Sets the colour used to render a visited hypertext item.
+
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ self._hypertextvisitedcolour = colour
+ self._dirty = True
+
+
+ def GetHyperTextVisitedColour(self):
+ """ Returns the colour used to render a visited hypertext item. """
+
+ return self._hypertextvisitedcolour
+
+
+ def SetItemVisited(self, item, visited=True):
+ """
+ Sets whether an hypertext item was visited.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `visited`: ``True`` to mark an hypertext item as visited, ``False`` otherwise.
+ """
+
+ newItem = self.GetItem(item, item._col)
+ newItem.SetVisited(visited)
+ self.SetItem(newItem)
+ self.RefreshLine(item)
+
+ return True
+
+
+ def GetItemVisited(self, item):
+ """
+ Returns whether an hypertext item was visited.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ item = self.GetItem(item, item._col)
+ return item.GetVisited()
+
+
+ def GetItemWindow(self, item):
+ """
+ Returns the window associated to the item (if any).
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ item = self.GetItem(item, item._col)
+ return item.GetWindow()
+
+
+ def SetItemWindow(self, item, wnd, expand=False):
+ """
+ Sets the window for the given item.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `wnd`: if not ``None``, a non-toplevel window to be displayed next to
+ the item;
+ :param `expand`: ``True`` to expand the column where the item/subitem lives,
+ so that the window will be fully visible.
+ """
+
+ if not self.InReportView() or not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ raise Exception("Widgets are only allowed in report mode and with the ULC_HAS_VARIABLE_ROW_HEIGHT style.")
+
+ item = self.GetItem(item, item._col)
+
+ if wnd is not None:
+ self._hasWindows = True
+ if item not in self._itemWithWindow:
+ self._itemWithWindow.append(item)
+ else:
+ self.DeleteItemWindow(item)
+ else:
+ self.DeleteItemWindow(item)
+
+ item.SetWindow(wnd, expand)
+ self.SetItem(item)
+ self.RecalculatePositions()
+ self.Refresh()
+
+
+ def DeleteItemWindow(self, item):
+ """
+ Deletes the window associated to an item (if any).
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ if item.GetWindow() is None:
+ return
+
+ item.DeleteWindow()
+ if item in self._itemWithWindow:
+ self._itemWithWindow.remove(item)
+
+ self.SetItem(item)
+ self.RecalculatePositions()
+
+
+ def GetItemWindowEnabled(self, item):
+ """
+ Returns whether the window associated to the item is enabled.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ item = self.GetItem(item, item._col)
+ return item.GetWindowEnabled()
+
+
+ def SetItemWindowEnabled(self, item, enable=True):
+ """
+ Enables/disables the window associated to the item.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `enable`: ``True`` to enable the associated window, ``False`` to
+ disable it.
+ """
+
+ item = self.GetItem(item, item._col)
+ item.SetWindowEnabled(enable)
+ self.SetItem(item)
+ self.Refresh()
+
+
+ def SetColumnCustomRenderer(self, col=0, renderer=None):
+ """
+ Associate a custom renderer to this column's header
+
+ :param `col`: the column index.
+ :param `renderer`: a class able to correctly render the input item.
+
+ :note: the renderer class **must** implement the methods `DrawHeaderButton`
+ and `GetForegroundColor`.
+ """
+
+ self._columns[col].SetCustomRenderer(renderer)
+
+
+ def GetColumnCustomRenderer(self, col):
+ """
+ Returns the custom renderer used to draw the column header
+
+ :param `col`: the column index.
+ """
+
+ return self._columns[col].GetCustomRenderer()
+
+
+ def GetItemCustomRenderer(self, item):
+ """
+ Returns the custom renderer used to draw the input item (if any).
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ item = self.GetItem(item, item._col)
+ return item.GetCustomRenderer()
+
+
+ def SetItemCustomRenderer(self, item, renderer=None):
+ """
+ Associate a custom renderer to this item.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `renderer`: a class able to correctly render the item.
+
+ :note: the renderer class **must** implement the methods `DrawSubItem`,
+ `GetLineHeight` and `GetSubItemWidth`.
+ """
+
+ item = self.GetItem(item, item._col)
+ item.SetCustomRenderer(renderer)
+ self.SetItem(item)
+ self.ResetLineDimensions()
+ self.Refresh()
+
+
+ def GetItemOverFlow(self, item):
+ """
+ Returns if the item is in the overflow state.
+
+ An item/subitem may overwrite neighboring items/subitems if its text would
+ not normally fit in the space allotted to it.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ item = self.GetItem(item, item._col)
+ return item.GetOverFlow()
+
+
+ def SetItemOverFlow(self, item, over=True):
+ """
+ Sets the item in the overflow/non overflow state.
+
+ An item/subitem may overwrite neighboring items/subitems if its text would
+ not normally fit in the space allotted to it.
+
+ :param `item`: an instance of :class:`UltimateListItem`;
+ :param `over`: ``True`` to set the item in a overflow state, ``False`` otherwise.
+ """
+
+ item = self.GetItem(item, item._col)
+ item.SetOverFlow(over)
+ self.SetItem(item)
+ self.Refresh()
+
+
+# ----------------------------------------------------------------------------
+# item count
+# ----------------------------------------------------------------------------
+
+ def GetItemCount(self):
+ """ Returns the number of items in the :class:`UltimateListCtrl`. """
+
+ return (self.IsVirtual() and [self._countVirt] or [len(self._lines)])[0]
+
+
+ def SetItemCount(self, count):
+ """
+ This method can only be used with virtual :class:`UltimateListCtrl`. It is used to
+ indicate to the control the number of items it contains. After calling it,
+ the main program should be ready to handle calls to various item callbacks
+ (such as :meth:`UltimateListCtrl.OnGetItemText() <UltimateListCtrl.OnGetItemText>`) for all items in the range from 0 to `count`.
+
+ :param `count`: the total number of items in :class:`UltimateListCtrl`.
+ """
+
+ self._selStore.SetItemCount(count)
+ self._countVirt = count
+
+ self.ResetVisibleLinesRange()
+
+ # scrollbars must be reset
+ self._dirty = True
+
+
+ def GetSelectedItemCount(self):
+ """ Returns the number of selected items in :class:`UltimateListCtrl`. """
+
+ # deal with the quick case first
+ if self.IsSingleSel():
+ return (self.HasCurrent() and [self.IsHighlighted(self._current)] or [False])[0]
+
+ # virtual controls remmebers all its selections itself
+ if self.IsVirtual():
+ return self._selStore.GetSelectedCount()
+
+ # TODO: we probably should maintain the number of items selected even for
+ # non virtual controls as enumerating all lines is really slow...
+ countSel = 0
+ count = self.GetItemCount()
+ for line in xrange(count):
+ if self.GetLine(line).IsHighlighted():
+ countSel += 1
+
+ return countSel
+
+
+# ----------------------------------------------------------------------------
+# item position/size
+# ----------------------------------------------------------------------------
+
+ def GetViewRect(self):
+ """
+ Returns the rectangle taken by all items in the control. In other words,
+ if the controls client size were equal to the size of this rectangle, no
+ scrollbars would be needed and no free space would be left.
+
+ :note: This function only works in the icon and small icon views, not in
+ list or report views.
+ """
+
+ if self.HasAGWFlag(ULC_LIST):
+ raise Exception("UltimateListCtrl.GetViewRect() not implemented for list view")
+
+ # we need to find the longest/tallest label
+ xMax = yMax = 0
+ count = self.GetItemCount()
+
+ if count:
+ for i in xrange(count):
+ # we need logical, not physical, coordinates here, so use
+ # GetLineRect() instead of GetItemRect()
+ r = self.GetLineRect(i)
+ x, y = r.GetRight(), r.GetBottom()
+
+ if x > xMax:
+ xMax = x
+ if y > yMax:
+ yMax = y
+
+ # some fudge needed to make it look prettier
+ xMax += 2*EXTRA_BORDER_X
+ yMax += 2*EXTRA_BORDER_Y
+
+ # account for the scrollbars if necessary
+ sizeAll = self.GetClientSize()
+ if xMax > sizeAll.x:
+ yMax += wx.SystemSettings.GetMetric(wx.SYS_HSCROLL_Y)
+ if yMax > sizeAll.y:
+ xMax += wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X)
+
+ return wx.Rect(0, 0, xMax, yMax)
+
+
+ def GetSubItemRect(self, item, subItem):
+ """
+ Returns the rectangle representing the size and position, in physical coordinates,
+ of the given subitem, i.e. the part of the row `item` in the column `subItem`.
+
+ :param `item`: the row in which the item lives;
+ :param `subItem`: the column in which the item lives. If set equal to the special
+ value ``ULC_GETSUBITEMRECT_WHOLEITEM`` the return value is the same as for
+ :meth:`~UltimateListMainWindow.GetItemRect`.
+
+ :note: This method is only meaningful when the :class:`UltimateListCtrl` is in the
+ report mode.
+ """
+
+ if not self.InReportView() and subItem == ULC_GETSUBITEMRECT_WHOLEITEM:
+ raise Exception("GetSubItemRect only meaningful in report view")
+
+ if item < 0 or item >= self.GetItemCount():
+ raise Exception("invalid item in GetSubItemRect")
+
+ # ensure that we're laid out, otherwise we could return nonsense
+ if self._dirty:
+ self.RecalculatePositions(True)
+
+ rect = self.GetLineRect(item)
+
+ # Adjust rect to specified column
+ if subItem != ULC_GETSUBITEMRECT_WHOLEITEM:
+ if subItem < 0 or subItem >= self.GetColumnCount():
+ raise Exception("invalid subItem in GetSubItemRect")
+
+ for i in xrange(subItem):
+ rect.x += self.GetColumnWidth(i)
+
+ rect.width = self.GetColumnWidth(subItem)
+
+ rect.x, rect.y = self.CalcScrolledPosition(rect.x, rect.y)
+ return rect
+
+
+ def GetItemRect(self, item):
+ """
+ Returns the rectangle representing the item's size and position, in physical
+ coordinates.
+
+ :param `item`: the row in which the item lives.
+ """
+
+ return self.GetSubItemRect(item, ULC_GETSUBITEMRECT_WHOLEITEM)
+
+
+ def GetItemPosition(self, item):
+ """
+ Returns the position of the item, in icon or small icon view.
+
+ :param `item`: the row in which the item lives.
+ """
+
+ rect = self.GetItemRect(item)
+ return wx.Point(rect.x, rect.y)
+
+
+# ----------------------------------------------------------------------------
+# geometry calculation
+# ----------------------------------------------------------------------------
+
+ def RecalculatePositions(self, noRefresh=False):
+ """
+ Recalculates all the items positions, and sets the scrollbars positions
+ too.
+
+ :param `noRefresh`: ``True`` to avoid calling `Refresh`, ``False`` otherwise.
+ """
+
+ count = self.GetItemCount()
+
+ if self.HasAGWFlag(ULC_ICON) and self._normal_image_list:
+ iconSpacing = self._normal_spacing
+ elif self.HasAGWFlag(ULC_SMALL_ICON) and self._small_image_list:
+ iconSpacing = self._small_spacing
+ else:
+ iconSpacing = 0
+
+ # Note that we do not call GetClientSize() here but
+ # GetSize() and subtract the border size for sunken
+ # borders manually. This is technically incorrect,
+ # but we need to know the client area's size WITHOUT
+ # scrollbars here. Since we don't know if there are
+ # any scrollbars, we use GetSize() instead. Another
+ # solution would be to call SetScrollbars() here to
+ # remove the scrollbars and call GetClientSize() then,
+ # but this might result in flicker and - worse - will
+ # reset the scrollbars to 0 which is not good at all
+ # if you resize a dialog/window, but don't want to
+ # reset the window scrolling. RR.
+ # Furthermore, we actually do NOT subtract the border
+ # width as 2 pixels is just the extra space which we
+ # need around the actual content in the window. Other-
+ # wise the text would e.g. touch the upper border. RR.
+ clientWidth, clientHeight = self.GetSize()
+
+ if self.InReportView():
+
+ self.ResetVisibleLinesRange()
+
+ if not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ # all lines have the same height and we scroll one line per step
+
+ lineHeight = self.GetLineHeight()
+ entireHeight = count*lineHeight + LINE_SPACING
+ decrement = 0
+ if entireHeight > self.GetClientSize()[1]:
+ decrement = SCROLL_UNIT_X
+
+ self._linesPerPage = clientHeight/lineHeight
+
+ self.SetScrollbars(SCROLL_UNIT_X, lineHeight,
+ (self.GetHeaderWidth()-decrement)/SCROLL_UNIT_X,
+ (entireHeight + lineHeight - 1)/lineHeight,
+ self.GetScrollPos(wx.HORIZONTAL),
+ self.GetScrollPos(wx.VERTICAL),
+ True)
+
+ else:
+
+ if count > 0:
+ entireHeight = self.GetLineY(count-1) + self.GetLineHeight(count-1) + LINE_SPACING
+ lineFrom, lineTo = self.GetVisibleLinesRange()
+ self._linesPerPage = lineTo - lineFrom + 1
+ else:
+ lineHeight = self.GetLineHeight()
+ entireHeight = count*lineHeight + LINE_SPACING
+ self._linesPerPage = clientHeight/lineHeight
+
+ decrement = 0
+ if entireHeight > self.GetClientSize()[1]:
+ decrement = SCROLL_UNIT_X
+
+ self.SetScrollbars(SCROLL_UNIT_X, SCROLL_UNIT_Y,
+ (self.GetHeaderWidth()-decrement)/SCROLL_UNIT_X,
+ (entireHeight + SCROLL_UNIT_Y - 1)/SCROLL_UNIT_Y,
+ self.GetScrollPos(wx.HORIZONTAL),
+ self.GetScrollPos(wx.VERTICAL),
+ True)
+
+ else: # !report
+
+ dc = wx.ClientDC(self)
+ dc.SetFont(self.GetFont())
+
+ lineHeight = self.GetLineHeight()
+
+ # we have 3 different layout strategies: either layout all items
+ # horizontally/vertically (ULC_ALIGN_XXX styles explicitly given) or
+ # to arrange them in top to bottom, left to right (don't ask me why
+ # not the other way round...) order
+ if self.HasAGWFlag(ULC_ALIGN_LEFT | ULC_ALIGN_TOP):
+
+ x = EXTRA_BORDER_X
+ y = EXTRA_BORDER_Y
+ widthMax = 0
+
+ for i in xrange(count):
+
+ line = self.GetLine(i)
+ line.CalculateSize(dc, iconSpacing)
+ line.SetPosition(x, y, iconSpacing)
+
+ sizeLine = self.GetLineSize(i)
+
+ if self.HasAGWFlag(ULC_ALIGN_TOP):
+
+ if sizeLine.x > widthMax:
+ widthMax = sizeLine.x
+
+ y += sizeLine.y
+
+ else: # ULC_ALIGN_LEFT
+
+ x += sizeLine.x + MARGIN_BETWEEN_ROWS
+
+ if self.HasAGWFlag(ULC_ALIGN_TOP):
+
+ # traverse the items again and tweak their sizes so that they are
+ # all the same in a row
+ for i in xrange(count):
+
+ line = self.GetLine(i)
+ line._gi.ExtendWidth(widthMax)
+
+ self.SetScrollbars(SCROLL_UNIT_X, lineHeight,
+ (x + SCROLL_UNIT_X)/SCROLL_UNIT_X,
+ (y + lineHeight)/lineHeight,
+ self.GetScrollPos(wx.HORIZONTAL),
+ self.GetScrollPos(wx.VERTICAL),
+ True)
+
+ else: # "flowed" arrangement, the most complicated case
+
+ # at first we try without any scrollbars, if the items don't fit into
+ # the window, we recalculate after subtracting the space taken by the
+ # scrollbar
+
+ entireWidth = 0
+
+ for tries in xrange(2):
+
+ entireWidth = 2*EXTRA_BORDER_X
+
+ if tries == 1:
+
+ # Now we have decided that the items do not fit into the
+ # client area, so we need a scrollbar
+ entireWidth += SCROLL_UNIT_X
+
+ x = EXTRA_BORDER_X
+ y = EXTRA_BORDER_Y
+ maxWidthInThisRow = 0
+
+ self._linesPerPage = 0
+ currentlyVisibleLines = 0
+
+ for i in xrange(count):
+
+ currentlyVisibleLines += 1
+ line = self.GetLine(i)
+ line.CalculateSize(dc, iconSpacing)
+ line.SetPosition(x, y, iconSpacing)
+
+ sizeLine = self.GetLineSize(i)
+
+ if maxWidthInThisRow < sizeLine.x:
+ maxWidthInThisRow = sizeLine.x
+
+ y += sizeLine.y
+ if currentlyVisibleLines > self._linesPerPage:
+ self._linesPerPage = currentlyVisibleLines
+
+ if y + sizeLine.y >= clientHeight:
+
+ currentlyVisibleLines = 0
+ y = EXTRA_BORDER_Y
+ maxWidthInThisRow += MARGIN_BETWEEN_ROWS
+ x += maxWidthInThisRow
+ entireWidth += maxWidthInThisRow
+ maxWidthInThisRow = 0
+
+ # We have reached the last item.
+ if i == count - 1:
+ entireWidth += maxWidthInThisRow
+
+ if tries == 0 and entireWidth + SCROLL_UNIT_X > clientWidth:
+ clientHeight -= wx.SystemSettings.GetMetric(wx.SYS_HSCROLL_Y)
+ self._linesPerPage = 0
+ break
+
+ if i == count - 1:
+ break # Everything fits, no second try required.
+
+ self.SetScrollbars(SCROLL_UNIT_X, lineHeight,
+ (entireWidth + SCROLL_UNIT_X)/SCROLL_UNIT_X,
+ 0,
+ self.GetScrollPos(wx.HORIZONTAL),
+ 0,
+ True)
+
+ self._dirty = False
+ if not noRefresh:
+ self.RefreshAll()
+
+
+ def RefreshAll(self):
+ """ Refreshes the entire :class:`UltimateListCtrl`. """
+
+ self._dirty = False
+ self.Refresh()
+
+ headerWin = self.GetListCtrl()._headerWin
+ if headerWin and headerWin._dirty:
+ headerWin._dirty = False
+ headerWin.Refresh()
+
+
+ def UpdateCurrent(self):
+ """ Updates the current line selection. """
+
+ if not self.HasCurrent() and not self.IsEmpty():
+ self.ChangeCurrent(0)
+
+
+ def GetNextItem(self, item, geometry=ULC_NEXT_ALL, state=ULC_STATE_DONTCARE):
+ """
+ Searches for an item with the given `geometry` or `state`, starting from `item`
+ but excluding the `item` itself.
+
+ :param `item`: the item at which starting the search. If set to -1, the first
+ item that matches the specified flags will be returned.
+ :param `geometry`: can be one of:
+
+ =================== ========= =================================
+ Geometry Flag Hex Value Description
+ =================== ========= =================================
+ ``ULC_NEXT_ABOVE`` 0x0 Searches for an item above the specified item
+ ``ULC_NEXT_ALL`` 0x1 Searches for subsequent item by index
+ ``ULC_NEXT_BELOW`` 0x2 Searches for an item below the specified item
+ ``ULC_NEXT_LEFT`` 0x3 Searches for an item to the left of the specified item
+ ``ULC_NEXT_RIGHT`` 0x4 Searches for an item to the right of the specified item
+ =================== ========= =================================
+
+ :param `state`: any combination of the following bits:
+
+ ============================ ========= ==============================
+ State Bits Hex Value Description
+ ============================ ========= ==============================
+ ``ULC_STATE_DONTCARE`` 0x0 Don't care what the state is
+ ``ULC_STATE_DROPHILITED`` 0x1 The item is highlighted to receive a drop event
+ ``ULC_STATE_FOCUSED`` 0x2 The item has the focus
+ ``ULC_STATE_SELECTED`` 0x4 The item is selected
+ ``ULC_STATE_CUT`` 0x8 The item is in the cut state
+ ``ULC_STATE_DISABLED`` 0x10 The item is disabled
+ ``ULC_STATE_FILTERED`` 0x20 The item has been filtered
+ ``ULC_STATE_INUSE`` 0x40 The item is in use
+ ``ULC_STATE_PICKED`` 0x80 The item has been picked
+ ``ULC_STATE_SOURCE`` 0x100 The item is a drag and drop source
+ ============================ ========= ==============================
+
+
+ :return: The first item with given `state` following `item` or -1 if no such item found.
+
+ :note: This function may be used to find all selected items in the
+ control like this::
+
+ item = -1
+
+ while 1:
+ item = listctrl.GetNextItem(item, ULC_NEXT_ALL, ULC_STATE_SELECTED)
+
+ if item == -1:
+ break
+
+ # This item is selected - do whatever is needed with it
+
+ wx.LogMessage("Item %ld is selected."%item)
+
+
+ """
+
+ ret = item
+ maxI = self.GetItemCount()
+
+ # notice that we start with the next item (or the first one if item == -1)
+ # and this is intentional to allow writing a simple loop to iterate over
+ # all selected items
+ ret += 1
+
+ if ret == maxI:
+ # this is not an error because the index was ok initially, just no
+ # such item
+ return -1
+
+ if not state:
+ # any will do
+ return ret
+
+ for line in xrange(ret, maxI):
+ if state & ULC_STATE_FOCUSED and line == self._current:
+ return line
+
+ if state & ULC_STATE_SELECTED and self.IsHighlighted(line):
+ return line
+
+ return -1
+
+
+# ----------------------------------------------------------------------------
+# deleting stuff
+# ----------------------------------------------------------------------------
+
+ def DeleteItem(self, lindex):
+ """
+ Deletes the specified item.
+
+ :param `lindex`: the index of the item to delete.
+
+ :note: This function sends the ``EVT_LIST_DELETE_ITEM`` event for the item
+ being deleted.
+ """
+
+ count = self.GetItemCount()
+ if lindex < 0 or lindex >= self.GetItemCount():
+ raise Exception("invalid item index in DeleteItem")
+
+ # we don't need to adjust the index for the previous items
+ if self.HasCurrent() and self._current >= lindex:
+
+ # if the current item is being deleted, we want the next one to
+ # become selected - unless there is no next one - so don't adjust
+ # self._current in this case
+ if self._current != lindex or self._current == count - 1:
+ self._current -= 1
+
+ if self.InReportView():
+
+ # mark the Column Max Width cache as dirty if the items in the line
+ # we're deleting contain the Max Column Width
+ line = self.GetLine(lindex)
+ item = UltimateListItem()
+
+ for i in xrange(len(self._columns)):
+ itemData = line._items[i]
+ item = itemData.GetItem(item)
+ itemWidth = self.GetItemWidthWithImage(item)
+
+ if itemWidth >= self._aColWidths[i]._nMaxWidth:
+ self._aColWidths[i]._bNeedsUpdate = True
+
+ if item.GetWindow():
+ self.DeleteItemWindow(item)
+
+ self.ResetVisibleLinesRange(True)
+ self._current = -1
+
+ self.SendNotify(lindex, wxEVT_COMMAND_LIST_DELETE_ITEM)
+
+ if self.IsVirtual():
+ self._countVirt -= 1
+ self._selStore.OnItemDelete(lindex)
+
+ else:
+ self._lines.pop(lindex)
+
+ # we need to refresh the (vert) scrollbar as the number of items changed
+ self._dirty = True
+ self._lineHeight = 0
+ self.ResetLineDimensions(True)
+ self.RecalculatePositions()
+ self.RefreshAfter(lindex)
+
+
+ def DeleteColumn(self, col):
+ """
+ Deletes the specified column.
+
+ :param `col`: the index of the column to delete.
+ """
+
+ self._columns.pop(col)
+ self._dirty = True
+
+ if not self.IsVirtual():
+ # update all the items
+ for i in xrange(len(self._lines)):
+ line = self.GetLine(i)
+ line._items.pop(col)
+
+ if self.InReportView(): # we only cache max widths when in Report View
+ self._aColWidths.pop(col)
+
+ # invalidate it as it has to be recalculated
+ self._headerWidth = 0
+
+
+ def DoDeleteAllItems(self):
+ """ Actually performs the deletion of all the items. """
+
+ if self.IsEmpty():
+ # nothing to do - in particular, don't send the event
+ return
+
+ self.ResetCurrent()
+
+ # to make the deletion of all items faster, we don't send the
+ # notifications for each item deletion in this case but only one event
+ # for all of them: this is compatible with wxMSW and documented in
+ # DeleteAllItems() description
+
+ event = UltimateListEvent(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, self.GetParent().GetId())
+ event.SetEventObject(self.GetParent())
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+
+ if self.IsVirtual():
+ self._countVirt = 0
+ self._selStore.Clear()
+
+ if self.InReportView():
+ self.ResetVisibleLinesRange(True)
+ for i in xrange(len(self._aColWidths)):
+ self._aColWidths[i]._bNeedsUpdate = True
+
+ for item in self._itemWithWindow[:]:
+ if item.GetWindow():
+ self.DeleteItemWindow(item)
+
+ self._lines = []
+ self._itemWithWindow = []
+ self._hasWindows = False
+
+
+ def DeleteAllItems(self):
+ """
+ Deletes all items in the :class:`UltimateListCtrl`.
+
+ :note: This function does not send the ``EVT_LIST_DELETE_ITEM`` event because
+ deleting many items from the control would be too slow then (unlike :meth:`~UltimateListMainWindow.DeleteItem`).
+ """
+
+ self.DoDeleteAllItems()
+ self.RecalculatePositions()
+
+
+ def DeleteEverything(self):
+ """ Deletes all items in the :class:`UltimateListCtrl`, resetting column widths to zero. """
+
+ self.DeleteAllItems()
+
+ count = len(self._columns)
+ for n in xrange(count):
+ self.DeleteColumn(0)
+
+ self.RecalculatePositions()
+ self.GetListCtrl().Refresh()
+
+
+# ----------------------------------------------------------------------------
+# scanning for an item
+# ----------------------------------------------------------------------------
+
+ def EnsureVisible(self, index):
+ """
+ Ensures this item is visible.
+
+ :param `index`: the index of the item to scroll into view.
+ """
+
+ if index < 0 or index >= self.GetItemCount():
+ raise Exception("invalid item index in EnsureVisible")
+
+ # We have to call this here because the label in question might just have
+ # been added and its position is not known yet
+ if self._dirty:
+ self.RecalculatePositions(True)
+
+ self.MoveToItem(index)
+
+
+ def FindItem(self, start, string, partial=False):
+ """
+ Find an item whose label matches this string.
+
+ :param `start`: the starting point of the input `string` or the beginning
+ if `start` is -1;
+ :param `string`: the string to look for matches;
+ :param `partial`: if ``True`` then this method will look for items which
+ begin with `string`.
+
+ :note: The string comparison is case insensitive.
+ """
+
+ if start < 0:
+ start = 0
+
+ str_upper = string.upper()
+ count = self.GetItemCount()
+
+ for i in xrange(start, count):
+ line = self.GetLine(i)
+ text = line.GetText(0)
+ line_upper = text.upper()
+ if not partial:
+ if line_upper == str_upper:
+ return i
+ else:
+ if line_upper.find(str_upper) == 0:
+ return i
+
+ return wx.NOT_FOUND
+
+
+ def FindItemData(self, start, data):
+ """
+ Find an item whose data matches this data.
+
+ :param `start`: the starting point of the input `data` or the beginning
+ if `start` is -1;
+ :param `data`: the data to look for matches.
+ """
+
+ if start < 0:
+ start = 0
+
+ count = self.GetItemCount()
+
+ for i in xrange(start, count):
+ line = self.GetLine(i)
+ item = UltimateListItem()
+ item = line.GetItem(0, item)
+
+ if item._data == data:
+ return i
+
+ return wx.NOT_FOUND
+
+
+ def FindItemAtPos(self, pt):
+ """
+ Find an item nearest this position.
+
+ :param `pt`: an instance of :class:`Point`.
+ """
+
+ topItem, dummy = self.GetVisibleLinesRange()
+ p = self.GetItemPosition(self.GetItemCount()-1)
+
+ if p.y == 0:
+ return topItem
+
+ id = int(math.floor(pt.y*float(self.GetItemCount()-topItem-1)/p.y+topItem))
+
+ if id >= 0 and id < self.GetItemCount():
+ return id
+
+ return wx.NOT_FOUND
+
+
+ def HitTest(self, x, y):
+ """
+ HitTest method for a :class:`UltimateListCtrl`.
+
+ :param `x`: the mouse `x` position;
+ :param `y`: the mouse `y` position.
+
+ :see: :meth:`~UltimateListMainWindow.HitTestLine` for a list of return flags.
+ """
+
+ x, y = self.CalcUnscrolledPosition(x, y)
+ count = self.GetItemCount()
+
+ if self.InReportView():
+ if not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ current = y/self.GetLineHeight()
+ if current < count:
+ newItem, flags = self.HitTestLine(current, x, y)
+ if flags:
+ return current, flags
+ else:
+ for current in xrange(self._lineFrom, count):
+ newItem, flags = self.HitTestLine(current, x, y)
+ if flags:
+ return current, flags
+
+ else:
+ # TODO: optimize it too! this is less simple than for report view but
+ # enumerating all items is still not a way to do it!!
+ for current in xrange(count):
+ newItem, flags = self.HitTestLine(current, x, y)
+ if flags:
+ return current, flags
+
+ return wx.NOT_FOUND, None
+
+
+# ----------------------------------------------------------------------------
+# adding stuff
+# ----------------------------------------------------------------------------
+
+ def InsertItem(self, item):
+ """
+ Inserts an item into :class:`UltimateListCtrl`.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ if self.IsVirtual():
+ raise Exception("can't be used with virtual control")
+
+ count = self.GetItemCount()
+ if item._itemId < 0:
+ raise Exception("invalid item index")
+
+ CheckVariableRowHeight(self, item._text)
+
+ if item._itemId > count:
+ item._itemId = count
+
+ id = item._itemId
+ self._dirty = True
+
+ if self.InReportView():
+ self.ResetVisibleLinesRange(True)
+
+ # calculate the width of the item and adjust the max column width
+ pWidthInfo = self._aColWidths[item.GetColumn()]
+ width = self.GetItemWidthWithImage(item)
+ item.SetWidth(width)
+
+ if width > pWidthInfo._nMaxWidth:
+ pWidthInfo._nMaxWidth = width
+
+ line = UltimateListLineData(self)
+ line.SetItem(item._col, item)
+
+ self._lines.insert(id, line)
+ self._dirty = True
+
+ # If an item is selected at or below the point of insertion, we need to
+ # increment the member variables because the current row's index has gone
+ # up by one
+ if self.HasCurrent() and self._current >= id:
+ self._current += 1
+
+ self.SendNotify(id, wxEVT_COMMAND_LIST_INSERT_ITEM)
+ self.RefreshLines(id, self.GetItemCount() - 1)
+
+
+ def InsertColumn(self, col, item):
+ """
+ Inserts a column into :class:`UltimateListCtrl`.
+
+ :param `col`: the column index at which we wish to insert a new column;
+ :param `item`: an instance of :class:`UltimateListItem`.
+
+ :return: the index at which the column has been inserted.
+
+ :note: This method is meaningful only if :class:`UltimateListCtrl` has the ``ULC_REPORT``
+ or the ``ULC_TILE`` styles set.
+ """
+
+ self._dirty = True
+
+ if self.InReportView() or self.InTileView() or self.HasAGWFlag(ULC_HEADER_IN_ALL_VIEWS):
+
+ if item._width == ULC_AUTOSIZE_USEHEADER:
+ item._width = self.GetTextLength(item._text)
+
+ column = UltimateListHeaderData(item)
+ colWidthInfo = ColWidthInfo()
+
+ insert = (col >= 0) and (col < len(self._columns))
+
+ if insert:
+ self._columns.insert(col, column)
+ self._aColWidths.insert(col, colWidthInfo)
+ idx = col
+
+ else:
+
+ self._columns.append(column)
+ self._aColWidths.append(colWidthInfo)
+ idx = len(self._columns)-1
+
+ if not self.IsVirtual():
+
+ # update all the items
+ for i in xrange(len(self._lines)):
+ line = self.GetLine(i)
+ data = UltimateListItemData(self)
+ if insert:
+ line._items.insert(col, data)
+ else:
+ line._items.append(data)
+
+ # invalidate it as it has to be recalculated
+ self._headerWidth = 0
+ return idx
+
+
+ def GetItemWidthWithImage(self, item):
+ """
+ Returns the item width, in pixels, considering the item text and its images.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ if item.GetCustomRenderer():
+ return item.GetCustomRenderer().GetSubItemWidth()
+
+ width = 0
+ dc = wx.ClientDC(self)
+
+ if item.GetFont().IsOk():
+ font = item.GetFont()
+ else:
+ font = self.GetFont()
+
+ dc.SetFont(font)
+
+ if item.GetKind() in [1, 2]:
+ ix, iy = self.GetCheckboxImageSize()
+ width += ix
+
+ if item.GetImage():
+ ix, iy = self.GetImageSize(item.GetImage())
+ width += ix + IMAGE_MARGIN_IN_REPORT_MODE
+
+ if item.GetText():
+ w, h, dummy = dc.GetMultiLineTextExtent(item.GetText())
+ width += w
+
+ if item.GetWindow():
+ width += item._windowsize.x + 5
+
+ return width
+
+
+ def GetItemTextSize(self, item):
+ """
+ Returns the item width, in pixels, considering only the item text.
+
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ width = ix = iy = start = end = 0
+ dc = wx.ClientDC(self)
+
+ if item.HasFont():
+ font = item.GetFont()
+ else:
+ font = self.GetFont()
+
+ dc.SetFont(font)
+
+ if item.GetKind() in [1, 2]:
+ ix, iy = self.GetCheckboxImageSize()
+ start += ix
+
+ if item.GetImage():
+ ix, iy = self.GetImageSize(item.GetImage())
+ start += ix + IMAGE_MARGIN_IN_REPORT_MODE
+
+ if item.GetText():
+ w, h, dummy = dc.GetMultiLineTextExtent(item.GetText())
+ end = w
+
+ return start, end
+
+
+# ----------------------------------------------------------------------------
+# sorting
+# ----------------------------------------------------------------------------
+
+ def OnCompareItems(self, line1, line2):
+ """
+ Returns whether 2 lines have the same index.
+
+ Override this function in the derived class to change the sort order of the items
+ in the :class:`UltimateListCtrl`. The function should return a negative, zero or positive
+ value if the first line is less than, equal to or greater than the second one.
+
+ :param `line1`: an instance of :class:`UltimateListItem`;
+ :param `line2`: another instance of :class:`UltimateListItem`.
+
+ :note: The base class version compares lines by their index.
+ """
+
+ item = UltimateListItem()
+ item1 = line1.GetItem(0, item)
+ item = UltimateListItem()
+ item2 = line2.GetItem(0, item)
+
+ data1 = item1._data
+ data2 = item2._data
+
+ if self.__func:
+ return self.__func(data1, data2)
+ else:
+ return cmp(data1, data2)
+
+
+ def SortItems(self, func):
+ """
+ Call this function to sort the items in the :class:`UltimateListCtrl`. Sorting is done
+ using the specified function `func`. This function must have the
+ following prototype::
+
+ def OnCompareItems(self, line1, line2):
+
+ DoSomething(line1, line2)
+ # function code
+
+
+ It is called each time when the two items must be compared and should return 0
+ if the items are equal, negative value if the first item is less than the second
+ one and positive value if the first one is greater than the second one.
+
+ :param `func`: the method to use to sort the items. The default is to use the
+ :meth:`~UltimateListMainWindow.OnCompareItems` method.
+ """
+
+ self.HighlightAll(False)
+ self.ResetCurrent()
+
+ if self._hasWindows:
+ self.HideWindows()
+
+ if not func:
+ self.__func = None
+ else:
+ self.__func = func
+
+ self._lines.sort(self.OnCompareItems)
+
+ if self.IsShownOnScreen():
+ self._dirty = True
+ self._lineHeight = 0
+ self.ResetLineDimensions(True)
+
+ self.RecalculatePositions(True)
+
+
+# ----------------------------------------------------------------------------
+# scrolling
+# ----------------------------------------------------------------------------
+
+ def OnScroll(self, event):
+ """
+ Handles the ``wx.EVT_SCROLLWIN`` event for :class:`UltimateListMainWindow`.
+
+ :param `event`: a :class:`ScrollEvent` event to be processed.
+ """
+
+ event.Skip()
+
+ # update our idea of which lines are shown when we redraw the window the
+ # next time
+ self.ResetVisibleLinesRange()
+
+ if self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ wx.CallAfter(self.RecalculatePositions, True)
+
+ if event.GetOrientation() == wx.HORIZONTAL:
+ lc = self.GetListCtrl()
+
+ if self.HasHeader():
+ lc._headerWin.Refresh()
+ lc._headerWin.Update()
+
+ if self.HasFooter():
+ lc._footerWin.Refresh()
+ lc._footerWin.Update()
+
+
+ def GetCountPerPage(self):
+ """
+ Returns the number of items that can fit vertically in the visible area
+ of the :class:`UltimateListCtrl` (list or report view) or the total number of
+ items in the list control (icon or small icon view).
+ """
+
+ if not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ if not self._linesPerPage:
+ self._linesPerPage = self.GetClientSize().y/self.GetLineHeight()
+
+ return self._linesPerPage
+
+ visibleFrom, visibleTo = self.GetVisibleLinesRange()
+ self._linesPerPage = visibleTo - visibleFrom + 1
+
+ return self._linesPerPage
+
+
+ def GetVisibleLinesRange(self):
+ """
+ Returns the range of visible items on screen.
+
+ :note: This method can be used only if :class:`UltimateListCtrl` has the ``ULC_REPORT``
+ style set.
+ """
+
+ if not self.InReportView():
+ raise Exception("this is for report mode only")
+
+ if self._lineFrom == -1:
+
+ count = self.GetItemCount()
+
+ if count:
+
+ if self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+
+ view_x, view_y = self.GetViewStart()
+ view_y *= SCROLL_UNIT_Y
+
+ for i in xrange(0, count):
+ rc = self.GetLineY(i)
+ if rc > view_y:
+ self._lineFrom = i - 1
+ break
+
+ if self._lineFrom < 0:
+ self._lineFrom = 0
+
+ self._lineTo = self._lineFrom
+ clientWidth, clientHeight = self.GetClientSize()
+
+ for i in xrange(self._lineFrom, count):
+ rc = self.GetLineY(i) + self.GetLineHeight(i)
+ if rc > view_y + clientHeight - 5:
+ break
+ self._lineTo += 1
+
+ else:
+
+ # No variable row height
+ self._lineFrom = self.GetScrollPos(wx.VERTICAL)
+
+ # this may happen if SetScrollbars() hadn't been called yet
+ if self._lineFrom >= count:
+ self._lineFrom = count - 1
+
+ self._lineTo = self._lineFrom + self._linesPerPage
+
+ # we redraw one extra line but this is needed to make the redrawing
+ # logic work when there is a fractional number of lines on screen
+ if self._lineTo >= count:
+ self._lineTo = count - 1
+
+ else: # empty control
+
+ self._lineFrom = -1
+ self._lineTo = -1
+
+ return self._lineFrom, self._lineTo
+
+
+ def ResetTextControl(self):
+ """ Called by :class:`UltimateListTextCtrl` when it marks itself for deletion."""
+
+ self._textctrl.Destroy()
+ self._textctrl = None
+
+ self.RecalculatePositions()
+ self.Refresh()
+
+
+ def SetFirstGradientColour(self, colour=None):
+ """
+ Sets the first gradient colour for gradient-style selections.
+
+ :param `colour`: if not ``None``, a valid :class:`Colour` instance. Otherwise,
+ the colour is taken from the system value ``wx.SYS_COLOUR_HIGHLIGHT``.
+ """
+
+ if colour is None:
+ colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+
+ self._firstcolour = colour
+ if self._usegradients:
+ self.RefreshSelected()
+
+
+ def SetSecondGradientColour(self, colour=None):
+ """
+ Sets the second gradient colour for gradient-style selections.
+
+ :param `colour`: if not ``None``, a valid :class:`Colour` instance. Otherwise,
+ the colour generated is a slightly darker version of the :class:`UltimateListCtrl`
+ background colour.
+ """
+
+ if colour is None:
+ # No colour given, generate a slightly darker from the
+ # UltimateListCtrl background colour
+ colour = self.GetBackgroundColour()
+ r, g, b = int(colour.Red()), int(colour.Green()), int(colour.Blue())
+ colour = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
+ colour = wx.Colour(colour[0], colour[1], colour[2])
+
+ self._secondcolour = colour
+
+ if self._usegradients:
+ self.RefreshSelected()
+
+
+ def GetFirstGradientColour(self):
+ """ Returns the first gradient colour for gradient-style selections. """
+
+ return self._firstcolour
+
+
+ def GetSecondGradientColour(self):
+ """ Returns the second gradient colour for gradient-style selections. """
+
+ return self._secondcolour
+
+
+ def EnableSelectionGradient(self, enable=True):
+ """
+ Globally enables/disables drawing of gradient selections.
+
+ :param `enable`: ``True`` to enable gradient-style selections, ``False``
+ to disable it.
+
+ :note: Calling this method disables any Vista-style selection previously
+ enabled.
+ """
+
+ self._usegradients = enable
+ self._vistaselection = False
+ self.RefreshSelected()
+
+
+ def SetGradientStyle(self, vertical=0):
+ """
+ Sets the gradient style for gradient-style selections.
+
+ :param `vertical`: 0 for horizontal gradient-style selections, 1 for vertical
+ gradient-style selections.
+ """
+
+ # 0 = Horizontal, 1 = Vertical
+ self._gradientstyle = vertical
+
+ if self._usegradients:
+ self.RefreshSelected()
+
+
+ def GetGradientStyle(self):
+ """
+ Returns the gradient style for gradient-style selections.
+
+ :return: 0 for horizontal gradient-style selections, 1 for vertical
+ gradient-style selections.
+ """
+
+ return self._gradientstyle
+
+
+ def EnableSelectionVista(self, enable=True):
+ """
+ Globally enables/disables drawing of Windows Vista selections.
+
+ :param `enable`: ``True`` to enable Vista-style selections, ``False`` to
+ disable it.
+
+ :note: Calling this method disables any gradient-style selection previously
+ enabled.
+ """
+
+ self._usegradients = False
+ self._vistaselection = enable
+ self.RefreshSelected()
+
+
+ def SetSelectedTextColour(self, colour=None):
+ """
+ Sets the colour of text applied to an item when it is selected.
+ If this method is not called, text color of selected items will be
+ the system value ``wx.SYS_COLOUR_HIGHLIGHTTEXT``, or the color set on
+ the item with SetTextColour.
+
+ :param `colour`: if not ``None``, a valid :class:`Colour` instance. Otherwise,
+ the colour is taken from the system value ``wx.SYS_COLOUR_HIGHLIGHTTEXT``.
+ """
+
+ if colour is None:
+ colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
+
+ self._highlightedtextcolour = colour
+ if self._usegradients:
+ self.RefreshSelected()
+
+
+ def GetSelectedTextColour(self):
+ """ Returns the colour applied to text when an item is selected. """
+
+ return self._highlightedtextcolour
+
+
+ def SetBackgroundImage(self, image):
+ """
+ Sets the :class:`UltimateListCtrl` background image.
+
+ :param `image`: if not ``None``, an instance of :class:`Bitmap`.
+
+ :note: At present, the background image can only be used in "tile" mode.
+
+ .. todo:: Support background images also in stretch and centered modes.
+ """
+
+ self._backgroundImage = image
+ self.Refresh()
+
+
+ def GetBackgroundImage(self):
+ """
+ Returns the :class:`UltimateListCtrl` background image (if any).
+
+ :note: At present, the background image can only be used in "tile" mode.
+
+ .. todo:: Support background images also in stretch and centered modes.
+ """
+
+ return self._backgroundImage
+
+
+ def SetWaterMark(self, watermark):
+ """
+ Sets the :class:`UltimateListCtrl` watermark image to be displayed in the bottom
+ right part of the window.
+
+ :param `watermark`: if not ``None``, an instance of :class:`Bitmap`.
+
+ .. todo:: Better support for this is needed.
+ """
+
+ self._waterMark = watermark
+ self.Refresh()
+
+
+ def GetWaterMark(self):
+ """
+ Returns the :class:`UltimateListCtrl` watermark image (if any), displayed in the
+ bottom right part of the window.
+
+ .. todo:: Better support for this is needed.
+ """
+
+ return self._waterMark
+
+
+ def SetDisabledTextColour(self, colour):
+ """
+ Sets the items disabled colour.
+
+ :param `colour`: an instance of :class:`Colour`.
+ """
+
+ # Disabled items colour
+ self._disabledColour = colour
+ self.Refresh()
+
+
+ def GetDisabledTextColour(self):
+ """ Returns the items disabled colour. """
+
+ return self._disabledColour
+
+
+ def ScrollList(self, dx, dy):
+ """
+ Scrolls the :class:`UltimateListCtrl`.
+
+ :param `dx`: if in icon, small icon or report view mode, specifies the number
+ of pixels to scroll. If in list view mode, `dx` specifies the number of
+ columns to scroll.
+ :param `dy`: always specifies the number of pixels to scroll vertically.
+ """
+
+ if not self.InReportView():
+ # TODO: this should work in all views but is not implemented now
+ return False
+
+ top, bottom = self.GetVisibleLinesRange()
+
+ if bottom == -1:
+ return 0
+
+ self.ResetVisibleLinesRange()
+
+ if not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ hLine = self.GetLineHeight()
+ self.Scroll(-1, top + dy/hLine)
+ else:
+ self.Scroll(-1, top + dy/SCROLL_UNIT_Y)
+
+ if wx.Platform == "__WXMAC__":
+ # see comment in MoveToItem() for why we do this
+ self.ResetVisibleLinesRange()
+
+ return True
+
+# -------------------------------------------------------------------------------------
+# UltimateListCtrl
+# -------------------------------------------------------------------------------------
+
+class UltimateListCtrl(wx.PyControl):
+ """
+ UltimateListCtrl is a class that mimics the behaviour of :class:`ListCtrl`, with almost
+ the same base functionalities plus some more enhancements. This class does
+ not rely on the native control, as it is a full owner-drawn list control.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, agwStyle=0, validator=wx.DefaultValidator, name="UltimateListCtrl"):
+ """
+ Default class constructor.
+
+ :param `parent`: parent window. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `style`: the underlying :class:`PyControl` window style;
+ :param `agwStyle`: the AGW-specific window style; can be almost any combination of the following
+ bits:
+
+ =============================== =========== ====================================================================================================
+ Window Styles Hex Value Description
+ =============================== =========== ====================================================================================================
+ ``ULC_VRULES`` 0x1 Draws light vertical rules between rows in report mode.
+ ``ULC_HRULES`` 0x2 Draws light horizontal rules between rows in report mode.
+ ``ULC_ICON`` 0x4 Large icon view, with optional labels.
+ ``ULC_SMALL_ICON`` 0x8 Small icon view, with optional labels.
+ ``ULC_LIST`` 0x10 Multicolumn list view, with optional small icons. Columns are computed automatically, i.e. you don't set columns as in ``ULC_REPORT``. In other words, the list wraps, unlike a :class:`ListBox`.
+ ``ULC_REPORT`` 0x20 Single or multicolumn report view, with optional header.
+ ``ULC_ALIGN_TOP`` 0x40 Icons align to the top. Win32 default, Win32 only.
+ ``ULC_ALIGN_LEFT`` 0x80 Icons align to the left.
+ ``ULC_AUTOARRANGE`` 0x100 Icons arrange themselves. Win32 only.
+ ``ULC_VIRTUAL`` 0x200 The application provides items text on demand. May only be used with ``ULC_REPORT``.
+ ``ULC_EDIT_LABELS`` 0x400 Labels are editable: the application will be notified when editing starts.
+ ``ULC_NO_HEADER`` 0x800 No header in report mode.
+ ``ULC_NO_SORT_HEADER`` 0x1000 No Docs.
+ ``ULC_SINGLE_SEL`` 0x2000 Single selection (default is multiple).
+ ``ULC_SORT_ASCENDING`` 0x4000 Sort in ascending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
+ ``ULC_SORT_DESCENDING`` 0x8000 Sort in descending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
+ ``ULC_TILE`` 0x10000 Each item appears as a full-sized icon with a label of one or more lines beside it (partially implemented).
+ ``ULC_NO_HIGHLIGHT`` 0x20000 No highlight when an item is selected.
+ ``ULC_STICKY_HIGHLIGHT`` 0x40000 Items are selected by simply hovering on them, with no need to click on them.
+ ``ULC_STICKY_NOSELEVENT`` 0x80000 Don't send a selection event when using ``ULC_STICKY_HIGHLIGHT`` style.
+ ``ULC_SEND_LEFTCLICK`` 0x100000 Send a left click event when an item is selected.
+ ``ULC_HAS_VARIABLE_ROW_HEIGHT`` 0x200000 The list has variable row heights.
+ ``ULC_AUTO_CHECK_CHILD`` 0x400000 When a column header has a checkbox associated, auto-check all the subitems in that column.
+ ``ULC_AUTO_TOGGLE_CHILD`` 0x800000 When a column header has a checkbox associated, toggle all the subitems in that column.
+ ``ULC_AUTO_CHECK_PARENT`` 0x1000000 Only meaningful foe checkbox-type items: when an item is checked/unchecked its column header item is checked/unchecked as well.
+ ``ULC_SHOW_TOOLTIPS`` 0x2000000 Show tooltips for ellipsized items/subitems (text too long to be shown in the available space) containing the full item/subitem text.
+ ``ULC_HOT_TRACKING`` 0x4000000 Enable hot tracking of items on mouse motion.
+ ``ULC_BORDER_SELECT`` 0x8000000 Changes border colour whan an item is selected, instead of highlighting the item.
+ ``ULC_TRACK_SELECT`` 0x10000000 Enables hot-track selection in a list control. Hot track selection means that an item is automatically selected when the cursor remains over the item for a certain period of time. The delay is retrieved on Windows using the `win32api` call `win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME)`, and is defaulted to 400ms on other platforms. This style applies to all views of `UltimateListCtrl`.
+ ``ULC_HEADER_IN_ALL_VIEWS`` 0x20000000 Show column headers in all view modes.
+ ``ULC_NO_FULL_ROW_SELECT`` 0x40000000 When an item is selected, the only the item in the first column is highlighted.
+ ``ULC_FOOTER`` 0x80000000 Show a footer too (only when header is present).
+ ``ULC_USER_ROW_HEIGHT`` 0x100000000 Allows to set a custom row height (one value for all the items, only in report mode).
+ =============================== =========== ====================================================================================================
+
+ :param `validator`: the window validator;
+ :param `name`: the window name.
+ """
+
+ self._imageListNormal = None
+ self._imageListSmall = None
+ self._imageListState = None
+
+ if not agwStyle & ULC_MASK_TYPE:
+ raise Exception("UltimateListCtrl style should have exactly one mode bit set")
+
+ if not (agwStyle & ULC_REPORT) and agwStyle & ULC_HAS_VARIABLE_ROW_HEIGHT:
+ raise Exception("Style ULC_HAS_VARIABLE_ROW_HEIGHT can only be used in report, non-virtual mode")
+
+ if agwStyle & ULC_STICKY_HIGHLIGHT and agwStyle & ULC_TRACK_SELECT:
+ raise Exception("Styles ULC_STICKY_HIGHLIGHT and ULC_TRACK_SELECT can not be combined")
+
+ if agwStyle & ULC_NO_HEADER and agwStyle & ULC_HEADER_IN_ALL_VIEWS:
+ raise Exception("Styles ULC_NO_HEADER and ULC_HEADER_IN_ALL_VIEWS can not be combined")
+
+ if agwStyle & ULC_USER_ROW_HEIGHT and (agwStyle & ULC_REPORT) == 0:
+ raise Exception("Style ULC_USER_ROW_HEIGHT can be used only with ULC_REPORT")
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style|wx.CLIP_CHILDREN, validator, name)
+
+ self._mainWin = None
+ self._headerWin = None
+ self._footerWin = None
+
+ self._headerHeight = wx.RendererNative.Get().GetHeaderButtonHeight(self)
+ self._footerHeight = self._headerHeight
+
+ if wx.Platform == "__WXGTK__":
+ style &= ~wx.BORDER_MASK
+ style |= wx.BORDER_THEME
+ else:
+ if style & wx.BORDER_THEME:
+ style -= wx.BORDER_THEME
+
+ self._agwStyle = agwStyle
+ if style & wx.SUNKEN_BORDER:
+ style -= wx.SUNKEN_BORDER
+
+ self._mainWin = UltimateListMainWindow(self, wx.ID_ANY, wx.Point(0, 0), wx.DefaultSize, style, agwStyle)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(self._mainWin, 1, wx.GROW)
+ self.SetSizer(sizer)
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+
+ self.CreateOrDestroyHeaderWindowAsNeeded()
+ self.CreateOrDestroyFooterWindowAsNeeded()
+
+ self.SetInitialSize(size)
+ wx.CallAfter(self.Layout)
+
+
+ def CreateOrDestroyHeaderWindowAsNeeded(self):
+ """ Creates or destroys the header window depending on the window style flags. """
+
+ needs_header = self.HasHeader()
+ has_header = self._headerWin is not None
+
+ if needs_header == has_header:
+ return
+
+ if needs_header:
+
+ self._headerWin = UltimateListHeaderWindow(self, wx.ID_ANY, self._mainWin,
+ wx.Point(0, 0),
+ wx.DefaultSize,
+ wx.TAB_TRAVERSAL, isFooter=False)
+
+ # ----------------------------------------------------
+ # How do you translate all this blah-blah to wxPython?
+ # ----------------------------------------------------
+ #if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
+ # wxFont font
+ #if wxOSX_USE_ATSU_TEXT
+ # font.MacCreateFromThemeFont( kThemeSmallSystemFont )
+ #else
+ # font.MacCreateFromUIFont( kCTFontSystemFontType )
+ #endif
+ # m_headerWin->SetFont( font )
+ #endif
+
+ self.GetSizer().Prepend(self._headerWin, 0, wx.GROW)
+
+ else:
+
+ self.GetSizer().Detach(self._headerWin)
+ self._headerWin.Destroy()
+ self._headerWin = None
+
+
+ def CreateOrDestroyFooterWindowAsNeeded(self):
+ """ Creates or destroys the footer window depending on the window style flags. """
+
+ needs_footer = self.HasFooter()
+ has_footer = self._footerWin is not None
+
+ if needs_footer == has_footer:
+ return
+
+ if needs_footer:
+
+ self._footerWin = UltimateListHeaderWindow(self, wx.ID_ANY, self._mainWin,
+ wx.Point(0, 0),
+ wx.DefaultSize,
+ wx.TAB_TRAVERSAL, isFooter=True)
+
+ # ----------------------------------------------------
+ # How do you translate all this blah-blah to wxPython?
+ # ----------------------------------------------------
+ #if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
+ # wxFont font
+ #if wxOSX_USE_ATSU_TEXT
+ # font.MacCreateFromThemeFont( kThemeSmallSystemFont )
+ #else
+ # font.MacCreateFromUIFont( kCTFontSystemFontType )
+ #endif
+ # m_headerWin->SetFont( font )
+ #endif
+
+ self.GetSizer().Add(self._footerWin, 0, wx.GROW)
+
+ else:
+
+ self.GetSizer().Detach(self._footerWin)
+ self._footerWin.Destroy()
+ self._footerWin = None
+
+
+ def HasHeader(self):
+ """ Returns ``True`` if :class:`UltimateListCtrl` has a header window. """
+
+ return self._mainWin.HasHeader()
+
+
+ def HasFooter(self):
+ """ Returns ``True`` if :class:`UltimateListCtrl` has a footer window. """
+
+ return self._mainWin.HasFooter()
+
+
+ def GetDefaultBorder(self):
+ """ Returns the default window border. """
+
+ return wx.BORDER_THEME
+
+
+ def SetSingleStyle(self, style, add=True):
+ """
+ Adds or removes a single window style.
+
+ :param `style`: can be one of the following bits:
+
+ =============================== =========== ====================================================================================================
+ Window Styles Hex Value Description
+ =============================== =========== ====================================================================================================
+ ``ULC_VRULES`` 0x1 Draws light vertical rules between rows in report mode.
+ ``ULC_HRULES`` 0x2 Draws light horizontal rules between rows in report mode.
+ ``ULC_ICON`` 0x4 Large icon view, with optional labels.
+ ``ULC_SMALL_ICON`` 0x8 Small icon view, with optional labels.
+ ``ULC_LIST`` 0x10 Multicolumn list view, with optional small icons. Columns are computed automatically, i.e. you don't set columns as in ``ULC_REPORT``. In other words, the list wraps, unlike a :class:`ListBox`.
+ ``ULC_REPORT`` 0x20 Single or multicolumn report view, with optional header.
+ ``ULC_ALIGN_TOP`` 0x40 Icons align to the top. Win32 default, Win32 only.
+ ``ULC_ALIGN_LEFT`` 0x80 Icons align to the left.
+ ``ULC_AUTOARRANGE`` 0x100 Icons arrange themselves. Win32 only.
+ ``ULC_VIRTUAL`` 0x200 The application provides items text on demand. May only be used with ``ULC_REPORT``.
+ ``ULC_EDIT_LABELS`` 0x400 Labels are editable: the application will be notified when editing starts.
+ ``ULC_NO_HEADER`` 0x800 No header in report mode.
+ ``ULC_NO_SORT_HEADER`` 0x1000 No Docs.
+ ``ULC_SINGLE_SEL`` 0x2000 Single selection (default is multiple).
+ ``ULC_SORT_ASCENDING`` 0x4000 Sort in ascending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
+ ``ULC_SORT_DESCENDING`` 0x8000 Sort in descending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
+ ``ULC_TILE`` 0x10000 Each item appears as a full-sized icon with a label of one or more lines beside it (partially implemented).
+ ``ULC_NO_HIGHLIGHT`` 0x20000 No highlight when an item is selected.
+ ``ULC_STICKY_HIGHLIGHT`` 0x40000 Items are selected by simply hovering on them, with no need to click on them.
+ ``ULC_STICKY_NOSELEVENT`` 0x80000 Don't send a selection event when using ``ULC_STICKY_HIGHLIGHT`` style.
+ ``ULC_SEND_LEFTCLICK`` 0x100000 Send a left click event when an item is selected.
+ ``ULC_HAS_VARIABLE_ROW_HEIGHT`` 0x200000 The list has variable row heights.
+ ``ULC_AUTO_CHECK_CHILD`` 0x400000 When a column header has a checkbox associated, auto-check all the subitems in that column.
+ ``ULC_AUTO_TOGGLE_CHILD`` 0x800000 When a column header has a checkbox associated, toggle all the subitems in that column.
+ ``ULC_AUTO_CHECK_PARENT`` 0x1000000 Only meaningful foe checkbox-type items: when an item is checked/unchecked its column header item is checked/unchecked as well.
+ ``ULC_SHOW_TOOLTIPS`` 0x2000000 Show tooltips for ellipsized items/subitems (text too long to be shown in the available space) containing the full item/subitem text.
+ ``ULC_HOT_TRACKING`` 0x4000000 Enable hot tracking of items on mouse motion.
+ ``ULC_BORDER_SELECT`` 0x8000000 Changes border colour whan an item is selected, instead of highlighting the item.
+ ``ULC_TRACK_SELECT`` 0x10000000 Enables hot-track selection in a list control. Hot track selection means that an item is automatically selected when the cursor remains over the item for a certain period of time. The delay is retrieved on Windows using the `win32api` call `win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME)`, and is defaulted to 400ms on other platforms. This style applies to all views of `UltimateListCtrl`.
+ ``ULC_HEADER_IN_ALL_VIEWS`` 0x20000000 Show column headers in all view modes.
+ ``ULC_NO_FULL_ROW_SELECT`` 0x40000000 When an item is selected, the only the item in the first column is highlighted.
+ ``ULC_FOOTER`` 0x80000000 Show a footer too (only when header is present).
+ =============================== =========== ====================================================================================================
+
+ :param `add`: ``True`` to add the window style, ``False`` to remove it.
+
+ :note: The style ``ULC_VIRTUAL`` can not be set/unset after construction.
+ """
+
+ if style & ULC_VIRTUAL:
+ raise Exception("ULC_VIRTUAL can't be [un]set")
+
+ flag = self.GetAGWWindowStyleFlag()
+
+ if add:
+
+ if style & ULC_MASK_TYPE:
+ flag &= ~(ULC_MASK_TYPE | ULC_VIRTUAL)
+ if style & ULC_MASK_ALIGN:
+ flag &= ~ULC_MASK_ALIGN
+ if style & ULC_MASK_SORT:
+ flag &= ~ULC_MASK_SORT
+
+ if add:
+ flag |= style
+ else:
+ flag &= ~style
+
+ # some styles can be set without recreating everything (as happens in
+ # SetAGWWindowStyleFlag() which calls ListMainWindow.DeleteEverything())
+ if not style & ~(ULC_HRULES | ULC_VRULES):
+ self.Refresh()
+ self.SetAGWWindowStyleFlag(self, flag)
+ else:
+ self.SetAGWWindowStyleFlag(flag)
+
+
+ def GetAGWWindowStyleFlag(self):
+ """
+ Returns the :class:`UltimateListCtrl` AGW-specific style flag.
+
+ :see: :meth:`~UltimateListCtrl.SetAGWWindowStyleFlag` for a list of possible style flags.
+ """
+
+ return self._agwStyle
+
+
+ def SetAGWWindowStyleFlag(self, style):
+ """
+ Sets the :class:`UltimateListCtrl` AGW-specific style flag.
+
+ :param `style`: the AGW-specific window style; can be almost any combination of the following
+ bits:
+
+ =============================== =========== ====================================================================================================
+ Window Styles Hex Value Description
+ =============================== =========== ====================================================================================================
+ ``ULC_VRULES`` 0x1 Draws light vertical rules between rows in report mode.
+ ``ULC_HRULES`` 0x2 Draws light horizontal rules between rows in report mode.
+ ``ULC_ICON`` 0x4 Large icon view, with optional labels.
+ ``ULC_SMALL_ICON`` 0x8 Small icon view, with optional labels.
+ ``ULC_LIST`` 0x10 Multicolumn list view, with optional small icons. Columns are computed automatically, i.e. you don't set columns as in ``ULC_REPORT``. In other words, the list wraps, unlike a :class:`ListBox`.
+ ``ULC_REPORT`` 0x20 Single or multicolumn report view, with optional header.
+ ``ULC_ALIGN_TOP`` 0x40 Icons align to the top. Win32 default, Win32 only.
+ ``ULC_ALIGN_LEFT`` 0x80 Icons align to the left.
+ ``ULC_AUTOARRANGE`` 0x100 Icons arrange themselves. Win32 only.
+ ``ULC_VIRTUAL`` 0x200 The application provides items text on demand. May only be used with ``ULC_REPORT``.
+ ``ULC_EDIT_LABELS`` 0x400 Labels are editable: the application will be notified when editing starts.
+ ``ULC_NO_HEADER`` 0x800 No header in report mode.
+ ``ULC_NO_SORT_HEADER`` 0x1000 No Docs.
+ ``ULC_SINGLE_SEL`` 0x2000 Single selection (default is multiple).
+ ``ULC_SORT_ASCENDING`` 0x4000 Sort in ascending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
+ ``ULC_SORT_DESCENDING`` 0x8000 Sort in descending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
+ ``ULC_TILE`` 0x10000 Each item appears as a full-sized icon with a label of one or more lines beside it (partially implemented).
+ ``ULC_NO_HIGHLIGHT`` 0x20000 No highlight when an item is selected.
+ ``ULC_STICKY_HIGHLIGHT`` 0x40000 Items are selected by simply hovering on them, with no need to click on them.
+ ``ULC_STICKY_NOSELEVENT`` 0x80000 Don't send a selection event when using ``ULC_STICKY_HIGHLIGHT`` style.
+ ``ULC_SEND_LEFTCLICK`` 0x100000 Send a left click event when an item is selected.
+ ``ULC_HAS_VARIABLE_ROW_HEIGHT`` 0x200000 The list has variable row heights.
+ ``ULC_AUTO_CHECK_CHILD`` 0x400000 When a column header has a checkbox associated, auto-check all the subitems in that column.
+ ``ULC_AUTO_TOGGLE_CHILD`` 0x800000 When a column header has a checkbox associated, toggle all the subitems in that column.
+ ``ULC_AUTO_CHECK_PARENT`` 0x1000000 Only meaningful foe checkbox-type items: when an item is checked/unchecked its column header item is checked/unchecked as well.
+ ``ULC_SHOW_TOOLTIPS`` 0x2000000 Show tooltips for ellipsized items/subitems (text too long to be shown in the available space) containing the full item/subitem text.
+ ``ULC_HOT_TRACKING`` 0x4000000 Enable hot tracking of items on mouse motion.
+ ``ULC_BORDER_SELECT`` 0x8000000 Changes border colour whan an item is selected, instead of highlighting the item.
+ ``ULC_TRACK_SELECT`` 0x10000000 Enables hot-track selection in a list control. Hot track selection means that an item is automatically selected when the cursor remains over the item for a certain period of time. The delay is retrieved on Windows using the `win32api` call `win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME)`, and is defaulted to 400ms on other platforms. This style applies to all views of `UltimateListCtrl`.
+ ``ULC_HEADER_IN_ALL_VIEWS`` 0x20000000 Show column headers in all view modes.
+ ``ULC_NO_FULL_ROW_SELECT`` 0x40000000 When an item is selected, the only the item in the first column is highlighted.
+ ``ULC_FOOTER`` 0x80000000 Show a footer too (only when header is present).
+ ``ULC_USER_ROW_HEIGHT`` 0x100000000 Allows to set a custom row height (one value for all the items, only in report mode).
+ =============================== =========== ====================================================================================================
+ """
+
+ if style & ULC_HAS_VARIABLE_ROW_HEIGHT and not self.HasAGWFlag(ULC_REPORT):
+ raise Exception("ULC_HAS_VARIABLE_ROW_HEIGHT style can be used only in report mode")
+
+ wasInReportView = self.HasAGWFlag(ULC_REPORT)
+ self._agwStyle = style
+
+ if self._mainWin:
+
+ inReportView = (style & ULC_REPORT) != 0
+
+ if inReportView != wasInReportView:
+ # we need to notify the main window about this change as it must
+ # update its data structures
+ self._mainWin.SetReportView(inReportView)
+
+ self.CreateOrDestroyHeaderWindowAsNeeded()
+ self.CreateOrDestroyFooterWindowAsNeeded()
+ self.GetSizer().Layout()
+
+ if style & ULC_HAS_VARIABLE_ROW_HEIGHT:
+ self._mainWin.ResetLineDimensions()
+ self._mainWin.ResetVisibleLinesRange()
+
+ self.Refresh()
+
+
+ def HasAGWFlag(self, flag):
+ """
+ Returns ``True`` if the window has the given flag bit set.
+
+ :param `flag`: the window style to check.
+
+ :see: :meth:`~UltimateListCtrl.SetAGWWindowStyleFlag` for a list of valid window styles.
+ """
+
+ return self._agwStyle & flag
+
+
+ def SetUserLineHeight(self, height):
+ """
+ Sets a custom value for the :class:`UltimateListCtrl` item height.
+
+ :param `height`: the custom height for all the items, in pixels.
+
+ :note: This method can be used only with ``ULC_REPORT`` and ``ULC_USER_ROW_HEIGHT`` styles set.
+ """
+
+ if self._mainWin:
+ self._mainWin.SetUserLineHeight(height)
+
+
+ def GetUserLineHeight(self):
+ """
+ Returns the custom value for the :class:`UltimateListCtrl` item height, if previously set with
+ :meth:`~UltimateListCtrl.SetUserLineHeight`.
+
+ :note: This method can be used only with ``ULC_REPORT`` and ``ULC_USER_ROW_HEIGHT`` styles set.
+ """
+
+ if self._mainWin:
+ return self._mainWin.GetUserLineHeight()
+
+
+ def GetColumn(self, col):
+ """
+ Returns information about this column.
+
+ :param `col`: an integer specifying the column index.
+ """
+
+ return self._mainWin.GetColumn(col)
+
+
+ def SetColumn(self, col, item):
+ """
+ Sets information about this column.
+
+ :param `col`: an integer specifying the column index;
+ :param `item`: an instance of :class:`UltimateListItem`.
+ """
+
+ self._mainWin.SetColumn(col, item)
+ return True
+
+
+ def GetColumnWidth(self, col):
+ """
+ Returns the column width for the input column.
+
+ :param `col`: an integer specifying the column index.
+ """
+
+ return self._mainWin.GetColumnWidth(col)
+
+
+ def SetColumnWidth(self, col, width):
+ """
+ Sets the column width.
+
+ :param `width`: can be a width in pixels or ``wx.LIST_AUTOSIZE`` (-1) or
+ ``wx.LIST_AUTOSIZE_USEHEADER`` (-2) or ``LIST_AUTOSIZE_FILL`` (-3).
+ ``wx.LIST_AUTOSIZE`` will resize the column to the length of its longest
+ item. ``wx.LIST_AUTOSIZE_USEHEADER`` will resize the column to the
+ length of the header (Win32) or 80 pixels (other platforms).
+ ``LIST_AUTOSIZE_FILL`` will resize the column fill the remaining width
+ of the window.
+
+ :note: In small or normal icon view, col must be -1, and the column width
+ is set for all columns.
+ """
+
+ self._mainWin.SetColumnWidth(col, width)
+ return True
+
+
+ def GetCountPerPage(self):
+ """
+ Returns the number of items that can fit vertically in the visible area
+ of the :class:`UltimateListCtrl` (list or report view) or the total number of
+ items in the list control (icon or small icon view).
+ """
+
+ return self._mainWin.GetCountPerPage() # different from Windows ?
+
+
+ def GetItem(self, itemOrId, col=0):
+ """
+ Returns the information about the input item.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or an integer specifying
+ the item index;
+ :param `col`: the column to which the item belongs to.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.GetItem(item, col)
+
+
+ def SetItem(self, info):
+ """
+ Sets the information about the input item.
+
+ :param `info`: an instance of :class:`UltimateListItem`.
+ """
+
+ self._mainWin.SetItem(info)
+ return True
+
+
+ def SetStringItem(self, index, col, label, imageIds=[], it_kind=0):
+ """
+ Sets a string or image at the given location.
+
+ :param `index`: the item index;
+ :param `col`: the column to which the item belongs to;
+ :param `label`: the item text;
+ :param `imageIds`: a Python list containing the image indexes for the
+ images associated to this item;
+ :param `it_kind`: the item kind. May be one of the following integers:
+
+ =============== ==========================
+ Item Kind Description
+ =============== ==========================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== ==========================
+
+ """
+
+ info = UltimateListItem()
+ info._text = label
+ info._mask = ULC_MASK_TEXT
+
+ if it_kind:
+ info._mask |= ULC_MASK_KIND
+ info._kind = it_kind
+
+ info._itemId = index
+ info._col = col
+
+ for ids in to_list(imageIds):
+ if ids > -1:
+ info._image.append(ids)
+
+ if info._image:
+ info._mask |= ULC_MASK_IMAGE
+
+ self._mainWin.SetItem(info)
+ return index
+
+
+ def GetItemState(self, item, stateMask):
+ """
+ Returns the item state flags for the input item.
+
+ :param `item`: the index of the item;
+ :param `stateMask`: the bitmask for the state flag.
+
+ :see: :meth:`~UltimateListCtrl.SetItemState` for a list of valid state flags.
+ """
+
+ return self._mainWin.GetItemState(item, stateMask)
+
+
+ def SetItemState(self, item, state, stateMask):
+ """
+ Sets the item state flags for the input item.
+
+ :param `item`: the index of the item; if defaulted to -1, the state flag
+ will be set for all the items;
+ :param `state`: any combination of the following bits:
+
+ ============================ ========= ==============================
+ State Bits Hex Value Description
+ ============================ ========= ==============================
+ ``ULC_STATE_DONTCARE`` 0x0 Don't care what the state is
+ ``ULC_STATE_DROPHILITED`` 0x1 The item is highlighted to receive a drop event
+ ``ULC_STATE_FOCUSED`` 0x2 The item has the focus
+ ``ULC_STATE_SELECTED`` 0x4 The item is selected
+ ``ULC_STATE_CUT`` 0x8 The item is in the cut state
+ ``ULC_STATE_DISABLED`` 0x10 The item is disabled
+ ``ULC_STATE_FILTERED`` 0x20 The item has been filtered
+ ``ULC_STATE_INUSE`` 0x40 The item is in use
+ ``ULC_STATE_PICKED`` 0x80 The item has been picked
+ ``ULC_STATE_SOURCE`` 0x100 The item is a drag and drop source
+ ============================ ========= ==============================
+
+ :param `stateMask`: the bitmask for the state flag.
+
+ """
+
+ self._mainWin.SetItemState(item, state, stateMask)
+ return True
+
+
+ def SetItemImage(self, item, image, selImage=-1):
+ """
+ Sets a Python list of image indexes associated with the item.
+
+ :param `item`: an integer specifying the item index;
+ :param `image`: a Python list of indexes into the image list associated
+ with the :class:`UltimateListCtrl`. In report view, this only sets the images
+ for the first column;
+ :param `selImage`: not used at present.
+ """
+
+ return self.SetItemColumnImage(item, 0, image)
+
+
+ def SetItemColumnImage(self, item, column, image):
+ """
+ Sets a Python list of image indexes associated with the item in the input
+ column.
+
+ :param `item`: an integer specifying the item index;
+ :param `column`: the column to which the item belongs to;
+ :param `image`: a Python list of indexes into the image list associated
+ with the :class:`UltimateListCtrl`.
+ """
+
+ info = UltimateListItem()
+ info._image = to_list(image)
+ info._mask = ULC_MASK_IMAGE
+ info._itemId = item
+ info._col = column
+ self._mainWin.SetItem(info)
+
+ return True
+
+
+ def GetItemText(self, item):
+ """
+ Returns the item text.
+
+ :param `item`: an instance of :class:`UltimateListItem` or an integer specifying
+ the item index.
+ """
+
+ return self._mainWin.GetItemText(item)
+
+
+ def SetItemText(self, item, text):
+ """
+ Sets the item text.
+
+ :param `item`: an instance of :class:`UltimateListItem` or an integer specifying
+ the item index;
+ :param `text`: the new item text.
+ """
+
+ self._mainWin.SetItemText(item, text)
+
+
+ def GetItemData(self, item):
+ """
+ Gets the application-defined data associated with this item.
+
+ :param `item`: an integer specifying the item index.
+ """
+
+ info = UltimateListItem()
+ info._mask = ULC_MASK_DATA
+ info._itemId = item
+ self._mainWin.GetItem(info)
+ return info._data
+
+
+ def SetItemData(self, item, data):
+ """
+ Sets the application-defined data associated with this item.
+
+ :param `item`: an integer specifying the item index;
+ :param `data`: the data to be associated with the input item.
+
+ :note: This function cannot be used to associate pointers with
+ the control items, use :meth:`~UltimateListCtrl.SetItemPyData` instead.
+ """
+
+ info = UltimateListItem()
+ info._mask = ULC_MASK_DATA
+ info._itemId = item
+ info._data = data
+ self._mainWin.SetItem(info)
+ return True
+
+
+ def GetItemPyData(self, item):
+ """
+ Returns the data for the item, which can be any Python object.
+
+ :param `item`: an integer specifying the item index.
+
+ :note: Please note that Python data is associated with the item and not
+ with subitems.
+ """
+
+ info = UltimateListItem()
+ info._mask = ULC_MASK_PYDATA
+ info._itemId = item
+ self._mainWin.GetItem(info)
+ return info._pyData
+
+
+ def SetItemPyData(self, item, pyData):
+ """
+ Sets the data for the item, which can be any Python object.
+
+ :param `item`: an integer specifying the item index;
+ :param `pyData`: any Python object.
+
+ :note: Please note that Python data is associated with the item and not
+ with subitems.
+ """
+
+ info = UltimateListItem()
+ info._mask = ULC_MASK_PYDATA
+ info._itemId = item
+ info._pyData = pyData
+ self._mainWin.SetItem(info)
+ return True
+
+
+ SetPyData = SetItemPyData
+ GetPyData = GetItemPyData
+
+
+ def GetViewRect(self):
+ """
+ Returns the rectangle taken by all items in the control. In other words,
+ if the controls client size were equal to the size of this rectangle, no
+ scrollbars would be needed and no free space would be left.
+
+ :note: This function only works in the icon and small icon views, not in
+ list or report views.
+ """
+
+ return self._mainWin.GetViewRect()
+
+
+ def GetItemRect(self, item, code=ULC_RECT_BOUNDS):
+ """
+ Returns the rectangle representing the item's size and position, in physical
+ coordinates.
+
+ :param `item`: the row in which the item lives;
+ :param `code`: one of ``ULC_RECT_BOUNDS``, ``ULC_RECT_ICON``, ``ULC_RECT_LABEL``.
+ """
+
+ return self.GetSubItemRect(item, ULC_GETSUBITEMRECT_WHOLEITEM, code)
+
+
+ def GetSubItemRect(self, item, subItem, code):
+ """
+ Returns the rectangle representing the size and position, in physical coordinates,
+ of the given subitem, i.e. the part of the row `item` in the column `subItem`.
+
+ :param `item`: the row in which the item lives;
+ :param `subItem`: the column in which the item lives. If set equal to the special
+ value ``ULC_GETSUBITEMRECT_WHOLEITEM`` the return value is the same as for
+ :meth:`~UltimateListCtrl.GetItemRect`;
+ :param `code`: one of ``ULC_RECT_BOUNDS``, ``ULC_RECT_ICON``, ``ULC_RECT_LABEL``.
+
+ :note: This method is only meaningful when the :class:`UltimateListCtrl` is in the
+ report mode.
+ """
+
+ rect = self._mainWin.GetSubItemRect(item, subItem)
+ if self._mainWin.HasHeader():
+ rect.y += self._headerHeight + 1
+
+ return rect
+
+
+ def GetItemPosition(self, item):
+ """
+ Returns the position of the item, in icon or small icon view.
+
+ :param `item`: the row in which the item lives.
+ """
+
+ return self._mainWin.GetItemPosition(item)
+
+
+ def SetItemPosition(self, item, pos):
+ """
+ Sets the position of the item, in icon or small icon view.
+
+ :param `item`: the row in which the item lives;
+ :param `pos`: the item position.
+
+ :note: This method is currently unimplemented and does nothing.
+ """
+
+ return False
+
+
+ def GetItemCount(self):
+ """ Returns the number of items in the :class:`UltimateListCtrl`. """
+
+ return self._mainWin.GetItemCount()
+
+
+ def GetColumnCount(self):
+ """ Returns the total number of columns in the :class:`UltimateListCtrl`. """
+
+ return self._mainWin.GetColumnCount()
+
+
+ def SetItemSpacing(self, spacing, isSmall=False):
+ """
+ Sets the spacing between item texts and icons.
+
+ :param `spacing`: the spacing between item texts and icons, in pixels;
+ :param `isSmall`: ``True`` if using a ``wx.IMAGE_LIST_SMALL`` image list,
+ ``False`` if using a ``wx.IMAGE_LIST_NORMAL`` image list.
+ """
+
+ self._mainWin.SetItemSpacing(spacing, isSmall)
+
+
+ def GetItemSpacing(self, isSmall=False):
+ """
+ Returns the spacing between item texts and icons, in pixels.
+
+ :param `isSmall`: ``True`` if using a ``wx.IMAGE_LIST_SMALL`` image list,
+ ``False`` if using a ``wx.IMAGE_LIST_NORMAL`` image list.
+ """
+
+ return self._mainWin.GetItemSpacing(isSmall)
+
+
+ def SetItemTextColour(self, item, col):
+ """
+ Sets the item text colour.
+
+ :param `item`: the index of the item;
+ :param `col`: a valid :class:`Colour` object.
+ """
+
+ info = UltimateListItem()
+ info._itemId = item
+ info = self._mainWin.GetItem(info)
+ info.SetTextColour(col)
+ self._mainWin.SetItem(info)
+
+
+ def GetItemTextColour(self, item):
+ """
+ Returns the item text colour.
+
+ :param `item`: the index of the item.
+ """
+
+ info = UltimateListItem()
+ info._itemId = item
+ info = self._mainWin.GetItem(info)
+
+ return info.GetTextColour()
+
+
+ def SetItemBackgroundColour(self, item, col):
+ """
+ Sets the item background colour.
+
+ :param `item`: the index of the item;
+ :param `col`: a valid :class:`Colour` object.
+ """
+
+ info = UltimateListItem()
+ info._itemId = item
+ info = self._mainWin.GetItem(info)
+ info.SetBackgroundColour(col)
+ self._mainWin.SetItem(info)
+
+
+ def GetItemBackgroundColour(self, item):
+ """
+ Returns the item background colour.
+
+ :param `item`: the index of the item.
+ """
+
+ info = UltimateListItem()
+ info._itemId = item
+ info = self._mainWin.GetItem(info)
+ return info.GetBackgroundColour()
+
+
+ def SetItemFont(self, item, f):
+ """
+ Sets the item font.
+
+ :param `item`: the index of the item;
+ :param `f`: a valid :class:`Font` object.
+ """
+
+ info = UltimateListItem()
+ info._itemId = item
+ info = self._mainWin.GetItem(info)
+ info.SetFont(f)
+ info.SetBackgroundColour(self.GetItemBackgroundColour(item))
+ self._mainWin.SetItem(info)
+
+
+ def GetItemFont(self, item):
+ """
+ Returns the item font.
+
+ :param `item`: the index of the item.
+ """
+
+ info = UltimateListItem()
+ info._itemId = item
+ info = self._mainWin.GetItem(info)
+ return info.GetFont()
+
+
+ def GetSelectedItemCount(self):
+ """ Returns the number of selected items in :class:`UltimateListCtrl`. """
+
+ return self._mainWin.GetSelectedItemCount()
+
+
+ def GetTextColour(self):
+ """ Returns the :class:`UltimateListCtrl` foreground colour. """
+
+ return self.GetForegroundColour()
+
+
+ def SetTextColour(self, col):
+ """
+ Sets the :class:`UltimateListCtrl` foreground colour.
+
+ :param `col`: a valid :class:`Colour` object.
+ """
+
+ self.SetForegroundColour(col)
+
+
+ def GetTopItem(self):
+ """ Gets the index of the topmost visible item when in list or report view. """
+
+ top, dummy = self._mainWin.GetVisibleLinesRange()
+ return top
+
+
+ def GetNextItem(self, item, geometry=ULC_NEXT_ALL, state=ULC_STATE_DONTCARE):
+ """
+ Searches for an item with the given `geometry` or `state`, starting from `item`
+ but excluding the `item` itself.
+
+ :param `item`: the item at which starting the search. If set to -1, the first
+ item that matches the specified flags will be returned.
+ :param `geometry`: can be one of:
+
+ =================== ========= =================================
+ Geometry Flag Hex Value Description
+ =================== ========= =================================
+ ``ULC_NEXT_ABOVE`` 0x0 Searches for an item above the specified item
+ ``ULC_NEXT_ALL`` 0x1 Searches for subsequent item by index
+ ``ULC_NEXT_BELOW`` 0x2 Searches for an item below the specified item
+ ``ULC_NEXT_LEFT`` 0x3 Searches for an item to the left of the specified item
+ ``ULC_NEXT_RIGHT`` 0x4 Searches for an item to the right of the specified item
+ =================== ========= =================================
+
+ :param `state`: any combination of the following bits:
+
+ ============================ ========= ==============================
+ State Bits Hex Value Description
+ ============================ ========= ==============================
+ ``ULC_STATE_DONTCARE`` 0x0 Don't care what the state is
+ ``ULC_STATE_DROPHILITED`` 0x1 The item is highlighted to receive a drop event
+ ``ULC_STATE_FOCUSED`` 0x2 The item has the focus
+ ``ULC_STATE_SELECTED`` 0x4 The item is selected
+ ``ULC_STATE_CUT`` 0x8 The item is in the cut state
+ ``ULC_STATE_DISABLED`` 0x10 The item is disabled
+ ``ULC_STATE_FILTERED`` 0x20 The item has been filtered
+ ``ULC_STATE_INUSE`` 0x40 The item is in use
+ ``ULC_STATE_PICKED`` 0x80 The item has been picked
+ ``ULC_STATE_SOURCE`` 0x100 The item is a drag and drop source
+ ============================ ========= ==============================
+
+
+ :return: The first item with given `state` following `item` or -1 if no such item found.
+
+ :note: This function may be used to find all selected items in the
+ control like this::
+
+ item = -1
+
+ while 1:
+ item = listctrl.GetNextItem(item, ULC_NEXT_ALL, ULC_STATE_SELECTED)
+
+ if item == -1:
+ break
+
+ # This item is selected - do whatever is needed with it
+
+ wx.LogMessage("Item %ld is selected."%item)
+
+
+ """
+
+ return self._mainWin.GetNextItem(item, geometry, state)
+
+
+ def GetImageList(self, which):
+ """
+ Returns the image list associated with the control.
+
+ :param `which`: one of ``wx.IMAGE_LIST_NORMAL``, ``wx.IMAGE_LIST_SMALL``,
+ ``wx.IMAGE_LIST_STATE`` (the last is unimplemented).
+
+ :note:
+
+ As :class:`UltimateListCtrl` allows you to use a standard :class:`ImageList` or
+ :class:`PyImageList`, the returned object depends on which kind of image list you
+ chose.
+ """
+
+ if which == wx.IMAGE_LIST_NORMAL:
+ return self._imageListNormal
+
+ elif which == wx.IMAGE_LIST_SMALL:
+ return self._imageListSmall
+
+ elif which == wx.IMAGE_LIST_STATE:
+ return self._imageListState
+
+ return None
+
+
+ def SetImageList(self, imageList, which):
+ """
+ Sets the image list associated with the control.
+
+ :param `imageList`: an instance of :class:`ImageList` or an instance of :class:`PyImageList`;
+ :param `which`: one of ``wx.IMAGE_LIST_NORMAL``, ``wx.IMAGE_LIST_SMALL``,
+ ``wx.IMAGE_LIST_STATE`` (the last is unimplemented).
+
+ :note: Using :class:`PyImageList` enables you to have images of different size inside the
+ image list. In your derived class, instead of doing this::
+
+ imageList = wx.ImageList(16, 16)
+ imageList.Add(someBitmap)
+ self.SetImageList(imageList, wx.IMAGE_LIST_SMALL)
+
+ You should do this::
+
+ imageList = PyImageList(16, 16)
+ imageList.Add(someBitmap)
+ self.SetImageList(imageList, wx.IMAGE_LIST_SMALL)
+
+ """
+
+ if which == wx.IMAGE_LIST_NORMAL:
+ self._imageListNormal = imageList
+
+ elif which == wx.IMAGE_LIST_SMALL:
+ self._imageListSmall = imageList
+
+ elif which == wx.IMAGE_LIST_STATE:
+ self._imageListState = imageList
+
+ self._mainWin.SetImageList(imageList, which)
+
+
+ def AssignImageList(self, imageList, which):
+ """
+ Assigns the image list associated with the control.
+
+ :param `imageList`: an instance of :class:`ImageList` or an instance of :class:`PyImageList`;
+ :param `which`: one of ``wx.IMAGE_LIST_NORMAL``, ``wx.IMAGE_LIST_SMALL``,
+ ``wx.IMAGE_LIST_STATE`` (the last is unimplemented).
+
+ :note: Using :class:`PyImageList` enables you to have images of different size inside the
+ image list. In your derived class, instead of doing this::
+
+ imageList = wx.ImageList(16, 16)
+ imageList.Add(someBitmap)
+ self.SetImageList(imageList, wx.IMAGE_LIST_SMALL)
+
+ You should do this::
+
+ imageList = PyImageList(16, 16)
+ imageList.Add(someBitmap)
+ self.SetImageList(imageList, wx.IMAGE_LIST_SMALL)
+
+ """
+
+ self.SetImageList(imageList, which)
+
+
+ def Arrange(self, flag):
+ """
+ Arranges the items in icon or small icon view.
+
+ :param `flag`: one of the following bits:
+
+ ========================== ========= ===============================
+ Alignment Flag Hex Value Description
+ ========================== ========= ===============================
+ ``ULC_ALIGN_DEFAULT`` 0x0 Default alignment
+ ``ULC_ALIGN_SNAP_TO_GRID`` 0x3 Snap to grid
+ ========================== ========= ===============================
+
+ :note: This method is currently unimplemented and does nothing.
+ """
+
+
+ return 0
+
+
+ def DeleteItem(self, item):
+ """
+ Deletes the specified item.
+
+ :param `item`: the index of the item to delete.
+
+ :note: This function sends the ``EVT_LIST_DELETE_ITEM`` event for the item
+ being deleted.
+ """
+
+ self._mainWin.DeleteItem(item)
+ return True
+
+
+ def DeleteAllItems(self):
+ """
+ Deletes all items in the :class:`UltimateListCtrl`.
+
+ :note: This function does not send the ``EVT_LIST_DELETE_ITEM`` event because
+ deleting many items from the control would be too slow then (unlike :meth:`~UltimateListCtrl.DeleteItem`).
+ """
+
+ self._mainWin.DeleteAllItems()
+ return True
+
+
+ def DeleteAllColumns(self):
+ """ Deletes all the column in :class:`UltimateListCtrl`. """
+
+ count = len(self._mainWin._columns)
+ for n in xrange(count):
+ self.DeleteColumn(0)
+
+ return True
+
+
+ def ClearAll(self):
+ """ Deletes everything in :class:`UltimateListCtrl`. """
+
+ self._mainWin.DeleteEverything()
+
+
+ def DeleteColumn(self, col):
+ """
+ Deletes the specified column.
+
+ :param `col`: the index of the column to delete.
+ """
+
+ self._mainWin.DeleteColumn(col)
+ return True
+
+
+ def EditLabel(self, item):
+ """
+ Starts editing an item label.
+
+ :param `item`: the index of the item to edit.
+ """
+
+ self._mainWin.EditLabel(item)
+
+
+ def EnsureVisible(self, item):
+ """
+ Ensures this item is visible.
+
+ :param `index`: the index of the item to scroll into view.
+ """
+
+ self._mainWin.EnsureVisible(item)
+ return True
+
+
+ def FindItem(self, start, str, partial=False):
+ """
+ Find an item whose label matches this string.
+
+ :param `start`: the starting point of the input `string` or the beginning
+ if `start` is -1;
+ :param `string`: the string to look for matches;
+ :param `partial`: if ``True`` then this method will look for items which
+ begin with `string`.
+
+ :note: The string comparison is case insensitive.
+ """
+
+ return self._mainWin.FindItem(start, str, partial)
+
+
+ def FindItemData(self, start, data):
+ """
+ Find an item whose data matches this data.
+
+ :param `start`: the starting point of the input `data` or the beginning
+ if `start` is -1;
+ :param `data`: the data to look for matches.
+ """
+
+ return self._mainWin.FindItemData(start, data)
+
+
+ def FindItemAtPos(self, start, pt):
+ """
+ Find an item nearest this position.
+
+ :param `pt`: an instance of :class:`Point`.
+ """
+
+ return self._mainWin.FindItemAtPos(pt)
+
+
+ def HitTest(self, pointOrTuple):
+ """
+ HitTest method for a :class:`UltimateListCtrl`.
+
+ :param `pointOrTuple`: an instance of :class:`Point` or a tuple representing
+ the mouse `x`, `y` position.
+
+ :see: :meth:`UltimateListMainWindow.HitTestLine() <UltimateListMainWindow.HitTestLine>` for a list of return flags.
+ """
+
+ if isinstance(pointOrTuple, wx.Point):
+ x, y = pointOrTuple.x, pointOrTuple.y
+ else:
+ x, y = pointOrTuple
+
+ return self._mainWin.HitTest(x, y)
+
+
+ def InsertItem(self, info):
+ """
+ Inserts an item into :class:`UltimateListCtrl`.
+
+ :param `info`: an instance of :class:`UltimateListItem`.
+ """
+
+ self._mainWin.InsertItem(info)
+ return info._itemId
+
+
+ def InsertStringItem(self, index, label, it_kind=0):
+ """
+ Inserts a string item at the given location.
+
+ :param `index`: the index at which we wish to insert the item;
+ :param `label`: the item text;
+ :param `it_kind`: the item kind.
+
+ :see: :meth:`~UltimateListCtrl.SetStringItem` for a list of valid item kinds.
+ """
+
+ info = UltimateListItem()
+ info._text = label
+ info._mask = ULC_MASK_TEXT
+
+ if it_kind:
+ info._mask |= ULC_MASK_KIND
+ info._kind = it_kind
+
+ info._itemId = index
+ return self.InsertItem(info)
+
+
+ def InsertImageItem(self, index, imageIds, it_kind=0):
+ """
+ Inserts an image item at the given location.
+
+ :param `index`: the index at which we wish to insert the item;
+ :param `imageIds`: a Python list containing the image indexes for the
+ images associated to this item;
+ :param `it_kind`: the item kind.
+
+ :see: :meth:`~UltimateListCtrl.SetStringItem` for a list of valid item kinds.
+ """
+
+ info = UltimateListItem()
+ info._mask = ULC_MASK_IMAGE
+
+ if it_kind:
+ info._mask |= ULC_MASK_KIND
+ info._kind = it_kind
+
+ info._image = to_list(imageIds)
+ info._itemId = index
+
+ return self.InsertItem(info)
+
+
+ def InsertImageStringItem(self, index, label, imageIds, it_kind=0):
+ """
+ Inserts an image+string item at the given location.
+
+ :param `index`: the index at which we wish to insert the item;
+ :param `label`: the item text;
+ :param `imageIds`: a Python list containing the image indexes for the
+ images associated to this item;
+ :param `it_kind`: the item kind.
+
+ :see: :meth:`~UltimateListCtrl.SetStringItem` for a list of valid item kinds.
+ """
+
+ info = UltimateListItem()
+ info._text = label
+ info._image = to_list(imageIds)
+ info._mask = ULC_MASK_TEXT | ULC_MASK_IMAGE
+
+ if it_kind:
+ info._mask |= ULC_MASK_KIND
+ info._kind = it_kind
+
+ info._itemId = index
+ return self.InsertItem(info)
+
+
+ def InsertColumnInfo(self, col, item):
+ """
+ Inserts a column into :class:`UltimateListCtrl`.
+
+ :param `col`: the column index at which we wish to insert a column;
+ :param `item`: an instance of :class:`UltimateListItem`.
+
+ :return: the index at which the column has been inserted.
+ """
+
+ if not self._mainWin.InReportView() and not self.HasAGWFlag(ULC_HEADER_IN_ALL_VIEWS) and \
+ not self._mainWin.InTileView():
+ raise Exception("Can't add column in non report/tile modes or without the ULC_HEADER_IN_ALL_VIEWS style set")
+
+ idx = self._mainWin.InsertColumn(col, item)
+ if self._headerWin:
+ self._headerWin.Refresh()
+
+ return idx
+
+
+ def InsertColumn(self, col, heading, format=ULC_FORMAT_LEFT, width=-1):
+ """
+ Inserts a column into :class:`UltimateListCtrl`.
+
+ :param `col`: the column index at which we wish to insert a column;
+ :param `heading`: the header text;
+ :param `format`: the column alignment flag. This can be one of the following
+ bits:
+
+ ============================ ========= ==============================
+ Alignment Bits Hex Value Description
+ ============================ ========= ==============================
+ ``ULC_FORMAT_LEFT`` 0x0 The item is left-aligned
+ ``ULC_FORMAT_RIGHT`` 0x1 The item is right-aligned
+ ``ULC_FORMAT_CENTRE`` 0x2 The item is centre-aligned
+ ``ULC_FORMAT_CENTER`` 0x2 The item is center-aligned
+ ============================ ========= ==============================
+
+ :param `width`: can be a width in pixels or ``wx.LIST_AUTOSIZE`` (-1) or
+ ``wx.LIST_AUTOSIZE_USEHEADER`` (-2) or ``LIST_AUTOSIZE_FILL`` (-3).
+ ``wx.LIST_AUTOSIZE`` will resize the column to the length of its longest
+ item. ``wx.LIST_AUTOSIZE_USEHEADER`` will resize the column to the
+ length of the header (Win32) or 80 pixels (other platforms).
+ ``LIST_AUTOSIZE_FILL`` will resize the column fill the remaining width
+ of the window.
+
+ :return: the index at which the column has been inserted.
+ """
+
+ item = UltimateListItem()
+ item._mask = ULC_MASK_TEXT | ULC_MASK_FORMAT | ULC_MASK_FONT
+ item._text = heading
+
+ if width >= -2:
+ item._mask |= ULC_MASK_WIDTH
+ item._width = width
+
+ item._format = format
+
+ return self.InsertColumnInfo(col, item)
+
+
+ def IsColumnShown(self, column):
+ """
+ Returns ``True`` if the input column is shown, ``False`` if it is hidden.
+
+ :param `column`: an integer specifying the column index.
+ """
+
+ if self._headerWin:
+ return self._mainWin.IsColumnShown(column)
+
+ raise Exception("Showing/hiding columns works only with the header shown")
+
+
+ def SetColumnShown(self, column, shown=True):
+ """
+ Sets the specified column as shown or hidden.
+
+ :param `column`: an integer specifying the column index;
+ :param `shown`: ``True`` to show the column, ``False`` to hide it.
+ """
+
+ col = self.GetColumn(column)
+ col._mask |= ULC_MASK_SHOWN
+ col.SetShown(shown)
+ self._mainWin.SetColumn(column, col)
+ self.Update()
+
+
+ def ScrollList(self, dx, dy):
+ """
+ Scrolls the :class:`UltimateListCtrl`.
+
+ :param `dx`: if in icon, small icon or report view mode, specifies the number
+ of pixels to scroll. If in list view mode, `dx` specifies the number of
+ columns to scroll.
+ :param `dy`: always specifies the number of pixels to scroll vertically.
+ """
+
+ return self._mainWin.ScrollList(dx, dy)
+
+
+# Sort items.
+# The return value is a negative number if the first item should precede the second
+# item, a positive number of the second item should precede the first,
+# or zero if the two items are equivalent.
+
+ def SortItems(self, func=None):
+ """
+ Call this function to sort the items in the :class:`UltimateListCtrl`. Sorting is done
+ using the specified function `func`. This function must have the
+ following prototype::
+
+ def OnCompareItems(self, line1, line2):
+
+ DoSomething(line1, line2)
+ # function code
+
+
+ It is called each time when the two items must be compared and should return 0
+ if the items are equal, negative value if the first item is less than the second
+ one and positive value if the first one is greater than the second one.
+
+ :param `func`: the method to use to sort the items. The default is to use the
+ :meth:`UltimateListMainWindow.OnCompareItems() <UltimateListMainWindow.OnCompareItems>` method.
+ """
+
+ self._mainWin.SortItems(func)
+ wx.CallAfter(self.Refresh)
+
+ return True
+
+
+# ----------------------------------------------------------------------------
+# event handlers
+# ----------------------------------------------------------------------------
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`UltimateListCtrl`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ if not self.IsShownOnScreen():
+ # We don't have the proper column sizes until we are visible so
+ # use CallAfter to resize the columns on the first display
+ if self._mainWin:
+ wx.CallAfter(self._mainWin.ResizeColumns)
+
+ if not self._mainWin:
+ return
+
+ # We need to override OnSize so that our scrolled
+ # window a) does call Layout() to use sizers for
+ # positioning the controls but b) does not query
+ # the sizer for their size and use that for setting
+ # the scrollable area as set that ourselves by
+ # calling SetScrollbar() further down.
+
+ self.DoLayout()
+
+
+ def OnSetFocus(self, event):
+ """
+ Handles the ``wx.EVT_SET_FOCUS`` event for :class:`UltimateListCtrl`.
+
+ :param `event`: a :class:`FocusEvent` event to be processed.
+ """
+
+ if self._mainWin:
+ self._mainWin.SetFocusIgnoringChildren()
+ self._mainWin.Update()
+ event.Skip()
+
+
+ def OnInternalIdle(self):
+ """
+ This method is normally only used internally, but sometimes an application
+ may need it to implement functionality that should not be disabled by an
+ application defining an `OnIdle` handler in a derived class.
+
+ This method may be used to do delayed painting, for example, and most
+ implementations call :meth:`Window.UpdateWindowUI` in order to send update events
+ to the window in idle time.
+ """
+
+ wx.PyControl.OnInternalIdle(self)
+
+ # do it only if needed
+ if self._mainWin and self._mainWin._dirty:
+ self._mainWin._shortItems = []
+ self._mainWin.RecalculatePositions()
+
+
+# ----------------------------------------------------------------------------
+# font/colours
+# ----------------------------------------------------------------------------
+
+ def SetBackgroundColour(self, colour):
+ """
+ Changes the background colour of :class:`UltimateListCtrl`.
+
+ :param `colour`: the colour to be used as the background colour, pass
+ :class:`NullColour` to reset to the default colour.
+
+ :note: The background colour is usually painted by the default :class:`EraseEvent`
+ event handler function under Windows and automatically under GTK.
+
+ :note: Setting the background colour does not cause an immediate refresh, so
+ you may wish to call :meth:`Window.ClearBackground` or :meth:`Window.Refresh` after
+ calling this function.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ if self._mainWin:
+ self._mainWin.SetBackgroundColour(colour)
+ self._mainWin._dirty = True
+
+ return True
+
+
+ def SetForegroundColour(self, colour):
+ """
+ Changes the foreground colour of :class:`UltimateListCtrl`.
+
+ :param `colour`: the colour to be used as the foreground colour, pass
+ :class:`NullColour` to reset to the default colour.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ if not wx.PyControl.SetForegroundColour(self, colour):
+ return False
+
+ if self._mainWin:
+ self._mainWin.SetForegroundColour(colour)
+ self._mainWin._dirty = True
+
+ if self._headerWin:
+ self._headerWin.SetForegroundColour(colour)
+
+ return True
+
+
+ def SetFont(self, font):
+ """
+ Sets the :class:`UltimateListCtrl` font.
+
+ :param `font`: a valid :class:`Font` instance.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ if not wx.PyControl.SetFont(self, font):
+ return False
+
+ if self._mainWin:
+ self._mainWin.SetFont(font)
+ self._mainWin._dirty = True
+
+ if self._headerWin:
+ self._headerWin.SetFont(font)
+
+ self.Refresh()
+
+ return True
+
+
+ def GetClassDefaultAttributes(self, variant):
+ """
+ Returns the default font and colours which are used by the control. This is
+ useful if you want to use the same font or colour in your own control as in
+ a standard control -- which is a much better idea than hard coding specific
+ colours or fonts which might look completely out of place on the users system,
+ especially if it uses themes.
+
+ This static method is "overridden'' in many derived classes and so calling,
+ for example, :meth:`Button.GetClassDefaultAttributes` () will typically return the
+ values appropriate for a button which will be normally different from those
+ returned by, say, :meth:`ListCtrl.GetClassDefaultAttributes` ().
+
+ :note: The :class:`VisualAttributes` structure has at least the fields `font`,
+ `colFg` and `colBg`. All of them may be invalid if it was not possible to
+ determine the default control appearance or, especially for the background
+ colour, if the field doesn't make sense as is the case for `colBg` for the
+ controls with themed background.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ attr = wx.VisualAttributes()
+ attr.colFg = wx.SystemSettings.GetColour(wx.SYS_COLOUR_LISTBOXTEXT)
+ attr.colBg = wx.SystemSettings.GetColour(wx.SYS_COLOUR_LISTBOX)
+ attr.font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ return attr
+
+
+ def GetScrolledWin(self):
+ """ Returns the header window owner. """
+
+ return self._headerWin.GetOwner()
+
+
+# ----------------------------------------------------------------------------
+# methods forwarded to self._mainWin
+# ----------------------------------------------------------------------------
+
+ def SetDropTarget(self, dropTarget):
+ """
+ Associates a drop target with this window.
+ If the window already has a drop target, it is deleted.
+
+ :param `dropTarget`: an instance of :class:`DropTarget`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ self._mainWin.SetDropTarget(dropTarget)
+
+
+ def GetDropTarget(self):
+ """
+ Returns the associated drop target, which may be ``None``.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._mainWin.GetDropTarget()
+
+
+ def SetCursor(self, cursor):
+ """
+ Sets the window's cursor.
+
+ :param `cursor`: specifies the cursor that the window should normally display.
+ The `cursor` may be :class:`NullCursor` in which case the window cursor will be
+ reset back to default.
+
+ :note: The window cursor also sets it for the children of the window implicitly.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return (self._mainWin and [self._mainWin.SetCursor(cursor)] or [False])[0]
+
+
+ def GetBackgroundColour(self):
+ """
+ Returns the background colour of the window.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return (self._mainWin and [self._mainWin.GetBackgroundColour()] or [wx.NullColour])[0]
+
+
+ def GetForegroundColour(self):
+ """
+ Returns the foreground colour of the window.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return (self._mainWin and [self._mainWin.GetForegroundColour()] or [wx.NullColour])[0]
+
+
+ def PopupMenu(self, menu, pos=wx.DefaultPosition):
+ """
+ Pops up the given `menu` at the specified coordinates, relative to this window,
+ and returns control when the user has dismissed the menu. If a menu item is
+ selected, the corresponding menu event is generated and will be processed as
+ usual. If the coordinates are not specified, the current mouse cursor position
+ is used.
+
+ :param `menu`: an instance of :class:`Menu` to pop up;
+ :param `pos`: the position where the menu will appear.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._mainWin.PopupMenu(menu, pos)
+
+
+ def ClientToScreen(self, pointOrTuple):
+ """
+ Converts to screen coordinates from coordinates relative to this window.
+
+ :param `pointOrTuple`: an instance of :class:`Point` or a tuple representing the
+ `x`, `y` coordinates for this point.
+
+ :return: the coordinates relative to the screen.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._mainWin.ClientToScreen(*pointOrTuple)
+
+
+ def ClientToScreenXY(self, x, y):
+ """
+ Converts to screen coordinates from coordinates relative to this window.
+
+ :param `x`: an integer specifying the `x` client coordinate;
+ :param `y`: an integer specifying the `y` client coordinate.
+
+ :return: the coordinates relative to the screen.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._mainWin.ClientToScreen(x, y)
+
+
+ def ScreenToClient(self, pointOrTuple):
+ """
+ Converts from screen to client window coordinates.
+
+ :param `pointOrTuple`: an instance of :class:`Point` or a tuple representing the
+ `x`, `y` coordinates for this point.
+
+ :return: the coordinates relative to this window.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._mainWin.ScreenToClient(*pointOrTuple)
+
+
+ def ScreenToClientXY(self, x, y):
+ """
+ Converts from screen to client window coordinates.
+
+ :param `x`: an integer specifying the `x` screen coordinate;
+ :param `y`: an integer specifying the `y` screen coordinate.
+
+ :return: the coordinates relative to this window.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ return self._mainWin.ScreenToClient(x, y)
+
+
+ def SetFocus(self):
+ """ This sets the window to receive keyboard input. """
+
+ # The test in window.cpp fails as we are a composite
+ # window, so it checks against "this", but not self._mainWin.
+ if wx.Window.FindFocus() != self:
+ self._mainWin.SetFocusIgnoringChildren()
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+ """
+
+ # Something is better than nothing...
+ # 100x80 is what the MSW version will get from the default
+ # wx.Control.DoGetBestSize
+ return wx.Size(100, 80)
+
+
+# ----------------------------------------------------------------------------
+# virtual list control support
+# ----------------------------------------------------------------------------
+
+ def OnGetItemText(self, item, col):
+ """
+ This function **must** be overloaded in the derived class for a control with
+ ``ULC_VIRTUAL`` style. It should return the string containing the text of
+ the given column for the specified item.
+
+ :param `item`: an integer specifying the item index;
+ :param `col`: the column index to which the item belongs to.
+ """
+
+ # this is a pure virtual function, in fact - which is not really pure
+ # because the controls which are not virtual don't need to implement it
+ raise Exception("UltimateListCtrl.OnGetItemText not supposed to be called")
+
+
+ def OnGetItemTextColour(self, item, col):
+ """
+ This function **must** be overloaded in the derived class for a control with
+ ``ULC_VIRTUAL`` style. It should return a :class:`Colour` object or ``None`` for
+ the default color.
+
+ :param `item`: an integer specifying the item index;
+ :param `col`: the column index to which the item belongs to.
+ """
+
+ # this is a pure virtual function, in fact - which is not really pure
+ # because the controls which are not virtual don't need to implement it
+ raise Exception("UltimateListCtrl.OnGetItemTextColour not supposed to be called")
+
+
+ def OnGetItemToolTip(self, item, col):
+ """
+ This function **must** be overloaded in the derived class for a control with
+ ``ULC_VIRTUAL`` style. It should return the string containing the text of
+ the tooltip for the specified item.
+
+ :param `item`: an integer specifying the item index;
+ :param `col`: the column index to which the item belongs to.
+ """
+
+ # this is a pure virtual function, in fact - which is not really pure
+ # because the controls which are not virtual don't need to implement it
+ raise Exception("UltimateListCtrl.OnGetItemToolTip not supposed to be called")
+
+
+ def OnGetItemImage(self, item):
+ """
+ This function **must** be overloaded in the derived class for a control with
+ ``ULC_VIRTUAL`` style having an image list (if the control doesn't have an
+ image list, it is not necessary to overload it). It should return a Python
+ list of indexes representing the images associated to the input item or an
+ empty list for no images.
+
+ :param `item`: an integer specifying the item index;
+
+ :note: In a control with ``ULC_REPORT`` style, :meth:`~UltimateListCtrl.OnGetItemImage` only gets called
+ for the first column of each line.
+
+ :note: The base class version always returns an empty Python list.
+ """
+
+ if self.GetImageList(wx.IMAGE_LIST_SMALL):
+ raise Exception("List control has an image list, OnGetItemImage should be overridden.")
+
+ return []
+
+
+ def OnGetItemColumnImage(self, item, column=0):
+ """
+ This function **must** be overloaded in the derived class for a control with
+ ``ULC_VIRTUAL`` and ``ULC_REPORT`` style. It should return a Python list of
+ indexes representing the images associated to the input item or an empty list
+ for no images.
+
+ :param `item`: an integer specifying the item index.
+
+ :note: The base class version always returns an empty Python list.
+ """
+
+ if column == 0:
+ return self.OnGetItemImage(item)
+
+ return []
+
+
+ def OnGetItemAttr(self, item):
+ """
+ This function may be overloaded in the derived class for a control with
+ ``ULC_VIRTUAL`` style. It should return the attribute for the specified
+ item or ``None`` to use the default appearance parameters.
+
+ :param `item`: an integer specifying the item index.
+
+ :note:
+
+ :class:`UltimateListCtrl` will not delete the pointer or keep a reference of it.
+ You can return the same :class:`UltimateListItemAttr` pointer for every
+ :meth:`~UltimateListCtrl.OnGetItemAttr` call.
+
+ :note: The base class version always returns ``None``.
+ """
+
+ if item < 0 or item > self.GetItemCount():
+ raise Exception("Invalid item index in OnGetItemAttr()")
+
+ # no attributes by default
+ return None
+
+
+ def OnGetItemCheck(self, item):
+ """
+ This function may be overloaded in the derived class for a control with
+ ``ULC_VIRTUAL`` style. It should return whether a checkbox-like item or
+ a radiobutton-like item is checked or unchecked.
+
+ :param `item`: an integer specifying the item index.
+
+ :note: The base class version always returns an empty list.
+ """
+
+ return []
+
+
+ def OnGetItemColumnCheck(self, item, column=0):
+ """
+ This function **must** be overloaded in the derived class for a control with
+ ``ULC_VIRTUAL`` and ``ULC_REPORT`` style. It should return whether a
+ checkbox-like item or a radiobutton-like item in the column header is checked
+ or unchecked.
+
+ :param `item`: an integer specifying the item index.
+
+ :note: The base class version always returns an empty Python list.
+ """
+
+ if column == 0:
+ return self.OnGetItemCheck(item)
+
+ return []
+
+
+ def OnGetItemKind(self, item):
+ """
+ This function **must** be overloaded in the derived class for a control with
+ ``ULC_VIRTUAL`` style. It should return the item kind for the input item.
+
+ :param `item`: an integer specifying the item index.
+
+ :note: The base class version always returns 0 (a standard item).
+
+ :see: :meth:`~UltimateListCtrl.SetItemKind` for a list of valid item kinds.
+ """
+
+ return 0
+
+
+ def OnGetItemColumnKind(self, item, column=0):
+ """
+ This function **must** be overloaded in the derived class for a control with
+ ``ULC_VIRTUAL`` style. It should return the item kind for the input item in
+ the header window.
+
+ :param `item`: an integer specifying the item index;
+ :param `column`: the column index.
+
+ :note: The base class version always returns 0 (a standard item).
+
+ :see: :meth:`~UltimateListCtrl.SetItemKind` for a list of valid item kinds.
+ """
+
+ if column == 0:
+ return self.OnGetItemKind(item)
+
+ return 0
+
+
+ def SetItemCount(self, count):
+ """
+ Sets the total number of items we handle.
+
+ :param `count`: the total number of items we handle.
+ """
+
+ if not self._mainWin.IsVirtual():
+ raise Exception("This is for virtual controls only")
+
+ self._mainWin.SetItemCount(count)
+
+
+ def RefreshItem(self, item):
+ """
+ Redraws the given item.
+
+ :param `item`: an integer specifying the item index;
+
+ :note: This is only useful for the virtual list controls as without calling
+ this function the displayed value of the item doesn't change even when the
+ underlying data does change.
+ """
+
+ self._mainWin.RefreshLine(item)
+
+
+ def RefreshItems(self, itemFrom, itemTo):
+ """
+ Redraws the items between `itemFrom` and `itemTo`.
+ The starting item must be less than or equal to the ending one.
+
+ Just as :meth:`~UltimateListCtrl.RefreshItem` this is only useful for virtual list controls
+
+ :param `itemFrom`: the first index of the refresh range;
+ :param `itemTo`: the last index of the refresh range.
+ """
+
+ self._mainWin.RefreshLines(itemFrom, itemTo)
+
+
+#
+# Generic UltimateListCtrl is more or less a container for two other
+# windows which drawings are done upon. These are namely
+# 'self._headerWin' and 'self._mainWin'.
+# Here we override 'virtual wxWindow::Refresh()' to mimic the
+# behaviour UltimateListCtrl has under wxMSW.
+#
+
+ def Refresh(self, eraseBackground=True, rect=None):
+ """
+ Causes this window, and all of its children recursively (except under wxGTK1
+ where this is not implemented), to be repainted.
+
+ :param `eraseBackground`: If ``True``, the background will be erased;
+ :param `rect`: If not ``None``, only the given rectangle will be treated as damaged.
+
+ :note: Note that repainting doesn't happen immediately but only during the next
+ event loop iteration, if you need to update the window immediately you should
+ use :meth:`~UltimateListCtrl.Update` instead.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ if not rect:
+
+ # The easy case, no rectangle specified.
+ if self._headerWin:
+ self._headerWin.Refresh(eraseBackground)
+
+ if self._mainWin:
+ self._mainWin.Refresh(eraseBackground)
+
+ else:
+
+ # Refresh the header window
+ if self._headerWin:
+
+ rectHeader = self._headerWin.GetRect()
+ rectHeader.Intersect(rect)
+ if rectHeader.GetWidth() and rectHeader.GetHeight():
+ x, y = self._headerWin.GetPosition()
+ rectHeader.OffsetXY(-x, -y)
+ self._headerWin.Refresh(eraseBackground, rectHeader)
+
+ # Refresh the main window
+ if self._mainWin:
+
+ rectMain = self._mainWin.GetRect()
+ rectMain.Intersect(rect)
+ if rectMain.GetWidth() and rectMain.GetHeight():
+ x, y = self._mainWin.GetPosition()
+ rectMain.OffsetXY(-x, -y)
+ self._mainWin.Refresh(eraseBackground, rectMain)
+
+
+ def Update(self):
+ """
+ Calling this method immediately repaints the invalidated area of the window
+ and all of its children recursively while this would usually only happen when
+ the flow of control returns to the event loop.
+
+ :note: This function doesn't invalidate any area of the window so nothing
+ happens if nothing has been invalidated (i.e. marked as requiring a redraw).
+ Use :meth:`~UltimateListCtrl.Refresh` first if you want to immediately redraw the window unconditionally.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ self._mainWin.ResetVisibleLinesRange(True)
+ wx.PyControl.Update(self)
+
+
+ def GetEditControl(self):
+ """
+ Returns a pointer to the edit :class:`UltimateListTextCtrl` if the item is being edited or
+ ``None`` otherwise (it is assumed that no more than one item may be edited
+ simultaneously).
+ """
+
+ retval = None
+
+ if self._mainWin:
+ retval = self._mainWin.GetEditControl()
+
+ return retval
+
+
+ def Select(self, idx, on=True):
+ """
+ Selects/deselects an item.
+
+ :param `idx`: the index of the item to select;
+ :param `on`: ``True`` to select the item, ``False`` to deselect it.
+ """
+
+ item = CreateListItem(idx, 0)
+ item = self._mainWin.GetItem(item, 0)
+ if not item.IsEnabled():
+ return
+
+ if on:
+ state = ULC_STATE_SELECTED
+ else:
+ state = 0
+
+
+ self.SetItemState(idx, state, ULC_STATE_SELECTED)
+
+
+ def Focus(self, idx):
+ """
+ Focus and show the given item.
+
+ :param `idx`: the index of the item to be focused.
+ """
+
+ self.SetItemState(idx, ULC_STATE_FOCUSED, ULC_STATE_FOCUSED)
+ self.EnsureVisible(idx)
+
+
+ def GetFocusedItem(self):
+ """ Returns the currently focused item or -1 if none is focused. """
+
+ return self.GetNextItem(-1, ULC_NEXT_ALL, ULC_STATE_FOCUSED)
+
+
+ def GetFirstSelected(self):
+ """ Return first selected item, or -1 when none is selected. """
+
+ return self.GetNextSelected(-1)
+
+
+ def GetNextSelected(self, item):
+ """
+ Returns subsequent selected items, or -1 when no more are selected.
+
+ :param `item`: the index of the item.
+ """
+
+ return self.GetNextItem(item, ULC_NEXT_ALL, ULC_STATE_SELECTED)
+
+
+ def IsSelected(self, idx):
+ """
+ Returns ``True`` if the item is selected.
+
+ :param `idx`: the index of the item to check for selection.
+ """
+
+ return (self.GetItemState(idx, ULC_STATE_SELECTED) & ULC_STATE_SELECTED) != 0
+
+
+ def IsItemChecked(self, itemOrId, col=0):
+ """
+ Returns whether an item is checked or not.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.IsItemChecked(item)
+
+
+ def IsItemEnabled(self, itemOrId, col=0):
+ """
+ Returns whether an item is enabled or not.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.IsItemEnabled(item)
+
+
+ def GetItemKind(self, itemOrId, col=0):
+ """
+ Returns the item kind.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to.
+
+ :see: :meth:`~UltimateListCtrl.SetItemKind` for a list of valid item kinds.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.GetItemKind(item)
+
+
+ def SetItemKind(self, itemOrId, col=0, kind=0):
+ """
+ Sets the item kind.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to;
+ :param `kind`: may be one of the following integers:
+
+ =============== ==========================
+ Item Kind Description
+ =============== ==========================
+ 0 A normal item
+ 1 A checkbox-like item
+ 2 A radiobutton-type item
+ =============== ==========================
+
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.SetItemKind(item, kind)
+
+
+ def EnableItem(self, itemOrId, col=0, enable=True):
+ """
+ Enables/disables an item.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to;
+ :param `enable`: ``True`` to enable the item, ``False`` otherwise.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.EnableItem(item, enable)
+
+
+ def IsItemHyperText(self, itemOrId, col=0):
+ """
+ Returns whether an item is hypertext or not.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.IsItemHyperText(item)
+
+
+ def SetItemHyperText(self, itemOrId, col=0, hyper=True):
+ """
+ Sets whether the item is hypertext or not.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to;
+ :param `hyper`: ``True`` to have an item with hypertext behaviour, ``False`` otherwise.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.SetItemHyperText(item, hyper)
+
+ def SetColumnToolTip(self, col, tip):
+ """
+ Sets the tooltip for the column header
+
+ :param `col`: the column index;
+ :param `tip`: the tooltip text
+ """
+
+ item = self.GetColumn(col)
+ item.SetToolTip(tip)
+ self.SetColumn(col, item)
+
+
+ def SetColumnImage(self, col, image):
+ """
+ Sets one or more images to the specified column.
+
+ :param `col`: the column index;
+ :param `image`: a Python list containing the image indexes for the
+ images associated to this column item.
+ """
+
+ item = self.GetColumn(col)
+ # preserve all other attributes too
+
+ item.SetMask(ULC_MASK_STATE |
+ ULC_MASK_TEXT |
+ ULC_MASK_IMAGE |
+ ULC_MASK_DATA |
+ ULC_SET_ITEM |
+ ULC_MASK_WIDTH |
+ ULC_MASK_FORMAT |
+ ULC_MASK_FONTCOLOUR |
+ ULC_MASK_FONT |
+ ULC_MASK_BACKCOLOUR |
+ ULC_MASK_KIND |
+ ULC_MASK_CHECK
+ )
+ item.SetImage(image)
+ self.SetColumn(col, item)
+
+
+ def ClearColumnImage(self, col):
+ """
+ Clears all the images in the specified column.
+
+ :param `col`: the column index;
+ """
+
+ self.SetColumnImage(col, -1)
+
+
+ def Append(self, entry):
+ """
+ Append an item to the :class:`UltimateListCtrl`.
+
+ :param `entry`: should be a sequence with an item for each column.
+ """
+
+ if entry:
+ if wx.USE_UNICODE:
+ cvtfunc = unicode
+ else:
+ cvtfunc = str
+ pos = self.GetItemCount()
+ self.InsertStringItem(pos, cvtfunc(entry[0]))
+ for i in range(1, len(entry)):
+ self.SetStringItem(pos, i, cvtfunc(entry[i]))
+
+ return pos
+
+
+ def SetFirstGradientColour(self, colour=None):
+ """
+ Sets the first gradient colour for gradient-style selections.
+
+ :param `colour`: if not ``None``, a valid :class:`Colour` instance. Otherwise,
+ the colour is taken from the system value ``wx.SYS_COLOUR_HIGHLIGHT``.
+ """
+
+ self._mainWin.SetFirstGradientColour(colour)
+
+
+ def SetSecondGradientColour(self, colour=None):
+ """
+ Sets the second gradient colour for gradient-style selections.
+
+ :param `colour`: if not ``None``, a valid :class:`Colour` instance. Otherwise,
+ the colour generated is a slightly darker version of the :class:`UltimateListCtrl`
+ background colour.
+ """
+
+ self._mainWin.SetSecondGradientColour(colour)
+
+
+ def GetFirstGradientColour(self):
+ """ Returns the first gradient colour for gradient-style selections. """
+
+ return self._mainWin.GetFirstGradientColour()
+
+
+ def GetSecondGradientColour(self):
+ """ Returns the second gradient colour for gradient-style selections. """
+
+ return self._mainWin.GetSecondGradientColour()
+
+
+ def EnableSelectionGradient(self, enable=True):
+ """
+ Globally enables/disables drawing of gradient selections.
+
+ :param `enable`: ``True`` to enable gradient-style selections, ``False``
+ to disable it.
+
+ :note: Calling this method disables any Vista-style selection previously
+ enabled.
+ """
+
+ self._mainWin.EnableSelectionGradient(enable)
+
+
+ def SetGradientStyle(self, vertical=0):
+ """
+ Sets the gradient style for gradient-style selections.
+
+ :param `vertical`: 0 for horizontal gradient-style selections, 1 for vertical
+ gradient-style selections.
+ """
+
+ self._mainWin.SetGradientStyle(vertical)
+
+
+ def GetGradientStyle(self):
+ """
+ Returns the gradient style for gradient-style selections.
+
+ :return: 0 for horizontal gradient-style selections, 1 for vertical
+ gradient-style selections.
+ """
+
+ return self._mainWin.GetGradientStyle()
+
+
+ def EnableSelectionVista(self, enable=True):
+ """
+ Globally enables/disables drawing of Windows Vista selections.
+
+ :param `enable`: ``True`` to enable Vista-style selections, ``False`` to
+ disable it.
+
+ :note: Calling this method disables any gradient-style selection previously
+ enabled.
+ """
+
+ self._mainWin.EnableSelectionVista(enable)
+
+
+ def SetSelectedTextColour(self, colour=None):
+ """
+ Sets the colour of text applied to an item when it is selected.
+ If this method is not called, text color of selected items will be
+ the system value ``wx.SYS_COLOUR_HIGHLIGHTTEXT``, or the color set on
+ the item with SetTextColour.
+
+ :param `colour`: if not ``None``, a valid :class:`Colour` instance. Otherwise,
+ the colour is taken from the system value ``wx.SYS_COLOUR_HIGHLIGHTTEXT``.
+ """
+
+ self._mainWin.SetSelectedTextColour(colour)
+
+
+ def GetSelectedTextColour(self):
+ """ Returns the colour applied to text when an item is selected. """
+
+ return self._mainWin.GetSelectedTextColour()
+
+
+ def SetBackgroundImage(self, image=None):
+ """
+ Sets the :class:`UltimateListCtrl` background image.
+
+ :param `image`: if not ``None``, an instance of :class:`Bitmap`.
+
+ :note: At present, the background image can only be used in "tile" mode.
+
+ .. todo:: Support background images also in stretch and centered modes.
+ """
+
+ self._mainWin.SetBackgroundImage(image)
+
+
+ def GetBackgroundImage(self):
+ """
+ Returns the :class:`UltimateListCtrl` background image (if any).
+
+ :note: At present, the background image can only be used in "tile" mode.
+
+ .. todo:: Support background images also in stretch and centered modes.
+ """
+
+ return self._mainWin.GetBackgroundImage()
+
+
+ def SetWaterMark(self, watermark=None):
+ """
+ Sets the :class:`UltimateListCtrl` watermark image to be displayed in the bottom
+ right part of the window.
+
+ :param `watermark`: if not ``None``, an instance of :class:`Bitmap`.
+
+ .. todo:: Better support for this is needed.
+ """
+
+ self._mainWin.SetWaterMark(watermark)
+
+
+ def GetWaterMark(self):
+ """
+ Returns the :class:`UltimateListCtrl` watermark image (if any), displayed in the
+ bottom right part of the window.
+
+ .. todo:: Better support for this is needed.
+ """
+
+ return self._mainWin.GetWaterMark()
+
+
+ def SetDisabledTextColour(self, colour):
+ """
+ Sets the items disabled colour.
+
+ :param `colour`: an instance of :class:`Colour`.
+ """
+
+ self._mainWin.SetDisabledTextColour(colour)
+
+
+ def GetDisabledTextColour(self):
+ """ Returns the items disabled colour. """
+
+ return self._mainWin.GetDisabledTextColour()
+
+
+ def GetHyperTextFont(self):
+ """ Returns the font used to render an hypertext item. """
+
+ return self._mainWin.GetHyperTextFont()
+
+
+ def SetHyperTextFont(self, font):
+ """
+ Sets the font used to render hypertext items.
+
+ :param `font`: a valid :class:`Font` instance.
+ """
+
+ self._mainWin.SetHyperTextFont(font)
+
+
+ def SetHyperTextNewColour(self, colour):
+ """
+ Sets the colour used to render a non-visited hypertext item.
+
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ self._mainWin.SetHyperTextNewColour(colour)
+
+
+ def GetHyperTextNewColour(self):
+ """ Returns the colour used to render a non-visited hypertext item. """
+
+ return self._mainWin.GetHyperTextNewColour()
+
+
+ def SetHyperTextVisitedColour(self, colour):
+ """
+ Sets the colour used to render a visited hypertext item.
+
+ :param `colour`: a valid :class:`Colour` instance.
+ """
+
+ self._mainWin.SetHyperTextVisitedColour(colour)
+
+
+ def GetHyperTextVisitedColour(self):
+ """ Returns the colour used to render a visited hypertext item. """
+
+ return self._mainWin.GetHyperTextVisitedColour()
+
+
+ def SetItemVisited(self, itemOrId, col=0, visited=True):
+ """
+ Sets whether an hypertext item was visited or not.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to;
+ :param `visited`: ``True`` to mark an hypertext item as visited, ``False`` otherwise.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.SetItemVisited(item, visited)
+
+
+ def GetItemVisited(self, itemOrId, col=0):
+ """
+ Returns whether an hypertext item was visited.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.GetItemVisited(item)
+
+
+ def GetItemWindow(self, itemOrId, col=0):
+ """
+ Returns the window associated to the item (if any).
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.GetItemWindow(item)
+
+
+ def SetItemWindow(self, itemOrId, col=0, wnd=None, expand=False):
+ """
+ Sets the window for the given item.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to;
+ :param `wnd`: a non-toplevel window to be displayed next to the item;
+ :param `expand`: ``True`` to expand the column where the item/subitem lives,
+ so that the window will be fully visible.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.SetItemWindow(item, wnd, expand)
+
+
+ def DeleteItemWindow(self, itemOrId, col=0):
+ """
+ Deletes the window associated to an item (if any).
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.DeleteItemWindow(item)
+
+
+ def GetItemWindowEnabled(self, itemOrId, col=0):
+ """
+ Returns whether the window associated to the item is enabled.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to;
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.GetItemWindowEnabled(item)
+
+
+ def SetItemWindowEnabled(self, itemOrId, col=0, enable=True):
+ """
+ Enables/disables the window associated to the item.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to;
+ :param `enable`: ``True`` to enable the associated window, ``False`` to disable it.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.SetItemWindowEnabled(item, enable)
+
+
+ def GetItemCustomRenderer(self, itemOrId, col=0):
+ """
+ Returns the custom renderer used to draw the input item (if any).
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.GetItemCustomRenderer(item)
+
+
+ def SetHeaderCustomRenderer(self, renderer=None):
+ """
+ Associate a custom renderer with the header - all columns will use it.
+
+ :param `renderer`: a class able to correctly render header buttons
+
+ :note: the renderer class **must** implement the methods `DrawHeaderButton`
+ and `GetForegroundColor`.
+ """
+
+ if not self.HasAGWFlag(ULC_REPORT):
+ raise Exception("Custom renderers can be used on with style = ULC_REPORT")
+
+ self._headerWin.SetCustomRenderer(renderer)
+
+
+ def SetFooterCustomRenderer(self, renderer=None):
+ """
+ Associate a custom renderer with the footer - all columns will use it.
+
+ :param `renderer`: a class able to correctly render header buttons
+
+ :note: the renderer class **must** implement the methods `DrawHeaderButton`
+ and `GetForegroundColor`.
+ """
+
+ if not self.HasAGWFlag(ULC_REPORT) or not self.HasAGWFlag(ULC_FOOTER):
+ raise Exception("Custom renderers can only be used on with style = ULC_REPORT | ULC_FOOTER")
+
+ self._footerWin.SetCustomRenderer(renderer)
+
+
+ def SetColumnCustomRenderer(self, col=0, renderer=None):
+ """
+ Associate a custom renderer to this column's header.
+
+ :param `col`: the column index.
+ :param `renderer`: a class able to correctly render the input item.
+
+ :note: the renderer class **must** implement the methods `DrawHeaderButton`
+ and `GetForegroundColor`.
+ """
+
+ if not self.HasAGWFlag(ULC_REPORT):
+ raise Exception("Custom renderers can be used on with style = ULC_REPORT")
+
+ return self._mainWin.SetCustomRenderer(col, renderer)
+
+
+ def SetItemCustomRenderer(self, itemOrId, col=0, renderer=None):
+ """
+ Associate a custom renderer to this item.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to;
+ :param `renderer`: a class able to correctly render the input item.
+
+ :note: the renderer class **must** implement the methods `DrawSubItem`,
+ `GetLineHeight` and `GetSubItemWidth`.
+ """
+
+ if not self.HasAGWFlag(ULC_REPORT) or not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
+ raise Exception("Custom renderers can be used on with style = ULC_REPORT | ULC_HAS_VARIABLE_ROW_HEIGHT")
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.SetItemCustomRenderer(item, renderer)
+
+
+ def SetItemOverFlow(self, itemOrId, col=0, over=True):
+ """
+ Sets the item in the overflow/non overflow state.
+
+ An item/subitem may overwrite neighboring items/subitems if its text would
+ not normally fit in the space allotted to it.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to;
+ :param `over`: ``True`` to set the item in a overflow state, ``False`` otherwise.
+ """
+
+ if not self.HasAGWFlag(ULC_REPORT) or self._mainWin.IsVirtual():
+ raise Exception("Overflowing items can be used only in report, non-virtual mode")
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.SetItemOverFlow(item, over)
+
+
+ def GetItemOverFlow(self, itemOrId, col=0):
+ """
+ Returns if the item is in the overflow state.
+
+ An item/subitem may overwrite neighboring items/subitems if its text would
+ not normally fit in the space allotted to it.
+
+ :param `itemOrId`: an instance of :class:`UltimateListItem` or the item index;
+ :param `col`: the column index to which the input item belongs to.
+ """
+
+ item = CreateListItem(itemOrId, col)
+ return self._mainWin.GetItemOverFlow(item)
+
+
+ def IsVirtual(self):
+ """ Returns ``True`` if the :class:`UltimateListCtrl` has the ``ULC_VIRTUAL`` style set. """
+
+ return self._mainWin.IsVirtual()
+
+
+ def GetScrollPos(self, orientation):
+ """
+ Returns the scrollbar position.
+
+ :param int `orientation`: defines for which scrollbar we ask the position.
+ May be ``wx.HORIZONTAL`` or ``wx.VERTICAL``.
+
+ :note: This method is forwarded to :class:`UltimateListMainWindow`.
+ """
+
+ if self._mainWin:
+ return self._mainWin.GetScrollPos(orientation)
+
+ return 0
+
+
+ def SetScrollPos(self, orientation, pos, refresh=True):
+ """
+ Sets the scrollbar position.
+
+ :param `orientation`: determines the scrollbar whose position is to be set.
+ May be ``wx.HORIZONTAL`` or ``wx.VERTICAL``;
+ :param `pos`: the scrollbar position in scroll units;
+ :param `refresh`: ``True`` to redraw the scrollbar, ``False`` otherwise.
+
+ :note: This method is forwarded to :class:`UltimateListMainWindow`.
+ """
+
+ if self._mainWin:
+ self._mainWin.SetScrollPos(orientation, pos, refresh)
+
+
+ def GetScrollThumb(self, orientation):
+ """
+ Returns the scrollbar size in pixels.
+
+ :param `orientation`: determines the scroll thumb whose position is to be retrieved.
+ May be ``wx.HORIZONTAL`` or ``wx.VERTICAL``.
+
+ :note: This method is forwarded to :class:`UltimateListMainWindow`.
+ """
+
+ if self._mainWin:
+ return self._mainWin.GetScrollThumb(orientation)
+
+ return 0
+
+
+ def GetScrollRange(self, orientation):
+ """
+ Returns the scrollbar range in pixels.
+
+ :param `orientation`: determines the scroll range whose position is to be retrieved.
+ May be ``wx.HORIZONTAL`` or ``wx.VERTICAL``.
+
+ :note: This method is forwarded to :class:`UltimateListMainWindow`.
+ """
+
+ if self._mainWin:
+ return self._mainWin.GetScrollRange(orientation)
+
+ return 0
+
+
+ def SetHeaderHeight(self, height):
+ """
+ Sets the :class:`UltimateListHeaderWindow` height, in pixels. This overrides the default
+ header window size derived from :class:`RendererNative`. If `height` is ``None``, the
+ default behaviour is restored.
+
+ :param `height`: the header window height, in pixels (if it is ``None``, the default
+ height obtained using :class:`RendererNative` is used).
+ """
+
+ if not self._headerWin:
+ return
+
+ if height is not None and height < 1:
+ raise Exception("Invalid height passed to SetHeaderHeight: %s"%repr(height))
+
+ self._headerWin._headerHeight = height
+ self.DoLayout()
+
+
+ def GetHeaderHeight(self):
+ """ Returns the :class:`UltimateListHeaderWindow` height, in pixels. """
+
+ if not self._headerWin:
+ return -1
+
+ return self._headerWin.GetWindowHeight()
+
+
+ def SetFooterHeight(self, height):
+ """
+ Sets the :class:`UltimateListHeaderWindow` height, in pixels. This overrides the default
+ footer window size derived from :class:`RendererNative`. If `height` is ``None``, the
+ default behaviour is restored.
+
+ :param `height`: the footer window height, in pixels (if it is ``None``, the default
+ height obtained using :class:`RendererNative` is used).
+ """
+
+ if not self._footerWin:
+ return
+
+ if height is not None and height < 1:
+ raise Exception("Invalid height passed to SetFooterHeight: %s"%repr(height))
+
+ self._footerWin._footerHeight = height
+ self.DoLayout()
+
+
+ def GetFooterHeight(self):
+ """ Returns the :class:`UltimateListHeaderWindow` height, in pixels. """
+
+ if not self._footerWin:
+ return -1
+
+ return self._headerWin.GetWindowHeight()
+
+
+ def DoLayout(self):
+ """
+ Layouts the header, main and footer windows. This is an auxiliary method to avoid code
+ duplication.
+ """
+
+ self.Layout()
+
+ self._mainWin.ResizeColumns()
+ self._mainWin.ResetVisibleLinesRange(True)
+ self._mainWin.RecalculatePositions()
+ self._mainWin.AdjustScrollbars()
+
+ if self._headerWin:
+ self._headerWin.Refresh()
+
+ if self._footerWin:
+ self._footerWin.Refresh()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/xlsgrid.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/xlsgrid.py
new file mode 100644
index 0000000..7476caa
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/xlsgrid.py
@@ -0,0 +1,2114 @@
+# --------------------------------------------------------------------------------- #
+# XLSGRID wxPython IMPLEMENTATION
+#
+# Andrea Gavana @ 08 Aug 2011
+# Latest Revision: 20 Mar 2012, 21.00 GMT
+#
+#
+# TODO List
+#
+# Current todo list:
+#
+# 1. There is currently no support for rich text, i.e. strings containing partial
+# bold, italic and underlined text, change of font inside a string, etc... xlrd
+# supports those (from version 0.7.2 in SVN) but there is no easy way to handle
+# changing fonts/colours/formatting in the same string in wxPython;
+#
+# 2. XLSGrid is sufficiently efficient and fast for reasonably small Excel files.
+# There might be some improvement to be made in the code to make it work with
+# bigger files and in a faster way;
+#
+# 3. There is currently no support for strikethrough fonts, although xlrd correctly
+# reports this format. The issue is a bug in wxWidgets itself which doesn't
+# allow the creation of strikethrough fonts (http://trac.wxwidgets.org/ticket/9907).
+#
+# For all kind of problems, requests of enhancements and bug reports, please write
+# to me at:
+#
+# andrea.gavana@gmail.com
+# andrea.gavana@maerskoil.com
+#
+# Or, obviously, to the wxPython mailing list!!!
+#
+#
+# End of comments
+# --------------------------------------------------------------------------------- #
+
+
+"""
+:class:`XLSGrid` is a class based on :class:`grid.Grid` that can be used to faithfully
+reproduce the appearance of a Microsoft Excel spreadsheet (one worksheet per
+every instance of :class:`XLSGrid`).
+
+
+Description
+===========
+
+:class:`XLSGrid` is a class based on :class:`grid.Grid` that can be used to faithfully
+reproduce the appearance of a Microsoft Excel spreadsheet (one worksheet per
+every instance of :class:`XLSGrid`).
+
+:class:`XLSGrid` is a completely owner-drawn control, and it relies on the power of
+:class:`grid.PyGridTableBase` and :class:`grid.PyGridCellRenderer` to draw the cell
+content. For this reasons (and for some others, see the TODOs section), it will
+work efficiently only for relatively small Excel files.
+
+:note:
+
+ :class:`XLSGrid` **requires** the `xlrd` package from:
+
+ http://pypi.python.org/pypi/xlrd
+
+ Minimum version requirement for `xlrd` is 0.7.1. If you wish to have
+ support for hyperlinks inside cells and rich text content, you need the
+ SVN version of `xlrd`.
+
+
+:note:
+
+ On Windows, it is **strongly** recommended to install Mark Hammonds'
+ `pywin32` package:
+
+ http://sourceforge.net/projects/pywin32/
+
+ This will allow you to perfectly reproduce the appearance of the Excel
+ worksheet in your instance of :class:`XLSGrid`.
+
+.. warning::
+
+ If Mark Hammonds' `pywin32` package is not available, the formatting
+ capabilities of :class:`XLSGrid` are severely limited; for instance, you won't
+ probably get the exact WYSIWYG between the Excel spreadsheet and :class:`XLSGrid`.
+
+
+.. warning::
+
+ :class:`XLSGrid` can only read Excel `.xls` files, not the newer versions
+ `.xlsx` generated by Office 2007/2010. If you have a `.xlsx` file, you will
+ need to save it in 1997-2003 Office compatibility mode.
+
+
+Currently this class provides a read-only subclass of :class:`grid.Grid`, with
+the following formatting features already implemented:
+
+* Cell background: support for any cell background colour and fill pattern
+ (hatching) in the Excel default set. There currently is no support for
+ gradient shading inside a cell as `xlrd` doesn't report this information.
+
+* Cell borders: support for all the border types and colours exposed by Excel
+ (left, top, bottom, right and diagonal borders, thin, double, thick, ect...
+ line styles).
+
+* Cell text: support for all kind of fonts (except strikethrough, but this is
+ a bug in wxWidgets), and font colours. As a subset of text/font capabilities,
+ :class:`XLSGrid` supports the following features found in Excel:
+
+ - Horizontal alignment: left, right, centered, left-indented;
+ - Vertical alignment: left, right, centered;
+ - Text direction: left-to-right or right-to-left;
+ - Text-wrapping: wrapping long texts inside a grid cell;
+ - Shrink-to-fit: text font is reduced until the text can fit in a one-line
+ inside the grid cell;
+ - Text rotation: text can be rotated from +90 to -90 degrees.
+
+* Cell rich text (new in version 0.2): support for strings containing partial
+ bold, italic and underlined text, change of font inside a string etc...
+ Cells with rich text content can not be multi-line and they will not honour
+ the `shrink-to-fit` and `wrapping` settings.
+
+* Cell text appearance: if you are using Mark Hammonds' `pywin32` package, the
+ text displayed in the :class:`XLSGrid` cells has exactly the same appearance as in
+ the Excel spreadsheet.
+
+* Cell comments (notes): if you are using Mark Hammonds' `pywin32` package,
+ cell comments (notes) are extracted and you will see a small red triangle at
+ the top-right corner of any cell containing a comment. Hovering with the
+ mouse on that cell will pop-up a "comment-window" displaying the comment
+ text (the comment window is based on :mod:`lib.agw.supertooltip`).
+
+* Cell hyperlinks: starting from version 0.7.2 (SVN), `xlrd` is capable of
+ extracting hyperlinks from Excel cells. This will be appropriately displayed
+ in :class:`XLSGrid` with a cursor changing and a tooltip on that cell.
+
+* Cell merging: merged cells in the Excel spreadsheet will be correctly handled
+ by :class:`XLSGrid`.
+
+* Columns and rows sizes: :class:`XLSGrid` calculates the correct rows and columns
+ sizes based on the Excel reported values in characters. The calculations are
+ based on the default width of the text in 1/256 of the width of the zero
+ character, using default Excel font (first FONT record in the Excel file).
+
+
+And a lot more. Check the demo for an almost complete review of the functionalities.
+
+
+Usage
+=====
+
+Sample usage::
+
+ import wx
+ import xlrd
+ import os
+
+ import xlsgrid as XG
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self):
+
+ wx.Frame.__init__(self, parent, -1, "XLSGrid Demo", size=(1000, 800))
+
+ filename = os.path.join(os.getcwd(), "Excel", "Example_1.xls")
+ sheetname = "Example_1"
+
+ book = xlrd.open_workbook(filename, formatting_info=1)
+
+ sheet = book.sheet_by_name(sheetname)
+ rows, cols = sheet.nrows, sheet.ncols
+
+ comments, texts = XG.ReadExcelCOM(filename, sheetname, rows, cols)
+
+ xls_grid = XG.XLSGrid(self)
+ xls_grid.PopulateGrid(book, sheet, texts, comments)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+:note: Please note that you **have to** pass the keyword `formatting_info` to
+ the method `xlrd.open_workbook` to obtain the cell formatting.
+
+
+TODOs
+=====
+
+1. :class:`XLSGrid` is sufficiently efficient and fast for reasonably small Excel files.
+ There might be some improvement to be made in the code to make it work with
+ bigger files and in a faster way;
+2. :class:`grid.Grid` seems to completely redraw itself at every resize event, even
+ if the cell content has not changed and it has not been damaged (this seems
+ to be fixed in wxPython 2.9.2.1);
+3. There is currently no support for strikethrough fonts, although `xlrd` correctly
+ reports this format. The issue is a bug in wxWidgets itself which doesn't
+ allow the creation of strikethrough fonts (http://trac.wxwidgets.org/ticket/9907).
+
+
+Supported Platforms
+===================
+
+:class:`XLSGrid` has been tested on the following platforms:
+ * Windows (Windows Vista and 7);
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+`No custom events are available for this class.`
+
+
+License And Version
+===================
+
+:class:`XLSGrid` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 20 Mar 2012, 21.00 GMT
+
+Version 0.4
+
+"""
+
+# Version Info
+__version__ = "0.4"
+
+# Start the imports
+import wx
+import os
+
+try:
+ import xlrd
+except ImportError:
+ pass
+
+import datetime
+import string
+
+import wx.grid as gridlib
+
+from wx.lib.embeddedimage import PyEmbeddedImage
+from wx.lib.wordwrap import wordwrap
+
+import supertooltip as STT
+
+from math import pi, sin, cos
+from operator import attrgetter
+
+_hasWin32 = False
+
+if wx.Platform == "__WXMSW__":
+ try:
+ from win32com.client import Dispatch
+ import pywintypes
+ _hasWin32 = True
+ except ImportError:
+ pass
+
+
+#----------------------------------------------------------------------
+# Constants used to translate xlrd stuff into wxPython stuff
+#----------------------------------------------------------------------
+
+BOTTOM = wx.BOTTOM
+TOP = wx.TOP
+LEFT = wx.LEFT
+RIGHT = wx.RIGHT
+DIAGONAL = 2 << 7
+
+XF_BORDER_STYLES = {"bottom": BOTTOM, "left": LEFT, "right": RIGHT,
+ "top": TOP, "diag": DIAGONAL}
+
+HORIZONTAL_ALIGNMENTS = {0: 0, 1: 0, 2: wx.ALIGN_CENTER_HORIZONTAL, 3: wx.ALIGN_RIGHT}
+VERTICAL_ALIGNMENTS = {0: 0, 1: wx.ALIGN_CENTER_VERTICAL, 2: wx.ALIGN_BOTTOM,
+ 3: wx.ALIGN_CENTER_VERTICAL, 4:wx.ALIGN_CENTER_VERTICAL}
+
+NO_LINE = 0x0
+THIN = 0x1
+MEDIUM = 0x2
+DASHED = 0x3
+DOTTED = 0x4
+THICK = 0x5
+DOUBLE = 0x6
+HAIR = 0x7
+MEDIUM_DASHED = 0x8
+THIN_DASH_DOTTED = 0x9
+MEDIUM_DASH_DOTTED = 0xA
+THIN_DASH_DOT_DOTTED = 0xB
+MEDIUM_DASH_DOT_DOTTED = 0xC
+SLANTED_MEDIUM_DASH_DOTTED = 0xD
+
+XF_PEN_STYLES = {NO_LINE: (0, None), THIN: (1, wx.SOLID), MEDIUM: (2, wx.SOLID),
+ DASHED: (1, wx.SHORT_DASH), DOTTED: (1, wx.DOT),
+ THICK: (3, wx.SOLID), DOUBLE: (1, wx.SOLID), HAIR: (1, wx.DOT),
+ MEDIUM_DASHED: (2, wx.LONG_DASH), THIN_DASH_DOTTED: (1, wx.DOT_DASH),
+ MEDIUM_DASH_DOTTED: (2, wx.DOT_DASH), THIN_DASH_DOT_DOTTED: (1, wx.DOT_DASH),
+ MEDIUM_DASH_DOT_DOTTED: (2, wx.DOT_DASH),
+ SLANTED_MEDIUM_DASH_DOTTED: (2, wx.DOT_DASH)
+ }
+
+XF_FONT_FAMILY = {0: wx.SWISS, 1: wx.ROMAN, 2: wx.SWISS,
+ 3: wx.MODERN, 4: wx.SCRIPT, 5: wx.DECORATIVE}
+
+# Unicode ordinals for Hebrew, Arabic and Syriac
+# I don't know if there are other RTL languages
+RTL_UNICODE = range(1424, 1872)
+
+# To guess text direction we exclude digits and punctuation
+USELESS_CHARS = string.punctuation + string.digits + " "
+
+
+#----------------------------------------------------------------------
+# Images used to draw the hatching on Excel cells background
+#----------------------------------------------------------------------
+
+_xls_background_01 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAADElE"
+ "QVQImWNgIB0AAAA0AAEjQ4N1AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_xls_background_02 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAFklE"
+ "QVQImWNgYGD4//8/lESwIAC7DABt4hfpI2a12wAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_xls_background_03 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAE0lE"
+ "QVQImWP4//8/AxqACuGUAQBI+Qv1NTPP3AAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_xls_background_04 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAH0lE"
+ "QVQImXXJsQ0AIAAEIc79d34LazsSwjbgPFXoOxdcCQwBh7OgqgAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_xls_background_05 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAFUlE"
+ "QVQImWNgwAUY////D+cwIcsAAEggAwHHgMubAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_xls_background_06 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAG0lE"
+ "QVQImWNkYGBgYGD4//8/AwMDEwMSwM0BAISAAwUnufp7AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_xls_background_07 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAHklE"
+ "QVQImWNkYGBgYGD4//8/EgVh/P//H86HikH4APOCFO3yiGicAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_xls_background_08 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAHUlE"
+ "QVQImWP4////////GSAAzvr//z8jmhADXCUAQSkU7eggG3gAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_xls_background_09 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAIElE"
+ "QVQImWNkYGBgYGD4//8/AwMDEwMy+P//P0QYXQYACtQI/cTE6U0AAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_xls_background_10 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAG0lE"
+ "QVQImW3IsQ0AAAjAIPz/6LobGRmgclVfswpsCPmQczsGAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_xls_background_11 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAFklE"
+ "QVQImWNgQAKM////h3OYkGVQOABvOgMD4NUKkwAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_xls_background_12 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAG0lE"
+ "QVQImWNkYGD4//8/AwMDAwMDEwMSwM0BAI13AwWY+Mx+AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_xls_background_13 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAI0lE"
+ "QVQImT3KsQ0AMAyAMMj/P9MhUUcLBCoAmEo9bFn7H/UBXEwMBN75abEAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_xls_background_14 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAIElE"
+ "QVQImT3KoQEAAAwCINz/P7tmI5C2QJKb2t6EYPMBOOUMBIWcMEIAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+_xls_background_15 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAGUlE"
+ "QVQImWNgQAKMDAwM////h3CYkGVQOABmQwMDJpgq9gAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_xls_background_16 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAHklE"
+ "QVQImWNgYGD4//8/lISzIAwEnxEqwMDAyMgIALKwF+2ym+hoAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+_xls_background_17 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAIklE"
+ "QVQImWNkYGD4//8/AwMDAwMDI5zFwMDABBVjZESXAQAc+AkAQ4bzDAAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+_xls_background_18 = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAECAIAAAA8r+mnAAAAA3NCSVQICAjb4U/gAAAAH0lE"
+ "QVQImWNkYGD4//8/AwZgxCrKwMDAhKKKkZGwDgA83QkAy10JvwAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+
+
+def SplitThousands(s, tSep=',', dSep='.'):
+ """
+ Splits a general float on thousands. GIGO on general input.
+
+ :param `s`: can be a float or a string, representing a number;
+ :param `tSep`: the character to be used as thousands separator;
+ :param `dSep`: the character to be used as decimal separator.
+
+ :returns: a string properly formatted with thousands and decimal
+ separators in it.
+
+ :note: This method is used only if Mark Hammonds' `pywin32` package is
+ not available to try and format a number in an intelligent way.
+
+ :note: This code has been obtained from the public domain:
+
+ http://code.activestate.com/recipes/498181-add-thousands-separator-commas-to-formatted-number/#c14
+
+ """
+
+ if not isinstance(s, basestring):
+ s = unicode(s, "utf-8", "ignore")
+
+ cnt = 0
+ numChars = dSep + '0123456789'
+ ls = len(s)
+
+ while cnt < ls and s[cnt] not in numChars:
+ cnt += 1
+
+ lhs = s[0:cnt]
+ s = s[cnt:]
+
+ if dSep == '':
+ cnt = -1
+ else:
+ cnt = s.rfind(dSep)
+
+ if cnt > 0:
+ rhs = dSep + s[cnt+1:]
+ s = s[:cnt]
+ else:
+ rhs = ''
+
+ splt = ''
+ while s != '':
+ splt = s[-3:] + tSep + splt
+ s = s[:-3]
+
+ return lhs + splt[:-1] + rhs
+
+
+def ReadExcelCOM(filename, sheetname, rows, cols):
+ """
+ Reads and Excel spreadsheet (a single worksheet) using Mark Hammonds' `pywin32`
+ package. If this package is not available, it returns two empty nested lists.
+
+ :param `filename`: a valid Excel `.xls` filename;
+ :param `sheetname`: the worksheet name inside the Excel file (i.e., the label
+ on the workbook tab at the bottom of the workbook);
+ :param `rows`: the number of significant rows in the worksheet, as returned
+ by `xlrd`;
+ :param `cols`: the number of significant columns in the worksheet, as returned
+ by `xlrd`.
+
+ :returns: two nested lists representing the comments (notes) on every cell and
+ the WYSIWYG representation of the cell content.
+
+ :note: If Mark Hammonds' `pywin32` package is not available, this method
+ returns two empty nested lists.
+ """
+
+ comments = [["" for i in range(cols)] for j in range(rows)]
+ texts = [[None for i in range(cols)] for j in range(rows)]
+
+ if not _hasWin32:
+ return comments, texts
+
+ try:
+ workbook = Excel(filename, sheetname)
+
+ for i in xrange(1, rows+1):
+ for j in xrange(1, cols+1):
+ texts[i-1][j-1] = workbook.GetText(i, j)
+
+ comm_range = workbook.GetCommentsRange()
+ if comm_range is not None:
+ for comm in comm_range:
+ comments[comm.Row-1][comm.Column-1] = comm.Comment.Text()
+
+ workbook.Close()
+
+ except pywintypes.com_error:
+ pass
+
+ return comments, texts
+
+
+def FontFromFont(font):
+ """
+ Creates a copy of the input `font`.
+
+ :param `font`: an instance of :class:`Font`.
+ """
+
+ new_font = wx.Font(font.GetPointSize(), font.GetFamily(), font.GetStyle(),
+ font.GetWeight(), font.GetUnderlined(),
+ font.GetFaceName(), font.GetEncoding())
+
+ return new_font
+
+
+class Excel(object):
+ """
+ A simple class that holds a COM interface to Excel.
+
+ By using the `win32com` module from Mark Hammonds' `pywin32` package, we
+ can manipulate various workbook/worksheet methods inside this class.
+ """
+
+ def __init__(self, filename, sheetname):
+ """
+ Default class constructor.
+
+ :param `filename`: a valid Excel `.xls` filename;
+ :param `sheetname`: the worksheet name inside the Excel file (i.e., the label
+ on the workbook tab at the bottom of the workbook).
+ """
+
+ self.xlApp = Dispatch('Excel.Application')
+ self.filename = filename
+ self.xlBook = self.xlApp.Workbooks.Open(filename)
+ self.sheet = self.xlBook.Worksheets(sheetname)
+
+ self.xlApp.Visible = 0
+
+
+ def Close(self, save=False):
+ """
+ Closes the Excel workbook, interrupting the COM interface.
+
+ :param `save`: ``True`` to save the changes you made to the workbook,
+ ``False`` otherwise.
+ """
+
+ self.xlBook.Close(SaveChanges=save)
+ del self.xlApp
+
+
+ def GetCommentsRange(self):
+ """
+ Returns a range of cells containing comments, using the VBA API.
+
+ """
+
+ try:
+ return self.sheet.Cells.SpecialCells(-4144)
+ except pywintypes.com_error:
+ return None
+
+
+ def GetText(self, row, col):
+ """
+ Returns the WYSIWYG text contained in a cell.
+
+ :param `row`: the row in which the cell lives;
+ :param `col`: the column in which the cell lives.
+
+ :note: The `row` and `col` parameters are not real Python index, as they
+ use the Excel indexing mode (i.e., first index is 1 and not 0).
+ """
+
+ cell = self.sheet.Cells(row, col)
+
+ if cell:
+ return cell.Text
+
+
+class XLSText(object):
+ """
+ This is a class which holds information about the cell content, in terms
+ of actual cell value, font, text colour, alignment and formatting.
+ """
+
+ def __init__(self, book, cell, xf_index, display_text=None, hyperlink=None, default_width=10):
+ """
+ Default class constructor.
+
+ :param `book`: an instance of the `xlrd.Book` class;
+ :param `cell`: an instance of `xlrd.sheet.Cell` class;
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`);
+ :param `display_text`: if Mark Hammonds' `pywin32` package is available,
+ this is the WYSIWYG cell content;
+ :param `hyperlink`: if this cell contains a hyperlink, it will be displayed
+ accordingly;
+ :param `default_width`: this is the default width of the text in 1/256
+ of the width of the zero character, using default Excel font (first FONT
+ record in the Excel file).
+
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
+ parameter will always be ``None`` as this feature is available only in
+ `xlrd` 0.7.2 (SVN).
+ """
+
+ XFClass = book.xf_list[xf_index]
+
+ font = book.font_list[XFClass.font_index]
+ self.font = self.CreateFont(font)
+
+ text_colour = book.colour_map[font.colour_index]
+ self.text_colour = self.CreateTextColour(text_colour)
+
+ if display_text is not None:
+ self.value = display_text
+ else:
+ format = book.format_map[XFClass.format_key]
+ self.CreateFormat(format, cell, book.datemode)
+
+ alignment = XFClass.alignment
+ self.CreateAlignment(alignment, default_width)
+
+ if hyperlink is not None:
+ self.SetupHyperlink(hyperlink)
+ else:
+ self.tooltip = None
+
+
+ def CreateFont(self, font):
+ """
+ Creates a suitable wxPython font starting from an Excel font.
+
+ :param `font`: an instance of `xlrd.formatting.Font` class.
+
+ :note: There is currently no support for strikethrough fonts, although
+ `xlrd` correctly reports this format. The issue is a bug in wxWidgets
+ itself which doesn't allow the creation of strikethrough fonts. See
+ (http://trac.wxwidgets.org/ticket/9907).
+ """
+
+ style, bold, underline = wx.FONTSTYLE_NORMAL, wx.NORMAL, False
+ if font.italic:
+ style = wx.FONTSTYLE_ITALIC
+ if font.underline_type > 0:
+ underline = True
+ if font.weight > 600:
+ bold = wx.BOLD
+
+ family = XF_FONT_FAMILY[font.family]
+ name = font.name
+ size = int(font.height/20.0)
+
+ if font.escapement_type > 0:
+ # subscript/superscript
+ size = int(size*0.7)
+
+ # No support for strike-through fonts in wxWidgets
+# if font.struck_out:
+# style = wx.FONTFLAG_DEFAULT
+# if bold:
+# style += wx.FONTFLAG_BOLD
+# if underline:
+# style += wx.FONTFLAG_UNDERLINED
+# if font.italic:
+# style += wx.FONTFLAG_ITALIC
+#
+# style += wx.FONTFLAG_STRIKETHROUGH
+# self.font = wx.FFont(size, family, style, name.encode())
+# else:
+
+ return wx.Font(size, family, style, bold, underline, name.encode())
+
+
+ def CreateTextColour(self, text_colour):
+ """
+ Creates a suitable wxPython colour for the text starting from a `xlrd`
+ tuple representing this colour.
+
+ :param `text_colour`: a tuple representing the RGB components of the
+ colour. If `text_colour` is ``None``, use the default ``wx.SYS_COLOUR_WINDOWTEXT``.
+ """
+
+ if text_colour is not None:
+ text_colour = wx.Colour(*text_colour)
+ else:
+ text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+
+ return text_colour
+
+
+ def CreateAlignment(self, alignment, default_width):
+ """
+ Creates a suitable wxPython alignment flag for the text starting from a
+ `xlrd` class representing this alignment.
+
+ :param `alignment`: an instance of `xlrd.formatting.XFAlignment` class;
+ :param `default_width`: this is the default width of the text in 1/256
+ of the width of the zero character, using default Excel font (first FONT
+ record in the Excel file).
+ """
+
+ hor_align, vert_align = alignment.hor_align, alignment.vert_align
+ self.horizontal_alignment = HORIZONTAL_ALIGNMENTS[hor_align]
+ self.vertical_alignment = VERTICAL_ALIGNMENTS[vert_align]
+
+ self.indent_level = alignment.indent_level
+ self.shrink_to_fit = alignment.shrink_to_fit
+ self.text_wrapped = alignment.text_wrapped
+
+ text_direction = 1
+
+ if alignment.text_direction == 0:
+ for char in self.value:
+ if char not in USELESS_CHARS:
+ if ord(char) in RTL_UNICODE:
+ text_direction = 2
+ break
+
+ self.text_direction = text_direction
+ self.default_width = default_width
+
+ if alignment.rotation > 90:
+ self.rotation = 90 - alignment.rotation
+ else:
+ self.rotation = alignment.rotation
+
+
+ def CreateFormat(self, format, cell, datemode):
+ """
+ This method tries to guess the best format to apply to the current text
+ value.
+
+ :param `format`: an instance of `xlrd.formatting.Format` class;
+ :param `cell`: an instance of `xlrd.sheet.Cell` class;
+ :param `datemode`: the datemode associated with this Excel workbook.
+
+ :note: This method is used only if Mark Hammonds' `pywin32` package is
+ not available to try and format the cell text in an intelligent way.
+
+ .. warning::
+
+ The formatting applied by this method is severely limited; for
+ instance, you won't probably get the exact WYSIWYG between the Excel
+ spreadsheet and :class:`XLSGrid`.
+ """
+
+ ctype, value = cell.ctype, cell.value
+
+ self.value = "%s"%value
+ isDate = False
+
+ if ctype == xlrd.XL_CELL_DATE:
+ value = xlrd.xldate_as_tuple(value, datemode)
+ isDate = True
+ elif ctype in [xlrd.XL_CELL_EMPTY, xlrd.XL_CELL_BLANK]:
+ return
+ elif ctype == xlrd.XL_CELL_TEXT:
+ self.value = "%s"%value
+ return
+ elif ctype == xlrd.XL_CELL_ERROR:
+ value = xlrd.error_text_from_code(ctype)
+ self.value = "%s"%value
+ return
+
+ self.FormatString(value, isDate, format.format_str)
+
+
+ def FormatString(self, value, isDate, format_str):
+ """
+ This method tries to guess the best format to apply to the current text
+ value.
+
+ :param `value`: the actual raw cell text value;
+ :param `isDate`: ``True`` if this value represents a `xlrd` date object,
+ ``False`` otherwise;
+ :param `format_str`: the actual formatting string as extracted from Excel.
+
+ :note: This method is used only if Mark Hammonds' `pywin32` package is
+ not available to try and format the cell text in an intelligent way.
+
+ .. warning::
+
+ The formatting applied by this method is severely limited; for
+ instance, you won't probably get the exact WYSIWYG between the Excel
+ spreadsheet and :class:`XLSGrid`.
+
+ """
+
+ if "General" in format_str:
+ self.value = "%s"%value
+ return
+
+ number_format = format_str
+ currency = percentage = ""
+
+ if not isDate:
+ symbol = ""
+ split = format_str.split()
+ if len(split) > 1:
+ # Accounting and currency shit
+ currency = split[0].split(".")[0] + "."
+ number_format = ".".join(split[1:])
+
+ if "%" in number_format:
+ percentage = "%"
+ value = 100*value
+ number_format = number_format[0:-1]
+
+ representation = "%d"
+ if "." in number_format:
+ split = number_format.split(".")
+ num_decimals = len(split[1])
+ representation = "%0." + str(num_decimals) + "f"
+
+ try:
+ value = representation%value
+ except ValueError:
+ # Fall back to string
+ value = unicode(value, "utf-8", "ignore")
+
+ if "#," in number_format:
+ value = SplitThousands(value)
+
+ value = currency + value + percentage
+
+ else:
+ number_format = format_str.replace("\\", "")
+ number_format = number_format.replace("-", "-%").replace("/", "/%")
+ value = datetime.datetime(*value)
+ try:
+ value = value.strftime(number_format)
+ except (ValueError, TypeError):
+ value = value.strftime("%d.%m.%Y")
+
+ self.value = value
+
+
+ def SetupHyperlink(self, hyperlink):
+ """
+ Sets up the cell text value in case it represents a hyperlink.
+
+ :param `hyperlink`: an instance of `xlrd.sheet.hyperlink`.
+
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
+ parameter will always be ``None`` as this feature is available only in
+ `xlrd` 0.7.2 (SVN).
+ """
+
+ url = (hyperlink.url_or_path and [hyperlink.url_or_path] or [hyperlink.textmark])[0]
+ self.tooltip = url
+
+
+ def IsHyperLink(self):
+ """
+ Returns whether the cell text is representing a hyperlink.
+
+ :returns: ``True`` if the cell text represents a hyperlink, ``False``
+ otherwise.
+ """
+
+ return self.tooltip is not None
+
+
+ def CombineAttr(self, attr):
+ """
+ Combines the input attribute `attr` with the features of the :class:`XLSText` class.
+
+ :param `attr`: an instance of :class:`grid.GridCellAttr`.
+ """
+
+ attr.SetAlignment(self.horizontal_alignment, self.vertical_alignment)
+ attr.SetTextColour(self.text_colour)
+ attr.SetFont(self.font)
+
+
+ def GetValue(self):
+ """ Returns the string representation of the cell text value. """
+
+ return self.value
+
+
+ def Draw(self, dc, rect):
+ """
+ Actually draws the text value on a grid cell.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the cell rectangle.
+ """
+
+ new_rect = wx.Rect(*rect)
+
+ xshift = yshift = 0
+ if self.rotation:
+ xshift = cos(self.rotation*pi/180)
+ yshift = sin(self.rotation*pi/180)
+
+ dc.SetTextForeground(self.text_colour)
+ dc.SetFont(self.font)
+
+ value = self.value
+ text_width, text_height = dc.GetTextExtent(value)
+
+ default_width = int(round(float(self.default_width)*text_width/256.0))
+
+ indentation = int(256.0*default_width/float(self.default_width))
+
+ if xshift == 0 and self.indent_level:
+ new_rect.SetLeft(new_rect.x + indentation)
+ else:
+ if self.horizontal_alignment == wx.ALIGN_LEFT:
+ new_rect.SetLeft(new_rect.x + 3)
+ elif self.horizontal_alignment == wx.ALIGN_RIGHT:
+ new_rect.SetWidth(new_rect.width - 1)
+
+ new_width = rect.width
+
+ if xshift > 0:
+ new_width = new_width/xshift
+
+ if self.shrink_to_fit:
+
+ font = FontFromFont(self.font)
+ point_size = font.GetPointSize()
+
+ while 1:
+ value = wordwrap(self.value, new_width, dc)
+ if "\n" not in value or point_size < 2:
+ break
+
+ point_size -= 1
+ font.SetPointSize(point_size)
+ dc.SetFont(font)
+
+ elif self.text_wrapped:
+
+ value = wordwrap(self.value, new_width, dc)
+ text_width, text_height, dummy = dc.GetMultiLineTextExtent(value)
+
+ if self.rotation:
+ if self.shrink_to_fit:
+ text_width, text_height = dc.GetTextExtent(value)
+
+ xc, yc = (rect.x+rect.width/2, rect.y+rect.height/2)
+ xp = xc - (text_width/2)*xshift - (text_height/2)*yshift
+ yp = yc + (text_width/2)*yshift - (text_height/2)*xshift
+
+ dc.DrawRotatedText(value, xp, yp, self.rotation)
+
+ else:
+
+ dc.DrawLabel(value, new_rect, self.horizontal_alignment|self.vertical_alignment)
+
+
+class XLSRichText(XLSText):
+ """
+ This is a class which holds information about the cell content, in terms
+ of actual cell value, font, text colour, alignment and formatting. In addition
+ to what :class:`XLSText` does, this class attempts to handle cells with rich text
+ content.
+ """
+
+ def __init__(self, book, cell, xf_index, display_text=None, hyperlink=None, rich_text=None, default_width=10):
+ """
+ Default class constructor.
+
+ :param `book`: an instance of the `xlrd.Book` class;
+ :param `cell`: an instance of `xlrd.sheet.Cell` class;
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`);
+ :param `display_text`: if Mark Hammonds' `pywin32` package is available,
+ this is the WYSIWYG cell content;
+ :param `hyperlink`: if this cell contains a hyperlink, it will be displayed
+ accordingly;
+ :param `rich_text`: if this cell contains text in rich text format, :class:`XLSGrid`
+ will do its best to render the text as rich text;
+ :param `default_width`: this is the default width of the text in 1/256
+ of the width of the zero character, using default Excel font (first FONT
+ record in the Excel file).
+
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
+ parameter will always be ``None`` as this feature is available only in
+ `xlrd` 0.7.2 (SVN).
+
+ :note: If you are using version 0.7.1 or lower for `xlrd`, this class will
+ note be used by :class:`XLSGrid`.
+
+ .. warning::
+
+ This class currently supports only single-line non-rotated text,
+ and it discards properties like `shrink-to-fit` and `wrapping`.
+
+ """
+
+ XLSText.__init__(self, book, cell, xf_index, display_text, hyperlink, default_width)
+
+ self.BuildChunks(book, xf_index, rich_text)
+
+
+ def BuildChunks(self, book, xf_index, rich_text):
+ """
+ Splits the cell content accordingly to their rich text format index.
+
+ :param `book`: an instance of the `xlrd.Book` class;
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`);
+ :param `rich_text`: if this cell contains text in rich text format, :class:`XLSGrid`
+ will do its best to render the text as rich text.
+ """
+
+ XFClass = book.xf_list[xf_index]
+ offset, index = rich_text[0]
+
+ if offset != 0:
+ new_tuple = (0, XFClass.font_index)
+ rich_text.insert(0, new_tuple)
+
+ value = self.value
+ rich_text.append((len(value), rich_text[-1][1]))
+ attributes = []
+
+ for indx in xrange(len(rich_text)-1):
+ offset_start, index_start = rich_text[indx]
+ offset_end, index_end = rich_text[indx+1]
+
+ chunk = value[offset_start:offset_end]
+
+ font = book.font_list[index_start]
+ ffont = self.CreateFont(font)
+ text_colour = book.colour_map[font.colour_index]
+ colour = self.CreateTextColour(text_colour)
+
+ ffont.escapement = font.escapement_type
+ attributes.append([chunk, ffont, colour])
+
+ self.attributes = attributes
+
+
+ def Measure(self, dc):
+ """
+ Convenience method to measure the maximum height and total width of all
+ the chunks of text composing our rich text string.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ maxH = -1
+ full_width = 0
+ for chunk, font, colour in self.attributes:
+ dc.SetFont(font)
+ width, height, descent, leading = dc.GetFullTextExtent(chunk, font)
+ maxH = max(maxH, height-leading)
+ full_width += width
+
+ return maxH, full_width
+
+
+ def Draw(self, dc, rect):
+ """
+ Actually draws all the chunks of text on a grid cell, one by one.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the cell rectangle.
+ """
+
+ new_rect = wx.Rect(*rect)
+
+ text_width, text_height = dc.GetTextExtent(self.value)
+ default_width = int(round(float(self.default_width)*text_width/256.0))
+ indentation = int(256.0*default_width/float(self.default_width))
+
+ maxH, full_width = self.Measure(dc)
+
+ if self.indent_level:
+ new_rect.SetLeft(new_rect.x + indentation)
+ else:
+ if self.horizontal_alignment == wx.ALIGN_LEFT:
+ new_rect.SetLeft(new_rect.x + 3)
+ elif self.horizontal_alignment == wx.ALIGN_RIGHT:
+ new_rect.SetLeft(new_rect.x + (new_rect.width - full_width) - 1)
+ else:
+ space = int((new_rect.width - full_width)/2.0)
+ new_rect.SetLeft(new_rect.x + space)
+ new_rect.SetWidth(full_width+space)
+
+ if self.vertical_alignment == wx.ALIGN_TOP:
+ vspace = 0
+ elif self.vertical_alignment == wx.ALIGN_BOTTOM:
+ vspace = (new_rect.height - maxH - 1)
+ else:
+ vspace = int((new_rect.height - maxH)/2.0)
+
+ start = new_rect.x
+ y = new_rect.y
+
+ for chunk, font, colour in self.attributes:
+ dc.SetTextForeground(colour)
+ dc.SetFont(font)
+ width, height, descent, leading = dc.GetFullTextExtent(chunk, font)
+ if font.escapement > 0:
+ height = height*0.7
+
+ ypos = y-height+maxH+vspace
+
+ if font.escapement == 1:
+ ypos = ypos - maxH + height
+
+ dc.DrawText(chunk, start, ypos)
+ start += width
+
+
+class XLSBackground(object):
+ """
+ This is a class which holds information about the cell background, in terms
+ of background colour and background pattern (hatching).
+ """
+
+ def __init__(self, book, xf_index):
+ """
+ Default class constructor.
+
+ :param `book`: an instance of the `xlrd.Book` class;
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`).
+ """
+
+ XFClass = book.xf_list[xf_index]
+
+ background = XFClass.background
+ background_colour = book.colour_map[background.background_colour_index]
+ pattern_colour = book.colour_map[background.pattern_colour_index]
+ fill_pattern = background.fill_pattern
+
+ self.CreateBackgroundColour(background_colour, pattern_colour, fill_pattern)
+
+
+ def CreateBackgroundColour(self, background_colour, pattern_colour, fill_pattern):
+ """
+ Creates a suitable wxPython colour for the cell background starting from
+ a `xlrd` tuple representing this colour.
+
+ :param `background_colour`: a tuple representing the RGB components of the
+ cell background colour. If `background_colour` is ``None``, use the
+ default ``wx.SYS_COLOUR_WINDOW``;
+ :param `pattern_colour`: a tuple representing the RGB components of the
+ cell pattern colour;
+ :param `fill_pattern`: the pattern to use to draw hatches on top of the
+ background.
+ """
+
+ if background_colour is not None:
+ background_colour = wx.Colour(*background_colour)
+ else:
+ background_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
+
+ if pattern_colour is not None:
+ pattern_colour = wx.Colour(*pattern_colour)
+
+ self.background_brush = wx.Brush(background_colour)
+ self.background_colour = background_colour
+
+ self.fill_brush = None
+
+ if fill_pattern <= 0:
+ return
+
+ r, g, b = pattern_colour
+
+ fill_image = eval("_xls_background_%02d.GetImage()"%fill_pattern)
+ fill_image.Replace(0, 0, 0, r, g, b)
+ r, g, b = background_colour.Red(), background_colour.Green(), background_colour.Blue()
+ fill_image.Replace(255, 255, 255, r, g, b)
+ fill_bitmap = fill_image.ConvertToBitmap()
+
+ self.fill_brush = wx.BrushFromBitmap(fill_bitmap)
+
+
+ def CombineAttr(self, attr):
+ """
+ Combines the input attribute `attr` with the features of the :class:`XLSBackground` class.
+
+ :param `attr`: an instance of :class:`grid.GridCellAttr`.
+ """
+
+ attr.SetBackgroundColour(self.background_colour)
+ return attr
+
+
+ def Draw(self, dc, rect):
+ """
+ Actually draws the cell background and pattern hatching on a grid cell.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the cell rectangle.
+ """
+
+ dc.SetClippingRect(rect)
+
+ dc.SetBackgroundMode(wx.SOLID)
+ dc.SetBrush(self.background_brush)
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.DrawRectangleRect(rect)
+
+ if self.fill_brush:
+
+ dc.SetBrush(self.fill_brush)
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ dc.DrawRectangleRect(rect)
+
+ dc.DestroyClippingRegion()
+
+
+class XLSBorder(object):
+ """
+ This is a class which holds information about a single cell border, in terms
+ of its location (top, left, bottom, right, diagonal), its colour, width and
+ shape.
+ """
+
+ def __init__(self, location, line_style, border_colour, default_colour, diagonals):
+ """
+ Default class constructor.
+
+ :param `location`: the actual border location (top, left, bottom, right,
+ diagonal);
+ :param `line_style`: the line style used by Excel to draw this border;
+ :param `border_colour`: the colour used by Excel to draw this border;
+ :param `default_colour`: the "magic" colour used by Excel to draw non-custom
+ border lines;
+ :param `diagonals`: a tuple containing whether or not to draw the up and down
+ diagonal borders.
+ """
+
+ self.draw_priority = 2
+
+ if line_style == NO_LINE:
+
+ if border_colour == (0, 0, 0):
+ self.draw_priority = 0
+ border_colour = wx.Colour(*default_colour)
+ else:
+ self.draw_priority = 1
+ border_colour = wx.BLACK
+
+ self.pen = wx.Pen(border_colour, 1, wx.SOLID)
+ pen_style = THIN
+
+ else:
+
+ if border_colour == (0, 0, 0):
+ border_colour = wx.Colour(*default_colour)
+ self.draw_priority = 2
+ elif border_colour is None:
+ border_colour = wx.BLACK
+ self.draw_priority = 2
+ else:
+ border_colour = wx.Colour(*border_colour)
+
+ pen_width, pen_style = XF_PEN_STYLES[line_style]
+ if pen_width > 2:
+ self.draw_priority = 4
+ elif pen_width > 1:
+ self.draw_priority = 3
+
+ self.pen = wx.Pen(border_colour, pen_width, pen_style)
+
+ self.diagonals = diagonals
+ self.location = location
+ self.pen_style = pen_style
+ self.line_style = line_style
+
+
+ def Draw(self, dc, rect):
+ """
+ Actually draws the cell border.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the cell rectangle.
+ """
+
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ dc.SetPen(self.pen)
+
+ if self.location == DIAGONAL:
+ self.DrawDiagonals(dc, rect)
+ else:
+ self.DrawBorder(dc, rect)
+
+
+ def DrawDiagonals(self, dc, rect):
+ """
+ Actually draws the cell diagonal border.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the cell rectangle.
+ """
+
+ diag_up, diag_down = self.diagonals
+
+ if diag_down:
+ xstart, ystart = rect.GetTopLeft()
+ xend, yend = rect.GetBottomRight()
+
+ if self.line_style == DOUBLE:
+ dc.DrawLine(xstart+2, ystart, xend, yend-2)
+ dc.DrawLine(xstart, ystart+2, xend-2, yend)
+ else:
+ dc.DrawLine(xstart, ystart, xend, yend)
+
+ if diag_up:
+
+ xstart, ystart = rect.GetBottomLeft()
+ xend, yend = rect.GetTopRight()
+
+ if self.line_style == DOUBLE:
+ dc.DrawLine(xstart, ystart-2, xend-2, yend)
+ dc.DrawLine(xstart+2, ystart, xend, yend+2)
+ else:
+ dc.DrawLine(xstart, ystart, xend, yend)
+
+
+ def DrawBorder(self, dc, rect):
+ """
+ Actually draws the cell border (one of left, right, bottom, top).
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the cell rectangle.
+ """
+
+ pen_width = self.pen.GetWidth()
+ location = self.location
+ new_rect = wx.Rect(*rect)
+
+ x, y, w, h = new_rect
+ line_style = self.line_style
+
+ shift = 0
+ if pen_width == 2:
+ shift = pen_width - 1
+ if pen_width > 2:
+ shift = pen_width - 2
+
+ if location == BOTTOM:
+
+ if self.draw_priority < 2:
+ return
+
+ if line_style == DOUBLE:
+ dc.DrawLine(x, y+h-1, x+w, y+h-1)
+ dc.DrawLine(x, y+h+1, x+w, y+h+1)
+ else:
+ dc.DrawLine(x+1, y+h, x+w, y+h)
+
+
+ elif location == TOP:
+
+ if line_style == DOUBLE:
+ dc.DrawLine(x, y-1, x+w, y-1)
+ dc.DrawLine(x, y+1, x+w, y+1)
+ else:
+ dc.DrawLine(x+1, y+shift, x+w, y+shift)
+
+ elif location == LEFT:
+
+ if line_style == DOUBLE:
+ dc.DrawLine(x-1, y, x-1, y+h)
+ dc.DrawLine(x+1, y, x+1, y+h)
+ else:
+ dc.DrawLine(x+shift, y+1, x+shift, y+h)
+
+ elif location == RIGHT:
+
+ if self.draw_priority < 2:
+ return
+
+ if line_style == DOUBLE:
+ dc.DrawLine(x+w-1, y, x+w-1, y+h)
+ dc.DrawLine(x+w+1, y, x+w+1, y+h)
+ else:
+ dc.DrawLine(x+w+1, y+1, x+w+1, y+h)
+
+
+class XLSBorderFactory(object):
+ """
+ This is a factory class which holds information about all the borders in a
+ cell. Its implementation and use is merely to simplify the handling of the
+ different cell borders (left, top, bottom, right, diagonal).
+ """
+
+ def __init__(self, book, border, default_colour):
+ """
+ Default class constructor.
+
+ :param `book`: an instance of the `xlrd.Book` class;
+ :param `border`: an instance of `xlrd.formatting.XFBorder` class;
+ :param `default_colour`: the "magic" colour used by Excel to draw non-custom
+ border lines.
+ """
+
+ borders = {}
+ diagonals = border.diag_up, border.diag_down
+
+ for label, location in XF_BORDER_STYLES.items():
+ line_style = getattr(border, "%s_line_style"%label)
+ colour_index = getattr(border, "%s_colour_index"%label)
+ border_colour = book.colour_map[colour_index]
+
+ border_class = XLSBorder(location, line_style, border_colour, default_colour, diagonals)
+ borders[location] = border_class
+
+ self.draw_priority = sorted(borders.values(), key=attrgetter('draw_priority'))
+
+
+ def Draw(self, dc, rect):
+ """
+ Actually draws all the cell borders based on their drawing priority.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the cell rectangle.
+
+ :note: The drawing priority is assigned depending on if the border is a
+ custom one or not. Customized borders are drawn last.
+ """
+
+ for border in self.draw_priority:
+ border.Draw(dc, rect)
+
+
+class XLSComment(object):
+ """
+ This is a class which holds information about the content of the "comment
+ window" (aka note) in Excel.
+
+ :note: If Mark Hammonds' `pywin32` package is not available, this class can
+ not be used.
+ """
+
+ def __init__(self, comment):
+ """
+ Default class constructor.
+
+ :param `comment`: the actual text contained in the Excel cell comment (note).
+ """
+
+ self.comment = comment
+
+
+ def Draw(self, dc, rect):
+ """
+ Actually draws a small red triangle in the top-right corder of the cell
+ to indicate that a comment is present.
+
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the cell rectangle.
+ """
+
+ right = rect.GetTopRight()
+ points = [wx.Point(right.x-5, right.y),
+ right,
+ wx.Point(right.x, right.y+5)]
+
+ dc.SetBrush(wx.RED_BRUSH)
+ dc.SetPen(wx.RED_PEN)
+ dc.DrawPolygon(points)
+
+
+class XLSCell(object):
+ """
+ This is a class which holds information about a single cell in :class:`XLSGrid`.
+ It stores (via auxiliary classes), all details about cell background, text,
+ font, colours and borders.
+ """
+
+ def __init__(self, book, cell, xf_index, xls_text, xls_comment, hyperlink, rich_text, default_width, default_colour):
+ """
+ Default class constructor.
+
+ :param `book`: an instance of the `xlrd.Book` class;
+ :param `cell`: an instance of `xlrd.sheet.Cell` class;
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`);
+ :param `xls_text`: the actual WYSIWYG cell text, if available;
+ :param `xls_comment`: the cell comment (note), if any;
+ :param `hyperlink`: an instance of `xlrd.sheet.hyperlink`;
+ :param `rich_text`: if this cell contains text in rich text format, :class:`XLSGrid`
+ will do its best to render the text as rich text;
+ :param `default_width`: this is the default width of the text in 1/256
+ of the width of the zero character, using default Excel font (first FONT
+ record in the Excel file);
+ :param `default_colour`: the "magic" colour used by Excel to draw non-custom
+ border lines.
+
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
+ parameter will always be ``None`` as this feature is available only in
+ `xlrd` 0.7.2 (SVN).
+
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the `rich_text`
+ parameter will always be ``None`` as this feature is available only in
+ `xlrd` 0.7.2 (SVN).
+
+ :note: if Mark Hammonds' `pywin32` package is not available, the `xls_text`
+ parameter will almost surely not be the WYSIWYG representation of the cell
+ text.
+
+ :note: If Mark Hammonds' `pywin32` package is not available, the `xls_comment`
+ parameter will always be ``None``.
+ """
+
+ self.size = 1, 1
+
+ self.comment = None
+ self.hyperlink = None
+
+ self.SetupCell(book, cell, xf_index, xls_text, xls_comment, hyperlink, rich_text, default_width, default_colour)
+
+
+ def SetupCell(self, book, cell, xf_index, xls_text, xls_comment, hyperlink, rich_text, default_width, default_colour):
+ """
+ Actually sets up the :class:`XLSCell` class. This is an auxiliary method to
+ avoid cluttering the :meth:`~xlsgrid.XLSCell.__init__` method.
+
+ :param `book`: an instance of the `xlrd.Book` class;
+ :param `cell`: an instance of `xlrd.sheet.Cell` class;
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`);
+ :param `xls_text`: the actual WYSIWYG cell text, if available;
+ :param `xls_comment`: the cell comment (note), if any;
+ :param `hyperlink`: an instance of `xlrd.sheet.hyperlink`;
+ :param `rich_text`: if this cell contains text in rich text format, :class:`XLSGrid`
+ will do its best to render the text as rich text;
+ :param `default_width`: this is the default width of the text in 1/256
+ of the width of the zero character, using default Excel font (first FONT
+ record in the Excel file);
+ :param `default_colour`: the "magic" colour used by Excel to draw non-custom
+ border lines.
+
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
+ parameter will always be ``None`` as this feature is available only in
+ `xlrd` 0.7.2 (SVN).
+
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the `rich_text`
+ parameter will always be ``None`` as this feature is available only in
+ `xlrd` 0.7.2 (SVN).
+
+ :note: if Mark Hammonds' `pywin32` package is not available, the `xls_text`
+ parameter will almost surely not be the WYSIWYG representation of the cell
+ text.
+
+ :note: If Mark Hammonds' `pywin32` package is not available, the `xls_comment`
+ parameter will always be ``None``.
+ """
+
+ cvalue = cell.value
+ self.raw_value = cvalue
+
+ if rich_text:
+ self.text = XLSRichText(book, cell, xf_index, xls_text, hyperlink, rich_text, default_width)
+ else:
+ self.text = XLSText(book, cell, xf_index, xls_text, hyperlink, default_width)
+
+ self.background = XLSBackground(book, xf_index)
+
+ XFClass = book.xf_list[xf_index]
+ border = XFClass.border
+
+ self.borders = XLSBorderFactory(book, border, default_colour)
+
+ if xls_comment:
+ self.comment = XLSComment(xls_comment)
+
+ self.attr = None
+
+
+ def GetAttr(self):
+ """
+ Returns the attribute to use for this specific cell.
+
+ :returns: an instance of :class:`grid.GridCellAttr`.
+ """
+
+ if self.attr is not None:
+ self.attr.IncRef()
+ return self.attr
+
+ attr = gridlib.GridCellAttr()
+
+ attr.SetRenderer(XLSRenderer(self))
+
+ attr.SetSize(*self.size)
+ attr.SetOverflow(True)
+ self.attr = attr
+ self.attr.IncRef()
+
+ return self.attr
+
+
+ def GetValue(self):
+ """ Returns the actual WYSIWYG representation of the cell value. """
+
+ return self.text.GetValue()
+
+
+ def SetValue(self, value):
+ """
+ Sets the actual WYSIWYG representation of the cell value.
+
+ :param `value`: the current text value to insert in the cell.
+
+ :note: This method is currently unused as everything is handled inside the :class:`XLSText` class.
+
+ :see: :meth:`~xlsgrid.XLSCell.GetValue`
+ """
+
+ self.value = value
+
+
+ def SetCellSize(self, rows, cols):
+ """
+ Sets the size of the cell.
+
+ Specifying a value of more than 1 in `rows` or `cols` will make the cell
+ at (`row`, `col`) span the block of the specified size, covering the other
+ cells which would be normally shown in it. Passing 1 for both arguments
+ resets the cell to normal appearance.
+
+ :param `rows`: number of rows to be occupied by this cell, must be >= 1;
+ :param `cols`: number of columns to be occupied by this cell, must be >= 1.
+ """
+
+ self.size = (rows, cols)
+
+
+ def GetComment(self):
+ """
+ Returns the cell comment, if any.
+
+ :returns: an instance of :class:`XLSComment`.
+
+ :note: If Mark Hammonds' `pywin32` package is not available, this method
+ always returns ``None``.
+ """
+
+ return self.comment
+
+
+class XLSRenderer(gridlib.PyGridCellRenderer):
+ """
+ This class is responsible for actually drawing the cell in the grid.
+
+ """
+
+ def __init__(self, cell):
+ """
+ Default class constructor.
+
+ :param `cell`: an instance of :class:`XLSCell`.
+ """
+
+ gridlib.PyGridCellRenderer.__init__(self)
+ self.cell = cell
+
+
+ def Draw(self, grid, attr, dc, rect, row, col, isSelected):
+ """
+ Draw the given cell on the provided `dc` inside the given rectangle using
+ default or selected state corresponding to the `isSelected` value.
+
+ :param `grid`: an instance of :class:`grid.Grid`;
+ :param `attr`: an instance of :class:`grid.GridCellAttr`;
+ :param `dc`: an instance of :class:`DC`;
+ :param `rect`: an instance of :class:`Rect`, representing the cell rectangle;
+ :param `row`: the row in which this cell lives;
+ :param `col`: the column in which this cell lives;
+ :param `isSelected`: ``True`` if the cell is selected, ``False`` otherwise.
+ """
+
+ # clear the background
+ dc.SetBackgroundMode(wx.SOLID)
+
+ cell = self.cell
+
+ cell.background.Draw(dc, rect)
+
+ if cell.borders:
+ cell.borders.Draw(dc, rect)
+
+ cell.text.Draw(dc, rect)
+
+ if cell.comment:
+ cell.comment.Draw(dc, rect)
+
+ if isSelected:
+
+ gdc = wx.GCDC(dc)
+
+ sys_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ brush_colour = wx.Colour(sys_colour.Red(), sys_colour.Green(), sys_colour.Blue(), 90)
+
+ gdc.SetBrush(wx.Brush(brush_colour))
+ gdc.SetPen(wx.TRANSPARENT_PEN)
+
+ gdc.DrawRectangleRect(rect)
+
+
+class XLSTable(gridlib.PyGridTableBase):
+ """
+ The almost abstract base class for grid tables.
+
+ A grid table is responsible for storing the grid data and, indirectly, grid
+ cell attributes. The data can be stored in the way most convenient for the
+ application but has to be provided in string form to :class:`grid.Grid`.
+ """
+
+ def __init__(self, grid, cells, rows, cols):
+ """
+ Default class constructor.
+
+ :param `grid`: an instance of :class:`grid.Grid`;
+ :param `cells`: a Python dictionary. For every key `(row, col)`, the
+ corresponding value is an instance of :class:`XLSCell`;
+ :param `rows`: the number of rows in the table;
+ :param `cols`: the number of columns in the table.
+ """
+
+ # The base class must be initialized *first*
+ gridlib.PyGridTableBase.__init__(self)
+
+ self.cells = cells
+ self.dimens = (rows, cols)
+
+
+ def GetNumberCols(self):
+ """ Returns the number of columns in the table. """
+
+ return self.dimens[1]
+
+
+ def GetNumberRows(self):
+ """ Returns the number of rows in the table. """
+
+ return self.dimens[0]
+
+
+ def GetValue(self, row, col):
+ """
+ Returns the cell content for the specified row and column.
+
+ :param `row`: the row in which this cell lives;
+ :param `col`: the column in which this cell lives.
+ """
+
+ cell = self.cells[(row, col)]
+ return cell.GetValue()
+
+
+ def SetValue(self, row, col, value):
+ """
+ sets the cell content for the specified row and column.
+
+ :param `row`: the row in which this cell lives;
+ :param `col`: the column in which this cell lives;
+ :param `value`: the new value to assign to the specified cell.
+ """
+
+ cell = self.cells[(row, col)]
+ cell.SetValue(value)
+
+
+ def GetAttr(self, row, col, kind):
+ """
+ Return the attribute for the given cell.
+
+ :param `row`: the row in which this cell lives;
+ :param `col`: the column in which this cell lives;
+ :param `kind`: the kind of the attribute to return.
+ """
+
+ cell = self.cells[(row, col)]
+ return cell.GetAttr()
+
+
+ def GetRawValue(self, row, col):
+ """
+ Returns the "raw" value for the cell content.
+
+ :param `row`: the row in which this cell lives;
+ :param `col`: the column in which this cell lives.
+ """
+
+ cell = self.cells[(row, col)]
+ return cell.raw_value
+
+
+class XLSGrid(gridlib.Grid):
+ """
+ :class:`XLSGrid` is a class based on :class:`grid.Grid` that can be used to faithfully
+ reproduce the appearance of a Microsoft Excel spreadsheet (one worksheet per
+ every instance of :class:`XLSGrid`).
+
+ :class:`XLSGrid` is a completely owner-drawn control, and it relies on the power of
+ :class:`grid.PyGridTableBase` and :class:`grid.PyGridCellRenderer` to draw the cell
+ content. For this reasons (and for some others, see the TODOs section), it will
+ work efficiently only for relatively small Excel files.
+ """
+
+ def __init__(self, parent):
+ """
+ Default class constructor.
+
+ :param `parent`: the grid parent window. Must not be ``None``.
+ """
+
+ gridlib.Grid.__init__(self, parent)
+
+ self.SetMargins(0, 0)
+ self.SetDefaultCellBackgroundColour(parent.GetBackgroundColour())
+ self.SetDefaultCellOverflow(True)
+
+ self.tip_window = None
+ self.tip_shown = False
+
+
+ def DestroyTip(self):
+ """
+ If a comment window or a tooltip over a hyperlink have been created, this
+ method destroys them.
+ """
+
+ if self.tip_window:
+ try:
+ self.tip_window.GetTipWindow().Destroy()
+ except wx.PyDeadObjectError:
+ pass
+
+ del self.tip_window
+ self.tip_window = None
+
+ if self.tip_shown:
+ self.GetGridWindow().SetToolTipString("")
+ self.GetGridWindow().SetCursor(wx.NullCursor)
+ self.tip_shown = False
+
+
+ def InstallGridHint(self):
+ """
+ Auxiliary method used to bind a ``wx.EVT_MOTION`` event to :class:`XLSGrid`.
+ """
+
+ self.prev_rowcol = [None, None]
+
+ def OnMouseMotion(event):
+ """
+ Handles a the ``wx.EVT_MOTION`` events for :class:`XLSGrid`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ # evt.GetRow() and evt.GetCol() would be nice to have here,
+ # but as this is a mouse event, not a grid event, they are not
+ # available and we need to compute them by hand.
+ position = event.GetPosition()
+ x, y = self.CalcUnscrolledPosition(position)
+ row = self.YToRow(y)
+ col = self.XToCol(x)
+
+ if [row, col] != self.prev_rowcol and row >= 0 and col >= 0:
+
+ self.prev_rowcol[:] = [row, col]
+ self.DestroyTip()
+ cell = self.cells[(row, col)]
+ rect = self.CellToRect(row, col)
+ comment = cell.GetComment()
+
+ window = self.GetGridWindow()
+ if cell.text.IsHyperLink():
+ window.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+ window.SetToolTipString(cell.text.tooltip)
+ self.tip_shown = True
+ if not comment:
+ return
+
+ if comment:
+ self.tip_window = TransientPopup(window, comment, wx.GetMousePosition())
+ event.Skip()
+
+ self.GetGridWindow().Bind(wx.EVT_MOTION, OnMouseMotion)
+
+
+ def PopulateGrid(self, book, sheet, display_texts, comments):
+ """
+ This is the main method of this class, and it is used to actually create
+ the cells, size the columns and rows, merging cells, etc...
+
+ :param `book`: an instance of the `xlrd.Book` class;
+ :param `sheet`: an instance of the `xlrd.sheet` class;
+ :param `display_texts`: if Mark Hammonds' `pywin32` package is available,
+ this is the WYSIWYG cell content for all the cells in the Excel worksheet;
+ :param `comments`: if Mark Hammonds' `pywin32` package is available,
+ this is a nested list of cell comments (notes) for all the cells in the
+ Excel worksheet.
+ """
+
+ self.BeginBatch()
+
+ nrows = sheet.nrows
+ ncols = sheet.ncols
+
+ default_width, default_height = self.GetDefaultFontData(book)
+ default_colour = self.GetGridLineColour()
+
+ hyperlinks, rich_text_list = {}, {}
+ if hasattr(sheet, "hyperlink_map"):
+ # New in xlrd version 0.7.2 from SVN
+ hyperlinks = sheet.hyperlink_map
+
+ if hasattr(sheet, "rich_text_runlist_map"):
+ # New in xlrd version 0.7.2 from SVN
+ rich_text_list = sheet.rich_text_runlist_map
+
+ self.cells = {}
+
+ for i in xrange(nrows):
+
+ for j in xrange(ncols):
+
+ hyperlink = rich_text = None
+
+ if (i, j) in hyperlinks:
+ hyperlink = hyperlinks[(i, j)]
+ if (i, j) in rich_text_list:
+ rich_text = rich_text_list[(i, j)]
+
+ self.FormatCell(book, sheet, i, j, display_texts, comments, hyperlink, rich_text, default_width, default_colour)
+
+ self.table = XLSTable(self, self.cells, nrows, ncols)
+ self.SetTable(self.table)
+
+ row_height = sheet.default_row_height
+ col_width = sheet.defcolwidth
+
+ for i in xrange(nrows):
+ if i in sheet.rowinfo_map:
+ current = sheet.rowinfo_map[i].height
+ else:
+ current = sheet.default_row_height
+
+ row_height = int(round(float(default_height)*current/256.0))
+ self.SetRowSize(i, row_height)
+
+ for j in xrange(ncols):
+ if j in sheet.colinfo_map:
+ current = sheet.colinfo_map[j].width
+ else:
+ current = sheet.defcolwidth
+
+ #col_width = int(round(float(default_width)*current/256.0))
+ if current is not None:
+ col_width = int (round (float (default_width) * current/256.0))
+ else:
+ col_width = 20 # Set a fixed size for cell
+ self.SetColSize(j, col_width)
+
+ for merged in sheet.merged_cells:
+ rlo, rhi, clo, chi = merged
+ if rlo >= 0 and rlo < len(self.cells) and clo >= 0:
+ self.cells[(rlo, clo)].SetCellSize(rhi-rlo, chi-clo)
+
+ self.EnableEditing(False)
+ self.EnableGridLines(False)
+ self.EndBatch()
+ self.ForceRefresh()
+ self.InstallGridHint()
+
+
+ def FormatCell(self, book, sheet, row, col, display_texts, comments, hyperlink, rich_text, default_width, default_colour):
+ """
+ Processes the creation of a single cell (an instance of :class:`XLSCell`).
+
+ :param `book`: an instance of the `xlrd.Book` class;
+ :param `sheet`: an instance of the `xlrd.sheet` class;
+ :param `row`: the row in which this cell lives;
+ :param `col`: the column in which this cell lives;
+ :param `display_texts`: if Mark Hammonds' `pywin32` package is available,
+ this is the WYSIWYG cell content for all the cells in the Excel worksheet;
+ :param `comments`: if Mark Hammonds' `pywin32` package is available,
+ this is a nested list of cell comments (notes) for all the cells in the
+ Excel worksheet;
+ :param `hyperlink`: if this cell contains a hyperlink, it will be displayed
+ accordingly;
+ :param `rich_text`: if this cell contains text in rich text format, :class:`XLSGrid`
+ will do its best to render the text as rich text;
+ :param `default_width`: this is the default width of the text in 1/256
+ of the width of the zero character, using default Excel font (first FONT
+ record in the Excel file);
+ :param `default_colour`: the "magic" colour used by Excel to draw non-custom
+ border lines.
+
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
+ parameter will always be ``None`` as this feature is available only in
+ `xlrd` 0.7.2 (SVN).
+
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the `rich_text`
+ parameter will always be ``None`` as this feature is available only in
+ `xlrd` 0.7.2 (SVN).
+
+ :note: If Mark Hammonds' `pywin32` package is not available, the `display_texts`
+ and `comments` parameter will be two empty nested lists.
+ """
+
+ cell = sheet.cell(row, col)
+
+ xf_index = sheet.cell_xf_index(row, col)
+ xls_text, xls_comment = display_texts[row][col], comments[row][col]
+
+ gridCell = XLSCell(book, cell, xf_index, xls_text, xls_comment, hyperlink, rich_text, default_width, default_colour)
+
+ self.cells[(row, col)] = gridCell
+
+
+ def GetDefaultFontData(self, book):
+ """
+ Returns suitable width and height (in pixels) starting from Excel's own
+ measurements (in characters, whatever that means).
+
+ :param `book`: an instance of the `xlrd.Book` class.
+
+ :returns: a `default_width` and `default_height` in pixels, based on the
+ default width of the text in 1/256 of the width of the zero character,
+ using default Excel font (first FONT record in the Excel file).
+ """
+
+ font = book.font_list[0]
+ style, bold, underline = wx.FONTSTYLE_NORMAL, wx.NORMAL, False
+
+ if font.italic:
+ style = wx.FONTSTYLE_ITALIC
+ if font.underline_type > 0:
+ underline = True
+ if font.weight > 600:
+ bold = wx.BOLD
+
+ family = XF_FONT_FAMILY[font.family]
+ name = font.name
+ size = int(font.height/20.0)
+
+ dc = wx.ClientDC(self)
+ font = wx.Font(size, family, style, bold, underline, name.encode())
+ dc.SetFont(font)
+ width, height, descent, leading = dc.GetFullTextExtent("0", font)
+
+ return width, height + descent - leading
+
+
+class TransientPopup(STT.SuperToolTip):
+ """
+ This is a sublass of :class:`SuperToolTip` and it is used to display a
+ "comment-window" on the cells containing a comment (a note).
+
+ :note: If Mark Hammonds' `pywin32` package is not available, this class is
+ never invoked.
+ """
+
+ def __init__(self, grid_window, comment, position):
+ """
+ Default class constructor.
+
+ :param `grid_window`: the actual window representing the grid;
+ :param `comment`: an instance of :class:`XLSComment`, containing the
+ text for this comment;
+ :param `position`: the position at which we pop up the comment
+ window (currently unused).
+ """
+
+ STT.SuperToolTip.__init__(self, grid_window)
+
+ xls_comment = comment.comment
+
+ split = xls_comment.split(":")
+ header, rest = split[0], split[1:]
+ rest = ":".join(rest)
+
+ dc = wx.ClientDC(grid_window)
+ rest = wordwrap(rest, 400, dc)
+
+ self.SetHeader(header)
+ self.SetMessage(rest)
+ self.SetTarget(grid_window)
+ self.SetDrawHeaderLine(True)
+
+ self.SetStartDelay(100000)
+ self.SetEndDelay(100000)
+ self.ApplyStyle("Office 2007 Blue")
+
+ self.SetDropShadow(True)
+ self.DoShowNow()
+
+ grid_window.SetFocus()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/zoombar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/zoombar.py
new file mode 100644
index 0000000..f9b5bad
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/agw/zoombar.py
@@ -0,0 +1,1316 @@
+"""
+:class:`ZoomBar` is a class that *appoximatively* mimics the behaviour of the Mac Dock,
+inside a :class:`Panel`.
+
+
+Description
+===========
+
+:class:`ZoomBar` is a class that *appoximatively* mimics the behaviour of the Mac Dock,
+inside a :class:`Panel`.
+
+Once you hover mouse over the :class:`ZoomBar` correct button will bubble up, grow to
+predefined size, so you can easily see the button you are about to click and
+have larger area to click. Difference this makes is amazing.
+
+The buttons are able to be zoomed from the bottom up (bottom fixed) as well
+as to zoom from a central point. Also the container is able to move the
+remaining buttons around the zoomed button.
+
+
+Usage
+=====
+
+Usage example::
+
+ import os
+ import random
+ import glob
+
+ import wx
+ import wx.lib.agw.zoombar as ZB
+
+ class MyFrame(wx.Frame):
+
+ def __init__(self, parent):
+
+ wx.Frame.__init__(self, parent, -1, "ZoomBar Demo")
+
+ panel = wx.Panel(self)
+
+ bar = ZB.ZoomBar(panel, -1)
+
+ standard = glob.glob(bitmapDir + "/*96.png")
+ reflections = glob.glob(bitmapDir + "/*96Flip40.png")
+
+ separatorImage = bitmapDir + "/separator.gif"
+ separatorReflection = bitmapDir + "/separatorFlip.png"
+ count = 0
+
+ for std, ref in zip(standard, reflections):
+ if random.randint(0, 1) == 1 and count > 0:
+ sep1 = wx.Bitmap(separatorImage, wx.BITMAP_TYPE_GIF)
+ sep2 = wx.Bitmap(separatorReflection, wx.BITMAP_TYPE_PNG)
+ bar.AddSeparator(sep1, sep2)
+
+ bname = os.path.split(std)[1][0:-6]
+ bar.AddButton(wx.Bitmap(std, wx.BITMAP_TYPE_PNG), wx.Bitmap(ref, wx.BITMAP_TYPE_PNG), bname)
+ count += 1
+
+ bar.ResetSize()
+
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(bar, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15)
+ panel.SetSizer(sizer)
+
+
+ # our normal wxApp-derived class, as usual
+
+ app = wx.App(0)
+
+ frame = MyFrame(None)
+ app.SetTopWindow(frame)
+ frame.Show()
+
+ app.MainLoop()
+
+
+Supported Platforms
+===================
+
+:class:`ZoomBar` has been tested on the following platforms:
+ * Windows (Windows XP).
+
+
+Window Styles
+=============
+
+`No particular window styles are available for this class.`
+
+
+Events Processing
+=================
+
+This class processes the following events:
+
+============================== ==================================================
+Event Name Description
+============================== ==================================================
+``EVT_ZOOMBAR`` Process a ``wxEVT_ZOOMBAR`` event, when a :class:`ZoomBar` button is clicked.
+============================== ==================================================
+
+
+License And Version
+===================
+
+:class:`ZoomBar` is distributed under the wxPython license.
+
+Latest Revision: Andrea Gavana @ 17 Aug 2011, 15.00 GMT
+
+Version 0.1
+
+"""
+
+import wx
+import sys
+
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+zoombackgrey = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAjkAAAAyCAYAAAC+s8qHAAAABHNCSVQICAgIfAhkiAAAIABJ"
+ "REFUeJzVXUuv5Udxr/O4xrzEAtvIAnYevkDAJp8piRfeeIGSsEFiY96QbUyiWRgn9reIieTx"
+ "YIGsAWQZCQkJz3h83/e8s0jquG7Nr17dfeY6JR2dc/rfXVXdXY9f9f88JpPpjEbTL37+s91u"
+ "tyN+EBF8XenDZPWR1yXp65rktclkAtv5tbwueU+nU5cXv9dtuq81xpLP77VcS45ci+12+8h1"
+ "OQ/Jg9u9uVk6ete5fTqdXtOb5cs2a66IJ1oDqYMe662Zlpnpg3hZdjqZTGg+n9MTTzxBn/nM"
+ "Z+jJJ5+k+XxO0+mUttstrVYrWiwWdHV1RVdXV7RYLGi9Xu/HTqdTmk6ntNvtaLPZ0Hq9Nm3e"
+ "WhO0FtoGJGl7IPrEnuQ1zy/1uvAckH7WONTH20ePpB8TfTIPtDba7lCfaLyUhWxQjtfXrHiI"
+ "rk0mE5rNZjSbzfa2wv622+1ou93Ser3ePzabDW232zDGWjYuydK5lby91jHGi1l6TXVskjEy"
+ "ylloblHOQetixXbrPfJBj6QcFPu5T7RPkR8zbbdbGLPRax672WxotVrRP/7TP7c5sUGTUSDn"
+ "3//tl7urqyu6uLig5XK5X0jPKNiI5GT1swVyvDHS4HW7pgzIschL7IhQsLISteyfdRivTZLc"
+ "m8w4rbeXBKv66Lmidi0XtVvj9BgLECIeco4jgjSyYwly+MEgZ7fb7UHOYrGg5XJJy+XyGsjh"
+ "gC4TVg/I8drlOG3HEphG4Eb6aGTfFh0C5PB4ZJMRwJF9NEBhYnDBr+WaWTJ2ux3NZrNrMvT6"
+ "WglFjplOp3ugw89EtAfGDHCyIEfPHcXZ1r1ApG0lsmUiDATk+lty9HvrYY3zrmViYRTj+H3r"
+ "+nogx3tvtaF2S4bsK9dytVrR5eUlnZyc0Mcff0y/ev0/hhlPN8j55av/ujs7O6PNZnMtCLOj"
+ "WECGX3vo2DImvUjWdU0oMGrHQABJtyN+klCwzxi3fN1jxN44tHaRbhXgogOcBYYs3hbwQPtk"
+ "va6um0w+SMdKErb6a6fnPtPplObzOR0dHe0f8iSHfUo+mJdMitvt9tpDAzRrXaXe3py8gCtl"
+ "yLnp99l1HAEos4TAgbYHD/hoPnKsB16sZItsEZ1KSH2jpIVADuvAwAaBHC9max11PLWuj6Rs"
+ "DEJtUkcvzqN84wE/6z2iKKZF+aMS6zLgJAtgvLllChzZzrZ3dXVFp6endHJyQicnJ3T//n26"
+ "d+8eLVfrbrDTBXLefOM/d3/6059ovV7Tcrmk1WpFy+Vy7yhWwGXSziSvS0PSwMMyQs0/2hwr"
+ "WOv3MkhpA9fVheXkmiww4I3NgBLrupSH9sXig0AI6ucBvgzvihN7fTPgCvGJKiVpi7yGiLhC"
+ "j6oguV7z+ZxmsxkdHR3tT3Jms9n+dhX7FfsYn+SwPNZT+p0ViCygU9k377qcn+4jwRnSD7VH"
+ "ySKzzxZl7APddmKybol4IMk65ZH26yVnRAh4aIAib1XJBxHtTwAlyNlsNqnYWgEz2aKvh6x1"
+ "RzJ1XLdIx3wL6PA1672VB5He8jnKW61gJwIhlnzZ5oFdq5CWMYptb7FY0Pn5OV1cXNDFxQVd"
+ "Xl7S8fEx/fGPf6TVetNlLPOewUT0yFG5dBZZFSCggqoFq4LQ41C7fI9IVxseaR76swZR8I0S"
+ "OGrPBLSs4Vs8eZx3nCjHRqAGyc4Ak+z7zNplEzdRfIvQk5mpzryAaSWJ9XpNs9ls7zNHR0d7"
+ "kLNerx8BOZyAdJCWhQWaL9LVel0Fv9Y8dXsFlGQAjtQpQ9oPrCCNQInmIdcBgZ8IxKDxaG0t"
+ "OVLfKP4xYNMPBuzV0xzNm9st2XrcSJCjbcrzb/YVBCgRX+tZ+5h8Rjz0e2tNMuvSA3Iq+lb8"
+ "L+KvX3Oc4gMS/rwh3wmSuf7bLzy/e+vX/91sMM0g5+47d3Z3797dV5pcYfKHh/iWlf78h3Yc"
+ "y1gyYEaO4fvSGshIo8oAEwt5e1RN+LJdGnsGHESE5imdwDNwj2dFH6u//HApWicNQLyElKl8"
+ "dB+0T1GlJ6myZposIM63peS17Xa7b2eQw0BH3grWwY3BDzrJyaxdxY4zRYLs49ldxjcPRUhH"
+ "2a7XOPsegRfdP2rz9NDkARIJ2PjBt64Y5LBdcQxnftbn9zRvq4+mkeBGy0QxBMn0QKMlwyvG"
+ "de7xxss25HNeXNQ+L+NcdV2tgqsC2CL+1rwlwJGxTRZwI6kZ5HzwwQd0enp6rQLgikAfeVqf"
+ "zyHCH4KVxkP0yeJHnwrPLI4HYqJg6zm0FSCR00W8LT4tpIOkFQyzOiG+klcmOUbAryq7ErA8"
+ "/hk+1pqhygyNReCDT234wZ/JIaL96SgHAH4vx8vTVHS7KgLP1rfqrP6ZdubnvdfjqzZu2ZxH"
+ "USDnPh648OxOghwPWFq3wdBYiweaQxSX0EkOAx15u1Of5mT20ro2AtggnpEvWmBekvUBZLS+"
+ "OnZaryP9td0iv5Pzq/he5VtXls5RLpX6Zu1Ar9Vut7sGphl4yzFf+tKX6LnnnqM7d+7Q3377"
+ "hd1/vfXrJkPqvl1F5Cc25DBM2oEsg5K8NCFD86jirJoyG4uuR8kbIXqLT1VfVDFk18oLtKiC"
+ "0mMsfaPKowoKEZDLzCWSkbmeSbRZUCmvS+CiP+OmT3JkUYA+S+HpZ9lehqL96QU5oys6KS8D"
+ "8CMw411DIInXRH5uS4MdvmZ93sdacyuhaPJuWaEiFZ20W+9le1T8VMmLhUiWBhAW6JTfTNPk"
+ "AZ0od3njrXnoMVZe9da0tVCIgE7Wbyw9JD9pZ1a8knL5s4mt1ARy7r5zZ/f222/vq8vogapL"
+ "OWF+Hy2058hV4NFC2U33wAgyXtQWyY8o0oGfrWQYASrpaBayzzhj9iRABykrOEXrrtfamodH"
+ "yA4yn3Gy9EOBk/0FnZLKfvIUxqu8NWVPAnT/LFUSYtRnBPH+ZuTpRGPZDuoj5egx8tREJ1nu"
+ "t9lsrumWOY3w5iPnzLKtvvoDoV4Cl7wR4LC+TajnYr3PxC7dJvcN2Z9VbMp9Q7FB80I5q5K7"
+ "vHnqMdn4qHVrIct+tC49udYCiBaoGkG1XxT6P3r//ffp/Pz82vG5rgJQ5SkpE4h1f0TRqYBF"
+ "oysLxNfSzUvefD0KCh5ZzoxkR+M9GVHQ9fbGcxgvIMjAWtXZChqyipZV36hTDd3P22+dlPRt"
+ "Be/bObqvfGTBD9LJWzPUX76vAK5DEtIBrZNOlN4D8fYSn6VXZU8QZfxQyuJEqD+krn80MOKr"
+ "ZXtxJ6KKrVj+afHIgjWLh5aj/bElXmTJ8inWK7sGrYR8IjPGu6Y/E6Z/3oB/UuOJJ56gL37x"
+ "i/Tcc8/Ru+++Sy88/62mSTWBHERe8tGbUdkAPc4z4iqNBDraGCx5ljNknCTrSF5ykrwqPCXv"
+ "HkPPyhrlpBFVwEl1TJYQwIlkjQg46HoE8h5nUfE4wM+niRBAiooADUQisGHxRXYgv2Y+gipg"
+ "oKcfyjXIxxDosdZP6x4VWSNsN1oDK+eOkmfN1yoMNC+Lv7VW3pjtdkuLxaJpXmULvvvOnd3H"
+ "H38MfwocneZYR1OaMujbqrgyZG2Kl4y9zfQq3R6jywSCauKyrh+i+siCNXZO5DzoRMKT1TqH"
+ "KsCJ7CFLuq83V+1D8lTUskepq37fslaenSNfik4qNQ/rlAXJbKUqn9HJ+BBUjREZm63EyV7/"
+ "i/Sz5FZ5ZtokSeAg41QlOWfktFAFVBxCdpZ6i9RMjs5SGeT84Q9/2H+ryrol5R3tMsnAaS2I"
+ "VXVUKt6bIs9ZtdNYycNyLu146Lp8Ru06Eekj6uzcouDn8csAW0t+y363Ok7Gniv8IiCjq0r5"
+ "sPbIs6ceXT3yjvRbeVTARZVa97ylX2ac9f4Qp5gcZxkoy8/eyA+yWx9MZh5oDQ956trCO5tP"
+ "srHJyjXa5zIFWYWsvOkdHEg5Lbet9NpEOjBVCz6+LTWfz/d2x7dL+cG3rL7whS/QrVu36L33"
+ "3qNvv/B82SCGnEXqCeqFtsjaHM2zokfPOFQZW5v5uBKJJCv5tcpuTdatQU3bBAJ+0fiMXWne"
+ "iHpAchTIWqpRVCDosVGy0fyi42yrPQs8rAKlupYIpEcgo3JMP6IqzBRa1jhrby3K2rg1Lnov"
+ "AY9+aCDdGlMRRXPP7LtFlg1V9In8RcpBflEB6T3kyWlZO8Rbv5bXJaFvTUe2k4mPciyD7c1m"
+ "QxcXF+U5lUDO3Xfu7I6Pj83/O0F/52AteBR4vY2qJMMqRQaUka/7ZoNspLcHsKpVsPXooWoy"
+ "zYzzgkmFX0v/iE8WmEXydT9+cKXNtqRPSzUoz/CPKBsgkb5VG/J8zOtT4V/Z20y/ajzLUibu"
+ "jCANTL3TuNEJvLLulk6tcr33vfyiviPn0xLfe6kaf1tlSBpp8yWQ8/vf/54uLi7Mb1VVkXgF"
+ "LFSvHYoqR/TVxOIF0AzAieSPNHqm7DF7FLyzemVtpvdWSnRCMdrJUUXJcvihK2xkN5lEheRk"
+ "9Ou5pVIBTyMD9EiKbAqd9uh29JrXNvovP48X0it7aqILU/ltF3Qbe6Sv6v5RnGuh6O5C5jTS"
+ "8xX54WyvMGvVvep3vac5FlX3JDoUkLem5C9x61tWR0dH9PnPf55u3bpF9+7dK3/LqgRyWo4A"
+ "W8Z7hAyn9QQhokwyr8ruWT+repbXWxJEzzFxhrfULeqX4XdIXb2A0htgoiCeGZu1Nyug/3+k"
+ "yM97+VYJ7VM1rnkxEl3vPUHJ6ITGZOJJdK0nHkkemp/mHcWXTOxozVGV06JRIP5QcVCSB9a8"
+ "05doPbIFuNxbvmV1cnJSmkMa5Nx9587u7OzskW9U6W9WWYaEnLwVpUqKnPGmq8EWY9Zzkq8r"
+ "JzmjqRrsosCePYHKykNtvckhE0wr87ACpAdQd7vdtV8NRxSdBkZ6oWveWkbrmglaTFmdW0Cn"
+ "R9WTx6yfjUw6LfaM4oe+nomXFh+rwBpFVRBQXW/PLzOFo7d+GVm9hE55D01ecYV8WrZXTtZ1"
+ "XBjhS2mQc+/ePTo7O9sHXPS1cQ8pZxTOOo0+5n0c1CsnAile200DNY+yibxCmdMMC3D0yNZ8"
+ "K/bVY4tyrLxtIfWybh2gOUS6VfxQ88nw8PZJ++6h/LcCBlrIi3MoUOs9bpFnPXv8omvoh1uJ"
+ "sM21AtssjbAHLzboNiSrRQdUpLSCIouQDbWcOI2gzBysX9aWxcpkMnnkdpW8ZTWfz699y4pv"
+ "Wb3//vv0/Le+mZ7ckP+uYoUtanXqyCBHJjjEJzLKXvCh5+jxjJBwb3KXc0a6ZU/ZdDLjNeRr"
+ "qCLP6iifM3PJEtoH2ZbdZz33ah8OXNYaah6W7qhf5ZpHls1Gc7bmJd9HVO3fStlCRLfzHL09"
+ "sa7pdssPM7w8PTOJUfoq/5eWfq95IVvV/ax1HQFskB5eP9nfWhsvJkR9on1+nMV51V8t8mxI"
+ "87SKG0++Bwr59Ww2o81mQ8fHx2m9Uyc5v7n7zu78/Hz/9+jWN6q8kxwmdHSVSewRVQKlDiaW"
+ "DlJXC6Uj/llCelR5sJ4t8pE+KGD07oMMklpepEOVWtfCOz3K9O3RW9qU/sNGlmdVcD1gxWvP"
+ "2jcKTJ7MiH9EI5NDpnA6hNyIrPh5CB2sxO75K9pHr79lF71F4iHIK+yiogH5b6YoG0nZOHSI"
+ "ta/GgApV9kJTCuS89957dHZ2du32FLpNhX4UUCqlFbUAkfd+hKNHPDJgJhovnzNyMrxa9LHW"
+ "GAUkBLoySalFt4z8kZQFqa2EAHFWJ7lH1u9OyCCqx3Ef2f+QNHoNs3yqJz4t/SrxRe9BxEsD"
+ "1UxBmG2vgHRNOq7L21by9sGh/6dpBGWKVp1PUH7hZ+9zcEg2EcFCxdOtup5ePtQncb02blE2"
+ "b2X4RLes+L+sjo6O6HOf+xzdunWLPvjgg/QtqyE/Bhg5WIToJZ+ouhoBOg6ZQCv9I12qelbn"
+ "l9G5BbxkAJUmnbCt0wrP1iwQ07PfKBlZVWkrCJVy9GvJG8nUfB5XBdlit6P3ZgRVk4tMIHrP"
+ "dF+vHb2vgh2vn7XGUeLzTnb0Z3MycT2K9zdJvetN5AMX9Jr53zRQ7Fn7lvyV9f0otk6nU5rP"
+ "57Rer+nBgwcpfUOQ8+5v7u74FGe1WoX/OO6hYv3aM47q8VT1eq+RtSLZKDC0JkkZdK1TAD3O"
+ "O0XLnnYhnlb/qM3a+6oeGRkZ/TKyW3hZPmDZhlf1oz3w9B1VgWmZ0anE4yR0UuI9JGXW5nHN"
+ "8VAAoeKj+lTA+82c1ph6iIQfFUPZ/lk5EcCsFqAtOtwUtcaTyolkD4Ug53e/+93+BwDlrxxr"
+ "YJP9TE5EXrUsr+u2m9roFqDioVXUZ0TFkaEswIn6IIeuGvSoYBCdDMp+N5W8ssWAtJGo8j4E"
+ "IR16AhUDc+86kn8oyoBTTvpen0q71U+vbdTeKk/2z/6fFd9KYIoKiajIyvhe1j+jflKetmO9"
+ "rvyofOaUbVoXL/J99ttq0TytebXGst6iv7XvZDIJfxhQ3rL67Gc/S9/4xjfoz3/+M33rm38T"
+ "TtQFOednpzv5mRtJ2UW1grEeZ50oyL4Wb0TRsVd2TKWfdTJVkeudbll9kTNZ/byHlmEl0EiO"
+ "7oueo7VBshF/i09FV/TekqvXIts/S9a8rTY9z0NRBFg9e9LXPT6Somp89KO6Di1kjc8AF2+M"
+ "bIuAfTR/zcPyL28uli9pnhnKrk0lsU8m8TeMvJzk2TGKPeia7KNfZ6j3QAFRRX6Pz/TEVHnL"
+ "6q9//Wso3wU5b775Jj148IDW6zUtFgtaLpe0Wq1ouVxe+1FA/Q0riyIjaQl6ljPq99XNi4I1"
+ "GtMy1gsg1cRtrUvWGSyjs3SwdPWc3FoHby3QdaSv7od+UwYFHd3H+j0aK1hF84z2Sl7XVZ6u"
+ "PKOAaemLZHltiE8kz5J1aGrxcY9HxWYlRQDVixsZ/bJyPR7R3ukTDi0f2arm5/n/iL0akdQt"
+ "IOadlFV1zvrTCOo5UR2lSwsPbU/yJEfHQ3m6c3R0RM888wydnp7SD3/wijvR8HYVCmzyvzpa"
+ "qXJrJOsU6HRpxDGe1iF7HBrx8/T2+meu9RotckTvtC572tZyjJ7pEwUjL9hmgIjm22NHlv5o"
+ "HT0AY/XnR8YGs341ok9Fl6xuhwRRkU1EPivb5X4g37dIxsmWUwxPd0tfJFMmHP0tqyr4y8wl"
+ "e4dAUnafMjEa6ay/Oezx4v3OgNxRxYDeO6RnNDaK17qfV1hV5GoeGpBbIOf4+JheeeUVkz+R"
+ "A3Iuzs92UslRn7nhiXlt1vVRBuHp3opGW/p484mqQo+XVYVW9bSSerUSGZlsM4Ev46xadqtt"
+ "ZX0hA2CzwBglTKv6rs7L62/ZFlMv0NEyWviN8t9MUsz6rm7TiQiRJc/SF+nVGie17AjoaP0y"
+ "5NnRaLLsNooJWi/LLjPrUI2ZHmXiYCYuZfr1FBqZ+JOx5V4yQc4bb7xBH3300f721Gq1uvbQ"
+ "t6sQiuTX3rUMWQkrSuwW9QYBz6B7AIWXXHqoUsFIXbxrke7Z4BcZf2VvPZ0y61oFA9UxHvER"
+ "LROqxPRv6Fhys36VAXi9viJ5HJpaiq8WvTLJxQI6aF8zYy0waQH6qNr2bCejC7KLKO7zIwMM"
+ "s0VPlTwA7YHPSB+kv/V7OdzGj8rcK76N+ltFUJYyY7KgR8dmXjP9VyK6XX4Y+ZlnnqHz83P6"
+ "0Q9/YC6MCXK8r4NXK+UqeUktquJbZEX82RC1E6AEmlmf7JpkQUmGRiQrRL1JJQK9lflba1xZ"
+ "72z/7KmLfG8FUZRYNIjK/odQJhi3JocqWEY8Iv0t3laiQP177dybF1oDL05a4yNZFvix+Htx"
+ "p+I/ElDrbxURXd9DmcQzdikTbwYQRnpG/ZAOWX2tvbX2AuUAKVO/lrrL9fSKMq+9QqNyiiS9"
+ "t63FotwXBHgk0OFbVicnJ/T973/flAFBzuXF+bUVQE5pGYnlwBl02gMQLLCSqVYtnTLGEBml"
+ "1c9D92gc61ShqqO0VPTZeWcosyZVwFIhXV30BhSvYtH99OsIsKEKkMdZAVf3ixJNJEvrWZGX"
+ "1cGSY7VpHSIZFR2iGIL2OjOf0QkH6VSxZWuNUDK2/jC2RW41MVrXLH0QZXONnH81LkQ6VXXO"
+ "gjT0+tBU8QE55pAEQc7rr79ODx8+3N+akt+qkr+Vwz8MGCFyD7h4FVgEeCJCvKzxHkDyXltV"
+ "jk5MWedAzhQ5tUdZuRkZnOyywC9Dep3QJ+urfEc6TWtgy/C12pA8LxlrYIRsD5FVqfJrC9RW"
+ "wbMGHB5lgUS2SBhFVZDgJZlsnByRqFrjJeKhAXQ2nlkyDuVblh4tQEe+b1lLa75ewTNqPbQ/"
+ "o+tW/xYaobfOAfKBblnxac7l5SX9+Ec/hMq7X5NCG6AXzQM3clwV3bVSr+NUUfJoQmCrh08U"
+ "cGV7BASrVbsnT+rYQoeyKSu5S7ktlLEpfqCfY9AOj4B2Bhxk5+CBsKx9tMjQ1z2wh+R7SbWH"
+ "LDDYMl63VdczavcKOQRSrDiPblfxdZ1wKv9rlQFTEaFcpPlY/DWfDPipAh2veNfrbhXGkX5V"
+ "ysb23rzTWphaD21j0u7m8zl95StfobOzM/re974HeT8Ccq4uL3ZEGMRINJyZSJTgRgQKj6pV"
+ "Qzb4o6AQ0Qhg1GLsFtgZRVWdDgkQJVX1qvTv6WsBhQhUZQBKtLbW6al8Hc2tZf96g/RNj6/w"
+ "a41pFkCLkk+rP8l4qIGjdWooTwpbYuBoOqTMLKipgp9Mrmwp3qICtaLXTeylpJHAjgiAnNde"
+ "e40ePnxIm82GFosFXV1d7b9JJb9RJW9V8T/WImWZ0AnQoSkTFFoTVrVqsZC5xwcBFK9fRXYG"
+ "8Fn9PSdE87EcGLVnqnG9fvIUIzunaM0ycrOgAO2dlSgsHeUpD6qsZT8k36piPX0y16z+Hp/q"
+ "OnpVMeLTKsebj7fGVltLO5IdyWst/iwbQmTZXSWmVPWz9IpizKEpe9Kk36N5WTEarW0kz1p/"
+ "T18Un0YX5NXYwQ/9QWxuQ9+yevrpp+ny8pJ+8uMfPaI8vF3lVXpSIEL7mUlYFPGxAlklgGWM"
+ "pYWspIWerf4Wz5aAnV2bbHKQFB37erz0GI8snqhfRAgwZMZngk1mLzQhW5cghm8VaBnytgA6"
+ "BbD2Luuj0Xxb/UfbRPSL0tY4NDci/xZND3nzQes+IlF4cTV7smC1eWAXran1v00o6Xi5wpKZ"
+ "aY/iV6V/ljK2pcla5yhfZWKw1qmHPBuJYl2FqvlO9tX/lybb+DUDnPl8Ts8++yxdXFzQd7/7"
+ "3Uf4XQM5i6vL3Xa7pclkAk9nsoFEO2cGSWYMKQOqsoCn6giVDRphKNVx2kEqwDPaH8lftlun"
+ "S9m9RGO9xFwB1VaCsBwcHdVneFrz8q5FNmolzopNoQDjjaskZS8ge/yj/fOSQIZaiq4sT/l+"
+ "RN+Iopiq+Vv+pNsqYAGRFQ8qtiD5RO1oP6197t1/xIuoDlyjWCl/DwutFyrAKvmgx/51LOzh"
+ "McoHNVVz4zWQc/v2bTo9PaXlcknL5ZIWi8UjPwAov10VJRJvolHAzwTBVsoCoFagkkXmmTEj"
+ "qhIkq0q6gqtUV1ZAZL7oObNHWbmZvlK2JzMz9yp4lv3RBzgtgIBsSvtcZFeZNcrMtdVeW20c"
+ "zRPp3kOW704m+C8adB+kZ5YyYCkLWvX47L7qRI1+M0d/IDSK5TqOfJpI7iuTBVwtQBQV4PK1"
+ "3ofMfmb8xdqDyKasfRm5T1leVozSpzryttXTTz9Ni8WCfvqTH1+b3FwzlovpOSdaCIR8uV0n"
+ "NW6X15hQfyS7B2miOSCSBliVd2gnzlZvLYTWOMszu6den1EkeWZ4V3So6qr9gl/L93ySqpOB"
+ "Pr5Ff4ark1IPaV69PpfVzZKj/a9i81nftU4pPD0tPhaIjvj2+olOVAgI82sZn+V1vVbb7Xaf"
+ "XCTQljL0/xlW/qz5JsmzMysGorzG/TwAjPhY7zVlAW2FqnmwcpLl6ZXhxQBa2xvbGo/fbrc0"
+ "n89pu93Ss88+Sx9++CF95zvfucZrb5mr5WJnAZcInVqOJMmrMC1UGaHlEQkxu3H6FMOi1kQT"
+ "VXyosrL4VPjqfqgiQdWL1OlQAQsFe2v9H1dVGK1nZr2tig7xyvD4NFHW3kaOR76B7Ne67iUj"
+ "T56Ui2RkY6MnR+qrqXedkV4twCQTF3VfT8ZNAqBIthdfK3aE7COrX0bHrM2MjCMRVtByH1cM"
+ "24Oc27dv0/Hx8f7W1NXV1f4HAPnHAOWtKr5dZZHlROjHAxG4shLZiAq1usBZYIPmYfWN5GV1"
+ "8mRWqlfdVgFGkU5aL/Rejh9JmYocJS35nE1UaP4ICFpgUVYq8oOc0l9QINF6t6xhzxxHUgtf"
+ "D9BEsloAZrbA0Lp5/bPzPjQAQL6g5aLqWtqf9f9DlpzM3JCfeg85Lpqv1450t5J51fYsWd6c"
+ "qjEqAjroMMHrn51T5ZQowxPFSGlr8ltWq9WKfvbTn+yV3t+uQp+QR4rzQ4MVDuToJECPl4sQ"
+ "LbBsZ134Q9EyCaD+HlVQN88tSt6ecyFd9drypmUJrbHWVa+dXPcINHoBQI/N6C0NFq2Dduhs"
+ "EsiAKtSG+ugKqyUJen0scM8y5/P/dcntdkuz2YwmkwltNptr/yWk/1dIjpf7y34i+3iyvXXp"
+ "IeQ71YoZtfcAlJ45ZhOn/PIG34a0+uo/c7T2J3rm19ofPZ2j+MnvrW+7sK3xQ9prlBM8uZoO"
+ "AaytEzjrpCUDLKzY4YElL39GIL4K8L3chOasx2RjX2VMZINsZxro8C0tvm311a9+lT788EN6"
+ "+eWX92PnRETr1XJ3+/ZtiKylscrfykEGrJ8tkOMhSW+imlCS7kGdmb7e9YyxRDyjcUwtht3r"
+ "DN417311/VAwaFlPvR8ZvfW1bCLNJHFt/xrMzWazvbNOp1PabDb7fdN/p8KJxALfshCx5mbN"
+ "s5pM0Fpo38wGPQ94VyplNNbSE/EfBYKiteXrvNdovH7O8szGEkkREEH/3oWAAAAEp0lEQVRf"
+ "7eVxEtxI+0RxH8mN6BDgO9IhsxeWfpVCKcqlTNZv0lVju6evpbPnm6hPVhcPuKHrVbueE33y"
+ "rSq+TXV1dUWLxYIuLy9psVjQYrGg5XL5CLjRE7JAjH4dXR9BkUNlQU42+GcMxKPKplUNCc21"
+ "h0flfWZeXnBHfVEy8vTJgCRLbgVwonFWgNKVG1cqs9ls/56rcQ/kWPNleWit0Hro117CtwCM"
+ "Bm/6um7zSMv3gA9a66jvIShKiKiv3AdvvNU36ofea4qSvdxX9JslTPoUR/7W0wigc8i9yxQD"
+ "Xjta40phpdfHypVRPo3m4+mf7YPsw5oTj6sCnkyhI+2Rv2E1m83oqaeeouPjY/r5z366+7u/"
+ "/4fJXE+GA+pyubwGeFar1bWg6W2C5zTepqEJZcFItBgjAZTkq197yd1KHig5RFVlNKaV0JpH"
+ "DhAFggrAawWIVQBjJV10281L4HKsNSbjuOywm81m76wS5HACkb86rqs6vW+Zk5wKqKskykz1"
+ "GpFe8xFAB1HPWMRHvvfsOQIqXlsEYizwFJEXu9lG+TXfTpXrJ09wJOCx+FttPTQazEp+nr9E"
+ "+6cJxSAEZCIQWvlNu0gn73rWp3v9ycIFkq+8Lr9GPpvN6Gtf+xrdv3+fXnrpJSIimvOtKjbK"
+ "xWJBZ2dndHZ2RpeXl/u/dZAfNPYMNYM2ZRsnA2sCSE60SYcANIgqiaLV6SqJRY+proNnWJEu"
+ "1vWeiiFDLfzQew/EWHKrCdvzG04Ws9lsD3Tk13Y5YcgP/ltH11JeJthV1x/5rMdfz9Vr89Z1"
+ "ZNFzSMqua9QPgRmvHb22xkeJ02pnntPplNbr9SO3rPQvduvfU8vKPTShPOIVK5U448XMbDzn"
+ "1x6AQXnUmkcU37I5KwN0dFyIdLP4WLInk8m1E8JIx/mrr75K9+/fp5OTE3rw4AEdHx/TxcXF"
+ "/ttUqBpEAS569l5nJjkySI2o9ioG4AUXz4ksvpYRj6ieM/JRW8Z5UILyAnSkd1Uva/0jnpZs"
+ "z3EtAGDtnf65cn7NDs0JQwIcDWJ0oZApFrIgNAMCI9/I+L/Ht0KVSjbD3xsj110nuhYb9cbz"
+ "nnl8W5JsZCt6vP4BQCYNciTwQXKs95b/jwCoEbDOghqr3dt7r13riA4OPD/K7mFGj4yOUZHj"
+ "Uc8pj9fOvvHlL3+ZHj58SP/yi5/v5svlkv7yl7/QRx99tAc4y+XykUDpLWZm0SsbkFmAStCN"
+ "+HgG3VLhozbU3pLELYqA0iGATva6Nf8Kn8patACXnj4ZkJMF7xLgyJMc69srzAMl4eyJiDe3"
+ "EUnFoyrYyYDfSM6h5yRlVJIlX4vGegBIt3uAB1HWTtGD++kTHQS6szHfSu6H3MMIwCIdDuFP"
+ "Uo/oA8feay2/FzzyfvfmFO/wBPXzZMo4OZlM6Otf/zo9fPiQXnzxRZr/9re/pbfeeotOT0/3"
+ "t6ZQgOw5ZqouRuviRcgSnSSMoh4QMFoXKW8k79ZA0xOQRgezx5HgKoTW00pk1a/k3gSxjXjJ"
+ "YXRw/LRQa2LLjIv8rgXY9xJK8jrRZm3007qnEd1EPDnkej5OMCmpchoeEcfP9XpNRET/Ax6j"
+ "kIck2UJrAAAAAElFTkSuQmCC")
+
+
+# ----------------------------------------------------------------------------
+# ZoomBar events and binding for handling them
+# ----------------------------------------------------------------------------
+
+wxEVT_ZOOMBAR = wx.NewEventType()
+EVT_ZOOMBAR = wx.PyEventBinder(wxEVT_ZOOMBAR, 1)
+""" Process a `wxEVT_ZOOMBAR` event, when a :class:`ZoomBar` button is clicked. """
+
+# ----------------------------------------------------------------------------
+
+def MakeDisabledBitmap(original):
+ """
+ Creates a disabled-looking bitmap starting from the input one.
+
+ :param `original`: an instance of :class:`Bitmap` to be greyed-out.
+ """
+
+ img = original.ConvertToImage()
+ return wx.BitmapFromImage(img.ConvertToGreyscale())
+
+# ----------------------------------------------------------------------------
+
+class ZoomBarImage(object):
+ """
+ This simple class holds information about a :class:`ZoomBar` button, such as normal
+ bitmaps, disabled bitmap, button label, etc...
+ """
+
+ def __init__(self, parent, bitmap, disabledBmp=wx.NullBitmap, label=""):
+ """
+ Default class constructor.
+
+ :param `parent`: the main :class:`ZoomBar` window;
+ :param `bitmap`: the button bitmap, an instance of :class:`Bitmap`;
+ :param `disabledBmp`: the button bitmap when the button is in a disabled
+ state;
+ :param `label`: the button label.
+ """
+
+ self._parent = parent
+ self._bitmap = bitmap
+
+ if not disabledBmp.IsOk():
+ disabledBmp = MakeDisabledBitmap(bitmap)
+
+ self._disabledBmp = disabledBmp
+ self._label = label
+
+ self._height = 36
+ self._width = 36
+
+ self._oldnx = 0
+ self._oldLeft = 0
+ self._oldTop = 0
+ self._oldWidth = 0
+ self._oldBottom = 0
+ self._oldHeight = 0
+ self._vCenter = 0
+ self._hCenter = 0
+ self._oldInc = -sys.maxint
+ self._isSeparator = False
+ self._enabled = True
+
+ # Larger number gives a greater zoom effect
+ self._zoomFactor = 3
+
+ # Whether this is a reflection or not
+ self._isAReflection = False
+
+ self._cachedBitmaps = {}
+ self._cachedDisabledBitmaps = {}
+
+
+ def SetZoomFactor(self, zoom):
+ """
+ Sets the zoom factor for the button. Larger number gives a greater zoom
+ effect.
+
+ :param `zoom`: a floating point number, greater than or equal to 1.0.
+ """
+
+ self._zoomFactor = zoom
+
+
+ def SetCenterZoom(self, center=True):
+ """
+ Sets to zoom from the center.
+
+ :param `center`: if ``True`` button zooms upwards.
+ """
+
+ self._centerZoom = center
+
+
+ def ZoomImage(self, nxcoord):
+ """
+ Zooms the button bitmap depending on the mouse x position.
+
+ :param `nxcoord`: the mouse x position relative to the button center.
+ """
+
+ if nxcoord < self._vCenter:
+ inc = int(((nxcoord - self._oldLeft)*10.0)/(self._oldWidth/2.0)) + 1
+ else:
+ inc = int(((self._oldLeft + self._oldWidth - nxcoord)*10.0)/(self._oldWidth/2)) + 1
+
+ if self._isSeparator:
+ return False
+
+ if abs(inc - self._oldInc) < 2:
+ return False
+
+ self._oldInc = inc
+
+ if not self._isAReflection:
+ # original button
+ inc = inc*self._zoomFactor
+ self._width = self._oldWidth + inc
+ self._left = self._vCenter - self._width/2
+ self._height = self._oldHeight + inc
+ self._top = self._oldBottom - self._height
+
+ else:
+ # the reflection
+ self._height = self._oldHeight + inc
+ self._width = self._oldWidth + inc
+ self._top = self._top + self._height
+
+ self._oldnx = nxcoord
+ return True
+
+
+ def SetSize(self, width, height):
+ """
+ Sets the button size.
+
+ :param `width`: the button width;
+ :param `height`: the button height.
+ """
+
+ self._width = width
+ self._height = height
+
+
+ def GetPosition(self):
+ """ Returns the button position. """
+
+ return wx.Point(self._left, self._top)
+
+
+ def GetSize(self):
+ """ Returns the button size. """
+
+ return wx.Size(self._width, self._height)
+
+
+ def GetBitmap(self):
+ """
+ Returns the button bitmap, which may be a scaled up version of the original
+ bitmap is the button is being zoomed.
+ """
+
+ if self._isAReflection:
+ return self._paintBitmap
+
+ if self._enabled:
+ return self._cachedBitmaps[self._width]
+
+ return self._cachedDisabledBitmaps[self._width]
+
+
+ def SetupProps(self, buttonSize):
+ """
+ Set up the button position and size.
+
+ :param `buttonSize`: the button original size (not zoomed), in pixels.
+ """
+
+ self._width = self._oldWidth = buttonSize
+ self._height = self._oldHeight = buttonSize
+
+ self._oldLeft = self._left
+ self._oldTop = self._top
+ self._vCenter = self._oldLeft + int(self._oldWidth/2.0)
+ self._hCenter = self._oldTop + int(self._oldHeight/2.0)
+ self._oldBottom = self._top + self._height
+
+ if self._isAReflection:
+ img = self._bitmap.ConvertToImage()
+ img = img.Scale(self._width, self._height, wx.IMAGE_QUALITY_HIGH)
+ self._paintBitmap = img.ConvertToBitmap()
+
+
+ def GetLabel(self):
+ """ Returns the button label (if any). """
+
+ return self._label
+
+
+ def SetLabel(self, label):
+ """
+ Sets the button label.
+
+ :param `label`: a string specifying the button label. May be an empty string
+ for no label.
+ """
+
+ self._label = label
+
+
+ def IsZoomed(self):
+ """ Returns ``True`` if the button is zoomed, ``False`` otherwise. """
+
+ return self._width/float(self._oldWidth) >= 1.25
+
+
+ def LoopScales(self, size):
+ """
+ Caches the bitmaps at various zoom levels to avoid calling every time
+ `image.Scale` on the button bitmap.
+
+ :param `size`: the original button size, in pixels.
+ """
+
+ if self._isAReflection:
+ return
+
+ for scale in range(size-10*self._zoomFactor, size+15*self._zoomFactor, self._zoomFactor):
+ if scale in self._cachedBitmaps or scale <= 0:
+ continue
+
+ img = self._bitmap.ConvertToImage()
+ img = img.Scale(scale, scale, wx.IMAGE_QUALITY_HIGH)
+ bmp = img.ConvertToBitmap()
+ self._cachedBitmaps[scale] = bmp
+
+ img = self._disabledBmp.ConvertToImage()
+ img = img.Scale(scale, scale, wx.IMAGE_QUALITY_HIGH)
+ bmp = img.ConvertToBitmap()
+ self._cachedDisabledBitmaps[scale] = bmp
+
+
+ def Enable(self, enable=True):
+ """
+ Enables/disables a button.
+
+ :param `enable`: ``True`` to enable a button, ``False`` to disable it.
+ """
+
+ self._enabled = enable
+
+
+ def IsEnabled(self):
+ """ Returns ``True`` if the button is enabled, ``False`` otherwise. """
+
+ return self._enabled
+
+
+class ImageBar(object):
+ """ This class holds the background button bar on which the buttons float. """
+
+ def __init__(self, bitmap=None):
+ """
+ Default class constructor.
+
+ :param `bitmap`: if not ``None``, the bitmap to use as a background button
+ bar on which the buttons float. It should be an instance of :class:`Image`.
+ """
+
+ if bitmap and bitmap.IsOk():
+ self._bitmap = bitmap
+ self._hasBitmap = bitmap
+ else:
+ self._bitmap = zoombackgrey.GetImage()
+ self._hasBitmap = None
+
+ self._left = 23
+ self._top = 53
+ self._startColour = wx.Colour(97, 97, 97)
+ self._endColour = wx.Colour(97, 97, 97)
+
+
+ def GetPosition(self):
+ """ Returns the position of :class:`ImageBar`, as a :class:`Point`. """
+
+ return wx.Point(self._left, self._top)
+
+
+ def GetSize(self):
+ """ Returns the size of :class:`ImageBar`, as a :class:`Size`. """
+
+ return wx.Size(self._bitmap.GetWidth(), self._bitmap.GetHeight())
+
+
+ def GetBitmap(self):
+ """ Returns the background button bar on which the buttons float. """
+
+ return self._bitmap
+
+
+ def SetPosition(self, xpos, ypos):
+ """
+ Sets the position of :class:`ImageBar`.
+
+ :param `xpos`: the `x` position of the bar;
+ :param `ypos`: the `y` position of the bar.
+ """
+
+ self._left = xpos
+ self._top = ypos
+
+
+ def SetSize(self, xSize, ySize):
+ """
+ Sets the size of :class:`ImageBar`.
+
+ :param `xSize`: the width of the bar, in pixels;
+ :param `ySize`: the height of the bar, in pixels.
+ """
+
+ self.SetBarColour(self._startColour, xSize, ySize)
+
+
+ def SetBarColour(self, colour, xSize=None, ySize=None):
+ """
+ Sets the background button bar colour.
+
+ :param `colour`: an instance of :class:`Colour`;
+ :param `xSize`: if not ``None``, the new :class:`ImageBar` width;
+ :param `ySize`: if not ``None``, the new :class:`ImageBar` height.
+ """
+
+ if not isinstance(colour, wx.Colour):
+ colour = wx.NamedColour(colour)
+
+ if self._hasBitmap:
+ bitmap = self._hasBitmap
+ else:
+ bitmap = zoombackgrey.GetImage()
+
+ if xSize is not None:
+ self._size = wx.Size(xSize, ySize)
+
+ bitmap.Rescale(self._size.width, self._size.height/2)
+
+ r1, g1, b1 = self._startColour.Red(), self._startColour.Green(), self._startColour.Blue()
+ r2, g2, b2 = colour.Red(), colour.Green(), colour.Blue()
+
+ fr = (r1 > 0 and [float(r2)/r1] or [0])[0]
+ fg = (g1 > 0 and [float(g2)/g1] or [0])[0]
+ fb = (b1 > 0 and [float(b2)/b1] or [0])[0]
+
+ bitmap = bitmap.AdjustChannels(fr, fg, fb, 1)
+ self._bitmap = bitmap.ConvertToBitmap()
+ self._endColour = colour
+
+
+ def GetBarColour(self):
+ """ Returns the background button bar colour. """
+
+ return self._endColour
+
+
+class ZoomBarEvent(wx.PyCommandEvent):
+ """ Event sent from the :class:`ZoomBar` when a button is activated. """
+
+ def __init__(self, eventType, eventId=1):
+ """
+ Default class constructor.
+
+ :param `eventType`: the event type;
+ :param `eventId`: the event identifier.
+ """
+
+ wx.PyCommandEvent.__init__(self, eventType, eventId)
+ self._eventType = eventType
+
+
+ def SetSelection(self, selection):
+ """
+ Sets the index of the selected button.
+
+ :param `selection`: an integer indicating the current selected button.
+ """
+
+ self._selection = selection
+
+
+ def GetSelection(self):
+ """ Returns the index of the selected button. """
+
+ return self._selection
+
+
+ def GetLabel(self):
+ """ Returns the text label of the selected button. """
+
+ return self._label
+
+
+ def SetLabel(self, label):
+ """
+ Sets the text label of the selected button.
+
+ :param `label`: the text label of the selected button.
+ """
+
+ self._label = label
+
+
+class ZoomBar(wx.PyControl):
+ """
+ :class:`ZoomBar` is a class that *appoximatively* mimics the behaviour of the Mac Dock,
+ inside a :class:`Panel`.
+
+ This is the main class implementation.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ name="ZoomBar"):
+ """
+ Default class constructor.
+
+ :param `parent`: the :class:`ZoomBar` parent. Must not be ``None``;
+ :param `id`: window identifier. A value of -1 indicates a default value;
+ :param `pos`: the control position. A value of (-1, -1) indicates a default position,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `size`: the control size. A value of (-1, -1) indicates a default size,
+ chosen by either the windowing system or wxPython, depending on platform;
+ :param `name`: the window name.
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size, style=wx.BORDER_THEME)
+
+ # Zoom from the center. If True button zooms upwards.
+ self._centerZoom = False
+ # Whether you want reflections or not
+ self._showReflections = True
+ # Allows us to nudge a reflection closer to original
+ self._nudgeReflection = 0
+ # Extension of the reflection. BMP or PNG etc.
+ # Initial size of the buttons
+ self._buttonSize = 48
+ # Show labels on hovering
+ self._showLabels = True
+ # used internally
+ self._noResize = False
+ self._buttons = []
+ self._reflectionButtons = []
+
+ self._imgBar = ImageBar()
+ self._previousHit = -1
+ self._currentHit = -1
+
+ wx.CallLater(200, self.OnLeaveWindow, None)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+
+ if wx.Platform == "__WXMSW__":
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
+
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+
+ def DoGetBestSize(self):
+ """
+ Gets the size which best suits the window: for a control, it would be the
+ minimal size which doesn't truncate the control, for a panel - the same size
+ as it would have after a call to `Fit()`.
+
+ :note: Overridden from :class:`PyControl`.
+ """
+
+ xSize = self._buttonSize*len(self._buttons) + len(self._buttons) + self._buttonSize
+ ySize = self._buttonSize*2
+ if self._showLabels:
+ dc = wx.ClientDC(self)
+ dummy, yextent = dc.GetTextExtent("Ajgt")
+ ySize += yextent
+
+ return wx.Size(xSize+50, ySize+20)
+
+
+ # reposition the buttons
+ def Reposition(self, toButton):
+ """
+ Repositions all the buttons inside the :class:`ZoomBar`.
+
+ :param `toButton`: the button currently hovered by the mouse (and hence zoomed).
+ """
+
+ nLeft = toButton._left
+ nRight = toButton._left + toButton._width + 1
+ nButton = self._buttons.index(toButton)
+
+ # do any buttons on the right
+ for n in xrange(nButton + 1, len(self._buttons)):
+ oButton = self._buttons[n]
+ oButton._left = nRight
+
+ if self._showReflections:
+ oButtonR = self._reflectionButtons[n]
+ oButtonR._left = nRight
+
+ nRight = nRight + oButton._width + 1
+
+ # Reset
+ nLeft = toButton._left
+
+ # now to the left
+ if nButton > 0:
+ # only for 2nd and more
+ for n in xrange(nButton-1, -1, -1):
+ oButton = self._buttons[n]
+ oButton._left = nLeft - (oButton._width + 1)
+ if self._showReflections:
+ oButtonR = self._reflectionButtons[n]
+ oButtonR._left = oButton._left
+
+ nLeft = oButton._left
+
+
+ # method to add required buttons
+ def AddButton(self, normalBmp, reflectionBmp=wx.NullBitmap, label="", disabledBmp=wx.NullBitmap,
+ disabledReflectionBmp=wx.NullBitmap):
+ """
+ Adds a button to :class:`ZoomBar`.
+
+ :param `normalBmp`: the button main bitmap, an instance of :class:`Bitmap`;
+ :param `reflectionBmp`: a bitmap representing a reflection of the main bitmap,
+ an instance of :class:`Bitmap`;
+ :param `label`: the button label;
+ :param `disabledBmp`: the button main bitmap when the button is in a disabled
+ state, an instance of :class:`Bitmap`;
+ :param `disabledReflectionBmp`: a bitmap representing a reflection of the main bitmap,
+ when the button is in a disabled state, an instance of :class:`Bitmap`.
+ """
+
+ button = ZoomBarImage(self, normalBmp, disabledBmp, label)
+
+ button.SetSize(self._buttonSize, self._buttonSize)
+ button._centerZoom = (self._showReflections and [False] or [self._centerZoom])[0]
+ self._buttons.append(button)
+
+ self.InitialReposition()
+
+ if self._showReflections and reflectionBmp.IsOk():
+
+ rbutton = ZoomBarImage(self, reflectionBmp, disabledReflectionBmp)
+ rbutton.SetSize(self._buttonSize, self._buttonSize)
+ rbutton._centerzoom = False
+ rbutton._isAReflection = True
+ self._reflectionButtons.append(rbutton)
+
+ return button
+
+
+ def AddSeparator(self, normalBmp, reflectionBmp=wx.NullBitmap):
+ """
+ Adds a separator to :class:`ZoomBar`.
+
+ :param `normalBmp`: the separator main bitmap, an instance of :class:`Bitmap`;
+ :param `reflectionBmp`: a bitmap representing a reflection of the main bitmap,
+ an instance of :class:`Bitmap`.
+ """
+
+ button = self.AddButton(normalBmp, reflectionBmp)
+ button._isSeparator = True
+
+
+ def SetZoomFactor(self, zoom):
+ """
+ Sets the zoom factor for all the buttons. Larger number gives a greater zoom
+ effect.
+
+ :param `zoom`: a floating point number, greater than or equal to 1.0.
+ """
+
+ if zoom < 1:
+ raise Exception("The zoom factor must be greater or equal to 1")
+
+ for button in self._buttons:
+ button._zoomFactor = zoom
+
+ self._zoomFactor = zoom
+ self.DoLayout()
+
+
+ def GetZoomFactor(self):
+ """ Returns the current zoom factor. """
+
+ return self._zoomFactor
+
+
+ def SetCenterZoom(self, center=True):
+ """
+ Sets to zoom from the center.
+
+ :param `center`: if ``True`` button zooms upwards.
+ """
+
+ self._centerZoom = center
+
+ for button in self._buttons:
+ button._centerZoom = (self._showReflections and [False] or [self._centerZoom])[0]
+
+ self.DoLayout()
+
+
+ def GetCenterZoom(self):
+ """ Returns ``True`` if buttons zoom upwards. """
+
+ return self._centerZoom
+
+
+ def SetShowReflections(self, show):
+ """
+ Sets whether to show reflections or not.
+
+ :param `show`: ``True`` to show reflections, ``False`` otherwise.
+ """
+
+ self._showReflections = show
+ self.DoLayout()
+
+
+ def GetShowReflections(self):
+ """ Returns ``True`` if reflections bitmap are currently shown. """
+
+ return self._showReflections
+
+
+ def SetShowLabels(self, show):
+ """
+ Sets whether to show button labels or not.
+
+ :param `show`: ``True`` to show button labels, ``False`` otherwise.
+ """
+
+ self._showLabels = show
+ self.DoLayout()
+
+
+ def GetShowLabels(self):
+ """ Returns ``True`` if button labels are currently shown. """
+
+ return self._showLabels
+
+
+ def SetBarColour(self, colour):
+ """
+ Sets the background button bar colour.
+
+ :param `colour`: an instance of :class:`Colour`;
+ """
+
+ self._imgBar.SetBarColour(colour)
+ self.Refresh()
+
+
+ def GetBarColour(self):
+ """ Returns the background button bar colour. """
+
+ return self._imgBar.GetBarColour()
+
+
+ def SetButtonSize(self, size):
+ """
+ Sets the original button size.
+
+ :param `size`: the new (not-zoomed) button size, in pixels.
+ """
+
+ self._buttonSize = size
+ self.DoLayout()
+
+
+ def GetButtonSize(self):
+ """ Returns the original (not zoomed) button size, in pixels. """
+
+ return self._buttonSize
+
+
+ def EnableButton(self, index, enable=True):
+ """
+ Enables/disables the button at position `index`.
+
+ :param `index`: the index of the button to enable/disable;
+ :param `enable`: ``True`` to enable the button, ``False`` to disable it.
+ """
+
+ if index < 0 or index >= len(self._buttons):
+ return False
+
+ self._buttons[index].Enable(enable)
+ self.Refresh()
+
+ return True
+
+
+ def IsButtonEnabled(self, index):
+ """
+ Returns ``True`` if the button at position `index` is enabled, ``False``
+ otherwise.
+
+ :param `index`: the index of the button to check.
+ """
+
+ if index < 0 or index >= len(self._buttons):
+ return False
+
+ return self._buttons[index].IsEnabled()
+
+
+ def DoLayout(self):
+ """ Common method to re-layout :class:`ZoomBar`. """
+
+ self.ResetSize()
+ self.GetContainingSizer().Layout()
+ self.Refresh()
+
+
+ def ResetSize(self):
+ """
+ Resets all the button sizes and positions, recalculating the optimal :class:`ZoomBar`
+ size.
+ """
+
+ xSize = self._buttonSize*len(self._buttons) + len(self._buttons) + self._buttonSize
+ ySize = self._buttonSize*2
+
+ self._imgBar.SetSize(xSize+self._buttonSize, ySize)
+
+ for button in self._buttons:
+ button.LoopScales(self._buttonSize)
+
+ if self._showLabels:
+ dc = wx.ClientDC(self)
+ dummy, yextent = dc.GetTextExtent("Ajgt")
+ ySize += yextent
+
+ if self._showReflections:
+ ySize += self._buttonSize/2
+ if self._centerZoom:
+ ySize += self._buttonSize
+
+ size = wx.Size(xSize+50, ySize)
+ self.SetInitialSize(size)
+ self.SnapToBottom(size)
+
+
+ # Sets up the initial buttons and sizes them from the center
+ def InitialReposition(self):
+ """
+ Sets up the initial buttons and sizes them from the center.
+ """
+
+ # repositions the button centrally
+ # odd buttons one is central - even, half by half
+
+ if not self._buttons:
+ return
+
+ size = self.GetSize()
+ oButton = self._buttons[0]
+ totalWidth = oButton._width*len(self._buttons) + len(self._buttons)
+ center = size.GetWidth()/2
+ nbCenter = totalWidth/2
+ nLeft = center - nbCenter
+
+ if self._showReflections:
+ nTop = self._imgBar._top - (oButton._height/2)
+ else:
+ if self._centerZoom:
+ nTop = size.height/2 - oButton._height/2
+ else:
+ nTop = size.height - oButton._height - 5
+
+ for oButton in self._buttons:
+ oButton._left = nLeft
+ oButton._top = nTop
+ oButton.SetupProps(self._buttonSize)
+ nLeft = nLeft + oButton._width+1
+
+ # And the reflection if any
+ if self._showReflections:
+ nLeft = center - nbCenter
+ nudge = self._nudgeReflection
+ for oButton in self._reflectionButtons:
+ oButton._left = nLeft
+ oButton._top = (nTop + oButton._height - 2) - nudge
+ oButton.SetupProps(self._buttonSize)
+ nLeft = nLeft + oButton._width + 1
+
+
+ def OnLeaveWindow(self, event):
+ """
+ Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`ZoomBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.GetScreenRect().Contains(wx.GetMousePosition()):
+ return
+
+ for button in self._buttons:
+ button.SetSize(self._buttonSize, self._buttonSize)
+
+ self.InitialReposition()
+ self.Refresh()
+
+
+ def OnSize(self, event):
+ """
+ Handles the ``wx.EVT_SIZE`` event for :class:`ZoomBar`.
+
+ :param `event`: a :class:`SizeEvent` event to be processed.
+ """
+
+ self.SnapToBottom(event.GetSize())
+ self.Refresh()
+ event.Skip()
+
+
+ def SnapToBottom(self, size):
+ """
+ Snaps the background button bar bitmap and all the buttons to the bottom
+ of :class:`ZoomBar`.
+
+ :param `size`: the current :class:`ZoomBar` size.
+ """
+
+ backgroundSize = self._imgBar.GetSize()
+ xPos = (size.width - backgroundSize.width)/2
+ yPos = (size.height - backgroundSize.height)
+
+ self._imgBar.SetPosition(xPos, yPos)
+ self.InitialReposition()
+
+
+ def OnPaint(self, event):
+ """
+ Handles the ``wx.EVT_PAINT`` event for :class:`ZoomBar`.
+
+ :param `event`: a :class:`PaintEvent` event to be processed.
+ """
+
+ dc = wx.AutoBufferedPaintDC(self)
+
+ dc.SetBackground(wx.WHITE_BRUSH)
+ dc.Clear()
+
+ background = self._imgBar.GetBitmap()
+ pos = self._imgBar.GetPosition()
+
+ dc.DrawBitmap(background, pos.x, pos.y, True)
+
+ if not self._buttons:
+ return
+
+ self.DrawButtons(dc)
+ self.DrawReflections(dc)
+ self.DrawLabels(dc)
+
+
+ def DrawButtons(self, dc):
+ """
+ Draws all the main button bitmaps on the :class:`ZoomBar` client window.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ for button in self._buttons:
+ pos = button.GetPosition()
+ bitmap = button.GetBitmap()
+
+ dc.DrawBitmap(bitmap, pos.x, pos.y, True)
+
+
+ def DrawReflections(self, dc):
+ """
+ Draws all the reflection button bitmaps on the :class:`ZoomBar` client window.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ if self._showReflections:
+ for button in self._reflectionButtons:
+ pos = button.GetPosition()
+ bitmap = button.GetBitmap()
+
+ dc.DrawBitmap(bitmap, pos.x, pos.y, True)
+
+
+ def DrawLabels(self, dc):
+ """
+ Draws all the button labels on the :class:`ZoomBar` client window.
+
+ :param `dc`: an instance of :class:`DC`.
+ """
+
+ if not self._showLabels:
+ return
+
+ dc.SetBrush(wx.WHITE_BRUSH)
+ dc.SetPen(wx.BLACK_PEN)
+
+ for button in self._buttons:
+ if not button.IsZoomed():
+ continue
+ label = button.GetLabel()
+ if not label:
+ continue
+
+ textWidth, textHeight = dc.GetTextExtent(label)
+ buttonPos = button.GetPosition()
+ buttonSize = button.GetSize()
+ xpos = buttonPos.x + (buttonSize.width - textWidth)/2
+ ypos = buttonPos.y - textHeight - 2
+
+ dc.DrawRectangle(xpos-2, ypos-1, textWidth+4, textHeight+2)
+ dc.DrawText(label, xpos, ypos)
+
+
+ def OnEraseBackground(self, event):
+ """
+ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`ZoomBar`.
+
+ :param `event`: a :class:`EraseEvent` event to be processed.
+
+ :note: This method is intentionally empty to avoid flicker.
+ """
+
+ pass
+
+
+ def OnMotion(self, event):
+ """
+ Handles the ``wx.EVT_MOTION`` event for :class:`ZoomBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ pos = event.GetPosition()
+ hit = self.HitTest(pos)
+
+ if hit >= 0:
+ button = self._buttons[hit]
+ if not button.ZoomImage(pos.x):
+ return
+
+ self.Reposition(button)
+ else:
+
+ if self._previousHit < 0:
+ return
+
+ for button in self._buttons:
+ button.SetSize(self._buttonSize, self._buttonSize)
+
+ self.InitialReposition()
+
+ self._previousHit = hit
+ self.Refresh()
+
+
+ def OnLeftDown(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_DOWN`` and ``wx.EVT_LEFT_DCLICK`` events for :class:`ZoomBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ self._currentHit = self.HitTest(event.GetPosition())
+
+
+ def OnLeftUp(self, event):
+ """
+ Handles the ``wx.EVT_LEFT_UP`` event for :class:`ZoomBar`.
+
+ :param `event`: a :class:`MouseEvent` event to be processed.
+ """
+
+ if self.HitTest(event.GetPosition()) != self._currentHit:
+ return
+
+ if not self.IsButtonEnabled(self._currentHit):
+ return
+
+ eventOut = ZoomBarEvent(wxEVT_ZOOMBAR, self.GetId())
+ eventOut.SetSelection(self._currentHit)
+ eventOut.SetLabel(self._buttons[self._currentHit].GetLabel())
+ eventOut.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+
+ def HitTest(self, pos):
+ """
+ HitTest method for :class:`ZoomBar`.
+
+ :param `pos`: the current mouse position.
+
+ :return: an index representing the button on which the mouse is hovering,
+ or ``wx.NOT_FOUND`` if no button has been hit.
+ """
+
+ for index, button in enumerate(self._buttons):
+ buttonPos = button.GetPosition()
+ if pos.x >= buttonPos.x and pos.x <= buttonPos.x + button._width:
+ return index
+
+ return wx.NOT_FOUND
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/__init__.py
new file mode 100644
index 0000000..03c3bc8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/__init__.py
@@ -0,0 +1,144 @@
+__author__ = "E. A. Tacao <e.a.tacao |at| estadao.com.br>"
+__date__ = "15 Fev 2006, 22:00 GMT-03:00"
+__version__ = "0.02"
+__doc__ = """
+AnalogClock - an analog clock.
+
+This control creates an analog clock window. Its features include shadowing,
+the ability to render numbers as well as any arbitrary polygon as tick marks,
+resize marks and hands proportionally as the widget itself is resized, rotate
+marks in a way the get aligned to the watch. It also has a dialog, accessed
+via a context menu item, allowing one to change on the fly all of its settings.
+
+
+Usage:
+
+ AnalogClock(parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.NO_BORDER, name="AnalogClock",
+ clockStyle=DEFAULT_CLOCK_STYLE,
+ minutesStyle=TICKS_CIRCLE, hoursStyle=TICKS_POLY)
+
+- parent, id, pos, size, style and name are used as in a wx.Window. Please
+ refer to the wx.Window docs for more details.
+
+- clockStyle defines the clock style, according to the options below:
+
+ ==================== ================================
+ SHOW_QUARTERS_TICKS Show marks for hours 3, 6, 9, 12
+ SHOW_HOURS_TICKS Show marks for all hours
+ SHOW_MINUTES_TICKS Show marks for minutes
+
+ SHOW_HOURS_HAND Show hours hand
+ SHOW_MINUTES_HAND Show minutes hand
+ SHOW_SECONDS_HAND Show seconds hand
+
+ SHOW_SHADOWS Show hands and marks shadows
+
+ ROTATE_TICKS Align tick marks to watch
+ OVERLAP_TICKS Draw tick marks for minutes even
+ when they match the hours marks.
+
+ DEFAULT_CLOCK_STYLE The same as SHOW_HOURS_TICKS|
+ SHOW_MINUTES_TICKS|
+ SHOW_HOURS_HAND|
+ SHOW_MINUTES_HAND|
+ SHOW_SECONDS_HAND|
+ SHOW_SHADOWS|ROTATE_TICKS
+ ==================== ================================
+
+- minutesStyle and hoursStyle define the the tick styles, according to the
+ options below:
+
+ ================= ======================================
+ TICKS_NONE Don't show tick marks.
+ TICKS_SQUARE Use squares as tick marks.
+ TICKS_CIRCLE Use circles as tick marks.
+ TICKS_POLY Use a polygon as tick marks. A
+ polygon can be passed using
+ SetTickPolygon, otherwise the default
+ polygon will be used.
+ TICKS_DECIMAL Use decimal numbers as tick marks.
+ TICKS_ROMAN Use Roman numbers as tick marks.
+ TICKS_BINARY Use binary numbers as tick marks.
+ TICKS_HEX Use hexadecimal numbers as tick marks.
+ ================= ======================================
+
+
+Notes:
+
+The 'target' keyword that's present in various of the AnalogClock methods may
+accept one (or more, combined using '|') of the following values:
+
+ ========= ===========================================
+ HOUR The values passed/retrieved are related to
+ the hours hand/ticks
+
+ MINUTE The values passed/retrieved are related to
+ the minutes hand/ticks
+
+ SECOND The values passed/retrieved are related to
+ the seconds hand/ticks
+
+ ALL The same as HOUR|MINUTE|SECOND, i. e., the
+ values passed/retrieved are related to all
+ of the hours hands/ticks. This is the
+ default value in all methods.
+ ========= ===========================================
+
+It is legal to pass target=ALL to methods that don't handle seconds (tick
+mark related methods). In such cases, ALL will be equivalent to HOUR|MINUTE.
+
+All of the 'Get' AnalogClock methods that allow the 'target' keyword
+will always return a tuple, e. g.:
+
+ ================================= ========================================
+ GetHandSize(target=HOUR) Returns a 1 element tuple, containing
+ the size of the hours hand.
+
+ GetHandSize(target=HOUR|MINUTE) Returns a 2 element tuple, containing
+ the sizes of the hours and the minutes
+ hands, respectively.
+
+ GetHandSize(target=ALL) Returns a 3 element tuple, containing
+ or the sizes of the hours, minutes and
+ GetHandSize() seconds hands, respectively.
+ ================================= ========================================
+
+
+About:
+
+Most of the ideas and part of the code of AnalogClock were based on the
+original wxPython's AnalogClock module, which was created by several folks on
+the wxPython-users list.
+
+AnalogClock is distributed under the wxWidgets license.
+
+This code should meet the wxPython Coding Guidelines
+<http://www.wxpython.org/codeguidelines.php> and the wxPython Style Guide
+<http://wiki.wxpython.org/index.cgi/wxPython_20Style_20Guide>.
+
+For all kind of problems, requests, enhancements, bug reports, etc,
+please drop me an e-mail.
+
+For updates please visit <http://j.domaindlx.com/elements28/wxpython/>.
+"""
+
+# History:
+#
+# Version 0.02:
+# - Module/namespace rearranges;
+# - All '-1' occurrences meaning "use any id" were eliminated or replaced
+# to 'wx.ID_ANY'.
+# - Better names to the methods triggered by the context menu events.
+# - Included small demo class code in analogclock.py.
+# Version 0.01:
+# - Initial release.
+
+#----------------------------------------------------------------------
+
+from analogclock import AnalogClock, AnalogClockWindow
+from styles import *
+
+#
+##
+### eof
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/analogclock.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/analogclock.py
new file mode 100644
index 0000000..16a7c4d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/analogclock.py
@@ -0,0 +1,633 @@
+# AnalogClock's main class
+# E. A. Tacao <e.a.tacao |at| estadao.com.br>
+# http://j.domaindlx.com/elements28/wxpython/
+# 15 Fev 2006, 22:00 GMT-03:00
+# Distributed under the wxWidgets license.
+#
+# For more info please see the __init__.py file.
+
+import wx
+
+from styles import *
+from helpers import Dyer, Face, Hand, HandSet, TickSet, Box
+from setup import Setup
+
+#----------------------------------------------------------------------
+
+class AnalogClock(wx.PyWindow):
+ """An analog clock."""
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.NO_BORDER, name="AnalogClock",
+ clockStyle=DEFAULT_CLOCK_STYLE,
+ minutesStyle=TICKS_CIRCLE, hoursStyle=TICKS_POLY):
+
+ wx.PyWindow.__init__(self, parent, id, pos, size, style, name)
+
+ # Base size for scale calc purposes.
+ self.basesize = wx.Size(348, 348)
+
+ # Store some references.
+ self.clockStyle = clockStyle
+ self.minutesStyle = minutesStyle
+ self.hoursStyle = hoursStyle
+
+ self.DrawHands = self._drawHands
+ self.DrawBox = self._drawBox
+ self.RecalcCoords = self._recalcCoords
+
+ self.shadowOffset = 3
+
+ self.allHandStyles = [SHOW_HOURS_HAND,
+ SHOW_MINUTES_HAND,
+ SHOW_SECONDS_HAND]
+
+ # Initialize clock face.
+ #
+ # By default we don't use colours or borders on the clock face.
+ bg = self.GetBackgroundColour()
+ face = Face(dyer=Dyer(bg, 0, bg))
+
+ # Initialize tick marks.
+ #
+ # TickSet is a set of tick marks; there's always two TickSets defined
+ # regardless whether they're being shown or not.
+ ticksM = TickSet(self, style=minutesStyle, size=5, kind="minutes")
+ ticksH = TickSet(self, style=hoursStyle, size=25, kind="hours",
+ rotate=clockStyle&ROTATE_TICKS)
+
+ # Box holds the clock face and tick marks.
+ self.Box = Box(self, face, ticksM, ticksH)
+
+ # Initialize hands.
+ #
+ # HandSet is the set of hands; there's always one HandSet defined
+ # regardless whether hands are being shown or not.
+ #
+ # A 'lenfac = 0.95', e.g., means that the lenght of that hand will
+ # be 95% of the maximum allowed hand lenght ('nice' maximum lenght).
+ handH = Hand(size=7, lenfac=0.7)
+ handM = Hand(size=5, lenfac=0.95)
+ handS = Hand(size=1, lenfac=0.95)
+ self.Hands = HandSet(self, handH, handM, handS)
+
+ # Create the customization dialog.
+ self.Setup = None
+
+ # Make a context menu.
+ popup1 = wx.NewId()
+ popup2 = wx.NewId()
+ cm = self.cm = wx.Menu()
+ cm.Append(popup1, "Customize...")
+ cm.Append(popup2, "About...")
+
+ # Set event handlers.
+ self.Bind(wx.EVT_SIZE, self._OnSize)
+ self.Bind(wx.EVT_PAINT, self._OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda evt: None)
+ self.Bind(wx.EVT_TIMER, self._OnTimer)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self._OnDestroyWindow)
+ self.Bind(wx.EVT_CONTEXT_MENU, self._OnContextMenu)
+ self.Bind(wx.EVT_MENU, self._OnShowSetup, id=popup1)
+ self.Bind(wx.EVT_MENU, self._OnShowAbout, id=popup2)
+
+ # Set initial size based on given size, or best size
+ self.SetInitialSize(size)
+
+ # Do initial drawing (in case there is not an initial size event)
+ self.RecalcCoords(self.GetSize())
+ self.DrawBox()
+
+ # Initialize the timer that drives the update of the clock face.
+ # Update every half second to ensure that there is at least one true
+ # update during each realtime second.
+ self.timer = wx.Timer(self)
+ self.timer.Start(500)
+
+
+ def DoGetBestSize(self):
+ # Just pull a number out of the air. If there is a way to
+ # calculate this then it should be done...
+ size = wx.Size(50,50)
+ self.CacheBestSize(size)
+ return size
+
+
+ def _OnSize(self, evt):
+ size = self.GetClientSize()
+ if size.x < 1 or size.y < 1:
+ return
+
+ self.RecalcCoords(size)
+ self.DrawBox()
+
+
+ def _OnPaint(self, evt):
+ dc = wx.BufferedPaintDC(self)
+ self.DrawHands(dc)
+
+
+ def _OnTimer(self, evt):
+ self.Refresh(False)
+ self.Update()
+
+
+ def _OnDestroyWindow(self, evt):
+ self.timer.Stop()
+ del self.timer
+
+
+ def _OnContextMenu(self, evt):
+ self.PopupMenu(self.cm)
+
+
+ def _OnShowSetup(self, evt):
+ if self.Setup is None:
+ self.Setup = Setup(self)
+ self.Setup.Show()
+ self.Setup.Raise()
+
+
+ def _OnShowAbout(self, evt):
+ msg = "AnalogClock\n\n" \
+ "by Several folks on wxPython-users\n" \
+ "with enhancements from E. A. Tacao."
+ title = "About..."
+ style = wx.OK|wx.ICON_INFORMATION
+
+ dlg = wx.MessageDialog(self, msg, title, style)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+
+ def _recalcCoords(self, size):
+ """
+ Recalculates all coordinates/geometry and inits the faceBitmap
+ to make sure the buffer is always the same size as the window.
+ """
+
+ self.faceBitmap = wx.EmptyBitmap(*size.Get())
+
+ # Recalc all coords.
+ scale = min([float(size.width) / self.basesize.width,
+ float(size.height) / self.basesize.height])
+
+ centre = wx.Point(size.width / 2., size.height / 2.)
+
+ self.Box.RecalcCoords(size, centre, scale)
+ self.Hands.RecalcCoords(size, centre, scale)
+
+ # Try to find a 'nice' maximum length for the hands so that they won't
+ # overlap the tick marks. OTOH, if you do want to allow overlapping the
+ # lenfac value (defined on __init__ above) has to be set to
+ # something > 1.
+ niceradius = self.Box.GetNiceRadiusForHands(centre)
+ self.Hands.SetMaxRadius(niceradius)
+
+
+ def _drawBox(self):
+ """Draws clock face and tick marks onto the faceBitmap."""
+ dc = wx.BufferedDC(None, self.faceBitmap)
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour(), wx.SOLID))
+ dc.Clear()
+ self.Box.Draw(dc)
+
+
+ def _drawHands(self, dc):
+ """
+ Draws the face bitmap, created on the last DrawBox call, and
+ clock hands.
+ """
+ dc.DrawBitmap(self.faceBitmap, 0, 0)
+ self.Hands.Draw(dc)
+
+
+ # Public methods --------------------------------------------------
+
+ def GetHandSize(self, target=ALL):
+ """Gets thickness of hands."""
+
+ return self.Hands.GetSize(target)
+
+
+ def GetHandFillColour(self, target=ALL):
+ """Gets fill colours of hands."""
+
+ return self.Hands.GetFillColour(target)
+
+
+ def GetHandBorderColour(self, target=ALL):
+ """Gets border colours of hands."""
+
+ return self.Hands.GetBorderColour(target)
+
+
+ def GetHandBorderWidth(self, target=ALL):
+ """Gets border widths of hands."""
+
+ return self.Hands.GetBorderWidth(target)
+
+
+ def GetTickSize(self, target=ALL):
+ """Gets sizes of ticks."""
+
+ return self.Box.GetTickSize(target)
+
+
+
+ def GetTickFillColour(self, target=ALL):
+ """Gets fill colours of ticks."""
+
+ return self.Box.GetTickFillColour(target)
+
+
+
+ def GetTickBorderColour(self, target=ALL):
+ """Gets border colours of ticks."""
+
+ return self.Box.GetTickBorderColour(target)
+
+
+
+ def GetTickBorderWidth(self, target=ALL):
+ """Gets border widths of ticks."""
+
+ return self.Box.GetTickBorderWidth(target)
+
+
+
+ def GetTickPolygon(self, target=ALL):
+ """
+ Gets lists of points to be used as polygon shapes
+ when using the TICKS_POLY style.
+ """
+
+ return self.Box.GetTickPolygon(target)
+
+
+
+ def GetTickFont(self, target=ALL):
+ """
+ Gets fonts for tick marks when using TICKS_DECIMAL or
+ TICKS_ROMAN style.
+ """
+
+ return self.Box.GetTickFont(target)
+
+
+
+ def GetTickOffset(self, target=ALL):
+ """Gets the distance of tick marks for hours from border."""
+
+ return self.Box.GetTickOffset(target)
+
+
+
+ def GetFaceFillColour(self):
+ """Gets fill colours of watch."""
+
+ return self.Box.Face.GetFillColour()
+
+
+
+ def GetFaceBorderColour(self):
+ """Gets border colours of watch."""
+
+ return self.Box.Face.GetBorderColour()
+
+
+
+ def GetFaceBorderWidth(self):
+ """Gets border width of watch."""
+
+ return self.Box.Face.GetBorderWidth()
+
+
+
+ def GetShadowColour(self):
+ """Gets the colour to be used to draw shadows."""
+
+ a_clock_part = self.Box
+ return a_clock_part.GetShadowColour()
+
+
+
+ def GetClockStyle(self):
+ """Returns the current clock style."""
+
+ return self.clockStyle
+
+
+ def GetTickStyle(self, target=ALL):
+ """Gets the tick style(s)."""
+
+ return self.Box.GetTickStyle(target)
+
+
+ def Reset(self):
+ """
+ Forces an immediate recalculation and redraw of all clock
+ elements.
+ """
+ size = self.GetClientSize()
+ if size.x < 1 or size.y < 1:
+ return
+ self.RecalcCoords(size)
+ self.DrawBox()
+ self.Refresh(False)
+
+
+ def SetHandSize(self, size, target=ALL):
+ """Sets thickness of hands."""
+
+ self.Hands.SetSize(size, target)
+
+
+ def SetHandFillColour(self, colour, target=ALL):
+ """Sets fill colours of hands."""
+
+ self.Hands.SetFillColour(colour, target)
+
+
+ def SetHandBorderColour(self, colour, target=ALL):
+ """Sets border colours of hands."""
+
+ self.Hands.SetBorderColour(colour, target)
+
+
+ def SetHandBorderWidth(self, width, target=ALL):
+ """Sets border widths of hands."""
+
+ self.Hands.SetBorderWidth(width, target)
+
+
+ def SetTickSize(self, size, target=ALL):
+ """Sets sizes of ticks."""
+
+ self.Box.SetTickSize(size, target)
+ self.Reset()
+
+
+ def SetTickFillColour(self, colour, target=ALL):
+ """Sets fill colours of ticks."""
+
+ self.Box.SetTickFillColour(colour, target)
+ self.Reset()
+
+
+ def SetTickBorderColour(self, colour, target=ALL):
+ """Sets border colours of ticks."""
+
+ self.Box.SetTickBorderColour(colour, target)
+ self.Reset()
+
+
+ def SetTickBorderWidth(self, width, target=ALL):
+ """Sets border widths of ticks."""
+
+ self.Box.SetTickBorderWidth(width, target)
+ self.Reset()
+
+
+ def SetTickPolygon(self, polygon, target=ALL):
+ """
+ Sets lists of points to be used as polygon shapes
+ when using the TICKS_POLY style.
+ """
+
+ self.Box.SetTickPolygon(polygon, target)
+ self.Reset()
+
+
+ def SetTickFont(self, font, target=ALL):
+ """
+ Sets fonts for tick marks when using text-based tick styles
+ such as TICKS_DECIMAL or TICKS_ROMAN.
+ """
+
+ self.Box.SetTickFont(font, target)
+ self.Reset()
+
+
+ def SetTickOffset(self, offset, target=ALL):
+ """Sets the distance of tick marks for hours from border."""
+
+ self.Box.SetTickOffset(offset, target)
+ self.Reset()
+
+
+ def SetFaceFillColour(self, colour):
+ """Sets fill colours of watch."""
+
+ self.Box.Face.SetFillColour(colour)
+ self.Reset()
+
+
+ def SetFaceBorderColour(self, colour):
+ """Sets border colours of watch."""
+
+ self.Box.Face.SetBorderColour(colour)
+ self.Reset()
+
+
+ def SetFaceBorderWidth(self, width):
+ """Sets border width of watch."""
+
+ self.Box.Face.SetBorderWidth(width)
+ self.Reset()
+
+
+ def SetShadowColour(self, colour):
+ """Sets the colour to be used to draw shadows."""
+
+ self.Hands.SetShadowColour(colour)
+ self.Box.SetShadowColour(colour)
+ self.Reset()
+
+
+ def SetClockStyle(self, style):
+ """
+ Set the clock style, according to the options below.
+
+ ==================== ================================
+ SHOW_QUARTERS_TICKS Show marks for hours 3, 6, 9, 12
+ SHOW_HOURS_TICKS Show marks for all hours
+ SHOW_MINUTES_TICKS Show marks for minutes
+
+ SHOW_HOURS_HAND Show hours hand
+ SHOW_MINUTES_HAND Show minutes hand
+ SHOW_SECONDS_HAND Show seconds hand
+
+ SHOW_SHADOWS Show hands and marks shadows
+
+ ROTATE_TICKS Align tick marks to watch
+ OVERLAP_TICKS Draw tick marks for minutes even
+ when they match the hours marks.
+ ==================== ================================
+ """
+
+ self.clockStyle = style
+ self.Box.SetIsRotated(style & ROTATE_TICKS)
+ self.Reset()
+
+
+ def SetTickStyle(self, style, target=ALL):
+ """
+ Set the tick style, according to the options below.
+
+ ================= ======================================
+ TICKS_NONE Don't show tick marks.
+ TICKS_SQUARE Use squares as tick marks.
+ TICKS_CIRCLE Use circles as tick marks.
+ TICKS_POLY Use a polygon as tick marks. A
+ polygon can be passed using
+ SetTickPolygon, otherwise the default
+ polygon will be used.
+ TICKS_DECIMAL Use decimal numbers as tick marks.
+ TICKS_ROMAN Use Roman numbers as tick marks.
+ TICKS_BINARY Use binary numbers as tick marks.
+ TICKS_HEX Use hexadecimal numbers as tick marks.
+ ================= ======================================
+ """
+
+ self.Box.SetTickStyle(style, target)
+ self.Reset()
+
+
+ def SetBackgroundColour(self, colour):
+ """Overriden base wx.Window method."""
+
+ wx.Window.SetBackgroundColour(self, colour)
+ self.Reset()
+
+
+ def SetForegroundColour(self, colour):
+ """
+ Overriden base wx.Window method. This method sets a colour for
+ all hands and ticks at once.
+ """
+
+ wx.Window.SetForegroundColour(self, colour)
+ self.SetHandFillColour(colour)
+ self.SetHandBorderColour(colour)
+ self.SetTickFillColour(colour)
+ self.SetTickBorderColour(colour)
+ self.Reset()
+
+
+ def SetWindowStyle(self, *args, **kwargs):
+ """Overriden base wx.Window method."""
+
+ size = self.GetSize()
+ self.Freeze()
+ wx.Window.SetWindowStyle(self, *args, **kwargs)
+ self.SetSize((10, 10))
+ self.SetSize(size)
+ self.Thaw()
+
+
+ def SetWindowStyleFlag(self, *args, **kwargs):
+ """Overriden base wx.Window method."""
+
+ self.SetWindowStyle(*args, **kwargs)
+
+
+# For backwards compatibility -----------------------------------------
+
+class AnalogClockWindow(AnalogClock):
+ """
+ A simple derived class that provides some backwards compatibility
+ with the old analogclock module.
+ """
+ def SetTickShapes(self, tsh, tsm=None):
+ self.SetTickPolygon(tsh)
+
+ def SetHandWeights(self, h=None, m=None, s=None):
+ if h:
+ self.SetHandSize(h, HOUR)
+ if m:
+ self.SetHandSize(m, MINUTE)
+ if s:
+ self.SetHandSize(s, SECOND)
+
+ def SetHandColours(self, h=None, m=None, s=None):
+ if h and not m and not s:
+ m=h
+ s=h
+ if h:
+ self.SetHandBorderColour(h, HOUR)
+ self.SetHandFillColour(h, HOUR)
+ if m:
+ self.SetHandBorderColour(m, MINUTE)
+ self.SetHandFillColour(m, MINUTE)
+ if s:
+ self.SetHandBorderColour(s, SECOND)
+ self.SetHandFillColour(s, SECOND)
+
+ def SetTickColours(self, h=None, m=None):
+ if not m:
+ m=h
+ if h:
+ self.SetTickBorderColour(h, HOUR)
+ self.SetTickFillColour(h, HOUR)
+ if m:
+ self.SetTickBorderColour(m, MINUTE)
+ self.SetTickFillColour(m, MINUTE)
+
+ def SetTickSizes(self, h=None, m=None):
+ if h:
+ self.SetTickSize(h, HOUR)
+ if m:
+ self.SetTickSize(m, MINUTE)
+
+ def SetTickFontss(self, h=None, m=None):
+ if h:
+ self.SetTickFont(h, HOUR)
+ if m:
+ self.SetTickFont(m, MINUTE)
+
+
+ def SetMinutesOffset(self, o):
+ pass
+
+ def SetShadowColour(self, s):
+ pass
+
+ def SetWatchPenBrush(self, p=None, b=None):
+ if p:
+ self.SetFaceBorderColour(p.GetColour())
+ self.SetFaceBorderWidth(p.GetWidth())
+ if b:
+ self.SetFaceFillColour(b.GetColour())
+
+ def SetClockStyle(self, style):
+ style |= SHOW_HOURS_HAND|SHOW_MINUTES_HAND|SHOW_SECONDS_HAND
+ AnalogClock.SetClockStyle(self, style)
+
+ def SetTickStyles(self, h=None, m=None):
+ if h:
+ self.SetTickStyle(h, HOUR)
+ if m:
+ self.SetTickStyle(h, MINUTE)
+
+
+# Test stuff ----------------------------------------------------------
+
+if __name__ == "__main__":
+ print wx.VERSION_STRING
+
+ class AcDemoApp(wx.App):
+ def OnInit(self):
+ frame = wx.Frame(None, -1, "AnalogClock", size=(375, 375))
+ clock = AnalogClock(frame)
+ frame.CentreOnScreen()
+ frame.Show()
+ return True
+
+ acApp = AcDemoApp(0)
+ acApp.MainLoop()
+
+
+#
+##
+### eof
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/helpers.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/helpers.py
new file mode 100644
index 0000000..c459067
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/helpers.py
@@ -0,0 +1,985 @@
+# AnalogClock's base classes
+# E. A. Tacao <e.a.tacao |at| estadao.com.br>
+# http://j.domaindlx.com/elements28/wxpython/
+# 15 Fev 2006, 22:00 GMT-03:00
+# Distributed under the wxWidgets license.
+
+from time import strftime, localtime
+import math
+import wx
+
+from styles import *
+
+#----------------------------------------------------------------------
+
+_targets = [HOUR, MINUTE, SECOND]
+
+#----------------------------------------------------------------------
+
+class Element:
+ """Base class for face, hands and tick marks."""
+
+ def __init__(self, idx=0, pos=None, size=None, offset=0, clocksize=None,
+ scale=1, rotate=False, kind=""):
+
+ self.idx = idx
+ self.pos = pos
+ self.size = size
+ self.offset = offset
+ self.clocksize = clocksize
+ self.scale = scale
+ self.rotate = rotate
+ self.kind = kind
+
+ self.text = None
+ self.angfac = [6, 30][self.kind == "hours"]
+
+
+ def _pol2rect(self, m, t):
+ return m * math.cos(math.radians(t)), m * math.sin(math.radians(t))
+
+
+ def _rect2pol(self, x, y):
+ return math.hypot(x, y), math.degrees(math.atan2(y, x))
+
+
+ def DrawRotated(self, dc, offset=0):
+ pass
+
+
+ def DrawStraight(self, dc, offset=0):
+ pass
+
+
+ def Draw(self, dc, offset=0):
+ if self.rotate:
+ self.DrawRotated(dc, offset)
+ else:
+ self.DrawStraight(dc, offset)
+
+
+ def RecalcCoords(self, clocksize, centre, scale):
+ pass
+
+
+ def GetSize(self):
+ return self.size
+
+
+ def GetOffset(self):
+ return self.offset
+
+
+ def GetIsRotated(self, rotate):
+ return self.rotate
+
+
+ def GetMaxSize(self, scale=1):
+ return self.size * scale
+
+
+ def GetScale(self):
+ return self.scale
+
+
+ def SetIsRotated(self, rotate):
+ self.rotate = rotate
+
+
+ def GetMaxSize(self, scale=1):
+ return self.size * scale
+
+
+ def GetPolygon(self):
+ return self.polygon
+
+
+ def SetPosition(self, pos):
+ self.pos = pos
+
+
+ def SetSize(self, size):
+ self.size = size
+
+
+ def SetOffset(self, offset):
+ self.offset = offset
+
+
+ def SetClockSize(self, clocksize):
+ self.clocksize = clocksize
+
+
+ def SetScale(self, scale):
+ self.scale = scale
+
+
+ def SetIsRotated(self, rotate):
+ self.rotate = rotate
+
+
+ def SetPolygon(self, polygon):
+ self.polygon = polygon
+
+#----------------------------------------------------------------------
+
+class ElementWithDyer(Element):
+ """Base class for clock face and hands."""
+
+ def __init__(self, **kwargs):
+ self.dyer = kwargs.pop("dyer", Dyer())
+ Element.__init__(self, **kwargs)
+
+
+ def GetFillColour(self):
+ return self.dyer.GetFillColour()
+
+
+ def GetBorderColour(self):
+ return self.dyer.GetBorderColour()
+
+
+ def GetBorderWidth(self):
+ return self.dyer.GetBorderWidth()
+
+
+ def GetShadowColour(self):
+ return self.dyer.GetShadowColour()
+
+
+ def SetFillColour(self, colour):
+ self.dyer.SetFillColour(colour)
+
+
+ def SetBorderColour(self, colour):
+ self.dyer.SetBorderColour(colour)
+
+
+ def SetBorderWidth(self, width):
+ self.dyer.SetBorderWidth(width)
+
+
+ def SetShadowColour(self, colour):
+ self.dyer.SetShadowColour(colour)
+
+#----------------------------------------------------------------------
+
+class Face(ElementWithDyer):
+ """Holds info about the clock face."""
+
+ def __init__(self, **kwargs):
+ ElementWithDyer.__init__(self, **kwargs)
+
+
+ def Draw(self, dc):
+ self.dyer.Select(dc)
+ dc.DrawCircle(self.pos.x, self.pos.y, self.radius)
+
+
+ def RecalcCoords(self, clocksize, centre, scale):
+ self.radius = min(clocksize.Get()) / 2. - self.dyer.width / 2.
+ self.pos = centre
+
+#----------------------------------------------------------------------
+
+class Hand(ElementWithDyer):
+ """Holds info about a clock hand."""
+
+ def __init__(self, **kwargs):
+ self.lenfac = kwargs.pop("lenfac")
+ ElementWithDyer.__init__(self, **kwargs)
+
+ self.SetPolygon([[-1, 0], [0, -1], [1, 0], [0, 4]])
+
+
+ def Draw(self, dc, end, offset=0):
+ radius, centre, r = end
+ angle = math.degrees(r)
+ polygon = self.polygon[:]
+ vscale = radius / max([y for x, y in polygon])
+
+ for i, (x, y) in enumerate(polygon):
+ x *= self.scale * self.size
+ y *= vscale * self.lenfac
+ m, t = self._rect2pol(x, y)
+ polygon[i] = self._pol2rect(m, t - angle)
+
+ dc.DrawPolygon(polygon, centre.x + offset, centre.y + offset)
+
+
+ def RecalcCoords(self, clocksize, centre, scale):
+ self.pos = centre
+ self.scale = scale
+
+#----------------------------------------------------------------------
+
+class TickSquare(Element):
+ """Holds info about a tick mark."""
+
+ def __init__(self, **kwargs):
+ Element.__init__(self, **kwargs)
+
+
+ def Draw(self, dc, offset=0):
+ width = height = self.size * self.scale
+ x = self.pos.x - width / 2.
+ y = self.pos.y - height / 2.
+
+ dc.DrawRectangle(x + offset, y + offset, width, height)
+
+#----------------------------------------------------------------------
+
+class TickCircle(Element):
+ """Holds info about a tick mark."""
+
+ def __init__(self, **kwargs):
+ Element.__init__(self, **kwargs)
+
+
+ def Draw(self, dc, offset=0):
+ radius = self.size * self.scale / 2.
+ x = self.pos.x
+ y = self.pos.y
+
+ dc.DrawCircle(x + offset, y + offset, radius)
+
+#----------------------------------------------------------------------
+
+class TickPoly(Element):
+ """Holds info about a tick mark."""
+
+ def __init__(self, **kwargs):
+ Element.__init__(self, **kwargs)
+
+ self.SetPolygon([[0, 1], [1, 0], [2, 1], [1, 5]])
+
+
+ def _calcPolygon(self):
+ width = max([x for x, y in self.polygon])
+ height = max([y for x, y in self.polygon])
+ tscale = self.size / max(width, height) * self.scale
+ polygon = [(x * tscale, y * tscale) for x, y in self.polygon]
+
+ width = max([x for x, y in polygon])
+ height = max([y for x, y in polygon])
+
+ return polygon, width, height
+
+
+ def DrawStraight(self, dc, offset=0):
+ polygon, width, height = self._calcPolygon()
+
+ x = self.pos.x - width / 2.
+ y = self.pos.y - height / 2.
+
+ dc.DrawPolygon(polygon, x + offset, y + offset)
+
+
+ def DrawRotated(self, dc, offset=0):
+ polygon, width, height = self._calcPolygon()
+
+ angle = 360 - self.angfac * (self.idx + 1)
+ r = math.radians(angle)
+
+ for i in range(len(polygon)):
+ m, t = self._rect2pol(*polygon[i])
+ t -= angle
+ polygon[i] = self._pol2rect(m, t)
+
+ x = self.pos.x - math.cos(r) * width / 2. - math.sin(r) * height / 2.
+ y = self.pos.y - math.cos(r) * height / 2. + math.sin(r) * width / 2.
+
+ dc.DrawPolygon(polygon, x + offset, y + offset)
+
+#----------------------------------------------------------------------
+
+class TickDecimal(Element):
+ """Holds info about a tick mark."""
+
+ def __init__(self, **kwargs):
+ Element.__init__(self, **kwargs)
+
+ self.text = "%s" % (self.idx + 1)
+
+
+ def DrawStraight(self, dc, offset=0):
+ width, height = dc.GetTextExtent(self.text)
+
+ x = self.pos.x - width / 2.
+ y = self.pos.y - height / 2.
+
+ dc.DrawText(self.text, x + offset, y + offset)
+
+
+ def DrawRotated(self, dc, offset=0):
+ width, height = dc.GetTextExtent(self.text)
+
+ angle = 360 - self.angfac * (self.idx + 1)
+ r = math.radians(angle)
+
+ x = self.pos.x - math.cos(r) * width / 2. - math.sin(r) * height / 2.
+ y = self.pos.y - math.cos(r) * height / 2. + math.sin(r) * width / 2.
+
+ dc.DrawRotatedText(self.text, x + offset, y + offset, angle)
+
+
+#----------------------------------------------------------------------
+
+class TickRoman(TickDecimal):
+ """Holds info about a tick mark."""
+
+ def __init__(self, **kwargs):
+ TickDecimal.__init__(self, **kwargs)
+
+ self.text = ["I","II","III","IV","V", \
+ "VI","VII","VIII","IX","X", \
+ "XI","XII","XIII","XIV","XV", \
+ "XVI","XVII","XVIII","XIX","XX", \
+ "XXI","XXII","XXIII","XXIV","XXV", \
+ "XXVI","XXVII","XXVIII","XXIX","XXX", \
+ "XXXI","XXXII","XXXIII","XXXIV","XXXV", \
+ "XXXVI","XXXVII","XXXVIII","XXXIX","XL", \
+ "XLI","XLII","XLIII","XLIV","XLV", \
+ "XLVI","XLVII","XLVIII","XLIX","L", \
+ "LI","LII","LIII","LIV","LV", \
+ "LVI","LVII","LVIII","LIX","LX"][self.idx]
+
+#----------------------------------------------------------------------
+
+class TickBinary(TickDecimal):
+ """Holds info about a tick mark."""
+
+ def __init__(self, **kwargs):
+ TickDecimal.__init__(self, **kwargs)
+
+ def d2b(n, b=""):
+ while n > 0:
+ b = str(n % 2) + b; n = n >> 1
+ return b.zfill(4)
+
+ self.text = d2b(self.idx + 1)
+
+#----------------------------------------------------------------------
+
+class TickHex(TickDecimal):
+ """Holds info about a tick mark."""
+
+ def __init__(self, **kwargs):
+ TickDecimal.__init__(self, **kwargs)
+
+ self.text = hex(self.idx + 1)[2:].upper()
+
+#----------------------------------------------------------------------
+
+class TickNone(Element):
+ """Holds info about a tick mark."""
+
+ def __init__(self, **kwargs):
+ Element.__init__(self, **kwargs)
+
+
+ def Draw(self, dc, offset=0):
+ pass
+
+#----------------------------------------------------------------------
+
+class Dyer:
+ """Stores info about colours and borders of clock Elements."""
+
+ def __init__(self, border=None, width=0, fill=None, shadow=None):
+ """
+ self.border (wx.Colour) border colour
+ self.width (int) border width
+ self.fill (wx.Colour) fill colour
+ self.shadow (wx.Colour) shadow colour
+ """
+
+ self.border = border or \
+ wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ self.fill = fill or \
+ wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ self.shadow = shadow or \
+ wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DSHADOW)
+ self.width = width
+
+
+ def Select(self, dc, shadow=False):
+ """Selects the current settings into the dc."""
+
+ if not shadow:
+ dc.SetPen(wx.Pen(self.border, self.width, wx.SOLID))
+ dc.SetBrush(wx.Brush(self.fill, wx.SOLID))
+ dc.SetTextForeground(self.fill)
+ else:
+ dc.SetPen(wx.Pen(self.shadow, self.width, wx.SOLID))
+ dc.SetBrush(wx.Brush(self.shadow, wx.SOLID))
+ dc.SetTextForeground(self.shadow)
+
+
+ def GetFillColour(self):
+ return self.fill
+
+
+ def GetBorderColour(self):
+ return self.border
+
+
+ def GetBorderWidth(self):
+ return self.width
+
+
+ def GetShadowColour(self):
+ return self.shadow
+
+
+ def SetFillColour(self, colour):
+ self.fill = colour
+
+
+ def SetBorderColour(self, colour):
+ self.border = colour
+
+
+ def SetBorderWidth(self, width):
+ self.width = width
+
+
+ def SetShadowColour(self, colour):
+ self.shadow = colour
+
+#----------------------------------------------------------------------
+
+class HandSet:
+ """Manages the set of hands."""
+
+ def __init__(self, parent, h, m, s):
+ self.parent = parent
+
+ self.hands = [h, m, s]
+ self.radius = 1
+ self.centre = wx.Point(1, 1)
+
+
+ def _draw(self, dc, shadow=False):
+ ends = [int(x) for x in strftime("%I %M %S", localtime()).split()]
+
+ flags = [self.parent.clockStyle & flag \
+ for flag in self.parent.allHandStyles]
+
+ a_hand = self.hands[0]
+
+ if shadow:
+ offset = self.parent.shadowOffset * a_hand.GetScale()
+ else:
+ offset = 0
+
+ for i, hand in enumerate(self.hands):
+ # Is this hand supposed to be drawn?
+ if flags[i]:
+ idx = ends[i]
+ # Is this the hours hand?
+ if i == 0:
+ idx = idx * 5 + ends[1] / 12 - 1
+ # else prevent exceptions on leap seconds
+ elif idx <= 0 or idx > 60:
+ idx = 59
+ # and adjust idx offset for minutes and non-leap seconds
+ else:
+ idx = idx - 1
+ angle = math.radians(180 - 6 * (idx + 1))
+
+ hand.dyer.Select(dc, shadow)
+ hand.Draw(dc, (self.radius, self.centre, angle), offset)
+
+
+ def Draw(self, dc):
+ if self.parent.clockStyle & SHOW_SHADOWS:
+ self._draw(dc, True)
+ self._draw(dc)
+
+
+ def RecalcCoords(self, clocksize, centre, scale):
+ self.centre = centre
+ [hand.RecalcCoords(clocksize, centre, scale) for hand in self.hands]
+
+
+ def SetMaxRadius(self, radius):
+ self.radius = radius
+
+
+ def GetSize(self, target):
+ r = []
+ for i, hand in enumerate(self.hands):
+ if _targets[i] & target:
+ r.append(hand.GetSize())
+ return tuple(r)
+
+
+ def GetFillColour(self, target):
+ r = []
+ for i, hand in enumerate(self.hands):
+ if _targets[i] & target:
+ r.append(hand.GetFillColour())
+ return tuple(r)
+
+
+ def GetBorderColour(self, target):
+ r = []
+ for i, hand in enumerate(self.hands):
+ if _targets[i] & target:
+ r.append(hand.GetBorderColour())
+ return tuple(r)
+
+
+ def GetBorderWidth(self, target):
+ r = []
+ for i, hand in enumerate(self.hands):
+ if _targets[i] & target:
+ r.append(hand.GetBorderWidth())
+ return tuple(r)
+
+
+ def GetShadowColour(self):
+ r = []
+ for i, hand in enumerate(self.hands):
+ if _targets[i] & target:
+ r.append(hand.GetShadowColour())
+ return tuple(r)
+
+
+ def SetSize(self, size, target):
+ for i, hand in enumerate(self.hands):
+ if _targets[i] & target:
+ hand.SetSize(size)
+
+
+ def SetFillColour(self, colour, target):
+ for i, hand in enumerate(self.hands):
+ if _targets[i] & target:
+ hand.SetFillColour(colour)
+
+
+ def SetBorderColour(self, colour, target):
+ for i, hand in enumerate(self.hands):
+ if _targets[i] & target:
+ hand.SetBorderColour(colour)
+
+
+ def SetBorderWidth(self, width, target):
+ for i, hand in enumerate(self.hands):
+ if _targets[i] & target:
+ hand.SetBorderWidth(width)
+
+
+ def SetShadowColour(self, colour):
+ for i, hand in enumerate(self.hands):
+ hand.SetShadowColour(colour)
+
+#----------------------------------------------------------------------
+
+class TickSet:
+ """Manages a set of tick marks."""
+
+ def __init__(self, parent, **kwargs):
+ self.parent = parent
+ self.dyer = Dyer()
+ self.noe = {"minutes": 60, "hours": 12}[kwargs["kind"]]
+ self.font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+ style = kwargs.pop("style")
+ self.kwargs = kwargs
+ self.SetStyle(style)
+
+
+ def _draw(self, dc, shadow=False):
+ dc.SetFont(self.font)
+
+ a_tick = self.ticks[0]
+
+ if shadow:
+ offset = self.parent.shadowOffset * a_tick.GetScale()
+ else:
+ offset = 0
+
+ clockStyle = self.parent.clockStyle
+
+ for idx, tick in self.ticks.items():
+ draw = False
+
+ # Are we a set of hours?
+ if self.noe == 12:
+ # Should we show all hours ticks?
+ if clockStyle & SHOW_HOURS_TICKS:
+ draw = True
+ # Or is this tick a quarter and should we show only quarters?
+ elif clockStyle & SHOW_QUARTERS_TICKS and not (idx + 1) % 3.:
+ draw = True
+ # Are we a set of minutes and minutes should be shown?
+ elif self.noe == 60 and clockStyle & SHOW_MINUTES_TICKS:
+ # If this tick occupies the same position of an hour/quarter
+ # tick, should we still draw it anyway?
+ if clockStyle & OVERLAP_TICKS:
+ draw = True
+ # Right, sir. I promise I won't overlap any tick.
+ else:
+ # Ensure that this tick won't overlap an hour tick.
+ if clockStyle & SHOW_HOURS_TICKS:
+ if (idx + 1) % 5.:
+ draw = True
+ # Ensure that this tick won't overlap a quarter tick.
+ elif clockStyle & SHOW_QUARTERS_TICKS:
+ if (idx + 1) % 15.:
+ draw = True
+ # We're not drawing quarters nor hours, so we can draw all
+ # minutes ticks.
+ else:
+ draw = True
+
+ if draw:
+ tick.Draw(dc, offset)
+
+
+ def Draw(self, dc):
+ if self.parent.clockStyle & SHOW_SHADOWS:
+ self.dyer.Select(dc, True)
+ self._draw(dc, True)
+ self.dyer.Select(dc)
+ self._draw(dc)
+
+
+ def RecalcCoords(self, clocksize, centre, scale):
+ a_tick = self.ticks[0]
+
+ size = a_tick.GetMaxSize(scale)
+ maxsize = size
+
+ # Try to find a 'good' max size for text-based ticks.
+ if a_tick.text is not None:
+ self.font.SetPointSize(size)
+ dc = wx.MemoryDC()
+ dc.SelectObject(wx.EmptyBitmap(*clocksize.Get()))
+ dc.SetFont(self.font)
+ maxsize = size
+ for tick in self.ticks.values():
+ maxsize = max(*(dc.GetTextExtent(tick.text) + (maxsize,)))
+
+ radius = self.radius = min(clocksize.Get()) / 2. - \
+ self.dyer.width / 2. - \
+ maxsize / 2. - \
+ a_tick.GetOffset() * scale - \
+ self.parent.shadowOffset * scale
+
+ # If we are a set of hours, the number of elements of this tickset is
+ # 12 and ticks are separated by a distance of 30 degrees;
+ # if we are a set of minutes, the number of elements of this tickset is
+ # 60 and ticks are separated by a distance of 6 degrees.
+ angfac = [6, 30][self.noe == 12]
+
+ for i, tick in self.ticks.items():
+ tick.SetClockSize(clocksize)
+ tick.SetScale(scale)
+
+ deg = 180 - angfac * (i + 1)
+ angle = math.radians(deg)
+
+ x = centre.x + radius * math.sin(angle)
+ y = centre.y + radius * math.cos(angle)
+
+ tick.SetPosition(wx.Point(x, y))
+
+
+ def GetSize(self):
+ return self.kwargs["size"]
+
+
+ def GetFillColour(self):
+ return self.dyer.GetFillColour()
+
+
+ def GetBorderColour(self):
+ return self.dyer.GetBorderColour()
+
+
+ def GetBorderWidth(self):
+ return self.dyer.GetBorderWidth()
+
+
+ def GetPolygon(self):
+ a_tick = self.ticks.values()[0]
+ return a_tick.GetPolygon()
+
+
+ def GetFont(self):
+ return self.font
+
+
+ def GetOffset(self):
+ a_tick = self.ticks[0]
+ return a_tick.GetOffset()
+
+
+ def GetShadowColour(self):
+ return self.dyer.GetShadowColour()
+
+
+ def GetIsRotated(self):
+ a_tick = self.ticks[0]
+ return a_tick.GetIsRotated()
+
+
+ def GetStyle(self):
+ return self.style
+
+
+ def SetSize(self, size):
+ self.kwargs["size"] = size
+ [tick.SetSize(size) for tick in self.ticks.values()]
+
+
+ def SetFillColour(self, colour):
+ self.dyer.SetFillColour(colour)
+
+
+ def SetBorderColour(self, colour):
+ self.dyer.SetBorderColour(colour)
+
+
+ def SetBorderWidth(self, width):
+ self.dyer.SetBorderWidth(width)
+
+
+ def SetPolygon(self, polygon):
+ [tick.SetPolygon(polygon) for tick in self.ticks.values()]
+
+
+ def SetFont(self, font):
+ self.font = font
+
+
+ def SetOffset(self, offset):
+ self.kwargs["offset"] = offset
+ [tick.SetOffset(offset) for tick in self.ticks.values()]
+
+
+ def SetShadowColour(self, colour):
+ self.dyer.SetShadowColour(colour)
+
+
+ def SetIsRotated(self, rotate):
+ self.kwargs["rotate"] = rotate
+ [tick.SetIsRotated(rotate) for tick in self.ticks.values()]
+
+
+ def SetStyle(self, style):
+ self.style = style
+ tickclass = allTickStyles[style]
+ self.kwargs["rotate"] = self.parent.clockStyle & ROTATE_TICKS
+
+ self.ticks = {}
+ for i in range(self.noe):
+ self.kwargs["idx"] = i
+ self.ticks[i] = tickclass(**self.kwargs)
+
+#----------------------------------------------------------------------
+
+class Box:
+ """Gathers info about the clock face and tick sets."""
+
+ def __init__(self, parent, Face, TicksM, TicksH):
+ self.parent = parent
+ self.Face = Face
+ self.TicksH = TicksH
+ self.TicksM = TicksM
+
+
+ def GetNiceRadiusForHands(self, centre):
+ a_tick = self.TicksM.ticks[0]
+ scale = a_tick.GetScale()
+ bw = max(self.TicksH.dyer.width / 2. * scale,
+ self.TicksM.dyer.width / 2. * scale)
+
+ mgt = self.TicksM.ticks[59]
+ my = mgt.pos.y + mgt.GetMaxSize(scale) + bw
+
+ hgt = self.TicksH.ticks[11]
+ hy = hgt.pos.y + hgt.GetMaxSize(scale) + bw
+
+ niceradius = centre.y - max(my, hy)
+ return niceradius
+
+
+ def Draw(self, dc):
+ [getattr(self, attr).Draw(dc) \
+ for attr in ["Face", "TicksM", "TicksH"]]
+
+
+ def RecalcCoords(self, size, centre, scale):
+ [getattr(self, attr).RecalcCoords(size, centre, scale) \
+ for attr in ["Face", "TicksH", "TicksM"]]
+
+
+ def GetTickSize(self, target):
+ r = []
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ r.append(tick.GetSize())
+ return tuple(r)
+
+
+ def GetTickFillColour(self, target):
+ r = []
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ r.append(tick.GetFillColour())
+ return tuple(r)
+
+
+ def GetTickBorderColour(self, target):
+ r = []
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ r.append(tick.GetBorderColour())
+ return tuple(r)
+
+
+ def GetTickBorderWidth(self, target):
+ r = []
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ r.append(tick.GetBorderWidth())
+ return tuple(r)
+
+
+ def GetTickPolygon(self, target):
+ r = []
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ r.append(tick.GetPolygon())
+ return tuple(r)
+
+
+ def GetTickFont(self, target):
+ r = []
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ r.append(tick.GetFont())
+ return tuple(r)
+
+
+ def GetIsRotated(self):
+ a_tickset = self.TicksH
+ return a_tickset.GetIsRotated()
+
+
+ def GetTickOffset(self, target):
+ r = []
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ r.append(tick.GetOffset())
+ return tuple(r)
+
+
+ def GetShadowColour(self):
+ a_tickset = self.TicksH
+ return a_tickset.GetShadowColour()
+
+
+ def GetTickStyle(self, target):
+ r = []
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ r.append(tick.GetStyle())
+ return tuple(r)
+
+
+ def SetTickSize(self, size, target):
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ tick.SetSize(size)
+
+
+ def SetTickFillColour(self, colour, target):
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ tick.SetFillColour(colour)
+
+
+ def SetTickBorderColour(self, colour, target):
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ tick.SetBorderColour(colour)
+
+
+ def SetTickBorderWidth(self, width, target):
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ tick.SetBorderWidth(width)
+
+
+ def SetTickPolygon(self, polygon, target):
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ tick.SetPolygon(polygon)
+
+
+ def SetTickFont(self, font, target):
+ fs = font.GetNativeFontInfoDesc()
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ tick.SetFont(wx.FontFromNativeInfoString(fs))
+
+
+ def SetIsRotated(self, rotate):
+ [getattr(self, attr).SetIsRotated(rotate) \
+ for attr in ["TicksH", "TicksM"]]
+
+
+ def SetTickOffset(self, offset, target):
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ tick.SetOffset(offset)
+
+
+ def SetShadowColour(self, colour):
+ for attr in ["TicksH", "TicksM"]:
+ tick = getattr(self, attr)
+ tick.SetShadowColour(colour)
+
+
+ def SetTickStyle(self, style, target):
+ for i, attr in enumerate(["TicksH", "TicksM"]):
+ if _targets[i] & target:
+ tick = getattr(self, attr)
+ tick.SetStyle(style)
+
+#----------------------------------------------------------------------
+
+# Relationship between styles and ticks class names.
+allTickStyles = {TICKS_BINARY: TickBinary,
+ TICKS_CIRCLE: TickCircle,
+ TICKS_DECIMAL: TickDecimal,
+ TICKS_HEX: TickHex,
+ TICKS_NONE: TickNone,
+ TICKS_POLY: TickPoly,
+ TICKS_ROMAN: TickRoman,
+ TICKS_SQUARE: TickSquare}
+
+
+#
+##
+### eof
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/__init__.py
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/buttontreectrlpanel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/buttontreectrlpanel.py
new file mode 100644
index 0000000..b76aea6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/buttontreectrlpanel.py
@@ -0,0 +1,290 @@
+__author__ = "E. A. Tacao <e.a.tacao |at| estadao.com.br>"
+__date__ = "12 Fev 2006, 22:00 GMT-03:00"
+__version__ = "0.03"
+__doc__ = """
+ButtonTreeCtrlPanel is a widget where one can place check buttons, tri-state
+check buttons, radio buttons, both, and the ability to display them
+hierarchically.
+
+
+About:
+
+ButtonTreeCtrlPanel is distributed under the wxWidgets license.
+
+For all kind of problems, requests, enhancements, bug reports, etc,
+please drop me an e-mail.
+
+For updates please visit <http://j.domaindlx.com/elements28/wxpython/>.
+"""
+
+import cStringIO
+
+import wx
+from wx.lib.newevent import NewEvent
+
+#----------------------------------------------------------------------------
+
+(ButtonTreeCtrlPanelEvent, EVT_BUTTONTREECTRLPANEL) = NewEvent()
+EVT_CHANGED = EVT_BUTTONTREECTRLPANEL
+
+#----------------------------------------------------------------------------
+
+class ButtonTreeCtrlPanel(wx.Panel):
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.WANTS_CHARS):
+ wx.Panel.__init__(self, parent, id, pos, size, style)
+
+ self.tree = wx.TreeCtrl(self, style=wx.TR_NO_LINES|wx.TR_HIDE_ROOT)
+
+ il = self.il = wx.ImageList(16, 16)
+ self.tree.SetImageList(il)
+
+ for bl in ["checkbox_checked", "checkbox_unchecked", "checkbox_tri",
+ "radiobox_checked", "radiobox_unchecked"]:
+ bitmap = getattr(self.__class__, bl).GetBitmap()
+ setattr(self, bl, il.Add(bitmap))
+
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_TOOLBAR, (16, 16))
+ self.empty_bitmap = il.Add(bmp)
+
+ self.root = self.tree.AddRoot("Root Item for ButtonTreeCtrlPanel")
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.tree.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftClicks)
+ self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnLeftClicks)
+ self.tree.Bind(wx.EVT_RIGHT_DOWN, self.OnRightClick)
+
+ self.allitems = []
+
+ wx.CallAfter(self.OnSize)
+
+
+ def _doLogicTest(self, style, value, item):
+ if style in [wx.CHK_2STATE, wx.CHK_3STATE]:
+ n = [self.checkbox_unchecked, self.checkbox_checked, \
+ self.checkbox_tri][value]
+
+ self.tree.SetPyData(item, (value, style))
+ self.tree.SetItemImage(item, n, wx.TreeItemIcon_Normal)
+
+ elif style == wx.RB_SINGLE:
+ if value:
+ parent = self.tree.GetItemParent(item)
+ (child, cookie) = self.tree.GetFirstChild(parent)
+
+ if self.tree.GetPyData(child):
+ self.tree.SetPyData(child, (False, wx.RB_SINGLE))
+ self.tree.SetItemImage(child, self.radiobox_unchecked, \
+ wx.TreeItemIcon_Normal)
+
+ for x in range(1, self.tree.GetChildrenCount(parent, False)):
+ (child, cookie) = self.tree.GetNextChild(parent, cookie)
+
+ if self.tree.GetPyData(child):
+ self.tree.SetPyData(child, (False, wx.RB_SINGLE))
+ self.tree.SetItemImage(child, self.radiobox_unchecked, \
+ wx.TreeItemIcon_Normal)
+
+ self.tree.SetPyData(item, (True, wx.RB_SINGLE))
+ self.tree.SetItemImage(item, self.radiobox_checked, \
+ wx.TreeItemIcon_Normal)
+
+ else:
+ self.tree.SetPyData(item, (False, wx.RB_SINGLE))
+ self.tree.SetItemImage(item, self.radiobox_unchecked, \
+ wx.TreeItemIcon_Normal)
+
+
+ def _getItems(self, parent=None, value=None):
+ if not parent:
+ parent = self.root
+ cil = []
+ (child, cookie) = self.tree.GetFirstChild(parent)
+ if child.IsOk():
+ d = self.tree.GetPyData(child)
+ if value is None or (d and d[0] == value):
+ cil.append(child)
+ for x in range(1, self.tree.GetChildrenCount(parent, False)):
+ (child, cookie) = self.tree.GetNextChild(parent, cookie)
+ if child.IsOk():
+ d = self.tree.GetPyData(child)
+ if value is None or (d and d[0] == value):
+ cil.append(child)
+ return cil
+
+
+ def AddItem(self, label, bmp=None, parent=None, style=None, value=False):
+ v = None
+
+ if bmp:
+ n = self.il.Add(bmp)
+ if not parent:
+ parent = self.root
+ if style is not None:
+ v = (value, style)
+
+ this_item = self.tree.AppendItem(parent, label)
+ self.tree.SetPyData(this_item, v)
+
+ if v:
+ self._doLogicTest(style, value, this_item)
+ else:
+ if bmp is None:
+ bmp = self.empty_bitmap
+ else:
+ bmp = self.il.Add(bmp)
+
+ self.tree.SetItemImage(this_item, bmp, wx.TreeItemIcon_Normal)
+
+ self.allitems.append(this_item)
+ [self.tree.Expand(x) for x in self.allitems]
+
+ return this_item
+
+
+ def ExpandItem(self, item):
+ self.tree.Expand(item)
+
+
+ def CollapseItem(self, item):
+ self.tree.Collapse(item)
+
+
+ def EnsureFirstVisible(self):
+ (child, cookie) = self.tree.GetFirstChild(self.root)
+ if child.IsOk():
+ self.tree.SelectItem(child)
+ self.tree.EnsureVisible(child)
+
+
+ def SetItemValue(self, item, value):
+ data = self.tree.GetPyData(item)
+ if data:
+ self._doLogicTest(data[1], value, item)
+
+
+ def GetItemValue(self, item):
+ data = self.tree.GetPyData(item)
+ if data:
+ return data[0]
+ else:
+ return None
+
+
+ def GetItemByLabel(self, label, parent=None):
+ r = None
+ for item in self._getItems(parent):
+ if self.tree.GetItemText(item) == label:
+ r = item; break
+ return r
+
+
+ def GetAllItems(self):
+ return self.allitems
+
+
+ def GetRootItems(self):
+ cil = []
+ for x in range(0, len(self.allitems)):
+ d = self.tree.GetPyData(self.allitems[x])
+ if not d:
+ cil.append(self.allitems[x])
+ return cil
+
+
+ def GetStringRootItems(self):
+ return [self.tree.GetItemText(x) for x in self.GetRootItems]
+
+
+ def GetItemsUnchecked(self, parent=None):
+ return self._getItems(parent, 0)
+
+
+ def GetItemsChecked(self, parent=None):
+ return self._getItems(parent, 1)
+
+
+ def GetItemsTri(self, parent=None):
+ return self._getItems(parent, 2)
+
+
+ def GetStringItemsUnchecked(self, parent=None):
+ return [self.tree.GetItemText(x) \
+ for x in self.GetItemsUnchecked(parent)]
+
+
+ def GetStringItemsChecked(self, parent=None):
+ return [self.tree.GetItemText(x) for x in self.GetItemsChecked(parent)]
+
+
+ def GetStringItemsTri(self, parent=None):
+ return [self.tree.GetItemText(x) for x in self.GetItemsTri(parent)]
+
+
+ def OnRightClick(self, evt):
+ item, flags = self.tree.HitTest(evt.GetPosition())
+ self.tree.SelectItem(item)
+
+
+ def OnLeftClicks(self, evt):
+ item, flags = self.tree.HitTest(evt.GetPosition())
+ if item:
+ text, data = self.tree.GetItemText(item), self.tree.GetPyData(item)
+ if data:
+ style = data[1]
+ if style == wx.CHK_2STATE:
+ value = not data[0]
+ elif style == wx.CHK_3STATE:
+ value = data[0] + 1
+ if value == 3: value = 0
+ else:
+ value = True
+
+ self._doLogicTest(style, value, item)
+
+ if value <> data[0]:
+ nevt = ButtonTreeCtrlPanelEvent(obj=self, id=self.GetId(),
+ item=item, val=value)
+ wx.PostEvent(self, nevt)
+
+ evt.Skip()
+
+
+ def OnSize(self, evt=None):
+ self.tree.SetSize(self.GetClientSize())
+
+# # Images generated by encode_bitmaps.py -----------------------------
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+ButtonTreeCtrlPanel.checkbox_unchecked = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAEFJ"
+ "REFUOI3tkzsOACAUwsrT+9/Yz6yDieJkZKfpAFIknITVBjJAq6XtFhVJ9wxm6iqzrW3wAU8A"
+ "hiGdTNo2kHvnDr+YDCrzE+JlAAAAAElFTkSuQmCC")
+
+ButtonTreeCtrlPanel.radiobox_checked = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAHFJ"
+ "REFUOI2tUtESgCAIA+3//1jpqW7R5tkRb8o2GODeulWildhmdqhEzBH49tad4TxbyMQXIQk9"
+ "BJCcgSpHZ8DaVRZugasCAmOOYJXxT24BQau5lNcoBdCK8m8mtqAILE87YJ7VHP49pJXQ9il/"
+ "jfIaT195QDiwOHL5AAAAAElFTkSuQmCC")
+
+ButtonTreeCtrlPanel.radiobox_unchecked = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAGdJ"
+ "REFUOI3NkksSgDAIQ4F6/xtru9LBmHTq4EJ2Hchr+LhHs0pESW1mm0r0Y+/57dGc1Tm2gMKH"
+ "AEA3QBZjocrRGTC7qoULcP6gCnMuuylv4UcA1h8GmxN1wCAK/O0hzUDLp/w2ylsY3w4wQW9/"
+ "cegAAAAASUVORK5CYII=")
+
+ButtonTreeCtrlPanel.checkbox_checked = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAGdJ"
+ "REFUOI2tk1EOgDAIQ1vm/W+s82uJqbAxkW9eU6CQ1lApK9EADgDo19l3QVrjfw5UdVbqNu0g"
+ "GjMlMNvRS0CbVwt2HQzoCUf7CUfIwK6ANq8u4zoYUOas4QgZGJAgfYl0OcqsvvMNP8koKiUm"
+ "7JsAAAAASUVORK5CYII=")
+
+ButtonTreeCtrlPanel.checkbox_tri = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAHBJ"
+ "REFUOI2tk0EOgDAIBJfqq9Sj+mj1aP1We2piCCCKnJnN0GyJUofIpBANoAeAaRzKW/DMF/1n"
+ "wFOt4bZug2PfxDNdARosBvBlC1YNGnSH52UV30c9wQOLAXzZglWDBj3BaoAXBliRvlQ6XGWK"
+ "fucKTYUl4c5UOHYAAAAASUVORK5CYII=")
+
+#
+##
+### eof
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/colourselect.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/colourselect.py
new file mode 100644
index 0000000..f3a1ddf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/colourselect.py
@@ -0,0 +1,80 @@
+# AnalogClock's colour selector for setup dialog
+# E. A. Tacao <e.a.tacao |at| estadao.com.br>
+# http://j.domaindlx.com/elements28/wxpython/
+# 15 Fev 2006, 22:00 GMT-03:00
+# Distributed under the wxWidgets license.
+
+import wx
+from wx.lib.newevent import NewEvent
+from wx.lib.buttons import GenBitmapButton
+
+#----------------------------------------------------------------------------
+
+(ColourSelectEvent, EVT_COLOURSELECT) = NewEvent()
+
+#----------------------------------------------------------------------------
+
+class ColourSelect(GenBitmapButton):
+ def __init__(self, parent, size=(21, 21), value=wx.BLACK):
+ w, h = size[0] - 5, size[1] - 5
+ GenBitmapButton.__init__(self, parent, wx.ID_ANY, wx.EmptyBitmap(w, h),
+ size=size)
+ self.SetBezelWidth(1)
+
+ self.parent = parent
+ self.SetValue(value)
+
+ self.parent.Bind(wx.EVT_BUTTON, self.OnClick, self)
+
+
+ def _makeBitmap(self):
+ bdr = 8; w, h = self.GetSize()
+ bmp = wx.EmptyBitmap(w - bdr, h - bdr)
+
+ dc = wx.MemoryDC()
+ dc.SelectObject(bmp)
+ dc.SetBackground(wx.Brush(self.value, wx.SOLID))
+ dc.Clear()
+ dc.SelectObject(wx.NullBitmap)
+
+ self.SetBitmapLabel(bmp)
+ self.Refresh()
+
+
+ def GetValue(self):
+ return self.value
+
+
+ def SetValue(self, value):
+ self.value = value
+ self._makeBitmap()
+
+
+ def OnClick(self, event):
+ win = wx.GetTopLevelParent(self)
+
+ data = wx.ColourData()
+ data.SetChooseFull(True)
+ data.SetColour(self.value)
+ [data.SetCustomColour(colour_index, win.customcolours[colour_index])
+ for colour_index in range(0, 16)]
+
+ dlg = wx.ColourDialog(win, data)
+ dlg.SetTitle("Select Colour")
+ changed = dlg.ShowModal() == wx.ID_OK
+
+ if changed:
+ data = dlg.GetColourData()
+ self.SetValue(data.GetColour())
+ win.customcolours = [data.GetCustomColour(colour_index) \
+ for colour_index in range(0, 16)]
+ dlg.Destroy()
+
+ if changed:
+ nevt = ColourSelectEvent(id=self.GetId(), obj=self, val=self.value)
+ wx.PostEvent(self.parent, nevt)
+
+
+#
+##
+### eof
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/fontselect.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/fontselect.py
new file mode 100644
index 0000000..9f93e02
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/lib_setup/fontselect.py
@@ -0,0 +1,61 @@
+# AnalogClock's font selector for setup dialog
+# E. A. Tacao <e.a.tacao |at| estadao.com.br>
+# http://j.domaindlx.com/elements28/wxpython/
+# 15 Fev 2006, 22:00 GMT-03:00
+# Distributed under the wxWidgets license.
+
+import wx
+from wx.lib.newevent import NewEvent
+from wx.lib.buttons import GenButton
+
+#----------------------------------------------------------------------------
+
+(FontSelectEvent, EVT_FONTSELECT) = NewEvent()
+
+#----------------------------------------------------------------------------
+
+class FontSelect(GenButton):
+ def __init__(self, parent, size=(75, 21), value=None):
+ GenButton.__init__(self, parent, wx.ID_ANY, label="Select...",
+ size=size)
+ self.SetBezelWidth(1)
+
+ self.parent = parent
+ self.SetValue(value)
+
+ self.parent.Bind(wx.EVT_BUTTON, self.OnClick, self)
+
+
+ def GetValue(self):
+ return self.value
+
+
+ def SetValue(self, value):
+ if value is None:
+ value = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self.value = value
+
+
+ def OnClick(self, event):
+ data = wx.FontData()
+ data.EnableEffects(False)
+ font = self.value; font.SetPointSize(10)
+ data.SetInitialFont(font)
+
+ dlg = wx.FontDialog(self, data)
+ changed = dlg.ShowModal() == wx.ID_OK
+
+ if changed:
+ data = dlg.GetFontData()
+ self.value = data.GetChosenFont()
+ self.Refresh()
+ dlg.Destroy()
+
+ if changed:
+ nevt = FontSelectEvent(id=self.GetId(), obj=self, val=self.value)
+ wx.PostEvent(self.parent, nevt)
+
+
+#
+##
+### eof
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/setup.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/setup.py
new file mode 100644
index 0000000..c09d2fc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/setup.py
@@ -0,0 +1,473 @@
+# AnalogClock setup dialog
+# E. A. Tacao <e.a.tacao |at| estadao.com.br>
+# http://j.domaindlx.com/elements28/wxpython/
+# 15 Fev 2006, 22:00 GMT-03:00
+# Distributed under the wxWidgets license.
+
+import wx
+
+import styles
+import lib_setup.colourselect as csel
+import lib_setup.fontselect as fsel
+import lib_setup.buttontreectrlpanel as bt
+
+#----------------------------------------------------------------------
+
+_window_styles = ['wx.SIMPLE_BORDER', 'wx.DOUBLE_BORDER', 'wx.SUNKEN_BORDER',
+ 'wx.RAISED_BORDER', 'wx.STATIC_BORDER', 'wx.NO_BORDER']
+
+#----------------------------------------------------------------------
+
+class _GroupBase(wx.Panel):
+ def __init__(self, parent, title, group):
+ wx.Panel.__init__(self, parent)
+
+ self.parent = parent
+ self.clock = self.parent.clock
+ self.group = group
+ self.target = {"Hours": styles.HOUR,
+ "Minutes": styles.MINUTE,
+ "Seconds": styles.SECOND}.get(title)
+
+ self.Bind(fsel.EVT_FONTSELECT, self.OnSelectFont)
+ self.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour)
+ self.Bind(wx.EVT_SPINCTRL, self.OnSpin)
+ self.Bind(wx.EVT_TEXT_ENTER, self.OnSpin)
+ self.Bind(wx.EVT_CHOICE, self.OnChoice)
+
+
+ def OnSelectFont(self, evt):
+ self.clock.SetTickFont(evt.val, self.target)
+
+
+ def OnSelectColour(self, evt):
+ obj = evt.obj; val = evt.val
+
+ if hasattr(self, "fc") and obj == self.fc:
+ if self.group == "Hands":
+ self.clock.SetHandFillColour(val, self.target)
+ elif self.group == "Ticks":
+ self.clock.SetTickFillColour(val, self.target)
+ elif self.group == "Face":
+ self.clock.SetFaceFillColour(val)
+
+ elif hasattr(self, "bc") and obj == self.bc:
+ if self.group == "Hands":
+ self.clock.SetHandBorderColour(val, self.target)
+ elif self.group == "Ticks":
+ self.clock.SetTickBorderColour(val, self.target)
+ elif self.group == "Face":
+ self.clock.SetFaceBorderColour(val)
+
+ elif hasattr(self, "sw") and obj == self.sw:
+ self.clock.SetShadowColour(val)
+
+ elif hasattr(self, "bg") and obj == self.bg:
+ self.clock.SetBackgroundColour(val)
+
+ elif hasattr(self, "fg") and obj == self.fg:
+ self.clock.SetForegroundColour(val)
+ self.parent.GetGrandParent().UpdateControls()
+
+
+ def OnSpin(self, evt):
+ obj = evt.GetEventObject(); val = evt.GetInt()
+
+ if hasattr(self, "bw") and obj == self.bw:
+ if self.group == "Hands":
+ self.clock.SetHandBorderWidth(val, self.target)
+ elif self.group == "Ticks":
+ self.clock.SetTickBorderWidth(val, self.target)
+ elif self.group == "Face":
+ self.clock.SetFaceBorderWidth(val)
+
+ elif hasattr(self, "sz") and obj == self.sz:
+ if self.group == "Hands":
+ self.clock.SetHandSize(val, self.target)
+ elif self.group == "Ticks":
+ self.clock.SetTickSize(val, self.target)
+
+ elif hasattr(self, "of") and obj == self.of:
+ self.clock.SetTickOffset(val, self.target)
+
+
+ def OnChoice(self, evt):
+ self.clock.SetWindowStyle(eval(evt.GetString()))
+
+
+ def UpdateControls(self):
+ if hasattr(self, "ft"):
+ self.ft.SetValue(self.clock.GetTickFont(self.target)[0])
+
+ if hasattr(self, "fc"):
+ if self.group == "Hands":
+ self.fc.SetValue(self.clock.GetHandFillColour(self.target)[0])
+ elif self.group == "Ticks":
+ self.fc.SetValue(self.clock.GetTickFillColour(self.target)[0])
+ elif self.group == "Face":
+ self.fc.SetValue(self.clock.GetFaceFillColour())
+
+ if hasattr(self, "bc"):
+ if self.group == "Hands":
+ self.bc.SetValue(self.clock.GetHandBorderColour(self.target)[0])
+ elif self.group == "Ticks":
+ self.bc.SetValue(self.clock.GetTickBorderColour(self.target)[0])
+ elif self.group == "Face":
+ self.bc.SetValue(self.clock.GetFaceBorderColour())
+
+ if hasattr(self, "sw"):
+ self.sw.SetValue(self.clock.GetShadowColour())
+
+ if hasattr(self, "bg"):
+ self.bg.SetValue(self.clock.GetBackgroundColour())
+
+ if hasattr(self, "fg"):
+ self.fg.SetValue(self.clock.GetForegroundColour())
+
+ if hasattr(self, "bw"):
+ if self.group == "Hands":
+ self.bw.SetValue(self.clock.GetHandBorderWidth(self.target)[0])
+ elif self.group == "Ticks":
+ self.bw.SetValue(self.clock.GetTickBorderWidth(self.target)[0])
+ elif self.group == "Face":
+ self.bw.SetValue(self.clock.GetFaceBorderWidth())
+
+ if hasattr(self, "sz"):
+ if self.group == "Hands":
+ self.sz.SetValue(self.clock.GetHandSize(self.target)[0])
+ elif self.group == "Ticks":
+ self.sz.SetValue(self.clock.GetTickSize(self.target)[0])
+
+ if hasattr(self, "of"):
+ self.of.SetValue(self.clock.GetTickOffset(self.target)[0])
+
+ if hasattr(self, "ws"):
+ for style in _window_styles:
+ if self.clock.GetWindowStyleFlag() & eval(style):
+ self.ws.SetStringSelection(style)
+ break
+
+#----------------------------------------------------------------------
+
+class _Group_1(_GroupBase):
+ def __init__(self, parent, title, group="Hands"):
+ _GroupBase.__init__(self, parent, title, group)
+
+ box = wx.StaticBoxSizer(wx.StaticBox(self, label=title), wx.VERTICAL)
+
+ sizer = self.sizer = wx.GridBagSizer(2, 6)
+
+ p = wx.StaticText(self, label="Border:")
+ sizer.Add(p, pos=(0, 0), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.bc = csel.ColourSelect(self)
+ sizer.Add(p, pos=(0, 1), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.bw = wx.SpinCtrl(self, size=(75, 21),
+ min=0, max=100, value="75")
+ sizer.Add(p, pos=(0, 2), span=(1, 2), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = wx.StaticText(self, label="Fill:")
+ sizer.Add(p, pos=(1, 0), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.fc = csel.ColourSelect(self)
+ sizer.Add(p, pos=(1, 1), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.ls = wx.StaticText(self, label="Size:")
+ sizer.Add(p, pos=(2, 0), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.sz = wx.SpinCtrl(self, size=(75, 21),
+ min=0, max=100, value="75")
+ sizer.Add(p, pos=(2, 1), span=(1, 3), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ box.Add(sizer)
+
+ self.SetSizer(box)
+
+#----------------------------------------------------------------------
+
+class _Group_2(_Group_1):
+ def __init__(self, parent, title, group="Ticks"):
+ _Group_1.__init__(self, parent, title, group)
+
+ sizer = self.sizer
+
+ p = wx.StaticText(self, label="Offset:")
+ sizer.Add(p, pos=(3, 0), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.of = wx.SpinCtrl(self, size=(75, 21),
+ min=0, max=100, value="75")
+ sizer.Add(p, pos=(3, 1), span=(1, 3), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = wx.StaticText(self, label="Font:")
+ sizer.Add(p, pos=(4, 0), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.ft = fsel.FontSelect(self)
+ sizer.Add(p, pos=(4, 1), span=(1, 3), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ self.GetSizer().Layout()
+
+#----------------------------------------------------------------------
+
+class _Group_3(_Group_1):
+ def __init__(self, parent, title, group="Face"):
+ _Group_1.__init__(self, parent, title, group)
+
+ sizer = self.sizer
+
+ for widget in [self.ls, self.sz]:
+ sizer.Detach(widget)
+ widget.Destroy()
+ sizer.Layout()
+
+ p = wx.StaticText(self, label="Shadow:")
+ sizer.Add(p, pos=(2, 0), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.sw = csel.ColourSelect(self)
+ sizer.Add(p, pos=(2, 1), span=(1, 3), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ self.GetSizer().Layout()
+
+#----------------------------------------------------------------------
+
+class _Group_4(_GroupBase):
+ def __init__(self, parent, title, group="Window"):
+ _GroupBase.__init__(self, parent, title, group)
+
+ box = wx.StaticBoxSizer(wx.StaticBox(self, label=title), wx.VERTICAL)
+
+ sizer = self.sizer = wx.GridBagSizer(2, 6)
+
+ p = wx.StaticText(self, label="Foreground:")
+ sizer.Add(p, pos=(0, 0), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.fg = csel.ColourSelect(self)
+ sizer.Add(p, pos=(0, 1), span=(1, 3), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = wx.StaticText(self, label="Background:")
+ sizer.Add(p, pos=(1, 0), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.bg = csel.ColourSelect(self)
+ sizer.Add(p, pos=(1, 1), span=(1, 3), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = wx.StaticText(self, label="Style:")
+ sizer.Add(p, pos=(2, 0), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ p = self.ws = wx.Choice(self, choices=_window_styles)
+ sizer.Add(p, pos=(2, 1), span=(1, 3), flag=wx.ALIGN_CENTRE_VERTICAL)
+
+ box.Add(sizer)
+
+ self.SetSizer(box)
+
+#----------------------------------------------------------------------
+
+class _PageBase(wx.Panel):
+ def __init__(self, parent):
+ wx.Panel.__init__(self, parent)
+
+ self.clock = self.GetGrandParent().GetParent()
+ self.sizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self.sizer)
+
+
+ def UpdateControls(self):
+ [group.UpdateControls() for group in self.GetChildren()]
+
+#----------------------------------------------------------------------
+
+class StylesPanel(bt.ButtonTreeCtrlPanel):
+ def __init__(self, parent):
+ bt.ButtonTreeCtrlPanel.__init__(self, parent)
+
+ self.clock = self.GetGrandParent().GetParent()
+
+ root = self.AddItem("Styles")
+ g1 = self.AddItem("General", parent=root)
+ g2 = self.AddItem("Hours", parent=root)
+ g3 = self.AddItem("Minutes", parent=root)
+ self.groups = [g1, g2, g3]
+
+ clockStyle = self.clock.GetClockStyle()
+ hourStyle, minuteStyle = self.clock.GetTickStyle()
+
+ for label in dir(styles):
+ if label.startswith("TICKS_"):
+ value = bool(getattr(styles, label) & hourStyle)
+ self.AddItem(label, parent=g2, style=wx.RB_SINGLE, value=value)
+
+ value = bool(getattr(styles, label) & minuteStyle)
+ self.AddItem(label, parent=g3, style=wx.RB_SINGLE, value=value)
+
+ elif not (label.startswith("DEFAULT_") or \
+ label.startswith("_") or \
+ label in ["HOUR", "MINUTE", "SECOND", "ALL"]):
+ value = bool(getattr(styles, label) & clockStyle)
+ self.AddItem(label, parent=g1, style=wx.CHK_2STATE, value=value)
+
+ self.EnsureFirstVisible()
+
+ self.Bind(bt.EVT_CHANGED, self.OnChanged)
+
+
+ def OnChanged(self, evt):
+ clockStyle, hourStyle, minuteStyle = \
+ [reduce(lambda x, y: x | y,
+ [getattr(styles, item) \
+ for item in self.GetStringItemsChecked(group)], 0) \
+ for group in self.groups]
+
+ self.clock.SetClockStyle(clockStyle)
+ self.clock.SetTickStyle(hourStyle, styles.HOUR)
+ self.clock.SetTickStyle(minuteStyle, styles.MINUTE)
+
+
+ def UpdateControls(self):
+ clockStyle = self.clock.GetClockStyle()
+ hourStyle, minuteStyle = self.clock.GetTickStyle()
+
+ [g1, g2, g3] = self.groups
+
+ for label in dir(styles):
+ if label.startswith("TICKS_"):
+ item = self.GetItemByLabel(label, g2)
+ value = bool(getattr(styles, label) & hourStyle)
+ self.SetItemValue(item, value)
+
+ item = self.GetItemByLabel(label, g3)
+ value = bool(getattr(styles, label) & minuteStyle)
+ self.SetItemValue(item, value)
+
+ elif not (label.startswith("DEFAULT_") or \
+ label.startswith("_") or \
+ label in ["HOUR", "MINUTE", "SECOND", "ALL"]):
+ item = self.GetItemByLabel(label, g1)
+ value = bool(getattr(styles, label) & clockStyle)
+ self.SetItemValue(item, value)
+
+#----------------------------------------------------------------------
+
+class HandsPanel(_PageBase):
+ def __init__(self, parent):
+ _PageBase.__init__(self, parent)
+
+ [self.sizer.Add(_Group_1(self, title), 1,
+ flag=wx.EXPAND|wx.ALL, border=6) \
+ for title in ["Hours", "Minutes", "Seconds"]]
+
+#----------------------------------------------------------------------
+
+class TicksPanel(_PageBase):
+ def __init__(self, parent):
+ _PageBase.__init__(self, parent)
+
+ [self.sizer.Add(_Group_2(self, title), 1,
+ flag=wx.EXPAND|wx.ALL, border=6) \
+ for title in ["Hours", "Minutes"]]
+
+#----------------------------------------------------------------------
+
+class MiscPanel(_PageBase):
+ def __init__(self, parent):
+ _PageBase.__init__(self, parent)
+
+ self.sizer.Add(_Group_3(self, "Face"), 1,
+ flag=wx.EXPAND|wx.ALL, border=6)
+ self.sizer.Add(_Group_4(self, "Window"), 1,
+ flag=wx.EXPAND|wx.ALL, border=6)
+
+#----------------------------------------------------------------------
+
+class Setup(wx.Dialog):
+ """AnalogClock customization dialog."""
+
+ def __init__(self, parent):
+ wx.Dialog.__init__(self, parent, title="AnalogClock Setup")
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ nb = self.nb = wx.Notebook(self)
+ for s in ["Styles", "Hands", "Ticks", "Misc"]:
+ page = eval(s + "Panel(nb)"); page.Fit()
+ nb.AddPage(page, s)
+ nb.Fit()
+ sizer.Add(nb, 1, flag = wx.EXPAND|wx.ALL, border=6)
+
+ bsizer = wx.BoxSizer(wx.HORIZONTAL)
+ bsizer.Add(wx.Button(self, label="Reset"),
+ flag = wx.LEFT|wx.RIGHT, border=6)
+ bsizer.Add(wx.Button(self, wx.ID_OK),
+ flag = wx.LEFT|wx.RIGHT, border=6)
+ sizer.Add(bsizer, 0, flag=wx.ALIGN_RIGHT|wx.ALL, border=6)
+
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+
+ self.customcolours = [None] * 16
+
+ self.SetSizerAndFit(sizer)
+ wx.CallAfter(self.UpdateControls)
+
+
+ def OnClose(self, evt):
+ self.Hide()
+
+
+ def OnButton(self, evt):
+ if evt.GetEventObject().GetLabel() == "Reset":
+ self.ResetClock()
+ evt.Skip()
+
+
+ def UpdateControls(self):
+ wx.BeginBusyCursor()
+ for i in range(self.nb.GetPageCount()):
+ self.nb.GetPage(i).UpdateControls()
+ wx.EndBusyCursor()
+
+
+ def ResetClock(self):
+ clock = self.GetParent()
+
+ wx.BeginBusyCursor()
+
+ clock.SetClockStyle(styles.DEFAULT_CLOCK_STYLE)
+ clock.SetTickStyle(styles.TICKS_POLY, styles.HOUR)
+ clock.SetTickStyle(styles.TICKS_CIRCLE, styles.MINUTE)
+
+ clock.SetTickFont(wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT))
+
+ clock.SetHandBorderWidth(0)
+ clock.SetTickBorderWidth(0)
+ clock.SetFaceBorderWidth(0)
+
+ clock.SetHandSize(7, styles.HOUR)
+ clock.SetHandSize(5, styles.MINUTE)
+ clock.SetHandSize(1, styles.SECOND)
+
+ clock.SetTickSize(25, styles.HOUR)
+ clock.SetTickSize(5, styles.MINUTE)
+
+ clock.SetTickOffset(0)
+
+ clock.SetWindowStyle(wx.NO_BORDER)
+
+ sw = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DSHADOW)
+ clock.SetShadowColour(sw)
+
+ no_color = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
+ clock.SetFaceFillColour(no_color)
+ clock.SetFaceBorderColour(no_color)
+ clock.SetBackgroundColour(no_color)
+
+ fg = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ clock.SetForegroundColour(fg)
+
+ self.UpdateControls()
+
+ wx.EndBusyCursor()
+
+
+#
+#
+### eof
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/styles.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/styles.py
new file mode 100644
index 0000000..a479920
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/analogclock/styles.py
@@ -0,0 +1,47 @@
+# AnalogClock constants
+# E. A. Tacao <e.a.tacao |at| estadao.com.br>
+# http://j.domaindlx.com/elements28/wxpython/
+# 15 Fev 2006, 22:00 GMT-03:00
+# Distributed under the wxWidgets license.
+
+# Style options that control the general clock appearance,
+# chosen via SetClockStyle.
+SHOW_QUARTERS_TICKS = 1
+SHOW_HOURS_TICKS = 2
+SHOW_MINUTES_TICKS = 4
+ROTATE_TICKS = 8
+SHOW_HOURS_HAND = 16
+SHOW_MINUTES_HAND = 32
+SHOW_SECONDS_HAND = 64
+SHOW_SHADOWS = 128
+OVERLAP_TICKS = 256
+
+DEFAULT_CLOCK_STYLE = SHOW_HOURS_TICKS|SHOW_MINUTES_TICKS| \
+ SHOW_HOURS_HAND|SHOW_MINUTES_HAND|SHOW_SECONDS_HAND| \
+ SHOW_SHADOWS|ROTATE_TICKS
+
+
+# Style options that control the appearance of tick marks,
+# chosen via SetTickStyle.
+TICKS_NONE = 1
+TICKS_SQUARE = 2
+TICKS_CIRCLE = 4
+TICKS_POLY = 8
+TICKS_DECIMAL = 16
+TICKS_ROMAN = 32
+TICKS_BINARY = 64
+TICKS_HEX = 128
+
+
+# Constants that may be used as 'target' keyword value in
+# the various Get/Set methods.
+HOUR = 1
+MINUTE = 2
+SECOND = 4
+
+ALL = HOUR|MINUTE|SECOND
+
+
+#
+##
+### eof
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/anchors.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/anchors.py
new file mode 100644
index 0000000..d90eebf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/anchors.py
@@ -0,0 +1,104 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.anchors
+# Purpose: A class that provides an easy to use interface over layout
+# constraints for anchored layout.
+#
+# Author: Riaan Booysen
+#
+# Created: 15-Dec-2000
+# RCS-ID: $Id$
+# Copyright: (c) 2000 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 11/30/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for wx namespace
+# o Tested with updated demo
+#
+"""
+`LayoutAnchors` is a class that implements Delphi's Anchors using
+`wx.LayoutConstraints`.
+"""
+
+import wx
+
+class LayoutAnchors(wx.LayoutConstraints):
+ """
+ A class that implements Delphi's Anchors with wx.LayoutConstraints.
+
+ Anchored sides maintain the distance from the edge of the control
+ to the same edge of the parent. When neither side is selected,
+ the control keeps the same relative position to both sides.
+
+ The current position and size of the control and it's parent is
+ used when setting up the constraints. To change the size or
+ position of an already anchored control, set the constraints to
+ None, reposition or resize and reapply the anchors.
+
+ Examples::
+
+ Let's anchor the right and bottom edge of a control and
+ resize it's parent.
+
+ ctrl.SetConstraints(LayoutAnchors(ctrl, left=0, top=0, right=1, bottom=1))
+
+ +=========+ +===================+
+ | +-----+ | | |
+ | | * | -> | |
+ | +--*--+ | | +-----+ |
+ +---------+ | | * |
+ | +--*--+ |
+ +-------------------+
+ * = anchored edge
+
+ When anchored on both sides the control will stretch horizontally.
+
+ ctrl.SetConstraints(LayoutAnchors(ctrl, 1, 0, 1, 1))
+
+ +=========+ +===================+
+ | +-----+ | | |
+ | * * | -> | |
+ | +--*--+ | | +---------------+ |
+ +---------+ | * ctrl * |
+ | +-------*-------+ |
+ +-------------------+
+ * = anchored edge
+
+ """
+ def __init__(self, control, left=1, top=1, right=0, bottom=0):
+ wx.LayoutConstraints.__init__(self)
+ parent = control.GetParent()
+ if not parent: return
+
+ pPos, pSize = parent.GetPosition(), parent.GetClientSize()
+ cPos, cSize = control.GetPosition(), control.GetSize()
+
+ self.setConstraintSides(self.left, wx.Left, left,
+ self.right, wx.Right, right,
+ self.width, wx.Width, self.centreX,
+ cPos.x, cSize.width, pSize.width, parent)
+
+ self.setConstraintSides(self.top, wx.Top, top,
+ self.bottom, wx.Bottom, bottom,
+ self.height, wx.Height, self.centreY,
+ cPos.y, cSize.height, pSize.height, parent)
+
+ def setConstraintSides(self, side1, side1Edge, side1Anchor,
+ side2, side2Edge, side2Anchor,
+ size, sizeEdge, centre,
+ cPos, cSize, pSize, parent):
+ if side2Anchor:
+ side2.SameAs(parent, side2Edge, pSize - (cPos + cSize))
+
+ if side1Anchor:
+ side1.SameAs(parent, side1Edge, cPos)
+
+ if not side2Anchor:
+ size.AsIs()
+ else:
+ size.AsIs()
+
+ if not side2Anchor:
+ centre.PercentOf(parent, sizeEdge,
+ int(((cPos + cSize / 2.0) / pSize)*100))
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/__init__.py
new file mode 100644
index 0000000..d310fdd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/__init__.py
@@ -0,0 +1 @@
+# package \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/flagart.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/flagart.py
new file mode 100644
index 0000000..e8204b9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/flagart.py
@@ -0,0 +1,1583 @@
+#Boa:PyImgResource:
+
+#----------------------------------------------------------------------
+# This file was generated by famfamfam_flags.py
+#
+
+"""
+See: http://www.famfamfam.com/lab/icons/flags
+
+FamFamFam Flag icons are available free for any purpose
+Copyright Mark James (mjames@gmail.com)
+
+This module is (c) 2006 Riaan Booysen and licensed under the Python license.
+
+"""
+
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+catalog = {}
+index = []
+
+index.append('AE')
+catalog['AE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA3UlE"
+ "QVQokYWOsU0DUBBD3ye/pKOKBF2YIiUd89BFTMEUabNJNiASTIBozr47igQBRcjTybrClj2a"
+ "HwoWz2AwFAQY4s8zATYboKtG1dNjujLLbrvsktIuqazU7mU3Aeh+eyeTzNcPZaZaSqmkVGRE"
+ "hVJ313enhq4+ulvaPmz7DGOMw/1hFoxM7LaRz7m7G6iqCeBs6XJgDNsT6HTbrfg/MLqBWTCk"
+ "jsDuiH/2dHdVzYKF3RJSS+v1OiIknVRShC07V6vVfr+fBVcyy2VLOG+tI7aPaju/AcYn1K+7"
+ "4QJfesZpBoG4DtcAAAAASUVORK5CYII=")
+
+index.append('AF')
+catalog['AF'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABbUlE"
+ "QVQokVWQvU5VYRRE5+ABAX8KCQIlFeEFKKkt7WngNSzvG1hb8gR0xqixMrHSwoiJMcZOIMHk"
+ "JtyzZ2Z/37YgJroy7SpmDfv7+/P5HAAASb+urvrycrcBJADg2SaeHwMBCADG6+vr2WwGoPXW"
+ "W4c9ZLtjlb1id+npbnnvRk1sPH1xOo7jCODi8jLtzCy7pKJKLLKTv+/Wt+05HdvrOxDG3ntr"
+ "LW1nWiq7gH5yXC3rzbv68N6uyZNMJRFYkpSZskVKKrKOjvT2tc7O+uFhD5qkOWWwCQuMsVhk"
+ "piXJZJTU11bz4ABTDKsrFZHRp5zCZBKB8SbCtiSSJLvUfnxf2trp9+7n+ddhsbARGUoxCWFE"
+ "le2IuHV6RL18FY83y7ny+RxkqmhGhrshjLf5JUUEyYqoL+drHz91skc00kS0SS3d/gokH21s"
+ "3J4GBXGQBnKwl6SHW9h9sOF09sQCA/7nJ9CB/GdPgIs9IIAE1vEH+0VpUzSLjT4AAAAASUVO"
+ "RK5CYII=")
+
+index.append('AL')
+catalog['AL'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABgElE"
+ "QVQokU3RP49NYRSF8XXe83IdF5mMiZhoFBKJRKX0MZCoVNOIZgqKaZSiEaLRjIbaF9AqNDq+"
+ "gj8Tk+u6M/fOefdae2/FkGif5il+3ecBNYACAFUQUYEROG4GCBAQQAAjUCuw+eI5gHSPiOq+"
+ "+2t5eyjF/fX+4f1p71InCzLIL6/eVAAAtPe9D387W90ZyvXl+Hi2lNndobP9ePZzsT0tMjt5"
+ "cdOAGoF0T/eUbvS582Mxtpa009LLg0ZrD4Y+jGEWooBSDOmeZIqfDo8uhYxcNvt6NLaxbbg+"
+ "LJbRLM3CWICCRLpCTOoKHOTDaddaa63tnC1rYVeTYc1bSxJADSAlUO681vnlSb6brSpN1t7P"
+ "Y2vSTZRhTBpIA4oBoJKm1gbZ073ftyY5H9t8bPdOdY++zQdZ0mAWrtXxIZxBCzOYPTnX9+LN"
+ "Pg9KnBF310+4WZLpCglABZBUv3GhkEGCFtT22vkkwxlSkUCPYLoC6D4CAOI/UQH2z/WvEmAA"
+ "gBH4A2X6QkAkcTlLAAAAAElFTkSuQmCC")
+
+index.append('AM')
+catalog['AM'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABE0lE"
+ "QVQokVVPvU6bQRCc+3yV3VKgiJY3oMzTIapILtMktDwaEgqS9WEJEm7nJ8XZkKxWoxntzGq3"
+ "1fU11hWzbI9hEmNAMjAbZ2Kg43BY7u4AxEaykTY2yEiZKIEMCem433csC5D8eoYUGT6NQ6bq"
+ "FKtCVbu8JNCxrnEwN0mYjukmwwqZIlipMtAvtj9uefPEN8tkSJOq8r+kylX6UrufeO9j0LZo"
+ "0qLrP58os1ylKYE/fYzPKz5uqQrpqkhz/fwfANrv7+hfv+X1MWHMqD7RZVUsuGIuu6un+4fu"
+ "BTATxhV9ZCouT2nCjOkYHd1HZAibC4AAWyPaydEWtQhSLIN4p1e0lz3wBg+YZyR4JpiSgGEC"
+ "W/wFGOaHzQZ1JyAAAAAASUVORK5CYII=")
+
+index.append('AR')
+catalog['AR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABOUlE"
+ "QVQokU2RvU5VURCF1z5sDyihwBsMjYWVEUsTShqUxEfwAWxIKK2peR5ibLTz5w1oTLAmuZFo"
+ "LnKy78y3LM6B3NXMl8maZGZNeffDi9AoREOEQmpBwBA0aCMEfaf6N/T+2ei2XbCQwOmSrKW6"
+ "xOC00z75vqhDaImul8bCSjsRduDAYScTz9aLGvX06fzFk9kSWZKNZRls27LxiNgPinZezuvz"
+ "LWa9JNmWZdm3X3JxjqPbfOuNI9+pFO3P1I3nTr2xDp/hl/PS/z55VRJQV90aJ/oDDXOpeeNw"
+ "1V9soF78YW/LLW3rbt03fvQaG8zN5Ab11d/mWY9/Pv6wpqtbB7oPJO9TYkop0e5DnX3drh0U"
+ "dTvrU6BpJUpKWoGwQOmS2JJEefXx5nebHjkEQyhBgRoCjRxIKKRe/wH2AXDnJMhVrAAAAABJ"
+ "RU5ErkJggg==")
+
+index.append('AT')
+catalog['AT'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA6UlE"
+ "QVQokX2RrW5CQRSEv21vatA3NwgcpjUoHgyN54EwvAGeF0C1glBca/b8TMXeFGhIJydfRkw2"
+ "Z+cUcVXe+4dTBKzXgDLJJEIehMsdd5nphl/bbQeA9P5BBBEyaxynmqyqVpmV2SyhY7nU6xv9"
+ "gFLuRChC7nK/Gvda68sw5G5XTqdT3/eAJITQH9VaGyeTyeVyaSuNqV/zWCCpu4Yevn+blzKz"
+ "2GJRViudz9xsLA/F3TeIKMPwudl0eTg87/c6HhlrGTsZ2YwbHsznQJfwZM50KjM8cMOsmOFO"
+ "o3trnIiE8n1/yH9u3PQDfNZaTYpscjsAAAAASUVORK5CYII=")
+
+index.append('AU')
+catalog['AU'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAACC0lE"
+ "QVQokU3HT0hTcRwA8O/b3mhLndO5tmnPtuUi56YdYguzwrKB2SIiKOiUFR2joGSHLkXBQBE6"
+ "ZlHQJbBGBDGFKK1cRA0TTALdFhk129JtbHu/9/vbVfhcPtLHkdszxo7o1PpYMS5zfoWHr7f+"
+ "PLy3ffB+AapFAApABy8MJB6+BFgHwNJQZOxRtI/YFTSfEkiVdngsNsvrNPqy+JtRrmJyLhKQ"
+ "ZSmzupGYXXkyOi6lTCbnnbv6wl9SLnNNM9TXaVyqqThmPFCkEkZYcTaG97tjE3MupWny3rju"
+ "nf+4rqvH6OtkVhsorq3BIFHc6e3diIoT/R0A8D2bj03MRS/3Oax1ADVd8fQwWK0vuOtPvT1n"
+ "sMSbg3p/oGRuOXLQq9gbrg7vUxE5e8xnkKWjvW4ApPdLrfkGx0wWkRrKVnVTS6Xlit7C1efJ"
+ "X15Py2Ti21q+UthQmxqNT18trnx9r/+c6QwMdFeLlQwxZfAWmeJcvjKfI0yIZGp17V9FCHFm"
+ "qOtxfMFkNGQW3ugAKFBOKD91yHPzYggTRhkHzgimnHPBhKbR0QfJUrnGGQOgOgCMKRNChPa0"
+ "tTvNJ8O7NUwwoZhQTJiKSZvDPHKpVyOMMQFAZQDMOW9uNE1/SPfsss1++qE4zJrGmOCUChXh"
+ "a+dDvp3bNMyeTS8BIAkgAkABEADehG6ut//G8ttbABwA/gMK+Buk8wRxpgAAAABJRU5ErkJg"
+ "gg==")
+
+index.append('AZ')
+catalog['AZ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABbklE"
+ "QVQokU2QvWpUYRiE5zs5uyFrwEYkP0SzaqugtW1uIhewd2AVvIM0ptvgJWjjDSguqNgJWbtV"
+ "RBFt1MRE93zvzLwp1oDDw/DAdFPw6DXmxCIGaJggQIL+19UgUYm2aXHKvZ0hACecqUwasplJ"
+ "m0bItMMZymfjVy0GAyy1X85ChjLDljKkSIQznFWudshbl/ror5ZJKTcODuq372lBMpmkSZMZ"
+ "YdIRjkiyv7b2cjxu0TQgoUgJQc3/Xt3d7W1sHj9/0bu+dTyZ/JlOM2hGRm2AxpITlpMSuTy8"
+ "2dseft7fH9y7u3xte+X2HVEiRdlJoAFQFg9UllB39L6bfVwfjX4+eTqfzc7evC0dS2XpiEoD"
+ "bQUkSpGiGW7y6+PDrGHx1/TIEV5M5pJ5CrQ7DzG6rw+/FWJYVayqUaNCYVYzTIq0bl32u09o"
+ "cYIIrvevhEiTYpjRI82wKDEpSSl1wg8UPABOAAL1Av4nvBADBFZxDq7cZQ8Pjp14AAAAAElF"
+ "TkSuQmCC")
+
+index.append('BE')
+catalog['BE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA7klE"
+ "QVQokW2RQUqDYQxE36dVRFTEjXThxgt4IW/SW/U61V0FV4riKjNJXPT/WxWHIau8zEAGv/Xx"
+ "zkUAVFHX1Cd1S3HwAlitVkBVVdXZeXKV4NE+xkeX6ke31HZLX+v1AoDebl8yMzOrBNmtyane"
+ "REe0NO7upoSqzkxnWurO7uh2t7qjOzq0A5AmIDO9k3y4/R/ADrBT0g8gDkCpY6qEvU+w7VD8"
+ "BuY5J4x9JUkRYVsRfxNa+/Ntb+dK1qyp9377RB3RFk4yPSd4uVxKsnMMgcYQGITMvcncuWD8"
+ "+fTmmVjgoszNGfXG6wOA4RSe4BuvWmXvCEAfcgAAAABJRU5ErkJggg==")
+
+index.append('BG')
+catalog['BG'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABB0lE"
+ "QVQokW1OMU5DUQzz+7wuldhYKhV1YeEenKkjCzfgMsyVmDgCqhg6dWEBFYnYcRh+Cx+EEzm2"
+ "nEhph8MBE9geeSq+IbsDmM/nAKpqvKka3WlMsN/v+2mppqL+Q2vNdt++bZfDMit/EpTLo/Sp"
+ "XJ4N/fnjueEO65v17n0nSxZNmkxGkhmRQTMUNFfnq839pgNQJYsqqUQzHDRZjIoo0hEVNFWC"
+ "0TEgB2lQVKiJjUREYyAIBoIDo4JFDkRHxyNW15y9hlJSKMkMiUpSIZEZMiUtL/S0Qf98wNml"
+ "/EKQRVYcHznyKEQo21XeAt3AQGGxKBJKiCAbCQkjS8gc20A7AJ40fts/EYAvPNBlhsfxqY8A"
+ "AAAASUVORK5CYII=")
+
+index.append('BH')
+catalog['BH'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABIklE"
+ "QVQokV2RPW7CQBCFn5FbFzSxlIgbQJPchpvQkZQhSKRBSorkDjTcgaSDC9BQ2AqJTBDOzuy8"
+ "FOsfwdNoNSt92jezLyqKArWS5dKGQ3gfrgYYoHUTKiqKIkmSQNA88hxv78xyeKUqVO10oghV"
+ "KfK7WMQVSgLAeoPXF37t4RxFQtnxSOcoEvV6BnRaGsBgwPsHpGkg6ITOtSViQGxmzQ5crzF5"
+ "4s939bwTSktDBMEhmJBkv8/nGW+ua8idOagaEDc0AH5+4HHC/Z7iqnlEGodIxICOmbEWbu84"
+ "mzG94p+7oKFKVW12qPZerTidcrdr6XCqQH3IJ8qyrNvtViN5j+2W4zEPB9R/b2VJ7+E9vM83"
+ "m5hkWZbBx+ZzG41wHm2TdNA/d+tUbaz3axgAAAAASUVORK5CYII=")
+
+index.append('BI')
+catalog['BI'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAB/0lE"
+ "QVQokTXJTUiTcRwH8O/zbMl8HvfC1tzKaI4sGy1q7JCCdIhePEanLqVEVqNL0SnommKHFkR0"
+ "6VSSQW8g2EkQKTIhiqSpGLY2UsKtPXtrm//n9///OkS3D3w0zmQgjJW+HrUlnaGQIlJEEEK1"
+ "WsSsAAW0AADx6XnlrGoHJqNfz34H0FhYqM/MOIJBSEm1GojgcrGUdj5vnho0Txxn5vbRdoc+"
+ "UNHchr8jHO6Om8n+8qvnVCwGzg274gerb6ZFLhceu7sttjfTWr318ebi9KLT7/F52nwPvqQT"
+ "ncnh6FB4fJyZi6W8sCmUTjMzM99bSU9lp/pC/fBBJ6UAhDp2LBUzqfkrZW4ysypYWvE3M9dZ"
+ "nJk9/Xb9XbcvyhqjBb2hWpKlYmm4TEHiW2WZayLQEw/2JrjaXKutVpo1r+m1JZEiKOi/XKRY"
+ "ElP5j9VUzT3uQz9ePCpll6yN7Nrj+1EzJp2iUC6QsqWS6IAulbQl5axcl7vrycCEh3n3+cu+"
+ "yH5vOBJN3TCYZ47N9vr3rRSXbRJQcKKEjfr6SDx1xJtkxT8vjUDT/NevMWuF0dvCKkWevR49"
+ "PDYXeZ/+fAeb0PAQ9kWbmRvzH6ynE47AdkhpVyrKtnXDYKKtfM4/dMEcPAnAc9WjzWXndpU7"
+ "PyViVaANIEABBAhA/fe/Ojr5cmnn5l99aCZ0THLLKQAAAABJRU5ErkJggg==")
+
+index.append('BLANK')
+catalog['BLANK'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAABHNCSVQICAgIfAhkiAAAABlJ"
+ "REFUKJFjZGRiZqAEMFGke9SAUQOoZQAAMjgAHL4jfPwAAAAASUVORK5CYII=")
+
+index.append('BN')
+catalog['BN'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABw0lE"
+ "QVQokS3MMWhTYRTF8fN976U+kxgNdojBoZAIDopUyZIOoougm4ug4CIdRASJFNRdaCdx6OAo"
+ "KMFZcLKbi2jBKKJRaRMpCVbb5L00eS/fvbnXIT3Tbzl/M2wCDrCYTgSQfQgDApF9s0AERlUB"
+ "TAYvwH9FepCJqsAwDAszwBBWJVFW5d2vr/xp2GZvALCATLYlfDre23ZRdDDvhAiGREnFmdRx"
+ "YXjpIKguLExvqmpMxgQXNnbO0juXLbVgVGQkTCLO2kPD7g/v7dpaHMf1en22WHTM+VxuEsfu"
+ "+RMNd+n0s5nCNT9702YuarIOg367aQDUavfb7RYzM/FK9aTn+dHl6+Wj+ejlqrhxofZYVVXV"
+ "WBv2+2bwDebIg18/Nx8uR0xM5K+eL9158z7taOXSmd7V26lM5tTcnKpaa3u9ngm/ICguCbVM"
+ "KhkPqPtbw3+Y/VRCsrf0+vv66I9zjojOzc/fWlysVCombODAsXtCLUgCjxQuCYViVuXOJq7c"
+ "7ZBzzMQ8KZfLjUbDF4YqG68gmiizgoPDZGcmEDpRpebH3DiSrQ5vdfnR8hCA2fkAYYiA3T6E"
+ "YX04howAgU2DA0AgjI3P+A9mXiz0vUkDDQAAAABJRU5ErkJggg==")
+
+index.append('BO')
+catalog['BO'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABHElE"
+ "QVQokW1RPaoUYRCs2f008pmpCwaC4DG8h7G5eAkRQzHzDiYewnsYi4Esbx/jV38GMysGNkVT"
+ "1d10QffSR0dcIzImEGBFiuA/GADw4ROApkuMpA7sJT7aB7Fyrco1b99/HABQ9OcP2EgqYW+7"
+ "YqWKJSsuj08Bxt0r338x82RF1Lh2w0awatasFbPm4eHd+RnG7WvcPF3NSyvUjVo2TP8SNmzm"
+ "4d7Nr3cYCBq3aoW4ZcLuQwpmw4aJDlGCEaFgK4StcnXYd28mYaPCEsYX4aV50e+EKRN6I6Wz"
+ "y0auHhzXzyvGmzPe8vJ9nhkqYjgzWe5kK5aKn+Py7YwBQdFpnFQxcjQxFW3YTuvYtWEIC74C"
+ "AfQPNjmvv92K2PMfrSN8t7ZlHI0AAAAASUVORK5CYII=")
+
+index.append('BR')
+catalog['BR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABrUlE"
+ "QVQokU2RO2iTYRSG3/75Qq0oIYMS24JDFcFbBkcVlAoi4uAloMRJUSGTQ10KCkWx4KK03kAc"
+ "xMvQCirWwUXNpi62OAgOUhW8ECxNm1/id95zjkOU5OFweOHlcIanC8fRxgD+3xGIHaE1TQQA"
+ "I+URB9zNzNRVTbet/x3AqXcJjWpKihhFZeLsRADg8G8L37XVGe8cTN173GWw8Gvv3UykUCVq"
+ "7M/1//vg7mqkcc+mtNSrw8Nj01YQ+kDzx9OLhx58levVDFWEgogEBho1SW/tT0sDnP5QOlIp"
+ "3Bz6UynVZ7pXnrkwdHhNrB6rR4qYoIkERG+ueXufJC4Oufx88PQNv/oky7jk/AnPbyy6R/f4"
+ "5tR8sa+BFAkiZueSk8/oiO5xS/6t0Gc++ehkmK95cfnr1sGue/HVe0EOCQiScwvJgfth6nOs"
+ "HB1du5jWfrosevVRY/f2c49n44ax7JdaNrs0izoCIugUFVEZf5m51JO+uLLDpc9FvPvj5vEg"
+ "FqhCJY0AAiKELCxbRRUxIVeUJ6W8tZEJdu3hutV5qilVaWJqALqws22x02jbtKKTv/JDL0E5"
+ "0S0eAAAAAElFTkSuQmCC")
+
+index.append('BT')
+catalog['BT'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABnklE"
+ "QVQokW3Kv2/McRzH8ef3e5+79tL2gtzFj5RGJcLAH+APYLIYDQYJ6R8gFpMwMHWiDFi7IGmE"
+ "ySAGgxCLgaQGOYk0vetdr+e+/Xzen/fLIGLxyHN8FpO3BMP5y3EHIzTwEq/wiIM38IA/IAQj"
+ "HL8BCEeOZ5HB1FhUtBA/q7BMKqLpVdp5uhY8AFL8gTKepQRZzRO+b6mqFKtx2bs26sbO6pfa"
+ "scNepwSE/t2eFaK2Pw4Go5hy3WPRXt5a+1nsiZpKnihx8IyblJCpjL9G5cbkkA9fD8fx/fOV"
+ "75tbncu3tBOVExBwUJaSZBSmKnVnVomTWl2hplPnr0I59+iSmolkDsENyeSmIlKz3t7rPqn2"
+ "Nwa5Sv1Jcy5t2MubGkTNpCInh9IdeVItTmYvrIe7/c12M2+nXrd17+LCh2fjufn+2TsaJcyU"
+ "zaD0CDXT9Mn+8PT0t+3Fh1eK6ebwzWOxq08r7dtnjtw/p3aUJXkGQjmLStO73sH1Zaayjs63"
+ "vr6oN2JxYIEy0TLcUCZnPDsUoyewhO/iHTyC4WOc//THb4UhI+oZPvWXAAAAAElFTkSuQmCC")
+
+index.append('BW')
+catalog['BW'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABDklE"
+ "QVQokX1RsUqjYRCcjT+KYAicoJ2BA/EN8wRi6YvcA9jYpFMfIU0gWB0XuIBC2J1vxuIzIXeI"
+ "U8wu7O6wzMT1s/8SHZRSoJCCJUigQGHfA8OfxN1PGBBsRxME0JaCPmoeNZtyyc2+f3obRoCM"
+ "3+VmSKDdDMq0O5dcMuXLkwAVm81mPB73l2x3/hIRsVwuA8BsNlutViRZLFZHZlVl7kpVTafT"
+ "+Xw+ACBbVe0P+vif9cy+AGAA0BpJZuVOPzPrUHsvASDW6/VkMvn++z6NiMViMZy/nN3e4HXr"
+ "Eg496Uy5ul3C1Sl+Pf4YQMmji+NuJZpBoRS9aUIzmqPJAkAFHt6xPQiV+Iw2/8tYIHCMD2d1"
+ "fWGuzZK5AAAAAElFTkSuQmCC")
+
+index.append('BY')
+catalog['BY'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABTElE"
+ "QVQokU2OsWpUYRCFv717sd1qCVuk8R3yEhbiC4RgqjRhGyux09ikixY+RTBBEFJY2vgQESxE"
+ "FpG9d6/unTPzj8W9yWY4HA7MfMMhuy6PjvL2NiEeSNDDP+ighTX8gd8wSaDvOTtLiVKISA/C"
+ "0x33lPKBb66va9Zrbm5yuWS5JCKlwUeZUpZmKU329wvUzGa52XB6urs2S/fxVJamAUAqUJXV"
+ "iqsrzs9TQj7s0mxUb7ssATXzOV2Xx8cj4OO/EbuHJdwLVKxWeXmZF+/uCtx53+/cLM2GSnV5"
+ "8iy/fO5Onh+euIpZSGEKWZGKKWRhHlLxxzP/+paqfPpY3rzefnjfTq2dqp1aM6pvKltX1kyt"
+ "qa2t1VXBI+qyN2fTVK9eLJ4uvISHVKQiL66QF/f0iIiMyGDLpPv56+9i7/uPbwcvDzAwcHYB"
+ "MNhCYZj/bzd1lgzDLI4AAAAASUVORK5CYII=")
+
+index.append('BZ')
+catalog['BZ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABpElE"
+ "QVQokVWRv2uTYRSFz/v1a5Jq2kRNJEJCsaU6KIIUXPxBJ0FxdHBycvZfcHARBPE/cBPH7oJQ"
+ "7SgFKzrZgrbW2LRJkybpl/eee69DKNSHMx14pieM8B8ECGQAgNzxaccDEDC78eLZWQAGN8Uo"
+ "X8gPhqcLUYyd3mR/Yiq0u1QInbQ3L7+mqNSyU7mdtqs6DQmxdKd1vp5lqlvN+H75SrdbErrQ"
+ "69UEuJQAcAPVxZAEffR49e7l6cWkccNqDxqVJ09XcpOjSI1UoQIxAUFzKpQ+d6FZz5eL3bD+"
+ "/dPal4/+a1QLxavXNqOEKCZ0wBLQ1FzVqahfbJb9TK5YybbpW83a7FwZ1dr8H1GLdNGxEE0V"
+ "oh7VmtvlQz84yo56+epPLOz19kcYtH9PS3QRJw2wFBGiLnRR//ytvnhvlVl6+/p8VNvo/Dic"
+ "aa18uBmpkUZLAEuRgQpRRGLA5PWrW/cfrs3kOyQOEN49X9rZh9BoiWoAkGJ3NwzPNaachNDj"
+ "RLr+dqFU6qvi716u7F6a6au5qbPvwGZonQg5zjwE+gCBAlA4UXrMPyh0GTDv/QqiAAAAAElF"
+ "TkSuQmCC")
+
+index.append('CA')
+catalog['CA'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABoUlE"
+ "QVQokU2RvW4TQRhF78zOetc/YMsOFqJBQAEPQEidmpI3SJkOCckSVV6AhoKfElHnBRBvYJTK"
+ "EkUKIhNSRCTKkoWdmW/muxSWEKe6xSmudEzz9JleXVln/fnpcLnEf5AEEGM8m816QAQS4HR9"
+ "2l88B1BcXw4GA5IkY9MYRTG5SdXSlbf291010py/vX7lMKoB6s+LfHm+sZOyffNWfR6+fFEY"
+ "QzIeH2t/Yu/cjoBDUmalJKREMqy+Bo3FyRrR/15+cTlXT7bRddnUDDEBTmNEzhRhCCTbd+/d"
+ "aGCGY5Z1/vDx+vvJ/PBQuwDTmRgS4OC9SlIRjUISD+7y6IjlyLTeNmfFw0eqmkJnXV+jRMAm"
+ "75mEIho8ydHe3p/ZVmwakbadzseLBUnxniHmuLnUthTREDQEVUVdjw8Ous+fTFVPd3ZMXeec"
+ "GUIuI0QS4NLFD4owRPVeVUmaXontx7ZXo6pyzqqqvtNesClFwCVAg5jpxObOGLOJVU23DKmA"
+ "tdYYU967X0zmKkkBcwwokIBfwI3Vynv/L/BmiMh6d7cHKADgLxaxMt388uCoAAAAAElFTkSu"
+ "QmCC")
+
+index.append('CB')
+catalog['CB'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABTklE"
+ "QVQokVWRL2/TcRyEr82P/UlaycKydCAIOIIhJAjI9AKC9AXMTPEOhsHxKta9BBI0eh5PBXSi"
+ "yC0hdJ+77x2ivwYwl0dc7sQzwPExzs6wtYXVCgBsSAAg9Wz3IGE4HAB4P5vh6Mi7uyZbIqDZ"
+ "SmQLoC2bCZPPl5cdAMy/Xc3nbTptd+9xxZbQYJ8upxzak+078KgDYKctfuj8/N3L5YunLa5E"
+ "MeNKagMc+PB69aUD0FqTpOXy4pMG4PMnTNj3XMkaiBDAEIDUSJL8ec2PM36/qgyrb5tpG26y"
+ "sH6QpGKNhjqdcrJfqX7134eBaWEIgGRVaTQ+fVuvnlVUaZv2JmEl0godAEnc2+PJyYfJg/pV"
+ "ZdP5m7FsOQ+z/bW77ADw8P7+m9ccj3V7q63Qpq2EGxstaXbLb9Syw8HBxeNHWCxwc9PrXHut"
+ "+s/x2v3Ozh9eL3jobZO0pwAAAABJRU5ErkJggg==")
+
+index.append('CD')
+catalog['CD'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABoUlE"
+ "QVQokU2RPWjTARDFLzEoNhZt0cYU/gqCH4TiR4nB4sfkZGdnHVx1FAQXlw6CheLgIKKDk5tV"
+ "R4eiaA1RSiF2KBmSGm3VBkHU5u6993dIKo7H3eO9d79McnGydf3FvtuTK4sVk8xlgDnMZe62"
+ "AUvdzM1g5maescO3Hs2MN9YLSFMxpVJIpKAUEKggAQUV5OzNu7nkaPXS8e6dudJCe5RSSAQD"
+ "aUgBBuigQwEmu/Nmnl1ZLD/8MLHQHoUUFEFHGmQx/9X71/SABwIy82yhVL184lVppAUSpENp"
+ "6hPJ0tT5J8mO1W7Qoy8Lysyza7Xx+7VT79vFoAIK6Nz++o2zT4e3d6YvPC4MfOsLQgDNPJsf"
+ "e31lfG5spPkvwLOPRz79GEjVfb50qLG+09E3CcgMuV/z5XvvKtVWHlT0d3pQK883kwND7V7p"
+ "AAFRMvMtdtJnr27Uv2xtdgY3f8L66p7O79zy9yEPBggK1K78trXqy5y9qcy8Pf35z97iMEEB"
+ "DCjYIyCQYEqK6jkoY8cO/pxaHrxWsMaZHstNrvhvlBnMZGZ/AR0PdcdtApHFAAAAAElFTkSu"
+ "QmCC")
+
+index.append('CF')
+catalog['CF'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABj0lE"
+ "QVQokU3KP0hVARiG8ffcc+x2K7qeweIqDWnSFEFrNdTqUK3V5ODQP5e7OkSTLS3h5OzgkhBc"
+ "XbMlCLpNIRQoaESbcU+D3/e939tgQb/tgafoXN0pu/Wbpd6d5z/Qgmeywa/PPQLjl/YxlgjC"
+ "EiQsYVGV3fGdtY2pqaX9a2vrHx4zoSOcevdUES9vTHgpUkx5iMrlZ9+qJLaG8/c6L16/fZSF"
+ "0pGUdnfl/v1yBuWhYHrofF2gQXFw8HNycoIEgKIQAECam5O5tjb1T6aKohgOP1WAAyhLSIIg"
+ "SJLMZK7/AAIwGo2qhfcLi9cXD48OKTLJVjLjoZncV7+uRjKNFCOjbtf9Qb8abA5mL87uNXuW"
+ "FgxPd9oDc5mtfFwxmtMtzenT3elmo6kQcLnRIsNplm40mcv9703zygPBMnACVX8e92fit3vK"
+ "M52wlMlcZq9uOdOTlvIUz4xx+QmquydxpQ6pJzlAySXHBUfE7Z5LIYVEgADP3USxvY1WC50O"
+ "2m2cPgsQmeAMEsgv4HESmTj2B5KxXKDSA72eAAAAAElFTkSuQmCC")
+
+index.append('CH')
+catalog['CH'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAABHNCSVQICAgIfAhkiAAAALBJ"
+ "REFUKJGFUsEVgzAI/VEPvk5gOoZrZIyM4SwePXp0Jydo/kXtIU1NClYuEODDh2BMVQMA9n07"
+ "8EeY2Y+qNsluiqxhUJAESLQfm+NYhBsBWFcgBGCaTp9zUVtbMAGAShQIQZsAJNWYZJB3TsB5"
+ "jg/vRbpk8Au+kbJABtDAJMUOviMQQEsCzkXwspxZfR+1tfcMLmlf+MUS266LhvdnsdRZ+QWT"
+ "LvG1b4fWQ/M9s0t8Ay6VSOU8nBloAAAAAElFTkSuQmCC")
+
+index.append('CL')
+catalog['CL'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABC0lE"
+ "QVQokXWMPUpDURCFv3vfExOLIGqT0qxBRFyKhTaCZRZg5U5SuQcbWyE2toJIEOxifiSa5M7c"
+ "GYsEyTPmcDgwnO9M4OqBb0UhwszYiblzCti/gpKJXp8dXhzvdx4HWXKjXkAADyEURRFj9BVN"
+ "JpOIcXlygHN+tPf2MX8fzWFZr33HzCJw+zTI7nfPI1HXjG+WmZXUdse6dXM/VEe3a5rTJhoA"
+ "Sl5f4me9GM8sezRLjbpPpw6rb5eDGK3fDxlot73Xc0mIuohL8iSekkslY6s17HZLgyDiKaFa"
+ "gao0qq6qUBoUqi7CL7Q+U0EzObMYRFGaTRdBMyqIBBFUWaQqOS9sEL7AVkz1/FMBP4aNaAa6"
+ "+++rAAAAAElFTkSuQmCC")
+
+index.append('CN')
+catalog['CN'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABJElE"
+ "QVQokV2RMUpDYRCEJ8mLYhGwElOkEAQvoEfwGOYQllp4HQuRmMLGUkG8gJ7AQkUQExOzM7tr"
+ "8b8XHsIWw7Iz+7HbeQECCKALANg+xvsd0DQFAFBLVwHsXpwPTjC7jP5ebB759qvPJoIppSRD"
+ "SrLo5+m0CmAwzt7O62Dsn2ceC24cev+A8xsmmcakhVmS1WikAjK/ypj5z637LzsDT5m/MY1h"
+ "llyFWV2kgApAfPnHqZDaOlK1z+UDl/eMVnaaBZnFEECsvLAun4QtziaWZJIlFU18SLUhXSmB"
+ "5gt9XzNphSfW2cVARm0oLSlbAP+nJaw3QCqIQYZZPdFwp1mIKU93AJWAoHrDYZJdeYp1fHP+"
+ "kOAe7ukuoPPYemRbqPXsaKoC/gA6rnMwXmwqoAAAAABJRU5ErkJggg==")
+
+index.append('CO')
+catalog['CO'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABEUlE"
+ "QVQokWWOsa6OYRCEn48vR6MhIhQSci5A7Z60Kjegdiki0WuERknjiEKhUvrtzDuj+M+fHGwm"
+ "kye7O5vdfr4h4bJCQnIC/yfYE24/fg6U0NBVFnFr4qLGjVq3unj9ageg1Xe6yGpFV6NWJ59m"
+ "Gm03HsTsQOnf29O6UTPtnEBEHnYMLHA3g4u6qVVRt2mnqEwrEGHj1rtnLx5++zFelSNXvoRR"
+ "5MyRvR7du/H25fudAzZ2xz15RsdYR50rhyA7B36LX4OFzJgxUuWOLzsy9jYDsH/qk7ufn+ri"
+ "azUZVcoMUjSRjm9VyvLZ+flHPuxncN2Ha/fv1O5MfRyvSkfGzkqXuw43YfsCBmAgEPAV/0fA"
+ "H7CAa8EDIY7HAAAAAElFTkSuQmCC")
+
+index.append('CR')
+catalog['CR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABJElE"
+ "QVQokWVRMUpDURCcl/wiKKg38BCeQCy8gxfwAEJuEFKr2FhYBCzEU3gLWy2sFDSKkt2dGYuf"
+ "RMVhGBjYXYadhu0JAktIiIIF1C/GSgNQh43RxeWhARuyRZckqWjSpJJiqcQqn44v2sIeArAB"
+ "GIBtwH/R+9ba63zeYTbD3p6/Pi3DslakLNkCadJS29iM25v2AOyMx3x8dJWyXOlMZCrSGYpw"
+ "Zq/D3d37u7tOAIrOVJX7hQhnrucU4QhlDqoEdALEUpUynOVMZzjy9+2lZgpob9PJaP9AH+99"
+ "0F61ym0SpGSLg62tp/Oz9rVYdMOhpeWLbNv6/yWgtfb88tKAk8nVEUukiiqKVJYoslwSKclF"
+ "2b6ejhtwvGpxXefa/hQMFCBg8A0y93t3R/GzpwAAAABJRU5ErkJggg==")
+
+index.append('CZ')
+catalog['CZ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABO0lE"
+ "QVQokXWRvWpUcRDFz978CWgUVkgQ/CjcUhtBbFcrC0GwSG9vkRfxRQIR8Va+QNrsRhDFF5C1"
+ "EBVSeGfOOWNxs0uQeIqZU/zODMNM8Orkzcvd1892AQCwPdaLZiPa7YbPtq/f/brSw3vXxkwV"
+ "gKpNu6DVatV1XbdTPDo9O/7yeyQ22D/jx4XNhlxXNfSfLHt+f1r/0XmAtKtctaPh3UdRfvrg"
+ "8gwAki1o21RJdUXD4Ylufjia7W2XZLIkSCWVNJlOcXDQSMqQiqqUX5y+vbN4P0RWhDIrojId"
+ "UZltNvs1DE20XClTNV/280V/DmUiApkVgUyQIAE0BDnSi/7Jsq+Icd4mVhFmgiqJQEOYquff"
+ "jh//WOLWbTO7TGSarMwJWeTW+gwADX/4ef/RPn5+BwwYAMC15/j+temAvzMZeRNn/GS2AAAA"
+ "AElFTkSuQmCC")
+
+index.append('DE')
+catalog['DE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABNUlE"
+ "QVQokXWQMaoUARBEa2ZnwUgUEwN/aqjgNzJUzD5o6D1+4C28iLCXMNHUowgy3V3dVQazaOQL"
+ "iqbgVdDL3d07zA4Jp61axbYICP9hI/f7+88AJEma6Zkj+wrZ090kebl83dZ1BfD9x88mj7qq"
+ "Kisr/xIRGfHh41sA2w3wSLohu7urmmQmM6uKEZWRmdwjK582AWyfmLczt6SrfGSmMxWpDGcq"
+ "wnuq4szegM0sz6DKRWe4SlchnKlM7fvhm2VgM4Dpf8NVjlDEVdt3V06kqzwcYOMb4Ll9kkei"
+ "xDkOt0W5MbQbov16iW/Y/AJ+Jj8eaaSxRtOWpD7erLElCX6y6D02FNzE+dWKWjRWLWqY1li0"
+ "2h677Ub1+hvL5cvLBwMVfELuEOCHWAMa1AlT0OC8QgGc8KvwBzggh2H1+79aAAAAAElFTkSu"
+ "QmCC")
+
+index.append('DK')
+catalog['DK'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABKElE"
+ "QVQokWVSO04DUQyc93YLBIpEhZRiG27AQeAgtNDlVilziFwhAkFBBFKWBKR4bA/FW5AAy4Vl"
+ "j39jlxFITJLAeURut7v5PIE/6gCAPoGTxQIAMpFZSqmz2dn9XX58yl0k3EXKPcmX5bIHACif"
+ "nhGhCEmKiM1DHvYiZRRNZknWYcjWAakJTQKQlLRsUJqMaSaykDYlRMhd7qBLUq3a72EETWYi"
+ "YQZSZAIlIkopkiS18spUM35LqXXc7Xr8xCAILe8/WlKRMrPfdt3s9jY2G7nL7HS10jgerm9y"
+ "/97maQvIvb+8fFqvewCNPpEgp2Z2xPE4Oc3khAciJpZEr/O5SHkAQNfVYcDhUBr97jUCERkB"
+ "oDwD/n1IBy7e3vzx8fXq6sfZ/qCduQJfBq5Z9b21BQQAAAAASUVORK5CYII=")
+
+index.append('DO')
+catalog['DO'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABN0lE"
+ "QVQokXVRMWqUYRSc798fixWEEIwsmCKN4gG8jYVN6lR2OYOFJxCCF0iX3gukiN1KakFZu+TN"
+ "vBmLfyOxcIrh8Zh5A/PG6s0FHtAyyrB/fnv/TLvvB4cGDOgRzwA+nb8NkMAdO7LXTzDm9fPT"
+ "05CRQloKub28nAEk+PHrrhd1uzudzG5utymG5aqQq+NjA3MbCbrTTrfVkewkcarCcjFVJidS"
+ "wAxZflBrb5hHMq1S5SqTqQppUsDo7jFGkiQA8n+Mafq9240tcHh2ptvbsEKZDOvg6qqn+d2H"
+ "r5Kplkz55YunXz5+ngxkHypXpSr3lfu76ixqypSl7jag2cC+OHJxuiqJk+L+trrVaf81UNNm"
+ "M8ioLQ5yTKtpjM3RuttLdbbVATxu/n3kwq9urnfro9cn54/Wy4A/xLJ3307zCyYAAAAASUVO"
+ "RK5CYII=")
+
+index.append('DZ')
+catalog['DZ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABmUlE"
+ "QVQokU2PPWtUURCG33PO3bu7lxWjZA2bsIUEFMk/0DqI6EJs9AfY2FhYGkFsBP0B1tqITSxD"
+ "GrHRRrAQO0VBtsr6lTWud8+Zr2NxF3WKYYrnnZnHnbw1msYZAAAkEok0zkJZfbqzU4YWgJyz"
+ "mZmZiJhZ8a2e3t+6kQHLpqaiKiJWhP5g0IZHzpb/1Xg8LgpfZOTJ4Q9RFRUyYab1nySr720w"
+ "sFbLbBGpqirnXMDMchZVVmGV4a/68sevXUo17/XOj9DvI4S/F8zMRyFRIRUWpiybn79XlO6e"
+ "OREujGa7z5z3jV4TEBEfiUSVhZJyIlr+PX8ntN8p5vdupzevJ9eueO9DCM65Rt1niqyShBNT"
+ "Up4Yn9qflgfT9s3tcv306qOdhg4hLF5CrEmFmBNTSvHpSmfewoNXH/jJ46NbVzORmQFwzgFQ"
+ "VY9Ys3ASSkyR0tsurm8sPVzrVZuX8nBonc7/xgAKxEMSXu4tkTIxJ2Fqp/FKaefO5uwc0Kxv"
+ "aDNzuHgMXw4QgRqLPgNKvHj+8nj3SAOpajMA+AMw503J6/1+rgAAAABJRU5ErkJggg==")
+
+index.append('EC')
+catalog['EC'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABKklE"
+ "QVQokW2OPUqdYRCFz6evIFcJiCERK7lNmuwgq8kCbMTaStKkdUMuINiqlSI2MYkXo6LvnB+L"
+ "zysKDofhcOZhZobHky/wDcay7Q7T6HY3YwOGDRM2ADT43+KnfQCAkCxEiBONQpgQYeyEs+Of"
+ "DWhAwKs54YQJYyaEGVRcMYelz+5oMAC/S8eVEKmYScGk0drkZlh8RB5eHpjrmRvXJzW0++UJ"
+ "2sfdvR/fv/2+vqUiizJlSkVRLkkU6ZI31lcPti/a9enm5ezDxZ9Wcsmki+50yUUVMw/1XxNg"
+ "2vBgahy7+GI0ms5wPEVLBjwcAZs7O/3sLFWueu69u8rkmIQVamk6/XV42LaA5bsZ1lbCSmkk"
+ "wEoxrIghQ0HK7d+vwHAOEPBb8ZXBK7MAPAH8bIEjRK/4bgAAAABJRU5ErkJggg==")
+
+index.append('EE')
+catalog['EE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA8klE"
+ "QVQokYWRMUpDURBFz4MHLsAilVi5BBcgrsfWxl25gSC4gCwhBFPbhpk7dyy++cZCPM0beOde"
+ "GGbwuGXFEEZGJkSYMCcRIsTJpCbw8nQH2Li73DJlq1plFVlWOd1Z/fr0Ppfqj88sd7mzXNVZ"
+ "zuqUszrkKGf65voKNDE25Zat6qqOsqpz8eRQh5x2lkGT7UPdP+twkKRUKhciMjPi/GRm3t7C"
+ "2wSkysw18P19qUcsAjCBKkmKjHN/RORl91oBjOPxuNlsuhvovwHGGLvdbtpe1H8DgO1pe7XX"
+ "A44x+MWA/gns93vbGGNJtu3vYVnUZ4Av1C5+7JEmXZcAAAAASUVORK5CYII=")
+
+index.append('EG')
+catalog['EG'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABI0lE"
+ "QVQokZ2PIU5DYRCE5388UCSoUipwNWCqkByCO5D6OhIsqUByABwXqEFyhl6gCkigwVQQ+s/s"
+ "DuIVAki+bCaTyewmW96AxIb8rd+jH2GbwO7lJQBnItMRVjhkCZJJS0laAvk8m7UADMfjEyIc"
+ "AdIRJk0m6UqzZq0gm8NDAe3OyUlzdIze/uZ8BCK45tbpe/OwnayWGslS6fV27u9LRJRSANiG"
+ "YTgzPpa34OP2wQXc+otSymq1arp3Nxlsu75ca73KWNfnK/8EyMzmT9u2Lcof3EvzV9/OzDIa"
+ "jSaTyXK5jAhJkkidn73aurnbk5QZkiKi3+9Pp9MCYDweLxYLkiRrrbXWzpDsnEQphsPhfD5v"
+ "AZAaDAYkpZC6RUrqtDvfgX/wCf7XTmN4WqTRAAAAAElFTkSuQmCC")
+
+index.append('ES')
+catalog['ES'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABH0lE"
+ "QVQokX2RrU5cURSFv3PntghCJQkCBUgQ9RieAVmN6CtMJsFjeBZsVVUtg2dUK5owyYTOlLln"
+ "/yzEvRM6CenOypcl9l5i7SLeJrf9uyoCxmNAmWQSIQ/C5Y67zPQPl3d3LQDSz19EECGznoOq"
+ "yapqlVk5PExoCVQEAfF3kS8L7e3X0Y5LJlWpDiaNYvlMkwABvlx53MJNu3q6WHd1s70RVRjQ"
+ "ABCSje6/+G8vXycfHo+6edmKH248kwaQXPL27OTPSXI9GZ1+bvVR6qS6YZUqskyaTPqYH48P"
+ "u+d1fdl9n35bf1ptsgeCS+5O6WB0dZWzGUMtQycDe+OGRzk+nk+nbUJjzsGBzPDADbNihjs9"
+ "3fvGiUgoq+1H/ufH/bwCdrRKr4/GDeYAAAAASUVORK5CYII=")
+
+index.append('ESPERANTO')
+catalog['ESPERANTO'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAABHNCSVQICAgIfAhkiAAAALtJ"
+ "REFUKJHNzLEKglAYhuH3yCGEaDu41RhODjk4uUejV+A1eAVdhIObU12DEDjW7BK1BdFmNVRk"
+ "GdjqEFhOfePP/7winIUPy7RkVVUIIQCYLqe3dJ8+adqei7RMS7ojV4u3Mf7QRwiBcTZ6dBo5"
+ "ABpAtI4IVgHewiMv8u9kPTDuj3EMB1vZKF39FJAASlckk4Rref0JA8goi+6D16BbP2bH7PvA"
+ "fDMvKOk2v36e1hb+T0Cy40TJo5U+cHsD6JgyzFPQGaoAAAAASUVORK5CYII=")
+
+index.append('ET')
+catalog['ET'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABhElE"
+ "QVQokV2LsWuTYRjE7/3yGSsWDbRKGgixnYRujg4d/A8KXerk4iK4OIiguDQ4Cy5uTk7ZRHB2"
+ "FXEqKFhqCUrBBFNjkn5573mec6iKevyG+3FcwvYqJmOcJAzZEBmZMMCACshA/l0WUGL87f7N"
+ "RwAiFHKPsHC3bOEWMne6mxvD6Xxx+3GJqg6mz6OBh3sEI3uyVLboMZ3usWI2ZCPJ9nITQIm1"
+ "wXJjzmJm4RE2J85dvFOr1T1iUlWH/QdSRae5Nc+fxQUkd6R0F+hLBtmTt93hbGmj3Ts4urQ7"
+ "uNKoH967ekPKElPqjMevCwCAS5QocJrrG+3ewdGqRVzrPB8eN6T8C1gECgCSSSZkKaeierW/"
+ "FcqtxQ8vP26fOTX6c4AYgUQgdW/pyyeYyXKeY2fz6ffTiwwt/Bh1n22VmoiEWWqvDXvvygBq"
+ "fdM+QYosc364c/19c93NL++9KThTzjLCHMcOoAygoGFlRSTMYSzIdX4VTJ2WzGAG9xMCSFMg"
+ "/gL/6n8TgJ8hCj2miB4d6gAAAABJRU5ErkJggg==")
+
+index.append('FI')
+catalog['FI'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABN0lE"
+ "QVQokW2RvWqUYRCFz3x+ooQVFAIKCRaSIlYKtpZeR65C0moj8UpSCNYWBsRKOysF0ZA0ESQB"
+ "Q7JF8r5nnkmxy+KKD1PNz4EzJ46OzzVnWHv2WQ1Nhq+7j1duykjMMQCnZ9NxkO6tTiRV1avt"
+ "TYpMbT64XVWz5t98+9lGpNlA0q+TS6NM6n9ERDMjKJmL9VSCXQlVS/IqFNFM6MnHnecbRyct"
+ "k9bLWT0paC67etI6Ni1ZX73x5uX7URdu5rKTWU66y4lNz+qmGXda0ns1I12MwlVVFNBdNs0A"
+ "mZUJSQIJFCARPw7+3F+/BVRp6/V+N928fbHBsnNJEfHpy+E4jFwLRUih2XY3VSX9U5IEbRQs"
+ "Xn73znUntiJCS8TiJr7v/14E+ejhntSk4d2Hp5MVGWS8SBudTadX03Ro9+qwo6AAAAAASUVO"
+ "RK5CYII=")
+
+index.append('FJ')
+catalog['FJ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABzElE"
+ "QVQokU2RP2iTYRjE702+tDEl1mgS27TFarFoh9JWHVxcKkKd2kGqg4OTFFGRDoIViujmIg4F"
+ "FxUHRUGnWBCqoLSCQ0HBuFnt0qQojSY1Cd/7PM85BP9sd8PB7+7c0vmZhTA3e+fT7I73iZbI"
+ "5WL32c7K+PjBscpV5AxiaBjEYIaaQeCGey4+fzApO3ONwkfWaq4j157dNl+or6aHgzhCUIxi"
+ "FKUYb89tBnfliSv0b3n7MlouW73ekkrVBYeFiweGkKQqxeiVXtnR5hBakE8Mnenbnyiv1YVu"
+ "eybe17vxpViotnqlKqfzl2L1avqklO55dPfOhdORtZFjLh5//DlY8W1fa7GHP7siu3ZvsNUr"
+ "KTQvmVNCCbOnxbxAEKQH9uVLyaVIf6Ozy5m+Womu7h0YPCS+TFPi+q3YVpYmJzKPnmIkghM/"
+ "HK7pzVGsVZvN0CQWpTfWyHMvrvSUClrdZBD9Nnjk6OJUgNCUTpRiEKVXemNTEGyfvZFpZ3Fi"
+ "LPtsvlFxePM9gJhoVJT+b+DPMiE485rH93DU+/sfuLwOhAjQMI9IKgltIhGiUHOiEIMQyyW8"
+ "u7Bg61QDzBymfkEMoSFs/op/1v4TYjAA+A0AOEaMXbWFtAAAAABJRU5ErkJggg==")
+
+index.append('FO')
+catalog['FO'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABQklE"
+ "QVQokW2RvUoDQRDHZ7kVm9wV4S4GycUPCD6FhYW+gYXvICjEj9pOW30CCx/ABxARsbFNIYci"
+ "Z9CQi0KKNGZmdsZiY4gmv2JYZnb+O/sfMxgM4Jew3n3uNxrzWb9bEREAkCksAJRKJQBQ1ePT"
+ "JC4O9stJFEWq6pOTdDod67V9uV0wf+RvQ9JZGGNGL/jbBEBOhB3yf2GPn9CGte7RWdzuOWZh"
+ "p0BITrcOP5GUWJCVSJCEWJeq9u7ixWQAyUmT33N1rMTKpIRKJERKKERC6A9z9ZXW9YNdC572"
+ "ypV8yOiUSS/bO9sLV0iCrMQjbR9XK/YRWrb/VQ3D0I+42ewp4hDl/jye/oAx5nV32Xq/fQpJ"
+ "hRBnmeTNZGYrImPLF+Mg+K6lSWCMgT8YgFGPKYpivMU0zW9hfQNusqw2uV0QYRHf8AN4MF/m"
+ "C35t4wAAAABJRU5ErkJggg==")
+
+index.append('FR')
+catalog['FR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABPElE"
+ "QVQokW2RPYpUURSE67x+BiM4iYK0Zi5AcANGxoIbMTExFjE0EWPd02xBzIycbu49t34MegQD"
+ "v6iCgiqq6t3XG/zF9NvX15LmnJJIVtWzVy98C04QMLADePPyCYA4do7HB0kAJLGd5N7Hz+Fy"
+ "d9b69f7DDgDB7/OSYvt0OiW5uKtK0vXPH+6Znnj4iMAGI44U2VS2bUtSVRdh2z08p9dMt4Gd"
+ "tGzJUmgl2bYtvtQJAM+Znu5V3Q3s3bQjedliDoeDbQP7BruqynNmtbuLNLA3TWXJlEnnHyQl"
+ "SU91p9d2SRhN2aSXzCX7ro10p9Wdnl4LXAb2MUh60aQW/R/mDJfXKorAfu4mff/qIILcLvtc"
+ "fqyqqjo8PposMVoG9vOZn77fjNHnwdvRT6+O3b3GaKm7xxjPv3wz7m4G8AfurXtmcb4hTgAA"
+ "AABJRU5ErkJggg==")
+
+index.append('GB')
+catalog['GB'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAACAklE"
+ "QVQokQXBW0hTYQDA8f93XKtWlIdFmkaidoGkhyiokRDRzRFFPkSZRQkVQhJIIPQQlpYRXZ5S"
+ "KUPowSLohrMLuS5iuaAyy7UopqVZmYquXc7Ozrbv6/cTNbXt7oJxvB7l3t0RmCWVWrHMkX+n"
+ "TujO4IbKT4GIQm4vSqRbL80oP9zQpVNzqn3kr5RGTPo/yETyx28ZNaR891p+6Y3E5OBPKQ1T"
+ "PrgpwyGfX67f1qahNAVvgw6Rmyc62vMc8WhciP4+8S0YNkS+IyKOVwvXxqans+MGRKWGAEDw"
+ "Zlhny2a8j7MyogwMYI7lZIQ5WUPDmSvdztA/LAvA5tZ6crXVC+1TKBhRFC3nQj39QfoCvHpP"
+ "1TEGv1bNizHXUs4Fdi7alO8lJW4+BpAwOMTYLybGCUUwDUb/8LyMpIlpkUpxZM8k2ETBEvIW"
+ "49BB4XKRmUnFASIRTJOZdq63YBiYSRIWRYX6iy6bR9+ZL7OGE9kCigtD1NfR8YQ1K5k7nbvP"
+ "KCvlWvPRW9nRuFmSYb/KVk0qhQIoXjTB6VpO1E4m7Bgm8VTPpJPGVvbua9zkV1Y0nU6BpSFB"
+ "Ubw0rHyd6uz57pE5tmlKHSxV5TuydXV7KEve91g+741Kk3QSkjZU+vvDpkBbi1ZRfW7/PabS"
+ "63bNX9vpBS73rlKjn5uJHXL4Jx55cgBc/wFytP7Lx9suAgAAAABJRU5ErkJggg==")
+
+index.append('GE')
+catalog['GE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABtklE"
+ "QVQokUWRT2sTURTF73t5mUCptg0BjUhXuo60OouCf3cu/IPahfgBXPkNBMFVoRuhIPgN3HRR"
+ "BQMt1kXQEpVqcRvIIo1aEhOcSTLz5t13j4uJehYXLvdy4Jyf6vV69Fciks/gdJU8TTodERER"
+ "Zv53MkRUqVQwHPivX3TtnFooA5StrYHdXLUKAMMhv3urLoRUPdVqtXTu7b4dDD5/cAf7AIjg"
+ "v3f94dTe7n862q3bvQYRMYshIgDFi1fmj82a2nK+gh2cAwDAXL5WLgUmXAEgwmr86GHx9l38"
+ "jkgrZBm8R5Lw3ns4p5eWEZTgPRW0TKyeP/7zyWOTbrzQ5Yo/7IAZjsk5iMfMDDzz6y2kCRyL"
+ "c3CusLg46hwZ82BVnw/pzFlSSqyF90gm/LEJZn3pKgUBhAtK+9TqhXJQ36Zut8vMzrl4p55l"
+ "mbU2TdPB/Xu/7twYj8ej0SiO4x8b61EUxXHcaDR0XnD6anO4/Way+TIPCvc/dPz8WX93J1p/"
+ "CkBEjIgAKC2Fc/1+KVzJW1YnTlJmlVJENHtr1SRJ8frNHJxqt9tTkEJCU6hBrSZEo2aTmfO/"
+ "XET0B9K2TnP0V/LHAAAAAElFTkSuQmCC")
+
+index.append('GH')
+catalog['GH'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABF0lE"
+ "QVQokW2OPYpUARCE6+kLhA2Ml2VMvIE38AaCiayB4GYewGQjT6ORsOM5PIOJHkBZ0KmfLoO3"
+ "g7NgUxRNV33QS/Fv5v7+Xy0FcH0NoDOYQVIHcW3YlXrit/v9CgBov/9AgqTS5neiKpastOx2"
+ "A6wAOr3XJmvfVcVSGwBpgHWCZQng1qgL3f7Wp4+idHnJs0ds1bIVFuEXtpfSqjXgVjefub/R"
+ "4Y+W8urt1t4Az+ABgNatiy3gq5d8csHdxeHNa7aHI0BUM1gfvse7F/r2kx4rZMShnkvRsy9U"
+ "xFCRx08f++sHrDAcK9JoixlqdHQp9MgTT0CsIDQ+PztX5Ik3cuSxRo5dJ0mTCQYLrgACBngi"
+ "n1x81ADAX4YyZWXkOpMSAAAAAElFTkSuQmCC")
+
+index.append('GL')
+catalog['GL'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABJklE"
+ "QVQokWVPu2oCURA9V1cLC8GFBKwC/oKNH2JnbWtvn7QJWiSFjVr4G6IkNta2IhaL3e7i2zt3"
+ "TopdxMfhwDAz58zDxHGMG6gCUL2GJ3gAisUiAJIAEIY8neD7zOWS4i2CIPCSwSSx22Ew4HyO"
+ "45G+z0aDtdqt2hgjIplUTaLf52SC7ZaHA1crvn9wsXjYoKqZ9PYg4HQKK7xcaC0vF+73HI2e"
+ "DcY1m6ZeZxRRBKp0Sid07pEiplSK220PvR4LBary6xO8/3I8ZquVLrTWVCoahhkFaC2XS/z+"
+ "3amt5XB4VUOEIgJ4CmRFeD6j06Eqq1Vms9xs2O1yNksNYiEOziExZKygXKa1+P7B6wvyebNe"
+ "I4rw9gYRiMC5hAqYPaA3xH360ALwDxiKW0pwzWHQAAAAAElFTkSuQmCC")
+
+index.append('GR')
+catalog['GR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABTklE"
+ "QVQokWWRP0sDQRDF311ONGLgCBEb01jpgV1EwUIQyWcR8TtYCxYW4qcQRAWLdEYFEcUUAUnE"
+ "qIdICvEPBDXH7nsWe4kBYWZ4swxvfzvr5ZbOAVzshgBKq2+g951YJERCJCatPwY/RELIBACW"
+ "S2EURZJW5m4h7W1OSxAACXIpSRQe4xcvjuNisSgJAABJ5zfvFCiRkkSmOjvin1aeAzfUnwZQ"
+ "u/u2pLGylsbKGBlLWuXDYGOn7g0vnpbn8wdbM5KW1+qkjrejlAIpirvJ9/1mMw5M0mN0DFR5"
+ "vU5HQqUhURrLBrXqvdduvxYK4YDhoGA/Afm+32o9BfvVzsJs5qtL9ZzkvHswFJwYHcmcVTrB"
+ "yVV7ajL30UmslaWsZV/QtaSlLJXPDW0eNrzGw+d4flgS3PogSUgf+kcIkcLlddPDxFH6kV0C"
+ "5l8QcOdw9RfrG2tQxEeGNAAAAABJRU5ErkJggg==")
+
+index.append('GT')
+catalog['GT'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABG0lE"
+ "QVQokWWPMWpWURSEv5t3i7+QYCDEwsIyy7DKHizsk8reFbgBV+Ai3IRrsLIIhCBJiI/HvXNm"
+ "LF5A8D/NwOE7M3Pacp3aADCs/vX14dBtG7D9tPryw2tkZDZzoNczXz4ClDPV3pyfLSdAkgCn"
+ "MzefYkcVOd8+P3c6wO1jVGzCybLjSRI5P+9iZ1benjXkjrEjU0aV5B+9z1DsyFHB5o5cbirK"
+ "Uf1PxxmVVOTMgkFHVKjKdKaODpKplx+mGuWOqBeDzKMEO0PJXskBd2SlzcoUU8cB2ZcqqgLq"
+ "DEvLVKYYdYSToZDIqAA6q6dPLk6ZlW3QGkDbBZbGu3NIs1MB3Lj6w28zzGpW//h+9+qAJNu2"
+ "75909f4CDN4t/gLVAHPNcoxygQAAAABJRU5ErkJggg==")
+
+index.append('HK')
+catalog['HK'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABUElE"
+ "QVQokVWRsS6EcRDE5/vfR3wcIqJQ0OoUSjqPQucJJDyFwlOI4pQaEi+h4nJESET4jrCzu6O4"
+ "I2wmky0mmd38qmcgMZ788b9yAIADCRSgdqB7cAAAmcpUBDwUjgiRIuX+64Nery4AoLy7V4Qi"
+ "QCqiu7mlmem3k5M0iiYzkWVlBUABgNQ4HVFKKZ2Odne0tja1uFgVpNlIIh2oE1CE3OFeVVVz"
+ "eKiXF93caqrpHB3NPDy87+3ZcDg6L4EagDxEwj0Zur7W9rZ6Z2oaZej8PD8+0gyk3POnweEu"
+ "muivx8ezgDY2lKnppj09ZduOfyAdKAmAlJnoaTY5P6/1dZnp8kJNM9HtjtJyz98GuItMUuTX"
+ "42O1v//Z71vbzl1dDQcDmcGZHiUiRxySXi0vF1Iecn6SubTUWVgYPj3Vq6twz4gSoQgHqj5g"
+ "/7n+Xfw/+0ngG/KLPeZjxNoEAAAAAElFTkSuQmCC")
+
+index.append('HN')
+catalog['HN'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABYklE"
+ "QVQokW2RMWsUcRTEZ+MSc14fIxhFCNjmCyjIgWI6BbvUfgkLEYuDQFC0SKHYiKBCIJ0g9oel"
+ "pY0WRi4KWpjdsPt/82Ysluvy+PGYx/CKYSpcfoN/xDAUCkEhBfA0UONvebRzDYAEWZlIKWmm"
+ "STPFFKmgmH63+7pGUQkd/uozlYmF7aAGSlFhRtH6hRHQ1dOnm7dvrJ10aTtlpwVbzoFwQpIl"
+ "jUc1m+uYz+eSJGXmcRN7b79HRN+Xru+7rpu++Pr7z3Hbtk3TtG07m82WhrS2bZ9dxp3Jedv7"
+ "n47efziyvb21NlquBteApCVJi9t90cv9H7bvTlbv3Vq1/ergZ9fnwjfJ6vHzz1uTq+0JJaVM"
+ "CnDKkpRmyoYkyeNz9fTZxwrYvf/w5rfDNkLBLHQpGZGFjlChI8gU6Y1L4y8HT2qAZ2pcuTgK"
+ "ihTpQQTFFNOZHh4sA6iAB8DKoshymhhaH/bKf9m9dMO0S+5pAAAAAElFTkSuQmCC")
+
+index.append('HR')
+catalog['HR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABbElE"
+ "QVQokW2RMWhTcRjE78VUO3QRRHAIiiCU7u3cDl3EVQQXETrpLAgFHQulgtDZxaHYybmb4JIh"
+ "Q0cHt/jImOTl/d9L/t939zmkjQg9juOG301XBP5J//cbXQSAw0MAIQFApxMK0YMqLMMs3OM6"
+ "6/PzLgAg4k8JEmSYvXt+4g/Df4c/0un712E5cg6zotcT0AEQihVt5PHXt5/Wp5+/HJyuT8wW"
+ "kfOVzQSApCRJJOls29YuL/Pe3mIwmO/sVFXVNE1Kqa7rlNJoNLoakHR3d2+aJu/uLum2359M"
+ "p0t6NpvVKZVlCZJL2tzMLKW0GAzm29ttv99sbY3H4yVdVVVd18PhsMCLn0evHpeThTGcMmo2"
+ "/HX2/UOYPXv68faDTaNcckbv7p1vb350kd0lo1aDW/efvDw4M2qNMspcHuEMKgB1keWKextr"
+ "TpEygZQzSJmCFCOcoQhXACqwfwEX5o7syEJ2zK9LdrgjC1wdjb8S03cdKh6exgAAAABJRU5E"
+ "rkJggg==")
+
+index.append('HU')
+catalog['HU'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA7ElE"
+ "QVQokX2OKVJDURBF76v6OBQuIgaWwSLYBCoKn11lH8kWYsAiolJ9h0b8fGa4out01elh7PEl"
+ "AgBkAS08VwETgPV2C6CTTmBDjgUpUpMtNRkp5GG3mwAAzeeXtmE3GRtkyCZTDKurQl6t15kv"
+ "dPqz3VUtdTGssLqYqnm+gGF7jAGgu9Fo9F8ZY5xOp/mli/UOvwZjJJk+pP/3d4/uJAMP2Dxu"
+ "jq9HWXSVWC6aNMvFpZV1d3O7fzpMOEMSTeoilepim2XSJVO22gAmFBitrlcMJSukyVASm7IU"
+ "WTZsG8DAPVBAAecfUEDjW94AIuRtBo6TpQMAAAAASUVORK5CYII=")
+
+index.append('ID')
+catalog['ID'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA9klE"
+ "QVQokX2OO0oEURBF7+vuwEBhxsBAtyK4GkPXYeYCDN2PuAADQ82aEZXh1f0Y9AyoMB4qKKh7"
+ "qqq9rEe8CwAACwAMGADAfe8f/YRZp3e3AGLDjhQ5IsyULIYMK8WQz/cPE0YA4NsrpEghd6Vy"
+ "MVVmpSq9j+cXBiYIkZe0yZBghWUyRVcPy73CaiSBiYC/PvXxHgq7fUx1V4XlqlS5d7Pa8UkH"
+ "ptXN9dHllTabSLHi5THFCmUxy3FpXK3Pnh6bJABJgiDIYYZhmOd5st1aS7LTDrBMSQ62/4/+"
+ "0SbbwzAsDva01vCLBgSA7cn2drv1AgzDB1jUb/9idu6XLw4+AAAAAElFTkSuQmCC")
+
+index.append('IE')
+catalog['IE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABFElE"
+ "QVQokW2PPYpUYRREz/d4gjhM5M8wgyaCGxGMXICJoamZgjCrcCsmsxiTCexAMNIWH9+tW2XQ"
+ "jYE9hxvWKeoOPsMGgEHs3u0WFsAHtD16+cLGE098n5U916+uj4n44vHFGAskCRArn94mFStd"
+ "+/dfVlYg337v2t3de+3P753nH39+5fvXZKZqPHxmWDF22i23unKKZnomRZdhBZpWJEvWSdyp"
+ "Gc+46AJWhNzVpb5TSDSTGRWSD0Jbsqan+kSw08dJ4zhJVGr2VKt6Ov7fqRmKVlo6TmpV1+Hu"
+ "+EEzFG7cwMpGWZdnl9Ul9TIWYIzBgWXlyXNounEbBh/hJwg22Lj5cHP14Mq2JNv6cfv09RuD"
+ "jwX8BUrDcqkVhANcAAAAAElFTkSuQmCC")
+
+index.append('IL')
+catalog['IL'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABDUlE"
+ "QVQokW2RsUoDURBF54UEwcZusRDs/AlLBbuQykKsRBBBAiJ2aQQbEQWtLBQbBe3SaOtfhEBK"
+ "q/cNO3OPxYbdjTrVfcy53Jl5KedsrZIkqRaS3N3M3L16pqWdfD8szCwALGSShYggZB64CCeE"
+ "O9dH05RzLooCqBIqwX+VUppMJt0aatO3LwhO9xYM1ZzdauI5jT1/MP1mpcdqh+EdG2scDxqD"
+ "u3dqGsAYbOIlJ7v0+5Ql+1sLEZI6kmoaeP+idMZjbl4pg6fPFg/u3q0NVc5hH+DqkeUeD2dE"
+ "0O42O/w6zvlBfZnGMF96fVuXF7gsHJe5m4dFJA9zWYSFLCKFEPY2UprNZu2P/CvaZWY/KQh5"
+ "EgUg+FQAAAAASUVORK5CYII=")
+
+index.append('IN')
+catalog['IN'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABQElE"
+ "QVQokU1NvWpUYRA93/WiGIv4s6YwMYgxIBaKgq8hPoLgI1hapcuTmN4mYJNGsBE7qyx2W1nI"
+ "Jm6xd86Pxd1dM5wZZs6ZOdNyhk14TAOGCRseG65HogeAw48AArcYUSCYLbxmdqiYcSVM6u/X"
+ "zz0AIKkZIlhJIYorqXUd4iGuduOhid47r9vNZ+h3EidCNP199/t0X9arR+eHk1nCmA5bf98P"
+ "TltJXWsJkozfPp3+Wl4sXjy992N6+e7NYydxnHSt/ZlfdB2AAMkGi8XyYHfry9n55WKZJE5G"
+ "CYDdja5A0AIkyfODO99+znl96+WT20lW6gpu+IDjt8ez+YwmVSWWi2KpaJaKIkWae9t7J0cn"
+ "PYiR2uz9XzU3l7RkYUCPATQntyajzaqaNGVJYihJkSwYDe+BASAwXAGvMFzDAPAP+jxNFrI5"
+ "ksMAAAAASUVORK5CYII=")
+
+index.append('IQ')
+catalog['IQ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABXElE"
+ "QVQokZ2OsWqTYRSG309/bCnqICYh1IBCFl0CpR30CvQCpO1lZO6eqygddS9CxE3U6Jq6KC0B"
+ "xRrBVmyaNMn3nnNeh9+iQicfXh6e5cBJwh/i375wSQC2tgAoAhFwlzncZAYzkfrL493dAgAg"
+ "fTmEO9xFlv69TDErZ5Gp0QigwNqa7t5DpQZBluEhN7lklFHuoilCeY5KJbpduHtEzMOefeqa"
+ "+czsjPnl4etXX99MZrPj6ejH2cn2+53ReDyZTIbDYfkSXnx+/uHnx/F8VF1ari7eePftbXHp"
+ "8kJaPJ2f7h3vHYz2FdpsbkREAUDSo1sPs+cH9fvufu3K1dXqioTb1xuSVm62nuw/Xb/zGFJE"
+ "pFar1W63j74fJSWS5kYyPGik0c1pTJGmnNZqtU6nU/T7/V6vNxgMSJLMOeecyyBZlhnNvNls"
+ "AigAkFav10mauVl5SDMrbWZ+Dv6DX3iOQn5NOXoqAAAAAElFTkSuQmCC")
+
+index.append('IR')
+catalog['IR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABVUlE"
+ "QVQokV1Pu05CURCcczkBlZioBYUIDVQW+gHW/oKFf0BHb/wH7CyNhbG2wVhqQ0FMSOxM8BGs"
+ "1BARgvfs2R0LHkEnk9nX7CbrcAL8YAoD4kwXGWbq4THE0f4RADMzmJpGU2WMNqGIxkgRjaJy"
+ "dXrl4eHgeqM3o85NkRpUokqwICpBg2gorZaRwDcPmxvZjbXsWm/U21zZfPl+2cqXnr6ftlaK"
+ "z6PX0nKxO+iW8+XHr8ft9e3hwdCpqnMOAEkQBDlOeXdLI/f2uJTlDM65wWCQTL6d9ibx8oIf"
+ "78x6np9xEYCZOVWdLkzvk6psNCjCep2ZzNyfJEm/388c53KoVtluIw3sdJim7HS4s0vvacZW"
+ "i2nKVgvjMR4ehjfXLgUytZp1uwiBIhThPFnIoeoqlc/7e29A8pOiUKAIoiIKRJwIYsREY4Qq"
+ "VBGCAW4E2ALxt/w3AvALz3tDHmqDQaIAAAAASUVORK5CYII=")
+
+index.append('IS')
+catalog['IS'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABYUlE"
+ "QVQokW1RsWrUcRjL7/5/h9ap7VXhKLQ4uvgABXFXN8EX8AlcvB4FEScHQRwENxEHcRMnB/sI"
+ "DuImOPQG0bYcHBSO70u+OJzn1AxZQhJCGm68xgr6+uBn112Tur2XCCKIBRGECARAIHoAzw72"
+ "AVS5tTacHADt8MlN0SyTRVmlZKXqzfhdDwDwr7OFqgDw+Bjw9Pd50qkiFayUyBptrQHsUVWC"
+ "qiTbNtN2sEinlKykgiWJMhBNUmsNgG0Yp/fvbb7/4IvQWpvP5+0HMBw/4nRq0pmViUxnVoYj"
+ "K7MinCzGpd29b1+OmqRlvGEYp3dvb378dGHDYDCYzWZ9t/Ni8vTW9M95Um/H+xVp+87kKLkc"
+ "UMliiazdq5c/P3/VY0GqlrLtirCdVPwzmNTSQAFgjwiqrmyskQLQj0YARsN1qpIlWRKrJMgF"
+ "VEP3+P+RZ7PD7xtb109OtrcfAgHU6uBaMf4CWkFmlGgAUDYAAAAASUVORK5CYII=")
+
+index.append('IT')
+catalog['IT'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA4klE"
+ "QVQokYWRQUoDURBE38jfeYIRAhLIObLyFll5BzfmFF4l98gJsjUXkAjD7+pqFyMjCaKPontT"
+ "Dxp64A0mAAzi/Hz2NQ+bjWFJ48L+aQ/Ydnkcxyqgalm7XUWUVBGXw6HRgHr/PKczM396C6dT"
+ "9V4Rw2plaBi70imnMm7bVdX7LBBhaECSKsmSddu+FoCGkDMylP8JkmchLVndXfmXMEQY7hBR"
+ "0bMrFdl/FyKQStL3SanImPO7oEBJJtCYCGu8HyNDSgAYhoGF9ZrMOYaBF/gAwQQTx9ejJNvz"
+ "BB632/nHM18uVneE/JK6zgAAAABJRU5ErkJggg==")
+
+index.append('JM')
+catalog['JM'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAByElE"
+ "QVQokVWRT0gTcBzF3/5EtZpmG4NyNYsyvYycEZF5SCIp81DQIUQooVMFHYPoEkg3b0XUIZiC"
+ "B7FDl+gfHcpIzCLaIGxtFGg5so05a/u+7/e3DjOoxzu8y+fw3vPU3mGhjFMfMZ0HADjAAfqP"
+ "BagAEbyPIxqA53QXkmNX123AdME9LrqSmsLMqdZUnSq53qv9jTwc0l9F7u544J+YQvf92pHE"
+ "/P49tt1r977zzbKxRjqSjAd4ISzRoMy+5tjTbUuAD8DezkOPXhTlt+1rYXfIfE4+rKhzHAjJ"
+ "5agEybvjcv0OqxbMZrN+AGZWqerEE51N62AfT+5g+xqasS0gqbSMjHImJSQ3kwC8AFSNJMl0"
+ "htduMvdVWoPS1iC5L3LpBmdSUpeqrgJmqqpCaY7IlbMS2yKZoswVqrGtMnyxuqt5FSAJwA+A"
+ "pKqc6NLB47I2yMl5ufWN4ng+LGcSHN0pI0nenlRTRb300Z6Oob6l/l7+JIdzksxL2Vg2eV5g"
+ "qsTORjl2kPGYflpomvu86GlvxNTLoY2b+OoHx/O2KKxvqk7pqNQmn54LW2/ECnmL9aQ8K8+w"
+ "UELiLZYz/78rf3MFUKAFDw+gtQF/ALzGPhZXojC7AAAAAElFTkSuQmCC")
+
+index.append('JO')
+catalog['JO'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABLUlE"
+ "QVQokZWOMUubcRjE741vnYSCuGQIxGq/gFvWTqEFIZMgCG6FLo4dXF261OxuWUqhIIRSCIqQ"
+ "IWu3fIBAuxUkU+B/zz3noJEO7+KP47jhDg5XeBmVgX/n5xNgnpmZkiIkxRMk105yPB7XAHbg"
+ "4z9/76Rv0pKUxGcKC0sphWSn0wFQA3Aa0jtpl+z2P/j0xE1UVbVYLFoJQMLBgTO7DE9+eTRq"
+ "HNjOzBYA7O/77My9nkkvlx6N/PWyoQ5ERA3A87mHQ0+nYLFrHw786WPDJRtAKwGTvr3FarXY"
+ "Kn7fb2wDeLxUJ7ARYfLmLYf9Teq6/PxOkWJRYUYkKUZq7/Wb2cWsTuB+M34ctX/vvWorIoMi"
+ "k5ERCjmYIUmWUghUX4DPA2AbKGvFfyHWIYEAgAe4hlu5xLXqFgAAAABJRU5ErkJggg==")
+
+index.append('JP')
+catalog['JP'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABA0lE"
+ "QVQokXWRPW4CMRCFx6utttgG0VBwDEoOQENBS4GUXAwlHeICFDTkGlsgEmmbRUKCImNrvhT+"
+ "CSnyZNkz1hu992z3eDzkCWYW9+eiIJjVItI0jYgAcQZil48n9H1fZxK/xfHI6QOvzGYsFoXt"
+ "nLOo8Ie937PdEgLqOZ34+uTlNQ5Eh1VxD8gwsNvhPappvb1zuRSREEIVwxWP3G6J6hVV7nfO"
+ "Z7KEmdVmlntkPKaq8Ip6VPEeESaTlAGSpcJnNGK55FsTW5XVium0vJiI1MVSmtxsaBoOB1SZ"
+ "z1mvS2IRCSG4YRjati23qYg+nctpRQQR6bquNrPr9Zo/Mliw/xBFfgAmk2yfBC2dxAAAAABJ"
+ "RU5ErkJggg==")
+
+index.append('KE')
+catalog['KE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABeklE"
+ "QVQokZWOP09TYRyFz3t70UJqdLHqUkg3Q5j0U/gRymBgRcNsGmUiYXdnYnGtiwvRgaXuRG8b"
+ "Y3JvA9II0qCXe9/z++NCE1efnOFJnuUA/0kA0O/3AdgcVSUpIqLqqlVdC0kRkoPBIAEA+GQy"
+ "KYoiz/P89LS3vt6ezR5c/NrY3PxWFOPxOBuNsiwjCSAcD4fdtTU38znldGoHBxCxXm+p3b4J"
+ "ZknaOBq8D2fAndc7OjlxERdCZKf6sx3SBdU3s4vd2qyqPUZXTZc7o8MPaQk0y0qvfruIRyYm"
+ "57zWhaZTp+W1Rvc6WqRLRFVHIL0FJElACBbgIQQPl0J4I1FtqQWKMYICtaAGIBx/+dhdeaqq"
+ "N1fdLn/keLufiNZbz+896ribu5t52kg/Hb0LeIUXz15+vcqopMVoftsWn4wZIg+7PNef0UpR"
+ "iunq3cef94YpKohwpdmhUkxopPH7qtD4UOW+tdxBE3UxNVQI2AYqQIA4n/wjMhcDBGjhL1ti"
+ "PSucHkU3AAAAAElFTkSuQmCC")
+
+index.append('KG')
+catalog['KG'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABKklE"
+ "QVQokW1RMWqVYRCc78sTKwkGLAK+RhuDheI5cqPcxMoz5AKWYhHBwlqESIJdIIG8mdkdi/9/"
+ "iYXLsmyxuzOzM27wGL2v/zYPaQDABsDTszMA6UY3quJCOXbsSLEhtR3pz/n5BgCQvvyNqlRF"
+ "wpMaW2Gov6tvFbHJSHO7NbBpIJ3H6VGbU84PRmmccPeJfaeQkSI1MAGg6gF9vuF4LX+lv3C8"
+ "4sEJQ4YrSAOzAbiWA6HGC+WAuWZdsQfzck+JjO0FIYtEMWL9Iu6YQ+Jol1v25W6dJlvCqkFa"
+ "DoD0N423nO+VUv2gPis7Rmp72r0uLAJWVrz/yPlOuacv1DcK2RZcqdp/SR7Hx0OKq60h5adi"
+ "z+caz9z2XH5YBWBcAd4b2f9zd3F9sXkCfwH251SCACM16gAAAABJRU5ErkJggg==")
+
+index.append('KH')
+catalog['KH'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABbUlE"
+ "QVQokV2RsWpUYRCFz/29d/eGda9rWMiquGhjKRYGKzsDbmETfAftFUFFsbA14CMIqQy+gcRC"
+ "3yI2ErUQqyAmO+fMjMVNIDh8DKcYZjhzKow/wQJ9CfAAenTSTwvUMLzaugYgAx7pAffwSCno"
+ "cIXU6yRj5+2XGvjTpv38tfTI8JBnP2EeYkhJBhkmv7TWAr/rz8t7V388tf39cE8yPdyWg9ks"
+ "PA6/7kHuy6M0S3Iwn9/GxwIA7ilVJFyjG9cHk3Oz588uvHzRjEdnb63DlWZpBhJAERDyIEVm"
+ "VVYfPBzdXaBdQdt2m/enjx5n3chMZpKOgBoAXJCSdmalK13Xbdwpk/Np1i0WZTIpg+Z4fX8h"
+ "gCTDDO4X32wBqJomM7Ouq+Ewgfn2dpUeUkgCKuDdk9c3v33/S4ZQSCeDdGNQQYU8eUi5X7k8"
+ "2t15XwPdAYfjaUP1XoLHjw8p3VO9iDzwBKYV8AGwkyD/43TSPeUfjDQzrVjF/Z4AAAAASUVO"
+ "RK5CYII=")
+
+index.append('KR')
+catalog['KR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAByklE"
+ "QVQokU1RS08TYRS9X1uYdsa2004Z0o4kIMUJRlRSFq410oYfYHDnD/DB1hBt4p4FC/snhLia"
+ "hYnB16qJj6hx0UUJAVL6mIlTtSl1Pu9hMWI4yck9q3PPyRH94YDOgJmJiDlU/3gKycwRIkrF"
+ "1VRcbe3tf//8ZQwiFdd0VU1rWkZLJqLRbx8+HjSbE+m0qWeZORYa93o9x3H8H37ONGdnZtBs"
+ "QkoUi612Z3t7S89kjGz2/NSUDD8A8H0/CILFpdJsIY+NDayt4cE9PFmfNieWV1Zc1z1qtwEw"
+ "s+gPB0klQUTdbldNJsWrN/FnmwiC3zIyGv3R767+XL3T77kFqyCE2GsdxsKWAHK5HBG9dFMl"
+ "GQ0iiaeLD1sjZf3g01VF0awCABJCMseYCQAAz/POaerAXrhvP4qOj+0rpn88apaW7eEv1+vn"
+ "83kBEHOEmAE0Go1areY4TuVaYu568TCapeHxzcvjt25YOzuvq9VqvV4PO8SYiIhUVQXw9t37"
+ "+Uvzj29f/LqkyL9YmFZ2dxvPt14YhqHrOoAwEgOwLKtcLnc6HdPME9GVC2qYc3KyUKlUDMOw"
+ "bZuIiEkced7ZIf8fkixPhyYpJRExEfEJhTEZN2ZjOv0AAAAASUVORK5CYII=")
+
+index.append('KW')
+catalog['KW'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABKElE"
+ "QVQokX1RP0odcRic3awi8WHxTMQnSBpPEN4BvISeIZ1t4J3APuoNcoBX5AYewNrWtCEQkeU3"
+ "f74U65b6McUwDHwzTAcA18AeMAIjoBmZSZshQBgAbLLBV+Rjwris2JFKihTSUsiI5vZmOwDA"
+ "cz39/O1z+9A0HTNkSJNmc2tpNE8XpxgxAEjK/6xfvry6OPh84DiJy6kkdmVS9nf2d7/tDgBs"
+ "S9Ko9XJ9sjqpN67ruvViPQCQTFJSkLfcVYWuS9IDmB40Nr9jr0JVkgEAydZaQbq/z3JpT/ld"
+ "9tQCSSX9YvF8dzdF0gB+f+GX29uX1qq1Iqu1kK9EhPzh7Ozvw8MAIJ1+fFodk6PcizX5pJ6c"
+ "xuht2GX3QAfgETgC/gCZ98VMJgWzCOA/nWhlKT+0ek8AAAAASUVORK5CYII=")
+
+index.append('KZ')
+catalog['KZ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABk0lE"
+ "QVQokU3R32vNcRzH8df3e75a7XA2u2CJNY3UslLIzYpyoZW7ccElhRu5FFfu3C21qxUllBsn"
+ "d9Kio/wqV3JBmnEzK3ScTZNzvt/35/lyg/wBj6tHVmv5g7Lxwv1SiNWQQkIKBAIFylGgQKWy"
+ "WsudnTPLGnmk6WRhJQko3O1R66pIOOGwK/vai7VC0rK23aqmcwsUdthbeb/HrTYbH/voGn0J"
+ "B97cl6kklyT5mOcS6tnJmGqf5ye5f5DmAR78whWu7MCCPIlhf7zL2bAzVzndutvjfmb1Glra"
+ "64d1VipcJYetUrmQnY57trQH+NJPexevXqf9jrITg29j90R6XuEKR5KCQqHPHrntk+Af1Ie9"
+ "OOEn9zi1wPZvDK3QOOw78xwJHFhBrsBOJ5gBtb1hlfqnNDblG5NujvrNeV9oMxQ4ULJFFBJb"
+ "WLjIFeFkLbLjHWPr+Trlm4MszaXLT30o+wMkVCjA1bl115s+HSisCgWbXvoM0PHAKE7OEk6W"
+ "gkzNn1ejcSn//u9S5d/X+G9aqCvl+g2/aVpzpMUQkwAAAABJRU5ErkJggg==")
+
+index.append('LA')
+catalog['LA'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABZklE"
+ "QVQokWWRvWqUYRCFz/vtZ4RFTUxcFdQUbpne1k5IoRaprERIY7edhAi5BgnY2go2snfgfZgi"
+ "IvnBaDSJZL93zjljsRhWnGJ4DoeBgacI/4wB/4WLOMtFQNncBJA27JRAQQSZZEZcbEScjcft"
+ "qPd0bfDg5PA4ZcuWaieGRKUIWaRIBudvL25h3G7fH91bHO6ro1NCV7U03z57NMjMd+P9nb1J"
+ "ASoV9J0bl3fwpgEdQnUJlQldmvLq+d2VYX9l2N94sTw315zV7Fg6ls4FqA2qlTAlKjotXGmu"
+ "9nuZmZnXr/VuLfTqeTDIICWADWjJ1ajKMA6+x8lvTg+OfsXuQUegY1YmIwG2qKQywlTaOD7n"
+ "xtvd9Sc3AWx/2Dv8yaag0qKVBlwe4+H61ssfX78pJIrBOpn+IIWblCiJopeWB6OPr9v3+HTp"
+ "yxCMjEgqGXDYkcnMSBIkJEv4rFWgnP4nlTM8rTjj/g9Gz0RszhHEXAAAAABJRU5ErkJggg==")
+
+index.append('LB')
+catalog['LB'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABUElE"
+ "QVQokVVRvUoeARCcPQ/tRDu5iILPoOYt8gwJMVY+QXwAbUVrIXU6LaIhpLIIEpD4RUyhRJTE"
+ "Dwsb8TPf7exOiuNOXZZhFmaW/bHfeIxssSFsebacQAlgan0VgDKRqQhFiFQQpOgiky4S9J8f"
+ "dkoAKMu4/oukGAqq1Ymu2tNdrFV7UU0nUI5eXY1VFQBIkgC7ub/ZPtz+N3x48/JtNV4pU5Ik"
+ "M4wuHRUoCpjBTGawQob98y/H/d73/tHe2b4rBbRpzCwys+0uQcf93ufTvduH29qHu72dX/0T"
+ "dQFkY+jUKW0dbIZCCQ+vw9e+rrPTSyTLztCssfFq48/d9fLHpVC8m3+9MLMY6YaRZgoAdgq8"
+ "eL8Slxdine5yz3ooOuuhkSLlFF3Bcnbu26fDkoAGA5uYBL1giG7uohfOpKO5coQYuh8AsB/P"
+ "H5lPHtyVaBHAfxBTROajm4qVAAAAAElFTkSuQmCC")
+
+index.append('LI')
+catalog['LI'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABVklE"
+ "QVQokWWMMWqUYRiE5//20xAli0ZYCLJCIgYsAkLK3MAjCN7CCwh6iTQpxUrSBbXwAIKFGJBY"
+ "xEZRgmBgl+Sdmfe12KRQ4WGYgYcZMH2BBBqABgESYkHCCQgQEJdFHcLT59t3Vn/evfXtwfTL"
+ "+6/rh9/Xj09WpVKWlHJKSaWcL5/tdzQA9XBzf6mfNcXO9GhjvPLk42My6aRMJZWkb0+WATUA"
+ "WTj4tHX96nxpdCbr1YdtcqE6lEEHHUopgejIxhzeft56c7gp57mvUAibhogQ6CEECucG0Pr9"
+ "04N78/GN2W+pLFu0JKVo0pJNSZY8uXbzNXb7u9neyq8xfhyXo6gii/F/pjhqG48w63Ng2dTC"
+ "ViRZihRLTEWRpSixpJF1AnQAJRWZ5MUZo8i8+GYxSky72Qn0BEoaJmtNhJzkYCbZpBQhlZTp"
+ "ZsNOYDgCBORl4u/5DwD+AH37YQGY0d3gAAAAAElFTkSuQmCC")
+
+index.append('LT')
+catalog['LT'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABIElE"
+ "QVQokVWNMU6cUQyE518eQjShBgpOgOi4QSROxAWi3CNtijSp03ACRKJUVFAgBaVCK4E845kU"
+ "b1mCZY0+22N74W9A2IYFAzDgDVuvLHiFAWF19AlA0oh30DsxomzTQpgI5tOvr2OsgAXRw5Ke"
+ "PqTnGJlZMWMuu8cAxs81jkosJj1P2kw0TU55gmt3r64fMc5+4PLj8/16rZYsmjTZLJNd1cXm"
+ "1JMPB1dfMPACudmUJYvNcrFJs7qq39bUwhoDQEeKyqWeH6q8WSsXJ4cMAYxvn3EaPt+Vqai6"
+ "aE0bzdpoM9T+ib7fYJwDB3/VfxjSZKpStYFtR4x67PcFMApoKoeHIaGOGBIkJJCLBCndS7e6"
+ "X4DlFhDgV/X7Ev/1DayAfyUid0PrCp4LAAAAAElFTkSuQmCC")
+
+index.append('LU')
+catalog['LU'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABGklE"
+ "QVQokX2PMUqDURCE5yWvUETjD2IEQUERbKy9hZV4EgttAxaewnPoCSw8hpW/gagRw3s7MxZ/"
+ "TBp1WIZvh2Vhkk9P8D4BAEASSiBmKKFSVKoKVCEsJ2PyiusRAEvJQtAWyET1yV5UkyYd1eR0"
+ "dJsxK6jF7QtEUI4Aw6SDjuoajuqorjUNdwRknJ374Ahb26BsgjLpuYdJi44wicFA+8M0Ho+b"
+ "pgFgG4bhv5RSats2d3W7aAG/CilJysuj///byZaULx83Lo49+TIF2pQph7zgro6EZtVX9/18"
+ "96TDzf7zhysRcqUrHXSVYwFyCHvreHtABtRDb3cNYQdBgUJV6iDUJYm2BGSldPPpqRBCEYoQ"
+ "QPlZpTmrc2AF3+HEeWs6fQpmAAAAAElFTkSuQmCC")
+
+index.append('LV')
+catalog['LV'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABGklE"
+ "QVQokXWRMWpCURBF75OHQhRSC2rhXtJkKfYhhQtInTLbcBNi87dgCEkRSKGSgMydO5Pi/y+m"
+ "yDBc7oOZN8Oc8gyc0UUA3ut1Wq8DoH4Dd+s1gIzIiJTCFfJ0D/cg5R5kuIt82WxqBYD8ef9I"
+ "KaQgWxUZpIyihZnI8XweQD0DHsnrajO5h1E00WSUmcgheQLK5243WSxklpmISCDa3TI7E92j"
+ "Doev222RVErJzMwEkP9HGQyOh0P9aprxbCYzdH9mXib0vh1VR6O33a48Aver1XG/D3eZBbuN"
+ "dTFm7ZVul8unpqkBhHuS0aZZmAWZZklma5zpSglANSDpN9NpkOGS9509hHSX1B7dgfIAnHqQ"
+ "dgXV/mJu8U+AX3wogUmU2HzTAAAAAElFTkSuQmCC")
+
+index.append('LY')
+catalog['LY'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA3ElE"
+ "QVQokVVR223DQAxjAH+kE7RARul0QaboAP3IYpmhEB/qh2zHPgiCdEeKPOiCH5yOgADaYup6"
+ "5wXA4/vRQOB03E6iSC21FCliKIvN5+9zAdDo19/LsduDGNBEhXQxvH3cVoV0HM88xwwVlYtN"
+ "hjRpVkotFBYEhsfDoFdQyFRtdbloQkOI1WLkaIOyUjQrZGouHaOwQHBrbOzo8XAky2K4EmTT"
+ "3D866rsIm/MqCxlC62T9ML5ChTIZuw1hgcDw8/rliJHylpJlSLYit91GcMH9tMg1T5FDOysH"
+ "/gF/KJDzB2IFMQAAAABJRU5ErkJggg==")
+
+index.append('MA')
+catalog['MA'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA7ElE"
+ "QVQokX1RMUoEQRCsORe5L5ywqWBiYuDj7lf3jENDQQMzzQ3uELuquwxmj90FsSmKYaaLrqlu"
+ "xly1Pv+JZgD7PQBXoQqZViJlCZJJL/h0OAwAAPvjE5nINNl5QtAMR5hs41jAAMDlVXdESSYR"
+ "YYaDXQCygKGAlgnJEiiL3+bzPUt8OMb1T5izAMAGALTwQL7fxHkbp228jpfuDuliKWXJDFAm"
+ "b9/iy0zF3Qu9mNBmS6QjIPWHDePxiSaLCz+SJXXBVf/iFMuUiSPmGxFKZKILNhR2O5NQQgTZ"
+ "SEjoLPUMkVlAO68X+c+Oe/0C+ctawBP+hnQAAAAASUVORK5CYII=")
+
+index.append('MC')
+catalog['MC'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAAyUlE"
+ "QVQokYWPS2oDQRBDXw/tC3hpmJP6Vr6BT+ELJGDwNqtutZRFD06GOIkoChUl1aeEL3jPX0YJ"
+ "cD4DsbEZIxoMRUJK7/mWPy6XCkDy9s4YjJHeZ96i9fSW1tJ7WVdDBeLs1K1F2qS9pfVpoHdD"
+ "NZQxkCLRFb2Y/TQAlcOBdU2tGZ6nbxf/eIDTyddreTwex+MxSQghv2NZltvtVm3PGv5Sz67t"
+ "ansW/xoASduGp2eilMIOBbZutX2/3yVJsj0XPrkkY4ykZVmAT1MWYm5ocuzlAAAAAElFTkSu"
+ "QmCC")
+
+index.append('MD')
+catalog['MD'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABW0lE"
+ "QVQokT2Qu2pVYRSEZ++zTzTeQIIQIl664Bv4AsHCdGmigpa2AUtbGysfQHuxsbKLaLCxtROs"
+ "BI1gJKJED8k/s2YszjbDx1SzZmB1WNzGsYT6tIYB+AUbPgUbH1ZhQBh9APDoySqAMmx0Sw+T"
+ "4Cy71CQHfaZXthQxJVMfnz0fACDY/cGqVCX6gunBq5enXby5Pkt49JkhQw4rFxvQwyhjnlYF"
+ "qb3dunpp1g759dvfpIXNIzLQQ3CgisqUE+68Xjz/tF1/M9vZXoibG91atRZRwICyFM1dTljV"
+ "nbnRYup7HzdTJkP+P4DKJq2K6LhJ3cbbx6TvXNtKOKZJSwYGwJKpUC46aZu32I4elNrde39i"
+ "pimiyajGBRYozytiZvh5e4N2S8f4pDl/a7nGBUleXppKYRmTFfjC5Bx7K/mNyYmFy5UqV6HK"
+ "QAe8AHTM/vv77uFD2CPv1mCMAPgHcLpkVfGzF3MAAAAASUVORK5CYII=")
+
+index.append('MG')
+catalog['MG'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABAElE"
+ "QVQokXWOPU5CARCE58lLiAlGEgoqGhsu5Dk8hVyIQ1h4DUQSMaGQhp3ZWYv3g8a42Uy2+GZm"
+ "m9PphGFszxeL/v5nWwDz+RxAVQHAZlPHT6QaaSLdkCXVoOfttu3yehqo/R6HQ5H9BotREUU2"
+ "q1XfcKWrIFVEST3KqGBnAGmgtX2lCxX6mz0aMBqqqus5TnmehcUizTBpRjFSnN7rZXyp+nw8"
+ "PfL9K6IYk2AyHExGBs2HO75e0Noe46sqFRcGzV90UlZOhI8fL3U65g1KZsiUU05oaBg9y9ul"
+ "0yzKoqmUSpmZlelEoNntdrZtS7K9fl7jDTBwAwgQEIAAAwJm+AYksGMfxpLrpwAAAABJRU5E"
+ "rkJggg==")
+
+index.append('MK')
+catalog['MK'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABiElE"
+ "QVQokT3JPUiWYRiG4fP1e9vCpqAiJQpC+gENnGyoraGfKYiWmqwxajGCoFGniIYmCQKpKcqt"
+ "oqXBisihJSz74cOhwETy07qv+3muFgnO6Tix8SUMhvK/LuryFzagB79hFVZGWF6hZQJu3+Aq"
+ "flyblUopzkJk02RnPPtCzvRW+UJ6SGunn7ZMwg57dInzhZnid6IUL8qt/FkOeTh8ObygZnqg"
+ "vqIF/NPcK+wrPia2FT8Lz6eRCZ8IH5Anw2/EoCq0dZRmsPAnvZgspA/KR+RRucrL4V/hKXk9"
+ "vEsMiRe0vAaK1+W15Hv6vUx4TLb8IdyTb4b3hvtFf9brtBzFF9Mf0z+CjfSQ3AnPyQ5/k9fD"
+ "j2SHt6s5rHqHts7RjMhfg4H02fAX+UlYsuWX4ZPylfADMZ9ezYS2Qqc/PS4OydPy83CEh+Ut"
+ "4Yfyffl4eEq8LcwWoK2n6JtIujt9VywVdgup2S/6kj1CyafkVuFa4UypAzS9HvUcdZYKFYAK"
+ "dY5aqWObuLk6sMA/749Ehz/eU98AAAAASUVORK5CYII=")
+
+index.append('MM')
+catalog['MM'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABF0lE"
+ "QVQokW2RsS5EURCGv3Ndi0i0KLZQUPEgHkWv3YfZnsYT6MQ7CMm2IuJirzv/nDOKw41FMplm"
+ "/u+ffzIJbsABmIBBgRY6cVrgb7Xgs9nB7t7k5Hjz4yOur7u+Tykr+dmaeyOFe3z3t6urFlhf"
+ "b44ON6bTSSn0/fZ8/owsdB9SmEIWZiGl6bRuoJSAiEgRpUSYleTlSyoLUwWQKtD0Aze3vYn3"
+ "Zb64fJEaVMJs9B4B6n0xDHcPw+Pitet8+ZyTUaQVdQXcC7RPnG7l89wvSickpJAa68OG0fvr"
+ "hhppB5KWYa+4/xz/UuMe7g5tgTX3+PYeA6xgLjyTMxVo5Ozvh4RnXEhJwp3a3cm5VoH0vvpI"
+ "/vvuOAI+ATPsVhKSc7rOAAAAAElFTkSuQmCC")
+
+index.append('MN')
+catalog['MN'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABHklE"
+ "QVQokV2RsWqVQRSEv/3vHxSxiCSFUdKIknfIO1iFQArfJPggvkZewN7WwsJKREEQQbwJyc7s"
+ "Tor9b+7FwxR7DjNn5rAlbKvDil9wuOk63FzzrG+aDjPA5SWn5FMvt/19f/pPpbXYxV6hx3t+"
+ "Fyl2pPXV1QxAcvSD340/7bvbX0dakNq7vqbWSOX4uMME5G3Yb1y0SDK1RorqoPXUukDqMHco"
+ "HxtvnC9msm+X3UOWmgcpEsOB8xaUM+VQ2q570GxG9nJ0ivPamSuy1Ad1sNlxKNtIXXEFp9Za"
+ "c3e3TcVwkLBjewhWzfkpHinWf3kWgYUbrTEE0wezPsosaC9eTk+EVGwkiqfiV7Q20KFc7/xi"
+ "hwM+w/OdwfobJ+M16h6eGU4S17GA1gAAAABJRU5ErkJggg==")
+
+index.append('MO')
+catalog['MO'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABj0lE"
+ "QVQokU2RMWtTcRTFz3v+CZQXaeoSGoliJlts1aVLqZP9CN0EQRRBQQSjgt38Burk7GqHdujk"
+ "IkjBSRdXoWrqEEig5JH37j33XocY6Bl+nOXAgV+GN0CF/3GAc8q8zPqMCQkT7G7vAvBwD7cw"
+ "0rKcACc1GapOuqpTTQ/eHyQkAPGnHFiYmXlokcxC77azd8flhHpai4SoabfZhSOHwz3MjW4e"
+ "eq+TlypFuvS5vClORP20C6EIRU0hyAEYjEGaRvDD33Jc8/bF7f76C7GCLm9/T4QiJuqzAUE3"
+ "NVXXO22strYeXL2/2lpBxLP1Jw9XXo0rvLyciwmNIM7hFjZ6G6N6JC5fx/L42qPN9mYjb5yU"
+ "J9cv3DjfaC41Wq9/fNLQxcbi4MsggdBQMaFTTfpH/YW0ULOecpqyNKpGw+lQXek0J4gEgsbZ"
+ "JTWdarVzZadTdNaW1g5/HX4bft/7+ZGhdKMbiIQK6lwultWUbqTuH++7O52VVXT2Wj0zszBz"
+ "gyDDc+B0LlLmUqszpuWM/ib+Ab9BPtFV+EpyAAAAAElFTkSuQmCC")
+
+index.append('MT')
+catalog['MT'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA70lE"
+ "QVQokW2RsW7CUAxFb17crfQLYGKhZUAMZeGv+DT+JlLVMjEEBqLQ5dnPt8NLQtL2yrI83HNt"
+ "yUXTNHBHCBjJr9fn5dKBvyUi8iRSVdV6/YYiACABER4OZdsGVZqx7/fjUdzs4+uzPp9NdbPd"
+ "kgTAlHg68XZjVGpkjFQtFgsHJIisVq/t/fvhJunOmH2RUTMAVQfE3RHC+25HEgTBTqo98wDQ"
+ "Aehcw0By4s6AWbehc0zye2C0ocgn/R/vHHxDPM1sfNIEoE/iTWEJKWHYMPSsoiwxn2M2gxnM"
+ "kFIuB4rL5WJm3qub6/plv//146wfNaZa7RkAoEoAAAAASUVORK5CYII=")
+
+index.append('MX')
+catalog['MX'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABcElE"
+ "QVQokUWQQYvNcRiFz/83/7lNSHfuNIRmalaUBRsbuhuz4SNI8gUsfAULCxtla+EL2CsWYqGk"
+ "xJQN6VIyZaKkG9f7nvcci/+UZ/HsTk+dDtcPovUYIL/dnTU0SQAkcbHY29oCQECAgB5ot67e"
+ "ATqponKyuta6Btg2AGcu37gJWUVnfnhwvwcAY/fXXqn+ZNhG5//IMftsy5lLx48NBckqiSqK"
+ "hm3P3j2TtHHqwpKtDEgiG5NAg1gWXazKou0v719+//T24b3bH988NuAIZSpSSQE9IkpiMYus"
+ "sj0aH5m3wwc2T49PnLRkUiWRJgk00FRlMYuhtP309YuvK5PVs2eevHouWxHKNNNMAA0ExaEQ"
+ "GYYvntvW/Aerts9fsl2RzlSkWQR6BIpDIaNoeTJev3L52v5JEc6wYZVL+4MUjx5ay8rf+bfr"
+ "OgCDAXStLW9uALAspoAOU4DAAhDwEzuPdkZtRFKSpJjPd6fTBhAA0IB/+qNU8P1bz0wAAAAA"
+ "SUVORK5CYII=")
+
+index.append('MY')
+catalog['MY'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABoklE"
+ "QVQokU2RP2gUYRDF35dvveyZU3NiGj0METGNBCzsBLX0KquAVqK9GywMWFqlsBElIiJYpIg2"
+ "hojYRFJd4Cr/gMihuTtDvIuaxj8k7jez8yx2o07x+M0UjzczDmhWy68X524BqF+89jOdAAyw"
+ "Jk4P5wTof+qq5fufOh7AcmP8+PhaqZQ+fX7iQ3v/zM0Dgz4jQDPu1K9eL7p+dRE4v9Lcd3Ji"
+ "pbJ7C5bVz/anXk5uXr4SI6UoJZgIQ/C1Qx/nH0cAANv4Ujl2ZKAS69a2JzMRDD+Yjb2SRhbi"
+ "vD+aTLkhf+9r35j1Z+7UL00ugzr76NSrtwcflqbLSE3VRBiEKr5We7+w4IDG3dtD5868ILPk"
+ "xgVRhmAifPZkpOwDyWIHwHn/vd12TeBwMp121yBiKlRhEAsSyw8XD1LERHLdNTr6bmnJSf+z"
+ "27OXWQaiCJuHNiu8zUiCdFG0ubrqWsBIkmi3ayJUpYjlmUQYAkUsH2ZZaWzsTaPhtjudqFot"
+ "bHauDrN/HwBoBhLAt1YrChu93+vrZmaqpvoXVNXMkPeagw0AfwC6FlrZi8M1hwAAAABJRU5E"
+ "rkJggg==")
+
+index.append('MZ')
+catalog['MZ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABhUlE"
+ "QVQokU3GPWuTYRjF8XM3d2JtbenSQoRHLXQUOvsFBMFJ0E27dxMXUayOgopzcXByEHEJiC+f"
+ "QDrVLtVJF4tpkqIxiel9rutcDvKA8Od3TnqyjlvXgFPAFBBgtf9XajNSAN+e3u2s48eSVOTh"
+ "JneZhZnMRLqZSBmdne1OBnCuHxsvvz+/4DurTtLldFKkSGdRKV7orOYrZGQAoVhMvvner96/"
+ "2WyfjYiIUKgeRYSknPP+6f08AT7P+epl+/PC2luP9pifkQc0kiylkDSykGR1pup86MwUoH0x"
+ "bb1eWdiYizQ5Px5cGfV7o15v1Dv81/CwO+x2h93BeAAgT4FXb/zh9cnRu9nZI//ozW1DIQpB"
+ "Q2GioViiNWgtAOkYaNzZjN2vmDc9uPdracEkRIQUkkKQFB5So3nyy97bDAB9iwZxiWjdXvxd"
+ "QiXEWoZKBBGeTqytHXzKAmaWDTfaURFTRxDBFAQMIJIhGeAIx7GrjzRehh5DK9BPyACDBBlU"
+ "INXfIAAGtPAXn2ZJkhleGGQAAAAASUVORK5CYII=")
+
+index.append('NG')
+catalog['NG'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABHklE"
+ "QVQokXWRsU5VYRCEv3M54ZpAIrkNoaCh4UGIvQ9AbXwBKxore0tfg5fgIShotKEgkWBy8u/M"
+ "rMWJSiBOsc3O5pvJTnyFBYCAuPtwd7R/lARI8rA8nH85RxAYMDPzxNW7q3WdzvHueLt5A93d"
+ "wLa2l+8vRVVUrutv1zMz0N9//XBsOwmb/ivHtz9vR0alTg9PCTMhaceK5epXGh4jo1zlYjAD"
+ "xmopUvTCnWR4DI9KVdYDobhcshQ1rwgaayRZiBnhSNHIkF8S/kXqZ4TqGh6yyqPT/ax0OsOj"
+ "uhQ5fwiy1k71n9LqUlsxYmahopODk3JJnqYJWCewt9k7e3vmttuOGUx8gkcQLLBw8/lmt79b"
+ "Py3p/un+4uMFAUBwyG/TfHYgwNw2twAAAABJRU5ErkJggg==")
+
+index.append('NI')
+catalog['NI'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABO0lE"
+ "QVQokV1RsWpUARCcvXuB3CkcwYQIKmmMrU0ES/2CNPmItPcFgRT+gpWFpSCIVcBfSJO0NldZ"
+ "KUEfd5683ZlJ8e7gzmFgYZllmZnA1OiwgoTCmkIJ3TaBBh0uzgBAthwUaJRMRmmYHJRcdMol"
+ "f76cNyjA+NGaAoWSi0g5udJluaOTfjoJ/FXz6gTH+94bQQbVn5laUpUaF91/KPlgjK9vFCQj"
+ "AoBtGIY9/5DzVspmPPKDc68REW3bDnq3q10/2V3NXnz/8sdMbwKQ1GyqsbqIt0c3fLZrbOnD"
+ "lhQv3+f0dfxceO3YJUX+prXUhELRZZM4fBjvPv5qbr/p+slwduckOvaZIDXJcpa7PlO6iOeP"
+ "gE9oUEoMHk9QdBIlJJGMIlIQkUYxZJcAKHC6wHxdZAn/8H+7feUpANjBPS8xYruwWMQjAAAA"
+ "AElFTkSuQmCC")
+
+index.append('NL')
+catalog['NL'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA/UlE"
+ "QVQokX2OzSqFYRSF16tPUueMJAnhElyByzKQCzAyNXQN5u7lJDE4RUeU3r1+DD4OCqvd6mm3"
+ "9mq34Ev+yb9OC4DTcwCxYUEKDTEUyBRDpWr0l+urAQDA3D1AgpwiVCmmmKp0pnp6pXrb2zEw"
+ "YPMou/tYm0AOCSlUyJAfMB6T2No00BaLxXQ6BZAEQZC/1FqbzWaD7TGdZAm/Cq2RHLwM/d+f"
+ "tARAw+HFydnx7fy1aMqdKrmo4tJNuqSDrcnN+eWA++en1z5fvBVdcqd7qahOL5007cn6KvA4"
+ "oLvk7Y31sYlyyaWx1aToSJYtjS/hFOhAB/gN+G1DwJ++8g7ZJGpzVKC8RwAAAABJRU5ErkJg"
+ "gg==")
+
+index.append('NO')
+catalog['NO'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABWklE"
+ "QVQokW2RsWpUYRSE57/32lhIltVik6yE2FiIpY3gS9hZiGAXTBGxkzyBgTxAGou0wpKnEAIq"
+ "QuyMK2iIRbgQ0vjPnDMWdxcsMsVwisOcM3zlJxa6a9989vXq8MG8bRNIAMAw6D/vAIx23wKw"
+ "vfditZQyfr3jECRLFk1ZTMrk99lRBwBw/voN4E8v25rPLYJM0qRZs1ZXttPp4gLCVgCITABW"
+ "NeVKs5o1SdeaZEMK6NYjSinDSwrbXvkw83Uqpdy/vCzt08/7L9fOe0ZasjIVZqTCVCqSYcmM"
+ "XB3dOHh1XCJiiDf85v3Zu+eTa+NtN03T93132ra3t7d0+mNldsSw7Ysnj7MySbBm5aIG1d3b"
+ "PDn+1CVgyqRtRtrOv8NGNenKZDWZEVAI6BKw1Ewmtu/c6gC069MmmBTEpFopIxCREQDKyRLh"
+ "Rt+PHn68+PLo23isJeMBMJYO4B/0nlqS8nC3FwAAAABJRU5ErkJggg==")
+
+index.append('NP')
+catalog['NP'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAABHNCSVQICAgIfAhkiAAAATdJ"
+ "REFUKJGVkMErg3Ecxj/vEGvZZi1pxEWtxYk4OCvJRUpOjv6M5eCyUu5ylByclDhZOCAHuSo1"
+ "jNW7wstqel/vfo+bNjNtn9tzeD49369FFWOpS/PS2Q1IDzejbbTKeOpcDqhgWWZg5KTUTCdQ"
+ "HSqmhA/E83nrdjcW6k/tl1sSGPNB1HGQ69IeDFq544lgYnjLb1rgV14pZ7MEwmECkQj5RILD"
+ "u5W2vsFVNRJY1SE5tKajhzQGmJ8+4N1+pOzYSC4yHm+FDeu3oL06fFVsPCCeyZD1rklulnh7"
+ "Xq8rNWSwb1HFdFru/b3cXE65uTmFe5cbzoe6H9hUHAd8H3yfjliMneI2oejMv5IfemOTugA9"
+ "LS0pv7CgM9ApaA/U1T31p6TmvlDPrKQvkIdkkAzIIAESkvA+r2o63/P7kcPE9IErAAAAAElF"
+ "TkSuQmCC")
+
+index.append('NR')
+catalog['NR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABUUlE"
+ "QVQokVWRMUtXARTFz9M3SBCiQfgHg3RyCFpahKQv0BC0Bq0ObU0trroJTuFnkD5E5Ozg5BAh"
+ "JZQRgmLvvXvPOdfh9Zc8nOHC/V24nNNg8hbEP9kIgkQQCoBA/OceYAtia+cNAMsuSJJNWTZp"
+ "SkmTSimpT9sfWgCoOvt9KZckalw7qVtHMqnlh/NAtDAkUEVZMumQSSc9pZVUUJkCosU9zs5w"
+ "FlmNClUly5JkSeT4oGTRReBv++3j58W1FzmcU4TVQGWWWU6bZdpZps12bulkUe3Kq2fvdyff"
+ "f86tP3l0eHx6eT1EKpMhZSookplK6vFk4cs+ZpDM9MbT1Xevn29vvpSbrmeX1Q/uw/2gbnAX"
+ "7sJBAGiBIHV0cvbrz9XXH+d9P+Q0RJKUSFGSbWs86JOuBnsHhxdX3dKD+5STnqKmxBGXADTA"
+ "+t06x0Zv58Jd3QAELXK+OQKNnAAAAABJRU5ErkJggg==")
+
+index.append('NZ')
+catalog['NZ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAB2ElE"
+ "QVQokU2RPWtTYRiG75ycJD2HNM1Jk8YQa8FGMQGx/QEWwUmloOhoR3FwEFcdpIO7Y6GI2ILo"
+ "IipiBRUsOuhQ6JdFB/tB09CYxMamyUne53ne1yEg3W4urmu6A5/vTL7bTz54tHw/tRq2rHvl"
+ "IzeG9MVzJ688KQEtgAEG2oACFGAHTqdvzT2f4GS6vfYdfguZbCyVeLNQXVzfJ9LM+rxb/tDo"
+ "b/hMbF4/nrRnrBfB1ULkby20Vzd+O+TF26TP+upVbdQnM+4Uc83fdT8+tZMczMYBtl66I5TL"
+ "h4dzFEvoo0M9I2cOEpml0LEOG0XyrJb6VO+bKg1MeEUjAiirOnY5EI093XC2At4WuTP1QTuf"
+ "r4djbSV3vbWkg9nKwDV384SpXYgUARU81fB2ndSX5T++31mv0sdvOyu7kuqRxTKPO9sFU5nb"
+ "8xYabr9uvjXD2z/e27O/7NvBOMfwlXuZhPr4Z4VWSqLI3NwsKGIiViTTfva4I4CyACbSSjST"
+ "EIlSukNGke56RFqRXI9uMImwBpQNMLOQEmLpSoqElKhuz/wwveTpZqe3My+j3aBFbDLpKJEw"
+ "C7MmFmJhEmLNLNOhsUuR4rxOixhAAsBV4ODQlwrgQ/s/YUAD7j/4kDqsVjcKdgAAAABJRU5E"
+ "rkJggg==")
+
+index.append('OM')
+catalog['OM'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABGklE"
+ "QVQokXWNPUpDARCE58WngvjTCYIQiB7AVtBjeAA9g6RO52ls08YcwNzAJkUsTRrBndlZixf/"
+ "UL9iZpadZZsJfnD2sgJsG539ogVwuVy+zmY75+fPo9HBwV4VgKpP+8ZisWgB5Gq1e3Hx9vQU"
+ "8/mfvY6maST1AGwcHi7H463BwOR/7Q7bzQQ4HQ7f5vOSikqxSJMOFsMRJivC5Ha//zCdtgZK"
+ "WWRJpiAiAiTIiqhOuyABaAVUqiQzTPXIYiDYRDRca3WZ7K0PSEdYqoibW0YGk/Q6hIOmUif7"
+ "erxDC8CSSZNFRsZXLxlJOmTKqUx4/UGbR0dFWnm8Q5pMyqIpS6XMTGciITT3gAABBgRcXwEB"
+ "CHgFDPhj7NbAO7zseXjgtt+GAAAAAElFTkSuQmCC")
+
+index.append('PA')
+catalog['PA'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABTUlE"
+ "QVQokVWQvUrcURTE517/KQJxm4WFCGJhZcDWVhAsrO3zDLaxTC1i6UMEBXshPoGVbBOIhVoo"
+ "BnfV4J6PGYvrLjocDlP8zmcZjUZ4JxIASaLfJ9AipoZAB6DX6wH4918k+vOQAMh2dvj8LHdF"
+ "zPLdyUnXGt+M9es8nyb6vlYXekVS/r3k41jmdJOZ3OviYrQJkr7OY3UBT5PSaEmNo5vMWwHd"
+ "31ZqWl+uEDTTaEw3msldZnSfcw+g+7bf/dyK20dlKqhIBIWI3Y2N6lYilKmI6l4Gg+7srLv+"
+ "w5sHXT3IU0F5ylMe5dPuD31UrTW2tyuMQUw5eehlIk/OODs8tIODdirJCpvSKUt5KkWPNzqH"
+ "Qz899eOjvLiQFBEdgkkNvpRIOBGpYIkspRQAcysrn/f2QGJpqf2mYPMeRrwQFjBOPYe/LSJI"
+ "kgQZZCt4BT95XQotDMJeAAAAAElFTkSuQmCC")
+
+index.append('PE')
+catalog['PE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAAz0lE"
+ "QVQokYWRzW2CMRBEn+HrAXHgAH3QCZ3QFY1QANdENJBcvLM7OfgLf0LJaA+WPE8e7zRzVwHX"
+ "K1VA3bTdFtxmAjgeAVe1KlYrG3Czl7CwfTg4wpIjvk6nCQD745NMMj3sj7pc3Lsj2mYzv+Dy"
+ "7I54ddvufQBEFEwFLRPJEqFX9zPA/AflSPkPIP1GSlly9L+Bdo8U4d6R3Pt7IGJk1gCW0ojo"
+ "iPeAAiWZDGARYr12BMrRYGvtXuduN3ZIZkH7fmixgPN5LliaD/v9fAXADwI9YYS3Muu2AAAA"
+ "AElFTkSuQmCC")
+
+index.append('PH')
+catalog['PH'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABcUlE"
+ "QVQokWWRsWuTARTEL18/tfhZyVAzNUsVhLagiODYf6CLdnXt6tS9Q/8BoUJEBQcRK6QgEdrZ"
+ "qRShOjlUsIouLomgJua9e+8cvipBj+O44XfTNXZ2OqurQ+AHACCBBAgQSMAAAjZZGtKNfv9R"
+ "r3fm6GiQqQiRGZGkyKSnM+jpTPfo9bYao9HX6elWhHZ3v3S774dDi4C73NM93MI8zNI92u1q"
+ "b+9uAZyXhkXxYWXl1Pr6Qrs9Yyb3cKOd0GFGM7onYEVmAp+BjtRZXJja2Li+tDRjFmNLsxiP"
+ "60GYRT0oge/AJ+mjdBY4rqqrm5vb3a3Fw+cDWtDpFjTS2eKFV3hdApU0J10SWtBFjcZ6Mn9r"
+ "+/FNM7lrIgufvwOUmZDmpNtAU++Ode+h3hzK/R8apEgCZeZPYFa6jBcv9eC+vg0muZNCBwMR"
+ "AMrMa+o/w9O3OthHs4lzFdwb7iBRJ4mI2gmUp7tXfq0t55+T/779v2v9BjchVftPWcpLAAAA"
+ "AElFTkSuQmCC")
+
+index.append('PK')
+catalog['PK'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABjUlE"
+ "QVQokWVRzUpbYRScm3u9kCYRaRclTQQLmiLd2K0V6gP4COILuK3bZunaTelbKFkpuHNV6M/W"
+ "RcXUxEqlVGKSJt+cn6+Lq1ToWRzOYmY4M5MMwgAAgBFHjfcNjAAHFFDAAQIK8P7IkAGYzWcB"
+ "5GneftMey1hh5qqmClUTcVUTMRWXzodOVsjHGN29N+7dhltzi4iNSvP7zdnEJhTSKS7z1XkQ"
+ "pQJdbHU1Nyq3X26vPX09CZMsyXZWdurlOpXiAkUJ9xMR1ZXK1fpqa6512DsKHpqV5vLj5c0X"
+ "m1SKCYjM3Qv5GKOYiEhtplZOyz9GlzR+vv6y+2n3YnjBSI0KouR+hy4IjLz+8zNP863WFgMZ"
+ "wkn/pDvsiouYQJHB/QGBdB52j1aevNp4vjEIgyGHC7WFg28Hx/1jc4Uic/x7iS40MrL98V1/"
+ "2F9/tl7Nq3tf905/n05tqmZ3HoqUkiSpV+qVtCJRxKRz1tk/3ze3ICGdSRfnFi0aFMnVzZW7"
+ "u/tUp0tvl/Drv4IfFv8IfwGHykCMTQsl5QAAAABJRU5ErkJggg==")
+
+index.append('PL')
+catalog['PL'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAAuklE"
+ "QVQokY2NMW5CQQxEn2FresSduQM3g+b3oKTZ8XpSbPLFD0TKaGzZ8hs5fL/zo1qrqqDeqQEc"
+ "DoDtAMAGHPYedt7oY1ka35CfB79TRFRm+yc9T1XVCmKljf/kDVAVA+J89rI4k0yvlqx0ypIl"
+ "Z8bpdL9cGuDbzder1dHkurvcu7Xp8XgUtIKQ3DuZG2hLz+c5A/tMS6zQayxFDsZgBnZKjkdL"
+ "5CCFFBKZzJ7JGNMF8Qn1ZLbrrxPwBcJ/XXnBf5aSAAAAAElFTkSuQmCC")
+
+index.append('PR')
+catalog['PR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABi0lE"
+ "QVQokW2Rz0uUYRSFz/u9r+OPmcGNiZBaSASlYIjmvv6B/oAgglaCUNuGFq0V3LVt0cY2sxI1"
+ "ClxMiouQoYU0LgqGmoWIheA38333vve4GDUXHp7F3Vx4DscBjQ94MIV2B8gBu4ICCuDiUCAB"
+ "AnC3WTkaQm0q2e1xmWSRalSxGKnaxURMhKq71aoD+KaC5m/eLh2+qgyUh3ppJEASvEiSkITZ"
+ "34ODBIAay/1oHA8vvi42/4SYBHgP73kJQADeWwgOiCsr7vEjbH3hXh1Hx3w2Vp04qZXlkJKd"
+ "y4iYSGF0dGd1NQB4OIt791kcYO0rTPjux5OnsTGTffN5uyNieW55biJ9ZAsIAD5tMEaurzE9"
+ "RTvni1sfZ0v/vE5TpVfEur1j7BkZGd/edoC8XHCNX1RFXz+Xljg2zuR/3/MAcM619vcDYB31"
+ "IrxTbr1dLg3eLJKk0VRJ0oxA9905hzR1QHvxeTavG3P4XMBplqp1NS5lVKnRLCLGzXo9AD+H"
+ "30/eAL4D6ZWB8+v2LgBnnkcsD9MsvJUAAAAASUVORK5CYII=")
+
+index.append('PT')
+catalog['PT'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABXklE"
+ "QVQokW2RMWuTYRSFz/fmbVIrpUI62CGCgyLipP4Dndw6unTrIJ2cM3YpiL9A3ARnCwr+AUH0"
+ "D+igS52iaYmJ6XfPufc6JKFLDw+XM9yHO9wGT4Eplgmgwt8t66VUTDDcHwKIiMjwxnHT4Wqk"
+ "jlTIlHI1p8fHFQVAnpz+2uj4/b7f61O7rhG7b5mnTGPS0izJZjAIoAKISA9//tC3WnXfOOfM"
+ "x5zuceOFJS2NCwFkAAUBT5d0NuP6e3UPDifPjuzLdtOjYNla2goSQIFB7nRWcD6ztlw5u367"
+ "LWtRWq5ZkheCFECFwUMKfR3ZrUd+59Vw++qN+e43S+uPLduVQzZkABUCneb28Yf6dzl5cnLt"
+ "z8/ud3Y+WZldbENKSYsLCtH5W3z5mb1N+/Da1GMZW5JLQYQc7gAq/oHSztYORbkriQErmZsC"
+ "CQkS3BcE0OABMAbOAQPOgYLR38t/vMh/jtdGdgUCTU8AAAAASUVORK5CYII=")
+
+index.append('PY')
+catalog['PY'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABH0lE"
+ "QVQokW1SO0oEQRSsnhkHNRHBQITdC3gMUwPxOG5gYGLoLUQQg8UbGIqBV/CDLKz/XdTpelUG"
+ "4/7A4lFUP+oV3fRLxgxa1P9WMoBeD4AlSIgwA0GTIJ2z53jU71cAAPvhERGIcM4t/1WTnRs3"
+ "jXNOnY6ACuOx6xoSANvwFJgdJNsoCg2H1ZvqtbJEWf5ZYN3d/VxeKOd6dx/d7iwgpWFTF+1L"
+ "p6G2Pfo43X45HO3489XzAEgVkhbcNlaW96588H2G5ZUFvw0pPb9/rdZLIbUTmlwfVnjSkGVU"
+ "ZfHwNEhYvz063rofZFKZIJVpUnkmTCno7mZ9fnJdoRHDG+tFsGCYUZCKSIySFMMRoqAwLQAJ"
+ "5Q2CgIB5bgXnvpjtBvwCb+9W8SwiBKMAAAAASUVORK5CYII=")
+
+index.append('QA')
+catalog['QA'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABJElE"
+ "QVQokX2QzyqFURTF1719GdxkYKSQl/AulJSMTJSBKKLIQClMjQwMmHgPI15BZpJ/6Za719rr"
+ "GJx7P0ZWuzM4+7fXWft0Bv2+MZTh1anJ+y8KCOB7dBK/6gz6/bFeD0AppV5d7W5n0pmpTDIl"
+ "kSlZ3Lq+bap9S98c7r88PaYkSowkRYohcnJ6BkD3L217Ye9AqkSIJEMMRjDCIoCmDVfHrna2"
+ "klSEqNZbESKTAtC1Xek6sHR0XNviQBGMIc0IkQAa22WIl+JyublBhuI3ukgFTaYIoOvWvqCU"
+ "snJypggxFLU4epCZAtBgFKlucrG+pmijU6REk0qlDKDz+f7aG59odyilnC4vpijVv8+UnMpM"
+ "Z57fPTS2P97ebNuWNT8794z/9ANrfVvlnss+EwAAAABJRU5ErkJggg==")
+
+index.append('RO')
+catalog['RO'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABFElE"
+ "QVQokV2RMUpdYRCFv3vzP0l6myAW2roAF5LCJgsJ2GVJD1IG7FyEnQgWgRiCqG/mzJwU9waf"
+ "Dqf95nxwJs6u+SsAZhgPV+cfD6DpppvxQp/RvGbwW5ffT4DuqT1/Ovq22exAtkB+TH+VMy05"
+ "83G7HQwwd7+y2tVz9y0827lG6ZtwhDOn4+OGAbSptsoq27LDlp12uMORC0Bmw0BdbVVLqGzH"
+ "63uH/QYABtEqp/wfyD0m7HSsSki9AFUtOWQVe0DYua80rUrRWYRacopV411DJpIlwWAnqTM7"
+ "5axpD1ga0hFWoqIKGKCUPx9uUlZ9mOcjeJqmBEEyxKmoWtIwwQ8I0LLj/c8vY9CioUX/oS/W"
+ "jZf7Byetb52vN2aSAAAAAElFTkSuQmCC")
+
+index.append('RS')
+catalog['RS'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABEAAAALCAYAAACZIGYHAAAABHNCSVQICAgIfAhkiAAAASdJ"
+ "REFUKJGdkb1Kw2AUht8kX0OamDRFq8FBDUVRyeLg4DWIo5OLgjfhZYiDm65ehZPwIUKnBhws"
+ "VSzaFAtJJTZpk3wuGjSlTfUZ38N5OD/cyeo6M2UF/6X54YOYsgJLK/0qhCTBkESYCcSpRCQb"
+ "POhAuNIDX+QgNCSsdZJ8yVWk1meH+vt3sLtUNefL3TI4wDX03nmn1QyGUTxO0I0SlVwbOxbm"
+ "qml4YLrwXj0w8NDMhcpdf6Ny73Pjx3hrgM9mvq6DC0UocREDYzF3FQCjEt5powBAlCTELy0E"
+ "yYQpviD7m2LdWJbSm/DPtW1fkEmfCVAeabJnHd9OErSfRBWUUvaTgeux2sUluzk9Y4HjsDwo"
+ "pWzkxYWShq2jw6luka5j2/afGrLYto1PPjGOVBw0sOsAAAAASUVORK5CYII=")
+
+index.append('RU')
+catalog['RU'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA8klE"
+ "QVQokW2PPU7CURDEfw/+FXY0hljQ2Fh4DRNuQss9PIVXoOAuFhYUho6YSEzezNu1eEQ+ZLLZ"
+ "nd3Zj2w5HJITIqKHzuIKDgZgMgHITChAZs8KjDNHeYbd7nvomzPznOQtlFIioiwWuVzmfk8E"
+ "rWVrRGRraV94O6fTslp9DZtNPD+X7RY7LeSUUspar/18DjAANlL+DXS591Wl6rFiF4gB6Eer"
+ "0uLU+u+ClBDDmvGTXn/qZ9hZHXJUhRzSkVQ3Kdzu/LDmbXiBsd9DH7eXd2LhVtrjPQwBI5nZ"
+ "LCXcsJCK1D/Dxqa1bgHlAHFmXKZXEvALP4llHm/RUYYAAAAASUVORK5CYII=")
+
+index.append('RW')
+catalog['RW'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABRUlE"
+ "QVQokW2MMYqUURCE673/zYKyKshssJHgZQQzgz2BCAZiZCKCgeCaGegBzPQQIngNMRFBHFc3"
+ "GXUcu6urDH4GdsGmKaqgvmqXnjqE+SgVAQEEKEgIgULsjDBCeH4DAGyXmwwJJZdbaUp1i0fL"
+ "F83x+uu945ca8/bJb5chgXIVaLNMeZu+c/hkPz50bY6WcYz7XYDlEkqgzELaWWY5y5TfrO7+"
+ "Yf8WB29PbyE0MkS3KJQ8MyVXebtjvsTBo4+vKC/3J6zX7edfLKaH1meDdtq0w0447ZRjjjZb"
+ "v7b6/m5cHAA27r+MgGcm/qu9X728hyGhtbQD4PnSuTZAmyTG4jEe3OSndaYyK7MiFLPJSjqz"
+ "gpWpun6l3j/DwAlOt7wwDody0Yo99yqzJztzShY5sVRV9WNTWKHhNrAF4szzjAagXRQw8A/4"
+ "uWjB1/pT4AAAAABJRU5ErkJggg==")
+
+index.append('SA')
+catalog['SA'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABc0lE"
+ "QVQokX2RvWpUcRTE535ks5vAInGLgDFGQmqtVRRsfYtUfjR5BH2G1IKd0bxAKpsQLFQEhVsI"
+ "G7tV2BXW5CZ77zkz529horFximGaHwMzGR7grwIgQMDO3YDmQmhQAnj28GkCEoKiQhHBIEVK"
+ "DHe6Qgq5/PWj3RJAAkY/RxGRIwfSaXtqtLmy47SZNQnppK3r5nhl6SqAEoGUUsvm1vU765c3"
+ "jpujd1/f31y90ck7RZYfDA/ubtz7PPr04u1zp58BDFJy+tFs2p3rrVy60it6h+PDlu10Nv1R"
+ "TwoUJrocQA6DQpQPFgdrg7VxPamtrr5X3c589a3qFgvD8XCv2pNI8axBwZSw+/FVljIGTWZu"
+ "JBu2eZZPTiakp0jngIGiy83bzdubC+ViSunPVv35vsuf7Dxu1TIuAnQGt99sMxQKkzndZFv3"
+ "t/a/7Lv899AASjTw4HJ/meFOUu5yih5OcefDS1GrS9cYjAgAGdb/ORIt/q9fMHo3F1zEQB0A"
+ "AAAASUVORK5CYII=")
+
+index.append('SB')
+catalog['SB'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABz0lE"
+ "QVQokYWNQUiTYRzGn7Xv+0gl3MKCCS0LVgdDSQyExU4WEVGHygiCWF285KkI8VKwaJcOUQQd"
+ "WjQIpnjx0mjhoGIOYY7ARtGhSQh90Sq3nM73+b/v12F17nd4Ts/ze3x+/1Ii0Ts5+XFq6kAy"
+ "6WrdAAwAQADzLzuB1fsX4kOjsFKp8NjYTtvGxMTugYHtpVKThNZGxBMxQh/FOhldiA298zqu"
+ "Jh4/8QFvU6mDw8Nd6fRP11WtltHaIw3pkbYfmzcvPz/UX1xZt2+X7Oz1rAVY9boJBv2iTXf3"
+ "tmZTlPJEfFTO6dibc8fm0VnLVnF38Ut4VxiAFY0Gxsd74leqT1N9s7NrmUyNdGBaNy5NHx4s"
+ "fGjItRfulih6pCEAq1Co5fMhKszM/Jqba5AdJ0YWzh9/1XSquVV/ctGlUcooCkUEgAWoXG5N"
+ "xMtM/x6MfD51tBjZt1Td2LpX2KjU1pWnqKlE0ZCa7YEhoZQTP/Oyv2/ZBMqvv+24U3Rp2Ba3"
+ "2yKi9d8Ha3SkEowtR/YWv0OevXfyK1/pUem2mxQlhqK1GA3AunjkVihwtnd/5VM99Kj8Qzx7"
+ "T08XNUULhWJEjOg2RgPwFR/AdfCwjPk0sIn/8gcg3yvgjsU2IAAAAABJRU5ErkJggg==")
+
+index.append('SD')
+catalog['SD'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABOUlE"
+ "QVQokZWPsUpCcRSHf957CVP0Sks4uPkALY1Ba20+QS9QW0NEUwVBDbX2BC1NQmtQb+ATOOiQ"
+ "3SI1Rfyf3zmnQTODlj4+vukHh4PqHhxzdUkBpsAEGAOfwAD4AN6BHK5xs3G5/ziIaDCDqlOh"
+ "dBKki/hSR81mAiKr9E82J+f3WSTqIlB1kblBXIKH4CK5Ws2ABIQF71ayw0Z6tX0Wec7d/Adb"
+ "BHFs7XYEQF0Z2C31Dp6OOytjL5eXTL2cepp6mnqp9JLPRyBoKioi0kk6Jw9H+uvCEoCZRSDU"
+ "SGOwsK7rpzunOcffe3czS0DM/iq+FS92L6Jp1J/0zczdZ10Qx/FwOExgoLPQK2R3WeO2EUII"
+ "IYjIvCISAimk1uv1VquVYIT862rhuVBdq7KspMwgOStJ/QYAsIV/8QVvRk9166paHAAAAABJ"
+ "RU5ErkJggg==")
+
+index.append('SE')
+catalog['SE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABTElE"
+ "QVQokU2RP2rUcRTE57v+NEVEQVEIEgRzAEsrKwuxEe9gERC2Mm4jKBaWNtp6hTSCpUUO4BkC"
+ "IZ2KqLBs3ps/FmZNhscwxXxeMwMP3mAtvXoNA8aFxQuUUYUiVnUWuiYAL+ePANgZO0tYgeZ7"
+ "j6lQptwS5bZb+jT/MAEAcvxzKQcnR0kjOvz2p+WmWiqq5G5tX98EaoJtQw5PLv5rxzWN1ZKz"
+ "kpsqqqi2WgZq6ADjzgJ1lBBh3HEnHXdccZ2G9Ni4/fvLwQQCUdLxGkidYmftihumiQlGwphJ"
+ "weeBc56Ke7hNDNx9/mzx5PD7L8qfH75LOq57+3tNltyrWdEtk9q5eeXr2/cTVqTVUtPrZ1Vk"
+ "US0XqiEOc2bONoDjCVVNb13dbAqXbiEN9/a1y5SbpkVHsmTZgAe2nv4f8sfHfRAmbuzeBwjU"
+ "+gwQMIC/3Ll5iJVVWFoAAAAASUVORK5CYII=")
+
+index.append('SG')
+catalog['SG'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABJ0lE"
+ "QVQokY2SPUpDURCFz73vQjQknY34k9IiriArcD3au5asIVWKYNIpaRRMHwKCiCikkTgz7xyL"
+ "p4KK4sd0881p5qQHgEDZ3oZZ1DUBAgD4YwIAUAjszOfV8bHNZry9zf0+1+u4ulKEIuDOCLkr"
+ "Qu53o1EBUPX7fnkZk0k5OdkMh/nwMO3t+/RC7jKXG83kXh0cBFAAqK6rXm9zf8/xeOvsTBEv"
+ "5+cyp5vcZC4zudOdQHUKtAaDfHQEKa5vfDZ7HY+bbLo1qszonrvdx9WqFKBeLGw6FRI6HUQr"
+ "t9uMgHt2b4IRkTzS7m4Bkq/XudORJAiCfifn/LRcFgJJkgT8ZTfbAArJCvjPAQBEFJKfNj5I"
+ "KeELCVDzzQJy8/zMd4LBb4AMEmTTgDfsYE4MubWOHgAAAABJRU5ErkJggg==")
+
+index.append('SI')
+catalog['SI'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABRklE"
+ "QVQokW2MsWpUYRCFz3/vD8oWgaBgFjux1EotrXwFCxEfQ7BTLAJ2Kgoi2KhFejtbfQMbG7GJ"
+ "RViFhM29uvznzBmLu4ZV/Bi+OTMDU8ZxxAa2J2+GE2RXALPZLBOrVaDk7HQPAMjMXLcNhmGo"
+ "0+PHz/cPFoe9Y/fhZXRd/o9Siu3Sb3988ujC8bFu3zzz6u1iGMIJyaKplEyZtOSdc6dePv1Q"
+ "43DY/7a6f+1LbF2/d+nzrdc7RE+50WxuNOnWTMbRksCPCliJN3uLs+/2xGCeb5lUUtmUbQqR"
+ "FBQAXIEa7t73V9uRRTOTdFPXAgy0KGsbdAfUuos7N8YHy+WBpWgy/5iMppDcZCkYW9vzZ3hR"
+ "7+J7/+uTf34FmWS2lq2tw8lGhKKsLl4BqoGOwnyeJBQQQRYSEiZLiJjKQBkBbxT+Hv85AfgN"
+ "XohcMYYB/8YAAAAASUVORK5CYII=")
+
+index.append('SK')
+catalog['SK'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABgElE"
+ "QVQokWWOv0uVcRTGn+97X296jSxEXByi/yIhIlFq6A+owaBwyhwa6kLR1NbUINRUQ6ijRDY0"
+ "iAVN/djMKMJFb/Tbe015r/ec8zwNr0jWh8PheXg4DyfFdgEQe5AEQJBkabiHk8gBZLUaAEnl"
+ "SSYASlIF0H62vv3Iy/ri4SNsbkmUB8Duq1P6j5SSu+cjE+tTFwZOr3zs3Wjo5i3Mzca799MP"
+ "Gm1WwhlBD7nTg/2H8/qVlfzlq+bYSP9Yu63Lk+g7pPHxuH7j53rrQ7Mb7ua0kBs7zqHBKuJL"
+ "Fg5RDOr+tFqbmpvJMv3uZE5ZwANuMocHggCQA1WJa+cmFxY+N+4V2Dlz7fyJr897LBiUMZky"
+ "F51pRxWgmpaAY/U7XX214uTo7cdd9bNeW3zaevGa5jSj2e5P5geODi0tzuTDQGXjE9+u4tfq"
+ "3eOn0rM31SfzA2bqdGSmUrjBIx1sHgFSAeQXL8lNZvDYFWZyV7ndFYEIRHxfXk7bAP8a7Lf/"
+ "RAD+AEvfR7lINIfTAAAAAElFTkSuQmCC")
+
+index.append('SN')
+catalog['SN'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABK0lE"
+ "QVQokVWRMWqWYRCEnzf5QUEEGzERYpEulZ12dhZ2HsBCsPQIqXIDbyKk8SJ2goVoJdgYFXdm"
+ "dyy+X4PDtM/ssLO44FqDXnJwAMNsNnPGcO0dcP7sHJjMZNaDhgavXz4cH9xUXjhS7EhXl5c7"
+ "APL5x5dO9zQRqxPlhhJllA+Vqkjr5GRgxzCTnnbao9CkEne0UkmltAFIe6Bpx257nOhKevtR"
+ "v1vPT+vO4X8AG+BptTz2mOj9t3r3Sd+l+7fr6T2l9pWwB3aYHntcU24nenS3Hh/pZ9WTI2Wu"
+ "L6x9JaOoujxWVxCp12dK1KmM/sXH9ga4rZZGaiVFKlFSK0qUqli46QZ2FBof3zpWy9tb0VoC"
+ "g1jm1HRvHli8ggJDQfH1DfB35mGKebjfeNMf/ixbkUHqougAAAAASUVORK5CYII=")
+
+index.append('SV')
+catalog['SV'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABPElE"
+ "QVQokVWRv2qUURDFz3U/99P0EVaICImkSCEBU/peopAHSJM2PolFioAQQhJSbyE2FiGoCC6G"
+ "yL0zv2Nxs0schuEwzL9zpuj1XFX3BqooUJUqqqGKGhJS9Dio6vDDs14MAiKVOCFTEY50BB0c"
+ "7c8HQaKbnwHOdKQjnekWjqCFW7gFrTFbfyzVcnJ5u7kxrRVbtukORrbAYAx4nD76fP69ZGYp"
+ "RZJtWZZt//qyf8v4fOudH1gpZbFYDJ1tT3VwNb87//ojaG/u/uztrK0aVAowrKpX83e3p4v2"
+ "Nsm9naf/bbCBcnz2+9WL8W8FbLsfHU6QLHBngP1knByfXheNl+8PNr7d1KUm1HCmW6O17CpF"
+ "EumXs+mnjxeDwNZsfWjhDCId4ZZEEjHJvNcanEiiaHKq1OqRyxhLzAOApH+kWGxNzYWtjQAA"
+ "AABJRU5ErkJggg==")
+
+index.append('SY')
+catalog['SY'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABDElE"
+ "QVQokZ1OPUsDQRScDdeG1ClSqIe/R0UQ0Tp/Ij8kpWClhxBIGUF/wxVWOU4iEW0i3BEM2Xn7"
+ "nsUmp0KwcHgM8z5md5zhG/pb7yxnAAYDAKYKVYRgEhDERCBipP3g5XicAADM5q8IASEYGXlT"
+ "nkZv3hvpej0Fkrqq2u02Nj6LvBNw7mM2azWhzWyl66y8WxnjhbdwNb2uZdl4VLWlqs2ro+fR"
+ "4/whm97ENitu718mw6fh9guISKJNBtjJ3lG9rk4PjuPgfP/s/fPt8vAits4MgFssFp1O5+/0"
+ "ceucK4rCAej3+2VZkiTpvffeR0EyKhGKhDRN8zxPAJDS7XZJigSRaKSIRBaRsAX+gS89B00d"
+ "BrzDKwAAAABJRU5ErkJggg==")
+
+index.append('SZ')
+catalog['SZ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABxklE"
+ "QVQokSXRTUuUYRQG4Pt955nJmqIsQkqaTQ3SoqDAZRCmNgW2axO0rgja6KLCQZAKatN3qwrU"
+ "RVFEURFE0spdJPRlgUGBo4uQ8GvGd85zzn1adP2FKzl+/UMjUwAASCohpCpVKKqizFRFVJSZ"
+ "aEtIA8PS6UoZABx0p7u7m9HUCNBhpNGNNLJ/dCKMFnoL+Zu++sdJuDnNqU5zVzC6qTO6RVLT"
+ "tW094W64dcp6Lswuz8y4WfD4u2lvHFFlbOThyrcvn+/cWPw1a1GyZmwtle6PIyUQzZBouWvd"
+ "5oPF16QmabMpU9M/Wzp27xwc6jixvXPkwQ+RGOMCkCqQwEqVbaubtg6/mu/rO3rsSHeMsV6v"
+ "D5yvvhh/X+w8O/3y4uEz+0ORAgQFgHQiOyS51m6ZfPzoiZplWRZCqA4N1iY/fRyofj9wsrGh"
+ "vHfhsgIhBUxty/N76lgjzUqM70QWYswbk6mvc9eu/K3NtY1d0jSXtLcDSBavotA1zOWaW3SP"
+ "MCOjWQTNTUAh1U3dGDbuqN1+FnobT8/JHuZdcySpOXc6SZHIHOhudKPT6eLVbFeyr//t/FL2"
+ "PzITFaGrQhSioEIIIVRBQon14R8k7mFOvA7V6wAAAABJRU5ErkJggg==")
+
+index.append('TH')
+catalog['TH'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABDklE"
+ "QVQokX1RsUpDURTLtQ+KVB2qi1MXdXJx0N3BjxEcqz/gz3QVuklxL35F9zrUCvaeJMfhQWuh"
+ "GkIIZwjhpCQ28LbfyZIAnp8BpAUnyHSCkRLIJDMiI5JMcjkalcwE0Ora5C6UUhaLRbm9e3m4"
+ "v/z4WMlppWzRVIqiLFoyw7SP+/tPj+Pm7fX9+upkNvskzXDQEYpQrY5QrVrrYHAEjBvAbU8y"
+ "GRnMWtvartU1MqrbCwnADfAtkYwaZmgd/zu7VkU4ogLLpnd4cXbePzjskkkqaNIMkQ6aFGnS"
+ "kk9Pe9PpTVmtVp1Ox/Zfz2kBoJQyn88bd7t7wyHajhKCEEsEyA1tSJA8mZSv7SH/2bjFD1//"
+ "ZYwkMQleAAAAAElFTkSuQmCC")
+
+index.append('TJ')
+catalog['TJ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABO0lE"
+ "QVQokY2PvU5bURCE51ybIEuWDBXix0kKXPEE9DwLBQUdEpKDkoYiVXgWXiBFmrT0kS1HuKHC"
+ "hRE6M7tDceGGMp9Wq1lpNNopP/GPBBIAIEBvZ6db0QcwmU4BONOZiLAiQ5YsmUzJpKUkf93e"
+ "9gEArvdLRyAiyYwwmaTJrExW15rkh/FYQFmv14PBoH3JNoD651szPDJ6sfrd+zx1Gdi2XUpZ"
+ "LpdNV8A2DC5umq1jx5P12Ds4i783foekJjNbt20ufvTG52X7xJZT3tgrHy9j9vXVDmRmWa1W"
+ "w+HQbb5hOxbf/TRzypv75dNVF980zXw+73fxnSjjC9jtdHQNCyY4/XI6e5hRZLCqVlWKNSrF"
+ "KjKqgoo43Dm8u77r4xkM7Y52GVSEggxSVKrdCkVGREQGAGAHGAGb+E9eACEOOiSM812rAAAA"
+ "AElFTkSuQmCC")
+
+index.append('TM')
+catalog['TM'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABj0lE"
+ "QVQokYWOP2tTcRiFTy733tyk9s8krThoFwdxKEjFyVFwlI4uIvoFghSku6M6FvoNnARB0MXB"
+ "qbQOTQsabdJgNFiqJiY1ue857+86JLj6DGc7PE8J1wHgzc+l3sfuELi7Aggzq1dO39ZhwBjT"
+ "zTEhBrBRe7LczYtQTheqD9PeTLnya9i7XdvabR3sdxpyMZByOl/UNiMAKPD76GuUt4933i9U"
+ "zuy1P8xXZx+/3FxbvZnLPn0/anTbjW9NugBECAhFSNKi3x2lSdhpHdy7sbZ9uLd+60FUiipJ"
+ "2USjmZMigBgBCj4e8HSUZ6VCjtf1d0/vbND9+far1knHSBMpUgIQwxCCJ4n/GYbZajCp3mnc"
+ "33p0aXG5efLluP+DookmTZJiCAo+Glgz41yfFMzNpN32PklzUjKRkpxTg+Rp4pkxqxYmmwSY"
+ "i5oeKNLlwQFEGINBcyvXrqbILly2aQBNZjKjJj1yyf2fQYPDRnz2ovW655YWJdFJp1zyIJcH"
+ "d3cFAShhHhjjWY7zwGdgHf/hLwvQQSbnuK52AAAAAElFTkSuQmCC")
+
+index.append('TN')
+catalog['TN'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABN0lE"
+ "QVQokX2RsUpDYQyFz61dBUEoFFsHp452cfIB1KFbp4Kzo25C36GrTr6C4uAktljhLrp07aq7"
+ "UF1ukv9z+ItaEEMI4ZCPhJwC/URa7f/MAknDoSRSUkqKwEPhuMsdM37Vj9vbuiQJXt8UoQhO"
+ "TrS9zcYGwHRKWTIeU1WYFe12kuqSSCynj4+1WHB5yXxOu02vR2uL7i7TJ8xklqRakhSRtysl"
+ "Hh/pdLi4YHOTsuTgEHOqKi+RVJMkD8wwI4L5nKMjRiMmE7pd1tcxWwLuKQOE445VpESrxc01"
+ "p6cMBpQl7+/fwM9JWZI57uzv8/xCv894zN4es1n+j9xxd6mepLUsmTEacX7O2RmNBsDdHff3"
+ "PDzgJg9FKAM1czWbmMlDV1cyK8zkrlx3dvIPFZGk4nPVyH88zvEFZ5M7foT/uzgAAAAASUVO"
+ "RK5CYII=")
+
+index.append('TO')
+catalog['TO'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA9klE"
+ "QVQokXVSQW4CMRBzlj1Wizhy4MiN5/ANpLZ8gfYX9AEceQ8S7RNWooeOnbiHLGhXaiPLUhTb"
+ "cTRJfd9jtEoBULrFogB/ogXQdR0uF59O2G6xXtvAbpekmdSQlnzn2/nc1mAfDsgZb+/+OCIl"
+ "X68mTTpohiNMptWqAA0A29jv0bZ+ea7bQRph/jhiADlUAoDNxscjDMO2HTHOrgwSQPs0n+N1"
+ "769PS6Cs4fihe8RDGm5wliUzQJk1mOPs4Q21UgES6QhIE9FUDcmSqmEm1YrjAhObCGXkjGpo"
+ "KCyXJqEMEWQiIaGyhJwrCpC+p4PEPwMu96/wC/4dTt9th7WGAAAAAElFTkSuQmCC")
+
+index.append('TR')
+catalog['TR'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABOUlE"
+ "QVQokX2RPUpDURCFz4uxUwOxsrAQwcbaLCBoOhcgdi7BBVgHN2CvRSwsJFWqlIFg5xJiVqB5"
+ "oHdm7mdxH2hAPAzDFPMxP6dCP8rr9Z9RIenmRhHkrJwVgYfCcZc7ZvzKq/G4LUlVxXKpCEUw"
+ "GChnJhPe3zEjGZZICbNqfz9LbUnk3HRfXurkBDMODxkOSQlLJCuAzLLUypIi5M7Bgfp97u64"
+ "uuL5mbpmNGJrGzNSM0RSS5I+vzDj9IwIZjNS4uWFx0e6XZ6e6PUawD0XgHDcWb4hcXyMJY6O"
+ "eH1lOGSxYDotQFmpnaXKjJT08MDODtfX1DXAxQWrFff3zTLuuHsBNtzLTdzecn7O5iajER8f"
+ "mDUHuMlDESpAC7S3h5k8NJ/LrNrdVacjM7nLvfxQEVmq6nUj//G46BtdQD5PmN5peQAAAABJ"
+ "RU5ErkJggg==")
+
+index.append('TT')
+catalog['TT'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAB0UlE"
+ "QVQokU2Lv0sbYRyHP5fDJZ5kDBmyBFzbimBLoA2lBYO0HToINzgoFRGU0C4Oaav/gf9CV1c3"
+ "iTg4abgm9jh7JO8ld8lLIiS9q43mh/cm77dTSz48PPAMH0y63UQiAQBAPB6ftFoTXZ8AAngA"
+ "hkAfuAP+AL8BH1Bofp6urr4dHTHGpJSpVOqDruPsjE5OMB6TEDTl++Nj9SAIlEzmSTb73TSr"
+ "1SpjzHacF6urdHtL5+fU/UXdLnU61OkomjZyHPUAoGQSvbu0rtu1Wrvd5pxbjL3c2CApqVyi"
+ "UFAYkhCYmxvV6+pXQEmncXkJoudra9eMcc4552al8npri6Qkw/h/eGg01H1AefqMgoAsC0SZ"
+ "9XWzUmk2m41Go/TTzu7ukpRULJIQiMVGnKv7AJaWKAhIhPhhgujV5mbZtj3P8zzPsKw3nz6S"
+ "JLq4UGKxYaulfgGwuEi+j/GYwpDKZSJa3t4u2bbruq7rGtb1u709AKhW729u1M9AZGGBfB9C"
+ "kBAUhmQYBKzkcoZl1er1muMUTfN9Po9IZFgoqHkg8ugxZqMUjWJWg6ZB0xTHgaK8zeXavj8Y"
+ "DHq9nsnY8s5O//BQ6QNyCkznzIw8PU1mMvg3Vij8BZ4ENaDZLG35AAAAAElFTkSuQmCC")
+
+index.append('TW')
+catalog['TW'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABEUlE"
+ "QVQokW2RsU0DURBE585nOUUCCRw4JiGiBWqwKAMKgIwuoApTAhRgUYB1BIYEgUC2bP7Mzif4"
+ "YHyC1WiSnbcaaSsc3mIzMmQkY63Ht9MDwH/UALi6PAJwvDvo1fX9fBFGROxMz3ta1mSW8o8v"
+ "JpOmnN5b+mS83+9X7fXi7mUlWbPW/MiJmSmnlMlqNDLQwLDNFEAmvVqJYcnfUaacWACQBhpI"
+ "EZiueXEzk/30/qkwbW/d3gAAGiTZDsXzqyQzckRIHnDxmy6AZKCJ+RgPZ7ltMxOoTG7X2Paq"
+ "VDJQkTklSJ1QNw0pSypATyoVtwt0MBEKRKAANYXhMJNQQARZkZBQXEJEkYFq2X0k/vvuZgXg"
+ "C0lTZuDB8+IlAAAAAElFTkSuQmCC")
+
+index.append('UA')
+catalog['UA'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA90lE"
+ "QVQokW2MQUpDUQxFz/t9CIrDTpQK4mZcjgtw7CLchmsQhO7AmYJzHVjQl+ReB/2tFgzhcBNO"
+ "0rgz+5JIECSk5h47DgEdcXsNIFtuZVKUnG6pRWqKcsohR/nh/rMzAbxtXKZEyFWEHTVLozzk"
+ "KF+cNr7UEZJLpEm5imFnOXbeKI9ylKMAdYbKLUXKuf/9x54ph+CDznK9PL4c9V1ySiFSCink"
+ "KKUUNefVyRHnj61eYXVjv5iB0w57/Mtpunp/WneJ5rAH5KF0YEPamdAlFqQdsJf+OYOCIukS"
+ "kxPOdtuAaC0gYcucbUqibZ6RUM5kn7eB3xEB/ABIh27o+OhYYQAAAABJRU5ErkJggg==")
+
+index.append('US')
+catalog['US'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABuUlE"
+ "QVQokVXRvWtTYRgF8PPWBBdRKAgWqcHF1U2koMVN7aCDINVFvGoGJzGLCuLQP0Ckg4jQVoQ6"
+ "dHBoQUFjLRksfixSDIUiJC3xJiG5uXnz3vfzeRykoZ7pBwfOckRUrGAYIpAHLMCAfVH4wGrQ"
+ "bv2xAAEEeABRsUIUXq16x3ah7J1zLz96Y/Tz995aY4zROssylWVKKbm0NCeiYmVy+vTiGgVC"
+ "IFjPgREI2vN3PEInQdqD7EMpce1C9VsFUfHTQtkbYyYf28FgMPHAdLvdk/d1rqTTNE2SpNPp"
+ "tNvtEK5Lma6vfxbR7bWz0xNzZQrEgeEdDPMGjFdffWMWSkFK1hrWjty8/GXjB6LonXPuzEPT"
+ "6/VOlUyr1dp3b6der+PSyr/tZrMZx3Gj0fhFYXn5TQ7g+VXhPc7N7CfPR2ZUMNXxOwE1Ojg1"
+ "xVrDGBjDWh++e7W6VRW12tbY2DHnHBExMxHtxdBZlh3PY/bt69zR+afi/JWRlTLHMZIEUkJK"
+ "aM1KwVoewjkq3Ti0/Vtsbv4sFE708/kDVjODmfj/eO+0HgW2Q6DRZ0/Ezq2LgfccuQsN9AEF"
+ "KMABerf9C2iAYqrHmBTIAAAAAElFTkSuQmCC")
+
+index.append('UY')
+catalog['UY'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABYklE"
+ "QVQokWWRsYqTURSEz725ucZCsovCFrL4CLaWgi+wb2AnqN2CjQ+wvoK2iqA2woqInYWFWGhh"
+ "iAqyQVlJsfzKjxA3+c98x2KTKDjNmTnVx0xq29bMzAwsZwMzg/X5T8XManVpPyVqf8fTxsO3"
+ "zfFcWAiT6BQiXCHYu/M6NU1T637Or8wEl6J3LSKFxVqsTM559GlSwOF3zoqQ2SiFvxzPiBAh"
+ "QkKEA8SZQe/W/YNS66D0duaL74EP6vVF9F98aH8de0d0onM6Red0YnuzTu99SUfNz83hcLHo"
+ "IqJfCzCbg/EXiSVYyfn96HPZfXJ49XJuZy5CACGFCAUClwlEABuny427B+XBo2/bW8PDH4sV"
+ "w5qEVVSnkOLC2VPzx+P0cTI9v3VO4t9ClsFYfS0iSklv3o2TXXl2++ZFBwlXdCeVC1c4OEjh"
+ "MgIRz3efpsnXqePLGU+cOY5j4O6YAYY7ZtnsD8yTlKlFNE/4AAAAAElFTkSuQmCC")
+
+index.append('UZ')
+catalog['UZ'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABZElE"
+ "QVQokX2RPUtcYRSE54WrYLGIuaYwYAgiQUhtvZWkkhTp0hlIE61SpLAQa39AQAgEf8BC2G6L"
+ "dCnlpgnpViMrQbJ+sAtx1zNnzpviZoNF4lMMw+EwxUwCNlqttysr83t7nw8OPgLe6ex8+/pz"
+ "+fH8+vobwAEDDBjXJgEbw+G7TqdbVWcRsbm5OhppejpdXIz29w+dQVetpNrt7QJAv3/dbD46"
+ "P79eW1s6PR2W92Z6vV9lOdPtXtJklJmTWlycBcbFK3w4ef9k0Du7L3355JIfm8t5ZHpBigyj"
+ "G0XO8sEh+mkwuGk0pgDknJGRkf9HSqmqvhcRUX/nnP+af4KUIrwIxORwZ37OKWd3pOfAy9e7"
+ "V8e9cJdRpJuLFCmj02V/mppberhVtYvWM5RPfxxdnlCkaG4mo2gyOi1ImYsuLZcZFQqMQflC"
+ "Y4GiSx51+KT9cJdLUpZCABKakylvD1prvXLGbX4DOjxvXkiHuOcAAAAASUVORK5CYII=")
+
+index.append('VA')
+catalog['VA'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABa0lE"
+ "QVQokVWRsU5UYRSE5/z3v7CuuqsbthA0JmoMpQVGSKwsNBY+i8/gE/gOPoGx08YCY2I0MRYS"
+ "moWGYlciQQKu7J1/xuKyUb56Zs45c2L/6xA6ADIAgWCRoBTdOztIV3QeShk6unr7JQC4wIYL"
+ "QGMh+kOg4/OMx+OMFk7gYheY9szRSYUO2baLbTsiQlIGBJd/ahSbBh1pOuXx0dbu7uvTWb16"
+ "91GvtywpSYQ9zy4WrcZq7Pxj/3jz06u6RB87W9+fT39/I5kgw3SrdmM3Nu3GZXp95fKzpy9O"
+ "9vZGX/r3N952+48lZQFGmXva+JmjciyeHL75NXl3q/dwJa59/vhhsHxjoaqzCLhYjUGLZ0OQ"
+ "rabubizdXD8YbS9WP9cePGlUJuNJlmDxbA3PD4hszapq4OSLa6uRIuXciZpkJmET1RBmmEhE"
+ "OUV0IhIiAFwYDGwAbvuP0XvoDwSIEEFChIBL9zaFpf/f3Br+AlOWRi5rOFPDAAAAAElFTkSu"
+ "QmCC")
+
+index.append('VE')
+catalog['VE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABZklE"
+ "QVQokV2RPWtUYRCFz3tzQbZII2lSLCHGTv+AWppAkjLY2ysiCklhk38QtEkjbPIDYpPAFvEi"
+ "bGFjYSmIXxBTqCEibrbYOWdmLO4mqPDwMF+cZoqf4PAbUGH5MiIAAAEE4gIghAiEEEK9uIf9"
+ "4Wbnsb94N712/SfgmQ6opKagKpmpPPfZm/26Cjy1u8cPbO3RM+BXJgHP5F9YpmWylG4IdbOM"
+ "nH8OfG3vAM+089TJaWuAIRRgsLGxcHQ0liAGlb1et9OpMnM00urqJzLMgsy5uUuDwasKCCnI"
+ "JIPMXq/bNMOVlY9LSx/6/d8HB/Nm0SIFoBqQO6Q05u5Ot2mG29s/zNIstra+j8d++HLh5o33"
+ "bSKgchu37t97ePrl1OVucrpaU24hyk1Bl3zmysz62yd1H6+ndC34GWSSaZZmk+JiIkJe/Ood"
+ "oA6gojA7myTkEEEWEhJaS3BvCaCMJp+dgH/b/1YA/gB/9Fp0l9PEswAAAABJRU5ErkJggg==")
+
+index.append('VN')
+catalog['VN'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABC0lE"
+ "QVQokX2RIU7dYRDE50+fAEETJOJpZB2GAyA4RV2v0CBAwFXaag5R1VM0gCKIhjZhZ/b7IT5S"
+ "eAlhM9ms2Jmd7Czopcbm/CYWJJ2eSmIMjaFu0uqQKMHmVX+4ulpJkuD6Rt3qxlY3B2aYX6aM"
+ "iyrsZb0e0koSg43tKo7DrvlZuChPguwhrYa0dCshUYcL8898MpjLYq/4/ELQvKD0dCmHM/Ot"
+ "wGAOixPz59mSkiFtSaJDggsXd8XXgoJHzovfj1RNvLJkU6VkKnFZfDH35nvxw//lSTIJH5Jp"
+ "EZtVcVLcmiqOzLZ5KGKl1a1J2HK0v4+ttGLZy9pKZGsn+pj5Q3UPafm7GeQ7Gc96AotzVU2K"
+ "OmSCAAAAAElFTkSuQmCC")
+
+index.append('VOLAPUK')
+catalog['VOLAPUK'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABhUlE"
+ "QVQokWVQwYqCUAB8PtRU0kgUs0KSToWUlw59Qqc+OuhalwpSKUvUKJPSyJfK20OHdre5DTPD"
+ "DENgjMEX4jhOkkTTtG+J/Mcdx1EUxbKsMAwFQUAIKYry20C8G2azmW3blmXVarXhcKhp2na7"
+ "LcvScZw8zzudjiiKk8nkEwAAhGG4WCwwxrvdjmXZLMuiKBqPx/V6Xdd1URQ/DVEULZfL6/X6"
+ "eDziODZNc7PZlGWpKArP8zRNR1F0v9+n06ksyzBJkv1+L8tyq9XCGLMsS5KkJEkQQt/3Pc87"
+ "HA4QQo7jXNdN0xQGQZCmaRiG8/mcIAiGYV6v1+Vy6ff7PM/rug4AOB6PgiDcbjff98lqtQoA"
+ "aDabNE1TFJXnuW3bhmFkWfbePRgMyrJ0XRchZJomgTF2HGe9XjMMw3FcmqaSJAVBEATBaDTK"
+ "sowgiKIoEEK9Xk9VVRIA0O12ZVn2PA8A0G63VVVdrVYQQsMwTqfT8/mkKKrRaFQqlT+3/sb5"
+ "fC6KQlXVb+kHSbvUw5wmwUQAAAAASUVORK5CYII=")
+
+index.append('VU')
+catalog['VU'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABkUlE"
+ "QVQokU2LTYjMARjGn//M38e6cBNa2nIy2MO4SGoPnOQwLOXjMAdOitO6rDPOo72uIkWKGuXG"
+ "QbFKe9mJk5ZCLnbXxyz/eZ/nfV8Hs6V+/XoOvwf7duDtQ4wAM4D/B4EB8AdYBX4BP4AVYAko"
+ "e1+w0J/+/L58MGs9j/3uKYerkOpSjUwp19zvdksA7xZz6dvHU2dqt25UP8lD8iSHGJOWZkkW"
+ "o6MB1ACE55sFv9etLl0tnrg/pQ1Ts+QgzYaQAZQAzh73rZu1/F13HuvKNC5eY0c0p9xMZk66"
+ "mXOX89m/Q1X5zfucuqCX86oq3r4uZxGBjCKiFlFk1MN93aZ67xFKAJ++6tiElles2VC7VZy+"
+ "XJlRNCNpQ5McG+u/eo0SwPM5fli0A3vVbuF8pz+YtMER0mlhTJobk0oNNggvUAIQ1Wyw3SrO"
+ "dVZtwqqDxooWxqAFmaagwlU4+igB7NmtE0d3Tt39ve3kFjZIJ9dTKQaVUsjTPdzTYSgLoDky"
+ "u30cOAyMA3NAAAIMiLUtAICAjfgLJMVRmyd9f8QAAAAASUVORK5CYII=")
+
+index.append('WS')
+catalog['WS'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABKUlE"
+ "QVQokWWRwUpCURRF99OXg0ZCTRxY1LChOAj6AT+gWb/RzB+p33BYgRBhEEg0kEhToiBCGiQU"
+ "PM/e954GT1PzsNmTuxbnwkmAIywmAjbvbIphBP4lBdBsnu7tb9fru1eXj7Vatdt9G7+Og2JR"
+ "NwXSJZ/3d6uVAgB8d2fr/OzaLJTLm53Oc4lTMkQO3eg0N3MyqVYjUABijGi3nyaTrNE46PXe"
+ "zdwos+BmzqmbzULOhBAKo9Hn8cnhV+b9/pgETTS6mU9tWQCQApYqKzG7u3gYDj42FGAyisw3"
+ "cEFLEUgD7hFuXS8+MFDO/NNc0PNOyAikEUhIN4O0Aq3SkFxSLhQlJ/EHrWsiFBACcqFAoVJx"
+ "EgoQQSYkJOQtIYQ8EUh+Vg+JtdMuPwH4BW/TXRAimTLYAAAAAElFTkSuQmCC")
+
+index.append('YE')
+catalog['YE'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAA+ElE"
+ "QVQokZWPPUpDURCFz5XbPEhArAJik42kCVlONmBtmUcW4QpcRXYRCIh2Fkks7pk5x+KRZwoV"
+ "/BhmzvzClA98o4u/FqMFIKAC6J4eAdhCCkpHIsMZjnDQEQiK4eD780sFAFhvr8h0poNgOuig"
+ "SQfdmthM3tw/CKi3m40XC5xOsC1BsuRMp2w500pHWiqTyd1nLefzues6ALZhGP6NUsrhcKiS"
+ "hmnbo/gRlCKpSroU/rxvF1tS3W775XJ1PB4zU9LoR2wPxel02vd9AbBer/f7PUmSrbWrwEYG"
+ "GRERMZ/Pd7tdBUDGbDbj0GAwGBGXlCkNC8O3/+YLVjNhourzb1MAAAAASUVORK5CYII=")
+
+index.append('YU')
+catalog['YU'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABEAAAALCAYAAACZIGYHAAAABHNCSVQICAgIfAhkiAAAASdJ"
+ "REFUKJGdkb1Kw2AUht8kX0OamDRFq8FBDUVRyeLg4DWIo5OLgjfhZYiDm65ehZPwIUKnBhws"
+ "VSzaFAtJJTZpk3wuGjSlTfUZ38N5OD/cyeo6M2UF/6X54YOYsgJLK/0qhCTBkESYCcSpRCQb"
+ "POhAuNIDX+QgNCSsdZJ8yVWk1meH+vt3sLtUNefL3TI4wDX03nmn1QyGUTxO0I0SlVwbOxbm"
+ "qml4YLrwXj0w8NDMhcpdf6Ny73Pjx3hrgM9mvq6DC0UocREDYzF3FQCjEt5powBAlCTELy0E"
+ "yYQpviD7m2LdWJbSm/DPtW1fkEmfCVAeabJnHd9OErSfRBWUUvaTgeux2sUluzk9Y4HjsDwo"
+ "pWzkxYWShq2jw6luka5j2/afGrLYto1PPjGOVBw0sOsAAAAASUVORK5CYII=")
+
+index.append('ZA')
+catalog['ZA'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAAB00lE"
+ "QVQokU3GT0iTcRzH8c+z/ba25xkamg1KkWA1D3UoQoSSpKCgIKGgrnWJIjoJ81JGiFC3rG5B"
+ "HTtIUEYQRURUginB6lAesnnInpw5ZHv25/f98+sgQfDizRuY6MRE+4k3owvFuWo+L8AGAlpA"
+ "A4iAKrAOVIA/gHfjHWziHpSzHdtPbR3sev3efJiBkGMGsyNy/7U2PW32fUP/2eq1+drS0u+P"
+ "4ZfRofM76zUzM+dKi47IWXJknbWOyOvpUcADMPt2bEd+Zfyr/6tpRBojey/mku0di8suipyq"
+ "U3GiTtVL++tTUx6AQqGwuy8cGsRkKf2TE2u2JQ6peEqUSTYQOe7OZJ/cmTQAmOXp86hciRdO"
+ "Nm79SJXVb3K9Wg2tkBVLQlaJhDdJCyEMABE+ejh25JDeLyVLrUSTI3bqB51JURIiYVYi5Yy/"
+ "BRkYAMPHvL493s2F4HPVWBvdPXg9iAWr34N6TUScqlN1opoJTPeuC+bhOPL95sps22rESNDI"
+ "/nOvHiWePa6E5WUiteTIKrMyay6XLhZfGj2Oq8XAj8UHervObBt+8SA9/6kWtKHXTxMps2NW"
+ "ESeiIgDUwyWAkR04MLb59uXTK0AIKKCA/TcMMACAgeRf4EIuX9eJDOYAAAAASUVORK5CYII=")
+
+index.append('ZW')
+catalog['ZW'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAA3NCSVQICAjb4U/gAAABmklE"
+ "QVQokU2RP2iTcRRF3y/9mvgn0Ukq0lIDdaiCLk4ODkqREmjAoUIEEUFc1bGCg5OrOlU3h4Ii"
+ "iF0yaEWFoE5Fl0wdOrlYIzFfk7z73rsONRK4cM98Tmpvt+eX52VJxERCJERsxCpiIjoGRUn5"
+ "n7y0v7TafDBzGs4IetCDFjQP84DTPOBhRtz5uJ7yPD8wWfICN97eWljoM0HESYxNSSWR0ky3"
+ "28xEhBMP8xfli8ura/duXIhBISnNAqApTcNAaBiyKbQfSdZ9vFKoH69c+fL76a/F6enXX7dO"
+ "9HMHAiDUoa4IqAMHe1gTSTutjWxrs9z4TNru+8bk+aXFWg3DIQBV1X+nAKrVaqvVyrKTZ/37"
+ "B9J2Px0unKu9vF5/cmTgQEADCCgNAQ3Dvim8E8lC4tDN+xHBM53ntxuXJnpZUgZCwKSREEmZ"
+ "wIIVizYnkjqdTqVSGQ5662+uXq53mCmpjD05I0sCoac0t/PzW+r3+wMMnzXvHj01Uk6LgBMW"
+ "Fv6/iZO+8mozbf/Ynj02K9dEeqOoOoo9znvty/IXxrxcMJLCp60AAAAASUVORK5CYII=")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/img2pyartprov.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/img2pyartprov.py
new file mode 100644
index 0000000..a03bf69
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/art/img2pyartprov.py
@@ -0,0 +1,57 @@
+#-----------------------------------------------------------------------------
+# Name: img2pyartprov.py
+# Purpose:
+#
+# Author: Riaan Booysen
+#
+# RCS-ID: $Id$
+# Copyright: (c) 2006
+# Licence: wxPython
+#-----------------------------------------------------------------------------
+""" ArtProvider class that publishes images from modules generated by img2py.
+
+Image modules must be generated with the -u and -n <name> parameters.
+
+Typical usage:
+>>> import wx, wx.lib.art.img2pyartprov, myimagemodule
+>>> wx.ArtProvider.PushProvider(wx.lib.art.img2pyartprov.Img2PyArtProvider(myimagemodule))
+
+If myimagemodule.catalog['MYIMAGE'] is defined, it can be accessed as:
+>>> wx.ArtProvider.GetBitmap('wxART_MYIMAGE')
+
+"""
+
+import wx
+
+_NULL_BMP = wx.NullBitmap
+class Img2PyArtProvider(wx.ArtProvider):
+ def __init__(self, imageModule, artIdPrefix='wxART_'):
+ self.catalog = {}
+ self.index = []
+ self.UpdateFromImageModule(imageModule)
+ self.artIdPrefix = artIdPrefix
+
+ wx.ArtProvider.__init__(self)
+
+ def UpdateFromImageModule(self, imageModule):
+ try:
+ self.catalog.update(imageModule.catalog)
+ except AttributeError:
+ raise Exception, 'No catalog dictionary defined for the image module'
+
+ try:
+ self.index.extend(imageModule.index)
+ except AttributeError:
+ raise Exception, 'No index list defined for the image module'
+
+ def GenerateArtIdList(self):
+ return [self.artIdPrefix+name for name in self.index]
+
+ def CreateBitmap(self, artId, artClient, size):
+ if artId.startswith(self.artIdPrefix):
+ name = artId[len(self.artIdPrefix):]
+ if name in self.catalog:
+ return self.catalog[name].GetBitmap()
+
+ return _NULL_BMP
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/busy.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/busy.py
new file mode 100644
index 0000000..be83017
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/busy.py
@@ -0,0 +1,148 @@
+#---------------------------------------------------------------------------
+# File: busy.py
+# Description: A class like wx.BusyInfo but which doesn't take up so much
+# space by default and which has a nicer look.
+#
+# Date: 11-Sept-2012
+# Author: Robin Dunn
+# Tags: phoenix-port unittest, documented
+#---------------------------------------------------------------------------
+
+"""
+A class like wx.BusyInfo but which doesn't take up so much space by default
+and which has a nicer look.
+"""
+
+import wx
+from wx.lib.stattext import GenStaticText as StaticText
+
+#---------------------------------------------------------------------------
+
+
+class BusyInfo(object):
+ """
+ This class is just like :class:`wx.BusyInfo`, except that its default
+ size is smaller, (unless the size of the message requires a larger window
+ size) and the background and foreground colors of the message box can be
+ set.
+
+ Creating an instace of the class witll create an show a window with the
+ given message, and when the instance is deleted then that window will be
+ closed. This class also implements the context manager magic methods, so
+ it can be used with Python's 'with` statement, like this::
+
+ with BusyInfo('Please wait...'):
+ doSomethingThatNeedsWaiting()
+
+ """
+
+ def __init__(self, msg, parent=None, bgColour=None, fgColour=None):
+ """
+ Create a new `BusyInfo`.
+
+ :param `msg`: a string to be displayed in the BusyInfo window.
+ :param `parent`: an optional window to be used as the parent of
+ the `BusyInfo`. If given then the BusyInfo will be centered
+ over that window, otherwise it will be centered on the screen.
+ :param `bgColour`: :class:`Colour` to be used for the background
+ of the `BusyInfo`
+ :param `fgColour`: :class:`Colour` to be used for the foreground (text)
+ of the `BusyInfo`
+ """
+ self.frame = _InfoFrame(parent, msg, bgColour, fgColour)
+ self.frame.Show()
+ self.frame.Refresh()
+ self.frame.Update()
+
+ def __del__(self):
+ self.Close()
+
+ def Close(self):
+ """
+ Hide and close the busy info box
+ """
+ if self.frame:
+ self.frame.Hide()
+ self.frame.Close()
+ self.frame = None
+
+
+ # Magic methods for using this class as a Context Manager
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.Close()
+ return False
+
+
+#---------------------------------------------------------------------------
+
+class _InfoFrame(wx.Frame):
+ def __init__(self, parent, msg, bgColour=None, fgColour=None):
+ wx.Frame.__init__(self, parent, style=wx.BORDER_SIMPLE|wx.FRAME_TOOL_WINDOW|wx.STAY_ON_TOP)
+
+ bgColour = bgColour if bgColour is not None else wx.Colour(253, 255, 225)
+ fgColour = fgColour if fgColour is not None else wx.BLACK
+
+ panel = wx.Panel(self)
+ text = StaticText(panel, -1, msg)
+
+ for win in [panel, text]:
+ win.SetCursor(wx.HOURGLASS_CURSOR)
+ win.SetBackgroundColour(bgColour)
+ win.SetForegroundColour(fgColour)
+
+ size = text.GetBestSize()
+ self.SetClientSize((size.width + 60, size.height + 40))
+ panel.SetSize(self.GetClientSize())
+ text.Center()
+ self.Center()
+
+
+#---------------------------------------------------------------------------
+
+
+if __name__ == '__main__':
+
+ def test1(frm):
+ with BusyInfo("short message...", frm):
+ wx.Sleep(2)
+ wx.CallLater(1000, test2, frm)
+
+ def test2(frm):
+ with BusyInfo("This is my longer short message. Please be patient...", frm):
+ wx.Sleep(2)
+ wx.CallLater(1000, test3, frm)
+
+ def test3(frm):
+ busy = BusyInfo("Without using the context manager...", frm)
+ wx.Sleep(2)
+ del busy
+ wx.CallLater(1000, test4, frm)
+
+ def test4(frm):
+ with BusyInfo("Without using the parent window..."):
+ wx.Sleep(2)
+ wx.CallLater(1000, test5, frm)
+
+ def test5(frm):
+
+ message = """A long message with line breaks:
+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
+eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
+veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
+commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit
+esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
+cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
+laborum."""
+ with BusyInfo(message, frm):
+ wx.Sleep(2)
+
+
+
+ app = wx.App(False)
+ frm = wx.Frame(None, title="BusyInfoTest")
+ wx.CallLater(1000, test1, frm)
+ frm.Show()
+ app.MainLoop()
+ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/buttonpanel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/buttonpanel.py
new file mode 100644
index 0000000..cb3ed0e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/buttonpanel.py
@@ -0,0 +1,13 @@
+# ============================================================== #
+# This is now just a stub, importing the real module which lives #
+# under wx.lib.agw.
+# ============================================================== #
+
+"""
+Attention! ButtonPanel now lives in wx.lib.agw, together with
+its friends in the Advanced Generic Widgets family.
+
+Please update your code!
+"""
+
+from wx.lib.agw.buttonpanel import * \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/buttons.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/buttons.py
new file mode 100644
index 0000000..1d87437
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/buttons.py
@@ -0,0 +1,657 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.buttons
+# Purpose: Various kinds of generic buttons, (not native controls but
+# self-drawn.)
+#
+# Author: Robin Dunn
+#
+# Created: 9-Dec-1999
+# RCS-ID: $Id$
+# Copyright: (c) 1999 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 11/30/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for wx namespace
+# o Tested with updated demo
+#
+
+"""
+This module implements various forms of generic buttons, meaning that
+they are not built on native controls but are self-drawn. They act
+like normal buttons but you are able to better control how they look,
+bevel width, colours, etc.
+"""
+
+import wx
+import imageutils
+
+
+#----------------------------------------------------------------------
+
+class GenButtonEvent(wx.PyCommandEvent):
+ """Event sent from the generic buttons when the button is activated. """
+ def __init__(self, eventType, id):
+ wx.PyCommandEvent.__init__(self, eventType, id)
+ self.isDown = False
+ self.theButton = None
+
+ def SetIsDown(self, isDown):
+ self.isDown = isDown
+
+ def GetIsDown(self):
+ return self.isDown
+
+ def SetButtonObj(self, btn):
+ self.theButton = btn
+
+ def GetButtonObj(self):
+ return self.theButton
+
+
+#----------------------------------------------------------------------
+
+class GenButton(wx.PyControl):
+ """A generic button, and base class for the other generic buttons."""
+
+ labelDelta = 1
+
+ def __init__(self, parent, id=-1, label='',
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = 0, validator = wx.DefaultValidator,
+ name = "genbutton"):
+ cstyle = style
+ if cstyle & wx.BORDER_MASK == 0:
+ cstyle |= wx.BORDER_NONE
+ wx.PyControl.__init__(self, parent, id, pos, size, cstyle, validator, name)
+
+ self.up = True
+ self.hasFocus = False
+ self.style = style
+ if style & wx.BORDER_NONE:
+ self.bezelWidth = 0
+ self.useFocusInd = False
+ else:
+ self.bezelWidth = 2
+ self.useFocusInd = True
+
+ self.SetLabel(label)
+ self.InheritAttributes()
+ self.SetInitialSize(size)
+ self.InitColours()
+
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnGainFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnLoseFocus)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda evt: None)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.InitOtherEvents()
+
+ def InitOtherEvents(self):
+ """
+ Override in a subclass to initialize any other events that
+ need to be bound. Added so __init__ doesn't need to be
+ overriden, which is complicated with multiple inheritance
+ """
+ pass
+
+
+ def SetInitialSize(self, size=None):
+ """
+ Given the current font and bezel width settings, calculate
+ and set a good size.
+ """
+ if size is None:
+ size = wx.DefaultSize
+ wx.PyControl.SetInitialSize(self, size)
+ SetBestSize = SetInitialSize
+
+
+ def DoGetBestSize(self):
+ """
+ Overridden base class virtual. Determines the best size of the
+ button based on the label and bezel size.
+ """
+ w, h, useMin = self._GetLabelSize()
+ if self.style & wx.BU_EXACTFIT:
+ width = w + 2 + 2 * self.bezelWidth + 4 * int(self.useFocusInd)
+ height = h + 2 + 2 * self.bezelWidth + 4 * int(self.useFocusInd)
+ else:
+ defSize = wx.Button.GetDefaultSize()
+ width = 12 + w
+ if useMin and width < defSize.width:
+ width = defSize.width
+ height = 11 + h
+ if useMin and height < defSize.height:
+ height = defSize.height
+ width = width + self.bezelWidth - 1
+ height = height + self.bezelWidth - 1
+ return (width, height)
+
+
+ def AcceptsFocus(self):
+ """Overridden base class virtual."""
+ return self.IsShown() and self.IsEnabled()
+
+
+ def GetDefaultAttributes(self):
+ """
+ Overridden base class virtual. By default we should use
+ the same font/colour attributes as the native Button.
+ """
+ return wx.Button.GetClassDefaultAttributes()
+
+
+ def ShouldInheritColours(self):
+ """
+ Overridden base class virtual. Buttons usually don't inherit
+ the parent's colours.
+ """
+ return False
+
+
+ def Enable(self, enable=True):
+ if enable != self.IsEnabled():
+ wx.PyControl.Enable(self, enable)
+ self.Refresh()
+
+
+ def SetBezelWidth(self, width):
+ """Set the width of the 3D effect"""
+ self.bezelWidth = width
+
+ def GetBezelWidth(self):
+ """Return the width of the 3D effect"""
+ return self.bezelWidth
+
+ def SetUseFocusIndicator(self, flag):
+ """Specifiy if a focus indicator (dotted line) should be used"""
+ self.useFocusInd = flag
+
+ def GetUseFocusIndicator(self):
+ """Return focus indicator flag"""
+ return self.useFocusInd
+
+
+ def InitColours(self):
+ """
+ Calculate a new set of highlight and shadow colours based on
+ the background colour. Works okay if the colour is dark...
+ """
+ faceClr = self.GetBackgroundColour()
+ r, g, b = faceClr.Get()
+ fr, fg, fb = min(255,r+32), min(255,g+32), min(255,b+32)
+ self.faceDnClr = wx.Colour(fr, fg, fb)
+ sr, sg, sb = max(0,r-32), max(0,g-32), max(0,b-32)
+ self.shadowPenClr = wx.Colour(sr,sg,sb)
+ hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64)
+ self.highlightPenClr = wx.Colour(hr,hg,hb)
+ self.focusClr = wx.Colour(hr, hg, hb)
+
+
+ def SetBackgroundColour(self, colour):
+ wx.PyControl.SetBackgroundColour(self, colour)
+ self.InitColours()
+
+
+ def SetForegroundColour(self, colour):
+ wx.PyControl.SetForegroundColour(self, colour)
+ self.InitColours()
+
+ def SetDefault(self):
+ tlw = wx.GetTopLevelParent(self)
+ if hasattr(tlw, 'SetDefaultItem'):
+ tlw.SetDefaultItem(self)
+
+ def _GetLabelSize(self):
+ """ used internally """
+ w, h = self.GetTextExtent(self.GetLabel())
+ return w, h, True
+
+
+ def Notify(self):
+ evt = GenButtonEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
+ evt.SetIsDown(not self.up)
+ evt.SetButtonObj(self)
+ evt.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(evt)
+
+
+ def DrawBezel(self, dc, x1, y1, x2, y2):
+ # draw the upper left sides
+ if self.up:
+ dc.SetPen(wx.Pen(self.highlightPenClr, 1, wx.SOLID))
+ else:
+ dc.SetPen(wx.Pen(self.shadowPenClr, 1, wx.SOLID))
+ for i in range(self.bezelWidth):
+ dc.DrawLine(x1+i, y1, x1+i, y2-i)
+ dc.DrawLine(x1, y1+i, x2-i, y1+i)
+
+ # draw the lower right sides
+ if self.up:
+ dc.SetPen(wx.Pen(self.shadowPenClr, 1, wx.SOLID))
+ else:
+ dc.SetPen(wx.Pen(self.highlightPenClr, 1, wx.SOLID))
+ for i in range(self.bezelWidth):
+ dc.DrawLine(x1+i, y2-i, x2+1, y2-i)
+ dc.DrawLine(x2-i, y1+i, x2-i, y2)
+
+
+ def DrawLabel(self, dc, width, height, dx=0, dy=0):
+ dc.SetFont(self.GetFont())
+ if self.IsEnabled():
+ dc.SetTextForeground(self.GetForegroundColour())
+ else:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+ label = self.GetLabel()
+ tw, th = dc.GetTextExtent(label)
+ if not self.up:
+ dx = dy = self.labelDelta
+ dc.DrawText(label, (width-tw)/2+dx, (height-th)/2+dy)
+
+
+ def DrawFocusIndicator(self, dc, w, h):
+ bw = self.bezelWidth
+ textClr = self.GetForegroundColour()
+ focusIndPen = wx.Pen(textClr, 1, wx.USER_DASH)
+ focusIndPen.SetDashes([1,1])
+ focusIndPen.SetCap(wx.CAP_BUTT)
+
+ if wx.Platform == "__WXMAC__":
+ dc.SetLogicalFunction(wx.XOR)
+ else:
+ focusIndPen.SetColour(self.focusClr)
+ dc.SetLogicalFunction(wx.INVERT)
+ dc.SetPen(focusIndPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(bw+2,bw+2, w-bw*2-4, h-bw*2-4)
+ dc.SetLogicalFunction(wx.COPY)
+
+
+ def OnPaint(self, event):
+ (width, height) = self.GetClientSizeTuple()
+ x1 = y1 = 0
+ x2 = width-1
+ y2 = height-1
+
+ dc = wx.PaintDC(self)
+ brush = self.GetBackgroundBrush(dc)
+ if brush is not None:
+ dc.SetBackground(brush)
+ dc.Clear()
+
+ self.DrawBezel(dc, x1, y1, x2, y2)
+ self.DrawLabel(dc, width, height)
+ if self.hasFocus and self.useFocusInd:
+ self.DrawFocusIndicator(dc, width, height)
+
+
+ def OnSize(self, event):
+ self.Refresh()
+ event.Skip()
+
+
+ def GetBackgroundBrush(self, dc):
+ if self.up:
+ colBg = self.GetBackgroundColour()
+ brush = wx.Brush(colBg, wx.SOLID)
+ if self.style & wx.BORDER_NONE:
+ myAttr = self.GetDefaultAttributes()
+ parAttr = self.GetParent().GetDefaultAttributes()
+ myDef = colBg == myAttr.colBg
+ parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg
+ if myDef and parDef:
+ if wx.Platform == "__WXMAC__":
+ c = wx.MacThemeColour(1) # 1 == kThemeBrushDialogBackgroundActive
+ brush = wx.Brush(c)
+ elif wx.Platform == "__WXMSW__":
+ if self.DoEraseBackground(dc):
+ brush = None
+ elif myDef and not parDef:
+ colBg = self.GetParent().GetBackgroundColour()
+ brush = wx.Brush(colBg, wx.SOLID)
+ else:
+ # this line assumes that a pressed button should be hilighted with
+ # a solid colour even if the background is supposed to be transparent
+ brush = wx.Brush(self.faceDnClr, wx.SOLID)
+ return brush
+
+
+ def OnLeftDown(self, event):
+ if not self.IsEnabled():
+ return
+ self.up = False
+ self.CaptureMouse()
+ self.SetFocus()
+ self.Refresh()
+ event.Skip()
+
+
+ def OnLeftUp(self, event):
+ if not self.IsEnabled() or not self.HasCapture():
+ return
+ if self.HasCapture():
+ self.ReleaseMouse()
+ if not self.up: # if the button was down when the mouse was released...
+ self.Notify()
+ self.up = True
+ if self: # in case the button was destroyed in the eventhandler
+ self.Refresh()
+ event.Skip()
+
+
+ def OnMotion(self, event):
+ if not self.IsEnabled() or not self.HasCapture():
+ return
+ if event.LeftIsDown() and self.HasCapture():
+ x,y = event.GetPositionTuple()
+ w,h = self.GetClientSizeTuple()
+ if self.up and x<w and x>=0 and y<h and y>=0:
+ self.up = False
+ self.Refresh()
+ return
+ if not self.up and (x<0 or y<0 or x>=w or y>=h):
+ self.up = True
+ self.Refresh()
+ return
+ event.Skip()
+
+
+ def OnGainFocus(self, event):
+ self.hasFocus = True
+ self.Refresh()
+ self.Update()
+
+
+ def OnLoseFocus(self, event):
+ self.hasFocus = False
+ self.Refresh()
+ self.Update()
+
+
+ def OnKeyDown(self, event):
+ if self.hasFocus and event.GetKeyCode() == ord(" "):
+ self.up = False
+ self.Refresh()
+ event.Skip()
+
+
+ def OnKeyUp(self, event):
+ if self.hasFocus and event.GetKeyCode() == ord(" "):
+ self.up = True
+ self.Notify()
+ self.Refresh()
+ event.Skip()
+
+
+#----------------------------------------------------------------------
+
+class GenBitmapButton(GenButton):
+ """A generic bitmap button."""
+
+ def __init__(self, parent, id=-1, bitmap=wx.NullBitmap,
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = 0, validator = wx.DefaultValidator,
+ name = "genbutton"):
+ self.bmpDisabled = None
+ self.bmpFocus = None
+ self.bmpSelected = None
+ self.SetBitmapLabel(bitmap)
+ GenButton.__init__(self, parent, id, "", pos, size, style, validator, name)
+
+
+ def GetBitmapLabel(self):
+ return self.bmpLabel
+ def GetBitmapDisabled(self):
+ return self.bmpDisabled
+ def GetBitmapFocus(self):
+ return self.bmpFocus
+ def GetBitmapSelected(self):
+ return self.bmpSelected
+
+
+ def SetBitmapDisabled(self, bitmap):
+ """Set bitmap to display when the button is disabled"""
+ self.bmpDisabled = bitmap
+
+ def SetBitmapFocus(self, bitmap):
+ """Set bitmap to display when the button has the focus"""
+ self.bmpFocus = bitmap
+ self.SetUseFocusIndicator(False)
+
+ def SetBitmapSelected(self, bitmap):
+ """Set bitmap to display when the button is selected (pressed down)"""
+ self.bmpSelected = bitmap
+
+ def SetBitmapLabel(self, bitmap, createOthers=True):
+ """
+ Set the bitmap to display normally.
+ This is the only one that is required. If
+ createOthers is True, then the other bitmaps
+ will be generated on the fly. Currently,
+ only the disabled bitmap is generated.
+ """
+ self.bmpLabel = bitmap
+ if bitmap is not None and createOthers:
+ image = wx.ImageFromBitmap(bitmap)
+ imageutils.grayOut(image)
+ self.SetBitmapDisabled(wx.BitmapFromImage(image))
+
+
+ def _GetLabelSize(self):
+ """ used internally """
+ if not self.bmpLabel:
+ return -1, -1, False
+ return self.bmpLabel.GetWidth()+2, self.bmpLabel.GetHeight()+2, False
+
+ def DrawLabel(self, dc, width, height, dx=0, dy=0):
+ bmp = self.bmpLabel
+ if self.bmpDisabled and not self.IsEnabled():
+ bmp = self.bmpDisabled
+ if self.bmpFocus and self.hasFocus:
+ bmp = self.bmpFocus
+ if self.bmpSelected and not self.up:
+ bmp = self.bmpSelected
+ bw,bh = bmp.GetWidth(), bmp.GetHeight()
+ if not self.up:
+ dx = dy = self.labelDelta
+ hasMask = bmp.GetMask() != None
+ dc.DrawBitmap(bmp, (width-bw)/2+dx, (height-bh)/2+dy, hasMask)
+
+
+#----------------------------------------------------------------------
+
+
+class GenBitmapTextButton(GenBitmapButton):
+ """A generic bitmapped button with text label"""
+ def __init__(self, parent, id=-1, bitmap=wx.NullBitmap, label='',
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = 0, validator = wx.DefaultValidator,
+ name = "genbutton"):
+ GenBitmapButton.__init__(self, parent, id, bitmap, pos, size, style, validator, name)
+ self.SetLabel(label)
+
+
+ def _GetLabelSize(self):
+ """ used internally """
+ w, h = self.GetTextExtent(self.GetLabel())
+ if not self.bmpLabel:
+ return w, h, True # if there isn't a bitmap use the size of the text
+
+ w_bmp = self.bmpLabel.GetWidth()+2
+ h_bmp = self.bmpLabel.GetHeight()+2
+ width = w + w_bmp
+ if h_bmp > h:
+ height = h_bmp
+ else:
+ height = h
+ return width, height, True
+
+
+ def DrawLabel(self, dc, width, height, dx=0, dy=0):
+ bmp = self.bmpLabel
+ if bmp is not None: # if the bitmap is used
+ if self.bmpDisabled and not self.IsEnabled():
+ bmp = self.bmpDisabled
+ if self.bmpFocus and self.hasFocus:
+ bmp = self.bmpFocus
+ if self.bmpSelected and not self.up:
+ bmp = self.bmpSelected
+ bw,bh = bmp.GetWidth(), bmp.GetHeight()
+ if not self.up:
+ dx = dy = self.labelDelta
+ hasMask = bmp.GetMask() is not None
+ else:
+ bw = bh = 0 # no bitmap -> size is zero
+
+ dc.SetFont(self.GetFont())
+ if self.IsEnabled():
+ dc.SetTextForeground(self.GetForegroundColour())
+ else:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+
+ label = self.GetLabel()
+ tw, th = dc.GetTextExtent(label) # size of text
+ if not self.up:
+ dx = dy = self.labelDelta
+
+ pos_x = (width-bw-tw)/2+dx # adjust for bitmap and text to centre
+ if bmp is not None:
+ dc.DrawBitmap(bmp, pos_x, (height-bh)/2+dy, hasMask) # draw bitmap if available
+ pos_x = pos_x + 2 # extra spacing from bitmap
+
+ dc.DrawText(label, pos_x + dx+bw, (height-th)/2+dy) # draw the text
+
+
+#----------------------------------------------------------------------
+
+
+class __ToggleMixin:
+ def SetToggle(self, flag):
+ self.up = not flag
+ self.Refresh()
+ SetValue = SetToggle
+
+ def GetToggle(self):
+ return not self.up
+ GetValue = GetToggle
+
+ def OnLeftDown(self, event):
+ if not self.IsEnabled():
+ return
+ self.saveUp = self.up
+ self.up = not self.up
+ self.CaptureMouse()
+ self.SetFocus()
+ self.Refresh()
+
+ def OnLeftUp(self, event):
+ if not self.IsEnabled() or not self.HasCapture():
+ return
+ if self.HasCapture():
+ self.ReleaseMouse()
+ self.Refresh()
+ if self.up != self.saveUp:
+ self.Notify()
+
+ def OnKeyDown(self, event):
+ event.Skip()
+
+ def OnMotion(self, event):
+ if not self.IsEnabled():
+ return
+ if event.LeftIsDown() and self.HasCapture():
+ x,y = event.GetPositionTuple()
+ w,h = self.GetClientSizeTuple()
+ if x<w and x>=0 and y<h and y>=0:
+ self.up = not self.saveUp
+ self.Refresh()
+ return
+ if (x<0 or y<0 or x>=w or y>=h):
+ self.up = self.saveUp
+ self.Refresh()
+ return
+ event.Skip()
+
+ def OnKeyUp(self, event):
+ if self.hasFocus and event.GetKeyCode() == ord(" "):
+ self.up = not self.up
+ self.Notify()
+ self.Refresh()
+ event.Skip()
+
+
+
+
+class GenToggleButton(__ToggleMixin, GenButton):
+ """A generic toggle button"""
+ pass
+
+class GenBitmapToggleButton(__ToggleMixin, GenBitmapButton):
+ """A generic toggle bitmap button"""
+ pass
+
+class GenBitmapTextToggleButton(__ToggleMixin, GenBitmapTextButton):
+ """A generic toggle bitmap button with text label"""
+ pass
+
+#----------------------------------------------------------------------
+
+
+class __ThemedMixin:
+ """ Use the native renderer to draw the bezel, also handle mouse-overs"""
+ def InitOtherEvents(self):
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouse)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouse)
+
+ def OnMouse(self, evt):
+ self.Refresh()
+ evt.Skip()
+
+ def DrawBezel(self, dc, x1, y1, x2, y2):
+ rect = wx.Rect(x1, y1, x2, y2)
+ if self.up:
+ state = 0
+ else:
+ state = wx.CONTROL_PRESSED | wx.CONTROL_SELECTED
+ if not self.IsEnabled():
+ state = wx.CONTROL_DISABLED
+ pt = self.ScreenToClient(wx.GetMousePosition())
+ if self.GetClientRect().Contains(pt):
+ state |= wx.CONTROL_CURRENT
+ wx.RendererNative.Get().DrawPushButton(self, dc, rect, state)
+
+
+
+class ThemedGenButton(__ThemedMixin, GenButton):
+ """A themed generic button"""
+ pass
+
+class ThemedGenBitmapButton(__ThemedMixin, GenBitmapButton):
+ """A themed generic bitmap button."""
+ pass
+
+class ThemedGenBitmapTextButton(__ThemedMixin, GenBitmapTextButton):
+ """A themed generic bitmapped button with text label"""
+ pass
+
+class ThemedGenToggleButton(__ThemedMixin, GenToggleButton):
+ """A themed generic toggle button"""
+ pass
+
+class ThemedGenBitmapToggleButton(__ThemedMixin, GenBitmapToggleButton):
+ """A themed generic toggle bitmap button"""
+ pass
+
+class ThemedGenBitmapTextToggleButton(__ThemedMixin, GenBitmapTextToggleButton):
+ """A themed generic toggle bitmap button with text label"""
+ pass
+
+
+#----------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/calendar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/calendar.py
new file mode 100644
index 0000000..80fdbd0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/calendar.py
@@ -0,0 +1,1236 @@
+#----------------------------------------------------------------------------
+# Name: calendar.py
+# Purpose: Calendar display control
+#
+# Author: Lorne White (email: lorne.white@telusplanet.net)
+#
+# Created:
+# Version 0.92
+# Date: Nov 26, 2001
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+# 12/01/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for wx namespace
+# o Tested with updated demo
+# o Added new event type EVT_CALENDAR. The reason for this is that the original
+# library used a hardcoded ID of 2100 for generating events. This makes it
+# very difficult to fathom when trying to decode the code since there's no
+# published API. Creating the new event binder might seem like overkill -
+# after all, you might ask, why not just use a new event ID and be done with
+# it? However, a consistent interface is very useful at times; also it makes
+# it clear that we're not just hunting for mouse clicks -- we're hunting
+# wabbit^H^H^H^H (sorry bout that) for calender-driven mouse clicks. So
+# that's my sad story. Shoot me if you must :-)
+# o There's still one deprecation warning buried in here somewhere, but I
+# haven't been able to find it yet. It only occurs when displaying a
+# print preview, and only the first time. It *could* be an error in the
+# demo, I suppose.
+#
+# Here's the traceback:
+#
+# C:\Python\lib\site-packages\wx\core.py:949: DeprecationWarning:
+# integer argument expected, got float
+# newobj = _core.new_Rect(*args, **kwargs)
+#
+# 12/17/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o A few style-guide nips and tucks
+# o Renamed wxCalendar to Calendar
+# o Couple of bugfixes
+#
+# 06/02/2004 - Joerg "Adi" Sieker adi@sieker.info
+#
+# o Changed color handling, use dictionary instead of members.
+# This causes all color changes to be ignored if they manipluate the members directly.
+# SetWeekColor and other method color methods were adapted to use the new dictionary.
+# o Added COLOR_* constants
+# o Added SetColor method for Calendar class
+# o Added 3D look of week header
+# o Added colors for 3D look of header
+# o Fixed width calculation.
+# Because of rounding difference the total width and height of the
+# calendar could be up to 6 pixels to small. The last column and row
+# are now wider/taller by the missing amount.
+# o Added SetTextAlign method to wxCalendar. This exposes logic
+# which was already there.
+# o Fixed CalDraw.SetMarg which set set_x_st and set_y_st which don't get used anywhere.
+# Instead set set_x_mrg and set_y_mrg
+# o Changed default X and Y Margin to 0.
+# o Added wxCalendar.SetMargin.
+#
+# 17/03/2004 - Joerg "Adi" Sieker adi@sieker.info
+# o Added keyboard navigation to the control.
+# Use the cursor keys to navigate through the ages. :)
+# The Home key function as go to today
+# o select day is now a filled rect instead of just an outline
+#
+# 15/04/2005 - Joe "shmengie" Brown joebrown@podiatryfl.com
+# o Adjusted spin control size/placement (On Windows ctrls were overlapping).
+# o Set Ok/Cancel buttons to wx.ID_OK & wx.ID_CANCEL to provide default dialog
+# behaviour.
+# o If no date has been clicked clicked, OnOk set the result to calend's date,
+# important if keyboard only navigation is used.
+#
+# 12/10/2006 - Walter Barnes walter_barnes05@yahoo.com
+# o Fixed CalDraw to properly render months that start on a Sunday.
+#
+# 21/10/2006 - Walter Barnes walter_barnes05@yahoo.com
+# o Fixed a bug in Calendar: Shift and Control key status was only recorded for
+# left-down events.
+# o Added handlers for wxEVT_MIDDLE_DOWN and wxEVT_MIDDLE_DCLICK to generate
+# EVT_CALENDAR for these mouse events.
+
+
+import wx
+
+from CDate import *
+
+CalDays = [6, 0, 1, 2, 3, 4, 5]
+AbrWeekday = {6:"Sun", 0:"Mon", 1:"Tue", 2:"Wed", 3:"Thu", 4:"Fri", 5:"Sat"}
+_MIDSIZE = 180
+
+COLOR_GRID_LINES = "grid_lines"
+COLOR_BACKGROUND = "background"
+COLOR_SELECTION_FONT = "selection_font"
+COLOR_SELECTION_BACKGROUND = "selection_background"
+COLOR_BORDER = "border"
+COLOR_HEADER_BACKGROUND = "header_background"
+COLOR_HEADER_FONT = "header_font"
+COLOR_WEEKEND_BACKGROUND = "weekend_background"
+COLOR_WEEKEND_FONT = "weekend_font"
+COLOR_FONT = "font"
+COLOR_3D_LIGHT = "3d_light"
+COLOR_3D_DARK = "3d_dark"
+COLOR_HIGHLIGHT_FONT = "highlight_font"
+COLOR_HIGHLIGHT_BACKGROUND = "highlight_background"
+
+BusCalDays = [0, 1, 2, 3, 4, 5, 6]
+
+# Calendar click event - added 12/1/03 by jmg (see above)
+wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED = wx.NewEventType()
+EVT_CALENDAR = wx.PyEventBinder(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED, 1)
+
+def GetMonthList():
+ monthlist = []
+ for i in range(13):
+ name = Month[i]
+ if name != None:
+ monthlist.append(name)
+ return monthlist
+
+def MakeColor(in_color):
+ try:
+ color = wxNamedColour(in_color)
+ except:
+ color = in_color
+ return color
+
+def DefaultColors():
+ colors = {}
+ colors[COLOR_GRID_LINES] = 'BLACK'
+ colors[COLOR_BACKGROUND] = 'WHITE'
+ colors[COLOR_SELECTION_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ colors[COLOR_SELECTION_BACKGROUND] =wx.Colour(255,255,225)
+ colors[COLOR_BORDER] = 'BLACK'
+ colors[COLOR_HEADER_BACKGROUND] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+ colors[COLOR_HEADER_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ colors[COLOR_WEEKEND_BACKGROUND] = 'LIGHT GREY'
+ colors[COLOR_WEEKEND_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ colors[COLOR_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ colors[COLOR_3D_LIGHT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNHIGHLIGHT)
+ colors[COLOR_3D_DARK] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+ colors[COLOR_HIGHLIGHT_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
+ colors[COLOR_HIGHLIGHT_BACKGROUND] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ return colors
+# calendar drawing routing
+
+class CalDraw:
+ def __init__(self, parent):
+ self.pwidth = 1
+ self.pheight = 1
+ try:
+ self.scale = parent.scale
+ except:
+ self.scale = 1
+
+ self.gridx = []
+ self.gridy = []
+
+ self.DefParms()
+
+ def DefParms(self):
+ self.num_auto = True # auto scale of the cal number day size
+ self.num_size = 12 # default size of calendar if no auto size
+ self.max_num_size = 12 # maximum size for calendar number
+
+ self.num_align_horz = wx.ALIGN_CENTRE # alignment of numbers
+ self.num_align_vert = wx.ALIGN_CENTRE
+ self.num_indent_horz = 0 # points indent from position, used to offset if not centered
+ self.num_indent_vert = 0
+
+ self.week_auto = True # auto scale of week font text
+ self.week_size = 10
+ self.max_week_size = 12
+
+ self.colors = DefaultColors()
+
+ self.font = wx.SWISS
+ self.bold = wx.NORMAL
+
+ self.hide_title = False
+ self.hide_grid = False
+ self.outer_border = True
+
+ self.title_offset = 0
+ self.cal_week_scale = 0.7
+ self.show_weekend = False
+ self.cal_type = "NORMAL"
+
+ def SetWeekColor(self, font_color, week_color):
+ # set font and background color for week title
+ self.colors[COLOR_HEADER_FONT] = MakeColor(font_color)
+ self.colors[COLOR_HEADER_BACKGROUND] = MakeColor(week_color)
+ self.colors[COLOR_3D_LIGHT] = MakeColor(week_color)
+ self.colors[COLOR_3D_DARK] = MakeColor(week_color)
+
+ def SetSize(self, size):
+ self.set_sizew = size[0]
+ self.set_sizeh = size[1]
+
+ def InitValues(self): # default dimensions of various elements of the calendar
+ self.rg = {}
+ self.cal_sel = {}
+ self.set_cy_st = 0 # start position
+ self.set_cx_st = 0
+
+ self.set_y_mrg = 1 # start of vertical draw default
+ self.set_x_mrg = 1
+ self.set_y_end = 1
+ def SetPos(self, xpos, ypos):
+ self.set_cx_st = xpos
+ self.set_cy_st = ypos
+
+ def SetMarg(self, xmarg, ymarg):
+ self.set_x_mrg = xmarg
+ self.set_y_mrg = ymarg
+ self.set_y_end = ymarg
+
+ def InitScale(self): # scale position values
+ self.sizew = int(self.set_sizew * self.pwidth)
+ self.sizeh = int(self.set_sizeh * self.pheight)
+
+ self.cx_st = int(self.set_cx_st * self.pwidth) # draw start position
+ self.cy_st = int(self.set_cy_st * self.pheight)
+
+ self.x_mrg = int(self.set_x_mrg * self.pwidth) # calendar draw margins
+ self.y_mrg = int(self.set_y_mrg * self.pheight)
+ self.y_end = int(self.set_y_end * self.pheight)
+
+ def DrawCal(self, DC, sel_lst=[]):
+ self.InitScale()
+
+ self.DrawBorder(DC)
+
+ if self.hide_title is False:
+ self.DrawMonth(DC)
+
+ self.Center()
+
+ self.DrawGrid(DC)
+ self.GetRect()
+ if self.show_weekend is True: # highlight weekend dates
+ self.SetWeekEnd()
+
+ self.AddSelect(sel_lst) # overrides the weekend highlight
+
+ self.DrawSel(DC) # highlighted days
+ self.DrawWeek(DC)
+ self.DrawNum(DC)
+
+ def AddSelect(self, list, cfont=None, cbackgrd = None):
+ if cfont is None:
+ cfont = self.colors[COLOR_SELECTION_FONT] # font digit color
+ if cbackgrd is None:
+ cbackgrd = self.colors[COLOR_SELECTION_BACKGROUND] # select background color
+
+ for val in list:
+ self.cal_sel[val] = (cfont, cbackgrd)
+
+ # draw border around the outside of the main display rectangle
+ def DrawBorder(self, DC, transparent = False):
+ if self.outer_border is True:
+ if transparent == False:
+ brush = wx.Brush(MakeColor(self.colors[COLOR_BACKGROUND]), wx.SOLID)
+ else:
+ brush = wx.TRANSPARENT_BRUSH
+ DC.SetBrush(brush)
+ DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_BORDER])))
+ # full display window area
+ rect = wx.Rect(self.cx_st, self.cy_st, self.sizew, self.sizeh)
+ DC.DrawRectangleRect(rect)
+
+ def DrawFocusIndicator(self, DC):
+ if self.outer_border is True:
+ DC.SetBrush(wx.TRANSPARENT_BRUSH)
+ DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_HIGHLIGHT_BACKGROUND]), style=wx.DOT))
+ # full display window area
+ rect = wx.Rect(self.cx_st, self.cy_st, self.sizew, self.sizeh)
+ DC.DrawRectangleRect(rect)
+
+ def DrawNumVal(self):
+ self.DrawNum()
+
+ # calculate the calendar days and offset position
+ def SetCal(self, year, month):
+ self.InitValues() # reset initial values
+
+ self.year = year
+ self.month = month
+
+ day = 1
+ t = Date(year, month, day)
+ dow = self.dow = t.day_of_week # start day in month
+ dim = self.dim = t.days_in_month # number of days in month
+
+ if self.cal_type == "NORMAL":
+ start_pos = dow+1
+ else:
+ start_pos = dow
+
+ if start_pos > 6:
+ start_pos = 0
+
+ self.st_pos = start_pos
+
+ self.cal_days = []
+ for i in range(start_pos):
+ self.cal_days.append('')
+
+ i = 1
+ while i <= dim:
+ self.cal_days.append(str(i))
+ i = i + 1
+
+ self.end_pos = start_pos + dim - 1
+
+ return start_pos
+
+ def SetWeekEnd(self, font_color=None, backgrd = None):
+ if font_color != None:
+ self.SetColor(COLOR_WEEKEND_FONT, MakeColor(font_color))
+ if backgrd != None:
+ self.SetColor(COLOR_WEEKEND_BACKGROUND, MakeColor(backgrd))
+
+ date = 6 - int(self.dow) # start day of first saturday
+ if date == 0: #...unless we start on Sunday
+ self.cal_sel[1] = (self.GetColor(COLOR_WEEKEND_FONT), self.GetColor(COLOR_WEEKEND_BACKGROUND))
+ date = 7
+
+ while date <= self.dim:
+ self.cal_sel[date] = (self.GetColor(COLOR_WEEKEND_FONT), self.GetColor(COLOR_WEEKEND_BACKGROUND)) # Saturday
+ date = date + 1
+
+ if date <= self.dim:
+ self.cal_sel[date] = (self.GetColor(COLOR_WEEKEND_FONT), self.GetColor(COLOR_WEEKEND_BACKGROUND)) # Sunday
+ date = date + 6
+ else:
+ date = date + 7
+
+ # get the display rectange list of the day grid
+ def GetRect(self):
+ cnt = 0
+ h = 0
+ w = 0
+ for y in self.gridy[1:-1]:
+ if y == self.gridy[-2]:
+ h = h + self.restH
+
+ for x in self.gridx[:-1]:
+ assert type(y) == int
+ assert type(x) == int
+
+ w = self.cellW
+ h = self.cellH
+
+ if x == self.gridx[-2]:
+ w = w + self.restW
+
+ rect = wx.Rect(x, y, w+1, h+1) # create rect region
+
+ self.rg[cnt] = rect
+ cnt = cnt + 1
+
+ return self.rg
+
+ def GetCal(self):
+ return self.cal_days
+
+ def GetOffset(self):
+ return self.st_pos
+
+ # month and year title
+ def DrawMonth(self, DC):
+ month = Month[self.month]
+
+ sizef = 11
+ if self.sizeh < _MIDSIZE:
+ sizef = 10
+
+ f = wx.Font(sizef, self.font, wx.NORMAL, self.bold)
+ DC.SetFont(f)
+
+ tw,th = DC.GetTextExtent(month)
+ adjust = self.cx_st + (self.sizew-tw)/2
+ DC.DrawText(month, adjust, self.cy_st + th)
+
+ year = str(self.year)
+ tw,th = DC.GetTextExtent(year)
+ adjust = self.sizew - tw - self.x_mrg
+
+ self.title_offset = th * 2
+
+ f = wx.Font(sizef, self.font, wx.NORMAL, self.bold)
+ DC.SetFont(f)
+ DC.DrawText(year, self.cx_st + adjust, self.cy_st + th)
+
+ def DrawWeek(self, DC): # draw the week days
+ # increase by 1 to include all gridlines
+ width = self.gridx[1] - self.gridx[0] + 1
+ height = self.gridy[1] - self.gridy[0] + 1
+ rect_w = self.gridx[-1] - self.gridx[0]
+
+ f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting
+
+ if self.week_auto == True:
+ test_size = self.max_week_size # max size
+ test_day = ' Sun '
+ while test_size > 2:
+ f.SetPointSize(test_size)
+ DC.SetFont(f)
+ tw,th = DC.GetTextExtent(test_day)
+
+ if tw < width and th < height:
+ break
+
+ test_size = test_size - 1
+ else:
+ f.SetPointSize(self.week_size) # set fixed size
+ DC.SetFont(f)
+
+ DC.SetTextForeground(MakeColor(self.colors[COLOR_HEADER_FONT]))
+
+ cnt_x = 0
+ cnt_y = 0
+
+ brush = wx.Brush(MakeColor(self.colors[COLOR_HEADER_BACKGROUND]), wx.SOLID)
+ DC.SetBrush(brush)
+
+ if self.cal_type == "NORMAL":
+ cal_days = CalDays
+ else:
+ cal_days = BusCalDays
+
+ for val in cal_days:
+ if val == cal_days[-1]:
+ width = width + self.restW
+
+ day = AbrWeekday[val]
+
+ if self.sizew < 200:
+ day = day[0]
+
+ dw,dh = DC.GetTextExtent(day)
+
+ diffx = (width-dw)/2
+ diffy = (height-dh)/2
+
+ x = self.gridx[cnt_x]
+ y = self.gridy[cnt_y]
+ pointXY = (x, y)
+ pointWH = (width, height)
+ if self.hide_grid == False:
+ pen = wx.Pen(MakeColor(self.GetColor(COLOR_GRID_LINES)), 1, wx.SOLID)
+ else:
+ pen = wx.Pen(MakeColor(self.GetColor(COLOR_BACKGROUND)), 1, wx.SOLID)
+ DC.SetPen(pen)
+ DC.DrawRectanglePointSize( pointXY, pointWH)
+
+ old_pen = DC.GetPen()
+
+ pen = wx.Pen(MakeColor(self.colors[COLOR_3D_LIGHT]), 1, wx.SOLID)
+ DC.SetPen(pen)
+ # draw the horizontal hilight
+ startPoint = wx.Point(x + 1 , y + 1)
+ endPoint = wx.Point(x + width - 1, y + 1)
+ DC.DrawLinePoint(startPoint, endPoint )
+
+ # draw the vertical hilight
+ startPoint = wx.Point(x + 1 , y + 1)
+ endPoint = wx.Point(x + 1, y + height - 2)
+ DC.DrawLinePoint(startPoint, endPoint )
+
+ pen = wx.Pen(MakeColor(self.colors[COLOR_3D_DARK]), 1, wx.SOLID)
+ DC.SetPen(pen)
+
+ # draw the horizontal lowlight
+ startPoint = wx.Point(x + 1, y + height - 2)
+ endPoint = wx.Point(x + width - 1, y + height - 2)
+ DC.DrawLinePoint(startPoint, endPoint )
+
+ # draw the vertical lowlight
+ startPoint = wx.Point(x + width - 2 , y + 2)
+ endPoint = wx.Point(x + width - 2, y + height - 2)
+ DC.DrawLinePoint(startPoint, endPoint )
+
+ pen = wx.Pen(MakeColor(self.colors[COLOR_FONT]), 1, wx.SOLID)
+
+ DC.SetPen(pen)
+
+ point = (x+diffx, y+diffy)
+ DC.DrawTextPoint(day, point)
+ cnt_x = cnt_x + 1
+
+ def _CalcFontSize(self, DC, f):
+ if self.num_auto == True:
+ test_size = self.max_num_size # max size
+ test_day = ' 99 '
+
+ while test_size > 2:
+ f.SetPointSize(test_size)
+ DC.SetFont(f)
+ tw,th = DC.GetTextExtent(test_day)
+
+ if tw < self.cellW and th < self.cellH:
+ sizef = test_size
+ break
+ test_size = test_size - 1
+ else:
+ f.SetPointSize(self.num_size) # set fixed size
+ DC.SetFont(f)
+
+ # draw the day numbers
+ def DrawNum(self, DC):
+ f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting
+ self._CalcFontSize(DC, f)
+
+ cnt_x = 0
+ cnt_y = 1
+ for val in self.cal_days:
+ x = self.gridx[cnt_x]
+ y = self.gridy[cnt_y]
+
+ self._DrawDayText(x, y, val, f, DC)
+
+ if cnt_x < 6:
+ cnt_x = cnt_x + 1
+ else:
+ cnt_x = 0
+ cnt_y = cnt_y + 1
+
+ def _DrawDayText(self, x, y, text, font, DC):
+
+ try:
+ num_val = int(text)
+ num_color = self.cal_sel[num_val][0]
+ except:
+ num_color = self.colors[COLOR_FONT]
+
+ DC.SetTextForeground(MakeColor(num_color))
+ DC.SetFont(font)
+
+ tw,th = DC.GetTextExtent(text)
+
+ if self.num_align_horz == wx.ALIGN_CENTRE:
+ adj_h = (self.cellW - tw)/2
+ elif self.num_align_horz == wx.ALIGN_RIGHT:
+ adj_h = self.cellW - tw
+ else:
+ adj_h = 0 # left alignment
+
+ adj_h = adj_h + self.num_indent_horz
+
+ if self.num_align_vert == wx.ALIGN_CENTRE:
+ adj_v = (self.cellH - th)/2
+ elif self.num_align_vert == wx.ALIGN_BOTTOM:
+ adj_v = self.cellH - th
+ else:
+ adj_v = 0 # left alignment
+
+ adj_v = adj_v + self.num_indent_vert
+
+ DC.DrawTextPoint(text, (x+adj_h, y+adj_v))
+
+ def DrawDayText(self, DC, key):
+ f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting
+ self._CalcFontSize(DC, f)
+
+ if key > self.end_pos:
+ key = self.end_pos
+
+ val = self.cal_days[key]
+ cnt_x = key % 7
+ cnt_y = int(key / 7)+1
+ x = self.gridx[cnt_x]
+ y = self.gridy[cnt_y]
+ self._DrawDayText(x, y, val, f, DC)
+
+
+ # calculate the dimensions in the center of the drawing area
+ def Center(self):
+ borderW = self.x_mrg * 2
+ borderH = self.y_mrg + self.y_end + self.title_offset
+
+ self.cellW = int((self.sizew - borderW)/7)
+ self.cellH = int((self.sizeh - borderH)/7)
+
+ self.restW = ((self.sizew - borderW)%7 ) - 1
+
+ # week title adjustment
+ self.weekHdrCellH = int(self.cellH * self.cal_week_scale)
+ # recalculate the cell height exkl. the week header and
+ # subtracting the size
+ self.cellH = int((self.sizeh - borderH - self.weekHdrCellH)/6)
+
+ self.restH = ((self.sizeh - borderH - self.weekHdrCellH)%6 ) - 1
+ self.calW = self.cellW * 7
+ self.calH = self.cellH * 6 + self.weekHdrCellH
+
+ # highlighted selected days
+ def DrawSel(self, DC):
+
+ for key in self.cal_sel.keys():
+ sel_color = self.cal_sel[key][1]
+ brush = wx.Brush(MakeColor(sel_color), wx.SOLID)
+ DC.SetBrush(brush)
+
+ if self.hide_grid is False:
+ DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_GRID_LINES]), 0))
+ else:
+ DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_BACKGROUND]), 0))
+
+ nkey = key + self.st_pos -1
+ rect = self.rg[nkey]
+
+ DC.DrawRectangleRect(rect)
+
+ # calculate and draw the grid lines
+ def DrawGrid(self, DC):
+ DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_GRID_LINES]), 0))
+
+ self.gridx = []
+ self.gridy = []
+
+ self.x_st = self.cx_st + self.x_mrg
+ # start postion of draw
+ self.y_st = self.cy_st + self.y_mrg + self.title_offset
+
+ x1 = self.x_st
+ y1 = self.y_st
+ y2 = y1 + self.calH + self.restH
+
+ for i in range(8):
+ if i == 7:
+ x1 = x1 + self.restW
+
+ if self.hide_grid is False:
+ DC.DrawLinePoint((x1, y1), (x1, y2))
+
+ self.gridx.append(x1)
+
+ x1 = x1 + self.cellW
+
+ x1 = self.x_st
+ y1 = self.y_st
+ x2 = x1 + self.calW + self.restW
+
+ for i in range(8):
+ if i == 7:
+ y1 = y1 + self.restH
+
+ if self.hide_grid is False:
+ DC.DrawLinePoint((x1, y1), (x2, y1))
+
+ self.gridy.append(y1)
+
+ if i == 0:
+ y1 = y1 + self.weekHdrCellH
+ else:
+ y1 = y1 + self.cellH
+
+ def GetColor(self, name):
+ return MakeColor(self.colors[name])
+
+ def SetColor(self, name, value):
+ self.colors[name] = MakeColor(value)
+
+
+class PrtCalDraw(CalDraw):
+ def InitValues(self):
+ self.rg = {}
+ self.cal_sel = {}
+ # start draw border location
+ self.set_cx_st = 1.0
+ self.set_cy_st = 1.0
+
+ # draw offset position
+ self.set_y_mrg = 0.2
+ self.set_x_mrg = 0.2
+ self.set_y_end = 0.2
+
+ # calculate the dimensions in the center of the drawing area
+ def SetPSize(self, pwidth, pheight):
+ self.pwidth = int(pwidth)/self.scale
+ self.pheight = int(pheight)/self.scale
+
+ def SetPreview(self, preview):
+ self.preview = preview
+
+
+
+class Calendar( wx.PyControl ):
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.Size(200,200),
+ style= 0, validator=wx.DefaultValidator,
+ name= "calendar"):
+ wx.PyControl.__init__(self, parent, id, pos, size, style | wx.WANTS_CHARS, validator, name)
+
+ self.hasFocus = False
+ # set the calendar control attributes
+
+ self.hide_grid = False
+ self.hide_title = False
+ self.show_weekend = False
+ self.cal_type = "NORMAL"
+ self.outer_border = True
+ self.num_align_horz = wx.ALIGN_CENTRE
+ self.num_align_vert = wx.ALIGN_CENTRE
+ self.colors = DefaultColors()
+ self.set_x_mrg = 1
+ self.set_y_mrg = 1
+ self.set_y_end = 1
+
+ self.select_list = []
+
+ self.SetBackgroundColour(MakeColor(self.colors[COLOR_BACKGROUND]))
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftEvent)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDEvent)
+ self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightEvent)
+ self.Bind(wx.EVT_RIGHT_DCLICK, self.OnRightDEvent)
+ self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleEvent)
+ self.Bind(wx.EVT_MIDDLE_DCLICK, self.OnMiddleDEvent)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+
+ self.sel_key = None # last used by
+ self.sel_lst = [] # highlighted selected days
+
+ # default calendar for current month
+ self.SetNow()
+
+ self.size = None
+ self.set_day = None
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ def AcceptsFocus(self):
+ return self.IsShown() and self.IsEnabled()
+
+ def GetColor(self, name):
+ return MakeColor(self.colors[name])
+
+ def SetColor(self, name, value):
+ self.colors[name] = MakeColor(value)
+
+ # control some of the main calendar attributes
+
+ def HideTitle(self):
+ self.hide_title = True
+
+ def HideGrid(self):
+ self.hide_grid = True
+
+ # determine the calendar rectangle click area and draw a selection
+
+ def ProcessClick(self, event):
+ self.SetFocus()
+ self.x, self.y = event.GetX(), event.GetY()
+ self.shiftkey = event.ShiftDown()
+ self.ctrlkey = event.ControlDown()
+ key = self.GetDayHit(self.x, self.y)
+ self.SelectDay(key)
+
+ # tab mouse click events and process
+
+ def OnLeftEvent(self, event):
+ self.click = 'LEFT'
+ self.ProcessClick(event)
+
+ def OnLeftDEvent(self, event):
+ self.click = 'DLEFT'
+ self.ProcessClick(event)
+
+ def OnRightEvent(self, event):
+ self.click = 'RIGHT'
+ self.ProcessClick(event)
+
+ def OnRightDEvent(self, event):
+ self.click = 'DRIGHT'
+ self.ProcessClick(event)
+
+ def OnMiddleEvent(self, event):
+ self.click = 'MIDDLE'
+ self.ProcessClick(event)
+
+ def OnMiddleDEvent(self, event):
+ self.click = 'DMIDDLE'
+ self.ProcessClick(event)
+
+ def OnSetFocus(self, event):
+ self.hasFocus = True
+ self.DrawFocusIndicator(True)
+
+ def OnKillFocus(self, event):
+ self.hasFocus = False
+ self.DrawFocusIndicator(False)
+
+ def OnKeyDown(self, event):
+ if not self.hasFocus:
+ event.Skip()
+ return
+
+ key_code = event.GetKeyCode()
+
+ if key_code == wx.WXK_TAB:
+ forward = not event.ShiftDown()
+ ne = wx.NavigationKeyEvent()
+ ne.SetDirection(forward)
+ ne.SetCurrentFocus(self)
+ ne.SetEventObject(self)
+ self.GetParent().GetEventHandler().ProcessEvent(ne)
+ event.Skip()
+ return
+
+ delta = None
+
+ if key_code == wx.WXK_UP:
+ delta = -7
+ elif key_code == wx.WXK_DOWN:
+ delta = 7
+ elif key_code == wx.WXK_LEFT:
+ delta = -1
+ elif key_code == wx.WXK_RIGHT:
+ delta = 1
+ elif key_code == wx.WXK_HOME:
+ curDate = wx.DateTimeFromDMY(int(self.cal_days[self.sel_key]),self.month - 1,self.year)
+ newDate = wx.DateTime_Now()
+ ts = newDate - curDate
+ delta = ts.GetDays()
+
+ if delta <> None:
+ curDate = wx.DateTimeFromDMY(int(self.cal_days[self.sel_key]),self.month - 1,self.year)
+ timeSpan = wx.TimeSpan_Days(delta)
+ newDate = curDate + timeSpan
+
+ if curDate.GetMonth() == newDate.GetMonth():
+ self.set_day = newDate.GetDay()
+ key = self.sel_key + delta
+ self.SelectDay(key)
+ else:
+ self.month = newDate.GetMonth() + 1
+ self.year = newDate.GetYear()
+ self.set_day = newDate.GetDay()
+ self.sel_key = None
+ self.DoDrawing(wx.ClientDC(self))
+
+ event.Skip()
+
+ def SetSize(self, set_size):
+ self.size = set_size
+
+ def SetSelDay(self, sel):
+ # list of highlighted days
+ self.sel_lst = sel
+
+ # get the current date
+ def SetNow(self):
+ dt = now()
+ self.month = dt.month
+ self.year = dt.year
+ self.day = dt.day
+
+ # set the current day
+ def SetCurrentDay(self):
+ self.SetNow()
+ self.set_day = self.day
+
+ # get the date, day, month, year set in calendar
+
+ def GetDate(self):
+ return self.day, self.month, self.year
+
+ def GetDay(self):
+ return self.day
+
+ def GetMonth(self):
+ return self.month
+
+ def GetYear(self):
+ return self.year
+
+ # set the day, month, and year
+
+ def SetDayValue(self, day):
+ self.set_day = day
+ self.day = day
+
+ def SetMonth(self, month):
+ if month >= 1 and month <= 12:
+ self.month = month
+ else:
+ self.month = 1
+ self.set_day = None
+
+ def SetYear(self, year):
+ self.year = year
+
+ # increment year and month
+
+ def IncYear(self):
+ self.year = self.year + 1
+ self.set_day = None
+
+ def DecYear(self):
+ self.year = self.year - 1
+ self.set_day = None
+
+ def IncMonth(self):
+ self.month = self.month + 1
+ if self.month > 12:
+ self.month = 1
+ self.year = self.year + 1
+ self.set_day = None
+
+ def DecMonth(self):
+ self.month = self.month - 1
+ if self.month < 1:
+ self.month = 12
+ self.year = self.year - 1
+ self.set_day = None
+
+ # test to see if the selection has a date and create event
+
+ def TestDay(self, key):
+ try:
+ self.day = int(self.cal_days[key])
+ except:
+ return None
+
+ if self.day == "":
+ return None
+ else:
+ # Changed 12/1/03 by jmg (see above) to support 2.5 event binding
+ evt = wx.PyCommandEvent(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED, self.GetId())
+ evt.click, evt.day, evt.month, evt.year = self.click, self.day, self.month, self.year
+ evt.shiftkey = self.shiftkey
+ evt.ctrlkey = self.ctrlkey
+ self.GetEventHandler().ProcessEvent(evt)
+
+ self.set_day = self.day
+ return key
+
+ # find the clicked area rectangle
+
+ def GetDayHit(self, mx, my):
+ for key in self.rg.keys():
+ val = self.rg[key]
+ ms_rect = wx.Rect(mx, my, 1, 1)
+ if wx.IntersectRect(ms_rect, val) is not None:
+ result = self.TestDay(key)
+ return result
+
+ return None
+
+ # calendar drawing
+
+ def SetWeekColor(self, font_color, week_color):
+ # set font and background color for week title
+ self.colors[COLOR_HEADER_FONT] = MakeColor(font_color)
+ self.colors[COLOR_HEADER_BACKGROUND] = MakeColor(week_color)
+ self.colors[COLOR_3D_LIGHT] = MakeColor(week_color)
+ self.colors[COLOR_3D_DARK] = MakeColor(week_color)
+
+ def SetTextAlign(self, vert, horz):
+ self.num_align_horz = horz
+ self.num_align_vert = vert
+
+ def AddSelect(self, list, font_color, back_color):
+ list_val = [list, font_color, back_color]
+ self.select_list.append(list_val)
+
+ def ShowWeekEnd(self):
+ # highlight weekend
+ self.show_weekend = True
+
+ def SetBusType(self):
+ self.cal_type = "BUS"
+
+ def OnSize(self, evt):
+ self.Refresh(False)
+ evt.Skip()
+
+ def OnPaint(self, event):
+ DC = wx.PaintDC(self)
+ self.DoDrawing(DC)
+
+ def DoDrawing(self, DC):
+ #DC = wx.PaintDC(self)
+ DC.BeginDrawing()
+
+ try:
+ cal = self.caldraw
+ except:
+ self.caldraw = CalDraw(self)
+ cal = self.caldraw
+
+ cal.hide_grid = self.hide_grid
+ cal.hide_title = self.hide_title
+ cal.show_weekend = self.show_weekend
+ cal.cal_type = self.cal_type
+ cal.outer_border = self.outer_border
+ cal.num_align_horz = self.num_align_horz
+ cal.num_align_vert = self.num_align_vert
+ cal.colors = self.colors
+
+ if self.size is None:
+ size = self.GetClientSize()
+ else:
+ size = self.size
+
+ # drawing attributes
+
+ cal.SetSize(size)
+ cal.SetCal(self.year, self.month)
+
+ # these have to set after SetCal as SetCal would overwrite them again.
+ cal.set_x_mrg = self.set_x_mrg
+ cal.set_y_mrg = self.set_y_mrg
+ cal.set_y_end = self.set_y_end
+
+ for val in self.select_list:
+ cal.AddSelect(val[0], val[1], val[2])
+
+ cal.DrawCal(DC, self.sel_lst)
+
+ self.rg = cal.GetRect()
+ self.cal_days = cal.GetCal()
+ self.st_pos = cal.GetOffset()
+ self.ymax = DC.MaxY()
+
+ if self.set_day != None:
+ self.SetDay(self.set_day)
+
+ DC.EndDrawing()
+
+ # draw the selection rectangle
+ def DrawFocusIndicator(self, draw):
+ DC = wx.ClientDC(self)
+ try:
+ if draw == True:
+ self.caldraw.DrawFocusIndicator(DC)
+ else:
+ self.caldraw.DrawBorder(DC,True)
+ except:
+ pass
+
+ def DrawRect(self, key, bgcolor = 'WHITE', fgcolor= 'PINK',width = 0):
+ if key == None:
+ return
+
+ DC = wx.ClientDC(self)
+ DC.BeginDrawing()
+
+ brush = wx.Brush(MakeColor(bgcolor))
+ DC.SetBrush(brush)
+
+ DC.SetPen(wx.TRANSPARENT_PEN)
+
+ rect = self.rg[key]
+ DC.DrawRectangle(rect.x+1, rect.y+1, rect.width-2, rect.height-2)
+
+ self.caldraw.DrawDayText(DC,key)
+
+ DC.EndDrawing()
+
+ def DrawRectOrg(self, key, fgcolor = 'BLACK', width = 0):
+ if key == None:
+ return
+
+ DC = wx.ClientDC(self)
+ DC.BeginDrawing()
+
+ brush = wx.Brush(wx.Colour(0, 0xFF, 0x80), wx.TRANSPARENT)
+ DC.SetBrush(brush)
+
+ try:
+ DC.SetPen(wx.Pen(MakeColor(fgcolor), width))
+ except:
+ DC.SetPen(wx.Pen(MakeColor(self.GetColor(COLOR_GRID_LINES)), width))
+
+ rect = self.rg[key]
+ DC.DrawRectangleRect(rect)
+
+ DC.EndDrawing()
+
+ # set the day selection
+
+ def SetDay(self, day):
+ d = day + self.st_pos - 1
+ self.SelectDay(d)
+
+ def IsDayInWeekend(self, key):
+ try:
+ t = Date(self.year, self.month, 1)
+
+ day = self.cal_days[key]
+ day = int(day) + t.day_of_week
+
+ if day % 7 == 6 or day % 7 == 0:
+ return True
+ except:
+ return False
+
+ def SelectDay(self, key):
+ sel_size = 1
+ # clear large selection
+
+ if self.sel_key != None:
+ (cfont, bgcolor) = self.__GetColorsForDay(self.sel_key)
+ self.DrawRect(self.sel_key, bgcolor,cfont, sel_size)
+
+ self.DrawRect(key, self.GetColor(COLOR_HIGHLIGHT_BACKGROUND), self.GetColor(COLOR_HIGHLIGHT_FONT), sel_size)
+ # store last used by
+ self.sel_key = key
+
+ def SetMargin(self, xmarg, ymarg):
+ self.set_x_mrg = xmarg
+ self.set_y_mrg = ymarg
+ self.set_y_end = ymarg
+ def __GetColorsForDay(self, key):
+ cfont = self.GetColor(COLOR_FONT)
+ bgcolor = self.GetColor(COLOR_BACKGROUND)
+
+ if self.IsDayInWeekend(key) is True and self.show_weekend is True:
+ cfont = self.GetColor(COLOR_WEEKEND_FONT)
+ bgcolor = self.GetColor(COLOR_WEEKEND_BACKGROUND)
+
+ try:
+ dayIdx = int(self.cal_days[key])
+ (cfont, bgcolor) = self.caldraw.cal_sel[dayIdx]
+ except:
+ pass
+
+ return (cfont, bgcolor)
+
+class CalenDlg(wx.Dialog):
+ def __init__(self, parent, month=None, day = None, year=None):
+ wx.Dialog.__init__(self, parent, -1, "Event Calendar", wx.DefaultPosition, (280, 360))
+ self.result = None
+
+ # set the calendar and attributes
+ self.calend = Calendar(self, -1, (20, 60), (240, 200))
+
+ if month == None:
+ self.calend.SetCurrentDay()
+ start_month = self.calend.GetMonth()
+ start_year = self.calend.GetYear()
+ else:
+ self.calend.month = start_month = month
+ self.calend.year = start_year = year
+ self.calend.SetDayValue(day)
+
+ self.calend.HideTitle()
+ self.ResetDisplay()
+
+ # get month list from DateTime
+ monthlist = GetMonthList()
+
+ # select the month
+ self.date = wx.ComboBox(self, -1, Month[start_month], (20, 20), (90, -1),
+ monthlist, wx.CB_DROPDOWN)
+ self.Bind(wx.EVT_COMBOBOX, self.EvtComboBox, self.date)
+
+ # alternate spin button to control the month
+ h = self.date.GetSize().height
+ self.m_spin = wx.SpinButton(self, -1, (115, 20), (h*1.5, h), wx.SP_VERTICAL)
+ self.m_spin.SetRange(1, 12)
+ self.m_spin.SetValue(start_month)
+ self.Bind(wx.EVT_SPIN, self.OnMonthSpin, self.m_spin)
+
+ # spin button to control the year
+ self.dtext = wx.TextCtrl(self, -1, str(start_year), (160, 20), (60, -1))
+ h = self.dtext.GetSize().height
+
+ self.y_spin = wx.SpinButton(self, -1, (225, 20), (h*1.5, h), wx.SP_VERTICAL)
+ self.y_spin.SetRange(1980, 2010)
+ self.y_spin.SetValue(start_year)
+
+ self.Bind(wx.EVT_SPIN, self.OnYrSpin, self.y_spin)
+ self.Bind(EVT_CALENDAR, self.MouseClick, self.calend)
+
+ x_pos = 50
+ y_pos = 280
+ but_size = (60, 25)
+
+ btn = wx.Button(self, wx.ID_OK, ' Ok ', (x_pos, y_pos), but_size)
+ self.Bind(wx.EVT_BUTTON, self.OnOk, btn)
+
+ btn = wx.Button(self, wx.ID_CANCEL, ' Close ', (x_pos + 120, y_pos), but_size)
+ self.Bind(wx.EVT_BUTTON, self.OnCancel, btn)
+
+ def OnOk(self, evt):
+ self.result = ['None', str(self.calend.day), Month[self.calend.month], str(self.calend.year)]
+ self.EndModal(wx.ID_OK)
+
+ def OnCancel(self, event):
+ self.EndModal(wx.ID_CANCEL)
+
+ # log the mouse clicks
+ def MouseClick(self, evt):
+ self.month = evt.month
+ # result click type and date
+ self.result = [evt.click, str(evt.day), Month[evt.month], str(evt.year)]
+
+ if evt.click == 'DLEFT':
+ self.EndModal(wx.ID_OK)
+
+ # month and year spin selection routines
+ def OnMonthSpin(self, event):
+ month = event.GetPosition()
+ self.date.SetValue(Month[month])
+ self.calend.SetMonth(month)
+ self.calend.Refresh()
+
+ def OnYrSpin(self, event):
+ year = event.GetPosition()
+ self.dtext.SetValue(str(year))
+ self.calend.SetYear(year)
+ self.calend.Refresh()
+
+ def EvtComboBox(self, event):
+ name = event.GetString()
+ monthval = self.date.FindString(name)
+ self.m_spin.SetValue(monthval+1)
+
+ self.calend.SetMonth(monthval+1)
+ self.ResetDisplay()
+
+ # set the calendar for highlighted days
+
+ def ResetDisplay(self):
+ month = self.calend.GetMonth()
+ self.calend.Refresh()
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/__init__.py
new file mode 100644
index 0000000..ccce2e3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/__init__.py
@@ -0,0 +1,36 @@
+"""
+PyColourChooser
+Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>
+
+This file is part of PyColourChooser.
+
+This version of PyColourChooser is open source; you can redistribute it
+and/or modify it under the licensed terms.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+"""
+
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxPyColorChooser -> PyColorChooser
+# o wxPyColourChooser -> PyColourChooser
+#
+
+from pycolourchooser import *
+
+# For the American in you
+PyColorChooser = PyColourChooser
+
+__all__ = [
+ 'canvas',
+ 'pycolourbox',
+ 'pycolourchooser',
+ 'pycolourslider',
+ 'pypalette',
+]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/canvas.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/canvas.py
new file mode 100644
index 0000000..cf9af06
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/canvas.py
@@ -0,0 +1,143 @@
+"""
+PyColourChooser
+Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>
+
+This file is part of PyColourChooser.
+
+This version of PyColourChooser is open source; you can redistribute it
+and/or modify it under the licensed terms.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+"""
+
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxPyColorChooser -> PyColorChooser
+# o wxPyColourChooser -> PyColourChooser
+#
+
+import wx
+
+class BitmapBuffer(wx.MemoryDC):
+ """A screen buffer class.
+
+ This class implements a screen output buffer. Data is meant to
+ be drawn in the buffer class and then blitted directly to the
+ output device, or on-screen window.
+ """
+ def __init__(self, width, height, colour):
+ """Initialize the empty buffer object."""
+ wx.MemoryDC.__init__(self)
+
+ self.width = width
+ self.height = height
+ self.colour = colour
+
+ self.bitmap = wx.EmptyBitmap(self.width, self.height)
+ self.SelectObject(self.bitmap)
+
+ # Initialize the buffer to the background colour
+ self.SetBackground(wx.Brush(self.colour, wx.SOLID))
+ self.Clear()
+
+ # Make each logical unit of the buffer equal to 1 pixel
+ self.SetMapMode(wx.MM_TEXT)
+
+ def GetBitmap(self):
+ """Returns the internal bitmap for direct drawing."""
+ return self.bitmap
+
+ # GetPixel seems to always return (-1, -1, -1, 255)
+ # on OS X so this is a workaround for that issue.
+ def GetPixelColour(self, x, y):
+ """Gets the color value of the pixel at the given
+ cords.
+
+ """
+ img = self.GetAsBitmap().ConvertToImage()
+ red = img.GetRed(x, y)
+ green = img.GetGreen(x, y)
+ blue = img.GetBlue(x, y)
+ return wx.Colour(red, green, blue)
+
+class Canvas(wx.Window):
+ """A canvas class for arbitrary drawing.
+
+ The Canvas class implements a window that allows for drawing
+ arbitrary graphics. It implements a double buffer scheme and
+ blits the off-screen buffer to the window during paint calls
+ by the windowing system for speed.
+
+ Some other methods for determining the canvas colour and size
+ are also provided.
+ """
+ def __init__(self, parent, id,
+ pos=wx.DefaultPosition,
+ size=wx.DefaultSize,
+ style=wx.SIMPLE_BORDER):
+ """Creates a canvas instance and initializes the off-screen
+ buffer. Also sets the handler for rendering the canvas
+ automatically via size and paint calls from the windowing
+ system."""
+ wx.Window.__init__(self, parent, id, pos, size, style)
+
+ # Perform an intial sizing
+ self.ReDraw()
+
+ # Register event handlers
+ self.Bind(wx.EVT_SIZE, self.onSize)
+ self.Bind(wx.EVT_PAINT, self.onPaint)
+
+ def MakeNewBuffer(self):
+ size = self.GetSize()
+ self.buffer = BitmapBuffer(size[0], size[1],
+ self.GetBackgroundColour())
+
+ def onSize(self, event):
+ """Perform actual redraw to off-screen buffer only when the
+ size of the canvas has changed. This saves a lot of computation
+ since the same image can be re-used, provided the canvas size
+ hasn't changed."""
+ self.MakeNewBuffer()
+ self.DrawBuffer()
+ self.Refresh()
+
+ def ReDraw(self):
+ """Explicitly tells the canvas to redraw it's contents."""
+ self.onSize(None)
+
+ def Refresh(self):
+ """Re-draws the buffer contents on-screen."""
+ dc = wx.ClientDC(self)
+ self.Blit(dc)
+
+ def onPaint(self, event):
+ """Renders the off-screen buffer on-screen."""
+ dc = wx.PaintDC(self)
+ self.Blit(dc)
+
+ def Blit(self, dc):
+ """Performs the blit of the buffer contents on-screen."""
+ width, height = self.buffer.GetSize()
+ dc.BeginDrawing()
+ dc.Blit(0, 0, width, height, self.buffer, 0, 0)
+ dc.EndDrawing()
+
+ def GetBoundingRect(self):
+ """Returns a tuple that contains the co-ordinates of the
+ top-left and bottom-right corners of the canvas."""
+ x, y = self.GetPosition()
+ w, h = self.GetSize()
+ return(x, y + h, x + w, y)
+
+ def DrawBuffer(self):
+ """Actual drawing function for drawing into the off-screen
+ buffer. To be overrideen in the implementing class. Do nothing
+ by default."""
+ pass
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/intl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/intl.py
new file mode 100644
index 0000000..b10d291
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/intl.py
@@ -0,0 +1,24 @@
+"""
+PyColourChooser
+Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>
+
+This file is part of PyColourChooser.
+
+This version of PyColourChooser is open source; you can redistribute it
+and/or modify it under the licensed terms.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+"""
+
+try:
+ import gettext
+
+ gettext.bindtextdomain('pycolourchooser')
+ gettext.textdomain('pycolourchooser')
+ _ = gettext.gettext
+except Exception, strerror:
+ print "Warning: Couldn't import translation function: %(str)s" %{ 'str' : strerror }
+ print "Defaulting to En"
+ _ = lambda x: x
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourbox.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourbox.py
new file mode 100644
index 0000000..a1108c7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourbox.py
@@ -0,0 +1,87 @@
+"""
+PyColourChooser
+Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>
+
+This file is part of PyColourChooser.
+
+This version of PyColourChooser is open source; you can redistribute it
+and/or modify it under the licensed terms.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+"""
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxPyColorChooser -> PyColorChooser
+# o wxPyColourChooser -> PyColourChooser
+#
+
+import wx
+
+class PyColourBox(wx.Panel):
+ """A Colour Selection Box
+
+ The Colour selection box implements button like behavior but contains
+ a solid-filled, coloured sub-box. Placing the colour in a sub-box allows
+ for filling in the main panel's background for a high-lighting effect.
+ """
+ def __init__(self, parent, id, colour=(0, 0, 0), size=(25, 20)):
+ """Creates a new colour box instance and initializes the colour
+ content."""
+ wx.Panel.__init__(self, parent, id, size=size, style=wx.NO_BORDER)
+
+ self.colour_box = wx.Window(self, -1, style=wx.SIMPLE_BORDER)
+
+ sizer = wx.GridSizer(1, 1)
+ sizer.Add(self.colour_box, 0, wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)
+ sizer.SetItemMinSize(self.colour_box, size[0] - 5, size[1] - 5)
+ self.SetAutoLayout(True)
+ self.SetSizer(sizer)
+ self.Layout()
+
+ self.real_bg = self.GetBackgroundColour()
+ self.SetColourTuple(colour)
+
+ def GetColourBox(self):
+ """Returns a reference to the internal box object containing the
+ color. This function is useful for setting up event handlers for
+ the box."""
+ return self.colour_box
+
+ def GetColour(self):
+ """Returns a wxColour object indicating the box's current colour."""
+ return self.colour_box.GetBackgroundColour()
+
+ def SetColour(self, colour):
+ """Accepts a wxColour object and sets the box's current color."""
+ self.colour_box.SetBackgroundColour(colour)
+ self.colour_box.Refresh()
+
+ def SetColourTuple(self, colour):
+ """Sets the box's current couple to the given tuple."""
+ self.colour = colour
+ self.colour_box.SetBackgroundColour(wx.Colour(*self.colour))
+
+ def Update(self):
+ wx.Panel.Update(self)
+ self.colour_box.Update()
+
+ def SetHighlight(self, val):
+ """Accepts a boolean 'val' toggling the box's highlighting."""
+ # XXX This code has been disabled for now until I can figure out
+ # how to get this to work reliably across all platforms.
+ if val:
+ #A wxColourPtr is returned in windows, making this difficult
+ red =(self.real_bg.Red() - 45) % 255
+ green =(self.real_bg.Green() - 45) % 255
+ blue =(self.real_bg.Blue() - 45) % 255
+ new_colour = wx.Colour(red, green, blue)
+ self.SetBackgroundColour(new_colour)
+ else:
+ self.SetBackgroundColour(self.real_bg)
+ self.Refresh()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourchooser.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourchooser.py
new file mode 100644
index 0000000..442eb74
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourchooser.py
@@ -0,0 +1,413 @@
+"""
+PyColourChooser
+Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>
+
+This file is part of PyColourChooser.
+
+This version of PyColourChooser is open source; you can redistribute it
+and/or modify it under the licensed terms.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+"""
+
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxPyColorChooser -> PyColorChooser
+# o wxPyColourChooser -> PyColourChooser
+# o Added wx.InitAllImageHandlers() to test code since
+# that's where it belongs.
+#
+
+import wx
+
+import pycolourbox
+import pypalette
+import pycolourslider
+import colorsys
+import intl
+
+from intl import _ # _
+
+class PyColourChooser(wx.Panel):
+ """A Pure-Python implementation of the colour chooser dialog.
+
+ The PyColourChooser is a pure python implementation of the colour
+ chooser dialog. It's useful for embedding the colour choosing functionality
+ inside other widgets, when the pop-up dialog is undesirable. It can also
+ be used as a drop-in replacement on the GTK platform, as the native
+ dialog is kind of ugly.
+ """
+
+ colour_names = [
+ 'ORANGE',
+ 'GOLDENROD',
+ 'WHEAT',
+ 'SPRING GREEN',
+ 'SKY BLUE',
+ 'SLATE BLUE',
+ 'MEDIUM VIOLET RED',
+ 'PURPLE',
+
+ 'RED',
+ 'YELLOW',
+ 'MEDIUM SPRING GREEN',
+ 'PALE GREEN',
+ 'CYAN',
+ 'LIGHT STEEL BLUE',
+ 'ORCHID',
+ 'LIGHT MAGENTA',
+
+ 'BROWN',
+ 'YELLOW',
+ 'GREEN',
+ 'CADET BLUE',
+ 'MEDIUM BLUE',
+ 'MAGENTA',
+ 'MAROON',
+ 'ORANGE RED',
+
+ 'FIREBRICK',
+ 'CORAL',
+ 'FOREST GREEN',
+ 'AQUAMARINE',
+ 'BLUE',
+ 'NAVY',
+ 'THISTLE',
+ 'MEDIUM VIOLET RED',
+
+ 'INDIAN RED',
+ 'GOLD',
+ 'MEDIUM SEA GREEN',
+ 'MEDIUM BLUE',
+ 'MIDNIGHT BLUE',
+ 'GREY',
+ 'PURPLE',
+ 'KHAKI',
+
+ 'BLACK',
+ 'MEDIUM FOREST GREEN',
+ 'KHAKI',
+ 'DARK GREY',
+ 'SEA GREEN',
+ 'LIGHT GREY',
+ 'MEDIUM SLATE BLUE',
+ 'WHITE',
+ ]
+
+ # Generate the custom colours. These colours are shared across
+ # all instances of the colour chooser
+ NO_CUSTOM_COLOURS = 16
+ custom_colours = [ (wx.Colour(255, 255, 255),
+ pycolourslider.PyColourSlider.HEIGHT / 2)
+ ] * NO_CUSTOM_COLOURS
+ last_custom = 0
+
+ idADD_CUSTOM = wx.NewId()
+ idSCROLL = wx.NewId()
+
+ def __init__(self, parent, id):
+ """Creates an instance of the colour chooser. Note that it is best to
+ accept the given size of the colour chooser as it is currently not
+ resizeable."""
+ wx.Panel.__init__(self, parent, id)
+
+ self.basic_label = wx.StaticText(self, -1, _("Basic Colours:"))
+ self.custom_label = wx.StaticText(self, -1, _("Custom Colours:"))
+ self.add_button = wx.Button(self, self.idADD_CUSTOM, _("Add to Custom Colours"))
+
+ self.Bind(wx.EVT_BUTTON, self.onAddCustom, self.add_button)
+
+ # Since we're going to be constructing widgets that require some serious
+ # computation, let's process any events (like redraws) right now
+ wx.Yield()
+
+ # Create the basic colours palette
+ self.colour_boxs = [ ]
+ colour_grid = wx.GridSizer(6, 8)
+ for name in self.colour_names:
+ new_id = wx.NewId()
+ box = pycolourbox.PyColourBox(self, new_id)
+
+ box.GetColourBox().Bind(wx.EVT_LEFT_DOWN, lambda x, b=box: self.onBasicClick(x, b))
+
+ self.colour_boxs.append(box)
+ colour_grid.Add(box, 0, wx.EXPAND)
+
+ # Create the custom colours palette
+ self.custom_boxs = [ ]
+ custom_grid = wx.GridSizer(2, 8)
+ for wxcolour, slidepos in self.custom_colours:
+ new_id = wx.NewId()
+ custom = pycolourbox.PyColourBox(self, new_id)
+
+ custom.GetColourBox().Bind(wx.EVT_LEFT_DOWN, lambda x, b=custom: self.onCustomClick(x, b))
+
+ custom.SetColour(wxcolour)
+ custom_grid.Add(custom, 0, wx.EXPAND)
+ self.custom_boxs.append(custom)
+
+ csizer = wx.BoxSizer(wx.VERTICAL)
+ csizer.Add((1, 25))
+ csizer.Add(self.basic_label, 0, wx.EXPAND)
+ csizer.Add((1, 5))
+ csizer.Add(colour_grid, 0, wx.EXPAND)
+ csizer.Add((1, 25))
+ csizer.Add(self.custom_label, 0, wx.EXPAND)
+ csizer.Add((1, 5))
+ csizer.Add(custom_grid, 0, wx.EXPAND)
+ csizer.Add((1, 5))
+ csizer.Add(self.add_button, 0, wx.EXPAND)
+
+ self.palette = pypalette.PyPalette(self, -1)
+ self.colour_slider = pycolourslider.PyColourSlider(self, -1)
+ self.slider = wx.Slider(
+ self, self.idSCROLL, 86, 0, self.colour_slider.HEIGHT - 1,
+ style=wx.SL_VERTICAL, size=(15, self.colour_slider.HEIGHT)
+ )
+
+ self.Bind(wx.EVT_COMMAND_SCROLL, self.onScroll, self.slider)
+ psizer = wx.BoxSizer(wx.HORIZONTAL)
+ psizer.Add(self.palette, 0, 0)
+ psizer.Add((10, 1))
+ psizer.Add(self.colour_slider, 0, wx.ALIGN_CENTER_VERTICAL)
+ psizer.Add(self.slider, 0, wx.ALIGN_CENTER_VERTICAL)
+
+ # Register mouse events for dragging across the palette
+ self.palette.Bind(wx.EVT_LEFT_DOWN, self.onPaletteDown)
+ self.palette.Bind(wx.EVT_LEFT_UP, self.onPaletteUp)
+ self.palette.Bind(wx.EVT_MOTION, self.onPaletteMotion)
+ self.mouse_down = False
+
+ self.solid = pycolourbox.PyColourBox(self, -1, size=(75, 50))
+ slabel = wx.StaticText(self, -1, _("Solid Colour"))
+ ssizer = wx.BoxSizer(wx.VERTICAL)
+ ssizer.Add(self.solid, 0, 0)
+ ssizer.Add((1, 2))
+ ssizer.Add(slabel, 0, wx.ALIGN_CENTER_HORIZONTAL)
+
+ hlabel = wx.StaticText(self, -1, _("H:"))
+ self.hentry = wx.TextCtrl(self, -1)
+ self.hentry.SetSize((40, -1))
+ slabel = wx.StaticText(self, -1, _("S:"))
+ self.sentry = wx.TextCtrl(self, -1)
+ self.sentry.SetSize((40, -1))
+ vlabel = wx.StaticText(self, -1, _("V:"))
+ self.ventry = wx.TextCtrl(self, -1)
+ self.ventry.SetSize((40, -1))
+ hsvgrid = wx.FlexGridSizer(1, 6, 2, 2)
+ hsvgrid.AddMany ([
+ (hlabel, 0, wx.ALIGN_CENTER_VERTICAL), (self.hentry, 0, wx.FIXED_MINSIZE),
+ (slabel, 0, wx.ALIGN_CENTER_VERTICAL), (self.sentry, 0, wx.FIXED_MINSIZE),
+ (vlabel, 0, wx.ALIGN_CENTER_VERTICAL), (self.ventry, 0, wx.FIXED_MINSIZE),
+ ])
+
+ rlabel = wx.StaticText(self, -1, _("R:"))
+ self.rentry = wx.TextCtrl(self, -1)
+ self.rentry.SetSize((40, -1))
+ glabel = wx.StaticText(self, -1, _("G:"))
+ self.gentry = wx.TextCtrl(self, -1)
+ self.gentry.SetSize((40, -1))
+ blabel = wx.StaticText(self, -1, _("B:"))
+ self.bentry = wx.TextCtrl(self, -1)
+ self.bentry.SetSize((40, -1))
+ lgrid = wx.FlexGridSizer(1, 6, 2, 2)
+ lgrid.AddMany([
+ (rlabel, 0, wx.ALIGN_CENTER_VERTICAL), (self.rentry, 0, wx.FIXED_MINSIZE),
+ (glabel, 0, wx.ALIGN_CENTER_VERTICAL), (self.gentry, 0, wx.FIXED_MINSIZE),
+ (blabel, 0, wx.ALIGN_CENTER_VERTICAL), (self.bentry, 0, wx.FIXED_MINSIZE),
+ ])
+
+ gsizer = wx.GridSizer(2, 1)
+ gsizer.SetVGap (10)
+ gsizer.SetHGap (2)
+ gsizer.Add(hsvgrid, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)
+ gsizer.Add(lgrid, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)
+
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer.Add(ssizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)
+ hsizer.Add(gsizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)
+
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ vsizer.Add((1, 5))
+ vsizer.Add(psizer, 0, 0)
+ vsizer.Add((1, 15))
+ vsizer.Add(hsizer, 0, wx.EXPAND)
+
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add((5, 1))
+ sizer.Add(csizer, 0, wx.EXPAND)
+ sizer.Add((10, 1))
+ sizer.Add(vsizer, 0, wx.EXPAND)
+ self.SetAutoLayout(True)
+ self.SetSizer(sizer)
+ sizer.Fit(self)
+
+ self.InitColours()
+ self.UpdateColour(self.solid.GetColour())
+
+ def InitColours(self):
+ """Initializes the pre-set palette colours."""
+ for i in range(len(self.colour_names)):
+ colour = wx.TheColourDatabase.FindColour(self.colour_names[i])
+ self.colour_boxs[i].SetColourTuple((colour.Red(),
+ colour.Green(),
+ colour.Blue()))
+
+ def onBasicClick(self, event, box):
+ """Highlights the selected colour box and updates the solid colour
+ display and colour slider to reflect the choice."""
+ if hasattr(self, '_old_custom_highlight'):
+ self._old_custom_highlight.SetHighlight(False)
+ if hasattr(self, '_old_colour_highlight'):
+ self._old_colour_highlight.SetHighlight(False)
+ box.SetHighlight(True)
+ self._old_colour_highlight = box
+ self.UpdateColour(box.GetColour())
+
+ def onCustomClick(self, event, box):
+ """Highlights the selected custom colour box and updates the solid
+ colour display and colour slider to reflect the choice."""
+ if hasattr(self, '_old_colour_highlight'):
+ self._old_colour_highlight.SetHighlight(False)
+ if hasattr(self, '_old_custom_highlight'):
+ self._old_custom_highlight.SetHighlight(False)
+ box.SetHighlight(True)
+ self._old_custom_highlight = box
+
+ # Update the colour panel and then the slider accordingly
+ box_index = self.custom_boxs.index(box)
+ base_colour, slidepos = self.custom_colours[box_index]
+ self.UpdateColour(box.GetColour())
+ self.slider.SetValue(slidepos)
+
+ def onAddCustom(self, event):
+ """Adds a custom colour to the custom colour box set. Boxes are
+ chosen in a round-robin fashion, eventually overwriting previously
+ added colours."""
+ # Store the colour and slider position so we can restore the
+ # custom colours just as they were
+ self.setCustomColour(self.last_custom,
+ self.solid.GetColour(),
+ self.colour_slider.GetBaseColour(),
+ self.slider.GetValue())
+ self.last_custom = (self.last_custom + 1) % self.NO_CUSTOM_COLOURS
+
+ def setCustomColour (self, index, true_colour, base_colour, slidepos):
+ """Sets the custom colour at the given index. true_colour is wxColour
+ object containing the actual rgb value of the custom colour.
+ base_colour (wxColour) and slidepos (int) are used to configure the
+ colour slider and set everything to its original position."""
+ self.custom_boxs[index].SetColour(true_colour)
+ self.custom_colours[index] = (base_colour, slidepos)
+
+ def UpdateColour(self, colour):
+ """Performs necessary updates for when the colour selection has
+ changed."""
+ # Reset the palette to erase any highlighting
+ self.palette.ReDraw()
+
+ # Set the color info
+ self.solid.SetColour(colour)
+ self.colour_slider.SetBaseColour(colour)
+ self.colour_slider.ReDraw()
+ self.slider.SetValue(0)
+ self.UpdateEntries(colour)
+
+ def UpdateEntries(self, colour):
+ """Updates the color levels to display the new values."""
+ # Temporary bindings
+ r = colour.Red()
+ g = colour.Green()
+ b = colour.Blue()
+
+ # Update the RGB entries
+ self.rentry.SetValue(str(r))
+ self.gentry.SetValue(str(g))
+ self.bentry.SetValue(str(b))
+
+ # Convert to HSV
+ h,s,v = colorsys.rgb_to_hsv(r / 255.0, g / 255.0, b / 255.0)
+ self.hentry.SetValue("%.2f" % (h))
+ self.sentry.SetValue("%.2f" % (s))
+ self.ventry.SetValue("%.2f" % (v))
+
+ def onPaletteDown(self, event):
+ """Stores state that the mouse has been pressed and updates
+ the selected colour values."""
+ self.mouse_down = True
+ self.palette.ReDraw()
+ self.doPaletteClick(event.X, event.Y)
+
+ def onPaletteUp(self, event):
+ """Stores state that the mouse is no longer depressed."""
+ self.mouse_down = False
+
+ def onPaletteMotion(self, event):
+ """Updates the colour values during mouse motion while the
+ mouse button is depressed."""
+ if self.mouse_down:
+ self.doPaletteClick(event.X, event.Y)
+
+ def doPaletteClick(self, m_x, m_y):
+ """Updates the colour values based on the mouse location
+ over the palette."""
+ # Get the colour value and update
+ colour = self.palette.GetValue(m_x, m_y)
+ self.UpdateColour(colour)
+
+ # Highlight a fresh selected area
+ self.palette.ReDraw()
+ self.palette.HighlightPoint(m_x, m_y)
+
+ # Force an onscreen update
+ self.solid.Update()
+ self.colour_slider.Refresh()
+
+ def onScroll(self, event):
+ """Updates the solid colour display to reflect the changing slider."""
+ value = self.slider.GetValue()
+ colour = self.colour_slider.GetValue(value)
+ self.solid.SetColour(colour)
+ self.UpdateEntries(colour)
+
+ def SetValue(self, colour):
+ """Updates the colour chooser to reflect the given wxColour."""
+ self.UpdateColour(colour)
+
+ def GetValue(self):
+ """Returns a wxColour object indicating the current colour choice."""
+ return self.solid.GetColour()
+
+def main():
+ """Simple test display."""
+ class App(wx.App):
+ def OnInit(self):
+ frame = wx.Frame(None, -1, 'PyColourChooser Test')
+
+ # Added here because that's where it's supposed to be,
+ # not embedded in the library. If it's embedded in the
+ # library, debug messages will be generated for duplicate
+ # handlers.
+ wx.InitAllImageHandlers()
+
+ chooser = PyColourChooser(frame, -1)
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(chooser, 0, 0)
+ frame.SetAutoLayout(True)
+ frame.SetSizer(sizer)
+ sizer.Fit(frame)
+
+ frame.Show(True)
+ self.SetTopWindow(frame)
+ return True
+ app = App(False)
+ app.MainLoop()
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourslider.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourslider.py
new file mode 100644
index 0000000..25b3727
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pycolourslider.py
@@ -0,0 +1,92 @@
+"""
+PyColourChooser
+Copyright (C) 2002 Michael Gilfix
+
+This file is part of PyColourChooser.
+
+You should have received a file COPYING containing license terms
+along with this program; if not, write to Michael Gilfix
+(mgilfix@eecs.tufts.edu) for a copy.
+
+This version of PyColourChooser is open source; you can redistribute it and/or
+modify it under the terms listed in the file COPYING.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+"""
+
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxPyColorChooser -> PyColorChooser
+# o wxPyColourChooser -> PyColourChooser
+#
+
+import wx
+
+import canvas
+import colorsys
+
+class PyColourSlider(canvas.Canvas):
+ """A Pure-Python Colour Slider
+
+ The colour slider displays transitions from value 0 to value 1 in
+ HSV, allowing the user to select a colour within the transition
+ spectrum.
+
+ This class is best accompanying by a wxSlider that allows the user
+ to select a particular colour shade.
+ """
+
+ HEIGHT = 172
+ WIDTH = 12
+
+ def __init__(self, parent, id, colour=None):
+ """Creates a blank slider instance. A colour must be set before the
+ slider will be filled in."""
+ # Set the base colour first since our base class calls the buffer
+ # drawing function
+ self.SetBaseColour(colour)
+
+ canvas.Canvas.__init__(self, parent, id, size=(self.WIDTH, self.HEIGHT))
+
+ def SetBaseColour(self, colour):
+ """Sets the base, or target colour, to use as the central colour
+ when calculating colour transitions."""
+ self.base_colour = colour
+
+ def GetBaseColour(self):
+ """Return the current colour used as a colour base for filling out
+ the slider."""
+ return self.base_colour
+
+ def GetValue(self, pos):
+ """Returns the colour value for a position on the slider. The position
+ must be within the valid height of the slider, or results can be
+ unpredictable."""
+ return self.buffer.GetPixelColour(0, pos)
+
+ def DrawBuffer(self):
+ """Actual implementation of the widget's drawing. We simply draw
+ from value 0.0 to value 1.0 in HSV."""
+ if self.base_colour is None:
+ return
+
+ target_red = self.base_colour.Red()
+ target_green = self.base_colour.Green()
+ target_blue = self.base_colour.Blue()
+
+ h,s,v = colorsys.rgb_to_hsv(target_red / 255.0, target_green / 255.0,
+ target_blue / 255.0)
+ v = 1.0
+ vstep = 1.0 / self.HEIGHT
+ for y_pos in range(0, self.HEIGHT):
+ r,g,b = [c * 255.0 for c in colorsys.hsv_to_rgb(h,s,v)]
+ colour = wx.Colour(int(r), int(g), int(b))
+ self.buffer.SetPen(wx.Pen(colour, 1, wx.SOLID))
+ self.buffer.DrawRectangle(0, y_pos, 15, 1)
+ v = v - vstep
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pypalette.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pypalette.py
new file mode 100644
index 0000000..49a33e4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourchooser/pypalette.py
@@ -0,0 +1,176 @@
+"""
+PyColourChooser
+Copyright (C) 2002 Michael Gilfix
+
+This file is part of PyColourChooser.
+
+You should have received a file COPYING containing license terms
+along with this program; if not, write to Michael Gilfix
+(mgilfix@eecs.tufts.edu) for a copy.
+
+This version of PyColourChooser is open source; you can redistribute it and/or
+modify it under the terms listed in the file COPYING.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+"""
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxPyColorChooser -> PyColorChooser
+# o wxPyColourChooser -> PyColourChooser
+# o Commented out wx.InitAllImageHandlers() (see comments at that
+# point for explanation
+#
+
+import wx
+
+import canvas
+import colorsys
+
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+Image = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAMgAAADACAYAAABBCyzzAAAABHNCSVQICAgIfAhkiAAACwNJ"
+ "REFUeJztnc16o0YQRZHt8SJZJO//lMkiWWQsKwsLK7S49dNdjTyTczYYhBBd7vqoom7B6bIs"
+ "l2VZluW3Zdld/l603fn8n18/ln8u2+Ufy/527/Pe731ffsmdeO+Ave3ZgRUb6tvf+2dXPS08"
+ "670uf9UMqPN7TwsASHAQAAMcBMDgZfn27eOv6+Ju+SKWz2L55CxP+0ux2T2cOg112utSDbfO"
+ "EJ5B1Iidj7OG8AwihnvUtFDDvFnjsYbgCgJggIMAGOAgAAb3Ocjs4DJJVQQajTyPj7aDHGyI"
+ "Lz4tjCPVGoQrCIABDgJggIMAGOg6iFdImBx8Hp173Ocg7Z7twNv19kzagbfri1h3PlaHUz+v"
+ "TlcNz6mDPC4XmT0j9mcGVxAAAxwEwAAHATB4WV5fP/6Kim5+ktxDbT99oah7w8FJ2curvfvP"
+ "l4ugxQJIg4MAGOAgAAZxLdakPhCF1ycw2g3QRpyvn8enH2RZluXbm/lx+ajrc4+aeghXEAAD"
+ "HATAAAcBMIj3pGclSNHcQ4Te7frxWqxo7qEM8qDCUFSD5fWDiBxkVv1jEev+jFAG6RWlUQcB"
+ "CIODABjgIAAGWos1Gmyq0LAz9O69/Z/NRU53BqgSpx2kxeqVHjXbX877H2erQL25yD3ewEcN"
+ "Qj8IQBocBMAABwEwyGuxshKkztC79/b/uszWP+r6QYrqIbPFaF4/yHl3szstekedfz5WVTJG"
+ "DgLQDQ4CYICDABjktVjzRDfmbtV3u3Ud5LXZEtVgTeqEUKF2NhfxNFlNY4yqg1Q9qqAdxiLW"
+ "7z/xkjKlwYp2CNEPAhAGBwEwwEEADOq0WHWim93ds7lHVoq0Zh5P3Q8IU2c0aIiVrCG8XMQp"
+ "DEXrIL1arP46yLEFIa4gAAY4CIABDgJgMP5+kFHxzSm1W7oVO18HyRqi2iDB3SYbItoPMnla"
+ "JPasMgg5CEAYHATAAAcBMND9IKNSJKUd6qyD9GqxYk8/ivSkjxaEOg0yyxC2BKmsDlJkhf8Q"
+ "NUivGA0tFkAYHATAAAcBMIhrsUY1WMGg03sSa7Xipl2/12Jlm/OzFYAgvbf9Oxtjnt/Nj8ty"
+ "kf5+kNmNMeQgAC44CIABDgJgMK7FmhR69z4Pa1SLpftBom/na5dRLVFSi9Uus6flDHPNQWZp"
+ "serrINm+ELRYAMPgIAAGOAiAQb8WS/U+j9/w3v1adT1E9aS/fbVkbOXgOsjL++7m8vpH3Bq9"
+ "FbJscz5aLIAwOAiAAQ4CYFBfBxnMRY7KPfye9KrGmMFcZLQfpK8N4i4HyU6Hur6Qql50etIB"
+ "ysFBAAxwEACDun6Q+hvfu4erijiVFGleP0ixFmt2P8hld3O6PBbNxOJ4BsmK0shBALrBQQAM"
+ "cBAAg7wWKxp0eje6nZ700XqId/tf94O07yj8n70f5Dr8NgfxpkF2WuRTU28mZGeGMsT3zTpX"
+ "EAADHATAAAcBMMhrsXo1WMkb39ncI5uLrMN8uy7r+kGKn0o7GnJn6yBXg3j9INHcI5uL+GQN"
+ "0ZuLvG2+DQA74CAABjgIgIHWYqmgMxpyJ2+AV0uPVMTZ5h7t0n9P+mRDLMHdJhtEabFG+0Dy"
+ "1nisIbiCABjgIAAGOAiAgdZiVd/+n/w4qOxtfxV5PklDZKPwyYYYrYO0A2+2Ky3WqERvUJG2"
+ "883qghDPxQIIg4MAGOAgAAa+FitaBsg2HxdJkGoUNz096UqN1HvnXzB6+z/bGHN9P/qag4zm"
+ "Hu16pyJtZ4/ROog3E86bowDADjgIgAEOAmAQ12KpoHNQctTSq7zJPv1IhN7Lc7chsslZpxZr"
+ "tgHO28MePfp4LtJroJwhuIIAGOAgAAY4CIBBXIvlNXsXS5GqQvBgyL28f66P5h5F9Y+WWQZR"
+ "dZBm8+OtMWqA9UzfxHa0WABpcBAAAxwEwGD8uVjRYDOoyfIUN1EtVhtxruvnZn0d7pqD+D3p"
+ "B0ff1bmHZwCRg3jSPFUei2qxFrFeNyP6DMIVBMAABwEwwEEADMa1WD9Y6L0u29B7XT6XNeMX"
+ "1T9aDjLM02mz+ujpYHxj7ozgCgJggIMAGOAgAAb9WqyDW7CrI84297gt2/vh1e8JObgfRBnA"
+ "McSjcpD6XGRshnAFATDAQQAMcBAAg7wWKxp0eg9A6nwulooslRarVdro3GNdjj4g7IsWhFrD"
+ "KANcn4fV5iC9Twc77rlYSpPl5RzvYv2yORoA7ICDABjgIAAGeS3WaMidJBqCD4bcn8t8HeQH"
+ "6UlPGkLVQR4/LaoLRLYhuIIAGOAgAAY4CIBB/h2Fkx7G2qvBGr39r3OQWYaYpMV6cB2k2go3"
+ "a1Sr83KG4AoCYICDABjgIAAGcS2WEt2MPhdLkK1/nJv1NsK8iPV8HSRqCKVCmtQgowyhDLKu"
+ "twZYD3va7pZNUZUVxqtCngYrWxBSM2V7FADYAQcBMMBBAAzGtVheg0Yy6PRCbi8Xae9mq1Bb"
+ "hN7LRT6VtjopG9RieSG3CrE9g6w/cz1edUe+GoZvld7CkGcYNRO23waAHXAQAAMcBMAgr8XK"
+ "9qT3PwBpc7hshOlprvYjzr0cZPSF8Z1PhBoVp6kmfc8A6880OYhXFRrVYvlEJ1TvTNg3DFcQ"
+ "AAMcBMAABwEw0DnIrGBTPd5I7Jatf7Tr0dxjPf57ug6SrQAk6yFe4cAziCdCEzxdj5d9N+Go"
+ "FuveGmrCZBtkPIPs/y5XEAADHATAAAcBMJjfkx7MPVp6Q2+tsYr93vtddO11RFQlY8ETzIbe"
+ "wZyjpc1BestjRZnYzh7R7LQzCSMHAfDBQQAMcBAAg1s/iLrB7S17JUgOvU9B8hQ23v33y+cR"
+ "R5OxQXFatjEmagBFc9zT9XjZLpj5TyruFaWtZ5z7Ha4gAAY4CIABDgJgcKuDeEHmQRKk0bvd"
+ "7Xr2+Pc5SNYgdXf+zRNdD/ferCvDJI9/uh531Ap15bEqA3gzY3t8riAABjgIgAEOAmCgcxDv"
+ "tQqTQ28VcV7E+noavcf1c5BRg3QWhh5kCJWDPHhaGCfe5iI1BuEKAmCAgwAY4CAABjctlrqB"
+ "nV1mm49Pqd1kKO4R1XZd7rYcbAjvhGcZojnemoOMTousFuveGrMM4R2fHATABQcBMMBBAAxu"
+ "dRBPRBMV2WTFN4JZIXd7WudmXecg3vqoCslhVsjdnt4191hzkNFRZzMyn6whctqr1hBcQQAM"
+ "cBAAAxwEwEDnIF7zd28vemc/SOvJvf0eqnvg9tSkUQMc9GzeVovl0RpAGSSYg1RPj/Y074nW"
+ "QVbaGdLuf27W9w3BFQTAAAcBMMBBAAxuWiwVKlctB2/7exGn2k+9qU6E3ju/4A2o1xCDWqxs"
+ "7uHUPdSr/Kr+7Z0pqUHUEN4v2gbgCgJggIMAGOAgAAa3OogXNEaDSxVsFt3+V/u1t/fV99Wb"
+ "6nQOUmWQSVqs6H5e8iVeozE6yjpreAOLZqfKIPsG4AoCYICDABjgIAAGOgeJ5hCjuYe4/a/W"
+ "leLmJNZb6ZL3xrrL9IEnKwBRg6hkrNMgp3UpzrZ31Pl6iBrIijcjlEFUErZdcgUBMMBBAAxw"
+ "EACDmxZLxbqzlw5qtzaUXpp1FWrHX+F3lAGEQaIDVy9hbLdnDZI8a+/fOzgNAnuqASqDeIbZ"
+ "fgoAO+AgAAY4CIDBrQ7i3W+PBpfR7QL1sYokF2c9u/3+F48yjMOoYToNVv3vHreK+mavAWzD"
+ "cAUBMMBBAAxwEAADnYO0eDHw6Pbk171H0maf1KpzkKO3d359fMC726tH1W+N6JGrDPEBVxAA"
+ "AxwEwAAHATD4F0lpw33hNrduAAAAAElFTkSuQmCC")
+
+
+class PyPalette(canvas.Canvas):
+ """The Pure-Python Palette
+
+ The PyPalette is a pure python implementation of a colour palette. The
+ palette implementation here imitates the palette layout used by MS
+ Windows and Adobe Photoshop.
+
+ The actual palette image has been embedded as an XPM for speed. The
+ actual reverse-engineered drawing algorithm is provided in the
+ GeneratePaletteBMP() method. The algorithm is tweakable by supplying
+ the granularity factor to improve speed at the cost of display
+ beauty. Since the generator isn't used in real time, no one will
+ likely care :) But if you need it for some sort of unforeseen realtime
+ application, it's there.
+ """
+
+ HORIZONTAL_STEP = 2
+ VERTICAL_STEP = 4
+
+ def __init__(self, parent, id):
+ """Creates a palette object."""
+ # Load the pre-generated palette XPM
+
+ # Leaving this in causes warning messages in some cases.
+ # It is the responsibility of the app to init the image
+ # handlers, IAW RD
+ #wx.InitAllImageHandlers()
+
+ self.palette = Image.GetBitmap()
+ canvas.Canvas.__init__ (self, parent, id, size=(200, 192))
+
+ def GetValue(self, x, y):
+ """Returns a colour value at a specific x, y coordinate pair. This
+ is useful for determining the colour found a specific mouse click
+ in an external event handler."""
+ return self.buffer.GetPixelColour(x, y)
+
+ def DrawBuffer(self):
+ """Draws the palette XPM into the memory buffer."""
+ #self.GeneratePaletteBMP ("foo.bmp")
+ self.buffer.DrawBitmap(self.palette, 0, 0, 0)
+
+ def HighlightPoint(self, x, y):
+ """Highlights an area of the palette with a little circle around
+ the coordinate point"""
+ colour = wx.Colour(0, 0, 0)
+ self.buffer.SetPen(wx.Pen(colour, 1, wx.SOLID))
+ self.buffer.SetBrush(wx.Brush(colour, wx.TRANSPARENT))
+ self.buffer.DrawCircle(x, y, 3)
+ self.Refresh()
+
+ def GeneratePaletteBMP(self, file_name, granularity=1):
+ """The actual palette drawing algorithm.
+
+ This used to be 100% reverse engineered by looking at the
+ values on the MS map, but has since been redone Correctly(tm)
+ according to the HSV (hue, saturation, value) colour model by
+ Charl P. Botha <http://cpbotha.net/>.
+
+ Speed is tweakable by changing the granularity factor, but
+ that affects how nice the output looks (makes the vertical
+ blocks bigger. This method was used to generate the embedded
+ XPM data."""
+ self.vertical_step = self.VERTICAL_STEP * granularity
+ width, height = self.GetSize ()
+
+ # simply iterate over hue (horizontal) and saturation (vertical)
+ value = 1.0
+ for y in range(0, height, self.vertical_step):
+ saturation = 1.0 - float(y) / float(height)
+ for x in range(0, width, self.HORIZONTAL_STEP):
+ hue = float(x) / float(width)
+ r,g,b = colorsys.hsv_to_rgb(hue, saturation, value)
+ colour = wx.Colour(int(r * 255.0), int(g * 255.0), int(b * 255.0))
+ self.buffer.SetPen(wx.Pen(colour, 1, wx.SOLID))
+ self.buffer.SetBrush(wx.Brush(colour, wx.SOLID))
+ self.buffer.DrawRectangle(x, y,
+ self.HORIZONTAL_STEP, self.vertical_step)
+
+ # this code is now simpler (and works)
+ bitmap = self.buffer.GetBitmap()
+ image = wx.ImageFromBitmap(bitmap)
+ image.SaveFile (file_name, wx.BITMAP_TYPE_XPM)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourdb.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourdb.py
new file mode 100644
index 0000000..c053c5c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourdb.py
@@ -0,0 +1,676 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.colourdb.py
+# Purpose: Adds a bunch of colour names and RGB values to the
+# colour database so they can be found by name
+#
+# Author: Robin Dunn
+#
+# Created: 13-March-2001
+# RCS-ID: $Id$
+# Copyright: (c) 2001 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""
+Load addition color names/values into the wx colour database. These
+names and values originally came from the rgb.txt file on my system...
+"""
+
+
+def getColourList():
+ """Returns a list of just the colour names used by this module."""
+ return [ x[0] for x in getColourInfoList() ]
+
+
+
+def getColourInfoList():
+ """Returns the list of colour name/value tuples used by this module."""
+ return [
+ ("SNOW", 255, 250, 250),
+ ("GHOST WHITE", 248, 248, 255),
+ ("GHOSTWHITE", 248, 248, 255),
+ ("WHITE SMOKE", 245, 245, 245),
+ ("WHITESMOKE", 245, 245, 245),
+ ("GAINSBORO", 220, 220, 220),
+ ("FLORAL WHITE", 255, 250, 240),
+ ("FLORALWHITE", 255, 250, 240),
+ ("OLD LACE", 253, 245, 230),
+ ("OLDLACE", 253, 245, 230),
+ ("LINEN", 250, 240, 230),
+ ("ANTIQUE WHITE", 250, 235, 215),
+ ("ANTIQUEWHITE", 250, 235, 215),
+ ("PAPAYA WHIP", 255, 239, 213),
+ ("PAPAYAWHIP", 255, 239, 213),
+ ("BLANCHED ALMOND", 255, 235, 205),
+ ("BLANCHEDALMOND", 255, 235, 205),
+ ("BISQUE", 255, 228, 196),
+ ("PEACH PUFF", 255, 218, 185),
+ ("PEACHPUFF", 255, 218, 185),
+ ("NAVAJO WHITE", 255, 222, 173),
+ ("NAVAJOWHITE", 255, 222, 173),
+ ("MOCCASIN", 255, 228, 181),
+ ("CORNSILK", 255, 248, 220),
+ ("IVORY", 255, 255, 240),
+ ("LEMON CHIFFON", 255, 250, 205),
+ ("LEMONCHIFFON", 255, 250, 205),
+ ("SEASHELL", 255, 245, 238),
+ ("HONEYDEW", 240, 255, 240),
+ ("MINT CREAM", 245, 255, 250),
+ ("MINTCREAM", 245, 255, 250),
+ ("AZURE", 240, 255, 255),
+ ("ALICE BLUE", 240, 248, 255),
+ ("ALICEBLUE", 240, 248, 255),
+ ("LAVENDER", 230, 230, 250),
+ ("LAVENDER BLUSH", 255, 240, 245),
+ ("LAVENDERBLUSH", 255, 240, 245),
+ ("MISTY ROSE", 255, 228, 225),
+ ("MISTYROSE", 255, 228, 225),
+ ("WHITE", 255, 255, 255),
+ ("BLACK", 0, 0, 0),
+ ("DARK SLATE GREY", 47, 79, 79),
+ ("DARKSLATEGREY", 47, 79, 79),
+ ("DIM GREY", 105, 105, 105),
+ ("DIMGREY", 105, 105, 105),
+ ("SLATE GREY", 112, 128, 144),
+ ("SLATEGREY", 112, 128, 144),
+ ("LIGHT SLATE GREY", 119, 136, 153),
+ ("LIGHTSLATEGREY", 119, 136, 153),
+ ("GREY", 190, 190, 190),
+ ("LIGHT GREY", 211, 211, 211),
+ ("LIGHTGREY", 211, 211, 211),
+ ("MIDNIGHT BLUE", 25, 25, 112),
+ ("MIDNIGHTBLUE", 25, 25, 112),
+ ("NAVY", 0, 0, 128),
+ ("NAVY BLUE", 0, 0, 128),
+ ("NAVYBLUE", 0, 0, 128),
+ ("CORNFLOWER BLUE", 100, 149, 237),
+ ("CORNFLOWERBLUE", 100, 149, 237),
+ ("DARK SLATE BLUE", 72, 61, 139),
+ ("DARKSLATEBLUE", 72, 61, 139),
+ ("SLATE BLUE", 106, 90, 205),
+ ("SLATEBLUE", 106, 90, 205),
+ ("MEDIUM SLATE BLUE", 123, 104, 238),
+ ("MEDIUMSLATEBLUE", 123, 104, 238),
+ ("LIGHT SLATE BLUE", 132, 112, 255),
+ ("LIGHTSLATEBLUE", 132, 112, 255),
+ ("MEDIUM BLUE", 0, 0, 205),
+ ("MEDIUMBLUE", 0, 0, 205),
+ ("ROYAL BLUE", 65, 105, 225),
+ ("ROYALBLUE", 65, 105, 225),
+ ("BLUE", 0, 0, 255),
+ ("DODGER BLUE", 30, 144, 255),
+ ("DODGERBLUE", 30, 144, 255),
+ ("DEEP SKY BLUE", 0, 191, 255),
+ ("DEEPSKYBLUE", 0, 191, 255),
+ ("SKY BLUE", 135, 206, 235),
+ ("SKYBLUE", 135, 206, 235),
+ ("LIGHT SKY BLUE", 135, 206, 250),
+ ("LIGHTSKYBLUE", 135, 206, 250),
+ ("STEEL BLUE", 70, 130, 180),
+ ("STEELBLUE", 70, 130, 180),
+ ("LIGHT STEEL BLUE", 176, 196, 222),
+ ("LIGHTSTEELBLUE", 176, 196, 222),
+ ("LIGHT BLUE", 173, 216, 230),
+ ("LIGHTBLUE", 173, 216, 230),
+ ("POWDER BLUE", 176, 224, 230),
+ ("POWDERBLUE", 176, 224, 230),
+ ("PALE TURQUOISE", 175, 238, 238),
+ ("PALETURQUOISE", 175, 238, 238),
+ ("DARK TURQUOISE", 0, 206, 209),
+ ("DARKTURQUOISE", 0, 206, 209),
+ ("MEDIUM TURQUOISE", 72, 209, 204),
+ ("MEDIUMTURQUOISE", 72, 209, 204),
+ ("TURQUOISE", 64, 224, 208),
+ ("CYAN", 0, 255, 255),
+ ("LIGHT CYAN", 224, 255, 255),
+ ("LIGHTCYAN", 224, 255, 255),
+ ("CADET BLUE", 95, 158, 160),
+ ("CADETBLUE", 95, 158, 160),
+ ("MEDIUM AQUAMARINE", 102, 205, 170),
+ ("MEDIUMAQUAMARINE", 102, 205, 170),
+ ("AQUAMARINE", 127, 255, 212),
+ ("DARK GREEN", 0, 100, 0),
+ ("DARKGREEN", 0, 100, 0),
+ ("DARK OLIVE GREEN", 85, 107, 47),
+ ("DARKOLIVEGREEN", 85, 107, 47),
+ ("DARK SEA GREEN", 143, 188, 143),
+ ("DARKSEAGREEN", 143, 188, 143),
+ ("SEA GREEN", 46, 139, 87),
+ ("SEAGREEN", 46, 139, 87),
+ ("MEDIUM SEA GREEN", 60, 179, 113),
+ ("MEDIUMSEAGREEN", 60, 179, 113),
+ ("LIGHT SEA GREEN", 32, 178, 170),
+ ("LIGHTSEAGREEN", 32, 178, 170),
+ ("PALE GREEN", 152, 251, 152),
+ ("PALEGREEN", 152, 251, 152),
+ ("SPRING GREEN", 0, 255, 127),
+ ("SPRINGGREEN", 0, 255, 127),
+ ("LAWN GREEN", 124, 252, 0),
+ ("LAWNGREEN", 124, 252, 0),
+ ("GREEN", 0, 255, 0),
+ ("CHARTREUSE", 127, 255, 0),
+ ("MEDIUM SPRING GREEN", 0, 250, 154),
+ ("MEDIUMSPRINGGREEN", 0, 250, 154),
+ ("GREEN YELLOW", 173, 255, 47),
+ ("GREENYELLOW", 173, 255, 47),
+ ("LIME GREEN", 50, 205, 50),
+ ("LIMEGREEN", 50, 205, 50),
+ ("YELLOW GREEN", 154, 205, 50),
+ ("YELLOWGREEN", 154, 205, 50),
+ ("FOREST GREEN", 34, 139, 34),
+ ("FORESTGREEN", 34, 139, 34),
+ ("OLIVE DRAB", 107, 142, 35),
+ ("OLIVEDRAB", 107, 142, 35),
+ ("DARK KHAKI", 189, 183, 107),
+ ("DARKKHAKI", 189, 183, 107),
+ ("KHAKI", 240, 230, 140),
+ ("PALE GOLDENROD", 238, 232, 170),
+ ("PALEGOLDENROD", 238, 232, 170),
+ ("LIGHT GOLDENROD YELLOW", 250, 250, 210),
+ ("LIGHTGOLDENRODYELLOW", 250, 250, 210),
+ ("LIGHT YELLOW", 255, 255, 224),
+ ("LIGHTYELLOW", 255, 255, 224),
+ ("YELLOW", 255, 255, 0),
+ ("GOLD", 255, 215, 0),
+ ("LIGHT GOLDENROD", 238, 221, 130),
+ ("LIGHTGOLDENROD", 238, 221, 130),
+ ("GOLDENROD", 218, 165, 32),
+ ("DARK GOLDENROD", 184, 134, 11),
+ ("DARKGOLDENROD", 184, 134, 11),
+ ("ROSY BROWN", 188, 143, 143),
+ ("ROSYBROWN", 188, 143, 143),
+ ("INDIAN RED", 205, 92, 92),
+ ("INDIANRED", 205, 92, 92),
+ ("SADDLE BROWN", 139, 69, 19),
+ ("SADDLEBROWN", 139, 69, 19),
+ ("SIENNA", 160, 82, 45),
+ ("PERU", 205, 133, 63),
+ ("BURLYWOOD", 222, 184, 135),
+ ("BEIGE", 245, 245, 220),
+ ("WHEAT", 245, 222, 179),
+ ("SANDY BROWN", 244, 164, 96),
+ ("SANDYBROWN", 244, 164, 96),
+ ("TAN", 210, 180, 140),
+ ("CHOCOLATE", 210, 105, 30),
+ ("FIREBRICK", 178, 34, 34),
+ ("BROWN", 165, 42, 42),
+ ("DARK SALMON", 233, 150, 122),
+ ("DARKSALMON", 233, 150, 122),
+ ("SALMON", 250, 128, 114),
+ ("LIGHT SALMON", 255, 160, 122),
+ ("LIGHTSALMON", 255, 160, 122),
+ ("ORANGE", 255, 165, 0),
+ ("DARK ORANGE", 255, 140, 0),
+ ("DARKORANGE", 255, 140, 0),
+ ("CORAL", 255, 127, 80),
+ ("LIGHT CORAL", 240, 128, 128),
+ ("LIGHTCORAL", 240, 128, 128),
+ ("TOMATO", 255, 99, 71),
+ ("ORANGE RED", 255, 69, 0),
+ ("ORANGERED", 255, 69, 0),
+ ("RED", 255, 0, 0),
+ ("HOT PINK", 255, 105, 180),
+ ("HOTPINK", 255, 105, 180),
+ ("DEEP PINK", 255, 20, 147),
+ ("DEEPPINK", 255, 20, 147),
+ ("PINK", 255, 192, 203),
+ ("LIGHT PINK", 255, 182, 193),
+ ("LIGHTPINK", 255, 182, 193),
+ ("PALE VIOLET RED", 219, 112, 147),
+ ("PALEVIOLETRED", 219, 112, 147),
+ ("MAROON", 176, 48, 96),
+ ("MEDIUM VIOLET RED", 199, 21, 133),
+ ("MEDIUMVIOLETRED", 199, 21, 133),
+ ("VIOLET RED", 208, 32, 144),
+ ("VIOLETRED", 208, 32, 144),
+ ("MAGENTA", 255, 0, 255),
+ ("VIOLET", 238, 130, 238),
+ ("PLUM", 221, 160, 221),
+ ("ORCHID", 218, 112, 214),
+ ("MEDIUM ORCHID", 186, 85, 211),
+ ("MEDIUMORCHID", 186, 85, 211),
+ ("DARK ORCHID", 153, 50, 204),
+ ("DARKORCHID", 153, 50, 204),
+ ("DARK VIOLET", 148, 0, 211),
+ ("DARKVIOLET", 148, 0, 211),
+ ("BLUE VIOLET", 138, 43, 226),
+ ("BLUEVIOLET", 138, 43, 226),
+ ("PURPLE", 160, 32, 240),
+ ("MEDIUM PURPLE", 147, 112, 219),
+ ("MEDIUMPURPLE", 147, 112, 219),
+ ("THISTLE", 216, 191, 216),
+ ("SNOW1", 255, 250, 250),
+ ("SNOW2", 238, 233, 233),
+ ("SNOW3", 205, 201, 201),
+ ("SNOW4", 139, 137, 137),
+ ("SEASHELL1", 255, 245, 238),
+ ("SEASHELL2", 238, 229, 222),
+ ("SEASHELL3", 205, 197, 191),
+ ("SEASHELL4", 139, 134, 130),
+ ("ANTIQUEWHITE1", 255, 239, 219),
+ ("ANTIQUEWHITE2", 238, 223, 204),
+ ("ANTIQUEWHITE3", 205, 192, 176),
+ ("ANTIQUEWHITE4", 139, 131, 120),
+ ("BISQUE1", 255, 228, 196),
+ ("BISQUE2", 238, 213, 183),
+ ("BISQUE3", 205, 183, 158),
+ ("BISQUE4", 139, 125, 107),
+ ("PEACHPUFF1", 255, 218, 185),
+ ("PEACHPUFF2", 238, 203, 173),
+ ("PEACHPUFF3", 205, 175, 149),
+ ("PEACHPUFF4", 139, 119, 101),
+ ("NAVAJOWHITE1", 255, 222, 173),
+ ("NAVAJOWHITE2", 238, 207, 161),
+ ("NAVAJOWHITE3", 205, 179, 139),
+ ("NAVAJOWHITE4", 139, 121, 94),
+ ("LEMONCHIFFON1", 255, 250, 205),
+ ("LEMONCHIFFON2", 238, 233, 191),
+ ("LEMONCHIFFON3", 205, 201, 165),
+ ("LEMONCHIFFON4", 139, 137, 112),
+ ("CORNSILK1", 255, 248, 220),
+ ("CORNSILK2", 238, 232, 205),
+ ("CORNSILK3", 205, 200, 177),
+ ("CORNSILK4", 139, 136, 120),
+ ("IVORY1", 255, 255, 240),
+ ("IVORY2", 238, 238, 224),
+ ("IVORY3", 205, 205, 193),
+ ("IVORY4", 139, 139, 131),
+ ("HONEYDEW1", 240, 255, 240),
+ ("HONEYDEW2", 224, 238, 224),
+ ("HONEYDEW3", 193, 205, 193),
+ ("HONEYDEW4", 131, 139, 131),
+ ("LAVENDERBLUSH1", 255, 240, 245),
+ ("LAVENDERBLUSH2", 238, 224, 229),
+ ("LAVENDERBLUSH3", 205, 193, 197),
+ ("LAVENDERBLUSH4", 139, 131, 134),
+ ("MISTYROSE1", 255, 228, 225),
+ ("MISTYROSE2", 238, 213, 210),
+ ("MISTYROSE3", 205, 183, 181),
+ ("MISTYROSE4", 139, 125, 123),
+ ("AZURE1", 240, 255, 255),
+ ("AZURE2", 224, 238, 238),
+ ("AZURE3", 193, 205, 205),
+ ("AZURE4", 131, 139, 139),
+ ("SLATEBLUE1", 131, 111, 255),
+ ("SLATEBLUE2", 122, 103, 238),
+ ("SLATEBLUE3", 105, 89, 205),
+ ("SLATEBLUE4", 71, 60, 139),
+ ("ROYALBLUE1", 72, 118, 255),
+ ("ROYALBLUE2", 67, 110, 238),
+ ("ROYALBLUE3", 58, 95, 205),
+ ("ROYALBLUE4", 39, 64, 139),
+ ("BLUE1", 0, 0, 255),
+ ("BLUE2", 0, 0, 238),
+ ("BLUE3", 0, 0, 205),
+ ("BLUE4", 0, 0, 139),
+ ("DODGERBLUE1", 30, 144, 255),
+ ("DODGERBLUE2", 28, 134, 238),
+ ("DODGERBLUE3", 24, 116, 205),
+ ("DODGERBLUE4", 16, 78, 139),
+ ("STEELBLUE1", 99, 184, 255),
+ ("STEELBLUE2", 92, 172, 238),
+ ("STEELBLUE3", 79, 148, 205),
+ ("STEELBLUE4", 54, 100, 139),
+ ("DEEPSKYBLUE1", 0, 191, 255),
+ ("DEEPSKYBLUE2", 0, 178, 238),
+ ("DEEPSKYBLUE3", 0, 154, 205),
+ ("DEEPSKYBLUE4", 0, 104, 139),
+ ("SKYBLUE1", 135, 206, 255),
+ ("SKYBLUE2", 126, 192, 238),
+ ("SKYBLUE3", 108, 166, 205),
+ ("SKYBLUE4", 74, 112, 139),
+ ("LIGHTSKYBLUE1", 176, 226, 255),
+ ("LIGHTSKYBLUE2", 164, 211, 238),
+ ("LIGHTSKYBLUE3", 141, 182, 205),
+ ("LIGHTSKYBLUE4", 96, 123, 139),
+ ("LIGHTSTEELBLUE1", 202, 225, 255),
+ ("LIGHTSTEELBLUE2", 188, 210, 238),
+ ("LIGHTSTEELBLUE3", 162, 181, 205),
+ ("LIGHTSTEELBLUE4", 110, 123, 139),
+ ("LIGHTBLUE1", 191, 239, 255),
+ ("LIGHTBLUE2", 178, 223, 238),
+ ("LIGHTBLUE3", 154, 192, 205),
+ ("LIGHTBLUE4", 104, 131, 139),
+ ("LIGHTCYAN1", 224, 255, 255),
+ ("LIGHTCYAN2", 209, 238, 238),
+ ("LIGHTCYAN3", 180, 205, 205),
+ ("LIGHTCYAN4", 122, 139, 139),
+ ("PALETURQUOISE1", 187, 255, 255),
+ ("PALETURQUOISE2", 174, 238, 238),
+ ("PALETURQUOISE3", 150, 205, 205),
+ ("PALETURQUOISE4", 102, 139, 139),
+ ("CADETBLUE1", 152, 245, 255),
+ ("CADETBLUE2", 142, 229, 238),
+ ("CADETBLUE3", 122, 197, 205),
+ ("CADETBLUE4", 83, 134, 139),
+ ("TURQUOISE1", 0, 245, 255),
+ ("TURQUOISE2", 0, 229, 238),
+ ("TURQUOISE3", 0, 197, 205),
+ ("TURQUOISE4", 0, 134, 139),
+ ("CYAN1", 0, 255, 255),
+ ("CYAN2", 0, 238, 238),
+ ("CYAN3", 0, 205, 205),
+ ("CYAN4", 0, 139, 139),
+ ("AQUAMARINE1", 127, 255, 212),
+ ("AQUAMARINE2", 118, 238, 198),
+ ("AQUAMARINE3", 102, 205, 170),
+ ("AQUAMARINE4", 69, 139, 116),
+ ("DARKSEAGREEN1", 193, 255, 193),
+ ("DARKSEAGREEN2", 180, 238, 180),
+ ("DARKSEAGREEN3", 155, 205, 155),
+ ("DARKSEAGREEN4", 105, 139, 105),
+ ("SEAGREEN1", 84, 255, 159),
+ ("SEAGREEN2", 78, 238, 148),
+ ("SEAGREEN3", 67, 205, 128),
+ ("SEAGREEN4", 46, 139, 87),
+ ("PALEGREEN1", 154, 255, 154),
+ ("PALEGREEN2", 144, 238, 144),
+ ("PALEGREEN3", 124, 205, 124),
+ ("PALEGREEN4", 84, 139, 84),
+ ("SPRINGGREEN1", 0, 255, 127),
+ ("SPRINGGREEN2", 0, 238, 118),
+ ("SPRINGGREEN3", 0, 205, 102),
+ ("SPRINGGREEN4", 0, 139, 69),
+ ("GREEN1", 0, 255, 0),
+ ("GREEN2", 0, 238, 0),
+ ("GREEN3", 0, 205, 0),
+ ("GREEN4", 0, 139, 0),
+ ("CHARTREUSE1", 127, 255, 0),
+ ("CHARTREUSE2", 118, 238, 0),
+ ("CHARTREUSE3", 102, 205, 0),
+ ("CHARTREUSE4", 69, 139, 0),
+ ("OLIVEDRAB1", 192, 255, 62),
+ ("OLIVEDRAB2", 179, 238, 58),
+ ("OLIVEDRAB3", 154, 205, 50),
+ ("OLIVEDRAB4", 105, 139, 34),
+ ("DARKOLIVEGREEN1", 202, 255, 112),
+ ("DARKOLIVEGREEN2", 188, 238, 104),
+ ("DARKOLIVEGREEN3", 162, 205, 90),
+ ("DARKOLIVEGREEN4", 110, 139, 61),
+ ("KHAKI1", 255, 246, 143),
+ ("KHAKI2", 238, 230, 133),
+ ("KHAKI3", 205, 198, 115),
+ ("KHAKI4", 139, 134, 78),
+ ("LIGHTGOLDENROD1", 255, 236, 139),
+ ("LIGHTGOLDENROD2", 238, 220, 130),
+ ("LIGHTGOLDENROD3", 205, 190, 112),
+ ("LIGHTGOLDENROD4", 139, 129, 76),
+ ("LIGHTYELLOW1", 255, 255, 224),
+ ("LIGHTYELLOW2", 238, 238, 209),
+ ("LIGHTYELLOW3", 205, 205, 180),
+ ("LIGHTYELLOW4", 139, 139, 122),
+ ("YELLOW1", 255, 255, 0),
+ ("YELLOW2", 238, 238, 0),
+ ("YELLOW3", 205, 205, 0),
+ ("YELLOW4", 139, 139, 0),
+ ("GOLD1", 255, 215, 0),
+ ("GOLD2", 238, 201, 0),
+ ("GOLD3", 205, 173, 0),
+ ("GOLD4", 139, 117, 0),
+ ("GOLDENROD1", 255, 193, 37),
+ ("GOLDENROD2", 238, 180, 34),
+ ("GOLDENROD3", 205, 155, 29),
+ ("GOLDENROD4", 139, 105, 20),
+ ("DARKGOLDENROD1", 255, 185, 15),
+ ("DARKGOLDENROD2", 238, 173, 14),
+ ("DARKGOLDENROD3", 205, 149, 12),
+ ("DARKGOLDENROD4", 139, 101, 8),
+ ("ROSYBROWN1", 255, 193, 193),
+ ("ROSYBROWN2", 238, 180, 180),
+ ("ROSYBROWN3", 205, 155, 155),
+ ("ROSYBROWN4", 139, 105, 105),
+ ("INDIANRED1", 255, 106, 106),
+ ("INDIANRED2", 238, 99, 99),
+ ("INDIANRED3", 205, 85, 85),
+ ("INDIANRED4", 139, 58, 58),
+ ("SIENNA1", 255, 130, 71),
+ ("SIENNA2", 238, 121, 66),
+ ("SIENNA3", 205, 104, 57),
+ ("SIENNA4", 139, 71, 38),
+ ("BURLYWOOD1", 255, 211, 155),
+ ("BURLYWOOD2", 238, 197, 145),
+ ("BURLYWOOD3", 205, 170, 125),
+ ("BURLYWOOD4", 139, 115, 85),
+ ("WHEAT1", 255, 231, 186),
+ ("WHEAT2", 238, 216, 174),
+ ("WHEAT3", 205, 186, 150),
+ ("WHEAT4", 139, 126, 102),
+ ("TAN1", 255, 165, 79),
+ ("TAN2", 238, 154, 73),
+ ("TAN3", 205, 133, 63),
+ ("TAN4", 139, 90, 43),
+ ("CHOCOLATE1", 255, 127, 36),
+ ("CHOCOLATE2", 238, 118, 33),
+ ("CHOCOLATE3", 205, 102, 29),
+ ("CHOCOLATE4", 139, 69, 19),
+ ("FIREBRICK1", 255, 48, 48),
+ ("FIREBRICK2", 238, 44, 44),
+ ("FIREBRICK3", 205, 38, 38),
+ ("FIREBRICK4", 139, 26, 26),
+ ("BROWN1", 255, 64, 64),
+ ("BROWN2", 238, 59, 59),
+ ("BROWN3", 205, 51, 51),
+ ("BROWN4", 139, 35, 35),
+ ("SALMON1", 255, 140, 105),
+ ("SALMON2", 238, 130, 98),
+ ("SALMON3", 205, 112, 84),
+ ("SALMON4", 139, 76, 57),
+ ("LIGHTSALMON1", 255, 160, 122),
+ ("LIGHTSALMON2", 238, 149, 114),
+ ("LIGHTSALMON3", 205, 129, 98),
+ ("LIGHTSALMON4", 139, 87, 66),
+ ("ORANGE1", 255, 165, 0),
+ ("ORANGE2", 238, 154, 0),
+ ("ORANGE3", 205, 133, 0),
+ ("ORANGE4", 139, 90, 0),
+ ("DARKORANGE1", 255, 127, 0),
+ ("DARKORANGE2", 238, 118, 0),
+ ("DARKORANGE3", 205, 102, 0),
+ ("DARKORANGE4", 139, 69, 0),
+ ("CORAL1", 255, 114, 86),
+ ("CORAL2", 238, 106, 80),
+ ("CORAL3", 205, 91, 69),
+ ("CORAL4", 139, 62, 47),
+ ("TOMATO1", 255, 99, 71),
+ ("TOMATO2", 238, 92, 66),
+ ("TOMATO3", 205, 79, 57),
+ ("TOMATO4", 139, 54, 38),
+ ("ORANGERED1", 255, 69, 0),
+ ("ORANGERED2", 238, 64, 0),
+ ("ORANGERED3", 205, 55, 0),
+ ("ORANGERED4", 139, 37, 0),
+ ("RED1", 255, 0, 0),
+ ("RED2", 238, 0, 0),
+ ("RED3", 205, 0, 0),
+ ("RED4", 139, 0, 0),
+ ("DEEPPINK1", 255, 20, 147),
+ ("DEEPPINK2", 238, 18, 137),
+ ("DEEPPINK3", 205, 16, 118),
+ ("DEEPPINK4", 139, 10, 80),
+ ("HOTPINK1", 255, 110, 180),
+ ("HOTPINK2", 238, 106, 167),
+ ("HOTPINK3", 205, 96, 144),
+ ("HOTPINK4", 139, 58, 98),
+ ("PINK1", 255, 181, 197),
+ ("PINK2", 238, 169, 184),
+ ("PINK3", 205, 145, 158),
+ ("PINK4", 139, 99, 108),
+ ("LIGHTPINK1", 255, 174, 185),
+ ("LIGHTPINK2", 238, 162, 173),
+ ("LIGHTPINK3", 205, 140, 149),
+ ("LIGHTPINK4", 139, 95, 101),
+ ("PALEVIOLETRED1", 255, 130, 171),
+ ("PALEVIOLETRED2", 238, 121, 159),
+ ("PALEVIOLETRED3", 205, 104, 137),
+ ("PALEVIOLETRED4", 139, 71, 93),
+ ("MAROON1", 255, 52, 179),
+ ("MAROON2", 238, 48, 167),
+ ("MAROON3", 205, 41, 144),
+ ("MAROON4", 139, 28, 98),
+ ("VIOLETRED1", 255, 62, 150),
+ ("VIOLETRED2", 238, 58, 140),
+ ("VIOLETRED3", 205, 50, 120),
+ ("VIOLETRED4", 139, 34, 82),
+ ("MAGENTA1", 255, 0, 255),
+ ("MAGENTA2", 238, 0, 238),
+ ("MAGENTA3", 205, 0, 205),
+ ("MAGENTA4", 139, 0, 139),
+ ("ORCHID1", 255, 131, 250),
+ ("ORCHID2", 238, 122, 233),
+ ("ORCHID3", 205, 105, 201),
+ ("ORCHID4", 139, 71, 137),
+ ("PLUM1", 255, 187, 255),
+ ("PLUM2", 238, 174, 238),
+ ("PLUM3", 205, 150, 205),
+ ("PLUM4", 139, 102, 139),
+ ("MEDIUMORCHID1", 224, 102, 255),
+ ("MEDIUMORCHID2", 209, 95, 238),
+ ("MEDIUMORCHID3", 180, 82, 205),
+ ("MEDIUMORCHID4", 122, 55, 139),
+ ("DARKORCHID1", 191, 62, 255),
+ ("DARKORCHID2", 178, 58, 238),
+ ("DARKORCHID3", 154, 50, 205),
+ ("DARKORCHID4", 104, 34, 139),
+ ("PURPLE1", 155, 48, 255),
+ ("PURPLE2", 145, 44, 238),
+ ("PURPLE3", 125, 38, 205),
+ ("PURPLE4", 85, 26, 139),
+ ("MEDIUMPURPLE1", 171, 130, 255),
+ ("MEDIUMPURPLE2", 159, 121, 238),
+ ("MEDIUMPURPLE3", 137, 104, 205),
+ ("MEDIUMPURPLE4", 93, 71, 139),
+ ("THISTLE1", 255, 225, 255),
+ ("THISTLE2", 238, 210, 238),
+ ("THISTLE3", 205, 181, 205),
+ ("THISTLE4", 139, 123, 139),
+ ("GREY0", 0, 0, 0),
+ ("GREY1", 3, 3, 3),
+ ("GREY2", 5, 5, 5),
+ ("GREY3", 8, 8, 8),
+ ("GREY4", 10, 10, 10),
+ ("GREY5", 13, 13, 13),
+ ("GREY6", 15, 15, 15),
+ ("GREY7", 18, 18, 18),
+ ("GREY8", 20, 20, 20),
+ ("GREY9", 23, 23, 23),
+ ("GREY10", 26, 26, 26),
+ ("GREY11", 28, 28, 28),
+ ("GREY12", 31, 31, 31),
+ ("GREY13", 33, 33, 33),
+ ("GREY14", 36, 36, 36),
+ ("GREY15", 38, 38, 38),
+ ("GREY16", 41, 41, 41),
+ ("GREY17", 43, 43, 43),
+ ("GREY18", 46, 46, 46),
+ ("GREY19", 48, 48, 48),
+ ("GREY20", 51, 51, 51),
+ ("GREY21", 54, 54, 54),
+ ("GREY22", 56, 56, 56),
+ ("GREY23", 59, 59, 59),
+ ("GREY24", 61, 61, 61),
+ ("GREY25", 64, 64, 64),
+ ("GREY26", 66, 66, 66),
+ ("GREY27", 69, 69, 69),
+ ("GREY28", 71, 71, 71),
+ ("GREY29", 74, 74, 74),
+ ("GREY30", 77, 77, 77),
+ ("GREY31", 79, 79, 79),
+ ("GREY32", 82, 82, 82),
+ ("GREY33", 84, 84, 84),
+ ("GREY34", 87, 87, 87),
+ ("GREY35", 89, 89, 89),
+ ("GREY36", 92, 92, 92),
+ ("GREY37", 94, 94, 94),
+ ("GREY38", 97, 97, 97),
+ ("GREY39", 99, 99, 99),
+ ("GREY40", 102, 102, 102),
+ ("GREY41", 105, 105, 105),
+ ("GREY42", 107, 107, 107),
+ ("GREY43", 110, 110, 110),
+ ("GREY44", 112, 112, 112),
+ ("GREY45", 115, 115, 115),
+ ("GREY46", 117, 117, 117),
+ ("GREY47", 120, 120, 120),
+ ("GREY48", 122, 122, 122),
+ ("GREY49", 125, 125, 125),
+ ("GREY50", 127, 127, 127),
+ ("GREY51", 130, 130, 130),
+ ("GREY52", 133, 133, 133),
+ ("GREY53", 135, 135, 135),
+ ("GREY54", 138, 138, 138),
+ ("GREY55", 140, 140, 140),
+ ("GREY56", 143, 143, 143),
+ ("GREY57", 145, 145, 145),
+ ("GREY58", 148, 148, 148),
+ ("GREY59", 150, 150, 150),
+ ("GREY60", 153, 153, 153),
+ ("GREY61", 156, 156, 156),
+ ("GREY62", 158, 158, 158),
+ ("GREY63", 161, 161, 161),
+ ("GREY64", 163, 163, 163),
+ ("GREY65", 166, 166, 166),
+ ("GREY66", 168, 168, 168),
+ ("GREY67", 171, 171, 171),
+ ("GREY68", 173, 173, 173),
+ ("GREY69", 176, 176, 176),
+ ("GREY70", 179, 179, 179),
+ ("GREY71", 181, 181, 181),
+ ("GREY72", 184, 184, 184),
+ ("GREY73", 186, 186, 186),
+ ("GREY74", 189, 189, 189),
+ ("GREY75", 191, 191, 191),
+ ("GREY76", 194, 194, 194),
+ ("GREY77", 196, 196, 196),
+ ("GREY78", 199, 199, 199),
+ ("GREY79", 201, 201, 201),
+ ("GREY80", 204, 204, 204),
+ ("GREY81", 207, 207, 207),
+ ("GREY82", 209, 209, 209),
+ ("GREY83", 212, 212, 212),
+ ("GREY84", 214, 214, 214),
+ ("GREY85", 217, 217, 217),
+ ("GREY86", 219, 219, 219),
+ ("GREY87", 222, 222, 222),
+ ("GREY88", 224, 224, 224),
+ ("GREY89", 227, 227, 227),
+ ("GREY90", 229, 229, 229),
+ ("GREY91", 232, 232, 232),
+ ("GREY92", 235, 235, 235),
+ ("GREY93", 237, 237, 237),
+ ("GREY94", 240, 240, 240),
+ ("GREY95", 242, 242, 242),
+ ("GREY96", 245, 245, 245),
+ ("GREY97", 247, 247, 247),
+ ("GREY98", 250, 250, 250),
+ ("GREY99", 252, 252, 252),
+ ("GREY100", 255, 255, 255),
+ ("DARK GREY", 169, 169, 169),
+ ("DARKGREY", 169, 169, 169),
+ ("DARK BLUE", 0, 0, 139),
+ ("DARKBLUE", 0, 0, 139),
+ ("DARK CYAN", 0, 139, 139),
+ ("DARKCYAN", 0, 139, 139),
+ ("DARK MAGENTA", 139, 0, 139),
+ ("DARKMAGENTA", 139, 0, 139),
+ ("DARK RED", 139, 0, 0),
+ ("DARKRED", 139, 0, 0),
+ ("LIGHT GREEN", 144, 238, 144),
+ ("LIGHTGREEN", 144, 238, 144),
+ ]
+
+
+_haveUpdated = False
+
+def updateColourDB():
+ """Updates the wx colour database by adding new colour names and RGB values."""
+ global _haveUpdated
+ if not _haveUpdated:
+ import wx
+ assert wx.GetApp() is not None, "You must have a wx.App object before you can use the colour database."
+ cl = getColourInfoList()
+
+ for info in cl:
+ wx.TheColourDatabase.Append(*info)
+
+ _haveUpdated = True
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourselect.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourselect.py
new file mode 100644
index 0000000..a41c5fd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourselect.py
@@ -0,0 +1,176 @@
+#----------------------------------------------------------------------------
+# Name: ColourSelect.py
+# Purpose: Colour Box Selection Control
+#
+# Author: Lorne White, Lorne.White@telusplanet.net
+#
+# Created: Feb 25, 2001
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+# creates a colour wxButton with selectable color
+# button click provides a colour selection box
+# button colour will change to new colour
+# GetColour method to get the selected colour
+
+# Updates:
+# call back to function if changes made
+
+# Cliff Wells, logiplexsoftware@earthlink.net:
+# - Made ColourSelect into "is a button" rather than "has a button"
+# - Added label parameter and logic to adjust the label colour according to the background
+# colour
+# - Added id argument
+# - Rearranged arguments to more closely follow wx conventions
+# - Simplified some of the code
+
+# Cliff Wells, 2002/02/07
+# - Added ColourSelect Event
+
+# 12/01/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for 2.5 compatability.
+#
+
+"""
+Provides a `ColourSelect` button that, when clicked, will display a
+colour selection dialog. The selected colour is displayed on the
+button itself.
+"""
+
+#----------------------------------------------------------------------------
+
+import wx
+
+#----------------------------------------------------------------------------
+
+wxEVT_COMMAND_COLOURSELECT = wx.NewEventType()
+
+class ColourSelectEvent(wx.PyCommandEvent):
+ def __init__(self, id, value):
+ wx.PyCommandEvent.__init__(self, id = id)
+ self.SetEventType(wxEVT_COMMAND_COLOURSELECT)
+ self.value = value
+
+ def GetValue(self):
+ return self.value
+
+EVT_COLOURSELECT = wx.PyEventBinder(wxEVT_COMMAND_COLOURSELECT, 1)
+
+#----------------------------------------------------------------------------
+
+class ColourSelect(wx.BitmapButton):
+ def __init__(self, parent, id=wx.ID_ANY, label="", colour=wx.BLACK,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ callback=None, style=0):
+ size = wx.Size(*size)
+ if label:
+ mdc = wx.MemoryDC(wx.EmptyBitmap(1,1))
+ w, h = mdc.GetTextExtent(label)
+ w += 6
+ h += 6
+ else:
+ w, h = 20, 20
+ size.width = size.width if size.width != -1 else w
+ size.height = size.height if size.height != -1 else h
+ wx.BitmapButton.__init__(self, parent, id, wx.EmptyBitmap(w,h),
+ pos=pos, size=size, style=style|wx.BU_AUTODRAW)
+
+ if type(colour) == type( () ):
+ colour = wx.Colour(*colour)
+ self.colour = colour
+ self.SetLabel(label)
+ self.callback = callback
+ bmp = self.MakeBitmap()
+ self.SetBitmap(bmp)
+ parent.Bind(wx.EVT_BUTTON, self.OnClick, self)
+
+
+ def GetColour(self):
+ return self.colour
+
+ def GetValue(self):
+ return self.colour
+
+ def SetValue(self, colour):
+ self.SetColour(colour)
+
+ def SetColour(self, colour):
+ if type(colour) == tuple:
+ colour = wx.Colour(*colour)
+ if type(colour) == str:
+ colour = wx.NamedColour(colour)
+
+ self.colour = colour
+ bmp = self.MakeBitmap()
+ self.SetBitmap(bmp)
+
+
+ def SetLabel(self, label):
+ self.label = label
+
+ def GetLabel(self):
+ return self.label
+
+
+ def MakeBitmap(self):
+ bdr = 8
+ width, height = self.GetSize()
+
+ # yes, this is weird, but it appears to work around a bug in wxMac
+ if "wxMac" in wx.PlatformInfo and width == height:
+ height -= 1
+
+ bmp = wx.EmptyBitmap(width-bdr, height-bdr)
+ dc = wx.MemoryDC()
+ dc.SelectObject(bmp)
+ dc.SetFont(self.GetFont())
+ label = self.GetLabel()
+ # Just make a little colored bitmap
+ dc.SetBackground(wx.Brush(self.colour))
+ dc.Clear()
+
+ if label:
+ # Add a label to it
+ avg = reduce(lambda a, b: a + b, self.colour.Get()) / 3
+ fcolour = avg > 128 and wx.BLACK or wx.WHITE
+ dc.SetTextForeground(fcolour)
+ dc.DrawLabel(label, (0,0, width-bdr, height-bdr),
+ wx.ALIGN_CENTER)
+
+ dc.SelectObject(wx.NullBitmap)
+ return bmp
+
+
+ def SetBitmap(self, bmp):
+ self.SetBitmapLabel(bmp)
+ #self.SetBitmapSelected(bmp)
+ #self.SetBitmapDisabled(bmp)
+ #self.SetBitmapFocus(bmp)
+ #self.SetBitmapSelected(bmp)
+ self.Refresh()
+
+
+ def OnChange(self):
+ evt = ColourSelectEvent(self.GetId(), self.GetValue())
+ evt.SetEventObject(self)
+ wx.PostEvent(self, evt)
+ if self.callback is not None:
+ self.callback()
+
+ def OnClick(self, event):
+ data = wx.ColourData()
+ data.SetChooseFull(True)
+ data.SetColour(self.colour)
+ dlg = wx.ColourDialog(wx.GetTopLevelParent(self), data)
+ changed = dlg.ShowModal() == wx.ID_OK
+
+ if changed:
+ data = dlg.GetColourData()
+ self.SetColour(data.GetColour())
+ dlg.Destroy()
+
+ # moved after dlg.Destroy, since who knows what the callback will do...
+ if changed:
+ self.OnChange()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourutils.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourutils.py
new file mode 100644
index 0000000..619f78f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/colourutils.py
@@ -0,0 +1,92 @@
+"""
+Some useful colour-related utility functions.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: $"
+__revision__ = "$Revision: $"
+
+import wx
+
+# Used on OSX to get access to carbon api constants
+if wx.Platform == '__WXMAC__':
+ try:
+ import Carbon.Appearance
+ except ImportError:
+ CARBON = False
+ else:
+ CARBON = True
+
+#-----------------------------------------------------------------------------#
+
+def AdjustAlpha(colour, alpha):
+ """Adjust the alpha of a given colour"""
+ return wx.Colour(colour.Red(), colour.Green(), colour.Blue(), alpha)
+
+
+def AdjustColour(color, percent, alpha=wx.ALPHA_OPAQUE):
+ """
+ Brighten/Darken input colour by percent and adjust alpha
+ channel if needed. Returns the modified color.
+
+ :param Colour `color`: color object to adjust
+ :param integer `percent`: percent to adjust +(brighten) or -(darken)
+ :keyword `alpha`: amount to adjust alpha channel
+
+ """
+ radj, gadj, badj = [ int(val * (abs(percent) / 100.))
+ for val in color.Get() ]
+
+ if percent < 0:
+ radj, gadj, badj = [ val * -1 for val in [radj, gadj, badj] ]
+ else:
+ radj, gadj, badj = [ val or 255 for val in [radj, gadj, badj] ]
+
+ red = min(color.Red() + radj, 255)
+ green = min(color.Green() + gadj, 255)
+ blue = min(color.Blue() + badj, 255)
+ return wx.Colour(red, green, blue, alpha)
+
+
+def BestLabelColour(color, bw=False):
+ """
+ Get the best color to use for the label that will be drawn on
+ top of the given color.
+
+ :param Colour `color`: background color that text will be drawn on
+ :keyword `bw`: If True, only return black or white
+
+ """
+ avg = sum(color.Get()) / 3
+ if avg > 192:
+ txt_color = wx.BLACK
+ elif avg > 128:
+ if bw: txt_color = wx.BLACK
+ else: txt_color = AdjustColour(color, -95)
+ elif avg < 64:
+ txt_color = wx.WHITE
+ else:
+ if bw: txt_color = wx.WHITE
+ else: txt_color = AdjustColour(color, 95)
+ return txt_color
+
+def GetHighlightColour():
+ """Get the default highlight color
+
+ :return: :class:`Colour`
+
+ """
+ if wx.Platform == '__WXMAC__':
+ if CARBON:
+ if wx.VERSION < (2, 9, 0, 0, ''):
+ # kThemeBrushButtonPressedLightHighlight
+ brush = wx.Brush(wx.BLACK)
+ brush.MacSetTheme(Carbon.Appearance.kThemeBrushFocusHighlight)
+ return brush.GetColour()
+ else:
+ color = wx.MacThemeColour(Carbon.Appearance.kThemeBrushFocusHighlight)
+ return color
+
+ # Fallback to text highlight color
+ return wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/combotreebox.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/combotreebox.py
new file mode 100644
index 0000000..945401d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/combotreebox.py
@@ -0,0 +1,927 @@
+"""
+ComboTreeBox provides a ComboBox that pops up a tree instead of a list.
+
+ComboTreeBox tries to provide the same interface as :class:`ComboBox` as much as
+possible. However, whereas the ComboBox widget uses indices to access
+items in the list of choices, ComboTreeBox uses TreeItemId's instead. If
+you add an item to the ComboTreeBox (using Append or Insert), the
+:class:`TreeItemId` associated with the added item is returned. You can then use
+that `TreeItemId` to add items as children of that first item. For
+example::
+
+ from wx.lib.combotreebox import ComboTreeBox
+ combo = ComboTreeBox(parent)
+ item1 = combo.Append('Item 1') # Add a root item
+ item1a = combo.Append('Item 1a', parent=item1) # Add a child to item1
+
+
+You can also add client data to each of the items like this::
+
+ item1 = combo.Append('Item 1', clientData=somePythonObject)
+ item1a = combo.Append('Item 1a', parent=item1,
+ clientData=someOtherPythonObject)
+
+
+And later fetch the client data like this::
+
+ somePythonObject = combo.GetClientData(item1)
+
+
+To get the client data of the currently selected item (if any)::
+
+ currentItem = combo.GetSelection()
+ if currentItem:
+ somePythonObject = combo.GetClientData(currentItem)
+
+
+Supported styles are the same as for :class:`ComboBox`, i.e. ``wx.CB_READONLY`` and
+``wx.CB_SORT``. Provide them as usual::
+
+ combo = ComboTreeBox(parent, style=wx.CB_READONLY|wx.CB_SORT)
+
+
+Supported platforms: wxMSW and wxMAC natively, wxGTK by means of a
+workaround.
+
+.. moduleauthor:: Frank Niessink <frank@niessink.com>
+
+Copyright 2006, 2008, 2010, Frank Niessink
+License: wxWidgets license
+Version: 1.1
+Date: August 1, 2010
+
+"""
+
+import wx
+
+__all__ = ['ComboTreeBox'] # Export only the ComboTreeBox widget
+
+
+# ---------------------------------------------------------------------------
+
+
+class IterableTreeCtrl(wx.TreeCtrl):
+ """
+ TreeCtrl is the same as :class:`TreeCtrl`, with a few convenience methods
+ added for easier navigation of items. """
+
+ def GetPreviousItem(self, item):
+ """
+ Returns the item that is on the line immediately above item
+ (as is displayed when the tree is fully expanded). The returned
+ item is invalid if item is the first item in the tree.
+
+ :param TreeItemId `item`: a :class:`TreeItemId`
+ :return: the :class:`TreeItemId` previous to the one passed in or an invalid item
+ :rtype: :class:`TreeItemId`
+
+ """
+ previousSibling = self.GetPrevSibling(item)
+ if previousSibling:
+ return self.GetLastChildRecursively(previousSibling)
+ else:
+ parent = self.GetItemParent(item)
+ if parent == self.GetRootItem() and \
+ (self.GetWindowStyle() & wx.TR_HIDE_ROOT):
+ # Return an invalid item, because the root item is hidden
+ return previousSibling
+ else:
+ return parent
+
+ def GetNextItem(self, item):
+ """
+ Returns the item that is on the line immediately below item
+ (as is displayed when the tree is fully expanded). The returned
+ item is invalid if item is the last item in the tree.
+
+ :param TreeItemId `item`: a :class:`TreeItemId`
+ :return: :class:`TreeItemId` of the next item or an invalid item
+ :rtype: :class:`TreeItemId`
+
+ """
+ if self.ItemHasChildren(item):
+ firstChild, cookie = self.GetFirstChild(item)
+ return firstChild
+ else:
+ return self.GetNextSiblingRecursively(item)
+
+ def GetFirstItem(self):
+ """
+ Returns the very first item in the tree. This is the root item
+ unless the root item is hidden. In that case the first child of
+ the root item is returned, if any. If the tree is empty, an
+ invalid tree item is returned.
+
+ :return: :class:`TreeItemId`
+ :rtype: :class:`TreeItemId`
+
+ """
+ rootItem = self.GetRootItem()
+ if rootItem and (self.GetWindowStyle() & wx.TR_HIDE_ROOT):
+ firstChild, cookie = self.GetFirstChild(rootItem)
+ return firstChild
+ else:
+ return rootItem
+
+ def GetLastChildRecursively(self, item):
+ """
+ Returns the last child of the last child ... of item. If item
+ has no children, item itself is returned. So the returned item
+ is always valid, assuming a valid item has been passed.
+
+ :param TreeItemId `item`: a :class:`TreeItemId`
+ :return: :class:`TreeItemId` of the last item or an invalid item
+ :rtype: :class:`TreeItemId`
+
+ """
+ lastChild = item
+ while self.ItemHasChildren(lastChild):
+ lastChild = self.GetLastChild(lastChild)
+ return lastChild
+
+ def GetNextSiblingRecursively(self, item):
+ """
+ Returns the next sibling of item if it has one. If item has no
+ next sibling the next sibling of the parent of item is returned.
+ If the parent has no next sibling the next sibling of the parent
+ of the parent is returned, etc. If none of the ancestors of item
+ has a next sibling, an invalid item is returned.
+
+ :param TreeItemId `item`: a :class:`TreeItemId`
+ :return: :class:`TreeItemId` of the next item or an invalid item
+ :rtype: :class:`TreeItemId`
+
+ """
+ if item == self.GetRootItem():
+ return wx.TreeItemId() # Return an invalid TreeItemId
+ nextSibling = self.GetNextSibling(item)
+ if nextSibling:
+ return nextSibling
+ else:
+ parent = self.GetItemParent(item)
+ return self.GetNextSiblingRecursively(parent)
+
+ def GetSelection(self):
+ """
+ Extend GetSelection to never return the root item if the
+ root item is hidden.
+ """
+ selection = super(IterableTreeCtrl, self).GetSelection()
+ if selection == self.GetRootItem() and \
+ (self.GetWindowStyle() & wx.TR_HIDE_ROOT):
+ return wx.TreeItemId() # Return an invalid TreeItemId
+ else:
+ return selection
+
+
+# ---------------------------------------------------------------------------
+
+
+class BasePopupFrame(wx.Frame):
+ """
+ BasePopupFrame is the base class for platform specific versions of the
+ PopupFrame. The PopupFrame is the frame that is popped up by ComboTreeBox.
+ It contains the tree of items that the user can select one item from. Upon
+ selection, or when focus is lost, the frame is hidden.
+ """
+
+ def __init__(self, parent):
+ super(BasePopupFrame, self).__init__(parent,
+ style=wx.DEFAULT_FRAME_STYLE & wx.FRAME_FLOAT_ON_PARENT &
+ ~(wx.RESIZE_BORDER | wx.CAPTION))
+ self._createInterior()
+ self._layoutInterior()
+ self._bindEventHandlers()
+
+ def _createInterior(self):
+ self._tree = IterableTreeCtrl(self,
+ style=wx.TR_HIDE_ROOT|wx.TR_LINES_AT_ROOT|wx.TR_HAS_BUTTONS)
+ self._tree.AddRoot('Hidden root node')
+
+ def _layoutInterior(self):
+ frameSizer = wx.BoxSizer(wx.HORIZONTAL)
+ frameSizer.Add(self._tree, flag=wx.EXPAND, proportion=1)
+ self.SetSizerAndFit(frameSizer)
+
+ def _bindEventHandlers(self):
+ self._tree.Bind(wx.EVT_CHAR, self.OnChar)
+ self._tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated)
+ self._tree.Bind(wx.EVT_LEFT_DOWN, self.OnMouseClick)
+
+ def _bindKillFocus(self):
+ self._tree.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+ def _unbindKillFocus(self):
+ self._tree.Unbind(wx.EVT_KILL_FOCUS)
+
+ def OnKillFocus(self, event):
+ # We hide the frame rather than destroy it, so it can be
+ # popped up again later. Use CallAfter so that clicking the combobox
+ # button doesn't immediately popup the frame again.
+ wx.CallAfter(self.Hide)
+ self.GetParent().NotifyNoItemSelected()
+ event.Skip()
+
+ def OnChar(self, keyEvent):
+ if self._keyShouldHidePopup(keyEvent):
+ self.Hide()
+ self.GetParent().NotifyNoItemSelected()
+ keyEvent.Skip()
+
+ def _keyShouldHidePopup(self, keyEvent):
+ return keyEvent.GetKeyCode() == wx.WXK_ESCAPE
+
+ def OnMouseClick(self, event):
+ item, flags = self._tree.HitTest(event.GetPosition())
+ if item and (flags & wx.TREE_HITTEST_ONITEMLABEL):
+ self._tree.SelectItem(item)
+ self.Hide()
+ self.GetParent().NotifyItemSelected(self._tree.GetItemText(item))
+ else:
+ event.Skip()
+
+ def OnItemActivated(self, event):
+ item = event.GetItem()
+ self.Hide()
+ self.GetParent().NotifyItemSelected(self._tree.GetItemText(item))
+
+ def Show(self):
+ self._bindKillFocus()
+ wx.CallAfter(self._tree.SetFocus)
+ super(BasePopupFrame, self).Show()
+
+ def Hide(self):
+ self._unbindKillFocus()
+ super(BasePopupFrame, self).Hide()
+
+ def GetTree(self):
+ return self._tree
+
+
+class MSWPopupFrame(BasePopupFrame):
+ """MSWPopupFrame is the base class Windows PopupFrame."""
+ def Show(self):
+ # Comply with the MS Windows Combobox behaviour: if the text in
+ # the text field is not in the tree, the first item in the tree
+ # is selected.
+ if not self._tree.GetSelection():
+ self._tree.SelectItem(self._tree.GetFirstItem())
+ super(MSWPopupFrame, self).Show()
+
+
+class MACPopupFrame(BasePopupFrame):
+ """MacPopupFrame is the base class Mac PopupFrame."""
+ def _bindKillFocus(self):
+ # On wxMac, the kill focus event doesn't work, but the
+ # deactivate event does:
+ self.Bind(wx.EVT_ACTIVATE, self.OnKillFocus)
+
+ def _unbindKillFocus(self):
+ self.Unbind(wx.EVT_ACTIVATE)
+
+ def OnKillFocus(self, event):
+ if not event.GetActive(): # We received a deactivate event
+ self.Hide()
+ wx.CallAfter(self.GetParent().NotifyNoItemSelected)
+ event.Skip()
+
+
+class GTKPopupFrame(BasePopupFrame):
+ """GTKPopupFrame is the base class GTK PopupFrame."""
+ def _keyShouldHidePopup(self, keyEvent):
+ # On wxGTK, Alt-Up also closes the popup:
+ return super(GTKPopupFrame, self)._keyShouldHidePopup(keyEvent) or \
+ (keyEvent.AltDown() and keyEvent.GetKeyCode() == wx.WXK_UP)
+
+
+# ---------------------------------------------------------------------------
+
+
+class BaseComboTreeBox(object):
+ """
+ BaseComboTreeBox is the base class for platform specific versions of the
+ ComboTreeBox.
+ """
+
+ def __init__(self, *args, **kwargs):
+ style = kwargs.pop('style', 0)
+ if style & wx.CB_READONLY:
+ style &= ~wx.CB_READONLY # We manage readonlyness ourselves
+ self._readOnly = True
+ else:
+ self._readOnly = False
+ if style & wx.CB_SORT:
+ style &= ~wx.CB_SORT # We manage sorting ourselves
+ self._sort = True
+ else:
+ self._sort = False
+ super(BaseComboTreeBox, self).__init__(style=style, *args, **kwargs)
+ self._createInterior()
+ self._layoutInterior()
+ self._bindEventHandlers()
+
+ # Methods to construct the widget.
+
+ def _createInterior(self):
+ self._popupFrame = self._createPopupFrame()
+ self._text = self._createTextCtrl()
+ self._button = self._createButton()
+ self._tree = self._popupFrame.GetTree()
+
+ def _createTextCtrl(self):
+ return self # By default, the text control is the control itself.
+
+ def _createButton(self):
+ return self # By default, the dropdown button is the control itself.
+
+ def _createPopupFrame(self):
+ # It is a subclass responsibility to provide the right PopupFrame,
+ # depending on platform:
+ raise NotImplementedError
+
+ def _layoutInterior(self):
+ pass # By default, there is no layout to be done.
+
+ def _bindEventHandlers(self):
+ for eventSource, eventType, eventHandler in self._eventsToBind():
+ eventSource.Bind(eventType, eventHandler)
+
+ def _eventsToBind(self):
+ """
+ _eventsToBind returns a list of eventSource, eventType,
+ eventHandlers tuples that will be bound. This method can be
+ extended to bind additional events. In that case, don't
+ forget to call _eventsToBind on the super class.
+
+ :return: [(eventSource, eventType, eventHandlers), ]
+ :rtype: list
+
+ """
+ return [(self._text, wx.EVT_KEY_DOWN, self.OnKeyDown),
+ (self._text, wx.EVT_TEXT, self.OnText),
+ (self._button, wx.EVT_BUTTON, self.OnMouseClick)]
+
+ # Event handlers
+
+ def OnMouseClick(self, event):
+ if self._popupFrame.IsShown():
+ self.Hide()
+ else:
+ self.Popup()
+ # Note that we don't call event.Skip() to prevent popping up the
+ # ComboBox's own box.
+
+ def OnKeyDown(self, keyEvent):
+ if self._keyShouldNavigate(keyEvent):
+ self._navigateUpOrDown(keyEvent)
+ elif self._keyShouldPopUpTree(keyEvent):
+ self.Popup()
+ else:
+ keyEvent.Skip()
+
+ def _keyShouldPopUpTree(self, keyEvent):
+ return (keyEvent.AltDown() or keyEvent.MetaDown()) and \
+ keyEvent.GetKeyCode() == wx.WXK_DOWN
+
+ def _keyShouldNavigate(self, keyEvent):
+ return keyEvent.GetKeyCode() in (wx.WXK_DOWN, wx.WXK_UP) and not \
+ self._keyShouldPopUpTree(keyEvent)
+
+ def _navigateUpOrDown(self, keyEvent):
+ item = self.GetSelection()
+ if item:
+ navigationMethods = {wx.WXK_DOWN: self._tree.GetNextItem,
+ wx.WXK_UP: self._tree.GetPreviousItem}
+ getNextItem = navigationMethods[keyEvent.GetKeyCode()]
+ nextItem = getNextItem(item)
+ else:
+ nextItem = self._tree.GetFirstItem()
+ if nextItem:
+ self.SetSelection(nextItem)
+
+ def OnText(self, event):
+ event.Skip()
+ textValue = self._text.GetValue()
+ selection = self._tree.GetSelection()
+ if not selection or self._tree.GetItemText(selection) != textValue:
+ # We need to change the selection because it doesn't match the
+ # text just entered
+ item = self.FindString(textValue)
+ if item:
+ self._tree.SelectItem(item)
+ else:
+ self._tree.Unselect()
+
+ # Methods called by the PopupFrame, to let the ComboTreeBox know
+ # about what the user did.
+
+ def NotifyItemSelected(self, text):
+ """
+ Simulate selection of an item by the user. This is meant to
+ be called by the PopupFrame when the user selects an item.
+ """
+ self._text.SetValue(text)
+ self._postComboBoxSelectedEvent(text)
+ self.SetFocus()
+
+ def _postComboBoxSelectedEvent(self, text):
+ """Simulate a selection event. """
+ event = wx.CommandEvent(wx.wxEVT_COMMAND_COMBOBOX_SELECTED,
+ self.GetId())
+ event.SetString(text)
+ self.GetEventHandler().ProcessEvent(event)
+
+ def NotifyNoItemSelected(self):
+ """
+ This is called by the PopupFrame when the user closes the
+ PopupFrame, without selecting an item.
+ """
+ self.SetFocus()
+
+ # Misc methods, not part of the ComboBox API.
+
+ def Popup(self):
+ """Pops up the frame with the tree."""
+ comboBoxSize = self.GetSize()
+ x, y = self.GetParent().ClientToScreen(self.GetPosition())
+ y += comboBoxSize[1]
+ width = comboBoxSize[0]
+ height = 300
+ self._popupFrame.SetDimensions(x, y, width, height)
+ # On wxGTK, when the Combobox width has been increased a call
+ # to SetMinSize is needed to force a resize of the popupFrame:
+ self._popupFrame.SetMinSize((width, height))
+ self._popupFrame.Show()
+
+ def Hide(self):
+ """Hide the popped up frame with the tree."""
+ self._popupFrame.Hide()
+
+ def GetTree(self):
+ """Returns the tree control that is popped up."""
+ return self._popupFrame.GetTree()
+
+ def FindClientData(self, clientData, parent=None):
+ """
+ Finds the *first* item in the tree with client data equal to the
+ given clientData. If no such item exists, an invalid item is
+ returned.
+
+ :param PyObject `clientData`: the client data to find
+ :keyword TreeItemId `parent`: :class:`TreeItemId` parent or None
+ :return: :class:`TreeItemId`
+ :rtype: :class:`TreeItemId`
+
+ """
+ parent = parent or self._tree.GetRootItem()
+ child, cookie = self._tree.GetFirstChild(parent)
+ while child:
+ if self.GetClientData(child) == clientData:
+ return child
+ else:
+ result = self.FindClientData(clientData, child)
+ if result:
+ return result
+ child, cookie = self._tree.GetNextChild(parent, cookie)
+ return child
+
+ def SetClientDataSelection(self, clientData):
+ """
+ Selects the item with the provided clientData in the control.
+ Returns True if the item belonging to the clientData has been
+ selected, False if it wasn't found in the control.
+
+ :param PyObject `clientData`: the client data to find
+ :return: True if an item has been selected, otherwise False
+ :rtype: bool
+
+ """
+ item = self.FindClientData(clientData)
+ if item:
+ self._tree.SelectItem(item)
+ string = self._tree.GetItemText(item)
+ if self._text.GetValue() != string:
+ self._text.SetValue(string)
+ return True
+ else:
+ return False
+
+ # The following methods are all part of the ComboBox API (actually
+ # the ControlWithItems API) and have been adapted to take TreeItemIds
+ # as parameter and return :class:`TreeItemId`s, rather than indices.
+
+ def Append(self, itemText, parent=None, clientData=None):
+ """
+ Adds the itemText to the control, associating the given clientData
+ with the item if not None. If parent is None, itemText is added
+ as a root item, else itemText is added as a child item of
+ parent. The return value is the :class:`TreeItemId` of the newly added
+ item.
+
+ :param string `itemText`: text to add to the control
+ :keyword TreeItemId `parent`: if None item is added as a root, else it
+ is added as a child of the parent.
+ :keyword PyObject `clientData`: the client data to find
+ :return: :class:`TreeItemId` of newly added item
+ :rtype: :class:`TreeItemId`
+
+ """
+ if parent is None:
+ parent = self._tree.GetRootItem()
+ item = self._tree.AppendItem(parent, itemText,
+ data=wx.TreeItemData(clientData))
+ if self._sort:
+ self._tree.SortChildren(parent)
+ return item
+
+ def Clear(self):
+ """Removes all items from the control."""
+ return self._tree.DeleteAllItems()
+
+ def Delete(self, item):
+ """Deletes the item from the control."""
+ return self._tree.Delete(item)
+
+ def FindString(self, string, parent=None):
+ """
+ Finds the *first* item in the tree with a label equal to the
+ given string. If no such item exists, an invalid item is
+ returned.
+
+ :param string `string`: string to be found in label
+ :keyword TreeItemId `parent`: :class:`TreeItemId` parent or None
+ :return: :class:`TreeItemId`
+ :rtype: :class:`TreeItemId`
+
+ """
+ parent = parent or self._tree.GetRootItem()
+ child, cookie = self._tree.GetFirstChild(parent)
+ while child:
+ if self._tree.GetItemText(child) == string:
+ return child
+ else:
+ result = self.FindString(string, child)
+ if result:
+ return result
+ child, cookie = self._tree.GetNextChild(parent, cookie)
+ return child
+
+ def GetSelection(self):
+ """
+ Returns the :class:`TreeItemId` of the selected item or an invalid item
+ if no item is selected.
+
+ :return: a TreeItemId
+ :rtype: :class:`TreeItemId`
+
+ """
+ selectedItem = self._tree.GetSelection()
+ if selectedItem and selectedItem != self._tree.GetRootItem():
+ return selectedItem
+ else:
+ return self.FindString(self.GetValue())
+
+ def GetString(self, item):
+ """
+ Returns the label of the given item.
+
+ :param TreeItemId `item`: :class:`TreeItemId` for which to get the label
+ :return: label
+ :rtype: string
+
+ """
+ if item:
+ return self._tree.GetItemText(item)
+ else:
+ return ''
+
+ def GetStringSelection(self):
+ """
+ Returns the label of the selected item or an empty string if no item
+ is selected.
+
+ :return: the label of the selected item or an empty string
+ :rtype: string
+
+ """
+ return self.GetValue()
+
+ def Insert(self, itemText, previous=None, parent=None, clientData=None):
+ """
+ Insert an item into the control before the ``previous`` item
+ and/or as child of the ``parent`` item. The itemText is associated
+ with clientData when not None.
+
+ :param string `itemText`: the items label
+ :keyword TreeItemId `previous`: the previous item
+ :keyword TreeItemId `parent`: the parent item
+ :keyword PyObject `clientData`: the data to associate
+ :return: the create :class:`TreeItemId`
+ :rtype: :class:`TreeItemId`
+
+ """
+ data = wx.TreeItemData(clientData)
+ if parent is None:
+ parent = self._tree.GetRootItem()
+ if previous is None:
+ item = self._tree.InsertItemBefore(parent, 0, itemText, data=data)
+ else:
+ item = self._tree.InsertItem(parent, previous, itemText, data=data)
+ if self._sort:
+ self._tree.SortChildren(parent)
+ return item
+
+ def IsEmpty(self):
+ """
+ Returns True if the control is empty or False if it has some items.
+
+ :return: True if control is empty
+ :rtype: boolean
+
+ """
+ return self.GetCount() == 0
+
+ def GetCount(self):
+ """
+ Returns the number of items in the control.
+
+ :return: items in control
+ :rtype: integer
+
+ """
+ # Note: We don't need to substract 1 for the hidden root item,
+ # because the TreeCtrl does that for us
+ return self._tree.GetCount()
+
+ def SetSelection(self, item):
+ """
+ Sets the provided item to be the selected item.
+
+ :param TreeItemId `item`: Select this item
+
+ """
+ self._tree.SelectItem(item)
+ self._text.SetValue(self._tree.GetItemText(item))
+
+ Select = SetSelection
+
+ def SetString(self, item, string):
+ """
+ Sets the label for the provided item.
+
+ :param TreeItemId `item`: item on which to set the label
+ :param string `string`: the label to set
+
+ """
+ self._tree.SetItemText(item, string)
+ if self._sort:
+ self._tree.SortChildren(self._tree.GetItemParent(item))
+
+ def SetStringSelection(self, string):
+ """
+ Selects the item with the provided string in the control.
+ Returns True if the provided string has been selected, False if
+ it wasn't found in the control.
+
+ :param string `string`: try to select the item with this string
+ :return: True if an item has been selected
+ :rtype: boolean
+
+ """
+ item = self.FindString(string)
+ if item:
+ if self._text.GetValue() != string:
+ self._text.SetValue(string)
+ self._tree.SelectItem(item)
+ return True
+ else:
+ return False
+
+ def GetClientData(self, item):
+ """
+ Returns the client data associated with the given item, if any.
+
+ :param TreeItemId `item`: item for which to get clientData
+ :return: the client data
+ :rtype: PyObject
+
+ """
+ return self._tree.GetItemPyData(item)
+
+ def SetClientData(self, item, clientData):
+ """
+ Associate the given client data with the provided item.
+
+ :param TreeItemId `item`: item for which to set the clientData
+ :param PyObject `clientData`: the data to set
+
+ """
+ self._tree.SetItemPyData(item, clientData)
+
+ def GetValue(self):
+ """
+ Returns the current value in the combobox text field.
+
+ :return: the current value in the combobox text field
+ :rtype: string
+
+ """
+ if self._text == self:
+ return super(BaseComboTreeBox, self).GetValue()
+ else:
+ return self._text.GetValue()
+
+ def SetValue(self, value):
+ """
+ Sets the text for the combobox text field.
+
+ NB: For a combobox with wxCB_READONLY style the string must be
+ in the combobox choices list, otherwise the call to SetValue()
+ is ignored.
+
+ :param string `value`: set the combobox text field
+
+ """
+ item = self._tree.GetSelection()
+ if not item or self._tree.GetItemText(item) != value:
+ item = self.FindString(value)
+ if self._readOnly and not item:
+ return
+ if self._text == self:
+ super(BaseComboTreeBox, self).SetValue(value)
+ else:
+ self._text.SetValue(value)
+ if item:
+ if self._tree.GetSelection() != item:
+ self._tree.SelectItem(item)
+ else:
+ self._tree.Unselect()
+
+
+class NativeComboTreeBox(BaseComboTreeBox, wx.ComboBox):
+ """
+ NativeComboTreeBox, and any subclass, uses the native ComboBox as basis,
+ but prevent it from popping up its drop down list and instead pops up a
+ PopupFrame containing a tree of items.
+ """
+
+ def _eventsToBind(self):
+ events = super(NativeComboTreeBox, self)._eventsToBind()
+ # Bind all mouse click events to self.OnMouseClick so we can
+ # intercept those events and prevent the native Combobox from
+ # popping up its list of choices.
+ for eventType in (wx.EVT_LEFT_DOWN, wx.EVT_LEFT_DCLICK,
+ wx.EVT_MIDDLE_DOWN, wx.EVT_MIDDLE_DCLICK,
+ wx.EVT_RIGHT_DOWN, wx.EVT_RIGHT_DCLICK):
+ events.append((self._button, eventType, self.OnMouseClick))
+ if self._readOnly:
+ events.append((self, wx.EVT_CHAR, self.OnChar))
+ return events
+
+ def OnChar(self, event):
+ # OnChar is only called when in read only mode. We don't call
+ # event.Skip() on purpose, to prevent the characters from being
+ # displayed in the text field.
+ pass
+
+
+class MSWComboTreeBox(NativeComboTreeBox):
+ """
+ MSWComboTreeBox adds one piece of functionality as compared to
+ NativeComboTreeBox: when the user browses through the tree, the
+ ComboTreeBox's text field is continuously updated to show the
+ currently selected item in the tree. If the user cancels
+ selecting a new item from the tree, e.g. by hitting escape, the
+ previous value (the one that was selected before the PopupFrame
+ was popped up) is restored.
+ """
+
+ def _createPopupFrame(self):
+ return MSWPopupFrame(self)
+
+ def _eventsToBind(self):
+ events = super(MSWComboTreeBox, self)._eventsToBind()
+ events.append((self._tree, wx.EVT_TREE_SEL_CHANGED,
+ self.OnSelectionChangedInTree))
+ return events
+
+ def OnSelectionChangedInTree(self, event):
+ if self.IsBeingDeleted():
+ return
+ item = event.GetItem()
+ if item:
+ selectedValue = self._tree.GetItemText(item)
+ if self.GetValue() != selectedValue:
+ self.SetValue(selectedValue)
+ event.Skip()
+
+ def _keyShouldPopUpTree(self, keyEvent):
+ return super(MSWComboTreeBox, self)._keyShouldPopUpTree(keyEvent) or \
+ (keyEvent.GetKeyCode() == wx.WXK_F4 and not keyEvent.HasModifiers()) or \
+ ((keyEvent.AltDown() or keyEvent.MetaDown()) and \
+ keyEvent.GetKeyCode() == wx.WXK_UP)
+
+ def SetValue(self, value):
+ """
+ Extend SetValue to also select the text in the
+ ComboTreeBox's text field.
+
+ :param string `value`: set the value and select it
+
+ """
+ super(MSWComboTreeBox, self).SetValue(value)
+ # We select the text in the ComboTreeBox's text field.
+ # There is a slight complication, however. When the control is
+ # deleted, SetValue is called. But if we call SetMark at that
+ # time, wxPython will crash. We can prevent this by comparing the
+ # result of GetLastPosition and the length of the value. If they
+ # match, all is fine. If they don't match, we don't call SetMark.
+ if self._text.GetLastPosition() == len(value):
+ self._text.SetMark(0, self._text.GetLastPosition())
+
+ def Popup(self, *args, **kwargs):
+ """
+ Extend Popup to store a copy of the current value, so we can
+ restore it later (in NotifyNoItemSelected). This is necessary
+ because MSWComboTreeBox will change the value as the user
+ browses through the items in the popped up tree.
+ """
+ self._previousValue = self.GetValue()
+ super(MSWComboTreeBox, self).Popup(*args, **kwargs)
+
+ def NotifyNoItemSelected(self, *args, **kwargs):
+ """
+ Restore the value copied previously, because the user has
+ not selected a new value.
+ """
+ self.SetValue(self._previousValue)
+ super(MSWComboTreeBox, self).NotifyNoItemSelected(*args, **kwargs)
+
+
+class MACComboTreeBox(NativeComboTreeBox):
+ def _createPopupFrame(self):
+ return MACPopupFrame(self)
+
+ def _createButton(self):
+ return self.GetChildren()[0] # The choice button
+
+ def _keyShouldNavigate(self, keyEvent):
+ return False # No navigation with up and down on wxMac
+
+ def _keyShouldPopUpTree(self, keyEvent):
+ return super(MACComboTreeBox, self)._keyShouldPopUpTree(keyEvent) or \
+ keyEvent.GetKeyCode() == wx.WXK_DOWN
+
+
+class GTKComboTreeBox(BaseComboTreeBox, wx.Panel):
+ """
+ The ComboTreeBox widget for wxGTK. This is actually a work
+ around because on wxGTK, there doesn't seem to be a way to intercept
+ mouse events sent to the Combobox. Intercepting those events is
+ necessary to prevent the Combobox from popping up the list and pop up
+ the tree instead. So, until wxPython makes intercepting those events
+ possible we build a poor man's Combobox ourselves using a TextCtrl and
+ a BitmapButton.
+ """
+
+ def _createPopupFrame(self):
+ return GTKPopupFrame(self)
+
+ def _createTextCtrl(self):
+ if self._readOnly:
+ style = wx.TE_READONLY
+ else:
+ style = 0
+ return wx.TextCtrl(self, style=style)
+
+ def _createButton(self):
+ bitmap = wx.ArtProvider.GetBitmap(wx.ART_GO_DOWN, client=wx.ART_BUTTON)
+ return wx.BitmapButton(self, bitmap=bitmap)
+
+ def _layoutInterior(self):
+ panelSizer = wx.BoxSizer(wx.HORIZONTAL)
+ panelSizer.Add(self._text, flag=wx.EXPAND, proportion=1)
+ panelSizer.Add(self._button)
+ self.SetSizerAndFit(panelSizer)
+
+
+# ---------------------------------------------------------------------------
+
+
+def ComboTreeBox(*args, **kwargs):
+ """
+ Factory function to create the right ComboTreeBox depending on
+ platform. You may force a specific class, e.g. for testing
+ purposes, by setting the keyword argument 'platform', e.g.
+ 'platform=GTK' or 'platform=MSW' or 'platform=MAC'.
+
+ :keyword string `platform`: 'GTK'|'MSW'|'MAC' can be used to override the
+ actual platform for testing
+
+ """
+
+ platform = kwargs.pop('platform', None) or wx.PlatformInfo[0][4:7]
+ ComboTreeBoxClassName = '%sComboTreeBox' % platform
+ ComboTreeBoxClass = globals()[ComboTreeBoxClassName]
+ return ComboTreeBoxClass(*args, **kwargs)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/customtreectrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/customtreectrl.py
new file mode 100644
index 0000000..f84c076
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/customtreectrl.py
@@ -0,0 +1,13 @@
+# ============================================================== #
+# This is now just a stub, importing the real module which lives #
+# under wx.lib.agw.
+# ============================================================== #
+
+"""
+Attention! CustomTreeCtrl now lives in wx.lib.agw, together with
+its friends in the Advanced Generic Widgets family.
+
+Please update your code!
+"""
+
+from wx.lib.agw.customtreectrl import * \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/delayedresult.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/delayedresult.py
new file mode 100644
index 0000000..fdb0a4b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/delayedresult.py
@@ -0,0 +1,420 @@
+"""
+This module supports the thread-safe, asynchronous transmission of data
+('delayed results') from a worker (non-GUI) thread to the main thread. Ie you don't
+need to mutex lock any data, the worker thread doesn't wait (or even check)
+for the result to be received, and the main thread doesn't wait for the
+worker thread to send the result. Instead, the consumer will be called
+automatically by the wx app when the worker thread result is available.
+
+In most cases you just need to use startWorker() with the correct parameters
+(your worker function and your 'consumer' in the simplest of cases). The
+only requirement on consumer is that it must accept a DelayedResult instance
+as first arg.
+
+In the following example, this will call consumer(delayedResult) with the
+return value from workerFn::
+
+ from delayedresult import startWorker
+ startWorker(consumer, workerFn)
+
+More advanced uses:
+
+- The other parameters to startWorker()
+- Derive from Producer to override _extraInfo (e.g. to provide traceback info)
+- Create your own worker-function-thread wrapper instead of using Producer
+- Create your own Handler-like wrapper to pre- or post-process the result
+ (see PreProcessChain)
+- Derive from Sender to use your own way of making result hop over the
+ "thread boundary" (from non-main thread to main thread), e.g. using Queue
+
+Thanks to Josiah Carlson for critical feedback/ideas that helped me
+improve this module.
+
+:Copyright: (c) 2006 by Oliver Schoenborn
+:License: wxWidgets license
+:Version: 1.0
+
+"""
+
+__author__ = 'Oliver Schoenborn at utoronto dot ca'
+__version__ = '1.0'
+
+__all__ = ('Sender', 'SenderNoWx', 'SenderWxEvent', 'SenderCallAfter',
+ 'Handler', 'DelayedResult', 'Producer', 'startWorker', 'PreProcessChain')
+
+
+import wx
+import threading
+import traceback
+
+
+class Struct:
+ """
+ An object that has attributes built from the dictionary given in
+ constructor. So ss=Struct(a=1, b='b') will satisfy assert ss.a == 1
+ and assert ss.b == 'b'.
+ """
+
+ def __init__(self, **kwargs):
+ self.__dict__.update( kwargs )
+
+
+class Handler:
+ """
+ Bind some of the arguments and keyword arguments of a callable ('listener').
+ Then when the Handler instance is called (e.g. `handler(result, **kwargs)`)
+ the result is passed as first argument to callable, the kwargs is
+ combined with those given at construction, and the args are those
+ given at construction. Its return value is returned.
+ """
+ def __init__(self, listener, *args, **kwargs ):
+ """Bind args and kwargs to listener. """
+ self.__listener = listener
+ self.__args = args
+ self.__kwargs = kwargs
+
+ def __call__(self, result, **moreKwargs):
+ """Listener is assumed to take result as first `arg`, then `*args`,
+ then the combination of moreKwargs and the kwargs given at construction."""
+ if moreKwargs:
+ moreKwargs.update(self.__kwargs)
+ else:
+ moreKwargs = self.__kwargs
+ return self.__listener(result, *self.__args, **moreKwargs)
+
+
+class Sender:
+ """
+ Base class for various kinds of senders. A sender sends a result
+ produced by a worker funtion to a result handler (listener). Note
+ that each sender can be given a "job id". This can be anything
+ (number, string, id, and object, etc) and is not used, it is
+ simply added as attribute whenever a DelayedResult is created.
+ This allows you to know, if desired, what result corresponds to
+ which sender. Note that uniqueness is not necessary.
+
+ Derive from this class if none of the existing derived classes
+ are adequate, and override _sendImpl().
+ """
+
+ def __init__(self, jobID=None):
+ """The optional jobID can be anything that you want to use to
+ track which sender particular results come from. """
+ self.__jobID = jobID
+
+ def getJobID(self):
+ """Return the jobID given at construction"""
+ return self.__jobID
+
+ def sendResult(self, result):
+ """This will send the result to handler, using whatever
+ technique the derived class uses. """
+ delayedResult = DelayedResult(result, jobID=self.__jobID)
+ self._sendImpl(delayedResult)
+
+ def sendException(self, exception, extraInfo = None, originalTb = None):
+ """Use this when the worker function raised an exception.
+ The *exception* is the instance of Exception caught. The extraInfo
+ could be anything you want (e.g. locals or traceback etc),
+ it will be added to the exception as attribute 'extraInfo'. The
+ exception will be raised when DelayedResult.get() is called."""
+ assert exception is not None
+ delayedResult = DelayedResult(extraInfo,
+ exception=exception, jobID=self.__jobID, originalTb=originalTb)
+ self._sendImpl(delayedResult)
+
+ def _sendImpl(self, delayedResult):
+ msg = '_sendImpl() must be implemented in %s' % self.__class__
+ raise NotImplementedError(msg)
+
+
+class SenderNoWx( Sender ):
+ """
+ Sender that works without wx. The results are sent directly, ie
+ the consumer will get them "in the worker thread". So it should
+ only be used for testing.
+ """
+ def __init__(self, consumer, jobID=None, args=(), kwargs={}):
+ """The consumer can be any callable of the form
+ `callable(result, *args, **kwargs)`"""
+ Sender.__init__(self, jobID)
+ if args or kwargs:
+ self.__consumer = Handler(consumer, *args, **kwargs)
+ else:
+ self.__consumer = consumer
+
+ def _sendImpl(self, delayedResult):
+ self.__consumer(delayedResult)
+
+
+class SenderWxEvent( Sender ):
+ """
+ This sender sends the delayed result produced in the worker thread
+ to an event handler in the main thread, via a wx event of class
+ *eventClass*. The result is an attribute of the event (default:
+ "delayedResult".
+ """
+ def __init__(self, handler, eventClass, resultAttr="delayedResult",
+ jobID=None, **kwargs):
+ """The handler must derive from wx.EvtHandler. The event class
+ is typically the first item in the pair returned by
+ wx.lib.newevent.NewEvent(). You can use the *resultAttr*
+ to change the attribute name of the generated event's
+ delayed result. """
+ Sender.__init__(self, jobID)
+ if not isinstance(handler, wx.EvtHandler):
+ msg = 'SenderWxEvent(handler=%s, ...) not allowed,' % type(handler)
+ msg = '%s handler must derive from wx.EvtHandler' % msg
+ raise ValueError(msg)
+ self.__consumer = Struct(handler=handler, eventClass=eventClass,
+ resultAttr=resultAttr, kwargs=kwargs)
+
+ def _sendImpl(self, delayedResult):
+ """Must not modify the consumer (that was created at construction)
+ since might be shared by several senders, each sending from
+ separate threads."""
+ consumer = self.__consumer
+ kwargs = consumer.kwargs.copy()
+ kwargs[ consumer.resultAttr ] = delayedResult
+ event = consumer.eventClass(** kwargs)
+ wx.PostEvent(consumer.handler, event)
+
+
+class SenderCallAfter( Sender ):
+ """
+ This sender sends the delayed result produced in the worker thread
+ to a callable in the main thread, via wx.CallAfter.
+ """
+ def __init__(self, listener, jobID=None, args=(), kwargs={}):
+ Sender.__init__(self, jobID)
+ if args or kwargs:
+ self.__consumer = Handler(listener, *args, **kwargs)
+ else:
+ self.__consumer = listener
+
+ def _sendImpl(self, delayedResult):
+ wx.CallAfter(self.__consumer, delayedResult)
+
+
+class DelayedResult:
+ """
+ Represent the actual delayed result coming from the non-main thread.
+ An instance of this is given to the result handler. This result is
+ either a (reference to a) the value sent, or an exception.
+ If the latter, the exception is raised when the get() method gets
+ called.
+ """
+
+ def __init__(self, result, jobID=None, exception = None, originalTb = None):
+ """You should never have to call this yourself. A DelayedResult
+ is created by a concrete Sender for you."""
+ self.__result = result
+ self.__exception = exception
+ self.__original_traceback = originalTb
+ self.__jobID = jobID
+
+ def getJobID(self):
+ """Return the jobID given when Sender initialized,
+ or None if none given. """
+ return self.__jobID
+
+ def get(self):
+ """Get the result. If an exception was sent instead of a result,
+ (via Sender's sendExcept()), that **exception is raised**, and
+ the original traceback is available as the 'originalTraceback'
+ variable in the exception object.
+
+ Otherwise, the result is simply returned.
+ """
+ if self.__exception: # exception was raised!
+ self.__exception.extraInfo = self.__result
+ self.__exception.originalTraceback = self.__original_traceback
+ raise self.__exception
+
+ return self.__result
+
+
+class AbortedException(Exception):
+ """Raise this in your worker function so that the sender knows
+ not to send a result to handler."""
+ pass
+
+
+class Producer(threading.Thread):
+ """
+ Represent the worker thread that produces delayed results.
+ It causes the given function to run in a separate thread,
+ and a sender to be used to send the return value of the function.
+ As with any threading.Thread, instantiate and call start().
+ Note that if the workerFn raises AbortedException, the result is not
+ sent and the thread terminates gracefully.
+ """
+
+ def __init__(self, sender, workerFn, args=(), kwargs={},
+ name=None, group=None, daemon=False,
+ sendReturn=True, senderArg=None):
+ """The sender will send the return value of
+ `workerFn(*args, **kwargs)` to the main thread. The name and group
+ are same as threading.Thread constructor parameters. Daemon causes
+ setDaemon() to be called. If sendReturn is False, then the return
+ value of workerFn() will not be sent. If senderArg is given, it
+ must be the name of the keyword arg to use to pass the sender into
+ the workerFn, so the function can send (typically many) results."""
+ if senderArg:
+ kwargs[senderArg] = sender
+ def wrapper():
+ try:
+ result = workerFn(*args, **kwargs)
+ except AbortedException:
+ pass
+ except Exception, exc:
+ originalTb = traceback.format_exc()
+ extraInfo = self._extraInfo(exc)
+ sender.sendException(exc, extraInfo, originalTb)
+ else:
+ if sendReturn:
+ sender.sendResult(result)
+
+ threading.Thread.__init__(self, name=name, group=group, target=wrapper)
+ if daemon:
+ self.setDaemon(daemon)
+
+ def _extraInfo(self, exception):
+ """This method could be overridden in a derived class to provide
+ extra information when an exception is being sent instead of a
+ result. """
+ return None
+
+
+class AbortEvent:
+ """
+ Convenience class that represents a kind of threading.Event that
+ raises AbortedException when called (see the __call__ method, everything
+ else is just to make it look like threading.Event).
+ """
+
+ def __init__(self):
+ self.__ev = threading.Event()
+
+ def __call__(self, timeout=None):
+ """See if event has been set (wait at most timeout if given). If so,
+ raise AbortedException. Otherwise return None. Allows you to do
+ 'while not event():' which will always succeed unless the event
+ has been set (then AbortedException will cause while to exit)."""
+ if timeout:
+ self.__ev.wait(timeout)
+ if self.__ev.isSet():
+ raise AbortedException()
+ return None
+
+ def __getattr__(self, name):
+ """This allows us to be a kind of threading.Event."""
+ if name in ('set','clear','wait','isSet'):
+ return getattr(self.__ev, name)
+
+
+def startWorker(
+ consumer, workerFn,
+ cargs=(), ckwargs={},
+ wargs=(), wkwargs={},
+ jobID=None, group=None, daemon=False,
+ sendReturn=True, senderArg=None):
+ """
+ Convenience function to send data produced by `workerFn(*wargs, **wkwargs)`
+ running in separate thread, to a `consumer(*cargs, **ckwargs)` running in
+ the main thread. This function merely creates a SenderCallAfter (or a
+ SenderWxEvent, if consumer derives from wx.EvtHandler), and a Producer,
+ and returns immediately after starting the Producer thread. The jobID
+ is used for the Sender and as name for the Producer thread. Returns the
+ thread created, in case caller needs join/etc.
+ """
+
+ if isinstance(consumer, wx.EvtHandler):
+ eventClass = cargs[0]
+ sender = SenderWxEvent(consumer, eventClass, jobID=jobID, **ckwargs)
+ else:
+ sender = SenderCallAfter(consumer, jobID, args=cargs, kwargs=ckwargs)
+
+ thread = Producer(
+ sender, workerFn, args=wargs, kwargs=wkwargs,
+ name=jobID, group=group, daemon=daemon,
+ senderArg=senderArg, sendReturn=sendReturn)
+
+ thread.start()
+ return thread
+
+
+class PreProcessChain:
+ """
+ Represent a 'delayed result pre-processing chain', a kind of Handler.
+ Useful when lower-level objects need to apply a sequence of transformations
+ to the delayed result before handing it over to a final handler.
+ This allows the starter of the worker function to not know
+ anything about the lower-level objects.
+ """
+ def __init__(self, handler, *args, **kwargs):
+ """Wrap `handler(result, *args, **kwargs)` so that the result
+ it receives has been transformed by us. """
+ if handler is None:# assume rhs is a chain
+ self.__chain = args[0]
+ else:
+ if args or kwargs:
+ handler = Handler(handler, *args, **kwargs)
+ self.__chain = [handler]
+
+ def addSub(self, callable, *args, **kwargs):
+ """Add a sub-callable, ie a `callable(result, *args, **kwargs)`
+ that returns a transformed result to the previously added
+ sub-callable (or the handler given at construction, if this is
+ the first call to addSub). """
+ self.__chain.append( Handler(callable, *args, **kwargs) )
+
+ def clone(self):
+ """Clone the chain. Shallow only. Useful when several threads
+ must be started but have different sub-callables. """
+ return PreProcessChain(None, self.__chain[:] )
+
+ def cloneAddSub(self, callable, *args, **kwargs):
+ """Convenience method that first clones self, then calls addSub()
+ on that clone with given arguments. """
+ cc = self.clone()
+ cc.addSub(callable, *args, **kwargs)
+
+ def count(self):
+ """How many pre-processors in the chain"""
+ return len(self.__chain)
+
+ class Traverser:
+ """
+ Traverses the chain of pre-processors it is given, transforming
+ the original delayedResult along the way. The return value of each
+ callable added via addSub() is given to the previous addSub() callable,
+ until the handler is reached.
+ """
+ def __init__(self, delayedResult, chain):
+ self.__dr = delayedResult
+ self.__chain = chain
+
+ def get(self):
+ """This makes handler think we are a delayedResult."""
+ if not self.__chain:
+ return self.__dr.get()
+
+ handler = self.__chain[0]
+ del self.__chain[0]
+ return handler(self)
+
+ def getJobID(self):
+ """Return the job id for the delayedResult we transform."""
+ return self.__dr.getJobID()
+
+
+ def __call__(self, delayedResult):
+ """This makes us a Handler. We just call handler(Traverser). The
+ handler will think it is getting a delayed result, but in fact
+ will be getting an instance of Traverser, which will take care
+ of properly applying the chain of transformations to delayedResult."""
+ chainTrav = self.Traverser(delayedResult, self.__chain[1:])
+ handler = self.__chain[0]
+ handler( chainTrav )
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/dialogs.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/dialogs.py
new file mode 100644
index 0000000..c55bfa9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/dialogs.py
@@ -0,0 +1,505 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.dialogs
+# Purpose: ScrolledMessageDialog, MultipleChoiceDialog and
+# function wrappers for the common dialogs by Kevin Altis.
+#
+# Author: Various
+#
+# Created: 3-January-2002
+# RCS-ID: $Id$
+# Copyright: (c) 2002 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/01/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for 2.5 compatability.
+#
+# 12/18/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxScrolledMessageDialog -> ScrolledMessageDialog
+# o wxMultipleChoiceDialog -> MultipleChoiceDialog
+#
+
+import wx
+import wx.lib.layoutf as layoutf
+
+#----------------------------------------------------------------------
+
+class ScrolledMessageDialog(wx.Dialog):
+ def __init__(self, parent, msg, caption,
+ pos=wx.DefaultPosition, size=(500,300),
+ style=wx.DEFAULT_DIALOG_STYLE):
+ wx.Dialog.__init__(self, parent, -1, caption, pos, size, style)
+ x, y = pos
+ if x == -1 and y == -1:
+ self.CenterOnScreen(wx.BOTH)
+
+ self.text = text = wx.TextCtrl(self, -1, msg,
+ style=wx.TE_MULTILINE | wx.TE_READONLY)
+
+ ok = wx.Button(self, wx.ID_OK, "OK")
+ ok.SetDefault()
+ lc = layoutf.Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self,ok))
+ text.SetConstraints(lc)
+
+ lc = layoutf.Layoutf('b=b5#1;x%w50#1;w!80;h*', (self,))
+ ok.SetConstraints(lc)
+ self.SetAutoLayout(1)
+ self.Layout()
+
+
+class MultipleChoiceDialog(wx.Dialog):
+ def __init__(self, parent, msg, title, lst, pos = wx.DefaultPosition,
+ size = (200,200), style = wx.DEFAULT_DIALOG_STYLE):
+ wx.Dialog.__init__(self, parent, -1, title, pos, size, style)
+
+ x, y = pos
+ if x == -1 and y == -1:
+ self.CenterOnScreen(wx.BOTH)
+
+ stat = wx.StaticText(self, -1, msg)
+ self.lbox = wx.ListBox(self, 100, wx.DefaultPosition, wx.DefaultSize,
+ lst, wx.LB_MULTIPLE)
+
+ ok = wx.Button(self, wx.ID_OK, "OK")
+ ok.SetDefault()
+ cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
+
+ dlgsizer = wx.BoxSizer(wx.VERTICAL)
+ dlgsizer.Add(stat, 0, wx.ALL, 4)
+ dlgsizer.Add(self.lbox, 1, wx.EXPAND | wx.ALL, 4)
+
+ btnsizer = wx.StdDialogButtonSizer()
+ btnsizer.AddButton(ok)
+ btnsizer.AddButton(cancel)
+ btnsizer.Realize()
+
+ dlgsizer.Add(btnsizer, 0, wx.ALL | wx.ALIGN_RIGHT, 4)
+
+ self.SetSizer(dlgsizer)
+
+ self.lst = lst
+ self.Layout()
+
+ def GetValue(self):
+ return self.lbox.GetSelections()
+
+ def GetValueString(self):
+ sel = self.lbox.GetSelections()
+ val = [ self.lst[i] for i in sel ]
+ return tuple(val)
+
+
+#----------------------------------------------------------------------
+"""
+function wrappers for wxPython system dialogs
+Author: Kevin Altis
+Date: 2003-1-2
+Rev: 3
+
+This is the third refactor of the PythonCard dialog.py module
+for inclusion in the main wxPython distribution. There are a number of
+design decisions and subsequent code refactoring to be done, so I'm
+releasing this just to get some feedback.
+
+rev 3:
+- result dictionary replaced by DialogResults class instance
+- should message arg be replaced with msg? most wxWindows dialogs
+ seem to use the abbreviation?
+
+rev 2:
+- All dialog classes have been replaced by function wrappers
+- Changed arg lists to more closely match wxWindows docs and wxPython.lib.dialogs
+- changed 'returned' value to the actual button id the user clicked on
+- added a returnedString value for the string version of the return value
+- reworked colorDialog and fontDialog so you can pass in just a color or font
+ for the most common usage case
+- probably need to use colour instead of color to match the English English
+ spelling in wxWindows (sigh)
+- I still think we could lose the parent arg and just always use None
+"""
+
+class DialogResults:
+ def __init__(self, returned):
+ self.returned = returned
+ self.accepted = returned in (wx.ID_OK, wx.ID_YES)
+ self.returnedString = returnedString(returned)
+
+ def __repr__(self):
+ return str(self.__dict__)
+
+def returnedString(ret):
+ if ret == wx.ID_OK:
+ return "Ok"
+ elif ret == wx.ID_CANCEL:
+ return "Cancel"
+ elif ret == wx.ID_YES:
+ return "Yes"
+ elif ret == wx.ID_NO:
+ return "No"
+
+
+## findDialog was created before wxPython got a Find/Replace dialog
+## but it may be instructive as to how a function wrapper can
+## be added for your own custom dialogs
+## this dialog is always modal, while wxFindReplaceDialog is
+## modeless and so doesn't lend itself to a function wrapper
+def findDialog(parent=None, searchText='', wholeWordsOnly=0, caseSensitive=0):
+ dlg = wx.Dialog(parent, -1, "Find", wx.DefaultPosition, (380, 120))
+
+ wx.StaticText(dlg, -1, 'Find what:', (7, 10))
+ wSearchText = wx.TextCtrl(dlg, -1, searchText, (80, 7), (195, -1))
+ wSearchText.SetValue(searchText)
+ wx.Button(dlg, wx.ID_OK, "Find Next", (285, 5), wx.DefaultSize).SetDefault()
+ wx.Button(dlg, wx.ID_CANCEL, "Cancel", (285, 35), wx.DefaultSize)
+
+ wWholeWord = wx.CheckBox(dlg, -1, 'Match whole word only',
+ (7, 35), wx.DefaultSize, wx.NO_BORDER)
+
+ if wholeWordsOnly:
+ wWholeWord.SetValue(1)
+
+ wCase = wx.CheckBox(dlg, -1, 'Match case', (7, 55), wx.DefaultSize, wx.NO_BORDER)
+
+ if caseSensitive:
+ wCase.SetValue(1)
+
+ wSearchText.SetSelection(0, len(wSearchText.GetValue()))
+ wSearchText.SetFocus()
+
+ result = DialogResults(dlg.ShowModal())
+ result.searchText = wSearchText.GetValue()
+ result.wholeWordsOnly = wWholeWord.GetValue()
+ result.caseSensitive = wCase.GetValue()
+ dlg.Destroy()
+ return result
+
+
+def colorDialog(parent=None, colorData=None, color=None):
+ if colorData:
+ dialog = wx.ColourDialog(parent, colorData)
+ else:
+ dialog = wx.ColourDialog(parent)
+ dialog.GetColourData().SetChooseFull(1)
+
+ if color is not None:
+ dialog.GetColourData().SetColour(color)
+
+ result = DialogResults(dialog.ShowModal())
+ result.colorData = dialog.GetColourData()
+ result.color = result.colorData.GetColour().Get()
+ dialog.Destroy()
+ return result
+
+
+## it is easier to just duplicate the code than
+## try and replace color with colour in the result
+def colourDialog(parent=None, colourData=None, colour=None):
+ if colourData:
+ dialog = wx.ColourDialog(parent, colourData)
+ else:
+ dialog = wx.ColourDialog(parent)
+ dialog.GetColourData().SetChooseFull(1)
+
+ if colour is not None:
+ dialog.GetColourData().SetColour(color)
+
+ result = DialogResults(dialog.ShowModal())
+ result.colourData = dialog.GetColourData()
+ result.colour = result.colourData.GetColour().Get()
+ dialog.Destroy()
+ return result
+
+
+def fontDialog(parent=None, fontData=None, font=None):
+ if fontData is None:
+ fontData = wx.FontData()
+ fontData.SetColour(wx.BLACK)
+ fontData.SetInitialFont(wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT))
+
+ if font is not None:
+ fontData.SetInitialFont(font)
+
+ dialog = wx.FontDialog(parent, fontData)
+ result = DialogResults(dialog.ShowModal())
+
+ if result.accepted:
+ fontData = dialog.GetFontData()
+ result.fontData = fontData
+ result.color = fontData.GetColour().Get()
+ result.colour = result.color
+ result.font = fontData.GetChosenFont()
+ else:
+ result.color = None
+ result.colour = None
+ result.font = None
+
+ dialog.Destroy()
+ return result
+
+
+def textEntryDialog(parent=None, message='', title='', defaultText='',
+ style=wx.OK | wx.CANCEL):
+ dialog = wx.TextEntryDialog(parent, message, title, defaultText, style)
+ result = DialogResults(dialog.ShowModal())
+ result.text = dialog.GetValue()
+ dialog.Destroy()
+ return result
+
+
+def messageDialog(parent=None, message='', title='Message box',
+ aStyle = wx.OK | wx.CANCEL | wx.CENTRE,
+ pos=wx.DefaultPosition):
+ dialog = wx.MessageDialog(parent, message, title, aStyle, pos)
+ result = DialogResults(dialog.ShowModal())
+ dialog.Destroy()
+ return result
+
+
+## KEA: alerts are common, so I'm providing a class rather than
+## requiring the user code to set up the right icons and buttons
+## the with messageDialog function
+def alertDialog(parent=None, message='', title='Alert', pos=wx.DefaultPosition):
+ return messageDialog(parent, message, title, wx.ICON_EXCLAMATION | wx.OK, pos)
+
+
+def scrolledMessageDialog(parent=None, message='', title='', pos=wx.DefaultPosition,
+ size=(500,300)):
+
+ dialog = ScrolledMessageDialog(parent, message, title, pos, size)
+ result = DialogResults(dialog.ShowModal())
+ dialog.Destroy()
+ return result
+
+
+def fileDialog(parent=None, title='Open', directory='', filename='', wildcard='*.*',
+ style=wx.OPEN | wx.MULTIPLE):
+
+ dialog = wx.FileDialog(parent, title, directory, filename, wildcard, style)
+ result = DialogResults(dialog.ShowModal())
+ if result.accepted:
+ result.paths = dialog.GetPaths()
+ else:
+ result.paths = None
+ dialog.Destroy()
+ return result
+
+
+## openFileDialog and saveFileDialog are convenience functions
+## they represent the most common usages of the fileDialog
+## with the most common style options
+def openFileDialog(parent=None, title='Open', directory='', filename='',
+ wildcard='All Files (*.*)|*.*',
+ style=wx.OPEN | wx.MULTIPLE):
+ return fileDialog(parent, title, directory, filename, wildcard, style)
+
+
+def saveFileDialog(parent=None, title='Save', directory='', filename='',
+ wildcard='All Files (*.*)|*.*',
+ style=wx.SAVE | wx.OVERWRITE_PROMPT):
+ return fileDialog(parent, title, directory, filename, wildcard, style)
+
+
+def dirDialog(parent=None, message='Choose a directory', path='', style=0,
+ pos=wx.DefaultPosition, size=wx.DefaultSize):
+
+ dialog = wx.DirDialog(parent, message, path, style, pos, size)
+ result = DialogResults(dialog.ShowModal())
+ if result.accepted:
+ result.path = dialog.GetPath()
+ else:
+ result.path = None
+ dialog.Destroy()
+ return result
+
+directoryDialog = dirDialog
+
+
+def singleChoiceDialog(parent=None, message='', title='', lst=[],
+ style=wx.OK | wx.CANCEL | wx.CENTRE):
+ dialog = wx.SingleChoiceDialog(parent, message, title, list(lst), style | wx.DEFAULT_DIALOG_STYLE)
+ result = DialogResults(dialog.ShowModal())
+ result.selection = dialog.GetStringSelection()
+ dialog.Destroy()
+ return result
+
+
+def multipleChoiceDialog(parent=None, message='', title='', lst=[],
+ pos=wx.DefaultPosition, size=wx.DefaultSize):
+
+ dialog = wx.MultiChoiceDialog(parent, message, title, lst,
+ wx.CHOICEDLG_STYLE, pos)
+ result = DialogResults(dialog.ShowModal())
+ result.selection = tuple([lst[i] for i in dialog.GetSelections()])
+ dialog.Destroy()
+ return result
+
+
+
+#---------------------------------------------------------------------------
+
+try:
+ wx.CANCEL_DEFAULT
+ wx.OK_DEFAULT
+except AttributeError:
+ wx.CANCEL_DEFAULT = 0
+ wx.OK_DEFAULT = 0
+
+
+
+class MultiMessageDialog(wx.Dialog):
+ """
+ A dialog like wx.MessageDialog, but with an optional 2nd message string
+ that is shown in a scrolled window, and also allows passing in the icon to
+ be shown instead of the stock error, question, etc. icons. The btnLabels
+ can be used if you'd like to change the stock labels on the buttons, it's
+ a dictionary mapping stock IDs to label strings.
+ """
+ CONTENT_MAX_W = 550
+ CONTENT_MAX_H = 350
+
+ def __init__(self, parent, message, caption = "Message Box", msg2="",
+ style = wx.OK | wx.CANCEL, pos = wx.DefaultPosition, icon=None,
+ btnLabels=None):
+ if 'wxMac' not in wx.PlatformInfo:
+ title = caption # the caption will be displayed inside the dialog on Macs
+ else:
+ title = ""
+
+ wx.Dialog.__init__(self, parent, -1, title, pos,
+ style = wx.DEFAULT_DIALOG_STYLE | style & (wx.STAY_ON_TOP | wx.DIALOG_NO_PARENT))
+
+ bitmap = None
+ isize = (32,32)
+
+ # was an icon passed to us?
+ if icon is not None:
+ if isinstance(icon, wx.Icon):
+ bitmap = wx.BitmapFromIcon(icon)
+ elif isinstance(icon, wx.Image):
+ bitmap = wx.BitmapFromImage(icon)
+ else:
+ assert isinstance(icon, wx.Bitmap)
+ bitmap = icon
+
+ else:
+ # check for icons in the style flags
+ artid = None
+ if style & wx.ICON_ERROR or style & wx.ICON_HAND:
+ artid = wx.ART_ERROR
+ elif style & wx.ICON_EXCLAMATION:
+ artid = wx.ART_WARNING
+ elif style & wx.ICON_QUESTION:
+ artid = wx.ART_QUESTION
+ elif style & wx.ICON_INFORMATION:
+ artid = wx.ART_INFORMATION
+
+ if artid is not None:
+ bitmap = wx.ArtProvider.GetBitmap(artid, wx.ART_MESSAGE_BOX, isize)
+
+ if bitmap:
+ bitmap = wx.StaticBitmap(self, -1, bitmap)
+ else:
+ bitmap = isize # will be a spacer when added to the sizer
+
+ # Sizer to contain the icon, text area and buttons
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(bitmap, 0, wx.TOP|wx.LEFT, 12)
+ sizer.Add((10,10))
+
+ # Make the text area
+ messageSizer = wx.BoxSizer(wx.VERTICAL)
+ if 'wxMac' in wx.PlatformInfo and caption:
+ caption = wx.StaticText(self, -1, caption)
+ caption.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
+ messageSizer.Add(caption)
+ messageSizer.Add((10,10))
+
+ stext = wx.StaticText(self, -1, message)
+ #stext.SetLabelMarkup(message) Wrap() causes all markup to be lost, so don't try to use it yet...
+ stext.Wrap(self.CONTENT_MAX_W)
+ messageSizer.Add(stext)
+
+ if msg2:
+ messageSizer.Add((15,15))
+ t = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH|wx.TE_DONTWRAP)
+ t.SetValue(msg2)
+
+ # Set size to be used by the sizer based on the message content,
+ # with good maximums
+ dc = wx.ClientDC(t)
+ dc.SetFont(t.GetFont())
+ w,h,lh = dc.GetMultiLineTextExtent(msg2)
+ w = min(self.CONTENT_MAX_W, 10 + w + wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X))
+ h = min(self.CONTENT_MAX_H, 10 + h)
+ t.SetMinSize((w,h))
+ messageSizer.Add(t, 0, wx.EXPAND)
+
+ # Make the buttons
+ buttonSizer = self.CreateStdDialogButtonSizer(
+ style & (wx.OK | wx.CANCEL | wx.YES_NO | wx.NO_DEFAULT
+ | wx.CANCEL_DEFAULT | wx.YES_DEFAULT | wx.OK_DEFAULT
+ ))
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ if btnLabels:
+ for sid, label in btnLabels.iteritems():
+ btn = self.FindWindowById(sid)
+ if btn:
+ btn.SetLabel(label)
+ messageSizer.Add(wx.Size(1, 15))
+ messageSizer.Add(buttonSizer, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, 12)
+
+ sizer.Add(messageSizer, 0, wx.LEFT | wx.RIGHT | wx.TOP, 12)
+ self.SetSizer(sizer)
+ self.Fit()
+ if parent:
+ self.CenterOnParent()
+ else:
+ self.CenterOnScreen()
+
+ for c in self.Children:
+ if isinstance(c, wx.Button):
+ wx.CallAfter(c.SetFocus)
+ break
+
+
+ def OnButton(self, evt):
+ if self.IsModal():
+ self.EndModal(evt.EventObject.Id)
+ else:
+ self.Close()
+
+
+
+
+def MultiMessageBox(message, caption, msg2="", style=wx.OK, parent=None,
+ icon=None, btnLabels=None):
+ """
+ A function like wx.MessageBox which uses MultiMessageDialog.
+ """
+ #if not style & wx.ICON_NONE and not style & wx.ICON_MASK:
+ if not style & wx.ICON_MASK:
+ if style & wx.YES:
+ style |= wx.ICON_QUESTION
+ else:
+ style |= wx.ICON_INFORMATION
+
+ dlg = MultiMessageDialog(parent, message, caption, msg2, style,
+ icon=icon, btnLabels=btnLabels)
+ ans = dlg.ShowModal()
+ dlg.Destroy()
+
+ if ans == wx.ID_OK:
+ return wx.OK
+ elif ans == wx.ID_YES:
+ return wx.YES
+ elif ans == wx.ID_NO:
+ return wx.NO
+ elif ans == wx.ID_CANCEL:
+ return wx.CANCEL
+
+ print "unexpected return code from MultiMessageDialog??"
+ return wx.CANCEL
+
+
+#---------------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/docview.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/docview.py
new file mode 100644
index 0000000..52b59a4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/docview.py
@@ -0,0 +1,3230 @@
+#----------------------------------------------------------------------------
+# Name: docview.py
+# Purpose: Port of the wxWindows docview classes
+#
+# Author: Peter Yared
+#
+# Created: 5/15/03
+# CVS-ID: $Id$
+# Copyright: (c) 2003-2006 ActiveGrid, Inc. (Port of wxWindows classes by Julian Smart et al)
+# License: wxWindows license
+#----------------------------------------------------------------------------
+
+
+import os
+import os.path
+import shutil
+import wx
+import sys
+_ = wx.GetTranslation
+
+
+#----------------------------------------------------------------------
+# docview globals
+#----------------------------------------------------------------------
+
+DOC_SDI = 1
+DOC_MDI = 2
+DOC_NEW = 4
+DOC_SILENT = 8
+DOC_OPEN_ONCE = 16
+DOC_NO_VIEW = 32
+DEFAULT_DOCMAN_FLAGS = DOC_SDI & DOC_OPEN_ONCE
+
+TEMPLATE_VISIBLE = 1
+TEMPLATE_INVISIBLE = 2
+TEMPLATE_NO_CREATE = (4 | TEMPLATE_VISIBLE)
+DEFAULT_TEMPLATE_FLAGS = TEMPLATE_VISIBLE
+
+MAX_FILE_HISTORY = 9
+
+
+#----------------------------------------------------------------------
+# Convenience functions from wxWindows used in docview
+#----------------------------------------------------------------------
+
+
+def FileNameFromPath(path):
+ """
+ Returns the filename for a full path.
+ """
+ return os.path.split(path)[1]
+
+def FindExtension(path):
+ """
+ Returns the extension of a filename for a full path.
+ """
+ return os.path.splitext(path)[1].lower()
+
+def FileExists(path):
+ """
+ Returns True if the path exists.
+ """
+ return os.path.isfile(path)
+
+def PathOnly(path):
+ """
+ Returns the path of a full path without the filename.
+ """
+ return os.path.split(path)[0]
+
+
+#----------------------------------------------------------------------
+# Document/View Classes
+#----------------------------------------------------------------------
+
+
+class Document(wx.EvtHandler):
+ """
+ The document class can be used to model an application's file-based data. It
+ is part of the document/view framework supported by wxWindows, and cooperates
+ with the wxView, wxDocTemplate and wxDocManager classes.
+
+ Note this wxPython version also keeps track of the modification date of the
+ document and if it changes on disk outside of the application, we will warn the
+ user before saving to avoid clobbering the file.
+ """
+
+
+ def __init__(self, parent=None):
+ """
+ Constructor. Define your own default constructor to initialize
+ application-specific data.
+ """
+ wx.EvtHandler.__init__(self)
+
+ self._documentParent = parent
+ self._documentTemplate = None
+ self._commandProcessor = None
+ self._savedYet = False
+ self._writeable = True
+
+ self._documentTitle = None
+ self._documentFile = None
+ self._documentTypeName = None
+ self._documentModified = False
+ self._documentModificationDate = None
+ self._documentViews = []
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ return False
+
+
+ def GetFilename(self):
+ """
+ Gets the filename associated with this document, or "" if none is
+ associated.
+ """
+ return self._documentFile
+
+
+ def GetTitle(self):
+ """
+ Gets the title for this document. The document title is used for an
+ associated frame (if any), and is usually constructed by the framework
+ from the filename.
+ """
+ return self._documentTitle
+
+
+ def SetTitle(self, title):
+ """
+ Sets the title for this document. The document title is used for an
+ associated frame (if any), and is usually constructed by the framework
+ from the filename.
+ """
+ self._documentTitle = title
+
+
+ def GetDocumentName(self):
+ """
+ The document type name given to the wxDocTemplate constructor,
+ copied to this document when the document is created. If several
+ document templates are created that use the same document type, this
+ variable is used in wxDocManager::CreateView to collate a list of
+ alternative view types that can be used on this kind of document.
+ """
+ return self._documentTypeName
+
+
+ def SetDocumentName(self, name):
+ """
+ Sets he document type name given to the wxDocTemplate constructor,
+ copied to this document when the document is created. If several
+ document templates are created that use the same document type, this
+ variable is used in wxDocManager::CreateView to collate a list of
+ alternative view types that can be used on this kind of document. Do
+ not change the value of this variable.
+ """
+ self._documentTypeName = name
+
+
+ def GetDocumentSaved(self):
+ """
+ Returns True if the document has been saved. This method has been
+ added to wxPython and is not in wxWindows.
+ """
+ return self._savedYet
+
+
+ def SetDocumentSaved(self, saved=True):
+ """
+ Sets whether the document has been saved. This method has been
+ added to wxPython and is not in wxWindows.
+ """
+ self._savedYet = saved
+
+
+ def GetCommandProcessor(self):
+ """
+ Returns the command processor associated with this document.
+ """
+ return self._commandProcessor
+
+
+ def SetCommandProcessor(self, processor):
+ """
+ Sets the command processor to be used for this document. The document
+ will then be responsible for its deletion. Normally you should not
+ call this; override OnCreateCommandProcessor instead.
+ """
+ self._commandProcessor = processor
+
+
+ def IsModified(self):
+ """
+ Returns true if the document has been modified since the last save,
+ false otherwise. You may need to override this if your document view
+ maintains its own record of being modified (for example if using
+ wxTextWindow to view and edit the document).
+ """
+ return self._documentModified
+
+
+ def Modify(self, modify):
+ """
+ Call with true to mark the document as modified since the last save,
+ false otherwise. You may need to override this if your document view
+ maintains its own record of being modified (for example if using
+ xTextWindow to view and edit the document).
+ This method has been extended to notify its views that the dirty flag has changed.
+ """
+ self._documentModified = modify
+ self.UpdateAllViews(hint=("modify", self, self._documentModified))
+
+
+ def SetDocumentModificationDate(self):
+ """
+ Saves the file's last modification date.
+ This is used to check if the file has been modified outside of the application.
+ This method has been added to wxPython and is not in wxWindows.
+ """
+ self._documentModificationDate = os.path.getmtime(self.GetFilename())
+
+
+ def GetDocumentModificationDate(self):
+ """
+ Returns the file's modification date when it was loaded from disk.
+ This is used to check if the file has been modified outside of the application.
+ This method has been added to wxPython and is not in wxWindows.
+ """
+ return self._documentModificationDate
+
+
+ def IsDocumentModificationDateCorrect(self):
+ """
+ Returns False if the file has been modified outside of the application.
+ This method has been added to wxPython and is not in wxWindows.
+ """
+ if not os.path.exists(self.GetFilename()): # document must be in memory only and can't be out of date
+ return True
+ return self._documentModificationDate == os.path.getmtime(self.GetFilename())
+
+
+ def GetViews(self):
+ """
+ Returns the list whose elements are the views on the document.
+ """
+ return self._documentViews
+
+
+ def GetDocumentTemplate(self):
+ """
+ Returns the template that created the document.
+ """
+ return self._documentTemplate
+
+
+ def SetDocumentTemplate(self, template):
+ """
+ Sets the template that created the document. Should only be called by
+ the framework.
+ """
+ self._documentTemplate = template
+
+
+ def DeleteContents(self):
+ """
+ Deletes the contents of the document. Override this method as
+ necessary.
+ """
+ return True
+
+
+ def Destroy(self):
+ """
+ Destructor. Removes itself from the document manager.
+ """
+ self.DeleteContents()
+ self._documentModificationDate = None
+ if self.GetDocumentManager():
+ self.GetDocumentManager().RemoveDocument(self)
+ wx.EvtHandler.Destroy(self)
+
+
+ def Close(self):
+ """
+ Closes the document, by calling OnSaveModified and then (if this true)
+ OnCloseDocument. This does not normally delete the document object:
+ use DeleteAllViews to do this implicitly.
+ """
+ if self.OnSaveModified():
+ if self.OnCloseDocument():
+ return True
+ else:
+ return False
+ else:
+ return False
+
+
+ def OnCloseDocument(self):
+ """
+ The default implementation calls DeleteContents (an empty
+ implementation) sets the modified flag to false. Override this to
+ supply additional behaviour when the document is closed with Close.
+ """
+ self.NotifyClosing()
+ self.DeleteContents()
+ self.Modify(False)
+ return True
+
+
+ def DeleteAllViews(self):
+ """
+ Calls wxView.Close and deletes each view. Deleting the final view will
+ implicitly delete the document itself, because the wxView destructor
+ calls RemoveView. This in turns calls wxDocument::OnChangedViewList,
+ whose default implemention is to save and delete the document if no
+ views exist.
+ """
+ manager = self.GetDocumentManager()
+ for view in self._documentViews:
+ if not view.Close():
+ return False
+ if self in manager.GetDocuments():
+ self.Destroy()
+ return True
+
+
+ def GetFirstView(self):
+ """
+ A convenience function to get the first view for a document, because
+ in many cases a document will only have a single view.
+ """
+ if len(self._documentViews) == 0:
+ return None
+ return self._documentViews[0]
+
+
+ def GetDocumentManager(self):
+ """
+ Returns the associated document manager.
+ """
+ if self._documentTemplate:
+ return self._documentTemplate.GetDocumentManager()
+ return None
+
+
+ def OnNewDocument(self):
+ """
+ The default implementation calls OnSaveModified and DeleteContents,
+ makes a default title for the document, and notifies the views that
+ the filename (in fact, the title) has changed.
+ """
+ if not self.OnSaveModified() or not self.OnCloseDocument():
+ return False
+ self.DeleteContents()
+ self.Modify(False)
+ self.SetDocumentSaved(False)
+ name = self.GetDocumentManager().MakeDefaultName()
+ self.SetTitle(name)
+ self.SetFilename(name, notifyViews = True)
+
+
+ def Save(self):
+ """
+ Saves the document by calling OnSaveDocument if there is an associated
+ filename, or SaveAs if there is no filename.
+ """
+ if not self.IsModified(): # and self._savedYet: This was here, but if it is not modified who cares if it hasn't been saved yet?
+ return True
+
+ """ check for file modification outside of application """
+ if not self.IsDocumentModificationDateCorrect():
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("Application")
+ res = wx.MessageBox(_("'%s' has been modified outside of %s. Overwrite '%s' with current changes?") % (self.GetPrintableName(), msgTitle, self.GetPrintableName()),
+ msgTitle,
+ wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION,
+ self.GetDocumentWindow())
+
+ if res == wx.NO:
+ return True
+ elif res == wx.YES:
+ pass
+ else: # elif res == wx.CANCEL:
+ return False
+
+ if not self._documentFile or not self._savedYet:
+ return self.SaveAs()
+ return self.OnSaveDocument(self._documentFile)
+
+
+ def SaveAs(self):
+ """
+ Prompts the user for a file to save to, and then calls OnSaveDocument.
+ """
+ docTemplate = self.GetDocumentTemplate()
+ if not docTemplate:
+ return False
+
+ descr = docTemplate.GetDescription() + _(" (") + docTemplate.GetFileFilter() + _(") |") + docTemplate.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
+ filename = wx.FileSelector(_("Save As"),
+ docTemplate.GetDirectory(),
+ FileNameFromPath(self.GetFilename()),
+ docTemplate.GetDefaultExtension(),
+ wildcard = descr,
+ flags = wx.SAVE | wx.OVERWRITE_PROMPT,
+ parent = self.GetDocumentWindow())
+ if filename == "":
+ return False
+
+ name, ext = os.path.splitext(filename)
+ if ext == "":
+ filename += '.' + docTemplate.GetDefaultExtension()
+
+ self.SetFilename(filename)
+ self.SetTitle(FileNameFromPath(filename))
+
+ for view in self._documentViews:
+ view.OnChangeFilename()
+
+ if not self.OnSaveDocument(filename):
+ return False
+
+ if docTemplate.FileMatchesTemplate(filename):
+ self.GetDocumentManager().AddFileToHistory(filename)
+
+ return True
+
+
+ def OnSaveDocument(self, filename):
+ """
+ Constructs an output file for the given filename (which must
+ not be empty), and calls SaveObject. If SaveObject returns true, the
+ document is set to unmodified; otherwise, an error message box is
+ displayed.
+ """
+ if not filename:
+ return False
+
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("File Error")
+
+ backupFilename = None
+ fileObject = None
+ copied = False
+ try:
+ # if current file exists, move it to a safe place temporarily
+ if os.path.exists(filename):
+
+ # Check if read-only.
+ if not os.access(filename, os.W_OK):
+ wx.MessageBox("Could not save '%s'. No write permission to overwrite existing file." % FileNameFromPath(filename),
+ msgTitle,
+ wx.OK | wx.ICON_EXCLAMATION,
+ self.GetDocumentWindow())
+ return False
+
+ i = 1
+ backupFilename = "%s.bak%s" % (filename, i)
+ while os.path.exists(backupFilename):
+ i += 1
+ backupFilename = "%s.bak%s" % (filename, i)
+ shutil.copy(filename, backupFilename)
+ copied = True
+
+ fileObject = file(filename, 'w')
+ self.SaveObject(fileObject)
+ fileObject.close()
+ fileObject = None
+
+ if backupFilename:
+ os.remove(backupFilename)
+ except:
+ # for debugging purposes
+ import traceback
+ traceback.print_exc()
+
+ if fileObject:
+ fileObject.close() # file is still open, close it, need to do this before removal
+
+ # save failed, remove copied file
+ if backupFilename and copied:
+ os.remove(backupFilename)
+
+ wx.MessageBox("Could not save '%s'. %s" % (FileNameFromPath(filename), sys.exc_value),
+ msgTitle,
+ wx.OK | wx.ICON_EXCLAMATION,
+ self.GetDocumentWindow())
+ return False
+
+ self.SetDocumentModificationDate()
+ self.SetFilename(filename, True)
+ self.Modify(False)
+ self.SetDocumentSaved(True)
+ #if wx.Platform == '__WXMAC__': # Not yet implemented in wxPython
+ # wx.FileName(file).MacSetDefaultTypeAndCreator()
+ return True
+
+
+ def OnOpenDocument(self, filename):
+ """
+ Constructs an input file for the given filename (which must not
+ be empty), and calls LoadObject. If LoadObject returns true, the
+ document is set to unmodified; otherwise, an error message box is
+ displayed. The document's views are notified that the filename has
+ changed, to give windows an opportunity to update their titles. All of
+ the document's views are then updated.
+ """
+ if not self.OnSaveModified():
+ return False
+
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("File Error")
+
+ fileObject = file(filename, 'r')
+ try:
+ self.LoadObject(fileObject)
+ fileObject.close()
+ fileObject = None
+ except:
+ # for debugging purposes
+ import traceback
+ traceback.print_exc()
+
+ if fileObject:
+ fileObject.close() # file is still open, close it
+
+ wx.MessageBox("Could not open '%s'. %s" % (FileNameFromPath(filename), sys.exc_value),
+ msgTitle,
+ wx.OK | wx.ICON_EXCLAMATION,
+ self.GetDocumentWindow())
+ return False
+
+ self.SetDocumentModificationDate()
+ self.SetFilename(filename, True)
+ self.Modify(False)
+ self.SetDocumentSaved(True)
+ self.UpdateAllViews()
+ return True
+
+
+ def LoadObject(self, file):
+ """
+ Override this function and call it from your own LoadObject before
+ loading your own data. LoadObject is called by the framework
+ automatically when the document contents need to be loaded.
+
+ Note that the wxPython version simply sends you a Python file object,
+ so you can use pickle.
+ """
+ return True
+
+
+ def SaveObject(self, file):
+ """
+ Override this function and call it from your own SaveObject before
+ saving your own data. SaveObject is called by the framework
+ automatically when the document contents need to be saved.
+
+ Note that the wxPython version simply sends you a Python file object,
+ so you can use pickle.
+ """
+ return True
+
+
+ def Revert(self):
+ """
+ Override this function to revert the document to its last saved state.
+ """
+ return False
+
+
+ def GetPrintableName(self):
+ """
+ Copies a suitable document name into the supplied name buffer.
+ The default function uses the title, or if there is no title, uses the
+ filename; or if no filename, the string 'Untitled'.
+ """
+ if self._documentTitle:
+ return self._documentTitle
+ elif self._documentFile:
+ return FileNameFromPath(self._documentFile)
+ else:
+ return _("Untitled")
+
+
+ def GetDocumentWindow(self):
+ """
+ Intended to return a suitable window for using as a parent for
+ document-related dialog boxes. By default, uses the frame associated
+ with the first view.
+ """
+ if len(self._documentViews) > 0:
+ return self._documentViews[0].GetFrame()
+ else:
+ return wx.GetApp().GetTopWindow()
+
+
+ def OnCreateCommandProcessor(self):
+ """
+ Override this function if you want a different (or no) command
+ processor to be created when the document is created. By default, it
+ returns an instance of wxCommandProcessor.
+ """
+ return CommandProcessor()
+
+
+ def OnSaveModified(self):
+ """
+ If the document has been modified, prompts the user to ask if the
+ changes should be changed. If the user replies Yes, the Save function
+ is called. If No, the document is marked as unmodified and the
+ function succeeds. If Cancel, the function fails.
+ """
+ if not self.IsModified():
+ return True
+
+ """ check for file modification outside of application """
+ if not self.IsDocumentModificationDateCorrect():
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("Warning")
+ res = wx.MessageBox(_("'%s' has been modified outside of %s. Overwrite '%s' with current changes?") % (self.GetPrintableName(), msgTitle, self.GetPrintableName()),
+ msgTitle,
+ wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION,
+ self.GetDocumentWindow())
+
+ if res == wx.NO:
+ self.Modify(False)
+ return True
+ elif res == wx.YES:
+ return wx.lib.docview.Document.Save(self)
+ else: # elif res == wx.CANCEL:
+ return False
+
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("Warning")
+
+ res = wx.MessageBox(_("Save changes to '%s'?") % self.GetPrintableName(),
+ msgTitle,
+ wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION,
+ self.GetDocumentWindow())
+
+ if res == wx.NO:
+ self.Modify(False)
+ return True
+ elif res == wx.YES:
+ return self.Save()
+ else: # elif res == wx.CANCEL:
+ return False
+
+
+ def Draw(context):
+ """
+ Called by printing framework to draw the view.
+ """
+ return True
+
+
+ def AddView(self, view):
+ """
+ If the view is not already in the list of views, adds the view and
+ calls OnChangedViewList.
+ """
+ if not view in self._documentViews:
+ self._documentViews.append(view)
+ self.OnChangedViewList()
+ return True
+
+
+ def RemoveView(self, view):
+ """
+ Removes the view from the document's list of views, and calls
+ OnChangedViewList.
+ """
+ if view in self._documentViews:
+ self._documentViews.remove(view)
+ self.OnChangedViewList()
+ return True
+
+
+ def OnCreate(self, path, flags):
+ """
+ The default implementation calls DeleteContents (an empty
+ implementation) sets the modified flag to false. Override this to
+ supply additional behaviour when the document is opened with Open.
+ """
+ if flags & DOC_NO_VIEW:
+ return True
+ return self.GetDocumentTemplate().CreateView(self, flags)
+
+
+ def OnChangedViewList(self):
+ """
+ Called when a view is added to or deleted from this document. The
+ default implementation saves and deletes the document if no views
+ exist (the last one has just been removed).
+ """
+ if len(self._documentViews) == 0:
+ if self.OnSaveModified():
+ pass # C version does a delete but Python will garbage collect
+
+
+ def UpdateAllViews(self, sender = None, hint = None):
+ """
+ Updates all views. If sender is non-NULL, does not update this view.
+ hint represents optional information to allow a view to optimize its
+ update.
+ """
+ for view in self._documentViews:
+ if view != sender:
+ view.OnUpdate(sender, hint)
+
+
+ def NotifyClosing(self):
+ """
+ Notifies the views that the document is going to close.
+ """
+ for view in self._documentViews:
+ view.OnClosingDocument()
+
+
+ def SetFilename(self, filename, notifyViews = False):
+ """
+ Sets the filename for this document. Usually called by the framework.
+ If notifyViews is true, wxView.OnChangeFilename is called for all
+ views.
+ """
+ self._documentFile = filename
+ if notifyViews:
+ for view in self._documentViews:
+ view.OnChangeFilename()
+
+
+ def GetWriteable(self):
+ """
+ Returns true if the document can be written to its accociated file path.
+ This method has been added to wxPython and is not in wxWindows.
+ """
+ if not self._writeable:
+ return False
+ if not self._documentFile: # Doesn't exist, do a save as
+ return True
+ else:
+ return os.access(self._documentFile, os.W_OK)
+
+
+ def SetWriteable(self, writeable):
+ """
+ Set to False if the document can not be saved. This will disable the ID_SAVE_AS
+ event and is useful for custom documents that should not be saveable. The ID_SAVE
+ event can be disabled by never Modifying the document. This method has been added
+ to wxPython and is not in wxWindows.
+ """
+ self._writeable = writeable
+
+
+class View(wx.EvtHandler):
+ """
+ The view class can be used to model the viewing and editing component of
+ an application's file-based data. It is part of the document/view
+ framework supported by wxWindows, and cooperates with the wxDocument,
+ wxDocTemplate and wxDocManager classes.
+ """
+
+ def __init__(self):
+ """
+ Constructor. Define your own default constructor to initialize
+ application-specific data.
+ """
+ wx.EvtHandler.__init__(self)
+ self._viewDocument = None
+ self._viewFrame = None
+
+
+ def Destroy(self):
+ """
+ Destructor. Removes itself from the document's list of views.
+ """
+ if self._viewDocument:
+ self._viewDocument.RemoveView(self)
+ wx.EvtHandler.Destroy(self)
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if not self.GetDocument() or not self.GetDocument().ProcessEvent(event):
+ return False
+ else:
+ return True
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ return False
+
+
+ def OnActivateView(self, activate, activeView, deactiveView):
+ """
+ Called when a view is activated by means of wxView::Activate. The
+ default implementation does nothing.
+ """
+ pass
+
+
+ def OnClosingDocument(self):
+ """
+ Override this to clean up the view when the document is being closed.
+ The default implementation does nothing.
+ """
+ pass
+
+
+ def OnDraw(self, dc):
+ """
+ Override this to draw the view for the printing framework. The
+ default implementation does nothing.
+ """
+ pass
+
+
+ def OnPrint(self, dc, info):
+ """
+ Override this to print the view for the printing framework. The
+ default implementation calls View.OnDraw.
+ """
+ self.OnDraw(dc)
+
+
+ def OnUpdate(self, sender, hint):
+ """
+ Called when the view should be updated. sender is a pointer to the
+ view that sent the update request, or NULL if no single view requested
+ the update (for instance, when the document is opened). hint is as yet
+ unused but may in future contain application-specific information for
+ making updating more efficient.
+ """
+ if hint:
+ if hint[0] == "modify": # if dirty flag changed, update the view's displayed title
+ frame = self.GetFrame()
+ if frame and hasattr(frame, "OnTitleIsModified"):
+ frame.OnTitleIsModified()
+ return True
+ return False
+
+
+ def OnChangeFilename(self):
+ """
+ Called when the filename has changed. The default implementation
+ constructs a suitable title and sets the title of the view frame (if
+ any).
+ """
+ if self.GetFrame():
+ appName = wx.GetApp().GetAppName()
+ if not self.GetDocument():
+ if appName:
+ title = appName
+ else:
+ return
+ else:
+ if appName and isinstance(self.GetFrame(), DocChildFrame): # Only need app name in title for SDI
+ title = appName + _(" - ")
+ else:
+ title = ''
+ self.GetFrame().SetTitle(title + self.GetDocument().GetPrintableName())
+
+
+ def GetDocument(self):
+ """
+ Returns the document associated with the view.
+ """
+ return self._viewDocument
+
+
+ def SetDocument(self, doc):
+ """
+ Associates the given document with the view. Normally called by the
+ framework.
+ """
+ self._viewDocument = doc
+ if doc:
+ doc.AddView(self)
+
+
+ def GetViewName(self):
+ """
+ Gets the name associated with the view (passed to the wxDocTemplate
+ constructor). Not currently used by the framework.
+ """
+ return self._viewTypeName
+
+
+ def SetViewName(self, name):
+ """
+ Sets the view type name. Should only be called by the framework.
+ """
+ self._viewTypeName = name
+
+
+ def Close(self, deleteWindow=True):
+ """
+ Closes the view by calling OnClose. If deleteWindow is true, this
+ function should delete the window associated with the view.
+ """
+ if self.OnClose(deleteWindow = deleteWindow):
+ return True
+ else:
+ return False
+
+
+ def Activate(self, activate=True):
+ """
+ Call this from your view frame's OnActivate member to tell the
+ framework which view is currently active. If your windowing system
+ doesn't call OnActivate, you may need to call this function from
+ OnMenuCommand or any place where you know the view must be active, and
+ the framework will need to get the current view.
+
+ The prepackaged view frame wxDocChildFrame calls wxView.Activate from
+ its OnActivate member and from its OnMenuCommand member.
+ """
+ if self.GetDocument() and self.GetDocumentManager():
+ self.OnActivateView(activate, self, self.GetDocumentManager().GetCurrentView())
+ self.GetDocumentManager().ActivateView(self, activate)
+
+
+ def OnClose(self, deleteWindow=True):
+ """
+ Implements closing behaviour. The default implementation calls
+ wxDocument.Close to close the associated document. Does not delete the
+ view. The application may wish to do some cleaning up operations in
+ this function, if a call to wxDocument::Close succeeded. For example,
+ if your application's all share the same window, you need to
+ disassociate the window from the view and perhaps clear the window. If
+ deleteWindow is true, delete the frame associated with the view.
+ """
+ if self.GetDocument():
+ return self.GetDocument().Close()
+ else:
+ return True
+
+
+ def OnCreate(self, doc, flags):
+ """
+ wxDocManager or wxDocument creates a wxView via a wxDocTemplate. Just
+ after the wxDocTemplate creates the wxView, it calls wxView::OnCreate.
+ In its OnCreate member function, the wxView can create a
+ wxDocChildFrame or a derived class. This wxDocChildFrame provides user
+ interface elements to view and/or edit the contents of the wxDocument.
+
+ By default, simply returns true. If the function returns false, the
+ view will be deleted.
+ """
+ return True
+
+
+ def OnCreatePrintout(self):
+ """
+ Returns a wxPrintout object for the purposes of printing. It should
+ create a new object every time it is called; the framework will delete
+ objects it creates.
+
+ By default, this function returns an instance of wxDocPrintout, which
+ prints and previews one page by calling wxView.OnDraw.
+
+ Override to return an instance of a class other than wxDocPrintout.
+ """
+ return DocPrintout(self, self.GetDocument().GetPrintableName())
+
+
+ def GetFrame(self):
+ """
+ Gets the frame associated with the view (if any). Note that this
+ "frame" is not a wxFrame at all in the generic MDI implementation
+ which uses the notebook pages instead of the frames and this is why
+ this method returns a wxWindow and not a wxFrame.
+ """
+ return self._viewFrame
+
+
+ def SetFrame(self, frame):
+ """
+ Sets the frame associated with this view. The application should call
+ this if possible, to tell the view about the frame. See GetFrame for
+ the explanation about the mismatch between the "Frame" in the method
+ name and the type of its parameter.
+ """
+ self._viewFrame = frame
+
+
+ def GetDocumentManager(self):
+ """
+ Returns the document manager instance associated with this view.
+ """
+ if self._viewDocument:
+ return self.GetDocument().GetDocumentManager()
+ else:
+ return None
+
+
+class DocTemplate(wx.Object):
+ """
+ The wxDocTemplate class is used to model the relationship between a
+ document class and a view class.
+ """
+
+
+ def __init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags=DEFAULT_TEMPLATE_FLAGS, icon=None):
+ """
+ Constructor. Create instances dynamically near the start of your
+ application after creating a wxDocManager instance, and before doing
+ any document or view operations.
+
+ manager is the document manager object which manages this template.
+
+ description is a short description of what the template is for. This
+ string will be displayed in the file filter list of Windows file
+ selectors.
+
+ filter is an appropriate file filter such as \*.txt.
+
+ dir is the default directory to use for file selectors.
+
+ ext is the default file extension (such as txt).
+
+ docTypeName is a name that should be unique for a given type of
+ document, used for gathering a list of views relevant to a
+ particular document.
+
+ viewTypeName is a name that should be unique for a given view.
+
+ docClass is a Python class. If this is not supplied, you will need to
+ derive a new wxDocTemplate class and override the CreateDocument
+ member to return a new document instance on demand.
+
+ viewClass is a Python class. If this is not supplied, you will need to
+ derive a new wxDocTemplate class and override the CreateView member to
+ return a new view instance on demand.
+
+ flags is a bit list of the following:
+ wx.TEMPLATE_VISIBLE The template may be displayed to the user in
+ dialogs.
+
+ wx.TEMPLATE_INVISIBLE The template may not be displayed to the user in
+ dialogs.
+
+ wx.DEFAULT_TEMPLATE_FLAGS Defined as wxTEMPLATE_VISIBLE.
+ """
+ self._docManager = manager
+ self._description = description
+ self._fileFilter = filter
+ self._directory = dir
+ self._defaultExt = ext
+ self._docTypeName = docTypeName
+ self._viewTypeName = viewTypeName
+ self._docType = docType
+ self._viewType = viewType
+ self._flags = flags
+ self._icon = icon
+
+ self._docManager.AssociateTemplate(self)
+
+
+ def GetDefaultExtension(self):
+ """
+ Returns the default file extension for the document data, as passed to
+ the document template constructor.
+ """
+ return self._defaultExt
+
+
+ def SetDefaultExtension(self, defaultExt):
+ """
+ Sets the default file extension.
+ """
+ self._defaultExt = defaultExt
+
+
+ def GetDescription(self):
+ """
+ Returns the text description of this template, as passed to the
+ document template constructor.
+ """
+ return self._description
+
+
+ def SetDescription(self, description):
+ """
+ Sets the template description.
+ """
+ self._description = description
+
+
+ def GetDirectory(self):
+ """
+ Returns the default directory, as passed to the document template
+ constructor.
+ """
+ return self._directory
+
+
+ def SetDirectory(self, dir):
+ """
+ Sets the default directory.
+ """
+ self._directory = dir
+
+
+ def GetDocumentManager(self):
+ """
+ Returns the document manager instance for which this template was
+ created.
+ """
+ return self._docManager
+
+
+ def SetDocumentManager(self, manager):
+ """
+ Sets the document manager instance for which this template was
+ created. Should not be called by the application.
+ """
+ self._docManager = manager
+
+
+ def GetFileFilter(self):
+ """
+ Returns the file filter, as passed to the document template
+ constructor.
+ """
+ return self._fileFilter
+
+
+ def SetFileFilter(self, filter):
+ """
+ Sets the file filter.
+ """
+ self._fileFilter = filter
+
+
+ def GetFlags(self):
+ """
+ Returns the flags, as passed to the document template constructor.
+ (see the constructor description for more details).
+ """
+ return self._flags
+
+
+ def SetFlags(self, flags):
+ """
+ Sets the internal document template flags (see the constructor
+ description for more details).
+ """
+ self._flags = flags
+
+
+ def GetIcon(self):
+ """
+ Returns the icon, as passed to the document template
+ constructor. This method has been added to wxPython and is
+ not in wxWindows.
+ """
+ return self._icon
+
+
+ def SetIcon(self, flags):
+ """
+ Sets the icon. This method has been added to wxPython and is not
+ in wxWindows.
+ """
+ self._icon = icon
+
+
+ def GetDocumentType(self):
+ """
+ Returns the Python document class, as passed to the document template
+ constructor.
+ """
+ return self._docType
+
+
+ def GetViewType(self):
+ """
+ Returns the Python view class, as passed to the document template
+ constructor.
+ """
+ return self._viewType
+
+
+ def IsVisible(self):
+ """
+ Returns true if the document template can be shown in user dialogs,
+ false otherwise.
+ """
+ return (self._flags & TEMPLATE_VISIBLE) == TEMPLATE_VISIBLE
+
+
+ def IsNewable(self):
+ """
+ Returns true if the document template can be shown in "New" dialogs,
+ false otherwise.
+
+ This method has been added to wxPython and is not in wxWindows.
+ """
+ return (self._flags & TEMPLATE_NO_CREATE) != TEMPLATE_NO_CREATE
+
+
+ def GetDocumentName(self):
+ """
+ Returns the document type name, as passed to the document template
+ constructor.
+ """
+ return self._docTypeName
+
+
+ def GetViewName(self):
+ """
+ Returns the view type name, as passed to the document template
+ constructor.
+ """
+ return self._viewTypeName
+
+
+ def CreateDocument(self, path, flags):
+ """
+ Creates a new instance of the associated document class. If you have
+ not supplied a class to the template constructor, you will need to
+ override this function to return an appropriate document instance.
+ """
+ doc = self._docType()
+ doc.SetFilename(path)
+ doc.SetDocumentTemplate(self)
+ self.GetDocumentManager().AddDocument(doc)
+ doc.SetCommandProcessor(doc.OnCreateCommandProcessor())
+ if doc.OnCreate(path, flags):
+ return doc
+ else:
+ if doc in self.GetDocumentManager().GetDocuments():
+ doc.DeleteAllViews()
+ return None
+
+
+ def CreateView(self, doc, flags):
+ """
+ Creates a new instance of the associated document view. If you have
+ not supplied a class to the template constructor, you will need to
+ override this function to return an appropriate view instance.
+ """
+ view = self._viewType()
+ view.SetDocument(doc)
+ if view.OnCreate(doc, flags):
+ return view
+ else:
+ view.Destroy()
+ return None
+
+
+ def FileMatchesTemplate(self, path):
+ """
+ Returns True if the path's extension matches one of this template's
+ file filter extensions.
+ """
+ ext = FindExtension(path)
+ if not ext: return False
+
+ extList = self.GetFileFilter().replace('*','').split(';')
+ return ext in extList
+
+
+class DocManager(wx.EvtHandler):
+ """
+ The wxDocManager class is part of the document/view framework supported by
+ wxWindows, and cooperates with the wxView, wxDocument and wxDocTemplate
+ classes.
+ """
+
+ def __init__(self, flags=DEFAULT_DOCMAN_FLAGS, initialize=True):
+ """
+ Constructor. Create a document manager instance dynamically near the
+ start of your application before doing any document or view operations.
+
+ flags is used in the Python version to indicate whether the document
+ manager is in DOC_SDI or DOC_MDI mode.
+
+ If initialize is true, the Initialize function will be called to
+ create a default history list object. If you derive from wxDocManager,
+ you may wish to call the base constructor with false, and then call
+ Initialize in your own constructor, to allow your own Initialize or
+ OnCreateFileHistory functions to be called.
+ """
+
+ wx.EvtHandler.__init__(self)
+
+ self._defaultDocumentNameCounter = 1
+ self._flags = flags
+ self._currentView = None
+ self._lastActiveView = None
+ self._maxDocsOpen = 10000
+ self._fileHistory = None
+ self._templates = []
+ self._docs = []
+ self._lastDirectory = ""
+
+ if initialize:
+ self.Initialize()
+
+ wx.EVT_MENU(self, wx.ID_OPEN, self.OnFileOpen)
+ wx.EVT_MENU(self, wx.ID_CLOSE, self.OnFileClose)
+ wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.OnFileCloseAll)
+ wx.EVT_MENU(self, wx.ID_REVERT, self.OnFileRevert)
+ wx.EVT_MENU(self, wx.ID_NEW, self.OnFileNew)
+ wx.EVT_MENU(self, wx.ID_SAVE, self.OnFileSave)
+ wx.EVT_MENU(self, wx.ID_SAVEAS, self.OnFileSaveAs)
+ wx.EVT_MENU(self, wx.ID_UNDO, self.OnUndo)
+ wx.EVT_MENU(self, wx.ID_REDO, self.OnRedo)
+ wx.EVT_MENU(self, wx.ID_PRINT, self.OnPrint)
+ wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.OnPrintSetup)
+ wx.EVT_MENU(self, wx.ID_PREVIEW, self.OnPreview)
+
+ wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.OnUpdateFileOpen)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.OnUpdateFileClose)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.OnUpdateFileCloseAll)
+ wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.OnUpdateFileRevert)
+ wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.OnUpdateFileNew)
+ wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.OnUpdateFileSave)
+ wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.OnUpdateFileSaveAs)
+ wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.OnUpdateUndo)
+ wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.OnUpdateRedo)
+ wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.OnUpdatePrint)
+ wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.OnUpdatePrintSetup)
+ wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.OnUpdatePreview)
+
+
+ def Destroy(self):
+ """
+ Destructor.
+ """
+ self.Clear()
+ wx.EvtHandler.Destroy(self)
+
+
+ def GetFlags(self):
+ """
+ Returns the document manager's flags. This method has been
+ added to wxPython and is not in wxWindows.
+ """
+ return self._flags
+
+
+ def CloseDocument(self, doc, force=True):
+ """
+ Closes the specified document.
+ """
+ if doc.Close() or force:
+ doc.DeleteAllViews()
+ if doc in self._docs:
+ doc.Destroy()
+ return True
+ return False
+
+
+ def CloseDocuments(self, force=True):
+ """
+ Closes all currently opened documents.
+ """
+ for document in self._docs[::-1]: # Close in lifo (reverse) order. We clone the list to make sure we go through all docs even as they are deleted
+ if not self.CloseDocument(document, force):
+ return False
+ if document:
+ document.DeleteAllViews() # Implicitly delete the document when the last view is removed
+ return True
+
+
+ def Clear(self, force=True):
+ """
+ Closes all currently opened document by callling CloseDocuments and
+ clears the document manager's templates.
+ """
+ if not self.CloseDocuments(force):
+ return False
+ self._templates = []
+ return True
+
+
+ def Initialize(self):
+ """
+ Initializes data; currently just calls OnCreateFileHistory. Some data
+ cannot always be initialized in the constructor because the programmer
+ must be given the opportunity to override functionality. In fact
+ Initialize is called from the wxDocManager constructor, but this can
+ be vetoed by passing false to the second argument, allowing the
+ derived class's constructor to call Initialize, possibly calling a
+ different OnCreateFileHistory from the default.
+
+ The bottom line: if you're not deriving from Initialize, forget it and
+ construct wxDocManager with no arguments.
+ """
+ self.OnCreateFileHistory()
+ return True
+
+
+ def OnCreateFileHistory(self):
+ """
+ A hook to allow a derived class to create a different type of file
+ history. Called from Initialize.
+ """
+ self._fileHistory = wx.FileHistory()
+
+
+ def OnFileClose(self, event):
+ """
+ Closes and deletes the currently active document.
+ """
+ doc = self.GetCurrentDocument()
+ if doc:
+ doc.DeleteAllViews()
+ if doc in self._docs:
+ self._docs.remove(doc)
+
+
+ def OnFileCloseAll(self, event):
+ """
+ Closes and deletes all the currently opened documents.
+ """
+ return self.CloseDocuments(force = False)
+
+
+ def OnFileNew(self, event):
+ """
+ Creates a new document and reads in the selected file.
+ """
+ self.CreateDocument('', DOC_NEW)
+
+
+ def OnFileOpen(self, event):
+ """
+ Creates a new document and reads in the selected file.
+ """
+ if not self.CreateDocument('', DEFAULT_DOCMAN_FLAGS):
+ self.OnOpenFileFailure()
+
+
+ def OnFileRevert(self, event):
+ """
+ Reverts the current document by calling wxDocument.Save for the current
+ document.
+ """
+ doc = self.GetCurrentDocument()
+ if not doc:
+ return
+ doc.Revert()
+
+
+ def OnFileSave(self, event):
+ """
+ Saves the current document by calling wxDocument.Save for the current
+ document.
+ """
+ doc = self.GetCurrentDocument()
+ if not doc:
+ return
+ doc.Save()
+
+
+ def OnFileSaveAs(self, event):
+ """
+ Calls wxDocument.SaveAs for the current document.
+ """
+ doc = self.GetCurrentDocument()
+ if not doc:
+ return
+ doc.SaveAs()
+
+
+ def OnPrint(self, event):
+ """
+ Prints the current document by calling its View's OnCreatePrintout
+ method.
+ """
+ view = self.GetCurrentView()
+ if not view:
+ return
+
+ printout = view.OnCreatePrintout()
+ if printout:
+ if not hasattr(self, "printData"):
+ self.printData = wx.PrintData()
+ self.printData.SetPaperId(wx.PAPER_LETTER)
+ self.printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
+
+ pdd = wx.PrintDialogData(self.printData)
+ printer = wx.Printer(pdd)
+ printer.Print(view.GetFrame(), printout)
+
+
+ def OnPrintSetup(self, event):
+ """
+ Presents the print setup dialog.
+ """
+ view = self.GetCurrentView()
+ if view:
+ parentWin = view.GetFrame()
+ else:
+ parentWin = wx.GetApp().GetTopWindow()
+
+ if not hasattr(self, "printData"):
+ self.printData = wx.PrintData()
+ self.printData.SetPaperId(wx.PAPER_LETTER)
+
+ data = wx.PrintDialogData(self.printData)
+ printDialog = wx.PrintDialog(parentWin, data)
+ printDialog.GetPrintDialogData().SetSetupDialog(True)
+ printDialog.ShowModal()
+
+ # this makes a copy of the wx.PrintData instead of just saving
+ # a reference to the one inside the PrintDialogData that will
+ # be destroyed when the dialog is destroyed
+ self.printData = wx.PrintData(printDialog.GetPrintDialogData().GetPrintData())
+
+ printDialog.Destroy()
+
+
+ def OnPreview(self, event):
+ """
+ Previews the current document by calling its View's OnCreatePrintout
+ method.
+ """
+ view = self.GetCurrentView()
+ if not view:
+ return
+
+ printout = view.OnCreatePrintout()
+ if printout:
+ if not hasattr(self, "printData"):
+ self.printData = wx.PrintData()
+ self.printData.SetPaperId(wx.PAPER_LETTER)
+ self.printData.SetPrintMode(wx.PRINT_MODE_PREVIEW)
+
+ data = wx.PrintDialogData(self.printData)
+ # Pass two printout objects: for preview, and possible printing.
+ preview = wx.PrintPreview(printout, view.OnCreatePrintout(), data)
+ if not preview.Ok():
+ wx.MessageBox(_("Unable to display print preview."))
+ return
+ # wxWindows source doesn't use base frame's pos, size, and icon, but did it this way so it would work like MS Office etc.
+ mimicFrame = wx.GetApp().GetTopWindow()
+ frame = wx.PreviewFrame(preview, mimicFrame, _("Print Preview"), mimicFrame.GetPosition(), mimicFrame.GetSize())
+ frame.SetIcon(mimicFrame.GetIcon())
+ frame.SetTitle(_("%s - %s - Preview") % (mimicFrame.GetTitle(), view.GetDocument().GetPrintableName()))
+ frame.Initialize()
+ frame.Show(True)
+
+
+ def OnUndo(self, event):
+ """
+ Issues an Undo command to the current document's command processor.
+ """
+ doc = self.GetCurrentDocument()
+ if not doc:
+ return
+ if doc.GetCommandProcessor():
+ doc.GetCommandProcessor().Undo()
+
+
+ def OnRedo(self, event):
+ """
+ Issues a Redo command to the current document's command processor.
+ """
+ doc = self.GetCurrentDocument()
+ if not doc:
+ return
+ if doc.GetCommandProcessor():
+ doc.GetCommandProcessor().Redo()
+
+
+ def OnUpdateFileOpen(self, event):
+ """
+ Updates the user interface for the File Open command.
+ """
+ event.Enable(True)
+
+
+ def OnUpdateFileClose(self, event):
+ """
+ Updates the user interface for the File Close command.
+ """
+ event.Enable(self.GetCurrentDocument() != None)
+
+
+ def OnUpdateFileCloseAll(self, event):
+ """
+ Updates the user interface for the File Close All command.
+ """
+ event.Enable(self.GetCurrentDocument() != None)
+
+
+ def OnUpdateFileRevert(self, event):
+ """
+ Updates the user interface for the File Revert command.
+ """
+ event.Enable(self.GetCurrentDocument() != None)
+
+
+ def OnUpdateFileNew(self, event):
+ """
+ Updates the user interface for the File New command.
+ """
+ return True
+
+
+ def OnUpdateFileSave(self, event):
+ """
+ Updates the user interface for the File Save command.
+ """
+ doc = self.GetCurrentDocument()
+ event.Enable(doc != None and doc.IsModified())
+
+
+ def OnUpdateFileSaveAs(self, event):
+ """
+ Updates the user interface for the File Save As command.
+ """
+ event.Enable(self.GetCurrentDocument() != None and self.GetCurrentDocument().GetWriteable())
+
+
+ def OnUpdateUndo(self, event):
+ """
+ Updates the user interface for the Undo command.
+ """
+ doc = self.GetCurrentDocument()
+ event.Enable(doc != None and doc.GetCommandProcessor() != None and doc.GetCommandProcessor().CanUndo())
+ if doc and doc.GetCommandProcessor():
+ doc.GetCommandProcessor().SetMenuStrings()
+ else:
+ event.SetText(_("&Undo\tCtrl+Z"))
+
+
+ def OnUpdateRedo(self, event):
+ """
+ Updates the user interface for the Redo command.
+ """
+ doc = self.GetCurrentDocument()
+ event.Enable(doc != None and doc.GetCommandProcessor() != None and doc.GetCommandProcessor().CanRedo())
+ if doc and doc.GetCommandProcessor():
+ doc.GetCommandProcessor().SetMenuStrings()
+ else:
+ event.SetText(_("&Redo\tCtrl+Y"))
+
+
+ def OnUpdatePrint(self, event):
+ """
+ Updates the user interface for the Print command.
+ """
+ event.Enable(self.GetCurrentDocument() != None)
+
+
+ def OnUpdatePrintSetup(self, event):
+ """
+ Updates the user interface for the Print Setup command.
+ """
+ return True
+
+
+ def OnUpdatePreview(self, event):
+ """
+ Updates the user interface for the Print Preview command.
+ """
+ event.Enable(self.GetCurrentDocument() != None)
+
+
+ def GetCurrentView(self):
+ """
+ Returns the currently active view.
+ """
+ if self._currentView:
+ return self._currentView
+ if len(self._docs) == 1:
+ return self._docs[0].GetFirstView()
+ return None
+
+
+ def GetLastActiveView(self):
+ """
+ Returns the last active view. This is used in the SDI framework where dialogs can be mistaken for a view
+ and causes the framework to deactivete the current view. This happens when something like a custom dialog box used
+ to operate on the current view is shown.
+ """
+ if len(self._docs) >= 1:
+ return self._lastActiveView
+ else:
+ return None
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ view = self.GetCurrentView()
+ if view:
+ if view.ProcessEvent(event):
+ return True
+ id = event.GetId()
+ if id == wx.ID_OPEN:
+ self.OnFileOpen(event)
+ return True
+ elif id == wx.ID_CLOSE:
+ self.OnFileClose(event)
+ return True
+ elif id == wx.ID_CLOSE_ALL:
+ self.OnFileCloseAll(event)
+ return True
+ elif id == wx.ID_REVERT:
+ self.OnFileRevert(event)
+ return True
+ elif id == wx.ID_NEW:
+ self.OnFileNew(event)
+ return True
+ elif id == wx.ID_SAVE:
+ self.OnFileSave(event)
+ return True
+ elif id == wx.ID_SAVEAS:
+ self.OnFileSaveAs(event)
+ return True
+ elif id == wx.ID_UNDO:
+ self.OnUndo(event)
+ return True
+ elif id == wx.ID_REDO:
+ self.OnRedo(event)
+ return True
+ elif id == wx.ID_PRINT:
+ self.OnPrint(event)
+ return True
+ elif id == wx.ID_PRINT_SETUP:
+ self.OnPrintSetup(event)
+ return True
+ elif id == wx.ID_PREVIEW:
+ self.OnPreview(event)
+ return True
+ else:
+ return False
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ id = event.GetId()
+ view = self.GetCurrentView()
+ if view:
+ if view.ProcessUpdateUIEvent(event):
+ return True
+ if id == wx.ID_OPEN:
+ self.OnUpdateFileOpen(event)
+ return True
+ elif id == wx.ID_CLOSE:
+ self.OnUpdateFileClose(event)
+ return True
+ elif id == wx.ID_CLOSE_ALL:
+ self.OnUpdateFileCloseAll(event)
+ return True
+ elif id == wx.ID_REVERT:
+ self.OnUpdateFileRevert(event)
+ return True
+ elif id == wx.ID_NEW:
+ self.OnUpdateFileNew(event)
+ return True
+ elif id == wx.ID_SAVE:
+ self.OnUpdateFileSave(event)
+ return True
+ elif id == wx.ID_SAVEAS:
+ self.OnUpdateFileSaveAs(event)
+ return True
+ elif id == wx.ID_UNDO:
+ self.OnUpdateUndo(event)
+ return True
+ elif id == wx.ID_REDO:
+ self.OnUpdateRedo(event)
+ return True
+ elif id == wx.ID_PRINT:
+ self.OnUpdatePrint(event)
+ return True
+ elif id == wx.ID_PRINT_SETUP:
+ self.OnUpdatePrintSetup(event)
+ return True
+ elif id == wx.ID_PREVIEW:
+ self.OnUpdatePreview(event)
+ return True
+ else:
+ return False
+
+
+ def CreateDocument(self, path, flags=0):
+ """
+ Creates a new document in a manner determined by the flags parameter,
+ which can be:
+
+ wx.lib.docview.DOC_NEW Creates a fresh document.
+ wx.lib.docview.DOC_SILENT Silently loads the given document file.
+
+ If wx.lib.docview.DOC_NEW is present, a new document will be created and returned,
+ possibly after asking the user for a template to use if there is more
+ than one document template. If wx.lib.docview.DOC_SILENT is present, a new document
+ will be created and the given file loaded into it. If neither of these
+ flags is present, the user will be presented with a file selector for
+ the file to load, and the template to use will be determined by the
+ extension (Windows) or by popping up a template choice list (other
+ platforms).
+
+ If the maximum number of documents has been reached, this function
+ will delete the oldest currently loaded document before creating a new
+ one.
+
+ wxPython version supports the document manager's wx.lib.docview.DOC_OPEN_ONCE
+ and wx.lib.docview.DOC_NO_VIEW flag.
+
+ if wx.lib.docview.DOC_OPEN_ONCE is present, trying to open the same file multiple
+ times will just return the same document.
+ if wx.lib.docview.DOC_NO_VIEW is present, opening a file will generate the document,
+ but not generate a corresponding view.
+ """
+ templates = []
+ for temp in self._templates:
+ if temp.IsVisible():
+ templates.append(temp)
+ if len(templates) == 0:
+ return None
+
+ if len(self.GetDocuments()) >= self._maxDocsOpen:
+ doc = self.GetDocuments()[0]
+ if not self.CloseDocument(doc, False):
+ return None
+
+ if flags & DOC_NEW:
+ for temp in templates[:]:
+ if not temp.IsNewable():
+ templates.remove(temp)
+ if len(templates) == 1:
+ temp = templates[0]
+ else:
+ temp = self.SelectDocumentType(templates)
+ if temp:
+ newDoc = temp.CreateDocument(path, flags)
+ if newDoc:
+ newDoc.SetDocumentName(temp.GetDocumentName())
+ newDoc.SetDocumentTemplate(temp)
+ newDoc.OnNewDocument()
+ return newDoc
+ else:
+ return None
+
+ if path and flags & DOC_SILENT:
+ temp = self.FindTemplateForPath(path)
+ else:
+ temp, path = self.SelectDocumentPath(templates, path, flags)
+
+ # Existing document
+ if path and self.GetFlags() & DOC_OPEN_ONCE:
+ for document in self._docs:
+ if document.GetFilename() and os.path.normcase(document.GetFilename()) == os.path.normcase(path):
+ """ check for file modification outside of application """
+ if not document.IsDocumentModificationDateCorrect():
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("Warning")
+ shortName = document.GetPrintableName()
+ res = wx.MessageBox(_("'%s' has been modified outside of %s. Reload '%s' from file system?") % (shortName, msgTitle, shortName),
+ msgTitle,
+ wx.YES_NO | wx.ICON_QUESTION,
+ self.FindSuitableParent())
+ if res == wx.YES:
+ if not self.CloseDocument(document, False):
+ wx.MessageBox(_("Couldn't reload '%s'. Unable to close current '%s'.") % (shortName, shortName))
+ return None
+ return self.CreateDocument(path, flags)
+ elif res == wx.NO: # don't ask again
+ document.SetDocumentModificationDate()
+
+ firstView = document.GetFirstView()
+ if not firstView and not (flags & DOC_NO_VIEW):
+ document.GetDocumentTemplate().CreateView(document, flags)
+ document.UpdateAllViews()
+ firstView = document.GetFirstView()
+
+ if firstView and firstView.GetFrame() and not (flags & DOC_NO_VIEW):
+ firstView.GetFrame().SetFocus() # Not in wxWindows code but useful nonetheless
+ if hasattr(firstView.GetFrame(), "IsIconized") and firstView.GetFrame().IsIconized(): # Not in wxWindows code but useful nonetheless
+ firstView.GetFrame().Iconize(False)
+ return None
+
+ if temp:
+ newDoc = temp.CreateDocument(path, flags)
+ if newDoc:
+ newDoc.SetDocumentName(temp.GetDocumentName())
+ newDoc.SetDocumentTemplate(temp)
+ if not newDoc.OnOpenDocument(path):
+ frame = newDoc.GetFirstView().GetFrame()
+ newDoc.DeleteAllViews() # Implicitly deleted by DeleteAllViews
+ if frame:
+ frame.Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it.
+ return None
+ self.AddFileToHistory(path)
+ return newDoc
+
+ return None
+
+
+ def CreateView(self, doc, flags=0):
+ """
+ Creates a new view for the given document. If more than one view is
+ allowed for the document (by virtue of multiple templates mentioning
+ the same document type), a choice of view is presented to the user.
+ """
+ templates = []
+ for temp in self._templates:
+ if temp.IsVisible():
+ if temp.GetDocumentName() == doc.GetDocumentName():
+ templates.append(temp)
+ if len(templates) == 0:
+ return None
+
+ if len(templates) == 1:
+ temp = templates[0]
+ view = temp.CreateView(doc, flags)
+ if view:
+ view.SetViewName(temp.GetViewName())
+ return view
+
+ temp = SelectViewType(templates)
+ if temp:
+ view = temp.CreateView(doc, flags)
+ if view:
+ view.SetViewName(temp.GetViewName())
+ return view
+ else:
+ return None
+
+
+ def DeleteTemplate(self, template, flags):
+ """
+ Placeholder, not yet implemented in wxWindows.
+ """
+ pass
+
+
+ def FlushDoc(self, doc):
+ """
+ Placeholder, not yet implemented in wxWindows.
+ """
+ return False
+
+
+ def MatchTemplate(self, path):
+ """
+ Placeholder, not yet implemented in wxWindows.
+ """
+ return None
+
+
+ def GetCurrentDocument(self):
+ """
+ Returns the document associated with the currently active view (if any).
+ """
+ view = self.GetCurrentView()
+ if view:
+ return view.GetDocument()
+ else:
+ return None
+
+
+ def MakeDefaultName(self):
+ """
+ Returns a suitable default name. This is implemented by appending an
+ integer counter to the string "Untitled" and incrementing the counter.
+ """
+ name = _("Untitled %d") % self._defaultDocumentNameCounter
+ self._defaultDocumentNameCounter = self._defaultDocumentNameCounter + 1
+ return name
+
+
+ def MakeFrameTitle(self):
+ """
+ Returns a suitable title for a document frame. This is implemented by
+ appending the document name to the application name.
+ """
+ appName = wx.GetApp().GetAppName()
+ if not doc:
+ title = appName
+ else:
+ docName = doc.GetPrintableName()
+ title = docName + _(" - ") + appName
+ return title
+
+
+ def AddFileToHistory(self, fileName):
+ """
+ Adds a file to the file history list, if we have a pointer to an
+ appropriate file menu.
+ """
+ if self._fileHistory:
+ self._fileHistory.AddFileToHistory(fileName)
+
+
+ def RemoveFileFromHistory(self, i):
+ """
+ Removes a file from the file history list, if we have a pointer to an
+ appropriate file menu.
+ """
+ if self._fileHistory:
+ self._fileHistory.RemoveFileFromHistory(i)
+
+
+ def GetFileHistory(self):
+ """
+ Returns the file history.
+ """
+ return self._fileHistory
+
+
+ def GetHistoryFile(self, i):
+ """
+ Returns the file at index i from the file history.
+ """
+ if self._fileHistory:
+ return self._fileHistory.GetHistoryFile(i)
+ else:
+ return None
+
+
+ def FileHistoryUseMenu(self, menu):
+ """
+ Use this menu for appending recently-visited document filenames, for
+ convenient access. Calling this function with a valid menu enables the
+ history list functionality.
+
+ Note that you can add multiple menus using this function, to be
+ managed by the file history object.
+ """
+ if self._fileHistory:
+ self._fileHistory.UseMenu(menu)
+
+
+ def FileHistoryRemoveMenu(self, menu):
+ """
+ Removes the given menu from the list of menus managed by the file
+ history object.
+ """
+ if self._fileHistory:
+ self._fileHistory.RemoveMenu(menu)
+
+
+ def FileHistoryLoad(self, config):
+ """
+ Loads the file history from a config object.
+ """
+ if self._fileHistory:
+ self._fileHistory.Load(config)
+
+
+ def FileHistorySave(self, config):
+ """
+ Saves the file history into a config object. This must be called
+ explicitly by the application.
+ """
+ if self._fileHistory:
+ self._fileHistory.Save(config)
+
+
+ def FileHistoryAddFilesToMenu(self, menu=None):
+ """
+ Appends the files in the history list, to all menus managed by the
+ file history object.
+
+ If menu is specified, appends the files in the history list to the
+ given menu only.
+ """
+ if self._fileHistory:
+ if menu:
+ self._fileHistory.AddFilesToThisMenu(menu)
+ else:
+ self._fileHistory.AddFilesToMenu()
+
+
+ def GetHistoryFilesCount(self):
+ """
+ Returns the number of files currently stored in the file history.
+ """
+ if self._fileHistory:
+ return self._fileHistory.GetNoHistoryFiles()
+ else:
+ return 0
+
+
+ def FindTemplateForPath(self, path):
+ """
+ Given a path, try to find template that matches the extension. This is
+ only an approximate method of finding a template for creating a
+ document.
+
+ Note this wxPython verson looks for and returns a default template if no specific template is found.
+ """
+ default = None
+ for temp in self._templates:
+ if temp.FileMatchesTemplate(path):
+ return temp
+
+ if "*.*" in temp.GetFileFilter():
+ default = temp
+ return default
+
+
+ def FindSuitableParent(self):
+ """
+ Returns a parent frame or dialog, either the frame with the current
+ focus or if there is no current focus the application's top frame.
+ """
+ parent = wx.GetApp().GetTopWindow()
+ focusWindow = wx.Window_FindFocus()
+ if focusWindow:
+ while focusWindow and not isinstance(focusWindow, wx.Dialog) and not isinstance(focusWindow, wx.Frame):
+ focusWindow = focusWindow.GetParent()
+ if focusWindow:
+ parent = focusWindow
+ return parent
+
+
+ def SelectDocumentPath(self, templates, flags, save):
+ """
+ Under Windows, pops up a file selector with a list of filters
+ corresponding to document templates. The wxDocTemplate corresponding
+ to the selected file's extension is returned.
+
+ On other platforms, if there is more than one document template a
+ choice list is popped up, followed by a file selector.
+
+ This function is used in wxDocManager.CreateDocument.
+ """
+ if wx.Platform == "__WXMSW__" or wx.Platform == "__WXGTK__" or wx.Platform == "__WXMAC__":
+ descr = ''
+ for temp in templates:
+ if temp.IsVisible():
+ if len(descr) > 0:
+ descr = descr + _('|')
+ descr = descr + temp.GetDescription() + _(" (") + temp.GetFileFilter() + _(") |") + temp.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
+ descr = _("All|*.*|%s") % descr # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
+ else:
+ descr = _("*.*")
+
+ dlg = wx.FileDialog(self.FindSuitableParent(),
+ _("Select a File"),
+ wildcard=descr,
+ style=wx.OPEN|wx.FILE_MUST_EXIST|wx.CHANGE_DIR)
+ # dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ else:
+ path = None
+ dlg.Destroy()
+
+ if path:
+ theTemplate = self.FindTemplateForPath(path)
+ return (theTemplate, path)
+
+ return (None, None)
+
+
+ def OnOpenFileFailure(self):
+ """
+ Called when there is an error opening a file.
+ """
+ pass
+
+
+ def SelectDocumentType(self, temps, sort=False):
+ """
+ Returns a document template by asking the user (if there is more than
+ one template). This function is used in wxDocManager.CreateDocument.
+
+ Parameters
+
+ templates - list of templates from which to choose a desired template.
+
+ sort - If more than one template is passed in in templates, then this
+ parameter indicates whether the list of templates that the user will
+ have to choose from is sorted or not when shown the choice box dialog.
+ Default is false.
+ """
+ templates = []
+ for temp in temps:
+ if temp.IsVisible():
+ want = True
+ for temp2 in templates:
+ if temp.GetDocumentName() == temp2.GetDocumentName() and temp.GetViewName() == temp2.GetViewName():
+ want = False
+ break
+ if want:
+ templates.append(temp)
+
+ if len(templates) == 0:
+ return None
+ elif len(templates) == 1:
+ return templates[0]
+
+ if sort:
+ def tempcmp(a, b):
+ return cmp(a.GetDescription(), b.GetDescription())
+ templates.sort(tempcmp)
+
+ strings = []
+ for temp in templates:
+ strings.append(temp.GetDescription())
+
+ res = wx.GetSingleChoiceIndex(_("Select a document type:"),
+ _("Documents"),
+ strings,
+ self.FindSuitableParent())
+ if res == -1:
+ return None
+ return templates[res]
+
+
+ def SelectViewType(self, temps, sort=False):
+ """
+ Returns a document template by asking the user (if there is more than one template), displaying a list of valid views. This function is used in wxDocManager::CreateView. The dialog normally will not appear because the array of templates only contains those relevant to the document in question, and often there will only be one such.
+ """
+ templates = []
+ strings = []
+ for temp in temps:
+ if temp.IsVisible() and temp.GetViewTypeName():
+ if temp.GetViewName() not in strings:
+ templates.append(temp)
+ strings.append(temp.GetViewTypeName())
+
+ if len(templates) == 0:
+ return None
+ elif len(templates) == 1:
+ return templates[0]
+
+ if sort:
+ def tempcmp(a, b):
+ return cmp(a.GetViewTypeName(), b.GetViewTypeName())
+ templates.sort(tempcmp)
+
+ res = wx.GetSingleChoiceIndex(_("Select a document view:"),
+ _("Views"),
+ strings,
+ self.FindSuitableParent())
+ if res == -1:
+ return None
+ return templates[res]
+
+
+ def GetTemplates(self):
+ """
+ Returns the document manager's template list. This method has been added to
+ wxPython and is not in wxWindows.
+ """
+ return self._templates
+
+
+ def AssociateTemplate(self, docTemplate):
+ """
+ Adds the template to the document manager's template list.
+ """
+ if docTemplate not in self._templates:
+ self._templates.append(docTemplate)
+
+
+ def DisassociateTemplate(self, docTemplate):
+ """
+ Removes the template from the list of templates.
+ """
+ self._templates.remove(docTemplate)
+
+
+ def AddDocument(self, document):
+ """
+ Adds the document to the list of documents.
+ """
+ if document not in self._docs:
+ self._docs.append(document)
+
+
+ def RemoveDocument(self, doc):
+ """
+ Removes the document from the list of documents.
+ """
+ if doc in self._docs:
+ self._docs.remove(doc)
+
+
+ def ActivateView(self, view, activate=True, deleting=False):
+ """
+ Sets the current view.
+ """
+ if activate:
+ self._currentView = view
+ self._lastActiveView = view
+ else:
+ self._currentView = None
+
+
+ def GetMaxDocsOpen(self):
+ """
+ Returns the number of documents that can be open simultaneously.
+ """
+ return self._maxDocsOpen
+
+
+ def SetMaxDocsOpen(self, maxDocsOpen):
+ """
+ Sets the maximum number of documents that can be open at a time. By
+ default, this is 10,000. If you set it to 1, existing documents will
+ be saved and deleted when the user tries to open or create a new one
+ (similar to the behaviour of Windows Write, for example). Allowing
+ multiple documents gives behaviour more akin to MS Word and other
+ Multiple Document Interface applications.
+ """
+ self._maxDocsOpen = maxDocsOpen
+
+
+ def GetDocuments(self):
+ """
+ Returns the list of documents.
+ """
+ return self._docs
+
+
+class DocParentFrame(wx.Frame):
+ """
+ The wxDocParentFrame class provides a default top-level frame for
+ applications using the document/view framework. This class can only be
+ used for SDI (not MDI) parent frames.
+
+ It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplates
+ classes.
+ """
+
+ def __init__(self, manager, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
+ """
+ Constructor. Note that the event table must be rebuilt for the
+ frame since the EvtHandler is not virtual.
+ """
+ wx.Frame.__init__(self, frame, id, title, pos, size, style)
+ self._docManager = manager
+
+ wx.EVT_CLOSE(self, self.OnCloseWindow)
+
+ wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
+ wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
+
+ wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
+
+ wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ return self._docManager and self._docManager.ProcessEvent(event)
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ return self._docManager and self._docManager.ProcessUpdateUIEvent(event)
+
+
+ def OnExit(self, event):
+ """
+ Called when File/Exit is chosen and closes the window.
+ """
+ self.Close()
+
+
+ def OnMRUFile(self, event):
+ """
+ Opens the appropriate file when it is selected from the file history
+ menu.
+ """
+ n = event.GetId() - wx.ID_FILE1
+ filename = self._docManager.GetHistoryFile(n)
+ if filename:
+ self._docManager.CreateDocument(filename, DOC_SILENT)
+ else:
+ self._docManager.RemoveFileFromHistory(n)
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("File Error")
+ wx.MessageBox("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list" % FileNameFromPath(file),
+ msgTitle,
+ wx.OK | wx.ICON_EXCLAMATION,
+ self)
+
+
+ def OnCloseWindow(self, event):
+ """
+ Deletes all views and documents. If no user input cancelled the
+ operation, the frame will be destroyed and the application will exit.
+ """
+ if self._docManager.Clear(not event.CanVeto()):
+ self.Destroy()
+ else:
+ event.Veto()
+
+
+class DocChildFrame(wx.Frame):
+ """
+ The wxDocChildFrame class provides a default frame for displaying
+ documents on separate windows. This class can only be used for SDI (not
+ MDI) child frames.
+
+ The class is part of the document/view framework supported by wxWindows,
+ and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
+ classes.
+ """
+
+
+ def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
+ """
+ Constructor. Note that the event table must be rebuilt for the
+ frame since the EvtHandler is not virtual.
+ """
+ wx.Frame.__init__(self, frame, id, title, pos, size, style, name)
+ wx.EVT_ACTIVATE(self, self.OnActivate)
+ wx.EVT_CLOSE(self, self.OnCloseWindow)
+ self._childDocument = doc
+ self._childView = view
+ if view:
+ view.SetFrame(self)
+
+ wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
+
+ wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if self._childView:
+ self._childView.Activate(True)
+ if not self._childView or not self._childView.ProcessEvent(event):
+ # IsInstance not working, but who cares just send all the commands up since this isn't a real ProcessEvent like wxWindows
+ # if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
+ if not self.GetParent() or not self.GetParent().ProcessEvent(event):
+ return False
+ else:
+ return True
+ else:
+ return True
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if self.GetParent():
+ self.GetParent().ProcessUpdateUIEvent(event)
+ else:
+ return False
+
+
+ def OnActivate(self, event):
+ """
+ Activates the current view.
+ """
+ event.Skip()
+ if self._childView:
+ self._childView.Activate(event.GetActive())
+
+
+ def OnCloseWindow(self, event):
+ """
+ Closes and deletes the current view and document.
+ """
+ if self._childView:
+ ans = False
+ if not event.CanVeto():
+ ans = True
+ else:
+ ans = self._childView.Close(deleteWindow = False)
+
+ if ans:
+ self._childView.Activate(False)
+ self._childView.Destroy()
+ self._childView = None
+ if self._childDocument:
+ self._childDocument.Destroy() # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
+ self._childDocument = None
+ self.Destroy()
+ else:
+ event.Veto()
+ else:
+ event.Veto()
+
+
+ def GetDocument(self):
+ """
+ Returns the document associated with this frame.
+ """
+ return self._childDocument
+
+
+ def SetDocument(self, document):
+ """
+ Sets the document for this frame.
+ """
+ self._childDocument = document
+
+
+ def GetView(self):
+ """
+ Returns the view associated with this frame.
+ """
+ return self._childView
+
+
+ def SetView(self, view):
+ """
+ Sets the view for this frame.
+ """
+ self._childView = view
+
+
+class DocMDIParentFrame(wx.MDIParentFrame):
+ """
+ The wxDocMDIParentFrame class provides a default top-level frame for
+ applications using the document/view framework. This class can only be
+ used for MDI parent frames.
+
+ It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
+ classes.
+ """
+
+
+ def __init__(self, manager, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
+ """
+ Constructor. Note that the event table must be rebuilt for the
+ frame since the EvtHandler is not virtual.
+ """
+ wx.MDIParentFrame.__init__(self, frame, id, title, pos, size, style, name)
+ self._docManager = manager
+
+ wx.EVT_CLOSE(self, self.OnCloseWindow)
+
+ wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
+ wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
+
+ wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
+
+ wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ return self._docManager and self._docManager.ProcessEvent(event)
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ return self._docManager and self._docManager.ProcessUpdateUIEvent(event)
+
+
+ def OnExit(self, event):
+ """
+ Called when File/Exit is chosen and closes the window.
+ """
+ self.Close()
+
+
+ def OnMRUFile(self, event):
+ """
+ Opens the appropriate file when it is selected from the file history
+ menu.
+ """
+ n = event.GetId() - wx.ID_FILE1
+ filename = self._docManager.GetHistoryFile(n)
+ if filename:
+ self._docManager.CreateDocument(filename, DOC_SILENT)
+ else:
+ self._docManager.RemoveFileFromHistory(n)
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("File Error")
+ wx.MessageBox("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list" % FileNameFromPath(file),
+ msgTitle,
+ wx.OK | wx.ICON_EXCLAMATION,
+ self)
+
+
+ def OnCloseWindow(self, event):
+ """
+ Deletes all views and documents. If no user input cancelled the
+ operation, the frame will be destroyed and the application will exit.
+ """
+ if self._docManager.Clear(not event.CanVeto()):
+ self.Destroy()
+ else:
+ event.Veto()
+
+
+class DocMDIChildFrame(wx.MDIChildFrame):
+ """
+ The wxDocMDIChildFrame class provides a default frame for displaying
+ documents on separate windows. This class can only be used for MDI child
+ frames.
+
+ The class is part of the document/view framework supported by wxWindows,
+ and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
+ classes.
+ """
+
+
+ def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
+ """
+ Constructor. Note that the event table must be rebuilt for the
+ frame since the EvtHandler is not virtual.
+ """
+ wx.MDIChildFrame.__init__(self, frame, id, title, pos, size, style, name)
+ self._childDocument = doc
+ self._childView = view
+ if view:
+ view.SetFrame(self)
+ # self.Create(doc, view, frame, id, title, pos, size, style, name)
+ self._activeEvent = None
+ self._activated = 0
+ wx.EVT_ACTIVATE(self, self.OnActivate)
+ wx.EVT_CLOSE(self, self.OnCloseWindow)
+
+ if frame: # wxBug: For some reason the EVT_ACTIVATE event is not getting triggered for the first mdi client window that is opened so we have to do it manually
+ mdiChildren = filter(lambda x: isinstance(x, wx.MDIChildFrame), frame.GetChildren())
+ if len(mdiChildren) == 1:
+ self.Activate()
+
+
+## # Couldn't get this to work, but seems to work fine with single stage construction
+## def Create(self, doc, view, frame, id, title, pos, size, style, name):
+## self._childDocument = doc
+## self._childView = view
+## if wx.MDIChildFrame.Create(self, frame, id, title, pos, size, style, name):
+## if view:
+## view.SetFrame(self)
+## return True
+## return False
+
+
+
+ def Activate(self): # Need this in case there are embedded sash windows and such, OnActivate is not getting called
+ """
+ Activates the current view.
+ """
+ if self._childView:
+ self._childView.Activate(True)
+
+
+ def ProcessEvent(event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if self._activeEvent == event:
+ return False
+
+ self._activeEvent = event # Break recursion loops
+
+ if self._childView:
+ self._childView.Activate(True)
+
+ if not self._childView or not self._childView.ProcessEvent(event):
+ if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
+ ret = False
+ else:
+ ret = True
+ else:
+ ret = True
+
+ self._activeEvent = None
+ return ret
+
+
+ def OnActivate(self, event):
+ """
+ Sets the currently active view to be the frame's view. You may need to
+ override (but still call) this function in order to set the keyboard
+ focus for your subwindow.
+ """
+ event.Skip()
+ if self._activated != 0:
+ return True
+ self._activated += 1
+ wx.MDIChildFrame.Activate(self)
+ if event.GetActive() and self._childView:
+ self._childView.Activate(event.GetActive())
+ self._activated = 0
+
+
+ def OnCloseWindow(self, event):
+ """
+ Closes and deletes the current view and document.
+ """
+ if self._childView:
+ ans = False
+ if not event.CanVeto():
+ ans = True
+ else:
+ ans = self._childView.Close(deleteWindow = False)
+
+ if ans:
+ self._childView.Activate(False)
+ self._childView.Destroy()
+ self._childView = None
+ if self._childDocument: # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
+ self._childDocument.DeleteContents()
+ if self._childDocument.GetDocumentManager():
+ self._childDocument.GetDocumentManager().RemoveDocument(self._childDocument)
+ self._childDocument = None
+ self.Destroy()
+ else:
+ event.Veto()
+ else:
+ event.Veto()
+
+
+ def GetDocument(self):
+ """
+ Returns the document associated with this frame.
+ """
+ return self._childDocument
+
+
+ def SetDocument(self, document):
+ """
+ Sets the document for this frame.
+ """
+ self._childDocument = document
+
+
+ def GetView(self):
+ """
+ Returns the view associated with this frame.
+ """
+ return self._childView
+
+
+ def SetView(self, view):
+ """
+ Sets the view for this frame.
+ """
+ self._childView = view
+
+
+ def OnTitleIsModified(self):
+ """
+ Add/remove to the frame's title an indication that the document is dirty.
+ If the document is dirty, an '*' is appended to the title
+ This method has been added to wxPython and is not in wxWindows.
+ """
+ title = self.GetTitle()
+ if title:
+ if self.GetDocument().IsModified():
+ if title.endswith("*"):
+ return
+ else:
+ title = title + "*"
+ self.SetTitle(title)
+ else:
+ if title.endswith("*"):
+ title = title[:-1]
+ self.SetTitle(title)
+ else:
+ return
+
+
+class DocPrintout(wx.Printout):
+ """
+ DocPrintout is a default Printout that prints the first page of a document
+ view.
+ """
+
+
+ def __init__(self, view, title="Printout"):
+ """
+ Constructor.
+ """
+ wx.Printout.__init__(self, title)
+ self._printoutView = view
+
+
+ def GetView(self):
+ """
+ Returns the DocPrintout's view.
+ """
+ return self._printoutView
+
+
+ def OnPrintPage(self, page):
+ """
+ Prints the first page of the view.
+ """
+ dc = self.GetDC()
+ ppiScreenX, ppiScreenY = self.GetPPIScreen()
+ ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
+ scale = ppiPrinterX/ppiScreenX
+ w, h = dc.GetSize()
+ pageWidth, pageHeight = self.GetPageSizePixels()
+ overallScale = scale * w / pageWidth
+ dc.SetUserScale(overallScale, overallScale)
+ if self._printoutView:
+ self._printoutView.OnDraw(dc)
+ return True
+
+
+ def HasPage(self, pageNum):
+ """
+ Indicates that the DocPrintout only has a single page.
+ """
+ return pageNum == 1
+
+
+ def GetPageInfo(self):
+ """
+ Indicates that the DocPrintout only has a single page.
+ """
+ minPage = 1
+ maxPage = 1
+ selPageFrom = 1
+ selPageTo = 1
+ return (minPage, maxPage, selPageFrom, selPageTo)
+
+
+#----------------------------------------------------------------------
+# Command Classes
+#----------------------------------------------------------------------
+
+class Command(wx.Object):
+ """
+ wxCommand is a base class for modelling an application command, which is
+ an action usually performed by selecting a menu item, pressing a toolbar
+ button or any other means provided by the application to change the data
+ or view.
+ """
+
+
+ def __init__(self, canUndo = False, name = None):
+ """
+ Constructor. wxCommand is an abstract class, so you will need to
+ derive a new class and call this constructor from your own constructor.
+
+ canUndo tells the command processor whether this command is undo-able.
+ You can achieve the same functionality by overriding the CanUndo member
+ function (if for example the criteria for undoability is context-
+ dependent).
+
+ name must be supplied for the command processor to display the command
+ name in the application's edit menu.
+ """
+ self._canUndo = canUndo
+ self._name = name
+
+
+ def CanUndo(self):
+ """
+ Returns true if the command can be undone, false otherwise.
+ """
+ return self._canUndo
+
+
+ def GetName(self):
+ """
+ Returns the command name.
+ """
+ return self._name
+
+
+ def Do(self):
+ """
+ Override this member function to execute the appropriate action when
+ called. Return true to indicate that the action has taken place, false
+ otherwise. Returning false will indicate to the command processor that
+ the action is not undoable and should not be added to the command
+ history.
+ """
+ return True
+
+
+ def Undo(self):
+ """
+ Override this member function to un-execute a previous Do. Return true
+ to indicate that the action has taken place, false otherwise. Returning
+ false will indicate to the command processor that the action is not
+ redoable and no change should be made to the command history.
+
+ How you implement this command is totally application dependent, but
+ typical strategies include:
+
+ Perform an inverse operation on the last modified piece of data in the
+ document. When redone, a copy of data stored in command is pasted back
+ or some operation reapplied. This relies on the fact that you know the
+ ordering of Undos; the user can never Undo at an arbitrary position in
+ he command history.
+
+ Restore the entire document state (perhaps using document
+ transactioning). Potentially very inefficient, but possibly easier to
+ code if the user interface and data are complex, and an 'inverse
+ execute' operation is hard to write.
+ """
+ return True
+
+
+class CommandProcessor(wx.Object):
+ """
+ wxCommandProcessor is a class that maintains a history of wxCommands, with
+ undo/redo functionality built-in. Derive a new class from this if you want
+ different behaviour.
+ """
+
+
+ def __init__(self, maxCommands=-1):
+ """
+ Constructor. maxCommands may be set to a positive integer to limit
+ the number of commands stored to it, otherwise (and by default) the
+ list of commands can grow arbitrarily.
+ """
+ self._maxCommands = maxCommands
+ self._editMenu = None
+ self._undoAccelerator = _("Ctrl+Z")
+ self._redoAccelerator = _("Ctrl+Y")
+ self.ClearCommands()
+
+
+ def _GetCurrentCommand(self):
+ if len(self._commands) == 0:
+ return None
+ else:
+ return self._commands[-1]
+
+
+ def _GetCurrentRedoCommand(self):
+ if len(self._redoCommands) == 0:
+ return None
+ else:
+ return self._redoCommands[-1]
+
+
+ def GetMaxCommands(self):
+ """
+ Returns the maximum number of commands that the command processor
+ stores.
+
+ """
+ return self._maxCommands
+
+
+ def GetCommands(self):
+ """
+ Returns the list of commands.
+ """
+ return self._commands
+
+
+ def ClearCommands(self):
+ """
+ Deletes all the commands in the list and sets the current command
+ pointer to None.
+ """
+ self._commands = []
+ self._redoCommands = []
+
+
+ def GetEditMenu(self):
+ """
+ Returns the edit menu associated with the command processor.
+ """
+ return self._editMenu
+
+
+ def SetEditMenu(self, menu):
+ """
+ Tells the command processor to update the Undo and Redo items on this
+ menu as appropriate. Set this to NULL if the menu is about to be
+ destroyed and command operations may still be performed, or the
+ command processor may try to access an invalid pointer.
+ """
+ self._editMenu = menu
+
+
+ def GetUndoAccelerator(self):
+ """
+ Returns the string that will be appended to the Undo menu item.
+ """
+ return self._undoAccelerator
+
+
+ def SetUndoAccelerator(self, accel):
+ """
+ Sets the string that will be appended to the Redo menu item.
+ """
+ self._undoAccelerator = accel
+
+
+ def GetRedoAccelerator(self):
+ """
+ Returns the string that will be appended to the Redo menu item.
+ """
+ return self._redoAccelerator
+
+
+ def SetRedoAccelerator(self, accel):
+ """
+ Sets the string that will be appended to the Redo menu item.
+ """
+ self._redoAccelerator = accel
+
+
+ def SetMenuStrings(self):
+ """
+ Sets the menu labels according to the currently set menu and the
+ current command state.
+ """
+ if self.GetEditMenu() != None:
+ undoCommand = self._GetCurrentCommand()
+ redoCommand = self._GetCurrentRedoCommand()
+ undoItem = self.GetEditMenu().FindItemById(wx.ID_UNDO)
+ redoItem = self.GetEditMenu().FindItemById(wx.ID_REDO)
+ if self.GetUndoAccelerator():
+ undoAccel = '\t' + self.GetUndoAccelerator()
+ else:
+ undoAccel = ''
+ if self.GetRedoAccelerator():
+ redoAccel = '\t' + self.GetRedoAccelerator()
+ else:
+ redoAccel = ''
+ if undoCommand and undoItem and undoCommand.CanUndo():
+ undoItem.SetText(_("&Undo ") + undoCommand.GetName() + undoAccel)
+ #elif undoCommand and not undoCommand.CanUndo():
+ # undoItem.SetText(_("Can't Undo") + undoAccel)
+ else:
+ undoItem.SetText(_("&Undo" + undoAccel))
+ if redoCommand and redoItem:
+ redoItem.SetText(_("&Redo ") + redoCommand.GetName() + redoAccel)
+ else:
+ redoItem.SetText(_("&Redo") + redoAccel)
+
+
+ def CanUndo(self):
+ """
+ Returns true if the currently-active command can be undone, false
+ otherwise.
+ """
+ if self._GetCurrentCommand() == None:
+ return False
+ return self._GetCurrentCommand().CanUndo()
+
+
+ def CanRedo(self):
+ """
+ Returns true if the currently-active command can be redone, false
+ otherwise.
+ """
+ return self._GetCurrentRedoCommand() != None
+
+
+ def Submit(self, command, storeIt=True):
+ """
+ Submits a new command to the command processor. The command processor
+ calls wxCommand::Do to execute the command; if it succeeds, the
+ command is stored in the history list, and the associated edit menu
+ (if any) updated appropriately. If it fails, the command is deleted
+ immediately. Once Submit has been called, the passed command should
+ not be deleted directly by the application.
+
+ storeIt indicates whether the successful command should be stored in
+ the history list.
+ """
+ done = command.Do()
+ if done:
+ del self._redoCommands[:]
+ if storeIt:
+ self._commands.append(command)
+ if self._maxCommands > -1:
+ if len(self._commands) > self._maxCommands:
+ del self._commands[0]
+ return done
+
+
+ def Redo(self):
+ """
+ Redoes the command just undone.
+ """
+ cmd = self._GetCurrentRedoCommand()
+ if not cmd:
+ return False
+ done = cmd.Do()
+ if done:
+ self._commands.append(self._redoCommands.pop())
+ return done
+
+
+ def Undo(self):
+ """
+ Undoes the command just executed.
+ """
+ cmd = self._GetCurrentCommand()
+ if not cmd:
+ return False
+ done = cmd.Undo()
+ if done:
+ self._redoCommands.append(self._commands.pop())
+ return done
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/dragscroller.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/dragscroller.py
new file mode 100644
index 0000000..7410da8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/dragscroller.py
@@ -0,0 +1,79 @@
+#-----------------------------------------------------------------------------
+# Name: dragscroller.py
+# Purpose: Scrolls a wx.ScrollWindow by dragging
+#
+# Author: Riaan Booysen
+#
+# Created: 2006/09/05
+# Copyright: (c) 2006
+# Licence: wxPython
+#-----------------------------------------------------------------------------
+
+import wx
+
+class DragScroller:
+ """ Scrolls a wx.ScrollWindow in the direction and speed of a mouse drag.
+
+ Call Start with the position of the drag start.
+ Call Stop on the drag release. """
+
+ def __init__(self, scrollwin, rate=30, sensitivity=0.75):
+ self.scrollwin = scrollwin
+ self.rate = rate
+ self.sensitivity = sensitivity
+
+ self.pos = None
+ self.timer = None
+
+ def GetScrollWindow(self):
+ return self.scrollwin
+ def SetScrollWindow(self, scrollwin):
+ self.scrollwin = scrollwin
+
+ def GetUpdateRate(self):
+ return self.rate
+ def SetUpdateRate(self, rate):
+ self.rate = rate
+
+ def GetSensitivity(self):
+ return self.sensitivity
+ def SetSensitivity(self, sensitivity):
+ self.sensitivity = sensitivity
+
+ def Start(self, pos):
+ """ Start a drag scroll operation """
+ if not self.scrollwin:
+ raise Exception, 'No ScrollWindow defined'
+
+ self.pos = pos
+ self.scrollwin.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
+ if not self.scrollwin.HasCapture():
+ self.scrollwin.CaptureMouse()
+
+ self.timer = wx.Timer(self.scrollwin)
+ self.scrollwin.Bind(wx.EVT_TIMER, self.OnTimerDoScroll, id=self.timer.GetId())
+ self.timer.Start(self.rate)
+
+ def Stop(self):
+ """ Stops a drag scroll operation """
+ if self.timer and self.scrollwin:
+ self.timer.Stop()
+ self.scrollwin.Disconnect(self.timer.GetId())
+ self.timer.Destroy()
+ self.timer = None
+
+ self.scrollwin.SetCursor(wx.STANDARD_CURSOR)
+ if self.scrollwin.HasCapture():
+ self.scrollwin.ReleaseMouse()
+
+ def OnTimerDoScroll(self, event):
+ if self.pos is None or not self.timer or not self.scrollwin:
+ return
+
+ new = self.scrollwin.ScreenToClient(wx.GetMousePosition())
+ dx = int((new.x-self.pos.x)*self.sensitivity)
+ dy = int((new.y-self.pos.y)*self.sensitivity)
+ spx = self.scrollwin.GetScrollPos(wx.HORIZONTAL)
+ spy = self.scrollwin.GetScrollPos(wx.VERTICAL)
+
+ self.scrollwin.Scroll(spx+dx, spy+dy)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/README.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/README.txt
new file mode 100644
index 0000000..6bf6163
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/README.txt
@@ -0,0 +1,77 @@
+wxEditor component
+------------------
+
+The wxEditor class implements a simple text editor using wxPython. You
+can create a custom editor by subclassing wxEditor. Even though much of
+the editor is implemented in Python, it runs surprisingly smoothly on
+normal hardware with small files.
+
+
+Keys
+----
+Keys are similar to Windows-based editors:
+
+Tab: 1 to 4 spaces (to next tab stop)
+Cursor movement: Arrow keys
+Beginning of line: Home
+End of line: End
+Beginning of buffer: Control-Home
+End of the buffer: Control-End
+Select text: Hold down Shift while moving the cursor
+Copy: Shift-Insert, Control-C
+Cut: Shift-Delete, Control-X
+Paste: Control-Insert, Control-V
+
+How to use it
+-------------
+The demo code (demo/wxEditor.py) shows how to use it as a simple text
+box. Use the SetText() and GetText() methods to set or get text from
+the component; these both return a list of strings.
+
+The samples/FrogEdit directory has an example of a simple text editor
+application that uses the wxEditor component.
+
+Subclassing
+-----------
+To add or change functionality, you can subclass this
+component. One example of this might be to change the key
+Alt key commands. In that case you would (for example) override the
+SetAltFuncs() method.
+
+History
+-------
+The original author of this component was Dirk Holtwic. It originally
+had limited support for syntax highlighting, but was not a usable text
+editor, as it didn't implement select (with keys or mouse), or any of
+the usual key sequences you'd expect in an editor. Robin Dunn did some
+refactoring work to make it more usable. Steve Howell and Adam Feuer
+did a lot of refactoring, and added some functionality, including
+keyboard and mouse select, properly working scrollbars, and
+overridable keys. Adam and Steve also removed support for
+syntax-highlighting while refactoring the code.
+
+To do
+-----
+Alt/Ctrl Arrow keys move by word
+Descriptive help text for keys
+Speed improvements
+Different fonts/colors
+
+
+Authors
+-------
+Steve Howell, Adam Feuer, Dirk Holtwic, Robin Dunn
+
+
+Contact
+-------
+You can find the latest code for wxEditor here:
+http://www.pobox.com/~adamf/software/
+
+We're not actively maintaining this code, but we can answer
+questions about it. You can email us at:
+
+Adam Feuer <adamf at pobox dot com>
+Steve Howell <showell at zipcon dot net>
+
+29 November 2001
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/__init__.py
new file mode 100644
index 0000000..05c8d86
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/__init__.py
@@ -0,0 +1,25 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.editor
+# Purpose: A package containing a colourizable text editror
+#
+# Author: Robin Dunn
+#
+# Created: 30-Dec-1999
+# RCS-ID: $Id$
+# Copyright: (c) 1999 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxEditor -> Editor
+#
+
+# This file makes this directory into a Python package
+
+
+# import the main classes into the package namespace.
+from editor import Editor
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/editor.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/editor.py
new file mode 100644
index 0000000..1bb0a98
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/editor.py
@@ -0,0 +1,976 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.editor.Editor
+# Purpose: An intelligent text editor with colorization capabilities.
+#
+# Original
+# Authors: Dirk Holtwic, Robin Dunn
+#
+# New
+# Authors: Adam Feuer, Steve Howell
+#
+# History:
+# This code used to support a fairly complex subclass that did
+# syntax coloring and outliner collapse mode. Adam and Steve
+# inherited the code, and added a lot of basic editor
+# functionality that had not been there before, such as cut-and-paste.
+#
+#
+# Created: 15-Dec-1999
+# RCS-ID: $Id$
+# Copyright: (c) 1999 by Dirk Holtwick, 1999
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxEditor -> Editor
+#
+
+import os
+import time
+
+import wx
+
+import selection
+import images
+
+#----------------------------
+
+def ForceBetween(min, val, max):
+ if val > max:
+ return max
+ if val < min:
+ return min
+ return val
+
+
+def LineTrimmer(lineOfText):
+ if len(lineOfText) == 0:
+ return ""
+ elif lineOfText[-1] == '\r':
+ return lineOfText[:-1]
+ else:
+ return lineOfText
+
+def LineSplitter(text):
+ return map (LineTrimmer, text.split('\n'))
+
+
+#----------------------------
+
+class Scroller:
+ def __init__(self, parent):
+ self.parent = parent
+ self.ow = 0
+ self.oh = 0
+ self.ox = 0
+ self.oy = 0
+
+ def SetScrollbars(self, fw, fh, w, h, x, y):
+ if (self.ow != w or self.oh != h or self.ox != x or self.oy != y):
+ self.parent.SetScrollbars(fw, fh, w, h, x, y)
+ self.ow = w
+ self.oh = h
+ self.ox = x
+ self.oy = y
+
+#----------------------------------------------------------------------
+
+class Editor(wx.ScrolledWindow):
+
+ def __init__(self, parent, id,
+ pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
+
+ wx.ScrolledWindow.__init__(self, parent, id,
+ pos, size,
+ style|wx.WANTS_CHARS)
+
+ self.isDrawing = False
+
+ self.InitCoords()
+ self.InitFonts()
+ self.SetColors()
+ self.MapEvents()
+ self.LoadImages()
+ self.InitDoubleBuffering()
+ self.InitScrolling()
+ self.SelectOff()
+ self.SetFocus()
+ self.SetText([""])
+ self.SpacesPerTab = 4
+
+##------------------ Init stuff
+
+ def InitCoords(self):
+ self.cx = 0
+ self.cy = 0
+ self.oldCx = 0
+ self.oldCy = 0
+ self.sx = 0
+ self.sy = 0
+ self.sw = 0
+ self.sh = 0
+ self.sco_x = 0
+ self.sco_y = 0
+
+ def MapEvents(self):
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_SCROLLWIN, self.OnScroll)
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+
+##------------------- Platform-specific stuff
+
+ def NiceFontForPlatform(self):
+ if wx.Platform == "__WXMSW__":
+ font = wx.Font(10, wx.MODERN, wx.NORMAL, wx.NORMAL)
+ else:
+ font = wx.Font(12, wx.MODERN, wx.NORMAL, wx.NORMAL, False)
+ if wx.Platform == "__WXMAC__":
+ font.SetNoAntiAliasing()
+ return font
+
+ def UnixKeyHack(self, key):
+ #
+ # this will be obsolete when we get the new wxWindows patch
+ #
+ # 12/14/03 - jmg
+ #
+ # Which patch? I don't know if this is needed, but I don't know
+ # why it's here either. Play it safe; leave it in.
+ #
+ if key <= 26:
+ key += ord('a') - 1
+ return key
+
+##-------------------- UpdateView/Cursor code
+
+ def OnSize(self, event):
+ self.AdjustScrollbars()
+ self.SetFocus()
+
+ def SetCharDimensions(self):
+ # TODO: We need a code review on this. It appears that Linux
+ # improperly reports window dimensions when the scrollbar's there.
+ self.bw, self.bh = self.GetClientSize()
+
+ if wx.Platform == "__WXMSW__":
+ self.sh = self.bh / self.fh
+ self.sw = (self.bw / self.fw) - 1
+ else:
+ self.sh = self.bh / self.fh
+ if self.LinesInFile() >= self.sh:
+ self.bw = self.bw - wx.SystemSettings_GetMetric(wx.SYS_VSCROLL_X)
+ self.sw = (self.bw / self.fw) - 1
+
+ self.sw = (self.bw / self.fw) - 1
+ if self.CalcMaxLineLen() >= self.sw:
+ self.bh = self.bh - wx.SystemSettings_GetMetric(wx.SYS_HSCROLL_Y)
+ self.sh = self.bh / self.fh
+
+
+ def UpdateView(self, dc = None):
+ if dc is None:
+ dc = wx.ClientDC(self)
+ if dc.Ok():
+ self.SetCharDimensions()
+ self.KeepCursorOnScreen()
+ self.DrawSimpleCursor(0,0, dc, True)
+ self.Draw(dc)
+
+ def OnPaint(self, event):
+ dc = wx.PaintDC(self)
+ if self.isDrawing:
+ return
+ self.isDrawing = True
+ self.UpdateView(dc)
+ wx.CallAfter(self.AdjustScrollbars)
+ self.isDrawing = False
+
+ def OnEraseBackground(self, evt):
+ pass
+
+##-------------------- Drawing code
+
+ def InitFonts(self):
+ dc = wx.ClientDC(self)
+ self.font = self.NiceFontForPlatform()
+ dc.SetFont(self.font)
+ self.fw = dc.GetCharWidth()
+ self.fh = dc.GetCharHeight()
+
+ def SetColors(self):
+ self.fgColor = wx.NamedColour('black')
+ self.bgColor = wx.NamedColour('white')
+ self.selectColor = wx.Colour(238, 220, 120) # r, g, b = emacsOrange
+
+ def InitDoubleBuffering(self):
+ pass
+
+ def DrawEditText(self, t, x, y, dc):
+ dc.DrawText(t, x * self.fw, y * self.fh)
+
+ def DrawLine(self, line, dc):
+ if self.IsLine(line):
+ l = line
+ t = self.lines[l]
+ dc.SetTextForeground(self.fgColor)
+ fragments = selection.Selection(
+ self.SelectBegin, self.SelectEnd,
+ self.sx, self.sw, line, t)
+ x = 0
+ for (data, selected) in fragments:
+ if selected:
+ dc.SetTextBackground(self.selectColor)
+ if x == 0 and len(data) == 0 and len(fragments) == 1:
+ data = ' '
+ else:
+ dc.SetTextBackground(self.bgColor)
+ self.DrawEditText(data, x, line - self.sy, dc)
+ x += len(data)
+
+ def Draw(self, odc=None):
+ if not odc:
+ odc = wx.ClientDC(self)
+
+ dc = wx.BufferedDC(odc)
+ if dc.IsOk():
+ dc.SetFont(self.font)
+ dc.SetBackgroundMode(wx.SOLID)
+ dc.SetTextBackground(self.bgColor)
+ dc.SetTextForeground(self.fgColor)
+ dc.Clear()
+ for line in range(self.sy, self.sy + self.sh):
+ self.DrawLine(line, dc)
+ if len(self.lines) < self.sh + self.sy:
+ self.DrawEofMarker(dc)
+ self.DrawCursor(dc)
+
+##------------------ eofMarker stuff
+
+ def LoadImages(self):
+ self.eofMarker = images.EofImage.GetBitmap()
+
+ def DrawEofMarker(self,dc):
+ x = 0
+ y = (len(self.lines) - self.sy) * self.fh
+ hasTransparency = 1
+ dc.DrawBitmap(self.eofMarker, x, y, hasTransparency)
+
+##------------------ cursor-related functions
+
+ def DrawCursor(self, dc = None):
+ if not dc:
+ dc = wx.ClientDC(self)
+
+ if (self.LinesInFile())<self.cy: #-1 ?
+ self.cy = self.LinesInFile()-1
+ s = self.lines[self.cy]
+
+ x = self.cx - self.sx
+ y = self.cy - self.sy
+ self.DrawSimpleCursor(x, y, dc)
+
+
+ def DrawSimpleCursor(self, xp, yp, dc = None, old=False):
+ if not dc:
+ dc = wx.ClientDC(self)
+
+ if old:
+ xp = self.sco_x
+ yp = self.sco_y
+
+ szx = self.fw
+ szy = self.fh
+ x = xp * szx
+ y = yp * szy
+ dc.Blit(x,y, szx,szy, dc, x,y, wx.SRC_INVERT)
+ self.sco_x = xp
+ self.sco_y = yp
+
+##-------- Enforcing screen boundaries, cursor movement
+
+ def CalcMaxLineLen(self):
+ """get length of longest line on screen"""
+ maxlen = 0
+ for line in self.lines[self.sy:self.sy+self.sh]:
+ if len(line) >maxlen:
+ maxlen = len(line)
+ return maxlen
+
+ def KeepCursorOnScreen(self):
+ self.sy = ForceBetween(max(0, self.cy-self.sh), self.sy, self.cy)
+ self.sx = ForceBetween(max(0, self.cx-self.sw), self.sx, self.cx)
+ self.AdjustScrollbars()
+
+ def HorizBoundaries(self):
+ self.SetCharDimensions()
+ maxLineLen = self.CalcMaxLineLen()
+ self.sx = ForceBetween(0, self.sx, max(self.sw, maxLineLen - self.sw + 1))
+ self.cx = ForceBetween(self.sx, self.cx, self.sx + self.sw - 1)
+
+ def VertBoundaries(self):
+ self.SetCharDimensions()
+ self.sy = ForceBetween(0, self.sy, max(self.sh, self.LinesInFile() - self.sh + 1))
+ self.cy = ForceBetween(self.sy, self.cy, self.sy + self.sh - 1)
+
+ def cVert(self, num):
+ self.cy = self.cy + num
+ self.cy = ForceBetween(0, self.cy, self.LinesInFile() - 1)
+ self.sy = ForceBetween(self.cy - self.sh + 1, self.sy, self.cy)
+ self.cx = min(self.cx, self.CurrentLineLength())
+
+ def cHoriz(self, num):
+ self.cx = self.cx + num
+ self.cx = ForceBetween(0, self.cx, self.CurrentLineLength())
+ self.sx = ForceBetween(self.cx - self.sw + 1, self.sx, self.cx)
+
+ def AboveScreen(self, row):
+ return row < self.sy
+
+ def BelowScreen(self, row):
+ return row >= self.sy + self.sh
+
+ def LeftOfScreen(self, col):
+ return col < self.sx
+
+ def RightOfScreen(self, col):
+ return col >= self.sx + self.sw
+
+##----------------- data structure helper functions
+
+ def GetText(self):
+ return self.lines
+
+ def SetText(self, lines):
+ self.InitCoords()
+ self.lines = lines
+ self.UnTouchBuffer()
+ self.SelectOff()
+ self.AdjustScrollbars()
+ self.UpdateView(None)
+
+ def IsLine(self, lineNum):
+ return (0<=lineNum) and (lineNum<self.LinesInFile())
+
+ def GetTextLine(self, lineNum):
+ if self.IsLine(lineNum):
+ return self.lines[lineNum]
+ return ""
+
+ def SetTextLine(self, lineNum, text):
+ if self.IsLine(lineNum):
+ self.lines[lineNum] = text
+
+ def CurrentLineLength(self):
+ return len(self.lines[self.cy])
+
+ def LinesInFile(self):
+ return len(self.lines)
+
+ def UnTouchBuffer(self):
+ self.bufferTouched = False
+
+ def BufferWasTouched(self):
+ return self.bufferTouched
+
+ def TouchBuffer(self):
+ self.bufferTouched = True
+
+
+##-------------------------- Mouse scroll timing functions
+
+ def InitScrolling(self):
+ # we don't rely on the windows system to scroll for us; we just
+ # redraw the screen manually every time
+ self.EnableScrolling(False, False)
+ self.nextScrollTime = 0
+ self.SCROLLDELAY = 0.050 # seconds
+ self.scrollTimer = wx.Timer(self)
+ self.scroller = Scroller(self)
+
+ def CanScroll(self):
+ if time.time() > self.nextScrollTime:
+ self.nextScrollTime = time.time() + self.SCROLLDELAY
+ return True
+ else:
+ return False
+
+ def SetScrollTimer(self):
+ oneShot = True
+ self.scrollTimer.Start(1000*self.SCROLLDELAY/2, oneShot)
+ self.Bind(wx.EVT_TIMER, self.OnTimer)
+
+ def OnTimer(self, event):
+ screenX, screenY = wx.GetMousePosition()
+ x, y = self.ScreenToClientXY(screenX, screenY)
+ self.MouseToRow(y)
+ self.MouseToCol(x)
+ self.SelectUpdate()
+
+##-------------------------- Mouse off screen functions
+
+ def HandleAboveScreen(self, row):
+ self.SetScrollTimer()
+ if self.CanScroll():
+ row = self.sy - 1
+ row = max(0, row)
+ self.cy = row
+
+ def HandleBelowScreen(self, row):
+ self.SetScrollTimer()
+ if self.CanScroll():
+ row = self.sy + self.sh
+ row = min(row, self.LinesInFile() - 1)
+ self.cy = row
+
+ def HandleLeftOfScreen(self, col):
+ self.SetScrollTimer()
+ if self.CanScroll():
+ col = self.sx - 1
+ col = max(0,col)
+ self.cx = col
+
+ def HandleRightOfScreen(self, col):
+ self.SetScrollTimer()
+ if self.CanScroll():
+ col = self.sx + self.sw
+ col = min(col, self.CurrentLineLength())
+ self.cx = col
+
+##------------------------ mousing functions
+
+ def MouseToRow(self, mouseY):
+ row = self.sy + (mouseY/ self.fh)
+ if self.AboveScreen(row):
+ self.HandleAboveScreen(row)
+ elif self.BelowScreen(row):
+ self.HandleBelowScreen(row)
+ else:
+ self.cy = min(row, self.LinesInFile() - 1)
+
+ def MouseToCol(self, mouseX):
+ col = self.sx + (mouseX / self.fw)
+ if self.LeftOfScreen(col):
+ self.HandleLeftOfScreen(col)
+ elif self.RightOfScreen(col):
+ self.HandleRightOfScreen(col)
+ else:
+ self.cx = min(col, self.CurrentLineLength())
+
+ def MouseToCursor(self, event):
+ self.MouseToRow(event.GetY())
+ self.MouseToCol(event.GetX())
+
+ def OnMotion(self, event):
+ if event.LeftIsDown() and self.HasCapture():
+ self.Selecting = True
+ self.MouseToCursor(event)
+ self.SelectUpdate()
+
+ def OnLeftDown(self, event):
+ self.MouseToCursor(event)
+ self.SelectBegin = (self.cy, self.cx)
+ self.SelectEnd = None
+ self.UpdateView()
+ self.CaptureMouse()
+ self.SetFocus()
+
+ def OnLeftUp(self, event):
+ if not self.HasCapture():
+ return
+
+ if self.SelectEnd is None:
+ self.OnClick()
+ else:
+ self.Selecting = False
+ self.SelectNotify(False, self.SelectBegin, self.SelectEnd)
+
+ self.ReleaseMouse()
+ self.scrollTimer.Stop()
+
+
+#------------------------- Scrolling
+
+ def HorizScroll(self, event, eventType):
+ maxLineLen = self.CalcMaxLineLen()
+
+ if eventType == wx.wxEVT_SCROLLWIN_LINEUP:
+ self.sx -= 1
+ elif eventType == wx.wxEVT_SCROLLWIN_LINEDOWN:
+ self.sx += 1
+ elif eventType == wx.wxEVT_SCROLLWIN_PAGEUP:
+ self.sx -= self.sw
+ elif eventType == wx.wxEVT_SCROLLWIN_PAGEDOWN:
+ self.sx += self.sw
+ elif eventType == wx.wxEVT_SCROLLWIN_TOP:
+ self.sx = self.cx = 0
+ elif eventType == wx.wxEVT_SCROLLWIN_BOTTOM:
+ self.sx = maxLineLen - self.sw
+ self.cx = maxLineLen
+ else:
+ self.sx = event.GetPosition()
+
+ self.HorizBoundaries()
+
+ def VertScroll(self, event, eventType):
+ if eventType == wx.wxEVT_SCROLLWIN_LINEUP:
+ self.sy -= 1
+ elif eventType == wx.wxEVT_SCROLLWIN_LINEDOWN:
+ self.sy += 1
+ elif eventType == wx.wxEVT_SCROLLWIN_PAGEUP:
+ self.sy -= self.sh
+ elif eventType == wx.wxEVT_SCROLLWIN_PAGEDOWN:
+ self.sy += self.sh
+ elif eventType == wx.wxEVT_SCROLLWIN_TOP:
+ self.sy = self.cy = 0
+ elif eventType == wx.wxEVT_SCROLLWIN_BOTTOM:
+ self.sy = self.LinesInFile() - self.sh
+ self.cy = self.LinesInFile()
+ else:
+ self.sy = event.GetPosition()
+
+ self.VertBoundaries()
+
+ def OnScroll(self, event):
+ dir = event.GetOrientation()
+ eventType = event.GetEventType()
+ if dir == wx.HORIZONTAL:
+ self.HorizScroll(event, eventType)
+ else:
+ self.VertScroll(event, eventType)
+ self.UpdateView()
+
+
+ def AdjustScrollbars(self):
+ if self:
+ for i in range(2):
+ self.SetCharDimensions()
+ self.scroller.SetScrollbars(
+ self.fw, self.fh,
+ self.CalcMaxLineLen()+3, max(self.LinesInFile()+1, self.sh),
+ self.sx, self.sy)
+
+#------------ backspace, delete, return
+
+ def BreakLine(self, event):
+ if self.IsLine(self.cy):
+ t = self.lines[self.cy]
+ self.lines = self.lines[:self.cy] + [t[:self.cx],t[self.cx:]] + self.lines[self.cy+1:]
+ self.cVert(1)
+ self.cx = 0
+ self.TouchBuffer()
+
+ def InsertChar(self,char):
+ if self.IsLine(self.cy):
+ t = self.lines[self.cy]
+ t = t[:self.cx] + char + t[self.cx:]
+ self.SetTextLine(self.cy, t)
+ self.cHoriz(1)
+ self.TouchBuffer()
+
+ def JoinLines(self):
+ t1 = self.lines[self.cy]
+ t2 = self.lines[self.cy+1]
+ self.cx = len(t1)
+ self.lines = self.lines[:self.cy] + [t1 + t2] + self.lines[self.cy+2:]
+ self.TouchBuffer()
+
+
+ def DeleteChar(self,x,y,oldtext):
+ newtext = oldtext[:x] + oldtext[x+1:]
+ self.SetTextLine(y, newtext)
+ self.TouchBuffer()
+
+
+ def BackSpace(self, event):
+ t = self.GetTextLine(self.cy)
+ if self.cx>0:
+ self.DeleteChar(self.cx-1,self.cy,t)
+ self.cHoriz(-1)
+ self.TouchBuffer()
+ elif self.cx == 0:
+ if self.cy > 0:
+ self.cy -= 1
+ self.JoinLines()
+ self.TouchBuffer()
+ else:
+ wx.Bell()
+
+ def Delete(self, event):
+ t = self.GetTextLine(self.cy)
+ if self.cx<len(t):
+ self.DeleteChar(self.cx,self.cy,t)
+ self.TouchBuffer()
+ else:
+ if self.cy < len(self.lines) - 1:
+ self.JoinLines()
+ self.TouchBuffer()
+
+ def Escape(self, event):
+ self.SelectOff()
+
+ def TabKey(self, event):
+ numSpaces = self.SpacesPerTab - (self.cx % self.SpacesPerTab)
+ self.SingleLineInsert(' ' * numSpaces)
+
+##----------- selection routines
+
+ def SelectUpdate(self):
+ self.SelectEnd = (self.cy, self.cx)
+ self.SelectNotify(self.Selecting, self.SelectBegin, self.SelectEnd)
+ self.UpdateView()
+
+ def NormalizedSelect(self):
+ (begin, end) = (self.SelectBegin, self.SelectEnd)
+ (bRow, bCol) = begin
+ (eRow, eCol) = end
+ if (bRow < eRow):
+ return (begin, end)
+ elif (eRow < bRow):
+ return (end, begin)
+ else:
+ if (bCol < eCol):
+ return (begin, end)
+ else:
+ return (end, begin)
+
+ def FindSelection(self):
+ if self.SelectEnd is None or self.SelectBegin is None:
+ wx.Bell()
+ return None
+ (begin, end) = self.NormalizedSelect()
+ (bRow, bCol) = begin
+ (eRow, eCol) = end
+ return (bRow, bCol, eRow, eCol)
+
+ def SelectOff(self):
+ self.SelectBegin = None
+ self.SelectEnd = None
+ self.Selecting = False
+ self.SelectNotify(False,None,None)
+
+ def CopySelection(self, event):
+ selection = self.FindSelection()
+ if selection is None:
+ return
+ (bRow, bCol, eRow, eCol) = selection
+
+ if bRow == eRow:
+ self.SingleLineCopy(bRow, bCol, eCol)
+ else:
+ self.MultipleLineCopy(bRow, bCol, eRow, eCol)
+
+ def OnCopySelection(self, event):
+ self.CopySelection(event)
+ self.SelectOff()
+
+ def CopyToClipboard(self, linesOfText):
+ do = wx.TextDataObject()
+ do.SetText(os.linesep.join(linesOfText))
+ wx.TheClipboard.Open()
+ wx.TheClipboard.SetData(do)
+ wx.TheClipboard.Close()
+
+ def SingleLineCopy(self, Row, bCol, eCol):
+ Line = self.GetTextLine(Row)
+ self.CopyToClipboard([Line[bCol:eCol]])
+
+ def MultipleLineCopy(self, bRow, bCol, eRow, eCol):
+ bLine = self.GetTextLine(bRow)[bCol:]
+ eLine = self.GetTextLine(eRow)[:eCol]
+ self.CopyToClipboard([bLine] + [l for l in self.lines[bRow + 1:eRow]] + [eLine])
+
+ def OnDeleteSelection(self, event):
+ selection = self.FindSelection()
+ if selection is None:
+ return
+ (bRow, bCol, eRow, eCol) = selection
+
+ if bRow == eRow:
+ self.SingleLineDelete(bRow, bCol, eCol)
+ else:
+ self.MultipleLineDelete(bRow, bCol, eRow, eCol)
+
+ self.TouchBuffer()
+
+ self.cy = bRow
+ self.cx = bCol
+ self.SelectOff()
+ self.UpdateView()
+
+
+ def SingleLineDelete(self, Row, bCol, eCol):
+ ModLine = self.GetTextLine(Row)
+ ModLine = ModLine[:bCol] + ModLine[eCol:]
+ self.SetTextLine(Row,ModLine)
+
+ def MultipleLineDelete(self, bRow, bCol, eRow, eCol):
+ bLine = self.GetTextLine(bRow)
+ eLine = self.GetTextLine(eRow)
+ ModLine = bLine[:bCol] + eLine[eCol:]
+ self.lines[bRow:eRow + 1] = [ModLine]
+
+ def OnPaste(self, event):
+ do = wx.TextDataObject()
+ wx.TheClipboard.Open()
+ success = wx.TheClipboard.GetData(do)
+ wx.TheClipboard.Close()
+ if success:
+ pastedLines = LineSplitter(do.GetText())
+ else:
+ wx.Bell()
+ return
+ if len(pastedLines) == 0:
+ wx.Bell()
+ return
+ elif len(pastedLines) == 1:
+ self.SingleLineInsert(pastedLines[0])
+ else:
+ self.MultipleLinePaste(pastedLines)
+
+ def SingleLineInsert(self, newText):
+ ModLine = self.GetTextLine(self.cy)
+ ModLine = ModLine[:self.cx] + newText + ModLine[self.cx:]
+ self.SetTextLine(self.cy, ModLine)
+ self.cHoriz(len(newText))
+ self.TouchBuffer()
+ self.UpdateView()
+
+ def MultipleLinePaste(self, pastedLines):
+ FirstLine = LastLine = self.GetTextLine(self.cy)
+ FirstLine = FirstLine[:self.cx] + pastedLines[0]
+ LastLine = pastedLines[-1] + LastLine[self.cx:]
+
+ NewSlice = [FirstLine]
+ NewSlice += [l for l in pastedLines[1:-1]]
+ NewSlice += [LastLine]
+ self.lines[self.cy:self.cy + 1] = NewSlice
+
+ self.cy = self.cy + len(pastedLines)-1
+ self.cx = len(pastedLines[-1])
+ self.TouchBuffer()
+ self.UpdateView()
+
+ def OnCutSelection(self,event):
+ self.CopySelection(event)
+ self.OnDeleteSelection(event)
+
+#-------------- Keyboard movement implementations
+
+ def MoveDown(self, event):
+ self.cVert(+1)
+
+ def MoveUp(self, event):
+ self.cVert(-1)
+
+ def MoveLeft(self, event):
+ if self.cx == 0:
+ if self.cy == 0:
+ wx.Bell()
+ else:
+ self.cVert(-1)
+ self.cx = self.CurrentLineLength()
+ else:
+ self.cx -= 1
+
+ def MoveRight(self, event):
+ linelen = self.CurrentLineLength()
+ if self.cx == linelen:
+ if self.cy == len(self.lines) - 1:
+ wx.Bell()
+ else:
+ self.cx = 0
+ self.cVert(1)
+ else:
+ self.cx += 1
+
+
+ def MovePageDown(self, event):
+ self.cVert(self.sh)
+
+ def MovePageUp(self, event):
+ self.cVert(-self.sh)
+
+ def MoveHome(self, event):
+ self.cx = 0
+
+ def MoveEnd(self, event):
+ self.cx = self.CurrentLineLength()
+
+ def MoveStartOfFile(self, event):
+ self.cy = 0
+ self.cx = 0
+
+ def MoveEndOfFile(self, event):
+ self.cy = len(self.lines) - 1
+ self.cx = self.CurrentLineLength()
+
+#-------------- Key handler mapping tables
+
+ def SetMoveSpecialFuncs(self, action):
+ action[wx.WXK_DOWN] = self.MoveDown
+ action[wx.WXK_UP] = self.MoveUp
+ action[wx.WXK_LEFT] = self.MoveLeft
+ action[wx.WXK_RIGHT] = self.MoveRight
+ action[wx.WXK_NEXT] = self.MovePageDown
+ action[wx.WXK_PRIOR] = self.MovePageUp
+ action[wx.WXK_HOME] = self.MoveHome
+ action[wx.WXK_END] = self.MoveEnd
+
+ def SetMoveSpecialControlFuncs(self, action):
+ action[wx.WXK_HOME] = self.MoveStartOfFile
+ action[wx.WXK_END] = self.MoveEndOfFile
+
+ def SetAltFuncs(self, action):
+ # subclass implements
+ pass
+
+ def SetControlFuncs(self, action):
+ action['c'] = self.OnCopySelection
+ action['d'] = self.OnDeleteSelection
+ action['v'] = self.OnPaste
+ action['x'] = self.OnCutSelection
+
+ def SetSpecialControlFuncs(self, action):
+ action[wx.WXK_INSERT] = self.OnCopySelection
+
+ def SetShiftFuncs(self, action):
+ action[wx.WXK_DELETE] = self.OnCutSelection
+ action[wx.WXK_INSERT] = self.OnPaste
+
+ def SetSpecialFuncs(self, action):
+ action[wx.WXK_BACK] = self.BackSpace
+ action[wx.WXK_DELETE] = self.Delete
+ action[wx.WXK_RETURN] = self.BreakLine
+ action[wx.WXK_ESCAPE] = self.Escape
+ action[wx.WXK_TAB] = self.TabKey
+
+##-------------- Logic for key handlers
+
+
+ def Move(self, keySettingFunction, key, event):
+ action = {}
+ keySettingFunction(action)
+
+ if not action.has_key(key):
+ return False
+
+ if event.ShiftDown():
+ if not self.Selecting:
+ self.Selecting = True
+ self.SelectBegin = (self.cy, self.cx)
+ action[key](event)
+ self.SelectEnd = (self.cy, self.cx)
+ else:
+ action[key](event)
+ if self.Selecting:
+ self.Selecting = False
+
+ self.SelectNotify(self.Selecting, self.SelectBegin, self.SelectEnd)
+ self.UpdateView()
+ return True
+
+ def MoveSpecialKey(self, event, key):
+ return self.Move(self.SetMoveSpecialFuncs, key, event)
+
+ def MoveSpecialControlKey(self, event, key):
+ if not event.ControlDown():
+ return False
+ return self.Move(self.SetMoveSpecialControlFuncs, key, event)
+
+ def Dispatch(self, keySettingFunction, key, event):
+ action = {}
+ keySettingFunction(action)
+ if action.has_key(key):
+ action[key](event)
+ self.UpdateView()
+ return True
+ return False
+
+ def ModifierKey(self, key, event, modifierKeyDown, MappingFunc):
+ if not modifierKeyDown:
+ return False
+
+ key = self.UnixKeyHack(key)
+ try:
+ key = chr(key)
+ except:
+ return False
+ if not self.Dispatch(MappingFunc, key, event):
+ wx.Bell()
+ return True
+
+ def ControlKey(self, event, key):
+ return self.ModifierKey(key, event, event.ControlDown(), self.SetControlFuncs)
+
+ def AltKey(self, event, key):
+ return self.ModifierKey(key, event, event.AltDown(), self.SetAltFuncs)
+
+ def SpecialControlKey(self, event, key):
+ if not event.ControlDown():
+ return False
+ if not self.Dispatch(self.SetSpecialControlFuncs, key, event):
+ wx.Bell()
+ return True
+
+ def ShiftKey(self, event, key):
+ if not event.ShiftDown():
+ return False
+ return self.Dispatch(self.SetShiftFuncs, key, event)
+
+ def NormalChar(self, event, key):
+ self.SelectOff()
+
+ # regular ascii
+ if not self.Dispatch(self.SetSpecialFuncs, key, event):
+ if (key>31) and (key<256):
+ self.InsertChar(chr(key))
+ else:
+ wx.Bell()
+ return
+ self.UpdateView()
+ self.AdjustScrollbars()
+
+ def OnChar(self, event):
+ key = event.GetKeyCode()
+ filters = [self.AltKey,
+ self.MoveSpecialControlKey,
+ self.ControlKey,
+ self.SpecialControlKey,
+ self.MoveSpecialKey,
+ self.ShiftKey,
+ self.NormalChar]
+ for filter in filters:
+ if filter(event,key):
+ break
+ return 0
+
+#----------------------- Eliminate memory leaks
+
+ def OnDestroy(self, event):
+ self.mdc = None
+ self.odc = None
+ self.bgColor = None
+ self.fgColor = None
+ self.font = None
+ self.selectColor = None
+ self.scrollTimer = None
+ self.eofMarker = None
+
+#-------------------- Abstract methods for subclasses
+
+ def OnClick(self):
+ pass
+
+ def SelectNotify(self, Selecting, SelectionBegin, SelectionEnd):
+ pass
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/images.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/images.py
new file mode 100644
index 0000000..8625953
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/images.py
@@ -0,0 +1,15 @@
+
+# images converted with wxPython's img2py.py tool
+
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+EofImage = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAABHNCSVQICAgIfAhkiAAAADpJ"
+ "REFUeJxdjsENADAIAsUJbv8p3aB90WD5KJwJCihrZg4g+06Q88EM0quqFkh1dqQAtZcfrIcc"
+ "5OEFYDIVnsU0yrQAAAAASUVORK5CYII=")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/selection.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/selection.py
new file mode 100644
index 0000000..df61cdc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/editor/selection.py
@@ -0,0 +1,44 @@
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+
+def RestOfLine(sx, width, data, bool):
+ if len(data) == 0 and sx == 0:
+ return [('', bool)]
+ if sx >= len(data):
+ return []
+ return [(data[sx:sx+width], bool)]
+
+def Selection(SelectBegin,SelectEnd, sx, width, line, data):
+ if SelectEnd is None or SelectBegin is None:
+ return RestOfLine(sx, width, data, False)
+ (bRow, bCol) = SelectBegin
+ (eRow, eCol) = SelectEnd
+ if (eRow < bRow):
+ (bRow, bCol) = SelectEnd
+ (eRow, eCol) = SelectBegin
+ if (line < bRow or eRow < line):
+ return RestOfLine(sx, width, data, False)
+ if (bRow < line and line < eRow):
+ return RestOfLine(sx, width, data, True)
+ if (bRow == eRow) and (eCol < bCol):
+ (bCol, eCol) = (eCol, bCol)
+ # selection either starts or ends on this line
+ end = min(sx+width, len(data))
+ if (bRow < line):
+ bCol = 0
+ if (line < eRow):
+ eCol = end
+ pieces = []
+ if (sx < bCol):
+ if bCol <= end:
+ pieces += [(data[sx:bCol], False)]
+ else:
+ return [(data[sx:end], False)]
+ pieces += [(data[max(bCol,sx):min(eCol,end)], True)]
+ if (eCol < end):
+ pieces += [(data[eCol:end], False)]
+ return pieces
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/embeddedimage.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/embeddedimage.py
new file mode 100644
index 0000000..06b968a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/embeddedimage.py
@@ -0,0 +1,75 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.embeddedimage
+# Purpose: Defines a class used for embedding PNG images in Python
+# code. The primary method of using this module is via
+# the code generator in wx.tools.img2py.
+#
+# Author: Anthony Tuininga
+#
+# Created: 26-Nov-2007
+# RCS-ID: $Id$
+# Copyright: (c) 2007 by Anthony Tuininga
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import base64
+import cStringIO
+import wx
+
+try:
+ b64decode = base64.b64decode
+except AttributeError:
+ b64decode = base64.decodestring
+
+
+class PyEmbeddedImage(object):
+ """
+ PyEmbeddedImage is primarily intended to be used by code generated
+ by img2py as a means of embedding image data in a python module so
+ the image can be used at runtime without needing to access the
+ image from an image file. This makes distributing icons and such
+ that an application uses simpler since tools like py2exe will
+ automatically bundle modules that are imported, and the
+ application doesn't have to worry about how to locate the image
+ files on the user's filesystem.
+
+ The class can also be used for image data that may be acquired
+ from some other source at runtime, such as over the network or
+ from a database. In this case pass False for isBase64 (unless the
+ data actually is base64 encoded.) Any image type that
+ wx.ImageFromStream can handle should be okay.
+ """
+
+ def __init__(self, data, isBase64=True):
+ self.data = data
+ self.isBase64 = isBase64
+
+ def GetBitmap(self):
+ return wx.BitmapFromImage(self.GetImage())
+
+ def GetData(self):
+ data = self.data
+ if self.isBase64:
+ data = b64decode(self.data)
+ return data
+
+ def GetIcon(self):
+ icon = wx.EmptyIcon()
+ icon.CopyFromBitmap(self.GetBitmap())
+ return icon
+
+ def GetImage(self):
+ stream = cStringIO.StringIO(self.GetData())
+ return wx.ImageFromStream(stream)
+
+ # added for backwards compatibility
+ getBitmap = GetBitmap
+ getData = GetData
+ getIcon = GetIcon
+ getImage = GetImage
+
+ # define properties, for convenience
+ Bitmap = property(GetBitmap)
+ Icon = property(GetIcon)
+ Image = property(GetImage)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/eventStack.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/eventStack.py
new file mode 100644
index 0000000..d057414
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/eventStack.py
@@ -0,0 +1,136 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.eventStack
+# Purpose: These mixins implement a push and pop menu/UI update event
+# handler system at the wx.App level. This is useful for resolving
+# cases where multiple views may want to respond to an event
+# (say, wx.ID_COPY) and where you also want a "default" handler
+# for the event (and UI update status) when there is no active
+# view which wishes to handle the event.
+#
+# Author: Kevin Ollivier
+#
+# Created: -Mar-
+# Copyright: (c) Kevin Ollivier
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import sys, os
+import wx
+
+class AppEventManager:
+ ui_events = [
+ wx.ID_NEW, wx.ID_OPEN, wx.ID_CLOSE_ALL, wx.ID_CLOSE,
+ wx.ID_REVERT, wx.ID_SAVE, wx.ID_SAVEAS, wx.ID_UNDO,
+ wx.ID_REDO, wx.ID_PRINT, wx.ID_PRINT_SETUP, wx.ID_PREVIEW,
+ wx.ID_EXIT
+ ]
+
+ def __init__(self):
+ pass
+
+ def RegisterEvents(self):
+ app = wx.GetApp()
+ #app.AddHandlerForID(wx.ID_EXIT, self.OnExit)
+ #app.AddHandlerForID(wx.ID_ABOUT, self.OnAbout)
+
+ for eventID in self.ui_events:
+ app.AddHandlerForID(eventID, self.ProcessEvent)
+ app.AddUIHandlerForID(eventID, self.ProcessUpdateUIEvent)
+
+class AppEventHandlerMixin:
+ """
+ The purpose of the AppEventHandlerMixin is to provide a centralized
+ location to manage menu and toolbar events. In an IDE which may have
+ any number of file editors and services open that may want to respond
+ to certain menu and toolbar events (e.g. copy, paste, select all),
+ we need this to efficiently make sure that the right handler is handling
+ the event.
+
+ To work with this system, views must call::
+
+ AddHandlerForID(ID, handlerFunc)
+
+
+ or::
+
+ AddUIHandlerForID(ID, handlerFunc)
+
+
+ in their EVT_SET_FOCUS handler, and call Remove(UI)HandlerForID(ID) in their
+ EVT_KILL_FOCUS handler.
+ """
+
+ def __init__(self):
+ self.handlers = {}
+ self.uihandlers = {}
+
+ # When a view changes the handler, move the old one here.
+ # Then "pop" the handler when the view loses the focus
+ self.pushed_handlers = {}
+ self.pushed_uihandlers = {}
+
+ def AddHandlerForIDs(self, eventID_list, handlerFunc):
+ for eventID in eventID_list:
+ self.AddHandlerForID(eventID, handlerFunc)
+
+ def AddHandlerForID(self, eventID, handlerFunc):
+ self.Bind(wx.EVT_MENU, self.HandleEvent, id=eventID)
+
+ if eventID in self.handlers:
+ self.pushed_handlers[eventID] = self.handlers[eventID]
+
+ self.handlers[eventID] = handlerFunc
+
+ def AddUIHandlerForID(self, eventID, handlerFunc):
+ self.Bind(wx.EVT_UPDATE_UI, self.HandleUpdateUIEvent, id=eventID)
+
+ if eventID in self.uihandlers:
+ self.pushed_uihandlers[eventID] = self.uihandlers[eventID]
+
+ self.uihandlers[eventID] = handlerFunc
+
+ def RemoveHandlerForIDs(self, eventID_list):
+ for eventID in eventID_list:
+ self.RemoveHandlerForID(eventID)
+
+ def RemoveHandlerForID(self, eventID):
+ self.Unbind(wx.EVT_MENU, id=eventID)
+ self.handlers[eventID] = None
+
+ if eventID in self.pushed_handlers:
+ self.handlers[eventID] = self.pushed_handlers[eventID]
+
+ def RemoveUIHandlerForID(self, eventID):
+ self.Unbind(wx.EVT_UPDATE_UI, id=eventID)
+ self.uihandlers[eventID] = None
+
+ if eventID in self.pushed_uihandlers:
+ self.uihandlers[eventID] = self.pushed_uihandlers[eventID]
+
+ def HandleEvent(self, event):
+ e_id = event.GetId()
+ if e_id in self.handlers:
+ handler = self.handlers[e_id]
+ try:
+ if handler:
+ return handler(event)
+ except wx.PyDeadObjectError:
+ self.RemoveHandlerForID(e_id)
+ else:
+ event.Skip()
+
+ return False
+
+ def HandleUpdateUIEvent(self, event):
+ e_id = event.GetId()
+ if e_id in self.uihandlers:
+ handler = self.uihandlers[e_id]
+ try:
+ if handler:
+ return handler(event)
+ except wx.PyDeadObjectError:
+ self.RemoveUIHandlerForID(e_id)
+ else:
+ event.Skip()
+
+ return False
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/eventwatcher.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/eventwatcher.py
new file mode 100644
index 0000000..9b61054
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/eventwatcher.py
@@ -0,0 +1,458 @@
+#----------------------------------------------------------------------------
+# Name: wx.lib.eventwatcher
+# Purpose: A widget that allows some or all events for a particular widget
+# to be captured and displayed.
+#
+# Author: Robin Dunn
+#
+# Created: 21-Jan-2009
+# RCS-ID: $Id: $
+# Copyright: (c) 2009 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+"""
+A widget and supporting classes for watching the events sent to some other widget.
+"""
+
+import wx
+from wx.lib.mixins.listctrl import CheckListCtrlMixin
+
+#----------------------------------------------------------------------------
+# Helpers for building the data structures used for tracking the
+# various event binders that are available
+
+_eventBinders = None
+_eventIdMap = None
+
+def _buildModuleEventMap(module):
+ count = 0
+ for name in dir(module):
+ if name.startswith('EVT_'):
+ item = getattr(module, name)
+ if isinstance(item, wx.PyEventBinder) and \
+ len(item.evtType) == 1 and \
+ item not in _eventBinders:
+ _eventBinders.append(item)
+ _eventIdMap[item.typeId] = name
+ count += 1
+ return count
+
+
+def buildWxEventMap():
+ """
+ Add the event binders from the main wx namespace. This is called
+ automatically from the EventWatcher.
+ """
+ global _eventBinders
+ global _eventIdMap
+ if _eventBinders is None:
+ _eventBinders = list()
+ _eventIdMap = dict()
+ _buildModuleEventMap(wx)
+
+
+def addModuleEvents(module):
+ """
+ Adds all the items in module that start with ``EVT_`` to the event
+ data structures used by the EventWatcher.
+ """
+ if _eventBinders is None:
+ buildWxEventMap()
+ return _buildModuleEventMap(module)
+
+
+# Events that should not be watched by default
+_noWatchList = [
+ wx.EVT_PAINT,
+ wx.EVT_NC_PAINT,
+ wx.EVT_ERASE_BACKGROUND,
+ wx.EVT_IDLE,
+ wx.EVT_UPDATE_UI,
+ wx.EVT_UPDATE_UI_RANGE,
+ ]
+OTHER_WIDTH = 250
+
+
+def _makeSourceString(wdgt):
+ if wdgt is None:
+ return "None"
+ else:
+ name = ''
+ id = 0
+ if hasattr(wdgt, 'GetName'):
+ name = wdgt.GetName()
+ if hasattr(wdgt, 'GetId'):
+ id = wdgt.GetId()
+ return '%s "%s" (%d)' % (wdgt.__class__.__name__, name, id)
+
+def _makeAttribString(evt):
+ "Find all the getters"
+ attribs = ""
+ for name in dir(evt):
+ if (name.startswith('Get') or name.startswith('Is')) and \
+ name not in [ 'GetEventObject',
+ 'GetEventType',
+ 'GetId',
+ 'GetSkipped',
+ 'GetTimestamp',
+ 'GetClientData',
+ 'GetClientObject',
+ ]:
+ try:
+ value = getattr(evt, name)()
+ attribs += "%s : %s\n" % (name, value)
+ except:
+ pass
+
+ return attribs.rstrip()
+
+#----------------------------------------------------------------------------
+
+class EventLog(wx.ListCtrl):
+ """
+ A virtual listctrl that displays information about the watched events.
+ """
+ def __init__(self, *args, **kw):
+ kw['style'] = wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES
+ wx.ListCtrl.__init__(self, *args, **kw)
+ self.clear()
+
+ if 'wxMac' in wx.PlatformInfo:
+ self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+
+ self.InsertColumn(0, "#", format=wx.LIST_FORMAT_RIGHT, width=50)
+ self.InsertColumn(1, "Event", width=200)
+ self.InsertColumn(2, "Source", width=200)
+
+ self.SetMinSize((450+wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X), 450))
+ self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onItemSelected)
+ self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.onItemActivated)
+ self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.onItemActivated)
+
+ def append(self, evt):
+ evtName = _eventIdMap.get(evt.GetEventType(), None)
+ if evtName is None:
+ evtName = 'Unknown: %d' % evt.GetEventType()
+ source = _makeSourceString(evt.GetEventObject())
+ attribs = _makeAttribString(evt)
+
+ lastIsSelected = self.currItem == len(self.data)-1
+ self.data.append( (evtName, source, attribs) )
+
+ count = len(self.data)
+ self.SetItemCount(count)
+ self.RefreshItem(count-1)
+ if lastIsSelected:
+ self.Select(count-1)
+ self.EnsureVisible(count-1)
+
+ def clear(self):
+ self.data = []
+ self.SetItemCount(0)
+ self.currItem = -1
+ self.Refresh()
+
+ def OnGetItemText(self, item, col):
+ if col == 0:
+ val = str(item+1)
+ else:
+ val = self.data[item][col-1]
+ return val
+
+ def OnGetItemAttr(self, item): return None
+ def OnGetItemImage(self, item): return -1
+
+ def onItemSelected(self, evt):
+ self.currItem = evt.GetIndex()
+
+ def onItemActivated(self, evt):
+ idx = evt.GetIndex()
+ text = self.data[idx][2]
+ wx.CallAfter(wx.TipWindow, self, text, OTHER_WIDTH)
+
+#----------------------------------------------------------------------------
+
+
+class EventChooser(wx.Panel):
+ """
+ Panel with CheckListCtrl for selecting which events will be watched.
+ """
+
+ class EventChooserLC(wx.ListCtrl, CheckListCtrlMixin):
+ def __init__(self, parent):
+ wx.ListCtrl.__init__(self, parent,
+ style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_HRULES|wx.LC_VRULES)
+ CheckListCtrlMixin.__init__(self)
+ if 'wxMac' in wx.PlatformInfo:
+ self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+
+ # this is called by the base class when an item is checked/unchecked
+ def OnCheckItem(self, index, flag):
+ self.Parent.OnCheckItem(index, flag)
+
+
+ def __init__(self, *args, **kw):
+ wx.Panel.__init__(self, *args, **kw)
+ self.updateCallback = lambda: None
+ self.doUpdate = True
+ self._event_name_filter = wx.SearchCtrl(self)
+ self._event_name_filter.ShowCancelButton(True)
+ self._event_name_filter.Bind(wx.EVT_TEXT, lambda evt: self.setWatchList(self.watchList))
+ self._event_name_filter.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self._ClearEventFilter)
+ self.lc = EventChooser.EventChooserLC(self)
+ btn1 = wx.Button(self, -1, "All")
+ btn2 = wx.Button(self, -1, "None")
+ btn1.SetToolTipString("Check all events")
+ btn2.SetToolTipString("Uncheck all events")
+
+ self.Bind(wx.EVT_BUTTON, self.onCheckAll, btn1)
+ self.Bind(wx.EVT_BUTTON, self.onUncheckAll, btn2)
+
+ self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.onItemActivated, self.lc)
+ self.lc.InsertColumn(0, "Binder", width=OTHER_WIDTH)
+
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+ btnSizer.Add(btn1, 0, wx.ALL, 5)
+ btnSizer.Add(btn2, 0, wx.ALL, 5)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(self._event_name_filter, 0, wx.EXPAND|wx.ALL, 5)
+ sizer.Add(self.lc, 1, wx.EXPAND)
+ sizer.Add(btnSizer)
+ self.SetSizer(sizer)
+
+
+ def setUpdateCallback(self, func):
+ self.updateCallback = func
+
+ def setWatchList(self, watchList):
+ self.doUpdate = False
+ searched = self._event_name_filter.GetValue().lower()
+ self.watchList = watchList
+ self.lc.DeleteAllItems()
+ count = 0
+ for index, (item, flag) in enumerate(watchList):
+ typeId = item.typeId
+ text = _eventIdMap.get(typeId, "[Unknown]")
+ if text.lower().find(searched) == -1:
+ continue
+ self.lc.InsertStringItem(count, text)
+ self.lc.SetItemData(count, index)
+ if flag:
+ self.lc.CheckItem(count)
+ count += 1
+ self.lc.SortItems(self.sortCompare)
+ self.doUpdate = True
+ self.updateCallback()
+
+
+ def OnCheckItem(self, index, flag):
+ index = self.lc.GetItemData(index)
+ item, f = self.watchList[index]
+ self.watchList[index] = (item, flag)
+ if self.doUpdate:
+ self.updateCallback()
+
+
+ def onItemActivated(self, evt):
+ self.lc.ToggleItem(evt.m_itemIndex)
+
+ def onCheckAll(self, evt):
+ self.doUpdate = False
+ for idx in range(self.lc.GetItemCount()):
+ self.lc.CheckItem(idx, True)
+ self.doUpdate = True
+ self.updateCallback()
+
+ def onUncheckAll(self, evt):
+ self.doUpdate = False
+ for idx in range(self.lc.GetItemCount()):
+ self.lc.CheckItem(idx, False)
+ self.doUpdate = True
+ self.updateCallback()
+
+
+ def sortCompare(self, data1, data2):
+ item1 = self.watchList[data1][0]
+ item2 = self.watchList[data2][0]
+ text1 = _eventIdMap.get(item1.typeId)
+ text2 = _eventIdMap.get(item2.typeId)
+ return cmp(text1, text2)
+
+ def _ClearEventFilter(self, evt):
+ self._event_name_filter.SetValue("")
+
+#----------------------------------------------------------------------------
+
+class EventWatcher(wx.Frame):
+ """
+ A frame that will catch and display al events sent to some widget.
+ """
+ def __init__(self, *args, **kw):
+ wx.Frame.__init__(self, *args, **kw)
+ self.SetTitle("EventWatcher")
+ self.SetExtraStyle(wx.WS_EX_BLOCK_EVENTS)
+ self._watchedWidget = None
+
+ buildWxEventMap()
+ self.buildWatchList(_noWatchList)
+
+ # Make the widgets
+ self.splitter = wx.SplitterWindow(self)
+ panel = wx.Panel(self.splitter)
+ self.splitter.Initialize(panel)
+ self.log = EventLog(panel)
+ clearBtn = wx.Button(panel, -1, "Clear")
+ addBtn = wx.Button(panel, -1, "Add Module")
+ watchBtn = wx.ToggleButton(panel, -1, "Watch")
+ watchBtn.SetValue(True)
+ selectBtn = wx.ToggleButton(panel, -1, ">>>")
+ self.selectBtn = selectBtn
+
+ clearBtn.SetToolTipString("Clear the event log")
+ addBtn.SetToolTipString("Add the event binders in an additional package or module to the watcher")
+ watchBtn.SetToolTipString("Toggle the watching of events")
+ selectBtn.SetToolTipString("Show/hide the list of events to be logged")
+
+ # Do the layout
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+ btnSizer.Add(clearBtn, 0, wx.RIGHT, 5)
+ btnSizer.Add(addBtn, 0, wx.RIGHT, 5)
+ btnSizer.Add((1,1), 1)
+ btnSizer.Add(watchBtn, 0, wx.RIGHT, 5)
+ btnSizer.Add((1,1), 1)
+ btnSizer.Add(selectBtn, 0, wx.RIGHT, 5)
+ sizer.Add(self.log, 1, wx.EXPAND)
+ sizer.Add(btnSizer, 0, wx.EXPAND|wx.ALL, 5)
+ panel.SetSizer(sizer)
+ self.Sizer = wx.BoxSizer()
+ self.Sizer.Add(self.splitter, 1, wx.EXPAND)
+ self.Fit()
+
+ # Bind events
+ self.Bind(wx.EVT_CLOSE, self.onCloseWindow)
+ self.Bind(wx.EVT_BUTTON, self.onClear, clearBtn)
+ self.Bind(wx.EVT_BUTTON, self.onAddModule, addBtn)
+ self.Bind(wx.EVT_TOGGLEBUTTON, self.onToggleWatch, watchBtn)
+ self.Bind(wx.EVT_TOGGLEBUTTON, self.onToggleSelectEvents, selectBtn)
+
+
+
+ def watch(self, widget):
+ assert self._watchedWidget is None, "Can only watch one widget at a time"
+ self.SetTitle("EventWatcher for " + _makeSourceString(widget))
+ for evtBinder, flag in self._watchedEvents:
+ if flag:
+ widget.Bind(evtBinder, self.onWatchedEvent)
+ self._watchedWidget = widget
+
+
+ def unwatch(self):
+ self.SetTitle("EventWatcher")
+ if self._watchedWidget:
+ for evtBinder, flag in self._watchedEvents:
+ self._watchedWidget.Unbind(evtBinder, handler=self.onWatchedEvent)
+ self._watchedWidget = None
+
+
+ def updateBindings(self):
+ widget = self._watchedWidget
+ self.unwatch()
+ self.watch(widget)
+
+
+ def onWatchedEvent(self, evt):
+ if self:
+ self.log.append(evt)
+ evt.Skip()
+
+ def buildWatchList(self, exclusions):
+ # This is a list of (PyEventBinder, flag) tuples where the flag indicates
+ # whether to bind that event or not. By default all execpt those in
+ # the _noWatchList wil be set to be watched.
+ self._watchedEvents = list()
+ for item in _eventBinders:
+ self._watchedEvents.append( (item, item not in exclusions) )
+
+ def onCloseWindow(self, evt):
+ self.unwatch()
+ evt.Skip()
+
+ def onClear(self, evt):
+ self.log.clear()
+
+ def onAddModule(self, evt):
+ try:
+ dlg = wx.TextEntryDialog(
+ self,
+ "Enter the package or module name to be scanned for \"EVT_\" event binders.",
+ "Add Module")
+ if dlg.ShowModal() == wx.ID_OK:
+ modname = dlg.GetValue()
+ try:
+ # Passing a non-empty fromlist will cause __import__ to
+ # return the imported submodule if a dotted name is passed.
+ module = __import__(modname, fromlist=[0])
+ except ImportError:
+ wx.MessageBox("Unable to import \"%s\"" % modname,
+ "Error")
+ return
+ count = addModuleEvents(module)
+ wx.MessageBox("%d new event binders found" % count,
+ "Success")
+
+ # Now unwatch and re-watch so we can get the new events bound
+ self.updateBindings()
+ finally:
+ dlg.Destroy()
+
+
+ def onToggleWatch(self, evt):
+ if evt.Checked():
+ self.watch(self._unwatchedWidget)
+ self._unwatchedWidget = None
+ else:
+ self._unwatchedWidget = self._watchedWidget
+ self.unwatch()
+
+
+ def onToggleSelectEvents(self, evt):
+ if evt.Checked():
+ self.selectBtn.SetLabel("<<<")
+ self._selectList = EventChooser(self.splitter)
+ self._selectList.setUpdateCallback(self.updateBindings)
+ self._selectList.setWatchList(self._watchedEvents)
+
+ self.SetSize(self.GetSize() + (OTHER_WIDTH,0))
+ self.splitter.SplitVertically(self.splitter.GetWindow1(),
+ self._selectList,
+ -OTHER_WIDTH)
+ else:
+ self.selectBtn.SetLabel(">>>")
+ sashPos = self.splitter.GetSashPosition()
+ self.splitter.Unsplit()
+ self._selectList.Destroy()
+ cs = self.GetClientSize()
+ self.SetClientSize((sashPos, cs.height))
+
+#----------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ app = wx.App(redirect=False)
+ frm = wx.Frame(None, title="Test Frame")
+ pnl = wx.Panel(frm)
+ txt = wx.TextCtrl(pnl, -1, "text", pos=(20,20))
+ btn = wx.Button(pnl, -1, "button", pos=(20,50))
+ frm.Show()
+
+ ewf=EventWatcher(frm)
+ ewf.watch(frm)
+ ewf.Show()
+
+ #import wx.lib.inspection
+ #wx.lib.inspection.InspectionTool().Show()
+
+ app.MainLoop()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/evtmgr.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/evtmgr.py
new file mode 100644
index 0000000..7699c7d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/evtmgr.py
@@ -0,0 +1,521 @@
+#---------------------------------------------------------------------------
+# Name: wxPython.lib.evtmgr
+# Purpose: An easier, more "Pythonic" and more OO method of registering
+# handlers for wxWindows events using the Publish/Subscribe
+# pattern.
+#
+# Author: Robb Shecter and Robin Dunn
+#
+# Created: 12-December-2002
+# RCS-ID: $Id$
+# Copyright: (c) 2003 by db-X Corporation
+# Licence: wxWindows license
+#---------------------------------------------------------------------------
+# 12/02/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for 2.5 compatability.
+#
+
+"""
+A module that allows multiple handlers to respond to single wxWidgets
+events. This allows true NxN Observer/Observable connections: One
+event can be received by multiple handlers, and one handler can
+receive multiple events.
+
+There are two ways to register event handlers. The first way is
+similar to standard wxPython handler registration::
+
+ from wx.lib.evtmgr import eventManager
+ eventManager.Register(handleEvents, EVT_BUTTON, win=frame, id=101)
+
+There's also a new object-oriented way to register for events. This
+invocation is equivalent to the one above, but does not require the
+programmer to declare or track control ids or parent containers::
+
+ eventManager.Register(handleEvents, EVT_BUTTON, myButton)
+
+"""
+import wx
+from wx.lib.pubsub import pub # publish / subscribe library
+
+#---------------------------------------------------------------------------
+
+
+class EventManager:
+ """
+ This is the main class in the module, and is the only class that
+ the application programmer needs to use. There is a pre-created
+ instance of this class called 'eventManager'. It should not be
+ necessary to create other instances.
+ """
+ def __init__(self):
+ self.eventAdapterDict = {}
+ self.messageAdapterDict = {}
+ self.windowTopicLookup = {}
+ self.listenerTopicLookup = {}
+ self.EMPTY_LIST = []
+
+
+ def Register(self, listener, event, source=None, win=None, id=None):
+ """
+ Registers a listener function (or any callable object) to
+ receive events of type event coming from the source window.
+ For example::
+
+ eventManager.Register(self.OnButton, EVT_BUTTON, theButton)
+
+ Alternatively, the specific window where the event is
+ delivered, and/or the ID of the event source can be specified.
+ For example::
+
+ eventManager.Register(self.OnButton, EVT_BUTTON, win=self, id=ID_BUTTON)
+
+ or::
+
+ eventManager.Register(self.OnButton, EVT_BUTTON, theButton, self)
+
+ """
+
+ # 1. Check if the 'event' is actually one of the multi-
+ # event macros.
+ if _macroInfo.isMultiEvent(event):
+ raise Exception, 'Cannot register the macro, '+`event`+'. Register instead the individual events.'
+
+ # Support a more OO API. This allows the GUI widget itself to
+ # be specified, and the id to be retrieved from the system,
+ # instead of kept track of explicitly by the programmer.
+ # (Being used to doing GUI work with Java, this seems to me to be
+ # the natural way of doing things.)
+ if source is not None:
+ id = source.GetId()
+
+ if win is None:
+ # Some widgets do not function as their own windows.
+ win = self._determineWindow(source)
+
+ topic = ".".join([str(event.typeId), str(win.GetId()), str(id)])
+
+ # Create an adapter from the PS system back to wxEvents, and
+ # possibly one from wxEvents:
+ if not self.__haveMessageAdapter(listener, topic):
+ messageAdapter = MessageAdapter(eventHandler=listener, topicPattern=topic)
+ try:
+ self.messageAdapterDict[topic][listener] = messageAdapter
+ except KeyError:
+ self.messageAdapterDict[topic] = {}
+ self.messageAdapterDict[topic][listener] = messageAdapter
+
+ if not self.eventAdapterDict.has_key(topic):
+ self.eventAdapterDict[topic] = EventAdapter(event, win, id)
+ else:
+ # Throwing away a duplicate request
+ pass
+
+ # For time efficiency when deregistering by window:
+ try:
+ self.windowTopicLookup[win].append(topic)
+ except KeyError:
+ self.windowTopicLookup[win] = []
+ self.windowTopicLookup[win].append(topic)
+
+ # For time efficiency when deregistering by listener:
+ try:
+ self.listenerTopicLookup[listener].append(topic)
+ except KeyError:
+ self.listenerTopicLookup[listener] = []
+ self.listenerTopicLookup[listener].append(topic)
+
+ # See if the source understands the listeningFor protocol.
+ # This is a bit of a test I'm working on - it allows classes
+ # to know when their events are being listened to. I use
+ # it to enable chaining events from contained windows only
+ # when needed.
+ if source is not None:
+ try:
+ # Let the source know that we're listening for this
+ # event.
+ source.listeningFor(event)
+ except AttributeError:
+ pass
+
+ # Some aliases for Register, just for kicks
+ Bind = Register
+ Subscribe = Register
+
+
+ def DeregisterWindow(self, win):
+ """
+ Deregister all events coming from the given window.
+ """
+ win = self._determineWindow(win)
+ topics = self.__getTopics(win)
+
+ if topics:
+ for aTopic in topics:
+ self.__deregisterTopic(aTopic)
+
+ del self.windowTopicLookup[win]
+
+
+ def DeregisterListener(self, listener):
+ """
+ Deregister all event notifications for the given listener.
+ """
+ try:
+ topicList = self.listenerTopicLookup[listener]
+ except KeyError:
+ return
+
+ for topic in topicList:
+ topicDict = self.messageAdapterDict[topic]
+
+ if topicDict.has_key(listener):
+ topicDict[listener].Destroy()
+ del topicDict[listener]
+
+ if len(topicDict) == 0:
+ self.eventAdapterDict[topic].Destroy()
+ del self.eventAdapterDict[topic]
+ del self.messageAdapterDict[topic]
+
+ del self.listenerTopicLookup[listener]
+
+
+ def GetStats(self):
+ """
+ Return a dictionary with data about my state.
+ """
+ stats = {}
+ stats['Adapters: Message'] = reduce(lambda x,y: x+y, [0] + map(len, self.messageAdapterDict.values()))
+ stats['Adapters: Event'] = len(self.eventAdapterDict)
+ stats['Topics: Total'] = len(self.__getTopics())
+ stats['Topics: Dead'] = len(self.GetDeadTopics())
+ return stats
+
+
+ def DeregisterDeadTopics(self):
+ """
+ Deregister any entries relating to dead
+ wxPython objects. Not sure if this is an
+ important issue; 1) My app code always de-registers
+ listeners it doesn't need. 2) I don't think
+ that lingering references to these dead objects
+ is a problem.
+ """
+ for topic in self.GetDeadTopics():
+ self.__deregisterTopic(topic)
+
+
+ def GetDeadTopics(self):
+ """
+ Return a list of topics relating to dead wxPython
+ objects.
+ """
+ return filter(self.__isDeadTopic, self.__getTopics())
+
+
+ def __winString(self, aWin):
+ """
+ A string rep of a window for debugging
+ """
+ try:
+ name = aWin.GetClassName()
+ i = id(aWin)
+ return '%s #%d' % (name, i)
+ except wx.PyDeadObjectError:
+ return '(dead wx.Object)'
+
+
+ def __topicString(self, aTopic):
+ """
+ A string rep of a topic for debugging
+ """
+ return '[%-26s %s]' % (aTopic[0].__name__, self.winString(aTopic[1]))
+
+
+ def __listenerString(self, aListener):
+ """
+ A string rep of a listener for debugging
+ """
+ try:
+ return aListener.im_class.__name__ + '.' + aListener.__name__
+ except:
+ return 'Function ' + aListener.__name__
+
+
+ def __deregisterTopic(self, aTopic):
+ try:
+ messageAdapterList = self.messageAdapterDict[aTopic].values()
+ except KeyError:
+ # This topic isn't valid. Probably because it was deleted
+ # by listener.
+ return
+
+ for messageAdapter in messageAdapterList:
+ messageAdapter.Destroy()
+
+ self.eventAdapterDict[aTopic].Destroy()
+ del self.messageAdapterDict[aTopic]
+ del self.eventAdapterDict[aTopic]
+
+
+ def __getTopics(self, win=None):
+ if win is None:
+ return self.messageAdapterDict.keys()
+
+ if win is not None:
+ try:
+ return self.windowTopicLookup[win]
+ except KeyError:
+ return self.EMPTY_LIST
+
+
+ def __isDeadWxObject(self, anObject):
+ return isinstance(anObject, wx._core._wxPyDeadObject)
+
+
+ def __isDeadTopic(self, aTopic):
+ return self.__isDeadWxObject(aTopic[1])
+
+
+ def __haveMessageAdapter(self, eventHandler, topicPattern):
+ """
+ Return True if there's already a message adapter
+ with these specs.
+ """
+ try:
+ return self.messageAdapterDict[topicPattern].has_key(eventHandler)
+ except KeyError:
+ return 0
+
+
+ def _determineWindow(self, aComponent):
+ """
+ Return the window that corresponds to this component.
+ A window is something that supports the Connect protocol.
+ Most things registered with the event manager are a window,
+ but there are apparently some exceptions. If more are
+ discovered, the implementation can be changed to a dictionary
+ lookup along the lines of class : function-to-get-window.
+ """
+ if isinstance(aComponent, wx.MenuItem):
+ return aComponent.GetMenu()
+ else:
+ return aComponent
+
+
+
+#---------------------------------------------------------------------------
+# From here down is implementaion and support classes, although you may
+# find some of them useful in other contexts.
+#---------------------------------------------------------------------------
+
+
+class EventMacroInfo:
+ """
+ A class that provides information about event macros.
+ """
+ def __init__(self):
+ pass
+
+ def getEventTypes(self, eventMacro):
+ """
+ Return the list of event types that the given
+ macro corresponds to.
+ """
+ return eventMacro.evtType
+
+
+ def eventIsA(self, event, macroList):
+ """
+ Return True if the event is one of the given
+ macros.
+ """
+ eventType = event.GetEventType()
+ for macro in macroList:
+ if eventType in self.getEventTypes(macro):
+ return 1
+ return 0
+
+
+ def macroIsA(self, macro, macroList):
+ """
+ Return True if the macro is in the macroList.
+ The added value of this method is that it takes
+ multi-events into account. The macroList parameter
+ will be coerced into a sequence if needed.
+ """
+ if callable(macroList):
+ macroList = (macroList,)
+ testList = self.getEventTypes(macro)
+ eventList = []
+ for m in macroList:
+ eventList.extend(self.getEventTypes(m))
+ # Return True if every element in testList is in eventList
+ for element in testList:
+ if element not in eventList:
+ return 0
+ return 1
+
+
+ def isMultiEvent(self, macro):
+ """
+ Return True if the given macro actually causes
+ multiple events to be registered.
+ """
+ return len(self.getEventTypes(macro)) > 1
+
+
+#---------------------------------------------------------------------------
+
+class FakeWindow:
+ """
+ Used internally by the EventMacroInfo class. The FakeWindow is
+ the most important component of the macro-info utility: it
+ implements the Connect() protocol of wxWindow, but instead of
+ registering for events, it keeps track of what parameters were
+ passed to it.
+ """
+ def __init__(self):
+ self.eventTypes = []
+
+ def Connect(self, id1, id2, eventType, handlerFunction):
+ self.eventTypes.append(eventType)
+
+
+#---------------------------------------------------------------------------
+
+class EventAdapter:
+ """
+ A class that adapts incoming wxWindows events to
+ Publish/Subscribe messages.
+
+ In other words, this is the object that's seen by the
+ wxWindows system. Only one of these registers for any
+ particular wxWindows event. It then relays it into the
+ PS system, which lets many listeners respond.
+ """
+ def __init__(self, func, win, id):
+ """
+ Instantiate a new adapter. Pre-compute my Publish/Subscribe
+ topic, which is constant, and register with wxWindows.
+ """
+ self.topic = ".".join([str(func.typeId), str(win.GetId()), str(id)])
+ self.id = id
+ self.win = win
+ self.eventType = _macroInfo.getEventTypes(func)[0]
+
+ # Register myself with the wxWindows event system
+ try:
+ func(win, id, self.handleEvent)
+ self.callStyle = 3
+ except (TypeError, AssertionError):
+ func(win, self.handleEvent)
+ self.callStyle = 2
+
+
+ def disconnect(self):
+ if self.callStyle == 3:
+ return self.win.Disconnect(self.id, -1, self.eventType)
+ else:
+ return self.win.Disconnect(-1, -1, self.eventType)
+
+
+ def handleEvent(self, event):
+ """
+ In response to a wxWindows event, send a PS message
+ """
+ pub.sendMessage(self.topic, message=event)
+
+
+ def Destroy(self):
+ try:
+ if not self.disconnect():
+ print 'disconnect failed'
+ except wx.PyDeadObjectError:
+ print 'disconnect failed: dead object' ##????
+
+
+#---------------------------------------------------------------------------
+
+class MessageAdapter:
+ """
+ A class that adapts incoming Publish/Subscribe messages
+ to wxWindows event calls.
+
+ This class works opposite the EventAdapter, and
+ retrieves the information an EventAdapter has sent in a message.
+ Strictly speaking, this class is not required: Event listeners
+ could pull the original wxEvent object out of the PS Message
+ themselves.
+
+ However, by pairing an instance of this class with each wxEvent
+ handler, the handlers can use the standard API: they receive an
+ event as a parameter.
+ """
+ def __init__(self, eventHandler, topicPattern):
+ """
+ Instantiate a new MessageAdapter that send wxEvents to the
+ given eventHandler.
+ """
+ self.eventHandler = eventHandler
+ self.topicPattern = topicPattern
+ pub.subscribe(self.deliverEvent, topicPattern)
+
+ def deliverEvent(self, message):
+ # the message is the event object
+ self.eventHandler(message)
+
+ def Destroy(self):
+ pub.unsubscribe(self.deliverEvent, self.topicPattern)
+
+
+#---------------------------------------------------------------------------
+# Create globals
+
+_macroInfo = EventMacroInfo()
+
+# For now a singleton is not enforced. Should it be or can we trust
+# the programmers?
+eventManager = EventManager()
+
+
+#---------------------------------------------------------------------------
+# simple test code
+
+
+if __name__ == '__main__':
+ app = wx.App()
+ frame = wx.Frame(None, -1, 'Event Test', size=(300,300))
+ button = wx.ToggleButton(frame, -1, 'Listen for Mouse Events')
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(button, 0, 0 | wx.ALL, 10)
+ frame.SetAutoLayout(1)
+ frame.SetSizer(sizer)
+
+ #
+ # Demonstrate 1) register/deregister, 2) Multiple listeners receiving
+ # one event, and 3) Multiple events going to one listener.
+ #
+
+ def printEvent(event):
+ print 'Name:',event.GetClassName(),'Timestamp',event.GetTimestamp()
+
+ def enableFrameEvents(event):
+ # Turn the output of mouse events on and off
+ if event.IsChecked():
+ print '\nEnabling mouse events...'
+ eventManager.Register(printEvent, wx.EVT_MOTION, frame)
+ eventManager.Register(printEvent, wx.EVT_LEFT_DOWN, frame)
+ else:
+ print '\nDisabling mouse events...'
+ eventManager.DeregisterWindow(frame)
+
+ # Send togglebutton events to both the on/off code as well
+ # as the function that prints to stdout.
+ eventManager.Register(printEvent, wx.EVT_TOGGLEBUTTON, button)
+ eventManager.Register(enableFrameEvents, wx.EVT_TOGGLEBUTTON, button)
+
+ frame.CenterOnScreen()
+ frame.Show(1)
+ app.MainLoop()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/expando.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/expando.py
new file mode 100644
index 0000000..72fcab0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/expando.py
@@ -0,0 +1,225 @@
+#---------------------------------------------------------------------------
+# Name: expando.py
+# Purpose: A multi-line text control that expands and collapses as more
+# or less lines are needed to display its content.
+#
+# Author: Robin Dunn
+#
+# Created: 18-Sept-2006
+# RCS-ID: $Id$
+# Copyright: (c) 2006 by Total Control Software
+# Licence: wxWindows license
+#
+#---------------------------------------------------------------------------
+"""
+This module contains the `ExpandoTextCtrl` which is a multi-line
+text control that will expand its height on the fly to be able to show
+all the lines of the content of the control.
+"""
+
+import wx
+import wx.lib.newevent
+
+
+# This event class and binder object can be used to catch
+# notifications that the ExpandoTextCtrl has resized itself and
+# that layout adjustments may need to be made.
+wxEVT_ETC_LAYOUT_NEEDED = wx.NewEventType()
+EVT_ETC_LAYOUT_NEEDED = wx.PyEventBinder( wxEVT_ETC_LAYOUT_NEEDED, 1 )
+
+
+#---------------------------------------------------------------------------
+
+class ExpandoTextCtrl(wx.TextCtrl):
+ """
+ The ExpandoTextCtrl is a multi-line wx.TextCtrl that will
+ adjust its height on the fly as needed to accomodate the number of
+ lines needed to display the current content of the control. It is
+ assumed that the width of the control will be a fixed value and
+ that only the height will be adjusted automatically. If the
+ control is used in a sizer then the width should be set as part of
+ the initial or min size of the control.
+
+ When the control resizes itself it will attempt to also make
+ necessary adjustments in the sizer hierarchy it is a member of (if
+ any) but if that is not suffiecient then the programmer can catch
+ the EVT_ETC_LAYOUT_NEEDED event in the container and make any
+ other layout adjustments that may be needed.
+ """
+ _defaultHeight = -1
+ _leading = 1 # TODO: find a way to calculate this, it may vary by platform
+
+ def __init__(self, parent, id=-1, value="",
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, validator=wx.DefaultValidator, name="expando"):
+ # find the default height of a single line control
+ self.defaultHeight = self._getDefaultHeight(parent)
+ # make sure we default to that height if none was given
+ w, h = size
+ if h == -1:
+ h = self.defaultHeight
+ # always use the multi-line style
+ style = style | wx.TE_MULTILINE | wx.TE_NO_VSCROLL | wx.TE_RICH2
+ # init the base class
+ wx.TextCtrl.__init__(self, parent, id, value, pos, (w, h),
+ style, validator, name)
+ # save some basic metrics
+ self.extraHeight = self.defaultHeight - self.GetCharHeight()
+ self.numLines = 1
+ self.maxHeight = -1
+ if value:
+ wx.CallAfter(self._adjustCtrl)
+
+ self.Bind(wx.EVT_TEXT, self.OnTextChanged)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def SetMaxHeight(self, h):
+ """
+ Sets the max height that the control will expand to on its
+ own, and adjusts it down if needed.
+ """
+ self.maxHeight = h
+ if h != -1 and self.GetSize().height > h:
+ self.SetSize((-1, h))
+
+ def GetMaxHeight(self):
+ """Sets the max height that the control will expand to on its own"""
+ return self.maxHeight
+
+
+ def SetFont(self, font):
+ wx.TextCtrl.SetFont(self, font)
+ self.numLines = -1
+ self._adjustCtrl()
+
+ def WriteText(self, text):
+ # work around a bug of a lack of a EVT_TEXT when calling
+ # WriteText on wxMac
+ wx.TextCtrl.WriteText(self, text)
+ self._adjustCtrl()
+
+ def AppendText(self, text):
+ # Instead of using wx.TextCtrl.AppendText append and set the
+ # insertion point ourselves. This works around a bug on wxMSW
+ # where it scrolls the old text out of view, and since there
+ # is no scrollbar there is no way to get back to it.
+ self.SetValue(self.GetValue() + text)
+ self.SetInsertionPointEnd()
+
+
+ def OnTextChanged(self, evt):
+ # check if any adjustments are needed on every text update
+ self._adjustCtrl()
+ evt.Skip()
+
+
+ def OnSize(self, evt):
+ # The number of lines needed can change when the ctrl is resized too.
+ self._adjustCtrl()
+ evt.Skip()
+
+
+ def _adjustCtrl(self):
+ # if the current number of lines is different than before
+ # then recalculate the size needed and readjust
+ numLines = self.GetNumberOfLines()
+ if numLines != self.numLines:
+ self.numLines = numLines
+ charHeight = self.GetCharHeight()
+ height = numLines * (charHeight+self._leading) + self.extraHeight
+ if not (self.maxHeight != -1 and height > self.maxHeight):
+ # The size is changing... if the control is not in a
+ # sizer then we just want to change the size and
+ # that's it, the programmer will need to deal with
+ # potential layout issues. If it is being managed by
+ # a sizer then we'll change the min size setting and
+ # then try to do a layout. In either case we'll also
+ # send an event so the parent can handle any special
+ # layout issues that it wants to deal with.
+ if self.GetContainingSizer() is not None:
+ mw, mh = self.GetMinSize()
+ self.SetMinSize((mw, height))
+ if self.GetParent().GetSizer() is not None:
+ self.GetParent().Layout()
+ else:
+ self.GetContainingSizer().Layout()
+ else:
+ self.SetSize((-1, height))
+ # send notification that layout may be needed
+ evt = wx.PyCommandEvent(wxEVT_ETC_LAYOUT_NEEDED, self.GetId())
+ evt.SetEventObject(self)
+ evt.height = height
+ evt.numLines = numLines
+ self.GetEventHandler().ProcessEvent(evt)
+
+
+ def _getDefaultHeight(self, parent):
+ # checked for cached value
+ if self.__class__._defaultHeight != -1:
+ return self.__class__._defaultHeight
+ # otherwise make a single line textctrl and find out its default height
+ tc = wx.TextCtrl(parent)
+ sz = tc.GetSize()
+ tc.Destroy()
+ self.__class__._defaultHeight = sz.height
+ return sz.height
+
+
+ if 'wxGTK' in wx.PlatformInfo or 'wxOSX-cocoa' in wx.PlatformInfo:
+ # GetNumberOfLines in some ports doesn't count wrapped lines, so we
+ # need to implement our own.
+ def GetNumberOfLines(self):
+ text = self.GetValue()
+ width = self.GetClientSize().width
+ dc = wx.ClientDC(self)
+ dc.SetFont(self.GetFont())
+ count = 0
+ for line in text.split('\n'):
+ count += 1
+ w, h = dc.GetTextExtent(line)
+ if w > width - self._getExtra():
+ # the width of the text is wider than the control,
+ # calc how many lines it will be wrapped to
+ count += self._wrapLine(line, dc, width)
+
+ if not count:
+ count = 1
+ return count
+
+ def _getExtra(self):
+ if 'wxOSX-cocoa' in wx.PlatformInfo:
+ return wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X)
+ else:
+ return 0
+
+ def _wrapLine(self, line, dc, width):
+ # Estimate where the control will wrap the lines and
+ # return the count of extra lines needed.
+ pte = dc.GetPartialTextExtents(line)
+ width -= wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X)
+ if not pte or width < pte[0]:
+ return 1
+ idx = 0
+ start = 0
+ count = 0
+ spc = -1
+ while idx < len(pte):
+ if line[idx] == ' ':
+ spc = idx
+ if pte[idx] - start > width:
+ # we've reached the max width, add a new line
+ count += 1
+ # did we see a space? if so restart the count at that pos
+ if spc != -1:
+ idx = spc + 1
+ spc = -1
+ try:
+ start = pte[idx]
+ except IndexError:
+ start = pte[-1]
+ else:
+ idx += 1
+ return count
+
+#---------------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/fancytext.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/fancytext.py
new file mode 100644
index 0000000..3a86c3e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/fancytext.py
@@ -0,0 +1,462 @@
+# 12/02/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for 2.5 compatability.
+#
+
+"""
+FancyText -- methods for rendering XML specified text
+
+This module exports four main methods::
+
+ def GetExtent(str, dc=None, enclose=True)
+ def GetFullExtent(str, dc=None, enclose=True)
+ def RenderToBitmap(str, background=None, enclose=True)
+ def RenderToDC(str, dc, x, y, enclose=True)
+
+In all cases, 'str' is an XML string. Note that start and end tags are
+only required if *enclose* is set to False. In this case the text
+should be wrapped in FancyText tags.
+
+In addition, the module exports one class::
+
+ class StaticFancyText(self, window, id, text, background, ...)
+
+This class works similar to StaticText except it interprets its text
+as FancyText.
+
+The text can support superscripts and subscripts, text in different
+sizes, colors, styles, weights and families. It also supports a
+limited set of symbols, currently *times*, *infinity*, *angle* as well
+as greek letters in both upper case (*Alpha* *Beta*... *Omega*) and
+lower case (*alpha* *beta*... *omega*).
+
+>>> frame = wx.Frame(wx.NULL, -1, "FancyText demo", wx.DefaultPosition)
+>>> sft = StaticFancyText(frame, -1, testText, wx.Brush("light grey", wx.SOLID))
+>>> frame.SetClientSize(sft.GetSize())
+>>> didit = frame.Show()
+>>> from guitest import PauseTests; PauseTests()
+
+"""
+
+# Copyright 2001-2003 Timothy Hochberg
+# Use as you see fit. No warantees, I cannot be held responsible, etc.
+
+import copy
+import math
+import sys
+
+import wx
+import xml.parsers.expat
+
+__all__ = "GetExtent", "GetFullExtent", "RenderToBitmap", "RenderToDC", "StaticFancyText"
+
+if sys.platform == "win32":
+ _greekEncoding = str(wx.FONTENCODING_CP1253)
+else:
+ _greekEncoding = str(wx.FONTENCODING_ISO8859_7)
+
+_families = {"fixed" : wx.FIXED, "default" : wx.DEFAULT, "decorative" : wx.DECORATIVE, "roman" : wx.ROMAN,
+ "script" : wx.SCRIPT, "swiss" : wx.SWISS, "modern" : wx.MODERN}
+_styles = {"normal" : wx.NORMAL, "slant" : wx.SLANT, "italic" : wx.ITALIC}
+_weights = {"normal" : wx.NORMAL, "light" : wx.LIGHT, "bold" : wx.BOLD}
+
+# The next three classes: Renderer, SizeRenderer and DCRenderer are
+# what you will need to override to extend the XML language. All of
+# the font stuff as well as the subscript and superscript stuff are in
+# Renderer.
+
+_greek_letters = ("alpha", "beta", "gamma", "delta", "epsilon", "zeta",
+ "eta", "theta", "iota", "kappa", "lambda", "mu", "nu",
+ "xi", "omnikron", "pi", "rho", "altsigma", "sigma", "tau", "upsilon",
+ "phi", "chi", "psi", "omega")
+
+def iround(number):
+ return int(round(number))
+
+def iceil(number):
+ return int(math.ceil(number))
+
+class Renderer:
+ """Class for rendering XML marked up text.
+
+ See the module docstring for a description of the markup.
+
+ This class must be subclassed and the methods the methods that do
+ the drawing overridden for a particular output device.
+
+ """
+ defaultSize = None
+ defaultFamily = wx.DEFAULT
+ defaultStyle = wx.NORMAL
+ defaultWeight = wx.NORMAL
+ defaultEncoding = None
+ defaultColor = "black"
+
+ def __init__(self, dc=None, x=0, y=None):
+ if dc == None:
+ dc = wx.MemoryDC()
+ self.dc = dc
+ self.offsets = [0]
+ self.fonts = [{}]
+ self.width = self.height = 0
+ self.x = x
+ self.minY = self.maxY = self._y = y
+ if Renderer.defaultSize is None:
+ Renderer.defaultSize = wx.NORMAL_FONT.GetPointSize()
+ if Renderer.defaultEncoding is None:
+ Renderer.defaultEncoding = wx.Font_GetDefaultEncoding()
+
+ def getY(self):
+ if self._y is None:
+ self.minY = self.maxY = self._y = self.dc.GetTextExtent("M")[1]
+ return self._y
+ def setY(self, value):
+ self._y = y
+ y = property(getY, setY)
+
+ def startElement(self, name, attrs):
+ method = "start_" + name
+ if not hasattr(self, method):
+ raise ValueError("XML tag '%s' not supported" % name)
+ getattr(self, method)(attrs)
+
+ def endElement(self, name):
+ methname = "end_" + name
+ if hasattr(self, methname):
+ getattr(self, methname)()
+ elif hasattr(self, "start_" + name):
+ pass
+ else:
+ raise ValueError("XML tag '%s' not supported" % methname)
+
+ def characterData(self, data):
+ self.dc.SetFont(self.getCurrentFont())
+ for i, chunk in enumerate(data.split('\n')):
+ if i:
+ self.x = 0
+ self.y = self.mayY = self.maxY + self.dc.GetTextExtent("M")[1]
+ if chunk:
+ width, height, descent, extl = self.dc.GetFullTextExtent(chunk)
+ self.renderCharacterData(data, iround(self.x), iround(self.y + self.offsets[-1] - height + descent))
+ else:
+ width = height = descent = extl = 0
+ self.updateDims(width, height, descent, extl)
+
+ def updateDims(self, width, height, descent, externalLeading):
+ self.x += width
+ self.width = max(self.x, self.width)
+ self.minY = min(self.minY, self.y+self.offsets[-1]-height+descent)
+ self.maxY = max(self.maxY, self.y+self.offsets[-1]+descent)
+ self.height = self.maxY - self.minY
+
+ def start_FancyText(self, attrs):
+ pass
+ start_wxFancyText = start_FancyText # For backward compatibility
+
+ def start_font(self, attrs):
+ for key, value in attrs.items():
+ if key == "size":
+ value = int(value)
+ elif key == "family":
+ value = _families[value]
+ elif key == "style":
+ value = _styles[value]
+ elif key == "weight":
+ value = _weights[value]
+ elif key == "encoding":
+ value = int(value)
+ elif key == "color":
+ pass
+ else:
+ raise ValueError("unknown font attribute '%s'" % key)
+ attrs[key] = value
+ font = copy.copy(self.fonts[-1])
+ font.update(attrs)
+ self.fonts.append(font)
+
+ def end_font(self):
+ self.fonts.pop()
+
+ def start_sub(self, attrs):
+ if attrs.keys():
+ raise ValueError("<sub> does not take attributes")
+ font = self.getCurrentFont()
+ self.offsets.append(self.offsets[-1] + self.dc.GetFullTextExtent("M", font)[1]*0.5)
+ self.start_font({"size" : font.GetPointSize() * 0.8})
+
+ def end_sub(self):
+ self.fonts.pop()
+ self.offsets.pop()
+
+ def start_sup(self, attrs):
+ if attrs.keys():
+ raise ValueError("<sup> does not take attributes")
+ font = self.getCurrentFont()
+ self.offsets.append(self.offsets[-1] - self.dc.GetFullTextExtent("M", font)[1]*0.3)
+ self.start_font({"size" : font.GetPointSize() * 0.8})
+
+ def end_sup(self):
+ self.fonts.pop()
+ self.offsets.pop()
+
+ def getCurrentFont(self):
+ font = self.fonts[-1]
+ return wx.Font(font.get("size", self.defaultSize),
+ font.get("family", self.defaultFamily),
+ font.get("style", self.defaultStyle),
+ font.get("weight",self.defaultWeight),
+ False, "",
+ font.get("encoding", self.defaultEncoding))
+
+ def getCurrentColor(self):
+ font = self.fonts[-1]
+ return wx.TheColourDatabase.FindColour(font.get("color", self.defaultColor))
+
+ def getCurrentPen(self):
+ return wx.Pen(self.getCurrentColor(), 1, wx.SOLID)
+
+ def renderCharacterData(self, data, x, y):
+ raise NotImplementedError()
+
+
+def _addGreek():
+ alpha = 0xE1
+ Alpha = 0xC1
+ def end(self):
+ pass
+ for i, name in enumerate(_greek_letters):
+ def start(self, attrs, code=chr(alpha+i)):
+ self.start_font({"encoding" : _greekEncoding})
+ self.characterData(code)
+ self.end_font()
+ setattr(Renderer, "start_%s" % name, start)
+ setattr(Renderer, "end_%s" % name, end)
+ if name == "altsigma":
+ continue # There is no capital for altsigma
+ def start(self, attrs, code=chr(Alpha+i)):
+ self.start_font({"encoding" : _greekEncoding})
+ self.characterData(code)
+ self.end_font()
+ setattr(Renderer, "start_%s" % name.capitalize(), start)
+ setattr(Renderer, "end_%s" % name.capitalize(), end)
+_addGreek()
+
+
+
+class SizeRenderer(Renderer):
+ """Processes text as if rendering it, but just computes the size."""
+
+ def __init__(self, dc=None):
+ Renderer.__init__(self, dc, 0, 0)
+
+ def renderCharacterData(self, data, x, y):
+ pass
+
+ def start_angle(self, attrs):
+ self.characterData("M")
+
+ def start_infinity(self, attrs):
+ width, height = self.dc.GetTextExtent("M")
+ width = max(width, 10)
+ height = max(height, width / 2)
+ self.updateDims(width, height, 0, 0)
+
+ def start_times(self, attrs):
+ self.characterData("M")
+
+ def start_in(self, attrs):
+ self.characterData("M")
+
+ def start_times(self, attrs):
+ self.characterData("M")
+
+
+class DCRenderer(Renderer):
+ """Renders text to a wxPython device context DC."""
+
+ def renderCharacterData(self, data, x, y):
+ self.dc.SetTextForeground(self.getCurrentColor())
+ self.dc.DrawText(data, x, y)
+
+ def start_angle(self, attrs):
+ self.dc.SetFont(self.getCurrentFont())
+ self.dc.SetPen(self.getCurrentPen())
+ width, height, descent, leading = self.dc.GetFullTextExtent("M")
+ y = self.y + self.offsets[-1]
+ self.dc.DrawLine(iround(self.x), iround(y), iround( self.x+width), iround(y))
+ self.dc.DrawLine(iround(self.x), iround(y), iround(self.x+width), iround(y-width))
+ self.updateDims(width, height, descent, leading)
+
+
+ def start_infinity(self, attrs):
+ self.dc.SetFont(self.getCurrentFont())
+ self.dc.SetPen(self.getCurrentPen())
+ width, height, descent, leading = self.dc.GetFullTextExtent("M")
+ width = max(width, 10)
+ height = max(height, width / 2)
+ self.dc.SetPen(wx.Pen(self.getCurrentColor(), max(1, width/10)))
+ self.dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ y = self.y + self.offsets[-1]
+ r = iround( 0.95 * width / 4)
+ xc = (2*self.x + width) / 2
+ yc = iround(y-1.5*r)
+ self.dc.DrawCircle(xc - r, yc, r)
+ self.dc.DrawCircle(xc + r, yc, r)
+ self.updateDims(width, height, 0, 0)
+
+ def start_times(self, attrs):
+ self.dc.SetFont(self.getCurrentFont())
+ self.dc.SetPen(self.getCurrentPen())
+ width, height, descent, leading = self.dc.GetFullTextExtent("M")
+ y = self.y + self.offsets[-1]
+ width *= 0.8
+ width = iround(width+.5)
+ self.dc.SetPen(wx.Pen(self.getCurrentColor(), 1))
+ self.dc.DrawLine(iround(self.x), iround(y-width), iround(self.x+width-1), iround(y-1))
+ self.dc.DrawLine(iround(self.x), iround(y-2), iround(self.x+width-1), iround(y-width-1))
+ self.updateDims(width, height, 0, 0)
+
+
+def RenderToRenderer(str, renderer, enclose=True):
+ try:
+ if enclose:
+ str = '<?xml version="1.0"?><FancyText>%s</FancyText>' % str
+ p = xml.parsers.expat.ParserCreate()
+ p.returns_unicode = 0
+ p.StartElementHandler = renderer.startElement
+ p.EndElementHandler = renderer.endElement
+ p.CharacterDataHandler = renderer.characterData
+ p.Parse(str, 1)
+ except xml.parsers.expat.error, err:
+ raise ValueError('error parsing text text "%s": %s' % (str, err))
+
+
+# Public interface
+
+
+def GetExtent(str, dc=None, enclose=True):
+ "Return the extent of str"
+ renderer = SizeRenderer(dc)
+ RenderToRenderer(str, renderer, enclose)
+ return iceil(renderer.width), iceil(renderer.height) # XXX round up
+
+
+def GetFullExtent(str, dc=None, enclose=True):
+ renderer = SizeRenderer(dc)
+ RenderToRenderer(str, renderer, enclose)
+ return iceil(renderer.width), iceil(renderer.height), -iceil(renderer.minY) # XXX round up
+
+
+def RenderToBitmap(str, background=None, enclose=1):
+ "Return str rendered on a minumum size bitmap"
+ dc = wx.MemoryDC()
+ # Chicken and egg problem, we need a bitmap in the DC in order to
+ # measure how big the bitmap should be...
+ dc.SelectObject(wx.EmptyBitmap(1,1))
+ width, height, dy = GetFullExtent(str, dc, enclose)
+ bmp = wx.EmptyBitmap(width, height)
+ dc.SelectObject(bmp)
+ if background is None:
+ dc.SetBackground(wx.WHITE_BRUSH)
+ else:
+ dc.SetBackground(background)
+ dc.Clear()
+ renderer = DCRenderer(dc, y=dy)
+ dc.BeginDrawing()
+ RenderToRenderer(str, renderer, enclose)
+ dc.EndDrawing()
+ dc.SelectObject(wx.NullBitmap)
+ if background is None:
+ img = wx.ImageFromBitmap(bmp)
+ bg = dc.GetBackground().GetColour()
+ img.SetMaskColour(bg.Red(), bg.Green(), bg.Blue())
+ bmp = img.ConvertToBitmap()
+ return bmp
+
+
+def RenderToDC(str, dc, x, y, enclose=1):
+ "Render str onto a wxDC at (x,y)"
+ width, height, dy = GetFullExtent(str, dc)
+ renderer = DCRenderer(dc, x, y+dy)
+ RenderToRenderer(str, renderer, enclose)
+
+
+class StaticFancyText(wx.StaticBitmap):
+ def __init__(self, window, id, text, *args, **kargs):
+ args = list(args)
+ kargs.setdefault('name', 'staticFancyText')
+ if 'background' in kargs:
+ background = kargs.pop('background')
+ elif args:
+ background = args.pop(0)
+ else:
+ background = wx.Brush(window.GetBackgroundColour(), wx.SOLID)
+
+ bmp = RenderToBitmap(text, background)
+ wx.StaticBitmap.__init__(self, window, id, bmp, *args, **kargs)
+
+
+# Old names for backward compatibiliry
+getExtent = GetExtent
+renderToBitmap = RenderToBitmap
+renderToDC = RenderToDC
+
+
+# Test Driver
+
+def test():
+ testText = \
+"""<font weight="bold" size="16">FancyText</font> -- <font style="italic" size="16">methods for rendering XML specified text</font>
+<font family="swiss" size="12">
+This module exports four main methods::
+<font family="fixed" style="slant">
+ def GetExtent(str, dc=None, enclose=True)
+ def GetFullExtent(str, dc=None, enclose=True)
+ def RenderToBitmap(str, background=None, enclose=True)
+ def RenderToDC(str, dc, x, y, enclose=True)
+</font>
+In all cases, 'str' is an XML string. Note that start and end tags
+are only required if *enclose* is set to False. In this case the
+text should be wrapped in FancyText tags.
+
+In addition, the module exports one class::
+<font family="fixed" style="slant">
+ class StaticFancyText(self, window, id, text, background, ...)
+</font>
+This class works similar to StaticText except it interprets its text
+as FancyText.
+
+The text can support<sup>superscripts</sup> and <sub>subscripts</sub>, text
+in different <font size="20">sizes</font>, <font color="blue">colors</font>, <font style="italic">styles</font>, <font weight="bold">weights</font> and
+<font family="script">families</font>. It also supports a limited set of symbols,
+currently <times/>, <infinity/>, <angle/> as well as greek letters in both
+upper case (<Alpha/><Beta/>...<Omega/>) and lower case (<alpha/><beta/>...<omega/>).
+
+We can use doctest/guitest to display this string in all its marked up glory.
+<font family="fixed">
+>>> frame = wx.Frame(wx.NULL, -1, "FancyText demo", wx.DefaultPosition)
+>>> sft = StaticFancyText(frame, -1, __doc__, wx.Brush("light grey", wx.SOLID))
+>>> frame.SetClientSize(sft.GetSize())
+>>> didit = frame.Show()
+>>> from guitest import PauseTests; PauseTests()
+
+</font></font>
+The End"""
+
+ app = wx.App()
+ box = wx.BoxSizer(wx.VERTICAL)
+ frame = wx.Frame(None, -1, "FancyText demo", wx.DefaultPosition)
+ frame.SetBackgroundColour("light grey")
+ sft = StaticFancyText(frame, -1, testText)
+ box.Add(sft, 1, wx.EXPAND)
+ frame.SetSizer(box)
+ frame.SetAutoLayout(True)
+ box.Fit(frame)
+ box.SetSizeHints(frame)
+ frame.Show()
+ app.MainLoop()
+
+if __name__ == "__main__":
+ test()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/filebrowsebutton.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/filebrowsebutton.py
new file mode 100644
index 0000000..2e2023a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/filebrowsebutton.py
@@ -0,0 +1,460 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.filebrowsebutton
+# Purpose: Composite controls that provide a Browse button next to
+# either a wxTextCtrl or a wxComboBox. The Browse button
+# launches a wxFileDialog and loads the result into the
+# other control.
+#
+# Author: Mike Fletcher
+#
+# RCS-ID: $Id$
+# Copyright: (c) 2000 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/02/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 Compatability changes
+#
+
+import os
+import types
+
+import wx
+
+#----------------------------------------------------------------------
+
+class FileBrowseButton(wx.Panel):
+ """
+ A control to allow the user to type in a filename or browse with
+ the standard file dialog to select file
+ """
+ def __init__ (self, parent, id= -1,
+ pos = wx.DefaultPosition,
+ size = wx.DefaultSize,
+ style = wx.TAB_TRAVERSAL,
+ labelText= "File Entry:",
+ buttonText= "Browse",
+ toolTip= "Type filename or click browse to choose file",
+ # following are the values for a file dialog box
+ dialogTitle = "Choose a file",
+ startDirectory = ".",
+ initialValue = "",
+ fileMask = "*.*",
+ fileMode = wx.FD_OPEN,
+ # callback for when value changes (optional)
+ changeCallback= lambda x:x,
+ labelWidth = 0,
+ name = 'fileBrowseButton',
+ ):
+ """
+ :param labelText: Text for label to left of text field
+ :param buttonText: Text for button which launches the file dialog
+ :param toolTip: Help text
+ :param dialogTitle: Title used in file dialog
+ :param startDirectory: Default directory for file dialog startup
+ :param fileMask: File mask (glob pattern, such as *.*) to use in file dialog
+ :param fileMode: wx.FD_OPEN or wx.FD_SAVE, indicates type of file dialog to use
+ :param changeCallback: Optional callback called for all changes in value of the control
+ :param labelWidth: Width of the label
+ """
+
+ # store variables
+ self.labelText = labelText
+ self.buttonText = buttonText
+ self.toolTip = toolTip
+ self.dialogTitle = dialogTitle
+ self.startDirectory = startDirectory
+ self.initialValue = initialValue
+ self.fileMask = fileMask
+ self.fileMode = fileMode
+ self.changeCallback = changeCallback
+ self.callCallback = True
+ self.labelWidth = labelWidth
+
+ # create the dialog
+ self.createDialog(parent, id, pos, size, style, name )
+ # Setting a value causes the changeCallback to be called.
+ # In this case that would be before the return of the
+ # constructor. Not good. So a default value on
+ # SetValue is used to disable the callback
+ self.SetValue( initialValue, 0)
+
+
+ def createDialog( self, parent, id, pos, size, style, name ):
+ """Setup the graphic representation of the dialog"""
+ wx.Panel.__init__ (self, parent, id, pos, size, style, name)
+ self.SetMinSize(size) # play nice with sizers
+
+ box = wx.BoxSizer(wx.HORIZONTAL)
+
+ self.label = self.createLabel( )
+ box.Add( self.label, 0, wx.CENTER )
+
+ self.textControl = self.createTextControl()
+ box.Add( self.textControl, 1, wx.LEFT|wx.CENTER, 5)
+
+ self.browseButton = self.createBrowseButton()
+ box.Add( self.browseButton, 0, wx.LEFT|wx.CENTER, 5)
+
+ # add a border around the whole thing and resize the panel to fit
+ outsidebox = wx.BoxSizer(wx.VERTICAL)
+ outsidebox.Add(box, 1, wx.EXPAND|wx.ALL, 3)
+ outsidebox.Fit(self)
+
+ self.SetAutoLayout(True)
+ self.SetSizer( outsidebox )
+ self.Layout()
+ if type( size ) == types.TupleType:
+ size = apply( wx.Size, size)
+ self.SetDimensions(-1, -1, size.width, size.height, wx.SIZE_USE_EXISTING)
+
+# if size.width != -1 or size.height != -1:
+# self.SetSize(size)
+
+ def SetBackgroundColour(self,color):
+ wx.Panel.SetBackgroundColour(self,color)
+ self.label.SetBackgroundColour(color)
+
+ def createLabel( self ):
+ """Create the label/caption"""
+ label = wx.StaticText(self, -1, self.labelText, style =wx.ALIGN_RIGHT )
+ font = label.GetFont()
+ w, h, d, e = self.GetFullTextExtent(self.labelText, font)
+ if self.labelWidth > 0:
+ label.SetSize((self.labelWidth+5, h))
+ else:
+ label.SetSize((w+5, h))
+ return label
+
+ def createTextControl( self):
+ """Create the text control"""
+ textControl = wx.TextCtrl(self, -1)
+ textControl.SetToolTipString( self.toolTip )
+ if self.changeCallback:
+ textControl.Bind(wx.EVT_TEXT, self.OnChanged)
+ textControl.Bind(wx.EVT_COMBOBOX, self.OnChanged)
+ return textControl
+
+ def OnChanged(self, evt):
+ if self.callCallback and self.changeCallback:
+ self.changeCallback(evt)
+
+ def createBrowseButton( self):
+ """Create the browse-button control"""
+ button =wx.Button(self, -1, self.buttonText)
+ button.SetToolTipString( self.toolTip )
+ button.Bind(wx.EVT_BUTTON, self.OnBrowse)
+ return button
+
+
+ def OnBrowse (self, event = None):
+ """ Going to browse for file... """
+ current = self.GetValue()
+ directory = os.path.split(current)
+ if os.path.isdir( current):
+ directory = current
+ current = ''
+ elif directory and os.path.isdir( directory[0] ):
+ current = directory[1]
+ directory = directory [0]
+ else:
+ directory = self.startDirectory
+ current = ''
+ dlg = wx.FileDialog(self, self.dialogTitle, directory, current,
+ self.fileMask, self.fileMode)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ self.SetValue(dlg.GetPath())
+ dlg.Destroy()
+
+
+ def GetValue (self):
+ """
+ retrieve current value of text control
+ """
+ return self.textControl.GetValue()
+
+ def SetValue (self, value, callBack=1):
+ """set current value of text control"""
+ save = self.callCallback
+ self.callCallback = callBack
+ self.textControl.SetValue(value)
+ self.callCallback = save
+
+
+ def GetLabel( self ):
+ """ Retrieve the label's current text """
+ return self.label.GetLabel()
+
+ def SetLabel( self, value ):
+ """ Set the label's current text """
+ rvalue = self.label.SetLabel( value )
+ self.Refresh( True )
+ return rvalue
+
+
+
+
+class FileBrowseButtonWithHistory( FileBrowseButton ):
+ """
+ with following additions:
+ __init__(..., history=None)
+
+ history -- optional list of paths for initial history drop-down
+ (must be passed by name, not a positional argument)
+ If history is callable it will must return a list used
+ for the history drop-down
+
+ changeCallback -- as for FileBrowseButton, but with a work-around
+ for win32 systems which don't appear to create wx.EVT_COMBOBOX
+ events properly. There is a (slight) chance that this work-around
+ will cause some systems to create two events for each Combobox
+ selection. If you discover this condition, please report it!
+
+ As for a FileBrowseButton.__init__ otherwise.
+
+ GetHistoryControl()
+ Return reference to the control which implements interfaces
+ required for manipulating the history list. See GetHistoryControl
+ documentation for description of what that interface is.
+
+ GetHistory()
+ Return current history list
+
+ SetHistory( value=(), selectionIndex = None )
+ Set current history list, if selectionIndex is not None, select that index
+
+ """
+ def __init__( self, *arguments, **namedarguments):
+ self.history = namedarguments.get( "history" )
+ if self.history:
+ del namedarguments["history"]
+
+ self.historyCallBack=None
+ if callable(self.history):
+ self.historyCallBack=self.history
+ self.history=None
+ name = namedarguments.get('name', 'fileBrowseButtonWithHistory')
+ namedarguments['name'] = name
+ FileBrowseButton.__init__(self, *arguments, **namedarguments)
+
+
+ def createTextControl( self):
+ """Create the text control"""
+ textControl = wx.ComboBox(self, -1, style = wx.CB_DROPDOWN )
+ textControl.SetToolTipString( self.toolTip )
+ textControl.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ if self.changeCallback:
+ textControl.Bind(wx.EVT_TEXT, self.OnChanged)
+ textControl.Bind(wx.EVT_COMBOBOX, self.OnChanged)
+ if self.history:
+ history=self.history
+ self.history=None
+ self.SetHistory( history, control=textControl)
+ return textControl
+
+
+ def GetHistoryControl( self ):
+ """
+ Return a pointer to the control which provides (at least)
+ the following methods for manipulating the history list:
+
+ Append( item ) -- add item
+ Clear() -- clear all items
+ Delete( index ) -- 0-based index to delete from list
+ SetSelection( index ) -- 0-based index to select in list
+
+ Semantics of the methods follow those for the wxComboBox control
+ """
+ return self.textControl
+
+
+ def SetHistory( self, value=(), selectionIndex = None, control=None ):
+ """Set the current history list"""
+ if control is None:
+ control = self.GetHistoryControl()
+ if self.history == value:
+ return
+ self.history = value
+ # Clear history values not the selected one.
+ tempValue=control.GetValue()
+ # clear previous values
+ control.Clear()
+ control.SetValue(tempValue)
+ # walk through, appending new values
+ for path in value:
+ control.Append( path )
+ if selectionIndex is not None:
+ control.SetSelection( selectionIndex )
+
+
+ def GetHistory( self ):
+ """Return the current history list"""
+ if self.historyCallBack != None:
+ return self.historyCallBack()
+ elif self.history:
+ return list( self.history )
+ else:
+ return []
+
+
+ def OnSetFocus(self, event):
+ """When the history scroll is selected, update the history"""
+ if self.historyCallBack != None:
+ self.SetHistory( self.historyCallBack(), control=self.textControl)
+ event.Skip()
+
+
+ if wx.Platform == "__WXMSW__":
+ def SetValue (self, value, callBack=1):
+ """ Convenient setting of text control value, works
+ around limitation of wx.ComboBox """
+ save = self.callCallback
+ self.callCallback = callBack
+ self.textControl.SetValue(value)
+ self.callCallback = save
+
+ # Hack to call an event handler
+ class LocalEvent:
+ def __init__(self, string):
+ self._string=string
+ def GetString(self):
+ return self._string
+ if callBack==1:
+ # The callback wasn't being called when SetValue was used ??
+ # So added this explicit call to it
+ self.changeCallback(LocalEvent(value))
+
+
+class DirBrowseButton(FileBrowseButton):
+ def __init__(self, parent, id = -1,
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = wx.TAB_TRAVERSAL,
+ labelText = 'Select a directory:',
+ buttonText = 'Browse',
+ toolTip = 'Type directory name or browse to select',
+ dialogTitle = '',
+ startDirectory = '.',
+ changeCallback = None,
+ dialogClass = wx.DirDialog,
+ newDirectory = False,
+ name = 'dirBrowseButton'):
+ FileBrowseButton.__init__(self, parent, id, pos, size, style,
+ labelText, buttonText, toolTip,
+ dialogTitle, startDirectory,
+ changeCallback = changeCallback,
+ name = name)
+ self.dialogClass = dialogClass
+ self.newDirectory = newDirectory
+ #
+
+ def OnBrowse(self, ev = None):
+ style=0
+
+ if not self.newDirectory:
+ style |= wx.DD_DIR_MUST_EXIST
+
+ dialog = self.dialogClass(self,
+ message = self.dialogTitle,
+ defaultPath = self.startDirectory,
+ style = style)
+
+ if dialog.ShowModal() == wx.ID_OK:
+ self.SetValue(dialog.GetPath())
+ dialog.Destroy()
+ #
+
+
+#----------------------------------------------------------------------
+
+
+if __name__ == "__main__":
+ #from skeletonbuilder import rulesfile
+ class SimpleCallback:
+ def __init__( self, tag ):
+ self.tag = tag
+ def __call__( self, event ):
+ print self.tag, event.GetString()
+ class DemoFrame( wx.Frame ):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, -1, "File entry with browse", size=(500,260))
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ panel = wx.Panel (self,-1)
+ innerbox = wx.BoxSizer(wx.VERTICAL)
+ control = FileBrowseButton(
+ panel,
+ initialValue = "z:\\temp",
+ )
+ innerbox.Add( control, 0, wx.EXPAND )
+ middlecontrol = FileBrowseButtonWithHistory(
+ panel,
+ labelText = "With History",
+ initialValue = "d:\\temp",
+ history = ["c:\\temp", "c:\\tmp", "r:\\temp","z:\\temp"],
+ changeCallback= SimpleCallback( "With History" ),
+ )
+ innerbox.Add( middlecontrol, 0, wx.EXPAND )
+ middlecontrol = FileBrowseButtonWithHistory(
+ panel,
+ labelText = "History callback",
+ initialValue = "d:\\temp",
+ history = self.historyCallBack,
+ changeCallback= SimpleCallback( "History callback" ),
+ )
+ innerbox.Add( middlecontrol, 0, wx.EXPAND )
+ self.bottomcontrol = control = FileBrowseButton(
+ panel,
+ labelText = "With Callback",
+ style = wx.SUNKEN_BORDER|wx.CLIP_CHILDREN ,
+ changeCallback= SimpleCallback( "With Callback" ),
+ )
+ innerbox.Add( control, 0, wx.EXPAND)
+ self.bottommostcontrol = control = DirBrowseButton(
+ panel,
+ labelText = "Simple dir browse button",
+ style = wx.SUNKEN_BORDER|wx.CLIP_CHILDREN)
+ innerbox.Add( control, 0, wx.EXPAND)
+ ID = wx.NewId()
+ innerbox.Add( wx.Button( panel, ID,"Change Label", ), 1, wx.EXPAND)
+ self.Bind(wx.EVT_BUTTON, self.OnChangeLabel , id=ID)
+ ID = wx.NewId()
+ innerbox.Add( wx.Button( panel, ID,"Change Value", ), 1, wx.EXPAND)
+ self.Bind(wx.EVT_BUTTON, self.OnChangeValue, id=ID )
+ panel.SetAutoLayout(True)
+ panel.SetSizer( innerbox )
+ self.history={"c:\\temp":1, "c:\\tmp":1, "r:\\temp":1,"z:\\temp":1}
+
+ def historyCallBack(self):
+ keys=self.history.keys()
+ keys.sort()
+ return keys
+
+ def OnFileNameChangedHistory (self, event):
+ self.history[event.GetString ()]=1
+
+ def OnCloseMe(self, event):
+ self.Close(True)
+ def OnChangeLabel( self, event ):
+ self.bottomcontrol.SetLabel( "Label Updated" )
+ def OnChangeValue( self, event ):
+ self.bottomcontrol.SetValue( "r:\\somewhere\\over\\the\\rainbow.htm" )
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+ class DemoApp(wx.App):
+ def OnInit(self):
+ wx.InitAllImageHandlers()
+ frame = DemoFrame(None)
+ frame.Show(True)
+ self.SetTopWindow(frame)
+ return True
+
+ def test( ):
+ app = DemoApp(0)
+ app.MainLoop()
+ print 'Creating dialog'
+ test( )
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flashwin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flashwin.py
new file mode 100644
index 0000000..8d3009f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flashwin.py
@@ -0,0 +1,262 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.flashwin
+# Purpose: A class that allows the use of the Shockwave Flash
+# ActiveX control
+#
+# Author: Robin Dunn
+#
+# Created: 22-March-2004
+# RCS-ID: $Id$
+# Copyright: (c) 2008 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import wx
+import wx.lib.activex
+import comtypes.client as cc
+
+import sys
+if not hasattr(sys, 'frozen'):
+ cc.GetModule( ('{D27CDB6B-AE6D-11CF-96B8-444553540000}', 1, 0) )
+from comtypes.gen import ShockwaveFlashObjects
+
+
+clsID = '{D27CDB6E-AE6D-11CF-96B8-444553540000}'
+progID = 'ShockwaveFlash.ShockwaveFlash.1'
+
+
+
+class FlashWindow(wx.lib.activex.ActiveXCtrl):
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name='FlashWindow'):
+ wx.lib.activex.ActiveXCtrl.__init__(self, parent, progID,
+ id, pos, size, style, name)
+
+ def SetZoomRect(self, left, top, right, bottom):
+ return self.ctrl.SetZoomRect(left, top, right, bottom)
+
+ def Zoom(self, factor):
+ return self.ctrl.Zoom(factor)
+
+ def Pan(self, x, y, mode):
+ return self.ctrl.Pan(x, y, mode)
+
+ def Play(self):
+ return self.ctrl.Play()
+
+ def Stop(self):
+ return self.ctrl.Stop()
+
+ def Back(self):
+ return self.ctrl.Back()
+
+ def Forward(self):
+ return self.ctrl.Forward()
+
+ def Rewind(self):
+ return self.ctrl.Rewind()
+
+ def StopPlay(self):
+ return self.ctrl.StopPlay()
+
+ def GotoFrame(self, FrameNum):
+ return self.ctrl.GotoFrame(FrameNum)
+
+ def CurrentFrame(self):
+ return self.ctrl.CurrentFrame()
+
+ def IsPlaying(self):
+ return self.ctrl.IsPlaying()
+
+ def PercentLoaded(self):
+ return self.ctrl.PercentLoaded()
+
+ def FrameLoaded(self, FrameNum):
+ return self.ctrl.FrameLoaded(FrameNum)
+
+ def FlashVersion(self):
+ return self.ctrl.FlashVersion()
+
+ def LoadMovie(self, layer, url):
+ return self.ctrl.LoadMovie(layer, url)
+
+ def TGotoFrame(self, target, FrameNum):
+ return self.ctrl.TGotoFrame(target, FrameNum)
+
+ def TGotoLabel(self, target, label):
+ return self.ctrl.TGotoLabel(target, label)
+
+ def TCurrentFrame(self, target):
+ return self.ctrl.TCurrentFrame(target)
+
+ def TCurrentLabel(self, target):
+ return self.ctrl.TCurrentLabel(target)
+
+ def TPlay(self, target):
+ return self.ctrl.TPlay(target)
+
+ def TStopPlay(self, target):
+ return self.ctrl.TStopPlay(target)
+
+ def SetVariable(self, name, value):
+ return self.ctrl.SetVariable(name, value)
+
+ def GetVariable(self, name):
+ return self.ctrl.GetVariable(name)
+
+ def TSetProperty(self, target, property, value):
+ return self.ctrl.TSetProperty(target, property, value)
+
+ def TGetProperty(self, target, property):
+ return self.ctrl.TGetProperty(target, property)
+
+ def TCallFrame(self, target, FrameNum):
+ return self.ctrl.TCallFrame(target, FrameNum)
+
+ def TCallLabel(self, target, label):
+ return self.ctrl.TCallLabel(target, label)
+
+ def TSetPropertyNum(self, target, property, value):
+ return self.ctrl.TSetPropertyNum(target, property, value)
+
+ def TGetPropertyNum(self, target, property):
+ return self.ctrl.TGetPropertyNum(target, property)
+
+ def TGetPropertyAsNumber(self, target, property):
+ return self.ctrl.TGetPropertyAsNumber(target, property)
+
+ # Getters, Setters and properties
+ def _get_ReadyState(self):
+ return self.ctrl.ReadyState
+ readystate = property(_get_ReadyState, None)
+
+ def _get_TotalFrames(self):
+ return self.ctrl.TotalFrames
+ totalframes = property(_get_TotalFrames, None)
+
+ def _get_Playing(self):
+ return self.ctrl.Playing
+ def _set_Playing(self, Playing):
+ self.ctrl.Playing = Playing
+ playing = property(_get_Playing, _set_Playing)
+
+ def _get_Quality(self):
+ return self.ctrl.Quality
+ def _set_Quality(self, Quality):
+ self.ctrl.Quality = Quality
+ quality = property(_get_Quality, _set_Quality)
+
+ def _get_ScaleMode(self):
+ return self.ctrl.ScaleMode
+ def _set_ScaleMode(self, ScaleMode):
+ self.ctrl.ScaleMode = ScaleMode
+ scalemode = property(_get_ScaleMode, _set_ScaleMode)
+
+ def _get_AlignMode(self):
+ return self.ctrl.AlignMode
+ def _set_AlignMode(self, AlignMode):
+ self.ctrl.AlignMode = AlignMode
+ alignmode = property(_get_AlignMode, _set_AlignMode)
+
+ def _get_BackgroundColor(self):
+ return self.ctrl.BackgroundColor
+ def _set_BackgroundColor(self, BackgroundColor):
+ self.ctrl.BackgroundColor = BackgroundColor
+ backgroundcolor = property(_get_BackgroundColor, _set_BackgroundColor)
+
+ def _get_Loop(self):
+ return self.ctrl.Loop
+ def _set_Loop(self, Loop):
+ self.ctrl.Loop = Loop
+ loop = property(_get_Loop, _set_Loop)
+
+ def _get_Movie(self):
+ return self.ctrl.Movie
+ def _set_Movie(self, Movie):
+ self.ctrl.Movie = Movie
+ movie = property(_get_Movie, _set_Movie)
+
+ def _get_FrameNum(self):
+ return self.ctrl.FrameNum
+ def _set_FrameNum(self, FrameNum):
+ self.ctrl.FrameNum = FrameNum
+ framenum = property(_get_FrameNum, _set_FrameNum)
+
+ def _get_WMode(self):
+ return self.ctrl.WMode
+ def _set_WMode(self, WMode):
+ self.ctrl.WMode = WMode
+ wmode = property(_get_WMode, _set_WMode)
+
+ def _get_SAlign(self):
+ return self.ctrl.SAlign
+ def _set_SAlign(self, SAlign):
+ self.ctrl.SAlign = SAlign
+ salign = property(_get_SAlign, _set_SAlign)
+
+ def _get_Menu(self):
+ return self.ctrl.Menu
+ def _set_Menu(self, Menu):
+ self.ctrl.Menu = Menu
+ menu = property(_get_Menu, _set_Menu)
+
+ def _get_Base(self):
+ return self.ctrl.Base
+ def _set_Base(self, Base):
+ self.ctrl.Base = Base
+ base = property(_get_Base, _set_Base)
+
+ def _get_Scale(self):
+ return self.ctrl.Scale
+ def _set_Scale(self, Scale):
+ self.ctrl.Scale = Scale
+ scale = property(_get_Scale, _set_Scale)
+
+ def _get_DeviceFont(self):
+ return self.ctrl.DeviceFont
+ def _set_DeviceFont(self, DeviceFont):
+ self.ctrl.DeviceFont = DeviceFont
+ devicefont = property(_get_DeviceFont, _set_DeviceFont)
+
+ def _get_EmbedMovie(self):
+ return self.ctrl.EmbedMovie
+ def _set_EmbedMovie(self, EmbedMovie):
+ self.ctrl.EmbedMovie = EmbedMovie
+ embedmovie = property(_get_EmbedMovie, _set_EmbedMovie)
+
+ def _get_BGColor(self):
+ return self.ctrl.BGColor
+ def _set_BGColor(self, BGColor):
+ self.ctrl.BGColor = BGColor
+ bgcolor = property(_get_BGColor, _set_BGColor)
+
+ def _get_Quality2(self):
+ return self.ctrl.Quality2
+ def _set_Quality2(self, Quality2):
+ self.ctrl.Quality2 = Quality2
+ quality2 = property(_get_Quality2, _set_Quality2)
+
+ def _get_SWRemote(self):
+ return self.ctrl.SWRemote
+ def _set_SWRemote(self, SWRemote):
+ self.ctrl.SWRemote = SWRemote
+ swremote = property(_get_SWRemote, _set_SWRemote)
+
+ def _get_FlashVars(self):
+ return self.ctrl.FlashVars
+ def _set_FlashVars(self, FlashVars):
+ self.ctrl.FlashVars = FlashVars
+ flashvars = property(_get_FlashVars, _set_FlashVars)
+
+ def _get_AllowScriptAccess(self):
+ return self.ctrl.AllowScriptAccess
+ def _set_AllowScriptAccess(self, AllowScriptAccess):
+ self.ctrl.AllowScriptAccess = AllowScriptAccess
+ allowscriptaccess = property(_get_AllowScriptAccess, _set_AllowScriptAccess)
+
+ def _get_MovieData(self):
+ return self.ctrl.MovieData
+ def _set_MovieData(self, MovieData):
+ self.ctrl.MovieData = MovieData
+ moviedata = property(_get_MovieData, _set_MovieData)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flashwin_old.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flashwin_old.py
new file mode 100644
index 0000000..77fb293
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flashwin_old.py
@@ -0,0 +1,652 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.flashwin
+# Purpose: A class that allows the use of the Shockwave Flash
+# ActiveX control
+#
+# Author: Robin Dunn
+#
+# Created: 22-March-2004
+# RCS-ID: $Id: flashwin.py 26301 2004-03-23 05:29:50Z RD $
+# Copyright: (c) 2004 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# This module was generated by the wx.activex.GernerateAXModule class
+# (See also the genaxmodule script.)
+
+import wx
+import wx.activex
+
+clsID = '{D27CDB6E-AE6D-11CF-96B8-444553540000}'
+progID = 'ShockwaveFlash.ShockwaveFlash.1'
+
+
+
+# Create eventTypes and event binders
+wxEVT_ReadyStateChange = wx.activex.RegisterActiveXEvent('OnReadyStateChange')
+wxEVT_Progress = wx.activex.RegisterActiveXEvent('OnProgress')
+wxEVT_FSCommand = wx.activex.RegisterActiveXEvent('FSCommand')
+
+EVT_ReadyStateChange = wx.PyEventBinder(wxEVT_ReadyStateChange, 1)
+EVT_Progress = wx.PyEventBinder(wxEVT_Progress, 1)
+EVT_FSCommand = wx.PyEventBinder(wxEVT_FSCommand, 1)
+
+
+# Derive a new class from ActiveXWindow
+class FlashWindow(wx.activex.ActiveXWindow):
+ def __init__(self, parent, ID=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name='FlashWindow'):
+ wx.activex.ActiveXWindow.__init__(self, parent,
+ wx.activex.CLSID('{D27CDB6E-AE6D-11CF-96B8-444553540000}'),
+ ID, pos, size, style, name)
+
+ # Methods exported by the ActiveX object
+ def QueryInterface(self, riid):
+ return self.CallAXMethod('QueryInterface', riid)
+
+ def AddRef(self):
+ return self.CallAXMethod('AddRef')
+
+ def Release(self):
+ return self.CallAXMethod('Release')
+
+ def GetTypeInfoCount(self):
+ return self.CallAXMethod('GetTypeInfoCount')
+
+ def GetTypeInfo(self, itinfo, lcid):
+ return self.CallAXMethod('GetTypeInfo', itinfo, lcid)
+
+ def GetIDsOfNames(self, riid, rgszNames, cNames, lcid):
+ return self.CallAXMethod('GetIDsOfNames', riid, rgszNames, cNames, lcid)
+
+ def Invoke(self, dispidMember, riid, lcid, wFlags, pdispparams):
+ return self.CallAXMethod('Invoke', dispidMember, riid, lcid, wFlags, pdispparams)
+
+ def SetZoomRect(self, left, top, right, bottom):
+ return self.CallAXMethod('SetZoomRect', left, top, right, bottom)
+
+ def Zoom(self, factor):
+ return self.CallAXMethod('Zoom', factor)
+
+ def Pan(self, x, y, mode):
+ return self.CallAXMethod('Pan', x, y, mode)
+
+ def Play(self):
+ return self.CallAXMethod('Play')
+
+ def Stop(self):
+ return self.CallAXMethod('Stop')
+
+ def Back(self):
+ return self.CallAXMethod('Back')
+
+ def Forward(self):
+ return self.CallAXMethod('Forward')
+
+ def Rewind(self):
+ return self.CallAXMethod('Rewind')
+
+ def StopPlay(self):
+ return self.CallAXMethod('StopPlay')
+
+ def GotoFrame(self, FrameNum):
+ return self.CallAXMethod('GotoFrame', FrameNum)
+
+ def CurrentFrame(self):
+ return self.CallAXMethod('CurrentFrame')
+
+ def IsPlaying(self):
+ return self.CallAXMethod('IsPlaying')
+
+ def PercentLoaded(self):
+ return self.CallAXMethod('PercentLoaded')
+
+ def FrameLoaded(self, FrameNum):
+ return self.CallAXMethod('FrameLoaded', FrameNum)
+
+ def FlashVersion(self):
+ return self.CallAXMethod('FlashVersion')
+
+ def LoadMovie(self, layer, url):
+ return self.CallAXMethod('LoadMovie', layer, url)
+
+ def TGotoFrame(self, target, FrameNum):
+ return self.CallAXMethod('TGotoFrame', target, FrameNum)
+
+ def TGotoLabel(self, target, label):
+ return self.CallAXMethod('TGotoLabel', target, label)
+
+ def TCurrentFrame(self, target):
+ return self.CallAXMethod('TCurrentFrame', target)
+
+ def TCurrentLabel(self, target):
+ return self.CallAXMethod('TCurrentLabel', target)
+
+ def TPlay(self, target):
+ return self.CallAXMethod('TPlay', target)
+
+ def TStopPlay(self, target):
+ return self.CallAXMethod('TStopPlay', target)
+
+ def SetVariable(self, name, value):
+ return self.CallAXMethod('SetVariable', name, value)
+
+ def GetVariable(self, name):
+ return self.CallAXMethod('GetVariable', name)
+
+ def TSetProperty(self, target, property, value):
+ return self.CallAXMethod('TSetProperty', target, property, value)
+
+ def TGetProperty(self, target, property):
+ return self.CallAXMethod('TGetProperty', target, property)
+
+ def TCallFrame(self, target, FrameNum):
+ return self.CallAXMethod('TCallFrame', target, FrameNum)
+
+ def TCallLabel(self, target, label):
+ return self.CallAXMethod('TCallLabel', target, label)
+
+ def TSetPropertyNum(self, target, property, value):
+ return self.CallAXMethod('TSetPropertyNum', target, property, value)
+
+ def TGetPropertyNum(self, target, property):
+ return self.CallAXMethod('TGetPropertyNum', target, property)
+
+ def TGetPropertyAsNumber(self, target, property):
+ return self.CallAXMethod('TGetPropertyAsNumber', target, property)
+
+ # Getters, Setters and properties
+ def _get_ReadyState(self):
+ return self.GetAXProp('ReadyState')
+ readystate = property(_get_ReadyState, None)
+
+ def _get_TotalFrames(self):
+ return self.GetAXProp('TotalFrames')
+ totalframes = property(_get_TotalFrames, None)
+
+ def _get_Playing(self):
+ return self.GetAXProp('Playing')
+ def _set_Playing(self, Playing):
+ self.SetAXProp('Playing', Playing)
+ playing = property(_get_Playing, _set_Playing)
+
+ def _get_Quality(self):
+ return self.GetAXProp('Quality')
+ def _set_Quality(self, Quality):
+ self.SetAXProp('Quality', Quality)
+ quality = property(_get_Quality, _set_Quality)
+
+ def _get_ScaleMode(self):
+ return self.GetAXProp('ScaleMode')
+ def _set_ScaleMode(self, ScaleMode):
+ self.SetAXProp('ScaleMode', ScaleMode)
+ scalemode = property(_get_ScaleMode, _set_ScaleMode)
+
+ def _get_AlignMode(self):
+ return self.GetAXProp('AlignMode')
+ def _set_AlignMode(self, AlignMode):
+ self.SetAXProp('AlignMode', AlignMode)
+ alignmode = property(_get_AlignMode, _set_AlignMode)
+
+ def _get_BackgroundColor(self):
+ return self.GetAXProp('BackgroundColor')
+ def _set_BackgroundColor(self, BackgroundColor):
+ self.SetAXProp('BackgroundColor', BackgroundColor)
+ backgroundcolor = property(_get_BackgroundColor, _set_BackgroundColor)
+
+ def _get_Loop(self):
+ return self.GetAXProp('Loop')
+ def _set_Loop(self, Loop):
+ self.SetAXProp('Loop', Loop)
+ loop = property(_get_Loop, _set_Loop)
+
+ def _get_Movie(self):
+ return self.GetAXProp('Movie')
+ def _set_Movie(self, Movie):
+ self.SetAXProp('Movie', Movie)
+ movie = property(_get_Movie, _set_Movie)
+
+ def _get_FrameNum(self):
+ return self.GetAXProp('FrameNum')
+ def _set_FrameNum(self, FrameNum):
+ self.SetAXProp('FrameNum', FrameNum)
+ framenum = property(_get_FrameNum, _set_FrameNum)
+
+ def _get_WMode(self):
+ return self.GetAXProp('WMode')
+ def _set_WMode(self, WMode):
+ self.SetAXProp('WMode', WMode)
+ wmode = property(_get_WMode, _set_WMode)
+
+ def _get_SAlign(self):
+ return self.GetAXProp('SAlign')
+ def _set_SAlign(self, SAlign):
+ self.SetAXProp('SAlign', SAlign)
+ salign = property(_get_SAlign, _set_SAlign)
+
+ def _get_Menu(self):
+ return self.GetAXProp('Menu')
+ def _set_Menu(self, Menu):
+ self.SetAXProp('Menu', Menu)
+ menu = property(_get_Menu, _set_Menu)
+
+ def _get_Base(self):
+ return self.GetAXProp('Base')
+ def _set_Base(self, Base):
+ self.SetAXProp('Base', Base)
+ base = property(_get_Base, _set_Base)
+
+ def _get_Scale(self):
+ return self.GetAXProp('Scale')
+ def _set_Scale(self, Scale):
+ self.SetAXProp('Scale', Scale)
+ scale = property(_get_Scale, _set_Scale)
+
+ def _get_DeviceFont(self):
+ return self.GetAXProp('DeviceFont')
+ def _set_DeviceFont(self, DeviceFont):
+ self.SetAXProp('DeviceFont', DeviceFont)
+ devicefont = property(_get_DeviceFont, _set_DeviceFont)
+
+ def _get_EmbedMovie(self):
+ return self.GetAXProp('EmbedMovie')
+ def _set_EmbedMovie(self, EmbedMovie):
+ self.SetAXProp('EmbedMovie', EmbedMovie)
+ embedmovie = property(_get_EmbedMovie, _set_EmbedMovie)
+
+ def _get_BGColor(self):
+ return self.GetAXProp('BGColor')
+ def _set_BGColor(self, BGColor):
+ self.SetAXProp('BGColor', BGColor)
+ bgcolor = property(_get_BGColor, _set_BGColor)
+
+ def _get_Quality2(self):
+ return self.GetAXProp('Quality2')
+ def _set_Quality2(self, Quality2):
+ self.SetAXProp('Quality2', Quality2)
+ quality2 = property(_get_Quality2, _set_Quality2)
+
+ def _get_SWRemote(self):
+ return self.GetAXProp('SWRemote')
+ def _set_SWRemote(self, SWRemote):
+ self.SetAXProp('SWRemote', SWRemote)
+ swremote = property(_get_SWRemote, _set_SWRemote)
+
+ def _get_FlashVars(self):
+ return self.GetAXProp('FlashVars')
+ def _set_FlashVars(self, FlashVars):
+ self.SetAXProp('FlashVars', FlashVars)
+ flashvars = property(_get_FlashVars, _set_FlashVars)
+
+ def _get_AllowScriptAccess(self):
+ return self.GetAXProp('AllowScriptAccess')
+ def _set_AllowScriptAccess(self, AllowScriptAccess):
+ self.SetAXProp('AllowScriptAccess', AllowScriptAccess)
+ allowscriptaccess = property(_get_AllowScriptAccess, _set_AllowScriptAccess)
+
+ def _get_MovieData(self):
+ return self.GetAXProp('MovieData')
+ def _set_MovieData(self, MovieData):
+ self.SetAXProp('MovieData', MovieData)
+ moviedata = property(_get_MovieData, _set_MovieData)
+
+
+# PROPERTIES
+# --------------------
+# readystate
+# type:int arg:VT_EMPTY canGet:True canSet:False
+#
+# totalframes
+# type:int arg:VT_EMPTY canGet:True canSet:False
+#
+# playing
+# type:bool arg:bool canGet:True canSet:True
+#
+# quality
+# type:int arg:int canGet:True canSet:True
+#
+# scalemode
+# type:int arg:int canGet:True canSet:True
+#
+# alignmode
+# type:int arg:int canGet:True canSet:True
+#
+# backgroundcolor
+# type:int arg:int canGet:True canSet:True
+#
+# loop
+# type:bool arg:bool canGet:True canSet:True
+#
+# movie
+# type:string arg:string canGet:True canSet:True
+#
+# framenum
+# type:int arg:int canGet:True canSet:True
+#
+# wmode
+# type:string arg:string canGet:True canSet:True
+#
+# salign
+# type:string arg:string canGet:True canSet:True
+#
+# menu
+# type:bool arg:bool canGet:True canSet:True
+#
+# base
+# type:string arg:string canGet:True canSet:True
+#
+# scale
+# type:string arg:string canGet:True canSet:True
+#
+# devicefont
+# type:bool arg:bool canGet:True canSet:True
+#
+# embedmovie
+# type:bool arg:bool canGet:True canSet:True
+#
+# bgcolor
+# type:string arg:string canGet:True canSet:True
+#
+# quality2
+# type:string arg:string canGet:True canSet:True
+#
+# swremote
+# type:string arg:string canGet:True canSet:True
+#
+# flashvars
+# type:string arg:string canGet:True canSet:True
+#
+# allowscriptaccess
+# type:string arg:string canGet:True canSet:True
+#
+# moviedata
+# type:string arg:string canGet:True canSet:True
+#
+#
+#
+#
+# METHODS
+# --------------------
+# QueryInterface
+# retType: VT_VOID
+# params:
+# riid
+# in:True out:False optional:False type:unsupported type 29
+# ppvObj
+# in:False out:True optional:False type:unsupported type 26
+#
+# AddRef
+# retType: int
+#
+# Release
+# retType: int
+#
+# GetTypeInfoCount
+# retType: VT_VOID
+# params:
+# pctinfo
+# in:False out:True optional:False type:int
+#
+# GetTypeInfo
+# retType: VT_VOID
+# params:
+# itinfo
+# in:True out:False optional:False type:int
+# lcid
+# in:True out:False optional:False type:int
+# pptinfo
+# in:False out:True optional:False type:unsupported type 26
+#
+# GetIDsOfNames
+# retType: VT_VOID
+# params:
+# riid
+# in:True out:False optional:False type:unsupported type 29
+# rgszNames
+# in:True out:False optional:False type:unsupported type 26
+# cNames
+# in:True out:False optional:False type:int
+# lcid
+# in:True out:False optional:False type:int
+# rgdispid
+# in:False out:True optional:False type:int
+#
+# Invoke
+# retType: VT_VOID
+# params:
+# dispidMember
+# in:True out:False optional:False type:int
+# riid
+# in:True out:False optional:False type:unsupported type 29
+# lcid
+# in:True out:False optional:False type:int
+# wFlags
+# in:True out:False optional:False type:int
+# pdispparams
+# in:True out:False optional:False type:unsupported type 29
+# pvarResult
+# in:False out:True optional:False type:VT_VARIANT
+# pexcepinfo
+# in:False out:True optional:False type:unsupported type 29
+# puArgErr
+# in:False out:True optional:False type:int
+#
+# SetZoomRect
+# retType: VT_VOID
+# params:
+# left
+# in:True out:False optional:False type:int
+# top
+# in:True out:False optional:False type:int
+# right
+# in:True out:False optional:False type:int
+# bottom
+# in:True out:False optional:False type:int
+#
+# Zoom
+# retType: VT_VOID
+# params:
+# factor
+# in:True out:False optional:False type:int
+#
+# Pan
+# retType: VT_VOID
+# params:
+# x
+# in:True out:False optional:False type:int
+# y
+# in:True out:False optional:False type:int
+# mode
+# in:True out:False optional:False type:int
+#
+# Play
+# retType: VT_VOID
+#
+# Stop
+# retType: VT_VOID
+#
+# Back
+# retType: VT_VOID
+#
+# Forward
+# retType: VT_VOID
+#
+# Rewind
+# retType: VT_VOID
+#
+# StopPlay
+# retType: VT_VOID
+#
+# GotoFrame
+# retType: VT_VOID
+# params:
+# FrameNum
+# in:True out:False optional:False type:int
+#
+# CurrentFrame
+# retType: int
+#
+# IsPlaying
+# retType: bool
+#
+# PercentLoaded
+# retType: int
+#
+# FrameLoaded
+# retType: bool
+# params:
+# FrameNum
+# in:True out:False optional:False type:int
+#
+# FlashVersion
+# retType: int
+#
+# LoadMovie
+# retType: VT_VOID
+# params:
+# layer
+# in:True out:False optional:False type:int
+# url
+# in:True out:False optional:False type:string
+#
+# TGotoFrame
+# retType: VT_VOID
+# params:
+# target
+# in:True out:False optional:False type:string
+# FrameNum
+# in:True out:False optional:False type:int
+#
+# TGotoLabel
+# retType: VT_VOID
+# params:
+# target
+# in:True out:False optional:False type:string
+# label
+# in:True out:False optional:False type:string
+#
+# TCurrentFrame
+# retType: int
+# params:
+# target
+# in:True out:False optional:False type:string
+#
+# TCurrentLabel
+# retType: string
+# params:
+# target
+# in:True out:False optional:False type:string
+#
+# TPlay
+# retType: VT_VOID
+# params:
+# target
+# in:True out:False optional:False type:string
+#
+# TStopPlay
+# retType: VT_VOID
+# params:
+# target
+# in:True out:False optional:False type:string
+#
+# SetVariable
+# retType: VT_VOID
+# params:
+# name
+# in:True out:False optional:False type:string
+# value
+# in:True out:False optional:False type:string
+#
+# GetVariable
+# retType: string
+# params:
+# name
+# in:True out:False optional:False type:string
+#
+# TSetProperty
+# retType: VT_VOID
+# params:
+# target
+# in:True out:False optional:False type:string
+# property
+# in:True out:False optional:False type:int
+# value
+# in:True out:False optional:False type:string
+#
+# TGetProperty
+# retType: string
+# params:
+# target
+# in:True out:False optional:False type:string
+# property
+# in:True out:False optional:False type:int
+#
+# TCallFrame
+# retType: VT_VOID
+# params:
+# target
+# in:True out:False optional:False type:string
+# FrameNum
+# in:True out:False optional:False type:int
+#
+# TCallLabel
+# retType: VT_VOID
+# params:
+# target
+# in:True out:False optional:False type:string
+# label
+# in:True out:False optional:False type:string
+#
+# TSetPropertyNum
+# retType: VT_VOID
+# params:
+# target
+# in:True out:False optional:False type:string
+# property
+# in:True out:False optional:False type:int
+# value
+# in:True out:False optional:False type:double
+#
+# TGetPropertyNum
+# retType: double
+# params:
+# target
+# in:True out:False optional:False type:string
+# property
+# in:True out:False optional:False type:int
+#
+# TGetPropertyAsNumber
+# retType: double
+# params:
+# target
+# in:True out:False optional:False type:string
+# property
+# in:True out:False optional:False type:int
+#
+#
+#
+#
+# EVENTS
+# --------------------
+# ReadyStateChange
+# retType: VT_VOID
+# params:
+# newState
+# in:False out:False optional:False type:int
+#
+# Progress
+# retType: VT_VOID
+# params:
+# percentDone
+# in:False out:False optional:False type:int
+#
+# FSCommand
+# retType: VT_VOID
+# params:
+# command
+# in:True out:False optional:False type:string
+# args
+# in:True out:False optional:False type:string
+#
+#
+#
+#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flatnotebook.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flatnotebook.py
new file mode 100644
index 0000000..1afdd58
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/flatnotebook.py
@@ -0,0 +1,13 @@
+# ============================================================== #
+# This is now just a stub, importing the real module which lives #
+# under wx.lib.agw.
+# ============================================================== #
+
+"""
+Attention! FlatNotebook now lives in wx.lib.agw, together with
+its friends in the Advanced Generic Widgets family.
+
+Please update your code!
+"""
+
+from wx.lib.agw.flatnotebook import * \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatbar.py
new file mode 100644
index 0000000..2fef791
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatbar.py
@@ -0,0 +1,310 @@
+#----------------------------------------------------------------------------
+# Name: floatbar.py
+# Purpose: Contains floating toolbar class
+#
+# Author: Bryn Keller
+#
+# Created: 10/4/99
+#----------------------------------------------------------------------------
+# 12/02/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 Compatability changes
+#
+# 12/07/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Added deprecation warning.
+#
+# 12/18/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxFloatBar -> FloatBar
+#
+
+"""
+NOTE: This module is *not* supported in any way. Use it however you
+ wish, but be warned that dealing with any consequences is
+ entirly up to you.
+ --Robin
+"""
+
+import warnings
+import wx
+
+warningmsg = r"""\
+
+################################################\
+# This module is not supported in any way! |
+# |
+# See cource code for wx.lib.floatbar for more |
+# information. |
+################################################/
+
+"""
+
+warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
+
+if wx.Platform == '__WXGTK__':
+ #
+ # For wxGTK all we have to do is set the wxTB_DOCKABLE flag
+ #
+ class FloatBar(wx.ToolBar):
+ def __init__(self, parent, ID,
+ pos = wx.DefaultPosition,
+ size = wx.DefaultSize,
+ style = 0,
+ name = 'toolbar'):
+ wx.ToolBar.__init__(self, parent, ID, pos, size,
+ style|wx.TB_DOCKABLE, name)
+
+ # these other methods just become no-ops
+ def SetFloatable(self, float):
+ pass
+
+ def IsFloating(self):
+ return 1
+
+ def GetTitle(self):
+ return ""
+
+
+ def SetTitle(self, title):
+ pass
+
+else:
+ _DOCKTHRESHOLD = 25
+
+ class FloatBar(wx.ToolBar):
+ """
+ wxToolBar subclass which can be dragged off its frame and later
+ replaced there. Drag on the toolbar to release it, close it like
+ a normal window to make it return to its original
+ position. Programmatically, call SetFloatable(True) and then
+ Float(True) to float, Float(False) to dock.
+ """
+
+ def __init__(self,*_args,**_kwargs):
+ """
+ In addition to the usual arguments, wxFloatBar accepts keyword
+ args of: title(string): the title that should appear on the
+ toolbar's frame when it is floating. floatable(bool): whether
+ user actions (i.e., dragging) can float the toolbar or not.
+ """
+ args = (self,) + _args
+ apply(wx.ToolBar.__init__, args, _kwargs)
+ if _kwargs.has_key('floatable'):
+ self.floatable = _kwargs['floatable']
+ assert type(self.floatable) == type(0)
+ else:
+ self.floatable = 0
+ self.floating = 0
+ if _kwargs.has_key('title'):
+ self.title = _kwargs['title']
+ assert type(self.title) == type("")
+ else:
+ self.title = ""
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+ self.parentframe = args[1]
+
+
+ def IsFloatable(self):
+ return self.floatable
+
+
+ def SetFloatable(self, float):
+ self.floatable = float
+ #Find the size of a title bar.
+ if not hasattr(self, 'titleheight'):
+ test = wx.MiniFrame(None, -1, "TEST")
+ test.SetClientSize((0,0))
+ self.titleheight = test.GetSize()[1]
+ test.Destroy()
+
+
+ def IsFloating(self):
+ return self.floating
+
+
+ def Realize(self):
+ wx.ToolBar.Realize(self)
+
+
+ def GetTitle(self):
+ return self.title
+
+
+ def SetTitle(self, title):
+ print 'SetTitle', title
+ self.title = title
+ if self.IsFloating():
+ self.floatframe.SetTitle(self.title)
+
+
+ ## def GetHome(self):
+ ## """
+ ## Returns the frame which this toolbar will return to when
+ ## docked, or the parent if currently docked.
+ ## """
+ ## if hasattr(self, 'parentframe'):
+ ## return self.parentframe
+ ## else:
+ ## return (self.GetParent())
+
+
+ ## def SetHome(self, frame):
+ ## """
+ ## Called when docked, this will remove the toolbar from its
+ ## current frame and attach it to another. If called when
+ ## floating, it will dock to the frame specified when the toolbar
+ ## window is closed.
+ ## """
+ ## if self.IsFloating():
+ ## self.parentframe = frame
+ ## self.floatframe.Reparent(frame)
+ ## else:
+ ## parent = self.GetParent()
+ ## self.Reparent(frame)
+ ## parent.SetToolBar(None)
+ ## size = parent.GetSize()
+ ## parent.SetSize(wxSize(0,0))
+ ## parent.SetSize(size)
+ ## frame.SetToolBar(self)
+ ## size = frame.GetSize()
+ ## frame.SetSize(wxSize(0,0))
+ ## frame.SetSize(size)
+
+
+ def Float(self, bool):
+ "Floats or docks the toolbar programmatically."
+ if bool:
+ self.parentframe = self.GetParent()
+ print self.title
+ if self.title:
+ useStyle = wx.DEFAULT_FRAME_STYLE
+ else:
+ useStyle = wx.THICK_FRAME
+ self.floatframe = wx.MiniFrame(self.parentframe, -1, self.title,
+ style = useStyle)
+
+ self.Reparent(self.floatframe)
+ self.parentframe.SetToolBar(None)
+ self.floating = 1
+ psize = self.parentframe.GetSize()
+ self.parentframe.SetSize((0,0))
+ self.parentframe.SetSize(psize)
+ self.floatframe.SetToolBar(self)
+ self.oldcolor = self.GetBackgroundColour()
+
+ w = psize[0]
+ h = self.GetSize()[1]
+ if self.title:
+ h = h + self.titleheight
+ self.floatframe.SetSize((w,h))
+ self.floatframe.SetClientSize(self.GetSize())
+ newpos = self.parentframe.GetPosition()
+ newpos.y = newpos.y + _DOCKTHRESHOLD * 2
+ self.floatframe.SetPosition(newpos)
+ self.floatframe.Show(True)
+
+ self.floatframe.Bind(wx.EVT_CLOSE, self.OnDock)
+ #self.floatframe.Bind(wx.EVT_MOVE, self.OnMove)
+
+ else:
+ self.Reparent(self.parentframe)
+ self.parentframe.SetToolBar(self)
+ self.floating = 0
+ self.floatframe.SetToolBar(None)
+ self.floatframe.Destroy()
+ size = self.parentframe.GetSize()
+ self.parentframe.SetSize((0,0))
+ self.parentframe.SetSize(size)
+ self.SetBackgroundColour(self.oldcolor)
+
+
+ def OnDock(self, e):
+ self.Float(0)
+ if hasattr(self, 'oldpos'):
+ del self.oldpos
+
+
+ def OnMove(self, e):
+ homepos = self.parentframe.ClientToScreen((0,0))
+ floatpos = self.floatframe.GetPosition()
+ if (abs(homepos.x - floatpos.x) < _DOCKTHRESHOLD and
+ abs(homepos.y - floatpos.y) < _DOCKTHRESHOLD):
+ self.Float(0)
+ #homepos = self.parentframe.GetPositionTuple()
+ #homepos = homepos[0], homepos[1] + self.titleheight
+ #floatpos = self.floatframe.GetPositionTuple()
+ #if abs(homepos[0] - floatpos[0]) < 35 and abs(homepos[1] - floatpos[1]) < 35:
+ # self._SetFauxBarVisible(True)
+ #else:
+ # self._SetFauxBarVisible(False)
+
+
+ def OnMouse(self, e):
+ if not self.IsFloatable():
+ e.Skip()
+ return
+
+ if e.ButtonDClick(1) or e.ButtonDClick(2) or e.ButtonDClick(3) or e.ButtonDown() or e.ButtonUp():
+ e.Skip()
+
+ if e.ButtonDown():
+ self.CaptureMouse()
+ self.oldpos = (e.GetX(), e.GetY())
+
+ if e.Entering():
+ self.oldpos = (e.GetX(), e.GetY())
+
+ if e.ButtonUp():
+ self.ReleaseMouse()
+ if self.IsFloating():
+ homepos = self.parentframe.ClientToScreen((0,0))
+ floatpos = self.floatframe.GetPosition()
+ if (abs(homepos.x - floatpos.x) < _DOCKTHRESHOLD and
+ abs(homepos.y - floatpos.y) < _DOCKTHRESHOLD):
+ self.Float(0)
+ return
+
+ if e.Dragging():
+ if not self.IsFloating():
+ self.Float(True)
+ self.oldpos = (e.GetX(), e.GetY())
+ else:
+ if hasattr(self, 'oldpos'):
+ loc = self.floatframe.GetPosition()
+ pt = (loc.x - (self.oldpos[0]-e.GetX()), loc.y - (self.oldpos[1]-e.GetY()))
+ self.floatframe.Move(pt)
+
+
+
+ def _SetFauxBarVisible(self, vis):
+ return
+ if vis:
+ if self.parentframe.GetToolBar() == None:
+ if not hasattr(self, 'nullbar'):
+ self.nullbar = wx.ToolBar(self.parentframe, -1)
+ print "Adding fauxbar."
+ self.nullbar.Reparent(self.parentframe)
+ print "Reparented."
+ self.parentframe.SetToolBar(self.nullbar)
+ print "Set toolbar"
+ col = wx.NamedColour("GREY")
+ self.nullbar.SetBackgroundColour(col)
+ print "Set color"
+ size = self.parentframe.GetSize()
+ self.parentframe.SetSize((0,0))
+ self.parentframe.SetSize(size)
+ print "Set size"
+ else:
+ print self.parentframe.GetToolBar()
+ else:
+ if self.parentframe.GetToolBar() != None:
+ print "Removing fauxbar"
+ self.nullbar.Reparent(self.floatframe)
+ self.parentframe.SetToolBar(None)
+ size = self.parentframe.GetSize()
+ self.parentframe.SetSize((0,0))
+ self.parentframe.SetSize(size)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/FloatCanvas.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/FloatCanvas.py
new file mode 100644
index 0000000..f46e32e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/FloatCanvas.py
@@ -0,0 +1,3301 @@
+#!/usr/bin/env python2
+
+
+from __future__ import division
+
+import sys
+mac = sys.platform.startswith("darwin")
+
+try:
+ import numpy as N
+except ImportError:
+ raise ImportError("I could not import numpy")
+
+from time import clock
+import wx
+
+from Utilities import BBox
+import GUIMode
+
+
+## A global variable to hold the Pixels per inch that wxWindows thinks is in use
+## This is used for scaling fonts.
+## This can't be computed on module __init__, because a wx.App might not have initialized yet.
+global FontScale
+
+## Custom Exceptions:
+
+class FloatCanvasError(Exception):
+ pass
+
+## Create all the mouse events -- this is for binding to Objects
+EVT_FC_ENTER_WINDOW = wx.NewEventType()
+EVT_FC_LEAVE_WINDOW = wx.NewEventType()
+EVT_FC_LEFT_DOWN = wx.NewEventType()
+EVT_FC_LEFT_UP = wx.NewEventType()
+EVT_FC_LEFT_DCLICK = wx.NewEventType()
+EVT_FC_MIDDLE_DOWN = wx.NewEventType()
+EVT_FC_MIDDLE_UP = wx.NewEventType()
+EVT_FC_MIDDLE_DCLICK = wx.NewEventType()
+EVT_FC_RIGHT_DOWN = wx.NewEventType()
+EVT_FC_RIGHT_UP = wx.NewEventType()
+EVT_FC_RIGHT_DCLICK = wx.NewEventType()
+EVT_FC_MOTION = wx.NewEventType()
+EVT_FC_MOUSEWHEEL = wx.NewEventType()
+## these two are for the hit-test stuff, I never make them real Events
+## fixme: could I use the PyEventBinder for the Object events too?
+EVT_FC_ENTER_OBJECT = wx.NewEventType()
+EVT_FC_LEAVE_OBJECT = wx.NewEventType()
+
+##Create all mouse event binding objects -- for binding to the Canvas
+EVT_LEFT_DOWN = wx.PyEventBinder(EVT_FC_LEFT_DOWN)
+EVT_LEFT_UP = wx.PyEventBinder(EVT_FC_LEFT_UP)
+EVT_LEFT_DCLICK = wx.PyEventBinder(EVT_FC_LEFT_DCLICK)
+EVT_MIDDLE_DOWN = wx.PyEventBinder(EVT_FC_MIDDLE_DOWN)
+EVT_MIDDLE_UP = wx.PyEventBinder(EVT_FC_MIDDLE_UP)
+EVT_MIDDLE_DCLICK = wx.PyEventBinder(EVT_FC_MIDDLE_DCLICK)
+EVT_RIGHT_DOWN = wx.PyEventBinder(EVT_FC_RIGHT_DOWN)
+EVT_RIGHT_UP = wx.PyEventBinder(EVT_FC_RIGHT_UP)
+EVT_RIGHT_DCLICK = wx.PyEventBinder(EVT_FC_RIGHT_DCLICK)
+EVT_MOTION = wx.PyEventBinder(EVT_FC_MOTION)
+EVT_ENTER_WINDOW = wx.PyEventBinder(EVT_FC_ENTER_WINDOW)
+EVT_LEAVE_WINDOW = wx.PyEventBinder(EVT_FC_LEAVE_WINDOW)
+EVT_MOUSEWHEEL = wx.PyEventBinder(EVT_FC_MOUSEWHEEL)
+
+
+class _MouseEvent(wx.PyCommandEvent):
+
+ """
+ This event class takes a regular wxWindows mouse event as a parameter,
+ and wraps it so that there is access to all the original methods. This
+ is similar to subclassing, but you can't subclass a wxWindows event
+
+ The goal is to be able to it just like a regular mouse event.
+
+ It adds the method:
+
+ GetCoords() , which returns and (x,y) tuple in world coordinates.
+
+ Another difference is that it is a CommandEvent, which propagates up
+ the window hierarchy until it is handled.
+
+ """
+
+ def __init__(self, EventType, NativeEvent, WinID, Coords = None):
+ wx.PyCommandEvent.__init__(self)
+
+ self.SetEventType( EventType )
+ self._NativeEvent = NativeEvent
+ self.Coords = Coords
+
+ def GetCoords(self):
+ return self.Coords
+
+ def __getattr__(self, name):
+ return getattr(self._NativeEvent, name)
+
+## fixme: This should probably be re-factored into a class
+_testBitmap = None
+
+def _cycleidxs(indexcount, maxvalue, step):
+
+ """
+ Utility function used by _colorGenerator
+ """
+ def colormatch(color):
+ """Return True if the color comes back from the bitmap identically."""
+ if len(color) < 3:
+ return True
+ global _testBitmap
+ dc = wx.MemoryDC()
+ if not _testBitmap:
+ _testBitmap = wx.EmptyBitmap(1, 1)
+ dc.SelectObject(_testBitmap)
+ dc.SetBackground(wx.BLACK_BRUSH)
+ dc.Clear()
+ dc.SetPen(wx.Pen(wx.Colour(*color), 4))
+ dc.DrawPoint(0,0)
+ if mac: # NOTE: can the Mac not jsut use the DC?
+ del dc # Mac can't work with bitmap when selected into a DC.
+ pdata = wx.AlphaPixelData(_testBitmap)
+ pacc = pdata.GetPixels()
+ pacc.MoveTo(pdata, 0, 0)
+ outcolor = pacc.Get()[:3]
+ else:
+ outcolor = dc.GetPixel(0,0)
+ return outcolor == color
+
+ if indexcount == 0:
+ yield ()
+ else:
+ for idx in xrange(0, maxvalue, step):
+ for tail in _cycleidxs(indexcount - 1, maxvalue, step):
+ color = (idx, ) + tail
+ if not colormatch(color):
+ continue
+ yield color
+
+def _colorGenerator():
+
+ """
+ Generates a series of unique colors used to do hit-tests with the Hit
+ Test bitmap
+ """
+ return _cycleidxs(indexcount=3, maxvalue=256, step=1)
+
+class DrawObject(object):
+ """
+ This is the base class for all the objects that can be drawn.
+
+ One must subclass from this (and an assortment of mixins) to create
+ a new DrawObject.
+
+ note: This class contain a series of static dictionaries:
+
+ * BrushList
+ * PenList
+ * FillStyleList
+ * LineStyleList
+
+ Is this still necessary?
+
+ """
+
+ def __init__(self, InForeground = False, IsVisible = True):
+ """
+ :param InForeground=False: whether you want the object in the foreground
+ :param param IsVisible = True: whther the object is visible
+ """
+ self.InForeground = InForeground
+
+ self._Canvas = None
+ #self._Actual_Canvas = None
+
+ self.HitColor = None
+ self.CallBackFuncs = {}
+
+ ## these are the defaults
+ self.HitAble = False
+ self.HitLine = True
+ self.HitFill = True
+ self.MinHitLineWidth = 3
+ self.HitLineWidth = 3 ## this gets re-set by the subclasses if necessary
+
+ self.Brush = None
+ self.Pen = None
+
+ self.FillStyle = "Solid"
+
+ self.Visible = IsVisible
+
+ # I pre-define all these as class variables to provide an easier
+ # interface, and perhaps speed things up by caching all the Pens
+ # and Brushes, although that may not help, as I think wx now
+ # does that on it's own. Send me a note if you know!
+ ## I'm caching fonts, because on GTK, getting a new font can take a
+ ## while. However, it gets cleared after every full draw as hanging
+ ## on to a bunch of large fonts takes a massive amount of memory.
+
+ ## a dict to cache Font Objects while drawing -- for those that need fonts
+ FontList = {}
+
+
+ BrushList = {
+ ( None,"Transparent") : wx.TRANSPARENT_BRUSH,
+ ("Blue","Solid") : wx.BLUE_BRUSH,
+ ("Green","Solid") : wx.GREEN_BRUSH,
+ ("White","Solid") : wx.WHITE_BRUSH,
+ ("Black","Solid") : wx.BLACK_BRUSH,
+ ("Grey","Solid") : wx.GREY_BRUSH,
+ ("MediumGrey","Solid") : wx.MEDIUM_GREY_BRUSH,
+ ("LightGrey","Solid") : wx.LIGHT_GREY_BRUSH,
+ ("Cyan","Solid") : wx.CYAN_BRUSH,
+ ("Red","Solid") : wx.RED_BRUSH
+ }
+ PenList = {
+ (None,"Transparent",1) : wx.TRANSPARENT_PEN,
+ ("Green","Solid",1) : wx.GREEN_PEN,
+ ("White","Solid",1) : wx.WHITE_PEN,
+ ("Black","Solid",1) : wx.BLACK_PEN,
+ ("Grey","Solid",1) : wx.GREY_PEN,
+ ("MediumGrey","Solid",1) : wx.MEDIUM_GREY_PEN,
+ ("LightGrey","Solid",1) : wx.LIGHT_GREY_PEN,
+ ("Cyan","Solid",1) : wx.CYAN_PEN,
+ ("Red","Solid",1) : wx.RED_PEN
+ }
+
+ FillStyleList = {
+ "Transparent" : wx.TRANSPARENT,
+ "Solid" : wx.SOLID,
+ "BiDiagonalHatch": wx.BDIAGONAL_HATCH,
+ "CrossDiagHatch" : wx.CROSSDIAG_HATCH,
+ "FDiagonal_Hatch": wx.FDIAGONAL_HATCH,
+ "CrossHatch" : wx.CROSS_HATCH,
+ "HorizontalHatch": wx.HORIZONTAL_HATCH,
+ "VerticalHatch" : wx.VERTICAL_HATCH
+ }
+
+ LineStyleList = {
+ "Solid" : wx.SOLID,
+ "Transparent": wx.TRANSPARENT,
+ "Dot" : wx.DOT,
+ "LongDash" : wx.LONG_DASH,
+ "ShortDash" : wx.SHORT_DASH,
+ "DotDash" : wx.DOT_DASH,
+ }
+
+ # # made a property so sub-classes c
+ # @property
+ # def _Canvas(self):
+ # """
+ # getter for the _Canvas property
+ # """
+ # return self._Actual_Canvas
+ # @_Canvas.setter
+ # def _Canvas(self, canvas):
+ # """
+ # setter for Canvas property
+ # """
+ # self._Actual_Canvas = canvas
+
+ def Bind(self, Event, CallBackFun):
+ ##fixme: Way too much Canvas Manipulation here!
+ self.CallBackFuncs[Event] = CallBackFun
+ self.HitAble = True
+ self._Canvas.UseHitTest = True
+ if self.InForeground and self._Canvas._ForegroundHTBitmap is None:
+ self._Canvas.MakeNewForegroundHTBitmap()
+ elif self._Canvas._HTBitmap is None:
+ self._Canvas.MakeNewHTBitmap()
+ if not self.HitColor:
+ if not self._Canvas.HitColorGenerator:
+ self._Canvas.HitColorGenerator = _colorGenerator()
+ self._Canvas.HitColorGenerator.next() # first call to prevent the background color from being used.
+ self.HitColor = self._Canvas.HitColorGenerator.next()
+ self.SetHitPen(self.HitColor,self.HitLineWidth)
+ self.SetHitBrush(self.HitColor)
+ # put the object in the hit dict, indexed by it's color
+ if not self._Canvas.HitDict:
+ self._Canvas.MakeHitDict()
+ self._Canvas.HitDict[Event][self.HitColor] = (self) # put the object in the hit dict, indexed by its color
+
+ def UnBindAll(self):
+ ## fixme: this only removes one from each list, there could be more.
+ ## + patch by Tim Ansel
+ if self._Canvas.HitDict:
+ for Event in self._Canvas.HitDict.itervalues():
+ try:
+ del Event[self.HitColor]
+ except KeyError:
+ pass
+ self.HitAble = False
+
+
+ def SetBrush(self, FillColor, FillStyle):
+ if FillColor is None or FillStyle is None:
+ #self.Brush = wx.TRANSPARENT_BRUSH
+ ## wx.TRANSPARENT_BRUSH seems to have a bug in Phoenix...
+ self.Brush = wx.Brush(wx.Colour(0,0,0),wx.TRANSPARENT)
+ ##fixme: should I really re-set the style?
+ self.FillStyle = "Transparent"
+ else:
+ self.Brush = self.BrushList.setdefault( (FillColor,FillStyle), wx.Brush(FillColor,self.FillStyleList[FillStyle] ) )
+
+ def SetPen(self,LineColor,LineStyle,LineWidth):
+ if (LineColor is None) or (LineStyle is None):
+ self.Pen = wx.TRANSPARENT_PEN
+ self.LineStyle = 'Transparent'
+ else:
+ self.Pen = self.PenList.setdefault( (LineColor,LineStyle,LineWidth), wx.Pen(LineColor,LineWidth,self.LineStyleList[LineStyle]) )
+
+ def SetHitBrush(self,HitColor):
+ if not self.HitFill:
+ self.HitBrush = wx.TRANSPARENT_BRUSH
+ else:
+ self.HitBrush = self.BrushList.setdefault( (HitColor,"solid"), wx.Brush(HitColor,self.FillStyleList["Solid"] ) )
+
+ def SetHitPen(self,HitColor,LineWidth):
+ if not self.HitLine:
+ self.HitPen = wx.TRANSPARENT_PEN
+ else:
+ self.HitPen = self.PenList.setdefault( (HitColor, "solid", self.HitLineWidth), wx.Pen(HitColor, self.HitLineWidth, self.LineStyleList["Solid"]) )
+
+ ## Just to make sure that they will always be there
+ ## the appropriate ones should be overridden in the subclasses
+ def SetColor(self, Color):
+ pass
+ def SetLineColor(self, LineColor):
+ pass
+ def SetLineStyle(self, LineStyle):
+ pass
+ def SetLineWidth(self, LineWidth):
+ pass
+ def SetFillColor(self, FillColor):
+ pass
+ def SetFillStyle(self, FillStyle):
+ pass
+
+ def PutInBackground(self):
+ if self._Canvas and self.InForeground:
+ self._Canvas._ForeDrawList.remove(self)
+ self._Canvas._DrawList.append(self)
+ self._Canvas._BackgroundDirty = True
+ self.InForeground = False
+
+ def PutInForeground(self):
+ if self._Canvas and (not self.InForeground):
+ self._Canvas._ForeDrawList.append(self)
+ self._Canvas._DrawList.remove(self)
+ self._Canvas._BackgroundDirty = True
+ self.InForeground = True
+
+ def Hide(self):
+ """
+ Make an object hidden (not drawn)
+ """
+ self.Visible = False
+
+ def Show(self):
+ """
+ Make an object visible on the canvas.
+ """
+ self.Visible = True
+
+class Group(DrawObject):
+ """
+ A group of other FloatCanvas Objects
+
+ Not all DrawObject methods may apply here.
+
+ Note that if an object is in more than one group, it will get drawn more than once.
+
+ """
+
+ def __init__(self, ObjectList=[], InForeground = False, IsVisible = True):
+ self.ObjectList = []
+
+ DrawObject.__init__(self, InForeground, IsVisible)
+
+ # this one uses a proprty for _Canvas...
+ self._Actual_Canvas = None
+
+ for obj in ObjectList:
+ self.AddObject(obj, calcBB = False)
+ self.CalcBoundingBox()
+
+ ## re-define _Canvas property so that the sub-objects get set up right
+ @property
+ def _Canvas(self):
+ """
+ getter for the _Canvas property
+ """
+ return self._Actual_Canvas
+ @_Canvas.setter
+ def _Canvas(self, canvas):
+ """
+ setter for Canvas property
+ """
+ self._Actual_Canvas = canvas
+ for obj in self.ObjectList:
+ obj._Canvas = canvas
+
+ def AddObject(self, obj, calcBB=True):
+ self.ObjectList.append(obj)
+ obj._Canvas = self._Canvas
+ if calcBB:
+ self.BoundingBox.Merge(obj.BoundingBox)
+
+ def AddObjects(self, Objects):
+ for o in Objects:
+ self.AddObject(o)
+
+ def CalcBoundingBox(self):
+ if self.ObjectList:
+ BB = BBox.BBox(self.ObjectList[0].BoundingBox).copy()
+ for obj in self.ObjectList[1:]:
+ BB.Merge(obj.BoundingBox)
+ else:
+ BB = BBox.NullBBox()
+ self.BoundingBox = BB
+
+ def SetColor(self, Color):
+ for o in self.ObjectList:
+ o.SetColor(Color)
+ def SetLineColor(self, Color):
+ for o in self.ObjectList:
+ o.SetLineColor(Color)
+ def SetLineStyle(self, LineStyle):
+ for o in self.ObjectList:
+ o.SetLineStyle(LineStyle)
+ def SetLineWidth(self, LineWidth):
+ for o in self.ObjectList:
+ o.SetLineWidth(LineWidth)
+ def SetFillColor(self, Color):
+ for o in self.ObjectList:
+ o.SetFillColor(Color)
+ def SetFillStyle(self, FillStyle):
+ for o in self.ObjectList:
+ o.SetFillStyle(FillStyle)
+ def Move(self, Delta):
+ for obj in self.ObjectList:
+ obj.Move(Delta)
+ self.BoundingBox += Delta
+
+ def Bind(self, Event, CallBackFun):
+ ## slight variation on DrawObject Bind Method:
+ ## fixme: There is a lot of repeated code from the DrawObject method, but
+ ## it all needs a lot of cleaning up anyway.
+ self.CallBackFuncs[Event] = CallBackFun
+ self.HitAble = True
+ self._Canvas.UseHitTest = True
+ if self.InForeground and self._Canvas._ForegroundHTBitmap is None:
+ self._Canvas.MakeNewForegroundHTBitmap()
+ elif self._Canvas._HTBitmap is None:
+ self._Canvas.MakeNewHTBitmap()
+ if not self.HitColor:
+ if not self._Canvas.HitColorGenerator:
+ self._Canvas.HitColorGenerator = _colorGenerator()
+ self._Canvas.HitColorGenerator.next() # first call to prevent the background color from being used.
+ # Set all contained objects to the same Hit color:
+ self.HitColor = self._Canvas.HitColorGenerator.next()
+ # for obj in self.ObjectList:
+ # obj.SetHitPen(self.HitColor, self.HitLineWidth)
+ # obj.SetHitBrush(self.HitColor)
+ # obj.HitAble = True
+ # put the object in the hit dict, indexed by it's color
+ self._ChangeChildrenHitColor(self.ObjectList)
+ if not self._Canvas.HitDict:
+ self._Canvas.MakeHitDict()
+ self._Canvas.HitDict[Event][self.HitColor] = (self)
+
+ def _ChangeChildrenHitColor(self, objlist):
+ for obj in objlist:
+ obj.SetHitPen(self.HitColor, self.HitLineWidth)
+ obj.SetHitBrush(self.HitColor)
+ obj.HitAble = True
+
+ if isinstance(obj, Group):
+ self._ChangeChildrenHitColor(obj.ObjectList)
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel = None, HTdc=None):
+ for obj in self.ObjectList:
+ obj._Draw(dc, WorldToPixel, ScaleWorldToPixel, HTdc)
+
+
+class ColorOnlyMixin:
+ """
+
+ Mixin class for objects that have just one color, rather than a fill
+ color and line color
+
+ """
+
+ def SetColor(self, Color):
+ self.SetPen(Color,"Solid",1)
+ self.SetBrush(Color,"Solid")
+
+ SetFillColor = SetColor # Just to provide a consistant interface
+
+class LineOnlyMixin:
+ """
+
+ Mixin class for objects that have just a line, rather than a fill
+ color and line color
+
+ """
+
+ def SetLineColor(self, LineColor):
+ self.LineColor = LineColor
+ self.SetPen(LineColor,self.LineStyle,self.LineWidth)
+ SetColor = SetLineColor# so that it will do something reasonable
+
+ def SetLineStyle(self, LineStyle):
+ self.LineStyle = LineStyle
+ self.SetPen(self.LineColor,LineStyle,self.LineWidth)
+
+ def SetLineWidth(self, LineWidth):
+ self.LineWidth = LineWidth
+ self.SetPen(self.LineColor,self.LineStyle,LineWidth)
+
+class LineAndFillMixin(LineOnlyMixin):
+ """
+
+ Mixin class for objects that have both a line and a fill color and
+ style.
+
+ """
+ def SetFillColor(self, FillColor):
+ self.FillColor = FillColor
+ self.SetBrush(FillColor, self.FillStyle)
+
+ def SetFillStyle(self, FillStyle):
+ self.FillStyle = FillStyle
+ self.SetBrush(self.FillColor,FillStyle)
+
+ def SetUpDraw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc):
+ dc.SetPen(self.Pen)
+ dc.SetBrush(self.Brush)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ return ( WorldToPixel(self.XY),
+ ScaleWorldToPixel(self.WH) )
+
+class XYObjectMixin:
+ """
+ This is a mixin class that provides some methods suitable for use
+ with objects that have a single (x,y) coordinate pair.
+ """
+
+ def Move(self, Delta ):
+ """
+
+ Move(Delta): moves the object by delta, where delta is a
+ (dx,dy) pair. Ideally a Numpy array of shape (2,)
+
+ """
+
+ Delta = N.asarray(Delta, N.float)
+ self.XY += Delta
+ self.BoundingBox += Delta
+
+ if self._Canvas:
+ self._Canvas.BoundingBoxDirty = True
+
+ def CalcBoundingBox(self):
+ ## This may get overwritten in some subclasses
+ self.BoundingBox = BBox.asBBox((self.XY, self.XY))
+
+ def SetPoint(self, xy):
+ xy = N.array(xy, N.float)
+ xy.shape = (2,)
+
+ self.XY = xy
+ self.CalcBoundingBox()
+
+ if self._Canvas:
+ self._Canvas.BoundingBoxDirty = True
+
+class PointsObjectMixin:
+ """
+
+ This is a mixin class that provides some methods suitable for use
+ with objects that have a set of (x,y) coordinate pairs.
+
+ """
+
+ def Move(self, Delta):
+ """
+ Move(Delta): moves the object by delta, where delta is an (dx,
+ dy) pair. Ideally a Numpy array of shape (2,)
+ """
+
+ Delta = N.asarray(Delta, N.float)
+ Delta.shape = (2,)
+ self.Points += Delta
+ self.BoundingBox += Delta
+ if self._Canvas:
+ self._Canvas.BoundingBoxDirty = True
+
+ def CalcBoundingBox(self):
+ self.BoundingBox = BBox.fromPoints(self.Points)
+ if self._Canvas:
+ self._Canvas.BoundingBoxDirty = True
+
+ def SetPoints(self, Points, copy = True):
+ """
+ Sets the coordinates of the points of the object to Points (NX2 array).
+
+ By default, a copy is made, if copy is set to False, a reference
+ is used, iff Points is a NumPy array of Floats. This allows you
+ to change some or all of the points without making any copies.
+
+ For example:
+
+ Points = Object.Points
+ Points += (5,10) # shifts the points 5 in the x dir, and 10 in the y dir.
+ Object.SetPoints(Points, False) # Sets the points to the same array as it was
+
+ """
+ if copy:
+ self.Points = N.array(Points, N.float)
+ self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point
+ else:
+ self.Points = N.asarray(Points, N.float)
+ self.CalcBoundingBox()
+
+
+class Polygon(PointsObjectMixin, LineAndFillMixin, DrawObject):
+
+ """
+
+ The Polygon class takes a list of 2-tuples, or a NX2 NumPy array of
+ point coordinates. so that Points[N][0] is the x-coordinate of
+ point N and Points[N][1] is the y-coordinate or Points[N,0] is the
+ x-coordinate of point N and Points[N,1] is the y-coordinate for
+ arrays.
+
+ The other parameters specify various properties of the Polygon, and
+ should be self explanatory.
+
+ """
+ def __init__(self,
+ Points,
+ LineColor = "Black",
+ LineStyle = "Solid",
+ LineWidth = 1,
+ FillColor = None,
+ FillStyle = "Solid",
+ InForeground = False):
+ DrawObject.__init__(self, InForeground)
+ self.Points = N.array(Points ,N.float) # this DOES need to make a copy
+ self.CalcBoundingBox()
+
+ self.LineColor = LineColor
+ self.LineStyle = LineStyle
+ self.LineWidth = LineWidth
+ self.FillColor = FillColor
+ self.FillStyle = FillStyle
+
+ self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
+
+ self.SetPen(LineColor,LineStyle,LineWidth)
+ self.SetBrush(FillColor,FillStyle)
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel = None, HTdc=None):
+ Points = WorldToPixel(self.Points)#.tolist()
+ dc.SetPen(self.Pen)
+ dc.SetBrush(self.Brush)
+ dc.DrawPolygon(Points)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawPolygon(Points)
+
+class Line(PointsObjectMixin, LineOnlyMixin, DrawObject,):
+ """
+
+ The Line class takes a list of 2-tuples, or a NX2 NumPy Float array
+ of point coordinates.
+
+ It will draw a straight line if there are two points, and a polyline
+ if there are more than two.
+
+ """
+ def __init__(self,Points,
+ LineColor = "Black",
+ LineStyle = "Solid",
+ LineWidth = 1,
+ InForeground = False):
+ DrawObject.__init__(self, InForeground)
+
+
+ self.Points = N.array(Points,N.float)
+ self.CalcBoundingBox()
+
+ self.LineColor = LineColor
+ self.LineStyle = LineStyle
+ self.LineWidth = LineWidth
+
+ self.SetPen(LineColor,LineStyle,LineWidth)
+
+ self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
+
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ Points = WorldToPixel(self.Points)
+ dc.SetPen(self.Pen)
+ dc.DrawLines(Points)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.DrawLines(Points)
+
+class Spline(Line):
+ def __init__(self, *args, **kwargs):
+ Line.__init__(self, *args, **kwargs)
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ Points = WorldToPixel(self.Points)
+ dc.SetPen(self.Pen)
+ dc.DrawSpline(Points)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.DrawSpline(Points)
+
+
+class Arrow(XYObjectMixin, LineOnlyMixin, DrawObject):
+ """
+ Arrow class definition.
+
+ API definition::
+
+ Arrow(XY, # coords of origin of arrow (x,y)
+ Length, # length of arrow in pixels
+ theta, # angle of arrow in degrees: zero is straight up
+ # +angle is to the right
+ LineColor = "Black",
+ LineStyle = "Solid",
+ LineWidth = 1,
+ ArrowHeadSize = 4, # size of arrowhead in pixels
+ ArrowHeadAngle = 45, # angle of arrow head in degrees
+ InForeground = False):
+
+
+ It will draw an arrow , starting at the point, (X,Y) pointing in
+ direction, theta.
+
+ """
+ def __init__(self,
+ XY,
+ Length,
+ Direction,
+ LineColor = "Black",
+ LineStyle = "Solid",
+ LineWidth = 2, # pixels
+ ArrowHeadSize = 8, # pixels
+ ArrowHeadAngle = 30, # degrees
+ InForeground = False):
+
+ DrawObject.__init__(self, InForeground)
+
+ self.XY = N.array(XY, N.float)
+ self.XY.shape = (2,) # Make sure it is a length 2 vector
+ self.Length = Length
+ self.Direction = float(Direction)
+ self.ArrowHeadSize = ArrowHeadSize
+ self.ArrowHeadAngle = float(ArrowHeadAngle)
+
+ self.CalcArrowPoints()
+ self.CalcBoundingBox()
+
+ self.LineColor = LineColor
+ self.LineStyle = LineStyle
+ self.LineWidth = LineWidth
+
+ self.SetPen(LineColor,LineStyle,LineWidth)
+
+ ##fixme: How should the HitTest be drawn?
+ self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
+
+ def SetDirection(self, Direction):
+ self.Direction = float(Direction)
+ self.CalcArrowPoints()
+
+ def SetLength(self, Length):
+ self.Length = Length
+ self.CalcArrowPoints()
+
+ def SetLengthDirection(self, Length, Direction):
+ self.Direction = float(Direction)
+ self.Length = Length
+ self.CalcArrowPoints()
+
+## def CalcArrowPoints(self):
+## L = self.Length
+## S = self.ArrowHeadSize
+## phi = self.ArrowHeadAngle * N.pi / 360
+## theta = (self.Direction-90.0) * N.pi / 180
+## ArrowPoints = N.array( ( (0, L, L - S*N.cos(phi),L, L - S*N.cos(phi) ),
+## (0, 0, S*N.sin(phi), 0, -S*N.sin(phi) ) ),
+## N.float )
+## RotationMatrix = N.array( ( ( N.cos(theta), -N.sin(theta) ),
+## ( N.sin(theta), N.cos(theta) ) ),
+## N.float
+## )
+## ArrowPoints = N.matrixmultiply(RotationMatrix, ArrowPoints)
+## self.ArrowPoints = N.transpose(ArrowPoints)
+
+ def CalcArrowPoints(self):
+ L = self.Length
+ S = self.ArrowHeadSize
+ phi = self.ArrowHeadAngle * N.pi / 360
+ theta = (270 - self.Direction) * N.pi / 180
+ AP = N.array( ( (0,0),
+ (0,0),
+ (N.cos(theta - phi), -N.sin(theta - phi) ),
+ (0,0),
+ (N.cos(theta + phi), -N.sin(theta + phi) ),
+ ), N.float )
+ AP *= S
+ shift = (-L*N.cos(theta), L*N.sin(theta) )
+ AP[1:,:] += shift
+ self.ArrowPoints = AP
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ dc.SetPen(self.Pen)
+ xy = WorldToPixel(self.XY)
+ ArrowPoints = xy + self.ArrowPoints
+ dc.DrawLines(ArrowPoints)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.DrawLines(ArrowPoints)
+
+
+class ArrowLine(PointsObjectMixin, LineOnlyMixin, DrawObject):
+ """
+ ArrowLine class definition.
+
+ API definition::
+
+ ArrowLine(Points, # coords of points
+ LineColor = "Black",
+ LineStyle = "Solid",
+ LineWidth = 1,
+ ArrowHeadSize = 4, # in pixels
+ ArrowHeadAngle = 45,
+ InForeground = False):
+
+
+ It will draw a set of arrows from point to point.
+
+ It takes a list of 2-tuples, or a NX2 NumPy Float array
+ of point coordinates.
+
+
+ """
+
+ def __init__(self,
+ Points,
+ LineColor = "Black",
+ LineStyle = "Solid",
+ LineWidth = 1, # pixels
+ ArrowHeadSize = 8, # pixels
+ ArrowHeadAngle = 30, # degrees
+ InForeground = False):
+
+ DrawObject.__init__(self, InForeground)
+
+ self.Points = N.asarray(Points,N.float)
+ self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point
+ self.ArrowHeadSize = ArrowHeadSize
+ self.ArrowHeadAngle = float(ArrowHeadAngle)
+
+ self.CalcArrowPoints()
+ self.CalcBoundingBox()
+
+ self.LineColor = LineColor
+ self.LineStyle = LineStyle
+ self.LineWidth = LineWidth
+
+ self.SetPen(LineColor,LineStyle,LineWidth)
+
+ self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
+
+ def CalcArrowPoints(self):
+ S = self.ArrowHeadSize
+ phi = self.ArrowHeadAngle * N.pi / 360
+ Points = self.Points
+ n = Points.shape[0]
+ self.ArrowPoints = N.zeros((n-1, 3, 2), N.float)
+ for i in xrange(n-1):
+ dx, dy = self.Points[i] - self.Points[i+1]
+ theta = N.arctan2(dy, dx)
+ AP = N.array( (
+ (N.cos(theta - phi), -N.sin(theta-phi)),
+ (0,0),
+ (N.cos(theta + phi), -N.sin(theta + phi))
+ ),
+ N.float )
+ self.ArrowPoints[i,:,:] = AP
+ self.ArrowPoints *= S
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ Points = WorldToPixel(self.Points)
+ ArrowPoints = Points[1:,N.newaxis,:] + self.ArrowPoints
+ dc.SetPen(self.Pen)
+ dc.DrawLines(Points)
+ for arrow in ArrowPoints:
+ dc.DrawLines(arrow)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.DrawLines(Points)
+ for arrow in ArrowPoints:
+ HTdc.DrawLines(arrow)
+
+
+class PointSet(PointsObjectMixin, ColorOnlyMixin, DrawObject):
+ """
+
+ The PointSet class takes a list of 2-tuples, or a NX2 NumPy array of
+ point coordinates.
+
+ If Points is a sequence of tuples: Points[N][0] is the x-coordinate of
+ point N and Points[N][1] is the y-coordinate.
+
+ If Points is a NumPy array: Points[N,0] is the x-coordinate of point
+ N and Points[N,1] is the y-coordinate for arrays.
+
+ Each point will be drawn the same color and Diameter. The Diameter
+ is in screen pixels, not world coordinates.
+
+ The hit-test code does not distingish between the points, you will
+ only know that one of the points got hit, not which one. You can use
+ PointSet.FindClosestPoint(WorldPoint) to find out which one
+
+ In the case of points, the HitLineWidth is used as diameter.
+
+ """
+ def __init__(self, Points, Color = "Black", Diameter = 1, InForeground = False):
+ DrawObject.__init__(self,InForeground)
+
+ self.Points = N.array(Points,N.float)
+ self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point
+ self.CalcBoundingBox()
+ self.Diameter = Diameter
+
+ self.HitLineWidth = min(self.MinHitLineWidth, Diameter)
+ self.SetColor(Color)
+
+ def SetDiameter(self,Diameter):
+ self.Diameter = Diameter
+
+ def FindClosestPoint(self, XY):
+ """
+
+ Returns the index of the closest point to the point, XY, given
+ in World coordinates. It's essentially random which you get if
+ there are more than one that are the same.
+
+ This can be used to figure out which point got hit in a mouse
+ binding callback, for instance. It's a lot faster that using a
+ lot of separate points.
+
+ """
+ d = self.Points - XY
+ return N.argmin(N.hypot(d[:,0],d[:,1]))
+
+
+ def DrawD2(self, dc, Points):
+ # A Little optimization for a diameter2 - point
+ dc.DrawPointList(Points)
+ dc.DrawPointList(Points + (1,0))
+ dc.DrawPointList(Points + (0,1))
+ dc.DrawPointList(Points + (1,1))
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ dc.SetPen(self.Pen)
+ Points = WorldToPixel(self.Points)
+ if self.Diameter <= 1:
+ dc.DrawPointList(Points)
+ elif self.Diameter <= 2:
+ self.DrawD2(dc, Points)
+ else:
+ dc.SetBrush(self.Brush)
+ radius = int(round(self.Diameter/2))
+ ##fixme: I really should add a DrawCircleList to wxPython
+ if len(Points) > 100:
+ xy = Points
+ xywh = N.concatenate((xy-radius, N.ones(xy.shape) * self.Diameter ), 1 )
+ dc.DrawEllipseList(xywh)
+ else:
+ for xy in Points:
+ dc.DrawCircle(xy[0],xy[1], radius)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ if self.Diameter <= 1:
+ HTdc.DrawPointList(Points)
+ elif self.Diameter <= 2:
+ self.DrawD2(HTdc, Points)
+ else:
+ if len(Points) > 100:
+ xy = Points
+ xywh = N.concatenate((xy-radius, N.ones(xy.shape) * self.Diameter ), 1 )
+ HTdc.DrawEllipseList(xywh)
+ else:
+ for xy in Points:
+ HTdc.DrawCircle(xy[0],xy[1], radius)
+
+class Point(XYObjectMixin, ColorOnlyMixin, DrawObject):
+ """
+
+ The Point class takes a 2-tuple, or a (2,) NumPy array of point
+ coordinates.
+
+ The Diameter is in screen points, not world coordinates, So the
+ Bounding box is just the point, and doesn't include the Diameter.
+
+ The HitLineWidth is used as diameter for the
+ Hit Test.
+
+ """
+ def __init__(self, XY, Color = "Black", Diameter = 1, InForeground = False):
+ DrawObject.__init__(self, InForeground)
+
+ self.XY = N.array(XY, N.float)
+ self.XY.shape = (2,) # Make sure it is a length 2 vector
+ self.CalcBoundingBox()
+ self.SetColor(Color)
+ self.Diameter = Diameter
+
+ self.HitLineWidth = self.MinHitLineWidth
+
+ def SetDiameter(self,Diameter):
+ self.Diameter = Diameter
+
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ dc.SetPen(self.Pen)
+ xy = WorldToPixel(self.XY)
+ if self.Diameter <= 1:
+ dc.DrawPoint(xy[0], xy[1])
+ else:
+ dc.SetBrush(self.Brush)
+ radius = int(round(self.Diameter/2))
+ dc.DrawCircle(xy[0],xy[1], radius)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ if self.Diameter <= 1:
+ HTdc.DrawPoint(xy[0], xy[1])
+ else:
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawCircle(xy[0],xy[1], radius)
+
+class SquarePoint(XYObjectMixin, ColorOnlyMixin, DrawObject):
+ """
+
+ The SquarePoint class takes a 2-tuple, or a (2,) NumPy array of point
+ coordinates. It produces a square dot, centered on Point
+
+ The Size is in screen points, not world coordinates, so the
+ Bounding box is just the point, and doesn't include the Size.
+
+ The HitLineWidth is used as diameter for the
+ Hit Test.
+
+ """
+ def __init__(self, Point, Color = "Black", Size = 4, InForeground = False):
+ DrawObject.__init__(self, InForeground)
+
+ self.XY = N.array(Point, N.float)
+ self.XY.shape = (2,) # Make sure it is a length 2 vector
+ self.CalcBoundingBox()
+ self.SetColor(Color)
+ self.Size = Size
+
+ self.HitLineWidth = self.MinHitLineWidth
+
+ def SetSize(self,Size):
+ self.Size = Size
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ Size = self.Size
+ dc.SetPen(self.Pen)
+ xc,yc = WorldToPixel(self.XY)
+
+ if self.Size <= 1:
+ dc.DrawPoint(xc, yc)
+ else:
+ x = xc - Size/2.0
+ y = yc - Size/2.0
+ dc.SetBrush(self.Brush)
+ dc.DrawRectangle(x, y, Size, Size)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ if self.Size <= 1:
+ HTdc.DrawPoint(xc, xc)
+ else:
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectangle(x, y, Size, Size)
+
+class RectEllipse(XYObjectMixin, LineAndFillMixin, DrawObject):
+ def __init__(self, XY, WH,
+ LineColor = "Black",
+ LineStyle = "Solid",
+ LineWidth = 1,
+ FillColor = None,
+ FillStyle = "Solid",
+ InForeground = False):
+
+ DrawObject.__init__(self,InForeground)
+
+ self.SetShape(XY, WH)
+ self.LineColor = LineColor
+ self.LineStyle = LineStyle
+ self.LineWidth = LineWidth
+ self.FillColor = FillColor
+ self.FillStyle = FillStyle
+
+ self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
+
+ # these define the behaviour when zooming makes the objects really small.
+ self.MinSize = 1
+ self.DisappearWhenSmall = True
+
+ self.SetPen(LineColor,LineStyle,LineWidth)
+ self.SetBrush(FillColor,FillStyle)
+
+ def SetShape(self, XY, WH):
+ self.XY = N.array( XY, N.float)
+ self.XY.shape = (2,)
+ self.WH = N.array( WH, N.float)
+ self.WH.shape = (2,)
+ self.CalcBoundingBox()
+
+ def CalcBoundingBox(self):
+ # you need this in case Width or Height are negative
+ corners = N.array((self.XY, (self.XY + self.WH) ), N.float)
+ self.BoundingBox = BBox.fromPoints(corners)
+ if self._Canvas:
+ self._Canvas.BoundingBoxDirty = True
+
+
+class Rectangle(RectEllipse):
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ ( XY, WH ) = self.SetUpDraw(dc,
+ WorldToPixel,
+ ScaleWorldToPixel,
+ HTdc)
+ WH[N.abs(WH) < self.MinSize] = self.MinSize
+ if not( self.DisappearWhenSmall and N.abs(WH).min() <= self.MinSize) : # don't try to draw it too tiny
+ dc.DrawRectanglePointSize(XY, WH)
+ if HTdc and self.HitAble:
+ HTdc.DrawRectanglePointSize(XY, WH)
+
+
+class Ellipse(RectEllipse):
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ ( XY, WH ) = self.SetUpDraw(dc,
+ WorldToPixel,
+ ScaleWorldToPixel,
+ HTdc)
+ WH[N.abs(WH) < self.MinSize] = self.MinSize
+ if not( self.DisappearWhenSmall and N.abs(WH).min() <= self.MinSize) : # don't try to draw it too tiny
+ dc.DrawEllipsePointSize(XY, WH)
+ if HTdc and self.HitAble:
+ HTdc.DrawEllipsePointSize(XY, WH)
+
+class Circle(XYObjectMixin, LineAndFillMixin, DrawObject):
+ def __init__(self, XY, Diameter,
+ LineColor = "Black",
+ LineStyle = "Solid",
+ LineWidth = 1,
+ FillColor = None,
+ FillStyle = "Solid",
+ InForeground = False):
+ DrawObject.__init__(self, InForeground)
+
+ self.XY = N.array(XY, N.float)
+ self.WH = N.array((Diameter/2, Diameter/2), N.float) # just to keep it compatible with others
+ self.CalcBoundingBox()
+
+ self.LineColor = LineColor
+ self.LineStyle = LineStyle
+ self.LineWidth = LineWidth
+ self.FillColor = FillColor
+ self.FillStyle = FillStyle
+
+ self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
+
+ # these define the behaviour when zooming makes the objects really small.
+ self.MinSize = 1
+ self.DisappearWhenSmall = True
+
+ self.SetPen(LineColor,LineStyle,LineWidth)
+ self.SetBrush(FillColor,FillStyle)
+
+ def SetDiameter(self, Diameter):
+ self.WH = N.array((Diameter/2, Diameter/2), N.float) # just to keep it compatible with others
+
+ def CalcBoundingBox(self):
+ # you need this in case Width or Height are negative
+ self.BoundingBox = BBox.fromPoints( (self.XY+self.WH, self.XY-self.WH) )
+ if self._Canvas:
+ self._Canvas.BoundingBoxDirty = True
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ ( XY, WH ) = self.SetUpDraw(dc,
+ WorldToPixel,
+ ScaleWorldToPixel,
+ HTdc)
+
+ WH[N.abs(WH) < self.MinSize] = self.MinSize
+ if not( self.DisappearWhenSmall and N.abs(WH).min() <= self.MinSize) : # don't try to draw it too tiny
+ dc.DrawCirclePoint(XY, WH[0])
+ if HTdc and self.HitAble:
+ HTdc.DrawCirclePoint(XY, WH[0])
+
+
+class TextObjectMixin(XYObjectMixin):
+ """
+
+ A mix in class that holds attributes and methods that are needed by
+ the Text objects
+
+ """
+
+ LayoutFontSize = 16 # font size used for calculating layout
+
+ def SetFont(self, Size, Family, Style, Weight, Underlined, FaceName):
+ self.Font = self.FontList.setdefault( (Size,
+ Family,
+ Style,
+ Weight,
+ Underlined,
+ FaceName),
+ #wx.FontFromPixelSize((0.45*Size,Size), # this seemed to give a decent height/width ratio on Windows
+ wx.Font(Size,
+ Family,
+ Style,
+ Weight,
+ Underlined,
+ FaceName) )
+
+ def SetColor(self, Color):
+ self.Color = Color
+
+ def SetBackgroundColor(self, BackgroundColor):
+ self.BackgroundColor = BackgroundColor
+
+ def SetText(self, String):
+ """
+ Re-sets the text displayed by the object
+
+ In the case of the ScaledTextBox, it will re-do the layout as appropriate
+
+ Note: only tested with the ScaledTextBox
+
+ """
+
+ self.String = String
+ self.LayoutText()
+
+ def LayoutText(self):
+ """
+ A dummy method to re-do the layout of the text.
+
+ A derived object needs to override this if required.
+
+ """
+ pass
+
+ ## store the function that shift the coords for drawing text. The
+ ## "c" parameter is the correction for world coordinates, rather
+ ## than pixel coords as the y axis is reversed
+ ## pad is the extra space around the text
+ ## if world = 1, the vertical shift is done in y-up coordinates
+ ShiftFunDict = {'tl': lambda x, y, w, h, world=0, pad=0: (x + pad, y + pad - 2*world*pad),
+ 'tc': lambda x, y, w, h, world=0, pad=0: (x - w/2, y + pad - 2*world*pad),
+ 'tr': lambda x, y, w, h, world=0, pad=0: (x - w - pad, y + pad - 2*world*pad),
+ 'cl': lambda x, y, w, h, world=0, pad=0: (x + pad, y - h/2 + world*h),
+ 'cc': lambda x, y, w, h, world=0, pad=0: (x - w/2, y - h/2 + world*h),
+ 'cr': lambda x, y, w, h, world=0, pad=0: (x - w - pad, y - h/2 + world*h),
+ 'bl': lambda x, y, w, h, world=0, pad=0: (x + pad, y - h + 2*world*h - pad + world*2*pad) ,
+ 'bc': lambda x, y, w, h, world=0, pad=0: (x - w/2, y - h + 2*world*h - pad + world*2*pad) ,
+ 'br': lambda x, y, w, h, world=0, pad=0: (x - w - pad, y - h + 2*world*h - pad + world*2*pad)}
+
+class Text(TextObjectMixin, DrawObject, ):
+ """
+ This class creates a text object, placed at the coordinates,
+ x,y. the "Position" argument is a two charactor string, indicating
+ where in relation to the coordinates the string should be oriented.
+
+ The first letter is: t, c, or b, for top, center and bottom The
+ second letter is: l, c, or r, for left, center and right The
+ position refers to the position relative to the text itself. It
+ defaults to "tl" (top left).
+
+ Size is the size of the font in pixels, or in points for printing
+ (if it ever gets implimented). Those will be the same, If you assume
+ 72 PPI.
+
+ * Family: Font family, a generic way of referring to fonts without
+ specifying actual facename. One of:
+
+ * wx.DEFAULT: Chooses a default font.
+ * wx.DECORATI: A decorative font.
+ * wx.ROMAN: A formal, serif font.
+ * wx.SCRIPT: A handwriting font.
+ * wx.SWISS: A sans-serif font.
+ * wx.MODERN: A fixed pitch font.
+
+ .. note:: these are only as good as the wxWindows defaults, which aren't so good.
+
+ * Style: One of wx.NORMAL, wx.SLANT and wx.ITALIC.
+ * Weight: One of wx.NORMAL, wx.LIGHT and wx.BOLD.
+ * Underlined: The value can be True or False. At present this may have an an
+ effect on Windows only.
+
+
+ Alternatively, you can set the kw arg: Font, to a wx.Font, and the
+ above will be ignored.
+
+ The size is fixed, and does not scale with the drawing.
+
+ The hit-test is done on the entire text extent
+
+ """
+
+ def __init__(self,String, xy,
+ Size = 14,
+ Color = "Black",
+ BackgroundColor = None,
+ Family = wx.MODERN,
+ Style = wx.NORMAL,
+ Weight = wx.NORMAL,
+ Underlined = False,
+ Position = 'tl',
+ InForeground = False,
+ Font = None):
+
+ DrawObject.__init__(self,InForeground)
+
+ self.String = String
+ # Input size in in Pixels, compute points size from FontScaleinfo.
+ # fixme: for printing, we'll have to do something a little different
+ self.Size = Size * FontScale
+
+ self.Color = Color
+ self.BackgroundColor = BackgroundColor
+
+ if not Font:
+ FaceName = ''
+ else:
+ FaceName = Font.GetFaceName()
+ Family = Font.GetFamily()
+ Size = Font.GetPointSize()
+ Style = Font.GetStyle()
+ Underlined = Font.GetUnderlined()
+ Weight = Font.GetWeight()
+ self.SetFont(Size, Family, Style, Weight, Underlined, FaceName)
+
+ self.BoundingBox = BBox.asBBox((xy, xy))
+
+ self.XY = N.asarray(xy)
+ self.XY.shape = (2,)
+
+ (self.TextWidth, self.TextHeight) = (None, None)
+ self.ShiftFun = self.ShiftFunDict[Position]
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ XY = WorldToPixel(self.XY)
+ dc.SetFont(self.Font)
+ dc.SetTextForeground(self.Color)
+ if self.BackgroundColor:
+ dc.SetBackgroundMode(wx.SOLID)
+ dc.SetTextBackground(self.BackgroundColor)
+ else:
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ if self.TextWidth is None or self.TextHeight is None:
+ (self.TextWidth, self.TextHeight) = dc.GetTextExtent(self.String)
+ XY = self.ShiftFun(XY[0], XY[1], self.TextWidth, self.TextHeight)
+ dc.DrawTextPoint(self.String, XY)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(XY, (self.TextWidth, self.TextHeight) )
+
+class ScaledText(TextObjectMixin, DrawObject, ):
+ ##fixme: this can be depricated and jsut use ScaledTextBox with different defaults.
+
+ """
+ This class creates a text object that is scaled when zoomed. It is
+ placed at the coordinates, x,y. the "Position" argument is a two
+ charactor string, indicating where in relation to the coordinates
+ the string should be oriented.
+
+ The first letter is: t, c, or b, for top, center and bottom.
+ The second letter is: l, c, or r, for left, center and right.
+ The position refers to the position relative to the text itself.
+ It defaults to "tl" (top left).
+
+ Size is the size of the font in world coordinates.
+
+ * Family: Font family, a generic way of referring to fonts without
+ specifying actual facename. One of:
+
+ * wx.DEFAULT: Chooses a default font.
+ * wx.DECORATIVE: A decorative font.
+ * wx.ROMAN: A formal, serif font.
+ * wx.SCRIPT: A handwriting font.
+ * wx.SWISS: A sans-serif font.
+ * wx.MODERN: A fixed pitch font.
+
+ .. note:: these are only as good as the wxWindows defaults, which aren't so good.
+
+ * Style: One of wx.NORMAL, wx.SLANT and wx.ITALIC.
+ * Weight: One of wx.NORMAL, wx.LIGHT and wx.BOLD.
+ * Underlined: The value can be True or False. At present this may have an
+ effect on Windows only.
+
+
+ Alternatively, you can set the kw arg: Font, to a wx.Font, and the
+ above will be ignored. The size of the font you specify will be
+ ignored, but the rest of its attributes will be preserved.
+
+ The size will scale as the drawing is zoomed.
+
+ Bugs/Limitations:
+
+ As fonts are scaled, they do end up a little different, so you don't
+ get exactly the same picture as you scale up and down, but it's
+ pretty darn close.
+
+ On wxGTK1 on my Linux system, at least, using a font of over about
+ 3000 pts. brings the system to a halt. It's the Font Server using
+ huge amounts of memory. My work around is to max the font size to
+ 3000 points, so it won't scale past there. GTK2 uses smarter font
+ drawing, so that may not be an issue in future versions, so feel
+ free to test. Another smarter way to do it would be to set a global
+ zoom limit at that point.
+
+ The hit-test is done on the entire text extent. This could be made
+ optional, but I haven't gotten around to it.
+
+ """
+
+ def __init__(self,
+ String,
+ XY,
+ Size,
+ Color = "Black",
+ BackgroundColor = None,
+ Family = wx.MODERN,
+ Style = wx.NORMAL,
+ Weight = wx.NORMAL,
+ Underlined = False,
+ Position = 'tl',
+ Font = None,
+ InForeground = False):
+
+ DrawObject.__init__(self,InForeground)
+
+ self.String = String
+ self.XY = N.array( XY, N.float)
+ self.XY.shape = (2,)
+ self.Size = Size
+ self.Color = Color
+ self.BackgroundColor = BackgroundColor
+ self.Family = Family
+ self.Style = Style
+ self.Weight = Weight
+ self.Underlined = Underlined
+ if not Font:
+ self.FaceName = ''
+ else:
+ self.FaceName = Font.GetFaceName()
+ self.Family = Font.GetFamily()
+ self.Style = Font.GetStyle()
+ self.Underlined = Font.GetUnderlined()
+ self.Weight = Font.GetWeight()
+
+ # Experimental max font size value on wxGTK2: this works OK on
+ # my system. If it's a lot larger, there is a crash, with the
+ # message:
+ #
+ # The application 'FloatCanvasDemo.py' lost its
+ # connection to the display :0.0; most likely the X server was
+ # shut down or you killed/destroyed the application.
+ #
+ # Windows and OS-X seem to be better behaved in this regard.
+ # They may not draw it, but they don't crash either!
+ self.MaxFontSize = 1000
+ self.MinFontSize = 1 # this can be changed to set a minimum size
+ self.DisappearWhenSmall = True
+ self.ShiftFun = self.ShiftFunDict[Position]
+
+ self.CalcBoundingBox()
+
+ def LayoutText(self):
+ # This will be called when the text is re-set
+ # nothing much to be done here
+ self.CalcBoundingBox()
+
+ def CalcBoundingBox(self):
+ ## this isn't exact, as fonts don't scale exactly.
+ dc = wx.MemoryDC()
+ bitmap = wx.EmptyBitmap(1, 1)
+ dc.SelectObject(bitmap) #wxMac needs a Bitmap selected for GetTextExtent to work.
+ DrawingSize = 40 # pts This effectively determines the resolution that the BB is computed to.
+ ScaleFactor = float(self.Size) / DrawingSize
+ self.SetFont(DrawingSize, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName)
+ dc.SetFont(self.Font)
+ (w,h) = dc.GetTextExtent(self.String)
+ w = w * ScaleFactor
+ h = h * ScaleFactor
+ x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1)
+ self.BoundingBox = BBox.asBBox(((x, y-h ),(x + w, y)))
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ (X,Y) = WorldToPixel( (self.XY) )
+
+ # compute the font size:
+ Size = abs( ScaleWorldToPixel( (self.Size, self.Size) )[1] ) # only need a y coordinate length
+ ## Check to see if the font size is large enough to blow up the X font server
+ ## If so, limit it. Would it be better just to not draw it?
+ ## note that this limit is dependent on how much memory you have, etc.
+ Size = min(Size, self.MaxFontSize)
+ Size = max(Size, self.MinFontSize) # smallest size you want - default to 0
+
+ # Draw the Text
+ if not( self.DisappearWhenSmall and Size <= self.MinFontSize) : # don't try to draw a zero sized font!
+ self.SetFont(Size, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName)
+ dc.SetFont(self.Font)
+ dc.SetTextForeground(self.Color)
+ if self.BackgroundColor:
+ dc.SetBackgroundMode(wx.SOLID)
+ dc.SetTextBackground(self.BackgroundColor)
+ else:
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ (w,h) = dc.GetTextExtent(self.String)
+ # compute the shift, and adjust the coordinates, if neccesary
+ # This had to be put in here, because it changes with Zoom, as
+ # fonts don't scale exactly.
+ xy = self.ShiftFun(X, Y, w, h)
+
+ dc.DrawTextPoint(self.String, xy)
+
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(xy, (w, h) )
+
+class ScaledTextBox(TextObjectMixin, DrawObject):
+ """
+ This class creates a TextBox object that is scaled when zoomed. It is
+ placed at the coordinates, x,y.
+
+ If the Width parameter is defined, the text will be wrapped to the width given.
+
+ A Box can be drawn around the text, be specifying:
+ LineWidth and/or FillColor
+
+ A space(margin) can be put all the way around the text, be specifying:
+ the PadSize argument in world coordinates.
+
+ The spacing between lines can be adjusted with the:
+ LineSpacing argument.
+
+ The "Position" argument is a two character string, indicating where
+ in relation to the coordinates the Box should be oriented.
+ -The first letter is: t, c, or b, for top, center and bottom.
+ -The second letter is: l, c, or r, for left, center and right The
+ position refers to the position relative to the text itself. It
+ defaults to "tl" (top left).
+
+ Size is the size of the font in world coordinates.
+
+ * Family: Font family, a generic way of referring to fonts without
+ specifying actual facename. One of:
+
+ * wx.DEFAULT: Chooses a default font.
+ * wx.DECORATI: A decorative font.
+ * wx.ROMAN: A formal, serif font.
+ * wx.SCRIPT: A handwriting font.
+ * wx.SWISS: A sans-serif font.
+ * wx.MODERN: A fixed pitch font.
+
+ .. note:: these are only as good as the wxWindows defaults, which aren't so good.
+
+ * Style: One of wx.NORMAL, wx.SLANT and wx.ITALIC.
+ * Weight: One of wx.NORMAL, wx.LIGHT and wx.BOLD.
+ * Underlined: The value can be True or False. At present this may have an an
+ effect on Windows only.
+
+
+ Alternatively, you can set the kw arg: Font, to a wx.Font, and the
+ above will be ignored. The size of the font you specify will be
+ ignored, but the rest of its attributes will be preserved.
+
+ The size will scale as the drawing is zoomed.
+
+ Bugs/Limitations:
+
+ As fonts are scaled, they do end up a little different, so you don't
+ get exactly the same picture as you scale up and down, but it's
+ pretty darn close.
+
+ On wxGTK1 on my Linux system, at least, using a font of over about
+ 1000 pts. brings the system to a halt. It's the Font Server using
+ huge amounts of memory. My work around is to max the font size to
+ 1000 points, so it won't scale past there. GTK2 uses smarter font
+ drawing, so that may not be an issue in future versions, so feel
+ free to test. Another smarter way to do it would be to set a global
+ zoom limit at that point.
+
+ The hit-test is done on the entire box. This could be made
+ optional, but I haven't gotten around to it.
+
+ """
+
+ def __init__(self, String,
+ Point,
+ Size,
+ Color = "Black",
+ BackgroundColor = None,
+ LineColor = 'Black',
+ LineStyle = 'Solid',
+ LineWidth = 1,
+ Width = None,
+ PadSize = None,
+ Family = wx.MODERN,
+ Style = wx.NORMAL,
+ Weight = wx.NORMAL,
+ Underlined = False,
+ Position = 'tl',
+ Alignment = "left",
+ Font = None,
+ LineSpacing = 1.0,
+ InForeground = False):
+ DrawObject.__init__(self,InForeground)
+
+ self.XY = N.array(Point, N.float)
+ self.Size = Size
+ self.Color = Color
+ self.BackgroundColor = BackgroundColor
+ self.LineColor = LineColor
+ self.LineStyle = LineStyle
+ self.LineWidth = LineWidth
+ self.Width = Width
+ if PadSize is None: # the default is just a little bit of padding
+ self.PadSize = Size/10.0
+ else:
+ self.PadSize = float(PadSize)
+ self.Family = Family
+ self.Style = Style
+ self.Weight = Weight
+ self.Underlined = Underlined
+ self.Alignment = Alignment.lower()
+ self.LineSpacing = float(LineSpacing)
+ self.Position = Position
+
+ if not Font:
+ self.FaceName = ''
+ else:
+ self.FaceName = Font.GetFaceName()
+ self.Family = Font.GetFamily()
+ self.Style = Font.GetStyle()
+ self.Underlined = Font.GetUnderlined()
+ self.Weight = Font.GetWeight()
+
+ # Experimental max font size value on wxGTK2: this works OK on
+ # my system. If it's a lot larger, there is a crash, with the
+ # message:
+ #
+ # The application 'FloatCanvasDemo.py' lost its
+ # connection to the display :0.0; most likely the X server was
+ # shut down or you killed/destroyed the application.
+ #
+ # Windows and OS-X seem to be better behaved in this regard.
+ # They may not draw it, but they don't crash either!
+
+ self.MaxFontSize = 1000
+ self.MinFontSize = 1 # this can be changed to set a larger minimum size
+ self.DisappearWhenSmall = True
+
+ self.ShiftFun = self.ShiftFunDict[Position]
+
+ self.String = String
+ self.LayoutText()
+ self.CalcBoundingBox()
+
+ self.SetPen(LineColor,LineStyle,LineWidth)
+ self.SetBrush(BackgroundColor, "Solid")
+
+
+ def WrapToWidth(self):
+ dc = wx.MemoryDC()
+ bitmap = wx.EmptyBitmap(1, 1)
+ dc.SelectObject(bitmap) #wxMac needs a Bitmap selected for GetTextExtent to work.
+ DrawingSize = self.LayoutFontSize # pts This effectively determines the resolution that the BB is computed to.
+ ScaleFactor = float(self.Size) / DrawingSize
+ Width = (self.Width - 2*self.PadSize) / ScaleFactor #Width to wrap to
+ self.SetFont(DrawingSize, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName)
+ dc.SetFont(self.Font)
+ NewStrings = []
+ for s in self.Strings:
+ #beginning = True
+ text = s.split(" ")
+ text.reverse()
+ LineLength = 0
+ NewText = text[-1]
+ del text[-1]
+ while text:
+ w = dc.GetTextExtent(' ' + text[-1])[0]
+ if LineLength + w <= Width:
+ NewText += ' '
+ NewText += text[-1]
+ LineLength = dc.GetTextExtent(NewText)[0]
+ else:
+ NewStrings.append(NewText)
+ NewText = text[-1]
+ LineLength = dc.GetTextExtent(text[-1])[0]
+ del text[-1]
+ NewStrings.append(NewText)
+ self.Strings = NewStrings
+
+ def ReWrap(self, Width):
+ self.Width = Width
+ self.LayoutText()
+
+ def LayoutText(self):
+ """
+
+ Calculates the positions of the words of text.
+
+ This isn't exact, as fonts don't scale exactly.
+ To help this, the position of each individual word
+ is stored separately, so that the general layout stays
+ the same in world coordinates, as the fonts scale.
+
+ """
+ self.Strings = self.String.split("\n")
+ if self.Width:
+ self.WrapToWidth()
+
+ dc = wx.MemoryDC()
+ bitmap = wx.EmptyBitmap(1, 1)
+ dc.SelectObject(bitmap) #wxMac needs a Bitmap selected for GetTextExtent to work.
+
+ DrawingSize = self.LayoutFontSize # pts This effectively determines the resolution that the BB is computed to.
+ ScaleFactor = float(self.Size) / DrawingSize
+
+ self.SetFont(DrawingSize, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName)
+ dc.SetFont(self.Font)
+ TextHeight = dc.GetTextExtent("X")[1]
+ SpaceWidth = dc.GetTextExtent(" ")[0]
+ LineHeight = TextHeight * self.LineSpacing
+
+ LineWidths = N.zeros((len(self.Strings),), N.float)
+ y = 0
+ Words = []
+ AllLinePoints = []
+
+ for i, s in enumerate(self.Strings):
+ LineWidths[i] = 0
+ LineWords = s.split(" ")
+ LinePoints = N.zeros((len(LineWords),2), N.float)
+ for j, word in enumerate(LineWords):
+ if j > 0:
+ LineWidths[i] += SpaceWidth
+ Words.append(word)
+ LinePoints[j] = (LineWidths[i], y)
+ w = dc.GetTextExtent(word)[0]
+ LineWidths[i] += w
+ y -= LineHeight
+ AllLinePoints.append(LinePoints)
+ TextWidth = N.maximum.reduce(LineWidths)
+ self.Words = Words
+
+ if self.Width is None:
+ BoxWidth = TextWidth * ScaleFactor + 2*self.PadSize
+ else: # use the defined Width
+ BoxWidth = self.Width
+ Points = N.zeros((0,2), N.float)
+
+ for i, LinePoints in enumerate(AllLinePoints):
+ ## Scale to World Coords.
+ LinePoints *= (ScaleFactor, ScaleFactor)
+ if self.Alignment == 'left':
+ LinePoints[:,0] += self.PadSize
+ elif self.Alignment == 'center':
+ LinePoints[:,0] += (BoxWidth - LineWidths[i]*ScaleFactor)/2.0
+ elif self.Alignment == 'right':
+ LinePoints[:,0] += (BoxWidth - LineWidths[i]*ScaleFactor-self.PadSize)
+ Points = N.concatenate((Points, LinePoints))
+
+ BoxHeight = -(Points[-1,1] - (TextHeight * ScaleFactor)) + 2*self.PadSize
+ #(x,y) = self.ShiftFun(self.XY[0], self.XY[1], BoxWidth, BoxHeight, world=1)
+ Points += (0, -self.PadSize)
+ self.Points = Points
+ self.BoxWidth = BoxWidth
+ self.BoxHeight = BoxHeight
+ self.CalcBoundingBox()
+
+ def CalcBoundingBox(self):
+
+ """
+
+ Calculates the Bounding Box
+
+ """
+
+ w, h = self.BoxWidth, self.BoxHeight
+ x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world=1)
+ self.BoundingBox = BBox.asBBox(((x, y-h ),(x + w, y)))
+
+ def GetBoxRect(self):
+ wh = (self.BoxWidth, self.BoxHeight)
+ xy = (self.BoundingBox[0,0], self.BoundingBox[1,1])
+
+ return (xy, wh)
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ xy, wh = self.GetBoxRect()
+
+ Points = self.Points + xy
+ Points = WorldToPixel(Points)
+ xy = WorldToPixel(xy)
+ wh = ScaleWorldToPixel(wh) * (1,-1)
+
+ # compute the font size:
+ Size = abs( ScaleWorldToPixel( (self.Size, self.Size) )[1] ) # only need a y coordinate length
+ ## Check to see if the font size is large enough to blow up the X font server
+ ## If so, limit it. Would it be better just to not draw it?
+ ## note that this limit is dependent on how much memory you have, etc.
+ Size = min(Size, self.MaxFontSize)
+ Size = max(Size, self.MinFontSize) # smallest size you want - default to 1
+
+ # Draw The Box
+ if (self.LineStyle and self.LineColor) or self.BackgroundColor:
+ dc.SetBrush(self.Brush)
+ dc.SetPen(self.Pen)
+ dc.DrawRectanglePointSize(xy , wh)
+
+ # Draw the Text
+ if not( self.DisappearWhenSmall and Size <= self.MinFontSize) : # don't try to draw a zero sized font!
+ self.SetFont(Size, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName)
+ dc.SetFont(self.Font)
+ dc.SetTextForeground(self.Color)
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ ## NOTE: DrawTextList seems to have a memory leak if you call it with a numpy array.
+ # This has probably been fixed in the wxPython source (as of 9/4/2013),
+ # but for older versions it's this way for now.
+ dc.DrawTextList(self.Words, Points.tolist())
+
+ # Draw the hit box.
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(xy, wh)
+
+class Bitmap(TextObjectMixin, DrawObject, ):
+ """
+ This class creates a bitmap object, placed at the coordinates,
+ x,y. the "Position" argument is a two charactor string, indicating
+ where in relation to the coordinates the bitmap should be oriented.
+
+ The first letter is: t, c, or b, for top, center and bottom The
+ second letter is: l, c, or r, for left, center and right The
+ position refers to the position relative to the text itself. It
+ defaults to "tl" (top left).
+
+ The size is fixed, and does not scale with the drawing.
+
+ """
+
+ def __init__(self,Bitmap,XY,
+ Position = 'tl',
+ InForeground = False):
+
+ DrawObject.__init__(self,InForeground)
+
+ if type(Bitmap) == wx._gdi.Bitmap:
+ self.Bitmap = Bitmap
+ elif type(Bitmap) == wx._core.Image:
+ self.Bitmap = wx.BitmapFromImage(Bitmap)
+
+ # Note the BB is just the point, as the size in World coordinates is not fixed
+ self.BoundingBox = BBox.asBBox( (XY,XY) )
+
+ self.XY = XY
+
+ (self.Width, self.Height) = self.Bitmap.GetWidth(), self.Bitmap.GetHeight()
+ self.ShiftFun = self.ShiftFunDict[Position]
+
+ # no need for a line width with bitmaps
+ self.MinHitLineWidth = 0
+ self.HitLineWidth = 0
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ XY = WorldToPixel(self.XY)
+ XY = self.ShiftFun(XY[0], XY[1], self.Width, self.Height)
+ dc.DrawBitmapPoint(self.Bitmap, XY, True)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(XY, (self.Width, self.Height) )
+
+class ScaledBitmap(TextObjectMixin, DrawObject, ):
+ """
+
+ This class creates a bitmap object, placed at the coordinates, XY,
+ of Height, H, in World coordinates. The width is calculated from the
+ aspect ratio of the bitmap.
+
+ the "Position" argument is a two character string, indicating
+ where in relation to the coordinates the bitmap should be oriented.
+
+ The first letter is: t, c, or b, for top, center and bottom The
+ second letter is: l, c, or r, for left, center and right The
+ position refers to the position relative to the text itself. It
+ defaults to "tl" (top left).
+
+ The size scales with the drawing
+
+ """
+
+ def __init__(self,
+ Bitmap,
+ XY,
+ Height,
+ Position = 'tl',
+ InForeground = False,
+ Quality='normal'):
+
+ DrawObject.__init__(self,InForeground)
+
+ if type(Bitmap) == wx._gdi.Bitmap:
+ self.Image = Bitmap.ConvertToImage()
+ elif type(Bitmap) == wx._core.Image:
+ self.Image = Bitmap
+
+ self.XY = XY
+ self.Height = Height
+ (self.bmpWidth, self.bmpHeight) = self.Image.GetWidth(), self.Image.GetHeight()
+ self.Width = self.bmpWidth / self.bmpHeight * Height
+ self.ShiftFun = self.ShiftFunDict[Position]
+ self.CalcBoundingBox()
+ self.ScaledBitmap = None
+ self.ScaledHeight = None
+ self.Quality = Quality
+
+ # no need for a line width with bitmaps
+ self.MinHitLineWidth = 0
+ self.HitLineWidth = 0
+
+
+ @property
+ def Quality(self):
+ if self._scale_quality == wx.IMAGE_QUALITY_NORMAL:
+ return 'normal'
+ elif self._scale_quality == wx.IMAGE_QUALITY_HIGH:
+ return 'high'
+ else:
+ raise ValueError('the _scale_quality attribute should only be set to wx.IMAGE_QUALITY_NORMAL or wx.IMAGE_QUALITY_HIGH')
+
+ @Quality.setter
+ def Quality(self, qual):
+ if qual.lower() == 'normal':
+ self._scale_quality = wx.IMAGE_QUALITY_NORMAL
+ elif qual.lower() == 'high':
+ self._scale_quality = wx.IMAGE_QUALITY_HIGH
+ else:
+ raise ValueError('the Quality property can only be set to "normal" or "high"')
+
+
+ def CalcBoundingBox(self):
+ ## this isn't exact, as fonts don't scale exactly.
+ w, h = self.Width, self.Height
+ x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1)
+ self.BoundingBox = BBox.asBBox( ( (x, y-h ), (x + w, y) ) )
+
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ XY = WorldToPixel(self.XY)
+ H = int(round(ScaleWorldToPixel(self.Height)[0]))
+ W = int(round(H * (self.bmpWidth / self.bmpHeight)))
+ if W == 0 or H == 0: # nothign to draw
+ return
+ else:
+ if (self.ScaledBitmap is None) or (H <> self.ScaledHeight) :
+ self.ScaledHeight = H
+ Img = self.Image.Scale(W, H, quality=self._scale_quality)
+ self.ScaledBitmap = wx.BitmapFromImage(Img)
+
+ XY = self.ShiftFun(XY[0], XY[1], W, H)
+ dc.DrawBitmapPoint(self.ScaledBitmap, XY, True)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(XY, (W, H) )
+
+class ScaledBitmap2(TextObjectMixin, DrawObject, ):
+ """
+
+ An alternative scaled bitmap that only scaled the required amount of
+ the main bitmap when zoomed in: EXPERIMENTAL!
+
+ """
+
+ def __init__(self,
+ Bitmap,
+ XY,
+ Height,
+ Width=None,
+ Position = 'tl',
+ InForeground = False,
+ Quality='normal'):
+
+ DrawObject.__init__(self,InForeground)
+
+ if type(Bitmap) == wx._gdi.Bitmap:
+ self.Image = Bitmap.ConvertToImage()
+ elif type(Bitmap) == wx._core.Image:
+ self.Image = Bitmap
+
+ self.XY = N.array(XY, N.float)
+ self.Height = Height
+ (self.bmpWidth, self.bmpHeight) = self.Image.GetWidth(), self.Image.GetHeight()
+ self.bmpWH = N.array((self.bmpWidth, self.bmpHeight), N.int32)
+ ## fixme: this should all accommodate different scales for X and Y
+ if Width is None:
+ self.BmpScale = float(self.bmpHeight) / Height
+ self.Width = self.bmpWidth / self.BmpScale
+ self.WH = N.array((self.Width, Height), N.float)
+ ##fixme: should this have a y = -1 to shift to y-up?
+ self.BmpScale = self.bmpWH / self.WH
+
+ self.ShiftFun = self.ShiftFunDict[Position]
+ self.CalcBoundingBox()
+ self.ScaledBitmap = None # cache of the last existing scaled bitmap
+ self.Quality = Quality
+
+ # no need for aline width with images.
+ self.MinHitLineWidth = 0
+ self.HitLineWidth = 0
+
+ @property
+ def Quality(self):
+ if self._scale_quality == wx.IMAGE_QUALITY_NORMAL:
+ return 'normal'
+ elif self._scale_quality == wx.IMAGE_QUALITY_HIGH:
+ return 'high'
+ else:
+ raise ValueError('the _scale_quality attribute should only be set to wx.IMAGE_QUALITY_NORMAL or wx.IMAGE_QUALITY_HIGH')
+
+ @Quality.setter
+ def Quality(self, qual):
+ if qual.lower() == 'normal':
+ self._scale_quality = wx.IMAGE_QUALITY_NORMAL
+ elif qual.lower() == 'high':
+ self._scale_quality = wx.IMAGE_QUALITY_HIGH
+ else:
+ raise ValueError('the Quality property can only be set to "normal" or "high"')
+
+ def CalcBoundingBox(self):
+ ## this isn't exact, as fonts don't scale exactly.
+ w,h = self.Width, self.Height
+ x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1)
+ self.BoundingBox = BBox.asBBox( ((x, y-h ), (x + w, y)) )
+
+ def WorldToBitmap(self, Pw):
+ """
+ computes bitmap coords from World coords
+ """
+ delta = Pw - self.XY
+ Pb = delta * self.BmpScale
+ Pb *= (1, -1) ##fixme: this may only works for Y-up projection!
+ ## and may only work for top left position
+
+ return Pb.astype(N.int_)
+
+ def _DrawEntireBitmap(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc):
+ """
+ this is pretty much the old code
+
+ Scales and Draws the entire bitmap.
+
+ """
+ XY = WorldToPixel(self.XY)
+ H = int(round(ScaleWorldToPixel(self.Height)[0]))
+ W = int(round(H * (self.bmpWidth / self.bmpHeight)))
+ if W == 0 or H == 0: # nothing to draw
+ return
+ else:
+ if (self.ScaledBitmap is None) or (self.ScaledBitmap[0] != (0, 0, self.bmpWidth, self.bmpHeight, W, H) ):
+ #if True: #fixme: (self.ScaledBitmap is None) or (H <> self.ScaledHeight) :
+ self.ScaledHeight = H
+ Img = self.Image.Scale(W, H, quality=self._scale_quality)
+ bmp = wx.BitmapFromImage(Img)
+ self.ScaledBitmap = ((0, 0, self.bmpWidth, self.bmpHeight , W, H), bmp)# this defines the cached bitmap
+ else:
+ bmp = self.ScaledBitmap[1]
+ XY = self.ShiftFun(XY[0], XY[1], W, H)
+ dc.DrawBitmapPoint(bmp, XY, True)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(XY, (W, H) )
+
+ def _DrawSubBitmap(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc):
+ """
+ Subsets just the part of the bitmap that is visible
+ then scales and draws that.
+
+ """
+ BBworld = BBox.asBBox(self._Canvas.ViewPortBB)
+ BBbitmap = BBox.fromPoints(self.WorldToBitmap(BBworld))
+
+ XYs = WorldToPixel(self.XY)
+ # figure out subimage:
+ # fixme: this should be able to be done more succinctly!
+
+ if BBbitmap[0,0] < 0:
+ Xb = 0
+ elif BBbitmap[0,0] > self.bmpWH[0]: # off the bitmap
+ Xb = 0
+ else:
+ Xb = BBbitmap[0,0]
+ XYs[0] = 0 # draw at origin
+
+ if BBbitmap[0,1] < 0:
+ Yb = 0
+ elif BBbitmap[0,1] > self.bmpWH[1]: # off the bitmap
+ Yb = 0
+ ShouldDraw = False
+ else:
+ Yb = BBbitmap[0,1]
+ XYs[1] = 0 # draw at origin
+
+ if BBbitmap[1,0] < 0:
+ #off the screen -- This should never happen!
+ Wb = 0
+ elif BBbitmap[1,0] > self.bmpWH[0]:
+ Wb = self.bmpWH[0] - Xb
+ else:
+ Wb = BBbitmap[1,0] - Xb
+
+ if BBbitmap[1,1] < 0:
+ # off the screen -- This should never happen!
+ Hb = 0
+ ShouldDraw = False
+ elif BBbitmap[1,1] > self.bmpWH[1]:
+ Hb = self.bmpWH[1] - Yb
+ else:
+ Hb = BBbitmap[1,1] - Yb
+
+ FullHeight = ScaleWorldToPixel(self.Height)[0]
+ scale = FullHeight / self.bmpWH[1]
+ Ws = int(scale * Wb + 0.5) # add the 0.5 to round
+ Hs = int(scale * Hb + 0.5)
+ if (self.ScaledBitmap is None) or (self.ScaledBitmap[0] != (Xb, Yb, Wb, Hb, Ws, Ws) ):
+ Img = self.Image.GetSubImage(wx.Rect(Xb, Yb, Wb, Hb))
+ Img.Rescale(Ws, Hs, quality=self._scale_quality)
+ bmp = wx.BitmapFromImage(Img)
+ self.ScaledBitmap = ((Xb, Yb, Wb, Hb, Ws, Ws), bmp)# this defines the cached bitmap
+ #XY = self.ShiftFun(XY[0], XY[1], W, H)
+ #fixme: get the shiftfun working!
+ else:
+ ##fixme: The cached bitmap could be used if the one needed is the same scale, but
+ ## a subset of the cached one.
+ bmp = self.ScaledBitmap[1]
+ dc.DrawBitmapPoint(bmp, XYs, True)
+
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(XYs, (Ws, Hs) )
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ BBworld = BBox.asBBox(self._Canvas.ViewPortBB)
+ ## first see if entire bitmap is displayed:
+ if BBworld.Inside(self.BoundingBox):
+ # use od code to draw entire bitmap
+ self._DrawEntireBitmap(dc , WorldToPixel, ScaleWorldToPixel, HTdc)
+ return
+ elif BBworld.Overlaps(self.BoundingBox):
+ self._DrawSubBitmap(dc , WorldToPixel, ScaleWorldToPixel, HTdc)
+ else:
+ #Not Drawing -- no part of image is showing
+ return
+
+class DotGrid:
+ """
+ An example of a Grid Object -- it is set on the FloatCanvas with one of:
+
+ FloatCanvas.GridUnder = Grid
+ FloatCanvas.GridOver = Grid
+
+ It will be drawn every time, regardless of the viewport.
+
+ In its _Draw method, it computes what to draw, given the ViewPortBB
+ of the Canvas it's being drawn on.
+
+ """
+ def __init__(self, Spacing, Size = 2, Color = "Black", Cross=False, CrossThickness = 1):
+
+ self.Spacing = N.array(Spacing, N.float)
+ self.Spacing.shape = (2,)
+ self.Size = Size
+ self.Color = Color
+ self.Cross = Cross
+ self.CrossThickness = CrossThickness
+
+ def CalcPoints(self, Canvas):
+ ViewPortBB = Canvas.ViewPortBB
+
+ Spacing = self.Spacing
+
+ minx, miny = N.floor(ViewPortBB[0] / Spacing) * Spacing
+ maxx, maxy = N.ceil(ViewPortBB[1] / Spacing) * Spacing
+
+ ##fixme: this could use vstack or something with numpy
+ x = N.arange(minx, maxx+Spacing[0], Spacing[0]) # making sure to get the last point
+ y = N.arange(miny, maxy+Spacing[1], Spacing[1]) # an extra is OK
+ Points = N.zeros((len(y), len(x), 2), N.float)
+ x.shape = (1,-1)
+ y.shape = (-1,1)
+ Points[:,:,0] += x
+ Points[:,:,1] += y
+ Points.shape = (-1,2)
+
+ return Points
+
+ def _Draw(self, dc, Canvas):
+ Points = self.CalcPoints(Canvas)
+
+ Points = Canvas.WorldToPixel(Points)
+
+ dc.SetPen(wx.Pen(self.Color,self.CrossThickness))
+
+ if self.Cross: # Use cross shaped markers
+ #Horizontal lines
+ LinePoints = N.concatenate((Points + (self.Size,0),Points + (-self.Size,0)),1)
+ dc.DrawLineList(LinePoints)
+ # Vertical Lines
+ LinePoints = N.concatenate((Points + (0,self.Size),Points + (0,-self.Size)),1)
+ dc.DrawLineList(LinePoints)
+ pass
+ else: # use dots
+ ## Note: this code borrowed from Pointset -- it really shouldn't be repeated here!.
+ if self.Size <= 1:
+ dc.DrawPointList(Points)
+ elif self.Size <= 2:
+ dc.DrawPointList(Points + (0,-1))
+ dc.DrawPointList(Points + (0, 1))
+ dc.DrawPointList(Points + (1, 0))
+ dc.DrawPointList(Points + (-1,0))
+ else:
+ dc.SetBrush(wx.Brush(self.Color))
+ radius = int(round(self.Size/2))
+ ##fixme: I really should add a DrawCircleList to wxPython
+ if len(Points) > 100:
+ xy = Points
+ xywh = N.concatenate((xy-radius, N.ones(xy.shape) * self.Size ), 1 )
+ dc.DrawEllipseList(xywh)
+ else:
+ for xy in Points:
+ dc.DrawCircle(xy[0],xy[1], radius)
+
+class Arc(XYObjectMixin, LineAndFillMixin, DrawObject):
+ def __init__(self,
+ StartXY,
+ EndXY,
+ CenterXY,
+ LineColor = "Black",
+ LineStyle = "Solid",
+ LineWidth = 1,
+ FillColor = None,
+ FillStyle = "Solid",
+ InForeground = False):
+ """
+ Draws an arc of a circle, centered on point CenterXY, from
+ the first point (StartXY) to the second (EndXY).
+
+ The arc is drawn in an anticlockwise direction from the start point to
+ the end point.
+
+ Parameters:
+ StartXY : start point
+ EndXY : end point
+ CenterXY: center point
+ LineColor = "Black",
+ LineStyle = "Solid",
+ LineWidth = 1,
+ FillColor = None,
+ FillStyle = "Solid",
+ InForeground = False):
+
+ """
+
+ DrawObject.__init__(self, InForeground)
+
+ # There is probably a more elegant way to do this next section
+ # The bounding box just gets set to the WH of a circle, with center at CenterXY
+ # This is suitable for a pie chart as it will be a circle anyway
+ radius = N.sqrt( (StartXY[0]-CenterXY[0])**2 + (StartXY[1]-CenterXY[1])**2 )
+ minX = CenterXY[0]-radius
+ minY = CenterXY[1]-radius
+ maxX = CenterXY[0]+radius
+ maxY = CenterXY[1]+radius
+ XY = [minX,minY]
+ WH = [maxX-minX,maxY-minY]
+
+ self.XY = N.asarray( XY, N.float).reshape((2,))
+ self.WH = N.asarray( WH, N.float).reshape((2,))
+
+ self.StartXY = N.asarray(StartXY, N.float).reshape((2,))
+ self.CenterXY = N.asarray(CenterXY, N.float).reshape((2,))
+ self.EndXY = N.asarray(EndXY, N.float).reshape((2,))
+
+ #self.BoundingBox = array((self.XY, (self.XY + self.WH)), Float)
+ self.CalcBoundingBox()
+
+ #Finish the setup; allocate color,style etc.
+ self.LineColor = LineColor
+ self.LineStyle = LineStyle
+ self.LineWidth = LineWidth
+ self.FillColor = FillColor
+ self.FillStyle = FillStyle
+
+ self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
+
+ self.SetPen(LineColor, LineStyle, LineWidth)
+ self.SetBrush(FillColor, FillStyle)
+
+ def Move(self, Delta ):
+ """
+
+ Move(Delta): moves the object by delta, where delta is a
+ (dx,dy) pair. Ideally a Numpy array of shape (2,)
+
+ """
+
+ Delta = N.asarray(Delta, N.float)
+ self.XY += Delta
+ self.StartXY += Delta
+ self.CenterXY += Delta
+ self.EndXY += Delta
+ self.BoundingBox += Delta
+
+ if self._Canvas:
+ self._Canvas.BoundingBoxDirty = True
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ self.SetUpDraw(dc , WorldToPixel, ScaleWorldToPixel, HTdc)
+ StartXY = WorldToPixel(self.StartXY)
+ EndXY = WorldToPixel(self.EndXY)
+ CenterXY = WorldToPixel(self.CenterXY)
+
+ dc.DrawArcPoint(StartXY, EndXY, CenterXY)
+ if HTdc and self.HitAble:
+ HTdc.DrawArcPoint(StartXY, EndXY, CenterXY)
+
+ def CalcBoundingBox(self):
+ self.BoundingBox = BBox.asBBox( N.array((self.XY, (self.XY + self.WH) ), N.float) )
+ if self._Canvas:
+ self._Canvas.BoundingBoxDirty = True
+
+
+#---------------------------------------------------------------------------
+class FloatCanvas(wx.Panel):
+ """
+ FloatCanvas.py
+
+ This is a high level window for drawing maps and anything else in an
+ arbitrary coordinate system.
+
+ The goal is to provide a convenient way to draw stuff on the screen
+ without having to deal with handling OnPaint events, converting to pixel
+ coordinates, knowing about wxWindows brushes, pens, and colors, etc. It
+ also provides virtually unlimited zooming and scrolling
+
+ I am using it for two things:
+ 1) general purpose drawing in floating point coordinates
+ 2) displaying map data in Lat-long coordinates
+
+ If the projection is set to None, it will draw in general purpose
+ floating point coordinates. If the projection is set to 'FlatEarth', it
+ will draw a FlatEarth projection, centered on the part of the map that
+ you are viewing. You can also pass in your own projection function.
+
+ It is double buffered, so re-draws after the window is uncovered by something
+ else are very quick.
+
+ It relies on NumPy, which is needed for speed (maybe, I havn't profiled it)
+
+ Bugs and Limitations:
+ Lots: patches, fixes welcome
+
+ For Map drawing: It ignores the fact that the world is, in fact, a
+ sphere, so it will do strange things if you are looking at stuff near
+ the poles or the date line. so far I don't have a need to do that, so I
+ havn't bothered to add any checks for that yet.
+
+ Zooming:
+ I have set no zoom limits. What this means is that if you zoom in really
+ far, you can get integer overflows, and get wierd results. It
+ doesn't seem to actually cause any problems other than wierd output, at
+ least when I have run it.
+
+ Speed:
+ I have done a couple of things to improve speed in this app. The one
+ thing I have done is used NumPy Arrays to store the coordinates of the
+ points of the objects. This allowed me to use array oriented functions
+ when doing transformations, and should provide some speed improvement
+ for objects with a lot of points (big polygons, polylines, pointsets).
+
+ The real slowdown comes when you have to draw a lot of objects, because
+ you have to call the wx.DC.DrawSomething call each time. This is plenty
+ fast for tens of objects, OK for hundreds of objects, but pretty darn
+ slow for thousands of objects.
+
+ The solution is to be able to pass some sort of object set to the DC
+ directly. I've used DC.DrawPointList(Points), and it helped a lot with
+ drawing lots of points. I havn't got a LineSet type object, so I havn't
+ used DC.DrawLineList yet. I'd like to get a full set of DrawStuffList()
+ methods implimented, and then I'd also have a full set of Object sets
+ that could take advantage of them. I hope to get to it some day.
+
+ Mouse Events:
+
+ At this point, there are a full set of custom mouse events. They are
+ just like the regular mouse events, but include an extra attribute:
+ Event.GetCoords(), that returns the (x,y) position in world
+ coordinates, as a length-2 NumPy vector of Floats.
+
+ Copyright: Christopher Barker
+
+ License: Same as the version of wxPython you are using it with
+
+ Please let me know if you're using this!!!
+
+ Contact me at:
+
+ Chris.Barker@noaa.gov
+
+ """
+
+ def __init__(self, parent, id = -1,
+ size = wx.DefaultSize,
+ ProjectionFun = None,
+ BackgroundColor = "WHITE",
+ Debug = False,
+ **kwargs):
+
+ wx.Panel.__init__( self, parent, id, wx.DefaultPosition, size, **kwargs)
+
+ self.ComputeFontScale()
+ self.InitAll()
+
+ self.BackgroundBrush = wx.Brush(BackgroundColor,wx.SOLID)
+
+ self.Debug = Debug
+
+ wx.EVT_PAINT(self, self.OnPaint)
+ wx.EVT_SIZE(self, self.OnSize)
+
+ wx.EVT_LEFT_DOWN(self, self.LeftDownEvent)
+ wx.EVT_LEFT_UP(self, self.LeftUpEvent)
+ wx.EVT_LEFT_DCLICK(self, self.LeftDoubleClickEvent)
+ wx.EVT_MIDDLE_DOWN(self, self.MiddleDownEvent)
+ wx.EVT_MIDDLE_UP(self, self.MiddleUpEvent)
+ wx.EVT_MIDDLE_DCLICK(self, self.MiddleDoubleClickEvent)
+ wx.EVT_RIGHT_DOWN(self, self.RightDownEvent)
+ wx.EVT_RIGHT_UP(self, self.RightUpEvent)
+ wx.EVT_RIGHT_DCLICK(self, self.RightDoubleCLickEvent)
+ wx.EVT_MOTION(self, self.MotionEvent)
+ wx.EVT_MOUSEWHEEL(self, self.WheelEvent)
+ wx.EVT_KEY_DOWN(self, self.KeyDownEvent)
+ wx.EVT_KEY_UP(self, self.KeyUpEvent)
+
+
+ ## CHB: I'm leaving these out for now.
+ #wx.EVT_ENTER_WINDOW(self, self. )
+ #wx.EVT_LEAVE_WINDOW(self, self. )
+
+ self.SetProjectionFun(ProjectionFun)
+
+ self.GUIMode = None # making sure the arrribute exists
+ self.SetMode(GUIMode.GUIMouse()) # make the default Mouse Mode.
+
+ # timer to give a delay when re-sizing so that buffers aren't re-built too many times.
+ self.SizeTimer = wx.PyTimer(self.OnSizeTimer)
+
+# self.InitializePanel()
+# self.MakeNewBuffers()
+
+# self.CreateCursors()
+
+ def ComputeFontScale(self):
+ ## A global variable to hold the scaling from pixel size to point size.
+ global FontScale
+ dc = wx.ScreenDC()
+ dc.SetFont(wx.Font(16, wx.ROMAN, wx.NORMAL, wx.NORMAL))
+ E = dc.GetTextExtent("X")
+ FontScale = 16/E[1]
+ del dc
+
+ def InitAll(self):
+ """
+ InitAll() sets everything in the Canvas to default state.
+
+ It can be used to reset the Canvas
+
+ """
+
+ self.HitColorGenerator = None
+ self.UseHitTest = False
+
+ self.NumBetweenBlits = 500
+
+ ## create the Hit Test Dicts:
+ self.HitDict = None
+ self._HTdc = None
+
+ self._DrawList = []
+ self._ForeDrawList = []
+ self.InitializePanel()
+ self.MakeNewBuffers()
+ self.BoundingBox = BBox.NullBBox()
+ self.BoundingBoxDirty = False
+ self.MinScale = None
+ self.MaxScale = None
+ self.ViewPortCenter= N.array( (0,0), N.float)
+
+ self.SetProjectionFun(None)
+
+ self.MapProjectionVector = N.array( (1,1), N.float) # No Projection to start!
+ self.TransformVector = N.array( (1,-1), N.float) # default Transformation
+
+ self.Scale = 1
+ self.ObjectUnderMouse = None
+
+ self.GridUnder = None
+ self.GridOver = None
+
+ self._BackgroundDirty = True
+
+ def SetProjectionFun(self, ProjectionFun):
+ if ProjectionFun == 'FlatEarth':
+ self.ProjectionFun = self.FlatEarthProjection
+ elif callable(ProjectionFun):
+ self.ProjectionFun = ProjectionFun
+ elif ProjectionFun is None:
+ self.ProjectionFun = lambda x=None: N.array( (1,1), N.float)
+ else:
+ raise FloatCanvasError('Projectionfun must be either:'
+ ' "FlatEarth", None, or a callable object '
+ '(function or callable object) that takes the '
+ 'ViewPortCenter and returns a MapProjectionVector')
+
+ def FlatEarthProjection(self, CenterPoint):
+ MaxLatitude = 75 # these were determined essentially arbitrarily
+ MinLatitude = -75
+ Lat = min(CenterPoint[1],MaxLatitude)
+ Lat = max(Lat,MinLatitude)
+ return N.array((N.cos(N.pi*Lat/180),1),N.float)
+
+ def SetMode(self, Mode):
+ '''
+ Set the GUImode to any of the available mode.
+ '''
+ # Set mode
+ if self.GUIMode is not None:
+ self.GUIMode.UnSet() # this lets the old mode clean up.
+ Mode.Canvas = self # make sure the mode is linked to this canvas
+ self.GUIMode = Mode
+ self.SetCursor(self.GUIMode.Cursor)
+
+ def MakeHitDict(self):
+ ##fixme: Should this just be None if nothing has been bound?
+ self.HitDict = {EVT_FC_LEFT_DOWN: {},
+ EVT_FC_LEFT_UP: {},
+ EVT_FC_LEFT_DCLICK: {},
+ EVT_FC_MIDDLE_DOWN: {},
+ EVT_FC_MIDDLE_UP: {},
+ EVT_FC_MIDDLE_DCLICK: {},
+ EVT_FC_RIGHT_DOWN: {},
+ EVT_FC_RIGHT_UP: {},
+ EVT_FC_RIGHT_DCLICK: {},
+ EVT_FC_ENTER_OBJECT: {},
+ EVT_FC_LEAVE_OBJECT: {},
+ EVT_FC_MOTION: {},
+ }
+
+ def _RaiseMouseEvent(self, Event, EventType):
+ """
+ This is called in various other places to raise a Mouse Event
+ """
+ pt = self.PixelToWorld( Event.GetPosition() )
+ evt = _MouseEvent(EventType, Event, self.GetId(), pt)
+ # called the Windows usual event handler
+ self.GetEventHandler().ProcessEvent(evt)
+
+ if wx.__version__ >= "2.8":
+ HitTestBitmapDepth = 32
+ def GetHitTestColor(self, xy):
+ if self._ForegroundHTBitmap:
+ pdata = wx.AlphaPixelData(self._ForegroundHTBitmap)
+ else:
+ pdata = wx.AlphaPixelData(self._HTBitmap)
+ if not pdata:
+ raise RuntimeError("Trouble Accessing Hit Test bitmap")
+ pacc = pdata.GetPixels()
+ pacc.MoveTo(pdata, xy[0], xy[1])
+ return pacc.Get()[:3]
+ else:
+ HitTestBitmapDepth = 24
+ #print "using pre-2.8 hit test code"
+ def GetHitTestColor(self, xy ):
+ dc = wx.MemoryDC()
+ if self._ForegroundHTBitmap:
+ dc.SelectObject(self._ForegroundHTBitmap)
+ else:
+ dc.SelectObject(self._HTBitmap)
+ hitcolor = dc.GetPixelPoint( xy )
+ return hitcolor.Get()
+ def UnBindAll(self):
+ """
+ Removes all bindings to Objects
+ """
+ self.HitDict = None
+
+ def _CallHitCallback(self, Object, xy, HitEvent):
+ """
+ a little book keeping to be done when a callback is called
+ """
+ Object.HitCoords = self.PixelToWorld( xy )
+ Object.HitCoordsPixel = xy
+ Object.CallBackFuncs[HitEvent](Object)
+
+ def HitTest(self, event, HitEvent):
+ """
+ Does a hit test on objects that are "hit-able"
+
+ If an object is hit, its event handler is called,
+ and this method returns True
+
+ If no object is hit, this method returns False.
+
+ If the event is outside the Window, no object will be considered hit
+ """
+ if self.HitDict:
+ # check if there are any objects in the dict for this event
+ if self.HitDict[ HitEvent ]:
+ xy = event.GetPosition()
+ winsize = self.Size
+ if not (xy[0] < 0 or xy[1] < 0 or xy[0] > winsize[0] or xy[1] > winsize[1]):
+ # The mouse event is in the Window
+ color = self.GetHitTestColor( xy )
+ if color in self.HitDict[ HitEvent ]:
+ Object = self.HitDict[ HitEvent ][color]
+ self._CallHitCallback(Object, xy, HitEvent)
+ return True
+ return False
+
+
+ def MouseOverTest(self, event):
+ ##fixme: Can this be cleaned up?
+ if (self.HitDict and
+ (self.HitDict[EVT_FC_ENTER_OBJECT ] or
+ self.HitDict[EVT_FC_LEAVE_OBJECT ] )
+ ):
+ xy = event.GetPosition()
+ color = self.GetHitTestColor( xy )
+ OldObject = self.ObjectUnderMouse
+ ObjectCallbackCalled = False
+ if color in self.HitDict[ EVT_FC_ENTER_OBJECT ]:
+ Object = self.HitDict[ EVT_FC_ENTER_OBJECT][color]
+ if (OldObject is None):
+ try:
+ self._CallHitCallback(Object, xy, EVT_FC_ENTER_OBJECT)
+ ObjectCallbackCalled = True
+ except KeyError:
+ pass # this means the enter event isn't bound for that object
+ elif OldObject == Object: # the mouse is still on the same object
+ pass
+ ## Is the mouse on a different object as it was...
+ elif not (Object == OldObject):
+ # call the leave object callback
+ try:
+ self._CallHitCallback(OldObject, xy, EVT_FC_LEAVE_OBJECT)
+ ObjectCallbackCalled = True
+ except KeyError:
+ pass # this means the leave event isn't bound for that object
+ try:
+ self._CallHitCallback(Object, xy, EVT_FC_ENTER_OBJECT)
+ ObjectCallbackCalled = True
+ except KeyError:
+ pass # this means the enter event isn't bound for that object
+ ## set the new object under mouse
+ self.ObjectUnderMouse = Object
+ elif color in self.HitDict[ EVT_FC_LEAVE_OBJECT ]:
+ Object = self.HitDict[ EVT_FC_LEAVE_OBJECT][color]
+ self.ObjectUnderMouse = Object
+ else:
+ # no objects under mouse bound to mouse-over events
+ self.ObjectUnderMouse = None
+ if OldObject:
+ try:
+ ## Add the hit coords to the Object
+ self._CallHitCallback(OldObject, xy, EVT_FC_LEAVE_OBJECT)
+ ObjectCallbackCalled = True
+ except KeyError:
+ pass # this means the leave event isn't bound for that object
+ return ObjectCallbackCalled
+ return False
+
+ ## fixme: There is a lot of repeated code here
+ ## Is there a better way?
+ ## probably -- shouldn't there always be a GUIMode?
+ ## there cvould be a null GUI Mode, and use that instead of None
+ def LeftDoubleClickEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnLeftDouble(event)
+ event.Skip()
+
+ def MiddleDownEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnMiddleDown(event)
+ event.Skip()
+
+ def MiddleUpEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnMiddleUp(event)
+ event.Skip()
+
+ def MiddleDoubleClickEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnMiddleDouble(event)
+ event.Skip()
+
+ def RightDoubleCLickEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnRightDouble(event)
+ event.Skip()
+
+ def WheelEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnWheel(event)
+ event.Skip()
+
+ def LeftDownEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnLeftDown(event)
+ event.Skip()
+
+ def LeftUpEvent(self, event):
+ if self.HasCapture():
+ self.ReleaseMouse()
+ if self.GUIMode:
+ self.GUIMode.OnLeftUp(event)
+ event.Skip()
+
+ def MotionEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnMove(event)
+ event.Skip()
+
+ def RightDownEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnRightDown(event)
+ event.Skip()
+
+ def RightUpEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnRightUp(event)
+ event.Skip()
+
+ def KeyDownEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnKeyDown(event)
+ event.Skip()
+
+ def KeyUpEvent(self, event):
+ if self.GUIMode:
+ self.GUIMode.OnKeyUp(event)
+ event.Skip()
+
+ def MakeNewBuffers(self):
+ ##fixme: this looks like tortured logic!
+ self._BackgroundDirty = True
+ # Make new offscreen bitmap:
+ self._Buffer = wx.EmptyBitmap(*self.PanelSize)
+ if self._ForeDrawList:
+ self._ForegroundBuffer = wx.EmptyBitmap(*self.PanelSize)
+ if self.UseHitTest:
+ self.MakeNewForegroundHTBitmap()
+ else:
+ self._ForegroundHTBitmap = None
+ else:
+ self._ForegroundBuffer = None
+ self._ForegroundHTBitmap = None
+
+ if self.UseHitTest:
+ self.MakeNewHTBitmap()
+ else:
+ self._HTBitmap = None
+ self._ForegroundHTBitmap = None
+
+ def MakeNewHTBitmap(self):
+ """
+ Off screen Bitmap used for Hit tests on background objects
+
+ """
+ self._HTBitmap = wx.EmptyBitmap(self.PanelSize[0],
+ self.PanelSize[1],
+ depth=self.HitTestBitmapDepth)
+
+ def MakeNewForegroundHTBitmap(self):
+ ## Note: the foreground and backround HT bitmaps are in separate functions
+ ## so that they can be created separate --i.e. when a foreground is
+ ## added after the backgound is drawn
+ """
+ Off screen Bitmap used for Hit tests on foreground objects
+
+ """
+ self._ForegroundHTBitmap = wx.EmptyBitmap(self.PanelSize[0],
+ self.PanelSize[1],
+ depth=self.HitTestBitmapDepth)
+
+ def OnSize(self, event=None):
+ self.InitializePanel()
+ #self.SizeTimer.Start(50, oneShot=True)
+ self.OnSizeTimer()
+
+ def OnSizeTimer(self, event=None):
+ self.MakeNewBuffers()
+ self.Draw()
+
+ def InitializePanel(self):
+ PanelSize = N.array(self.GetClientSizeTuple(), N.int32)
+ self.PanelSize = N.maximum(PanelSize, (2,2)) ## OS-X sometimes gives a Size event when the panel is size (0,0)
+ self.HalfPanelSize = self.PanelSize / 2 # lrk: added for speed in WorldToPixel
+ self.AspectRatio = float(self.PanelSize[0]) / self.PanelSize[1]
+
+ def OnPaint(self, event):
+ dc = wx.PaintDC(self)
+ if self._ForegroundBuffer:
+ dc.DrawBitmap(self._ForegroundBuffer,0,0)
+ else:
+ dc.DrawBitmap(self._Buffer,0,0)
+ ## this was so that rubber band boxes and the like could get drawn here
+ ## but it looks like a wx.ClientDC is a better bet still.
+ #try:
+ # self.GUIMode.DrawOnTop(dc)
+ #except AttributeError:
+ # pass
+
+ def Draw(self, Force=False):
+ """
+
+ Canvas.Draw(Force=False)
+
+ Re-draws the canvas.
+
+ Note that the buffer will not be re-drawn unless something has
+ changed. If you change a DrawObject directly, then the canvas
+ will not know anything has changed. In this case, you can force
+ a re-draw by passing in True for the Force flag:
+
+ Canvas.Draw(Force=True)
+
+ There is a main buffer set up to double buffer the screen, so
+ you can get quick re-draws when the window gets uncovered.
+
+ If there are any objects in self._ForeDrawList, then the
+ background gets drawn to a new buffer, and the foreground
+ objects get drawn on top of it. The final result is blitted to
+ the screen, and stored for future Paint events. This is done so
+ that you can have a complicated background, but have something
+ changing on the foreground, without having to wait for the
+ background to get re-drawn. This can be used to support simple
+ animation, for instance.
+
+ """
+
+ if N.sometrue(self.PanelSize <= 2 ):
+ # it's possible for this to get called before being properly initialized.
+ return
+ if self.Debug: start = clock()
+ ScreenDC = wx.ClientDC(self)
+ ViewPortWorld = N.array(( self.PixelToWorld((0,0)),
+ self.PixelToWorld(self.PanelSize) )
+ )
+ self.ViewPortBB = N.array( ( N.minimum.reduce(ViewPortWorld),
+ N.maximum.reduce(ViewPortWorld) ) )
+
+ dc = wx.MemoryDC()
+ dc.SelectObject(self._Buffer)
+ if self._BackgroundDirty or Force:
+ dc.SetBackground(self.BackgroundBrush)
+ dc.Clear()
+ if self._HTBitmap is not None:
+ HTdc = wx.MemoryDC()
+ HTdc.SelectObject(self._HTBitmap)
+ HTdc.Clear()
+ else:
+ HTdc = None
+ if self.GridUnder is not None:
+ self.GridUnder._Draw(dc, self)
+ self._DrawObjects(dc, self._DrawList, ScreenDC, self.ViewPortBB, HTdc)
+ self._BackgroundDirty = False
+ del HTdc
+
+ if self._ForeDrawList:
+ ## If an object was just added to the Foreground, there might not yet be a buffer
+ if self._ForegroundBuffer is None:
+ self._ForegroundBuffer = wx.EmptyBitmap(self.PanelSize[0],
+ self.PanelSize[1])
+
+ dc = wx.MemoryDC() ## I got some strange errors (linewidths wrong) if I didn't make a new DC here
+ dc.SelectObject(self._ForegroundBuffer)
+ dc.DrawBitmap(self._Buffer,0,0)
+ if self._ForegroundHTBitmap is not None:
+ ForegroundHTdc = wx.MemoryDC()
+ ForegroundHTdc.SelectObject( self._ForegroundHTBitmap)
+ ForegroundHTdc.Clear()
+ if self._HTBitmap is not None:
+ #Draw the background HT buffer to the foreground HT buffer
+ ForegroundHTdc.DrawBitmap(self._HTBitmap, 0, 0)
+ else:
+ ForegroundHTdc = None
+ self._DrawObjects(dc,
+ self._ForeDrawList,
+ ScreenDC,
+ self.ViewPortBB,
+ ForegroundHTdc)
+ if self.GridOver is not None:
+ self.GridOver._Draw(dc, self)
+ ScreenDC.Blit(0, 0, self.PanelSize[0],self.PanelSize[1], dc, 0, 0)
+ # If the canvas is in the middle of a zoom or move,
+ # the Rubber Band box needs to be re-drawn
+ ##fixme: maybe GUIModes should never be None, and rather have a Do-nothing GUI-Mode.
+ if self.GUIMode is not None:
+ self.GUIMode.UpdateScreen()
+
+ if self.Debug:
+ print "Drawing took %f seconds of CPU time"%(clock()-start)
+ if self._HTBitmap is not None:
+ self._HTBitmap.SaveFile('junk.png', wx.BITMAP_TYPE_PNG)
+
+ ## Clear the font cache. If you don't do this, the X font server
+ ## starts to take up Massive amounts of memory This is mostly a
+ ## problem with very large fonts, that you get with scaled text
+ ## when zoomed in.
+ ## fixme -- this should probably be in the FLoatCanvas,
+ ## rather than DrawObject, but it works here.
+ DrawObject.FontList = {}
+
+ def _ShouldRedraw(DrawList, ViewPortBB):
+ # lrk: Returns the objects that should be redrawn
+ ## fixme: should this check be moved into the object?
+ BB2 = ViewPortBB
+ redrawlist = []
+ for Object in DrawList:
+ if Object.BoundingBox.Overlaps(BB2):
+ redrawlist.append(Object)
+ return redrawlist
+ _ShouldRedraw = staticmethod(_ShouldRedraw)
+
+ def MoveImage(self, shift, CoordType, ReDraw=True):
+ """
+ move the image in the window.
+
+ shift is an (x,y) tuple, specifying the amount to shift in each direction
+
+ It can be in any of three coordinates: Panel, Pixel, World,
+ specified by the CoordType parameter
+
+ Panel coordinates means you want to shift the image by some
+ fraction of the size of the displaed image
+
+ Pixel coordinates means you want to shift the image by some number of pixels
+
+ World coordinates mean you want to shift the image by an amount
+ in Floating point world coordinates
+
+ """
+ shift = N.asarray(shift,N.float)
+ CoordType = CoordType.lower()
+ if CoordType == 'panel':# convert from panel coordinates
+ shift = shift * N.array((-1,1),N.float) *self.PanelSize/self.TransformVector
+ elif CoordType == 'pixel': # convert from pixel coordinates
+ shift = shift/self.TransformVector
+ elif CoordType == 'world': # No conversion
+ pass
+ else:
+ raise FloatCanvasError('CoordType must be either "Panel", "Pixel", or "World"')
+
+ self.ViewPortCenter = self.ViewPortCenter + shift
+ self.MapProjectionVector = self.ProjectionFun(self.ViewPortCenter)
+ self.TransformVector = N.array((self.Scale,-self.Scale),N.float) * self.MapProjectionVector
+ self._BackgroundDirty = True
+ if ReDraw:
+ self.Draw()
+
+ def Zoom(self, factor, center = None, centerCoords="world", keepPointInPlace=False):
+
+ """
+ Zoom(factor, center) changes the amount of zoom of the image by factor.
+ If factor is greater than one, the image gets larger.
+ If factor is less than one, the image gets smaller.
+ :param factor: amount to zoom in or out If factor is greater than one,
+ the image gets larger. If factor is less than one, the
+ image gets smaller.
+ :param center: a tuple of (x,y) coordinates of the center of the viewport,
+ after zooming. If center is not given, the center will stay the same.
+
+ :param centerCoords: flag indicating whether the center given is in pixel or world
+ coords. Options are: "world" or "pixel"
+ :param keepPointInPlace: boolean flag. If False, the center point is what's given.
+ If True, the image is shifted so that the given center point
+ is kept in the same pixel space. This facilitates keeping the
+ same point under the mouse when zooming with the scroll wheel.
+ """
+ if center is None:
+ center = self.ViewPortCenter
+ centerCoords = 'world' #override input if they don't give a center point.
+
+ if centerCoords == "pixel":
+ oldpoint = self.PixelToWorld( center )
+ else:
+ oldpoint = N.array(center, N.float)
+
+ self.Scale = self.Scale*factor
+ if keepPointInPlace:
+ self.SetToNewScale(False)
+
+ if centerCoords == "pixel":
+ newpoint = self.PixelToWorld( center )
+ else:
+ newpoint = N.array(center, N.float)
+ delta = (newpoint - oldpoint)
+ self.MoveImage(-delta, 'world')
+ else:
+ self.ViewPortCenter = oldpoint
+ self.SetToNewScale()
+
+ def ZoomToBB(self, NewBB=None, DrawFlag=True, margin_adjust=0.95):
+
+ """
+
+ Zooms the image to the bounding box given, or to the bounding
+ box of all the objects on the canvas, if none is given.
+
+ :param NewBB=None: the bounding box you want to zoom in to.
+ If None, it will be calcuated from all the
+ objects on the Canvas.
+ :type NewBB: floatcanvas.utilities.BBox.BBox object (or something compatible).
+
+ :param DrawFlag=True: If True, will force a re-draw, regardless of whether
+ anythign has changed on the Canvas
+
+ :param margin_adjust=0.95: amount to adjust the scale so the BB will have a
+ bit of margin in the Canvas. 1.0 shoud be a tight fit.
+
+ :type margin_adjust: float
+
+ """
+ if NewBB is not None:
+ BoundingBox = NewBB
+ else:
+ if self.BoundingBoxDirty:
+ self._ResetBoundingBox()
+ BoundingBox = self.BoundingBox
+ if (BoundingBox is not None) and (not BoundingBox.IsNull()):
+ self.ViewPortCenter = N.array(((BoundingBox[0,0]+BoundingBox[1,0])/2,
+ (BoundingBox[0,1]+BoundingBox[1,1])/2 ),N.float_)
+ self.MapProjectionVector = self.ProjectionFun(self.ViewPortCenter)
+ # Compute the new Scale
+ BoundingBox = BoundingBox*self.MapProjectionVector # this does need to make a copy!
+ try:
+ self.Scale = min(abs(self.PanelSize[0] / (BoundingBox[1,0]-BoundingBox[0,0])),
+ abs(self.PanelSize[1] / (BoundingBox[1,1]-BoundingBox[0,1])) )*margin_adjust
+ except ZeroDivisionError: # this will happen if the BB has zero width or height
+ try: #width == 0
+ self.Scale = (self.PanelSize[0] / (BoundingBox[1,0]-BoundingBox[0,0]))*margin_adjust
+ except ZeroDivisionError:
+ try: # height == 0
+ self.Scale = (self.PanelSize[1] / (BoundingBox[1,1]-BoundingBox[0,1]))*margin_adjust
+ except ZeroDivisionError: #zero size! (must be a single point)
+ self.Scale = 1
+
+ if DrawFlag:
+ self._BackgroundDirty = True
+ else:
+ # Reset the shifting and scaling to defaults when there is no BB
+ self.ViewPortCenter= N.array( (0,0), N.float)
+ self.Scale= 1
+ self.SetToNewScale(DrawFlag=DrawFlag)
+
+ def SetToNewScale(self, DrawFlag=True):
+ Scale = self.Scale
+ if self.MinScale is not None:
+ Scale = max(Scale, self.MinScale)
+ if self.MaxScale is not None:
+ Scale = min(Scale, self.MaxScale)
+ self.MapProjectionVector = self.ProjectionFun(self.ViewPortCenter)
+ self.TransformVector = N.array((Scale,-Scale),N.float) * self.MapProjectionVector
+ self.Scale = Scale
+ self._BackgroundDirty = True
+ if DrawFlag:
+ self.Draw()
+
+ def RemoveObjects(self, Objects):
+ for Object in Objects:
+ self.RemoveObject(Object, ResetBB=False)
+ self.BoundingBoxDirty = True
+
+ def RemoveObject(self, Object, ResetBB = True):
+ ##fixme: Using the list.remove method is kind of slow
+ if Object.InForeground:
+ self._ForeDrawList.remove(Object)
+ if not self._ForeDrawList:
+ self._ForegroundBuffer = None
+ self._ForegroundHTdc = None
+ else:
+ self._DrawList.remove(Object)
+ self._BackgroundDirty = True
+ if ResetBB:
+ self.BoundingBoxDirty = True
+
+ def ClearAll(self, ResetBB=True):
+ """
+ ClearAll(ResetBB=True)
+
+ Removes all DrawObjects from the Canvas
+
+ If ResetBB is set to False, the original bounding box will remain
+
+ """
+ self._DrawList = []
+ self._ForeDrawList = []
+ self._BackgroundDirty = True
+ self.HitColorGenerator = None
+ self.UseHitTest = False
+ if ResetBB:
+ self._ResetBoundingBox()
+ self.MakeNewBuffers()
+ self.HitDict = None
+
+ def _ResetBoundingBox(self):
+ SetToNull=False
+ if self._DrawList or self._ForeDrawList:
+ bblist = []
+ for obj in self._DrawList + self._ForeDrawList:
+ if not obj.BoundingBox.IsNull():
+ bblist.append(obj.BoundingBox)
+ if bblist: # if there are only NullBBoxes in DrawLists
+ self.BoundingBox = BBox.fromBBArray(bblist)
+ else:
+ SetToNull = True
+ if self.BoundingBox.Width == 0 or self.BoundingBox.Height == 0:
+ SetToNull=True
+ else:
+ SetToNull=True
+ if SetToNull:
+ self.BoundingBox = BBox.NullBBox()
+ self.ViewPortCenter= N.array( (0,0), N.float)
+ self.TransformVector = N.array( (1,-1), N.float)
+ self.MapProjectionVector = N.array( (1,1), N.float)
+ self.Scale = 1
+ self.BoundingBoxDirty = False
+
+ def PixelToWorld(self, Points):
+ """
+ Converts coordinates from Pixel coordinates to world coordinates.
+
+ Points is a tuple of (x,y) coordinates, or a list of such tuples,
+ or a NX2 Numpy array of x,y coordinates.
+
+ """
+ return (((N.asarray(Points, N.float) -
+ (self.PanelSize/2))/self.TransformVector) +
+ self.ViewPortCenter)
+
+ def WorldToPixel(self,Coordinates):
+ """
+ This function will get passed to the drawing functions of the objects,
+ to transform from world to pixel coordinates.
+ Coordinates should be a NX2 array of (x,y) coordinates, or
+ a 2-tuple, or sequence of 2-tuples.
+ """
+ #Note: this can be called by users code for various reasons, so N.asarray is needed.
+ return (((N.asarray(Coordinates,N.float) -
+ self.ViewPortCenter)*self.TransformVector)+
+ (self.HalfPanelSize)).astype('i')
+
+ def ScaleWorldToPixel(self,Lengths):
+ """
+ This function will get passed to the drawing functions of the objects,
+ to Change a length from world to pixel coordinates.
+
+ Lengths should be a NX2 array of (x,y) coordinates, or
+ a 2-tuple, or sequence of 2-tuples.
+ """
+ return ( (N.asarray(Lengths, N.float)*self.TransformVector) ).astype('i')
+
+ def ScalePixelToWorld(self,Lengths):
+ """
+ This function computes a pair of x.y lengths,
+ to change then from pixel to world coordinates.
+
+ Lengths should be a NX2 array of (x,y) coordinates, or
+ a 2-tuple, or sequence of 2-tuples.
+ """
+ return (N.asarray(Lengths,N.float) / self.TransformVector)
+
+ def AddObject(self, obj):
+ # put in a reference to the Canvas, so remove and other stuff can work
+ obj._Canvas = self
+ if obj.InForeground:
+ self._ForeDrawList.append(obj)
+ self.UseForeground = True
+ else:
+ self._DrawList.append(obj)
+ self._BackgroundDirty = True
+ self.BoundingBoxDirty = True
+ return obj
+
+ def AddObjects(self, Objects):
+ for Object in Objects:
+ self.AddObject(Object)
+
+ def _DrawObjects(self, dc, DrawList, ScreenDC, ViewPortBB, HTdc = None):
+ """
+ This is a convenience function;
+ This function takes the list of objects and draws them to specified
+ device context.
+ """
+ dc.SetBackground(self.BackgroundBrush)
+ dc.BeginDrawing()
+ #i = 0
+ PanelSize0, PanelSize1 = self.PanelSize # for speed
+ WorldToPixel = self.WorldToPixel # for speed
+ ScaleWorldToPixel = self.ScaleWorldToPixel # for speed
+ Blit = ScreenDC.Blit # for speed
+ NumBetweenBlits = self.NumBetweenBlits # for speed
+ for i, Object in enumerate(self._ShouldRedraw(DrawList, ViewPortBB)):
+ if Object.Visible:
+ Object._Draw(dc, WorldToPixel, ScaleWorldToPixel, HTdc)
+ if (i+1) % NumBetweenBlits == 0:
+ Blit(0, 0, PanelSize0, PanelSize1, dc, 0, 0)
+ dc.EndDrawing()
+
+ def SaveAsImage(self, filename, ImageType=wx.BITMAP_TYPE_PNG):
+ """
+
+ Saves the current image as an image file. The default is in the
+ PNG format. Other formats can be specified using the wx flags:
+
+ wx.BITMAP_TYPE_PNG
+ wx.BITMAP_TYPE_JPG
+ wx.BITMAP_TYPE_BMP
+ wx.BITMAP_TYPE_XBM
+ wx.BITMAP_TYPE_XPM
+ etc. (see the wx docs for the complete list)
+
+ """
+
+ self._Buffer.SaveFile(filename, ImageType)
+
+
+def _makeFloatCanvasAddMethods(): ## lrk's code for doing this in module __init__
+ classnames = ["Circle", "Ellipse", "Arc", "Rectangle", "ScaledText", "Polygon",
+ "Line", "Text", "PointSet","Point", "Arrow", "ArrowLine", "ScaledTextBox",
+ "SquarePoint","Bitmap", "ScaledBitmap", "ScaledBitmap2", "Spline", "Group"]
+ for classname in classnames:
+ klass = globals()[classname]
+ def getaddshapemethod(klass=klass):
+ def addshape(self, *args, **kwargs):
+ Object = klass(*args, **kwargs)
+ self.AddObject(Object)
+ return Object
+ return addshape
+ addshapemethod = getaddshapemethod()
+ methodname = "Add" + classname
+ setattr(FloatCanvas, methodname, addshapemethod)
+ docstring = "Creates %s and adds its reference to the canvas.\n" % classname
+ docstring += "Argument protocol same as %s class" % classname
+ if klass.__doc__:
+ docstring += ", whose docstring is:\n%s" % klass.__doc__
+ FloatCanvas.__dict__[methodname].__doc__ = docstring
+
+_makeFloatCanvasAddMethods()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/GUIMode.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/GUIMode.py
new file mode 100644
index 0000000..fac9dbf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/GUIMode.py
@@ -0,0 +1,378 @@
+#!/usr/bin/env python2
+"""
+
+Module that holds the GUI modes used by FloatCanvas
+
+Note that this can only be imported after a wx.App() has been created.
+
+This approach was inspired by Christian Blouin, who also wrote the initial
+version of the code.
+
+"""
+
+import wx
+## fixme: events should live in their own module, so all of FloatCanvas
+## wouldn't have to be imported here.
+import FloatCanvas, Resources
+from Utilities import BBox
+import numpy as N
+
+class Cursors(object):
+ """
+ Class to hold the standard Cursors
+
+ """
+ def __init__(self):
+ if "wxMac" in wx.PlatformInfo: # use 16X16 cursors for wxMac
+ self.HandCursor = wx.CursorFromImage(Resources.getHand16Image())
+ self.GrabHandCursor = wx.CursorFromImage(Resources.getGrabHand16Image())
+
+ img = Resources.getMagPlus16Image()
+ img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6)
+ img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 6)
+ self.MagPlusCursor = wx.CursorFromImage(img)
+
+ img = Resources.getMagMinus16Image()
+ img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6)
+ img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 6)
+ self.MagMinusCursor = wx.CursorFromImage(img)
+ else: # use 24X24 cursors for GTK and Windows
+ self.HandCursor = wx.CursorFromImage(Resources.getHandImage())
+ self.GrabHandCursor = wx.CursorFromImage(Resources.getGrabHandImage())
+
+ img = Resources.getMagPlusImage()
+ img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 9)
+ img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 9)
+ self.MagPlusCursor = wx.CursorFromImage(img)
+
+ img = Resources.getMagMinusImage()
+ img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 9)
+ img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 9)
+ self.MagMinusCursor = wx.CursorFromImage(img)
+
+
+class GUIBase(object):
+ """
+ Basic Mouse mode and baseclass for other GUImode.
+
+ This one does nothing with any event
+
+ """
+ def __init__(self, Canvas=None):
+ self.Canvas = Canvas # set the FloatCanvas for the mode
+ # it gets set when the Mode is set on the Canvas.
+ self.Cursors = Cursors()
+
+ Cursor = wx.NullCursor
+ def UnSet(self):
+ """
+ this method gets called by FloatCanvas when a new mode is being set
+ on the Canvas
+ """
+ pass
+ # Handlers
+ def OnLeftDown(self, event):
+ pass
+ def OnLeftUp(self, event):
+ pass
+ def OnLeftDouble(self, event):
+ pass
+ def OnRightDown(self, event):
+ pass
+ def OnRightUp(self, event):
+ pass
+ def OnRightDouble(self, event):
+ pass
+ def OnMiddleDown(self, event):
+ pass
+ def OnMiddleUp(self, event):
+ pass
+ def OnMiddleDouble(self, event):
+ pass
+ def OnWheel(self, event):
+ pass
+ def OnMove(self, event):
+ pass
+ def OnKeyDown(self, event):
+ pass
+ def OnKeyUp(self, event):
+ pass
+ def UpdateScreen(self):
+ """
+ Update gets called if the screen has been repainted in the middle of a zoom in
+ so the Rubber Band Box can get updated. Other GUIModes may require something similar
+ """
+ pass
+
+## some mix-ins for use with the other modes:
+class ZoomWithMouseWheel():
+ def OnWheel(self, event):
+ point = event.Position
+ if event.GetWheelRotation() < 0:
+ self.Canvas.Zoom(0.9, point, centerCoords = "pixel", keepPointInPlace=True)
+ else:
+ self.Canvas.Zoom(1.1, point, centerCoords = "pixel", keepPointInPlace=True)
+
+
+class GUIMouse(GUIBase):
+ """
+
+ Mouse mode checks for a hit test, and if nothing is hit,
+ raises a FloatCanvas mouse event for each event.
+
+ """
+
+ Cursor = wx.NullCursor
+
+ # Handlers
+ def OnLeftDown(self, event):
+ EventType = FloatCanvas.EVT_FC_LEFT_DOWN
+ if not self.Canvas.HitTest(event, EventType):
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+ def OnLeftUp(self, event):
+ EventType = FloatCanvas.EVT_FC_LEFT_UP
+ if not self.Canvas.HitTest(event, EventType):
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+ def OnLeftDouble(self, event):
+ EventType = FloatCanvas.EVT_FC_LEFT_DCLICK
+ if not self.Canvas.HitTest(event, EventType):
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+ def OnMiddleDown(self, event):
+ EventType = FloatCanvas.EVT_FC_MIDDLE_DOWN
+ if not self.Canvas.HitTest(event, EventType):
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+ def OnMiddleUp(self, event):
+ EventType = FloatCanvas.EVT_FC_MIDDLE_UP
+ if not self.Canvas.HitTest(event, EventType):
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+ def OnMiddleDouble(self, event):
+ EventType = FloatCanvas.EVT_FC_MIDDLE_DCLICK
+ if not self.Canvas.HitTest(event, EventType):
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+ def OnRightDown(self, event):
+ EventType = FloatCanvas.EVT_FC_RIGHT_DOWN
+ if not self.Canvas.HitTest(event, EventType):
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+ def OnRightUp(self, event):
+ EventType = FloatCanvas.EVT_FC_RIGHT_UP
+ if not self.Canvas.HitTest(event, EventType):
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+ def OnRightDouble(self, event):
+ EventType = FloatCanvas.EVT_FC_RIGHT_DCLICK
+ if not self.Canvas.HitTest(event, EventType):
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+ def OnWheel(self, event):
+ EventType = FloatCanvas.EVT_FC_MOUSEWHEEL
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+ def OnMove(self, event):
+ ## The Move event always gets raised, even if there is a hit-test
+ EventType = FloatCanvas.EVT_FC_MOTION
+ # process the object hit test for EVT_MOTION bindings
+ self.Canvas.HitTest(event, EventType)
+ # process enter and leave events
+ self.Canvas.MouseOverTest(event)
+ # then raise the event on the canvas
+ self.Canvas._RaiseMouseEvent(event, EventType)
+
+
+class GUIMove(ZoomWithMouseWheel, GUIBase):
+ """
+ Mode that moves the image (pans).
+ It doesn't change any coordinates, it only changes what the viewport is
+ """
+ def __init__(self, canvas=None):
+ GUIBase.__init__(self, canvas)
+ self.Cursor = self.Cursors.HandCursor
+ self.GrabCursor = self.Cursors.GrabHandCursor
+ self.StartMove = None
+ self.MidMove = None
+ self.PrevMoveXY = None
+
+ ## timer to give a delay when moving so that buffers aren't re-built too many times.
+ self.MoveTimer = wx.PyTimer(self.OnMoveTimer)
+
+ def OnLeftDown(self, event):
+ self.Canvas.SetCursor(self.GrabCursor)
+ self.Canvas.CaptureMouse()
+ self.StartMove = N.array( event.GetPosition() )
+ self.MidMove = self.StartMove
+ self.PrevMoveXY = (0,0)
+
+ def OnLeftUp(self, event):
+ self.Canvas.SetCursor(self.Cursor)
+ if self.StartMove is not None:
+ self.EndMove = N.array(event.GetPosition())
+ DiffMove = self.MidMove-self.EndMove
+ self.Canvas.MoveImage(DiffMove, 'Pixel', ReDraw=True)
+
+ def OnMove(self, event):
+ # Always raise the Move event.
+ self.Canvas._RaiseMouseEvent(event, FloatCanvas.EVT_FC_MOTION)
+ if event.Dragging() and event.LeftIsDown() and not self.StartMove is None:
+ self.EndMove = N.array(event.GetPosition())
+ self.MoveImage(event)
+ DiffMove = self.MidMove-self.EndMove
+ self.Canvas.MoveImage(DiffMove, 'Pixel', ReDraw=False)# reset the canvas without re-drawing
+ self.MidMove = self.EndMove
+ self.MoveTimer.Start(30, oneShot=True)
+
+ def OnMoveTimer(self, event=None):
+ self.Canvas.Draw()
+
+ def UpdateScreen(self):
+ ## The screen has been re-drawn, so StartMove needs to be reset.
+ self.StartMove = self.MidMove
+
+ def MoveImage(self, event ):
+ #xy1 = N.array( event.GetPosition() )
+ xy1 = self.EndMove
+ wh = self.Canvas.PanelSize
+ xy_tl = xy1 - self.StartMove
+ dc = wx.ClientDC(self.Canvas)
+ dc.BeginDrawing()
+ x1,y1 = self.PrevMoveXY
+ x2,y2 = xy_tl
+ w,h = self.Canvas.PanelSize
+ ##fixme: This sure could be cleaner!
+ ## This is all to fill in the background with the background color
+ ## without flashing as the image moves.
+ if x2 > x1 and y2 > y1:
+ xa = xb = x1
+ ya = yb = y1
+ wa = w
+ ha = y2 - y1
+ wb = x2- x1
+ hb = h
+ elif x2 > x1 and y2 <= y1:
+ xa = x1
+ ya = y1
+ wa = x2 - x1
+ ha = h
+ xb = x1
+ yb = y2 + h
+ wb = w
+ hb = y1 - y2
+ elif x2 <= x1 and y2 > y1:
+ xa = x1
+ ya = y1
+ wa = w
+ ha = y2 - y1
+ xb = x2 + w
+ yb = y1
+ wb = x1 - x2
+ hb = h - y2 + y1
+ elif x2 <= x1 and y2 <= y1:
+ xa = x2 + w
+ ya = y1
+ wa = x1 - x2
+ ha = h
+ xb = x1
+ yb = y2 + h
+ wb = w
+ hb = y1 - y2
+
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(self.Canvas.BackgroundBrush)
+ dc.DrawRectangle(xa, ya, wa, ha)
+ dc.DrawRectangle(xb, yb, wb, hb)
+ self.PrevMoveXY = xy_tl
+ if self.Canvas._ForeDrawList:
+ dc.DrawBitmapPoint(self.Canvas._ForegroundBuffer,xy_tl)
+ else:
+ dc.DrawBitmapPoint(self.Canvas._Buffer,xy_tl)
+ dc.EndDrawing()
+ #self.Canvas.Update()
+
+class GUIZoomIn(ZoomWithMouseWheel, GUIBase):
+
+ def __init__(self, canvas=None):
+ GUIBase.__init__(self, canvas)
+ self.StartRBBox = None
+ self.PrevRBBox = None
+ self.Cursor = self.Cursors.MagPlusCursor
+
+ def OnLeftDown(self, event):
+ self.StartRBBox = N.array( event.GetPosition() )
+ self.PrevRBBox = None
+ self.Canvas.CaptureMouse()
+
+ def OnLeftUp(self, event):
+ if event.LeftUp() and not self.StartRBBox is None:
+ self.PrevRBBox = None
+ EndRBBox = event.GetPosition()
+ StartRBBox = self.StartRBBox
+ # if mouse has moved less that ten pixels, don't use the box.
+ if ( abs(StartRBBox[0] - EndRBBox[0]) > 10
+ and abs(StartRBBox[1] - EndRBBox[1]) > 10 ):
+ EndRBBox = self.Canvas.PixelToWorld(EndRBBox)
+ StartRBBox = self.Canvas.PixelToWorld(StartRBBox)
+ self.Canvas.ZoomToBB( BBox.fromPoints(N.r_[EndRBBox,StartRBBox]) )
+ else:
+ Center = self.Canvas.PixelToWorld(StartRBBox)
+ self.Canvas.Zoom(1.5,Center)
+ self.StartRBBox = None
+
+ def OnMove(self, event):
+ # Always raise the Move event.
+ self.Canvas._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
+ if event.Dragging() and event.LeftIsDown() and not (self.StartRBBox is None):
+ xy0 = self.StartRBBox
+ xy1 = N.array( event.GetPosition() )
+ wh = abs(xy1 - xy0)
+ wh[0] = max(wh[0], int(wh[1]*self.Canvas.AspectRatio))
+ wh[1] = int(wh[0] / self.Canvas.AspectRatio)
+ xy_c = (xy0 + xy1) / 2
+ dc = wx.ClientDC(self.Canvas)
+ dc.BeginDrawing()
+ dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetLogicalFunction(wx.XOR)
+ if self.PrevRBBox:
+ dc.DrawRectanglePointSize(*self.PrevRBBox)
+ self.PrevRBBox = ( xy_c - wh/2, wh )
+ dc.DrawRectanglePointSize( *self.PrevRBBox )
+ dc.EndDrawing()
+
+ def UpdateScreen(self):
+ """
+ Update gets called if the screen has been repainted in the middle of a zoom in
+ so the Rubber Band Box can get updated
+ """
+ #if False:
+ if self.PrevRBBox is not None:
+ dc = wx.ClientDC(self.Canvas)
+ dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetLogicalFunction(wx.XOR)
+ dc.DrawRectanglePointSize(*self.PrevRBBox)
+
+ def OnRightDown(self, event):
+ self.Canvas.Zoom(1/1.5, event.GetPosition(), centerCoords="pixel")
+
+
+class GUIZoomOut(ZoomWithMouseWheel, GUIBase):
+
+ def __init__(self, Canvas=None):
+ GUIBase.__init__(self, Canvas)
+ self.Cursor = self.Cursors.MagMinusCursor
+
+ def OnLeftDown(self, event):
+ self.Canvas.Zoom(1/1.5, event.GetPosition(), centerCoords="pixel")
+
+ def OnRightDown(self, event):
+ self.Canvas.Zoom(1.5, event.GetPosition(), centerCoords="pixel")
+
+ def OnMove(self, event):
+ # Always raise the Move event.
+ self.Canvas._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/NavCanvas.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/NavCanvas.py
new file mode 100644
index 0000000..8c31b10
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/NavCanvas.py
@@ -0,0 +1,93 @@
+"""
+A Panel that includes the FloatCanvas and Navigation controls
+
+"""
+
+import wx
+import FloatCanvas, Resources, GUIMode
+
+class NavCanvas(wx.Panel):
+ """
+ NavCanvas.py
+
+ This is a high level window that encloses the FloatCanvas in a panel
+ and adds a Navigation toolbar.
+
+ """
+
+ def __init__(self,
+ parent,
+ id = wx.ID_ANY,
+ size = wx.DefaultSize,
+ **kwargs): # The rest just get passed into FloatCanvas
+ wx.Panel.__init__(self, parent, id, size=size)
+
+ self.Modes = [("Pointer", GUIMode.GUIMouse(), Resources.getPointerBitmap()),
+ ("Zoom In", GUIMode.GUIZoomIn(), Resources.getMagPlusBitmap()),
+ ("Zoom Out", GUIMode.GUIZoomOut(), Resources.getMagMinusBitmap()),
+ ("Pan", GUIMode.GUIMove(), Resources.getHandBitmap()),
+ ]
+
+ self.BuildToolbar()
+ ## Create the vertical sizer for the toolbar and Panel
+ box = wx.BoxSizer(wx.VERTICAL)
+ box.Add(self.ToolBar, 0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4)
+
+ self.Canvas = FloatCanvas.FloatCanvas(self, **kwargs)
+ box.Add(self.Canvas, 1, wx.GROW)
+
+ self.SetSizerAndFit(box)
+
+ # default to first mode
+ #self.ToolBar.ToggleTool(self.PointerTool.GetId(), True)
+ self.Canvas.SetMode(self.Modes[0][1])
+
+ return None
+
+ def BuildToolbar(self):
+ """
+ This is here so it can be over-ridden in a ssubclass, to add extra tools, etc
+ """
+ tb = wx.ToolBar(self)
+ self.ToolBar = tb
+ tb.SetToolBitmapSize((24,24))
+ self.AddToolbarModeButtons(tb, self.Modes)
+ self.AddToolbarZoomButton(tb)
+ tb.Realize()
+ ## fixme: remove this when the bug is fixed!
+ #wx.CallAfter(self.HideShowHack) # this required on wxPython 2.8.3 on OS-X
+
+ def AddToolbarModeButtons(self, tb, Modes):
+ self.ModesDict = {}
+ for Mode in Modes:
+ tool = tb.AddRadioTool(wx.ID_ANY, shortHelp=Mode[0], bitmap=Mode[2])
+ self.Bind(wx.EVT_TOOL, self.SetMode, tool)
+ self.ModesDict[tool.GetId()]=Mode[1]
+ #self.ZoomOutTool = tb.AddRadioTool(wx.ID_ANY, bitmap=Resources.getMagMinusBitmap(), shortHelp = "Zoom Out")
+ #self.Bind(wx.EVT_TOOL, lambda evt : self.SetMode(Mode=self.GUIZoomOut), self.ZoomOutTool)
+
+ def AddToolbarZoomButton(self, tb):
+ tb.AddSeparator()
+
+ self.ZoomButton = wx.Button(tb, label="Zoom To Fit")
+ tb.AddControl(self.ZoomButton)
+ self.ZoomButton.Bind(wx.EVT_BUTTON, self.ZoomToFit)
+
+
+ def HideShowHack(self):
+ ##fixme: remove this when the bug is fixed!
+ """
+ Hack to hide and show button on toolbar to get around OS-X bug on
+ wxPython2.8 on OS-X
+ """
+ self.ZoomButton.Hide()
+ self.ZoomButton.Show()
+
+ def SetMode(self, event):
+ Mode = self.ModesDict[event.GetId()]
+ self.Canvas.SetMode(Mode)
+
+ def ZoomToFit(self,Event):
+ self.Canvas.ZoomToBB()
+ self.Canvas.SetFocus() # Otherwise the focus stays on the Button, and wheel events are lost.
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Resources.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Resources.py
new file mode 100644
index 0000000..d3208ee
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Resources.py
@@ -0,0 +1,316 @@
+#----------------------------------------------------------------------
+# This file was generated by /usr/local/bin/img2py
+#
+from wx import ImageFromStream, BitmapFromImage
+import cStringIO, zlib
+
+
+def getMagPlusData():
+ return zlib.decompress(
+'x\xda\x01*\x01\xd5\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\
+\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\
+\x08\x08|\x08d\x88\x00\x00\x00\xe1IDATx\x9c\xb5U\xd1\x0e\xc4 \x08\xa3n\xff\
+\xff\xc5\xdb\xb8\xa7\xee<\x04\x86gFb\xb2\x88\xb6\x14\x90\x01m\x937m\x8f\x1c\
+\xd7yh\xe4k\xdb\x8e*\x01<\x05\x04\x07F\x1cU\x9d"\x19\x14\\\xe7\xa1\x1e\xf07"\
+\x90H+$?\x04\x16\x9c\xd1z\x04\x00J$m\x06\xdc\xee\x03Hku\x13\xd8C\x16\x84+"O\
+\x1b\xa2\x07\xca"\xb7\xc6sY\xbdD\x926\xf5.\xce\x06!\xd2)x\xcb^\'\x08S\xe4\
+\xe5x&5\xb4[A\xb5h\xb4j=\x9a\xc8\xf8\xecm\xd4\\\x9e\xdf\xbb?\x10\xf0P\x06\
+\x12\xed?=\xb6a\xd8=\xcd\xa2\xc8T\xd5U2t\x11\x95d\xa3"\x9aQ\x9e\x12\xb7M\x19\
+I\x9f\xff\x1e\xd8\xa63#q\xff\x07U\x8b\xd2\xd9\xa7k\xe9\xa1U\x94,\xbf\xe4\x88\
+\xe4\xf6\xaf\x12x$}\x8a\xc2Q\xf1\'\x89\xf2\x9b\xfbKE\xae\xd8\x07+\xd2\xa7c\
+\xdf\x0e\xc3D\x00\x00\x00\x00IEND\xaeB`\x82\xe2ovy' )
+
+def getMagPlusBitmap():
+ return BitmapFromImage(getMagPlusImage())
+
+def getMagPlusImage():
+ stream = cStringIO.StringIO(getMagPlusData())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getPointerData():
+ return zlib.decompress(
+"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x12 \xcc\xc1\
+\x06$\x1f\x94\xdb\xfe\x00R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4o\xf5tq\x0c\
+\xa9\x98\xb3\xf5\xdaE\xa1V\x05\x0e\x96\x0bw\xbf\xfc\xdf\xbfc\xd1\xf4\xd9\x87\
+\xa7\xa84Mw_n\xa3\xeb&\xbcS\xf4N\xa9\xdcn\x86\x03aZ\x1bWl{\xcet\x92m\xed\x8a\
+[\xd1*\x9c\x82\x91\x93\x9eMuP\xd6\xbe4\xa3\xa1\xcd\xe8\x84\xc0\t%=\x85\xe6\
+\x1d\x8d\x1aF\xac.\x132\x13\xc4^\x9ek\x14\xffx\xc6K\xa3\xd1\xcd-3\xa8\xa1M'\
+\x85\xf3Ck\xcb\xb9\x07\xd7\x7f\x85\x7f=\xa7Ts\xe2^\xff\x83\xfb\xf1\x97\x15\
+\x15\x94\xd2\xbc/5tl\t\xb3\x11\xcc\xe7\x12\xbe0;\xfa\xef7\x85X\x87\xfc{z:S'\
+\x86-}\xb6\xe0\xbb\xc2\xfc\x03\x7f\xa7\\\xf3\xb5jM/fX\xf0/\xf7\xe3\xb5\xca7\
+\x8f\xe66s\xf3\x99\xe7\xf8\x9e\xb4(\xfd\t\xf4\x00\x83\xa7\xab\x9f\xcb:\xa7\
+\x84&\x00\xc7Jh8" )
+
+def getPointerBitmap():
+ return BitmapFromImage(getPointerImage())
+
+def getPointerImage():
+ stream = cStringIO.StringIO(getPointerData())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getMagMinusData():
+ return zlib.decompress(
+'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x12 \xcc\xc1\
+\x06$\x1f\x94\xdb\xfe\x00R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xdf\xf6tq\
+\x0c\xa9\x98\xb354\x9a\xaf\xc5\x80#e\xd5w\xfb\x8d\xa7\xea.\xa6j\x06\xec\xeaU\
+Q[vE\xb2m\xba\x83\xf5\x0b_k\xe5\xe3\xc5\xf12?o\x15.\xf2b\xf0ol`V\xe63\xd6\
+\x9f\xc8\xc35\xefw\x12\xff\x0fi\xc1\x96\x0em\x15{\x16\xb1\x98E_9\x18\xa6x\
+\xdc\xe2\xdaa\xcb>\xe1\xda*\xe1\x1b\xde\x82\x15O\xfc\xa5\x9d\xdc\x83\x19\xb7\
+\xabD\xee\xed\x98dv\xd6n\r\x9b\xe3\x12\x91=\xa9\xeb\x85[4\xa3<\x9d\xd3b\x1d\
+\xb7f$]]\x96\xe1\xf2\xf8\xc6y\x8f5\xf6\xd2\xdb\x96\xe9\xdfT\\\xd5p\xbe-7\xa2\
+ls\xac\x88\xa4\xf1n\xaf6=!\xd5\x9b\xab:\xca\xa6,?\x92\x1b\xdc\xe9r\xe0\xcb\
+\xe2\xe6\x15\x13v\xfco^\xe5\xfa\xf2\xca\xcb[R[\xba&\xbd\xf5\xec\xf3\xd8U?\
+\xfd\x80\xf2EM\xae\xf0\xa3\xf3Ut\xde\x17\xed\x0b}\xd2U\xcb0Ugv\x82\xa1Q\xc7S\
+\xa07\x19<]\xfd\\\xd69%4\x01\x00+\xecq\xf9' )
+
+def getMagMinusBitmap():
+ return BitmapFromImage(getMagMinusImage())
+
+def getMagMinusImage():
+ stream = cStringIO.StringIO(getMagMinusData())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getMoveButtonData():
+ return zlib.decompress(
+'x\xda\x01,\x01\xd3\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\
+\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\
+\x08\x08|\x08d\x88\x00\x00\x00\xe3IDATx\x9c\xb5\x96\xd1\x16\x84 \x08D\x19\
+\xf5\xff\xbf\xb8\x9a}Y[\xc2P\xe8\xb4<\xaa\xcc\x15\x1c-\xa0T\x89\xc6\xb1o\x14\
+\x11)\xb5!\x9aS2\xe2\x00\x04\xc0\tz\r\xd0\xc5{d K\x80\x15\xcfB\xa6\x00O<\x03\
+q\x01+\xf1(\xa4\xb9\xe4\xda@\xf2\x92\xd8\x81fx\xea\xaa\x01p\xec\x1b{\x82N\
+\xb4\xbb\xb4\xa2\x9e\x85\x8b]\x94\xb5\xa1\x8e\xbb\xdc\x13\xa0{\x9e\xb9H+\x08\
+P\xeap\xa0\xb6\xc7:92\xdf\xd7\x94\xda\x00\x92!\xb7<\t\x92\xf1\xa7\xe2i\xb4n\
+\xc7\x7f\xb5\xa8\x89\xfc<\xaf\x17x6\x8c\xccwq\x11\xe5\xa2/\xe4\xbe\xceDh\xf1\
+\x0b@C\x9e\xd8\xd4\xcb\xc5\xec\x83c\xdb\xf2\xcaS\xa1\xc5=\xfb\xdaq\x92\xf4 \
+\xaeM\xa3g\xb2j\xe9\xf4\x1e\xac \x91\r\xb8-2\x90\xa1]Q3\x84n\xb2\xad$\xe3\
+\xb4e\x05\x06\x92\xfem\xf9\x00\x8d\xa7\xbb\x936\xe9\xf2\xae\x00\x00\x00\x00I\
+END\xaeB`\x82\xed\x9c\x836' )
+
+def getMoveButtonBitmap():
+ return BitmapFromImage(getMoveButtonImage())
+
+def getMoveButtonImage():
+ stream = cStringIO.StringIO(getMoveButtonData())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getMoveCursorData():
+ return zlib.decompress(
+"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\xc2 \xcc\xc1\
+\x06$\x8b\x02\xcc\xce\x00)\x96b'\xcf\x10\x0e \xa8\xe1H\xe9\x00\xf2\xd7z\xba8\
+\x86T\xccYz\xe5\xa0\xd0a\x05\x0e\x96\x0b\xb1_\xff\xef\xb7\xe0\xb4-)\x98\xb0\
+\xe0\xc6\xab\x8b/Ns\xf5\xa5\xac<q\xac8>(+y\xdb\xba7\x0e*\x1f\xefL\x97I\xe4b<\
+\xc0gqTg\x892\xb3\xb3NS\xd9\x01\xf1eG\xc5\x04;z\xaaK\xd6]9\xc6!c\x10\xfd&\
+\xf2\xbbH\x97P\xd0\xfa6\xdbY\xbe)\xfd\xd2g\xb3/\xf5\xad\xcd\xdab,\xb2\xa4C\
+\xc6\x91y\xc5Q\xbb\xb6\xacd\xe6}\xae[9\xff\xaf\x8d|\xbf\xcc\x7f\xc7\xabe\xfe\
+W\xf6\xffl]]\xcd\xd2\xf3\xfd\xc2\xff\t\x17WO,5o\x8a;Ys(~\x81\xa6\x19s\xf8\
+\x05\xa1\xcf\tlKg\xb0\x96\xc7\xdd\xe2_\xd9\xbe,\xc7\xc4,\xf8=\xd0\xe1\x0c\
+\x9e\xae~.\xeb\x9c\x12\x9a\x00\x0b\xb6b\x8e" )
+
+def getMoveCursorBitmap():
+ return BitmapFromImage(getMoveCursorImage())
+
+def getMoveCursorImage():
+ stream = cStringIO.StringIO(getMoveCursorData())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getMoveRLCursorData():
+ return zlib.decompress(
+"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\xc2 \xcc\xc1\
+\x06$\x8b\x02\xcc\xce\x00)\x96b'\xcf\x10\x0e \xa8\xe1H\xe9\x00\xf2{<]\x1cC*\
+\xe6\x9c\xbd\xe2\xc8\xd7\xa0\xc0\xc3r \xf6\xc1\x7f}\xb6WG\xa5Z\xa75H=\x96\
+\x93\xb6Z\xb8\xa4\x91G0_u\x8fZm\xdb\xd5I\xa9K\xdf%mMQ\xbciZU*~\xb9-\xd0\xe6C\
+\xd3Y\x07\xe5\t\xbb\xa4\xc4T.\xf9'\xcf\xe54\xfcx ,/\xc5\xd5\xb1\xeb\x84\xf2\
+\x0b\xa6\xb6\x19\x19\xbd\xc5\xcf\xd38\x19\xca>|\x9c\xad\xaa[\xb5@\x8e\xe5W\
+\xab\xad\xb3\xc3f)m\xe5\xed\x01\xedg\x9b\xc4X\xe6|[\xe3\xab\x1b\xb9\x86m\xbd\
+\xdd\x91wO\xf6\xff\xbf\xc9\xf6\xc6#\xdf|\x8be\x98\x16\xd0]\x0c\x9e\xae~.\xeb\
+\x9c\x12\x9a\x00\x11\x04M\x96" )
+
+def getMoveRLCursorBitmap():
+ return BitmapFromImage(getMoveRLCursorImage())
+
+def getMoveRLCursorImage():
+ stream = cStringIO.StringIO(getMoveRLCursorData())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getMoveUDCursorData():
+ return zlib.decompress(
+'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\xc2 \xcc\xc1\
+\x06$\x8b\x02\xcc\xce\x00)\x96b\'\xcf\x10\x0e \xa8\xe1H\xe9\x00\xf2gx\xba8\
+\x86T\xccY{\xc5\x91\xef\x88\x02\x07k@\xc0\xfb\xfaG\xdb\xf6\xcf6\x14t\xb1\x9b\
+,\xb9\xedE\xb7\xc2\xaa[\xbb6T\xbc\xe3^\xcb\x9f\xfa:\x8a5(\xb4\xf2\x1d\xb7}\
+\xa2\xb0\x90\xe0\xca\x06\xf7\x9c\xd64\x03\x83#J+\x98\xf2"\xd8\x0c/$\x88j0\
+\xb7O\xfc\x1d\xc0\xf0av\xda\x8e)?\n\rg\xc4\x0bL\x9btFz\xee\xe6\xfcG\xebo\x84\
+\xa9I\x9f1\x9d\xff\xad\xe7\xee\xb2\xf3\x8c\x06\xf9\xd7\xa6\xfc\xdcy\xf6M\x82\
+\xf6\x96\xb99\xaf#Y{\x16\x08$?\xe0\xb4JR7h\x0e:\xd3\xcc\xb3\xe8\x06WX\xdd-\
+\xf1\xf5<\x05n\xca[\xef\xfd\x01\xba\x91\xc1\xd3\xd5\xcfe\x9dSB\x13\x00/\x9bT\
+s' )
+
+def getMoveUDCursorBitmap():
+ return BitmapFromImage(getMoveUDCursorImage())
+
+def getMoveUDCursorImage():
+ stream = cStringIO.StringIO(getMoveUDCursorData())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getGrabHandData():
+ return zlib.decompress(
+'x\xda\x01Z\x01\xa5\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\
+\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\
+\x08\x08|\x08d\x88\x00\x00\x01\x11IDATx\x9c\xb5U\xd1\x12\x830\x08Kh\xff\xff\
+\x8b7\xb3\x97\xd1C\xa4Zw\x93;\x1fJ1\t\x98VJ\x92\xb5N<\x14\x04 I\x00\x80H\xb4\
+\xbd_\x8a9_{\\\x89\xf2z\x02\x18/J\x82\xb5\xce\xed\xfd\x12\xc9\x91\x03\x00_\
+\xc7\xda\x8al\x00{\xfdW\xfex\xf2zeO\x92h\xed\x80\x05@\xa45D\xc5\xb3\x98u\x12\
+\xf7\xab.\xa9\xd0k\x1eK\x95\xbb\x1a]&0\x92\xf0\'\xc6]gI\xda\tsr\xab\x8aI\x1e\
+\\\xe3\xa4\x0e\xb4*`7"\x07\x8f\xaa"x\x05\xe0\xdfo6B\xf3\x17\xe3\x98r\xf1\xaf\
+\x07\xd1Z\'%\x95\x0erW\xac\x8c\xe3\xe0\xfd\xd8AN\xae\xb8\xa3R\x9as>\x11\x8bl\
+yD\xab\x1f\xf3\xec\x1cY\x06\x89$\xbf\x80\xfb\x14\\dw\x90x\x12\xa3+\xeeD\x16%\
+I\xe3\x1c\xb8\xc7c\'\xd5Y8S\x9f\xc3Zg\xcf\x89\xe8\xaao\'\xbbk{U\xfd\xc0\xacX\
+\xab\xbb\xe8\xae\xfa)AEr\x15g\x86(\t\xfe\x19\xa4\xb5\xe9f\xfem\xde\xdd\xbf$\
+\xf8G<>\xa2\xc7\t>\tE\xfc\x8a\xf6\x8dqc\x00\x00\x00\x00IEND\xaeB`\x82\xdb\
+\xd0\x8f\n' )
+
+def getGrabHandBitmap():
+ return BitmapFromImage(getGrabHandImage())
+
+def getGrabHandImage():
+ stream = cStringIO.StringIO(getGrabHandData())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getHandData():
+ return zlib.decompress(
+'x\xda\x01Y\x01\xa6\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\
+\x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\
+\x08\x08|\x08d\x88\x00\x00\x01\x10IDATx\x9c\xad\x96\xe1\x02\xc2 \x08\x849\
+\xf5\xfd\x9fx\xdb\xf5\'\x8c!\xa8\xab\xee\x975\xe5\x83\x0b\\@\xa9\xb2\xab\xeb\
+<\xa8\xebR\x1bv\xce\xb4\'\xc1\x81OL\x92\xdc\x81\x0c\x00\x1b\x88\xa4\x94\xda\
+\xe0\x83\x8b\x88\x00\x10\x92\xcb\x8a\xca,K\x1fT\xa1\x1e\x04\xe0f_\n\x88\x02\
+\xf1:\xc3\x83>\x81\x0c\x92\x02v\xe5+\xba\xce\x83\xb7f\xb8\xd1\x9c\x8fz8\xb2*\
+\x93\xb7l\xa8\xe0\x9b\xa06\xb8]_\xe7\xc1\x01\x10U\xe1m\x98\xc9\xefm"ck\xea\
+\x1a\x80\xa0Th\xb9\xfd\x877{V*Qk\xda,\xb4\x8b\xf4;[\xa1\xcf6\xaa4\x9cd\x85X\
+\xb0\r\\j\x83\x9dd\x92\xc3 \xf6\xbd\xab\x0c2\x05\xc0p\x9a\xa7]\xf4\x14\x18]3\
+7\x80}h?\xff\xa2\xa2\xe5e\x90\xact\xaf\xe8B\x14y[4\x83|\x13\xdc\x9e\xeb\x16e\
+\x90\xa7\xf2I\rw\x91\x87d\xd7p\x96\xbd\xd70\x07\xda\xe3v\x9a\xf5\xc5\xb2\xb2\
++\xb24\xbc\xaew\xedZe\x9f\x02"\xc8J\xdb\x83\xf6oa\xf5\xb7\xa5\xbf8\x12\xffW\
+\xcf_\xbd;\xe4\x8c\x03\x10\xdb^\x00\x00\x00\x00IEND\xaeB`\x82\xd1>\x97B' )
+
+def getHandBitmap():
+ return BitmapFromImage(getHandImage())
+
+def getHandImage():
+ stream = cStringIO.StringIO(getHandData())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getGrabHand16Data():
+ return zlib.decompress(
+'x\xda\x01\x0f\x01\xf0\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\
+\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\
+\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\xc6IDATx\x9c\x9d\x92Qn\x031\x08D\x07\
+\xd6\xc7\xc0\xf7?\x98}\x8c$\xaf\x1f[,\xaf\xb5n\x9a !\r\x08\x0f\x0c\xd8\x00\
+\xfc(\xa6o-"\x000?\xc4\xaf\xedp\xc6\xe9\x00\xa5\xf7\xaeZ\xab^\xcf\x07\xb5VI\
+\xda\xe2\x8c\x13\x9b\x99\x06{N\xf2\x0e\xa7KB\x12\xe5\x13\xb9\xbdw\x0123\xc1\
+\x18\xe4dZw1\xeb\x9c1\xe7\xcb\xe1\x0e(".\x9d\xe6\xab\xec0 @%\x17\xd4Z\xd3\'\
+\xe74;K\xbd\xb5&I\xe3\x12\x7f=\xca\x8bD\x84\xc6\xe4\xa9-\xb7\xbb\xdez\xd6\
+\xbf\xd6\x00xj\xfb\xef$\xb3T?\x8a\xf9\xbc\xa0\x1d\xc9\xfa\x99f\xf3K0\x91\xbc\
+\xeb~K\xf0\x8d\x99\xf9qI\xbc\x9e\x0f\xf2\xa7e\xb7\xbb\xdc\x96 \x1f\xac\x85w9\
+I\xfa\x01\xd6\xd0\xefe\x16\x16\xb7\x9b\x00\x00\x00\x00IEND\xaeB`\x82\x0bmo\
+\xbf' )
+
+def getGrabHand16Bitmap():
+ return BitmapFromImage(getGrabHand16Image())
+
+def getGrabHand16Image():
+ stream = cStringIO.StringIO(getGrabHand16Data())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getMondrianData():
+ return zlib.decompress(
+'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\n \xcc\xc1\x04\
+$\xffH\xbc]\x0c\xa4\x98\x8b\x9d<C888n?\xf4\x7f\x00\xe4\xa6{\xba8\x86T\xccy;\
+\xd5\x93\xaf\xc1\x80\x87\xd9\xb6\xa3\xffc\xd1<\xb1u"^G\xc5\x18\x0f\xd9\xed\
+\x9a\xf8\xfc\xc2\x8e\xa9\x93Z\x97\xac\xd8)\x98\xfd\xbb\xc2\xaa\xe4z\xf0-\xa3\
+\x07\xec\r%\x0bo\x9db~^\xc50eo\x11\x7f\x1c\xc3\x0ba\xa3\x93\xacg\xae\x9f_\
+\xbf\x92\x91\xcd#K\x84\xf7\x86\xd5.\xf6\r\xcf\xad\x192u\xd6&Z~\xfekm\xf0\xa0\
+\xd27c\x9e\xa0kv\xf2\x83\x17@+\x19<]\xfd\\\xd69%4\x01\x00}A@\xa3' )
+
+def getMondrianBitmap():
+ return BitmapFromImage(getMondrianImage())
+
+def getMondrianImage():
+ stream = cStringIO.StringIO(getMondrianData())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getHand16Data():
+ return zlib.decompress(
+'x\xda\x01\x02\x01\xfd\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\
+\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\
+\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\xb9IDATx\x9c\x8dS\xd1\x0e\x84 \x0ck\
+\x87\x9f\x81\xff\xff\x93j\xef\xe12\xd8\xcd\xe1\xb9\xc4H\xc6,m\xa9\xa45\xac\
+\xea:\x0f\xf9\xda\xda\xc6r\x88\xd6\xc6\xa3T\xbdw\x01\x100\xb7\xe2<\xad\x81\
+\xce\xe0:\x0f\x91\xf3\x10I 9\xde\xb1\x1f\x19Yf\xe4\x03\xab>I\x90\x1c\xf2\xb6\
+\x95\xfex\xea\nH\x92n\x0c\x9c\xf6\xdb2`\xba\x9d\xd0!\t\xd66>\x02\xea\xbb\xfb\
+\xe3\xb4\xaf\xb3\xe3\xde\x8b3\x16\x80\xb0\xef;\x00\xa0\xf7^\xd3\xad\xb2\x10\
+\xd1\xfc\xee\xcb\xfbNL\x06KZ\x1b\x19p\xcdO\xa6\xe5Ysj\x1e\x98\x18\xdf\x7f\
+\x1f\x03!HoAn\xfe<\xeaK\xfd\xd2\x9f\xeao\xac\xa8\xae|\xba%1\xca\xc9U\xf5>\
+\x98\xdc\xd9g\xb0\x13Hr\x00\x00\x00\x00IEND\xaeB`\x82\xde\xa5p@' )
+
+def getHand16Bitmap():
+ return BitmapFromImage(getHand16Image())
+
+def getHand16Image():
+ stream = cStringIO.StringIO(getHand16Data())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getMagPlus16Data():
+ return zlib.decompress(
+"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x02 \xcc\xc1\
+\x06$\xe5?\xffO\x04R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4o\xf3tq\x0c\xa9\x98\
+358\x9a\xef\xb0\x01\xc7\xe3\x89\xc9S~\xc7oZ\xfb}c\x93\x86\xe2\xc5g\xeb\xb9\
+\x12\x93}N\xe9xI~/m\xe2ra\xbf>+9\xc4\xe8\xf3\x1dn\x06\xed\x89\x02\x05F\x06\
+\x92\x0b\x96\xdf\xeb\xea\xf1\xfa\xb6\xec\xb7U3\x03\x83\xb7`\x8d;\x13C\xc4\
+\x94\x88/\xcf\xa5\xba'\x85x\x9b\x1e\xd1\xbbb\xd6\xbc\xc7\xeb\x9e\xed\xce\x9c\
+\x8fE\nV\x12\x0e,/\xef\xef6\xf6\xd3\xbe\xf2Lvf\x87G\x8d\x96\xf1\xf1}q\xa7\
+\xc5\r7\xdf\xf3\x9d^t\xb4PFa\xd17.\xc1G\xc6\xa5_\x85\x94\x03\x8c\xab\xf7\n\
+\x9e\xcaz\xb7\xe4\xd0\xeb\xb5\x93\x7f\x19\xbf\r8\xcf\x93\xb0\xef\x10\x9f\\\
+\xde\x84\xd2\x0f\xf1L\x91G\x8c\x7f0t=<{\xccE9L\x01\xe8\x03\x06OW?\x97uN\tM\
+\x00\xe1\xf8b\xe3" )
+
+def getMagPlus16Bitmap():
+ return BitmapFromImage(getMagPlus16Image())
+
+def getMagPlus16Image():
+ stream = cStringIO.StringIO(getMagPlus16Data())
+ return ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def getMagMinus16Data():
+ return zlib.decompress(
+"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x02 \xcc\xc1\
+\x06$\xe5?\xffO\x04R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xaf\xf4tq\x0c\xa9\
+\x98\xb36\xd8Q\xa8\xc5\x80C\xf9\x80\xf1\x9b\xff\xf6+\xd3\xf8\xb5\xb75\x87\
+\xdc\x9dy\xd6P5\xd3I4`\xb2\xe0\xefmABWdfrW\x881_\x8f\x9c4g\xe6\x1c6E5}\xc6'\
+\x0f\xbc\x85\xcf?\xca\xeaPIW\x93\xe0\xcb\xdf}N\xefc\x96Aq}\xe4#mfSw\xd35\xcf\
+VL\x8a\xe5\x99\xf7(\xec\xc2\xe30\xc6\x80o\xe2?\xc3\xb2\xd7^\xedn\x9b\xe5\xa0\
+[\xb5\xe9\xd0&\x1d\x91\x89\x9fmL\x02^\x8b.\xfa\x9f\xd2)T\x93\xed\xfb-\xf7\
+\xed\xfd\xc3/\xc4<\x8d\x9a\xf4'?\x99\xff\x92\xef\xe7L\xcf\xae}a\xdfg\xc5\xe6\
+\xf4\xcd\xe7q\x9b|\xe3 \xfb\xa7#\x1bw\xe4\x1f\xcdj\x01:\x9a\xc1\xd3\xd5\xcfe\
+\x9dSB\x13\x00<\xbf^\xf7" )
+
+def getMagMinus16Bitmap():
+ return BitmapFromImage(getMagMinus16Image())
+
+def getMagMinus16Image():
+ stream = cStringIO.StringIO(getMagMinus16Data())
+ return ImageFromStream(stream)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/ScreenShot.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/ScreenShot.py
new file mode 100644
index 0000000..5f21140
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/ScreenShot.py
@@ -0,0 +1,1785 @@
+#----------------------------------------------------------------------
+# This file was generated by /usr/local/bin/img2py
+#
+from wx import ImageFromStream, BitmapFromImage
+import cStringIO, zlib
+
+
+def getScreenShotData():
+ return zlib.decompress(
+'x\xdatzeP\\M\xd0.N\xf0\xe0\x16\xdc\xdd\x12\xdc\xdd\t/\xee\xee\xee\x0e!\x10\
+\xdc\xdd\t\xee\xee\x8b\xbbC`\x91`\x8b;\xcb\xe2.\x97|_\xdd\x7f\xf7v\xd5\xd4\
+\xa9\x9a\xd3\xa7\xa7g\xba{\xe6y\xa6N\xe4we\x194d"d(((49Y\xc9\xff\xa0\xa0\xa0\
+/>\x9a\xe8\'\x84\x8f\x1e\tK\xd6\xe4\x8f\x07\x9c\x9b\xb8\x9c\xfa\xa7\x0f\xf1\
+\xffd\x1e\x01\x05E\x0e%\')\xa6\xee\x9ds\x96\xeb\x95\xf3\xc5\xe3\xf5=\x9fK\
+\xaf\xf6>\xa9\xaac\x8f\xb5\xdb\x80\x11\x89\x9a\x9aZ\x92\x9f\xb2;"\xea\xf7\
+\x00\xc6\x85\x02\xf9\xcf\xab[&O\xb1\x84R\xf2\x01|\xf8\xdeBJ\xf2\x08\x1c)qq\
+\xf2\x04\x90\x1f\xeb>\xeb\xb2\xdff\xf7\x1a\xe7\xf5\xb3\x99\xe3\xe4\xd9LkgwZ\
+\xf6\xe1\xaeK\xfcZn\x8f\x80\xc0u\xd6\xfd\xf35\xeb\x80\x01\x8d\xca\xd8\xd1\
+\xffJ\x0c\xe3\xd0\xb60\x14\xc9\xffH\xee\xd8\x1c\xbc\xbe\xcc?\xb1\xc2)Di\x8f\
+\xfb\'3\xf4C\xbc\xeb\x88\xbf\x8b\x8av\xb7W\xb0\xef\xd1\xee)bx\xcf\x19}L\xdb1\
+\xc4d\xac$\x0b\xf5\xb6\xf8\xf9\xa9\xe0\x0c\xba<\xdc\xdd)\xc5\xda\xfa<\xdc\
+\xa5\tN\x97\xeb\xc8\xce%\x080\xabu[l\xffW\xab\xe8\x9f\xd6?)\xfal\xf0\xa1\xf2\
+O\xa4)\x00?N\xffw|qw\xe8\xe5\xb9\x7fB\xf8\xeb\x08\xa6\xb6\xe8\x9fp!\xff\xbf\
+\xfc\x90\xc4w\xfe_/U#X\xff\xff\x06Q\x191j\x1c\x88\xce%x\xa9\xe6\xec\n\xfe\
+\xb7\'\xc2\x19\xee\xa9\xa0E\xe9e\xefr\x8a\x827\xab!\xe4\xe3\xeb\xa2\x9fkl\
+\xde\x8c\x85\xfb\xf9\xef\xb3Yb\xfcX\x1fV\x9d\xdcO}\x1f\xfe\xc0\xeb[\raUX#\
+\xeaj\xe1\xbb\x91\xe4\xf6\x8b\xe1C\xb6\xa5\xf0\x9ds1\xc3\xd3\x9cg\xfd\n\xf8\
+\x0b\x1d\xce\xde4{6\xef\xdc)\x96\xe7"YE|\x04\xd5\xf0/M$\xff)\xfcj\xf3\x96a\\\
+\x05y\xd7\x9db]\x7f\x98\x96\xc7w!\xc9\xa5\xdf%Z^\xfa\xe5\x7f\xf41\x19+\xc9-;\
+\x0f\x0c\xc9\xae\x80\xcc{\xf1\x16\xf9!\xb1\xb6\x11\x0f\xf7\xc2HV\xd0`H\x9et)\
+\xd7\xd9\x83\xee\xc6\x1c\x0eDt\x8dd\xec\x01\xf01\xd7p\xe7a\xbdx\xd1x\xe1\x8f\
+)\xa12\xcd\xb9f\x86G\xb3\xee\xf0\xf3\xcfm\x7fL\x02zX\x0f\xff\xb4@\xeccH\x13\
+\xb3\xf2a=;#@\xc4\xe9\x91\xa42{\x95\x1e>\xa4@\x82\x0cv\x99\xd03\xec\xbf\xae\
+\xee\xfbc\x92\x8a\x8f\xb5\xc4&\xdd\xd6\xdex\xcax\xf8\xf3\xfb#\x04\x83?\'\xaf\
+H\xd0/=\xb7W\xdb\x1c\x7f\x9d\x1e\x85\xd2b\xa5\xfb\x94\xdf\xf3\xcf\xfd\x8b[XN\
+"}\x86oTf\x9c\xb2\xf1\xd3.\xe7\xb2\x94\xdf\xc5?\xa7\xff\x12(\x9f\xae=\x13\
+\xb8k\x01>\xfaoD[\x12\xa3\xcf\xc5\x97\t\xff\x93\xfey\xba\x8e\xbf\x91Z[\xb4\
+\x1bOj!|\xf5\xa1IG\xf9\xa5\x11\xadsA`=\xbc\xc0\r\xe1\xa2\xbb\xf7\xec\xcb\xb9\
+\xc4\x1f\xa4\x1f\x1fo\xf9\xff\x18\x1c\xf1c^Z\xder}\xbd\xd3t\xd1\x1a\xc7\x0e\
+\xe9a\x93KJ\xb0\xd0\xf96m\xcc\x8e\xfa\x14\xe8\x81\x80\xef\xb4\xed\xd9\x1d\
+\xb8W\n?\xe8\xc1+1r\x02nk7\xaa\xd3\xbb\xb9\xaa\'\x91\xa1w\xaf\xf2\xbb\xf9\
+\x8d\xf2@ #\xbdc\xfcl\x89\xee\xe1X2\xac\x19\x1e\xa3\x98\xc4\x11\xeb\xc2\xb1\
+\xab\x93\xf6H\xb3\x83\x1a\xa9\xba\xa6U|\xee\xa6z\xc3\x1b\xd1<$\x98\xd5>2\x10\
+\x10\xb2bX\xe5\x9b\xf3\xcb\x06\xff{\x0e{vl\xac\xd3g;Ys\x97\')L\x87\xceq\xcd\
+\xc1\xfe\xbb\xd9\x8aV\xd2\xb2\xc19T\xd10\xbexx\x9b*\x06\xe5\x0c\x12\xf7\r\
+\x8bIA\x9ei\xa5\xec\x9b\x85\x9c\xb9\xa86\xefNP\xfcWL2\x1b\xcd{P\x19\xe3kij-\
+\xc3\x97\xab]\x82\xf1#\x18\xe1\xd2D\x1d\xadw\xad8\x0f\xf0?\x83\xfai\xcfh1?3\
+\x19\xed\x08\xdf+\xfd"\xe1m\x0e\x9f\x91\x1e<\xe0\xef\xd1\x80\r\xe8B\x1bq\x9e\
+\xba\x0eh8#J\xf0\xe6\xca:\xe8\xae.3\xcbT\xa0\x99\xc48\x07u\x9dI^\x9ekyW3\xba\
+y\xf0\xd9V\xf2H\xefu\x1d \xfd\xc1\x14D\xf2\xa1:\xa7?\xab\xd7e\x00\x91\xe9\
+\x8c@t\xcd\x0e\x82\xb0\t\x8c\x86\xe2\n\xffG\xa8|\xb9\x84e\x9b{\xf1\x07\xde\
+\x1f\xd5\xad\xf1\x19j\x14\xe0\xc9\xc9\xe6A\x83\x02duVaS\xce\xf8%\xf7\x15c71\
+\x16u\x82%\x9c>";F\xee+\xf0\xaf\xde/j\x81\xf1\xb8\xe3|\xf8\xef)\xec!\x97\x97\
+@(Y\xdc&\xed\xcc\x00\xa1w\xadK\xb58w{\x14\xfa\x8f\xe2\x91\xe8\xff\x0e\x98\
+\xf2h\x88c\x05\xfc\x887A\xf7r\x84\x85;(\xad\xbd\xc8\xa4rVz\xeb\xa6\xce\x9e\
+\x87\xf6\xee\xd8\x19u\x17X\xd5Px\x88\x0b\xd6\xcb\xc9\xedR\x7f\x93\xb8\x7f\
+\xce\x1c\xb7\xe2\xe2z\xb4\xe7\xfe\xfa\x16[\n\xd2\x9d\x9f\xde\xd5\xde\x80\xa1\
+9\xa6\xbd\xe7\xecqt\x11\xfb\xbc\x1e\xf4\xda\xef\xe5WH/\xdd\xc5\x92\xadv\xf0\
+\x98\xbc9L\xb1\xb6\x01\xcc\x13\xda\xbe\xe4\x7f\xb9\x1b\xd2=(\xa9\xdd\xcb\x89\
+\x99\x1c\x04Y\x8a\xad\x9b\xc7\x08cH6\x98\xc2@y\xea`|rw\xa1\xd5\xdb>\xc5\xeb\
+\x16\xdc\x19\xe9C\x04\x9e\xc4\xa5}O\xafeX\x90\x12\xf9\xf4\xcf5"_\xe5dSy:P\
+\xc2\x19\x0f\xdb\x86\xe0\xcc\xeb\x13\xd3n/$\xf0U\x0e\xb8\xc9\xb7\xd0\xb0\xe8\
+\xe4\x93\xfcy\xf0j\xaa\xea)\xcd\'\x19\xdd\x8f\xeb_\x18\xe4"\xdd>":\x1d\xb7\
+\xe4\xa1\xeeQ\xda\x01\xbfN\xd3\xca\xbd&|\xcf=u\xc0\xf7\x8a\xe7T\x06\x8c$\xff\
+tN\xde\xc6CD\xbcq];>\x81\xec\'@\x1b\xd2\xc7C\'\x8c:\xd6\xa5\x7fi\xc6:\xfb\
+\x8aGx \x08\xaa{\x86\xc5\xc6\xb2d\xa7\xb2\x91\x1b\x1a\xe5\xa50)\xddlv\x9d\
+\x14\x83r5\x8b\x86\xadm\xb3Q\x03f\x10\xc3\x8a\x00\xa5\xfc\xcb\x91n\xfe|f\xb9\
+\x8c+\xfd~*\x19\xc7\xbaeFP\xd5\x14\xad\x0e\x1cJ\x98$\x84\x9b\x9d\x95\xfc\x94\
+\xe0c\x8d5=\xa5\xac\x83\xd0G\xd7\xfb \x9c\xda\xe7!\xf2\xc8\xa5\xc3\x01\x0f\
+\x95s\x06\xc2\xf8\x0b\x95`\xb1\xa2\xd2\x05m\xdf\x1a042\x13\xfb\xe0&\x9b\x04\
+\xe7\xfd\x13\xd45\xbcv+\xac\x8f\x89\x0f\xa5\xfa\xd9\xa6\x89g\'\x85\xc4|d\x0f\
+\x1a\xe6Vh?\'\xd9\x85\xaf\x90\xfdbj\xd2QF ;\x0bD\x0b\xcc\x19=K)\x11K\'A)\xac\
+\xe1\xe2\x85C\xce9\x8d\x9f\xd4\xc7?I\x8c\xfc\xe7\x86\xd8\xe7\xdf\xf9xN\xbc\
+\xedC\xc4\xc6\x1ewJS\xd3\x8fL\xa2\x7f\xac\xaf\x9ck\xf4\x9c\x12{8\x85\xba7\
+\xd3\xfc\xc8m\xfd\x94\x93\x88\x050\xa1\x13\xf1\xf4\x84\xa0l\x0e\xce\xa0\x9d\
+\xda\x06AS\x02-l\t\xf6\xf2\x87I9z\x1c\xc8\xbe\xd5\xc1l\x126\xbf\xe2\xbf\xb6\
+\xdd\x19\xbb\xceT\xf5\xee\xe4\xb4\xac^\xeb\xef\xd4\xa0\xdc\x1e\x89\xe3_p(vQ\
+\xac8\xd9\x0b0\xfa\xdbAs%\xcf\x86U\xdbm$\xcfOw\x14\x0fI\x969&\xd4\xfdz\xd5T@\
+\xd1*-\xdbu\xe7\x87\xadu\x1b\xc6\xd5\xba\xb8[s\n_\xbf\xdb\xcdo\xbb\x94\xa9\
+\xe3p\xda\xbct\n1\xde\xcb\xc6\x0e*\xb8\x92\x0fU\x90p\xa2\x81,\xbd\xb1I]\x02\
+\xf9\xd8NW\x03\x1d$\xe8|c\xc2\x16j\xad]>FE\xe6\x85\x9c\x883\xdd\xa8\xb5\x17\
+\xd1,\xcc\x06jE\x0ev\x9c\xa6\x13\x175v7\xfc\x0cD$\x1c\xdc\x1bQ.\xae\xb6\xe31\
+\x88\xe3\xc6\x8a\xad\x90\xe8yoo\xf7\xd1\xae\xe9\xd4\x80<G\x93\x7fr\xc4\x7f\
+\xfa\xa6\xa3\xf3J\n\xfb^G\xc30\xe4\xf1\x86\x11T\xe1\x1f\x9a\xaa\xb3\x9cL,\
+\x90\x18O\xf4&\x1e\xc6\xb7Ir\xb6L\xb6]\xd3\x98v\x19\xb8\x01\xc9L\x07DI\xd9\
+\x18\x89\xba,\x9d\xc2\x89\xd7\xcds;\xeb\x07\xbb\x05\x0f=\x9f\x88W={\xdc)\xe0\
+~\xf5\xef\xa6\xdfju\x8f\xf65/\xfc\xd8\x8d,\xa5\xaf\xb0&\x00\x9eM5\xfb\xb0\
+\x9a\x16F\x10.-\xe9$\x1aI\x8a\xa7\xd4Y81\xd14\x0bj9\xa2\x04k\xbf]"-\xaf\x8ey\
+*L\x07\'\xc5B\xd1:\xf3\x92\xc99e\xe538\xd4\x9f\x89\x80<d\xcb\xb2\x9c5\xa7\
+\xe8\x8ea\xcd\xd9g\x8f c\xe9y,<\x9f\x92\xd3\xe3#I\x94\xf4S\xbf\xd7_y\xfc\xf0\
+5l=\xc8&\x11<[x\x90m\xac\x13\xd1\xb4\xb66\x05\xa3\xa0\x88\x0b\x99\x7f\xeb\
+\xfeQ;\x07\xc59\x93=w*\x89\x89\x19\xa9\x8d)\x04\x1cq\x96z,\xcf\xab"\x16R\x07\
+\x1a\xc5\xd9n\x89\xe6\xe3\xddq1\x9c\x81`!%\xa4\xb3\xa4\xc4\xae\x91\xd6\xfd\
+\x1eD\xa8\xefa+\xdd!\x9b\xfa\x15\xa6\xac\x98\xf7$\xbd\xe8\xdf\xf2H\xc6\x06\
+\xd2\xa8\xe54\xba\xd1pL\xees\xf1\xa2\x00y\xae\x9c\xd3\x8f\x04\xf0\xd8\x1fk\t\
+\xc8%y\x9dyG\xf8\xfb\xf7\x81\xdf\xb3"\x9dW\x02\xeby\x8d\xa7\xe2\x80\x86\x08\
+\x98q\x84]\x02\x12^\xc6\x1eKo\xb4R\xe9\xbd\x17X\xe5;%\x8eo\x00\x0f?#:<Sq\xb4\
+0\xe1\xf4\x8f\x94\xbf\x0e\t@i\xe1\xebzp\x08J|\xecW1n\x8e\x07\xe9c1\xe3VA\xcf\
+\xb4\xa0\xca74(\xc2\x03\xffR:\x16\xca\xe1b8\x87\xd7\xcd\xe3\xfc\xa7\xd8T\x11\
+\xaf+\x01(jB\xe0\x83\xed\x1cF=o\xa7\xba\xcfV8\x7f\xabs\xb9\x19\n\x14W\x12~\
+\x13\xa7\x82\xc3vt\xe1\x912\x8d\x1b|\xcb\xe3\xc1\x0f\xbbT\x15\x8fX7\xa3\xcc\
+\xbc\xda\xcahGv\x82\x04\xeaq\x92\xc4\xda\x96n\xe7\x8aS\x06::\xcd\x06Y[\xbf\
+\x89q\xceC\x0c\xeb.\xc0\xda\n:\xdb\x999J_\xdbB\xbf\xce\xeenY\x05\xdcKM\x1a\
+\xde\xe2\xcb]\x87\xdbhq\x04~\xb3})\xe3\xab\xfd\xcc\xd3\x88Y=\xc5C\xa3\n\xa9!\
+80\x00r\xe3\x81\t\xb6*\x8e\xba\x13\xfd9\x0e\x13\xd9\xc6\xf4\xbd\xa6ySo\x89\
+\xd0\xe6\x93W\xaa \x877|\xa9\x87\xbb?A$X\x12\xdaK\xc5\x19\xc2\x7f4gz{\xa7\
+\xd7~\x15\xab\xf6\xa3\xb5\xea\x0fO\xc6D:\x97\\\xdf3Wk\xb7u\xc8\x1d\xbb\xb2\
+\xc31\xada\xc0\xadL \x90\n\xd7e\xb9\xd5\xf5\x9e5\xda\xbb;\x18+\xee\xbb\x9f\
+\xdeR\x95\xb0\xb7\x9c[\xe6\xfc\xb7_\x82>\xde\x1e\xb2\x97\xa4h\xdeF\x18\xf1Aw\
+j\xf7v\x1bv[\xf1\x8e\xc1\xa79\x1c\xa1\xc46\xc2)\xed\x8e\xd2N\x06\xc0t\xa7\
+\xa0i\xc9\xd4E|\xf9\xaeQ\xe4\xf8\xf5f\xf2\xdf\xedNF\xc7\x0b8\x97\xd6\xc8\xe7\
+\xc6\xd1^\xec\x053\x81\x15\x03\xaf\xe4;L\x7f@;`\xdf\xba\xdb\x1fW\x7fVK\xb9\
+\x94\xbb\xa0\x97X_\x83\xe5\x87<\x16>\xe0\x94\xdb\x08\xfb\xfc\x90\x00Q\x8e\
+\xdc\x92W\xbb\xe0\xc3\x91\xc3\xf92\x86\xc8\xc5\xb3\x89`\xd2\x1bv-\x8a\xff\
+\xeb/\xa3p\x94E\x88V\xc0E\xd2\xe8\xaa\xe0\x17_b\xaa\x9a\xe8\x8c\x99?\x98\xb9\
+C\xfa$\xb9\xec.\x1d\xe5\x06\xac\xa7\xd6f-\xe7\x9e\xef\xbf&\x8d\x01\xb3-\xdeW\
+\x17\xb6\x8b\xed5l\x0c~w\xed\xef#X\x1f>\x89\xd2\x80\xb60\xaf\xc1LB|oW\xa6*\
+\xe0@#\xbbf\x91\xf3k\xeb\xcb3/\xad\xf6\xebLDq\xea\xda\x1dc\x8d\xc5\x01L\xc8\
+\xe2\x9a\x93\xcb\xfbq\x8c\xf0\x07\xd8#\xe4.d\xd9\xe9)$\x89\x8b\xc0X\n\tE\xd9\
+$\xafP\xc0\xaeZ\xaf\xcb\x17\xecZuzK=>\x0e\xf1\x15\xb4B\xbe\xda\xc1u\xa4\xe8\
+\xf5z\xe2\xbf\xdf\x94-uW\xa2\xc8\xb6u\xb2T\x03O\xa7\xd42\xa0*\x94\xc3\n\xfd\
+\x16ln\xb5\xe93\x18jF^A\xe5\xe9Y\x0e9\x17\xc6\x88\xfb\x87M\\\xf3\xdeg\x89\
+\xbc\xd8\xd7dM\xd8k\x9c\x96\x95\x18\x12\x16\xc1Y\x10\x83[\x87\xaf\xd7S\\\xb3\
+\xce\xf7\x1b^2\x01\x9d\xb5\r\xce&\xa7\xd2{\xc3L\xeb\xef\xd0\xa15\x83F\xfdL\
+\xdfY\xdd\xd8\x0bz\xbc\x9e\x00\t\xaa7=\xc0\x19\xf7\xf4\x0e\xf9!\x99%\x07\xd3\
+\xa1\x02\x94\xf6\x99\xfa-\xac\xcb\x8d\xcd\t2gI_\xeasW\xa7\xb0U\x0faM\x82\x08\
+\xef\xb2\xb3\x95\xa2\x89\x10\x8co\x08\xe7X\xe7\xd6\x9f\x1e\xbf\xef\x85\xdaE\
+\xfaS\xe7\x85\x14\x9cm\xd4p]\xcd}\xa0\x9e\xc1\x89\xc8|\xc8v\xec\x88t\xef\xd3\
+\xc16\x96bW\x88\x86\x0f\xb1\xfdr\x07\x1e\x95M\x97\'ur\xa3\x15\xc6G(\xfc\x94.\
+\xefHQ\xee\xa5\xff\x02T-\x12e&d\xdd\xe9\xfc\xb0\xd1\xd2;\xd8z0\x18\xa8\xbe\
+\xd1\x19\xd2\xb1\x03\xe0k\xb9\xecs\x1e:\xf8e\x99\x92Z\xf3\xfb?i\xe4-\xeau\
+\x15\xd9\x04\x84\xef\xc2\x04i:\t\xe3\xe1\x15\xccO\xe0\xe96/\x13\xdb8\xdeZ\
+\xb3g\xb0\xba\x194\xcb\xf0|\xe0\xc6\x18\x86B\x16P\x08\x87c\xb7\xed"\xe3R\x9d\
+\x11\xd9-\xf8.\x9cD\xc0\xb3\xdey{`[\x18U\xa4k\xb4\xbf\xe5@\xcc}\xfdd0\xf6\
+\x9cs\x19)\xec\x03\x12S!\xa7\xf7\x85\t\xb0\x92:\xcap\x19\xa5?\x8a\x0e\xfb\
+\xd5\xc3\xceh\xd6\xe8\xc2\xb3W\x8b\xf7\x98\x8d\xa2\xdf\xbfo\x7f\xbet`\x03\
+\xd5\xa5\xfc\xb7H\x9e\x81{>\xa07&\x11\xf9 [\x15-\xbc\x1el\x0b\xcb\xa0R\xc5\
+\xe5\xfe\x91o\\\xf6\xd6\x1b_\x15\x9e\xb2<\xa4\xb0\xd6\xb9SX\xaf\x0b\xe2p\xc8\
+\x94)\x8c\xda\x9d\x0b\xf4\x86d\x88A%\xaa\x83\x1eU\x18m\xd6\x9d\x04r\xffR6\
+\xfaa\xec\x1fx6\x19\xbe/}|\tZj\x8f69{^J=?N\x94\xae\xb4\x83\xaf@\xfb\xe5-\xd2\
+5\xb9T\xe7 \xc2+\xf2\xb0\xf5\xe0\xdc\xb9(\x93\x84{npf\xb1A\xe9 v\xc7\x12\xcb\
+\x9f\xe3x\xdb\xad\xa2\xd1XqgI\xee\\\x99\x19\xdd\xef\x9a\xd9Y[!\xfaL\x16\xa7{\
+QpW\xd1\x86\x85\x16\xfb?H?X2\x16\xa3\xd5\xf9^\xab\x19\xd6\x81*!\x03#\xed\x1b\
+\xa9\xe3\xf3|";\xe9\xb9^\x85\xc3G\x19S6\xe6\x84\xcb\x8f),\xe3H/\xa8\xda\xb7\
+\xd7\x9co[\xefq~y\x16\x04\xfe\xe3\x02\xdf\x8fg\xb5\xb3&\xe5\xbdI\xe3/\xa4u\
+\x1fJz\x0b\xc1v\xb8p\xd8\x10\xebO^\xf5`\x04\xec+\xeb\xc8\xf6\xff\x01\x8b\xcd\
+X\xb5\xd1\xdc\x040\xa5\xf1\xb7\xe9\xb2#\xa3Eb\xec\x93~\xf4C\x02)\xfb\x10%\
+\xdea\x0bwi\x84\x7f8\x9eh\xee\x8b\x02q\xa5)\xd3v\xc4\xbd1\x92\xd7\xefWk\xa4G\
+\xe7\x8e\x85\xf0Id2T\xcc\xf0m\x15\x01\xe2\n\xd5\x03\x80u<\xfa\x8d8+??\x91\
+\xa4Z\x97\x97\xc1]\xf3s\x9d\x08\xdcj\xd9d\x89p\x06j\xdb\xe4:\xfe\xe6\x0e+\
+\x19(\xc0\xb6o\xe0\xdc\x00\xae\xb4\xf7\x971\xa5\x05;r\xd3Q\x8c\xd0?\x06ui\
+\xd2\xce\x02\x91\xbd\x13\xfa\x8ey\xef\x91\x8e\xe8\x96\xbf\xe9\xd1\xbb\x03OX;\
+\xe6\xae\xa5\xe2\xac\x95\xda\x1aN\xf6 $\xb0\xb3\xdc\xf4\xa7\x91\xb1<\xa2\x13\
+\xd0+\xe4\xe3\xfdm\xb6\x07\xcf[\xd6\xbc<\xd4\xbf}\xb4\xd3c\xe6\xcb\xbf\xd2\
+\xfc*mv\xfc\x9d\xe52\xd0;\x9d\xc5vg\xc3\x88I\xf0\xaf\x8b\xa4\xc4\x10\x95\x83\
+\x11\xbf\xee\xfc\xa4\x7f\xb8\x8b}\xd3=<\xae\x0b\x81\xb7\xce\x921j\xf3kY\\\
+\xdc\xbf\\Ce,*Y\xa4\x82\xc3\x83\x04s\xbeo\xf8\xa9C\x10)w~\x07(Jl+#\xc6\xe3\n\
+\xeb\xb7W;\xb3 P\xfda\xd1]j\xffH5B\xd4\x7f\xce\x12\xc2\xf8K\xbd(\x1a7ko\xc3R\
+\x109\xde\xf6j\x8d\xc0\xe7\xf0\xe8\x0e\xad\xf9\x11\x88[\xed\xfd\xfe`|\xe8!V\
+\x01\x88\xe2m\x03\xcf\xf1u\xb8\xe7D\x88\x88AL\xeb]A\xca\x7f\xee\xb7\xe7\x8d(\
+0\xa8AE\xe3\x16\xb5\xa9J\x85\\\x9c\xff\x82\xb4p\xfdo\xb7aR\xba\xb5{\x15\xc3\
+\x82 z\x9d\x1d\xf6\x93<o@\x0c4\x1fNEt\x87?\xda7[\xc9u\xdc\xc8\xb73\xb3<\xfd\
+\x17g\xd8\xd5<\x9f\x83\xccr2\x95\xf6\xf6\x11\xc0\xf4\xf3a\xfb;\x82|\xfb\xee\
+\xee\x07iDf\x04m\x17\xea\xf5\xf0\xf7\x7f\x18\x95\x19\r\xefo\xee*\x02\xcb\x93\
+\xcd\x8cy\xe3\xb3b\x1ay\x08\xfe\xd2\x18US\xbf>\xefy>\x17[\xb1*o\xb8\xf8\xfe\
+\x91\xf64\x19\xdfHk\xe8\xdd6\xae\x16\x91~\x19\x8eIY-`\xcb\xa52\x18!4\xf1\x8d\
+\x0f\xa2X\xd9)\xf7\xde\xc9\xe4\xc10w\xb2\xfa\xf1\x9f\x14\n\xabK\x19\x9e\x03\
+\x82b\'\x18\xe3\xf1jO\x9c\x9dZ\x9a\x9d-|}\xfb\xf6\x11\xaa\xda\x15\xda\xadS-\
+\x84\xb0a\x17o&\xec\xa9\xf07`>\x82iJ\xcf\xbc\xca5\x8e|\xefYR\x97\xbf0\xf3$\
+\x07\xfep\xdb\xc9f\xb9MWw@w\xd6\xef\x8b\xff\xda{g\x90\xe8\xe8g\x06\xd66_\xf2\
+\xcb\x1e\xc0\x1f\xfe\xe2Q.\x82\x98R\xfb\xa4\x86\xd0\x8fS\x04\x95\x8f\xaa\x04\
+r\xf5\xbd\r\xe1\xd6\xf2\xad\xf3\xbe}\xb4\xaf\xa5\xfa"\xe8\xf5R\xca\x17\xd09\
+\x08\x02\xe9lz\xc78\xb0\xf9\x862\xad\x9am\xc7\x0b?Y\x8fYx\x9e\xfd\xed\x87\
+\xc5\x10\xfc\xec\x9e)\xfa\xdam0z\xca\xf4\x97\xed\xf5\xc9\xe1$ln\x02=\xbd\xff\
+3\xc4\x99\xc5h\x83\x9f\xb4\xf3\x08\xaf}&a\x87\x05\xa4\x0b\tO\xden6G$\xfa\xc3\
+\x9d\x83\xea\xa5\x0e\xe0\x91p\x08\xe8\xbc\xf0H|\xf7\x06.\xbe|\xb4W\x10\xe8\
+\x83\xc5\xd5\xfb>\xb3t-k|^\xb8\x12R\x1b\x1d\xbf\xd5,\xdc.\xd0\xdb\n\x99j\xe0\
+\xc3\x02\x13\xba\x8e\xed\xd3\x92b\x8eW\xe3R\x1a\x8aT(\x19\xaf:\xbe\xf2\xd9\
+\x7f\xddq\xf8\xf5\x9c\x94j\xf4cz\x15\xdby\x83\xd4\x8e\x07\xac\x14\x1cR\x02\
+\xf5\xef\xaeAt\xf4Pi\xf8\xfa\xbb{g\x88\x15\x99\x1fc\xb9\xb1\xc8\xd3Q\x91\xba\
+ \xd9Ck#\x89\x83\xdd\xaaG\xf5\x07y\xa8\xf6-On\xe5N\xc6*\xeba\xb5\xe70V\xfa\
+\x14\xa0\x84\xf6\rD\xc9Z\x9f\xf8\xb1Ap\x1e\xd6\xf1\xdc+!\x89(K\x9cRx\xf1\ni\
+\xf0S\xe1\x1b\xf4y\x8cP\x0f\x1e\x0bc\x84\xb61\x05l\x9fD\xffd\xd5s\xdb\xe1\
+\xd5\x13\xf1f;\xe2\x9c\xcdkg\xab\xa4$\x8d\xb1Fh\xf6\x89\xd6H\x0cK\xaeg\xd0:X\
+\xf8\x1a\x04\xfd\x0e^\x85W]\t\xfa\xba\xe2\xb5\xcb\x045\xb5}P\x0f\xc8E\x0b\
+\x93\x91\xf7j\xc8\xef8*]#O^\xa0MX\xfa\xfd\xf2\x88\xb5\x19\xe9g\xa8\xf8\xa3\
+\x80\x13r\xabdHj\xb8\xdc\\\xdc*\xc6\x7f!6\xb0\x9cD\xc0<Y\xd8\xea\xae&9\x89\
+\xe19\x97f\x90.4}\x97\xbf\xb1e\xe5"\xd34u\xe2\\\x96\xd2\xc1|]\xb8F"\xd1\x03\
+\x11\xb5\xb1`\x81\xbf\x95\xf0\xa7^E\xd5LN\xf9\xfe\x8a0\xa3\x8e\xdf\x19\xf7\
+\xd31\x18\x83\xb3\xa3\x0c^\x14\x13\x02^\xb1\xbd\xdfn\xb7uh\xf3\xf9}\xdb\xbdq\
+\x9c\x8c\x1e\x07\xb2\xaa+pF\xf4\xbd\xbf=\xc7X\x0b\xf2\x84\x8d~;\\\xa4\'\x89\
+\xfdi2\xb9\xd2wD\nAO\xff0,fp<gY\x7f\xdd\xf3,q\x9c%~\xaf}\xfeAm\x19\x0cv\xf3=\
+\xf1\xd0\x0bj\xf17*?\xc2\xfb\xef\xf2E\xacyX\x00K\x1fF\x84\xe8\xb4\x0cC\xd3\
+\xd1;\xe8Oc\x8fC\xd3=\x03\x1b:F\xdc\x05\xfcd\xbd\xf5t\x1a\x9f\xb0\x04\xcc\
+\x93\xeb\x8d\xd6\x80\xf8$cj\xc2\xf3\x08\xd4\x91\xd9f\xf0\xa5\x7f>)^\xc0\x97\
+\xf6\xbe\xd9\xcc\xff\xb9\x9b\tQ\x0c\xda\xd8\xab\xdd\xcfQ\xe0\xee\xac\xb9\x9f\
+\xa3>\x91p\xf8\x15>\xc0\x02\n\xf8\x07{\xd4\xa5\xf4\x99\x1e\xec!V"\xb7\x8a\t.\
+|\xc0\xf5v\xfd\xd3\x1eJR\x96\x99#Jf\xa2\xcdCm\xb3=}\x03~\xfe\xa2/Z\x1bn\x9b\
+\xc8\xf6@Z\xf7\x0e#2\x06\x95\x05\x1c\x93t\xed\xf7\x8e\x17\xf1\xfbf6\x95\x07\
+\xa8\x8bvPwz\xd3\x1e\xd4u\x91\xdb\xfa\xf6\x7f\x97]\x1c\xd5\xb27\x89\xc6\xbf:\
+\xab!7\x95.!\x002\'\x17\xff:\xa6\xb1\x9fb\x17\xb55\xa4\xb5zBX3\xf4sK\xaa\x1c\
+\xbe\x88\xffy\xb8KC\x7f\xd8\xbc,s\xf2\x97\xb85\x8c~\x84\x80\x8a\xb0\x9c\xfa \
+\x01\xf4\x9e\x06w_\x97\x0f\x84FZ|V\x87\xff\x0bKr\x86YE\xd6\xe5\xc6X\xdcFE\
+\x9eC\xfd\x14-\xbd6oMA$\xd9\xdb+zS\x96\x98\xe0\xbbf\xb6\x1eJJ\xfeq4\x17a\xd3\
+\xc0,\n\xbfOD\xb3\xa1[w\x82\xf0\xfc\xda\xcf\xbd\xd2#x\xb4\x85\x82\x93W\\\x06\
+\xb9\x84\t\xc6R\rS\x03[G\xe6a\xe9\xbe\xefu\xf8\xbc\x7fI%\x16ZM;.\x89\xd4\xf8\
+\xa8\x8c\xad\xc0^\xc7\xb9\xc9\xcf\x05T\xe2U=O\xdf\x9b\x0e0\xf0U\x05\xd9\xf4\
+\xbe\x81\xcf\xf9\xd8\xee\xfd\xfczX_\x8c o\x95\xcf\xaf\x07m\x13\x0f\xd7\x18"\
+\xa7\xf7\xad\xa3\xfc\x80\x1f\xf9&pL/;z\xcc#&aa\xfe\x91K\xa8\x99y\xde\tR\xec\
+\xab\x14\x05\x12\xe4\x9d\xd2\xe4%\x1d\xef*\xa3\xca\xb0\xcd\x16\x13\xee\xc5\
+\x93\xda\xd8\x16\xf6\x1c0\xe8E1\xcc?\xc8C\xfa\xa1\xa5;\x93\x84\xf17Y\x12\xfe\
+\xd6\x16O\x11"d\x04S\xa3\xfcId\x05\xe6\xa1o\x8csv7p*S\xc9R~J\xbaz4\xf5\x85\
+\xa7=0\x94\xd0\x92\x80\x07k\xc84\xe8\xf0?\xb5\xd4\x19F\xff*\xcd\xb2\xd5%:=\
+\xb6\xb7\xe9\x9f\x9fS\xae[\xfc9h)\x91D-\x19\x12\x8c\xb1;]lQ\xfa];G\xe2x\x80\
+\xa1\xd8\x92\xfa\xd1\x81.)\xc2+=c9\x87W\xd9,B\xd0\xd9\xa8kx]\x8a^\xb5-\xbb\
+\x80F\xaf\x90\x0b\xb7\x1a\xa9\xfe\xb9\xfd\x87Z\x98\x17\xe4\x89%\xb3\x02I\x91\
+(\x7f8i\x05[\xa7\xc1\x19\xab\xc1\x12\x9b\xf6\x19\xf3\x1e\x90\x08\x98\xa7\xc1\
+\\\xe52_\xe54\x07$\x17\xf0hJs\xfe\xa0\x0f.\x80t\rk\xf7\xdb\x1c\x05a\xe2_\xbf\
+\xf1\xe5\xdc\xae\x9b\x89uf\xfa\xec6\xb2J|\x9b\xe2\xe0\x05~.\x81\xeb\xc1\x81E\
+\xcfN\xfe\x86\xf2\x0e\xd7\xf7tM:DM\xd4\xa0\x80\xee\xe8\xb77\xfb\x03\xc7]\x80\
+\xb5\xeb\x97?9\xe5\xb9\xdf\xdb\xd9\xc7,1%\xcb~t\xe0\xeftR\x94\xc8\x91w\xabf"\
+\\\x0c-\x83\xbc\xea\x82\x061f,WZ\xd46 \x93\x96\n\xcd\x16\xbe=\xefM\xad\x0c\
+\xd0>kZ\xbew6\t\xc6o\xd2\xfb\xcf\x8b\xf2fz\x1e\xd7dG\xcai+O7\x0e_\x0f&\x02\
+\xd1l,\x1d1f9\x04YE2Cw\x08\xee\xf2\xbe\xac\xaa\xf7W_\x8eS[\x8d\xb8\x98._\x94\
+\xd1\x9f\xc0\x08K\xdb\xcc$2\xe4SR<\xae\x8f\x9eYJy\xafqZp\x9e\xc2\xd3~\xc1\
+\xc3\xa4\xec0B\xfe.`XX*{\xb7\xd2jE\xd5\x08\x85\x8e\xcd\xab8\x11\x12r\x1a,\
+\x91@\xd1\xa1a\xec\x9f)ZM3\x10\x8e\x08Mten\x1bE}\xc6\xb1\x1a=F\xf9\xd7\xac\
+\x8f\x94*9\xb5+\xa3\xda&\x1a\x9a\xfe\xfdl\xba\xde\xcb\x0c|RXy\xf6i\x91.\x0e\
+\xb8\xfa\xf9\x05&-G\x19\xc0_\xe3\xee\xa1[!\xa81\x9a\x16\x7f\xaf\xea{.O;\x95Q\
+\xa2;C\x03\x8a\'\xcb\x18Y\xd5!\x85v\x8f\r\x0e_k\xb0\xff8\x15.\xb6\xfc\xdd$Yo\
+D\x0b\x1dy$4\x1a$\xdd\xe2\xae\xfe\xec?~\x9f\xe8%\xcd\xce\xad\x0c\xe3\xae$Z}\
+\xf0\x96!\xec\xf53\xc3\xbe7\x10\xc9\xd4\xb8v[\x8f\xce:\x93Y\xa7$e\xfc]\xe3\
+\x93\xa3h\x11y\xd7\x91,\x99\xf04\xa3\xa7\xe5z1\xcb\x95\xe2\xb3\t\x826U\x96`\
+\xd2{7\x1c\\\xd1R>\x08cz\x97\xdd\x97\xdf\xe7\xe9>\x03\x894\xde\x1e\xafi{B\
+\xc8L\x00\xef\xdc\xe2^jz\xb3\xa1%\xc0q\xf7=i\xea=\xe8Y#\xb2$\xb1\x8e;\xdf\
+\x9d\x02\x1a\x85\xd2F\xb8\xa8\t\xc9\xf9o\'\x1a?\xe8D\xeb\xce\x96DB\x03P\xe7\
+\nk\xbf\x17\xba&\xbd+\x1d\xf9-O\xefM\x94\x00\xb5\xfdg!\x1b\xc0\x81ce\xfc\xf2\
+\x13\x8b\xf6\x9c\xf7\x96L\xe6N\xcf\x93\x1f]Xs\xff\xae%d\xa7\xe12O"\x0bX\x82K\
+]8G\x0c#\x07\xb0\xb7\x850\'ar\xb2(\xe6rjz\xfe\xa2J\xc3^zR\x1d\x18~\xa6&\xd4\
+\xc1\xa9\xcf\xee\xc3;\x0cr;\x1e\x87\xf7\xab\x92\x15o\x82J\x8a\x01\xdabt\x18\
+\x85\x13\xc6\xcd\xa6\x1c)\xde\xf6\x8e)q\xafc\xc0v\xbbpr\xa3\x05\xb3g\x98\r>\
+\xf9C\x11o\xfa\xa2\xd9Y\x95\x1dt\xb5\x0fI\x9a\xeeb\x7f\x86\x83\xb6\xf3\xc2_b\
+\xbd\xf5n\xdbK\xf9\xdbtI\xf5\x1f\'\x97\xdc\xe4\xdd\xa7\xdc\xa3[\xe7\xeb=\xe8\
+\xf8\x163\xf9\xbf[\x81\xdd\xefO\x87\xf4\x01`t\xea\x9a\xce\x06\x8c\xbae\xef\
+\x93\xe0N\xc6\x06\x1b$\x0frF\xac\xdc\xaf\xd3\xf0\xe3\xc5y\x8e\xcdb\xf2\x8d1b\
+\xa1\x7f\xf7\xdc\x19O\xf5\x12\x9f\xd1\xbbk\x80\x03\x12l\xe7\xfb7\xfbx\x8e\
+\x1d\xed\xdan\x9dRm\x02\x7f\x03\x15\x9f\x1fTf>\xcdr\xa2IS\xeft\x07\x94p13\t\
+\xa6\xec\x83\xc1a\xefW\xf1\xe9a\xdd\xef\xb2\x9f\x95I\xa5\xca\x85\xf0Z\xf5\
+\xba\x85$\x0e\x86\xdc\x91\xcaF\x1e\xa3[~\xd03\xc18)]L\xb9el\x0f)F\xe6y\'v\
+\xb9\xce\xf21\xb6\xdbV\xda\x12\x03\xebr\x07\x83\x83\xe8\x07?\x1b\x8c\xbf-;\
+\x89\x97\xfd\xe0\x18\xa2!\xde\x84/\x9c\x8d*5\x8c\x00\xab\x96F\xc2\xbe3\xc4\
+\x10\xbaC\x8b\x0c\x12h\xd1$,\x95\xeb\x7f\xda\x07\xbe\xd4\x85\x8e\x08\xc6{\
+\xa3p\x16\x7fC\xa6ne\x9al\xb3\x90u\x7fh6\xaaeK\x19\xafM\x8b<Fb\xf9\xa2\xc4\
+\xd7\x98\xef\x1d_\x85\xa3\xddU\x9c\x82\xb4<\x15\xfd\xd0\xe4\x9ekm\xfa\xbe\
+\xea\x15\xc2\xba\xcb>\xf1%\x93\xa9\xc2Q\x1a\x8a\x81\x05\x06\x9e\x0e~G`qt\x83\
+\xb8j/>/\xcfZ\xe63"7mN"\xd6\xe0\xd5\xbc}\xda\xd4\xd4\x8e\xda\x1a\xa5"\xc7\t"\
+\xb4\x82\x0c"b\x9b\xbf\xf4\xe2\xa5\xd9\xb9M#*\xdd\x1d\xd8%]\x1e7q\x9c\xc7\
+\xc6\x8bd2\xe8\x9a\xa9\xf2\x1e\xbdzau\xf7\xd9\xa3Z\xb7\xd6\x95E\xb5mO\x14(\
+\xa8\xces\xf0\xd7RV\x08\x99\xc3\x01\n&ziL\x14%\xbe\xee\x956\xc8\xdb\x8f\xeb}\
+\xd5\xfdO\xf7Y4$E5)}\xac\xa3$\x8fcA\xd6\xe0XZ\xa0\x98;\x92\xba5d\x9c\x95|\
+\x8c\xd3\xb3h\xe7\r\x1c\x1b\x02\xe4:\x89\xb4\x9bF\xef.0\x91\xe8{5\xa7\xba{\
+\xc57O\x80\xef\t\xda\xed\xf0w\x19\xc7\x81J\x0b:\xb4x;\x8d\x1a\xd6\xef\xb2\
+\xc6*$\xbf\xb8;\x94\xf1~"[KxZ\xc2\x85k\xf7]A\xad5\xe2\x8a\xedz1G\x95N\x8c; e\
+\xb4\xad\xdd}\xcd\xaf):)/s\xd3\xd3O\xcaT8\xa7\xb7\x98\xf9\x85-;\x19U\xb6|\
+\xb0\xa7\x1e@\x1c\xdf\xfdF\xa8\xe1\x97M\xcfkC^\xa1g>\xac\x04\xcc\xf4p\x84~T\
+\x03\xca\xca\xc6\x0e;z5^K\xb2\x88\x04\xeec\xebvV\xab\xab\xa4D\x9cb\xc9\xd9\
+\xcd\xf7\x80f;\xbd)\xe2\xc2\xd1\xa1\xfe$\xb0\x99\xe9\xe0L\x92\xa4\xb3\x18\
+\x1f\xc7\x88\xff\x87eZQ\x036\x1f\x84\xdc5Y8\x11n]\xfe\xf7\xa9\x11s.\xf3g\xf7\
+\xda\x90\x88\xd1+\x7f\rZ\xdef\xd7\x1c\x05\xbbY\xdb\x8f\x15\xa2#\xd2\xdd\xdb\
+\x00\x98\xa0\xa0#]dN\xa1\xda\x8c\x1a\x95\xcd\x83\xc0\xd7\xb5\xa0\xf3\xad\xf8\
+\xd3;\xc0\xa6U\xc9\x88\xdbh\t\x8a6\xbf\x1a_O\xe5\x882\xe8\x1d(\x8c\xfer\xc9\
+\x0b\x95\x1e\xe4G\x8a\x1f\xd8\xb4\xd0\xfd\xb2JS\xf7\xc7\xce\x85\xddC\x8eu3P\
+\x0c\x89r\xe3\xda\x04\x9e\xadv\xa3/\x1e\xd4\x195%>\x1b\x98\xbf\xe2\x15\xfd|+\
+\x92\x0f\x1a\x0f\n\xec\x15\xe9\xbb\xc4 \xfdwl\x157{\xb3\xfe\xbc\xb29\xf1\xd9\
+\x90\xe3\x8c\xf5\x99\xf8\x95\xf0\x87\xe2\xbb\xbf,\xf5RU\xe8i;#\xec"\xb6\x85-\
+\xadw\xa8\x11\xdeo\x1abW\x95p\x90W@\x81n\xd7\xb5\n\x83\xcau\xd8\xaf\x10|\x1b\
+_\xd7\xb03:P\x07\xeeG\xda\xb4t#p\x08%\xb8\xe9\xfef.\xca\xfc\xbb\x10\x1c\xd9\
+\x17\xef\x98;\xd85>\x81=\x9b\x06\xfb\xa6\xe9\xef\xef\xca\x89\xd2\xeb\x8c)\
+\x84\x87\xa2\xf4M\xe3\xfcx\xba\xa5\xe5u\xd5HE\x83)\xe64\xff\x87\xdd6\xd3\xc9\
+\x92$\xaf\xd0r\x05\x16\xa4\x18YV \xf4\x80]\xde\xd2\x16\x06\xc3\xdf\xe1[\xa4\
+\x8b\xa5\xe1\xbbs\x9b\xdf\x13v\x90\xc0\xd4Nf\xe6\'\x17\xae\x97\xa5\x0e\xcb\
+\xa8)b\xe8j\xe7\x1f1\xfc\xc1\x85\xbb\x94\x08\xa9\xb8t\xe5oN\xafW\x08Q\xcbFu\
+\xbau"\xb5\xd7\xce5\x17\xb2\xe3\x158c\x15\xea\xad\xa7\x95C\x96o\xa6,\xbbA\
+\x86}F\xdcgtL4yMe\xf8\x17Mu5C\xfe\xf3#\xf9\xe7\xef\xa14Z\x8a;a\x8bMG\xde\x9d\
+\xc1\x01\xc4)\xd1\x0e3\x95\x97\xfe\xa7\xabM\x8f\xcffk+W\xf1\x9c9\xe8\x91\xeb\
+I8\x8e\x01g\x82\xc8l"\xe1\x13\x0b\xca\xa15\xc4\x1c\xc3D\xda\xd7\xe1\xd1\xb2\
+\x93*{\xe1A+cw\xbb\xdfp\xcci\xaf\xd7:\xd9\xb6+\xf7\x87\xf5/6\x1e\xabs/19\xe4\
+\xa4k{\x820\x83\x9e\x1f\xf1\x0c\x1f\xb7i\xabI\xb8\xf1\xf4\x05\x13\x89\xc9\
+\xf8\xc3\xab\xd2\x94v\xef\xdf5g\xb6\x8f\x198\x19X\xc4e\x15\xbc\xffs\x12\xbc\
+\xdfp#\\\x04\x1b\xac_\xde\xf8}\xf5\xd4n\xb7\\A=\x7f\x19\xff\x8f\x19\xdc}>{\t\
+\xbcn\xbb\xe8^f-k\x99\x19\xe8\xcd\xdf\x14\xf7\xcbN\x9d\x91jx\xb9\x88\xd3 \
+\x97\xb8\x14k\xf1\xf6\xf3\xa2\xbc~\x15\x86\x0e\xf4z\xd8$\x88\xa1\xc4\x07\x89\
+\xe4\xbbi\xe2^\x97\x90\xf5\x1e\xe4\xf1<\xc2"F\x03R,\x92\xb9v\xbd\xb7\xea\xd2\
+\x81\xfa\x1b\xe3\\Fo<`4\xbc\xb4M\xf6X\x81%\xd6\xdd_@\xee;\x07\xde\xe9\xe7Y\
+\xb0\x05\xe4I\xfe<\xe0\xd1t\xc2s\xc1\xe4T\x95\xd4V\xe5\xcc\xf6\xb7i\x10v~O`\
+\n\x18\x92\x0b\xb7U\xa1\x97\xfaj\xf8\x06~d\xee*\xce 3|\t\xf3\xebM\xbb\xdbf0\
+\xabFiG\x18)&\x98\x9f!R\x99\x98r\x19\xc2-\xc1J\xce\xfc\xc1\xc1\x81\xd0ON\xb9\
+\x92\xcb\xdb\t\xfe\x9b\x05\xa8W\xf72\xe6\x9b\x93|\x0e\xf6\x05L\xea\x89\x12\
+\xf9\x90$u\xd9\x8ci\xc5\xb1}P\x8c+C\xcc\x90\x11\xf8,-\xd6?)\xd1\x13\x8b\xeb\
+\x89\xac\xf7\xa9\xeeh1\xc0\xadM\n\xc6N\xc6\xbe\x01\xd5B\x16\xec\xde\x1f\xdd\
+\xcd#};`%\x95\xd1>8\xfd\xcf\xc6\xb6&\x11\xd0:\xa2\x9f\xe1\x90iUT\x91\xbc\xe3\
+i^\x847%\xc6+*\x94\xcd\xeb\xeaX\x1b$\x8cW\x19\x12\x11\xf8\xda\x9f_\x97\xd8r\
+\xa7\x11\xb3\xe3\xff\xcc\x95\x08\xa2q\xb7\xde^\xcc\t\xc3V\xe1\xfb\xa5!\x8d"\
+\xab8`exS{O\r7\xd5m\xc8\x1c\xcc\xfd\xa2\x10QhGM\x8b@\xdcQ7 \x8e\x05\xe3A\xd9\
+\xea\x01\x1en\x10\xd7\xa0\xcb\x05\x17\xa6\xd6\x17\xa5\x14\xb3D\xe2\x02Nq\xb7\
+\x89E\xa8$\xf8F\xbcT\x8c\xc1\xeap\x85;\xa2\\\x88"5\xa5^A$\x03K\xae{\xc3L\xda\
+]\x94\x91/\x15\xc7\x82oW\xb4\xc2|\xe5\xd5z\x9a\x1b\xe2\x12z\xf8\xf8,3\x88b+\
+\xf9\x83\x07{d*\xe7\xc6@;\x99u\x04\xf0\xa1S\x9a\xcb\xae\xc4aB\xee\x9e\x0fr\
+\xeb\xf0X\xb3\xe5\xa4\xf9\x02\x92z\xb7O\n\x92\xa1\x98=H\xca\x92\xb5\xa7;%\
+\xa6\xd9\xfb\xfceX@\x9d7e\xf3\xe6=\xa09\x9d-\x97+\xd5\xc2(\xf7\x00\xef\x02\
+\xa5\x97/\xfc/\x1c\xd7\xec\xc6#\xb7\x03\x1a\x9e\xb2r\xba\xb50\xf3\xb5\x04y\
+\x81\x9a\x83\xfbC\xe1\xa2|s\x8d\xe1\xa3\xa0ft7\xc4\xef\x06\xd5\x06\xd7\xddgf\
+\x7f\xb8-=)\tw\xb4\xce1p\xb9{&<\xe8\xef\xec\xbc]i\xfd\x0e\xed\xfe\xc3Gb\x03\
+\x11\xb3\x1f\xd6f[\x9d\xafU\xd2]\xfbk\x9a\x1e\xb7\x86\x03\xf4]f\xfd\x191x\
+\x9a\xf6\xc9,\x02\x9f\xc1\xc7\x9awk\xfa\x1b\xb3C\xef\xf4\x85(\xed\xf8\x1fQFv\
+\xcaQ\xb8;a\x88\xb0\x04G\xeb~%\xfc\xac\x86\x96\xf1\x9f\x99\\F\n\x12S\xca\xa5\
+\xb0\x9f\x1e\xc6t\xf6\xa4\xcd\xc3\x11\xef\xc6hH\x9b\xcf\x17\xe5)!\xf6\xe3\
+\x1f\xad\xde!\xa66%\xdc\x91_\xf7\xfc\xf0\x8ebQ\xba\r\xc2\xc7\x83\xb2\xecr\
+\xaaN\x16\x85\xd4\xbb\x01tGO\xa9\xc9\xe6\xb5\xcf\x8b\xcb\x12\x90\xb1\xe8U\
+\xf1\x96\xfaO\x9c8\xa4\x18\xb3\xab\x90\xe3O\x01q\xcd\xc8M8\x8aYQ5\xa3\x13\
+\x8d\xe2(\x97\r\x13\xfb\xd7\x0f\xc16Y\xa7\x9d\xec\xcf\xedK4e\x87\xed4p\x8c\
+\xe0\xc8\xacS\xdc\xac\x17\xa7\xcf\xdb\x08\xcdR\xf22YX\x8f`\xa5~$hs\x96\xfbN~\
+\r\xf2%\xfb\x9du\x9f\xe1\xae\xfb\x8a\xd1\xd4\x1e\x93gUM6\xcd\xf8|\x80\xa4\
+\xfe$2>\r\x81\x11\xad$\x1e;\xdf\x84\xcfA.\xb8=\xa7\x8dD)\x8a7cW\xb0m\xcfl\
+\xed\xa4\xfdH\xaf\xc4\xff0U\xe1\xef\xcd\x13G\x9cCU\xd1\x895J\xdd\xab)\xf7#\
+\xbc\xc8\xff\xfd\x17 \xda\x8f\xd0\xe4T\xba\xd4\xd0\x8f4a\x1c\xb0\x8b[\t\xf6R\
+\x88%\xf7U\xae\xec^\x1e\x07\xa4\xa3\'d\x10)\xbc-\xb8\'q\x9a\xb2g\xa5\xbc>r\
+\xab\xd9\x8e\'\x8d\x95_\xe7x\xd5\x9c8\xbbi\xc6\x96\x95V\xa7\xde\xcc:,\xb0|\
+\xddbg\xa4\xab\x03t$W\x00\xb9\x9c3R]\xee\t\x15\xae+\x84\x97\xc4\xf5B~=\xc1d\
+\x1e|\x99\x95\x8b\x83\x90\nBrN\x1f\xf8\xb3|\xd5;\xce\x944rq\x94\'\xbf\xb3t\
+\xee\x839i\xa7\xc6\xf7\x1a\x9df\xe98X\xc2v:v\xbd\xafN\xdf\x89\x9a\xcd\xa2\
+\xf1\x00?\xee1\xb52&n\xc8\x02\x833\xa6B\xff\xa0\xd8\x19\xcb\xc7\xd2\x1c\xee\
+\xd8\x0c\x99\xd3\xb8\xeeYQ\xb5]\xa9\x8eSH\x8c\x91\'\xf3\x92\xc1\xceY\xa2\x07\
+h-\xfa\x92\x97\xb3%\x8c\xd5|b\x83b-\xe1\xab\x1e\x16\x1c\xc5\x815\xa88\xb1\
+\xa9P\x12\xd76\xbb\x85\xea&9!\x11\xe6\xdd\xfc\xa2\xc9S\xa7c\xc5\x14,\x8f\xb7\
+u\tk\x02F\x16\x8b8W\xb2]\xb6PI\xbe\xbe)\t\x04\x92\xe58\x9d\xdfs\x13\xbb-\x1e\
+\xfe]/\xf2\xb6\x1d\xb0\xb8z\xb0\xef\xa3\xdaz\x9e\xb0M\xb0\x18V+\x90\x92Gm\
+\xbe\xf7\x05\xd1\xb5\x95\xcf\x1a8\x1c\xd3\xf6\x86}\rY\xac7\'\xd7l\xf7\xca\
+\xca\xa4\xf6\x19\xa9\xdd\x90\xd8\x12\x9b\xe9\x9e>\xdf[\x81\xd4\xba\xd6A&\x1b\
+\x1cZ^\x9eZ1\xb4o[2\xf5}\x0f\x05{\xdc\xf3\xa1\xed\xd2c\x85\xc8\xf2\x0e6\xac<\
+\xe7@\xe5\x11\x81\xfaI\xae\xa0\xb5N\xa1\xdeM\x97c\x17\xc5\xfc\x84O?\xf7\xd0\
+\x9b\xa3#y\\\xafU\xd28\xbc<0S\xc3\xb3m\xca\x8f~/W\n\xc6<\x82\xb0\xfd\xebXjf_\
+\xb3\xab\xbd\xffk\xdcy\xdc8\xa8{\x9aN\xa7\xce\xdc\xe5\xa2)=\xc7\x94\x9b\x8e+\
+\xbb\x93$\xce\xad\xe0LMN!\x96\xcaq=\xfa\x92\x95<\xd9\xb4i\x80\xc9\xa9]/Bm\
+\xc58z\x98\xebu.,\\\xf6.\x04&S9\xdb\xaa\x9e\xa4m\xb8b\xe2\xf2\xd9\xa9\x82\
+\xec\xd6\xff"{\xe0\xd3?\x82\x89\xa3\xec\xe1\n\xf4\x87>p\xbf}(l\xa9\xcc\x05`\
+\xc4\xcd{\x94C\xebU\xc1\xaf00\xa5\xdd\x0f\xb9\xff\x87\x8f\x93\xd0\xe3\xed/\
+\xaa\x10@\x9ddP\xb3\xa7\x17>\xb0\xe5\xc61ib]?\x87\xd0\xa0yt\xd9\xb8T\x15eqf\
+\x19\xb9\xee\n\x9d,\xd4N@\xdd&M\xeb\xaa\x8byX\x81\xb9Wcd\xdb\x95\x15\x04Q\
+\xbf2\x108U\xb6a\xc5.g\x9f\xb4\xa6X7\xdc\xaa]\xf7q\x12\xcf\x8d\xfff\xc7\xfa\
+\xb3\'\xc7\xa9\xd3\x86\xc8f\xfc\x04q\x93U\x81\x8d\x05\xbcAMSQW\xe1\xb4\xe1\
+\x85\xa1"\xf2\xd4,\xdf\x05\x8d\xda\xd2\xc8X>S\xbfo\x7f\xf1\xc4\x12;\xe4h\xd6\
+\xa3-\x80\x03\x1d\xab\xf4\xb5\xd3\x00\x84\x14F\xe0\x9bS\xc0\xc5\xd0\xe5"\xd4\
+E0\x8d\xa0|f\xb3\xf5\xf7N7\xc6\x12\x16\xfb\xd0\x9c\xc3o\xdf{\xe6\xc32<p\xfea\
+\xff\x16\x02\xf5g\xce\xb4D\xeb\xe7e\xc7\xf1B\x0b\xbd!q\x83P\xf4\xb3e9Z$\x8ac\
+\xf6t\x17\n\xed\xc5@\xd6\xad#\x8fP\xdf|U\xd9C\xac\x97@\x8c|\xb1/\xbb\xaeo\
+\xae\xf6\xe4\x9a\xcf\xdej\x10\xccw\x1eC9x\xf7d\xe4\xd4d\xea/\xdcHf\xd5\xc1\
+\xd8\\4\xe6\xd0\xa8\xca\x19\xae\xec\xbe\xf7J\x10DZ\'f\x92\xee\xe6%\x8f\xcex6\
+\x1c#\x80\x17\x85\x85\x80-C^\xf6\xb4\xc6}\xfepr\xdb\x0bJ\x99P}\x04\xe2*\xe4{\
+!\n\xef\xf7\x9b\x96_\x81;\x1b\xf5\xb51\xc9\xbdk?\xcf\xbe\xe7\x8b\xfau\xe2*H1\
+\xc5\x92\xe5\xf7e\xe0H\x9c[\x00\xc7{[q\xc4\xbe<\xd2@c\xf3\x0f\nH7\xe4\x8bL\
+\xe4 \xcf\xb1]u\xf7\x88\x96r\x18\xd1\x96\xe80\xa0&/H\xef\xf1\x81\x88\xb4\xb1\
+^18\xc5\x04:\x15\x92\xdb\x1d\xcb\xf90\x85T"\x99\'ot\x99o\xb4\x99y\xed\xbbyI<\
+\x87)\x93\x0bJ\nXm\x9f]\\\xae\xb6\xef\x0b5Q6H\x99\x9e\xd1\x82\x1f|M\xbat\x9a\
+\x0e(\x17\xfd\x92_?I\x87\x04\x05\x1aJ\xd8\xd1\xe5\xabW\xcc\xaa\xd9\xe6\xc8\
+\xda\xc5\xbfs\xc7\x12\rF&\x16\xf7\xa0\xa5\xbc\xe9n\x83\xd2\xcc\x16U\x87\xab\
+\xb8\x1a\xbeFKdWBgd\xa5LV\x9c\x8f\xd4/ym_\t~\xe4\xb5\xfeY\xb72(\xc8\x11\xe3\
+\x83\x1e7\x92x\xa4\x80\xcb\x8b\xce\xd7/\xf5\xb9\x16\x93Y\x1b\x9d\xecp-\x80\n\
+\xed/YL\xeb\xc0U\xc6l\xde\x05>\xa4\x8b\xe2\xdc\x92i\xad\xda\xe9\xc1|\x8d\xce\
+t\x85i\xcds?]\t\xfc\xee\x86`\'8\xafWW*\x8bH\x05\x9d\x97\xe1q\x1c\xc5Ic\xb0\
+\xdeu\x82\x85\xf7\xd1\xbd\xdfJ\xfd\xe4\xb5_\x1d[B\x05\xbd\x13\x8d\x97/\x91\
+\xf8O\xe83\xe5(\x8c(}\x8f\xe8\xa4TN3#\x16\xaf\xd7\xc6\xa0\xd4\xbf{\xc2\xf129\
++\xa1%\xcb\xef\x146\xef\xa3e\x1b\xa3Z\x1e\xd4\xed\xd1N\x97\xfb\xc9\x19]\xf4\
+\xe1\xa3\x8e\xfe\xe9r\xd1\xae\xed\xbb<\x87n\x8b^xWO\x83z\xb0\xe7<\xb43\x92\
+\xf14\x8d\xe1M\xd6\\\x07\xf0\xeb9\xa42\x07QX\x8b\xcd\xe7\xc9\xd39/`Ks\x06o\
+\x82\xd2\xa2\xa6\xf4\x89\xdes\x8a\xebuS\xd3kq\xc4\xaf\xb9\xc7\xe6\x8b\xc87\
+\xd4\x9f\x16\x1e%\x8b\x14`\x9a-\'\x9a\xef4\x9c9W\xc8+4\xc8;j\xde\x7f\xd6Z\
+\x90d\x0c\xba\xe7#R\xea\xf3\xf0\xff\x00\x1e\x17\x17\x14\xfe\x04\x00\xcb\xac+\
+\xea\x8a:kp\xcb\xdc\x9c\xe1\xe9Z\xc9\x1d\xbe\xb7\xaeU]\x1ah*\'U\xe4\x14\xbf\
+\xfa\xa4m<\x8ai\xaf\xb5h\xb7\xf4N\xce\x97L>\xbe\xdc\xaah\x00\x15\xd3\xfa\xd6\
+|^s\x9fag\xbf\x88\x9d\xbd\xb7\'\xddI3iU\xeb\xc8J\xf8 \xa2w&\x13G\xa7_y\xde\
+\xce\x04:\xb9\x9d\x9fP\xda\xaa4\xbb\xd8:\xc1\xa6\xa1\x13w\xd00\xe4d\x93L\nh\
+\xe4\x89\x9dv\xb4Y:/\x1cjZ(rs\xec^\xd1V\xea\xf1?\xd2\x1b\xf2\xc5\x97\xa09\
+\xe3\xd5\xefi]\xeb\xf4\xb6\xe5\xec\xe4\xa8\xf7\xdc\xc1[\xe0\x80\xbe\xe3(\xa8\
+z"\xe3\xa2\x81\t$\x87\xf7i\x87\x08\xd6\xc3"\xef\t\x1a\x99\xe5\xc68\xbb\xaeO7\
+\x14\x85\x98\xe2!\xdd\x81\x0c\xca\x15\xb0:\xf5\xd7\x7f\xb4\xf08\xbb\x7f#`\
+\xc2\xce\xbe\xa8!\xfdy>\xad\x1d|1^\xedx\xd9I\xd383\xd4\xea\xe7\xc3?\xd8=j\
+\xb2\xe7BI\xa6\xcf\xca\x95\x1b~\x1b\xdb\r#\xb2M\xa5\xbb\xab\xab\xce\x1bl-ZTd\
+\x9b\xa2\xe6\xd1;H\xeee\xc8\xa3X\xbe\x0cx\x0eb\xdb\ny\xdf\x18=\x0eQ\x8a(\x94\
+\x05-|\xfd\xafi\xe7q4Y\xe03\x1a\x8cO\xf2|\xfbI\xb0\x94`\xc0i\xefq\xc3_\xbe\
+\xfa\x86$\x8c\xf7\xfa|\xb6u\xfel5?\xe2\x95\xdb~\x86\xd4\xc9\xee\n\xf9\x15\
+\xc8\x89\x9e\x95\x8b\xb9\x1b\xda\xae\x95\xe5\xce\x91\x07\xe0^ %\xc6\x07Z%7\
+\x1fb%\xb4\xfcv\xfd]\xf6\xf2\xae\xb4\xadB\x01\xffB\x189>\x9a\xda\x93\xbe\xb6\
+\x19\x04u\xabzfiMH\x07\xe4T\xee\xa07\xadI\xc0\xfb\r\xa3N\xee\xcf4\x16\xbc\
+\x93\x15\x1d\xda)\x9f\xb7\xb5\x82\x9d\xd8ai\xa1s\xb0\xf7\xd6\xfde\xa3#\xd7\
+\xd0\xee\xf3"!\xf5A\xaf\x9f\x8a\xf6\xed\x9fA\x8f|X\xd9\x10w\xfcz\xbe/Y\xe0\
+\xa4,\x81\x97\xde6\x17Z\xd8\xc2\xd9F\t\x9b\xe0\x90V\xdc\xdaoxd\x11\x86\xd1!\
+\x9b\xa0G\x8a\xe5\xf7{\xac\xc0\x8bY\xa6\x06\xf7\x9b+\xdbk<P\xdd\xed\x1e\x8d\
+\xdfap\xd0\xd3\x03\xcb:\x8f\x11C\xc7S\xd1}-\x8c\xf1J\x8b\x1a\x07\x81\xd4\xdb\
+\xcb\xe0\xec\xdfkU\xf8\x8a\xdd\x9d\x0e\xd3i\x98y7l\xa8\xe0%\x00\xeb]W`\xcal\
+\xfeu1X\xc7\x17\xbc\xb5+\xc60&_\xca\xde\x12a\xb5\xb9r\x9ewW\x16\x7f\xc7\xc9\
+\xca\x12<\x89\xa7\xb2]Y\x02\xfc\xeb\xd6\x98\xf7\x1eh#\x14\x1f\xb0\x8bR\x9d\
+\xa1\x16J\xde\xf7\xcaV\xbb\xdb\xe1d$n\xd3\x00\x88\xce\xbe\xe7\xbd\n\x9a~\x16\
+1/\x93\xf4+\xfa%\xe3\xe4\x9f\x9e\x1f\xe4\xcaP\xc8\x85\x04\r+\xadz\xf0\x84;\
+\xfe\xb2\xa3\x92\'\xday\xdfJBE\xc7\x92H\x9c6k<\xd7\xe6\xfa\xf8\x02\xb1\xe8z\
+\xddCO\xd3\xe7\xc8\x1cGq\xd3\xf6\x9c^\x08Dz\x08\xbb\x8fSm\xa4\x8c\xaf\xcb\
+\x13\t\xcf\x9e\xc9\x1e\xee\xb9B\x10\xf6[\xbb6\xe8\x8c\x83\x14\xae\x1d\xd6_Mr\
+\xc9N\xcb\xf5\x81v\x8bOd\xb9\xc8\xdeo\xd9\x7f{\xf3\xe9\xfbl\x1d\xea\xf3e\xf2\
+\x90n \xf4E\x11\xa76\xfa\xb4\t6\xe6t\x1c\xe2_\xee\xe8\xaa\xa8\x96\xccn2\x9b\
+\xad\xf2=\xfao/\xadT?M0+\x83\x1d\xb6^\x0fC\x10\x8f\xd1\xf1\xcc\x0c\xfb\xb0\
+\xa3\xb8^J=\xbeD1\x97-,\xe1\x80b\xf5Sp\xed\x16\xa4\x8a\xf3l}RB\x8fJ\xbf}*\
+\xe6&\xb2\x9e\xfd\x91\xe6\x82\x05>\xe6\x8c#\xefm\xce\xe3-g\x89:k\xb2\x19\xef\
+\x1e\xea[;\x85o\x1a\xa0)\x0b\xa9y\xf7\x8d\x07\x00\xf7\x03\xaf\xb1\xd4\xd4\
+\xc6\xc7\xa6\xe9\x18\xbe\xc5\xfe\r\x95\x9c\xe2\xb0DE\xa0\xfa)V\xdc\x00\x88\
+\x1a\\k}pr\x0e%\xb7V\xf7\x8a>\xd5\xb4\xb5@4]\xe5\x8cG\xd1\xc2j.:RK\xde\xa9\
+\x00:\x0f\xaf}]\xcf\xd5\xe5\x1b]qA\x98\xfd{?#\xcc\xe4\xd9\xff\xb3\x0f\x11\
+\x976\x9a\x9b`\x80\xb1\x03)\x94\x05\xc4Z\x19\xdfZn\x1b\t;\xa6\xc2\xd0\x0b\
+\xbe\xaa\xe3\xb9\xbe\xee\r\x9c\x98}?\xb9\x14f\x16\xf71~\x98+y\xdb\xf7g\xba\
+\xe3\xb9\x1cE\x14\xb9\xcd>\x8fV-\xd2\xfb{\t\x9c\x16|\xcd\xf9\x0f\x8ea8\xa0EV\
+\xf0zB,\xcfg\x9f\xbc\xb9\r\x90\xde}Y\xdb\x0b0*#w~\xc7H%z~,\x83\xc3\xe2\xff)\
+\xa2\xed\xd5\xaa\xedB\xb4\xda\xf7\xe7 Os\xcd\xd2dc&\xf9&\xe0\xab9\xa1\xe1\
+\xcb=+\xc8\xdb\x82\'\x19\xdd{\x1e\x0eQ7ja\xdea\xb77\xef\xb9\xcdv\xb50\xf7\
+\x04\xb1~\x06\x8f\xa9N\xa4K\x03\x88\x8b~1\xe3\xe4y\xfd\xd1\x9e\x95z\x9d.\x99\
+\xa0\xef\xed\xc0\xcd\x97g\xe0\xf7\xe3QL\x99|\x0e\xb6\xad\x03\xf5\xf7\x01\x82\
+;\xcd\xaa\x91\xa4\xe0\x86o\xe1\xe9\xcbv\xf5!{\xfb\xb5\xee\xd2\x0f\xe0\xce4|i\
+\xb1\n1\x1a\x12%99\x89\x1f\xe7\x92\x99q_3g\xbe\x1e)^\xd6$\x93\xf2\xf5\x04{B)\
+sE\x88I\xcaD\xcbV_\xbc\xe6\x07\x9c\xd0\x812}\x1e\xa7\x0c\x019\x0b\xd5}|\xfb\
+\xddic\x81*\x05\x19\xef\xe7B\xf6O\xd2\xc6L\x82X\xa7\xc4}\xd6\xd7A\xde\x13\
+\xd5\xd8cHI\xcfF\xed\x92\r\x19?o\xe1\x11y]\xc9\xbb\xf4u\xb4\x92\xb3\x9d\xbdi\
+\xc16y[\xd7\x17xK\xbf\xfbO\x8a\xcbU\xcc\x98XUg\x89O\xba.\xac/v\xb4\xbc\\\xde\
+\x98J*m\xa4\x05\x14W\xaany\xab$\x1b&\xa2S\xcf\xa9\x82\'\x1a\x97\xd2\x1c)\x0b\
+\xa8\xba\xc2\xf1!Y\x17K\x86tF\xef3\xb49D\xe3\x82\x0e\x99\x9c-R\x8d\x95\xeaU3\
+}\x04\xd70\xac\x19_\x03\xf70\xdfz|\xb3\x07\x9b\xfa\x94\xb8\xa1;\xb5\xe4\xd3\
+\x84\xa4\xe3\xac\xad<\x93\xa1\xc6(\xa8\x002_\x1a\xb1D\xd3\xff0$\xf8\xe9v\xe8\
+x\xd11\x90\x0c\xea\x8e\xc8\xdd\xdc\x14\xb5g8\x81\x18\x7f|3\x1cY\x10\xb8\x80H\
+O"\xb7\xb9{\xb8\x9e\xfc\x06\xa8\x9bZ\x8aQ(\xb0=c\x15\xd6A\xbc>\xd1\x07^\xccG\
+t&\xc2S.1\xb63\x06\x00\x1a\xa8C\xef\xd7\xfc\xef\x1a\xca\xc4\xa3\xda\xd9.]\
+\xde\xa0\x9d:\xda\xf8\xcb\xfdT\x03\x04\\u6\x9d\x94\xec\x83#\'\x9a\x99Z\xb0\
+\x11\x9e\x94\xe6\x9e\xdf\x80\xadF\x9c\x00IA\xcd"\xb8\n\x9c\x1d:\xc2J\x07\x9b\
+\xe2<D\xad\xca\xd5\xf1L\xac\xa5\x1e\xd7\t\x06\x16\x98\xa4\xf2\x19\x82\x8a<\
+\xfa\xc4?\x14\x08,\xa0Bl\xe1\x8f\xca\xc8\xd5|\x7fKmxd\xd0Vn\xb1f\xaeQ:m\x95\
+\x8f\xbb\xd1\x01\xc7\xb5\xf6-iV\xc33\x1b\x82FD\x07,f\xe4\xc9\x03T)\xe4\x80#\
+\x98F)Q|T\xa4\x129\x914\x85\x11\xc0\xe3\xdf\xcb\xf3\xd1\xee><i\x13\xdc\x80\
+\xb8o\xf3\ruiyaoZ\xf0X\xd3\x08I\xb4V\x89\xbc,\xd1\x0f\x85\xee1\xbf\xe4\xaa\
+\xc7\xe2\xe8h\xb9\x11B\xac\xa1\xcc\x8b\x9d\xf8\xeb[\xb4\xeb\xd5\x9b\xe7\x1bk\
+\x92\xd2f\'\x13\xbb\xfec\xa6\x86\xf6}\x16\x8e\x1f?\xc8\xd7:\x89%g\xd2\xe8\
+\xc1\x12 \xaf\x1b\x10U\xab\x9d\'d\xc1\xc2\x12H\t\'tZ\x05\xee\xd7\x03\xe7\x86\
+\x08`m\xaeQd\xf3\x92\'!\xf2q\x14\x16b\xfe\xa6\x9c\x85\xfd?Z\xaa\x92K\xb1\xb3\
+\xc7s8\xc9\xaa\xcc\x87\x18\x89\xcb\xeb\xe8e\xee\xc6\t3]\x96\x92"\x86\x05\xf8\
+\xf8"\xc7\xd5h\x93l\xce\xfa\xa9y9\xa0`89\xe5\xb3\x95\x910\xc3\x99\x8d1\xe8\
+\xbcTBdk\x9c\xa0\xe6*\x9aS\xcf\xee\x9e\x1c<\x8b\'\xc5jv\xa2\x0ecq6j\xf5\x05n\
+s\xd1\x07\x942[\xf8,8\xdd\\3\xb8\x1d\x92l\x01\x0c\x12\x96\xab\xf1\x056\xdd\
+\xc1\xd9d\xb9H}TH\xf8\xf53Ye\xba\xe75\x91,_\xb5\xcehp\x94\t\x89\x1c(\xdb\x08\
+\x02\x87%MXuv\xbcw\xe4\xa4\x87~\\C\xd0\x99o\r\x9aI\xecJ\x1d\xd7lN\xda4)\x05\
+\x84z{\x0b\xef\x0b\xa0o\x11\'\xe2\xb8\xbe\xdf\xdcJ\xed\x19ppU\xcfv\x1c\x9e\
+\xb7\xd5k\xc2\xcf\xactm\x8f0\x8d\xcd\xcc\x84\x92\x7f\xf3i\xdd\xb8@\x9e!\x9d}\
+ep\x10\x83\x0e\x1b\x82\xaa\xb9\xf3g\xa7\x1dN\xf01\x94#\xd8u\xd7h\x06W\x0e\
+\x08\xf7\xb5\x96\xfc\x96\xcc\xe9\xf4\xa5\xc8\xf0K\xc1\xaah\xa4wv.P[\xb48\xdf\
+C\x8d\xcc\x14\x18&o\x99}V\xa1\xce\xcb\xe1\n\xfe(\xc9%\xa2\xf7hfH\xe3\xf1\x97\
+w\xa5\x87\n\xb4V<\x94\xd6\x9a\x82\xe8_t\xee\xf4\x1e\xc3\x06\xee\xa5\xe5NIH\
+\xc3\x848\xa0\xaf\xf1\x0b\xf0\xf0\xd0(\xc6\x04\xb1\xd21\xe3\xd2\xb2\xca\xe46\
+\xbe\xdc\xbb\xac\xdfaL\x99\xcbt\xff\xbeo\xdc\'\x0ct%Gq p\xa6\xe1$6\xb8\xc30\
+\x94<Fp\xf43\xa3CKtE\xb6?\xe0\xec \xff7\xa6\xcd\x1f\x9cG\xac\xc0w7\x86\x00\
+\x98Lm\xf8\xea\xc7\xfc\x85Wa\xc5\xcb\xf0\x97h \xc1\xbe\xa2\xd8\xe3\x99\xce7\
+\x98\xb4\xa11\xd6\x83PO\xe8\x105\x86\xed\x93B\x9f\x1c\xc5\xfe\x8a-\t\xd40ol\
+\x1f\xa3,\xa9\x19\x1a ;B;!-uYRB\x0e\xf2_\xb9\xcf`^\xf3`\xdaXy\xb7\xfe\xf5\
+\x83\xc0\xc9Rj\xb7\x99F)\xc5\xac\xaf\x05NQO\xfd\xaa\xa2#\xf4P\xbc\x1c\xe1\
+\x97\x1a/\x8f\xc1\xc4\x19\xee=\x80\x159j\x07\xc9\x009\xbb\xcf\xc7\xca7\xfe.\
+\x9eM\xa6|\xbf\xaeE\xdd\xcb\xfb\xa5\xb3\xbfu!\xb2G+\x85\xed\xd9\xb3\xb6\x7f\
+\x7f\xeeT`\xfaU\x13P\xb2\xa3\x85\xff\xeda\xda\xc9\xe9t\x87\x8d\xf8\x0e~\xbdG\
+",y\x83\x12W\x08\xe1\x0c\xab\x9a{\xfd\xa4-&\xc3\x9a\x9c\x86#,%\t5\x8a5\xefgK\
+C6,\x9b}\xc9Ar\xdfA@\xc8\xa2\\\x9a\x99wj\xc1Vi\x07u\x9ayX\x8b\xbd\xab+\xd6\
+\xb8\xdd\x0c\x9a\xddJ\xc0\xa6\x0f\xfe\xe8R\xacXgn\xc7j\xe4OO\x8d\xd6\x19\xf5\
+L`\x80\x94\xae$\x12-\x19\xbb\xf1\xd9s\xa4\x8a0\xb9\xabw\xcf\xde\xdd\x05\xaf\
+\xe2wn5\xcb\'Gh\x8e\t\x97\xa8\xc6O\x03cu\xbdX\xdf\xc2@\xf7<\x03\xd6k\xfbF\
+\xf5\x02\xa7/\xe38 ^\xfc\xc2\x9c\xb5\xdc\xf5\xca7@\xae\xf4\xf0<\xa6d\xe2\xa5\
+\x91A\xdf\xd9(\x1b\x9d\x83\x89\xf1%\xba\xf4\xcb\xd0M\xbd\xdb\xdc\xeeU\xb2\
+\xce\xc3<\x9a"\xc0\x8b\xcf\xc6*\x16\x83\x02\xb4:t@\xcd\x05.`3\x8e\xb9\x9f\
+\x15C.\xbb\xa9d\xab\x8d\xb3\xde\xa6\x9cHP-{\x13\x06s\xc8\xb3]\x89\x16O\xcdX\
+\x9csi\xfd\xe7l`#z\xb94@?6\x95\xcd\x97\xb8?\x89_5\xab\x94\xa1\xf1%i\x8a\x93\
+\'`\x9f\x91\xed\x92\xd4\xc7|\xe9\x89\xa7\xae<\x8b\xba\xe2\'k8q\xf6t\xff\xe6\
+\xfb\x03\xa6\x01\xf4<0\x0bLI\x9c\xad\xf4\xa5\x8d~\x87\x84\xd5E\x07\x89\xf9\
+\xe9\x8d1\x8aTg\xbd\xce\x8e\xcd\xfeI\xcf\xd8$\xe2s\xab\xa3\xe4\x11\xb6kzF\
+\x88nW\x0bh\xcd,\xc5\xb3\xa7\x163\xfdrTr\xa7\xdb\x96\x93\xda\xfd\x13\x0e\x89\
+\x9aQU\x1au\xa6\xcb\xe6\xf4v\xa4D\xd5sP\x17\x91\x91U\xbd\xf1\nW"\xc7\x9d\xcb\
+\xeb1\xab]a@\x10\x0bC\x93\x9b\x06\x10\xa56_a\xbe\xfa\x8b\xb2P\x1b_9\x133\xd6\
+Ng\xca\x91!\xa4\x94\xccc\x18\xc6\xaaF8\xfefx\xf75\xad-\xc7\xb1\xc8\xc4\x80\
+\xd0A\xe6t\x85\xab\x01v\x859)3e@PB8S\x81\xf6F\xc0C)\x86\xcb,\xe2\x9e\x83\x81\
+&3\x8e\n\xad\x19RQP\xdb\x10IuL\xc2\xfb\x05\xdd\xd4t\xca\xdc\xc2\xa2\xb1\xd8\
+\x9aHN\xadQ\xbd*\x03\xb8K\xe85\xa7^\xb9\xa9\x1e\x8f\xa6\xb7K\xd9\xabj\xb3\
+\xf8\x1f\x86\xd4\xb9M\xc9e\xd4\xbd\xb7\xd1-\\\xe6\x03+\xcd\x8f\x99\xec\xa9}\
+\xec\xcc\xe6\x03}8\xb2t\xafg\x90n\x96\xb0\x90\x98\x96\x0e\xd7\x9d\'SP\xf5\
+\x0b\x03\x9f\x14\xcd\x94\x08\xc4t\xa6\xf7\xed\xb4\x92\xff\xc0\xedp\xba\xb0ly\
+\xa4\xb5F~\xc1\xd6NB(\xd3\x07\x1e:^%\xad\xa0\xed\x1c\x87+\xca\xed\xdb\xa1B\
+\xe3\x0f\x12L9\xbc\xcfp%-\xe5\x11\xa1\x1c\xa1\x18\x17\xfd\x8f\x96\xf3t3s9\
+\xcb\xc6\x1e\xb6\xad\xe8h\xbf\xc6K\xddm\xaa2\xb7V\xbc\xbc(Sf\x132\x9ce\xbfp\
+\x83;\xbe6D\xdd\x03\x90\x8f\xc0\r\x97#\x93\xa7\xe5u\x8e\x03\xf6_\x8d\xaf\x19\
+\xea\xd5\x81L\x8dm\x83[\xf7\x8a\x1e\xa2\xa01\xcbC\xe2\x9c\x14/\xa0\x18U\xa1\
+\xfd^\\\xbe\xa0\xf2\xaa\xce\xeex\x87uee\xd2\xce\xbaO\xd3\xd1c\xe2\xe1\xcbO\
+\xac\x86sy+\x81\xbb\xc3\x8d\x1c\x7f\xb5\x8a\xfclN\xbe\x90a\x8c\x9a;\xbf\xb1\
+\xcd\xfb3\xcb\x13\xe1\xba\xdfe\x8bQg)\xea\x87\xe2\x17\x95</\xb3m"\xa28h\xfa_\
+\xdd0}\x14R\xf8q\x84\xbe\x91|y\x1b\xe7\xa7\xee4\x05\xf0\x87W\xa4\x94\xd5{P5\
+\xfe\x8e\x89\x0fw\xadR\x80I\x99v\xdd9\xf2\x8b\x9b\xad\xc4\x1d\xab\xbc\rB\x9e\
+\xa8\xc4<\x92\xc7\xb3\x99\xb8\xf5G\x848\xd5Z.\r\xa9\xe7\tv\xe9.j\t\xe9\xa3\
+\xbe\x15\xe5kc[L\xa9F\x84\x10\xb2|@\xect\x0b\xde\xc7\xec\xd9\x8c\xdb\xaaIv\
+\x9a*\xect5\xcb\x83\xefO\xa7L\xe5\xef[\x04\x1au\xe0X^~\x83\xe8u \x0c]\x99\
+\xdf9\'JO{\xe8\xcd\xca\xdbN\xc0S\xaa\xc1B\x97\x0f\x94N\x12\xef7\x89\xc2"\xad\
+0CY\x90S\xc1\x95\xba\x90F\xd0\xeaps8+\xb9\x87a\xde& \xf1\xbf\xfb7\x93\xca\
+\xb7V\x0c\xbf\xce\xabG\xdd&s]+\x06|]\xba?\x0b\x7f\xc5w\xdc\xe8\x18:\x9e\xbf4\
+j)i\xd6d\xb7\xd6\xf7\xa9\xf4\xf9\xed\xa4\xf6\xacq\x10\xe1\xb65\'\xa0\xb6\xaf\
+\xe5H\xff\xec\x90\xb1\xd1\xa9d\xdc\xa4\xef\xbb\xd4Q\xbebL\xa1\xb7\x9dcH\xf8/\
+k\xb2\xf8\xdb\xa4\x06)r\xd9\xf0LC\x99\xc8\xb6\xf7\xb0M5\x12\xe7\xaf\x80okN\
+\xf2\x80|\xab\xb6\xcd\xd1mp\xf6\xc3Q\x8b\xc8E7>\x88\x9ak\x16\x88is\xb9\xe3\
+\x93#\xa8*\xa6\xa6\x86\x82\xc8\x134\xd2\xc8f\xf8\xab\x7f\xef\xfd\xc6\x04|Rx~\
+$<cp\xc6\xd6\\\xc6T\x199\x9d/YW\xcd\xd2\xfc\x93\xdc,\xc5\xc2\xd5\xbf2\xfbk\
+\x1a\xd9n\xff\xe4,\xf2c\xf7\x8d\xd6\x90\x1b\x93\xe4*\x175 Y\xf0\xb0\x90O\xaf\
+\x94G\xb3\xf0\xa8\\\xd4?\xfd.\xd6\xc5"\x12\xebe+\x85\xfa\x8e\xac\xea`3\x1b\
+\x83J\x8e\xf3=`\xedW\xd7>\xf6\xaf<"\xba\xc6F\xea\xbc\x00\x8b\xc5\xf5\xeb#\
+\xe2J\x1f\xc2\n$\x7f\xd776k\xa1Ml\x1dK\x90\x96\xbc\xfc\xa2\xb9\xa6cO|\xd6\
+\x81\xf2\x7f;f\xed\xae+\x8a\x86o\xb3\xac\xf7\x9c\xbb(\xd7/Ck\xf4}\xeb8t<<\
+\xfa\xc7^]$\x88\'G\xbc\xdfe^{\xe3\xd9we\xf0?\'\x83\t_\xee\x85{Y\xd77K\xf6B\
+\x1d\xa5\xd4O\xb9\xf3\x0f\xfe(\x08d\xb8\xacQ.\xb6Z\xad7&\x8c\xe4.\x9es\xdc"T\
+%\xaf\xaf\xa5\xda-\x10\xa2h\xc8\x1f\xbb1\xa7\x91\xd2\xaa\xe4\x1d\xe19U,\xf7\
+\xcf\xc9,\x01\xd5\x96?\xb8\xff \x1cK\x07\x16z\xb2\xa8aG\xdf[\x0b\xe4)\x00\
+\x0f\xdf\xea}\x17o\xf19,\x8c\xd6\xf0\xf5t\xed\x07\x16\x1b\xd6\xd9KG\x02\xfc\
+\x91|\xa2\xcdD\xaa\xd8\x8fHC\xc7[Qu\xe5\xb4u%\xe7\x1d\x01\x17\xbdU\xdd\xc7k\
+\xec8$m\xac\xfe\xa4\xbd\xcc\xbb=\xbb\xf0L\xf5\xad\xcc\xad\ry\xf5*\xecL\x1e\
+\xdd~?4\x1f,\x86\xe9\xd5\xde\x80p$\xddF\xa1\xcd\xc3\xcc\xbe\x0c|\xe7\x1fya\
+\xac\xe8\xaf\xb3\xbd\x99w\tA\\\xd8b8\xe3\x1d\xdeD+\x87*\xa5\xe7\xdd\x83\x0b]\
+\x1eP~2\x19\x13\xc5b\xbe\xdd\xa2f\xb5\xa2V\x95\x8as\xa10\x96\xb3w\x10s\x8f\
+\x93G\x96\x85\xd7\xd3O\xad\x04\xfb06\xe3\'L\xde\xa6\x97\xc5wc\x9c7\xea-b8p]o\
+\x83\x9cm\xde\x88\x92I\x15\xde6\x88:\x87\xa9\xe5\xd5\x7f\xff\xfe\xc4y\x97B\
+\xab\x87\xd8\xd3]\xe6\xca\x13\xe9\xb8\x12\x0fy}zCS\x81\xa3A\xff\xdd(yg\'E\
+\xc4\xba\xcb\x98zy}\xe0\x92wk!\xd60tzm\xd1\xd8\xb9\x9b\x11\xb4\x89\x9c\xea\
+\xad\x904\x84\x18\xf4\xf8\x03\xbb\xe1v\x0cH\xd1\xa1\xd1\xad\xa4e\xabc0\x8c\
+\x14\xd8}\x87\x17x\xb5\x1c/\x18\xce\xfc\x89\xd9\x903\xfe\x1e\xf4\x1a\x91\xf6\
+\xc4\xbf\xd4\xfd\x84,\xc5e\x99\x94\x94\x17i\xfd\xf5\x0fpQJb\xd1&\x8b\x91\xa9\
+\xfd\xb2\x94\xe9U\xbfQ\xaf\xed\xccr\xad\xd5 \xc7\xed1\xf5\x1cl\xb1_\xe5\xa4\
+\xde\xc8l\x1c\xff\x15\x97\x129\x02K\x11D\xe7\xea^\xab\xb6h\xd6\xcd\xa4s\xb0E\
+\x999\x84\x1e\xbc\x87\x17\xd1\xf4\x89\xe0\xec\xbb\x13f=\x9f\xc5\xdb\xd5\x9bg\
+\x9c\xe6B\xd3\xb3\xf5\xb7\xdc\x8d\x89\x96\x06\xff\xb7b(?\xd5\x0c.\xbe|\\\x14\
+\xda\x06\x97C\x97\xfb\xe6\x83VG\xcb\xb7W\xd2\x83\xc0;\xc1\xa5f\x04\xc9\xf0D>\
+4\x8c\xcfkyrh\xb9\x19\xa8\x94\xefn@\x9f\x85V\xdf\x97&\x0e\x0e\x0e}\xe79\xf9T\
+o\x14\x18fy\x8f\x04K\xe4\xb7\xec\x93\x8a\xe3\xad\xbff\xc4\x19\xaf\x7f\xf7\rO\
+}g\xd8\xe0\x94\x99&\xe3\xb8\xfe\\\x9e\x8b\xe9Z\xc5RMO\xfaY*\xb2\xbb,I\x1c6]\
+\xe6\x05U\xc2\xfc\x81B\x152n\xfeAE:\x0f\xfcO\xfb\xf5\xd7\xfe\xb9\x8f\xdf[sdX\
+\xadf\xb1}\xfd\x88\x84U\xa5\xa4U\xe5\x95\xdeLyH\x84\x9aY\xd7\'\xf77\xa8\x1c\
+\xda\xa3\xd8\xe0s\xf3\xcc\x19u\x159\x03-\x13\x1a\x93S\xe9%\x96\xd5r>\x04P\nS\
+\xa7\x1e\x0e1\x98\xfd\xf1\xf7Q\x9c\xc8\\\x94)\xfe\xd3\xc8\xc8d\xaf\xf1\xefn\
+\x05B\x84\x06\x01\xea\x9e\xf7\x01\xd2+\xa5D\xab\xe5\x0c\xdfT{\x1c\x08Eg\xab"\
+}6\x98\xba[u\xc8Z-\nG\xea\xf9\xf9\x8b\xdc\x11\x0c(|\xdf\x9d\xf8\x19\xe2\x17\
+\xbe#0C\xfb\x9aC\xd9\xfbX\xb8"\nJ\x95\xbfP\x03\x0b\x84\x97\xfb<\x93\xc7\xcd|\
+J\x8eS\x1dq\x90G\x8f\xfa\x92\x0b1_\xe1\x0c\xb2;\xb9i\x00\xdaW\x0bE\x04`jw\
+\x17\xfeT\xe2\xce\xe82j\xa07\xd0>}\x89\x0eZ\xc6\x95\xaf\x94\xf5r"\xba\xa2\
+\xe6\xff\x0f\xbe\xd1\x95Z\xdf\xb3\xc0\xdc\xcbT\xa8\x06\xc7\xc4\x9a\x94\x0e\
+\x98\xc7j\xb7$*\xccg\x00S\xad\xe8pD\xce7\n\xac\x1c\xc31g^I\x82K\xa3\x8e\xcc\
+\xea\xb9?0\xa4IUN0\xcfA\x08\x06\xb5_\\\xf7w;\x91\xa7\xd3jv\x188\xfeD\x1d\x0e\
+\x97\x8a\xe1\x8e\xf4\xcd\xc7\xaaE\xc7\xc61\xe2\xce\xce\xa0n\xb1\xb28\x8c\x0b\
+\xf8\x02\xa9\xc5 \x82\xde\xc1\xbaLF\xf4lr\x02\xcaL\xe9x\xf6\xf8\x19\xba\xb8`\
+\xba\xb8\xb8h\xd7h2\xe7\x92|\x01\x01V\x9c^\xe1Q\x0e\x13R\x8a\x03\t\x04\r5gZ\
+\x1d:\x13,\x1e\xce\xf2\x9d\xa0\x8d\xd9\t\x1ev\xc0^\xcf5\xbdf\x1b\xbd\x0c]\
+\xda\x01\xd8_\xe9\x8a\xd9o\x0b\x9d\xa0\x8c\xa3T\xae\xf4\xca\xfa\'\t\xec\xfb"\
+W~\xf7\xc8)\xf1R"\xb0\xcc\xc0L@\xecW\x1da\xe9\xca\x14\x02\xbb\x97:\x93,\x00I\
+\xfd\xb8\xab\xfe\xd5\xc8\xa2\xc6\xa7z\xaf\x93\xe3\x86\xcf\xa9\xd7|:\x8b\x92\
+\x16\x01\xd9\xb6\xbe\xa6\x1bpX\xa7\xb4\xe5\xf1\x93\xe4W\xaf\xd93fwC.\x8c\xd0\
+F\xcd\xe5)\x0f\xde\xb7\x8f,\x91na8N\x10VS\x87\xceJ\xb9\xdc|H\xdea@`\x08\xc5\
+\xa4\xf3\xcb\xb1\xd2T\xe0\x0b\xa7\xa9\x9b\xd0\xa0\x8e\x1c\xf6\xbcv\xe3\x9d~\
+\x9c\xc8#\xd2-^\x0b\xb1\xe0#\x8e\xfb\xcc7\xd7\xf1\x92*\x8e\xdb\x96\xab\xf5\
+\xeeS\xf2l\x80\xca\x0f\xfeT?Q\xeb\x8e\xf4\x80Y#\xeav\xc9N\xdf\x15o@z\x99\xa8\
+\x1f\x13\x89\xe1\xb1I!\xf6D\xd9\x18u\xcb\xc4^\xdeRO\xbd\xed\xa8\x82{ip\x8b\
+\xea\x7f\xdf*m\xecO\x0b\xdczD\x15\xe3c\xcc\xdc\xf8\xc3\xf8\xc0\x9f\x90\xb6\
+\xd1\xc8\xf6\xd4\xa3\xd4\x1f\xcc\xeb\x9b-\xc4\xf5\x0e\xe8\xe9\xd30\xe1G\xfc?\
+g\xf3\xdc\xc5\x91\xc6\t\x03\x82\x8bD\xde#\xf2\xb2\xd0\xa7-\x86\x08\xa8\x1e\
+\x97\xa7L\xdeP\x96\xbf;\x1b0\x84\xfd\x1d\xcb\x0fV\xe4\xd6^OV\x91\x0e\x0br8\
+\x8d\xe7q*\xa1Rb\x01\xc99\xc0pyF\x06~\x1b\xf4\xb3}\x8do\xa0B\xcbr[\x10\xf22p\
+\xa7c\xba>A\xcdMy7\x11\xd8\x0f\xfa;3~\xc8\xdd\xb9\x11\x90Fm!T\xa3\xf9\xb3\
+\xd6a\xd5<_@"\xdf\xc2\xee<8\t\x96\xd2&\xf6$\x1c\xd5\xc9\x9eC\xfe\xcdK+\x8aSs\
+\x9f\x05\xd4\x1f\x16\x10\x10b\t:et\xc6\x8f\x83\x12\r\xbb\x1c\x95*=WE\x9c\xcd\
+\x98\xa2\xb5\x9c\xcd\xac\xd5]\xdevo\xf4k+\xc3(\xef\x87f`YM\x0ff\xa2\xb1\xbb\
+\xa7;\xa9T\xf8I\xcenb\xba\xd5\xe0$\xf69\x83\xc7)\xcd6\x8by\xd2\xffn\xa5\xb5\
+\xbe\x13\xff\x9b\xe63\xa2V\x944\x17\x03\xbc\x9a\x1cC\x86\xbc?\xa0\xf7p8\xab\
+\xe4\xcdN%]#h\x1b\x0f\x9ds\xd5dB8q\'\xa4\xb0\x13l\xd6\x9e\xa1$\xcd\xca\xeb\
+\xc7\xdf\xe6\xef"7f\x91\x8ce\xeas\xf5f\x97!\xc4\xd0\x8e\xcf@\xc7\x928\xda\
+\xe3\x83\xa9PZ\xd1\xebVs\xcd$\x87\x85Mus\xd0|\xfe=h\xb9\xe7\x90G{\x91;|xdN\
+\x86\x9b\xfc\xb62}\\\xdfp\xaa]\xa14\x99\xc4\xea\xf7\xdd#\xd1\xbd\x91\\r0\xca\
+\xacp\xfa\r\xea>eUE\xc5n\xd3l\xab\x8d\xa3^\x02E\x91\xf2\xa7N\x9a:\x1e\x0e\
+\xcd\'\x8f78\xb9\x15\xab@(\xfc\xa6\x92\xee\x1cO\t\x14\xf0qc\xa5B\x01\x8b\xe6\
+c\xb7N\x88\xbbY+-\xfd\xe4\xdf\xaf\xa6\xe6\xbe;\xa9\x9b\xe5\x0b\x9fQ\xe2.D\
+\x9c4cEKG2:\xf1`\x1f\x85e\x18\x01\xf0\xb5b\x93w\xf2\xba^\x1a\xc9-\x95\xa1/v\
+\n\x91\xd3w<6h.\xb4\xc8NY2\x1f|\x84\xefuB\x99h\x89\x0c\x91\xe1\x85X\xe6N\x07\
+\xfb\xa5tQ}yni)\x98\\L1~\xfe\x89\xab\xc8\xf0\xc6\xed\x12p4W\xdf7\xd8?\xbf!\
+\x01\x06\x84\x14\xe0\xc7@\x89\x85\xddH\x07\xdfHC\xeb\x84\xce\x0c\xbb\x1dq6\
+\x9b9\x08H\xa9\xe4\xcc\xab\xe9s\xde\xa6&\xa5\xe2n\x7f\xbdG\x1e\xf2b\xc2\xa0\
+\xaf\x88\x155\xbf\x15}\x91u\xc4\xcd\xe8\x18\x14\xf5j\x9c\xe7\xa5\xf1\xd3I\\\
+\x9bpQ\xf5h$23`\xdb\x05\xc0%\xe9\xa5\xf6\xfe\xae`f;+\xe6\x1f\x16\xa9\x16\x96\
+k\x9eWU\x93\xf6\xf7%-\xe5\xdd\xbf\xc7\xccN\x10\xb5\xf7\xfb\x92|%\x1f\x11\xaf\
+U\xa7\xa6f\xa0\xe2\xd7\xf9\xfe\x98D\xc2\x99\xda{5\xf4\x19\'\xd0\x8a\x1bc\x86\
+\x87\xeb~\xe4=r+\x19\x03\x9d\x10\r\x86\x10\r\x01\x90d\xb1\xdah\x0eHN!\xae\
+\xd9(.>\x8d\x80\xc9@\xfb\xfe_\xca\xe4\xde\x00\xb3|\x19^\xbd\xb7&\xa6K\xc3\
+\xf6=\xcd\xac\xac\xdcV\x05b\xad\xc9\xc0i\xf4\xb8 !\xf4I<\xa6\x957\xe7\x80\
+\x14\xc0e\xfb\x00\xf9\xc5\xe3\xb2\xfdS.#&\xaf\xac\xfb/\xdc~\x7f\x8b\xf7\x8ew\
+\xef\xf5\x1ah!\x94\x81\xce\x1d\x88\x0fa5^\x9a\xe0\xee}\xec\xe0[\xf9"\xac~\
+\x10HV-\x9e]R\x98\x9a\xdc\xfb\x1a#w\xcf\xaa\xa5\x94\xef\xbcF\tP\xe1\x86\xcds\
+\xd9\xc8\x89.\xe5r1\xe4\x80\x12\xca\xd5\\\xean!=\xc3"\xc0aZ2\x86WC4\xf7\x8a(\
+\xfe\x86$v\xca\x10J\xb9\xf0\x88m\xbeo\xc2R*C\xde\xa3f\xc3\x9e\xb2\x8a\xf5\
+\xbaP\xdb/\x99`\xb2\x83\x99x#\x9d9\xa2\x9fyNmA \xca\xf9C\x0c\xa6\tw\xe7\xa9\
+\xf6680\x9f\n\xd3\xa0\x0f\x96\\\x80\x86H\x98\xb9\xc8eP\xaeQ\x13O\xcd\x19\xfc\
+\xc5\xb4\xf1u#\xadtA[\xfe\xdcP\xfe\xeed\xfc\xcb\xfbm\xe9\x8f\xb4N\xb6\xf1&\
+\xd7\x97\xd2\x95e\r)u\xe8\xca\xb6\x82\xec\xac6!qf\x01\x8b\xd2\xb3\xd3w\xa0\
+\xc5\xb6K\xe2\xc0n\x7fzd7\xf3\x8d\'\x1cR\x12\x0f\x84\x8a\xb0.)6\x1f>\xce\xd2\
+\xa3\x83+\x1dQ\x1f\xe6\xed&\xd6\xe9"\x15\xdf\x08\xb5\xdb-\xa595\x14=X.\xfdI\
+\xcfs\xa0\xccCq\x93D\xe7\x87V\x99\xb4\xca\xd6\xc2\x02u\\\xd7\xfb\xcf\xcd\x9b\
+p\xaf\x15Y\x8e\xbfP\x1e\x95j\xa6 \xef\xda..\xe7\xc58\xc4C\xa6B/:\x81\x8ekZ\
+\xf0\xb9F\x83\xab \nK\xd5O\xd2\xaaz\x8f"#\xec\x847\xb8f\x9f"\x9c\x8d\xcb6W\
+\xfd_\xfa\xe7\x80w\x00\xb4\x83\x11\x0e\\\x16\x1d\xb8\xc0\'\t@!\xa9\x10\xec\
+\xa9\xf2S!m\xcfm<\xc9\xbfu\xb9\xc4e\x82N\xcc\xdcF\x0eA^\xe3\xe5b.\xcaFNa\xd9\
+Y\x02\xbe\xc0eW\xae\xf4\xdd\x98\xcf\xb3.CH\x0c\'\xd3\xf5]\xde\xd3\x93\xac\
+\xff\xe4\xccR_Q\x18\xfb\xe9\'\xc8\\n\xe7a\x90\x8c\xeb1!vq\xcd\xc9\xad\xee:]\
+\xa7\x17\x91\x9c\x89\xd5\xd7\xac9x\xc6(\xe8\xe3\xa0\n\x08B\xa2\xfboC\xea\xd2\
+$qg\xb0?\xfd\x12\xdd4\x1aN\xabs\xa7!\x8cu\x8b"\x81DYjl9\x9f\xdc\xce\xa2\xc14\
+1\xfe\x1a\xff\xaa\xd8fe\xcag\'\xfaK\xd0\x0e\xb6n+<\xdb\t%\x01\xda\x90\x1d\\\
+\x90G\xaa\xd4R\xa2\x8c\'\xef\x07>\xf2;\x82\x7f\x8e\xb4\xe6$\x1f!\xc2\x8c),\
+\xab\xf9\xcd\xc1\xc9\xf1I\xa3\x91\xe3\xcb\x12\x8bof\x9d\xfd}D\xdb=\x817{3\
+\xd1\xa26\xa5"R\xd7i:q$\x93l\xb0\xd5\xc2\xdc\x94\xcd\xcaj\x85\xc9G"_oE;q\x00\
+\xe9|\xef\x83 =IB\xf9\x81\x04\xaeA\xbd\xaf\xd1e:\xa3|\x18O\xea\xb0\xcd\xba\
+\x12\x81AW;\xb8\xe6\xd0\xb1duZJ(\xe9\xc1\x9a\xbb\'\x18H\x9d\x03m\x7f\xbbm\
+\xc0\x97Fl\xfd[\x97?K\xb4b\xaf\xb3\x83\x0ew\x05\xa0o\xadnj\x07\x0e@\xca\x85A\
+\x99C\xdf=\xe6\xa7\xc7\xb7\x9a\x83\xf7n\xcf,\x95\xe3w\x7f\x86V=\xd6o+\xb1\
+\x8e\xf5 \x14\xd4]\xca>*\x08\x1c\t\xaaCx\x04\xdd\x81\xc1k\xeb\x94\xa4\xacUm\
+\x9b\xe2^\x1eG\xfb\x08\xb0Z\xa0\x07\xe7\x17Gwwh\x0c\xe2\x15\x86\xb9\xfas\xde\
+Xb\xe5\xa4\x807jd\xa7<H\xba\xa7e\xc47\xce}?&\xbe\xa7\xe8\xf8\x97\x91\xc5\xae\
+H\xb9x 3\x16pM%\xfdA\x94\x83:C\x8ee\x9a\xc6F\x97\xdbe\x17\x181\xad4\x90\x83W\
+7\x91HB\x0f\x12?\xf7k\xe8\xdc\xc8|\xcf p\x0e\x80\x9c\xa8l[\xc6\x8cX\xa3\x06(\
+\x06\x1d\xa1\x98\xd4\x92\xe4\x84R\xbf#\xb2\xe3?\x0e\xbfe\xc2{\x94\xa9H[\xf4\
+\x16\xfc\x01$r\x07v\t\xdb3\tb5\x84\xc7\xabC\x14=UD\xcc;\xc7\xdf\x05"BE\x97xD\
+\xb5Ny\xb1\x80\'\r\xbc/"\xc0;\xeeY\x160n\x934\xdf\x1eb\xbf\x81\xb6\xd0\xa7\
+\x86\x83@A\xf5O\x9f\x93\xd1\x85b\xc9\xfd\xf8\xc4\\\xcd\xa2\xdaY\xdf\xd1M\xa5\
+,\xb4K|\x80\x0c\'\x9bB8\x8fw2\xf4\x80\x08\x0c2\xc0\x0f\x99\x88\xb3\x94\xf2\
+\xf7Y\x8e,\x1e-\xf6\xe35\x059\x01\x85\xdcA\x96\x08\x18\x9a\xf7\x96\x18!\xaf\
+\xae\xc8\xc1B\x03\x8e\x89\xba\x08y\xb2\xb8\xda\xb1\xa2UD\xf1\x97!w\xe4\xe1\
+\x96\xe9\xd8\xff\xfb/@m\xa6\xc4S\xd2\xa5\xe3\xa4q=f\xabC\xb1U\xc3|\xd4\x7f\
+\xbc>\xea\xdf\xea\\\xe3\xf9\xb3:\xca\x1a\xa2A\xd5\xd2\xbd\x0eC_-\x1f\x95\x80\
+\xe21\xa72\x1e\x19\xec\x91\xd1JKg\xe6\x96\xec\x04r\xe37l\xd8\xab\x8b\xa4\xe4\
+\t\x14P\xfd\xb6Ykj\xfc\t\xe2\xa1\xc9eP\xb9\x01\xfbc\xc5qpD\x80\xdd\x01\xacKY\
+\xc7\x01\\\xbdT\xdf\xa3Y\xe1;\x1c\xbb%\xfd\xe2,\xabF2$\x85\xa1g\xbb\x00\xaf\
+\x96\xb8A\xd2J\xb3Q(v\x82\x16\xa7\xd8\xfe\xea\x0b\x8fhC\xcb\xdb;\xbd\x08\xb9\
+\x10R2\xab,\x85.\x96\xb25\xde\xcb)+\x13D\xae8<wL2Rwh\x08]\xdc\x8ca\x9cpcpR\
+\xe7\x0c\xc5\xa9\xbf\x87\x0b\xb6\x9a+s&ST\xc5\xf32&8\x15\xf6k\xdf\xa7\xb6\
+\xb8GQL\xb8\xb1\xde@\xd6_\xcb\xa9\x08,\xf8\xa7G\'\xc3 Pt\xd3h\xd8Y\x82X\x92\
+\x1c\xbd\xb2L\xcc\xf1\xfb\xact\x9a\x05\xf3\x15\xe2\x041\xd9\xff\x01\x9c@c\
+\xbfCh\xdf\xfb\xe5\xfe+h\x18K\xe1\n\xb8\x92.38\xe3b\xae\xfcno\xa1}\xf6\xc4}\
+\xc4\xc4\' h\xd4\xe3\xec\xb5\x86n9\x1bn#\x92\xde\xac\x06l\xe9\xa1\x1f\x08\
+\xdc\xbf\xb2\x13\x05H\xdd\xfd\xa8o;L\x04\xb3\xbeG:.O\xd1\xe4\xfbV\x90\xb9\
+\xdc\xff\xc7{\xfa\x8f;T\xf9\xe1.\xd1w\x11\xa9\xfb\xdc\xb5\r\xdfB.\xc3\x81.\
+\xe2C\x8f.\xe0\x03@\x96dN<\xb7\x85\xf8\x92L\x12&\xa8#_\x93g\x8e\x0b(\xe0\x92\
+M#I\x13%E\xcdi\x1d\xfc0\xc9\xc2\xaf, \xff\xaa\xd9~\xd3m\x8d\xdd4l8N\xdb\x9e\
+\x1a,\xe5-8-\xfe\xc72\xfb\xf1\xcb\xc2n\xa80\xdc8-v\xbf\x9a\xe7\x87~\xf4\x9f\
+\x88c\r\xc2\xe5\xae\x92\'0\xa5\xc6j\xce\xfb\xd6\xf8G"\xcaR\x18\x0c\xfa[\xa1m\
+\xb0\xe8\xaf\xf5\xed\xc2(\x80\xdd\xe7+=+\xd5A\x8aQ\x998\xb1f\x8a\xdf:\xb7=\
+\xf3q\xd0m\n;\xbd\x9a\x18\x05(z\x17j,<ef\x0e\x19\xcb&h\xce\x1b\xff\xb5\x85\
+\xb4\x1f\xa8C\xeaU\x8b\xb8/\xe1\x9e+\x97\xf8\x0f\xd7\x18\xb8/\xc2\xd6\xe0MQt\
+\xa2\xcb\x18\x15p\x19G\xbc\x15{J;\xce\xc4n\x9cq=HF\x1b\xb2A\x02AF\x90Ep\x88\
+\x18\xecf\xc4\xdeX\x8c\x968\x0c]\x89\x18;\x13\x10|*\x8f\xc8\x0e\'\xd5o\xecc\
+\xcaw\xd4c\x87\xe6\x8c\xc0\t\x91\xb6\x00%Y\xcd\x19\xf1Q\xab\xbb\x1e\x88\xc4\
+\xc9\x19\x9a\xe2]\xfb\xcf\x83\x9c\xfe\xd3.U\x8b\xd0\xd1\x8e\xad\xb1\xdbO\xc0\
+\xcd\xa9q8\xbb\xb5\x876\xfa\x83w>\xfa\xbd\xd3\xd7!;\xb5EZ4\x8aC\xe6a\t\xc6`\
+\x89\xb8\xdd4M5\x06\x0e\xae1q\xed|\xf9@\xe2\x1d\x89\xf5\x1d\'\xca\xd8}\xba\
+\xad\xf4J\x02\xa6\xbe\xc2\xed\x16\xfc\xaf%\xe9\x93\rA\xadD\xef\x18\x80\x85Ar\
+\xa8\xe5\xc5\xda\xd3c\xca\xb63\xf9\xfe\xf3\x026\x16\x8a\x1f\x9fJ\xc9\x9dgs\
+\xfc\xa9O\x07\xecF\xf7\r\x80\x1b)\x04\x8bw\xd1\x89.cL\xc0eli\xadX\xf3kq\xc6\
+\x07\xbe:eA\x02\x93\x84\xc3\xe4\x80x\x0b\xb6>\xe3Z\x90E\x8c\xedI\x98[\xd31\
+\xb7\xa4!\xf4\xf5\xb2\xec\xd8W\xeb\xb7\x8d`c\xca\x92\xc5\x86\xbd\xa3\xc7/\
+\x08.~B\xfa\xa0\x0bx\xcee\xfe\xfd\x8c\x9b?/\xa7\xe2\xa5\xedC2.\' \x90\xbem\
+\x91\xe6<_7\xe0\x89\x8f\xd6qd\xeb[\xfd\xdeWwE+\xf1\x13\xd3U\xd3\x12\x8a\xd3i\
+\xfc\xf8D\xbf\xb7\xe9\x8d\xaa\x98L\xdf\xfb\xfbf\xaeG\x96\xf1+\xa1jL\x8c\xc1\
+\xd6\x12aU\x8d\x00$\x1e\x0f\\\xa6\xb4\xe5,\xff\xac\x84D\x93Hx\xc9\x8d\xa3\
+\x8b$\xa3L\x87C\xfdEw\xd8!_\xdb\t\x12\x16\xbe\x82\x13\xac\x88\x8b\xaf\x15.\
+\x18D\xa6<}\x9d\xdb\x0bc\xebrr\xfc\xbdF\xa6]=\x0e\xd1\xe89\xce\xcc\x15%t\xf4\
+\xa4R\xb7K\xe3\xacxe\x0f\x8cvt\x97\xfa\xe03f\x04\\\x16\x9dt\x97\x9c\xc2\x96\
+\x16Y0\x91j\x1b\x82\x84=\xb5\x1d{j;\x8e\x94v\x12\x8e+\x8d\x08\x1c]\xfe\x16]0\
+W\xb8,+)ci\x0b\xd4\xd6I\xda\xbc<\x9a7\x05\xeeI\x1c\rR\xe7\xfa\xa7?\xd5\xbe}p\
+\xc8\x82jB\xf5\x15V\x113\x80;1\xd0q\xb0\x8e\xac\xf3JT\xd3R\xe6\xe6\x03\x83\
+\x97z\'K\x12\xf6V\x0b\xe6tu\x1aR\xcc\xb8\xc4\x88\x04\xdc\xa4Q<&Z\x0c\xa7+]\
+\x96\xa3c}\x03\xa4\x9be\xaa}R\xb8\x1bm"\xd3C\xe4\x81G",\x8b6\x18\x02\x8a\xb8\
+\xaf+\xbd\xe8k\x0bH*P~\xb3\xb2$q\xecg\x1f\xd0y\xa4\x81S\x8d\x93)\xb9{\xa9j\
+\xdd\x89\xab\xd3\xe8\xfeh3]\xc7\x02\x0f\xe7D\x96\x11\xa0\xc6\xb7\xeb\xdep\
+\xa1\x8b\xf8\xe02&\x04\\\x16$:\xa7\x96\xe1H\xf2O\xd3\x12E#\x99\xc5\xd3\x883f\
+\xd0\xf4A9\xc8\xe04\xd9q\xc6[p$u"\x1bC\xbb=Mi\xfeB\xd3S\x1f<%\xacmg\xb5\x9f\
+\x80\xa7\x9f3\x01\xe3\xef\xb7\x07\x8c^\x1f(\x86X\xa3\xa60t\x97k\xa4\xdb\x0c\
+\x02Z}\x85\x83\x8axo\xff\x9b\xc6\x00\xb4n\xadD\xfe\x7f\x92\xeaf\x16?>\x95\
+\x84I\x99t\x1f\xf7\xbfqjuP\xea\x0f\x96\x8a6?\x01O,\xc9\xa4\xf3p\x83\xe6\xf2\
+\xbe\x0f5\x82\x00%w\x9f3\xe0\xe3\xf0&;\xce\xa0*\xf02\x18"\xee\xebFW\xa2\xd0\
+\xd5\xdd\xc8\x02\x85\x01\xf4\'pm\x9cY\xe6\x80\xa0n\xcb\xde\xe5\x14h\xb3\x0b\
+\xa4\x86\xa8\x85\x1em2\x96N \xf7\x8b\x1e\xefV\xf9K;\xe8<\xa2\x9c\xef\x86ue\
+\xd8oI`Z\xe2\\\xf7|\xc1 2\xf5\xfe\x95\xec[\xfbN\xc0\xe6H\xa1D\xcf\xb7\xc9\
+\x887bRR\xbf\x1e\x00\x06Chu\x11\x1f<\xc6\x84\x80[\xf3k4\xc5;\xa61\x8b9\xd7}\
+\x99\xec\xb3\'\xd3\xdb\xd0I\xe7\xff\xfd]5_\x16d\xec\xa9m\xf4\xe6\xd4c\xd7X\
+\xdfE\xf2L\xff\xaaj\xae\x8b7\x10\xcd\x9f\x953\xe1\xb6E*W\xbb!\xceD\xde\xd5\
+\xb38\xfd\xa7]A\xd6\xec?\xa29\xc0\xe9\x0e\xb7p\x95(`\x88\xa0L\xe6P\xe0-J\xce\
+%\x9bU\x02l\xef\xe8\xa1yS\x85_4\xf0\xf8\x9b\xe7s\xe4\xc7\xff\xf1\xf3:D*\xde\
+\xf7N_\xe77\x06\x0e\xd0y\xb8\xde\xaf\xcdk\xea\xc2\x02j5r\x7f\xb5\x1ej\x0e?\
+\xba\x9b\xb4E\xc1[)\x02~)l\x007\x9eu\xa3\xdf\xb4MM\xff\xe0\xe8\t%e\xef\xda\
+\xbc\xc7\xdc\xd3\xbd\x8f\xddl\xd6\xee/\x1e\x8aGyT\xf5\xde7uL\xf0\x11\xd8\xea\
+\xde\x81E\x98\xffg\x9d\xba\n@C\x8fH\xec\xc4\xd9$ey\xbe\xefc\xdd\x06\xceJ\xd5\
+\x0e\x14\xed\x0f\xa1\xac\xf0\xe5e\xe9\x94|\xdb\xf3\xdbi\xfe\xbc\xdc/\xcf{S\
+\xf3\xbf\xc84\xe7\x90i\xf6\xdc+\xccY\tL\xbaw9G~\xfa!r?\x03\x1c]\x0f\xc0K\xde\
+\xfc\x9aj\xdc\xddhr\xf4K0\xfbk\xf5\xf7\xa0\xd4s\x17*=\xf5\x0eLm\xa9\x18,\x8a\
+\xc1\xe0-\xe2\xde\x8dd\xbc\x89\xa4\x95\xa8\x8e\xc2\x19/\xe0\x92\xc9No\xae\
+\xffM#\xb6n\x1c\xf1\xa7\xc7c2)?0SZ\xbc\xdf\xcdF\x90\x05\xcc\xadi\x98[\xd3\
+\xb0\xe6\xd6b-\xf4/\xce"\x08\x90s\x99\xba\xa1\x82\xecp\xd2\xba=xI@{\xbb\x95\
+\x86\x8f\x8e3\xee\x02u\xa4l\xde\x95\xb3i\xdf_G\xfb\x9e\x9a\x00k\xf6\x1f-W?@L\
+N\x92f=ho\x04Q\xa0\xf8\xce\xa5\xc4\xe5\'\x07]n\xa8\xf9s\xf9\x85\xee\xd7_\x9e\
+\xa0t\xe1\xf2\xb6,\xab^\xdbC\xe6\x8a\x89\xaa\x06L\xa9s\xf3\xc8\xbf\xb6\x94\
+\xaa\xd7\xf6\x0ex\xffZ\x15\xe1Z\xb7\x9d\xa6\xf0\xa6y\xaai)\xa5y\xc4\x17\xa5a\
+\xa9\x08>\x84c\xb7\xc0\xf8/\xcf\x0b\xba\x0ch\x8bw$\xb8\xbe\xb7\xf7\xba\x14/\
+\xd0[--\\\x99\x9e\x1el\x95~a\x14\x05\xec^\x81}\xc9d\x91@*\xddx~o\x91X\xdfo\
+\xbf\xeb\xdf\x13{\xee\xe5)*\x01o\xb2\t\x1c\xb7\x0c\xcd\x10\x81\xc9dd\xea\xf7\
+V\xb9\x9b\x1aY\xab;8\xf1\x1b\xff<o\x87\xec\xe0?\ropM\xfe71\x0b\x9e\xc0\xca\
+\xd4yy\xe4_WJ\xd5\xab\xea2\xb2.\xc2\xf5\nIV;\x86\x04\xcf\xc3\xb5)%\x0ecbL\
+\xc4\xb5%\xfak%[]\xb1\x17^N\xc5\x84\xc2\xd9\x88\xa8cn\x062,\xa0\xe3\xcf\xc8\
+\x18(\x19Dl\x19-JP\x9a\x17\x82\xddH\\\x95\xda}-\x9a\x0c$N\x0e\x9c_l\xec\xd6\
+\x8e*\xcf\xbdb&IS\xd4\xeb\xd5\x7fX\x16V\xab\xd1\xaaWw\xfb]`\x82(0\xed\xc1\
+\xf35[\x9a\x06#6\'\x99\xd8\xbc\xe0\xe2*K\x92f\xad\xf6q_\x98\xac\xb1\xb4\x07c\
+b\x0cS\x1f\\E\xf6\xea\xe0=\x9eC\xe1\xeb.\x0f9\x06\x1e\x00y\xf1\n\xe4\xc5+\
+\xfc\x82\xc8\\\xa2\xe4m\x95[\xab\xda1\xf9W\xbe\xa5\xf0\xa6yL\xb8u\x11B\x84\
+\xa5aM\xc9\xb1\xe4_5\x9b\x84\x89\x81\xc5\xae\xbb\xbc\xd5olS\x10`\xd2=\xcb\
+\x02\x16\xf1A\x06{\x07\xd8\xfa\xf4=X\xa0\xdd@\xc4\xfb\xf5\x9a\xfb\xdd\xaf]\
+\xe2\xed\xe2\xad\x96\xe8\x0f\xa5\xc4\x99\xfc\xa3\xb1K\xc5\xd5\x1aK\xaa\xb1\
+\xf6\xb9\xc2\xc3!\xdb\xeco\xbd\x1e\xeb\x12\xf9\xb2\xf1g\x18\xd1\xf6\x18y\xa7\
+;y\x13\xe8\xfcj\xa5\x8d\t\x02\x9c\xbf\xfa\\\xa5\xd4. \xf5:9\xf6\xcb\xf5\x01\
+\xe3_:\x1c\xad\xaco\xfc\x87\xdf\xf4\x82\xeb\xe7\xaa\xda\x99z\x13\xaeW\xa8\
+\xb7\xd9?\xbe"\xd06\xbd\x89\xcdN\xf4\xbb\x7fE\x0b\xe1\xe4Q\x84\xad\x1b\xfd\
+\xfe\xee\xfa\xe5F?\xeb[\xa7\x7f\x9c\xf1\x16\xb8=\xc5?\xaa\xdb\xdc\x92\x8e\
+\xa0Q\xc5i\xd6\xa3\x97\xd2\xba\xb3\x8a\xbaw\x0f\xd1\xbe\xb7V\xe5\xd62\xd8}n\
+\x04\x82@\xc1\rs)\xbca\xaej\xb2\xbd\xd5J\xe5_v\x87ul\xb6\x16+\'\x9e\xf9\x9c\
+\xa9\xdf[\xa9\x9a.\xc6\x18\x98\xfa\xc0JZ\xb6WR\xf7\xcfCt\x1c\xac\xd3t\xb1\
+\xc5d&\x90:?\x9f\x8ce\x13H\x99\x93G\xd9\xe3\x1bC6Si\xd9^I\xde\x15\xea\xa7\
+\xe2\x9c\xcbgbk\xb6P\xfb\xde\x11d\x87G\xfc\xc4\x18\x03Y+J(\xbcq\x1e\xa6\xb4\
+\xe8\x04U\xf5W\xb4\xbd\xf1X\t\x81\x85\xc0%\xe2\xd9q\x06\xcc\x89J}j\xa7\xcfPc\
+\xee\x17g\x92\xb6\xb0\x90\x9a\x7f\x1c\xa0ysE\xc0\x87.sF<)\xa5y\xa4/\x19O\xda\
+\x82\x02\x04\x83H\xe71u\x858\xdfq\xec\xaa\xbf\xeda\xda\x0f\xd4\xc7\x97P\x9c\
+\xc1\x9c_]N\xe5\xab{\xe88P\x8b\xd3\xea\xe0\xb3/\xbd\xc9\xe2?_\x85\xbd\x0b\
+\xa4>\xaf\xaf\xb5\xaa\x9d\xa2\x9bJ\xb0\xf88a\x04A\xe9Ko\x8a\x89Q\x04\xdf\xd6\
+\xbf\xca}\xaf\xd7\xdc\xcf\x9f\xb90\xf4\x82Q 5V\xa4\xa3G\xfd\x00}\xbd\xe1\x87\
+\x9c\x94vS\xc7\t\x95\xf5m\x93\x05\x1a{\x05jzD\x1am\x02\x93\x13\x9ca\x8de\x8f\
+\x8b\x910\xc4\xc84\xf6\xaa\x05\xffb\xf1N\xe6\x99.\xe4=\xe97l\x97\xde\xa5K\
+\xd6~@\t\xe7\xfc\x82\xbf+}N\xe9L\xa6L)v\xbf?\xf9\xdb\xcf\xb0\x9c\x0e\xee\xc9\
+*\xb7\x1c\xa3\xfa\x8d}\xe4_\xe3\x19\xb2\x10\x04\x98|\xefr\xf6\xad}\x07*\xfa\
+\x97\x85\xd2}\xa2\x89\xf8\xf1\xea\x06,\xe3\xbf\xba\x80\xae\xe3M~\xf7\x04cR\
+\x0ci\x0b\n\xc8\\^L\xca\xbc|\xaa\xfe\xb6G\xf3\xf3\xea\x8c|\xcex\x01w\xc6\xf9\
+\xe7\\\x9b\xba\xfdkd\xbbH[P@\xda\x82\x02l-\x16Z\xb6\x9c\xa6\xfd@-\xd6\xd3m\
+\xd8\xbb\xd4\x96S\xea\x82\x02?\xf1\x96z\x1d\x1c}x}X\xd6\xb7\x8b\x96-\x15\x9c\
+\xfc\xddf\x8a\xef8\xdbo^\xfa\xa2B\xd2\x17\x15\xe2\xb4\xda\xb1T\xb6\xe1h\xb3*\
+\xad8\x93b\x88\xcdI\xf2\x0b\x94\n\x87\xda\xb7\x0f\x92s\xf14U\x9dsA\x80\xa2\
+\xaf/\xa2\xe0\xbaR\xbaN6\xe3\xb4\xda1%\xc7\x92P\x9c\xa1Z\xce\xdenE\xfe\xff\
+\xec\x9dw\x9c\x14\xf5\xfd\xff_\xb3\xbd^\xefw\x94\xe3\x8er(E\x11PQ\x11Ab\xc3\
+\x825\xe6\x1bC\x14%\x881\xf6$_\x13cb\xf2%Jl\xf9I\x8c\n\xc6\x125\xb1a#\x82\
+\x1d;\x10T@\xfa\x1dw\x1c\xc7\xf5\xdbk\xdb\xcb\xcc\xef\x8f\xb9\xd9\x9d\x9d\
+\xb2;\xb3;\xbb\xb7\xb77\xcf\xc7c\x1f\xb73;m\xef\xe6\xe6\xf5y\x97\xcf\xfb\x1d\
+\xa4`(\x8c>\xef\xe4\xbb"\x03\x90\x96\xd7w\xf3\x12\xc44\x06-\x08\xbd|\x97\xa6\
+PE3\x00aW\xa1?\xa4\x01AP\xe1y\xbfBtzBxq\xdaz\xfcp\xf7u\xf09\xf8"n\xaa\xc8\
+\xc1\x84\x1bOE\xf5\xcaS\xe1k\x1b\x80\xaf\xd3\x89\x907\x00BC@g7\xc1Tf\x8f;x\
+\x11K\xce\xeb\xfe\xb4\x91\x17\x7f7U\xe4`\xe2m\xd1}\xd7|\xacg~\xa0\xdf\x83\
+\xc2Y\xb9\xbcih\xcc\xbes_\xfe1\xe6\xe2\xc7hk\xaa\xc7\x9dK\xe8J#;Y\x96\xf3\
+\x9fW\xad\xe2\xedw\xe7\x9f\xfe\x84\xd9gEw1\xfb\xd1\xf8\xf5\xb8\xfa\xfb\xebx\
+\xdb\xee\x94i\x85o\x8e\xd3!\xae2W\x87\xe6\xbe\xe8xt!Q\x89\x07\x0c_\xa3\x89\
+\xda\x85\x1d\xfdZ\x90 \xe0\x0e\x11p%\x11\xb6>1\'\x88o\x06t<\x11/#jp\x9d\xf6\
+\x11\\\xab}\x18\x1d8\x0c\xf3\xbd\xe6\xc8\xdf\xb7\xa2\x04\xa6\x9f])yp\xaa1ha4\
+\xd2\xf7qqI\x11N?#R\xe9e\xff\xfez\x0c\xfc\xb7\x05Z\x93.\xaa\xd2\x1a\x17\x83\
+\xc6\x88\xd67\xf7 gZ9\xec\x93#\x96\xaf\xcen\xc4\xe4\xbb\xceD\xc7\xffn\x06\
+\x15\xa4\x07<\x04\x15\x92<;\xa4\xe7\xcb#(^\x10\xed!3\x16Y1\xf3\xb1K\xe0jp\
+\xc0\xdf\xeb\x82F\xa7\x85\xb1\xd4\x9eqa0\x95\xc4\xc9z\x01\xa7\xf4|w\x16\x11\
+\x8c|m\xe7\xc1.\xe4\xce(\x87\x86#0\x86\x02\x0b\xca\xce\x9b\x82\xb2\xf3"I9\
+\x9b\x1f\xfc\x16A\x1f= `b^\x0c\xben\x17\x0e\xde\xff\x11\x9c\x87zd_c\xc7\xa6\
+\x03\xf0;<\xa8\xfd\xf9<\xe8\xecF\xde\xe7Z\xb3^17\x97\xdf\xe1F\xc3c\x9fc\xe2m\
+|\xf7\xa1\xd6j@\xee4\xe1.[\x83{;p\xf0\xc1-\x18\xb7l6\x8aN\x8f\x16%\xb6\xbb\
+\xbf\xf3\xe3zp\x8b\x86V,\x9d\xc6\x1b\xecH\xc1P,\x1c\xb6\x98\xf3\xc2\xd5\x00\
+\x807\xea\x01\xbb!\x88s\xab\xdb\x01\x00\xb7,\x0b\x84\xe3\xdf\xdc\x96\x9a/M[\
+\x0f\x8dV\x83\x13~r\x02*/\x9f\xce\x9bfC\x10\xb4@\xc6\x0bC0\x08u\xb0\xe2r\xf8\
+o_\xc0Tf\x87m\x92\xb4\xcau~\x87\x1b{\xef\xd9\x8cy\x1b.\x89\xbfq\x92\xfc\xe6\
+\xfb\xeb\xf0\xc7\xe3\xa3E|B\x8c\xed\xc5\xf8\xc1\xf2\xe5\xd8\xbcn\x1d\xd6\xae\
+y\x04\xab\xee\xe47t/\xb5\xe9Ph\xd1\xa2\xc7\x1d\xfd\xf7\xd0@\x8b\t\xc4\t\xe8\
+\x881\xd6\x15\x1b\xc0\t\xa1%\x80\x93r\x82\xa8wkP\xef\xd6\xf2\x84\x8f\x00\x81\
+2\xd4\x00\x12oC\xa1\xbf\xef\x98\x1f\x9d\x88\xb9\x17\xf1\xeb(\x00\xc0\x94)\
+\xb5\xc0\x0b\xb5\xe8\xfdo\x0b\xf6\xffQ\xbc\xdd\xce\xd2\xf2\xeb\x90\xf7<\xbfK\
+\x1e\x00Xk\x8bp\xee\xcb?\n/o\xbb\xea\x9f1\x07\x03l\xfav\xb4`p_\'\xecu\xd1u\
+\xf8\t\r\x01\xdb\xc4B\x00\xc2\xe7\x040\xec\x15\x02U\x12\'\xfb\x05\x9c\x10\
+\xb89Y\xcf\x85\x96\x97w\xa2\xfd\xdd\xfd(:\xad\x1aE\xa7W\xc3>\xa5D\xb4>\xb89\
+\'\x1f\x83]\xd1\x16=\xe9\x0b\xa2\xfd?\xfb\xd1\xf2\xcaN\xc1\xd2\xa3R\xe9\xdd\
+\xd6\x8c\xefVu\xa2\xf2\x8a\xe9(={24F\xe9\x16+\xe9\x0f\xc1\xf1U\x13\x06\x0fHs\
+\x83u\x7f\xda\x88\x90/\x84\xda\x9b\x84\x07\x0cl\x02\x03^\xb4\xbc\xf4\x1d:6\
+\x1f\x00ER\xf0\xb6eVI\x90\xceF7n=\x8f~`\x12\x88$\xc9\x94\x08\xf4\xc5&C$v<\
+\xbd\x03\xdd\x9f5\xa2\xea\x8a\x19(<m\xbc\xac\xf9\xb2d \x04\xc7W\xcdh\x7fg\
+\xaf$\x97c\xc8\x1b\xc4\xde{6a\xc2\xcaSP4\xbf&\xe6\xb6\x8e\xedGq\xf8\xb1/\x11\
+\xe8\x17\xae\xd2\x97\n\x18\x11g/+\rA\x00W\xf7O\xc6m\xba\x17QMHS\xcf<=\x85\
+\xf1f\x12\xf7\xde~#\x9e\\\xfb\x98\xacsM\xb4\x92\xa80\x928\xe4\xd6\xe2\xa8\
+\x97\x84V\xc6#N\xee\xdf7\x93\xa0H\n\x07\xd7|\x82\xc9w\x9f%\xb9\xd4\xb1\xab\
+\xbe\x1bmo\xefE\xf7gM\xa9\xbd8\x95\x94\x91\xf5\x02N\x90\x1aP\x9a\xe8\xd1t\
+\xc8\xe8\x85\x1e\x91v\x90\xc1A\x1f\xda\xdf\xdd\x8f\xf6w\xf7C\x9fcB\xce\xf1\
+\xa5\xb0O)\x81e|>\x8c\xa5v\xe8s\xcd\xd0\x18u\x98x\xfa\xf9\xf08z\x10r\xfaA\
+\xb8\x0c8\xf4\xf0g\xe8\xdd\xd6\x9c|\xfdr\r\x05\xbf\xbd\x1f\x9e\x1c\'\x1c\x9f\
+\xef\xc4\xce\xff\xfaA\x19\x83 \xa9\x10\x1d\xf7\xd4\xe9a\xb0\xd8`\xb2\xe7\xc1\
+\x9aW\x0ckn9l\xc6RP\xdd:\x0c\xec\xed@\xffw\xad\xb2\x07\x0f\xbd[\x9b\xf1\xcd\
+\xae6\x94,\x9c\x88\xbc\x13+@\xe6\x04\xe0\x1c8\x86\xc1\xaeV8;\xdb\xe1rt\xc3\
+\xefv\x82$\x03\xf4 h\x16\xfd\xbbt\x1e\xde\x8f\xb6\x97\xbfD\xc1\xd8ZT\xd4\xcd\
+\x829W\xf9\xcc\xe5d`\x97q,\x1eZ\xe6\n\xf9\x91C\x0e\x1c\xf9\xd3\xc7\xa8,\xb5"\
+\x7f\xce\x18\xe4\x1cW\n\xcb\xf8\x02\x18\x8b\xac\xd0Z\xf5 4t\xd9Sg[\x07\xda\
+\xbe\xff\x16\x8e\xe6z\xb8z;\x11\x089AjB@.@\x9c\xa8\x81\xc6o\x84\xd6m\xc6\xc6\
+s\xff\x82\xc5\xaf\xaf\x82\xdeL\xbbb\xd9q\xfe\x907\x88C\x0f\x7f\x86\xb6\x8d\
+\xfbP\xf6\x83\xc9\xb0\x1f_\x06c\x91\x15\x14I\xc1\xefpc`O;\xba>\xa8\xc7\xc0\
+\xdeH,\x98\xdd\xe0\xc2\xe7\x1aD\xfb\x81\xef\xe0h>\x84\xc1\xae6x\x07z\x11\xf4\
+\xfb\x00P\xb8\xf4\xd2K\xe1\xf1x\xf0\xf2\xda\xb5\xc8/)AQ\x19\x7f:\xa3\x1c\xfe\
+x\xfcz\xc5E\x9c)\xdaro\xe0\x078Ys\t\xe6h\x96`<1\x03%\x9a*\x84(:\x8b\xd6\xa4\
+\xa5`\xd3\x01\xf9:\x12\xa5&\n\xb6\xa1\x9e\xder\xc4;\xea\x9c:`fN\x08\x17\rN\
+\xc5,\xe2\\L\xd1\x9c\x8a1\xc4q(D\x15\xacTn\xf8\xef\x1b\x18\xf0\xc2\xe7\xd1\
+\xc2\xb5\xf30\xaa\xaf\x99\n\x8dI\x0b\xfb\xf8j\x1czHZ\x82\x95w\xb0\x0f\x1d\
+\x87v\xa3\xf7h\x03\x06\xbb\xe9\xbfM\xc0\xeb\x015\x9b\x02\x11\x8a\xdc\x1f\xfa\
+\x81\x1ch\x02\x14H\x81\x84>1Zv\x7f\x8d\xae\xe9_I\xde\xde\xd8U\x044VcU\x97\
+\x13\'\x93\x14\xaerx`\x9dP\x08]\x8e\t\x1a\xa3\x16\xa4?\x84\xe6\xed\x9fa\xcf\
+\x96W\xf8;\x9f\x14\xbdhj-\x83\xa5E\x9d\xc65\x12 V\xd5<\x94\xd5\xfe\x93\xfei{\
+\x102Ggh\xea\xdcV\xe4\xec\xa9\x03\xa8\xd4t\xaa\x92\n\xa9\x0f\xc0[\xd1\x0e_Q\
+\x17(\xad\xfc:\xd9\x9a\x80\x01\xc6\x8eb\x98[+\xe2o\xcc\x81\xd2\x90\x08\xe4\
+\xf6#P\xd0K\xb7\xa7\xd4%0\x08\xa1\x08\x98:J`n\x1e\x03BF\xd7/n\xf68 <\x1d\xcb\
+_\xdc\x03g5\xbf\x8f\xb6X)V\xc1Kd5V\xe0\n9\x03\xb7\xa0I\xc0>\x08_E;\xfc\xb9\
+\xb1\x13\x92\xd8\x10\xa4\x16\xc6\xf6\x12\x98[+\x04\x13$\xe3\xc1\x9dON\x1a}\
+\xf0T\x1d\x83\xaf\xc0\x01\x08y\x91d\xb0\xf0\xd2Ky1p6\xc9Z\xe1L\x1c\\\xc8\x85\
+.\xb7\xea\xda?_z\t_m\xdd*\xfb\x1a\xe4\x90\xbf\xed\xa4\xf0\xfdJ\xcd\x9d\x8f\
+\xb3\x1f\xe3w\r\x8b\x95l\x19\xb0\x0f\xa2cZ\x1b,A\xe9\tg\x94\x8e\xc0\xe0$\x0b\
+\x06\x8e\xb7a\xfa\x1dcE\xb7c\xeeQM\x99\x03\x9a\xc9M\x92\x8fo\xec*\x82\xb5\
+\xb1Zt\x8e5 \xfe\xff\xc4EH\xc0]\xd5\x8d\xf0\x15\xa7\xa6\t\x10\xc3\xd1\xabJ\
+\xc3\xdeOu\x1e\xb84\xb2\xde\x02\xd7\r\xd8x\x02\x1e\xb4\xb8\xe0\x1e{\x14\x96\
+\xe6\xb1Q\xf3\x83\xd3\x06\x01\xf8J:\xe1\x1e\xd3\x02J\x93x\x83\x0bR\xef\x87?\
+\xbfW\xb6\x80{\xc6\xb6\xc0[\xdc\x99\xd0\xa0!\n\x82\x82\xb7\xac\x03\x946\x04k\
+\xa3@\xdf\xcf\x14\x11\xeb!\xc5\x85m\x91\x97\x0c\xbd\xe7\n9\xb3\\l\x07\xdc\
+\xe3\x8e\xc0W(?\x8f\x81\xd2\x84\xe0\xadhC\xa0\xa0\x17\xf6C\x13\xa1\xf1H/\x03\
+\xcb\x16o\x8a\xa2\xb0dm!\x9e\xfb\xc7{<\xcfQ:P\xd2\nW\xaadj\xa6@\xe9B\xe1\xfb\
+\xc3"3\xe1\x8e\x08R\xc8\xd9\xeb\x82\xa5\xc5\x07\xd2\\"z\x7fp+\xe6\xc9E\x9d\
+\x9e5\xba\xc8z\x017v\x15\xc3W\xca\xaf\x8a\xe6-\xed@\xc8\xe8\x83\xb5q<4\x01\
+\x91\xb9\xb9)\x80"H\xb8&4\xc1/"\x12DP\x07}_.t^\x0b\x10\xd4\x00Z\x12!\x93\x17\
+\x81\x9c\x01\x90\xc6\xc4\xa6\rq\xf1\xe5\xf7\x88\x8a7\x11\xd4A\xef\xb2A\xe31B\
+\x13\xa4\x7f/\xa4.\x80\xa0\xc5\x8d\xa0\xdd)h\r\xfa\x8a\xbba\xec*\x86\xce)\
+\x9e\xdd?\xdc\xb0\xe7\xfd\n\xc5\xc7\t\xb3\x0f\x8e\xbaz\x10f\xfe\xef\x98\x08j\
+a\x18\xc8\x85\xc6c\x86&\xa0\x03E\x90\x08\x99}\x08\xe4\xf6\xf3\xfe&!\x93\x17\
+\x03S\xf6#g\xefTh|\xf2\xaa\xd6Q\x14\x85\x7f\xfd\xeb#l\xda\xb4-\xad\x15\x1a\
+\xb8\xb1\xf0T\xb8\xd2\x192M\xbc\xe9\x01^\xfc\xc1g\xc8\xe4\xc5\xe0\xe4\x83\
+\x82\xff\x83V\xab\t\xc7\x1f?\x01\x15\x15\x85xjc\x13\x00\x12\x95-\x01\xc1\xfb\
+C7\x10\x94t\x7f\x90\x83fP\r\x95\xb0\xe9\t\x10\x04\x01oY;H\x81\x84\\Co>\xb4\
+\x83V\xe8<\xf1g\xa4h\x9df\x98\x9b\xe9\xb9\xff\xbe\x92.\x90\xa6\xc8\xb5\x99Z\
+\xcb\xc2\xc9\xbd\xb1f\xe9\xa8d\x16Y/\xe0:\xb7\x05\xc6\x8eb\xf8J\xf9I)\x81\
+\xbc>\xf4O\xdf\rsK\x05\x8c\x9d\xa5 R\xedR\'\x00wM#\xfc\x05\xfc\xa9:\x04\xa9\
+\x81\xf9h\x15L]%\x00)t\x1dt\x0bTO\xd51\x04\xf2\xa4\xbbv\xa5\xa0\xf5\x98`p\
+\x14B\xdf\x9bG?\x08D\xbc\x12\xa4\xd1\x0f\xd7\x84\xc3\x82ee}\xc5\xdd\x92\x05\
+\\\xac\x04\xa9T\x12\xb52\xb8\xf1\xf1G\x9e\xa1\x07(\xdd\xdd\xfd\xb8\xed\xe7O\
+\x810p\x1e\x90!\r,-U0v\x16\xd3-fy\x07\x04|\x05=p\x8do\x02\xb4\x11k\x99\xd4\
+\x07\xe0\xacm@\xce\xde)\xb2\xc24\xef\xbc\xf35-\xde\x02\xe8\x07r\xa0w\xe4C\
+\xe7\xb6\xe2\xf9C\xabA\x92$\xf4z=L&\x13\x1e\xfd\xe7?\xd1\xdf\xdd\x8d\x9e\x8e\
+\x0e\xec\xd9\x9eX\xa3\x16\xae\x88\'K\xa2\xbd\xbe\xcb\xcb\xca0e\x12\xbf\x8f7\
+\xc3\xfe\x83\x07y\xeb\xcaJK\x91\x97\x9b\xcb[\xbf\xc5\xf7\x19o]\xd5\xee\x89\
+\xf4\x14=\xd6=\xfe\xfeM\x8dQnt\xae\xfb\x9c4\xfa00e?(\x81\xfb\xe3G\xd7\x9c\
+\x85\x05\x0bN\x80^O?J/\xbe\xf84\x9cv\xe3f\xf4W\x03\xb3?\x19\x97\xf8\xfd\xe12\
+\x83r\x99a\x1e\n\xef\xe8\x06m\x18\xa8\xdb\xcf\x1b@\x07\xedNX\x8e\x8c\x85\xc6\
+\x1f\xff\xf7\xad\xf5X`\xf6X\xe0+pp\xc4\xbb\x1c\x96\x16\xe1\xb6\xaf\x91}\xe9X\
+\xbe\x18\x81\x1c~r\xab\xd6k\x86\xc6/\xc38\x921\xeb@\x85&\xeb\x05\x1c\x00,\
+\xcdcA\x9a}\x827\x19\xa5\r\xc1=\xee(\xbce\x9d\xb4\x90;\nS\x16\x1b\xf7\x96v\
+\xd01M\x0e\x9a\x80\x1e\xf6\xfd\x93\xa0\x8d9\x8a&\xe8\xc1Hw\x91\xe2\x02\x9e\
+\xb3wj\xb85j,4>\x03l\x07\'\xa2\x7f\xfan\x9e5\x10\xb4:E\xf6\x12F\xaeh+\t\xb1u\
+Kx\x00\x11\x08\x04\xf1\xe8\xa3\xaf\xf1\xc5\xdb\xafGhW-Ld\x8cA\t\x05\x18{\n\
+\xa1\xf5\x19y\x0f\xd7\xa0\xd5\t_\x11\xed\x99\x88\xc7\xadu\x1f`\xe5\x9bS\xf0\
+\xdak\xfc\x81\x89&\xa0\x87\xad\xbe\x06\xba\xc1H99\xb7\x9b\x0e\ty\xbd^\x0c\
+\x0e\x0e\xe2\xea\x1fD\x8a\xb2\xfc\xf0\x87\xfcZ\xe8k\xee\xbe\x1b\x07\x0e\x1c\
+\x88{\x1d\xec:\xe9\x7f<~}T\xd5\xb6X<\xf0\xc0\x03\xf17\x824\xeb{\xe1\x82\x05X\
+\xb8`\x81\xe8\xe7\xabn\xe1\xc7\xd9\xcf^\xb8\x10\'\xcf\x99\xc3[\xff\xbb\x96\
+\xdf\xf3\xf7\x7f\xe5\x02\xc1\xe3\x8a\xc5\xbc)\x82\x84sb=O\xbc5\x01=\xec\x07&\
+a\xf1\xe2\x18\xf9\x18\xac\xfb\xa3\xff\xf8}`\x17\x84\x94s\x7f\x00\x80\xcei\
+\x83\xb5y\x1c\\\xe3\x9a\xa2\xd6\x93\xba\x00\x9c\xb5\xf5\xb0\xef\x9b"<\xc8\
+\xe4\x102{\xe1\x9e\x10\xe9x\xa8\xef\xcf\x81\xe5\x98\x84\x8am\xede0\xb5\x8b\'\
+I\n\xb5\xb15\xb7\x95\xc3\xd0\x15c\xfa\x1a\x17"v\xf9i\x15>Y_J\x15\xa0\xfbx\
+\xdb\x0fN\x82\xa1[\xfcf"\x8d>\xb8j\x1a\xd1\x7f\xfc\xf7C\x89C\xca^\x03i\xf0\
+\xc3]%p\x83R\x04l\x07\'\xc6\x11\xef\x08\x1ao\xeci_r\xd1zM\x92\xc4\x9b\x81\
+\x08ia\xec\xe6OS!\x8d\xa9\xe9\xa0\x96j\xde~\xfbK47s\x84\x85\x02B{\xabA\xb9\
+\xcc\xe8\xf4\x84\xe2\xc6$uN\x1bL\x1d\xa5\xbc\xf5\x9e\xf26i\xf7\x11A\xe1\xcfw\
+\xbf\n\x8a3y\x99\x08\xea`\xdf[\x17%\xde\xa9\x84+\xd8lA\xe7\xf1\xe4\x0e\xfa%@\
+\xa2\xd6w&\xe2\xa9hC\xd0\xc2)SJ\x01\xd6\xfa\x1ah\xdd\xb1\xffg\x99\xaam:\xa7\
+\r\xce\xc9\xfc\x9a\x06\x92\xef\x8f!\x8c\x1dE\x82\xff{A\x9b\x0b\xee\xf1\xcdq\
+\xf7\xa7\xb4!\x0c\xd6\x1e\n\xe7Vh|\x06\xd8\x1aj\x86=\x997\x1e3\xeam\xe1\x97J\
+4\xa3B\xc0\x01\x00$\x01\xdb\xe1j\xd8\x0eO\x00\x11\x14\x17\xac\x90\xd9\x0bWm\
+\x03\xfa\x8f\xff\x1e\xfe\x82^\xc5\x84\xdcS\xde\n\x08T\x0c3\xb5\x96\x8b\xd6Y\
+\x17B\xab\xb4\x80\xcb87\x83\xd0 \x82\xd2\xa6?\xe1J\x88\x87\xf7-\n\xbf\xe2\
+\xd1\xd7\xe7\xc4\x7f\xfe\xc3\xcfx&\xdb\x8a@\xf5G?,\xe2\t\xb9\x90\x80\x93&\
+\x9f$\xcf\x84?\xaf\x17!\x0b\x7f\xfe\xb7\xe5\xc8Xh}\xca\xfe\xbd\xe3!\xd5\xea\
+\x96K\xa6\xc5\xbe\xd9\x88\xd5E\'\xf5\x01x\xcb\xdbx\xeb\x8d]\xc5\xd0\x0f\r\
+\xaa\xb8\x9e\xa4\xd3n\xdc\x1c\xb5\xcc\x88\xf8\x98\x7f\xf1\xfb\x08H\xbd?XW\nK\
+\xd38\xe8\x04\x06\x0e\xbe\xe2\xae\xa8,\xf1\xfbJ\xc9\xf0\x8b\x86\x82\xb3\xba\
+\x11\xa4\x99.EHP\x1a\xd8\x0e\xd5F\x15\xb5J\x07\x8b\xb6/\x0b\xbf\xe2!$\xda\
+\xaa\x88G3z\x04\x1c\x00@\xc0\xd0]\x88\xdc]\xd3`\xec,\x8e9\xf2\x0c\x99=p\xd6\
+\xd6\xa3\xff\xb8=C\xd3\x89\x12OW\xa74$\xfc\xc5\xfc\xa45\x82\xd4\xc2\x1c\xc3-\
+%\x04Aj\x93N\xba\xb37\xd4\xc2\xbeo2\xec\xfb&\xc3\xd2\x12\xdf}\xc6\xbb\x06\
+\xc1\xdbf\xf8g#rE;\x96\x88\xdfZ\xf7\x01>\xf9\xe4;\x04\x02\xfct\xe2\xbc\xca\
+\x8bE{e\x8b\x89\xb8\xc6g\x80\xd6\xcb/\xc9\x19\xc8\x8f\x1f\xee\x10\xca\xcf\
+\xd0zMt8G\x80U5\x0f\xc5=\xa6R\x88Z\xe17\xcc\xa2_\x1cRa}/_\xb9R\xf1cJ\xc1W\
+\xd2%<\xe8n\x8b\xaeVxk\xdd\x078\xed\xc6\xcd<\xf1f\xa3\xf1\x19\x10\xcc\xe5\
+\x8b\xa5\x94\xfb\x83\rAj\xe0\xd6\xf5\xc1\xaf\xe7g\xb1\xbb\xc77!hu\xb2D;\x82\
+\xb7\xbc\x03\x81\x82H\'<k\xd3x\xe8\xdc\xf2\x07\xef\xc9 Tr\x98\x81\xddJ\xf4\
+\x9a\x0b\xeaT\xa1\x96\xc8\xa8\x88\x81s\xd1\x04\xf5\xb06\x8d\x87\xb9\xa3\x0c\
+\xee\xf2V:#\\D\xcbC\x167\x9c\x93\x0fA?\x90\x03\xcb\x911\x92]\xddl\x82y\xfd\
+\x82S\x82\xf4=y\xb2\xdc\xd7\x0c\x1a\xafQ0#U*Z\xa7\x15\xe9i\xb6\x98\xc9Px\xf3\
+\xa5m\x00\xe79\xa8uY\xa0\xdb\xb33f!\x18v\xa3\x94\xa8}\xdd&\x84L\xd1\x96t\xc0\
+\xe6D\xacJ\xdb\xa4>\x80@\x0e?)\xd0\xd0S\x18sL$&\xe2\x0e\xf0c\x91\xa7\x15]\
+\x8cEA\xbe\x87 \x16\xec\xef|y\xc5\x1a\xd1\x01\r\r=\x08J\xd5\xb4\xb1u\x8f?\
+\x9e\xd4\xfe\x89A\xc1W\xc8\x9f\xf7\xacuY\x04\xbd"\xf1z\x86\xcf\xfeX\x0b\x7f\
+\xae\x0e\xba\xfe\xe8\x01c\xbc\xfbC\x88\xb2\xef\xe6\xe1\xf5\xeb\xc7\xe1\xcc]\
+\xafE\xf5?\xa6\x08\n\xabm\xfc\xe7\xd3\r\xafO\xc4\x9fWG\xee\x0bSg\x89\xbc\xd8\
+t\x9a\xb8\x86\xd3\x96Y%>\xa3R\xc0\x194\x1e\x13l\x87\' \xd4V\x01oE+|\x05\xe2B\
+\x1e\xc8\x19@\xff\xf1{aj+\x85\xf9X\xa5\xa4\x84\x91\xf0\xbe\x02Y\xdb\x00`\xe8\
+\xcb\x13\\\x1f\x0fcw\x11\xb4\x1e\xfa\xdf^\xebO\xaf\x8bu\xa4\xc2\xed\x16F\x9a\
+\xfcQ\x99\xb8\x0c\x86\x01:\x9bYJE7\xae\x90k\xb8\x1d\xeb \xdcL\x87M0w\x00BJ\
+\xad\xef\x1f\xde\x86\x13r\xe6#\x1fyB\x87q+\x92\xe8D\x92\x010nt\xe6\xef\x1e\
+\xef\xfeH\x04\xd2\xcc\x7ff\xc4\xbb?\xc4X\xfa\xd4\x11x**\xe1\xa9j\t\xaf[{\x84\
+\xef\x11\x01\x80\xbf\xfd\xed\x8d\xf0sM\xe7\xb2\xc1|$\xb3\x8a\xa4\xcc\xa8\xb7\
+a\x06T\xf1N\x84Q\xe6B\x17F\xeb1\xc1\xda0\x01\xb9\xbb\xa7\xd1\x89nb\xaeu\x82\
+\x82\xb7\xa2\x1d\x83\xc7\xed\x93\x95\xb4\x15\xe2&\xc1\x0c\xa1Kp\xbe\xa5\xb1\
+\xab\x18\xd6\xa6\xf1\xb06\x8d\x87\xa9U\xb8\xf9\xc8h\x84\x1b\x8fd\x96\x85\\w\
+\x01\x91\xd8#30b`z\x18Ss\xe7\xa3\xc4\xac\x15\xb4D\x99\xf8\xb8P\x056J\x17\x8c\
+Y\xac\'h\xe5\xb6~\x01\x00\x02Z\xb72\xed[\x95"\x9e\x98\xdf\xb5\xf0.\xc1\xf5\
+\x99\x1c\xfb\x8e\x85\xd4\xfb\x83\x8dP\xcfp\x86\xed\x0bB\xa0\xb4\xfc\xe7J\xbc\
+\xfb#\x16\xe6\xb6r\xe8{i#@L\xbc\x01``\x80~\xfe\x10\x01\x1dl\x87jd\x19\x1fJ\
+\xc2\xcd\xf4\xff`\xf63\xb2]\xe5;k\xe5\xcdv\xc9vF\xb5\x05\xceE\xeb\xa5-r\xb2\
+\xb5\x12\x9e\xcaVA\x17\x1a\x00\x04-n\x0cL\xdd\x0b\xfb\xde:IIF!\x81\xe2\x0f\
+\x04\xa9\x917G2\xc5P\x9a\x10B67\x82f7H\xb3\x0f\xa4\xde\x0fR\x1f\x00\xa5\r\
+\xd1\x0f\x18\r\xc0X\x8a\xc3Q!L*R\xa7\xa7\x91&\xaf\xe0\xfa\x90\xd9\x03_\xb1@#\
+\x8b\xc3\xaf\x82\x9a;\x19\x00\x90{\xf8\x00\x06\x03\xfc\xdf\x81\xdb\xe8\x12t\
+\xe0P\xfa \x08\x9f\xf0\xc3](yM\x13\xd0\x81 \x87?\xc8\xc1\xb5\xc2;=\xa18\xae\
+\xf4\xcc\xa1\xa0\x85\x1f2Xu\x85\xf4\xdc\x01\xd9\xf7\xc7\x109A\xf1\xff\r}\x9f\
+\xb0\x97"\xd6\xfd\x11\x13\nxd\xa0\x06\x90\xd0_H\xa3!`\xad\xaf\x914_<\x950"\
+\xaef\x95+\x83*\xe0\x02h\xbcFX\x1b\xaaal/\x86kB#Bf\xfe?3\xa9\x0f\xc05\xb1\
+\x1e9{\xa6\xc6\x9d\x86!Tg\x9c\x08\xe8\xa1\xf8\\5\x99P\x9a\x10\xfcE\x0e\xf8\n\
+{\x10\xb2;Ae@"Z\xba\x10\xcb!\xf0\x08d\x1d\x87\xa1\x9a\xe8\x9f\xd5\xf2\\WT\
+\x8c~\xe5\xa4\x81?\xb8\x13r\xc5\x0f\x17R\\\xe9k_\xbeMp}\xa6Y\xdf\xe3V\x04q\
+\xe4\ti\x8f\xbc\x84\xee\x0f\x00\xc5\xb1\x8a%\xb6\n\xaff\xdf\x1fk\x1bn\x8bJ\
+\x1c\\\xdb \xfc\xbbe\xb8\xaf\xf4/1?_5\x8e\x9e\xeagj\x1a\x03\xfd`j\xc22m3>\
+\x87\x11\xd2ByRE{g\xadS\x15x\t\xa8.\xf4\x18\xe8\\6\xe4\xec\x99\n\xbdH\xac:hq\
+\xc3_\xc8/\xcc\xc2C\xa8\x88\x97`\xb5\xb5tA\xc1W\xdc\x85\xbe\x99\xbb\xe0\x1a\
+\xdf\x84\xa0}0\xab\xc5[\xc8u\x07m\x1a\xbf/!n\x95\x85\x84\x06w\t$6\xa6\x0b\
+\xa9q\xf1T\x88\xb7-?\xb5\x03\x82\xa8\xe9d\xc3p\x7f\xc4\x13\xebD18\n`j/\x89\
+\xbfa\x82\x94\xef<-\xee6r,n\xd5M.\x1d\xd5\x02\x8f\x03Aja;T\x8b\xc1)\x07\x10\
+\x14HF\xf3\x17:b\x16\x88\x01\xe8\x02]<#}\xb8\xf4\x9b\xa0\xe7\x83\xfa\x8b\xc4\
+\x1bv\x10\x01\x1dt.\x1b\xb4>\x134>=4!=\x10\xd2\xd0\xa5f):\xa1\xcf[\x96Y\xd6U\
+<x\x95\xb6\xd28\x80r\xf8H\x88\xd5\xdb"\xb4\x02C\xa7\x0c\x8bP\xc4\xb2\xc2\xc5\
+\xaco\xa5QJ\xbc%[\xe1i\x1e`\'*\xde\x05_\xde\x01\x00p\x9c\x1a\xc3\x12\x1f\xc6\
+\xb1\xb9\x1c+\xfa\xb9w\xf6\xd1\xfb \xb3\x92\xec2\x19U\xc0%@P\x04l\x87\'\xa0o\
+\xfa.~-b\x8bP\x12\x12\x87\x90\x16\xd0E\xc7\xbfH\xdd\xf0d\xed\xba+\x8f\x89\
+\x887\x01cW!\x8c\x9d%\xd0\xb9,\x885\xc2\xa0\xf4Iv1\xcb\x00\xc4b\xcc9\xdfOMh~\
+l\xbc\xb6\xa5\x9d\x10\x9ez6R\xfc\x1el\x11\x8f\x17\x0b\xcf\x04\xd7\xb9\x7f\
+\xda\xae\xf0{\xc3\xee\xe9\xb2\xf7W\xe2\xfe\x10\x9bV\x06\xc4Nx{\xa5\xf5\xce\
+\xb0\x1b\xfd\xf2\x8a5q\x8b\xeb\xe4\n\xd4\x81g\xe3/t\xc0+R-0\x95\x8c\xb9_\x9a\
+[}g\xad3j\x1e8 ,\xfc\xaae\xce\'\xeb]\xe8\xa4\xd1\x07\xd2\xe8\x03\xa5KNt4>\
+\x03\x0c}\xf9\xbc\xf5\x94>\xbe\x10\x0b%\x8eP\xba`\xf2\xed<e\x12\xadq\xdd5\
+\x00\x00 \x00IDAT2y\x05+K\x11\xa4\x06\xf6}\x93`m\xac\x1e\xaa\n\x97\xd9\xa5\
+\x15\x95@\xe3\x15\x8e3\x0b\xe5;H\x81\x9d\xad^|\xe6Y\xd2\x0b\xc1\x08X\xdb\x99\
+R\xd5.\x16\x9d\x9eP\xda\xaco\xb9p\xaduF\xcc\x99~\xe5R\xa6\xbc)}\x7f$\xc3[\
+\x8d\x0e\xde\x8bA\xaf\xd7\xa3\xf1\xb8\xdf\xc6=\x86g\xdcQ\x04m\x99%\x80;k\x9d\
+\xaa(\'I\xd6[\xe0}3\xe8\x7f^s[9\xccGcw\xdc\x89\x87n\xd0\x06\x7f~t\xcc\x9b\
+\x92`Bi=f\xc1\xa9dA\x8b+e\x89%B\xf8\x8a\xbb\x04\xb5\xd9rd\\Z\xaf#\x13\x10k\
+\xbf\x18\xb2\xb9\x81\x9e\xc4\x8b\\\xc8\x9d?\xae\t\xeaA\x1a\xa2\xa7$R\xc3\xe4\
+\x9d\x89\x05\xd3\x83\xfd\xf2{?\x8a\xb9]\xaa\xacogo\xa9\xa21p1W:3\x08\xd3\xed\
+{Gp?9\xf7\x87\x94\xe2.\xc92w\xee\xdc\xa8A\xe0\xed\xfaV\xe8\x07\xed\x18\x9c|\
+\x08l\xff\x0e\x05\n\x1d\'\x1cE\xf9\xd7\xb5im\x9f\xcc\xb0,pr\xf8\xfdp62\xca6\
+\xb2\xde\x02g\xe0>$\x13\x81\x08\xf1\x7f]\x1a\t\tG:\xa7\xb0\xcb-\x90\xd7\x9f\
+\xf45\xc9!\x98\xcb\x8f\xe1\xd3\xcdI2\xaf*S\xaa\xd1:\xad\x82\xedc\x85:\xd6%\
+\x82\xd4\xf9\xe3!\x0f\xffaJ\x1a\xfd\x82}\xd7\xe3\xc1kw\x99B^y[\xd9\x9a\xe9R\
+\xca\xa5:{\x85]\xc0\xdc&0\xb1`\xac\xf0x\xa4\xfa\xfeP\x82\xba\xba:\xbcE^\x1c\
+\xb5\xcer\xac\x12\xfa\xfe\\\x98[*x\xdb\x9b}N\xb8j\x0f+\x9e\xb0*\x16\xe7\xa6H\
+\xfa<l\xf1\x06b\x978V\x91\xc7\xa8\x11\xf0\x90\x02\x02.\xe4.\xd7H\x98\x07n\
+\xe8\x17\xceb\xf7\x15\xf6\x80\x8a\x91\xa1\xac4!#\xdf\xfd\xa7\xf5\x983\xbe\
+\x1bQ* H\r\xf4\xfd\xfc\xd8a\xc8\xec\xe6w\x9fJ\xe6<C".&\xe4\x94@\xc1\x16\x8a \
+\x13p\xd5RpU7%~\xa1qXu\xff\x16\xac\xba\x7f\x0bJ\xccZQ\xf1N\xc6\xfaN\xa6\\j \
+\x10=p\xe1\n\xbdX\x0c<\x96+]\xa9\xfb#^q\x97D)--\xc5\x8c\x193\xa2\xd6\xdd\xdd\
+\x13\n\xff/\x9b\xdb*\xa0\xef\xe5_\x7f\xc0>\x00\xef\x98c\x82\xc7\x94\xd3\x08\
+\x08\x88\x9fYN\n\xd4JPQ\x96Q#\xe0JX\xe0\x01\x81\x18\x92V\xc4\xbaf\xa3\xf1\
+\x1a\x05\xb7\xa3\x0c\x01\xc1F\x16\xa9B0\xb6\x9a@\xb6m\xb6L93v\n\xe7\x86{\xab\
+\x8eA\xc9\xf42\xb65\xce\x089\x03\xd5/|\xff\xf8s\xe45\xb9\xf0\x94\xb7\x0f5\
+\xdd\x19}\xb8\xdc|A5\xec\x9e\x1e~q\x91j\x85\xa7\xeb\xfe\x90\x8b{\xa0\x0f\xf3\
+\xe6\xcd\xc3\xdf\x9aO\x8aZ\xaf\t\xb2\xbc9\x14`k\xac\x11,4\xe5)o\x83?\xbf7j\
+\x9d\x9cF@R\xa7\x84\x1d\xbd\xcf\x95P\x8c[M`\x93\xce\xa8\x11p\xca\xe0G2\xfft\
+\xa4\xc1\x8f@.\xdf\xe5-\x94\xd8&\x84I\xa4\xeb\x98\xa7\xaa%\xe1z\xc8r\x11,\
+\xf5)\xd3\xed\x1a2y\xe1\xa9\x14\x1e\xc1\x8f4\xf4\xfdy\x82\xad\x19\xfdy}\xf0\
+\x95\x08W\xe1K\x06\xc1D\xb7\xde\\\x08%&\xf8\x8b\xbb%\xbb\xd1\xfd\x85\x0exD\
+\xac*\xa5\x19\xee\xa2-z\x1d?n\xdd\xd3#>%R\x8cX\tm\xcc\xdfH\xa9\xfb#\x9e\x15\
+\xfe\xf0\xbeE\xf0\xfbw\xc1\xef\xdf%\xba\x1dC(\x18\xc0\xe7/<\x05\xa31Z\x98\
+\x7f\xdb\xc1\xff\xdf&\x82\xf4\x14X\xa1\xff{\xd7\x84F\x84D\xaa\xcd\x89\x11K\
+\xb85z\xfe9\xc8\xa1\n\x94b%\x8eU\x92g\xf4\x088A%1u\x8b\x82{\xdcQ\xde\x03U\
+\xeb5A?`\x97t\x04co\x81`\xdfoJCbp\xcaA^\x17+9\xd7&\xf5A/\x94Y\x1b2y%\xbbk\
+\x83v\'\x06\xa6\xeeS\xc4\x9b\x91\x11P\x80\xa5i\x1c\x84\x04\xd45\xae\x89n\'\
+\x99\xcc\xe15\xa4\xe0\xef*J\xc8\xb5F\x18\x04]\xb5^t\x17\xb4\xc7=\x87\xaf\xb8\
+\x0b\xce\t\x87\x01P\xd0x\xf8-&\xb3\r\xbb\x9d\xff\xffv\xb8\xa9IV\x1c<\x14\x8a\
+v]\x8b\xba\xd2\x15\xbc?\x84D\\\x03\x12o\xfd\xf1\x94\xa8u\xf1D\xfc\x9b\x8d\
+\xaf\xa1\xe7hS\xcc\xda\xe7l\xb4n\x0b,\x8d\xe3y\xeb)m\x08\xce\x89\r\x92\xca"K\
+\xb1\xb8\r\xb9\xfcg\x0b\x9d\xf5N\xff]n\xad\xfb \xfc\xe2\xc2L!#H`\xc6-\xea\
+\x1cp9\x8c\x1a\x01\x07\x00\xe7\xe4C\xb4\xebHV\x82\x10\x05w\xd51^\xf69\x00XZ\
+\xaa\xa4\xc7\x8f)\xc0z\xb8Z\xd0eM\xea\xfd\xe8?n/\xbc%\x1d\xa0$^\x1b\xa5\x0b\
+\xc2W\xda\x89\xfei{$7V\x11\xcb4w\x8do\x8c\xd9P\x81\xd2\x84\xe0\xae<\x86\x81)\
+\xfb32C:\x19tN\x1b\xcc\xc7\xf8\t? \x00\xd7\xf8&\xb8j\x1b\xc2\x96\x84$\x08\
+\xfa\xc1\xe5\x1a\x7f\x04}\'|\x07\x7f\x9e\xb8[\x9b\x11qC\xee\xd9\x82\x9fk&\
+\x1cCW^;:\xbd\xfc\xbfM\xc8\xe0\x83\xb3\xe60\x1d\xf7&(\x10\x14\x01{C\x8d\xf4\
+\xebL\x80\xe1\xb6\xbe\x01:\xf6\xcb\xa5\xa3\xa3\x03\xbb\xf7\xec\x89\xb9\x9f6\
+\xa0\xc5\xd6/\xbe\xc2\x03\x7f\xf8?l\xffj+\x00i\xaet\xa5\xef\x0f\x02\x80)\xe4\
+D\x91\xff(\xc6\xb9w\xe3\xbb\xef\xea%\xef\xdb\xf8\xedV\xd4o\xfd\x8c\xb7\x9e)\
+\xe6"\x86\xb1\xa7\x10\xc6\x0e~%\xb6\x90\xd9\rwu\x13\x00J\xd0J\x96S=-t\x98\
+\xef\xaa\x0f\x99\xbd\xf0\xc7I\xd4\xa54!X\x9b\xbc(\xf9\xc0\x01\xf3\x11a#f\xd3\
+\xa5\x9b$]\xc3h$\xeb\xa7\x91\xb1\tZ]pN\xac\x87\xc6g\x84\xa9\xab\x18\x86\x9e\
+\x82\x98Ih!\x8b\x07\xee\xb1G\x11\xc8\x11p\x9dw\x15B\xef\x90\xd7\x0eT\xeb1\
+\xc3\xd60\x01\xce\x89\xb4\xc5\x14\xfd!\t\xf7\xf8fx+\xdb`p\x14B?`\x87\xc6c\
+\x84\x86\xd4\x81\xa2\x00J\x17\x02i\xf4!du!\x903\x88\x80mPv\xa6\xb2\xa1\xab\
+\x08\xdeR\xfe\xc36hw\xa2\x7f\xda\x1e\x98\xdaK\xa1\x1b\xb4C\x1b\xd4\x83"(\x84\
+\x8c^\x04s\x07\xe0+\xee\x16\xac\xe7\xce%J\xdc)"\xa3K\x82\xb21\x1f+\x07i\xf0\
+\xc1W\xccw\x8b\xfa\n\x1c\xf0\xe5\xf7B?\x90\x03}\x7f.\xb4.34~c\xd8-IiC \r~\
+\x84\xcc\x1e\x84l.\x04r\x06d\xf5j\'\xb6n\x81\x01\x14\xf4s& \x80\xc3\x9c\x0f)\
+h\'\x1d\x05U\xd5\x85\x9e\xde\x1cX(\x03\xa0\r!hu!`\x1f\x882\x0c\xad\x8d\xd5\
+\xd0\n\xb8{\x81\xa1\xcc\xe9!KK\x130(\xda\x0b:\xddE[&\xd5\xd6b\xdf\xfe\xfd\
+\xbc\xf5\xcf<\xff<~\xb0h\x11\x8e\x9b:\x159v;\xcc\x83fX\x07\xad\xc8\xef\xccG\
+\xe9\x91RT4U\xe0\xa9\xc0\xdf\x01\x00g\x9cufx\xbfUw\xde\x82\xb5k\x1e\x89Y\xa1\
+M\xa9\xfbcj\xb3\x0b\xee\xa2\x01h)\xf9\xb3\x05z[\x8fb\xfb\x86\x17\x01\xc4\xee\
+<&\x86\xa5y,BV7o.\xb8\xaf\xb0\x07\xdaA+L\x9d\xa5a\x11O\xa4\xec\xa9\xbe\xc2.\
+\xf8\x9ct\xd5\x1eF\xe8X9\xfd\xbb\t\xeaAQ\x14H\xa3\x1f!\x8b\x1b\xfe\x9c\x01\
+\x04\xf3\x06P\xf0%=@u\xd6\x98\x05\xcf{\xcek\xe7\xa81p\x11F\x95\x803\x90F\x1f\
+\xdcU-pW\xb5@\xeb1A\xe7\xb4A\xeb3\x83\x08jA\x11$H\x93\x1fA\xdb\xa0H\xabG@\
+\xdf\x97\x07k\xd3x$R\xf0\xc4\xd0[\x00k=\xe0\xae9,hm\x93\xfa\x00\xbc\xa5\xed\
+\xf0\x96\xc6w\x9f\xcaE\xe7\xb6\xc0\xd8U,\xd8M\x894\xfa\xe0\x1e\xd7\x1c\xf7\
+\x18\x1a\x9f\x01\x86\xee"x+\xf9\x9d\x19zO\xfc6\xfc^\xdf\x97\x07\xfb\xc1\x89\
+\xfc\x03\x10\x80\xafH\x9a\xeb1`\x13\xee\xa3\x1e\xab\x1b\x14\x1b\x83\xa3@\xe2\
+ \x82\x80\xb5\xa9\x1aD@\x07o\x85\xc0\xef\x9d\xa0\x10\xc8\xed\x17\xcc\x81P\
+\x06\x02\xd6os0p\xbc^P\xfc\t\x8b\x17\xb0x!\x16d1\xb7T\xc5,\xe7\x1b\xc8\xebC`\
+\xc8\x13\xa0uY\x12\x12\xf0L)\xda2\xe7\xa4\x93\xf0\xce\xbb\xef\xf2\xdc\xe0>\
+\x9f\x0fom\xdc\x88\xb76n\x04\x00\\\x8c\x8b\x85v\x8f\t[\xc4\xa3\xfb\x83+w\x7f\
+pK\xac\xff\xe5\xa5\xbd8\xeb\xac\x13\xc3\xcb\x06\xc3P\xd2\x9d\xd9\x0bM\x1e-Z\
+\xf5\xdb\xbf\xc0\xdeO6#\x14\xe4{\xbffw\xc4\xcf\xde\x0f\xe4\x0e\x804\xf8\xa0\
+\xef\xcf\x11,\xe6\xc2\x84\x07\xc7\xfe\x91\x0e\xf1\r4\x90\xc8\xa9\x89]\x17\
+\x82+\xa8\x86\xeeB\xb8+\x8f\xf1\x8c\nJ\x13\x82gL\x0b<cZ\x90(\xaax\x8b\x93\
+\xf5\x02n9V\toq\x97h\xdc6d\x96\x1e\x03\x06\x05\x98\xda\xcaan\xa9\x04\x91D\
+\xb52\xa3\xa3\x00Z\xaf\x11\xae\x9a\xc6\xb4%\xb01X\x8e\x8c\x05i\xf4%4\x9f\xd5\
+\xd0]\x08k\xf38\x90z\x9f\xa0\x80K\x81\xa2\x92\x9f\xee$u\x7f\xfd`\x8et/\x00\
+\x05XZ\xe8\x8eM\xae\xf1G\xe4\xb9\xcdE (\r\xb4\x01i\xe5$5\x01=l\x07&ap\xca\
+\x01\xe9a\n\n\xb04\x8f\x81\xa9C8ARQv\xd0]\xad0+b\xfd\rG\xc9\xd4\xbc\xbc<\x9c\
+\x7f\xee\xb9x\xeb\x1d\xe1B+\xf1\xd0\xeb\xf5\xc8\xcb\x8f\xf6\x9c1VxLRp\x7fP\
+\x84\x06!\x8d\x11\xa7\xdd\xb8\x99\xf7\x99&\xd7\r\xcd$z@\xcdX\xde\x00\xdf\xfa\
+\x9e={6\x1a\x1a\x1ab\x9e\xc7W\xdc\t\x7fA\xaf\xf8\x06\x04\x9d\xe3\xb3\xff)zq\
+\xec\x92\xb1\xa2\x02.&\xa6\x1a\xbf\x01\x96c\x95pW%&\xd4\x94\x96@\xc822<v\x99\
+D\xd6\x0b\xb8\xe9X\x05L\xad\xe5\x08\xd8\x07\xe1/t\xc0\x9f\xd7+\xa9\xfci\x14\
+\x14\x9dmn:V!\x98\x95\x9a\x08:\xb7\x159\xbb\x8f\x83\xbf\xb8\x1b\xde\xb2\xf6\
+\x84J4\xea\x06m0v\x16C\xe3\x93\xde~\x92 5\xb0\x1d\x98\x04O\xe51\xf8\xca\xdb%\
+\xc5\xdcu.\x1b\xccG+\xa1\x1f\xa0\xff\xa95\xa44Q\x1a\x89\xe8\xfbs\x91\xb7{\
+\x1a\xbcE\x9d\xf0\x95u%\x94\\\xa8\xf1\x98`\xea)\x82\xb1\xab\x18D@\xfa\xbf\
+\x98\xcemA\xee\x9e\xa9pNh\x14l\x9c\xc3\x86r\x9b@\x1e\x1a\x8b\x81>\x1bL\xfc\
+\xa9\xe4\x8a\xb2\xf6\xe5\xdb"\x02\x9e\x01,^\xb8\x10\xc1@\x00\xef\xbe\xf7\x9e\
+\xe4\xe45\xb7\xdd\x8d\xab\x16\xff\x08g.Z\x80\x9c\x18\xb5\xc3\xe35;Q\xe2\xfe\
+\xf0\x13F8\xf5\x85\x18\xd0\x15!D$\xfe\x08^5nG\xdaf\xb3I\xb1\x82M\xade\xa0\
+\x08\x12\x9e\x8aV\xc9\xceI\x8d\xdf\x80\xbeY\x068\'Z\x102E\xa7d\x15\xf7^\x06\
+\x00X\xb4]\xa0\x19\x91\n\x80Q \xe0\x00\x00\x8a\xa0cT\x039\xb0\x12\xe3\x114\
+\xbb\x11\xb2;\x11\xb4\xb8\x102{A\x1a\xfctmr\rE\xdfwA\r4~#\xb4n3\xf4N;\xf4\
+\xbdy))?H\x80\x80\xb1\xab\x18\xc6\xae"\x84\xac\x1e\xf8s\xfb\x10\xb4:\x112\
+\xf9h\x8f\x81\x86\xce0\'H-4A\x1d\x08\x9f\x1eZ\x8f\x19:\xa7\r\xfa\xfe\xdc\x84\
+\xaf\x89\xa0\x08XZ\xaa`\xea(\x81\xbf\xd8\x81\x80\xbd\x1fA\xb3\x070\x04AQtu6\
+\x8d\xd7\x08\xfd\xa0\x1d\x06G>\xaf>:Aj\xa1\xf1\x1b\xb2\'\x1b\x9d\x0bI\xc0\
+\xd4Y\nSg\tB\x16\x0f\x02\xb9\x03C\x7f\x97\xa1{EK\x86\x13\xc7\x88\xa0\x8e\xbe\
+W\xbc&\xe8\x9cV\xe8\xfa\xed\xd0zMH\xb4\x9e\xbc\xc6gD\xce\xbe\xc9\x08\xe4\x0e\
+\xc2_\xd4\x8d\x80m\x10\xa4\x91v\x17k\xfd:\x04\xfb\xcd \xbb\xf2Au\xe7\x85\x13\
+(\xd9\xa5YS\xc6\xach\xcbo8\x1b\x96\x10\x04\x81\xf3\xcf=\x17\xb3g\xcd\xc2W\
+\xdb\xb6\xe1\xe0\xa1C\xe8\xea\xea\x82\xc7\xeb\x05I\x92\xd0\xeb\xf5\xe8\xb5\
+\xf4b\xb0`\x10=e=h\xafnGwy7^\x9c\xf5\x8a\xe81%Y\xe1\x0cI\xdc\x1f\xf57\xba\
+\x10\xcc\xd1\xc1\xff\x96\xb0\xd7d\xce\xf25\xd8\xb6N\xb8PN"\xb1\xefd\x91\xe7\
+\xbe&`>V\tCO!|E\xddt>\x88\xc9G\xf7| (\x10\xa4\x06D@\x07\xad\xd7\x0c\x9d\xd3\
+\n\xfd@.tN\x1b\x8e,;\xca;\x12#\xde\x0c\x8b\xb6/SE\\\x00bU\xcdC\xd9Q\x95CE%\
+\xcb\x89\xd7\xf1\x0cP^\xc43!\xf3<\x11\nZ\xf8\xd9\xea\xae\x13\xe3\x0f8\x19\
+\x11g\xacpj\xee|\x9c\xfdXu\xf8\xf3dE\x84\x992\xe5\x7fS \xb3}\x88m\xeb\xee\
+\xc4[\x8d\x0e<?o}x\xdd\x8f\xbf\xb8\x0e\xa7\xfd\xe8\xe9\xf0rT\xe6\xf9\x93\xb4\
+wd\xd5\xfd[\xe2\x9e_N{\xcft\xc5\x9e\x99\xdf\xc95\x17\xd4\x85\xd7q\x05\x1cP\
+\xadp!F\xd542\x15\x95\x91\x8c\x94\x8eg\x9d\x9e\x90\xa8\xb8\xcbe\xa4\x8a\xb7\
+\x120s\xc3\xd9\xe2\r\xd0\x96\xa0\x12\x18.\x12\xcf!\x99\xb3|\ro\x1d[\xbc\x13A\
+nf\xb9\x9a862P\x05\\Ee\x84!\xb5Q\x8aRB>\x9a\x90ZfU\t\x12\xedF\xf6\xf9\x0b\
+\xd7F\xaf\xb8a\x96\xa8\xf5=R\x85\xbb+\xff\xd5\xa8e\xd5\xfa\x16ft\xc4\xc0UT\
+\xd2\x04\xdbBK\xf5C\x87\x11q\x00(\x19jc\xca\xaea\xfd\xa3\xf1\x9b\x13\x8e\x8f\
+\x8ff\xeb\x9bAJ\xdf\xf0T\xf1\xc7?\xad\xc7\xb8\xa1\xf7O\x8c\x97\x9fO\x91\x89\
+\xaer\xb9t\xe5\xbf\x9a\xb1\xd7\x96)\xa8\x16\xb8\x8a\x8aBp\xdd\xabJ\xb9[c\xc1\
+\xb6\xc6\xb9\r(^h\xfaA\xf8\xbdj\x8dK\x87m\x85s\x07aJ\x0f\xca\xe4Z\xe1<\xeb\
+\x9b\xc3H\xb5\xb8U\x12C\xb5\xc0UT\xb2\x00\xba\xe0H\xec6\x90R\xadq\xd5\xfa\
+\x8e\xae\xd0\xf6\xfeM\x8dC\xbf\xdf\xf4#\xc7\xfa\x96[=-\x93`\'\xb0\xa9HG\x15p\
+\x15\x95,\xa6\xc4\xac\xe5Y\xdf\x89\xb8\xd5G\x93xs\x19?\xf3C\x1c\xd9*\xfc\xa8\
+T"d2\xfbc\xad\xa4\xde\xe0b\xd6\xf7\x93\xd4\x93\x92\xce#E\xb8\xd7\xfe\x92\x0e\
+\xc9H\xc9hO5\x998\xd0\xc84T\x01WQ\x11\xe1\xda\x17\xf9S\x91\x18\x9e\xbe\x9a/h\
+\x1f\xcc~&\xad1p\x06\xb1\xde\xcd\xb7,\x0b\x00s\xe7\x87\xe3\xe3R\x84<SJ\xa6f\
+\x02\xf1\xe6\x86\x0b\x85L\x94\xfc\x9b\xc7\xb3\xbe\x95\x14n\xa5`\xdf\x8bj\xdb\
+\xd0\xd4\xa3\n\xb8\x8a\n\x87X\xc2\xcd\xdd\x86+\xe4\xe9\xce\x96\x15\x12o\xe6\
+\xc1\xc9<\xfe\xd9\x89nB\xb1\xf0NO(\xa65>\x9a\xado\x86H]\xf4\xd4\xb0m\xdd\x9d\
+\x82\xd3\xc7\x18\xd8\xd6w\xfb\xf8Wc\x8a\xf7\xa6K7\xe1\x9c\xd7\xce\x01 _\xbc\
+\xe3Y\xdem3>G\xf9\xce\xd3\x04?\xe3\xde\x8b\x0f\xef[\x14W\xc4\x999\xe0*\x89\
+\xa1\n\xb8J\xc6\x90\x0e\xf7\xdd\xb5\r\xf3\xe3o4W`\xddV~\x07,\x80\x16r!k<\x93\
+`\x84\x87\x9a;\x1f\xc5\x10.\x04\xd3\xe9\t\xe1\x95\xb7\x85+\x80\xa9\xc4v\xa3\
+\xb3aD,\x11\xeb\x93-\xe2\x9b\xf6\xf2\xad\xef\xf6\xf1\xaf\xf2\xd6\t\x91\xca\
+\xee]b\xe2\xad2<\xa8\x02\xae\x92\xf5H\x12\xedx\xcc\x9d\x12y\xcf\x11s1k\\\x08\
+\xed\xf9M\x92N\x17\xda8^\xea\x95I\x86-\xe4bnu.#\xd1\xfaN\xb4\n\x9b\x10\xb1\
+\xdc\xe8\xdc\x90\xc9\xf9\xb6H#\x0f)\xd6\xa7TV4Q8[\xa2x\x8f\xc4\xb8\xb1\x9a\
+\xc0\x968\xaa\x80\xabd\x0cJZ\xdeb\xa2\xfd\xeb?\xb4%t\xbc\xd5\xf7\x94G\x16b\
+\x889\x17\xae`\xff\xf5\xca\x9fH:\xdf\xcdx6jYL\xd0o\xad\xfb@v\xdcQh\xfe\xb8\
+\x1a\xfbN\x0c&d"\x96\x87 \x97m\xeb\xee\x84\xe3\xd4\xbf\xc8\xdeo\xd6;t+\xd3Y\
+\x9c\xb1\xc6\x9f\xfe\xf1\x15\xee\xfe\xe9)x\xfa\x96\xd4w\xfaJ\xe4^\x14c$\x0eD\
+\x86\x03U\xc0U\xb2\n!\xe1NT\xb4\xc5\x8e!(\xe6[\xf7G\xb9\xd3\x19\xe1\x96*\xd8\
+\\\xb8\xfb1\x82.$\xe4\x89<(\xd9\xd6\xf8\xdfn\x17n\x921\x12\xad\xefT\x92\xea8\
+\xb8\x10+\x9ab\xb7\xaa`\x84[\x8c\xbb\x7fz\n\x00\xe0\xdaG"\x9e\x96T\x8a\xb9\
+\x9a\xb8\x96^\xd4f&*Y\x03W\xbc\xa5\n\xf7{e\xb4 /n\x97\'\xf4QB\x0e\x00[\xf7\
+\xe3\xd9\x17\xb6\x02H\\\xb8\xe3q\xf3\xbf\xc5\x85\x1cH,\x0b8\xdb\xe6}\xc7r\
+\xa1\xff\xf8\xd2\xab\xf0\xfck\xff\x92}Ln\x93\x13!\xa4\xfe\xee\xd9\x89[3n\x19\
+C\x1f\xbf\x81\xfe\x1bp\xado\xb6\x80\x9f},\xd2\x06\xb5\x7f\xc9?\xa4\\v\x98\
+\xb3V,\x15\\\x9f\x0e\xcb<\x16;\x1f9*\xe8BW-pi\xa8\x16\xb8JV\xc0\x16o%,n)0\
+\xe7Y}O9\x9e\xbd\xf9Y\xe0\x85\xd4\t7\x03s|!\x8b\x9c- W]u/\xfe\xb5\xef\xde\
+\xb8"\x9em\xe2\xcdeC\xb5\x03\x00\xf0^\xaf\x13\x8b\xf3m\t\x89\xb7T\x92\xb1>\
+\x9f\xa4\x9e\xc4\xa6K7\x01\xed\x91u\xaf~\x91\x03TF[\xd8\xeb\xae\xef\xc7\xe5\
+\xed\xaf\xcb>\xfeGOD\xf6a\x8b9c\x99\x0f\xb7\x90\xab$\x86*\xe0*#\x9aD\xadn6r-\
+o.\xcf\xde\xfcl\xca\x85\x9b\x0b[\xc8\x85\xac\xf1\x7f\xfd\xeb\xde\xb4^O&\xc2\
+\x887\x03#\xe2\x99\x04\xbbz\xda\xba\xf6Scn\xbb\xeezZ\xcc_)[\x9a\x90\x8830b\
+\xce\x15\xf2\xe1\x10q5\x81-9\xd4Z\xe8*#\x16\xae\xd5\x9d.\xcb\x9baJ\xf7{\x98\
+\xd2\xfd^\xda\xc5\x9b\xcd_\xaf\xfc\t\xb4\xe77I\xceng\x93\xad\xd6\xf7\x86j\
+\x07O\xbc\x93\x85\xa9\x8f\xaeT\x83\x93k.\xa8\x8b\x12\xafe\x81\x93\xa3>\xb7}\
+\xb2X\x91\xf3\xc4\xe2\xa3\'^\x8f\xb2\xcc\xd9q\xf2\xe1Du\x9fKG\x15p\x95\x11\
+\xc9p\xb8\xcc\xd90\xc2=\x9c\xe2\xcd\xc0\\\xc7\x1dw\xac\x8bZ\x9f\x88Kw\xa4\
+\x8b\xf7\x16\xbd~\xb8/!&3\xeam\x82V\xa7\xf3\xcc\xf7x\xebb\xc5\xb9_)\x13\x8ei\
+\'\x02W\xc43E\xc8U\xe2\xa3\xba\xd0UF\x1c\x99"\xde\xa2\xec\x19\xfay\\\x12\'I\
+\xe0\x18\x7f\xbd\xf2\'\xc0\x1d\xeb$\xcd!\x1f\x8d\xd3\xc6\x86\xd3}.\xa7\xbdg:\
+\xaco.\\\xb7\xfap\xb9\xd4U\xe4\xa1Z\xe0*#\x96\x8c\x14\xefa\x86q\xa9\'\xc2H\
+\xb7\xbe\xc5\xb8\xa4\xb1@\x11\xf1N\xc4\x8d.\xa5\xbd\xe7e\xf3\x06x\xeb\x1e]\
+\xba"\xee\xb1\x95\xb4\xc2\x192\xd1\xa5\xae"\x8ej\x81\xabd\x169F\xa0:O\xf8\
+\xb3\x9d\x1da\xeb;\x15\xe2m6\x1b\xa0\xd7E[\x1dN\xa7\x17$EO\xe5\x91,\xde\xc9X\
+\xde\n\x1c\xe3\xafW\xfeD4\xb9\r\xc8n\xeb{~ \x10\xe5F\xbf\xa4\xb1@p;\xebS\xbb\
+\x01\x00\xae\xeb\xa7%t\x9eX5\xc1\x01y\x167\x9b\xf5\x05\xaf\x01K_\x93\xbc=\
+\x93\xd0V\xfb\xdc\xc6\xf0\xba\xfak\xceO\xe8\xdc\x0c\x1f=\xf1:\xceZ\xb1\x14\
+\xcd\xf3\xae\xc3\xa2\xed\xf4\xbaT\xd4\xf8O\xf4w\xa4\x12A\xb5\xc0U2\x8br\x1b\
+\x88\xcb\xa6\x08\xbe\x14)\x89\x1a\x83\x82<+\xcaJ\xf3\xa2^\xda!A\xcft\xcb\x9b\
+\x8b\\K<\x95\xd6\xf7\xf2\x95+Svl!\xd8\xa2\xadt2\x1b\x83\x12\xe2\xfd\xdc;\xfb\
+\x04\xado\xb9\xb0\xc5[h9\x11\x9a\xe7]\x17\xb5\xcc\xed\xbc\x96*\xd4\x046y\xa8\
+\x16\xf8h\xa6\xdc\x06b\xde\x18\xa0:\x17\xb0\x19\x01P\xc0\x80\x1fh\x1d\x04u\
+\xc0\x01|\xd7\x0e\x90i\xae\xf3s\xa0\x07\xd4oY\xd5\xaer\x8c \xee\x8c\xce\xd0M\
+\x95\xeb\xfcX[o\xf8\xfd\xa4\xda\xf2\x18[\x8e\\\x86\xc3\xfa^\xf7\xf8\xe3i=\
+\x1fW\xb4\x85D<Q\xcb\x9b\xa9\x8d>nE\x90W\xd4E\x8ep\x0b\xb1\xbe@\xba\xe5\xad\
+\xa2\x02\xa8\x02>z\x19\x97\x0b\xe2\xa7\xd3\x01\x82\x00\xf5\xdf6\x10\xad\x83\
+\x80A\x0bL\xc8\x03\xea\nAL-\x02\xb5\xbf\x1bp\x07\x86\xfbJ\xa3\x18\xc9q\xef\
+\xd9C59v\xda\x01\x7f\x1a|_\\W:[\xbc\xd9\xa26?\x10\xc0\x96\xa6A\x00\xc0\xc9UV\
+\x18u\xaacN\x0eR\x85\x9b){\xfa\xdc\xd0\xf2[\xab+StE*\xa3\x05\xf5?u\x94B,\x9e\
+\x00h5\xa0\xde>\x04\xbc}\x08\xd4\x8evP_\x1d\x03\xf5\xc2\x1eP\x1f7\x0f\xf7\
+\xe5e%s\xfb\xe8\x97\x81T\xf6\xb8\xfe\xd9\xfa\xf0K\n\\\x8bt\x8b^\x8f\x0f\x1b\
+\xfa\xf1aC?|\xc1\xec\xac\xac\xac\x0f\xec\x0f\xbf\x94BJ\x82\x1aC\xbc\x9a\xe5R\
+\xaco\xb1\xe2-\xab\xefZ\x1f\xb5\x9cl\x0c\x1c\x00.y\xb5\x11\x97\xbc\xda\x18^\
+\x1e\xfb\xc5\xfa\xb4\'\xb5\xad\xfd\xe5\xfcp\x8ba\x15aT\x01\x1f\xadT\xd2\x0f\
+\x1e\xe2@\x0f\xef#\xa2\xd7\x9b\xee\xab\x91\xc4pX\xdf\x13\x1c\x9fet\xec\x9b+\
+\xda\xdce&\x16\x9eM\x89k\x05o\xb6\xa0\xe0\xcd\x16\xd1\xcf\xb9\x89k\xec6\x9f\
+\x1b\x9dUx\xaf\xd7\x89\xf7z\x13\x8f\xb52\xd9\xe8}k\xfa\xe2n\xbb\xb3\xd6\x19\
+\x15\xd7e\xb2\xbc\x95\xb6\xbeW\xdf\xb5\x1e\xf5\xd7\x9c\xaf\x88x\xb3\x91r\xcc\
+\xb6\x19\x9f\xcb>\xae\x9a\xc0\xa6\x0c\xaa\x0b}\xb42dhQ\x06\xfe\\O\xaa\xb9\
+\x1f\xc4\x87M@P`\xc4M\x00\x98Z\x0c\x9cT\x0e\xa2\xc2\x0e\x98u\xf4v=^P\x8d}\
+\xc0{\x87\x81 \xcb\xc4\xd4i\x80\xc9\x85 &\x17\x02U6 \xcf\x04\xe8\xb5\x80/\
+\x04\xea\xe8\x00\xf0n\x03\xd0\xe9R\xe4+i4\x1a\xe4\xe5Z`\xb7\x99`0\xd0B\x16\
+\x08\x04\xd1?\xe0A_\x9f\x13B\xb6\xa5\xd1\xa8GA\xbe\x15\x16\xb3\x11Z\xad\x06$\
+I!\x10P\xa6\xda\x16@\xbb\xcd\t\xce\x89g\x0eD\xbb\xd0{\xf5\xc0!+\x7f_=\x05L\
+\x1f\x04&\xf6\x00\xf9\x1a@C\x92\xe85j\xb0\xdf\n|\x97\x03\x90\x04\xbd\xdd\x8e\
+f\x12/l\x8b\xfc\xadn\x02\xb0\xb9\x88uL\x83\x157\x1d\xd8\x11\xfe\xfc\xbf\xed\
+\xad8\xe9\x94\n4\xd6\xf7\x82\x02\x11u\xce/\x9a\x07ab\xb9\xd0\x8b\xaczL+5\'\
+\xf2\xd5c\xb2|\xe5\xca\x94\xc6\xc6\xd9"\xee\x9f\xb6\x0b\x00-\xdelRYZ\x95-\
+\xda\xf1,W9\xb1\xef\xcb\xdb_\x17\x9d>\x96l\x89U6k\xde\xbaIp\xbd\xd0\xfc\xf0X\
+\t}r\xe0&\xb0)\xd9^8[Q-\xf0\xd1J#m=\x10\x97L\xa6\xa7n\xb1qx@}r\x04\xf0s|\xbd\
+\x1a\x00\x97\xd5\x81\xb8j*\x88J;\xb0\xfd\x18\xf0\xe6\x01\xe0\xebV\xc0f\x00qJ\
+%-\xd8lN,\x03q\xd5T`\\\x0eP\xdf\x07\xbc{\x18\xd4\xbb\x87\x81\x01/\x88\xda|\
+\x10W\xc5\xae\x85|\xe5\x91\x93c~\xce\xa0\xd3i1\xb6\xaa\x10E\x85v\x04\x83!tv\
+\x0f\xa0\xab{\x00$E\xa1\xb8\xc8\x8e\xf2\xf2|\xde>v\x9b\x19c\xc7\x14\xc1n3#\
+\x10\x0ca`\xd0\x03\xb7\xdb\x07\xb6\xd2?w~rsm\xe7\xf4\x01s\xfa\xe9\x17\xc3\
+\xcc\xc1\xc8\xba9\xfd\xc0$7\x7f?[\x08\xb8\xb2\x158\xa5\x17\x18\xa4\x80\xcf|\
+\xc0gE\x1a\x044\xc0\xa9}\xc09\xdd\x91m\xc7\x17\x12\xb8\xea$-\xf2\xcc\xb4\x18\
+w\x18\x80\x0e\xd6\x9f\xf4\xf1+\x1f\xc1\x7f\x0bi7\xeb\xce\xfc\x17\xf1\x82\xfd\
+gx~\xf9r46\xf4\xa3\xb1\xbe\x17\x8d\xf5\x91\xe4\xbd\xaf\x8e:\xf1q\xe3@\xf8\
+\xf5}\x872\x83+.\xc9\x88\xb7\xe3\xa2*8.\xa2\xc58\xdd\x19\xee\xf1\xe0Z\xdcl\
+\x12\xb1\xbe\xe7\x9c\x18\x11\xe4m\xdf\xd0\xf7\xa2R"-\x07\xf6\xfc\xf0T\xa3\
+\xba\xce\xa5\xa3Z\xe0\xa3\x95\xb7\x0f\x01?\x9dA\'\xb3\xfdb\x0e\xa8\xaf\x8f\
+\x01_\x1c\x8d\x99\xb4F\x9c:\x06\x98^\x02\xb8\x02\xa0\xfe\xfe\r\xd0\x17q\xb5\
+\x13\x14\x05\x9c1Vt_\xea\x89o\x00w\xc4\xb2\xa5\xf6v\x81\xb8}.Pl\x05,\xba\xa8\
+\xcf\xe4C\xa0\xa2,\x1f\x06\x83\x0e=\x8eA\xf48"\x0f\xd0\xfe\x017\xc6\x8d)\x82\
+\xcdj\x82\xd5b\x84\xcb\xed\x03@\x0b~YI.\x08\x00\xad\xed\xbdp:\xa3\xc3\x06Je\
+\xa1\xaf\x1d\x17y\x7f\xd3\x11\xfa\xe73\x95\x803\xc6\x7f\x1eA\x01\xe7v\x02yA`\
+[\x1e\xb0-\xd2E\x12{\xec\xc0U\xad\xc0\x0470\xce\x03\x18\xb6\x07\xe0\x9f\xadG\
+\xa1\x95@Y\x0e\x81\x87>\x0e\xa2\xd4\x0f\xe4\x05\x80\x81\xa1sP\x04\x89j\xe7\
+\x19\xa8\xb7\x7f\x80\xcfJ\x1e\x02@\xe1\x9b\xc7\xa3\xa7\x8d\xdd\xf3!\xedf\xbe\
+c^9rL#\xa7\x02\x97\x94\x81\x80a\xf7\xf4\xb0\x15\xae\x14L6z\xdf\x9a>\xe4\xdd\
+\x99\x97\xf0\xf4\'\xa53\xcf\x95\xb4\xc2U2\x1f\xd5\x02\x1f\xa5P\xbd^P\x7f\xdb\
+\x01|\xd9\x02h\x01\xe2\x8c1 \xee\x98\x0bbq5-\xa8\\4\x00\xe6\xd1\xbd\x8b\xa9O\
+\x9b\xa3\xc4\x1b\x00\xa8\x1e\x91\xb8\xf9A\x07\xa8\xe7v\xf3\x05\xba\x9f\xb5\
+\xbd.9\xc1\xb0X\x0c0\x99\xf4\x08\x91$\x1c\xbd\xd1\x16#EQ\x18\x1c\x12g\x9b\
+\xcd\x04\x8a\x0c\x81"C\xc8\xcb5\x83\xd0\x10p\xb9\xbc<\xf1\x1en\xc6x\x81R?\
+\xe0\xd5\x02;r\xa3?\x0b\x018d\xa1\xdf\xd7\x0eY\xee\x86\xed\x01\x18\xb6\x07P\
+\xdb\x10\xc4gC\x8e\x86\xc5\xdd\x80=\x04\xc04\x0bgt\xfc\x12\x1a\xca\x80\x8f\
+\xca~\x0f\x08\x06\x12\xb2\x9f\x80~\n\xcf]\xae\x94\xfb<\x96x3\xees\xc6\x82\
+\xbd\xceq\xa9"\xe7\x8c%\xd2\xa9\xa8\xd0\x06D\xbe\x83R\xc9l7<5\x0b7<5\x8b\xb7\
+~\xd5\xfd[T\xf7\xb9DT\x0b|4\xe3\r\x82z\xb7\x01\xf8\xa2\x05\xc4\xbc*\xe0\xa4\
+\n\xe0\xf4\xb1 fW\x80\xda\xd4\x00|\xd3\x1ey\xde\x17Z\x01\xdbP\x82\x94@\xe2\
+\x1b\xf6w\x83z\xda\r\xf89\xff\xdc}\xde\x88\xd8\x13\x00,zz\xba\x9a\x84\xa9J\
+\xd76\xcc\x87K\xb8\x90V\x146\x0b\xed/\xf6z\xfc\xa0(\xbe@\x05\x87b\xf9\xbe\
+\xaeF\xbc\x7f\xef5\x00\x80\xabV\xbf\x08\xe4O\x86\xd3\xed\x8f\x7f\x82d\x08\
+\xb1\x7f\x1f\xd2\x06*\xe3\x86~]mFZ\xb0\xb9\xb8\x86\x0eS(p\xe9\xbb\xed@\xb9\
+\x0f\x98\xe4\x02\xce\xe9\x02\xf6\x05.\xc5\xa4\x81\x1f\xe0\xe5q\xd7\xc0\xaf\
+\xa1\x15?[K\xa6J!\x93\xda\x89^\xf8\xebc\xb8\xe8\x89\xe1\xbe\x8a\xf4\xa3&\xb0\
+)\x87*\xe0*\xc0\x80\x8f\x16\xf2O\x8f\xd2\x16\xf8\x89e .\x9e\x0c\x98t\xa0\xbe\
+\x18\xca\xe0\xcd5D\xb6\xef\xf3\xf1\x8f\xe1\x0e\x80j\xec\xc5\x9e\xfe\xaf\xb0w\
+p+\x1c\xfevP\xa0`\xd7\x17`\xe6i\x97a\xea\x82K\xa0\x1d\x9b\x0f\xe8\x95w\xfa\
+\xe8\x86,x\xab\xd5\x14\xd3\xf5\x9d7v2\x16\xff\xe1\x1d|r\xff\x8f\x90[F\xbb\
+\xfb\x83A\xe5\x12\xd6\x04\xb9\xe9z`\xd7N\xfa\xfd\x8b;bo;\x84m\xe8\x92\xaa\
+\xdd\x11\xb7\xbb\x10\x06\x11c\xfa\xe3B\xa0\xc8\x0f\x94\xfa\x80\xd2\x8e\xff\
+\xc5\xfb\xe5\xbf\x81\xc3\xd8 \xe3\xa2U\xa4\x10\xab\xa8\x8b\x10B\xd6\xf7\x9b+\
+N\xc6EO|-\xf9\x9c$k\x80\x9a\xae\x84\xb6T\xf1\xe4\xf5\x91\xff\x07\xb5\x02[b\
+\xa8\x02\xae\x12\xc1\xe5\x07\xb5\xe1\x00\xe0\x0b\xd1\ti\xf3\xc6\x00C\x02N\
+\x84XjA\x08\xedL\xe1\x83\x8e\x97p\xd0\xb9\x03s\x0b\xce\xc1\x05\xe5\xcb\xa1#\
+\x0c\xf0..A\xee\xfc\x13@y\xfc\xc0\xa7G\x80#\x03\xa0\x9c~ @\x81\xb8}\x8e"\x97\
+\xcdX\xdd\x9dM\x07\xb0k\xf3K\x00\x05\xe8-vX\xf2\xcbQ>\xe3L\xe8\x8c\xb4\xcf\
+\x99dU\x95\xd3\x1b\xcdC\xfb*r\t\xe2<\xfet\xe4}\x0c1f\xc3\xa4\x0e\xb6\x19\x81\
+\xef\xed\xe2\xdb\x05\x04\xff\x0e|(V\x1a\xfch\xb6\xbeS\x89\x90\x88s\xdd\xe7l.\
+\xfc\xf5\xb1\x84\xce\xf3\xcb\x8d\x11\xb1_s\xc1)\t\x1d#\x19\x98:\xe9j\xb7\xb2\
+\xcc@\x8d\x81\x8fR\x88kg\x8a\xff\xf5\xb7\xb7\xd2?m\xac9\xc5\xec\x98w\x89\x85\
+\xb7\xcba\xd7\xf78\xe8\xdc\x81\x13\xf2\x16\xe0\xa4\xfc\xc5\xb0hs`\xc8\xb1#\
+\xf7\x8c\x13\x00\x00\x83\xcf~\x06\xea\x93fz\xaaY\x97\x1b\xe8\xf3(\xf3E(\n-\
+\xbb\xe9y\xa8Fk\x1eJ\xe7\\\x8e\x8a\xd3\x7f\x0cm\xfe\x04l}\xe9At\xb64c`\xd0\
+\x83\x81A\x0f\x9c.\xfa;\x94L=\x15~/\xedN\xd6h\xf8*8\xa5G~\x1fmY\xc4\x11\xde\
+\xc5\x15t {\xb2\xc9\x88\x03V\x88\xbe\x0e\xf3\xff\x0c\x00\x803{\x00\x0b\xd9\
+\x8f/\x8b\x1f\x05\x00,h\xff\r\xf2\xfd\xd5\x92.\x8d\x928(P\xe1\x13\xabK\x99R\
+\xb1\xef5\x17\x9c\x82\x93\xc7\x95\x86\x97\xd3\x19\x0b\x7f\xe4\xb3]\xf8\xbe\
+\x9d.\x02\xb4\xfao\xafc\xabc\x93b\xc7\xfe~\xe0K\xc5\x8e5\x9aP\x05|\xb4\x12\
+\xae\x7f.\x80i\xc8\x92`%\x9aQ}^Zx\x01`\x16\xdfM\xbdop\x1b\x00\x023\xf3"\xd3?\
+\x88\x02KX\xac\xccCc\x82g\x8e\xfc\x1ek\x1bn\xc3\xdf\x9b\x7f%zi\xee\xd0 \xd66\
+\xdc\x86Y\x98\x85\xf3p^x\xfdW\x8f\xff\x02\xef\xdf{!\xbe\\{\x13\x9c\x9dt\xb5\
+\xb8\xce\xfd_c\xe7\xdb\xff\x00\x00\xe4\x16\x97b\xcf\xbf\xef\xc3\x965\xd7\xa0\
+\xf1\xd3\x7fC\xa33\x08\x1e\x1f\x00z\x9a\x0f\xd1_\xd5\xc8\xaf^F\x8d\x99)\xba\
+\x9f\x12\xe8bTb\xdbPW\x8d\xe2\xa1\x01\xd2@\xbf\x0f\xcfW\xc9+\xf8q\xbc\x13\
+\x98\xec\xa2\xf0^\xf9\xdd\xf8\xa6\xe09\xec\xce{\x05z\xd2\x8cs[\xefGGy{\xdc\
+\xfd\x83\xa1\xd1\x99\xe4\x96(LQ\x17\x06)\xadFGb\xcd\xf3~\xaf\x1f\x9dN\x0f&\
+\x15\xe7\x81\xa2(|\xbam/\xc6[\xa7Fm\xa3N\xffJ?\xaa\x80\x8ff\xaas\xf9\xd6\xa0\
+\x86\x00\xe6\x0f\xcd}\xda\xd9\x19YO\x01\xd4\x16Z4\x89\xd9\x15\xc0\x9c\x8a\
+\xa8};\xbd\xcd\x183f:,\xb6H\xd6\x19\xc5\x9a\x92\xa6\x1fW\x04\x00\xf8\xf1\xd8\
+\xbb\xf1\xb3i\x8f\xe0g\xbf\xfb\x8f\xe8e\xe9\t#\xce(Z\x8a\xbbpW\xd4\xfa\xc2\
+\x9a\x99\xa89\xf3j\xb8{Z\xe1\xe9\xa5\xc5\xe8\xd8\x8e\xf7\xd0}\xe4\x00\x0e}\
+\xfd>\x00`\xe9\x1f\xfe\x89\xf9\xbfX\x0b\xb7\xa3\x1d\xb5\x0b\x7f\x0cK>=\xd8\
+\xf8\xe6\x1f\xbf\xc2\xee\x17~\x83\xf7\xee\xb9\x00-\xdb\xdfE\xc3\xb6\x0f\x01\
+\x00y\xb9\x16\x18\xf4\xb4+\xd0\xef\xeeG\xff\xee\x8dp\x80\xe5\xb7n<\x0c\xfc\
+\xf4j\xe0\xf4\xd9\xc05W\x02\x8d\xacX\xb2s\x10\xf8\xeb\x83\xc0\xd2\xf3\xe9\
+\xcf\x17\x9e\x06,\xbf\x06\xd8\xb7G\xf0{\xf9\x02C\x1e\x00V\xf2\x99\x06@\x19\
+\x93R\xd0E\xff\xbe\xed9\x06\x94\x96\xd3UXv}\xdb\x89B\x81\x99}9A:Y\x8dM\x89\
+\x1f8\xdd\x01l+z\x12\xcd\xd6\xaf\x00\x00\x9f\x97<\x84N\xd3\x1e\x14\xf8j\xf0\
+\xf6\xfe^\xd1\x1ct\xd3PnB\xeb`\xe4d$E\xa1\xa5?\xc5I~\t\x10\xaf\x12\xdbp\xc3\
+\x15q\xa5\xaco1\xe4X\xe1\xbfx\xfd\x89\xf0K\x0e\xfb:{Q[\x94\x0b\x83V\x83\x03\
+\x87[\x11\x0c\x86Pb\x1c#\xfbZ\x85\x12\xd8\xc4\x9a\xbb\xa8\xc4G\x8d\x81\x8fV(\
+\x80\xb8\xac\x0e8m,\xa8\xfd\xdd \x1c^PV\x1d\x88\xe9\xa5@\xb9\rh\x1e\xa0\xa7\
+\x8b\xb1\xd9\xd5\x01\x94\xd9\x80\xd3\xaa@,\x99\x08\xcc\xab\x02\x8e\xd1M0.\
+\xca[\x8f\xc215\xa0\xd6\xee\x00<C\t)=n\xa0\xb1\x9f\x1e(\xfcx\x1aP\xef\x80\
+\x8e \x80\x9a<\xa0\xcb\r*D\x82\xd0j\x80\xf3j\x80}\xdd\xf4\x80!\xc7\x08}u)\
+\xa6a\x0cN\xea\x9c\x82\x1a[\xe4\x1aN\xba\xf4F\x00\x80\xd5\xa2CIe\x15(\x00\
+\xbdGh\xb1l=\xd6\x81\n\xb7\x0fV\x8b\x11SO\x98\x89\x92\xdf=\x85\x10a\x80%\xbf\
+\x14F\x83\x16\x93\xfe\xf4,\x1c\x8e\x01tv\xf6\xe2\xab\xc7o\xc6\xf7\x1f\xbe\
+\x869W\xdc\x0c\x83A\x87qcK\xe0\xf7\x07\xa1\xd3\x97"XS\x89#\xef\xacE\xfe\x95\
+\xb4\x87\xe0\xfc^-v\\\xbc\x0c\x07\x1c\xcd\xc0s\xeb\x81\xd6V\xa0\xba\x06\xf0\
+\xf9\x80U7\x00\xedm\xc0o\x7f\x0f\x9c4\x07h9\n\xfc|\x05p\xac\x05\xa8\xe37\xf4\
+>\xda\xde\x88\xda1u8\xd3A\xcf\xe3\xd6\x02(\xf7\x02N-\xf0/c\x0fp\xc32`?\xfd0\
+\xab;\xbe\x18\xc1\x00\x89\x9en\x0f~\xe8\x06\xda\x8d@\xbf\x8e\xde\xa7\xc0\x0f\
+\x14\x04\x80os\xe889#\xe6\'\xf7\x01~\xad\x03\xad\xe6\xef\xc2\xe7$\x11\xc4a\
+\xdb\x16\x94x\x8f\xc3w\xedn\xe4\x98t\x18\x97g\xc0\xc4BS\xd4\xb5M\xc87bo\xa7\
+\x07o\xee\xef\xc5\xbe.\x0fB$\x89\xe6>?\xecF-n\x9c[\n\x15\xe9\x0c\x0e\x0ebm\
+\xc3}X\xbb\x84^v\x9c\xfa\x97\xf0gE_\xdd\x89R\x9b\x195+"\x05\x8a<\x81 \xde?\
+\xd8\x82\xdd\xed\x0e\xf4{}\xd0k4(\xb5[p\xc9\xf1\xd5\x18\x93\'-c;VB\xdb\x03\
+\x1f\x7f\x8b\x05\xb5\x95\xf8\xe7\xf6\rQ\xeb\x7f\xf1\xfa\x13xt\xe9\n\xd1c\x06\
+I\x12\xf7l\xde\x8e%\x17]\x8c\xd7w\xd1\x03\xc2;\xdf\xf9\nx\x87~\xff\xb7\xfe\
+\xdbqB\xde\x02\x9cZH\x7fQu\xeaW\xfaQ\x05|\xb4\xf2\xf0VP\xd3J@\xd4\x16\x80\
+\x98[\t\x98t \x82$\xd0\xe9\xa23\xd2\xb7\xb6\x02!\x8e\xaf\x97\x02\xa8\xcd\r \
+\x1a\x1c\xc0\xc9\x95\xc0\xd8\\`Z\t\xe0\'A\xb5\xf5b\xff\xc6\r\x98\xdc[\x1c\
+\xbd\xfd\xbf\xbe\x07\x16\xd7\x80\x98Z\x04\xa2\xae\x10T\x8f\x17\xc4\xc7G@}u\
+\x0c\x9e\x1b\'\xc3RR\x02\xe2\xb8b`\xc0\x0fjgg\xb8\x07\xf1S\xc5\x00\x00 \x00I\
+DAT\x1f8\x00|\n\xe0t\xdc\x19>\\Yi\x1e\xfd\xf3\xea\x9f\x03\x14p\xb0\xa1\rA\
+\x1f\xed\xd6/\xac\x99\x85c\xad\xbd\xc8\xb1\x9b\x90c\xb7 \xbf\xb2\x1aZ\xad\
+\x0e$E\xc1\xef\x0f\xa2\xc7\xe1D\xff\x80w\xc8\xadN \xe8\xf3\xe2hk\x0fJ\x8ar`\
+\xb5\x9a`\xd0k\xe1\xf2\xf8\xf0\xce\xff\xad\xc2\xd5K\x16\x86\x13\xc9\n\xca\
+\xc6\xc1R7\x0e\xc8\x01\xf0\xe9G\x91\xef\xf6\xee\xdb@\xfdA\xe0\x97\xbf\x01N\
+\x1br\x1b\xd6N\x02\xc6\x89\xc7\x9a?\xfd\xf6=h;;1~\xe6\xa9\xa8%\xf5pj\x81F\
+\x0b=\xf5\x0b\x7f}\x12\xe8\xee\xc2%[\xbe\xc6\x86\xf9\'C\xab%0sV\x19~\xf9\xe3\
+\x9bPw\xfa\xf9(\xa9\x9e\x822\x1f\x9d\xb8\xd6\xab\xa7\x8b\xbb\xec\x19r\x14\
+\x94\xfb\x80\xb3\xc3\x95\xd9\n0\xd3\xf1#\xb4X\xb6\x01\x00\x08\x82\xc0\xc9\
+\xdd7F\xae\xa1i\x00U9|\x01\xbf`r\x1eH\x92BC\xaf\x0f{:\xdc\xc81j1\xa9\xd8\x8c\
+9\x95\x025^\x87\x19\xa6\n[\xa6b4\x1aq\xf1\xc5\x17cR)\xf0\xab\xdd\xd1eF\xcf\
+\x9eT\x85\x0f\x0f\x1dC\rk\xdd\xdf\xbf\xda\x8b^\x8f\x0fW\xce\xac\xc5\xc4\xa2\
+\\t\xbb<x\xe2\xab\xbd\xe8q{%\x0bx,\xaa\x7fx\x1f^^w\'\xfe)s?\xadF\x83?\x9e3\
+\x07\x94\xaf\x15\x9b\rz\\?\xb7\x0e\xe59\x16\xbc\xdd\xd9\x8f\xd3O\xaaC\xdf\
+\xe6SA\x10j\xd2\xc4p\xa2\n\xf8(\x85\xea\xf5\x02\x9f6\xf3\xadl)\xfb\xd6\xf7\
+\x02\xac\xf2\x9b\x00\xf0\xce%\\eT\x9bM\x13\rP\xa0\xb8\x06-P\xdc\xbd\xb8\x15w\
+ww)\xeeV\xdc\xdd]\x0b\x14\x8aS<@p/\x10\\\x8a\x04i\xb1\xe2\xee\xf0\xc1\xfb\
+\xe5\xd7\x9e\xf3\x9c}\xf6\xce\xec\xce\xcc\xbd\xd9I\x92E>\xcb\xef\xb1\xf9\x1c\
+\xbeH9\x1d\xa2\xc3:}\x00\\\r\x05\x8f<\x8b\x8b\xb4B/\x10\x0f\to\x91\xablIc\
+\xec\'\xff!\x068\xf4\xfb\x8d\xf71iL\x08\xe3\xabgVcw\x11\x84\x00\xe8\x90}cI\
+\x00@%\x9dT1:\x99\xe2\x1a\xa1vrI\xafY#\x00\xca\xd9\xd2|c\x90\x1b+ \xe0\xe2a$\
+\xb2\xbb\x13\x83\x8e\x88\xe8\xdb\xe1\x92\xd2\x8b`<\xce\xc5\xc3\x9a\x7f\x90"\
+\xaf\xc7\xea\x91\x87\xe9\x9f\xd0V\x18\xe3\xf7\n\xb4\x0f\xf6(lExtL}\xd4\xeb\
+\x8b\xd2\x0b^\x0b\x7f6\xfe\xa5\xf7t\x90\xc5\x06`\xd0T\xa0\xd1\x04\xa8\xa2b\
+\x93?\x9a\x9a\xfa\xf56\x126\x81|\xa5TW\x8ffd)\xaefP\xf4n\xa1\xb0\x8b\xd1\x15\
+hpl\xb3\xa3\x04\xa8\x08pJBW\x1aL\xd5\x94Ak\xc9G\x0b\xf8\xe0\x08Ix\xcdM\t\xb6\
+\x88\x05\x18|\x96\\a\x98\xe1\xf4\x99\xd1X \x9fV\xda\xd2\xc0\xc1\xa4\xf6x\x0e\
+\xe2\x87\xcd\x8e\ts\xddM\xb7\x8c\xba\xe4\x8bt\xc0\x14\x16G\xc8\xc7\xa9\xeds\
+\n\x89\x14\xba\xc9\xfa @\xb0\xe1C\xe2\x06\xbe\x88\x10Y!\xf8\x87\xc2\xbb\xeb\
+\x0bj\x0c\xf3\x803\xcb\x98\x0fvME\xc8\xa0\x18\x8a\xb4\xdcJ\x97\x91;\xe6\xbc^\
+\xe1%w\x9f/\x02uZ\xd6\x9f\xe96B[\xbb\x89w\x1e\xff\x1av\xfar\x8em\xb1\xbb\xa6\
+<\xd2\xfc<,\x13\xe5w\x0f2P\xaah:\x7f\xd7\xa1p\xe5\x0e\xb7f\xd8C\x08\xab~\xf0\
+)Z\x84N\xfa\xbc\xa9^\x83[@\x16q\xbe*\xbcf\xb6\xcaj\xc1\x8c\xd1zmnf/FRD\xd0\
+\x94b\xdcw\xf3\x8b^\x8d@\x97\xcc\x9e\xefy5m\xf1\xe4\x95\xa27_\xc6C\x9eb\xaa9\
+\xe0\x0f\xca\xe1\x14\xe6;\xfe\x08\x84\xe1?Ur\x00@U\xb7a\x82q\xe1O\xa5\x19\
+\x17\xf0w\xe2 \xbd\x01I\xd9\xb7/z\xc3*\xf8h\xff$]\xe8\xdb\xbb\xd9\x0f\xe9Rk\
+\xbb\n\x97~V\xa3\xfa\x14v~!ud9\xbf\'\xd0N\x16_\xd8\x19S\x81\x1f\xa3\xb3\xcfA\
+W \xa8\xbd\x1c\x01\x1f~9\t\xb9\x1e\x90\xccUTBWQC\x10\xbc03{@\xd1Yg\xc8\x86\
+\x13\xb8\x00\x8fC\n_\xac\xb9$DbP\x98(8%\xb6~\xfa\xaf\xe5g1\x9b9\x90\xbd\xa4\
+\xce\xa7H\x12\x03\xa0\xbf\xbf\xbe\xd3Go\x8d\xc8\xd4\x06\x83\x08\x01\xce\x93S\
+\xe7\xff\x9c\xb6\rWV\xfb\xa9\xc1\x1e\n\xb0+\x19\xb5\xda\xf5\xa5\x07\x9a\x06Z\
+w(i9Cg-\xeaXR\x13b\xaf\x10\x19.$\x14&\x85H\x1e\x10Z\xb7\xfa!\x99S\x9bvR\xc6\
+\xdfP\xd0j\ru\x9a\x9e~\xe8<\xae\x1f\xfc\xb4y\xe0H\xc2%\x0cP\x15\x87\xb8_\xf3\
+\x13\xe9\x9d\x8a+\x90\xab\xa6\xa0.\xb2\xfd\x18\xd9\x03\xf9M\xe8\xbe\xc0\x01l\
+\xeeN:\x96\x1e\xae\xf5.\xe7\x02Q\xa4\xff\xb0|\n\xb8f\xe0\xbf\xf6Cg\x90\xb0~\
+\'}\x9d\x88K\x1b\xaf\xc7\xa31m\xb9Ul\xf7\xdd\x7fS}gZ\xc48\x90:x=\x03p\x01\
+\xf9f\xfe\x0f\x11c`]\x8b"\xdb\xd6\xdfi\xfa\xa0\xbf\xce>X \xdf\xfe\x8e\xf8\
+\x9c\xb4\xc6\x9f\xd4\x85\xa7[E\x9a\x83\xa5y\xd2A\xe2\xc8\x8d\xf8\xac\xbd\x9f\
+\xfc\xb6\xed\x83\xd6\xabm\x8cF\xabq\xad\xdd+\x89\xc1\xc1\xc1\xa7\x8c\xe9\xe3\
+\xe3\x028\xf2\x8c\x81\t~\xa19l\xf4\x88\xf3\xb0\xda\xaaq\xb3\xb1,R\xc9\xf5\
+\xd8\x1d\x0f"\xc3\x11\xe6/\x18\x80S[e\xed9\xee\xd8\x97\xaf\xcc,\xf4t\x80\x82\
+U\x18\x13\x18\xe7~&\xc1\x80[t@\x90af\xa2\xdd\xd0\x13\xdeq\x12\xce\x8b\xcd=\t\
+\x01\xa2\xedX\xc2\x84\xcdo\xd1\xc4gFe\x83\xb8?,]|~\xe0W^B\xc0\xf9 \xf8a\xed\
+\x99\xac\xe9\xe8\xf1\xdd\xf0s\x07\x12Q\ri\x19\x18\xdb\xc6\x1dA\'v\xb8G\x8b\
+\x03}\xa5\xf0\x19\xc8\x7f\xf0\xa2xr\xd9Ml\xca\xa60\xfcpc\x84+\x0c\xf9}\xd3\
+\x85\x04KDP\xdd\xf6QH<\xf4]J\xdc\x1c\x07m\x94\x8d\xf6u\xdf`\x8f>q\x10~!\xe2\
+\xaa\xa3\xc9\xb3n\x90\x12\xe2\xe1\x13iy9,DO\xc2i\xb86\x1c\x82*\xbct\xf0\x89\
+\xe8~\x89Qk\xda\xe5J_\x0bv\xd1\x00E![\xce\xc980\xca\xb3f\x9d\xe0\x0e"(\x95t5\
+\x01<b\xf6\x15\xdaA\x1c\x10\xd8\xb0\x84\xdb%\xd1\x0f\xad\xcb\x9c\x9e\xa5\x19\
+\xbc\xb7\x0f\xf4\xf9N\x82?Gm\xe5\xb3 \xdc\xcan{\xb7\x88a\x109\xefU\x83\xbf\
+\x9a\xa1o\x96^_\x89#Zy`\x80\xdcv\xff\x1a:\xdf\x81\xc4j\xd1\xdf^\xc3(\x04\xb3\
+\xbcqR4_\xc83zN\x93\x0b\xc3\x94\xf9@\x08?v!\xe1u\xb8\xb9\x8c\xc0/z\xb8\x18h\
+\x13\xeb\x03nG\xd1\xa2\xf8a\x8b\x9d\xe0\xe8\x8f\x08I\xa0Q\xc1E\xca\x9f\x8e\
+\x8b\xc1\xc1\xebU\x93\xe9h\xed\xdf\x12\n[\xefFA\xe8w\x07\x04\xf1\xd5\xbd\x0b\
+\x93B)l\xc4\xd7\'\xbde\x87Zs\xfb\xda\xc1=\xc1\x06\xa1\xb0 \x04<\xad\x8c\xc0|\
+"2\x99(\xe9qS\x86;q(n\xe5$\x08\x8aN\rN\x17I\xb4\x7f3\xba\'\xc1-\xb0\x1dm\xca\
+v\xff/\xe8j\x12\xeeE\x07\x11\xfc\x88=\xf5[tx\x83V\x11\x81\xa5\x83a\xe7\x06\
+\x9fB\xbd\xe6d\x1a\xb0x_\x9b\xc5\xc5\xfaX\xf0\x9d\xce\x867{\x85+\xbcmif\n\
+\xd9\x98-\xec\x8b%\xfc\x94\xed\xfbO7|\xaa6\xec\xa6\xbe>\xe4\'\xb7\nw\xc6jV$\
+\x1b\x18\xa4f\xab\xbbgk{\xd7\x88\xca\xa8\xddd\xe0\xa7\xdc\xf2\xc9kp7\x1eB(\
+\xbaZ\xeeET\xfd\xfe\x8cb\x8f\xf2\xbe(\n\xd7\xdf\xe0\x92@\x1e[\xab\x0e\x8d\
+\xa8W\xd3+J35\xd4\x86\x8a\x8f\xc6\xbc\x0f\x84\xb3\x9e\x14V\x1d\xb2\x1d\xbe\
+\xc7x\x0bB\xef\x80\xdd\xdaw\xf0\x81x\x93=\x853O\xa4\xcf\xbe\xdb\xca)\xfc\xd6\
+z\x98\xf5]\x9c\x9a=\xe1\xab;rz\x1b\x15\x10\xb1Va\xc9\x1f\xe9\x1d\xb5\x854\
+\xb7w\xcb\\\x89\x12H\xb7\xe7\r\xacg\xf7\x07X\xb1^\x90%l\x03\xe1N\x04\xa7\x86\
+\x9d\xe0\xc2\x9bV\xd63S\x7f\x94.\xa1\x85\xf8\xd7\xe2\xc2\x1f\x8f\x90\xce\xa7\
+\x95\xa7\xcd\x837\x0f\xcf\x07(6\xdc\xadk\x92*\xd3\x82\xedA\x80i\xbd\x13\xcb\
+\xff\xb4\x12\xc7<g\x00\xea\xf3\xff\x93Mk:\xb6\xa9\x05>{<\x01|\xf6dv\xaf\xa7`\
+)d\xf5\xe1\x05\x83]\xfb\x8c\xbf\x91\xcf\x8d\xd4jh\xa0\x18P\x97\xfa\xb1=\x10\
+\x8a\x9a\xee\xf4\x01\xef%W2\xa3\x1d\x89c\xd3y\xf2\x89\x02^n\xcdu\x8d\x8c\xf9\
+\xfa\x07W2\xc8\xda\xd0\xadY\x99\xab/\xe0\x82\xe9\xb0&\xb9o\xf8\x16\xef\xbb\
+\x1e~\xfc\xd8\xc0\xed\xbe\xdd\xb8\xb8hy\xe9\xdd\xcd|\xc4X\x00{\xe0@\xb2\xc7\
+\xc9,\x90{\x1d\xcd\xfa@="\x16\x1e\xf388\':f\x13\xe1\x8cPe\x83\'\xb8\xf1r\xba\
+\x818\xe4.\xe9\xcf\xc8\xf5\x0c?\x91|65\xbe\xbf\xdd\x1a\xfd\x92\x95\x88\xc2\t\
+f\x86\x8esPn\xe1?\xb6\xf1\xfdBN\xb4\xf4\xaf\xa2\xc2\xd0\x07g[\xb6D%j\x0c09\
+\x91/\x18*\x98\x91\xbf\xcfk6\xab0\x91\xe6\xe0\xab^\x9f\xf4\xfcza\xb8a?\x9dA9\
+g\x10\x16\x96;\xa1\xcbh\xa3\x1c\xb4\x1c\xcd\xc4\xa9\x02o@]\xe2\xd3n\x85R\xeb\
+\x90\x958\x7f\x93\x16\xdb>\xbd\xceXr\x90_\x17\xe7\xc6\xc4W\xdc\xd9m\xc3\xee\
+\xf8|\xd3\x98} \xa5\xbdt\xcf\xb2\x01j!\xa1\xd4\xb1\x08\x9fB\xbc\x8e\\G\xbcTW\
+sE_\x07w\xff\x82\xee6\x9d\x07\x9e\xdf\x07\x8f\xc92\xc9KU\xff\x1e\xc0qL\x1f\
+\x97\x00:\xa77\xf5\xba3`Wf3\xcd\xcf\xd7\x16\xa3\x9a\x85L\x18\x16\xa2\xfd\x1c\
+\xcc\xd5UJ\x8f\xe2\xac\xee\xe0\x95\x1ak#\x7f\xe6\x0c,\xffU\x18\x86`$\x87\xc4\
+\x85_\xeb\x9c\xab\xa0\x08\xd8Z\x94\xd5\x1eE}M\xed\xa3\x04[\xd1-I@\x88\xcez\
+\xec\xca\xca\xe9\xad\xb9C\xccP\x0f\xe7\x02\xb2v\xcf\xfd\x8e\xde\x92\xfd\xa6V\
+\xdf\xbd\xe7u\x06\xf2POdh<D\x86\xfe\xf7\x85\xc3#\x8b\xd5\x19\xf6\xec\xf7\x8f\
+V\xfe\x81\xa0\xc4\xbe>\xfe\x10k\xcd\xe1\x94!\x8dh.|\xf63\xab\x8d\x98[]\xc6\
+\x0c3\xad\x15]@\x90\xa6J\xad\xcb\xe8r\xc4\x8a\xc5I\xc9\xd0\xc4\x97\xd7\xa5d\
+\x89\xa3=\x19\xcdV\xf7\xd4F\xee\x07\xb8\xb0\xb0=\xf2Y\x8d\xdb\xb0\xeb\xea\
+\xf43\xb1Q\xf2\x18\x97\xa3\xe7\xb8\x953\xd0\xe6\xa7\t\x97\x89\xf35C(j\xa9\
+\xda\x15y6\xac\xb1[\xe43U\xdc\xb0\xdc2\xc7\x1c\xd8\x19\x80\xba\xcc\x12\x85\
+\x1f\xfe\xe18\x8b\x1f.#\xd8O\x93M\x98\xd5\xben\x94\x9eM\xee\x19\xdf/\xaf\x02\
+\xbc\xc0~^\xe7\x9a\xd3\xc1\xa3QE\xd6X\xe9!\xddMd|\x87\xcd\x18/\x06\xf3\xf5\n\
+\xbc\x13f_\x7f\x9d\x9f\xac_\x980\xd7\x12\x0e\x84\x95\xe7\xce\xd1\xd1f\x9e\
+\xd6Bw\x05\t\xbdV6\xb1\xed\xb8\r6\x8d\xdcW\x92L\xdcb:\xde\xf7R\xd5\x1d\xd1\
+\xbd\xc8\xa8\xc1\x12\xeb\x9b\x14J<\xae+s\xc4Y\xb1k\xbf\xee\x1f3\x15#\xd4\x9e\
+QPK\x8c\x18\xbf%VH_v\xe0\xde\x8a\xe9\xc8^V\xeb\x0f\x84u]\xe5\x08\x13\xe8\xd2\
+\xc6\xe2&U^\xfam\xc5]\\*\x8a\x8bXus\xe7to\x06\xa8\xaa\x05RA\x15,\xf0\x1e\xf3\
+\x88l\xdc\r\x82\x8b\xb2\xf3\x19\x0e\xe5{\xb1\xc1r\xd5\xec\xd1\x94Bu5\xd8\x97\
+Ka\xd7\x02\x89-\xb4&\x95\xe6\xdb\x1e|\x05\x81\xbe\xd7\x7f\xfc\x15\xdf\xc5+\
+\xe2\xc9\xc3\xc4g\xe6\x10x*q\xd9\xf5\xc2\tmW\x08f\\\r\x02ysRk\x85K\xe4\xd6w\
+\x99\'\xcb| \x06|\x80\xbf\x19{U\x0cgc\xa0\x958<\xf2W\x90\x96\x12\xe4\x96z\
+\x84\xb9\xf6-`\x98\xbb\x05/\x1a\x14\x8f\xca\x14(\xa8xB\x07\xea:\xc8Ozg\xfdb\
+\x08\r/\xc5\xac\xe7\xbd\xd9\x0e\xb2\x99tv\xccw\xff\xa8\x07\x1e\xac>\x91\x18\
+\x14P]*&S\x1e_\xe4^\xcd\x98\xa7xu\xea\xaf(I\x99\x01\x87u!\xb4\xddq;\xa0\x08\
+\xbey8+\xe8\x06z\xda.\x7f\xcd\xc5\x10@\xaa\x9a\xd2\xd4\xf5\xa7m<R\x7f\xce\
+\x1c\x18\x90\x0c\xdb\xdaG\xbc\xe2_\xdb\xa4\xc2\xe9\\s\xa2\xf0Q\xf3\xa2\r\x07\
+\xcbI\xba\xf7\xc9\xbb\x99\xb6\xb0\xd5\xe8S03\xcc\xf7(\x1f\xeeX\x90\x1e\x8a\
+\xa1\xa5D\x9fg)\xad:m~t\xf2C\xe6\xfe\x1f<\xdfM-_\xb8\x19\xaa-Y%b\xf5_\xff\
+\x94\xb6\x9b\xd8j\x83h}\xd1\x8b\xf4\xf6\xe0p\xc2\xf5Mi\x0e\x8e\xadPn\x9d\xf5\
+\xd7]\xc3\xf5\xc7\x91\x111[\xfa\xcc5\rciWQ\xcf\xde=\xd6\x14\xa6\r\x82!\x12Q\
+\x96\xe9\xd6\xb9IUx\xaf\x80\xa9\xa6\xbfss\x9f<\xda2\xa1N\xbe+\xceh\xac\x19\
+\xb0e\x18\xc8\xd5%\x85\xb4\xad\xb9\xcaH\x1a\xf0\xabW\x9fh\xe8\xae\xd6oA\xd5\
+\x06\xbf\x82\x9cqWEl\xab]\x9a\x8fb\x7fEm\xef\xe7\x8c\x80\xcf_c\xd2\xfcJh\xbb\
+!q\xd3\xb8,2P\x17A\x9bL~\xea\x9ee\xea\x80\x93\x1f:\x11.@@@\x1f\ngr[}b1 \xb0\
+\xd0\xc4\xde\xe2\x01i\xee\x1a\x1cXQu\x0e\x94\x8a\xe2\x11\xaf>\x90\xf5\x1a\
+\x17N/\x87\xad\xe50\xe3{\xf8\xa3\xef\xd2t\'\xf1\xc1!AG\':\x8a\x97x\xc5K96`\
+\x88\x19\xfb\xe2\xac\xf3fk\'P$w\xee\x0e[4\xc6[\x006\x18\x8b\x12\x8a\n\x81\
+\xce\x9c\xcaK\xe6\xf5\xaetGc\x9f\xd0\xd6>\x8b\xca\xd9f\xca;\xe8\xa4\xc8\xf6M\
+P\xa7\xd6)"\xcd\x11\xbcZ\xb6}\x98\xe8\x14\xafG\xca\xc9\xbdL\x91\xbc\xa5\xa5\
+\\&N\xc8\xa9\xe3}\xbd\x83\xab\xc8.\xdfs\xaf\x14>?\xa1\xa12\x966S^\x8f\x19\
+\x13\xac\xee4\x8f\xde\x9fN\xa7\xcc\xb0\xba]o\xb6\xd9(\x92\xe0\xe4?\x8c-St{c\
+\x19\xde\t:\xfd}}\xea\xca`\xb6!\xf6\xbem\xae\xb17\xfd-v~\xa9V"\x13\xe3\xd7\
+\x06\xc1\xf9a!\xa6\xc8\xbb\xe2\x88\x8d\xfc\n\xbc\xb6Z\xc6\xd6\xd6\x18\x81\
+\x7fg\xa0\x00\xde\xc6\xb3\xa2\xf7Ne\xa1\xfd\x07*g\x80d\xf4\x8b\x17\x87\x86\
+\xdb\xe3:\xd7:\x1b\xf3l#\x8d\xf3\xb1\xb7]\x7f\xb7\x1f\x90\xc8c\xdep\x1d$\x1e\
+a\x82AlP\x1f\x98\xa7\xe2NOKE>\xc3\x0bu\xf9\xd1\x18\x9e\xc7\x0c\x8a\x8ei\xcb\
+\xb2+\xe0[\xd7%p\xfd\xf3\xb2\x8d\x0f\xc0\xc5t%\x9c\x1d\x92R\xab\xd6G\xd6\xbf\
+\xf45)\x87\x19\xbdk\xc9\xc0Je\xf3\xda?\xde\xf7vXf\x91L\xa4\xa7\x82\xca\xf5RU\
+v\x9e[Y\xac\xd5\x91\x81X\x1e\x03\xae\x0c\x0f|\xb4x\xfbe\xdc\x15\x87\xe5\x1c\
+\x89+\xde\xee\xe0\xd3\x7f\xfe\xd923\xab\x1d\xa8o\xcb\xf3\x18.\xb9$.\r\xcb\
+\x0bO\xba\xca/\xf7\xb6\xae\xdc\x9e`\x8e\xceI\xd8\xa1\x94+\xfa\xee\x8d\xd26\
+\xd6\xea\x8f\xd3M\x91\x83\x0b"\xdcI4~W\xed\xc7\xa9\x07\x86\xf1\xf5y}c\xbd\
+\xc3Z~L\x1e\x0f\x0e\xe1\xbe\xee\xfe\xdbE\xbc\x90\x99Y\xc1\x1e\xfb\xf7\x1e\
+\xa0+\x82l\x08K\xef=\xa4Eo\xa7_r\xe38\x8aQ\xef\x85\xd6\xf2\x1d\x07\xe1k\xdd\
+\xb2Aqp)l6\xa3o\xa9\x01\x18\xb5e:\xee\xf2\xed2\xfb\xb0\xb8\xd7\x7f1\xdd\x94h\
+\x86\'\x1f\x1dN1\xf3Gi\x9b\xe4\x0c\xb6o\xec\xd3\x84\xd1&\xd4\x1c\x01nY \xa1\
+\xf0\xc1IO\x85\xdfV\x05\r5\xd6\x9c\xd8\xbbe\xbf\x06\x8aS\x84F\xdb\xe4\xef\
+\xad\t&\x8c\xcc(\xb7\xf0\x87\x04q\xbe\xcb\\d\x13\xc9\x03"\xe8\xb5\xda\xbf\
+\xd4X\xf24C\x96\x1d\x06\xc4 \xbe\xb1E:\xb3pc\xad\xa5\xdcKv\xb5^\x99\x96\xb7\
+\x97\xaa\xcaR\x1a\x88\x06\x06\x8a\xba\xf3\x945\xb3\x0e\x17\x94\xf0/\x0f|\xed\
+\xea\xf1\x02\xcai\xe0P\xce\xe2,\x85\x11%\x84\r~\x8d\xa2e 83\x08\x1d;y\xb2\
+\xb1)\x05_\xc8dc\xb7\xdc\xd7^\x81\tx3%\xcc\xd7sY\xd6\xc2\xc6\xd8x\x8a\xfc\
+\xd3ir\xab\x9d\xdf:\x032by\xa61\x86y \xa3y\xe8\xaaA\xb7\x1e\xd1\xd1\xad%\x95\
+\x94\x8c\x86;\xf6\xe4V^\xa8\xe6Q\xf3\xb3\x02\xc4\x98\xcd\xed\xd4\x98X\x1e\
+\xecF\xe8\xdd\xb3\xc6\xe4\xcc\x91&\xd7\xc3z\xa2\xd3\x08)\xad}\x93>G\x1fL\x08\
+8\xa7\x1a\x81o)\x8d\xe9\x84\xd5[\xc7\x99A\xb7\x81\x8e\xfc1\x8dy\x8b\x85*\xaf\
+\xef\xecs\xed\x15\xb3T\x99\xfe\x9a+\xd3\x96;\xa6\x10A\x16e{\xfe\xb3\xb2|$5\
+\x02\x04x|\xd1\xf2\x88\x0e`k\xa6h\xfbS0v\x0f=\xe1\xc6\x0b\xc2:\xeb\x19\xd3L\
+\x91\x14\x9c\xf7\x83^\x8b\x00\x82\xd025\xcd\xe5\x85\xd8\xba\xaf+L\xbb\x8a\
+\x93\xe3\x196\x18tc5`2(Z\\M\xc8\x12u\xad\xc82\xdbjoN\x12\xd3B\x80\x1e\xf9\
+\xda\x02)xN-_\xf5F\xa8\'\xd8\xf2\xc4\xc6\x8fV\xf2\x93\xae:\xcd\x11\x9f\x1a\
+\xf9\x1b\xfe\xc5\x1b\xdb\xf7\x0f&\x0e\xe1\x9d\xb9\x93[\xb8\x9c8\xa4\x0b\x03&\
+\x02\x1f\x94.Y\x8a\xfelv\xca/||9\x8a\x92\xf4c\x19\x0euql\xa6\x94\x1b(\xe5x0g\
+n\x89\xa5j\x9a\xd0\xedB\xf0\xce\x8f\xfb\x8a\xca\x87d\xaf\xff\xafn7\xfa\xf6\
+\x9c\xb3\xd5l\x8d6{\xd3q\xd2\xfd\xb5\xa4\x11\xce\xbf\x8fv\x90\x02\xadF\x92\
+\x8eDGy1-^\xe2u\n\x9b\x1b\xcef\xfb\x1a\x8e\xf6\x01\x8f\xbb_\x9eN\xca\x8d\xbd\
+\xb5s \x01\xf0A\x99\x96\xba\x9bf\x14\xcf\x07\x88\xb5\xfd\x19\x88{7\xae\xcc\
+\xd64\xc1\x0e\xfd\x96\xf3.-a\x0c\xd0\xff\xf7\x15em\xea\xae\xcf\xa3\x9b\xc8\
+\x8c7\xa8\xcf\xa4\x05\x0b\xb0v\x01JC\xea/7\xc3\x18\xa1z\x1dH\x00\x95\x87M8\
+\xd9\xe8\xdb\xf9uc\xc4 %\xde\xaf\xda[=\xb4\x84\xda\xfc^\t\xa0\xa4\xed\xea\
+\x94\x8070\xd3\xdf\x19\xd0!IQ_\xf3\x9dw\xa4\x8fhmu\x91}xt\xb7j>e\x82\xf9\xe7\
+:\x0c|\x93ytou\xc3\x15P;~\xd0\xfa}\xa8\xf0\x87\x84o\xb4o\x99\xb7M\xaaGg93\
+\xc20C\xb1\x08\xbc\xf8D\x10 \x9f\xf57]\xa3\xb6\xe52\xe5\\N,\xab\xa9\xf5\x0e\
+\xc9\x1e\xb7\x84W\x85OZ7\x9b\xff}\xfc\xc8\xf7\x9f\xc9\xce\x83\x19\xcc3b\xc7\
+\x1e\xa3\x8eP\x96l\xfc>A? \xae\x93\x9e\x8a\xfe\xcf\xe9\xec\xfbJ\xbb\x00% \
+\xc7K\x93\xa1 \x96\xb2T\xd6v\xcf3\xb1\xaa\xcc\xc9\xa7\x06\rd/A3\xfd\xads\xc3\
+\xfdQLf\xe84\xdeC\xa8\xf1*\xe2\xe7W\xd5\x06\xfbvd\x04G\xf56\xe3l\x8cW%%j\xd6\
+M\xe4S\x05\xb8\xe1\xb5x\xf4U\xfaKe\xac\xa9\x1d}c\xa9\xb3$%\xb2Y!\xfb\xd8\x87\
+\n\x1f\xb16k\x9fNa\x0ekb\xe7vh#Q\x8d\xe2\x9bX\n\xe8#\x1d\xc2Q&\xb0\nY\x7f*\
+\x97i\x99\x8ci\xbdQ\x9a\xf7j\xf3\xf5\n\x0c\x06gJ\xc4\xf4\xee\xd9\xb4p\xfa~m\
+\x92Z\xdc\x1a\x02fV\x8d\x89\xdc\x7fcn*\x05\x9cz_\t\xed\xe9B\x1d\xf1\xf9\xf5\
+\xfaO\xca\xeb;#\xc1\x00\xff4bC[TA\xdd\x81\x9d\xa8*T\xb2\x9c\xcd.\x00\x10\xf8\
+\xf1.\xc1RmWc,\xf8\x80E\xfb\x93|\xfb2\x966\x98GC\xa0\x8f\x95\xdaY\xc3C&`4\\\
+\xff\xd8\x9d\xca\x1dC>\xe3\xbf\xf4\xedT\xb3\x96\x966\x06>V\xdb_\xe9\xf2~\xf4\
+\x05\xaf\xe8|T\x07\xd7\x01>\xd36\xd6\xfb\xb4m\x8b~\xf0<B\x00\xd8\xef\xfb\x02\
+\xf5Ir\xfb\n\x07\x19\xa0\xae\x90\x19\x9b\xbb\xf7\x14\x1c\x83\xd5o\xedb\x93\
+\x1c\xf4\x0b\xf9\xcc\x9aK\x80W\xdd7J\xa1\x96<\x95\x91R\xa1\x88]\xedXk\xe3T\
+\xee\x19e\x14\x9b\xb4\xc1\xff\x15\xe7\xa4"\x9f\xaeD\xb4\t\xc6\xf2\xcf*\xfe1\
+\xe3\xb0\xbe\xc7\xaf\xeb\xaa\xccP\xc6\xa5D\xa3@\xda\xa1,Z\xb8oS{\xd0P\xb7\
+\xb1\x00\xa2g?\xcd\t\xf1\xa5\x84\xa5Q{R\x86\xa0\xc2\x0e\xa3^\xe9\xe0Po@\xb2Z\
+o\\\x94\xb5-\x9a{D\xb2\x1e"\xc9\x1b%\x85\xd3i\xf2\xd7\xbd}Bl,$\xcc\xb0\xf3.\
+\xc9\x92K$\x16B\xcal3\x18\xd3\xa1\x17\xcd\'{/\xc3\x82\x90\xca\x0c>\x8bu\xd8\
+\xbcQ\xa0\xe9H\xe9c\xde\x91R\xe6Q<\xee,\xe7P\x0e32\xff\x9cY\x07O\x05\x14\x8b\
+vQ\x98\xe3^YX\x93\xc5w\xc1\xda\xc8+%\xb2\xf7F\xe3]d\x03\xde\xe8B\x86\xf1\xf7\
+A{T#4\x07\xc4\xafkYf\x99\xc6\xf24\xe6\xc5E\xd1\x9a\x87w\xab*\x84\xaf3\xb2\
+\xec\x88\xe3q]\xed}\xc0\xc4Gv\xc2\x06zi]\x1f\xcar\x12I\xe4\xbeQ\xees1\xc3\
+\xcb\x12\x8e\xfc\xdf\xdb\xa8\xb5\x90\xbd\xed@Vx+\x168\x9a\xd8Ue\xb3\xb0G\x18\
+A\xff\xdb\xcc\xf7j\xc9\xdd\xfb\xcb\x112\xcc!\xdd\\\xab\to7,s}\xd4\x00\x1b\
+\x14\x8f\xa3\xf6\x15\t\xc9U\x85=\x97\n\xd3\x9d(\x05\x13\xe2\xd1\x05\x9eWi(\
+\x97\xd1\xa3\x14\xa2\xde\x97^[\x9e\xd5X\xedH\xbf\x85\x16\xa7T\xe5E\x95\x84\
+\xbc\x99\xb1%\xe5u\x03pb\x82\x83\x98[\x96+wa.\x9d\x7f\xed\xc9\x82\x8b\x13Q\
+\xbf\xbfk\xf2%\xa9\xad3B\x0b\xea\xe3\x94\x0eH\xa4\xde\xe6\xf96\xa5\x12\xfc\
+\xd2$\x12\x7f\xb6P\x91e+B\xf8\x8e\xfc\xa9@\xc4\xba\x02!7B\xae\xba\xe1G\xa2\
+\xc7vw\x8e\xea\xf1\x85}c\x17\x0cW\xb4"\xb5\xfc\x06M/}\xf6\xdc\xb5\x14;\xf0*E\
+\xf1C\xe6k\x05\xf4\x0b\xf8\x88\x19P\x81\xca:JS\x8eT\xff\x0f\xa2O\xe5\xf40\
+\x91\x1a\x94\xab\xaeo\xb2\xa3\x0c\xf8J\xfdsw\x9dCY\x01s\n\x93\x08\xf5\x1d\
+\xc9{UQ\\B\xc6\xcf\x98\xef\xf8\xc1\x8a\xe5l\xf3\x9f\xc5m>\x7f\xd4\xeb\xd1\
+\x9e\x17\xc4\xe5)\x8a\x17\xb8\xc9\xed`\x92\xea-\xc4/\xda\x98\x8c\xb5\x08@\
+\xf2y\x1f}#\xd3\xda\x05\xf3\x1aI\x11\x84\xb5\x1d\x06\xa3\x04\xde\x0c\x1c\xb3\
+0T\xb4;\xb0\xb8MiV\x06\xd2u\xd3\xbf6\x8e\xd6OW\xb7c/\x1c\xfa\xdd\xb9\xb0rZ\
+\x00\xf0y9\x9f:\xf1kE\x95\xa8\xa7:E\xea\xcd[|0JV5\xd0`\x89.\xef\xbf\xbc\xf8u\
+\x15I\xb8?X\xc0;\x81\xf4\xa2\xad\xaa\xbc\xe1*Q\x0c\xa9\xe1d,\xb7\x88(\xb7*\
+\x18Z\x7fE\x81\xb0\xd9\xdd^\xf5O\x19\x05]6\x80G\x94y\xad\xd8\x7f\xb3\xcb\xf5\
+\x91rh\xf7\xd8q\x196\x10\xdek\xeb<F\x86\xe9~\x89;(\xe9K\x84\xff\xd3\xe9\xc5\
+\xd2\xfc\xa9\xa7w6\xf1\xcb\x026\xbf\x81\xf1S\xe0\x14\xb6\x9fOT\xfaT\x06]\x82\
+\xb1\xff\xb7\xbd\xb3%\x8b\x92\x95\xbc\xb7\xa4^\x12\xa2\xb1\xa8\xa0MT+Y\x8b\
+\xec\xfb\x8f\x00r\xfeC\xadqZ\x91/\xa8\x19\x15t)\xf9\xcdK\xd6\xc2\x1f\\\xccj@\
+\x9a\xcb\r\xef}\xaf\xdc3\x1b(\x96|\xa5\xc0D\xd7\x85\xbd]f\xeb\xb7tG\x81\x8c\
+\x96\x9e\x95-\xbd\xa8\x8d\x83\xed\xf4\xd9O\xef\xf7\xf9\x0f\xd7\xe9pm\x1f\xf6\
+\xd3M\x8a\x0cg\xeb\xd8+\xb47n\x16#\xd3\xcc\x05\tgn\x8f\x06\x8d\x94\xe4\x86\
+\x96/\xb4\xcd\xa0\xfepFQ\x05\x1djmpm\xfe\x9c\\\xe2\x0c\n=\x01\xac!\x06I0\xd6\
+\x08\x0fUh\xaf\x1f\xdd\xbf\x13)<gi\nC?\x82Rfe|m/wn\x8c\x9e\xdf\x0bc^n<?\x80Q\
+4\r\xd1\xce\xe5-\x91\x04\xbf9\xbe!\xae\xb9\xfb;s\x94\xe6M\xac\xf2\x80\x9a\
+\xda\xc8\xba\xf1)[7\t\x1d\xa2~\x00\xe2\xe3\xdde\xbf\xbamf\xad\xce\x84\xa8\
+\xc6\x81 \x1f\x87"\xa8-\x89\xc9a\xce\x06\x80\xd9\x93\xa7\xf9\xf9\xc0sC\x841\
+\x98zadw\xbd\xfb\x1d\xa8=\xa8\x8d\x87\xd6\x93\x85\xa4(\x92s\tQ\xdb&\x88\xe7E\
+\x00O\xad==\x9c\x8e\xc3 \x9f\x99$<F:\xd5\x99\xf3\x8d\xfa\xb8\x92B\xf1G\xd9:\
+\x9bY<\xceX\xda\x9cSW\xcd\x90\xee},;\xfaOJ\xfd\x10\xa54~\xcfO\x05Ea\x8a\xf8l\
+\xa5\xaa\x1e8\xdd\xeeD\x80\x86q\xc5\xe3\xf3\xe5)\xd5\xc3s]J\x8cAu\x1f\n)\xd5\
+pH\x00\x19N%\xb9\xb9:1\xc1\xf2\x05\x88]\xba\x88\x1b\x8d#\xbb\xafR3\xa1\x83\
+\xa1\xed\xa2\xd5\'W\xc5\xbe<\xcd\xc2\x7f\xccT\xe9\xc5\xb8\xefdw\x9f&\xa8G2\
+\x86\x94,\t\xef\x0fD\xeb\x0c\xe1M\xc8\xb1\xdb\x9fYe\xa4c\xba\xd4\x8b\x8a2\
+\x8d\t\x90\x9a\xe9\x1eT\xdc\xa3\xdbk\x19b\xf9\x8c\x0c4\xee\x99\x93[\xfc\'\
+\xed\x0eH\x03\x057\xcd\xad\xe0\xb2\x19\xa0\x06f\x83M\x13\xf0=\xe0\x8e \xa3\
+\x8c \xe3\xdb\xa6K\xf3\xf5\xa6\xaf"$pd!m\x91\xb4\xcbVf\xc5\x0ee\xab\xf2\xe9\
+\xf3\x9c\x8f\xb1\x1b\xa6t\xf3\x952Jfz\xdc\xb1o\xa1\xfb\xeb=\x15IH\xe5;x\xe6R\
+\xd3E>\xe2\x96\xab\xce\xc6\x85\xd1\x07\xbfy \xc6\xa6\x96\x1f\xe6\x95Pi;4\xbc\
+\x16\xc6\x0b\xae\xae\x15,\xccPs\xb1\x89}|\xe3K\x19\xb8\xa8\x90\x151\xe4<{\
+\xfc\x14s\x03g\xfc\xacQ{\xe8\xaf\x96ORp\xd47\xf1\r\x02\xa7=*C\nm\xa5{\xfcE\
+\xc5\xcd_\xf5sZ\x17\xc8\x02\xc3h\xc1\xdc\x18\x9e\xc2\x08\x1e?\x87\xe8\xfd\
+\xf8\xe6\xdd\xd8\xd6|\x1czj\xf7\xba\x86\xa4\xee~t\xcf8\x0fY\xfc\x05D]5J\x12\
+\xb5\xc5\x1b\x85\x19\xa5\x17\xd7\xa3\xe2\xe948\xcd@\xbd2\xeb\xa9\xdeYn\xad\
+\xfd\xe0\x01X\xe8H\x13\xae\xc9\x85\x11O\xf4\xea\x1f\x14\x03\xea\xc1U\xbd\x9b\
+\xe0C\x02\xef2\xdd\xa5q\xaf\xa5\xbd8\xc7~\x90\xcd\x03G\xb5\x03\xae\xa7W#|\n\
+\xf3VU\xad\xf7{\x01\xac\x97`\x16\x04\xed\x81t\xd7V\x8cV\x0f\xa3S\x1a\x07 ?Ke\
+Lc\xa9 \xc7\xbcfA\x00\xca\x93%@e\xf5>a\xb82\'\xb2\xefb\\\xc48%\xa7O\xaeD\xf6\
+g\xdb\x7f\' \ro]\x02\x01^./u\xc5[\x92eTo\xea,\xa1\xedz{\xa5x9\xe9\xd7\x97\
+\xf0\x1c\xfa\xec\xa3\x12r#V\x8b\xa2\x1fZ\x03\xc6J\x9b\xf5\xe6\x8d\xfe\xa2\
+\xef\xabz\xda\xa5\x89\xb1\xc9\x9c\x1b\x08\'\x8a\'\xa4\xde\xda\x06ei\x86\xc0\
+\x84a\xab\xb3\xcf_:\x82\xfc/\x1f4\x0c;\xf2H\xb7\xcedZ=H[\xc0\xacDw[\x9d\xbc\
+\xeb\x19I\xe1\x13\x16%\x8b\x01\xb7\x80\x7f\xf8\xd0\xd2[\x8f\xd2\x95{<1\xa0\
+\x91\xa5\xaa\xf9\x06\x03!\xa2\xf6\x06\x87du\x1b\xb5q\xf8\x80\xaa\xcc!\xc8\
+\xad}\x96p\x91\x8c\xb9\xde\xad\xe8\xc05\x7f\x8f,\x82\xb1H7\xcf\t\xa5;"s\xae\
+\x1db=7\xfc\x12\xa0\xc69\xaf\xf9\xb7D\xefu\xa6lY\x14w&\x1d\x16\xfe\xa9\x82Ue\
+\x8f\xa5\xdd\xa1\x1fUJy8K\xe1\xa6K~]GW\xa0\x0eD\x80H\x95\xd9\x19\x98\x8eZ\
+\xe60\xb4\x9b\xd2\x9a>\xfb;\xbe~\\:\xd4\xa3 :JwO\xada\xfab=\xa1\xe9\xea\xd0\
+\x90"c\x9f\x04\xebD\xc19\x7f\xb8\xb1\x0f\xdf\xc1\x18/\xa0BF\xfa\xad\xfb\x19\
+\xfbs\x02|\xae\xc2\x0cI\xeb\xa4\x8f \xf6\xfea\x86\xed\x81`*\xce,\x87G\x97\
+\xa7\xab\xc4\xc0CW\xcd\xfa&\x06\x1d\xd1\x90]\xf4O\x7fQ\x19\xe7eB\xed\xa6\xd7\
+\xc9\x193\xe8\xe1\xbf\xc3^\xd3\x10\x03}\x18\xd6\xb0\x02\x1a\xd2\xfb"oM\x10*3\
+U\xea\xb3\xfd\xa9\x06\xce\x11G\xb7\xd3\x81W\xbf;\t\xc3\xbe\x18\xd0\x19\x08\
+\x04\xaa\xce-\xf9\xdc\xcb2\x11\x0b-\xffSB4C\xb2\xaf\x97\xab\x8e\xd1\xddd\x88\
+.\x1az\x05`A\xa19\xa0\xc6~\xf2\x15D([\xefF\xef\xdf\xd2\x18z\x19\xdbJpV\x89\
+\x82LN\xeb%NM\xf4Z\xe2\t]\x9a&n\r<\xedu$}\xa4B^\x91MPn\x0e\xb0\xb1\xec\x8f!(\
+#\xd4+\x9cS\xaa\xca\xf73\xaf\x1a\xfc\xd5\xdb\xac\xb4\xa1\xfd\xaf\x055\xc1=\
+\xc6\xabx\xd4\xfa\xb7\x8d\xff0e:\xc9|Jp\xfd@\x9bX-\xc6\xe1\xf0\x9dx\x0e\xc9\
+\x94\xf2\xe61w\xb5\xc4\xea\x9eb\xb91\xaf\xf0NK6\r\x94a_\xfc\r\'\x16v\xcd(\
+\x8b&x\xf1\xd9U\xb8\xd3\x1f\x9bY\x853]\xe1\'$QPT\x04:T\xf3~f\xb1\xa7a\xe8*\
+\xf8Iu\xe5\x1f\xdc\x03\xa7\xd2\x00a\xd8\xbb{\x9a\xbf\xf2\xcb7\x18\x18\xe8\
+\xc6\x08\xed\xd8\xf5\xa7\xf6\xcfd\xaa\xb0\\\x08\xb5\xc5\x14\xa1\x16a6\x9f8\
+\xf3\xea\xdd\xa4F\x82\xa7q\xf1\x95\x99\xc5\x90\xec\xc5\xce\x9c\xb8L\x99\x9b\
+\xffkQ\x0f\x19\xc1*\x9f\xb6\xd5\xa4\xfb\x92O\x16\xd8\x87\x04\x08B\xd6\xf8vu\
+\xa45}\x94 X\x14\xdb0\xe0\xd4\xb6\x9d\x176\x99\xcdB\xc0\xe3\xfb|^\xd5w\xe0\
+\xbb\xf8dGP\'\xa3\xfb]g\xb3\xe4*P\x82\xa1\x12\xbe6\xc5\x93\xa3y\x91\'S\xa1f\
+\xb4\xc0\x81\xca6_\x9b\xa9"\xa9\xf9)\x99\xd6\xdd\xd4\xee1Y\x9a[\xd2?\xa3\xe2\
+\xd8\xed\xf8s(\xf3\xce\x19\x81\xd2\r_\xae\x0eE\xcd\x82\xac2\xfa\xab\'e\x19\
+\xb3\x17\x0e\x04H\x0f\xedb\xad\xe9\x13\x86\x06\xb8J\x93m\xf3\xc7\x80N\xdcq\\\
+\x90(\x90NF{\x8c\\\xd9\xdb\x99c` DY\xe4\xaf\xd3Q\xeb\xc59Yh\xd57o\x9f\x0c\
+\x1f\xb9\x06y\x97\xe9\xac\xa3V\x02\x0b\x88\xdex\xad\xaaE\xe5\x83as\xd7\x97\
+\xbf\x9f\x8c\x93c\x93\xe6\x99\xb5A\xbf\x9d%\x05q\xc2\xf3\\\x8e\x8c=\xe6;\x01\
+\xdf\x07{\xd4\xc9\xa1\x87V\x94j\xd8Kj>d\xe5\x12o\x7f&%\x81v#Y\x1e\xc7\x82\
+\x9d\xaf\xcfL\xb5\xbc\xef\xde=\xecZT\x05KJ\xec\xd9\x8f\xdc&)\xc0\xed\xfdL\
+\x01z\xc6\xbe \xd9\xbcQ\r\xcc%\x11\x00\x8c\xc8\x07\x99a\xaf\x06\x8d\xbbUp\
+\xc2\xc5\x16.\xdd\x17/\xac_\x0e\x8fh4\x0c\x07\xcc\xa2|\xf4\xd8\x9a(\xfd\xef\
+\x97\x03\x15\xc0%3\xdd\x15\xdb\xa1v\xbfW\xf9/\xb7<\xfa7\xab\x95@m@`:X\xb6%\
+\xb5\xd2Q\xdd\xde4\xb1\x05\x929%\xa2\x03K\x86\xe1\x98\xe1[\x16\xcd\x0b\x10<\
+\x18\xff\x13\xcd\x9b\xab\xe0\x96[\xf5\x9dt>\xbc\xb6\xb8\x18 6\xea\xc3\xd0?\
+\x860il\xd6\x05\xb2\xb050\xf8eb\xf6=\xaa\x95\x08E\x1b\xef\xed\xf8\xb1S\xcdj\
+\x0bh\x96\xd7^\xcc\xb9E\xdf\xa1\xab\xf2\xf8r\xbc\'\xbdxi\xf5\xdaQu\xc5\xbd!y\
+\xd1\xf0\x9a<>\x84@;R<=>\x06SQ\x92\xff\xa423\x8db\xa7\xd0\xd9\xf9\x84ao\xde\
+\x83I\xcb\x01\x93\xfa\x8dJ*\x81\x1d\x1d\x89\x95\xc6\xf3Q\xc1>\xd4>\xce\xd8\
+\xe2\xa3V\\|\xea\xedF\x14kTR\xef\x08\xf2Gw\x93\xd1\x94\x9e\xbd\xae\xe6\xaaN/\
+\xcf\xda\xda_dB\xda\x93\x97\xe3F\x9c\x1d\x8d\x1dW>\xca\xca\x9c\xb3k\xf3k\\\
+\x8dO5\xeb\xaa\xdd\xe7SGjMC8\x8f\x1b=\xc0\xd1\xc5\xc1\xfb\xaf:\xdd\xf6\xf9c\
+\xb1)\xfb\xc2d\x0cw\x0cM_""\x12\x82\xed\x86\xd2X\x03\xee\xf2\xfe\x1e<\x9c\
+\xacpEh\xa7\xe4\x1a\x1c_\xb8\x9f\x91\x1e\xdc>\xca\xc8\n~\x13y\xfc\xf3\xf4y\
+\x13\xc5&\x8e\n\xa1\xa0G\xdeY$oX\xd1\x08uz\xf2/\x864\x06\xee\xd3\x87\x8d\xeb\
+\xf7T\xab{Fn}\xb1O\xb9\xc4\xf6\xf0-\xc1S\xf5\xa7}\xdf\x98\x9d\'\xb2\x92XVq\
+\x82\xd5.\xd1\xbd\xb1\x1e\xfcZ\xaa\x9a\xf7\xb7\xb2\xc1.\x1c\xaaN\x1d-t\xbb$q\
+6Uzp\x0fuD\x82\xad\xba\xc6_.\x9a\x06\n\x8f_\xf4\x94\xb0&i\x8f\xa3\xcd\xa5\
+\x7f=\x12\xba\x9d;\xb2\xa6\xf5\xd0V6P\xdf\xee\xd6\xf1\x9c\x9d\x1e\xc1\x7f\
+\xf1U\x98\xb2\x8b\xc0G`\xde\xc8Q\xb5,~\xdf\x9ay\x00\xd6\x90\x14 \xf1\xe8\x12\
+9h\\0\xd1?\xbf\x9a\xe5a\x821y"H\xfb\x89\xbb\xddwq?CX\x19\x851\xa7%,\xa7\xb9\
+\x11ItB\x8a\x01\'?q:\x05[K\x08<G\xf2*;00"\xed\xe9Z3o.5g\xf7\xf3*\x94\xe9jv\
+\xaa\x9042>Z\x96\xb4G3\xf5/e\xbe\x90Q\xfc\xb0\x1e/\xdd \\\xf5\xf2[M\t^\x7fx\
+\xc3\x96\x83\xd7\xb2\xa3v\xf29\x92~dp[\xb7\x03\xc8Hs\xecQ\xe0\xce\xf1#\x07\
+\x8d\n\x12j\xca\x0b+\xf2\x00!@\\\xd4[\xe5\xdf\xf5\x99$\xf0\xf6\x05m\xe50\xdc\
+\xdc\x18\xca\xa5c4\x03\x85]\x9b\x82\xecb~\xa9\x84\t\x04\xf3b\xf7/ME\x1alE"\
+\xec&.\xbd\x8e\xf6\xdc_\xeac\xfd\xb1\xe2\xd0\xfc\xcb\xbd\x1eT\x15\xcb\x1a\'{\
+m6Y\x84!\x95\xc4d\xae\x83\xbd\xc3\x0c.5:\x19\x1a\x07c\x91&\xba\x92\xe7\xfe\
+\xe4e\xde\xc0\\\xb3(\x10\xb8\x01\x99k\x181\xe8\xce\x89Dw\x85\xf3\x15\xc0\x90\
+/i\xc5\x08\x86\xfbc\xcd\xd9\x84:c^wj\x987\xd9\xa1\xb0\x82\x17(\x92\xa4\xe6\
+\xf4\x8e\xd3N\xca\x1dm\x1f\xccW\xb7\x08D$Sz\xd4W\xe7u\xc7\xce-\xa3C\x95\x06q\
+\xca\xb6\xf6\x80\x99\x86\xdf\xd5\x7f%R\x1dcp=V\x8fzWY_\x96%\xeb\x1a\xfd\x1c\
+\xfa\xf8$\xb8\x8cz\xfd\xc0\x8a\x1bz\x14)\x86\xe7O\x1f\x06<\x19t`}\xfe\xb8\
+\xbf,s\x12\n\x00`\xffx\xeb\x05\xd0\xbc[\xf09\x0e\xd7\x93\x1b\x84U\xfe\x86\
+\xb3\x1c\x91\xd8\xd2\xc3\x05o\xf9q\xd3\xa8\xde\x87\x9aQ\xd8\x1b\x86\x8d\xdfL\
+\xaf\x9a\x82\xa2\xb4\xa7\xe4\x86\x05Q\xcakt\xb0\x9e\x08U\xc8\xf7\xe4<EW\x8fc\
+\x16;r\x13\xe5\xee\xb3\x96_\x11\xbc\xb0:X\x9eZ\xb8\xebl\xa5B\xa5g\xd0KH\xc4j\
+\x91\x1d\xfa\xbaO\xf4\xefC\xebA\xb4\rY\t\xf8\t\xacP\x99\xb1\\|\x8c\x03\x9d\
+\xa7\xa7R\x19\\\x7fz\xcf+n\xd6`eT"\xee:\xac\xc7\x8cHD{\xcaL\xb6\xcc_\xbf\x82\
+\xf6\xb7\xf2\xbd\x0b1]HP&\x13\xf1\x9c\'\xa2\xe8\xc2\xaa\xc0\x04T\xd8\x9b\x01\
+m"W\x9f\xdb\xff\x8d\x03\xe9>3c\x98\x18\x1b\x86\xe78\x88\xbe\x1b\xa8e\xdb\xb9\
+\xe9\xc0\x94>\x1f\x9e\x9c\xefxZ\xcaD0\xe9\xc2\x987\tQ\xfe\xacA\xce\xef0\xc0N\
+\\O\x1b\xe7\xddI\xe6\xe2\x1d\xe4iu\xaf\xc2\x08;"\xb9=e_\xf4\x0b>\x0c\x98\xd7\
+\xc2~-\x85\xa9/F\x90\x1bRk\x8e=;\xe7\xf8|\x0b\xe7wv\xf6\xd5\xfbo\xd1\xba\xdb\
+\xee#\x87MK\xd4\xb3I\x84\x1b3y4\xaf\x999x.\xb2\xbe\x0b\xdf\xe2\xba-\x92\x11\
+\xda\x96\x842\x96\x9c\xa9\xd9\xd7\xe7\xaaQr\xc1\x8b\xe5\xc0>p"F r \xf9!q[\
+\xc8\x88+{\xa4\xaaJ%\xf6\xa9\xdc\nE\x01F\x88\xbbx^JQV\x08\x14k\xea?fW\x99\
+\xac\x8d\xa8\xb6\xa8\x96\xcbo|8\xbds\x08\x970\xfc\xb3\xeb\xafR\xd2x\xd3\x90\
+\x88\xfb\xb0+w\xb3\xd7\xcf\xd6\xbaBH\xd6\x1f\xa2Z\xd6\xaa\r\xc3yu\x90\xfb\
+\xb2_Y\x1a\xa2\xc10\xd9\xd1\xc9\x96]G`\xbeG\xa5n\xba\x87\x9fUoi\xedd\xc1\xd2\
+\x03\x83@\x87R\x0f\xe2\x0e\xefQ\x00 c\xfd\xe5f\xa0%\xd2\xa6\xbd\x08\xe2\xc1\
+\xfa\x83_Y4{\xe4++\x1c;\x96\x982\x0e\xc9k\x88\x99&\xcb\x83\xe4\x9b\tbC\xb7\
+\xc2i\x0b\xc4k\xe5\xc6\x9co\x04\xd4\xab\xccN\x18\xfa\xbd&ey\x8f\xb0\x12qL\
+\xea\xaa\xc5\x8d\x80\xcaP$\xfa\x81.\xbaK\xf9rL\xb6\xfeH\x03\xfb\xde-\xd7[\
+\x19\xae.\xfdD\xdfB(\xc0\xc7\r\xed\xda\x83\xeb#`\x9fj+\xfa\x9b\xc4\xc4i\xaf;\
+\n\xdfZ\x88\xe4\xb6.,zB\x94\xb2\xee\x85jW\xfd\t\xa6\x811\x9a\x1a9\xfa0[\xc2\
+\x90J3\x82m\x0b\x06\xd7dO\x816b@\xf0\x99\xc1\xe4H\x07\x13bK\xca\xa1\xfdJ\xf8\
+S\x0f\xeen\xa8\x12q=\xe3\xdf\xa8\xa1U\x8e\xbf\x88UI\x99\x08ld\xb6\xc3K3\'\
+\xbf#\xc0 \xec\x07\xd6\x83T\xb1\xd4\xef\x0b\xee\xd1_\xeaU\xd2a\xb9\x06\x1f\
+\xb0\xf6\xae|\xae.\xf5\xc4,&\x9dyA\x0b[q\x1dTW\x8b\x85c9\xfe\x880\xe5g\xba\
+\xe3(\xb7\xd1t"\x91\xa1\xf9\xf6\xb6\x02=;\xd7\xfd\x8fw\xd9c:\x1a\xb9\xd8s\
+\xae\xfdf\xa2\x13\x9f\xf8)D\x95"\xf2N\x18M\xd29i\x93\x84\xc8\x02\xac,I\x1c\
+\x92?\xd2\xdew\xd4\x8b\xb1\x8bu\x98M1Gz\xb0R\xa4\x89\\})\x87f$\x83\xb6\xc6\
+\x16\xf8\xe0\xa0#r\x85\xbb\x9e\x0e\xe1\xbbR( \x9aX\x83\xf9i)[\x07\xeb\x0c\
+\x0b\xa6\x9dr\xe8\xad\xa2\xc8\xd05f\xbdf|y\xb8%@\xf0ecv\x84\xd8niM\xab\xbf\
+\xa0\x85H\xf8\xfaD?\x99\xacN\x94\xe5J<=\x18\xdcBdnxm\x86ek\xea\xa3\x06\x8e\
+\xc7\x7f`[\xf4\xe0\xc7s;\xb7\xf88\xc9\xa2\x1c\xad\x8b~\x98\xab>\x0b\x1d(`\
+\xdb\xa1$\x89Z\x00QS}\xeej\x85}\xe0\x8c\xf7YQ\xf1\x80\x9c\xc3\xef\xf0l\xf5e]\
+\x7f\xd4\xb2\xce4}\x99\xc5M\xa3>\rl\x08\x97?~\xb1\x11}\xe0\xbdz\xa2o\xc9\xbf\
+\xcf\xe7\x0c\\E\xb8\xa8G\x8f\xcb\xbcO\xc1\xeb\xae\xe4\xa9\x17Y\x8c\xca\xd1\
+\x8fx\xda\xf7\x8dS\x96\xfe\xd6/\xc4\x96\x12;V\xffR\xd6K8\x92\x17c\xfa\xfc\
+\x93\xd8\\\x9b\x00\x98\x16\xc5\x00\xc75\xd8\xd7U\xc3\x92\r4B\x1d\'\xf30\x7f.\
+\x17\xb8\x832F3\xdbQ\xd7N\xe0[\xdeT\xc0<\xd8\xfe(\xe6\xef`\x0f\xdf(\xdb\x9f0\
+\x98S\t\xfd\x8cy\xc5\xfc\x8d\x91h+\xba\xb3\xce\x95wi4\x15\x11\xba\xd1\xe5\
+\xa6\xa5\xf2\xc7m\xa7\x83\'\x1d\x11\xe4\x06\x95\x0c;\xa4\xc38\xf2\x89^p&{\
+\xf2\x0c+\xbd\xe2l\xa8\xbd\x99\xf9r\xb1\xb4\xe0\x92\x86\xdc\x18\xf7E?\xd1\
+\xecJ\xfa7x\x92\xf01\xef\xd9\x08Q\xddmU\xbe\x96\xaae>\xd0\xab\xe1#\xfb\xa9X\
+\xc7V\xa7\xd9\x86\xde@\xe74l\xad\xcb&\xf5L\xb8{jb\x0e#\x0b\x15\xf9;\x8ab\x19\
+\x99<p\x11\x82\xb9!m]\x1e\x0f>\xc0\xe5c\xc8\xd9\x84\xe7_/\xbd\x1e\xda\xa4\
+\xd8\xa7\x82\xaa\x87r\xea\x8a\xb6\x91\x9dTC\xc73\x84$\x93Ct\xca\x0e\xaaJ\x8e\
+\xfe\x1c\x85&\xf6\x95H0\x8b\xb0\xf5SZ\xfc\xd5\xf6,\x84\x8b\xc6\x0bP\xcf)X\
+\xae\x8fS\xc3\x1e\xb7n\xa5\xbf\xb7U\xf3>^3\xbe)|\x19i\xe8CU\xeb\x94\xcb\xbf\
+\xab\xb1\x05rV\x14\xde\x0cN\x13\xc1\xf9\xe8\xfa\xa2I\x7f\x12\x12\xee\x85\xd6\
+\x95\xe8\x80N\xc2G\x84\xebt\xcd,\x91C\xb9#\x93\x10p\t\xe9\xbb(\xc7\xe8\xab\
+\xc4\x1a\xccB\n:@\x1f\xf7VS\xfc^J\\$=\xc7\xf9\x0c\xc0\xb6\x82rdQ\xc9n+\x91xu\
+\xfe\xd0\xd6?\xc01\xdb_\x18\xe3\x18\xfay)\xe1L\xee \xa06\xbbk\xaa9q\xfd\xd2e\
+e\x15E\xb7q\xd7\xb2\x8fc\xc8\xeb\xc6i\xa7\x11\x85E\x11\xb9\x13\xf6\xf9a\xc3S\
+)\xdc\x17d\x0e\x95\xb4\xf7\xde<\n1\xf8Jo\xf1\x9d\xb6\x8f\xb2\x8a\xec\x12"\
+\x13\xf8\x142\x06\xd0\xb9>\x98\x911c\xa2\xbe\xb4\xb5\xc8\xa1\x12\xc7:y-\xe8\
+\x9a[\xc7\xe7\xf6q\x8a\xa2\xe3\xc6\x97\r\xffz3S1\xd0\xa6i\xb1\x1eH\xf0\x0br\
+\xfe\t\xf5iw\xa5\xd1\xb1>\xac\x1f\x08-J#`\xea\xdf\xb3C\xa3\xbd\x1dS\xc9P\x07\
+\xe6\x91\xc6\xad\xbf\xaen\xe5\xf3vi\x8b\xd5Io\xf0\xa3\x1d4\xd2\x92\xf4\x8e\
+\x05\x9b\xf2\xde|K\xa3\xf4\'{>{\xb6h\xf1\x15\xc5\xfcX\x17\x8f!!\x86|q\'|\xf2\
+\x84>\x8c\xe9\x00\xe9\xe7ml\xcf\xe1\xef\x86\xe5\x9a\xaf\'\x893\xbe\xa6\x19\
+\xfcj\x902M6F\xac^{\xc2e\x170Xbl(\xbeQO2\xfe\xf4,\xfao\xecC\xac\xb7\xf6\xa2\
+\xcbdY\xce\xd3\xfc\xea\xa7\xaf\xf4\x00\xa1i\xcc\x83k\'\x9a\xb2\xbc\xf5~\xc6\
+\x1f\xd7\r\xcd\x7f\xdek71\x99\x98N4Q@\x93\xc4w\xbe9=5x\x08\xbe\x96\x90\xbe\
+\xe7\x0c\xc1\xa9\xaat44\x87`\xbb\xa0\xdeL^\x12\xa7\xe2\xfc\x84\xcc\xaf\x1f\
+\x82\n@6\xf7\xe0\x1a\xeb?5\xef\xcf\x89v\xafv\xfe\xacdi{\xd1\x9c\x04^\xe1\x19\
+\xb5\x9d\xd2/\x06\x18\r\x8a`\x97K\xd2c\x8d\x01q\x10~\x92:F\n\x16\xf4\x85\xd1\
+%\x00+G\xc5&\xa2bO\xf4\xb1\xa2\xfe\xd6\'\x0b\xd8\xdbp\xa862\rkDy5*\\\xd8D\
+\xf1\xb8\xddH\xd2\xb3\xa9,\xd16\x8a\x08\xdfX\xb3\xd2\xb4Nt\xcd\xaei\xd5\xd4\
+\x85$\xc8\x88\xd0\x8a\t\xc9\x94\xb2I\\\x9f8|yBE\x87\x17\xf0\xde\xff+px"4\xe1\
+&\xed\xd9\xd0\x14\x800I\xba6Z\xbcl\xc5\xe2\xc4G,3/e\xec\xd9jvAt\xb2^\x83/^\
+\x0fB<h\xa3\xbf\xe6\x07\xe0\x83\xbb\x8a\xbe\x1d)R\xbd\x12\x04\x04j\xe8\x1f]\
+\x10N\xd4\xf1\x87\x85\x9a\xf1\x93r`\xdd\rgge\xb8y\xe7p\xf4/\xba\x8e\x95u+\
+\xaf\x87\x95\xd3+\xab8C\xd3\x81Z\xcc\xa1\x04g\xa3\x03>\xd3\xb5\xd8\x9f\xbfb\
+\x10; \xcd\x94\x7f}O\xe8I\xd1h\xce\x8b\x91\xe7~o\x97\xe3\xa1h\xda}n\x0bf\xdb\
+\xd0p\xaa\x1a\xab\xd3:=<\xca\x98\xa3\x14\x9fh\x12\xc4\x97\x96\xe5\x10\xea\
+\xaa#WI\x8f\xf8c\n\x98\xab\xd60\xd0\xcf\xa3\xf3\xafb\xa8K\xda\xdeO\xec<{\xd1\
+\x9e\x84"\xf5l\xd6\xba\xfeD\xfd\xae\xf6\x1a\xa6\xe9Z\xd9\xd6\xa9\x8bJ\xc6\
+\x03\x9b&\xb4_\xbf.{\x97z\x90\xd5\xb5\x92\x95uU\x87\xe8\xef\xe6%\x9a\x9c\x9a\
+\xe5\x7fS\t\xc99i\xd5\x90\x99^\xa0\xd6BL\xc4;\x95U\xa2geIq\x86\x83Kx\xe0\xcb\
+\x84\x10\x89\x07\x96\xa3E\xb8\x9fi\xf44\xf5\xe0^{\x91\x14s\xe2\xb6\xfe\xb5\
+\xd6\x1d\xd1\xc53\xc0\xea\xc9\xf8\xd8\x12\xce\xf6R\x85\xe2\xd2cN\x94\r\xec\
+\x1e\xfa\xf9\xcb\x9f\xcc\x07\xf2\xf2\xf7\xa8\xf5\xe2G.\xd9nx\xe0\x13\xfd9%\
+\x97,\xa3\xa1\xbb\xbcu\xa5\x96\xd7;,8\xbc\xb4\xa2\x7f\xf9\xf1\x83#<*_\x08\
+\xffTN\x87\r\xf5\n)\x84\xa7{\x1a(.\xb3\xf7>\x92\x87\xaaY\xb3=m\x02-~j\x1e?p\
+\x87mD\xe8\xc6\xfa8g\x9aOD\x1e\xd1\xf1\xe4\xd7\x87!\xcf\xea\x9f\xd2R\xf8\xbe\
+\x96\xa0"x?l\xf5_[h \x8e\xea\xb3\xe8\xbcc\xbdM\x9cr\x98\xea\xbd\xa2\x14\xc2]\
+\xbc\xcfn\xdb\x1a9\x8c?\xb0\xeb)\xc1M\xf7_\xe6\xda\xb6\xcb\xdd\x9e\xca\xf1\
+\x86%\xab\x9fG\x94\xed\xa3\xc9\x0ez\xb9\x07<[\xa9\x99C\xb0\x81l\xdf\xd4@\xab\
+\xa3\xa1\xdb8\x89"\x90\xa2c\xca\x91D>\x8f\x9a\xc1\xe0\xf7;^\xfcX_)kaD\x0f\
+\x0b\xa4\xb4\r/\xc4(\xef\xd504\xff\xa4\x7f\xdc\xa1<\x12w\x12\xffn\xec\xda\
+\x95\xac\xbb\xcf\x99\xf6,\xc3\xda\xab\x97o=\xcfU\x81+\xc2\xf7(\xf0\xc3\xff\
+\x1d\xf2 k\xc2\xd1k\xe5\xd1`\x18O\xbb\xa1\xd8\x94\xba\xd1\x9b\x92\xe0\xe4{\
+\xa5A\xa3\xa3:\x1d\x13\x83\xfb:\xff\xa6\xa1\x16}\xec\'[8\x95\xd3\x9f\xdd\x81\
+\x93)\xb1\xa3\x04j\xb2\x01n\xd3\xea\xb25\xec\x80\xe7\xbaB`\xae6v\x1c\xc2\xef\
+E\x8f\xa4~!\xe9\xdew\x0f8\xcd:\x84\xb0\x90i\x02p\x15\xaa%\xd2\x1c\xa1\xb0\
+\x13\xa3?\x00\xdd\x93\xcc\xd3H\xe6g\x97+\xd1\xf2p\x8f\x18\xdf\x07\xb7\xfb\
+\xcfAy\xfa\x19\xac\x06\x85\xb9\xa4H\xccg\x8b\\R\x10*nM0\xa1E\x0f\xa0\xd4\x06\
+Q`\x84H,\x10\xb5\xe5\xdd\xc1d\xc2\xd1V~\x81\x16K6\x7ffD\x83\\\x01_Ch\x8b3\
+\x992\xc9R\x9f\x83\x1b\xab;\xdf\xf4I\xd7\x83\xdcb}\x81:(\x82\xdd\xe4\x03\x1a\
+B%ry\xcdi\xf0\xb4\xee^\x0eU\xf4\xf8\xb9\xda(\x9b\xb2E$\xdc\x08\xfc\xef19\xd8\
+\xf2\xa0`\xdb3Q,-r\xf9S\xada##\xc1Kb\x8d\xfc\x87\xb3\xbc\x9f3\x8c\xfe\xe9L\
+\xb6z2\x0em\xe6$U\x84\xbf\x7f\x99\xdb\xcb#\xb5\x83\x99\x92\x9a\xd7b\x15\xf0\
+\xbd\x9d\x96\\\x86bf\xeb\xf3\xb6\x8e\x92\xf15U$\xea\x06n\xfd\xfd\xdaW\xdcQ\
+\xb8\x02\xf7\x1c\r]\xe8\x8e\xbe\xe6\x1f\xf8\x83\r\xfeI\xe7\xffy\xcaOD`\x90\
+\x163\xa7\x11?J\x0c\xb5\xab\xb1 \xd4\x92A\xf2\t\xe1\x11H<;H\r4Q\xfa\x16lg\
+\xcd\xb4\x95R\xe1\x96\xea\xd6\xe7\xe5\x99o\xd2\x1f\xdd\xabH\xb6""\x02\x8c%;\
+\xec\x8c\xe3\x0e\xafE\xe6%\x9c\xc6\xbb\xa5*\xc3\x95\xe0\'\x1bj\xc1\xe4(S\xc9\
+\xf8lD\xea\x0cD\x91\xfd\x065FB pB\x15\xc9\xf5yy\xa4\xd9\xb1\x90`\xe0lL\x84\
+\xb1\xe1v\xa3\xf9\x86\xd4\x83\xeb\x12|\xb3$]}"i`\x1c\xcf\x80?2V\xc5\xd6\x12\
+\x8e\xb9"\xa6\xfb@M\x0c\xa7BH\xf1\xdcI\xb8\x81\xaf\x94\xde q7\xff\xe9/<\xb0\
+\x9c\x1aZ\xfb[\x0co\x8a=`&^p\x91^\x0fG\x7f>\xe8$x\x01\x1c\xed\x93\xd6\xd6Off\
+\xf7^\x8b7\x94\xc0\xc3\x12h\x7f\xe4\xe53=\x1f\xe2z8\x8f\x06a\xcf\xd6\\F\x96\
+\xc9\xd8\xce\x17F\xeb\x1e\x0cQ`\x95E\x97\xf7\xe4}J\xfe\x12_\xd7\xbe\xeb\xa8\
+\x14\xe1{\xbb\x19\\Sn\x92\x95\xbek\x18D\xfd\xe1\xe1_\xd9oy\xbe\x85\xf5\x89Q\
+\x15\x0c\x11\x91\x96\\N\xd8\xab\xf1:\x88\xf1\':\x9aY\xfbF\xf2U\xf9\x8a"\x9c\
+\x85ss\xa3)\xe7A\xfc\xa1{\x8aOD\xca\x14\xc8\x9a\xe6\xfcZ\x8a\x9dH\xf34f\xd2\
+\x04\xc9\xe5\xb7\x1e\x9e\x84\xd7\x86hS\xcc\xec\x8b\x9e\x1f\x05\x0b\xb2\xff\
+\xa5\x04\xa9\x9b\x13\x1bh\xb6\xce|\xe9n\x89\xe6\x0f\xfcdW\xe8\x9f\xe8`\xbdn\
+\xbe\xb2\xcfp">\xc1\xe8\x96\x92vO]l(\xa6\xe0\xb2\xf0#\x83w\x17\xa0t\x99o\x11\
+\xb8H\xfe#\xde\xf8\x92"\xe0\x84\xe5\xd7\x96E\xa1\xfc\x0f\xfe\x0c\xc0]\x97\\9\
+7f\'7\xc5;\x9d3\xa2}|\x01\xae\xd5\xc1\xb2\x00\x89O\x94\xdc\x82\xdd\xa8\\k\
+\xbbs(N.\xab\xa7\x14e*\x9ccI<\x8b\x1f\x9dj<\xa8/\xb3\'/\x83\xe8u\xce\x96\xe5\
+\xb49\xad\xfdm\x91\x1eHW\n\xfcX\xd7\xb5\x91\\\xeaDk\x85]\xd7\xe4\xab\xe2O\
+\xf9\xc4\xe4\x9b\x83\xc1\xdf\xb1\x8b\xde\xbd\x03R\x14\xf7p\xa8\xcc*\xccq\x88\
+\\\xc77\x8f\xdch\x99\xd8\xcb\xa1\xfd\x1c@"\xbe\x82"\xff\xb0\xb0m\x84od\x92\
+\xe8\x0e\xb1B\xf1\xf1\x00^\x1b\xcf\x99\x82\xb1"\x1c\x89\xcb\x06\x7f\xd8\x1c\
+\xbd\x0f]\x1f\x11J\xfd\x06(\'\x14\x9eks\xa9\xea\x86J\x1cF\x7fL\xc39\x7fe\xfe\
+K^\x0b\x02\x17\x0b(sd\x86\xfa\xa8\xff\xa0\x7fV\'\xed\xea:\x87\xec\xe2\xb1|\
+\x8bM\x8f\xf9w\xb1\xcb\xb4\xbf\xc7\xf4\xea\xf4m\x1c\xfe\xab\x00C\x03\xa2\xb2\
+R\x0e\x8f\x85\x07\xef\xd0\x1aOs\xf1f\xec\xfb\xd2*\xcek\x91n|\xc4u-tn\x8a\t\
+\x8d\xf7\xaez\xb8J\x15\xdbz\xba\xea\x90\xda\xd8\x9e\xd9\xfe5`!\x96\xa8X~\x83\
+0\x88_\xca\x8e\x07~\x11\xb7\xc0UQ=\xb9\xa6d\xad\x92`>\x17\x98\xadvFn\x8b\xe2\
+\x11# \xfe\xa39\xee\x07\xfbUS\xe8\x95\x16r\xb8\xad,\xe1J|\x882\x13L\xad\xa4t\
+\\Oa\x08F\xe6\xe5\x1aO\x94\xc6"I\xb9\xb7d\xbe\x94\xbc\x7f\xff;\xc1\x84\xb8\
+\x0e\x81\xbd\xebwp\x94\xcf\x8b\xee\xe8\x18\xecR\xeb<\x9a\x8d\xae^\xa1`\xc4\
+\x9e[lz\xce>\xe5u)\xbd\xca>\xc9\x1d\x077B/\xf6\x08\xcal\xcaR\xc2 \xe8\x9f\
+\x7f\x05\xef>1-\xc9\xa6\xe3J\x96\xde\x89\xde\xc4\x95(\xf8\x1a\xb4\x94s\x04\
+\xfc\xb9\x90\xe7I\x8b\x1b\xa2N\xf6,\xae9\x92k\xe7\x06)T>\xbe\xb7\x15Y\x10\
+\xff\xb1v\xc31,}\x88\x02\xbd\xa1h\x89\xfc\xd9\xe5I\xf4PP\xf6\xd7w\x03`\xe6&\
+\xb2\xa0\xadl}dL\xa7\x91\x1a\xfd\xe4\xdc\xd8\x08\x8aC\xa4\xa8\xfe)\x9c\\\x02\
+yr~0\xaf\x94\xfc\r\xd7,\xf1\x84\x97\x1c\x84\xc1I\xa3;\xc5\x9b\xbf\xb2k\xb4\
+\xc7\xbf#\x1d\xd9\xd2\xd8\xf1@E\x82e\xfdqN\x83\xd4\xa4\xb2;\xa7\xea\x07\xeb\
+\xdfl\'\x7f\xfc\x9e\xed\x1c\xb2\xe9N\xd4P5\xdd\x0c\xf7\x86"fg\xc5/\xe6\xa1KK\
+\':F\\\x08\x9f\xf4\xa6\x0e\xc5e\xd8\xb8\xaf\xcd\x85g\x12xS\xf2W\xcb\xf02)\
+\xeb\xaa`\x02\x97?\x15\xea\n\x0f\x9ce\x99O\xc0\xa4!\x1dv;\x84!\xf77c\xa8\xaa\
+Q`\x10\x08\xf4\x13\xe4\x8aGy\x12\x17\xff\xca\xc6^\xb0(\xd6c\xba\x7f\x08]\xa2\
+\xed#X\x11\xcfR\xf64\x15\\I\xbd\xc4\xf4&\xbf\x96f7B\x17\xc3\x1d.\xae\xfe\x94\
+wM\x81\xecB\x11QO\x1dvV\xb8F@\xca\x98\x13\xed\x18}f\xdb\xcd\xe9]\x11;\xf9t\
+\x9c\x1a\xc5\xf3:\xcf\xdd\xecY\x99\xb5\x92z"\xe6\xdd^\xf2\xb8\x88\xb9\xd1\
+\xf9Qn\x8d\x00\x92Th\x82>\xd7\xd9d\xe1\xa6\xe3\xc4\xad\xb5\xe0b\xee\x11\x1a \
+\xae\x952\x8b\x15\x91d\xd1-\xdb\xf9\x9e\xbd^L\xbf*\xbe^(\xec\xec\x0fi\xdc\
+\x8f\xc6\x07\tw\xb9\xb8\xc5\xfb"H\x18\x02\x0eS0/\xf6\xe0\xe3\x17\x8c\x9d@w\
+\xb1\xf1#!\x18\xcca3\x16\xf9\x80\xf2\x0f\xc6\xe0\xe4\x7f\xa9\xd6\x7fWYB\x90\
+\xeb)\x0f\xc7\x7f\xd7y\xd4F\x7f\x1b\xf0\xa6\r\xf1.\xc28X!\xf9m\xe9.\xbdDf\
+\x1b#{\xdb\xce\x7f\xd8\xe0\r/$>\x85w\xbc\x1d\x83\xe7\xf5tn\x9dx\xfc\xd7\x9d\
+\xf7*\x17uYU\xaf\xbf\x93\xa9\xb6\x10\xa2\x19x\x0e\xc3\xed\xe4\x9b\xde~#\xd3\
+\xdeB\x00\xdf\x96Y\x94\xa4\x8b\xf2\xf4\xab[8v\x97lM;\xa9\x85\xebn\x1a\x0f$\
+\xc5\x89D \x8b*\xe8\xd4\xd2\x82@\xd0\x05\x9f\x93\x1d\x9d/<oOw\x10K\x9b\xb29S\
+s:M\xa1\xde#\xaa\xbfY\x12\xaed6k3C`c;\xe6-Y\xb7{\xa8\x82\xaa\xedT\x16\x84f\
+\xf93\xedN\x9f\xf8P\x833\x1e\xa1\t\xbev\xda\x86\x06i\xb0\x01wv\xe5\xc9\xe7d\
+\xbc\xfa\xa8\x9fD\x10m\x9e\x88\x15\xc8h\xa0\xbf^\x12\xd9\xd2\xc3E\x1d\xeb\
+\xb9\x96@z\x0fc\xe0\xeb\xad\xc8\xc5\xa8y\xe9de?\x15n\xf0)GV\xa9\xcc\xf2\x9fe\
+\x85\xad\xab\xba\xc2\xd9/\xedK\xc9\x92i\x16\xf7x\xab\x14N\xd2\xd4\xa4\x88\
+\x03v\x024eq\xf2\xd8\x1d*\x19\xaf\x1f\xe2\xbfJI\xbd\xed\x11\x01\xfe^y\x88q5\
+\xc4\x86\x9c\xf7{N\xba%\xd3\xb8\xe1f\xd4\xef|}P\x11\x18\x87J\xd8\xd9\xe8\xa5\
+\xfaL\xc4\x92\xa4\xff\xa9-\x9aVD\x87{\x16\xd9}J\xcdSPeL\x1bQ\x1c\xb0\x7f\x0e\
+\xf6\xbe\x84n\xcb&3}\x1a\xc6w\x1aw\xad\xb8Ys1\x9a\xb9_P\x10nB1,\x99\x8ec\x94\
+\xfb\xbd-\xa2\x87\xe7X\x8b\xeaa\xec\xae|\xeeQq\x19]\xe6m\x03\xb3h\xf3\x89e\
+\xa8\xdf\xe0\xb6h\xa8\x01\xa7\x8fHw?W\xa5/\x83\xe5o\xb6|l\x08\xdeYt\xc2\xdb\
+\nD\xf8\xa5,\xd0\x8d\xf7\xea[\xeb\x9f\x15\xfe2}\xcd\xaf\xe6n{\xd5.\xd36R\x03\
+g\x83\xc4\xc3\xf7\xd8\x08T\r3\xd2\x16\x96\xd7\xfcG80\xcc[\xa9\xf8\xcc\x1bD\
+\xf1V\x12q\x88\xb1\xfe\xbc\xb8\x9c\xe45S\x1f\x0c\xec\xea\xad&\xea\x0c\n-\xbb\
+\x16\x15\x04/\xa7\x14K\xa6\xd3p\xc3\x13z\xeb\x8c@\x01j\x1a9\x02\xa0\x05\xb3\
+\xab\xe5+]\xb7!.\x1c\xfc\xfc\x81\xb2\xe94\xbaTQ\xf7O\x83\xe4\xe4[\xcb\x9d\
+\xc2\xf5\xff\xb9\x0b\x95\x80\xce\xd1\x009Z\xfb\xcfhx\xb5\x8b\x9bsM\xe9\xe0W\
+\xeco\xdd\xa6o\x0f\xaac\x97\xec<\xaa\xceF\xbc\xb3r\xca\xa6\xe3x\xdel\xa5\x17\
+%\x85v\x16\x7f\x93W\xb7\x95\xca4\x9b\x13g\xf5p\xcf^\x98\x96\xee\x98\xe2\xca\
+\xc1\xb6\xf8d\x0e\xc581J~\xe4YV\x90\xe0\xf1o\xf7\xfe\xda\xb9h\x83\x1c\x8e\
+\xe7\x1co\x85\xad\x8e\\\x7f=\xdac\xb1\xb7\xa8\x89\xd1U]s\xa2\xfa*\x82\xa5\
+\xd4\x8b-\xda\x8dh\x8b\x19=9\x84.iC\xa3\xec\xa4\xfe\x8f\x90\rG\xb5\x89\x96\
+\xff \xb3\xc6\xadm\xa2\xae\x82\x9f\xc3\x13\xbf${\xca\x06\xc5\xa0${\x00\xd7\
+\x8e~z\x14roy\x00*\xfb\x17\x85\xe7\xa4\xa8\xfaJ#\x88\xe2\xa5\xd4\xa9\xdc\xd9\
+I\x15\xd9\xdf\xac\x91*\xa1\xc7\xd6k\xe2\x1a\x94xE\xf4\xfa\xa4\x840\xf2\xbf]x\
+u\xda\x87bx\x83\x92i\x9bO9.Q\xaf\x88\xa4^\x87C\xe4/\x18\x1dA\xfd\x1f,\xcf\
+\xcb\xda\x00\xaf\x1fYI%\x89Z1\x93\x90\xff\x01"\xf5 \xb2' )
+
+def getScreenShotBitmap():
+ return BitmapFromImage(getScreenShotImage())
+
+def getScreenShotImage():
+ stream = cStringIO.StringIO(getScreenShotData())
+ return ImageFromStream(stream)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/BBox.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/BBox.py
new file mode 100644
index 0000000..2fef1b9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/BBox.py
@@ -0,0 +1,303 @@
+#!/usr/bin/env python2
+
+"""
+A Bounding Box object and assorted utilities , subclassed from a numpy array
+
+"""
+
+import numpy as N
+
+class BBox(N.ndarray):
+ """
+ A Bounding Box object:
+
+ Takes Data as an array. Data is any python sequence that can be turned into a
+ 2x2 numpy array of floats:
+
+ [[MinX, MinY ],
+ [MaxX, MaxY ]]
+
+ It is a subclass of numpy.ndarray, so for the most part it can be used as
+ an array, and arrays that fit the above description can be used in its place.
+
+ Usually created by the factory functions:
+
+ asBBox
+
+ and
+
+ fromPoints
+
+ """
+ def __new__(subtype, data):
+ """
+ Takes Data as an array. Data is any python sequence that can be turned into a
+ 2x2 numpy array of floats:
+
+ [[MinX, MinY ],
+ [MaxX, MaxY ]]
+
+ You don't usually call this directly. BBox objects are created with the factory functions:
+
+ asBBox
+
+ and
+
+ fromPoints
+
+ """
+ arr = N.array(data, N.float)
+ arr.shape = (2,2)
+ if arr[0,0] > arr[1,0] or arr[0,1] > arr[1,1]:
+ # note: zero sized BB OK.
+ raise ValueError("BBox values not aligned: \n minimum values must be less that maximum values")
+ return N.ndarray.__new__(subtype, shape=arr.shape, dtype=arr.dtype, buffer=arr)
+
+ def Overlaps(self, BB):
+ """
+ Overlap(BB):
+
+ Tests if the given Bounding Box overlaps with this one.
+ Returns True is the Bounding boxes overlap, False otherwise
+ If they are just touching, returns True
+ """
+
+ if N.isinf(self).all() or N.isinf(BB).all():
+ return True
+ if ( (self[1,0] >= BB[0,0]) and (self[0,0] <= BB[1,0]) and
+ (self[1,1] >= BB[0,1]) and (self[0,1] <= BB[1,1]) ):
+ return True
+ else:
+ return False
+
+ def Inside(self, BB):
+ """
+ Inside(BB):
+
+ Tests if the given Bounding Box is entirely inside this one.
+
+ Returns True if it is entirely inside, or touching the
+ border.
+
+ Returns False otherwise
+ """
+ if ( (BB[0,0] >= self[0,0]) and (BB[1,0] <= self[1,0]) and
+ (BB[0,1] >= self[0,1]) and (BB[1,1] <= self[1,1]) ):
+ return True
+ else:
+ return False
+
+ def PointInside(self, Point):
+ """
+ Inside(BB):
+
+ Tests if the given Point is entirely inside this one.
+
+ Returns True if it is entirely inside, or touching the
+ border.
+
+ Returns False otherwise
+
+ Point is any length-2 sequence (tuple, list, array) or two numbers
+ """
+ if Point[0] >= self[0,0] and \
+ Point[0] <= self[1,0] and \
+ Point[1] <= self[1,1] and \
+ Point[1] >= self[0,1]:
+ return True
+ else:
+ return False
+
+ def Merge(self, BB):
+ """
+ Joins this bounding box with the one passed in, maybe making this one bigger
+
+ """
+ if self.IsNull():
+ self[:] = BB
+ elif N.isnan(BB).all(): ## BB may be a regular array, so I can't use IsNull
+ pass
+ else:
+ if BB[0,0] < self[0,0]: self[0,0] = BB[0,0]
+ if BB[0,1] < self[0,1]: self[0,1] = BB[0,1]
+ if BB[1,0] > self[1,0]: self[1,0] = BB[1,0]
+ if BB[1,1] > self[1,1]: self[1,1] = BB[1,1]
+
+ return None
+
+ def IsNull(self):
+ return N.isnan(self).all()
+
+ ## fixme: it would be nice to add setter, too.
+ def _getLeft(self):
+ return self[0,0]
+ Left = property(_getLeft)
+ def _getRight(self):
+ return self[1,0]
+ Right = property(_getRight)
+ def _getBottom(self):
+ return self[0,1]
+ Bottom = property(_getBottom)
+ def _getTop(self):
+ return self[1,1]
+ Top = property(_getTop)
+
+ def _getWidth(self):
+ return self[1,0] - self[0,0]
+ Width = property(_getWidth)
+
+ def _getHeight(self):
+ return self[1,1] - self[0,1]
+ Height = property(_getHeight)
+
+ def _getCenter(self):
+ return self.sum(0) / 2.0
+ Center = property(_getCenter)
+ ### This could be used for a make BB from a bunch of BBs
+
+ #~ def _getboundingbox(bboxarray): # lrk: added this
+ #~ # returns the bounding box of a bunch of bounding boxes
+ #~ upperleft = N.minimum.reduce(bboxarray[:,0])
+ #~ lowerright = N.maximum.reduce(bboxarray[:,1])
+ #~ return N.array((upperleft, lowerright), N.float)
+ #~ _getboundingbox = staticmethod(_getboundingbox)
+
+
+ ## Save the ndarray __eq__ for internal use.
+ Array__eq__ = N.ndarray.__eq__
+ def __eq__(self, BB):
+ """
+ __eq__(BB) The equality operator
+
+ A == B if and only if all the entries are the same
+
+ """
+ if self.IsNull() and N.isnan(BB).all(): ## BB may be a regular array, so I can't use IsNull
+ return True
+ else:
+ return self.Array__eq__(BB).all()
+
+
+def asBBox(data):
+ """
+ returns a BBox object.
+
+ If object is a BBox, it is returned unaltered
+
+ If object is a numpy array, a BBox object is returned that shares a
+ view of the data with that array. The numpy array should be of the correct
+ format: a 2x2 numpy array of floats:
+
+ [[MinX, MinY ],
+ [MaxX, MaxY ]]
+
+ """
+
+ if isinstance(data, BBox):
+ return data
+ arr = N.asarray(data, N.float)
+ return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)
+
+def fromPoints(Points):
+ """
+ fromPoints (Points).
+
+ reruns the bounding box of the set of points in Points. Points can
+ be any python object that can be turned into a numpy NX2 array of Floats.
+
+ If a single point is passed in, a zero-size Bounding Box is returned.
+
+ """
+ Points = N.asarray(Points, N.float).reshape(-1,2)
+
+ arr = N.vstack( (Points.min(0), Points.max(0)) )
+ return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)
+
+def fromBBArray(BBarray):
+ """
+ Builds a BBox object from an array of Bounding Boxes.
+ The resulting Bounding Box encompases all the included BBs.
+
+ The BBarray is in the shape: (Nx2x2) where BBarray[n] is a 2x2 array that represents a BBox
+ """
+
+ #upperleft = N.minimum.reduce(BBarray[:,0])
+ #lowerright = N.maximum.reduce(BBarray[:,1])
+
+# BBarray = N.asarray(BBarray, N.float).reshape(-1,2)
+# arr = N.vstack( (BBarray.min(0), BBarray.max(0)) )
+ BBarray = N.asarray(BBarray, N.float).reshape(-1,2,2)
+ arr = N.vstack( (BBarray[:,0,:].min(0), BBarray[:,1,:].max(0)) )
+ return asBBox(arr)
+ #return asBBox( (upperleft, lowerright) ) * 2
+
+def NullBBox():
+ """
+ Returns a BBox object with all NaN entries.
+
+ This represents a Null BB box;
+
+ BB merged with it will return BB.
+
+ Nothing is inside it.
+
+ """
+
+ arr = N.array(((N.nan, N.nan),(N.nan, N.nan)), N.float)
+ return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)
+
+def InfBBox():
+ """
+ Returns a BBox object with all -inf and inf entries
+
+ """
+
+ arr = N.array(((-N.inf, -N.inf),(N.inf, N.inf)), N.float)
+ return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)
+
+class RectBBox(BBox):
+ """
+ subclass of a BBox that can be used for a rotated Rectangle
+
+ contributed by MArco Oster (marco.oster@bioquant.uni-heidelberg.de)
+
+ """
+
+ def __new__(self, data, edges=None):
+ return BBox.__new__(self, data)
+
+ def __init__(self, data, edges=None):
+ ''' assume edgepoints are ordered such you can walk along all edges with left rotation sense
+ This may be:
+ left-top
+ left-bottom
+ right-bottom
+ right-top
+
+ or any rotation.
+ '''
+ BBox.BBox(data)
+ self.edges = np.asarray(edges)
+
+ print "new rectbbox created"
+
+
+ def ac_leftOf_ab(self, a, b, c):
+ ab = np.array(b) - np.array(a)
+ ac = np.array(c) - np.array(a)
+
+ return (ac[0]*ab[1] - ac[1]*ab[0]) <= 0
+
+ def PointInside(self, point):
+ print "point inside called"
+
+ for edge in xrange(4):
+ if self.ac_leftOf_ab(self.edges[edge],
+ self.edges[(edge+1)%4],
+ point):
+ continue
+ else:
+ return False
+ return True
+
+ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/BBoxTest.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/BBoxTest.py
new file mode 100644
index 0000000..6deb6b9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/BBoxTest.py
@@ -0,0 +1,563 @@
+#!/usr/bin/env python2
+
+
+"""
+Test code for the BBox Object
+
+"""
+
+import unittest
+
+from BBox import *
+
+class testCreator(unittest.TestCase):
+ def testCreates(self):
+ B = BBox(((0,0),(5,5)))
+ self.failUnless(isinstance(B, BBox))
+
+ def testType(self):
+ B = N.array(((0,0),(5,5)))
+ self.failIf(isinstance(B, BBox))
+
+ def testDataType(self):
+ B = BBox(((0,0),(5,5)))
+ self.failUnless(B.dtype == N.float)
+
+ def testShape(self):
+ B = BBox((0,0,5,5))
+ self.failUnless(B.shape == (2,2))
+
+ def testShape2(self):
+ self.failUnlessRaises(ValueError, BBox, (0,0,5) )
+
+ def testShape3(self):
+ self.failUnlessRaises(ValueError, BBox, (0,0,5,6,7) )
+
+ def testArrayConstruction(self):
+ A = N.array(((4,5),(10,12)), N.float_)
+ B = BBox(A)
+ self.failUnless(isinstance(B, BBox))
+
+ def testMinMax(self):
+ self.failUnlessRaises(ValueError, BBox, (0,0,-1,6) )
+
+ def testMinMax2(self):
+ self.failUnlessRaises(ValueError, BBox, (0,0,1,-6) )
+
+ def testMinMax(self):
+ # OK to have a zero-sized BB
+ B = BBox(((0,0),(0,5)))
+ self.failUnless(isinstance(B, BBox))
+
+ def testMinMax2(self):
+ # OK to have a zero-sized BB
+ B = BBox(((10.0,-34),(10.0,-34.0)))
+ self.failUnless(isinstance(B, BBox))
+
+ def testMinMax3(self):
+ # OK to have a tiny BB
+ B = BBox(((0,0),(1e-20,5)))
+ self.failUnless(isinstance(B, BBox))
+
+ def testMinMax4(self):
+ # Should catch tiny difference
+ self.failUnlessRaises(ValueError, BBox, ((0,0), (-1e-20,5)) )
+
+class testAsBBox(unittest.TestCase):
+
+ def testPassThrough(self):
+ B = BBox(((0,0),(5,5)))
+ C = asBBox(B)
+ self.failUnless(B is C)
+
+ def testPassThrough2(self):
+ B = (((0,0),(5,5)))
+ C = asBBox(B)
+ self.failIf(B is C)
+
+ def testPassArray(self):
+ # Different data type
+ A = N.array( (((0,0),(5,5))) )
+ C = asBBox(A)
+ self.failIf(A is C)
+
+ def testPassArray2(self):
+ # same data type -- should be a view
+ A = N.array( (((0,0),(5,5))), N.float_ )
+ C = asBBox(A)
+ A[0,0] = -10
+ self.failUnless(C[0,0] == A[0,0])
+
+class testIntersect(unittest.TestCase):
+
+ def testSame(self):
+ B = BBox(((-23.5, 456),(56, 532.0)))
+ C = BBox(((-23.5, 456),(56, 532.0)))
+ self.failUnless(B.Overlaps(C) )
+
+ def testUpperLeft(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (0, 12),(10, 32.0) ) )
+ self.failUnless(B.Overlaps(C) )
+
+ def testUpperRight(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (12, 12),(25, 32.0) ) )
+ self.failUnless(B.Overlaps(C) )
+
+ def testLowerRight(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (12, 5),(25, 15) ) )
+ self.failUnless(B.Overlaps(C) )
+
+ def testLowerLeft(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (-10, 5),(8.5, 15) ) )
+ self.failUnless(B.Overlaps(C) )
+
+ def testBelow(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (-10, 5),(8.5, 9.2) ) )
+ self.failIf(B.Overlaps(C) )
+
+ def testAbove(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (-10, 25.001),(8.5, 32) ) )
+ self.failIf(B.Overlaps(C) )
+
+ def testLeft(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (4, 8),(4.95, 32) ) )
+ self.failIf(B.Overlaps(C) )
+
+ def testRight(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (17.1, 8),(17.95, 32) ) )
+ self.failIf(B.Overlaps(C) )
+
+ def testInside(self):
+ B = BBox( ( (-15, -25),(-5, -10) ) )
+ C = BBox( ( (-12, -22), (-6, -8) ) )
+ self.failUnless(B.Overlaps(C) )
+
+ def testOutside(self):
+ B = BBox( ( (-15, -25),(-5, -10) ) )
+ C = BBox( ( (-17, -26), (3, 0) ) )
+ self.failUnless(B.Overlaps(C) )
+
+ def testTouch(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (15, 8),(17.95, 32) ) )
+ self.failUnless(B.Overlaps(C) )
+
+ def testCorner(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (15, 25),(17.95, 32) ) )
+ self.failUnless(B.Overlaps(C) )
+
+ def testZeroSize(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (15, 25),(15, 25) ) )
+ self.failUnless(B.Overlaps(C) )
+
+ def testZeroSize2(self):
+ B = BBox( ( (5, 10),(5, 10) ) )
+ C = BBox( ( (15, 25),(15, 25) ) )
+ self.failIf(B.Overlaps(C) )
+
+ def testZeroSize3(self):
+ B = BBox( ( (5, 10),(5, 10) ) )
+ C = BBox( ( (0, 8),(10, 12) ) )
+ self.failUnless(B.Overlaps(C) )
+
+ def testZeroSize4(self):
+ B = BBox( ( (5, 1),(10, 25) ) )
+ C = BBox( ( (8, 8),(8, 8) ) )
+ self.failUnless(B.Overlaps(C) )
+
+
+
+class testEquality(unittest.TestCase):
+ def testSame(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ C = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ self.failUnless(B == C)
+
+ def testIdentical(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ self.failUnless(B == B)
+
+ def testNotSame(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ C = BBox( ( (1.0, 2.0), (5.0, 10.1) ) )
+ self.failIf(B == C)
+
+ def testWithArray(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ C = N.array( ( (1.0, 2.0), (5.0, 10.0) ) )
+ self.failUnless(B == C)
+
+ def testWithArray2(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ C = N.array( ( (1.0, 2.0), (5.0, 10.0) ) )
+ self.failUnless(C == B)
+
+ def testWithArray2(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ C = N.array( ( (1.01, 2.0), (5.0, 10.0) ) )
+ self.failIf(C == B)
+
+class testInside(unittest.TestCase):
+ def testSame(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ C = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ self.failUnless(B.Inside(C))
+
+ def testPoint(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ C = BBox( ( (3.0, 4.0), (3.0, 4.0) ) )
+ self.failUnless(B.Inside(C))
+
+ def testPointOutside(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ C = BBox( ( (-3.0, 4.0), (0.10, 4.0) ) )
+ self.failIf(B.Inside(C))
+
+ def testUpperLeft(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (0, 12),(10, 32.0) ) )
+ self.failIf(B.Inside(C) )
+
+ def testUpperRight(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (12, 12),(25, 32.0) ) )
+ self.failIf(B.Inside(C) )
+
+ def testLowerRight(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (12, 5),(25, 15) ) )
+ self.failIf(B.Inside(C) )
+
+ def testLowerLeft(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (-10, 5),(8.5, 15) ) )
+ self.failIf(B.Inside(C) )
+
+ def testBelow(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (-10, 5),(8.5, 9.2) ) )
+ self.failIf(B.Inside(C) )
+
+ def testAbove(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (-10, 25.001),(8.5, 32) ) )
+ self.failIf(B.Inside(C) )
+
+ def testLeft(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (4, 8),(4.95, 32) ) )
+ self.failIf(B.Inside(C) )
+
+ def testRight(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ C = BBox( ( (17.1, 8),(17.95, 32) ) )
+ self.failIf(B.Inside(C) )
+
+class testPointInside(unittest.TestCase):
+ def testPointIn(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ P = (3.0, 4.0)
+ self.failUnless(B.PointInside(P))
+
+ def testUpperLeft(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ P = (4, 30)
+ self.failIf(B.PointInside(P))
+
+ def testUpperRight(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ P = (16, 30)
+ self.failIf(B.PointInside(P))
+
+ def testLowerRight(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ P = (16, 4)
+ self.failIf(B.PointInside(P))
+
+ def testLowerLeft(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ P = (-10, 5)
+ self.failIf(B.PointInside(P))
+
+ def testBelow(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ P = (10, 5)
+ self.failIf(B.PointInside(P))
+
+ def testAbove(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ P = ( 10, 25.001)
+ self.failIf(B.PointInside(P))
+
+ def testLeft(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ P = (4, 12)
+ self.failIf(B.PointInside(P))
+
+ def testRight(self):
+ B = BBox( ( (5, 10),(15, 25) ) )
+ P = (17.1, 12.3)
+ self.failIf(B.PointInside(P))
+
+ def testPointOnTopLine(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ P = (3.0, 10.0)
+ self.failUnless(B.PointInside(P))
+
+ def testPointLeftTopLine(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ P = (-3.0, 10.0)
+ self.failIf(B.PointInside(P))
+
+ def testPointOnBottomLine(self):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ P = (3.0, 5.0)
+ self.failUnless(B.PointInside(P))
+
+ def testPointOnLeft(self):
+ B = BBox( ( (-10.0, -10.0), (-1.0, -1.0) ) )
+ P = (-10, -5.0)
+ self.failUnless(B.PointInside(P))
+
+ def testPointOnRight(self):
+ B = BBox( ( (-10.0, -10.0), (-1.0, -1.0) ) )
+ P = (-1, -5.0)
+ self.failUnless(B.PointInside(P))
+
+ def testPointOnBottomRight(self):
+ B = BBox( ( (-10.0, -10.0), (-1.0, -1.0) ) )
+ P = (-1, -10.0)
+ self.failUnless(B.PointInside(P))
+
+class testFromPoints(unittest.TestCase):
+
+ def testCreate(self):
+ Pts = N.array( ((5,2),
+ (3,4),
+ (1,6),
+ ), N.float_ )
+ B = fromPoints(Pts)
+ #B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ self.failUnless(B[0,0] == 1.0 and
+ B[0,1] == 2.0 and
+ B[1,0] == 5.0 and
+ B[1,1] == 6.0
+ )
+ def testCreateInts(self):
+ Pts = N.array( ((5,2),
+ (3,4),
+ (1,6),
+ ) )
+ B = fromPoints(Pts)
+ self.failUnless(B[0,0] == 1.0 and
+ B[0,1] == 2.0 and
+ B[1,0] == 5.0 and
+ B[1,1] == 6.0
+ )
+
+ def testSinglePoint(self):
+ Pts = N.array( (5,2), N.float_ )
+ B = fromPoints(Pts)
+ self.failUnless(B[0,0] == 5.0 and
+ B[0,1] == 2.0 and
+ B[1,0] == 5.0 and
+ B[1,1] == 2.0
+ )
+
+ def testListTuples(self):
+ Pts = [ (3, 6.5),
+ (13, 43.2),
+ (-4.32, -4),
+ (65, -23),
+ (-0.0001, 23.432),
+ ]
+ B = fromPoints(Pts)
+ self.failUnless(B[0,0] == -4.32 and
+ B[0,1] == -23.0 and
+ B[1,0] == 65.0 and
+ B[1,1] == 43.2
+ )
+class testMerge(unittest.TestCase):
+ A = BBox( ((-23.5, 456), (56, 532.0)) )
+ B = BBox( ((-20.3, 460), (54, 465 )) )# B should be completely inside A
+ C = BBox( ((-23.5, 456), (58, 540.0)) )# up and to the right or A
+ D = BBox( ((-26.5, 12), (56, 532.0)) )
+
+ def testInside(self):
+ C = self.A.copy()
+ C.Merge(self.B)
+ self.failUnless(C == self.A)
+
+ def testFullOutside(self):
+ C = self.B.copy()
+ C.Merge(self.A)
+ self.failUnless(C == self.A)
+
+ def testUpRight(self):
+ A = self.A.copy()
+ A.Merge(self.C)
+ self.failUnless(A[0] == self.A[0] and A[1] == self.C[1])
+
+ def testDownLeft(self):
+ A = self.A.copy()
+ A.Merge(self.D)
+ self.failUnless(A[0] == self.D[0] and A[1] == self.A[1])
+
+class testWidthHeight(unittest.TestCase):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ def testWidth(self):
+ self.failUnless(self.B.Width == 4.0)
+
+ def testWidth(self):
+ self.failUnless(self.B.Height == 8.0)
+
+ def attemptSetWidth(self):
+ self.B.Width = 6
+
+ def attemptSetHeight(self):
+ self.B.Height = 6
+
+ def testSetW(self):
+ self.failUnlessRaises(AttributeError, self.attemptSetWidth)
+
+ def testSetH(self):
+ self.failUnlessRaises(AttributeError, self.attemptSetHeight)
+
+class testCenter(unittest.TestCase):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ def testCenter(self):
+ self.failUnless( (self.B.Center == (3.0, 6.0)).all() )
+
+ def attemptSetCenter(self):
+ self.B.Center = (6, 5)
+
+ def testSetCenter(self):
+ self.failUnlessRaises(AttributeError, self.attemptSetCenter)
+
+
+class testBBarray(unittest.TestCase):
+ BBarray = N.array( ( ((-23.5, 456), (56, 532.0)),
+ ((-20.3, 460), (54, 465 )),
+ ((-23.5, 456), (58, 540.0)),
+ ((-26.5, 12), (56, 532.0)),
+ ),
+ dtype=N.float)
+ BB = asBBox( ((-26.5, 12.), ( 58. , 540.)) )
+
+ def testJoin(self):
+ BB = fromBBArray(self.BBarray)
+ self.failUnless(BB == self.BB, "Wrong BB was created. It was:\n%s \nit should have been:\n%s"%(BB, self.BB))
+
+class testNullBBox(unittest.TestCase):
+ B1 = NullBBox()
+ B2 = NullBBox()
+ B3 = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+
+ def testValues(self):
+ self.failUnless( N.alltrue(N.isnan(self.B1)) )
+
+ def testIsNull(self):
+ self.failUnless( self.B1.IsNull )
+
+ def testEquals(self):
+ self.failUnless( (self.B1 == self.B2) == True )
+
+ def testNotEquals(self):
+ self.failUnless ( (self.B1 == self.B3) == False,
+ "NotEquals failed for\n%s,\n %s:%s"%(self.B1, self.B3, (self.B1 == self.B3)) )
+
+ def testNotEquals2(self):
+ self.failUnless ( (self.B3 == self.B1) == False,
+ "NotEquals failed for\n%s,\n %s:%s"%(self.B3, self.B1, (self.B3 == self.B1)) )
+
+ def testMerge(self):
+ C = self.B1.copy()
+ C.Merge(self.B3)
+ self.failUnless( C == self.B3,
+ "merge failed, got: %s"%C )
+
+ def testOverlaps(self):
+ self.failUnless( self.B1.Overlaps(self.B3) == False)
+
+ def testOverlaps2(self):
+ self.failUnless( self.B3.Overlaps(self.B1) == False)
+
+
+class testInfBBox(unittest.TestCase):
+ B1 = InfBBox()
+ B2 = InfBBox()
+ B3 = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+ NB = NullBBox()
+
+ def testValues(self):
+ self.failUnless( N.alltrue(N.isinf(self.B1)) )
+
+# def testIsNull(self):
+# self.failUnless( self.B1.IsNull )
+
+ def testEquals(self):
+ self.failUnless( (self.B1 == self.B2) == True )
+
+ def testNotEquals(self):
+ print (self.B1 == self.B3) == False
+ self.failUnless ( (self.B1 == self.B3) == False,
+ "NotEquals failed for\n%s,\n %s:%s"%(self.B1, self.B3, (self.B1 == self.B3)) )
+
+ def testNotEquals2(self):
+ self.failUnless ( (self.B3 == self.B1) == False,
+ "NotEquals failed for\n%s,\n %s:%s"%(self.B3, self.B1, (self.B3 == self.B1)) )
+
+ def testMerge(self):
+ C = self.B1.copy()
+ C.Merge(self.B3)
+ self.failUnless( C == self.B2,
+ "merge failed, got: %s"%C )
+
+ def testMerge2(self):
+ C = self.B3.copy()
+ C.Merge(self.B1)
+ self.failUnless( C == self.B1,
+ "merge failed, got: %s"%C )
+
+ def testOverlaps(self):
+ self.failUnless( self.B1.Overlaps(self.B2) == True)
+
+ def testOverlaps2(self):
+ self.failUnless( self.B3.Overlaps(self.B1) == True)
+
+ def testOverlaps3(self):
+ self.failUnless( self.B1.Overlaps(self.B3) == True)
+
+ def testOverlaps4(self):
+ self.failUnless( self.B1.Overlaps(self.NB) == True)
+
+ def testOverlaps5(self):
+ self.failUnless( self.NB.Overlaps(self.B1) == True)
+
+
+class testSides(unittest.TestCase):
+ B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
+
+ def testLeft(self):
+ self.failUnless( self.B.Left == 1.0 )
+ def testRight(self):
+ self.failUnless( self.B.Right == 5.0 )
+ def testBottom(self):
+ self.failUnless( self.B.Bottom == 2.0 )
+ def testTop(self):
+ self.failUnless( self.B.Top == 10.0 )
+
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/Colors.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/Colors.py
new file mode 100644
index 0000000..b6d4e9e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/Colors.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python2
+
+"""
+Colors.py
+
+Assorted stuff for Colors support. At the moment, only a few color sets.
+
+Many of these are from:
+http://geography.uoregon.edu/datagraphics/color_scales.htm
+
+They may have been modified some
+
+CategoricalColor1: A list of colors that are distict.
+BlueToRed11: 11 colors from blue to red
+
+
+"""
+
+## Categorical 12-step scheme, after ColorBrewer 11-step Paired Scheme
+## From: http://geography.uoregon.edu/datagraphics/color_scales.htm
+# CategoricalColor1 = [ (255, 191, 127),
+# (255, 127, 0),
+# (255, 255, 153),
+# (255, 255, 50),
+# (178, 255, 140),
+# ( 50, 255, 0),
+# (165, 237, 255),
+# (25, 178, 255),
+# (204, 191, 255),
+# (101, 76, 255),
+# (255, 153, 191),
+# (229, 25, 50),
+# ]
+
+CategoricalColor1 = [ (229, 25, 50),
+ (101, 76, 255),
+ ( 50, 255, 0),
+ (255, 127, 0),
+ (255, 255, 50),
+ (255, 153, 191),
+ (25, 178, 255),
+ (178, 255, 140),
+ (255, 191, 127),
+ (204, 191, 255),
+ (165, 237, 255),
+ (255, 255, 153),
+ ]
+
+RedToBlue11 = [ (165, 0, 33),
+ (216, 38, 50),
+ (247, 109, 94),
+ (255, 173, 114),
+ (255, 224, 153),
+ (255, 255, 191),
+ (224, 255, 255),
+ (170, 247, 255),
+ (114, 216, 255),
+ ( 63, 160, 255),
+ ( 38, 76, 255),
+ ]
+
+BlueToDarkRed12 = [( 41, 10, 216),
+ ( 38, 77, 255),
+ ( 63, 160, 255),
+ (114, 217, 255),
+ (170, 247, 255),
+ (224, 255, 255),
+ (255, 255, 191),
+ (255, 224, 153),
+ (255, 173, 114),
+ (247, 109, 94),
+ (216, 38, 50),
+ (165, 0, 33),
+ ]
+
+BlueToDarkRed10 = [( 41, 10, 216),
+ ( 38, 77, 255),
+ ( 63, 160, 255),
+ (114, 217, 255),
+ (170, 247, 255),
+ (255, 224, 153),
+ (255, 173, 114),
+ (247, 109, 94),
+ (216, 38, 50),
+ (165, 0, 33),
+ ]
+
+BlueToDarkRed8 = [( 41, 10, 216),
+ ( 38, 77, 255),
+ ( 63, 160, 255),
+ (114, 217, 255),
+ (255, 173, 114),
+ (247, 109, 94),
+ (216, 38, 50),
+ (165, 0, 33),
+ ]
+
+
+
+if __name__ == "__main__":
+ import wx
+ # tiny test app
+ AllSchemes = [("CategoricalColor1", CategoricalColor1),
+ ("RedToBlue11", RedToBlue11),
+ ("BlueToDarkRed12", BlueToDarkRed12),
+ ("BlueToDarkRed10", BlueToDarkRed10),
+ ("BlueToDarkRed8", BlueToDarkRed8)
+ ]
+ class TestFrame(wx.Frame):
+ def __init__(self, *args, **kwargs):
+ wx.Frame.__init__(self, *args, **kwargs)
+ Hsizer = wx.BoxSizer(wx.HORIZONTAL)
+ for scheme in AllSchemes:
+ Sizer = wx.BoxSizer(wx.VERTICAL)
+ Sizer.Add(wx.StaticText(self, label=scheme[0]), 0, wx.ALL, 5)
+ for c in scheme[1]:
+ w = wx.Window(self, size=(100, 20))
+ w.SetBackgroundColour(wx.Colour(*c))
+ Sizer.Add(w, 0, wx.ALL, 5)
+ Hsizer.Add(Sizer, 0, wx.ALL, 5)
+ self.SetSizerAndFit(Hsizer)
+ self.Show()
+
+ A = wx.App(False)
+ F = TestFrame(None)
+ A.MainLoop()
+ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/GUI.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/GUI.py
new file mode 100644
index 0000000..28ca6c7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/GUI.py
@@ -0,0 +1,88 @@
+"""
+
+Part of the floatcanvas.Utilities package.
+
+This module contains assorted GUI-related utilities that can be used
+with FloatCanvas
+
+So far, they are:
+
+RubberBandBox: used to draw a RubberBand Box on the screen
+
+"""
+
+import numpy as np
+
+import wx
+from wx.lib.floatcanvas import FloatCanvas, GUIMode
+
+class RubberBandBox(GUIMode.GUIBase):
+ """
+ Class to provide a GUI Mode that makes a rubber band box that can be drawn on a Window
+
+ """
+
+ def __init__(self, CallBack, Tol=5):
+
+ """
+ To initialize:
+
+ RubberBandBox(CallBack, Tol=5)
+
+ CallBack: is the method you want called when the mouse is
+ released. That method will be called, passing in a rect
+ parameter, where rect is: (Point, WH) of the rect in
+ world coords.
+
+ Tol: The tolerance for the smallest rectangle allowed. defaults
+ to 5. In pixels
+
+
+ Attributes:
+
+ CallBack: The callback function.
+
+ """
+
+ self.Canvas = None # this will be set when the mode is set on a Canvas
+ self.CallBack = CallBack
+ self.Tol = Tol
+
+ self.Drawing = False
+ self.RBRect = None
+ self.StartPointWorld = None
+
+ return None
+
+ def OnMove(self, event):
+ if self.Drawing:
+ x, y = self.StartPoint
+ Cornerx, Cornery = event.GetPosition()
+ w, h = ( Cornerx - x, Cornery - y)
+ if abs(w) > self.Tol and abs(h) > self.Tol:
+ # draw the RB box
+ dc = wx.ClientDC(self.Canvas)
+ dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetLogicalFunction(wx.XOR)
+ if self.RBRect:
+ dc.DrawRectanglePointSize(*self.RBRect)
+ self.RBRect = ((x, y), (w, h) )
+ dc.DrawRectanglePointSize(*self.RBRect)
+ self.Canvas._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
+
+ def OnLeftDown(self, event):
+ # Start drawing
+ self.Drawing = True
+ self.StartPoint = event.GetPosition()
+
+ def OnLeftUp(self, event):
+ # Stop Drawing
+ if self.Drawing:
+ self.Drawing = False
+ if self.RBRect:
+ world_rect = (self.Canvas.PixelToWorld(self.RBRect[0]),
+ self.Canvas.ScalePixelToWorld(self.RBRect[1])
+ )
+ wx.CallAfter(self.CallBack, world_rect)
+ self.RBRect = None
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/__init__.py
new file mode 100644
index 0000000..b3162b3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/Utilities/__init__.py
@@ -0,0 +1,7 @@
+"""
+__init__ for the floatcanvas Utilities package
+
+"""
+pass
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/__init__.py
new file mode 100644
index 0000000..ee2d191
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/floatcanvas/__init__.py
@@ -0,0 +1,98 @@
+"""
+This is the floatcanvas package. It provides two primary modules, and a
+support module.
+
+FloatCanvas.py contains the main FloatCanvas class, and its supporting
+classes. NavCanvas.py contains a wrapper for the FloatCanvas that
+provides the canvas and a toolbar with tools that allow you to navigate
+the canvas (zooming, panning, etc.) Resources.py is a module that
+contains a few resources required by the FloatCanvas (icons, etc)
+
+The FloatCanvas is a high level window for drawing maps and anything
+else in an arbitrary coordinate system.
+
+The goal is to provide a convenient way to draw stuff on the screen
+without having to deal with handling OnPaint events, converting to pixel
+coordinates, knowing about wxWindows brushes, pens, and colors, etc. It
+also provides virtually unlimited zooming and scrolling
+
+I am using it for two things:
+1) general purpose drawing in floating point coordinates
+2) displaying map data in Lat-long coordinates
+
+If the projection is set to None, it will draw in general purpose
+floating point coordinates. If the projection is set to 'FlatEarth', it
+will draw a FlatEarth projection, centered on the part of the map that
+you are viewing. You can also pass in your own projection function.
+
+It is double buffered, so re-draws after the window is uncovered by
+something else are very quick.
+
+It relies on NumPy, which is needed for speed (maybe, I haven't profiled
+properly) and convenience.
+
+Bugs and Limitations: Lots: patches, fixes welcome
+
+For Map drawing: It ignores the fact that the world is, in fact, a
+sphere, so it will do strange things if you are looking at stuff near
+the poles or the date line. so far I don't have a need to do that, so I
+havn't bothered to add any checks for that yet.
+
+Zooming: I have set no zoom limits. What this means is that if you zoom
+in really far, you can get integer overflows, and get weird results. It
+doesn't seem to actually cause any problems other than weird output, at
+least when I have run it.
+
+Speed: I have done a couple of things to improve speed in this app. The
+one thing I have done is used NumPy Arrays to store the coordinates of
+the points of the objects. This allowed me to use array oriented
+functions when doing transformations, and should provide some speed
+improvement for objects with a lot of points (big polygons, polylines,
+pointsets).
+
+The real slowdown comes when you have to draw a lot of objects, because
+you have to call the wx.DC.DrawSomething call each time. This is plenty
+fast for tens of objects, OK for hundreds of objects, but pretty darn
+slow for thousands of objects.
+
+If you are zoomed in, it checks the Bounding box of an object before
+drawing it. This makes it a great deal faster when there are a lot of
+objects and you are zoomed in so that only a few are shown.
+
+Mouse Events:
+
+There are a full set of custom mouse events. They are just like the
+regular mouse events, but include an extra attribute: Event.GetCoords(),
+that returns the (x,y) position in world coordinates, as a length-2
+NumPy vector of Floats.
+
+There are also a full set of bindings to mouse events on objects, so
+that you can specify a given function be called when an object is
+clicked, mouse-over'd, etc.
+
+See the Demo for what it can do, and how to use it.
+
+Copyright: Christopher Barker
+License: Same as the version of wxPython you are using it with.
+
+TRAC site for some docs and updates:
+http://trac.paulmcnett.com/floatcanvas
+
+Mailing List:
+http://mail.paulmcnett.com/cgi-bin/mailman/listinfo/floatcanvas
+
+The latest code is in the main wx SVN:
+
+http://svn.wxwidgets.org/viewvc/wx/wxPython/3rdParty/FloatCanvas/
+
+Check for updates or answers to questions, send me an email.
+Please let me know if you're using this!!!
+Contact me at:
+
+Chris.Barker@noaa.gov
+
+"""
+
+__version__ = "0.9.18"
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/foldmenu.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/foldmenu.py
new file mode 100644
index 0000000..1c1bc1f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/foldmenu.py
@@ -0,0 +1,89 @@
+# 12/07/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 Compatability changes
+#
+
+import wx
+from wx.lib.evtmgr import eventManager
+
+class FoldOutWindow(wx.PopupWindow):
+ def __init__(self,parent,style=0):
+ wx.PopupWindow.__init__(self,parent,style)
+ self.SetAutoLayout(True)
+ self.sizer=wx.BoxSizer(wx.HORIZONTAL)
+ self.SetSizer(self.sizer, deleteOld=False)
+ self.handlers={}
+ self.InitColors()
+ self.inWindow=False
+ self.Bind(wx.EVT_ENTER_WINDOW, self.evEnter)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.evLeave)
+
+ def InitColors(self):
+ faceClr = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
+ self.SetBackgroundColour(faceClr)
+
+ def AddButton(self,bitmap,handler=None):
+ id=wx.NewId()
+ btn=wx.BitmapButton(self,id,bitmap)
+ self.sizer.Add(btn, 1, wx.ALIGN_CENTER|wx.ALL|wx.EXPAND, 2)
+ self.Bind(wx.EVT_BUTTON, self.OnBtnClick, btn)
+ self.sizer.Fit(self)
+ self.Layout()
+
+ if handler:
+ self.handlers[id]=handler
+
+ return id
+
+ def Popup(self):
+ if not self.IsShown():
+ self.Show()
+
+ def OnBtnClick(self,event):
+ id=event.GetEventObject().GetId()
+
+ if self.handlers.has_key(id):
+ self.handlers[id](event)
+
+ self.Hide()
+ self.inWindow=False
+ event.Skip()
+
+ def evEnter(self,event):
+ self.inWindow=True
+ self.rect=self.GetRect()
+ event.Skip()
+
+ def evLeave(self,event):
+ if self.inWindow:
+ if not self.rect.Inside(self.ClientToScreen(event.GetPosition())):
+ self.Hide()
+
+ event.Skip()
+
+
+
+
+
+class FoldOutMenu(wx.BitmapButton):
+ def __init__(self,parent,id,bitmap,pos = wx.DefaultPosition,
+ size = wx.DefaultSize, style = wx.BU_AUTODRAW,
+ validator = wx.DefaultValidator, name = "button"):
+
+ wx.BitmapButton.__init__(self, parent, id, bitmap, pos, size, style,
+ validator, name)
+
+ self.parent=parent
+ self.parent.Bind(wx.EVT_BUTTON, self.click, self)
+ self.popwin=FoldOutWindow(self.parent)
+
+ def AddButton(self,bitmap,handler=None):
+ return self.popwin.AddButton(bitmap,handler=handler)
+
+ def click(self,event):
+ pos=self.GetPosition()
+ sz=self.GetSize()
+ pos.x=pos.x+sz.width
+ pos.y=pos.y+sz.height/2
+ self.popwin.Position(pos,sz)
+ self.popwin.Popup()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/foldpanelbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/foldpanelbar.py
new file mode 100644
index 0000000..20d4416
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/foldpanelbar.py
@@ -0,0 +1,13 @@
+# ============================================================== #
+# This is now just a stub, importing the real module which lives #
+# under wx.lib.agw.
+# ============================================================== #
+
+"""
+Attention! FoldPanelBar now lives in wx.lib.agw, together with
+its friends in the Advanced Generic Widgets family.
+
+Please update your code!
+"""
+
+from wx.lib.agw.foldpanelbar import * \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/gestures.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/gestures.py
new file mode 100644
index 0000000..6d7278b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/gestures.py
@@ -0,0 +1,310 @@
+#Mouse Gestures
+
+#Version 0.0.1
+
+#By Daniel Pozmanter
+#drpython@bluebottle.com
+
+#Released under the terms of the wxWindows License.
+
+"""
+This is a class to add Mouse Gestures to a program.
+It can be used in two ways:
+
+1. Automatic:
+ Automatically runs mouse gestures.
+ You need to set the gestures, and their associated actions,
+ as well as the Mouse Button/Modifiers to use.
+
+2. Manual:
+ Same as above, but you do not need to set the mouse button/modifiers.
+ You can launch this from events as you wish.
+
+An example is provided in the demo.
+The parent window is where the mouse events will be recorded.
+(So if you want to record them in a pop up window, use manual mode,
+and set the pop up as the parent).
+
+Start() starts recording mouse movement.
+End() stops the recording, compiles all the gestures into a list,
+and looks through the registered gestures to find a match.
+The first matchs associated action is then run.
+
+The marginoferror is how much to forgive when calculating movement:
+If the margin is 25, then movement less than 25 pixels will not be detected.
+
+Recognized: L, R, U, D, 1, 3, 7, 9
+
+Styles: Manual (Automatic By Default), DisplayNumbersForDiagonals (Off By Default).
+Not Yet Implemented
+
+The criteria for a direction is as follows:
+x in a row. (Where x is the WobbleTolerance).
+So if the WobbleTolerance is 9
+'URUUUUUUUUUUUUUUURUURUUUU1' is Up.
+
+The higher this number, the less sensitive this class is.
+So the more likely something like 1L will translate to 1.
+
+This is good, since the mouse does tend to wobble somewhat,
+and a higher number allows for this.
+
+To change this, use SetWobbleTolerance
+
+Also, to help with recognition of a diagonal versus
+a vey messy straight line, if the greater absolute value
+is not greater than twice the lesser, only the grater value
+is counted.
+
+In automatic mode, EVT_MOUSE_EVENTS is used.
+This allows the user to change the mouse button/modifiers at runtime.
+"""
+
+###########################################
+
+'''
+Changelog:
+0.0.1: Treats a mouse leaving event as mouse up.
+ (Bug Report, Thanks Peter Damoc).
+
+
+0.0.0: Initial Release.
+'''
+
+###########################################
+#ToDo:
+
+#Fully Implement Manual Mode
+
+#Add "Ends With": AddGestureEndsWith(self, gesture, action, args)
+#Add "Starts With": AddGestuteStartsWith(self, gesture, action, args)
+
+#For better control of when the gesture starts and stops,
+#use manual mode.
+#At the moment, you need to Bind the OnMouseMotion event if you want to use
+#manual mode.
+
+import wx
+
+class MouseGestures:
+ def __init__(self, parent, Auto=True, MouseButton=wx.MOUSE_BTN_MIDDLE):
+ self.parent = parent
+
+ self.gestures = []
+ self.actions = []
+ self.actionarguments = []
+
+ self.mousebutton = MouseButton
+ self.modifiers = []
+
+ self.recording = False
+
+ self.lastposition = (-1, -1)
+
+ self.pen = wx.Pen(wx.Colour(0, 144, 255), 5)
+
+ self.dc = wx.ScreenDC()
+ self.dc.SetPen(self.pen)
+
+ self.showgesture = False
+
+ self.wobbletolerance = 7
+
+ self.rawgesture = ''
+
+ self.SetAuto(Auto)
+
+ def _check_modifiers(self, event):
+ '''Internal: Returns True if all needed modifiers are down
+ for the given event.'''
+ if len(self.modifiers) > 0:
+ good = True
+ if wx.WXK_CONTROL in self.modifiers:
+ good = good and event.ControlDown()
+ if wx.WXK_SHIFT in self.modifiers:
+ good = good and event.ShiftDown()
+ if wx.WXK_ALT in self.modifiers:
+ good = good and event.AltDown()
+ return good
+ return True
+
+ def AddGesture(self, gesture, action, *args):
+ '''Registers a gesture, and an associated function, with any arguments needed.'''
+ #Make Sure not a duplicate:
+ self.RemoveGesture(gesture)
+
+ self.gestures.append(gesture)
+ self.actions.append(action)
+ self.actionarguments.append(args)
+
+ def DoAction(self, gesture):
+ '''If the gesture is in the array of registered gestures, run the associated function.'''
+ if gesture in self.gestures:
+ i = self.gestures.index(gesture)
+ apply(self.actions[i], self.actionarguments[i])
+
+ def End(self):
+ '''Stops recording the points to create the mouse gesture from,
+ and creates the mouse gesture, returns the result as a string.'''
+ self.recording = False
+
+ #Figure out the gestures (Look for occurances of 5 in a row or more):
+
+ tempstring = '0'
+ possiblechange = '0'
+
+ directions = ''
+
+ for g in self.rawgesture:
+ l = len(tempstring)
+ if g != tempstring[l - 1]:
+ if g == possiblechange:
+ tempstring = g + g
+ else:
+ possiblechange = g
+ else:
+ tempstring += g
+ if len(tempstring) >= self.wobbletolerance:
+ ld = len(directions)
+ if ld > 0:
+ if directions[ld - 1] != g:
+ directions += g
+ else:
+ directions += g
+ tempstring = '0'
+
+ if self.showgesture:
+ self.parent.Refresh()
+
+ return directions
+
+ def GetDirection(self, point1, point2):
+ '''Gets the direction between two points.'''
+ #point1 is the old point
+ #point2 is current
+
+ x1, y1 = point1
+ x2, y2 = point2
+
+ #(Negative = Left, Up)
+ #(Positive = Right, Down)
+
+ horizontal = x2 - x1
+ vertical = y2 - y1
+
+ horizontalchange = abs(horizontal) > 0
+ verticalchange = abs(vertical) > 0
+
+ if horizontalchange and verticalchange:
+ ah = abs(horizontal)
+ av = abs(vertical)
+ if ah > av:
+ if (ah / av) > 2:
+ vertical = 0
+ verticalchange = False
+ elif av > ah:
+ if (av / ah) > 2:
+ horizontal = 0
+ horizontalchange = False
+
+ if horizontalchange and verticalchange:
+ #Diagonal
+ if (horizontal > 0) and (vertical > 0):
+ return '3'
+ elif (horizontal > 0) and (vertical < 0):
+ return '9'
+ elif (horizontal < 0) and (vertical > 0):
+ return '1'
+ else:
+ return '7'
+ else:
+ #Straight Line
+ if horizontalchange:
+ if horizontal > 0:
+ return 'R'
+ else:
+ return 'L'
+ else:
+ if vertical > 0:
+ return 'D'
+ else:
+ return 'U'
+
+ def GetRecording(self):
+ '''Returns whether or not Gesture Recording has started.'''
+ return self.recording
+
+ def OnMotion(self, event):
+ '''Internal. Used if Start() has been run'''
+ if self.recording:
+ currentposition = event.GetPosition()
+ if self.lastposition != (-1, -1):
+ self.rawgesture += self.GetDirection(self.lastposition, currentposition)
+ if self.showgesture:
+ #Draw it!
+ px1, py1 = self.parent.ClientToScreen(self.lastposition)
+ px2, py2 = self.parent.ClientToScreen(currentposition)
+ self.dc.DrawLine(px1, py1, px2, py2)
+
+ self.lastposition = currentposition
+
+ event.Skip()
+
+ def OnMouseEvent(self, event):
+ '''Internal. Used in Auto Mode.'''
+ if event.ButtonDown(self.mousebutton) and self._check_modifiers(event):
+ self.Start()
+ elif (event.ButtonUp(self.mousebutton) or event.Leaving()) and self.GetRecording():
+ result = self.End()
+ self.DoAction(result)
+ event.Skip()
+
+ def RemoveGesture(self, gesture):
+ '''Removes a gesture, and its associated action'''
+ if gesture in self.gestures:
+ i = self.gestures.index(gesture)
+
+ del self.gestures[i]
+ del self.actions[i]
+ del self.actionarguments[i]
+
+ def SetAuto(self, auto):
+ '''Warning: Once auto is set, it stays set, unless you manually use UnBind'''
+ if auto:
+ self.parent.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
+ self.parent.Bind(wx.EVT_MOTION, self.OnMotion)
+
+ def SetGesturePen(self, pen):
+ '''Sets the wx pen used to visually represent each gesture'''
+ self.pen = pen
+ self.dc.SetPen(self.pen)
+
+ def SetGesturePen(self, colour, width):
+ '''Sets the colour and width of the line drawn to visually represent each gesture'''
+ self.pen = wx.Pen(colour, width)
+ self.dc.SetPen(self.pen)
+
+ def SetGesturesVisible(self, vis):
+ '''Sets whether a line is drawn to visually represent each gesture'''
+ self.showgesture = vis
+
+ def SetModifiers(self, modifiers=[]):
+ '''Takes an array of wx Key constants (Control, Shift, and/or Alt).
+ Leave empty to unset all modifiers.'''
+ self.modifiers = modifiers
+
+ def SetMouseButton(self, mousebutton):
+ '''Takes the wx constant for the target mousebutton'''
+ self.mousebutton = mousebutton
+
+ def SetWobbleTolerance(self, wobbletolerance):
+ '''Sets just how much wobble this class can take!'''
+ self.WobbleTolerance = wobbletolerance
+
+ def Start(self):
+ '''Starts recording the points to create the mouse gesture from'''
+ self.recording = True
+ self.rawgesture = ''
+ self.lastposition = (-1, -1)
+ if self.showgesture:
+ self.parent.Refresh()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/graphics.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/graphics.py
new file mode 100644
index 0000000..aef35b5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/graphics.py
@@ -0,0 +1,1706 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.graphics
+# Purpose: A wx.GraphicsContext-like API implemented using wx.lib.wxcairo
+#
+# Author: Robin Dunn
+#
+# Created: 15-Sept-2008
+# RCS-ID: $Id$
+# Copyright: (c) 2008 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""
+This module implements an API similar to wx.GraphicsContext and the
+related classes. In this case the implementation for all platforms is
+done using Cairo, via the wx.lib.wxcairo glue module.
+
+Why do this? Why not just use wx.GraphicsContext everywhere? Using
+Cairo on every platform enables us to more easily be totally
+consistent on all platforms. Implementing it in Python means that it
+is easy to fill in the gaps in functionality with features of Cairo
+that GraphicsContext may not provide, like converting text to a path,
+using compositing operators, or being able to provide an
+implementation for things like context.Clear().
+
+Why not just use Cairo directly? There may be times when you do want
+to use wx.GrpahicsContext, so being able to share code between that
+and this implementation is nice. Also, I like the class hierarchy and
+API exposed by the wx.GraphicsContext classes a little better than
+Cairo's.
+"""
+
+import cairo
+import math
+
+import wx
+import wx.lib.wxcairo
+
+
+
+# Other ideas:
+# 1. TextToPath (or maybe make this part of the Path class
+# 3. Relative moves, lines, curves, etc.
+# 5. maybe expose cairo_paint, cairo_paint_with_alpha, cairo_mask?
+
+#---------------------------------------------------------------------------
+# Image surface formats
+
+FORMAT_ARGB32 = cairo.FORMAT_ARGB32
+FORMAT_RGB24 = cairo.FORMAT_RGB24
+FORMAT_A8 = cairo.FORMAT_A8
+FORMAT_A1 = cairo.FORMAT_A1
+
+
+#---------------------------------------------------------------------------
+# Compositing operators. See http://cairographics.org/operators
+
+# clear destination layer (bounded)
+OPERATOR_CLEAR = cairo.OPERATOR_CLEAR
+
+# replace destination layer (bounded)
+OPERATOR_SOURCE = cairo.OPERATOR_SOURCE
+
+# draw source layer on top of destination layer (bounded)
+OPERATOR_OVER = cairo.OPERATOR_OVER
+
+# draw source where there was destination content (unbounded)
+OPERATOR_IN = cairo.OPERATOR_IN
+
+# draw source where there was no destination content (unbounded)
+OPERATOR_OUT = cairo.OPERATOR_OUT
+
+# draw source on top of destination content and only there
+OPERATOR_ATOP = cairo.OPERATOR_ATOP
+
+# ignore the source
+OPERATOR_DEST = cairo.OPERATOR_DEST
+
+# draw destination on top of source
+OPERATOR_DEST_OVER = cairo.OPERATOR_DEST_OVER
+
+# leave destination only where there was source content (unbounded)
+OPERATOR_DEST_IN = cairo.OPERATOR_DEST_IN
+
+# leave destination only where there was no source content
+OPERATOR_DEST_OUT = cairo.OPERATOR_DEST_OUT
+
+# leave destination on top of source content and only there (unbounded)
+OPERATOR_DEST_ATOP = cairo.OPERATOR_DEST_ATOP
+
+# source and destination are shown where there is only one of them
+OPERATOR_XOR = cairo.OPERATOR_XOR
+
+# source and destination layers are accumulated
+OPERATOR_ADD = cairo.OPERATOR_ADD
+
+# like over, but assuming source and dest are disjoint geometries
+OPERATOR_SATURATE = cairo.OPERATOR_SATURATE
+
+
+
+#---------------------------------------------------------------------------
+# Anti-alias modes. Note that according to the Cairo docs none of the
+# current backends support the the SUBPIXEL mode.
+
+# Use the default antialiasing for the subsystem and target device
+ANTIALIAS_DEFAULT = cairo.ANTIALIAS_DEFAULT
+
+# Use a bilevel alpha mask
+ANTIALIAS_NONE = cairo.ANTIALIAS_NONE
+
+# Perform single-color antialiasing (using shades of gray for black
+# text on a white background, for example).
+ANTIALIAS_GRAY = cairo.ANTIALIAS_GRAY
+
+# Perform antialiasing by taking advantage of the order of subpixel
+# elements on devices such as LCD panels
+ANTIALIAS_SUBPIXEL = cairo.ANTIALIAS_SUBPIXEL
+
+
+
+#---------------------------------------------------------------------------
+# A decorator that makes creating properties a little cleaner and simpler
+
+def Property( function ):
+ return property( **function() )
+
+#---------------------------------------------------------------------------
+
+NullGraphicsPen = None
+NullGraphicsBrush = None
+NullGraphicsFont = None
+NullGraphicsMatrix = None
+NullGraphicsPath = None
+
+
+class GraphicsObject(object):
+ # This probably isn't needed at all anymore since we'll just use
+ # None insead of the Null objects, but we'll keep it anyway in
+ # case it's needed to help write compatible code.
+ def IsNull(self):
+ return False
+
+
+#---------------------------------------------------------------------------
+
+class GraphicsPen(GraphicsObject):
+ """
+ A Pen is used to define the properties of how a stroke is drawn.
+ """
+ _capMap = { wx.CAP_BUTT : cairo.LINE_CAP_BUTT,
+ wx.CAP_ROUND : cairo.LINE_CAP_ROUND,
+ wx.CAP_PROJECTING : cairo.LINE_CAP_SQUARE }
+
+ _joinMap = { wx.JOIN_BEVEL : cairo.LINE_JOIN_BEVEL,
+ wx.JOIN_MITER : cairo.LINE_JOIN_MITER,
+ wx.JOIN_ROUND : cairo.LINE_JOIN_ROUND }
+
+
+ def __init__(self, colour=wx.BLACK, width=1, style=wx.SOLID):
+ GraphicsObject.__init__(self)
+ self._colour = _makeColour(colour)
+ self._width = width
+ self._style = style
+ self._cap = wx.CAP_ROUND
+ self._dashes = []
+ self._join = wx.JOIN_ROUND
+ self._stipple = None
+ self._pattern = None
+
+
+ @staticmethod
+ def CreateFromPen(pen):
+ """Convert a wx.Pen to a GraphicsPen"""
+ assert isinstance(pen, wx.Pen)
+ p = GraphicsPen(pen.Colour, pen.Width, pen.Style)
+ p._cap = pen.Cap
+ p._dashes = pen.Dashes
+ p._join = pen.Join
+ return p
+
+
+ @staticmethod
+ def CreateFromPattern(pattern, width=1):
+ """
+ Create a Pen directly from a Cairo Pattern object. This is
+ similar to using a stipple bitmap, but saves a step, and
+ patterns can include gradients, etc.
+ """
+ p = GraphicsPen(wx.BLACK, width, wx.STIPPLE)
+ p._pattern = pattern
+ return p
+
+
+ @Property
+ def Colour():
+ def fget(self):
+ return self._colour
+ def fset(self, value):
+ self._colour = value
+ return locals()
+
+ @Property
+ def Width():
+ def fget(self):
+ return self._width
+ def fset(self, value):
+ self._width = value
+ return locals()
+
+ @Property
+ def Style():
+ def fget(self):
+ return self._style
+ def fset(self, value):
+ self._style = value
+ return locals()
+
+ @Property
+ def Cap():
+ def fget(self):
+ return self._cap
+ def fset(self, value):
+ self._cap = value
+ return locals()
+
+ @Property
+ def Dashes():
+ def fget(self):
+ return self._dashes
+ def fset(self, value):
+ self._dashes = value
+ return locals()
+
+ @Property
+ def Join():
+ def fget(self):
+ return self._join
+ def fset(self, value):
+ self._join = value
+ return locals()
+
+ @Property
+ def Stipple():
+ def fget(self):
+ return self._stipple
+ def fset(self, value):
+ self._stipple = value
+ self._pattern = None
+ return locals()
+
+ @Property
+ def Pattern():
+ def fget(self):
+ return self._pattern
+ def fset(self, value):
+ self._pattern = value
+ return locals()
+
+
+
+ def Apply(self, ctx):
+ # set up the context with this pen's parameters
+ ctx = ctx.GetNativeContext()
+ ctx.set_line_width(self._width)
+ ctx.set_line_cap(self._capMap[self._cap])
+ ctx.set_line_join(self._joinMap[self._join])
+ ctx.set_dash([])
+
+ if self._style == wx.SOLID:
+ ctx.set_source_rgba( *_colourToValues(self._colour) )
+
+ elif self._style == wx.STIPPLE:
+ if not self._pattern and self._stipple:
+ # make a pattern from the stipple bitmap
+ img = wx.lib.wxcairo.ImageSurfaceFromBitmap(self._stipple)
+ self._pattern = cairo.SurfacePattern(img)
+ self._pattern.set_extend(cairo.EXTEND_REPEAT)
+ ctx.set_source(self._pattern)
+
+ elif self._style == wx.USER_DASH:
+ ctx.set_source_rgba( *_colourToValues(self._colour) )
+ ctx.set_dash(self._dashes)
+
+ elif self._style in [wx.DOT, wx.DOT_DASH, wx.LONG_DASH, wx.SHORT_DASH]:
+ ctx.set_source_rgba( *_colourToValues(self._colour) )
+ ctx.set_dash( _stdDashes(self._style, self._width) )
+
+ elif self._style in [wx.BDIAGONAL_HATCH, wx.CROSSDIAG_HATCH, wx.FDIAGONAL_HATCH,
+ wx.CROSS_HATCH, wx.HORIZONTAL_HATCH, wx.VERTICAL_HATCH]:
+ pass # TODO make a stock pattern...
+
+
+#---------------------------------------------------------------------------
+
+class GraphicsBrush(GraphicsObject):
+ """
+ A Brush is used to define how fills are painted. They can have
+ either a solid fill (colors with or without alpha), a stipple
+ created from a wx.Bitmap, or a cairo Pattern object.
+ """
+
+ def __init__(self, colour=wx.BLACK, style=wx.SOLID):
+ self._colour = _makeColour(colour)
+ self._style = style
+ self._stipple = None
+ self._pattern = None
+
+
+ @staticmethod
+ def CreateFromBrush(brush):
+ """Converts a wx.Brush to a GraphicsBrush"""
+ assert isinstance(brush, wx.Brush)
+ b = GraphicsBrush(brush.Colour, brush.Style)
+ if brush.Style == wx.STIPPLE:
+ b._stipple = brush.Stipple
+ else:
+ b._stipple = None
+ return b
+
+
+ @staticmethod
+ def CreateFromPattern(pattern):
+ """
+ Create a Brush directly from a Cairo Pattern object. This is
+ similar to using a stipple bitmap, but saves a step, and
+ patterns can include gradients, etc.
+ """
+ b = GraphicsBrush(style=wx.STIPPLE)
+ b._pattern = pattern
+ return b
+
+
+ @Property
+ def Colour():
+ def fget(self):
+ return self._colour
+ def fset(self, value):
+ self._colour = value
+ return locals()
+
+ @Property
+ def Style():
+ def fget(self):
+ return self._style
+ def fset(self, value):
+ self._style = value
+ return locals()
+
+ @Property
+ def Stipple():
+ def fget(self):
+ return self._stipple
+ def fset(self, value):
+ self._stipple = value
+ self._pattern = None
+ return locals()
+
+
+ @Property
+ def Pattern():
+ def fget(self):
+ return self._pattern
+ def fset(self, value):
+ self._pattern = value
+ return locals()
+
+
+ def Apply(self, ctx):
+ ctx = ctx.GetNativeContext()
+
+ if self._style == wx.SOLID:
+ ctx.set_source_rgba( *_colourToValues(self._colour) )
+
+ elif self._style == wx.STIPPLE:
+ if not self._pattern and self._stipple:
+ # make a pattern from the stipple bitmap
+ img = wx.lib.wxcairo.ImageSurfaceFromBitmap(self._stipple)
+ self._pattern = cairo.SurfacePattern(img)
+ self._pattern.set_extend(cairo.EXTEND_REPEAT)
+ ctx.set_source(self._pattern)
+
+#---------------------------------------------------------------------------
+
+class GraphicsFont(GraphicsObject):
+ """
+ """
+ def __init__(self):
+ # TODO: Should we be able to create a GrpahicsFont from other
+ # properties, or will it always be via a wx.Font? What about
+ # creating from a cairo.FontFace or cairo.ScaledFont?
+ self._font = None
+ self._colour = None
+ self._pointSize = None
+ self._fontface = None
+ # To remain consistent with the GC API a color is associated
+ # with the font, and nothing else. Since this is Cairo and
+ # it's easy to do, we'll also allow a brush to be used...
+ self._brush = None
+
+
+ def IsNull(self):
+ return self._font is None
+
+
+ @staticmethod
+ def CreateFromFont(font, colour=None):
+ f = GraphicsFont()
+ f._font = font
+ f._colour = _makeColour(colour)
+ f._pointSize = font.GetPointSize()
+ f._fontface = wx.lib.wxcairo.FontFaceFromFont(font)
+ return f
+
+
+ @Property
+ def Colour():
+ def fget(self):
+ return self._colour
+ def fset(self, value):
+ self._colour = value
+ return locals()
+
+ @Property
+ def PointSize():
+ def fget(self):
+ return self._pointSize
+ def fset(self, value):
+ self._pointSize = value
+ return locals()
+
+ @Property
+ def Brush():
+ def fget(self):
+ return self._brush
+ def fset(self, value):
+ self._brush = value
+ return locals()
+
+
+ def Apply(self, ctx, colour):
+ nctx = ctx.GetNativeContext()
+ if self._brush is not None:
+ self._brush.Apply(ctx)
+ else:
+ if colour is None: colour = wx.BLACK
+ nctx.set_source_rgba( *_colourToValues(colour) )
+ nctx.set_font_face(self._fontface)
+ nctx.set_font_size(self._pointSize)
+
+
+#---------------------------------------------------------------------------
+
+class GraphicsBitmap(GraphicsObject):
+ """
+ A GraphicsBitmap is a wrapper around a cairo ImageSurface. It can
+ be used as a source for drawing images, or as a target of drawing
+ operations.
+ """
+ def __init__(self, width=-1, height=-1, format=FORMAT_ARGB32):
+ """Create either a NULL GraphicsBitmap or an empty one if a size is given"""
+ self._surface = None
+ if width > 0 and height > 0:
+ self._surface = cairo.ImageSurface(format, width, height)
+
+
+ def IsNull(self):
+ return self._surface is None
+
+
+ @staticmethod
+ def CreateFromBitmap(bitmap):
+ """Create a GraphicsBitmap from a wx.Bitmap"""
+ b = GraphicsBitmap()
+ b._surface = wx.lib.wxcairo.ImageSurfaceFromBitmap(bitmap)
+ return b
+
+
+ @staticmethod
+ def CreateFromPNG(filename):
+ """Create a GraphicsBitmap from a PNG file"""
+ b = GraphicsBitmap()
+ b._surface = cairo.ImageSurface.create_from_png(filename)
+ return b
+
+
+ @staticmethod
+ def CreateFromSurface(surface):
+ """Use an existing cairo ImageSurface as a GraphicsBitmap"""
+ b = GraphicsBitmap()
+ b._surface = surface
+ return b
+
+
+ @staticmethod
+ def CreateFromBuffer(buffer, width, height,
+ format=FORMAT_ARGB32, stride=-1):
+ """
+ Creates a GraphicsBitmap that uses the given buffer object as
+ the pixel storage. This means that the current contents of
+ the buffer will be the initial state of the bitmap, and
+ anything drawn to this surface will be stored in the given
+ buffer.
+ """
+ b = GraphicsBitmap()
+ if stride == -1:
+ try:
+ stride = cairo.ImageSurface.format_stride_for_width(format, width)
+ except AttributeError:
+ stride = width * 4
+ b._surface = cairo.ImageSurface.create_for_data(
+ buffer, format, width, height, stride)
+
+ # save a reference to the buffer to ensure that it lives as
+ # long as this object does
+ b._buffer = buffer
+ return b
+
+
+ @Property
+ def Width():
+ def fget(self):
+ return self._surface.get_width()
+ return locals()
+
+ @Property
+ def Height():
+ def fget(self):
+ return self._surface.get_height()
+ return locals()
+
+ @Property
+ def Size():
+ def fget(self):
+ return (self.Width, self.Height)
+ return locals()
+
+
+ @Property
+ def Format():
+ def fget(self):
+ return self._surface.get_format()
+ return locals()
+
+ @Property
+ def Stride():
+ def fget(self):
+ return self._surface.get_stride()
+ return locals()
+
+ @Property
+ def Surface():
+ def fget(self):
+ return self._surface
+ return locals()
+
+
+#---------------------------------------------------------------------------
+
+class GraphicsMatrix(GraphicsObject):
+ """
+ A matrix holds an affine transformations, such as a scale,
+ rotation, shear, or a combination of these, and is used to convert
+ between different coordinante spaces.
+ """
+ def __init__(self):
+ self._matrix = cairo.Matrix()
+
+
+ def Set(self, a=1.0, b=0.0, c=0.0, d=1.0, tx=0.0, ty=0.0):
+ """Set the componenets of the matrix by value, default values
+ are the identity matrix."""
+ self._matrix = cairo.Matrix(a, b, c, d, tx, ty)
+
+
+ def Get(self):
+ """Return the component values of the matrix as a tuple."""
+ return tuple(self._matrix)
+
+
+ def GetNativeMatrix(self):
+ return self._matrix
+
+
+ def Concat(self, matrix):
+ """Concatenates the matrix passed with the current matrix."""
+ self._matrix = self._matrix * matrix._matrix
+ return self
+
+
+ def Invert(self):
+ """Inverts the matrix."""
+ self._matrix.invert()
+ return self
+
+
+ def IsEqual(self, matrix):
+ """Returns True if the elements of the transformation matricies are equal."""
+ return self._matrix == matrix._matrix
+
+
+ def IsIdentity():
+ """Returns True if this is the identity matrix."""
+ return self._matrix == cairo.Matrix()
+
+
+ def Rotate(self, angle):
+ """Rotates the matrix in radians"""
+ self._matrix.rotate(angle)
+ return self
+
+
+ def Scale(self, xScale, yScale):
+ """Scale the matrix"""
+ self._matrix.scale(xScale, yScale)
+ return self
+
+
+ def Translate(self, dx, dy):
+ """Translate the metrix. This shifts the origin."""
+ self._matrix.translate(dx, dy)
+ return self
+
+
+ def TransformPoint(self, x, y):
+ """Applies this matrix to a point and returns the result"""
+ return self._matrix.transform_point(x, y)
+
+
+ def TransformDistance(self, dx, dy):
+ """
+ Applies this matrix to a distance (ie. performs all transforms
+ except translations.)
+ """
+ return self._matrix.transform_distance(dx, dy)
+
+
+ def Clone(self):
+ m = GraphicsMatrix()
+ m.Set(*self.Get())
+ return m
+
+#---------------------------------------------------------------------------
+
+class GraphicsPath(GraphicsObject):
+ """
+ A GraphicsPath is a representaion of a geometric path, essentially
+ a collection of lines and curves. Paths can be used to define
+ areas to be stroked and filled on a GraphicsContext.
+ """
+ def __init__(self):
+ # A path is essentially just a context that we use just for
+ # collecting path moves, lines, and curves in order to apply
+ # them to the real context. So we'll use a 1x1 image surface
+ # for the backend, since we won't ever actually use it for
+ # rendering in this context.
+ surface = cairo.ImageSurface(FORMAT_ARGB32, 1, 1)
+ self._pathContext = cairo.Context(surface)
+
+
+ def AddArc(self, x, y, radius, startAngle, endAngle, clockwise=True):
+ """
+ Adds an arc of a circle centering at (x,y) with radius, from
+ startAngle to endAngle.
+ """
+ # clockwise means positive in our system (y pointing downwards)
+ if clockwise or endAngle-startAngle >= 2*math.pi:
+ self._pathContext.arc(x, y, radius, startAngle, endAngle)
+ else:
+ self._pathContext.arc_negative(x, y, radius, startAngle, endAngle)
+ return self
+
+
+ def AddArcToPoint(self, x1, y1 , x2, y2, radius ):
+ """
+ Adds a an arc to two tangents connecting (current) to (x1,y1)
+ and (x1,y1) to (x2,y2), also a straight line from (current) to
+ (x1,y1)
+ """
+ current = wx.Point2D(*self.GetCurrentPoint())
+ p1 = wx.Point2D(x1, y1)
+ p2 = wx.Point2D(x2, y2)
+
+ v1 = current - p1
+ v1.Normalize()
+ v2 = p2 - p1
+ v2.Normalize()
+
+ alpha = v1.GetVectorAngle() - v2.GetVectorAngle()
+ if alpha < 0:
+ alpha = 360 + alpha
+ alpha = math.radians(alpha)
+
+ dist = radius / math.sin(alpha/2) * math.cos(alpha/2)
+
+ # calculate tangential points
+ t1 = (v1 * dist) + p1
+ t2 = (v2 * dist) + p1
+
+ nv1 = wx.Point2D(*v1.Get())
+ nv1.SetVectorAngle(v1.GetVectorAngle() - 90)
+ c = t1 + nv1 * radius
+
+ a1 = v1.GetVectorAngle() + 90
+ a2 = v2.GetVectorAngle() - 90
+
+ self.AddLineToPoint(t1.x, t1.y)
+ self.AddArc(c.x, c.y, radius, math.radians(a1), math.radians(a2), True)
+ self.AddLineToPoint(p2.x, p2.y)
+ return self
+
+
+ def AddCircle(self, x, y, radius):
+ """
+ Appends a new closed sub-path as a circle around (x,y).
+ """
+ self.MoveToPoint(x + radius, y)
+ self.AddArc( x, y, radius, 0, 2*math.pi, False)
+ self.CloseSubpath()
+ return self
+
+
+ def AddCurveToPoint(self, cx1, cy1, cx2, cy2, x, y):
+ """
+ Adds a cubic Bezier curve from the current point, using two
+ control points and an end point.
+ """
+ self._pathContext.curve_to(cx1, cy1, cx2, cy2, x, y)
+ return self
+
+
+ def AddEllipse(self, x, y, w, h):
+ """
+ Appends an elipse fitting into the given rectangle as a closed sub-path.
+ """
+ rw = w / 2.0
+ rh = h / 2.0
+ xc = x + rw
+ yc = y + rh
+ m = GraphicsMatrix()
+ m.Translate(xc, yc)
+ m.Scale(rw / rh, 1.0)
+ p = GraphicsPath()
+ p.AddCircle(0,0, rh)
+ p.Transform(m)
+ self.AddPath(p)
+ return self
+
+
+ def AddLineToPoint(self, x, y):
+ """
+ Adds a straight line from the current point to (x,y)
+ """
+ self._pathContext.line_to(x, y)
+ return self
+
+
+ def AddPath(self, path):
+ """
+ Appends the given path to this path.
+ """
+ self._pathContext.append_path(path.GetNativePath())
+ return self
+
+
+ def AddQuadCurveToPoint(self, cx, cy, x, y):
+ """
+ Adds a quadratic Bexier curve from the current point, using a
+ control point and an end point.
+ """
+ # calculate using degree elevation to a cubic bezier
+ start = wx.Point2D()
+ start.x, start.y = self.GetCurrentPoint()
+ end = wx.Point2D(x, y)
+ c = wx.Point2D(cx, cy)
+ c1 = start * (1/3.0) + c * (2/3.0)
+ c2 = c * (2/3.0) + end * (1/3.0)
+ self.AddCurveToPoint(c1.x, c1.y, c2.x, c2.y, x, y);
+ return self
+
+
+ def AddRectangle(self, x, y, w, h):
+ """
+ Adds a new rectanlge as a closed sub-path.
+ """
+ self._pathContext.rectangle(x, y, w, h)
+ return self
+
+
+ def AddRoundedRectangle(self, x, y, w, h, radius):
+ """
+ Adds a new rounded rectanlge as a closed sub-path.
+ """
+ if radius == 0:
+ self.AddRectangle(x,y,w,h)
+ else:
+ self.MoveToPoint( x + w, y + h / 2.0)
+ self.AddArcToPoint(x + w, y + h, x + w / 2.0, y + h, radius)
+ self.AddArcToPoint(x, y + h, x, y + h / 2.0, radius)
+ self.AddArcToPoint(x, y , x + w / 2.0, y, radius)
+ self.AddArcToPoint(x + w, y, x + w, y + h / 2.0, radius)
+ self.CloseSubpath()
+ return self
+
+
+ def CloseSubpath(self):
+ """
+ Adds a line segment to the path from the current point to the
+ beginning of the current sub-path, and closes this sub-path.
+ """
+ self._pathContext.close_path()
+ return self
+
+
+ def Contains(self, x, y, fillStyle=wx.ODDEVEN_RULE):
+ """
+ Returns True if the point lies within the path.
+ """
+ d = { wx.WINDING_RULE : cairo.FILL_RULE_WINDING,
+ wx.ODDEVEN_RULE : cairo.FILL_RULE_EVEN_ODD }
+ rule = d[fillStyle]
+ self._pathContext.set_fill_rule(rule)
+ return self._pathContext.in_stroke(x,y) or self._pathContext.in_fill(x,y)
+
+
+ def GetCurrentPoint(self):
+ """
+ Gets the current point of the path, which is conceptually the
+ final point reached by the last path operation.
+ """
+ return self._pathContext.get_current_point()
+
+
+ def GetNativePath(self):
+ """
+ Returns the path as a cairo.Path object.
+ """
+ return self._pathContext.copy_path()
+
+
+ def MoveToPoint(self, x, y):
+ """
+ Begins a new sub-path at (x,y) by moving the "current point" there.
+ """
+ self._pathContext.move_to(x, y)
+ return self
+
+
+ def Transform(self, matrix):
+ """
+ Transforms each point in this path by the matirx
+ """
+ # as we don't have a true path object, we have to apply the
+ # inverse matrix to the context
+ # TODO: should we clone the matrix before inverting it?
+ m = matrix.GetNativeMatrix()
+ m.invert()
+ self._pathContext.transform(m)
+ return self
+
+
+ def Clone(self):
+ """
+ Return a new path initialized with the current contents of this path.
+ """
+ p = GraphicsPath()
+ p.AddPath(self)
+ return p
+
+
+ def GetBox(self):
+ """
+ Return the bounding box enclosing all points on this path.
+ """
+ x1,y1,x2,y2 = self._pathContext.stroke_extents()
+ if x2 < x1:
+ x = x2
+ w = x1 - x2
+ else:
+ x = x1
+ w = x2 - x1
+
+ if y2 < y1:
+ y = y2
+ h = y1 - y2
+ else:
+ y = y1
+ h = y2 - y1
+ return (x, y, w, h)
+
+
+#---------------------------------------------------------------------------
+
+class GraphicsGradientStop(object):
+ """
+ This class represents a single color-stop in a gradient brush. The
+ position is a floating poitn value between zero and 1.0 which represents
+ the distance between the gradient's starting point and ending point.
+ """
+ def __init__(self, colour=wx.TransparentColour, pos=0.0):
+ self.SetColour(colour)
+ self.SetPosition(pos)
+
+ def GetColour(self):
+ return self._colour
+ def SetColour(self, value):
+ value = _makeColour(value)
+ assert isinstance(value, wx.Colour)
+ self._colour = value
+ Colour = property(GetColour, SetColour)
+
+
+ def GetPosition(self):
+ return self._pos
+ def SetPosition(self, value):
+ assert value >= 0.0 and value <= 1.0
+ self._pos = value
+ Position = property(GetPosition, SetPosition)
+
+
+
+class GraphicsGradientStops(object):
+ """
+ An ordered collection of gradient color stops for a gradient brush. There
+ is always at least the starting stop and the ending stop in the collection.
+ """
+ def __init__(self, startColour=wx.TransparentColour,
+ endColour=wx.TransparentColour):
+ self._stops = list()
+ self.Add(startColour, 0.0)
+ self.Add(endColour, 1.0)
+
+
+ def Add(self, *args):
+ """
+ Add a new color to the collection. args may be either a gradient stop,
+ or a colour and position.
+ """
+ if len(args) == 2:
+ col, pos = args
+ stop = GraphicsGradientStop(col, pos)
+ elif len(args) == 1:
+ stop = args[0]
+ else:
+ raise ValueError, "Invalid parameters passed to Add"
+ assert isinstance(stop, GraphicsGradientStop)
+
+ self._stops.append(stop)
+ self._stops.sort(key=lambda x: x.Position)
+
+
+ def GetCount(self):
+ return len(self._stops)
+ Count = property(GetCount)
+ def __len__(self):
+ return self.GetCount()
+
+
+ def Item(self, n):
+ return self._stops[n]
+ def __getitem__(self, n):
+ return self._stops[n]
+
+
+ def GetStartColour(self):
+ return self._stops[0].Colour
+ def SetStartColour(self, col):
+ self._stops[0].Colour = col
+ StartColour = property(GetStartColour, SetStartColour)
+
+
+ def GetEndColour(self):
+ return self._stops[-1].Colour
+ def SetEndColour(self, col):
+ self._stops[-1].Colour = col
+ EndColour = property(GetEndColour, SetEndColour)
+
+
+#---------------------------------------------------------------------------
+
+class GraphicsContext(GraphicsObject):
+ """
+ The GraphicsContext is the object which facilitates drawing to a surface.
+ """
+ def __init__(self, context=None, size=None):
+ self._context = context
+ self._pen = None
+ self._brush = None
+ self._font = None
+ self._fontColour = None
+ self._layerOpacities = []
+ self._width = 10000.0
+ self._height = 10000.0
+ if size is not None:
+ self._width, self._height = size
+
+
+ def IsNull(self):
+ return self._context is None
+
+
+ @staticmethod
+ def Create(dc):
+ # TODO: Support creating directly from a wx.Window too.
+ assert isinstance(dc, wx.DC)
+ ctx = wx.lib.wxcairo.ContextFromDC(dc)
+ return GraphicsContext(ctx, dc.GetSize())
+
+ @staticmethod
+ def CreateFromNative(cairoContext):
+ return GraphicsContext(cairoContext)
+
+ @staticmethod
+ def CreateMeasuringContext():
+ """
+ If you need a temporary context just to quickly measure some
+ text extents, or etc. then using this function will be a
+ little less expensive than creating a real DC for it.
+ """
+ surface = cairo.ImageSurface(FORMAT_ARGB32, 1, 1)
+ ctx = cairo.Context(surface)
+ return GraphicsContext(ctx,
+ (surface.get_width(), surface.get_height()))
+
+ @staticmethod
+ def CreateFromSurface(surface):
+ """
+ Wrap a context around the given cairo Surface. Note that a
+ GraphicsBitmap contains a cairo ImageSurface which is
+ accessible via the Surface property.
+ """
+ return GraphicsContext(cairo.Context(surface),
+ (surface.get_width(), surface.get_height()))
+
+
+ @Property
+ def Context():
+ def fget(self):
+ return self._context
+ return locals()
+
+
+ # Our implementation is able to create these things direclty, but
+ # we'll keep them here too for compatibility with wx.GraphicsContext.
+
+ def CreateBrush(self, brush):
+ """
+ Create a brush from a wx.Brush.
+ """
+ return GraphicsBrush.CreateFromBrush(brush)
+
+ def CreateFont(self, font, colour=None):
+ """
+ Create a font from a wx.Font
+ """
+ return GraphicsFont.CreateFromFont(font, colour)
+
+
+ def CreateLinearGradientBrush(self, x1, y1, x2, y2, *args):
+ """
+ Creates a native brush having a linear gradient, starting at (x1,y1)
+ to (x2,y2) with the given boundary colors or the specified stops.
+
+ The `*args` can be either a GraphicsGradientStops or just two colours to
+ be used as the starting and ending gradient colours.
+ """
+ if len(args) ==1:
+ stops = args[0]
+ elif len(args) == 2:
+ c1 = _makeColour(c1)
+ c2 = _makeColour(c2)
+ stops = GraphicsGradientStops(c1, c2)
+ else:
+ raise ValueError, "Invalid args passed to CreateLinearGradientBrush"
+
+ pattern = cairo.LinearGradient(x1, y1, x2, y2)
+ for stop in stops:
+ pattern.add_color_stop_rgba(stop.Position, *_colourToValues(stop.Colour))
+ return GraphicsBrush.CreateFromPattern(pattern)
+
+
+ def CreateRadialGradientBrush(self, xo, yo, xc, yc, radius, *args):
+ """
+ Creates a native brush, having a radial gradient originating at point
+ (xo,yo) and ending on a circle around (xc,yc) with the given radius;
+ the colours may be specified by just the two extremes or the full
+ array of gradient stops.
+
+ The `*args` can be either a GraphicsGradientStops or just two colours to
+ be used as the starting and ending gradient colours.
+ """
+ if len(args) ==1:
+ stops = args[0]
+ elif len(args) == 2:
+ oColour = _makeColour(oColour)
+ cColour = _makeColour(cColour)
+ stops = GraphicsGradientStops(oColour, cColour)
+ else:
+ raise ValueError, "Invalid args passed to CreateLinearGradientBrush"
+
+ pattern = cairo.RadialGradient(xo, yo, 0.0, xc, yc, radius)
+ for stop in stops:
+ pattern.add_color_stop_rgba(stop.Position, *_colourToValues(stop.Colour))
+ return GraphicsBrush.CreateFromPattern(pattern)
+
+
+ def CreateMatrix(self, a=1.0, b=0, c=0, d=1.0, tx=0, ty=0):
+ """
+ Create a new matrix object.
+ """
+ m = GraphicsMatrix()
+ m.Set(a, b, c, d, tx, ty)
+ return m
+
+ def CreatePath(self):
+ """
+ Create a new path obejct.
+ """
+ return GraphicsPath()
+
+ def CreatePen(self, pen):
+ """
+ Create a new pen from a wx.Pen.
+ """
+ return GraphicsPen.CreateFromPen(pen)
+
+
+
+
+ def PushState(self):
+ """
+ Makes a copy of the current state of the context (ie the
+ transformation matrix) and saves it on an internal stack of
+ saved states. The saved state will be restored when PopState
+ is called.
+ """
+ self._context.save()
+
+
+ def PopState(self):
+ """
+ Restore the most recently saved state which was saved with
+ PushState.
+ """
+ self._context.restore()
+
+
+ def Clip(self, x, y, w, h):
+ """
+ Adds the rectangle to the current clipping region. The
+ clipping region causes drawing operations to be limited to the
+ clipped areas of the context.
+ """
+ p = GraphicsPath()
+ p.AddRectangle(x, y, w, h)
+ self._context.append_path(p.GetNativePath())
+ self._context.clip()
+
+
+ def ClipRegion(self, region):
+ """
+ Adds the wx.Region to the current clipping region.
+ """
+ p = GraphicsPath()
+ ri = wx.RegionIterator(region)
+ while ri:
+ rect = ri.GetRect()
+ p.AddRectangle( *rect )
+ ri.Next()
+ self._context.append_path(p.GetNativePath())
+ self._context.clip()
+
+
+ def ResetClip(self):
+ """
+ Resets the clipping region to the original shape of the context.
+ """
+ self._context.reset_clip()
+
+
+ def GetNativeContext(self):
+ return self._context
+
+
+ # Since DC logical functions are conceptually different than
+ # compositing operators don't pretend they are the same thing, or
+ # try ot implement them using the compositing operators.
+ def GetLogicalFunction(self):
+ raise NotImplementedError("See GetCompositingOperator")
+ def SetLogicalFunction(self, function):
+ raise NotImplementedError("See SetCompositingOperator")
+
+
+ def Translate(self, dx, dy):
+ """
+ Modifies the current transformation matrix by translating the
+ user-space origin by (dx, dy).
+ """
+ self._context.translate(dx, dy)
+
+
+ def Scale(self, xScale, yScale):
+ """
+ Modifies the current transformation matrix by translating the
+ user-space axes by xScale and yScale.
+ """
+ self._context.scale(xScale, yScale)
+
+
+ def Rotate(self, angle):
+ """
+ Modifies the current transformation matrix by rotating the
+ user-space axes by angle radians.
+ """
+ self._context.rotate(angle)
+
+
+ def ConcatTransform(self, matrix):
+ """
+ Modifies the current transformation matrix by applying matrix
+ as an additional transformation.
+ """
+ self._context.transform(matrix.GetNativeMatrix())
+
+
+ def SetTransform(self, matrix):
+ """
+ Set the context's current transformation matrix to matrix.
+ """
+ self._context.set_matrix(matrix.GetNativeMatrix())
+
+
+ def GetTransform(self):
+ """
+ Returns the context's current transformation matrix.
+ """
+ gm = GraphicsMatrix()
+ gm.Set( *tuple(self._context.get_matrix()) )
+ return gm
+
+
+ def SetPen(self, pen):
+ """
+ Set the pen to be used for stroking lines in future drawing
+ operations. Either a wx.Pen or a GraphicsPen object may be
+ used.
+ """
+ if isinstance(pen, wx.Pen):
+ if not pen.Ok() or pen.Style == wx.TRANSPARENT:
+ pen = None
+ else:
+ pen = GraphicsPen.CreateFromPen(pen)
+ self._pen = pen
+
+ def GetPen(self): return self._pen
+ Pen = property(GetPen, SetPen)
+
+
+ def SetBrush(self, brush):
+ """
+ Set the brush to be used for filling shapes in future drawing
+ operations. Either a wx.Brush or a GraphicsBrush object may
+ be used.
+ """
+ if isinstance(brush, wx.Brush):
+ if not brush.Ok() or brush.Style == wx.TRANSPARENT:
+ brush = None
+ else:
+ brush = GraphicsBrush.CreateFromBrush(brush)
+ self._brush = brush
+
+ def GetBrush(self): return self._brush
+ Brush = property(GetBrush, SetBrush)
+
+
+ def SetFont(self, font, colour=None):
+ """
+ Sets the font to be used for drawing text. Either a wx.Font
+ or a GrpahicsFont may be used.
+ """
+ if isinstance(font, wx.Font):
+ font = GraphicsFont.CreateFromFont(font, colour)
+ self._font = font
+ if colour is not None:
+ self._fontColour = _makeColour(colour)
+ else:
+ self._fontColour = font._colour
+
+ def GetFont(self): return (self._font, self._fontColour)
+ def _SetFont(self, *both): self.SetFont(*both)
+ Font = property(GetFont, _SetFont)
+
+
+ def StrokePath(self, path):
+ """
+ Strokes the path (draws the lines) using the current pen.
+ """
+ if self._pen:
+ offset = _OffsetHelper(self)
+ self._context.append_path(path.GetNativePath())
+ self._pen.Apply(self)
+ self._context.stroke()
+
+
+ def FillPath(self, path, fillStyle=wx.ODDEVEN_RULE):
+ """
+ Fills the path using the current brush.
+ """
+ if self._brush:
+ offset = _OffsetHelper(self)
+ self._context.append_path(path.GetNativePath())
+ self._brush.Apply(self)
+ d = { wx.WINDING_RULE : cairo.FILL_RULE_WINDING,
+ wx.ODDEVEN_RULE : cairo.FILL_RULE_EVEN_ODD }
+ rule = d[fillStyle]
+ self._context.set_fill_rule(rule)
+ self._context.fill()
+
+
+ def DrawPath(self, path, fillStyle=wx.ODDEVEN_RULE):
+ """
+ Draws the path by first filling it and then stroking it.
+ """
+ # TODO: this could be optimized by moving the stroke and fill
+ # code here and only loading the path once.
+ self.FillPath(path, fillStyle)
+ self.StrokePath(path)
+
+
+ def DrawText(self, text, x, y, backgroundBrush=None):
+ """
+ Draw the text at (x,y) using the current font. If
+ backgroundBrush is set then it is used to fill the rectangle
+ behind the text.
+ """
+ if backgroundBrush:
+ formerBrush = self._brush
+ formerPen = self._pen
+ self.SetBrush(backgroundBrush)
+ self.SetPen(None)
+ width, height = self.GetTextExtent(text)
+ path = GraphicsPath()
+ path.AddRectangle(x, y, width, height)
+ self.FillPath(path)
+ self._DrawText(text, x, y)
+ self.SetBrush(formerBrush)
+ self.SetPen(formerPen)
+
+ else:
+ self._DrawText(text, x, y)
+
+
+ def _DrawText(self, text, x, y, angle=None):
+ # helper used by DrawText and DrawRotatedText
+ if angle is not None:
+ self.PushState()
+ self.Translate(x, y)
+ self.Rotate(-angle)
+ x = y = 0
+
+ self._font.Apply(self, self._fontColour)
+ # Cairo's x,y for drawing text is at the baseline, so we need to adjust
+ # the position we move to by the ascent.
+ fe = self._context.font_extents()
+ ascent = fe[0]
+ self._context.move_to( x, y + ascent )
+ self._context.show_text(text)
+
+ if angle is not None:
+ self.PopState()
+
+
+ def DrawRotatedText(self, text, x, y, angle, backgroundBrush=None):
+ """
+ Draw the text at (x,y) using the current font and rotated
+ angle radians. If backgroundBrush is set then it is used to
+ fill the rectangle behind the text.
+ """
+ if backgroundBrush:
+ formerBrush = self._brush
+ formerPen = self._pen
+ self.SetBrush(backgroundBrush)
+ self.SetPen(None)
+ width, height = self.GetTextExtent(text)
+ path = GraphicsPath()
+ path.AddRectangle(0, 0, width, height)
+ self.PushState()
+ self.Translate(x, y)
+ self.Rotate(-angle)
+ self.FillPath(path)
+ self.PopState()
+ self._DrawText(text, x, y, angle)
+ self.SetBrush(formerBrush)
+ self.SetPen(formerPen)
+
+ else:
+ self._DrawText(text, x, y, angle)
+
+
+ def GetFullTextExtent(self, text):
+ """
+ Returns the (width, height, descent, externalLeading) of the
+ text using the current font.
+ """
+ if not text:
+ return (0,0,0,0)
+
+ self._font.Apply(self, self._fontColour)
+
+ te = self._context.text_extents(text)
+ width = te[2]
+
+ fe = self._context.font_extents()
+ height = fe[2]
+ descent = fe[1]
+ ascent = fe[0]
+ externalLeading = max(0, height - (ascent + descent))
+
+ return (width, height, descent, externalLeading)
+
+
+ def GetTextExtent(self, text):
+ """
+ Returns the (width, height) of the text using the current
+ font.
+ """
+ (width, height, descent, externalLeading) = self.GetFullTextExtent(text)
+ return (width, height)
+
+
+ def GetPartialTextExtents(self, text):
+ raise NotImplementedError("TODO")
+
+
+ def DrawBitmap(self, bmp, x, y, w=-1, h=-1):
+ """
+ Draw the bitmap at (x,y). If the width and height parameters
+ are passed then the bitmap is scaled to fit that size. Either
+ a wx.Bitmap or a GraphicsBitmap may be used.
+ """
+ if isinstance(bmp, wx.Bitmap):
+ bmp = GraphicsBitmap.CreateFromBitmap(bmp)
+
+ # In case we're scaling the image by using a width and height
+ # different than the bitmap's size, create a pattern
+ # transformation on the surface and draw the transformed
+ # pattern.
+ self.PushState()
+ pattern = cairo.SurfacePattern(bmp.Surface)
+
+ bw, bh = bmp.Size
+ if w == -1: w = bw
+ if h == -1: h = bh
+ scaleX = w / float(bw)
+ scaleY = h / float(bh)
+
+ self._context.translate(x, y)
+ self._context.scale(scaleX, scaleY)
+ self._context.set_source(pattern)
+
+ # use the original size here since the context is scaled already...
+ self._context.rectangle(0, 0, bw, bh)
+ # fill the rectangle with the pattern
+ self._context.fill()
+
+ self.PopState()
+
+
+ def DrawIcon(self, icon, x, y, w=-1, h=-1):
+ raise NotImplementedError("TODO")
+
+
+ def StrokeLine(self, x1, y1, x2, y2):
+ """
+ Strokes a single line using the current pen.
+ """
+ path = GraphicsPath()
+ path.MoveToPoint(x1, y1)
+ path.AddLineToPoint(x2, y2)
+ self.StrokePath(path)
+
+
+ def StrokeLines(self, points):
+ """
+ Stroke a series of conencted lines using the current pen.
+ Points is a sequence of points or 2-tuples, and lines are
+ drawn from point to point through the end of the sequence.
+ """
+ path = GraphicsPath()
+ x, y = points[0]
+ path.MoveToPoint(x, y)
+ for point in points[1:]:
+ x, y = point
+ path.AddLineToPoint(x, y)
+ self.StrokePath(path)
+
+
+ def StrokeLineSegments(self, beginPoints, endPoints):
+ """
+ Stroke a series of lines using the current pen. For each line
+ the begin point is taken from the beginPoints sequence and the
+ ending point is taken from the endPoints sequence.
+ """
+ path = GraphicsPath()
+ for begin, end in zip(beginPoints, endPoints):
+ path.MoveToPoint(begin[0], begin[1])
+ path.AddLineToPoint(end[0], end[1])
+ self.StrokePath(path)
+
+
+ def DrawLines(self, points, fillStyle=wx.ODDEVEN_RULE):
+ """
+ Stroke and fill a series of connected lines using the current
+ pen and current brush.
+ """
+ path = GraphicsPath()
+ x, y = points[0]
+ path.MoveToPoint(x, y)
+ for point in points[1:]:
+ x, y = point
+ path.AddLineToPoint(x, y)
+ self.DrawPath(path, fillStyle)
+
+
+ def DrawRectangle(self, x, y, w, h):
+ """
+ Stroke and fill a rectangle using the current pen and current
+ brush.
+ """
+ path = GraphicsPath()
+ path.AddRectangle(x, y, w, h)
+ self.DrawPath(path)
+
+
+ def DrawEllipse(self, x, y, w, h):
+ """
+ Stroke and fill an elipse that fits in the given rectangle,
+ using the current pen and current brush.
+ """
+ path = GraphicsPath()
+ path.AddEllipse(x, y, w, h)
+ self.DrawPath(path)
+
+
+ def DrawRoundedRectangle(self, x, y, w, h, radius):
+ """
+ Stroke and fill a rounded rectangle using the current pen and
+ current brush.
+ """
+ path = GraphicsPath()
+ path.AddRoundedRectangle(x, y, w, h, radius)
+ self.DrawPath(path)
+
+
+
+ def GetCompositingOperator(self):
+ """
+ Returns the current compositing operator for the context.
+ """
+ return self._context.get_operator()
+
+ def SetCompositingOperator(self, op):
+ """
+ Sets the compositin operator to be used for all drawing
+ operations. The default operator is OPERATOR_OVER.
+ """
+ return self._context.set_operator(op)
+
+
+ def GetAntialiasMode(self):
+ """
+ Returns the current antialias mode.
+ """
+ return self._context.get_antialias()
+
+ def SetAntialiasMode(self, mode=ANTIALIAS_DEFAULT):
+ """
+ Set the antialiasing mode of the rasterizer used for drawing
+ shapes. This value is a hint, and a particular backend may or
+ may not support a particular value.
+ """
+ self._context.set_antialias(mode)
+
+
+ def BeginLayer(self, opacity):
+ """
+ Redirects future rendering to a temorary context. See `EndLayer`.
+ """
+ self._layerOpacities.append(opacity)
+ self._context.push_group()
+
+
+ def EndLayer(self):
+ """
+ Composites the drawing done on the temporary context created
+ in `BeginLayer` back into the main context, using the opacity
+ specified for the layer.
+ """
+ opacity = self._layerOpacities.pop()
+ self._context.pop_group_to_source()
+ self._context.paint_with_alpha(opacity)
+
+
+ def GetSize(self):
+ return (self._width, self._height)
+ Size = property(GetSize)
+
+
+ # Some things not in wx.GraphicsContext (yet)
+
+ def DrawCircle(self, x, y, radius):
+ """
+ Stroke and fill a circle centered at (x,y) with the given
+ radius, using the current pen and brush.
+ """
+ path = GraphicsPath()
+ path.AddCircle(x, y, radius)
+ self.DrawPath(path)
+
+
+ def ClipPath(self, path):
+ """
+ Set the clip region to the path.
+ """
+ self._context.append_path(path.GetNativePath())
+ self._context.clip()
+
+
+ def Clear(self, colour=None):
+ """
+ Clear the context using the given color or the currently set brush.
+ """
+ if colour is not None:
+ brush = GraphicsBrush(colour)
+ elif self._brush is None:
+ brush = GraphicsBrush(wx.WHITE)
+ else:
+ brush = self._brush
+
+ self.PushState()
+ op = self._context.get_operator()
+ self._context.set_operator(cairo.OPERATOR_SOURCE)
+ self._context.reset_clip()
+
+ brush.Apply(self)
+ self._context.paint()
+
+ self._context.set_operator(op)
+ self.PopState()
+
+
+#---------------------------------------------------------------------------
+# Utility functions
+
+def _makeColour(colour):
+ # make a wx.Colour from any of the allowed typemaps (string, tuple,
+ # etc.)
+ if isinstance(colour, (basestring, tuple)):
+ return wx.NamedColour(colour)
+ else:
+ return colour
+
+
+def _colourToValues(c):
+ # Convert wx.Colour components to a set of values between 0 and 1
+ return tuple( [x/255.0 for x in c.Get(True)] )
+
+
+
+class _OffsetHelper(object):
+ def __init__(self, ctx):
+ self.ctx = ctx
+ self.offset = 0
+ if ctx._pen:
+ penwidth = ctx._pen.Width
+ if penwidth == 0:
+ penwidth = 1
+ self.offset = (penwidth % 2) == 1;
+ if self.offset:
+ ctx.Translate(0.5, 0.5)
+
+ def __del__(self):
+ if self.offset:
+ self.ctx.Translate(-0.5, -0.5)
+
+
+
+def _stdDashes(style, width):
+ if width < 1.0:
+ width = 1.0
+
+ if style == wx.DOT:
+ dashes = [ width, width + 2.0]
+ elif style == wx.DOT_DASH:
+ dashes = [ 9.0, 6.0, 3.0, 3.0 ]
+ elif style == wx.LONG_DASH:
+ dashes = [ 19.0, 9.0 ]
+ elif style == wx.SHORT_DASH:
+ dashes = [ 9.0, 6.0 ]
+
+ return dashes
+
+
+#---------------------------------------------------------------------------
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/gridmovers.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/gridmovers.py
new file mode 100644
index 0000000..f724805
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/gridmovers.py
@@ -0,0 +1,493 @@
+#----------------------------------------------------------------------------
+# Name: GridColMover.py
+# Purpose: Grid Column Mover Extension
+#
+# Author: Gerrit van Dyk (email: gerritvd@decillion.net)
+#
+# Version 0.1
+# Date: Nov 19, 2002
+# RCS-ID: $Id$
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+# 12/07/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 Compatability changes
+#
+# 12/18/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxGridColMoveEvent -> GridColMoveEvent
+# o wxGridRowMoveEvent -> GridRowMoveEvent
+# o wxGridColMover -> GridColMover
+# o wxGridRowMover -> GridRowMover
+#
+
+
+import wx
+import wx.grid
+
+#----------------------------------------------------------------------------
+# event class and macros
+#
+# New style 12/7/03
+#
+
+wxEVT_COMMAND_GRID_COL_MOVE = wx.NewEventType()
+wxEVT_COMMAND_GRID_ROW_MOVE = wx.NewEventType()
+
+EVT_GRID_COL_MOVE = wx.PyEventBinder(wxEVT_COMMAND_GRID_COL_MOVE, 1)
+EVT_GRID_ROW_MOVE = wx.PyEventBinder(wxEVT_COMMAND_GRID_ROW_MOVE, 1)
+
+#----------------------------------------------------------------------------
+
+class GridColMoveEvent(wx.PyCommandEvent):
+ def __init__(self, id, dCol, bCol):
+ wx.PyCommandEvent.__init__(self, id = id)
+ self.SetEventType(wxEVT_COMMAND_GRID_COL_MOVE)
+ self.moveColumn = dCol
+ self.beforeColumn = bCol
+
+ def GetMoveColumn(self):
+ return self.moveColumn
+
+ def GetBeforeColumn(self):
+ return self.beforeColumn
+
+
+class GridRowMoveEvent(wx.PyCommandEvent):
+ def __init__(self, id, dRow, bRow):
+ wx.PyCommandEvent.__init__(self,id = id)
+ self.SetEventType(wxEVT_COMMAND_GRID_ROW_MOVE)
+ self.moveRow = dRow
+ self.beforeRow = bRow
+
+ def GetMoveRow(self):
+ return self.moveRow
+
+ def GetBeforeRow(self):
+ return self.beforeRow
+
+
+#----------------------------------------------------------------------------
+# graft new methods into the wxGrid class
+
+def _ColToRect(self,col):
+ if self.GetNumberRows() > 0:
+ rect = self.CellToRect(0,col)
+ else:
+ rect = wx.Rect()
+ rect.height = self.GetColLabelSize()
+ rect.width = self.GetColSize(col)
+
+ for cCol in range(0,col):
+ rect.x += self.GetColSize(cCol)
+
+ rect.y = self.GetGridColLabelWindow().GetPosition()[1]
+ return rect
+
+wx.grid.Grid.ColToRect = _ColToRect
+
+
+def _RowToRect(self,row):
+ if self.GetNumberCols() > 0:
+ rect = self.CellToRect(row,0)
+ else:
+ rect = wx.Rect()
+ rect.width = self.GetRowLabelSize()
+ rect.height = self.GetRowSize(row)
+
+ for cRow in range(0,row):
+ rect.y += self.GetRowSize(cRow)
+
+ rect.x = self.GetGridRowLabelWindow().GetPosition()[0]
+ return rect
+
+wx.grid.Grid.RowToRect = _RowToRect
+
+
+#----------------------------------------------------------------------------
+
+class ColDragWindow(wx.Window):
+ def __init__(self,parent,image,dragCol):
+ wx.Window.__init__(self,parent,-1, style=wx.SIMPLE_BORDER)
+ self.image = image
+ self.SetSize((self.image.GetWidth(),self.image.GetHeight()))
+ self.ux = parent.GetScrollPixelsPerUnit()[0]
+ self.moveColumn = dragCol
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+ def DisplayAt(self,pos,y):
+ x = self.GetPositionTuple()[0]
+ if x == pos:
+ self.Refresh() # Need to display insertion point
+ else:
+ self.MoveXY(pos,y)
+
+ def GetMoveColumn(self):
+ return self.moveColumn
+
+ def _GetInsertionInfo(self):
+ parent = self.GetParent()
+ sx = parent.GetViewStart()[0] * self.ux
+ sx -= parent.GetRowLabelSize()
+ x = self.GetPosition()[0]
+ w = self.GetSize()[0]
+ sCol = parent.XToCol(x + sx)
+ eCol = parent.XToCol(x + w + sx)
+ iPos = xPos = xCol = 99999
+ centerPos = x + sx + (w / 2)
+
+ for col in range(sCol,eCol + 1):
+ cx = parent.ColToRect(col)[0]
+
+ if abs(cx - centerPos) < iPos:
+ iPos = abs(cx - centerPos)
+ xCol = col
+ xPos = cx
+
+ if xCol < 0 or xCol > parent.GetNumberCols():
+ xCol = parent.GetNumberCols()
+
+ return (xPos - sx - x,xCol)
+
+ def GetInsertionColumn(self):
+ return self._GetInsertionInfo()[1]
+
+ def GetInsertionPos(self):
+ return self._GetInsertionInfo()[0]
+
+ def OnPaint(self,evt):
+ dc = wx.PaintDC(self)
+ w,h = self.GetSize()
+ dc.DrawBitmap(self.image, 0,0)
+ dc.SetPen(wx.Pen(wx.BLACK,1,wx.SOLID))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(0,0, w,h)
+ iPos = self.GetInsertionPos()
+ dc.DrawLine(iPos,h - 10, iPos,h)
+
+
+
+
+class RowDragWindow(wx.Window):
+ def __init__(self,parent,image,dragRow):
+ wx.Window.__init__(self,parent,-1, style=wx.SIMPLE_BORDER)
+ self.image = image
+ self.SetSize((self.image.GetWidth(),self.image.GetHeight()))
+ self.uy = parent.GetScrollPixelsPerUnit()[1]
+ self.moveRow = dragRow
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+ def DisplayAt(self,x,pos):
+ y = self.GetPosition()[1]
+ if y == pos:
+ self.Refresh() # Need to display insertion point
+ else:
+ self.MoveXY(x,pos)
+
+ def GetMoveRow(self):
+ return self.moveRow
+
+ def _GetInsertionInfo(self):
+ parent = self.GetParent()
+ sy = parent.GetViewStart()[1] * self.uy
+ sy -= parent.GetColLabelSize()
+ y = self.GetPosition()[1]
+ h = self.GetSize()[1]
+ sRow = parent.YToRow(y + sy)
+ eRow = parent.YToRow(y + h + sy)
+ iPos = yPos = yRow = 99999
+ centerPos = y + sy + (h / 2)
+
+ for row in range(sRow,eRow + 1):
+ cy = parent.RowToRect(row)[1]
+
+ if abs(cy - centerPos) < iPos:
+ iPos = abs(cy - centerPos)
+ yRow = row
+ yPos = cy
+
+ if yRow < 0 or yRow > parent.GetNumberRows():
+ yRow = parent.GetNumberRows()
+
+ return (yPos - sy - y,yRow)
+
+ def GetInsertionRow(self):
+ return self._GetInsertionInfo()[1]
+
+ def GetInsertionPos(self):
+ return self._GetInsertionInfo()[0]
+
+ def OnPaint(self,evt):
+ dc = wx.PaintDC(self)
+ w,h = self.GetSize()
+ dc.DrawBitmap(self.image, 0,0)
+ dc.SetPen(wx.Pen(wx.BLACK,1,wx.SOLID))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(0,0, w,h)
+ iPos = self.GetInsertionPos()
+ dc.DrawLine(w - 10,iPos, w,iPos)
+
+#----------------------------------------------------------------------------
+
+class GridColMover(wx.EvtHandler):
+ def __init__(self,grid):
+ wx.EvtHandler.__init__(self)
+
+ self.grid = grid
+ self.lwin = grid.GetGridColLabelWindow()
+ self.lwin.PushEventHandler(self)
+ self.colWin = None
+ self.ux = self.grid.GetScrollPixelsPerUnit()[0]
+ self.startX = -10
+ self.cellX = 0
+ self.didMove = False
+ self.isDragging = False
+
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnPress)
+ self.Bind(wx.EVT_LEFT_UP, self.OnRelease)
+
+ def OnMouseMove(self,evt):
+ if not self.isDragging:
+ evt.Skip()
+ else:
+ _rlSize = self.grid.GetRowLabelSize()
+ if abs(self.startX - evt.X) >= 3 \
+ and abs(evt.X - self.lastX) >= 3:
+ self.lastX = evt.X
+ self.didMove = True
+ sx,y = self.grid.GetViewStart()
+ w,h = self.lwin.GetClientSize()
+ x = sx * self.ux
+
+ if (evt.X + x) < x:
+ x = evt.X + x
+ elif evt.X > w:
+ x += evt.X - w
+
+ if x < 1: x = 0
+ else: x /= self.ux
+
+ if x != sx:
+ if wx.Platform == '__WXMSW__':
+ self.colWin.Show(False)
+
+ self.grid.Scroll(x,y)
+
+ x,y = self.lwin.ClientToScreenXY(evt.X,0)
+ x,y = self.grid.ScreenToClientXY(x,y)
+
+ if not self.colWin.IsShown():
+ self.colWin.Show(True)
+
+ px = x - self.cellX
+
+ if px < 0 + _rlSize: px = 0 + _rlSize
+
+ if px > w - self.colWin.GetSize()[0] + _rlSize:
+ px = w - self.colWin.GetSize()[0] + _rlSize
+
+ self.colWin.DisplayAt(px,y)
+ return
+
+
+ def OnPress(self,evt):
+ self.startX = self.lastX = evt.X
+ _rlSize = self.grid.GetRowLabelSize()
+ sx = self.grid.GetViewStart()[0] * self.ux
+ sx -= _rlSize
+ px,py = self.lwin.ClientToScreenXY(evt.X,evt.Y)
+ px,py = self.grid.ScreenToClientXY(px,py)
+
+ if self.grid.XToEdgeOfCol(px + sx) != wx.NOT_FOUND:
+ evt.Skip()
+ return
+
+ self.isDragging = True
+ self.didMove = False
+ col = self.grid.XToCol(px + sx)
+ rect = self.grid.ColToRect(col)
+ self.cellX = px + sx - rect.x
+ size = self.lwin.GetSize()
+ rect.y = 0
+ rect.x -= sx + _rlSize
+ rect.height = size[1]
+ colImg = self._CaptureImage(rect)
+ self.colWin = ColDragWindow(self.grid,colImg,col)
+ self.colWin.Show(False)
+ self.lwin.CaptureMouse()
+ evt.Skip()
+
+ def OnRelease(self,evt):
+ if self.isDragging:
+ self.lwin.ReleaseMouse()
+ self.colWin.Show(False)
+ self.isDragging = False
+
+ if not self.didMove:
+ px = self.lwin.ClientToScreenXY(self.startX,0)[0]
+ px = self.grid.ScreenToClientXY(px,0)[0]
+ sx = self.grid.GetViewStart()[0] * self.ux
+ sx -= self.grid.GetRowLabelSize()
+ col = self.grid.XToCol(px+sx)
+
+ if col != wx.NOT_FOUND:
+ self.grid.SelectCol(col,evt.ControlDown())
+
+ return
+ else:
+ bCol = self.colWin.GetInsertionColumn()
+ dCol = self.colWin.GetMoveColumn()
+ wx.PostEvent(self,
+ GridColMoveEvent(self.grid.GetId(), dCol, bCol))
+
+ self.colWin.Destroy()
+ evt.Skip()
+
+ def _CaptureImage(self,rect):
+ bmp = wx.EmptyBitmap(rect.width,rect.height)
+ memdc = wx.MemoryDC()
+ memdc.SelectObject(bmp)
+ dc = wx.WindowDC(self.lwin)
+ memdc.Blit(0,0, rect.width, rect.height, dc, rect.x, rect.y)
+ memdc.SelectObject(wx.NullBitmap)
+ return bmp
+
+
+class GridRowMover(wx.EvtHandler):
+ def __init__(self,grid):
+ wx.EvtHandler.__init__(self)
+
+ self.grid = grid
+ self.lwin = grid.GetGridRowLabelWindow()
+ self.lwin.PushEventHandler(self)
+ self.rowWin = None
+ self.uy = self.grid.GetScrollPixelsPerUnit()[1]
+ self.startY = -10
+ self.cellY = 0
+ self.didMove = False
+ self.isDragging = False
+
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnPress)
+ self.Bind(wx.EVT_LEFT_UP, self.OnRelease)
+
+ def OnMouseMove(self,evt):
+ if not self.isDragging:
+ evt.Skip()
+ else:
+ _clSize = self.grid.GetColLabelSize()
+ if abs(self.startY - evt.Y) >= 3 \
+ and abs(evt.Y - self.lastY) >= 3:
+ self.lastY = evt.Y
+ self.didMove = True
+ x,sy = self.grid.GetViewStart()
+ w,h = self.lwin.GetClientSizeTuple()
+ y = sy * self.uy
+
+ if (evt.Y + y) < y:
+ y = evt.Y + y
+ elif evt.Y > h:
+ y += evt.Y - h
+
+ if y < 1:
+ y = 0
+ else:
+ y /= self.uy
+
+ if y != sy:
+ if wx.Platform == '__WXMSW__':
+ self.rowWin.Show(False)
+
+ self.grid.Scroll(x,y)
+
+ x,y = self.lwin.ClientToScreenXY(0,evt.Y)
+ x,y = self.grid.ScreenToClientXY(x,y)
+
+ if not self.rowWin.IsShown():
+ self.rowWin.Show(True)
+
+ py = y - self.cellY
+
+ if py < 0 + _clSize:
+ py = 0 + _clSize
+
+ if py > h - self.rowWin.GetSize()[1] + _clSize:
+ py = h - self.rowWin.GetSize()[1] + _clSize
+
+ self.rowWin.DisplayAt(x,py)
+ return
+
+
+ def OnPress(self,evt):
+ self.startY = self.lastY = evt.Y
+ _clSize = self.grid.GetColLabelSize()
+ sy = self.grid.GetViewStart()[1] * self.uy
+ sy -= _clSize
+ px,py = self.lwin.ClientToScreenXY(evt.X,evt.Y)
+ px,py = self.grid.ScreenToClientXY(px,py)
+
+ if self.grid.YToEdgeOfRow(py + sy) != wx.NOT_FOUND:
+ evt.Skip()
+ return
+
+ row = self.grid.YToRow(py + sy)
+
+ if row == wx.NOT_FOUND:
+ evt.Skip()
+ return
+
+ self.isDragging = True
+ self.didMove = False
+
+ rect = self.grid.RowToRect(row)
+ self.cellY = py + sy - rect.y
+ size = self.lwin.GetSize()
+ rect.x = 0
+ rect.y -= sy + _clSize
+ rect.width = size[0]
+ rowImg = self._CaptureImage(rect)
+ self.rowWin = RowDragWindow(self.grid,rowImg,row)
+ self.rowWin.Show(False)
+ self.lwin.CaptureMouse()
+ evt.Skip()
+
+ def OnRelease(self,evt):
+ if self.isDragging:
+ self.lwin.ReleaseMouse()
+ self.rowWin.Show(False)
+ self.isDragging = False
+
+ if not self.didMove:
+ py = self.lwin.ClientToScreenXY(0,self.startY)[1]
+ py = self.grid.ScreenToClientXY(0,py)[1]
+ sy = self.grid.GetViewStart()[1] * self.uy
+ sy -= self.grid.GetColLabelSize()
+ row = self.grid.YToRow(py + sy)
+
+ if row != wx.NOT_FOUND:
+ self.grid.SelectRow(row,evt.ControlDown())
+ return
+ else:
+ bRow = self.rowWin.GetInsertionRow()
+ dRow = self.rowWin.GetMoveRow()
+
+ wx.PostEvent(self,
+ GridRowMoveEvent(self.grid.GetId(), dRow, bRow))
+
+ self.rowWin.Destroy()
+ evt.Skip()
+
+ def _CaptureImage(self,rect):
+ bmp = wx.EmptyBitmap(rect.width,rect.height)
+ memdc = wx.MemoryDC()
+ memdc.SelectObject(bmp)
+ dc = wx.WindowDC(self.lwin)
+ memdc.Blit(0,0, rect.width, rect.height, dc, rect.x, rect.y)
+ memdc.SelectObject(wx.NullBitmap)
+ return bmp
+
+
+#----------------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/grids.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/grids.py
new file mode 100644
index 0000000..5adfc20
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/grids.py
@@ -0,0 +1,302 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.grids
+# Purpose: An example sizer derived from the C++ wxPySizer that
+# sizes items in a fixed or flexible grid.
+#
+# Author: Robin Dunn
+#
+# Created: 21-Sept-1999
+# RCS-ID: $Id$
+# Copyright: (c) 1999 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/07/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 Compatability changes
+#
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o In keeping with the common idiom, the sizers in this module
+# have been given the 'Py' prefix to avoid confusion with the
+# native sizers of the same name. However, the reverse renamer
+# still has the old wx*Sizer since the whole point of the
+# reverse renamer is backward compatability.
+# o wxGridSizer -> PyGridSizer
+# o wxFlexGridSizer -> PyFlexGridSizer
+# o Deprecation warning added.
+#
+
+"""
+In this module you will find PyGridSizer and PyFlexGridSizer. Please
+note that these sizers have since been ported to C++ (as wx.GridSizer
+and wx.FlexGridSizer) and those versions are now exposed in the regular
+wxPython wrappers. However I am also leaving them here in the library
+so they can serve as an example of how to implement sizers in Python.
+
+PyGridSizer: Sizes and positions items such that all rows are the same
+height and all columns are the same width. You can specify a gap in
+pixels to be used between the rows and/or the columns. When you
+create the sizer you specify the number of rows or the number of
+columns and then as you add items it figures out the other dimension
+automatically. Like other sizers, items can be set to fill their
+available space, or to be aligned on a side, in a corner, or in the
+center of the space. When the sizer is resized, all the items are
+resized the same amount so all rows and all columns remain the same
+size.
+
+PyFlexGridSizer: Derives from PyGridSizer and adds the ability for
+particular rows and/or columns to be marked as growable. This means
+that when the sizer changes size, the growable rows and colums are the
+ones that stretch. The others remain at their initial size.
+"""
+
+
+import operator
+import warnings
+import wx
+
+warningmsg = r"""\
+
+################################################\
+# THIS MODULE IS DEPRECATED |
+# |
+# You should use the native wx.GridSizer and |
+# wx.FlexGridSizer unless there is a compelling |
+# need to use this module. |
+################################################/
+
+
+"""
+
+warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
+
+
+#----------------------------------------------------------------------
+
+class PyGridSizer(wx.PySizer):
+ def __init__(self, rows=0, cols=0, hgap=0, vgap=0):
+ wx.PySizer.__init__(self)
+ if rows == 0 and cols == 0:
+ raise ValueError, "rows and cols cannot both be zero"
+
+ self.rows = rows
+ self.cols = cols
+ self.hgap = hgap
+ self.vgap = vgap
+
+
+ def SetRows(self, rows):
+ if rows == 0 and self.cols == 0:
+ raise ValueError, "rows and cols cannot both be zero"
+ self.rows = rows
+
+ def SetColumns(self, cols):
+ if self.rows == 0 and cols == 0:
+ raise ValueError, "rows and cols cannot both be zero"
+ self.cols = cols
+
+ def GetRows(self):
+ return self.rows
+
+ def GetColumns(self):
+ return self.cols
+
+ def SetHgap(self, hgap):
+ self.hgap = hgap
+
+ def SetVgap(self, vgap):
+ self.vgap = vgap
+
+ def GetHgap(self, hgap):
+ return self.hgap
+
+ def GetVgap(self, vgap):
+ return self.vgap
+
+ #--------------------------------------------------
+ def CalcMin(self):
+ items = self.GetChildren()
+ nitems = len(items)
+ nrows = self.rows
+ ncols = self.cols
+
+ if ncols > 0:
+ nrows = (nitems + ncols-1) / ncols
+ else:
+ ncols = (nitems + nrows-1) / nrows
+
+ # Find the max width and height for any component.
+ w = 0
+ h = 0
+ for item in items:
+ size = item.CalcMin()
+ w = max(w, size.width)
+ h = max(h, size.height)
+
+ return wx.Size(ncols * w + (ncols-1) * self.hgap,
+ nrows * h + (nrows-1) * self.vgap)
+
+
+ #--------------------------------------------------
+ def RecalcSizes(self):
+ items = self.GetChildren()
+ if not items:
+ return
+
+ nitems = len(items)
+ nrows = self.rows
+ ncols = self.cols
+
+ if ncols > 0:
+ nrows = (nitems + ncols-1) / ncols
+ else:
+ ncols = (nitems + nrows-1) / nrows
+
+
+ sz = self.GetSize()
+ pt = self.GetPosition()
+ w = (sz.width - (ncols - 1) * self.hgap) / ncols;
+ h = (sz.height - (nrows - 1) * self.vgap) / nrows;
+
+ x = pt.x
+ for c in range(ncols):
+ y = pt.y
+ for r in range(nrows):
+ i = r * ncols + c
+ if i < nitems:
+ self.SetItemBounds(items[i], x, y, w, h)
+
+ y = y + h + self.vgap
+
+ x = x + w + self.hgap
+
+
+ #--------------------------------------------------
+ def SetItemBounds(self, item, x, y, w, h):
+ # calculate the item's size and position within
+ # its grid cell
+ ipt = wx.Point(x, y)
+ isz = item.CalcMin()
+ flag = item.GetFlag()
+
+ if flag & wx.EXPAND or flag & wx.SHAPED:
+ isz = (w, h)
+ else:
+ if flag & wx.ALIGN_CENTER_HORIZONTAL:
+ ipt.x = x + (w - isz.width) / 2
+ elif flag & wx.ALIGN_RIGHT:
+ ipt.x = x + (w - isz.width)
+
+ if flag & wx.ALIGN_CENTER_VERTICAL:
+ ipt.y = y + (h - isz.height) / 2
+ elif flag & wx.ALIGN_BOTTOM:
+ ipt.y = y + (h - isz.height)
+
+ item.SetDimension(ipt, isz)
+
+
+#----------------------------------------------------------------------
+
+
+
+class PyFlexGridSizer(PyGridSizer):
+ def __init__(self, rows=0, cols=0, hgap=0, vgap=0):
+ PyGridSizer.__init__(self, rows, cols, hgap, vgap)
+ self.rowHeights = []
+ self.colWidths = []
+ self.growableRows = []
+ self.growableCols = []
+
+ def AddGrowableRow(self, idx):
+ self.growableRows.append(idx)
+
+ def AddGrowableCol(self, idx):
+ self.growableCols.append(idx)
+
+ #--------------------------------------------------
+ def CalcMin(self):
+ items = self.GetChildren()
+ nitems = len(items)
+ nrows = self.rows
+ ncols = self.cols
+
+ if ncols > 0:
+ nrows = (nitems + ncols-1) / ncols
+ else:
+ ncols = (nitems + nrows-1) / nrows
+
+ # Find the max width and height for any component.
+ self.rowHeights = [0] * nrows
+ self.colWidths = [0] * ncols
+
+ for i in range(len(items)):
+ size = items[i].CalcMin()
+ row = i / ncols
+ col = i % ncols
+ self.rowHeights[row] = max(size.height, self.rowHeights[row])
+ self.colWidths[col] = max(size.width, self.colWidths[col])
+
+ # Add up all the widths and heights
+ cellsWidth = reduce(operator.__add__, self.colWidths)
+ cellHeight = reduce(operator.__add__, self.rowHeights)
+
+ return wx.Size(cellsWidth + (ncols-1) * self.hgap,
+ cellHeight + (nrows-1) * self.vgap)
+
+
+ #--------------------------------------------------
+ def RecalcSizes(self):
+ items = self.GetChildren()
+ if not items:
+ return
+
+ nitems = len(items)
+ nrows = self.rows
+ ncols = self.cols
+
+ if ncols > 0:
+ nrows = (nitems + ncols-1) / ncols
+ else:
+ ncols = (nitems + nrows-1) / nrows
+
+ minsz = self.CalcMin()
+ sz = self.GetSize()
+ pt = self.GetPosition()
+
+ # Check for growables
+ if self.growableRows and sz.height > minsz.height:
+ delta = (sz.height - minsz.height) / len(self.growableRows)
+ for idx in self.growableRows:
+ self.rowHeights[idx] = self.rowHeights[idx] + delta
+
+ if self.growableCols and sz.width > minsz.width:
+ delta = (sz.width - minsz.width) / len(self.growableCols)
+ for idx in self.growableCols:
+ self.colWidths[idx] = self.colWidths[idx] + delta
+
+ # bottom right corner
+ sz = wx.Size(pt.x + sz.width, pt.y + sz.height)
+
+ # Layout each cell
+ x = pt.x
+ for c in range(ncols):
+ y = pt.y
+ for r in range(nrows):
+ i = r * ncols + c
+
+ if i < nitems:
+ w = max(0, min(self.colWidths[c], sz.width - x))
+ h = max(0, min(self.rowHeights[r], sz.height - y))
+ self.SetItemBounds(items[i], x, y, w, h)
+
+ y = y + self.rowHeights[r] + self.vgap
+
+ x = x + self.colWidths[c] + self.hgap
+
+#----------------------------------------------------------------------
+
+
+
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/hyperlink.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/hyperlink.py
new file mode 100644
index 0000000..dfc045c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/hyperlink.py
@@ -0,0 +1,13 @@
+# ============================================================== #
+# This is now just a stub, importing the real module which lives #
+# under wx.lib.agw.
+# ============================================================== #
+
+"""
+Attention! HyperLinkCtrl now lives in wx.lib.agw, together with
+its friends in the Advanced Generic Widgets family.
+
+Please update your code!
+"""
+
+from wx.lib.agw.hyperlink import * \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/iewin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/iewin.py
new file mode 100644
index 0000000..36dfe59
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/iewin.py
@@ -0,0 +1,250 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.iewin
+# Purpose: A class that allows the use of the IE web browser
+# ActiveX control
+#
+# Author: Robin Dunn
+#
+# Created: 22-March-2004
+# RCS-ID: $Id$
+# Copyright: (c) 2008 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import wx
+import wx.lib.activex
+import comtypes.client as cc
+
+import sys
+if not hasattr(sys, 'frozen'):
+ cc.GetModule('shdocvw.dll') # IWebBrowser2 and etc.
+from comtypes.gen import SHDocVw
+
+
+clsID = '{8856F961-340A-11D0-A96B-00C04FD705A2}'
+progID = 'Shell.Explorer.2'
+
+
+# Flags to be used with the RefreshPage method
+REFRESH_NORMAL = 0
+REFRESH_IFEXPIRED = 1
+REFRESH_CONTINUE = 2
+REFRESH_COMPLETELY = 3
+
+# Flags to be used with LoadUrl, Navigate, Navigate2 methods
+NAV_OpenInNewWindow = 0x1
+NAV_NoHistory = 0x2
+NAV_NoReadFromCache = 0x4
+NAV_NoWriteToCache = 0x8
+NAV_AllowAutosearch = 0x10
+NAV_BrowserBar = 0x20
+NAV_Hyperlink = 0x40
+NAV_EnforceRestricted = 0x80,
+NAV_NewWindowsManaged = 0x0100,
+NAV_UntrustedForDownload = 0x0200,
+NAV_TrustedForActiveX = 0x0400,
+NAV_OpenInNewTab = 0x0800,
+NAV_OpenInBackgroundTab = 0x1000,
+NAV_KeepWordWheelText = 0x2000
+
+
+#----------------------------------------------------------------------
+
+class IEHtmlWindow(wx.lib.activex.ActiveXCtrl):
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name='IEHtmlWindow'):
+ wx.lib.activex.ActiveXCtrl.__init__(self, parent, progID,
+ id, pos, size, style, name)
+
+ self._canGoBack = False
+ self._canGoForward = False
+
+
+ def LoadString(self, html):
+ """Load the html document from a string"""
+ if self.ctrl.Document is None:
+ self.LoadUrl('about:blank')
+ doc = self.ctrl.Document
+ doc.write(html)
+ doc.close()
+
+
+ def LoadStream(self, stream):
+ """
+ Load the html document from a Python file-like object.
+ """
+ if self.ctrl.Document is None:
+ self.LoadUrl('about:blank')
+ doc = self.ctrl.Document
+ for line in stream:
+ doc.write(line)
+ doc.close()
+
+
+ def LoadUrl(self, URL, Flags=0):
+ """Load the document from url."""
+ return self.ctrl.Navigate2(URL, Flags)
+
+
+ def GetStringSelection(self, asHTML=True):
+ """
+ Returns the contents of the selected portion of the document as
+ either html or plain text.
+ """
+ if self.ctrl.Document is None:
+ return ""
+ if not hasattr(sys, 'frozen'): cc.GetModule('mshtml.tlb')
+ from comtypes.gen import MSHTML
+ doc = self.ctrl.Document.QueryInterface(MSHTML.IHTMLDocument2)
+ sel = doc.selection
+ range = sel.createRange()
+ if asHTML:
+ return range.htmlText
+ else:
+ return range.text
+
+
+ def GetText(self, asHTML=True):
+ """
+ Returns the contents of the the html document as either html or plain text.
+ """
+ if self.ctrl.Document is None:
+ return ""
+ if not hasattr(sys, 'frozen'): cc.GetModule('mshtml.tlb')
+ from comtypes.gen import MSHTML
+ doc = self.ctrl.Document.QueryInterface(MSHTML.IHTMLDocument2)
+ if not asHTML:
+ # if just fetching the text then get it from the body property
+ return doc.body.innerText
+
+ # otherwise look in the all property
+ for idx in range(doc.all.length):
+ # the first item with content should be the <html> tag and all its
+ # children.
+ item = doc.all.item(idx)
+ if item is None:
+ continue
+ return item.outerHTML
+ return ""
+
+
+ def Print(self, showDialog=False):
+ if showDialog:
+ prompt = SHDocVw.OLECMDEXECOPT_PROMPTUSER
+ else:
+ prompt = SHDocVw.OLECMDEXECOPT_DONTPROMPTUSER
+ self.ctrl.ExecWB(SHDocVw.OLECMDID_PRINT, prompt)
+
+
+ def PrintPreview(self):
+ self.ctrl.ExecWB( SHDocVw.OLECMDID_PRINTPREVIEW,
+ SHDocVw.OLECMDEXECOPT_DODEFAULT)
+
+
+
+ def GoBack(self):
+ if self.CanGoBack():
+ return self.ctrl.GoBack()
+
+ def GoForward(self):
+ if self.CanGoForward():
+ return self.ctrl.GoForward()
+
+ def CanGoBack(self):
+ return self._canGoBack
+
+ def CanGoForward(self):
+ return self._canGoForward
+
+ def GoHome(self):
+ return self.ctrl.GoHome()
+
+ def GoSearch(self):
+ return self.ctrl.GoSearch()
+
+ def Navigate(self, URL, Flags=0, TargetFrameName=None, PostData=None, Headers=None):
+ return self.ctrl.Navigate2( URL, Flags, TargetFrameName, PostData, Headers)
+
+ def RefreshPage(self, Level=REFRESH_NORMAL):
+ return self.ctrl.Refresh2(Level)
+
+ def Stop(self):
+ return self.ctrl.Stop()
+
+ def Quit(self):
+ return self.ctrl.Quit()
+
+
+ # COM Event handlers
+ def CommandStateChange(self, this, command, enable):
+ # watch the command states to know when it is possible to use
+ # GoBack or GoForward
+ if command == SHDocVw.CSC_NAVIGATEFORWARD:
+ self._canGoForward = enable
+ if command == SHDocVw.CSC_NAVIGATEBACK:
+ self._canGoBack = enable
+
+
+ # Getters, Setters and properties
+ def _get_Busy(self):
+ return self.ctrl.Busy
+ busy = property(_get_Busy, None)
+
+ def _get_Document(self):
+ return self.ctrl.Document
+ document = property(_get_Document, None)
+
+ def _get_LocationName(self):
+ return self.ctrl.LocationName
+ locationname = property(_get_LocationName, None)
+
+ def _get_LocationURL(self):
+ return self.ctrl.LocationURL
+ locationurl = property(_get_LocationURL, None)
+
+ def _get_ReadyState(self):
+ return self.ctrl.ReadyState
+ readystate = property(_get_ReadyState, None)
+
+ def _get_Offline(self):
+ return self.ctrl.Offline
+ def _set_Offline(self, Offline):
+ self.ctrl.Offline = Offline
+ offline = property(_get_Offline, _set_Offline)
+
+ def _get_Silent(self):
+ return self.ctrl.Silent
+ def _set_Silent(self, Silent):
+ self.ctrl.Silent = Silent
+ silent = property(_get_Silent, _set_Silent)
+
+ def _get_RegisterAsBrowser(self):
+ return self.ctrl.RegisterAsBrowser
+ def _set_RegisterAsBrowser(self, RegisterAsBrowser):
+ self.ctrl.RegisterAsBrowser = RegisterAsBrowser
+ registerasbrowser = property(_get_RegisterAsBrowser, _set_RegisterAsBrowser)
+
+ def _get_RegisterAsDropTarget(self):
+ return self.ctrl.RegisterAsDropTarget
+ def _set_RegisterAsDropTarget(self, RegisterAsDropTarget):
+ self.ctrl.RegisterAsDropTarget = RegisterAsDropTarget
+ registerasdroptarget = property(_get_RegisterAsDropTarget, _set_RegisterAsDropTarget)
+
+ def _get_Type(self):
+ return self.ctrl.Type
+ type = property(_get_Type, None)
+
+
+
+if __name__ == '__main__':
+ app = wx.App(False)
+ frm = wx.Frame(None, title="AX Test Window")
+
+ ie = IEHtmlWindow(frm)
+
+ frm.Show()
+ import wx.lib.inspection
+ wx.lib.inspection.InspectionTool().Show()
+ app.MainLoop()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/iewin_old.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/iewin_old.py
new file mode 100644
index 0000000..5380285
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/iewin_old.py
@@ -0,0 +1,895 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.iewin
+# Purpose: A class that allows the use of the IE web browser
+# ActiveX control
+#
+# Author: Robin Dunn
+#
+# Created: 22-March-2004
+# RCS-ID: $Id: iewin.py 41669 2006-10-06 23:21:07Z RD $
+# Copyright: (c) 2004 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+# This module was originally generated by the
+# wx.activex.GernerateAXModule class but has been tweaked somewhat as
+# indicated below.
+
+import wx
+import wx.activex
+
+clsID = '{8856F961-340A-11D0-A96B-00C04FD705A2}'
+progID = 'Shell.Explorer.2'
+
+
+# Flags to be used with the RefreshPage method
+REFRESH_NORMAL = 0
+REFRESH_IFEXPIRED = 1
+REFRESH_CONTINUE = 2
+REFRESH_COMPLETELY = 3
+
+# Flags to be used with LoadUrl, Navigate, Navigate2 methods
+NAV_OpenInNewWindow = 0x1
+NAV_NoHistory = 0x2
+NAV_NoReadFromCache = 0x4
+NAV_NoWriteToCache = 0x8
+NAV_AllowAutosearch = 0x10
+NAV_BrowserBar = 0x20
+NAV_Hyperlink = 0x40
+
+
+
+# Create eventTypes and event binders
+wxEVT_StatusTextChange = wx.activex.RegisterActiveXEvent('StatusTextChange')
+wxEVT_ProgressChange = wx.activex.RegisterActiveXEvent('ProgressChange')
+wxEVT_CommandStateChange = wx.activex.RegisterActiveXEvent('CommandStateChange')
+wxEVT_DownloadBegin = wx.activex.RegisterActiveXEvent('DownloadBegin')
+wxEVT_DownloadComplete = wx.activex.RegisterActiveXEvent('DownloadComplete')
+wxEVT_TitleChange = wx.activex.RegisterActiveXEvent('TitleChange')
+wxEVT_PropertyChange = wx.activex.RegisterActiveXEvent('PropertyChange')
+wxEVT_BeforeNavigate2 = wx.activex.RegisterActiveXEvent('BeforeNavigate2')
+wxEVT_NewWindow2 = wx.activex.RegisterActiveXEvent('NewWindow2')
+wxEVT_NavigateComplete2 = wx.activex.RegisterActiveXEvent('NavigateComplete2')
+wxEVT_DocumentComplete = wx.activex.RegisterActiveXEvent('DocumentComplete')
+wxEVT_Quit = wx.activex.RegisterActiveXEvent('OnQuit')
+wxEVT_Visible = wx.activex.RegisterActiveXEvent('OnVisible')
+wxEVT_ToolBar = wx.activex.RegisterActiveXEvent('OnToolBar')
+wxEVT_MenuBar = wx.activex.RegisterActiveXEvent('OnMenuBar')
+wxEVT_StatusBar = wx.activex.RegisterActiveXEvent('OnStatusBar')
+wxEVT_FullScreen = wx.activex.RegisterActiveXEvent('OnFullScreen')
+wxEVT_TheaterMode = wx.activex.RegisterActiveXEvent('OnTheaterMode')
+wxEVT_WindowSetResizable = wx.activex.RegisterActiveXEvent('WindowSetResizable')
+wxEVT_WindowSetLeft = wx.activex.RegisterActiveXEvent('WindowSetLeft')
+wxEVT_WindowSetTop = wx.activex.RegisterActiveXEvent('WindowSetTop')
+wxEVT_WindowSetWidth = wx.activex.RegisterActiveXEvent('WindowSetWidth')
+wxEVT_WindowSetHeight = wx.activex.RegisterActiveXEvent('WindowSetHeight')
+wxEVT_WindowClosing = wx.activex.RegisterActiveXEvent('WindowClosing')
+wxEVT_ClientToHostWindow = wx.activex.RegisterActiveXEvent('ClientToHostWindow')
+wxEVT_SetSecureLockIcon = wx.activex.RegisterActiveXEvent('SetSecureLockIcon')
+wxEVT_FileDownload = wx.activex.RegisterActiveXEvent('FileDownload')
+wxEVT_NavigateError = wx.activex.RegisterActiveXEvent('NavigateError')
+wxEVT_PrintTemplateInstantiation = wx.activex.RegisterActiveXEvent('PrintTemplateInstantiation')
+wxEVT_PrintTemplateTeardown = wx.activex.RegisterActiveXEvent('PrintTemplateTeardown')
+wxEVT_UpdatePageStatus = wx.activex.RegisterActiveXEvent('UpdatePageStatus')
+wxEVT_PrivacyImpactedStateChange = wx.activex.RegisterActiveXEvent('PrivacyImpactedStateChange')
+
+EVT_StatusTextChange = wx.PyEventBinder(wxEVT_StatusTextChange, 1)
+EVT_ProgressChange = wx.PyEventBinder(wxEVT_ProgressChange, 1)
+EVT_CommandStateChange = wx.PyEventBinder(wxEVT_CommandStateChange, 1)
+EVT_DownloadBegin = wx.PyEventBinder(wxEVT_DownloadBegin, 1)
+EVT_DownloadComplete = wx.PyEventBinder(wxEVT_DownloadComplete, 1)
+EVT_TitleChange = wx.PyEventBinder(wxEVT_TitleChange, 1)
+EVT_PropertyChange = wx.PyEventBinder(wxEVT_PropertyChange, 1)
+EVT_BeforeNavigate2 = wx.PyEventBinder(wxEVT_BeforeNavigate2, 1)
+EVT_NewWindow2 = wx.PyEventBinder(wxEVT_NewWindow2, 1)
+EVT_NavigateComplete2 = wx.PyEventBinder(wxEVT_NavigateComplete2, 1)
+EVT_DocumentComplete = wx.PyEventBinder(wxEVT_DocumentComplete, 1)
+EVT_Quit = wx.PyEventBinder(wxEVT_Quit, 1)
+EVT_Visible = wx.PyEventBinder(wxEVT_Visible, 1)
+EVT_ToolBar = wx.PyEventBinder(wxEVT_ToolBar, 1)
+EVT_MenuBar = wx.PyEventBinder(wxEVT_MenuBar, 1)
+EVT_StatusBar = wx.PyEventBinder(wxEVT_StatusBar, 1)
+EVT_FullScreen = wx.PyEventBinder(wxEVT_FullScreen, 1)
+EVT_TheaterMode = wx.PyEventBinder(wxEVT_TheaterMode, 1)
+EVT_WindowSetResizable = wx.PyEventBinder(wxEVT_WindowSetResizable, 1)
+EVT_WindowSetLeft = wx.PyEventBinder(wxEVT_WindowSetLeft, 1)
+EVT_WindowSetTop = wx.PyEventBinder(wxEVT_WindowSetTop, 1)
+EVT_WindowSetWidth = wx.PyEventBinder(wxEVT_WindowSetWidth, 1)
+EVT_WindowSetHeight = wx.PyEventBinder(wxEVT_WindowSetHeight, 1)
+EVT_WindowClosing = wx.PyEventBinder(wxEVT_WindowClosing, 1)
+EVT_ClientToHostWindow = wx.PyEventBinder(wxEVT_ClientToHostWindow, 1)
+EVT_SetSecureLockIcon = wx.PyEventBinder(wxEVT_SetSecureLockIcon, 1)
+EVT_FileDownload = wx.PyEventBinder(wxEVT_FileDownload, 1)
+EVT_NavigateError = wx.PyEventBinder(wxEVT_NavigateError, 1)
+EVT_PrintTemplateInstantiation = wx.PyEventBinder(wxEVT_PrintTemplateInstantiation, 1)
+EVT_PrintTemplateTeardown = wx.PyEventBinder(wxEVT_PrintTemplateTeardown, 1)
+EVT_UpdatePageStatus = wx.PyEventBinder(wxEVT_UpdatePageStatus, 1)
+EVT_PrivacyImpactedStateChange = wx.PyEventBinder(wxEVT_PrivacyImpactedStateChange, 1)
+
+
+# For this there are a few special methods implemented in C++ in the
+# IEHtmlWindowBase class, so derive from it instead of ActiveXWindow.
+class IEHtmlWindow(wx.activex.IEHtmlWindowBase):
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name='IEHtmlWindow', ID=-1):
+ # in case the old 'ID' param is used as a keyword
+ if ID != -1:
+ id = ID
+
+ wx.activex.IEHtmlWindowBase.__init__(self, parent,
+ wx.activex.CLSID('{8856F961-340A-11D0-A96B-00C04FD705A2}'),
+ id, pos, size, style, name)
+
+
+ # Methods from IEHtmlWindowBase. Redirected from here just for
+ # the sake of completeness...
+ def LoadString(self, html):
+ """Load the html document from a string"""
+ return wx.activex.IEHtmlWindowBase.LoadString(self, html)
+
+
+ def LoadStream(self, stream):
+ """
+ Load the html document from a wx.InputStream or a Python
+ file-like object.
+ """
+ return wx.activex.IEHtmlWindowBase.LoadStream(self, stream)
+
+
+ def LoadUrl(self, URL, Flags=0):
+ """Load the document from url."""
+ return self.Navigate2(URL, Flags)
+
+
+ def GetStringSelection(self, asHTML=True):
+ """
+ Returns the contents of the selected portion of the document as
+ either html or plain text.
+ """
+ return wx.activex.IEHtmlWindowBase.GetStringSelection(self, asHTML)
+
+
+ def GetText(self, asHTML=True):
+ """
+ Returns the contents of the the html document as either html or plain text.
+ """
+ return wx.activex.IEHtmlWindowBase.GetText(self, asHTML)
+
+
+ def SetCharset(self, charset):
+ """"""
+ return wx.activex.IEHtmlWindowBase.SetCharset(self, charset)
+
+
+ # Methods exported by the ActiveX object
+ def QueryInterface(self, riid):
+ return self.CallAXMethod('QueryInterface', riid)
+
+ def AddRef(self):
+ return self.CallAXMethod('AddRef')
+
+ def Release(self):
+ return self.CallAXMethod('Release')
+
+ def GetTypeInfoCount(self):
+ return self.CallAXMethod('GetTypeInfoCount')
+
+ def GetTypeInfo(self, itinfo, lcid):
+ return self.CallAXMethod('GetTypeInfo', itinfo, lcid)
+
+ def GetIDsOfNames(self, riid, rgszNames, cNames, lcid):
+ return self.CallAXMethod('GetIDsOfNames', riid, rgszNames, cNames, lcid)
+
+ def Invoke(self, dispidMember, riid, lcid, wFlags, pdispparams):
+ return self.CallAXMethod('Invoke', dispidMember, riid, lcid, wFlags, pdispparams)
+
+ def GoBack(self):
+ return self.CallAXMethod('GoBack')
+
+ def GoForward(self):
+ return self.CallAXMethod('GoForward')
+
+ def GoHome(self):
+ return self.CallAXMethod('GoHome')
+
+ def GoSearch(self):
+ return self.CallAXMethod('GoSearch')
+
+ # added default for Flags
+ def Navigate(self, URL, Flags=0, TargetFrameName=None, PostData=None, Headers=None):
+ return self.CallAXMethod('Navigate', URL, Flags, TargetFrameName, PostData, Headers)
+
+ # Removed to prevent conflict with wx.Window.Refresh
+ #def Refresh(self):
+ # return self.CallAXMethod('Refresh')
+
+ # renamed
+ def RefreshPage(self, Level=REFRESH_NORMAL):
+ return self.CallAXMethod('Refresh2', Level)
+
+ def Stop(self):
+ return self.CallAXMethod('Stop')
+
+ def Quit(self):
+ return self.CallAXMethod('Quit')
+
+ def ClientToWindow(self, pcx, pcy):
+ return self.CallAXMethod('ClientToWindow', pcx, pcy)
+
+ def PutProperty(self, Property, vtValue):
+ return self.CallAXMethod('PutProperty', Property, vtValue)
+
+ def GetProperty(self, Property):
+ return self.CallAXMethod('GetProperty', Property)
+
+ # added default for flags
+ def Navigate2(self, URL, Flags=0, TargetFrameName=None, PostData=None, Headers=None):
+ return self.CallAXMethod('Navigate2', URL, Flags, TargetFrameName, PostData, Headers)
+
+ def QueryStatusWB(self, cmdID):
+ return self.CallAXMethod('QueryStatusWB', cmdID)
+
+ def ExecWB(self, cmdID, cmdexecopt, pvaIn, pvaOut=None):
+ return self.CallAXMethod('ExecWB', cmdID, cmdexecopt, pvaIn, pvaOut)
+
+ def ShowBrowserBar(self, pvaClsid, pvarShow, pvarSize=None):
+ return self.CallAXMethod('ShowBrowserBar', pvaClsid, pvarShow, pvarSize)
+
+ # Getters, Setters and properties
+ def _get_Application(self):
+ return self.GetAXProp('Application')
+ application = property(_get_Application, None)
+
+ def _get_Parent(self):
+ return self.GetAXProp('Parent')
+ parent = property(_get_Parent, None)
+
+ def _get_Container(self):
+ return self.GetAXProp('Container')
+ container = property(_get_Container, None)
+
+ def _get_Document(self):
+ return self.GetAXProp('Document')
+ document = property(_get_Document, None)
+
+ def _get_TopLevelContainer(self):
+ return self.GetAXProp('TopLevelContainer')
+ toplevelcontainer = property(_get_TopLevelContainer, None)
+
+ def _get_Type(self):
+ return self.GetAXProp('Type')
+ type = property(_get_Type, None)
+
+ def _get_Left(self):
+ return self.GetAXProp('Left')
+ def _set_Left(self, Left):
+ self.SetAXProp('Left', Left)
+ left = property(_get_Left, _set_Left)
+
+ def _get_Top(self):
+ return self.GetAXProp('Top')
+ def _set_Top(self, Top):
+ self.SetAXProp('Top', Top)
+ top = property(_get_Top, _set_Top)
+
+ def _get_Width(self):
+ return self.GetAXProp('Width')
+ def _set_Width(self, Width):
+ self.SetAXProp('Width', Width)
+ width = property(_get_Width, _set_Width)
+
+ def _get_Height(self):
+ return self.GetAXProp('Height')
+ def _set_Height(self, Height):
+ self.SetAXProp('Height', Height)
+ height = property(_get_Height, _set_Height)
+
+ def _get_LocationName(self):
+ return self.GetAXProp('LocationName')
+ locationname = property(_get_LocationName, None)
+
+ def _get_LocationURL(self):
+ return self.GetAXProp('LocationURL')
+ locationurl = property(_get_LocationURL, None)
+
+ def _get_Busy(self):
+ return self.GetAXProp('Busy')
+ busy = property(_get_Busy, None)
+
+ def _get_Name(self):
+ return self.GetAXProp('Name')
+ name = property(_get_Name, None)
+
+ def _get_HWND(self):
+ return self.GetAXProp('HWND')
+ hwnd = property(_get_HWND, None)
+
+ def _get_FullName(self):
+ return self.GetAXProp('FullName')
+ fullname = property(_get_FullName, None)
+
+ def _get_Path(self):
+ return self.GetAXProp('Path')
+ path = property(_get_Path, None)
+
+ def _get_Visible(self):
+ return self.GetAXProp('Visible')
+ def _set_Visible(self, Visible):
+ self.SetAXProp('Visible', Visible)
+ visible = property(_get_Visible, _set_Visible)
+
+ def _get_StatusBar(self):
+ return self.GetAXProp('StatusBar')
+ def _set_StatusBar(self, StatusBar):
+ self.SetAXProp('StatusBar', StatusBar)
+ statusbar = property(_get_StatusBar, _set_StatusBar)
+
+ def _get_StatusText(self):
+ return self.GetAXProp('StatusText')
+ def _set_StatusText(self, StatusText):
+ self.SetAXProp('StatusText', StatusText)
+ statustext = property(_get_StatusText, _set_StatusText)
+
+ def _get_ToolBar(self):
+ return self.GetAXProp('ToolBar')
+ def _set_ToolBar(self, ToolBar):
+ self.SetAXProp('ToolBar', ToolBar)
+ toolbar = property(_get_ToolBar, _set_ToolBar)
+
+ def _get_MenuBar(self):
+ return self.GetAXProp('MenuBar')
+ def _set_MenuBar(self, MenuBar):
+ self.SetAXProp('MenuBar', MenuBar)
+ menubar = property(_get_MenuBar, _set_MenuBar)
+
+ def _get_FullScreen(self):
+ return self.GetAXProp('FullScreen')
+ def _set_FullScreen(self, FullScreen):
+ self.SetAXProp('FullScreen', FullScreen)
+ fullscreen = property(_get_FullScreen, _set_FullScreen)
+
+ def _get_ReadyState(self):
+ return self.GetAXProp('ReadyState')
+ readystate = property(_get_ReadyState, None)
+
+ def _get_Offline(self):
+ return self.GetAXProp('Offline')
+ def _set_Offline(self, Offline):
+ self.SetAXProp('Offline', Offline)
+ offline = property(_get_Offline, _set_Offline)
+
+ def _get_Silent(self):
+ return self.GetAXProp('Silent')
+ def _set_Silent(self, Silent):
+ self.SetAXProp('Silent', Silent)
+ silent = property(_get_Silent, _set_Silent)
+
+ def _get_RegisterAsBrowser(self):
+ return self.GetAXProp('RegisterAsBrowser')
+ def _set_RegisterAsBrowser(self, RegisterAsBrowser):
+ self.SetAXProp('RegisterAsBrowser', RegisterAsBrowser)
+ registerasbrowser = property(_get_RegisterAsBrowser, _set_RegisterAsBrowser)
+
+ def _get_RegisterAsDropTarget(self):
+ return self.GetAXProp('RegisterAsDropTarget')
+ def _set_RegisterAsDropTarget(self, RegisterAsDropTarget):
+ self.SetAXProp('RegisterAsDropTarget', RegisterAsDropTarget)
+ registerasdroptarget = property(_get_RegisterAsDropTarget, _set_RegisterAsDropTarget)
+
+ def _get_TheaterMode(self):
+ return self.GetAXProp('TheaterMode')
+ def _set_TheaterMode(self, TheaterMode):
+ self.SetAXProp('TheaterMode', TheaterMode)
+ theatermode = property(_get_TheaterMode, _set_TheaterMode)
+
+ def _get_AddressBar(self):
+ return self.GetAXProp('AddressBar')
+ def _set_AddressBar(self, AddressBar):
+ self.SetAXProp('AddressBar', AddressBar)
+ addressbar = property(_get_AddressBar, _set_AddressBar)
+
+ def _get_Resizable(self):
+ return self.GetAXProp('Resizable')
+ def _set_Resizable(self, Resizable):
+ self.SetAXProp('Resizable', Resizable)
+ resizable = property(_get_Resizable, _set_Resizable)
+
+
+# PROPERTIES
+# --------------------
+# application
+# type:VT_DISPATCH arg:VT_EMPTY canGet:True canSet:False
+#
+# parent
+# type:VT_DISPATCH arg:VT_EMPTY canGet:True canSet:False
+#
+# container
+# type:VT_DISPATCH arg:VT_EMPTY canGet:True canSet:False
+#
+# document
+# type:VT_DISPATCH arg:VT_EMPTY canGet:True canSet:False
+#
+# toplevelcontainer
+# type:bool arg:VT_EMPTY canGet:True canSet:False
+#
+# type
+# type:string arg:VT_EMPTY canGet:True canSet:False
+#
+# left
+# type:int arg:int canGet:True canSet:True
+#
+# top
+# type:int arg:int canGet:True canSet:True
+#
+# width
+# type:int arg:int canGet:True canSet:True
+#
+# height
+# type:int arg:int canGet:True canSet:True
+#
+# locationname
+# type:string arg:VT_EMPTY canGet:True canSet:False
+#
+# locationurl
+# type:string arg:VT_EMPTY canGet:True canSet:False
+#
+# busy
+# type:bool arg:VT_EMPTY canGet:True canSet:False
+#
+# name
+# type:string arg:VT_EMPTY canGet:True canSet:False
+#
+# hwnd
+# type:int arg:VT_EMPTY canGet:True canSet:False
+#
+# fullname
+# type:string arg:VT_EMPTY canGet:True canSet:False
+#
+# path
+# type:string arg:VT_EMPTY canGet:True canSet:False
+#
+# visible
+# type:bool arg:bool canGet:True canSet:True
+#
+# statusbar
+# type:bool arg:bool canGet:True canSet:True
+#
+# statustext
+# type:string arg:string canGet:True canSet:True
+#
+# toolbar
+# type:int arg:int canGet:True canSet:True
+#
+# menubar
+# type:bool arg:bool canGet:True canSet:True
+#
+# fullscreen
+# type:bool arg:bool canGet:True canSet:True
+#
+# readystate
+# type:unsupported type 29 arg:VT_EMPTY canGet:True canSet:False
+#
+# offline
+# type:bool arg:bool canGet:True canSet:True
+#
+# silent
+# type:bool arg:bool canGet:True canSet:True
+#
+# registerasbrowser
+# type:bool arg:bool canGet:True canSet:True
+#
+# registerasdroptarget
+# type:bool arg:bool canGet:True canSet:True
+#
+# theatermode
+# type:bool arg:bool canGet:True canSet:True
+#
+# addressbar
+# type:bool arg:bool canGet:True canSet:True
+#
+# resizable
+# type:bool arg:bool canGet:True canSet:True
+#
+#
+#
+#
+# METHODS
+# --------------------
+# QueryInterface
+# retType: VT_VOID
+# params:
+# riid
+# in:True out:False optional:False type:unsupported type 29
+# ppvObj
+# in:False out:True optional:False type:unsupported type 26
+#
+# AddRef
+# retType: int
+#
+# Release
+# retType: int
+#
+# GetTypeInfoCount
+# retType: VT_VOID
+# params:
+# pctinfo
+# in:False out:True optional:False type:int
+#
+# GetTypeInfo
+# retType: VT_VOID
+# params:
+# itinfo
+# in:True out:False optional:False type:int
+# lcid
+# in:True out:False optional:False type:int
+# pptinfo
+# in:False out:True optional:False type:unsupported type 26
+#
+# GetIDsOfNames
+# retType: VT_VOID
+# params:
+# riid
+# in:True out:False optional:False type:unsupported type 29
+# rgszNames
+# in:True out:False optional:False type:unsupported type 26
+# cNames
+# in:True out:False optional:False type:int
+# lcid
+# in:True out:False optional:False type:int
+# rgdispid
+# in:False out:True optional:False type:int
+#
+# Invoke
+# retType: VT_VOID
+# params:
+# dispidMember
+# in:True out:False optional:False type:int
+# riid
+# in:True out:False optional:False type:unsupported type 29
+# lcid
+# in:True out:False optional:False type:int
+# wFlags
+# in:True out:False optional:False type:int
+# pdispparams
+# in:True out:False optional:False type:unsupported type 29
+# pvarResult
+# in:False out:True optional:False type:VT_VARIANT
+# pexcepinfo
+# in:False out:True optional:False type:unsupported type 29
+# puArgErr
+# in:False out:True optional:False type:int
+#
+# GoBack
+# retType: VT_VOID
+#
+# GoForward
+# retType: VT_VOID
+#
+# GoHome
+# retType: VT_VOID
+#
+# GoSearch
+# retType: VT_VOID
+#
+# Navigate
+# retType: VT_VOID
+# params:
+# URL
+# in:True out:False optional:False type:string
+# Flags
+# in:True out:False optional:False type:VT_VARIANT
+# TargetFrameName
+# in:True out:False optional:True type:VT_VARIANT
+# PostData
+# in:True out:False optional:True type:VT_VARIANT
+# Headers
+# in:True out:False optional:True type:VT_VARIANT
+#
+# Refresh
+# retType: VT_VOID
+#
+# Refresh2
+# retType: VT_VOID
+# params:
+# Level
+# in:True out:False optional:False type:VT_VARIANT
+#
+# Stop
+# retType: VT_VOID
+#
+# Quit
+# retType: VT_VOID
+#
+# ClientToWindow
+# retType: VT_VOID
+# params:
+# pcx
+# in:True out:True optional:False type:int
+# pcy
+# in:True out:True optional:False type:int
+#
+# PutProperty
+# retType: VT_VOID
+# params:
+# Property
+# in:True out:False optional:False type:string
+# vtValue
+# in:True out:False optional:False type:VT_VARIANT
+#
+# GetProperty
+# retType: VT_VARIANT
+# params:
+# Property
+# in:True out:False optional:False type:string
+#
+# Navigate2
+# retType: VT_VOID
+# params:
+# URL
+# in:True out:False optional:False type:VT_VARIANT
+# Flags
+# in:True out:False optional:False type:VT_VARIANT
+# TargetFrameName
+# in:True out:False optional:True type:VT_VARIANT
+# PostData
+# in:True out:False optional:True type:VT_VARIANT
+# Headers
+# in:True out:False optional:True type:VT_VARIANT
+#
+# QueryStatusWB
+# retType: unsupported type 29
+# params:
+# cmdID
+# in:True out:False optional:False type:unsupported type 29
+#
+# ExecWB
+# retType: VT_VOID
+# params:
+# cmdID
+# in:True out:False optional:False type:unsupported type 29
+# cmdexecopt
+# in:True out:False optional:False type:unsupported type 29
+# pvaIn
+# in:True out:False optional:False type:VT_VARIANT
+# pvaOut
+# in:True out:True optional:True type:VT_VARIANT
+#
+# ShowBrowserBar
+# retType: VT_VOID
+# params:
+# pvaClsid
+# in:True out:False optional:False type:VT_VARIANT
+# pvarShow
+# in:True out:False optional:False type:VT_VARIANT
+# pvarSize
+# in:True out:False optional:True type:VT_VARIANT
+#
+#
+#
+#
+# EVENTS
+# --------------------
+# StatusTextChange
+# retType: VT_VOID
+# params:
+# Text
+# in:True out:False optional:False type:string
+#
+# ProgressChange
+# retType: VT_VOID
+# params:
+# Progress
+# in:True out:False optional:False type:int
+# ProgressMax
+# in:True out:False optional:False type:int
+#
+# CommandStateChange
+# retType: VT_VOID
+# params:
+# Command
+# in:True out:False optional:False type:int
+# Enable
+# in:True out:False optional:False type:bool
+#
+# DownloadBegin
+# retType: VT_VOID
+#
+# DownloadComplete
+# retType: VT_VOID
+#
+# TitleChange
+# retType: VT_VOID
+# params:
+# Text
+# in:True out:False optional:False type:string
+#
+# PropertyChange
+# retType: VT_VOID
+# params:
+# szProperty
+# in:True out:False optional:False type:string
+#
+# BeforeNavigate2
+# retType: VT_VOID
+# params:
+# pDisp
+# in:True out:False optional:False type:VT_DISPATCH
+# URL
+# in:True out:False optional:False type:VT_VARIANT
+# Flags
+# in:True out:False optional:False type:VT_VARIANT
+# TargetFrameName
+# in:True out:False optional:False type:VT_VARIANT
+# PostData
+# in:True out:False optional:False type:VT_VARIANT
+# Headers
+# in:True out:False optional:False type:VT_VARIANT
+# Cancel
+# in:True out:True optional:False type:bool
+#
+# NewWindow2
+# retType: VT_VOID
+# params:
+# ppDisp
+# in:True out:True optional:False type:VT_DISPATCH
+# Cancel
+# in:True out:True optional:False type:bool
+#
+# NavigateComplete2
+# retType: VT_VOID
+# params:
+# pDisp
+# in:True out:False optional:False type:VT_DISPATCH
+# URL
+# in:True out:False optional:False type:VT_VARIANT
+#
+# DocumentComplete
+# retType: VT_VOID
+# params:
+# pDisp
+# in:True out:False optional:False type:VT_DISPATCH
+# URL
+# in:True out:False optional:False type:VT_VARIANT
+#
+# Quit
+# retType: VT_VOID
+#
+# Visible
+# retType: VT_VOID
+# params:
+# Visible
+# in:True out:False optional:False type:bool
+#
+# ToolBar
+# retType: VT_VOID
+# params:
+# ToolBar
+# in:True out:False optional:False type:bool
+#
+# MenuBar
+# retType: VT_VOID
+# params:
+# MenuBar
+# in:True out:False optional:False type:bool
+#
+# StatusBar
+# retType: VT_VOID
+# params:
+# StatusBar
+# in:True out:False optional:False type:bool
+#
+# FullScreen
+# retType: VT_VOID
+# params:
+# FullScreen
+# in:True out:False optional:False type:bool
+#
+# TheaterMode
+# retType: VT_VOID
+# params:
+# TheaterMode
+# in:True out:False optional:False type:bool
+#
+# WindowSetResizable
+# retType: VT_VOID
+# params:
+# Resizable
+# in:True out:False optional:False type:bool
+#
+# WindowSetLeft
+# retType: VT_VOID
+# params:
+# Left
+# in:True out:False optional:False type:int
+#
+# WindowSetTop
+# retType: VT_VOID
+# params:
+# Top
+# in:True out:False optional:False type:int
+#
+# WindowSetWidth
+# retType: VT_VOID
+# params:
+# Width
+# in:True out:False optional:False type:int
+#
+# WindowSetHeight
+# retType: VT_VOID
+# params:
+# Height
+# in:True out:False optional:False type:int
+#
+# WindowClosing
+# retType: VT_VOID
+# params:
+# IsChildWindow
+# in:True out:False optional:False type:bool
+# Cancel
+# in:True out:True optional:False type:bool
+#
+# ClientToHostWindow
+# retType: VT_VOID
+# params:
+# CX
+# in:True out:True optional:False type:int
+# CY
+# in:True out:True optional:False type:int
+#
+# SetSecureLockIcon
+# retType: VT_VOID
+# params:
+# SecureLockIcon
+# in:True out:False optional:False type:int
+#
+# FileDownload
+# retType: VT_VOID
+# params:
+# Cancel
+# in:True out:True optional:False type:bool
+#
+# NavigateError
+# retType: VT_VOID
+# params:
+# pDisp
+# in:True out:False optional:False type:VT_DISPATCH
+# URL
+# in:True out:False optional:False type:VT_VARIANT
+# Frame
+# in:True out:False optional:False type:VT_VARIANT
+# StatusCode
+# in:True out:False optional:False type:VT_VARIANT
+# Cancel
+# in:True out:True optional:False type:bool
+#
+# PrintTemplateInstantiation
+# retType: VT_VOID
+# params:
+# pDisp
+# in:True out:False optional:False type:VT_DISPATCH
+#
+# PrintTemplateTeardown
+# retType: VT_VOID
+# params:
+# pDisp
+# in:True out:False optional:False type:VT_DISPATCH
+#
+# UpdatePageStatus
+# retType: VT_VOID
+# params:
+# pDisp
+# in:True out:False optional:False type:VT_DISPATCH
+# nPage
+# in:True out:False optional:False type:VT_VARIANT
+# fDone
+# in:True out:False optional:False type:VT_VARIANT
+#
+# PrivacyImpactedStateChange
+# retType: VT_VOID
+# params:
+# bImpacted
+# in:True out:False optional:False type:bool
+#
+#
+#
+#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/imagebrowser.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/imagebrowser.py
new file mode 100644
index 0000000..5b80b4c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/imagebrowser.py
@@ -0,0 +1,753 @@
+#----------------------------------------------------------------------------
+# Name: BrowseImage.py
+# Purpose: Display and Select Image Files
+#
+# Original Author: Lorne White
+#
+# Version: 2.0
+# Date: June 16, 2007
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+# 2.0 Release - Bill Baxter (wbaxter@gmail.com)
+# Date: June 16, 2007
+# o Changed to use sizers instead of fixed placement.
+# o Made dialog resizeable
+# o Added a splitter between file list and view pane
+# o Made directory path editable
+# o Added an "up" button" to go to the parent dir
+# o Changed to show directories in file list
+# o Don't select images on double click any more
+# o Added a 'broken image' display for files that wx fails to identify
+# o Redesigned appearance -- using bitmap buttons now, and rearranged things
+# o Fixed display of masked gifs
+# o Fixed zooming logic to show shrunken images at correct aspect ratio
+# o Added different background modes for preview (white/grey/dark/checkered)
+# o Added framing modes for preview (no frame/box frame/tinted border)
+#
+#----------------------------------------------------------------------------
+#
+# 12/08/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for wx namespace
+# o Corrected a nasty bug or two - see comments below.
+# o There was a duplicate ImageView.DrawImage() method. Que?
+#
+#----------------------------------------------------------------------------
+# 1.0 Release - Lorne White
+# Date: January 29, 2002
+# Create list of all available image file types
+# View "All Image" File Types as default filter
+# Sort the file list
+# Use newer "re" function for patterns
+#
+
+#---------------------------------------------------------------------------
+
+import os
+import sys
+import wx
+
+#---------------------------------------------------------------------------
+
+BAD_IMAGE = -1
+ID_WHITE_BG = wx.NewId()
+ID_BLACK_BG = wx.NewId()
+ID_GREY_BG = wx.NewId()
+ID_CHECK_BG = wx.NewId()
+ID_NO_FRAME = wx.NewId()
+ID_BOX_FRAME = wx.NewId()
+ID_CROP_FRAME = wx.NewId()
+
+def ConvertBMP(file_nm):
+ if file_nm is None:
+ return None
+
+ fl_fld = os.path.splitext(file_nm)
+ ext = fl_fld[1]
+ ext = ext[1:].lower()
+
+ # Don't try to create it directly because wx throws up
+ # an annoying messasge dialog if the type isn't supported.
+ if wx.Image.CanRead(file_nm):
+ image = wx.Image(file_nm, wx.BITMAP_TYPE_ANY)
+ return image
+
+ # BAD_IMAGE means a bad image, None just means no image (i.e. directory)
+ return BAD_IMAGE
+
+
+def GetCheckeredBitmap(blocksize=8,ntiles=4,rgb0='\xFF', rgb1='\xCC'):
+ """Creates a square RGB checkered bitmap using the two specified colors.
+
+ Inputs:
+
+ - blocksize: the number of pixels in each solid color square
+ - ntiles: the number of tiles along width and height. Each tile is 2x2 blocks.
+ - rbg0, rgb1: the first and second colors, as 3-byte strings.
+ If only 1 byte is provided, it is treated as a grey value.
+
+ The bitmap returned will have width = height = blocksize*ntiles*2
+ """
+ size = blocksize*ntiles*2
+
+ if len(rgb0)==1:
+ rgb0 = rgb0 * 3
+ if len(rgb1)==1:
+ rgb1 = rgb1 * 3
+
+ strip0 = (rgb0*blocksize + rgb1*blocksize)*(ntiles*blocksize)
+ strip1 = (rgb1*blocksize + rgb0*blocksize)*(ntiles*blocksize)
+ band = strip0 + strip1
+ data = band * ntiles
+ return wx.BitmapFromBuffer(size, size, data)
+
+def GetNamedBitmap(name):
+ return IMG_CATALOG[name].getBitmap()
+
+
+class ImageView(wx.Window):
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.BORDER_SUNKEN
+ ):
+ wx.Window.__init__(self, parent, id, pos, size, style=style)
+
+ self.image = None
+
+ self.check_bmp = None
+ self.check_dim_bmp = None
+
+ # dark_bg is the brush/bitmap to use for painting in the whole background
+ # lite_bg is the brush/bitmap/pen to use for painting the image rectangle
+ self.dark_bg = None
+ self.lite_bg = None
+
+ self.border_mode = ID_CROP_FRAME
+ self.SetBackgroundMode( ID_WHITE_BG )
+ self.SetBorderMode( ID_NO_FRAME )
+
+ # Changed API of wx uses tuples for size and pos now.
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def SetValue(self, file_nm): # display the selected file in the panel
+ image = ConvertBMP(file_nm)
+ self.image = image
+ self.Refresh()
+
+ def SetBackgroundMode(self, mode):
+ self.bg_mode = mode
+ self._updateBGInfo()
+
+ def _updateBGInfo(self):
+ bg = self.bg_mode
+ border = self.border_mode
+
+ self.dark_bg = None
+ self.lite_bg = None
+
+ if border == ID_BOX_FRAME:
+ self.lite_bg = wx.BLACK_PEN
+
+ if bg == ID_WHITE_BG:
+ if border == ID_CROP_FRAME:
+ self.SetBackgroundColour('LIGHT GREY')
+ self.lite_bg = wx.WHITE_BRUSH
+ else:
+ self.SetBackgroundColour('WHITE')
+
+ elif bg == ID_GREY_BG:
+ if border == ID_CROP_FRAME:
+ self.SetBackgroundColour('GREY')
+ self.lite_bg = wx.LIGHT_GREY_BRUSH
+ else:
+ self.SetBackgroundColour('LIGHT GREY')
+
+ elif bg == ID_BLACK_BG:
+ if border == ID_BOX_FRAME:
+ self.lite_bg = wx.WHITE_PEN
+ if border == ID_CROP_FRAME:
+ self.SetBackgroundColour('GREY')
+ self.lite_bg = wx.BLACK_BRUSH
+ else:
+ self.SetBackgroundColour('BLACK')
+
+ else:
+ if self.check_bmp is None:
+ self.check_bmp = GetCheckeredBitmap()
+ self.check_dim_bmp = GetCheckeredBitmap(rgb0='\x7F', rgb1='\x66')
+ if border == ID_CROP_FRAME:
+ self.dark_bg = self.check_dim_bmp
+ self.lite_bg = self.check_bmp
+ else:
+ self.dark_bg = self.check_bmp
+
+ self.Refresh()
+
+ def SetBorderMode(self, mode):
+ self.border_mode = mode
+ self._updateBGInfo()
+
+ def OnSize(self, event):
+ event.Skip()
+ self.Refresh()
+
+ def OnPaint(self, event):
+ dc = wx.PaintDC(self)
+ self.DrawImage(dc)
+
+ def OnEraseBackground(self, evt):
+ if self.bg_mode != ID_CHECK_BG:
+ evt.Skip()
+ return
+ dc = evt.GetDC()
+ if dc:
+ self.PaintBackground(dc, self.dark_bg)
+
+ def PaintBackground(self, dc, painter, rect=None):
+ if painter is None:
+ return
+ if rect is None:
+ pos = self.GetPosition()
+ sz = self.GetSize()
+ else:
+ pos = rect.Position
+ sz = rect.Size
+
+ if type(painter)==wx.Brush:
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(painter)
+ dc.DrawRectangle(pos.x,pos.y,sz.width,sz.height)
+ elif type(painter)==wx.Pen:
+ dc.SetPen(painter)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(pos.x-1,pos.y-1,sz.width+2,sz.height+2)
+ else:
+ self.TileBackground(dc, painter, pos.x,pos.y,sz.width,sz.height)
+
+
+ def TileBackground(self, dc, bmp, x,y,w,h):
+ """Tile bmp into the specified rectangle"""
+ bw = bmp.GetWidth()
+ bh = bmp.GetHeight()
+
+ dc.SetClippingRegion(x,y,w,h)
+
+ # adjust so 0,0 so we always match with a tiling starting at 0,0
+ dx = x % bw
+ x = x - dx
+ w = w + dx
+
+ dy = y % bh
+ y = y - dy
+ h = h + dy
+
+ tx = x
+ x2 = x+w
+ y2 = y+h
+
+ while tx < x2:
+ ty = y
+ while ty < y2:
+ dc.DrawBitmap(bmp, tx, ty)
+ ty += bh
+ tx += bw
+
+ def DrawImage(self, dc):
+
+ if not hasattr(self,'image') or self.image is None:
+ return
+
+ wwidth,wheight = self.GetSize()
+ image = self.image
+ bmp = None
+ if image != BAD_IMAGE and image.IsOk():
+ iwidth = image.GetWidth() # dimensions of image file
+ iheight = image.GetHeight()
+ else:
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_MISSING_IMAGE, wx.ART_MESSAGE_BOX, (64,64))
+ iwidth = bmp.GetWidth()
+ iheight = bmp.GetHeight()
+
+ # squeeze iwidth x iheight image into window, preserving aspect ratio
+
+ xfactor = float(wwidth) / iwidth
+ yfactor = float(wheight) / iheight
+
+ if xfactor < 1.0 and xfactor < yfactor:
+ scale = xfactor
+ elif yfactor < 1.0 and yfactor < xfactor:
+ scale = yfactor
+ else:
+ scale = 1.0
+
+ owidth = int(scale*iwidth)
+ oheight = int(scale*iheight)
+
+ diffx = (wwidth - owidth)/2 # center calc
+ diffy = (wheight - oheight)/2 # center calc
+
+ if not bmp:
+ if owidth!=iwidth or oheight!=iheight:
+ sc_image = sc_image = image.Scale(owidth,oheight)
+ else:
+ sc_image = image
+ bmp = sc_image.ConvertToBitmap()
+
+ if image != BAD_IMAGE and image.IsOk():
+ self.PaintBackground(dc, self.lite_bg, wx.Rect(diffx,diffy,owidth,oheight))
+
+ dc.DrawBitmap(bmp, diffx, diffy, useMask=True) # draw the image to window
+
+
+class ImagePanel(wx.Panel):
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.NO_BORDER
+ ):
+ wx.Panel.__init__(self, parent, id, pos, size, style=style)
+
+ vbox = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(vbox)
+
+ self.view = ImageView(self)
+ vbox.Add(self.view, 1, wx.GROW|wx.ALL, 0)
+
+ hbox_ctrls = wx.BoxSizer(wx.HORIZONTAL)
+ vbox.Add(hbox_ctrls, 0, wx.ALIGN_RIGHT|wx.TOP, 4)
+
+ bmp = GetNamedBitmap('White')
+ btn = wx.BitmapButton(self, ID_WHITE_BG, bmp, style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
+ btn.SetToolTipString("Set background to white")
+ hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
+
+ bmp = GetNamedBitmap('Grey')
+ btn = wx.BitmapButton(self, ID_GREY_BG, bmp, style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
+ btn.SetToolTipString("Set background to grey")
+ hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
+
+ bmp = GetNamedBitmap('Black')
+ btn = wx.BitmapButton(self, ID_BLACK_BG, bmp, style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
+ btn.SetToolTipString("Set background to black")
+ hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
+
+ bmp = GetNamedBitmap('Checked')
+ btn = wx.BitmapButton(self, ID_CHECK_BG, bmp, style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
+ btn.SetToolTipString("Set background to chekered pattern")
+ hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
+
+
+ hbox_ctrls.AddSpacer(7)
+
+ bmp = GetNamedBitmap('NoFrame')
+ btn = wx.BitmapButton(self, ID_NO_FRAME, bmp, style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnSetBorderMode, btn)
+ btn.SetToolTipString("No framing around image")
+ hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
+
+ bmp = GetNamedBitmap('BoxFrame')
+ btn = wx.BitmapButton(self, ID_BOX_FRAME, bmp, style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnSetBorderMode, btn)
+ btn.SetToolTipString("Frame image with a box")
+ hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
+
+ bmp = GetNamedBitmap('CropFrame')
+ btn = wx.BitmapButton(self, ID_CROP_FRAME, bmp, style=wx.BU_EXACTFIT|wx.BORDER_SIMPLE)
+ self.Bind(wx.EVT_BUTTON, self.OnSetBorderMode, btn)
+ btn.SetToolTipString("Frame image with a dimmed background")
+ hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
+
+
+ def SetValue(self, file_nm): # display the selected file in the panel
+ self.view.SetValue(file_nm)
+
+ def SetBackgroundMode(self, mode):
+ self.view.SetBackgroundMode(mode)
+
+ def SetBorderMode(self, mode):
+ self.view.SetBorderMode(mode)
+
+ def OnSetImgBackground(self, event):
+ mode = event.GetId()
+ self.SetBackgroundMode(mode)
+
+ def OnSetBorderMode(self, event):
+ mode = event.GetId()
+ self.SetBorderMode(mode)
+
+
+
+class ImageDialog(wx.Dialog):
+ def __init__(self, parent, set_dir = None):
+ wx.Dialog.__init__(self, parent, -1, "Image Browser", wx.DefaultPosition, (400, 400),style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
+
+ self.set_dir = os.getcwd()
+ self.set_file = None
+
+ if set_dir != None:
+ if os.path.exists(set_dir): # set to working directory if nothing set
+ self.set_dir = set_dir
+
+ vbox_top = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(vbox_top)
+
+ hbox_loc = wx.BoxSizer(wx.HORIZONTAL)
+ vbox_top.Add(hbox_loc, 0, wx.GROW|wx.ALIGN_LEFT|wx.ALL, 0)
+
+ loc_label = wx.StaticText( self, -1, "Folder:")
+ hbox_loc.Add(loc_label, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.ADJUST_MINSIZE, 5)
+
+ self.dir = wx.TextCtrl( self, -1, self.set_dir, style=wx.TE_RICH|wx.TE_PROCESS_ENTER)
+ self.Bind(wx.EVT_TEXT_ENTER, self.OnDirectoryTextSet, self.dir)
+ hbox_loc.Add(self.dir, 1, wx.GROW|wx.ALIGN_LEFT|wx.ALL, 5)
+
+ up_bmp = wx.ArtProvider.GetBitmap(wx.ART_GO_DIR_UP, wx.ART_BUTTON, (16,16))
+ btn = wx.BitmapButton(self, -1, up_bmp)
+ btn.SetHelpText("Up one level")
+ btn.SetToolTipString("Up one level")
+ self.Bind(wx.EVT_BUTTON, self.OnUpDirectory, btn)
+ hbox_loc.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 2)
+
+ folder_bmp = wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_BUTTON, (16,16))
+ btn = wx.BitmapButton(self, -1, folder_bmp)
+ btn.SetHelpText("Browse for a &folder...")
+ btn.SetToolTipString("Browse for a folder...")
+ self.Bind(wx.EVT_BUTTON, self.OnChooseDirectory, btn)
+ hbox_loc.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+
+ hbox_nav = wx.BoxSizer(wx.HORIZONTAL)
+ vbox_top.Add(hbox_nav, 0, wx.ALIGN_LEFT|wx.ALL, 0)
+
+
+ label = wx.StaticText( self, -1, "Files of type:")
+ hbox_nav.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
+
+ self.fl_ext = '*.bmp' # initial setting for file filtering
+ self.GetFiles() # get the file list
+
+ self.fl_ext_types = (
+ # display, filter
+ ("All supported formats", "All"),
+ ("BMP (*.bmp)", "*.bmp"),
+ ("GIF (*.gif)", "*.gif"),
+ ("PNG (*.png)", "*.png"),
+ ("JPEG (*.jpg)", "*.jpg"),
+ ("ICO (*.ico)", "*.ico"),
+ ("PNM (*.pnm)", "*.pnm"),
+ ("PCX (*.pcx)", "*.pcx"),
+ ("TIFF (*.tif)", "*.tif"),
+ ("All Files", "*.*"),
+ )
+ self.set_type,self.fl_ext = self.fl_ext_types[0] # initial file filter setting
+ self.fl_types = [ x[0] for x in self.fl_ext_types ]
+ self.sel_type = wx.ComboBox( self, -1, self.set_type,
+ wx.DefaultPosition, wx.DefaultSize, self.fl_types,
+ wx.CB_DROPDOWN )
+ # after this we don't care about the order any more
+ self.fl_ext_types = dict(self.fl_ext_types)
+
+ self.Bind(wx.EVT_COMBOBOX, self.OnSetType, self.sel_type)
+ hbox_nav.Add(self.sel_type, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
+
+ splitter = wx.SplitterWindow( self, -1, wx.DefaultPosition, wx.Size(100, 100), 0 )
+ splitter.SetMinimumPaneSize(100)
+
+ split_left = wx.Panel( splitter, -1, wx.DefaultPosition, wx.DefaultSize,
+ wx.NO_BORDER|wx.TAB_TRAVERSAL )
+ vbox_left = wx.BoxSizer(wx.VERTICAL)
+ split_left.SetSizer(vbox_left)
+
+
+ self.tb = tb = wx.ListBox( split_left, -1, wx.DefaultPosition, wx.DefaultSize,
+ self.fl_list, wx.LB_SINGLE )
+ self.Bind(wx.EVT_LISTBOX, self.OnListClick, tb)
+ self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnListDClick, tb)
+ vbox_left.Add(self.tb, 1, wx.GROW|wx.ALL, 0)
+
+ width, height = self.tb.GetSize()
+
+ split_right = wx.Panel( splitter, -1, wx.DefaultPosition, wx.DefaultSize,
+ wx.NO_BORDER|wx.TAB_TRAVERSAL )
+ vbox_right = wx.BoxSizer(wx.VERTICAL)
+ split_right.SetSizer(vbox_right)
+
+ self.image_view = ImagePanel( split_right )
+ vbox_right.Add(self.image_view, 1, wx.GROW|wx.ALL, 0)
+
+ splitter.SplitVertically(split_left, split_right, 150)
+ vbox_top.Add(splitter, 1, wx.GROW|wx.ALL, 5)
+
+ hbox_btns = wx.BoxSizer(wx.HORIZONTAL)
+ vbox_top.Add(hbox_btns, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
+
+ ok_btn = wx.Button( self, wx.ID_OPEN, "", wx.DefaultPosition, wx.DefaultSize, 0 )
+ self.Bind(wx.EVT_BUTTON, self.OnOk, ok_btn)
+ #ok_btn.SetDefault()
+ hbox_btns.Add(ok_btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
+
+ cancel_btn = wx.Button( self, wx.ID_CANCEL, "",
+ wx.DefaultPosition, wx.DefaultSize, 0 )
+ hbox_btns.Add(cancel_btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
+
+ self.ResetFiles()
+
+ def ChangeFileTypes(self, ft_tuple):
+ # Change list of file types to be supported
+ self.fl_ext_types = ft_tuple
+ self.set_type, self.fl_ext = self.fl_ext_types[0] # initial file filter setting
+ self.fl_types = [ x[0] for x in self.fl_ext_types ]
+ self.sel_type.Clear()
+ self.sel_type.AppendItems(self.fl_types)
+ self.sel_type.SetSelection(0)
+ self.fl_ext_types = dict(self.fl_ext_types)
+
+ def GetFiles(self): # get the file list using directory and extension values
+ if self.fl_ext == "All":
+ all_files = []
+
+ if self.fl_types[-1] == 'All Files':
+ allTypes = self.fl_types[-1:]
+ else:
+ allTypes = self.fl_types[1:]
+ for ftypes in allTypes: # get list of all
+ filter = self.fl_ext_types[ftypes]
+ #print "filter = ", filter
+ self.fl_val = FindFiles(self, self.set_dir, filter)
+ all_files = all_files + self.fl_val.files # add to list of files
+
+ self.fl_list = all_files
+ else:
+ self.fl_val = FindFiles(self, self.set_dir, self.fl_ext)
+ self.fl_list = self.fl_val.files
+
+
+ self.fl_list.sort() # sort the file list
+ # prepend the directories
+ self.fl_ndirs = len(self.fl_val.dirs)
+ self.fl_list = sorted(self.fl_val.dirs) + self.fl_list
+
+ def DisplayDir(self): # display the working directory
+ if self.dir:
+ ipt = self.dir.GetInsertionPoint()
+ self.dir.SetValue(self.set_dir)
+ self.dir.SetInsertionPoint(ipt)
+
+ def OnSetType(self, event):
+ val = event.GetString() # get file type value
+ self.fl_ext = self.fl_ext_types[val]
+ self.ResetFiles()
+
+ def OnListDClick(self, event):
+ self.OnOk('dclick')
+
+ def OnListClick(self, event):
+ val = event.GetSelection()
+ self.SetListValue(val)
+
+ def SetListValue(self, val):
+ file_nm = self.fl_list[val]
+ self.set_file = file_val = os.path.join(self.set_dir, file_nm)
+ if val>=self.fl_ndirs:
+ self.image_view.SetValue(file_val)
+ else:
+ self.image_view.SetValue(None)
+
+ def OnDirectoryTextSet(self,event):
+ event.Skip()
+ path = event.GetString()
+ if os.path.isdir(path):
+ self.set_dir = path
+ self.ResetFiles()
+ return
+
+ if os.path.isfile(path):
+ dname,fname = os.path.split(path)
+ if os.path.isdir(dname):
+ self.ResetFiles()
+ # try to select fname in list
+ try:
+ idx = self.fl_list.index(fname)
+ self.tb.SetSelection(idx)
+ self.SetListValue(idx)
+ return
+ except ValueError:
+ pass
+
+ wx.Bell()
+
+ def OnUpDirectory(self, event):
+ sdir = os.path.split(self.set_dir)[0]
+ self.set_dir = sdir
+ self.ResetFiles()
+
+ def OnChooseDirectory(self, event): # set the new directory
+ dlg = wx.DirDialog(self)
+ dlg.SetPath(self.set_dir)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ self.set_dir = dlg.GetPath()
+ self.ResetFiles()
+
+ dlg.Destroy()
+
+ def ResetFiles(self): # refresh the display with files and initial image
+ self.DisplayDir()
+ self.GetFiles()
+
+ # Changed 12/8/03 jmg
+ #
+ # o Clear listbox first
+ # o THEN check to see if there are any valid files of the selected
+ # type,
+ # o THEN if we have any files to display, set the listbox up,
+ #
+ # OTHERWISE
+ #
+ # o Leave it cleared
+ # o Clear the image viewer.
+ #
+ # This avoids a nasty assert error.
+ #
+ self.tb.Clear()
+
+ if len(self.fl_list):
+ self.tb.Set(self.fl_list)
+
+ for idir in xrange(self.fl_ndirs):
+ d = self.fl_list[idir]
+ # mark directories as 'True' with client data
+ self.tb.SetClientData(idir, True)
+ self.tb.SetString(idir,'['+d+']')
+
+ try:
+ self.tb.SetSelection(0)
+ self.SetListValue(0)
+ except:
+ self.image_view.SetValue(None)
+ else:
+ self.image_view.SetValue(None)
+
+ def GetFile(self):
+ return self.set_file
+
+ def GetDirectory(self):
+ return self.set_dir
+
+ def OnCancel(self, event):
+ self.result = None
+ self.EndModal(wx.ID_CANCEL)
+
+ def OnOk(self, event):
+ if os.path.isdir(self.set_file):
+ sdir = os.path.split(self.set_file)
+
+ #os.path.normapth?
+ if sdir and sdir[-1]=='..':
+ sdir = os.path.split(sdir[0])[0]
+ sdir = os.path.split(sdir)
+ self.set_dir = os.path.join(*sdir)
+ self.set_file = None
+ self.ResetFiles()
+ elif event != 'dclick':
+ self.result = self.set_file
+ self.EndModal(wx.ID_OK)
+
+
+
+class FindFiles:
+ def __init__(self, parent, dir, mask, with_dirs=True):
+ filelist = []
+ dirlist = [".."]
+ self.dir = dir
+ self.file = ""
+ mask = mask.upper()
+ pattern = self.MakeRegex(mask)
+
+ for i in os.listdir(dir):
+ if i == "." or i == "..":
+ continue
+
+ path = os.path.join(dir, i)
+
+ if os.path.isdir(path):
+ dirlist.append(i)
+ continue
+
+ path = path.upper()
+ value = i.upper()
+
+ if pattern.match(value) != None:
+ filelist.append(i)
+
+
+ self.files = filelist
+ if with_dirs:
+ self.dirs = dirlist
+
+ def MakeRegex(self, pattern):
+ import re
+ f = "" # Set up a regex for file names
+
+ for ch in pattern:
+ if ch == "*":
+ f = f + ".*"
+ elif ch == ".":
+ f = f + "\."
+ elif ch == "?":
+ f = f + "."
+ else:
+ f = f + ch
+
+ return re.compile(f+'$')
+
+ def StripExt(self, file_nm):
+ fl_fld = os.path.splitext(file_nm)
+ fl_name = fl_fld[0]
+ ext = fl_fld[1]
+ return ext[1:]
+
+
+#----------------------------------------------------------------------
+# This part of the file was generated by C:\Python25\Scripts\img2py
+# then edited slightly.
+
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+IMG_CATALOG = {}
+
+IMG_CATALOG['White'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAAIUlE"
+ "QVQYlWNgIAIwMjAw/P//H58KRkYmYkwaVUScIqIAAMjRAxRV8+5MAAAAAElFTkSuQmCC")
+
+IMG_CATALOG['Grey'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAAIklE"
+ "QVQYlWNgIAIwMjAwnDlzBo8KExMTJmJMGlVEnCKiAAC24wMULFLZGAAAAABJRU5ErkJggg==")
+
+IMG_CATALOG['Black'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAADklE"
+ "QVQYlWNgGAVDFQAAAbwAATN8mzYAAAAASUVORK5CYII=")
+
+IMG_CATALOG['Checked'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAAMUlE"
+ "QVQYlWNgIAIwMjAwnDlzBlnI2NgYRQUjIxMxJtFZEQsDhkvPnj07sG4iShFRAAAougYW+urT"
+ "ZwAAAABJRU5ErkJggg==")
+
+IMG_CATALOG['NoFrame'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAANklE"
+ "QVQYla2PQQoAIBACnej/X7ZbUEQtkudhVKkQJNm+EdAqpggCgB+m44kFml1bY39q0k15Bsuc"
+ "CR/z8ajiAAAAAElFTkSuQmCC")
+
+IMG_CATALOG['BoxFrame'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAAQ0lE"
+ "QVQYlZ2O0QoAIAgDd9L//7I9CFEhJu1psmNOaghJ7l4RYJ0m1U0R2X4vevcHVOiG0tcHBABh"
+ "8nWpIhpPLtn0rwm4WyD966x3sgAAAABJRU5ErkJggg==")
+
+IMG_CATALOG['CropFrame'] = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAA3NCSVQICAjb4U/gAAAASUlE"
+ "QVQYlb2QMQrAQAgEZ0P+q0/RF5tCuIMUh2myhcgyjCAMIiAiDoS7XxPTCLrXZmaAJKCqgMz8"
+ "YHpD7ThBkvpcz93z6wtGeQD/sQ8bfXs8NAAAAABJRU5ErkJggg==")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/imageutils.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/imageutils.py
new file mode 100644
index 0000000..4686887
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/imageutils.py
@@ -0,0 +1,98 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.imageutils
+# Purpose: A collection of functions for simple image manipulations
+#
+# Author: Robb Shecter
+#
+# Created: 7-Nov-2002
+# RCS-ID: $Id$
+# Copyright: (c) 2002 by
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import wx
+
+def grayOut(anImage):
+ """
+ Convert the given image (in place) to a grayed-out
+ version, appropriate for a 'disabled' appearance.
+ """
+ factor = 0.7 # 0 < f < 1. Higher is grayer.
+ if anImage.HasMask():
+ maskColor = (anImage.GetMaskRed(), anImage.GetMaskGreen(), anImage.GetMaskBlue())
+ else:
+ maskColor = None
+ if anImage.HasAlpha():
+ alpha = anImage.GetAlphaData()
+ else:
+ alpha = None
+
+ data = map(ord, list(anImage.GetData()))
+
+ for i in range(0, len(data), 3):
+ pixel = (data[i], data[i+1], data[i+2])
+ pixel = makeGray(pixel, factor, maskColor)
+ for x in range(3):
+ data[i+x] = pixel[x]
+ anImage.SetData(''.join(map(chr, data)))
+ if alpha:
+ anImage.SetAlphaData(alpha)
+
+
+def makeGray((r,g,b), factor, maskColor):
+ """
+ Make a pixel grayed-out. If the pixel
+ matches the maskColor, it won't be
+ changed.
+ """
+ if (r,g,b) != maskColor:
+ return map(lambda x: int((230 - x) * factor) + x, (r,g,b))
+ else:
+ return (r,g,b)
+
+
+
+def stepColour(c, step):
+ """
+ stepColour is a utility function that simply darkens or lightens a
+ color, based on the specified step value. A step of 0 is
+ completely black and a step of 200 is totally white, and 100
+ results in the same color as was passed in.
+ """
+ def _blendColour(fg, bg, dstep):
+ result = bg + (dstep * (fg - bg))
+ if result < 0:
+ result = 0
+ if result > 255:
+ result = 255
+ return result
+
+ if step == 100:
+ return c
+
+ r = c.Red()
+ g = c.Green()
+ b = c.Blue()
+
+ # step is 0..200 where 0 is completely black
+ # and 200 is completely white and 100 is the same
+ # convert that to a range of -1.0 .. 1.0
+ step = min(step, 200)
+ step = max(step, 0)
+ dstep = (step - 100.0)/100.0
+
+ if step > 100:
+ # blend with white
+ bg = 255.0
+ dstep = 1.0 - dstep # 0 = transparent fg; 1 = opaque fg
+ else:
+ # blend with black
+ bg = 0.0
+ dstep = 1.0 + dstep; # 0 = transparent fg; 1 = opaque fg
+
+ r = _blendColour(r, bg, dstep)
+ g = _blendColour(g, bg, dstep)
+ b = _blendColour(b, bg, dstep)
+
+ return wx.Colour(int(r), int(g), int(b))
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/infoframe.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/infoframe.py
new file mode 100644
index 0000000..14ab217
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/infoframe.py
@@ -0,0 +1,492 @@
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxPyInformationalMessagesFrame -> PyInformationalMessagesFrame
+# o dummy_wxPyInformationalMessagesFrame -> dummy_PyInformationalMessagesFrame
+#
+
+"""
+infoframe.py
+Released under wxWindows license etc.
+
+This is a fairly rudimentary, but slightly fancier tha
+wxPyOnDemandOutputWindow (on which it's based; thanks Robin), version
+of the same sort of thing: a file-like class called
+wxInformationalMessagesFrame. This window also has a status bar with a
+couple of buttons for controlling the echoing of all output to a file
+with a randomly-chosen filename...
+
+The class behaves similarly to wxPyOnDemandOutputWindow in that (at
+least by default) the frame does not appear until written to, but is
+somewhat different in that, either under programmatic (the
+DisableOutput method) or user (the frame's close button, it's status
+bar's "Dismiss" button, or a "Disable output" item of some menu,
+perhaps of some other frame), the frame will be destroyed, an
+associated file closed, and writing to it will then do nothing. This
+can be reversed: either under programmatic (the EnableOutput method)
+or user (an "Enable output" item of some menu), a new frame will be
+opened,And an associated file (with a "randomly"selected filename)
+opened for writing [to which all subsequent displayed messages will be
+echoed].
+
+Please note that, like wxPyOnDemandOutputWindow, the instance is not
+itself a subclass of wxWindow: when the window is open (and ONLY
+then), it's "frame" attribute is the actual instance of wFrame...
+
+Typical usage::
+
+ from wx.lib.infoframe import *
+ ... # ... modify your wxApp as follows:
+ class myApp(wxApp):
+ outputWindowClass = PyInformationalMessagesFrame
+ # ...
+
+
+If you're running on Linux, you'll also have to supply an argument 1 to your
+constructor of myApp to redirect stdout/stderr to this window (it's done
+automatically for you on Windows).
+
+If you don't want to redirect stdout/stderr, but use the class directly: do
+it this way::
+
+ InformationalMessagesFrame = PyInformationalMessagesFrame( \
+ options_from_progname, # (default = "")
+ txt), # (default = "informational messages")
+
+ #^^^^ early in the program
+ # ...
+
+ InformationalMessagesFrame(list_of_items)
+
+ # where list_of_items:
+ #
+ # comma-separated list of items to display.
+ # Note that these will never be separated by spaces as they may
+ # be when used in the Python 'print' command
+
+
+The latter statement, of course, may be repeated arbitrarily often.
+The window will not appear until it is written to, and it may be
+manually closed by the user, after which it will reappear again until
+written to... Also note that all output is echoed to a file with a
+randomly-generated name [see the mktemp module in the standard
+library], in the directory given as the 'dir' keyword argument to the
+InformationalMessagesFrame constructor [which has a default value of
+'.'), or set via the method SetOutputDirectory... This file will be
+closed with the window--a new one will be created [by default] upon
+each subsequent reopening.
+
+Please also note the methods EnableOutput and DisableOutput, and the
+possible arguments for the constructor in the code below... (* TO DO:
+explain this here...*) Neither of these methods need be used at all,
+and in this case the frame will only be displayed once it has been
+written to, like wxPyOnDemandOutputWindow.
+
+The former, EnableOutput, displays the frame with an introductory
+message, opens a random file to which future displayed output also
+goes (unless the nofile attribute is present), and sets the __debug__
+variable of each module to 1 (unless the no __debug__ attribute is
+present]. This is so that you can say, in any module whatsoever::
+
+ if __debug__:
+ InformationalMessagesFrame("... with lots of %<Character> constructs"
+ % TUPLE)
+
+
+without worrying about the overhead of evaluating the arguments, and
+calling the wxInformationalMessagesFrame instance, in the case where
+debugging is not turned on. (This won't happen if the instance has an
+attribute no__debug__; you can arrange this by sub-classing...)
+
+"Debug mode" can also be turned on by selecting the item-"Enable
+output" from the "Debug" menu [the default--see the optional arguments
+to the SetOtherMenuBar method] of a frame which has been either passed
+appropriately to the constructor of the wxInformationalMessagesFrame
+(see the code), or set via the SetOtherMenuBar method thereof. This
+also writes an empty string to the instance, meaning that the frame
+will open (unless DisablOutput has been called) with an appropriate
+introductory message (which will vary according to whether the
+instance/class has the "no __debug__" attribute)^ I have found this to
+be an extremely useful tool, in lieu of a full wxPython debugger...
+
+Following this, the menu item is also disabled, and an item "Disable
+output" (again, by default) is enabled. Note that these need not be
+done: e.g., you don't NEED to have a menu with appropriate items; in
+this case simply do not call the SetOtherMenuBar method or use the
+othermenubar keyword argument of the class instance constructor.
+
+The DisableOutput method does the reverse of this; it closes the
+window (and associated file), and sets the __debug__ variable of each
+module whose name begins with a capital letter {this happens to be the
+author's personal practice; all my python module start with capital
+letters} to 0. It also enables/disabled the appropriate menu items,
+if this was done previously (or SetOtherMenuBar has been called...).
+Note too that after a call to DisableOutput, nothing further will be
+done upon subsequent write()'s, until the EnableOutput method is
+called, either explicitly or by the menu selection above...
+
+Finally, note that the file-like method close() destroys the window
+(and closes any associated file) and there is a file-like method
+write() which displays it's argument.
+
+All (well, most) of this is made clear by the example code at the end
+of this file, which is run if the file is run by itself; otherwise,
+see the appropriate "stub" file in the wxPython demo.
+
+"""
+
+import os
+import sys
+import tempfile
+
+import wx
+
+class _MyStatusBar(wx.StatusBar):
+ def __init__(self, parent, callbacks=None, useopenbutton=0):
+ wx.StatusBar.__init__(self, parent, -1, style=wx.TAB_TRAVERSAL)
+ self.SetFieldsCount(3)
+
+ self.SetStatusText("",0)
+
+ self.button1 = wx.Button(self, -1, "Dismiss", style=wx.TAB_TRAVERSAL)
+ self.Bind(wx.EVT_BUTTON, self.OnButton1, self.button1)
+
+ if not useopenbutton:
+ self.button2 = wx.Button(self, -1, "Close File", style=wx.TAB_TRAVERSAL)
+ else:
+ self.button2 = wx.Button(self, -1, "Open New File", style=wx.TAB_TRAVERSAL)
+
+ self.Bind(wx.EVT_BUTTON, self.OnButton2, self.button2)
+ self.useopenbutton = useopenbutton
+ self.callbacks = callbacks
+
+ # figure out how tall to make the status bar
+ dc = wx.ClientDC(self)
+ dc.SetFont(self.GetFont())
+ (w,h) = dc.GetTextExtent('X')
+ h = int(h * 1.8)
+ self.SetSize((100, h))
+ self.OnSize("dummy")
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ # reposition things...
+ def OnSize(self, event):
+ self.CalculateSizes()
+ rect = self.GetFieldRect(1)
+ self.button1.SetPosition((rect.x+5, rect.y+2))
+ self.button1.SetSize((rect.width-10, rect.height-4))
+ rect = self.GetFieldRect(2)
+ self.button2.SetPosition((rect.x+5, rect.y+2))
+ self.button2.SetSize((rect.width-10, rect.height-4))
+
+ # widths........
+ def CalculateSizes(self):
+ dc = wx.ClientDC(self.button1)
+ dc.SetFont(self.button1.GetFont())
+ (w1,h) = dc.GetTextExtent(self.button1.GetLabel())
+
+ dc = wx.ClientDC(self.button2)
+ dc.SetFont(self.button2.GetFont())
+ (w2,h) = dc.GetTextExtent(self.button2.GetLabel())
+
+ self.SetStatusWidths([-1,w1+15,w2+15])
+
+ def OnButton1(self,event):
+ self.callbacks[0] ()
+
+ def OnButton2(self,event):
+ if self.useopenbutton and self.callbacks[2] ():
+ self.button2.SetLabel ("Close File")
+ elif self.callbacks[1] ():
+ self.button2.SetLabel ("Open New File")
+
+ self.useopenbutton = 1 - self.useopenbutton
+ self.OnSize("")
+ self.button2.Refresh(True)
+ self.Refresh()
+
+
+
+class PyInformationalMessagesFrame(object):
+ def __init__(self,
+ progname="",
+ text="informational messages",
+ dir='.',
+ menuname="Debug",
+ enableitem="Enable output",
+ disableitem="Disable output",
+ othermenubar=None):
+
+ self.SetOtherMenuBar(othermenubar,
+ menuname=menuname,
+ enableitem=enableitem,
+ disableitem=disableitem)
+
+ if hasattr(self,"othermenu") and self.othermenu is not None:
+ i = self.othermenu.FindMenuItem(self.menuname,self.disableitem)
+ self.othermenu.Enable(i,0)
+ i = self.othermenu.FindMenuItem(self.menuname,self.enableitem)
+ self.othermenu.Enable(i,1)
+
+ self.frame = None
+ self.title = "%s %s" % (progname,text)
+ self.parent = None # use the SetParent method if desired...
+ self.softspace = 1 # of rather limited use
+
+ if dir:
+ self.SetOutputDirectory(dir)
+
+
+ def SetParent(self, parent):
+ self.parent = parent
+
+
+ def SetOtherMenuBar(self,
+ othermenu,
+ menuname="Debug",
+ enableitem="Enable output",
+ disableitem="Disable output"):
+ self.othermenu = othermenu
+ self.menuname = menuname
+ self.enableitem = enableitem
+ self.disableitem = disableitem
+
+
+ f = None
+
+
+ def write(self, string):
+ if not wx.Thread_IsMain():
+ # Aquire the GUI mutex before making GUI calls. Mutex is released
+ # when locker is deleted at the end of this function.
+ #
+ # TODO: This should be updated to use wx.CallAfter similarly to how
+ # PyOnDemandOutputWindow.write was so it is not necessary
+ # to get the gui mutex
+ locker = wx.MutexGuiLocker()
+
+ if self.Enabled:
+ if self.f:
+ self.f.write(string)
+ self.f.flush()
+
+ move = 1
+ if (hasattr(self,"text")
+ and self.text is not None
+ and self.text.GetInsertionPoint() != self.text.GetLastPosition()):
+ move = 0
+
+ if not self.frame:
+ self.frame = wx.Frame(self.parent, -1, self.title, size=(450, 300),
+ style=wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
+
+ self.text = wx.TextCtrl(self.frame, -1, "",
+ style = wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH)
+
+ self.frame.sb = _MyStatusBar(self.frame,
+ callbacks=[self.DisableOutput,
+ self.CloseFile,
+ self.OpenNewFile],
+ useopenbutton=hasattr(self,
+ "nofile"))
+ self.frame.SetStatusBar(self.frame.sb)
+ self.frame.Show(True)
+ self.frame.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+ if hasattr(self,"nofile"):
+ self.text.AppendText(
+ "Please close this window (or select the "
+ "'Dismiss' button below) when desired. By "
+ "default all messages written to this window "
+ "will NOT be written to a file--you "
+ "may change this by selecting 'Open New File' "
+ "below, allowing you to select a "
+ "new file...\n\n")
+ else:
+ tempfile.tempdir = self.dir
+ filename = os.path.abspath(tempfile.mktemp ())
+
+ self.text.AppendText(
+ "Please close this window (or select the "
+ "'Dismiss' button below) when desired. By "
+ "default all messages written to this window "
+ "will also be written to the file '%s'--you "
+ "may close this file by selecting 'Close "
+ "File' below, whereupon this button will be "
+ "replaced with one allowing you to select a "
+ "new file...\n\n" % filename)
+ try:
+ self.f = open(filename, 'w')
+ self.frame.sb.SetStatusText("File '%s' opened..."
+ % filename,
+ 0)
+ except EnvironmentError:
+ self.frame.sb.SetStatusText("File creation failed "
+ "(filename '%s')..."
+ % filename,
+ 0)
+ self.text.AppendText(string)
+
+ if move:
+ self.text.ShowPosition(self.text.GetLastPosition())
+
+ if not hasattr(self,"no__debug__"):
+ for m in sys.modules.values():
+ if m is not None:# and m.__dict__.has_key("__debug__"):
+ m.__dict__["__debug__"] = 1
+
+ if hasattr(self,"othermenu") and self.othermenu is not None:
+ i = self.othermenu.FindMenuItem(self.menuname,self.disableitem)
+ self.othermenu.Enable(i,1)
+ i = self.othermenu.FindMenuItem(self.menuname,self.enableitem)
+ self.othermenu.Enable(i,0)
+
+
+ Enabled = 1
+
+ def OnCloseWindow(self, event, exiting=0):
+ if self.f:
+ self.f.close()
+ self.f = None
+
+ if (hasattr(self,"othermenu") and self.othermenu is not None
+ and self.frame is not None
+ and not exiting):
+
+ i = self.othermenu.FindMenuItem(self.menuname,self.disableitem)
+ self.othermenu.Enable(i,0)
+ i = self.othermenu.FindMenuItem(self.menuname,self.enableitem)
+ self.othermenu.Enable(i,1)
+
+ if not hasattr(self,"no__debug__"):
+ for m in sys.modules.values():
+ if m is not None:# and m.__dict__.has_key("__debug__"):
+ m.__dict__["__debug__"] = 0
+
+ if self.frame is not None: # typically True, but, e.g., allows
+ # DisableOutput method (which calls this
+ # one) to be called when the frame is not
+ # actually open, so that it is always safe
+ # to call this method...
+ frame = self.frame
+ self.frame = self.text = None
+ frame.Destroy()
+ self.Enabled = 1
+
+
+ def EnableOutput(self,
+ event=None,# event must be the first optional argument...
+ othermenubar=None,
+ menuname="Debug",
+ enableitem="Enable output",
+ disableitem="Disable output"):
+
+ if othermenubar is not None:
+ self.SetOtherMenuBar(othermenubar,
+ menuname=menuname,
+ enableitem=enableitem,
+ disableitem=disableitem)
+ self.Enabled = 1
+ if self.f:
+ self.f.close()
+ self.f = None
+ self.write("")
+
+
+ def CloseFile(self):
+ if self.f:
+ if self.frame:
+ self.frame.sb.SetStatusText("File '%s' closed..."
+ % os.path.abspath(self.f.name),
+ 0)
+ self.f.close ()
+ self.f = None
+ else:
+ if self.frame:
+ self.frame.sb.SetStatusText("")
+ if self.frame:
+ self.frame.sb.Refresh()
+ return 1
+
+
+ def OpenNewFile(self):
+ self.CloseFile()
+ dlg = wx.FileDialog(self.frame,
+ "Choose a new log file", self.dir,"","*",
+ wx.SAVE | wx.OVERWRITE_PROMPT)
+ if dlg.ShowModal() == wx.ID_CANCEL:
+ dlg.Destroy()
+ return 0
+ else:
+ try:
+ self.f = open(os.path.abspath(dlg.GetPath()),'w')
+ except EnvironmentError:
+ dlg.Destroy()
+ return 0
+ dlg.Destroy()
+ if self.frame:
+ self.frame.sb.SetStatusText("File '%s' opened..."
+ % os.path.abspath(self.f.name),
+ 0)
+ if hasattr(self,"nofile"):
+ self.frame.sb = _MyStatusBar(self.frame,
+ callbacks=[self.DisableOutput,
+ self.CloseFile,
+ self.OpenNewFile])
+ self.frame.SetStatusBar(self.frame.sb)
+ if hasattr(self,"nofile"):
+ delattr(self,"nofile")
+ return 1
+
+
+ def DisableOutput(self,
+ event=None,# event must be the first optional argument...
+ exiting=0):
+ self.write("<InformationalMessagesFrame>.DisableOutput()\n")
+ if hasattr(self,"frame") \
+ and self.frame is not None:
+ self.OnCloseWindow("Dummy",exiting=exiting)
+ self.Enabled = 0
+
+
+ def close(self):
+ self.DisableOutput()
+
+
+ def flush(self):
+ if self.text:
+ self.text.SetInsertionPointEnd()
+ wx.Yield()
+
+
+ def __call__(self,* args):
+ for s in args:
+ self.write (str (s))
+
+
+ def SetOutputDirectory(self,dir):
+ self.dir = os.path.abspath(dir)
+## sys.__stderr__.write("Directory: os.path.abspath(%s) = %s\n"
+## % (dir,self.dir))
+
+
+
+class Dummy_PyInformationalMessagesFrame(object):
+ def __init__(self,progname=""):
+ self.softspace = 1
+ def __call__(self,*args):
+ pass
+ def write(self,s):
+ pass
+ def flush(self):
+ pass
+ def close(self):
+ pass
+ def EnableOutput(self):
+ pass
+ def __call__(self,* args):
+ pass
+ def DisableOutput(self,exiting=0):
+ pass
+ def SetParent(self,wX):
+ pass
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/inspection.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/inspection.py
new file mode 100644
index 0000000..5a8f8d2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/inspection.py
@@ -0,0 +1,1237 @@
+#----------------------------------------------------------------------------
+# Name: wx.lib.inspection
+# Purpose: A widget inspection tool that allows easy introspection of
+# all the live widgets and sizers in an application.
+#
+# Author: Robin Dunn
+#
+# Created: 26-Jan-2007
+# RCS-ID: $Id$
+# Copyright: (c) 2007 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+# NOTE: This class was originally based on ideas sent to the
+# wxPython-users mail list by Dan Eloff. See also
+# wx.lib.mixins.inspect for a class that can be mixed-in with wx.App
+# to provide Hot-Key access to the inspection tool.
+
+import wx
+import wx.py
+import wx.stc
+#import wx.aui as aui
+import wx.lib.agw.aui as aui
+import wx.lib.utils as utils
+import sys
+import inspect
+
+#----------------------------------------------------------------------------
+
+class InspectionTool:
+ """
+ The InspectionTool is a singleton that manages creating and
+ showing an InspectionFrame.
+ """
+
+ # Note: This is the Borg design pattern which ensures that all
+ # instances of this class are actually using the same set of
+ # instance data. See
+ # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531
+ __shared_state = {}
+ def __init__(self):
+ self.__dict__ = self.__shared_state
+ if not hasattr(self, 'initialized'):
+ self.initialized = False
+
+ def Init(self, pos=wx.DefaultPosition, size=wx.Size(850,700),
+ config=None, locals=None, app=None):
+ """
+ Init is used to set some parameters that will be used later
+ when the inspection tool is shown. Suitable defaults will be
+ used for all of these parameters if they are not provided.
+
+ :param pos: The default position to show the frame at
+ :param size: The default size of the frame
+ :param config: A wx.Config object to be used to store layout
+ and other info to when the inspection frame is closed.
+ This info will be restored the next time the inspection
+ frame is used.
+ :param locals: A dictionary of names to be added to the PyCrust
+ namespace.
+ :param app: A reference to the wx.App object.
+ """
+ self._frame = None
+ self._pos = pos
+ self._size = size
+ self._config = config
+ self._locals = locals
+ self._app = app
+ if not self._app:
+ self._app = wx.GetApp()
+ self.initialized = True
+
+
+ def Show(self, selectObj=None, refreshTree=False):
+ """
+ Creates the inspection frame if it hasn't been already, and
+ raises it if neccessary. Pass a widget or sizer in selectObj
+ to have that object be preselected in widget tree. If
+ refreshTree is True then the widget tree will be rebuilt,
+ otherwise if the tree has already been built it will be left
+ alone.
+ """
+ if not self.initialized:
+ self.Init()
+
+ parent = self._app.GetTopWindow()
+ if not selectObj:
+ selectObj = parent
+ if not self._frame:
+ self._frame = InspectionFrame( parent=parent,
+ pos=self._pos,
+ size=self._size,
+ config=self._config,
+ locals=self._locals,
+ app=self._app)
+ if selectObj:
+ self._frame.SetObj(selectObj)
+ if refreshTree:
+ self._frame.RefreshTree()
+ self._frame.Show()
+ if self._frame.IsIconized():
+ self._frame.Iconize(False)
+ self._frame.Raise()
+
+
+#----------------------------------------------------------------------------
+
+
+class InspectionFrame(wx.Frame):
+ """
+ This class is the frame that holds the wxPython inspection tools.
+ The toolbar and AUI splitters/floating panes are also managed
+ here. The contents of the tool windows are handled by other
+ classes.
+ """
+ def __init__(self, wnd=None, locals=None, config=None,
+ app=None, title="wxPython Widget Inspection Tool",
+ *args, **kw):
+ kw['title'] = title
+ wx.Frame.__init__(self, *args, **kw)
+
+ self.SetExtraStyle(wx.WS_EX_BLOCK_EVENTS)
+ self.includeSizers = False
+ self.started = False
+
+ self.SetIcon(Icon.GetIcon())
+ self.MakeToolBar()
+ panel = wx.Panel(self, size=self.GetClientSize())
+
+ # tell FrameManager to manage this frame
+ self.mgr = aui.AuiManager(panel,
+ aui.AUI_MGR_DEFAULT
+ | aui.AUI_MGR_TRANSPARENT_DRAG
+ | aui.AUI_MGR_ALLOW_ACTIVE_PANE)
+
+ # make the child tools
+ self.tree = InspectionTree(panel, size=(100,300))
+ self.info = InspectionInfoPanel(panel,
+ style=wx.NO_BORDER,
+ )
+
+ if not locals:
+ locals = {}
+ myIntroText = (
+ "Python %s on %s, wxPython %s\n"
+ "NOTE: The 'obj' variable refers to the object selected in the tree."
+ % (sys.version.split()[0], sys.platform, wx.version()))
+ self.crust = wx.py.crust.Crust(panel, locals=locals,
+ intro=myIntroText,
+ showInterpIntro=False,
+ style=wx.NO_BORDER,
+ )
+ self.locals = self.crust.shell.interp.locals
+ self.crust.shell.interp.introText = ''
+ self.locals['obj'] = self.obj = wnd
+ self.locals['app'] = app
+ self.locals['wx'] = wx
+ wx.CallAfter(self._postStartup)
+
+ # put the chlid tools in AUI panes
+ self.mgr.AddPane(self.info,
+ aui.AuiPaneInfo().Name("info").Caption("Object Info").
+ CenterPane().CaptionVisible(True).
+ CloseButton(False).MaximizeButton(True)
+ )
+ self.mgr.AddPane(self.tree,
+ aui.AuiPaneInfo().Name("tree").Caption("Widget Tree").
+ CaptionVisible(True).Left().Dockable(True).Floatable(True).
+ BestSize((280,200)).CloseButton(False).MaximizeButton(True)
+ )
+ self.mgr.AddPane(self.crust,
+ aui.AuiPaneInfo().Name("crust").Caption("PyCrust").
+ CaptionVisible(True).Bottom().Dockable(True).Floatable(True).
+ BestSize((400,200)).CloseButton(False).MaximizeButton(True)
+ )
+
+ self.mgr.Update()
+
+ if config is None:
+ config = wx.Config('wxpyinspector')
+ self.config = config
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ if self.Parent:
+ tlw = self.Parent.GetTopLevelParent()
+ tlw.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.LoadSettings(self.config)
+ self.crust.shell.lineNumbers = False
+ self.crust.shell.setDisplayLineNumbers(False)
+ self.crust.shell.SetMarginWidth(1, 0)
+
+
+ def MakeToolBar(self):
+ tbar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.TB_FLAT | wx.TB_TEXT | wx.NO_BORDER )
+ tbar.SetToolBitmapSize((24,24))
+
+ refreshBmp = Refresh.GetBitmap()
+ findWidgetBmp = Find.GetBitmap()
+ showSizersBmp = ShowSizers.GetBitmap()
+ expandTreeBmp = ExpandTree.GetBitmap()
+ collapseTreeBmp = CollapseTree.GetBitmap()
+ highlightItemBmp = HighlightItem.GetBitmap()
+ evtWatcherBmp = EvtWatcher.GetBitmap()
+
+ toggleFillingBmp = ShowFilling.GetBitmap()
+
+ refreshTool = tbar.AddLabelTool(-1, 'Refresh', refreshBmp,
+ shortHelp = 'Refresh widget tree (F1)')
+ findWidgetTool = tbar.AddLabelTool(-1, 'Find', findWidgetBmp,
+ shortHelp='Find new target widget. (F2) Click here and\nthen on another widget in the app.')
+ showSizersTool = tbar.AddLabelTool(-1, 'Sizers', showSizersBmp,
+ shortHelp='Include sizers in widget tree (F3)',
+ kind=wx.ITEM_CHECK)
+ expandTreeTool = tbar.AddLabelTool(-1, 'Expand', expandTreeBmp,
+ shortHelp='Expand all tree items (F4)')
+ collapseTreeTool = tbar.AddLabelTool(-1, 'Collapse', collapseTreeBmp,
+ shortHelp='Collapse all tree items (F5)')
+ highlightItemTool = tbar.AddLabelTool(-1, 'Highlight', highlightItemBmp,
+ shortHelp='Attempt to highlight live item (F6)')
+ evtWatcherTool = tbar.AddLabelTool(-1, 'Events', evtWatcherBmp,
+ shortHelp='Watch the events of the selected item (F7)')
+
+ toggleFillingTool = tbar.AddLabelTool(-1, 'Filling', toggleFillingBmp,
+ shortHelp='Show PyCrust \'filling\' (F8)',
+ kind=wx.ITEM_CHECK)
+ tbar.Realize()
+
+ self.Bind(wx.EVT_TOOL, self.OnRefreshTree, refreshTool)
+ self.Bind(wx.EVT_TOOL, self.OnFindWidget, findWidgetTool)
+ self.Bind(wx.EVT_TOOL, self.OnShowSizers, showSizersTool)
+ self.Bind(wx.EVT_TOOL, self.OnExpandTree, expandTreeTool)
+ self.Bind(wx.EVT_TOOL, self.OnCollapseTree, collapseTreeTool)
+ self.Bind(wx.EVT_TOOL, self.OnHighlightItem, highlightItemTool)
+ self.Bind(wx.EVT_TOOL, self.OnWatchEvents, evtWatcherTool)
+ self.Bind(wx.EVT_TOOL, self.OnToggleFilling, toggleFillingTool)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnShowSizersUI, showSizersTool)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnWatchEventsUI, evtWatcherTool)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnToggleFillingUI, toggleFillingTool)
+
+ tbl = wx.AcceleratorTable(
+ [(wx.ACCEL_NORMAL, wx.WXK_F1, refreshTool.GetId()),
+ (wx.ACCEL_NORMAL, wx.WXK_F2, findWidgetTool.GetId()),
+ (wx.ACCEL_NORMAL, wx.WXK_F3, showSizersTool.GetId()),
+ (wx.ACCEL_NORMAL, wx.WXK_F4, expandTreeTool.GetId()),
+ (wx.ACCEL_NORMAL, wx.WXK_F5, collapseTreeTool.GetId()),
+ (wx.ACCEL_NORMAL, wx.WXK_F6, highlightItemTool.GetId()),
+ (wx.ACCEL_NORMAL, wx.WXK_F7, evtWatcherTool.GetId()),
+ (wx.ACCEL_NORMAL, wx.WXK_F8, toggleFillingTool.GetId()),
+ ])
+ self.SetAcceleratorTable(tbl)
+
+
+ def _postStartup(self):
+ if self.crust.ToolsShown():
+ self.crust.ToggleTools()
+ self.UpdateInfo()
+ self.started = True
+
+
+ def OnClose(self, evt):
+ self.SaveSettings(self.config)
+ evt.Skip()
+ if hasattr(self, 'mgr'):
+ self.mgr.UnInit()
+ del self.mgr
+ if self.Parent:
+ tlw = self.Parent.GetTopLevelParent()
+ tlw.Unbind(wx.EVT_CLOSE, handler=self.OnClose)
+
+
+ def UpdateInfo(self):
+ self.info.UpdateInfo(self.obj)
+
+
+ def SetObj(self, obj):
+ if self.obj is obj:
+ return
+ self.locals['obj'] = self.obj = obj
+ self.UpdateInfo()
+ if not self.tree.built:
+ self.tree.BuildTree(obj, includeSizers=self.includeSizers)
+ else:
+ self.tree.SelectObj(obj)
+
+
+ def HighlightCurrentItem(self):
+ """
+ Draw a highlight rectangle around the item represented by the
+ current tree selection.
+ """
+ if not hasattr(self, 'highlighter'):
+ self.highlighter = _InspectionHighlighter()
+ self.highlighter.HighlightCurrentItem(self.tree)
+
+
+ def RefreshTree(self):
+ self.tree.BuildTree(self.obj, includeSizers=self.includeSizers)
+
+
+ def OnRefreshTree(self, evt):
+ self.RefreshTree()
+ self.UpdateInfo()
+
+
+ def OnFindWidget(self, evt):
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLost)
+ self.CaptureMouse()
+ self.finding = wx.BusyInfo("Click on any widget in the app...")
+
+
+ def OnCaptureLost(self, evt):
+ self.Unbind(wx.EVT_LEFT_DOWN)
+ self.Unbind(wx.EVT_MOUSE_CAPTURE_LOST)
+ del self.finding
+
+ def OnLeftDown(self, evt):
+ self.ReleaseMouse()
+ wnd = wx.FindWindowAtPointer()
+ if wnd is not None:
+ self.SetObj(wnd)
+ else:
+ wx.Bell()
+ self.OnCaptureLost(evt)
+
+
+ def OnShowSizers(self, evt):
+ self.includeSizers = not self.includeSizers
+ self.RefreshTree()
+
+
+ def OnExpandTree(self, evt):
+ current = self.tree.GetSelection()
+ self.tree.ExpandAll()
+ self.tree.EnsureVisible(current)
+
+
+ def OnCollapseTree(self, evt):
+ current = self.tree.GetSelection()
+ self.tree.CollapseAll()
+ self.tree.EnsureVisible(current)
+ self.tree.SelectItem(current)
+
+
+ def OnHighlightItem(self, evt):
+ self.HighlightCurrentItem()
+
+
+ def OnWatchEvents(self, evt):
+ item = self.tree.GetSelection()
+ obj = self.tree.GetItemPyData(item)
+ if isinstance(obj, wx.Window):
+ import wx.lib.eventwatcher as ew
+ watcher = ew.EventWatcher(self)
+ watcher.watch(obj)
+ watcher.Show()
+
+ def OnWatchEventsUI(self, evt):
+ item = self.tree.GetSelection()
+ if item:
+ obj = self.tree.GetItemPyData(item)
+ evt.Enable(isinstance(obj, wx.Window))
+
+
+ def OnToggleFilling(self, evt):
+ self.crust.ToggleTools()
+
+
+ def OnShowSizersUI(self, evt):
+ evt.Check(self.includeSizers)
+
+
+ def OnToggleFillingUI(self, evt):
+ if self.started:
+ evt.Check(self.crust.ToolsShown())
+
+
+ def LoadSettings(self, config):
+ self.crust.LoadSettings(config)
+ self.info.LoadSettings(config)
+
+ pos = wx.Point(config.ReadInt('Window/PosX', -1),
+ config.ReadInt('Window/PosY', -1))
+
+ size = wx.Size(config.ReadInt('Window/Width', -1),
+ config.ReadInt('Window/Height', -1))
+ self.SetSize(size)
+ self.Move(pos)
+ rect = utils.AdjustRectToScreen(self.GetRect())
+ self.SetRect(rect)
+
+ perspective = config.Read('perspective', '')
+ if perspective:
+ try:
+ self.mgr.LoadPerspective(perspective)
+ except wx.PyAssertionError:
+ # ignore bad perspective string errors
+ pass
+ self.includeSizers = config.ReadBool('includeSizers', False)
+
+
+ def SaveSettings(self, config):
+ self.crust.SaveSettings(config)
+ self.info.SaveSettings(config)
+
+ if not self.IsIconized() and not self.IsMaximized():
+ w, h = self.GetSize()
+ config.WriteInt('Window/Width', w)
+ config.WriteInt('Window/Height', h)
+
+ px, py = self.GetPosition()
+ config.WriteInt('Window/PosX', px)
+ config.WriteInt('Window/PosY', py)
+
+ perspective = self.mgr.SavePerspective()
+ config.Write('perspective', perspective)
+ config.WriteBool('includeSizers', self.includeSizers)
+
+#---------------------------------------------------------------------------
+
+# should inspection frame (and children) be includeed in the tree?
+INCLUDE_INSPECTOR = True
+
+USE_CUSTOMTREECTRL = False
+if USE_CUSTOMTREECTRL:
+ import wx.lib.agw.customtreectrl as CT
+ TreeBaseClass = CT.CustomTreeCtrl
+else:
+ TreeBaseClass = wx.TreeCtrl
+
+class InspectionTree(TreeBaseClass):
+ """
+ All of the widgets in the app, and optionally their sizers, are
+ loaded into this tree.
+ """
+ def __init__(self, *args, **kw):
+ #s = kw.get('style', 0)
+ #kw['style'] = s | wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT
+ TreeBaseClass.__init__(self, *args, **kw)
+ self.roots = []
+ self.built = False
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectionChanged)
+ self.toolFrame = wx.GetTopLevelParent(self)
+ if 'wxMac' in wx.PlatformInfo:
+ self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+
+
+ def BuildTree(self, startWidget, includeSizers=False, expandFrame=False):
+ if self.GetCount():
+ self.DeleteAllItems()
+ self.roots = []
+ self.built = False
+
+ realRoot = self.AddRoot('Top-level Windows')
+
+ for w in wx.GetTopLevelWindows():
+ if w is wx.GetTopLevelParent(self) and not INCLUDE_INSPECTOR:
+ continue
+ root = self._AddWidget(realRoot, w, includeSizers)
+ self.roots.append(root)
+
+ # Expand the subtree containing the startWidget, and select it.
+ if not startWidget or not isinstance(startWidget, wx.Window):
+ startWidget = wx.GetApp().GetTopWindow()
+ if expandFrame:
+ top = wx.GetTopLevelParent(startWidget)
+ topItem = self.FindWidgetItem(top)
+ if topItem:
+ self.ExpandAllChildren(topItem)
+ self.built = True
+ self.SelectObj(startWidget)
+
+
+ def _AddWidget(self, parentItem, widget, includeSizers):
+ text = self.GetTextForWidget(widget)
+ item = self.AppendItem(parentItem, text)
+ self.SetItemPyData(item, widget)
+
+ # Add the sizer and widgets in the sizer, if we're showing them
+ widgetsInSizer = []
+ if includeSizers and widget.GetSizer() is not None:
+ widgetsInSizer = self._AddSizer(item, widget.GetSizer())
+
+ # Add any children not in the sizer, or all children if we're
+ # not showing the sizers
+ for child in widget.GetChildren():
+ if (not child in widgetsInSizer and
+ (not child.IsTopLevel() or
+ isinstance(child, wx.PopupWindow))):
+ self._AddWidget(item, child, includeSizers)
+
+ return item
+
+
+ def _AddSizer(self, parentItem, sizer):
+ widgets = []
+ text = self.GetTextForSizer(sizer)
+ item = self.AppendItem(parentItem, text)
+ self.SetItemPyData(item, sizer)
+ self.SetItemTextColour(item, "blue")
+
+ for si in sizer.GetChildren():
+ if si.IsWindow():
+ w = si.GetWindow()
+ self._AddWidget(item, w, True)
+ widgets.append(w)
+ elif si.IsSizer():
+ ss = si.GetSizer()
+ widgets += self._AddSizer(item, ss)
+ ss._parentSizer = sizer
+ else:
+ i = self.AppendItem(item, "Spacer")
+ self.SetItemPyData(i, si)
+ self.SetItemTextColour(i, "blue")
+ return widgets
+
+
+ def FindWidgetItem(self, widget):
+ """
+ Find the tree item for a widget.
+ """
+ for item in self.roots:
+ found = self._FindWidgetItem(widget, item)
+ if found:
+ return found
+ return None
+
+ def _FindWidgetItem(self, widget, item):
+ if self.GetItemPyData(item) is widget:
+ return item
+ child, cookie = self.GetFirstChild(item)
+ while child:
+ found = self._FindWidgetItem(widget, child)
+ if found:
+ return found
+ child, cookie = self.GetNextChild(item, cookie)
+ return None
+
+
+ def GetTextForWidget(self, widget):
+ """
+ Returns the string to be used in the tree for a widget
+ """
+ if hasattr(widget, 'GetName'):
+ return "%s (\"%s\")" % (widget.__class__.__name__, widget.GetName())
+ return widget.__class__.__name__
+
+
+ def GetTextForSizer(self, sizer):
+ """
+ Returns the string to be used in the tree for a sizer
+ """
+ return "%s" % sizer.__class__.__name__
+
+
+ def SelectObj(self, obj):
+ item = self.FindWidgetItem(obj)
+ if item:
+ self.EnsureVisible(item)
+ self.SelectItem(item)
+
+
+ def OnSelectionChanged(self, evt):
+ item = evt.GetItem()
+ if item:
+ obj = self.GetItemPyData(item)
+ self.toolFrame.SetObj(obj)
+
+
+#---------------------------------------------------------------------------
+
+class InspectionInfoPanel(wx.stc.StyledTextCtrl):
+ """
+ Used to display information about the currently selected items.
+ Currently just a read-only wx.stc.StyledTextCtrl with some plain
+ text. Should probably add some styles to make things easier to
+ read.
+ """
+ def __init__(self, *args, **kw):
+ wx.stc.StyledTextCtrl.__init__(self, *args, **kw)
+
+ from wx.py.editwindow import FACES
+ self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT,
+ "face:%(mono)s,size:%(size)d,back:%(backcol)s" % FACES)
+ self.StyleClearAll()
+ self.SetReadOnly(True)
+ self.SetMarginType(1, 0)
+ self.SetMarginWidth(1, 0)
+ self.SetSelForeground(True, wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
+ self.SetSelBackground(True, wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT))
+
+
+ def LoadSettings(self, config):
+ zoom = config.ReadInt('View/Zoom/Info', 0)
+ self.SetZoom(zoom)
+
+ def SaveSettings(self, config):
+ config.WriteInt('View/Zoom/Info', self.GetZoom())
+
+
+ def UpdateInfo(self, obj):
+ st = []
+ if not obj:
+ st.append("Item is None or has been destroyed.")
+
+ elif isinstance(obj, wx.Window):
+ st += self.FmtWidget(obj)
+
+ elif isinstance(obj, wx.Sizer):
+ st += self.FmtSizer(obj)
+
+ elif isinstance(obj, wx.SizerItem):
+ st += self.FmtSizerItem(obj)
+
+ self.SetReadOnly(False)
+ self.SetText('\n'.join(st))
+ self.SetReadOnly(True)
+
+
+ def Fmt(self, name, value):
+ if isinstance(value, (str, unicode)):
+ return " %s = '%s'" % (name, value)
+ else:
+ return " %s = %s" % (name, value)
+
+
+ def FmtWidget(self, obj):
+ def _countChildren(children):
+ count = 0
+ for child in children:
+ if not child.IsTopLevel():
+ count += 1
+ count += _countChildren(child.GetChildren())
+ return count
+ def _countAllChildren(children):
+ count = 0
+ for child in children:
+ count += 1
+ count += _countAllChildren(child.GetChildren())
+ return count
+
+ count = len([c for c in obj.GetChildren() if not c.IsTopLevel()])
+ rcount = _countChildren(obj.GetChildren())
+ tlwcount = _countAllChildren(obj.GetChildren())
+
+ st = ["Widget:"]
+ if hasattr(obj, 'GetName'):
+ st.append(self.Fmt('name', obj.GetName()))
+ st.append(self.Fmt('class', obj.__class__))
+ st.append(self.Fmt('bases', obj.__class__.__bases__))
+ st.append(self.Fmt('module', inspect.getmodule(obj)))
+ if hasattr(obj, 'this'):
+ st.append(self.Fmt('this', repr(obj.this)))
+ st.append(self.Fmt('id', obj.GetId()))
+ st.append(self.Fmt('style', obj.GetWindowStyle()))
+ st.append(self.Fmt('pos', obj.GetPosition()))
+ st.append(self.Fmt('size', obj.GetSize()))
+ st.append(self.Fmt('minsize', obj.GetMinSize()))
+ st.append(self.Fmt('bestsize', obj.GetBestSize()))
+ st.append(self.Fmt('client size', obj.GetClientSize()))
+ st.append(self.Fmt('virtual size',obj.GetVirtualSize()))
+ st.append(self.Fmt('IsEnabled', obj.IsEnabled()))
+ st.append(self.Fmt('IsShown', obj.IsShown()))
+ st.append(self.Fmt('IsFrozen', obj.IsFrozen()))
+ st.append(self.Fmt('fg color', obj.GetForegroundColour()))
+ st.append(self.Fmt('bg color', obj.GetBackgroundColour()))
+ st.append(self.Fmt('label', obj.GetLabel()))
+ if hasattr(obj, 'GetTitle'):
+ st.append(self.Fmt('title', obj.GetTitle()))
+ if hasattr(obj, 'GetValue'):
+ try:
+ st.append(self.Fmt('value', obj.GetValue()))
+ except:
+ pass
+ st.append(' child count = %d (direct) %d (recursive) %d (include TLWs)' %
+ (count, rcount, tlwcount))
+ if obj.GetContainingSizer() is not None:
+ st.append('')
+ sizer = obj.GetContainingSizer()
+ st += self.FmtSizerItem(sizer.GetItem(obj))
+ return st
+
+
+ def FmtSizerItem(self, obj):
+ if obj is None:
+ return ['SizerItem: None']
+
+ st = ['SizerItem:']
+ st.append(self.Fmt('proportion', obj.GetProportion()))
+ st.append(self.Fmt('flag',
+ FlagsFormatter(itemFlags, obj.GetFlag())))
+ st.append(self.Fmt('border', obj.GetBorder()))
+ st.append(self.Fmt('pos', obj.GetPosition()))
+ st.append(self.Fmt('size', obj.GetSize()))
+ st.append(self.Fmt('minsize', obj.GetMinSize()))
+ st.append(self.Fmt('ratio', obj.GetRatio()))
+ st.append(self.Fmt('IsWindow', obj.IsWindow()))
+ st.append(self.Fmt('IsSizer', obj.IsSizer()))
+ st.append(self.Fmt('IsSpacer', obj.IsSpacer()))
+ st.append(self.Fmt('IsShown', obj.IsShown()))
+ if isinstance(obj, wx.GBSizerItem):
+ st.append(self.Fmt('cellpos', obj.GetPos()))
+ st.append(self.Fmt('cellspan', obj.GetSpan()))
+ st.append(self.Fmt('endpos', obj.GetEndPos()))
+ return st
+
+
+ def FmtSizer(self, obj):
+ st = ['Sizer:']
+ st.append(self.Fmt('class', obj.__class__))
+ if hasattr(obj, 'this'):
+ st.append(self.Fmt('this', repr(obj.this)))
+ st.append(self.Fmt('pos', obj.GetPosition()))
+ st.append(self.Fmt('size', obj.GetSize()))
+ st.append(self.Fmt('minsize', obj.GetMinSize()))
+ if isinstance(obj, wx.BoxSizer):
+ st.append(self.Fmt('orientation',
+ FlagsFormatter(orientFlags, obj.GetOrientation())))
+ if isinstance(obj, wx.GridSizer):
+ st.append(self.Fmt('cols', obj.GetCols()))
+ st.append(self.Fmt('rows', obj.GetRows()))
+ st.append(self.Fmt('vgap', obj.GetVGap()))
+ st.append(self.Fmt('hgap', obj.GetHGap()))
+ if isinstance(obj, wx.FlexGridSizer):
+ st.append(self.Fmt('rowheights', obj.GetRowHeights()))
+ st.append(self.Fmt('colwidths', obj.GetColWidths()))
+ st.append(self.Fmt('flexdir',
+ FlagsFormatter(orientFlags, obj.GetFlexibleDirection())))
+ st.append(self.Fmt('nonflexmode',
+ FlagsFormatter(flexmodeFlags, obj.GetNonFlexibleGrowMode())))
+ if isinstance(obj, wx.GridBagSizer):
+ st.append(self.Fmt('emptycell', obj.GetEmptyCellSize()))
+
+ if hasattr(obj, '_parentSizer'):
+ st.append('')
+ st += self.FmtSizerItem(obj._parentSizer.GetItem(obj))
+
+ return st
+
+
+class FlagsFormatter(object):
+ def __init__(self, d, val):
+ self.d = d
+ self.val = val
+
+ def __str__(self):
+ st = []
+ for k in self.d.keys():
+ if self.val & k:
+ st.append(self.d[k])
+ if st:
+ return '|'.join(st)
+ else:
+ return '0'
+
+orientFlags = {
+ wx.HORIZONTAL : 'wx.HORIZONTAL',
+ wx.VERTICAL : 'wx.VERTICAL',
+ }
+
+itemFlags = {
+ wx.TOP : 'wx.TOP',
+ wx.BOTTOM : 'wx.BOTTOM',
+ wx.LEFT : 'wx.LEFT',
+ wx.RIGHT : 'wx.RIGHT',
+# wx.ALL : 'wx.ALL',
+ wx.EXPAND : 'wx.EXPAND',
+# wx.GROW : 'wx.GROW',
+ wx.SHAPED : 'wx.SHAPED',
+ wx.STRETCH_NOT : 'wx.STRETCH_NOT',
+# wx.ALIGN_CENTER : 'wx.ALIGN_CENTER',
+ wx.ALIGN_LEFT : 'wx.ALIGN_LEFT',
+ wx.ALIGN_RIGHT : 'wx.ALIGN_RIGHT',
+ wx.ALIGN_TOP : 'wx.ALIGN_TOP',
+ wx.ALIGN_BOTTOM : 'wx.ALIGN_BOTTOM',
+ wx.ALIGN_CENTER_VERTICAL : 'wx.ALIGN_CENTER_VERTICAL',
+ wx.ALIGN_CENTER_HORIZONTAL : 'wx.ALIGN_CENTER_HORIZONTAL',
+ wx.ADJUST_MINSIZE : 'wx.ADJUST_MINSIZE',
+ wx.FIXED_MINSIZE : 'wx.FIXED_MINSIZE',
+ }
+
+flexmodeFlags = {
+ wx.FLEX_GROWMODE_NONE : 'wx.FLEX_GROWMODE_NONE',
+ wx.FLEX_GROWMODE_SPECIFIED : 'wx.FLEX_GROWMODE_SPECIFIED',
+ wx.FLEX_GROWMODE_ALL : 'wx.FLEX_GROWMODE_ALL',
+ }
+
+
+
+
+#---------------------------------------------------------------------------
+
+class _InspectionHighlighter(object):
+ """
+ All the highlighting code. A separate class to help reduce the
+ clutter in InspectionFrame.
+ """
+
+ # should non TLWs be flashed too? Otherwise use a highlight rectangle
+ flashAll = False
+
+ color1 = 'red' # for widgets and sizers
+ color2 = 'red' # for item boundaries in sizers
+ color3 = '#00008B' # for items in sizers
+
+ highlightTime = 3000 # how long to display the highlights
+
+ # how to draw it
+ useOverlay = 'wxMac' in wx.PlatformInfo
+
+
+ def __init__(self):
+ if self.useOverlay:
+ self.overlay = wx.Overlay()
+
+
+ def HighlightCurrentItem(self, tree):
+ """
+ Draw a highlight rectangle around the item represented by the
+ current tree selection.
+ """
+ item = tree.GetSelection()
+ obj = tree.GetItemPyData(item)
+
+ if isinstance(obj, wx.Window):
+ self.HighlightWindow(obj)
+
+ elif isinstance(obj, wx.Sizer):
+ self.HighlightSizer(obj)
+
+ elif isinstance(obj, wx.SizerItem): # Spacer
+ pItem = tree.GetItemParent(item)
+ sizer = tree.GetItemPyData(pItem)
+ self.HighlightSizerItem(obj, sizer)
+
+ else:
+ raise RuntimeError("unknown object type: %s" % obj.__class__.__name__)
+
+
+ def HighlightWindow(self, win):
+ rect = win.GetRect()
+ tlw = win.GetTopLevelParent()
+ if self.flashAll or tlw is win:
+ self.FlickerTLW(win)
+ return
+ else:
+ pos = self.FindHighlightPos(tlw, win.ClientToScreen((0,0)))
+ rect.SetPosition(pos)
+ self.DoHighlight(tlw, rect, self.color1)
+
+
+ def HighlightSizerItem(self, item, sizer, penWidth=2):
+ win = sizer.GetContainingWindow()
+ tlw = win.GetTopLevelParent()
+ rect = item.GetRect()
+ pos = rect.GetPosition()
+ pos = self.FindHighlightPos(tlw, win.ClientToScreen(pos))
+ rect.SetPosition(pos)
+ if rect.width < 1: rect.width = 1
+ if rect.width < 1: rect.width = 1
+ self.DoHighlight(tlw, rect, self.color1, penWidth)
+
+
+ def HighlightSizer(self, sizer):
+ # first do the outline of the whole sizer like normal
+ win = sizer.GetContainingWindow()
+ tlw = win.GetTopLevelParent()
+ pos = sizer.GetPosition()
+ pos = self.FindHighlightPos(tlw, win.ClientToScreen(pos))
+ rect = wx.RectPS(pos, sizer.GetSize())
+ dc, dco = self.DoHighlight(tlw, rect, self.color1)
+
+ # Now highlight the actual items within the sizer. This may
+ # get overdrawn by the code below for item boundaries, but if
+ # there is border padding then this will help make it more
+ # obvious.
+ dc.SetPen(wx.Pen(self.color3, 1))
+ for item in sizer.GetChildren():
+ if item.IsShown():
+ if item.IsWindow():
+ r = item.GetWindow().GetRect()
+ elif item.IsSizer():
+ p = item.GetSizer().GetPosition()
+ s = item.GetSizer().GetSize()
+ r = wx.RectPS(p,s)
+ else:
+ continue
+ r = self.AdjustRect(tlw, win, r)
+ dc.DrawRectangleRect(r)
+
+ # Next highlight the area allocated to each item in the sizer.
+ # Each kind of sizer will need to be done a little
+ # differently.
+ dc.SetPen(wx.Pen(self.color2, 1))
+
+ if isinstance(sizer, wx.WrapSizer):
+ for item in sizer.GetChildren():
+ ir = self.AdjustRect(tlw, win, item.Rect)
+ dc.DrawRectangleRect(ir)
+
+ # wx.BoxSizer, wx.StaticBoxSizer
+ elif isinstance(sizer, wx.BoxSizer):
+ # NOTE: we have to do some reverse-engineering here for
+ # borders because the sizer and sizer item don't give us
+ # enough information to know for sure where item
+ # (allocated) boundaries are, just the boundaries of the
+ # actual widgets. TODO: It would be nice to add something
+ # to wx.SizerItem that would give us the full bounds, but
+ # that will have to wait until 2.9...
+ x, y = rect.GetPosition()
+ if sizer.Orientation == wx.HORIZONTAL:
+ y1 = y + rect.height
+ for item in sizer.GetChildren():
+ ir = self.AdjustRect(tlw, win, item.Rect)
+ x = ir.x
+ if item.Flag & wx.LEFT:
+ x -= item.Border
+ dc.DrawLine(x, y, x, y1)
+ if item.IsSizer():
+ dc.DrawRectangleRect(ir)
+
+ if sizer.Orientation == wx.VERTICAL:
+ x1 = x + rect.width
+ for item in sizer.GetChildren():
+ ir = self.AdjustRect(tlw, win, item.Rect)
+ y = ir.y
+ if item.Flag & wx.TOP:
+ y -= item.Border
+ dc.DrawLine(x, y, x1, y)
+ if item.IsSizer():
+ dc.DrawRectangleRect(ir)
+
+ # wx.FlexGridSizer, wx.GridBagSizer
+ elif isinstance(sizer, wx.FlexGridSizer):
+ sizer.Layout()
+ y = rect.y
+ for rh in sizer.RowHeights[:-1]:
+ y += rh
+ dc.DrawLine(rect.x, y, rect.x+rect.width, y)
+ y+= sizer.VGap
+ dc.DrawLine(rect.x, y, rect.x+rect.width, y)
+ x = rect.x
+ for cw in sizer.ColWidths[:-1]:
+ x += cw
+ dc.DrawLine(x, rect.y, x, rect.y+rect.height)
+ x+= sizer.HGap
+ dc.DrawLine(x, rect.y, x, rect.y+rect.height)
+
+ # wx.GridSizer
+ elif isinstance(sizer, wx.GridSizer):
+ # NOTE: More reverse engineering (see above.) This time we
+ # need to determine what the sizer is using for row
+ # heights and column widths.
+ #rh = cw = 0
+ #for item in sizer.GetChildren():
+ # rh = max(rh, item.Size.height)
+ # cw = max(cw, item.Size.width)
+ cw = (rect.width - sizer.HGap*(sizer.Cols-1)) / sizer.Cols
+ rh = (rect.height - sizer.VGap*(sizer.Rows-1)) / sizer.Rows
+ y = rect.y
+ for i in range(sizer.Rows-1):
+ y += rh
+ dc.DrawLine(rect.x, y, rect.x+rect.width, y)
+ y+= sizer.VGap
+ dc.DrawLine(rect.x, y, rect.x+rect.width, y)
+ x = rect.x
+ for i in range(sizer.Cols-1):
+ x += cw
+ dc.DrawLine(x, rect.y, x, rect.y+rect.height)
+ x+= sizer.HGap
+ dc.DrawLine(x, rect.y, x, rect.y+rect.height)
+
+ # Anything else is probably a custom sizer, just highlight the items
+ else:
+ del dc, odc
+ for item in sizer.GetChildren():
+ self.HighlightSizerItem(item, sizer, 1)
+
+
+ def FindHighlightPos(self, tlw, pos):
+ if self.useOverlay:
+ # We'll be using a ClientDC in this case so adjust the
+ # position accordingly
+ pos = tlw.ScreenToClient(pos)
+ return pos
+
+
+ def AdjustRect(self, tlw, win, rect):
+ pos = self.FindHighlightPos(tlw, win.ClientToScreen(rect.Position))
+ rect.Position = pos
+ return wx.RectPS(pos, rect.Size)
+
+
+ def DoHighlight(self, tlw, rect, colour, penWidth=2):
+ if not tlw.IsFrozen():
+ tlw.Freeze()
+
+ if self.useOverlay:
+ dc = wx.ClientDC(tlw)
+ dco = wx.DCOverlay(self.overlay, dc)
+ dco.Clear()
+ else:
+ dc = wx.ScreenDC()
+ dco = None
+
+ dc.SetPen(wx.Pen(colour, penWidth))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ drawRect = wx.Rect(*rect)
+ dc.DrawRectangleRect(drawRect)
+
+ drawRect.Inflate(2,2)
+ if not self.useOverlay:
+ pos = tlw.ScreenToClient(drawRect.GetPosition())
+ drawRect.SetPosition(pos)
+ wx.CallLater(self.highlightTime, self.DoUnhighlight, tlw, drawRect)
+
+ return dc, dco
+
+
+ def DoUnhighlight(self, tlw, rect):
+ if not tlw:
+ return
+ if tlw.IsFrozen():
+ tlw.Thaw()
+ if self.useOverlay:
+ dc = wx.ClientDC(tlw)
+ dco = wx.DCOverlay(self.overlay, dc)
+ dco.Clear()
+ del dc, dco
+ self.overlay.Reset()
+ else:
+ tlw.RefreshRect(rect)
+
+
+ def FlickerTLW(self, tlw):
+ """
+ Use a timer to alternate a TLW between shown and hidded state a
+ few times. Use to highlight a TLW since drawing and clearing an
+ outline is trickier.
+ """
+ self.flickerCount = 0
+ tlw.Hide()
+ self.cl = wx.CallLater(300, self._Toggle, tlw)
+
+
+ def _Toggle(self, tlw):
+ if tlw.IsShown():
+ tlw.Hide()
+ self.cl.Restart()
+ else:
+ tlw.Show()
+ self.flickerCount += 1
+ if self.flickerCount < 4:
+ self.cl.Restart()
+
+
+#---------------------------------------------------------------------------
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+Refresh = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAABehJ"
+ "REFUSImdll1olNkZx3/vRzIxk5lJbMwmGHccP+JHS6VrYo3TKCvL0i0LLTRB8cbLitp6p9ib"
+ "elHohVLT0BqXBnetqBQveiWF0oXiF+1FS4PUxFgbm0yYTN/JZL4nmcl7/r3IJMRlodAHDhwO"
+ "z8d5/uf/PM+x+N9yADgDfAtwAAvwgafAJ8DfvsxIq3q4G86cuiHAB8C/gZLjOO/4vv8u8LWu"
+ "rq4lgGQy2dTQ0JDZuXPn9snJyXmgGYgBnwMGcCzwBZb7BedbgJ+5rntk69atJdd1f/D69evX"
+ "tm1bAwMDDA4ONlmWxYMHD5iYmGj0fT8BhGOx2Cezs7MdKysrfwZ+DCTXgmzMaovjOPdXs1tf"
+ "nwJXgX8ODQ0plUqpXC7r9OnTAmZDodDNtra2zzba2Lb9AOj8MtjGAIVCIfX29ppDhw6Z1tZW"
+ "AWpvb9fNmzf9dDqtUqmksbExPxQKCdC+ffvU29ur3t5eEw6H1wL9po7KunzgOM4/AB08eNBM"
+ "TU3J8zxdunRJtm3r4sWLkqRCoaBkMilJunz5smzb1oULFzQ/P6/p6Wn19/cbQK7rvgQ+2hig"
+ "Z/v27c8A9fX1yfM8JRIJJZNJzczMKJVKqVQqKZ/PK5fLqVgsKpVKaWZmRslkUolEQouLixoY"
+ "GDCAotHo34H9bEijMZvNft7W1hYJBAJf9zyPeDxOR0cHoVCIxsZGarUalmVhWRbGGILBIJFI"
+ "hGAwSK1WY3h4mIcPH1qVSuVue3v75cXFxQyQBzjQ09Pz3V27dn0jEon8qv5QmpmZ0crKirLZ"
+ "rMrlsr4olUpF2WxW1WpVnucpGAyu4f8LYKfjOB8CBxzgSqFQ+NhxnI8zmUxfMBiMnD9/nmPH"
+ "jtHY2Iht2xSLRcbHx3ny5AnPnz8nn88TCoXYtGkTxhh8f5WNExMTlMvlDtu2+4wx/cBugOeA"
+ "4vG4Tp48qdHRUV+SisWicrmcJOnp06d6//331dDQINu2dfToUT169EiSlMvlVCgUJEm3bt3y"
+ "BwcHdfz4cdm2rbpvXnR1dVVGRkaUy+WUz+eVTCbX95J07949NTQ0bOS6bt++LUnK5/PK5/Mq"
+ "FApKp9NKpVIaHR1Vd3f3MvDCZa1nuC6+72NZFsFg8K0CkbQOA4AxBmPMWzrFYpFwOIxlWdi2"
+ "jWVZAJYD/KhUKr2ztLTE48ePWVpaMocPH7Z838cYQyAQIJ/P8+rVK2ZnZ5HEkSNHGBoaIhqN"
+ "sry8jG3bbN68mfv375uRkRHr2bNnjI+PO0DKAq4AvbZtNxljdnR0dMTOnDnDuXPnCIfDABQK"
+ "BSYnJ5mensYYw44dO9i7dy/hcBhJVCoVRkZGGB4eJpfLzXV2ds5mMpmVarX6AqDDcZzj9cL4"
+ "+f9L0+bmZgEKh8O3enp6+vbs2fN94D0HKEmqxWKxYDabPRqJRN47e/YsAwMDBINBXNfFGEOl"
+ "UqFarVKtVtdhCQQCACwvL1Or1VhcXKRUKk3Ozc39cWFh4V/Ay7U32rWxVczPzyuRSMjzPHme"
+ "p4WFBRUKhbcYk8lk5Hme0um0EomE0um04vG4AMVisWfAPoFl1wNsT8zNbV4jTaVSIRgMcv36"
+ "daLRKFevXqWlpYVyuQxAS0sLN27cIBqNcu3aNZqamlhaWkKSABKJxBYgZoEQWEOrPenTOobq"
+ "7+838Xjc7N+/X4BaWlo0Njbm5/N5ZbNZ3blzx+/s7BSg1tZWxeNxxePx9fYO3AUaV69brwOg"
+ "qz4s1guqtbX1t+Fw+NfA7IkTJ5TL5ZTJZHTq1CkBb4BfAp9ttHFd93dA95pvF+AgNPwVksaY"
+ "HwIV13W/2d3dnX/z5s1Pd+/e7TQ3N+9LJpPdd+/exXVdPM/Dtu2XxpiRWCzWJOmrc3NzbbVa"
+ "7S8rKyuXgASrqBh+AnY9i43z+aM6bbf29PR8LxAI/AlQd3f38rZt25YdxxHwB8dxvg28C+wF"
+ "vrMOS30MrGdwBSytDmgLMBb8fo1eU1NT7cAE8JVEIrHx2zLt+/5/gJm66mT9oharPwsL4L/1"
+ "GXlKb/xX4wAAAABJRU5ErkJggg==")
+
+Find = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAABgRJ"
+ "REFUSIm1lU1oG9sVx/9z5440+kBWJUvGDZESXuskZPMIwVaoybNp4niXEChdJPDAIWk+IGnA"
+ "i1Ioz9208apk10WcZFMI3Zgugrww6cNxKcakdoK/ghU7k5EsW2PLljXfc2duFw/5uaRv1x4Y"
+ "uHc4c3/38P+fM8D/OYTDm7Gxsd/4vv/H169fQ5IkAIDjODh16hSy2ey3t27d6geAJ0+eFDVN"
+ "G1xYWEA4HAYAeJ6H3t5eUEp/f+PGjZHPSOPj48P37t1j+XyeAzh4QqEQLxQK/Pr1639v5V67"
+ "dq3Y29t7kEMI4aIo8lwux2/fvs3Gx8d/28qlrYXv+18RQsTNzU129epVWigUUC6X8fz5c8zN"
+ "zUEQBKuVu7a2Zs7MzOD06dO4c+cOJicnUavVMDs7ywRBoIyxfgB/+A8ApXS7Xq8jkUjQCxcu"
+ "4MqVK1hbW8OrV6/w6dMndHV1fXHmzJmvCSGs2WyeePPmDU6ePImbN2+CUgpVVVEqleju7i4o"
+ "pdufVSDLMhhj0DQNMzMz2Nragu/72N7ehizLLJ1Od3me91wQBKRSKSSTSW9+fl56/PgxFhcX"
+ "IQgCNE2DbdsIhUL4DOC6LjjnIIRAFEXU63VYloUgCBAEAVUUJTBN0wGAWCwW5pxLtm1jdXUV"
+ "mqYhnU4fGIMxdgAgrcWHDx+aiqJAFEVks1l4nodisQjHcdDT04NsNvuPYrEYLRaL0Ww2++rc"
+ "uXMwDAMTExM4duwYGGNwXRfVahUrKysHABEA7t69+7u3b9/ekmU50t3dDV3XMTExgUqlAlmW"
+ "cfbsWdi2Td+9e3cEwIWurq6vkslk29LSEmq1GjRNQz6fR0dHByRJgqqq06VS6eUBoLu7+2+r"
+ "q6s/2traYslkkszOzkJRFMiyjFwux8LhMNF1PWGa5rl4PP6zeDze5rouDMNg9Xqd7O3tQRRF"
+ "ZDIZqKqKcrncdv/+/a2pqalFCgDhcPhjpVL50jRNWigU0N/fj0uXLkFVVayvr9OFhYVSNBot"
+ "p1KpPgAol8tTjUajI5/PnxgYGIAoitB1HdVqFe/fv/dyudxPG43GXwD8FQDw8OHDuVQqxQcG"
+ "BnitVuOGYfD19XU+PDzM29raOIBhAJFDDZgEcLuvr48risKbzSbXNI2PjIxwWZZ5LpfjDx48"
+ "WD5wESEElFLoug5VVRGJRFAqlaDressZDIB7qPE9AL7jOFBVFYZhYGNjA3t7e5AkCYIggBDy"
+ "vU0dx3FM04Smadjc3IQsy1heXoZpmq1Z8ysAg4cA4wB+7DgOKpUKPM/DysoKdnZ2YJomJEmC"
+ "4zguAIhjY2MjL168+DmAeKFQQGdnJ2zbRrVaRb1ex/Lyssc57+jp6fnJ8ePHkc/ncfTo0S/K"
+ "5XI2kUh43d3douu6KJfLkCQJ7e3taDQaqFQq4qNHj2KUMfbN4uIiLl686J8/f16sVqtIJpNw"
+ "HAecc9i2LeVyOQwODm7ruv4tgCAej/dVq9WsYRiSaZpwHAe6riMajeLy5ctgjPkvX75sZ4x9"
+ "Q6anp8E5RyaTET3Pw87ODmzbxs7ODhhjoJSCEIL9/f1/jY6O/mJ0dPSXzWbzn5RSuK6Ler0O"
+ "27bRaDSgKAosy0ImkxEBYHp6GqQlimVZYIyBEALHcUAIgSB897vgnINzHjqkQbg1VgRBgOM4"
+ "EAQBoVAInufBsr4bvJIkodUHKJVKkGUZrutid3cXhmHA9338UFBKYRgGVldXEQqFYJomLMvC"
+ "3NwcSqXSwVyirRuKoohUKoVYLIZMJoOPHz8iCALIsvxfQUEQgFKKzs5OdHR0QFVVbG9vgzEG"
+ "y7K+t2kkEkEQBFBVNVhaWiLRaBTxeByKoiAIAtRqNT+dTosA2g8d3k4pRb1e9+fn58V0Og1V"
+ "VdFsNsE5h6Ioge/7JBKJgFqWNX/kyJETGxsbkampKXDOEQTBQYmSJInxeBwAploAQsjrWCx2"
+ "VpIkcXJyEr7vQ5Kkw7qRzs5Ox7KsZQEAhoaG5iKRyJctcQ5HIpFAo9H487Nnz+4cfj80NPSn"
+ "RCLx6/39/c++kWUZtm2vPH369NQPivi/in8Df18XwyUA5+QAAAAASUVORK5CYII=")
+
+ShowSizers = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAABChJ"
+ "REFUSIm1lU1oXFUUx3/33nn3zbx5mcm0M5OZxGlNAn6XUqlRKIIWKrXqRlCLOwvitrooqKDg"
+ "RhcirkSpigSECl0WBa104UKoSIoLS8TWlja1NTOTyUzz5s37uNdFWpumJSktHriry//8zj38"
+ "z7nwP4dY5/7BUqn0quu62621i9cJhSjGcTzTarUOAr/dFn1sbGy/N+SdksgoQ2bh2mFBQpTz"
+ "vdP1ev3AWjkya10qpe4yPbPZ3GeUecEMswQoYK4I3w+wzWiz3qgbtw0AQoHoswWfNxyYLYE2"
+ "8GcVfr8IzU5gjOnfCWA5YuCvHPw0CRkLhGDjW5LeGiAFWjGcaYKyUHLAwvoeWQcgpczZjM3z"
+ "A3CiD5fPAlikFXRicNy8lNJbK4das/A0VdKVJd/4oWqJZhSGVcJUeH3n5JA/NGe1OhEG/W+i"
+ "KJq9LUAURe1KuVJQrrqnn4YVrXXkOE5gFCpf8NteLvdts9k8AgRXJDf0bC1ArlgsTiVJsqfX"
+ "6+1K03RQLpenfd//tdvtbh0MBvdaaxe01pcGg8FFlq1wU8jNoqiUeq5Wqx3SWlutdWvTpk3v"
+ "ANuBbY1G423Xdecdx7EjIyOHlVLPA6X1kl4lK6XU7rGxsU+UUkue54XlcvlL4LEVL36kUql8"
+ "ns/nl6SUwejo6EGl1DNcM81/r7ihRfl8fmehUHil2Wzu1Vr3Xdc9lCTJZ4PB4DhXzAlcAOa0"
+ "1koIMdntdqdKpZInhGjHcXx6ZT4FjDQajR21Wm2L7/sPJ0nyYr/ff1ZKOV8ul2eTJDnS6XSO"
+ "sjwN4mp1cRw3s9lssVQq1cIwVEmSbNVa+9VqNTsyMjLh+/744uJiT3ied8BxnJcx6QMS0wkH"
+ "UaEfJe6w4mc8v5AINWOS+KMgCGZWVuZ53taMlPtRaqovTRAv9LaTdQIn5y0oYzZkkaejOJ6m"
+ "Xq8fk0IkCGVxci2UnsfNz1MatSDtUN7rT0xMvLa6lePj4/v8wlAfsCVUuJFMZxh1eQMqyIFF"
+ "irRerx/LGGMCYa3ioV1f8el30/w4k8V178bNfMjHL3mcPREA0U1MES3ZNK2R6Z9katpgkpBU"
+ "jFLovcnJRz8QF54wxgTXVoUQl9iBzz/bniQlT39JIdecQywICfEwQwFkd4KqdAmDS8gKEMLK"
+ "XZTaOVImsbyOpM1QXiPkmgBAZBApeOEsS5OSjD8gJYsG6AFkhBA5C3D6+G72vudTGYXg8gYQ"
+ "0J6DDB4sK67LLISjhXQ6xLm3+OXxU6RuBGxEM0sPLFkhRC5jjDmntD5D2N4jDr8LsMCV+bCQ"
+ "t8Xhs0mStFYD4jhu55B/LEpx//vi/A5gieWdJLBoV+m2MeacAJ6uVqt7pZQNa+11v5MQohAE"
+ "wdFut/sFcH4VY9T3/X2+7z9lre2t0mXTNP17fn7+6/V6fMfxL1klnkaQRVDaAAAAAElFTkSu"
+ "QmCC")
+
+ShowFilling = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAZ5J"
+ "REFUSIntlc9KAkEcxz+tu7OxLRSuGUXtIfUpukW9QJcO3nqELoLXLr2Bt47dRBAqgxJ6BqMw"
+ "PJe0FEliaLNrFxV1zXatY9/TMDPf72eG3/yBf/2guaH2DrALrADtGfME8AKUgCsAdWhwX1XV"
+ "bSnlMtCZEaApivrqeXJxEmBDSrl+dHQoNjf3OD9/xjSDJ5vmMre3Z1xeHi8AG/3+YcAH8GEY"
+ "SbG6uoVtP2IYwQFLS2s8PT0MciYBALi5uUfTrrEsB88LDtB1C027A+h+N6cAvBUK+e6surg4"
+ "6wLvvSwAlHFKu/0ZfNkBvD6AEGJmwCSvrwaNRgOAZrMZKtw0zYF3KiCXy1Eul2m1WqEAhmFQ"
+ "q9VgrMg+QKVSoVqt4oU5QoCiKHQ6/vvpA2QyGdLpNPV6PRQgHo+Tz+fJZrPTAYlEgmQyiW3b"
+ "oQBCCFKpFIy+b36ArusDQ1j1vCM18B3TaDQaOrgvy7Jgyg7mgflisQiA4zihwmOxGKVSCUDv"
+ "ZTFOO/mL5zoSiby6rnsFHMDoDk6llA6//HBc1+1/OP8Kpi8497f1tG0HzQAAAABJRU5ErkJg"
+ "gg==")
+
+Icon = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAALhJ"
+ "REFUWIXtl80SgyAMhHeR99Y+eJseLAdHbJM0TjiwN2dI+MgfQpYFmSqpu0+AEQDqrwXyeorH"
+ "McvCEIBdm3F7/fr0FKgBRFaIrHkAdykdQFmEGm2HL233BAIAYmxYEqjePo9SBYBvBKppclDz"
+ "prMcqAhbAtknJx+3AKRHgGhnv4iApQY+jtSWpOY27BnifNt5uyk9BekAoZNwl21yDBSBi/63"
+ "yOMiLAXaf8AuwP9n94vzaTYBsgHeht4lXXmb7yQAAAAASUVORK5CYII=")
+
+CollapseTree = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAf9J"
+ "REFUSIm9lD9r20AYhx9Fxe5SKDIynVJodFMaChkC6eBCJ+WWdulSb1o6RR8gH6AfQF5aSksX"
+ "aQ0eajwVkinO1MFk0YXg0uLSISZDoQhcddAf5MR241buD4670/tyD+/vXh0sWdqUb1vAQ2Bj"
+ "Suwb0E7Xx38DaAKPgTuAnJLfSSEAn4DWIoAm8ByQruti2zYAlmUBoJSi2+3ieV4R1v0TJANs"
+ "AS8Ap9PpYFkWUSSuJFcqIUopAKSUAO+A18yxS0/nZ8AD13WFbdtEkWB9Hep1ODqC0QgMA8bj"
+ "GqYJhmGgaRq9Xm8I3AY+zgKspPMGIIuHZ6qn4/Q02UeRIIpEZqEkua+ZWpkXLEM3ipvEe9C0"
+ "ad2bqN+P89zr6P9WoJRidVXQ78e55/U09h1YW5vMTTWcB8i66B7wq1arie1ti/G4hmEknfNl"
+ "BD8Kh1cqIbp+ThAEVKtVBoNBCziZBfjX/wDgEHg0C7D0O8gs+grcAm76vi80TcM04eJCYZqg"
+ "6+ecnR0TBAGu6+L7PlJKhAgJQ+6SvF/vrwNsAm+BD0B8eTQajXztOMT7HnFrL48fpGNCizzX"
+ "Q5IXdDfdN/Y92Hna5s2rJ+y+zPPm3skiOoCkip+f23Fr70o1pWgCkoGKkKV3URnKqyjaxTKs"
+ "omCX4+SQ0pS1aew4xJub5VZwGZQdfv83yOfTR/iA1xwAAAAASUVORK5CYII=")
+
+ExpandTree = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAepJ"
+ "REFUSIm1lDFr20AYhp+ri+iSxUUhW4dIU9wlQ4YOKnRSj4K7Z9NSCFg/ID+gP0BZWkpLF3kN"
+ "Giq0pkOpMxWSTFIIFIqHQCFbUQnXQTpFslXXptYLx90nvdzD9913Bx1LtHzbA54Aj1v+nQFf"
+ "yvXpMoD7M/E+8AzYAmSLP66BbSBcBTACXED6vo/rugBYlgVAlmUkSSKDIND+rXJeCNEl2gNe"
+ "AV4cx1iWRZ7bc2bDSMmyDAApJcAH4C0LytUr5wPA8n3fdl2XPLfZ2YHNTbi+vjPf3j7ENKHf"
+ "7yOEYDKZTIHfwNe/Ae7V0pX1zbUGA8FgILi8LOI8t8lzW5dQ0t4Mc4DO1ADoA724ACEEQtx1"
+ "8XBYZDLrXQnQhRoA3SEAUaSIItWIz89Vm3e6DOAMiJMkwTBSALa3i6Gl14aRYhgpSZLgOA7A"
+ "t0WA/70HAJ+Bp//KoDPpi/YD2AAehGFoCyEwTbi5yTBN6PV+cnV1yng8xvd9wjBESoltp6Qp"
+ "jyjer4/LAPeB98AnQM0Ox3GqteehjgPU0WH1/6QcDa3yXE8pDnRUxs5xAM9fRrx7M2T0uvIt"
+ "PJNVdAJFFr++R+rocC6btagB0aA6pPMuWoeqLOrlootSUSuX51WQtUm3qfI81O7uejOYBenN"
+ "X/wBVz/ONKbGYPkAAAAASUVORK5CYII=")
+
+HighlightItem = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAQZJ"
+ "REFUSInFlTGSgjAUhv8XuIRl9ga0XgmuoI5abwfH8Ai22GlJZ0otuQD5t3DZ1V1CwgzgP8OQ"
+ "QCZfkv+9FxEVYUrFbYO2oW+wqEiGAtRzhyRIQh9eH+RXAMBmvfIuohcwheLnTnZ6vM3NjAaQ"
+ "1mTahvrAHwCzj+BJVI83sesHAMjRM3OVgNkFm/WK292+EzKvB86zr5Lu76b2AubdAbqMda0+"
+ "UOIqFdY2lKMHYGrw06DL3Tbrxzmi/Iq0JNLyO/Pxm/Uze/BXVRIUKajvKM6AXuh/kfjeHTC7"
+ "TAdw1RfahmlJFOewgtjvQY/0QgeNe3MUOVQsw2/OwQBRkQy5Op2lYixN7sEXVhRd4PXVHvwA"
+ "AAAASUVORK5CYII=")
+
+EvtWatcher = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAABwxJ"
+ "REFUSIltlltsXFcVhr+zzzlzztw949vMxGPHl3Hiqk6I07RJhcBGoUK0VSuaSFwahAChSkiV"
+ "QCotlQAJP/FAeKFPSChRJUAtqZACjUpJBCqUlEY0l7HjpraT+DKejDPjmfHcznXz0Bg1iPWy"
+ "ttbD/629tbT/pXB/KIAEVCADxIBdwMi93AX4QBlYA5aBIlADNvg/oXzirAIeoAcCgVFN0460"
+ "Wq0DuVzuc7VaLVspl52xsTHN9TwWFxfdbDarKYqysLKy8tdYLHalXq9fBG7fa0Dcy/8F7BSi"
+ "hmEcdF33Cc/znt63b1//1NRUMBQKqeFolOHRMTzbYmlxEcdx2Nrast+7eNFaWl6+bZrm667r"
+ "nnNd9ypg7Whq9yA+EInH4w/VarUTmqY9MTMz03vs2HFS/X1eOjvojmUHFM22sIMRXN/nxlxe"
+ "lutVdXLqYPTM73774KVLl+KKosSCwaBst9vXdiDqzg0MwzjSbDafBR6bmppKv/TSS+7MzLTs"
+ "7elTUwMp0ed7wlwvCnOwX8QjQaHHYiKdSCqHcjkvkckwl893VSqVbtd1DV3XC77vFwFFvff2"
+ "4wjxFen7xx46dCjzwosvuuO5nNbT0yuSXWFk0KSx3sa53aLal6QtBVFF0GdZinBsoaZSjO7e"
+ "LfP5fG+1Wu0TQmwbhnHLdd1tFRgIhULTtmV9Z3p6Ovvyyy+7ubExbWhoCEWoBBWPSzWdM4UE"
+ "C+U011YM3gvojCwskZAOzclxkgFDCYZCyv79+735+fnuUqkUjUQii51Op6YCWcdxnsiNjR0+"
+ "fuKE+cUjR+Sg7wurt5eA6bB2I8b3/1Hn3EKFY+UYzS2H2Y1bbFlpDuaydJsbBAo1woMDaLqO"
+ "lFIpFApsbGysxGKxD1XgwJ7x8ecOPPLI4NMPP+w9ODqq2uEwkSvLrJWzfP5PS/SoJb7xpSy/"
+ "GNUJd6noWoK3bn1E+a7D4XiaaJ+FpwWpVatKu9Vyt5vNrmaj4ZZKpUsCGCkWi/1d8TiZ3cMS"
+ "VcHvWLyvJHj2gy0mBz1+/7VJHvRXmDv5dc6e/jF1c4HUeJjXS02ev9HhcjCDY2ok0ymGRkak"
+ "qigU79xJCyFGNGBXrV4XXaEQxsiI4mnglRv8OZbjxvYax2cGaEfavPnTU/CrV1kH1qv/5Oi3"
+ "XyG1Z4wr60Xenw+xJ75JVzyAOzSkqIEAtmUZpmkOCqBrYmJCGx4bI9SxICCoZrJEFySvtNL8"
+ "xoqQ+uGP+OXJn0EkigiY8Ie/cPvfeY4GVX7QTMFNG+PGBqwX0KWv7H3gAbIDA4FOp5PQAN+2"
+ "LGlLiV6vozp1lOgAvq6wrnkc3FQpVvtYBYRl47s2AJoQtARsuS6RqE7j0Ql0Ddy7VdxOB8u2"
+ "JeALoLy0vOzevL5AvbsLPJPEu9exd8NPomtcr3jseupJeOYxcCyQEp47wa7Dh3hrq8PJ3iLa"
+ "uABVQVU1LMeR1+fnKZVKlmmamxqwtiuT8betDvXFRUlmEMZ7eDzZ4vrGCK9duUx/LsL0t37N"
+ "+sQ7aIZB6tHPkF8pYJeafDfdw5Pr8/j9uymUNvlwfl5quk4ymbQrlcqKBiwJIZaqtVpvcXVd"
+ "jA4OSW9olzJuW/xcKxJWDV5d1Ulne/jqp79Mx4U3i228lQDP70nyvf0msZaPVymzcrcsC8Wi"
+ "aGxvI4T4CFhSgWC9Xk90ms29vcPD4eHJSS9gu0JtO8Q6qxwaHmYpFmF5ZZPHb0VQq5Lzosg3"
+ "H0jzwsEg+qhLM9GLslGg4jj+uQvn1fNvv32rVCqdicfjH6iAHg6HzVKpNNWoVvt6+/tlJBAQ"
+ "aduiMZ4jNqiwt0cwkOjBNyVG3OXop7p5Zp9NT9ii09bwOy3my2X+/u678tXTp8Xq2trlZDL5"
+ "RrVaXVWBhuM4DdM01ZXV1ZFrV68md4+O+mp/v5Lo6kJKlRgukynJ/u46hwvzjOdMjFAAPAXL"
+ "arO4tMTfLlxgdnZWFIvFq4ZhnG40GheAzZ3vuuq6bktVVSqVSnd+bq53ct8+T1NVGYnElGg4"
+ "pPjSQ8VD85r43XGMaIzKZlmura95Fy9eFLOzs9RqtX8JId5wXfeP8PFk7wAUoBQMBu86jhOs"
+ "1Wp983Nz3YBotZredqPhSV/BcjzZDGjybrPl5/Nz3rWrV+XZs2e1U6dO+Xfu3MkLId7QNO01"
+ "z/MWd/z9fy3TCIfDeyzL+oLruk8NDw8PT05O9qiqqgcCAbl3YkJxfJ/r165JVQil0Wy2L1++"
+ "XC4WiwuGYZyRUp63bfsm4O5oftL0dyAiGAxmDMM4UK1WJ4eGhj67vb09tFWtkk6lDN9xZHFz"
+ "08pkMhJYKBQK7ySTyXylUrkClO51vmPD920V90GA/lgsFqrX6/26ro8oijJo23YC8E3TvGvb"
+ "9m0hxHI4HC7XarXmJ8Th49UHgP8A40NGDcCfTKIAAAAASUVORK5CYII=")
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/intctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/intctrl.py
new file mode 100644
index 0000000..0e34dc3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/intctrl.py
@@ -0,0 +1,921 @@
+#----------------------------------------------------------------------------
+# Name: wxPython.lib.intctrl.py
+# Author: Will Sadkin
+# Created: 01/16/2003
+# Copyright: (c) 2003 by Will Sadkin
+# RCS-ID: $Id$
+# License: wxWindows license
+#----------------------------------------------------------------------------
+# NOTE:
+# This was written to provide a standard integer edit control for wxPython.
+#
+# IntCtrl permits integer (long) values to be retrieved or set via
+# .GetValue() and .SetValue(), and provides an EVT_INT() event function
+# for trapping changes to the control.
+#
+# It supports negative integers as well as the naturals, and does not
+# permit leading zeros or an empty control; attempting to delete the
+# contents of the control will result in a (selected) value of zero,
+# thus preserving a legitimate integer value, or an empty control
+# (if a value of None is allowed for the control.) Similarly, replacing the
+# contents of the control with '-' will result in a selected (absolute)
+# value of -1.
+#
+# IntCtrl also supports range limits, with the option of either
+# enforcing them or simply coloring the text of the control if the limits
+# are exceeded.
+#----------------------------------------------------------------------------
+# 12/08/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 Compatability changes
+#
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxIntUpdateEvent -> IntUpdateEvent
+# o wxIntValidator -> IntValidator
+# o wxIntCtrl -> IntCtrl
+#
+
+import string
+import types
+
+import wx
+
+#----------------------------------------------------------------------------
+
+from sys import maxint
+MAXINT = maxint # (constants should be in upper case)
+MININT = -maxint-1
+
+#----------------------------------------------------------------------------
+
+# Used to trap events indicating that the current
+# integer value of the control has been changed.
+wxEVT_COMMAND_INT_UPDATED = wx.NewEventType()
+EVT_INT = wx.PyEventBinder(wxEVT_COMMAND_INT_UPDATED, 1)
+
+#----------------------------------------------------------------------------
+
+# wxWindows' wxTextCtrl translates Composite "control key"
+# events into single events before returning them to its OnChar
+# routine. The doc says that this results in 1 for Ctrl-A, 2 for
+# Ctrl-B, etc. However, there are no wxPython or wxWindows
+# symbols for them, so I'm defining codes for Ctrl-X (cut) and
+# Ctrl-V (paste) here for readability:
+WXK_CTRL_X = (ord('X')+1) - ord('A')
+WXK_CTRL_V = (ord('V')+1) - ord('A')
+
+class IntUpdatedEvent(wx.PyCommandEvent):
+ def __init__(self, id, value = 0, object=None):
+ wx.PyCommandEvent.__init__(self, wxEVT_COMMAND_INT_UPDATED, id)
+
+ self.__value = value
+ self.SetEventObject(object)
+
+ def GetValue(self):
+ """Retrieve the value of the control at the time
+ this event was generated."""
+ return self.__value
+
+
+#----------------------------------------------------------------------------
+
+class IntValidator( wx.PyValidator ):
+ """
+ Validator class used with IntCtrl; handles all validation of input
+ prior to changing the value of the underlying wx.TextCtrl.
+ """
+ def __init__(self):
+ wx.PyValidator.__init__(self)
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+
+ def Clone (self):
+ return self.__class__()
+
+ def Validate(self, window): # window here is the *parent* of the ctrl
+ """
+ Because each operation on the control is vetted as it's made,
+ the value of the control is always valid.
+ """
+ return 1
+
+
+ def OnChar(self, event):
+ """
+ Validates keystrokes to make sure the resulting value will a legal
+ value. Erasing the value causes it to be set to 0, with the value
+ selected, so it can be replaced. Similarly, replacing the value
+ with a '-' sign causes the value to become -1, with the value
+ selected. Leading zeros are removed if introduced by selection,
+ and are prevented from being inserted.
+ """
+ key = event.GetKeyCode()
+ ctrl = event.GetEventObject()
+
+ if 'wxMac' in wx.PlatformInfo:
+ if event.CmdDown() and key == ord('c'):
+ key = WXK_CTRL_C
+ elif event.CmdDown() and key == ord('v'):
+ key = WXK_CTRL_V
+
+ value = ctrl.GetValue()
+ textval = wx.TextCtrl.GetValue(ctrl)
+ allow_none = ctrl.IsNoneAllowed()
+
+ pos = ctrl.GetInsertionPoint()
+ sel_start, sel_to = ctrl.GetSelection()
+ select_len = sel_to - sel_start
+
+# (Uncomment for debugging:)
+## print 'keycode:', key
+## print 'pos:', pos
+## print 'sel_start, sel_to:', sel_start, sel_to
+## print 'select_len:', select_len
+## print 'textval:', textval
+
+ # set defaults for processing:
+ allow_event = 1
+ set_to_none = 0
+ set_to_zero = 0
+ set_to_minus_one = 0
+ paste = 0
+ internally_set = 0
+
+ new_value = value
+ new_text = textval
+ new_pos = pos
+
+ # Validate action, and predict resulting value, so we can
+ # range check the result and validate that too.
+
+ if key in (wx.WXK_DELETE, wx.WXK_BACK, WXK_CTRL_X):
+ if select_len:
+ new_text = textval[:sel_start] + textval[sel_to:]
+ elif key == wx.WXK_DELETE and pos < len(textval):
+ new_text = textval[:pos] + textval[pos+1:]
+ elif key == wx.WXK_BACK and pos > 0:
+ new_text = textval[:pos-1] + textval[pos:]
+ # (else value shouldn't change)
+
+ if new_text in ('', '-'):
+ # Deletion of last significant digit:
+ if allow_none and new_text == '':
+ new_value = None
+ set_to_none = 1
+ else:
+ new_value = 0
+ set_to_zero = 1
+ else:
+ try:
+ new_value = ctrl._fromGUI(new_text)
+ except ValueError:
+ allow_event = 0
+
+
+ elif key == WXK_CTRL_V: # (see comments at top of file)
+ # Only allow paste if number:
+ paste_text = ctrl._getClipboardContents()
+ new_text = textval[:sel_start] + paste_text + textval[sel_to:]
+ if new_text == '' and allow_none:
+ new_value = None
+ set_to_none = 1
+ else:
+ try:
+ # Convert the resulting strings, verifying they
+ # are legal integers and will fit in proper
+ # size if ctrl limited to int. (if not,
+ # disallow event.)
+ new_value = ctrl._fromGUI(new_text)
+
+ if paste_text:
+ paste_value = ctrl._fromGUI(paste_text)
+ else:
+ paste_value = 0
+
+ new_pos = sel_start + len(str(paste_value))
+
+ # if resulting value is 0, truncate and highlight value:
+ if new_value == 0 and len(new_text) > 1:
+ set_to_zero = 1
+
+ elif paste_value == 0:
+ # Disallow pasting a leading zero with nothing selected:
+ if( select_len == 0
+ and value is not None
+ and ( (value >= 0 and pos == 0)
+ or (value < 0 and pos in [0,1]) ) ):
+ allow_event = 0
+
+ paste = 1
+
+ except ValueError:
+ allow_event = 0
+
+
+ elif key < wx.WXK_SPACE or key > 255:
+ pass # event ok
+
+
+ elif chr(key) == '-':
+ # Allow '-' to result in -1 if replacing entire contents:
+ if( value is None
+ or (value == 0 and pos == 0)
+ or (select_len >= len(str(abs(value)))) ):
+ new_value = -1
+ set_to_minus_one = 1
+
+ # else allow negative sign only at start, and only if
+ # number isn't already zero or negative:
+ elif pos != 0 or (value is not None and value < 0):
+ allow_event = 0
+ else:
+ new_text = '-' + textval
+ new_pos = 1
+ try:
+ new_value = ctrl._fromGUI(new_text)
+ except ValueError:
+ allow_event = 0
+
+
+ elif chr(key) in string.digits:
+ # disallow inserting a leading zero with nothing selected
+ if( chr(key) == '0'
+ and select_len == 0
+ and value is not None
+ and ( (value >= 0 and pos == 0)
+ or (value < 0 and pos in [0,1]) ) ):
+ allow_event = 0
+ # disallow inserting digits before the minus sign:
+ elif value is not None and value < 0 and pos == 0:
+ allow_event = 0
+ else:
+ new_text = textval[:sel_start] + chr(key) + textval[sel_to:]
+ try:
+ new_value = ctrl._fromGUI(new_text)
+ except ValueError:
+ allow_event = 0
+
+ else:
+ # not a legal char
+ allow_event = 0
+
+
+ if allow_event:
+ # Do range checking for new candidate value:
+ if ctrl.IsLimited() and not ctrl.IsInBounds(new_value):
+ allow_event = 0
+ elif new_value is not None:
+ # ensure resulting text doesn't result in a leading 0:
+ if not set_to_zero and not set_to_minus_one:
+ if( (new_value > 0 and new_text[0] == '0')
+ or (new_value < 0 and new_text[1] == '0')
+ or (new_value == 0 and select_len > 1 ) ):
+
+ # Allow replacement of leading chars with
+ # zero, but remove the leading zero, effectively
+ # making this like "remove leading digits"
+
+ # Account for leading zero when positioning cursor:
+ if( key == wx.WXK_BACK
+ or (paste and paste_value == 0 and new_pos > 0) ):
+ new_pos = new_pos - 1
+
+ wx.CallAfter(ctrl.SetValue, new_value)
+ wx.CallAfter(ctrl.SetInsertionPoint, new_pos)
+ internally_set = 1
+
+ elif paste:
+ # Always do paste numerically, to remove
+ # leading/trailing spaces
+ wx.CallAfter(ctrl.SetValue, new_value)
+ wx.CallAfter(ctrl.SetInsertionPoint, new_pos)
+ internally_set = 1
+
+ elif (new_value == 0 and len(new_text) > 1 ):
+ allow_event = 0
+
+ if allow_event:
+ ctrl._colorValue(new_value) # (one way or t'other)
+
+# (Uncomment for debugging:)
+## if allow_event:
+## print 'new value:', new_value
+## if paste: print 'paste'
+## if set_to_none: print 'set_to_none'
+## if set_to_zero: print 'set_to_zero'
+## if set_to_minus_one: print 'set_to_minus_one'
+## if internally_set: print 'internally_set'
+## else:
+## print 'new text:', new_text
+## print 'disallowed'
+## print
+
+ if allow_event:
+ if set_to_none:
+ wx.CallAfter(ctrl.SetValue, new_value)
+
+ elif set_to_zero:
+ # select to "empty" numeric value
+ wx.CallAfter(ctrl.SetValue, new_value)
+ wx.CallAfter(ctrl.SetInsertionPoint, 0)
+ wx.CallAfter(ctrl.SetSelection, 0, 1)
+
+ elif set_to_minus_one:
+ wx.CallAfter(ctrl.SetValue, new_value)
+ wx.CallAfter(ctrl.SetInsertionPoint, 1)
+ wx.CallAfter(ctrl.SetSelection, 1, 2)
+
+ elif not internally_set:
+ event.Skip() # allow base wxTextCtrl to finish processing
+
+ elif not wx.Validator_IsSilent():
+ wx.Bell()
+
+
+ def TransferToWindow(self):
+ """ Transfer data from validator to window.
+
+ The default implementation returns False, indicating that an error
+ occurred. We simply return True, as we don't do any data transfer.
+ """
+ return True # Prevent wx.Dialog from complaining.
+
+
+ def TransferFromWindow(self):
+ """ Transfer data from window to validator.
+
+ The default implementation returns False, indicating that an error
+ occurred. We simply return True, as we don't do any data transfer.
+ """
+ return True # Prevent wx.Dialog from complaining.
+
+
+#----------------------------------------------------------------------------
+
+class IntCtrl(wx.TextCtrl):
+ """
+ This class provides a control that takes and returns integers as
+ value, and provides bounds support and optional value limiting.
+
+ IntCtrl(
+ parent, id = -1,
+ value = 0,
+ pos = wxDefaultPosition,
+ size = wxDefaultSize,
+ style = 0,
+ validator = wxDefaultValidator,
+ name = "integer",
+ min = None,
+ max = None,
+ limited = False,
+ allow_none = False,
+ allow_long = False,
+ default_color = wxBLACK,
+ oob_color = wxRED )
+
+ value
+ If no initial value is set, the default will be zero, or
+ the minimum value, if specified. If an illegal string is specified,
+ a ValueError will result. (You can always later set the initial
+ value with SetValue() after instantiation of the control.)
+ min
+ The minimum value that the control should allow. This can be
+ adjusted with SetMin(). If the control is not limited, any value
+ below this bound will be colored with the current out-of-bounds color.
+ If min < -sys.maxint-1 and the control is configured to not allow long
+ values, the minimum bound will still be set to the long value, but
+ the implicit bound will be -sys.maxint-1.
+ max
+ The maximum value that the control should allow. This can be
+ adjusted with SetMax(). If the control is not limited, any value
+ above this bound will be colored with the current out-of-bounds color.
+ if max > sys.maxint and the control is configured to not allow long
+ values, the maximum bound will still be set to the long value, but
+ the implicit bound will be sys.maxint.
+
+ limited
+ Boolean indicating whether the control prevents values from
+ exceeding the currently set minimum and maximum values (bounds).
+ If False and bounds are set, out-of-bounds values will
+ be colored with the current out-of-bounds color.
+
+ allow_none
+ Boolean indicating whether or not the control is allowed to be
+ empty, representing a value of None for the control.
+
+ allow_long
+ Boolean indicating whether or not the control is allowed to hold
+ and return a long as well as an int.
+
+ default_color
+ Color value used for in-bounds values of the control.
+
+ oob_color
+ Color value used for out-of-bounds values of the control
+ when the bounds are set but the control is not limited.
+
+ validator
+ Normally None, IntCtrl uses its own validator to do value
+ validation and input control. However, a validator derived
+ from IntValidator can be supplied to override the data
+ transfer methods for the IntValidator class.
+ """
+
+ def __init__ (
+ self, parent, id=-1, value = 0,
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = 0, validator = wx.DefaultValidator,
+ name = "integer",
+ min=None, max=None,
+ limited = 0, allow_none = 0, allow_long = 0,
+ default_color = wx.BLACK, oob_color = wx.RED,
+ ):
+
+ # Establish attrs required for any operation on value:
+ self.__min = None
+ self.__max = None
+ self.__limited = 0
+ self.__default_color = wx.BLACK
+ self.__oob_color = wx.RED
+ self.__allow_none = 0
+ self.__allow_long = 0
+ self.__oldvalue = None
+
+ if validator == wx.DefaultValidator:
+ validator = IntValidator()
+
+ wx.TextCtrl.__init__(
+ self, parent, id, self._toGUI(0),
+ pos, size, style, validator, name )
+
+ # The following lets us set out our "integer update" events:
+ self.Bind(wx.EVT_TEXT, self.OnText )
+
+ # Establish parameters, with appropriate error checking
+
+ self.SetBounds(min, max)
+ self.SetLimited(limited)
+ self.SetColors(default_color, oob_color)
+ self.SetNoneAllowed(allow_none)
+ self.SetLongAllowed(allow_long)
+ self.SetValue(value)
+ self.__oldvalue = 0
+
+
+ def OnText( self, event ):
+ """
+ Handles an event indicating that the text control's value
+ has changed, and issue EVT_INT event.
+ NOTE: using wx.TextCtrl.SetValue() to change the control's
+ contents from within a wx.EVT_CHAR handler can cause double
+ text events. So we check for actual changes to the text
+ before passing the events on.
+ """
+ value = self.GetValue()
+ if value != self.__oldvalue:
+ try:
+ self.GetEventHandler().ProcessEvent(
+ IntUpdatedEvent( self.GetId(), self.GetValue(), self ) )
+ except ValueError:
+ return
+ # let normal processing of the text continue
+ event.Skip()
+ self.__oldvalue = value # record for next event
+
+
+ def GetValue(self):
+ """
+ Returns the current integer (long) value of the control.
+ """
+ return self._fromGUI( wx.TextCtrl.GetValue(self) )
+
+ def SetValue(self, value):
+ """
+ Sets the value of the control to the integer value specified.
+ The resulting actual value of the control may be altered to
+ conform with the bounds set on the control if limited,
+ or colored if not limited but the value is out-of-bounds.
+ A ValueError exception will be raised if an invalid value
+ is specified.
+ """
+ wx.TextCtrl.SetValue( self, self._toGUI(value) )
+ self._colorValue()
+
+
+ def ChangeValue(self, value):
+ "Change the value without sending an EVT_TEXT event."""
+ wx.TextCtrl.ChangeValue(self, self._toGUI(value))
+ self.__oldvalue = self.GetValue() # record for next event
+ self._colorValue()
+
+
+ def SetMin(self, min=None):
+ """
+ Sets the minimum value of the control. If a value of None
+ is provided, then the control will have no explicit minimum value.
+ If the value specified is greater than the current maximum value,
+ then the function returns 0 and the minimum will not change from
+ its current setting. On success, the function returns 1.
+
+ If successful and the current value is lower than the new lower
+ bound, if the control is limited, the value will be automatically
+ adjusted to the new minimum value; if not limited, the value in the
+ control will be colored with the current out-of-bounds color.
+
+ If min > -sys.maxint-1 and the control is configured to not allow longs,
+ the function will return 0, and the min will not be set.
+ """
+ if( self.__max is None
+ or min is None
+ or (self.__max is not None and self.__max >= min) ):
+ self.__min = min
+
+ if self.IsLimited() and min is not None and self.GetValue() < min:
+ self.SetValue(min)
+ else:
+ self._colorValue()
+ return 1
+ else:
+ return 0
+
+
+ def GetMin(self):
+ """
+ Gets the minimum value of the control. It will return the current
+ minimum integer, or None if not specified.
+ """
+ return self.__min
+
+
+ def SetMax(self, max=None):
+ """
+ Sets the maximum value of the control. If a value of None
+ is provided, then the control will have no explicit maximum value.
+ If the value specified is less than the current minimum value, then
+ the function returns 0 and the maximum will not change from its
+ current setting. On success, the function returns 1.
+
+ If successful and the current value is greater than the new upper
+ bound, if the control is limited the value will be automatically
+ adjusted to this maximum value; if not limited, the value in the
+ control will be colored with the current out-of-bounds color.
+
+ If max > sys.maxint and the control is configured to not allow longs,
+ the function will return 0, and the max will not be set.
+ """
+ if( self.__min is None
+ or max is None
+ or (self.__min is not None and self.__min <= max) ):
+ self.__max = max
+
+ if self.IsLimited() and max is not None and self.GetValue() > max:
+ self.SetValue(max)
+ else:
+ self._colorValue()
+ return 1
+ else:
+ return 0
+
+
+ def GetMax(self):
+ """
+ Gets the maximum value of the control. It will return the current
+ maximum integer, or None if not specified.
+ """
+ return self.__max
+
+
+ def SetBounds(self, min=None, max=None):
+ """
+ This function is a convenience function for setting the min and max
+ values at the same time. The function only applies the maximum bound
+ if setting the minimum bound is successful, and returns True
+ only if both operations succeed.
+ NOTE: leaving out an argument will remove the corresponding bound.
+ """
+ ret = self.SetMin(min)
+ return ret and self.SetMax(max)
+
+
+ def GetBounds(self):
+ """
+ This function returns a two-tuple (min,max), indicating the
+ current bounds of the control. Each value can be None if
+ that bound is not set.
+ """
+ return (self.__min, self.__max)
+
+
+ def SetLimited(self, limited):
+ """
+ If called with a value of True, this function will cause the control
+ to limit the value to fall within the bounds currently specified.
+ If the control's value currently exceeds the bounds, it will then
+ be limited accordingly.
+
+ If called with a value of 0, this function will disable value
+ limiting, but coloring of out-of-bounds values will still take
+ place if bounds have been set for the control.
+ """
+ self.__limited = limited
+ if limited:
+ min = self.GetMin()
+ max = self.GetMax()
+ if not min is None and self.GetValue() < min:
+ self.SetValue(min)
+ elif not max is None and self.GetValue() > max:
+ self.SetValue(max)
+ else:
+ self._colorValue()
+
+
+ def IsLimited(self):
+ """
+ Returns True if the control is currently limiting the
+ value to fall within the current bounds.
+ """
+ return self.__limited
+
+
+ def IsInBounds(self, value=None):
+ """
+ Returns True if no value is specified and the current value
+ of the control falls within the current bounds. This function can
+ also be called with a value to see if that value would fall within
+ the current bounds of the given control.
+ """
+ if value is None:
+ value = self.GetValue()
+
+ if( not (value is None and self.IsNoneAllowed())
+ and type(value) not in (types.IntType, types.LongType) ):
+ raise ValueError (
+ 'IntCtrl requires integer values, passed %s'% repr(value) )
+
+ min = self.GetMin()
+ max = self.GetMax()
+ if min is None: min = value
+ if max is None: max = value
+
+ # if bounds set, and value is None, return False
+ if value == None and (min is not None or max is not None):
+ return 0
+ else:
+ return min <= value <= max
+
+
+ def SetNoneAllowed(self, allow_none):
+ """
+ Change the behavior of the validation code, allowing control
+ to have a value of None or not, as appropriate. If the value
+ of the control is currently None, and allow_none is 0, the
+ value of the control will be set to the minimum value of the
+ control, or 0 if no lower bound is set.
+ """
+ self.__allow_none = allow_none
+ if not allow_none and self.GetValue() is None:
+ min = self.GetMin()
+ if min is not None: self.SetValue(min)
+ else: self.SetValue(0)
+
+
+ def IsNoneAllowed(self):
+ return self.__allow_none
+
+
+ def SetLongAllowed(self, allow_long):
+ """
+ Change the behavior of the validation code, allowing control
+ to have a long value or not, as appropriate. If the value
+ of the control is currently long, and allow_long is 0, the
+ value of the control will be adjusted to fall within the
+ size of an integer type, at either the sys.maxint or -sys.maxint-1,
+ for positive and negative values, respectively.
+ """
+ current_value = self.GetValue()
+ if not allow_long and type(current_value) is types.LongType:
+ if current_value > 0:
+ self.SetValue(MAXINT)
+ else:
+ self.SetValue(MININT)
+ self.__allow_long = allow_long
+
+
+ def IsLongAllowed(self):
+ return self.__allow_long
+
+
+
+ def SetColors(self, default_color=wx.BLACK, oob_color=wx.RED):
+ """
+ Tells the control what colors to use for normal and out-of-bounds
+ values. If the value currently exceeds the bounds, it will be
+ recolored accordingly.
+ """
+ self.__default_color = default_color
+ self.__oob_color = oob_color
+ self._colorValue()
+
+
+ def GetColors(self):
+ """
+ Returns a tuple of (default_color, oob_color), indicating
+ the current color settings for the control.
+ """
+ return self.__default_color, self.__oob_color
+
+
+ def _colorValue(self, value=None):
+ """
+ Colors text with oob_color if current value exceeds bounds
+ set for control.
+ """
+ if not self.IsInBounds(value):
+ self.SetForegroundColour(self.__oob_color)
+ else:
+ self.SetForegroundColour(self.__default_color)
+ self.Refresh()
+
+
+ def _toGUI( self, value ):
+ """
+ Conversion function used to set the value of the control; does
+ type and bounds checking and raises ValueError if argument is
+ not a valid value.
+ """
+ if value is None and self.IsNoneAllowed():
+ return ''
+ elif type(value) == types.LongType and not self.IsLongAllowed():
+ raise ValueError (
+ 'IntCtrl requires integer value, passed long' )
+ elif type(value) not in (types.IntType, types.LongType):
+ raise ValueError (
+ 'IntCtrl requires integer value, passed %s'% repr(value) )
+
+ elif self.IsLimited():
+ min = self.GetMin()
+ max = self.GetMax()
+ if not min is None and value < min:
+ raise ValueError (
+ 'value is below minimum value of control %d'% value )
+ if not max is None and value > max:
+ raise ValueError (
+ 'value exceeds value of control %d'% value )
+
+ return str(value)
+
+
+ def _fromGUI( self, value ):
+ """
+ Conversion function used in getting the value of the control.
+ """
+
+ # One or more of the underlying text control implementations
+ # issue an intermediate EVT_TEXT when replacing the control's
+ # value, where the intermediate value is an empty string.
+ # So, to ensure consistency and to prevent spurious ValueErrors,
+ # we make the following test, and react accordingly:
+ #
+ if value == '':
+ if not self.IsNoneAllowed():
+ return 0
+ else:
+ return None
+ else:
+ try:
+ return int( value )
+ except ValueError:
+ if self.IsLongAllowed():
+ return long( value )
+ else:
+ raise
+
+
+ def Cut( self ):
+ """
+ Override the wxTextCtrl's .Cut function, with our own
+ that does validation. Will result in a value of 0
+ if entire contents of control are removed.
+ """
+ sel_start, sel_to = self.GetSelection()
+ select_len = sel_to - sel_start
+ textval = wx.TextCtrl.GetValue(self)
+
+ do = wx.TextDataObject()
+ do.SetText(textval[sel_start:sel_to])
+ wx.TheClipboard.Open()
+ wx.TheClipboard.SetData(do)
+ wx.TheClipboard.Close()
+ if select_len == len(wxTextCtrl.GetValue(self)):
+ if not self.IsNoneAllowed():
+ self.SetValue(0)
+ self.SetInsertionPoint(0)
+ self.SetSelection(0,1)
+ else:
+ self.SetValue(None)
+ else:
+ new_value = self._fromGUI(textval[:sel_start] + textval[sel_to:])
+ self.SetValue(new_value)
+
+
+ def _getClipboardContents( self ):
+ """
+ Subroutine for getting the current contents of the clipboard.
+ """
+ do = wx.TextDataObject()
+ wx.TheClipboard.Open()
+ success = wx.TheClipboard.GetData(do)
+ wx.TheClipboard.Close()
+
+ if not success:
+ return None
+ else:
+ # Remove leading and trailing spaces before evaluating contents
+ return do.GetText().strip()
+
+
+ def Paste( self ):
+ """
+ Override the wxTextCtrl's .Paste function, with our own
+ that does validation. Will raise ValueError if not a
+ valid integerizable value.
+ """
+ paste_text = self._getClipboardContents()
+ if paste_text:
+ # (conversion will raise ValueError if paste isn't legal)
+ sel_start, sel_to = self.GetSelection()
+ text = wx.TextCtrl.GetValue( self )
+ new_text = text[:sel_start] + paste_text + text[sel_to:]
+ if new_text == '' and self.IsNoneAllowed():
+ self.SetValue(None)
+ else:
+ value = self._fromGUI(new_text)
+ self.SetValue(value)
+ new_pos = sel_start + len(paste_text)
+ wx.CallAfter(self.SetInsertionPoint, new_pos)
+
+
+
+#===========================================================================
+
+if __name__ == '__main__':
+
+ import traceback
+
+ class myDialog(wx.Dialog):
+ def __init__(self, parent, id, title,
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = wx.DEFAULT_DIALOG_STYLE ):
+ wx.Dialog.__init__(self, parent, id, title, pos, size, style)
+
+ self.int_ctrl = IntCtrl(self, wx.NewId(), size=(55,20))
+ self.OK = wx.Button( self, wx.ID_OK, "OK")
+ self.Cancel = wx.Button( self, wx.ID_CANCEL, "Cancel")
+
+ vs = wx.BoxSizer( wx.VERTICAL )
+ vs.Add( self.int_ctrl, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
+ hs = wx.BoxSizer( wx.HORIZONTAL )
+ hs.Add( self.OK, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
+ hs.Add( self.Cancel, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
+ vs.Add(hs, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
+
+ self.SetAutoLayout( True )
+ self.SetSizer( vs )
+ vs.Fit( self )
+ vs.SetSizeHints( self )
+ self.Bind(EVT_INT, self.OnInt, self.int_ctrl)
+
+ def OnInt(self, event):
+ print 'int now', event.GetValue()
+
+ class TestApp(wx.App):
+ def OnInit(self):
+ try:
+ self.frame = wx.Frame(None, -1, "Test", (20,20), (120,100) )
+ self.panel = wx.Panel(self.frame, -1)
+ button = wx.Button(self.panel, 10, "Push Me", (20, 20))
+ self.Bind(wx.EVT_BUTTON, self.OnClick, button)
+ except:
+ traceback.print_exc()
+ return False
+ return True
+
+ def OnClick(self, event):
+ dlg = myDialog(self.panel, -1, "test IntCtrl")
+ dlg.int_ctrl.SetValue(501)
+ dlg.int_ctrl.SetInsertionPoint(1)
+ dlg.int_ctrl.SetSelection(1,2)
+ rc = dlg.ShowModal()
+ print 'final value', dlg.int_ctrl.GetValue()
+ del dlg
+ self.frame.Destroy()
+
+ def Show(self):
+ self.frame.Show(True)
+
+ try:
+ app = TestApp(0)
+ app.Show()
+ app.MainLoop()
+ except:
+ traceback.print_exc()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/itemspicker.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/itemspicker.py
new file mode 100644
index 0000000..71f7f38
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/itemspicker.py
@@ -0,0 +1,243 @@
+'''
+Created on Oct 3, 2010
+
+@authors: Daphna Rosenbom,Gitty Zinger,Moshe Cohavi and Yoav Glazner
+The widget is contributed by NDS ltd under the same license as wxPython
+
+items_picker.ItemsPicker:
+ - Displays available items to choose from,</LI>
+ - Selection is done by the Add button or Double Click,</LI>
+ - De-Selection is done by the Remove button or Double Click,</LI>
+
+ Derived from wxPanel
+'''
+import wx
+__version__ = 0.1
+
+IP_DEFAULT_STYLE = 0
+IP_SORT_CHOICES = 1
+IP_SORT_SELECTED = 2
+IP_REMOVE_FROM_CHOICES = 4
+
+
+wxEVT_IP_SELECTION_CHANGED = wx.NewEventType()
+EVT_IP_SELECTION_CHANGED = wx.PyEventBinder(wxEVT_IP_SELECTION_CHANGED, 1)
+LB_STYLE = wx.LB_EXTENDED|wx.LB_HSCROLL
+
+
+class IpSelectionChanged(wx.PyCommandEvent):
+ def __init__(self, id, items, object = None):
+ wx.PyCommandEvent.__init__(self, wxEVT_IP_SELECTION_CHANGED, id)
+ self.__items = items
+ self.SetEventObject(object)
+
+ def GetItems(self):
+ return self.__items
+
+
+class ItemsPicker(wx.Panel):
+ '''
+ ItemsPicker is a widget that allows the user to form a set of picked
+ items out of a given list
+ '''
+ def __init__(self, parent, id=wx.ID_ANY, choices = [],
+ label = '', selectedLabel = '',
+ ipStyle = IP_DEFAULT_STYLE,
+ *args, **kw):
+ '''
+ ItemsPicker(parent, choices = [], label = '', selectedLabel = '',
+ ipStyle = IP_DEFAULT_STYLE)
+ '''
+ wx.Panel.__init__(self, parent, id, *args, **kw)
+ self._ipStyle = ipStyle
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(self._CreateSourceList(choices, label), 1,
+ wx.EXPAND|wx.ALL, 5)
+ sizer.Add(self._CreateButtons(), 0, wx.ALIGN_CENTER|wx.ALL, 5)
+ sizer.Add(self._CreateDestList(selectedLabel), 1,
+ wx.EXPAND|wx.ALL, 5)
+ self.SetSizer(sizer)
+
+
+ def SetItems(self, items):
+ '''SetItems(self, items)=> None
+ items - Sequence of strings that the user can pick from'''
+ return self._source.SetItems(items)
+
+
+ def GetItems(self):
+ '''GetItems(self)=> items
+ returns list of strings that the user can pick from'''
+ return self._source.GetItems()
+
+
+ Items = property(fget = GetItems,
+ fset = SetItems,
+ doc = 'See GetItems/SetItems')
+
+
+ def GetSelections(self):
+ '''GetSelections(self)=>items
+ returns list of strings that were selected
+ '''
+ return self._dest.GetItems()
+
+
+ def SetSelections(self, items):
+ '''SetSelections(self, items)=>None
+ items - Sequence of strings to be selected
+ The items are displayed in the selection part of the widget'''
+ assert len(items)==len(set(items)),"duplicate items are not allowed"
+ if items != self._dest.GetItems():
+ self._dest.SetItems(items)
+ self._FireIpSelectionChanged()
+
+
+ Selections = property(fget = GetSelections,
+ fset = SetSelections,
+ doc = 'See GetSelections/SetSelections')
+
+
+ def _CreateButtons(self):
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ self.bAdd = wx.Button(self, -1, label = 'Add ->')
+ self.bAdd.Bind(wx.EVT_BUTTON, self._OnAdd)
+ self.bRemove = wx.Button(self, -1, label = '<- Remove')
+ self.bRemove.Bind(wx.EVT_BUTTON, self._OnRemove)
+ sizer.Add(self.bAdd, 0, wx.EXPAND|wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
+ sizer.Add(self.bRemove, 0, wx.EXPAND|wx.ALL, 5)
+ return sizer
+
+
+ def _set_add_button_label(self, label=None):
+ if label is None:
+ return
+ self.bAdd.SetLabel(label)
+
+ add_button_label = property(fset = _set_add_button_label, fget = lambda x:x)
+
+
+ def _set_remove_button_label(self, label=None):
+ if label is None:
+ return
+ self.bRemove.SetLabel(label)
+
+ remove_button_label = property(fset = _set_remove_button_label, fget = lambda x:x)
+
+
+ def _OnAdd(self, e):
+ if self._ipStyle & IP_REMOVE_FROM_CHOICES:
+ self._MoveItems(self._source,self._dest)
+ else:
+ self._AddSelectedItems()
+
+ def _MoveItems(self,source,dest):
+ selections = source.GetSelections()
+ selectedItems = map(source.GetString, selections)
+ dest.SetItems(dest.GetItems() + selectedItems)
+ selections = set(selections)
+ source.SetItems([item for i, item in enumerate(source.GetItems())\
+ if i not in selections])
+ self._FireIpSelectionChanged()
+
+ def _AddSelectedItems(self):
+ newItems = map(self._source.GetString, self._source.GetSelections())
+ items = self._dest.GetItems()
+ oldItems = set(items)
+ for newItem in newItems:
+ if newItem not in oldItems:
+ items.append(newItem)
+ self.SetSelections(items)
+
+
+ def _FireIpSelectionChanged(self):
+ self.GetEventHandler().ProcessEvent(
+ IpSelectionChanged(self.GetId(),
+ self._dest.GetItems(),
+ self ))
+
+
+ def _OnRemove(self, e):
+ if self._ipStyle & IP_REMOVE_FROM_CHOICES:
+ self._MoveItems(self._dest, self._source)
+ else:
+ self._RemoveSelected()
+
+ def _RemoveSelected(self):
+ selections = self._dest.GetSelections()
+ if selections:
+ allItems = self._dest.GetItems()
+ items = [item for i, item in enumerate(allItems)\
+ if i not in selections]
+ self.SetSelections(items)
+ self._FireIpSelectionChanged()
+
+
+ def _CreateSourceList(self, items, label):
+ style = LB_STYLE
+ if self._ipStyle & IP_SORT_CHOICES:
+ style |= wx.LB_SORT
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ if label:
+ sizer.Add(wx.StaticText(self, label = label), 0,
+ wx.ALIGN_LEFT|wx.ALL, 5)
+ self._source = wx.ListBox(self, -1, style = style)
+ self._source.Bind(wx.EVT_LISTBOX_DCLICK, self._OnDClick)
+ self._source.SetItems(items)
+ sizer.Add(self._source, 1, wx.EXPAND|wx.ALL, 5)
+ return sizer
+
+
+ def _CreateDestList(self, label):
+ style = LB_STYLE
+ if self._ipStyle & IP_SORT_SELECTED:
+ style |= wx.LB_SORT
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ if label:
+ sizer.Add(wx.StaticText(self, label = label), 0,
+ wx.ALIGN_LEFT|wx.ALL, 5)
+ self._dest = wx.ListBox(self, -1, style = style)
+ self._dest.Bind(wx.EVT_LISTBOX_DCLICK, self._OnDClick)
+ sizer.Add(self._dest, 1, wx.EXPAND|wx.ALL, 5)
+ return sizer
+
+
+ def _OnDClick(self, e):
+ lb = e.GetEventObject()
+ selections = lb.GetSelections()
+ if len(selections) != 1:
+ return #DCLICK only works on one item
+ if e.GetSelection() != selections[0]:
+ #this can happen using ^DCLICK when two items are selected
+ return
+ if lb == self._source:
+ self._OnAdd(e)
+ else:
+ self._OnRemove(e)
+
+
+
+
+if __name__ == '__main__':
+ test = wx.App(0)
+ frame = wx.Frame(None, -1)
+ d = wx.Dialog(frame, style = wx.RESIZE_BORDER|wx.DEFAULT_DIALOG_STYLE)
+
+ d.sizer = wx.BoxSizer(wx.VERTICAL)
+ d.sizer.Add(wx.StaticText(d, -1, label = 'Example of the ItemsPicker'),
+ 0, wx.ALL, 10)
+ ip = ItemsPicker(d, -1, ['pop', 'cool', 'lame'],
+ 'Stuff:', 'Selected stuff:',IP_SORT_SELECTED|IP_SORT_CHOICES|IP_REMOVE_FROM_CHOICES)
+ ip.add_button_label = u'left -> right'
+ ip.remove_button_label = u'right -> left'
+ d.sizer.Add(ip, 1, wx.EXPAND, 1)
+ d.SetSizer(d.sizer)
+ test.SetTopWindow(frame)
+ def callback(e):
+ print 'selected items', e.GetItems()
+ d.Bind(EVT_IP_SELECTION_CHANGED, callback)
+ d.ShowModal()
+ d.Destroy()
+ frame.Close()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/langlistctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/langlistctrl.py
new file mode 100644
index 0000000..74038bc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/langlistctrl.py
@@ -0,0 +1,424 @@
+#-----------------------------------------------------------------------------
+# Name: languagectrls.py
+# Purpose:
+#
+# Author: Riaan Booysen
+#
+# Created: 2006
+# RCS-ID: $Id$
+# Copyright: (c) 2006 Riaan Booysen
+# License: wxPython
+#-----------------------------------------------------------------------------
+""" ListCtrl and functions to display languages and the flags of their countries
+"""
+import wx
+
+from wx.lib.art import flagart
+
+langIdCountryMap = {
+ # generated from wx.Locale info and locale.windows_locale
+ wx.LANGUAGE_AFRIKAANS: 'ZA',
+ wx.LANGUAGE_ALBANIAN: 'AL',
+ wx.LANGUAGE_ARABIC_ALGERIA: 'DZ',
+ wx.LANGUAGE_ARABIC_BAHRAIN: 'BH',
+ wx.LANGUAGE_ARABIC_EGYPT: 'EG',
+ wx.LANGUAGE_ARABIC_IRAQ: 'IQ',
+ wx.LANGUAGE_ARABIC_JORDAN: 'JO',
+ wx.LANGUAGE_ARABIC_KUWAIT: 'KW',
+ wx.LANGUAGE_ARABIC_LEBANON: 'LB',
+ wx.LANGUAGE_ARABIC_LIBYA: 'LY',
+ wx.LANGUAGE_ARABIC_MOROCCO: 'MA',
+ wx.LANGUAGE_ARABIC_OMAN: 'OM',
+ wx.LANGUAGE_ARABIC_QATAR: 'QA',
+ wx.LANGUAGE_ARABIC_SAUDI_ARABIA: 'SA',
+ wx.LANGUAGE_ARABIC_SUDAN: 'SD',
+ wx.LANGUAGE_ARABIC_SYRIA: 'SY',
+ wx.LANGUAGE_ARABIC_TUNISIA: 'TN',
+ wx.LANGUAGE_ARABIC_UAE: 'AE',
+ wx.LANGUAGE_ARABIC_YEMEN: 'YE',
+ wx.LANGUAGE_ARMENIAN: 'AM',
+ wx.LANGUAGE_AZERI: 'AZ',
+ wx.LANGUAGE_AZERI_CYRILLIC: 'AZ',
+ wx.LANGUAGE_AZERI_LATIN: 'AZ',
+ wx.LANGUAGE_BASQUE: 'ES',
+ wx.LANGUAGE_BELARUSIAN: 'BY',
+ wx.LANGUAGE_BENGALI: 'IN',
+ wx.LANGUAGE_BRETON: 'FR',
+ wx.LANGUAGE_BULGARIAN: 'BG',
+ wx.LANGUAGE_CATALAN: 'ES',
+ wx.LANGUAGE_CHINESE: 'CN',
+ wx.LANGUAGE_CHINESE_HONGKONG: 'HK',
+ wx.LANGUAGE_CHINESE_MACAU: 'MO',
+ wx.LANGUAGE_CHINESE_SIMPLIFIED: 'CN',
+ wx.LANGUAGE_CHINESE_SINGAPORE: 'SG',
+ wx.LANGUAGE_CHINESE_TAIWAN: 'TW',
+ wx.LANGUAGE_CHINESE_TRADITIONAL: 'CN',
+ wx.LANGUAGE_CROATIAN: 'HR',
+ wx.LANGUAGE_CZECH: 'CZ',
+ wx.LANGUAGE_DANISH: 'DK',
+# wx.LANGUAGE_DEFAULT: 'ZA',
+ wx.LANGUAGE_DUTCH: 'NL',
+ wx.LANGUAGE_DUTCH_BELGIAN: 'BE',
+ wx.LANGUAGE_ENGLISH: 'GB',
+ wx.LANGUAGE_ENGLISH_AUSTRALIA: 'AU',
+ wx.LANGUAGE_ENGLISH_BELIZE: 'BZ',
+ wx.LANGUAGE_ENGLISH_BOTSWANA: 'BW',
+ wx.LANGUAGE_ENGLISH_CANADA: 'CA',
+ wx.LANGUAGE_ENGLISH_CARIBBEAN: 'CB',
+ wx.LANGUAGE_ENGLISH_DENMARK: 'DK',
+ wx.LANGUAGE_ENGLISH_EIRE: 'IE',
+ wx.LANGUAGE_ENGLISH_JAMAICA: 'JM',
+ wx.LANGUAGE_ENGLISH_NEW_ZEALAND: 'NZ',
+ wx.LANGUAGE_ENGLISH_PHILIPPINES: 'PH',
+ wx.LANGUAGE_ENGLISH_SOUTH_AFRICA: 'ZA',
+ wx.LANGUAGE_ENGLISH_TRINIDAD: 'TT',
+ wx.LANGUAGE_ENGLISH_UK: 'GB',
+ wx.LANGUAGE_ENGLISH_US: 'US',
+ wx.LANGUAGE_ENGLISH_ZIMBABWE: 'ZW',
+ wx.LANGUAGE_ESTONIAN: 'EE',
+ wx.LANGUAGE_FAEROESE: 'FO',
+ wx.LANGUAGE_FARSI: 'IR',
+ wx.LANGUAGE_FINNISH: 'FI',
+ wx.LANGUAGE_FRENCH: 'FR',
+ wx.LANGUAGE_FRENCH_BELGIAN: 'BE',
+ wx.LANGUAGE_FRENCH_CANADIAN: 'CA',
+ wx.LANGUAGE_FRENCH_LUXEMBOURG: 'LU',
+ wx.LANGUAGE_FRENCH_MONACO: 'MC',
+ wx.LANGUAGE_FRENCH_SWISS: 'CH',
+ wx.LANGUAGE_FRISIAN: 'NL',
+ wx.LANGUAGE_GALICIAN: 'ES',
+ wx.LANGUAGE_GEORGIAN: 'GE',
+ wx.LANGUAGE_GERMAN: 'DE',
+ wx.LANGUAGE_GERMAN_AUSTRIAN: 'AT',
+ wx.LANGUAGE_GERMAN_BELGIUM: 'BE',
+ wx.LANGUAGE_GERMAN_LIECHTENSTEIN: 'LI',
+ wx.LANGUAGE_GERMAN_LUXEMBOURG: 'LU',
+ wx.LANGUAGE_GERMAN_SWISS: 'CH',
+ wx.LANGUAGE_GREEK: 'GR',
+ wx.LANGUAGE_GREENLANDIC: 'GL',
+ wx.LANGUAGE_GUJARATI: 'IN',
+ wx.LANGUAGE_HEBREW: 'IL',
+ wx.LANGUAGE_HINDI: 'IN',
+ wx.LANGUAGE_HUNGARIAN: 'HU',
+ wx.LANGUAGE_ICELANDIC: 'IS',
+ wx.LANGUAGE_INDONESIAN: 'ID',
+ wx.LANGUAGE_INUKTITUT: 'CA',
+ wx.LANGUAGE_IRISH: 'IE',
+ wx.LANGUAGE_ITALIAN: 'IT',
+ wx.LANGUAGE_ITALIAN_SWISS: 'CH',
+ wx.LANGUAGE_JAPANESE: 'JP',
+ wx.LANGUAGE_KANNADA: 'IN',
+ wx.LANGUAGE_KASHMIRI_INDIA: 'IN',
+ wx.LANGUAGE_KAZAKH: 'KZ',
+ wx.LANGUAGE_KERNEWEK: 'GB',
+ wx.LANGUAGE_KIRGHIZ: 'KG',
+ wx.LANGUAGE_KOREAN: 'KR',
+ wx.LANGUAGE_LATVIAN: 'LV',
+ wx.LANGUAGE_LITHUANIAN: 'LT',
+ wx.LANGUAGE_MACEDONIAN: 'MK',
+ wx.LANGUAGE_MALAY: 'MY',
+ wx.LANGUAGE_MALAYALAM: 'IN',
+ wx.LANGUAGE_MALAY_BRUNEI_DARUSSALAM: 'BN',
+ wx.LANGUAGE_MALAY_MALAYSIA: 'MY',
+ wx.LANGUAGE_MALTESE: 'MT',
+ wx.LANGUAGE_MAORI: 'NZ',
+ wx.LANGUAGE_MARATHI: 'IN',
+ wx.LANGUAGE_MONGOLIAN: 'MN',
+ wx.LANGUAGE_NEPALI: 'NP',
+ wx.LANGUAGE_NEPALI_INDIA: 'IN',
+ wx.LANGUAGE_NORWEGIAN_BOKMAL: 'NO',
+ wx.LANGUAGE_NORWEGIAN_NYNORSK: 'NO',
+ wx.LANGUAGE_OCCITAN: 'FR',
+ wx.LANGUAGE_ORIYA: 'IN',
+ wx.LANGUAGE_PASHTO: 'AF',
+ wx.LANGUAGE_POLISH: 'PL',
+ wx.LANGUAGE_PORTUGUESE: 'PT',
+ wx.LANGUAGE_PORTUGUESE_BRAZILIAN: 'BR',
+ wx.LANGUAGE_PUNJABI: 'IN',
+ wx.LANGUAGE_RHAETO_ROMANCE: 'CH',
+ wx.LANGUAGE_ROMANIAN: 'RO',
+ wx.LANGUAGE_RUSSIAN: 'RU',
+ wx.LANGUAGE_RUSSIAN_UKRAINE: 'UA',
+ wx.LANGUAGE_SANSKRIT: 'IN',
+ wx.LANGUAGE_SERBIAN_CYRILLIC: 'YU',
+ wx.LANGUAGE_SERBIAN_LATIN: 'YU',
+ wx.LANGUAGE_SETSWANA: 'ZA',
+ wx.LANGUAGE_SLOVAK: 'SK',
+ wx.LANGUAGE_SLOVENIAN: 'SI',
+ wx.LANGUAGE_SPANISH: 'ES',
+ wx.LANGUAGE_SPANISH_ARGENTINA: 'AR',
+ wx.LANGUAGE_SPANISH_BOLIVIA: 'BO',
+ wx.LANGUAGE_SPANISH_CHILE: 'CL',
+ wx.LANGUAGE_SPANISH_COLOMBIA: 'CO',
+ wx.LANGUAGE_SPANISH_COSTA_RICA: 'CR',
+ wx.LANGUAGE_SPANISH_DOMINICAN_REPUBLIC: 'DO',
+ wx.LANGUAGE_SPANISH_ECUADOR: 'EC',
+ wx.LANGUAGE_SPANISH_EL_SALVADOR: 'SV',
+ wx.LANGUAGE_SPANISH_GUATEMALA: 'GT',
+ wx.LANGUAGE_SPANISH_HONDURAS: 'HN',
+ wx.LANGUAGE_SPANISH_MEXICAN: 'MX',
+ wx.LANGUAGE_SPANISH_MODERN: 'ES',
+ wx.LANGUAGE_SPANISH_NICARAGUA: 'NI',
+ wx.LANGUAGE_SPANISH_PANAMA: 'PA',
+ wx.LANGUAGE_SPANISH_PARAGUAY: 'PY',
+ wx.LANGUAGE_SPANISH_PERU: 'PE',
+ wx.LANGUAGE_SPANISH_PUERTO_RICO: 'PR',
+ wx.LANGUAGE_SPANISH_URUGUAY: 'UY',
+ wx.LANGUAGE_SPANISH_US: 'US',
+ wx.LANGUAGE_SPANISH_VENEZUELA: 'VE',
+ wx.LANGUAGE_SWAHILI: 'KE',
+ wx.LANGUAGE_SWEDISH: 'SE',
+ wx.LANGUAGE_SWEDISH_FINLAND: 'FI',
+ wx.LANGUAGE_TAGALOG: 'PH',
+ wx.LANGUAGE_TAMIL: 'IN',
+ wx.LANGUAGE_TATAR: 'RU',
+ wx.LANGUAGE_TELUGU: 'IN',
+ wx.LANGUAGE_THAI: 'TH',
+ wx.LANGUAGE_TURKISH: 'TR',
+ wx.LANGUAGE_UKRAINIAN: 'UA',
+ wx.LANGUAGE_URDU: 'PK',
+ wx.LANGUAGE_URDU_INDIA: 'IN',
+ wx.LANGUAGE_URDU_PAKISTAN: 'PK',
+ wx.LANGUAGE_UZBEK: 'UZ',
+ wx.LANGUAGE_UZBEK_CYRILLIC: 'UZ',
+ wx.LANGUAGE_UZBEK_LATIN: 'UZ',
+ wx.LANGUAGE_VIETNAMESE: 'VN',
+ wx.LANGUAGE_WELSH: 'GB',
+ wx.LANGUAGE_XHOSA: 'ZA',
+ wx.LANGUAGE_ZULU: 'ZA',
+ # manually defined language/country mapping
+ wx.LANGUAGE_ABKHAZIAN: 'GE',
+ wx.LANGUAGE_AFAR: 'ET',
+ wx.LANGUAGE_AMHARIC: 'ET',
+ wx.LANGUAGE_ASSAMESE: 'IN',
+ wx.LANGUAGE_AYMARA: 'BO',
+ wx.LANGUAGE_ARABIC: 'SA',
+ wx.LANGUAGE_BASHKIR: 'RU',
+ wx.LANGUAGE_BHUTANI: 'BT',
+ wx.LANGUAGE_BIHARI: 'IN',
+ wx.LANGUAGE_BISLAMA: 'VU',
+ wx.LANGUAGE_BURMESE: 'MM',
+ wx.LANGUAGE_CAMBODIAN: 'KH',
+ wx.LANGUAGE_CORSICAN: 'FR',
+ wx.LANGUAGE_ESPERANTO: 'ESPERANTO',
+ wx.LANGUAGE_FIJI: 'FJ',
+ wx.LANGUAGE_GUARANI: 'PY',
+ wx.LANGUAGE_HAUSA: 'NG',
+ wx.LANGUAGE_INTERLINGUA: 'US',
+ wx.LANGUAGE_INTERLINGUE: 'US',
+ wx.LANGUAGE_INUPIAK: 'US',
+ wx.LANGUAGE_JAVANESE: 'IN',
+ wx.LANGUAGE_KASHMIRI: 'IN',
+ wx.LANGUAGE_KINYARWANDA: 'RW',
+ wx.LANGUAGE_KIRUNDI: 'BI',
+ wx.LANGUAGE_KONKANI: 'IN',
+ wx.LANGUAGE_KURDISH: 'IQ',
+ wx.LANGUAGE_LAOTHIAN: 'LA',
+ wx.LANGUAGE_LATIN: 'VA',
+ wx.LANGUAGE_LINGALA: 'CD',
+ wx.LANGUAGE_MALAGASY: 'MG',
+ wx.LANGUAGE_MANIPURI: 'IN',
+ wx.LANGUAGE_MOLDAVIAN: 'MD',
+ wx.LANGUAGE_NAURU: 'NR',
+ wx.LANGUAGE_OROMO: 'ET',
+ wx.LANGUAGE_QUECHUA: 'BO',
+ wx.LANGUAGE_SAMOAN: 'WS',
+ wx.LANGUAGE_SANGHO: 'CF',
+ wx.LANGUAGE_SCOTS_GAELIC: 'GB',
+ wx.LANGUAGE_SERBO_CROATIAN: 'HR',
+ wx.LANGUAGE_SESOTHO: 'ZA',
+ wx.LANGUAGE_SHONA: 'ZW',
+ wx.LANGUAGE_SINDHI: 'PK',
+ wx.LANGUAGE_SINHALESE: 'IN',
+ wx.LANGUAGE_SISWATI: 'SZ',
+ wx.LANGUAGE_SOMALI: 'SB',
+ wx.LANGUAGE_SUNDANESE: 'SD',
+ wx.LANGUAGE_TAJIK: 'TJ',
+ wx.LANGUAGE_TIBETAN: 'CN',
+ wx.LANGUAGE_TIGRINYA: 'ET',
+ wx.LANGUAGE_TONGA: 'TO',
+ wx.LANGUAGE_TSONGA: 'MZ',
+ wx.LANGUAGE_TURKMEN: 'TM',
+ wx.LANGUAGE_TWI: 'GH',
+ wx.LANGUAGE_UIGHUR: 'CN',
+ wx.LANGUAGE_VOLAPUK: 'VOLAPUK',
+ wx.LANGUAGE_WOLOF: 'SN',
+ wx.LANGUAGE_YIDDISH: 'IL',
+ wx.LANGUAGE_YORUBA: 'NG',
+ wx.LANGUAGE_ZHUANG: 'CN',
+}
+
+LC_AVAILABLE, LC_ALL, LC_ONLY = 1, 2, 4
+
+
+# wx.LANGUAGE_SERBIAN gives an error for me
+_wxLangIds = [n for n in dir(wx) if n.startswith('LANGUAGE_')]
+for _l in ('LANGUAGE_UNKNOWN', 'LANGUAGE_USER_DEFINED', 'LANGUAGE_SERBIAN'):
+ if _l in _wxLangIds:
+ _wxLangIds.remove(_l)
+
+
+def CreateLanguagesResourceLists(filter=LC_AVAILABLE, only=()):
+ """ Returns a tuple of (bitmaps, language descriptions, language ids) """
+ icons = wx.ImageList(16, 11)
+ names = []
+ langs = []
+
+ langIdNameMap = BuildLanguageCountryMapping()
+
+ wxLangIds = []
+ for li in _wxLangIds:
+ wxLI = getattr(wx, li)
+ try:
+ if (filter == LC_ONLY and wxLI in only) or \
+ (filter == LC_AVAILABLE and wx.Locale.IsAvailable(wxLI)) or \
+ (filter == LC_ALL):
+ wxLangIds.append(wxLI)
+ except wx.PyAssertionError:
+ # invalid language assertions
+ pass
+ except AttributeError:
+ # wx 2.6
+ wxLangIds.append(wxLI)
+
+ langCodes = [(langIdNameMap[wxLangId], wxLangId)
+ for wxLangId in wxLangIds
+ if wxLangId in langIdNameMap]
+
+ for lc, wxli in langCodes:
+ l, cnt = lc.split('_')
+
+ if cnt in flagart.catalog:
+ bmp = flagart.catalog[cnt].getBitmap()
+ else:
+ bmp = flagart.catalog['BLANK'].getBitmap()
+
+ icons.Add(bmp)
+ name = wx.Locale.GetLanguageName(wxli)
+ if wxli == wx.LANGUAGE_DEFAULT:
+ #print cnt, name, lc, wxli
+ name = 'Default: '+name
+
+ names.append(name)
+ langs.append(wxli)
+
+ return icons, names, langs
+
+
+def GetLanguageFlag(lang):
+ """ Returns a bitmap of the flag for the country of the language id """
+ langIdNameMap = BuildLanguageCountryMapping()
+ if lang in langIdNameMap:
+ cnt = langIdNameMap[lang].split('_')[1]
+ if cnt in flagart.catalog:
+ return flagart.catalog[cnt].getBitmap()
+ return flagart.catalog['BLANK'].getBitmap()
+
+
+def BuildLanguageCountryMapping():
+ """ Builds a mapping of language ids to LANG_COUNTRY codes """
+ res = {}
+ for name in _wxLangIds:
+ n = 'wx.'+name
+ wn = getattr(wx, name)
+
+ li = wx.Locale.GetLanguageInfo(wn)
+ if li:
+ code = li.CanonicalName
+
+ if wn in langIdCountryMap:
+ # override, drop country
+ if '_' in code:
+ code = code.split('_')[0]
+ code += '_'+langIdCountryMap[wn]
+
+ # map unhandled to blank images
+ elif '_' not in code:
+ code += '_BLANK'
+
+ res[wn] = code
+ return res
+
+def GetWxIdentifierForLanguage(lang):
+ """ Returns the language id as a string """
+ for n in dir(wx):
+ if n.startswith('LANGUAGE_') and getattr(wx, n) == lang:
+ return n
+ raise Exception, 'Language %s not found'%lang
+
+
+#-------------------------------------------------------------------------------
+
+class LanguageListCtrl(wx.ListCtrl):
+ """ wx.ListCtrl derived control that displays languages and flags """
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.LC_REPORT | wx.LC_NO_HEADER | wx.LC_SINGLE_SEL,
+ filter=LC_AVAILABLE, only=(), select=None, name='languagelistctrl'):
+
+ wx.ListCtrl.__init__(self, parent, id, pos, size, style, name=name)
+
+ self.SetUpFilter(filter, only)
+ self.Language = select
+
+ def SetUpFilter(self, filter=LC_AVAILABLE, only=()):
+ """ Filters the languages displayed in the control """
+ lang = self.GetLanguage()
+
+ self.filter, self.only = filter, only
+ self.icons, self.choices, self.langs = CreateLanguagesResourceLists(filter, only)
+
+ self.AssignImageList(self.icons, wx.IMAGE_LIST_SMALL)
+
+ self.ClearAll()
+ self.InsertColumn(0, '', width=175)
+ for i in range(len(self.choices)):
+ self.InsertImageStringItem(i, self.choices[i], i)
+
+ self.SetLanguage(lang)
+
+ def GetLanguage(self):
+ """ Returns the language id for the currently selected language in the control """
+ idx = self.GetFirstSelected()
+ if idx != -1:
+ return self.langs[idx]
+ else:
+ None
+
+ def SetLanguage(self, lang):
+ """ Selects the given language ids item in the control """
+ if lang is not None:
+ if lang in self.langs:
+ idx = self.langs.index(lang)
+ self.Select(idx)
+ self.Focus(idx)
+
+ Language = property(GetLanguage, SetLanguage, doc="See `GetLanguage` and `SetLanguage`")
+
+#-------------------------------------------------------------------------------
+
+
+if __name__ == '__main__':
+ a = wx.App()
+
+ print GetLanguageFlag(wx.LANGUAGE_AFRIKAANS)
+
+ f=wx.Frame(None, -1)
+ f.p=wx.Panel(f, -1)
+ s=wx.BoxSizer(wx.VERTICAL)
+ f.p.SetSizer(s)
+ try:
+ f.lc=LanguageChoice(f.p, pos = (220, 10), size = (200, 25))
+ s.Add(f.lc, 0, wx.GROW)
+ except:
+ pass
+ f.llc=LanguageListCtrl(f.p, pos = (10, 10), size = (200, 200),
+ filter=LC_ONLY,
+ only=(wx.LANGUAGE_AFRIKAANS, wx.LANGUAGE_ENGLISH,
+ wx.LANGUAGE_FRENCH, wx.LANGUAGE_GERMAN, wx.LANGUAGE_ITALIAN,
+ wx.LANGUAGE_PORTUGUESE_BRAZILIAN, wx.LANGUAGE_SPANISH),
+ select=wx.LANGUAGE_ENGLISH)
+## filter=LC_ALL)
+ s.Add(f.llc, 1, wx.GROW)
+ f.Show()
+
+ a.MainLoop()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/layoutf.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/layoutf.py
new file mode 100644
index 0000000..82111fb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/layoutf.py
@@ -0,0 +1,270 @@
+# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for wx namespace
+#
+# 12/18/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxScrolledMessageDialog -> ScrolledMessageDialog
+#
+
+import re
+import wx
+
+class Layoutf(wx.LayoutConstraints):
+ """
+ The class Layoutf(wxLayoutConstraints) presents a simplification
+ of the wxLayoutConstraints syntax. The name Layoutf is choosen
+ because of the similarity with C's printf function.
+
+ Quick Example::
+
+ lc = Layoutf('t=t#1;l=r10#2;r!100;h%h50#1', (self, self.panel))
+
+
+ is equivalent to::
+
+ lc = wx.LayoutContraints()
+ lc.top.SameAs(self, wx.Top)
+ lc.left.SameAs(self.panel, wx.Right, 10)
+ lc.right.Absolute(100)
+ lc.height.PercentOf(self, wx.Height, 50)
+
+
+ Usage:
+
+ You can give a constraint string to the Layoutf constructor,
+ or use the 'pack' method. The following are equivalent::
+
+ lc = Layoutf('t=t#1;l=r#2;r!100;h%h50#1', (self, self.panel))
+
+
+ and::
+
+ lc = Layoutf()
+ lc.pack('t=t#1;l=r#2;r!100;h%h50#1', (self, self.panel))
+
+
+ Besides 'pack' there's also 'debug_pack' which does not set
+ constraints, but prints traditional wxLayoutConstraint calls to
+ stdout.
+
+ The calls to the Layoutf constructor and pack methods have
+ the following argument list:
+
+ `(constraint_string, objects_tuple)`
+
+
+ Constraint String syntax:
+
+ Constraint directives are separated by semi-colons. You
+ generally (always?) need four directives to completely describe a
+ subwindow's location.
+
+ A single directive has either of the following forms:
+
+ 1. <own attribute><compare operation>[numerical argument]
+ for example ``r!100`` -> lc.right.Absolute(100) )
+ and ``w*`` -> lc.width.AsIs()
+
+ 2. <own attribute><compare operation>[numerical argument]
+ #<compare object nr.>
+ for example ``t_10#2`` -> lc.top.Below(<second obj>, 10)
+
+ 3. <own attribute><compare operation><compare attribute>
+ [numerical argument]#<compare object nr.>
+ for example ``w%h50#2`` -> lc.width.PercentOf(<second obj>, wx.Height, 50) and ``t=b#1`` -> lc.top.SameAs(<first obj>, wx.Bottom)
+
+ Which one you need is defined by the <compare operation>
+ type. The following take type 1 (no object to compare with):
+
+ * '!': 'Absolute', '?': 'Unconstrained', '*': 'AsIs'
+
+ These take type 2 (need to be compared with another object)
+
+ * '<': 'LeftOf', '>': 'RightOf', '^': 'Above', '_': 'Below'
+
+ These take type 3 (need to be compared to another object
+ attribute)
+
+ * '=': 'SameAs', '%': 'PercentOf'
+
+ For all types, the <own attribute> letter can be any of
+
+ * 't': 'top', 'l': 'left', 'b': 'bottom',
+ * 'r': 'right', 'h': 'height', 'w': 'width',
+ * 'x': 'centreX', 'y': 'centreY'
+
+ If the operation takes an (optional) numerical argument, place it
+ in [numerical argument]. For type 3 directives, the <compare
+ attribute> letter can be any of
+
+ * 't': 'wxTop', 'l': 'wxLeft', 'b': 'wx.Bottom'
+ * 'r': 'wxRight', 'h': 'wxHeight', 'w': 'wx.Width',
+ * 'x': 'wxCentreX', 'y': 'wx.CentreY'
+
+ Note that these are the same letters as used for <own attribute>,
+ so you'll only need to remember one set. Finally, the object
+ whose attribute is refered to, is specified by #<compare object
+ nr>, where <compare object nr> is the 1-based (stupid, I know,
+ but I've gotten used to it) index of the object in the
+ objects_tuple argument.
+
+ Bugs:
+
+ Not entirely happy about the logic in the order of arguments
+ after the <compare operation> character.
+
+ Not all wxLayoutConstraint methods are included in the
+ syntax. However, the type 3 directives are generally the most
+ used. Further excuse: wxWindows layout constraints are at the
+ time of this writing not documented.
+
+"""
+
+ attr_d = { 't': 'top', 'l': 'left', 'b': 'bottom',
+ 'r': 'right', 'h': 'height', 'w': 'width',
+ 'x': 'centreX', 'y': 'centreY' }
+ op_d = { '=': 'SameAs', '%': 'PercentOf', '<': 'LeftOf',
+ '>': 'RightOf', '^': 'Above', '_': 'Below',
+ '!': 'Absolute', '?': 'Unconstrained', '*': 'AsIs' }
+ cmp_d = { 't': 'wx.Top', 'l': 'wx.Left', 'b': 'wx.Bottom',
+ 'r': 'wx.Right', 'h': 'wx.Height', 'w': 'wx.Width',
+ 'x': 'wx.CentreX', 'y': 'wx.CentreY' }
+
+ rexp1 = re.compile('^\s*([tlrbhwxy])\s*([!\?\*])\s*(\d*)\s*$')
+ rexp2 = re.compile('^\s*([tlrbhwxy])\s*([=%<>^_])\s*([tlrbhwxy]?)\s*(\d*)\s*#(\d+)\s*$')
+
+ def __init__(self,pstr=None,winlist=None):
+ wx.LayoutConstraints.__init__(self)
+ if pstr:
+ self.pack(pstr,winlist)
+
+ def pack(self, pstr, winlist):
+ pstr = pstr.lower()
+ for item in pstr.split(';'):
+ m = self.rexp1.match(item)
+ if m:
+ g = list(m.groups())
+ attr = getattr(self, self.attr_d[g[0]])
+ func = getattr(attr, self.op_d[g[1]])
+ if g[1] == '!':
+ func(int(g[2]))
+ else:
+ func()
+ continue
+ m = self.rexp2.match(item)
+ if not m: raise ValueError
+ g = list(m.groups())
+ attr = getattr(self, self.attr_d[g[0]])
+ func = getattr(attr, self.op_d[g[1]])
+ if g[3]: g[3] = int(g[3])
+ else: g[3] = None;
+ g[4] = int(g[4]) - 1
+ if g[1] in '<>^_':
+ if g[3]: func(winlist[g[4]], g[3])
+ else: func(winlist[g[4]])
+ else:
+ cmp = eval(self.cmp_d[g[2]])
+ if g[3]: func(winlist[g[4]], cmp, g[3])
+ else: func(winlist[g[4]], cmp)
+
+ def debug_pack(self, pstr, winlist):
+ pstr = pstr.lower()
+ for item in pstr.split(';'):
+ m = self.rexp1.match(item)
+ if m:
+ g = list(m.groups())
+ attr = getattr(self, self.attr_d[g[0]])
+ func = getattr(attr, self.op_d[g[1]])
+ if g[1] == '!':
+ print "%s.%s.%s(%s)" % \
+ ('self',self.attr_d[g[0]],self.op_d[g[1]],g[2])
+ else:
+ print "%s.%s.%s()" % \
+ ('self',self.attr_d[g[0]],self.op_d[g[1]])
+ continue
+ m = self.rexp2.match(item)
+ if not m: raise ValueError
+ g = list(m.groups())
+ if g[3]: g[3] = int(g[3])
+ else: g[3] = 0;
+ g[4] = int(g[4]) - 1
+ if g[1] in '<>^_':
+ if g[3]: print "%s.%s.%s(%s,%d)" % \
+ ('self',self.attr_d[g[0]],self.op_d[g[1]],winlist[g[4]],
+ g[3])
+ else: print "%s.%s.%s(%s)" % \
+ ('self',self.attr_d[g[0]],self.op_d[g[1]],winlist[g[4]])
+ else:
+ if g[3]: print "%s.%s.%s(%s,%s,%d)" % \
+ ('self',self.attr_d[g[0]],self.op_d[g[1]],winlist[g[4]],
+ self.cmp_d[g[2]],g[3])
+ else: print "%s.%s.%s(%s,%s)" % \
+ ('self',self.attr_d[g[0]],self.op_d[g[1]],winlist[g[4]],
+ self.cmp_d[g[2]])
+
+if __name__=='__main__':
+
+ class TestLayoutf(wx.Frame):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, -1, 'Test Layout Constraints',
+ wx.DefaultPosition, (500, 300))
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+ self.SetAutoLayout(True)
+
+ self.panelA = wx.Window(self, -1, style=wx.SIMPLE_BORDER)
+ self.panelA.SetBackgroundColour(wx.BLUE)
+ self.panelA.SetConstraints(Layoutf('t=t10#1;l=l10#1;b=b10#1;r%r50#1',(self,)))
+
+ self.panelB = wx.Window(self, -1, style=wx.SIMPLE_BORDER)
+ self.panelB.SetBackgroundColour(wx.RED)
+ self.panelB.SetConstraints(Layoutf('t=t10#1;r=r10#1;b%b30#1;l>10#2', (self,self.panelA)))
+
+ self.panelC = wx.Window(self, -1, style=wx.SIMPLE_BORDER)
+ self.panelC.SetBackgroundColour(wx.WHITE)
+ self.panelC.SetConstraints(Layoutf('t_10#3;r=r10#1;b=b10#1;l>10#2', (self,self.panelA,self.panelB)))
+
+ b = wx.Button(self.panelA, -1, ' About: ')
+ b.SetConstraints(Layoutf('X=X#1;Y=Y#1;h*;w%w50#1', (self.panelA,)))
+ self.Bind(wx.EVT_BUTTON, self.OnAbout, b)
+
+ b = wx.Button(self.panelB, 100, ' Panel B ')
+ b.SetConstraints(Layoutf('t=t2#1;r=r4#1;h*;w*', (self.panelB,)))
+
+ self.panelD = wx.Window(self.panelC, -1, style=wx.SIMPLE_BORDER)
+ self.panelD.SetBackgroundColour(wx.GREEN)
+ self.panelD.SetConstraints(Layoutf('b%h50#1;r%w50#1;h=h#2;w=w#2', (self.panelC, b)))
+
+ b = wx.Button(self.panelC, -1, ' Panel C ')
+ b.SetConstraints(Layoutf('t_#1;l>#1;h*;w*', (self.panelD,)))
+ self.Bind(wx.EVT_BUTTON, self.OnButton, b)
+
+ wx.StaticText(self.panelD, -1, "Panel D", (4, 4)).SetBackgroundColour(wx.GREEN)
+
+ def OnButton(self, event):
+ self.Close(True)
+
+ def OnAbout(self, event):
+ import wx.lib.dialogs
+ msg = wx.lib.dialogs.ScrolledMessageDialog(self, Layoutf.__doc__, "about")
+ msg.ShowModal()
+ msg.Destroy()
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+ class TestApp(wx.App):
+ def OnInit(self):
+ frame = TestLayoutf(None)
+ frame.Show(1)
+ self.SetTopWindow(frame)
+ return 1
+
+ app = TestApp(0)
+ app.MainLoop()
+
+
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/__init__.py
new file mode 100644
index 0000000..0f8824b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/__init__.py
@@ -0,0 +1,26 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.masked
+# Purpose: A package containing the masked edit controls
+#
+# Author: Will Sadkin, Jeff Childers
+#
+# Created: 6-Mar-2004
+# RCS-ID: $Id$
+# Copyright: (c) 2004
+# License: wxWidgets license
+#----------------------------------------------------------------------
+__author__ = "Will Sadkin <wsadkin |at| parlancecorp.com>"
+__date__ = "02 Dec 2006, 19:00 GMT-05:00"
+__version__ = "1.11"
+__doc__ = """\
+package providing "masked edit" controls, allowing characters within a data entry control to remain fixed, and providing fine-grain control over allowed user input.
+"""
+
+# import relevant external symbols into package namespace:
+from maskededit import *
+from textctrl import BaseMaskedTextCtrl, PreMaskedTextCtrl, TextCtrl
+from combobox import BaseMaskedComboBox, PreMaskedComboBox, ComboBox, MaskedComboBoxSelectEvent
+from numctrl import NumCtrl, wxEVT_COMMAND_MASKED_NUMBER_UPDATED, EVT_NUM, NumberUpdatedEvent
+from timectrl import TimeCtrl, wxEVT_TIMEVAL_UPDATED, EVT_TIMEUPDATE, TimeUpdatedEvent
+from ipaddrctrl import IpAddrCtrl
+from ctrl import Ctrl, controlTypes
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/combobox.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/combobox.py
new file mode 100644
index 0000000..76da846
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/combobox.py
@@ -0,0 +1,794 @@
+#----------------------------------------------------------------------------
+# Name: masked.combobox.py
+# Authors: Will Sadkin
+# Email: wsadkin@nameconnector.com
+# Created: 02/11/2003
+# Copyright: (c) 2003 by Will Sadkin, 2003
+# RCS-ID: $Id$
+# License: wxWidgets license
+#----------------------------------------------------------------------------
+#
+# This masked edit class allows for the semantics of masked controls
+# to be applied to combo boxes.
+#
+#----------------------------------------------------------------------------
+
+"""
+Provides masked edit capabilities within a ComboBox format, as well as
+a base class from which you can derive masked comboboxes tailored to a specific
+function. See maskededit module overview for how to configure the control.
+"""
+
+import wx, types, string
+from wx.lib.masked import *
+
+# jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
+# be a good place to implement the 2.3 logger class
+from wx.tools.dbg import Logger
+##dbg = Logger()
+##dbg(enable=1)
+
+## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+## Because calling SetSelection programmatically does not fire EVT_COMBOBOX
+## events, we have to do it ourselves when we auto-complete.
+class MaskedComboBoxSelectEvent(wx.PyCommandEvent):
+ """
+ Because calling SetSelection programmatically does not fire EVT_COMBOBOX
+ events, the derived control has to do it itself when it auto-completes.
+ """
+ def __init__(self, id, selection = 0, object=None):
+ wx.PyCommandEvent.__init__(self, wx.wxEVT_COMMAND_COMBOBOX_SELECTED, id)
+
+ self.__selection = selection
+ self.SetEventObject(object)
+
+ def GetSelection(self):
+ """Retrieve the value of the control at the time
+ this event was generated."""
+ return self.__selection
+
+class MaskedComboBoxEventHandler(wx.EvtHandler):
+ """
+ This handler ensures that the derived control can react to events
+ from the base control before any external handlers run, to ensure
+ proper behavior.
+ """
+ def __init__(self, combobox):
+ wx.EvtHandler.__init__(self)
+ self.combobox = combobox
+ combobox.PushEventHandler(self)
+ self.Bind(wx.EVT_SET_FOCUS, self.combobox._OnFocus ) ## defeat automatic full selection
+ self.Bind(wx.EVT_KILL_FOCUS, self.combobox._OnKillFocus ) ## run internal validator
+ self.Bind(wx.EVT_LEFT_DCLICK, self.combobox._OnDoubleClick) ## select field under cursor on dclick
+ self.Bind(wx.EVT_RIGHT_UP, self.combobox._OnContextMenu ) ## bring up an appropriate context menu
+ self.Bind(wx.EVT_CHAR, self.combobox._OnChar ) ## handle each keypress
+ self.Bind(wx.EVT_KEY_DOWN, self.combobox._OnKeyDownInComboBox ) ## for special processing of up/down keys
+ self.Bind(wx.EVT_KEY_DOWN, self.combobox._OnKeyDown ) ## for processing the rest of the control keys
+ ## (next in evt chain)
+ self.Bind(wx.EVT_COMBOBOX, self.combobox._OnDropdownSelect ) ## to bring otherwise completely independent base
+ ## ctrl selection into maskededit framework
+ self.Bind(wx.EVT_TEXT, self.combobox._OnTextChange ) ## color control appropriately & keep
+ ## track of previous value for undo
+
+
+
+class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
+ """
+ Base class for generic masked edit comboboxes; allows auto-complete of values.
+ It is not meant to be instantiated directly, but rather serves as a base class
+ for any subsequent refinements.
+ """
+ def __init__( self, parent, id=-1, value = '',
+ pos = wx.DefaultPosition,
+ size = wx.DefaultSize,
+ choices = [],
+ style = wx.CB_DROPDOWN,
+ validator = wx.DefaultValidator,
+ name = "maskedComboBox",
+ setupEventHandling = True, ## setup event handling by default):
+ **kwargs):
+
+
+ kwargs['choices'] = choices ## set up maskededit to work with choice list too
+
+ self._prevSelection = (-1, -1)
+
+ ## Since combobox completion is case-insensitive, always validate same way
+ if not kwargs.has_key('compareNoCase'):
+ kwargs['compareNoCase'] = True
+
+ MaskedEditMixin.__init__( self, name, **kwargs )
+
+ self._choices = self._ctrl_constraints._choices
+## dbg('self._choices:', self._choices)
+
+ if self._ctrl_constraints._alignRight:
+ choices = [choice.rjust(self._masklength) for choice in choices]
+ else:
+ choices = [choice.ljust(self._masklength) for choice in choices]
+
+ wx.ComboBox.__init__(self, parent, id, value='',
+ pos=pos, size = size,
+ choices=choices, style=style|wx.WANTS_CHARS,
+ validator=validator,
+ name=name)
+ self.controlInitialized = True
+
+ self._PostInit(style=style, setupEventHandling=setupEventHandling,
+ name=name, value=value, **kwargs)
+
+
+ def _PostInit(self, style=wx.CB_DROPDOWN,
+ setupEventHandling = True, ## setup event handling by default):
+ name = "maskedComboBox", value='', **kwargs):
+
+ # This is necessary, because wxComboBox currently provides no
+ # method for determining later if this was specified in the
+ # constructor for the control...
+ self.__readonly = style & wx.CB_READONLY == wx.CB_READONLY
+
+ if not hasattr(self, 'controlInitialized'):
+
+ self.controlInitialized = True ## must have been called via XRC, therefore base class is constructed
+ if not kwargs.has_key('choices'):
+ choices=[]
+ kwargs['choices'] = choices ## set up maskededit to work with choice list too
+ self._choices = []
+
+ ## Since combobox completion is case-insensitive, always validate same way
+ if not kwargs.has_key('compareNoCase'):
+ kwargs['compareNoCase'] = True
+
+ MaskedEditMixin.__init__( self, name, **kwargs )
+
+ self._choices = self._ctrl_constraints._choices
+## dbg('self._choices:', self._choices)
+
+ if self._ctrl_constraints._alignRight:
+ choices = [choice.rjust(self._masklength) for choice in choices]
+ else:
+ choices = [choice.ljust(self._masklength) for choice in choices]
+ wx.ComboBox.Clear(self)
+ wx.ComboBox.AppendItems(self, choices)
+
+
+ # Set control font - fixed width by default
+ self._setFont()
+
+ if self._autofit:
+ self.SetClientSize(self._CalcSize())
+ width = self.GetSize().width
+ height = self.GetBestSize().height
+ self.SetInitialSize((width, height))
+
+
+ if value:
+ # ensure value is width of the mask of the control:
+ if self._ctrl_constraints._alignRight:
+ value = value.rjust(self._masklength)
+ else:
+ value = value.ljust(self._masklength)
+
+ if self.__readonly:
+ self.SetStringSelection(value)
+ else:
+ self._SetInitialValue(value)
+
+
+ self._SetKeycodeHandler(wx.WXK_UP, self._OnSelectChoice)
+ self._SetKeycodeHandler(wx.WXK_DOWN, self._OnSelectChoice)
+
+ self.replace_next_combobox_event = False
+ self.correct_selection = -1
+
+ if setupEventHandling:
+ ## Setup event handling functions through event handler object,
+ ## to guarantee processing prior to giving event callbacks from
+ ## outside the class:
+ self.evt_handler = MaskedComboBoxEventHandler(self)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnWindowDestroy )
+
+
+
+ def __repr__(self):
+ return "<MaskedComboBox: %s>" % self.GetValue()
+
+
+ def OnWindowDestroy(self, event):
+ # clean up associated event handler object:
+ if self.RemoveEventHandler(self.evt_handler):
+ wx.CallAfter(self.evt_handler.Destroy)
+ event.Skip()
+
+
+ def _CalcSize(self, size=None):
+ """
+ Calculate automatic size if allowed; augment base mixin function
+ to account for the selector button.
+ """
+ size = self._calcSize(size)
+ return (size[0]+20, size[1])
+
+
+ def SetFont(self, *args, **kwargs):
+ """ Set the font, then recalculate control size, if appropriate. """
+ wx.ComboBox.SetFont(self, *args, **kwargs)
+ if self._autofit:
+## dbg('calculated size:', self._CalcSize())
+ self.SetClientSize(self._CalcSize())
+ width = self.GetSize().width
+ height = self.GetBestSize().height
+## dbg('setting client size to:', (width, height))
+ self.SetInitialSize((width, height))
+
+
+ def _GetSelection(self):
+ """
+ Allow mixin to get the text selection of this control.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+## dbg('MaskedComboBox::_GetSelection()')
+ return self.GetMark()
+
+ def _SetSelection(self, sel_start, sel_to):
+ """
+ Allow mixin to set the text selection of this control.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+## dbg('MaskedComboBox::_SetSelection: setting mark to (%d, %d)' % (sel_start, sel_to))
+ if not self.__readonly:
+ return self.SetMark( sel_start, sel_to )
+
+
+ def _GetInsertionPoint(self):
+## dbg('MaskedComboBox::_GetInsertionPoint()', indent=1)
+## ret = self.GetInsertionPoint()
+ # work around new bug in 2.5, in which the insertion point
+ # returned is always at the right side of the selection,
+ # rather than the start, as is the case with TextCtrl.
+ ret = self.GetMark()[0]
+## dbg('returned', ret, indent=0)
+ return ret
+
+ def _SetInsertionPoint(self, pos):
+## dbg('MaskedComboBox::_SetInsertionPoint(%d)' % pos)
+ if not self.__readonly:
+ self.SetInsertionPoint(pos)
+
+
+ def IsEmpty(*args, **kw):
+ return MaskedEditMixin.IsEmpty(*args, **kw)
+
+
+ def _GetValue(self):
+ """
+ Allow mixin to get the raw value of the control with this function.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+ return self.GetValue()
+
+ def _SetValue(self, value):
+ """
+ Allow mixin to set the raw value of the control with this function.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+ # For wxComboBox, ensure that values are properly padded so that
+ # if varying length choices are supplied, they always show up
+ # in the window properly, and will be the appropriate length
+ # to match the mask:
+ if self._ctrl_constraints._alignRight:
+ value = value.rjust(self._masklength)
+ else:
+ value = value.ljust(self._masklength)
+
+ # Record current selection and insertion point, for undo
+ self._prevSelection = self._GetSelection()
+ self._prevInsertionPoint = self._GetInsertionPoint()
+## dbg('MaskedComboBox::_SetValue(%s), selection beforehand: %d' % (value, self.GetSelection()))
+ wx.ComboBox.SetValue(self, value)
+## dbg('MaskedComboBox::_SetValue(%s), selection now: %d' % (value, self.GetSelection()))
+ # text change events don't always fire, so we check validity here
+ # to make certain formatting is applied:
+ self._CheckValid()
+
+ def SetValue(self, value):
+ """
+ This function redefines the externally accessible .SetValue to be
+ a smart "paste" of the text in question, so as not to corrupt the
+ masked control. NOTE: this must be done in the class derived
+ from the base wx control.
+ """
+## dbg('MaskedComboBox::SetValue(%s)' % value, indent=1)
+ if not self._mask:
+ wx.ComboBox.SetValue(value) # revert to base control behavior
+## dbg('no mask; deferring to base class', indent=0)
+ return
+ # else...
+ # empty previous contents, replacing entire value:
+## dbg('MaskedComboBox::SetValue: selection beforehand: %d' % (self.GetSelection()))
+ self._SetInsertionPoint(0)
+ self._SetSelection(0, self._masklength)
+
+ if( len(value) < self._masklength # value shorter than control
+ and (self._isFloat or self._isInt) # and it's a numeric control
+ and self._ctrl_constraints._alignRight ): # and it's a right-aligned control
+ # try to intelligently "pad out" the value to the right size:
+ value = self._template[0:self._masklength - len(value)] + value
+## dbg('padded value = "%s"' % value)
+
+ # For wxComboBox, ensure that values are properly padded so that
+ # if varying length choices are supplied, they always show up
+ # in the window properly, and will be the appropriate length
+ # to match the mask:
+ elif self._ctrl_constraints._alignRight:
+ value = value.rjust(self._masklength)
+ else:
+ value = value.ljust(self._masklength)
+
+
+ # make SetValue behave the same as if you had typed the value in:
+ try:
+ value, replace_to = self._Paste(value, raise_on_invalid=True, just_return_value=True)
+ if self._isFloat:
+ self._isNeg = False # (clear current assumptions)
+ value = self._adjustFloat(value)
+ elif self._isInt:
+ self._isNeg = False # (clear current assumptions)
+ value = self._adjustInt(value)
+ elif self._isDate and not self.IsValid(value) and self._4digityear:
+ value = self._adjustDate(value, fixcentury=True)
+ except ValueError:
+ # If date, year might be 2 digits vs. 4; try adjusting it:
+ if self._isDate and self._4digityear:
+ dateparts = value.split(' ')
+ dateparts[0] = self._adjustDate(dateparts[0], fixcentury=True)
+ value = string.join(dateparts, ' ')
+ value = self._Paste(value, raise_on_invalid=True, just_return_value=True)
+ else:
+ raise
+## dbg('adjusted value: "%s"' % value)
+
+ # Attempt to compensate for fact that calling .SetInsertionPoint() makes the
+ # selection index -1, even if the resulting set value is in the list.
+ # So, if we are setting a value that's in the list, use index selection instead.
+ if value in self._choices:
+ index = self._choices.index(value)
+ self._prevValue = self._curValue
+ self._curValue = self._choices[index]
+ self._ctrl_constraints._autoCompleteIndex = index
+ self.SetSelection(index)
+ else:
+ self._SetValue(value)
+#### dbg('queuing insertion after .SetValue', replace_to)
+ wx.CallAfter(self._SetInsertionPoint, replace_to)
+ wx.CallAfter(self._SetSelection, replace_to, replace_to)
+## dbg(indent=0)
+
+
+ def _Refresh(self):
+ """
+ Allow mixin to refresh the base control with this function.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+ wx.ComboBox.Refresh(self)
+
+ def Refresh(self):
+ """
+ This function redefines the externally accessible .Refresh() to
+ validate the contents of the masked control as it refreshes.
+ NOTE: this must be done in the class derived from the base wx control.
+ """
+ self._CheckValid()
+ self._Refresh()
+
+
+ def _IsEditable(self):
+ """
+ Allow mixin to determine if the base control is editable with this function.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+ return not self.__readonly
+
+
+ def Cut(self):
+ """
+ This function redefines the externally accessible .Cut to be
+ a smart "erase" of the text in question, so as not to corrupt the
+ masked control. NOTE: this must be done in the class derived
+ from the base wx control.
+ """
+ if self._mask:
+ self._Cut() # call the mixin's Cut method
+ else:
+ wx.ComboBox.Cut(self) # else revert to base control behavior
+
+
+ def Paste(self):
+ """
+ This function redefines the externally accessible .Paste to be
+ a smart "paste" of the text in question, so as not to corrupt the
+ masked control. NOTE: this must be done in the class derived
+ from the base wx control.
+ """
+ if self._mask:
+ self._Paste() # call the mixin's Paste method
+ else:
+ wx.ComboBox.Paste(self) # else revert to base control behavior
+
+
+ def Undo(self):
+ """
+ This function defines the undo operation for the control. (The default
+ undo is 1-deep.)
+ """
+ if not self.__readonly:
+ if self._mask:
+ self._Undo()
+ else:
+ wx.ComboBox.Undo(self) # else revert to base control behavior
+
+ def Append( self, choice, clientData=None ):
+ """
+ This base control function override is necessary so the control can keep track
+ of any additions to the list of choices, because wx.ComboBox doesn't have an
+ accessor for the choice list. The code here is the same as in the
+ SetParameters() mixin function, but is done for the individual value
+ as appended, so the list can be built incrementally without speed penalty.
+ """
+ if self._mask:
+ if type(choice) not in (types.StringType, types.UnicodeType):
+ raise TypeError('%s: choices must be a sequence of strings' % str(self._index))
+ elif not self.IsValid(choice):
+ raise ValueError('%s: "%s" is not a valid value for the control as specified.' % (str(self._index), choice))
+
+ if not self._ctrl_constraints._choices:
+ self._ctrl_constraints._compareChoices = []
+ self._ctrl_constraints._choices = []
+ self._hasList = True
+
+ compareChoice = choice.strip()
+
+ if self._ctrl_constraints._compareNoCase:
+ compareChoice = compareChoice.lower()
+
+ if self._ctrl_constraints._alignRight:
+ choice = choice.rjust(self._masklength)
+ else:
+ choice = choice.ljust(self._masklength)
+ if self._ctrl_constraints._fillChar != ' ':
+ choice = choice.replace(' ', self._fillChar)
+## dbg('updated choice:', choice)
+
+
+ self._ctrl_constraints._compareChoices.append(compareChoice)
+ self._ctrl_constraints._choices.append(choice)
+ self._choices = self._ctrl_constraints._choices # (for shorthand)
+
+ if( not self.IsValid(choice) and
+ (not self._ctrl_constraints.IsEmpty(choice) or
+ (self._ctrl_constraints.IsEmpty(choice) and self._ctrl_constraints._validRequired) ) ):
+ raise ValueError('"%s" is not a valid value for the control "%s" as specified.' % (choice, self.name))
+
+ wx.ComboBox.Append(self, choice, clientData)
+
+
+ def AppendItems( self, choices ):
+ """
+ AppendItems() is handled in terms of Append, to avoid code replication.
+ """
+ for choice in choices:
+ self.Append(choice)
+
+
+ def Clear( self ):
+ """
+ This base control function override is necessary so the derived control can
+ keep track of any additions to the list of choices, because wx.ComboBox
+ doesn't have an accessor for the choice list.
+ """
+ if self._mask:
+ self._choices = []
+ self._ctrl_constraints._autoCompleteIndex = -1
+ if self._ctrl_constraints._choices:
+ self.SetCtrlParameters(choices=[])
+ wx.ComboBox.Clear(self)
+
+
+ def _OnCtrlParametersChanged(self):
+ """
+ This overrides the mixin's default OnCtrlParametersChanged to detect
+ changes in choice list, so masked.Combobox can update the base control:
+ """
+ if self.controlInitialized and self._choices != self._ctrl_constraints._choices:
+ wx.ComboBox.Clear(self)
+ self._choices = self._ctrl_constraints._choices
+ for choice in self._choices:
+ wx.ComboBox.Append( self, choice )
+
+
+ # Not all wx platform implementations have .GetMark, so we make the following test,
+ # and fall back to our old hack if they don't...
+ #
+ if not hasattr(wx.ComboBox, 'GetMark'):
+ def GetMark(self):
+ """
+ This function is a hack to make up for the fact that wx.ComboBox has no
+ method for returning the selected portion of its edit control. It
+ works, but has the nasty side effect of generating lots of intermediate
+ events.
+ """
+## dbg(suspend=1) # turn off debugging around this function
+## dbg('MaskedComboBox::GetMark', indent=1)
+ if self.__readonly:
+## dbg(indent=0)
+ return 0, 0 # no selection possible for editing
+## sel_start, sel_to = wxComboBox.GetMark(self) # what I'd *like* to have!
+ sel_start = sel_to = self.GetInsertionPoint()
+## dbg("current sel_start:", sel_start)
+ value = self.GetValue()
+## dbg('value: "%s"' % value)
+
+ self._ignoreChange = True # tell _OnTextChange() to ignore next event (if any)
+
+ wx.ComboBox.Cut(self)
+ newvalue = self.GetValue()
+## dbg("value after Cut operation:", newvalue)
+
+ if newvalue != value: # something was selected; calculate extent
+## dbg("something selected")
+ sel_to = sel_start + len(value) - len(newvalue)
+ wx.ComboBox.SetValue(self, value) # restore original value and selection (still ignoring change)
+ wx.ComboBox.SetInsertionPoint(self, sel_start)
+ wx.ComboBox.SetMark(self, sel_start, sel_to)
+
+ self._ignoreChange = False # tell _OnTextChange() to pay attn again
+
+## dbg('computed selection:', sel_start, sel_to, indent=0, suspend=0)
+ return sel_start, sel_to
+ else:
+ def GetMark(self):
+## dbg('MaskedComboBox::GetMark()', indent = 1)
+ ret = wx.ComboBox.GetMark(self)
+## dbg('returned', ret, indent=0)
+ return ret
+
+
+ def SetSelection(self, index):
+ """
+ Necessary override for bookkeeping on choice selection, to keep current value
+ current.
+ """
+## dbg('MaskedComboBox::SetSelection(%d)' % index, indent=1)
+ if self._mask:
+ self._prevValue = self._curValue
+ self._ctrl_constraints._autoCompleteIndex = index
+ if index != -1:
+ self._curValue = self._choices[index]
+ else:
+ self._curValue = None
+ wx.ComboBox.SetSelection(self, index)
+## dbg('selection now: %d' % self.GetCurrentSelection(), indent=0)
+
+
+ def _OnKeyDownInComboBox(self, event):
+ """
+ This function is necessary because navigation and control key events
+ do not seem to normally be seen by the wxComboBox's EVT_CHAR routine.
+ (Tabs don't seem to be visible no matter what, except for CB_READONLY
+ controls, for some bizarre reason... {:-( )
+ """
+ key = event.GetKeyCode()
+## dbg('MaskedComboBox::OnKeyDownInComboBox(%d)' % key)
+ if event.GetKeyCode() in self._nav + self._control:
+ if not self._IsEditable():
+ # WANTS_CHARS with CB_READONLY apparently prevents navigation on WXK_TAB;
+ # ensure we can still navigate properly, as maskededit mixin::OnChar assumes
+ # that event.Skip() will just work, but it doesn't:
+ if self._keyhandlers.has_key(key):
+ self._keyhandlers[key](event)
+ # else pass
+ else:
+## dbg('calling OnChar()')
+ self._OnChar(event)
+ else:
+ event.Skip() # let mixin default KeyDown behavior occur
+## dbg(indent=0)
+
+
+ def _OnDropdownSelect(self, event):
+ """
+ This function appears to be necessary because dropdown selection seems to
+ manipulate the contents of the control in an inconsistent way, properly
+ changing the selection index, but *not* the value. (!) Calling SetSelection()
+ on a selection event for the same selection would seem like a nop, but it seems to
+ fix the problem.
+ """
+## dbg('MaskedComboBox::OnDropdownSelect(%d)' % event.GetSelection(), indent=1)
+ if self.replace_next_combobox_event:
+## dbg('replacing EVT_COMBOBOX')
+ self.replace_next_combobox_event = False
+ self._OnAutoSelect(self._ctrl_constraints, self.correct_selection)
+ else:
+## dbg('skipping EVT_COMBOBOX')
+ event.Skip()
+## dbg(indent=0)
+
+
+ def _OnSelectChoice(self, event):
+ """
+ This function appears to be necessary, because the processing done
+ on the text of the control somehow interferes with the combobox's
+ selection mechanism for the arrow keys.
+ """
+## dbg('MaskedComboBox::OnSelectChoice', indent=1)
+
+ if not self._mask:
+ event.Skip()
+ return
+
+ value = self.GetValue().strip()
+
+ if self._ctrl_constraints._compareNoCase:
+ value = value.lower()
+
+ if event.GetKeyCode() == wx.WXK_UP:
+ direction = -1
+ else:
+ direction = 1
+ match_index, partial_match = self._autoComplete(
+ direction,
+ self._ctrl_constraints._compareChoices,
+ value,
+ self._ctrl_constraints._compareNoCase,
+ current_index = self._ctrl_constraints._autoCompleteIndex)
+ if match_index is not None:
+## dbg('setting selection to', match_index)
+ # issue appropriate event to outside:
+ self._OnAutoSelect(self._ctrl_constraints, match_index=match_index)
+ self._CheckValid()
+ keep_processing = False
+ else:
+ pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
+ field = self._FindField(pos)
+ if self.IsEmpty() or not field._hasList:
+## dbg('selecting 1st value in list')
+ self._OnAutoSelect(self._ctrl_constraints, match_index=0)
+ self._CheckValid()
+ keep_processing = False
+ else:
+ # attempt field-level auto-complete
+## dbg(indent=0)
+ keep_processing = self._OnAutoCompleteField(event)
+## dbg('keep processing?', keep_processing, indent=0)
+ return keep_processing
+
+
+ def _OnAutoSelect(self, field, match_index=None):
+ """
+ Override mixin (empty) autocomplete handler, so that autocompletion causes
+ combobox to update appropriately.
+ Additionally allow items that aren't in the drop down.
+ """
+## dbg('MaskedComboBox::OnAutoSelect(%d, %s)' % (field._index, repr(match_index)), indent=1)
+## field._autoCompleteIndex = match
+ if isinstance(match_index, int):
+ if field == self._ctrl_constraints:
+ self.SetSelection(match_index)
+## dbg('issuing combo selection event')
+ self.GetEventHandler().ProcessEvent(
+ MaskedComboBoxSelectEvent( self.GetId(), match_index, self ) )
+ self._CheckValid()
+## dbg('field._autoCompleteIndex:', match)
+## dbg('self.GetCurrentSelection():', self.GetCurrentSelection())
+ end = self._goEnd(getPosOnly=True)
+## dbg('scheduling set of end position to:', end)
+ # work around bug in wx 2.5
+ wx.CallAfter(self.SetInsertionPoint, 0)
+ wx.CallAfter(self.SetInsertionPoint, end)
+ elif isinstance(match_index, str) or isinstance(match_index, unicode):
+## dbg('CallAfter SetValue')
+ # Preserve the textbox contents
+ # See commentary in _OnReturn docstring.
+ wx.CallAfter(self.SetValue, match_index)
+#### dbg('queuing insertion after .SetValue', replace_to)
+## dbg(indent=0)
+
+
+ def _OnReturn(self, event):
+ """
+ For wx.ComboBox, it seems that if you hit return when the dropdown is
+ dropped, the event that dismisses the dropdown will also blank the
+ control, because of the implementation of wxComboBox. So this function
+ examines the selection and if it is -1, and the value according to
+ (the base control!) is a value in the list, then it schedules a
+ programmatic wxComboBox.SetSelection() call to pick the appropriate
+ item in the list. (and then does the usual OnReturn bit.)
+ If the value isn't a value in the list then allow the current textbox contents to stay.
+ """
+## dbg('MaskedComboBox::OnReturn', indent=1)
+## dbg('current value: "%s"' % self.GetValue(), 'current selection:', self.GetCurrentSelection())
+ if self.GetCurrentSelection() == -1 and self.GetValue().lower().strip() in self._ctrl_constraints._compareChoices:
+## dbg('attempting to correct the selection to make it %d' % self._ctrl_constraints._autoCompleteIndex)
+## wx.CallAfter(self.SetSelection, self._ctrl_constraints._autoCompleteIndex)
+ self.replace_next_combobox_event = True
+ self.correct_selection = self._ctrl_constraints._autoCompleteIndex
+ else:
+ # Not doing this causes the item to be empty after hitting return on a non-selection while the drop
+ # down is showing. Not all masked comboboxes require choices from an autocomplete list.
+ self.replace_next_combobox_event = True
+ self.correct_selection = self._GetValue()
+ event.m_keyCode = wx.WXK_TAB
+ event.Skip()
+## dbg(indent=0)
+
+
+ def _LostFocus(self):
+## dbg('MaskedComboBox::LostFocus; Selection=%d, value="%s"' % (self.GetSelection(), self.GetValue()))
+ if self.GetCurrentSelection() == -1 and self.GetValue().lower().strip() in self._ctrl_constraints._compareChoices:
+## dbg('attempting to correct the selection to make it %d' % self._ctrl_constraints._autoCompleteIndex)
+ wx.CallAfter(self.SetSelection, self._ctrl_constraints._autoCompleteIndex)
+
+
+class ComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
+ """
+ The "user-visible" masked combobox control, this class is
+ identical to the BaseMaskedComboBox class it's derived from.
+ (This extra level of inheritance allows us to add the generic
+ set of masked edit parameters only to this class while allowing
+ other classes to derive from the "base" masked combobox control,
+ and provide a smaller set of valid accessor functions.)
+ See BaseMaskedComboBox for available methods.
+ """
+ pass
+
+
+class PreMaskedComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
+ """
+ This class exists to support the use of XRC subclassing.
+ """
+ # This should really be wx.EVT_WINDOW_CREATE but it is not
+ # currently delivered for native controls on all platforms, so
+ # we'll use EVT_SIZE instead. It should happen shortly after the
+ # control is created as the control is set to its "best" size.
+ _firstEventType = wx.EVT_SIZE
+
+ def __init__(self):
+ pre = wx.PreComboBox()
+ self.PostCreate(pre)
+ self.Bind(self._firstEventType, self.OnCreate)
+
+
+ def OnCreate(self, evt):
+ self.Unbind(self._firstEventType)
+ self._PostInit()
+
+__i = 0
+## CHANGELOG:
+## ====================
+## Version 1.4
+## 1. Added handler for EVT_COMBOBOX to address apparently inconsistent behavior
+## of control when the dropdown control is used to do a selection.
+## NOTE: due to misbehavior of wx.ComboBox re: losing all concept of the
+## current selection index if SetInsertionPoint() is called, which is required
+## to support masked .SetValue(), this control is flaky about retaining selection
+## information. I can't truly fix this without major changes to the base control,
+## but I've tried to compensate as best I can.
+## TODO: investigate replacing base control with ComboCtrl instead...
+## 2. Fixed navigation in readonly masked combobox, which was not working because
+## the base control doesn't do navigation if style=CB_READONLY|WANTS_CHARS.
+##
+##
+## Version 1.3
+## 1. Made definition of "hack" GetMark conditional on base class not
+## implementing it properly, to allow for migration in wx code base
+## while taking advantage of improvements therein for some platforms.
+##
+## Version 1.2
+## 1. Converted docstrings to reST format, added doc for ePyDoc.
+## 2. Renamed helper functions, vars etc. not intended to be visible in public
+## interface to code.
+##
+## Version 1.1
+## 1. Added .SetFont() method that properly resizes control
+## 2. Modified control to support construction via XRC mechanism.
+## 3. Added AppendItems() to conform with latest combobox.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/ctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/ctrl.py
new file mode 100644
index 0000000..dda7bc2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/ctrl.py
@@ -0,0 +1,108 @@
+#----------------------------------------------------------------------------
+# Name: wxPython.lib.masked.ctrl.py
+# Author: Will Sadkin
+# Created: 09/24/2003
+# Copyright: (c) 2003 by Will Sadkin
+# RCS-ID: $Id$
+# License: wxWindows license
+#----------------------------------------------------------------------------
+# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for wx namespace (minor)
+#
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Removed wx prefix
+#
+
+"""
+
+*masked.Ctrl* is actually a factory function for several types of
+masked edit controls:
+
+ ================= =========================================================
+ masked.TextCtrl standard masked edit text box
+ masked.ComboBox adds combobox capabilities
+ masked.IpAddrCtrl adds logical input semantics for IP address entry
+ masked.TimeCtrl special subclass handling lots of time formats as values
+ masked.NumCtrl special subclass handling numeric values
+ ================= =========================================================
+
+masked.Ctrl works by looking for a special *controlType*
+parameter in the variable arguments of the control, to determine
+what kind of instance to return.
+controlType can be one of::
+
+ controlTypes.TEXT
+ controlTypes.COMBO
+ controlTypes.IPADDR
+ controlTypes.TIME
+ controlTypes.NUMBER
+
+These constants are also available individually, ie, you can
+use either of the following::
+
+ from wx.lib.masked import Ctrl, COMBO, TEXT, NUMBER, TIME
+ from wx.lib.masked import Ctrl, controlTypes
+
+If not specified as a keyword argument, the default controlType is
+controlTypes.TEXT.
+
+Each of the above classes has its own unique arguments, but Masked.Ctrl
+provides a single "unified" interface for masked controls.
+
+
+"""
+
+from wx.lib.masked import TextCtrl, ComboBox, IpAddrCtrl
+from wx.lib.masked import NumCtrl
+from wx.lib.masked import TimeCtrl
+
+
+# "type" enumeration for class instance factory function
+TEXT = 0
+COMBO = 1
+IPADDR = 2
+TIME = 3
+NUMBER = 4
+
+# for ease of import
+class controlTypes:
+ TEXT = TEXT
+ COMBO = COMBO
+ IPADDR = IPADDR
+ TIME = TIME
+ NUMBER = NUMBER
+
+
+def Ctrl( *args, **kwargs):
+ """
+ Actually a factory function providing a unifying
+ interface for generating masked controls.
+ """
+ if not kwargs.has_key('controlType'):
+ controlType = TEXT
+ else:
+ controlType = kwargs['controlType']
+ del kwargs['controlType']
+
+ if controlType == TEXT:
+ return TextCtrl(*args, **kwargs)
+
+ elif controlType == COMBO:
+ return ComboBox(*args, **kwargs)
+
+ elif controlType == IPADDR:
+ return IpAddrCtrl(*args, **kwargs)
+
+ elif controlType == TIME:
+ return TimeCtrl(*args, **kwargs)
+
+ elif controlType == NUMBER:
+ return NumCtrl(*args, **kwargs)
+
+ else:
+ raise AttributeError(
+ "invalid controlType specified: %s" % repr(controlType))
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/ipaddrctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/ipaddrctrl.py
new file mode 100644
index 0000000..086b60e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/ipaddrctrl.py
@@ -0,0 +1,220 @@
+#----------------------------------------------------------------------------
+# Name: masked.ipaddrctrl.py
+# Authors: Will Sadkin
+# Email: wsadkin@nameconnector.com
+# Created: 02/11/2003
+# Copyright: (c) 2003 by Will Sadkin, 2003
+# RCS-ID: $Id$
+# License: wxWidgets license
+#----------------------------------------------------------------------------
+# NOTE:
+# Masked.IpAddrCtrl is a minor modification to masked.TextCtrl, that is
+# specifically tailored for entering IP addresses. It allows for
+# right-insert fields and provides an accessor to obtain the entered
+# address with extra whitespace removed.
+#
+#----------------------------------------------------------------------------
+"""
+Provides a smart text input control that understands the structure and
+limits of IP Addresses, and allows automatic field navigation as the
+user hits '.' when typing.
+"""
+
+import wx, types, string
+from wx.lib.masked import BaseMaskedTextCtrl
+
+# jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
+# be a good place to implement the 2.3 logger class
+from wx.tools.dbg import Logger
+##dbg = Logger()
+##dbg(enable=0)
+
+class IpAddrCtrlAccessorsMixin:
+ """
+ Defines IpAddrCtrl's list of attributes having their own
+ Get/Set functions, exposing only those that make sense for
+ an IP address control.
+ """
+
+ exposed_basectrl_params = (
+ 'fields',
+ 'retainFieldValidation',
+ 'formatcodes',
+ 'fillChar',
+ 'defaultValue',
+ 'description',
+
+ 'useFixedWidthFont',
+ 'signedForegroundColour',
+ 'emptyBackgroundColour',
+ 'validBackgroundColour',
+ 'invalidBackgroundColour',
+
+ 'emptyInvalid',
+ 'validFunc',
+ 'validRequired',
+ )
+
+ for param in exposed_basectrl_params:
+ propname = param[0].upper() + param[1:]
+ exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
+ exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
+
+ if param.find('Colour') != -1:
+ # add non-british spellings, for backward-compatibility
+ propname.replace('Colour', 'Color')
+
+ exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
+ exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
+
+
+class IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ):
+ """
+ This class is a particular type of MaskedTextCtrl that accepts
+ and understands the semantics of IP addresses, reformats input
+ as you move from field to field, and accepts '.' as a navigation
+ character, so that typing an IP address can be done naturally.
+ """
+
+
+
+ def __init__( self, parent, id=-1, value = '',
+ pos = wx.DefaultPosition,
+ size = wx.DefaultSize,
+ style = wx.TE_PROCESS_TAB,
+ validator = wx.DefaultValidator,
+ name = 'IpAddrCtrl',
+ setupEventHandling = True, ## setup event handling by default
+ **kwargs):
+
+ if not kwargs.has_key('mask'):
+ kwargs['mask'] = mask = "###.###.###.###"
+ if not kwargs.has_key('formatcodes'):
+ kwargs['formatcodes'] = 'F_Sr<>'
+ if not kwargs.has_key('validRegex'):
+ kwargs['validRegex'] = "( \d| \d\d|(1\d\d|2[0-4]\d|25[0-5]))(\.( \d| \d\d|(1\d\d|2[0-4]\d|25[0-5]))){3}"
+
+
+ BaseMaskedTextCtrl.__init__(
+ self, parent, id=id, value = value,
+ pos=pos, size=size,
+ style = style,
+ validator = validator,
+ name = name,
+ setupEventHandling = setupEventHandling,
+ **kwargs)
+
+
+ # set up individual field parameters as well:
+ field_params = {}
+ field_params['validRegex'] = "( | \d| \d |\d | \d\d|\d\d |\d \d|(1\d\d|2[0-4]\d|25[0-5]))"
+
+ # require "valid" string; this prevents entry of any value > 255, but allows
+ # intermediate constructions; overall control validation requires well-formatted value.
+ field_params['formatcodes'] = 'V'
+
+ if field_params:
+ for i in self._field_indices:
+ self.SetFieldParameters(i, **field_params)
+
+ # This makes '.' act like tab:
+ self._AddNavKey('.', handler=self.OnDot)
+ self._AddNavKey('>', handler=self.OnDot) # for "shift-."
+
+
+ def OnDot(self, event):
+ """
+ Defines what action to take when the '.' character is typed in the
+ control. By default, the current field is right-justified, and the
+ cursor is placed in the next field.
+ """
+## dbg('IpAddrCtrl::OnDot', indent=1)
+ pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
+ oldvalue = self.GetValue()
+ edit_start, edit_end, slice = self._FindFieldExtent(pos, getslice=True)
+ if not event.ShiftDown():
+ if pos > edit_start and pos < edit_end:
+ # clip data in field to the right of pos, if adjusting fields
+ # when not at delimeter; (assumption == they hit '.')
+ newvalue = oldvalue[:pos] + ' ' * (edit_end - pos) + oldvalue[edit_end:]
+ self._SetValue(newvalue)
+ self._SetInsertionPoint(pos)
+## dbg(indent=0)
+ return self._OnChangeField(event)
+
+
+
+ def GetAddress(self):
+ """
+ Returns the control value, with any spaces removed.
+ """
+ value = BaseMaskedTextCtrl.GetValue(self)
+ return value.replace(' ','') # remove spaces from the value
+
+
+ def _OnCtrl_S(self, event):
+## dbg("IpAddrCtrl::_OnCtrl_S")
+ if self._demo:
+ print "value:", self.GetAddress()
+ return False
+
+ def SetValue(self, value):
+ """
+ Takes a string value, validates it for a valid IP address,
+ splits it into an array of 4 fields, justifies it
+ appropriately, and inserts it into the control.
+ Invalid values will raise a ValueError exception.
+ """
+## dbg('IpAddrCtrl::SetValue(%s)' % str(value), indent=1)
+ if type(value) not in (types.StringType, types.UnicodeType):
+## dbg(indent=0)
+ raise ValueError('%s must be a string', str(value))
+
+ bValid = True # assume True
+ parts = value.split('.')
+
+ if len(parts) != 4:
+ bValid = False
+ else:
+ for i in range(4):
+ part = parts[i]
+ if not 0 <= len(part) <= 3:
+ bValid = False
+ break
+ elif part.strip(): # non-empty part
+ try:
+ j = string.atoi(part)
+ if not 0 <= j <= 255:
+ bValid = False
+ break
+ else:
+ parts[i] = '%3d' % j
+ except:
+ bValid = False
+ break
+ else:
+ # allow empty sections for SetValue (will result in "invalid" value,
+ # but this may be useful for initializing the control:
+ parts[i] = ' ' # convert empty field to 3-char length
+
+ if not bValid:
+## dbg(indent=0)
+ raise ValueError('value (%s) must be a string of form n.n.n.n where n is empty or in range 0-255' % str(value))
+ else:
+## dbg('parts:', parts)
+ value = string.join(parts, '.')
+ BaseMaskedTextCtrl.SetValue(self, value)
+## dbg(indent=0)
+
+__i=0
+## CHANGELOG:
+## ====================
+## Version 1.2
+## 1. Fixed bugs involving missing imports now that these classes are in
+## their own module.
+## 2. Added doc strings for ePyDoc.
+## 3. Renamed helper functions, vars etc. not intended to be visible in public
+## interface to code.
+##
+## Version 1.1
+## Made ipaddrctrls allow right-insert in subfields, now that insert/cut/paste works better
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/maskededit.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/maskededit.py
new file mode 100644
index 0000000..6eff051
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/maskededit.py
@@ -0,0 +1,7265 @@
+#----------------------------------------------------------------------------
+# Name: maskededit.py
+# Authors: Will Sadkin, Jeff Childers
+# Email: wsadkin@parlancecorp.com, jchilders_98@yahoo.com
+# Created: 02/11/2003
+# Copyright: (c) 2003 by Jeff Childers, Will Sadkin, 2003
+# Portions: (c) 2002 by Will Sadkin, 2002-2007
+# RCS-ID: $Id$
+# License: wxWidgets license
+#----------------------------------------------------------------------------
+# NOTE:
+# MaskedEdit controls are based on a suggestion made on [wxPython-Users] by
+# Jason Hihn, and borrows liberally from Will Sadkin's original masked edit
+# control for time entry, TimeCtrl (which is now rewritten using this
+# control!).
+#
+# MaskedEdit controls do not normally use validators, because they do
+# careful manipulation of the cursor in the text window on each keystroke,
+# and validation is cursor-position specific, so the control intercepts the
+# key codes before the validator would fire. However, validators can be
+# provided to do data transfer to the controls.
+#
+#----------------------------------------------------------------------------
+#
+# This file now contains the bulk of the logic behind all masked controls,
+# the MaskedEditMixin class, the Field class, and the autoformat codes.
+#
+#----------------------------------------------------------------------------
+#
+# 03/30/2004 - Will Sadkin (wsadkin@parlancecorp.com)
+#
+# o Split out TextCtrl, ComboBox and IpAddrCtrl into their own files,
+# o Reorganized code into masked package
+#
+# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for wx namespace. No guarantees. This is one huge file.
+#
+# 12/13/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Missed wx.DateTime stuff earlier.
+#
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o MaskedEditMixin -> MaskedEditMixin
+# o wxMaskedTextCtrl -> maskedTextCtrl
+# o wxMaskedComboBoxSelectEvent -> MaskedComboBoxSelectEvent
+# o wxMaskedComboBox -> MaskedComboBox
+# o wxIpAddrCtrl -> IpAddrCtrl
+# o wxTimeCtrl -> TimeCtrl
+#
+
+__doc__ = """\
+contains MaskedEditMixin class that drives all the other masked controls.
+
+====================
+Masked Edit Overview
+====================
+
+masked.TextCtrl:
+ is a sublassed text control that can carefully control the user's input
+ based on a mask string you provide.
+
+ General usage example::
+
+ control = masked.TextCtrl( win, -1, '', mask = '(###) ###-####')
+
+ The example above will create a text control that allows only numbers to be
+ entered and then only in the positions indicated in the mask by the # sign.
+
+masked.ComboBox:
+ is a similar subclass of wxComboBox that allows the same sort of masking,
+ but also can do auto-complete of values, and can require the value typed
+ to be in the list of choices to be colored appropriately.
+
+masked.Ctrl:
+ is actually a factory function for several types of masked edit controls:
+
+ ================= ==================================================
+ masked.TextCtrl standard masked edit text box
+ masked.ComboBox adds combobox capabilities
+ masked.IpAddrCtrl adds special semantics for IP address entry
+ masked.TimeCtrl special subclass handling lots of types as values
+ masked.NumCtrl special subclass handling numeric values
+ ================= ==================================================
+
+ It works by looking for a *controlType* parameter in the keyword
+ arguments of the control, to determine what kind of instance to return.
+ If not specified as a keyword argument, the default control type returned
+ will be masked.TextCtrl.
+
+ Each of the above classes has its own set of arguments, but masked.Ctrl
+ provides a single "unified" interface for masked controls.
+
+What follows is a description of how to configure the generic masked.TextCtrl
+and masked.ComboBox; masked.NumCtrl and masked.TimeCtrl have their own demo
+pages and interface descriptions.
+
+=========================
+
+Initialization Parameters
+-------------------------
+mask
+ Allowed mask characters and function:
+
+ ========= ==========================================================
+ Character Function
+ ========= ==========================================================
+ # Allow numeric only (0-9)
+ N Allow letters and numbers (0-9)
+ A Allow uppercase letters only
+ a Allow lowercase letters only
+ C Allow any letter, upper or lower
+ X Allow string.letters, string.punctuation, string.digits
+ & Allow string.punctuation only (doesn't include all unicode symbols)
+ \* Allow any visible character
+ | explicit field boundary (takes no space in the control; allows mix
+ of adjacent mask characters to be treated as separate fields,
+ eg: '&|###' means "field 0 = '&', field 1 = '###'", but there's
+ no fixed characters in between.
+ ========= ==========================================================
+
+
+ These controls define these sets of characters using string.letters,
+ string.uppercase, etc. These sets are affected by the system locale
+ setting, so in order to have the masked controls accept characters
+ that are specific to your users' language, your application should
+ set the locale.
+ For example, to allow international characters to be used in the
+ above masks, you can place the following in your code as part of
+ your application's initialization code::
+
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+
+ The controls now also support (by popular demand) all "visible" characters,
+ by use of the * mask character, including unicode characters above
+ the standard ANSI keycode range.
+ Note: As string.punctuation doesn't typically include all unicode
+ symbols, you will have to use includechars to get some of these into
+ otherwise restricted positions in your control, such as those specified
+ with &.
+
+ Using these mask characters, a variety of template masks can be built. See
+ the demo for some other common examples include date+time, social security
+ number, etc. If any of these characters are needed as template rather
+ than mask characters, they can be escaped with \, ie. \N means "literal N".
+ (use \\ for literal backslash, as in: r'CCC\\NNN'.)
+
+
+ .. note::
+
+ Masks containing only # characters and one optional decimal point
+ character are handled specially, as "numeric" controls. Such
+ controls have special handling for typing the '-' key, handling
+ the "decimal point" character as truncating the integer portion,
+ optionally allowing grouping characters and so forth.
+ There are several parameters and format codes that only make sense
+ when combined with such masks, eg. groupChar, decimalChar, and so
+ forth (see below). These allow you to construct reasonable
+ numeric entry controls.
+
+
+ .. note::
+
+ Changing the mask for a control deletes any previous field classes
+ (and any associated validation or formatting constraints) for them.
+
+
+useFixedWidthFont
+ By default, masked edit controls use a fixed width font, so that
+ the mask characters are fixed within the control, regardless of
+ subsequent modifications to the value. Set to False if having
+ the control font be the same as other controls is required. (This is
+ a control-level parameter.)
+
+ .. versionchanged:: 2.9.5
+ The default is changed to False for numctrl only
+
+defaultEncoding
+ (Applies to unicode systems only) By default, the default unicode encoding
+ used is latin1, or iso-8859-1. If necessary, you can set this control-level
+ parameter to govern the codec used to decode your keyboard inputs.
+ (This is a control-level parameter.)
+
+formatcodes
+ These other properties can be passed to the class when instantiating it:
+ Formatcodes are specified as a string of single character formatting
+ codes that modify behavior of the control::
+
+ _ Allow spaces
+ ! Force upper
+ ^ Force lower
+ R Right-align field(s)
+ r Right-insert in field(s) (implies R)
+ < Stay in field until explicit navigation out of it
+
+ > Allow insert/delete within partially filled fields (as
+ opposed to the default "overwrite" mode for fixed-width
+ masked edit controls.) This allows single-field controls
+ or each field within a multi-field control to optionally
+ behave more like standard text controls.
+ (See EMAIL or phone number autoformat examples.)
+
+ *Note: This also governs whether backspace/delete operations
+ shift contents of field to right of cursor, or just blank the
+ erased section.
+
+ Also, when combined with 'r', this indicates that the field
+ or control allows right insert anywhere within the current
+ non-empty value in the field. (Otherwise right-insert behavior
+ is only performed to when the entire right-insertable field is
+ selected or the cursor is at the right edge of the field.*
+
+
+ , Allow grouping character in integer fields of numeric controls
+ and auto-group/regroup digits (if the result fits) when leaving
+ such a field. (If specified, .SetValue() will attempt to
+ auto-group as well.)
+ ',' is also the default grouping character. To change the
+ grouping character and/or decimal character, use the groupChar
+ and decimalChar parameters, respectively.
+ Note: typing the "decimal point" character in such fields will
+ clip the value to that left of the cursor for integer
+ fields of controls with "integer" or "floating point" masks.
+ If the ',' format code is specified, this will also cause the
+ resulting digits to be regrouped properly, using the current
+ grouping character.
+ - Prepend and reserve leading space for sign to mask and allow
+ signed values (negative #s shown in red by default.) Can be
+ used with argument useParensForNegatives (see below.)
+ 0 integer fields get leading zeros
+ D Date[/time] field
+ T Time field
+ F Auto-Fit: the control calulates its size from
+ the length of the template mask
+ V validate entered chars against validRegex before allowing them
+ to be entered vs. being allowed by basic mask and then having
+ the resulting value just colored as invalid.
+ (See USSTATE autoformat demo for how this can be used.)
+ S select entire field when navigating to new field
+
+fillChar
+
+defaultValue
+ These controls have two options for the initial state of the control.
+ If a blank control with just the non-editable characters showing
+ is desired, simply leave the constructor variable fillChar as its
+ default (' '). If you want some other character there, simply
+ change the fillChar to that value. Note: changing the control's fillChar
+ will implicitly reset all of the fields' fillChars to this value.
+
+ If you need different default characters in each mask position,
+ you can specify a defaultValue parameter in the constructor, or
+ set them for each field individually.
+ This value must satisfy the non-editable characters of the mask,
+ but need not conform to the replaceable characters.
+
+groupChar
+
+decimalChar
+ These parameters govern what character is used to group numbers
+ and is used to indicate the decimal point for numeric format controls.
+ The default groupChar is ',', the default decimalChar is '.'
+ By changing these, you can customize the presentation of numbers
+ for your location.
+
+ Eg::
+
+ formatcodes = ',', groupChar='\'' allows 12'345.34
+ formatcodes = ',', groupChar='.', decimalChar=',' allows 12.345,34
+
+ (These are control-level parameters.)
+
+shiftDecimalChar
+ The default "shiftDecimalChar" (used for "backwards-tabbing" until
+ shift-tab is fixed in wxPython) is '>' (for QUERTY keyboards.) for
+ other keyboards, you may want to customize this, eg '?' for shift ',' on
+ AZERTY keyboards, ':' or ';' for other European keyboards, etc.
+ (This is a control-level parameter.)
+
+useParensForNegatives=False
+ This option can be used with signed numeric format controls to
+ indicate signs via () rather than '-'.
+ (This is a control-level parameter.)
+
+autoSelect=False
+ This option can be used to have a field or the control try to
+ auto-complete on each keystroke if choices have been specified.
+
+autoCompleteKeycodes=[]
+ By default, DownArrow, PageUp and PageDown will auto-complete a
+ partially entered field. Shift-DownArrow, Shift-UpArrow, PageUp
+ and PageDown will also auto-complete, but if the field already
+ contains a matched value, these keys will cycle through the list
+ of choices forward or backward as appropriate. Shift-Up and
+ Shift-Down also take you to the next/previous field after any
+ auto-complete action.
+
+ Additional auto-complete keys can be specified via this parameter.
+ Any keys so specified will act like PageDown.
+ (This is a control-level parameter.)
+
+
+
+Validating User Input
+=====================
+There are a variety of initialization parameters that are used to validate
+user input. These parameters can apply to the control as a whole, and/or
+to individual fields:
+
+======================== ==================================================================
+excludeChars A string of characters to exclude even if otherwise allowed
+includeChars A string of characters to allow even if otherwise disallowed
+validRegex Use a regular expression to validate the contents of the text box
+validRange Pass a rangeas list (low,high) to limit numeric fields/values
+choices A list of strings that are allowed choices for the control.
+choiceRequired value must be member of choices list
+compareNoCase Perform case-insensitive matching when validating against list. *Note: for masked.ComboBox, this defaults to True.*
+emptyInvalid Boolean indicating whether an empty value should be considered invalid
+validFunc A function to call of the form: bool = func(candidate_value) which will return True if the candidate_value satisfies some external criteria for the control in addition to the the other validation, or False if not. (This validation is applied last in the chain of validations.)
+validRequired Boolean indicating whether or not keys that are allowed by the mask, but result in an invalid value are allowed to be entered into the control. Setting this to True implies that a valid default value is set for the control.
+retainFieldValidation False by default; if True, this allows individual fields to retain their own validation constraints independently of any subsequent changes to the control's overall parameters. (This is a control-level parameter.)
+validator Validators are not normally needed for masked controls, because of the nature of the validation and control of input. However, you can supply one to provide data transfer routines for the controls.
+raiseOnInvalidPaste False by default; normally a bad paste simply is ignored with a bell; if True, this will cause a ValueError exception to be thrown, with the .value attribute of the exception containing the bad value.
+stopFieldChangeIfInvalid False by default; tries to prevent navigation out of a field if its current value is invalid. Can be used to create a hybrid of validation settings, allowing intermediate invalid values in a field without sacrificing ability to limit values as with validRequired. NOTE: It is possible to end up with an invalid value when using this option if focus is switched to some other control via mousing. To avoid this, consider deriving a class that defines _LostFocus() function that returns the control to a valid value when the focus shifts. (AFAICT, The change in focus is unpreventable.)
+======================== ==================================================================
+
+
+Coloring Behavior
+=================
+
+The following parameters have been provided to allow you to change the default
+coloring behavior of the control. These can be set at construction, or via
+the .SetCtrlParameters() function. Pass a color as string e.g. 'Yellow':
+
+======================== =======================================================================
+emptyBackgroundColour Control Background color when identified as empty. Default=White
+invalidBackgroundColour Control Background color when identified as Not valid. Default=Yellow
+validBackgroundColour Control Background color when identified as Valid. Default=white
+======================== =======================================================================
+
+
+The following parameters control the default foreground color coloring behavior of the
+control. Pass a color as string e.g. 'Yellow':
+
+======================== ======================================================================
+foregroundColour Control foreground color when value is not negative. Default=Black
+signedForegroundColour Control foreground color when value is negative. Default=Red
+======================== ======================================================================
+
+
+Fields
+======
+
+Each part of the mask that allows user input is considered a field. The fields
+are represented by their own class instances. You can specify field-specific
+constraints by constructing or accessing the field instances for the control
+and then specifying those constraints via parameters.
+
+fields
+ This parameter allows you to specify Field instances containing
+ constraints for the individual fields of a control, eg: local
+ choice lists, validation rules, functions, regexps, etc.
+ It can be either an ordered list or a dictionary. If a list,
+ the fields will be applied as fields 0, 1, 2, etc.
+ If a dictionary, it should be keyed by field index.
+ the values should be a instances of maskededit.Field.
+
+ Any field not represented by the list or dictionary will be
+ implicitly created by the control.
+
+ Eg::
+
+ fields = [ Field(formatcodes='_r'), Field('choices=['a', 'b', 'c']) ]
+
+ Or::
+
+ fields = {
+ 1: ( Field(formatcodes='_R', choices=['a', 'b', 'c']),
+ 3: ( Field(choices=['01', '02', '03'], choiceRequired=True)
+ }
+
+ The following parameters are available for individual fields, with the
+ same semantics as for the whole control but applied to the field in question:
+
+ ============== =============================================================================
+ fillChar if set for a field, it will override the control's fillChar for that field
+ groupChar if set for a field, it will override the control's default
+ defaultValue sets field-specific default value; overrides any default from control
+ compareNoCase overrides control's settings
+ emptyInvalid determines whether field is required to be filled at all times
+ validRequired if set, requires field to contain valid value
+ ============== =============================================================================
+
+ If any of the above parameters are subsequently specified for the control as a
+ whole, that new value will be propagated to each field, unless the
+ retainFieldValidation control-level parameter is set.
+
+ ============== ==============================
+ formatcodes Augments control's settings
+ excludeChars ' ' '
+ includeChars ' ' '
+ validRegex ' ' '
+ validRange ' ' '
+ choices ' ' '
+ choiceRequired ' ' '
+ validFunc ' ' '
+ ============== ==============================
+
+
+
+Control Class Functions
+=======================
+
+.GetPlainValue(value=None)
+ Returns the value specified (or the control's text value
+ not specified) without the formatting text.
+ In the example above, might return phone no='3522640075',
+ whereas control.GetValue() would return '(352) 264-0075'
+.ClearValue()
+ Returns the control's value to its default, and places the
+ cursor at the beginning of the control.
+.SetValue()
+ Does "smart replacement" of passed value into the control, as does
+ the .Paste() method. As with other text entry controls, the
+ .SetValue() text replacement begins at left-edge of the control,
+ with missing mask characters inserted as appropriate.
+ .SetValue will also adjust integer, float or date mask entry values,
+ adding commas, auto-completing years, etc. as appropriate.
+ For "right-aligned" numeric controls, it will also now automatically
+ right-adjust any value whose length is less than the width of the
+ control before attempting to set the value.
+ If a value does not follow the format of the control's mask, or will
+ not fit into the control, a ValueError exception will be raised.
+
+ Eg::
+
+ mask = '(###) ###-####'
+ .SetValue('1234567890') => '(123) 456-7890'
+ .SetValue('(123)4567890') => '(123) 456-7890'
+ .SetValue('(123)456-7890') => '(123) 456-7890'
+ .SetValue('123/4567-890') => illegal paste; ValueError
+
+ mask = '#{6}.#{2}', formatcodes = '_,-',
+ .SetValue('111') => ' 111 . '
+ .SetValue(' %9.2f' % -111.12345 ) => ' -111.12'
+ .SetValue(' %9.2f' % 1234.00 ) => ' 1,234.00'
+ .SetValue(' %9.2f' % -1234567.12345 ) => insufficient room; ValueError
+
+ mask = '#{6}.#{2}', formatcodes = '_,-R' # will right-adjust value for right-aligned control
+ .SetValue('111') => padded value misalignment ValueError: " 111" will not fit
+ .SetValue('%.2f' % 111 ) => ' 111.00'
+ .SetValue('%.2f' % -111.12345 ) => ' -111.12'
+
+
+.IsValid(value=None)
+ Returns True if the value specified (or the value of the control
+ if not specified) passes validation tests
+.IsEmpty(value=None)
+ Returns True if the value specified (or the value of the control
+ if not specified) is equal to an "empty value," ie. all
+ editable characters == the fillChar for their respective fields.
+.IsDefault(value=None)
+ Returns True if the value specified (or the value of the control
+ if not specified) is equal to the initial value of the control.
+
+.Refresh()
+ Recolors the control as appropriate to its current settings.
+
+.SetCtrlParameters(\*\*kwargs)
+ This function allows you to set up and/or change the control parameters
+ after construction; it takes a list of key/value pairs as arguments,
+ where the keys can be any of the mask-specific parameters in the constructor.
+
+ Eg::
+
+ ctl = masked.TextCtrl( self, -1 )
+ ctl.SetCtrlParameters( mask='###-####',
+ defaultValue='555-1212',
+ formatcodes='F')
+
+.GetCtrlParameter(parametername)
+ This function allows you to retrieve the current value of a parameter
+ from the control.
+
+ *Note:* Each of the control parameters can also be set using its
+ own Set and Get function. These functions follow a regular form:
+ All of the parameter names start with lower case; for their
+ corresponding Set/Get function, the parameter name is capitalized.
+
+ Eg::
+
+ ctl.SetMask('###-####')
+ ctl.SetDefaultValue('555-1212')
+ ctl.GetChoiceRequired()
+ ctl.GetFormatcodes()
+
+ *Note:* After any change in parameters, the choices for the
+ control are reevaluated to ensure that they are still legal. If you
+ have large choice lists, it is therefore more efficient to set parameters
+ before setting the choices available.
+
+.SetFieldParameters(field_index, \*\*kwargs)
+ This function allows you to specify change individual field
+ parameters after construction. (Indices are 0-based.)
+
+.GetFieldParameter(field_index, parametername)
+ Allows the retrieval of field parameters after construction
+
+
+The control detects certain common constructions. In order to use the signed feature
+(negative numbers and coloring), the mask has to be all numbers with optionally one
+decimal point. Without a decimal (e.g. '######', the control will treat it as an integer
+value. With a decimal (e.g. '###.##'), the control will act as a floating point control
+(i.e. press decimal to 'tab' to the decimal position). Pressing decimal in the
+integer control truncates the value. However, for a true numeric control,
+masked.NumCtrl provides all this, and true numeric input/output support as well.
+
+
+Check your controls by calling each control's .IsValid() function and the
+.IsEmpty() function to determine which controls have been a) filled in and
+b) filled in properly.
+
+
+Regular expression validations can be used flexibly and creatively.
+Take a look at the demo; the zip-code validation succeeds as long as the
+first five numerals are entered. the last four are optional, but if
+any are entered, there must be 4 to be valid.
+
+masked.Ctrl Configuration
+=========================
+masked.Ctrl works by looking for a special *controlType*
+parameter in the variable arguments of the control, to determine
+what kind of instance to return.
+controlType can be one of::
+
+ controlTypes.TEXT
+ controlTypes.COMBO
+ controlTypes.IPADDR
+ controlTypes.TIME
+ controlTypes.NUMBER
+
+These constants are also available individually, ie, you can
+use either of the following::
+
+ from wx.lib.masked import MaskedCtrl, controlTypes
+ from wx.lib.masked import MaskedCtrl, COMBO, TEXT, NUMBER, IPADDR
+
+If not specified as a keyword argument, the default controlType is
+controlTypes.TEXT.
+
+"""
+
+"""
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+DEVELOPER COMMENTS:
+
+Naming Conventions
+------------------
+ All methods of the Mixin that are not meant to be exposed to the external
+ interface are prefaced with '_'. Those functions that are primarily
+ intended to be internal subroutines subsequently start with a lower-case
+ letter; those that are primarily intended to be used and/or overridden
+ by derived subclasses start with a capital letter.
+
+ The following methods must be used and/or defined when deriving a control
+ from MaskedEditMixin. NOTE: if deriving from a *masked edit* control
+ (eg. class IpAddrCtrl(masked.TextCtrl) ), then this is NOT necessary,
+ as it's already been done for you in the base class.
+
+ ._SetInitialValue()
+ This function must be called after the associated base
+ control has been initialized in the subclass __init__
+ function. It sets the initial value of the control,
+ either to the value specified if non-empty, the
+ default value if specified, or the "template" for
+ the empty control as necessary. It will also set/reset
+ the font if necessary and apply formatting to the
+ control at this time.
+
+ ._GetSelection()
+ REQUIRED
+ Each class derived from MaskedEditMixin must define
+ the function for getting the start and end of the
+ current text selection. The reason for this is
+ that not all controls have the same function name for
+ doing this; eg. wx.TextCtrl uses .GetSelection(),
+ whereas we had to write a .GetMark() function for
+ wxComboBox, because .GetSelection() for the control
+ gets the currently selected list item from the combo
+ box, and the control doesn't (yet) natively provide
+ a means of determining the text selection.
+ ._SetSelection()
+ REQUIRED
+ Similarly to _GetSelection, each class derived from
+ MaskedEditMixin must define the function for setting
+ the start and end of the current text selection.
+ (eg. .SetSelection() for masked.TextCtrl, and .SetMark() for
+ masked.ComboBox.
+
+ ._GetInsertionPoint()
+ ._SetInsertionPoint()
+ REQUIRED
+ For consistency, and because the mixin shouldn't rely
+ on fixed names for any manipulations it does of any of
+ the base controls, we require each class derived from
+ MaskedEditMixin to define these functions as well.
+
+ ._GetValue()
+ ._SetValue() REQUIRED
+ Each class derived from MaskedEditMixin must define
+ the functions used to get and set the raw value of the
+ control.
+ This is necessary so that recursion doesn't take place
+ when setting the value, and so that the mixin can
+ call the appropriate function after doing all its
+ validation and manipulation without knowing what kind
+ of base control it was mixed in with. To handle undo
+ functionality, the ._SetValue() must record the current
+ selection prior to setting the value.
+
+ .Cut()
+ .Paste()
+ .Undo()
+ .SetValue() REQUIRED
+ Each class derived from MaskedEditMixin must redefine
+ these functions to call the _Cut(), _Paste(), _Undo()
+ and _SetValue() methods, respectively for the control,
+ so as to prevent programmatic corruption of the control's
+ value. This must be done in each derivation, as the
+ mixin cannot itself override a member of a sibling class.
+
+ ._Refresh() REQUIRED
+ Each class derived from MaskedEditMixin must define
+ the function used to refresh the base control.
+
+ .Refresh() REQUIRED
+ Each class derived from MaskedEditMixin must redefine
+ this function so that it checks the validity of the
+ control (via self._CheckValid) and then refreshes
+ control using the base class method.
+
+ ._IsEditable() REQUIRED
+ Each class derived from MaskedEditMixin must define
+ the function used to determine if the base control is
+ editable or not. (For masked.ComboBox, this has to
+ be done with code, rather than specifying the proper
+ function in the base control, as there isn't one...)
+ ._CalcSize() REQUIRED
+ Each class derived from MaskedEditMixin must define
+ the function used to determine how wide the control
+ should be given the mask. (The mixin function
+ ._calcSize() provides a baseline estimate.)
+
+
+Event Handling
+--------------
+ Event handlers are "chained", and MaskedEditMixin usually
+ swallows most of the events it sees, thereby preventing any other
+ handlers from firing in the chain. It is therefore required that
+ each class derivation using the mixin to have an option to hook up
+ the event handlers itself or forego this operation and let a
+ subclass of the masked control do so. For this reason, each
+ subclass should probably include the following code::
+
+ if setupEventHandling:
+ ## Setup event handlers
+ EVT_SET_FOCUS( self, self._OnFocus ) ## defeat automatic full selection
+ EVT_KILL_FOCUS( self, self._OnKillFocus ) ## run internal validator
+ EVT_LEFT_DCLICK(self, self._OnDoubleClick) ## select field under cursor on dclick
+ EVT_RIGHT_UP(self, self._OnContextMenu ) ## bring up an appropriate context menu
+ EVT_KEY_DOWN( self, self._OnKeyDown ) ## capture control events not normally seen, eg ctrl-tab.
+ EVT_CHAR( self, self._OnChar ) ## handle each keypress
+ EVT_TEXT( self, self.GetId(), self._OnTextChange ) ## color control appropriately & keep
+ ## track of previous value for undo
+
+ where setupEventHandling is an argument to its constructor.
+
+ These 5 handlers must be "wired up" for the masked edit
+ controls to provide default behavior. (The setupEventHandling
+ is an argument to masked.TextCtrl and masked.ComboBox, so
+ that controls derived from *them* may replace one of these
+ handlers if they so choose.)
+
+ If your derived control wants to preprocess events before
+ taking action, it should then set up the event handling itself,
+ so it can be first in the event handler chain.
+
+
+ The following routines are available to facilitate changing
+ the default behavior of masked edit controls:
+
+ ._SetKeycodeHandler(keycode, func)
+ ._SetKeyHandler(char, func)
+ Use to replace default handling for any given keycode.
+ func should take the key event as argument and return
+ False if no further action is required to handle the
+ key. Eg:
+ self._SetKeycodeHandler(WXK_UP, self.IncrementValue)
+ self._SetKeyHandler('-', self._OnChangeSign)
+
+ (Setting a func of None removes any keyhandler for the given key.)
+
+ "Navigation" keys are assumed to change the cursor position, and
+ therefore don't cause automatic motion of the cursor as insertable
+ characters do.
+
+ ._AddNavKeycode(keycode, handler=None)
+ ._AddNavKey(char, handler=None)
+ Allows controls to specify other keys (and optional handlers)
+ to be treated as navigational characters. (eg. '.' in IpAddrCtrl)
+
+ ._GetNavKeycodes() Returns the current list of navigational keycodes.
+
+ ._SetNavKeycodes(key_func_tuples)
+ Allows replacement of the current list of keycode
+ processed as navigation keys, and bind associated
+ optional keyhandlers. argument is a list of key/handler
+ tuples. Passing a value of None for the handler in a
+ given tuple indicates that default processing for the key
+ is desired.
+
+ ._FindField(pos) Returns the Field object associated with this position
+ in the control.
+
+ ._FindFieldExtent(pos, getslice=False, value=None)
+ Returns edit_start, edit_end of the field corresponding
+ to the specified position within the control, and
+ optionally also returns the current contents of that field.
+ If value is specified, it will retrieve the slice the corresponding
+ slice from that value, rather than the current value of the
+ control.
+
+ ._AdjustField(pos)
+ This is, the function that gets called for a given position
+ whenever the cursor is adjusted to leave a given field.
+ By default, it adjusts the year in date fields if mask is a date,
+ It can be overridden by a derived class to
+ adjust the value of the control at that time.
+ (eg. IpAddrCtrl reformats the address in this way.)
+
+ ._Change() Called by internal EVT_TEXT handler. Return False to force
+ skip of the normal class change event.
+ ._Keypress(key) Called by internal EVT_CHAR handler. Return False to force
+ skip of the normal class keypress event.
+ ._LostFocus() Called by internal EVT_KILL_FOCUS handler
+
+ ._OnKeyDown(event)
+ This is the default EVT_KEY_DOWN routine; it just checks for
+ "navigation keys", and if event.ControlDown(), it fires the
+ mixin's _OnChar() routine, as such events are not always seen
+ by the "cooked" EVT_CHAR routine.
+
+ ._OnChar(event) This is the main EVT_CHAR handler for the
+ MaskedEditMixin.
+
+ The following routines are used to handle standard actions
+ for control keys:
+ _OnArrow(event) used for arrow navigation events
+ _OnCtrl_A(event) 'select all'
+ _OnCtrl_C(event) 'copy' (uses base control function, as copy is non-destructive)
+ _OnCtrl_S(event) 'save' (does nothing)
+ _OnCtrl_V(event) 'paste' - calls _Paste() method, to do smart paste
+ _OnCtrl_X(event) 'cut' - calls _Cut() method, to "erase" selection
+ _OnCtrl_Z(event) 'undo' - resets value to previous value (if any)
+
+ _OnChangeField(event) primarily used for tab events, but can be
+ used for other keys (eg. '.' in IpAddrCtrl)
+
+ _OnErase(event) used for backspace and delete
+ _OnHome(event)
+ _OnEnd(event)
+
+ The following routine provides a hook back to any class derivations, so that
+ they can react to parameter changes before any value is set/reset as a result of
+ those changes. (eg. masked.ComboBox needs to detect when the choices list is
+ modified, either implicitly or explicitly, so it can reset the base control
+ to have the appropriate choice list *before* the initial value is reset to match.)
+
+ _OnCtrlParametersChanged()
+
+Accessor Functions
+------------------
+ For convenience, each class derived from MaskedEditMixin should
+ define an accessors mixin, so that it exposes only those parameters
+ that make sense for the derivation. This is done with an intermediate
+ level of inheritance, ie:
+
+ class BaseMaskedTextCtrl( TextCtrl, MaskedEditMixin ):
+
+ class TextCtrl( BaseMaskedTextCtrl, MaskedEditAccessorsMixin ):
+ class ComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
+ class NumCtrl( BaseMaskedTextCtrl, MaskedNumCtrlAccessorsMixin ):
+ class IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ):
+ class TimeCtrl( BaseMaskedTextCtrl, TimeCtrlAccessorsMixin ):
+
+ etc.
+
+ Each accessors mixin defines Get/Set functions for the base class parameters
+ that are appropriate for that derivation.
+ This allows the base classes to be "more generic," exposing the widest
+ set of options, while not requiring derived classes to be so general.
+"""
+
+import copy
+import difflib
+import re
+import string
+import types
+
+import wx
+
+# jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
+# be a good place to implement the 2.3 logger class
+from wx.tools.dbg import Logger
+
+##dbg = Logger()
+##dbg(enable=1)
+
+## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+## Constants for identifying control keys and classes of keys:
+
+WXK_CTRL_A = (ord('A')+1) - ord('A') ## These keys are not already defined in wx
+WXK_CTRL_C = (ord('C')+1) - ord('A')
+WXK_CTRL_S = (ord('S')+1) - ord('A')
+WXK_CTRL_V = (ord('V')+1) - ord('A')
+WXK_CTRL_X = (ord('X')+1) - ord('A')
+WXK_CTRL_Z = (ord('Z')+1) - ord('A')
+
+nav = (
+ wx.WXK_BACK, wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_UP, wx.WXK_DOWN, wx.WXK_TAB,
+ wx.WXK_HOME, wx.WXK_END, wx.WXK_RETURN, wx.WXK_PRIOR, wx.WXK_NEXT,
+ wx.WXK_NUMPAD_LEFT, wx.WXK_NUMPAD_RIGHT, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_DOWN,
+ wx.WXK_NUMPAD_HOME, wx.WXK_NUMPAD_END, wx.WXK_NUMPAD_ENTER, wx.WXK_NUMPAD_PRIOR, wx.WXK_NUMPAD_NEXT
+ )
+
+control = (
+ wx.WXK_BACK, wx.WXK_DELETE, wx.WXK_INSERT,
+ wx.WXK_NUMPAD_DELETE, wx.WXK_NUMPAD_INSERT,
+ WXK_CTRL_A, WXK_CTRL_C, WXK_CTRL_S, WXK_CTRL_V,
+ WXK_CTRL_X, WXK_CTRL_Z
+ )
+
+# Because unicode can go over the ansi character range, we need to explicitly test
+# for all non-visible keystrokes, rather than just assuming a particular range for
+# visible characters:
+wx_control_keycodes = range(32) + list(nav) + list(control) + [
+ wx.WXK_START, wx.WXK_LBUTTON, wx.WXK_RBUTTON, wx.WXK_CANCEL, wx.WXK_MBUTTON,
+ wx.WXK_CLEAR, wx.WXK_SHIFT, wx.WXK_CONTROL, wx.WXK_MENU, wx.WXK_PAUSE,
+ wx.WXK_CAPITAL, wx.WXK_SELECT, wx.WXK_PRINT, wx.WXK_EXECUTE, wx.WXK_SNAPSHOT,
+ wx.WXK_HELP, wx.WXK_NUMPAD0, wx.WXK_NUMPAD1, wx.WXK_NUMPAD2, wx.WXK_NUMPAD3,
+ wx.WXK_NUMPAD4, wx.WXK_NUMPAD5, wx.WXK_NUMPAD6, wx.WXK_NUMPAD7, wx.WXK_NUMPAD8,
+ wx.WXK_NUMPAD9, wx.WXK_MULTIPLY, wx.WXK_ADD, wx.WXK_SEPARATOR, wx.WXK_SUBTRACT,
+ wx.WXK_DECIMAL, wx.WXK_DIVIDE, wx.WXK_F1, wx.WXK_F2, wx.WXK_F3, wx.WXK_F4,
+ wx.WXK_F5, wx.WXK_F6, wx.WXK_F7, wx.WXK_F8, wx.WXK_F9, wx.WXK_F10, wx.WXK_F11,
+ wx.WXK_F12, wx.WXK_F13, wx.WXK_F14, wx.WXK_F15, wx.WXK_F16, wx.WXK_F17,
+ wx.WXK_F18, wx.WXK_F19, wx.WXK_F20, wx.WXK_F21, wx.WXK_F22, wx.WXK_F23,
+ wx.WXK_F24, wx.WXK_NUMLOCK, wx.WXK_SCROLL, wx.WXK_PAGEUP, wx.WXK_PAGEDOWN,
+ wx.WXK_NUMPAD_SPACE, wx.WXK_NUMPAD_TAB, wx.WXK_NUMPAD_ENTER, wx.WXK_NUMPAD_F1,
+ wx.WXK_NUMPAD_F2, wx.WXK_NUMPAD_F3, wx.WXK_NUMPAD_F4, wx.WXK_NUMPAD_HOME,
+ wx.WXK_NUMPAD_LEFT, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_RIGHT, wx.WXK_NUMPAD_DOWN,
+ wx.WXK_NUMPAD_PRIOR, wx.WXK_NUMPAD_PAGEUP, wx.WXK_NUMPAD_NEXT, wx.WXK_NUMPAD_PAGEDOWN,
+ wx.WXK_NUMPAD_END, wx.WXK_NUMPAD_BEGIN, wx.WXK_NUMPAD_INSERT, wx.WXK_NUMPAD_DELETE,
+ wx.WXK_NUMPAD_EQUAL, wx.WXK_NUMPAD_MULTIPLY, wx.WXK_NUMPAD_ADD, wx.WXK_NUMPAD_SEPARATOR,
+ wx.WXK_NUMPAD_SUBTRACT, wx.WXK_NUMPAD_DECIMAL, wx.WXK_NUMPAD_DIVIDE, wx.WXK_WINDOWS_LEFT,
+ wx.WXK_WINDOWS_RIGHT, wx.WXK_WINDOWS_MENU, wx.WXK_COMMAND,
+ # Hardware-specific buttons
+ wx.WXK_SPECIAL1, wx.WXK_SPECIAL2, wx.WXK_SPECIAL3, wx.WXK_SPECIAL4, wx.WXK_SPECIAL5,
+ wx.WXK_SPECIAL6, wx.WXK_SPECIAL7, wx.WXK_SPECIAL8, wx.WXK_SPECIAL9, wx.WXK_SPECIAL10,
+ wx.WXK_SPECIAL11, wx.WXK_SPECIAL12, wx.WXK_SPECIAL13, wx.WXK_SPECIAL14, wx.WXK_SPECIAL15,
+ wx.WXK_SPECIAL16, wx.WXK_SPECIAL17, wx.WXK_SPECIAL18, wx.WXK_SPECIAL19, wx.WXK_SPECIAL20
+ ]
+
+
+## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+## Constants for masking. This is where mask characters
+## are defined.
+## maskchars used to identify valid mask characters from all others
+## # - allow numeric 0-9 only
+## A - allow uppercase only. Combine with forceupper to force lowercase to upper
+## a - allow lowercase only. Combine with forcelower to force upper to lowercase
+## C - allow any letter, upper or lower
+## X - allow string.letters, string.punctuation, string.digits
+## & - allow string.punctuation only (doesn't include all unicode symbols)
+## * - allow any visible character
+
+## Note: locale settings affect what "uppercase", lowercase, etc comprise.
+## Note: '|' is not a maskchar, in that it is a mask processing directive, and so
+## does not appear here.
+##
+maskchars = ("#","A","a","X","C","N",'*','&')
+ansichars = ""
+for i in xrange(32, 256):
+ ansichars += chr(i)
+
+months = '(01|02|03|04|05|06|07|08|09|10|11|12)'
+charmonths = '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)'
+charmonths_dict = {'jan': 1, 'feb': 2, 'mar': 3, 'apr': 4, 'may': 5, 'jun': 6,
+ 'jul': 7, 'aug': 8, 'sep': 9, 'oct': 10, 'nov': 11, 'dec': 12}
+
+days = '(01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)'
+hours = '(0\d| \d|1[012])'
+milhours = '(00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23)'
+minutes = """(00|01|02|03|04|05|06|07|08|09|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)"""
+seconds = minutes
+am_pm_exclude = 'BCDEFGHIJKLMNOQRSTUVWXYZ\x8a\x8c\x8e\x9f\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd8\xd9\xda\xdb\xdc\xdd\xde'
+
+states = "AL,AK,AZ,AR,CA,CO,CT,DE,DC,FL,GA,GU,HI,ID,IL,IN,IA,KS,KY,LA,MA,ME,MD,MI,MN,MS,MO,MT,NE,NV,NH,NJ,NM,NY,NC,ND,OH,OK,OR,PA,PR,RI,SC,SD,TN,TX,UT,VA,VT,VI,WA,WV,WI,WY".split(',')
+
+state_names = ['Alabama','Alaska','Arizona','Arkansas',
+ 'California','Colorado','Connecticut',
+ 'Delaware','District of Columbia',
+ 'Florida','Georgia','Hawaii',
+ 'Idaho','Illinois','Indiana','Iowa',
+ 'Kansas','Kentucky','Louisiana',
+ 'Maine','Maryland','Massachusetts','Michigan',
+ 'Minnesota','Mississippi','Missouri','Montana',
+ 'Nebraska','Nevada','New Hampshire','New Jersey',
+ 'New Mexico','New York','North Carolina','North Dakokta',
+ 'Ohio','Oklahoma','Oregon',
+ 'Pennsylvania','Puerto Rico','Rhode Island',
+ 'South Carolina','South Dakota',
+ 'Tennessee','Texas','Utah',
+ 'Vermont','Virginia',
+ 'Washington','West Virginia',
+ 'Wisconsin','Wyoming']
+
+## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+## The following dictionary defines the current set of autoformats:
+
+masktags = {
+ "USPHONEFULLEXT": {
+ 'mask': "(###) ###-#### x:###",
+ 'formatcodes': 'F^->',
+ 'validRegex': "^\(\d{3}\) \d{3}-\d{4}",
+ 'description': "Phone Number w/opt. ext"
+ },
+ "USPHONETIGHTEXT": {
+ 'mask': "###-###-#### x:###",
+ 'formatcodes': 'F^->',
+ 'validRegex': "^\d{3}-\d{3}-\d{4}",
+ 'description': "Phone Number\n (w/hyphens and opt. ext)"
+ },
+ "USPHONEFULL": {
+ 'mask': "(###) ###-####",
+ 'formatcodes': 'F^->',
+ 'validRegex': "^\(\d{3}\) \d{3}-\d{4}",
+ 'description': "Phone Number only"
+ },
+ "USPHONETIGHT": {
+ 'mask': "###-###-####",
+ 'formatcodes': 'F^->',
+ 'validRegex': "^\d{3}-\d{3}-\d{4}",
+ 'description': "Phone Number\n(w/hyphens)"
+ },
+ "USSTATE": {
+ 'mask': "AA",
+ 'formatcodes': 'F!V',
+ 'validRegex': "([ACDFGHIKLMNOPRSTUVW] |%s)" % string.join(states,'|'),
+ 'choices': states,
+ 'choiceRequired': True,
+ 'description': "US State Code"
+ },
+ "USSTATENAME": {
+ 'mask': "ACCCCCCCCCCCCCCCCCCC",
+ 'formatcodes': 'F_',
+ 'validRegex': "([ACDFGHIKLMNOPRSTUVW] |%s)" % string.join(state_names,'|'),
+ 'choices': state_names,
+ 'choiceRequired': True,
+ 'description': "US State Name"
+ },
+
+ "USDATETIMEMMDDYYYY/HHMMSS": {
+ 'mask': "##/##/#### ##:##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + months + '/' + days + '/' + '\d{4} ' + hours + ':' + minutes + ':' + seconds + ' (A|P)M',
+ 'description': "US Date + Time"
+ },
+ "USDATETIMEMMDDYYYY-HHMMSS": {
+ 'mask': "##-##-#### ##:##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + months + '-' + days + '-' + '\d{4} ' + hours + ':' + minutes + ':' + seconds + ' (A|P)M',
+ 'description': "US Date + Time\n(w/hypens)"
+ },
+ "USDATE24HRTIMEMMDDYYYY/HHMMSS": {
+ 'mask': "##/##/#### ##:##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + months + '/' + days + '/' + '\d{4} ' + milhours + ':' + minutes + ':' + seconds,
+ 'description': "US Date + 24Hr (Military) Time"
+ },
+ "USDATE24HRTIMEMMDDYYYY-HHMMSS": {
+ 'mask': "##-##-#### ##:##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + months + '-' + days + '-' + '\d{4} ' + milhours + ':' + minutes + ':' + seconds,
+ 'description': "US Date + 24Hr Time\n(w/hypens)"
+ },
+ "USDATETIMEMMDDYYYY/HHMM": {
+ 'mask': "##/##/#### ##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + months + '/' + days + '/' + '\d{4} ' + hours + ':' + minutes + ' (A|P)M',
+ 'description': "US Date + Time\n(without seconds)"
+ },
+ "USDATE24HRTIMEMMDDYYYY/HHMM": {
+ 'mask': "##/##/#### ##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + months + '/' + days + '/' + '\d{4} ' + milhours + ':' + minutes,
+ 'description': "US Date + 24Hr Time\n(without seconds)"
+ },
+ "USDATETIMEMMDDYYYY-HHMM": {
+ 'mask': "##-##-#### ##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + months + '-' + days + '-' + '\d{4} ' + hours + ':' + minutes + ' (A|P)M',
+ 'description': "US Date + Time\n(w/hypens and w/o secs)"
+ },
+ "USDATE24HRTIMEMMDDYYYY-HHMM": {
+ 'mask': "##-##-#### ##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + months + '-' + days + '-' + '\d{4} ' + milhours + ':' + minutes,
+ 'description': "US Date + 24Hr Time\n(w/hyphens and w/o seconds)"
+ },
+ "USDATEMMDDYYYY/": {
+ 'mask': "##/##/####",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + months + '/' + days + '/' + '\d{4}',
+ 'description': "US Date\n(MMDDYYYY)"
+ },
+ "USDATEMMDDYY/": {
+ 'mask': "##/##/##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + months + '/' + days + '/\d\d',
+ 'description': "US Date\n(MMDDYY)"
+ },
+ "USDATEMMDDYYYY-": {
+ 'mask': "##-##-####",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + months + '-' + days + '-' +'\d{4}',
+ 'description': "MM-DD-YYYY"
+ },
+
+ "EUDATEYYYYMMDD/": {
+ 'mask': "####/##/##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + '\d{4}'+ '/' + months + '/' + days,
+ 'description': "YYYY/MM/DD"
+ },
+ "EUDATEYYYYMMDD.": {
+ 'mask': "####.##.##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + '\d{4}'+ '.' + months + '.' + days,
+ 'description': "YYYY.MM.DD"
+ },
+ "EUDATEDDMMYYYY/": {
+ 'mask': "##/##/####",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + days + '/' + months + '/' + '\d{4}',
+ 'description': "DD/MM/YYYY"
+ },
+ "EUDATEDDMMYYYY.": {
+ 'mask': "##.##.####",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + days + '.' + months + '.' + '\d{4}',
+ 'description': "DD.MM.YYYY"
+ },
+ "EUDATEDDMMMYYYY.": {
+ 'mask': "##.CCC.####",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + days + '.' + charmonths + '.' + '\d{4}',
+ 'description': "DD.Month.YYYY"
+ },
+ "EUDATEDDMMMYYYY/": {
+ 'mask': "##/CCC/####",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + days + '/' + charmonths + '/' + '\d{4}',
+ 'description': "DD/Month/YYYY"
+ },
+
+ "EUDATETIMEYYYYMMDD/HHMMSS": {
+ 'mask': "####/##/## ##:##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + '\d{4}'+ '/' + months + '/' + days + ' ' + hours + ':' + minutes + ':' + seconds + ' (A|P)M',
+ 'description': "YYYY/MM/DD HH:MM:SS"
+ },
+ "EUDATETIMEYYYYMMDD.HHMMSS": {
+ 'mask': "####.##.## ##:##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + '\d{4}'+ '.' + months + '.' + days + ' ' + hours + ':' + minutes + ':' + seconds + ' (A|P)M',
+ 'description': "YYYY.MM.DD HH:MM:SS"
+ },
+ "EUDATETIMEDDMMYYYY/HHMMSS": {
+ 'mask': "##/##/#### ##:##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + days + '/' + months + '/' + '\d{4} ' + hours + ':' + minutes + ':' + seconds + ' (A|P)M',
+ 'description': "DD/MM/YYYY HH:MM:SS"
+ },
+ "EUDATETIMEDDMMYYYY.HHMMSS": {
+ 'mask': "##.##.#### ##:##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + days + '.' + months + '.' + '\d{4} ' + hours + ':' + minutes + ':' + seconds + ' (A|P)M',
+ 'description': "DD.MM.YYYY HH:MM:SS"
+ },
+
+ "EUDATETIMEYYYYMMDD/HHMM": {
+ 'mask': "####/##/## ##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + '\d{4}'+ '/' + months + '/' + days + ' ' + hours + ':' + minutes + ' (A|P)M',
+ 'description': "YYYY/MM/DD HH:MM"
+ },
+ "EUDATETIMEYYYYMMDD.HHMM": {
+ 'mask': "####.##.## ##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + '\d{4}'+ '.' + months + '.' + days + ' ' + hours + ':' + minutes + ' (A|P)M',
+ 'description': "YYYY.MM.DD HH:MM"
+ },
+ "EUDATETIMEDDMMYYYY/HHMM": {
+ 'mask': "##/##/#### ##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + days + '/' + months + '/' + '\d{4} ' + hours + ':' + minutes + ' (A|P)M',
+ 'description': "DD/MM/YYYY HH:MM"
+ },
+ "EUDATETIMEDDMMYYYY.HHMM": {
+ 'mask': "##.##.#### ##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'DF!',
+ 'validRegex': '^' + days + '.' + months + '.' + '\d{4} ' + hours + ':' + minutes + ' (A|P)M',
+ 'description': "DD.MM.YYYY HH:MM"
+ },
+
+ "EUDATE24HRTIMEYYYYMMDD/HHMMSS": {
+ 'mask': "####/##/## ##:##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + '\d{4}'+ '/' + months + '/' + days + ' ' + milhours + ':' + minutes + ':' + seconds,
+ 'description': "YYYY/MM/DD 24Hr Time"
+ },
+ "EUDATE24HRTIMEYYYYMMDD.HHMMSS": {
+ 'mask': "####.##.## ##:##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + '\d{4}'+ '.' + months + '.' + days + ' ' + milhours + ':' + minutes + ':' + seconds,
+ 'description': "YYYY.MM.DD 24Hr Time"
+ },
+ "EUDATE24HRTIMEDDMMYYYY/HHMMSS": {
+ 'mask': "##/##/#### ##:##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + days + '/' + months + '/' + '\d{4} ' + milhours + ':' + minutes + ':' + seconds,
+ 'description': "DD/MM/YYYY 24Hr Time"
+ },
+ "EUDATE24HRTIMEDDMMYYYY.HHMMSS": {
+ 'mask': "##.##.#### ##:##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + days + '.' + months + '.' + '\d{4} ' + milhours + ':' + minutes + ':' + seconds,
+ 'description': "DD.MM.YYYY 24Hr Time"
+ },
+ "EUDATE24HRTIMEYYYYMMDD/HHMM": {
+ 'mask': "####/##/## ##:##",
+ 'formatcodes': 'DF','validRegex': '^' + '\d{4}'+ '/' + months + '/' + days + ' ' + milhours + ':' + minutes,
+ 'description': "YYYY/MM/DD 24Hr Time\n(w/o seconds)"
+ },
+ "EUDATE24HRTIMEYYYYMMDD.HHMM": {
+ 'mask': "####.##.## ##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + '\d{4}'+ '.' + months + '.' + days + ' ' + milhours + ':' + minutes,
+ 'description': "YYYY.MM.DD 24Hr Time\n(w/o seconds)"
+ },
+ "EUDATE24HRTIMEDDMMYYYY/HHMM": {
+ 'mask': "##/##/#### ##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + days + '/' + months + '/' + '\d{4} ' + milhours + ':' + minutes,
+ 'description': "DD/MM/YYYY 24Hr Time\n(w/o seconds)"
+ },
+ "EUDATE24HRTIMEDDMMYYYY.HHMM": {
+ 'mask': "##.##.#### ##:##",
+ 'formatcodes': 'DF',
+ 'validRegex': '^' + days + '.' + months + '.' + '\d{4} ' + milhours + ':' + minutes,
+ 'description': "DD.MM.YYYY 24Hr Time\n(w/o seconds)"
+ },
+
+ "TIMEHHMMSS": {
+ 'mask': "##:##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'TF!',
+ 'validRegex': '^' + hours + ':' + minutes + ':' + seconds + ' (A|P)M',
+ 'description': "HH:MM:SS (A|P)M\n(see TimeCtrl)"
+ },
+ "TIMEHHMM": {
+ 'mask': "##:## AM",
+ 'excludeChars': am_pm_exclude,
+ 'formatcodes': 'TF!',
+ 'validRegex': '^' + hours + ':' + minutes + ' (A|P)M',
+ 'description': "HH:MM (A|P)M\n(see TimeCtrl)"
+ },
+ "24HRTIMEHHMMSS": {
+ 'mask': "##:##:##",
+ 'formatcodes': 'TF',
+ 'validRegex': '^' + milhours + ':' + minutes + ':' + seconds,
+ 'description': "24Hr HH:MM:SS\n(see TimeCtrl)"
+ },
+ "24HRTIMEHHMM": {
+ 'mask': "##:##",
+ 'formatcodes': 'TF',
+ 'validRegex': '^' + milhours + ':' + minutes,
+ 'description': "24Hr HH:MM\n(see TimeCtrl)"
+ },
+ "USSOCIALSEC": {
+ 'mask': "###-##-####",
+ 'formatcodes': 'F',
+ 'validRegex': "\d{3}-\d{2}-\d{4}",
+ 'description': "Social Sec#"
+ },
+ "CREDITCARD": {
+ 'mask': "####-####-####-####",
+ 'formatcodes': 'F',
+ 'validRegex': "\d{4}-\d{4}-\d{4}-\d{4}",
+ 'description': "Credit Card"
+ },
+ "EXPDATEMMYY": {
+ 'mask': "##/##",
+ 'formatcodes': "F",
+ 'validRegex': "^" + months + "/\d\d",
+ 'description': "Expiration MM/YY"
+ },
+ "USZIP": {
+ 'mask': "#####",
+ 'formatcodes': 'F',
+ 'validRegex': "^\d{5}",
+ 'description': "US 5-digit zip code"
+ },
+ "USZIPPLUS4": {
+ 'mask': "#####-####",
+ 'formatcodes': 'F',
+ 'validRegex': "\d{5}-(\s{4}|\d{4})",
+ 'description': "US zip+4 code"
+ },
+ "PERCENT": {
+ 'mask': "0.##",
+ 'formatcodes': 'F',
+ 'validRegex': "^0.\d\d",
+ 'description': "Percentage"
+ },
+ "AGE": {
+ 'mask': "###",
+ 'formatcodes': "F",
+ 'validRegex': "^[1-9]{1} |[1-9][0-9] |1[0|1|2][0-9]",
+ 'description': "Age"
+ },
+ "EMAIL": {
+ 'mask': "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ 'excludeChars': " \\/*&%$#!+='\"",
+ 'formatcodes': "F>",
+ 'validRegex': "^\w+([\-\.]\w+)*@((([a-zA-Z0-9]+(\-[a-zA-Z0-9]+)*\.)+)[a-zA-Z]{2,4}|\[(\d|\d\d|(1\d\d|2[0-4]\d|25[0-5]))(\.(\d|\d\d|(1\d\d|2[0-4]\d|25[0-5]))){3}\]) *$",
+ 'description': "Email address"
+ },
+ "IPADDR": {
+ 'mask': "###.###.###.###",
+ 'formatcodes': 'F_Sr',
+ 'validRegex': "( \d| \d\d|(1\d\d|2[0-4]\d|25[0-5]))(\.( \d| \d\d|(1\d\d|2[0-4]\d|25[0-5]))){3}",
+ 'description': "IP Address\n(see IpAddrCtrl)"
+ }
+ }
+
+# build demo-friendly dictionary of descriptions of autoformats
+autoformats = []
+for key, value in masktags.items():
+ autoformats.append((key, value['description']))
+autoformats.sort()
+
+## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+class Field:
+ """
+ This class manages the individual fields in a masked edit control.
+ Each field has a zero-based index, indicating its position in the
+ control, an extent, an associated mask, and a plethora of optional
+ parameters. Fields can be instantiated and then associated with
+ parent masked controls, in order to provide field-specific configuration.
+ Alternatively, fields will be implicitly created by the parent control
+ if not provided at construction, at which point, the fields can then
+ manipulated by the controls .SetFieldParameters() method.
+ """
+ valid_params = {
+ 'index': None, ## which field of mask; set by parent control.
+ 'mask': "", ## mask chars for this field
+ 'extent': (), ## (edit start, edit_end) of field; set by parent control.
+ 'formatcodes': "", ## codes indicating formatting options for the control
+ 'fillChar': ' ', ## used as initial value for each mask position if initial value is not given
+ 'groupChar': ',', ## used with numeric fields; indicates what char groups 3-tuple digits
+ 'decimalChar': '.', ## used with numeric fields; indicates what char separates integer from fraction
+ 'shiftDecimalChar': '>', ## used with numeric fields, indicates what is above the decimal point char on keyboard
+ 'useParensForNegatives': False, ## used with numeric fields, indicates that () should be used vs. - to show negative numbers.
+ 'defaultValue': "", ## use if you want different positional defaults vs. all the same fillChar
+ 'excludeChars': "", ## optional string of chars to exclude even if main mask type does
+ 'includeChars': "", ## optional string of chars to allow even if main mask type doesn't
+ 'validRegex': "", ## optional regular expression to use to validate the control
+ 'validRange': (), ## Optional hi-low range for numerics
+ 'choices': [], ## Optional list for character expressions
+ 'choiceRequired': False, ## If choices supplied this specifies if valid value must be in the list
+ 'compareNoCase': False, ## Optional flag to indicate whether or not to use case-insensitive list search
+ 'autoSelect': False, ## Set to True to try auto-completion on each keystroke:
+ 'validFunc': None, ## Optional function for defining additional, possibly dynamic validation constraints on contrl
+ 'validRequired': False, ## Set to True to disallow input that results in an invalid value
+ 'emptyInvalid': False, ## Set to True to make EMPTY = INVALID
+ 'description': "", ## primarily for autoformats, but could be useful elsewhere
+ 'raiseOnInvalidPaste': False, ## if True, paste into field will cause ValueError
+ 'stopFieldChangeIfInvalid': False,## if True, disallow field navigation out of invalid field
+ }
+
+ # This list contains all parameters that when set at the control level should
+ # propagate down to each field:
+ propagating_params = ('fillChar', 'groupChar', 'decimalChar','useParensForNegatives',
+ 'compareNoCase', 'emptyInvalid', 'validRequired', 'raiseOnInvalidPaste',
+ 'stopFieldChangeIfInvalid')
+
+ def __init__(self, **kwargs):
+ """
+ This is the "constructor" for setting up parameters for fields.
+ a field_index of -1 is used to indicate "the entire control."
+ """
+#### dbg('Field::Field', indent=1)
+ # Validate legitimate set of parameters:
+ for key in kwargs.keys():
+ if key not in Field.valid_params.keys():
+#### dbg(indent=0)
+ ae = AttributeError('invalid parameter "%s"' % (key))
+ ae.attribute = key
+ raise ae
+
+ # Set defaults for each parameter for this instance, and fully
+ # populate initial parameter list for configuration:
+ for key, value in Field.valid_params.items():
+ setattr(self, '_' + key, copy.copy(value))
+ if not kwargs.has_key(key):
+ kwargs[key] = copy.copy(value)
+
+ self._autoCompleteIndex = -1
+ self._SetParameters(**kwargs)
+ self._ValidateParameters(**kwargs)
+
+#### dbg(indent=0)
+
+
+ def _SetParameters(self, **kwargs):
+ """
+ This function can be used to set individual or multiple parameters for
+ a masked edit field parameter after construction.
+ """
+## dbg(suspend=1)
+## dbg('maskededit.Field::_SetParameters', indent=1)
+ # Validate keyword arguments:
+ for key in kwargs.keys():
+ if key not in Field.valid_params.keys():
+## dbg(indent=0, suspend=0)
+ ae = AttributeError('invalid keyword argument "%s"' % key)
+ ae.attribute = key
+ raise ae
+
+## if self._index is not None: dbg('field index:', self._index)
+## dbg('parameters:', indent=1)
+ for key, value in kwargs.items():
+## dbg('%s:' % key, value)
+ pass
+## dbg(indent=0)
+
+
+ old_fillChar = self._fillChar # store so we can change choice lists accordingly if it changes
+
+ # First, Assign all parameters specified:
+ for key in Field.valid_params.keys():
+ if kwargs.has_key(key):
+ setattr(self, '_' + key, kwargs[key] )
+
+ if kwargs.has_key('formatcodes'): # (set/changed)
+ self._forceupper = '!' in self._formatcodes
+ self._forcelower = '^' in self._formatcodes
+ self._groupdigits = ',' in self._formatcodes
+ self._okSpaces = '_' in self._formatcodes
+ self._padZero = '0' in self._formatcodes
+ self._autofit = 'F' in self._formatcodes
+ self._insertRight = 'r' in self._formatcodes
+ self._allowInsert = '>' in self._formatcodes
+ self._alignRight = 'R' in self._formatcodes or 'r' in self._formatcodes
+ self._moveOnFieldFull = not '<' in self._formatcodes
+ self._selectOnFieldEntry = 'S' in self._formatcodes
+
+ if kwargs.has_key('groupChar'):
+ self._groupChar = kwargs['groupChar']
+ if kwargs.has_key('decimalChar'):
+ self._decimalChar = kwargs['decimalChar']
+ if kwargs.has_key('shiftDecimalChar'):
+ self._shiftDecimalChar = kwargs['shiftDecimalChar']
+
+ if kwargs.has_key('formatcodes') or kwargs.has_key('validRegex'):
+ self._regexMask = 'V' in self._formatcodes and self._validRegex
+
+ if kwargs.has_key('fillChar'):
+ self._old_fillChar = old_fillChar
+#### dbg("self._old_fillChar: '%s'" % self._old_fillChar)
+
+ if kwargs.has_key('mask') or kwargs.has_key('validRegex'): # (set/changed)
+ self._isInt = _isInteger(self._mask)
+## dbg('isInt?', self._isInt, 'self._mask:"%s"' % self._mask)
+
+## dbg(indent=0, suspend=0)
+
+
+ def _ValidateParameters(self, **kwargs):
+ """
+ This function can be used to validate individual or multiple parameters for
+ a masked edit field parameter after construction.
+ """
+## dbg(suspend=1)
+## dbg('maskededit.Field::_ValidateParameters', indent=1)
+## if self._index is not None: dbg('field index:', self._index)
+#### dbg('parameters:', indent=1)
+## for key, value in kwargs.items():
+#### dbg('%s:' % key, value)
+#### dbg(indent=0)
+#### dbg("self._old_fillChar: '%s'" % self._old_fillChar)
+
+ # Verify proper numeric format params:
+ if self._groupdigits and self._groupChar == self._decimalChar:
+## dbg(indent=0, suspend=0)
+ ae = AttributeError("groupChar '%s' cannot be the same as decimalChar '%s'" % (self._groupChar, self._decimalChar))
+ ae.attribute = self._groupChar
+ raise ae
+
+
+ # Now go do validation, semantic and inter-dependency parameter processing:
+ if kwargs.has_key('choices') or kwargs.has_key('compareNoCase') or kwargs.has_key('choiceRequired'): # (set/changed)
+
+ self._compareChoices = [choice.strip() for choice in self._choices]
+
+ if self._compareNoCase and self._choices:
+ self._compareChoices = [item.lower() for item in self._compareChoices]
+
+ if kwargs.has_key('choices'):
+ self._autoCompleteIndex = -1
+
+
+ if kwargs.has_key('validRegex'): # (set/changed)
+ if self._validRegex:
+ try:
+ if self._compareNoCase:
+ self._filter = re.compile(self._validRegex, re.IGNORECASE)
+ else:
+ self._filter = re.compile(self._validRegex)
+ except:
+## dbg(indent=0, suspend=0)
+ raise TypeError('%s: validRegex "%s" not a legal regular expression' % (str(self._index), self._validRegex))
+ else:
+ self._filter = None
+
+ if kwargs.has_key('validRange'): # (set/changed)
+ self._hasRange = False
+ self._rangeHigh = 0
+ self._rangeLow = 0
+ if self._validRange:
+ if type(self._validRange) != types.TupleType or len( self._validRange )!= 2 or self._validRange[0] > self._validRange[1]:
+## dbg(indent=0, suspend=0)
+ raise TypeError('%s: validRange %s parameter must be tuple of form (a,b) where a <= b'
+ % (str(self._index), repr(self._validRange)) )
+
+ self._hasRange = True
+ self._rangeLow = self._validRange[0]
+ self._rangeHigh = self._validRange[1]
+
+ if kwargs.has_key('choices') or (len(self._choices) and len(self._choices[0]) != len(self._mask)): # (set/changed)
+ self._hasList = False
+ if self._choices and type(self._choices) not in (types.TupleType, types.ListType):
+## dbg(indent=0, suspend=0)
+ raise TypeError('%s: choices must be a sequence of strings' % str(self._index))
+ elif len( self._choices) > 0:
+ for choice in self._choices:
+ if type(choice) not in (types.StringType, types.UnicodeType):
+## dbg(indent=0, suspend=0)
+ raise TypeError('%s: choices must be a sequence of strings' % str(self._index))
+
+ length = len(self._mask)
+## dbg('len(%s)' % self._mask, length, 'len(self._choices):', len(self._choices), 'length:', length, 'self._alignRight?', self._alignRight)
+ if len(self._choices) and length:
+ if len(self._choices[0]) > length:
+ # changed mask without respecifying choices; readjust the width as appropriate:
+ self._choices = [choice.strip() for choice in self._choices]
+ if self._alignRight:
+ self._choices = [choice.rjust( length ) for choice in self._choices]
+ else:
+ self._choices = [choice.ljust( length ) for choice in self._choices]
+## dbg('aligned choices:', self._choices)
+
+ if hasattr(self, '_template'):
+ # Verify each choice specified is valid:
+ for choice in self._choices:
+ if self.IsEmpty(choice) and not self._validRequired:
+ # allow empty values even if invalid, (just colored differently)
+ continue
+ if not self.IsValid(choice):
+## dbg(indent=0, suspend=0)
+ ve = ValueError('%s: "%s" is not a valid value for the control as specified.' % (str(self._index), choice))
+ ve.value = choice
+ raise ve
+ self._hasList = True
+
+#### dbg("kwargs.has_key('fillChar')?", kwargs.has_key('fillChar'), "len(self._choices) > 0?", len(self._choices) > 0)
+#### dbg("self._old_fillChar:'%s'" % self._old_fillChar, "self._fillChar: '%s'" % self._fillChar)
+ if kwargs.has_key('fillChar') and len(self._choices) > 0:
+ if kwargs['fillChar'] != ' ':
+ self._choices = [choice.replace(' ', self._fillChar) for choice in self._choices]
+ else:
+ self._choices = [choice.replace(self._old_fillChar, self._fillChar) for choice in self._choices]
+## dbg('updated choices:', self._choices)
+
+
+ if kwargs.has_key('autoSelect') and kwargs['autoSelect']:
+ if not self._hasList:
+## dbg('no list to auto complete; ignoring "autoSelect=True"')
+ self._autoSelect = False
+
+ # reset field validity assumption:
+ self._valid = True
+## dbg(indent=0, suspend=0)
+
+
+ def _GetParameter(self, paramname):
+ """
+ Routine for retrieving the value of any given parameter
+ """
+ if Field.valid_params.has_key(paramname):
+ return getattr(self, '_' + paramname)
+ else:
+ TypeError('Field._GetParameter: invalid parameter "%s"' % key)
+
+
+ def IsEmpty(self, slice):
+ """
+ Indicates whether the specified slice is considered empty for the
+ field.
+ """
+## dbg('Field::IsEmpty("%s")' % slice, indent=1)
+ if not hasattr(self, '_template'):
+## dbg(indent=0)
+ raise AttributeError('_template')
+
+## dbg('self._template: "%s"' % self._template)
+## dbg('self._defaultValue: "%s"' % str(self._defaultValue))
+ if slice == self._template and not self._defaultValue:
+## dbg(indent=0)
+ return True
+
+ elif slice == self._template:
+ empty = True
+ for pos in range(len(self._template)):
+#### dbg('slice[%(pos)d] != self._fillChar?' %locals(), slice[pos] != self._fillChar[pos])
+ if slice[pos] not in (' ', self._fillChar):
+ empty = False
+ break
+## dbg("IsEmpty? %(empty)d (do all mask chars == fillChar?)" % locals(), indent=0)
+ return empty
+ else:
+## dbg("IsEmpty? 0 (slice doesn't match template)", indent=0)
+ return False
+
+
+ def IsValid(self, slice):
+ """
+ Indicates whether the specified slice is considered a valid value for the
+ field.
+ """
+## dbg(suspend=1)
+## dbg('Field[%s]::IsValid("%s")' % (str(self._index), slice), indent=1)
+ valid = True # assume true to start
+
+ if self.IsEmpty(slice):
+## dbg(indent=0, suspend=0)
+ if self._emptyInvalid:
+ return False
+ else:
+ return True
+
+ elif self._hasList and self._choiceRequired:
+## dbg("(member of list required)")
+ # do case-insensitive match on list; strip surrounding whitespace from slice (already done for choices):
+ if self._fillChar != ' ':
+ slice = slice.replace(self._fillChar, ' ')
+## dbg('updated slice:"%s"' % slice)
+ compareStr = slice.strip()
+
+ if self._compareNoCase:
+ compareStr = compareStr.lower()
+ valid = compareStr in self._compareChoices
+
+ elif self._hasRange and not self.IsEmpty(slice):
+## dbg('validating against range')
+ try:
+ # allow float as well as int ranges (int comparisons for free.)
+ valid = self._rangeLow <= float(slice) <= self._rangeHigh
+ except:
+ valid = False
+
+ elif self._validRegex and self._filter:
+## dbg('validating against regex')
+ valid = (re.match( self._filter, slice) is not None)
+
+ if valid and self._validFunc:
+## dbg('validating against supplied function')
+ valid = self._validFunc(slice)
+## dbg('valid?', valid, indent=0, suspend=0)
+ return valid
+
+
+ def _AdjustField(self, slice):
+ """ 'Fixes' an integer field. Right or left-justifies, as required."""
+## dbg('Field::_AdjustField("%s")' % slice, indent=1)
+ length = len(self._mask)
+#### dbg('length(self._mask):', length)
+#### dbg('self._useParensForNegatives?', self._useParensForNegatives)
+ if self._isInt:
+ if self._useParensForNegatives:
+ signpos = slice.find('(')
+ right_signpos = slice.find(')')
+ intStr = slice.replace('(', '').replace(')', '') # drop sign, if any
+ else:
+ signpos = slice.find('-')
+ intStr = slice.replace( '-', '' ) # drop sign, if any
+ right_signpos = -1
+
+ intStr = intStr.replace(' ', '') # drop extra spaces
+ intStr = string.replace(intStr,self._fillChar,"") # drop extra fillchars
+ intStr = string.replace(intStr,"-","") # drop sign, if any
+ intStr = string.replace(intStr, self._groupChar, "") # lose commas/dots
+#### dbg('intStr:"%s"' % intStr)
+ start, end = self._extent
+ field_len = end - start
+ if not self._padZero and len(intStr) != field_len and intStr.strip():
+ intStr = str(long(intStr))
+#### dbg('raw int str: "%s"' % intStr)
+#### dbg('self._groupdigits:', self._groupdigits, 'self._formatcodes:', self._formatcodes)
+ if self._groupdigits:
+ new = ''
+ cnt = 1
+ for i in range(len(intStr)-1, -1, -1):
+ new = intStr[i] + new
+ if (cnt) % 3 == 0:
+ new = self._groupChar + new
+ cnt += 1
+ if new and new[0] == self._groupChar:
+ new = new[1:]
+ if len(new) <= length:
+ # expanded string will still fit and leave room for sign:
+ intStr = new
+ # else... leave it without the commas...
+
+## dbg('padzero?', self._padZero)
+## dbg('len(intStr):', len(intStr), 'field length:', length)
+ if self._padZero and len(intStr) < length:
+ intStr = '0' * (length - len(intStr)) + intStr
+ if signpos != -1: # we had a sign before; restore it
+ if self._useParensForNegatives:
+ intStr = '(' + intStr[1:]
+ if right_signpos != -1:
+ intStr += ')'
+ else:
+ intStr = '-' + intStr[1:]
+ elif signpos != -1 and slice[0:signpos].strip() == '': # - was before digits
+ if self._useParensForNegatives:
+ intStr = '(' + intStr
+ if right_signpos != -1:
+ intStr += ')'
+ else:
+ intStr = '-' + intStr
+ elif right_signpos != -1:
+ # must have had ')' but '(' was before field; re-add ')'
+ intStr += ')'
+ slice = intStr
+
+ slice = slice.strip() # drop extra spaces
+
+ if self._alignRight: ## Only if right-alignment is enabled
+ slice = slice.rjust( length )
+ else:
+ slice = slice.ljust( length )
+ if self._fillChar != ' ':
+ slice = slice.replace(' ', self._fillChar)
+## dbg('adjusted slice: "%s"' % slice, indent=0)
+ return slice
+
+
+## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+class MaskedEditMixin:
+ """
+ This class allows us to abstract the masked edit functionality that could
+ be associated with any text entry control. (eg. wx.TextCtrl, wx.ComboBox, etc.)
+ It forms the basis for all of the lib.masked controls.
+ """
+ valid_ctrl_params = {
+ 'mask': 'XXXXXXXXXXXXX', ## mask string for formatting this control
+ 'autoformat': "", ## optional auto-format code to set format from masktags dictionary
+ 'fields': {}, ## optional list/dictionary of maskededit.Field class instances, indexed by position in mask
+ 'datestyle': 'MDY', ## optional date style for date-type values. Can trigger autocomplete year
+ 'autoCompleteKeycodes': [], ## Optional list of additional keycodes which will invoke field-auto-complete
+ 'useFixedWidthFont': True, ## Use fixed-width font instead of default for base control
+ 'defaultEncoding': 'latin1', ## optional argument to indicate unicode codec to use (unicode ctrls only)
+ 'retainFieldValidation': False, ## Set this to true if setting control-level parameters independently,
+ ## from field validation constraints
+ 'emptyBackgroundColour': "White",
+ 'validBackgroundColour': "White",
+ 'invalidBackgroundColour': "Yellow",
+ 'foregroundColour': "Black",
+ 'signedForegroundColour': "Red",
+ 'demo': False}
+
+
+ def __init__(self, name = 'MaskedEdit', **kwargs):
+ """
+ This is the "constructor" for setting up the mixin variable parameters for the composite class.
+ """
+
+ self.name = name
+
+ # set up flag for doing optional things to base control if possible
+ if not hasattr(self, 'controlInitialized'):
+ self.controlInitialized = False
+
+ # Set internal state var for keeping track of whether or not a character
+ # action results in a modification of the control, since .SetValue()
+ # doesn't modify the base control's internal state:
+ self.modified = False
+ self._previous_mask = None
+
+ # Validate legitimate set of parameters:
+ for key in kwargs.keys():
+ if key.replace('Color', 'Colour') not in MaskedEditMixin.valid_ctrl_params.keys() + Field.valid_params.keys():
+ raise TypeError('%s: invalid parameter "%s"' % (name, key))
+
+ ## Set up dictionary that can be used by subclasses to override or add to default
+ ## behavior for individual characters. Derived subclasses needing to change
+ ## default behavior for keys can either redefine the default functions for the
+ ## common keys or add functions for specific keys to this list. Each function
+ ## added should take the key event as argument, and return False if the key
+ ## requires no further processing.
+ ##
+ ## Initially populated with navigation and function control keys:
+ self._keyhandlers = {
+ # default navigation keys and handlers:
+ wx.WXK_BACK: self._OnErase,
+ wx.WXK_LEFT: self._OnArrow,
+ wx.WXK_NUMPAD_LEFT: self._OnArrow,
+ wx.WXK_RIGHT: self._OnArrow,
+ wx.WXK_NUMPAD_RIGHT: self._OnArrow,
+ wx.WXK_UP: self._OnAutoCompleteField,
+ wx.WXK_NUMPAD_UP: self._OnAutoCompleteField,
+ wx.WXK_DOWN: self._OnAutoCompleteField,
+ wx.WXK_NUMPAD_DOWN: self._OnAutoCompleteField,
+ wx.WXK_TAB: self._OnChangeField,
+ wx.WXK_HOME: self._OnHome,
+ wx.WXK_NUMPAD_HOME: self._OnHome,
+ wx.WXK_END: self._OnEnd,
+ wx.WXK_NUMPAD_END: self._OnEnd,
+ wx.WXK_RETURN: self._OnReturn,
+ wx.WXK_NUMPAD_ENTER: self._OnReturn,
+ wx.WXK_PRIOR: self._OnAutoCompleteField,
+ wx.WXK_NUMPAD_PRIOR: self._OnAutoCompleteField,
+ wx.WXK_NEXT: self._OnAutoCompleteField,
+ wx.WXK_NUMPAD_NEXT: self._OnAutoCompleteField,
+
+ # default function control keys and handlers:
+ wx.WXK_DELETE: self._OnDelete,
+ wx.WXK_NUMPAD_DELETE: self._OnDelete,
+ wx.WXK_INSERT: self._OnInsert,
+ wx.WXK_NUMPAD_INSERT: self._OnInsert,
+
+ WXK_CTRL_A: self._OnCtrl_A,
+ WXK_CTRL_C: self._OnCtrl_C,
+ WXK_CTRL_S: self._OnCtrl_S,
+ WXK_CTRL_V: self._OnCtrl_V,
+ WXK_CTRL_X: self._OnCtrl_X,
+ WXK_CTRL_Z: self._OnCtrl_Z,
+ }
+
+ ## bind standard navigational and control keycodes to this instance,
+ ## so that they can be augmented and/or changed in derived classes:
+ self._nav = list(nav)
+ self._control = list(control)
+
+ ## Dynamically evaluate and store string constants for mask chars
+ ## so that locale settings can be made after this module is imported
+ ## and the controls created after that is done can allow the
+ ## appropriate characters:
+ self.maskchardict = {
+ '#': string.digits,
+ 'A': string.uppercase,
+ 'a': string.lowercase,
+ 'X': string.letters + string.punctuation + string.digits,
+ 'C': string.letters,
+ 'N': string.letters + string.digits,
+ '&': string.punctuation,
+ '*': ansichars # to give it a value, but now allows any non-wxcontrol character
+ }
+
+ ## self._ignoreChange is used by MaskedComboBox, because
+ ## of the hack necessary to determine the selection; it causes
+ ## EVT_TEXT messages from the combobox to be ignored if set.
+ self._ignoreChange = False
+
+ # These are used to keep track of previous value, for undo functionality:
+ self._curValue = None
+ self._prevValue = None
+
+ self._valid = True
+
+ # Set defaults for each parameter for this instance, and fully
+ # populate initial parameter list for configuration:
+ for key, value in MaskedEditMixin.valid_ctrl_params.items():
+ setattr(self, '_' + key, copy.copy(value))
+ if not kwargs.has_key(key):
+#### dbg('%s: "%s"' % (key, repr(value)))
+ kwargs[key] = copy.copy(value)
+
+ # Create a "field" that holds global parameters for control constraints
+ self._ctrl_constraints = self._fields[-1] = Field(index=-1)
+ self.SetCtrlParameters(**kwargs)
+
+
+
+ def SetCtrlParameters(self, **kwargs):
+ """
+ This public function can be used to set individual or multiple masked edit
+ parameters after construction. (See maskededit module overview for the list
+ of valid parameters.)
+ """
+## dbg(suspend=1)
+## dbg('MaskedEditMixin::SetCtrlParameters', indent=1)
+#### dbg('kwargs:', indent=1)
+## for key, value in kwargs.items():
+#### dbg(key, '=', value)
+#### dbg(indent=0)
+
+ # Validate keyword arguments:
+ constraint_kwargs = {}
+ ctrl_kwargs = {}
+ for key, value in kwargs.items():
+ key = key.replace('Color', 'Colour') # for b-c, and standard wxPython spelling
+ if key not in MaskedEditMixin.valid_ctrl_params.keys() + Field.valid_params.keys():
+## dbg(indent=0, suspend=0)
+ ae = AttributeError('Invalid keyword argument "%s" for control "%s"' % (key, self.name))
+ ae.attribute = key
+ raise ae
+ elif key in Field.valid_params.keys():
+ constraint_kwargs[key] = value
+ else:
+ ctrl_kwargs[key] = value
+
+ mask = None
+ reset_args = {}
+
+ if ctrl_kwargs.has_key('autoformat'):
+ autoformat = ctrl_kwargs['autoformat']
+ else:
+ autoformat = None
+
+ # handle "parochial name" backward compatibility:
+ if autoformat and autoformat.find('MILTIME') != -1 and autoformat not in masktags.keys():
+ autoformat = autoformat.replace('MILTIME', '24HRTIME')
+
+ if autoformat != self._autoformat and autoformat in masktags.keys():
+## dbg('autoformat:', autoformat)
+ self._autoformat = autoformat
+ mask = masktags[self._autoformat]['mask']
+ # gather rest of any autoformat parameters:
+ for param, value in masktags[self._autoformat].items():
+ if param == 'mask': continue # (must be present; already accounted for)
+ constraint_kwargs[param] = value
+
+ elif autoformat and not autoformat in masktags.keys():
+ ae = AttributeError('invalid value for autoformat parameter: %s' % repr(autoformat))
+ ae.attribute = autoformat
+ raise ae
+ else:
+## dbg('autoformat not selected')
+ if kwargs.has_key('mask'):
+ mask = kwargs['mask']
+## dbg('mask:', mask)
+
+ ## Assign style flags
+ if mask is None:
+## dbg('preserving previous mask')
+ mask = self._previous_mask # preserve previous mask
+ else:
+## dbg('mask (re)set')
+ reset_args['reset_mask'] = mask
+ constraint_kwargs['mask'] = mask
+
+ # wipe out previous fields; preserve new control-level constraints
+ self._fields = {-1: self._ctrl_constraints}
+
+
+ if ctrl_kwargs.has_key('fields'):
+ # do field parameter type validation, and conversion to internal dictionary
+ # as appropriate:
+ fields = ctrl_kwargs['fields']
+ if type(fields) in (types.ListType, types.TupleType):
+ for i in range(len(fields)):
+ field = fields[i]
+ if not isinstance(field, Field):
+## dbg(indent=0, suspend=0)
+ raise TypeError('invalid type for field parameter: %s' % repr(field))
+ self._fields[i] = field
+
+ elif type(fields) == types.DictionaryType:
+ for index, field in fields.items():
+ if not isinstance(field, Field):
+## dbg(indent=0, suspend=0)
+ raise TypeError('invalid type for field parameter: %s' % repr(field))
+ self._fields[index] = field
+ else:
+## dbg(indent=0, suspend=0)
+ raise TypeError('fields parameter must be a list or dictionary; not %s' % repr(fields))
+
+ # Assign constraint parameters for entire control:
+#### dbg('control constraints:', indent=1)
+## for key, value in constraint_kwargs.items():
+#### dbg('%s:' % key, value)
+#### dbg(indent=0)
+
+ # determine if changing parameters that should affect the entire control:
+ for key in MaskedEditMixin.valid_ctrl_params.keys():
+ if key in ( 'mask', 'fields' ): continue # (processed separately)
+ if ctrl_kwargs.has_key(key):
+ setattr(self, '_' + key, ctrl_kwargs[key])
+
+ # Validate color parameters, converting strings to named colors and validating
+ # result if appropriate:
+ for key in ('emptyBackgroundColour', 'invalidBackgroundColour', 'validBackgroundColour',
+ 'foregroundColour', 'signedForegroundColour'):
+ if ctrl_kwargs.has_key(key):
+ if type(ctrl_kwargs[key]) in (types.StringType, types.UnicodeType):
+ c = wx.NamedColour(ctrl_kwargs[key])
+ if c.Get() == (-1, -1, -1):
+ raise TypeError('%s not a legal color specification for %s' % (repr(ctrl_kwargs[key]), key))
+ else:
+ # replace attribute with wxColour object:
+ setattr(self, '_' + key, c)
+ # attach a python dynamic attribute to wxColour for debug printouts
+ c._name = ctrl_kwargs[key]
+
+ elif type(ctrl_kwargs[key]) != type(wx.BLACK):
+ raise TypeError('%s not a legal color specification for %s' % (repr(ctrl_kwargs[key]), key))
+
+
+## dbg('self._retainFieldValidation:', self._retainFieldValidation)
+ if not self._retainFieldValidation:
+ # Build dictionary of any changing parameters which should be propagated to the
+ # component fields:
+ for arg in Field.propagating_params:
+#### dbg('kwargs.has_key(%s)?' % arg, kwargs.has_key(arg))
+#### dbg('getattr(self._ctrl_constraints, _%s)?' % arg, getattr(self._ctrl_constraints, '_'+arg))
+ reset_args[arg] = kwargs.has_key(arg) and kwargs[arg] != getattr(self._ctrl_constraints, '_'+arg)
+#### dbg('reset_args[%s]?' % arg, reset_args[arg])
+
+ # Set the control-level constraints:
+ self._ctrl_constraints._SetParameters(**constraint_kwargs)
+
+ # This routine does the bulk of the interdependent parameter processing, determining
+ # the field extents of the mask if changed, resetting parameters as appropriate,
+ # determining the overall template value for the control, etc.
+ self._configure(mask, **reset_args)
+
+ # now that we've propagated the field constraints and mask portions to the
+ # various fields, validate the constraints
+ self._ctrl_constraints._ValidateParameters(**constraint_kwargs)
+
+ # Validate that all choices for given fields are at least of the
+ # necessary length, and that they all would be valid pastes if pasted
+ # into their respective fields:
+#### dbg('validating choices')
+ self._validateChoices()
+
+
+ self._autofit = self._ctrl_constraints._autofit
+ self._isNeg = False
+
+ self._isDate = 'D' in self._ctrl_constraints._formatcodes and _isDateType(mask)
+ self._isTime = 'T' in self._ctrl_constraints._formatcodes and _isTimeType(mask)
+ if self._isDate:
+ # Set _dateExtent, used in date validation to locate date in string;
+ # always set as though year will be 4 digits, even if mask only has
+ # 2 digits, so we can always properly process the intended year for
+ # date validation (leap years, etc.)
+ if self._mask.find('CCC') != -1: self._dateExtent = 11
+ else: self._dateExtent = 10
+
+ self._4digityear = len(self._mask) > 8 and self._mask[9] == '#'
+
+ if self._isDate and self._autoformat:
+ # Auto-decide datestyle:
+ if self._autoformat.find('MDDY') != -1: self._datestyle = 'MDY'
+ elif self._autoformat.find('YMMD') != -1: self._datestyle = 'YMD'
+ elif self._autoformat.find('YMMMD') != -1: self._datestyle = 'YMD'
+ elif self._autoformat.find('DMMY') != -1: self._datestyle = 'DMY'
+ elif self._autoformat.find('DMMMY') != -1: self._datestyle = 'DMY'
+
+ # Give derived controls a chance to react to parameter changes before
+ # potentially changing current value of the control.
+ self._OnCtrlParametersChanged()
+
+ if self.controlInitialized:
+ # Then the base control is available for configuration;
+ # take action on base control based on new settings, as appropriate.
+ if kwargs.has_key('useFixedWidthFont'):
+ # Set control font - fixed width by default
+ self._setFont()
+
+ if reset_args.has_key('reset_mask'):
+## dbg('reset mask')
+ curvalue = self._GetValue()
+ if curvalue.strip():
+ try:
+## dbg('attempting to _SetInitialValue(%s)' % self._GetValue())
+ self._SetInitialValue(self._GetValue())
+ except Exception, e:
+## dbg('exception caught:', e)
+## dbg("current value doesn't work; attempting to reset to template")
+ self._SetInitialValue()
+ else:
+## dbg('attempting to _SetInitialValue() with template')
+ self._SetInitialValue()
+
+ elif kwargs.has_key('useParensForNegatives'):
+ newvalue = self._getSignedValue()[0]
+
+ if newvalue is not None:
+ # Adjust for new mask:
+ if len(newvalue) < len(self._mask):
+ newvalue += ' '
+ elif len(newvalue) > len(self._mask):
+ if newvalue[-1] in (' ', ')'):
+ newvalue = newvalue[:-1]
+
+## dbg('reconfiguring value for parens:"%s"' % newvalue)
+ self._SetValue(newvalue)
+
+ if self._prevValue != newvalue:
+ self._prevValue = newvalue # disallow undo of sign type
+
+ if self._autofit:
+## dbg('calculated size:', self._CalcSize())
+ self.SetClientSize(self._CalcSize())
+ width = self.GetSize().width
+ height = self.GetBestSize().height
+## dbg('setting client size to:', (width, height))
+ self.SetInitialSize((width, height))
+
+ # Set value/type-specific formatting
+ self._applyFormatting()
+## dbg(indent=0, suspend=0)
+
+ def SetMaskParameters(self, **kwargs):
+ """ old name for the SetCtrlParameters function (DEPRECATED)"""
+ return self.SetCtrlParameters(**kwargs)
+
+
+ def GetCtrlParameter(self, paramname):
+ """
+ Routine for retrieving the value of any given parameter
+ """
+ if MaskedEditMixin.valid_ctrl_params.has_key(paramname.replace('Color','Colour')):
+ return getattr(self, '_' + paramname.replace('Color', 'Colour'))
+ elif Field.valid_params.has_key(paramname):
+ return self._ctrl_constraints._GetParameter(paramname)
+ else:
+ TypeError('"%s".GetCtrlParameter: invalid parameter "%s"' % (self.name, paramname))
+
+ def GetMaskParameter(self, paramname):
+ """ old name for the GetCtrlParameters function (DEPRECATED)"""
+ return self.GetCtrlParameter(paramname)
+
+
+## This idea worked, but Boa was unable to use this solution...
+## def _attachMethod(self, func):
+## import new
+## setattr(self, func.__name__, new.instancemethod(func, self, self.__class__))
+##
+##
+## def _DefinePropertyFunctions(exposed_params):
+## for param in exposed_params:
+## propname = param[0].upper() + param[1:]
+##
+## exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
+## exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
+## self._attachMethod(locals()['Set%s' % propname])
+## self._attachMethod(locals()['Get%s' % propname])
+##
+## if param.find('Colour') != -1:
+## # add non-british spellings, for backward-compatibility
+## propname.replace('Colour', 'Color')
+##
+## exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
+## exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
+## self._attachMethod(locals()['Set%s' % propname])
+## self._attachMethod(locals()['Get%s' % propname])
+##
+
+
+ def SetFieldParameters(self, field_index, **kwargs):
+ """
+ Routine provided to modify the parameters of a given field.
+ Because changes to fields can affect the overall control,
+ direct access to the fields is prevented, and the control
+ is always "reconfigured" after setting a field parameter.
+ (See maskededit module overview for the list of valid field-level
+ parameters.)
+ """
+ if field_index not in self._field_indices:
+ ie = IndexError('%s is not a valid field for control "%s".' % (str(field_index), self.name))
+ ie.index = field_index
+ raise ie
+ # set parameters as requested:
+ self._fields[field_index]._SetParameters(**kwargs)
+
+ # Possibly reprogram control template due to resulting changes, and ensure
+ # control-level params are still propagated to fields:
+ self._configure(self._previous_mask)
+ self._fields[field_index]._ValidateParameters(**kwargs)
+
+ if self.controlInitialized:
+ if kwargs.has_key('fillChar') or kwargs.has_key('defaultValue'):
+ self._SetInitialValue()
+
+ if self._autofit:
+ # this is tricky, because, as Robin explains:
+ # "Basically there are two sizes to deal with, that are potentially
+ # different. The client size is the inside size and may, depending
+ # on platform, exclude the borders and such. The normal size is
+ # the outside size that does include the borders. What you are
+ # calculating (in _CalcSize) is the client size, but the sizers
+ # deal with the full size and so that is the minimum size that
+ # we need to set with SetInitialSize. The root of the problem is
+ # that in _calcSize the current client size height is returned,
+ # instead of a height based on the current font. So I suggest using
+ # _calcSize to just get the width, and then use GetBestSize to
+ # get the height."
+ self.SetClientSize(self._CalcSize())
+ width = self.GetSize().width
+ height = self.GetBestSize().height
+ self.SetInitialSize((width, height))
+
+
+ # Set value/type-specific formatting
+ self._applyFormatting()
+
+
+ def GetFieldParameter(self, field_index, paramname):
+ """
+ Routine provided for getting a parameter of an individual field.
+ """
+ if field_index not in self._field_indices:
+ ie = IndexError('%s is not a valid field for control "%s".' % (str(field_index), self.name))
+ ie.index = field_index
+ raise ie
+ elif Field.valid_params.has_key(paramname):
+ return self._fields[field_index]._GetParameter(paramname)
+ else:
+ ae = AttributeError('"%s".GetFieldParameter: invalid parameter "%s"' % (self.name, paramname))
+ ae.attribute = paramname
+ raise ae
+
+
+ def _SetKeycodeHandler(self, keycode, func):
+ """
+ This function adds and/or replaces key event handling functions
+ used by the control. <func> should take the event as argument
+ and return False if no further action on the key is necessary.
+ """
+ if func:
+ self._keyhandlers[keycode] = func
+ elif self._keyhandlers.has_key(keycode):
+ del self._keyhandlers[keycode]
+
+
+ def _SetKeyHandler(self, char, func):
+ """
+ This function adds and/or replaces key event handling functions
+ for ascii characters. <func> should take the event as argument
+ and return False if no further action on the key is necessary.
+ """
+ self._SetKeycodeHandler(ord(char), func)
+
+
+ def _AddNavKeycode(self, keycode, handler=None):
+ """
+ This function allows a derived subclass to augment the list of
+ keycodes that are considered "navigational" keys.
+ """
+ self._nav.append(keycode)
+ if handler:
+ self._keyhandlers[keycode] = handler
+ elif self.keyhandlers.has_key(keycode):
+ del self._keyhandlers[keycode]
+
+
+
+ def _AddNavKey(self, char, handler=None):
+ """
+ This function is a convenience function so you don't have to
+ remember to call ord() for ascii chars to be used for navigation.
+ """
+ self._AddNavKeycode(ord(char), handler)
+
+
+ def _GetNavKeycodes(self):
+ """
+ This function retrieves the current list of navigational keycodes for
+ the control.
+ """
+ return self._nav
+
+
+ def _SetNavKeycodes(self, keycode_func_tuples):
+ """
+ This function allows you to replace the current list of keycode processed
+ as navigation keys, and bind associated optional keyhandlers.
+ """
+ self._nav = []
+ for keycode, func in keycode_func_tuples:
+ self._nav.append(keycode)
+ if func:
+ self._keyhandlers[keycode] = func
+ elif self.keyhandlers.has_key(keycode):
+ del self._keyhandlers[keycode]
+
+
+ def _processMask(self, mask):
+ """
+ This subroutine expands {n} syntax in mask strings, and looks for escaped
+ special characters and returns the expanded mask, and an dictionary
+ of booleans indicating whether or not a given position in the mask is
+ a mask character or not.
+ """
+## dbg('_processMask: mask', mask, indent=1)
+ # regular expression for parsing c{n} syntax:
+ rex = re.compile('([' +string.join(maskchars,"") + '])\{(\d+)\}')
+ s = mask
+ match = rex.search(s)
+ while match: # found an(other) occurrence
+ maskchr = s[match.start(1):match.end(1)] # char to be repeated
+ repcount = int(s[match.start(2):match.end(2)]) # the number of times
+ replacement = string.join( maskchr * repcount, "") # the resulting substr
+ s = s[:match.start(1)] + replacement + s[match.end(2)+1:] #account for trailing '}'
+ match = rex.search(s) # look for another such entry in mask
+
+ self._decimalChar = self._ctrl_constraints._decimalChar
+ self._shiftDecimalChar = self._ctrl_constraints._shiftDecimalChar
+
+ self._isFloat = _isFloatingPoint(s) and not self._ctrl_constraints._validRegex
+ self._isInt = _isInteger(s) and not self._ctrl_constraints._validRegex
+ self._signOk = '-' in self._ctrl_constraints._formatcodes and (self._isFloat or self._isInt)
+ self._useParens = self._ctrl_constraints._useParensForNegatives
+ self._isNeg = False
+#### dbg('self._signOk?', self._signOk, 'self._useParens?', self._useParens)
+#### dbg('isFloatingPoint(%s)?' % (s), _isFloatingPoint(s),
+## 'ctrl regex:', self._ctrl_constraints._validRegex)
+
+ if self._signOk and s[0] != ' ':
+ s = ' ' + s
+ if self._ctrl_constraints._defaultValue and self._ctrl_constraints._defaultValue[0] != ' ':
+ self._ctrl_constraints._defaultValue = ' ' + self._ctrl_constraints._defaultValue
+ self._signpos = 0
+
+ if self._useParens:
+ s += ' '
+ self._ctrl_constraints._defaultValue += ' '
+
+
+ # Now, go build up a dictionary of booleans, indexed by position,
+ # indicating whether or not a given position is masked or not.
+ # Also, strip out any '|' chars, adjusting the mask as necessary,
+ # marking the appropriate positions for field boundaries:
+ ismasked = {}
+ explicit_field_boundaries = []
+ s = list(s)
+ i = 0
+ while i < len(s):
+ if s[i] == '\\': # if escaped character:
+ ismasked[i] = False # mark position as not a mask char
+ if i+1 < len(s): # if another char follows...
+ del s[i] # elide the '\'
+ if s[i] == '\\': # if next char also a '\', char is a literal '\'
+ del s[i] # elide the 2nd '\' as well
+ i += 1 # increment to next char
+ elif s[i] == '|':
+ del s[i] # elide the '|'
+ explicit_field_boundaries.append(i)
+ # keep index where it is:
+ else: # else if special char, mark position accordingly
+ ismasked[i] = s[i] in maskchars
+#### dbg('ismasked[%d]:' % i, ismasked[i], ''.join(s))
+ i += 1 # increment to next char
+#### dbg('ismasked:', ismasked)
+ s = ''.join(s)
+## dbg('new mask: "%s"' % s, indent=0)
+
+ return s, ismasked, explicit_field_boundaries
+
+
+ def _calcFieldExtents(self):
+ """
+ Subroutine responsible for establishing/configuring field instances with
+ indices and editable extents appropriate to the specified mask, and building
+ the lookup table mapping each position to the corresponding field.
+ """
+ self._lookupField = {}
+ if self._mask:
+
+ ## Create dictionary of positions,characters in mask
+ self.maskdict = {}
+ for charnum in range( len( self._mask)):
+ self.maskdict[charnum] = self._mask[charnum:charnum+1]
+
+ # For the current mask, create an ordered list of field extents
+ # and a dictionary of positions that map to field indices:
+
+ if self._signOk: start = 1
+ else: start = 0
+
+ if self._isFloat:
+ # Skip field "discovery", and just construct a 2-field control with appropriate
+ # constraints for a floating-point entry.
+
+ # .setdefault always constructs 2nd argument even if not needed, so we do this
+ # the old-fashioned way...
+ if not self._fields.has_key(0):
+ self._fields[0] = Field()
+ if not self._fields.has_key(1):
+ self._fields[1] = Field()
+
+ self._decimalpos = string.find( self._mask, '.')
+## dbg('decimal pos =', self._decimalpos)
+
+ formatcodes = self._fields[0]._GetParameter('formatcodes')
+ if 'R' not in formatcodes: formatcodes += 'R'
+ self._fields[0]._SetParameters(index=0, extent=(start, self._decimalpos),
+ mask=self._mask[start:self._decimalpos], formatcodes=formatcodes)
+ end = len(self._mask)
+ if self._signOk and self._useParens:
+ end -= 1
+ self._fields[1]._SetParameters(index=1, extent=(self._decimalpos+1, end),
+ mask=self._mask[self._decimalpos+1:end])
+
+ for i in range(self._decimalpos+1):
+ self._lookupField[i] = 0
+
+ for i in range(self._decimalpos+1, len(self._mask)+1):
+ self._lookupField[i] = 1
+
+ elif self._isInt:
+ # Skip field "discovery", and just construct a 1-field control with appropriate
+ # constraints for a integer entry.
+ if not self._fields.has_key(0):
+ self._fields[0] = Field(index=0)
+ end = len(self._mask)
+ if self._signOk and self._useParens:
+ end -= 1
+ self._fields[0]._SetParameters(index=0, extent=(start, end),
+ mask=self._mask[start:end])
+ for i in range(len(self._mask)+1):
+ self._lookupField[i] = 0
+ else:
+ # generic control; parse mask to figure out where the fields are:
+ field_index = 0
+ pos = 0
+ i = self._findNextEntry(pos,adjustInsert=False) # go to 1st entry point:
+ if i < len(self._mask): # no editable chars!
+ for j in range(pos, i+1):
+ self._lookupField[j] = field_index
+ pos = i # figure out field for 1st editable space:
+
+ while i <= len(self._mask):
+#### dbg('searching: outer field loop: i = ', i)
+ if self._isMaskChar(i):
+#### dbg('1st char is mask char; recording edit_start=', i)
+ edit_start = i
+ # Skip to end of editable part of current field:
+ while i < len(self._mask) and self._isMaskChar(i):
+ self._lookupField[i] = field_index
+ i += 1
+ if i in self._explicit_field_boundaries:
+ break
+#### dbg('edit_end =', i)
+ edit_end = i
+ self._lookupField[i] = field_index
+#### dbg('self._fields.has_key(%d)?' % field_index, self._fields.has_key(field_index))
+ if not self._fields.has_key(field_index):
+ kwargs = Field.valid_params.copy()
+ kwargs['index'] = field_index
+ kwargs['extent'] = (edit_start, edit_end)
+ kwargs['mask'] = self._mask[edit_start:edit_end]
+ self._fields[field_index] = Field(**kwargs)
+ else:
+ self._fields[field_index]._SetParameters(
+ index=field_index,
+ extent=(edit_start, edit_end),
+ mask=self._mask[edit_start:edit_end])
+ pos = i
+ i = self._findNextEntry(pos, adjustInsert=False) # go to next field:
+#### dbg('next entry:', i)
+ if i > pos:
+ for j in range(pos, i+1):
+ self._lookupField[j] = field_index
+ if i >= len(self._mask):
+ break # if past end, we're done
+ else:
+ field_index += 1
+#### dbg('next field:', field_index)
+
+ indices = self._fields.keys()
+ indices.sort()
+ self._field_indices = indices[1:]
+#### dbg('lookupField map:', indent=1)
+## for i in range(len(self._mask)):
+#### dbg('pos %d:' % i, self._lookupField[i])
+#### dbg(indent=0)
+
+ # Verify that all field indices specified are valid for mask:
+ for index in self._fields.keys():
+ if index not in [-1] + self._lookupField.values():
+ ie = IndexError('field %d is not a valid field for mask "%s"' % (index, self._mask))
+ ie.index = index
+ raise ie
+
+
+
+ def _calcTemplate(self, reset_fillchar, reset_default):
+ """
+ Subroutine for processing current fillchars and default values for
+ whole control and individual fields, constructing the resulting
+ overall template, and adjusting the current value as necessary.
+ """
+ default_set = False
+ if self._ctrl_constraints._defaultValue:
+ default_set = True
+ else:
+ for field in self._fields.values():
+ if field._defaultValue and not reset_default:
+ default_set = True
+## dbg('default set?', default_set)
+
+ # Determine overall new template for control, and keep track of previous
+ # values, so that current control value can be modified as appropriate:
+ if self.controlInitialized: curvalue = list(self._GetValue())
+ else: curvalue = None
+
+ if hasattr(self, '_fillChar'): old_fillchars = self._fillChar
+ else: old_fillchars = None
+
+ if hasattr(self, '_template'): old_template = self._template
+ else: old_template = None
+
+ self._template = ""
+
+ self._fillChar = {}
+ reset_value = False
+
+ for field in self._fields.values():
+ field._template = ""
+
+ for pos in range(len(self._mask)):
+#### dbg('pos:', pos)
+ field = self._FindField(pos)
+#### dbg('field:', field._index)
+ start, end = field._extent
+
+ if pos == 0 and self._signOk:
+ self._template = ' ' # always make 1st 1st position blank, regardless of fillchar
+ elif self._isFloat and pos == self._decimalpos:
+ self._template += self._decimalChar
+ elif self._isMaskChar(pos):
+ if field._fillChar != self._ctrl_constraints._fillChar and not reset_fillchar:
+ fillChar = field._fillChar
+ else:
+ fillChar = self._ctrl_constraints._fillChar
+ self._fillChar[pos] = fillChar
+
+ # Replace any current old fillchar with new one in current value;
+ # if action required, set reset_value flag so we can take that action
+ # after we're all done
+ if self.controlInitialized and old_fillchars and old_fillchars.has_key(pos) and curvalue:
+ if curvalue[pos] == old_fillchars[pos] and old_fillchars[pos] != fillChar:
+ reset_value = True
+ curvalue[pos] = fillChar
+
+ if not field._defaultValue and not self._ctrl_constraints._defaultValue:
+#### dbg('no default value')
+ self._template += fillChar
+ field._template += fillChar
+
+ elif field._defaultValue and not reset_default:
+#### dbg('len(field._defaultValue):', len(field._defaultValue))
+#### dbg('pos-start:', pos-start)
+ if len(field._defaultValue) > pos-start:
+#### dbg('field._defaultValue[pos-start]: "%s"' % field._defaultValue[pos-start])
+ self._template += field._defaultValue[pos-start]
+ field._template += field._defaultValue[pos-start]
+ else:
+#### dbg('field default not long enough; using fillChar')
+ self._template += fillChar
+ field._template += fillChar
+ else:
+ if len(self._ctrl_constraints._defaultValue) > pos:
+#### dbg('using control default')
+ self._template += self._ctrl_constraints._defaultValue[pos]
+ field._template += self._ctrl_constraints._defaultValue[pos]
+ else:
+#### dbg('ctrl default not long enough; using fillChar')
+ self._template += fillChar
+ field._template += fillChar
+#### dbg('field[%d]._template now "%s"' % (field._index, field._template))
+#### dbg('self._template now "%s"' % self._template)
+ else:
+ self._template += self._mask[pos]
+
+ self._fields[-1]._template = self._template # (for consistency)
+
+ if curvalue: # had an old value, put new one back together
+ newvalue = string.join(curvalue, "")
+ else:
+ newvalue = None
+
+ if default_set:
+ self._defaultValue = self._template
+## dbg('self._defaultValue:', self._defaultValue)
+ if not self.IsEmpty(self._defaultValue) and not self.IsValid(self._defaultValue):
+#### dbg(indent=0)
+ ve = ValueError('Default value of "%s" is not a valid value for control "%s"' % (self._defaultValue, self.name))
+ ve.value = self._defaultValue
+ raise ve
+
+ # if no fillchar change, but old value == old template, replace it:
+ if newvalue == old_template:
+ newvalue = self._template
+ reset_value = True
+ else:
+ self._defaultValue = None
+
+ if reset_value:
+## dbg('resetting value to: "%s"' % newvalue)
+ pos = self._GetInsertionPoint()
+ sel_start, sel_to = self._GetSelection()
+ self._SetValue(newvalue)
+ self._SetInsertionPoint(pos)
+ self._SetSelection(sel_start, sel_to)
+
+
+ def _propagateConstraints(self, **reset_args):
+ """
+ Subroutine for propagating changes to control-level constraints and
+ formatting to the individual fields as appropriate.
+ """
+ parent_codes = self._ctrl_constraints._formatcodes
+ parent_includes = self._ctrl_constraints._includeChars
+ parent_excludes = self._ctrl_constraints._excludeChars
+ for i in self._field_indices:
+ field = self._fields[i]
+ inherit_args = {}
+ if len(self._field_indices) == 1:
+ inherit_args['formatcodes'] = parent_codes
+ inherit_args['includeChars'] = parent_includes
+ inherit_args['excludeChars'] = parent_excludes
+ else:
+ field_codes = current_codes = field._GetParameter('formatcodes')
+ for c in parent_codes:
+ if c not in field_codes: field_codes += c
+ if field_codes != current_codes:
+ inherit_args['formatcodes'] = field_codes
+
+ include_chars = current_includes = field._GetParameter('includeChars')
+ for c in parent_includes:
+ if not c in include_chars: include_chars += c
+ if include_chars != current_includes:
+ inherit_args['includeChars'] = include_chars
+
+ exclude_chars = current_excludes = field._GetParameter('excludeChars')
+ for c in parent_excludes:
+ if not c in exclude_chars: exclude_chars += c
+ if exclude_chars != current_excludes:
+ inherit_args['excludeChars'] = exclude_chars
+
+ if reset_args.has_key('defaultValue') and reset_args['defaultValue']:
+ inherit_args['defaultValue'] = "" # (reset for field)
+
+ for param in Field.propagating_params:
+#### dbg('reset_args.has_key(%s)?' % param, reset_args.has_key(param))
+#### dbg('reset_args.has_key(%(param)s) and reset_args[%(param)s]?' % locals(), reset_args.has_key(param) and reset_args[param])
+ if reset_args.has_key(param):
+ inherit_args[param] = self.GetCtrlParameter(param)
+#### dbg('inherit_args[%s]' % param, inherit_args[param])
+
+ if inherit_args:
+ field._SetParameters(**inherit_args)
+ field._ValidateParameters(**inherit_args)
+
+
+ def _validateChoices(self):
+ """
+ Subroutine that validates that all choices for given fields are at
+ least of the necessary length, and that they all would be valid pastes
+ if pasted into their respective fields.
+ """
+ for field in self._fields.values():
+ if field._choices:
+ index = field._index
+ if len(self._field_indices) == 1 and index == 0 and field._choices == self._ctrl_constraints._choices:
+## dbg('skipping (duplicate) choice validation of field 0')
+ continue
+#### dbg('checking for choices for field', field._index)
+ start, end = field._extent
+ field_length = end - start
+#### dbg('start, end, length:', start, end, field_length)
+ for choice in field._choices:
+#### dbg('testing "%s"' % choice)
+ valid_paste, ignore, replace_to = self._validatePaste(choice, start, end)
+ if not valid_paste:
+#### dbg(indent=0)
+ ve = ValueError('"%s" could not be entered into field %d of control "%s"' % (choice, index, self.name))
+ ve.value = choice
+ ve.index = index
+ raise ve
+ elif replace_to > end:
+#### dbg(indent=0)
+ ve = ValueError('"%s" will not fit into field %d of control "%s"' (choice, index, self.name))
+ ve.value = choice
+ ve.index = index
+ raise ve
+
+#### dbg(choice, 'valid in field', index)
+
+
+ def _configure(self, mask, **reset_args):
+ """
+ This function sets flags for automatic styling options. It is
+ called whenever a control or field-level parameter is set/changed.
+
+ This routine does the bulk of the interdependent parameter processing, determining
+ the field extents of the mask if changed, resetting parameters as appropriate,
+ determining the overall template value for the control, etc.
+
+ reset_args is supplied if called from control's .SetCtrlParameters()
+ routine, and indicates which if any parameters which can be
+ overridden by individual fields have been reset by request for the
+ whole control.
+
+ """
+## dbg(suspend=1)
+## dbg('MaskedEditMixin::_configure("%s")' % mask, indent=1)
+
+ # Preprocess specified mask to expand {n} syntax, handle escaped
+ # mask characters, etc and build the resulting positionally keyed
+ # dictionary for which positions are mask vs. template characters:
+ self._mask, self._ismasked, self._explicit_field_boundaries = self._processMask(mask)
+ self._masklength = len(self._mask)
+#### dbg('processed mask:', self._mask)
+
+ # Preserve original mask specified, for subsequent reprocessing
+ # if parameters change.
+## dbg('mask: "%s"' % self._mask, 'previous mask: "%s"' % self._previous_mask)
+ self._previous_mask = mask # save unexpanded mask for next time
+ # Set expanded mask and extent of field -1 to width of entire control:
+ self._ctrl_constraints._SetParameters(mask = self._mask, extent=(0,self._masklength))
+
+ # Go parse mask to determine where each field is, construct field
+ # instances as necessary, configure them with those extents, and
+ # build lookup table mapping each position for control to its corresponding
+ # field.
+#### dbg('calculating field extents')
+
+ self._calcFieldExtents()
+
+
+ # Go process defaultValues and fillchars to construct the overall
+ # template, and adjust the current value as necessary:
+ reset_fillchar = reset_args.has_key('fillChar') and reset_args['fillChar']
+ reset_default = reset_args.has_key('defaultValue') and reset_args['defaultValue']
+
+#### dbg('calculating template')
+ self._calcTemplate(reset_fillchar, reset_default)
+
+ # Propagate control-level formatting and character constraints to each
+ # field if they don't already have them; if only one field, propagate
+ # control-level validation constraints to field as well:
+#### dbg('propagating constraints')
+ self._propagateConstraints(**reset_args)
+
+
+ if self._isFloat and self._fields[0]._groupChar == self._decimalChar:
+ raise AttributeError('groupChar (%s) and decimalChar (%s) must be distinct.' %
+ (self._fields[0]._groupChar, self._decimalChar) )
+
+#### dbg('fields:', indent=1)
+## for i in [-1] + self._field_indices:
+#### dbg('field %d:' % i, self._fields[i].__dict__)
+#### dbg(indent=0)
+
+ # Set up special parameters for numeric control, if appropriate:
+ if self._signOk:
+ self._signpos = 0 # assume it starts here, but it will move around on floats
+ signkeys = ['-', '+', ' ']
+ if self._useParens:
+ signkeys += ['(', ')']
+ for key in signkeys:
+ keycode = ord(key)
+ if not self._keyhandlers.has_key(keycode):
+ self._SetKeyHandler(key, self._OnChangeSign)
+ elif self._isInt or self._isFloat:
+ signkeys = ['-', '+', ' ', '(', ')']
+ for key in signkeys:
+ keycode = ord(key)
+ if self._keyhandlers.has_key(keycode) and self._keyhandlers[keycode] == self._OnChangeSign:
+ self._SetKeyHandler(key, None)
+
+
+
+ if self._isFloat or self._isInt:
+ if self.controlInitialized:
+ value = self._GetValue()
+#### dbg('value: "%s"' % value, 'len(value):', len(value),
+## 'len(self._ctrl_constraints._mask):',len(self._ctrl_constraints._mask))
+ if len(value) < len(self._ctrl_constraints._mask):
+ newvalue = value
+ if self._useParens and len(newvalue) < len(self._ctrl_constraints._mask) and newvalue.find('(') == -1:
+ newvalue += ' '
+ if self._signOk and len(newvalue) < len(self._ctrl_constraints._mask) and newvalue.find(')') == -1:
+ newvalue = ' ' + newvalue
+ if len(newvalue) < len(self._ctrl_constraints._mask):
+ if self._ctrl_constraints._alignRight:
+ newvalue = newvalue.rjust(len(self._ctrl_constraints._mask))
+ else:
+ newvalue = newvalue.ljust(len(self._ctrl_constraints._mask))
+## dbg('old value: "%s"' % value)
+## dbg('new value: "%s"' % newvalue)
+ try:
+ self._ChangeValue(newvalue)
+ except Exception, e:
+## dbg('exception raised:', e, 'resetting to initial value')
+ self._SetInitialValue()
+
+ elif len(value) > len(self._ctrl_constraints._mask):
+ newvalue = value
+ if not self._useParens and newvalue[-1] == ' ':
+ newvalue = newvalue[:-1]
+ if not self._signOk and len(newvalue) > len(self._ctrl_constraints._mask):
+ newvalue = newvalue[1:]
+ if not self._signOk:
+ newvalue, signpos, right_signpos = self._getSignedValue(newvalue)
+
+## dbg('old value: "%s"' % value)
+## dbg('new value: "%s"' % newvalue)
+ try:
+ self._ChangeValue(newvalue)
+ except Exception, e:
+## dbg('exception raised:', e, 'resetting to initial value')
+ self._SetInitialValue()
+ elif not self._signOk and ('(' in value or '-' in value):
+ newvalue, signpos, right_signpos = self._getSignedValue(value)
+## dbg('old value: "%s"' % value)
+## dbg('new value: "%s"' % newvalue)
+ try:
+ self._ChangeValue(newvalue)
+ except e:
+## dbg('exception raised:', e, 'resetting to initial value')
+ self._SetInitialValue()
+
+ # Replace up/down arrow default handling:
+ # make down act like tab, up act like shift-tab:
+
+#### dbg('Registering numeric navigation and control handlers (if not already set)')
+ if not self._keyhandlers.has_key(wx.WXK_DOWN):
+ self._SetKeycodeHandler(wx.WXK_DOWN, self._OnChangeField)
+ if not self._keyhandlers.has_key(wx.WXK_NUMPAD_DOWN):
+ self._SetKeycodeHandler(wx.WXK_DOWN, self._OnChangeField)
+ if not self._keyhandlers.has_key(wx.WXK_UP):
+ self._SetKeycodeHandler(wx.WXK_UP, self._OnUpNumeric) # (adds "shift" to up arrow, and calls _OnChangeField)
+ if not self._keyhandlers.has_key(wx.WXK_NUMPAD_UP):
+ self._SetKeycodeHandler(wx.WXK_UP, self._OnUpNumeric) # (adds "shift" to up arrow, and calls _OnChangeField)
+
+ # On ., truncate contents right of cursor to decimal point (if any)
+ # leaves cursor after decimal point if floating point, otherwise at 0.
+ if not self._keyhandlers.has_key(ord(self._decimalChar)) or self._keyhandlers[ord(self._decimalChar)] != self._OnDecimalPoint:
+ self._SetKeyHandler(self._decimalChar, self._OnDecimalPoint)
+
+ if not self._keyhandlers.has_key(ord(self._shiftDecimalChar)) or self._keyhandlers[ord(self._shiftDecimalChar)] != self._OnChangeField:
+ self._SetKeyHandler(self._shiftDecimalChar, self._OnChangeField) # (Shift-'.' == '>' on US keyboards)
+
+ # Allow selective insert of groupchar in numbers:
+ if not self._keyhandlers.has_key(ord(self._fields[0]._groupChar)) or self._keyhandlers[ord(self._fields[0]._groupChar)] != self._OnGroupChar:
+ self._SetKeyHandler(self._fields[0]._groupChar, self._OnGroupChar)
+
+## dbg(indent=0, suspend=0)
+
+
+ def _SetInitialValue(self, value=""):
+ """
+ fills the control with the generated or supplied default value.
+ It will also set/reset the font if necessary and apply
+ formatting to the control at this time.
+ """
+## dbg('MaskedEditMixin::_SetInitialValue("%s")' % value, indent=1)
+ if not value:
+ self._prevValue = self._curValue = self._template
+ # don't apply external validation rules in this case, as template may
+ # not coincide with "legal" value...
+ try:
+ if isinstance(self, wx.TextCtrl):
+ self._ChangeValue(self._curValue) # note the use of "raw" ._ChangeValue()...
+ else:
+ self._SetValue(self._curValue) # note the use of "raw" ._SetValue()...
+ except Exception, e:
+## dbg('exception thrown:', e, indent=0)
+ raise
+ else:
+ # Otherwise apply validation as appropriate to passed value:
+#### dbg('value = "%s", length:' % value, len(value))
+ self._prevValue = self._curValue = value
+ try:
+ if isinstance(self, wx.TextCtrl):
+ self.ChangeValue(value) # use public (validating) .SetValue()
+ else:
+ self.SetValue(value)
+ except Exception, e:
+## dbg('exception thrown:', e, indent=0)
+ raise
+
+
+ # Set value/type-specific formatting
+ self._applyFormatting()
+## dbg(indent=0)
+
+
+ def _calcSize(self, size=None):
+ """ Calculate automatic size if allowed; must be called after the base control is instantiated"""
+#### dbg('MaskedEditMixin::_calcSize', indent=1)
+ cont = (size is None or size == wx.DefaultSize)
+
+ if cont and self._autofit:
+#### dbg('isinstance(self, wx.lib.masked.numctrl.NumCtrl): "%s"' % self.__class__)
+ # sizing of numctrl when using proportional font and
+ # wxPython 2.9 is not working when using "M"
+ # GetTextExtent returns a width which is way to large
+ # instead we use '9' for numctrl and a selection of
+ # characters instead of just 'M' for textctrl and combobox
+ # where the mask is larger then 10 characters long
+ if isinstance(self, wx.lib.masked.numctrl.NumCtrl):
+ sizing_text = '9' * self._masklength
+ wAdjust = 8
+ elif isinstance(self, wx.lib.masked.combobox.ComboBox):
+ if self._masklength > 10:
+ tC, sC = divmod(self._masklength, 10.0)
+ sizing_text = 'FDSJKLREUI' * int(tC)
+ sizing_text += 'M' * int(sC)
+ wAdjust = 26
+ else:
+ sizing_text = ""
+ for cn in range(self._masklength):
+ if cn % 2:
+ sizing_text += "M"
+ else:
+ sizing_text += "I"
+ wAdjust = 4
+ else:
+ if self._masklength > 10:
+ tC, sC = divmod(self._masklength, 10.0)
+ sizing_text = 'FDSJKLREUI' * int(tC)
+ sizing_text += 'M' * int(sC)
+ else:
+ sizing_text = ""
+ for cn in range(self._masklength):
+ if cn % 2:
+ sizing_text += "M"
+ else:
+ sizing_text += "I"
+ wAdjust = 4
+ if wx.Platform != "__WXMSW__": # give it a little extra space
+ sizing_text += 'M'
+ if wx.Platform == "__WXMAC__": # give it even a little more...
+ sizing_text += 'M'
+#### dbg('len(sizing_text):', len(sizing_text), 'sizing_text: "%s"' % sizing_text)
+ w, h = self.GetTextExtent(sizing_text)
+ size = (w+wAdjust, self.GetSize().height)
+#### dbg('size:', size, indent=0)
+ return size
+
+
+ def _setFont(self):
+ """ Set the control's font typeface -- pass the font name as str."""
+#### dbg('MaskedEditMixin::_setFont', indent=1)
+ if not self._useFixedWidthFont:
+ self._font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ else:
+ font = self.GetFont() # get size, weight, etc from current font
+ points = font.GetPointSize()
+ if 'wxMac' in wx.PlatformInfo \
+ and self.GetWindowVariant() == wx.WINDOW_VARIANT_MINI:
+ points -= 1
+
+ # Set to teletype font (guaranteed to be mappable to all wxWindows
+ # platforms:
+ self._font = wx.Font( points, wx.TELETYPE, font.GetStyle(),
+ font.GetWeight(), font.GetUnderlined())
+#### dbg('font string: "%s"' % font.GetNativeFontInfo().ToString())
+
+ self.SetFont(self._font)
+#### dbg(indent=0)
+
+
+ def _OnTextChange(self, event):
+ """
+ Handler for EVT_TEXT event.
+ self._Change() is provided for subclasses, and may return False to
+ skip this method logic. This function returns True if the event
+ detected was a legitimate event, or False if it was a "bogus"
+ EVT_TEXT event. (NOTE: There is currently an issue with calling
+ .SetValue from within the EVT_CHAR handler that causes duplicate
+ EVT_TEXT events for the same change.)
+ """
+ newvalue = self._GetValue()
+## dbg('MaskedEditMixin::_OnTextChange: value: "%s"' % newvalue, indent=1)
+ bValid = False
+ if self._ignoreChange: # ie. if an "intermediate text change event"
+## dbg(indent=0)
+ return bValid
+
+ ##! WS: For some inexplicable reason, every wx.TextCtrl.SetValue
+ ## call is generating two (2) EVT_TEXT events. On certain platforms,
+ ## (eg. linux/GTK) the 1st is an empty string value.
+ ## This is the only mechanism I can find to mask this problem:
+ if newvalue == self._curValue or len(newvalue) == 0:
+## dbg('ignoring bogus text change event', indent=0)
+ pass
+ else:
+## dbg('curvalue: "%s", newvalue: "%s", len(newvalue): %d' % (self._curValue, newvalue, len(newvalue)))
+ if self._Change():
+ if self._signOk and self._isNeg and newvalue.find('-') == -1 and newvalue.find('(') == -1:
+## dbg('clearing self._isNeg')
+ self._isNeg = False
+ text, self._signpos, self._right_signpos = self._getSignedValue()
+ self._CheckValid() # Recolor control as appropriate
+## dbg('calling event.Skip()')
+ event.Skip()
+ bValid = True
+ self._prevValue = self._curValue # save for undo
+ self._curValue = newvalue # Save last seen value for next iteration
+## dbg(indent=0)
+ return bValid
+
+
+ def _OnKeyDown(self, event):
+ """
+ This function allows the control to capture Ctrl-events like Ctrl-tab,
+ that are not normally seen by the "cooked" EVT_CHAR routine.
+ """
+ # Get keypress value, adjusted by control options (e.g. convert to upper etc)
+ key = event.GetKeyCode()
+ if key in self._nav and event.ControlDown():
+ # then this is the only place we will likely see these events;
+ # process them now:
+## dbg('MaskedEditMixin::OnKeyDown: calling _OnChar')
+ self._OnChar(event)
+ return
+ # else allow regular EVT_CHAR key processing
+ event.Skip()
+
+
+ def _OnChar(self, event):
+ """
+ This is the engine of MaskedEdit controls. It examines each keystroke,
+ decides if it's allowed, where it should go or what action to take.
+ """
+## dbg('MaskedEditMixin::_OnChar', indent=1)
+
+ # Get keypress value, adjusted by control options (e.g. convert to upper etc)
+ key = event.GetKeyCode()
+ orig_pos = self._GetInsertionPoint()
+ orig_value = self._GetValue()
+## dbg('keycode = ', key)
+## dbg('current pos = ', orig_pos)
+## dbg('current selection = ', self._GetSelection())
+
+ if not self._Keypress(key):
+## dbg(indent=0)
+ return
+
+ # If no format string for this control, or the control is marked as "read-only",
+ # skip the rest of the special processing, and just "do the standard thing:"
+ if not self._mask or not self._IsEditable():
+ event.Skip()
+## dbg(indent=0)
+ return
+
+ # Process navigation and control keys first, with
+ # position/selection unadulterated:
+ if key in self._nav + self._control:
+ if self._keyhandlers.has_key(key):
+ keep_processing = self._keyhandlers[key](event)
+ if self._GetValue() != orig_value:
+ self.modified = True
+ if not keep_processing:
+## dbg(indent=0)
+ return
+ self._applyFormatting()
+## dbg(indent=0)
+ return
+
+ # Else... adjust the position as necessary for next input key,
+ # and determine resulting selection:
+ pos = self._adjustPos( orig_pos, key ) ## get insertion position, adjusted as needed
+ sel_start, sel_to = self._GetSelection() ## check for a range of selected text
+## dbg("pos, sel_start, sel_to:", pos, sel_start, sel_to)
+
+ keep_processing = True
+ # Capture user past end of format field
+ if pos > len(self.maskdict):
+## dbg("field length exceeded:",pos)
+ keep_processing = False
+
+ key = self._adjustKey(pos, key) # apply formatting constraints to key:
+
+ if self._keyhandlers.has_key(key):
+ # there's an override for default behavior; use override function instead
+## dbg('using supplied key handler:', self._keyhandlers[key])
+ keep_processing = self._keyhandlers[key](event)
+ if self._GetValue() != orig_value:
+ self.modified = True
+ if not keep_processing:
+## dbg(indent=0)
+ return
+ # else skip default processing, but do final formatting
+ if key in wx_control_keycodes:
+## dbg('key in wx_control_keycodes')
+ event.Skip() # non-printable; let base control handle it
+ keep_processing = False
+ else:
+ field = self._FindField(pos)
+
+ if 'unicode' in wx.PlatformInfo:
+ if key < 256:
+ char = chr(key) # (must work if we got this far)
+ char = char.decode(self._defaultEncoding)
+ else:
+ char = unichr(event.GetUnicodeKey())
+## dbg('unicode char:', char)
+ excludes = u''
+ if type(field._excludeChars) != types.UnicodeType:
+ excludes += field._excludeChars.decode(self._defaultEncoding)
+ if type(self._ctrl_constraints) != types.UnicodeType:
+ excludes += self._ctrl_constraints._excludeChars.decode(self._defaultEncoding)
+ else:
+ char = chr(key) # (must work if we got this far)
+ excludes = field._excludeChars + self._ctrl_constraints._excludeChars
+
+## dbg("key ='%s'" % chr(key))
+ if chr(key) == ' ':
+## dbg('okSpaces?', field._okSpaces)
+ pass
+
+
+ if char in excludes:
+ keep_processing = False
+
+ if keep_processing and self._isCharAllowed( char, pos, checkRegex = True ):
+## dbg("key allowed by mask")
+ # insert key into candidate new value, but don't change control yet:
+ oldstr = self._GetValue()
+ newstr, newpos, new_select_to, match_field, match_index = self._insertKey(
+ char, pos, sel_start, sel_to, self._GetValue(), allowAutoSelect = True)
+## dbg("str with '%s' inserted:" % char, '"%s"' % newstr)
+ if self._ctrl_constraints._validRequired and not self.IsValid(newstr):
+## dbg('not valid; checking to see if adjusted string is:')
+ keep_processing = False
+ if self._isFloat and newstr != self._template:
+ newstr = self._adjustFloat(newstr)
+## dbg('adjusted str:', newstr)
+ if self.IsValid(newstr):
+## dbg("it is!")
+ keep_processing = True
+ wx.CallAfter(self._SetInsertionPoint, self._decimalpos)
+ if not keep_processing:
+## dbg("key disallowed by validation")
+ if not wx.Validator_IsSilent() and orig_pos == pos:
+ wx.Bell()
+
+ if keep_processing:
+ unadjusted = newstr
+
+ # special case: adjust date value as necessary:
+ if self._isDate and newstr != self._template:
+ newstr = self._adjustDate(newstr)
+## dbg('adjusted newstr:', newstr)
+
+ if newstr != orig_value:
+ self.modified = True
+
+ wx.CallAfter(self._SetValue, newstr)
+
+ # Adjust insertion point on date if just entered 2 digit year, and there are now 4 digits:
+ if not self.IsDefault() and self._isDate and self._4digityear:
+ year2dig = self._dateExtent - 2
+ if pos == year2dig and unadjusted[year2dig] != newstr[year2dig]:
+ newpos = pos+2
+
+## dbg('queuing insertion point: (%d)' % newpos)
+ wx.CallAfter(self._SetInsertionPoint, newpos)
+
+ if match_field is not None:
+## dbg('matched field')
+ self._OnAutoSelect(match_field, match_index)
+
+ if new_select_to != newpos:
+## dbg('queuing selection: (%d, %d)' % (newpos, new_select_to))
+ wx.CallAfter(self._SetSelection, newpos, new_select_to)
+ else:
+ newfield = self._FindField(newpos)
+ if newfield != field and newfield._selectOnFieldEntry:
+## dbg('queuing insertion point: (%d)' % newfield._extent[0])
+ wx.CallAfter(self._SetInsertionPoint, newfield._extent[0])
+## dbg('queuing selection: (%d, %d)' % (newfield._extent[0], newfield._extent[1]))
+ wx.CallAfter(self._SetSelection, newfield._extent[0], newfield._extent[1])
+ else:
+ wx.CallAfter(self._SetSelection, newpos, new_select_to)
+ keep_processing = False
+
+ elif keep_processing:
+## dbg('char not allowed')
+ keep_processing = False
+ if (not wx.Validator_IsSilent()) and orig_pos == pos:
+ wx.Bell()
+
+ self._applyFormatting()
+
+ # Move to next insertion point
+ if keep_processing and key not in self._nav:
+ pos = self._GetInsertionPoint()
+ next_entry = self._findNextEntry( pos )
+ if pos != next_entry:
+## dbg("moving from %(pos)d to next valid entry: %(next_entry)d" % locals())
+ wx.CallAfter(self._SetInsertionPoint, next_entry )
+
+ if self._isTemplateChar(pos):
+ self._AdjustField(pos)
+## dbg(indent=0)
+
+
+ def _FindFieldExtent(self, pos=None, getslice=False, value=None):
+ """ returns editable extent of field corresponding to
+ position pos, and, optionally, the contents of that field
+ in the control or the value specified.
+ Template chars are bound to the preceding field.
+ For masks beginning with template chars, these chars are ignored
+ when calculating the current field.
+
+ Eg: with template (###) ###-####,
+ >>> self._FindFieldExtent(pos=0)
+ 1, 4
+ >>> self._FindFieldExtent(pos=1)
+ 1, 4
+ >>> self._FindFieldExtent(pos=5)
+ 1, 4
+ >>> self._FindFieldExtent(pos=6)
+ 6, 9
+ >>> self._FindFieldExtent(pos=10)
+ 10, 14
+ etc.
+ """
+## dbg('MaskedEditMixin::_FindFieldExtent(pos=%s, getslice=%s)' % (str(pos), str(getslice)) ,indent=1)
+
+ field = self._FindField(pos)
+ if not field:
+ if getslice:
+ return None, None, ""
+ else:
+ return None, None
+ edit_start, edit_end = field._extent
+ if getslice:
+ if value is None: value = self._GetValue()
+ slice = value[edit_start:edit_end]
+## dbg('edit_start:', edit_start, 'edit_end:', edit_end, 'slice: "%s"' % slice)
+## dbg(indent=0)
+ return edit_start, edit_end, slice
+ else:
+## dbg('edit_start:', edit_start, 'edit_end:', edit_end)
+## dbg(indent=0)
+ return edit_start, edit_end
+
+
+ def _FindField(self, pos=None):
+ """
+ Returns the field instance in which pos resides.
+ Template chars are bound to the preceding field.
+ For masks beginning with template chars, these chars are ignored
+ when calculating the current field.
+
+ """
+#### dbg('MaskedEditMixin::_FindField(pos=%s)' % str(pos) ,indent=1)
+ if pos is None: pos = self._GetInsertionPoint()
+ elif pos < 0 or pos > self._masklength:
+ raise IndexError('position %s out of range of control' % str(pos))
+
+ if len(self._fields) == 0:
+## dbg(indent=0)
+ return None
+
+ # else...
+#### dbg(indent=0)
+ return self._fields[self._lookupField[pos]]
+
+
+ def ClearValue(self):
+ """ Blanks the current control value by replacing it with the default value."""
+## dbg("MaskedEditMixin::ClearValue - value reset to default value (template)")
+ self._SetValue( self._template )
+ self._SetInsertionPoint(0)
+ self.Refresh()
+
+ def ClearValueAlt(self):
+ """ Blanks the current control value by replacing it with the default value.
+ Using ChangeValue, so not to fire a change event"""
+## dbg("MaskedEditMixin::ClearValueAlt - value reset to default value (template)")
+ self._ChangeValue( self._template )
+ self._SetInsertionPoint(0)
+ self.Refresh()
+
+ def _baseCtrlEventHandler(self, event):
+ """
+ This function is used whenever a key should be handled by the base control.
+ """
+ event.Skip()
+ return False
+
+
+ def _OnUpNumeric(self, event):
+ """
+ Makes up-arrow act like shift-tab should; ie. take you to start of
+ previous field.
+ """
+## dbg('MaskedEditMixin::_OnUpNumeric', indent=1)
+ event.shiftDown = 1
+## dbg('event.ShiftDown()?', event.ShiftDown())
+ self._OnChangeField(event)
+## dbg(indent=0)
+
+
+ def _OnArrow(self, event):
+ """
+ Used in response to left/right navigation keys; makes these actions skip
+ over mask template chars.
+ """
+## dbg("MaskedEditMixin::_OnArrow", indent=1)
+ pos = self._GetInsertionPoint()
+ keycode = event.GetKeyCode()
+ sel_start, sel_to = self._GetSelection()
+ entry_end = self._goEnd(getPosOnly=True)
+ if keycode in (wx.WXK_RIGHT, wx.WXK_DOWN, wx.WXK_NUMPAD_RIGHT, wx.WXK_NUMPAD_DOWN):
+ if( ( not self._isTemplateChar(pos) and pos+1 > entry_end)
+ or ( self._isTemplateChar(pos) and pos >= entry_end) ):
+## dbg("can't advance", indent=0)
+ return False
+ elif self._isTemplateChar(pos):
+ self._AdjustField(pos)
+ elif keycode in (wx.WXK_LEFT, wx.WXK_UP, wx.WXK_NUMPAD_LEFT, wx.WXK_NUMPAD_UP) and sel_start == sel_to and pos > 0 and self._isTemplateChar(pos-1):
+## dbg('adjusting field')
+ self._AdjustField(pos)
+
+ # treat as shifted up/down arrows as tab/reverse tab:
+ if event.ShiftDown() and keycode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_DOWN):
+ # remove "shifting" and treat as (forward) tab:
+ event.shiftDown = False
+ keep_processing = self._OnChangeField(event)
+
+ elif self._FindField(pos)._selectOnFieldEntry:
+ if( keycode in (wx.WXK_UP, wx.WXK_LEFT, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_LEFT)
+ and sel_start != 0
+ and self._isTemplateChar(sel_start-1)
+ and sel_start != self._masklength
+ and not self._signOk and not self._useParens):
+
+ # call _OnChangeField to handle "ctrl-shifted event"
+ # (which moves to previous field and selects it.)
+ event.shiftDown = True
+ event.sontrolDown = True
+ keep_processing = self._OnChangeField(event)
+ elif( keycode in (wx.WXK_DOWN, wx.WXK_RIGHT, wx.WXK_NUMPAD_DOWN, wx.WXK_NUMPAD_RIGHT)
+ and sel_to != self._masklength
+ and self._isTemplateChar(sel_to)):
+
+ # when changing field to the right, ensure don't accidentally go left instead
+ event.shiftDown = False
+ keep_processing = self._OnChangeField(event)
+ else:
+ # treat arrows as normal, allowing selection
+ # as appropriate:
+## dbg('using base ctrl event processing')
+ event.Skip()
+ else:
+ if( (sel_to == self._fields[0]._extent[0] and keycode in (wx.WXK_LEFT, wx.WXK_NUMPAD_LEFT) )
+ or (sel_to == self._masklength and keycode in (wx.WXK_RIGHT, wx.WXK_NUMPAD_RIGHT) ) ):
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+ else:
+ # treat arrows as normal, allowing selection
+ # as appropriate:
+## dbg('using base event processing')
+ event.Skip()
+
+ keep_processing = False
+## dbg(indent=0)
+ return keep_processing
+
+
+ def _OnCtrl_S(self, event):
+ """ Default Ctrl-S handler; prints value information if demo enabled. """
+## dbg("MaskedEditMixin::_OnCtrl_S")
+ if self._demo:
+ print 'MaskedEditMixin.GetValue() = "%s"\nMaskedEditMixin.GetPlainValue() = "%s"' % (self.GetValue(), self.GetPlainValue())
+ print "Valid? => " + str(self.IsValid())
+ print "Current field, start, end, value =", str( self._FindFieldExtent(getslice=True))
+ return False
+
+
+ def _OnCtrl_X(self, event=None):
+ """ Handles ctrl-x keypress in control and Cut operation on context menu.
+ Should return False to skip other processing. """
+## dbg("MaskedEditMixin::_OnCtrl_X", indent=1)
+ self.Cut()
+## dbg(indent=0)
+ return False
+
+ def _OnCtrl_C(self, event=None):
+ """ Handles ctrl-C keypress in control and Copy operation on context menu.
+ Uses base control handling. Should return False to skip other processing."""
+ self.Copy()
+ return False
+
+ def _OnCtrl_V(self, event=None):
+ """ Handles ctrl-V keypress in control and Paste operation on context menu.
+ Should return False to skip other processing. """
+## dbg("MaskedEditMixin::_OnCtrl_V", indent=1)
+ self.Paste()
+## dbg(indent=0)
+ return False
+
+ def _OnInsert(self, event=None):
+ """ Handles shift-insert and control-insert operations (paste and copy, respectively)"""
+## dbg("MaskedEditMixin::_OnInsert", indent=1)
+ if event and isinstance(event, wx.KeyEvent):
+ if event.ShiftDown():
+ self.Paste()
+ elif event.ControlDown():
+ self.Copy()
+ # (else do nothing)
+ # (else do nothing)
+## dbg(indent=0)
+ return False
+
+ def _OnDelete(self, event=None):
+ """ Handles shift-delete and delete operations (cut and erase, respectively)"""
+## dbg("MaskedEditMixin::_OnDelete", indent=1)
+ if event and isinstance(event, wx.KeyEvent):
+ if event.ShiftDown():
+ self.Cut()
+ else:
+ self._OnErase(event)
+ else:
+ self._OnErase(event)
+## dbg(indent=0)
+ return False
+
+ def _OnCtrl_Z(self, event=None):
+ """ Handles ctrl-Z keypress in control and Undo operation on context menu.
+ Should return False to skip other processing. """
+## dbg("MaskedEditMixin::_OnCtrl_Z", indent=1)
+ self.Undo()
+## dbg(indent=0)
+ return False
+
+ def _OnCtrl_A(self,event=None):
+ """ Handles ctrl-a keypress in control. Should return False to skip other processing. """
+ end = self._goEnd(getPosOnly=True)
+ if not event or (isinstance(event, wx.KeyEvent) and event.ShiftDown()):
+ wx.CallAfter(self._SetInsertionPoint, 0)
+ wx.CallAfter(self._SetSelection, 0, self._masklength)
+ else:
+ wx.CallAfter(self._SetInsertionPoint, 0)
+ wx.CallAfter(self._SetSelection, 0, end)
+ return False
+
+
+ def _OnErase(self, event=None, just_return_value=False):
+ """ Handles backspace and delete keypress in control. Should return False to skip other processing."""
+## dbg("MaskedEditMixin::_OnErase", indent=1)
+ sel_start, sel_to = self._GetSelection() ## check for a range of selected text
+
+ if event is None: # called as action routine from Cut() operation.
+ key = wx.WXK_DELETE
+ else:
+ key = event.GetKeyCode()
+
+ field = self._FindField(sel_to)
+ start, end = field._extent
+ value = self._GetValue()
+ oldstart = sel_start
+
+ # If trying to erase beyond "legal" bounds, disallow operation:
+ if( (sel_to == 0 and key == wx.WXK_BACK)
+ or (self._signOk and sel_to == 1 and value[0] == ' ' and key == wx.WXK_BACK)
+ or (sel_to == self._masklength and sel_start == sel_to and key in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and not field._insertRight)
+ or (self._signOk and self._useParens
+ and sel_start == sel_to
+ and sel_to == self._masklength - 1
+ and value[sel_to] == ' ' and key in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and not field._insertRight) ):
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+## dbg(indent=0)
+ return False
+
+
+ if( field._insertRight # an insert-right field
+ and value[start:end] != self._template[start:end] # and field not empty
+ and sel_start >= start # and selection starts in field
+ and ((sel_to == sel_start # and no selection
+ and sel_to == end # and cursor at right edge
+ and key in (wx.WXK_BACK, wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE)) # and either delete or backspace key
+ or # or
+ (key == wx.WXK_BACK # backspacing
+ and (sel_to == end # and selection ends at right edge
+ or sel_to < end and field._allowInsert)) ) ): # or allow right insert at any point in field
+
+## dbg('delete left')
+ # if backspace but left of cursor is empty, adjust cursor right before deleting
+ while( key == wx.WXK_BACK
+ and sel_start == sel_to
+ and sel_start < end
+ and value[start:sel_start] == self._template[start:sel_start]):
+ sel_start += 1
+ sel_to = sel_start
+
+## dbg('sel_start, start:', sel_start, start)
+
+ if sel_start == sel_to:
+ keep = sel_start -1
+ else:
+ keep = sel_start
+ newfield = value[start:keep] + value[sel_to:end]
+
+ # handle sign char moving from outside field into the field:
+ move_sign_into_field = False
+ if not field._padZero and self._signOk and self._isNeg and value[0] in ('-', '('):
+ signchar = value[0]
+ newfield = signchar + newfield
+ move_sign_into_field = True
+## dbg('cut newfield: "%s"' % newfield)
+
+ # handle what should fill in from the left:
+ left = ""
+ for i in range(start, end - len(newfield)):
+ if field._padZero:
+ left += '0'
+ elif( self._signOk and self._isNeg and i == 1
+ and ((self._useParens and newfield.find('(') == -1)
+ or (not self._useParens and newfield.find('-') == -1)) ):
+ left += ' '
+ else:
+ left += self._template[i] # this can produce strange results in combination with default values...
+ newfield = left + newfield
+## dbg('filled newfield: "%s"' % newfield)
+
+ newstr = value[:start] + newfield + value[end:]
+
+ # (handle sign located in "mask position" in front of field prior to delete)
+ if move_sign_into_field:
+ newstr = ' ' + newstr[1:]
+ pos = sel_to
+ else:
+ # handle erasure of (left) sign, moving selection accordingly...
+ if self._signOk and sel_start == 0:
+ newstr = value = ' ' + value[1:]
+ sel_start += 1
+
+ if field._allowInsert and sel_start >= start:
+ # selection (if any) falls within current insert-capable field:
+ select_len = sel_to - sel_start
+ # determine where cursor should end up:
+ if key == wx.WXK_BACK:
+ if select_len == 0:
+ newpos = sel_start -1
+ else:
+ newpos = sel_start
+ erase_to = sel_to
+ else:
+ newpos = sel_start
+ if sel_to == sel_start:
+ erase_to = sel_to + 1
+ else:
+ erase_to = sel_to
+
+ if self._isTemplateChar(newpos) and select_len == 0:
+ if self._signOk:
+ if value[newpos] in ('(', '-'):
+ newpos += 1 # don't move cusor
+ newstr = ' ' + value[newpos:]
+ elif value[newpos] == ')':
+ # erase right sign, but don't move cursor; (matching left sign handled later)
+ newstr = value[:newpos] + ' '
+ else:
+ # no deletion; just move cursor
+ newstr = value
+ else:
+ # no deletion; just move cursor
+ newstr = value
+ else:
+ if erase_to > end: erase_to = end
+ erase_len = erase_to - newpos
+
+ left = value[start:newpos]
+## dbg("retained ='%s'" % value[erase_to:end], 'sel_to:', sel_to, "fill: '%s'" % self._template[end - erase_len:end])
+ right = value[erase_to:end] + self._template[end-erase_len:end]
+ pos_adjust = 0
+ if field._alignRight:
+ rstripped = right.rstrip()
+ if rstripped != right:
+ pos_adjust = len(right) - len(rstripped)
+ right = rstripped
+
+ if not field._insertRight and value[-1] == ')' and end == self._masklength - 1:
+ # need to shift ) into the field:
+ right = right[:-1] + ')'
+ value = value[:-1] + ' '
+
+ newfield = left+right
+ if pos_adjust:
+ newfield = newfield.rjust(end-start)
+ newpos += pos_adjust
+## dbg("left='%s', right ='%s', newfield='%s'" %(left, right, newfield))
+ newstr = value[:start] + newfield + value[end:]
+
+ pos = newpos
+
+ else:
+ if sel_start == sel_to:
+## dbg("current sel_start, sel_to:", sel_start, sel_to)
+ if key == wx.WXK_BACK:
+ sel_start, sel_to = sel_to-1, sel_to-1
+## dbg("new sel_start, sel_to:", sel_start, sel_to)
+
+ if field._padZero and not value[start:sel_to].replace('0', '').replace(' ','').replace(field._fillChar, ''):
+ # preceding chars (if any) are zeros, blanks or fillchar; new char should be 0:
+ newchar = '0'
+ else:
+ newchar = self._template[sel_to] ## get an original template character to "clear" the current char
+## dbg('value = "%s"' % value, 'value[%d] = "%s"' %(sel_start, value[sel_start]))
+
+ if self._isTemplateChar(sel_to):
+ if sel_to == 0 and self._signOk and value[sel_to] == '-': # erasing "template" sign char
+ newstr = ' ' + value[1:]
+ sel_to += 1
+ elif self._signOk and self._useParens and (value[sel_to] == ')' or value[sel_to] == '('):
+ # allow "change sign" by removing both parens:
+ newstr = value[:self._signpos] + ' ' + value[self._signpos+1:-1] + ' '
+ else:
+ newstr = value
+ newpos = sel_to
+ else:
+ if field._insertRight and sel_start == sel_to:
+ # force non-insert-right behavior, by selecting char to be replaced:
+ sel_to += 1
+ newstr, ignore = self._insertKey(newchar, sel_start, sel_start, sel_to, value)
+
+ else:
+ # selection made
+ newstr = self._eraseSelection(value, sel_start, sel_to)
+
+ pos = sel_start # put cursor back at beginning of selection
+
+ if self._signOk and self._useParens:
+ # account for resultant unbalanced parentheses:
+ left_signpos = newstr.find('(')
+ right_signpos = newstr.find(')')
+
+ if left_signpos == -1 and right_signpos != -1:
+ # erased left-sign marker; get rid of right sign marker:
+ newstr = newstr[:right_signpos] + ' ' + newstr[right_signpos+1:]
+
+ elif left_signpos != -1 and right_signpos == -1:
+ # erased right-sign marker; get rid of left-sign marker:
+ newstr = newstr[:left_signpos] + ' ' + newstr[left_signpos+1:]
+
+## dbg("oldstr:'%s'" % value, 'oldpos:', oldstart)
+## dbg("newstr:'%s'" % newstr, 'pos:', pos)
+
+ # if erasure results in an invalid field, disallow it:
+## dbg('field._validRequired?', field._validRequired)
+## dbg('field.IsValid("%s")?' % newstr[start:end], field.IsValid(newstr[start:end]))
+ if field._validRequired and not field.IsValid(newstr[start:end]):
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+## dbg(indent=0)
+ return False
+
+ # If the caller just wants the erased value without validation
+ # (because a just pressed key might make this string valid again)
+ # then return it.
+ if just_return_value:
+## dbg(indent=0)
+ return newstr
+
+ # if erasure results in an invalid value, disallow it:
+ if self._ctrl_constraints._validRequired and not self.IsValid(newstr):
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+## dbg(indent=0)
+ return False
+
+ # else...
+## dbg('setting value (later) to', newstr)
+ wx.CallAfter(self._SetValue, newstr)
+## dbg('setting insertion point (later) to', pos)
+ wx.CallAfter(self._SetInsertionPoint, pos)
+## dbg(indent=0)
+ if newstr != value:
+ self.modified = True
+ return False
+
+
+ def _OnEnd(self,event):
+ """ Handles End keypress in control. Should return False to skip other processing. """
+## dbg("MaskedEditMixin::_OnEnd", indent=1)
+ pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
+ if not event.ControlDown():
+ end = self._masklength # go to end of control
+ if self._signOk and self._useParens:
+ end = end - 1 # account for reserved char at end
+ else:
+ end_of_input = self._goEnd(getPosOnly=True)
+ sel_start, sel_to = self._GetSelection()
+ if sel_to < pos: sel_to = pos
+ field = self._FindField(sel_to)
+ field_end = self._FindField(end_of_input)
+
+ # pick different end point if either:
+ # - cursor not in same field
+ # - or at or past last input already
+ # - or current selection = end of current field:
+#### dbg('field != field_end?', field != field_end)
+#### dbg('sel_to >= end_of_input?', sel_to >= end_of_input)
+ if field != field_end or sel_to >= end_of_input:
+ edit_start, edit_end = field._extent
+#### dbg('edit_end:', edit_end)
+#### dbg('sel_to:', sel_to)
+#### dbg('sel_to == edit_end?', sel_to == edit_end)
+#### dbg('field._index < self._field_indices[-1]?', field._index < self._field_indices[-1])
+
+ if sel_to == edit_end and field._index < self._field_indices[-1]:
+ edit_start, edit_end = self._FindFieldExtent(self._findNextEntry(edit_end)) # go to end of next field:
+ end = edit_end
+## dbg('end moved to', end)
+
+ elif sel_to == edit_end and field._index == self._field_indices[-1]:
+ # already at edit end of last field; select to end of control:
+ end = self._masklength
+## dbg('end moved to', end)
+ else:
+ end = edit_end # select to end of current field
+## dbg('end moved to ', end)
+ else:
+ # select to current end of input
+ end = end_of_input
+
+
+#### dbg('pos:', pos, 'end:', end)
+
+ if event.ShiftDown():
+ if not event.ControlDown():
+## dbg("shift-end; select to end of control")
+ pass
+ else:
+## dbg("shift-ctrl-end; select to end of non-whitespace")
+ pass
+ wx.CallAfter(self._SetInsertionPoint, pos)
+ wx.CallAfter(self._SetSelection, pos, end)
+ else:
+ if not event.ControlDown():
+## dbg('go to end of control:')
+ pass
+ wx.CallAfter(self._SetInsertionPoint, end)
+ wx.CallAfter(self._SetSelection, end, end)
+
+## dbg(indent=0)
+ return False
+
+
+ def _OnReturn(self, event):
+ """
+ Swallows the return, issues a Navigate event instead, since
+ masked controls are "single line" by defn.
+ """
+## dbg('MaskedEditMixin::OnReturn')
+ self.Navigate(True)
+ return False
+
+
+ def _OnHome(self,event):
+ """ Handles Home keypress in control. Should return False to skip other processing."""
+## dbg("MaskedEditMixin::_OnHome", indent=1)
+ pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
+ sel_start, sel_to = self._GetSelection()
+
+ # There are 5 cases here:
+
+ # 1) shift: select from start of control to end of current
+ # selection.
+ if event.ShiftDown() and not event.ControlDown():
+## dbg("shift-home; select to start of control")
+ start = 0
+ end = sel_start
+
+ # 2) no shift, no control: move cursor to beginning of control.
+ elif not event.ControlDown():
+## dbg("home; move to start of control")
+ start = 0
+ end = 0
+
+ # 3) No shift, control: move cursor back to beginning of field; if
+ # there already, go to beginning of previous field.
+ # 4) shift, control, start of selection not at beginning of control:
+ # move sel_start back to start of field; if already there, go to
+ # start of previous field.
+ elif( event.ControlDown()
+ and (not event.ShiftDown()
+ or (event.ShiftDown() and sel_start > 0) ) ):
+ if len(self._field_indices) > 1:
+ field = self._FindField(sel_start)
+ start, ignore = field._extent
+ if sel_start == start and field._index != self._field_indices[0]: # go to start of previous field:
+ start, ignore = self._FindFieldExtent(sel_start-1)
+ elif sel_start == start:
+ start = 0 # go to literal beginning if edit start
+ # not at that point
+ end_of_field = True
+
+ else:
+ start = 0
+
+ if not event.ShiftDown():
+## dbg("ctrl-home; move to beginning of field")
+ end = start
+ else:
+## dbg("shift-ctrl-home; select to beginning of field")
+ end = sel_to
+
+ else:
+ # 5) shift, control, start of selection at beginning of control:
+ # unselect by moving sel_to backward to beginning of current field;
+ # if already there, move to start of previous field.
+ start = sel_start
+ if len(self._field_indices) > 1:
+ # find end of previous field:
+ field = self._FindField(sel_to)
+ if sel_to > start and field._index != self._field_indices[0]:
+ ignore, end = self._FindFieldExtent(field._extent[0]-1)
+ else:
+ end = start
+ end_of_field = True
+ else:
+ end = start
+ end_of_field = False
+## dbg("shift-ctrl-home; unselect to beginning of field")
+
+## dbg('queuing new sel_start, sel_to:', (start, end))
+ wx.CallAfter(self._SetInsertionPoint, start)
+ wx.CallAfter(self._SetSelection, start, end)
+## dbg(indent=0)
+ return False
+
+
+ def _OnChangeField(self, event):
+ """
+ Primarily handles TAB events, but can be used for any key that
+ designer wants to change fields within a masked edit control.
+ """
+## dbg('MaskedEditMixin::_OnChangeField', indent = 1)
+ # determine end of current field:
+ pos = self._GetInsertionPoint()
+## dbg('current pos:', pos)
+ sel_start, sel_to = self._GetSelection()
+
+ # no fields; process tab normally
+ # sel_to == -1 would cause an index error in _FindField
+ if self._masklength < 0 or sel_to == -1:
+ if pos != -1:
+ self._AdjustField(pos)
+ if event.GetKeyCode() == wx.WXK_TAB:
+## dbg('tab to next ctrl')
+ # As of 2.5.2, you don't call event.Skip() to do
+ # this, but instead force explicit navigation, if
+ # wx.TE_PROCESS_TAB is used (like in the masked edits)
+ self.Navigate(True)
+ #else: do nothing
+## dbg(indent=0)
+ return False
+
+ field = self._FindField(sel_to)
+ index = field._index
+ field_start, field_end = field._extent
+ slice = self._GetValue()[field_start:field_end]
+
+## dbg('field._stopFieldChangeIfInvalid?', field._stopFieldChangeIfInvalid)
+## dbg('field.IsValid(slice)?', field.IsValid(slice))
+
+ if field._stopFieldChangeIfInvalid and not field.IsValid(slice):
+## dbg('field invalid; field change disallowed')
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+## dbg(indent=0)
+ return False
+
+
+ if event.ShiftDown():
+
+ # "Go backward"
+
+ # NOTE: doesn't yet work with SHIFT-tab under wx; the control
+ # never sees this event! (But I've coded for it should it ever work,
+ # and it *does* work for '.' in IpAddrCtrl.)
+
+ if pos < field_start:
+## dbg('cursor before 1st field; cannot change to a previous field')
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+## dbg(indent=0)
+ return False
+
+ if event.ControlDown():
+## dbg('queuing select to beginning of field:', field_start, pos)
+ wx.CallAfter(self._SetInsertionPoint, field_start)
+ wx.CallAfter(self._SetSelection, field_start, pos)
+## dbg(indent=0)
+ return False
+
+ elif index == 0:
+ # We're already in the 1st field; process shift-tab normally:
+ self._AdjustField(pos)
+ if event.GetKeyCode() == wx.WXK_TAB:
+## dbg('tab to previous ctrl')
+ # As of 2.5.2, you don't call event.Skip() to do
+ # this, but instead force explicit navigation, if
+ # wx.TE_PROCESS_TAB is used (like in the masked edits)
+ self.Navigate(False)
+ else:
+## dbg('position at beginning')
+ wx.CallAfter(self._SetInsertionPoint, field_start)
+## dbg(indent=0)
+ return False
+ else:
+ # find beginning of previous field:
+ begin_prev = self._FindField(field_start-1)._extent[0]
+ self._AdjustField(pos)
+## dbg('repositioning to', begin_prev)
+ wx.CallAfter(self._SetInsertionPoint, begin_prev)
+ if self._FindField(begin_prev)._selectOnFieldEntry:
+ edit_start, edit_end = self._FindFieldExtent(begin_prev)
+## dbg('queuing selection to (%d, %d)' % (edit_start, edit_end))
+ wx.CallAfter(self._SetInsertionPoint, edit_start)
+ wx.CallAfter(self._SetSelection, edit_start, edit_end)
+## dbg(indent=0)
+ return False
+
+ else:
+ # "Go forward"
+ if event.ControlDown():
+## dbg('queuing select to end of field:', pos, field_end)
+ wx.CallAfter(self._SetInsertionPoint, pos)
+ wx.CallAfter(self._SetSelection, pos, field_end)
+## dbg(indent=0)
+ return False
+ else:
+ if pos < field_start:
+## dbg('cursor before 1st field; go to start of field')
+ wx.CallAfter(self._SetInsertionPoint, field_start)
+ if field._selectOnFieldEntry:
+ wx.CallAfter(self._SetSelection, field_end, field_start)
+ else:
+ wx.CallAfter(self._SetSelection, field_start, field_start)
+ return False
+ # else...
+## dbg('end of current field:', field_end)
+## dbg('go to next field')
+ if field_end == self._fields[self._field_indices[-1]]._extent[1]:
+ self._AdjustField(pos)
+ if event.GetKeyCode() == wx.WXK_TAB:
+## dbg('tab to next ctrl')
+ # As of 2.5.2, you don't call event.Skip() to do
+ # this, but instead force explicit navigation, if
+ # wx.TE_PROCESS_TAB is used (like in the masked edits)
+ self.Navigate(True)
+ else:
+## dbg('position at end')
+ wx.CallAfter(self._SetInsertionPoint, field_end)
+## dbg(indent=0)
+ return False
+ else:
+ # we have to find the start of the next field
+ next_pos = self._findNextEntry(field_end)
+ if next_pos == field_end:
+## dbg('already in last field')
+ self._AdjustField(pos)
+ if event.GetKeyCode() == wx.WXK_TAB:
+## dbg('tab to next ctrl')
+ # As of 2.5.2, you don't call event.Skip() to do
+ # this, but instead force explicit navigation, if
+ # wx.TE_PROCESS_TAB is used (like in the masked edits)
+ self.Navigate(True)
+ #else: do nothing
+## dbg(indent=0)
+ return False
+ else:
+ self._AdjustField( pos )
+
+ # move cursor to appropriate point in the next field and select as necessary:
+ field = self._FindField(next_pos)
+ edit_start, edit_end = field._extent
+ if field._selectOnFieldEntry:
+## dbg('move to ', next_pos)
+ wx.CallAfter(self._SetInsertionPoint, next_pos)
+ edit_start, edit_end = self._FindFieldExtent(next_pos)
+## dbg('queuing select', edit_start, edit_end)
+ wx.CallAfter(self._SetSelection, edit_end, edit_start)
+ else:
+ if field._insertRight:
+ next_pos = field._extent[1]
+## dbg('move to ', next_pos)
+ wx.CallAfter(self._SetInsertionPoint, next_pos)
+## dbg(indent=0)
+ return False
+## dbg(indent=0)
+
+
+ def _OnDecimalPoint(self, event):
+## dbg('MaskedEditMixin::_OnDecimalPoint', indent=1)
+ field = self._FindField(self._GetInsertionPoint())
+ start, end = field._extent
+ slice = self._GetValue()[start:end]
+
+ if field._stopFieldChangeIfInvalid and not field.IsValid(slice):
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+ return False
+
+ pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
+
+ if self._isFloat: ## handle float value, move to decimal place
+## dbg('key == Decimal tab; decimal pos:', self._decimalpos)
+ value = self._GetValue()
+ if pos < self._decimalpos:
+ clipped_text = value[0:pos] + self._decimalChar + value[self._decimalpos+1:]
+## dbg('value: "%s"' % self._GetValue(), "clipped_text:'%s'" % clipped_text)
+ newstr = self._adjustFloat(clipped_text)
+ else:
+ newstr = self._adjustFloat(value)
+ wx.CallAfter(self._SetValue, newstr)
+ fraction = self._fields[1]
+ start, end = fraction._extent
+ wx.CallAfter(self._SetInsertionPoint, start)
+ if fraction._selectOnFieldEntry:
+## dbg('queuing selection after decimal point to:', (start, end))
+ wx.CallAfter(self._SetSelection, end, start)
+ else:
+ wx.CallAfter(self._SetSelection, start, start)
+ keep_processing = False
+
+ if self._isInt: ## handle integer value, truncate from current position
+## dbg('key == Integer decimal event')
+ value = self._GetValue()
+ clipped_text = value[0:pos]
+## dbg('value: "%s"' % self._GetValue(), "clipped_text:'%s'" % clipped_text)
+ newstr = self._adjustInt(clipped_text)
+## dbg('newstr: "%s"' % newstr)
+ wx.CallAfter(self._SetValue, newstr)
+ newpos = len(newstr.rstrip())
+ if newstr.find(')') != -1:
+ newpos -= 1 # (don't move past right paren)
+ wx.CallAfter(self._SetInsertionPoint, newpos)
+ wx.CallAfter(self._SetSelection, newpos, newpos)
+ keep_processing = False
+## dbg(indent=0)
+
+
+ def _OnChangeSign(self, event):
+## dbg('MaskedEditMixin::_OnChangeSign', indent=1)
+ key = event.GetKeyCode()
+ pos = self._adjustPos(self._GetInsertionPoint(), key)
+ value = self._eraseSelection()
+ integer = self._fields[0]
+ start, end = integer._extent
+ sel_start, sel_to = self._GetSelection()
+
+#### dbg('adjusted pos:', pos)
+ if chr(key) in ('-','+','(', ')') or (chr(key) == " " and pos == self._signpos):
+ cursign = self._isNeg
+## dbg('cursign:', cursign)
+ if chr(key) in ('-','(', ')'):
+ if sel_start <= self._signpos:
+ self._isNeg = True
+ else:
+ self._isNeg = (not self._isNeg) ## flip value
+ else:
+ self._isNeg = False
+## dbg('isNeg?', self._isNeg)
+
+ text, self._signpos, self._right_signpos = self._getSignedValue(candidate=value)
+## dbg('text:"%s"' % text, 'signpos:', self._signpos, 'right_signpos:', self._right_signpos)
+ if text is None:
+ text = value
+
+ if self._isNeg and self._signpos is not None and self._signpos != -1:
+ if self._useParens and self._right_signpos is not None:
+ text = text[:self._signpos] + '(' + text[self._signpos+1:self._right_signpos] + ')' + text[self._right_signpos+1:]
+ else:
+ text = text[:self._signpos] + '-' + text[self._signpos+1:]
+ else:
+#### dbg('self._isNeg?', self._isNeg, 'self.IsValid(%s)' % text, self.IsValid(text))
+ if self._useParens:
+ text = text[:self._signpos] + ' ' + text[self._signpos+1:self._right_signpos] + ' ' + text[self._right_signpos+1:]
+ else:
+ text = text[:self._signpos] + ' ' + text[self._signpos+1:]
+## dbg('clearing self._isNeg')
+ self._isNeg = False
+
+ wx.CallAfter(self._SetValue, text)
+ wx.CallAfter(self._applyFormatting)
+## dbg('pos:', pos, 'signpos:', self._signpos)
+ if pos == self._signpos or integer.IsEmpty(text[start:end]):
+ wx.CallAfter(self._SetInsertionPoint, self._signpos+1)
+ else:
+ wx.CallAfter(self._SetInsertionPoint, pos)
+
+ keep_processing = False
+ else:
+ keep_processing = True
+## dbg(indent=0)
+ return keep_processing
+
+
+ def _OnGroupChar(self, event):
+ """
+ This handler is only registered if the mask is a numeric mask.
+ It allows the insertion of ',' or '.' if appropriate.
+ """
+## dbg('MaskedEditMixin::_OnGroupChar', indent=1)
+ keep_processing = True
+ pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
+ sel_start, sel_to = self._GetSelection()
+ groupchar = self._fields[0]._groupChar
+ if not self._isCharAllowed(groupchar, pos, checkRegex=True):
+ keep_processing = False
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+
+ if keep_processing:
+ newstr, newpos = self._insertKey(groupchar, pos, sel_start, sel_to, self._GetValue() )
+## dbg("str with '%s' inserted:" % groupchar, '"%s"' % newstr)
+ if self._ctrl_constraints._validRequired and not self.IsValid(newstr):
+ keep_processing = False
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+
+ if keep_processing:
+ wx.CallAfter(self._SetValue, newstr)
+ wx.CallAfter(self._SetInsertionPoint, newpos)
+ keep_processing = False
+## dbg(indent=0)
+ return keep_processing
+
+
+ def _findNextEntry(self,pos, adjustInsert=True):
+ """ Find the insertion point for the next valid entry character position."""
+## dbg('MaskedEditMixin::_findNextEntry', indent=1)
+ if self._isTemplateChar(pos) or pos in self._explicit_field_boundaries: # if changing fields, pay attn to flag
+ adjustInsert = adjustInsert
+ else: # else within a field; flag not relevant
+ adjustInsert = False
+
+ while self._isTemplateChar(pos) and pos < self._masklength:
+ pos += 1
+
+ # if changing fields, and we've been told to adjust insert point,
+ # look at new field; if empty and right-insert field,
+ # adjust to right edge:
+ if adjustInsert and pos < self._masklength:
+ field = self._FindField(pos)
+ start, end = field._extent
+ slice = self._GetValue()[start:end]
+ if field._insertRight and field.IsEmpty(slice):
+ pos = end
+## dbg('final pos:', pos, indent=0)
+ return pos
+
+
+ def _findNextTemplateChar(self, pos):
+ """ Find the position of the next non-editable character in the mask."""
+ while not self._isTemplateChar(pos) and pos < self._masklength:
+ pos += 1
+ return pos
+
+
+ def _OnAutoCompleteField(self, event):
+## dbg('MaskedEditMixin::_OnAutoCompleteField', indent =1)
+ pos = self._GetInsertionPoint()
+ field = self._FindField(pos)
+ edit_start, edit_end, slice = self._FindFieldExtent(pos, getslice=True)
+
+ match_index = None
+ keycode = event.GetKeyCode()
+
+ if field._fillChar != ' ':
+ text = slice.replace(field._fillChar, '')
+ else:
+ text = slice
+ text = text.strip()
+ keep_processing = True # (assume True to start)
+## dbg('field._hasList?', field._hasList)
+ if field._hasList:
+## dbg('choices:', field._choices)
+## dbg('compareChoices:', field._compareChoices)
+ choices, choice_required = field._compareChoices, field._choiceRequired
+ if keycode in (wx.WXK_PRIOR, wx.WXK_UP, wx.WXK_NUMPAD_PRIOR, wx.WXK_NUMPAD_UP):
+ direction = -1
+ else:
+ direction = 1
+ match_index, partial_match = self._autoComplete(direction, choices, text, compareNoCase=field._compareNoCase, current_index = field._autoCompleteIndex)
+ if( match_index is None
+ and (keycode in self._autoCompleteKeycodes + [wx.WXK_PRIOR, wx.WXK_NEXT, wx.WXK_NUMPAD_PRIOR, wx.WXK_NUMPAD_NEXT]
+ or (keycode in [wx.WXK_UP, wx.WXK_DOWN, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_DOWN] and event.ShiftDown() ) ) ):
+ # Select the 1st thing from the list:
+ match_index = 0
+
+ if( match_index is not None
+ and ( keycode in self._autoCompleteKeycodes + [wx.WXK_PRIOR, wx.WXK_NEXT, wx.WXK_NUMPAD_PRIOR, wx.WXK_NUMPAD_NEXT]
+ or (keycode in [wx.WXK_UP, wx.WXK_DOWN, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_DOWN] and event.ShiftDown())
+ or (keycode in [wx.WXK_DOWN, wx.WXK_NUMPAD_DOWN] and partial_match) ) ):
+
+ # We're allowed to auto-complete:
+## dbg('match found')
+ value = self._GetValue()
+ newvalue = value[:edit_start] + field._choices[match_index] + value[edit_end:]
+## dbg('setting value to "%s"' % newvalue)
+ self._SetValue(newvalue)
+ self._SetInsertionPoint(min(edit_end, len(newvalue.rstrip())))
+ self._OnAutoSelect(field, match_index)
+ self._CheckValid() # recolor as appopriate
+
+
+ if keycode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT, wx.WXK_RIGHT,
+ wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_DOWN, wx.WXK_NUMPAD_LEFT, wx.WXK_NUMPAD_RIGHT):
+ # treat as left right arrow if unshifted, tab/shift tab if shifted.
+ if event.ShiftDown():
+ if keycode in (wx.WXK_DOWN, wx.WXK_RIGHT, wx.WXK_NUMPAD_DOWN, wx.WXK_NUMPAD_RIGHT):
+ # remove "shifting" and treat as (forward) tab:
+ event.shiftDown = False
+ keep_processing = self._OnChangeField(event)
+ else:
+ keep_processing = self._OnArrow(event)
+ # else some other key; keep processing the key
+
+## dbg('keep processing?', keep_processing, indent=0)
+ return keep_processing
+
+
+ def _OnAutoSelect(self, field, match_index = None):
+ """
+ Function called if autoselect feature is enabled and entire control
+ is selected:
+ """
+## dbg('MaskedEditMixin::OnAutoSelect', field._index)
+ if match_index is not None:
+ field._autoCompleteIndex = match_index
+
+
+ def _autoComplete(self, direction, choices, value, compareNoCase, current_index):
+ """
+ This function gets called in response to Auto-complete events.
+ It attempts to find a match to the specified value against the
+ list of choices; if exact match, the index of then next
+ appropriate value in the list, based on the given direction.
+ If not an exact match, it will return the index of the 1st value from
+ the choice list for which the partial value can be extended to match.
+ If no match found, it will return None.
+ The function returns a 2-tuple, with the 2nd element being a boolean
+ that indicates if partial match was necessary.
+ """
+## dbg('autoComplete(direction=', direction, 'choices=',choices, 'value=',value,'compareNoCase?', compareNoCase, 'current_index:', current_index, indent=1)
+ if value is None:
+## dbg('nothing to match against', indent=0)
+ return (None, False)
+
+ partial_match = False
+
+ if compareNoCase:
+ value = value.lower()
+
+ last_index = len(choices) - 1
+ if value in choices:
+## dbg('"%s" in', choices)
+ if current_index is not None and choices[current_index] == value:
+ index = current_index
+ else:
+ index = choices.index(value)
+
+## dbg('matched "%s" (%d)' % (choices[index], index))
+ if direction == -1:
+## dbg('going to previous')
+ if index == 0: index = len(choices) - 1
+ else: index -= 1
+ else:
+ if index == len(choices) - 1: index = 0
+ else: index += 1
+## dbg('change value to "%s" (%d)' % (choices[index], index))
+ match = index
+ else:
+ partial_match = True
+ value = value.strip()
+## dbg('no match; try to auto-complete:')
+ match = None
+## dbg('searching for "%s"' % value)
+ if current_index is None:
+ indices = range(len(choices))
+ if direction == -1:
+ indices.reverse()
+ else:
+ if direction == 1:
+ indices = range(current_index +1, len(choices)) + range(current_index+1)
+## dbg('range(current_index+1 (%d), len(choices) (%d)) + range(%d):' % (current_index+1, len(choices), current_index+1), indices)
+ else:
+ indices = range(current_index-1, -1, -1) + range(len(choices)-1, current_index-1, -1)
+## dbg('range(current_index-1 (%d), -1) + range(len(choices)-1 (%d)), current_index-1 (%d):' % (current_index-1, len(choices)-1, current_index-1), indices)
+#### dbg('indices:', indices)
+ for index in indices:
+ choice = choices[index]
+ if choice.find(value, 0) == 0:
+## dbg('match found:', choice)
+ match = index
+ break
+ else:
+## dbg('choice: "%s" - no match' % choice)
+ pass
+ if match is not None:
+## dbg('matched', match)
+ pass
+ else:
+## dbg('no match found')
+ pass
+## dbg(indent=0)
+ return (match, partial_match)
+
+
+ def _AdjustField(self, pos):
+ """
+ This function gets called by default whenever the cursor leaves a field.
+ The pos argument given is the char position before leaving that field.
+ By default, floating point, integer and date values are adjusted to be
+ legal in this function. Derived classes may override this function
+ to modify the value of the control in a different way when changing fields.
+
+ NOTE: these change the value immediately, and restore the cursor to
+ the passed location, so that any subsequent code can then move it
+ based on the operation being performed.
+ """
+ newvalue = value = self._GetValue()
+ field = self._FindField(pos)
+ start, end, slice = self._FindFieldExtent(getslice=True)
+ newfield = field._AdjustField(slice)
+ newvalue = value[:start] + newfield + value[end:]
+
+ if self._isFloat and newvalue != self._template:
+ newvalue = self._adjustFloat(newvalue)
+
+ if self._ctrl_constraints._isInt and value != self._template:
+ newvalue = self._adjustInt(value)
+
+ if self._isDate and value != self._template:
+ newvalue = self._adjustDate(value, fixcentury=True)
+ if self._4digityear:
+ year2dig = self._dateExtent - 2
+ if pos == year2dig and value[year2dig] != newvalue[year2dig]:
+ pos = pos+2
+
+ if newvalue != value:
+## dbg('old value: "%s"\nnew value: "%s"' % (value, newvalue))
+ self._SetValue(newvalue)
+ self._SetInsertionPoint(pos)
+
+
+ def _adjustKey(self, pos, key):
+ """ Apply control formatting to the key (e.g. convert to upper etc). """
+ field = self._FindField(pos)
+ if field._forceupper and key in range(97,123):
+ key = ord( chr(key).upper())
+
+ if field._forcelower and key in range(65,90):
+ key = ord( chr(key).lower())
+
+ return key
+
+
+ def _adjustPos(self, pos, key):
+ """
+ Checks the current insertion point position and adjusts it if
+ necessary to skip over non-editable characters.
+ """
+## dbg('_adjustPos', pos, key, indent=1)
+ sel_start, sel_to = self._GetSelection()
+ # If a numeric or decimal mask, and negatives allowed, reserve the
+ # first space for sign, and last one if using parens.
+ if( self._signOk
+ and ((pos == self._signpos and key in (ord('-'), ord('+'), ord(' ')) )
+ or (self._useParens and pos == self._masklength -1))):
+## dbg('adjusted pos:', pos, indent=0)
+ return pos
+
+ if key not in self._nav:
+ field = self._FindField(pos)
+
+## dbg('field._insertRight?', field._insertRight)
+## if self._signOk: dbg('self._signpos:', self._signpos)
+ if field._insertRight: # if allow right-insert
+ start, end = field._extent
+ slice = self._GetValue()[start:end].strip()
+ field_len = end - start
+ if pos == end: # if cursor at right edge of field
+ # if not filled or supposed to stay in field, keep current position
+#### dbg('pos==end')
+#### dbg('len (slice):', len(slice))
+#### dbg('field_len?', field_len)
+#### dbg('pos==end; len (slice) < field_len?', len(slice) < field_len)
+#### dbg('not field._moveOnFieldFull?', not field._moveOnFieldFull)
+ if( len(slice) == field_len and field._moveOnFieldFull
+ and (not field._stopFieldChangeIfInvalid or
+ field._stopFieldChangeIfInvalid and field.IsValid(slice))):
+ # move cursor to next field:
+ pos = self._findNextEntry(pos)
+ self._SetInsertionPoint(pos)
+ if pos < sel_to:
+ self._SetSelection(pos, sel_to) # restore selection
+ else:
+ self._SetSelection(pos, pos) # remove selection
+ else: # leave cursor alone
+ pass
+ else:
+ # if at start of control, move to right edge
+ if (sel_to == sel_start
+ and (self._isTemplateChar(pos) or (pos == start and len(slice)+ 1 < field_len))
+ and pos != end):
+ pos = end # move to right edge
+## elif sel_start <= start and sel_to == end:
+## # select to right edge of field - 1 (to replace char)
+## pos = end - 1
+## self._SetInsertionPoint(pos)
+## # restore selection
+## self._SetSelection(sel_start, pos)
+
+ # if selected to beginning and signed, and not changing sign explicitly:
+ elif self._signOk and sel_start == 0 and key not in (ord('-'), ord('+'), ord(' ')):
+ # adjust to past reserved sign position:
+ pos = self._fields[0]._extent[0]
+## dbg('adjusting field to ', pos)
+ self._SetInsertionPoint(pos)
+ # but keep original selection, to allow replacement of any sign:
+ self._SetSelection(0, sel_to)
+ else:
+ pass # leave position/selection alone
+
+ # else make sure the user is not trying to type over a template character
+ # If they are, move them to the next valid entry position
+ elif self._isTemplateChar(pos):
+ if( (not field._moveOnFieldFull
+ and (not self._signOk
+ or (self._signOk and field._index == 0 and pos > 0) ) )
+
+ or (field._stopFieldChangeIfInvalid
+ and not field.IsValid(self._GetValue()[start:end]) ) ):
+
+ # don't move to next field without explicit cursor movement
+ pass
+ else:
+ # find next valid position
+ pos = self._findNextEntry(pos)
+ self._SetInsertionPoint(pos)
+ if pos < sel_to: # restore selection
+ self._SetSelection(pos, sel_to)
+ else:
+ self._SetSelection(pos, pos)
+## dbg('adjusted pos:', pos, indent=0)
+ return pos
+
+
+ def _adjustFloat(self, candidate=None):
+ """
+ 'Fixes' an floating point control. Collapses spaces, right-justifies, etc.
+ """
+## dbg('MaskedEditMixin::_adjustFloat, candidate = "%s"' % candidate, indent=1)
+ lenInt,lenFraction = [len(s) for s in self._mask.split('.')] ## Get integer, fraction lengths
+
+ if candidate is None: value = self._GetValue()
+ else: value = candidate
+## dbg('value = "%(value)s"' % locals(), 'len(value):', len(value))
+ intStr, fracStr = value.split(self._decimalChar)
+
+ intStr = self._fields[0]._AdjustField(intStr)
+## dbg('adjusted intStr: "%s"' % intStr)
+ lenInt = len(intStr)
+ fracStr = fracStr + ('0'*(lenFraction-len(fracStr))) # add trailing spaces to decimal
+
+## dbg('intStr "%(intStr)s"' % locals())
+## dbg('lenInt:', lenInt)
+
+ intStr = string.rjust( intStr[-lenInt:], lenInt)
+## dbg('right-justifed intStr = "%(intStr)s"' % locals())
+ newvalue = intStr + self._decimalChar + fracStr
+
+ if self._signOk:
+ if len(newvalue) < self._masklength:
+ newvalue = ' ' + newvalue
+ signedvalue = self._getSignedValue(newvalue)[0]
+ if signedvalue is not None: newvalue = signedvalue
+
+ # Finally, align string with decimal position, left-padding with
+ # fillChar:
+ newdecpos = newvalue.find(self._decimalChar)
+ if newdecpos < self._decimalpos:
+ padlen = self._decimalpos - newdecpos
+ newvalue = string.join([' ' * padlen] + [newvalue] ,'')
+
+ if self._signOk and self._useParens:
+ if newvalue.find('(') != -1:
+ newvalue = newvalue[:-1] + ')'
+ else:
+ newvalue = newvalue[:-1] + ' '
+
+## dbg('newvalue = "%s"' % newvalue)
+ if candidate is None:
+ wx.CallAfter(self._SetValue, newvalue)
+## dbg(indent=0)
+ return newvalue
+
+
+ def _adjustInt(self, candidate=None):
+ """ 'Fixes' an integer control. Collapses spaces, right or left-justifies."""
+## dbg("MaskedEditMixin::_adjustInt", candidate)
+ lenInt = self._masklength
+ if candidate is None: value = self._GetValue()
+ else: value = candidate
+
+ intStr = self._fields[0]._AdjustField(value)
+ intStr = intStr.strip() # drop extra spaces
+## dbg('adjusted field: "%s"' % intStr)
+
+ if self._isNeg and intStr.find('-') == -1 and intStr.find('(') == -1:
+ if self._useParens:
+ intStr = '(' + intStr + ')'
+ else:
+ intStr = '-' + intStr
+ elif self._isNeg and intStr.find('-') != -1 and self._useParens:
+ intStr = intStr.replace('-', '(')
+
+ if( self._signOk and ((self._useParens and intStr.find('(') == -1)
+ or (not self._useParens and intStr.find('-') == -1))):
+ intStr = ' ' + intStr
+ if self._useParens:
+ intStr += ' ' # space for right paren position
+
+ elif self._signOk and self._useParens and intStr.find('(') != -1 and intStr.find(')') == -1:
+ # ensure closing right paren:
+ intStr += ')'
+
+ if self._fields[0]._alignRight: ## Only if right-alignment is enabled
+ intStr = intStr.rjust( lenInt )
+ else:
+ intStr = intStr.ljust( lenInt )
+
+ if candidate is None:
+ wx.CallAfter(self._SetValue, intStr )
+ return intStr
+
+
+ def _adjustDate(self, candidate=None, fixcentury=False, force4digit_year=False):
+ """
+ 'Fixes' a date control, expanding the year if it can.
+ Applies various self-formatting options.
+ """
+## dbg("MaskedEditMixin::_adjustDate", indent=1)
+ if candidate is None: text = self._GetValue()
+ else: text = candidate
+## dbg('text=', text)
+ if self._datestyle == "YMD":
+ year_field = 0
+ else:
+ year_field = 2
+
+## dbg('getYear: "%s"' % _getYear(text, self._datestyle))
+ year = string.replace( _getYear( text, self._datestyle),self._fields[year_field]._fillChar,"") # drop extra fillChars
+ month = _getMonth( text, self._datestyle)
+ day = _getDay( text, self._datestyle)
+## dbg('self._datestyle:', self._datestyle, 'year:', year, 'Month', month, 'day:', day)
+
+ yearVal = None
+ yearstart = self._dateExtent - 4
+ if( len(year) < 4
+ and (fixcentury
+ or force4digit_year
+ or (self._GetInsertionPoint() > yearstart+1 and text[yearstart+2] == ' ')
+ or (self._GetInsertionPoint() > yearstart+2 and text[yearstart+3] == ' ') ) ):
+ ## user entered less than four digits and changing fields or past point where we could
+ ## enter another digit:
+ try:
+ yearVal = int(year)
+ except:
+## dbg('bad year=', year)
+ year = text[yearstart:self._dateExtent]
+
+ if len(year) < 4 and yearVal:
+ if len(year) == 2:
+ # Fix year adjustment to be less "20th century" :-) and to adjust heuristic as the
+ # years pass...
+ now = wx.DateTime_Now()
+ century = (now.GetYear() /100) * 100 # "this century"
+ twodig_year = now.GetYear() - century # "this year" (2 digits)
+ # if separation between today's 2-digit year and typed value > 50,
+ # assume last century,
+ # else assume this century.
+ #
+ # Eg: if 2003 and yearVal == 30, => 2030
+ # if 2055 and yearVal == 80, => 2080
+ # if 2010 and yearVal == 96, => 1996
+ #
+ if abs(yearVal - twodig_year) > 50:
+ yearVal = (century - 100) + yearVal
+ else:
+ yearVal = century + yearVal
+ year = str( yearVal )
+ else: # pad with 0's to make a 4-digit year
+ year = "%04d" % yearVal
+ if self._4digityear or force4digit_year:
+ text = _makeDate(year, month, day, self._datestyle, text) + text[self._dateExtent:]
+## dbg('newdate: "%s"' % text, indent=0)
+ return text
+
+
+ def _goEnd(self, getPosOnly=False):
+ """ Moves the insertion point to the end of user-entry """
+## dbg("MaskedEditMixin::_goEnd; getPosOnly:", getPosOnly, indent=1)
+ text = self._GetValue()
+#### dbg('text: "%s"' % text)
+ i = 0
+ if len(text.rstrip()):
+ for i in range( min( self._masklength-1, len(text.rstrip())), -1, -1):
+#### dbg('i:', i, 'self._isMaskChar(%d)' % i, self._isMaskChar(i))
+ if self._isMaskChar(i):
+ char = text[i]
+#### dbg("text[%d]: '%s'" % (i, char))
+ if char != ' ':
+ i += 1
+ break
+
+ if i == 0:
+ pos = self._goHome(getPosOnly=True)
+ else:
+ pos = min(i,self._masklength)
+
+ field = self._FindField(pos)
+ start, end = field._extent
+ if field._insertRight and pos < end:
+ pos = end
+## dbg('next pos:', pos)
+## dbg(indent=0)
+ if getPosOnly:
+ return pos
+ else:
+ self._SetInsertionPoint(pos)
+
+
+ def _goHome(self, getPosOnly=False):
+ """ Moves the insertion point to the beginning of user-entry """
+## dbg("MaskedEditMixin::_goHome; getPosOnly:", getPosOnly, indent=1)
+ text = self._GetValue()
+ for i in range(self._masklength):
+ if self._isMaskChar(i):
+ break
+ pos = max(i, 0)
+## dbg(indent=0)
+ if getPosOnly:
+ return pos
+ else:
+ self._SetInsertionPoint(max(i,0))
+
+
+
+ def _getAllowedChars(self, pos):
+ """ Returns a string of all allowed user input characters for the provided
+ mask character plus control options
+ """
+ maskChar = self.maskdict[pos]
+ okchars = self.maskchardict[maskChar] ## entry, get mask approved characters
+
+ # convert okchars to unicode if required; will force subsequent appendings to
+ # result in unicode strings
+ if 'unicode' in wx.PlatformInfo and type(okchars) != types.UnicodeType:
+ okchars = okchars.decode(self._defaultEncoding)
+
+ field = self._FindField(pos)
+ if okchars and field._okSpaces: ## Allow spaces?
+ okchars += " "
+ if okchars and field._includeChars: ## any additional included characters?
+ okchars += field._includeChars
+#### dbg('okchars[%d]:' % pos, okchars)
+ return okchars
+
+
+ def _isMaskChar(self, pos):
+ """ Returns True if the char at position pos is a special mask character (e.g. NCXaA#)
+ """
+ if pos < self._masklength:
+ return self._ismasked[pos]
+ else:
+ return False
+
+
+ def _isTemplateChar(self,Pos):
+ """ Returns True if the char at position pos is a template character (e.g. -not- NCXaA#)
+ """
+ if Pos < self._masklength:
+ return not self._isMaskChar(Pos)
+ else:
+ return False
+
+
+ def _isCharAllowed(self, char, pos, checkRegex=False, allowAutoSelect=True, ignoreInsertRight=False):
+ """ Returns True if character is allowed at the specific position, otherwise False."""
+## dbg('_isCharAllowed', char, pos, checkRegex, indent=1)
+ field = self._FindField(pos)
+ right_insert = False
+
+ if self.controlInitialized:
+ sel_start, sel_to = self._GetSelection()
+ else:
+ sel_start, sel_to = pos, pos
+
+ if (field._insertRight or self._ctrl_constraints._insertRight) and not ignoreInsertRight:
+ start, end = field._extent
+ field_len = end - start
+ if self.controlInitialized:
+ value = self._GetValue()
+ fstr = value[start:end].strip()
+ if field._padZero:
+ while fstr and fstr[0] == '0':
+ fstr = fstr[1:]
+ input_len = len(fstr)
+ if self._signOk and '-' in fstr or '(' in fstr:
+ input_len -= 1 # sign can move out of field, so don't consider it in length
+ else:
+ value = self._template
+ input_len = 0 # can't get the current "value", so use 0
+
+
+ # if entire field is selected or position is at end and field is not full,
+ # or if allowed to right-insert at any point in field and field is not full and cursor is not at a fillChar
+ # or the field is a singleton integer field and is currently 0 and we're at the end:
+ if( (sel_start, sel_to) == field._extent
+ or (pos == end and ((input_len < field_len)
+ or (field_len == 1
+ and input_len == field_len
+ and field._isInt
+ and value[end-1] == '0'
+ )
+ ) ) ):
+ pos = end - 1
+## dbg('pos = end - 1 = ', pos, 'right_insert? 1')
+ right_insert = True
+ elif( field._allowInsert and sel_start == sel_to
+ and (sel_to == end or (sel_to < self._masklength and value[sel_start] != field._fillChar))
+ and input_len < field_len ):
+ pos = sel_to - 1 # where character will go
+## dbg('pos = sel_to - 1 = ', pos, 'right_insert? 1')
+ right_insert = True
+ # else leave pos alone...
+ else:
+## dbg('pos stays ', pos, 'right_insert? 0')
+ pass
+
+ if self._isTemplateChar( pos ): ## if a template character, return empty
+## dbg('%d is a template character; returning False' % pos, indent=0)
+ return False
+
+ if self._isMaskChar( pos ):
+ okChars = self._getAllowedChars(pos)
+
+ if self._fields[0]._groupdigits and (self._isInt or (self._isFloat and pos < self._decimalpos)):
+ okChars += self._fields[0]._groupChar
+
+ if self._signOk:
+ if self._isInt or (self._isFloat and pos < self._decimalpos):
+ okChars += '-'
+ if self._useParens:
+ okChars += '('
+ elif self._useParens and (self._isInt or (self._isFloat and pos > self._decimalpos)):
+ okChars += ')'
+
+#### dbg('%s in %s?' % (char, okChars), char in okChars)
+ approved = (self.maskdict[pos] == '*' or char in okChars)
+
+ if approved and checkRegex:
+## dbg("checking appropriate regex's")
+ value = self._eraseSelection(self._GetValue())
+ if right_insert:
+ # move the position to the right side of the insertion:
+ at = pos+1
+ else:
+ at = pos
+ if allowAutoSelect:
+ newvalue, ignore, ignore, ignore, ignore = self._insertKey(char, at, sel_start, sel_to, value, allowAutoSelect=True)
+ else:
+ newvalue, ignore = self._insertKey(char, at, sel_start, sel_to, value)
+## dbg('newvalue: "%s"' % newvalue)
+
+ fields = [self._FindField(pos)] + [self._ctrl_constraints]
+ for field in fields: # includes fields[-1] == "ctrl_constraints"
+ if field._regexMask and field._filter:
+## dbg('checking vs. regex')
+ start, end = field._extent
+ slice = newvalue[start:end]
+ approved = (re.match( field._filter, slice) is not None)
+## dbg('approved?', approved)
+ if not approved: break
+## dbg(indent=0)
+ return approved
+ else:
+## dbg('%d is a !???! character; returning False', indent=0)
+## dbg(indent=0)
+ return False
+
+
+ def _applyFormatting(self):
+ """ Apply formatting depending on the control's state.
+ Need to find a way to call this whenever the value changes, in case the control's
+ value has been changed or set programatically.
+ """
+## dbg(suspend=1)
+## dbg('MaskedEditMixin::_applyFormatting', indent=1)
+
+ # Handle negative numbers
+ if self._signOk:
+ text, signpos, right_signpos = self._getSignedValue()
+## dbg('text: "%s", signpos:' % text, signpos)
+ if text and signpos != self._signpos:
+ self._signpos = signpos
+ if not text or text[signpos] not in ('-','('):
+ self._isNeg = False
+## dbg('no valid sign found; new sign:', self._isNeg)
+ elif text and self._valid and not self._isNeg and text[signpos] in ('-', '('):
+## dbg('setting _isNeg to True')
+ self._isNeg = True
+## dbg('self._isNeg:', self._isNeg)
+
+ if self._signOk and self._isNeg:
+ fc = self._signedForegroundColour
+ else:
+ fc = self._foregroundColour
+
+ if hasattr(fc, '_name'):
+ c =fc._name
+ else:
+ c = fc
+## dbg('setting foreground to', c)
+ self.SetForegroundColour(fc)
+
+ if self._valid:
+## dbg('valid')
+ if self.IsEmpty():
+ bc = self._emptyBackgroundColour
+ else:
+ bc = self._validBackgroundColour
+ else:
+## dbg('invalid')
+ bc = self._invalidBackgroundColour
+ if hasattr(bc, '_name'):
+ c =bc._name
+ else:
+ c = bc
+## dbg('setting background to', c)
+ self.SetBackgroundColour(bc)
+ self._Refresh()
+## dbg(indent=0, suspend=0)
+
+
+ def _getAbsValue(self, candidate=None):
+ """ Return an unsigned value (i.e. strip the '-' prefix if any), and sign position(s).
+ """
+## dbg('MaskedEditMixin::_getAbsValue; candidate="%s"' % candidate, indent=1)
+ if candidate is None: text = self._GetValue()
+ else: text = candidate
+ right_signpos = text.find(')')
+
+ if self._isInt:
+ if self._ctrl_constraints._alignRight and self._fields[0]._fillChar == ' ':
+ signpos = text.find('-')
+ if signpos == -1:
+## dbg('no - found; searching for (')
+ signpos = text.find('(')
+ elif signpos != -1:
+## dbg('- found at', signpos)
+ pass
+
+ if signpos == -1:
+## dbg('signpos still -1')
+## dbg('len(%s) (%d) < len(%s) (%d)?' % (text, len(text), self._mask, self._masklength), len(text) < self._masklength)
+ if len(text) < self._masklength:
+ text = ' ' + text
+ if len(text) < self._masklength:
+ text += ' '
+ if len(text) > self._masklength and text[-1] in (')', ' '):
+ text = text[:-1]
+ else:
+## dbg('len(%s) (%d), len(%s) (%d)' % (text, len(text), self._mask, self._masklength))
+## dbg('len(%s) - (len(%s) + 1):' % (text, text.lstrip()) , len(text) - (len(text.lstrip()) + 1))
+ signpos = len(text) - (len(text.lstrip()) + 1)
+
+ if self._useParens and not text.strip():
+ signpos -= 1 # empty value; use penultimate space
+## dbg('signpos:', signpos)
+ if signpos >= 0:
+ text = text[:signpos] + ' ' + text[signpos+1:]
+
+ else:
+ if self._signOk:
+ signpos = 0
+ text = self._template[0] + text[1:]
+ else:
+ signpos = -1
+
+ if right_signpos != -1:
+ if self._signOk:
+ text = text[:right_signpos] + ' ' + text[right_signpos+1:]
+ elif len(text) > self._masklength:
+ text = text[:right_signpos] + text[right_signpos+1:]
+ right_signpos = -1
+
+
+ elif self._useParens and self._signOk:
+ # figure out where it ought to go:
+ right_signpos = self._masklength - 1 # initial guess
+ if not self._ctrl_constraints._alignRight:
+## dbg('not right-aligned')
+ if len(text.strip()) == 0:
+ right_signpos = signpos + 1
+ elif len(text.strip()) < self._masklength:
+ right_signpos = len(text.rstrip())
+## dbg('right_signpos:', right_signpos)
+
+ groupchar = self._fields[0]._groupChar
+ try:
+ value = long(text.replace(groupchar,'').replace('(','-').replace(')','').replace(' ', ''))
+ except:
+## dbg('invalid number', indent=0)
+ return None, signpos, right_signpos
+
+ else: # float value
+ try:
+ groupchar = self._fields[0]._groupChar
+ value = float(text.replace(groupchar,'').replace(self._decimalChar, '.').replace('(', '-').replace(')','').replace(' ', ''))
+## dbg('value:', value)
+ except:
+ value = None
+
+ if value < 0 and value is not None:
+ signpos = text.find('-')
+ if signpos == -1:
+ signpos = text.find('(')
+
+ text = text[:signpos] + self._template[signpos] + text[signpos+1:]
+ else:
+ # look forwards up to the decimal point for the 1st non-digit
+## dbg('decimal pos:', self._decimalpos)
+## dbg('text: "%s"' % text)
+ if self._signOk:
+ signpos = self._decimalpos - (len(text[:self._decimalpos].lstrip()) + 1)
+ # prevent checking for empty string - Tomo - Wed 14 Jan 2004 03:19:09 PM CET
+ if len(text) >= signpos+1 and text[signpos+1] in ('-','('):
+ signpos += 1
+ else:
+ signpos = -1
+## dbg('signpos:', signpos)
+
+ if self._useParens:
+ if self._signOk:
+ right_signpos = self._masklength - 1
+ text = text[:right_signpos] + ' '
+ if text[signpos] == '(':
+ text = text[:signpos] + ' ' + text[signpos+1:]
+ else:
+ right_signpos = text.find(')')
+ if right_signpos != -1:
+ text = text[:-1]
+ right_signpos = -1
+
+ if value is None:
+## dbg('invalid number')
+ text = None
+
+## dbg('abstext = "%s"' % text, 'signpos:', signpos, 'right_signpos:', right_signpos)
+## dbg(indent=0)
+ return text, signpos, right_signpos
+
+
+ def _getSignedValue(self, candidate=None):
+ """ Return a signed value by adding a "-" prefix if the value
+ is set to negative, or a space if positive.
+ """
+## dbg('MaskedEditMixin::_getSignedValue; candidate="%s"' % candidate, indent=1)
+ if candidate is None: text = self._GetValue()
+ else: text = candidate
+
+
+ abstext, signpos, right_signpos = self._getAbsValue(text)
+ if self._signOk:
+ if abstext is None:
+## dbg(indent=0)
+ return abstext, signpos, right_signpos
+
+ if self._isNeg or text[signpos] in ('-', '('):
+ if self._useParens:
+ sign = '('
+ else:
+ sign = '-'
+ else:
+ sign = ' '
+ if abstext[signpos] not in string.digits:
+ text = abstext[:signpos] + sign + abstext[signpos+1:]
+ else:
+ # this can happen if value passed is too big; sign assumed to be
+ # in position 0, but if already filled with a digit, prepend sign...
+ text = sign + abstext
+ if self._useParens and text.find('(') != -1:
+ text = text[:right_signpos] + ')' + text[right_signpos+1:]
+ else:
+ text = abstext
+## dbg('signedtext = "%s"' % text, 'signpos:', signpos, 'right_signpos', right_signpos)
+## dbg(indent=0)
+ return text, signpos, right_signpos
+
+
+ def GetPlainValue(self, candidate=None):
+ """ Returns control's value stripped of the template text.
+ plainvalue = MaskedEditMixin.GetPlainValue()
+ """
+## dbg('MaskedEditMixin::GetPlainValue; candidate="%s"' % candidate, indent=1)
+
+ if candidate is None: text = self._GetValue()
+ else: text = candidate
+
+ if self.IsEmpty():
+## dbg('returned ""', indent=0)
+ return ""
+ else:
+ plain = ""
+ for idx in range( min(len(self._template), len(text)) ):
+ if self._mask[idx] in maskchars:
+ plain += text[idx]
+
+ if self._isFloat or self._isInt:
+## dbg('plain so far: "%s"' % plain)
+ plain = plain.replace('(', '-').replace(')', ' ')
+## dbg('plain after sign regularization: "%s"' % plain)
+
+ if self._signOk and self._isNeg and plain.count('-') == 0:
+ # must be in reserved position; add to "plain value"
+ plain = '-' + plain.strip()
+
+ if self._fields[0]._alignRight:
+ lpad = plain.count(',')
+ plain = ' ' * lpad + plain.replace(',','')
+ else:
+ plain = plain.replace(',','')
+## dbg('plain after pad and group:"%s"' % plain)
+
+## dbg('returned "%s"' % plain.rstrip(), indent=0)
+ return plain.rstrip()
+
+
+ def IsEmpty(self, value=None):
+ """
+ Returns True if control is equal to an empty value.
+ (Empty means all editable positions in the template == fillChar.)
+ """
+ if value is None: value = self._GetValue()
+ if value == self._template and not self._defaultValue:
+#### dbg("IsEmpty? 1 (value == self._template and not self._defaultValue)")
+ return True # (all mask chars == fillChar by defn)
+ elif value == self._template:
+ empty = True
+ for pos in range(len(self._template)):
+#### dbg('isMaskChar(%(pos)d)?' % locals(), self._isMaskChar(pos))
+#### dbg('value[%(pos)d] != self._fillChar?' %locals(), value[pos] != self._fillChar[pos])
+ if self._isMaskChar(pos) and value[pos] not in (' ', self._fillChar[pos]):
+ empty = False
+#### dbg("IsEmpty? %(empty)d (do all mask chars == fillChar?)" % locals())
+ return empty
+ else:
+#### dbg("IsEmpty? 0 (value doesn't match template)")
+ return False
+
+
+ def IsDefault(self, value=None):
+ """
+ Returns True if the value specified (or the value of the control if not specified)
+ is equal to the default value.
+ """
+ if value is None: value = self._GetValue()
+ return value == self._template
+
+
+ def IsValid(self, value=None):
+ """ Indicates whether the value specified (or the current value of the control
+ if not specified) is considered valid."""
+#### dbg('MaskedEditMixin::IsValid("%s")' % value, indent=1)
+ if value is None: value = self._GetValue()
+ ret = self._CheckValid(value)
+#### dbg(indent=0)
+ return ret
+
+
+ def _eraseSelection(self, value=None, sel_start=None, sel_to=None):
+ """ Used to blank the selection when inserting a new character. """
+## dbg("MaskedEditMixin::_eraseSelection", indent=1)
+ if value is None: value = self._GetValue()
+ if sel_start is None or sel_to is None:
+ sel_start, sel_to = self._GetSelection() ## check for a range of selected text
+## dbg('value: "%s"' % value)
+## dbg("current sel_start, sel_to:", sel_start, sel_to)
+
+ newvalue = list(value)
+ for i in range(sel_start, sel_to):
+ if self._signOk and newvalue[i] in ('-', '(', ')'):
+## dbg('found sign (%s) at' % newvalue[i], i)
+
+ # balance parentheses:
+ if newvalue[i] == '(':
+ right_signpos = value.find(')')
+ if right_signpos != -1:
+ newvalue[right_signpos] = ' '
+
+ elif newvalue[i] == ')':
+ left_signpos = value.find('(')
+ if left_signpos != -1:
+ newvalue[left_signpos] = ' '
+
+ newvalue[i] = ' '
+
+ elif self._isMaskChar(i):
+ field = self._FindField(i)
+ if field._padZero:
+ newvalue[i] = '0'
+ else:
+ newvalue[i] = self._template[i]
+
+ value = string.join(newvalue,"")
+## dbg('new value: "%s"' % value)
+## dbg(indent=0)
+ return value
+
+
+ def _insertKey(self, char, pos, sel_start, sel_to, value, allowAutoSelect=False):
+ """ Handles replacement of the character at the current insertion point."""
+## dbg('MaskedEditMixin::_insertKey', "\'" + char + "\'", pos, sel_start, sel_to, '"%s"' % value, indent=1)
+
+ text = self._eraseSelection(value)
+ field = self._FindField(pos)
+ start, end = field._extent
+ newtext = ""
+ newpos = pos
+
+ # if >= 2 chars selected in a right-insert field, do appropriate erase on field,
+ # then set selection to end, and do usual right insert.
+ if sel_start != sel_to and sel_to >= sel_start+2:
+ field = self._FindField(sel_start)
+ if( field._insertRight # if right-insert
+ and field._allowInsert # and allow insert at any point in field
+ and field == self._FindField(sel_to) ): # and selection all in same field
+ text = self._OnErase(just_return_value=True) # remove selection before insert
+## dbg('text after (left)erase: "%s"' % text)
+ pos = sel_start = sel_to
+
+ if pos != sel_start and sel_start == sel_to:
+ # adjustpos must have moved the position; make selection match:
+ sel_start = sel_to = pos
+
+## dbg('field._insertRight?', field._insertRight)
+## dbg('field._allowInsert?', field._allowInsert)
+## dbg('sel_start, end', sel_start, end)
+ if sel_start < end:
+## dbg('text[sel_start] != field._fillChar?', text[sel_start] != field._fillChar)
+ pass
+
+ if( field._insertRight # field allows right insert
+ and ((sel_start, sel_to) == field._extent # and whole field selected
+ or (sel_start == sel_to # or nothing selected
+ and (sel_start == end # and cursor at right edge
+ or (field._allowInsert # or field allows right-insert
+ and sel_start < end # next to other char in field:
+ and text[sel_start] != field._fillChar) ) ) ) ):
+## dbg('insertRight')
+ fstr = text[start:end]
+ erasable_chars = [field._fillChar, ' ']
+
+ # if zero padding field, or a single digit, and currently a value of 0, allow erasure of 0:
+ if field._padZero or (field._isInt and (end - start == 1) and fstr[0] == '0'):
+ erasable_chars.append('0')
+
+ erased = ''
+#### dbg("fstr[0]:'%s'" % fstr[0])
+#### dbg('field_index:', field._index)
+#### dbg("fstr[0] in erasable_chars?", fstr[0] in erasable_chars)
+#### dbg("self._signOk and field._index == 0 and fstr[0] in ('-','(')?", self._signOk and field._index == 0 and fstr[0] in ('-','('))
+ if fstr[0] in erasable_chars or (self._signOk and field._index == 0 and fstr[0] in ('-','(')):
+ erased = fstr[0]
+#### dbg('value: "%s"' % text)
+#### dbg('fstr: "%s"' % fstr)
+#### dbg("erased: '%s'" % erased)
+ field_sel_start = sel_start - start
+ field_sel_to = sel_to - start
+## dbg('left fstr: "%s"' % fstr[1:field_sel_start])
+## dbg('right fstr: "%s"' % fstr[field_sel_to:end])
+ fstr = fstr[1:field_sel_start] + char + fstr[field_sel_to:end]
+ if field._alignRight and sel_start != sel_to:
+ field_len = end - start
+## pos += (field_len - len(fstr)) # move cursor right by deleted amount
+ pos = sel_to
+## dbg('setting pos to:', pos)
+ if field._padZero:
+ fstr = '0' * (field_len - len(fstr)) + fstr
+ else:
+ fstr = fstr.rjust(field_len) # adjust the field accordingly
+## dbg('field str: "%s"' % fstr)
+
+ newtext = text[:start] + fstr + text[end:]
+ if erased in ('-', '(') and self._signOk:
+ newtext = erased + newtext[1:]
+## dbg('newtext: "%s"' % newtext)
+
+ if self._signOk and field._index == 0:
+ start -= 1 # account for sign position
+
+#### dbg('field._moveOnFieldFull?', field._moveOnFieldFull)
+#### dbg('len(fstr.lstrip()) == end-start?', len(fstr.lstrip()) == end-start)
+ if( field._moveOnFieldFull and pos == end
+ and len(fstr.lstrip()) == end-start # if field now full
+ and (not field._stopFieldChangeIfInvalid # and we either don't care about valid
+ or (field._stopFieldChangeIfInvalid # or we do and the current field value is valid
+ and field.IsValid(fstr)))):
+
+ newpos = self._findNextEntry(end) # go to next field
+ else:
+ newpos = pos # else keep cursor at current position
+
+ if not newtext:
+## dbg('not newtext')
+ if newpos != pos:
+## dbg('newpos:', newpos)
+ pass
+ if self._signOk and self._useParens:
+ old_right_signpos = text.find(')')
+
+ if field._allowInsert and not field._insertRight and sel_to <= end and sel_start >= start:
+## dbg('inserting within a left-insert-capable field')
+ field_len = end - start
+ before = text[start:sel_start]
+ after = text[sel_to:end].strip()
+#### dbg("current field:'%s'" % text[start:end])
+#### dbg("before:'%s'" % before, "after:'%s'" % after)
+ new_len = len(before) + len(after) + 1 # (for inserted char)
+#### dbg('new_len:', new_len)
+
+ if new_len < field_len:
+ retained = after + self._template[end-(field_len-new_len):end]
+ elif new_len > end-start:
+ retained = after[1:]
+ else:
+ retained = after
+
+ left = text[0:start] + before
+#### dbg("left:'%s'" % left, "retained:'%s'" % retained)
+ right = retained + text[end:]
+ else:
+ left = text[0:pos]
+ right = text[pos+1:]
+
+ if 'unicode' in wx.PlatformInfo and type(char) != types.UnicodeType:
+ # convert the keyboard constant to a unicode value, to
+ # ensure it can be concatenated into the control value:
+ char = char.decode(self._defaultEncoding)
+
+ newtext = left + char + right
+#### dbg('left: "%s"' % left)
+#### dbg('right: "%s"' % right)
+#### dbg('newtext: "%s"' % newtext)
+
+ if self._signOk and self._useParens:
+ # Balance parentheses:
+ left_signpos = newtext.find('(')
+
+ if left_signpos == -1: # erased '('; remove ')'
+ right_signpos = newtext.find(')')
+ if right_signpos != -1:
+ newtext = newtext[:right_signpos] + ' ' + newtext[right_signpos+1:]
+
+ elif old_right_signpos != -1:
+ right_signpos = newtext.find(')')
+
+ if right_signpos == -1: # just replaced right-paren
+ if newtext[pos] == ' ': # we just erased '); erase '('
+ newtext = newtext[:left_signpos] + ' ' + newtext[left_signpos+1:]
+ else: # replaced with digit; move ') over
+ if self._ctrl_constraints._alignRight or self._isFloat:
+ newtext = newtext[:-1] + ')'
+ else:
+ rstripped_text = newtext.rstrip()
+ right_signpos = len(rstripped_text)
+## dbg('old_right_signpos:', old_right_signpos, 'right signpos now:', right_signpos)
+ newtext = newtext[:right_signpos] + ')' + newtext[right_signpos+1:]
+
+ if( field._insertRight # if insert-right field (but we didn't start at right edge)
+ and field._moveOnFieldFull # and should move cursor when full
+ and len(newtext[start:end].strip()) == end-start # and field now full
+ and (not field._stopFieldChangeIfInvalid # and we either don't care about valid
+ or (field._stopFieldChangeIfInvalid # or we do and the current field value is valid
+ and field.IsValid(newtext[start:end].strip())))):
+
+ newpos = self._findNextEntry(end) # go to next field
+## dbg('newpos = nextentry =', newpos)
+ else:
+## dbg('pos:', pos, 'newpos:', pos+1)
+ newpos = pos+1
+
+
+ if allowAutoSelect:
+ new_select_to = newpos # (default return values)
+ match_field = None
+ match_index = None
+
+ if field._autoSelect:
+ match_index, partial_match = self._autoComplete(1, # (always forward)
+ field._compareChoices,
+ newtext[start:end],
+ compareNoCase=field._compareNoCase,
+ current_index = field._autoCompleteIndex-1)
+ if match_index is not None and partial_match:
+ matched_str = newtext[start:end]
+ newtext = newtext[:start] + field._choices[match_index] + newtext[end:]
+ new_select_to = end
+ match_field = field
+ if field._insertRight:
+ # adjust position to just after partial match in field
+ newpos = end - (len(field._choices[match_index].strip()) - len(matched_str.strip()))
+
+ elif self._ctrl_constraints._autoSelect:
+ match_index, partial_match = self._autoComplete(
+ 1, # (always forward)
+ self._ctrl_constraints._compareChoices,
+ newtext,
+ self._ctrl_constraints._compareNoCase,
+ current_index = self._ctrl_constraints._autoCompleteIndex - 1)
+ if match_index is not None and partial_match:
+ matched_str = newtext
+ newtext = self._ctrl_constraints._choices[match_index]
+ edit_end = self._ctrl_constraints._extent[1]
+ new_select_to = min(edit_end, len(newtext.rstrip()))
+ match_field = self._ctrl_constraints
+ if self._ctrl_constraints._insertRight:
+ # adjust position to just after partial match in control:
+ newpos = self._masklength - (len(self._ctrl_constraints._choices[match_index].strip()) - len(matched_str.strip()))
+
+## dbg('newtext: "%s"' % newtext, 'newpos:', newpos, 'new_select_to:', new_select_to)
+## dbg(indent=0)
+ return newtext, newpos, new_select_to, match_field, match_index
+ else:
+## dbg('newtext: "%s"' % newtext, 'newpos:', newpos)
+## dbg(indent=0)
+ return newtext, newpos
+
+
+ def _OnFocus(self,event):
+ """
+ This event handler is currently necessary to work around new default
+ behavior as of wxPython2.3.3;
+ The TAB key auto selects the entire contents of the wx.TextCtrl *after*
+ the EVT_SET_FOCUS event occurs; therefore we can't query/adjust the selection
+ *here*, because it hasn't happened yet. So to prevent this behavior, and
+ preserve the correct selection when the focus event is not due to tab,
+ we need to pull the following trick:
+ """
+## dbg('MaskedEditMixin::_OnFocus')
+ if self.IsBeingDeleted() or self.GetParent().IsBeingDeleted():
+ return
+ wx.CallAfter(self._fixSelection)
+ event.Skip()
+ self.Refresh()
+
+
+ def _CheckValid(self, candidate=None):
+ """
+ This is the default validation checking routine; It verifies that the
+ current value of the control is a "valid value," and has the side
+ effect of coloring the control appropriately.
+ """
+## dbg(suspend=1)
+## dbg('MaskedEditMixin::_CheckValid: candidate="%s"' % candidate, indent=1)
+ oldValid = self._valid
+ if candidate is None: value = self._GetValue()
+ else: value = candidate
+## dbg('value: "%s"' % value)
+ oldvalue = value
+ valid = True # assume True
+
+ if not self.IsDefault(value) and self._isDate: ## Date type validation
+ valid = self._validateDate(value)
+## dbg("valid date?", valid)
+
+ elif not self.IsDefault(value) and self._isTime:
+ valid = self._validateTime(value)
+## dbg("valid time?", valid)
+
+ elif not self.IsDefault(value) and (self._isInt or self._isFloat): ## Numeric type
+ valid = self._validateNumeric(value)
+## dbg("valid Number?", valid)
+
+ if valid: # and not self.IsDefault(value): ## generic validation accounts for IsDefault()
+ ## valid so far; ensure also allowed by any list or regex provided:
+ valid = self._validateGeneric(value)
+## dbg("valid value?", valid)
+
+## dbg('valid?', valid)
+
+ if not candidate:
+ self._valid = valid
+ self._applyFormatting()
+ if self._valid != oldValid:
+## dbg('validity changed: oldValid =',oldValid,'newvalid =', self._valid)
+## dbg('oldvalue: "%s"' % oldvalue, 'newvalue: "%s"' % self._GetValue())
+ pass
+## dbg(indent=0, suspend=0)
+ return valid
+
+
+ def _validateGeneric(self, candidate=None):
+ """ Validate the current value using the provided list or Regex filter (if any).
+ """
+ if candidate is None:
+ text = self._GetValue()
+ else:
+ text = candidate
+
+ valid = True # assume True
+ for i in [-1] + self._field_indices: # process global constraints first:
+ field = self._fields[i]
+ start, end = field._extent
+ slice = text[start:end]
+ valid = field.IsValid(slice)
+ if not valid:
+ break
+
+ return valid
+
+
+ def _validateNumeric(self, candidate=None):
+ """ Validate that the value is within the specified range (if specified.)"""
+ if candidate is None: value = self._GetValue()
+ else: value = candidate
+ try:
+ groupchar = self._fields[0]._groupChar
+ if self._isFloat:
+ number = float(value.replace(groupchar, '').replace(self._decimalChar, '.').replace('(', '-').replace(')', ''))
+ else:
+ number = long( value.replace(groupchar, '').replace('(', '-').replace(')', ''))
+ if value.strip():
+ if self._fields[0]._alignRight:
+ require_digit_at = self._fields[0]._extent[1]-1
+ else:
+ require_digit_at = self._fields[0]._extent[0]
+## dbg('require_digit_at:', require_digit_at)
+## dbg("value[rda]: '%s'" % value[require_digit_at])
+ if value[require_digit_at] not in list(string.digits):
+ valid = False
+ return valid
+ # else...
+## dbg('number:', number)
+ if self._ctrl_constraints._hasRange:
+ valid = self._ctrl_constraints._rangeLow <= number <= self._ctrl_constraints._rangeHigh
+ else:
+ valid = True
+ groupcharpos = value.rfind(groupchar)
+ if groupcharpos != -1: # group char present
+## dbg('groupchar found at', groupcharpos)
+ if self._isFloat and groupcharpos > self._decimalpos:
+ # 1st one found on right-hand side is past decimal point
+## dbg('groupchar in fraction; illegal')
+ return False
+ elif self._isFloat:
+ integer = value[:self._decimalpos].strip()
+ else:
+ integer = value.strip()
+## dbg("integer:'%s'" % integer)
+ if integer[0] in ('-', '('):
+ integer = integer[1:]
+ if integer[-1] == ')':
+ integer = integer[:-1]
+
+ parts = integer.split(groupchar)
+## dbg('parts:', parts)
+ for i in range(len(parts)):
+ if i == 0 and abs(int(parts[0])) > 999:
+## dbg('group 0 too long; illegal')
+ valid = False
+ break
+ elif i > 0 and (len(parts[i]) != 3 or ' ' in parts[i]):
+## dbg('group %i (%s) not right size; illegal' % (i, parts[i]))
+ valid = False
+ break
+ except ValueError:
+## dbg('value not a valid number')
+ valid = False
+ return valid
+
+
+ def _validateDate(self, candidate=None):
+ """ Validate the current date value using the provided Regex filter.
+ Generally used for character types.BufferType
+ """
+## dbg('MaskedEditMixin::_validateDate', indent=1)
+ if candidate is None: value = self._GetValue()
+ else: value = candidate
+## dbg('value = "%s"' % value)
+ text = self._adjustDate(value, force4digit_year=True) ## Fix the date up before validating it
+## dbg('text =', text)
+ valid = True # assume True until proven otherwise
+
+ try:
+ # replace fillChar in each field with space:
+ datestr = text[0:self._dateExtent]
+ for i in range(3):
+ field = self._fields[i]
+ start, end = field._extent
+ fstr = datestr[start:end]
+ fstr.replace(field._fillChar, ' ')
+ datestr = datestr[:start] + fstr + datestr[end:]
+
+ year, month, day = _getDateParts( datestr, self._datestyle)
+ year = int(year)
+## dbg('self._dateExtent:', self._dateExtent)
+ if self._dateExtent == 11:
+ month = charmonths_dict[month.lower()]
+ else:
+ month = int(month)
+ day = int(day)
+## dbg('year, month, day:', year, month, day)
+
+ except ValueError:
+## dbg('cannot convert string to integer parts')
+ valid = False
+ except KeyError:
+## dbg('cannot convert string to integer month')
+ valid = False
+
+ if valid:
+ # use wxDateTime to unambiguously try to parse the date:
+ # ### Note: because wxDateTime is *brain-dead* and expects months 0-11,
+ # rather than 1-12, so handle accordingly:
+ if month > 12:
+ valid = False
+ else:
+ month -= 1
+ try:
+## dbg("trying to create date from values day=%d, month=%d, year=%d" % (day,month,year))
+ dateHandler = wx.DateTimeFromDMY(day,month,year)
+## dbg("succeeded")
+ dateOk = True
+ except:
+## dbg('cannot convert string to valid date')
+ dateOk = False
+ if not dateOk:
+ valid = False
+
+ if valid:
+ # wxDateTime doesn't take kindly to leading/trailing spaces when parsing,
+ # so we eliminate them here:
+ timeStr = text[self._dateExtent+1:].strip() ## time portion of the string
+ if timeStr:
+## dbg('timeStr: "%s"' % timeStr)
+ try:
+ checkTime = dateHandler.ParseTime(timeStr)
+ valid = checkTime == len(timeStr)
+ except:
+ valid = False
+ if not valid:
+## dbg('cannot convert string to valid time')
+ pass
+## if valid: dbg('valid date')
+## dbg(indent=0)
+ return valid
+
+
+ def _validateTime(self, candidate=None):
+ """ Validate the current time value using the provided Regex filter.
+ Generally used for character types.BufferType
+ """
+## dbg('MaskedEditMixin::_validateTime', indent=1)
+ # wxDateTime doesn't take kindly to leading/trailing spaces when parsing,
+ # so we eliminate them here:
+ if candidate is None: value = self._GetValue().strip()
+ else: value = candidate.strip()
+## dbg('value = "%s"' % value)
+ valid = True # assume True until proven otherwise
+
+ dateHandler = wx.DateTime_Today()
+ try:
+ checkTime = dateHandler.ParseTime(value)
+## dbg('checkTime:', checkTime, 'len(value)', len(value))
+ valid = checkTime == len(value)
+ except:
+ valid = False
+
+ if not valid:
+## dbg('cannot convert string to valid time')
+ pass
+## if valid: dbg('valid time')
+## dbg(indent=0)
+ return valid
+
+
+ def _OnKillFocus(self,event):
+ """ Handler for EVT_KILL_FOCUS event.
+ """
+## dbg('MaskedEditMixin::_OnKillFocus', 'isDate=',self._isDate, indent=1)
+ if self.IsBeingDeleted() or self.GetParent().IsBeingDeleted():
+ return
+ if self._mask and self._IsEditable():
+ self._AdjustField(self._GetInsertionPoint())
+ self._CheckValid() ## Call valid handler
+
+ self._LostFocus() ## Provided for subclass use
+ event.Skip()
+## dbg(indent=0)
+
+
+ def _fixSelection(self):
+ """
+ This gets called after the TAB traversal selection is made, if the
+ focus event was due to this, but before the EVT_LEFT_* events if
+ the focus shift was due to a mouse event.
+
+ The trouble is that, a priori, there's no explicit notification of
+ why the focus event we received. However, the whole reason we need to
+ do this is because the default behavior on TAB traveral in a wx.TextCtrl is
+ now to select the entire contents of the window, something we don't want.
+ So we can *now* test the selection range, and if it's "the whole text"
+ we can assume the cause, change the insertion point to the start of
+ the control, and deselect.
+ """
+## dbg('MaskedEditMixin::_fixSelection', indent=1)
+ # can get here if called with wx.CallAfter after underlying
+ # control has been destroyed on close, but after focus
+ # events
+ if not self or not self._mask or not self._IsEditable():
+## dbg(indent=0)
+ return
+
+ sel_start, sel_to = self._GetSelection()
+## dbg('sel_start, sel_to:', sel_start, sel_to, 'self.IsEmpty()?', self.IsEmpty())
+
+ if( sel_start == 0 and sel_to >= len( self._mask ) #(can be greater in numeric controls because of reserved space)
+ and (not self._ctrl_constraints._autoSelect or self.IsEmpty() or self.IsDefault() ) ):
+ # This isn't normally allowed, and so assume we got here by the new
+ # "tab traversal" behavior, so we need to reset the selection
+ # and insertion point:
+## dbg('entire text selected; resetting selection to start of control')
+ self._goHome()
+ field = self._FindField(self._GetInsertionPoint())
+ edit_start, edit_end = field._extent
+ if field._selectOnFieldEntry:
+ if self._isFloat or self._isInt and field == self._fields[0]:
+ edit_start = 0
+ self._SetInsertionPoint(edit_start)
+ self._SetSelection(edit_start, edit_end)
+
+ elif field._insertRight:
+ self._SetInsertionPoint(edit_end)
+ self._SetSelection(edit_end, edit_end)
+
+ elif (self._isFloat or self._isInt):
+
+ text, signpos, right_signpos = self._getAbsValue()
+ if text is None or text == self._template:
+ integer = self._fields[0]
+ edit_start, edit_end = integer._extent
+
+ if integer._selectOnFieldEntry:
+## dbg('select on field entry:')
+ self._SetInsertionPoint(0)
+ self._SetSelection(0, edit_end)
+
+ elif integer._insertRight:
+## dbg('moving insertion point to end')
+ self._SetInsertionPoint(edit_end)
+ self._SetSelection(edit_end, edit_end)
+ else:
+## dbg('numeric ctrl is empty; start at beginning after sign')
+ self._SetInsertionPoint(signpos+1) ## Move past minus sign space if signed
+ self._SetSelection(signpos+1, signpos+1)
+
+ elif sel_start > self._goEnd(getPosOnly=True):
+## dbg('cursor beyond the end of the user input; go to end of it')
+ self._goEnd()
+ else:
+## dbg('sel_start, sel_to:', sel_start, sel_to, 'self._masklength:', self._masklength)
+ pass
+## dbg(indent=0)
+
+
+ def _Keypress(self,key):
+ """ Method provided to override OnChar routine. Return False to force
+ a skip of the 'normal' OnChar process. Called before class OnChar.
+ """
+ return True
+
+
+ def _LostFocus(self):
+ """ Method provided for subclasses. _LostFocus() is called after
+ the class processes its EVT_KILL_FOCUS event code.
+ """
+ pass
+
+
+ def _OnDoubleClick(self, event):
+ """ selects field under cursor on dclick."""
+ pos = self._GetInsertionPoint()
+ field = self._FindField(pos)
+ start, end = field._extent
+ self._SetInsertionPoint(start)
+ self._SetSelection(start, end)
+
+
+ def _Change(self):
+ """ Method provided for subclasses. Called by internal EVT_TEXT
+ handler. Return False to override the class handler, True otherwise.
+ """
+ return True
+
+
+ def _Cut(self):
+ """
+ Used to override the default Cut() method in base controls, instead
+ copying the selection to the clipboard and then blanking the selection,
+ leaving only the mask in the selected area behind.
+ Note: _Cut (read "undercut" ;-) must be called from a Cut() override in the
+ derived control because the mixin functions can't override a method of
+ a sibling class.
+ """
+## dbg("MaskedEditMixin::_Cut", indent=1)
+ value = self._GetValue()
+## dbg('current value: "%s"' % value)
+ sel_start, sel_to = self._GetSelection() ## check for a range of selected text
+## dbg('selected text: "%s"' % value[sel_start:sel_to].strip())
+ do = wx.TextDataObject()
+ do.SetText(value[sel_start:sel_to].strip())
+ wx.TheClipboard.Open()
+ wx.TheClipboard.SetData(do)
+ wx.TheClipboard.Close()
+
+ if sel_to - sel_start != 0:
+ self._OnErase()
+## dbg(indent=0)
+
+
+# WS Note: overriding Copy is no longer necessary given that you
+# can no longer select beyond the last non-empty char in the control.
+#
+## def _Copy( self ):
+## """
+## Override the wx.TextCtrl's .Copy function, with our own
+## that does validation. Need to strip trailing spaces.
+## """
+## sel_start, sel_to = self._GetSelection()
+## select_len = sel_to - sel_start
+## textval = wx.TextCtrl._GetValue(self)
+##
+## do = wx.TextDataObject()
+## do.SetText(textval[sel_start:sel_to].strip())
+## wx.TheClipboard.Open()
+## wx.TheClipboard.SetData(do)
+## wx.TheClipboard.Close()
+
+
+ def _getClipboardContents( self ):
+ """ Subroutine for getting the current contents of the clipboard.
+ """
+ do = wx.TextDataObject()
+ wx.TheClipboard.Open()
+ success = wx.TheClipboard.GetData(do)
+ wx.TheClipboard.Close()
+
+ if not success:
+ return None
+ else:
+ # Remove leading and trailing spaces before evaluating contents
+ return do.GetText().strip()
+
+
+ def _validatePaste(self, paste_text, sel_start, sel_to, raise_on_invalid=False):
+ """
+ Used by paste routine and field choice validation to see
+ if a given slice of paste text is legal for the area in question:
+ returns validity, replacement text, and extent of paste in
+ template.
+ """
+## dbg(suspend=1)
+## dbg('MaskedEditMixin::_validatePaste("%(paste_text)s", %(sel_start)d, %(sel_to)d), raise_on_invalid? %(raise_on_invalid)d' % locals(), indent=1)
+ select_length = sel_to - sel_start
+ maxlength = select_length
+## dbg('sel_to - sel_start:', maxlength)
+ if maxlength == 0:
+ maxlength = self._masklength - sel_start
+ item = 'control'
+ else:
+ item = 'selection'
+## dbg('maxlength:', maxlength)
+ if 'unicode' in wx.PlatformInfo and type(paste_text) != types.UnicodeType:
+ paste_text = paste_text.decode(self._defaultEncoding)
+
+ length_considered = len(paste_text)
+ if length_considered > maxlength:
+## dbg('paste text will not fit into the %s:' % item, indent=0)
+ if raise_on_invalid:
+## dbg(indent=0, suspend=0)
+ if item == 'control':
+ ve = ValueError('"%s" will not fit into the control "%s"' % (paste_text, self.name))
+ ve.value = paste_text
+ raise ve
+ else:
+ ve = ValueError('"%s" will not fit into the selection' % paste_text)
+ ve.value = paste_text
+ raise ve
+ else:
+## dbg(indent=0, suspend=0)
+ return False, None, None
+
+ text = self._template
+## dbg('length_considered:', length_considered)
+
+ valid_paste = True
+ replacement_text = ""
+ replace_to = sel_start
+ i = 0
+ while valid_paste and i < length_considered and replace_to < self._masklength:
+ if paste_text[i:] == self._template[replace_to:length_considered]:
+ # remainder of paste matches template; skip char-by-char analysis
+## dbg('remainder paste_text[%d:] (%s) matches template[%d:%d]' % (i, paste_text[i:], replace_to, length_considered))
+ replacement_text += paste_text[i:]
+ replace_to = i = length_considered
+ continue
+ # else:
+ char = paste_text[i]
+ field = self._FindField(replace_to)
+ if not field._compareNoCase:
+ if field._forceupper: char = char.upper()
+ elif field._forcelower: char = char.lower()
+
+## dbg('char:', "'"+char+"'", 'i =', i, 'replace_to =', replace_to)
+## dbg('self._isTemplateChar(%d)?' % replace_to, self._isTemplateChar(replace_to))
+ if not self._isTemplateChar(replace_to) and self._isCharAllowed( char, replace_to, allowAutoSelect=False, ignoreInsertRight=True):
+ replacement_text += char
+## dbg("not template(%(replace_to)d) and charAllowed('%(char)s',%(replace_to)d)" % locals())
+## dbg("replacement_text:", '"'+replacement_text+'"')
+ i += 1
+ replace_to += 1
+ elif( char == self._template[replace_to]
+ or (self._signOk and
+ ( (i == 0 and (char == '-' or (self._useParens and char == '(')))
+ or (i == self._masklength - 1 and self._useParens and char == ')') ) ) ):
+ replacement_text += char
+## dbg("'%(char)s' == template(%(replace_to)d)" % locals())
+## dbg("replacement_text:", '"'+replacement_text+'"')
+ i += 1
+ replace_to += 1
+ else:
+ next_entry = self._findNextEntry(replace_to, adjustInsert=False)
+ if next_entry == replace_to:
+ valid_paste = False
+ else:
+ replacement_text += self._template[replace_to:next_entry]
+## dbg("skipping template; next_entry =", next_entry)
+## dbg("replacement_text:", '"'+replacement_text+'"')
+ replace_to = next_entry # so next_entry will be considered on next loop
+
+ if not valid_paste and raise_on_invalid:
+## dbg('raising exception', indent=0, suspend=0)
+ ve = ValueError('"%s" cannot be inserted into the control "%s"' % (paste_text, self.name))
+ ve.value = paste_text
+ raise ve
+
+
+ elif i < len(paste_text):
+ valid_paste = False
+ if raise_on_invalid:
+## dbg('raising exception', indent=0, suspend=0)
+ ve = ValueError('"%s" will not fit into the control "%s"' % (paste_text, self.name))
+ ve.value = paste_text
+ raise ve
+
+## dbg('valid_paste?', valid_paste)
+ if valid_paste:
+## dbg('replacement_text: "%s"' % replacement_text, 'replace to:', replace_to)
+ pass
+## dbg(indent=0, suspend=0)
+ return valid_paste, replacement_text, replace_to
+
+
+ def _Paste( self, value=None, raise_on_invalid=False, just_return_value=False ):
+ """
+ Used to override the base control's .Paste() function,
+ with our own that does validation.
+ Note: _Paste must be called from a Paste() override in the
+ derived control because the mixin functions can't override a
+ method of a sibling class.
+ """
+## dbg('MaskedEditMixin::_Paste (value = "%s")' % value, indent=1)
+ if value is None:
+ paste_text = self._getClipboardContents()
+ else:
+ paste_text = value
+
+ if paste_text is not None:
+
+ if 'unicode' in wx.PlatformInfo and type(paste_text) != types.UnicodeType:
+ paste_text = paste_text.decode(self._defaultEncoding)
+
+## dbg('paste text: "%s"' % paste_text)
+ # (conversion will raise ValueError if paste isn't legal)
+ sel_start, sel_to = self._GetSelection()
+## dbg('selection:', (sel_start, sel_to))
+
+ # special case: handle allowInsert fields properly
+ field = self._FindField(sel_start)
+ edit_start, edit_end = field._extent
+ new_pos = None
+ if field._allowInsert and sel_to <= edit_end and (sel_start + len(paste_text) < edit_end or field._insertRight):
+ if field._insertRight:
+ # want to paste to the left; see if it will fit:
+ left_text = self._GetValue()[edit_start:sel_start].lstrip()
+## dbg('len(left_text):', len(left_text))
+## dbg('len(paste_text):', len(paste_text))
+## dbg('sel_start - (len(left_text) + len(paste_text)) >= edit_start?', sel_start - (len(left_text) + len(paste_text)) >= edit_start)
+ if sel_start - (len(left_text) - (sel_to - sel_start) + len(paste_text)) >= edit_start:
+ # will fit! create effective paste text, and move cursor back to do so:
+ paste_text = left_text + paste_text
+ sel_start -= len(left_text)
+ paste_text = paste_text.rjust(sel_to - sel_start)
+## dbg('modified paste_text to be: "%s"' % paste_text)
+## dbg('modified selection to:', (sel_start, sel_to))
+ else:
+## dbg("won't fit left;", 'paste text remains: "%s"' % paste_text)
+ pass
+ else:
+ paste_text = paste_text + self._GetValue()[sel_to:edit_end].rstrip()
+## dbg("allow insert, but not insert right;", 'paste text set to: "%s"' % paste_text)
+
+
+ new_pos = sel_start + len(paste_text) # store for subsequent positioning
+## dbg('paste within insertable field; adjusted paste_text: "%s"' % paste_text, 'end:', edit_end)
+## dbg('expanded selection to:', (sel_start, sel_to))
+
+ # Another special case: paste won't fit, but it's a right-insert field where entire
+ # non-empty value is selected, and there's room if the selection is expanded leftward:
+ if( len(paste_text) > sel_to - sel_start
+ and field._insertRight
+ and sel_start > edit_start
+ and sel_to >= edit_end
+ and not self._GetValue()[edit_start:sel_start].strip() ):
+ # text won't fit within selection, but left of selection is empty;
+ # check to see if we can expand selection to accommodate the value:
+ empty_space = sel_start - edit_start
+ amount_needed = len(paste_text) - (sel_to - sel_start)
+ if amount_needed <= empty_space:
+ sel_start -= amount_needed
+## dbg('expanded selection to:', (sel_start, sel_to))
+
+
+ # another special case: deal with signed values properly:
+ if self._signOk:
+ signedvalue, signpos, right_signpos = self._getSignedValue()
+ paste_signpos = paste_text.find('-')
+ if paste_signpos == -1:
+ paste_signpos = paste_text.find('(')
+
+ # if paste text will result in signed value:
+#### dbg('paste_signpos != -1?', paste_signpos != -1)
+#### dbg('sel_start:', sel_start, 'signpos:', signpos)
+#### dbg('field._insertRight?', field._insertRight)
+#### dbg('sel_start - len(paste_text) >= signpos?', sel_start - len(paste_text) <= signpos)
+ if paste_signpos != -1 and (sel_start <= signpos
+ or (field._insertRight and sel_start - len(paste_text) <= signpos)):
+ signed = True
+ else:
+ signed = False
+ # remove "sign" from paste text, so we can auto-adjust for sign type after paste:
+ paste_text = paste_text.replace('-', ' ').replace('(',' ').replace(')','')
+## dbg('unsigned paste text: "%s"' % paste_text)
+ else:
+ signed = False
+
+ # another special case: deal with insert-right fields when selection is empty and
+ # cursor is at end of field:
+#### dbg('field._insertRight?', field._insertRight)
+#### dbg('sel_start == edit_end?', sel_start == edit_end)
+#### dbg('sel_start', sel_start, 'sel_to', sel_to)
+ if field._insertRight and sel_start == edit_end and sel_start == sel_to:
+ sel_start -= len(paste_text)
+ if sel_start < 0:
+ sel_start = 0
+## dbg('adjusted selection:', (sel_start, sel_to))
+
+ raise_on_invalid = raise_on_invalid or field._raiseOnInvalidPaste
+ try:
+ valid_paste, replacement_text, replace_to = self._validatePaste(paste_text, sel_start, sel_to, raise_on_invalid)
+ except:
+## dbg('exception thrown', indent=0)
+ raise
+
+ if not valid_paste:
+## dbg('paste text not legal for the selection or portion of the control following the cursor;')
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+## dbg(indent=0)
+ return None, -1
+ # else...
+ text = self._eraseSelection()
+
+ new_text = text[:sel_start] + replacement_text + text[replace_to:]
+ if new_text:
+ new_text = string.ljust(new_text,self._masklength)
+ if signed:
+ new_text, signpos, right_signpos = self._getSignedValue(candidate=new_text)
+ if new_text:
+ if self._useParens:
+ new_text = new_text[:signpos] + '(' + new_text[signpos+1:right_signpos] + ')' + new_text[right_signpos+1:]
+ else:
+ new_text = new_text[:signpos] + '-' + new_text[signpos+1:]
+ if not self._isNeg:
+ self._isNeg = 1
+
+## dbg("new_text:", '"'+new_text+'"')
+
+ if not just_return_value:
+ if new_text != self._GetValue():
+ self.modified = True
+ if new_text == '':
+ self.ClearValue()
+ else:
+ wx.CallAfter(self._SetValue, new_text)
+ if new_pos is None:
+ new_pos = sel_start + len(replacement_text)
+ wx.CallAfter(self._SetInsertionPoint, new_pos)
+ else:
+## dbg(indent=0)
+ return new_text, replace_to
+ elif just_return_value:
+## dbg(indent=0)
+ return self._GetValue(), sel_to
+## dbg(indent=0)
+
+ def _Undo(self, value=None, prev=None, just_return_results=False):
+ """ Provides an Undo() method in base controls. """
+## dbg("MaskedEditMixin::_Undo", indent=1)
+ if value is None:
+ value = self._GetValue()
+ if prev is None:
+ prev = self._prevValue
+## dbg('current value: "%s"' % value)
+## dbg('previous value: "%s"' % prev)
+ if prev is None:
+## dbg('no previous value', indent=0)
+ return
+
+ elif value != prev:
+ # Determine what to select: (relies on fixed-length strings)
+ # (This is a lot harder than it would first appear, because
+ # of mask chars that stay fixed, and so break up the "diff"...)
+
+ # Determine where they start to differ:
+ i = 0
+ length = len(value) # (both are same length in masked control)
+
+ while( value[:i] == prev[:i] ):
+ i += 1
+ sel_start = i - 1
+
+
+ # handle signed values carefully, so undo from signed to unsigned or vice-versa
+ # works properly:
+ if self._signOk:
+ text, signpos, right_signpos = self._getSignedValue(candidate=prev)
+ if self._useParens:
+ if prev[signpos] == '(' and prev[right_signpos] == ')':
+ self._isNeg = True
+ else:
+ self._isNeg = False
+ # eliminate source of "far-end" undo difference if using balanced parens:
+ value = value.replace(')', ' ')
+ prev = prev.replace(')', ' ')
+ elif prev[signpos] == '-':
+ self._isNeg = True
+ else:
+ self._isNeg = False
+
+ # Determine where they stop differing in "undo" result:
+ sm = difflib.SequenceMatcher(None, a=value, b=prev)
+ i, j, k = sm.find_longest_match(sel_start, length, sel_start, length)
+## dbg('i,j,k = ', (i,j,k), 'value[i:i+k] = "%s"' % value[i:i+k], 'prev[j:j+k] = "%s"' % prev[j:j+k] )
+
+ if k == 0: # no match found; select to end
+ sel_to = length
+ else:
+ code_5tuples = sm.get_opcodes()
+ for op, i1, i2, j1, j2 in code_5tuples:
+## dbg("%7s value[%d:%d] (%s) prev[%d:%d] (%s)" % (op, i1, i2, value[i1:i2], j1, j2, prev[j1:j2]))
+ pass
+
+ diff_found = False
+ # look backward through operations needed to produce "previous" value;
+ # first change wins:
+ for next_op in range(len(code_5tuples)-1, -1, -1):
+ op, i1, i2, j1, j2 = code_5tuples[next_op]
+## dbg('value[i1:i2]: "%s"' % value[i1:i2], 'template[i1:i2] "%s"' % self._template[i1:i2])
+ field = self._FindField(i2)
+ if op == 'insert' and prev[j1:j2] != self._template[j1:j2]:
+## dbg('insert found: selection =>', (j1, j2))
+ sel_start = j1
+ sel_to = j2
+ diff_found = True
+ break
+ elif op == 'delete' and value[i1:i2] != self._template[i1:i2]:
+ edit_start, edit_end = field._extent
+ if field._insertRight and (field._allowInsert or i2 == edit_end):
+ sel_start = i2
+ sel_to = i2
+ else:
+ sel_start = i1
+ sel_to = j1
+## dbg('delete found: selection =>', (sel_start, sel_to))
+ diff_found = True
+ break
+ elif op == 'replace':
+ if not prev[i1:i2].strip() and field._insertRight:
+ sel_start = sel_to = j2
+ else:
+ sel_start = j1
+ sel_to = j2
+## dbg('replace found: selection =>', (sel_start, sel_to))
+ diff_found = True
+ break
+
+
+ if diff_found:
+ # now go forwards, looking for earlier changes:
+## dbg('searching forward...')
+ for next_op in range(len(code_5tuples)):
+ op, i1, i2, j1, j2 = code_5tuples[next_op]
+ field = self._FindField(i1)
+ if op == 'equal':
+ continue
+ elif op == 'replace':
+ if field._insertRight:
+ # if replace with spaces in an insert-right control, ignore "forward" replace
+ if not prev[i1:i2].strip():
+ continue
+ elif j1 < i1:
+## dbg('setting sel_start to', j1)
+ sel_start = j1
+ else:
+## dbg('setting sel_start to', i1)
+ sel_start = i1
+ else:
+## dbg('setting sel_start to', i1)
+ sel_start = i1
+## dbg('saw replace; breaking')
+ break
+ elif op == 'insert' and not value[i1:i2]:
+## dbg('forward %s found' % op)
+ if prev[j1:j2].strip():
+## dbg('item to insert non-empty; setting sel_start to', j1)
+ sel_start = j1
+ break
+ elif not field._insertRight:
+## dbg('setting sel_start to inserted space:', j1)
+ sel_start = j1
+ break
+ elif op == 'delete':
+## dbg('delete; field._insertRight?', field._insertRight, 'value[%d:%d].lstrip: "%s"' % (i1,i2,value[i1:i2].lstrip()))
+ if field._insertRight:
+ if value[i1:i2].lstrip():
+## dbg('setting sel_start to ', j1)
+ sel_start = j1
+## dbg('breaking loop')
+ break
+ else:
+ continue
+ else:
+## dbg('saw delete; breaking')
+ break
+ else:
+## dbg('unknown code!')
+ # we've got what we need
+ break
+
+
+ if not diff_found:
+## dbg('no insert,delete or replace found (!)')
+ # do "left-insert"-centric processing of difference based on l.c.s.:
+ if i == j and j != sel_start: # match starts after start of selection
+ sel_to = sel_start + (j-sel_start) # select to start of match
+ else:
+ sel_to = j # (change ends at j)
+
+
+ # There are several situations where the calculated difference is
+ # not what we want to select. If changing sign, or just adding
+ # group characters, we really don't want to highlight the characters
+ # changed, but instead leave the cursor where it is.
+ # Also, there a situations in which the difference can be ambiguous;
+ # Consider:
+ #
+ # current value: 11234
+ # previous value: 1111234
+ #
+ # Where did the cursor actually lie and which 1s were selected on the delete
+ # operation?
+ #
+ # Also, difflib can "get it wrong;" Consider:
+ #
+ # current value: " 128.66"
+ # previous value: " 121.86"
+ #
+ # difflib produces the following opcodes, which are sub-optimal:
+ # equal value[0:9] ( 12) prev[0:9] ( 12)
+ # insert value[9:9] () prev[9:11] (1.)
+ # equal value[9:10] (8) prev[11:12] (8)
+ # delete value[10:11] (.) prev[12:12] ()
+ # equal value[11:12] (6) prev[12:13] (6)
+ # delete value[12:13] (6) prev[13:13] ()
+ #
+ # This should have been:
+ # equal value[0:9] ( 12) prev[0:9] ( 12)
+ # replace value[9:11] (8.6) prev[9:11] (1.8)
+ # equal value[12:13] (6) prev[12:13] (6)
+ #
+ # But it didn't figure this out!
+ #
+ # To get all this right, we use the previous selection recorded to help us...
+
+ if (sel_start, sel_to) != self._prevSelection:
+## dbg('calculated selection', (sel_start, sel_to), "doesn't match previous", self._prevSelection)
+
+ prev_sel_start, prev_sel_to = self._prevSelection
+ field = self._FindField(sel_start)
+ if( self._signOk
+ and sel_start < self._masklength
+ and (prev[sel_start] in ('-', '(', ')')
+ or value[sel_start] in ('-', '(', ')')) ):
+ # change of sign; leave cursor alone...
+## dbg("prev[sel_start] in ('-', '(', ')')?", prev[sel_start] in ('-', '(', ')'))
+## dbg("value[sel_start] in ('-', '(', ')')?", value[sel_start] in ('-', '(', ')'))
+## dbg('setting selection to previous one')
+ sel_start, sel_to = self._prevSelection
+
+ elif field._groupdigits and (value[sel_start:sel_to] == field._groupChar
+ or prev[sel_start:sel_to] == field._groupChar):
+ # do not highlight grouping changes
+## dbg('value[sel_start:sel_to] == field._groupChar?', value[sel_start:sel_to] == field._groupChar)
+## dbg('prev[sel_start:sel_to] == field._groupChar?', prev[sel_start:sel_to] == field._groupChar)
+## dbg('setting selection to previous one')
+ sel_start, sel_to = self._prevSelection
+
+ else:
+ calc_select_len = sel_to - sel_start
+ prev_select_len = prev_sel_to - prev_sel_start
+
+## dbg('sel_start == prev_sel_start', sel_start == prev_sel_start)
+## dbg('sel_to > prev_sel_to', sel_to > prev_sel_to)
+
+ if prev_select_len >= calc_select_len:
+ # old selection was bigger; trust it:
+## dbg('prev_select_len >= calc_select_len?', prev_select_len >= calc_select_len)
+ if not field._insertRight:
+## dbg('setting selection to previous one')
+ sel_start, sel_to = self._prevSelection
+ else:
+ sel_to = self._prevSelection[1]
+## dbg('setting selection to', (sel_start, sel_to))
+
+ elif( sel_to > prev_sel_to # calculated select past last selection
+ and prev_sel_to < len(self._template) # and prev_sel_to not at end of control
+ and sel_to == len(self._template) ): # and calculated selection goes to end of control
+
+ i, j, k = sm.find_longest_match(prev_sel_to, length, prev_sel_to, length)
+## dbg('i,j,k = ', (i,j,k), 'value[i:i+k] = "%s"' % value[i:i+k], 'prev[j:j+k] = "%s"' % prev[j:j+k] )
+ if k > 0:
+ # difflib must not have optimized opcodes properly;
+ sel_to = j
+
+ else:
+ # look for possible ambiguous diff:
+
+ # if last change resulted in no selection, test from resulting cursor position:
+ if prev_sel_start == prev_sel_to:
+ calc_select_len = sel_to - sel_start
+ field = self._FindField(prev_sel_start)
+
+ # determine which way to search from last cursor position for ambiguous change:
+ if field._insertRight:
+ test_sel_start = prev_sel_start
+ test_sel_to = prev_sel_start + calc_select_len
+ else:
+ test_sel_start = prev_sel_start - calc_select_len
+ test_sel_to = prev_sel_start
+ else:
+ test_sel_start, test_sel_to = prev_sel_start, prev_sel_to
+
+## dbg('test selection:', (test_sel_start, test_sel_to))
+## dbg('calc change: "%s"' % prev[sel_start:sel_to])
+## dbg('test change: "%s"' % prev[test_sel_start:test_sel_to])
+
+ # if calculated selection spans characters, and same characters
+ # "before" the previous insertion point are present there as well,
+ # select the ones related to the last known selection instead.
+ if( sel_start != sel_to
+ and test_sel_to < len(self._template)
+ and prev[test_sel_start:test_sel_to] == prev[sel_start:sel_to] ):
+
+ sel_start, sel_to = test_sel_start, test_sel_to
+
+ # finally, make sure that the old and new values are
+ # different where we say they're different:
+ while( sel_to - 1 > 0
+ and sel_to > sel_start
+ and value[sel_to-1:] == prev[sel_to-1:]):
+ sel_to -= 1
+ while( sel_start + 1 < self._masklength
+ and sel_start < sel_to
+ and value[:sel_start+1] == prev[:sel_start+1]):
+ sel_start += 1
+
+## dbg('sel_start, sel_to:', sel_start, sel_to)
+## dbg('previous value: "%s"' % prev)
+## dbg(indent=0)
+ if just_return_results:
+ return prev, (sel_start, sel_to)
+ # else...
+ self._SetValue(prev)
+ self._SetInsertionPoint(sel_start)
+ self._SetSelection(sel_start, sel_to)
+
+ else:
+## dbg('no difference between previous value')
+## dbg(indent=0)
+ if just_return_results:
+ return prev, self._GetSelection()
+
+
+ def _OnClear(self, event):
+ """ Provides an action for context menu delete operation """
+ self.ClearValue()
+
+
+ def _OnContextMenu(self, event):
+## dbg('MaskedEditMixin::OnContextMenu()', indent=1)
+ menu = wx.Menu()
+ menu.Append(wx.ID_UNDO, "Undo", "")
+ menu.AppendSeparator()
+ menu.Append(wx.ID_CUT, "Cut", "")
+ menu.Append(wx.ID_COPY, "Copy", "")
+ menu.Append(wx.ID_PASTE, "Paste", "")
+ menu.Append(wx.ID_CLEAR, "Delete", "")
+ menu.AppendSeparator()
+ menu.Append(wx.ID_SELECTALL, "Select All", "")
+
+ wx.EVT_MENU(menu, wx.ID_UNDO, self._OnCtrl_Z)
+ wx.EVT_MENU(menu, wx.ID_CUT, self._OnCtrl_X)
+ wx.EVT_MENU(menu, wx.ID_COPY, self._OnCtrl_C)
+ wx.EVT_MENU(menu, wx.ID_PASTE, self._OnCtrl_V)
+ wx.EVT_MENU(menu, wx.ID_CLEAR, self._OnClear)
+ wx.EVT_MENU(menu, wx.ID_SELECTALL, self._OnCtrl_A)
+
+ # ## WSS: The base control apparently handles
+ # enable/disable of wx.ID_CUT, wx.ID_COPY, wx.ID_PASTE
+ # and wx.ID_CLEAR menu items even if the menu is one
+ # we created. However, it doesn't do undo properly,
+ # so we're keeping track of previous values ourselves.
+ # Therefore, we have to override the default update for
+ # that item on the menu:
+ wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self._UndoUpdateUI)
+ self._contextMenu = menu
+
+ self.PopupMenu(menu, event.GetPosition())
+ menu.Destroy()
+ self._contextMenu = None
+## dbg(indent=0)
+
+ def _UndoUpdateUI(self, event):
+ if self._prevValue is None or self._prevValue == self._curValue:
+ self._contextMenu.Enable(wx.ID_UNDO, False)
+ else:
+ self._contextMenu.Enable(wx.ID_UNDO, True)
+
+
+ def _OnCtrlParametersChanged(self):
+ """
+ Overridable function to allow derived classes to take action as a
+ result of parameter changes prior to possibly changing the value
+ of the control.
+ """
+ pass
+
+ ## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+class MaskedEditAccessorsMixin:
+ """
+ To avoid a ton of boiler-plate, and to automate the getter/setter generation
+ for each valid control parameter so we never forget to add the functions when
+ adding parameters, this class programmatically adds the masked edit mixin
+ parameters to itself.
+ (This makes it easier for Designers like Boa to deal with masked controls.)
+
+ To further complicate matters, this is done with an extra level of inheritance,
+ so that "general" classes like masked.TextCtrl can have all possible attributes,
+ while derived classes, like masked.TimeCtrl and masked.NumCtrl can prevent
+ exposure of those optional attributes of their base class that do not make
+ sense for their derivation.
+
+ Therefore, we define:
+ BaseMaskedTextCtrl(TextCtrl, MaskedEditMixin)
+ and
+ masked.TextCtrl(BaseMaskedTextCtrl, MaskedEditAccessorsMixin).
+
+ This allows us to then derive:
+ masked.NumCtrl( BaseMaskedTextCtrl )
+
+ and not have to expose all the same accessor functions for the
+ derived control when they don't all make sense for it.
+
+ """
+
+ # Define the default set of attributes exposed by the most generic masked controls:
+ exposed_basectrl_params = MaskedEditMixin.valid_ctrl_params.keys() + Field.valid_params.keys()
+ exposed_basectrl_params.remove('index')
+ exposed_basectrl_params.remove('extent')
+ exposed_basectrl_params.remove('foregroundColour') # (base class already has this)
+
+ for param in exposed_basectrl_params:
+ propname = param[0].upper() + param[1:]
+ exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
+ exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
+
+ if param.find('Colour') != -1:
+ # add non-british spellings, for backward-compatibility
+ propname.replace('Colour', 'Color')
+
+ exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
+ exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
+
+
+
+
+## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+## these are helper subroutines:
+
+def _movetofloat( origvalue, fmtstring, neg, addseparators=False, sepchar = ',',fillchar=' '):
+ """ addseparators = add separator character every three numerals if True
+ """
+ fmt0 = fmtstring.split('.')
+ fmt1 = fmt0[0]
+ fmt2 = fmt0[1]
+ val = origvalue.split('.')[0].strip()
+ ret = fillchar * (len(fmt1)-len(val)) + val + "." + "0" * len(fmt2)
+ if neg:
+ ret = '-' + ret[1:]
+ return (ret,len(fmt1))
+
+
+def _isDateType( fmtstring ):
+ """ Checks the mask and returns True if it fits an allowed
+ date or datetime format.
+ """
+ dateMasks = ("^##/##/####",
+ "^##-##-####",
+ "^##.##.####",
+ "^####/##/##",
+ "^####-##-##",
+ "^####.##.##",
+ "^##/CCC/####",
+ "^##.CCC.####",
+ "^##/##/##$",
+ "^##/##/## ",
+ "^##/CCC/##$",
+ "^##.CCC.## ",)
+ reString = "|".join(dateMasks)
+ filter = re.compile( reString)
+ if re.match(filter,fmtstring): return True
+ return False
+
+def _isTimeType( fmtstring ):
+ """ Checks the mask and returns True if it fits an allowed
+ time format.
+ """
+ reTimeMask = "^##:##(:##)?( (AM|PM))?"
+ filter = re.compile( reTimeMask )
+ if re.match(filter,fmtstring): return True
+ return False
+
+
+def _isFloatingPoint( fmtstring):
+ filter = re.compile("[ ]?[#]+\.[#]+\n")
+ if re.match(filter,fmtstring+"\n"): return True
+ return False
+
+
+def _isInteger( fmtstring ):
+ filter = re.compile("[#]+\n")
+ if re.match(filter,fmtstring+"\n"): return True
+ return False
+
+
+def _getDateParts( dateStr, dateFmt ):
+ if len(dateStr) > 11: clip = dateStr[0:11]
+ else: clip = dateStr
+ if clip[-2] not in string.digits:
+ clip = clip[:-1] # (got part of time; drop it)
+
+ dateSep = (('/' in clip) * '/') + (('-' in clip) * '-') + (('.' in clip) * '.')
+ slices = clip.split(dateSep)
+ if dateFmt == "MDY":
+ y,m,d = (slices[2],slices[0],slices[1]) ## year, month, date parts
+ elif dateFmt == "DMY":
+ y,m,d = (slices[2],slices[1],slices[0]) ## year, month, date parts
+ elif dateFmt == "YMD":
+ y,m,d = (slices[0],slices[1],slices[2]) ## year, month, date parts
+ else:
+ y,m,d = None, None, None
+ if not y:
+ return None
+ else:
+ return y,m,d
+
+
+def _getDateSepChar(dateStr):
+ clip = dateStr[0:10]
+ dateSep = (('/' in clip) * '/') + (('-' in clip) * '-') + (('.' in clip) * '.')
+ return dateSep
+
+
+def _makeDate( year, month, day, dateFmt, dateStr):
+ sep = _getDateSepChar( dateStr)
+ if dateFmt == "MDY":
+ return "%s%s%s%s%s" % (month,sep,day,sep,year) ## year, month, date parts
+ elif dateFmt == "DMY":
+ return "%s%s%s%s%s" % (day,sep,month,sep,year) ## year, month, date parts
+ elif dateFmt == "YMD":
+ return "%s%s%s%s%s" % (year,sep,month,sep,day) ## year, month, date parts
+ else:
+ return None
+
+
+def _getYear(dateStr,dateFmt):
+ parts = _getDateParts( dateStr, dateFmt)
+ return parts[0]
+
+def _getMonth(dateStr,dateFmt):
+ parts = _getDateParts( dateStr, dateFmt)
+ return parts[1]
+
+def _getDay(dateStr,dateFmt):
+ parts = _getDateParts( dateStr, dateFmt)
+ return parts[2]
+
+## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+class __test(wx.App):
+ def OnInit(self):
+ from wx.lib.rcsizer import RowColSizer
+ self.frame = wx.Frame( None, -1, "MaskedEditMixin 0.0.7 Demo Page #1", size = (700,600))
+ self.panel = wx.Panel( self.frame, -1)
+ self.sizer = RowColSizer()
+ self.labels = []
+ self.editList = []
+ rowcount = 4
+
+ id, id1 = wx.NewId(), wx.NewId()
+ self.command1 = wx.Button( self.panel, id, "&Close" )
+ self.command2 = wx.Button( self.panel, id1, "&AutoFormats" )
+ self.sizer.Add(self.command1, row=0, col=0, flag=wx.ALL, border = 5)
+ self.sizer.Add(self.command2, row=0, col=1, colspan=2, flag=wx.ALL, border = 5)
+ self.panel.Bind(wx.EVT_BUTTON, self.onClick, self.command1 )
+## self.panel.SetDefaultItem(self.command1 )
+ self.panel.Bind(wx.EVT_BUTTON, self.onClickPage, self.command2)
+
+ self.check1 = wx.CheckBox( self.panel, -1, "Disallow Empty" )
+ self.check2 = wx.CheckBox( self.panel, -1, "Highlight Empty" )
+ self.sizer.Add( self.check1, row=0,col=3, flag=wx.ALL,border=5 )
+ self.sizer.Add( self.check2, row=0,col=4, flag=wx.ALL,border=5 )
+ self.panel.Bind(wx.EVT_CHECKBOX, self._onCheck1, self.check1 )
+ self.panel.Bind(wx.EVT_CHECKBOX, self._onCheck2, self.check2 )
+
+
+ label = """Press ctrl-s in any field to output the value and plain value. Press ctrl-x to clear and re-set any field.
+Note that all controls have been auto-sized by including F in the format code.
+Try entering nonsensical or partial values in validated fields to see what happens (use ctrl-s to test the valid status)."""
+ label2 = "\nNote that the State and Last Name fields are list-limited (Name:Smith,Jones,Williams)."
+
+ self.label1 = wx.StaticText( self.panel, -1, label)
+ self.label2 = wx.StaticText( self.panel, -1, "Description")
+ self.label3 = wx.StaticText( self.panel, -1, "Mask Value")
+ self.label4 = wx.StaticText( self.panel, -1, "Format")
+ self.label5 = wx.StaticText( self.panel, -1, "Reg Expr Val. (opt)")
+ self.label6 = wx.StaticText( self.panel, -1, "MaskedEdit Ctrl")
+ self.label7 = wx.StaticText( self.panel, -1, label2)
+ self.label7.SetForegroundColour("Blue")
+ self.label1.SetForegroundColour("Blue")
+ self.label2.SetFont(wx.Font(9,wx.SWISS,wx.NORMAL,wx.BOLD))
+ self.label3.SetFont(wx.Font(9,wx.SWISS,wx.NORMAL,wx.BOLD))
+ self.label4.SetFont(wx.Font(9,wx.SWISS,wx.NORMAL,wx.BOLD))
+ self.label5.SetFont(wx.Font(9,wx.SWISS,wx.NORMAL,wx.BOLD))
+ self.label6.SetFont(wx.Font(9,wx.SWISS,wx.NORMAL,wx.BOLD))
+
+ self.sizer.Add( self.label1, row=1,col=0,colspan=7, flag=wx.ALL,border=5)
+ self.sizer.Add( self.label7, row=2,col=0,colspan=7, flag=wx.ALL,border=5)
+ self.sizer.Add( self.label2, row=3,col=0, flag=wx.ALL,border=5)
+ self.sizer.Add( self.label3, row=3,col=1, flag=wx.ALL,border=5)
+ self.sizer.Add( self.label4, row=3,col=2, flag=wx.ALL,border=5)
+ self.sizer.Add( self.label5, row=3,col=3, flag=wx.ALL,border=5)
+ self.sizer.Add( self.label6, row=3,col=4, flag=wx.ALL,border=5)
+
+ # The following list is of the controls for the demo. Feel free to play around with
+ # the options!
+ controls = [
+ #description mask excl format regexp range,list,initial
+ ("Phone No", "(###) ###-#### x:###", "", 'F!^-R', "^\(\d\d\d\) \d\d\d-\d\d\d\d", (),[],''),
+ ("Last Name Only", "C{14}", "", 'F {list}', '^[A-Z][a-zA-Z]+', (),('Smith','Jones','Williams'),''),
+ ("Full Name", "C{14}", "", 'F_', '^[A-Z][a-zA-Z]+ [A-Z][a-zA-Z]+', (),[],''),
+ ("Social Sec#", "###-##-####", "", 'F', "\d{3}-\d{2}-\d{4}", (),[],''),
+ ("U.S. Zip+4", "#{5}-#{4}", "", 'F', "\d{5}-(\s{4}|\d{4})",(),[],''),
+ ("U.S. State (2 char)\n(with default)","AA", "", 'F!', "[A-Z]{2}", (),states, 'AZ'),
+ ("Customer No", "\CAA-###", "", 'F!', "C[A-Z]{2}-\d{3}", (),[],''),
+ ("Date (MDY) + Time\n(with default)", "##/##/#### ##:## AM", 'BCDEFGHIJKLMNOQRSTUVWXYZ','DFR!',"", (),[], r'03/05/2003 12:00 AM'),
+ ("Invoice Total", "#{9}.##", "", 'F-R,', "", (),[], ''),
+ ("Integer (signed)\n(with default)", "#{6}", "", 'F-R', "", (),[], '0 '),
+ ("Integer (unsigned)\n(with default), 1-399", "######", "", 'F', "", (1,399),[], '1 '),
+ ("Month selector", "XXX", "", 'F', "", (),
+ ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],""),
+ ("fraction selector","#/##", "", 'F', "^\d\/\d\d?", (),
+ ['2/3', '3/4', '1/2', '1/4', '1/8', '1/16', '1/32', '1/64'], "")
+ ]
+
+ for control in controls:
+ self.sizer.Add( wx.StaticText( self.panel, -1, control[0]),row=rowcount, col=0,border=5,flag=wx.ALL)
+ self.sizer.Add( wx.StaticText( self.panel, -1, control[1]),row=rowcount, col=1,border=5, flag=wx.ALL)
+ self.sizer.Add( wx.StaticText( self.panel, -1, control[3]),row=rowcount, col=2,border=5, flag=wx.ALL)
+ self.sizer.Add( wx.StaticText( self.panel, -1, control[4][:20]),row=rowcount, col=3,border=5, flag=wx.ALL)
+
+ if control in controls[:]:#-2]:
+ newControl = MaskedTextCtrl( self.panel, -1, "",
+ mask = control[1],
+ excludeChars = control[2],
+ formatcodes = control[3],
+ includeChars = "",
+ validRegex = control[4],
+ validRange = control[5],
+ choices = control[6],
+ defaultValue = control[7],
+ demo = True)
+ if control[6]: newControl.SetCtrlParameters(choiceRequired = True)
+ else:
+ newControl = MaskedComboBox( self.panel, -1, "",
+ choices = control[7],
+ choiceRequired = True,
+ mask = control[1],
+ formatcodes = control[3],
+ excludeChars = control[2],
+ includeChars = "",
+ validRegex = control[4],
+ validRange = control[5],
+ demo = True)
+ self.editList.append( newControl )
+
+ self.sizer.Add( newControl, row=rowcount,col=4,flag=wx.ALL,border=5)
+ rowcount += 1
+
+ self.sizer.AddGrowableCol(4)
+
+ self.panel.SetSizer(self.sizer)
+ self.panel.SetAutoLayout(1)
+
+ self.frame.Show(1)
+ self.MainLoop()
+
+ return True
+
+ def onClick(self, event):
+ self.frame.Close()
+
+ def onClickPage(self, event):
+ self.page2 = __test2(self.frame,-1,"")
+ self.page2.Show(True)
+
+ def _onCheck1(self,event):
+ """ Set required value on/off """
+ value = event.IsChecked()
+ if value:
+ for control in self.editList:
+ control.SetCtrlParameters(emptyInvalid=True)
+ control.Refresh()
+ else:
+ for control in self.editList:
+ control.SetCtrlParameters(emptyInvalid=False)
+ control.Refresh()
+ self.panel.Refresh()
+
+ def _onCheck2(self,event):
+ """ Highlight empty values"""
+ value = event.IsChecked()
+ if value:
+ for control in self.editList:
+ control.SetCtrlParameters( emptyBackgroundColour = 'Aquamarine')
+ control.Refresh()
+ else:
+ for control in self.editList:
+ control.SetCtrlParameters( emptyBackgroundColour = 'White')
+ control.Refresh()
+ self.panel.Refresh()
+
+
+## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+class __test2(wx.Frame):
+ def __init__(self, parent, id, caption):
+ wx.Frame.__init__( self, parent, id, "MaskedEdit control 0.0.7 Demo Page #2 -- AutoFormats", size = (550,600))
+ from wx.lib.rcsizer import RowColSizer
+ self.panel = wx.Panel( self, -1)
+ self.sizer = RowColSizer()
+ self.labels = []
+ self.texts = []
+ rowcount = 4
+
+ label = """\
+All these controls have been created by passing a single parameter, the AutoFormat code.
+The class contains an internal dictionary of types and formats (autoformats).
+To see a great example of validations in action, try entering a bad email address, then tab out."""
+
+ self.label1 = wx.StaticText( self.panel, -1, label)
+ self.label2 = wx.StaticText( self.panel, -1, "Description")
+ self.label3 = wx.StaticText( self.panel, -1, "AutoFormat Code")
+ self.label4 = wx.StaticText( self.panel, -1, "MaskedEdit Control")
+ self.label1.SetForegroundColour("Blue")
+ self.label2.SetFont(wx.Font(9,wx.SWISS,wx.NORMAL,wx.BOLD))
+ self.label3.SetFont(wx.Font(9,wx.SWISS,wx.NORMAL,wx.BOLD))
+ self.label4.SetFont(wx.Font(9,wx.SWISS,wx.NORMAL,wx.BOLD))
+
+ self.sizer.Add( self.label1, row=1,col=0,colspan=3, flag=wx.ALL,border=5)
+ self.sizer.Add( self.label2, row=3,col=0, flag=wx.ALL,border=5)
+ self.sizer.Add( self.label3, row=3,col=1, flag=wx.ALL,border=5)
+ self.sizer.Add( self.label4, row=3,col=2, flag=wx.ALL,border=5)
+
+ id, id1 = wx.NewId(), wx.NewId()
+ self.command1 = wx.Button( self.panel, id, "&Close")
+ self.command2 = wx.Button( self.panel, id1, "&Print Formats")
+ self.panel.Bind(wx.EVT_BUTTON, self.onClick, self.command1)
+ self.panel.SetDefaultItem(self.command1)
+ self.panel.Bind(wx.EVT_BUTTON, self.onClickPrint, self.command2)
+
+ # The following list is of the controls for the demo. Feel free to play around with
+ # the options!
+ controls = [
+ ("Phone No","USPHONEFULLEXT"),
+ ("US Date + Time","USDATETIMEMMDDYYYY/HHMM"),
+ ("US Date MMDDYYYY","USDATEMMDDYYYY/"),
+ ("Time (with seconds)","TIMEHHMMSS"),
+ ("Military Time\n(without seconds)","24HRTIMEHHMM"),
+ ("Social Sec#","USSOCIALSEC"),
+ ("Credit Card","CREDITCARD"),
+ ("Expiration MM/YY","EXPDATEMMYY"),
+ ("Percentage","PERCENT"),
+ ("Person's Age","AGE"),
+ ("US Zip Code","USZIP"),
+ ("US Zip+4","USZIPPLUS4"),
+ ("Email Address","EMAIL"),
+ ("IP Address", "(derived control IpAddrCtrl)")
+ ]
+
+ for control in controls:
+ self.sizer.Add( wx.StaticText( self.panel, -1, control[0]),row=rowcount, col=0,border=5,flag=wx.ALL)
+ self.sizer.Add( wx.StaticText( self.panel, -1, control[1]),row=rowcount, col=1,border=5, flag=wx.ALL)
+ if control in controls[:-1]:
+ self.sizer.Add( MaskedTextCtrl( self.panel, -1, "",
+ autoformat = control[1],
+ demo = True),
+ row=rowcount,col=2,flag=wx.ALL,border=5)
+ else:
+ self.sizer.Add( IpAddrCtrl( self.panel, -1, "", demo=True ),
+ row=rowcount,col=2,flag=wx.ALL,border=5)
+ rowcount += 1
+
+ self.sizer.Add(self.command1, row=0, col=0, flag=wx.ALL, border = 5)
+ self.sizer.Add(self.command2, row=0, col=1, flag=wx.ALL, border = 5)
+ self.sizer.AddGrowableCol(3)
+
+ self.panel.SetSizer(self.sizer)
+ self.panel.SetAutoLayout(1)
+
+ def onClick(self, event):
+ self.Close()
+
+ def onClickPrint(self, event):
+ for format in masktags.keys():
+ sep = "+------------------------+"
+ print "%s\n%s \n Mask: %s \n RE Validation string: %s\n" % (sep,format, masktags[format]['mask'], masktags[format]['validRegex'])
+
+## ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+if __name__ == "__main__":
+ app = __test(False)
+
+__i=0
+##
+## Current Issues:
+## ===================================
+##
+## 1. WS: For some reason I don't understand, the control is generating two (2)
+## EVT_TEXT events for every one (1) .SetValue() of the underlying control.
+## I've been unsuccessful in determining why or in my efforts to make just one
+## occur. So, I've added a hack to save the last seen value from the
+## control in the EVT_TEXT handler, and if *different*, call event.Skip()
+## to propagate it down the event chain, and let the application see it.
+##
+## 2. WS: MaskedComboBox is deficient in several areas, all having to do with the
+## behavior of the underlying control that I can't fix. The problems are:
+## a) The background coloring doesn't work in the text field of the control;
+## instead, there's a only border around it that assumes the correct color.
+## b) The control will not pass WXK_TAB to the event handler, no matter what
+## I do, and there's no style wxCB_PROCESS_TAB like wxTE_PROCESS_TAB to
+## indicate that we want these events. As a result, MaskedComboBox
+## doesn't do the nice field-tabbing that MaskedTextCtrl does.
+## c) Auto-complete had to be reimplemented for the control because programmatic
+## setting of the value of the text field does not set up the auto complete
+## the way that the control processing keystrokes does. (But I think I've
+## implemented a fairly decent approximation.) Because of this the control
+## also won't auto-complete on dropdown, and there's no event I can catch
+## to work around this problem.
+## d) There is no method provided for getting the selection; the hack I've
+## implemented has its flaws, not the least of which is that due to the
+## strategy that I'm using, the paste buffer is always replaced by the
+## contents of the control's selection when in focus, on each keystroke;
+## this makes it impossible to paste anything into a MaskedComboBox
+## at the moment... :-(
+## e) The other deficient behavior, likely induced by the workaround for (d),
+## is that you can can't shift-left to select more than one character
+## at a time.
+##
+##
+## 3. WS: Controls on wxPanels don't seem to pass Shift-WXK_TAB to their
+## EVT_KEY_DOWN or EVT_CHAR event handlers. Until this is fixed in
+## wxWindows, shift-tab won't take you backwards through the fields of
+## a MaskedTextCtrl like it should. Until then Shifted arrow keys will
+## work like shift-tab and tab ought to.
+##
+
+## To-Do's:
+## =============================##
+## 1. Add Popup list for auto-completable fields that simulates combobox on individual
+## fields. Example: City validates against list of cities, or zip vs zip code list.
+## 2. Allow optional monetary symbols (eg. $, pounds, etc.) at front of a "decimal"
+## control.
+## 3. Fix shift-left selection for MaskedComboBox.
+## 5. Transform notion of "decimal control" to be less "entire control"-centric,
+## so that monetary symbols can be included and still have the appropriate
+## semantics. (Big job, as currently written, but would make control even
+## more useful for business applications.)
+
+
+## CHANGELOG:
+## ====================
+## Version 1.13
+## 1. Added parameter option stopFieldChangeIfInvalid, which can be used to relax the
+## validation rules for a control, but make best efforts to stop navigation out of
+## that field should its current value be invalid. Note: this does not prevent the
+## value from remaining invalid if focus for the control is lost, via mousing etc.
+##
+## Version 1.12
+## 1. Added proper support for NUMPAD keypad keycodes for navigation and control.
+##
+## Version 1.11
+## 1. Added value member to ValueError exceptions, so that people can catch them
+## and then display their own errors, and added attribute raiseOnInvalidPaste,
+## so one doesn't have to subclass the controls simply to force generation of
+## a ValueError on a bad paste operation.
+## 2. Fixed handling of unicode charsets by converting to explicit control char
+## set testing for passing those keystrokes to the base control, and then
+## changing the semantics of the * maskchar to indicate any visible char.
+## 3. Added '|' mask specification character, which allows splitting of contiguous
+## mask characters into separate fields, allowing finer control of behavior
+## of a control.
+##
+##
+## Version 1.10
+## 1. Added handling for WXK_DELETE and WXK_INSERT, such that shift-delete
+## cuts, shift-insert pastes, and ctrl-insert copies.
+##
+## Version 1.9
+## 1. Now ignores kill focus events when being destroyed.
+## 2. Added missing call to set insertion point on changing fields.
+## 3. Modified SetKeyHandler() to accept None as means of removing one.
+## 4. Fixed keyhandler processing for group and decimal character changes.
+## 5. Fixed a problem that prevented input into the integer digit of a
+## integerwidth=1 numctrl, if the current value was 0.
+## 6. Fixed logic involving processing of "_signOk" flag, to remove default
+## sign key handlers if false, so that SetAllowNegative(False) in the
+## NumCtrl works properly.
+## 7. Fixed selection logic for numeric controls so that if selectOnFieldEntry
+## is true, and the integer portion of an integer format control is selected
+## and the sign position is selected, the sign keys will always result in a
+## negative value, rather than toggling the previous sign.
+##
+##
+## Version 1.8
+## 1. Fixed bug involving incorrect variable name, causing combobox autocomplete to fail.
+## 2. Added proper support for unicode version of wxPython
+## 3. Added * as mask char meaning "all ansi chars" (ordinals 32-255).
+## 4. Converted doc strings to use reST format, for ePyDoc documentation.
+## 5. Renamed helper functions, classes, etc. not intended to be visible in public
+## interface to code.
+##
+## Version 1.7
+## 1. Fixed intra-right-insert-field erase, such that it doesn't leave a hole, but instead
+## shifts the text to the left accordingly.
+## 2. Fixed _SetValue() to place cursor after last character inserted, rather than end of
+## mask.
+## 3. Fixed some incorrect undo behavior for right-insert fields, and allowed derived classes
+## (eg. numctrl) to pass modified values for undo processing (to handle/ignore grouping
+## chars properly.)
+## 4. Fixed autoselect behavior to work similarly to (2) above, so that combobox
+## selection will only select the non-empty text, as per request.
+## 5. Fixed tabbing to work with 2.5.2 semantics.
+## 6. Fixed size calculation to handle changing fonts
+##
+## Version 1.6
+## 1. Reorganized masked controls into separate package, renamed things accordingly
+## 2. Split actual controls out of this file into their own files.
+## Version 1.5
+## (Reported) bugs fixed:
+## 1. Crash ensues if you attempt to change the mask of a read-only
+## MaskedComboBox after initial construction.
+## 2. Changed strategy of defining Get/Set property functions so that
+## these are now generated dynamically at runtime, rather than as
+## part of the class definition. (This makes it possible to have
+## more general base classes that have many more options for configuration
+## without requiring that derivations support the same options.)
+## 3. Fixed IsModified for _Paste() and _OnErase().
+##
+## Enhancements:
+## 1. Fixed "attribute function inheritance," since base control is more
+## generic than subsequent derivations, not all property functions of a
+## generic control should be exposed in those derivations. New strategy
+## uses base control classes (eg. BaseMaskedTextCtrl) that should be
+## used to derive new class types, and mixed with their own mixins to
+## only expose those attributes from the generic masked controls that
+## make sense for the derivation. (This makes Boa happier.)
+## 2. Renamed (with b-c) MILTIME autoformats to 24HRTIME, so as to be less
+## "parochial."
+##
+## Version 1.4
+## (Reported) bugs fixed:
+## 1. Right-click menu allowed "cut" operation that destroyed mask
+## (was implemented by base control)
+## 2. MaskedComboBox didn't allow .Append() of mixed-case values; all
+## got converted to lower case.
+## 3. MaskedComboBox selection didn't deal with spaces in values
+## properly when autocompleting, and didn't have a concept of "next"
+## match for handling choice list duplicates.
+## 4. Size of MaskedComboBox was always default.
+## 5. Email address regexp allowed some "non-standard" things, and wasn't
+## general enough.
+## 6. Couldn't easily reset MaskedComboBox contents programmatically.
+## 7. Couldn't set emptyInvalid during construction.
+## 8. Under some versions of wxPython, readonly comboboxes can apparently
+## return a GetInsertionPoint() result (655535), causing masked control
+## to fail.
+## 9. Specifying an empty mask caused the controls to traceback.
+## 10. Can't specify float ranges for validRange.
+## 11. '.' from within a the static portion of a restricted IP address
+## destroyed the mask from that point rightward; tab when cursor is
+## before 1st field takes cursor past that field.
+##
+## Enhancements:
+## 12. Added Ctrl-Z/Undo handling, (and implemented context-menu properly.)
+## 13. Added auto-select option on char input for masked controls with
+## choice lists.
+## 14. Added '>' formatcode, allowing insert within a given or each field
+## as appropriate, rather than requiring "overwrite". This makes single
+## field controls that just have validation rules (eg. EMAIL) much more
+## friendly. The same flag controls left shift when deleting vs just
+## blanking the value, and for right-insert fields, allows right-insert
+## at any non-blank (non-sign) position in the field.
+## 15. Added option to use to indicate negative values for numeric controls.
+## 16. Improved OnFocus handling of numeric controls.
+## 17. Enhanced Home/End processing to allow operation on a field level,
+## using ctrl key.
+## 18. Added individual Get/Set functions for control parameters, for
+## simplified integration with Boa Constructor.
+## 19. Standardized "Colour" parameter names to match wxPython, with
+## non-british spellings still supported for backward-compatibility.
+## 20. Added '&' mask specification character for punctuation only (no letters
+## or digits).
+## 21. Added (in a separate file) wx.MaskedCtrl() factory function to provide
+## unified interface to the masked edit subclasses.
+##
+##
+## Version 1.3
+## 1. Made it possible to configure grouping, decimal and shift-decimal characters,
+## to make controls more usable internationally.
+## 2. Added code to smart "adjust" value strings presented to .SetValue()
+## for right-aligned numeric format controls if they are shorter than
+## than the control width, prepending the missing portion, prepending control
+## template left substring for the missing characters, so that setting
+## numeric values is easier.
+## 3. Renamed SetMaskParameters SetCtrlParameters() (with old name preserved
+## for b-c), as this makes more sense.
+##
+## Version 1.2
+## 1. Fixed .SetValue() to replace the current value, rather than the current
+## selection. Also changed it to generate ValueError if presented with
+## either a value which doesn't follow the format or won't fit. Also made
+## set value adjust numeric and date controls as if user entered the value.
+## Expanded doc explaining how SetValue() works.
+## 2. Fixed EUDATE* autoformats, fixed IsDateType mask list, and added ability to
+## use 3-char months for dates, and EUDATETIME, and EUDATEMILTIME autoformats.
+## 3. Made all date autoformats automatically pick implied "datestyle".
+## 4. Added IsModified override, since base wx.TextCtrl never reports modified if
+## .SetValue used to change the value, which is what the masked edit controls
+## use internally.
+## 5. Fixed bug in date position adjustment on 2 to 4 digit date conversion when
+## using tab to "leave field" and auto-adjust.
+## 6. Fixed bug in _isCharAllowed() for negative number insertion on pastes,
+## and bug in ._Paste() that didn't account for signs in signed masks either.
+## 7. Fixed issues with _adjustPos for right-insert fields causing improper
+## selection/replacement of values
+## 8. Fixed _OnHome handler to properly handle extending current selection to
+## beginning of control.
+## 9. Exposed all (valid) autoformats to demo, binding descriptions to
+## autoformats.
+## 10. Fixed a couple of bugs in email regexp.
+## 11. Made maskchardict an instance var, to make mask chars to be more
+## amenable to international use.
+## 12. Clarified meaning of '-' formatcode in doc.
+## 13. Fixed a couple of coding bugs being flagged by Python2.1.
+## 14. Fixed several issues with sign positioning, erasure and validity
+## checking for "numeric" masked controls.
+## 15. Added validation to IpAddrCtrl.SetValue().
+##
+## Version 1.1
+## 1. Changed calling interface to use boolean "useFixedWidthFont" (True by default)
+## vs. literal font facename, and use wxTELETYPE as the font family
+## if so specified.
+## 2. Switched to use of dbg module vs. locally defined version.
+## 3. Revamped entire control structure to use Field classes to hold constraint
+## and formatting data, to make code more hierarchical, allow for more
+## sophisticated masked edit construction.
+## 4. Better strategy for managing options, and better validation on keywords.
+## 5. Added 'V' format code, which requires that in order for a character
+## to be accepted, it must result in a string that passes the validRegex.
+## 6. Added 'S' format code which means "select entire field when navigating
+## to new field."
+## 7. Added 'r' format code to allow "right-insert" fields. (implies 'R'--right-alignment)
+## 8. Added '<' format code to allow fields to require explicit cursor movement
+## to leave field.
+## 9. Added validFunc option to other validation mechanisms, that allows derived
+## classes to add dynamic validation constraints to the control.
+## 10. Fixed bug in validatePaste code causing possible IndexErrors, and also
+## fixed failure to obey case conversion codes when pasting.
+## 11. Implemented '0' (zero-pad) formatting code, as it wasn't being done anywhere...
+## 12. Removed condition from OnDecimalPoint, so that it always truncates right on '.'
+## 13. Enhanced IpAddrCtrl to use right-insert fields, selection on field traversal,
+## individual field validation to prevent field values > 255, and require explicit
+## tab/. to change fields.
+## 14. Added handler for left double-click to select field under cursor.
+## 15. Fixed handling for "Read-only" styles.
+## 16. Separated signedForegroundColor from 'R' style, and added foregroundColor
+## attribute, for more consistent and controllable coloring.
+## 17. Added retainFieldValidation parameter, allowing top-level constraints
+## such as "validRequired" to be set independently of field-level equivalent.
+## (needed in TimeCtrl for bounds constraints.)
+## 18. Refactored code a bit, cleaned up and commented code more heavily, fixed
+## some of the logic for setting/resetting parameters, eg. fillChar, defaultValue,
+## etc.
+## 19. Fixed maskchar setting for upper/lowercase, to work in all locales.
+##
+##
+## Version 1.0
+## 1. Decimal point behavior restored for decimal and integer type controls:
+## decimal point now trucates the portion > 0.
+## 2. Return key now works like the tab character and moves to the next field,
+## provided no default button is set for the form panel on which the control
+## resides.
+## 3. Support added in _FindField() for subclasses controls (like timecontrol)
+## to determine where the current insertion point is within the mask (i.e.
+## which sub-'field'). See method documentation for more info and examples.
+## 4. Added Field class and support for all constraints to be field-specific
+## in addition to being globally settable for the control.
+## Choices for each field are validated for length and pastability into
+## the field in question, raising ValueError if not appropriate for the control.
+## Also added selective additional validation based on individual field constraints.
+## By default, SHIFT-WXK_DOWN, SHIFT-WXK_UP, WXK_PRIOR and WXK_NEXT all
+## auto-complete fields with choice lists, supplying the 1st entry in
+## the choice list if the field is empty, and cycling through the list in
+## the appropriate direction if already a match. WXK_DOWN will also auto-
+## complete if the field is partially completed and a match can be made.
+## SHIFT-WXK_UP/DOWN will also take you to the next field after any
+## auto-completion performed.
+## 5. Added autoCompleteKeycodes=[] parameters for allowing further
+## customization of the control. Any keycode supplied as a member
+## of the _autoCompleteKeycodes list will be treated like WXK_NEXT. If
+## requireFieldChoice is set, then a valid value from each non-empty
+## choice list will be required for the value of the control to validate.
+## 6. Fixed "auto-sizing" to be relative to the font actually used, rather
+## than making assumptions about character width.
+## 7. Fixed GetMaskParameter(), which was non-functional in previous version.
+## 8. Fixed exceptions raised to provide info on which control had the error.
+## 9. Fixed bug in choice management of MaskedComboBox.
+## 10. Fixed bug in IpAddrCtrl causing traceback if field value was of
+## the form '# #'. Modified control code for IpAddrCtrl so that '.'
+## in the middle of a field clips the rest of that field, similar to
+## decimal and integer controls.
+##
+##
+## Version 0.0.7
+## 1. "-" is a toggle for sign; "+" now changes - signed numerics to positive.
+## 2. ',' in formatcodes now causes numeric values to be comma-delimited (e.g.333,333).
+## 3. New support for selecting text within the control.(thanks Will Sadkin!)
+## Shift-End and Shift-Home now select text as you would expect
+## Control-Shift-End selects to the end of the mask string, even if value not entered.
+## Control-A selects all *entered* text, Shift-Control-A selects everything in the control.
+## 4. event.Skip() added to onKillFocus to correct remnants when running in Linux (contributed-
+## for some reason I couldn't find the original email but thanks!!!)
+## 5. All major key-handling code moved to their own methods for easier subclassing: OnHome,
+## OnErase, OnEnd, OnCtrl_X, OnCtrl_A, etc.
+## 6. Email and autoformat validations corrected using regex provided by Will Sadkin (thanks!).
+## (The rest of the changes in this version were done by Will Sadkin with permission from Jeff...)
+## 7. New mechanism for replacing default behavior for any given key, using
+## ._SetKeycodeHandler(keycode, func) and ._SetKeyHandler(char, func) now available
+## for easier subclassing of the control.
+## 8. Reworked the delete logic, cut, paste and select/replace logic, as well as some bugs
+## with insertion point/selection modification. Changed Ctrl-X to use standard "cut"
+## semantics, erasing the selection, rather than erasing the entire control.
+## 9. Added option for an "default value" (ie. the template) for use when a single fillChar
+## is not desired in every position. Added IsDefault() function to mean "does the value
+## equal the template?" and modified .IsEmpty() to mean "do all of the editable
+## positions in the template == the fillChar?"
+## 10. Extracted mask logic into mixin, so we can have both MaskedTextCtrl and MaskedComboBox,
+## now included.
+## 11. MaskedComboBox now adds the capability to validate from list of valid values.
+## Example: City validates against list of cities, or zip vs zip code list.
+## 12. Fixed oversight in EVT_TEXT handler that prevented the events from being
+## passed to the next handler in the event chain, causing updates to the
+## control to be invisible to the parent code.
+## 13. Added IPADDR autoformat code, and subclass IpAddrCtrl for controlling tabbing within
+## the control, that auto-reformats as you move between cells.
+## 14. Mask characters [A,a,X,#] can now appear in the format string as literals, by using '\'.
+## 15. It is now possible to specify repeating masks, e.g. #{3}-#{3}-#{14}
+## 16. Fixed major bugs in date validation, due to the fact that
+## wxDateTime.ParseDate is too liberal, and will accept any form that
+## makes any kind of sense, regardless of the datestyle you specified
+## for the control. Unfortunately, the strategy used to fix it only
+## works for versions of wxPython post 2.3.3.1, as a C++ assert box
+## seems to show up on an invalid date otherwise, instead of a catchable
+## exception.
+## 17. Enhanced date adjustment to automatically adjust heuristic based on
+## current year, making last century/this century determination on
+## 2-digit year based on distance between today's year and value;
+## if > 50 year separation, assume last century (and don't assume last
+## century is 20th.)
+## 18. Added autoformats and support for including HHMMSS as well as HHMM for
+## date times, and added similar time, and militaray time autoformats.
+## 19. Enhanced tabbing logic so that tab takes you to the next field if the
+## control is a multi-field control.
+## 20. Added stub method called whenever the control "changes fields", that
+## can be overridden by subclasses (eg. IpAddrCtrl.)
+## 21. Changed a lot of code to be more functionally-oriented so side-effects
+## aren't as problematic when maintaining code and/or adding features.
+## Eg: IsValid() now does not have side-effects; it merely reflects the
+## validity of the value of the control; to determine validity AND recolor
+## the control, _CheckValid() should be used with a value argument of None.
+## Similarly, made most reformatting function take an optional candidate value
+## rather than just using the current value of the control, and only
+## have them change the value of the control if a candidate is not specified.
+## In this way, you can do validation *before* changing the control.
+## 22. Changed validRequired to mean "disallow chars that result in invalid
+## value." (Old meaning now represented by emptyInvalid.) (This was
+## possible once I'd made the changes in (19) above.)
+## 23. Added .SetMaskParameters and .GetMaskParameter methods, so they
+## can be set/modified/retrieved after construction. Removed individual
+## parameter setting functions, in favor of this mechanism, so that
+## all adjustment of the control based on changing parameter values can
+## be handled in one place with unified mechanism.
+## 24. Did a *lot* of testing and fixing re: numeric values. Added ability
+## to type "grouping char" (ie. ',') and validate as appropriate.
+## 25. Fixed ZIPPLUS4 to allow either 5 or 4, but if > 5 must be 9.
+## 26. Fixed assumption about "decimal or integer" masks so that they're only
+## made iff there's no validRegex associated with the field. (This
+## is so things like zipcodes which look like integers can have more
+## restrictive validation (ie. must be 5 digits.)
+## 27. Added a ton more doc strings to explain use and derivation requirements
+## and did regularization of the naming conventions.
+## 28. Fixed a range bug in _adjustKey preventing z from being handled properly.
+## 29. Changed behavior of '.' (and shift-.) in numeric controls to move to
+## reformat the value and move the next field as appropriate. (shift-'.',
+## ie. '>' moves to the previous field.
+
+## Version 0.0.6
+## 1. Fixed regex bug that caused autoformat AGE to invalidate any age ending
+## in '0'.
+## 2. New format character 'D' to trigger date type. If the user enters 2 digits in the
+## year position, the control will expand the value to four digits, using numerals below
+## 50 as 21st century (20+nn) and less than 50 as 20th century (19+nn).
+## Also, new optional parameter datestyle = set to one of {MDY|DMY|YDM}
+## 3. revalid parameter renamed validRegex to conform to standard for all validation
+## parameters (see 2 new ones below).
+## 4. New optional init parameter = validRange. Used only for int/dec (numeric) types.
+## Allows the developer to specify a valid low/high range of values.
+## 5. New optional init parameter = validList. Used for character types. Allows developer
+## to send a list of values to the control to be used for specific validation.
+## See the Last Name Only example - it is list restricted to Smith/Jones/Williams.
+## 6. Date type fields now use wxDateTime's parser to validate the date and time.
+## This works MUCH better than my kludgy regex!! Thanks to Robin Dunn for pointing
+## me toward this solution!
+## 7. Date fields now automatically expand 2-digit years when it can. For example,
+## if the user types "03/10/67", then "67" will auto-expand to "1967". If a two-year
+## date is entered it will be expanded in any case when the user tabs out of the
+## field.
+## 8. New class functions: SetValidBackgroundColor, SetInvalidBackgroundColor, SetEmptyBackgroundColor,
+## SetSignedForeColor allow accessto override default class coloring behavior.
+## 9. Documentation updated and improved.
+## 10. Demo - page 2 is now a wxFrame class instead of a wxPyApp class. Works better.
+## Two new options (checkboxes) - test highlight empty and disallow empty.
+## 11. Home and End now work more intuitively, moving to the first and last user-entry
+## value, respectively.
+## 12. New class function: SetRequired(bool). Sets the control's entry required flag
+## (i.e. disallow empty values if True).
+##
+## Version 0.0.5
+## 1. get_plainValue method renamed to GetPlainValue following the wxWindows
+## StudlyCaps(tm) standard (thanks Paul Moore). ;)
+## 2. New format code 'F' causes the control to auto-fit (auto-size) itself
+## based on the length of the mask template.
+## 3. Class now supports "autoformat" codes. These can be passed to the class
+## on instantiation using the parameter autoformat="code". If the code is in
+## the dictionary, it will self set the mask, formatting, and validation string.
+## I have included a number of samples, but I am hoping that someone out there
+## can help me to define a whole bunch more.
+## 4. I have added a second page to the demo (as well as a second demo class, test2)
+## to showcase how autoformats work. The way they self-format and self-size is,
+## I must say, pretty cool.
+## 5. Comments added and some internal cosmetic revisions re: matching the code
+## standards for class submission.
+## 6. Regex validation is now done in real time - field turns yellow immediately
+## and stays yellow until the entered value is valid
+## 7. Cursor now skips over template characters in a more intuitive way (before the
+## next keypress).
+## 8. Change, Keypress and LostFocus methods added for convenience of subclasses.
+## Developer may use these methods which will be called after EVT_TEXT, EVT_CHAR,
+## and EVT_KILL_FOCUS, respectively.
+## 9. Decimal and numeric handlers have been rewritten and now work more intuitively.
+##
+## Version 0.0.4
+## 1. New .IsEmpty() method returns True if the control's value is equal to the
+## blank template string
+## 2. Control now supports a new init parameter: revalid. Pass a regular expression
+## that the value will have to match when the control loses focus. If invalid,
+## the control's BackgroundColor will turn yellow, and an internal flag is set (see next).
+## 3. Demo now shows revalid functionality. Try entering a partial value, such as a
+## partial social security number.
+## 4. New .IsValid() value returns True if the control is empty, or if the value matches
+## the revalid expression. If not, .IsValid() returns False.
+## 5. Decimal values now collapse to decimal with '.00' on losefocus if the user never
+## presses the decimal point.
+## 6. Cursor now goes to the beginning of the field if the user clicks in an
+## "empty" field intead of leaving the insertion point in the middle of the
+## field.
+## 7. New "N" mask type includes upper and lower chars plus digits. a-zA-Z0-9.
+## 8. New formatcodes init parameter replaces other init params and adds functions.
+## String passed to control on init controls:
+## _ Allow spaces
+## ! Force upper
+## ^ Force lower
+## R Show negative #s in red
+## , Group digits
+## - Signed numerals
+## 0 Numeric fields get leading zeros
+## 9. Ctrl-X in any field clears the current value.
+## 10. Code refactored and made more modular (esp in OnChar method). Should be more
+## easy to read and understand.
+## 11. Demo enhanced.
+## 12. Now has _doc_.
+##
+## Version 0.0.3
+## 1. GetPlainValue() now returns the value without the template characters;
+## so, for example, a social security number (123-33-1212) would return as
+## 123331212; also removes white spaces from numeric/decimal values, so
+## "- 955.32" is returned "-955.32". Press ctrl-S to see the plain value.
+## 2. Press '.' in an integer style masked control and truncate any trailing digits.
+## 3. Code moderately refactored. Internal names improved for clarity. Additional
+## internal documentation.
+## 4. Home and End keys now supported to move cursor to beginning or end of field.
+## 5. Un-signed integers and decimals now supported.
+## 6. Cosmetic improvements to the demo.
+## 7. Class renamed to MaskedTextCtrl.
+## 8. Can now specify include characters that will override the basic
+## controls: for example, includeChars = "@." for email addresses
+## 9. Added mask character 'C' -> allow any upper or lowercase character
+## 10. .SetSignColor(str:color) sets the foreground color for negative values
+## in signed controls (defaults to red)
+## 11. Overview documentation written.
+##
+## Version 0.0.2
+## 1. Tab now works properly when pressed in last position
+## 2. Decimal types now work (e.g. #####.##)
+## 3. Signed decimal or numeric values supported (i.e. negative numbers)
+## 4. Negative decimal or numeric values now can show in red.
+## 5. Can now specify an "exclude list" with the excludeChars parameter.
+## See date/time formatted example - you can only enter A or P in the
+## character mask space (i.e. AM/PM).
+## 6. Backspace now works properly, including clearing data from a selected
+## region but leaving template characters intact. Also delete key.
+## 7. Left/right arrows now work properly.
+## 8. Removed EventManager call from test so demo should work with wxPython 2.3.3
+##
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/numctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/numctrl.py
new file mode 100644
index 0000000..1be9898
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/numctrl.py
@@ -0,0 +1,1926 @@
+#----------------------------------------------------------------------------
+# Name: wxPython.lib.masked.numctrl.py
+# Author: Will Sadkin
+# Created: 09/06/2003
+# Copyright: (c) 2003-2007 by Will Sadkin
+# RCS-ID: $Id$
+# License: wxWidgets license
+#----------------------------------------------------------------------------
+# NOTE:
+# This was written to provide a numeric edit control for wxPython that
+# does things like right-insert (like a calculator), and does grouping, etc.
+# (ie. the features of masked.TextCtrl), but allows Get/Set of numeric
+# values, rather than text.
+#
+# Masked.NumCtrl permits integer, and floating point values to be set
+# retrieved or set via .GetValue() and .SetValue() (type chosen based on
+# fraction width, and provides an masked.EVT_NUM() event function for trapping
+# changes to the control.
+#
+# It supports negative numbers as well as the naturals, and has the option
+# of not permitting leading zeros or an empty control; if an empty value is
+# not allowed, attempting to delete the contents of the control will result
+# in a (selected) value of zero, thus preserving a legitimate numeric value.
+# Similarly, replacing the contents of the control with '-' will result in
+# a selected (absolute) value of -1.
+#
+# masked.NumCtrl also supports range limits, with the option of either
+# enforcing them or simply coloring the text of the control if the limits
+# are exceeded.
+#
+# masked.NumCtrl is intended to support fixed-point numeric entry, and
+# is derived from BaseMaskedTextCtrl. As such, it supports a limited range
+# of values to comply with a fixed-width entry mask.
+#----------------------------------------------------------------------------
+# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for wx namespace
+#
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxMaskedEditMixin -> MaskedEditMixin
+# o wxMaskedTextCtrl -> masked.TextCtrl
+# o wxMaskedNumNumberUpdatedEvent -> masked.NumberUpdatedEvent
+# o wxMaskedNumCtrl -> masked.NumCtrl
+#
+
+"""
+masked.NumCtrl:
+ - allows you to get and set integer or floating point numbers as value,</LI>
+ - provides bounds support and optional value limiting,</LI>
+ - has the right-insert input style that MaskedTextCtrl supports,</LI>
+ - provides optional automatic grouping, sign control and format, grouping and decimal
+ character selection, etc. etc.</LI>
+
+
+ Being derived from masked.TextCtrl, the control only allows
+ fixed-point notation. That is, it has a fixed (though reconfigurable)
+ maximum width for the integer portion and optional fixed width
+ fractional portion.
+
+ Here's the API::
+
+ from wx.lib.masked import NumCtrl
+
+ NumCtrl(
+ parent, id = -1,
+ value = 0,
+ pos = wx.DefaultPosition,
+ size = wx.DefaultSize,
+ style = 0,
+ validator = wx.DefaultValidator,
+ name = "masked.number",
+ integerWidth = 10,
+ fractionWidth = 0,
+ allowNone = False,
+ allowNegative = True,
+ useParensForNegatives = False,
+ groupDigits = False,
+ groupChar = ',',
+ decimalChar = '.',
+ min = None,
+ max = None,
+ limited = False,
+ limitOnFieldChange = False,
+ selectOnEntry = True,
+ foregroundColour = "Black",
+ signedForegroundColour = "Red",
+ emptyBackgroundColour = "White",
+ validBackgroundColour = "White",
+ invalidBackgroundColour = "Yellow",
+ autoSize = True
+ )
+
+
+ value
+ If no initial value is set, the default will be zero, or
+ the minimum value, if specified. If an illegal string is specified,
+ a ValueError will result. (You can always later set the initial
+ value with SetValue() after instantiation of the control.)
+
+ integerWidth
+ Indicates how many places to the right of any decimal point
+ should be allowed in the control. This will, perforce, limit
+ the size of the values that can be entered. This number need
+ not include space for grouping characters or the sign, if either
+ of these options are enabled, as the resulting underlying
+ mask is automatically by the control. The default of 10
+ will allow any 32 bit integer value. The minimum value
+ for integerWidth is 1.
+
+ fractionWidth
+ Indicates how many decimal places to show for numeric value.
+ If default (0), then the control will display and return only
+ integer or long values.
+
+ allowNone
+ Boolean indicating whether or not the control is allowed to be
+ empty, representing a value of None for the control.
+
+ allowNegative
+ Boolean indicating whether or not control is allowed to hold
+ negative numbers.
+
+ useParensForNegatives
+ If true, this will cause negative numbers to be displayed with ()s
+ rather than -, (although '-' will still trigger a negative number.)
+
+ groupDigits
+ Indicates whether or not grouping characters should be allowed and/or
+ inserted when leaving the control or the decimal character is entered.
+
+ groupChar
+ What grouping character will be used if allowed. (By default ',')
+
+ decimalChar
+ If fractionWidth is > 0, what character will be used to represent
+ the decimal point. (By default '.')
+
+ min
+ The minimum value that the control should allow. This can be also be
+ adjusted with SetMin(). If the control is not limited, any value
+ below this bound will result in a background colored with the current
+ invalidBackgroundColour. If the min specified will not fit into the
+ control, the min setting will be ignored.
+
+ max
+ The maximum value that the control should allow. This can be
+ adjusted with SetMax(). If the control is not limited, any value
+ above this bound will result in a background colored with the current
+ invalidBackgroundColour. If the max specified will not fit into the
+ control, the max setting will be ignored.
+
+ limited
+ Boolean indicating whether the control prevents values from
+ exceeding the currently set minimum and maximum values (bounds).
+ If False and bounds are set, out-of-bounds values will
+ result in a background colored with the current invalidBackgroundColour.
+
+ limitOnFieldChange
+ An alternative to limited, this boolean indicates whether or not a
+ field change should be allowed if the value in the control
+ is out of bounds. If True, and control focus is lost, this will also
+ cause the control to take on the nearest bound value.
+
+ selectOnEntry
+ Boolean indicating whether or not the value in each field of the
+ control should be automatically selected (for replacement) when
+ that field is entered, either by cursor movement or tabbing.
+ This can be desirable when using these controls for rapid data entry.
+
+ foregroundColour
+ Color value used for positive values of the control.
+
+ signedForegroundColour
+ Color value used for negative values of the control.
+
+ emptyBackgroundColour
+ What background color to use when the control is considered
+ "empty." (allow_none must be set to trigger this behavior.)
+
+ validBackgroundColour
+ What background color to use when the control value is
+ considered valid.
+
+ invalidBackgroundColour
+ Color value used for illegal values or values out-of-bounds of the
+ control when the bounds are set but the control is not limited.
+
+ autoSize
+ Boolean indicating whether or not the control should set its own
+ width based on the integer and fraction widths. True by default.
+ <I>Note:</I> Setting this to False will produce seemingly odd
+ behavior unless the control is large enough to hold the maximum
+ specified value given the widths and the sign positions; if not,
+ the control will appear to "jump around" as the contents scroll.
+ (ie. autoSize is highly recommended.)
+
+--------------------------
+
+masked.EVT_NUM(win, id, func)
+ Respond to a EVT_COMMAND_MASKED_NUMBER_UPDATED event, generated when
+ the value changes. Notice that this event will always be sent when the
+ control's contents changes - whether this is due to user input or
+ comes from the program itself (for example, if SetValue() is called.)
+
+
+SetValue(int|long|float|string)
+ Sets the value of the control to the value specified, if
+ possible. The resulting actual value of the control may be
+ altered to conform to the format of the control, changed
+ to conform with the bounds set on the control if limited,
+ or colored if not limited but the value is out-of-bounds.
+ A ValueError exception will be raised if an invalid value
+ is specified.
+
+GetValue()
+ Retrieves the numeric value from the control. The value
+ retrieved will be either be returned as a long if the
+ fractionWidth is 0, or a float otherwise.
+
+
+SetParameters(\*\*kwargs)
+ Allows simultaneous setting of various attributes
+ of the control after construction. Keyword arguments
+ allowed are the same parameters as supported in the constructor.
+
+
+SetIntegerWidth(value)
+ Resets the width of the integer portion of the control. The
+ value must be >= 1, or an AttributeError exception will result.
+ This value should account for any grouping characters that might
+ be inserted (if grouping is enabled), but does not need to account
+ for the sign, as that is handled separately by the control.
+GetIntegerWidth()
+ Returns the current width of the integer portion of the control,
+ not including any reserved sign position.
+
+
+SetFractionWidth(value)
+ Resets the width of the fractional portion of the control. The
+ value must be >= 0, or an AttributeError exception will result. If
+ 0, the current value of the control will be truncated to an integer
+ value.
+GetFractionWidth()
+ Returns the current width of the fractional portion of the control.
+
+
+SetMin(min=None)
+ Resets the minimum value of the control. If a value of <I>None</I>
+ is provided, then the control will have no explicit minimum value.
+ If the value specified is greater than the current maximum value,
+ then the function returns False and the minimum will not change from
+ its current setting. On success, the function returns True.
+
+ If successful and the current value is lower than the new lower
+ bound, if the control is limited, the value will be automatically
+ adjusted to the new minimum value; if not limited, the value in the
+ control will be colored as invalid.
+
+ If min > the max value allowed by the width of the control,
+ the function will return False, and the min will not be set.
+
+GetMin()
+ Gets the current lower bound value for the control.
+ It will return None if no lower bound is currently specified.
+
+
+SetMax(max=None)
+ Resets the maximum value of the control. If a value of <I>None</I>
+ is provided, then the control will have no explicit maximum value.
+ If the value specified is less than the current minimum value, then
+ the function returns False and the maximum will not change from its
+ current setting. On success, the function returns True.
+
+ If successful and the current value is greater than the new upper
+ bound, if the control is limited the value will be automatically
+ adjusted to this maximum value; if not limited, the value in the
+ control will be colored as invalid.
+
+ If max > the max value allowed by the width of the control,
+ the function will return False, and the max will not be set.
+
+GetMax()
+ Gets the current upper bound value for the control.
+ It will return None if no upper bound is currently specified.
+
+
+SetBounds(min=None,max=None)
+ This function is a convenience function for setting the min and max
+ values at the same time. The function only applies the maximum bound
+ if setting the minimum bound is successful, and returns True
+ only if both operations succeed. <B><I>Note:</I> leaving out an argument
+ will remove the corresponding bound.
+GetBounds()
+ This function returns a two-tuple (min,max), indicating the
+ current bounds of the control. Each value can be None if
+ that bound is not set.
+
+
+IsInBounds(value=None)
+ Returns <I>True</I> if no value is specified and the current value
+ of the control falls within the current bounds. This function can also
+ be called with a value to see if that value would fall within the current
+ bounds of the given control.
+
+
+SetLimited(bool)
+ If called with a value of True, this function will cause the control
+ to limit the value to fall within the bounds currently specified.
+ If the control's value currently exceeds the bounds, it will then
+ be limited accordingly.
+ If called with a value of False, this function will disable value
+ limiting, but coloring of out-of-bounds values will still take
+ place if bounds have been set for the control.
+
+GetLimited()
+
+IsLimited()
+ Returns <I>True</I> if the control is currently limiting the
+ value to fall within the current bounds.
+
+SetLimitOnFieldChange()
+ If called with a value of True, will cause the control to allow
+ out-of-bounds values, but will prevent field change if attempted
+ via navigation, and if the control loses focus, it will change
+ the value to the nearest bound.
+
+GetLimitOnFieldChange()
+
+IsLimitedOnFieldChange()
+ Returns <I>True</I> if the control is currently limiting the
+ value on field change.
+
+
+SetAllowNone(bool)
+ If called with a value of True, this function will cause the control
+ to allow the value to be empty, representing a value of None.
+ If called with a value of False, this function will prevent the value
+ from being None. If the value of the control is currently None,
+ ie. the control is empty, then the value will be changed to that
+ of the lower bound of the control, or 0 if no lower bound is set.
+
+GetAllowNone()
+
+IsNoneAllowed()
+ Returns <I>True</I> if the control currently allows its
+ value to be None.
+
+
+SetAllowNegative(bool)
+ If called with a value of True, this function will cause the
+ control to allow the value to be negative (and reserve space for
+ displaying the sign. If called with a value of False, and the
+ value of the control is currently negative, the value of the
+ control will be converted to the absolute value, and then
+ limited appropriately based on the existing bounds of the control
+ (if any).
+
+GetAllowNegative()
+
+IsNegativeAllowed()
+ Returns <I>True</I> if the control currently permits values
+ to be negative.
+
+
+SetGroupDigits(bool)
+ If called with a value of True, this will make the control
+ automatically add and manage grouping characters to the presented
+ value in integer portion of the control.
+
+GetGroupDigits()
+
+IsGroupingAllowed()
+ Returns <I>True</I> if the control is currently set to group digits.
+
+
+SetGroupChar()
+ Sets the grouping character for the integer portion of the
+ control. (The default grouping character this is ','.
+GetGroupChar()
+ Returns the current grouping character for the control.
+
+
+SetSelectOnEntry()
+ If called with a value of <I>True</I>, this will make the control
+ automatically select the contents of each field as it is entered
+ within the control. (The default is True.)
+ GetSelectOnEntry()
+ Returns <I>True</I> if the control currently auto selects
+ the field values on entry.
+
+
+SetAutoSize(bool)
+ Resets the autoSize attribute of the control.
+GetAutoSize()
+ Returns the current state of the autoSize attribute for the control.
+
+"""
+
+import copy
+import string
+import types
+
+import wx
+
+from sys import maxint
+MAXINT = maxint # (constants should be in upper case)
+MININT = -maxint-1
+
+from wx.tools.dbg import Logger
+from wx.lib.masked import MaskedEditMixin, Field, BaseMaskedTextCtrl
+##dbg = Logger()
+##dbg(enable=1)
+
+#----------------------------------------------------------------------------
+
+wxEVT_COMMAND_MASKED_NUMBER_UPDATED = wx.NewEventType()
+EVT_NUM = wx.PyEventBinder(wxEVT_COMMAND_MASKED_NUMBER_UPDATED, 1)
+
+#----------------------------------------------------------------------------
+
+class NumberUpdatedEvent(wx.PyCommandEvent):
+ """
+ Used to fire an EVT_NUM event whenever the value in a NumCtrl changes.
+ """
+
+ def __init__(self, id, value = 0, object=None):
+ wx.PyCommandEvent.__init__(self, wxEVT_COMMAND_MASKED_NUMBER_UPDATED, id)
+
+ self.__value = value
+ self.SetEventObject(object)
+
+ def GetValue(self):
+ """Retrieve the value of the control at the time
+ this event was generated."""
+ return self.__value
+
+
+#----------------------------------------------------------------------------
+class NumCtrlAccessorsMixin:
+ """
+ Defines masked.NumCtrl's list of attributes having their own
+ Get/Set functions, ignoring those that make no sense for
+ a numeric control.
+ """
+ exposed_basectrl_params = (
+ 'decimalChar',
+ 'shiftDecimalChar',
+ 'groupChar',
+ 'useParensForNegatives',
+ 'defaultValue',
+ 'description',
+
+ 'useFixedWidthFont',
+ 'autoSize',
+ 'signedForegroundColour',
+ 'emptyBackgroundColour',
+ 'validBackgroundColour',
+ 'invalidBackgroundColour',
+
+ 'emptyInvalid',
+ 'validFunc',
+ 'validRequired',
+ 'stopFieldChangeIfInvalid',
+ )
+ for param in exposed_basectrl_params:
+ propname = param[0].upper() + param[1:]
+ exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
+ exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
+
+ if param.find('Colour') != -1:
+ # add non-british spellings, for backward-compatibility
+ propname.replace('Colour', 'Color')
+
+ exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
+ exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
+
+
+
+#----------------------------------------------------------------------------
+
+class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
+ """
+ Masked edit control supporting "native" numeric values, ie. .SetValue(3), for
+ example, and supporting a variety of formatting options, including automatic
+ rounding specifiable precision, grouping and decimal place characters, etc.
+ """
+
+
+ valid_ctrl_params = {
+ 'integerWidth': 10, # by default allow all 32-bit integers
+ 'fractionWidth': 0, # by default, use integers
+ 'decimalChar': '.', # by default, use '.' for decimal point
+ 'allowNegative': True, # by default, allow negative numbers
+ 'useParensForNegatives': False, # by default, use '-' to indicate negatives
+ 'groupDigits': True, # by default, don't insert grouping
+ 'groupChar': ',', # by default, use ',' for grouping
+ 'min': None, # by default, no bounds set
+ 'max': None,
+ 'limited': False, # by default, no limiting even if bounds set
+ 'limitOnFieldChange': False, # by default, don't limit if changing fields, even if bounds set
+ 'allowNone': False, # by default, don't allow empty value
+ 'selectOnEntry': True, # by default, select the value of each field on entry
+ 'foregroundColour': "Black",
+ 'signedForegroundColour': "Red",
+ 'emptyBackgroundColour': "White",
+ 'validBackgroundColour': "White",
+ 'invalidBackgroundColour': "Yellow",
+ 'useFixedWidthFont': False, # use base control default font, instead of fixed width one
+ 'autoSize': True, # by default, set the width of the control based on the mask
+ }
+
+
+ def __init__ (
+ self, parent, id=-1, value = 0,
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = wx.TE_PROCESS_TAB, validator = wx.DefaultValidator,
+ name = "masked.num",
+ **kwargs ):
+
+## dbg('masked.NumCtrl::__init__', indent=1)
+
+ # Set defaults for control:
+## dbg('setting defaults:')
+ for key, param_value in NumCtrl.valid_ctrl_params.items():
+ # This is done this way to make setattr behave consistently with
+ # "private attribute" name mangling
+ setattr(self, '_' + key, copy.copy(param_value))
+
+ # Assign defaults for all attributes:
+ init_args = copy.deepcopy(NumCtrl.valid_ctrl_params)
+## dbg('kwargs:', kwargs)
+ for key, param_value in kwargs.items():
+ key = key.replace('Color', 'Colour')
+ if key not in NumCtrl.valid_ctrl_params.keys():
+ raise AttributeError('invalid keyword argument "%s"' % key)
+ else:
+ init_args[key] = param_value
+## dbg('init_args:', indent=1)
+ for key, param_value in init_args.items():
+## dbg('%s:' % key, param_value)
+ pass
+## dbg(indent=0)
+
+ # Process initial fields for the control, as part of construction:
+ if type(init_args['integerWidth']) != types.IntType:
+ raise AttributeError('invalid integerWidth (%s) specified; expected integer' % repr(init_args['integerWidth']))
+ elif init_args['integerWidth'] < 1:
+ raise AttributeError('invalid integerWidth (%s) specified; must be > 0' % repr(init_args['integerWidth']))
+
+ fields = {}
+
+ if init_args.has_key('fractionWidth'):
+ if type(init_args['fractionWidth']) != types.IntType:
+ raise AttributeError('invalid fractionWidth (%s) specified; expected integer' % repr(self._fractionWidth))
+ elif init_args['fractionWidth'] < 0:
+ raise AttributeError('invalid fractionWidth (%s) specified; must be >= 0' % repr(init_args['fractionWidth']))
+ self._fractionWidth = init_args['fractionWidth']
+
+ if self._fractionWidth:
+ fracmask = '.' + '#{%d}' % self._fractionWidth
+## dbg('fracmask:', fracmask)
+ fields[1] = Field(defaultValue='0'*self._fractionWidth)
+ else:
+ fracmask = ''
+
+ self._integerWidth = init_args['integerWidth']
+ if init_args['groupDigits']:
+ self._groupSpace = (self._integerWidth - 1) / 3
+ else:
+ self._groupSpace = 0
+ intmask = '#{%d}' % (self._integerWidth + self._groupSpace)
+ if self._fractionWidth:
+ emptyInvalid = False
+ else:
+ emptyInvalid = True
+ fields[0] = Field(formatcodes='r<>', emptyInvalid=emptyInvalid)
+## dbg('intmask:', intmask)
+
+ # don't bother to reprocess these arguments:
+ del init_args['integerWidth']
+ del init_args['fractionWidth']
+
+ self._autoSize = init_args['autoSize']
+ if self._autoSize:
+ formatcodes = 'FR<'
+ else:
+ formatcodes = 'R<'
+
+
+ mask = intmask+fracmask
+
+ # initial value of state vars
+ self._oldvalue = 0
+ self._integerEnd = 0
+ self._typedSign = False
+
+ # Construct the base control:
+ BaseMaskedTextCtrl.__init__(
+ self, parent, id, '',
+ pos, size, style, validator, name,
+ mask = mask,
+ formatcodes = formatcodes,
+ fields = fields,
+ validFunc=self.IsInBounds,
+ setupEventHandling = False)
+
+ self.Bind(wx.EVT_SET_FOCUS, self._OnFocus ) ## defeat automatic full selection
+ self.Bind(wx.EVT_KILL_FOCUS, self._OnKillFocus ) ## run internal validator
+ self.Bind(wx.EVT_LEFT_DCLICK, self._OnDoubleClick) ## select field under cursor on dclick
+ self.Bind(wx.EVT_RIGHT_UP, self._OnContextMenu ) ## bring up an appropriate context menu
+ self.Bind(wx.EVT_KEY_DOWN, self._OnKeyDown ) ## capture control events not normally seen, eg ctrl-tab.
+ self.Bind(wx.EVT_CHAR, self._OnChar ) ## handle each keypress
+ self.Bind(wx.EVT_TEXT, self.OnTextChange ) ## color control appropriately & keep
+ ## track of previous value for undo
+
+ # Establish any additional parameters, with appropriate error checking
+ self.SetParameters(**init_args)
+
+ # right alignment with prefixed blanks doesn't work with wxPython 2.9+
+ if wx.Platform == "__WXMSW__":
+ self.SetWindowStyleFlag(self.GetWindowStyleFlag() | wx.TE_RIGHT)
+
+ # Set the value requested (if possible)
+## wxCallAfter(self.SetValue, value)
+ self.SetValue(value)
+
+ # Ensure proper coloring:
+ self.Refresh()
+## dbg('finished NumCtrl::__init__', indent=0)
+
+
+ def SetParameters(self, **kwargs):
+ """
+ This function is used to initialize and reconfigure the control.
+ See TimeCtrl module overview for available parameters.
+ """
+## dbg('NumCtrl::SetParameters', indent=1)
+ maskededit_kwargs = {}
+ reset_fraction_width = False
+
+
+ if( (kwargs.has_key('integerWidth') and kwargs['integerWidth'] != self._integerWidth)
+ or (kwargs.has_key('fractionWidth') and kwargs['fractionWidth'] != self._fractionWidth)
+ or (kwargs.has_key('groupDigits') and kwargs['groupDigits'] != self._groupDigits)
+ or (kwargs.has_key('autoSize') and kwargs['autoSize'] != self._autoSize) ):
+
+ fields = {}
+
+ if kwargs.has_key('fractionWidth'):
+ if type(kwargs['fractionWidth']) != types.IntType:
+ raise AttributeError('invalid fractionWidth (%s) specified; expected integer' % repr(kwargs['fractionWidth']))
+ elif kwargs['fractionWidth'] < 0:
+ raise AttributeError('invalid fractionWidth (%s) specified; must be >= 0' % repr(kwargs['fractionWidth']))
+ else:
+ if self._fractionWidth != kwargs['fractionWidth']:
+ self._fractionWidth = kwargs['fractionWidth']
+
+ if self._fractionWidth:
+ fracmask = '.' + '#{%d}' % self._fractionWidth
+ fields[1] = Field(defaultValue='0'*self._fractionWidth)
+ emptyInvalid = False
+ else:
+ emptyInvalid = True
+ fracmask = ''
+## dbg('fracmask:', fracmask)
+
+ if kwargs.has_key('integerWidth'):
+ if type(kwargs['integerWidth']) != types.IntType:
+## dbg(indent=0)
+ raise AttributeError('invalid integerWidth (%s) specified; expected integer' % repr(kwargs['integerWidth']))
+ elif kwargs['integerWidth'] < 0:
+## dbg(indent=0)
+ raise AttributeError('invalid integerWidth (%s) specified; must be > 0' % repr(kwargs['integerWidth']))
+ else:
+ self._integerWidth = kwargs['integerWidth']
+
+ if kwargs.has_key('groupDigits'):
+ self._groupDigits = kwargs['groupDigits']
+
+ if self._groupDigits:
+ self._groupSpace = (self._integerWidth - 1) / 3
+ else:
+ self._groupSpace = 0
+
+ intmask = '#{%d}' % (self._integerWidth + self._groupSpace)
+## dbg('intmask:', intmask)
+ fields[0] = Field(formatcodes='r<>', emptyInvalid=emptyInvalid)
+ maskededit_kwargs['fields'] = fields
+
+ # don't bother to reprocess these arguments:
+ if kwargs.has_key('integerWidth'):
+ del kwargs['integerWidth']
+ if kwargs.has_key('fractionWidth'):
+ del kwargs['fractionWidth']
+
+ maskededit_kwargs['mask'] = intmask+fracmask
+
+ if kwargs.has_key('groupChar') or kwargs.has_key('decimalChar'):
+ old_groupchar = self._groupChar # save so we can reformat properly
+ old_decimalchar = self._decimalChar
+## dbg("old_groupchar: '%s'" % old_groupchar)
+## dbg("old_decimalchar: '%s'" % old_decimalchar)
+ groupchar = old_groupchar
+ decimalchar = old_decimalchar
+ old_numvalue = self._GetNumValue(self._GetValue())
+
+ if kwargs.has_key('groupChar'):
+ maskededit_kwargs['groupChar'] = kwargs['groupChar']
+ groupchar = kwargs['groupChar']
+ if kwargs.has_key('decimalChar'):
+ maskededit_kwargs['decimalChar'] = kwargs['decimalChar']
+ decimalchar = kwargs['decimalChar']
+
+ # Add sanity check to make sure these are distinct, and if not,
+ # raise attribute error
+ if groupchar == decimalchar:
+ raise AttributeError('groupChar and decimalChar must be distinct')
+
+
+ # for all other parameters, assign keyword args as appropriate:
+ for key, param_value in kwargs.items():
+ key = key.replace('Color', 'Colour')
+ if key not in NumCtrl.valid_ctrl_params.keys():
+ raise AttributeError('invalid keyword argument "%s"' % key)
+ elif key not in MaskedEditMixin.valid_ctrl_params.keys():
+ setattr(self, '_' + key, param_value)
+ elif key in ('mask', 'autoformat'): # disallow explicit setting of mask
+ raise AttributeError('invalid keyword argument "%s"' % key)
+ else:
+ maskededit_kwargs[key] = param_value
+## dbg('kwargs:', kwargs)
+
+ # reprocess existing format codes to ensure proper resulting format:
+ formatcodes = self.GetCtrlParameter('formatcodes')
+ if kwargs.has_key('allowNegative'):
+ if kwargs['allowNegative'] and '-' not in formatcodes:
+ formatcodes += '-'
+ maskededit_kwargs['formatcodes'] = formatcodes
+ elif not kwargs['allowNegative'] and '-' in formatcodes:
+ formatcodes = formatcodes.replace('-','')
+ maskededit_kwargs['formatcodes'] = formatcodes
+
+ if kwargs.has_key('groupDigits'):
+ if kwargs['groupDigits'] and ',' not in formatcodes:
+ formatcodes += ','
+ maskededit_kwargs['formatcodes'] = formatcodes
+ elif not kwargs['groupDigits'] and ',' in formatcodes:
+ formatcodes = formatcodes.replace(',','')
+ maskededit_kwargs['formatcodes'] = formatcodes
+
+ if kwargs.has_key('selectOnEntry'):
+ self._selectOnEntry = kwargs['selectOnEntry']
+## dbg("kwargs['selectOnEntry']?", kwargs['selectOnEntry'], "'S' in formatcodes?", 'S' in formatcodes)
+ if kwargs['selectOnEntry'] and 'S' not in formatcodes:
+ formatcodes += 'S'
+ maskededit_kwargs['formatcodes'] = formatcodes
+ elif not kwargs['selectOnEntry'] and 'S' in formatcodes:
+ formatcodes = formatcodes.replace('S','')
+ maskededit_kwargs['formatcodes'] = formatcodes
+
+ if kwargs.has_key('autoSize'):
+ self._autoSize = kwargs['autoSize']
+ if kwargs['autoSize'] and 'F' not in formatcodes:
+ formatcodes += 'F'
+ maskededit_kwargs['formatcodes'] = formatcodes
+ elif not kwargs['autoSize'] and 'F' in formatcodes:
+ formatcodes = formatcodes.replace('F', '')
+ maskededit_kwargs['formatcodes'] = formatcodes
+
+
+ if 'r' in formatcodes and self._fractionWidth:
+ # top-level mask should only be right insert if no fractional
+ # part will be shown; ie. if reconfiguring control, remove
+ # previous "global" setting.
+ formatcodes = formatcodes.replace('r', '')
+ maskededit_kwargs['formatcodes'] = formatcodes
+
+
+ if kwargs.has_key('limited'):
+ if kwargs['limited'] and not self._limited:
+ maskededit_kwargs['validRequired'] = True
+ elif not kwargs['limited'] and self._limited:
+ maskededit_kwargs['validRequired'] = False
+ self._limited = kwargs['limited']
+
+ if kwargs.has_key('limitOnFieldChange'):
+ if kwargs['limitOnFieldChange'] and not self._limitOnFieldChange:
+ maskededit_kwargs['stopFieldChangeIfInvalid'] = True
+ elif kwargs['limitOnFieldChange'] and self._limitOnFieldChange:
+ maskededit_kwargs['stopFieldChangeIfInvalid'] = False
+
+## dbg('maskededit_kwargs:', maskededit_kwargs)
+ if maskededit_kwargs.keys():
+ self.SetCtrlParameters(**maskededit_kwargs)
+
+ # Go ensure all the format codes necessary are present:
+ orig_intformat = intformat = self.GetFieldParameter(0, 'formatcodes')
+ if 'r' not in intformat:
+ intformat += 'r'
+ if '>' not in intformat:
+ intformat += '>'
+ if intformat != orig_intformat:
+ if self._fractionWidth:
+ self.SetFieldParameters(0, formatcodes=intformat)
+ else:
+ self.SetCtrlParameters(formatcodes=intformat)
+
+ # Record end of integer and place cursor there unless selecting, or select entire field:
+ integerStart, integerEnd = self._fields[0]._extent
+ if not self._fields[0]._selectOnFieldEntry:
+ self.SetInsertionPoint(0)
+ self.SetInsertionPoint(integerEnd)
+ self.SetSelection(integerEnd, integerEnd)
+ else:
+ self.SetInsertionPoint(0) # include any sign
+ self.SetSelection(0, integerEnd)
+
+
+ # Set min and max as appropriate:
+ if kwargs.has_key('min'):
+ min = kwargs['min']
+ if( self._max is None
+ or min is None
+ or (self._max is not None and self._max >= min) ):
+## dbg('examining min')
+ if min is not None:
+ try:
+ textmin = self._toGUI(min, apply_limits = False)
+ except ValueError:
+## dbg('min will not fit into control; ignoring', indent=0)
+ raise
+## dbg('accepted min')
+ self._min = min
+ else:
+## dbg('ignoring min')
+ pass
+
+
+ if kwargs.has_key('max'):
+ max = kwargs['max']
+ if( self._min is None
+ or max is None
+ or (self._min is not None and self._min <= max) ):
+## dbg('examining max')
+ if max is not None:
+ try:
+ textmax = self._toGUI(max, apply_limits = False)
+ except ValueError:
+## dbg('max will not fit into control; ignoring', indent=0)
+ raise
+## dbg('accepted max')
+ self._max = max
+ else:
+## dbg('ignoring max')
+ pass
+
+ if kwargs.has_key('allowNegative'):
+ self._allowNegative = kwargs['allowNegative']
+
+ # Ensure current value of control obeys any new restrictions imposed:
+ text = self._GetValue()
+## dbg('text value: "%s"' % text)
+ if kwargs.has_key('groupChar') and self._groupChar != old_groupchar and text.find(old_groupchar) != -1:
+ text = old_numvalue
+## dbg('old_groupchar: "%s" newgroupchar: "%s"' % (old_groupchar, self._groupChar))
+ if kwargs.has_key('decimalChar') and self._decimalChar != old_decimalchar and text.find(old_decimalchar) != -1:
+ text = old_numvalue
+
+ if text != self._GetValue():
+ if self._decimalChar != '.':
+ # ensure latest decimal char is in "numeric value" so it won't be removed
+ # when going to the GUI:
+ text = text.replace('.', self._decimalChar)
+ newtext = self._toGUI(text)
+## dbg('calling wx.TextCtrl.ChangeValue(self, %s)' % newtext)
+ wx.TextCtrl.ChangeValue(self, newtext)
+
+ value = self.GetValue()
+
+## dbg('self._allowNegative?', self._allowNegative)
+ if not self._allowNegative and self._isNeg:
+ value = abs(value)
+## dbg('abs(value):', value)
+ self._isNeg = False
+
+ elif not self._allowNone and BaseMaskedTextCtrl.GetValue(self) == '':
+ if self._min > 0:
+ value = self._min
+ else:
+ value = 0
+
+ sel_start, sel_to = self.GetSelection()
+ if self.IsLimited() and self._min is not None and value < self._min:
+## dbg('Set to min value:', self._min)
+ self._ChangeValue(self._toGUI(self._min))
+
+ elif self.IsLimited() and self._max is not None and value > self._max:
+## dbg('Setting to max value:', self._max)
+ self._ChangeValue(self._toGUI(self._max))
+ else:
+ # reformat current value as appropriate to possibly new conditions
+## dbg('Reformatting value:', value)
+ sel_start, sel_to = self.GetSelection()
+ self._ChangeValue(self._toGUI(value))
+ self.Refresh() # recolor as appropriate
+## dbg('finished NumCtrl::SetParameters', indent=0)
+
+
+
+ def _GetNumValue(self, value):
+ """
+ This function attempts to "clean up" a text value, providing a regularized
+ convertable string, via atol() or atof(), for any well-formed numeric text value.
+ """
+ return value.replace(self._groupChar, '').replace(self._decimalChar, '.').replace('(', '-').replace(')','').strip()
+
+
+ def GetFraction(self, candidate=None):
+ """
+ Returns the fractional portion of the value as a float. If there is no
+ fractional portion, the value returned will be 0.0.
+ """
+ if not self._fractionWidth:
+ return 0.0
+ else:
+ fracstart, fracend = self._fields[1]._extent
+ if candidate is None:
+ value = self._toGUI(BaseMaskedTextCtrl.GetValue(self))
+ else:
+ value = self._toGUI(candidate)
+ fracstring = value[fracstart:fracend].strip()
+ if not value:
+ return 0.0
+ else:
+ return string.atof(fracstring)
+
+ def _OnChangeSign(self, event):
+## dbg('NumCtrl::_OnChangeSign', indent=1)
+ self._typedSign = True
+ MaskedEditMixin._OnChangeSign(self, event)
+## dbg(indent=0)
+
+
+ def _disallowValue(self):
+## dbg('NumCtrl::_disallowValue')
+ # limited and -1 is out of bounds
+ if self._typedSign:
+ self._isNeg = False
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+ sel_start, sel_to = self._GetSelection()
+## dbg('queuing reselection of (%d, %d)' % (sel_start, sel_to))
+ wx.CallAfter(self.SetInsertionPoint, sel_start) # preserve current selection/position
+ wx.CallAfter(self.SetSelection, sel_start, sel_to)
+
+
+ def _OnChangeField(self, event):
+ """
+ This routine enhances the base masked control _OnFieldChange(). It's job
+ is to ensure limits are imposed if limitOnFieldChange is enabled.
+ """
+## dbg('NumCtrl::_OnFieldChange', indent=1)
+ if self._limitOnFieldChange and not (self._min <= self.GetValue() <= self._max):
+ self._disallowValue()
+## dbg('oob - field change disallowed',indent=0)
+ return False
+ else:
+## dbg(indent=0)
+ return MaskedEditMixin._OnChangeField(self, event) # call the baseclass function
+
+
+ def _LostFocus(self):
+ """
+ On loss of focus, if limitOnFieldChange is set, ensure value conforms to limits.
+ """
+## dbg('NumCtrl::_LostFocus', indent=1)
+ if self._limitOnFieldChange:
+## dbg("limiting on loss of focus")
+ value = self.GetValue()
+ if self._min is not None and value < self._min:
+## dbg('Set to min value:', self._min)
+ self._SetValue(self._toGUI(self._min))
+
+ elif self._max is not None and value > self._max:
+## dbg('Setting to max value:', self._max)
+ self._SetValue(self._toGUI(self._max))
+ # (else do nothing.)
+ # (else do nothing.)
+## dbg(indent=0)
+ return True
+
+
+ def _SetValue(self, value):
+ """
+ This routine supersedes the base masked control _SetValue(). It is
+ needed to ensure that the value of the control is always representable/convertable
+ to a numeric return value (via GetValue().) This routine also handles
+ automatic adjustment and grouping of the value without explicit intervention
+ by the user.
+ """
+
+## dbg('NumCtrl::_SetValue("%s")' % value, indent=1)
+
+ if( (self._fractionWidth and value.find(self._decimalChar) == -1) or
+ (self._fractionWidth == 0 and value.find(self._decimalChar) != -1) ) :
+ value = self._toGUI(value)
+
+ numvalue = self._GetNumValue(value)
+## dbg('cleansed value: "%s"' % numvalue)
+ replacement = None
+
+ if numvalue == "":
+ if self._allowNone:
+## dbg('calling base BaseMaskedTextCtrl._SetValue(self, "%s")' % value)
+ BaseMaskedTextCtrl._SetValue(self, value)
+ self.Refresh()
+## dbg(indent=0)
+ return
+ elif self._min > 0 and self.IsLimited():
+ replacement = self._min
+ else:
+ replacement = 0
+## dbg('empty value; setting replacement:', replacement)
+
+ if replacement is None:
+ # Go get the integer portion about to be set and verify its validity
+ intstart, intend = self._fields[0]._extent
+## dbg('intstart, intend:', intstart, intend)
+## dbg('raw integer:"%s"' % value[intstart:intend])
+ int = self._GetNumValue(value[intstart:intend])
+ numval = self._fromGUI(value)
+
+## dbg('integer: "%s"' % int)
+ try:
+ # if a float value, this will implicitly verify against limits,
+ # and generate an exception if out-of-bounds and limited
+ # if not a float, it will just return 0.0, and we therefore
+ # have to test against the limits explicitly after testing
+ # special cases for handling -0 and empty controls...
+ fracval = self.GetFraction(value)
+ except ValueError, e:
+## dbg('Exception:', e, 'must be out of bounds; disallow value')
+ self._disallowValue()
+## dbg(indent=0)
+ return
+
+ if fracval == 0.0: # (can be 0 for floats as well as integers)
+ # we have to do special testing to account for emptying controls, or -0
+ # and/or just leaving the sign character or changing the sign,
+ # so we can do appropriate things to the value of the control,
+ # we can't just immediately test to see if the value is valid
+ # If all of these special cases are not in play, THEN we can do
+ # a limits check and see if the value is otherwise ok...
+
+## dbg('self._isNeg?', self._isNeg)
+ if int == '-' and self._oldvalue < 0 and not self._typedSign:
+## dbg('just a negative sign; old value < 0; setting replacement of 0')
+ replacement = 0
+ self._isNeg = False
+ elif int[:2] == '-0':
+ if self._oldvalue < 0:
+## dbg('-0; setting replacement of 0')
+ replacement = 0
+ self._isNeg = False
+ elif not self._limited or (self._min < -1 and self._max >= -1):
+## dbg('-0; setting replacement of -1')
+ replacement = -1
+ self._isNeg = True
+ else:
+ # limited and -1 is out of bounds
+ self._disallowValue()
+## dbg(indent=0)
+ return
+
+ elif int == '-' and (self._oldvalue >= 0 or self._typedSign):
+ if not self._limited or (self._min < -1 and self._max >= -1):
+## dbg('just a negative sign; setting replacement of -1')
+ replacement = -1
+ else:
+ # limited and -1 is out of bounds
+ self._disallowValue()
+## dbg(indent=0)
+ return
+
+ elif( self._typedSign
+ and int.find('-') != -1
+ and self._limited
+ and not self._min <= numval <= self._max):
+ # changed sign resulting in value that's now out-of-bounds;
+ # disallow
+ self._disallowValue()
+## dbg(indent=0)
+ return
+
+ if replacement is None:
+ if int and int != '-':
+ try:
+ string.atol(int)
+ except ValueError:
+ # integer requested is not legal. This can happen if the user
+ # is attempting to insert a digit in the middle of the control
+ # resulting in something like " 3 45". Disallow such actions:
+## dbg('>>>>>>>>>>>>>>>> "%s" does not convert to a long!' % int)
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+ sel_start, sel_to = self._GetSelection()
+## dbg('queuing reselection of (%d, %d)' % (sel_start, sel_to))
+ wx.CallAfter(self.SetInsertionPoint, sel_start) # preserve current selection/position
+ wx.CallAfter(self.SetSelection, sel_start, sel_to)
+## dbg(indent=0)
+ return
+
+## dbg('numvalue: "%s"' % numvalue.replace(' ', ''))
+ # finally, (potentially re) verify that numvalue will pass any limits imposed:
+ try:
+ if self._fractionWidth:
+ value = self._toGUI(string.atof(numvalue))
+ else:
+ value = self._toGUI(string.atol(numvalue))
+ except ValueError, e:
+## dbg('Exception:', e, 'must be out of bounds; disallow value')
+ self._disallowValue()
+## dbg(indent=0)
+ return
+
+## dbg('modified value: "%s"' % value)
+
+
+ self._typedSign = False # reset state var
+
+ if replacement is not None:
+ # Value presented wasn't a legal number, but control should do something
+ # reasonable instead:
+## dbg('setting replacement value:', replacement)
+ self._SetValue(self._toGUI(replacement))
+ sel_start = BaseMaskedTextCtrl.GetValue(self).find(str(abs(replacement))) # find where it put the 1, so we can select it
+ sel_to = sel_start + len(str(abs(replacement)))
+## dbg('queuing selection of (%d, %d)' %(sel_start, sel_to))
+ wx.CallAfter(self.SetInsertionPoint, sel_start)
+ wx.CallAfter(self.SetSelection, sel_start, sel_to)
+## dbg(indent=0)
+ return
+
+ # Otherwise, apply appropriate formatting to value:
+
+ # Because we're intercepting the value and adjusting it
+ # before a sign change is detected, we need to do this here:
+ if '-' in value or '(' in value:
+ self._isNeg = True
+ else:
+ self._isNeg = False
+
+## dbg('value:"%s"' % value, 'self._useParens:', self._useParens)
+ if self._fractionWidth:
+ adjvalue = self._adjustFloat(self._GetNumValue(value).replace('.',self._decimalChar))
+ else:
+ adjvalue = self._adjustInt(self._GetNumValue(value))
+## dbg('adjusted value: "%s"' % adjvalue)
+
+
+ sel_start, sel_to = self._GetSelection() # record current insertion point
+## dbg('calling BaseMaskedTextCtrl._SetValue(self, "%s")' % adjvalue)
+ BaseMaskedTextCtrl._SetValue(self, adjvalue)
+ # After all actions so far scheduled, check that resulting cursor
+ # position is appropriate, and move if not:
+ wx.CallAfter(self._CheckInsertionPoint)
+
+## dbg('finished NumCtrl::_SetValue', indent=0)
+
+ def _CheckInsertionPoint(self):
+ # If current insertion point is before the end of the integer and
+ # its before the 1st digit, place it just after the sign position:
+## dbg('NumCtrl::CheckInsertionPoint', indent=1)
+ sel_start, sel_to = self._GetSelection()
+ text = self._GetValue()
+ if sel_to < self._fields[0]._extent[1] and text[sel_to] in (' ', '-', '('):
+ text, signpos, right_signpos = self._getSignedValue()
+## dbg('setting selection(%d, %d)' % (signpos+1, signpos+1))
+ self.SetInsertionPoint(signpos+1)
+ self.SetSelection(signpos+1, signpos+1)
+## dbg(indent=0)
+
+
+ def _OnErase( self, event=None, just_return_value=False ):
+ """
+ This overrides the base control _OnErase, so that erasing around
+ grouping characters auto selects the digit before or after the
+ grouping character, so that the erasure does the right thing.
+ """
+## dbg('NumCtrl::_OnErase', indent=1)
+ if event is None: # called as action routine from Cut() operation.
+ key = wx.WXK_DELETE
+ else:
+ key = event.GetKeyCode()
+ #if grouping digits, make sure deletes next to group char always
+ # delete next digit to appropriate side:
+ if self._groupDigits:
+ value = BaseMaskedTextCtrl.GetValue(self)
+ sel_start, sel_to = self._GetSelection()
+
+ if key == wx.WXK_BACK:
+ # if 1st selected char is group char, select to previous digit
+ if sel_start > 0 and sel_start < len(self._mask) and value[sel_start:sel_to] == self._groupChar:
+ self.SetInsertionPoint(sel_start-1)
+ self.SetSelection(sel_start-1, sel_to)
+
+ # elif previous char is group char, select to previous digit
+ elif sel_start > 1 and sel_start == sel_to and value[sel_start-1:sel_start] == self._groupChar:
+ self.SetInsertionPoint(sel_start-2)
+ self.SetSelection(sel_start-2, sel_to)
+
+ elif key == wx.WXK_DELETE:
+ if( sel_to < len(self._mask) - 2 + (1 *self._useParens)
+ and sel_start == sel_to
+ and value[sel_to] == self._groupChar ):
+ self.SetInsertionPoint(sel_start)
+ self.SetSelection(sel_start, sel_to+2)
+
+ elif( sel_to < len(self._mask) - 2 + (1 *self._useParens)
+ and value[sel_start:sel_to] == self._groupChar ):
+ self.SetInsertionPoint(sel_start)
+ self.SetSelection(sel_start, sel_to+1)
+## dbg(indent=0)
+ return BaseMaskedTextCtrl._OnErase(self, event, just_return_value)
+
+
+ def OnTextChange( self, event ):
+ """
+ Handles an event indicating that the text control's value
+ has changed, and issue EVT_NUM event.
+ NOTE: using wxTextCtrl.SetValue() to change the control's
+ contents from within a EVT_CHAR handler can cause double
+ text events. So we check for actual changes to the text
+ before passing the events on.
+ """
+## dbg('NumCtrl::OnTextChange', indent=1)
+ if not BaseMaskedTextCtrl._OnTextChange(self, event):
+## dbg(indent=0)
+ return
+
+ # else... legal value
+
+ value = self.GetValue()
+ if value != self._oldvalue:
+ try:
+ self.GetEventHandler().ProcessEvent(
+ NumberUpdatedEvent( self.GetId(), self.GetValue(), self ) )
+ except ValueError:
+## dbg(indent=0)
+ return
+ # let normal processing of the text continue
+ event.Skip()
+ self._oldvalue = value # record for next event
+## dbg(indent=0)
+
+ def _GetValue(self):
+ """
+ Override of BaseMaskedTextCtrl to allow mixin to get the raw text value of the
+ control with this function.
+ """
+ return wx.TextCtrl.GetValue(self)
+
+
+ def GetValue(self):
+ """
+ Returns the current numeric value of the control.
+ """
+ return self._fromGUI( BaseMaskedTextCtrl.GetValue(self) )
+
+ def SetValue(self, value):
+ """
+ Sets the value of the control to the value specified.
+ The resulting actual value of the control may be altered to
+ conform with the bounds set on the control if limited,
+ or colored if not limited but the value is out-of-bounds.
+ A ValueError exception will be raised if an invalid value
+ is specified.
+ """
+## dbg('NumCtrl::SetValue(%s)' % value, indent=1)
+ BaseMaskedTextCtrl.SetValue( self, self._toGUI(value) )
+## dbg(indent=0)
+
+ def ChangeValue(self, value):
+ """
+ Sets the value of the control to the value specified.
+ The resulting actual value of the control may be altered to
+ conform with the bounds set on the control if limited,
+ or colored if not limited but the value is out-of-bounds.
+ A ValueError exception will be raised if an invalid value
+ is specified.
+ """
+## dbg('NumCtrl::ChangeValue(%s)' % value, indent=1)
+ BaseMaskedTextCtrl.ChangeValue( self, self._toGUI(value) )
+## dbg(indent=0)
+
+
+
+
+ def SetIntegerWidth(self, value):
+ self.SetParameters(integerWidth=value)
+ def GetIntegerWidth(self):
+ return self._integerWidth
+
+ def SetFractionWidth(self, value):
+ self.SetParameters(fractionWidth=value)
+ def GetFractionWidth(self):
+ return self._fractionWidth
+
+
+
+ def SetMin(self, min=None):
+ """
+ Sets the minimum value of the control. If a value of None
+ is provided, then the control will have no explicit minimum value.
+ If the value specified is greater than the current maximum value,
+ then the function returns False and the minimum will not change from
+ its current setting. On success, the function returns True.
+
+ If successful and the current value is lower than the new lower
+ bound, if the control is limited, the value will be automatically
+ adjusted to the new minimum value; if not limited, the value in the
+ control will be colored as invalid.
+
+ If min > the max value allowed by the width of the control,
+ the function will return False, and the min will not be set.
+ """
+## dbg('NumCtrl::SetMin(%s)' % repr(min), indent=1)
+ if( self._max is None
+ or min is None
+ or (self._max is not None and self._max >= min) ):
+ try:
+ self.SetParameters(min=min)
+ bRet = True
+ except ValueError:
+ bRet = False
+ else:
+ bRet = False
+## dbg(indent=0)
+ return bRet
+
+ def GetMin(self):
+ """
+ Gets the lower bound value of the control. It will return
+ None if not specified.
+ """
+ return self._min
+
+
+ def SetMax(self, max=None):
+ """
+ Sets the maximum value of the control. If a value of None
+ is provided, then the control will have no explicit maximum value.
+ If the value specified is less than the current minimum value, then
+ the function returns False and the maximum will not change from its
+ current setting. On success, the function returns True.
+
+ If successful and the current value is greater than the new upper
+ bound, if the control is limited the value will be automatically
+ adjusted to this maximum value; if not limited, the value in the
+ control will be colored as invalid.
+
+ If max > the max value allowed by the width of the control,
+ the function will return False, and the max will not be set.
+ """
+ if( self._min is None
+ or max is None
+ or (self._min is not None and self._min <= max) ):
+ try:
+ self.SetParameters(max=max)
+ bRet = True
+ except ValueError:
+ bRet = False
+ else:
+ bRet = False
+
+ return bRet
+
+
+ def GetMax(self):
+ """
+ Gets the maximum value of the control. It will return the current
+ maximum integer, or None if not specified.
+ """
+ return self._max
+
+
+ def SetBounds(self, min=None, max=None):
+ """
+ This function is a convenience function for setting the min and max
+ values at the same time. The function only applies the maximum bound
+ if setting the minimum bound is successful, and returns True
+ only if both operations succeed.
+ NOTE: leaving out an argument will remove the corresponding bound.
+ """
+ ret = self.SetMin(min)
+ return ret and self.SetMax(max)
+
+
+ def GetBounds(self):
+ """
+ This function returns a two-tuple (min,max), indicating the
+ current bounds of the control. Each value can be None if
+ that bound is not set.
+ """
+ return (self._min, self._max)
+
+
+ def SetLimited(self, limited):
+ """
+ If called with a value of True, this function will cause the control
+ to limit the value to fall within the bounds currently specified.
+ If the control's value currently exceeds the bounds, it will then
+ be limited accordingly.
+
+ If called with a value of False, this function will disable value
+ limiting, but coloring of out-of-bounds values will still take
+ place if bounds have been set for the control.
+ """
+ self.SetParameters(limited = limited)
+
+
+ def IsLimited(self):
+ """
+ Returns True if the control is currently limiting the
+ value to fall within the current bounds.
+ """
+ return self._limited
+
+ def GetLimited(self):
+ """ (For regularization of property accessors) """
+ return self.IsLimited()
+
+ def SetLimitOnFieldChange(self, limit):
+ """
+ If called with a value of True, this function will cause the control
+ to prevent navigation out of the current field if its value is out-of-bounds,
+ and limit the value to fall within the bounds currently specified if the
+ control loses focus.
+
+ If called with a value of False, this function will disable value
+ limiting, but coloring of out-of-bounds values will still take
+ place if bounds have been set for the control.
+ """
+ self.SetParameters(limitOnFieldChange = limit)
+
+
+ def IsLimitedOnFieldChange(self):
+ """
+ Returns True if the control is currently limiting the
+ value to fall within the current bounds.
+ """
+ return self._limitOnFieldChange
+
+ def GetLimitOnFieldChange(self):
+ """ (For regularization of property accessors) """
+ return self.IsLimitedOnFieldChange()
+
+
+ def IsInBounds(self, value=None):
+ """
+ Returns True if no value is specified and the current value
+ of the control falls within the current bounds. This function can
+ also be called with a value to see if that value would fall within
+ the current bounds of the given control.
+ """
+## dbg('IsInBounds(%s)' % repr(value), indent=1)
+ if value is None:
+ value = self.GetValue()
+ else:
+ try:
+ value = self._GetNumValue(self._toGUI(value))
+ except ValueError, e:
+## dbg('error getting NumValue(self._toGUI(value)):', e, indent=0)
+ return False
+ if value.strip() == '':
+ value = None
+ elif self._fractionWidth:
+ value = float(value)
+ else:
+ value = long(value)
+
+ min = self.GetMin()
+ max = self.GetMax()
+ if min is None: min = value
+ if max is None: max = value
+
+ # if bounds set, and value is None, return False
+ if value == None and (min is not None or max is not None):
+## dbg('finished IsInBounds', indent=0)
+ return 0
+ else:
+## dbg('finished IsInBounds', indent=0)
+ return min <= value <= max
+
+
+ def SetAllowNone(self, allow_none):
+ """
+ Change the behavior of the validation code, allowing control
+ to have a value of None or not, as appropriate. If the value
+ of the control is currently None, and allow_none is False, the
+ value of the control will be set to the minimum value of the
+ control, or 0 if no lower bound is set.
+ """
+ self._allowNone = allow_none
+ if not allow_none and self.GetValue() is None:
+ min = self.GetMin()
+ if min is not None: self.SetValue(min)
+ else: self.SetValue(0)
+
+
+ def IsNoneAllowed(self):
+ return self._allowNone
+ def GetAllowNone(self):
+ """ (For regularization of property accessors) """
+ return self.IsNoneAllowed()
+
+ def SetAllowNegative(self, value):
+ self.SetParameters(allowNegative=value)
+ def IsNegativeAllowed(self):
+ return self._allowNegative
+ def GetAllowNegative(self):
+ """ (For regularization of property accessors) """
+ return self.IsNegativeAllowed()
+
+ def SetGroupDigits(self, value):
+ self.SetParameters(groupDigits=value)
+ def IsGroupingAllowed(self):
+ return self._groupDigits
+ def GetGroupDigits(self):
+ """ (For regularization of property accessors) """
+ return self.IsGroupingAllowed()
+
+ def SetGroupChar(self, value):
+ self.SetParameters(groupChar=value)
+ def GetGroupChar(self):
+ return self._groupChar
+
+ def SetDecimalChar(self, value):
+ self.SetParameters(decimalChar=value)
+ def GetDecimalChar(self):
+ return self._decimalChar
+
+ def SetSelectOnEntry(self, value):
+ self.SetParameters(selectOnEntry=value)
+ def GetSelectOnEntry(self):
+ return self._selectOnEntry
+
+ def SetAutoSize(self, value):
+ self.SetParameters(autoSize=value)
+ def GetAutoSize(self):
+ return self._autoSize
+
+
+ # (Other parameter accessors are inherited from base class)
+
+
+ def _toGUI( self, value, apply_limits = True ):
+ """
+ Conversion function used to set the value of the control; does
+ type and bounds checking and raises ValueError if argument is
+ not a valid value.
+ """
+## dbg('NumCtrl::_toGUI(%s)' % repr(value), indent=1)
+ if value is None and self.IsNoneAllowed():
+## dbg(indent=0)
+ return self._template
+
+ elif type(value) in (types.StringType, types.UnicodeType):
+ value = self._GetNumValue(value)
+## dbg('cleansed num value: "%s"' % value)
+ if value == "":
+ if self.IsNoneAllowed():
+## dbg(indent=0)
+ return self._template
+ else:
+## dbg('exception raised:', e, indent=0)
+ raise ValueError ('NumCtrl requires numeric value, passed %s'% repr(value) )
+ # else...
+ try:
+ if self._fractionWidth or value.find('.') != -1:
+ value = float(value)
+ else:
+ value = long(value)
+ except Exception, e:
+## dbg('exception raised:', e, indent=0)
+ raise ValueError ('NumCtrl requires numeric value, passed %s'% repr(value) )
+
+ elif type(value) not in (types.IntType, types.LongType, types.FloatType):
+## dbg(indent=0)
+ raise ValueError (
+ 'NumCtrl requires numeric value, passed %s'% repr(value) )
+
+ if not self._allowNegative and value < 0:
+ raise ValueError (
+ 'control configured to disallow negative values, passed %s'% repr(value) )
+
+ if self.IsLimited() and apply_limits:
+ min = self.GetMin()
+ max = self.GetMax()
+ if not min is None and value < min:
+## dbg(indent=0)
+ raise ValueError (
+ 'value %d is below minimum value of control'% value )
+ if not max is None and value > max:
+## dbg(indent=0)
+ raise ValueError (
+ 'value %d exceeds value of control'% value )
+
+ adjustwidth = len(self._mask) - (1 * self._useParens * self._signOk)
+## dbg('len(%s):' % self._mask, len(self._mask))
+## dbg('adjustwidth - groupSpace:', adjustwidth - self._groupSpace)
+## dbg('adjustwidth:', adjustwidth)
+ if self._fractionWidth == 0:
+ s = str(long(value)).rjust(self._integerWidth)
+ else:
+ format = '%' + '%d.%df' % (self._integerWidth+self._fractionWidth+1, self._fractionWidth)
+ s = format % float(value)
+## dbg('s:"%s"' % s, 'len(s):', len(s))
+ if len(s) > (adjustwidth - self._groupSpace):
+## dbg(indent=0)
+ raise ValueError ('value %s exceeds the integer width of the control (%d)' % (s, self._integerWidth))
+ elif s[0] not in ('-', ' ') and self._allowNegative and len(s) == (adjustwidth - self._groupSpace):
+## dbg(indent=0)
+ raise ValueError ('value %s exceeds the integer width of the control (%d)' % (s, self._integerWidth))
+
+ s = s.rjust(adjustwidth).replace('.', self._decimalChar)
+ if self._signOk and self._useParens:
+ if s.find('-') != -1:
+ s = s.replace('-', '(') + ')'
+ else:
+ s += ' '
+## dbg('returned: "%s"' % s, indent=0)
+ return s
+
+
+ def _fromGUI( self, value ):
+ """
+ Conversion function used in getting the value of the control.
+ """
+## dbg(suspend=0)
+## dbg('NumCtrl::_fromGUI(%s)' % value, indent=1)
+ # One or more of the underlying text control implementations
+ # issue an intermediate EVT_TEXT when replacing the control's
+ # value, where the intermediate value is an empty string.
+ # So, to ensure consistency and to prevent spurious ValueErrors,
+ # we make the following test, and react accordingly:
+ #
+ if value.strip() == '':
+ if not self.IsNoneAllowed():
+## dbg('empty value; not allowed,returning 0', indent = 0)
+ if self._fractionWidth:
+ return 0.0
+ else:
+ return 0
+ else:
+## dbg('empty value; returning None', indent = 0)
+ return None
+ else:
+ value = self._GetNumValue(value)
+## dbg('Num value: "%s"' % value)
+ if self._fractionWidth:
+ try:
+## dbg(indent=0)
+ return float( value )
+ except ValueError:
+## dbg("couldn't convert to float; returning None")
+ return None
+ else:
+ raise
+ else:
+ try:
+## dbg(indent=0)
+ return int( value )
+ except ValueError:
+ try:
+## dbg(indent=0)
+ return long( value )
+ except ValueError:
+## dbg("couldn't convert to long; returning None")
+ return None
+
+ else:
+ raise
+ else:
+## dbg('exception occurred; returning None')
+ return None
+
+
+ def _Paste( self, value=None, raise_on_invalid=False, just_return_value=False ):
+ """
+ Preprocessor for base control paste; if value needs to be right-justified
+ to fit in control, do so prior to paste:
+ """
+## dbg('NumCtrl::_Paste (value = "%s")' % value, indent=1)
+ if value is None:
+ paste_text = self._getClipboardContents()
+ else:
+ paste_text = value
+ sel_start, sel_to = self._GetSelection()
+ orig_sel_start = sel_start
+ orig_sel_to = sel_to
+## dbg('selection:', (sel_start, sel_to))
+ old_value = self._GetValue()
+
+ #
+ field = self._FindField(sel_start)
+ edit_start, edit_end = field._extent
+
+ # handle possibility of groupChar being a space:
+ newtext = paste_text.lstrip()
+ lspace_count = len(paste_text) - len(newtext)
+ paste_text = ' ' * lspace_count + newtext.replace(self._groupChar, '').replace('(', '-').replace(')','')
+
+ if field._insertRight and self._groupDigits:
+ # want to paste to the left; see if it will fit:
+ left_text = old_value[edit_start:sel_start].lstrip()
+## dbg('len(left_text):', len(left_text))
+## dbg('len(paste_text):', len(paste_text))
+## dbg('sel_start - (len(left_text) + len(paste_text)) >= edit_start?', sel_start - (len(left_text) + len(paste_text)) >= edit_start)
+ if sel_start - (len(left_text) + len(paste_text)) >= edit_start:
+ # will fit! create effective paste text, and move cursor back to do so:
+ paste_text = left_text + paste_text
+ sel_start -= len(paste_text)
+ sel_start += sel_to - orig_sel_start # decrease by amount selected
+ else:
+## dbg("won't fit left;", 'paste text remains: "%s"' % paste_text)
+## dbg('adjusted start before accounting for grouping:', sel_start)
+## dbg('adjusted paste_text before accounting for grouping: "%s"' % paste_text)
+ pass
+ if self._groupDigits and sel_start != orig_sel_start:
+ left_len = len(old_value[:sel_to].lstrip())
+ # remove group chars from adjusted paste string, and left pad to wipe out
+ # old characters, so that selection will remove the right chars, and
+ # readjust will do the right thing:
+ paste_text = paste_text.replace(self._groupChar,'')
+ adjcount = left_len - len(paste_text)
+ paste_text = ' ' * adjcount + paste_text
+ sel_start = sel_to - len(paste_text)
+## dbg('adjusted start after accounting for grouping:', sel_start)
+## dbg('adjusted paste_text after accounting for grouping: "%s"' % paste_text)
+ self.SetInsertionPoint(sel_to)
+ self.SetSelection(sel_start, sel_to)
+
+ new_text, replace_to = MaskedEditMixin._Paste(self,
+ paste_text,
+ raise_on_invalid=raise_on_invalid,
+ just_return_value=True)
+ self._SetInsertionPoint(orig_sel_to)
+ self._SetSelection(orig_sel_start, orig_sel_to)
+ if not just_return_value and new_text is not None:
+ if new_text != self._GetValue():
+ self.modified = True
+ if new_text == '':
+ self.ClearValue()
+ else:
+ wx.CallAfter(self._SetValue, new_text)
+ wx.CallAfter(self._SetInsertionPoint, replace_to)
+## dbg(indent=0)
+ else:
+## dbg(indent=0)
+ return new_text, replace_to
+
+ def _Undo(self, value=None, prev=None):
+ '''numctrl's undo is more complicated than the base control's, due to
+ grouping characters; we don't want to consider them when calculating
+ the undone portion.'''
+## dbg('NumCtrl::_Undo', indent=1)
+ if value is None: value = self._GetValue()
+ if prev is None: prev = self._prevValue
+ if not self._groupDigits:
+ ignore, (new_sel_start, new_sel_to) = BaseMaskedTextCtrl._Undo(self, value, prev, just_return_results = True)
+ self._SetValue(prev)
+ self._SetInsertionPoint(new_sel_start)
+ self._SetSelection(new_sel_start, new_sel_to)
+ self._prevSelection = (new_sel_start, new_sel_to)
+## dbg('resetting "prev selection" to', self._prevSelection)
+## dbg(indent=0)
+ return
+ # else...
+ sel_start, sel_to = self._prevSelection
+ edit_start, edit_end = self._FindFieldExtent(0)
+
+ adjvalue = self._GetNumValue(value).rjust(self._masklength)
+ adjprev = self._GetNumValue(prev ).rjust(self._masklength)
+
+ # move selection to account for "ungrouped" value:
+ left_text = value[sel_start:].lstrip()
+ numleftgroups = len(left_text) - len(left_text.replace(self._groupChar, ''))
+ adjsel_start = sel_start + numleftgroups
+ right_text = value[sel_to:].lstrip()
+ numrightgroups = len(right_text) - len(right_text.replace(self._groupChar, ''))
+ adjsel_to = sel_to + numrightgroups
+## dbg('adjusting "previous" selection from', (sel_start, sel_to), 'to:', (adjsel_start, adjsel_to))
+ self._prevSelection = (adjsel_start, adjsel_to)
+
+ # determine appropriate selection for ungrouped undo
+ ignore, (new_sel_start, new_sel_to) = BaseMaskedTextCtrl._Undo(self, adjvalue, adjprev, just_return_results = True)
+
+ # adjust new selection based on grouping:
+ left_len = edit_end - new_sel_start
+ numleftgroups = left_len / 3
+ new_sel_start -= numleftgroups
+ if numleftgroups and left_len % 3 == 0:
+ new_sel_start += 1
+
+ if new_sel_start < self._masklength and prev[new_sel_start] == self._groupChar:
+ new_sel_start += 1
+
+ right_len = edit_end - new_sel_to
+ numrightgroups = right_len / 3
+ new_sel_to -= numrightgroups
+
+ if new_sel_to and prev[new_sel_to-1] == self._groupChar:
+ new_sel_to -= 1
+
+ if new_sel_start > new_sel_to:
+ new_sel_to = new_sel_start
+
+ # for numbers, we don't care about leading whitespace; adjust selection if
+ # it includes leading space.
+ prev_stripped = prev.lstrip()
+ prev_start = self._masklength - len(prev_stripped)
+ if new_sel_start < prev_start:
+ new_sel_start = prev_start
+
+## dbg('adjusted selection accounting for grouping:', (new_sel_start, new_sel_to))
+ self._SetValue(prev)
+ self._SetInsertionPoint(new_sel_start)
+ self._SetSelection(new_sel_start, new_sel_to)
+ self._prevSelection = (new_sel_start, new_sel_to)
+## dbg('resetting "prev selection" to', self._prevSelection)
+## dbg(indent=0)
+
+#===========================================================================
+
+if __name__ == '__main__':
+
+ import traceback
+
+ class myDialog(wx.Dialog):
+ def __init__(self, parent, id, title,
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = wx.DEFAULT_DIALOG_STYLE ):
+ wx.Dialog.__init__(self, parent, id, title, pos, size, style)
+
+ self.int_ctrl = NumCtrl(self, wx.NewId(), size=(55,20))
+ self.OK = wx.Button( self, wx.ID_OK, "OK")
+ self.Cancel = wx.Button( self, wx.ID_CANCEL, "Cancel")
+
+ vs = wx.BoxSizer( wx.VERTICAL )
+ vs.Add( self.int_ctrl, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
+ hs = wx.BoxSizer( wx.HORIZONTAL )
+ hs.Add( self.OK, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
+ hs.Add( self.Cancel, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
+ vs.Add(hs, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
+
+ self.SetAutoLayout( True )
+ self.SetSizer( vs )
+ vs.Fit( self )
+ vs.SetSizeHints( self )
+ self.Bind(EVT_NUM, self.OnChange, self.int_ctrl)
+
+ def OnChange(self, event):
+ print 'value now', event.GetValue()
+
+ class TestApp(wx.App):
+ def OnInit(self):
+ try:
+ self.frame = wx.Frame(None, -1, "Test", (20,20), (120,100) )
+ self.panel = wx.Panel(self.frame, -1)
+ button = wx.Button(self.panel, -1, "Push Me", (20, 20))
+ self.Bind(wx.EVT_BUTTON, self.OnClick, button)
+ except:
+ traceback.print_exc()
+ return False
+ return True
+
+ def OnClick(self, event):
+ dlg = myDialog(self.panel, -1, "test NumCtrl")
+ dlg.int_ctrl.SetValue(501)
+ dlg.int_ctrl.SetInsertionPoint(1)
+ dlg.int_ctrl.SetSelection(1,2)
+ rc = dlg.ShowModal()
+ print 'final value', dlg.int_ctrl.GetValue()
+ del dlg
+ self.frame.Destroy()
+
+ def Show(self):
+ self.frame.Show(True)
+
+ try:
+ app = TestApp(0)
+ app.Show()
+ app.MainLoop()
+ except:
+ traceback.print_exc()
+
+__i=0
+## To-Do's:
+## =============================##
+## 1. Add support for printf-style format specification.
+## 2. Add option for repositioning on 'illegal' insertion point.
+##
+## Version 1.4
+## 1. In response to user request, added limitOnFieldChange feature, so that
+## out-of-bounds values can be temporarily added to the control, but should
+## navigation be attempted out of an invalid field, it will not navigate,
+## and if focus is lost on a control so limited with an invalid value, it
+## will change the value to the nearest bound.
+##
+## Version 1.3
+## 1. fixed to allow space for a group char.
+##
+## Version 1.2
+## 1. Allowed select/replace digits.
+## 2. Fixed undo to ignore grouping chars.
+##
+## Version 1.1
+## 1. Fixed .SetIntegerWidth() and .SetFractionWidth() functions.
+## 2. Added autoSize parameter, to allow manual sizing of the control.
+## 3. Changed inheritance to use wxBaseMaskedTextCtrl, to remove exposure of
+## nonsensical parameter methods from the control, so it will work
+## properly with Boa.
+## 4. Fixed allowNone bug found by user sameerc1@grandecom.net
+##
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/textctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/textctrl.py
new file mode 100644
index 0000000..727f448
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/textctrl.py
@@ -0,0 +1,419 @@
+#----------------------------------------------------------------------------
+# Name: masked.textctrl.py
+# Authors: Jeff Childers, Will Sadkin
+# Email: jchilders_98@yahoo.com, wsadkin@nameconnector.com
+# Created: 02/11/2003
+# Copyright: (c) 2003 by Jeff Childers, Will Sadkin, 2003
+# Portions: (c) 2002 by Will Sadkin, 2002-2003
+# RCS-ID: $Id$
+# License: wxWidgets license
+#----------------------------------------------------------------------------
+#
+# This file contains the most typically used generic masked control,
+# masked.TextCtrl. It also defines the BaseMaskedTextCtrl, which can
+# be used to derive other "semantics-specific" classes, like masked.NumCtrl,
+# masked.TimeCtrl, and masked.IpAddrCtrl.
+#
+#----------------------------------------------------------------------------
+"""
+Provides a generic, fully configurable masked edit text control, as well as
+a base class from which you can derive masked controls tailored to a specific
+function. See maskededit module overview for how to configure the control.
+"""
+
+import wx
+from wx.lib.masked import *
+
+# jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
+# be a good place to implement the 2.3 logger class
+from wx.tools.dbg import Logger
+##dbg = Logger()
+##dbg(enable=1)
+
+
+class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
+ """
+ This is the primary derivation from MaskedEditMixin. It provides
+ a general masked text control that can be configured with different
+ masks.
+
+ However, this is done with an extra level of inheritance, so that
+ "general" classes like masked.TextCtrl can have all possible attributes,
+ while derived classes, like masked.TimeCtrl and masked.NumCtrl
+ can prevent exposure of those optional attributes of their base
+ class that do not make sense for their derivation. Therefore,
+ we define::
+
+ BaseMaskedTextCtrl(TextCtrl, MaskedEditMixin)
+
+ and::
+
+ masked.TextCtrl(BaseMaskedTextCtrl, MaskedEditAccessorsMixin).
+
+ This allows us to then derive::
+
+ masked.NumCtrl( BaseMaskedTextCtrl )
+
+ and not have to expose all the same accessor functions for the
+ derived control when they don't all make sense for it.
+
+ In practice, BaseMaskedTextCtrl should never be instantiated directly,
+ but should only be used in derived classes.
+ """
+
+ def __init__( self, parent, id=-1, value = '',
+ pos = wx.DefaultPosition,
+ size = wx.DefaultSize,
+ style = wx.TE_PROCESS_TAB,
+ validator=wx.DefaultValidator, ## placeholder provided for data-transfer logic
+ name = 'maskedTextCtrl',
+ setupEventHandling = True, ## setup event handling by default
+ **kwargs):
+
+ if not hasattr(self, 'this'):
+ wx.TextCtrl.__init__(self, parent, id, value='',
+ pos=pos, size = size,
+ style=style, validator=validator,
+ name=name)
+
+ self._PostInit(setupEventHandling = setupEventHandling,
+ name=name, value=value,**kwargs )
+
+
+ def _PostInit(self,setupEventHandling=True,
+ name='maskedTextCtrl' , value='', **kwargs):
+
+ self.controlInitialized = True
+ MaskedEditMixin.__init__( self, name, **kwargs )
+
+ self._SetInitialValue(value)
+
+ if setupEventHandling:
+ ## Setup event handlers
+ self.Bind(wx.EVT_SET_FOCUS, self._OnFocus ) ## defeat automatic full selection
+ self.Bind(wx.EVT_KILL_FOCUS, self._OnKillFocus ) ## run internal validator
+ self.Bind(wx.EVT_LEFT_DCLICK, self._OnDoubleClick) ## select field under cursor on dclick
+ self.Bind(wx.EVT_RIGHT_UP, self._OnContextMenu ) ## bring up an appropriate context menu
+ self.Bind(wx.EVT_KEY_DOWN, self._OnKeyDown ) ## capture control events not normally seen, eg ctrl-tab.
+ self.Bind(wx.EVT_CHAR, self._OnChar ) ## handle each keypress
+ self.Bind(wx.EVT_TEXT, self._OnTextChange ) ## color control appropriately & keep
+ ## track of previous value for undo
+
+
+ def __repr__(self):
+ return "<BaseMaskedTextCtrl: %s>" % self.GetValue()
+
+
+ def _GetSelection(self):
+ """
+ Allow mixin to get the text selection of this control.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+ return self.GetSelection()
+
+ def _SetSelection(self, sel_start, sel_to):
+ """
+ Allow mixin to set the text selection of this control.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+#### dbg("MaskedTextCtrl::_SetSelection(%(sel_start)d, %(sel_to)d)" % locals())
+ if self:
+ return self.SetSelection( sel_start, sel_to )
+
+## def SetSelection(self, sel_start, sel_to):
+## """
+## This is just for debugging...
+## """
+## dbg("MaskedTextCtrl::SetSelection(%(sel_start)d, %(sel_to)d)" % locals())
+## wx.TextCtrl.SetSelection(self, sel_start, sel_to)
+
+
+ def _GetInsertionPoint(self):
+ return self.GetInsertionPoint()
+
+ def _SetInsertionPoint(self, pos):
+#### dbg("MaskedTextCtrl::_SetInsertionPoint(%(pos)d)" % locals())
+ if self:
+ self.SetInsertionPoint(pos)
+
+## def SetInsertionPoint(self, pos):
+## """
+## This is just for debugging...
+## """
+## dbg("MaskedTextCtrl::SetInsertionPoint(%(pos)d)" % locals())
+## wx.TextCtrl.SetInsertionPoint(self, pos)
+
+
+ def IsEmpty(*args, **kw):
+ return MaskedEditMixin.IsEmpty(*args, **kw)
+
+ def _GetValue(self):
+ """
+ Allow mixin to get the raw value of the control with this function.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+ return self.GetValue()
+
+
+ def _SetValue(self, value):
+ """
+ Allow mixin to set the raw value of the control with this function.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+## dbg('MaskedTextCtrl::_SetValue("%(value)s", use_change_value=%(use_change_value)d)' % locals(), indent=1)
+ # Record current selection and insertion point, for undo
+ self._prevSelection = self._GetSelection()
+ self._prevInsertionPoint = self._GetInsertionPoint()
+ wx.TextCtrl.SetValue(self, value)
+## dbg(indent=0)
+
+ def _ChangeValue(self, value):
+ """
+ Allow mixin to set the raw value of the control with this function without
+ generating an event as a result. (New for masked.TextCtrl as of 2.8.4)
+ """
+## dbg('MaskedTextCtrl::_ChangeValue("%(value)s", use_change_value=%(use_change_value)d)' % locals(), indent=1)
+ # Record current selection and insertion point, for undo
+ self._prevSelection = self._GetSelection()
+ self._prevInsertionPoint = self._GetInsertionPoint()
+ wx.TextCtrl.ChangeValue(self, value)
+## dbg(indent=0)
+
+ def SetValue(self, value):
+ """
+ This function redefines the externally accessible .SetValue() to be
+ a smart "paste" of the text in question, so as not to corrupt the
+ masked control. NOTE: this must be done in the class derived
+ from the base wx control.
+ """
+ self.ModifyValue(value, use_change_value=False)
+
+ def ChangeValue(self, value):
+ """
+ Provided to accomodate similar functionality added to base control in wxPython 2.7.1.1.
+ """
+ self.ModifyValue(value, use_change_value=True)
+
+
+ def ModifyValue(self, value, use_change_value=False):
+ """
+ This factored function of common code does the bulk of the work for SetValue
+ and ChangeValue.
+ """
+## dbg('MaskedTextCtrl::ModifyValue("%(value)s", use_change_value=%(use_change_value)d)' % locals(), indent=1)
+
+ if not self._mask:
+ if use_change_value:
+ wx.TextCtrl.ChangeValue(self, value) # revert to base control behavior
+ else:
+ wx.TextCtrl.SetValue(self, value) # revert to base control behavior
+ return
+
+ # empty previous contents, replacing entire value:
+ self._SetInsertionPoint(0)
+ self._SetSelection(0, self._masklength)
+ if self._signOk and self._useParens:
+ signpos = value.find('-')
+ if signpos != -1:
+ value = value[:signpos] + '(' + value[signpos+1:].strip() + ')'
+ elif value.find(')') == -1 and len(value) < self._masklength:
+ value += ' ' # add place holder for reserved space for right paren
+
+ if( len(value) < self._masklength # value shorter than control
+ and (self._isFloat or self._isInt) # and it's a numeric control
+ and self._ctrl_constraints._alignRight ): # and it's a right-aligned control
+
+## dbg('len(value)', len(value), ' < self._masklength', self._masklength)
+ # try to intelligently "pad out" the value to the right size:
+ value = self._template[0:self._masklength - len(value)] + value
+ if self._isFloat and value.find('.') == -1:
+ value = value[1:]
+## dbg('padded value = "%s"' % value)
+
+ # make Set/ChangeValue behave the same as if you had typed the value in:
+ try:
+ value, replace_to = self._Paste(value, raise_on_invalid=True, just_return_value=True)
+ if self._isFloat:
+ self._isNeg = False # (clear current assumptions)
+ value = self._adjustFloat(value)
+ elif self._isInt:
+ self._isNeg = False # (clear current assumptions)
+ value = self._adjustInt(value)
+ elif self._isDate and not self.IsValid(value) and self._4digityear:
+ value = self._adjustDate(value, fixcentury=True)
+ except ValueError:
+ # If date, year might be 2 digits vs. 4; try adjusting it:
+ if self._isDate and self._4digityear:
+ dateparts = value.split(' ')
+ dateparts[0] = self._adjustDate(dateparts[0], fixcentury=True)
+ value = string.join(dateparts, ' ')
+## dbg('adjusted value: "%s"' % value)
+ value, replace_to = self._Paste(value, raise_on_invalid=True, just_return_value=True)
+ else:
+## dbg('exception thrown', indent=0)
+ raise
+ if use_change_value:
+ self._ChangeValue(value)
+ else:
+ self._SetValue(value) # note: to preserve similar capability, .SetValue()
+ # does not change IsModified()
+#### dbg('queuing insertion after ._Set/ChangeValue', replace_to)
+ # set selection to last char replaced by paste
+ wx.CallAfter(self._SetInsertionPoint, replace_to)
+ wx.CallAfter(self._SetSelection, replace_to, replace_to)
+## dbg(indent=0)
+
+
+ def SetFont(self, *args, **kwargs):
+ """ Set the font, then recalculate control size, if appropriate. """
+ wx.TextCtrl.SetFont(self, *args, **kwargs)
+ if self._autofit:
+## dbg('calculated size:', self._CalcSize())
+ self.SetClientSize(self._CalcSize())
+ width = self.GetSize().width
+ height = self.GetBestSize().height
+## dbg('setting client size to:', (width, height))
+ self.SetInitialSize((width, height))
+
+
+ def Clear(self):
+ """ Blanks the current control value by replacing it with the default value."""
+## dbg("MaskedTextCtrl::Clear - value reset to default value (template)")
+ if self._mask:
+ self.ClearValue()
+ else:
+ wx.TextCtrl.Clear(self) # else revert to base control behavior
+
+
+ def _Refresh(self):
+ """
+ Allow mixin to refresh the base control with this function.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+## dbg('MaskedTextCtrl::_Refresh', indent=1)
+ wx.TextCtrl.Refresh(self)
+## dbg(indent=0)
+
+
+ def Refresh(self):
+ """
+ This function redefines the externally accessible .Refresh() to
+ validate the contents of the masked control as it refreshes.
+ NOTE: this must be done in the class derived from the base wx control.
+ """
+## dbg('MaskedTextCtrl::Refresh', indent=1)
+ self._CheckValid()
+ self._Refresh()
+## dbg(indent=0)
+
+
+ def _IsEditable(self):
+ """
+ Allow mixin to determine if the base control is editable with this function.
+ REQUIRED by any class derived from MaskedEditMixin.
+ """
+ return wx.TextCtrl.IsEditable(self)
+
+
+ def Cut(self):
+ """
+ This function redefines the externally accessible .Cut to be
+ a smart "erase" of the text in question, so as not to corrupt the
+ masked control. NOTE: this must be done in the class derived
+ from the base wx control.
+ """
+ if self._mask:
+ self._Cut() # call the mixin's Cut method
+ else:
+ wx.TextCtrl.Cut(self) # else revert to base control behavior
+
+
+ def Paste(self):
+ """
+ This function redefines the externally accessible .Paste to be
+ a smart "paste" of the text in question, so as not to corrupt the
+ masked control. NOTE: this must be done in the class derived
+ from the base wx control.
+ """
+ if self._mask:
+ self._Paste() # call the mixin's Paste method
+ else:
+ wx.TextCtrl.Paste(self, value) # else revert to base control behavior
+
+
+ def Undo(self):
+ """
+ This function defines the undo operation for the control. (The default
+ undo is 1-deep.)
+ """
+ if self._mask:
+ self._Undo()
+ else:
+ wx.TextCtrl.Undo(self) # else revert to base control behavior
+
+
+ def IsModified(self):
+ """
+ This function overrides the raw wx.TextCtrl method, because the
+ masked edit mixin uses SetValue to change the value, which doesn't
+ modify the state of this attribute. So, the derived control keeps track
+ on each keystroke to see if the value changes, and if so, it's been
+ modified.
+ """
+ return wx.TextCtrl.IsModified(self) or self.modified
+
+
+ def _CalcSize(self, size=None):
+ """
+ Calculate automatic size if allowed; use base mixin function.
+ """
+ return self._calcSize(size)
+
+
+class TextCtrl( BaseMaskedTextCtrl, MaskedEditAccessorsMixin ):
+ """
+ The "user-visible" masked text control; it is identical to the
+ BaseMaskedTextCtrl class it's derived from.
+ (This extra level of inheritance allows us to add the generic
+ set of masked edit parameters only to this class while allowing
+ other classes to derive from the "base" masked text control,
+ and provide a smaller set of valid accessor functions.)
+ See BaseMaskedTextCtrl for available methods.
+ """
+ pass
+
+
+class PreMaskedTextCtrl( BaseMaskedTextCtrl, MaskedEditAccessorsMixin ):
+ """
+ This class exists to support the use of XRC subclassing.
+ """
+ # This should really be wx.EVT_WINDOW_CREATE but it is not
+ # currently delivered for native controls on all platforms, so
+ # we'll use EVT_SIZE instead. It should happen shortly after the
+ # control is created as the control is set to its "best" size.
+ _firstEventType = wx.EVT_SIZE
+
+ def __init__(self):
+ pre = wx.PreTextCtrl()
+ self.PostCreate(pre)
+ self.Bind(self._firstEventType, self.OnCreate)
+
+
+ def OnCreate(self, evt):
+ self.Unbind(self._firstEventType)
+ self._PostInit()
+
+__i=0
+## CHANGELOG:
+## ====================
+## Version 1.3
+## - Added support for ChangeValue() function, similar to that of the base
+## control, added in wxPython 2.7.1.1.
+##
+## Version 1.2
+## - Converted docstrings to reST format, added doc for ePyDoc.
+## removed debugging override functions.
+##
+## Version 1.1
+## 1. Added .SetFont() method that properly resizes control
+## 2. Modified control to support construction via XRC mechanism.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/timectrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/timectrl.py
new file mode 100644
index 0000000..0a35018
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/masked/timectrl.py
@@ -0,0 +1,1405 @@
+#----------------------------------------------------------------------------
+# Name: timectrl.py
+# Author: Will Sadkin
+# Created: 09/19/2002
+# Copyright: (c) 2002 by Will Sadkin, 2002
+# RCS-ID: $Id$
+# License: wxWindows license
+#----------------------------------------------------------------------------
+# NOTE:
+# This was written way it is because of the lack of masked edit controls
+# in wxWindows/wxPython. I would also have preferred to derive this
+# control from a wxSpinCtrl rather than wxTextCtrl, but the wxTextCtrl
+# component of that control is inaccessible through the interface exposed in
+# wxPython.
+#
+# TimeCtrl does not use validators, because it does careful manipulation
+# of the cursor in the text window on each keystroke, and validation is
+# cursor-position specific, so the control intercepts the key codes before the
+# validator would fire.
+#
+# TimeCtrl now also supports .SetValue() with either strings or wxDateTime
+# values, as well as range limits, with the option of either enforcing them
+# or simply coloring the text of the control if the limits are exceeded.
+#
+# Note: this class now makes heavy use of wxDateTime for parsing and
+# regularization, but it always does so with ephemeral instances of
+# wxDateTime, as the C++/Python validity of these instances seems to not
+# persist. Because "today" can be a day for which an hour can "not exist"
+# or be counted twice (1 day each per year, for DST adjustments), the date
+# portion of all wxDateTimes used/returned have their date portion set to
+# Jan 1, 1970 (the "epoch.")
+#----------------------------------------------------------------------------
+# 12/13/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for V2.5 compatability
+# o wx.SpinCtl has some issues that cause the control to
+# lock up. Noted in other places using it too, it's not this module
+# that's at fault.
+#
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxMaskedTextCtrl -> masked.TextCtrl
+# o wxTimeCtrl -> masked.TimeCtrl
+#
+
+"""
+*TimeCtrl* provides a multi-cell control that allows manipulation of a time
+value. It supports 12 or 24 hour format, and you can use wxDateTime or mxDateTime
+to get/set values from the control.
+
+Left/right/tab keys to switch cells within a TimeCtrl, and the up/down arrows act
+like a spin control. TimeCtrl also allows for an actual spin button to be attached
+to the control, so that it acts like the up/down arrow keys.
+
+The ! or c key sets the value of the control to the current time.
+
+ Here's the API for TimeCtrl::
+
+ from wx.lib.masked import TimeCtrl
+
+ TimeCtrl(
+ parent, id = -1,
+ value = '00:00:00',
+ pos = wx.DefaultPosition,
+ size = wx.DefaultSize,
+ style = wxTE_PROCESS_TAB,
+ validator = wx.DefaultValidator,
+ name = "time",
+ format = 'HHMMSS',
+ fmt24hr = False,
+ displaySeconds = True,
+ spinButton = None,
+ min = None,
+ max = None,
+ limited = None,
+ oob_color = "Yellow"
+ )
+
+
+ value
+ If no initial value is set, the default will be midnight; if an illegal string
+ is specified, a ValueError will result. (You can always later set the initial time
+ with SetValue() after instantiation of the control.)
+
+ size
+ The size of the control will be automatically adjusted for 12/24 hour format
+ if wx.DefaultSize is specified. NOTE: due to a problem with wx.DateTime, if the
+ locale does not use 'AM/PM' for its values, the default format will automatically
+ change to 24 hour format, and an AttributeError will be thrown if a non-24 format
+ is specified.
+
+ style
+ By default, TimeCtrl will process TAB events, by allowing tab to the
+ different cells within the control.
+
+ validator
+ By default, TimeCtrl just uses the default (empty) validator, as all
+ of its validation for entry control is handled internally. However, a validator
+ can be supplied to provide data transfer capability to the control.
+
+ format
+ This parameter can be used instead of the fmt24hr and displaySeconds
+ parameters, respectively; it provides a shorthand way to specify the time
+ format you want. Accepted values are 'HHMMSS', 'HHMM', '24HHMMSS', and
+ '24HHMM'. If the format is specified, the other two arguments will be ignored.
+
+ fmt24hr
+ If True, control will display time in 24 hour time format; if False, it will
+ use 12 hour AM/PM format. SetValue() will adjust values accordingly for the
+ control, based on the format specified. (This value is ignored if the *format*
+ parameter is specified.)
+
+ displaySeconds
+ If True, control will include a seconds field; if False, it will
+ just show hours and minutes. (This value is ignored if the *format*
+ parameter is specified.)
+
+ spinButton
+ If specified, this button's events will be bound to the behavior of the
+ TimeCtrl, working like up/down cursor key events. (See BindSpinButton.)
+
+ min
+ Defines the lower bound for "valid" selections in the control.
+ By default, TimeCtrl doesn't have bounds. You must set both upper and lower
+ bounds to make the control pay attention to them, (as only one bound makes no sense
+ with times.) "Valid" times will fall between the min and max "pie wedge" of the
+ clock.
+ max
+ Defines the upper bound for "valid" selections in the control.
+ "Valid" times will fall between the min and max "pie wedge" of the
+ clock. (This can be a "big piece", ie. min = 11pm, max= 10pm
+ means *all but the hour from 10:00pm to 11pm are valid times.*)
+ limited
+ If True, the control will not permit entry of values that fall outside the
+ set bounds.
+
+ oob_color
+ Sets the background color used to indicate out-of-bounds values for the control
+ when the control is not limited. This is set to "Yellow" by default.
+
+--------------------
+
+EVT_TIMEUPDATE(win, id, func)
+ func is fired whenever the value of the control changes.
+
+
+SetValue(time_string | wxDateTime | wxTimeSpan | mx.DateTime | mx.DateTimeDelta)
+ Sets the value of the control to a particular time, given a valid
+ value; raises ValueError on invalid value.
+
+*NOTE:* This will only allow mx.DateTime or mx.DateTimeDelta if mx.DateTime
+ was successfully imported by the class module.
+
+GetValue(as_wxDateTime = False, as_mxDateTime = False, as_wxTimeSpan=False, as mxDateTimeDelta=False)
+ Retrieves the value of the time from the control. By default this is
+ returned as a string, unless one of the other arguments is set; args are
+ searched in the order listed; only one value will be returned.
+
+GetWxDateTime(value=None)
+ When called without arguments, retrieves the value of the control, and applies
+ it to the wxDateTimeFromHMS() constructor, and returns the resulting value.
+ The date portion will always be set to Jan 1, 1970. This form is the same
+ as GetValue(as_wxDateTime=True). GetWxDateTime can also be called with any of the
+ other valid time formats settable with SetValue, to regularize it to a single
+ wxDateTime form. The function will raise ValueError on an unconvertable argument.
+
+GetMxDateTime()
+ Retrieves the value of the control and applies it to the DateTime.Time()
+ constructor,and returns the resulting value. (The date portion will always be
+ set to Jan 1, 1970.) (Same as GetValue(as_wxDateTime=True); provided for backward
+ compatibility with previous release.)
+
+
+BindSpinButton(SpinBtton)
+ Binds an externally created spin button to the control, so that up/down spin
+ events change the active cell or selection in the control (in addition to the
+ up/down cursor keys.) (This is primarily to allow you to create a "standard"
+ interface to time controls, as seen in Windows.)
+
+
+SetMin(min=None)
+ Sets the expected minimum value, or lower bound, of the control.
+ (The lower bound will only be enforced if the control is
+ configured to limit its values to the set bounds.)
+ If a value of *None* is provided, then the control will have
+ explicit lower bound. If the value specified is greater than
+ the current lower bound, then the function returns False and the
+ lower bound will not change from its current setting. On success,
+ the function returns True. Even if set, if there is no corresponding
+ upper bound, the control will behave as if it is unbounded.
+
+ If successful and the current value is outside the
+ new bounds, if the control is limited the value will be
+ automatically adjusted to the nearest bound; if not limited,
+ the background of the control will be colored with the current
+ out-of-bounds color.
+
+GetMin(as_string=False)
+ Gets the current lower bound value for the control, returning
+ None, if not set, or a wxDateTime, unless the as_string parameter
+ is set to True, at which point it will return the string
+ representation of the lower bound.
+
+
+SetMax(max=None)
+ Sets the expected maximum value, or upper bound, of the control.
+ (The upper bound will only be enforced if the control is
+ configured to limit its values to the set bounds.)
+ If a value of *None* is provided, then the control will
+ have no explicit upper bound. If the value specified is less
+ than the current lower bound, then the function returns False and
+ the maximum will not change from its current setting. On success,
+ the function returns True. Even if set, if there is no corresponding
+ lower bound, the control will behave as if it is unbounded.
+
+ If successful and the current value is outside the
+ new bounds, if the control is limited the value will be
+ automatically adjusted to the nearest bound; if not limited,
+ the background of the control will be colored with the current
+ out-of-bounds color.
+
+GetMax(as_string = False)
+ Gets the current upper bound value for the control, returning
+ None, if not set, or a wxDateTime, unless the as_string parameter
+ is set to True, at which point it will return the string
+ representation of the lower bound.
+
+
+
+SetBounds(min=None,max=None)
+ This function is a convenience function for setting the min and max
+ values at the same time. The function only applies the maximum bound
+ if setting the minimum bound is successful, and returns True
+ only if both operations succeed. *Note: leaving out an argument
+ will remove the corresponding bound, and result in the behavior of
+ an unbounded control.*
+
+GetBounds(as_string = False)
+ This function returns a two-tuple (min,max), indicating the
+ current bounds of the control. Each value can be None if
+ that bound is not set. The values will otherwise be wxDateTimes
+ unless the as_string argument is set to True, at which point they
+ will be returned as string representations of the bounds.
+
+
+IsInBounds(value=None)
+ Returns *True* if no value is specified and the current value
+ of the control falls within the current bounds. This function can also
+ be called with a value to see if that value would fall within the current
+ bounds of the given control. It will raise ValueError if the value
+ specified is not a wxDateTime, mxDateTime (if available) or parsable string.
+
+
+IsValid(value)
+ Returns *True* if specified value is a legal time value and
+ falls within the current bounds of the given control.
+
+
+SetLimited(bool)
+ If called with a value of True, this function will cause the control
+ to limit the value to fall within the bounds currently specified.
+ (Provided both bounds have been set.)
+ If the control's value currently exceeds the bounds, it will then
+ be set to the nearest bound.
+ If called with a value of False, this function will disable value
+ limiting, but coloring of out-of-bounds values will still take
+ place if bounds have been set for the control.
+IsLimited()
+ Returns *True* if the control is currently limiting the
+ value to fall within the current bounds.
+
+
+"""
+
+import copy
+import string
+import types
+
+import wx
+
+from wx.tools.dbg import Logger
+from wx.lib.masked import Field, BaseMaskedTextCtrl
+
+dbg = Logger()
+##dbg(enable=0)
+
+try:
+ from mx import DateTime
+ accept_mx = True
+except ImportError:
+ accept_mx = False
+
+# This class of event fires whenever the value of the time changes in the control:
+wxEVT_TIMEVAL_UPDATED = wx.NewEventType()
+EVT_TIMEUPDATE = wx.PyEventBinder(wxEVT_TIMEVAL_UPDATED, 1)
+
+class TimeUpdatedEvent(wx.PyCommandEvent):
+ """
+ Used to fire an EVT_TIMEUPDATE event whenever the value in a TimeCtrl changes.
+ """
+ def __init__(self, id, value ='12:00:00 AM'):
+ wx.PyCommandEvent.__init__(self, wxEVT_TIMEVAL_UPDATED, id)
+ self.value = value
+ def GetValue(self):
+ """Retrieve the value of the time control at the time this event was generated"""
+ return self.value
+
+class TimeCtrlAccessorsMixin:
+ """
+ Defines TimeCtrl's list of attributes having their own Get/Set functions,
+ ignoring those in the base class that make no sense for a time control.
+ """
+ exposed_basectrl_params = (
+ 'defaultValue',
+ 'description',
+
+ 'useFixedWidthFont',
+ 'emptyBackgroundColour',
+ 'validBackgroundColour',
+ 'invalidBackgroundColour',
+
+ 'validFunc',
+ 'validRequired',
+ )
+ for param in exposed_basectrl_params:
+ propname = param[0].upper() + param[1:]
+ exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
+ exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
+
+ if param.find('Colour') != -1:
+ # add non-british spellings, for backward-compatibility
+ propname.replace('Colour', 'Color')
+
+ exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
+ exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
+
+
+class TimeCtrl(BaseMaskedTextCtrl):
+ """
+ Masked control providing several time formats and manipulation of time values.
+ """
+
+ valid_ctrl_params = {
+ 'format' : 'HHMMSS', # default format code
+ 'displaySeconds' : True, # by default, shows seconds
+ 'min': None, # by default, no bounds set
+ 'max': None,
+ 'limited': False, # by default, no limiting even if bounds set
+ 'useFixedWidthFont': True, # by default, use a fixed-width font
+ 'oob_color': "Yellow" # by default, the default masked.TextCtrl "invalid" color
+ }
+
+ def __init__ (
+ self, parent, id=-1, value = '00:00:00',
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ fmt24hr=False,
+ spinButton = None,
+ style = wx.TE_PROCESS_TAB,
+ validator = wx.DefaultValidator,
+ name = "time",
+ **kwargs ):
+
+ # set defaults for control:
+## dbg('setting defaults:')
+
+ self.__fmt24hr = False
+ wxdt = wx.DateTimeFromDMY(1, 0, 1970)
+ try:
+ if wxdt.Format('%p') != 'AM':
+ TimeCtrl.valid_ctrl_params['format'] = '24HHMMSS'
+ self.__fmt24hr = True
+ fmt24hr = True # force/change default positional argument
+ # (will countermand explicit set to False too.)
+ except:
+ TimeCtrl.valid_ctrl_params['format'] = '24HHMMSS'
+ self.__fmt24hr = True
+ fmt24hr = True # force/change default positional argument
+ # (will countermand explicit set to False too.)
+
+ for key, param_value in TimeCtrl.valid_ctrl_params.items():
+ # This is done this way to make setattr behave consistently with
+ # "private attribute" name mangling
+ setattr(self, "_TimeCtrl__" + key, copy.copy(param_value))
+
+ # create locals from current defaults, so we can override if
+ # specified in kwargs, and handle uniformly:
+ min = self.__min
+ max = self.__max
+ limited = self.__limited
+ self.__posCurrent = 0
+ # handle deprecated keword argument name:
+ if kwargs.has_key('display_seconds'):
+ kwargs['displaySeconds'] = kwargs['display_seconds']
+ del kwargs['display_seconds']
+ if not kwargs.has_key('displaySeconds'):
+ kwargs['displaySeconds'] = True
+
+ # (handle positional arg (from original release) differently from rest of kwargs:)
+ if not kwargs.has_key('format'):
+ if fmt24hr:
+ if kwargs.has_key('displaySeconds') and kwargs['displaySeconds']:
+ kwargs['format'] = '24HHMMSS'
+ del kwargs['displaySeconds']
+ else:
+ kwargs['format'] = '24HHMM'
+ else:
+ if kwargs.has_key('displaySeconds') and kwargs['displaySeconds']:
+ kwargs['format'] = 'HHMMSS'
+ del kwargs['displaySeconds']
+ else:
+ kwargs['format'] = 'HHMM'
+
+ if not kwargs.has_key('useFixedWidthFont'):
+ # allow control over font selection:
+ kwargs['useFixedWidthFont'] = self.__useFixedWidthFont
+
+ maskededit_kwargs = self.SetParameters(**kwargs)
+
+ # allow for explicit size specification:
+ if size != wx.DefaultSize:
+ # override (and remove) "autofit" autoformat code in standard time formats:
+ maskededit_kwargs['formatcodes'] = 'T!'
+
+ # This allows range validation if set
+ maskededit_kwargs['validFunc'] = self.IsInBounds
+
+ # This allows range limits to affect insertion into control or not
+ # dynamically without affecting individual field constraint validation
+ maskededit_kwargs['retainFieldValidation'] = True
+
+ # Now we can initialize the base control:
+ BaseMaskedTextCtrl.__init__(
+ self, parent, id=id,
+ pos=pos, size=size,
+ style = style,
+ validator = validator,
+ name = name,
+ setupEventHandling = False,
+ **maskededit_kwargs)
+
+
+ # This makes ':' act like tab (after we fix each ':' key event to remove "shift")
+ self._SetKeyHandler(':', self._OnChangeField)
+
+
+ # This makes the up/down keys act like spin button controls:
+ self._SetKeycodeHandler(wx.WXK_UP, self.__OnSpinUp)
+ self._SetKeycodeHandler(wx.WXK_DOWN, self.__OnSpinDown)
+
+
+ # This allows ! and c/C to set the control to the current time:
+ self._SetKeyHandler('!', self.__OnSetToNow)
+ self._SetKeyHandler('c', self.__OnSetToNow)
+ self._SetKeyHandler('C', self.__OnSetToNow)
+
+
+ # Set up event handling ourselves, so we can insert special
+ # processing on the ":' key to remove the "shift" attribute
+ # *before* the default handlers have been installed, so
+ # that : takes you forward, not back, and so we can issue
+ # EVT_TIMEUPDATE events on changes:
+
+ self.Bind(wx.EVT_SET_FOCUS, self._OnFocus ) ## defeat automatic full selection
+ self.Bind(wx.EVT_KILL_FOCUS, self._OnKillFocus ) ## run internal validator
+ self.Bind(wx.EVT_LEFT_UP, self.__LimitSelection) ## limit selections to single field
+ self.Bind(wx.EVT_LEFT_DCLICK, self._OnDoubleClick ) ## select field under cursor on dclick
+ self.Bind(wx.EVT_KEY_DOWN, self._OnKeyDown ) ## capture control events not normally seen, eg ctrl-tab.
+ self.Bind(wx.EVT_CHAR, self.__OnChar ) ## remove "shift" attribute from colon key event,
+ ## then call BaseMaskedTextCtrl._OnChar with
+ ## the possibly modified event.
+ self.Bind(wx.EVT_TEXT, self.__OnTextChange, self ) ## color control appropriately and EVT_TIMEUPDATE events
+
+
+ # Validate initial value and set if appropriate
+ try:
+ self.SetBounds(min, max)
+ self.SetLimited(limited)
+ self.SetValue(value)
+ except:
+ self.SetValue('00:00:00')
+
+ if spinButton:
+ self.BindSpinButton(spinButton) # bind spin button up/down events to this control
+
+
+ def SetParameters(self, **kwargs):
+ """
+ Function providing access to the parameters governing TimeCtrl display and bounds.
+ """
+## dbg('TimeCtrl::SetParameters(%s)' % repr(kwargs), indent=1)
+ maskededit_kwargs = {}
+ reset_format = False
+
+ if kwargs.has_key('display_seconds'):
+ kwargs['displaySeconds'] = kwargs['display_seconds']
+ del kwargs['display_seconds']
+ if kwargs.has_key('format') and kwargs.has_key('displaySeconds'):
+ del kwargs['displaySeconds'] # always apply format if specified
+
+ # assign keyword args as appropriate:
+ for key, param_value in kwargs.items():
+ if key not in TimeCtrl.valid_ctrl_params.keys():
+ raise AttributeError('invalid keyword argument "%s"' % key)
+
+ if key == 'format':
+ wxdt = wx.DateTimeFromDMY(1, 0, 1970)
+ try:
+ if wxdt.Format('%p') != 'AM':
+ require24hr = True
+ else:
+ require24hr = False
+ except:
+ require24hr = True
+
+ # handle both local or generic 'maskededit' autoformat codes:
+ if param_value == 'HHMMSS' or param_value == 'TIMEHHMMSS':
+ self.__displaySeconds = True
+ self.__fmt24hr = False
+ elif param_value == 'HHMM' or param_value == 'TIMEHHMM':
+ self.__displaySeconds = False
+ self.__fmt24hr = False
+ elif param_value == '24HHMMSS' or param_value == '24HRTIMEHHMMSS':
+ self.__displaySeconds = True
+ self.__fmt24hr = True
+ elif param_value == '24HHMM' or param_value == '24HRTIMEHHMM':
+ self.__displaySeconds = False
+ self.__fmt24hr = True
+ else:
+ raise AttributeError('"%s" is not a valid format' % param_value)
+
+ if require24hr and not self.__fmt24hr:
+ raise AttributeError('"%s" is an unsupported time format for the current locale' % param_value)
+
+ reset_format = True
+
+ elif key in ("displaySeconds", "display_seconds") and not kwargs.has_key('format'):
+ self.__displaySeconds = param_value
+ reset_format = True
+
+ elif key == "min": min = param_value
+ elif key == "max": max = param_value
+ elif key == "limited": limited = param_value
+
+ elif key == "useFixedWidthFont":
+ maskededit_kwargs[key] = param_value
+
+ elif key == "oob_color":
+ maskededit_kwargs['invalidBackgroundColor'] = param_value
+
+ if reset_format:
+ if self.__fmt24hr:
+ if self.__displaySeconds: maskededit_kwargs['autoformat'] = '24HRTIMEHHMMSS'
+ else: maskededit_kwargs['autoformat'] = '24HRTIMEHHMM'
+
+ # Set hour field to zero-pad, right-insert, require explicit field change,
+ # select entire field on entry, and require a resultant valid entry
+ # to allow character entry:
+ hourfield = Field(formatcodes='0r<SV', validRegex='0\d|1\d|2[0123]', validRequired=True)
+ else:
+ if self.__displaySeconds: maskededit_kwargs['autoformat'] = 'TIMEHHMMSS'
+ else: maskededit_kwargs['autoformat'] = 'TIMEHHMM'
+
+ # Set hour field to allow spaces (at start), right-insert,
+ # require explicit field change, select entire field on entry,
+ # and require a resultant valid entry to allow character entry:
+ hourfield = Field(formatcodes='_0<rSV', validRegex='0[1-9]| [1-9]|1[012]', validRequired=True)
+ ampmfield = Field(formatcodes='S', emptyInvalid = True, validRequired = True)
+
+ # Field 1 is always a zero-padded right-insert minute field,
+ # similarly configured as above:
+ minutefield = Field(formatcodes='0r<SV', validRegex='[0-5]\d', validRequired=True)
+
+ fields = [ hourfield, minutefield ]
+ if self.__displaySeconds:
+ fields.append(copy.copy(minutefield)) # second field has same constraints as field 1
+
+ if not self.__fmt24hr:
+ fields.append(ampmfield)
+
+ # set fields argument:
+ maskededit_kwargs['fields'] = fields
+
+ # This allows range validation if set
+ maskededit_kwargs['validFunc'] = self.IsInBounds
+
+ # This allows range limits to affect insertion into control or not
+ # dynamically without affecting individual field constraint validation
+ maskededit_kwargs['retainFieldValidation'] = True
+
+ if hasattr(self, 'controlInitialized') and self.controlInitialized:
+ self.SetCtrlParameters(**maskededit_kwargs) # set appropriate parameters
+
+ # Validate initial value and set if appropriate
+ try:
+ self.SetBounds(min, max)
+ self.SetLimited(limited)
+ self.SetValue(value)
+ except:
+ self.SetValue('00:00:00')
+## dbg(indent=0)
+ return {} # no arguments to return
+ else:
+## dbg(indent=0)
+ return maskededit_kwargs
+
+
+ def BindSpinButton(self, sb):
+ """
+ This function binds an externally created spin button to the control, so that
+ up/down events from the button automatically change the control.
+ """
+## dbg('TimeCtrl::BindSpinButton')
+ self.__spinButton = sb
+ if self.__spinButton:
+ # bind event handlers to spin ctrl
+ self.__spinButton.Bind(wx.EVT_SPIN_UP, self.__OnSpinUp, self.__spinButton)
+ self.__spinButton.Bind(wx.EVT_SPIN_DOWN, self.__OnSpinDown, self.__spinButton)
+
+
+ def __repr__(self):
+ return "<TimeCtrl: %s>" % self.GetValue()
+
+
+ def SetValue(self, value):
+ """
+ Validating SetValue function for time values:
+ This function will do dynamic type checking on the value argument,
+ and convert wxDateTime, mxDateTime, or 12/24 format time string
+ into the appropriate format string for the control.
+ """
+## dbg('TimeCtrl::SetValue(%s)' % repr(value), indent=1)
+ try:
+ strtime = self._toGUI(self.__validateValue(value))
+ except:
+## dbg('validation failed', indent=0)
+ raise
+
+## dbg('strtime:', strtime)
+ self._SetValue(strtime)
+## dbg(indent=0)
+
+ def ChangeValue(self, value):
+ """
+ Validating ChangeValue function for time values:
+ This function will do dynamic type checking on the value argument,
+ and convert wxDateTime, mxDateTime, or 12/24 format time string
+ into the appropriate format string for the control.
+ """
+## dbg('TimeCtrl::ChangeValue(%s)' % repr(value), indent=1)
+ try:
+ strtime = self._toGUI(self.__validateValue(value))
+ except:
+## dbg('validation failed', indent=0)
+ raise
+
+## dbg('strtime:', strtime)
+ self._ChangeValue(strtime)
+## dbg(indent=0)
+
+ def GetValue(self,
+ as_wxDateTime = False,
+ as_mxDateTime = False,
+ as_wxTimeSpan = False,
+ as_mxDateTimeDelta = False):
+ """
+ This function returns the value of the display as a string by default, but
+ supports return as a wx.DateTime, mx.DateTime, wx.TimeSpan, or mx.DateTimeDelta,
+ if requested. (Evaluated in the order above-- first one wins!)
+ """
+
+
+ if as_wxDateTime or as_mxDateTime or as_wxTimeSpan or as_mxDateTimeDelta:
+ value = self.GetWxDateTime()
+ if as_wxDateTime:
+ pass
+ elif as_mxDateTime:
+ value = DateTime.DateTime(1970, 1, 1, value.GetHour(), value.GetMinute(), value.GetSecond())
+ elif as_wxTimeSpan:
+ value = wx.TimeSpan(value.GetHour(), value.GetMinute(), value.GetSecond())
+ elif as_mxDateTimeDelta:
+ value = DateTime.DateTimeDelta(0, value.GetHour(), value.GetMinute(), value.GetSecond())
+ else:
+ value = BaseMaskedTextCtrl.GetValue(self)
+ return value
+
+
+ def SetWxDateTime(self, wxdt):
+ """
+ Because SetValue can take a wx.DateTime, this is now just an alias.
+ """
+ self.SetValue(wxdt)
+
+
+ def GetWxDateTime(self, value=None):
+ """
+ This function is the conversion engine for TimeCtrl; it takes
+ one of the following types:
+
+ * time string
+ * wx.DateTime
+ * wx.TimeSpan
+ * mxDateTime
+ * mxDateTimeDelta
+
+ and converts it to a wx.DateTime that always has Jan 1, 1970 as its date
+ portion, so that range comparisons around values can work using
+ wx.DateTime's built-in comparison function. If a value is not
+ provided to convert, the string value of the control will be used.
+ If the value is not one of the accepted types, a ValueError will be
+ raised.
+ """
+ global accept_mx
+## dbg(suspend=1)
+## dbg('TimeCtrl::GetWxDateTime(%s)' % repr(value), indent=1)
+ if value is None:
+## dbg('getting control value')
+ value = self.GetValue()
+## dbg('value = "%s"' % value)
+
+ if type(value) == types.UnicodeType:
+ value = str(value) # convert to regular string
+
+ valid = True # assume true
+ if type(value) == types.StringType:
+
+ # Construct constant wxDateTime, then try to parse the string:
+ wxdt = wx.DateTimeFromDMY(1, 0, 1970)
+## dbg('attempting conversion')
+ value = value.strip() # (parser doesn't like leading spaces)
+ valid = wxdt.ParseTime(value)
+
+ if not valid:
+ # deal with bug/deficiency in wx.DateTime:
+ try:
+ if wxdt.Format('%p') not in ('AM', 'PM') and checkTime in (5,8):
+ # couldn't parse the AM/PM field
+ raise ValueError('cannot convert string "%s" to valid time for the current locale; please use 24hr time instead' % value)
+ else:
+ ## dbg(indent=0, suspend=0)
+ raise ValueError('cannot convert string "%s" to valid time' % value)
+ except:
+ raise ValueError('cannot convert string "%s" to valid time for the current locale; please use 24hr time instead' % value)
+
+ else:
+ if isinstance(value, wx.DateTime):
+ hour, minute, second = value.GetHour(), value.GetMinute(), value.GetSecond()
+ elif isinstance(value, wx.TimeSpan):
+ totalseconds = value.GetSeconds()
+ hour = totalseconds / 3600
+ minute = totalseconds / 60 - (hour * 60)
+ second = totalseconds - ((hour * 3600) + (minute * 60))
+
+ elif accept_mx and isinstance(value, DateTime.DateTimeType):
+ hour, minute, second = value.hour, value.minute, value.second
+ elif accept_mx and isinstance(value, DateTime.DateTimeDeltaType):
+ hour, minute, second = value.hour, value.minute, value.second
+ else:
+ # Not a valid function argument
+ if accept_mx:
+ error = 'GetWxDateTime requires wxDateTime, mxDateTime or parsable time string, passed %s'% repr(value)
+ else:
+ error = 'GetWxDateTime requires wxDateTime or parsable time string, passed %s'% repr(value)
+## dbg(indent=0, suspend=0)
+ raise ValueError(error)
+
+ wxdt = wx.DateTimeFromDMY(1, 0, 1970)
+ wxdt.SetHour(hour)
+ wxdt.SetMinute(minute)
+ wxdt.SetSecond(second)
+
+## dbg('wxdt:', wxdt, indent=0, suspend=0)
+ return wxdt
+
+
+ def SetMxDateTime(self, mxdt):
+ """
+ Because SetValue can take an mx.DateTime, (if DateTime is importable),
+ this is now just an alias.
+ """
+ self.SetValue(value)
+
+
+ def GetMxDateTime(self, value=None):
+ """
+ Returns the value of the control as an mx.DateTime, with the date
+ portion set to January 1, 1970.
+ """
+ if value is None:
+ t = self.GetValue(as_mxDateTime=True)
+ else:
+ # Convert string 1st to wxDateTime, then use components, since
+ # mx' DateTime.Parser.TimeFromString() doesn't handle AM/PM:
+ wxdt = self.GetWxDateTime(value)
+ hour, minute, second = wxdt.GetHour(), wxdt.GetMinute(), wxdt.GetSecond()
+ t = DateTime.DateTime(1970,1,1) + DateTimeDelta(0, hour, minute, second)
+ return t
+
+
+ def SetMin(self, min=None):
+ """
+ Sets the minimum value of the control. If a value of None
+ is provided, then the control will have no explicit minimum value.
+ If the value specified is greater than the current maximum value,
+ then the function returns 0 and the minimum will not change from
+ its current setting. On success, the function returns 1.
+
+ If successful and the current value is lower than the new lower
+ bound, if the control is limited, the value will be automatically
+ adjusted to the new minimum value; if not limited, the value in the
+ control will be colored as invalid.
+ """
+## dbg('TimeCtrl::SetMin(%s)'% repr(min), indent=1)
+ if min is not None:
+ try:
+ min = self.GetWxDateTime(min)
+ self.__min = self._toGUI(min)
+ except:
+## dbg('exception occurred', indent=0)
+ return False
+ else:
+ self.__min = min
+
+ if self.IsLimited() and not self.IsInBounds():
+ self.SetLimited(self.__limited) # force limited value:
+ else:
+ self._CheckValid()
+ ret = True
+## dbg('ret:', ret, indent=0)
+ return ret
+
+
+ def GetMin(self, as_string = False):
+ """
+ Gets the minimum value of the control.
+ If None, it will return None. Otherwise it will return
+ the current minimum bound on the control, as a wxDateTime
+ by default, or as a string if as_string argument is True.
+ """
+## dbg(suspend=1)
+## dbg('TimeCtrl::GetMin, as_string?', as_string, indent=1)
+ if self.__min is None:
+## dbg('(min == None)')
+ ret = self.__min
+ elif as_string:
+ ret = self.__min
+## dbg('ret:', ret)
+ else:
+ try:
+ ret = self.GetWxDateTime(self.__min)
+ except:
+## dbg(suspend=0)
+## dbg('exception occurred', indent=0)
+ raise
+## dbg('ret:', repr(ret))
+## dbg(indent=0, suspend=0)
+ return ret
+
+
+ def SetMax(self, max=None):
+ """
+ Sets the maximum value of the control. If a value of None
+ is provided, then the control will have no explicit maximum value.
+ If the value specified is less than the current minimum value, then
+ the function returns False and the maximum will not change from its
+ current setting. On success, the function returns True.
+
+ If successful and the current value is greater than the new upper
+ bound, if the control is limited the value will be automatically
+ adjusted to this maximum value; if not limited, the value in the
+ control will be colored as invalid.
+ """
+## dbg('TimeCtrl::SetMax(%s)' % repr(max), indent=1)
+ if max is not None:
+ try:
+ max = self.GetWxDateTime(max)
+ self.__max = self._toGUI(max)
+ except:
+## dbg('exception occurred', indent=0)
+ return False
+ else:
+ self.__max = max
+## dbg('max:', repr(self.__max))
+ if self.IsLimited() and not self.IsInBounds():
+ self.SetLimited(self.__limited) # force limited value:
+ else:
+ self._CheckValid()
+ ret = True
+## dbg('ret:', ret, indent=0)
+ return ret
+
+
+ def GetMax(self, as_string = False):
+ """
+ Gets the minimum value of the control.
+ If None, it will return None. Otherwise it will return
+ the current minimum bound on the control, as a wxDateTime
+ by default, or as a string if as_string argument is True.
+ """
+## dbg(suspend=1)
+## dbg('TimeCtrl::GetMin, as_string?', as_string, indent=1)
+ if self.__max is None:
+## dbg('(max == None)')
+ ret = self.__max
+ elif as_string:
+ ret = self.__max
+## dbg('ret:', ret)
+ else:
+ try:
+ ret = self.GetWxDateTime(self.__max)
+ except:
+## dbg(suspend=0)
+## dbg('exception occurred', indent=0)
+ raise
+## dbg('ret:', repr(ret))
+## dbg(indent=0, suspend=0)
+ return ret
+
+
+ def SetBounds(self, min=None, max=None):
+ """
+ This function is a convenience function for setting the min and max
+ values at the same time. The function only applies the maximum bound
+ if setting the minimum bound is successful, and returns True
+ only if both operations succeed.
+ **NOTE:** leaving out an argument will remove the corresponding bound.
+ """
+ ret = self.SetMin(min)
+ return ret and self.SetMax(max)
+
+
+ def GetBounds(self, as_string = False):
+ """
+ This function returns a two-tuple (min,max), indicating the
+ current bounds of the control. Each value can be None if
+ that bound is not set.
+ """
+ return (self.GetMin(as_string), self.GetMax(as_string))
+
+
+ def SetLimited(self, limited):
+ """
+ If called with a value of True, this function will cause the control
+ to limit the value to fall within the bounds currently specified.
+ If the control's value currently exceeds the bounds, it will then
+ be limited accordingly.
+
+ If called with a value of 0, this function will disable value
+ limiting, but coloring of out-of-bounds values will still take
+ place if bounds have been set for the control.
+ """
+## dbg('TimeCtrl::SetLimited(%d)' % limited, indent=1)
+ self.__limited = limited
+
+ if not limited:
+ self.SetMaskParameters(validRequired = False)
+ self._CheckValid()
+## dbg(indent=0)
+ return
+
+## dbg('requiring valid value')
+ self.SetMaskParameters(validRequired = True)
+
+ min = self.GetMin()
+ max = self.GetMax()
+ if min is None or max is None:
+## dbg('both bounds not set; no further action taken')
+ return # can't limit without 2 bounds
+
+ elif not self.IsInBounds():
+ # set value to the nearest bound:
+ try:
+ value = self.GetWxDateTime()
+ except:
+## dbg('exception occurred', indent=0)
+ raise
+
+ if min <= max: # valid range doesn't span midnight
+## dbg('min <= max')
+ # which makes the "nearest bound" computation trickier...
+
+ # determine how long the "invalid" pie wedge is, and cut
+ # this interval in half for comparison purposes:
+
+ # Note: relies on min and max and value date portions
+ # always being the same.
+ interval = (min + wx.TimeSpan(24, 0, 0, 0)) - max
+
+ half_interval = wx.TimeSpan(
+ 0, # hours
+ 0, # minutes
+ interval.GetSeconds() / 2, # seconds
+ 0) # msec
+
+ if value < min: # min is on next day, so use value on
+ # "next day" for "nearest" interval calculation:
+ cmp_value = value + wx.TimeSpan(24, 0, 0, 0)
+ else: # "before midnight; ok
+ cmp_value = value
+
+ if (cmp_value - max) > half_interval:
+## dbg('forcing value to min (%s)' % min.FormatTime())
+ self.SetValue(min)
+ else:
+## dbg('forcing value to max (%s)' % max.FormatTime())
+ self.SetValue(max)
+ else:
+## dbg('max < min')
+ # therefore max < value < min guaranteed to be true,
+ # so "nearest bound" calculation is much easier:
+ if (value - max) >= (min - value):
+ # current value closer to min; pick that edge of pie wedge
+## dbg('forcing value to min (%s)' % min.FormatTime())
+ self.SetValue(min)
+ else:
+## dbg('forcing value to max (%s)' % max.FormatTime())
+ self.SetValue(max)
+
+## dbg(indent=0)
+
+
+
+ def IsLimited(self):
+ """
+ Returns True if the control is currently limiting the
+ value to fall within any current bounds. *Note:* can
+ be set even if there are no current bounds.
+ """
+ return self.__limited
+
+
+ def IsInBounds(self, value=None):
+ """
+ Returns True if no value is specified and the current value
+ of the control falls within the current bounds. As the clock
+ is a "circle", both minimum and maximum bounds must be set for
+ a value to ever be considered "out of bounds". This function can
+ also be called with a value to see if that value would fall within
+ the current bounds of the given control.
+ """
+ if value is not None:
+ try:
+ value = self.GetWxDateTime(value) # try to regularize passed value
+ except ValueError:
+## dbg('ValueError getting wxDateTime for %s' % repr(value), indent=0)
+ raise
+
+## dbg('TimeCtrl::IsInBounds(%s)' % repr(value), indent=1)
+ if self.__min is None or self.__max is None:
+## dbg(indent=0)
+ return True
+
+ elif value is None:
+ try:
+ value = self.GetWxDateTime()
+ except:
+## dbg('exception occurred', indent=0)
+ raise
+
+## dbg('value:', value.FormatTime())
+
+ # Get wxDateTime representations of bounds:
+ min = self.GetMin()
+ max = self.GetMax()
+
+ midnight = wx.DateTimeFromDMY(1, 0, 1970)
+ if min <= max: # they don't span midnight
+ ret = min <= value <= max
+
+ else:
+ # have to break into 2 tests; to be in bounds
+ # either "min" <= value (<= midnight of *next day*)
+ # or midnight <= value <= "max"
+ ret = min <= value or (midnight <= value <= max)
+## dbg('in bounds?', ret, indent=0)
+ return ret
+
+
+ def IsValid( self, value ):
+ """
+ Can be used to determine if a given value would be a legal and
+ in-bounds value for the control.
+ """
+ try:
+ self.__validateValue(value)
+ return True
+ except ValueError:
+ return False
+
+ def SetFormat(self, format):
+ self.SetParameters(format=format)
+
+ def GetFormat(self):
+ if self.__displaySeconds:
+ if self.__fmt24hr: return '24HHMMSS'
+ else: return 'HHMMSS'
+ else:
+ if self.__fmt24hr: return '24HHMM'
+ else: return 'HHMM'
+
+#-------------------------------------------------------------------------------------------------------------
+# these are private functions and overrides:
+
+
+ def __OnTextChange(self, event=None):
+## dbg('TimeCtrl::OnTextChange', indent=1)
+
+ # Allow Maskedtext base control to color as appropriate,
+ # and Skip the EVT_TEXT event (if appropriate.)
+ ##! WS: For some inexplicable reason, every wxTextCtrl.SetValue()
+ ## call is generating two (2) EVT_TEXT events. (!)
+ ## The the only mechanism I can find to mask this problem is to
+ ## keep track of last value seen, and declare a valid EVT_TEXT
+ ## event iff the value has actually changed. The masked edit
+ ## OnTextChange routine does this, and returns True on a valid event,
+ ## False otherwise.
+ if not BaseMaskedTextCtrl._OnTextChange(self, event):
+ return
+
+## dbg('firing TimeUpdatedEvent...')
+ evt = TimeUpdatedEvent(self.GetId(), self.GetValue())
+ evt.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(evt)
+## dbg(indent=0)
+
+
+ def SetInsertionPoint(self, pos):
+ """
+ This override records the specified position and associated cell before
+ calling base class' function. This is necessary to handle the optional
+ spin button, because the insertion point is lost when the focus shifts
+ to the spin button.
+ """
+## dbg('TimeCtrl::SetInsertionPoint', pos, indent=1)
+ BaseMaskedTextCtrl.SetInsertionPoint(self, pos) # (causes EVT_TEXT event to fire)
+ self.__posCurrent = self.GetInsertionPoint()
+## dbg(indent=0)
+
+
+ def SetSelection(self, sel_start, sel_to):
+## dbg('TimeCtrl::SetSelection', sel_start, sel_to, indent=1)
+
+ # Adjust selection range to legal extent if not already
+ if sel_start < 0:
+ sel_start = 0
+
+ if self.__posCurrent != sel_start: # force selection and insertion point to match
+ self.SetInsertionPoint(sel_start)
+ cell_start, cell_end = self._FindField(sel_start)._extent
+ if not cell_start <= sel_to <= cell_end:
+ sel_to = cell_end
+
+ self.__bSelection = sel_start != sel_to
+ BaseMaskedTextCtrl.SetSelection(self, sel_start, sel_to)
+## dbg(indent=0)
+
+
+ def __OnSpin(self, key):
+ """
+ This is the function that gets called in response to up/down arrow or
+ bound spin button events.
+ """
+ self.__IncrementValue(key, self.__posCurrent) # changes the value
+
+ # Ensure adjusted control regains focus and has adjusted portion
+ # selected:
+ self.SetFocus()
+ start, end = self._FindField(self.__posCurrent)._extent
+ self.SetInsertionPoint(start)
+ self.SetSelection(start, end)
+## dbg('current position:', self.__posCurrent)
+
+
+ def __OnSpinUp(self, event):
+ """
+ Event handler for any bound spin button on EVT_SPIN_UP;
+ causes control to behave as if up arrow was pressed.
+ """
+## dbg('TimeCtrl::OnSpinUp', indent=1)
+ self.__OnSpin(wx.WXK_UP)
+ keep_processing = False
+## dbg(indent=0)
+ return keep_processing
+
+
+ def __OnSpinDown(self, event):
+ """
+ Event handler for any bound spin button on EVT_SPIN_DOWN;
+ causes control to behave as if down arrow was pressed.
+ """
+## dbg('TimeCtrl::OnSpinDown', indent=1)
+ self.__OnSpin(wx.WXK_DOWN)
+ keep_processing = False
+## dbg(indent=0)
+ return keep_processing
+
+
+ def __OnChar(self, event):
+ """
+ Handler to explicitly look for ':' keyevents, and if found,
+ clear the m_shiftDown field, so it will behave as forward tab.
+ It then calls the base control's _OnChar routine with the modified
+ event instance.
+ """
+## dbg('TimeCtrl::OnChar', indent=1)
+ keycode = event.GetKeyCode()
+## dbg('keycode:', keycode)
+ if keycode == ord(':'):
+## dbg('colon seen! removing shift attribute')
+ event.m_shiftDown = False
+ BaseMaskedTextCtrl._OnChar(self, event ) ## handle each keypress
+## dbg(indent=0)
+
+
+ def __OnSetToNow(self, event):
+ """
+ This is the key handler for '!' and 'c'; this allows the user to
+ quickly set the value of the control to the current time.
+ """
+ self.SetValue(wx.DateTime_Now().FormatTime())
+ keep_processing = False
+ return keep_processing
+
+
+ def __LimitSelection(self, event):
+ """
+ Event handler for motion events; this handler
+ changes limits the selection to the new cell boundaries.
+ """
+## dbg('TimeCtrl::LimitSelection', indent=1)
+ pos = self.GetInsertionPoint()
+ self.__posCurrent = pos
+ sel_start, sel_to = self.GetSelection()
+ selection = sel_start != sel_to
+ if selection:
+ # only allow selection to end of current cell:
+ start, end = self._FindField(sel_start)._extent
+ if sel_to < pos: sel_to = start
+ elif sel_to > pos: sel_to = end
+
+## dbg('new pos =', self.__posCurrent, 'select to ', sel_to)
+ self.SetInsertionPoint(self.__posCurrent)
+ self.SetSelection(self.__posCurrent, sel_to)
+ if event: event.Skip()
+## dbg(indent=0)
+
+
+ def __IncrementValue(self, key, pos):
+## dbg('TimeCtrl::IncrementValue', key, pos, indent=1)
+ text = self.GetValue()
+ field = self._FindField(pos)
+## dbg('field: ', field._index)
+ start, end = field._extent
+ slice = text[start:end]
+ if key == wx.WXK_UP: increment = 1
+ else: increment = -1
+
+ if slice in ('A', 'P'):
+ if slice == 'A': newslice = 'P'
+ elif slice == 'P': newslice = 'A'
+ newvalue = text[:start] + newslice + text[end:]
+
+ elif field._index == 0:
+ # adjusting this field is trickier, as its value can affect the
+ # am/pm setting. So, we use wxDateTime to generate a new value for us:
+ # (Use a fixed date not subject to DST variations:)
+ converter = wx.DateTimeFromDMY(1, 0, 1970)
+## dbg('text: "%s"' % text)
+ converter.ParseTime(text.strip())
+ currenthour = converter.GetHour()
+## dbg('current hour:', currenthour)
+ newhour = (currenthour + increment) % 24
+## dbg('newhour:', newhour)
+ converter.SetHour(newhour)
+## dbg('converter.GetHour():', converter.GetHour())
+ newvalue = converter # take advantage of auto-conversion for am/pm in .SetValue()
+
+ else: # minute or second field; handled the same way:
+ newslice = "%02d" % ((int(slice) + increment) % 60)
+ newvalue = text[:start] + newslice + text[end:]
+
+ try:
+ self.SetValue(newvalue)
+
+ except ValueError: # must not be in bounds:
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+## dbg(indent=0)
+
+
+ def _toGUI( self, wxdt ):
+ """
+ This function takes a wxdt as an unambiguous representation of a time, and
+ converts it to a string appropriate for the format of the control.
+ """
+ if self.__fmt24hr:
+ if self.__displaySeconds: strval = wxdt.Format('%H:%M:%S')
+ else: strval = wxdt.Format('%H:%M')
+ else:
+ if self.__displaySeconds: strval = wxdt.Format('%I:%M:%S %p')
+ else: strval = wxdt.Format('%I:%M %p')
+
+ return strval
+
+
+ def __validateValue( self, value ):
+ """
+ This function converts the value to a wxDateTime if not already one,
+ does bounds checking and raises ValueError if argument is
+ not a valid value for the control as currently specified.
+ It is used by both the SetValue() and the IsValid() methods.
+ """
+## dbg('TimeCtrl::__validateValue(%s)' % repr(value), indent=1)
+ if not value:
+## dbg(indent=0)
+ raise ValueError('%s not a valid time value' % repr(value))
+
+ valid = True # assume true
+ try:
+ value = self.GetWxDateTime(value) # regularize form; can generate ValueError if problem doing so
+ except:
+## dbg('exception occurred', indent=0)
+ raise
+
+ if self.IsLimited() and not self.IsInBounds(value):
+## dbg(indent=0)
+ raise ValueError (
+ 'value %s is not within the bounds of the control' % str(value) )
+## dbg(indent=0)
+ return value
+
+#----------------------------------------------------------------------------
+# Test jig for TimeCtrl:
+
+if __name__ == '__main__':
+ import traceback
+
+ class TestPanel(wx.Panel):
+ def __init__(self, parent, id,
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ fmt24hr = 0, test_mx = 0,
+ style = wx.TAB_TRAVERSAL ):
+
+ wx.Panel.__init__(self, parent, id, pos, size, style)
+
+ self.test_mx = test_mx
+
+ self.tc = TimeCtrl(self, 10, fmt24hr = fmt24hr)
+ sb = wx.SpinButton( self, 20, wx.DefaultPosition, (-1,20), 0 )
+ self.tc.BindSpinButton(sb)
+
+ sizer = wx.BoxSizer( wx.HORIZONTAL )
+ sizer.Add( self.tc, 0, wx.ALIGN_CENTRE|wx.LEFT|wx.TOP|wx.BOTTOM, 5 )
+ sizer.Add( sb, 0, wx.ALIGN_CENTRE|wx.RIGHT|wx.TOP|wx.BOTTOM, 5 )
+
+ self.SetAutoLayout( True )
+ self.SetSizer( sizer )
+ sizer.Fit( self )
+ sizer.SetSizeHints( self )
+
+ self.Bind(EVT_TIMEUPDATE, self.OnTimeChange, self.tc)
+
+ def OnTimeChange(self, event):
+## dbg('OnTimeChange: value = ', event.GetValue())
+ wxdt = self.tc.GetWxDateTime()
+## dbg('wxdt =', wxdt.GetHour(), wxdt.GetMinute(), wxdt.GetSecond())
+ if self.test_mx:
+ mxdt = self.tc.GetMxDateTime()
+## dbg('mxdt =', mxdt.hour, mxdt.minute, mxdt.second)
+
+
+ class MyApp(wx.App):
+ def OnInit(self):
+ import sys
+ fmt24hr = '24' in sys.argv
+ test_mx = 'mx' in sys.argv
+ try:
+ frame = wx.Frame(None, -1, "TimeCtrl Test", (20,20), (100,100) )
+ panel = TestPanel(frame, -1, (-1,-1), fmt24hr=fmt24hr, test_mx = test_mx)
+ frame.Show(True)
+ except:
+ traceback.print_exc()
+ return False
+ return True
+
+ try:
+ app = MyApp(0)
+ app.MainLoop()
+ except:
+ traceback.print_exc()
+__i=0
+
+## CHANGELOG:
+## ====================
+## Version 1.3
+## 1. Converted docstrings to reST format, added doc for ePyDoc.
+## 2. Renamed helper functions, vars etc. not intended to be visible in public
+## interface to code.
+##
+## Version 1.2
+## 1. Changed parameter name display_seconds to displaySeconds, to follow
+## other masked edit conventions.
+## 2. Added format parameter, to remove need to use both fmt24hr and displaySeconds.
+## 3. Changed inheritance to use BaseMaskedTextCtrl, to remove exposure of
+## nonsensical parameter methods from the control, so it will work
+## properly with Boa.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/__init__.py
new file mode 100644
index 0000000..5586cba
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/__init__.py
@@ -0,0 +1,18 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.mixins
+# Purpose: A package for helpful wxPython mix-in classes
+#
+# Author: Robin Dunn
+#
+# Created: 15-May-2001
+# RCS-ID: $Id$
+# Copyright: (c) 2001 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/grid.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/grid.py
new file mode 100644
index 0000000..586d24e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/grid.py
@@ -0,0 +1,48 @@
+#----------------------------------------------------------------------------
+# Name: wx.lib.mixins.grid
+# Purpose: Helpful mix-in classes for wx.Grid
+#
+# Author: Robin Dunn
+#
+# Created: 5-June-2001
+# RCS-ID: $Id$
+# Copyright: (c) 2001 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o Untested
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxGridAutoEditMixin -> GridAutoEditMixin
+#
+
+import wx
+import wx.grid
+
+#----------------------------------------------------------------------------
+
+
+class GridAutoEditMixin:
+ """A mix-in class that automatically enables the grid edit control when
+ a cell is selected.
+
+ If your class hooks EVT_GRID_SELECT_CELL be sure to call event.Skip so
+ this handler will be called too.
+ """
+
+ def __init__(self):
+ self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.__OnSelectCell)
+
+
+ def __DoEnableEdit(self):
+ if self.CanEnableCellControl():
+ self.EnableCellEditControl()
+
+
+ def __OnSelectCell(self, evt):
+ wx.CallAfter(self.__DoEnableEdit)
+ evt.Skip()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/gridlabelrenderer.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/gridlabelrenderer.py
new file mode 100644
index 0000000..e7df71b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/gridlabelrenderer.py
@@ -0,0 +1,248 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.mixins.gridlabelrenderer
+# Purpose: A Grid mixin that enables renderers to be plugged in
+# for drawing the row and col labels, similar to how the
+# cell renderers work.
+#
+# Author: Robin Dunn
+#
+# Created: 20-Mar-2009
+# RCS-ID: $Id$
+# Copyright: (c) 2009 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""
+A Grid mixin that enables renderers to be plugged in for drawing the
+row and col labels, similar to how the cell renderers work.
+"""
+
+import wx
+
+
+class GridWithLabelRenderersMixin(object):
+ """
+ This class can be mixed with wx.grid.Grid to add the ability to plugin
+ label renderer objects for the row, column and corner labels, similar to
+ how the cell renderers work in the main Grid class.
+ """
+ def __init__(self):
+ self.GetGridRowLabelWindow().Bind(wx.EVT_PAINT, self._onPaintRowLabels)
+ self.GetGridColLabelWindow().Bind(wx.EVT_PAINT, self._onPaintColLabels)
+ self.GetGridCornerLabelWindow().Bind(wx.EVT_PAINT, self._onPaintCornerLabel)
+
+ self._rowRenderers = dict()
+ self._colRenderers = dict()
+ self._cornderRenderer = None
+ self._defRowRenderer = None
+ self._defColRenderer = None
+
+
+ def SetRowLabelRenderer(self, row, renderer):
+ """
+ Register a renderer to be used for drawing the label for the
+ given row.
+ """
+ if renderer is None:
+ if row in self._rowRenderers:
+ del self._rowRenderers[row]
+ else:
+ self._rowRenderers[row] = renderer
+
+
+ def SetDefaultRowLabelRenderer(self, renderer):
+ """
+ Set the row label renderer that should be used for any row
+ that does not have an explicitly set renderer. Defaults to
+ an instance of `GridDefaultRowLabelRenderer`.
+ """
+ self._defRowRenderer = renderer
+
+
+ def SetColLabelRenderer(self, col, renderer):
+ """
+ Register a renderer to be used for drawing the label for the
+ given column.
+ """
+ if renderer is None:
+ if col in self._colRenderers:
+ del self._colRenderers[col]
+ else:
+ self._colRenderers[col] = renderer
+
+
+ def SetDefaultColLabelRenderer(self, renderer):
+ """
+ Set the column label renderer that should be used for any
+ column that does not have an explicitly set renderer.
+ Defaults to an instance of `GridDefaultColLabelRenderer`.
+ """
+ self._defColRenderer = renderer
+
+
+
+ def SetCornerLabelRenderer(self, renderer):
+ """
+ Sets the renderer that should be used for drawing the area in
+ the upper left corner of the Grid, between the row labels and
+ the column labels. Defaults to an instance of
+ `GridDefaultCornerLabelRenderer`
+ """
+ self._cornderRenderer = renderer
+
+
+ #----------------------------------------------------------------
+
+ def _onPaintRowLabels(self, evt):
+ window = evt.GetEventObject()
+ dc = wx.PaintDC(window)
+
+ rows = self.CalcRowLabelsExposed(window.GetUpdateRegion())
+ if rows == [-1]:
+ return
+
+ x, y = self.CalcUnscrolledPosition((0,0))
+ pt = dc.GetDeviceOrigin()
+ dc.SetDeviceOrigin(pt.x, pt.y-y)
+ for row in rows:
+ top, bottom = self._getRowTopBottom(row)
+ rect = wx.Rect()
+ rect.top = top
+ rect.bottom = bottom
+ rect.x = 0
+ rect.width = self.GetRowLabelSize()
+
+ renderer = self._rowRenderers.get(row, None) or \
+ self._defRowRenderer or GridDefaultRowLabelRenderer()
+ renderer.Draw(self, dc, rect, row)
+
+
+ def _onPaintColLabels(self, evt):
+ window = evt.GetEventObject()
+ dc = wx.PaintDC(window)
+
+ cols = self.CalcColLabelsExposed(window.GetUpdateRegion())
+ if cols == [-1]:
+ return
+
+ x, y = self.CalcUnscrolledPosition((0,0))
+ pt = dc.GetDeviceOrigin()
+ dc.SetDeviceOrigin(pt.x-x, pt.y)
+ for col in cols:
+ left, right = self._getColLeftRight(col)
+ rect = wx.Rect()
+ rect.left = left
+ rect.right = right
+ rect.y = 0
+ rect.height = self.GetColLabelSize()
+
+ renderer = self._colRenderers.get(col, None) or \
+ self._defColRenderer or GridDefaultColLabelRenderer()
+ renderer.Draw(self, dc, rect, col)
+
+
+ def _onPaintCornerLabel(self, evt):
+ window = evt.GetEventObject()
+ dc = wx.PaintDC(window)
+ w, h = window.GetSize()
+ rect = wx.Rect(0, 0, w, h)
+
+ renderer = self._cornderRenderer or GridDefaultCornerLabelRenderer()
+ renderer.Draw(self, dc, rect, -1)
+
+
+
+ # NOTE: These helpers or something like them should probably be publicly
+ # available in the C++ wxGrid class, but they are currently protected so
+ # for now we will have to calculate them ourselves.
+ def _getColLeftRight(self, col):
+ c = 0
+ left = 0
+ while c < col:
+ left += self.GetColSize(c)
+ c += 1
+ right = left + self.GetColSize(col)
+ return left, right
+
+ def _getRowTopBottom(self, row):
+ r = 0
+ top = 0
+ while r < row:
+ top += self.GetRowSize(r)
+ r += 1
+ bottom = top + self.GetRowSize(row) - 1
+ return top, bottom
+
+
+
+
+class GridLabelRenderer(object):
+ """
+ Base class for row, col or corner label renderers.
+ """
+
+ def Draw(self, grid, dc, rect, row_or_col):
+ """
+ Override this method in derived classes to do the actual
+ drawing of the label.
+ """
+ raise NotImplementedError
+
+
+ # These two can be used to duplicate the default wxGrid label drawing
+ def DrawBorder(self, grid, dc, rect):
+ """
+ Draw a standard border around the label, to give a simple 3D
+ effect like the stock wx.grid.Grid labels do.
+ """
+ top = rect.top
+ bottom = rect.bottom
+ left = rect.left
+ right = rect.right
+ dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DSHADOW)))
+ dc.DrawLine(right, top, right, bottom)
+ dc.DrawLine(left, top, left, bottom)
+ dc.DrawLine(left, bottom, right, bottom)
+ dc.SetPen(wx.WHITE_PEN)
+ dc.DrawLine(left+1, top, left+1, bottom)
+ dc.DrawLine(left+1, top, right, top)
+
+
+ def DrawText(self, grid, dc, rect, text, hAlign, vAlign):
+ """
+ Draw the label's text in the rectangle, using the alignment
+ flags, and the grid's specified label font and color.
+ """
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ dc.SetTextForeground(grid.GetLabelTextColour())
+ dc.SetFont(grid.GetLabelFont())
+ rect = wx.Rect(*rect)
+ rect.Deflate(2,2)
+ grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign)
+
+
+
+# These classes draw approximately the same things that the built-in
+# label windows do in C++, but are adapted to fit into this label
+# renderer scheme.
+
+class GridDefaultRowLabelRenderer(GridLabelRenderer):
+ def Draw(self, grid, dc, rect, row):
+ hAlign, vAlign = grid.GetRowLabelAlignment()
+ text = grid.GetRowLabelValue(row)
+ self.DrawBorder(grid, dc, rect)
+ self.DrawText(grid, dc, rect, text, hAlign, vAlign)
+
+class GridDefaultColLabelRenderer(GridLabelRenderer):
+ def Draw(self, grid, dc, rect, col):
+ hAlign, vAlign = grid.GetColLabelAlignment()
+ text = grid.GetColLabelValue(col)
+ self.DrawBorder(grid, dc, rect)
+ self.DrawText(grid, dc, rect, text, hAlign, vAlign)
+
+class GridDefaultCornerLabelRenderer(GridLabelRenderer):
+ def Draw(self, grid, dc, rect, row_or_col):
+ self.DrawBorder(grid, dc, rect)
+
+
+#---------------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/imagelist.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/imagelist.py
new file mode 100644
index 0000000..d599d7a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/imagelist.py
@@ -0,0 +1,78 @@
+#----------------------------------------------------------------------------
+# Name: wx.lib.mixins.imagelist
+# Purpose: Helpful mix-in classes for using a wxImageList
+#
+# Author: Robin Dunn
+#
+# Created: 15-May-2001
+# RCS-ID: $Id$
+# Copyright: (c) 2001 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o Untested.
+#
+
+import wx
+
+#----------------------------------------------------------------------------
+
+class MagicImageList:
+ '''
+ Mix-in to provide "magic" growing image lists
+ By Mike Fletcher
+ '''
+
+ ### LAZYTREE and LISTCONTROL Methods
+ DEFAULTICONSIZE = 16
+
+ def SetupIcons(self, images=(), size=None):
+ self.__size = size or self.DEFAULTICONSIZE
+ self.__magicImageList = wx.ImageList (self.__size,self.__size)
+ self.__magicImageListMapping = {}
+ self.SetImageList (
+ self.__magicImageList, {
+ 16:wx.IMAGE_LIST_SMALL,
+ 32:wx.IMAGE_LIST_NORMAL,
+ }[self.__size]
+ )
+ for image in images:
+ self.AddIcon (image)
+
+ def GetIcons (self, node):
+ '''Get icon indexes for a given node, or None if no associated icon'''
+ icon = self.GetIcon( node )
+ if icon:
+ index = self.AddIcon (icon)
+ return index, index
+ return None
+
+
+ ### Local methods...
+ def AddIcon(self, icon, mask = wx.NullBitmap):
+ '''Add an icon to the image list, or get the index if already there'''
+ index = self.__magicImageListMapping.get (id (icon))
+ if index is None:
+ if isinstance( icon, wxIconPtr ):
+ index = self.__magicImageList.AddIcon( icon )
+ elif isinstance( icon, wx.BitmapPtr ):
+ if isinstance( mask, wx.Colour ):
+ index = self.__magicImageList.AddWithColourMask( icon, mask )
+ else:
+ index = self.__magicImageList.Add( icon, mask )
+ else:
+ raise ValueError("Unexpected icon object %s, "
+ "expected wx.Icon or wx.Bitmap" % (icon))
+ self.__magicImageListMapping [id (icon)] = index
+ return index
+
+ ### Customisation point...
+ def GetIcon( self, node ):
+ '''Get the actual icon object for a node'''
+ if hasattr (node,"DIAGRAMICON"):
+ return node.DIAGRAMICON
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/inspection.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/inspection.py
new file mode 100644
index 0000000..0a5c377
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/inspection.py
@@ -0,0 +1,89 @@
+#----------------------------------------------------------------------------
+# Name: wx.lib.mixins.inspection
+# Purpose: A mix-in class that can add PyCrust-based inspection of the
+# app's widgets and sizers.
+#
+# Author: Robin Dunn
+#
+# Created: 21-Nov-2006
+# RCS-ID: $Id$
+# Copyright: (c) 2006 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+# NOTE: This class was originally based on ideas sent to the
+# wxPython-users mail list by Dan Eloff.
+
+import wx
+from wx.lib.inspection import InspectionTool
+
+
+#----------------------------------------------------------------------------
+
+class InspectionMixin(object):
+ """
+ This class is intended to be used as a mix-in with the wx.App
+ class. When used it will add the ability to popup a
+ InspectionFrame window where the widget under the mouse cursor
+ will be selected in the tree and loaded into the shell's namespace
+ as 'obj'. The default key sequence to activate the inspector is
+ Ctrl-Alt-I (or Cmd-Alt-I on Mac) but this can be changed via
+ parameters to the `Init` method, or the application can call
+ `ShowInspectionTool` from other event handlers if desired.
+
+ To use this class simply derive a class from wx.App and
+ InspectionMixin and then call the `Init` method from the app's
+ OnInit.
+ """
+ def InitInspection(self, pos=wx.DefaultPosition, size=wx.Size(850,700),
+ config=None, locals=None,
+ alt=True, cmd=True, shift=False, keyCode=ord('I')):
+ """
+ Make the event binding that will activate the InspectionFrame window.
+ """
+ self.Bind(wx.EVT_KEY_DOWN, self._OnKeyPress)
+ self._alt = alt
+ self._cmd = cmd
+ self._shift = shift
+ self._keyCode = keyCode
+ InspectionTool().Init(pos, size, config, locals, self)
+
+ def _OnKeyPress(self, evt):
+ """
+ Event handler, check for our hot-key. Normally it is
+ Ctrl-Alt-I but that can be changed by what is passed to the
+ Init method.
+ """
+ if evt.AltDown() == self._alt and \
+ evt.CmdDown() == self._cmd and \
+ evt.ShiftDown() == self._shift and \
+ evt.GetKeyCode() == self._keyCode:
+ self.ShowInspectionTool()
+ else:
+ evt.Skip()
+
+ Init = InitInspection # compatibility alias
+
+ def ShowInspectionTool(self):
+ """
+ Show the Inspection tool, creating it if neccesary, setting it
+ to display the widget under the cursor.
+ """
+ # get the current widget under the mouse
+ wnd = wx.FindWindowAtPointer()
+ InspectionTool().Show(wnd)
+
+
+#---------------------------------------------------------------------------
+
+class InspectableApp(wx.App, InspectionMixin):
+ """
+ A simple mix of wx.App and InspectionMixin that can be used stand-alone.
+ """
+
+ def OnInit(self):
+ self.InitInspection()
+ return True
+
+#---------------------------------------------------------------------------
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/listctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/listctrl.py
new file mode 100644
index 0000000..35bc075
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/listctrl.py
@@ -0,0 +1,877 @@
+#----------------------------------------------------------------------------
+# Name: wx.lib.mixins.listctrl
+# Purpose: Helpful mix-in classes for wxListCtrl
+#
+# Author: Robin Dunn
+#
+# Created: 15-May-2001
+# RCS-ID: $Id$
+# Copyright: (c) 2001 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o ListCtrlSelectionManagerMix untested.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxColumnSorterMixin -> ColumnSorterMixin
+# o wxListCtrlAutoWidthMixin -> ListCtrlAutoWidthMixin
+# ...
+# 13/10/2004 - Pim Van Heuven (pim@think-wize.com)
+# o wxTextEditMixin: Support Horizontal scrolling when TAB is pressed on long
+# ListCtrls, support for WXK_DOWN, WXK_UP, performance improvements on
+# very long ListCtrls, Support for virtual ListCtrls
+#
+# 15-Oct-2004 - Robin Dunn
+# o wxTextEditMixin: Added Shift-TAB support
+#
+# 2008-11-19 - raf <raf@raf.org>
+# o ColumnSorterMixin: Added GetSortState()
+#
+
+import locale
+import wx
+
+#----------------------------------------------------------------------------
+
+class ColumnSorterMixin:
+ """
+ A mixin class that handles sorting of a wx.ListCtrl in REPORT mode when
+ the column header is clicked on.
+
+ There are a few requirments needed in order for this to work genericly:
+
+ 1. The combined class must have a GetListCtrl method that
+ returns the wx.ListCtrl to be sorted, and the list control
+ must exist at the time the wx.ColumnSorterMixin.__init__
+ method is called because it uses GetListCtrl.
+
+ 2. Items in the list control must have a unique data value set
+ with list.SetItemData.
+
+ 3. The combined class must have an attribute named itemDataMap
+ that is a dictionary mapping the data values to a sequence of
+ objects representing the values in each column. These values
+ are compared in the column sorter to determine sort order.
+
+ Interesting methods to override are GetColumnSorter,
+ GetSecondarySortValues, and GetSortImages. See below for details.
+ """
+
+ def __init__(self, numColumns):
+ self.SetColumnCount(numColumns)
+ list = self.GetListCtrl()
+ if not list:
+ raise ValueError, "No wx.ListCtrl available"
+ list.Bind(wx.EVT_LIST_COL_CLICK, self.__OnColClick, list)
+
+
+ def SetColumnCount(self, newNumColumns):
+ self._colSortFlag = [0] * newNumColumns
+ self._col = -1
+
+
+ def SortListItems(self, col=-1, ascending=1):
+ """Sort the list on demand. Can also be used to set the sort column and order."""
+ oldCol = self._col
+ if col != -1:
+ self._col = col
+ self._colSortFlag[col] = ascending
+ self.GetListCtrl().SortItems(self.GetColumnSorter())
+ self.__updateImages(oldCol)
+
+
+ def GetColumnWidths(self):
+ """
+ Returns a list of column widths. Can be used to help restore the current
+ view later.
+ """
+ list = self.GetListCtrl()
+ rv = []
+ for x in range(len(self._colSortFlag)):
+ rv.append(list.GetColumnWidth(x))
+ return rv
+
+
+ def GetSortImages(self):
+ """
+ Returns a tuple of image list indexesthe indexes in the image list for an image to be put on the column
+ header when sorting in descending order.
+ """
+ return (-1, -1) # (decending, ascending) image IDs
+
+
+ def GetColumnSorter(self):
+ """Returns a callable object to be used for comparing column values when sorting."""
+ return self.__ColumnSorter
+
+
+ def GetSecondarySortValues(self, col, key1, key2):
+ """Returns a tuple of 2 values to use for secondary sort values when the
+ items in the selected column match equal. The default just returns the
+ item data values."""
+ return (key1, key2)
+
+
+ def __OnColClick(self, evt):
+ oldCol = self._col
+ self._col = col = evt.GetColumn()
+ self._colSortFlag[col] = int(not self._colSortFlag[col])
+ self.GetListCtrl().SortItems(self.GetColumnSorter())
+ if wx.Platform != "__WXMAC__" or wx.SystemOptions.GetOptionInt("mac.listctrl.always_use_generic") == 1:
+ self.__updateImages(oldCol)
+ evt.Skip()
+ self.OnSortOrderChanged()
+
+
+ def OnSortOrderChanged(self):
+ """
+ Callback called after sort order has changed (whenever user
+ clicked column header).
+ """
+ pass
+
+
+ def GetSortState(self):
+ """
+ Return a tuple containing the index of the column that was last sorted
+ and the sort direction of that column.
+ Usage:
+ col, ascending = self.GetSortState()
+ # Make changes to list items... then resort
+ self.SortListItems(col, ascending)
+ """
+ return (self._col, self._colSortFlag[self._col])
+
+
+ def __ColumnSorter(self, key1, key2):
+ col = self._col
+ ascending = self._colSortFlag[col]
+ item1 = self.itemDataMap[key1][col]
+ item2 = self.itemDataMap[key2][col]
+
+ #--- Internationalization of string sorting with locale module
+ if type(item1) == unicode and type(item2) == unicode:
+ cmpVal = locale.strcoll(item1, item2)
+ elif type(item1) == str or type(item2) == str:
+ cmpVal = locale.strcoll(str(item1), str(item2))
+ else:
+ cmpVal = cmp(item1, item2)
+ #---
+
+ # If the items are equal then pick something else to make the sort value unique
+ if cmpVal == 0:
+ cmpVal = apply(cmp, self.GetSecondarySortValues(col, key1, key2))
+
+ if ascending:
+ return cmpVal
+ else:
+ return -cmpVal
+
+
+ def __updateImages(self, oldCol):
+ sortImages = self.GetSortImages()
+ if self._col != -1 and sortImages[0] != -1:
+ img = sortImages[self._colSortFlag[self._col]]
+ list = self.GetListCtrl()
+ if oldCol != -1:
+ list.ClearColumnImage(oldCol)
+ list.SetColumnImage(self._col, img)
+
+
+#----------------------------------------------------------------------------
+#----------------------------------------------------------------------------
+
+class ListCtrlAutoWidthMixin:
+ """ A mix-in class that automatically resizes the last column to take up
+ the remaining width of the wx.ListCtrl.
+
+ This causes the wx.ListCtrl to automatically take up the full width of
+ the list, without either a horizontal scroll bar (unless absolutely
+ necessary) or empty space to the right of the last column.
+
+ NOTE: This only works for report-style lists.
+
+ WARNING: If you override the EVT_SIZE event in your wx.ListCtrl, make
+ sure you call event.Skip() to ensure that the mixin's
+ _OnResize method is called.
+
+ This mix-in class was written by Erik Westra <ewestra@wave.co.nz>
+ """
+ def __init__(self):
+ """ Standard initialiser.
+ """
+ self._resizeColMinWidth = None
+ self._resizeColStyle = "LAST"
+ self._resizeCol = 0
+ self.Bind(wx.EVT_SIZE, self._onResize)
+ self.Bind(wx.EVT_LIST_COL_END_DRAG, self._onResize, self)
+
+
+ def setResizeColumn(self, col):
+ """
+ Specify which column that should be autosized. Pass either
+ 'LAST' or the column number. Default is 'LAST'.
+ """
+ if col == "LAST":
+ self._resizeColStyle = "LAST"
+ else:
+ self._resizeColStyle = "COL"
+ self._resizeCol = col
+
+
+ def resizeLastColumn(self, minWidth):
+ """ Resize the last column appropriately.
+
+ If the list's columns are too wide to fit within the window, we use
+ a horizontal scrollbar. Otherwise, we expand the right-most column
+ to take up the remaining free space in the list.
+
+ This method is called automatically when the wx.ListCtrl is resized;
+ you can also call it yourself whenever you want the last column to
+ be resized appropriately (eg, when adding, removing or resizing
+ columns).
+
+ 'minWidth' is the preferred minimum width for the last column.
+ """
+ self.resizeColumn(minWidth)
+
+
+ def resizeColumn(self, minWidth):
+ self._resizeColMinWidth = minWidth
+ self._doResize()
+
+
+ # =====================
+ # == Private Methods ==
+ # =====================
+
+ def _onResize(self, event):
+ """ Respond to the wx.ListCtrl being resized.
+
+ We automatically resize the last column in the list.
+ """
+ if 'gtk2' in wx.PlatformInfo or 'gtk3' in wx.PlatformInfo:
+ self._doResize()
+ else:
+ wx.CallAfter(self._doResize)
+ event.Skip()
+
+
+ def _doResize(self):
+ """ Resize the last column as appropriate.
+
+ If the list's columns are too wide to fit within the window, we use
+ a horizontal scrollbar. Otherwise, we expand the right-most column
+ to take up the remaining free space in the list.
+
+ We remember the current size of the last column, before resizing,
+ as the preferred minimum width if we haven't previously been given
+ or calculated a minimum width. This ensure that repeated calls to
+ _doResize() don't cause the last column to size itself too large.
+ """
+
+ if not self: # avoid a PyDeadObject error
+ return
+
+ if self.GetSize().height < 32:
+ return # avoid an endless update bug when the height is small.
+
+ numCols = self.GetColumnCount()
+ if numCols == 0: return # Nothing to resize.
+
+ if(self._resizeColStyle == "LAST"):
+ resizeCol = self.GetColumnCount()
+ else:
+ resizeCol = self._resizeCol
+
+ resizeCol = max(1, resizeCol)
+
+ if self._resizeColMinWidth == None:
+ self._resizeColMinWidth = self.GetColumnWidth(resizeCol - 1)
+
+ # We're showing the vertical scrollbar -> allow for scrollbar width
+ # NOTE: on GTK, the scrollbar is included in the client size, but on
+ # Windows it is not included
+ listWidth = self.GetClientSize().width
+ if wx.Platform != '__WXMSW__':
+ if self.GetItemCount() > self.GetCountPerPage():
+ scrollWidth = wx.SystemSettings_GetMetric(wx.SYS_VSCROLL_X)
+ listWidth = listWidth - scrollWidth
+
+ totColWidth = 0 # Width of all columns except last one.
+ for col in range(numCols):
+ if col != (resizeCol-1):
+ totColWidth = totColWidth + self.GetColumnWidth(col)
+
+ resizeColWidth = self.GetColumnWidth(resizeCol - 1)
+
+ if totColWidth + self._resizeColMinWidth > listWidth:
+ # We haven't got the width to show the last column at its minimum
+ # width -> set it to its minimum width and allow the horizontal
+ # scrollbar to show.
+ self.SetColumnWidth(resizeCol-1, self._resizeColMinWidth)
+ return
+
+ # Resize the last column to take up the remaining available space.
+
+ self.SetColumnWidth(resizeCol-1, listWidth - totColWidth)
+
+
+
+
+#----------------------------------------------------------------------------
+#----------------------------------------------------------------------------
+
+SEL_FOC = wx.LIST_STATE_SELECTED | wx.LIST_STATE_FOCUSED
+def selectBeforePopup(event):
+ """Ensures the item the mouse is pointing at is selected before a popup.
+
+ Works with both single-select and multi-select lists."""
+ ctrl = event.GetEventObject()
+ if isinstance(ctrl, wx.ListCtrl):
+ n, flags = ctrl.HitTest(event.GetPosition())
+ if n >= 0:
+ if not ctrl.GetItemState(n, wx.LIST_STATE_SELECTED):
+ for i in range(ctrl.GetItemCount()):
+ ctrl.SetItemState(i, 0, SEL_FOC)
+ #for i in getListCtrlSelection(ctrl, SEL_FOC):
+ # ctrl.SetItemState(i, 0, SEL_FOC)
+ ctrl.SetItemState(n, SEL_FOC, SEL_FOC)
+
+
+def getListCtrlSelection(listctrl, state=wx.LIST_STATE_SELECTED):
+ """ Returns list of item indexes of given state (selected by defaults) """
+ res = []
+ idx = -1
+ while 1:
+ idx = listctrl.GetNextItem(idx, wx.LIST_NEXT_ALL, state)
+ if idx == -1:
+ break
+ res.append(idx)
+ return res
+
+wxEVT_DOPOPUPMENU = wx.NewEventType()
+EVT_DOPOPUPMENU = wx.PyEventBinder(wxEVT_DOPOPUPMENU, 0)
+
+
+class ListCtrlSelectionManagerMix:
+ """Mixin that defines a platform independent selection policy
+
+ As selection single and multi-select list return the item index or a
+ list of item indexes respectively.
+ """
+ _menu = None
+
+ def __init__(self):
+ self.Bind(wx.EVT_RIGHT_DOWN, self.OnLCSMRightDown)
+ self.Bind(EVT_DOPOPUPMENU, self.OnLCSMDoPopup)
+# self.Connect(-1, -1, self.wxEVT_DOPOPUPMENU, self.OnLCSMDoPopup)
+
+
+ def getPopupMenu(self):
+ """ Override to implement dynamic menus (create) """
+ return self._menu
+
+
+ def setPopupMenu(self, menu):
+ """ Must be set for default behaviour """
+ self._menu = menu
+
+
+ def afterPopupMenu(self, menu):
+ """ Override to implement dynamic menus (destroy) """
+ pass
+
+
+ def getSelection(self):
+ res = getListCtrlSelection(self)
+ if self.GetWindowStyleFlag() & wx.LC_SINGLE_SEL:
+ if res:
+ return res[0]
+ else:
+ return -1
+ else:
+ return res
+
+
+ def OnLCSMRightDown(self, event):
+ selectBeforePopup(event)
+ event.Skip()
+ menu = self.getPopupMenu()
+ if menu:
+ evt = wx.PyEvent()
+ evt.SetEventType(wxEVT_DOPOPUPMENU)
+ evt.menu = menu
+ evt.pos = event.GetPosition()
+ wx.PostEvent(self, evt)
+
+
+ def OnLCSMDoPopup(self, event):
+ self.PopupMenu(event.menu, event.pos)
+ self.afterPopupMenu(event.menu)
+
+
+#----------------------------------------------------------------------------
+#----------------------------------------------------------------------------
+from bisect import bisect
+
+
+class TextEditMixin:
+ """
+ A mixin class that enables any text in any column of a
+ multi-column listctrl to be edited by clicking on the given row
+ and column. You close the text editor by hitting the ENTER key or
+ clicking somewhere else on the listctrl. You switch to the next
+ column by hiting TAB.
+
+ To use the mixin you have to include it in the class definition
+ and call the __init__ function::
+
+ class TestListCtrl(wx.ListCtrl, TextEditMixin):
+ def __init__(self, parent, ID, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0):
+ wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
+ TextEditMixin.__init__(self)
+
+
+ Authors: Steve Zatz, Pim Van Heuven (pim@think-wize.com)
+ """
+
+ editorBgColour = wx.Colour(255,255,175) # Yellow
+ editorFgColour = wx.Colour(0,0,0) # black
+
+ def __init__(self):
+ #editor = wx.TextCtrl(self, -1, pos=(-1,-1), size=(-1,-1),
+ # style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB \
+ # |wx.TE_RICH2)
+
+ self.make_editor()
+ self.Bind(wx.EVT_TEXT_ENTER, self.CloseEditor)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
+ self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self)
+
+
+ def make_editor(self, col_style=wx.LIST_FORMAT_LEFT):
+
+ style =wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB|wx.TE_RICH2
+ style |= {wx.LIST_FORMAT_LEFT: wx.TE_LEFT,
+ wx.LIST_FORMAT_RIGHT: wx.TE_RIGHT,
+ wx.LIST_FORMAT_CENTRE : wx.TE_CENTRE
+ }[col_style]
+
+ editor = wx.TextCtrl(self, -1, style=style)
+ editor.SetBackgroundColour(self.editorBgColour)
+ editor.SetForegroundColour(self.editorFgColour)
+ font = self.GetFont()
+ editor.SetFont(font)
+
+ self.curRow = 0
+ self.curCol = 0
+
+ editor.Hide()
+ if hasattr(self, 'editor'):
+ self.editor.Destroy()
+ self.editor = editor
+
+ self.col_style = col_style
+ self.editor.Bind(wx.EVT_CHAR, self.OnChar)
+ self.editor.Bind(wx.EVT_KILL_FOCUS, self.CloseEditor)
+
+
+ def OnItemSelected(self, evt):
+ self.curRow = evt.GetIndex()
+ evt.Skip()
+
+
+ def OnChar(self, event):
+ ''' Catch the TAB, Shift-TAB, cursor DOWN/UP key code
+ so we can open the editor at the next column (if any).'''
+
+ keycode = event.GetKeyCode()
+ if keycode == wx.WXK_TAB and event.ShiftDown():
+ self.CloseEditor()
+ if self.curCol-1 >= 0:
+ self.OpenEditor(self.curCol-1, self.curRow)
+
+ elif keycode == wx.WXK_TAB:
+ self.CloseEditor()
+ if self.curCol+1 < self.GetColumnCount():
+ self.OpenEditor(self.curCol+1, self.curRow)
+
+ elif keycode == wx.WXK_ESCAPE:
+ self.CloseEditor()
+
+ elif keycode == wx.WXK_DOWN:
+ self.CloseEditor()
+ if self.curRow+1 < self.GetItemCount():
+ self._SelectIndex(self.curRow+1)
+ self.OpenEditor(self.curCol, self.curRow)
+
+ elif keycode == wx.WXK_UP:
+ self.CloseEditor()
+ if self.curRow > 0:
+ self._SelectIndex(self.curRow-1)
+ self.OpenEditor(self.curCol, self.curRow)
+
+ else:
+ event.Skip()
+
+
+ def OnLeftDown(self, evt=None):
+ ''' Examine the click and double
+ click events to see if a row has been click on twice. If so,
+ determine the current row and columnn and open the editor.'''
+
+ if self.editor.IsShown():
+ self.CloseEditor()
+
+ x,y = evt.GetPosition()
+ row,flags = self.HitTest((x,y))
+
+ if row != self.curRow: # self.curRow keeps track of the current row
+ evt.Skip()
+ return
+
+ # the following should really be done in the mixin's init but
+ # the wx.ListCtrl demo creates the columns after creating the
+ # ListCtrl (generally not a good idea) on the other hand,
+ # doing this here handles adjustable column widths
+
+ self.col_locs = [0]
+ loc = 0
+ for n in range(self.GetColumnCount()):
+ loc = loc + self.GetColumnWidth(n)
+ self.col_locs.append(loc)
+
+
+ col = bisect(self.col_locs, x+self.GetScrollPos(wx.HORIZONTAL)) - 1
+ self.OpenEditor(col, row)
+
+
+ def OpenEditor(self, col, row):
+ ''' Opens an editor at the current position. '''
+
+ # give the derived class a chance to Allow/Veto this edit.
+ evt = wx.ListEvent(wx.wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, self.GetId())
+ evt.m_itemIndex = row
+ evt.m_col = col
+ item = self.GetItem(row, col)
+ evt.m_item.SetId(item.GetId())
+ evt.m_item.SetColumn(item.GetColumn())
+ evt.m_item.SetData(item.GetData())
+ evt.m_item.SetText(item.GetText())
+ ret = self.GetEventHandler().ProcessEvent(evt)
+ if ret and not evt.IsAllowed():
+ return # user code doesn't allow the edit.
+
+ if self.GetColumn(col).m_format != self.col_style:
+ self.make_editor(self.GetColumn(col).m_format)
+
+ x0 = self.col_locs[col]
+ x1 = self.col_locs[col+1] - x0
+
+ scrolloffset = self.GetScrollPos(wx.HORIZONTAL)
+
+ # scroll forward
+ if x0+x1-scrolloffset > self.GetSize()[0]:
+ if wx.Platform == "__WXMSW__":
+ # don't start scrolling unless we really need to
+ offset = x0+x1-self.GetSize()[0]-scrolloffset
+ # scroll a bit more than what is minimum required
+ # so we don't have to scroll everytime the user presses TAB
+ # which is very tireing to the eye
+ addoffset = self.GetSize()[0]/4
+ # but be careful at the end of the list
+ if addoffset + scrolloffset < self.GetSize()[0]:
+ offset += addoffset
+
+ self.ScrollList(offset, 0)
+ scrolloffset = self.GetScrollPos(wx.HORIZONTAL)
+ else:
+ # Since we can not programmatically scroll the ListCtrl
+ # close the editor so the user can scroll and open the editor
+ # again
+ self.editor.SetValue(self.GetItem(row, col).GetText())
+ self.curRow = row
+ self.curCol = col
+ self.CloseEditor()
+ return
+
+ y0 = self.GetItemRect(row)[1]
+
+ editor = self.editor
+ editor.SetDimensions(x0-scrolloffset,y0, x1,-1)
+
+ editor.SetValue(self.GetItem(row, col).GetText())
+ editor.Show()
+ editor.Raise()
+ editor.SetSelection(-1,-1)
+ editor.SetFocus()
+
+ self.curRow = row
+ self.curCol = col
+
+
+ # FIXME: this function is usually called twice - second time because
+ # it is binded to wx.EVT_KILL_FOCUS. Can it be avoided? (MW)
+ def CloseEditor(self, evt=None):
+ ''' Close the editor and save the new value to the ListCtrl. '''
+ if not self.editor.IsShown():
+ return
+ text = self.editor.GetValue()
+ self.editor.Hide()
+ self.SetFocus()
+
+ # post wxEVT_COMMAND_LIST_END_LABEL_EDIT
+ # Event can be vetoed. It doesn't has SetEditCanceled(), what would
+ # require passing extra argument to CloseEditor()
+ evt = wx.ListEvent(wx.wxEVT_COMMAND_LIST_END_LABEL_EDIT, self.GetId())
+ evt.m_itemIndex = self.curRow
+ evt.m_col = self.curCol
+ item = self.GetItem(self.curRow, self.curCol)
+ evt.m_item.SetId(item.GetId())
+ evt.m_item.SetColumn(item.GetColumn())
+ evt.m_item.SetData(item.GetData())
+ evt.m_item.SetText(text) #should be empty string if editor was canceled
+ ret = self.GetEventHandler().ProcessEvent(evt)
+ if not ret or evt.IsAllowed():
+ if self.IsVirtual():
+ # replace by whather you use to populate the virtual ListCtrl
+ # data source
+ self.SetVirtualData(self.curRow, self.curCol, text)
+ else:
+ self.SetStringItem(self.curRow, self.curCol, text)
+ self.RefreshItem(self.curRow)
+
+ def _SelectIndex(self, row):
+ listlen = self.GetItemCount()
+ if row < 0 and not listlen:
+ return
+ if row > (listlen-1):
+ row = listlen -1
+
+ self.SetItemState(self.curRow, ~wx.LIST_STATE_SELECTED,
+ wx.LIST_STATE_SELECTED)
+ self.EnsureVisible(row)
+ self.SetItemState(row, wx.LIST_STATE_SELECTED,
+ wx.LIST_STATE_SELECTED)
+
+
+
+#----------------------------------------------------------------------------
+#----------------------------------------------------------------------------
+
+"""
+FILENAME: CheckListCtrlMixin.py
+AUTHOR: Bruce Who (bruce.who.hk at gmail.com)
+DATE: 2006-02-09
+$Revision$
+DESCRIPTION:
+ This script provide a mixin for ListCtrl which add a checkbox in the first
+ column of each row. It is inspired by limodou's CheckList.py(which can be
+ got from his NewEdit) and improved:
+ - You can just use InsertStringItem() to insert new items;
+ - Once a checkbox is checked/unchecked, the corresponding item is not
+ selected;
+ - You can use SetItemData() and GetItemData();
+ - Interfaces are changed to OnCheckItem(), IsChecked(), CheckItem().
+
+ You should not set a imagelist for the ListCtrl once this mixin is used.
+
+HISTORY:
+1.3 - You can check/uncheck a group of sequential items by <Shift-click>:
+ First click(or <Shift-Click>) item1 to check/uncheck it, then
+ Shift-click item2 to check/uncheck it, and you'll find that all
+ items between item1 and item2 are check/unchecked!
+1.2 - Add ToggleItem()
+1.1 - Initial version
+"""
+
+class CheckListCtrlMixin:
+ """
+ This is a mixin for ListCtrl which add a checkbox in the first
+ column of each row. It is inspired by limodou's CheckList.py(which
+ can be got from his NewEdit) and improved:
+
+ - You can just use InsertStringItem() to insert new items;
+
+ - Once a checkbox is checked/unchecked, the corresponding item
+ is not selected;
+
+ - You can use SetItemData() and GetItemData();
+
+ - Interfaces are changed to OnCheckItem(), IsChecked(),
+ CheckItem().
+
+ You should not set a imagelist for the ListCtrl once this mixin is used.
+ """
+ def __init__(self, check_image=None, uncheck_image=None, imgsz=(16,16)):
+ if check_image is not None:
+ imgsz = check_image.GetSize()
+ elif uncheck_image is not None:
+ imgsz = check_image.GetSize()
+
+ self.__imagelist_ = wx.ImageList(*imgsz)
+
+ # Create default checkbox images if none were specified
+ if check_image is None:
+ check_image = self.__CreateBitmap(wx.CONTROL_CHECKED, imgsz)
+
+ if uncheck_image is None:
+ uncheck_image = self.__CreateBitmap(0, imgsz)
+
+ self.uncheck_image = self.__imagelist_.Add(uncheck_image)
+ self.check_image = self.__imagelist_.Add(check_image)
+ self.SetImageList(self.__imagelist_, wx.IMAGE_LIST_SMALL)
+ self.__last_check_ = None
+
+ self.Bind(wx.EVT_LEFT_DOWN, self.__OnLeftDown_)
+
+ # override the default methods of ListCtrl/ListView
+ self.InsertStringItem = self.__InsertStringItem_
+
+ def __CreateBitmap(self, flag=0, size=(16, 16)):
+ """Create a bitmap of the platforms native checkbox. The flag
+ is used to determine the checkboxes state (see wx.CONTROL_*)
+
+ """
+ bmp = wx.EmptyBitmap(*size)
+ dc = wx.MemoryDC(bmp)
+ dc.Clear()
+ wx.RendererNative.Get().DrawCheckBox(self, dc,
+ (0, 0, size[0], size[1]), flag)
+ dc.SelectObject(wx.NullBitmap)
+ return bmp
+
+ # NOTE: if you use InsertItem, InsertImageItem or InsertImageStringItem,
+ # you must set the image yourself.
+ def __InsertStringItem_(self, index, label):
+ index = self.InsertImageStringItem(index, label, 0)
+ return index
+
+ def __OnLeftDown_(self, evt):
+ (index, flags) = self.HitTest(evt.GetPosition())
+ if flags == wx.LIST_HITTEST_ONITEMICON:
+ img_idx = self.GetItem(index).GetImage()
+ flag_check = img_idx == 0
+ begin_index = index
+ end_index = index
+ if self.__last_check_ is not None \
+ and wx.GetKeyState(wx.WXK_SHIFT):
+ last_index, last_flag_check = self.__last_check_
+ if last_flag_check == flag_check:
+ # XXX what if the previous item is deleted or new items
+ # are inserted?
+ item_count = self.GetItemCount()
+ if last_index < item_count:
+ if last_index < index:
+ begin_index = last_index
+ end_index = index
+ elif last_index > index:
+ begin_index = index
+ end_index = last_index
+ else:
+ assert False
+ while begin_index <= end_index:
+ self.CheckItem(begin_index, flag_check)
+ begin_index += 1
+ self.__last_check_ = (index, flag_check)
+ else:
+ evt.Skip()
+
+ def OnCheckItem(self, index, flag):
+ pass
+
+ def IsChecked(self, index):
+ return self.GetItem(index).GetImage() == 1
+
+ def CheckItem(self, index, check = True):
+ img_idx = self.GetItem(index).GetImage()
+ if img_idx == 0 and check is True:
+ self.SetItemImage(index, 1)
+ self.OnCheckItem(index, True)
+ elif img_idx == 1 and check is False:
+ self.SetItemImage(index, 0)
+ self.OnCheckItem(index, False)
+
+ def ToggleItem(self, index):
+ self.CheckItem(index, not self.IsChecked(index))
+
+
+#----------------------------------------------------------------------------
+#----------------------------------------------------------------------------
+
+# Mode Flags
+HIGHLIGHT_ODD = 1 # Highlight the Odd rows
+HIGHLIGHT_EVEN = 2 # Highlight the Even rows
+
+class ListRowHighlighter:
+ """Editra Control Library: ListRowHighlighter
+ Mixin class that handles automatic background highlighting of alternate
+ rows in the a ListCtrl. The background of the rows are highlighted
+ automatically as items are added or inserted in the control based on the
+ mixins Mode and set Color. By default the Even rows will be highlighted with
+ the systems highlight color.
+
+ """
+ def __init__(self, color=None, mode=HIGHLIGHT_EVEN):
+ """Initialize the highlighter mixin
+ @keyword color: Set a custom highlight color (default uses system color)
+ @keyword mode: HIGHLIGHT_EVEN (default) or HIGHLIGHT_ODD
+
+ """
+ # Attributes
+ self._color = color
+ self._defaultb = wx.SystemSettings.GetColour(wx.SYS_COLOUR_LISTBOX)
+ self._mode = mode
+
+ # Event Handlers
+ self.Bind(wx.EVT_LIST_INSERT_ITEM, lambda evt: self.RefreshRows())
+ self.Bind(wx.EVT_LIST_DELETE_ITEM, lambda evt: self.RefreshRows())
+
+ def RefreshRows(self):
+ """Re-color all the rows"""
+ for row in xrange(self.GetItemCount()):
+ if self._defaultb is None:
+ self._defaultb = self.GetItemBackgroundColour(row)
+
+ if self._mode & HIGHLIGHT_EVEN:
+ dohlight = not row % 2
+ else:
+ dohlight = row % 2
+
+ if dohlight:
+ if self._color is None:
+ if wx.Platform in ['__WXGTK__', '__WXMSW__']:
+ color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DLIGHT)
+ else:
+ color = wx.Colour(237, 243, 254)
+ else:
+ color = self._color
+ else:
+ color = self._defaultb
+
+ self.SetItemBackgroundColour(row, color)
+
+ def SetHighlightColor(self, color):
+ """Set the color used to highlight the rows. Call :meth:`RefreshRows` after
+ this if you wish to update all the rows highlight colors.
+ @param color: wx.Color or None to set default
+
+ """
+ self._color = color
+
+ def SetHighlightMode(self, mode):
+ """Set the highlighting mode to either HIGHLIGHT_EVEN or to
+ HIGHLIGHT_ODD. Call :meth:`RefreshRows` afterwards to update the list
+ state.
+ @param mode: HIGHLIGHT_* mode value
+
+ """
+ self._mode = mode
+
+#----------------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/rubberband.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/rubberband.py
new file mode 100644
index 0000000..f2eb7a8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/rubberband.py
@@ -0,0 +1,406 @@
+#---------------------------------------------------------------------------
+# Name: wxPython.lib.mixins.rubberband
+# Purpose: A mixin class for doing "RubberBand"-ing on a window.
+#
+# Author: Robb Shecter and members of wxPython-users
+#
+# Created: 11-September-2002
+# RCS-ID: $Id$
+# Copyright: (c) 2002 by db-X Corporation
+# Licence: wxWindows license
+#---------------------------------------------------------------------------
+# 12/14/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o Tested, but there is an anomaly between first use and subsequent uses.
+# First use is odd, subsequent uses seem to be OK. Init error?
+# -- No, the first time it uses an aspect ratio, but after the reset it doesn't.
+#
+
+"""
+A mixin class for doing "RubberBand"-ing on a window.
+"""
+
+import wx
+
+#
+# Some miscellaneous mathematical and geometrical functions
+#
+
+def isNegative(aNumber):
+ """
+ x < 0: 1
+ else: 0
+ """
+ return aNumber < 0
+
+
+def normalizeBox(box):
+ """
+ Convert any negative measurements in the current
+ box to positive, and adjust the origin.
+ """
+ x, y, w, h = box
+ if w < 0:
+ x += (w+1)
+ w *= -1
+ if h < 0:
+ y += (h+1)
+ h *= -1
+ return (x, y, w, h)
+
+
+def boxToExtent(box):
+ """
+ Convert a box specification to an extent specification.
+ I put this into a seperate function after I realized that
+ I had been implementing it wrong in several places.
+ """
+ b = normalizeBox(box)
+ return (b[0], b[1], b[0]+b[2]-1, b[1]+b[3]-1)
+
+
+def pointInBox(x, y, box):
+ """
+ Return True if the given point is contained in the box.
+ """
+ e = boxToExtent(box)
+ return x >= e[0] and x <= e[2] and y >= e[1] and y <= e[3]
+
+
+def pointOnBox(x, y, box, thickness=1):
+ """
+ Return True if the point is on the outside edge
+ of the box. The thickness defines how thick the
+ edge should be. This is necessary for HCI reasons:
+ For example, it's normally very difficult for a user
+ to manuever the mouse onto a one pixel border.
+ """
+ outerBox = box
+ innerBox = (box[0]+thickness, box[1]+thickness, box[2]-(thickness*2), box[3]-(thickness*2))
+ return pointInBox(x, y, outerBox) and not pointInBox(x, y, innerBox)
+
+
+def getCursorPosition(x, y, box, thickness=1):
+ """
+ Return a position number in the range 0 .. 7 to indicate
+ where on the box border the point is. The layout is:
+
+ 0 1 2
+ 7 3
+ 6 5 4
+ """
+ x0, y0, x1, y1 = boxToExtent(box)
+ w, h = box[2], box[3]
+ delta = thickness - 1
+ p = None
+
+ if pointInBox(x, y, (x0, y0, thickness, thickness)):
+ p = 0
+ elif pointInBox(x, y, (x1-delta, y0, thickness, thickness)):
+ p = 2
+ elif pointInBox(x, y, (x1-delta, y1-delta, thickness, thickness)):
+ p = 4
+ elif pointInBox(x, y, (x0, y1-delta, thickness, thickness)):
+ p = 6
+ elif pointInBox(x, y, (x0+thickness, y0, w-(thickness*2), thickness)):
+ p = 1
+ elif pointInBox(x, y, (x1-delta, y0+thickness, thickness, h-(thickness*2))):
+ p = 3
+ elif pointInBox(x, y, (x0+thickness, y1-delta, w-(thickness*2), thickness)):
+ p = 5
+ elif pointInBox(x, y, (x0, y0+thickness, thickness, h-(thickness*2))):
+ p = 7
+
+ return p
+
+
+
+
+class RubberBand:
+ """
+ A stretchable border which is drawn on top of an
+ image to define an area.
+ """
+ def __init__(self, drawingSurface, aspectRatio=None):
+ self.__THICKNESS = 5
+ self.drawingSurface = drawingSurface
+ self.aspectRatio = aspectRatio
+ self.hasLetUp = 0
+ self.currentlyMoving = None
+ self.currentBox = None
+ self.__enabled = 1
+ self.__currentCursor = None
+
+ drawingSurface.Bind(wx.EVT_MOUSE_EVENTS, self.__handleMouseEvents)
+ drawingSurface.Bind(wx.EVT_PAINT, self.__handleOnPaint)
+
+ def __setEnabled(self, enabled):
+ self.__enabled = enabled
+
+ def __isEnabled(self):
+ return self.__enabled
+
+ def __handleOnPaint(self, event):
+ #print 'paint'
+ event.Skip()
+
+ def __isMovingCursor(self):
+ """
+ Return True if the current cursor is one used to
+ mean moving the rubberband.
+ """
+ return self.__currentCursor == wx.CURSOR_HAND
+
+ def __isSizingCursor(self):
+ """
+ Return True if the current cursor is one of the ones
+ I may use to signify sizing.
+ """
+ sizingCursors = [wx.CURSOR_SIZENESW,
+ wx.CURSOR_SIZENS,
+ wx.CURSOR_SIZENWSE,
+ wx.CURSOR_SIZEWE,
+ wx.CURSOR_SIZING,
+ wx.CURSOR_CROSS]
+ try:
+ sizingCursors.index(self.__currentCursor)
+ return 1
+ except ValueError:
+ return 0
+
+
+ def __handleMouseEvents(self, event):
+ """
+ React according to the new event. This is the main
+ entry point into the class. This method contains the
+ logic for the class's behavior.
+ """
+ if not self.enabled:
+ return
+
+ x, y = event.GetPosition()
+
+ # First make sure we have started a box.
+ if self.currentBox == None and not event.LeftDown():
+ # No box started yet. Set cursor to the initial kind.
+ self.__setCursor(wx.CURSOR_CROSS)
+ return
+
+ if event.LeftDown():
+ if self.currentBox == None:
+ # No RB Box, so start a new one.
+ self.currentBox = (x, y, 0, 0)
+ self.hasLetUp = 0
+ elif self.__isSizingCursor():
+ # Starting a sizing operation. Change the origin.
+ position = getCursorPosition(x, y, self.currentBox, thickness=self.__THICKNESS)
+ self.currentBox = self.__denormalizeBox(position, self.currentBox)
+
+ elif event.Dragging() and event.LeftIsDown():
+ # Use the cursor type to determine operation
+ if self.__isMovingCursor():
+ if self.currentlyMoving or pointInBox(x, y, self.currentBox):
+ if not self.currentlyMoving:
+ self.currentlyMoving = (x - self.currentBox[0], y - self.currentBox[1])
+ self.__moveTo(x - self.currentlyMoving[0], y - self.currentlyMoving[1])
+ elif self.__isSizingCursor():
+ self.__resizeBox(x, y)
+
+ elif event.LeftUp():
+ self.hasLetUp = 1
+ self.currentlyMoving = None
+ self.__normalizeBox()
+
+ elif event.Moving() and not event.Dragging():
+ # Simple mouse movement event
+ self.__mouseMoved(x,y)
+
+ def __denormalizeBox(self, position, box):
+ x, y, w, h = box
+ b = box
+ if position == 2 or position == 3:
+ b = (x, y + (h-1), w, h * -1)
+ elif position == 0 or position == 1 or position == 7:
+ b = (x + (w-1), y + (h-1), w * -1, h * -1)
+ elif position == 6:
+ b = (x + (w-1), y, w * -1, h)
+ return b
+
+ def __resizeBox(self, x, y):
+ """
+ Resize and repaint the box based on the given mouse
+ coordinates.
+ """
+ # Implement the correct behavior for dragging a side
+ # of the box: Only change one dimension.
+ if not self.aspectRatio:
+ if self.__currentCursor == wx.CURSOR_SIZENS:
+ x = None
+ elif self.__currentCursor == wx.CURSOR_SIZEWE:
+ y = None
+
+ x0,y0,w0,h0 = self.currentBox
+ currentExtent = boxToExtent(self.currentBox)
+ if x == None:
+ if w0 < 1:
+ w0 += 1
+ else:
+ w0 -= 1
+ x = x0 + w0
+ if y == None:
+ if h0 < 1:
+ h0 += 1
+ else:
+ h0 -= 1
+ y = y0 + h0
+ x1,y1 = x, y
+ w, h = abs(x1-x0)+1, abs(y1-y0)+1
+ if self.aspectRatio:
+ w = max(w, int(h * self.aspectRatio))
+ h = int(w / self.aspectRatio)
+ w *= [1,-1][isNegative(x1-x0)]
+ h *= [1,-1][isNegative(y1-y0)]
+ newbox = (x0, y0, w, h)
+ self.__drawAndErase(boxToDraw=normalizeBox(newbox), boxToErase=normalizeBox(self.currentBox))
+ self.currentBox = (x0, y0, w, h)
+
+ def __normalizeBox(self):
+ """
+ Convert any negative measurements in the current
+ box to positive, and adjust the origin.
+ """
+ self.currentBox = normalizeBox(self.currentBox)
+
+ def __mouseMoved(self, x, y):
+ """
+ Called when the mouse moved without any buttons pressed
+ or dragging being done.
+ """
+ # Are we on the bounding box?
+ if pointOnBox(x, y, self.currentBox, thickness=self.__THICKNESS):
+ position = getCursorPosition(x, y, self.currentBox, thickness=self.__THICKNESS)
+ cursor = [
+ wx.CURSOR_SIZENWSE,
+ wx.CURSOR_SIZENS,
+ wx.CURSOR_SIZENESW,
+ wx.CURSOR_SIZEWE,
+ wx.CURSOR_SIZENWSE,
+ wx.CURSOR_SIZENS,
+ wx.CURSOR_SIZENESW,
+ wx.CURSOR_SIZEWE
+ ] [position]
+ self.__setCursor(cursor)
+ elif pointInBox(x, y, self.currentBox):
+ self.__setCursor(wx.CURSOR_HAND)
+ else:
+ self.__setCursor()
+
+ def __setCursor(self, id=None):
+ """
+ Set the mouse cursor to the given id.
+ """
+ if self.__currentCursor != id: # Avoid redundant calls
+ if id:
+ self.drawingSurface.SetCursor(wx.StockCursor(id))
+ else:
+ self.drawingSurface.SetCursor(wx.NullCursor)
+ self.__currentCursor = id
+
+ def __moveCenterTo(self, x, y):
+ """
+ Move the rubber band so that its center is at (x,y).
+ """
+ x0, y0, w, h = self.currentBox
+ x2, y2 = x - (w/2), y - (h/2)
+ self.__moveTo(x2, y2)
+
+ def __moveTo(self, x, y):
+ """
+ Move the rubber band so that its origin is at (x,y).
+ """
+ newbox = (x, y, self.currentBox[2], self.currentBox[3])
+ self.__drawAndErase(boxToDraw=newbox, boxToErase=self.currentBox)
+ self.currentBox = newbox
+
+ def __drawAndErase(self, boxToDraw, boxToErase=None):
+ """
+ Draw one box shape and possibly erase another.
+ """
+ dc = wx.ClientDC(self.drawingSurface)
+ dc.BeginDrawing()
+ dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetLogicalFunction(wx.XOR)
+ if boxToErase:
+ r = wx.Rect(*boxToErase)
+ dc.DrawRectangleRect(r)
+
+ r = wx.Rect(*boxToDraw)
+ dc.DrawRectangleRect(r)
+ dc.EndDrawing()
+
+ def __dumpMouseEvent(self, event):
+ print 'Moving: ',event.Moving()
+ print 'Dragging: ',event.Dragging()
+ print 'LeftDown: ',event.LeftDown()
+ print 'LeftisDown: ',event.LeftIsDown()
+ print 'LeftUp: ',event.LeftUp()
+ print 'Position: ',event.GetPosition()
+ print 'x,y: ',event.GetX(),event.GetY()
+ print
+
+
+ #
+ # The public API:
+ #
+
+ def reset(self, aspectRatio=None):
+ """
+ Clear the existing rubberband
+ """
+ self.currentBox = None
+ self.aspectRatio = aspectRatio
+ self.drawingSurface.Refresh()
+
+ def getCurrentExtent(self):
+ """
+ Return (x0, y0, x1, y1) or None if
+ no drawing has yet been done.
+ """
+ if not self.currentBox:
+ extent = None
+ else:
+ extent = boxToExtent(self.currentBox)
+ return extent
+
+ enabled = property(__isEnabled, __setEnabled, None, 'True if I am responding to mouse events')
+
+
+
+if __name__ == '__main__':
+ app = wx.App()
+ frame = wx.Frame(None, -1, title='RubberBand Test', size=(300,300))
+
+ # Add a panel that the rubberband will work on.
+ panel = wx.Panel(frame, -1)
+ panel.SetBackgroundColour(wx.BLUE)
+
+ # Create the rubberband
+ frame.rubberBand = RubberBand(drawingSurface=panel)
+ frame.rubberBand.reset(aspectRatio=0.5)
+
+ # Add a button that creates a new rubberband
+ def __newRubberBand(event):
+ frame.rubberBand.reset()
+ button = wx.Button(frame, 100, 'Reset Rubberband')
+ frame.Bind(wx.EVT_BUTTON, __newRubberBand, button)
+
+ # Layout the frame
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(panel, 1, wx.EXPAND | wx.ALL, 5)
+ sizer.Add(button, 0, wx.ALIGN_CENTER | wx.ALL, 5)
+ frame.SetAutoLayout(1)
+ frame.SetSizer(sizer)
+ frame.Show(1)
+ app.MainLoop()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/treemixin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/treemixin.py
new file mode 100644
index 0000000..e057103
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mixins/treemixin.py
@@ -0,0 +1,661 @@
+"""
+treemixin.py
+
+This module provides three mixin classes that can be used with tree
+controls:
+
+- VirtualTree is a class that, when mixed in with a tree control,
+ makes the tree control virtual, similar to a ListCtrl in virtual mode.
+ A virtual tree control builds the tree itself by means of callbacks,
+ so the programmer is freed from the burden of building the tree herself.
+
+- DragAndDrop is a mixin class that helps with dragging and dropping of
+ items. The graphical part of dragging and dropping tree items is done by
+ this mixin class. You only need to implement the OnDrop method that is
+ called when the drop happens.
+
+- ExpansionState is a mixin that can be queried for the expansion state of
+ all items in the tree to restore it later.
+
+All mixin classes work with wx.TreeCtrl, wx.gizmos.TreeListCtrl,
+and wx.lib.customtreectrl.CustomTreeCtrl. They can be used together or
+separately.
+
+The VirtualTree and DragAndDrop mixins force the wx.TR_HIDE_ROOT style.
+
+.. moduleauthor:: Frank Niessink <frank@niessink.com>
+
+License: wxWidgets license
+Version: 1.1
+Date: 24 September 2007
+
+ExpansionState is based on code and ideas from Karsten Hilbert.
+Andrea Gavana provided help with the CustomTreeCtrl integration.
+"""
+
+
+import wx
+
+
+class TreeAPIHarmonizer(object):
+ """ This class attempts to hide the differences in API between the
+ different tree controls that are part of wxPython. """
+
+ def __callSuper(self, methodName, default, *args, **kwargs):
+ # If our super class has a method called methodName, call it,
+ # otherwise return the default value.
+ superClass = super(TreeAPIHarmonizer, self)
+ if hasattr(superClass, methodName):
+ return getattr(superClass, methodName)(*args, **kwargs)
+ else:
+ return default
+
+ def GetColumnCount(self, *args, **kwargs):
+ # Only TreeListCtrl has columns, return 0 if we are mixed in
+ # with another tree control.
+ return self.__callSuper('GetColumnCount', 0, *args, **kwargs)
+
+ def GetItemType(self, *args, **kwargs):
+ # Only CustomTreeCtrl has different item types, return the
+ # default item type if we are mixed in with another tree control.
+ return self.__callSuper('GetItemType', 0, *args, **kwargs)
+
+ def SetItemType(self, item, newType):
+ # CustomTreeCtrl doesn't support changing the item type on the fly,
+ # so we create a new item and delete the old one. We currently only
+ # keep the item text, would be nicer to also retain other attributes.
+ text = self.GetItemText(item)
+ newItem = self.InsertItem(self.GetItemParent(item), item, text,
+ ct_type=newType)
+ self.Delete(item)
+ return newItem
+
+ def IsItemChecked(self, *args, **kwargs):
+ # Only CustomTreeCtrl supports checkable items, return False if
+ # we are mixed in with another tree control.
+ return self.__callSuper('IsItemChecked', False, *args, **kwargs)
+
+ def GetItemChecked(self, *args, **kwargs):
+ # For consistency's sake, provide a 'Get' and 'Set' method for
+ # checkable items.
+ return self.IsItemChecked(*args, **kwargs)
+
+ def SetItemChecked(self, *args, **kwargs):
+ # For consistency's sake, provide a 'Get' and 'Set' method for
+ # checkable items.
+ return self.CheckItem(*args, **kwargs)
+
+ def GetMainWindow(self, *args, **kwargs):
+ # Only TreeListCtrl has a separate main window, return self if we are
+ # mixed in with another tree control.
+ return self.__callSuper('GetMainWindow', self, *args, **kwargs)
+
+ def GetItemImage(self, item, which=wx.TreeItemIcon_Normal, column=-1):
+ # CustomTreeCtrl always wants the which argument, so provide it
+ # TreeListCtr.GetItemImage has a different order of arguments than
+ # the other tree controls. Hide the differenes.
+ if self.GetColumnCount():
+ args = (item, column, which)
+ else:
+ args = (item, which)
+ return super(TreeAPIHarmonizer, self).GetItemImage(*args)
+
+ def SetItemImage(self, item, imageIndex, which=wx.TreeItemIcon_Normal,
+ column=-1):
+ # The SetItemImage signature is different for TreeListCtrl and
+ # other tree controls. This adapter method hides the differences.
+ if self.GetColumnCount():
+ args = (item, imageIndex, column, which)
+ else:
+ args = (item, imageIndex, which)
+ super(TreeAPIHarmonizer, self).SetItemImage(*args)
+
+ def UnselectAll(self):
+ # Unselect all items, regardless of whether we are in multiple
+ # selection mode or not.
+ if self.HasFlag(wx.TR_MULTIPLE):
+ super(TreeAPIHarmonizer, self).UnselectAll()
+ else:
+ # CustomTreeCtrl Unselect() doesn't seem to work in all cases,
+ # also invoke UnselectAll just to be sure.
+ self.Unselect()
+ super(TreeAPIHarmonizer, self).UnselectAll()
+
+ def GetCount(self):
+ # TreeListCtrl correctly ignores the root item when it is hidden,
+ # but doesn't count the root item when it is visible
+ itemCount = super(TreeAPIHarmonizer, self).GetCount()
+ if self.GetColumnCount() and not self.HasFlag(wx.TR_HIDE_ROOT):
+ itemCount += 1
+ return itemCount
+
+ def GetSelections(self):
+ # Always return a list of selected items, regardless of whether
+ # we are in multiple selection mode or not.
+ if self.HasFlag(wx.TR_MULTIPLE):
+ selections = super(TreeAPIHarmonizer, self).GetSelections()
+ else:
+ selection = self.GetSelection()
+ if selection:
+ selections = [selection]
+ else:
+ selections = []
+ # If the root item is hidden, it should never be selected,
+ # unfortunately, CustomTreeCtrl allows it to be selected.
+ if self.HasFlag(wx.TR_HIDE_ROOT):
+ rootItem = self.GetRootItem()
+ if rootItem and rootItem in selections:
+ selections.remove(rootItem)
+ return selections
+
+ def GetFirstVisibleItem(self):
+ # TreeListCtrl raises an exception or even crashes when invoking
+ # GetFirstVisibleItem on an empty tree.
+ if self.GetRootItem():
+ return super(TreeAPIHarmonizer, self).GetFirstVisibleItem()
+ else:
+ return wx.TreeItemId()
+
+ def SelectItem(self, item, *args, **kwargs):
+ # Prevent the hidden root from being selected, otherwise TreeCtrl
+ # crashes
+ if self.HasFlag(wx.TR_HIDE_ROOT) and item == self.GetRootItem():
+ return
+ else:
+ return super(TreeAPIHarmonizer, self).SelectItem(item, *args,
+ **kwargs)
+
+ def HitTest(self, *args, **kwargs):
+ """ HitTest returns a two-tuple (item, flags) for tree controls
+ without columns and a three-tuple (item, flags, column) for tree
+ controls with columns. Our caller can indicate this method to
+ always return a three-tuple no matter what tree control we're mixed
+ in with by specifying the optional argument 'alwaysReturnColumn'
+ to be True. """
+ alwaysReturnColumn = kwargs.pop('alwaysReturnColumn', False)
+ hitTestResult = super(TreeAPIHarmonizer, self).HitTest(*args, **kwargs)
+ if len(hitTestResult) == 2 and alwaysReturnColumn:
+ hitTestResult += (0,)
+ return hitTestResult
+
+ def ExpandAll(self, item=None):
+ # TreeListCtrl wants an item as argument. That's an inconsistency with
+ # the TreeCtrl API. Also, TreeCtrl doesn't allow invoking ExpandAll
+ # on a tree with hidden root node, so prevent that.
+ if self.HasFlag(wx.TR_HIDE_ROOT):
+ rootItem = self.GetRootItem()
+ if rootItem:
+ child, cookie = self.GetFirstChild(rootItem)
+ while child:
+ self.ExpandAllChildren(child)
+ child, cookie = self.GetNextChild(rootItem, cookie)
+ else:
+ try:
+ super(TreeAPIHarmonizer, self).ExpandAll()
+ except TypeError:
+ if item is None:
+ item = self.GetRootItem()
+ super(TreeAPIHarmonizer, self).ExpandAll(item)
+
+ def ExpandAllChildren(self, item):
+ # TreeListCtrl and CustomTreeCtrl don't have ExpandallChildren
+ try:
+ super(TreeAPIHarmonizer, self).ExpandAllChildren(item)
+ except AttributeError:
+ self.Expand(item)
+ child, cookie = self.GetFirstChild(item)
+ while child:
+ self.ExpandAllChildren(child)
+ child, cookie = self.GetNextChild(item, cookie)
+
+
+class TreeHelper(object):
+ """ This class provides methods that are not part of the API of any
+ tree control, but are convenient to have available. """
+
+ def GetItemChildren(self, item=None, recursively=False):
+ """ Return the children of item as a list. """
+ if not item:
+ item = self.GetRootItem()
+ if not item:
+ return []
+ children = []
+ child, cookie = self.GetFirstChild(item)
+ while child:
+ children.append(child)
+ if recursively:
+ children.extend(self.GetItemChildren(child, True))
+ child, cookie = self.GetNextChild(item, cookie)
+ return children
+
+ def GetIndexOfItem(self, item):
+ """ Return the index of item. """
+ parent = self.GetItemParent(item)
+ if parent:
+ parentIndices = self.GetIndexOfItem(parent)
+ ownIndex = self.GetItemChildren(parent).index(item)
+ return parentIndices + (ownIndex,)
+ else:
+ return ()
+
+ def GetItemByIndex(self, index):
+ """ Return the item specified by index. """
+ item = self.GetRootItem()
+ for i in index:
+ children = self.GetItemChildren(item)
+ item = children[i]
+ return item
+
+
+class VirtualTree(TreeAPIHarmonizer, TreeHelper):
+ """ This is a mixin class that can be used to allow for virtual tree
+ controls. It can be mixed in with wx.TreeCtrl, wx.gizmos.TreeListCtrl,
+ wx.lib.customtree.CustomTreeCtrl.
+
+ To use it derive a new class from this class and one of the tree
+ controls, e.g.::
+
+ class MyTree(VirtualTree, wx.TreeCtrl):
+ # Other code here
+
+
+ VirtualTree uses several callbacks (such as OnGetItemText) to
+ retrieve information needed to construct the tree and render the
+ items. To specify what item the callback needs information about,
+ the callback passes an item index. Whereas for list controls a simple
+ integer index can be used, for tree controls indicating a specific
+ item is a little bit more complicated. See below for a more detailed
+ explanation of the how index works.
+
+ Note that VirtualTree forces the wx.TR_HIDE_ROOT style.
+
+ In your subclass you *must* override OnGetItemText and
+ OnGetChildrenCount. These two methods are the minimum needed to
+ construct the tree and render the item labels. If you want to add
+ images, change fonts our colours, etc., you need to override the
+ appropriate OnGetXXX method as well.
+
+ About indices: your callbacks are passed a tuple of integers that
+ identifies the item the VirtualTree wants information about. An
+ empty tuple, i.e. (), represents the hidden root item. A tuple with
+ one integer, e.g. (3,), represents a visible root item, in this case
+ the fourth one. A tuple with two integers, e.g. (3,0), represents a
+ child of a visible root item, in this case the first child of the
+ fourth root item.
+ """
+
+ def __init__(self, *args, **kwargs):
+ kwargs['style'] = kwargs.get('style', wx.TR_DEFAULT_STYLE) | \
+ wx.TR_HIDE_ROOT
+ super(VirtualTree, self).__init__(*args, **kwargs)
+ self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding)
+ self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed)
+
+ def OnGetChildrenCount(self, index):
+ """ This function *must* be overloaded in the derived class.
+ It should return the number of child items of the item with the
+ provided index. If index == () it should return the number of
+ root items. """
+ raise NotImplementedError
+
+ def OnGetItemText(self, index, column=0):
+ """ This function *must* be overloaded in the derived class. It
+ should return the string containing the text of the specified
+ item. """
+ raise NotImplementedError
+
+ def OnGetItemFont(self, index):
+ """ This function may be overloaded in the derived class. It
+ should return the wx.Font to be used for the specified item. """
+ return wx.NullFont
+
+ def OnGetItemTextColour(self, index):
+ """ This function may be overloaded in the derived class. It
+ should return the wx.Colour to be used as text colour for the
+ specified item. """
+ return wx.NullColour
+
+ def OnGetItemBackgroundColour(self, index):
+ """ This function may be overloaded in the derived class. It
+ should return the wx.Colour to be used as background colour for
+ the specified item. """
+ return wx.NullColour
+
+ def OnGetItemImage(self, index, which=wx.TreeItemIcon_Normal, column=0):
+ """ This function may be overloaded in the derived class. It
+ should return the index of the image to be used. Don't forget
+ to associate an ImageList with the tree control. """
+ return -1
+
+ def OnGetItemType(self, index):
+ """ This function may be overloaded in the derived class, but
+ that only makes sense when this class is mixed in with a tree
+ control that supports checkable items, i.e. CustomTreeCtrl.
+ This method should return whether the item is to be normal (0,
+ the default), a checkbox (1) or a radiobutton (2).
+ Note that OnGetItemChecked needs to be implemented as well; it
+ should return whether the item is actually checked. """
+ return 0
+
+ def OnGetItemChecked(self, index):
+ """ This function may be overloaded in the derived class, but
+ that only makes sense when this class is mixed in with a tree
+ control that supports checkable items, i.e. CustomTreeCtrl.
+ This method should return whether the item is to be checked.
+ Note that OnGetItemType should return 1 (checkbox) or 2
+ (radiobutton) for this item. """
+ return False
+
+ def RefreshItems(self):
+ """ Redraws all visible items. """
+ rootItem = self.GetRootItem()
+ if not rootItem:
+ rootItem = self.AddRoot('Hidden root')
+ self.RefreshChildrenRecursively(rootItem)
+
+ def RefreshItem(self, index):
+ """ Redraws the item with the specified index. """
+ try:
+ item = self.GetItemByIndex(index)
+ except IndexError:
+ # There's no corresponding item for index, because its parent
+ # has not been expanded yet.
+ return
+ hasChildren = bool(self.OnGetChildrenCount(index))
+ self.DoRefreshItem(item, index, hasChildren)
+
+ def RefreshChildrenRecursively(self, item, itemIndex=None):
+ """ Refresh the children of item, reusing as much of the
+ existing items in the tree as possible. """
+ if itemIndex is None:
+ itemIndex = self.GetIndexOfItem(item)
+ reusableChildren = self.GetItemChildren(item)
+ for childIndex in self.ChildIndices(itemIndex):
+ if reusableChildren:
+ child = reusableChildren.pop(0)
+ else:
+ child = self.AppendItem(item, '')
+ self.RefreshItemRecursively(child, childIndex)
+ for child in reusableChildren:
+ self.Delete(child)
+
+ def RefreshItemRecursively(self, item, itemIndex):
+ """ Refresh the item and its children recursively. """
+ hasChildren = bool(self.OnGetChildrenCount(itemIndex))
+ item = self.DoRefreshItem(item, itemIndex, hasChildren)
+ # We need to refresh the children when the item is expanded and
+ # when the item has no children, because in the latter case we
+ # might have to delete old children from the tree:
+ if self.IsExpanded(item) or not hasChildren:
+ self.RefreshChildrenRecursively(item, itemIndex)
+ self.SetItemHasChildren(item, hasChildren)
+
+ def DoRefreshItem(self, item, index, hasChildren):
+ """ Refresh one item. """
+ item = self.RefreshItemType(item, index)
+ self.RefreshItemText(item, index)
+ self.RefreshColumns(item, index)
+ self.RefreshItemFont(item, index)
+ self.RefreshTextColour(item, index)
+ self.RefreshBackgroundColour(item, index)
+ self.RefreshItemImage(item, index, hasChildren)
+ self.RefreshCheckedState(item, index)
+ return item
+
+ def RefreshItemText(self, item, index):
+ self.__refreshAttribute(item, index, 'ItemText')
+
+ def RefreshColumns(self, item, index):
+ for columnIndex in range(1, self.GetColumnCount()):
+ self.__refreshAttribute(item, index, 'ItemText', columnIndex)
+
+ def RefreshItemFont(self, item, index):
+ self.__refreshAttribute(item, index, 'ItemFont')
+
+ def RefreshTextColour(self, item, index):
+ self.__refreshAttribute(item, index, 'ItemTextColour')
+
+ def RefreshBackgroundColour(self, item, index):
+ self.__refreshAttribute(item, index, 'ItemBackgroundColour')
+
+ def RefreshItemImage(self, item, index, hasChildren):
+ regularIcons = [wx.TreeItemIcon_Normal, wx.TreeItemIcon_Selected]
+ expandedIcons = [wx.TreeItemIcon_Expanded,
+ wx.TreeItemIcon_SelectedExpanded]
+ # Refresh images in first column:
+ for icon in regularIcons:
+ self.__refreshAttribute(item, index, 'ItemImage', icon)
+ for icon in expandedIcons:
+ if hasChildren:
+ imageIndex = self.OnGetItemImage(index, icon)
+ else:
+ imageIndex = -1
+ if self.GetItemImage(item, icon) != imageIndex or imageIndex == -1:
+ self.SetItemImage(item, imageIndex, icon)
+ # Refresh images in remaining columns, if any:
+ for columnIndex in range(1, self.GetColumnCount()):
+ for icon in regularIcons:
+ self.__refreshAttribute(item, index, 'ItemImage', icon,
+ columnIndex)
+
+ def RefreshItemType(self, item, index):
+ return self.__refreshAttribute(item, index, 'ItemType')
+
+ def RefreshCheckedState(self, item, index):
+ self.__refreshAttribute(item, index, 'ItemChecked')
+
+ def ChildIndices(self, itemIndex):
+ childrenCount = self.OnGetChildrenCount(itemIndex)
+ return [itemIndex + (childNumber,) for childNumber \
+ in range(childrenCount)]
+
+ def OnItemExpanding(self, event):
+ self.RefreshChildrenRecursively(event.GetItem())
+ event.Skip()
+
+ def OnItemCollapsed(self, event):
+ parent = self.GetItemParent(event.GetItem())
+ if not parent:
+ parent = self.GetRootItem()
+ self.RefreshChildrenRecursively(parent)
+ event.Skip()
+
+ def __refreshAttribute(self, item, index, attribute, *args):
+ """ Refresh the specified attribute if necessary. """
+ value = getattr(self, 'OnGet%s'%attribute)(index, *args)
+ if getattr(self, 'Get%s'%attribute)(item, *args) != value:
+ return getattr(self, 'Set%s'%attribute)(item, value, *args)
+ else:
+ return item
+
+
+class DragAndDrop(TreeAPIHarmonizer, TreeHelper):
+ """ This is a mixin class that can be used to easily implement
+ dragging and dropping of tree items. It can be mixed in with
+ wx.TreeCtrl, wx.gizmos.TreeListCtrl, or wx.lib.customtree.CustomTreeCtrl.
+
+ To use it derive a new class from this class and one of the tree
+ controls, e.g.::
+
+ class MyTree(DragAndDrop, wx.TreeCtrl):
+ # Other code here
+
+
+ You *must* implement OnDrop. OnDrop is called when the user has
+ dropped an item on top of another item. It's up to you to decide how
+ to handle the drop. If you are using this mixin together with the
+ VirtualTree mixin, it makes sense to rearrange your underlying data
+ and then call RefreshItems to let the virtual tree refresh itself. """
+
+ def __init__(self, *args, **kwargs):
+ kwargs['style'] = kwargs.get('style', wx.TR_DEFAULT_STYLE) | \
+ wx.TR_HIDE_ROOT
+ super(DragAndDrop, self).__init__(*args, **kwargs)
+ self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag)
+
+ def OnDrop(self, dropItem, dragItem):
+ """ This function must be overloaded in the derived class.
+ dragItem is the item being dragged by the user. dropItem is the
+ item dragItem is dropped upon. If the user doesn't drop dragItem
+ on another item, dropItem equals the (hidden) root item of the
+ tree control. """
+ raise NotImplementedError
+
+ def OnBeginDrag(self, event):
+ # We allow only one item to be dragged at a time, to keep it simple
+ self._dragItem = event.GetItem()
+ if self.IsValidDragItem(self._dragItem):
+ self.StartDragging()
+ event.Allow()
+ else:
+ event.Veto()
+
+ def OnEndDrag(self, event):
+ self.StopDragging()
+ dropTarget = event.GetItem()
+ if not dropTarget:
+ dropTarget = self.GetRootItem()
+ if self.IsValidDropTarget(dropTarget):
+ self.UnselectAll()
+ if dropTarget != self.GetRootItem():
+ self.SelectItem(dropTarget)
+ self.OnDrop(dropTarget, self._dragItem)
+
+ def OnDragging(self, event):
+ if not event.Dragging():
+ self.StopDragging()
+ return
+ item, flags, column = self.HitTest(wx.Point(event.GetX(), event.GetY()),
+ alwaysReturnColumn=True)
+ if not item:
+ item = self.GetRootItem()
+ if self.IsValidDropTarget(item):
+ self.SetCursorToDragging()
+ else:
+ self.SetCursorToDroppingImpossible()
+ if flags & wx.TREE_HITTEST_ONITEMBUTTON:
+ self.Expand(item)
+ if self.GetSelections() != [item]:
+ self.UnselectAll()
+ if item != self.GetRootItem():
+ self.SelectItem(item)
+ event.Skip()
+
+ def StartDragging(self):
+ self.GetMainWindow().Bind(wx.EVT_MOTION, self.OnDragging)
+ self.Bind(wx.EVT_TREE_END_DRAG, self.OnEndDrag)
+ self.SetCursorToDragging()
+
+ def StopDragging(self):
+ self.GetMainWindow().Unbind(wx.EVT_MOTION)
+ self.Unbind(wx.EVT_TREE_END_DRAG)
+ self.ResetCursor()
+ self.UnselectAll()
+ self.SelectItem(self._dragItem)
+
+ def SetCursorToDragging(self):
+ self.GetMainWindow().SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+
+ def SetCursorToDroppingImpossible(self):
+ self.GetMainWindow().SetCursor(wx.StockCursor(wx.CURSOR_NO_ENTRY))
+
+ def ResetCursor(self):
+ self.GetMainWindow().SetCursor(wx.NullCursor)
+
+ def IsValidDropTarget(self, dropTarget):
+ if dropTarget:
+ allChildren = self.GetItemChildren(self._dragItem, recursively=True)
+ parent = self.GetItemParent(self._dragItem)
+ return dropTarget not in [self._dragItem, parent] + allChildren
+ else:
+ return True
+
+ def IsValidDragItem(self, dragItem):
+ return dragItem and dragItem != self.GetRootItem()
+
+
+class ExpansionState(TreeAPIHarmonizer, TreeHelper):
+ """ This is a mixin class that can be used to save and restore
+ the expansion state (i.e. which items are expanded and which items
+ are collapsed) of a tree. It can be mixed in with wx.TreeCtrl,
+ wx.gizmos.TreeListCtrl, or wx.lib.customtree.CustomTreeCtrl.
+
+ To use it derive a new class from this class and one of the tree
+ controls, e.g.::
+
+ class MyTree(ExpansionState, wx.TreeCtrl):
+ # Other code here
+
+
+ By default, ExpansionState uses the position of tree items in the tree
+ to keep track of which items are expanded. This should be sufficient
+ for the simple scenario where you save the expansion state of the tree
+ when the user closes the application or file so that you can restore
+ the expansion state when the user start the application or loads that
+ file for the next session.
+
+ If you need to add or remove items between the moments of saving and
+ restoring the expansion state (e.g. in case of a multi-user application)
+ you must override GetItemIdentity so that saving and loading of the
+ expansion doesn't depend on the position of items in the tree, but
+ rather on some more stable characteristic of the underlying domain
+ object, e.g. a social security number in case of persons or an isbn
+ number in case of books. """
+
+ def GetItemIdentity(self, item):
+ """ Return a hashable object that represents the identity of the
+ item. By default this returns the position of the item in the
+ tree. You may want to override this to return the item label
+ (if you know that labels are unique and don't change), or return
+ something that represents the underlying domain object, e.g.
+ a database key. """
+ return self.GetIndexOfItem(item)
+
+ def GetExpansionState(self):
+ """ GetExpansionState() -> list of expanded items. Expanded items
+ are coded as determined by the result of GetItemIdentity(item). """
+ root = self.GetRootItem()
+ if not root:
+ return []
+ if self.HasFlag(wx.TR_HIDE_ROOT):
+ return self.GetExpansionStateOfChildren(root)
+ else:
+ return self.GetExpansionStateOfItem(root)
+
+ def SetExpansionState(self, listOfExpandedItems):
+ """ SetExpansionState(listOfExpandedItems). Expands all tree items
+ whose identity, as determined by GetItemIdentity(item), is present
+ in the list and collapses all other tree items. """
+ root = self.GetRootItem()
+ if not root:
+ return
+ if self.HasFlag(wx.TR_HIDE_ROOT):
+ self.SetExpansionStateOfChildren(listOfExpandedItems, root)
+ else:
+ self.SetExpansionStateOfItem(listOfExpandedItems, root)
+
+ ExpansionState = property(GetExpansionState, SetExpansionState)
+
+ def GetExpansionStateOfItem(self, item):
+ listOfExpandedItems = []
+ if self.IsExpanded(item):
+ listOfExpandedItems.append(self.GetItemIdentity(item))
+ listOfExpandedItems.extend(self.GetExpansionStateOfChildren(item))
+ return listOfExpandedItems
+
+ def GetExpansionStateOfChildren(self, item):
+ listOfExpandedItems = []
+ for child in self.GetItemChildren(item):
+ listOfExpandedItems.extend(self.GetExpansionStateOfItem(child))
+ return listOfExpandedItems
+
+ def SetExpansionStateOfItem(self, listOfExpandedItems, item):
+ if self.GetItemIdentity(item) in listOfExpandedItems:
+ self.Expand(item)
+ self.SetExpansionStateOfChildren(listOfExpandedItems, item)
+ else:
+ self.Collapse(item)
+
+ def SetExpansionStateOfChildren(self, listOfExpandedItems, item):
+ for child in self.GetItemChildren(item):
+ self.SetExpansionStateOfItem(listOfExpandedItems, child)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/msgpanel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/msgpanel.py
new file mode 100644
index 0000000..a69b1eb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/msgpanel.py
@@ -0,0 +1,96 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.msgpanel
+# Purpose: The MessagePanel class (Note: this class used to live
+# in the demo's Main module.)
+#
+# Author: Robin Dunn
+#
+# Created: 19-Oct-2009
+# RCS-ID: $Id: $
+# Copyright: (c) 2009 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""
+MessagePanel is a simple panel class for displaying a message, very
+much like how wx.MessageDialog works, including the icon flags.
+"""
+
+import wx
+
+#----------------------------------------------------------------------
+
+class MessagePanel(wx.Panel):
+ def __init__(self, parent, message, caption='', flags=0):
+ wx.Panel.__init__(self, parent)
+
+ # Make widgets
+ icon = None
+ if flags:
+ artid = None
+ if flags & wx.ICON_EXCLAMATION:
+ artid = wx.ART_WARNING
+ elif flags & wx.ICON_ERROR:
+ artid = wx.ART_ERROR
+ elif flags & wx.ICON_QUESTION:
+ artid = wx.ART_QUESTION
+ elif flags & wx.ICON_INFORMATION:
+ artid = wx.ART_INFORMATION
+
+ if artid is not None:
+ bmp = wx.ArtProvider.GetBitmap(artid, wx.ART_MESSAGE_BOX, (32,32))
+ icon = wx.StaticBitmap(self, -1, bmp)
+
+ if not icon:
+ icon = (32,32) # make a spacer instead
+
+ if caption:
+ caption = wx.StaticText(self, -1, caption)
+ caption.SetFont(wx.Font(24, wx.SWISS, wx.NORMAL, wx.BOLD))
+
+ message = wx.StaticText(self, -1, message)
+
+ # add to sizers for layout
+ tbox = wx.BoxSizer(wx.VERTICAL)
+ if caption:
+ tbox.Add(caption)
+ tbox.Add((10,10))
+ tbox.Add(message)
+
+ hbox = wx.BoxSizer(wx.HORIZONTAL)
+ hbox.Add((10,10), 1)
+ hbox.Add(icon)
+ hbox.Add((10,10))
+ hbox.Add(tbox)
+ hbox.Add((10,10), 1)
+
+ box = wx.BoxSizer(wx.VERTICAL)
+ box.Add((10,10), 1)
+ box.Add(hbox, 0, wx.EXPAND)
+ box.Add((10,10), 2)
+
+ self.SetSizer(box)
+ self.Fit()
+
+
+#----------------------------------------------------------------------
+
+
+if __name__ == '__main__':
+ app = wx.App(redirect=False)
+ frm = wx.Frame(None, title='MessagePanel Test')
+ pnl = MessagePanel(frm, flags=wx.ICON_EXCLAMATION,
+ caption="Please stand by...",
+ message="""\
+This is a test. This is a test of the emergency broadcast
+system. Had this been a real emergency, you would have
+already been reduced to a pile of radioactive cinders and
+wondering why 'duck and cover' didn't help.
+
+This is only a test...""")
+ frm.Sizer = wx.BoxSizer()
+ frm.Sizer.Add(pnl, 1, wx.EXPAND)
+ frm.Fit()
+ frm.Show()
+ app.MainLoop()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/multisash.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/multisash.py
new file mode 100644
index 0000000..3f6d7fc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/multisash.py
@@ -0,0 +1,746 @@
+#----------------------------------------------------------------------
+# Name: multisash
+# Purpose: Multi Sash control
+#
+# Author: Gerrit van Dyk
+#
+# Created: 2002/11/20
+# Version: 0.1
+# RCS-ID: $Id$
+# License: wxWindows license
+#----------------------------------------------------------------------
+# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxMultiSash -> MultiSash
+# o wxMultiSplit -> MultiSplit
+# o wxMultiViewLeaf -> MultiViewLeaf
+#
+
+import wx
+
+MV_HOR = 0
+MV_VER = not MV_HOR
+
+SH_SIZE = 5
+CR_SIZE = SH_SIZE * 3
+
+#----------------------------------------------------------------------
+
+class MultiSash(wx.Window):
+ def __init__(self, *_args,**_kwargs):
+ apply(wx.Window.__init__,(self,) + _args,_kwargs)
+ self._defChild = EmptyChild
+ self.child = MultiSplit(self,self,(0,0),self.GetSize())
+ self.Bind(wx.EVT_SIZE,self.OnMultiSize)
+
+ def SetDefaultChildClass(self,childCls):
+ self._defChild = childCls
+ self.child.DefaultChildChanged()
+
+ def OnMultiSize(self,evt):
+ self.child.SetSize(self.GetSize())
+
+ def UnSelect(self):
+ self.child.UnSelect()
+
+ def Clear(self):
+ old = self.child
+ self.child = MultiSplit(self,self,(0,0),self.GetSize())
+ old.Destroy()
+ self.child.OnSize(None)
+
+ def GetSaveData(self):
+ saveData = {}
+ saveData['_defChild_class'] = self._defChild.__name__
+ saveData['_defChild_mod'] = self._defChild.__module__
+ saveData['child'] = self.child.GetSaveData()
+ return saveData
+
+ def SetSaveData(self,data):
+ mod = data['_defChild_mod']
+ dChild = mod + '.' + data['_defChild_class']
+ exec 'import %s' % mod
+ self._defChild = eval(dChild)
+ old = self.child
+ self.child = MultiSplit(self,self,wx.Point(0,0),self.GetSize())
+ self.child.SetSaveData(data['child'])
+ old.Destroy()
+ self.OnMultiSize(None)
+ self.child.OnSize(None)
+
+
+#----------------------------------------------------------------------
+
+
+class MultiSplit(wx.Window):
+ def __init__(self,multiView,parent,pos,size,view1 = None):
+ wx.Window.__init__(self,id = -1,parent = parent,pos = pos,size = size,
+ style = wx.CLIP_CHILDREN)
+ self.multiView = multiView
+ self.view2 = None
+ if view1:
+ self.view1 = view1
+ self.view1.Reparent(self)
+ self.view1.MoveXY(0,0)
+ else:
+ self.view1 = MultiViewLeaf(self.multiView,self,
+ (0,0),self.GetSize())
+ self.direction = None
+
+ self.Bind(wx.EVT_SIZE,self.OnSize)
+
+ def GetSaveData(self):
+ saveData = {}
+ if self.view1:
+ saveData['view1'] = self.view1.GetSaveData()
+ if isinstance(self.view1,MultiSplit):
+ saveData['view1IsSplit'] = 1
+ if self.view2:
+ saveData['view2'] = self.view2.GetSaveData()
+ if isinstance(self.view2,MultiSplit):
+ saveData['view2IsSplit'] = 1
+ saveData['direction'] = self.direction
+ v1,v2 = self.GetPosition()
+ saveData['x'] = v1
+ saveData['y'] = v2
+ v1,v2 = self.GetSize()
+ saveData['w'] = v1
+ saveData['h'] = v2
+ return saveData
+
+ def SetSaveData(self,data):
+ self.direction = data['direction']
+ self.SetDimensions(int(data['x']), int(data['y']), int(data['w']), int(data['h']))
+ v1Data = data.get('view1',None)
+ if v1Data:
+ isSplit = data.get('view1IsSplit',None)
+ old = self.view1
+ if isSplit:
+ self.view1 = MultiSplit(self.multiView,self,
+ (0,0),self.GetSize())
+ else:
+ self.view1 = MultiViewLeaf(self.multiView,self,
+ (0,0),self.GetSize())
+ self.view1.SetSaveData(v1Data)
+ if old:
+ old.Destroy()
+ v2Data = data.get('view2',None)
+ if v2Data:
+ isSplit = data.get('view2IsSplit',None)
+ old = self.view2
+ if isSplit:
+ self.view2 = MultiSplit(self.multiView,self,
+ (0,0),self.GetSize())
+ else:
+ self.view2 = MultiViewLeaf(self.multiView,self,
+ (0,0),self.GetSize())
+ self.view2.SetSaveData(v2Data)
+ if old:
+ old.Destroy()
+ if self.view1:
+ self.view1.OnSize(None)
+ if self.view2:
+ self.view2.OnSize(None)
+
+ def UnSelect(self):
+ if self.view1:
+ self.view1.UnSelect()
+ if self.view2:
+ self.view2.UnSelect()
+
+ def DefaultChildChanged(self):
+ if not self.view2:
+ self.view1.DefaultChildChanged()
+
+ def AddLeaf(self,direction,caller,pos):
+ if self.view2:
+ if caller == self.view1:
+ self.view1 = MultiSplit(self.multiView,self,
+ caller.GetPosition(),
+ caller.GetSize(),
+ caller)
+ self.view1.AddLeaf(direction,caller,pos)
+ else:
+ self.view2 = MultiSplit(self.multiView,self,
+ caller.GetPosition(),
+ caller.GetSize(),
+ caller)
+ self.view2.AddLeaf(direction,caller,pos)
+ else:
+ self.direction = direction
+ w,h = self.GetSize()
+ if direction == MV_HOR:
+ x,y = (pos,0)
+ w1,h1 = (w-pos,h)
+ w2,h2 = (pos,h)
+ else:
+ x,y = (0,pos)
+ w1,h1 = (w,h-pos)
+ w2,h2 = (w,pos)
+ self.view2 = MultiViewLeaf(self.multiView, self, (x,y), (w1,h1))
+ self.view1.SetSize((w2,h2))
+ self.view2.OnSize(None)
+
+ def DestroyLeaf(self,caller):
+ if not self.view2: # We will only have 2 windows if
+ return # we need to destroy any
+ parent = self.GetParent() # Another splitview
+ if parent == self.multiView: # We'r at the root
+ if caller == self.view1:
+ old = self.view1
+ self.view1 = self.view2
+ self.view2 = None
+ old.Destroy()
+ else:
+ self.view2.Destroy()
+ self.view2 = None
+ self.view1.SetSize(self.GetSize())
+ self.view1.Move(self.GetPosition())
+ else:
+ w,h = self.GetSize()
+ x,y = self.GetPosition()
+ if caller == self.view1:
+ if self == parent.view1:
+ parent.view1 = self.view2
+ else:
+ parent.view2 = self.view2
+ self.view2.Reparent(parent)
+ self.view2.SetDimensions(x,y,w,h)
+ else:
+ if self == parent.view1:
+ parent.view1 = self.view1
+ else:
+ parent.view2 = self.view1
+ self.view1.Reparent(parent)
+ self.view1.SetDimensions(x,y,w,h)
+ self.view1 = None
+ self.view2 = None
+ self.Destroy()
+
+ def CanSize(self,side,view):
+ if self.SizeTarget(side,view):
+ return True
+ return False
+
+ def SizeTarget(self,side,view):
+ if self.direction == side and self.view2 and view == self.view1:
+ return self
+ parent = self.GetParent()
+ if parent != self.multiView:
+ return parent.SizeTarget(side,self)
+ return None
+
+ def SizeLeaf(self,leaf,pos,side):
+ if self.direction != side:
+ return
+ if not (self.view1 and self.view2):
+ return
+ if pos < 10: return
+ w,h = self.GetSize()
+ if side == MV_HOR:
+ if pos > w - 10: return
+ else:
+ if pos > h - 10: return
+ if side == MV_HOR:
+ self.view1.SetDimensions(0,0,pos,h)
+ self.view2.SetDimensions(pos,0,w-pos,h)
+ else:
+ self.view1.SetDimensions(0,0,w,pos)
+ self.view2.SetDimensions(0,pos,w,h-pos)
+
+ def OnSize(self,evt):
+ if not self.view2:
+ self.view1.SetSize(self.GetSize())
+ self.view1.OnSize(None)
+ return
+ v1w,v1h = self.view1.GetSize()
+ v2w,v2h = self.view2.GetSize()
+ v1x,v1y = self.view1.GetPosition()
+ v2x,v2y = self.view2.GetPosition()
+ w,h = self.GetSize()
+
+ if v1x != v2x:
+ ratio = float(w) / float((v1w + v2w))
+ v1w *= ratio
+ v2w = w - v1w
+ v2x = v1w
+ else:
+ v1w = v2w = w
+
+ if v1y != v2y:
+ ratio = float(h) / float((v1h + v2h))
+ v1h *= ratio
+ v2h = h - v1h
+ v2y = v1h
+ else:
+ v1h = v2h = h
+
+ self.view1.SetDimensions(int(v1x), int(v1y), int(v1w), int(v1h))
+ self.view2.SetDimensions(int(v2x), int(v2y), int(v2w), int(v2h))
+ self.view1.OnSize(None)
+ self.view2.OnSize(None)
+
+
+#----------------------------------------------------------------------
+
+
+class MultiViewLeaf(wx.Window):
+ def __init__(self,multiView,parent,pos,size):
+ wx.Window.__init__(self,id = -1,parent = parent,pos = pos,size = size,
+ style = wx.CLIP_CHILDREN)
+ self.multiView = multiView
+
+ self.sizerHor = MultiSizer(self,MV_HOR)
+ self.sizerVer = MultiSizer(self,MV_VER)
+ self.creatorHor = MultiCreator(self,MV_HOR)
+ self.creatorVer = MultiCreator(self,MV_VER)
+ self.detail = MultiClient(self,multiView._defChild)
+ self.closer = MultiCloser(self)
+
+ self.Bind(wx.EVT_SIZE,self.OnSize)
+
+ self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE))
+
+
+ def GetSaveData(self):
+ saveData = {}
+ saveData['detailClass_class'] = self.detail.child.__class__.__name__
+ saveData['detailClass_mod'] = self.detail.child.__module__
+ if hasattr(self.detail.child,'GetSaveData'):
+ attr = getattr(self.detail.child,'GetSaveData')
+ if callable(attr):
+ dData = attr()
+ if dData:
+ saveData['detail'] = dData
+ v1,v2 = self.GetPosition()
+ saveData['x'] = v1
+ saveData['y'] = v2
+ v1,v2 = self.GetSize()
+ saveData['w'] = v1
+ saveData['h'] = v2
+ return saveData
+
+ def SetSaveData(self,data):
+ mod = data['detailClass_mod']
+ dChild = mod + '.' + data['detailClass_class']
+ exec 'import %s' % mod
+ detClass = eval(dChild)
+ self.SetDimensions(data['x'],data['y'],data['w'],data['h'])
+ old = self.detail
+ self.detail = MultiClient(self,detClass)
+ dData = data.get('detail',None)
+ if dData:
+ if hasattr(self.detail.child,'SetSaveData'):
+ attr = getattr(self.detail.child,'SetSaveData')
+ if callable(attr):
+ attr(dData)
+ old.Destroy()
+ self.detail.OnSize(None)
+
+ def UnSelect(self):
+ self.detail.UnSelect()
+
+ def DefaultChildChanged(self):
+ self.detail.SetNewChildCls(self.multiView._defChild)
+
+ def AddLeaf(self,direction,pos):
+ if pos < 10: return
+ w,h = self.GetSize()
+ if direction == MV_VER:
+ if pos > h - 10: return
+ else:
+ if pos > w - 10: return
+ self.GetParent().AddLeaf(direction,self,pos)
+
+ def DestroyLeaf(self):
+ self.GetParent().DestroyLeaf(self)
+
+ def SizeTarget(self,side):
+ return self.GetParent().SizeTarget(side,self)
+
+ def CanSize(self,side):
+ return self.GetParent().CanSize(side,self)
+
+ def OnSize(self,evt):
+ def doresize():
+ try:
+ self.sizerHor.OnSize(evt)
+ self.sizerVer.OnSize(evt)
+ self.creatorHor.OnSize(evt)
+ self.creatorVer.OnSize(evt)
+ self.detail.OnSize(evt)
+ self.closer.OnSize(evt)
+ except:
+ pass
+ wx.CallAfter(doresize)
+
+#----------------------------------------------------------------------
+
+
+class MultiClient(wx.Window):
+ def __init__(self,parent,childCls):
+ w,h = self.CalcSize(parent)
+ wx.Window.__init__(self,id = -1,parent = parent,
+ pos = (0,0),
+ size = (w,h),
+ style = wx.CLIP_CHILDREN | wx.SUNKEN_BORDER)
+ self.child = childCls(self)
+ self.child.MoveXY(2,2)
+ self.normalColour = self.GetBackgroundColour()
+ self.selected = False
+
+ self.Bind(wx.EVT_SET_FOCUS,self.OnSetFocus)
+ self.Bind(wx.EVT_CHILD_FOCUS,self.OnChildFocus)
+
+ def UnSelect(self):
+ if self.selected:
+ self.selected = False
+ self.SetBackgroundColour(self.normalColour)
+ self.Refresh()
+
+ def Select(self):
+ self.GetParent().multiView.UnSelect()
+ self.selected = True
+ self.SetBackgroundColour(wx.Colour(255,255,0)) # Yellow
+ self.Refresh()
+
+ def CalcSize(self,parent):
+ w,h = parent.GetSize()
+ w -= SH_SIZE
+ h -= SH_SIZE
+ return (w,h)
+
+ def OnSize(self,evt):
+ w,h = self.CalcSize(self.GetParent())
+ self.SetDimensions(0,0,w,h)
+ w,h = self.GetClientSize()
+ self.child.SetSize((w-4,h-4))
+
+ def SetNewChildCls(self,childCls):
+ if self.child:
+ self.child.Destroy()
+ self.child = None
+ self.child = childCls(self)
+ self.child.MoveXY(2,2)
+
+ def OnSetFocus(self,evt):
+ self.Select()
+
+ def OnChildFocus(self,evt):
+ self.OnSetFocus(evt)
+## from Funcs import FindFocusedChild
+## child = FindFocusedChild(self)
+## child.Bind(wx.EVT_KILL_FOCUS,self.OnChildKillFocus)
+
+
+#----------------------------------------------------------------------
+
+
+class MultiSizer(wx.Window):
+ def __init__(self,parent,side):
+ self.side = side
+ x,y,w,h = self.CalcSizePos(parent)
+ wx.Window.__init__(self,id = -1,parent = parent,
+ pos = (x,y),
+ size = (w,h),
+ style = wx.CLIP_CHILDREN)
+
+ self.px = None # Previous X
+ self.py = None # Previous Y
+ self.isDrag = False # In Dragging
+ self.dragTarget = None # View being sized
+
+ self.Bind(wx.EVT_LEAVE_WINDOW,self.OnLeave)
+ self.Bind(wx.EVT_ENTER_WINDOW,self.OnEnter)
+ self.Bind(wx.EVT_MOTION,self.OnMouseMove)
+ self.Bind(wx.EVT_LEFT_DOWN,self.OnPress)
+ self.Bind(wx.EVT_LEFT_UP,self.OnRelease)
+
+ self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE))
+
+
+ def CalcSizePos(self,parent):
+ pw,ph = parent.GetSize()
+ if self.side == MV_HOR:
+ x = CR_SIZE + 2
+ y = ph - SH_SIZE
+ w = pw - CR_SIZE - SH_SIZE - 2
+ h = SH_SIZE
+ else:
+ x = pw - SH_SIZE
+ y = CR_SIZE + 2 + SH_SIZE
+ w = SH_SIZE
+ h = ph - CR_SIZE - SH_SIZE - 4 - SH_SIZE # For Closer
+ return (x,y,w,h)
+
+ def OnSize(self,evt):
+ x,y,w,h = self.CalcSizePos(self.GetParent())
+ self.SetDimensions(x,y,w,h)
+
+ def OnLeave(self,evt):
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+
+ def OnEnter(self,evt):
+ if not self.GetParent().CanSize(not self.side):
+ return
+ if self.side == MV_HOR:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_SIZENS))
+ else:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_SIZEWE))
+
+ def OnMouseMove(self,evt):
+ if self.isDrag:
+ DrawSash(self.dragTarget,self.px,self.py,self.side)
+ self.px,self.py = self.ClientToScreenXY(evt.x, evt.y)
+ self.px,self.py = self.dragTarget.ScreenToClientXY(self.px,self.py)
+ DrawSash(self.dragTarget,self.px,self.py,self.side)
+ else:
+ evt.Skip()
+
+ def OnPress(self,evt):
+ self.dragTarget = self.GetParent().SizeTarget(not self.side)
+ if self.dragTarget:
+ self.isDrag = True
+ self.px,self.py = self.ClientToScreenXY(evt.x, evt.y)
+ self.px,self.py = self.dragTarget.ScreenToClientXY(self.px,self.py)
+ DrawSash(self.dragTarget,self.px,self.py,self.side)
+ self.CaptureMouse()
+ else:
+ evt.Skip()
+
+ def OnRelease(self,evt):
+ if self.isDrag:
+ DrawSash(self.dragTarget,self.px,self.py,self.side)
+ self.ReleaseMouse()
+ self.isDrag = False
+ if self.side == MV_HOR:
+ self.dragTarget.SizeLeaf(self.GetParent(),
+ self.py,not self.side)
+ else:
+ self.dragTarget.SizeLeaf(self.GetParent(),
+ self.px,not self.side)
+ self.dragTarget = None
+ else:
+ evt.Skip()
+
+#----------------------------------------------------------------------
+
+
+class MultiCreator(wx.Window):
+ def __init__(self,parent,side):
+ self.side = side
+ x,y,w,h = self.CalcSizePos(parent)
+ wx.Window.__init__(self,id = -1,parent = parent,
+ pos = (x,y),
+ size = (w,h),
+ style = wx.CLIP_CHILDREN)
+
+ self.px = None # Previous X
+ self.py = None # Previous Y
+ self.isDrag = False # In Dragging
+
+ self.Bind(wx.EVT_LEAVE_WINDOW,self.OnLeave)
+ self.Bind(wx.EVT_ENTER_WINDOW,self.OnEnter)
+ self.Bind(wx.EVT_MOTION,self.OnMouseMove)
+ self.Bind(wx.EVT_LEFT_DOWN,self.OnPress)
+ self.Bind(wx.EVT_LEFT_UP,self.OnRelease)
+ self.Bind(wx.EVT_PAINT,self.OnPaint)
+
+ def CalcSizePos(self,parent):
+ pw,ph = parent.GetSize()
+ if self.side == MV_HOR:
+ x = 2
+ y = ph - SH_SIZE
+ w = CR_SIZE
+ h = SH_SIZE
+ else:
+ x = pw - SH_SIZE
+ y = 4 + SH_SIZE # Make provision for closer
+ w = SH_SIZE
+ h = CR_SIZE
+ return (x,y,w,h)
+
+ def OnSize(self,evt):
+ x,y,w,h = self.CalcSizePos(self.GetParent())
+ self.SetDimensions(x,y,w,h)
+
+ def OnLeave(self,evt):
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+
+ def OnEnter(self,evt):
+ if self.side == MV_HOR:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+ else:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_POINT_LEFT))
+
+ def OnMouseMove(self,evt):
+ if self.isDrag:
+ parent = self.GetParent()
+ DrawSash(parent,self.px,self.py,self.side)
+ self.px,self.py = self.ClientToScreenXY(evt.x, evt.y)
+ self.px,self.py = parent.ScreenToClientXY(self.px,self.py)
+ DrawSash(parent,self.px,self.py,self.side)
+ else:
+ evt.Skip()
+
+ def OnPress(self,evt):
+ self.isDrag = True
+ parent = self.GetParent()
+ self.px,self.py = self.ClientToScreenXY(evt.x, evt.y)
+ self.px,self.py = parent.ScreenToClientXY(self.px,self.py)
+ DrawSash(parent,self.px,self.py,self.side)
+ self.CaptureMouse()
+
+ def OnRelease(self,evt):
+ if self.isDrag:
+ parent = self.GetParent()
+ DrawSash(parent,self.px,self.py,self.side)
+ self.ReleaseMouse()
+ self.isDrag = False
+
+ if self.side == MV_HOR:
+ parent.AddLeaf(MV_VER,self.py)
+ else:
+ parent.AddLeaf(MV_HOR,self.px)
+ else:
+ evt.Skip()
+
+ def OnPaint(self,evt):
+ dc = wx.PaintDC(self)
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour(),wx.SOLID))
+ dc.Clear()
+
+ highlight = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNHIGHLIGHT), 1, wx.SOLID)
+ shadow = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW), 1, wx.SOLID)
+ black = wx.Pen(wx.BLACK,1,wx.SOLID)
+ w,h = self.GetSize()
+ w -= 1
+ h -= 1
+
+ # Draw outline
+ dc.SetPen(highlight)
+ dc.DrawLine(0,0, 0,h)
+ dc.DrawLine(0,0, w,0)
+ dc.SetPen(black)
+ dc.DrawLine(0,h, w+1,h)
+ dc.DrawLine(w,0, w,h)
+ dc.SetPen(shadow)
+ dc.DrawLine(w-1,2, w-1,h)
+
+#----------------------------------------------------------------------
+
+
+class MultiCloser(wx.Window):
+ def __init__(self,parent):
+ x,y,w,h = self.CalcSizePos(parent)
+ wx.Window.__init__(self,id = -1,parent = parent,
+ pos = (x,y),
+ size = (w,h),
+ style = wx.CLIP_CHILDREN)
+
+ self.down = False
+ self.entered = False
+
+ self.Bind(wx.EVT_LEFT_DOWN,self.OnPress)
+ self.Bind(wx.EVT_LEFT_UP,self.OnRelease)
+ self.Bind(wx.EVT_PAINT,self.OnPaint)
+ self.Bind(wx.EVT_LEAVE_WINDOW,self.OnLeave)
+ self.Bind(wx.EVT_ENTER_WINDOW,self.OnEnter)
+
+ def OnLeave(self,evt):
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ self.entered = False
+
+ def OnEnter(self,evt):
+ self.SetCursor(wx.StockCursor(wx.CURSOR_BULLSEYE))
+ self.entered = True
+
+ def OnPress(self,evt):
+ self.down = True
+ evt.Skip()
+
+ def OnRelease(self,evt):
+ if self.down and self.entered:
+ self.GetParent().DestroyLeaf()
+ else:
+ evt.Skip()
+ self.down = False
+
+ def OnPaint(self,evt):
+ dc = wx.PaintDC(self)
+ dc.SetBackground(wx.Brush(wx.RED,wx.SOLID))
+ dc.Clear()
+
+ def CalcSizePos(self,parent):
+ pw,ph = parent.GetSize()
+ x = pw - SH_SIZE
+ w = SH_SIZE
+ h = SH_SIZE + 2
+ y = 1
+ return (x,y,w,h)
+
+ def OnSize(self,evt):
+ x,y,w,h = self.CalcSizePos(self.GetParent())
+ self.SetDimensions(x,y,w,h)
+
+
+#----------------------------------------------------------------------
+
+
+class EmptyChild(wx.Window):
+ def __init__(self,parent):
+ wx.Window.__init__(self,parent,-1, style = wx.CLIP_CHILDREN)
+
+
+#----------------------------------------------------------------------
+
+
+def DrawSash(win,x,y,direction):
+ dc = wx.ScreenDC()
+ dc.StartDrawingOnTopWin(win)
+ bmp = wx.EmptyBitmap(8,8)
+ bdc = wx.MemoryDC()
+ bdc.SelectObject(bmp)
+ bdc.DrawRectangle(-1,-1, 10,10)
+ for i in range(8):
+ for j in range(8):
+ if ((i + j) & 1):
+ bdc.DrawPoint(i,j)
+
+ brush = wx.Brush(wx.Colour(0,0,0))
+ brush.SetStipple(bmp)
+
+ dc.SetBrush(brush)
+ dc.SetLogicalFunction(wx.XOR)
+
+ body_w,body_h = win.GetClientSize()
+
+ if y < 0:
+ y = 0
+ if y > body_h:
+ y = body_h
+ if x < 0:
+ x = 0
+ if x > body_w:
+ x = body_w
+
+ if direction == MV_HOR:
+ x = 0
+ else:
+ y = 0
+
+ x,y = win.ClientToScreenXY(x,y)
+
+ w = body_w
+ h = body_h
+
+ if direction == MV_HOR:
+ dc.DrawRectangle(x,y-2, w,4)
+ else:
+ dc.DrawRectangle(x-2,y, 4,h)
+
+ dc.EndDrawingOnTop()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mvctree.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mvctree.py
new file mode 100644
index 0000000..cb24e59
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/mvctree.py
@@ -0,0 +1,1150 @@
+# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o I'm a little nervous about some of it though.
+#
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxTreeModel -> TreeModel
+# o wxMVCTree -> MVCTree
+# o wxMVCTreeEvent -> MVCTreeEvent
+# o wxMVCTreeNotifyEvent -> MVCTreeNotifyEvent
+#
+
+"""
+MVCTree is a control which handles hierarchical data. It is constructed
+in model-view-controller architecture, so the display of that data, and
+the content of the data can be changed greatly without affecting the other parts.
+
+MVCTree actually is even more configurable than MVC normally implies, because
+almost every aspect of it is pluggable:
+
+* MVCTree - Overall controller, and the window that actually gets placed in the GUI.
+
+ * Painter - Paints the control. The 'view' part of MVC.
+
+ * NodePainter - Paints just the nodes
+ * LinePainter - Paints just the lines between the nodes
+ * TextConverter - Figures out what text to print for each node
+
+ * Editor - Edits the contents of a node, if the model is editable.
+ * LayoutEngine - Determines initial placement of nodes
+ * Transform - Adjusts positions of nodes for movement or special effects.
+ * TreeModel - Contains the data which the rest of the control acts on. The 'model' part of MVC.
+
+
+Author/Maintainer - Bryn Keller <xoltar@starship.python.net>
+
+
+.. note::
+
+ This module is *not* supported in any way. Use it however you
+ wish, but be warned that dealing with any consequences is
+ entirly up to you.
+ --Robin
+"""
+
+#------------------------------------------------------------------------
+import os
+import sys
+import traceback
+import warnings
+
+import wx
+#------------------------------------------------------------------------
+
+warningmsg = r"""\
+
+################################################\
+# This module is not supported in any way! |
+# |
+# See cource code for wx.lib.mvctree for more |
+# information. |
+################################################/
+
+"""
+
+warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
+#------------------------------------------------------------------------
+
+class MVCTreeNode:
+ """
+ Used internally by MVCTree to manage its data. Contains information about
+ screen placement, the actual data associated with it, and more. These are
+ the nodes passed to all the other helper parts to do their work with.
+ """
+ def __init__(self, data=None, parent = None, kids = None, x = 0, y = 0):
+ self.x = 0
+ self.y = 0
+ self.projx = 0
+ self.projy = 0
+ self.parent = parent
+ self.kids = kids
+ if self.kids is None:
+ self.kids = []
+ self.data = data
+ self.expanded = False
+ self.selected = False
+ self.built = False
+ self.scale = 0
+
+ def GetChildren(self):
+ return self.kids
+
+ def GetParent(self):
+ return self.parent
+
+ def Remove(self, node):
+ try:
+ self.kids.remove(node)
+ except:
+ pass
+ def Add(self, node):
+ self.kids.append(node)
+ node.SetParent(self)
+
+ def SetParent(self, parent):
+ if self.parent and not (self.parent is parent):
+ self.parent.Remove(self)
+ self.parent = parent
+ def __str__(self):
+ return "Node: " + str(self.data) + " (" + str(self.x) + ", " + str(self.y) + ")"
+ def __repr__(self):
+ return str(self.data)
+ def GetTreeString(self, tabs=0):
+ s = tabs * '\t' + str(self) + '\n'
+ for kid in self.kids:
+ s = s + kid.GetTreeString(tabs + 1)
+ return s
+
+
+class Editor:
+ def __init__(self, tree):
+ self.tree = tree
+ def Edit(self, node):
+ raise NotImplementedError
+ def EndEdit(self, node, commit):
+ raise NotImplementedError
+ def CanEdit(self, node):
+ raise NotImplementedError
+
+class LayoutEngine:
+ """
+ Interface for layout engines.
+ """
+ def __init__(self, tree):
+ self.tree = tree
+ def Layout(self, node):
+ raise NotImplementedError
+ def GetNodeList(self):
+ raise NotImplementedError
+
+class Transform:
+ """
+ Transform interface.
+ """
+ def __init__(self, tree):
+ self.tree = tree
+ def Transform(self, node, offset, rotation):
+ """
+ This method should only change the projx and projy attributes of
+ the node. These represent the position of the node as it should
+ be drawn on screen. Adjusting the x and y attributes can and
+ should cause havoc.
+ """
+ raise NotImplementedError
+
+ def GetSize(self):
+ """
+ Returns the size of the entire tree as laid out and transformed
+ as a tuple
+ """
+ raise NotImplementedError
+
+class Painter:
+ """
+ This is the interface that MVCTree expects from painters. All painters should
+ be Painter subclasses.
+ """
+ def __init__(self, tree):
+ self.tree = tree
+ self.textcolor = wx.NamedColour("BLACK")
+ self.bgcolor = wx.NamedColour("WHITE")
+ self.fgcolor = wx.NamedColour("BLUE")
+ self.linecolor = wx.NamedColour("GREY")
+ self.font = wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)
+ self.bmp = None
+
+ def GetFont(self):
+ return self.font
+
+ def SetFont(self, font):
+ self.font = font
+ self.tree.Refresh()
+ def GetBuffer(self):
+ return self.bmp
+ def ClearBuffer(self):
+ self.bmp = None
+ def Paint(self, dc, node, doubleBuffered=1, paintBackground=1):
+ raise NotImplementedError
+ def GetTextColour(self):
+ return self.textcolor
+ def SetTextColour(self, color):
+ self.textcolor = color
+ self.textbrush = wx.Brush(color)
+ self.textpen = wx.Pen(color, 1, wx.SOLID)
+ def GetBackgroundColour(self):
+ return self.bgcolor
+ def SetBackgroundColour(self, color):
+ self.bgcolor = color
+ self.bgbrush = wx.Brush(color)
+ self.bgpen = wx.Pen(color, 1, wx.SOLID)
+ def GetForegroundColour(self):
+ return self.fgcolor
+ def SetForegroundColour(self, color):
+ self.fgcolor = color
+ self.fgbrush = wx.Brush(color)
+ self.fgpen = wx.Pen(color, 1, wx.SOLID)
+ def GetLineColour(self):
+ return self.linecolor
+ def SetLineColour(self, color):
+ self.linecolor = color
+ self.linebrush = wx.Brush(color)
+ self.linepen = wx.Pen( color, 1, wx.SOLID)
+ def GetForegroundPen(self):
+ return self.fgpen
+ def GetBackgroundPen(self):
+ return self.bgpen
+ def GetTextPen(self):
+ return self.textpen
+ def GetForegroundBrush(self):
+ return self.fgbrush
+ def GetBackgroundBrush(self):
+ return self.bgbrush
+ def GetTextBrush(self):
+ return self.textbrush
+ def GetLinePen(self):
+ return self.linepen
+ def GetLineBrush(self):
+ return self.linebrush
+ def OnMouse(self, evt):
+ if evt.LeftDClick():
+ x, y = self.tree.CalcUnscrolledPosition(evt.GetX(), evt.GetY())
+ for item in self.rectangles:
+ if item[1].Contains((x,y)):
+ self.tree.Edit(item[0].data)
+ self.tree.OnNodeClick(item[0], evt)
+ return
+ elif evt.ButtonDown():
+ x, y = self.tree.CalcUnscrolledPosition(evt.GetX(), evt.GetY())
+ for item in self.rectangles:
+ if item[1].Contains((x, y)):
+ self.tree.OnNodeClick(item[0], evt)
+ return
+ for item in self.knobs:
+ if item[1].Contains((x, y)):
+ self.tree.OnKnobClick(item[0])
+ return
+ evt.Skip()
+
+
+class TreeModel:
+ """
+ Interface for tree models
+ """
+ def GetRoot(self):
+ raise NotImplementedError
+ def SetRoot(self, root):
+ raise NotImplementedError
+ def GetChildCount(self, node):
+ raise NotImplementedError
+ def GetChildAt(self, node, index):
+ raise NotImplementedError
+ def GetParent(self, node):
+ raise NotImplementedError
+ def AddChild(self, parent, child):
+ if hasattr(self, 'tree') and self.tree:
+ self.tree.NodeAdded(parent, child)
+ def RemoveNode(self, child):
+ if hasattr(self, 'tree') and self.tree:
+ self.tree.NodeRemoved(child)
+ def InsertChild(self, parent, child, index):
+ if hasattr(self, 'tree') and self.tree:
+ self.tree.NodeInserted(parent, child, index)
+ def IsLeaf(self, node):
+ raise NotImplementedError
+
+ def IsEditable(self, node):
+ return False
+
+ def SetEditable(self, node):
+ return False
+
+class NodePainter:
+ """
+ This is the interface expected of a nodepainter.
+ """
+ def __init__(self, painter):
+ self.painter = painter
+ def Paint(self, node, dc, location = None):
+ """
+ location should be provided only to draw in an unusual position
+ (not the node's normal position), otherwise the node's projected x and y
+ coordinates will be used.
+ """
+ raise NotImplementedError
+
+class LinePainter:
+ """
+ The linepainter interface.
+ """
+ def __init__(self, painter):
+ self.painter = painter
+ def Paint(self, parent, child, dc):
+ raise NotImplementedError
+
+class TextConverter:
+ """
+ TextConverter interface.
+ """
+ def __init__(self, painter):
+ self.painter = painter
+ def Convert(node):
+ """
+ Should return a string. The node argument will be an
+ MVCTreeNode.
+ """
+ raise NotImplementedError
+
+
+class BasicTreeModel(TreeModel):
+ """
+ A very simple treemodel implementation, but flexible enough for many needs.
+ """
+ def __init__(self):
+ self.children = {}
+ self.parents = {}
+ self.root = None
+ def GetRoot(self):
+ return self.root
+ def SetRoot(self, root):
+ self.root = root
+ def GetChildCount(self, node):
+ if self.children.has_key(node):
+ return len(self.children[node])
+ else:
+ return 0
+ def GetChildAt(self, node, index):
+ return self.children[node][index]
+
+ def GetParent(self, node):
+ return self.parents[node]
+
+ def AddChild(self, parent, child):
+ self.parents[child]=parent
+ if not self.children.has_key(parent):
+ self.children[parent]=[]
+ self.children[parent].append(child)
+ TreeModel.AddChild(self, parent, child)
+ return child
+
+ def RemoveNode(self, node):
+ parent = self.parents[node]
+ del self.parents[node]
+ self.children[parent].remove(node)
+ TreeModel.RemoveNode(self, node)
+
+ def InsertChild(self, parent, child, index):
+ self.parents[child]=parent
+ if not self.children.has_key(parent):
+ self.children[parent]=[]
+ self.children[parent].insert(child, index)
+ TreeModel.InsertChild(self, parent, child, index)
+ return child
+
+ def IsLeaf(self, node):
+ return not self.children.has_key(node)
+
+ def IsEditable(self, node):
+ return False
+
+ def SetEditable(self, node, bool):
+ return False
+
+
+class FileEditor(Editor):
+ def Edit(self, node):
+ treenode = self.tree.nodemap[node]
+ self.editcomp = wxTextCtrl(self.tree, -1)
+ for rect in self.tree.painter.rectangles:
+ if rect[0] == treenode:
+ self.editcomp.SetPosition((rect[1][0], rect[1][1]))
+ break
+ self.editcomp.SetValue(node.fileName)
+ self.editcomp.SetSelection(0, len(node.fileName))
+ self.editcomp.SetFocus()
+ self.treenode = treenode
+# self.editcomp.Bind(wx.EVT_KEY_DOWN, self._key)
+ self.editcomp.Bind(wx.EVT_KEY_UP, self._key)
+ self.editcomp.Bind(wx.EVT_LEFT_DOWN, self._mdown)
+ self.editcomp.CaptureMouse()
+
+ def CanEdit(self, node):
+ return isinstance(node, FileWrapper)
+
+ def EndEdit(self, commit):
+ if not self.tree._EditEnding(self.treenode.data):
+ return
+ if commit:
+ node = self.treenode.data
+ try:
+ os.rename(node.path + os.sep + node.fileName, node.path + os.sep + self.editcomp.GetValue())
+ node.fileName = self.editcomp.GetValue()
+ except:
+ traceback.print_exc()
+ self.editcomp.ReleaseMouse()
+ self.editcomp.Destroy()
+ del self.editcomp
+ self.tree.Refresh()
+
+
+ def _key(self, evt):
+ if evt.GetKeyCode() == wx.WXK_RETURN:
+ self.EndEdit(True)
+ elif evt.GetKeyCode() == wx.WXK_ESCAPE:
+ self.EndEdit(False)
+ else:
+ evt.Skip()
+
+ def _mdown(self, evt):
+ if evt.IsButton():
+ x, y = evt.GetPosition()
+ w, h = self.editcomp.GetSize()
+ if x < 0 or y < 0 or x > w or y > h:
+ self.EndEdit(False)
+
+
+class FileWrapper:
+ """
+ Node class for FSTreeModel.
+ """
+ def __init__(self, path, fileName):
+ self.path = path
+ self.fileName = fileName
+
+ def __str__(self):
+ return self.fileName
+
+class FSTreeModel(BasicTreeModel):
+ """
+ This treemodel models the filesystem starting from a given path.
+ """
+ def __init__(self, path):
+ BasicTreeModel.__init__(self)
+ fw = FileWrapper(path, path.split(os.sep)[-1])
+ self._Build(path, fw)
+ self.SetRoot(fw)
+ self._editable = True
+ def _Build(self, path, fileWrapper):
+ for name in os.listdir(path):
+ fw = FileWrapper(path, name)
+ self.AddChild(fileWrapper, fw)
+ childName = path + os.sep + name
+ if os.path.isdir(childName):
+ self._Build(childName, fw)
+
+ def IsEditable(self, node):
+ return self._editable
+
+ def SetEditable(self, node, bool):
+ self._editable = bool
+
+class LateFSTreeModel(FSTreeModel):
+ """
+ This treemodel models the filesystem starting from a given path.
+ It retrieves the directory list as requested.
+ """
+ def __init__(self, path):
+ BasicTreeModel.__init__(self)
+ name = path.split(os.sep)[-1]
+ pathpart = path[:-len(name)]
+ fw = FileWrapper(pathpart, name)
+ self._Build(path, fw)
+ self.SetRoot(fw)
+ self._editable = True
+ self.children = {}
+ self.parents = {}
+ def _Build(self, path, parent):
+ ppath = parent.path + os.sep + parent.fileName
+ if not os.path.isdir(ppath):
+ return
+ for name in os.listdir(ppath):
+ fw = FileWrapper(ppath, name)
+ self.AddChild(parent, fw)
+ def GetChildCount(self, node):
+ if self.children.has_key(node):
+ return FSTreeModel.GetChildCount(self, node)
+ else:
+ self._Build(node.path, node)
+ return FSTreeModel.GetChildCount(self, node)
+
+ def IsLeaf(self, node):
+ return not os.path.isdir(node.path + os.sep + node.fileName)
+
+class StrTextConverter(TextConverter):
+ def Convert(self, node):
+ return str(node.data)
+
+class NullTransform(Transform):
+ def GetSize(self):
+ return tuple(self.size)
+
+ def Transform(self, node, offset, rotation):
+ self.size = [0,0]
+ list = self.tree.GetLayoutEngine().GetNodeList()
+ for node in list:
+ node.projx = node.x + offset[0]
+ node.projy = node.y + offset[1]
+ if node.projx > self.size[0]:
+ self.size[0] = node.projx
+ if node.projy > self.size[1]:
+ self.size[1] = node.projy
+
+class Rect(object):
+ def __init__(self, x, y, width, height):
+ self.x = x
+ self.y = y
+ self.width = width
+ self.height = height
+ def __getitem__(self, index):
+ return (self.x, self.y, self.width, self.height)[index]
+
+ def __setitem__(self, index, value):
+ name = ['x', 'y', 'width', 'height'][index]
+ setattr(self, name, value)
+
+ def Contains(self, other):
+ if type(other) == type(()):
+ other = Rect(other[0], other[1], 0, 0)
+ if other.x >= self.x:
+ if other.y >= self.y:
+ if other.width + other.x <= self.width + self.x:
+ if other.height + other.y <= self.height + self.y:
+ return True
+ return False
+
+ def __str__(self):
+ return "Rect: " + str([self.x, self.y, self.width, self.height])
+
+class TreeLayout(LayoutEngine):
+ def SetHeight(self, num):
+ self.NODE_HEIGHT = num
+
+ def __init__(self, tree):
+ LayoutEngine.__init__(self, tree)
+ self.NODE_STEP = 20
+ self.NODE_HEIGHT = 20
+ self.nodelist = []
+
+ def Layout(self, node):
+ self.nodelist = []
+ self.NODE_HEIGHT = self.tree.GetFont().GetPointSize() * 2
+ self.layoutwalk(node)
+
+ def GetNodeList(self):
+ return self.nodelist
+
+ def layoutwalk(self, node):
+ if node == self.tree.currentRoot:
+ node.level = 1
+ self.lastY = (-self.NODE_HEIGHT)
+ node.x = self.NODE_STEP * node.level
+ node.y = self.lastY + self.NODE_HEIGHT
+ self.lastY = node.y
+ self.nodelist.append(node)
+ if node.expanded:
+ for kid in node.kids:
+ kid.level = node.level + 1
+ self.layoutwalk(kid)
+
+class TreePainter(Painter):
+ """
+ The default painter class. Uses double-buffering, delegates the painting of nodes and
+ lines to helper classes deriving from NodePainter and LinePainter.
+ """
+ def __init__(self, tree, nodePainter = None, linePainter = None, textConverter = None):
+ Painter.__init__(self, tree)
+ if not nodePainter:
+ nodePainter = TreeNodePainter(self)
+ self.nodePainter = nodePainter
+ if not linePainter:
+ linePainter = TreeLinePainter(self)
+ self.linePainter = linePainter
+ if not textConverter:
+ textConverter = StrTextConverter(self)
+ self.textConverter = textConverter
+ self.charWidths = []
+
+ def Paint(self, dc, node, doubleBuffered=1, paintBackground=1):
+ if not self.charWidths:
+ self.charWidths = []
+ for i in range(25):
+ self.charWidths.append(dc.GetTextExtent("D")[0] * i)
+ self.charHeight = dc.GetTextExtent("D")[1]
+ self.textpen = wx.Pen(self.GetTextColour(), 1, wx.SOLID)
+ self.fgpen = wx.Pen(self.GetForegroundColour(), 1, wx.SOLID)
+ self.bgpen = wx.Pen(self.GetBackgroundColour(), 1, wx.SOLID)
+ self.linepen = wx.Pen(self.GetLineColour(), 1, wx.SOLID)
+ self.dashpen = wx.Pen(self.GetLineColour(), 1, wx.DOT)
+ self.textbrush = wx.Brush(self.GetTextColour(), wx.SOLID)
+ self.fgbrush = wx.Brush(self.GetForegroundColour(), wx.SOLID)
+ self.bgbrush = wx.Brush(self.GetBackgroundColour(), wx.SOLID)
+ self.linebrush = wx.Pen(self.GetLineColour(), 1, wx.SOLID)
+ treesize = self.tree.GetSize()
+ size = self.tree.transform.GetSize()
+ size = (max(treesize.width, size[0]+50), max(treesize.height, size[1]+50))
+ dc.BeginDrawing()
+ if doubleBuffered:
+ mem_dc = wx.MemoryDC()
+ if not self.GetBuffer():
+ self.knobs = []
+ self.rectangles = []
+ self.bmp = wx.EmptyBitmap(size[0], size[1])
+ mem_dc.SelectObject(self.GetBuffer())
+ mem_dc.SetPen(self.GetBackgroundPen())
+ mem_dc.SetBrush(self.GetBackgroundBrush())
+ mem_dc.DrawRectangle(0, 0, size[0], size[1])
+ mem_dc.SetFont(self.tree.GetFont())
+ self.paintWalk(node, mem_dc)
+ else:
+ mem_dc.SelectObject(self.GetBuffer())
+ xstart, ystart = self.tree.CalcUnscrolledPosition(0,0)
+ size = self.tree.GetClientSizeTuple()
+ dc.Blit(xstart, ystart, size[0], size[1], mem_dc, xstart, ystart)
+ else:
+ if node == self.tree.currentRoot:
+ self.knobs = []
+ self.rectangles = []
+ dc.SetPen(self.GetBackgroundPen())
+ dc.SetBrush(self.GetBackgroundBrush())
+ dc.SetFont(self.tree.GetFont())
+ if paintBackground:
+ dc.DrawRectangle(0, 0, size[0], size[1])
+ if node:
+ #Call with not paintBackground because if we are told not to paint the
+ #whole background, we have to paint in parts to undo selection coloring.
+ pb = paintBackground
+ self.paintWalk(node, dc, not pb)
+ dc.EndDrawing()
+
+ def GetDashPen(self):
+ return self.dashpen
+
+ def SetLinePen(self, pen):
+ Painter.SetLinePen(self, pen)
+ self.dashpen = wx.Pen(pen.GetColour(), 1, wx.DOT)
+
+ def paintWalk(self, node, dc, paintRects=0):
+ self.linePainter.Paint(node.parent, node, dc)
+ self.nodePainter.Paint(node, dc, drawRects = paintRects)
+ if node.expanded:
+ for kid in node.kids:
+ if not self.paintWalk(kid, dc, paintRects):
+ return False
+ for kid in node.kids:
+ px = (kid.projx - self.tree.layout.NODE_STEP) + 5
+ py = kid.projy + kid.height/2
+ if (not self.tree.model.IsLeaf(kid.data)) or ((kid.expanded or self.tree._assumeChildren) and len(kid.kids)):
+ dc.SetPen(self.linepen)
+ dc.SetBrush(self.bgbrush)
+ dc.DrawRectangle(px -4, py-4, 9, 9)
+ self.knobs.append( (kid, Rect(px -4, py -4, 9, 9)) )
+ dc.SetPen(self.textpen)
+ if not kid.expanded:
+ dc.DrawLine(px, py -2, px, py + 3)
+ dc.DrawLine(px -2, py, px + 3, py)
+ if node == self.tree.currentRoot:
+ px = (node.projx - self.tree.layout.NODE_STEP) + 5
+ py = node.projy + node.height/2
+ dc.SetPen(self.linepen)
+ dc.SetBrush(self.bgbrush)
+ dc.DrawRectangle(px -4, py-4, 9, 9)
+ self.knobs.append( (node, Rect(px -4, py -4, 9, 9)) )
+ dc.SetPen(self.textpen)
+ if not node.expanded:
+ dc.DrawLine(px, py -2, px, py + 3)
+ dc.DrawLine(px -2, py, px + 3, py)
+ return True
+
+ def OnMouse(self, evt):
+ Painter.OnMouse(self, evt)
+
+class TreeNodePainter(NodePainter):
+ def Paint(self, node, dc, location = None, drawRects = 0):
+ text = self.painter.textConverter.Convert(node)
+ extent = dc.GetTextExtent(text)
+ node.width = extent[0]
+ node.height = extent[1]
+ if node.selected:
+ dc.SetPen(self.painter.GetLinePen())
+ dc.SetBrush(self.painter.GetForegroundBrush())
+ dc.SetTextForeground(wx.NamedColour("WHITE"))
+ dc.DrawRectangle(node.projx -1, node.projy -1, node.width + 3, node.height + 3)
+ else:
+ if drawRects:
+ dc.SetBrush(self.painter.GetBackgroundBrush())
+ dc.SetPen(self.painter.GetBackgroundPen())
+ dc.DrawRectangle(node.projx -1, node.projy -1, node.width + 3, node.height + 3)
+ dc.SetTextForeground(self.painter.GetTextColour())
+ dc.DrawText(text, node.projx, node.projy)
+ self.painter.rectangles.append((node, Rect(node.projx, node.projy, node.width, node.height)))
+
+class TreeLinePainter(LinePainter):
+ def Paint(self, parent, child, dc):
+ dc.SetPen(self.painter.GetDashPen())
+ px = py = cx = cy = 0
+ if parent is None or child == self.painter.tree.currentRoot:
+ px = (child.projx - self.painter.tree.layout.NODE_STEP) + 5
+ py = child.projy + self.painter.tree.layout.NODE_HEIGHT/2 -2
+ cx = child.projx
+ cy = py
+ dc.DrawLine(px, py, cx, cy)
+ else:
+ px = parent.projx + 5
+ py = parent.projy + parent.height
+ cx = child.projx -5
+ cy = child.projy + self.painter.tree.layout.NODE_HEIGHT/2 -3
+ dc.DrawLine(px, py, px, cy)
+ dc.DrawLine(px, cy, cx, cy)
+
+#>> Event defs
+wxEVT_MVCTREE_BEGIN_EDIT = wx.NewEventType() #Start editing. Vetoable.
+wxEVT_MVCTREE_END_EDIT = wx.NewEventType() #Stop editing. Vetoable.
+wxEVT_MVCTREE_DELETE_ITEM = wx.NewEventType() #Item removed from model.
+wxEVT_MVCTREE_ITEM_EXPANDED = wx.NewEventType()
+wxEVT_MVCTREE_ITEM_EXPANDING = wx.NewEventType()
+wxEVT_MVCTREE_ITEM_COLLAPSED = wx.NewEventType()
+wxEVT_MVCTREE_ITEM_COLLAPSING = wx.NewEventType()
+wxEVT_MVCTREE_SEL_CHANGED = wx.NewEventType()
+wxEVT_MVCTREE_SEL_CHANGING = wx.NewEventType() #Vetoable.
+wxEVT_MVCTREE_KEY_DOWN = wx.NewEventType()
+wxEVT_MVCTREE_ADD_ITEM = wx.NewEventType() #Item added to model.
+
+EVT_MVCTREE_SEL_CHANGED = wx.PyEventBinder(wxEVT_MVCTREE_SEL_CHANGED, 1)
+EVT_MVCTREE_SEL_CHANGING = wx.PyEventBinder(wxEVT_MVCTREE_SEL_CHANGING, 1)
+EVT_MVCTREE_ITEM_EXPANDED = wx.PyEventBinder(wxEVT_MVCTREE_ITEM_EXPANDED, 1)
+EVT_MVCTREE_ITEM_EXPANDING = wx.PyEventBinder(wxEVT_MVCTREE_ITEM_EXPANDING, 1)
+EVT_MVCTREE_ITEM_COLLAPSED = wx.PyEventBinder(wxEVT_MVCTREE_ITEM_COLLAPSED, 1)
+EVT_MVCTREE_ITEM_COLLAPSING = wx.PyEventBinder(wxEVT_MVCTREE_ITEM_COLLAPSING, 1)
+EVT_MVCTREE_ADD_ITEM = wx.PyEventBinder(wxEVT_MVCTREE_ADD_ITEM, 1)
+EVT_MVCTREE_DELETE_ITEM = wx.PyEventBinder(wxEVT_MVCTREE_DELETE_ITEM, 1)
+EVT_MVCTREE_KEY_DOWN = wx.PyEventBinder(wxEVT_MVCTREE_KEY_DOWN, 1)
+
+class MVCTreeEvent(wx.PyCommandEvent):
+ def __init__(self, type, id, node = None, nodes = None, keyEvent = None, **kwargs):
+ apply(wx.PyCommandEvent.__init__, (self, type, id), kwargs)
+ self.node = node
+ self.nodes = nodes
+ self.keyEvent = keyEvent
+ def GetNode(self):
+ return self.node
+ def GetNodes(self):
+ return self.nodes
+ def getKeyEvent(self):
+ return self.keyEvent
+
+class MVCTreeNotifyEvent(MVCTreeEvent):
+ def __init__(self, type, id, node = None, nodes = None, **kwargs):
+ apply(MVCTreeEvent.__init__, (self, type, id, node, nodes), kwargs)
+ self.notify = wx.NotifyEvent(type, id)
+ def getNotifyEvent(self):
+ return self.notify
+
+class MVCTree(wx.ScrolledWindow):
+ """
+ The main mvc tree class.
+ """
+ def __init__(self, parent, id, model = None, layout = None, transform = None,
+ painter = None, *args, **kwargs):
+ apply(wx.ScrolledWindow.__init__, (self, parent, id), kwargs)
+ self.nodemap = {}
+ self._multiselect = False
+ self._selections = []
+ self._assumeChildren = False
+ self._scrollx = False
+ self._scrolly = False
+ self.doubleBuffered = False
+ self._lastPhysicalSize = self.GetSize()
+ self._editors = []
+ if not model:
+ model = BasicTreeModel()
+ model.SetRoot("Root")
+ self.SetModel(model)
+ if not layout:
+ layout = TreeLayout(self)
+ self.layout = layout
+ if not transform:
+ transform = NullTransform(self)
+ self.transform = transform
+ if not painter:
+ painter = TreePainter(self)
+ self.painter = painter
+ self.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False))
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.doubleBuffered = True
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def Refresh(self):
+ if self.doubleBuffered:
+ self.painter.ClearBuffer()
+ wx.ScrolledWindow.Refresh(self, False)
+
+ def GetPainter(self):
+ return self.painter
+
+ def GetLayoutEngine(self):
+ return self.layout
+
+ def GetTransform(self):
+ return self.transform
+
+ def __repr__(self):
+ return "<MVCTree instance at %s>" % str(hex(id(self)))
+
+ def __str__(self):
+ return self.__repr__()
+
+ def NodeAdded(self, parent, child):
+ e = MVCTreeEvent(wxEVT_MVCTREE_ADD_ITEM, self.GetId(), node = child, nodes = [parent, child])
+ self.GetEventHandler().ProcessEvent(e)
+ self.painter.ClearBuffer()
+
+ def NodeInserted(self, parent, child, index):
+ e = MVCTreeEvent(wxEVT_MVCTREE_ADD_ITEM, self.GetId(), node = child, nodes = [parent, child])
+ self.GetEventHandler().ProcessEvent(e)
+ self.painter.ClearBuffer()
+
+ def NodeRemoved(self, node):
+ e = MVCTreeEvent(wxEVT_MVCTREE_DELETE_ITEM, self.GetId(), node = child, nodes = [parent, child])
+ self.GetEventHandler().ProcessEvent(e)
+ self.painter.ClearBuffer()
+
+ def OnKeyDown(self, evt):
+ e = MVCTreeEvent(wxEVT_MVCTREE_KEY_DOWN, self.GetId(), keyEvent = evt)
+ self.GetEventHandler().ProcessEvent(e)
+
+ def SetFont(self, font):
+ self.painter.SetFont(font)
+ dc = wx.ClientDC(self)
+ dc.SetFont(font)
+ self.layout.SetHeight(dc.GetTextExtent("")[1] + 18)
+ self.painter.ClearBuffer()
+
+ def GetFont(self):
+ return self.painter.GetFont()
+
+ def AddEditor(self, editor):
+ self._editors.append(editor)
+
+ def RemoveEditor(self, editor):
+ self._editors.remove(editor)
+
+ def OnMouse(self, evt):
+ self.painter.OnMouse(evt)
+
+ def OnNodeClick(self, node, mouseEvent):
+ if node.selected and (self.IsMultiSelect() and mouseEvent.ControlDown()):
+ self.RemoveFromSelection(node.data)
+ else:
+ self.AddToSelection(node.data, mouseEvent.ControlDown(), mouseEvent.ShiftDown())
+
+ def OnKnobClick(self, node):
+ self.SetExpanded(node.data, not node.expanded)
+
+ def GetDisplayText(self, node):
+ treenode = self.nodemap[node]
+ return self.painter.textConverter.Convert(treenode)
+
+ def IsDoubleBuffered(self):
+ return self.doubleBuffered
+
+ def SetDoubleBuffered(self, bool):
+ """
+ By default MVCTree is double-buffered.
+ """
+ self.doubleBuffered = bool
+
+ def GetModel(self):
+ return self.model
+
+ def SetModel(self, model):
+ """
+ Completely change the data to be displayed.
+ """
+ self.model = model
+ model.tree = self
+ self.laidOut = 0
+ self.transformed = 0
+ self._selections = []
+ self.layoutRoot = MVCTreeNode()
+ self.layoutRoot.data = self.model.GetRoot()
+ self.layoutRoot.expanded = True
+ self.LoadChildren(self.layoutRoot)
+ self.currentRoot = self.layoutRoot
+ self.offset = [0,0]
+ self.rotation = 0
+ self._scrollset = None
+ self.Refresh()
+
+ def GetCurrentRoot(self):
+ return self.currentRoot
+
+ def LoadChildren(self, layoutNode):
+ if layoutNode.built:
+ return
+ else:
+ self.nodemap[layoutNode.data]=layoutNode
+ for i in range(self.GetModel().GetChildCount(layoutNode.data)):
+ p = MVCTreeNode("RAW", layoutNode, [])
+ layoutNode.Add(p)
+ p.data = self.GetModel().GetChildAt(layoutNode.data, i)
+ self.nodemap[p.data]=p
+ layoutNode.built = True
+ if not self._assumeChildren:
+ for kid in layoutNode.kids:
+ self.LoadChildren(kid)
+
+ def OnEraseBackground(self, evt):
+ pass
+
+ def OnSize(self, evt):
+ size = self.GetSize()
+ self.center = (size.width/2, size.height/2)
+ if self._lastPhysicalSize.width < size.width or self._lastPhysicalSize.height < size.height:
+ self.painter.ClearBuffer()
+ self._lastPhysicalSize = size
+
+ def GetSelection(self):
+ "Returns a tuple of selected nodes."
+ return tuple(self._selections)
+
+ def SetSelection(self, nodeTuple):
+ if type(nodeTuple) != type(()):
+ nodeTuple = (nodeTuple,)
+ e = MVCTreeNotifyEvent(wxEVT_MVCTREE_SEL_CHANGING, self.GetId(), nodeTuple[0], nodes = nodeTuple)
+ self.GetEventHandler().ProcessEvent(e)
+ if not e.notify.IsAllowed():
+ return
+ for node in nodeTuple:
+ treenode = self.nodemap[node]
+ treenode.selected = True
+ for node in self._selections:
+ treenode = self.nodemap[node]
+ node.selected = False
+ self._selections = list(nodeTuple)
+ e = MVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), nodeTuple[0], nodes = nodeTuple)
+ self.GetEventHandler().ProcessEvent(e)
+
+ def IsMultiSelect(self):
+ return self._multiselect
+
+ def SetMultiSelect(self, bool):
+ self._multiselect = bool
+
+ def IsSelected(self, node):
+ return self.nodemap[node].selected
+
+ def Edit(self, node):
+ if not self.model.IsEditable(node):
+ return
+ for ed in self._editors:
+ if ed.CanEdit(node):
+ e = MVCTreeNotifyEvent(wxEVT_MVCTREE_BEGIN_EDIT, self.GetId(), node)
+ self.GetEventHandler().ProcessEvent(e)
+ if not e.notify.IsAllowed():
+ return
+ ed.Edit(node)
+ self._currentEditor = ed
+ break
+
+ def EndEdit(self):
+ if self._currentEditor:
+ self._currentEditor.EndEdit
+ self._currentEditor = None
+
+ def _EditEnding(self, node):
+ e = MVCTreeNotifyEvent(wxEVT_MVCTREE_END_EDIT, self.GetId(), node)
+ self.GetEventHandler().ProcessEvent(e)
+ if not e.notify.IsAllowed():
+ return False
+ self._currentEditor = None
+ return True
+
+
+ def SetExpanded(self, node, bool):
+ treenode = self.nodemap[node]
+ if bool:
+ e = MVCTreeNotifyEvent(wxEVT_MVCTREE_ITEM_EXPANDING, self.GetId(), node)
+ self.GetEventHandler().ProcessEvent(e)
+ if not e.notify.IsAllowed():
+ return
+ if not treenode.built:
+ self.LoadChildren(treenode)
+ else:
+ e = MVCTreeNotifyEvent(wxEVT_MVCTREE_ITEM_COLLAPSING, self.GetId(), node)
+ self.GetEventHandler().ProcessEvent(e)
+ if not e.notify.IsAllowed():
+ return
+ treenode.expanded = bool
+ e = None
+ if treenode.expanded:
+ e = MVCTreeEvent(wxEVT_MVCTREE_ITEM_EXPANDED, self.GetId(), node)
+ else:
+ e = MVCTreeEvent(wxEVT_MVCTREE_ITEM_COLLAPSED, self.GetId(), node)
+ self.GetEventHandler().ProcessEvent(e)
+ self.layout.Layout(self.currentRoot)
+ self.transform.Transform(self.currentRoot, self.offset, self.rotation)
+ self.Refresh()
+
+ def IsExpanded(self, node):
+ return self.nodemap[node].expanded
+
+ def AddToSelection(self, nodeOrTuple, enableMulti = True, shiftMulti = False):
+ nodeTuple = nodeOrTuple
+ if type(nodeOrTuple)!= type(()):
+ nodeTuple = (nodeOrTuple,)
+ e = MVCTreeNotifyEvent(wxEVT_MVCTREE_SEL_CHANGING, self.GetId(), nodeTuple[0], nodes = nodeTuple)
+ self.GetEventHandler().ProcessEvent(e)
+ if not e.notify.IsAllowed():
+ return
+ changeparents = []
+ if not (self.IsMultiSelect() and (enableMulti or shiftMulti)):
+ for node in self._selections:
+ treenode = self.nodemap[node]
+ treenode.selected = False
+ changeparents.append(treenode)
+ node = nodeTuple[0]
+ self._selections = [node]
+ treenode = self.nodemap[node]
+ changeparents.append(treenode)
+ treenode.selected = True
+ else:
+ if shiftMulti:
+ for node in nodeTuple:
+ treenode = self.nodemap[node]
+ oldtreenode = self.nodemap[self._selections[0]]
+ if treenode.parent == oldtreenode.parent:
+ found = 0
+ for kid in oldtreenode.parent.kids:
+ if kid == treenode or kid == oldtreenode:
+ found = not found
+ kid.selected = True
+ self._selections.append(kid.data)
+ changeparents.append(kid)
+ elif found:
+ kid.selected = True
+ self._selections.append(kid.data)
+ changeparents.append(kid)
+ else:
+ for node in nodeTuple:
+ try:
+ self._selections.index(node)
+ except ValueError:
+ self._selections.append(node)
+ treenode = self.nodemap[node]
+ treenode.selected = True
+ changeparents.append(treenode)
+ e = MVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), nodeTuple[0], nodes = nodeTuple)
+ self.GetEventHandler().ProcessEvent(e)
+ dc = wx.ClientDC(self)
+ self.PrepareDC(dc)
+ for node in changeparents:
+ if node:
+ self.painter.Paint(dc, node, doubleBuffered = 0, paintBackground = 0)
+ self.painter.ClearBuffer()
+
+ def RemoveFromSelection(self, nodeTuple):
+ if type(nodeTuple) != type(()):
+ nodeTuple = (nodeTuple,)
+ changeparents = []
+ for node in nodeTuple:
+ self._selections.remove(node)
+ treenode = self.nodemap[node]
+ changeparents.append(treenode)
+ treenode.selected = False
+ e = MVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), node, nodes = nodeTuple)
+ self.GetEventHandler().ProcessEvent(e)
+ dc = wx.ClientDC(self)
+ self.PrepareDC(dc)
+ for node in changeparents:
+ if node:
+ self.painter.Paint(dc, node, doubleBuffered = 0, paintBackground = 0)
+ self.painter.ClearBuffer()
+
+
+ def GetBackgroundColour(self):
+ if hasattr(self, 'painter') and self.painter:
+ return self.painter.GetBackgroundColour()
+ else:
+ return wx.Window.GetBackgroundColour(self)
+ def SetBackgroundColour(self, color):
+ if hasattr(self, 'painter') and self.painter:
+ self.painter.SetBackgroundColour(color)
+ else:
+ wx.Window.SetBackgroundColour(self, color)
+ def GetForegroundColour(self):
+ if hasattr(self, 'painter') and self.painter:
+ return self.painter.GetForegroundColour()
+ else:
+ return wx.Window.GetBackgroundColour(self)
+ def SetForegroundColour(self, color):
+ if hasattr(self, 'painter') and self.painter:
+ self.painter.SetForegroundColour(color)
+ else:
+ wx.Window.SetBackgroundColour(self, color)
+
+ def SetAssumeChildren(self, bool):
+ self._assumeChildren = bool
+
+ def GetAssumeChildren(self):
+ return self._assumeChildren
+
+ def OnPaint(self, evt):
+ """
+ Ensures that the tree has been laid out and transformed, then calls the painter
+ to paint the control.
+ """
+ try:
+ self.EnableScrolling(False, False)
+ if not self.laidOut:
+ self.layout.Layout(self.currentRoot)
+ self.laidOut = True
+ self.transformed = False
+ if not self.transformed:
+ self.transform.Transform(self.currentRoot, self.offset, self.rotation)
+ self.transformed = True
+ tsize = None
+ tsize = list(self.transform.GetSize())
+ tsize[0] = tsize[0] + 50
+ tsize[1] = tsize[1] + 50
+ w, h = self.GetSize()
+ if tsize[0] > w or tsize[1] > h:
+ if not hasattr(self, '_oldsize') or (tsize[0] > self._oldsize[0] or tsize[1] > self._oldsize[1]):
+ self._oldsize = tsize
+ oldstart = self.GetViewStart()
+ self._lastPhysicalSize = self.GetSize()
+ self.SetScrollbars(10, 10, tsize[0]/10, tsize[1]/10)
+ self.Scroll(oldstart[0], oldstart[1])
+ dc = wx.PaintDC(self)
+ self.PrepareDC(dc)
+ dc.SetFont(self.GetFont())
+ self.painter.Paint(dc, self.currentRoot, self.doubleBuffered)
+ except:
+ traceback.print_exc()
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/newevent.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/newevent.py
new file mode 100644
index 0000000..9a8f67d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/newevent.py
@@ -0,0 +1,115 @@
+"""Easy generation of new events classes and binder objects"""
+
+__author__ = "Miki Tebeka <miki.tebeka@gmail.com>"
+
+import wx
+
+#---------------------------------------------------------------------------
+
+def NewEvent():
+ """Generate new (Event, Binder) tuple
+ e.g. MooEvent, EVT_MOO = NewEvent()
+ """
+ evttype = wx.NewEventType()
+
+ class _Event(wx.PyEvent):
+ def __init__(self, **kw):
+ wx.PyEvent.__init__(self)
+ self.SetEventType(evttype)
+ self.__dict__.update(kw)
+
+ return _Event, wx.PyEventBinder(evttype)
+
+
+
+def NewCommandEvent():
+ """Generate new (CmdEvent, Binder) tuple
+ e.g. MooCmdEvent, EVT_MOO = NewCommandEvent()
+ """
+ evttype = wx.NewEventType()
+
+ class _Event(wx.PyCommandEvent):
+ def __init__(self, id, **kw):
+ wx.PyCommandEvent.__init__(self, evttype, id)
+ self.__dict__.update(kw)
+
+ return _Event, wx.PyEventBinder(evttype, 1)
+
+
+#---------------------------------------------------------------------------
+
+def _test():
+ """A little smoke test"""
+ from threading import Thread
+ from time import sleep
+
+ MooEvent, EVT_MOO = NewEvent()
+ GooEvent, EVT_GOO = NewCommandEvent()
+
+ DELAY = 0.7
+
+ def evt_thr(win):
+ sleep(DELAY)
+ wx.PostEvent(win, MooEvent(moo=1))
+
+ def cmd_thr(win, id):
+ sleep(DELAY)
+ wx.PostEvent(win, GooEvent(id, goo=id))
+
+ ID_CMD1 = wx.NewId()
+ ID_CMD2 = wx.NewId()
+
+ class Frame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "MOO")
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ EVT_MOO(self, self.on_moo)
+ b = wx.Button(self, -1, "Generate MOO")
+ sizer.Add(b, 1, wx.EXPAND)
+ wx.EVT_BUTTON(self, b.GetId(), self.on_evt_click)
+ b = wx.Button(self, ID_CMD1, "Generate GOO with %d" % ID_CMD1)
+ sizer.Add(b, 1, wx.EXPAND)
+ wx.EVT_BUTTON(self, ID_CMD1, self.on_cmd_click)
+ b = wx.Button(self, ID_CMD2, "Generate GOO with %d" % ID_CMD2)
+ sizer.Add(b, 1, wx.EXPAND)
+ wx.EVT_BUTTON(self, ID_CMD2, self.on_cmd_click)
+
+ EVT_GOO(self, ID_CMD1, self.on_cmd1)
+ EVT_GOO(self, ID_CMD2, self.on_cmd2)
+
+ self.SetSizer(sizer)
+ self.SetAutoLayout(True)
+ sizer.Fit(self)
+
+ def on_evt_click(self, e):
+ t = Thread(target=evt_thr, args=(self, ))
+ t.setDaemon(True)
+ t.start()
+
+ def on_cmd_click(self, e):
+ t = Thread(target=cmd_thr, args=(self, e.GetId()))
+ t.setDaemon(True)
+ t.start()
+
+ def show(self, msg, title):
+ dlg = wx.MessageDialog(self, msg, title, wx.OK)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+ def on_moo(self, e):
+ self.show("MOO = %s" % e.moo, "Got Moo")
+
+ def on_cmd1(self, e):
+ self.show("goo = %s" % e.goo, "Got Goo (cmd1)")
+
+ def on_cmd2(self, e):
+ self.show("goo = %s" % e.goo, "Got Goo (cmd2)")
+
+
+ app = wx.App()
+ f = Frame()
+ f.Show(True)
+ app.MainLoop()
+
+if __name__ == "__main__":
+ _test()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/nvdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/nvdlg.py
new file mode 100644
index 0000000..2300df2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/nvdlg.py
@@ -0,0 +1,155 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.nvdlg
+# Purpose: Dialog for editing name/value pairs
+#
+# Author: Robin Dunn
+#
+# Created: 30-Nov-2009
+# RCS-ID: $Id: $
+# Copyright: (c) 2009 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+
+"""
+A simple dialog that can prompt for values for any arbitrary set of name/value
+pairs, where the fields are defined by a list of info passed to the
+constructor. A dictionary of initial values can also be passed. Each item in
+the fields list is a tuple of 3 items, which are:
+
+ * a string to be used for the attribute name for storing the value
+ * a string to be used for the label
+ * None, or a dictionary of kwargs to be passed to the wx.TextCtrl ctor
+"""
+
+import wx
+
+MARGIN = 4
+
+
+
+class SimpleNameValueDialog(wx.Dialog):
+ def __init__(self, parent, id=-1, title="", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE,
+ fields=[], initialValues=None,
+ captionTitle="", captionDescr=""):
+ wx.Dialog.__init__(self, parent, id, title, pos, size, style)
+
+ self._fields = dict()
+ self.Sizer = wx.BoxSizer(wx.VERTICAL)
+ self._contentSizer = wx.FlexGridSizer(cols=2, hgap=MARGIN, vgap=MARGIN)
+ self._contentSizer.AddGrowableCol(1)
+
+ if captionTitle:
+ titleTxt = wx.StaticText(self, -1, captionTitle)
+ titleTxt.SetFont(wx.FFont(18, wx.SWISS, wx.FONTFLAG_BOLD))
+ self.Sizer.Add(titleTxt, 0, wx.ALL, MARGIN)
+ if captionDescr:
+ descTxt = wx.StaticText(self, -1, captionDescr)
+ self.Sizer.Add(descTxt, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM, MARGIN)
+ if captionTitle or captionDescr:
+ self.Sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, MARGIN)
+
+ self.createFields(fields)
+ self.loadValues(initialValues)
+
+ self.Sizer.Add(self._contentSizer, 1, wx.EXPAND|wx.ALL, MARGIN)
+ self.Sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, MARGIN)
+
+ # TODO: add ability to specify which stock or custom buttons are used
+ btnSizer = wx.StdDialogButtonSizer()
+ btnSizer.AddButton(wx.Button(self, wx.ID_OK))
+ btnSizer.AddButton(wx.Button(self, wx.ID_CANCEL))
+ btnSizer.Realize()
+ self.Sizer.Add(btnSizer, 0, wx.EXPAND|wx.ALL, MARGIN)
+ self.FindWindowById(wx.ID_OK).SetDefault()
+
+ self.Fit()
+
+
+ def createFields(self, fields):
+ self.destroyFields()
+ for name, label, args in fields:
+ kwargs = dict(validator=_TransferValidator(name))
+ if args:
+ kwargs.update(args)
+ stxt = wx.StaticText(self, -1, label)
+ txt = wx.TextCtrl(self, **kwargs)
+
+ self._contentSizer.Add(stxt, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
+ self._contentSizer.Add(txt, 0, wx.EXPAND)
+
+ self.__dict__[name] = ""
+ self._fields[name] = (stxt, txt)
+
+
+ def destroyFields(self):
+ for name, widgets in self._fields.iteritems():
+ for w in widgets:
+ w.Destroy()
+ del self.__dict__[name]
+
+
+ def loadValues(self, values):
+ self.clearValues()
+ for name, value in values.iteritems():
+ if name in self._fields.keys():
+ setattr(self, name, value)
+
+ def clearValues(self):
+ for name in self._fields.keys():
+ setattr(self, name, "")
+
+
+
+class _TransferValidator(wx.PyValidator):
+ """
+ This validator is used to transfer values to/from the widgets and
+ attributes of the dialog.
+ """
+ def __init__(self, name):
+ wx.PyValidator.__init__(self)
+ self.name = name
+
+ def Clone(self):
+ return _TransferValidator(self.name)
+
+
+ def Validate(self, win):
+ return True
+
+ def TransferFromWindow(self):
+ dlg = self.Window.Parent
+ value = dlg._fields[self.name][1].GetValue()
+ setattr(dlg, self.name, value)
+ return True
+
+ def TransferToWindow(self):
+ dlg = self.Window.Parent
+ value = getattr(dlg, self.name)
+ dlg._fields[self.name][1].SetValue(value)
+ return True
+
+
+
+
+if __name__ == '__main__':
+ from wx.lib.mixins.inspection import InspectableApp
+ app = InspectableApp(redirect=False)
+ #app = wx.App(redirect=False)
+
+ fields = [ ('username', 'Login ID:', None),
+ ('passwd', 'Password:', dict(size=(150,-1), style=wx.TE_PASSWORD)),
+ ]
+
+ dlg = SimpleNameValueDialog(None, title="This is the title",
+ fields=fields,
+ initialValues=dict(username='rdunn'),
+ captionTitle="Login",
+ captionDescr="Enter your testing credentials")
+ if dlg.ShowModal() == wx.ID_OK:
+ print dlg.username, dlg.passwd
+ dlg.Destroy()
+ app.MainLoop()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/__init__.py
new file mode 100644
index 0000000..4629b2c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/__init__.py
@@ -0,0 +1,22 @@
+"""
+The Object Graphics Library provides for simple drawing and manipulation
+of 2D objects.
+"""
+
+from _basic import *
+from _diagram import *
+from _canvas import *
+from _lines import *
+from _bmpshape import *
+from _divided import *
+from _composit import *
+from _drawn import *
+
+
+# Set things up for documenting with epydoc. The __docfilter__ will
+# prevent some things from being documented, and anything in __all__
+# will appear to actually exist in this module.
+import wx._core as _wx
+__docfilter__ = _wx.__DocFilter(globals())
+__all__ = [name for name in dir() if not name.startswith('_')]
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_basic.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_basic.py
new file mode 100644
index 0000000..09a0db0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_basic.py
@@ -0,0 +1,3179 @@
+# -*- coding: utf-8 -*-
+#----------------------------------------------------------------------------
+# Name: basic.py
+# Purpose: The basic OGL shapes
+#
+# Author: Pierre Hjälm (from C++ original by Julian Smart)
+#
+# Created: 2004-05-08
+# RCS-ID: $Id$
+# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+import wx
+import math
+
+from _oglmisc import *
+
+DragOffsetX = 0.0
+DragOffsetY = 0.0
+
+def OGLInitialize():
+ global WhiteBackgroundPen, WhiteBackgroundBrush, TransparentPen
+ global BlackForegroundPen, NormalFont
+
+ WhiteBackgroundPen = wx.Pen(wx.WHITE, 1, wx.SOLID)
+ WhiteBackgroundBrush = wx.Brush(wx.WHITE, wx.SOLID)
+
+ TransparentPen = wx.Pen(wx.WHITE, 1, wx.TRANSPARENT)
+ BlackForegroundPen = wx.Pen(wx.BLACK, 1, wx.SOLID)
+
+ NormalFont = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL)
+
+
+def OGLCleanUp():
+ pass
+
+
+class ShapeTextLine(object):
+ def __init__(self, the_x, the_y, the_line):
+ self._x = the_x
+ self._y = the_y
+ self._line = the_line
+
+ def GetX(self):
+ return self._x
+
+ def GetY(self):
+ return self._y
+
+ def SetX(self, x):
+ self._x = x
+
+ def SetY(self, y):
+ self._y = y
+
+ def SetText(self, text):
+ self._line = text
+
+ def GetText(self):
+ return self._line
+
+
+
+class ShapeEvtHandler(object):
+ def __init__(self, prev = None, shape = None):
+ self._previousHandler = prev
+ self._handlerShape = shape
+
+ def SetShape(self, sh):
+ self._handlerShape = sh
+
+ def GetShape(self):
+ return self._handlerShape
+
+ def SetPreviousHandler(self, handler):
+ self._previousHandler = handler
+
+ def GetPreviousHandler(self):
+ return self._previousHandler
+
+ def OnDelete(self):
+ if self!=self.GetShape():
+ del self
+
+ def OnDraw(self, dc):
+ if self._previousHandler:
+ self._previousHandler.OnDraw(dc)
+
+ def OnMoveLinks(self, dc):
+ if self._previousHandler:
+ self._previousHandler.OnMoveLinks(dc)
+
+ def OnMoveLink(self, dc, moveControlPoints = True):
+ if self._previousHandler:
+ self._previousHandler.OnMoveLink(dc, moveControlPoints)
+
+ def OnDrawContents(self, dc):
+ if self._previousHandler:
+ self._previousHandler.OnDrawContents(dc)
+
+ def OnDrawBranches(self, dc, erase = False):
+ if self._previousHandler:
+ self._previousHandler.OnDrawBranches(dc, erase = erase)
+
+ def OnSize(self, x, y):
+ if self._previousHandler:
+ self._previousHandler.OnSize(x, y)
+
+ def OnMovePre(self, dc, x, y, old_x, old_y, display = True):
+ if self._previousHandler:
+ return self._previousHandler.OnMovePre(dc, x, y, old_x, old_y, display)
+ else:
+ return True
+
+ def OnMovePost(self, dc, x, y, old_x, old_y, display = True):
+ if self._previousHandler:
+ return self._previousHandler.OnMovePost(dc, x, y, old_x, old_y, display)
+ else:
+ return True
+
+ def OnErase(self, dc):
+ if self._previousHandler:
+ self._previousHandler.OnErase(dc)
+
+ def OnEraseContents(self, dc):
+ if self._previousHandler:
+ self._previousHandler.OnEraseContents(dc)
+
+ def OnHighlight(self, dc):
+ if self._previousHandler:
+ self._previousHandler.OnHighlight(dc)
+
+ def OnLeftClick(self, x, y, keys, attachment):
+ if self._previousHandler:
+ self._previousHandler.OnLeftClick(x, y, keys, attachment)
+
+ def OnLeftDoubleClick(self, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnLeftDoubleClick(x, y, keys, attachment)
+
+ def OnRightClick(self, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnRightClick(x, y, keys, attachment)
+
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnDragLeft(draw, x, y, keys, attachment)
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnBeginDragLeft(x, y, keys, attachment)
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnEndDragLeft(x, y, keys, attachment)
+
+ def OnDragRight(self, draw, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnDragRight(draw, x, y, keys, attachment)
+
+ def OnBeginDragRight(self, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnBeginDragRight(x, y, keys, attachment)
+
+ def OnEndDragRight(self, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnEndDragRight(x, y, keys, attachment)
+
+ # Control points ('handles') redirect control to the actual shape,
+ # to make it easier to override sizing behaviour.
+ def OnSizingDragLeft(self, pt, draw, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnSizingDragLeft(pt, draw, x, y, keys, attachment)
+
+ def OnSizingBeginDragLeft(self, pt, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnSizingBeginDragLeft(pt, x, y, keys, attachment)
+
+ def OnSizingEndDragLeft(self, pt, x, y, keys = 0, attachment = 0):
+ if self._previousHandler:
+ self._previousHandler.OnSizingEndDragLeft(pt, x, y, keys, attachment)
+
+ def OnBeginSize(self, w, h):
+ pass
+
+ def OnEndSize(self, w, h):
+ pass
+
+ def OnDrawOutline(self, dc, x, y, w, h):
+ if self._previousHandler:
+ self._previousHandler.OnDrawOutline(dc, x, y, w, h)
+
+ def OnDrawControlPoints(self, dc):
+ if self._previousHandler:
+ self._previousHandler.OnDrawControlPoints(dc)
+
+ def OnEraseControlPoints(self, dc):
+ if self._previousHandler:
+ self._previousHandler.OnEraseControlPoints(dc)
+
+ # Can override this to prevent or intercept line reordering.
+ def OnChangeAttachment(self, attachment, line, ordering):
+ if self._previousHandler:
+ self._previousHandler.OnChangeAttachment(attachment, line, ordering)
+
+
+
+class Shape(ShapeEvtHandler):
+ """OGL base class
+
+ Shape(canvas = None)
+
+ The wxShape is the top-level, abstract object that all other objects
+ are derived from. All common functionality is represented by wxShape's
+ members, and overriden members that appear in derived classes and have
+ behaviour as documented for wxShape, are not documented separately.
+ """
+
+ GraphicsInSizeToContents = False
+
+ def __init__(self, canvas = None):
+ ShapeEvtHandler.__init__(self)
+
+ self._eventHandler = self
+ self.SetShape(self)
+ self._id = 0
+ self._formatted = False
+ self._canvas = canvas
+ self._xpos = 0.0
+ self._ypos = 0.0
+ self._pen = BlackForegroundPen
+ self._brush = wx.WHITE_BRUSH
+ self._font = NormalFont
+ self._textColour = wx.BLACK
+ self._textColourName = wx.BLACK
+ self._visible = False
+ self._selected = False
+ self._attachmentMode = ATTACHMENT_MODE_NONE
+ self._spaceAttachments = True
+ self._disableLabel = False
+ self._fixedWidth = False
+ self._fixedHeight = False
+ self._drawHandles = True
+ self._sensitivity = OP_ALL
+ self._draggable = True
+ self._parent = None
+ self._formatMode = FORMAT_CENTRE_HORIZ | FORMAT_CENTRE_VERT
+ self._shadowMode = SHADOW_NONE
+ self._shadowOffsetX = 6
+ self._shadowOffsetY = 6
+ self._shadowBrush = wx.BLACK_BRUSH
+ self._textMarginX = 5
+ self._textMarginY = 5
+ self._regionName = "0"
+ self._centreResize = True
+ self._maintainAspectRatio = False
+ self._highlighted = False
+ self._rotation = 0.0
+ self._branchNeckLength = 10
+ self._branchStemLength = 10
+ self._branchSpacing = 10
+ self._branchStyle = BRANCHING_ATTACHMENT_NORMAL
+
+ self._regions = []
+ self._lines = []
+ self._controlPoints = []
+ self._attachmentPoints = []
+ self._text = []
+ self._children = []
+
+ # Set up a default region. Much of the above will be put into
+ # the region eventually (the duplication is for compatibility)
+ region = ShapeRegion()
+ region.SetName("0")
+ region.SetFont(NormalFont)
+ region.SetFormatMode(FORMAT_CENTRE_HORIZ | FORMAT_CENTRE_VERT)
+ region.SetColour("BLACK")
+ self._regions.append(region)
+
+ def __str__(self):
+ return "<%s.%s>" % (self.__class__.__module__, self.__class__.__name__)
+
+ def GetClassName(self):
+ return str(self.__class__).split(".")[-1][:-2]
+
+ def Delete(self):
+ """
+ Fully disconnect this shape from parents, children, the
+ canvas, etc.
+ """
+ if self._parent:
+ self._parent.GetChildren().remove(self)
+
+ for child in self.GetChildren():
+ child.Delete()
+
+ self.ClearText()
+ self.ClearRegions()
+ self.ClearAttachments()
+
+ self._handlerShape = None
+
+ if self._canvas:
+ self.RemoveFromCanvas(self._canvas)
+
+ if self.GetEventHandler():
+ self.GetEventHandler().OnDelete()
+ self._eventHandler = None
+
+ def Draggable(self):
+ """TRUE if the shape may be dragged by the user."""
+ return True
+
+ def SetShape(self, sh):
+ self._handlerShape = sh
+
+ def GetCanvas(self):
+ """Get the internal canvas."""
+ return self._canvas
+
+ def GetBranchStyle(self):
+ return self._branchStyle
+
+ def GetRotation(self):
+ """Return the angle of rotation in radians."""
+ return self._rotation
+
+ def SetRotation(self, rotation):
+ self._rotation = rotation
+
+ def SetHighlight(self, hi, recurse = False):
+ """Set the highlight for a shape. Shape highlighting is unimplemented."""
+ self._highlighted = hi
+ if recurse:
+ for shape in self._children:
+ shape.SetHighlight(hi, recurse)
+
+ def SetSensitivityFilter(self, sens = OP_ALL, recursive = False):
+ """Set the shape to be sensitive or insensitive to specific mouse
+ operations.
+
+ sens is a bitlist of the following:
+
+ * OP_CLICK_LEFT
+ * OP_CLICK_RIGHT
+ * OP_DRAG_LEFT
+ * OP_DRAG_RIGHT
+ * OP_ALL (equivalent to a combination of all the above).
+ """
+ self._draggable = sens & OP_DRAG_LEFT
+
+ self._sensitivity = sens
+ if recursive:
+ for shape in self._children:
+ shape.SetSensitivityFilter(sens, True)
+
+ def SetDraggable(self, drag, recursive = False):
+ """Set the shape to be draggable or not draggable."""
+ self._draggable = drag
+ if drag:
+ self._sensitivity |= OP_DRAG_LEFT
+ elif self._sensitivity & OP_DRAG_LEFT:
+ self._sensitivity -= OP_DRAG_LEFT
+
+ if recursive:
+ for shape in self._children:
+ shape.SetDraggable(drag, True)
+
+ def SetDrawHandles(self, drawH):
+ """Set the drawHandles flag for this shape and all descendants.
+ If drawH is TRUE (the default), any handles (control points) will
+ be drawn. Otherwise, the handles will not be drawn.
+ """
+ self._drawHandles = drawH
+ for shape in self._children:
+ shape.SetDrawHandles(drawH)
+
+ def SetShadowMode(self, mode, redraw = False):
+ """Set the shadow mode (whether a shadow is drawn or not).
+ mode can be one of the following:
+
+ SHADOW_NONE
+ No shadow (the default).
+ SHADOW_LEFT
+ Shadow on the left side.
+ SHADOW_RIGHT
+ Shadow on the right side.
+ """
+ if redraw and self.GetCanvas():
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+ self.Erase(dc)
+ self._shadowMode = mode
+ self.Draw(dc)
+ else:
+ self._shadowMode = mode
+
+ def GetShadowMode(self):
+ """Return the current shadow mode setting"""
+ return self._shadowMode
+
+ def SetCanvas(self, theCanvas):
+ """Identical to Shape.Attach."""
+ self._canvas = theCanvas
+ for shape in self._children:
+ shape.SetCanvas(theCanvas)
+
+ def AddToCanvas(self, theCanvas, addAfter = None):
+ """Add the shape to the canvas's shape list.
+ If addAfter is non-NULL, will add the shape after this one.
+ """
+ theCanvas.AddShape(self, addAfter)
+
+ lastImage = self
+ for object in self._children:
+ object.AddToCanvas(theCanvas, lastImage)
+ lastImage = object
+
+ def InsertInCanvas(self, theCanvas):
+ """Insert the shape at the front of the shape list of canvas."""
+ theCanvas.InsertShape(self)
+
+ lastImage = self
+ for object in self._children:
+ object.AddToCanvas(theCanvas, lastImage)
+ lastImage = object
+
+ def RemoveFromCanvas(self, theCanvas):
+ """Remove the shape from the canvas."""
+ if self.Selected():
+ self.Select(False)
+
+ self._canvas = None
+ theCanvas.RemoveShape(self)
+ for object in self._children:
+ object.RemoveFromCanvas(theCanvas)
+
+ def ClearAttachments(self):
+ """Clear internal custom attachment point shapes (of class
+ wxAttachmentPoint).
+ """
+ self._attachmentPoints = []
+
+ def ClearText(self, regionId = 0):
+ """Clear the text from the specified text region."""
+ if regionId == 0:
+ self._text = ""
+ if regionId < len(self._regions):
+ self._regions[regionId].ClearText()
+
+ def ClearRegions(self):
+ """Clear the ShapeRegions from the shape."""
+ self._regions = []
+
+ def AddRegion(self, region):
+ """Add a region to the shape."""
+ self._regions.append(region)
+
+ def SetDefaultRegionSize(self):
+ """Set the default region to be consistent with the shape size."""
+ if not self._regions:
+ return
+ w, h = self.GetBoundingBoxMax()
+ self._regions[0].SetSize(w, h)
+
+ def HitTest(self, x, y):
+ """Given a point on a canvas, returns TRUE if the point was on the
+ shape, and returns the nearest attachment point and distance from
+ the given point and target.
+ """
+ width, height = self.GetBoundingBoxMax()
+ if abs(width) < 4:
+ width = 4.0
+ if abs(height) < 4:
+ height = 4.0
+
+ width += 4 # Allowance for inaccurate mousing
+ height += 4
+
+ left = self._xpos - width / 2.0
+ top = self._ypos - height / 2.0
+ right = self._xpos + width / 2.0
+ bottom = self._ypos + height / 2.0
+
+ nearest_attachment = 0
+
+ # If within the bounding box, check the attachment points
+ # within the object.
+ if x >= left and x <= right and y >= top and y <= bottom:
+ n = self.GetNumberOfAttachments()
+ nearest = 999999
+
+ # GetAttachmentPosition[Edge] takes a logical attachment position,
+ # i.e. if it's rotated through 90%, position 0 is East-facing.
+
+ for i in range(n):
+ e = self.GetAttachmentPositionEdge(i)
+ if e:
+ xp, yp = e
+ l = math.sqrt(((xp - x) * (xp - x)) + (yp - y) * (yp - y))
+ if l < nearest:
+ nearest = l
+ nearest_attachment = i
+
+ return nearest_attachment, nearest
+ return False
+
+ # Format a text string according to the region size, adding
+ # strings with positions to region text list
+
+ def FormatText(self, dc, s, i = 0):
+ """Reformat the given text region; defaults to formatting the
+ default region.
+ """
+ self.ClearText(i)
+
+ if not self._regions:
+ return
+
+ if i >= len(self._regions):
+ return
+
+ region = self._regions[i]
+ region._regionText = s
+ dc.SetFont(region.GetFont())
+
+ w, h = region.GetSize()
+
+ stringList = FormatText(dc, s, (w - 2 * self._textMarginX), (h - 2 * self._textMarginY), region.GetFormatMode())
+ for s in stringList:
+ line = ShapeTextLine(0.0, 0.0, s)
+ region.GetFormattedText().append(line)
+
+ actualW = w
+ actualH = h
+ # Don't try to resize an object with more than one image (this
+ # case should be dealt with by overriden handlers)
+ if (region.GetFormatMode() & FORMAT_SIZE_TO_CONTENTS) and \
+ len(region.GetFormattedText()) and \
+ len(self._regions) == 1 and \
+ not Shape.GraphicsInSizeToContents:
+
+ actualW, actualH = GetCentredTextExtent(dc, region.GetFormattedText())
+ if actualW + 2 * self._textMarginX != w or actualH + 2 * self._textMarginY != h:
+ # If we are a descendant of a composite, must make sure
+ # the composite gets resized properly
+
+ topAncestor = self.GetTopAncestor()
+ if topAncestor != self:
+ Shape.GraphicsInSizeToContents = True
+
+ composite = topAncestor
+ composite.Erase(dc)
+ self.SetSize(actualW + 2 * self._textMarginX, actualH + 2 * self._textMarginY)
+ self.Move(dc, self._xpos, self._ypos)
+ composite.CalculateSize()
+ if composite.Selected():
+ composite.DeleteControlPoints(dc)
+ composite.MakeControlPoints()
+ composite.MakeMandatoryControlPoints()
+ # Where infinite recursion might happen if we didn't stop it
+ composite.Draw(dc)
+ Shape.GraphicsInSizeToContents = False
+ else:
+ self.Erase(dc)
+
+ self.SetSize(actualW + 2 * self._textMarginX, actualH + 2 * self._textMarginY)
+ self.Move(dc, self._xpos, self._ypos)
+ self.EraseContents(dc)
+ CentreText(dc, region.GetFormattedText(), self._xpos, self._ypos, actualW - 2 * self._textMarginX, actualH - 2 * self._textMarginY, region.GetFormatMode())
+ self._formatted = True
+
+ def Recentre(self, dc):
+ """Do recentring (or other formatting) for all the text regions
+ for this shape.
+ """
+ w, h = self.GetBoundingBoxMin()
+ for region in self._regions:
+ CentreText(dc, region.GetFormattedText(), self._xpos, self._ypos, w - 2 * self._textMarginX, h - 2 * self._textMarginY, region.GetFormatMode())
+
+ def GetPerimeterPoint(self, x1, y1, x2, y2):
+ """Get the point at which the line from (x1, y1) to (x2, y2) hits
+ the shape. Returns False if the line doesn't hit the perimeter.
+ """
+ return False
+
+ def SetPen(self, the_pen):
+ """Set the pen for drawing the shape's outline."""
+ self._pen = the_pen
+
+ def SetBrush(self, the_brush):
+ """Set the brush for filling the shape's shape."""
+ self._brush = the_brush
+
+ # Get the top - most (non-division) ancestor, or self
+ def GetTopAncestor(self):
+ """Return the top-most ancestor of this shape (the root of
+ the composite).
+ """
+ if not self.GetParent():
+ return self
+
+ if isinstance(self.GetParent(), DivisionShape):
+ return self
+ return self.GetParent().GetTopAncestor()
+
+ # Region functions
+ def SetFont(self, the_font, regionId = 0):
+ """Set the font for the specified text region."""
+ self._font = the_font
+ if regionId < len(self._regions):
+ self._regions[regionId].SetFont(the_font)
+
+ def GetFont(self, regionId = 0):
+ """Get the font for the specified text region."""
+ if regionId >= len(self._regions):
+ return None
+ return self._regions[regionId].GetFont()
+
+ def SetFormatMode(self, mode, regionId = 0):
+ """Set the format mode of the default text region. The argument
+ can be a bit list of the following:
+
+ FORMAT_NONE
+ No formatting.
+ FORMAT_CENTRE_HORIZ
+ Horizontal centring.
+ FORMAT_CENTRE_VERT
+ Vertical centring.
+ """
+ if regionId < len(self._regions):
+ self._regions[regionId].SetFormatMode(mode)
+
+ def GetFormatMode(self, regionId = 0):
+ if regionId >= len(self._regions):
+ return 0
+ return self._regions[regionId].GetFormatMode()
+
+ def SetTextColour(self, the_colour, regionId = 0):
+ """Set the colour for the specified text region."""
+ self._textColour = wx.TheColourDatabase.Find(the_colour)
+ self._textColourName = the_colour
+
+ if regionId < len(self._regions):
+ self._regions[regionId].SetColour(the_colour)
+
+ def GetTextColour(self, regionId = 0):
+ """Get the colour for the specified text region."""
+ if regionId >= len(self._regions):
+ return ""
+ return self._regions[regionId].GetColour()
+
+ def SetRegionName(self, name, regionId = 0):
+ """Set the name for this region.
+ The name for a region is unique within the scope of the whole
+ composite, whereas a region id is unique only for a single image.
+ """
+ if regionId < len(self._regions):
+ self._regions[regionId].SetName(name)
+
+ def GetRegionName(self, regionId = 0):
+ """Get the region's name.
+ A region's name can be used to uniquely determine a region within
+ an entire composite image hierarchy. See also Shape.SetRegionName.
+ """
+ if regionId >= len(self._regions):
+ return ""
+ return self._regions[regionId].GetName()
+
+ def GetRegionId(self, name):
+ """Get the region's identifier by name.
+ This is not unique for within an entire composite, but is unique
+ for the image.
+ """
+ for i, r in enumerate(self._regions):
+ if r.GetName() == name:
+ return i
+ return -1
+
+ # Name all _regions in all subimages recursively
+ def NameRegions(self, parentName=""):
+ """Make unique names for all the regions in a shape or composite shape."""
+ n = self.GetNumberOfTextRegions()
+ for i in range(n):
+ if parentName:
+ buff = parentName+"."+str(i)
+ else:
+ buff = str(i)
+ self.SetRegionName(buff, i)
+
+ for j, child in enumerate(self._children):
+ if parentName:
+ buff = parentName+"."+str(j)
+ else:
+ buff = str(j)
+ child.NameRegions(buff)
+
+ # Get a region by name, possibly looking recursively into composites
+ def FindRegion(self, name):
+ """Find the actual image ('this' if non-composite) and region id
+ for the given region name.
+ """
+ id = self.GetRegionId(name)
+ if id > -1:
+ return self, id
+
+ for child in self._children:
+ actualImage, regionId = child.FindRegion(name)
+ if actualImage:
+ return actualImage, regionId
+
+ return None, -1
+
+ # Finds all region names for this image (composite or simple).
+ def FindRegionNames(self):
+ """Get a list of all region names for this image (composite or simple)."""
+ list = []
+ n = self.GetNumberOfTextRegions()
+ for i in range(n):
+ list.append(self.GetRegionName(i))
+
+ for child in self._children:
+ list += child.FindRegionNames()
+
+ return list
+
+ def AssignNewIds(self):
+ """Assign new ids to this image and its children."""
+ self._id = wx.NewId()
+ for child in self._children:
+ child.AssignNewIds()
+
+ def OnDraw(self, dc):
+ pass
+
+ def OnMoveLinks(self, dc):
+ # Want to set the ends of all attached links
+ # to point to / from this object
+
+ for line in self._lines:
+ line.GetEventHandler().OnMoveLink(dc)
+
+ def OnDrawContents(self, dc):
+ if not self._regions:
+ return
+
+ bound_x, bound_y = self.GetBoundingBoxMin()
+
+ if self._pen:
+ dc.SetPen(self._pen)
+
+ for region in self._regions:
+ if region.GetFont():
+ dc.SetFont(region.GetFont())
+
+ dc.SetTextForeground(region.GetActualColourObject())
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ if not self._formatted:
+ CentreText(dc, region.GetFormattedText(), self._xpos, self._ypos, bound_x - 2 * self._textMarginX, bound_y - 2 * self._textMarginY, region.GetFormatMode())
+ self._formatted = True
+
+ if not self.GetDisableLabel():
+ DrawFormattedText(dc, region.GetFormattedText(), self._xpos, self._ypos, bound_x - 2 * self._textMarginX, bound_y - 2 * self._textMarginY, region.GetFormatMode())
+
+
+ def DrawContents(self, dc):
+ """Draw the internal graphic of the shape (such as text).
+
+ Do not override this function: override OnDrawContents, which
+ is called by this function.
+ """
+ self.GetEventHandler().OnDrawContents(dc)
+
+ def OnSize(self, x, y):
+ pass
+
+ def OnMovePre(self, dc, x, y, old_x, old_y, display = True):
+ return True
+
+ def OnErase(self, dc):
+ if not self._visible:
+ return
+
+ # Erase links
+ for line in self._lines:
+ line.GetEventHandler().OnErase(dc)
+
+ self.GetEventHandler().OnEraseContents(dc)
+
+ def OnEraseContents(self, dc):
+ if not self._visible:
+ return
+
+ xp, yp = self.GetX(), self.GetY()
+ minX, minY = self.GetBoundingBoxMin()
+ maxX, maxY = self.GetBoundingBoxMax()
+
+ topLeftX = xp - maxX / 2.0 - 2
+ topLeftY = yp - maxY / 2.0 - 2
+
+ penWidth = 0
+ if self._pen:
+ penWidth = self._pen.GetWidth()
+
+ dc.SetPen(self.GetBackgroundPen())
+ dc.SetBrush(self.GetBackgroundBrush())
+
+ dc.DrawRectangle(topLeftX - penWidth, topLeftY - penWidth, maxX + penWidth * 2 + 4, maxY + penWidth * 2 + 4)
+
+ def EraseLinks(self, dc, attachment = -1, recurse = False):
+ """Erase links attached to this shape, but do not repair damage
+ caused to other shapes.
+ """
+ if not self._visible:
+ return
+
+ for line in self._lines:
+ if attachment == -1 or (line.GetTo() == self and line.GetAttachmentTo() == attachment or line.GetFrom() == self and line.GetAttachmentFrom() == attachment):
+ line.GetEventHandler().OnErase(dc)
+
+ if recurse:
+ for child in self._children:
+ child.EraseLinks(dc, attachment, recurse)
+
+ def DrawLinks(self, dc, attachment = -1, recurse = False):
+ """Draws any lines linked to this shape."""
+ if not self._visible:
+ return
+
+ for line in self._lines:
+ if attachment == -1 or (line.GetTo() == self and line.GetAttachmentTo() == attachment or line.GetFrom() == self and line.GetAttachmentFrom() == attachment):
+ line.Draw(dc)
+
+ if recurse:
+ for child in self._children:
+ child.DrawLinks(dc, attachment, recurse)
+
+ # Returns TRUE if pt1 <= pt2 in the sense that one point comes before
+ # another on an edge of the shape.
+ # attachmentPoint is the attachment point (= side) in question.
+
+ # This is the default, rectangular implementation.
+ def AttachmentSortTest(self, attachmentPoint, pt1, pt2):
+ """Return TRUE if pt1 is less than or equal to pt2, in the sense
+ that one point comes before another on an edge of the shape.
+
+ attachment is the attachment point (side) in question.
+
+ This function is used in Shape.MoveLineToNewAttachment to determine
+ the new line ordering.
+ """
+ physicalAttachment = self.LogicalToPhysicalAttachment(attachmentPoint)
+ if physicalAttachment in [0, 2]:
+ return pt1[0] <= pt2[0]
+ elif physicalAttachment in [1, 3]:
+ return pt1[1] <= pt2[1]
+
+ return False
+
+ def MoveLineToNewAttachment(self, dc, to_move, x, y):
+ """Move the given line (which must already be attached to the shape)
+ to a different attachment point on the shape, or a different order
+ on the same attachment.
+
+ Calls Shape.AttachmentSortTest and then
+ ShapeEvtHandler.OnChangeAttachment.
+ """
+ if self.GetAttachmentMode() == ATTACHMENT_MODE_NONE:
+ return False
+
+ # Is (x, y) on this object? If so, find the new attachment point
+ # the user has moved the point to
+ hit = self.HitTest(x, y)
+ if not hit:
+ return False
+
+ newAttachment, distance = hit
+
+ self.EraseLinks(dc)
+
+ if to_move.GetTo() == self:
+ oldAttachment = to_move.GetAttachmentTo()
+ else:
+ oldAttachment = to_move.GetAttachmentFrom()
+
+ # The links in a new ordering
+ # First, add all links to the new list
+ newOrdering = self._lines[:]
+
+ # Delete the line object from the list of links; we're going to move
+ # it to another position in the list
+ del newOrdering[newOrdering.index(to_move)]
+
+ old_x = -99999.9
+ old_y = -99999.9
+
+ found = False
+
+ for line in newOrdering:
+ if line.GetTo() == self and oldAttachment == line.GetAttachmentTo() or \
+ line.GetFrom() == self and oldAttachment == line.GetAttachmentFrom():
+ startX, startY, endX, endY = line.GetEnds()
+ if line.GetTo() == self:
+ xp = endX
+ yp = endY
+ else:
+ xp = startX
+ yp = startY
+
+ thisPoint = wx.RealPoint(xp, yp)
+ lastPoint = wx.RealPoint(old_x, old_y)
+ newPoint = wx.RealPoint(x, y)
+
+ if self.AttachmentSortTest(newAttachment, newPoint, thisPoint) and self.AttachmentSortTest(newAttachment, lastPoint, newPoint):
+ found = True
+ newOrdering.insert(newOrdering.index(line), to_move)
+
+ old_x = xp
+ old_y = yp
+ if found:
+ break
+
+ if not found:
+ newOrdering.append(to_move)
+
+ self.GetEventHandler().OnChangeAttachment(newAttachment, to_move, newOrdering)
+ return True
+
+ def OnChangeAttachment(self, attachment, line, ordering):
+ if line.GetTo() == self:
+ line.SetAttachmentTo(attachment)
+ else:
+ line.SetAttachmentFrom(attachment)
+
+ self.ApplyAttachmentOrdering(ordering)
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+ self.MoveLinks(dc)
+
+ if not self.GetCanvas().GetQuickEditMode():
+ self.GetCanvas().Redraw(dc)
+
+ # Reorders the lines according to the given list
+ def ApplyAttachmentOrdering(self, linesToSort):
+ """Apply the line ordering in linesToSort to the shape, to reorder
+ the way lines are attached.
+ """
+ linesStore = self._lines[:]
+
+ self._lines = []
+
+ for line in linesToSort:
+ if line in linesStore:
+ del linesStore[linesStore.index(line)]
+ self._lines.append(line)
+
+ # Now add any lines that haven't been listed in linesToSort
+ self._lines += linesStore
+
+ def SortLines(self, attachment, linesToSort):
+ """ Reorder the lines coming into the node image at this attachment
+ position, in the order in which they appear in linesToSort.
+
+ Any remaining lines not in the list will be added to the end.
+ """
+ # This is a temporary store of all the lines at this attachment
+ # point. We'll tick them off as we've processed them.
+ linesAtThisAttachment = []
+
+ for line in self._lines[:]:
+ if line.GetTo() == self and line.GetAttachmentTo() == attachment or \
+ line.GetFrom() == self and line.GetAttachmentFrom() == attachment:
+ linesAtThisAttachment.append(line)
+ del self._lines[self._lines.index(line)]
+
+ for line in linesToSort:
+ if line in linesAtThisAttachment:
+ # Done this one
+ del linesAtThisAttachment[linesAtThisAttachment.index(line)]
+ self._lines.append(line)
+
+ # Now add any lines that haven't been listed in linesToSort
+ self._lines += linesAtThisAttachment
+
+ def OnHighlight(self, dc):
+ pass
+
+ def OnLeftClick(self, x, y, keys = 0, attachment = 0):
+ if self._sensitivity & OP_CLICK_LEFT != OP_CLICK_LEFT:
+ if self._parent:
+ attachment, dist = self._parent.HitTest(x, y)
+ self._parent.GetEventHandler().OnLeftClick(x, y, keys, attachment)
+
+ def OnRightClick(self, x, y, keys = 0, attachment = 0):
+ if self._sensitivity & OP_CLICK_RIGHT != OP_CLICK_RIGHT:
+ attachment, dist = self._parent.HitTest(x, y)
+ self._parent.GetEventHandler().OnRightClick(x, y, keys, attachment)
+
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ if self._sensitivity & OP_DRAG_LEFT != OP_DRAG_LEFT:
+ if self._parent:
+ hit = self._parent.HitTest(x, y)
+ if hit:
+ attachment, dist = hit
+ self._parent.GetEventHandler().OnDragLeft(draw, x, y, keys, attachment)
+ return
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+ dc.SetLogicalFunction(OGLRBLF)
+
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ xx = x + DragOffsetX
+ yy = y + DragOffsetY
+
+ xx, yy = self._canvas.Snap(xx, yy)
+ w, h = self.GetBoundingBoxMax()
+ self.GetEventHandler().OnDrawOutline(dc, xx, yy, w, h)
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ global DragOffsetX, DragOffsetY
+
+ if self._sensitivity & OP_DRAG_LEFT != OP_DRAG_LEFT:
+ if self._parent:
+ hit = self._parent.HitTest(x, y)
+ if hit:
+ attachment, dist = hit
+ self._parent.GetEventHandler().OnBeginDragLeft(x, y, keys, attachment)
+ return
+
+ DragOffsetX = self._xpos - x
+ DragOffsetY = self._ypos - y
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ # New policy: don't erase shape until end of drag.
+ # self.Erase(dc)
+ xx = x + DragOffsetX
+ yy = y + DragOffsetY
+ xx, yy = self._canvas.Snap(xx, yy)
+ dc.SetLogicalFunction(OGLRBLF)
+
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ w, h = self.GetBoundingBoxMax()
+ self.GetEventHandler().OnDrawOutline(dc, xx, yy, w, h)
+ self._canvas.CaptureMouse()
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ if self._canvas.HasCapture():
+ self._canvas.ReleaseMouse()
+ if self._sensitivity & OP_DRAG_LEFT != OP_DRAG_LEFT:
+ if self._parent:
+ hit = self._parent.HitTest(x, y)
+ if hit:
+ attachment, dist = hit
+ self._parent.GetEventHandler().OnEndDragLeft(x, y, keys, attachment)
+ return
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dc.SetLogicalFunction(wx.COPY)
+ xx = x + DragOffsetX
+ yy = y + DragOffsetY
+ xx, yy = self._canvas.Snap(xx, yy)
+
+ # New policy: erase shape at end of drag.
+ self.Erase(dc)
+
+ self.Move(dc, xx, yy)
+ if self._canvas and not self._canvas.GetQuickEditMode():
+ self._canvas.Redraw(dc)
+
+ def OnDragRight(self, draw, x, y, keys = 0, attachment = 0):
+ if self._sensitivity & OP_DRAG_RIGHT != OP_DRAG_RIGHT:
+ if self._parent:
+ attachment, dist = self._parent.HitTest(x, y)
+ self._parent.GetEventHandler().OnDragRight(draw, x, y, keys, attachment)
+ return
+
+ def OnBeginDragRight(self, x, y, keys = 0, attachment = 0):
+ if self._sensitivity & OP_DRAG_RIGHT != OP_DRAG_RIGHT:
+ if self._parent:
+ attachment, dist = self._parent.HitTest(x, y)
+ self._parent.GetEventHandler().OnBeginDragRight(x, y, keys, attachment)
+ return
+
+ def OnEndDragRight(self, x, y, keys = 0, attachment = 0):
+ if self._sensitivity & OP_DRAG_RIGHT != OP_DRAG_RIGHT:
+ if self._parent:
+ attachment, dist = self._parent.HitTest(x, y)
+ self._parent.GetEventHandler().OnEndDragRight(x, y, keys, attachment)
+ return
+
+ def OnDrawOutline(self, dc, x, y, w, h):
+ points = [[x - w / 2.0, y - h / 2.0],
+ [x + w / 2.0, y - h / 2.0],
+ [x + w / 2.0, y + h / 2.0],
+ [x - w / 2.0, y + h / 2.0],
+ [x - w / 2.0, y - h / 2.0],
+ ]
+
+ dc.DrawLines(points)
+
+ def Attach(self, can):
+ """Set the shape's internal canvas pointer to point to the given canvas."""
+ self._canvas = can
+
+ def Detach(self):
+ """Disassociates the shape from its canvas."""
+ self._canvas = None
+
+ def Move(self, dc, x, y, display = True):
+ """Move the shape to the given position.
+ Redraw if display is TRUE.
+ """
+ old_x = self._xpos
+ old_y = self._ypos
+
+ if not self.GetEventHandler().OnMovePre(dc, x, y, old_x, old_y, display):
+ return
+
+ self._xpos, self._ypos = x, y
+
+ self.ResetControlPoints()
+
+ if display:
+ self.Draw(dc)
+
+ self.MoveLinks(dc)
+
+ self.GetEventHandler().OnMovePost(dc, x, y, old_x, old_y, display)
+
+ def MoveLinks(self, dc):
+ """Redraw all the lines attached to the shape."""
+ self.GetEventHandler().OnMoveLinks(dc)
+
+ def Draw(self, dc):
+ """Draw the whole shape and any lines attached to it.
+
+ Do not override this function: override OnDraw, which is called
+ by this function.
+ """
+ if self._visible:
+ self.GetEventHandler().OnDraw(dc)
+ self.GetEventHandler().OnDrawContents(dc)
+ self.GetEventHandler().OnDrawControlPoints(dc)
+ self.GetEventHandler().OnDrawBranches(dc)
+
+ def Flash(self):
+ """Flash the shape."""
+ if self.GetCanvas():
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dc.SetLogicalFunction(OGLRBLF)
+ self.Draw(dc)
+ dc.SetLogicalFunction(wx.COPY)
+ self.Draw(dc)
+
+ def Show(self, show):
+ """Set a flag indicating whether the shape should be drawn."""
+ self._visible = show
+ for child in self._children:
+ child.Show(show)
+
+ def Erase(self, dc):
+ """Erase the shape.
+ Does not repair damage caused to other shapes.
+ """
+ self.GetEventHandler().OnErase(dc)
+ self.GetEventHandler().OnEraseControlPoints(dc)
+ self.GetEventHandler().OnDrawBranches(dc, erase = True)
+
+ def EraseContents(self, dc):
+ """Erase the shape contents, that is, the area within the shape's
+ minimum bounding box.
+ """
+ self.GetEventHandler().OnEraseContents(dc)
+
+ def AddText(self, string):
+ """Add a line of text to the shape's default text region."""
+ if not self._regions:
+ return
+
+ region = self._regions[0]
+ #region.ClearText()
+ new_line = ShapeTextLine(0, 0, string)
+ text = region.GetFormattedText()
+ text.append(new_line)
+
+ self._formatted = False
+
+ def SetSize(self, x, y, recursive = True):
+ """Set the shape's size."""
+ self.SetAttachmentSize(x, y)
+ self.SetDefaultRegionSize()
+
+ def SetAttachmentSize(self, w, h):
+ width, height = self.GetBoundingBoxMin()
+ if width == 0:
+ scaleX = 1.0
+ else:
+ scaleX = float(w) / width
+ if height == 0:
+ scaleY = 1.0
+ else:
+ scaleY = float(h) / height
+
+ for point in self._attachmentPoints:
+ point._x = point._x * scaleX
+ point._y = point._y * scaleY
+
+ # Add line FROM this object
+ def AddLine(self, line, other, attachFrom = 0, attachTo = 0, positionFrom = -1, positionTo = -1):
+ """Add a line between this shape and the given other shape, at the
+ specified attachment points.
+
+ The position in the list of lines at each end can also be specified,
+ so that the line will be drawn at a particular point on its attachment
+ point.
+ """
+ if positionFrom == -1:
+ if not line in self._lines:
+ self._lines.append(line)
+ else:
+ # Don't preserve old ordering if we have new ordering instructions
+ try:
+ self._lines.remove(line)
+ except ValueError:
+ pass
+ if positionFrom < len(self._lines):
+ self._lines.insert(positionFrom, line)
+ else:
+ self._lines.append(line)
+
+ if positionTo == -1:
+ if not other in other._lines:
+ other._lines.append(line)
+ else:
+ # Don't preserve old ordering if we have new ordering instructions
+ try:
+ other._lines.remove(line)
+ except ValueError:
+ pass
+ if positionTo < len(other._lines):
+ other._lines.insert(positionTo, line)
+ else:
+ other._lines.append(line)
+
+ line.SetFrom(self)
+ line.SetTo(other)
+ line.SetAttachments(attachFrom, attachTo)
+
+ dc = wx.ClientDC(self._canvas)
+ self._canvas.PrepareDC(dc)
+ self.MoveLinks(dc)
+
+ def RemoveLine(self, line):
+ """Remove the given line from the shape's list of attached lines."""
+ if line.GetFrom() == self:
+ line.GetTo()._lines.remove(line)
+ else:
+ line.GetFrom()._lines.remove(line)
+
+ self._lines.remove(line)
+
+ # Default - make 6 control points
+ def MakeControlPoints(self):
+ """Make a list of control points (draggable handles) appropriate to
+ the shape.
+ """
+ maxX, maxY = self.GetBoundingBoxMax()
+ minX, minY = self.GetBoundingBoxMin()
+
+ widthMin = minX + CONTROL_POINT_SIZE + 2
+ heightMin = minY + CONTROL_POINT_SIZE + 2
+
+ # Offsets from main object
+ top = -heightMin / 2.0
+ bottom = heightMin / 2.0 + (maxY - minY)
+ left = -widthMin / 2.0
+ right = widthMin / 2.0 + (maxX - minX)
+
+ control = ControlPoint(self._canvas, self, CONTROL_POINT_SIZE, left, top, CONTROL_POINT_DIAGONAL)
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ control = ControlPoint(self._canvas, self, CONTROL_POINT_SIZE, 0, top, CONTROL_POINT_VERTICAL)
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ control = ControlPoint(self._canvas, self, CONTROL_POINT_SIZE, right, top, CONTROL_POINT_DIAGONAL)
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ control = ControlPoint(self._canvas, self, CONTROL_POINT_SIZE, right, 0, CONTROL_POINT_HORIZONTAL)
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ control = ControlPoint(self._canvas, self, CONTROL_POINT_SIZE, right, bottom, CONTROL_POINT_DIAGONAL)
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ control = ControlPoint(self._canvas, self, CONTROL_POINT_SIZE, 0, bottom, CONTROL_POINT_VERTICAL)
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ control = ControlPoint(self._canvas, self, CONTROL_POINT_SIZE, left, bottom, CONTROL_POINT_DIAGONAL)
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ control = ControlPoint(self._canvas, self, CONTROL_POINT_SIZE, left, 0, CONTROL_POINT_HORIZONTAL)
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ def MakeMandatoryControlPoints(self):
+ """Make the mandatory control points.
+
+ For example, the control point on a dividing line should appear even
+ if the divided rectangle shape's handles should not appear (because
+ it is the child of a composite, and children are not resizable).
+ """
+ for child in self._children:
+ child.MakeMandatoryControlPoints()
+
+ def ResetMandatoryControlPoints(self):
+ """Reset the mandatory control points."""
+ for child in self._children:
+ child.ResetMandatoryControlPoints()
+
+ def ResetControlPoints(self):
+ """Reset the positions of the control points (for instance when the
+ shape's shape has changed).
+ """
+ self.ResetMandatoryControlPoints()
+
+ if len(self._controlPoints) == 0:
+ return
+
+ maxX, maxY = self.GetBoundingBoxMax()
+ minX, minY = self.GetBoundingBoxMin()
+
+ widthMin = minX + CONTROL_POINT_SIZE + 2
+ heightMin = minY + CONTROL_POINT_SIZE + 2
+
+ # Offsets from main object
+ top = -heightMin / 2.0
+ bottom = heightMin / 2.0 + (maxY - minY)
+ left = -widthMin / 2.0
+ right = widthMin / 2.0 + (maxX - minX)
+
+ self._controlPoints[0]._xoffset = left
+ self._controlPoints[0]._yoffset = top
+
+ self._controlPoints[1]._xoffset = 0
+ self._controlPoints[1]._yoffset = top
+
+ self._controlPoints[2]._xoffset = right
+ self._controlPoints[2]._yoffset = top
+
+ self._controlPoints[3]._xoffset = right
+ self._controlPoints[3]._yoffset = 0
+
+ self._controlPoints[4]._xoffset = right
+ self._controlPoints[4]._yoffset = bottom
+
+ self._controlPoints[5]._xoffset = 0
+ self._controlPoints[5]._yoffset = bottom
+
+ self._controlPoints[6]._xoffset = left
+ self._controlPoints[6]._yoffset = bottom
+
+ self._controlPoints[7]._xoffset = left
+ self._controlPoints[7]._yoffset = 0
+
+ def DeleteControlPoints(self, dc = None):
+ """Delete the control points (or handles) for the shape.
+
+ Does not redraw the shape.
+ """
+ for control in self._controlPoints[:]:
+ if dc:
+ control.GetEventHandler().OnErase(dc)
+ control.Delete()
+ self._controlPoints.remove(control)
+ self._controlPoints = []
+
+ # Children of divisions are contained objects,
+ # so stop here
+ if not isinstance(self, DivisionShape):
+ for child in self._children:
+ child.DeleteControlPoints(dc)
+
+ def OnDrawControlPoints(self, dc):
+ if not self._drawHandles:
+ return
+
+ dc.SetBrush(wx.BLACK_BRUSH)
+ dc.SetPen(wx.BLACK_PEN)
+
+ for control in self._controlPoints:
+ control.Draw(dc)
+
+ # Children of divisions are contained objects,
+ # so stop here.
+ # This test bypasses the type facility for speed
+ # (critical when drawing)
+
+ if not isinstance(self, DivisionShape):
+ for child in self._children:
+ child.GetEventHandler().OnDrawControlPoints(dc)
+
+ def OnEraseControlPoints(self, dc):
+ for control in self._controlPoints:
+ control.Erase(dc)
+
+ if not isinstance(self, DivisionShape):
+ for child in self._children:
+ child.GetEventHandler().OnEraseControlPoints(dc)
+
+ def Select(self, select, dc = None):
+ """Select or deselect the given shape, drawing or erasing control points
+ (handles) as necessary.
+ """
+ self._selected = select
+ if select:
+ self.MakeControlPoints()
+ # Children of divisions are contained objects,
+ # so stop here
+ if not isinstance(self, DivisionShape):
+ for child in self._children:
+ child.MakeMandatoryControlPoints()
+ if dc:
+ self.GetEventHandler().OnDrawControlPoints(dc)
+ else:
+ self.DeleteControlPoints(dc)
+ if not isinstance(self, DivisionShape):
+ for child in self._children:
+ child.DeleteControlPoints(dc)
+
+ def Selected(self):
+ """TRUE if the shape is currently selected."""
+ return self._selected
+
+ def AncestorSelected(self):
+ """TRUE if the shape's ancestor is currently selected."""
+ if self._selected:
+ return True
+ if not self.GetParent():
+ return False
+ return self.GetParent().AncestorSelected()
+
+ def GetNumberOfAttachments(self):
+ """Get the number of attachment points for this shape."""
+ # Should return the MAXIMUM attachment point id here,
+ # so higher-level functions can iterate through all attachments,
+ # even if they're not contiguous.
+
+ if len(self._attachmentPoints) == 0:
+ return 4
+ else:
+ maxN = 3
+ for point in self._attachmentPoints:
+ if point._id > maxN:
+ maxN = point._id
+ return maxN + 1
+
+ def AttachmentIsValid(self, attachment):
+ """TRUE if attachment is a valid attachment point."""
+ if len(self._attachmentPoints) == 0:
+ return attachment in range(4)
+
+ for point in self._attachmentPoints:
+ if point._id == attachment:
+ return True
+ return False
+
+ def GetAttachmentPosition(self, attachment, nth = 0, no_arcs = 1, line = None):
+ """Get the position at which the given attachment point should be drawn.
+
+ If attachment isn't found among the attachment points of the shape,
+ returns None.
+ """
+ if self._attachmentMode == ATTACHMENT_MODE_NONE:
+ return self._xpos, self._ypos
+ elif self._attachmentMode == ATTACHMENT_MODE_BRANCHING:
+ pt, stemPt = self.GetBranchingAttachmentPoint(attachment, nth)
+ return pt[0], pt[1]
+ elif self._attachmentMode == ATTACHMENT_MODE_EDGE:
+ if len(self._attachmentPoints):
+ for point in self._attachmentPoints:
+ if point._id == attachment:
+ return self._xpos + point._x, self._ypos + point._y
+ return None
+ else:
+ # Assume is rectangular
+ w, h = self.GetBoundingBoxMax()
+ top = self._ypos + h / 2.0
+ bottom = self._ypos - h / 2.0
+ left = self._xpos - w / 2.0
+ right = self._xpos + w / 2.0
+
+ # wtf?
+ line and line.IsEnd(self)
+
+ physicalAttachment = self.LogicalToPhysicalAttachment(attachment)
+
+ # Simplified code
+ if physicalAttachment == 0:
+ pt = self.CalcSimpleAttachment((left, bottom), (right, bottom), nth, no_arcs, line)
+ elif physicalAttachment == 1:
+ pt = self.CalcSimpleAttachment((right, bottom), (right, top), nth, no_arcs, line)
+ elif physicalAttachment == 2:
+ pt = self.CalcSimpleAttachment((left, top), (right, top), nth, no_arcs, line)
+ elif physicalAttachment == 3:
+ pt = self.CalcSimpleAttachment((left, bottom), (left, top), nth, no_arcs, line)
+ else:
+ return None
+ return pt[0], pt[1]
+ return None
+
+ def GetBoundingBoxMax(self):
+ """Get the maximum bounding box for the shape, taking into account
+ external features such as shadows.
+ """
+ ww, hh = self.GetBoundingBoxMin()
+ if self._shadowMode != SHADOW_NONE:
+ ww += self._shadowOffsetX
+ hh += self._shadowOffsetY
+ return ww, hh
+
+ def GetBoundingBoxMin(self):
+ """Get the minimum bounding box for the shape, that defines the area
+ available for drawing the contents (such as text).
+
+ Must be overridden.
+ """
+ return 0, 0
+
+ def HasDescendant(self, image):
+ """TRUE if image is a descendant of this composite."""
+ if image == self:
+ return True
+ for child in self._children:
+ if child.HasDescendant(image):
+ return True
+ return False
+
+ # Assuming the attachment lies along a vertical or horizontal line,
+ # calculate the position on that point.
+ def CalcSimpleAttachment(self, pt1, pt2, nth, noArcs, line):
+ """Assuming the attachment lies along a vertical or horizontal line,
+ calculate the position on that point.
+
+ Parameters:
+
+ pt1
+ The first point of the line repesenting the edge of the shape.
+
+ pt2
+ The second point of the line representing the edge of the shape.
+
+ nth
+ The position on the edge (for example there may be 6 lines at
+ this attachment point, and this may be the 2nd line.
+
+ noArcs
+ The number of lines at this edge.
+
+ line
+ The line shape.
+
+ Remarks
+
+ This function expects the line to be either vertical or horizontal,
+ and determines which.
+ """
+ isEnd = line and line.IsEnd(self)
+
+ # Are we horizontal or vertical?
+ isHorizontal = RoughlyEqual(pt1[1], pt2[1])
+
+ if isHorizontal:
+ if pt1[0] > pt2[0]:
+ firstPoint = pt2
+ secondPoint = pt1
+ else:
+ firstPoint = pt1
+ secondPoint = pt2
+
+ if self._spaceAttachments:
+ if line and line.GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ # Align line according to the next handle along
+ point = line.GetNextControlPoint(self)
+ if point[0] < firstPoint[0]:
+ x = firstPoint[0]
+ elif point[0] > secondPoint[0]:
+ x = secondPoint[0]
+ else:
+ x = point[0]
+ else:
+ x = firstPoint[0] + (nth + 1) * (secondPoint[0] - firstPoint[0]) / (noArcs + 1.0)
+ else:
+ x = (secondPoint[0] - firstPoint[0]) / 2.0 # Midpoint
+ y = pt1[1]
+ else:
+ assert RoughlyEqual(pt1[0], pt2[0])
+
+ if pt1[1] > pt2[1]:
+ firstPoint = pt2
+ secondPoint = pt1
+ else:
+ firstPoint = pt1
+ secondPoint = pt2
+
+ if self._spaceAttachments:
+ if line and line.GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ # Align line according to the next handle along
+ point = line.GetNextControlPoint(self)
+ if point[1] < firstPoint[1]:
+ y = firstPoint[1]
+ elif point[1] > secondPoint[1]:
+ y = secondPoint[1]
+ else:
+ y = point[1]
+ else:
+ y = firstPoint[1] + (nth + 1) * (secondPoint[1] - firstPoint[1]) / (noArcs + 1.0)
+ else:
+ y = (secondPoint[1] - firstPoint[1]) / 2.0 # Midpoint
+ x = pt1[0]
+
+ return x, y
+
+ # Return the zero-based position in m_lines of line
+ def GetLinePosition(self, line):
+ """Get the zero-based position of line in the list of lines
+ for this shape.
+ """
+ try:
+ return self._lines.index(line)
+ except:
+ return 0
+
+
+ # |________|
+ # | <- root
+ # | <- neck
+ # shoulder1 ->---------<- shoulder2
+ # | | | | |
+ # <- branching attachment point N-1
+
+ def GetBranchingAttachmentInfo(self, attachment):
+ """Get information about where branching connections go.
+
+ Returns FALSE if there are no lines at this attachment.
+ """
+ physicalAttachment = self.LogicalToPhysicalAttachment(attachment)
+
+ # Number of lines at this attachment
+ lineCount = self.GetAttachmentLineCount(attachment)
+
+ if not lineCount:
+ return False
+
+ totalBranchLength = self._branchSpacing * (lineCount - 1)
+ root = self.GetBranchingAttachmentRoot(attachment)
+
+ neck = wx.RealPoint()
+ shoulder1 = wx.RealPoint()
+ shoulder2 = wx.RealPoint()
+
+ # Assume that we have attachment points 0 to 3: top, right, bottom, left
+ if physicalAttachment == 0:
+ neck[0] = self.GetX()
+ neck[1] = root[1] - self._branchNeckLength
+
+ shoulder1[0] = root[0] - totalBranchLength / 2.0
+ shoulder2[0] = root[0] + totalBranchLength / 2.0
+
+ shoulder1[1] = neck[1]
+ shoulder2[1] = neck[1]
+ elif physicalAttachment == 1:
+ neck[0] = root[0] + self._branchNeckLength
+ neck[1] = root[1]
+
+ shoulder1[0] = neck[0]
+ shoulder2[0] = neck[0]
+
+ shoulder1[1] = neck[1] - totalBranchLength / 2.0
+ shoulder1[1] = neck[1] + totalBranchLength / 2.0
+ elif physicalAttachment == 2:
+ neck[0] = self.GetX()
+ neck[1] = root[1] + self._branchNeckLength
+
+ shoulder1[0] = root[0] - totalBranchLength / 2.0
+ shoulder2[0] = root[0] + totalBranchLength / 2.0
+
+ shoulder1[1] = neck[1]
+ shoulder2[1] = neck[1]
+ elif physicalAttachment == 3:
+ neck[0] = root[0] - self._branchNeckLength
+ neck[1] = root[1]
+
+ shoulder1[0] = neck[0]
+ shoulder2[0] = neck[0]
+
+ shoulder1[1] = neck[1] - totalBranchLength / 2.0
+ shoulder2[1] = neck[1] + totalBranchLength / 2.0
+ else:
+ raise Exception, "Unrecognised attachment point in GetBranchingAttachmentInfo"
+ return root, neck, shoulder1, shoulder2
+
+ def GetBranchingAttachmentPoint(self, attachment, n):
+ physicalAttachment = self.LogicalToPhysicalAttachment(attachment)
+
+ root, neck, shoulder1, shoulder2 = self.GetBranchingAttachmentInfo(attachment)
+ pt = wx.RealPoint()
+ stemPt = wx.RealPoint()
+
+ if physicalAttachment == 0:
+ pt[1] = neck[1] - self._branchStemLength
+ pt[0] = shoulder1[0] + n * self._branchSpacing
+
+ stemPt[0] = pt[0]
+ stemPt[1] = neck[1]
+ elif physicalAttachment == 2:
+ pt[1] = neck[1] + self._branchStemLength
+ pt[0] = shoulder1[0] + n * self._branchStemLength
+
+ stemPt[0] = pt[0]
+ stemPt[1] = neck[1]
+ elif physicalAttachment == 1:
+ pt[0] = neck[0] + self._branchStemLength
+ pt[1] = shoulder1[1] + n * self._branchSpacing
+
+ stemPt[0] = neck[0]
+ stemPt[1] = pt[1]
+ elif physicalAttachment == 3:
+ pt[0] = neck[0] - self._branchStemLength
+ pt[1] = shoulder1[1] + n * self._branchSpacing
+
+ stemPt[0] = neck[0]
+ stemPt[1] = pt[1]
+ else:
+ raise Exception, "Unrecognised attachment point in GetBranchingAttachmentPoint"
+
+ return pt, stemPt
+
+ def GetAttachmentLineCount(self, attachment):
+ """Get the number of lines at this attachment position."""
+ count = 0
+ for lineShape in self._lines:
+ if lineShape.GetFrom() == self and lineShape.GetAttachmentFrom() == attachment:
+ count += 1
+ elif lineShape.GetTo() == self and lineShape.GetAttachmentTo() == attachment:
+ count += 1
+ return count
+
+ def GetBranchingAttachmentRoot(self, attachment):
+ """Get the root point at the given attachment."""
+ physicalAttachment = self.LogicalToPhysicalAttachment(attachment)
+
+ root = wx.RealPoint()
+
+ width, height = self.GetBoundingBoxMax()
+
+ # Assume that we have attachment points 0 to 3: top, right, bottom, left
+ if physicalAttachment == 0:
+ root[0] = self.GetX()
+ root[1] = self.GetY() - height / 2.0
+ elif physicalAttachment == 1:
+ root[0] = self.GetX() + width / 2.0
+ root[1] = self.GetY()
+ elif physicalAttachment == 2:
+ root[0] = self.GetX()
+ root[1] = self.GetY() + height / 2.0
+ elif physicalAttachment == 3:
+ root[0] = self.GetX() - width / 2.0
+ root[1] = self.GetY()
+ else:
+ raise Exception, "Unrecognised attachment point in GetBranchingAttachmentRoot"
+
+ return root
+
+ # Draw or erase the branches (not the actual arcs though)
+ def OnDrawBranchesAttachment(self, dc, attachment, erase = False):
+ count = self.GetAttachmentLineCount(attachment)
+ if count == 0:
+ return
+
+ root, neck, shoulder1, shoulder2 = self.GetBranchingAttachmentInfo(attachment)
+
+ if erase:
+ dc.SetPen(wx.WHITE_PEN)
+ dc.SetBrush(wx.WHITE_BRUSH)
+ else:
+ dc.SetPen(wx.BLACK_PEN)
+ dc.SetBrush(wx.BLACK_BRUSH)
+
+ # Draw neck
+ dc.DrawLine(root[0], root[1], neck[0], neck[1])
+
+ if count > 1:
+ # Draw shoulder-to-shoulder line
+ dc.DrawLine(shoulder1[0], shoulder1[1], shoulder2[0], shoulder2[1])
+ # Draw all the little branches
+ for i in range(count):
+ pt, stemPt = self.GetBranchingAttachmentPoint(attachment, i)
+ dc.DrawLine(stemPt[0], stemPt[1], pt[0], pt[1])
+
+ if self.GetBranchStyle() & BRANCHING_ATTACHMENT_BLOB and count > 1:
+ blobSize = 6.0
+ dc.DrawEllipse(stemPt[0] - blobSize / 2.0, stemPt[1] - blobSize / 2.0, blobSize, blobSize)
+
+ def OnDrawBranches(self, dc, erase = False):
+ if self._attachmentMode != ATTACHMENT_MODE_BRANCHING:
+ return
+ for i in range(self.GetNumberOfAttachments()):
+ self.OnDrawBranchesAttachment(dc, i, erase)
+
+ def GetAttachmentPositionEdge(self, attachment, nth = 0, no_arcs = 1, line = None):
+ """ Only get the attachment position at the _edge_ of the shape,
+ ignoring branching mode. This is used e.g. to indicate the edge of
+ interest, not the point on the attachment branch.
+ """
+ oldMode = self._attachmentMode
+
+ # Calculate as if to edge, not branch
+ if self._attachmentMode == ATTACHMENT_MODE_BRANCHING:
+ self._attachmentMode = ATTACHMENT_MODE_EDGE
+ res = self.GetAttachmentPosition(attachment, nth, no_arcs, line)
+ self._attachmentMode = oldMode
+
+ return res
+
+ def PhysicalToLogicalAttachment(self, physicalAttachment):
+ """ Rotate the standard attachment point from physical
+ (0 is always North) to logical (0 -> 1 if rotated by 90 degrees)
+ """
+ if RoughlyEqual(self.GetRotation(), 0):
+ i = physicalAttachment
+ elif RoughlyEqual(self.GetRotation(), math.pi / 2.0):
+ i = physicalAttachment - 1
+ elif RoughlyEqual(self.GetRotation(), math.pi):
+ i = physicalAttachment - 2
+ elif RoughlyEqual(self.GetRotation(), 3 * math.pi / 2.0):
+ i = physicalAttachment - 3
+ else:
+ # Can't handle -- assume the same
+ return physicalAttachment
+
+ if i < 0:
+ i += 4
+
+ return i
+
+ def LogicalToPhysicalAttachment(self, logicalAttachment):
+ """Rotate the standard attachment point from logical
+ to physical (0 is always North).
+ """
+ if RoughlyEqual(self.GetRotation(), 0):
+ i = logicalAttachment
+ elif RoughlyEqual(self.GetRotation(), math.pi / 2.0):
+ i = logicalAttachment + 1
+ elif RoughlyEqual(self.GetRotation(), math.pi):
+ i = logicalAttachment + 2
+ elif RoughlyEqual(self.GetRotation(), 3 * math.pi / 2.0):
+ i = logicalAttachment + 3
+ else:
+ return logicalAttachment
+
+ if i > 3:
+ i -= 4
+
+ return i
+
+ def Rotate(self, x, y, theta):
+ """Rotate about the given axis by the given amount in radians."""
+ self._rotation = theta
+ if self._rotation < 0:
+ self._rotation += 2 * math.pi
+ elif self._rotation > 2 * math.pi:
+ self._rotation -= 2 * math.pi
+
+ def GetBackgroundPen(self):
+ """Return pen of the right colour for the background."""
+ if self.GetCanvas():
+ return wx.Pen(self.GetCanvas().GetBackgroundColour(), 1, wx.SOLID)
+ return WhiteBackgroundPen
+
+ def GetBackgroundBrush(self):
+ """Return brush of the right colour for the background."""
+ if self.GetCanvas():
+ return wx.Brush(self.GetCanvas().GetBackgroundColour(), wx.SOLID)
+ return WhiteBackgroundBrush
+
+ def GetX(self):
+ """Get the x position of the centre of the shape."""
+ return self._xpos
+
+ def GetY(self):
+ """Get the y position of the centre of the shape."""
+ return self._ypos
+
+ def SetX(self, x):
+ """Set the x position of the shape."""
+ self._xpos = x
+
+ def SetY(self, y):
+ """Set the y position of the shape."""
+ self._ypos = y
+
+ def GetParent(self):
+ """Return the parent of this shape, if it is part of a composite."""
+ return self._parent
+
+ def SetParent(self, p):
+ self._parent = p
+
+ def GetChildren(self):
+ """Return the list of children for this shape."""
+ return self._children
+
+ def GetDrawHandles(self):
+ """Return the list of drawhandles."""
+ return self._drawHandles
+
+ def GetEventHandler(self):
+ """Return the event handler for this shape."""
+ return self._eventHandler
+
+ def SetEventHandler(self, handler):
+ """Set the event handler for this shape."""
+ self._eventHandler = handler
+
+ def Recompute(self):
+ """Recomputes any constraints associated with the shape.
+
+ Normally applicable to CompositeShapes only, but harmless for
+ other classes of Shape.
+ """
+ return True
+
+ def IsHighlighted(self):
+ """TRUE if the shape is highlighted. Shape highlighting is unimplemented."""
+ return self._highlighted
+
+ def GetSensitivityFilter(self):
+ """Return the sensitivity filter, a bitlist of values.
+
+ See Shape.SetSensitivityFilter.
+ """
+ return self._sensitivity
+
+ def SetFixedSize(self, x, y):
+ """Set the shape to be fixed size."""
+ self._fixedWidth = x
+ self._fixedHeight = y
+
+ def GetFixedSize(self):
+ """Return flags indicating whether the shape is of fixed size in
+ either direction.
+ """
+ return self._fixedWidth, self._fixedHeight
+
+ def GetFixedWidth(self):
+ """TRUE if the shape cannot be resized in the horizontal plane."""
+ return self._fixedWidth
+
+ def GetFixedHeight(self):
+ """TRUE if the shape cannot be resized in the vertical plane."""
+ return self._fixedHeight
+
+ def SetSpaceAttachments(self, sp):
+ """Indicate whether lines should be spaced out evenly at the point
+ they touch the node (sp = True), or whether they should join at a single
+ point (sp = False).
+ """
+ self._spaceAttachments = sp
+
+ def GetSpaceAttachments(self):
+ """Return whether lines should be spaced out evenly at the point they
+ touch the node (True), or whether they should join at a single point
+ (False).
+ """
+ return self._spaceAttachments
+
+ def SetCentreResize(self, cr):
+ """Specify whether the shape is to be resized from the centre (the
+ centre stands still) or from the corner or side being dragged (the
+ other corner or side stands still).
+ """
+ self._centreResize = cr
+
+ def GetCentreResize(self):
+ """TRUE if the shape is to be resized from the centre (the centre stands
+ still), or FALSE if from the corner or side being dragged (the other
+ corner or side stands still)
+ """
+ return self._centreResize
+
+ def SetMaintainAspectRatio(self, ar):
+ """Set whether a shape that resizes should not change the aspect ratio
+ (width and height should be in the original proportion).
+ """
+ self._maintainAspectRatio = ar
+
+ def GetMaintainAspectRatio(self):
+ """TRUE if shape keeps aspect ratio during resize."""
+ return self._maintainAspectRatio
+
+ def GetLines(self):
+ """Return the list of lines connected to this shape."""
+ return self._lines
+
+ def SetDisableLabel(self, flag):
+ """Set flag to TRUE to stop the default region being shown."""
+ self._disableLabel = flag
+
+ def GetDisableLabel(self):
+ """TRUE if the default region will not be shown, FALSE otherwise."""
+ return self._disableLabel
+
+ def SetAttachmentMode(self, mode):
+ """Set the attachment mode.
+
+ If TRUE, attachment points will be significant when drawing lines to
+ and from this shape.
+ If FALSE, lines will be drawn as if to the centre of the shape.
+ """
+ self._attachmentMode = mode
+
+ def GetAttachmentMode(self):
+ """Return the attachment mode.
+
+ See Shape.SetAttachmentMode.
+ """
+ return self._attachmentMode
+
+ def SetId(self, i):
+ """Set the integer identifier for this shape."""
+ self._id = i
+
+ def GetId(self):
+ """Return the integer identifier for this shape."""
+ return self._id
+
+ def IsShown(self):
+ """TRUE if the shape is in a visible state, FALSE otherwise.
+
+ Note that this has nothing to do with whether the window is hidden
+ or the shape has scrolled off the canvas; it refers to the internal
+ visibility flag.
+ """
+ return self._visible
+
+ def GetPen(self):
+ """Return the pen used for drawing the shape's outline."""
+ return self._pen
+
+ def GetBrush(self):
+ """Return the brush used for filling the shape."""
+ return self._brush
+
+ def GetNumberOfTextRegions(self):
+ """Return the number of text regions for this shape."""
+ return len(self._regions)
+
+ def GetRegions(self):
+ """Return the list of ShapeRegions."""
+ return self._regions
+
+ # Control points ('handles') redirect control to the actual shape, to
+ # make it easier to override sizing behaviour.
+ def OnSizingDragLeft(self, pt, draw, x, y, keys = 0, attachment = 0):
+ bound_x, bound_y = self.GetBoundingBoxMin()
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dc.SetLogicalFunction(OGLRBLF)
+
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ if self.GetCentreResize():
+ # Maintain the same centre point
+ new_width = 2.0 * abs(x - self.GetX())
+ new_height = 2.0 * abs(y - self.GetY())
+
+ # Constrain sizing according to what control point you're dragging
+ if pt._type == CONTROL_POINT_HORIZONTAL:
+ if self.GetMaintainAspectRatio():
+ new_height = bound_y * (new_width / bound_x)
+ else:
+ new_height = bound_y
+ elif pt._type == CONTROL_POINT_VERTICAL:
+ if self.GetMaintainAspectRatio():
+ new_width = bound_x * (new_height / bound_y)
+ else:
+ new_width = bound_x
+ elif pt._type == CONTROL_POINT_DIAGONAL and (keys & KEY_SHIFT):
+ new_height = bound_y * (new_width / bound_x)
+
+ if self.GetFixedWidth():
+ new_width = bound_x
+
+ if self.GetFixedHeight():
+ new_height = bound_y
+
+ pt._controlPointDragEndWidth = new_width
+ pt._controlPointDragEndHeight = new_height
+
+ self.GetEventHandler().OnDrawOutline(dc, self.GetX(), self.GetY(), new_width, new_height)
+ else:
+ # Don't maintain the same centre point
+ newX1 = min(pt._controlPointDragStartX, x)
+ newY1 = min(pt._controlPointDragStartY, y)
+ newX2 = max(pt._controlPointDragStartX, x)
+ newY2 = max(pt._controlPointDragStartY, y)
+ if pt._type == CONTROL_POINT_HORIZONTAL:
+ newY1 = pt._controlPointDragStartY
+ newY2 = newY1 + pt._controlPointDragStartHeight
+ elif pt._type == CONTROL_POINT_VERTICAL:
+ newX1 = pt._controlPointDragStartX
+ newX2 = newX1 + pt._controlPointDragStartWidth
+ elif pt._type == CONTROL_POINT_DIAGONAL and (keys & KEY_SHIFT or self.GetMaintainAspectRatio()):
+ newH = (newX2 - newX1) * (float(pt._controlPointDragStartHeight) / pt._controlPointDragStartWidth)
+ if self.GetY() > pt._controlPointDragStartY:
+ newY2 = newY1 + newH
+ else:
+ newY1 = newY2 - newH
+
+ newWidth = float(newX2 - newX1)
+ newHeight = float(newY2 - newY1)
+
+ if pt._type == CONTROL_POINT_VERTICAL and self.GetMaintainAspectRatio():
+ newWidth = bound_x * (newHeight / bound_y)
+
+ if pt._type == CONTROL_POINT_HORIZONTAL and self.GetMaintainAspectRatio():
+ newHeight = bound_y * (newWidth / bound_x)
+
+ pt._controlPointDragPosX = newX1 + newWidth / 2.0
+ pt._controlPointDragPosY = newY1 + newHeight / 2.0
+ if self.GetFixedWidth():
+ newWidth = bound_x
+
+ if self.GetFixedHeight():
+ newHeight = bound_y
+
+ pt._controlPointDragEndWidth = newWidth
+ pt._controlPointDragEndHeight = newHeight
+ self.GetEventHandler().OnDrawOutline(dc, pt._controlPointDragPosX, pt._controlPointDragPosY, newWidth, newHeight)
+
+ def OnSizingBeginDragLeft(self, pt, x, y, keys = 0, attachment = 0):
+ self._canvas.CaptureMouse()
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dc.SetLogicalFunction(OGLRBLF)
+
+ bound_x, bound_y = self.GetBoundingBoxMin()
+ self.GetEventHandler().OnBeginSize(bound_x, bound_y)
+
+ # Choose the 'opposite corner' of the object as the stationary
+ # point in case this is non-centring resizing.
+ if pt.GetX() < self.GetX():
+ pt._controlPointDragStartX = self.GetX() + bound_x / 2.0
+ else:
+ pt._controlPointDragStartX = self.GetX() - bound_x / 2.0
+
+ if pt.GetY() < self.GetY():
+ pt._controlPointDragStartY = self.GetY() + bound_y / 2.0
+ else:
+ pt._controlPointDragStartY = self.GetY() - bound_y / 2.0
+
+ if pt._type == CONTROL_POINT_HORIZONTAL:
+ pt._controlPointDragStartY = self.GetY() - bound_y / 2.0
+ elif pt._type == CONTROL_POINT_VERTICAL:
+ pt._controlPointDragStartX = self.GetX() - bound_x / 2.0
+
+ # We may require the old width and height
+ pt._controlPointDragStartWidth = bound_x
+ pt._controlPointDragStartHeight = bound_y
+
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ if self.GetCentreResize():
+ new_width = 2.0 * abs(x - self.GetX())
+ new_height = 2.0 * abs(y - self.GetY())
+
+ # Constrain sizing according to what control point you're dragging
+ if pt._type == CONTROL_POINT_HORIZONTAL:
+ if self.GetMaintainAspectRatio():
+ new_height = bound_y * (new_width / bound_x)
+ else:
+ new_height = bound_y
+ elif pt._type == CONTROL_POINT_VERTICAL:
+ if self.GetMaintainAspectRatio():
+ new_width = bound_x * (new_height / bound_y)
+ else:
+ new_width = bound_x
+ elif pt._type == CONTROL_POINT_DIAGONAL and (keys & KEY_SHIFT):
+ new_height = bound_y * (new_width / bound_x)
+
+ if self.GetFixedWidth():
+ new_width = bound_x
+
+ if self.GetFixedHeight():
+ new_height = bound_y
+
+ pt._controlPointDragEndWidth = new_width
+ pt._controlPointDragEndHeight = new_height
+ self.GetEventHandler().OnDrawOutline(dc, self.GetX(), self.GetY(), new_width, new_height)
+ else:
+ # Don't maintain the same centre point
+ newX1 = min(pt._controlPointDragStartX, x)
+ newY1 = min(pt._controlPointDragStartY, y)
+ newX2 = max(pt._controlPointDragStartX, x)
+ newY2 = max(pt._controlPointDragStartY, y)
+ if pt._type == CONTROL_POINT_HORIZONTAL:
+ newY1 = pt._controlPointDragStartY
+ newY2 = newY1 + pt._controlPointDragStartHeight
+ elif pt._type == CONTROL_POINT_VERTICAL:
+ newX1 = pt._controlPointDragStartX
+ newX2 = newX1 + pt._controlPointDragStartWidth
+ elif pt._type == CONTROL_POINT_DIAGONAL and (keys & KEY_SHIFT or self.GetMaintainAspectRatio()):
+ newH = (newX2 - newX1) * (float(pt._controlPointDragStartHeight) / pt._controlPointDragStartWidth)
+ if pt.GetY() > pt._controlPointDragStartY:
+ newY2 = newY1 + newH
+ else:
+ newY1 = newY2 - newH
+
+ newWidth = float(newX2 - newX1)
+ newHeight = float(newY2 - newY1)
+
+ if pt._type == CONTROL_POINT_VERTICAL and self.GetMaintainAspectRatio():
+ newWidth = bound_x * (newHeight / bound_y)
+
+ if pt._type == CONTROL_POINT_HORIZONTAL and self.GetMaintainAspectRatio():
+ newHeight = bound_y * (newWidth / bound_x)
+
+ pt._controlPointDragPosX = newX1 + newWidth / 2.0
+ pt._controlPointDragPosY = newY1 + newHeight / 2.0
+ if self.GetFixedWidth():
+ newWidth = bound_x
+
+ if self.GetFixedHeight():
+ newHeight = bound_y
+
+ pt._controlPointDragEndWidth = newWidth
+ pt._controlPointDragEndHeight = newHeight
+ self.GetEventHandler().OnDrawOutline(dc, pt._controlPointDragPosX, pt._controlPointDragPosY, newWidth, newHeight)
+
+ def OnSizingEndDragLeft(self, pt, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ if self._canvas.HasCapture():
+ self._canvas.ReleaseMouse()
+ dc.SetLogicalFunction(wx.COPY)
+ self.Recompute()
+ self.ResetControlPoints()
+
+ self.Erase(dc)
+
+ self.SetSize(pt._controlPointDragEndWidth, pt._controlPointDragEndHeight)
+
+ # The next operation could destroy this control point (it does for
+ # label objects, via formatting the text), so save all values we're
+ # going to use, or we'll be accessing garbage.
+
+ #return
+
+ if self.GetCentreResize():
+ self.Move(dc, self.GetX(), self.GetY())
+ else:
+ self.Move(dc, pt._controlPointDragPosX, pt._controlPointDragPosY)
+
+ # Recursively redraw links if we have a composite
+ if len(self.GetChildren()):
+ self.DrawLinks(dc, -1, True)
+
+ width, height = self.GetBoundingBoxMax()
+ self.GetEventHandler().OnEndSize(width, height)
+
+ if not self._canvas.GetQuickEditMode() and pt._eraseObject:
+ self._canvas.Redraw(dc)
+
+
+
+class RectangleShape(Shape):
+ """
+ The wxRectangleShape has rounded or square corners.
+
+ Derived from:
+ Shape
+ """
+ def __init__(self, w = 0.0, h = 0.0):
+ Shape.__init__(self)
+ self._width = w
+ self._height = h
+ self._cornerRadius = 0.0
+ self.SetDefaultRegionSize()
+
+ def OnDraw(self, dc):
+ x1 = self._xpos - self._width / 2.0
+ y1 = self._ypos - self._height / 2.0
+
+ if self._shadowMode != SHADOW_NONE:
+ if self._shadowBrush:
+ dc.SetBrush(self._shadowBrush)
+ dc.SetPen(TransparentPen)
+
+ if self._cornerRadius:
+ dc.DrawRoundedRectangle(x1 + self._shadowOffsetX, y1 + self._shadowOffsetY, self._width, self._height, self._cornerRadius)
+ else:
+ dc.DrawRectangle(x1 + self._shadowOffsetX, y1 + self._shadowOffsetY, self._width, self._height)
+
+ if self._pen:
+ if self._pen.GetWidth() == 0:
+ dc.SetPen(TransparentPen)
+ else:
+ dc.SetPen(self._pen)
+ if self._brush:
+ dc.SetBrush(self._brush)
+
+ if self._cornerRadius:
+ dc.DrawRoundedRectangle(x1, y1, self._width, self._height, self._cornerRadius)
+ else:
+ dc.DrawRectangle(x1, y1, self._width, self._height)
+
+ def GetBoundingBoxMin(self):
+ return self._width, self._height
+
+ def SetSize(self, x, y, recursive = False):
+ self.SetAttachmentSize(x, y)
+ self._width = max(x, 1)
+ self._height = max(y, 1)
+ self.SetDefaultRegionSize()
+
+ def GetCornerRadius(self):
+ """Get the radius of the rectangle's rounded corners."""
+ return self._cornerRadius
+
+ def SetCornerRadius(self, rad):
+ """Set the radius of the rectangle's rounded corners.
+
+ If the radius is zero, a non-rounded rectangle will be drawn.
+ If the radius is negative, the value is the proportion of the smaller
+ dimension of the rectangle.
+ """
+ self._cornerRadius = rad
+
+ # Assume (x1, y1) is centre of box (most generally, line end at box)
+ def GetPerimeterPoint(self, x1, y1, x2, y2):
+ bound_x, bound_y = self.GetBoundingBoxMax()
+ return FindEndForBox(bound_x, bound_y, self._xpos, self._ypos, x2, y2)
+
+ def GetWidth(self):
+ return self._width
+
+ def GetHeight(self):
+ return self._height
+
+ def SetWidth(self, w):
+ self._width = w
+
+ def SetHeight(self, h):
+ self._height = h
+
+
+
+class PolygonShape(Shape):
+ """A PolygonShape's shape is defined by a number of points passed to
+ the object's constructor. It can be used to create new shapes such as
+ diamonds and triangles.
+ """
+ def __init__(self):
+ Shape.__init__(self)
+
+ self._points = None
+ self._originalPoints = None
+
+ def Create(self, the_points = None):
+ """Takes a list of wx.RealPoints or tuples; each point is an offset
+ from the centre.
+ """
+ self.ClearPoints()
+
+ if not the_points:
+ self._originalPoints = []
+ self._points = []
+ else:
+ self._originalPoints = the_points
+
+ # Duplicate the list of points
+ self._points = []
+ for point in the_points:
+ new_point = wx.Point(point[0], point[1])
+ self._points.append(new_point)
+ self.CalculateBoundingBox()
+ self._originalWidth = self._boundWidth
+ self._originalHeight = self._boundHeight
+ self.SetDefaultRegionSize()
+
+ def ClearPoints(self):
+ self._points = []
+ self._originalPoints = []
+
+ # Width and height. Centre of object is centre of box
+ def GetBoundingBoxMin(self):
+ return self._boundWidth, self._boundHeight
+
+ def GetPoints(self):
+ """Return the internal list of polygon vertices."""
+ return self._points
+
+ def GetOriginalPoints(self):
+ return self._originalPoints
+
+ def GetOriginalWidth(self):
+ return self._originalWidth
+
+ def GetOriginalHeight(self):
+ return self._originalHeight
+
+ def SetOriginalWidth(self, w):
+ self._originalWidth = w
+
+ def SetOriginalHeight(self, h):
+ self._originalHeight = h
+
+ def CalculateBoundingBox(self):
+ # Calculate bounding box at construction (and presumably resize) time
+ left = 10000
+ right = -10000
+ top = 10000
+ bottom = -10000
+
+ for point in self._points:
+ if point[0] < left:
+ left = point[0]
+ if point[0] > right:
+ right = point[0]
+
+ if point[1] < top:
+ top = point[1]
+ if point[1] > bottom:
+ bottom = point[1]
+
+ self._boundWidth = right - left
+ self._boundHeight = bottom - top
+
+ def CalculatePolygonCentre(self):
+ """Recalculates the centre of the polygon, and
+ readjusts the point offsets accordingly.
+ Necessary since the centre of the polygon
+ is expected to be the real centre of the bounding
+ box.
+ """
+ left = 10000
+ right = -10000
+ top = 10000
+ bottom = -10000
+
+ for point in self._points:
+ if point[0] < left:
+ left = point[0]
+ if point[0] > right:
+ right = point[0]
+
+ if point[1] < top:
+ top = point[1]
+ if point[1] > bottom:
+ bottom = point[1]
+
+ bwidth = right - left
+ bheight = bottom - top
+
+ newCentreX = left + bwidth / 2.0
+ newCentreY = top + bheight / 2.0
+
+ for i in range(len(self._points)):
+ self._points[i] = self._points[i][0] - newCentreX, self._points[i][1] - newCentreY
+ self._xpos += newCentreX
+ self._ypos += newCentreY
+
+ def HitTest(self, x, y):
+ # Imagine four lines radiating from this point. If all of these lines
+ # hit the polygon, we're inside it, otherwise we're not. Obviously
+ # we'd need more radiating lines to be sure of correct results for
+ # very strange (concave) shapes.
+ endPointsX = [x, x + 1000, x, x - 1000]
+ endPointsY = [y - 1000, y, y + 1000, y]
+
+ xpoints = []
+ ypoints = []
+
+ for point in self._points:
+ xpoints.append(point[0] + self._xpos)
+ ypoints.append(point[1] + self._ypos)
+
+ # We assume it's inside the polygon UNLESS one or more
+ # lines don't hit the outline.
+ isContained = True
+
+ for i in range(4):
+ if not PolylineHitTest(xpoints, ypoints, x, y, endPointsX[i], endPointsY[i]):
+ isContained = False
+
+ if not isContained:
+ return False
+
+ nearest_attachment = 0
+
+ # If a hit, check the attachment points within the object
+ nearest = 999999
+
+ for i in range(self.GetNumberOfAttachments()):
+ e = self.GetAttachmentPositionEdge(i)
+ if e:
+ xp, yp = e
+ l = math.sqrt((xp - x) * (xp - x) + (yp - y) * (yp - y))
+ if l < nearest:
+ nearest = l
+ nearest_attachment = i
+
+ return nearest_attachment, nearest
+
+ # Really need to be able to reset the shape! Otherwise, if the
+ # points ever go to zero, we've lost it, and can't resize.
+ def SetSize(self, new_width, new_height, recursive = True):
+ self.SetAttachmentSize(new_width, new_height)
+
+ # Multiply all points by proportion of new size to old size
+ x_proportion = abs(float(new_width) / self._originalWidth)
+ y_proportion = abs(float(new_height) / self._originalHeight)
+
+ for i in range(max(len(self._points), len(self._originalPoints))):
+ self._points[i] = wx.Point(self._originalPoints[i][0] * x_proportion, self._originalPoints[i][1] * y_proportion)
+
+ self._boundWidth = abs(new_width)
+ self._boundHeight = abs(new_height)
+ self.SetDefaultRegionSize()
+
+ # Make the original points the same as the working points
+ def UpdateOriginalPoints(self):
+ """If we've changed the shape, must make the original points match the
+ working points with this function.
+ """
+ self._originalPoints = []
+
+ for point in self._points:
+ original_point = wx.RealPoint(point[0], point[1])
+ self._originalPoints.append(original_point)
+
+ self.CalculateBoundingBox()
+ self._originalWidth = self._boundWidth
+ self._originalHeight = self._boundHeight
+
+ def AddPolygonPoint(self, pos):
+ """Add a control point after the given point."""
+ try:
+ firstPoint = self._points[pos]
+ except ValueError:
+ firstPoint = self._points[0]
+
+ try:
+ secondPoint = self._points[pos + 1]
+ except ValueError:
+ secondPoint = self._points[0]
+
+ x = (secondPoint[0] - firstPoint[0]) / 2.0 + firstPoint[0]
+ y = (secondPoint[1] - firstPoint[1]) / 2.0 + firstPoint[1]
+ point = wx.RealPoint(x, y)
+
+ if pos >= len(self._points) - 1:
+ self._points.append(point)
+ else:
+ self._points.insert(pos + 1, point)
+
+ self.UpdateOriginalPoints()
+
+ if self._selected:
+ self.DeleteControlPoints()
+ self.MakeControlPoints()
+
+ def DeletePolygonPoint(self, pos):
+ """Delete the given control point."""
+ if pos < len(self._points):
+ del self._points[pos]
+ self.UpdateOriginalPoints()
+ if self._selected:
+ self.DeleteControlPoints()
+ self.MakeControlPoints()
+
+ # Assume (x1, y1) is centre of box (most generally, line end at box)
+ def GetPerimeterPoint(self, x1, y1, x2, y2):
+ # First check for situation where the line is vertical,
+ # and we would want to connect to a point on that vertical --
+ # oglFindEndForPolyline can't cope with this (the arrow
+ # gets drawn to the wrong place).
+ if self._attachmentMode == ATTACHMENT_MODE_NONE and x1 == x2:
+ # Look for the point we'd be connecting to. This is
+ # a heuristic...
+ for point in self._points:
+ if point[0] == 0:
+ if y2 > y1 and point[1] > 0:
+ return point[0] + self._xpos, point[1] + self._ypos
+ elif y2 < y1 and point[1] < 0:
+ return point[0] + self._xpos, point[1] + self._ypos
+
+ xpoints = []
+ ypoints = []
+ for point in self._points:
+ xpoints.append(point[0] + self._xpos)
+ ypoints.append(point[1] + self._ypos)
+
+ return FindEndForPolyline(xpoints, ypoints, x1, y1, x2, y2)
+
+ def OnDraw(self, dc):
+ if self._shadowMode != SHADOW_NONE:
+ if self._shadowBrush:
+ dc.SetBrush(self._shadowBrush)
+ dc.SetPen(TransparentPen)
+
+ dc.DrawPolygon(self._points, self._xpos + self._shadowOffsetX, self._ypos, self._shadowOffsetY)
+
+ if self._pen:
+ if self._pen.GetWidth() == 0:
+ dc.SetPen(TransparentPen)
+ else:
+ dc.SetPen(self._pen)
+ if self._brush:
+ dc.SetBrush(self._brush)
+ dc.DrawPolygon(self._points, self._xpos, self._ypos)
+
+ def OnDrawOutline(self, dc, x, y, w, h):
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ # Multiply all points by proportion of new size to old size
+ x_proportion = abs(float(w) / self._originalWidth)
+ y_proportion = abs(float(h) / self._originalHeight)
+
+ intPoints = []
+ for point in self._originalPoints:
+ intPoints.append(wx.Point(x_proportion * point[0], y_proportion * point[1]))
+ dc.DrawPolygon(intPoints, x, y)
+
+ # Make as many control points as there are vertices
+ def MakeControlPoints(self):
+ for point in self._points:
+ control = PolygonControlPoint(self._canvas, self, CONTROL_POINT_SIZE, point, point[0], point[1])
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ def ResetControlPoints(self):
+ for i in range(min(len(self._points), len(self._controlPoints))):
+ point = self._points[i]
+ self._controlPoints[i]._xoffset = point[0]
+ self._controlPoints[i]._yoffset = point[1]
+ self._controlPoints[i].polygonVertex = point
+
+ def GetNumberOfAttachments(self):
+ maxN = max(len(self._points) - 1, 0)
+ for point in self._attachmentPoints:
+ if point._id > maxN:
+ maxN = point._id
+ return maxN + 1
+
+ def GetAttachmentPosition(self, attachment, nth = 0, no_arcs = 1, line = None):
+ if self._attachmentMode == ATTACHMENT_MODE_EDGE and self._points and attachment < len(self._points):
+ point = self._points[0]
+ return point[0] + self._xpos, point[1] + self._ypos
+ return Shape.GetAttachmentPosition(self, attachment, nth, no_arcs, line)
+
+ def AttachmentIsValid(self, attachment):
+ if not self._points:
+ return False
+
+ if attachment >= 0 and attachment < len(self._points):
+ return True
+
+ for point in self._attachmentPoints:
+ if point._id == attachment:
+ return True
+
+ return False
+
+ # Rotate about the given axis by the given amount in radians
+ def Rotate(self, x, y, theta):
+ actualTheta = theta - self._rotation
+
+ # Rotate attachment points
+ sinTheta = math.sin(actualTheta)
+ cosTheta = math.cos(actualTheta)
+
+ for point in self._attachmentPoints:
+ x1 = point._x
+ y1 = point._y
+
+ point._x = x1 * cosTheta - y1 * sinTheta + x * (1 - cosTheta) + y * sinTheta
+ point._y = x1 * sinTheta + y1 * cosTheta + y * (1 - cosTheta) + x * sinTheta
+
+ for i in range(len(self._points)):
+ x1, y1 = self._points[i]
+
+ self._points[i] = x1 * cosTheta - y1 * sinTheta + x * (1 - cosTheta) + y * sinTheta, x1 * sinTheta + y1 * cosTheta + y * (1 - cosTheta) + x * sinTheta
+
+ for i in range(len(self._originalPoints)):
+ x1, y1 = self._originalPoints[i]
+
+ self._originalPoints[i] = x1 * cosTheta - y1 * sinTheta + x * (1 - cosTheta) + y * sinTheta, x1 * sinTheta + y1 * cosTheta + y * (1 - cosTheta) + x * sinTheta
+
+ # Added by Pierre Hjälm. If we don't do this the outline will be
+ # the wrong size. Hopefully it won't have any ill effects.
+ self.UpdateOriginalPoints()
+
+ self._rotation = theta
+
+ self.CalculatePolygonCentre()
+ self.CalculateBoundingBox()
+ self.ResetControlPoints()
+
+ # Control points ('handles') redirect control to the actual shape, to
+ # make it easier to override sizing behaviour.
+ def OnSizingDragLeft(self, pt, draw, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dc.SetLogicalFunction(OGLRBLF)
+
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ # Code for CTRL-drag in C++ version commented out
+
+ pt.CalculateNewSize(x, y)
+
+ self.GetEventHandler().OnDrawOutline(dc, self.GetX(), self.GetY(), pt.GetNewSize()[0], pt.GetNewSize()[1])
+
+ def OnSizingBeginDragLeft(self, pt, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ self.Erase(dc)
+
+ dc.SetLogicalFunction(OGLRBLF)
+
+ bound_x, bound_y = self.GetBoundingBoxMin()
+
+ dist = math.sqrt((x - self.GetX()) * (x - self.GetX()) + (y - self.GetY()) * (y - self.GetY()))
+
+ pt._originalDistance = dist
+ pt._originalSize[0] = bound_x
+ pt._originalSize[1] = bound_y
+
+ if pt._originalDistance == 0:
+ pt._originalDistance = 0.0001
+
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ # Code for CTRL-drag in C++ version commented out
+
+ pt.CalculateNewSize(x, y)
+
+ self.GetEventHandler().OnDrawOutline(dc, self.GetX(), self.GetY(), pt.GetNewSize()[0], pt.GetNewSize()[1])
+
+ self._canvas.CaptureMouse()
+
+ def OnSizingEndDragLeft(self, pt, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ if self._canvas.HasCapture():
+ self._canvas.ReleaseMouse()
+ dc.SetLogicalFunction(wx.COPY)
+
+ # If we're changing shape, must reset the original points
+ if keys & KEY_CTRL:
+ self.CalculateBoundingBox()
+ self.CalculatePolygonCentre()
+ else:
+ self.SetSize(pt.GetNewSize()[0], pt.GetNewSize()[1])
+
+ self.Recompute()
+ self.ResetControlPoints()
+ self.Move(dc, self.GetX(), self.GetY())
+ if not self._canvas.GetQuickEditMode():
+ self._canvas.Redraw(dc)
+
+
+
+class EllipseShape(Shape):
+ """The EllipseShape behaves similarly to the RectangleShape but is
+ elliptical.
+
+ Derived from:
+ wxShape
+ """
+ def __init__(self, w, h):
+ Shape.__init__(self)
+ self._width = w
+ self._height = h
+ self.SetDefaultRegionSize()
+
+ def GetBoundingBoxMin(self):
+ return self._width, self._height
+
+ def GetPerimeterPoint(self, x1, y1, x2, y2):
+ bound_x, bound_y = self.GetBoundingBoxMax()
+
+ return DrawArcToEllipse(self._xpos, self._ypos, bound_x, bound_y, x2, y2, x1, y1)
+
+ def GetWidth(self):
+ return self._width
+
+ def GetHeight(self):
+ return self._height
+
+ def SetWidth(self, w):
+ self._width = w
+
+ def SetHeight(self, h):
+ self._height = h
+
+ def OnDraw(self, dc):
+ if self._shadowMode != SHADOW_NONE:
+ if self._shadowBrush:
+ dc.SetBrush(self._shadowBrush)
+ dc.SetPen(TransparentPen)
+ dc.DrawEllipse(self._xpos - self.GetWidth() / 2.0 + self._shadowOffsetX,
+ self._ypos - self.GetHeight() / 2.0 + self._shadowOffsetY,
+ self.GetWidth(), self.GetHeight())
+
+ if self._pen:
+ if self._pen.GetWidth() == 0:
+ dc.SetPen(TransparentPen)
+ else:
+ dc.SetPen(self._pen)
+ if self._brush:
+ dc.SetBrush(self._brush)
+ dc.DrawEllipse(self._xpos - self.GetWidth() / 2.0, self._ypos - self.GetHeight() / 2.0, self.GetWidth(), self.GetHeight())
+
+ def SetSize(self, x, y, recursive = True):
+ self.SetAttachmentSize(x, y)
+ self._width = x
+ self._height = y
+ self.SetDefaultRegionSize()
+
+ def GetNumberOfAttachments(self):
+ return Shape.GetNumberOfAttachments(self)
+
+ # There are 4 attachment points on an ellipse - 0 = top, 1 = right,
+ # 2 = bottom, 3 = left.
+ def GetAttachmentPosition(self, attachment, nth = 0, no_arcs = 1, line = None):
+ if self._attachmentMode == ATTACHMENT_MODE_BRANCHING:
+ return Shape.GetAttachmentPosition(self, attachment, nth, no_arcs, line)
+
+ if self._attachmentMode != ATTACHMENT_MODE_NONE:
+ top = self._ypos + self._height / 2.0
+ bottom = self._ypos - self._height / 2.0
+ left = self._xpos - self._width / 2.0
+ right = self._xpos + self._width / 2.0
+
+ physicalAttachment = self.LogicalToPhysicalAttachment(attachment)
+
+ if physicalAttachment == 0:
+ if self._spaceAttachments:
+ x = left + (nth + 1) * self._width / (no_arcs + 1.0)
+ else:
+ x = self._xpos
+ y = top
+ # We now have the point on the bounding box: but get the point
+ # on the ellipse by imagining a vertical line from
+ # (x, self._ypos - self._height - 500) to (x, self._ypos) intersecting
+ # the ellipse.
+
+ return DrawArcToEllipse(self._xpos, self._ypos, self._width, self._height, x, self._ypos - self._height - 500, x, self._ypos)
+ elif physicalAttachment == 1:
+ x = right
+ if self._spaceAttachments:
+ y = bottom + (nth + 1) * self._height / (no_arcs + 1.0)
+ else:
+ y = self._ypos
+ return DrawArcToEllipse(self._xpos, self._ypos, self._width, self._height, self._xpos + self._width + 500, y, self._xpos, y)
+ elif physicalAttachment == 2:
+ if self._spaceAttachments:
+ x = left + (nth + 1) * self._width / (no_arcs + 1.0)
+ else:
+ x = self._xpos
+ y = bottom
+ return DrawArcToEllipse(self._xpos, self._ypos, self._width, self._height, x, self._ypos + self._height + 500, x, self._ypos)
+ elif physicalAttachment == 3:
+ x = left
+ if self._spaceAttachments:
+ y = bottom + (nth + 1) * self._height / (no_arcs + 1.0)
+ else:
+ y = self._ypos
+ return DrawArcToEllipse(self._xpos, self._ypos, self._width, self._height, self._xpos - self._width - 500, y, self._xpos, y)
+ else:
+ return Shape.GetAttachmentPosition(self, attachment, x, y, nth, no_arcs, line)
+ else:
+ return self._xpos, self._ypos
+
+
+
+class CircleShape(EllipseShape):
+ """An EllipseShape whose width and height are the same."""
+ def __init__(self, diameter):
+ EllipseShape.__init__(self, diameter, diameter)
+ self.SetMaintainAspectRatio(True)
+
+ def GetPerimeterPoint(self, x1, y1, x2, y2):
+ return FindEndForCircle(self._width / 2.0, self._xpos, self._ypos, x2, y2)
+
+
+
+class TextShape(RectangleShape):
+ """As wxRectangleShape, but only the text is displayed."""
+ def __init__(self, width, height):
+ RectangleShape.__init__(self, width, height)
+
+ def OnDraw(self, dc):
+ pass
+
+
+
+class ShapeRegion(object):
+ """Object region."""
+ def __init__(self, region = None):
+ if region:
+ self._regionText = region._regionText
+ self._regionName = region._regionName
+ self._textColour = region._textColour
+
+ self._font = region._font
+ self._minHeight = region._minHeight
+ self._minWidth = region._minWidth
+ self._width = region._width
+ self._height = region._height
+ self._x = region._x
+ self._y = region._y
+
+ self._regionProportionX = region._regionProportionX
+ self._regionProportionY = region._regionProportionY
+ self._formatMode = region._formatMode
+ self._actualColourObject = region._actualColourObject
+ self._actualPenObject = None
+ self._penStyle = region._penStyle
+ self._penColour = region._penColour
+
+ self.ClearText()
+ for line in region._formattedText:
+ new_line = ShapeTextLine(line.GetX(), line.GetY(), line.GetText())
+ self._formattedText.append(new_line)
+ else:
+ self._regionText = ""
+ self._font = NormalFont
+ self._minHeight = 5.0
+ self._minWidth = 5.0
+ self._width = 0.0
+ self._height = 0.0
+ self._x = 0.0
+ self._y = 0.0
+
+ self._regionProportionX = -1.0
+ self._regionProportionY = -1.0
+ self._formatMode = FORMAT_CENTRE_HORIZ | FORMAT_CENTRE_VERT
+ self._regionName = ""
+ self._textColour = "BLACK"
+ self._penColour = "BLACK"
+ self._penStyle = wx.SOLID
+ self._actualColourObject = wx.TheColourDatabase.Find("BLACK")
+ self._actualPenObject = None
+
+ self._formattedText = []
+
+ def ClearText(self):
+ self._formattedText = []
+
+ def SetFont(self, f):
+ self._font = f
+
+ def SetMinSize(self, w, h):
+ self._minWidth = w
+ self._minHeight = h
+
+ def SetSize(self, w, h):
+ self._width = w
+ self._height = h
+
+ def SetPosition(self, xp, yp):
+ self._x = xp
+ self._y = yp
+
+ def SetProportions(self, xp, yp):
+ self._regionProportionX = xp
+ self._regionProportionY = yp
+
+ def SetFormatMode(self, mode):
+ self._formatMode = mode
+
+ def SetColour(self, col):
+ self._textColour = col
+ self._actualColourObject = col
+
+ def GetActualColourObject(self):
+ self._actualColourObject = wx.TheColourDatabase.Find(self.GetColour())
+ return self._actualColourObject
+
+ def SetPenColour(self, col):
+ self._penColour = col
+ self._actualPenObject = None
+
+ # Returns NULL if the pen is invisible
+ # (different to pen being transparent; indicates that
+ # region boundary should not be drawn.)
+ def GetActualPen(self):
+ if self._actualPenObject:
+ return self._actualPenObject
+
+ if not self._penColour:
+ return None
+ if self._penColour=="Invisible":
+ return None
+ self._actualPenObject = wx.Pen(self._penColour, 1, self._penStyle)
+ return self._actualPenObject
+
+ def SetText(self, s):
+ self._regionText = s
+
+ def SetName(self, s):
+ self._regionName = s
+
+ def GetText(self):
+ return self._regionText
+
+ def GetFont(self):
+ return self._font
+
+ def GetMinSize(self):
+ return self._minWidth, self._minHeight
+
+ def GetProportion(self):
+ return self._regionProportionX, self._regionProportionY
+
+ def GetSize(self):
+ return self._width, self._height
+
+ def GetPosition(self):
+ return self._x, self._y
+
+ def GetFormatMode(self):
+ return self._formatMode
+
+ def GetName(self):
+ return self._regionName
+
+ def GetColour(self):
+ return self._textColour
+
+ def GetFormattedText(self):
+ return self._formattedText
+
+ def GetPenColour(self):
+ return self._penColour
+
+ def GetPenStyle(self):
+ return self._penStyle
+
+ def SetPenStyle(self, style):
+ self._penStyle = style
+ self._actualPenObject = None
+
+ def GetWidth(self):
+ return self._width
+
+ def GetHeight(self):
+ return self._height
+
+
+
+class ControlPoint(RectangleShape):
+ def __init__(self, theCanvas, object, size, the_xoffset, the_yoffset, the_type):
+ RectangleShape.__init__(self, size, size)
+
+ self._canvas = theCanvas
+ self._shape = object
+ self._xoffset = the_xoffset
+ self._yoffset = the_yoffset
+ self._type = the_type
+ self.SetPen(BlackForegroundPen)
+ self.SetBrush(wx.BLACK_BRUSH)
+ self._oldCursor = None
+ self._visible = True
+ self._eraseObject = True
+
+ # Don't even attempt to draw any text - waste of time
+ def OnDrawContents(self, dc):
+ pass
+
+ def OnDraw(self, dc):
+ self._xpos = self._shape.GetX() + self._xoffset
+ self._ypos = self._shape.GetY() + self._yoffset
+ RectangleShape.OnDraw(self, dc)
+
+ def OnErase(self, dc):
+ RectangleShape.OnErase(self, dc)
+
+ # Implement resizing of canvas object
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ self._shape.GetEventHandler().OnSizingDragLeft(self, draw, x, y, keys, attachment)
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ self._shape.GetEventHandler().OnSizingBeginDragLeft(self, x, y, keys, attachment)
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ self._shape.GetEventHandler().OnSizingEndDragLeft(self, x, y, keys, attachment)
+
+ def GetNumberOfAttachments(self):
+ return 1
+
+ def GetAttachmentPosition(self, attachment, nth = 0, no_arcs = 1, line = None):
+ return self._xpos, self._ypos
+
+ def SetEraseObject(self, er):
+ self._eraseObject = er
+
+
+class PolygonControlPoint(ControlPoint):
+ def __init__(self, theCanvas, object, size, vertex, the_xoffset, the_yoffset):
+ ControlPoint.__init__(self, theCanvas, object, size, the_xoffset, the_yoffset, 0)
+ self._polygonVertex = vertex
+ self._originalDistance = 0.0
+ self._newSize = wx.RealPoint()
+ self._originalSize = wx.RealPoint()
+
+ def GetNewSize(self):
+ return self._newSize
+
+ # Calculate what new size would be, at end of resize
+ def CalculateNewSize(self, x, y):
+ bound_x, bound_y = self.GetShape().GetBoundingBoxMax()
+ dist = math.sqrt((x - self._shape.GetX()) * (x - self._shape.GetX()) + (y - self._shape.GetY()) * (y - self._shape.GetY()))
+
+ self._newSize[0] = dist / self._originalDistance * self._originalSize[0]
+ self._newSize[1] = dist / self._originalDistance * self._originalSize[1]
+
+ # Implement resizing polygon or moving the vertex
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ self._shape.GetEventHandler().OnSizingDragLeft(self, draw, x, y, keys, attachment)
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ self._shape.GetEventHandler().OnSizingBeginDragLeft(self, x, y, keys, attachment)
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ self._shape.GetEventHandler().OnSizingEndDragLeft(self, x, y, keys, attachment)
+
+from _canvas import *
+from _lines import *
+from _composit import *
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_bmpshape.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_bmpshape.py
new file mode 100644
index 0000000..68e2e2e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_bmpshape.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+#----------------------------------------------------------------------------
+# Name: bmpshape.py
+# Purpose: Bitmap shape
+#
+# Author: Pierre Hjälm (from C++ original by Julian Smart)
+#
+# Created: 2004-05-08
+# RCS-ID: $Id$
+# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+from _basic import RectangleShape
+
+
+class BitmapShape(RectangleShape):
+ """Draws a bitmap (non-resizable)."""
+ def __init__(self):
+ RectangleShape.__init__(self, 100, 50)
+ self._filename = ""
+
+ def OnDraw(self, dc):
+ if not self._bitmap.Ok():
+ return
+
+ x = self._xpos - self._bitmap.GetWidth() / 2.0
+ y = self._ypos - self._bitmap.GetHeight() / 2.0
+ dc.DrawBitmap(self._bitmap, x, y, True)
+
+ def SetSize(self, w, h, recursive = True):
+ if self._bitmap.Ok():
+ w = self._bitmap.GetWidth()
+ h = self._bitmap.GetHeight()
+
+ self.SetAttachmentSize(w, h)
+
+ self._width = w
+ self._height = h
+
+ self.SetDefaultRegionSize()
+
+ def GetBitmap(self):
+ """Return a the bitmap associated with this shape."""
+ return self._bitmap
+
+ def SetBitmap(self, bitmap):
+ """Set the bitmap associated with this shape.
+
+ You can delete the bitmap from the calling application, since
+ reference counting will take care of holding on to the internal bitmap
+ data.
+ """
+ self._bitmap = bitmap
+ if self._bitmap.Ok():
+ self.SetSize(self._bitmap.GetWidth(), self._bitmap.GetHeight())
+
+ def SetFilename(self, f):
+ """Set the bitmap filename."""
+ self._filename = f
+
+ def GetFilename(self):
+ """Return the bitmap filename."""
+ return self._filename
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_canvas.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_canvas.py
new file mode 100644
index 0000000..b04b69f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_canvas.py
@@ -0,0 +1,363 @@
+# -*- coding: utf-8 -*-
+#----------------------------------------------------------------------------
+# Name: canvas.py
+# Purpose: The canvas class
+#
+# Author: Pierre Hjälm (from C++ original by Julian Smart)
+#
+# Created: 2004-05-08
+# RCS-ID: $Id$
+# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+import wx
+from _lines import LineShape
+from _composit import *
+
+NoDragging, StartDraggingLeft, ContinueDraggingLeft, StartDraggingRight, ContinueDraggingRight = 0, 1, 2, 3, 4
+
+KEY_SHIFT, KEY_CTRL = 1, 2
+
+
+
+# Helper function: True if 'contains' wholly contains 'contained'.
+def WhollyContains(contains, contained):
+ xp1, yp1 = contains.GetX(), contains.GetY()
+ xp2, yp2 = contained.GetX(), contained.GetY()
+
+ w1, h1 = contains.GetBoundingBoxMax()
+ w2, h2 = contained.GetBoundingBoxMax()
+
+ left1 = xp1 - w1 / 2.0
+ top1 = yp1 - h1 / 2.0
+ right1 = xp1 + w1 / 2.0
+ bottom1 = yp1 + h1 / 2.0
+
+ left2 = xp2 - w2 / 2.0
+ top2 = yp2 - h2 / 2.0
+ right2 = xp2 + w2 / 2.0
+ bottom2 = yp2 + h2 / 2.0
+
+ return ((left1 <= left2) and (top1 <= top2) and (right1 >= right2) and (bottom1 >= bottom2))
+
+
+
+class ShapeCanvas(wx.ScrolledWindow):
+ def __init__(self, parent = None, id = -1, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.BORDER, name = "ShapeCanvas"):
+ wx.ScrolledWindow.__init__(self, parent, id, pos, size, style, name)
+
+ self._shapeDiagram = None
+ self._dragState = NoDragging
+ self._draggedShape = None
+ self._oldDragX = 0
+ self._oldDragY = 0
+ self._firstDragX = 0
+ self._firstDragY = 0
+ self._checkTolerance = True
+
+ wx.EVT_PAINT(self, self.OnPaint)
+ wx.EVT_MOUSE_EVENTS(self, self.OnMouseEvent)
+
+ def SetDiagram(self, diag):
+ self._shapeDiagram = diag
+
+ def GetDiagram(self):
+ return self._shapeDiagram
+
+ def OnPaint(self, evt):
+ dc = wx.PaintDC(self)
+ self.PrepareDC(dc)
+
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour(), wx.SOLID))
+ dc.Clear()
+
+ if self.GetDiagram():
+ self.GetDiagram().Redraw(dc)
+
+ def OnMouseEvent(self, evt):
+ dc = wx.ClientDC(self)
+ self.PrepareDC(dc)
+
+ x, y = evt.GetLogicalPosition(dc)
+
+ keys = 0
+ if evt.ShiftDown():
+ keys |= KEY_SHIFT
+ if evt.ControlDown():
+ keys |= KEY_CTRL
+
+ dragging = evt.Dragging()
+
+ # Check if we're within the tolerance for mouse movements.
+ # If we're very close to the position we started dragging
+ # from, this may not be an intentional drag at all.
+ if dragging:
+ if self._checkTolerance:
+ # the difference between two logical coordinates is a logical coordinate
+ dx = abs(x - self._firstDragX)
+ dy = abs(y - self._firstDragY)
+ toler = self.GetDiagram().GetMouseTolerance()
+ if (dx <= toler) and (dy <= toler):
+ return
+ # If we've ignored the tolerance once, then ALWAYS ignore
+ # tolerance in this drag, even if we come back within
+ # the tolerance range.
+ self._checkTolerance = False
+
+ # Dragging - note that the effect of dragging is left entirely up
+ # to the object, so no movement is done unless explicitly done by
+ # object.
+ if dragging and self._draggedShape and self._dragState == StartDraggingLeft:
+ self._dragState = ContinueDraggingLeft
+
+ # If the object isn't m_draggable, transfer message to canvas
+ if self._draggedShape.Draggable():
+ self._draggedShape.GetEventHandler().OnBeginDragLeft(x, y, keys, self._draggedAttachment)
+ else:
+ self._draggedShape = None
+ self.OnBeginDragLeft(x, y, keys)
+
+ self._oldDragX, self._oldDragY = x, y
+
+ elif dragging and self._draggedShape and self._dragState == ContinueDraggingLeft:
+ # Continue dragging
+ self._draggedShape.GetEventHandler().OnDragLeft(False, self._oldDragX, self._oldDragY, keys, self._draggedAttachment)
+ self._draggedShape.GetEventHandler().OnDragLeft(True, x, y, keys, self._draggedAttachment)
+ self._oldDragX, self._oldDragY = x, y
+
+ elif evt.LeftUp() and self._draggedShape and self._dragState == ContinueDraggingLeft:
+ self._dragState = NoDragging
+ self._checkTolerance = True
+
+ self._draggedShape.GetEventHandler().OnDragLeft(False, self._oldDragX, self._oldDragY, keys, self._draggedAttachment)
+ self._draggedShape.GetEventHandler().OnEndDragLeft(x, y, keys, self._draggedAttachment)
+ self._draggedShape = None
+
+ elif dragging and self._draggedShape and self._dragState == StartDraggingRight:
+ self._dragState = ContinueDraggingRight
+ if self._draggedShape.Draggable:
+ self._draggedShape.GetEventHandler().OnBeginDragRight(x, y, keys, self._draggedAttachment)
+ else:
+ self._draggedShape = None
+ self.OnBeginDragRight(x, y, keys)
+ self._oldDragX, self._oldDragY = x, y
+
+ elif dragging and self._draggedShape and self._dragState == ContinueDraggingRight:
+ # Continue dragging
+ self._draggedShape.GetEventHandler().OnDragRight(False, self._oldDragX, self._oldDragY, keys, self._draggedAttachment)
+ self._draggedShape.GetEventHandler().OnDragRight(True, x, y, keys, self._draggedAttachment)
+ self._oldDragX, self._oldDragY = x, y
+
+ elif evt.RightUp() and self._draggedShape and self._dragState == ContinueDraggingRight:
+ self._dragState = NoDragging
+ self._checkTolerance = True
+
+ self._draggedShape.GetEventHandler().OnDragRight(False, self._oldDragX, self._oldDragY, keys, self._draggedAttachment)
+ self._draggedShape.GetEventHandler().OnEndDragRight(x, y, keys, self._draggedAttachment)
+ self._draggedShape = None
+
+ # All following events sent to canvas, not object
+ elif dragging and not self._draggedShape and self._dragState == StartDraggingLeft:
+ self._dragState = ContinueDraggingLeft
+ self.OnBeginDragLeft(x, y, keys)
+ self._oldDragX, self._oldDragY = x, y
+
+ elif dragging and not self._draggedShape and self._dragState == ContinueDraggingLeft:
+ # Continue dragging
+ self.OnDragLeft(False, self._oldDragX, self._oldDragY, keys)
+ self.OnDragLeft(True, x, y, keys)
+ self._oldDragX, self._oldDragY = x, y
+
+ elif evt.LeftUp() and not self._draggedShape and self._dragState == ContinueDraggingLeft:
+ self._dragState = NoDragging
+ self._checkTolerance = True
+
+ self.OnDragLeft(False, self._oldDragX, self._oldDragY, keys)
+ self.OnEndDragLeft(x, y, keys)
+ self._draggedShape = None
+
+ elif dragging and not self._draggedShape and self._dragState == StartDraggingRight:
+ self._dragState = ContinueDraggingRight
+ self.OnBeginDragRight(x, y, keys)
+ self._oldDragX, self._oldDragY = x, y
+
+ elif dragging and not self._draggedShape and self._dragState == ContinueDraggingRight:
+ # Continue dragging
+ self.OnDragRight(False, self._oldDragX, self._oldDragY, keys)
+ self.OnDragRight(True, x, y, keys)
+ self._oldDragX, self._oldDragY = x, y
+
+ elif evt.RightUp() and not self._draggedShape and self._dragState == ContinueDraggingRight:
+ self._dragState = NoDragging
+ self._checkTolerance = True
+
+ self.OnDragRight(False, self._oldDragX, self._oldDragY, keys)
+ self.OnEndDragRight(x, y, keys)
+ self._draggedShape = None
+
+ # Non-dragging events
+ elif evt.IsButton():
+ self._checkTolerance = True
+
+ # Find the nearest object
+ attachment = 0
+
+ nearest_object, attachment = self.FindShape(x, y)
+ if nearest_object: # Object event
+ if evt.LeftDown():
+ self._draggedShape = nearest_object
+ self._draggedAttachment = attachment
+ self._dragState = StartDraggingLeft
+ self._firstDragX = x
+ self._firstDragY = y
+
+ elif evt.LeftUp():
+ # N.B. Only register a click if the same object was
+ # identified for down *and* up.
+ if nearest_object == self._draggedShape:
+ nearest_object.GetEventHandler().OnLeftClick(x, y, keys, attachment)
+ self._draggedShape = None
+ self._dragState = NoDragging
+
+ elif evt.LeftDClick():
+ nearest_object.GetEventHandler().OnLeftDoubleClick(x, y, keys, attachment)
+ self._draggedShape = None
+ self._dragState = NoDragging
+
+ elif evt.RightDown():
+ self._draggedShape = nearest_object
+ self._draggedAttachment = attachment
+ self._dragState = StartDraggingRight
+ self._firstDragX = x
+ self._firstDragY = y
+
+ elif evt.RightUp():
+ if nearest_object == self._draggedShape:
+ nearest_object.GetEventHandler().OnRightClick(x, y, keys, attachment)
+ self._draggedShape = None
+ self._dragState = NoDragging
+
+ else: # Canvas event
+ if evt.LeftDown():
+ self._draggedShape = None
+ self._dragState = StartDraggingLeft
+ self._firstDragX = x
+ self._firstDragY = y
+
+ elif evt.LeftUp():
+ self.OnLeftClick(x, y, keys)
+ self._draggedShape = None
+ self._dragState = NoDragging
+
+ elif evt.RightDown():
+ self._draggedShape = None
+ self._dragState = StartDraggingRight
+ self._firstDragX = x
+ self._firstDragY = y
+
+ elif evt.RightUp():
+ self.OnRightClick(x, y, keys)
+ self._draggedShape = None
+ self._dragState = NoDragging
+
+ def FindShape(self, x, y, info = None, notObject = None):
+ nearest = 100000.0
+ nearest_attachment = 0
+ nearest_object = None
+
+ # Go backward through the object list, since we want:
+ # (a) to have the control points drawn LAST to overlay
+ # the other objects
+ # (b) to find the control points FIRST if they exist
+
+ rl = self.GetDiagram().GetShapeList()[:]
+ rl.reverse()
+ for object in rl:
+ # First pass for lines, which might be inside a container, so we
+ # want lines to take priority over containers. This first loop
+ # could fail if we clickout side a line, so then we'll
+ # try other shapes.
+ if object.IsShown() and \
+ isinstance(object, LineShape) and \
+ object.HitTest(x, y) and \
+ ((info == None) or isinstance(object, info)) and \
+ (not notObject or not notObject.HasDescendant(object)):
+ temp_attachment, dist = object.HitTest(x, y)
+ # A line is trickier to spot than a normal object.
+ # For a line, since it's the diagonal of the box
+ # we use for the hit test, we may have several
+ # lines in the box and therefore we need to be able
+ # to specify the nearest point to the centre of the line
+ # as our hit criterion, to give the user some room for
+ # manouevre.
+ if dist < nearest:
+ nearest = dist
+ nearest_object = object
+ nearest_attachment = temp_attachment
+
+ for object in rl:
+ # On second pass, only ever consider non-composites or
+ # divisions. If children want to pass up control to
+ # the composite, that's up to them.
+ if (object.IsShown() and
+ (isinstance(object, DivisionShape) or
+ not isinstance(object, CompositeShape)) and
+ object.HitTest(x, y) and
+ (info == None or isinstance(object, info)) and
+ (not notObject or not notObject.HasDescendant(object))):
+ temp_attachment, dist = object.HitTest(x, y)
+ if not isinstance(object, LineShape):
+ # If we've hit a container, and we have already
+ # found a line in the first pass, then ignore
+ # the container in case the line is in the container.
+ # Check for division in case line straddles divisions
+ # (i.e. is not wholly contained).
+ if not nearest_object or not (isinstance(object, DivisionShape) or WhollyContains(object, nearest_object)):
+ nearest_object = object
+ nearest_attachment = temp_attachment
+ break
+
+ return nearest_object, nearest_attachment
+
+ def AddShape(self, object, addAfter = None):
+ self.GetDiagram().AddShape(object, addAfter)
+
+ def InsertShape(self, object):
+ self.GetDiagram().InsertShape(object)
+
+ def RemoveShape(self, object):
+ self.GetDiagram().RemoveShape(object)
+
+ def GetQuickEditMode(self):
+ return self.GetDiagram().GetQuickEditMode()
+
+ def Redraw(self, dc):
+ self.GetDiagram().Redraw(dc)
+
+ def Snap(self, x, y):
+ return self.GetDiagram().Snap(x, y)
+
+ def OnLeftClick(self, x, y, keys = 0):
+ pass
+
+ def OnRightClick(self, x, y, keys = 0):
+ pass
+
+ def OnDragLeft(self, draw, x, y, keys = 0):
+ pass
+
+ def OnBeginDragLeft(self, x, y, keys = 0):
+ pass
+
+ def OnEndDragLeft(self, x, y, keys = 0):
+ pass
+
+ def OnDragRight(self, draw, x, y, keys = 0):
+ pass
+
+ def OnBeginDragRight(self, x, y, keys = 0):
+ pass
+
+ def OnEndDragRight(self, x, y, keys = 0):
+ pass
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_composit.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_composit.py
new file mode 100644
index 0000000..013e06c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_composit.py
@@ -0,0 +1,1442 @@
+# -*- coding: utf-8 -*-
+#----------------------------------------------------------------------------
+# Name: composit.py
+# Purpose: Composite class
+#
+# Author: Pierre Hjälm (from C++ original by Julian Smart)
+#
+# Created: 2004-05-08
+# RCS-ID: $Id$
+# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+import sys
+import wx
+
+from _basic import RectangleShape, Shape, ControlPoint
+from _oglmisc import *
+
+KEY_SHIFT, KEY_CTRL = 1, 2
+
+_objectStartX = 0.0
+_objectStartY = 0.0
+
+CONSTRAINT_CENTRED_VERTICALLY = 1
+CONSTRAINT_CENTRED_HORIZONTALLY = 2
+CONSTRAINT_CENTRED_BOTH = 3
+CONSTRAINT_LEFT_OF = 4
+CONSTRAINT_RIGHT_OF = 5
+CONSTRAINT_ABOVE = 6
+CONSTRAINT_BELOW = 7
+CONSTRAINT_ALIGNED_TOP = 8
+CONSTRAINT_ALIGNED_BOTTOM = 9
+CONSTRAINT_ALIGNED_LEFT = 10
+CONSTRAINT_ALIGNED_RIGHT = 11
+
+# Like aligned, but with the objects centred on the respective edge
+# of the reference object.
+CONSTRAINT_MIDALIGNED_TOP = 12
+CONSTRAINT_MIDALIGNED_BOTTOM = 13
+CONSTRAINT_MIDALIGNED_LEFT = 14
+CONSTRAINT_MIDALIGNED_RIGHT = 15
+
+
+# Backwards compatibility names. These should be removed eventually.
+gyCONSTRAINT_CENTRED_VERTICALLY = CONSTRAINT_CENTRED_VERTICALLY
+gyCONSTRAINT_CENTRED_HORIZONTALLY = CONSTRAINT_CENTRED_HORIZONTALLY
+gyCONSTRAINT_CENTRED_BOTH = CONSTRAINT_CENTRED_BOTH
+gyCONSTRAINT_LEFT_OF = CONSTRAINT_LEFT_OF
+gyCONSTRAINT_RIGHT_OF = CONSTRAINT_RIGHT_OF
+gyCONSTRAINT_ABOVE = CONSTRAINT_ABOVE
+gyCONSTRAINT_BELOW = CONSTRAINT_BELOW
+gyCONSTRAINT_ALIGNED_TOP = CONSTRAINT_ALIGNED_TOP
+gyCONSTRAINT_ALIGNED_BOTTOM = CONSTRAINT_ALIGNED_BOTTOM
+gyCONSTRAINT_ALIGNED_LEFT = CONSTRAINT_ALIGNED_LEFT
+gyCONSTRAINT_ALIGNED_RIGHT = CONSTRAINT_ALIGNED_RIGHT
+gyCONSTRAINT_MIDALIGNED_TOP = CONSTRAINT_MIDALIGNED_TOP
+gyCONSTRAINT_MIDALIGNED_BOTTOM = CONSTRAINT_MIDALIGNED_BOTTOM
+gyCONSTRAINT_MIDALIGNED_LEFT = CONSTRAINT_MIDALIGNED_LEFT
+gyCONSTRAINT_MIDALIGNED_RIGHT = CONSTRAINT_MIDALIGNED_RIGHT
+
+
+
+class ConstraintType(object):
+ def __init__(self, theType, theName, thePhrase):
+ self._type = theType
+ self._name = theName
+ self._phrase = thePhrase
+
+
+
+ConstraintTypes = [
+ [CONSTRAINT_CENTRED_VERTICALLY,
+ ConstraintType(CONSTRAINT_CENTRED_VERTICALLY, "Centre vertically", "centred vertically w.r.t.")],
+
+ [CONSTRAINT_CENTRED_HORIZONTALLY,
+ ConstraintType(CONSTRAINT_CENTRED_HORIZONTALLY, "Centre horizontally", "centred horizontally w.r.t.")],
+
+ [CONSTRAINT_CENTRED_BOTH,
+ ConstraintType(CONSTRAINT_CENTRED_BOTH, "Centre", "centred w.r.t.")],
+
+ [CONSTRAINT_LEFT_OF,
+ ConstraintType(CONSTRAINT_LEFT_OF, "Left of", "left of")],
+
+ [CONSTRAINT_RIGHT_OF,
+ ConstraintType(CONSTRAINT_RIGHT_OF, "Right of", "right of")],
+
+ [CONSTRAINT_ABOVE,
+ ConstraintType(CONSTRAINT_ABOVE, "Above", "above")],
+
+ [CONSTRAINT_BELOW,
+ ConstraintType(CONSTRAINT_BELOW, "Below", "below")],
+
+ # Alignment
+ [CONSTRAINT_ALIGNED_TOP,
+ ConstraintType(CONSTRAINT_ALIGNED_TOP, "Top-aligned", "aligned to the top of")],
+
+ [CONSTRAINT_ALIGNED_BOTTOM,
+ ConstraintType(CONSTRAINT_ALIGNED_BOTTOM, "Bottom-aligned", "aligned to the bottom of")],
+
+ [CONSTRAINT_ALIGNED_LEFT,
+ ConstraintType(CONSTRAINT_ALIGNED_LEFT, "Left-aligned", "aligned to the left of")],
+
+ [CONSTRAINT_ALIGNED_RIGHT,
+ ConstraintType(CONSTRAINT_ALIGNED_RIGHT, "Right-aligned", "aligned to the right of")],
+
+ # Mid-alignment
+ [CONSTRAINT_MIDALIGNED_TOP,
+ ConstraintType(CONSTRAINT_MIDALIGNED_TOP, "Top-midaligned", "centred on the top of")],
+
+ [CONSTRAINT_MIDALIGNED_BOTTOM,
+ ConstraintType(CONSTRAINT_MIDALIGNED_BOTTOM, "Bottom-midaligned", "centred on the bottom of")],
+
+ [CONSTRAINT_MIDALIGNED_LEFT,
+ ConstraintType(CONSTRAINT_MIDALIGNED_LEFT, "Left-midaligned", "centred on the left of")],
+
+ [CONSTRAINT_MIDALIGNED_RIGHT,
+ ConstraintType(CONSTRAINT_MIDALIGNED_RIGHT, "Right-midaligned", "centred on the right of")]
+ ]
+
+
+
+
+class Constraint(object):
+ """A Constraint object helps specify how child shapes are laid out with
+ respect to siblings and parents.
+
+ Derived from:
+ wxObject
+ """
+ def __init__(self, type, constraining, constrained):
+ self._xSpacing = 0.0
+ self._ySpacing = 0.0
+
+ self._constraintType = type
+ self._constrainingObject = constraining
+
+ self._constraintId = 0
+ self._constraintName = "noname"
+
+ self._constrainedObjects = constrained[:]
+
+ def __repr__(self):
+ return "<%s.%s>" % (self.__class__.__module__, self.__class__.__name__)
+
+ def SetSpacing(self, x, y):
+ """Sets the horizontal and vertical spacing for the constraint."""
+ self._xSpacing = x
+ self._ySpacing = y
+
+ def Equals(self, a, b):
+ """Return TRUE if x and y are approximately equal (for the purposes
+ of evaluating the constraint).
+ """
+ marg = 0.5
+
+ return b <= a + marg and b >= a - marg
+
+ def Evaluate(self):
+ """Evaluate this constraint and return TRUE if anything changed."""
+ maxWidth, maxHeight = self._constrainingObject.GetBoundingBoxMax()
+ minWidth, minHeight = self._constrainingObject.GetBoundingBoxMin()
+ x = self._constrainingObject.GetX()
+ y = self._constrainingObject.GetY()
+
+ dc = wx.ClientDC(self._constrainingObject.GetCanvas())
+ self._constrainingObject.GetCanvas().PrepareDC(dc)
+
+ if self._constraintType == CONSTRAINT_CENTRED_VERTICALLY:
+ n = len(self._constrainedObjects)
+ totalObjectHeight = 0.0
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ totalObjectHeight += height2
+
+ # Check if within the constraining object...
+ if totalObjectHeight + (n + 1) * self._ySpacing <= minHeight:
+ spacingY = (minHeight - totalObjectHeight) / (n + 1.0)
+ startY = y - minHeight / 2.0
+ else: # Otherwise, use default spacing
+ spacingY = self._ySpacing
+ startY = y - (totalObjectHeight + (n + 1) * spacingY) / 2.0
+
+ # Now position the objects
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ startY += spacingY + height2 / 2.0
+ if not self.Equals(startY, constrainedObject.GetY()):
+ constrainedObject.Move(dc, constrainedObject.GetX(), startY, False)
+ changed = True
+ startY += height2 / 2.0
+ return changed
+ elif self._constraintType == CONSTRAINT_CENTRED_HORIZONTALLY:
+ n = len(self._constrainedObjects)
+ totalObjectWidth = 0.0
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ totalObjectWidth += width2
+
+ # Check if within the constraining object...
+ if totalObjectWidth + (n + 1) * self._xSpacing <= minWidth:
+ spacingX = (minWidth - totalObjectWidth) / (n + 1.0)
+ startX = x - minWidth / 2.0
+ else: # Otherwise, use default spacing
+ spacingX = self._xSpacing
+ startX = x - (totalObjectWidth + (n + 1) * spacingX) / 2.0
+
+ # Now position the objects
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ startX += spacingX + width2 / 2.0
+ if not self.Equals(startX, constrainedObject.GetX()):
+ constrainedObject.Move(dc, startX, constrainedObject.GetY(), False)
+ changed = True
+ startX += width2 / 2.0
+ return changed
+ elif self._constraintType == CONSTRAINT_CENTRED_BOTH:
+ n = len(self._constrainedObjects)
+ totalObjectWidth = 0.0
+ totalObjectHeight = 0.0
+
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ totalObjectWidth += width2
+ totalObjectHeight += height2
+
+ # Check if within the constraining object...
+ if totalObjectHeight + (n + 1) * self._xSpacing <= minWidth:
+ spacingX = (minWidth - totalObjectWidth) / (n + 1.0)
+ startX = x - minWidth / 2.0
+ else: # Otherwise, use default spacing
+ spacingX = self._xSpacing
+ startX = x - (totalObjectWidth + (n + 1) * spacingX) / 2.0
+
+ # Check if within the constraining object...
+ if totalObjectHeight + (n + 1) * self._ySpacing <= minHeight:
+ spacingY = (minHeight - totalObjectHeight) / (n + 1.0)
+ startY = y - minHeight / 2.0
+ else: # Otherwise, use default spacing
+ spacingY = self._ySpacing
+ startY = y - (totalObjectHeight + (n + 1) * spacingY) / 2.0
+
+ # Now position the objects
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ startX += spacingX + width2 / 2.0
+ startY += spacingY + height2 / 2.0
+
+ if not self.Equals(startX, constrainedObject.GetX()) or not self.Equals(startY, constrainedObject.GetY()):
+ constrainedObject.Move(dc, startX, startY, False)
+ changed = True
+
+ startX += width2 / 2.0
+ startY += height2 / 2.0
+ return changed
+ elif self._constraintType == CONSTRAINT_LEFT_OF:
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+
+ x3 = x - minWidth / 2.0 - width2 / 2.0 - self._xSpacing
+ if not self.Equals(x3, constrainedObject.GetX()):
+ changed = True
+ constrainedObject.Move(dc, x3, constrainedObject.GetY(), False)
+ return changed
+ elif self._constraintType == CONSTRAINT_RIGHT_OF:
+ changed = False
+
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ x3 = x + minWidth / 2.0 + width2 / 2.0 + self._xSpacing
+ if not self.Equals(x3, constrainedObject.GetX()):
+ constrainedObject.Move(dc, x3, constrainedObject.GetY(), False)
+ changed = True
+ return changed
+ elif self._constraintType == CONSTRAINT_ABOVE:
+ changed = False
+
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+
+ y3 = y - minHeight / 2.0 - height2 / 2.0 - self._ySpacing
+ if not self.Equals(y3, constrainedObject.GetY()):
+ changed = True
+ constrainedObject.Move(dc, constrainedObject.GetX(), y3, False)
+ return changed
+ elif self._constraintType == CONSTRAINT_BELOW:
+ changed = False
+
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+
+ y3 = y + minHeight / 2.0 + height2 / 2.0 + self._ySpacing
+ if not self.Equals(y3, constrainedObject.GetY()):
+ changed = True
+ constrainedObject.Move(dc, constrainedObject.GetX(), y3, False)
+ return changed
+ elif self._constraintType == CONSTRAINT_ALIGNED_LEFT:
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ x3 = x - minWidth / 2.0 + width2 / 2.0 + self._xSpacing
+ if not self.Equals(x3, constrainedObject.GetX()):
+ changed = True
+ constrainedObject.Move(dc, x3, constrainedObject.GetY(), False)
+ return changed
+ elif self._constraintType == CONSTRAINT_ALIGNED_RIGHT:
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ x3 = x + minWidth / 2.0 - width2 / 2.0 - self._xSpacing
+ if not self.Equals(x3, constrainedObject.GetX()):
+ changed = True
+ constrainedObject.Move(dc, x3, constrainedObject.GetY(), False)
+ return changed
+ elif self._constraintType == CONSTRAINT_ALIGNED_TOP:
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ y3 = y - minHeight / 2.0 + height2 / 2.0 + self._ySpacing
+ if not self.Equals(y3, constrainedObject.GetY()):
+ changed = True
+ constrainedObject.Move(dc, constrainedObject.GetX(), y3, False)
+ return changed
+ elif self._constraintType == CONSTRAINT_ALIGNED_BOTTOM:
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ width2, height2 = constrainedObject.GetBoundingBoxMax()
+ y3 = y + minHeight / 2.0 - height2 / 2.0 - self._ySpacing
+ if not self.Equals(y3, constrainedObject.GetY()):
+ changed = True
+ constrainedObject.Move(dc, constrainedObject.GetX(), y3, False)
+ return changed
+ elif self._constraintType == CONSTRAINT_MIDALIGNED_LEFT:
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ x3 = x - minWidth / 2.0
+ if not self.Equals(x3, constrainedObject.GetX()):
+ changed = True
+ constrainedObject.Move(dc, x3, constrainedObject.GetY(), False)
+ return changed
+ elif self._constraintType == CONSTRAINT_MIDALIGNED_RIGHT:
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ x3 = x + minWidth / 2.0
+ if not self.Equals(x3, constrainedObject.GetX()):
+ changed = True
+ constrainedObject.Move(dc, x3, constrainedObject.GetY(), False)
+ return changed
+ elif self._constraintType == CONSTRAINT_MIDALIGNED_TOP:
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ y3 = y - minHeight / 2.0
+ if not self.Equals(y3, constrainedObject.GetY()):
+ changed = True
+ constrainedObject.Move(dc, constrainedObject.GetX(), y3, False)
+ return changed
+ elif self._constraintType == CONSTRAINT_MIDALIGNED_BOTTOM:
+ changed = False
+ for constrainedObject in self._constrainedObjects:
+ y3 = y + minHeight / 2.0
+ if not self.Equals(y3, constrainedObject.GetY()):
+ changed = True
+ constrainedObject.Move(dc, constrainedObject.GetX(), y3, False)
+ return changed
+
+ return False
+
+OGLConstraint = wx.deprecated(Constraint,
+ "The OGLConstraint name is deprecated, use `ogl.Constraint` instead.")
+
+
+class CompositeShape(RectangleShape):
+ """This is an object with a list of child objects, and a list of size
+ and positioning constraints between the children.
+
+ Derived from:
+ wxRectangleShape
+ """
+ def __init__(self):
+ RectangleShape.__init__(self, 100.0, 100.0)
+
+ self._oldX = self._xpos
+ self._oldY = self._ypos
+
+ self._constraints = []
+ self._divisions = [] # In case it's a container
+
+ def OnDraw(self, dc):
+ x1 = self._xpos - self._width / 2.0
+ y1 = self._ypos - self._height / 2.0
+
+ if self._shadowMode != SHADOW_NONE:
+ if self._shadowBrush:
+ dc.SetBrush(self._shadowBrush)
+ dc.SetPen(wx.Pen(wx.WHITE, 1, wx.TRANSPARENT))
+
+ if self._cornerRadius:
+ dc.DrawRoundedRectangle(x1 + self._shadowOffsetX, y1 + self._shadowOffsetY, self._width, self._height, self._cornerRadius)
+ else:
+ dc.DrawRectangle(x1 + self._shadowOffsetX, y1 + self._shadowOffsetY, self._width, self._height)
+
+ # For debug purposes /pi
+ #dc.DrawRectangle(x1, y1, self._width, self._height)
+
+ def OnDrawContents(self, dc):
+ for object in self._children:
+ object.Draw(dc)
+ object.DrawLinks(dc)
+
+ Shape.OnDrawContents(self, dc)
+
+ def OnMovePre(self, dc, x, y, old_x, old_y, display = True):
+ diffX = x - old_x
+ diffY = y - old_y
+
+ for object in self._children:
+ object.Erase(dc)
+ object.Move(dc, object.GetX() + diffX, object.GetY() + diffY, display)
+
+ return True
+
+ def OnErase(self, dc):
+ RectangleShape.OnErase(self, dc)
+ for object in self._children:
+ object.Erase(dc)
+
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ xx, yy = self._canvas.Snap(x, y)
+ offsetX = xx - _objectStartX
+ offsetY = yy - _objectStartY
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dc.SetLogicalFunction(OGLRBLF)
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ self.GetEventHandler().OnDrawOutline(dc, self.GetX() + offsetX, self.GetY() + offsetY, self.GetWidth(), self.GetHeight())
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ global _objectStartX, _objectStartY
+
+ _objectStartX = x
+ _objectStartY = y
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ #self.Erase(dc)
+
+ dc.SetLogicalFunction(OGLRBLF)
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ self._canvas.CaptureMouse()
+
+ xx, yy = self._canvas.Snap(x, y)
+ offsetX = xx - _objectStartX
+ offsetY = yy - _objectStartY
+
+ self.GetEventHandler().OnDrawOutline(dc, self.GetX() + offsetX, self.GetY() + offsetY, self.GetWidth(), self.GetHeight())
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ if self._canvas.HasCapture():
+ self._canvas.ReleaseMouse()
+
+ if not self._draggable:
+ if self._parent:
+ self._parent.GetEventHandler().OnEndDragLeft(x, y, keys, 0)
+ return
+
+ self.Erase(dc)
+
+ dc.SetLogicalFunction(wx.COPY)
+
+ xx, yy = self._canvas.Snap(x, y)
+ offsetX = xx - _objectStartX
+ offsetY = yy - _objectStartY
+
+ self.Move(dc, self.GetX() + offsetX, self.GetY() + offsetY)
+
+ if self._canvas and not self._canvas.GetQuickEditMode():
+ self._canvas.Redraw(dc)
+
+ def OnRightClick(self, x, y, keys = 0, attachment = 0):
+ # If we get a ctrl-right click, this means send the message to
+ # the division, so we can invoke a user interface for dealing
+ # with regions.
+ if keys & KEY_CTRL:
+ for division in self._divisions:
+ hit = division.HitTest(x, y)
+ if hit:
+ division.GetEventHandler().OnRightClick(x, y, keys, hit[0])
+ break
+
+ def SetSize(self, w, h, recursive = True):
+ self.SetAttachmentSize(w, h)
+
+ xScale = float(w) / max(1, self.GetWidth())
+ yScale = float(h) / max(1, self.GetHeight())
+
+ self._width = w
+ self._height = h
+
+ if not recursive:
+ return
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ for object in self._children:
+ # Scale the position first
+ newX = (object.GetX() - self.GetX()) * xScale + self.GetX()
+ newY = (object.GetY() - self.GetY()) * yScale + self.GetY()
+ object.Show(False)
+ object.Move(dc, newX, newY)
+ object.Show(True)
+
+ # Now set the scaled size
+ xbound, ybound = object.GetBoundingBoxMax()
+ if not object.GetFixedWidth():
+ xbound *= xScale
+ if not object.GetFixedHeight():
+ ybound *= yScale
+ object.SetSize(xbound, ybound)
+
+ self.SetDefaultRegionSize()
+
+ def AddChild(self, child, addAfter = None):
+ """Adds a child shape to the composite.
+
+ If addAfter is not None, the shape will be added after this shape.
+ """
+ self._children.append(child)
+ child.SetParent(self)
+ if self._canvas:
+ # Ensure we add at the right position
+ if addAfter:
+ child.RemoveFromCanvas(self._canvas)
+ child.AddToCanvas(self._canvas, addAfter)
+
+ def RemoveChild(self, child):
+ """Removes the child from the composite and any constraint
+ relationships, but does not delete the child.
+ """
+ if child in self._children:
+ self._children.remove(child)
+ if child in self._divisions:
+ self._divisions.remove(child)
+ self.RemoveChildFromConstraints(child)
+ child.SetParent(None)
+
+ def Delete(self):
+ """
+ Fully disconnect this shape from parents, children, the
+ canvas, etc.
+ """
+ for child in self.GetChildren():
+ self.RemoveChild(child)
+ child.Delete()
+ RectangleShape.Delete(self)
+ self._constraints = []
+ self._divisions = []
+
+ def DeleteConstraintsInvolvingChild(self, child):
+ """This function deletes constraints which mention the given child.
+
+ Used when deleting a child from the composite.
+ """
+ for constraint in self._constraints:
+ if constraint._constrainingObject == child or child in constraint._constrainedObjects:
+ self._constraints.remove(constraint)
+
+ def RemoveChildFromConstraints(self, child):
+ for constraint in self._constraints:
+ if child in constraint._constrainedObjects:
+ constraint._constrainedObjects.remove(child)
+ if constraint._constrainingObject == child:
+ constraint._constrainingObject = None
+
+ # Delete the constraint if no participants left
+ if not constraint._constrainingObject:
+ self._constraints.remove(constraint)
+
+ def AddConstraint(self, constraint):
+ """Adds a constraint to the composite."""
+ self._constraints.append(constraint)
+ if constraint._constraintId == 0:
+ constraint._constraintId = wx.NewId()
+ return constraint
+
+ def AddSimpleConstraint(self, type, constraining, constrained):
+ """Add a constraint of the given type to the composite.
+
+ constraining is the shape doing the constraining
+ constrained is a list of shapes being constrained
+ """
+ constraint = Constraint(type, constraining, constrained)
+ if constraint._constraintId == 0:
+ constraint._constraintId = wx.NewId()
+ self._constraints.append(constraint)
+ return constraint
+
+ def FindConstraint(self, cId):
+ """Finds the constraint with the given id.
+
+ Returns a tuple of the constraint and the actual composite the
+ constraint was in, in case that composite was a descendant of
+ this composit.
+
+ Returns None if not found.
+ """
+ for constraint in self._constraints:
+ if constraint._constraintId == cId:
+ return constraint, self
+
+ # If not found, try children
+ for child in self._children:
+ if isinstance(child, CompositeShape):
+ constraint = child.FindConstraint(cId)
+ if constraint:
+ return constraint[0], child
+
+ return None
+
+ def DeleteConstraint(self, constraint):
+ """Deletes constraint from composite."""
+ self._constraints.remove(constraint)
+
+ def CalculateSize(self):
+ """Calculates the size and position of the composite based on
+ child sizes and positions.
+ """
+ maxX = -999999.9
+ maxY = -999999.9
+ minX = 999999.9
+ minY = 999999.9
+
+ for child in self._children:
+ # Recalculate size of composite objects because may not conform
+ # to size it was set to - depends on the children.
+ if isinstance(child, CompositeShape):
+ child.CalculateSize()
+
+ w, h = child.GetBoundingBoxMax()
+ if child.GetX() + w / 2.0 > maxX:
+ maxX = child.GetX() + w / 2.0
+ if child.GetX() - w / 2.0 < minX:
+ minX = child.GetX() - w / 2.0
+ if child.GetY() + h / 2.0 > maxY:
+ maxY = child.GetY() + h / 2.0
+ if child.GetY() - h / 2.0 < minY:
+ minY = child.GetY() - h / 2.0
+
+ self._width = maxX - minX
+ self._height = maxY - minY
+ self._xpos = self._width / 2.0 + minX
+ self._ypos = self._height / 2.0 + minY
+
+ def Recompute(self):
+ """Recomputes any constraints associated with the object. If FALSE is
+ returned, the constraints could not be satisfied (there was an
+ inconsistency).
+ """
+ noIterations = 0
+ changed = True
+ while changed and noIterations < 500:
+ changed = self.Constrain()
+ noIterations += 1
+
+ return not changed
+
+ def Constrain(self):
+ self.CalculateSize()
+
+ changed = False
+ for child in self._children:
+ if isinstance(child, CompositeShape) and child.Constrain():
+ changed = True
+
+ for constraint in self._constraints:
+ if constraint.Evaluate():
+ changed = True
+
+ return changed
+
+ def MakeContainer(self):
+ """Makes this composite into a container by creating one child
+ DivisionShape.
+ """
+ division = self.OnCreateDivision()
+ self._divisions.append(division)
+ self.AddChild(division)
+
+ division.SetSize(self._width, self._height)
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ division.Move(dc, self.GetX(), self.GetY())
+ self.Recompute()
+ division.Show(True)
+
+ def OnCreateDivision(self):
+ return DivisionShape()
+
+ def FindContainerImage(self):
+ """Finds the image used to visualize a container. This is any child of
+ the composite that is not in the divisions list.
+ """
+ for child in self._children:
+ if child in self._divisions:
+ return child
+
+ return None
+
+ def ContainsDivision(self, division):
+ """Returns TRUE if division is a descendant of this container."""
+ if division in self._divisions:
+ return True
+
+ for child in self._children:
+ if isinstance(child, CompositeShape):
+ return child.ContainsDivision(division)
+
+ return False
+
+ def GetDivisions(self):
+ """Return the list of divisions."""
+ return self._divisions
+
+ def GetConstraints(self):
+ """Return the list of constraints."""
+ return self._constraints
+
+
+# A division object is a composite with special properties,
+# to be used for containment. It's a subdivision of a container.
+# A containing node image consists of a composite with a main child shape
+# such as rounded rectangle, plus a list of division objects.
+# It needs to be a composite because a division contains pieces
+# of diagram.
+# NOTE a container has at least one wxDivisionShape for consistency.
+# This can be subdivided, so it turns into two objects, then each of
+# these can be subdivided, etc.
+
+DIVISION_SIDE_NONE =0
+DIVISION_SIDE_LEFT =1
+DIVISION_SIDE_TOP =2
+DIVISION_SIDE_RIGHT =3
+DIVISION_SIDE_BOTTOM =4
+
+originalX = 0.0
+originalY = 0.0
+originalW = 0.0
+originalH = 0.0
+
+
+
+class DivisionControlPoint(ControlPoint):
+ def __init__(self, the_canvas, object, size, the_xoffset, the_yoffset, the_type):
+ ControlPoint.__init__(self, the_canvas, object, size, the_xoffset, the_yoffset, the_type)
+ self.SetEraseObject(False)
+
+ # Implement resizing of canvas object
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ ControlPoint.OnDragLeft(self, draw, x, y, keys, attachment)
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ global originalX, originalY, originalW, originalH
+
+ originalX = self._shape.GetX()
+ originalY = self._shape.GetY()
+ originalW = self._shape.GetWidth()
+ originalH = self._shape.GetHeight()
+
+ ControlPoint.OnBeginDragLeft(self, x, y, keys, attachment)
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ ControlPoint.OnEndDragLeft(self, x, y, keys, attachment)
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ division = self._shape
+ divisionParent = division.GetParent()
+
+ # Need to check it's within the bounds of the parent composite
+ x1 = divisionParent.GetX() - divisionParent.GetWidth() / 2.0
+ y1 = divisionParent.GetY() - divisionParent.GetHeight() / 2.0
+ x2 = divisionParent.GetX() + divisionParent.GetWidth() / 2.0
+ y2 = divisionParent.GetY() + divisionParent.GetHeight() / 2.0
+
+ # Need to check it has not made the division zero or negative
+ # width / height
+ dx1 = division.GetX() - division.GetWidth() / 2.0
+ dy1 = division.GetY() - division.GetHeight() / 2.0
+ dx2 = division.GetX() + division.GetWidth() / 2.0
+ dy2 = division.GetY() + division.GetHeight() / 2.0
+
+ success = True
+ if division.GetHandleSide() == DIVISION_SIDE_LEFT:
+ if x <= x1 or x >= x2 or x >= dx2:
+ success = False
+ # Try it out first...
+ elif not division.ResizeAdjoining(DIVISION_SIDE_LEFT, x, True):
+ success = False
+ else:
+ division.ResizeAdjoining(DIVISION_SIDE_LEFT, x, False)
+ elif division.GetHandleSide() == DIVISION_SIDE_TOP:
+ if y <= y1 or y >= y2 or y >= dy2:
+ success = False
+ elif not division.ResizeAdjoining(DIVISION_SIDE_TOP, y, True):
+ success = False
+ else:
+ division.ResizingAdjoining(DIVISION_SIDE_TOP, y, False)
+ elif division.GetHandleSide() == DIVISION_SIDE_RIGHT:
+ if x <= x1 or x >= x2 or x <= dx1:
+ success = False
+ elif not division.ResizeAdjoining(DIVISION_SIDE_RIGHT, x, True):
+ success = False
+ else:
+ division.ResizeAdjoining(DIVISION_SIDE_RIGHT, x, False)
+ elif division.GetHandleSide() == DIVISION_SIDE_BOTTOM:
+ if y <= y1 or y >= y2 or y <= dy1:
+ success = False
+ elif not division.ResizeAdjoining(DIVISION_SIDE_BOTTOM, y, True):
+ success = False
+ else:
+ division.ResizeAdjoining(DIVISION_SIDE_BOTTOM, y, False)
+
+ if not success:
+ division.SetSize(originalW, originalH)
+ division.Move(dc, originalX, originalY)
+
+ divisionParent.Draw(dc)
+ division.GetEventHandler().OnDrawControlPoints(dc)
+
+
+
+DIVISION_MENU_SPLIT_HORIZONTALLY =1
+DIVISION_MENU_SPLIT_VERTICALLY =2
+DIVISION_MENU_EDIT_LEFT_EDGE =3
+DIVISION_MENU_EDIT_TOP_EDGE =4
+DIVISION_MENU_EDIT_RIGHT_EDGE =5
+DIVISION_MENU_EDIT_BOTTOM_EDGE =6
+DIVISION_MENU_DELETE_ALL =7
+
+
+
+class PopupDivisionMenu(wx.Menu):
+ def __init__(self):
+ wx.Menu.__init__(self)
+ self.Append(DIVISION_MENU_SPLIT_HORIZONTALLY,"Split horizontally")
+ self.Append(DIVISION_MENU_SPLIT_VERTICALLY,"Split vertically")
+ self.AppendSeparator()
+ self.Append(DIVISION_MENU_EDIT_LEFT_EDGE,"Edit left edge")
+ self.Append(DIVISION_MENU_EDIT_TOP_EDGE,"Edit top edge")
+
+ wx.EVT_MENU_RANGE(self, DIVISION_MENU_SPLIT_HORIZONTALLY, DIVISION_MENU_EDIT_BOTTOM_EDGE, self.OnMenu)
+
+ def SetClientData(self, data):
+ self._clientData = data
+
+ def GetClientData(self):
+ return self._clientData
+
+ def OnMenu(self, event):
+ division = self.GetClientData()
+ if event.GetId() == DIVISION_MENU_SPLIT_HORIZONTALLY:
+ division.Divide(wx.HORIZONTAL)
+ elif event.GetId() == DIVISION_MENU_SPLIT_VERTICALLY:
+ division.Divide(wx.VERTICAL)
+ elif event.GetId() == DIVISION_MENU_EDIT_LEFT_EDGE:
+ division.EditEdge(DIVISION_SIDE_LEFT)
+ elif event.GetId() == DIVISION_MENU_EDIT_TOP_EDGE:
+ division.EditEdge(DIVISION_SIDE_TOP)
+
+
+
+class DivisionShape(CompositeShape):
+ """A division shape is like a composite in that it can contain further
+ objects, but is used exclusively to divide another shape into regions,
+ or divisions. A wxDivisionShape is never free-standing.
+
+ Derived from:
+ wxCompositeShape
+ """
+ def __init__(self):
+ CompositeShape.__init__(self)
+ self.SetSensitivityFilter(OP_CLICK_LEFT | OP_CLICK_RIGHT | OP_DRAG_RIGHT)
+ self.SetCentreResize(False)
+ self.SetAttachmentMode(True)
+ self._leftSide = None
+ self._rightSide = None
+ self._topSide = None
+ self._bottomSide = None
+ self._handleSide = DIVISION_SIDE_NONE
+ self._leftSidePen = wx.BLACK_PEN
+ self._topSidePen = wx.BLACK_PEN
+ self._leftSideColour = "BLACK"
+ self._topSideColour = "BLACK"
+ self._leftSideStyle = "Solid"
+ self._topSideStyle = "Solid"
+ self.ClearRegions()
+
+ def SetLeftSide(self, shape):
+ """Set the the division on the left side of this division."""
+ self._leftSide = shape
+
+ def SetTopSide(self, shape):
+ """Set the the division on the top side of this division."""
+ self._topSide = shape
+
+ def SetRightSide(self, shape):
+ """Set the the division on the right side of this division."""
+ self._rightSide = shape
+
+ def SetBottomSide(self, shape):
+ """Set the the division on the bottom side of this division."""
+ self._bottomSide = shape
+
+ def GetLeftSide(self):
+ """Return the division on the left side of this division."""
+ return self._leftSide
+
+ def GetTopSide(self):
+ """Return the division on the top side of this division."""
+ return self._topSide
+
+ def GetRightSide(self):
+ """Return the division on the right side of this division."""
+ return self._rightSide
+
+ def GetBottomSide(self):
+ """Return the division on the bottom side of this division."""
+ return self._bottomSide
+
+ def SetHandleSide(self, side):
+ """Sets the side which the handle appears on.
+
+ Either DIVISION_SIDE_LEFT or DIVISION_SIDE_TOP.
+ """
+ self._handleSide = side
+
+ def GetHandleSide(self):
+ """Return the side which the handle appears on."""
+ return self._handleSide
+
+ def SetLeftSidePen(self, pen):
+ """Set the colour for drawing the left side of the division."""
+ self._leftSidePen = pen
+
+ def SetTopSidePen(self, pen):
+ """Set the colour for drawing the top side of the division."""
+ self._topSidePen = pen
+
+ def GetLeftSidePen(self):
+ """Return the pen used for drawing the left side of the division."""
+ return self._leftSidePen
+
+ def GetTopSidePen(self):
+ """Return the pen used for drawing the top side of the division."""
+ return self._topSidePen
+
+ def GetLeftSideColour(self):
+ """Return the colour used for drawing the left side of the division."""
+ return self._leftSideColour
+
+ def GetTopSideColour(self):
+ """Return the colour used for drawing the top side of the division."""
+ return self._topSideColour
+
+ def SetLeftSideColour(self, colour):
+ """Set the colour for drawing the left side of the division."""
+ self._leftSideColour = colour
+
+ def SetTopSideColour(self, colour):
+ """Set the colour for drawing the top side of the division."""
+ self._topSideColour = colour
+
+ def GetLeftSideStyle(self):
+ """Return the style used for the left side of the division."""
+ return self._leftSideStyle
+
+ def GetTopSideStyle(self):
+ """Return the style used for the top side of the division."""
+ return self._topSideStyle
+
+ def SetLeftSideStyle(self, style):
+ self._leftSideStyle = style
+
+ def SetTopSideStyle(self, style):
+ self._lefttopStyle = style
+
+ def OnDraw(self, dc):
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+
+ x1 = self.GetX() - self.GetWidth() / 2.0
+ y1 = self.GetY() - self.GetHeight() / 2.0
+ x2 = self.GetX() + self.GetWidth() / 2.0
+ y2 = self.GetY() + self.GetHeight() / 2.0
+
+ # Should subtract 1 pixel if drawing under Windows
+ if sys.platform[:3] == "win":
+ y2 -= 1
+
+ if self._leftSide:
+ dc.SetPen(self._leftSidePen)
+ dc.DrawLine(x1, y2, x1, y1)
+
+ if self._topSide:
+ dc.SetPen(self._topSidePen)
+ dc.DrawLine(x1, y1, x2, y1)
+
+ # For testing purposes, draw a rectangle so we know
+ # how big the division is.
+ #dc.SetBrush(wx.RED_BRUSH)
+ #dc.DrawRectangle(x1, y1, self.GetWidth(), self.GetHeight())
+
+ def OnDrawContents(self, dc):
+ CompositeShape.OnDrawContents(self, dc)
+
+ def OnMovePre(self, dc, x, y, oldx, oldy, display = True):
+ diffX = x - oldx
+ diffY = y - oldy
+ for object in self._children:
+ object.Erase(dc)
+ object.Move(dc, object.GetX() + diffX, object.GetY() + diffY, display)
+ return True
+
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ if self._sensitivity & OP_DRAG_LEFT != OP_DRAG_LEFT:
+ if self._parent:
+ hit = self._parent.HitTest(x, y)
+ if hit:
+ attachment, dist = hit
+ self._parent.GetEventHandler().OnDragLeft(draw, x, y, keys, attachment)
+ return
+ Shape.OnDragLeft(self, draw, x, y, keys, attachment)
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ if self._sensitivity & OP_DRAG_LEFT != OP_DRAG_LEFT:
+ if self._parent:
+ hit = self._parent.HitTest(x, y)
+ if hit:
+ attachment, dist = hit
+ self._parent.GetEventHandler().OnBeginDragLeft(x, y, keys, attachment)
+ return
+ Shape.OnBeginDragLeft(x, y, keys, attachment)
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ if self._canvas.HasCapture():
+ self._canvas.ReleaseMouse()
+ if self._sensitivity & OP_DRAG_LEFT != OP_DRAG_LEFT:
+ if self._parent:
+ hit = self._parent.HitTest(x, y)
+ if hit:
+ attachment, dist = hit
+ self._parent.GetEventHandler().OnEndDragLeft(x, y, keys, attachment)
+ return
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dc.SetLogicalFunction(wx.COPY)
+
+ self._xpos, self._ypos = self._canvas.Snap(self._xpos, self._ypos)
+ self.GetEventHandler().OnMovePre(dc, x, y, self._oldX, self._oldY)
+
+ self.ResetControlPoints()
+ self.Draw(dc)
+ self.MoveLinks(dc)
+ self.GetEventHandler().OnDrawControlPoints(dc)
+
+ if self._canvas and not self._canvas.GetQuickEditMode():
+ self._canvas.Redraw(dc)
+
+ def SetSize(self, w, h, recursive = True):
+ self._width = w
+ self._height = h
+ RectangleShape.SetSize(self, w, h, recursive)
+
+ def CalculateSize(self):
+ pass
+
+ # Experimental
+ def OnRightClick(self, x, y, keys = 0, attachment = 0):
+ if keys & KEY_CTRL:
+ self.PopupMenu(x, y)
+ else:
+ if self._parent:
+ hit = self._parent.HitTest(x, y)
+ if hit:
+ attachment, dist = hit
+ self._parent.GetEventHandler().OnRightClick(x, y, keys, attachment)
+
+ # Divide wx.HORIZONTALly or wx.VERTICALly
+ def Divide(self, direction):
+ """Divide this division into two further divisions,
+ horizontally (direction is wxHORIZONTAL) or
+ vertically (direction is wxVERTICAL).
+ """
+ # Calculate existing top-left, bottom-right
+ x1 = self.GetX() - self.GetWidth() / 2.0
+ y1 = self.GetY() - self.GetHeight() / 2.0
+
+ compositeParent = self.GetParent()
+ oldWidth = self.GetWidth()
+ oldHeight = self.GetHeight()
+ if self.Selected():
+ self.Select(False)
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ if direction == wx.VERTICAL:
+ # Dividing vertically means notionally putting a horizontal
+ # line through it.
+ # Break existing piece into two.
+ newXPos1 = self.GetX()
+ newYPos1 = y1 + self.GetHeight() / 4.0
+ newXPos2 = self.GetX()
+ newYPos2 = y1 + 3 * self.GetHeight() / 4.0
+ newDivision = compositeParent.OnCreateDivision()
+ newDivision.Show(True)
+
+ self.Erase(dc)
+
+ # Anything adjoining the bottom of this division now adjoins the
+ # bottom of the new division.
+ for obj in compositeParent.GetDivisions():
+ if obj.GetTopSide() == self:
+ obj.SetTopSide(newDivision)
+
+ newDivision.SetTopSide(self)
+ newDivision.SetBottomSide(self._bottomSide)
+ newDivision.SetLeftSide(self._leftSide)
+ newDivision.SetRightSide(self._rightSide)
+ self._bottomSide = newDivision
+
+ compositeParent.GetDivisions().append(newDivision)
+
+ # CHANGE: Need to insert this division at start of divisions in the
+ # object list, because e.g.:
+ # 1) Add division
+ # 2) Add contained object
+ # 3) Add division
+ # Division is now receiving mouse events _before_ the contained
+ # object, because it was added last (on top of all others)
+
+ # Add after the image that visualizes the container
+ compositeParent.AddChild(newDivision, compositeParent.FindContainerImage())
+
+ self._handleSide = DIVISION_SIDE_BOTTOM
+ newDivision.SetHandleSide(DIVISION_SIDE_TOP)
+
+ self.SetSize(oldWidth, oldHeight / 2.0)
+ self.Move(dc, newXPos1, newYPos1)
+
+ newDivision.SetSize(oldWidth, oldHeight / 2.0)
+ newDivision.Move(dc, newXPos2, newYPos2)
+ else:
+ # Dividing horizontally means notionally putting a vertical line
+ # through it.
+ # Break existing piece into two.
+ newXPos1 = x1 + self.GetWidth() / 4.0
+ newYPos1 = self.GetY()
+ newXPos2 = x1 + 3 * self.GetWidth() / 4.0
+ newYPos2 = self.GetY()
+ newDivision = compositeParent.OnCreateDivision()
+ newDivision.Show(True)
+
+ self.Erase(dc)
+
+ # Anything adjoining the left of this division now adjoins the
+ # left of the new division.
+ for obj in compositeParent.GetDivisions():
+ if obj.GetLeftSide() == self:
+ obj.SetLeftSide(newDivision)
+
+ newDivision.SetTopSide(self._topSide)
+ newDivision.SetBottomSide(self._bottomSide)
+ newDivision.SetLeftSide(self)
+ newDivision.SetRightSide(self._rightSide)
+ self._rightSide = newDivision
+
+ compositeParent.GetDivisions().append(newDivision)
+ compositeParent.AddChild(newDivision, compositeParent.FindContainerImage())
+
+ self._handleSide = DIVISION_SIDE_RIGHT
+ newDivision.SetHandleSide(DIVISION_SIDE_LEFT)
+
+ self.SetSize(oldWidth / 2.0, oldHeight)
+ self.Move(dc, newXPos1, newYPos1)
+
+ newDivision.SetSize(oldWidth / 2.0, oldHeight)
+ newDivision.Move(dc, newXPos2, newYPos2)
+
+ if compositeParent.Selected():
+ compositeParent.DeleteControlPoints(dc)
+ compositeParent.MakeControlPoints()
+ compositeParent.MakeMandatoryControlPoints()
+
+ compositeParent.Draw(dc)
+ return True
+
+ def MakeControlPoints(self):
+ self.MakeMandatoryControlPoints()
+
+ def MakeMandatoryControlPoints(self):
+ maxX, maxY = self.GetBoundingBoxMax()
+ x = y = 0.0
+ direction = 0
+
+ if self._handleSide == DIVISION_SIDE_LEFT:
+ x = -maxX / 2.0
+ direction = CONTROL_POINT_HORIZONTAL
+ elif self._handleSide == DIVISION_SIDE_TOP:
+ y = -maxY / 2.0
+ direction = CONTROL_POINT_VERTICAL
+ elif self._handleSide == DIVISION_SIDE_RIGHT:
+ x = maxX / 2.0
+ direction = CONTROL_POINT_HORIZONTAL
+ elif self._handleSide == DIVISION_SIDE_BOTTOM:
+ y = maxY / 2.0
+ direction = CONTROL_POINT_VERTICAL
+
+ if self._handleSide != DIVISION_SIDE_NONE:
+ control = DivisionControlPoint(self._canvas, self, CONTROL_POINT_SIZE, x, y, direction)
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ def ResetControlPoints(self):
+ self.ResetMandatoryControlPoints()
+
+ def ResetMandatoryControlPoints(self):
+ if not self._controlPoints:
+ return
+
+ maxX, maxY = self.GetBoundingBoxMax()
+
+ node = self._controlPoints[0]
+
+ if self._handleSide == DIVISION_SIDE_LEFT and node:
+ node._xoffset = -maxX / 2.0
+ node._yoffset = 0.0
+
+ if self._handleSide == DIVISION_SIDE_TOP and node:
+ node._xoffset = 0.0
+ node._yoffset = -maxY / 2.0
+
+ if self._handleSide == DIVISION_SIDE_RIGHT and node:
+ node._xoffset = maxX / 2.0
+ node._yoffset = 0.0
+
+ if self._handleSide == DIVISION_SIDE_BOTTOM and node:
+ node._xoffset = 0.0
+ node._yoffset = maxY / 2.0
+
+ def AdjustLeft(self, left, test):
+ """Adjust a side.
+
+ Returns FALSE if it's not physically possible to adjust it to
+ this point.
+ """
+ x2 = self.GetX() + self.GetWidth() / 2.0
+
+ if left >= x2:
+ return False
+
+ if test:
+ return True
+
+ newW = x2 - left
+ newX = left + newW / 2.0
+ self.SetSize(newW, self.GetHeight())
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ self.Move(dc, newX, self.GetY())
+ return True
+
+ def AdjustTop(self, top, test):
+ """Adjust a side.
+
+ Returns FALSE if it's not physically possible to adjust it to
+ this point.
+ """
+ y2 = self.GetY() + self.GetHeight() / 2.0
+
+ if top >= y2:
+ return False
+
+ if test:
+ return True
+
+ newH = y2 - top
+ newY = top + newH / 2.0
+ self.SetSize(self.GetWidth(), newH)
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ self.Move(dc, self.GetX(), newY)
+ return True
+
+ def AdjustRight(self, right, test):
+ """Adjust a side.
+
+ Returns FALSE if it's not physically possible to adjust it to
+ this point.
+ """
+ x1 = self.GetX() - self.GetWidth() / 2.0
+
+ if right <= x1:
+ return False
+
+ if test:
+ return True
+
+ newW = right - x1
+ newX = x1 + newW / 2.0
+ self.SetSize(newW, self.GetHeight())
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ self.Move(dc, newX, self.GetY())
+ return True
+
+ def AdjustTop(self, top, test):
+ """Adjust a side.
+
+ Returns FALSE if it's not physically possible to adjust it to
+ this point.
+ """
+ y1 = self.GetY() - self.GetHeight() / 2.0
+
+ if bottom <= y1:
+ return False
+
+ if test:
+ return True
+
+ newH = bottom - y1
+ newY = y1 + newH / 2.0
+ self.SetSize(self.GetWidth(), newH)
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ self.Move(dc, self.GetX(), newY)
+ return True
+
+ # Resize adjoining divisions.
+
+ # Behaviour should be as follows:
+ # If right edge moves, find all objects whose left edge
+ # adjoins this object, and move left edge accordingly.
+ # If left..., move ... right.
+ # If top..., move ... bottom.
+ # If bottom..., move top.
+ # If size goes to zero or end position is other side of start position,
+ # resize to original size and return.
+ #
+ def ResizeAdjoining(self, side, newPos, test):
+ """Resize adjoining divisions at the given side.
+
+ If test is TRUE, just see whether it's possible for each adjoining
+ region, returning FALSE if it's not.
+
+ side can be one of:
+
+ * DIVISION_SIDE_NONE
+ * DIVISION_SIDE_LEFT
+ * DIVISION_SIDE_TOP
+ * DIVISION_SIDE_RIGHT
+ * DIVISION_SIDE_BOTTOM
+ """
+ divisionParent = self.GetParent()
+ for division in divisionParent.GetDivisions():
+ if side == DIVISION_SIDE_LEFT:
+ if division._rightSide == self:
+ success = division.AdjustRight(newPos, test)
+ if not success and test:
+ return false
+ elif side == DIVISION_SIDE_TOP:
+ if division._bottomSide == self:
+ success = division.AdjustBottom(newPos, test)
+ if not success and test:
+ return False
+ elif side == DIVISION_SIDE_RIGHT:
+ if division._leftSide == self:
+ success = division.AdjustLeft(newPos, test)
+ if not success and test:
+ return False
+ elif side == DIVISION_SIDE_BOTTOM:
+ if division._topSide == self:
+ success = division.AdjustTop(newPos, test)
+ if not success and test:
+ return False
+ return True
+
+ def EditEdge(self, side):
+ print "EditEdge() not implemented."
+
+ def PopupMenu(self, x, y):
+ menu = PopupDivisionMenu()
+ menu.SetClientData(self)
+ if self._leftSide:
+ menu.Enable(DIVISION_MENU_EDIT_LEFT_EDGE, True)
+ else:
+ menu.Enable(DIVISION_MENU_EDIT_LEFT_EDGE, False)
+ if self._topSide:
+ menu.Enable(DIVISION_MENU_EDIT_TOP_EDGE, True)
+ else:
+ menu.Enable(DIVISION_MENU_EDIT_TOP_EDGE, False)
+
+ x1, y1 = self._canvas.GetViewStart()
+ unit_x, unit_y = self._canvas.GetScrollPixelsPerUnit()
+
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ mouse_x = dc.LogicalToDeviceX(x - x1 * unit_x)
+ mouse_y = dc.LogicalToDeviceY(y - y1 * unit_y)
+
+ self._canvas.PopupMenu(menu, (mouse_x, mouse_y))
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_diagram.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_diagram.py
new file mode 100644
index 0000000..345a464
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_diagram.py
@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*-
+#----------------------------------------------------------------------------
+# Name: diagram.py
+# Purpose: Diagram class
+#
+# Author: Pierre Hjälm (from C++ original by Julian Smart)
+#
+# Created: 2004-05-08
+# RCS-ID: $Id$
+# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+import wx
+
+DEFAULT_MOUSE_TOLERANCE = 3
+
+
+
+class Diagram(object):
+ """Encapsulates an entire diagram, with methods for drawing. A diagram has
+ an associated ShapeCanvas.
+
+ Derived from:
+ Object
+ """
+ def __init__(self):
+ self._diagramCanvas = None
+ self._quickEditMode = False
+ self._snapToGrid = True
+ self._gridSpacing = 5.0
+ self._shapeList = []
+ self._mouseTolerance = DEFAULT_MOUSE_TOLERANCE
+
+ def Redraw(self, dc):
+ """Draw the shapes in the diagram on the specified device context."""
+ if self._shapeList:
+ if self.GetCanvas():
+ self.GetCanvas().SetCursor(wx.HOURGLASS_CURSOR)
+ for object in self._shapeList:
+ object.Draw(dc)
+ if self.GetCanvas():
+ self.GetCanvas().SetCursor(wx.STANDARD_CURSOR)
+
+ def Clear(self, dc):
+ """Clear the specified device context."""
+ dc.Clear()
+
+ def AddShape(self, object, addAfter = None):
+ """Adds a shape to the diagram. If addAfter is not None, the shape
+ will be added after addAfter.
+ """
+ if not object in self._shapeList:
+ if addAfter:
+ self._shapeList.insert(self._shapeList.index(addAfter) + 1, object)
+ else:
+ self._shapeList.append(object)
+
+ object.SetCanvas(self.GetCanvas())
+
+ def InsertShape(self, object):
+ """Insert a shape at the front of the shape list."""
+ self._shapeList.insert(0, object)
+
+ def RemoveShape(self, object):
+ """Remove the shape from the diagram (non-recursively) but do not
+ delete it.
+ """
+ if object in self._shapeList:
+ self._shapeList.remove(object)
+
+ def RemoveAllShapes(self):
+ """Remove all shapes from the diagram but do not delete the shapes."""
+ self._shapeList = []
+
+ def DeleteAllShapes(self):
+ """Remove and delete all shapes in the diagram."""
+ for shape in self._shapeList[:]:
+ if not shape.GetParent():
+ self.RemoveShape(shape)
+ shape.Delete()
+
+ def ShowAll(self, show):
+ """Call Show for each shape in the diagram."""
+ for shape in self._shapeList:
+ shape.Show(show)
+
+ def DrawOutline(self, dc, x1, y1, x2, y2):
+ """Draw an outline rectangle on the current device context."""
+ dc.SetPen(wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ dc.DrawLines([[x1, y1], [x2, y1], [x2, y2], [x1, y2], [x1, y1]])
+
+ def RecentreAll(self, dc):
+ """Make sure all text that should be centred, is centred."""
+ for shape in self._shapeList:
+ shape.Recentre(dc)
+
+ def SetCanvas(self, canvas):
+ """Set the canvas associated with this diagram."""
+ self._diagramCanvas = canvas
+
+ def GetCanvas(self):
+ """Return the shape canvas associated with this diagram."""
+ return self._diagramCanvas
+
+ def FindShape(self, id):
+ """Return the shape for the given identifier."""
+ for shape in self._shapeList:
+ if shape.GetId() == id:
+ return shape
+ return None
+
+ def Snap(self, x, y):
+ """'Snaps' the coordinate to the nearest grid position, if
+ snap-to-grid is on."""
+ if self._snapToGrid:
+ return self._gridSpacing * int(x / self._gridSpacing + 0.5), self._gridSpacing * int(y / self._gridSpacing + 0.5)
+ return x, y
+
+ def SetGridSpacing(self, spacing):
+ """Sets grid spacing."""
+ self._gridSpacing = spacing
+
+ def SetSnapToGrid(self, snap):
+ """Sets snap-to-grid mode."""
+ self._snapToGrid = snap
+
+ def GetGridSpacing(self):
+ """Return the grid spacing."""
+ return self._gridSpacing
+
+ def GetSnapToGrid(self):
+ """Return snap-to-grid mode."""
+ return self._snapToGrid
+
+ def SetQuickEditMode(self, mode):
+ """Set quick-edit-mode on of off.
+
+ In this mode, refreshes are minimized, but the diagram may need
+ manual refreshing occasionally.
+ """
+ self._quickEditMode = mode
+
+ def GetQuickEditMode(self):
+ """Return quick edit mode."""
+ return self._quickEditMode
+
+ def SetMouseTolerance(self, tolerance):
+ """Set the tolerance within which a mouse move is ignored.
+
+ The default is 3 pixels.
+ """
+ self._mouseTolerance = tolerance
+
+ def GetMouseTolerance(self):
+ """Return the tolerance within which a mouse move is ignored."""
+ return self._mouseTolerance
+
+ def GetShapeList(self):
+ """Return the internal shape list."""
+ return self._shapeList
+
+ def GetCount(self):
+ """Return the number of shapes in the diagram."""
+ return len(self._shapeList)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_divided.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_divided.py
new file mode 100644
index 0000000..2727638
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_divided.py
@@ -0,0 +1,402 @@
+# -*- coding: utf-8 -*-
+#----------------------------------------------------------------------------
+# Name: divided.py
+# Purpose: DividedShape class
+#
+# Author: Pierre Hjälm (from C++ original by Julian Smart)
+#
+# Created: 2004-05-08
+# RCS-ID: $Id$
+# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+import sys
+import wx
+
+from _basic import ControlPoint, RectangleShape, Shape
+from _oglmisc import *
+
+
+
+class DividedShapeControlPoint(ControlPoint):
+ def __init__(self, the_canvas, object, region, size, the_m_xoffset, the_m_yoffset, the_type):
+ ControlPoint.__init__(self, the_canvas, object, size, the_m_xoffset, the_m_yoffset, the_type)
+ self.regionId = region
+
+ # Implement resizing of divided object division
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dc.SetLogicalFunction(OGLRBLF)
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ dividedObject = self._shape
+ x1 = dividedObject.GetX() - dividedObject.GetWidth() / 2.0
+ y1 = y
+ x2 = dividedObject.GetX() + dividedObject.GetWidth() / 2.0
+ y2 = y
+
+ dc.DrawLine(x1, y1, x2, y2)
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dc.SetLogicalFunction(OGLRBLF)
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ dividedObject = self._shape
+
+ x1 = dividedObject.GetX() - dividedObject.GetWidth() / 2.0
+ y1 = y
+ x2 = dividedObject.GetX() + dividedObject.GetWidth() / 2.0
+ y2 = y
+
+ dc.DrawLine(x1, y1, x2, y2)
+ self._canvas.CaptureMouse()
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dividedObject = self._shape
+ if not dividedObject.GetRegions()[self.regionId]:
+ return
+
+ thisRegion = dividedObject.GetRegions()[self.regionId]
+ nextRegion = None
+
+ dc.SetLogicalFunction(wx.COPY)
+
+ if self._canvas.HasCapture():
+ self._canvas.ReleaseMouse()
+
+ # Find the old top and bottom of this region,
+ # and calculate the new proportion for this region
+ # if legal.
+ currentY = dividedObject.GetY() - dividedObject.GetHeight() / 2.0
+ maxY = dividedObject.GetY() + dividedObject.GetHeight() / 2.0
+
+ # Save values
+ theRegionTop = 0
+ nextRegionBottom = 0
+
+ for i in range(len(dividedObject.GetRegions())):
+ region = dividedObject.GetRegions()[i]
+ proportion = region._regionProportionY
+ yy = currentY + dividedObject.GetHeight() * proportion
+ actualY = min(maxY, yy)
+
+ if region == thisRegion:
+ thisRegionTop = currentY
+
+ if i + 1 < len(dividedObject.GetRegions()):
+ nextRegion = dividedObject.GetRegions()[i + 1]
+ if region == nextRegion:
+ nextRegionBottom = actualY
+
+ currentY = actualY
+
+ if not nextRegion:
+ return
+
+ # Check that we haven't gone above this region or below
+ # next region.
+ if y <= thisRegionTop or y >= nextRegionBottom:
+ return
+
+ dividedObject.EraseLinks(dc)
+
+ # Now calculate the new proportions of this region and the next region
+ thisProportion = float(y - thisRegionTop) / dividedObject.GetHeight()
+ nextProportion = float(nextRegionBottom - y) / dividedObject.GetHeight()
+
+ thisRegion.SetProportions(0, thisProportion)
+ nextRegion.SetProportions(0, nextProportion)
+ self._yoffset = y - dividedObject.GetY()
+
+ # Now reformat text
+ for i, region in enumerate(dividedObject.GetRegions()):
+ if region.GetText():
+ s = region.GetText()
+ dividedObject.FormatText(dc, s, i)
+
+ dividedObject.SetRegionSizes()
+ dividedObject.Draw(dc)
+ dividedObject.GetEventHandler().OnMoveLinks(dc)
+
+
+
+class DividedShape(RectangleShape):
+ """A DividedShape is a rectangle with a number of vertical divisions.
+ Each division may have its text formatted with independent characteristics,
+ and the size of each division relative to the whole image may be specified.
+
+ Derived from:
+ RectangleShape
+ """
+ def __init__(self, w, h):
+ RectangleShape.__init__(self, w, h)
+ self.ClearRegions()
+
+ def OnDraw(self, dc):
+ RectangleShape.OnDraw(self, dc)
+
+ def OnDrawContents(self, dc):
+ if self.GetRegions():
+ defaultProportion = 1.0 / len(self.GetRegions())
+ else:
+ defaultProportion = 0.0
+ currentY = self._ypos - self._height / 2.0
+ maxY = self._ypos + self._height / 2.0
+
+ leftX = self._xpos - self._width / 2.0
+ rightX = self._xpos + self._width / 2.0
+
+ if self._pen:
+ dc.SetPen(self._pen)
+
+ dc.SetTextForeground(self._textColour)
+
+ # For efficiency, don't do this under X - doesn't make
+ # any visible difference for our purposes.
+ if sys.platform[:3] == "win":
+ dc.SetTextBackground(self._brush.GetColour())
+
+ if self.GetDisableLabel():
+ return
+
+ xMargin = 2
+ yMargin = 2
+
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+
+ for region in self.GetRegions():
+ dc.SetFont(region.GetFont())
+ dc.SetTextForeground(region.GetActualColourObject())
+
+ if region._regionProportionY < 0:
+ proportion = defaultProportion
+ else:
+ proportion = region._regionProportionY
+
+ y = currentY + self._height * proportion
+ actualY = min(maxY, y)
+
+ centreX = self._xpos
+ centreY = currentY + (actualY - currentY) / 2.0
+
+ DrawFormattedText(dc, region._formattedText, centreX, centreY, self._width - 2 * xMargin, actualY - currentY - 2 * yMargin, region._formatMode)
+
+ if y <= maxY and region != self.GetRegions()[-1]:
+ regionPen = region.GetActualPen()
+ if regionPen:
+ dc.SetPen(regionPen)
+ dc.DrawLine(leftX, y, rightX, y)
+
+ currentY = actualY
+
+ def SetSize(self, w, h, recursive = True):
+ self.SetAttachmentSize(w, h)
+ self._width = w
+ self._height = h
+ self.SetRegionSizes()
+
+ def SetRegionSizes(self):
+ """Set all region sizes according to proportions and this object
+ total size.
+ """
+ if not self.GetRegions():
+ return
+
+ if self.GetRegions():
+ defaultProportion = 1.0 / len(self.GetRegions())
+ else:
+ defaultProportion = 0.0
+ currentY = self._ypos - self._height / 2.0
+ maxY = self._ypos + self._height / 2.0
+
+ for region in self.GetRegions():
+ if region._regionProportionY <= 0:
+ proportion = defaultProportion
+ else:
+ proportion = region._regionProportionY
+
+ sizeY = proportion * self._height
+ y = currentY + sizeY
+ actualY = min(maxY, y)
+
+ centreY = currentY + (actualY - currentY) / 2.0
+
+ region.SetSize(self._width, sizeY)
+ region.SetPosition(0, centreY - self._ypos)
+
+ currentY = actualY
+
+ # Attachment points correspond to regions in the divided box
+ def GetAttachmentPosition(self, attachment, nth = 0, no_arcs = 1, line = None):
+ totalNumberAttachments = len(self.GetRegions()) * 2 + 2
+ if self.GetAttachmentMode() == ATTACHMENT_MODE_NONE or attachment >= totalNumberAttachments:
+ return Shape.GetAttachmentPosition(self, attachment, nth, no_arcs)
+
+ n = len(self.GetRegions())
+ isEnd = line and line.IsEnd(self)
+
+ left = self._xpos - self._width / 2.0
+ right = self._xpos + self._width / 2.0
+ top = self._ypos - self._height / 2.0
+ bottom = self._ypos + self._height / 2.0
+
+ # Zero is top, n + 1 is bottom
+ if attachment == 0:
+ y = top
+ if self._spaceAttachments:
+ if line and line.GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ # Align line according to the next handle along
+ point = line.GetNextControlPoint(self)
+ if point[0] < left:
+ x = left
+ elif point[0] > right:
+ x = right
+ else:
+ x = point[0]
+ else:
+ x = left + (nth + 1) * self._width / (no_arcs + 1.0)
+ else:
+ x = self._xpos
+ elif attachment == n + 1:
+ y = bottom
+ if self._spaceAttachments:
+ if line and line.GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ # Align line according to the next handle along
+ point = line.GetNextControlPoint(self)
+ if point[0] < left:
+ x = left
+ elif point[0] > right:
+ x = right
+ else:
+ x = point[0]
+ else:
+ x = left + (nth + 1) * self._width / (no_arcs + 1.0)
+ else:
+ x = self._xpos
+ else: # Left or right
+ isLeft = not attachment < (n + 1)
+ if isLeft:
+ i = totalNumberAttachments - attachment - 1
+ else:
+ i = attachment - 1
+
+ region = self.GetRegions()[i]
+ if region:
+ if isLeft:
+ x = left
+ else:
+ x = right
+
+ # Calculate top and bottom of region
+ top = self._ypos + region._y - region._height / 2.0
+ bottom = self._ypos + region._y + region._height / 2.0
+
+ # Assuming we can trust the absolute size and
+ # position of these regions
+ if self._spaceAttachments:
+ if line and line.GetAlignmentType(isEnd) == LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ # Align line according to the next handle along
+ point = line.GetNextControlPoint(self)
+ if point[1] < bottom:
+ y = bottom
+ elif point[1] > top:
+ y = top
+ else:
+ y = point[1]
+ else:
+ y = top + (nth + 1) * region._height / (no_arcs + 1.0)
+ else:
+ y = self._ypos + region._y
+ else:
+ return False
+ return x, y
+
+ def GetNumberOfAttachments(self):
+ # There are two attachments for each region (left and right),
+ # plus one on the top and one on the bottom.
+ n = len(self.GetRegions()) * 2 + 2
+
+ maxN = n - 1
+ for point in self._attachmentPoints:
+ if point._id > maxN:
+ maxN = point._id
+
+ return maxN + 1
+
+ def AttachmentIsValid(self, attachment):
+ totalNumberAttachments = len(self.GetRegions()) * 2 + 2
+ if attachment >= totalNumberAttachments:
+ return Shape.AttachmentIsValid(self, attachment)
+ else:
+ return attachment >= 0
+
+ def MakeControlPoints(self):
+ RectangleShape.MakeControlPoints(self)
+ self.MakeMandatoryControlPoints()
+
+ def MakeMandatoryControlPoints(self):
+ currentY = self.GetY() - self._height / 2.0
+ maxY = self.GetY() + self._height / 2.0
+
+ for i, region in enumerate(self.GetRegions()):
+ proportion = region._regionProportionY
+
+ y = currentY + self._height * proportion
+ actualY = min(maxY, y)
+
+ if region != self.GetRegions()[-1]:
+ controlPoint = DividedShapeControlPoint(self._canvas, self, i, CONTROL_POINT_SIZE, 0, actualY - self.GetY(), 0)
+ self._canvas.AddShape(controlPoint)
+ self._controlPoints.append(controlPoint)
+
+ currentY = actualY
+
+ def ResetControlPoints(self):
+ # May only have the region handles, (n - 1) of them
+ if len(self._controlPoints) > len(self.GetRegions()) - 1:
+ RectangleShape.ResetControlPoints(self)
+
+ self.ResetMandatoryControlPoints()
+
+ def ResetMandatoryControlPoints(self):
+ currentY = self.GetY() - self._height / 2.0
+ maxY = self.GetY() + self._height / 2.0
+
+ i = 0
+ for controlPoint in self._controlPoints:
+ if isinstance(controlPoint, DividedShapeControlPoint):
+ region = self.GetRegions()[i]
+ proportion = region._regionProportionY
+
+ y = currentY + self._height * proportion
+ actualY = min(maxY, y)
+
+ controlPoint._xoffset = 0
+ controlPoint._yoffset = actualY - self.GetY()
+
+ currentY = actualY
+
+ i += 1
+
+ def EditRegions(self):
+ """Edit the region colours and styles. Not implemented."""
+ print "EditRegions() is unimplemented"
+
+ def OnRightClick(self, x, y, keys = 0, attachment = 0):
+ if keys & KEY_CTRL:
+ self.EditRegions()
+ else:
+ RectangleShape.OnRightClick(self, x, y, keys, attachment)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_drawn.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_drawn.py
new file mode 100644
index 0000000..5862b03
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_drawn.py
@@ -0,0 +1,888 @@
+# -*- coding: utf-8 -*-
+#----------------------------------------------------------------------------
+# Name: drawn.py
+# Purpose: DrawnShape class
+#
+# Author: Pierre Hjälm (from C++ original by Julian Smart)
+#
+# Created: 2004-08-25
+# RCS-ID: $Id$
+# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart
+# License: wxWindows license
+#----------------------------------------------------------------------------
+
+import os.path
+
+from _basic import RectangleShape
+from _oglmisc import *
+
+METAFLAGS_OUTLINE = 1
+METAFLAGS_ATTACHMENTS = 2
+
+DRAWN_ANGLE_0 = 0
+DRAWN_ANGLE_90 = 1
+DRAWN_ANGLE_180 = 2
+DRAWN_ANGLE_270 = 3
+
+# Drawing operations
+DRAWOP_SET_PEN = 1
+DRAWOP_SET_BRUSH = 2
+DRAWOP_SET_FONT = 3
+DRAWOP_SET_TEXT_COLOUR = 4
+DRAWOP_SET_BK_COLOUR = 5
+DRAWOP_SET_BK_MODE = 6
+DRAWOP_SET_CLIPPING_RECT = 7
+DRAWOP_DESTROY_CLIPPING_RECT = 8
+
+DRAWOP_DRAW_LINE = 20
+DRAWOP_DRAW_POLYLINE = 21
+DRAWOP_DRAW_POLYGON = 22
+DRAWOP_DRAW_RECT = 23
+DRAWOP_DRAW_ROUNDED_RECT = 24
+DRAWOP_DRAW_ELLIPSE = 25
+DRAWOP_DRAW_POINT = 26
+DRAWOP_DRAW_ARC = 27
+DRAWOP_DRAW_TEXT = 28
+DRAWOP_DRAW_SPLINE = 29
+DRAWOP_DRAW_ELLIPTIC_ARC = 30
+
+class DrawOp(object):
+ def __init__(self, theOp):
+ self._op = theOp
+
+ def GetOp(self):
+ return self._op
+
+ def GetPerimeterPoint(self, x1, y1, x2, y2, xOffset, yOffset, attachmentMode):
+ return False
+
+ def Scale(self,scaleX, scaleY):
+ pass
+
+ def Translate(self, x, y):
+ pass
+
+ def Rotate(self, x, y, theta, sinTheta, cosTheta):
+ pass
+
+class OpSetGDI(DrawOp):
+ """Set font, brush, text colour."""
+ def __init__(self, theOp, theImage, theGdiIndex, theMode = 0):
+ DrawOp.__init__(self, theOp)
+
+ self._gdiIndex = theGdiIndex
+ self._image = theImage
+ self._mode = theMode
+
+ def Do(self, dc, xoffset = 0, yoffset = 0):
+ if self._op == DRAWOP_SET_PEN:
+ # Check for overriding this operation for outline colour
+ if self._gdiIndex in self._image._outlineColours:
+ if self._image._outlinePen:
+ dc.SetPen(self._image._outlinePen)
+ else:
+ try:
+ dc.SetPen(self._image._gdiObjects[self._gdiIndex])
+ except IndexError:
+ pass
+ elif self._op == DRAWOP_SET_BRUSH:
+ # Check for overriding this operation for outline or fill colour
+ if self._gdiIndex in self._image._outlineColours:
+ # Need to construct a brush to match the outline pen's colour
+ if self._image._outlinePen:
+ br = wx.Brush(self._image._outlinePen, wx.SOLID)
+ if br:
+ dc.SetBrush(br)
+ elif self._gdiIndex in self._image._fillColours:
+ if self._image._fillBrush:
+ dc.SetBrush(self._image._fillBrush)
+ else:
+ brush = self._image._gdiObjects[self._gdiIndex]
+ if brush:
+ dc.SetBrush(brush)
+ elif self._op == DRAWOP_SET_FONT:
+ try:
+ dc.SetFont(self._image._gdiObjects[self._gdiIndex])
+ except IndexError:
+ pass
+ elif self._op == DRAWOP_SET_TEXT_COLOUR:
+ dc.SetTextForeground(wx.Colour(self._r, self._g, self._b))
+ elif self._op == DRAWOP_SET_BK_COLOUR:
+ dc.SetTextBackground(wx.Colour(self._r, self._g, self._b))
+ elif self._op == DRAWOP_SET_BK_MODE:
+ dc.SetBackgroundMode(self._mode)
+
+
+class OpSetClipping(DrawOp):
+ """Set/destroy clipping."""
+ def __init__(self, theOp, theX1, theY1, theX2, theY2):
+ DrawOp.__init__(self, theOp)
+
+ self._x1 = theX1
+ self._y1 = theY1
+ self._x2 = theX2
+ self._y2 = theY2
+
+ def Do(self, dc, xoffset, yoffset):
+ if self._op == DRAWOP_SET_CLIPPING_RECT:
+ dc.SetClippingRegion(self._x1 + xoffset, self._y1 + yoffset, self._x2 + xoffset, self._y2 + yoffset)
+ elif self._op == DRAWOP_DESTROY_CLIPPING_RECT:
+ dc.DestroyClippingRegion()
+
+ def Scale(self, scaleX, scaleY):
+ self._x1 *= scaleX
+ self._y1 *= scaleY
+ self._x2 *= scaleX
+ self._y2 *= scaleY
+
+ def Translate(self, x, y):
+ self._x1 += x
+ self._y1 += y
+
+
+class OpDraw(DrawOp):
+ """Draw line, rectangle, rounded rectangle, ellipse, point, arc, text."""
+ def __init__(self, theOp, theX1, theY1, theX2, theY2, theRadius = 0.0, s = ""):
+ DrawOp.__init__(self, theOp)
+
+ self._x1 = theX1
+ self._y1 = theY1
+ self._x2 = theX2
+ self._y2 = theY2
+ self._x3 = 0.0
+ self._y3 = 0.0
+ self._radius = theRadius
+ self._textString = s
+
+ def Do(self, dc, xoffset, yoffset):
+ if self._op == DRAWOP_DRAW_LINE:
+ dc.DrawLine(self._x1 + xoffset, self._y1 + yoffset, self._x2 + xoffset, self._y2 + yoffset)
+ elif self._op == DRAWOP_DRAW_RECT:
+ dc.DrawRectangle(self._x1 + xoffset, self._y1 + yoffset, self._x2, self._y2)
+ elif self._op == DRAWOP_DRAW_ROUNDED_RECT:
+ dc.DrawRoundedRectangle(self._x1 + xoffset, self._y1 + yoffset, self._x2, self._y2, self._radius)
+ elif self._op == DRAWOP_DRAW_ELLIPSE:
+ dc.DrawEllipse(self._x1 + xoffset, self._y1 + yoffset, self._x2, self._y2)
+ elif self._op == DRAWOP_DRAW_ARC:
+ dc.DrawArc(self._x2 + xoffset, self._y2 + yoffset, self._x3 + xoffset, self._y3 + yoffset, self._x1 + xoffset, self._y1 + yoffset)
+ elif self._op == DRAWOP_DRAW_ELLIPTIC_ARC:
+ dc.DrawEllipticArc(self._x1 + xoffset, self._y1 + yoffset, self._x2, self._y2, self._x3 * 360 / (2 * math.pi), self._y3 * 360 / (2 * math.pi))
+ elif self._op == DRAWOP_DRAW_POINT:
+ dc.DrawPoint(self._x1 + xoffset, self._y1 + yoffset)
+ elif self._op == DRAWOP_DRAW_TEXT:
+ dc.DrawText(self._textString, self._x1 + xoffset, self._y1 + yoffset)
+ def Scale(self, scaleX, scaleY):
+ self._x1 *= scaleX
+ self._y1 *= scaleY
+ self._x2 *= scaleX
+ self._y2 *= scaleY
+
+ if self._op != DRAWOP_DRAW_ELLIPTIC_ARC:
+ self._x3 *= scaleX
+ self._y3 *= scaleY
+
+ self._radius *= scaleX
+
+ def Translate(self, x, y):
+ self._x1 += x
+ self._y1 += y
+
+ if self._op == DRAWOP_DRAW_LINE:
+ self._x2 += x
+ self._y2 += y
+ elif self._op == DRAWOP_DRAW_ARC:
+ self._x2 += x
+ self._y2 += y
+ self._x3 += x
+ self._y3 += y
+
+ def Rotate(self, x, y, theta, sinTheta, cosTheta):
+ newX1 = self._x1 * cosTheta + self._y1 * sinTheta + x * (1 - cosTheta) + y * sinTheta
+ newY1 = self._x1 * sinTheta + self._y1 * cosTheta + y * (1 - cosTheta) + x * sinTheta
+
+ if self._op == DRAWOP_DRAW_LINE:
+ newX2 = self._x2 * cosTheta - self._y2 * sinTheta + x * (1 - cosTheta) + y * sinTheta
+ newY2 = self._x2 * sinTheta + self._y2 * cosTheta + y * (1 - cosTheta) + x * sinTheta;
+
+ self._x1 = newX1
+ self._y1 = newY1
+ self._x2 = newX2
+ self._y2 = newY2
+
+ elif self._op in [DRAWOP_DRAW_RECT, DRAWOP_DRAW_ROUNDED_RECT, DRAWOP_DRAW_ELLIPTIC_ARC]:
+ # Assume only 0, 90, 180, 270 degree rotations.
+ # oldX1, oldY1 represents the top left corner. Find the
+ # bottom right, and rotate that. Then the width/height is
+ # the difference between x/y values.
+ oldBottomRightX = self._x1 + self._x2
+ oldBottomRightY = self._y1 + self._y2
+ newBottomRightX = oldBottomRightX * cosTheta - oldBottomRightY * sinTheta + x * (1 - cosTheta) + y * sinTheta
+ newBottomRightY = oldBottomRightX * sinTheta + oldBottomRightY * cosTheta + y * (1 - cosTheta) + x * sinTheta
+
+ # Now find the new top-left, bottom-right coordinates.
+ minX = min(newX1, newBottomRightX)
+ minY = min(newY1, newBottomRightY)
+ maxX = max(newX1, newBottomRightX)
+ maxY = max(newY1, newBottomRightY)
+
+ self._x1 = minX
+ self._y1 = minY
+ self._x2 = maxX - minX # width
+ self._y2 = maxY - minY # height
+
+ if self._op == DRAWOP_DRAW_ELLIPTIC_ARC:
+ # Add rotation to angles
+ self._x3 += theta
+ self._y3 += theta
+ elif self._op == DRAWOP_DRAW_ARC:
+ newX2 = self._x2 * cosTheta - self._y2 * sinTheta + x * (1 - cosTheta) + y * sinTheta
+ newY2 = self._x2 * sinTheta + self._y2 * cosTheta + y * (1 - cosTheta) + x * sinTheta
+ newX3 = self._x3 * cosTheta - self._y3 * sinTheta + x * (1 - cosTheta) + y * sinTheta
+ newY3 = self._x3 * sinTheta + self._y3 * cosTheta + y * (1 - cosTheta) + x * sinTheta
+
+ self._x1 = newX1
+ self._y1 = newY1
+ self._x2 = newX2
+ self._y2 = newY2
+ self._x3 = newX3
+ self._y3 = newY3
+
+
+class OpPolyDraw(DrawOp):
+ """Draw polygon, polyline, spline."""
+ def __init__(self, theOp, thePoints):
+ DrawOp.__init__(self, theOp)
+
+ self._noPoints = len(thePoints)
+ self._points = thePoints
+
+ def Do(self, dc, xoffset, yoffset):
+ if self._op == DRAWOP_DRAW_POLYLINE:
+ dc.DrawLines(self._points, xoffset, yoffset)
+ elif self._op == DRAWOP_DRAW_POLYGON:
+ dc.DrawPolygon(self._points, xoffset, yoffset)
+ elif self._op == DRAWOP_DRAW_SPLINE:
+ dc.DrawSpline(self._points) # no offsets in DrawSpline
+
+ def Scale(self, scaleX, scaleY):
+ for i in range(self._noPoints):
+ self._points[i] = wx.Point(self._points[i][0] * scaleX, self._points[i][1] * scaleY)
+
+ def Translate(self, x, y):
+ for i in range(self._noPoints):
+ self._points[i][0] += x
+ self._points[i][1] += y
+
+ def Rotate(self, x, y, theta, sinTheta, cosTheta):
+ for i in range(self._noPoints):
+ x1 = self._points[i][0]
+ y1 = self._points[i][1]
+
+ self._points[i] = x1 * cosTheta - y1 * sinTheta + x * (1 - cosTheta) + y * sinTheta, x1 * sinTheta + y1 * cosTheta + y * (1 - cosTheta) + x * sinTheta
+
+ def OnDrawOutline(self, dc, x, y, w, h, oldW, oldH):
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ # Multiply all points by proportion of new size to old size
+ x_proportion = abs(w / oldW)
+ y_proportion = abs(h / oldH)
+
+ dc.DrawPolygon([(x_proportion * x, y_proportion * y) for x, y in self._points], x, y)
+
+ def GetPerimeterPoint(self, x1, y1, x2, y2, xOffset, yOffset, attachmentMode):
+ # First check for situation where the line is vertical,
+ # and we would want to connect to a point on that vertical --
+ # oglFindEndForPolyline can't cope with this (the arrow
+ # gets drawn to the wrong place).
+ if attachmentMode == ATTACHMENT_MODE_NONE and x1 == x2:
+ # Look for the point we'd be connecting to. This is
+ # a heuristic...
+ for point in self._points:
+ if point[0] == 0:
+ if y2 > y1 and point[1] > 0:
+ return point[0]+xOffset, point[1]+yOffset
+ elif y2 < y1 and point[1] < 0:
+ return point[0]+xOffset, point[1]+yOffset
+
+ return FindEndForPolyline([ p[0] + xOffset for p in self._points ],
+ [ p[1] + yOffset for p in self._points ],
+ x1, y1, x2, y2)
+
+
+class PseudoMetaFile(object):
+ """
+ A simple metafile-like class which can load data from a Windows
+ metafile on all platforms.
+ """
+ def __init__(self):
+ self._currentRotation = 0
+ self._rotateable = True
+ self._width = 0.0
+ self._height = 0.0
+ self._outlinePen = None
+ self._fillBrush = None
+ self._outlineOp = -1
+
+ self._ops = []
+ self._gdiObjects = []
+
+ self._outlineColours = []
+ self._fillColours = []
+
+ def Clear(self):
+ self._ops = []
+ self._gdiObjects = []
+ self._outlineColours = []
+ self._fillColours = []
+ self._outlineColours = -1
+
+ def IsValid(self):
+ return self._ops != []
+
+ def GetOps(self):
+ return self._ops
+
+ def SetOutlineOp(self, op):
+ self._outlineOp = op
+
+ def GetOutlineOp(self):
+ return self._outlineOp
+
+ def SetOutlinePen(self, pen):
+ self._outlinePen = pen
+
+ def GetOutlinePen(self, pen):
+ return self._outlinePen
+
+ def SetFillBrush(self, brush):
+ self._fillBrush = brush
+
+ def GetFillBrush(self):
+ return self._fillBrush
+
+ def SetSize(self, w, h):
+ self._width = w
+ self._height = h
+
+ def SetRotateable(self, rot):
+ self._rotateable = rot
+
+ def GetRotateable(self):
+ return self._rotateable
+
+ def GetFillColours(self):
+ return self._fillColours
+
+ def GetOutlineColours(self):
+ return self._outlineColours
+
+ def Draw(self, dc, xoffset, yoffset):
+ for op in self._ops:
+ op.Do(dc, xoffset, yoffset)
+
+ def Scale(self, sx, sy):
+ for op in self._ops:
+ op.Scale(sx, sy)
+
+ self._width *= sx
+ self._height *= sy
+
+ def Translate(self, x, y):
+ for op in self._ops:
+ op.Translate(x, y)
+
+ def Rotate(self, x, y, theta):
+ theta1 = theta - self._currentRotation
+ if theta1 == 0:
+ return
+
+ cosTheta = math.cos(theta1)
+ sinTheta = math.sin(theta1)
+
+ for op in self._ops:
+ op.Rotate(x, y, theta, sinTheta, cosTheta)
+
+ self._currentRotation = theta
+
+ def LoadFromMetaFile(self, filename, rwidth, rheight):
+ if not os.path.exist(filename):
+ return False
+
+ print "LoadFromMetaFile not implemented yet."
+ return False # TODO
+
+ # Scale to fit size
+ def ScaleTo(self, w, h):
+ scaleX = w / self._width
+ scaleY = h / self._height
+
+ self.Scale(scaleX, scaleY)
+
+ def GetBounds(self):
+ maxX, maxY, minX, minY = -99999.9, -99999.9, 99999.9, 99999.9
+
+ for op in self._ops:
+ if op.GetOp() in [DRAWOP_DRAW_LINE, DRAWOP_DRAW_RECT, DRAWOP_DRAW_ROUNDED_RECT, DRAWOP_DRAW_ELLIPSE, DRAWOP_DRAW_POINT, DRAWOP_DRAW_TEXT]:
+ if op._x1 < minX:
+ minX = op._x1
+ if op._x1 > maxX:
+ maxX = op._x1
+ if op._y1 < minY:
+ minY = op._y1
+ if op._y1 > maxY:
+ maxY = op._y1
+ if op.GetOp() == DRAWOP_DRAW_LINE:
+ if op._x2 < minX:
+ minX = op._x2
+ if op._x2 > maxX:
+ maxX = op._x2
+ if op._y2 < minY:
+ minY = op._y2
+ if op._y2 > maxY:
+ maxY = op._y2
+ elif op.GetOp() in [ DRAWOP_DRAW_RECT, DRAWOP_DRAW_ROUNDED_RECT, DRAWOP_DRAW_ELLIPSE]:
+ if op._x1 + op._x2 < minX:
+ minX = op._x1 + op._x2
+ if op._x1 + op._x2 > maxX:
+ maxX = op._x1 + op._x2
+ if op._y1 + op._y2 < minY:
+ minY = op._y1 + op._y2
+ if op._y1 + op._y2 > maxX:
+ maxY = op._y1 + op._y2
+ elif op.GetOp() == DRAWOP_DRAW_ARC:
+ # TODO: don't yet know how to calculate the bounding box
+ # for an arc. So pretend it's a line; to get a correct
+ # bounding box, draw a blank rectangle first, of the
+ # correct size.
+ if op._x1 < minX:
+ minX = op._x1
+ if op._x1 > maxX:
+ maxX = op._x1
+ if op._y1 < minY:
+ minY = op._y1
+ if op._y1 > maxY:
+ maxY = op._y1
+ if op._x2 < minX:
+ minX = op._x2
+ if op._x2 > maxX:
+ maxX = op._x2
+ if op._y2 < minY:
+ minY = op._y2
+ if op._y2 > maxY:
+ maxY = op._y2
+ elif op.GetOp() in [DRAWOP_DRAW_POLYLINE, DRAWOP_DRAW_POLYGON, DRAWOP_DRAW_SPLINE]:
+ for point in op._points:
+ if point[0] < minX:
+ minX = point[0]
+ if point[0] > maxX:
+ maxX = point[0]
+ if point[1] < minY:
+ minY = point[1]
+ if point[1] > maxY:
+ maxY = point[1]
+
+ return [minX, minY, maxX, maxY]
+
+ # Calculate size from current operations
+ def CalculateSize(self, shape):
+ boundMinX, boundMinY, boundMaxX, boundMaxY = self.GetBounds()
+
+ # By Pierre Hjälm: This is NOT in the old version, which
+ # gets this totally wrong. Since the drawing is centered, we
+ # cannot get the width by measuring from left to right, we
+ # must instead make enough room to handle the largest
+ # coordinates
+ #self.SetSize(boundMaxX - boundMinX, boundMaxY - boundMinY)
+
+ w = max(abs(boundMinX), abs(boundMaxX)) * 2
+ h = max(abs(boundMinY), abs(boundMaxY)) * 2
+
+ self.SetSize(w, h)
+
+ if shape:
+ shape.SetWidth(self._width)
+ shape.SetHeight(self._height)
+
+ # Set of functions for drawing into a pseudo metafile
+ def DrawLine(self, pt1, pt2):
+ op = OpDraw(DRAWOP_DRAW_LINE, pt1[0], pt1[1], pt2[0], pt2[1])
+ self._ops.append(op)
+
+ def DrawRectangle(self, rect):
+ op = OpDraw(DRAWOP_DRAW_RECT, rect[0], rect[1], rect[2], rect[3])
+ self._ops.append(op)
+
+ def DrawRoundedRectangle(self, rect, radius):
+ op = OpDraw(DRAWOP_DRAW_ROUNDED_RECT, rect[0], rect[1], rect[2], rect[3])
+ op._radius = radius
+ self._ops.append(op)
+
+ def DrawEllipse(self, rect):
+ op = OpDraw(DRAWOP_DRAW_ELLIPSE, rect[0], rect[1], rect[2], rect[3])
+ self._ops.append(op)
+
+ def DrawArc(self, centrePt, startPt, endPt):
+ op = OpDraw(DRAWOP_DRAW_ARC, centrePt[0], centrePt[1], startPt[0], startPt[1])
+ op._x3, op._y3 = endPt
+
+ self._ops.append(op)
+
+ def DrawEllipticArc(self, rect, startAngle, endAngle):
+ startAngleRadians = startAngle * math.pi * 2 / 360
+ endAngleRadians = endAngle * math.pi * 2 / 360
+
+ op = OpDraw(DRAWOP_DRAW_ELLIPTIC_ARC, rect[0], rect[1], rect[2], rect[3])
+ op._x3 = startAngleRadians
+ op._y3 = endAngleRadians
+
+ self._ops.append(op)
+
+ def DrawPoint(self, pt):
+ op = OpDraw(DRAWOP_DRAW_POINT, pt[0], pt[1], 0, 0)
+ self._ops.append(op)
+
+ def DrawText(self, text, pt):
+ op = OpDraw(DRAWOP_DRAW_TEXT, pt[0], pt[1], 0, 0)
+ op._textString = text
+ self._ops.append(op)
+
+ def DrawLines(self, pts):
+ op = OpPolyDraw(DRAWOP_DRAW_POLYLINE, pts)
+ self._ops.append(op)
+
+ # flags:
+ # oglMETAFLAGS_OUTLINE: will be used for drawing the outline and
+ # also drawing lines/arrows at the circumference.
+ # oglMETAFLAGS_ATTACHMENTS: will be used for initialising attachment
+ # points at the vertices (perhaps a rare case...)
+ def DrawPolygon(self, pts, flags = 0):
+ op = OpPolyDraw(DRAWOP_DRAW_POLYGON, pts)
+ self._ops.append(op)
+
+ if flags & METAFLAGS_OUTLINE:
+ self._outlineOp = len(self._ops) - 1
+
+ def DrawSpline(self, pts):
+ op = OpPolyDraw(DRAWOP_DRAW_SPLINE, pts)
+ self._ops.append(op)
+
+ def SetClippingRect(self, rect):
+ OpSetClipping(DRAWOP_SET_CLIPPING_RECT, rect[0], rect[1], rect[2], rect[3])
+
+ def DestroyClippingRect(self):
+ op = OpSetClipping(DRAWOP_DESTROY_CLIPPING_RECT, 0, 0, 0, 0)
+ self._ops.append(op)
+
+ def SetPen(self, pen, isOutline = False):
+ self._gdiObjects.append(pen)
+ op = OpSetGDI(DRAWOP_SET_PEN, self, len(self._gdiObjects) - 1)
+ self._ops.append(op)
+
+ if isOutline:
+ self._outlineColours.append(len(self._gdiObjects) - 1)
+
+ def SetBrush(self, brush, isFill = False):
+ self._gdiObjects.append(brush)
+ op = OpSetGDI(DRAWOP_SET_BRUSH, self, len(self._gdiObjects) - 1)
+ self._ops.append(op)
+
+ if isFill:
+ self._fillColours.append(len(self._gdiObjects) - 1)
+
+ def SetFont(self, font):
+ self._gdiObjects.append(font)
+ op = OpSetGDI(DRAWOP_SET_FONT, self, len(self._gdiObjects) - 1)
+ self._ops.append(op)
+
+ def SetTextColour(self, colour):
+ op = OpSetGDI(DRAWOP_SET_TEXT_COLOUR, self, 0)
+ op._r, op._g, op._b = colour.Red(), colour.Green(), colour.Blue()
+
+ self._ops.append(op)
+
+ def SetBackgroundColour(self, colour):
+ op = OpSetGDI(DRAWOP_SET_BK_COLOUR, self, 0)
+ op._r, op._g, op._b = colour.Red(), colour.Green(), colour.Blue()
+
+ self._ops.append(op)
+
+ def SetBackgroundMode(self, mode):
+ op = OpSetGDI(DRAWOP_SET_BK_MODE, self, 0)
+ self._ops.append(op)
+
+class DrawnShape(RectangleShape):
+ """
+ Draws a pseudo-metafile shape, which can be loaded from a simple
+ Windows metafile.
+
+ wxDrawnShape allows you to specify a different shape for each of four
+ orientations (North, West, South and East). It also provides a set of
+ drawing functions for programmatic drawing of a shape, so that during
+ construction of the shape you can draw into it as if it were a device
+ context.
+
+ Derived from:
+ RectangleShape
+ """
+ def __init__(self):
+ RectangleShape.__init__(self, 100, 50)
+ self._saveToFile = True
+ self._currentAngle = DRAWN_ANGLE_0
+
+ self._metafiles=PseudoMetaFile(), PseudoMetaFile(), PseudoMetaFile(), PseudoMetaFile()
+
+ def OnDraw(self, dc):
+ # Pass pen and brush in case we have force outline
+ # and fill colours
+ if self._shadowMode != SHADOW_NONE:
+ if self._shadowBrush:
+ self._metafiles[self._currentAngle]._fillBrush = self._shadowBrush
+ self._metafiles[self._currentAngle]._outlinePen = wx.Pen(wx.WHITE, 1, wx.TRANSPARENT)
+ self._metafiles[self._currentAngle].Draw(dc, self._xpos + self._shadowOffsetX, self._ypos + self._shadowOffsetY)
+
+ self._metafiles[self._currentAngle]._outlinePen = self._pen
+ self._metafiles[self._currentAngle]._fillBrush = self._brush
+ self._metafiles[self._currentAngle].Draw(dc, self._xpos, self._ypos)
+
+ def SetSize(self, w, h, recursive = True):
+ self.SetAttachmentSize(w, h)
+
+ if self.GetWidth() == 0.0:
+ scaleX = 1
+ else:
+ scaleX = w / self.GetWidth()
+
+ if self.GetHeight() == 0.0:
+ scaleY = 1
+ else:
+ scaleY = h / self.GetHeight()
+
+ for i in range(4):
+ if self._metafiles[i].IsValid():
+ self._metafiles[i].Scale(scaleX, scaleY)
+
+ self._width = w
+ self._height = h
+ self.SetDefaultRegionSize()
+
+ def Scale(self, sx, sy):
+ """Scale the shape by the given amount."""
+ for i in range(4):
+ if self._metafiles[i].IsValid():
+ self._metafiles[i].Scale(sx, sy)
+ self._metafiles[i].CalculateSize(self)
+
+ def Translate(self, x, y):
+ """Translate the shape by the given amount."""
+ for i in range(4):
+ if self._metafiles[i].IsValid():
+ self._metafiles[i].Translate(x, y)
+ self._metafiles[i].CalculateSize(self)
+
+ # theta is absolute rotation from the zero position
+ def Rotate(self, x, y, theta):
+ """Rotate about the given axis by the given amount in radians."""
+ self._currentAngle = self.DetermineMetaFile(theta)
+
+ if self._currentAngle == 0:
+ # Rotate metafile
+ if not self._metafiles[0].GetRotateable():
+ return
+
+ self._metafiles[0].Rotate(x, y, theta)
+
+ actualTheta = theta - self._rotation
+
+ # Rotate attachment points
+ sinTheta = math.sin(actualTheta)
+ cosTheta = math.cos(actualTheta)
+
+ for point in self._attachmentPoints:
+ x1 = point._x
+ y1 = point._y
+
+ point._x = x1 * cosTheta - y1 * sinTheta + x * (1.0 - cosTheta) + y * sinTheta
+ point._y = x1 * sinTheta + y1 * cosTheta + y * (1.0 - cosTheta) + x * sinTheta
+
+ self._rotation = theta
+
+ self._metafiles[self._currentAngle].CalculateSize(self)
+
+ # Which metafile do we use now? Based on current rotation and validity
+ # of metafiles.
+ def DetermineMetaFile(self, rotation):
+ tolerance = 0.0001
+ angles = [0.0, math.pi / 2, math.pi, 3 * math.pi / 2]
+
+ whichMetaFile = 0
+
+ for i in range(4):
+ if RoughlyEqual(rotation, angles[i], tolerance):
+ whichMetaFile = i
+ break
+
+ if whichMetaFile > 0 and not self._metafiles[whichMetaFile].IsValid():
+ whichMetaFile = 0
+
+ return whichMetaFile
+
+ def OnDrawOutline(self, dc, x, y, w, h):
+ if self._metafiles[self._currentAngle].GetOutlineOp() != -1:
+ op = self._metafiles[self._currentAngle].GetOps()[self._metafiles[self._currentAngle].GetOutlineOp()]
+ if op.OnDrawOutline(dc, x, y, w, h, self._width, self._height):
+ return
+
+ # Default... just use a rectangle
+ RectangleShape.OnDrawOutline(self, dc, x, y, w, h)
+
+ # Get the perimeter point using the special outline op, if there is one,
+ # otherwise use default wxRectangleShape scheme
+ def GetPerimeterPoint(self, x1, y1, x2, y2):
+ if self._metafiles[self._currentAngle].GetOutlineOp() != -1:
+ op = self._metafiles[self._currentAngle].GetOps()[self._metafiles[self._currentAngle].GetOutlineOp()]
+ p = op.GetPerimeterPoint(x1, y1, x2, y2, self.GetX(), self.GetY(), self.GetAttachmentMode())
+ if p:
+ return p
+
+ return RectangleShape.GetPerimeterPoint(self, x1, y1, x2, y2)
+
+ def LoadFromMetaFile(self, filename):
+ """Load a (very simple) Windows metafile, created for example by
+ Top Draw, the Windows shareware graphics package."""
+ return self._metafiles[0].LoadFromMetaFile(filename)
+
+ # Set of functions for drawing into a pseudo metafile.
+ # They use integers, but doubles are used internally for accuracy
+ # when scaling.
+ def DrawLine(self, pt1, pt2):
+ self._metafiles[self._currentAngle].DrawLine(pt1, pt2)
+
+ def DrawRectangle(self, rect):
+ self._metafiles[self._currentAngle].DrawRectangle(rect)
+
+ def DrawRoundedRectangle(self, rect, radius):
+ """Draw a rounded rectangle.
+
+ radius is the corner radius. If radius is negative, it expresses
+ the radius as a proportion of the smallest dimension of the rectangle.
+ """
+ self._metafiles[self._currentAngle].DrawRoundedRectangle(rect, radius)
+
+ def DrawEllipse(self, rect):
+ self._metafiles[self._currentAngle].DrawEllipse(rect)
+
+ def DrawArc(self, centrePt, startPt, endPt):
+ """Draw an arc."""
+ self._metafiles[self._currentAngle].DrawArc(centrePt, startPt, endPt)
+
+ def DrawEllipticArc(self, rect, startAngle, endAngle):
+ """Draw an elliptic arc."""
+ self._metafiles[self._currentAngle].DrawEllipticArc(rect, startAngle, endAngle)
+
+ def DrawPoint(self, pt):
+ self._metafiles[self._currentAngle].DrawPoint(pt)
+
+ def DrawText(self, text, pt):
+ self._metafiles[self._currentAngle].DrawText(text, pt)
+
+ def DrawLines(self, pts):
+ self._metafiles[self._currentAngle].DrawLines(pts)
+
+ def DrawPolygon(self, pts, flags = 0):
+ """Draw a polygon.
+
+ flags can be one or more of:
+ METAFLAGS_OUTLINE (use this polygon for the drag outline) and
+ METAFLAGS_ATTACHMENTS (use the vertices of this polygon for attachments).
+ """
+ if flags and METAFLAGS_ATTACHMENTS:
+ self.ClearAttachments()
+ for i in range(len(pts)):
+ self._attachmentPoints.append(AttachmentPoint(i,pts[i][0],pts[i][1]))
+ self._metafiles[self._currentAngle].DrawPolygon(pts, flags)
+
+ def DrawSpline(self, pts):
+ self._metafiles[self._currentAngle].DrawSpline(pts)
+
+ def SetClippingRect(self, rect):
+ """Set the clipping rectangle."""
+ self._metafiles[self._currentAngle].SetClippingRect(rect)
+
+ def DestroyClippingRect(self):
+ """Destroy the clipping rectangle."""
+ self._metafiles[self._currentAngle].DestroyClippingRect()
+
+ def SetDrawnPen(self, pen, isOutline = False):
+ """Set the pen for this metafile.
+
+ If isOutline is True, this pen is taken to indicate the outline
+ (and if the outline pen is changed for the whole shape, the pen
+ will be replaced with the outline pen).
+ """
+ self._metafiles[self._currentAngle].SetPen(pen, isOutline)
+
+ def SetDrawnBrush(self, brush, isFill = False):
+ """Set the brush for this metafile.
+
+ If isFill is True, the brush is used as the fill brush.
+ """
+ self._metafiles[self._currentAngle].SetBrush(brush, isFill)
+
+ def SetDrawnFont(self, font):
+ self._metafiles[self._currentAngle].SetFont(font)
+
+ def SetDrawnTextColour(self, colour):
+ """Set the current text colour for the current metafile."""
+ self._metafiles[self._currentAngle].SetTextColour(colour)
+
+ def SetDrawnBackgroundColour(self, colour):
+ """Set the current background colour for the current metafile."""
+ self._metafiles[self._currentAngle].SetBackgroundColour(colour)
+
+ def SetDrawnBackgroundMode(self, mode):
+ """Set the current background mode for the current metafile."""
+ self._metafiles[self._currentAngle].SetBackgroundMode(mode)
+
+ def CalculateSize(self):
+ """Calculate the wxDrawnShape size from the current metafile.
+
+ Call this after you have drawn into the shape.
+ """
+ self._metafiles[self._currentAngle].CalculateSize(self)
+
+ def DrawAtAngle(self, angle):
+ """Set the metafile for the given orientation, which can be one of:
+
+ * DRAWN_ANGLE_0
+ * DRAWN_ANGLE_90
+ * DRAWN_ANGLE_180
+ * DRAWN_ANGLE_270
+ """
+ self._currentAngle = angle
+
+ def GetAngle(self):
+ """Return the current orientation, which can be one of:
+
+ * DRAWN_ANGLE_0
+ * DRAWN_ANGLE_90
+ * DRAWN_ANGLE_180
+ * DRAWN_ANGLE_270
+ """
+ return self._currentAngle
+
+ def GetRotation(self):
+ """Return the current rotation of the shape in radians."""
+ return self._rotation
+
+ def SetSaveToFile(self, save):
+ """If save is True, the image will be saved along with the shape's
+ other attributes. The reason why this might not be desirable is that
+ if there are many shapes with the same image, it would be more
+ efficient for the application to save one copy, and not duplicate
+ the information for every shape. The default is True.
+ """
+ self._saveToFile = save
+
+ def GetMetaFile(self, which = 0):
+ """Return a reference to the internal 'pseudo-metafile'."""
+ return self._metafiles[which]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_lines.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_lines.py
new file mode 100644
index 0000000..5780abc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_lines.py
@@ -0,0 +1,1532 @@
+# -*- coding: utf-8 -*-
+#----------------------------------------------------------------------------
+# Name: lines.py
+# Purpose: LineShape class
+#
+# Author: Pierre Hjälm (from C++ original by Julian Smart)
+#
+# Created: 2004-05-08
+# RCS-ID: $Id$
+# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+import sys
+import math
+
+from _basic import Shape, ShapeRegion, ShapeTextLine, ControlPoint, RectangleShape
+from _oglmisc import *
+
+# Line alignment flags
+# Vertical by default
+LINE_ALIGNMENT_HORIZ = 1
+LINE_ALIGNMENT_VERT = 0
+LINE_ALIGNMENT_TO_NEXT_HANDLE = 2
+LINE_ALIGNMENT_NONE = 0
+
+
+
+class LineControlPoint(ControlPoint):
+ def __init__(self, theCanvas = None, object = None, size = 0.0, x = 0.0, y = 0.0, the_type = 0):
+ ControlPoint.__init__(self, theCanvas, object, size, x, y, the_type)
+ self._xpos = x
+ self._ypos = y
+ self._type = the_type
+ self._point = None
+ self._originalPos = None
+
+ def OnDraw(self, dc):
+ RectangleShape.OnDraw(self, dc)
+
+ # Implement movement of Line point
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ self._shape.GetEventHandler().OnSizingDragLeft(self, draw, x, y, keys, attachment)
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ self._shape.GetEventHandler().OnSizingBeginDragLeft(self, x, y, keys, attachment)
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ self._shape.GetEventHandler().OnSizingEndDragLeft(self, x, y, keys, attachment)
+
+
+
+class ArrowHead(object):
+ def __init__(self, type = 0, end = 0, size = 0.0, dist = 0.0, name = "", mf = None, arrowId = -1):
+ if isinstance(type, ArrowHead):
+ pass
+ else:
+ self._arrowType = type
+ self._arrowEnd = end
+ self._arrowSize = size
+ self._xOffset = dist
+ self._yOffset = 0.0
+ self._spacing = 5.0
+
+ self._arrowName = name
+ self._metaFile = mf
+ self._id = arrowId
+ if self._id == -1:
+ self._id = wx.NewId()
+
+ def _GetType(self):
+ return self._arrowType
+
+ def GetPosition(self):
+ return self._arrowEnd
+
+ def SetPosition(self, pos):
+ self._arrowEnd = pos
+
+ def GetXOffset(self):
+ return self._xOffset
+
+ def GetYOffset(self):
+ return self._yOffset
+
+ def GetSpacing(self):
+ return self._spacing
+
+ def GetSize(self):
+ return self._arrowSize
+
+ def SetSize(self, size):
+ self._arrowSize = size
+ if self._arrowType == ARROW_METAFILE and self._metaFile:
+ oldWidth = self._metaFile._width
+ if oldWidth == 0:
+ return
+
+ scale = float(size) / oldWidth
+ if scale != 1:
+ self._metaFile.Scale(scale, scale)
+
+ def GetName(self):
+ return self._arrowName
+
+ def SetXOffset(self, x):
+ self._xOffset = x
+
+ def SetYOffset(self, y):
+ self._yOffset = y
+
+ def GetMetaFile(self):
+ return self._metaFile
+
+ def GetId(self):
+ return self._id
+
+ def GetArrowEnd(self):
+ return self._arrowEnd
+
+ def GetArrowSize(self):
+ return self._arrowSize
+
+ def SetSpacing(self, sp):
+ self._spacing = sp
+
+
+
+class LabelShape(RectangleShape):
+ def __init__(self, parent, region, w, h):
+ RectangleShape.__init__(self, w, h)
+ self._lineShape = parent
+ self._shapeRegion = region
+ self.SetPen(wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT))
+
+ def OnDraw(self, dc):
+ if self._lineShape and not self._lineShape.GetDrawHandles():
+ return
+
+ x1 = self._xpos - self._width / 2.0
+ y1 = self._ypos - self._height / 2.0
+
+ if self._pen:
+ if self._pen.GetWidth() == 0:
+ dc.SetPen(wx.Pen(wx.WHITE, 1, wx.TRANSPARENT))
+ else:
+ dc.SetPen(self._pen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ if self._cornerRadius > 0:
+ dc.DrawRoundedRectangle(x1, y1, self._width, self._height, self._cornerRadius)
+ else:
+ dc.DrawRectangle(x1, y1, self._width, self._height)
+
+ def OnDrawContents(self, dc):
+ pass
+
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ RectangleShape.OnDragLeft(self, draw, x, y, keys, attachment)
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ RectangleShape.OnBeginDragLeft(self, x, y, keys, attachment)
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ RectangleShape.OnEndDragLeft(self, x, y, keys, attachment)
+
+ def OnMovePre(self, dc, x, y, old_x, old_y, display):
+ return self._lineShape.OnLabelMovePre(dc, self, x, y, old_x, old_y, display)
+
+ # Divert left and right clicks to line object
+ def OnLeftClick(self, x, y, keys = 0, attachment = 0):
+ self._lineShape.GetEventHandler().OnLeftClick(x, y, keys, attachment)
+
+ def OnRightClick(self, x, y, keys = 0, attachment = 0):
+ self._lineShape.GetEventHandler().OnRightClick(x, y, keys, attachment)
+
+
+
+class LineShape(Shape):
+ """LineShape may be attached to two nodes;
+ it may be segmented, in which case a control point is drawn for each joint.
+
+ A wxLineShape may have arrows at the beginning, end and centre.
+
+ Derived from:
+ Shape
+ """
+ def __init__(self):
+ Shape.__init__(self)
+
+ self._sensitivity = OP_CLICK_LEFT | OP_CLICK_RIGHT
+ self._draggable = False
+ self._attachmentTo = 0
+ self._attachmentFrom = 0
+ self._from = None
+ self._to = None
+ self._erasing = False
+ self._arrowSpacing = 5.0
+ self._ignoreArrowOffsets = False
+ self._isSpline = False
+ self._maintainStraightLines = False
+ self._alignmentStart = 0
+ self._alignmentEnd = 0
+
+ self._lineControlPoints = None
+
+ # Clear any existing regions (created in an earlier constructor)
+ # and make the three line regions.
+ self.ClearRegions()
+ for name in ["Middle","Start","End"]:
+ newRegion = ShapeRegion()
+ newRegion.SetName(name)
+ newRegion.SetSize(150, 50)
+ self._regions.append(newRegion)
+
+ self._labelObjects = [None, None, None]
+ self._lineOrientations = []
+ self._lineControlPoints = []
+ self._arcArrows = []
+
+ def GetFrom(self):
+ """Return the 'from' object."""
+ return self._from
+
+ def GetTo(self):
+ """Return the 'to' object."""
+ return self._to
+
+ def GetAttachmentFrom(self):
+ """Return the attachment point on the 'from' node."""
+ return self._attachmentFrom
+
+ def GetAttachmentTo(self):
+ """Return the attachment point on the 'to' node."""
+ return self._attachmentTo
+
+ def GetLineControlPoints(self):
+ return self._lineControlPoints
+
+ def SetSpline(self, spline):
+ """Specifies whether a spline is to be drawn through the control points."""
+ self._isSpline = spline
+
+ def IsSpline(self):
+ """TRUE if a spline is drawn through the control points."""
+ return self._isSpline
+
+ def SetAttachmentFrom(self, attach):
+ """Set the 'from' shape attachment."""
+ self._attachmentFrom = attach
+
+ def SetAttachmentTo(self, attach):
+ """Set the 'to' shape attachment."""
+ self._attachmentTo = attach
+
+ # This is really to distinguish between lines and other images.
+ # For lines, want to pass drag to canvas, since lines tend to prevent
+ # dragging on a canvas (they get in the way.)
+ def Draggable(self):
+ return False
+
+ def SetIgnoreOffsets(self, ignore):
+ """Set whether to ignore offsets from the end of the line when drawing."""
+ self._ignoreArrowOffsets = ignore
+
+ def GetArrows(self):
+ return self._arcArrows
+
+ def GetAlignmentStart(self):
+ return self._alignmentStart
+
+ def GetAlignmentEnd(self):
+ return self._alignmentEnd
+
+ def IsEnd(self, nodeObject):
+ """TRUE if shape is at the end of the line."""
+ return self._to == nodeObject
+
+ def MakeLineControlPoints(self, n):
+ """Make a given number of control points (minimum of two)."""
+ self._lineControlPoints = []
+
+ for _ in range(n):
+ point = wx.RealPoint(-999, -999)
+ self._lineControlPoints.append(point)
+
+ # pi: added _initialised to keep track of when we have set
+ # the middle points to something other than (-999, -999)
+ self._initialised = False
+
+ def InsertLineControlPoint(self, dc = None, point = None):
+ """Insert a control point at an optional given position."""
+ if dc:
+ self.Erase(dc)
+
+ if point:
+ line_x, line_y = point
+ else:
+ last_point = self._lineControlPoints[-1]
+ second_last_point = self._lineControlPoints[-2]
+
+ line_x = (last_point[0] + second_last_point[0]) / 2.0
+ line_y = (last_point[1] + second_last_point[1]) / 2.0
+
+ point = wx.RealPoint(line_x, line_y)
+ self._lineControlPoints.insert(len(self._lineControlPoints)-1, point)
+
+ def DeleteLineControlPoint(self):
+ """Delete an arbitary point on the line."""
+ if len(self._lineControlPoints) < 3:
+ return False
+
+ del self._lineControlPoints[-2]
+ return True
+
+ def Initialise(self):
+ """Initialise the line object."""
+ if self._lineControlPoints:
+ # Just move the first and last control points
+ first_point = self._lineControlPoints[0]
+ last_point = self._lineControlPoints[-1]
+
+ # If any of the line points are at -999, we must
+ # initialize them by placing them half way between the first
+ # and the last.
+
+ for i in range(1,len(self._lineControlPoints)):
+ point = self._lineControlPoints[i]
+ if point[0] == -999:
+ if first_point[0] < last_point[0]:
+ x1 = first_point[0]
+ x2 = last_point[0]
+ else:
+ x2 = first_point[0]
+ x1 = last_point[0]
+ if first_point[1] < last_point[1]:
+ y1 = first_point[1]
+ y2 = last_point[1]
+ else:
+ y2 = first_point[1]
+ y1 = last_point[1]
+ self._lineControlPoints[i] = wx.RealPoint((x2 - x1) / 2.0 + x1, (y2 - y1) / 2.0 + y1)
+ self._initialised = True
+
+ def FormatText(self, dc, s, i):
+ """Format a text string according to the region size, adding
+ strings with positions to region text list.
+ """
+ self.ClearText(i)
+
+ if len(self._regions) == 0 or i >= len(self._regions):
+ return
+
+ region = self._regions[i]
+ region.SetText(s)
+ dc.SetFont(region.GetFont())
+
+ w, h = region.GetSize()
+ # Initialize the size if zero
+ if (w == 0 or h == 0) and s:
+ w, h = 100, 50
+ region.SetSize(w, h)
+
+ string_list = FormatText(dc, s, w - 5, h - 5, region.GetFormatMode())
+ for s in string_list:
+ line = ShapeTextLine(0.0, 0.0, s)
+ region.GetFormattedText().append(line)
+
+ actualW = w
+ actualH = h
+ if region.GetFormatMode() & FORMAT_SIZE_TO_CONTENTS:
+ actualW, actualH = GetCentredTextExtent(dc, region.GetFormattedText(), self._xpos, self._ypos, w, h)
+ if actualW != w or actualH != h:
+ xx, yy = self.GetLabelPosition(i)
+ self.EraseRegion(dc, region, xx, yy)
+ if len(self._labelObjects) < i:
+ self._labelObjects[i].Select(False, dc)
+ self._labelObjects[i].Erase(dc)
+ self._labelObjects[i].SetSize(actualW, actualH)
+
+ region.SetSize(actualW, actualH)
+
+ if len(self._labelObjects) < i:
+ self._labelObjects[i].Select(True, dc)
+ self._labelObjects[i].Draw(dc)
+
+ CentreText(dc, region.GetFormattedText(), self._xpos, self._ypos, actualW, actualH, region.GetFormatMode())
+ self._formatted = True
+
+ def DrawRegion(self, dc, region, x, y):
+ """Format one region at this position."""
+ if self.GetDisableLabel():
+ return
+
+ w, h = region.GetSize()
+
+ # Get offset from x, y
+ xx, yy = region.GetPosition()
+
+ xp = xx + x
+ yp = yy + y
+
+ # First, clear a rectangle for the text IF there is any
+ if len(region.GetFormattedText()):
+ dc.SetPen(self.GetBackgroundPen())
+ dc.SetBrush(self.GetBackgroundBrush())
+
+ # Now draw the text
+ if region.GetFont():
+ dc.SetFont(region.GetFont())
+ dc.DrawRectangle(xp - w / 2.0, yp - h / 2.0, w, h)
+
+ if self._pen:
+ dc.SetPen(self._pen)
+ dc.SetTextForeground(region.GetActualColourObject())
+
+ DrawFormattedText(dc, region.GetFormattedText(), xp, yp, w, h, region.GetFormatMode())
+
+ def EraseRegion(self, dc, region, x, y):
+ """Erase one region at this position."""
+ if self.GetDisableLabel():
+ return
+
+ w, h = region.GetSize()
+
+ # Get offset from x, y
+ xx, yy = region.GetPosition()
+
+ xp = xx + x
+ yp = yy + y
+
+ if region.GetFormattedText():
+ dc.SetPen(self.GetBackgroundPen())
+ dc.SetBrush(self.GetBackgroundBrush())
+
+ dc.DrawRectangle(xp - w / 2.0, yp - h / 2.0, w, h)
+
+ def GetLabelPosition(self, position):
+ """Get the reference point for a label.
+
+ Region x and y are offsets from this.
+ position is 0 (middle), 1 (start), 2 (end).
+ """
+ if position == 0:
+ # Want to take the middle section for the label
+ half_way = int(len(self._lineControlPoints) / 2.0)
+
+ # Find middle of this line
+ point = self._lineControlPoints[half_way - 1]
+ next_point = self._lineControlPoints[half_way]
+
+ dx = next_point[0] - point[0]
+ dy = next_point[1] - point[1]
+
+ return point[0] + dx / 2.0, point[1] + dy / 2.0
+ elif position == 1:
+ return self._lineControlPoints[0][0], self._lineControlPoints[0][1]
+ elif position == 2:
+ return self._lineControlPoints[-1][0], self._lineControlPoints[-1][1]
+
+ def Straighten(self, dc = None):
+ """Straighten verticals and horizontals."""
+ if len(self._lineControlPoints) < 3:
+ return
+
+ if dc:
+ self.Erase(dc)
+
+ GraphicsStraightenLine(self._lineControlPoints[-1], self._lineControlPoints[-2])
+
+ for i in range(len(self._lineControlPoints) - 2):
+ GraphicsStraightenLine(self._lineControlPoints[i], self._lineControlPoints[i + 1])
+
+ if dc:
+ self.Draw(dc)
+
+ def Unlink(self):
+ """Unlink the line from the nodes at either end."""
+ if self._to:
+ self._to.GetLines().remove(self)
+ if self._from:
+ self._from.GetLines().remove(self)
+ self._to = None
+ self._from = None
+ for i in range(3):
+ if self._labelObjects[i]:
+ self._labelObjects[i].Select(False)
+ self._labelObjects[i].RemoveFromCanvas(self._canvas)
+ self.ClearArrowsAtPosition(-1)
+
+ # Override Delete to unlink before deleting
+ def Delete(self):
+ self.Unlink()
+ Shape.Delete(self)
+
+ def SetEnds(self, x1, y1, x2, y2):
+ """Set the end positions of the line."""
+ self._lineControlPoints[0] = wx.RealPoint(x1, y1)
+ self._lineControlPoints[-1] = wx.RealPoint(x2, y2)
+
+ # Find centre point
+ self._xpos = (x1 + x2) / 2.0
+ self._ypos = (y1 + y2) / 2.0
+
+ # Get absolute positions of ends
+ def GetEnds(self):
+ """Get the visible endpoints of the lines for drawing between two objects."""
+ first_point = self._lineControlPoints[0]
+ last_point = self._lineControlPoints[-1]
+
+ return first_point[0], first_point[1], last_point[0], last_point[1]
+
+ def SetAttachments(self, from_attach, to_attach):
+ """Specify which object attachment points should be used at each end
+ of the line.
+ """
+ self._attachmentFrom = from_attach
+ self._attachmentTo = to_attach
+
+ def HitTest(self, x, y):
+ if not self._lineControlPoints:
+ return False
+
+ # Look at label regions in case mouse is over a label
+ inLabelRegion = False
+ for i in range(3):
+ if self._regions[i]:
+ region = self._regions[i]
+ if len(region._formattedText):
+ xp, yp = self.GetLabelPosition(i)
+ # Offset region from default label position
+ cx, cy = region.GetPosition()
+ cw, ch = region.GetSize()
+ cx += xp
+ cy += yp
+
+ rLeft = cx - cw / 2.0
+ rTop = cy - ch / 2.0
+ rRight = cx + cw / 2.0
+ rBottom = cy + ch / 2.0
+ if x > rLeft and x < rRight and y > rTop and y < rBottom:
+ inLabelRegion = True
+ break
+
+ for i in range(len(self._lineControlPoints) - 1):
+ point1 = self._lineControlPoints[i]
+ point2 = self._lineControlPoints[i + 1]
+
+ # For inaccurate mousing allow 8 pixel corridor
+ extra = 4
+
+ dx = point2[0] - point1[0]
+ dy = point2[1] - point1[1]
+
+ seg_len = math.sqrt(dx * dx + dy * dy)
+ if dy == 0 and dx == 0:
+ continue
+ distance_from_seg = seg_len * float((x - point1[0]) * dy - (y - point1[1]) * dx) / (dy * dy + dx * dx)
+ distance_from_prev = seg_len * float((y - point1[1]) * dy + (x - point1[0]) * dx) / (dy * dy + dx * dx)
+
+ if abs(distance_from_seg) < extra and distance_from_prev >= 0 and distance_from_prev <= seg_len or inLabelRegion:
+ return 0, distance_from_seg
+
+ return False
+
+ def DrawArrows(self, dc):
+ """Draw all arrows."""
+ # Distance along line of each arrow: space them out evenly
+ startArrowPos = 0.0
+ endArrowPos = 0.0
+ middleArrowPos = 0.0
+
+ for arrow in self._arcArrows:
+ ah = arrow.GetArrowEnd()
+ if ah == ARROW_POSITION_START:
+ if arrow.GetXOffset() and not self._ignoreArrowOffsets:
+ # If specified, x offset is proportional to line length
+ self.DrawArrow(dc, arrow, arrow.GetXOffset(), True)
+ else:
+ self.DrawArrow(dc, arrow, startArrowPos, False)
+ startArrowPos += arrow.GetSize() + arrow.GetSpacing()
+ elif ah == ARROW_POSITION_END:
+ if arrow.GetXOffset() and not self._ignoreArrowOffsets:
+ self.DrawArrow(dc, arrow, arrow.GetXOffset(), True)
+ else:
+ self.DrawArrow(dc, arrow, endArrowPos, False)
+ endArrowPos += arrow.GetSize() + arrow.GetSpacing()
+ elif ah == ARROW_POSITION_MIDDLE:
+ arrow.SetXOffset(middleArrowPos)
+ if arrow.GetXOffset() and not self._ignoreArrowOffsets:
+ self.DrawArrow(dc, arrow, arrow.GetXOffset(), True)
+ else:
+ self.DrawArrow(dc, arrow, middleArrowPos, False)
+ middleArrowPos += arrow.GetSize() + arrow.GetSpacing()
+
+ def DrawArrow(self, dc, arrow, XOffset, proportionalOffset):
+ """Draw the given arrowhead (or annotation)."""
+ first_line_point = self._lineControlPoints[0]
+ second_line_point = self._lineControlPoints[1]
+
+ last_line_point = self._lineControlPoints[-1]
+ second_last_line_point = self._lineControlPoints[-2]
+
+ # Position of start point of line, at the end of which we draw the arrow
+ startPositionX, startPositionY = 0.0, 0.0
+
+ ap = arrow.GetPosition()
+ if ap == ARROW_POSITION_START:
+ # If we're using a proportional offset, calculate just where this
+ # will be on the line.
+ realOffset = XOffset
+ if proportionalOffset:
+ totalLength = math.sqrt((second_line_point[0] - first_line_point[0]) * (second_line_point[0] - first_line_point[0]) + (second_line_point[1] - first_line_point[1]) * (second_line_point[1] - first_line_point[1]))
+ realOffset = XOffset * totalLength
+
+ positionOnLineX, positionOnLineY = GetPointOnLine(second_line_point[0], second_line_point[1], first_line_point[0], first_line_point[1], realOffset)
+
+ startPositionX = second_line_point[0]
+ startPositionY = second_line_point[1]
+ elif ap == ARROW_POSITION_END:
+ # If we're using a proportional offset, calculate just where this
+ # will be on the line.
+ realOffset = XOffset
+ if proportionalOffset:
+ totalLength = math.sqrt((second_last_line_point[0] - last_line_point[0]) * (second_last_line_point[0] - last_line_point[0]) + (second_last_line_point[1] - last_line_point[1]) * (second_last_line_point[1] - last_line_point[1]));
+ realOffset = XOffset * totalLength
+
+ positionOnLineX, positionOnLineY = GetPointOnLine(second_last_line_point[0], second_last_line_point[1], last_line_point[0], last_line_point[1], realOffset)
+
+ startPositionX = second_last_line_point[0]
+ startPositionY = second_last_line_point[1]
+ elif ap == ARROW_POSITION_MIDDLE:
+ # Choose a point half way between the last and penultimate points
+ x = (last_line_point[0] + second_last_line_point[0]) / 2.0
+ y = (last_line_point[1] + second_last_line_point[1]) / 2.0
+
+ # If we're using a proportional offset, calculate just where this
+ # will be on the line.
+ realOffset = XOffset
+ if proportionalOffset:
+ totalLength = math.sqrt((second_last_line_point[0] - x) * (second_last_line_point[0] - x) + (second_last_line_point[1] - y) * (second_last_line_point[1] - y));
+ realOffset = XOffset * totalLength
+
+ positionOnLineX, positionOnLineY = GetPointOnLine(second_last_line_point[0], second_last_line_point[1], x, y, realOffset)
+ startPositionX = second_last_line_point[0]
+ startPositionY = second_last_line_point[1]
+
+ # Add yOffset to arrow, if any
+
+ # The translation that the y offset may give
+ deltaX = 0.0
+ deltaY = 0.0
+ if arrow.GetYOffset and not self._ignoreArrowOffsets:
+ # |(x4, y4)
+ # |d
+ # |
+ # (x1, y1)--------------(x3, y3)------------------(x2, y2)
+ # x4 = x3 - d * math.sin(theta)
+ # y4 = y3 + d * math.cos(theta)
+ #
+ # Where theta = math.tan(-1) of (y3-y1) / (x3-x1)
+ x1 = startPositionX
+ y1 = startPositionY
+ x3 = float(positionOnLineX)
+ y3 = float(positionOnLineY)
+ d = -arrow.GetYOffset() # Negate so +offset is above line
+
+ if x3 == x1:
+ theta = math.pi / 2.0
+ else:
+ theta = math.atan((y3 - y1) / (x3 - x1))
+
+ x4 = x3 - d * math.sin(theta)
+ y4 = y3 + d * math.cos(theta)
+
+ deltaX = x4 - positionOnLineX
+ deltaY = y4 - positionOnLineY
+
+ at = arrow._GetType()
+ if at == ARROW_ARROW:
+ arrowLength = arrow.GetSize()
+ arrowWidth = arrowLength / 3.0
+
+ tip_x, tip_y, side1_x, side1_y, side2_x, side2_y = GetArrowPoints(startPositionX + deltaX, startPositionY + deltaY, positionOnLineX + deltaX, positionOnLineY + deltaY, arrowLength, arrowWidth)
+
+ points = [[tip_x, tip_y],
+ [side1_x, side1_y],
+ [side2_x, side2_y],
+ [tip_x, tip_y]]
+
+ dc.SetPen(self._pen)
+ dc.SetBrush(self._brush)
+ dc.DrawPolygon(points)
+ elif at in [ARROW_HOLLOW_CIRCLE, ARROW_FILLED_CIRCLE]:
+ # Find point on line of centre of circle, which is a radius away
+ # from the end position
+ diameter = arrow.GetSize()
+ x, y = GetPointOnLine(startPositionX + deltaX, startPositionY + deltaY,
+ positionOnLineX + deltaX, positionOnLineY + deltaY,
+ diameter / 2.0)
+ x1 = x - diameter / 2.0
+ y1 = y - diameter / 2.0
+ dc.SetPen(self._pen)
+ if arrow._GetType() == ARROW_HOLLOW_CIRCLE:
+ dc.SetBrush(self.GetBackgroundBrush())
+ else:
+ dc.SetBrush(self._brush)
+
+ dc.DrawEllipse(x1, y1, diameter, diameter)
+ elif at == ARROW_SINGLE_OBLIQUE:
+ pass
+ elif at == ARROW_METAFILE:
+ if arrow.GetMetaFile():
+ # Find point on line of centre of object, which is a half-width away
+ # from the end position
+ #
+ # width
+ # <-- start pos <-----><-- positionOnLineX
+ # _____
+ # --------------| x | <-- e.g. rectangular arrowhead
+ # -----
+ #
+ x, y = GetPointOnLine(startPositionX, startPositionY,
+ positionOnLineX, positionOnLineY,
+ arrow.GetMetaFile()._width / 2.0)
+ # Calculate theta for rotating the metafile.
+ #
+ # |
+ # | o(x2, y2) 'o' represents the arrowhead.
+ # | /
+ # | /
+ # | /theta
+ # | /(x1, y1)
+ # |______________________
+ #
+ theta = 0.0
+ x1 = startPositionX
+ y1 = startPositionY
+ x2 = float(positionOnLineX)
+ y2 = float(positionOnLineY)
+
+ if x1 == x2 and y1 == y2:
+ theta = 0.0
+ elif x1 == x2 and y1 > y2:
+ theta = 3.0 * math.pi / 2.0
+ elif x1 == x2 and y2 > y1:
+ theta = math.pi / 2.0
+ elif x2 > x1 and y2 >= y1:
+ theta = math.atan((y2 - y1) / (x2 - x1))
+ elif x2 < x1:
+ theta = math.pi + math.atan((y2 - y1) / (x2 - x1))
+ elif x2 > x1 and y2 < y1:
+ theta = 2 * math.pi + math.atan((y2 - y1) / (x2 - x1))
+ else:
+ raise Exception, "Unknown arrowhead rotation case"
+
+ # Rotate about the centre of the object, then place
+ # the object on the line.
+ if arrow.GetMetaFile().GetRotateable():
+ arrow.GetMetaFile().Rotate(0.0, 0.0, theta)
+
+ if self._erasing:
+ # If erasing, just draw a rectangle
+ minX, minY, maxX, maxY = arrow.GetMetaFile().GetBounds()
+ # Make erasing rectangle slightly bigger or you get droppings
+ extraPixels = 4
+ dc.DrawRectangle(deltaX + x + minX - extraPixels / 2.0, deltaY + y + minY - extraPixels / 2.0, maxX - minX + extraPixels, maxY - minY + extraPixels)
+ else:
+ arrow.GetMetaFile().Draw(dc, x + deltaX, y + deltaY)
+
+ def OnErase(self, dc):
+ old_pen = self._pen
+ old_brush = self._brush
+
+ bg_pen = self.GetBackgroundPen()
+ bg_brush = self.GetBackgroundBrush()
+ self.SetPen(bg_pen)
+ self.SetBrush(bg_brush)
+
+ bound_x, bound_y = self.GetBoundingBoxMax()
+ if self._font:
+ dc.SetFont(self._font)
+
+ # Undraw text regions
+ for i in range(3):
+ if self._regions[i]:
+ x, y = self.GetLabelPosition(i)
+ self.EraseRegion(dc, self._regions[i], x, y)
+
+ # Undraw line
+ dc.SetPen(self.GetBackgroundPen())
+ dc.SetBrush(self.GetBackgroundBrush())
+
+ # Drawing over the line only seems to work if the line has a thickness
+ # of 1.
+ if old_pen and old_pen.GetWidth() > 1:
+ dc.DrawRectangle(self._xpos - bound_x / 2.0 - 2, self._ypos - bound_y / 2.0 - 2,
+ bound_x + 4, bound_y + 4)
+ else:
+ self._erasing = True
+ self.GetEventHandler().OnDraw(dc)
+ self.GetEventHandler().OnEraseControlPoints(dc)
+ self._erasing = False
+
+ if old_pen:
+ self.SetPen(old_pen)
+ if old_brush:
+ self.SetBrush(old_brush)
+
+ def GetBoundingBoxMin(self):
+ x1, y1 = 10000, 10000
+ x2, y2 = -10000, -10000
+
+ for point in self._lineControlPoints:
+ if point[0] < x1:
+ x1 = point[0]
+ if point[1] < y1:
+ y1 = point[1]
+ if point[0] > x2:
+ x2 = point[0]
+ if point[1] > y2:
+ y2 = point[1]
+
+ return x2 - x1, y2 - y1
+
+ # For a node image of interest, finds the position of this arc
+ # amongst all the arcs which are attached to THIS SIDE of the node image,
+ # and the number of same.
+ def FindNth(self, image, incoming):
+ """Find the position of the line on the given object.
+
+ Specify whether incoming or outgoing lines are being considered
+ with incoming.
+ """
+ n = -1
+ num = 0
+
+ if image == self._to:
+ this_attachment = self._attachmentTo
+ else:
+ this_attachment = self._attachmentFrom
+
+ # Find number of lines going into / out of this particular attachment point
+ for line in image.GetLines():
+ if line._from == image:
+ # This is the nth line attached to 'image'
+ if line == self and not incoming:
+ n = num
+
+ # Increment num count if this is the same side (attachment number)
+ if line._attachmentFrom == this_attachment:
+ num += 1
+
+ if line._to == image:
+ # This is the nth line attached to 'image'
+ if line == self and incoming:
+ n = num
+
+ # Increment num count if this is the same side (attachment number)
+ if line._attachmentTo == this_attachment:
+ num += 1
+
+ return n, num
+
+ def OnDrawOutline(self, dc, x, y, w, h):
+ old_pen = self._pen
+ old_brush = self._brush
+
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ self.SetPen(dottedPen)
+ self.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ self.GetEventHandler().OnDraw(dc)
+
+ if old_pen:
+ self.SetPen(old_pen)
+ else:
+ self.SetPen(None)
+ if old_brush:
+ self.SetBrush(old_brush)
+ else:
+ self.SetBrush(None)
+
+ def OnMovePre(self, dc, x, y, old_x, old_y, display = True):
+ x_offset = x - old_x
+ y_offset = y - old_y
+
+ if self._lineControlPoints and not (x_offset == 0 and y_offset == 0):
+ for point in self._lineControlPoints:
+ point[0] += x_offset
+ point[1] += y_offset
+
+ # Move temporary label rectangles if necessary
+ for i in range(3):
+ if self._labelObjects[i]:
+ self._labelObjects[i].Erase(dc)
+ xp, yp = self.GetLabelPosition(i)
+ if i < len(self._regions):
+ xr, yr = self._regions[i].GetPosition()
+ else:
+ xr, yr = 0, 0
+ self._labelObjects[i].Move(dc, xp + xr, yp + yr)
+ return True
+
+ def OnMoveLink(self, dc, moveControlPoints = True):
+ """Called when a connected object has moved, to move the link to
+ correct position
+ """
+ if not self._from or not self._to:
+ return
+
+ # Do each end - nothing in the middle. User has to move other points
+ # manually if necessary
+ end_x, end_y, other_end_x, other_end_y = self.FindLineEndPoints()
+
+ oldX, oldY = self._xpos, self._ypos
+
+ # pi: The first time we go through FindLineEndPoints we can't
+ # use the middle points (since they don't have sane values),
+ # so we just do what we do for a normal line. Then we call
+ # Initialise to set the middle points, and then FindLineEndPoints
+ # again, but this time (and from now on) we use the middle
+ # points to calculate the end points.
+ # This was buggy in the C++ version too.
+
+ self.SetEnds(end_x, end_y, other_end_x, other_end_y)
+
+ if len(self._lineControlPoints) > 2:
+ self.Initialise()
+
+ # Do a second time, because one may depend on the other
+ end_x, end_y, other_end_x, other_end_y = self.FindLineEndPoints()
+ self.SetEnds(end_x, end_y, other_end_x, other_end_y)
+
+ # Try to move control points with the arc
+ x_offset = self._xpos - oldX
+ y_offset = self._ypos - oldY
+
+ # Only move control points if it's a self link. And only works
+ # if attachment mode is ON
+ if self._from == self._to and self._from.GetAttachmentMode() != ATTACHMENT_MODE_NONE and moveControlPoints and self._lineControlPoints and not (x_offset == 0 and y_offset == 0):
+ for point in self._lineControlPoints[1:-1]:
+ point[0] += x_offset
+ point[1] += y_offset
+
+ self.Move(dc, self._xpos, self._ypos)
+
+ def FindLineEndPoints(self):
+ """Finds the x, y points at the two ends of the line.
+
+ This function can be used by e.g. line-routing routines to
+ get the actual points on the two node images where the lines will be
+ drawn to / from.
+ """
+ if not self._from or not self._to:
+ return
+
+ # Do each end - nothing in the middle. User has to move other points
+ # manually if necessary.
+ second_point = self._lineControlPoints[1]
+ second_last_point = self._lineControlPoints[-2]
+
+ # pi: If we have a segmented line and this is the first time,
+ # do this as a straight line.
+ if len(self._lineControlPoints) > 2 and self._initialised:
+ if self._from.GetAttachmentMode() != ATTACHMENT_MODE_NONE:
+ nth, no_arcs = self.FindNth(self._from, False) # Not incoming
+ end_x, end_y = self._from.GetAttachmentPosition(self._attachmentFrom, nth, no_arcs, self)
+ else:
+ end_x, end_y = self._from.GetPerimeterPoint(self._from.GetX(), self._from.GetY(), second_point[0], second_point[1])
+
+ if self._to.GetAttachmentMode() != ATTACHMENT_MODE_NONE:
+ nth, no_arch = self.FindNth(self._to, True) # Incoming
+ other_end_x, other_end_y = self._to.GetAttachmentPosition(self._attachmentTo, nth, no_arch, self)
+ else:
+ other_end_x, other_end_y = self._to.GetPerimeterPoint(self._to.GetX(), self._to.GetY(), second_last_point[0], second_last_point[1])
+ else:
+ fromX = self._from.GetX()
+ fromY = self._from.GetY()
+ toX = self._to.GetX()
+ toY = self._to.GetY()
+
+ if self._from.GetAttachmentMode() != ATTACHMENT_MODE_NONE:
+ nth, no_arcs = self.FindNth(self._from, False)
+ end_x, end_y = self._from.GetAttachmentPosition(self._attachmentFrom, nth, no_arcs, self)
+ fromX = end_x
+ fromY = end_y
+
+ if self._to.GetAttachmentMode() != ATTACHMENT_MODE_NONE:
+ nth, no_arcs = self.FindNth(self._to, True)
+ other_end_x, other_end_y = self._to.GetAttachmentPosition(self._attachmentTo, nth, no_arcs, self)
+ toX = other_end_x
+ toY = other_end_y
+
+ if self._from.GetAttachmentMode() == ATTACHMENT_MODE_NONE:
+ end_x, end_y = self._from.GetPerimeterPoint(self._from.GetX(), self._from.GetY(), toX, toY)
+
+ if self._to.GetAttachmentMode() == ATTACHMENT_MODE_NONE:
+ other_end_x, other_end_y = self._to.GetPerimeterPoint(self._to.GetX(), self._to.GetY(), fromX, fromY)
+
+ return end_x, end_y, other_end_x, other_end_y
+
+
+ def OnDraw(self, dc):
+ if not self._lineControlPoints:
+ return
+
+ if self._pen:
+ dc.SetPen(self._pen)
+ if self._brush:
+ dc.SetBrush(self._brush)
+
+ points = []
+ for point in self._lineControlPoints:
+ points.append(wx.Point(point[0], point[1]))
+
+ if self._isSpline:
+ dc.DrawSpline(points)
+ else:
+ dc.DrawLines(points)
+
+ if sys.platform[:3] == "win":
+ # For some reason, last point isn't drawn under Windows
+ pt = points[-1]
+ dc.DrawPoint(pt[0], pt[1])
+
+ # Problem with pen - if not a solid pen, does strange things
+ # to the arrowhead. So make (get) a new pen that's solid.
+ if self._pen and self._pen.GetStyle() != wx.SOLID:
+ solid_pen = wx.Pen(self._pen.GetColour(), 1, wx.SOLID)
+ if solid_pen:
+ dc.SetPen(solid_pen)
+
+ self.DrawArrows(dc)
+
+ def OnDrawControlPoints(self, dc):
+ if not self._drawHandles:
+ return
+
+ # Draw temporary label rectangles if necessary
+ for i in range(3):
+ if self._labelObjects[i]:
+ self._labelObjects[i].Draw(dc)
+
+ Shape.OnDrawControlPoints(self, dc)
+
+ def OnEraseControlPoints(self, dc):
+ # Erase temporary label rectangles if necessary
+
+ for i in range(3):
+ if self._labelObjects[i]:
+ self._labelObjects[i].Erase(dc)
+
+ Shape.OnEraseControlPoints(self, dc)
+
+ def OnDragLeft(self, draw, x, y, keys = 0, attachment = 0):
+ pass
+
+ def OnBeginDragLeft(self, x, y, keys = 0, attachment = 0):
+ pass
+
+ def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
+ pass
+
+ def OnDrawContents(self, dc):
+ if self.GetDisableLabel():
+ return
+
+ for i in range(3):
+ if self._regions[i]:
+ x, y = self.GetLabelPosition(i)
+ self.DrawRegion(dc, self._regions[i], x, y)
+
+ def SetTo(self, object):
+ """Set the 'to' object for the line."""
+ self._to = object
+
+ def SetFrom(self, object):
+ """Set the 'from' object for the line."""
+ self._from = object
+
+ def MakeControlPoints(self):
+ """Make handle control points."""
+ if self._canvas and self._lineControlPoints:
+ first = self._lineControlPoints[0]
+ last = self._lineControlPoints[-1]
+
+ control = LineControlPoint(self._canvas, self, CONTROL_POINT_SIZE, first[0], first[1], CONTROL_POINT_ENDPOINT_FROM)
+ control._point = first
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ for point in self._lineControlPoints[1:-1]:
+ control = LineControlPoint(self._canvas, self, CONTROL_POINT_SIZE, point[0], point[1], CONTROL_POINT_LINE)
+ control._point = point
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ control = LineControlPoint(self._canvas, self, CONTROL_POINT_SIZE, last[0], last[1], CONTROL_POINT_ENDPOINT_TO)
+ control._point = last
+ self._canvas.AddShape(control)
+ self._controlPoints.append(control)
+
+ def ResetControlPoints(self):
+ if self._canvas and self._lineControlPoints and self._controlPoints:
+ for i in range(min(len(self._controlPoints), len(self._lineControlPoints))):
+ point = self._lineControlPoints[i]
+ control = self._controlPoints[i]
+ control.SetX(point[0])
+ control.SetY(point[1])
+
+ # Override select, to create / delete temporary label-moving objects
+ def Select(self, select, dc = None):
+ Shape.Select(self, select, dc)
+ if select:
+ for i in range(3):
+ if self._regions[i]:
+ region = self._regions[i]
+ if region._formattedText:
+ w, h = region.GetSize()
+ x, y = region.GetPosition()
+ xx, yy = self.GetLabelPosition(i)
+
+ if self._labelObjects[i]:
+ self._labelObjects[i].Select(False)
+ self._labelObjects[i].RemoveFromCanvas(self._canvas)
+
+ self._labelObjects[i] = self.OnCreateLabelShape(self, region, w, h)
+ self._labelObjects[i].AddToCanvas(self._canvas)
+ self._labelObjects[i].Show(True)
+ if dc:
+ self._labelObjects[i].Move(dc, x + xx, y + yy)
+ self._labelObjects[i].Select(True, dc)
+ else:
+ for i in range(3):
+ if self._labelObjects[i]:
+ self._labelObjects[i].Select(False, dc)
+ self._labelObjects[i].Erase(dc)
+ self._labelObjects[i].RemoveFromCanvas(self._canvas)
+ self._labelObjects[i] = None
+
+ # Control points ('handles') redirect control to the actual shape, to
+ # make it easier to override sizing behaviour.
+ def OnSizingDragLeft(self, pt, draw, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ dc.SetLogicalFunction(OGLRBLF)
+
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ dc.SetPen(dottedPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ if pt._type == CONTROL_POINT_LINE:
+ x, y = self._canvas.Snap(x, y)
+
+ pt.SetX(x)
+ pt.SetY(y)
+ pt._point[0] = x
+ pt._point[1] = y
+
+ old_pen = self.GetPen()
+ old_brush = self.GetBrush()
+
+ self.SetPen(dottedPen)
+ self.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ self.GetEventHandler().OnMoveLink(dc, False)
+
+ self.SetPen(old_pen)
+ self.SetBrush(old_brush)
+
+ def OnSizingBeginDragLeft(self, pt, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ if pt._type == CONTROL_POINT_LINE:
+ pt._originalPos = pt._point
+ x, y = self._canvas.Snap(x, y)
+
+ self.Erase(dc)
+
+ # Redraw start and end objects because we've left holes
+ # when erasing the line
+ self.GetFrom().OnDraw(dc)
+ self.GetFrom().OnDrawContents(dc)
+ self.GetTo().OnDraw(dc)
+ self.GetTo().OnDrawContents(dc)
+
+ self.SetDisableLabel(True)
+ dc.SetLogicalFunction(OGLRBLF)
+
+ pt._xpos = x
+ pt._ypos = y
+ pt._point[0] = x
+ pt._point[1] = y
+
+ old_pen = self.GetPen()
+ old_brush = self.GetBrush()
+
+ dottedPen = wx.Pen(wx.Colour(0, 0, 0), 1, wx.DOT)
+ self.SetPen(dottedPen)
+ self.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ self.GetEventHandler().OnMoveLink(dc, False)
+
+ self.SetPen(old_pen)
+ self.SetBrush(old_brush)
+
+ if pt._type == CONTROL_POINT_ENDPOINT_FROM or pt._type == CONTROL_POINT_ENDPOINT_TO:
+ self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_BULLSEYE))
+ pt._oldCursor = wx.STANDARD_CURSOR
+
+ def OnSizingEndDragLeft(self, pt, x, y, keys = 0, attachment = 0):
+ dc = wx.ClientDC(self.GetCanvas())
+ self.GetCanvas().PrepareDC(dc)
+
+ self.SetDisableLabel(False)
+
+ if pt._type == CONTROL_POINT_LINE:
+ x, y = self._canvas.Snap(x, y)
+
+ rpt = wx.RealPoint(x, y)
+
+ # Move the control point back to where it was;
+ # MoveControlPoint will move it to the new position
+ # if it decides it wants. We only moved the position
+ # during user feedback so we could redraw the line
+ # as it changed shape.
+ pt._xpos = pt._originalPos[0]
+ pt._ypos = pt._originalPos[1]
+ pt._point[0] = pt._originalPos[0]
+ pt._point[1] = pt._originalPos[1]
+
+ self.OnMoveMiddleControlPoint(dc, pt, rpt)
+
+ if pt._type == CONTROL_POINT_ENDPOINT_FROM:
+ if pt._oldCursor:
+ self._canvas.SetCursor(pt._oldCursor)
+
+ if self.GetFrom():
+ self.GetFrom().MoveLineToNewAttachment(dc, self, x, y)
+
+ if pt._type == CONTROL_POINT_ENDPOINT_TO:
+ if pt._oldCursor:
+ self._canvas.SetCursor(pt._oldCursor)
+
+ if self.GetTo():
+ self.GetTo().MoveLineToNewAttachment(dc, self, x, y)
+
+ # This is called only when a non-end control point is moved
+ def OnMoveMiddleControlPoint(self, dc, lpt, pt):
+ lpt._xpos = pt[0]
+ lpt._ypos = pt[1]
+
+ lpt._point[0] = pt[0]
+ lpt._point[1] = pt[1]
+
+ self.GetEventHandler().OnMoveLink(dc)
+
+ return True
+
+ def AddArrow(self, type, end = ARROW_POSITION_END, size = 10.0, xOffset = 0.0, name = "", mf = None, arrowId = -1):
+ """Add an arrow (or annotation) to the line.
+
+ type may currently be one of:
+
+ ARROW_HOLLOW_CIRCLE
+ Hollow circle.
+ ARROW_FILLED_CIRCLE
+ Filled circle.
+ ARROW_ARROW
+ Conventional arrowhead.
+ ARROW_SINGLE_OBLIQUE
+ Single oblique stroke.
+ ARROW_DOUBLE_OBLIQUE
+ Double oblique stroke.
+ ARROW_DOUBLE_METAFILE
+ Custom arrowhead.
+
+ end may currently be one of:
+
+ ARROW_POSITION_END
+ Arrow appears at the end.
+ ARROW_POSITION_START
+ Arrow appears at the start.
+
+ arrowSize specifies the length of the arrow.
+
+ xOffset specifies the offset from the end of the line.
+
+ name specifies a name for the arrow.
+
+ mf can be a wxPseduoMetaFile, perhaps loaded from a simple Windows
+ metafile.
+
+ arrowId is the id for the arrow.
+ """
+ arrow = ArrowHead(type, end, size, xOffset, name, mf, arrowId)
+ self._arcArrows.append(arrow)
+ return arrow
+
+ # Add arrowhead at a particular position in the arrowhead list
+ def AddArrowOrdered(self, arrow, referenceList, end):
+ """Add an arrowhead in the position indicated by the reference list
+ of arrowheads, which contains all legal arrowheads for this line, in
+ the correct order. E.g.
+
+ Reference list: a b c d e
+ Current line list: a d
+
+ Add c, then line list is: a c d.
+
+ If no legal arrowhead position, return FALSE. Assume reference list
+ is for one end only, since it potentially defines the ordering for
+ any one of the 3 positions. So we don't check the reference list for
+ arrowhead position.
+ """
+ if not referenceList:
+ return False
+
+ targetName = arrow.GetName()
+
+ # First check whether we need to insert in front of list,
+ # because this arrowhead is the first in the reference
+ # list and should therefore be first in the current list.
+ refArrow = referenceList[0]
+ if refArrow.GetName() == targetName:
+ self._arcArrows.insert(0, arrow)
+ return True
+
+ i1 = i2 = 0
+ while i1 < len(referenceList) and i2 < len(self._arcArrows):
+ refArrow = referenceList[i1]
+ currArrow = self._arcArrows[i2]
+
+ # Matching: advance current arrow pointer
+ if currArrow.GetArrowEnd() == end and currArrow.GetName() == refArrow.GetName():
+ i2 += 1
+
+ # Check if we're at the correct position in the
+ # reference list
+ if targetName == refArrow.GetName():
+ if i2 < len(self._arcArrows):
+ self._arcArrows.insert(i2, arrow)
+ else:
+ self._arcArrows.append(arrow)
+ return True
+ i1 += 1
+
+ self._arcArrows.append(arrow)
+ return True
+
+ def ClearArrowsAtPosition(self, end):
+ """Delete the arrows at the specified position, or at any position
+ if position is -1.
+ """
+ if end == -1:
+ self._arcArrows = []
+ return
+
+ for arrow in self._arcArrows:
+ if arrow.GetArrowEnd() == end:
+ self._arcArrows.remove(arrow)
+
+ def ClearArrow(self, name):
+ """Delete the arrow with the given name."""
+ for arrow in self._arcArrows:
+ if arrow.GetName() == name:
+ self._arcArrows.remove(arrow)
+ return True
+ return False
+
+ def FindArrowHead(self, position, name):
+ """Find arrowhead by position and name.
+
+ if position is -1, matches any position.
+ """
+ for arrow in self._arcArrows:
+ if (position == -1 or position == arrow.GetArrowEnd()) and arrow.GetName() == name:
+ return arrow
+
+ return None
+
+ def FindArrowHeadId(self, arrowId):
+ """Find arrowhead by id."""
+ for arrow in self._arcArrows:
+ if arrowId == arrow.GetId():
+ return arrow
+
+ return None
+
+ def DeleteArrowHead(self, position, name):
+ """Delete arrowhead by position and name.
+
+ if position is -1, matches any position.
+ """
+ for arrow in self._arcArrows:
+ if (position == -1 or position == arrow.GetArrowEnd()) and arrow.GetName() == name:
+ self._arcArrows.remove(arrow)
+ return True
+ return False
+
+ def DeleteArrowHeadId(self, id):
+ """Delete arrowhead by id."""
+ for arrow in self._arcArrows:
+ if arrowId == arrow.GetId():
+ self._arcArrows.remove(arrow)
+ return True
+ return False
+
+ # Calculate the minimum width a line
+ # occupies, for the purposes of drawing lines in tools.
+ def FindMinimumWidth(self):
+ """Find the horizontal width for drawing a line with arrows in
+ minimum space. Assume arrows at end only.
+ """
+ minWidth = 0.0
+ for arrowHead in self._arcArrows:
+ minWidth += arrowHead.GetSize()
+ if arrowHead != self._arcArrows[-1]:
+ minWidth += arrowHead + GetSpacing
+
+ # We have ABSOLUTE minimum now. So
+ # scale it to give it reasonable aesthetics
+ # when drawing with line.
+ if minWidth > 0:
+ minWidth = minWidth * 1.4
+ else:
+ minWidth = 20.0
+
+ self.SetEnds(0.0, 0.0, minWidth, 0.0)
+ self.Initialise()
+
+ return minWidth
+
+ def FindLinePosition(self, x, y):
+ """Find which position we're talking about at this x, y.
+
+ Returns ARROW_POSITION_START, ARROW_POSITION_MIDDLE, ARROW_POSITION_END.
+ """
+ startX, startY, endX, endY = self.GetEnds()
+
+ # Find distances from centre, start and end. The smallest wins
+ centreDistance = math.sqrt((x - self._xpos) * (x - self._xpos) + (y - self._ypos) * (y - self._ypos))
+ startDistance = math.sqrt((x - startX) * (x - startX) + (y - startY) * (y - startY))
+ endDistance = math.sqrt((x - endX) * (x - endX) + (y - endY) * (y - endY))
+
+ if centreDistance < startDistance and centreDistance < endDistance:
+ return ARROW_POSITION_MIDDLE
+ elif startDistance < endDistance:
+ return ARROW_POSITION_START
+ else:
+ return ARROW_POSITION_END
+
+ def SetAlignmentOrientation(self, isEnd, isHoriz):
+ if isEnd:
+ if isHoriz and self._alignmentEnd & LINE_ALIGNMENT_HORIZ != LINE_ALIGNMENT_HORIZ:
+ self._alignmentEnd != LINE_ALIGNMENT_HORIZ
+ elif not isHoriz and self._alignmentEnd & LINE_ALIGNMENT_HORIZ == LINE_ALIGNMENT_HORIZ:
+ self._alignmentEnd -= LINE_ALIGNMENT_HORIZ
+ else:
+ if isHoriz and self._alignmentStart & LINE_ALIGNMENT_HORIZ != LINE_ALIGNMENT_HORIZ:
+ self._alignmentStart != LINE_ALIGNMENT_HORIZ
+ elif not isHoriz and self._alignmentStart & LINE_ALIGNMENT_HORIZ == LINE_ALIGNMENT_HORIZ:
+ self._alignmentStart -= LINE_ALIGNMENT_HORIZ
+
+ def SetAlignmentType(self, isEnd, alignType):
+ if isEnd:
+ if alignType == LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ if self._alignmentEnd & LINE_ALIGNMENT_TO_NEXT_HANDLE != LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ self._alignmentEnd |= LINE_ALIGNMENT_TO_NEXT_HANDLE
+ elif self._alignmentEnd & LINE_ALIGNMENT_TO_NEXT_HANDLE == LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ self._alignmentEnd -= LINE_ALIGNMENT_TO_NEXT_HANDLE
+ else:
+ if alignType == LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ if self._alignmentStart & LINE_ALIGNMENT_TO_NEXT_HANDLE != LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ self._alignmentStart |= LINE_ALIGNMENT_TO_NEXT_HANDLE
+ elif self._alignmentStart & LINE_ALIGNMENT_TO_NEXT_HANDLE == LINE_ALIGNMENT_TO_NEXT_HANDLE:
+ self._alignmentStart -= LINE_ALIGNMENT_TO_NEXT_HANDLE
+
+ def GetAlignmentOrientation(self, isEnd):
+ if isEnd:
+ return self._alignmentEnd & LINE_ALIGNMENT_HORIZ == LINE_ALIGNMENT_HORIZ
+ else:
+ return self._alignmentStart & LINE_ALIGNMENT_HORIZ == LINE_ALIGNMENT_HORIZ
+
+ def GetAlignmentType(self, isEnd):
+ if isEnd:
+ return self._alignmentEnd & LINE_ALIGNMENT_TO_NEXT_HANDLE
+ else:
+ return self._alignmentStart & LINE_ALIGNMENT_TO_NEXT_HANDLE
+
+ def GetNextControlPoint(self, shape):
+ """Find the next control point in the line after the start / end point,
+ depending on whether the shape is at the start or end.
+ """
+ n = len(self._lineControlPoints)
+ if self._to == shape:
+ # Must be END of line, so we want (n - 1)th control point.
+ # But indexing ends at n-1, so subtract 2.
+ nn = n - 2
+ else:
+ nn = 1
+ if nn < len(self._lineControlPoints):
+ return self._lineControlPoints[nn]
+ return None
+
+ def OnCreateLabelShape(self, parent, region, w, h):
+ return LabelShape(parent, region, w, h)
+
+
+ def OnLabelMovePre(self, dc, labelShape, x, y, old_x, old_y, display):
+ labelShape._shapeRegion.SetSize(labelShape.GetWidth(), labelShape.GetHeight())
+
+ # Find position in line's region list
+ i = self._regions.index(labelShape._shapeRegion)
+
+ xx, yy = self.GetLabelPosition(i)
+ # Set the region's offset, relative to the default position for
+ # each region.
+ labelShape._shapeRegion.SetPosition(x - xx, y - yy)
+ labelShape.SetX(x)
+ labelShape.SetY(y)
+
+ # Need to reformat to fit region
+ if labelShape._shapeRegion.GetText():
+ s = labelShape._shapeRegion.GetText()
+ labelShape.FormatText(dc, s, i)
+ self.DrawRegion(dc, labelShape._shapeRegion, xx, yy)
+ return True
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_oglmisc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_oglmisc.py
new file mode 100644
index 0000000..e29df42
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ogl/_oglmisc.py
@@ -0,0 +1,415 @@
+# -*- coding: utf-8 -*-
+#----------------------------------------------------------------------------
+# Name: oglmisc.py
+# Purpose: Miscellaneous OGL support functions
+#
+# Author: Pierre Hjälm (from C++ original by Julian Smart)
+#
+# Created: 2004-05-08
+# RCS-ID: $Id$
+# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+
+import math
+
+import wx
+
+# Control point types
+# Rectangle and most other shapes
+CONTROL_POINT_VERTICAL = 1
+CONTROL_POINT_HORIZONTAL = 2
+CONTROL_POINT_DIAGONAL = 3
+
+# Line
+CONTROL_POINT_ENDPOINT_TO = 4
+CONTROL_POINT_ENDPOINT_FROM = 5
+CONTROL_POINT_LINE = 6
+
+# Types of formatting: can be combined in a bit list
+FORMAT_NONE = 0 # Left justification
+FORMAT_CENTRE_HORIZ = 1 # Centre horizontally
+FORMAT_CENTRE_VERT = 2 # Centre vertically
+FORMAT_SIZE_TO_CONTENTS = 4 # Resize shape to contents
+
+# Attachment modes
+ATTACHMENT_MODE_NONE, ATTACHMENT_MODE_EDGE, ATTACHMENT_MODE_BRANCHING = 0, 1, 2
+
+# Shadow mode
+SHADOW_NONE, SHADOW_LEFT, SHADOW_RIGHT = 0, 1, 2
+
+OP_CLICK_LEFT, OP_CLICK_RIGHT, OP_DRAG_LEFT, OP_DRAG_RIGHT = 1, 2, 4, 8
+OP_ALL = OP_CLICK_LEFT | OP_CLICK_RIGHT | OP_DRAG_LEFT | OP_DRAG_RIGHT
+
+# Sub-modes for branching attachment mode
+BRANCHING_ATTACHMENT_NORMAL = 1
+BRANCHING_ATTACHMENT_BLOB = 2
+
+# logical function to use when drawing rubberband boxes, etc.
+OGLRBLF = wx.INVERT
+
+CONTROL_POINT_SIZE = 6
+
+# Types of arrowhead
+# (i) Built-in
+ARROW_HOLLOW_CIRCLE = 1
+ARROW_FILLED_CIRCLE = 2
+ARROW_ARROW = 3
+ARROW_SINGLE_OBLIQUE = 4
+ARROW_DOUBLE_OBLIQUE = 5
+# (ii) Custom
+ARROW_METAFILE = 20
+
+# Position of arrow on line
+ARROW_POSITION_START = 0
+ARROW_POSITION_END = 1
+ARROW_POSITION_MIDDLE = 2
+
+# Line alignment flags
+# Vertical by default
+LINE_ALIGNMENT_HORIZ = 1
+LINE_ALIGNMENT_VERT = 0
+LINE_ALIGNMENT_TO_NEXT_HANDLE = 2
+LINE_ALIGNMENT_NONE = 0
+
+
+
+# Format a string to a list of strings that fit in the given box.
+# Interpret %n and 10 or 13 as a new line.
+def FormatText(dc, text, width, height, formatMode):
+ i = 0
+ word = ""
+ word_list = []
+ end_word = False
+ new_line = False
+ while i < len(text):
+ if text[i] == "%":
+ i += 1
+ if i == len(text):
+ word += "%"
+ else:
+ if text[i] == "n":
+ new_line = True
+ end_word = True
+ i += 1
+ else:
+ word += "%" + text[i]
+ i += 1
+ elif text[i] in ["\012","\015"]:
+ new_line = True
+ end_word = True
+ i += 1
+ elif text[i] == " ":
+ end_word = True
+ i += 1
+ else:
+ word += text[i]
+ i += 1
+
+ if i == len(text):
+ end_word = True
+
+ if end_word:
+ word_list.append(word)
+ word = ""
+ end_word = False
+ if new_line:
+ word_list.append(None)
+ new_line = False
+
+ # Now, make a list of strings which can fit in the box
+ string_list = []
+ buffer = ""
+ for s in word_list:
+ oldBuffer = buffer
+ if s is None:
+ # FORCE NEW LINE
+ if len(buffer) > 0:
+ string_list.append(buffer)
+ buffer = ""
+ else:
+ if len(buffer):
+ buffer += " "
+ buffer += s
+ x, y = dc.GetTextExtent(buffer)
+
+ # Don't fit within the bounding box if we're fitting
+ # shape to contents
+ if (x > width) and not (formatMode & FORMAT_SIZE_TO_CONTENTS):
+ # Deal with first word being wider than box
+ if len(oldBuffer):
+ string_list.append(oldBuffer)
+ buffer = s
+ if len(buffer):
+ string_list.append(buffer)
+
+ return string_list
+
+
+
+def GetCentredTextExtent(dc, text_list, xpos = 0, ypos = 0, width = 0, height = 0):
+ if not text_list:
+ return 0, 0
+
+ max_width = 0
+ for line in text_list:
+ current_width, char_height = dc.GetTextExtent(line.GetText())
+ if current_width > max_width:
+ max_width = current_width
+
+ return max_width, len(text_list) * char_height
+
+
+
+def CentreText(dc, text_list, xpos, ypos, width, height, formatMode):
+ if not text_list:
+ return
+
+ # First, get maximum dimensions of box enclosing text
+ char_height = 0
+ max_width = 0
+ current_width = 0
+
+ # Store text extents for speed
+ widths = []
+ for line in text_list:
+ current_width, char_height = dc.GetTextExtent(line.GetText())
+ widths.append(current_width)
+ if current_width > max_width:
+ max_width = current_width
+
+ max_height = len(text_list) * char_height
+
+ if formatMode & FORMAT_CENTRE_VERT:
+ if max_height < height:
+ yoffset = ypos - height / 2.0 + (height - max_height) / 2.0
+ else:
+ yoffset = ypos - height / 2.0
+ yOffset = ypos
+ else:
+ yoffset = 0.0
+ yOffset = 0.0
+
+ if formatMode & FORMAT_CENTRE_HORIZ:
+ xoffset = xpos - width / 2.0
+ xOffset = xpos
+ else:
+ xoffset = 0.0
+ xOffset = 0.0
+
+ for i, line in enumerate(text_list):
+ if formatMode & FORMAT_CENTRE_HORIZ and widths[i] < width:
+ x = (width - widths[i]) / 2.0 + xoffset
+ else:
+ x = xoffset
+ y = i * char_height + yoffset
+
+ line.SetX(x - xOffset)
+ line.SetY(y - yOffset)
+
+
+
+def DrawFormattedText(dc, text_list, xpos, ypos, width, height, formatMode):
+ if formatMode & FORMAT_CENTRE_HORIZ:
+ xoffset = xpos
+ else:
+ xoffset = xpos - width / 2.0
+
+ if formatMode & FORMAT_CENTRE_VERT:
+ yoffset = ypos
+ else:
+ yoffset = ypos - height / 2.0
+
+ # +1 to allow for rounding errors
+ dc.SetClippingRegion(xpos - width / 2.0, ypos - height / 2.0, width + 1, height + 1)
+
+ for line in text_list:
+ dc.DrawText(line.GetText(), xoffset + line.GetX(), yoffset + line.GetY())
+
+ dc.DestroyClippingRegion()
+
+
+
+def RoughlyEqual(val1, val2, tol = 0.00001):
+ return val1 < (val2 + tol) and val1 > (val2 - tol) and \
+ val2 < (val1 + tol) and val2 > (val1 - tol)
+
+
+
+def FindEndForBox(width, height, x1, y1, x2, y2):
+ xvec = [x1 - width / 2.0, x1 - width / 2.0, x1 + width / 2.0, x1 + width / 2.0, x1 - width / 2.0]
+ yvec = [y1 - height / 2.0, y1 + height / 2.0, y1 + height / 2.0, y1 - height / 2.0, y1 - height / 2.0]
+
+ return FindEndForPolyline(xvec, yvec, x2, y2, x1, y1)
+
+
+
+def CheckLineIntersection(x1, y1, x2, y2, x3, y3, x4, y4):
+ denominator_term = (y4 - y3) * (x2 - x1) - (y2 - y1) * (x4 - x3)
+ numerator_term = (x3 - x1) * (y4 - y3) + (x4 - x3) * (y1 - y3)
+
+ length_ratio = 1.0
+ k_line = 1.0
+
+ # Check for parallel lines
+ if denominator_term < 0.005 and denominator_term > -0.005:
+ line_constant = -1.0
+ else:
+ line_constant = float(numerator_term) / denominator_term
+
+ # Check for intersection
+ if line_constant < 1.0 and line_constant > 0.0:
+ # Now must check that other line hits
+ if (y4 - y3) < 0.005 and (y4 - y3) > -0.005:
+ k_line = (x1 - x3 + line_constant * (x2 - x1)) / (x4 - x3)
+ else:
+ k_line = (y1 - y3 + line_constant * (y2 - y1)) / (y4 - y3)
+ if k_line >= 0 and k_line < 1:
+ length_ratio = line_constant
+ else:
+ k_line = 1
+
+ return length_ratio, k_line
+
+
+
+def FindEndForPolyline(xvec, yvec, x1, y1, x2, y2):
+ lastx = xvec[0]
+ lasty = yvec[0]
+
+ min_ratio = 1.0
+
+ for i in range(1, len(xvec)):
+ line_ratio, other_ratio = CheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i])
+ lastx = xvec[i]
+ lasty = yvec[i]
+
+ if line_ratio < min_ratio:
+ min_ratio = line_ratio
+
+ # Do last (implicit) line if last and first doubles are not identical
+ if not (xvec[0] == lastx and yvec[0] == lasty):
+ line_ratio, other_ratio = CheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[0], yvec[0])
+ if line_ratio < min_ratio:
+ min_ratio = line_ratio
+
+ return x1 + (x2 - x1) * min_ratio, y1 + (y2 - y1) * min_ratio
+
+
+
+def PolylineHitTest(xvec, yvec, x1, y1, x2, y2):
+ isAHit = False
+ lastx = xvec[0]
+ lasty = yvec[0]
+
+ min_ratio = 1.0
+
+ for i in range(1, len(xvec)):
+ line_ratio, other_ratio = CheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i])
+ if line_ratio != 1.0:
+ isAHit = True
+ lastx = xvec[i]
+ lasty = yvec[i]
+
+ if line_ratio < min_ratio:
+ min_ratio = line_ratio
+
+ # Do last (implicit) line if last and first doubles are not identical
+ if not (xvec[0] == lastx and yvec[0] == lasty):
+ line_ratio, other_ratio = CheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[0], yvec[0])
+ if line_ratio != 1.0:
+ isAHit = True
+
+ return isAHit
+
+
+
+def GraphicsStraightenLine(point1, point2):
+ dx = point2[0] - point1[0]
+ dy = point2[1] - point1[1]
+
+ if dx == 0:
+ return
+ elif abs(float(dy) / dx) > 1:
+ point2[0] = point1[0]
+ else:
+ point2[1] = point1[1]
+
+
+
+def GetPointOnLine(x1, y1, x2, y2, length):
+ l = math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
+ if l < 0.01:
+ l = 0.01
+
+ i_bar = (x2 - x1) / l
+ j_bar = (y2 - y1) / l
+
+ return -length * i_bar + x2, -length * j_bar + y2
+
+
+
+def GetArrowPoints(x1, y1, x2, y2, length, width):
+ l = math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
+
+ if l < 0.01:
+ l = 0.01
+
+ i_bar = (x2 - x1) / l
+ j_bar = (y2 - y1) / l
+
+ x3 = -length * i_bar + x2
+ y3 = -length * j_bar + y2
+
+ return x2, y2, width * -j_bar + x3, width * i_bar + y3, -width * -j_bar + x3, -width * i_bar + y3
+
+
+
+def DrawArcToEllipse(x1, y1, width1, height1, x2, y2, x3, y3):
+ a1 = width1 / 2.0
+ b1 = height1 / 2.0
+
+ # Check that x2 != x3
+ if abs(x2 - x3) < 0.05:
+ x4 = x2
+ if y3 > y2:
+ y4 = y1 - math.sqrt((b1 * b1 - (((x2 - x1) * (x2 - x1)) * (b1 * b1) / (a1 * a1))))
+ else:
+ y4 = y1 + math.sqrt((b1 * b1 - (((x2 - x1) * (x2 - x1)) * (b1 * b1) / (a1 * a1))))
+ return x4, y4
+
+ # Calculate the x and y coordinates of the point where arc intersects ellipse
+ A = (1 / (a1 * a1))
+ B = ((y3 - y2) * (y3 - y2)) / ((x3 - x2) * (x3 - x2) * b1 * b1)
+ C = (2 * (y3 - y2) * (y2 - y1)) / ((x3 - x2) * b1 * b1)
+ D = ((y2 - y1) * (y2 - y1)) / (b1 * b1)
+ E = (A + B)
+ F = (C - (2 * A * x1) - (2 * B * x2))
+ G = ((A * x1 * x1) + (B * x2 * x2) - (C * x2) + D - 1)
+ H = (float(y3 - y2) / (x3 - x2))
+ K = ((F * F) - (4 * E * G))
+
+ if K >= 0:
+ # In this case the line intersects the ellipse, so calculate intersection
+ if x2 >= x1:
+ ellipse1_x = ((F * -1) + math.sqrt(K)) / (2 * E)
+ ellipse1_y = ((H * (ellipse1_x - x2)) + y2)
+ else:
+ ellipse1_x = (((F * -1) - math.sqrt(K)) / (2 * E))
+ ellipse1_y = ((H * (ellipse1_x - x2)) + y2)
+ else:
+ # in this case, arc does not intersect ellipse, so just draw arc
+ ellipse1_x = x3
+ ellipse1_y = y3
+
+ return ellipse1_x, ellipse1_y
+
+
+
+def FindEndForCircle(radius, x1, y1, x2, y2):
+ H = math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
+
+ if H == 0:
+ return x1, y1
+ else:
+ return radius * (x2 - x1) / H + x1, radius * (y2 - y1) / H + y1
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/__init__.py
new file mode 100644
index 0000000..09020fb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/__init__.py
@@ -0,0 +1,68 @@
+# Name: __init__.py
+# Package: wx.lib.pdfviewer
+#
+# Purpose: A PDF file viewer
+#
+# Author: David Hughes dfh@forestfield.co.uk
+# Copyright: Forestfield Software Ltd
+# Licence: Same as wxPython host
+
+# History: Created 17 Aug 2009
+#
+#----------------------------------------------------------------------------
+"""
+wx.lib.pdfviewer
+
+The wx.lib.pdfviewer pdfViewer class is derived from wx.ScrolledWindow
+and can display and print PDF files. The whole file can be scrolled from
+end to end at whatever magnification (zoom-level) is specified.
+
+The viewer uses pyPdf to parse the pdf file so it is a requirement that
+this must be installed. The pyPdf home page is http://pybrary.net/pyPdf/
+and the library can also be downloaded from http://pypi.python.org/pypi/pyPdf/1.12
+
+There is an optional pdfButtonPanel class, derived from wx.lib.buttonpanel,
+that can be placed, for example, at the top of the scrolled viewer window,
+and which contains navigation and zoom controls. Alternatively you can drive
+the viewer from controls in your own application.
+
+Externally callable methods are: LoadFile, Save, Print, SetZoom, and GoPage
+
+viewer.LoadFile(pathname)
+ Reads and displays the specified PDF file
+
+viewer.Save()
+ Opens standard file dialog to specify save file name
+
+viewer.Print()
+ Opens print dialog to choose printing options
+
+viewer.SetZoom(zoomscale)
+ zoomscale: positive integer or floating zoom scale to render the file at
+ corresponding size where 1.0 is "actual" point size (1/72").
+ -1 fits page width and -2 fits page height into client area
+ Redisplays the current page(s) at the new size
+
+viewer.GoPage(pagenumber)
+ Displays specified page
+
+The viewer renders the pdf file content using Cairo if installed,
+otherwise wx.GraphicsContext is used. Printing is achieved by writing
+directly to a wx.PrintDC and using wx.Printer.
+
+Please note that pdfviewer is a far from complete implementation of the pdf
+specification and will probably fail to display any random file you supply.
+However it does seem to be OK with the sort of files produced by ReportLab that
+use Western languages. The biggest limitation is probably that it doesn't (yet?)
+support embedded fonts and will substitute one of the standard fonts instead.
+
+The icons used in pdfButtonbar are Free Icons by Axialis Software: http://www.axialis.com
+You can freely use them in any project or website, commercially or not.
+TERMS OF USE:
+You must keep the credits of the authors: "Axialis Team", even if you modify them.
+See ./bitmaps/ReadMe.txt for further details
+
+"""
+
+from viewer import pdfViewer
+from buttonpanel import pdfButtonPanel
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/bezier.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/bezier.py
new file mode 100644
index 0000000..6da6e89
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/bezier.py
@@ -0,0 +1,64 @@
+# Name: bezier.py
+# Package: wx.lib.pdfviewer
+#
+# Purpose: Compute Bezier curves for PDF rendered using wx.DC
+# Adapted from the original source code, see below.
+#
+# Author: David Hughes dfh@forestfield.co.uk
+# Copyright: Forestfield Software Ltd
+# Licence: Public domain
+
+# History: Created 17 Jun 2009
+#
+#----------------------------------------------------------------------------
+
+import wx
+from vec2d import *
+
+def calculate_bezier(p, steps = 30):
+ """
+ Calculate a bezier curve from 4 control points and return a
+ list of the resulting points.
+ Depends on the 2d vector class from http://www.pygame.org/wiki/2DVectorClass
+
+ 2007 Victor Blomqvist
+ Released to the Public Domain
+ The function uses the forward differencing algorithm described at
+ http://www.niksula.cs.hut.fi/~hkankaan/Homepages/bezierfast.html
+ """
+
+ t = 1.0 / steps
+ temp = t*t
+
+ f = p[0]
+ fd = 3 * (p[1] - p[0]) * t
+ fdd_per_2 = 3 * (p[0] - 2 * p[1] + p[2]) * temp
+ fddd_per_2 = 3 * (3 * (p[1] - p[2]) + p[3] - p[0]) * temp * t
+
+ fddd = fddd_per_2 + fddd_per_2
+ fdd = fdd_per_2 + fdd_per_2
+ fddd_per_6 = fddd_per_2 * (1.0 / 3)
+
+ points = []
+ for x in range(steps):
+ points.append(f)
+ f = f + fd + fdd_per_2 + fddd_per_6
+ fd = fd + fdd + fddd_per_2
+ fdd = fdd + fddd
+ fdd_per_2 = fdd_per_2 + fddd_per_2
+ points.append(f)
+ return points
+
+def compute_points(controlpoints, nsteps=30):
+ """ Input 4 control points as wxRealPoints and convert to vec2d instances.
+ compute the nsteps points on the resulting curve and return them
+ as a list of wxPoints """
+ controlvectors = []
+ for p in controlpoints:
+ controlvectors.append(vec2d(p.x, p.y))
+ pointvectors = calculate_bezier(controlvectors, nsteps)
+ curvepoints = []
+ for v in pointvectors:
+ curvepoints.append(wx.Point(v[0], v[1]))
+ return curvepoints
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/buttonpanel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/buttonpanel.py
new file mode 100644
index 0000000..e015191
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/buttonpanel.py
@@ -0,0 +1,211 @@
+# Name: buttonpanel.py
+# Package: wx.lib.pdfviewer
+#
+# Purpose: A button panel class for pdf viewer
+#
+# Author: David Hughes dfh@forestfield.co.uk
+# Copyright: Forestfield Software Ltd
+# Licence: Same as wxPython host
+
+# History: Created 26 Jun 2009
+#
+#----------------------------------------------------------------------------
+
+import sys, os, time
+
+import images
+import wx
+import wx.lib.agw.buttonpanel as bp
+
+class pdfButtonPanel(bp.ButtonPanel):
+ " Containing panel is completely occupied by a button panel "
+ def __init__(self, parent, id, pos, size, style):
+ "Panel for user to select pdf viewer actions"
+ self.viewer = None # reference to viewer is set by their common parent
+ self.numpages = None
+ bp.ButtonPanel.__init__(self, parent, id, "",
+ agwStyle=bp.BP_USE_GRADIENT, alignment=bp.BP_ALIGN_LEFT)
+ self.SetProperties()
+ self.CreateButtons()
+
+ def CreateButtons(self):
+ " Add buttons and controls"
+ self.pagelabel = wx.StaticText(self, -1, 'Page')
+ self.page = wx.TextCtrl(self, -1, size=(30, -1), style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER)
+ self.page.Bind(wx.EVT_KILL_FOCUS, self.OnPage)
+ self.Bind(wx.EVT_TEXT_ENTER, self.OnPage, self.page)
+ self.maxlabel = wx.StaticText(self, -1, ' ')
+ self.zoom = wx.ComboBox(self, -1, style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
+ self.comboval = (('Actual size', 1.0), ('Fit width', -1), ('Fit page', -2),
+ ('25%', 0.25), ('50%', 0.5), ('75%', 0.75), ('100%', 1.0),
+ ('125%', 1.25), ('150%', 1.5), ('200%', 2.0), ('400%', 4.0),
+ ('800%', 8.0), ('1000%', 10.0))
+ for item in self.comboval:
+ self.zoom.Append(item[0], item[1]) # string value and client data
+ self.Bind(wx.EVT_COMBOBOX, self.OnZoomSet, self.zoom)
+ self.Bind(wx.EVT_TEXT_ENTER, self.OnZoomSet, self.zoom)
+ self.zoom.Bind(wx.EVT_KILL_FOCUS, self.OnZoomSet)
+ panelitems = [
+ ('btn', images.PrintIt.GetBitmap(), wx.ITEM_NORMAL, "Print", self.OnPrint),
+ ('sep',),
+ ('btn', images.SaveIt.GetBitmap(), wx.ITEM_NORMAL, "Save", self.OnSave),
+ ('sep',),
+ ('btn', images.First.GetBitmap(), wx.ITEM_NORMAL, "First page", self.OnFirst),
+ ('btn', images.Prev.GetBitmap(), wx.ITEM_NORMAL, "Previous page", self.OnPrev),
+ ('btn', images.Next.GetBitmap(), wx.ITEM_NORMAL, "Next page", self.OnNext),
+ ('btn', images.Last.GetBitmap(), wx.ITEM_NORMAL, "Last page", self.OnLast),
+ ('Ctrl', self.pagelabel),
+ ('ctrl', self.page),
+ ('ctrl', self.maxlabel),
+ ('sep',),
+ ('btn', images.ZoomOut.GetBitmap(), wx.ITEM_NORMAL, "Zoom out", self.OnZoomOut),
+ ('btn', images.ZoomIn.GetBitmap(), wx.ITEM_NORMAL, "Zoom in", self.OnZoomIn),
+ ('ctrl', self.zoom),
+ ('btn', images.Width.GetBitmap(), wx.ITEM_NORMAL, "Fit page width", self.OnWidth),
+ ('btn', images.Height.GetBitmap(), wx.ITEM_NORMAL, "Fit page height", self.OnHeight),
+ ]
+
+ self.Freeze()
+ for item in panelitems:
+ if item[0].lower() == 'btn':
+ type, image, kind, popup, handler = item
+ btn = bp.ButtonInfo(self, wx.NewId(),image, kind=kind,
+ shortHelp=popup, longHelp='')
+ self.AddButton(btn)
+ self.Bind(wx.EVT_BUTTON, handler, id=btn.GetId())
+ elif item[0].lower() == 'sep':
+ self.AddSeparator()
+ elif item[0].lower() == 'space':
+ self.AddSpacer(item[1])
+ elif item[0].lower() == 'ctrl':
+ self.AddControl(item[1])
+ self.Thaw()
+ self.DoLayout()
+
+
+ def SetProperties(self):
+ " Setup the buttonpanel colours, borders etc."
+ bpArt = self.GetBPArt()
+ bpArt.SetGradientType(bp.BP_GRADIENT_VERTICAL)
+ bpArt.SetColor(bp.BP_GRADIENT_COLOUR_FROM, wx.Colour(119, 136, 153)) #light slate
+ bpArt.SetColor(bp.BP_GRADIENT_COLOUR_TO, wx.Colour(245, 245, 245)) # white smoke
+ bpArt.SetColor(bp.BP_BORDER_COLOUR, wx.Colour(119, 136, 153))
+ bpArt.SetColor(bp.BP_BUTTONTEXT_COLOUR, wx.Colour(0,0,0)) # not used
+ bpArt.SetColor(bp.BP_SEPARATOR_COLOUR,
+ bp.BrightenColour(wx.Colour(60, 11, 112), 0.85))
+ bpArt.SetColor(bp.BP_SELECTION_BRUSH_COLOUR, wx.Colour(225, 225, 255)) # used?
+ bpArt.SetColor(bp.BP_SELECTION_PEN_COLOUR,
+ wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION))
+
+ def Update(self, pagenum, numpages, zoomscale):
+ """ Called from viewer to initialize and update controls. In viewer,
+ page range is 0 to numpages-1. In button controls it is 1 to numpages
+ """
+ self.pageno = pagenum + 1
+ self.page.SetValue('%d' % self.pageno)
+ if numpages <> self.numpages:
+ self.maxlabel.SetLabel('of %d' % numpages)
+ self.numpages = numpages
+ self.percentzoom = zoomscale * 100
+ self.zoom.SetValue('%.0f%%' % self.percentzoom)
+ self.zoomtext = self.zoom.GetValue() # save last good value
+
+ def OnSave(self, event):
+ "Save PDF"
+ self.viewer.Save()
+
+ def OnPrint(self, event):
+ "Print PDF"
+ self.viewer.Print()
+
+ def OnFirst(self, event):
+ " Show first page of report"
+ if self.pageno > 1:
+ self.pageno = 1
+ self.ChangePage()
+
+ def OnPrev(self, event):
+ " Show previous page of report"
+ if self.pageno > 1:
+ self.pageno -= 1
+ self.ChangePage()
+
+ def OnNext(self, event):
+ " Show next page of report"
+ if self.pageno < self.numpages:
+ self.pageno += 1
+ self.ChangePage()
+
+ def OnLast(self, event):
+ " Show last page of report"
+ if self.pageno < self.numpages:
+ self.pageno = self.numpages
+ self.ChangePage()
+
+ def OnPage(self,event):
+ " Go to page if valid page number entered"
+ try:
+ newpage = int(self.page.GetValue())
+ if 1 <= newpage <= self.numpages:
+ if newpage <> self.pageno:
+ self.pageno = newpage
+ self.ChangePage()
+ except ValueError:
+ pass
+ if hasattr(self, 'pageno'):
+ self.page.SetValue('%d' % self.pageno)
+ else:
+ self.page.SetValue('')
+
+ def OnZoomOut(self, event):
+ "Decrease page magnification"
+ self.viewer.SetZoom(max(0.1, self.percentzoom*0.5/100.0))
+
+ def OnZoomIn(self, event):
+ "Increase page magnification"
+ self.viewer.SetZoom(min(self.percentzoom*2/100.0, 10))
+
+ def OnZoomSet(self, event):
+ " Process zoom combo-box event. Either a list selection or value entered"
+ MINZ = 0
+ MAXZ = 1000
+ newzoom_scale = None
+ num = self.zoom.GetSelection()
+ if num >= 0: # selection from list
+ newzoom_scale = self.zoom.GetClientData(num)
+ else: # combo text
+ astring = self.zoom.GetValue().strip().replace('%','') # ignore percent sign
+ try:
+ numvalue = float(astring)
+ if numvalue < MINZ or numvalue > MAXZ:
+ numvalue = None
+ except ValueError:
+ numvalue = None
+ if numvalue: # numeric value
+ newzoom_scale = numvalue/100.0
+ else: # valid text?
+ textvalue = self.zoom.GetValue()
+ for k in range(len(self.comboval)):
+ if textvalue.lower() == self.comboval[k][0].lower():
+ newzoom_scale = self.comboval[k][1]
+ break
+
+ if newzoom_scale:
+ self.viewer.SetZoom(newzoom_scale) # will send update to set zoomtext
+ else:
+ self.zoom.SetValue(self.zoomtext) # restore last good value
+ event.Skip()
+
+ def OnWidth(self, event):
+ "Fit display to page width"
+ self.viewer.SetZoom(-1)
+
+ def OnHeight(self, event):
+ "Fit display to page height"
+ self.viewer.SetZoom(-2)
+
+ def ChangePage(self):
+ " Update viewer and self.page control with new page number"
+ self.page.SetValue('%d' % self.pageno)
+ self.viewer.GoPage(self.pageno - 1)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/dcgraphics.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/dcgraphics.py
new file mode 100644
index 0000000..a50c79e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/dcgraphics.py
@@ -0,0 +1,353 @@
+# Name: dcgraphics.py
+# Package: wx.lib.pdfviewer
+#
+# Purpose: A wx.GraphicsContext-like API implemented using wx.DC
+# based on wx.lib.graphics by Robin Dunn
+#
+# Author: David Hughes dfh@forestfield.co.uk
+# Copyright: Forestfield Software Ltd
+# Licence: Same as wxPython host
+
+# History: 8 Aug 2009 - created
+# 12 Dec 2011 - amended DrawText
+#
+#----------------------------------------------------------------------------
+"""
+This module implements an API similar to wx.GraphicsContext and the
+related classes. The implementation is done using wx.DC
+
+Why do this? Neither wx.GraphicsContext not the Cairo-based
+GraphicsContext API provided by wx.lib.graphics can be written
+directly to a PrintDC. It can be done via an intermediate bitmap in
+a MemoryDC but transferring this to a PrintDC is an order of magnitude
+slower than writing directly.
+
+Why not just use wxPrintDC directly? There may be times when you do want
+to use wx.GraphicsContext for its displayed appearance and for its
+clean(er) API, so being able to use the same code for printing as well is nice.
+
+It started out with the intention of being a full implementation of the
+GraphicsContext API but so far only contains the sub-set required to render PDF.
+It also contains the co-ordinate twiddles for the PDF origin, which would need
+to be separated out if this was ever developed to be more general purpose.
+"""
+import copy
+from math import asin, pi
+import bezier
+import wx
+
+class dcGraphicsState:
+ """ Each instance holds the current graphics state. It can be
+ saved (pushed) and restored (popped) by the owning parent
+ """
+ def __init__ (self):
+ """ Creates an instance with default values """
+ self.Yoffset = 0.0
+ self.Xtrans = 0.0
+ self.Ytrans = 0.0
+ self.Xscale = 1.0
+ self.Yscale = 1.0
+ self.sinA = 0.0
+ self.cosA = 1.0
+ self.tanAlpha = 0.0
+ self.tanBeta = 0.0
+ self.rotDegrees = 0
+
+ def Ytop(self, y):
+ """ Return y co-ordinate wrt top of current page """
+ return self.Yoffset + y
+
+ def Translate(self, dx, dy):
+ """move the origin from the current point to (dx,dy) """
+ self.Xtrans += (dx * self.Xscale)
+ self.Ytrans += (dy * self.Yscale)
+
+ def Scale(self, sx, sy):
+ """scale the current co-ordinates """
+ self.Xscale *= sx
+ self.Yscale *= sy
+
+ def Rotate(self, cosA, sinA):
+ """ Compute the (text only) rotation angle
+ sinA is inverted to cancel the original inversion in
+ pdfviewer.drawfile that was introduced because of the difference
+ in y direction between pdf and GraphicsContext co-ordinates
+ """
+ self.cosA = cosA
+ self.sinA = sinA
+ self.rotDegrees += asin(-self.sinA) * 180 / pi
+
+ def Skew(self, tanAlpha, tanBeta):
+ self.tanAlpha = tanAlpha
+ self.tanBeta = tanBeta
+
+ def Get_x(self, x=0, y=0):
+ """ Return x co-ordinate using graphic states and transforms
+ Input x,y are current co-ords
+ """
+ return ((x*self.cosA*self.Xscale - y*self.sinA*self.Yscale) + self.Xtrans)
+
+ def Get_y(self, x=0, y=0):
+ """ Return y co-ordinate using graphic states and transforms
+ Input x,y are current co-ords
+ """
+ return self.Ytop((x*self.sinA*self.Xscale + y*self.cosA*self.Yscale) + self.Ytrans)
+
+ def Get_angle(self):
+ """ Return rotation angle in degrees """
+ return self.rotDegrees
+
+#----------------------------------------------------------------------------
+
+class dcGraphicsContext(object):
+
+ def __init__(self, context=None, yoffset=0, have_cairo=False):
+ """ The incoming co-ordinates have a bottom left origin with increasing
+ y downwards (so y values are all negative). The DC origin is top left
+ also with increasing y down. yoffset informs us of the page height.
+ wx.DC and wx.GraphicsContext fonts are too big in the ratio of pixels
+ per inch to points per inch. If screen rendering used Cairo, printed
+ fonts need to be scaled but if wx.GC was used, they are already scaled
+ """
+ self._context = context
+ self.gstate = dcGraphicsState()
+ self.saved_state = []
+ self.gstate.Yoffset = yoffset
+ self.fontscale = 1.0
+ if have_cairo and wx.PlatformInfo[1] == 'wxMSW':
+ self.fontscale = 72.0 / 96.0
+
+
+ @staticmethod
+ def Create(dc, yoffset, have_cairo):
+ """ The created pGraphicsContext instance uses the dc itself """
+ assert isinstance(dc, wx.DC)
+ return dcGraphicsContext(dc, yoffset, have_cairo)
+
+ def CreateMatrix(self, a=1.0, b=0, c=0, d=1.0, tx=0, ty=0):
+ """
+ Create a new matrix object.
+ """
+ m = dcGraphicsMatrix()
+ m.Set(a, b, c, d, tx, ty)
+ return m
+
+ def CreatePath(self):
+ """
+ Create a new path obejct.
+ """
+ return dcGraphicsPath(parent=self)
+
+ def PushState(self):
+ """
+ Makes a copy of the current state of the context and saves it
+ on an internal stack of saved states. The saved state will be
+ restored when PopState is called.
+ """
+ self.saved_state.append(copy.deepcopy(self.gstate))
+
+ def PopState(self):
+ """
+ Restore the most recently saved state which was saved with PushState.
+ """
+ self.gstate = self.saved_state.pop()
+
+ def Scale(self, xScale, yScale):
+ """
+ Sets the dc userscale factor
+ """
+ self._context.SetUserScale(xScale, yScale)
+
+ def ConcatTransform(self, matrix):
+ """
+ Modifies the current transformation matrix by applying matrix
+ as an additional transformation.
+ """
+ g = self.gstate
+ a, b, c, d, e, f = map(float, matrix.Get())
+ g.Translate(e, f)
+ if d == a and c == -b and b <> 0:
+ g.Rotate(a, b)
+ else:
+ g.Scale(a, d)
+ g.Skew(b,c)
+
+ def SetPen(self, pen):
+ """
+ Set the wx.Pen to be used for stroking lines in future drawing
+ operations.
+ """
+ self._context.SetPen(pen)
+
+ def SetBrush(self, brush):
+ """
+ Set the Brush to be used for filling shapes in future drawing
+ operations.
+ """
+ self._context.SetBrush(brush)
+
+ def SetFont(self, font, colour=None):
+ """
+ Sets the wx.Font to be used for drawing text.
+ Don't set the dc font yet as it may need to be scaled
+ """
+ self._font = font
+ if colour is not None:
+ self._context.SetTextForeground(colour)
+
+ def StrokePath(self, path):
+ """
+ Strokes the path (draws the lines) using the current pen.
+ """
+ raise NotImplementedError("TODO")
+
+
+ def FillPath(self, path, fillStyle=wx.ODDEVEN_RULE):
+ """
+ Fills the path using the current brush.
+ """
+ raise NotImplementedError("TODO")
+
+
+ def DrawPath(self, path, fillStyle=wx.ODDEVEN_RULE):
+ """
+ Draws the path using current pen and brush.
+ """
+ pathdict = {'SetPen': self._context.SetPen,
+ 'DrawLine': self._context.DrawLine,
+ 'DrawRectangle': self._context.DrawRectangle,
+ 'DrawSpline': self._context.DrawSpline}
+ for pathcmd, args, kwargs in path.commands:
+ pathdict[pathcmd](*args, **kwargs)
+ if path.allpoints:
+ self._context.DrawPolygon(path.allpoints, 0, 0, fillStyle)
+
+
+ def DrawText(self, text, x, y, backgroundBrush=None):
+ """
+ Set the dc font at the required size.
+ Ensure original font is not altered
+ Draw the text at (x,y) using the current font.
+ Ignore backgroundBrush
+ """
+ g = self.gstate
+ orgsize = self._font.GetPointSize()
+ newsize = orgsize * (g.Xscale * self.fontscale)
+
+ self._font.SetPointSize(newsize)
+ self._context.SetFont(self._font)
+ self._context.DrawRotatedText(text, g.Get_x(x, y), g.Get_y(x, y), g.Get_angle())
+ self._font.SetPointSize(orgsize)
+
+
+ def DrawBitmap(self, bmp, x, y, w=-1, h=-1):
+ """
+ Draw the bitmap at (x,y), ignoring w, h
+ """
+ g = self.gstate
+ self._context.DrawBitmap(bmp, g.Get_x(x, y), g.Get_y(x, y))
+
+#---------------------------------------------------------------------------
+
+class dcGraphicsMatrix(object):
+ """
+ A matrix holds an affine transformations, such as a scale,
+ rotation, shear, or a combination of these, and is used to convert
+ between different coordinante spaces.
+ """
+ def __init__(self):
+ self._matrix = ()
+
+
+ def Set(self, a=1.0, b=0.0, c=0.0, d=1.0, tx=0.0, ty=0.0):
+ """Set the componenets of the matrix by value, default values
+ are the identity matrix."""
+ self._matrix = (a, b, c, d, tx, ty)
+
+
+ def Get(self):
+ """Return the component values of the matrix as a tuple."""
+ return tuple(self._matrix)
+
+#---------------------------------------------------------------------------
+
+class dcGraphicsPath(object):
+ """
+ A GraphicsPath is a representaion of a geometric path, essentially
+ a collection of lines and curves. Paths can be used to define
+ areas to be stroked and filled on a GraphicsContext.
+ """
+ def __init__(self, parent=None):
+ """ A path is essentially an object that we use just for
+ collecting path moves, lines, and curves in order to apply
+ them to the real context using DrawPath
+ """
+ self.commands = []
+ self.allpoints = []
+ if parent:
+ self.gstate = parent.gstate
+ self.fillcolour = parent._context.GetBrush().GetColour()
+ self.isfilled = parent._context.GetBrush().GetStyle() <> wx.TRANSPARENT
+
+ def AddCurveToPoint(self, cx1, cy1, cx2, cy2, x, y):
+ """
+ Adds a cubic Bezier curve from the current point, using two
+ control points and an end point.
+ """
+ g = self.gstate
+ clist = []
+ clist.append(wx.RealPoint(self.xc, self.yc))
+ clist.append(wx.RealPoint(g.Get_x(cx1, cy1), g.Get_y(cx1, cy1)))
+ clist.append(wx.RealPoint(g.Get_x(cx2, cy2), g.Get_y(cx2, cy2)))
+ clist.append(wx.RealPoint(g.Get_x(x, y), g.Get_y(x, y)))
+ self.xc, self.yc = clist[-1]
+ plist = bezier.compute_points(clist, 64)
+ if self.isfilled:
+ self.allpoints.extend(plist)
+ else:
+ self.commands.append(['DrawSpline', (plist,), {}])
+
+ def AddLineToPoint(self, x, y):
+ """
+ Adds a straight line from the current point to (x,y)
+ """
+ x2 = self.gstate.Get_x(x, y)
+ y2 = self.gstate.Get_y(x, y)
+ if self.isfilled:
+ self.allpoints.extend([wx.Point(self.xc, self.yc), wx.Point(x2, y2)])
+ else:
+ self.commands.append(['DrawLine', (self.xc, self.yc, x2, y2), {}])
+ self.xc = x2
+ self.yc = y2
+
+ def AddRectangle(self, x, y, w, h):
+ """
+ Adds a new rectangle as a closed sub-path.
+ """
+ g = self.gstate
+ xr = g.Get_x(x, y)
+ yr = g.Get_y(x, y)
+ wr = w*g.Xscale*g.cosA - h*g.Yscale*g.sinA
+ hr = w*g.Xscale*g.sinA + h*g.Yscale*g.cosA
+ if round(wr) == 1 or round(hr) == 1: # draw thin rectangles as lines
+ self.commands.append(['SetPen', (wx.Pen(self.fillcolour, 1.0),), {}])
+ self.commands.append(['DrawLine', (xr, yr, xr+wr-1, yr+hr), {}])
+ else:
+ self.commands.append(['DrawRectangle', (xr, yr, wr, hr), {}])
+
+ def CloseSubpath(self):
+ """
+ Adds a line segment to the path from the current point to the
+ beginning of the current sub-path, and closes this sub-path.
+ """
+ if self.isfilled:
+ self.allpoints.extend([wx.Point(self.xc, self.yc), wx.Point(self.x0, self.y0)])
+
+ def MoveToPoint(self, x, y):
+ """
+ Begins a new sub-path at (x,y) by moving the "current point" there.
+ """
+ self.x0 = self.xc = self.gstate.Get_x(x, y)
+ self.y0 = self.yc = self.gstate.Get_y(x, y)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/images.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/images.py
new file mode 100644
index 0000000..5b95d7c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/images.py
@@ -0,0 +1,240 @@
+#----------------------------------------------------------------------
+# This file was generated by ./encode_bitmaps.py
+#
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+First = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACz0lEQVRIiX1WsUodQRQ9Z7ME"
+ "AoKJxC5EEgyKGk2RP7B8IA/Uwi+wsLS18g8srVKkCQGbZyFJG5tUIoSAIAQtAhaBBBuJmXtS"
+ "zNzZ2X1PF5a9b+bOnTtn7jn3ceHzwgcAM7jv0R2vuS3IOmMGwHBWk5wB8EaSSBIAJIkobJEe"
+ "VJJopCRBICzGp0UfWfSXCTCgHpntfVnHIMOnsMb24JJQS8phlX54pkVAdTZQCurf6G/Ddk0Q"
+ "ACg0UJSwlFB0IIg+TcBs09K4qYDozgscAUUBiaQWPF27khSPHHdUtiUtPl5U/1kfi+OLkkkK"
+ "aS59Jx5OaO3lmmQxhoKEgJZdUYTDQSP9eDBw7fkad9/sYn1qnXkuAJUqrr5YxaA3YG+qRwSA"
+ "oVgbQAQwQlRAkY9bQuFPiPOz47PYebuDpadLSFWd5zI8RYw6lVyuCkloVUi8H409GMPW6y1s"
+ "vNpAxSpXHUUPKi9PCE0VpQGmQVLMlZI20PyTeQ56A0w+moQTsiQmQmetJaIpbZBrvqxrr3UA"
+ "0+PTnjFKvvg6BbWydh7kO7irrj1OztRh6Z7AUGadOQEBVetiQqJ5iLaf4OLPBa7/XmPko7Qu"
+ "JHkI7cuucrAieHZKG5xcnWDl4wqOzo9Gb1Ak2P1WThInUGl7HUnS1fWVtj9ta/NwE5e/L0vt"
+ "koLaJC3syomhoEi0EMmEAEJRqCDQiXT84xj9933uf93Hbbil61QmWsyefg91xtowRJSD7wc4"
+ "/XmK81/nrbmbfzfY+7KHw2+HWJ5ebu6ro2GSwLl3cycQltoMTB1qpIDd0b2KDTJZhdOaRsDA"
+ "VPdJZtsdCgY2/EBbrpv+0Ei9ZalHnUgCmABjK6vcubqn6WbalfbirZNQJRZqiMlJX1QGyv5K"
+ "heT649ij6YCRyamJZzbGgM7GfORCVug+FIc6YP7DAKFGwFkXEplQqOSwlJc+DgcKaLKw4Ow/"
+ "oX1dfBQFFGsAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+Prev = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAB3RJTUUH2QYaCSkRaCYhigAA"
+ "AAlwSFlzAAALEgAACxIB0t1+/AAAAARnQU1BAACxjwv8YQUAAAMGSURBVHjadVYxS1xBEJ6Z"
+ "typYBIsgJBCr6BVJoekMSSXpBDGgpd39AVHzC8Ta2tLmilSmC5gycD8gkEOsxEA0hXAgRsyb"
+ "7OzO7Nt9d75j2dndmd2Zb7+ZPex86vQAoQPysW+oTT5qydSsIyIwMSBhGDN6ucKkK7L/DZwf"
+ "drzyYtgfmVEssZR9Y2+EQYX8XHNQGnvFoCMHBls/Lw646DizeSqL5qVXkEPighyC5bpGxbks"
+ "kYgsttI7Dfdxr1HPrbxHYl/pOjU6uddx3m8e9eMBhUfZHSR8IXo19i4qbGwqXRO/vK346mTS"
+ "wg5wKBQFHKTRjUISdeQOWmsCEaNenYQWwoseYYCBVHYqhx7TnLTF54uw9moN22vitPTkSLlB"
+ "Y1rVyAEGm/Nt9sksHHw4gOOPx7D0bKlYy+1EDhAlWLKQdVwwZGpiCraWtrj7pgvTE9N6KcAJ"
+ "LlKoCaNtYlGVsajheWKIyCsvV3Dn7Q7PzcxZ6kFd10HfwwGJYdSwTgQXMsG8BA0xY8j803nY"
+ "e7cHyy+W/RYMI5/aBoJUmuGSC7qPy+8gKFEMcdJNwu77Xdh8vQnhqsTwsQN0M4WmoXPojF6U"
+ "sGTB8gEf4PzmnId/h2xwWG8tqwKcUZMT9X1PgSEVRGoqvUSusYbezx6ufl5F30MNdcCUiNCa"
+ "JmNDZaU4KmUBswisdiiL2Nh1c3/D+/192Piywf3f/bERFF5rNNaTXLJ5HUqsC/mdkssS52x4"
+ "ht1vXdj+vo2Xt5dlBLnXZqv7UUoMTZJwCGGRNGns5dNfp7D+dR0OfxzC7b/bogZZ/cnrlTOe"
+ "20RKtCzMXJb1O76Do8ERnFycwMLMwmjtwuYJcBZOSrQqK9dVrOQ23y7XV/dXfP3nuizXunmQ"
+ "wUpFXoIzeRyvC732s5o/t/q5/PVR/Bq4qF2us3IOWe3KIbICxQaR0xeNyje2qEuQXrcEQwGF"
+ "yfYy1hlEJC9FFeEIL1dWixJc+rrZezvyzyO6MAJPOMDDMLC/IPb3Ixa6cpNiHbJ54IR/qlWN"
+ "PPgPVhphQTIBT3gAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+Next = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACtUlEQVRIiYWWPUtcQRSG33e9"
+ "ETGS2EQhWAnGhFik22I7F1KlDegPsPYP+AfEYn+ANnYBCz/QJmAVQqyy2Agq6QRBUiUgiMx5"
+ "U8zHnfvhZuByz9w5e2bOM2feWS59XfoCYBGjmp54LNqCrPbNABguC5KLAD5IEkkCgCQRmS0y"
+ "BpUkGilJEAjz8WneR+b9ZQIMKFpXO2rVPkgzCyvtGFwSCkkprEInrjQLqNoECkHj2/tb0y4I"
+ "AgCFEkWOJUdRQ+B9yoDJpoXvpgzRkxvYgiJDIqmCp253JPmU/YxKtqTeq55mxmcg57/LhTFX"
+ "+sNBMh9DToJDxe5QRMRBI2N6MHB5dplH/SOsvVnjBCb8mPNjcAAcGG267LcOhANlQielFNKN"
+ "FQDn05wcm8T6+3Xsf9xH/3U/jVX8Ql9OqR/HOjG98EEBU6yUVF1zz+c06A20s7yDhRcLHoUr"
+ "scFBoV9FFHHEd8QQDo4vsax1Z7vY+7THje4Gpp9NM8cVEdGRAZ+fIF912mRXzSA2ABjjmFbe"
+ "ruDk84lW362qo05jk2GQnFDAgCfrOhy7KCFJOuilYmp8ivMv51GokDljOOHpTEDwE4ys65Ym"
+ "CWc3Z9j8tonr39flhgeZoIhyAldOEIMnp5YJbv7cYOv7Fk5/nSbftgMW30WWVq4xpR2w3D/e"
+ "Y/vnNnaHu3h4fIhao0z8lMtJmiBWT2UP/CbRy5B0fHXMwY8B7v7epbEa64pcQ2H/rIao8ggY"
+ "3g5xcHGA89vzxliFda5bme3l2rUhEmTQ4cVh/JFKrn6sjiLJe24LKGhMiNINZbWUrUxZhqpc"
+ "17Akua5lAJgAY6UC/lchkhpY6k8Bl99AzSoKNa48UPJXuASDndgjQwTzupMu8zJgo0Iyvow+"
+ "FBs3YPrDAKGAw2UdSVuFZCut+kQcyNAkYcHlP13rmcgeVJ4HAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Last = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACwklEQVRIiX1WPUtcURA9s3lK"
+ "bAwoIbAkEEJEsxgSLEw6MWkEC/cn6H/wH2hjbSvEzljZahobUwSEEAgSCRIIa2NjEQMWuXNS"
+ "3HvnzX2764NlZ++dNzPnzNfK7KfZjwCmcdfDIR/NMkFtnCkAxXklItMAXpOkiAgAkKTAyRTJ"
+ "RklSVIQkQQg02heNOtSoTyWgQDUw2ruijkb6UWgtZ+MkUZE0s0w/cqTOIBsOmIzm76iv/XIl"
+ "EAAQoqbC0+KpaFAQdWqDJoumc6WjaGgCB1DhKCFZ0NOUWyQj5OiRJpNcbi+zfb8NhnjOkO4C"
+ "OTM+g+7TLucfzpMabTCQCCjkllCQ6RAVyfCgkIVHC3KweIDV56sywpF4F+Ld0pMlbLzdkLUX"
+ "a4IASHDvBggChEq0DFKCmysAIcIcuzeG9Zfr2H+/j7nJueLOqI1Rg4HxLsD0WhleOmCiKSYT"
+ "YtU19WCKu+92uflmExOjE3QFUL8bSIaSriolRJKiCMUqJUVpDQgAK89WuPh4UXp/evE8Iijf"
+ "1dRoTA6s5n1d51r3/ZGe8dFxdiY7ds5AGBLXB7FMFRha1wMQ5JFioyUF5qK2ngBRJjknyxJV"
+ "xF0/t/9ucXF9USY5pPEQXF8o0DJjzrgpDXBw8vsE3b0ujn8d1w5cgM3vysHyMybKjparv1fY"
+ "+ryFo59H8M3Yl4NyVqUqUpQ50DoHSuXe9z3Z/rKNm9sbf9eXA2dcagehAdPNktPLU+yc7uDs"
+ "6qzv7vDHIXrXPVxeX9b5aswwkpDOh85XEK/KIZU21MABNmR7OQek7YtvlagYRbahmpC1hkxF"
+ "Oa4btNi4Zl44gRYZorM6kry5mmiakTZHu/tUCH4Dsa+T0/CjN2T6TIWUZOMe9QaMnZyWuHVj"
+ "NJi70SC7sSJZRyh9G9D+MICoEHDepIRKCKVc5HWkpU6mA44aGyw4/w8M23JBubTHcwAAAABJ"
+ "RU5ErkJggg==")
+
+#----------------------------------------------------------------------
+PrintIt = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAADDUlEQVRIiZ2Wz2pUWRDGf9Xc"
+ "yAgRxkVDFsFGRARHISADbdCNvkCEPIAL8R3c+RZKnmBmp45usuyFzKySxRCT+GehkUQik0Fb"
+ "O9fuez4X554/99rJwgPNrXO6uk7VV9/9qu3S6qU/gAsct3TExwVbyLXOHODYKszsArAgSWZm"
+ "AJJkZLbMQlBJMmcmSQjD+fjmvI+c95cTOCimZntc1j7Ij1W4ZIfgkigkxbCqNyHTLKBaF6gO"
+ "Gp7e3/1oF4YBmEhQBFgWfl3geve6h8InQB3SEELY+sd1Bu8HwgW4PIQ4X0mCaEoDb83fYml+"
+ "ibo1hEvMLD7/2fubwdvBVKhw1BD5bJqw+CpCUJGtsPdPC5gfAZEMhMXS0kU2dmOAyK7IKvMs"
+ "MjMbV2OomizK4KJIXK4xdlBQgODBxgNW3642GVT7hP27T++Y0QwA42o8BSKXIEJopb9Cv9vP"
+ "Cdu222SOZ893nnP3r7uhCnDQqQ3DQfdE1/rdvqdVvXI730/zWZxftLmTc1hlRuVjFrEpgo46"
+ "MaO8scc3uXk2w0ysQE6+AnNmVDAshyb00xUA9qX8AhWxgk5sioOv5VdGkxE/uypVDEdD8pgF"
+ "FbHjTo790T69Uz3WPqzx7M2zJnuO0Kab526y2Fvk8+Fnym/lESzymOnlwUt6p3o8ff1U5aRk"
+ "6fwSBLYk7kRr8GbAo38fcfXMVW182EgvXbggsCjI7L3BPR7OPtSr/17Z/Wv3uTJ3RU+2ntjB"
+ "6CAFFzZ7YlbLl5dtMplw58872t7btp2DHaj89+mCDCIcHI4P2RxtJgiAG2dvUL/V8azoJBmr"
+ "JhXbe9utIRTkumpC5J2EXALi8YvH2h/u+8lSg3X6l9Pc/v12U67btqAwZxGiOKGc15bdT7uU"
+ "k1LLvy0nOaWWa1A5KW33/92AeZL6pGnYxZWLa4gFnETQ8TAWEwEsm1ZhJOZYNy9Ic2W9oMrl"
+ "NSuzttusiGrrbWXil6SeDKLwJjeyDhnVPwwlZ/ha8DFZO+v0hwFRULGVZR2Htsmag7wl09En"
+ "Y1u0U8e2vgN1UBiOxfpC0gAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+SaveIt = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAADAElEQVRIiZ1Wv09TURT+zuuj"
+ "JWmMOomOrQaDDCTGri7MQoh/RfkLmFmY2AqJA7MbDQODjP5IQ2JEJwiJSNKURBY1OLT0ns/h"
+ "/nwPJMabvPTc+84797vf+c65ldk3s68BTOOmwb886m2CWlpTAIqjXESmAcyRpIgIAJCkILEp"
+ "4oOSpKgISYIQqI0van2o1p9KQIH8WrQ3obZBrp5Co+2Dk0ROMoSlm3ikSUCWNqAL6n+tv161"
+ "c4EAgBD2aFO1Kczfm7cU2YAEIG5TOyfEvQk+JGXvdA9nF2eWLrUniRQ5dAsPFtB+2IZLB0gG"
+ "O52n696uZ3VsHmwWaMsTVCDJDJn/iEnQYKfzso9QAFOmiAIQ4tXhksyRjmT7dBsjMwoU+Xfe"
+ "H4RUsyqWHi2xVqmJUGxe1KuLyKOW7YIH1f/dx9rnNYzNGO5D+y4mEqKCCipoTbXQvNO06jEo"
+ "UaSRoqAKAI1bDfZe9DDWcSpeDyCIeSKbQK1SC6qjcfE8RW43cYsFirpfuxiZka27KISCiqpZ"
+ "FUuPLUUepKgrNLoNguaTE/Qv+lz7aClKdO+f4F9BBa37LTTuNizqJMlWpgq40o4tAWDzdlN6"
+ "L3u41Eub5EREbk4A4iiybcaDdEkOJyihC2Myn0SNtX+qA781DYMo7AYmbuBq4v9HqScVVaRJ"
+ "j7Go2D3uYvXdKoaXQ/oGliQS9Yk6V56vYPHJImgHCnGCihQxB5YiiogMfg0wHA3Zftq+Umgg"
+ "2HnfkcHPQfAXFcAkPUpLFEGBkx8nhSPTEMvPlq/NQedtp0hp4RKyvhkNQUPCADTk7vEutw62"
+ "vHTpZczAQdKLDH2JgiSVGqimWqnmohIo8jfU+od1Hn4/lPOLc4gRbvQ2IkVJoYmK7H/b9wFl"
+ "58tOuPH8CWTm1cwnEHNQEr6P+2sxCiDoOrkSU66DnV6xJA/yYnuN2fdKcOphym/wJ4JyQj+z"
+ "mIJtK9ld4gG1R+Q+DG08thXxPkIpo45/GEDkMDhKUIdLO1RjRF1UiPeJ8o12LPyjPzWYSc7N"
+ "KY0aAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Left = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACzUlEQVRIiZ1WPUsdURA9Z11B"
+ "7EMIgRQJxCJGEkgidoKFpWATK3+AKFgIgo1YiSAIr4hia5N/IKRRCSSFwSbVS5MukB+g+JE7"
+ "J8X9fk8tXLjs7N3ZuTNnZs4sR7+MfgYwgvsu3bEsyoKsZ88AGLotyREAbySJJAFAkohCFhmN"
+ "ShKNlCQIhHn7NK8j8/oyAQa0t3p7n9feSH8UluVoXBJaScmswkP0tDCongMUjMa717d+uSGI"
+ "CAdF0kgYQMtygIJTj6dII2gkXNBxQceBcKBMoAv7DmjuTKTVa3FkETvvd0Bj3ncBDufluJdk"
+ "Q4BIPtQKlhimgJVXK5p/Me8dMUDO68m8jiQP1y0QtRQBgbE6ioNIEWuv1zT3fI4pUgfBwGCQ"
+ "MRdlFYX3Psm5lpMngIBGDTbebmDm2UxdZAESSRVc6duimjxEliGCeecHMYjNd5uafjqNqroA"
+ "nH086y3mdPbuj13snu56exGiVCV+k0PNELY/bGvyyWRutNCAADCAAZG+0arGJNmgSXDFXmlT"
+ "UgQMN8PqTHQw/mi88rqUy+c+nVhZQZaFHITWVoPGewH0eVcauiuC1HwhyRDQlIk5vzrHwvEC"
+ "Tv6c4EGXALk62U1qjNA0l9eXWD5axuHvwwcdkJot3HMVWeaYG7vB6vGqLq4vMPtytsJ67NMY"
+ "nHOxSmLD5cqpuSpA5EA5ZW5xgPvnuH6yzoOfBwDBeIVoGQ5glOkCd7mwH/LQlLxRwhUoAVtf"
+ "t7B/uo8UhOV31XfWvzxdu36IYIIsh9z51tHVzRWWJpYgp5qLSrrulQW0od0ZlD2H9HCLTNz7"
+ "vofu3y7kFBspTbr0bTHxIvXECAATELklehInVwj56NcRZALFzD/VbO5fbdl5KEM25QopJlcP"
+ "lasgyEz1KCCK0ysN82wwdmMKucCXUYdi9WNQ/TBAaOHQ7YWkhKHwuoIi6UQ4UECTp0f3P4CK"
+ "ICuf1hoBAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Right = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACs0lEQVRIiZ2Wv0scQRTHv9+7"
+ "BU//gZSBELwEhaQIaS0sLNJYWlnGC1xlo2ChrSAIVwhXWySNljFYnEIkpDLEVJdA/gohgs77"
+ "ptiZ2ZndnGAGhns7vHv73uf9mOX86fwHAF3ctzRhW5AFWe3MABjGBckugJeSRJIAIElEIosM"
+ "RiWJRkoSBMJK+7RSR1bqywQYUPzT2/u8Lo00o7BKDsYloZAUzco/BE8Tg6q9QN5o+C31rSm3"
+ "CCLgoEgaCQNolexRkEYuPloEjYTzOs7rOBAOlAl0/twBrYmJtOamiP3X++g/74NGwHkcDuU2"
+ "5LLBI1IZaoYlhFlHBODts7fqsIO9yz0F1jBMQCQiVEmGxUosMqXnJUqSq91VbL3aIuVxueS/"
+ "Ca6iquXoSbM6wm9trcyuYIpT2L7YhjOXI1VAZBUiGLQ2u4Zet5cWbF2O1SZJy0+XMd2axsZo"
+ "Q7fuNhiPiEIE9IdsoYU223nTeTl9Ts+Xniyp0+5w/dM6buymbETfKy1YmUSZQjKjd6mn9ee6"
+ "zsLjBR28OdBMa6a0Y5Ccz4Fv7WokAA+KIMgEQVFwCP1TRhB3qN//WOe/z9E77uH6z3WW7AKu"
+ "yrjviQevk/EJNj9u4u7urlF5nHs/9w3CC5+LZheHl5vQVhtX764y40c/jrBzulOVaf6C70Vo"
+ "qpgDn3QYGAdaOYeCzZiDw8tD7o52YWbZuPZV2UQ0yXOK1RlKlMOvQww+D3J95XI5rp1iY1Rj"
+ "WFCYLYoRhQrG4GKg4ZdhOrarOZbKAgoaI6J4Q1l+QwVcktA/7uvs11lW1imWcOPVIwBMgLGB"
+ "J8UnCaOfo4gsVl2KqLYLuHS8JmF62V9/Sg0lo1zJgKxGPRJE4faKl3llMHRjDDnhy6BDMfsw"
+ "yD4YIBRwGNeRZJVTeZ1XSNBJLqIox4rG+C+fohr4fgXssAAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+Width = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAADeUlEQVRIiZWWT2gVVxTGf2cy"
+ "L5TEQDA2aUFINmKJjyiUtjQidGHblcsGQRBx1Y3BjRtFXIkLF4ILcRehWmtWQRfWUIpdJC5E"
+ "07hJUpAUJWmLpf5pCYS8ez8Xd+78y4vQgeGdmTnz3Xu+Od93njWnmz8Au3nXoS1OH2MhX7vn"
+ "Ac9Sama7gX2SZGYGIElGKZZZBJUk82aShDB8wDcfcuRDvrzAQ9p2t+/adQDZXIUv4gguiVRS"
+ "DqvsIu60BKjaAspA42/I95vj1DAAEwUVZVrKVNQoCDkFYB6bz+57lSja8gO2oaJEiaQKPfU4"
+ "kRRKDisqj1XEPR09Gn1/VHLhen//fnUn3eE9h+QDhpyEoxInJiPSYd4slpeVbCO9I0x+MWkH"
+ "PzwYnjk4NHjIbn11i+HeYcNjODBXetdhOExeJHlJWbmxA8wbx3cd59qBa+zs3lnpDgSDPYNc"
+ "//o6Rz86SuIT5IWcwBHOsBBJLC+7IXmpr9HH1c+v6uTwSaWWxg8d6HAi6x0aSUOnPjmlK19e"
+ "YXvndslJclW6rHm7OYfYhxAeG+0f5fzH57XjvR2F0Mxs5b8VFl8ugtCevj020DVQEeaLtRd2"
+ "+qfTzD6bDUIMWvnVmlPNOUl7U1LGh8c5tusYWev+78PLM/F4gsszl2m1WshrPsn4tk46Geoe"
+ "ssSSIIzsKMfl63Y5HUmHDfUO0aBhuKCLjv5v+r9FfLDR2uDes3v2av0lnw58RpqkeRlmZiv/"
+ "rvDwj4csv1qmq9Fl2zq35QsBrLt1u/DzBS7ev0ir1YrC/DPJv7oD7zw3Fr7nyN0jLL9erpQ/"
+ "83yG8R/HOXH3BI9WH1WePf3nKYdvHObm45tFJ7XrIrkgroW/Fxi7Paap36YKjxK50GIXSdLk"
+ "/KTGvhtj6a8ltRNsGkVV8RYvrW2s2Zn7Z3jw/IHOHjgbhRiNzt6sv9G56XM2vThd+E9hhBat"
+ "IsXVPKTmJXcW7/Bk9Qkj/SN56bO/z3Lpl0usvl6t5tc8TBI2PDE8h9hbBc4mVFsD22J6lRaQ"
+ "8nkxn5q3nKJ8QvnqhMIXJctTtesaLRW6JNJM+uAFYbFiJ3Fy1aup77Ru7aUzxZUnkFQCV8ng"
+ "VAbK85UNwdhZkXuKCZhGJefDvACMYslLzqdXeCaEmWzTBMz/MCBSHEt1SuSFyaqDvNhpNSfS"
+ "QYmawsqW3gIVgl7eufygTQAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+Height = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAADXklEQVRIiX1Wz2tcVRT+vjfP"
+ "dKE4jNhBI1kISogMxlQZQgKW/gtdtnQZaLclq5Z2kRYyJH9DtyXQLkSxopBBitK6KKmIDBmD"
+ "CxeGGLEEIWli7/lc3B/vvb6ZXri8M/eec+493z3fOcPOd50NANN41dCYaVEWZC+tGQDDdk5y"
+ "GsAnkkSSACBJREkWGZ1KEo2UJAiEef80ryPz+jIBBuQjbzvm1g00AAEv7EU9Civk6FwScknJ"
+ "rcKPeNN0a/Py1Y+uQhLWfllTcBq/Xt/qck4QACgUUJRhiVCcbZ/FxfcvAoAe7z3mwz8fep3C"
+ "YZJpYd2EbOxDWjHbE22szK4gYwaCuP3pbbRPtQEX4HDw01CVDcgkeQj8iUqyvJwpw+rcqloT"
+ "LUUIWxMtrXZXQVFwkMz7kJPCoUnOKCLCQSNjeCFkLn24hO7pLuMAAJLstrtYmlkiDIQD6Eq2"
+ "DoQDPUQlKEI0KdQzb53B5enLY+lx5eMrmHt7LkElV4cri+GFBQWY0Myb6n3WU4MND1cY5Wxr"
+ "sKG1z9fUfK3pbZ0kV4UrD7lLCIKBFCGTFt5d4OCfAQYYSBJnWjOYfGMSknRwfMAne08U7LA4"
+ "uagHwwfJlhaIJoCdLzpbkmbHkSam28r8Cs5/cB4AsLW3hUtfXUp7r7D7OYcBgdqj89oKTpCM"
+ "cBEuRGwsyoe/dbKFCogqDw0Dzr13DvPvzCdezJ6eTY879eYUri1eS3uP/niE/m/9VCYoojjA"
+ "lUIKzmXCYH+AW/O30DzVRMjONNqvt3GhcwEk8ezoGe78dKcGT/xWskiuINruv7u6+cPNlDWj"
+ "skiSbnx7Q7sHu1WSluQsEkNOnmiODLnMzd83ufHrBlgakWgAcPfpXfaHfcJKRHMFSf0BpbqR"
+ "SFIiyvqP6xj+PayRbLg/xHp/vbCz+pSETE5INSRB5NfkpOcnz7H8zbKO/jtKEB2eHGr5y2Uc"
+ "nxyPhKUCEY1IsFioIa4a8s7+Dnvf9wj42t7b7HHnr52RtUtSZT2XU3hxAcYawaJ87+k9LEwt"
+ "QBLub90vsq7Sm+szhyt3IKnkXKX2Jwi4/vX1Ys87VUxtCEUHRNENPZNDE09s9A4jG1NDPzw6"
+ "TB0u6lCsdcD0hwFCDoftlyGpsDE28uKmVZ0IB0rQFLzc/h/4UISz4M1LhAAAAABJRU5ErkJg"
+ "gg==")
+
+#----------------------------------------------------------------------
+ZoomIn = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAELklEQVRIiX1WTWhUVxg95817"
+ "GlON2ug0KRiJaJOQBEWarm0F46qLGqhIcZ1EkEYCulBcunAhCLrJSgraRaG0hSyiEXUlGcmk"
+ "Tn9MLTb+jEyiScAkxsx47+nivfvmzUQdeMz37vveufc75/t57Bjp+BFACz7003su62xBtmrN"
+ "ArCY9Em2ANgjSSQJAJJEJGyRDlSSaElJgkDYEJ829JEN/WUFWMB/52k/dOoQZHUUtmw7cEnw"
+ "JcWwim7cSROAqtpAEaj7D/3tatsnCAAUylQ4Wnau34nuhm41fdTEoini/tx9DD8d1uLbRToq"
+ "EoCxTRutW4GdI53ZWINoAw+eBlsHeWT7ERCMtQGAuZU5nc6c5p3nd5wWYSQWZQ3Kekyk0t+l"
+ "eyF8kqTgVNspROC4VbiFq4+uYmJ2Ag3rGtCwrgHd27pxb/oeni8+j7mONajUZNqjwjNCAC3Z"
+ "ur6Vh7cfBgCey53j8bvHsXnNZmZfZtkz0sOxmTEEXsCzn59FRAVhABrSUQMDwoCygpfcWRK6"
+ "G7tBELn5HK79ew0yQn9bP7rqu7BcWsaZu2dgrEFzXTP2btkLGAAm5FtG8X20ETxZhVkRLmhb"
+ "7TYBwPjLcfW19il3KAdJ6mvvU+7bnPKv8ni2+EwA0L65XTLld2UkmRBPRoIB/IgzQqFQS6Ul"
+ "AFD92nrezt8GDNTf2c9MIYPMdAYBAm1au4kAFDBgFL1gQYqxyK5WvCid5CLJzGQEAPs/3a/8"
+ "Ql6X71+GJI0VxnQpe0k9O3tQt6ZOAPDf/KN3njpiRDKRBrQMhbLkyJMRPl54jNqglkP7hti1"
+ "tQu7f9jNK39c4dG2ozz5xUm4tJ1ZfEGaUFgaEgYVIsMC7PipIwthTxyahF11uzT01RC3rNsC"
+ "SVoxK/Q9H77nw/UsSXq18orHfjuG8fx4ZR2UC3AilT6U7oVFQ6yFBWZfz2L40TA3BBvQVNeE"
+ "2qCWHj28tW+RX8hjY81GAkBNUMODnx3EX4U/8WT+KV0NuEKDRYHt19qzEHa70q5oXBZIIYX6"
+ "mnrQEvPL85ARLhy8gH3N++L+WDIlnPj1BEb/Ga1ugL+n0t+ke2HRKKuwKbhiCUOmjLD0ZolL"
+ "b5ZojKExBjce3mDr1hY0f7yDJOnRw4GWA3ww/YBTL6ZcVhIWBS8uiqgwqgtFRqueF0tFfP/L"
+ "AG4+vBlHEaQCDH45WBG9JHgyQpxeRgpTLFxzReTs5LNiqYiBnwc0Ojkat/rJ6Ukl0l6wQCr9"
+ "dbqXlo0JkakodV02OLriZ9G6NZbX/75OgpianeL5kfN8XXxdflco+DJOWAGWFd1wlehVE0wS"
+ "Sirh4s2L751+PkxyAkkJcCXGn5Lgsb+iIRjZ8cRDeQL6rpLjYV4GdHmtRF67UUrnQ7Hiw6Di"
+ "gwGCD4PJakqilK0c5OWTVvo4OpCgJp5/mPwf/ayV5rr3q+AAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+ZoomOut = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAEE0lEQVRIiX1WTUxUVxT+vjdv"
+ "Kj8FbcERmoCh0Q4ESBsT66ZNaE2EVY3tStO4hrgphkQXunbhwkTdsW2kJk2a1oQ0KERdNYEA"
+ "StpKbSkqENACqYLIDPd+Xbx737wZqpNM3nn3nXfuud/5vnMe24bavgOQxZt+es3feluQLVmz"
+ "ACymQ5JZAB9JEkkCgCQRCVukDypJtKQkQSBsFJ828pGN/GUFWCD832zflHUUZPspbMH2wSUh"
+ "lBSHlbvxmSYCqmQDuaD+Gvnb7XZIEAAoFKDwsOx7ex866zrVWNnInMnh/sp9DD4Z1NrWGj0U"
+ "iYCxTevWrcD2ofaJuAZugwCB+pr7eGLvCRCMawMAK5srOjd6jncX7vpaRCexKNSgUI/JVObr"
+ "TDeEPUkIzrachQuO24u3cW3mGiaXJ1FXXoe68jp0NnRibGkMC2sLMdZxDYprssT2n9snIHcC"
+ "S2arsrj+6XUR5IWpCxj4ayDOroxluPrJVR3ac4gz/87o6I2jlFVp1km4JoPkzpLQWd8Jgpha"
+ "ncLAnwOQcdkZYCO/gfO/nIexBk3VTThQewAw0TNZRb7u3r8TOsrFrGioaAAAjP8zrp7mHvS0"
+ "9CTJi7Zv2zC3NqfGqka0vtOqsbkxD4k8PSEUWOQW6Ba5nl8HANXsqOGd+TuAQSQot00aae3a"
+ "sYsAlGaaLpBgQYoxXF4rYUwzl8Xo01Ec23sMh987rCv3rmB0YTTJexzPHkf1W9UCgL9XZxRD"
+ "mMja60BWCGABWhImug49HuKjF49Qka5gf0c/D+4+iJRSrAwqebLlJM98fAaetk/XnpEm4jwN"
+ "CRMVFwaxzbbv2yIW2bjHYH/1fvV/3s/a8lpI0qbZZBiECIMQvmdJ0vPN5zx14xTG58eLdVAQ"
+ "4GQq81WmGxZ1cS0ssPxyGYMzg6xKV6GxuhEV6QoGDLBltzD/Yh47y3YSAMrSZez6oAu/Lf6K"
+ "x6tP6DXgKQuLRbYOtE5A+NBjVtS4LJBCCjVlNaAlVjdWISNc6rqEjqaOuD/mTR6nfzqN4T+G"
+ "SxvgvVTmy0w3LOplFTUF10fckSkjrL9a5/qrdRpjaIzBrYe32Lw7i6Z33ydJBgxwJHuED5Ye"
+ "cPbZrGclYbEYxKJwwigVSsySxPNcPodvfuzFyMOR+BTpVBp9n/UVnV4SAhlBRnLBFEk9WpNx"
+ "dHN28lkun0PvD70anh6OW/300rSnp/MFUpkvMt20rE8UmXLU9WzwcMXP3Lo1ljd/v0mCmF2e"
+ "5cWhi3yZe1l4V1gMZXxhBVgWdcNtRS+ZYJKQVx6XRy6/dvqFMMkJVFCsV6/rL0oGj/3lhqBX"
+ "sp94KEzA0Cs5HuaFgJ7XSvDatxV6H4pFHwZFHwwQQhhMl0LiKFs8yAuZFvt4OJCAJp5/mP4P"
+ "yFN2/NjDF0IAAAAASUVORK5CYII=")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/vec2d.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/vec2d.py
new file mode 100644
index 0000000..f505a64
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/vec2d.py
@@ -0,0 +1,468 @@
+# Name: vec2d.py
+# Package: wx.lib.pdfviewer
+#
+# Purpose: 2D vector class. Used for computing Bezier curves
+#
+# Author:
+# Copyright:
+# Licence: LGPL - from http://www.pygame.org/wiki/2DVectorClass
+
+# History: Created 17 Jun 2009
+#
+#----------------------------------------------------------------------------
+
+import operator
+import math
+
+class vec2d(object):
+ """2d vector class, supports vector and scalar operators,
+ and also provides a bunch of high level functions
+ """
+ __slots__ = ['x', 'y']
+
+ def __init__(self, x_or_pair, y = None):
+ if y == None:
+ self.x = x_or_pair[0]
+ self.y = x_or_pair[1]
+ else:
+ self.x = x_or_pair
+ self.y = y
+
+ def __len__(self):
+ return 2
+
+ def __getitem__(self, key):
+ if key == 0:
+ return self.x
+ elif key == 1:
+ return self.y
+ else:
+ raise IndexError("Invalid subscript "+str(key)+" to vec2d")
+
+ def __setitem__(self, key, value):
+ if key == 0:
+ self.x = value
+ elif key == 1:
+ self.y = value
+ else:
+ raise IndexError("Invalid subscript "+str(key)+" to vec2d")
+
+ # String representaion (for debugging)
+ def __repr__(self):
+ return 'vec2d(%s, %s)' % (self.x, self.y)
+
+ # Comparison
+ def __eq__(self, other):
+ if hasattr(other, "__getitem__") and len(other) == 2:
+ return self.x == other[0] and self.y == other[1]
+ else:
+ return False
+
+ def __ne__(self, other):
+ if hasattr(other, "__getitem__") and len(other) == 2:
+ return self.x != other[0] or self.y != other[1]
+ else:
+ return True
+
+ def __nonzero__(self):
+ return bool(self.x or self.y)
+
+ # Generic operator handlers
+ def _o2(self, other, f):
+ "Any two-operator operation where the left operand is a vec2d"
+ if isinstance(other, vec2d):
+ return vec2d(f(self.x, other.x),
+ f(self.y, other.y))
+ elif (hasattr(other, "__getitem__")):
+ return vec2d(f(self.x, other[0]),
+ f(self.y, other[1]))
+ else:
+ return vec2d(f(self.x, other),
+ f(self.y, other))
+
+ def _r_o2(self, other, f):
+ "Any two-operator operation where the right operand is a vec2d"
+ if (hasattr(other, "__getitem__")):
+ return vec2d(f(other[0], self.x),
+ f(other[1], self.y))
+ else:
+ return vec2d(f(other, self.x),
+ f(other, self.y))
+
+ def _io(self, other, f):
+ "inplace operator"
+ if (hasattr(other, "__getitem__")):
+ self.x = f(self.x, other[0])
+ self.y = f(self.y, other[1])
+ else:
+ self.x = f(self.x, other)
+ self.y = f(self.y, other)
+ return self
+
+ # Addition
+ def __add__(self, other):
+ if isinstance(other, vec2d):
+ return vec2d(self.x + other.x, self.y + other.y)
+ elif hasattr(other, "__getitem__"):
+ return vec2d(self.x + other[0], self.y + other[1])
+ else:
+ return vec2d(self.x + other, self.y + other)
+ __radd__ = __add__
+
+ def __iadd__(self, other):
+ if isinstance(other, vec2d):
+ self.x += other.x
+ self.y += other.y
+ elif hasattr(other, "__getitem__"):
+ self.x += other[0]
+ self.y += other[1]
+ else:
+ self.x += other
+ self.y += other
+ return self
+
+ # Subtraction
+ def __sub__(self, other):
+ if isinstance(other, vec2d):
+ return vec2d(self.x - other.x, self.y - other.y)
+ elif (hasattr(other, "__getitem__")):
+ return vec2d(self.x - other[0], self.y - other[1])
+ else:
+ return vec2d(self.x - other, self.y - other)
+ def __rsub__(self, other):
+ if isinstance(other, vec2d):
+ return vec2d(other.x - self.x, other.y - self.y)
+ if (hasattr(other, "__getitem__")):
+ return vec2d(other[0] - self.x, other[1] - self.y)
+ else:
+ return vec2d(other - self.x, other - self.y)
+ def __isub__(self, other):
+ if isinstance(other, vec2d):
+ self.x -= other.x
+ self.y -= other.y
+ elif (hasattr(other, "__getitem__")):
+ self.x -= other[0]
+ self.y -= other[1]
+ else:
+ self.x -= other
+ self.y -= other
+ return self
+
+ # Multiplication
+ def __mul__(self, other):
+ if isinstance(other, vec2d):
+ return vec2d(self.x*other.x, self.y*other.y)
+ if (hasattr(other, "__getitem__")):
+ return vec2d(self.x*other[0], self.y*other[1])
+ else:
+ return vec2d(self.x*other, self.y*other)
+ __rmul__ = __mul__
+
+ def __imul__(self, other):
+ if isinstance(other, vec2d):
+ self.x *= other.x
+ self.y *= other.y
+ elif (hasattr(other, "__getitem__")):
+ self.x *= other[0]
+ self.y *= other[1]
+ else:
+ self.x *= other
+ self.y *= other
+ return self
+
+ # Division
+ def __div__(self, other):
+ return self._o2(other, operator.div)
+ def __rdiv__(self, other):
+ return self._r_o2(other, operator.div)
+ def __idiv__(self, other):
+ return self._io(other, operator.div)
+
+ def __floordiv__(self, other):
+ return self._o2(other, operator.floordiv)
+ def __rfloordiv__(self, other):
+ return self._r_o2(other, operator.floordiv)
+ def __ifloordiv__(self, other):
+ return self._io(other, operator.floordiv)
+
+ def __truediv__(self, other):
+ return self._o2(other, operator.truediv)
+ def __rtruediv__(self, other):
+ return self._r_o2(other, operator.truediv)
+ def __itruediv__(self, other):
+ return self._io(other, operator.floordiv)
+
+ # Modulo
+ def __mod__(self, other):
+ return self._o2(other, operator.mod)
+ def __rmod__(self, other):
+ return self._r_o2(other, operator.mod)
+
+ def __divmod__(self, other):
+ return self._o2(other, operator.divmod)
+ def __rdivmod__(self, other):
+ return self._r_o2(other, operator.divmod)
+
+ # Exponentation
+ def __pow__(self, other):
+ return self._o2(other, operator.pow)
+ def __rpow__(self, other):
+ return self._r_o2(other, operator.pow)
+
+ # Bitwise operators
+ def __lshift__(self, other):
+ return self._o2(other, operator.lshift)
+ def __rlshift__(self, other):
+ return self._r_o2(other, operator.lshift)
+
+ def __rshift__(self, other):
+ return self._o2(other, operator.rshift)
+ def __rrshift__(self, other):
+ return self._r_o2(other, operator.rshift)
+
+ def __and__(self, other):
+ return self._o2(other, operator.and_)
+ __rand__ = __and__
+
+ def __or__(self, other):
+ return self._o2(other, operator.or_)
+ __ror__ = __or__
+
+ def __xor__(self, other):
+ return self._o2(other, operator.xor)
+ __rxor__ = __xor__
+
+ # Unary operations
+ def __neg__(self):
+ return vec2d(operator.neg(self.x), operator.neg(self.y))
+
+ def __pos__(self):
+ return vec2d(operator.pos(self.x), operator.pos(self.y))
+
+ def __abs__(self):
+ return vec2d(abs(self.x), abs(self.y))
+
+ def __invert__(self):
+ return vec2d(-self.x, -self.y)
+
+ # vectory functions
+ def get_length_sqrd(self):
+ return self.x**2 + self.y**2
+
+ def get_length(self):
+ return math.sqrt(self.x**2 + self.y**2)
+ def __setlength(self, value):
+ length = self.get_length()
+ self.x *= value/length
+ self.y *= value/length
+ length = property(get_length, __setlength, None, "gets or sets the magnitude of the vector")
+
+ def rotate(self, angle_degrees):
+ radians = math.radians(angle_degrees)
+ cos = math.cos(radians)
+ sin = math.sin(radians)
+ x = self.x*cos - self.y*sin
+ y = self.x*sin + self.y*cos
+ self.x = x
+ self.y = y
+
+ def rotated(self, angle_degrees):
+ radians = math.radians(angle_degrees)
+ cos = math.cos(radians)
+ sin = math.sin(radians)
+ x = self.x*cos - self.y*sin
+ y = self.x*sin + self.y*cos
+ return vec2d(x, y)
+
+ def get_angle(self):
+ if (self.get_length_sqrd() == 0):
+ return 0
+ return math.degrees(math.atan2(self.y, self.x))
+ def __setangle(self, angle_degrees):
+ self.x = self.length
+ self.y = 0
+ self.rotate(angle_degrees)
+ angle = property(get_angle, __setangle, None, "gets or sets the angle of a vector")
+
+ def get_angle_between(self, other):
+ cross = self.x*other[1] - self.y*other[0]
+ dot = self.x*other[0] + self.y*other[1]
+ return math.degrees(math.atan2(cross, dot))
+
+ def normalized(self):
+ length = self.length
+ if length != 0:
+ return self/length
+ return vec2d(self)
+
+ def normalize_return_length(self):
+ length = self.length
+ if length != 0:
+ self.x /= length
+ self.y /= length
+ return length
+
+ def perpendicular(self):
+ return vec2d(-self.y, self.x)
+
+ def perpendicular_normal(self):
+ length = self.length
+ if length != 0:
+ return vec2d(-self.y/length, self.x/length)
+ return vec2d(self)
+
+ def dot(self, other):
+ return float(self.x*other[0] + self.y*other[1])
+
+ def get_distance(self, other):
+ return math.sqrt((self.x - other[0])**2 + (self.y - other[1])**2)
+
+ def get_dist_sqrd(self, other):
+ return (self.x - other[0])**2 + (self.y - other[1])**2
+
+ def projection(self, other):
+ other_length_sqrd = other[0]*other[0] + other[1]*other[1]
+ projected_length_times_other_length = self.dot(other)
+ return other*(projected_length_times_other_length/other_length_sqrd)
+
+ def cross(self, other):
+ return self.x*other[1] - self.y*other[0]
+
+ def interpolate_to(self, other, range):
+ return vec2d(self.x + (other[0] - self.x)*range, self.y + (other[1] - self.y)*range)
+
+ def convert_to_basis(self, x_vector, y_vector):
+ return vec2d(self.dot(x_vector)/x_vector.get_length_sqrd(), self.dot(y_vector)/y_vector.get_length_sqrd())
+
+ def __getstate__(self):
+ return [self.x, self.y]
+
+ def __setstate__(self, dict):
+ self.x, self.y = dict
+
+########################################################################
+## Unit Testing ##
+########################################################################
+if __name__ == "__main__":
+
+ import unittest
+ import pickle
+
+ ####################################################################
+ class UnitTestVec2D(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def testCreationAndAccess(self):
+ v = vec2d(111,222)
+ self.assert_(v.x == 111 and v.y == 222)
+ v.x = 333
+ v[1] = 444
+ self.assert_(v[0] == 333 and v[1] == 444)
+
+ def testMath(self):
+ v = vec2d(111,222)
+ self.assertEqual(v + 1, vec2d(112,223))
+ self.assert_(v - 2 == [109,220])
+ self.assert_(v * 3 == (333,666))
+ self.assert_(v / 2.0 == vec2d(55.5, 111))
+ self.assert_(v / 2 == (55, 111))
+ self.assert_(v ** vec2d(2,3) == [12321, 10941048])
+ self.assert_(v + [-11, 78] == vec2d(100, 300))
+ self.assert_(v / [11,2] == [10,111])
+
+ def testReverseMath(self):
+ v = vec2d(111,222)
+ self.assert_(1 + v == vec2d(112,223))
+ self.assert_(2 - v == [-109,-220])
+ self.assert_(3 * v == (333,666))
+ self.assert_([222,999] / v == [2,4])
+ self.assert_([111,222] ** vec2d(2,3) == [12321, 10941048])
+ self.assert_([-11, 78] + v == vec2d(100, 300))
+
+ def testUnary(self):
+ v = vec2d(111,222)
+ v = -v
+ self.assert_(v == [-111,-222])
+ v = abs(v)
+ self.assert_(v == [111,222])
+
+ def testLength(self):
+ v = vec2d(3,4)
+ self.assert_(v.length == 5)
+ self.assert_(v.get_length_sqrd() == 25)
+ self.assert_(v.normalize_return_length() == 5)
+ self.assert_(v.length == 1)
+ v.length = 5
+ self.assert_(v == vec2d(3,4))
+ v2 = vec2d(10, -2)
+ self.assert_(v.get_distance(v2) == (v - v2).get_length())
+
+ def testAngles(self):
+ v = vec2d(0, 3)
+ self.assertEquals(v.angle, 90)
+ v2 = vec2d(v)
+ v.rotate(-90)
+ self.assertEqual(v.get_angle_between(v2), 90)
+ v2.angle -= 90
+ self.assertEqual(v.length, v2.length)
+ self.assertEquals(v2.angle, 0)
+ self.assertEqual(v2, [3, 0])
+ self.assert_((v - v2).length < .00001)
+ self.assertEqual(v.length, v2.length)
+ v2.rotate(300)
+ self.assertAlmostEquals(v.get_angle_between(v2), -60)
+ v2.rotate(v2.get_angle_between(v))
+ angle = v.get_angle_between(v2)
+ self.assertAlmostEquals(v.get_angle_between(v2), 0)
+
+ def testHighLevel(self):
+ basis0 = vec2d(5.0, 0)
+ basis1 = vec2d(0, .5)
+ v = vec2d(10, 1)
+ self.assert_(v.convert_to_basis(basis0, basis1) == [2, 2])
+ self.assert_(v.projection(basis0) == (10, 0))
+ self.assert_(basis0.dot(basis1) == 0)
+
+ def testCross(self):
+ lhs = vec2d(1, .5)
+ rhs = vec2d(4,6)
+ self.assert_(lhs.cross(rhs) == 4)
+
+ def testComparison(self):
+ int_vec = vec2d(3, -2)
+ flt_vec = vec2d(3.0, -2.0)
+ zero_vec = vec2d(0, 0)
+ self.assert_(int_vec == flt_vec)
+ self.assert_(int_vec != zero_vec)
+ self.assert_((flt_vec == zero_vec) == False)
+ self.assert_((flt_vec != int_vec) == False)
+ self.assert_(int_vec == (3, -2))
+ self.assert_(int_vec != [0, 0])
+ self.assert_(int_vec != 5)
+ self.assert_(int_vec != [3, -2, -5])
+
+ def testInplace(self):
+ inplace_vec = vec2d(5, 13)
+ inplace_ref = inplace_vec
+ inplace_src = vec2d(inplace_vec)
+ inplace_vec *= .5
+ inplace_vec += .5
+ inplace_vec /= (3, 6)
+ inplace_vec += vec2d(-1, -1)
+ alternate = (inplace_src*.5 + .5)/vec2d(3,6) + [-1, -1]
+ self.assertEquals(inplace_vec, inplace_ref)
+ self.assertEquals(inplace_vec, alternate)
+
+ def testPickle(self):
+ testvec = vec2d(5, .3)
+ testvec_str = pickle.dumps(testvec)
+ loaded_vec = pickle.loads(testvec_str)
+ self.assertEquals(testvec, loaded_vec)
+
+ ####################################################################
+ unittest.main()
+
+ ########################################################################
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/viewer.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/viewer.py
new file mode 100644
index 0000000..4f9afc2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfviewer/viewer.py
@@ -0,0 +1,1117 @@
+# Name: viewer.py
+# Package: wx.lib.pdfviewer
+#
+# Purpose: A PDF report viewer class
+#
+# Author: David Hughes dfh@forestfield.co.uk
+# Copyright: Forestfield Software Ltd
+# Licence: Same as wxPython host
+
+# History: 17 Jun 2009 Created
+#
+# 08 Oct 2011 Michael Hipp michael@redmule.com
+# Added prompt, printer_name, orientation options to
+# pdfViewer.Print(). Added option to pdfViewer.LoadFile() to
+# accept a file-like object as well as a path string
+#
+# 23 Mar 2013 Werner F Bruhin werner.bruhin@free.fr
+# Added option to import PyPDF2 instead and converted
+# ShowLoadProgress and UsePrintDirect from directives
+# into settable properties
+#
+# 14 Jun 2013 David Hughes
+# Use mupdf library (via Python-fitz bindings) as backend PDF
+# extraction & rendering engine if installed otherwise use
+# PyPDF2 else pyPdf. Available from
+# https://github.com/rk700/python-fitz
+# http://www.mupdf.com
+# http://knowah.github.io/PyPDF2/
+# http://pypi.python.org/pypi/pyPdf/1.12
+#
+# WARNING. mupdf is GPL so be wary of distributing this in a frozen app
+# using py2exe, py2app or similar.
+#
+#----------------------------------------------------------------------------
+
+import sys, os, time, types
+import copy, shutil, cStringIO
+import wx
+
+VERBOSE = False
+# the following only used with pyPdf/PyPDF2
+CACHE_LATE_PAGES = True
+LATE_THRESHOLD = 200 # Time to render (ttr), milliseconds
+
+try:
+ import fitz
+ mupdf = True
+ if VERBOSE: print 'pdfviewer using Python-fitz/mupdf library (GPL)'
+except ImportError:
+ mupdf = False
+ try:
+ import PyPDF2
+ from PyPDF2 import PdfFileReader
+ from PyPDF2.pdf import ContentStream, PageObject
+ from PyPDF2.filters import ASCII85Decode, FlateDecode
+ if VERBOSE: print 'pdfviewer using PyPDF2'
+ except ImportError:
+ try:
+ import pyPdf
+ from pyPdf import PdfFileReader
+ from pyPdf.pdf import ContentStream, PageObject
+ from pyPdf.filters import ASCII85Decode, FlateDecode
+ if VERBOSE: print 'pdfviewer using PyPdf'
+ except ImportError:
+ msg = "Python-fitz (mupdf) or PyPDF2 or pyPdf package must be available"
+ raise ImportError(msg)
+try:
+ import cairo
+ from wx.lib.graphics import GraphicsContext
+ have_cairo = True
+ if VERBOSE: print 'pdfviewer using Cairo'
+except ImportError:
+ have_cairo = False
+ GraphicsContext = wx.GraphicsContext
+ if VERBOSE: print 'pdfviewer using wx.GraphicsContext'
+
+if not mupdf:
+ from dcgraphics import dcGraphicsContext
+ # New PageObject method added by Forestfield Software
+ # locate and return all commands in the order they
+ # occur in the content stream
+ def extractOperators(self):
+ ops = []
+ content = self["/Contents"].getObject()
+ if not isinstance(content, ContentStream):
+ content = ContentStream(content, self.pdf)
+ for op in content.operations:
+ ops.append(op)
+ return ops
+ # Inject this method into the PageObject class
+ PageObject.extractOperators = extractOperators
+
+ # If reportlab is installed, use its stringWidth metric. For justifying text,
+ # where widths are cumulative, dc.GetTextExtent consistently underestimates,
+ # possibly because it returns integer rather than float.
+ try:
+ from reportlab.pdfbase.pdfmetrics import stringWidth
+ have_rlwidth = True
+ if VERBOSE: print 'pdfviewer using reportlab stringWidth function'
+ except ImportError:
+ have_rlwidth = False
+
+#----------------------------------------------------------------------------
+
+class pdfViewer(wx.ScrolledWindow):
+ """ View pdf reports in a scrolled window. Contents are read from PDF file
+ and rendered in a GraphicsContext. Show visible window contents
+ as quickly as possible then read the whole file and build the set of drawing
+ commands for each page. Using pyPdf this can take time for a big file or if
+ there are complex drawings eg. ReportLab's colour shading inside charts and a
+ progress bar can be displayed by setting self.ShowLoadProgress = True (default)
+ """
+ def __init__(self, parent, id, pos, size, style):
+ wx.ScrolledWindow.__init__(self, parent, id, pos, size,
+ style | wx.NO_FULL_REPAINT_ON_RESIZE)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) # recommended in wxWidgets docs
+ self.buttonpanel = None # reference to panel is set by their common parent
+ self._showLoadProgress = (not mupdf)
+ self._usePrintDirect = (not mupdf)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_SIZE, self.OnResize)
+ self.Bind(wx.EVT_SCROLLWIN, self.OnScroll)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+ self.have_file = False
+ self.resizing = False
+ self.numpages = None
+ self.zoomscale = -1 # fit page to screen width
+ self.nom_page_gap = 20 # nominal inter-page gap (points)
+ self.scrollrate = 20 # pixels per scrollbar increment
+ self.ClearBackground()
+
+ def OnIdle(self, event):
+ " Redraw on resize"
+ if self.resizing:
+ self.Render()
+ self.resizing = False
+ event.Skip()
+
+ def OnEraseBackground(self, event):
+ "Does this need to be handled?"
+ event.Skip()
+
+ def OnResize(self, event):
+ " Buffer size change due to client area resize."
+ self.resizing = True
+ if hasattr(self, 'cachedpages'):
+ self.cachedpages = {}
+ event.Skip()
+
+ def OnScroll(self,event):
+ " Recalculate and redraw visible area. CallAfter is *essential* for coordination."
+ wx.CallAfter(self.Render, force=False)
+ event.Skip()
+
+ def OnPaint(self, event):
+ " Refresh visible window with bitmap contents"
+ paintDC = wx.PaintDC(self)
+ if hasattr(self, 'pdc'):
+ paintDC.BeginDrawing()
+ paintDC.Blit(0, 0, self.winwidth, self.winheight, self.pdc,
+ self.xshift, self.yshift)
+ paintDC.EndDrawing()
+ else:
+ paintDC.Clear()
+
+#----------------------------------------------------------------------------
+
+ # This section defines the externally callable methods:
+ # LoadFile, Save, Print, SetZoom, and GoPage also
+ # getters and setters for ShowLoadProgress and UsePrintDirect
+ # that are only needed if using pyPdf
+
+ def LoadFile(self, pdf_file):
+ """
+ Read pdf file using pypdf. Assume all pages are same size, for now.
+
+ :param `pdf_file`: can be either a string holding a filename path or
+ a file-like object (pyPdf only).
+ """
+ if isinstance(pdf_file, types.StringTypes):
+ # it must be a filename/path string, open it as a file
+ fileobj = file(pdf_file, 'rb')
+ self.pdfpathname = pdf_file
+ else:
+ # assume it is a file-like object
+ fileobj = pdf_file
+ self.pdfpathname = '' # empty default file name
+ self.ShowLoadProgress = True
+ if mupdf:
+ self.pdfdoc = mupdfProcessor(self, self.pdfpathname)
+ else:
+ self.pdfdoc = pypdfProcessor(self, fileobj, self.ShowLoadProgress)
+ self.cachedpages = {}
+
+ self.numpages = self.pdfdoc.numpages
+ self.pagewidth = self.pdfdoc.pagewidth
+ self.pageheight = self.pdfdoc.pageheight
+ self.newdoc = True
+ self.Scroll(0,0) # in case this is a re-LoadFile
+ self.CalculateDimensions(True) # to get initial visible page range
+ # draw and display the minimal set of pages
+ self.pdfdoc.DrawFile(self.frompage, self.topage)
+ self.have_file = True
+ # now draw full set of pages
+ wx.CallAfter(self.pdfdoc.DrawFile, 0, self.numpages-1)
+
+ def Save(self):
+ "Save a copy of the pdf file if it was originally named"
+ if self.pdfpathname:
+ wild = "Portable document format (*.pdf)|*.pdf"
+ dlg = wx.FileDialog(self, message="Save file as ...",
+ wildcard=wild, style=wx.SAVE|wx.OVERWRITE_PROMPT)
+ if dlg.ShowModal() == wx.ID_OK:
+ pathname = dlg.GetPath()
+ shutil.copy(self.pdfpathname, pathname)
+ dlg.Destroy()
+
+ def Print(self, prompt=True, printer_name=None, orientation=None):
+ """
+ Print the pdf.
+
+ :param boolean `prompt`: show the print dialog to the user (True/False). If
+ False, the print dialog will not be shown and the pdf will be printed
+ immediately. Default: True.
+ :param string `printer_name`: the name of the printer that is to
+ receive the printout. Default: as set by the O/S.
+ :param `orientation`: select the orientation (wx.PORTRAIT or
+ wx.LANDSCAPE) for the printout. Default: as set by the O/S.
+ """
+ pdd = wx.PrintDialogData()
+ pdd.SetMinPage(1)
+ pdd.SetFromPage(1)
+ pdd.SetMaxPage(self.numpages)
+ pdd.SetToPage(self.numpages)
+ pdata = pdd.GetPrintData()
+ if printer_name:
+ pdata.SetPrinterName(printer_name)
+ if orientation:
+ pdata.SetOrientation(orientation)
+ # PrintData does not return actual PrintQuality - it can't as printer_name not known
+ # but it defaults to wx.PRINT_QUALITY_HIGH, overriding user's own setting for the
+ # printer. However calling SetQuality with a value of 0 seems to leave the printer
+ # setting untouched
+ pdata.SetQuality(0)
+ printer = wx.Printer(pdd)
+ printout = pdfPrintout('', self)
+ if (not printer.Print(self, printout, prompt=prompt) and
+ printer.GetLastError() == wx.PRINTER_ERROR):
+ dlg = wx.MessageDialog(self, 'Unable to perform printing',
+ 'Printer' , wx.OK | wx.ICON_INFORMATION)
+ dlg.ShowModal()
+ dlg.Destroy()
+ printout.Destroy()
+
+ def SetZoom(self, zoomscale):
+ """ Positive integer or floating zoom scale will render the file at corresponding
+ size where 1.0 is "actual" point size (1/72").
+ -1 fits page width and -2 fits page height into client area
+ Redisplay the current page(s) at the new size
+ """
+ pagenow = self.frompage
+ self.zoomscale = zoomscale
+ if hasattr(self, 'cachedpages'):
+ self.cachedpages = {}
+ self.CalculateDimensions(True)
+ self.GoPage(pagenow)
+
+ def GoPage(self, pagenum):
+ if pagenum > 0 and pagenum <= self.numpages:
+ self.Scroll(0, pagenum*self.Ypagepixels/self.GetScrollPixelsPerUnit()[1])
+ else:
+ self.Scroll(0, 0)
+ # calling Scroll sometimes doesn't raise wx.EVT_SCROLLWIN eg Windows 8 64 bit - so
+ wx.CallAfter(self.Render, force=False)
+
+ @property
+ def ShowLoadProgress(self):
+ """Property to control if loading progress be shown."""
+ return self._showLoadProgress
+
+ @ShowLoadProgress.setter
+ def ShowLoadProgress(self, flag):
+ """Setter for showLoadProgress."""
+ self._showLoadProgress = flag
+
+ @property
+ def UsePrintDirect(self):
+ """
+ Property to control to use either Cairo (via a page buffer) or
+ dcGraphicsContext depending.
+ """
+ return self._usePrintDirect
+
+ @UsePrintDirect.setter
+ def UsePrintDirect(self, flag):
+ """Setter for usePrintDirect."""
+ self._usePrintDirect = flag
+
+#----------------------------------------------------------------------------
+
+ "This section is concerned with rendering a sub-set of drawing commands on demand"
+
+ def CalculateDimensions(self, force):
+ """ Compute the required buffer sizes to hold the viewed rectangle and
+ the range of pages visible. Override force flag and set true if
+ the current set of rendered pages changes
+ """
+ self.frompage = 0
+ self.topage = 0
+ self.clientdc = dc = wx.ClientDC(self) # dc for device scaling
+ self.device_scale = dc.GetPPI()[0]/72.0 # pixels per inch / points per inch
+ if wx.PlatformInfo[1] == 'wxMSW':
+ # for Windows only wx.GraphicsContext fonts are too big in the ratio
+ # of screen pixels per inch to points per inch
+ self.font_scale = 1.0 / self.device_scale
+ else:
+ self.font_scale = 1.0
+
+ self.winwidth, self.winheight = self.GetClientSizeTuple()
+ if self.winheight < 100:
+ return
+ self.Ypage = self.pageheight + self.nom_page_gap
+ if self.zoomscale > 0.0:
+ self.scale = self.zoomscale * self.device_scale
+ else:
+ if int(self.zoomscale) == -1: # fit width
+ self.scale = self.winwidth / self.pagewidth
+ else: # fit page
+ self.scale = self.winheight / self.pageheight
+ self.Xpagepixels = int(round(self.pagewidth*self.scale))
+ self.Ypagepixels = int(round(self.Ypage*self.scale))
+
+ # adjust inter-page gap so Ypagepixels is a whole number of scroll increments
+ # and page numbers change precisely on a scroll click
+ idiv = self.Ypagepixels/self.scrollrate
+ nlo = idiv * self.scrollrate
+ nhi = (idiv + 1) * self.scrollrate
+ if nhi - self.Ypagepixels < self.Ypagepixels - nlo:
+ self.Ypagepixels = nhi
+ else:
+ self.Ypagepixels = nlo
+ self.page_gap = self.Ypagepixels/self.scale - self.pageheight
+
+ self.maxwidth = max(self.winwidth, self.Xpagepixels)
+ self.maxheight = max(self.winheight, self.numpages*self.Ypagepixels)
+ self.SetVirtualSize((self.maxwidth, self.maxheight))
+ self.SetScrollRate(self.scrollrate,self.scrollrate)
+
+ xv, yv = self.GetViewStart()
+ dx, dy = self.GetScrollPixelsPerUnit()
+ self.x0, self.y0 = (xv * dx, yv * dy)
+ self.frompage = min(self.y0/self.Ypagepixels, self.numpages-1)
+ self.topage = min((self.y0+self.winheight-1)/self.Ypagepixels, self.numpages-1)
+ self.pagebufferwidth = max(self.Xpagepixels, self.winwidth)
+ self.pagebufferheight = (self.topage - self.frompage + 1) * self.Ypagepixels
+
+ # Inform buttonpanel controls of any changes
+ if self.buttonpanel:
+ self.buttonpanel.Update(self.frompage, self.numpages,
+ self.scale/self.device_scale)
+
+ self.page_y0 = self.frompage * self.Ypagepixels
+ self.page_x0 = 0
+ self.xshift = self.x0 - self.page_x0
+ self.yshift = self.y0 - self.page_y0
+ if force: # by external request
+ self.cur_frompage = self.frompage
+ self.cur_topage = self.topage
+ else: # page range unchanged? whole visible area will always be inside page buffer
+ if self.frompage <> self.cur_frompage or self.topage <> self.cur_topage:
+ force = True # due to page buffer change
+ self.cur_frompage = self.frompage
+ self.cur_topage = self.topage
+ return force
+
+ def Render(self, force=True):
+ """ Recalculate dimensions as client area may have been scrolled or resized.
+ The smallest unit of rendering that can be done is the pdf page. So render
+ the drawing commands for the pages in the visible rectangle into a buffer
+ big enough to hold this set of pages. Force re-creating the page buffer
+ only when client view moves outside it.
+ With pyPdf, use gc.Translate to render each page wrt the pdf origin,
+ which is at the bottom left corner of the page.
+ """
+ if not self.have_file:
+ return
+ force = self.CalculateDimensions(force or self.newdoc)
+ self.newdoc = False # this ensured page buffer recreated if a new document
+ if force:
+ # Initialize the buffer bitmap.
+ self.pagebuffer = wx.EmptyBitmap(self.pagebufferwidth, self.pagebufferheight)
+ self.pdc = wx.MemoryDC(self.pagebuffer) # must persist
+ gc = GraphicsContext.Create(self.pdc) # Cairo/wx.GraphicsContext API
+ # white background
+ path = gc.CreatePath()
+ path.AddRectangle(0, 0, self.pagebuffer.GetWidth(), self.pagebuffer.GetHeight())
+ gc.SetBrush(wx.WHITE_BRUSH)
+ gc.FillPath(path)
+
+ for pageno in range(self.frompage, self.topage+1):
+ self.xpageoffset = 0 - self.x0
+ self.ypageoffset = pageno*self.Ypagepixels - self.page_y0
+ if not mupdf and pageno in self.cachedpages:
+ self.pdc.Blit(self.xpageoffset, self.ypageoffset,
+ self.Xpagepixels, self.Ypagepixels,
+ self.cachedpages[pageno], 0, 0)
+ else:
+ t1 = time.time()
+ gc.PushState()
+ if mupdf:
+ gc.Translate(self.xpageoffset, self.ypageoffset)
+ # scaling is done inside RenderPage
+ else:
+
+ gc.Translate(self.xpageoffset, self.ypageoffset +
+ self.pageheight*self.scale)
+ gc.Scale(self.scale, self.scale)
+ self.pdfdoc.RenderPage(gc, pageno, self.scale)
+ # Show inter-page gap
+ gc.SetBrush(wx.Brush(wx.Colour(180, 180, 180))) #mid grey
+ gc.SetPen(wx.TRANSPARENT_PEN)
+ if mupdf:
+ gc.DrawRectangle(0, self.pageheight*self.scale,
+ self.pagewidth*self.scale, self.page_gap*self.scale)
+ else:
+ gc.DrawRectangle(0, 0, self.pagewidth, self.page_gap)
+ gc.PopState()
+ ttr = time.time()-t1
+ if not mupdf and CACHE_LATE_PAGES and ttr * 1000 > LATE_THRESHOLD:
+ self.CachePage(pageno) # save page out of buffer
+ gc.PushState()
+ gc.Translate(0-self.x0, 0-self.page_y0)
+ self.RenderPageBoundaries(gc)
+ gc.PopState()
+
+ self.Refresh(0) # Blit appropriate area of new or existing page buffer to screen
+
+ def RenderPageBoundaries(self, gc):
+ "Show non-page areas in grey"
+ gc.SetBrush(wx.Brush(wx.Colour(180, 180, 180))) #mid grey
+ gc.SetPen(wx.TRANSPARENT_PEN)
+ gc.Scale(1.0, 1.0)
+ extrawidth = self.winwidth - self.Xpagepixels
+ if extrawidth > 0:
+ gc.DrawRectangle(self.winwidth-extrawidth, 0, extrawidth, self.maxheight)
+ extraheight = self.winheight - (self.numpages*self.Ypagepixels - self.y0)
+ if extraheight > 0:
+ gc.DrawRectangle(0, self.winheight-extraheight, self.maxwidth, extraheight)
+
+ def CachePage(self, pageno):
+ """ When page takes a 'long' time to render, save its contents out of
+ self.pdc and re-use it to minimise jerky scrolling
+ """
+ cachebuffer = wx.EmptyBitmap(self.Xpagepixels, self.Ypagepixels)
+ cdc = wx.MemoryDC(cachebuffer)
+ cdc.Blit(0, 0, self.Xpagepixels, self.Ypagepixels,
+ self.pdc, self.xpageoffset, self.ypageoffset)
+ self.cachedpages[pageno] = cdc
+
+#============================================================================
+
+class mupdfProcessor(object):
+ """ Create an instance of this class to open a PDF file, process the contents of
+ each page and render each one on demand using the GPL mupdf library, which is
+ accessed via the python-fitz package bindings
+ """
+ def __init__(self, parent, pathname):
+ " pathname must be Stringtype not unicode"
+ self.parent = parent
+ if isinstance(pathname, types.UnicodeType):
+ pathname = pathname.encode('latin-1')
+ self.context = fitz.Context(fitz.FZ_STORE_UNLIMITED)
+ self.pdfdoc = self.context.open_document(pathname)
+ self.numpages = self.pdfdoc.count_pages()
+ page1 = self.pdfdoc.load_page(0)
+ self.pagewidth = page1.bound_page().x1
+ self.pageheight = page1.bound_page().y1
+ self.pagedrawings = {}
+ self.zoom_error = False #set if memory errors during render
+
+ def DrawFile(self, frompage, topage):
+ """ Build set of drawing commands from PDF contents. This need be done only
+ once for the whole file. Each page is placed in a display_list which can
+ be (re)drawn many times using run_display_list()
+ """
+ for pageno in range(frompage, topage+1):
+ self.page = self.pdfdoc.load_page(pageno)
+ self.pagedrawings[pageno] = self.context.new_display_list()
+ mdev = self.pagedrawings[pageno].new_list_device()
+ self.page.run_page(mdev, fitz.fz_identity, None)
+ self.page_rect = self.page.bound_page()
+ self.parent.GoPage(frompage)
+
+ def RenderPage(self, gc, pageno, scale=1.0):
+ " Render the set of pagedrawings into gc for specified page "
+ self.trans = fitz.scale_matrix(scale, scale)
+ self.rect = self.trans.transform_rect(self.page_rect) #page_rect is the unscaled one
+ self.bbox = self.rect.round_rect()
+
+ try:
+ self.pix = self.context.new_pixmap_with_irect(fitz.fz_device_rgb, self.bbox)
+ self.pix.clear_pixmap(255)
+ width = self.pix.get_width()
+ height = self.pix.get_height()
+ dev = self.pix.new_draw_device()
+ self.pagedrawings[pageno].run_display_list(dev, self.trans, self.rect, None)
+ bmp = wx.BitmapFromBufferRGBA(width, height,self.pix.get_samples())
+ gbmp = gc.CreateBitmap(bmp)
+ gc.DrawBitmap(gbmp, 0, 0, width, height)
+ self.zoom_error = False
+ except RuntimeError, MemoryError:
+ if not self.zoom_error: # report once only
+ self.zoom_error = True
+ dlg = wx.MessageDialog(self, 'Out of memory. Zoom level too high',
+ 'pdf viewer' , wx.OK |wx.ICON_EXCLAMATION)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+#============================================================================
+
+class pypdfProcessor(object):
+ """ Create an instance of this class to open a PDF file, process the contents of
+ each page and draw each one on demand using the Python pypdf package
+ """
+ def __init__(self, parent, fileobj, showloadprogress):
+ self.parent = parent
+ self.showloadprogress = showloadprogress
+ self.pdfdoc = PdfFileReader(fileobj)
+ self.numpages = self.pdfdoc.getNumPages()
+ page1 = self.pdfdoc.getPage(0)
+ self.pagewidth = float(page1.mediaBox.getUpperRight_x())
+ self.pageheight = float(page1.mediaBox.getUpperRight_y())
+ self.pagedrawings = {}
+ self.unimplemented = {}
+ self.formdrawings = {}
+
+ "These methods interpret the PDF contents as a set of drawing commands"
+
+ def Progress(self, ptype, value):
+ " This function is called at regular intervals during Drawfile"
+ if ptype == 'start':
+ msg = 'Reading pdf file'
+ self.progbar = wx.ProgressDialog('Load file', msg, value, None,
+ wx.PD_AUTO_HIDE|
+ wx.PD_ESTIMATED_TIME|wx.PD_REMAINING_TIME)
+ elif ptype == 'progress':
+ self.progbar.Update(value)
+ elif ptype == 'end':
+ self.progbar.Destroy()
+
+ def DrawFile(self, frompage, topage):
+ """ Build set of drawing commands from PDF contents. Ideally these could be drawn
+ straight into a PseudoDC and the visible section painted directly into
+ scrolled window, but we need to be able to zoom and scale the output quickly
+ without having to rebuild the drawing commands (slow). So roll our
+ own command lists, one per page, into self.pagedrawings.
+ """
+ t0 = time.time()
+ numpages_generated = 0
+ rp = (self.showloadprogress and frompage == 0 and topage == self.numpages-1)
+ if rp: self.Progress('start', self.numpages)
+ for self.pageno in range(frompage, topage+1):
+ self.gstate = pdfState() # state is reset with every new page
+ self.saved_state = []
+ self.page = self.pdfdoc.getPage(self.pageno)
+ numpages_generated += 1
+ pdf_fonts = self.FetchFonts(self.page)
+ self.pagedrawings[self.pageno] = self.ProcessOperators(
+ self.page.extractOperators(), pdf_fonts)
+ if rp: self.Progress('progress', numpages_generated)
+
+ ## print 'Pages %d to %d. %d pages created in %.2f seconds' % (
+ ## frompage, topage, numpages_generated,(time.time()-t0))
+ if rp: self.Progress('end', None)
+ self.parent.GoPage(frompage)
+
+ def RenderPage(self, gc, pageno, scale=None):
+ """ Render the set of pagedrawings
+ In a pdf file, bitmaps are treated as being of unit width and height and
+ are scaled via a previous ConcatTransform containing the corresponding width
+ and height as scale factors. wx.GraphicsContext/Cairo appear not to respond to
+ this so scaling is removed from transform and width & height are added
+ to the Drawbitmap call.
+ """
+ drawdict = {'ConcatTransform': gc.ConcatTransform,
+ 'PushState': gc.PushState,
+ 'PopState': gc.PopState,
+ 'SetFont': gc.SetFont,
+ 'SetPen': gc.SetPen,
+ 'SetBrush': gc.SetBrush,
+ 'DrawText': gc.DrawText,
+ 'DrawBitmap': gc.DrawBitmap,
+ 'CreatePath': gc.CreatePath,
+ 'DrawPath': gc.DrawPath }
+ for drawcmd, args, kwargs in self.pagedrawings[pageno]:
+ if drawcmd == 'ConcatTransform':
+ cm = gc.CreateMatrix(*args, **kwargs)
+ args = (cm,)
+ if drawcmd == 'CreatePath':
+ gp = drawdict[drawcmd](*args, **kwargs)
+ continue
+ elif drawcmd == 'DrawPath':
+ args = (gp, args[1])
+ if drawcmd in drawdict:
+ drawdict[drawcmd](*args, **kwargs)
+ else:
+ pathdict = {'MoveToPoint': gp.MoveToPoint,
+ 'AddLineToPoint': gp.AddLineToPoint,
+ 'AddCurveToPoint': gp.AddCurveToPoint,
+ 'AddRectangle': gp.AddRectangle,
+ 'CloseSubpath': gp.CloseSubpath }
+ if drawcmd in pathdict:
+ pathdict[drawcmd](*args, **kwargs)
+
+ def FetchFonts(self, currentobject):
+ " Return the standard fonts in current page or form"
+ pdf_fonts = {}
+ try:
+ fonts = currentobject["/Resources"].getObject()['/Font']
+ for key in fonts:
+ pdf_fonts[key] = fonts[key]['/BaseFont'][1:] # remove the leading '/'
+ except KeyError:
+ pass
+ return pdf_fonts
+
+ def ProcessOperators(self, opslist, pdf_fonts):
+ " Interpret each operation in opslist and return in drawlist"
+ drawlist = []
+ path = []
+ for operand, operator in opslist :
+ g = self.gstate
+ if operator == 'cm': # new transformation matrix
+ # some operands need inverting because directions of y axis
+ # in pdf and graphics context are opposite
+ a, b, c, d, e, f = map(float, operand)
+ drawlist.append(['ConcatTransform', (a, -b, -c, d, e, -f), {}])
+ elif operator == 'q': # save state
+ self.saved_state.append(copy.deepcopy(g))
+ drawlist.append(['PushState', (), {}])
+ elif operator == 'Q': # restore state
+ self.gstate = self.saved_state.pop()
+ drawlist.append(['PopState', (), {}])
+ elif operator == 'RG': # Stroke RGB
+ rs, gs, bs = [int(v*255) for v in map(float, operand)]
+ g.strokeRGB = wx.Colour(rs, gs, bs)
+ elif operator == 'rg': # Fill RGB
+ rf, gf, bf = [int(v*255) for v in map(float, operand)]
+ g.fillRGB = wx.Colour(rf, gf, bf)
+ elif operator == 'K': # Stroke CMYK
+ rs, gs, bs = self.ConvertCMYK(operand)
+ g.strokeRGB = wx.Colour(rs, gs, bs)
+ elif operator == 'k': # Fill CMYK
+ rf, gf, bf = self.ConvertCMYK(operand)
+ g.fillRGB = wx.Colour(rf, gf, bf)
+ elif operator == 'w': # Line width
+ g.lineWidth = float(operand[0])
+ elif operator == 'J': # Line cap
+ ix = float(operand[0])
+ g.lineCapStyle = {0: wx.CAP_BUTT, 1: wx.CAP_ROUND,
+ 2: wx.CAP_PROJECTING}[ix]
+ elif operator == 'j': # Line join
+ ix = float(operand[0])
+ g.lineJoinStyle = {0: wx.JOIN_MITER, 1: wx.JOIN_ROUND,
+ 2: wx.JOIN_BEVEL}[ix]
+ elif operator == 'd': # Line dash pattern
+ g.lineDashArray = map(int, operand[0])
+ g.lineDashPhase = int(operand[1])
+ elif operator in ('m', 'c', 'l', 're', 'v', 'y', 'h'): # path defining ops
+ path.append([map(float, operand), operator])
+ elif operator in ('b', 'B', 'b*', 'B*', 'f', 'F', 'f*',
+ 's', 'S', 'n'): # path drawing ops
+ drawlist.extend(self.DrawPath(path, operator))
+ path = []
+ elif operator == 'BT': # begin text object
+ g.textMatrix = [1, 0, 0, 1, 0, 0]
+ g.textLineMatrix = [1, 0, 0, 1, 0, 0]
+ elif operator == 'ET': # end text object
+ continue
+ elif operator == 'Tm': # text matrix
+ g.textMatrix = map(float, operand)
+ g.textLineMatrix = map(float, operand)
+ elif operator == 'TL': # text leading
+ g.leading = float(operand[0])
+ #elif operator == 'Tc': # character spacing
+ # g.charSpacing = float(operand[0])
+ elif operator == 'Tw': # word spacing
+ g.wordSpacing = float(operand[0])
+ elif operator == 'Ts': # super/subscript
+ g.textRise = float(operand[0])
+ elif operator == 'Td': # next line via offsets
+ g.textLineMatrix[4] += float(operand[0])
+ g.textLineMatrix[5] += float(operand[1])
+ g.textMatrix = copy.copy(g.textLineMatrix)
+ elif operator == 'T*': # next line via leading
+ g.textLineMatrix[4] += 0
+ g.textLineMatrix[5] -= g.leading if g.leading is not None else 0
+ g.textMatrix = copy.copy(g.textLineMatrix)
+ elif operator == 'Tf': # text font
+ g.font = pdf_fonts[operand[0]]
+ g.fontSize = float(operand[1])
+ elif operator == 'Tj': # show text
+ drawlist.extend(self.DrawTextString(operand[0]))
+ elif operator == 'Do': # invoke named XObject
+ dlist = self.InsertXObject(operand[0])
+ if dlist: # may be unimplemented decode
+ drawlist.extend(dlist)
+ elif operator == 'INLINE IMAGE': # special pyPdf case + operand is a dict
+ dlist = self.InlineImage(operand)
+ if dlist: # may be unimplemented decode
+ drawlist.extend(dlist)
+ else: # report once
+ if operator not in self.unimplemented:
+ if VERBOSE: print 'PDF operator %s is not implemented' % operator
+ self.unimplemented[operator] = 1
+
+ # Fix bitmap transform. Remove the scaling from any transform matrix that precedes
+ # a DrawBitmap operation as the scaling is now done in that operation.
+ for k in range(len(drawlist)-1):
+ if drawlist[k][0] == 'ConcatTransform' and drawlist[k+1][0] == 'DrawBitmap':
+ args = list(drawlist[k][1])
+ args[0] = 1.0
+ args[3] = 1.0
+ drawlist[k][1] = tuple(args)
+ return drawlist
+
+ def SetFont(self, pdfont, size):
+ """ Returns wx.Font instance from supplied pdf font information """
+ self.knownfont = True
+ pdfont = pdfont.lower()
+ if pdfont.count('courier'):
+ family = wx.FONTFAMILY_MODERN
+ font = 'Courier New'
+ elif pdfont.count('helvetica'):
+ family = wx.FONTFAMILY_SWISS
+ font = 'Arial'
+ elif pdfont.count('times'):
+ family = wx.FONTFAMILY_ROMAN
+ font = 'Times New Roman'
+ elif pdfont.count('symbol'):
+ family = wx.FONTFAMILY_DEFAULT
+ font = 'Symbol'
+ elif pdfont.count('zapfdingbats'):
+ family = wx.FONTFAMILY_DEFAULT
+ font = 'Wingdings'
+ else:
+ if VERBOSE: print 'Unknown font %s' % pdfont
+ self.knownfont = False
+ family = wx.FONTFAMILY_SWISS
+ font = 'Arial'
+
+ weight = wx.FONTWEIGHT_NORMAL
+ if pdfont.count('bold'):
+ weight = wx.FONTWEIGHT_BOLD
+ style = wx.FONTSTYLE_NORMAL
+ if pdfont.count('oblique') or pdfont.count('italic'):
+ style = wx.FONTSTYLE_ITALIC
+ return wx.Font(max(1,size), family, style, weight, faceName=font)
+
+ def DrawTextString(self, text):
+ "word spacing only works for horizontal text (??)"
+ dlist = []
+ g = self.gstate
+ f = self.SetFont(g.font, g.fontSize*self.parent.font_scale)
+ dlist.append(['SetFont', (f, g.fillRGB), {}])
+ if g.wordSpacing > 0:
+ textlist = text.split(' ')
+ else:
+ textlist = [text,]
+ for item in textlist:
+ dlist.append(self.DrawTextItem(item, f))
+ return dlist
+
+ def DrawTextItem(self, textitem, f):
+ dc = wx.ClientDC(self.parent) # dummy dc for text extents
+ g = self.gstate
+ x = g.textMatrix[4]
+ y = g.textMatrix[5] + g.textRise
+ if g.wordSpacing > 0:
+ textitem += ' '
+ wid, ht, descend, xlead = dc.GetFullTextExtent(textitem, f)
+ if have_rlwidth and self.knownfont: # use ReportLab stringWidth if available
+ width = stringWidth(textitem, g.font, g.fontSize)
+ else:
+ width = wid
+ g.textMatrix[4] += (width + g.wordSpacing) # update current x position
+ return ['DrawText', (textitem, x, -y-(ht-descend)), {}]
+
+ def DrawPath(self, path, action):
+ """ Stroke and/or fill the defined path depending on operator """
+ dlist = []
+ g = self.gstate
+ acts = {'S': (1, 0, 0),
+ 's': (1, 0, 0),
+ 'f': (0, 1, wx.WINDING_RULE),
+ 'F': (0, 1, wx.WINDING_RULE),
+ 'f*': (0, 1, wx.ODDEVEN_RULE),
+ 'B': (1, 1, wx.WINDING_RULE),
+ 'B*': (1, 1, wx.ODDEVEN_RULE),
+ 'b': (1, 1, wx.WINDING_RULE),
+ 'b*': (1, 1, wx.ODDEVEN_RULE),
+ 'n': (0, 0, 0) }
+ stroke, fill, rule = acts[action]
+ if action in ('s', 'b', 'b*'):
+ path.append([[], 'h']) # close path
+
+ if stroke:
+ if g.lineDashArray:
+ style = wx.USER_DASH
+ else:
+ style = wx.SOLID
+ cpen = wx.Pen(g.strokeRGB, g.lineWidth, style)
+ cpen.SetCap(g.lineCapStyle)
+ cpen.SetJoin(g.lineJoinStyle)
+ if g.lineDashArray:
+ cpen.SetDashes(g.lineDashArray)
+ dlist.append(['SetPen', (cpen,), {}])
+ else:
+ dlist.append(['SetPen', (wx.TRANSPARENT_PEN,), {}])
+
+ if fill:
+ dlist.append(['SetBrush', (wx.Brush(g.fillRGB),), {}])
+ else:
+ dlist.append(['SetBrush', (wx.TRANSPARENT_BRUSH,), {}])
+
+ dlist.append(['CreatePath', (), {}])
+ for xylist, op in path:
+ if op == 'm': # move (to) current point
+ x0 = xc = xylist[0]
+ y0 = yc = -xylist[1]
+ dlist.append(['MoveToPoint', (x0, y0), {}])
+ elif op == 'l': # draw line
+ x2 = xylist[0]
+ y2 = -xylist[1]
+ dlist.append(['AddLineToPoint', (x2, y2), {}])
+ xc = x2
+ yc = y2
+ elif op == 're': # draw rectangle (x,y at top left)
+ x = xylist[0]
+ y = -xylist[1]
+ w = xylist[2]
+ h = xylist[3]
+ dlist.append(['AddRectangle', (x, y-h, w, h), {}])
+ elif op in ('c', 'v', 'y'): # draw Bezier curve
+ args = []
+ if op == 'v':
+ args.extend([xc, yc])
+ args.extend([xylist[0], -xylist[1],
+ xylist[2], -xylist[3]])
+ if op == 'y':
+ args.extend([xylist[2], -xylist[3]])
+ if op == 'c':
+ args.extend([xylist[4], -xylist[5]])
+ dlist.append(['AddCurveToPoint', args, {}])
+ elif op == 'h':
+ dlist.append(['CloseSubpath', (), {}])
+ dlist.append(['DrawPath', ('GraphicsPath', rule), {}])
+ return dlist
+
+ def InsertXObject(self, name):
+ " XObject can be an image or a 'form' (an arbitrary PDF sequence) "
+ dlist = []
+ xobject = self.page["/Resources"].getObject()['/XObject']
+ stream = xobject[name]
+ if stream.get('/Subtype') == '/Form':
+ # insert contents into current page drawing
+ if not name in self.formdrawings: # extract if not already done
+ pdf_fonts = self.FetchFonts(stream)
+ bbox = stream.get('/BBox')
+ matrix = stream.get('/Matrix')
+ form_ops = ContentStream(stream, self.pdfdoc).operations
+ oplist = [([], 'q'), (matrix, 'cm')] # push state & apply matrix
+ oplist.extend(form_ops) # add form contents
+ oplist.append(([], 'Q')) # restore original state
+ self.formdrawings[name] = self.ProcessOperators(oplist, pdf_fonts)
+ dlist.extend(self.formdrawings[name])
+ elif stream.get('/Subtype') == '/Image':
+ width = stream['/Width']
+ height = stream['/Height']
+ depth = stream['/BitsPerComponent']
+ filters = stream["/Filter"]
+ item = self.AddBitmap(stream._data, width, height, filters)
+ if item: # may be unimplemented
+ dlist.append(item)
+ return dlist
+
+ def InlineImage(self, operand):
+ " operand contains an image"
+ dlist = []
+ data = operand.get('data')
+ settings = operand.get('settings')
+ width = settings['/W']
+ height = settings['/H']
+ depth = settings['/BPC']
+ filters = settings['/F']
+ item = self.AddBitmap(data, width, height, filters)
+ if item: # may be unimplemented
+ dlist.append(item)
+ return dlist
+
+ def AddBitmap(self, data, width, height, filters):
+ "Add wx.Bitmap from data, processed by filters"
+ if '/A85' in filters or '/ASCII85Decode' in filters:
+ data = _AsciiBase85DecodePYTHON(data)
+ if '/Fl' in filters or '/FlateDecode' in filters:
+ data = FlateDecode.decode(data, None)
+ if '/CCF' in filters or '/CCITTFaxDecode' in filters:
+ if VERBOSE:
+ print 'PDF operation /CCITTFaxDecode is not implemented'
+ return []
+ if '/DCT' in filters or '/DCTDecode' in filters:
+ stream = cStringIO.StringIO(data)
+ image = wx.ImageFromStream(stream, wx.BITMAP_TYPE_JPEG)
+ bitmap = wx.BitmapFromImage(image)
+ else:
+ bitmap = wx.BitmapFromBuffer(width, height, data)
+ return ['DrawBitmap', (bitmap, 0, 0-height, width, height), {}]
+
+ def ConvertCMYK(self, operand):
+ "Convert CMYK values (0 to 1.0) in operand to nearest RGB"
+ c, m, y, k = operand
+ r = round((1-c)*(1-k)*255)
+ b = round((1-y)*(1-k)*255)
+ g = round((1-m)*(1-k)*255)
+ return (r, g, b)
+
+#----------------------------------------------------------------------------
+
+class pdfState(object):
+ """ Instance holds the current pdf graphics and text state. It can be
+ saved (pushed) and restored (popped) by the owning parent
+ """
+ def __init__ (self):
+ """ Creates an instance with default values. Individual attributes
+ are modified directly not via getters and setters """
+ self.lineWidth = 1.0
+ self.lineCapStyle = wx.CAP_BUTT
+ self.lineJoinStyle = wx.JOIN_MITER
+ self.lineDashArray = []
+ self.lineDashPhase = 0
+ self.miterLimit = None
+ self.strokeRGB = wx.Colour(0, 0, 0)
+ self.fillRGB = wx.Colour(0, 0, 0) # used for both shapes & text
+ self.fillMode = None
+
+ self.textMatrix = [1, 0, 0, 1, 0, 0]
+ self.textLineMatrix = [1, 0, 0, 1, 0, 0]
+ self.charSpacing = 0
+ self.wordSpacing = 0
+ self.horizontalScaling = None
+ self.leading = None
+ self.font = None
+ self.fontSize = None
+ self.textRenderMode = None
+ self.textRise = 0
+
+#------------------------------------------------------------------------------
+
+class pdfPrintout(wx.Printout):
+ """ Class encapsulating the functionality of printing out the document. The methods below
+ over-ride those of the base class and supply document-specific information to the
+ printing framework that calls them internally.
+ """
+ def __init__(self, title, view):
+ "Pass in the instance of dpViewer to be printed"
+ wx.Printout.__init__(self, title)
+ self.view = view
+
+ def HasPage(self, pageno):
+ "Report whether pageno exists"
+ if pageno <= self.view.numpages:
+ return True
+ else:
+ return False
+
+ def GetPageInfo(self):
+ """ Supply maximum range of pages and the range to be printed
+ These are initial values passed to Printer dialog, where they
+ can be amended by user.
+ """
+ max = self.view.numpages
+ return (1, max, 1, max)
+
+ def OnPrintPage(self, page):
+ """ Provide the data for page by rendering the drawing commands
+ to the printer DC using either Cairo (via a page buffer) or
+ dcGraphicsContext depending on self.view.usePrintDirect
+ """
+ if not mupdf and self.view.UsePrintDirect:
+ self.PrintDirect(page)
+ else:
+ self.PrintViaBuffer(page)
+ return True
+
+ def PrintDirect(self, page):
+ """ Provide the data for page by rendering the drawing commands
+ to the printer DC using dcGraphicsContext
+ """
+ pageno = page - 1 # zero based
+ width = self.view.pagewidth
+ height = self.view.pageheight
+ self.FitThisSizeToPage(wx.Size(width, height))
+ dc = self.GetDC()
+ gc = dcGraphicsContext.Create(dc, height, have_cairo)
+ self.view.pdfdoc.RenderPage(gc, pageno)
+
+ def PrintViaBuffer(self, page):
+ """ Provide the data for page by drawing it as a bitmap to the printer DC
+ sfac needs to provide a high enough resolution bitmap for printing that
+ reduces anti-aliasing blur but be kept small to minimise printing time
+ """
+ sfac = 4.0
+ pageno = page - 1 # zero based
+ dc = self.GetDC()
+ width = self.view.pagewidth*sfac
+ height = self.view.pageheight*sfac
+ self.FitThisSizeToPage(wx.Size(width, height))
+ # Initialize the buffer bitmap.
+ abuffer = wx.EmptyBitmap(width, height)
+ mdc = wx.MemoryDC(abuffer)
+ gc = GraphicsContext.Create(mdc)
+ # white background
+ path = gc.CreatePath()
+ path.AddRectangle(0, 0, width, height)
+ gc.SetBrush(wx.WHITE_BRUSH)
+ gc.FillPath(path)
+ if mupdf:
+ self.view.pdfdoc.RenderPage(gc, pageno, sfac)
+ else:
+ gc.Translate(0, height)
+ gc.Scale(sfac, sfac)
+ self.view.pdfdoc.RenderPage(gc, pageno)
+ dc.DrawBitmap(abuffer, 0, 0)
+
+#------------------------------------------------------------------------------
+
+""" The following has been "borrowed" from from reportlab.pdfbase.pdfutils,
+ where it is used for testing, because the equivalent function in pyPdf
+ fails when attempting to decode an embedded JPEG image
+"""
+
+def _AsciiBase85DecodePYTHON(input):
+ """Decodes input using ASCII-Base85 coding.
+
+ This is not used - Acrobat Reader decodes for you
+ - but a round trip is essential for testing."""
+ #strip all whitespace
+ stripped = ''.join(input.split())
+ #check end
+ assert stripped[-2:] == '~>', 'Invalid terminator for Ascii Base 85 Stream'
+ stripped = stripped[:-2] #chop off terminator
+
+ #may have 'z' in it which complicates matters - expand them
+ stripped = stripped.replace('z','!!!!!')
+ # special rules apply if not a multiple of five bytes.
+ whole_word_count, remainder_size = divmod(len(stripped), 5)
+ #print '%d words, %d leftover' % (whole_word_count, remainder_size)
+ #assert remainder_size <> 1, 'invalid Ascii 85 stream!'
+ cut = 5 * whole_word_count
+ body, lastbit = stripped[0:cut], stripped[cut:]
+
+ out = [].append
+ for i in xrange(whole_word_count):
+ offset = i*5
+ c1 = ord(body[offset]) - 33
+ c2 = ord(body[offset+1]) - 33
+ c3 = ord(body[offset+2]) - 33
+ c4 = ord(body[offset+3]) - 33
+ c5 = ord(body[offset+4]) - 33
+
+ num = ((85L**4) * c1) + ((85**3) * c2) + ((85**2) * c3) + (85*c4) + c5
+
+ temp, b4 = divmod(num,256)
+ temp, b3 = divmod(temp,256)
+ b1, b2 = divmod(temp, 256)
+
+ assert num == 16777216 * b1 + 65536 * b2 + 256 * b3 + b4, 'dodgy code!'
+ out(chr(b1))
+ out(chr(b2))
+ out(chr(b3))
+ out(chr(b4))
+
+ #decode however many bytes we have as usual
+ if remainder_size > 0:
+ while len(lastbit) < 5:
+ lastbit = lastbit + '!'
+ c1 = ord(lastbit[0]) - 33
+ c2 = ord(lastbit[1]) - 33
+ c3 = ord(lastbit[2]) - 33
+ c4 = ord(lastbit[3]) - 33
+ c5 = ord(lastbit[4]) - 33
+ num = (((85*c1+c2)*85+c3)*85+c4)*85L + (c5
+ +(0,0,0xFFFFFF,0xFFFF,0xFF)[remainder_size])
+ temp, b4 = divmod(num,256)
+ temp, b3 = divmod(temp,256)
+ b1, b2 = divmod(temp, 256)
+ assert num == 16777216 * b1 + 65536 * b2 + 256 * b3 + b4, 'dodgy code!'
+ #print 'decoding: %d %d %d %d %d -> %d -> %d %d %d %d' % (
+ # c1,c2,c3,c4,c5,num,b1,b2,b3,b4)
+
+ #the last character needs 1 adding; the encoding loses
+ #data by rounding the number to x bytes, and when
+ #divided repeatedly we get one less
+ if remainder_size == 2:
+ lastword = chr(b1)
+ elif remainder_size == 3:
+ lastword = chr(b1) + chr(b2)
+ elif remainder_size == 4:
+ lastword = chr(b1) + chr(b2) + chr(b3)
+ else:
+ lastword = ''
+ out(lastword)
+
+ #terminator code for ascii 85
+ return ''.join(out.__self__)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfwin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfwin.py
new file mode 100644
index 0000000..73fadba
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfwin.py
@@ -0,0 +1,296 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.pdfwin
+# Purpose: A class that allows the use of the Acrobat PDF reader
+# ActiveX control
+#
+# Author: Robin Dunn
+#
+# Created: 22-March-2004
+# RCS-ID: $Id$
+# Copyright: (c) 2008 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import wx
+
+_min_adobe_version = None
+
+def get_min_adobe_version():
+ return _min_adobe_version
+
+def get_acroversion():
+ " Included for backward compatibility"
+ return _min_adobe_version
+
+#----------------------------------------------------------------------
+
+if wx.PlatformInfo[1] == 'wxMSW':
+ import wx.lib.activex
+ import comtypes.client as cc
+ import comtypes
+ import ctypes
+
+ try: # Adobe Reader >= 7.0
+ cc.GetModule( ('{05BFD3F1-6319-4F30-B752-C7A22889BCC4}', 1, 0) )
+ progID = 'AcroPDF.PDF.1'
+ _min_adobe_version = 7.0
+ except:
+ try: # Adobe Reader 5 or 6
+ cc.GetModule( ('{CA8A9783-280D-11CF-A24D-444553540000}', 1, 0) )
+ progID = 'PDF.PdfCtrl.5'
+ _min_adobe_version = 5.0
+ except:
+ pass # Adobe Reader not installed (progID is not defined)
+ # Use get_min_adobe_version() before instantiating PDFWindow
+
+ #------------------------------------------------------------------------------
+
+ class PDFWindow(wx.lib.activex.ActiveXCtrl):
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name='PDFWindow'):
+ wx.lib.activex.ActiveXCtrl.__init__(self, parent, progID,
+ id, pos, size, style, name)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroyWindow)
+
+ def OnDestroyWindow(self, event):
+ wx.CallAfter(self.FreeDlls)
+
+ def FreeDlls(self):
+ """
+ Unloads any DLLs that are no longer in use when all COM object instances are
+ released. This prevents the error 'The instruction at "0x0700609c" referenced
+ memory at "0x00000014". The memory could not be read' when application closes
+ """
+ ctypes.windll.ole32.CoFreeUnusedLibraries()
+
+ def LoadFile(self, fileName):
+ """
+ Opens and displays the specified document within the browser.
+ """
+ return self.ctrl.LoadFile(fileName)
+
+ def GetVersions(self):
+ """
+ Deprecated: No longer available - do not use.
+ """
+ return self.ctrl.GetVersions()
+
+ def Print(self):
+ """
+ Prints the document according to the specified options in a user dialog box.
+ """
+ return self.ctrl.Print()
+
+ def goBackwardStack(self):
+ """
+ Goes to the previous view on the view stack, if it exists.
+ """
+ return self.ctrl.goBackwardStack()
+
+ def goForwardStack(self):
+ """
+ Goes to the next view on the view stack, if it exists.
+ """
+ return self.ctrl.goForwardStack()
+
+ def gotoFirstPage(self):
+ """
+ Goes to the first page in the document.
+ """
+ return self.ctrl.gotoFirstPage()
+
+ def gotoLastPage(self):
+ """
+ Goes to the last page in the document.
+ """
+ return self.ctrl.gotoLastPage()
+
+ def gotoNextPage(self):
+ """
+ Goes to the next page in the document, if it exists
+ """
+ return self.ctrl.gotoNextPage()
+
+ def gotoPreviousPage(self):
+ """
+ Goes to the previous page in the document, if it exists.
+ """
+ return self.ctrl.gotoPreviousPage()
+
+ def printAll(self):
+ """
+ Prints the entire document without displaying a user
+ dialog box. The current printer, page settings, and job
+ settings are used. This method returns immediately, even
+ if the printing has not completed.
+ """
+ return self.ctrl.printAll()
+
+ def printAllFit(self, shrinkToFit):
+ """
+ Prints the entire document without a user dialog box, and
+ (if shrinkToFit) shrinks pages as needed to fit the
+ imageable area of a page in the printer.
+ """
+ return self.ctrl.printAllFit(shrinkToFit)
+
+ def printPages(self, from_, to):
+ """
+ Prints the specified pages without displaying a user dialog box.
+ """
+ return self.ctrl.printPages(from_, to)
+
+ def printPagesFit(self, from_, to, shrinkToFit):
+ """
+ Prints the specified pages without displaying a user
+ dialog box, and (if shrinkToFit) shrinks pages as needed
+ to fit the imageable area of a page in the printer.
+ """
+ return self.ctrl.printPagesFit( from_, to, shrinkToFit)
+
+ def printWithDialog(self):
+ """
+ Prints the document according to the specified options in
+ a user dialog box. These options may include embedded
+ printing and specifying which printer is to be used.
+
+ NB. The page range in the dialog defaults to
+ 'From Page 1 to 1' - Use Print() above instead. (dfh)
+ """
+ return self.ctrl.printWithDialog()
+
+ def setCurrentHighlight(self, a, b, c, d):
+ return self.ctrl.setCurrentHighlight(a, b, c, d)
+
+ def setCurrentPage(self, npage):
+ """
+ Goes to the specified page in the document. Maintains the
+ current location within the page and zoom level. npage is
+ the page number of the destination page. The first page
+ in a document is page 0.
+
+ ## Oh no it isn't! The first page is 1 (dfh)
+ """
+ return self.ctrl.setCurrentPage(npage)
+
+ def setLayoutMode(self, layoutMode):
+ """
+ LayoutMode possible values:
+
+ ================= ====================================
+ 'DontCare' use the current user preference
+ 'SinglePage' use single page mode (as in pre-Acrobat 3.0 viewers)
+ 'OneColumn' use one-column continuous mode
+ 'TwoColumnLeft' use two-column continuous mode, first page on the left
+ 'TwoColumnRight' use two-column continuous mode, first page on the right
+ ================= ====================================
+ """
+ return self.ctrl.setLayoutMode(layoutMode)
+
+ def setNamedDest(self, namedDest):
+ """
+ Changes the page view to the named destination in the specified string.
+ """
+ return self.ctrl.setNamedDest(namedDest)
+
+ def setPageMode(self, pageMode):
+ """
+ Sets the page mode to display the document only, or to
+ additionally display bookmarks or thumbnails. pageMode =
+ 'none' or 'bookmarks' or 'thumbs'.
+
+ ## NB.'thumbs' is case-sensitive, the other are not (dfh)
+ """
+ return self.ctrl.setPageMode(pageMode)
+
+ def setShowScrollbars(self, On):
+ """
+ Determines whether scrollbars will appear in the document
+ view.
+
+ ## NB. If scrollbars are off, the navigation tools disappear as well (dfh)
+ """
+ return self.ctrl.setShowScrollbars(On)
+
+ def setShowToolbar(self, On):
+ """
+ Determines whether a toolbar will appear in the application.
+ """
+ return self.ctrl.setShowToolbar(On)
+
+ def setView(self, viewMode):
+ """
+ Determines how the page will fit in the current view.
+ viewMode possible values:
+
+ ======== ==============================================
+ 'Fit' fits whole page within the window both vertically and horizontally.
+ 'FitH' fits the width of the page within the window.
+ 'FitV' fits the height of the page within the window.
+ 'FitB' fits bounding box within the window both vertically and horizontally.
+ 'FitBH' fits the width of the bounding box within the window.
+ 'FitBV' fits the height of the bounding box within the window.
+ ======== ==============================================
+ """
+ return self.ctrl.setView(viewMode)
+
+ def setViewRect(self, left, top, width, height):
+ """
+ Sets the view rectangle according to the specified coordinates.
+
+ :param left: The upper left horizontal coordinate.
+ :param top: The vertical coordinate in the upper left corner.
+ :param width: The horizontal width of the rectangle.
+ :param height: The vertical height of the rectangle.
+ """
+ return self.ctrl.setViewRect(left, top, width, height)
+
+ def setViewScroll(self, viewMode, offset):
+ """
+ Sets the view of a page according to the specified string.
+ Depending on the view mode, the page is either scrolled to
+ the right or scrolled down by the amount specified in
+ offset. Possible values of viewMode are as in setView
+ above. offset is the horizontal or vertical coordinate
+ positioned either at the left or top edge.
+ """
+ return self.ctrl.setViewScroll(viewMode, offset)
+
+ def setZoom(self, percent):
+ """
+ Sets the magnification according to the specified value
+ expressed as a percentage (float)
+ """
+ return self.ctrl.setZoom(percent)
+
+ def setZoomScroll(self, percent, left, top):
+ """
+ Sets the magnification according to the specified value,
+ and scrolls the page view both horizontally and vertically
+ according to the specified amounts.
+
+ :param left: the horizontal coordinate positioned at the left edge.
+ :param top: the vertical coordinate positioned at the top edge.
+ """
+ return self.ctrl.setZoomScroll(percent, left, top)
+
+
+#------------------------------------------------------------------------------
+
+
+
+
+if __name__ == '__main__':
+ app = wx.App(False)
+ frm = wx.Frame(None, title="AX Test Window")
+
+ pdf = PDFWindow(frm)
+
+ frm.Show()
+ import wx.lib.inspection
+ wx.lib.inspection.InspectionTool().Show()
+ app.MainLoop()
+
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfwin_old.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfwin_old.py
new file mode 100644
index 0000000..19b73ae
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pdfwin_old.py
@@ -0,0 +1,790 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.pdfwin
+# Purpose: A class that allows the use of the Acrobat PDF reader
+# ActiveX control
+#
+# Author: Robin Dunn
+#
+# Created: 22-March-2004
+# RCS-ID: $Id: pdfwin.py 49208 2007-10-18 00:40:21Z RD $
+# Copyright: (c) 2004 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import wx
+
+#----------------------------------------------------------------------
+
+_acroversion = None
+
+def get_acroversion():
+ " Return version of Adobe Acrobat executable or None"
+ global _acroversion
+ if _acroversion == None and wx.PlatformInfo[1] == 'wxMSW':
+ import _winreg
+ regKey = _winreg.HKEY_LOCAL_MACHINE
+ acrokeys, acroversions = [], []
+ try:
+ adobesoft = _winreg.OpenKey(regKey, r'Software\Adobe')
+ except WindowsError:
+ regKey = _winreg.HKEY_CURRENT_USER
+ adobesoft = _winreg.OpenKey(regKey, r'Software\Adobe')
+
+ for index in range(_winreg.QueryInfoKey(adobesoft)[0]):
+ key = _winreg.EnumKey(adobesoft, index)
+ if "acrobat" in key.lower():
+ acrokeys.append(_winreg.OpenKey(regKey, 'Software\\Adobe\\%s' % key))
+ for acrokey in acrokeys:
+ for index in range(_winreg.QueryInfoKey(acrokey)[0]):
+ key = _winreg.EnumKey(acrokey, index)
+ try:
+ acroversions.append(float(key))
+ except:
+ pass
+ acroversions.sort(reverse=True)
+ if acroversions:
+ _acroversion = acroversions[0]
+ return _acroversion
+
+
+#----------------------------------------------------------------------
+
+# The ActiveX module from Acrobat 7.0 has changed and it seems to now
+# require much more from the container than what our wx.activex module
+# provides. If we try to use it via wx.activex then Acrobat crashes.
+# So instead we will use Internet Explorer (via the win32com modules
+# so we can use better dynamic dispatch) and embed the Acrobat control
+# within that. Acrobat provides the IAcroAXDocShim COM class that is
+# accessible via the IE window's Document property after a PDF file
+# has been loaded.
+#
+# Details of the Acrobat reader methods can be found in
+# http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACOverview.pdf
+# http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACReference.pdf
+#
+# Co-ordinates passed as parameters are in points (1/72 inch).
+
+
+if get_acroversion() >= 7.0:
+
+ from wx.lib.activexwrapper import MakeActiveXClass
+ import win32com.client.gencache
+ _browserModule = win32com.client.gencache.EnsureModule(
+ "{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 1)
+
+ class PDFWindowError(RuntimeError):
+ def __init__(self):
+ RuntimeError.__init__(self, "A PDF must be loaded before calling this method.")
+
+
+ class PDFWindow(wx.Panel):
+ def __init__(self, *args, **kw):
+ wx.Panel.__init__(self, *args, **kw)
+
+ # Make a new class that derives from the WebBrowser class
+ # in the COM module imported above. This class also
+ # derives from wxWindow and implements the machinery
+ # needed to integrate the two worlds.
+ _WebBrowserClass = MakeActiveXClass(_browserModule.WebBrowser)
+ self.ie = _WebBrowserClass(self, -1)
+ sizer = wx.BoxSizer()
+ sizer.Add(self.ie, 1, wx.EXPAND)
+ self.SetSizer(sizer)
+
+
+ def LoadFile(self, fileName):
+ """
+ Opens and displays the specified document within the browser.
+ """
+ if self.ie.Document:
+ return self.ie.Document.LoadFile(fileName)
+ else:
+ self.ie.Navigate2(fileName)
+ return True # can we sense failure at this point?
+
+ def GetVersions(self):
+ """
+ Deprecated: No longer available - do not use.
+ """
+ if self.ie.Document:
+ return self.ie.Document.GetVersions()
+ else:
+ raise PDFWindowError()
+
+ def Print(self):
+ """
+ Prints the document according to the specified options in a user dialog box.
+ """
+ if self.ie.Document:
+ return self.ie.Document.Print()
+ else:
+ raise PDFWindowError()
+
+ def goBackwardStack(self):
+ """
+ Goes to the previous view on the view stack, if it exists.
+ """
+ if self.ie.Document:
+ return self.ie.Document.goBackwardStack()
+ else:
+ raise PDFWindowError()
+
+ def goForwardStack(self):
+ """
+ Goes to the next view on the view stack, if it exists.
+ """
+ if self.ie.Document:
+ return self.ie.Document.goForwardStack()
+ else:
+ raise PDFWindowError()
+
+ def gotoFirstPage(self):
+ """
+ Goes to the first page in the document.
+ """
+ if self.ie.Document:
+ return self.ie.Document.gotoFirstPage()
+ else:
+ raise PDFWindowError()
+
+ def gotoLastPage(self):
+ """
+ Goes to the last page in the document.
+ """
+ if self.ie.Document:
+ return self.ie.Document.gotoLastPage()
+ else:
+ raise PDFWindowError()
+
+ def gotoNextPage(self):
+ """
+ Goes to the next page in the document, if it exists
+ """
+ if self.ie.Document:
+ return self.ie.Document.gotoNextPage()
+ else:
+ raise PDFWindowError()
+
+ def gotoPreviousPage(self):
+ """
+ Goes to the previous page in the document, if it exists.
+ """
+ if self.ie.Document:
+ return self.ie.Document.gotoPreviousPage()
+ else:
+ raise PDFWindowError()
+
+ def printAll(self):
+ """
+ Prints the entire document without displaying a user
+ dialog box. The current printer, page settings, and job
+ settings are used. This method returns immediately, even
+ if the printing has not completed.
+ """
+ if self.ie.Document:
+ return self.ie.Document.printAll()
+ else:
+ raise PDFWindowError()
+
+ def printAllFit(self, shrinkToFit):
+ """
+ Prints the entire document without a user dialog box, and
+ (if shrinkToFit) shrinks pages as needed to fit the
+ imageable area of a page in the printer.
+ """
+ if self.ie.Document:
+ return self.ie.Document.printAllFit(shrinkToFit)
+ else:
+ raise PDFWindowError()
+
+ def printPages(self, from_, to):
+ """
+ Prints the specified pages without displaying a user dialog box.
+ """
+ if self.ie.Document:
+ return self.ie.Document.printPages(from_, to)
+ else:
+ raise PDFWindowError()
+
+ def printPagesFit(self, from_, to, shrinkToFit):
+ """
+ Prints the specified pages without displaying a user
+ dialog box, and (if shrinkToFit) shrinks pages as needed
+ to fit the imageable area of a page in the printer.
+ """
+ if self.ie.Document:
+ return self.ie.Document.printPagesFit( from_, to, shrinkToFit)
+ else:
+ raise PDFWindowError()
+
+ def printWithDialog(self):
+ """
+ Prints the document according to the specified options in
+ a user dialog box. These options may include embedded
+ printing and specifying which printer is to be used.
+
+ NB. The page range in the dialog defaults to
+ 'From Page 1 to 1' - Use Print() above instead. (dfh)
+ """
+ if self.ie.Document:
+ return self.ie.Document.printWithDialog()
+ else:
+ raise PDFWindowError()
+
+ def setCurrentHighlight(self, a, b, c, d):
+ if self.ie.Document:
+ return self.ie.Document.setCurrentHighlight(a, b, c, d)
+ else:
+ raise PDFWindowError()
+
+ def setCurrentPage(self, npage):
+ """
+ Goes to the specified page in the document. Maintains the
+ current location within the page and zoom level. npage is
+ the page number of the destination page. The first page
+ in a document is page 0.
+
+ ## Oh no it isn't! The first page is 1 (dfh)
+ """
+ if self.ie.Document:
+ return self.ie.Document.setCurrentPage(npage)
+ else:
+ raise PDFWindowError()
+
+ def setLayoutMode(self, layoutMode):
+ """
+ LayoutMode possible values:
+
+ ================= ====================================
+ 'DontCare' use the current user preference
+ 'SinglePage' use single page mode (as in pre-Acrobat
+ 3.0 viewers)
+ 'OneColumn' use one-column continuous mode
+ 'TwoColumnLeft' use two-column continuous mode, first
+ page on the left
+ 'TwoColumnRight' use two-column continuous mode, first
+ page on the right
+ ================= ====================================
+ """
+ if self.ie.Document:
+ return self.ie.Document.setLayoutMode(layoutMode)
+ else:
+ raise PDFWindowError()
+
+ def setNamedDest(self, namedDest):
+ """
+ Changes the page view to the named destination in the specified string.
+ """
+ if self.ie.Document:
+ return self.ie.Document.setNamedDest(namedDest)
+ else:
+ raise PDFWindowError()
+
+ def setPageMode(self, pageMode):
+ """
+ Sets the page mode to display the document only, or to
+ additionally display bookmarks or thumbnails. pageMode =
+ 'none' or 'bookmarks' or 'thumbs'.
+
+ ## NB.'thumbs' is case-sensitive, the other are not (dfh)
+ """
+ if self.ie.Document:
+ return self.ie.Document.setPageMode(pageMode)
+ else:
+ raise PDFWindowError()
+
+ def setShowScrollbars(self, On):
+ """
+ Determines whether scrollbars will appear in the document
+ view.
+
+ ## NB. If scrollbars are off, the navigation tools disappear as well (dfh)
+ """
+ if self.ie.Document:
+ return self.ie.Document.setShowScrollbars(On)
+ else:
+ raise PDFWindowError()
+
+ def setShowToolbar(self, On):
+ """
+ Determines whether a toolbar will appear in the application.
+ """
+ if self.ie.Document:
+ return self.ie.Document.setShowToolbar(On)
+ else:
+ raise PDFWindowError()
+
+ def setView(self, viewMode):
+ """
+ Determines how the page will fit in the current view.
+ viewMode possible values:
+
+ ======== ==============================================
+ 'Fit' fits whole page within the window both vertically
+ and horizontally.
+ 'FitH' fits the width of the page within the window.
+ 'FitV' fits the height of the page within the window.
+ 'FitB' fits bounding box within the window both vertically
+ and horizontally.
+ 'FitBH' fits the width of the bounding box within the window.
+ 'FitBV' fits the height of the bounding box within the window.
+ ======== ==============================================
+ """
+ if self.ie.Document:
+ return self.ie.Document.setView(viewMode)
+ else:
+ raise PDFWindowError()
+
+ def setViewRect(self, left, top, width, height):
+ """
+ Sets the view rectangle according to the specified coordinates.
+
+ :param left: The upper left horizontal coordinate.
+ :param top: The vertical coordinate in the upper left corner.
+ :param width: The horizontal width of the rectangle.
+ :param height: The vertical height of the rectangle.
+ """
+ if self.ie.Document:
+ return self.ie.Document.setViewRect(left, top, width, height)
+ else:
+ raise PDFWindowError()
+
+ def setViewScroll(self, viewMode, offset):
+ """
+ Sets the view of a page according to the specified string.
+ Depending on the view mode, the page is either scrolled to
+ the right or scrolled down by the amount specified in
+ offset. Possible values of viewMode are as in setView
+ above. offset is the horizontal or vertical coordinate
+ positioned either at the left or top edge.
+ """
+ if self.ie.Document:
+ return self.ie.Document.setViewScroll(viewMode, offset)
+ else:
+ raise PDFWindowError()
+
+ def setZoom(self, percent):
+ """
+ Sets the magnification according to the specified value
+ expressed as a percentage (float)
+ """
+ if self.ie.Document:
+ return self.ie.Document.setZoom(percent)
+ else:
+ raise PDFWindowError()
+
+ def setZoomScroll(self, percent, left, top):
+ """
+ Sets the magnification according to the specified value,
+ and scrolls the page view both horizontally and vertically
+ according to the specified amounts.
+
+ :param left: the horizontal coordinate positioned at the left edge.
+ :param top: the vertical coordinate positioned at the top edge.
+ """
+ if self.ie.Document:
+ return self.ie.Document.setZoomScroll(percent, left, top)
+ else:
+ raise PDFWindowError()
+
+
+
+elif get_acroversion() is not None:
+ import wx.activex
+
+ clsID = '{CA8A9780-280D-11CF-A24D-444553540000}'
+ progID = 'AcroPDF.PDF.1'
+
+
+ # Create eventTypes and event binders
+ wxEVT_Error = wx.activex.RegisterActiveXEvent('OnError')
+ wxEVT_Message = wx.activex.RegisterActiveXEvent('OnMessage')
+
+ EVT_Error = wx.PyEventBinder(wxEVT_Error, 1)
+ EVT_Message = wx.PyEventBinder(wxEVT_Message, 1)
+
+
+ # Derive a new class from ActiveXWindow
+ class PDFWindow(wx.activex.ActiveXWindow):
+ def __init__(self, parent, ID=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name='PDFWindow'):
+ wx.activex.ActiveXWindow.__init__(self, parent,
+ wx.activex.CLSID('{CA8A9780-280D-11CF-A24D-444553540000}'),
+ ID, pos, size, style, name)
+
+ # Methods exported by the ActiveX object
+ def QueryInterface(self, riid):
+ return self.CallAXMethod('QueryInterface', riid)
+
+ def AddRef(self):
+ return self.CallAXMethod('AddRef')
+
+ def Release(self):
+ return self.CallAXMethod('Release')
+
+ def GetTypeInfoCount(self):
+ return self.CallAXMethod('GetTypeInfoCount')
+
+ def GetTypeInfo(self, itinfo, lcid):
+ return self.CallAXMethod('GetTypeInfo', itinfo, lcid)
+
+ def GetIDsOfNames(self, riid, rgszNames, cNames, lcid):
+ return self.CallAXMethod('GetIDsOfNames', riid, rgszNames, cNames, lcid)
+
+ def Invoke(self, dispidMember, riid, lcid, wFlags, pdispparams):
+ return self.CallAXMethod('Invoke', dispidMember, riid, lcid, wFlags, pdispparams)
+
+ def LoadFile(self, fileName):
+ return self.CallAXMethod('LoadFile', fileName)
+
+ def setShowToolbar(self, On):
+ return self.CallAXMethod('setShowToolbar', On)
+
+ def gotoFirstPage(self):
+ return self.CallAXMethod('gotoFirstPage')
+
+ def gotoLastPage(self):
+ return self.CallAXMethod('gotoLastPage')
+
+ def gotoNextPage(self):
+ return self.CallAXMethod('gotoNextPage')
+
+ def gotoPreviousPage(self):
+ return self.CallAXMethod('gotoPreviousPage')
+
+ def setCurrentPage(self, n):
+ return self.CallAXMethod('setCurrentPage', n)
+
+ def goForwardStack(self):
+ return self.CallAXMethod('goForwardStack')
+
+ def goBackwardStack(self):
+ return self.CallAXMethod('goBackwardStack')
+
+ def setPageMode(self, pageMode):
+ return self.CallAXMethod('setPageMode', pageMode)
+
+ def setLayoutMode(self, layoutMode):
+ return self.CallAXMethod('setLayoutMode', layoutMode)
+
+ def setNamedDest(self, namedDest):
+ return self.CallAXMethod('setNamedDest', namedDest)
+
+ def Print(self):
+ return self.CallAXMethod('Print')
+
+ def printWithDialog(self):
+ return self.CallAXMethod('printWithDialog')
+
+ def setZoom(self, percent):
+ return self.CallAXMethod('setZoom', percent)
+
+ def setZoomScroll(self, percent, left, top):
+ return self.CallAXMethod('setZoomScroll', percent, left, top)
+
+ def setView(self, viewMode):
+ return self.CallAXMethod('setView', viewMode)
+
+ def setViewScroll(self, viewMode, offset):
+ return self.CallAXMethod('setViewScroll', viewMode, offset)
+
+ def setViewRect(self, left, top, width, height):
+ return self.CallAXMethod('setViewRect', left, top, width, height)
+
+ def printPages(self, from_, to):
+ return self.CallAXMethod('printPages', from_, to)
+
+ def printPagesFit(self, from_, to, shrinkToFit):
+ return self.CallAXMethod('printPagesFit', from_, to, shrinkToFit)
+
+ def printAll(self):
+ return self.CallAXMethod('printAll')
+
+ def printAllFit(self, shrinkToFit):
+ return self.CallAXMethod('printAllFit', shrinkToFit)
+
+ def setShowScrollbars(self, On):
+ return self.CallAXMethod('setShowScrollbars', On)
+
+ def GetVersions(self):
+ return self.CallAXMethod('GetVersions')
+
+ def setCurrentHighlight(self, a, b, c, d):
+ return self.CallAXMethod('setCurrentHighlight', a, b, c, d)
+
+ def postMessage(self, strArray):
+ return self.CallAXMethod('postMessage', strArray)
+
+ # Getters, Setters and properties
+ def _get_src(self):
+ return self.GetAXProp('src')
+ def _set_src(self, src):
+ self.SetAXProp('src', src)
+ src = property(_get_src, _set_src)
+
+ def _get_messageHandler(self):
+ return self.GetAXProp('messageHandler')
+ def _set_messageHandler(self, messageHandler):
+ self.SetAXProp('messageHandler', messageHandler)
+ messagehandler = property(_get_messageHandler, _set_messageHandler)
+
+
+# PROPERTIES
+# --------------------
+# src
+# type:string arg:string canGet:True canSet:True
+#
+# messagehandler
+# type:VT_VARIANT arg:VT_VARIANT canGet:True canSet:True
+#
+#
+#
+#
+# METHODS
+# --------------------
+# QueryInterface
+# retType: VT_VOID
+# params:
+# riid
+# in:True out:False optional:False type:unsupported type 29
+# ppvObj
+# in:False out:True optional:False type:unsupported type 26
+#
+# AddRef
+# retType: int
+#
+# Release
+# retType: int
+#
+# GetTypeInfoCount
+# retType: VT_VOID
+# params:
+# pctinfo
+# in:False out:True optional:False type:int
+#
+# GetTypeInfo
+# retType: VT_VOID
+# params:
+# itinfo
+# in:True out:False optional:False type:int
+# lcid
+# in:True out:False optional:False type:int
+# pptinfo
+# in:False out:True optional:False type:unsupported type 26
+#
+# GetIDsOfNames
+# retType: VT_VOID
+# params:
+# riid
+# in:True out:False optional:False type:unsupported type 29
+# rgszNames
+# in:True out:False optional:False type:unsupported type 26
+# cNames
+# in:True out:False optional:False type:int
+# lcid
+# in:True out:False optional:False type:int
+# rgdispid
+# in:False out:True optional:False type:int
+#
+# Invoke
+# retType: VT_VOID
+# params:
+# dispidMember
+# in:True out:False optional:False type:int
+# riid
+# in:True out:False optional:False type:unsupported type 29
+# lcid
+# in:True out:False optional:False type:int
+# wFlags
+# in:True out:False optional:False type:int
+# pdispparams
+# in:True out:False optional:False type:unsupported type 29
+# pvarResult
+# in:False out:True optional:False type:VT_VARIANT
+# pexcepinfo
+# in:False out:True optional:False type:unsupported type 29
+# puArgErr
+# in:False out:True optional:False type:int
+#
+# LoadFile
+# retType: bool
+# params:
+# fileName
+# in:True out:False optional:False type:string
+#
+# setShowToolbar
+# retType: VT_VOID
+# params:
+# On
+# in:True out:False optional:False type:bool
+#
+# gotoFirstPage
+# retType: VT_VOID
+#
+# gotoLastPage
+# retType: VT_VOID
+#
+# gotoNextPage
+# retType: VT_VOID
+#
+# gotoPreviousPage
+# retType: VT_VOID
+#
+# setCurrentPage
+# retType: VT_VOID
+# params:
+# n
+# in:True out:False optional:False type:int
+#
+# goForwardStack
+# retType: VT_VOID
+#
+# goBackwardStack
+# retType: VT_VOID
+#
+# setPageMode
+# retType: VT_VOID
+# params:
+# pageMode
+# in:True out:False optional:False type:string
+#
+# setLayoutMode
+# retType: VT_VOID
+# params:
+# layoutMode
+# in:True out:False optional:False type:string
+#
+# setNamedDest
+# retType: VT_VOID
+# params:
+# namedDest
+# in:True out:False optional:False type:string
+#
+# Print
+# retType: VT_VOID
+#
+# printWithDialog
+# retType: VT_VOID
+#
+# setZoom
+# retType: VT_VOID
+# params:
+# percent
+# in:True out:False optional:False type:double
+#
+# setZoomScroll
+# retType: VT_VOID
+# params:
+# percent
+# in:True out:False optional:False type:double
+# left
+# in:True out:False optional:False type:double
+# top
+# in:True out:False optional:False type:double
+#
+# setView
+# retType: VT_VOID
+# params:
+# viewMode
+# in:True out:False optional:False type:string
+#
+# setViewScroll
+# retType: VT_VOID
+# params:
+# viewMode
+# in:True out:False optional:False type:string
+# offset
+# in:True out:False optional:False type:double
+#
+# setViewRect
+# retType: VT_VOID
+# params:
+# left
+# in:True out:False optional:False type:double
+# top
+# in:True out:False optional:False type:double
+# width
+# in:True out:False optional:False type:double
+# height
+# in:True out:False optional:False type:double
+#
+# printPages
+# retType: VT_VOID
+# params:
+# from
+# in:True out:False optional:False type:int
+# to
+# in:True out:False optional:False type:int
+#
+# printPagesFit
+# retType: VT_VOID
+# params:
+# from
+# in:True out:False optional:False type:int
+# to
+# in:True out:False optional:False type:int
+# shrinkToFit
+# in:True out:False optional:False type:bool
+#
+# printAll
+# retType: VT_VOID
+#
+# printAllFit
+# retType: VT_VOID
+# params:
+# shrinkToFit
+# in:True out:False optional:False type:bool
+#
+# setShowScrollbars
+# retType: VT_VOID
+# params:
+# On
+# in:True out:False optional:False type:bool
+#
+# GetVersions
+# retType: VT_VARIANT
+#
+# setCurrentHightlight
+# retType: VT_VOID
+# params:
+# a
+# in:True out:False optional:False type:int
+# b
+# in:True out:False optional:False type:int
+# c
+# in:True out:False optional:False type:int
+# d
+# in:True out:False optional:False type:int
+#
+# setCurrentHighlight
+# retType: VT_VOID
+# params:
+# a
+# in:True out:False optional:False type:int
+# b
+# in:True out:False optional:False type:int
+# c
+# in:True out:False optional:False type:int
+# d
+# in:True out:False optional:False type:int
+#
+# postMessage
+# retType: VT_VOID
+# params:
+# strArray
+# in:True out:False optional:False type:VT_VARIANT
+#
+#
+#
+#
+# EVENTS
+# --------------------
+# Error
+# retType: VT_VOID
+#
+# Message
+# retType: VT_VOID
+#
+#
+#
+#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/platebtn.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/platebtn.py
new file mode 100644
index 0000000..966a149
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/platebtn.py
@@ -0,0 +1,761 @@
+###############################################################################
+# Name: platebtn.py #
+# Purpose: PlateButton is a flat label button with support for bitmaps and #
+# drop menu. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Control Library: PlateButton
+
+The PlateButton is a custom owner drawn flat button, that in many ways emulates
+the buttons found the bookmark bar of the Safari browser. It can be used as a
+drop in replacement for wx.Button/wx.BitmapButton under most circumstances. It
+also offers a wide range of options for customizing its appearance, a
+description of each of the main style settings is listed below.
+
+Main Button Styles:
+Any combination of the following values may be passed to the constructor's style
+keyword parameter.
+
+PB_STYLE_DEFAULT:
+Creates a flat label button with rounded corners, the highlight for mouse over
+and press states is based off of the hightlight color from the systems current
+theme.
+
+PB_STYLE_GRADIENT:
+The highlight and press states are drawn with gradient using the current
+highlight color.
+
+PB_STYLE_SQUARE:
+Instead of the default rounded shape use a rectangular shaped button with
+square edges.
+
+PB_STYLE_NOBG:
+This style only has an effect on Windows but does not cause harm to use on the
+platforms. It should only be used when the control is shown on a panel or other
+window that has a non solid color for a background. i.e a gradient or image is
+painted on the background of the parent window. If used on a background with
+a solid color it may cause the control to loose its transparent appearance.
+
+PB_STYLE_DROPARROW:
+Add a drop button arrow to the button that will send a separate event when
+clicked on.
+
+Other attributes can be configured after the control has been created. The
+settings that are currently available are as follows:
+
+ - SetBitmap: Change/Add the bitmap at any time and the control will resize and
+ refresh to display it.
+ - SetLabelColor: Explicitly set text colors
+ - SetMenu: Set the button to have a popupmenu. When a menu is set a small drop
+ arrow will be drawn on the button that can then be clicked to show
+ a menu.
+ - SetPressColor: Use a custom highlight color
+
+
+Overridden Methods Inherited from PyControl:
+
+ - SetFont: Changing the font is one way to set the size of the button, by
+ default the control will inherit its font from its parent.
+
+ - SetWindowVariant: Setting the window variant will cause the control to
+ resize to the corresponding variant size. However if the
+ button is using a bitmap the bitmap will remain unchanged
+ and only the font will be adjusted.
+
+Requirements:
+ - python2.4 or higher
+ - wxPython2.8 or higher
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: platebtn.py 69230 2011-09-29 15:23:52Z CJP $"
+__revision__ = "$Revision: 69230 $"
+
+__all__ = ["PlateButton",
+ "PLATE_NORMAL", "PLATE_PRESSED", "PLATE_HIGHLIGHT",
+
+ "PB_STYLE_DEFAULT", "PB_STYLE_GRADIENT", "PB_STYLE_SQUARE",
+ "PB_STYLE_NOBG", "PB_STYLE_DROPARROW", "PB_STYLE_TOGGLE",
+
+ "EVT_PLATEBTN_DROPARROW_PRESSED"]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.lib.newevent
+
+# Local Imports
+from wx.lib.colourutils import *
+
+#-----------------------------------------------------------------------------#
+# Button States
+PLATE_NORMAL = 0
+PLATE_PRESSED = 1
+PLATE_HIGHLIGHT = 2
+
+# Button Styles
+PB_STYLE_DEFAULT = 1 # Normal Flat Background
+PB_STYLE_GRADIENT = 2 # Gradient Filled Background
+PB_STYLE_SQUARE = 4 # Use square corners instead of rounded
+PB_STYLE_NOBG = 8 # Useful on Windows to get a transparent appearance
+ # when the control is shown on a non solid background
+PB_STYLE_DROPARROW = 16 # Draw drop arrow and fire EVT_PLATEBTN_DROPRROW_PRESSED event
+PB_STYLE_TOGGLE = 32 # Stay pressed until clicked again
+
+#-----------------------------------------------------------------------------#
+
+# EVT_BUTTON used for normal event notification
+# EVT_TOGGLE_BUTTON used for toggle button mode notification
+PlateBtnDropArrowPressed, EVT_PLATEBTN_DROPARROW_PRESSED = wx.lib.newevent.NewEvent()
+
+#-----------------------------------------------------------------------------#
+
+class PlateButton(wx.PyControl):
+ """PlateButton is a custom type of flat button with support for
+ displaying bitmaps and having an attached dropdown menu.
+
+ """
+ def __init__(self, parent, id=wx.ID_ANY, label='', bmp=None,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=PB_STYLE_DEFAULT, name=wx.ButtonNameStr):
+ """Create a PlateButton
+
+ :keyword string `label`: Buttons label text
+ :keyword Bitmap `bmp`: Buttons bitmap
+ :keyword `style`: Button style
+
+ """
+ super(PlateButton, self).__init__(parent, id, pos, size,
+ wx.BORDER_NONE|wx.TRANSPARENT_WINDOW,
+ name=name)
+
+ # Attributes
+ self.InheritAttributes()
+ self._bmp = dict(enable=None, disable=None)
+ if bmp is not None:
+ assert isinstance(bmp, wx.Bitmap) and bmp.IsOk()
+ self._bmp['enable'] = bmp
+ img = bmp.ConvertToImage()
+ img = img.ConvertToGreyscale(.795, .073, .026) #(.634, .224, .143)
+ self._bmp['disable'] = wx.BitmapFromImage(img)
+
+ self._menu = None
+ self.SetLabel(label)
+ self._style = style
+ self._state = dict(pre=PLATE_NORMAL, cur=PLATE_NORMAL)
+ self._color = self.__InitColors()
+ self._pressed = False
+
+ # Setup Initial Size
+ self.SetInitialSize(size)
+
+ # Event Handlers
+ self.Bind(wx.EVT_PAINT, lambda evt: self.__DrawButton())
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+ # Mouse Events
+ self.Bind(wx.EVT_LEFT_DCLICK, lambda evt: self._ToggleState())
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_ENTER_WINDOW,
+ lambda evt: self._SetState(PLATE_HIGHLIGHT))
+ self.Bind(wx.EVT_LEAVE_WINDOW,
+ lambda evt: wx.CallLater(80, self.__LeaveWindow))
+
+ # Other events
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self.Bind(wx.EVT_CONTEXT_MENU, lambda evt: self.ShowMenu())
+
+ def __DrawBitmap(self, gc):
+ """Draw the bitmap if one has been set
+
+ :param GCDC `gc`: :class:`GCDC` to draw with
+ :return: x cordinate to draw text at
+
+ """
+ if self.IsEnabled():
+ bmp = self._bmp['enable']
+ else:
+ bmp = self._bmp['disable']
+
+ if bmp is not None and bmp.IsOk():
+ bw, bh = bmp.GetSize()
+ ypos = (self.GetSize()[1] - bh) // 2
+ gc.DrawBitmap(bmp, 6, ypos, bmp.GetMask() != None)
+ return bw + 6
+ else:
+ return 6
+
+ def __DrawDropArrow(self, gc, xpos, ypos):
+ """Draw a drop arrow if needed and restore pen/brush after finished
+
+ :param GCDC `gc`: :class:`GCDC` to draw with
+ :param int `xpos`: x cord to start at
+ :param int `ypos`: y cord to start at
+
+ """
+ if self._menu is not None or self._style & PB_STYLE_DROPARROW:
+ # Positioning needs a little help on Windows
+ if wx.Platform == '__WXMSW__':
+ xpos -= 2
+ tripoints = [(xpos, ypos), (xpos + 6, ypos), (xpos + 3, ypos + 5)]
+ brush_b = gc.GetBrush()
+ pen_b = gc.GetPen()
+ gc.SetPen(wx.TRANSPARENT_PEN)
+ gc.SetBrush(wx.Brush(gc.GetTextForeground()))
+ gc.DrawPolygon(tripoints)
+ gc.SetBrush(brush_b)
+ gc.SetPen(pen_b)
+ else:
+ pass
+
+ def __DrawHighlight(self, gc, width, height):
+ """Draw the main highlight/pressed state
+
+ :param GCDC `gc`: :class:`GCDC` to draw with
+ :param int `width`: width of highlight
+ :param int `height`: height of highlight
+
+ """
+ if self._state['cur'] == PLATE_PRESSED:
+ color = self._color['press']
+ else:
+ color = self._color['hlight']
+
+ if self._style & PB_STYLE_SQUARE:
+ rad = 0
+ else:
+ rad = (height - 3) / 2
+
+ if self._style & PB_STYLE_GRADIENT:
+ gc.SetBrush(wx.TRANSPARENT_BRUSH)
+ rgc = gc.GetGraphicsContext()
+ brush = rgc.CreateLinearGradientBrush(0, 1, 0, height,
+ color, AdjustAlpha(color, 55))
+ rgc.SetBrush(brush)
+ else:
+ gc.SetBrush(wx.Brush(color))
+
+ gc.DrawRoundedRectangle(1, 1, width - 2, height - 2, rad)
+
+ def __PostEvent(self):
+ """Post a button event to parent of this control"""
+ if self._style & PB_STYLE_TOGGLE:
+ etype = wx.wxEVT_COMMAND_TOGGLEBUTTON_CLICKED
+ else:
+ etype = wx.wxEVT_COMMAND_BUTTON_CLICKED
+ bevt = wx.CommandEvent(etype, self.GetId())
+ bevt.SetEventObject(self)
+ bevt.SetString(self.GetLabel())
+ self.GetEventHandler().ProcessEvent(bevt)
+
+ def __DrawButton(self):
+ """Draw the button"""
+ # TODO using a buffered paintdc on windows with the nobg style
+ # causes lots of weird drawing. So currently the use of a
+ # buffered dc is dissabled for this style.
+ if PB_STYLE_NOBG & self._style:
+ dc = wx.PaintDC(self)
+ else:
+ dc = wx.AutoBufferedPaintDCFactory(self)
+
+ gc = wx.GCDC(dc)
+
+ # Setup
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ gc.SetBrush(wx.TRANSPARENT_BRUSH)
+ gc.SetFont(self.Font)
+ dc.SetFont(self.Font)
+ gc.SetBackgroundMode(wx.TRANSPARENT)
+
+ # The background needs some help to look transparent on
+ # on Gtk and Windows
+ if wx.Platform in ['__WXGTK__', '__WXMSW__']:
+ gc.SetBackground(self.GetBackgroundBrush(gc))
+ gc.Clear()
+
+ # Calc Object Positions
+ width, height = self.GetSize()
+ if wx.Platform == '__WXGTK__':
+ tw, th = dc.GetTextExtent(self.Label)
+ else:
+ tw, th = gc.GetTextExtent(self.Label)
+ txt_y = max((height - th) // 2, 1)
+
+ if self._state['cur'] == PLATE_HIGHLIGHT:
+ gc.SetTextForeground(self._color['htxt'])
+ gc.SetPen(wx.TRANSPARENT_PEN)
+ self.__DrawHighlight(gc, width, height)
+
+ elif self._state['cur'] == PLATE_PRESSED:
+ gc.SetTextForeground(self._color['htxt'])
+ if wx.Platform == '__WXMAC__':
+ pen = wx.Pen(GetHighlightColour(), 1, wx.SOLID)
+ else:
+ pen = wx.Pen(AdjustColour(self._color['press'], -80, 220), 1)
+ gc.SetPen(pen)
+
+ self.__DrawHighlight(gc, width, height)
+ txt_x = self.__DrawBitmap(gc)
+ t_x = max((width - tw - (txt_x + 2)) // 2, txt_x + 2)
+ if wx.Platform == '__WXGTK__':
+ dc.DrawText(self.Label, t_x, txt_y)
+ else:
+ gc.DrawText(self.Label, t_x, txt_y)
+ self.__DrawDropArrow(gc, width - 10, (height // 2) - 2)
+
+ else:
+ if self.IsEnabled():
+ gc.SetTextForeground(self.GetForegroundColour())
+ else:
+ txt_c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)
+ gc.SetTextForeground(txt_c)
+
+ # Draw bitmap and text
+ if self._state['cur'] != PLATE_PRESSED:
+ txt_x = self.__DrawBitmap(gc)
+ t_x = max((width - tw - (txt_x + 2)) // 2, txt_x + 2)
+ if wx.Platform == '__WXGTK__':
+ dc.DrawText(self.Label, t_x, txt_y)
+ else:
+ gc.DrawText(self.Label, t_x, txt_y)
+ self.__DrawDropArrow(gc, width - 10, (height // 2) - 2)
+
+ def __InitColors(self):
+ """Initialize the default colors"""
+ color = GetHighlightColour()
+ pcolor = AdjustColour(color, -12)
+ colors = dict(default=True,
+ hlight=color,
+ press=pcolor,
+ htxt=BestLabelColour(self.GetForegroundColour()))
+ return colors
+
+ def __LeaveWindow(self):
+ """Handle updating the buttons state when the mouse cursor leaves"""
+ if (self._style & PB_STYLE_TOGGLE) and self._pressed:
+ self._SetState(PLATE_PRESSED)
+ else:
+ self._SetState(PLATE_NORMAL)
+ self._pressed = False
+
+ def _SetState(self, state):
+ """Manually set the state of the button
+
+ :param `state`: one of the PLATE_* values
+
+ ..note::
+ the state may be altered by mouse actions
+
+ ..note::
+ Internal use only!
+
+ """
+ self._state['pre'] = self._state['cur']
+ self._state['cur'] = state
+ if wx.Platform == '__WXMSW__':
+ self.Parent.RefreshRect(self.Rect, False)
+ else:
+ self.Refresh()
+
+ def _ToggleState(self):
+ """Toggle button state
+
+ ..note::
+ Internal Use Only!
+
+ """
+ if self._state['cur'] != PLATE_PRESSED:
+ self._SetState(PLATE_PRESSED)
+ else:
+ self._SetState(PLATE_HIGHLIGHT)
+
+ #---- End Private Member Function ----#
+
+ #---- Public Member Functions ----#
+
+ BitmapDisabled = property(lambda self: self.GetBitmapDisabled(),
+ lambda self, bmp: self.SetBitmapDisabled(bmp))
+ BitmapLabel = property(lambda self: self.GetBitmapLabel(),
+ lambda self, bmp: self.SetBitmap(bmp))
+
+ # Aliases
+ BitmapFocus = BitmapLabel
+ BitmapHover = BitmapLabel
+ BitmapSelected = BitmapLabel
+
+ LabelText = property(lambda self: self.GetLabel(),
+ lambda self, lbl: self.SetLabel(lbl))
+
+ def AcceptsFocus(self):
+ """Can this window have the focus?"""
+ return self.IsEnabled()
+
+ def Disable(self):
+ """Disable the control"""
+ super(PlateButton, self).Disable()
+ self.Refresh()
+
+ def DoGetBestSize(self):
+ """Calculate the best size of the button
+
+ :return: :class:`Size`
+
+ """
+ width = 4
+ height = 6
+ if self.Label:
+ # NOTE: Should measure with a GraphicsContext to get right
+ # size, but due to random segfaults on linux special
+ # handling is done in the drawing instead...
+ lsize = self.GetFullTextExtent(self.Label)
+ width += lsize[0]
+ height += lsize[1]
+
+ if self._bmp['enable'] is not None:
+ bsize = self._bmp['enable'].Size
+ width += (bsize[0] + 10)
+ if height <= bsize[1]:
+ height = bsize[1] + 6
+ else:
+ height += 3
+ else:
+ width += 10
+
+ if self._menu is not None or self._style & PB_STYLE_DROPARROW:
+ width += 12
+
+ best = wx.Size(width, height)
+ self.CacheBestSize(best)
+ return best
+
+ def Enable(self, enable=True):
+ """Enable/Disable the control"""
+ super(PlateButton, self).Enable(enable)
+ self.Refresh()
+
+ def GetBackgroundBrush(self, dc):
+ """Get the brush for drawing the background of the button
+
+ :return: :class:`Brush`
+
+ ..note::
+ used internally when on gtk
+
+ """
+ if wx.Platform == '__WXMAC__' or self._style & PB_STYLE_NOBG:
+ return wx.TRANSPARENT_BRUSH
+
+ bkgrd = self.GetBackgroundColour()
+ brush = wx.Brush(bkgrd, wx.SOLID)
+ my_attr = self.GetDefaultAttributes()
+ p_attr = self.Parent.GetDefaultAttributes()
+ my_def = bkgrd == my_attr.colBg
+ p_def = self.Parent.GetBackgroundColour() == p_attr.colBg
+ if my_def and not p_def:
+ bkgrd = self.Parent.GetBackgroundColour()
+ brush = wx.Brush(bkgrd, wx.SOLID)
+ return brush
+
+ def GetBitmapDisabled(self):
+ """Get the bitmap of the disable state
+
+ :return: :class:`Bitmap` or None
+
+ """
+ return self.BitmapDisabled
+
+ def GetBitmapLabel(self):
+ """Get the label bitmap
+
+ :return: :class:`Bitmap` or None
+
+ """
+ return self.BitmapLabel
+
+ # GetBitmap Aliases for BitmapButton api
+ GetBitmapFocus = GetBitmapLabel
+ GetBitmapHover = GetBitmapLabel
+
+ # Alias for GetLabel
+ GetLabelText = wx.PyControl.GetLabel
+
+ def GetMenu(self):
+ """Return the menu associated with this button or None if no
+ menu is associated with it.
+
+ """
+ return self._menu
+
+ def GetState(self):
+ """Get the current state of the button
+
+ :return: int
+
+ ..seeAlso::
+ PLATE_NORMAL, PLATE_HIGHLIGHT, PLATE_PRESSED
+
+ """
+ return self._state['cur']
+
+ def HasTransparentBackground(self):
+ """Override setting of background fill"""
+ return True
+
+ def IsPressed(self):
+ """Return if button is pressed (PB_STYLE_TOGGLE)
+
+ :return: bool
+
+ """
+ return self._pressed
+
+ #---- Event Handlers ----#
+
+ def OnErase(self, evt):
+ """Trap the erase event to keep the background transparent
+ on windows.
+
+ :param `evt`: wx.EVT_ERASE_BACKGROUND
+
+ """
+ pass
+
+ def OnFocus(self, evt):
+ """Set the visual focus state if need be"""
+ if self._state['cur'] == PLATE_NORMAL:
+ self._SetState(PLATE_HIGHLIGHT)
+
+ def OnKeyUp(self, evt):
+ """Execute a single button press action when the Return key is pressed
+ and this control has the focus.
+
+ :param `evt`: wx.EVT_KEY_UP
+
+ """
+ if evt.GetKeyCode() == wx.WXK_SPACE:
+ self._SetState(PLATE_PRESSED)
+ self.__PostEvent()
+ wx.CallLater(100, self._SetState, PLATE_HIGHLIGHT)
+ else:
+ evt.Skip()
+
+ def OnKillFocus(self, evt):
+ """Set the visual state back to normal when focus is lost
+ unless the control is currently in a pressed state.
+
+ """
+ # Note: this delay needs to be at least as much as the on in the KeyUp
+ # handler to prevent ghost highlighting from happening when
+ # quickly changing focus and activating buttons
+ if self._state['cur'] != PLATE_PRESSED:
+ self._SetState(PLATE_NORMAL)
+
+ def OnLeftDown(self, evt):
+ """Sets the pressed state and depending on the click position will
+ show the popup menu if one has been set.
+
+ """
+ if (self._style & PB_STYLE_TOGGLE):
+ self._pressed = not self._pressed
+
+ pos = evt.GetPositionTuple()
+ self._SetState(PLATE_PRESSED)
+ size = self.GetSizeTuple()
+ if pos[0] >= size[0] - 16:
+ if self._menu is not None:
+ self.ShowMenu()
+ elif self._style & PB_STYLE_DROPARROW:
+ event = PlateBtnDropArrowPressed()
+ event.SetEventObject(self)
+ self.EventHandler.ProcessEvent(event)
+
+ self.SetFocus()
+
+ def OnLeftUp(self, evt):
+ """Post a button event if the control was previously in a
+ pressed state.
+
+ :param `evt`: :class:`MouseEvent`
+
+ """
+ if self._state['cur'] == PLATE_PRESSED:
+ pos = evt.GetPositionTuple()
+ size = self.GetSizeTuple()
+ if not (self._style & PB_STYLE_DROPARROW and pos[0] >= size[0] - 16):
+ self.__PostEvent()
+
+ if self._pressed:
+ self._SetState(PLATE_PRESSED)
+ else:
+ self._SetState(PLATE_HIGHLIGHT)
+
+ def OnMenuClose(self, evt):
+ """Refresh the control to a proper state after the menu has been
+ dismissed.
+
+ :param `evt`: wx.EVT_MENU_CLOSE
+
+ """
+ mpos = wx.GetMousePosition()
+ if self.HitTest(self.ScreenToClient(mpos)) != wx.HT_WINDOW_OUTSIDE:
+ self._SetState(PLATE_HIGHLIGHT)
+ else:
+ self._SetState(PLATE_NORMAL)
+ evt.Skip()
+
+ #---- End Event Handlers ----#
+
+ def SetBitmap(self, bmp):
+ """Set the bitmap displayed in the button
+
+ :param `bmp`: :class:`Bitmap`
+
+ """
+ self._bmp['enable'] = bmp
+ img = bmp.ConvertToImage()
+ img = img.ConvertToGreyscale(.795, .073, .026) #(.634, .224, .143)
+ self._bmp['disable'] = img.ConvertToBitmap()
+ self.InvalidateBestSize()
+
+ def SetBitmapDisabled(self, bmp):
+ """Set the bitmap for the disabled state
+
+ :param `bmp`: :class:`Bitmap`
+
+ """
+ self._bmp['disable'] = bmp
+
+ # Aliases for SetBitmap* functions from BitmapButton
+ SetBitmapFocus = SetBitmap
+ SetBitmapHover = SetBitmap
+ SetBitmapLabel = SetBitmap
+ SetBitmapSelected = SetBitmap
+
+ def SetFocus(self):
+ """Set this control to have the focus"""
+ if self._state['cur'] != PLATE_PRESSED:
+ self._SetState(PLATE_HIGHLIGHT)
+ super(PlateButton, self).SetFocus()
+
+ def SetFont(self, font):
+ """Adjust size of control when font changes"""
+ super(PlateButton, self).SetFont(font)
+ self.InvalidateBestSize()
+
+ def SetLabel(self, label):
+ """Set the label of the button
+
+ :param string `label`: lable string
+
+ """
+ super(PlateButton, self).SetLabel(label)
+ self.InvalidateBestSize()
+
+ def SetLabelColor(self, normal, hlight=wx.NullColour):
+ """Set the color of the label. The optimal label color is usually
+ automatically selected depending on the button color. In some
+ cases the colors that are chosen may not be optimal.
+
+ The normal state must be specified, if the other two params are left
+ Null they will be automatically guessed based on the normal color. To
+ prevent this automatic color choices from happening either specify
+ a color or None for the other params.
+
+ :param Colour `normal`: Label color for normal state (:class:`Colour`)
+ :keyword Colour `hlight`: Color for when mouse is hovering over
+
+ """
+ assert isinstance(normal, wx.Colour), "Must supply a colour object"
+ self._color['default'] = False
+ self.SetForegroundColour(normal)
+
+ if hlight is not None:
+ if hlight.IsOk():
+ self._color['htxt'] = hlight
+ else:
+ self._color['htxt'] = BestLabelColour(normal)
+
+ if wx.Platform == '__WXMSW__':
+ self.Parent.RefreshRect(self.GetRect(), False)
+ else:
+ self.Refresh()
+
+ def SetMenu(self, menu):
+ """Set the menu that can be shown when clicking on the
+ drop arrow of the button.
+
+ :param Menu `menu`: :class:`Menu` to use as a PopupMenu
+
+ ..note::
+ Arrow is not drawn unless a menu is set
+
+ """
+ if self._menu is not None:
+ self.Unbind(wx.EVT_MENU_CLOSE)
+
+ self._menu = menu
+ self.Bind(wx.EVT_MENU_CLOSE, self.OnMenuClose)
+ self.InvalidateBestSize()
+
+ def SetPressColor(self, color):
+ """Set the color used for highlighting the pressed state
+
+ :param Colour `color`: :class:`Colour`
+
+ ..note::
+ also resets all text colours as necessary
+
+ """
+ self._color['default'] = False
+ if color.Alpha() == 255:
+ self._color['hlight'] = AdjustAlpha(color, 200)
+ else:
+ self._color['hlight'] = color
+ self._color['press'] = AdjustColour(color, -10, 160)
+ self._color['htxt'] = BestLabelColour(self._color['hlight'])
+ self.Refresh()
+
+ def SetWindowStyle(self, style):
+ """Sets the window style bytes, the updates take place
+ immediately no need to call refresh afterwards.
+
+ :param `style`: bitmask of PB_STYLE_* values
+
+ """
+ self._style = style
+ self.Refresh()
+
+ def SetWindowVariant(self, variant):
+ """Set the variant/font size of this control"""
+ super(PlateButton, self).SetWindowVariant(variant)
+ self.InvalidateBestSize()
+
+ def ShouldInheritColours(self):
+ """Overridden base class virtual. If the parent has non-default
+ colours then we want this control to inherit them.
+
+ """
+ return True
+
+ def ShowMenu(self):
+ """Show the dropdown menu if one is associated with this control"""
+ if self._menu is not None:
+ size = self.GetSizeTuple()
+ adj = wx.Platform == '__WXMAC__' and 3 or 0
+
+ if self._style & PB_STYLE_SQUARE:
+ xpos = 1
+ else:
+ xpos = size[1] / 2
+
+ self.PopupMenu(self._menu, (xpos, size[1] + adj))
+
+ #---- End Public Member Functions ----#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/plot.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/plot.py
new file mode 100644
index 0000000..94696c5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/plot.py
@@ -0,0 +1,2531 @@
+#-----------------------------------------------------------------------------
+# Name: wx.lib.plot.py
+# Purpose: Line, Bar and Scatter Graphs
+#
+# Author: Gordon Williams
+#
+# Created: 2003/11/03
+# RCS-ID: $Id$
+# Copyright: (c) 2002
+# Licence: Use as you wish.
+#-----------------------------------------------------------------------------
+# 12/15/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o Renamed to plot.py in the wx.lib directory.
+# o Reworked test frame to work with wx demo framework. This saves a bit
+# of tedious cut and paste, and the test app is excellent.
+#
+# 12/18/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxScrolledMessageDialog -> ScrolledMessageDialog
+#
+# Oct 6, 2004 Gordon Williams (g_will@cyberus.ca)
+# - Added bar graph demo
+# - Modified line end shape from round to square.
+# - Removed FloatDCWrapper for conversion to ints and ints in arguments
+#
+# Oct 15, 2004 Gordon Williams (g_will@cyberus.ca)
+# - Imported modules given leading underscore to name.
+# - Added Cursor Line Tracking and User Point Labels.
+# - Demo for Cursor Line Tracking and Point Labels.
+# - Size of plot preview frame adjusted to show page better.
+# - Added helper functions PositionUserToScreen and PositionScreenToUser in PlotCanvas.
+# - Added functions GetClosestPoints (all curves) and GetClosestPoint (only closest curve)
+# can be in either user coords or screen coords.
+#
+# Jun 22, 2009 Florian Hoech (florian.hoech@gmx.de)
+# - Fixed exception when drawing empty plots on Mac OS X
+# - Fixed exception when trying to draw point labels on Mac OS X (Mac OS X
+# point label drawing code is still slow and only supports wx.COPY)
+# - Moved label positions away from axis lines a bit
+# - Added PolySpline class and modified demo 1 and 2 to use it
+# - Added center and diagonal lines option (Set/GetEnableCenterLines,
+# Set/GetEnableDiagonals)
+# - Added anti-aliasing option with optional high-resolution mode
+# (Set/GetEnableAntiAliasing, Set/GetEnableHiRes) and demo
+# - Added option to specify exact number of tick marks to use for each axis
+# (SetXSpec(<number>, SetYSpec(<number>) -- work like 'min', but with
+# <number> tick marks)
+# - Added support for background and foreground colours (enabled via
+# SetBackgroundColour/SetForegroundColour on a PlotCanvas instance)
+# - Changed PlotCanvas printing initialization from occuring in __init__ to
+# occur on access. This will postpone any IPP and / or CUPS warnings
+# which appear on stderr on some Linux systems until printing functionality
+# is actually used.
+#
+#
+
+"""
+This is a simple light weight plotting module that can be used with
+Boa or easily integrated into your own wxPython application. The
+emphasis is on small size and fast plotting for large data sets. It
+has a reasonable number of features to do line and scatter graphs
+easily as well as simple bar graphs. It is not as sophisticated or
+as powerful as SciPy Plt or Chaco. Both of these are great packages
+but consume huge amounts of computer resources for simple plots.
+They can be found at http://scipy.com
+
+This file contains two parts; first the re-usable library stuff, then,
+after a "if __name__=='__main__'" test, a simple frame and a few default
+plots for examples and testing.
+
+Based on wxPlotCanvas
+Written by K.Hinsen, R. Srinivasan;
+Ported to wxPython Harm van der Heijden, feb 1999
+
+Major Additions Gordon Williams Feb. 2003 (g_will@cyberus.ca)
+ -More style options
+ -Zooming using mouse "rubber band"
+ -Scroll left, right
+ -Grid(graticule)
+ -Printing, preview, and page set up (margins)
+ -Axis and title labels
+ -Cursor xy axis values
+ -Doc strings and lots of comments
+ -Optimizations for large number of points
+ -Legends
+
+Did a lot of work here to speed markers up. Only a factor of 4
+improvement though. Lines are much faster than markers, especially
+filled markers. Stay away from circles and triangles unless you
+only have a few thousand points.
+
+Times for 25,000 points
+Line - 0.078 sec
+Markers
+Square - 0.22 sec
+dot - 0.10
+circle - 0.87
+cross,plus - 0.28
+triangle, triangle_down - 0.90
+
+Thanks to Chris Barker for getting this version working on Linux.
+
+Zooming controls with mouse (when enabled):
+ Left mouse drag - Zoom box.
+ Left mouse double click - reset zoom.
+ Right mouse click - zoom out centred on click location.
+"""
+
+import string as _string
+import time as _time
+import sys
+import wx
+
+# Needs NumPy
+try:
+ import numpy as np
+except:
+ msg = """
+ This module requires the NumPy module, which could not be
+ imported. It probably is not installed (it's not part of the
+ standard Python distribution). See the Numeric Python site
+ (http://numpy.scipy.org) for information on downloading source or
+ binaries."""
+ raise ImportError("NumPy not found.\n" + msg)
+
+
+#
+# Plotting classes...
+#
+class PolyPoints:
+
+ """Base Class for lines and markers
+ - All methods are private.
+ """
+
+ def __init__(self, points, attr):
+ self._points = np.array(points).astype(np.float64)
+ self._logscale = (False, False)
+ self._pointSize = (1.0, 1.0)
+ self.currentScale = (1, 1)
+ self.currentShift = (0, 0)
+ self.scaled = self.points
+ self.attributes = {}
+ self.attributes.update(self._attributes)
+ for name, value in attr.items():
+ if name not in self._attributes.keys():
+ raise KeyError(
+ "Style attribute incorrect. Should be one of %s" % self._attributes.keys())
+ self.attributes[name] = value
+
+ def setLogScale(self, logscale):
+ self._logscale = logscale
+
+ def __getattr__(self, name):
+ if name == 'points':
+ if len(self._points) > 0:
+ data = np.array(self._points, copy=True)
+ if self._logscale[0]:
+ data = self.log10(data, 0)
+ if self._logscale[1]:
+ data = self.log10(data, 1)
+ return data
+ else:
+ return self._points
+ else:
+ raise AttributeError(name)
+
+ def log10(self, data, ind):
+ data = np.compress(data[:, ind] > 0, data, 0)
+ data[:, ind] = np.log10(data[:, ind])
+ return data
+
+ def boundingBox(self):
+ if len(self.points) == 0:
+ # no curves to draw
+ # defaults to (-1,-1) and (1,1) but axis can be set in Draw
+ minXY = np.array([-1.0, -1.0])
+ maxXY = np.array([1.0, 1.0])
+ else:
+ minXY = np.minimum.reduce(self.points)
+ maxXY = np.maximum.reduce(self.points)
+ return minXY, maxXY
+
+ def scaleAndShift(self, scale=(1, 1), shift=(0, 0)):
+ if len(self.points) == 0:
+ # no curves to draw
+ return
+ if (scale is not self.currentScale) or (shift is not self.currentShift):
+ # update point scaling
+ self.scaled = scale * self.points + shift
+ self.currentScale = scale
+ self.currentShift = shift
+ # else unchanged use the current scaling
+
+ def getLegend(self):
+ return self.attributes['legend']
+
+ def getClosestPoint(self, pntXY, pointScaled=True):
+ """Returns the index of closest point on the curve, pointXY, scaledXY, distance
+ x, y in user coords
+ if pointScaled == True based on screen coords
+ if pointScaled == False based on user coords
+ """
+ if pointScaled == True:
+ # Using screen coords
+ p = self.scaled
+ pxy = self.currentScale * np.array(pntXY) + self.currentShift
+ else:
+ # Using user coords
+ p = self.points
+ pxy = np.array(pntXY)
+ # determine distance for each point
+ d = np.sqrt(np.add.reduce((p - pxy) ** 2, 1)) # sqrt(dx^2+dy^2)
+ pntIndex = np.argmin(d)
+ dist = d[pntIndex]
+ return [pntIndex, self.points[pntIndex], self.scaled[pntIndex] / self._pointSize, dist]
+
+
+class PolyLine(PolyPoints):
+
+ """Class to define line type and style
+ - All methods except __init__ are private.
+ """
+
+ _attributes = {'colour': 'black',
+ 'width': 1,
+ 'style': wx.PENSTYLE_SOLID,
+ 'legend': ''}
+
+ def __init__(self, points, **attr):
+ """
+ Creates PolyLine object
+
+ :param `points`: sequence (array, tuple or list) of (x,y) points making up line
+ :keyword `attr`: keyword attributes, default to:
+
+ ========================== ================================
+ 'colour'= 'black' wx.Pen Colour any wx.Colour
+ 'width'= 1 Pen width
+ 'style'= wx.PENSTYLE_SOLID wx.Pen style
+ 'legend'= '' Line Legend to display
+ ========================== ================================
+
+ """
+ PolyPoints.__init__(self, points, attr)
+
+ def draw(self, dc, printerScale, coord=None):
+ colour = self.attributes['colour']
+ width = self.attributes['width'] * printerScale * self._pointSize[0]
+ style = self.attributes['style']
+ if not isinstance(colour, wx.Colour):
+ colour = wx.Colour(colour)
+ pen = wx.Pen(colour, width, style)
+ pen.SetCap(wx.CAP_BUTT)
+ dc.SetPen(pen)
+ if coord == None:
+ if len(self.scaled): # bugfix for Mac OS X
+ dc.DrawLines(self.scaled)
+ else:
+ dc.DrawLines(coord) # draw legend line
+
+ def getSymExtent(self, printerScale):
+ """Width and Height of Marker"""
+ h = self.attributes['width'] * printerScale * self._pointSize[0]
+ w = 5 * h
+ return (w, h)
+
+
+class PolySpline(PolyLine):
+
+ """Class to define line type and style
+ - All methods except __init__ are private.
+ """
+
+ _attributes = {'colour': 'black',
+ 'width': 1,
+ 'style': wx.PENSTYLE_SOLID,
+ 'legend': ''}
+
+ def __init__(self, points, **attr):
+ """
+ Creates PolyLine object
+
+ :param `points`: sequence (array, tuple or list) of (x,y) points making up spline
+ :keyword `attr`: keyword attributes, default to:
+
+ ========================== ================================
+ 'colour'= 'black' wx.Pen Colour any wx.Colour
+ 'width'= 1 Pen width
+ 'style'= wx.PENSTYLE_SOLID wx.Pen style
+ 'legend'= '' Line Legend to display
+ ========================== ================================
+
+ """
+ PolyLine.__init__(self, points, **attr)
+
+ def draw(self, dc, printerScale, coord=None):
+ colour = self.attributes['colour']
+ width = self.attributes['width'] * printerScale * self._pointSize[0]
+ style = self.attributes['style']
+ if not isinstance(colour, wx.Colour):
+ colour = wx.Colour(colour)
+ pen = wx.Pen(colour, width, style)
+ pen.SetCap(wx.CAP_ROUND)
+ dc.SetPen(pen)
+ if coord == None:
+ if len(self.scaled): # bugfix for Mac OS X
+ dc.DrawSpline(self.scaled)
+ else:
+ dc.DrawLines(coord) # draw legend line
+
+
+class PolyMarker(PolyPoints):
+
+ """Class to define marker type and style
+ - All methods except __init__ are private.
+ """
+
+ _attributes = {'colour': 'black',
+ 'width': 1,
+ 'size': 2,
+ 'fillcolour': None,
+ 'fillstyle': wx.BRUSHSTYLE_SOLID,
+ 'marker': 'circle',
+ 'legend': ''}
+
+ def __init__(self, points, **attr):
+ """
+ Creates PolyMarker object
+
+ :param `points`: sequence (array, tuple or list) of (x,y) points
+ :keyword `attr`: keyword attributes, default to:
+
+ ================================ ================================
+ 'colour'= 'black' wx.Pen Colour any wx.Colour
+ 'width'= 1 Pen width
+ 'size'= 2 Marker size
+ 'fillcolour'= same as colour wx.Brush Colour any wx.Colour
+ 'fillstyle'= wx.BRUSHSTYLE_SOLID wx.Brush fill style (use wx.BRUSHSTYLE_TRANSPARENT for no fill)
+ 'style'= wx.FONTFAMILY_SOLID wx.Pen style
+ 'marker'= 'circle' Marker shape
+ 'legend'= '' Line Legend to display
+ ================================ ================================
+
+ Marker Shapes:
+ - 'circle'
+ - 'dot'
+ - 'square'
+ - 'triangle'
+ - 'triangle_down'
+ - 'cross'
+ - 'plus'
+ """
+
+ PolyPoints.__init__(self, points, attr)
+
+ def draw(self, dc, printerScale, coord=None):
+ colour = self.attributes['colour']
+ width = self.attributes['width'] * printerScale * self._pointSize[0]
+ size = self.attributes['size'] * printerScale * self._pointSize[0]
+ fillcolour = self.attributes['fillcolour']
+ fillstyle = self.attributes['fillstyle']
+ marker = self.attributes['marker']
+
+ if colour and not isinstance(colour, wx.Colour):
+ colour = wx.Colour(colour)
+ if fillcolour and not isinstance(fillcolour, wx.Colour):
+ fillcolour = wx.Colour(fillcolour)
+
+ dc.SetPen(wx.Pen(colour, width))
+ if fillcolour:
+ dc.SetBrush(wx.Brush(fillcolour, fillstyle))
+ else:
+ dc.SetBrush(wx.Brush(colour, fillstyle))
+ if coord == None:
+ if len(self.scaled): # bugfix for Mac OS X
+ self._drawmarkers(dc, self.scaled, marker, size)
+ else:
+ self._drawmarkers(dc, coord, marker, size) # draw legend marker
+
+ def getSymExtent(self, printerScale):
+ """Width and Height of Marker"""
+ s = 5 * self.attributes['size'] * printerScale * self._pointSize[0]
+ return (s, s)
+
+ def _drawmarkers(self, dc, coords, marker, size=1):
+ f = eval('self._' + marker)
+ f(dc, coords, size)
+
+ def _circle(self, dc, coords, size=1):
+ fact = 2.5 * size
+ wh = 5.0 * size
+ rect = np.zeros((len(coords), 4), np.float) + [0.0, 0.0, wh, wh]
+ rect[:, 0:2] = coords - [fact, fact]
+ dc.DrawEllipseList(rect.astype(np.int32))
+
+ def _dot(self, dc, coords, size=1):
+ dc.DrawPointList(coords)
+
+ def _square(self, dc, coords, size=1):
+ fact = 2.5 * size
+ wh = 5.0 * size
+ rect = np.zeros((len(coords), 4), np.float) + [0.0, 0.0, wh, wh]
+ rect[:, 0:2] = coords - [fact, fact]
+ dc.DrawRectangleList(rect.astype(np.int32))
+
+ def _triangle(self, dc, coords, size=1):
+ shape = [(-2.5 * size, 1.44 * size),
+ (2.5 * size, 1.44 * size), (0.0, -2.88 * size)]
+ poly = np.repeat(coords, 3, 0)
+ poly.shape = (len(coords), 3, 2)
+ poly += shape
+ dc.DrawPolygonList(poly.astype(np.int32))
+
+ def _triangle_down(self, dc, coords, size=1):
+ shape = [(-2.5 * size, -1.44 * size),
+ (2.5 * size, -1.44 * size), (0.0, 2.88 * size)]
+ poly = np.repeat(coords, 3, 0)
+ poly.shape = (len(coords), 3, 2)
+ poly += shape
+ dc.DrawPolygonList(poly.astype(np.int32))
+
+ def _cross(self, dc, coords, size=1):
+ fact = 2.5 * size
+ for f in [[-fact, -fact, fact, fact], [-fact, fact, fact, -fact]]:
+ lines = np.concatenate((coords, coords), axis=1) + f
+ dc.DrawLineList(lines.astype(np.int32))
+
+ def _plus(self, dc, coords, size=1):
+ fact = 2.5 * size
+ for f in [[-fact, 0, fact, 0], [0, -fact, 0, fact]]:
+ lines = np.concatenate((coords, coords), axis=1) + f
+ dc.DrawLineList(lines.astype(np.int32))
+
+
+class PlotGraphics:
+
+ """Container to hold PolyXXX objects and graph labels
+ - All methods except __init__ are private.
+ """
+
+ def __init__(self, objects, title='', xLabel='', yLabel=''):
+ """Creates PlotGraphics object
+ objects - list of PolyXXX objects to make graph
+ title - title shown at top of graph
+ xLabel - label shown on x-axis
+ yLabel - label shown on y-axis
+ """
+ if type(objects) not in [list, tuple]:
+ raise TypeError("objects argument should be list or tuple")
+ self.objects = objects
+ self.title = title
+ self.xLabel = xLabel
+ self.yLabel = yLabel
+ self._pointSize = (1.0, 1.0)
+
+ def setLogScale(self, logscale):
+ if type(logscale) != tuple:
+ raise TypeError(
+ 'logscale must be a tuple of bools, e.g. (False, False)')
+ if len(self.objects) == 0:
+ return
+ for o in self.objects:
+ o.setLogScale(logscale)
+
+ def boundingBox(self):
+ p1, p2 = self.objects[0].boundingBox()
+ for o in self.objects[1:]:
+ p1o, p2o = o.boundingBox()
+ p1 = np.minimum(p1, p1o)
+ p2 = np.maximum(p2, p2o)
+ return p1, p2
+
+ def scaleAndShift(self, scale=(1, 1), shift=(0, 0)):
+ for o in self.objects:
+ o.scaleAndShift(scale, shift)
+
+ def setPrinterScale(self, scale):
+ """Thickens up lines and markers only for printing"""
+ self.printerScale = scale
+
+ def setXLabel(self, xLabel=''):
+ """Set the X axis label on the graph"""
+ self.xLabel = xLabel
+
+ def setYLabel(self, yLabel=''):
+ """Set the Y axis label on the graph"""
+ self.yLabel = yLabel
+
+ def setTitle(self, title=''):
+ """Set the title at the top of graph"""
+ self.title = title
+
+ def getXLabel(self):
+ """Get x axis label string"""
+ return self.xLabel
+
+ def getYLabel(self):
+ """Get y axis label string"""
+ return self.yLabel
+
+ def getTitle(self, title=''):
+ """Get the title at the top of graph"""
+ return self.title
+
+ def draw(self, dc):
+ for o in self.objects:
+ # t=_time.clock() # profile info
+ o._pointSize = self._pointSize
+ o.draw(dc, self.printerScale)
+ #dt= _time.clock()-t
+ #print(o, "time=", dt)
+
+ def getSymExtent(self, printerScale):
+ """Get max width and height of lines and markers symbols for legend"""
+ self.objects[0]._pointSize = self._pointSize
+ symExt = self.objects[0].getSymExtent(printerScale)
+ for o in self.objects[1:]:
+ o._pointSize = self._pointSize
+ oSymExt = o.getSymExtent(printerScale)
+ symExt = np.maximum(symExt, oSymExt)
+ return symExt
+
+ def getLegendNames(self):
+ """Returns list of legend names"""
+ lst = [None] * len(self)
+ for i in range(len(self)):
+ lst[i] = self.objects[i].getLegend()
+ return lst
+
+ def __len__(self):
+ return len(self.objects)
+
+ def __getitem__(self, item):
+ return self.objects[item]
+
+
+#-------------------------------------------------------------------------
+# Main window that you will want to import into your application.
+
+class PlotCanvas(wx.Panel):
+
+ """
+ Subclass of a wx.Panel which holds two scrollbars and the actual
+ plotting canvas (self.canvas). It allows for simple general plotting
+ of data with zoom, labels, and automatic axis scaling."""
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, name="plotCanvas"):
+ """Constructs a panel, which can be a child of a frame or
+ any other non-control window"""
+
+ wx.Panel.__init__(self, parent, id, pos, size, style, name)
+
+ sizer = wx.FlexGridSizer(2, 2, 0, 0)
+ self.canvas = wx.Window(self, -1)
+ self.sb_vert = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL)
+ self.sb_vert.SetScrollbar(0, 1000, 1000, 1000)
+ self.sb_hor = wx.ScrollBar(self, -1, style=wx.SB_HORIZONTAL)
+ self.sb_hor.SetScrollbar(0, 1000, 1000, 1000)
+
+ sizer.Add(self.canvas, 1, wx.EXPAND)
+ sizer.Add(self.sb_vert, 0, wx.EXPAND)
+ sizer.Add(self.sb_hor, 0, wx.EXPAND)
+ sizer.Add((0, 0))
+
+ sizer.AddGrowableRow(0, 1)
+ sizer.AddGrowableCol(0, 1)
+
+ self.sb_vert.Show(False)
+ self.sb_hor.Show(False)
+
+ self.SetSizer(sizer)
+ self.Fit()
+
+ self.border = (1, 1)
+
+ self.SetBackgroundColour("white")
+
+ # Create some mouse events for zooming
+ self.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
+ self.canvas.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp)
+ self.canvas.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.canvas.Bind(wx.EVT_LEFT_DCLICK, self.OnMouseDoubleClick)
+ self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown)
+
+ # scrollbar events
+ self.Bind(wx.EVT_SCROLL_THUMBTRACK, self.OnScroll)
+ self.Bind(wx.EVT_SCROLL_PAGEUP, self.OnScroll)
+ self.Bind(wx.EVT_SCROLL_PAGEDOWN, self.OnScroll)
+ self.Bind(wx.EVT_SCROLL_LINEUP, self.OnScroll)
+ self.Bind(wx.EVT_SCROLL_LINEDOWN, self.OnScroll)
+
+ # set curser as cross-hairs
+ self.canvas.SetCursor(wx.CROSS_CURSOR)
+ self.HandCursor = wx.Cursor(Hand.GetImage())
+ self.GrabHandCursor = wx.Cursor(GrabHand.GetImage())
+ self.MagCursor = wx.Cursor(MagPlus.GetImage())
+
+ # Things for printing
+ self._print_data = None
+ self._pageSetupData = None
+ self.printerScale = 1
+ self.parent = parent
+
+ # scrollbar variables
+ self._sb_ignore = False
+ self._adjustingSB = False
+ self._sb_xfullrange = 0
+ self._sb_yfullrange = 0
+ self._sb_xunit = 0
+ self._sb_yunit = 0
+
+ self._dragEnabled = False
+ self._screenCoordinates = np.array([0.0, 0.0])
+
+ self._logscale = (False, False)
+
+ # Zooming variables
+ self._zoomInFactor = 0.5
+ self._zoomOutFactor = 2
+ self._zoomCorner1 = np.array([0.0, 0.0]) # left mouse down corner
+ self._zoomCorner2 = np.array([0.0, 0.0]) # left mouse up corner
+ self._zoomEnabled = False
+ self._hasDragged = False
+
+ # Drawing Variables
+ self.last_draw = None
+ self._pointScale = 1
+ self._pointShift = 0
+ self._xSpec = 'auto'
+ self._ySpec = 'auto'
+ self._gridEnabled = False
+ self._legendEnabled = False
+ self._titleEnabled = True
+ self._centerLinesEnabled = False
+ self._diagonalsEnabled = False
+
+ # Fonts
+ self._fontCache = {}
+ self._fontSizeAxis = 10
+ self._fontSizeTitle = 15
+ self._fontSizeLegend = 7
+
+ # pointLabels
+ self._pointLabelEnabled = False
+ self.last_PointLabel = None
+ self._pointLabelFunc = None
+ self.canvas.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
+ if sys.platform != "darwin":
+ self._logicalFunction = wx.EQUIV # (NOT src) XOR dst
+ else:
+ # wx.EQUIV not supported on Mac OS X
+ self._logicalFunction = wx.COPY
+
+ self._useScientificNotation = False
+
+ self._antiAliasingEnabled = False
+ self._hiResEnabled = False
+ self._pointSize = (1.0, 1.0)
+ self._fontScale = 1.0
+
+ self.canvas.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.canvas.Bind(wx.EVT_SIZE, self.OnSize)
+ # OnSize called to make sure the buffer is initialized.
+ # This might result in OnSize getting called twice on some
+ # platforms at initialization, but little harm done.
+ self.OnSize(None) # sets the initial size based on client size
+
+ self._gridColour = wx.BLACK
+
+ def SetCursor(self, cursor):
+ self.canvas.SetCursor(cursor)
+
+ def GetGridColour(self):
+ return self._gridColour
+
+ def SetGridColour(self, colour):
+ if isinstance(colour, wx.Colour):
+ self._gridColour = colour
+ else:
+ self._gridColour = wx.Colour(colour)
+
+ # SaveFile
+ def SaveFile(self, fileName=''):
+ """Saves the file to the type specified in the extension. If no file
+ name is specified a dialog box is provided. Returns True if sucessful,
+ otherwise False.
+
+ .bmp Save a Windows bitmap file.
+ .xbm Save an X bitmap file.
+ .xpm Save an XPM bitmap file.
+ .png Save a Portable Network Graphics file.
+ .jpg Save a Joint Photographic Experts Group file.
+ """
+ extensions = {
+ "bmp": wx.BITMAP_TYPE_BMP, # Save a Windows bitmap file.
+ "xbm": wx.BITMAP_TYPE_XBM, # Save an X bitmap file.
+ "xpm": wx.BITMAP_TYPE_XPM, # Save an XPM bitmap file.
+ "jpg": wx.BITMAP_TYPE_JPEG, # Save a JPG file.
+ "png": wx.BITMAP_TYPE_PNG, # Save a PNG file.
+ }
+
+ fType = _string.lower(fileName[-3:])
+ dlg1 = None
+ while fType not in extensions:
+
+ if dlg1: # FileDialog exists: Check for extension
+ dlg2 = wx.MessageDialog(self, 'File name extension\n'
+ 'must be one of\nbmp, xbm, xpm, png, or jpg',
+ 'File Name Error', wx.OK | wx.ICON_ERROR)
+ try:
+ dlg2.ShowModal()
+ finally:
+ dlg2.Destroy()
+ # FileDialog doesn't exist: just check one
+ else:
+ dlg1 = wx.FileDialog(
+ self,
+ "Choose a file with extension bmp, gif, xbm, xpm, png, or jpg", ".", "",
+ "BMP files (*.bmp)|*.bmp|XBM files (*.xbm)|*.xbm|XPM file (*.xpm)|*.xpm|PNG files (*.png)|*.png|JPG files (*.jpg)|*.jpg",
+ wx.SAVE | wx.OVERWRITE_PROMPT
+ )
+
+ if dlg1.ShowModal() == wx.ID_OK:
+ fileName = dlg1.GetPath()
+ fType = _string.lower(fileName[-3:])
+ else: # exit without saving
+ dlg1.Destroy()
+ return False
+
+ if dlg1:
+ dlg1.Destroy()
+
+ # Save Bitmap
+ res = self._Buffer.SaveFile(fileName, extensions[fType])
+ return res
+
+ @property
+ def print_data(self):
+ if not self._print_data:
+ self._print_data = wx.PrintData()
+ self._print_data.SetPaperId(wx.PAPER_LETTER)
+ self._print_data.SetOrientation(wx.LANDSCAPE)
+ return self._print_data
+
+ @property
+ def pageSetupData(self):
+ if not self._pageSetupData:
+ self._pageSetupData = wx.PageSetupDialogData()
+ self._pageSetupData.SetMarginBottomRight((25, 25))
+ self._pageSetupData.SetMarginTopLeft((25, 25))
+ self._pageSetupData.SetPrintData(self.print_data)
+ return self._pageSetupData
+
+ def PageSetup(self):
+ """Brings up the page setup dialog"""
+ data = self.pageSetupData
+ data.SetPrintData(self.print_data)
+ dlg = wx.PageSetupDialog(self.parent, data)
+ try:
+ if dlg.ShowModal() == wx.ID_OK:
+ data = dlg.GetPageSetupData() # returns wx.PageSetupDialogData
+ # updates page parameters from dialog
+ self.pageSetupData.SetMarginBottomRight(
+ data.GetMarginBottomRight())
+ self.pageSetupData.SetMarginTopLeft(data.GetMarginTopLeft())
+ self.pageSetupData.SetPrintData(data.GetPrintData())
+ self._print_data = wx.PrintData(
+ data.GetPrintData()) # updates print_data
+ finally:
+ dlg.Destroy()
+
+ def Printout(self, paper=None):
+ """Print current plot."""
+ if paper != None:
+ self.print_data.SetPaperId(paper)
+ pdd = wx.PrintDialogData(self.print_data)
+ printer = wx.Printer(pdd)
+ out = PlotPrintout(self)
+ print_ok = printer.Print(self.parent, out)
+ if print_ok:
+ self._print_data = wx.PrintData(
+ printer.GetPrintDialogData().GetPrintData())
+ out.Destroy()
+
+ def PrintPreview(self):
+ """Print-preview current plot."""
+ printout = PlotPrintout(self)
+ printout2 = PlotPrintout(self)
+ self.preview = wx.PrintPreview(printout, printout2, self.print_data)
+ if not self.preview.IsOk():
+ wx.MessageDialog(self, "Print Preview failed.\n"
+ "Check that default printer is configured\n",
+ "Print error", wx.OK | wx.CENTRE).ShowModal()
+ self.preview.SetZoom(40)
+ # search up tree to find frame instance
+ frameInst = self
+ while not isinstance(frameInst, wx.Frame):
+ frameInst = frameInst.GetParent()
+ frame = wx.PreviewFrame(self.preview, frameInst, "Preview")
+ frame.Initialize()
+ frame.SetPosition(self.GetPosition())
+ frame.SetSize((600, 550))
+ frame.Centre(wx.BOTH)
+ frame.Show(True)
+
+ def setLogScale(self, logscale):
+ if type(logscale) != tuple:
+ raise TypeError(
+ 'logscale must be a tuple of bools, e.g. (False, False)')
+ if self.last_draw is not None:
+ graphics, xAxis, yAxis = self.last_draw
+ graphics.setLogScale(logscale)
+ self.last_draw = (graphics, None, None)
+ self.SetXSpec('min')
+ self.SetYSpec('min')
+ self._logscale = logscale
+
+ def getLogScale(self):
+ return self._logscale
+
+ def SetFontSizeAxis(self, point=10):
+ """Set the tick and axis label font size (default is 10 point)"""
+ self._fontSizeAxis = point
+
+ def GetFontSizeAxis(self):
+ """Get current tick and axis label font size in points"""
+ return self._fontSizeAxis
+
+ def SetFontSizeTitle(self, point=15):
+ """Set Title font size (default is 15 point)"""
+ self._fontSizeTitle = point
+
+ def GetFontSizeTitle(self):
+ """Get current Title font size in points"""
+ return self._fontSizeTitle
+
+ def SetFontSizeLegend(self, point=7):
+ """Set Legend font size (default is 7 point)"""
+ self._fontSizeLegend = point
+
+ def GetFontSizeLegend(self):
+ """Get current Legend font size in points"""
+ return self._fontSizeLegend
+
+ def SetShowScrollbars(self, value):
+ """Set True to show scrollbars"""
+ if value not in [True, False]:
+ raise TypeError("Value should be True or False")
+ if value == self.GetShowScrollbars():
+ return
+ self.sb_vert.Show(value)
+ self.sb_hor.Show(value)
+ wx.CallAfter(self.Layout)
+
+ def GetShowScrollbars(self):
+ """Set True to show scrollbars"""
+ return self.sb_vert.IsShown()
+
+ def SetUseScientificNotation(self, useScientificNotation):
+ self._useScientificNotation = useScientificNotation
+
+ def GetUseScientificNotation(self):
+ return self._useScientificNotation
+
+ def SetEnableAntiAliasing(self, enableAntiAliasing):
+ """Set True to enable anti-aliasing."""
+ self._antiAliasingEnabled = enableAntiAliasing
+ self.Redraw()
+
+ def GetEnableAntiAliasing(self):
+ return self._antiAliasingEnabled
+
+ def SetEnableHiRes(self, enableHiRes):
+ """Set True to enable high-resolution mode when using anti-aliasing."""
+ self._hiResEnabled = enableHiRes
+ self.Redraw()
+
+ def GetEnableHiRes(self):
+ return self._hiResEnabled
+
+ def SetEnableDrag(self, value):
+ """Set True to enable drag."""
+ if value not in [True, False]:
+ raise TypeError("Value should be True or False")
+ if value:
+ if self.GetEnableZoom():
+ self.SetEnableZoom(False)
+ self.SetCursor(self.HandCursor)
+ else:
+ self.SetCursor(wx.CROSS_CURSOR)
+ self._dragEnabled = value
+
+ def GetEnableDrag(self):
+ return self._dragEnabled
+
+ def SetEnableZoom(self, value):
+ """Set True to enable zooming."""
+ if value not in [True, False]:
+ raise TypeError("Value should be True or False")
+ if value:
+ if self.GetEnableDrag():
+ self.SetEnableDrag(False)
+ self.SetCursor(self.MagCursor)
+ else:
+ self.SetCursor(wx.CROSS_CURSOR)
+ self._zoomEnabled = value
+
+ def GetEnableZoom(self):
+ """True if zooming enabled."""
+ return self._zoomEnabled
+
+ def SetEnableGrid(self, value):
+ """Set True, 'Horizontal' or 'Vertical' to enable grid."""
+ if value not in [True, False, 'Horizontal', 'Vertical']:
+ raise TypeError(
+ "Value should be True, False, Horizontal or Vertical")
+ self._gridEnabled = value
+ self.Redraw()
+
+ def GetEnableGrid(self):
+ """True if grid enabled."""
+ return self._gridEnabled
+
+ def SetEnableCenterLines(self, value):
+ """Set True, 'Horizontal' or 'Vertical' to enable center line(s)."""
+ if value not in [True, False, 'Horizontal', 'Vertical']:
+ raise TypeError(
+ "Value should be True, False, Horizontal or Vertical")
+ self._centerLinesEnabled = value
+ self.Redraw()
+
+ def GetEnableCenterLines(self):
+ """True if grid enabled."""
+ return self._centerLinesEnabled
+
+ def SetEnableDiagonals(self, value):
+ """Set True, 'Bottomleft-Topright' or 'Bottomright-Topleft' to enable
+ center line(s)."""
+ if value not in [True, False, 'Bottomleft-Topright', 'Bottomright-Topleft']:
+ raise TypeError(
+ "Value should be True, False, Bottomleft-Topright or Bottomright-Topleft")
+ self._diagonalsEnabled = value
+ self.Redraw()
+
+ def GetEnableDiagonals(self):
+ """True if grid enabled."""
+ return self._diagonalsEnabled
+
+ def SetEnableLegend(self, value):
+ """Set True to enable legend."""
+ if value not in [True, False]:
+ raise TypeError("Value should be True or False")
+ self._legendEnabled = value
+ self.Redraw()
+
+ def GetEnableLegend(self):
+ """True if Legend enabled."""
+ return self._legendEnabled
+
+ def SetEnableTitle(self, value):
+ """Set True to enable title."""
+ if value not in [True, False]:
+ raise TypeError("Value should be True or False")
+ self._titleEnabled = value
+ self.Redraw()
+
+ def GetEnableTitle(self):
+ """True if title enabled."""
+ return self._titleEnabled
+
+ def SetEnablePointLabel(self, value):
+ """Set True to enable pointLabel."""
+ if value not in [True, False]:
+ raise TypeError("Value should be True or False")
+ self._pointLabelEnabled = value
+ self.Redraw() # will erase existing pointLabel if present
+ self.last_PointLabel = None
+
+ def GetEnablePointLabel(self):
+ """True if pointLabel enabled."""
+ return self._pointLabelEnabled
+
+ def SetPointLabelFunc(self, func):
+ """Sets the function with custom code for pointLabel drawing
+ ******** more info needed ***************
+ """
+ self._pointLabelFunc = func
+
+ def GetPointLabelFunc(self):
+ """Returns pointLabel Drawing Function"""
+ return self._pointLabelFunc
+
+ def Reset(self):
+ """Unzoom the plot."""
+ self.last_PointLabel = None # reset pointLabel
+ if self.last_draw is not None:
+ self._Draw(self.last_draw[0])
+
+ def ScrollRight(self, units):
+ """Move view right number of axis units."""
+ self.last_PointLabel = None # reset pointLabel
+ if self.last_draw is not None:
+ graphics, xAxis, yAxis = self.last_draw
+ xAxis = (xAxis[0] + units, xAxis[1] + units)
+ self._Draw(graphics, xAxis, yAxis)
+
+ def ScrollUp(self, units):
+ """Move view up number of axis units."""
+ self.last_PointLabel = None # reset pointLabel
+ if self.last_draw is not None:
+ graphics, xAxis, yAxis = self.last_draw
+ yAxis = (yAxis[0] + units, yAxis[1] + units)
+ self._Draw(graphics, xAxis, yAxis)
+
+ def GetXY(self, event):
+ """Wrapper around _getXY, which handles log scales"""
+ x, y = self._getXY(event)
+ if self.getLogScale()[0]:
+ x = np.power(10, x)
+ if self.getLogScale()[1]:
+ y = np.power(10, y)
+ return x, y
+
+ def _getXY(self, event):
+ """Takes a mouse event and returns the XY user axis values."""
+ x, y = self.PositionScreenToUser(event.GetPosition())
+ return x, y
+
+ def PositionUserToScreen(self, pntXY):
+ """Converts User position to Screen Coordinates"""
+ userPos = np.array(pntXY)
+ x, y = userPos * self._pointScale + self._pointShift
+ return x, y
+
+ def PositionScreenToUser(self, pntXY):
+ """Converts Screen position to User Coordinates"""
+ screenPos = np.array(pntXY)
+ x, y = (screenPos - self._pointShift) / self._pointScale
+ return x, y
+
+ def SetXSpec(self, type='auto'):
+ """xSpec- defines x axis type. Can be 'none', 'min' or 'auto'
+ where:
+
+ * 'none' - shows no axis or tick mark values
+ * 'min' - shows min bounding box values
+ * 'auto' - rounds axis range to sensible values
+ * <number> - like 'min', but with <number> tick marks
+ """
+ self._xSpec = type
+
+ def SetYSpec(self, type='auto'):
+ """ySpec- defines x axis type. Can be 'none', 'min' or 'auto'
+ where:
+
+ * 'none' - shows no axis or tick mark values
+ * 'min' - shows min bounding box values
+ * 'auto' - rounds axis range to sensible values
+ * <number> - like 'min', but with <number> tick marks
+ """
+ self._ySpec = type
+
+ def GetXSpec(self):
+ """Returns current XSpec for axis"""
+ return self._xSpec
+
+ def GetYSpec(self):
+ """Returns current YSpec for axis"""
+ return self._ySpec
+
+ def GetXMaxRange(self):
+ xAxis = self._getXMaxRange()
+ if self.getLogScale()[0]:
+ xAxis = np.power(10, xAxis)
+ return xAxis
+
+ def _getXMaxRange(self):
+ """Returns (minX, maxX) x-axis range for displayed graph"""
+ graphics = self.last_draw[0]
+ p1, p2 = graphics.boundingBox() # min, max points of graphics
+ xAxis = self._axisInterval(self._xSpec, p1[0], p2[0]) # in user units
+ return xAxis
+
+ def GetYMaxRange(self):
+ yAxis = self._getYMaxRange()
+ if self.getLogScale()[1]:
+ yAxis = np.power(10, yAxis)
+ return yAxis
+
+ def _getYMaxRange(self):
+ """Returns (minY, maxY) y-axis range for displayed graph"""
+ graphics = self.last_draw[0]
+ p1, p2 = graphics.boundingBox() # min, max points of graphics
+ yAxis = self._axisInterval(self._ySpec, p1[1], p2[1])
+ return yAxis
+
+ def GetXCurrentRange(self):
+ xAxis = self._getXCurrentRange()
+ if self.getLogScale()[0]:
+ xAxis = np.power(10, xAxis)
+ return xAxis
+
+ def _getXCurrentRange(self):
+ """Returns (minX, maxX) x-axis for currently displayed portion of graph"""
+ return self.last_draw[1]
+
+ def GetYCurrentRange(self):
+ yAxis = self._getYCurrentRange()
+ if self.getLogScale()[1]:
+ yAxis = np.power(10, yAxis)
+ return yAxis
+
+ def _getYCurrentRange(self):
+ """Returns (minY, maxY) y-axis for currently displayed portion of graph"""
+ return self.last_draw[2]
+
+ def Draw(self, graphics, xAxis=None, yAxis=None, dc=None):
+ """Wrapper around _Draw, which handles log axes"""
+
+ graphics.setLogScale(self.getLogScale())
+
+ # check Axis is either tuple or none
+ if type(xAxis) not in [type(None), tuple]:
+ raise TypeError(
+ "xAxis should be None or (minX,maxX)" + str(type(xAxis)))
+ if type(yAxis) not in [type(None), tuple]:
+ raise TypeError(
+ "yAxis should be None or (minY,maxY)" + str(type(xAxis)))
+
+ # check case for axis = (a,b) where a==b caused by improper zooms
+ if xAxis != None:
+ if xAxis[0] == xAxis[1]:
+ return
+ if self.getLogScale()[0]:
+ xAxis = np.log10(xAxis)
+ if yAxis != None:
+ if yAxis[0] == yAxis[1]:
+ return
+ if self.getLogScale()[1]:
+ yAxis = np.log10(yAxis)
+ self._Draw(graphics, xAxis, yAxis, dc)
+
+ def _Draw(self, graphics, xAxis=None, yAxis=None, dc=None):
+ """\
+ Draw objects in graphics with specified x and y axis.
+ graphics- instance of PlotGraphics with list of PolyXXX objects
+ xAxis - tuple with (min, max) axis range to view
+ yAxis - same as xAxis
+ dc - drawing context - doesn't have to be specified.
+ If it's not, the offscreen buffer is used
+ """
+
+ if dc == None:
+ # sets new dc and clears it
+ dc = wx.BufferedDC(wx.ClientDC(self.canvas), self._Buffer)
+ bbr = wx.Brush(self.GetBackgroundColour(), wx.BRUSHSTYLE_SOLID)
+ dc.SetBackground(bbr)
+ dc.SetBackgroundMode(wx.SOLID)
+ dc.Clear()
+ if self._antiAliasingEnabled:
+ if not isinstance(dc, wx.GCDC):
+ try:
+ dc = wx.GCDC(dc)
+ except Exception:
+ pass
+ else:
+ if self._hiResEnabled:
+ # high precision - each logical unit is 1/20 of a point
+ dc.SetMapMode(wx.MM_TWIPS)
+ self._pointSize = tuple(
+ 1.0 / lscale for lscale in dc.GetLogicalScale())
+ self._setSize()
+ elif self._pointSize != (1.0, 1.0):
+ self._pointSize = (1.0, 1.0)
+ self._setSize()
+ if (sys.platform in ("darwin", "win32") or not isinstance(dc, wx.GCDC) or wx.VERSION >= (2, 9)):
+ self._fontScale = sum(self._pointSize) / 2.0
+ else:
+ # on Linux, we need to correct the font size by a certain factor if wx.GCDC is used,
+ # to make text the same size as if wx.GCDC weren't used
+ screenppi = map(float, wx.ScreenDC().GetPPI())
+ ppi = dc.GetPPI()
+ self._fontScale = (screenppi[
+ 0] / ppi[0] * self._pointSize[0] + screenppi[1] / ppi[1] * self._pointSize[1]) / 2.0
+ graphics._pointSize = self._pointSize
+
+ dc.SetTextForeground(self.GetForegroundColour())
+ dc.SetTextBackground(self.GetBackgroundColour())
+
+ # dc.Clear()
+
+ # set font size for every thing but title and legend
+ dc.SetFont(self._getFont(self._fontSizeAxis))
+
+ # sizes axis to axis type, create lower left and upper right corners of
+ # plot
+ if xAxis == None or yAxis == None:
+ # One or both axis not specified in Draw
+ p1, p2 = graphics.boundingBox() # min, max points of graphics
+ if xAxis == None:
+ xAxis = self._axisInterval(
+ self._xSpec, p1[0], p2[0]) # in user units
+ if yAxis == None:
+ yAxis = self._axisInterval(self._ySpec, p1[1], p2[1])
+ # Adjust bounding box for axis spec
+ # lower left corner user scale (xmin,ymin)
+ p1[0], p1[1] = xAxis[0], yAxis[0]
+ # upper right corner user scale (xmax,ymax)
+ p2[0], p2[1] = xAxis[1], yAxis[1]
+ else:
+ # Both axis specified in Draw
+ # lower left corner user scale (xmin,ymin)
+ p1 = np.array([xAxis[0], yAxis[0]])
+ # upper right corner user scale (xmax,ymax)
+ p2 = np.array([xAxis[1], yAxis[1]])
+
+ # saves most recient values
+ self.last_draw = (graphics, np.array(xAxis), np.array(yAxis))
+
+ # Get ticks and textExtents for axis if required
+ if self._xSpec is not 'none':
+ xticks = self._xticks(xAxis[0], xAxis[1])
+ else:
+ xticks = None
+ if xticks:
+ # w h of x axis text last number on axis
+ xTextExtent = dc.GetTextExtent(xticks[-1][1])
+ else:
+ xTextExtent = (0, 0) # No text for ticks
+ if self._ySpec is not 'none':
+ yticks = self._yticks(yAxis[0], yAxis[1])
+ else:
+ yticks = None
+ if yticks:
+ if self.getLogScale()[1]:
+ yTextExtent = dc.GetTextExtent('-2e-2')
+ else:
+ yTextExtentBottom = dc.GetTextExtent(yticks[0][1])
+ yTextExtentTop = dc.GetTextExtent(yticks[-1][1])
+ yTextExtent = (max(yTextExtentBottom[0], yTextExtentTop[0]),
+ max(yTextExtentBottom[1], yTextExtentTop[1]))
+ else:
+ yticks = None
+ yTextExtent = (0, 0) # No text for ticks
+
+ # TextExtents for Title and Axis Labels
+ titleWH, xLabelWH, yLabelWH = self._titleLablesWH(dc, graphics)
+
+ # TextExtents for Legend
+ legendBoxWH, legendSymExt, legendTextExt = self._legendWH(dc, graphics)
+
+ # room around graph area
+ # use larger of number width or legend width
+ rhsW = max(xTextExtent[0], legendBoxWH[0]) + 5 * self._pointSize[0]
+ lhsW = yTextExtent[0] + yLabelWH[1] + 3 * self._pointSize[0]
+ bottomH = max(
+ xTextExtent[1], yTextExtent[1] / 2.) + xLabelWH[1] + 2 * self._pointSize[1]
+ topH = yTextExtent[1] / 2. + titleWH[1]
+ # make plot area smaller by text size
+ textSize_scale = np.array([rhsW + lhsW, bottomH + topH])
+ # shift plot area by this amount
+ textSize_shift = np.array([lhsW, bottomH])
+
+ # draw title if requested
+ if self._titleEnabled:
+ dc.SetFont(self._getFont(self._fontSizeTitle))
+ titlePos = (self.plotbox_origin[0] + lhsW + (self.plotbox_size[0] - lhsW - rhsW) / 2. - titleWH[0] / 2.,
+ self.plotbox_origin[1] - self.plotbox_size[1])
+ dc.DrawText(graphics.getTitle(), titlePos[0], titlePos[1])
+
+ # draw label text
+ dc.SetFont(self._getFont(self._fontSizeAxis))
+ xLabelPos = (self.plotbox_origin[0] + lhsW + (self.plotbox_size[0] - lhsW - rhsW) / 2. - xLabelWH[0] / 2.,
+ self.plotbox_origin[1] - xLabelWH[1])
+ dc.DrawText(graphics.getXLabel(), xLabelPos[0], xLabelPos[1])
+ yLabelPos = (self.plotbox_origin[0] - 3 * self._pointSize[0],
+ self.plotbox_origin[1] - bottomH - (self.plotbox_size[1] - bottomH - topH) / 2. + yLabelWH[0] / 2.)
+ if graphics.getYLabel(): # bug fix for Linux
+ dc.DrawRotatedText(
+ graphics.getYLabel(), yLabelPos[0], yLabelPos[1], 90)
+
+ # drawing legend makers and text
+ if self._legendEnabled:
+ self._drawLegend(
+ dc, graphics, rhsW, topH, legendBoxWH, legendSymExt, legendTextExt)
+
+ # allow for scaling and shifting plotted points
+ scale = (self.plotbox_size - textSize_scale) / \
+ (p2 - p1) * np.array((1, -1))
+ shift = -p1 * scale + self.plotbox_origin + \
+ textSize_shift * np.array((1, -1))
+ # make available for mouse events
+ self._pointScale = scale / self._pointSize
+ self._pointShift = shift / self._pointSize
+ self._drawAxes(dc, p1, p2, scale, shift, xticks, yticks)
+
+ graphics.scaleAndShift(scale, shift)
+ # thicken up lines and markers if printing
+ graphics.setPrinterScale(self.printerScale)
+
+ # set clipping area so drawing does not occur outside axis box
+ ptx, pty, rectWidth, rectHeight = self._point2ClientCoord(p1, p2)
+ # allow graph to overlap axis lines by adding units to width and height
+ dc.SetClippingRegion(ptx * self._pointSize[0], pty * self._pointSize[
+ 1], rectWidth * self._pointSize[0] + 2, rectHeight * self._pointSize[1] + 1)
+ # Draw the lines and markers
+ #start = _time.clock()
+ graphics.draw(dc)
+ # print("entire graphics drawing took: %f second"%(_time.clock() - start))
+ # remove the clipping region
+ dc.DestroyClippingRegion()
+
+ self._adjustScrollbars()
+
+ def Redraw(self, dc=None):
+ """Redraw the existing plot."""
+ if self.last_draw is not None:
+ graphics, xAxis, yAxis = self.last_draw
+ self._Draw(graphics, xAxis, yAxis, dc)
+
+ def Clear(self):
+ """Erase the window."""
+ self.last_PointLabel = None # reset pointLabel
+ dc = wx.BufferedDC(wx.ClientDC(self.canvas), self._Buffer)
+ bbr = wx.Brush(self.GetBackgroundColour(), wx.SOLID)
+ dc.SetBackground(bbr)
+ dc.SetBackgroundMode(wx.SOLID)
+ dc.Clear()
+ if self._antiAliasingEnabled:
+ try:
+ dc = wx.GCDC(dc)
+ except Exception:
+ pass
+ dc.SetTextForeground(self.GetForegroundColour())
+ dc.SetTextBackground(self.GetBackgroundColour())
+ self.last_draw = None
+
+ def Zoom(self, Center, Ratio):
+ """ Zoom on the plot
+ Centers on the X,Y coords given in Center
+ Zooms by the Ratio = (Xratio, Yratio) given
+ """
+ self.last_PointLabel = None # reset maker
+ x, y = Center
+ if self.last_draw != None:
+ (graphics, xAxis, yAxis) = self.last_draw
+ w = (xAxis[1] - xAxis[0]) * Ratio[0]
+ h = (yAxis[1] - yAxis[0]) * Ratio[1]
+ xAxis = (x - w / 2, x + w / 2)
+ yAxis = (y - h / 2, y + h / 2)
+ self._Draw(graphics, xAxis, yAxis)
+
+ def GetClosestPoints(self, pntXY, pointScaled=True):
+ """Returns list with
+ [curveNumber, legend, index of closest point, pointXY, scaledXY, distance]
+ list for each curve.
+ Returns [] if no curves are being plotted.
+
+ x, y in user coords
+ if pointScaled == True based on screen coords
+ if pointScaled == False based on user coords
+ """
+ if self.last_draw == None:
+ # no graph available
+ return []
+ graphics, xAxis, yAxis = self.last_draw
+ l = []
+ for curveNum, obj in enumerate(graphics):
+ # check there are points in the curve
+ if len(obj.points) == 0:
+ continue # go to next obj
+ #[curveNumber, legend, index of closest point, pointXY, scaledXY, distance]
+ cn = [curveNum] + \
+ [obj.getLegend()] + obj.getClosestPoint(pntXY, pointScaled)
+ l.append(cn)
+ return l
+
+ def GetClosestPoint(self, pntXY, pointScaled=True):
+ """Returns list with
+ [curveNumber, legend, index of closest point, pointXY, scaledXY, distance]
+ list for only the closest curve.
+ Returns [] if no curves are being plotted.
+
+ x, y in user coords
+ if pointScaled == True based on screen coords
+ if pointScaled == False based on user coords
+ """
+ # closest points on screen based on screen scaling (pointScaled= True)
+ # list [curveNumber, index, pointXY, scaledXY, distance] for each curve
+ closestPts = self.GetClosestPoints(pntXY, pointScaled)
+ if closestPts == []:
+ return [] # no graph present
+ # find one with least distance
+ dists = [c[-1] for c in closestPts]
+ mdist = min(dists) # Min dist
+ i = dists.index(mdist) # index for min dist
+ return closestPts[i] # this is the closest point on closest curve
+
+ GetClosetPoint = GetClosestPoint
+
+ def UpdatePointLabel(self, mDataDict):
+ """Updates the pointLabel point on screen with data contained in
+ mDataDict.
+
+ mDataDict will be passed to your function set by
+ SetPointLabelFunc. It can contain anything you
+ want to display on the screen at the scaledXY point
+ you specify.
+
+ This function can be called from parent window with onClick,
+ onMotion events etc.
+ """
+ if self.last_PointLabel != None:
+ # compare pointXY
+ if np.sometrue(mDataDict["pointXY"] != self.last_PointLabel["pointXY"]):
+ # closest changed
+ self._drawPointLabel(self.last_PointLabel) # erase old
+ self._drawPointLabel(mDataDict) # plot new
+ else:
+ # just plot new with no erase
+ self._drawPointLabel(mDataDict) # plot new
+ # save for next erase
+ self.last_PointLabel = mDataDict
+
+ # event handlers **********************************
+ def OnMotion(self, event):
+ if self._zoomEnabled and event.LeftIsDown():
+ if self._hasDragged:
+ self._drawRubberBand(
+ self._zoomCorner1, self._zoomCorner2) # remove old
+ else:
+ self._hasDragged = True
+ self._zoomCorner2[0], self._zoomCorner2[1] = self._getXY(event)
+ self._drawRubberBand(
+ self._zoomCorner1, self._zoomCorner2) # add new
+ elif self._dragEnabled and event.LeftIsDown():
+ coordinates = event.GetPosition()
+ newpos, oldpos = map(np.array, map(
+ self.PositionScreenToUser, [coordinates, self._screenCoordinates]))
+ dist = newpos - oldpos
+ self._screenCoordinates = coordinates
+
+ if self.last_draw is not None:
+ graphics, xAxis, yAxis = self.last_draw
+ yAxis -= dist[1]
+ xAxis -= dist[0]
+ self._Draw(graphics, xAxis, yAxis)
+
+ def OnMouseLeftDown(self, event):
+ self._zoomCorner1[0], self._zoomCorner1[1] = self._getXY(event)
+ self._screenCoordinates = np.array(event.GetPosition())
+ if self._dragEnabled:
+ self.SetCursor(self.GrabHandCursor)
+ self.canvas.CaptureMouse()
+
+ def OnMouseLeftUp(self, event):
+ if self._zoomEnabled:
+ if self._hasDragged == True:
+ self._drawRubberBand(
+ self._zoomCorner1, self._zoomCorner2) # remove old
+ self._zoomCorner2[0], self._zoomCorner2[1] = self._getXY(event)
+ self._hasDragged = False # reset flag
+ minX, minY = np.minimum(self._zoomCorner1, self._zoomCorner2)
+ maxX, maxY = np.maximum(self._zoomCorner1, self._zoomCorner2)
+ self.last_PointLabel = None # reset pointLabel
+ if self.last_draw != None:
+ self._Draw(
+ self.last_draw[0], xAxis=(minX, maxX), yAxis = (minY, maxY), dc = None)
+ # else: # A box has not been drawn, zoom in on a point
+ # this interfered with the double click, so I've disables it.
+ # X,Y = self._getXY(event)
+ # self.Zoom( (X,Y), (self._zoomInFactor,self._zoomInFactor) )
+ if self._dragEnabled:
+ self.SetCursor(self.HandCursor)
+ if self.canvas.HasCapture():
+ self.canvas.ReleaseMouse()
+
+ def OnMouseDoubleClick(self, event):
+ if self._zoomEnabled:
+ # Give a little time for the click to be totally finished
+ # before (possibly) removing the scrollbars and trigering
+ # size events, etc.
+ wx.CallLater(200, self.Reset)
+
+ def OnMouseRightDown(self, event):
+ if self._zoomEnabled:
+ X, Y = self._getXY(event)
+ self.Zoom((X, Y), (self._zoomOutFactor, self._zoomOutFactor))
+
+ def OnPaint(self, event):
+ # All that is needed here is to draw the buffer to screen
+ if self.last_PointLabel != None:
+ self._drawPointLabel(self.last_PointLabel) # erase old
+ self.last_PointLabel = None
+ dc = wx.BufferedPaintDC(self.canvas, self._Buffer)
+ if self._antiAliasingEnabled:
+ try:
+ dc = wx.GCDC(dc)
+ except Exception:
+ pass
+
+ def OnSize(self, event):
+ # The Buffer init is done here, to make sure the buffer is always
+ # the same size as the Window
+ Size = self.canvas.GetClientSize()
+ Size.width = max(1, Size.width)
+ Size.height = max(1, Size.height)
+
+ # Make new offscreen bitmap: this bitmap will always have the
+ # current drawing in it, so it can be used to save the image to
+ # a file, or whatever.
+ self._Buffer = wx.Bitmap(Size.width, Size.height)
+ self._setSize()
+
+ self.last_PointLabel = None # reset pointLabel
+
+ if self.last_draw is None:
+ self.Clear()
+ else:
+ graphics, xSpec, ySpec = self.last_draw
+ self._Draw(graphics, xSpec, ySpec)
+
+ def OnLeave(self, event):
+ """Used to erase pointLabel when mouse outside window"""
+ if self.last_PointLabel != None:
+ self._drawPointLabel(self.last_PointLabel) # erase old
+ self.last_PointLabel = None
+
+ def OnScroll(self, evt):
+ if not self._adjustingSB:
+ self._sb_ignore = True
+ sbpos = evt.GetPosition()
+
+ if evt.GetOrientation() == wx.VERTICAL:
+ fullrange, pagesize = self.sb_vert.GetRange(
+ ), self.sb_vert.GetPageSize()
+ sbpos = fullrange - pagesize - sbpos
+ dist = sbpos * self._sb_xunit - \
+ (self._getXCurrentRange()[0] - self._sb_xfullrange)
+ self.ScrollUp(dist)
+
+ if evt.GetOrientation() == wx.HORIZONTAL:
+ dist = sbpos * self._sb_xunit - \
+ (self._getXCurrentRange()[0] - self._sb_xfullrange[0])
+ self.ScrollRight(dist)
+
+ # Private Methods **************************************************
+ def _setSize(self, width=None, height=None):
+ """DC width and height."""
+ if width == None:
+ (self.width, self.height) = self.canvas.GetClientSize()
+ else:
+ self.width, self.height = width, height
+ self.width *= self._pointSize[0] # high precision
+ self.height *= self._pointSize[1] # high precision
+ self.plotbox_size = 0.97 * np.array([self.width, self.height])
+ xo = 0.5 * (self.width - self.plotbox_size[0])
+ yo = self.height - 0.5 * (self.height - self.plotbox_size[1])
+ self.plotbox_origin = np.array([xo, yo])
+
+ def _setPrinterScale(self, scale):
+ """Used to thicken lines and increase marker size for print out."""
+ # line thickness on printer is very thin at 600 dot/in. Markers small
+ self.printerScale = scale
+
+ def _printDraw(self, printDC):
+ """Used for printing."""
+ if self.last_draw != None:
+ graphics, xSpec, ySpec = self.last_draw
+ self._Draw(graphics, xSpec, ySpec, printDC)
+
+ def _drawPointLabel(self, mDataDict):
+ """Draws and erases pointLabels"""
+ width = self._Buffer.GetWidth()
+ height = self._Buffer.GetHeight()
+ if sys.platform != "darwin":
+ tmp_Buffer = wx.Bitmap(width, height)
+ dcs = wx.MemoryDC()
+ dcs.SelectObject(tmp_Buffer)
+ dcs.Clear()
+ else:
+ tmp_Buffer = self._Buffer.GetSubBitmap((0, 0, width, height))
+ dcs = wx.MemoryDC(self._Buffer)
+ self._pointLabelFunc(dcs, mDataDict) # custom user pointLabel function
+
+ dc = wx.ClientDC(self.canvas)
+ dc = wx.BufferedDC(dc, self._Buffer)
+ # this will erase if called twice
+ dc.Blit(0, 0, width, height, dcs, 0, 0, self._logicalFunction)
+ if sys.platform == "darwin":
+ self._Buffer = tmp_Buffer
+
+ def _drawLegend(self, dc, graphics, rhsW, topH, legendBoxWH, legendSymExt, legendTextExt):
+ """Draws legend symbols and text"""
+ # top right hand corner of graph box is ref corner
+ trhc = self.plotbox_origin + \
+ (self.plotbox_size - [rhsW, topH]) * [1, -1]
+ # border space between legend sym and graph box
+ legendLHS = .091 * legendBoxWH[0]
+ # 1.1 used as space between lines
+ lineHeight = max(legendSymExt[1], legendTextExt[1]) * 1.1
+ dc.SetFont(self._getFont(self._fontSizeLegend))
+ for i in range(len(graphics)):
+ o = graphics[i]
+ s = i * lineHeight
+ if isinstance(o, PolyMarker):
+ # draw marker with legend
+ pnt = (trhc[0] + legendLHS + legendSymExt[0] / 2.,
+ trhc[1] + s + lineHeight / 2.)
+ o.draw(dc, self.printerScale, coord=np.array([pnt]))
+ elif isinstance(o, PolyLine):
+ # draw line with legend
+ pnt1 = (trhc[0] + legendLHS, trhc[1] + s + lineHeight / 2.)
+ pnt2 = (trhc[0] + legendLHS + legendSymExt[0],
+ trhc[1] + s + lineHeight / 2.)
+ o.draw(dc, self.printerScale, coord=np.array([pnt1, pnt2]))
+ else:
+ raise TypeError(
+ "object is neither PolyMarker or PolyLine instance")
+ # draw legend txt
+ pnt = (trhc[0] + legendLHS + legendSymExt[0] + 5 * self._pointSize[0],
+ trhc[1] + s + lineHeight / 2. - legendTextExt[1] / 2)
+ dc.DrawText(o.getLegend(), pnt[0], pnt[1])
+ dc.SetFont(self._getFont(self._fontSizeAxis)) # reset
+
+ def _titleLablesWH(self, dc, graphics):
+ """Draws Title and labels and returns width and height for each"""
+ # TextExtents for Title and Axis Labels
+ dc.SetFont(self._getFont(self._fontSizeTitle))
+ if self._titleEnabled:
+ title = graphics.getTitle()
+ titleWH = dc.GetTextExtent(title)
+ else:
+ titleWH = (0, 0)
+ dc.SetFont(self._getFont(self._fontSizeAxis))
+ xLabel, yLabel = graphics.getXLabel(), graphics.getYLabel()
+ xLabelWH = dc.GetTextExtent(xLabel)
+ yLabelWH = dc.GetTextExtent(yLabel)
+ return titleWH, xLabelWH, yLabelWH
+
+ def _legendWH(self, dc, graphics):
+ """Returns the size in screen units for legend box"""
+ if self._legendEnabled != True:
+ legendBoxWH = symExt = txtExt = (0, 0)
+ else:
+ # find max symbol size
+ symExt = graphics.getSymExtent(self.printerScale)
+ # find max legend text extent
+ dc.SetFont(self._getFont(self._fontSizeLegend))
+ txtList = graphics.getLegendNames()
+ txtExt = dc.GetTextExtent(txtList[0])
+ for txt in graphics.getLegendNames()[1:]:
+ txtExt = np.maximum(txtExt, dc.GetTextExtent(txt))
+ maxW = symExt[0] + txtExt[0]
+ maxH = max(symExt[1], txtExt[1])
+ # padding .1 for lhs of legend box and space between lines
+ maxW = maxW * 1.1
+ maxH = maxH * 1.1 * len(txtList)
+ dc.SetFont(self._getFont(self._fontSizeAxis))
+ legendBoxWH = (maxW, maxH)
+ return (legendBoxWH, symExt, txtExt)
+
+ def _drawRubberBand(self, corner1, corner2):
+ """Draws/erases rect box from corner1 to corner2"""
+ ptx, pty, rectWidth, rectHeight = self._point2ClientCoord(
+ corner1, corner2)
+ # draw rectangle
+ dc = wx.ClientDC(self.canvas)
+ dc.SetPen(wx.Pen(wx.BLACK))
+ dc.SetBrush(wx.Brush(wx.WHITE, wx.BRUSHSTYLE_TRANSPARENT))
+ dc.SetLogicalFunction(wx.INVERT)
+ dc.DrawRectangle(ptx, pty, rectWidth, rectHeight)
+ dc.SetLogicalFunction(wx.COPY)
+
+ def _getFont(self, size):
+ """Take font size, adjusts if printing and returns wx.Font"""
+ s = size * self.printerScale * self._fontScale
+ of = self.GetFont()
+ # Linux speed up to get font from cache rather than X font server
+ key = (int(s), of.GetFamily(), of.GetStyle(), of.GetWeight())
+ font = self._fontCache.get(key, None)
+ if font:
+ return font # yeah! cache hit
+ else:
+ font = wx.Font(
+ int(s), of.GetFamily(), of.GetStyle(), of.GetWeight())
+ self._fontCache[key] = font
+ return font
+
+ def _point2ClientCoord(self, corner1, corner2):
+ """Converts user point coords to client screen int coords x,y,width,height"""
+ c1 = np.array(corner1)
+ c2 = np.array(corner2)
+ # convert to screen coords
+ pt1 = c1 * self._pointScale + self._pointShift
+ pt2 = c2 * self._pointScale + self._pointShift
+ # make height and width positive
+ pul = np.minimum(pt1, pt2) # Upper left corner
+ plr = np.maximum(pt1, pt2) # Lower right corner
+ rectWidth, rectHeight = plr - pul
+ ptx, pty = pul
+ return ptx, pty, rectWidth, rectHeight
+
+ def _axisInterval(self, spec, lower, upper):
+ """Returns sensible axis range for given spec"""
+ if spec == 'none' or spec == 'min' or isinstance(spec, (float, int)):
+ if lower == upper:
+ return lower - 0.5, upper + 0.5
+ else:
+ return lower, upper
+ elif spec == 'auto':
+ range = upper - lower
+ if range == 0.:
+ return lower - 0.5, upper + 0.5
+ log = np.log10(range)
+ power = np.floor(log)
+ fraction = log - power
+ if fraction <= 0.05:
+ power = power - 1
+ grid = 10. ** power
+ lower = lower - lower % grid
+ mod = upper % grid
+ if mod != 0:
+ upper = upper - mod + grid
+ return lower, upper
+ elif type(spec) == type(()):
+ lower, upper = spec
+ if lower <= upper:
+ return lower, upper
+ else:
+ return upper, lower
+ else:
+ raise ValueError(str(spec) + ': illegal axis specification')
+
+ def _drawAxes(self, dc, p1, p2, scale, shift, xticks, yticks):
+
+ # increases thickness for printing only
+ penWidth = self.printerScale * self._pointSize[0]
+ dc.SetPen(wx.Pen(self._gridColour, penWidth))
+
+ # set length of tick marks--long ones make grid
+ if self._gridEnabled:
+ x, y, width, height = self._point2ClientCoord(p1, p2)
+ if self._gridEnabled == 'Horizontal':
+ yTickLength = (width / 2.0 + 1) * self._pointSize[1]
+ xTickLength = 3 * self.printerScale * self._pointSize[0]
+ elif self._gridEnabled == 'Vertical':
+ yTickLength = 3 * self.printerScale * self._pointSize[1]
+ xTickLength = (height / 2.0 + 1) * self._pointSize[0]
+ else:
+ yTickLength = (width / 2.0 + 1) * self._pointSize[1]
+ xTickLength = (height / 2.0 + 1) * self._pointSize[0]
+ else:
+ # lengthens lines for printing
+ yTickLength = 3 * self.printerScale * self._pointSize[1]
+ xTickLength = 3 * self.printerScale * self._pointSize[0]
+
+ if self._xSpec is not 'none':
+ lower, upper = p1[0], p2[0]
+ text = 1
+ # miny, maxy and tick lengths
+ for y, d in [(p1[1], -xTickLength), (p2[1], xTickLength)]:
+ for x, label in xticks:
+ pt = scale * np.array([x, y]) + shift
+ # draws tick mark d units
+ dc.DrawLine(pt[0], pt[1], pt[0], pt[1] + d)
+ if text:
+ dc.DrawText(
+ label, pt[0], pt[1] + 2 * self._pointSize[1])
+ a1 = scale * np.array([lower, y]) + shift
+ a2 = scale * np.array([upper, y]) + shift
+ # draws upper and lower axis line
+ dc.DrawLine(a1[0], a1[1], a2[0], a2[1])
+ text = 0 # axis values not drawn on top side
+
+ if self._ySpec is not 'none':
+ lower, upper = p1[1], p2[1]
+ text = 1
+ h = dc.GetCharHeight()
+ for x, d in [(p1[0], -yTickLength), (p2[0], yTickLength)]:
+ for y, label in yticks:
+ pt = scale * np.array([x, y]) + shift
+ dc.DrawLine(pt[0], pt[1], pt[0] - d, pt[1])
+ if text:
+ dc.DrawText(label, pt[0] - dc.GetTextExtent(label)[0] - 3 * self._pointSize[0],
+ pt[1] - 0.75 * h)
+ a1 = scale * np.array([x, lower]) + shift
+ a2 = scale * np.array([x, upper]) + shift
+ dc.DrawLine(a1[0], a1[1], a2[0], a2[1])
+ text = 0 # axis values not drawn on right side
+
+ if self._centerLinesEnabled:
+ if self._centerLinesEnabled in ('Horizontal', True):
+ y1 = scale[1] * p1[1] + shift[1]
+ y2 = scale[1] * p2[1] + shift[1]
+ y = (y1 - y2) / 2.0 + y2
+ dc.DrawLine(
+ scale[0] * p1[0] + shift[0], y, scale[0] * p2[0] + shift[0], y)
+ if self._centerLinesEnabled in ('Vertical', True):
+ x1 = scale[0] * p1[0] + shift[0]
+ x2 = scale[0] * p2[0] + shift[0]
+ x = (x1 - x2) / 2.0 + x2
+ dc.DrawLine(
+ x, scale[1] * p1[1] + shift[1], x, scale[1] * p2[1] + shift[1])
+
+ if self._diagonalsEnabled:
+ if self._diagonalsEnabled in ('Bottomleft-Topright', True):
+ dc.DrawLine(scale[0] * p1[0] + shift[0], scale[1] * p1[1] +
+ shift[1], scale[0] * p2[0] + shift[0], scale[1] * p2[1] + shift[1])
+ if self._diagonalsEnabled in ('Bottomright-Topleft', True):
+ dc.DrawLine(scale[0] * p1[0] + shift[0], scale[1] * p2[1] +
+ shift[1], scale[0] * p2[0] + shift[0], scale[1] * p1[1] + shift[1])
+
+ def _xticks(self, *args):
+ if self._logscale[0]:
+ return self._logticks(*args)
+ else:
+ attr = {'numticks': self._xSpec}
+ return self._ticks(*args, **attr)
+
+ def _yticks(self, *args):
+ if self._logscale[1]:
+ return self._logticks(*args)
+ else:
+ attr = {'numticks': self._ySpec}
+ return self._ticks(*args, **attr)
+
+ def _logticks(self, lower, upper):
+ #lower,upper = map(np.log10,[lower,upper])
+ # print('logticks',lower,upper)
+ ticks = []
+ mag = np.power(10, np.floor(lower))
+ if upper - lower > 6:
+ t = np.power(10, np.ceil(lower))
+ base = np.power(10, np.floor((upper - lower) / 6))
+
+ def inc(t):
+ return t * base - t
+ else:
+ t = np.ceil(np.power(10, lower) / mag) * mag
+
+ def inc(t):
+ return 10 ** int(np.floor(np.log10(t) + 1e-16))
+ majortick = int(np.log10(mag))
+ while t <= pow(10, upper):
+ if majortick != int(np.floor(np.log10(t) + 1e-16)):
+ majortick = int(np.floor(np.log10(t) + 1e-16))
+ ticklabel = '1e%d' % majortick
+ else:
+ if upper - lower < 2:
+ minortick = int(t / pow(10, majortick) + .5)
+ ticklabel = '%de%d' % (minortick, majortick)
+ else:
+ ticklabel = ''
+ ticks.append((np.log10(t), ticklabel))
+ t += inc(t)
+ if len(ticks) == 0:
+ ticks = [(0, '')]
+ return ticks
+
+ def _ticks(self, lower, upper, numticks=None):
+ if isinstance(numticks, (float, int)):
+ ideal = (upper - lower) / float(numticks)
+ else:
+ ideal = (upper - lower) / 7.
+ log = np.log10(ideal)
+ power = np.floor(log)
+ if isinstance(numticks, (float, int)):
+ grid = ideal
+ else:
+ fraction = log - power
+ factor = 1.
+ error = fraction
+ for f, lf in self._multiples:
+ e = np.fabs(fraction - lf)
+ if e < error:
+ error = e
+ factor = f
+ grid = factor * 10. ** power
+ if self._useScientificNotation and (power > 4 or power < -4):
+ format = '%+7.1e'
+ elif power >= 0:
+ digits = max(1, int(power))
+ format = '%' + repr(digits) + '.0f'
+ else:
+ digits = -int(power)
+ format = '%' + repr(digits + 2) + '.' + repr(digits) + 'f'
+ ticks = []
+ t = -grid * np.floor(-lower / grid)
+ while t <= upper:
+ if t == -0:
+ t = 0
+ ticks.append((t, format % (t,)))
+ t = t + grid
+ return ticks
+
+ _multiples = [(2., np.log10(2.)), (5., np.log10(5.))]
+
+ def _adjustScrollbars(self):
+ if self._sb_ignore:
+ self._sb_ignore = False
+ return
+
+ if not self.GetShowScrollbars():
+ return
+
+ self._adjustingSB = True
+ needScrollbars = False
+
+ # horizontal scrollbar
+ r_current = self._getXCurrentRange()
+ r_max = list(self._getXMaxRange())
+ sbfullrange = float(self.sb_hor.GetRange())
+
+ r_max[0] = min(r_max[0], r_current[0])
+ r_max[1] = max(r_max[1], r_current[1])
+
+ self._sb_xfullrange = r_max
+
+ unit = (r_max[1] - r_max[0]) / float(self.sb_hor.GetRange())
+ pos = int((r_current[0] - r_max[0]) / unit)
+
+ if pos >= 0:
+ pagesize = int((r_current[1] - r_current[0]) / unit)
+
+ self.sb_hor.SetScrollbar(pos, pagesize, sbfullrange, pagesize)
+ self._sb_xunit = unit
+ needScrollbars = needScrollbars or (pagesize != sbfullrange)
+ else:
+ self.sb_hor.SetScrollbar(0, 1000, 1000, 1000)
+
+ # vertical scrollbar
+ r_current = self._getYCurrentRange()
+ r_max = list(self._getYMaxRange())
+ sbfullrange = float(self.sb_vert.GetRange())
+
+ r_max[0] = min(r_max[0], r_current[0])
+ r_max[1] = max(r_max[1], r_current[1])
+
+ self._sb_yfullrange = r_max
+
+ unit = (r_max[1] - r_max[0]) / sbfullrange
+ pos = int((r_current[0] - r_max[0]) / unit)
+
+ if pos >= 0:
+ pagesize = int((r_current[1] - r_current[0]) / unit)
+ pos = (sbfullrange - 1 - pos - pagesize)
+ self.sb_vert.SetScrollbar(pos, pagesize, sbfullrange, pagesize)
+ self._sb_yunit = unit
+ needScrollbars = needScrollbars or (pagesize != sbfullrange)
+ else:
+ self.sb_vert.SetScrollbar(0, 1000, 1000, 1000)
+
+ self.SetShowScrollbars(needScrollbars)
+ self._adjustingSB = False
+
+#-------------------------------------------------------------------------
+# Used to layout the printer page
+
+
+class PlotPrintout(wx.Printout):
+
+ """Controls how the plot is made in printing and previewing"""
+ # Do not change method names in this class,
+ # we have to override wx.Printout methods here!
+
+ def __init__(self, graph):
+ """graph is instance of plotCanvas to be printed or previewed"""
+ wx.Printout.__init__(self)
+ self.graph = graph
+
+ def HasPage(self, page):
+ if page == 1:
+ return True
+ else:
+ return False
+
+ def GetPageInfo(self):
+ return (1, 1, 1, 1) # disable page numbers
+
+ def OnPrintPage(self, page):
+ dc = self.GetDC() # allows using floats for certain functions
+## print("PPI Printer",self.GetPPIPrinter())
+## print("PPI Screen", self.GetPPIScreen())
+## print("DC GetSize", dc.GetSize())
+## print("GetPageSizePixels", self.GetPageSizePixels())
+ # Note PPIScreen does not give the correct number
+ # Calulate everything for printer and then scale for preview
+ PPIPrinter = self.GetPPIPrinter() # printer dots/inch (w,h)
+ # PPIScreen= self.GetPPIScreen() # screen dots/inch (w,h)
+ dcSize = dc.GetSize() # DC size
+ if self.graph._antiAliasingEnabled and not isinstance(dc, wx.GCDC):
+ try:
+ dc = wx.GCDC(dc)
+ except Exception:
+ pass
+ else:
+ if self.graph._hiResEnabled:
+ # high precision - each logical unit is 1/20 of a point
+ dc.SetMapMode(wx.MM_TWIPS)
+ pageSize = self.GetPageSizePixels() # page size in terms of pixcels
+ clientDcSize = self.graph.GetClientSize()
+
+ # find what the margins are (mm)
+ margLeftSize, margTopSize = self.graph.pageSetupData.GetMarginTopLeft()
+ margRightSize, margBottomSize = self.graph.pageSetupData.GetMarginBottomRight()
+
+ # calculate offset and scale for dc
+ pixLeft = margLeftSize * PPIPrinter[0] / 25.4 # mm*(dots/in)/(mm/in)
+ pixRight = margRightSize * PPIPrinter[0] / 25.4
+ pixTop = margTopSize * PPIPrinter[1] / 25.4
+ pixBottom = margBottomSize * PPIPrinter[1] / 25.4
+
+ plotAreaW = pageSize[0] - (pixLeft + pixRight)
+ plotAreaH = pageSize[1] - (pixTop + pixBottom)
+
+ # ratio offset and scale to screen size if preview
+ if self.IsPreview():
+ ratioW = float(dcSize[0]) / pageSize[0]
+ ratioH = float(dcSize[1]) / pageSize[1]
+ pixLeft *= ratioW
+ pixTop *= ratioH
+ plotAreaW *= ratioW
+ plotAreaH *= ratioH
+
+ # rescale plot to page or preview plot area
+ self.graph._setSize(plotAreaW, plotAreaH)
+
+ # Set offset and scale
+ dc.SetDeviceOrigin(pixLeft, pixTop)
+
+ # Thicken up pens and increase marker size for printing
+ ratioW = float(plotAreaW) / clientDcSize[0]
+ ratioH = float(plotAreaH) / clientDcSize[1]
+ aveScale = (ratioW + ratioH) / 2
+ if self.graph._antiAliasingEnabled and not self.IsPreview():
+ scale = dc.GetUserScale()
+ dc.SetUserScale(
+ scale[0] / self.graph._pointSize[0], scale[1] / self.graph._pointSize[1])
+ self.graph._setPrinterScale(aveScale) # tickens up pens for printing
+
+ self.graph._printDraw(dc)
+ # rescale back to original
+ self.graph._setSize()
+ self.graph._setPrinterScale(1)
+ self.graph.Redraw() # to get point label scale and shift correct
+
+ return True
+
+
+#----------------------------------------------------------------------
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+MagPlus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAOFJ"
+ "REFUeJy1VdEOxCAIo27//8XbuKfuPASGZ0Zisoi2FJABbZM3bY8c13lo5GvbjioBPAUEB0Yc"
+ "VZ0iGRRc56Ee8DcikEgrJD8EFpzRegQASiRtBtzuA0hrdRPYQxaEKyJPG6IHyiK3xnNZvUSS"
+ "NvUuzgYh0il4y14nCFPk5XgmNbRbQbVotGo9msj47G3UXJ7fuz8Q8FAGEu0/PbZh2D3NoshU"
+ "1VUydBGVZKMimlGeErdNGUmf/x7YpjMjcf8HVYvS2adr6aFVlCy/5Ijk9q8SeCR9isJR8SeJ"
+ "8pv7S0Wu2Acr0qdj3w7DRAAAAABJRU5ErkJggg==")
+
+GrabHand = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAARFJ"
+ "REFUeJy1VdESgzAIS2j//4s3s5fRQ6Rad5M7H0oxCZhWSpK1TjwUBCBJAIBItL1fijlfe1yJ"
+ "8noCGC9KgrXO7f0SyZEDAF/H2opsAHv9V/548nplT5Jo7YAFQKQ1RMWzmHUS96suqdBrHkuV"
+ "uxpdJjCS8CfGXWdJ2glzcquKSR5c46QOtCpgNyIHj6oieAXg3282QvMX45hy8a8H0VonJZUO"
+ "clesjOPg/dhBTq64o1Kacz4Ri2x5RKsf8+wcWQaJJL+A+xRcZHeQeBKjK+5EFiVJ4xy4x2Mn"
+ "1Vk4U5/DWmfPieiqbye7a3tV/cCsWKu76K76KUFFchVnhigJ/hmktelm/m3e3b8k+Ec8PqLH"
+ "CT4JRfyK9o1xYwAAAABJRU5ErkJggg==")
+
+Hand = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAARBJ"
+ "REFUeJytluECwiAIhDn1/Z942/UnjCGoq+6XNeWDC1xAqbKr6zyo61Ibds60J8GBT0yS3IEM"
+ "ABuIpJTa4IOLiAAQksuKyixLH1ShHgTgZl8KiALxOsODPoEMkgJ25Su6zoO3ZrjRnI96OLIq"
+ "k7dsqOCboDa4XV/nwQEQVeFtmMnvbSJja+oagKBUaLn9hzd7VipRa9ostIv0O1uhzzaqNJxk"
+ "hViwDVxqg51kksMg9r2rDDIFwHCap130FBhdMzeAfWg//6Ki5WWQrHSv6EIUeVs0g3wT3J7r"
+ "FmWQp/JJDXeRh2TXcJa91zAH2uN2mvXFsrIrsjS8rnftWmWfAiLIStuD9m9h9belvzgS/1fP"
+ "X7075IwDENteAAAAAElFTkSuQmCC")
+
+#---------------------------------------------------------------------------
+# if running standalone...
+#
+# ...a sample implementation using the above
+#
+
+
+def _draw1Objects():
+ # 100 points sin function, plotted as green circles
+ data1 = 2. * np.pi * np.arange(200) / 200.
+ data1.shape = (100, 2)
+ data1[:, 1] = np.sin(data1[:, 0])
+ markers1 = PolyMarker(
+ data1, legend='Green Markers', colour='green', marker='circle', size=1)
+
+ # 50 points cos function, plotted as red line
+ data1 = 2. * np.pi * np.arange(100) / 100.
+ data1.shape = (50, 2)
+ data1[:, 1] = np.cos(data1[:, 0])
+ lines = PolySpline(data1, legend='Red Line', colour='red')
+
+ # A few more points...
+ pi = np.pi
+ markers2 = PolyMarker([(0., 0.), (pi / 4., 1.), (pi / 2, 0.),
+ (3. * pi / 4., -1)], legend='Cross Legend', colour='blue',
+ marker='cross')
+
+ return PlotGraphics([markers1, lines, markers2], "Graph Title", "X Axis", "Y Axis")
+
+
+def _draw2Objects():
+ # 100 points sin function, plotted as green dots
+ data1 = 2. * np.pi * np.arange(200) / 200.
+ data1.shape = (100, 2)
+ data1[:, 1] = np.sin(data1[:, 0])
+ line1 = PolySpline(
+ data1, legend='Green Line', colour='green', width=6, style=wx.PENSTYLE_DOT)
+
+ # 50 points cos function, plotted as red dot-dash
+ data1 = 2. * np.pi * np.arange(100) / 100.
+ data1.shape = (50, 2)
+ data1[:, 1] = np.cos(data1[:, 0])
+ line2 = PolySpline(
+ data1, legend='Red Line', colour='red', width=3, style=wx.PENSTYLE_DOT_DASH)
+
+ # A few more points...
+ pi = np.pi
+ markers1 = PolyMarker([(0., 0.), (pi / 4., 1.), (pi / 2, 0.),
+ (3. * pi / 4., -1)], legend='Cross Hatch Square', colour='blue', width=3, size=6,
+ fillcolour='red', fillstyle=wx.CROSSDIAG_HATCH,
+ marker='square')
+
+ return PlotGraphics([markers1, line1, line2], "Big Markers with Different Line Styles")
+
+
+def _draw3Objects():
+ markerList = ['circle', 'dot', 'square', 'triangle', 'triangle_down',
+ 'cross', 'plus', 'circle']
+ m = []
+ for i in range(len(markerList)):
+ m.append(PolyMarker([(2 * i + .5, i + .5)], legend=markerList[i], colour='blue',
+ marker=markerList[i]))
+ return PlotGraphics(m, "Selection of Markers", "Minimal Axis", "No Axis")
+
+
+def _draw4Objects():
+ # 25,000 point line
+ data1 = np.arange(5e5, 1e6, 10)
+ data1.shape = (25000, 2)
+ line1 = PolyLine(data1, legend='Wide Line', colour='green', width=5)
+
+ # A few more points...
+ markers2 = PolyMarker(data1, legend='Square', colour='blue',
+ marker='square')
+ return PlotGraphics([line1, markers2], "25,000 Points", "Value X", "")
+
+
+def _draw5Objects():
+ # Empty graph with axis defined but no points/lines
+ points = []
+ line1 = PolyLine(points, legend='Wide Line', colour='green', width=5)
+ return PlotGraphics([line1], "Empty Plot With Just Axes", "Value X", "Value Y")
+
+
+def _draw6Objects():
+ # Bar graph
+ points1 = [(1, 0), (1, 10)]
+ line1 = PolyLine(points1, colour='green', legend='Feb.', width=10)
+ points1g = [(2, 0), (2, 4)]
+ line1g = PolyLine(points1g, colour='red', legend='Mar.', width=10)
+ points1b = [(3, 0), (3, 6)]
+ line1b = PolyLine(points1b, colour='blue', legend='Apr.', width=10)
+
+ points2 = [(4, 0), (4, 12)]
+ line2 = PolyLine(points2, colour='Yellow', legend='May', width=10)
+ points2g = [(5, 0), (5, 8)]
+ line2g = PolyLine(points2g, colour='orange', legend='June', width=10)
+ points2b = [(6, 0), (6, 4)]
+ line2b = PolyLine(points2b, colour='brown', legend='July', width=10)
+
+ return PlotGraphics([line1, line1g, line1b, line2, line2g, line2b],
+ "Bar Graph - (Turn on Grid, Legend)", "Months", "Number of Students")
+
+
+def _draw7Objects():
+ # Empty graph with axis defined but no points/lines
+ x = np.arange(1, 1000, 1)
+ y1 = 4.5 * x ** 2
+ y2 = 2.2 * x ** 3
+ points1 = np.transpose([x, y1])
+ points2 = np.transpose([x, y2])
+ line1 = PolyLine(points1, legend='quadratic', colour='blue', width=1)
+ line2 = PolyLine(points2, legend='cubic', colour='red', width=1)
+ return PlotGraphics([line1, line2], "double log plot", "Value X", "Value Y")
+
+
+class TestFrame(wx.Frame):
+
+ def __init__(self, parent, id, title):
+ wx.Frame.__init__(self, parent, id, title,
+ wx.DefaultPosition, (600, 400))
+
+ # Now Create the menu bar and items
+ self.mainmenu = wx.MenuBar()
+
+ menu = wx.Menu()
+ menu.Append(200, 'Page Setup...', 'Setup the printer page')
+ self.Bind(wx.EVT_MENU, self.OnFilePageSetup, id=200)
+
+ menu.Append(201, 'Print Preview...', 'Show the current plot on page')
+ self.Bind(wx.EVT_MENU, self.OnFilePrintPreview, id=201)
+
+ menu.Append(202, 'Print...', 'Print the current plot')
+ self.Bind(wx.EVT_MENU, self.OnFilePrint, id=202)
+
+ menu.Append(203, 'Save Plot...', 'Save current plot')
+ self.Bind(wx.EVT_MENU, self.OnSaveFile, id=203)
+
+ menu.Append(205, 'E&xit', 'Enough of this already!')
+ self.Bind(wx.EVT_MENU, self.OnFileExit, id=205)
+ self.mainmenu.Append(menu, '&File')
+
+ menu = wx.Menu()
+ menu.Append(206, 'Draw1', 'Draw plots1')
+ self.Bind(wx.EVT_MENU, self.OnPlotDraw1, id=206)
+ menu.Append(207, 'Draw2', 'Draw plots2')
+ self.Bind(wx.EVT_MENU, self.OnPlotDraw2, id=207)
+ menu.Append(208, 'Draw3', 'Draw plots3')
+ self.Bind(wx.EVT_MENU, self.OnPlotDraw3, id=208)
+ menu.Append(209, 'Draw4', 'Draw plots4')
+ self.Bind(wx.EVT_MENU, self.OnPlotDraw4, id=209)
+ menu.Append(210, 'Draw5', 'Draw plots5')
+ self.Bind(wx.EVT_MENU, self.OnPlotDraw5, id=210)
+ menu.Append(260, 'Draw6', 'Draw plots6')
+ self.Bind(wx.EVT_MENU, self.OnPlotDraw6, id=260)
+ menu.Append(261, 'Draw7', 'Draw plots7')
+ self.Bind(wx.EVT_MENU, self.OnPlotDraw7, id=261)
+
+ menu.Append(211, '&Redraw', 'Redraw plots')
+ self.Bind(wx.EVT_MENU, self.OnPlotRedraw, id=211)
+ menu.Append(212, '&Clear', 'Clear canvas')
+ self.Bind(wx.EVT_MENU, self.OnPlotClear, id=212)
+ menu.Append(213, '&Scale', 'Scale canvas')
+ self.Bind(wx.EVT_MENU, self.OnPlotScale, id=213)
+ menu.Append(
+ 214, 'Enable &Zoom', 'Enable Mouse Zoom', kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnEnableZoom, id=214)
+ menu.Append(215, 'Enable &Grid', 'Turn on Grid', kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnEnableGrid, id=215)
+ menu.Append(
+ 217, 'Enable &Drag', 'Activates dragging mode', kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnEnableDrag, id=217)
+ menu.Append(
+ 220, 'Enable &Legend', 'Turn on Legend', kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnEnableLegend, id=220)
+ menu.Append(
+ 222, 'Enable &Point Label', 'Show Closest Point', kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnEnablePointLabel, id=222)
+
+ menu.Append(
+ 223, 'Enable &Anti-Aliasing', 'Smooth output', kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnEnableAntiAliasing, id=223)
+ menu.Append(224, 'Enable &High-Resolution AA',
+ 'Draw in higher resolution', kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnEnableHiRes, id=224)
+
+ menu.Append(
+ 226, 'Enable Center Lines', 'Draw center lines', kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnEnableCenterLines, id=226)
+ menu.Append(
+ 227, 'Enable Diagonal Lines', 'Draw diagonal lines', kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnEnableDiagonals, id=227)
+
+ menu.Append(
+ 231, 'Set Gray Background', 'Change background colour to gray')
+ self.Bind(wx.EVT_MENU, self.OnBackgroundGray, id=231)
+ menu.Append(
+ 232, 'Set &White Background', 'Change background colour to white')
+ self.Bind(wx.EVT_MENU, self.OnBackgroundWhite, id=232)
+ menu.Append(
+ 233, 'Set Red Label Text', 'Change label text colour to red')
+ self.Bind(wx.EVT_MENU, self.OnForegroundRed, id=233)
+ menu.Append(
+ 234, 'Set &Black Label Text', 'Change label text colour to black')
+ self.Bind(wx.EVT_MENU, self.OnForegroundBlack, id=234)
+
+ menu.Append(225, 'Scroll Up 1', 'Move View Up 1 Unit')
+ self.Bind(wx.EVT_MENU, self.OnScrUp, id=225)
+ menu.Append(230, 'Scroll Rt 2', 'Move View Right 2 Units')
+ self.Bind(wx.EVT_MENU, self.OnScrRt, id=230)
+ menu.Append(235, '&Plot Reset', 'Reset to original plot')
+ self.Bind(wx.EVT_MENU, self.OnReset, id=235)
+
+ self.mainmenu.Append(menu, '&Plot')
+
+ menu = wx.Menu()
+ menu.Append(300, '&About', 'About this thing...')
+ self.Bind(wx.EVT_MENU, self.OnHelpAbout, id=300)
+ self.mainmenu.Append(menu, '&Help')
+
+ self.SetMenuBar(self.mainmenu)
+
+ # A status bar to tell people what's happening
+ self.CreateStatusBar(1)
+
+ self.client = PlotCanvas(self)
+ # define the function for drawing pointLabels
+ self.client.SetPointLabelFunc(self.DrawPointLabel)
+ # Create mouse event for showing cursor coords in status bar
+ self.client.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
+ # Show closest point when enabled
+ self.client.canvas.Bind(wx.EVT_MOTION, self.OnMotion)
+
+ self.Show(True)
+
+ def DrawPointLabel(self, dc, mDataDict):
+ """This is the fuction that defines how the pointLabels are plotted
+ dc - DC that will be passed
+ mDataDict - Dictionary of data that you want to use for the pointLabel
+
+ As an example I have decided I want a box at the curve point
+ with some text information about the curve plotted below.
+ Any wxDC method can be used.
+ """
+ # ----------
+ dc.SetPen(wx.Pen(wx.BLACK))
+ dc.SetBrush(wx.Brush(wx.BLACK, wx.BRUSHSTYLE_SOLID))
+
+ sx, sy = mDataDict["scaledXY"] # scaled x,y of closest point
+ # 10by10 square centered on point
+ dc.DrawRectangle(sx - 5, sy - 5, 10, 10)
+ px, py = mDataDict["pointXY"]
+ cNum = mDataDict["curveNum"]
+ pntIn = mDataDict["pIndex"]
+ legend = mDataDict["legend"]
+ # make a string to display
+ s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" % (
+ cNum, legend, px, py, pntIn)
+ dc.DrawText(s, sx, sy + 1)
+ # -----------
+
+ def OnMouseLeftDown(self, event):
+ s = "Left Mouse Down at Point: (%.4f, %.4f)" % self.client._getXY(
+ event)
+ self.SetStatusText(s)
+ event.Skip() # allows plotCanvas OnMouseLeftDown to be called
+
+ def OnMotion(self, event):
+ # show closest point (when enbled)
+ if self.client.GetEnablePointLabel() == True:
+ # make up dict with info for the pointLabel
+ # I've decided to mark the closest point on the closest curve
+ dlst = self.client.GetClosestPoint(
+ self.client._getXY(event), pointScaled=True)
+ if dlst != []: # returns [] if none
+ curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst
+ # make up dictionary to pass to my user function (see
+ # DrawPointLabel)
+ mDataDict = {"curveNum": curveNum, "legend": legend, "pIndex": pIndex,
+ "pointXY": pointXY, "scaledXY": scaledXY}
+ # pass dict to update the pointLabel
+ self.client.UpdatePointLabel(mDataDict)
+ event.Skip() # go to next handler
+
+ def OnFilePageSetup(self, event):
+ self.client.PageSetup()
+
+ def OnFilePrintPreview(self, event):
+ self.client.PrintPreview()
+
+ def OnFilePrint(self, event):
+ self.client.Printout()
+
+ def OnSaveFile(self, event):
+ self.client.SaveFile()
+
+ def OnFileExit(self, event):
+ self.Close()
+
+ def OnPlotDraw1(self, event):
+ self.resetDefaults()
+ self.client.Draw(_draw1Objects())
+
+ def OnPlotDraw2(self, event):
+ self.resetDefaults()
+ self.client.Draw(_draw2Objects())
+
+ def OnPlotDraw3(self, event):
+ self.resetDefaults()
+ self.client.SetFont(
+ wx.Font(10, wx.FONTFAMILY_SCRIPT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
+ self.client.SetFontSizeAxis(20)
+ self.client.SetFontSizeLegend(12)
+ self.client.SetXSpec('min')
+ self.client.SetYSpec('none')
+ self.client.Draw(_draw3Objects())
+
+ def OnPlotDraw4(self, event):
+ self.resetDefaults()
+ drawObj = _draw4Objects()
+ self.client.Draw(drawObj)
+# profile
+## start = _time.clock()
+# for x in range(10):
+# self.client.Draw(drawObj)
+## print("10 plots of Draw4 took: %f sec."%(_time.clock() - start))
+# profile end
+
+ def OnPlotDraw5(self, event):
+ # Empty plot with just axes
+ self.resetDefaults()
+ drawObj = _draw5Objects()
+ # make the axis X= (0,5), Y=(0,10)
+ # (default with None is X= (-1,1), Y= (-1,1))
+ self.client.Draw(drawObj, xAxis=(0, 5), yAxis= (0, 10))
+
+ def OnPlotDraw6(self, event):
+ # Bar Graph Example
+ self.resetDefaults()
+ # self.client.SetEnableLegend(True) #turn on Legend
+ # self.client.SetEnableGrid(True) #turn on Grid
+ self.client.SetXSpec('none') # turns off x-axis scale
+ self.client.SetYSpec('auto')
+ self.client.Draw(_draw6Objects(), xAxis=(0, 7))
+
+ def OnPlotDraw7(self, event):
+ # log scale example
+ self.resetDefaults()
+ self.client.setLogScale((True, True))
+ self.client.Draw(_draw7Objects())
+
+ def OnPlotRedraw(self, event):
+ self.client.Redraw()
+
+ def OnPlotClear(self, event):
+ self.client.Clear()
+
+ def OnPlotScale(self, event):
+ if self.client.last_draw != None:
+ graphics, xAxis, yAxis = self.client.last_draw
+ self.client.Draw(graphics, (1, 3.05), (0, 1))
+
+ def OnEnableZoom(self, event):
+ self.client.SetEnableZoom(event.IsChecked())
+ self.mainmenu.Check(217, not event.IsChecked())
+
+ def OnEnableGrid(self, event):
+ self.client.SetEnableGrid(event.IsChecked())
+
+ def OnEnableDrag(self, event):
+ self.client.SetEnableDrag(event.IsChecked())
+ self.mainmenu.Check(214, not event.IsChecked())
+
+ def OnEnableLegend(self, event):
+ self.client.SetEnableLegend(event.IsChecked())
+
+ def OnEnablePointLabel(self, event):
+ self.client.SetEnablePointLabel(event.IsChecked())
+
+ def OnEnableAntiAliasing(self, event):
+ self.client.SetEnableAntiAliasing(event.IsChecked())
+
+ def OnEnableHiRes(self, event):
+ self.client.SetEnableHiRes(event.IsChecked())
+
+ def OnEnableCenterLines(self, event):
+ self.client.SetEnableCenterLines(event.IsChecked())
+
+ def OnEnableDiagonals(self, event):
+ self.client.SetEnableDiagonals(event.IsChecked())
+
+ def OnBackgroundGray(self, event):
+ self.client.SetBackgroundColour("#CCCCCC")
+ self.client.Redraw()
+
+ def OnBackgroundWhite(self, event):
+ self.client.SetBackgroundColour("white")
+ self.client.Redraw()
+
+ def OnForegroundRed(self, event):
+ self.client.SetForegroundColour("red")
+ self.client.Redraw()
+
+ def OnForegroundBlack(self, event):
+ self.client.SetForegroundColour("black")
+ self.client.Redraw()
+
+ def OnScrUp(self, event):
+ self.client.ScrollUp(1)
+
+ def OnScrRt(self, event):
+ self.client.ScrollRight(2)
+
+ def OnReset(self, event):
+ self.client.Reset()
+
+ def OnHelpAbout(self, event):
+ from wx.lib.dialogs import ScrolledMessageDialog
+ about = ScrolledMessageDialog(self, __doc__, "About...")
+ about.ShowModal()
+
+ def resetDefaults(self):
+ """Just to reset the fonts back to the PlotCanvas defaults"""
+ self.client.SetFont(
+ wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
+ self.client.SetFontSizeAxis(10)
+ self.client.SetFontSizeLegend(7)
+ self.client.setLogScale((False, False))
+ self.client.SetXSpec('auto')
+ self.client.SetYSpec('auto')
+
+
+def __test():
+
+ class MyApp(wx.App):
+
+ def OnInit(self):
+ wx.InitAllImageHandlers()
+ frame = TestFrame(None, -1, "PlotCanvas")
+ # frame.Show(True)
+ self.SetTopWindow(frame)
+ return True
+
+ app = MyApp(0)
+ app.MainLoop()
+
+if __name__ == '__main__':
+ __test()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/popupctl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/popupctl.py
new file mode 100644
index 0000000..9f70fd5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/popupctl.py
@@ -0,0 +1,249 @@
+#----------------------------------------------------------------------
+# Name: popup
+# Purpose: Generic popup control
+#
+# Author: Gerrit van Dyk
+#
+# Created: 2002/11/20
+# Version: 0.1
+# RCS-ID: $Id$
+# License: wxWindows license
+#----------------------------------------------------------------------
+# 11/24/2007 - Cody Precord
+#
+# o Use RendererNative to draw button
+#
+# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxPopupDialog -> PopupDialog
+# o wxPopupControl -> PopupControl
+#
+
+import wx
+from wx.lib.buttons import GenButtonEvent
+
+
+class PopButton(wx.PyControl):
+ def __init__(self,*_args,**_kwargs):
+ wx.PyControl.__init__(self, *_args, **_kwargs)
+
+ self.up = True
+ self.didDown = False
+
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+ def Notify(self):
+ evt = GenButtonEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
+ evt.SetIsDown(not self.up)
+ evt.SetButtonObj(self)
+ evt.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(evt)
+
+ def OnEraseBackground(self, event):
+ pass
+
+ def OnLeftDown(self, event):
+ if not self.IsEnabled():
+ return
+ self.didDown = True
+ self.up = False
+ self.CaptureMouse()
+ self.GetParent().textCtrl.SetFocus()
+ self.Refresh()
+ event.Skip()
+
+ def OnLeftUp(self, event):
+ if not self.IsEnabled():
+ return
+ if self.didDown:
+ self.ReleaseMouse()
+ if not self.up:
+ self.Notify()
+ self.up = True
+ self.Refresh()
+ self.didDown = False
+ event.Skip()
+
+ def OnMotion(self, event):
+ if not self.IsEnabled():
+ return
+ if event.LeftIsDown():
+ if self.didDown:
+ x,y = event.GetPosition()
+ w,h = self.GetClientSize()
+ if self.up and x<w and x>=0 and y<h and y>=0:
+ self.up = False
+ self.Refresh()
+ return
+ if not self.up and (x<0 or y<0 or x>=w or y>=h):
+ self.up = True
+ self.Refresh()
+ return
+ event.Skip()
+
+ def OnPaint(self, event):
+ dc = wx.BufferedPaintDC(self)
+ if self.up:
+ flag = wx.CONTROL_CURRENT
+ else:
+ flag = wx.CONTROL_PRESSED
+ wx.RendererNative.Get().DrawComboBoxDropButton(self, dc, self.GetClientRect(), flag)
+
+
+#---------------------------------------------------------------------------
+
+
+# Tried to use wxPopupWindow but the control misbehaves on MSW
+class PopupDialog(wx.Dialog):
+ def __init__(self,parent,content = None):
+ wx.Dialog.__init__(self,parent,-1,'', style = wx.BORDER_SIMPLE|wx.STAY_ON_TOP)
+
+ self.ctrl = parent
+ self.win = wx.Window(self,-1,pos = (0,0),style = 0)
+
+ if content:
+ self.SetContent(content)
+
+ def SetContent(self,content):
+ self.content = content
+ self.content.Reparent(self.win)
+ self.content.Show(True)
+ self.win.SetClientSize(self.content.GetSize())
+ self.SetSize(self.win.GetSize())
+
+ def Display(self):
+ pos = self.ctrl.ClientToScreen( (0,0) )
+ dSize = wx.GetDisplaySize()
+ selfSize = self.GetSize()
+ tcSize = self.ctrl.GetSize()
+
+ pos.x -= (selfSize.width - tcSize.width) / 2
+ if pos.x + selfSize.width > dSize.width:
+ pos.x = dSize.width - selfSize.width
+ if pos.x < 0:
+ pos.x = 0
+
+ pos.y += tcSize.height
+ if pos.y + selfSize.height > dSize.height:
+ pos.y = dSize.height - selfSize.height
+ if pos.y < 0:
+ pos.y = 0
+
+ self.Move(pos)
+
+ self.ctrl.FormatContent()
+
+ self.ShowModal()
+
+
+#---------------------------------------------------------------------------
+
+
+class PopupControl(wx.PyControl):
+ def __init__(self,*_args,**_kwargs):
+ if _kwargs.has_key('value'):
+ del _kwargs['value']
+ style = _kwargs.get('style', 0)
+ if (style & wx.BORDER_MASK) == 0:
+ style |= wx.BORDER_NONE
+ _kwargs['style'] = style
+ wx.PyControl.__init__(self, *_args, **_kwargs)
+
+ self.textCtrl = wx.TextCtrl(self, wx.ID_ANY, '', pos = (0,0))
+ self.bCtrl = PopButton(self, wx.ID_ANY, style=wx.BORDER_NONE)
+ self.pop = None
+ self.content = None
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.bCtrl.Bind(wx.EVT_BUTTON, self.OnButton, self.bCtrl)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnFocus)
+
+ self.SetInitialSize(_kwargs.get('size', wx.DefaultSize))
+ self.SendSizeEvent()
+
+
+ def OnFocus(self,evt):
+ # embedded control should get focus on TAB keypress
+ self.textCtrl.SetFocus()
+ evt.Skip()
+
+
+ def OnSize(self, evt):
+ # layout the child widgets
+ w,h = self.GetClientSize()
+ self.textCtrl.SetDimensions(0, 0, w - self.marginWidth - self.buttonWidth, h)
+ self.bCtrl.SetDimensions(w - self.buttonWidth, 0, self.buttonWidth, h)
+
+ def DoGetBestSize(self):
+ # calculate the best size of the combined control based on the
+ # needs of the child widgets.
+ tbs = self.textCtrl.GetBestSize()
+ return wx.Size(tbs.width + self.marginWidth + self.buttonWidth,
+ tbs.height)
+
+
+ def OnButton(self, evt):
+ if not self.pop:
+ if self.content:
+ self.pop = PopupDialog(self,self.content)
+ del self.content
+ else:
+ print 'No Content to pop'
+ if self.pop:
+ self.pop.Display()
+
+
+ def Enable(self, flag):
+ wx.PyControl.Enable(self,flag)
+ self.textCtrl.Enable(flag)
+ self.bCtrl.Enable(flag)
+
+
+ def SetPopupContent(self, content):
+ if not self.pop:
+ self.content = content
+ self.content.Show(False)
+ else:
+ self.pop.SetContent(content)
+
+ def FormatContent(self):
+ pass
+
+ def PopDown(self):
+ if self.pop:
+ self.pop.EndModal(1)
+
+ def SetValue(self, value):
+ self.textCtrl.SetValue(value)
+
+ def GetValue(self):
+ return self.textCtrl.GetValue()
+
+ def SetFont(self, font):
+ self.textCtrl.SetFont(font)
+
+ def GetFont(self):
+ return self.textCtrl.GetFont()
+
+
+ def _get_marginWidth(self):
+ if 'wxMac' in wx.PlatformInfo:
+ return 6
+ else:
+ return 3
+ marginWidth = property(_get_marginWidth)
+
+ def _get_buttonWidth(self):
+ return 20
+ buttonWidth = property(_get_buttonWidth)
+
+
+# an alias
+PopupCtrl = PopupControl
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/printout.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/printout.py
new file mode 100644
index 0000000..f0b364c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/printout.py
@@ -0,0 +1,1156 @@
+#----------------------------------------------------------------------------
+# Name: printout.py
+# Purpose: preview and printing class -> table/grid printing
+#
+# Author: Lorne White (email: lorne.white@telusplanet.net)
+#
+# Created:
+# Version 0.75
+# Date: May 15, 2002
+# Licence: wxWindows license
+#----------------------------------------------------------------------------
+# Release Notes
+
+# fixed bug for string wider than print region
+# add index to data list after parsing total pages for paging
+#----------------------------------------------------------------------------
+# 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+# o 2.5 compatability update.
+#----------------------------------------------------------------------------
+# 11/23/2004 - Vernon Cole (wnvcole@peppermillcas.com)
+# o Generalize for non-2-dimensional sequences and non-text data
+# (can use as a simple text printer by supplying a list of strings.)
+# o Add a small _main_ for self test
+
+import copy
+import types
+import wx
+
+class PrintBase(object):
+ def SetPrintFont(self, font): # set the DC font parameters
+ fattr = font["Attr"]
+ if fattr[0] == 1:
+ weight = wx.BOLD
+ else:
+ weight = wx.NORMAL
+
+ if fattr[1] == 1:
+ set_style = wx.ITALIC
+ else:
+ set_style = wx.NORMAL
+
+ underline = fattr[2]
+ fcolour = self.GetFontColour(font)
+ self.DC.SetTextForeground(fcolour)
+
+ setfont = wx.Font(font["Size"], wx.SWISS, set_style, weight, underline)
+ setfont.SetFaceName(font["Name"])
+ self.DC.SetFont(setfont)
+
+ def GetFontColour(self, font):
+ fcolour = font["Colour"]
+ return wx.Colour(fcolour[0], fcolour[1], fcolour[2])
+
+ def OutTextRegion(self, textout, txtdraw = True):
+ textlines = textout.split('\n')
+ y = copy.copy(self.y) + self.pt_space_before
+ for text in textlines:
+ remain = 'X'
+ while remain != "":
+ vout, remain = self.SetFlow(text, self.region)
+ if self.draw == True and txtdraw == True:
+ test_out = self.TestFull(vout)
+ if self.align == wx.ALIGN_LEFT:
+ self.DC.DrawText(test_out, self.indent+self.pcell_left_margin, y)
+
+ elif self.align == wx.ALIGN_CENTRE:
+ diff = self.GetCellDiff(test_out, self.region)
+ self.DC.DrawText(test_out, self.indent+diff/2, y)
+
+ elif self.align == wx.ALIGN_RIGHT:
+ diff = self.GetCellDiff(test_out, self.region)
+ self.DC.DrawText(test_out, self.indent+diff, y)
+
+ else:
+ self.DC.DrawText(test_out, self.indent+self.pcell_left_margin, y)
+ text = remain
+ y = y + self.space
+ return y - self.space + self.pt_space_after
+
+ def GetCellDiff(self, text, width): # get the remaining cell size for adjustment
+ w, h = self.DC.GetTextExtent(text)
+ diff = width - w
+ if diff < 0:
+ diff = 0
+ return diff
+
+ def TestFull(self, text_test):
+ w, h = self.DC.GetTextExtent(text_test)
+ if w > self.region: # trouble fitting into cell
+ return self.SetChar(text_test, self.region) # fit the text to the cell size
+ else:
+ return text_test
+
+ def SetFlow(self, ln_text, width):
+ width = width - self.pcell_right_margin
+ text = ""
+ split = ln_text.split()
+ if len(split) == 1:
+ return ln_text, ""
+
+ try:
+ w, h = self.DC.GetTextExtent(" " + split[0])
+ if w >= width:
+ return ln_text, ""
+ except:
+ pass
+
+ cnt = 0
+ for word in split:
+ bword = " " + word # blank + word
+ length = len(bword)
+
+ w, h = self.DC.GetTextExtent(text + bword)
+ if w < width:
+ text = text + bword
+ cnt = cnt + 1
+ else:
+ remain = ' '.join(split[cnt:])
+ text = text.strip()
+ return text, remain
+
+ remain = ' '.join(split[cnt:])
+ vout = text.strip()
+ return vout, remain
+
+ def SetChar(self, ln_text, width): # truncate string to fit into width
+ width = width - self.pcell_right_margin - self.pcell_left_margin
+ text = ""
+ for val in ln_text:
+ w, h = self.DC.GetTextExtent(text + val)
+ if w > width:
+ text = text + ".."
+ return text # fitted text value
+ text = text + val
+ return text
+
+ def OutTextPageWidth(self, textout, y_out, align, indent, txtdraw = True):
+ textlines = textout.split('\n')
+ y = copy.copy(y_out)
+
+ pagew = self.parent.page_width * self.pwidth # full page width
+ w, h = self.DC.GetTextExtent(textout)
+ y_line = h
+
+ for text in textlines:
+ remain = 'X'
+ while remain != "":
+ vout, remain = self.SetFlow(text, pagew)
+ if self.draw == True and txtdraw == True:
+ test_out = vout
+ if align == wx.ALIGN_LEFT:
+ self.DC.DrawText(test_out, indent, y)
+
+ elif align == wx.ALIGN_CENTRE:
+ diff = self.GetCellDiff(test_out, pagew)
+ self.DC.DrawText(test_out, indent+diff/2, y)
+
+ elif align == wx.ALIGN_RIGHT:
+ diff = self.GetCellDiff(test_out, pagew)
+ self.DC.DrawText(test_out, indent+diff, y)
+
+ else:
+ self.DC.DrawText(test_out, indent, y_out)
+ text = remain
+ y = y + y_line
+ return y - y_line
+
+ def GetDate(self):
+ date, time = self.GetNow()
+ return date
+
+ def GetDateTime(self):
+ date, time = self.GetNow()
+ return date + ' ' + time
+
+ def GetNow(self):
+ now = wx.DateTime.Now()
+ date = now.FormatDate()
+ time = now.FormatTime()
+ return date, time
+
+ def SetPreview(self, preview):
+ self.preview = preview
+
+ def SetPSize(self, width, height):
+ self.pwidth = width/self.scale
+ self.pheight = height/self.scale
+
+ def SetScale(self, scale):
+ self.scale = scale
+
+ def SetPTSize(self, width, height):
+ self.ptwidth = width
+ self.ptheight = height
+
+ def getWidth(self):
+ return self.sizew
+
+ def getHeight(self):
+ return self.sizeh
+
+
+class PrintTableDraw(wx.ScrolledWindow, PrintBase):
+ def __init__(self, parent, DC, size):
+ self.parent = parent
+ self.DC = DC
+ self.scale = parent.scale
+ self.width = size[0]
+ self.height = size[1]
+ self.SetDefaults()
+
+ def SetDefaults(self):
+ self.page = 1
+ self.total_pages = None
+
+ self.page_width = self.parent.page_width
+ self.page_height = self.parent.page_height
+
+ self.left_margin = self.parent.left_margin
+ self.right_margin = self.parent.right_margin
+
+ self.top_margin = self.parent.top_margin
+ self.bottom_margin = self.parent.bottom_margin
+ self.cell_left_margin = self.parent.cell_left_margin
+ self.cell_right_margin = self.parent.cell_right_margin
+
+ self.label_colour = self.parent.label_colour
+
+ self.row_line_colour = self.parent.row_line_colour
+ self.row_line_size = self.parent.row_line_size
+
+ self.row_def_line_colour = self.parent.row_def_line_colour
+ self.row_def_line_size = self.parent.row_def_line_size
+
+ self.column_line_colour = self.parent.column_line_colour
+ self.column_line_size = self.parent.column_line_size
+
+ self.column_def_line_size = self.parent.column_def_line_size
+ self.column_def_line_colour = self.parent.column_def_line_colour
+
+ self.text_font = self.parent.text_font
+
+ self.label_font = self.parent.label_font
+
+ def AdjustValues(self):
+ self.vertical_offset = self.pheight * self.parent.vertical_offset
+ self.horizontal_offset = self.pheight * self.parent.horizontal_offset
+
+ self.pcell_left_margin = self.pwidth * self.cell_left_margin
+ self.pcell_right_margin = self.pwidth * self.cell_right_margin
+ self.ptop_margin = self.pheight * self.top_margin
+ self.pbottom_margin = self.pheight * self.bottom_margin
+
+ self.pheader_margin = self.pheight * self.parent.header_margin
+ self.pfooter_margin = self.pheight * self.parent.footer_margin
+
+ self.cell_colour = self.parent.set_cell_colour
+ self.cell_text = self.parent.set_cell_text
+
+ self.column = []
+ self.column_align = []
+ self.column_bgcolour = []
+ self.column_txtcolour = []
+
+ set_column_align = self.parent.set_column_align
+ set_column_bgcolour = self.parent.set_column_bgcolour
+ set_column_txtcolour = self.parent.set_column_txtcolour
+
+ pos_x = self.left_margin * self.pwidth + self.horizontal_offset # left margin
+ self.column.append(pos_x)
+
+ #module logic expects two dimensional data -- fix input if needed
+ if isinstance(self.data,types.StringTypes):
+ self.data = [[copy.copy(self.data)]] # a string becomes a single cell
+ try:
+ rows = len(self.data)
+ except TypeError:
+ self.data = [[str(self.data)]] # a non-iterable becomes a single cell
+ rows = 1
+ first_value = self.data[0]
+
+ if isinstance(first_value, types.StringTypes): # a sequence of strings
+ if self.label == [] and self.set_column == []:
+ data = []
+ for x in self.data: #becomes one column
+ data.append([x])
+ else:
+ data = [self.data] #becames one row
+ self.data = data
+ first_value = data[0]
+ try:
+ column_total = len(first_value)
+ except TypeError: # a sequence of non-iterables
+ if self.label == [] and self.set_column == []:
+ data = [] #becomes one column
+ for x in self.data:
+ data.append([str(x)])
+ column_total = 1
+ else:
+ data = [self.data] #becomes one row
+ column_total = len(self.data)
+ self.data = data
+ first_value = data[0]
+
+ if self.set_column == []:
+ table_width = self.page_width - self.left_margin - self.right_margin
+ if self.label == []:
+ temp = first_value
+ else:
+ temp = self.label
+ width = table_width/(len(temp))
+ for val in temp:
+ column_width = width * self.pwidth
+ pos_x = pos_x + column_width
+ self.column.append(pos_x) # position of each column
+ else:
+ for val in self.set_column:
+ column_width = val * self.pwidth
+ pos_x = pos_x + column_width
+ self.column.append(pos_x) # position of each column
+
+ if pos_x > self.page_width * self.pwidth: # check if it fits in page
+ print "Warning, Too Wide for Page"
+ return
+
+ if self.label != []:
+ if len(self.column) -1 != len(self.label):
+ print "Column Settings Incorrect", "\nColumn Value: " + str(self.column), "\nLabel Value: " + str(self.label)
+ return
+
+ if column_total != len(self.column) -1:
+ print "Cannot fit", first_value, 'in', len(self.column)-1, 'columns.'
+ return
+
+ for col in range(column_total):
+ try:
+ align = set_column_align[col] # check if custom column alignment
+ except:
+ align = wx.ALIGN_LEFT
+ self.column_align.append(align)
+
+ try:
+ colour = set_column_bgcolour[col] # check if custom column background colour
+ except:
+ colour = self.parent.column_colour
+ self.column_bgcolour.append(colour)
+
+ try:
+ colour = set_column_txtcolour[col] # check if custom column text colour
+ except:
+ colour = self.GetFontColour(self.parent.text_font)
+ self.column_txtcolour.append(colour)
+
+
+ def SetPointAdjust(self):
+ f = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL) # setup using 10 point
+ self.DC.SetFont(f)
+ f.SetFaceName(self.text_font["Name"])
+ x, y = self.DC.GetTextExtent("W")
+
+ self.label_pt_space_before = self.parent.label_pt_adj_before * y/10 # extra spacing for label per point value
+ self.label_pt_space_after = self.parent.label_pt_adj_after * y/10
+
+ self.text_pt_space_before = self.parent.text_pt_adj_before * y/10 # extra spacing for row text per point value
+ self.text_pt_space_after = self.parent.text_pt_adj_after * y/10
+
+ def SetPage(self, page):
+ self.page = page
+
+ def SetColumns(self, col):
+ self.column = col
+
+ def OutCanvas(self):
+ self.AdjustValues()
+ self.SetPointAdjust()
+
+ self.y_start = self.ptop_margin + self.vertical_offset
+ self.y_end = self.parent.page_height * self.pheight - self.pbottom_margin + self.vertical_offset
+
+ self.SetPrintFont(self.label_font)
+
+ x, y = self.DC.GetTextExtent("W")
+ self.label_space = y
+
+ self.SetPrintFont(self.text_font)
+
+ x, y = self.DC.GetTextExtent("W")
+ self.space = y
+
+ if self.total_pages is None:
+ self.GetTotalPages() # total pages for display/printing
+
+ self.data_cnt = self.page_index[self.page-1]
+
+ self.draw = True
+ self.PrintHeader()
+ self.PrintFooter()
+ self.OutPage()
+
+ def GetTotalPages(self):
+ self.data_cnt = 0
+ self.draw = False
+ self.page_index = [0]
+
+ cnt = 0
+ while 1:
+ test = self.OutPage()
+ self.page_index.append(self.data_cnt)
+ if test == False:
+ break
+ cnt = cnt + 1
+
+ self.total_pages = cnt + 1
+
+ def OutPage(self):
+ self.y = self.y_start
+ self.end_x = self.column[-1]
+
+ if self.data_cnt < len(self.data): # if there data for display on the page
+ if self.label != []: # check if header defined
+ self.PrintLabel()
+ else:
+ return False
+
+ for val in self.data:
+ try:
+ row_val = self.data[self.data_cnt]
+ except:
+ self.FinishDraw()
+ return False
+
+ max_y = self.PrintRow(row_val, False) # test to see if row will fit in remaining space
+ test = max_y + self.space
+
+ if test > self.y_end:
+ break
+
+ self.ColourRowCells(max_y-self.y+self.space) # colour the row/column
+ max_y = self.PrintRow(row_val, True) # row fits - print text
+ self.DrawGridLine() # top line of cell
+ self.y = max_y + self.space
+
+ if self.y > self.y_end:
+ break
+
+ self.data_cnt = self.data_cnt + 1
+
+ self.FinishDraw()
+
+ if self.data_cnt == len(self.data): # last value in list
+ return False
+
+ return True
+
+
+ def PrintLabel(self):
+ self.pt_space_before = self.label_pt_space_before # set the point spacing
+ self.pt_space_after = self.label_pt_space_after
+
+ self.LabelColorRow(self.label_colour)
+ self.SetPrintFont(self.label_font)
+
+ self.col = 0
+ max_y = 0
+ for vtxt in self.label:
+ self.region = self.column[self.col+1] - self.column[self.col]
+ self.indent = self.column[self.col]
+
+ self.align = wx.ALIGN_LEFT
+
+ max_out = self.OutTextRegion(vtxt, True)
+ if max_out > max_y:
+ max_y = max_out
+ self.col = self.col + 1
+
+ self.DrawGridLine() # top line of label
+ self.y = max_y + self.label_space
+
+ def PrintHeader(self): # print the header array
+ if self.draw == False:
+ return
+
+ for val in self.parent.header:
+ self.SetPrintFont(val["Font"])
+
+ header_indent = val["Indent"] * self.pwidth
+ text = val["Text"]
+
+ htype = val["Type"]
+ if htype == "Date":
+ addtext = self.GetDate()
+ elif htype == "Date & Time":
+ addtext = self.GetDateTime()
+ else:
+ addtext = ""
+
+ self.OutTextPageWidth(text+addtext, self.pheader_margin, val["Align"], header_indent, True)
+
+ def PrintFooter(self): # print the header array
+ if self.draw == False:
+ return
+
+ footer_pos = self.parent.page_height * self.pheight - self.pfooter_margin + self.vertical_offset
+ for val in self.parent.footer:
+ self.SetPrintFont(val["Font"])
+
+ footer_indent = val["Indent"] * self.pwidth
+ text = val["Text"]
+
+ ftype = val["Type"]
+ if ftype == "Pageof":
+ addtext = "Page " + str(self.page) + " of " + str(self.total_pages)
+ elif ftype == "Page":
+ addtext = "Page " + str(self.page)
+ elif ftype == "Num":
+ addtext = str(self.page)
+ elif ftype == "Date":
+ addtext = self.GetDate()
+ elif ftype == "Date & Time":
+ addtext = self.GetDateTime()
+ else:
+ addtext = ""
+
+ self.OutTextPageWidth(text+addtext, footer_pos, val["Align"], footer_indent, True)
+
+
+ def LabelColorRow(self, colour):
+ brush = wx.Brush(colour, wx.SOLID)
+ self.DC.SetBrush(brush)
+ height = self.label_space + self.label_pt_space_before + self.label_pt_space_after
+ self.DC.DrawRectangle(self.column[0], self.y,
+ self.end_x-self.column[0]+1, height)
+
+ def ColourRowCells(self, height):
+ if self.draw == False:
+ return
+
+ col = 0
+ for colour in self.column_bgcolour:
+ cellcolour = self.GetCellColour(self.data_cnt, col)
+ if cellcolour is not None:
+ colour = cellcolour
+
+ brush = wx.Brush(colour, wx.SOLID)
+ self.DC.SetBrush(brush)
+ self.DC.SetPen(wx.Pen(wx.NamedColour('WHITE'), 0))
+
+ start_x = self.column[col]
+ width = self.column[col+1] - start_x + 2
+ self.DC.DrawRectangle(start_x, self.y, width, height)
+ col = col + 1
+
+ def PrintRow(self, row_val, draw = True, align = wx.ALIGN_LEFT):
+ self.SetPrintFont(self.text_font)
+
+ self.pt_space_before = self.text_pt_space_before # set the point spacing
+ self.pt_space_after = self.text_pt_space_after
+
+ self.col = 0
+ max_y = 0
+ for vtxt in row_val:
+ if not isinstance(vtxt,types.StringTypes):
+ vtxt = str(vtxt)
+ self.region = self.column[self.col+1] - self.column[self.col]
+ self.indent = self.column[self.col]
+ self.align = self.column_align[self.col]
+
+ fcolour = self.column_txtcolour[self.col] # set font colour
+ celltext = self.GetCellTextColour(self.data_cnt, self.col)
+ if celltext is not None:
+ fcolour = celltext # override the column colour
+
+ self.DC.SetTextForeground(fcolour)
+
+ max_out = self.OutTextRegion(vtxt, draw)
+ if max_out > max_y:
+ max_y = max_out
+ self.col = self.col + 1
+ return max_y
+
+ def GetCellColour(self, row, col): # check if custom colour defined for the cell background
+ try:
+ set = self.cell_colour[row]
+ except:
+ return None
+ try:
+ colour = set[col]
+ return colour
+ except:
+ return None
+
+ def GetCellTextColour(self, row, col): # check if custom colour defined for the cell text
+ try:
+ set = self.cell_text[row]
+ except:
+ return None
+ try:
+ colour = set[col]
+ return colour
+ except:
+ return None
+
+ def FinishDraw(self):
+ self.DrawGridLine() # draw last row line
+ self.DrawColumns() # draw all vertical lines
+
+ def DrawGridLine(self):
+ if self.draw == True \
+ and len(self.column) > 2: #supress grid lines if only one column
+ try:
+ size = self.row_line_size[self.data_cnt]
+ except:
+ size = self.row_def_line_size
+
+ if size < 1: return
+
+ try:
+ colour = self.row_line_colour[self.data_cnt]
+ except:
+ colour = self.row_def_line_colour
+
+ self.DC.SetPen(wx.Pen(colour, size))
+
+ y_out = self.y
+# y_out = self.y + self.pt_space_before + self.pt_space_after # adjust for extra spacing
+ self.DC.DrawLine(self.column[0], y_out, self.end_x, y_out)
+
+ def DrawColumns(self):
+ if self.draw == True \
+ and len(self.column) > 2: #surpress grid line if only one column
+ col = 0
+ for val in self.column:
+ try:
+ size = self.column_line_size[col]
+ except:
+ size = self.column_def_line_size
+
+ if size < 1: continue
+
+ try:
+ colour = self.column_line_colour[col]
+ except:
+ colour = self.column_def_line_colour
+
+ indent = val
+
+ self.DC.SetPen(wx.Pen(colour, size))
+ self.DC.DrawLine(indent, self.y_start, indent, self.y)
+ col = col + 1
+
+ def DrawText(self):
+ self.DoRefresh()
+
+ def DoDrawing(self, DC):
+ size = DC.GetSize()
+ self.DC = DC
+
+ DC.BeginDrawing()
+ self.DrawText()
+ DC.EndDrawing()
+
+ self.sizew = DC.MaxY()
+ self.sizeh = DC.MaxX()
+
+
+class PrintTable(object):
+ def __init__(self, parentFrame=None):
+ self.data = []
+ self.set_column = []
+ self.label = []
+ self.header = []
+ self.footer = []
+
+ self.set_column_align = {}
+ self.set_column_bgcolour = {}
+ self.set_column_txtcolour = {}
+ self.set_cell_colour = {}
+ self.set_cell_text = {}
+ self.column_line_size = {}
+ self.column_line_colour = {}
+ self.row_line_size = {}
+ self.row_line_colour = {}
+
+ self.parentFrame = parentFrame
+ self.SetPreviewSize()
+
+ self.printData = wx.PrintData()
+ self.scale = 1.0
+
+ self.SetParms()
+ self.SetColors()
+ self.SetFonts()
+ self.TextSpacing()
+
+ self.SetPrinterOffset()
+ self.SetHeaderValue()
+ self.SetFooterValue()
+ self.SetMargins()
+ self.SetPortrait()
+
+ def SetPreviewSize(self, position = wx.Point(0, 0), size="Full"):
+ if size == "Full":
+ r = wx.GetClientDisplayRect()
+ self.preview_frame_size = r.GetSize()
+ self.preview_frame_pos = r.GetPosition()
+ else:
+ self.preview_frame_size = size
+ self.preview_frame_pos = position
+
+ def SetPaperId(self, paper):
+ self.printData.SetPaperId(paper)
+
+ def SetOrientation(self, orient):
+ self.printData.SetOrientation(orient)
+
+ def SetColors(self):
+ self.row_def_line_colour = wx.NamedColour('BLACK')
+ self.row_def_line_size = 1
+
+ self.column_def_line_colour = wx.NamedColour('BLACK')
+ self.column_def_line_size = 1
+ self.column_colour = wx.NamedColour('WHITE')
+
+ self.label_colour = wx.NamedColour('LIGHT GREY')
+
+ def SetFonts(self):
+ self.label_font = { "Name": self.default_font_name, "Size": 12, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
+ self.text_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
+
+ def TextSpacing(self):
+ self.label_pt_adj_before = 0 # point adjustment before and after the label text
+ self.label_pt_adj_after = 0
+
+ self.text_pt_adj_before = 0 # point adjustment before and after the row text
+ self.text_pt_adj_after = 0
+
+ def SetLabelSpacing(self, before, after): # method to set the label space adjustment
+ self.label_pt_adj_before = before
+ self.label_pt_adj_after = after
+
+ def SetRowSpacing(self, before, after): # method to set the row space adjustment
+ self.text_pt_adj_before = before
+ self.text_pt_adj_after = after
+
+ def SetPrinterOffset(self): # offset to adjust for printer
+ self.vertical_offset = -0.1
+ self.horizontal_offset = -0.1
+
+ def SetHeaderValue(self):
+ self.header_margin = 0.25
+ self.header_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
+ self.header_align = wx.ALIGN_CENTRE
+ self.header_indent = 0
+ self.header_type = "Text"
+
+ def SetFooterValue(self):
+ self.footer_margin = 0.7
+ self.footer_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
+ self.footer_align = wx.ALIGN_CENTRE
+ self.footer_indent = 0
+ self.footer_type = "Pageof"
+
+ def SetMargins(self):
+ self.left_margin = 0.5
+ self.right_margin = 0.5 # only used if no column sizes
+
+ self.top_margin = 0.8
+ self.bottom_margin = 1.0
+ self.cell_left_margin = 0.1
+ self.cell_right_margin = 0.1
+
+ def SetPortrait(self):
+ self.printData.SetPaperId(wx.PAPER_LETTER)
+ self.printData.SetOrientation(wx.PORTRAIT)
+ self.page_width = 8.5
+ self.page_height = 11.0
+
+ def SetLandscape(self):
+ self.printData.SetOrientation(wx.LANDSCAPE)
+ self.page_width = 11.0
+ self.page_height = 8.5
+
+ def SetParms(self):
+ self.ymax = 1
+ self.xmax = 1
+ self.page = 1
+ self.total_pg = 100
+
+ self.preview = None
+ self.page = 0
+
+ self.default_font_name = "Arial"
+ self.default_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
+
+ def SetColAlignment(self, col, align=wx.ALIGN_LEFT):
+ self.set_column_align[col] = align
+
+ def SetColBackgroundColour(self, col, colour):
+ self.set_column_bgcolour[col] = colour
+
+ def SetColTextColour(self, col, colour):
+ self.set_column_txtcolour[col] = colour
+
+ def SetCellColour(self, row, col, colour): # cell background colour
+ try:
+ set = self.set_cell_colour[row] # test if row already exists
+ try:
+ set[col] = colour # test if column already exists
+ except:
+ set = { col: colour } # create the column value
+ except:
+ set = { col: colour } # create the column value
+
+ self.set_cell_colour[row] = set # create dictionary item for colour settings
+
+ def SetCellText(self, row, col, colour): # font colour for custom cells
+ try:
+ set = self.set_cell_text[row] # test if row already exists
+ try:
+ set[col] = colour # test if column already exists
+ except:
+ set = { col: colour } # create the column value
+ except:
+ set = { col: colour } # create the column value
+
+ self.set_cell_text[row] = set # create dictionary item for colour settings
+
+ def SetColumnLineSize(self, col, size): # column line size
+ self.column_line_size[col] = size # create dictionary item for column line settings
+
+ def SetColumnLineColour(self, col, colour):
+ self.column_line_colour[col] = colour
+
+ def SetRowLineSize(self, row, size):
+ self.row_line_size[row] = size
+
+ def SetRowLineColour(self, row, colour):
+ self.row_line_colour[row] = colour
+
+ def GetColour(self, colour): # returns colours based from wxColour value
+ red = colour.Red()
+ blue = colour.Blue()
+ green = colour.Green()
+ return [red, green, blue ]
+
+ def SetHeader(self, text = "", type = "Text", font=None, align = None, indent = None, colour = None, size = None):
+ set = { "Text": text }
+
+ if font is None:
+ set["Font"] = copy.copy(self.default_font)
+ else:
+ set["Font"] = font
+
+ if colour is not None:
+ setfont = set["Font"]
+ setfont["Colour"] = self.GetColour(colour)
+
+ if size is not None:
+ setfont = set["Font"]
+ setfont["Size"] = size
+
+ if align is None:
+ set["Align"] = self.header_align
+ else:
+ set["Align"] = align
+
+ if indent is None:
+ set["Indent"] = self.header_indent
+ else:
+ set["Indent"] = indent
+
+ if type is None:
+ set["Type"] = self.header_type
+ else:
+ set["Type"] = type
+
+ self.header.append(set)
+
+ def SetFooter(self, text = "", type = None, font=None, align = None, indent = None, colour = None, size = None):
+ set = { "Text": text }
+
+ if font is None:
+ set["Font"] = copy.copy(self.default_font)
+ else:
+ set["Font"] = font
+
+ if colour is not None:
+ setfont = set["Font"]
+ setfont["Colour"] = self.GetColour(colour)
+
+ if size is not None:
+ setfont = set["Font"]
+ setfont["Size"] = size
+
+ if align is None:
+ set["Align"] = self.footer_align
+ else:
+ set["Align"] = align
+
+ if indent is None:
+ set["Indent"] = self.footer_indent
+ else:
+ set["Indent"] = indent
+
+ if type is None:
+ set["Type"] = self.footer_type
+ else:
+ set["Type"] = type
+
+ self.footer.append(set)
+
+ def Preview(self):
+ data = wx.PrintDialogData(self.printData)
+ printout = SetPrintout(self)
+ printout2 = SetPrintout(self)
+ self.preview = wx.PrintPreview(printout, printout2, data)
+ if not self.preview.Ok():
+ wx.MessageBox("There was a problem printing!", "Printing", wx.OK)
+ return
+
+ self.preview.SetZoom(60) # initial zoom value
+ frame = wx.PreviewFrame(self.preview, self.parentFrame, "Print preview")
+
+ frame.Initialize()
+ if self.parentFrame:
+ frame.SetPosition(self.preview_frame_pos)
+ frame.SetSize(self.preview_frame_size)
+ frame.Show(True)
+
+ def Print(self):
+ pdd = wx.PrintDialogData(self.printData)
+ printer = wx.Printer(pdd)
+ printout = SetPrintout(self)
+ if not printer.Print(self.parentFrame, printout):
+ if wx.Printer.GetLastError() == wx.PRINTER_ERROR:
+ wx.MessageBox("There was a problem printing.\n"
+ "Perhaps your current printer is not set correctly?",
+ "Printing", wx.OK)
+ else:
+ self.printData = wx.PrintData( printer.GetPrintDialogData().GetPrintData() )
+ printout.Destroy()
+
+ def DoDrawing(self, DC):
+ size = DC.GetSize()
+ DC.BeginDrawing()
+
+ table = PrintTableDraw(self, DC, size)
+ table.data = self.data
+ table.set_column = self.set_column
+ table.label = self.label
+ table.SetPage(self.page)
+
+ if self.preview is None:
+ table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
+ table.SetPTSize(size[0], size[1])
+ table.SetPreview(False)
+ else:
+ if self.preview == 1:
+ table.scale = self.scale
+ table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
+ else:
+ table.SetPSize(self.pwidth, self.pheight)
+
+ table.SetPTSize(self.ptwidth, self.ptheight)
+ table.SetPreview(self.preview)
+
+ table.OutCanvas()
+ self.page_total = table.total_pages # total display pages
+
+ DC.EndDrawing()
+
+ self.ymax = DC.MaxY()
+ self.xmax = DC.MaxX()
+
+ self.sizeh = size[0]
+ self.sizew = size[1]
+
+ def GetTotalPages(self):
+ self.page_total = 100
+ return self.page_total
+
+ def HasPage(self, page):
+ if page <= self.page_total:
+ return True
+ else:
+ return False
+
+ def SetPage(self, page):
+ self.page = page
+
+ def SetPageSize(self, width, height):
+ self.pwidth, self.pheight = width, height
+
+ def SetTotalSize(self, width, height):
+ self.ptwidth, self.ptheight = width, height
+
+ def SetPreview(self, preview, scale):
+ self.preview = preview
+ self.scale = scale
+
+ def SetTotalSize(self, width, height):
+ self.ptwidth = width
+ self.ptheight = height
+
+class PrintGrid(object):
+ def __init__(self, parent, grid, format = [], total_col = None, total_row = None):
+ if total_row is None:
+ total_row = grid.GetNumberRows()
+ if total_col is None:
+ total_col = grid.GetNumberCols()
+
+ self.total_row = total_row
+ self.total_col = total_col
+ self.grid = grid
+
+ data = []
+ for row in range(total_row):
+ row_val = []
+ value = grid.GetRowLabelValue(row)
+ row_val.append(value)
+
+ for col in range(total_col):
+ value = grid.GetCellValue(row, col)
+ row_val.append(value)
+ data.append(row_val)
+
+ label = [""]
+ for col in range(total_col):
+ value = grid.GetColLabelValue(col)
+ label.append(value)
+
+ self.table = PrintTable(parent)
+ self.table.cell_left_margin = 0.0
+ self.table.cell_right_margin = 0.0
+
+ self.table.label = label
+ self.table.set_column = format
+ self.table.data = data
+
+ def GetTable(self):
+ return self.table
+
+ def SetAttributes(self):
+ for row in range(self.total_row):
+ for col in range(self.total_col):
+ colour = self.grid.GetCellTextColour(row, col-1)
+ self.table.SetCellText(row, col, colour)
+
+ colour = self.grid.GetCellBackgroundColour(row, col-1)
+ self.table.SetCellColour(row, col, colour)
+
+ def Preview(self):
+ self.table.Preview()
+
+ def Print(self):
+ self.table.Print()
+
+
+class SetPrintout(wx.Printout):
+ def __init__(self, canvas):
+ wx.Printout.__init__(self)
+ self.canvas = canvas
+ self.end_pg = 1000
+
+ def OnBeginDocument(self, start, end):
+ return super(SetPrintout, self).OnBeginDocument(start, end)
+
+ def OnEndDocument(self):
+ super(SetPrintout, self).OnEndDocument()
+
+ def HasPage(self, page):
+ try:
+ end = self.canvas.HasPage(page)
+ return end
+ except:
+ return True
+
+ def GetPageInfo(self):
+ try:
+ self.end_pg = self.canvas.GetTotalPages()
+ except:
+ pass
+
+ end_pg = self.end_pg
+ str_pg = 1
+ return (str_pg, end_pg, str_pg, end_pg)
+
+ def OnPreparePrinting(self):
+ super(SetPrintout, self).OnPreparePrinting()
+
+ def OnBeginPrinting(self):
+ dc = self.GetDC()
+
+ self.preview = self.IsPreview()
+ if (self.preview):
+ self.pixelsPerInch = self.GetPPIScreen()
+ else:
+ self.pixelsPerInch = self.GetPPIPrinter()
+
+ (w, h) = dc.GetSize()
+ scaleX = float(w) / 1000
+ scaleY = float(h) / 1000
+ self.printUserScale = min(scaleX, scaleY)
+
+ super(SetPrintout, self).OnBeginPrinting()
+
+ def GetSize(self):
+ self.psizew, self.psizeh = self.GetPPIPrinter()
+ return self.psizew, self.psizeh
+
+ def GetTotalSize(self):
+ self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
+ return self.ptsizew, self.ptsizeh
+
+ def OnPrintPage(self, page):
+ dc = self.GetDC()
+ (w, h) = dc.GetSize()
+ scaleX = float(w) / 1000
+ scaleY = float(h) / 1000
+ self.printUserScale = min(scaleX, scaleY)
+ dc.SetUserScale(self.printUserScale, self.printUserScale)
+
+ self.preview = self.IsPreview()
+
+ self.canvas.SetPreview(self.preview, self.printUserScale)
+ self.canvas.SetPage(page)
+
+ self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
+ self.canvas.SetTotalSize(self.ptsizew, self.ptsizeh)
+
+ self.psizew, self.psizeh = self.GetPPIPrinter()
+ self.canvas.SetPageSize(self.psizew, self.psizeh)
+
+ self.canvas.DoDrawing(dc)
+ return True
+
+if __name__ == '__main__':
+ app = wx.App()
+ frame = wx.Frame(None, -1, "Dummy wx frame for testing printout.py")
+ frame.Show(True)
+ ptbl = PrintTable(frame)
+ ptbl.SetHeader('This is the test HEADER')
+ # a single sequence will print out as a single column with no borders ...
+ ptbl.data = (
+ 'This is the first line of text.',
+ 'This is the second line\nand the third. The fourth will be the number "4.0".',
+ 04.00,
+ 'This is the fifth line, but by design it is too long to fit in the width of a standard'\
+ ' page, so it will be forced to wrap around in order to fit without having '\
+ 'some of its verbose verbage truncated.',
+ 'Here we have the final line.'
+ )
+ #... but, if labels or columns are defined, a single sequence will print out as a single row
+ ##ptbl.label = ('One','Two','Three','Four','5')
+ ptbl.Preview()
+ app.MainLoop()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/progressindicator.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/progressindicator.py
new file mode 100644
index 0000000..c337368
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/progressindicator.py
@@ -0,0 +1,152 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.progressindicator
+# Purpose:
+#
+# Author: Robin Dunn
+#
+# Created: 22-Oct-2009
+# RCS-ID: $Id: $
+# Copyright: (c) 2009 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""
+A simple gauge with a label that is suitable for use in places like a
+status bar. It can be used in either an automatic indeterminant
+(pulse) mode or in determinante mode where the programmer will need to
+update the position of the progress bar. The indicator can be set to
+hide itself when it is not active.
+"""
+
+import wx
+
+#----------------------------------------------------------------------
+# Supported Styles
+
+PI_PULSEMODE = 1
+PI_HIDEINACTIVE = 2
+
+#----------------------------------------------------------------------
+
+class ProgressIndicator(wx.Panel):
+ def __init__(self, *args, **kw):
+ wx.Panel.__init__(self, *args, **kw)
+
+ self.label = wx.StaticText(self)
+ self.gauge = wx.Gauge(self, range=100,
+ style=wx.GA_HORIZONTAL|wx.GA_SMOOTH)
+
+ self._startCount = 0
+ self.Sizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.Sizer.Add(self.label, 0, wx.ALIGN_CENTER_VERTICAL)
+ self.Sizer.Add(self.gauge, 1, wx.EXPAND)
+
+ size = wx.DefaultSize
+ if kw.has_key('size'):
+ size = kw['size']
+ elif len(args) >= 4:
+ size=args[3] # parent, id, pos, size, style, name
+
+ self.SetInitialSize(size)
+
+ if self.HasFlag(PI_PULSEMODE):
+ self.timer = wx.Timer(self)
+ self.Bind(wx.EVT_TIMER, self.onTimer)
+ if self.HasFlag(PI_HIDEINACTIVE):
+ self.Hide()
+
+
+ def __del__(self):
+ if hasattr(self, 'timer'):
+ self.timer.Stop()
+ del self.timer
+
+
+ def Start(self, label=None):
+ """
+ Show (if necessary) and begin displaying progress
+ """
+ self._startCount += 1
+ if label is not None:
+ self.SetLabel(label)
+ if self.HasFlag(PI_HIDEINACTIVE):
+ self.Show()
+ self.Layout()
+ if self.HasFlag(PI_PULSEMODE):
+ self.gauge.Pulse()
+ self.timer.Start(250)
+ else:
+ self.gauge.SetValue(0)
+
+
+ def Stop(self, clearLabel=False):
+ """
+ Stop showing progress
+ """
+ # Make sure Stop is called as many times as Start was. Only really
+ # stop when the count reaches zero.
+ if self._startCount == 0:
+ return # should be already stopped...
+ self._startCount -= 1
+ if self._startCount:
+ return # there's still more starts than stops...
+
+ if self.HasFlag(PI_HIDEINACTIVE):
+ self.Hide()
+
+ if self.HasFlag(PI_PULSEMODE):
+ self.timer.Stop()
+
+ if clearLabel:
+ self.label.SetLabel("")
+
+
+ def SetLabel(self, text):
+ """
+ Set the text displayed in the label.
+ """
+ self.label.SetLabel(text)
+ self.Layout()
+
+
+ def SetValue(self, value, label=None):
+ """
+ For determinante mode (non-pulse) update the progress indicator to the
+ given value. For example, if the job is 45% done then pass 45 to this
+ method (as long as the range is still set to 100.)
+ """
+ if label is not None:
+ self.SetLabel(label)
+ self.gauge.SetValue(value)
+
+
+ def SetRange(self, maxval):
+ """
+ For determinante mode (non-pulse) set the max value that the gauge can
+ be set to. Defaults to 100.
+ """
+ self.gauge.SetRange(maxval)
+
+
+ def onTimer(self, evt):
+ self.gauge.Pulse()
+
+
+#----------------------------------------------------------------------
+
+if __name__ == '__main__':
+ app = wx.App(redirect=False)
+ frm = wx.Frame(None, title="ProgressIndicator")
+ pnl = wx.Panel(frm)
+ pi1 = ProgressIndicator(pnl, pos=(20,20), size=(150,-1),
+ style=PI_HIDEINACTIVE|PI_PULSEMODE)
+
+ pi2 = ProgressIndicator(pnl, pos=(20,60), size=(150,-1),
+ style=PI_HIDEINACTIVE)
+
+ import wx.lib.inspection
+ wx.lib.inspection.InspectionTool().Show()
+
+ frm.Show()
+ app.MainLoop()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/__init__.py
new file mode 100644
index 0000000..bace45f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/__init__.py
@@ -0,0 +1,25 @@
+"""
+Pubsub package initialization.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+Last change info:
+- $Date: 2013-12-22 11:36:16 -0500 (Sun, 22 Dec 2013) $
+- $Revision: 344 $
+
+"""
+
+LAST_RELEASE_DATE = "2013-09-15"
+LAST_RELEASE_VER = "3.2.1b"
+
+__version__ = "3.3.0rc1"
+
+__all__ = [
+ 'pub',
+ 'utils',
+ 'setupkwargs',
+ 'setuparg1',
+ '__version__'
+ ]
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/__init__.py
new file mode 100644
index 0000000..ca66104
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/__init__.py
@@ -0,0 +1,92 @@
+"""
+Core package of pubsub, holding the publisher, listener, and topic
+object modules. Functions defined here are used internally by
+pubsub so that the right modules can be found later, based on the
+selected messaging protocol.
+
+Indeed some of the API depends on the messaging
+protocol used. For instance sendMessage(), defined in publisher.py,
+has a different signature (and hence implementation) for the kwargs
+protocol than for the arg1 protocol.
+
+The most convenient way to
+support this is to put the parts of the package that differ based
+on protocol in separate folder, and add one of those folders to
+the package's __path__ variable (defined automatically by the Python
+interpreter when __init__.py is executed). For instance, code
+specific to the kwargs protocol goes in the kwargs folder, and code
+specific to the arg1 protocol in the arg1 folder. Then when doing
+"from pubsub.core import listener", the correct listener.py will be
+found for the specified protocol. The default protocol is kwargs.
+
+Only one protocol can be used in an application. The default protocol,
+if none is chosen by user, is kwargs, as selected by the call to
+_prependModulePath() at end of this file.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+
+def _prependModulePath(extra):
+ """Insert extra at beginning of package's path list. Should only be
+ called once, at package load time, to set the folder used for
+ implementation specific to the default message protocol."""
+ corepath = __path__
+ initpyLoc = corepath[-1]
+ import os
+ corepath.insert(0, os.path.join(initpyLoc, extra))
+
+# add appropriate subdir for protocol-specific implementation
+from .. import policies
+_prependModulePath(policies.msgDataProtocol)
+
+from .publisher import Publisher
+
+from .callables import (
+ AUTO_TOPIC,
+)
+
+from .listener import (
+ Listener,
+ getID as getListenerID,
+ ListenerMismatchError,
+ IListenerExcHandler,
+)
+
+from .topicobj import (
+ Topic,
+ SenderMissingReqdMsgDataError,
+ SenderUnknownMsgDataError,
+ MessageDataSpecError,
+ TopicDefnError,
+ ExcHandlerError,
+)
+
+from .topicmgr import (
+ TopicManager,
+ TopicDefnError,
+ TopicNameError,
+ ALL_TOPICS,
+)
+
+from .topicdefnprovider import (
+ ITopicDefnProvider,
+ TopicDefnProvider,
+ ITopicDefnDeserializer,
+ UnrecognizedSourceFormatError,
+
+ exportTopicTreeSpec,
+ TOPIC_TREE_FROM_MODULE,
+ TOPIC_TREE_FROM_STRING,
+ TOPIC_TREE_FROM_CLASS,
+)
+
+from .topictreetraverser import (
+ TopicTreeTraverser,
+)
+
+from .notificationmgr import (
+ INotificationHandler,
+) \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/__init__.py
new file mode 100644
index 0000000..d84ec66
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/__init__.py
@@ -0,0 +1,16 @@
+"""
+This is not really a package init file, it is only here to simplify the
+packaging and installation of pubsub.core's protocol-specific subfolders
+by setuptools. The python modules in this folder are automatically made
+part of pubsub.core via pubsub.core's __path__. Hence, this should not
+be imported directly, it is part of pubsub.core when the messaging
+protocol is "arg1" (and not usable otherwise).
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+
+msg = 'Should not import this directly, used by pubsub.core if applicable'
+raise RuntimeError(msg) \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/listenerimpl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/listenerimpl.py
new file mode 100644
index 0000000..5178a92
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/listenerimpl.py
@@ -0,0 +1,97 @@
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from .listenerbase import (ListenerBase, ValidatorBase)
+from .callables import ListenerMismatchError
+from .. import policies
+
+
+class Message:
+ """
+ A simple container object for the two components of a topic messages
+ in the pubsub legacy API: the
+ topic and the user data. An instance of Message is given to your
+ listener when called by sendMessage(topic). The data is accessed
+ via the 'data' attribute, and can be type of object.
+ """
+ def __init__(self, topicNameTuple, data):
+ self.topic = topicNameTuple
+ self.data = data
+
+ def __str__(self):
+ return '[Topic: '+repr(self.topic)+', Data: '+repr(self.data)+']'
+
+
+class Listener(ListenerBase):
+ """
+ Wraps a callable so it can be stored by weak reference and introspected
+ to verify that it adheres to a topic's MDS.
+
+ A Listener instance has the same hash value as the callable that it wraps.
+
+ A callable will be given data when a message is sent to it. In the arg1
+ protocol only one object can be sent via sendMessage, it is put in a
+ Message object in its "data" field, the listener receives the Message
+ object.
+ """
+
+ def __call__(self, actualTopic, data):
+ """Call the listener with data. Note that it raises RuntimeError
+ if listener is dead. Should always return True (False would require
+ the callable_ be dead but self hasn't yet been notified of it...)."""
+ kwargs = {}
+ if self._autoTopicArgName is not None:
+ kwargs[self._autoTopicArgName] = actualTopic
+ cb = self._callable()
+ if cb is None:
+ self._calledWhenDead()
+ msg = Message(actualTopic.getNameTuple(), data)
+ cb(msg, **kwargs)
+ return True
+
+
+class ListenerValidator(ValidatorBase):
+ """
+ Accept one arg or *args; accept any **kwarg,
+ and require that the Listener have at least all the kwargs (can
+ have extra) of Topic.
+ """
+
+ def _validateArgs(self, listener, paramsInfo):
+ # accept **kwargs
+ # accept *args
+ # accept any keyword args
+
+ if (paramsInfo.getAllArgs() == ()) and paramsInfo.acceptsAllUnnamedArgs:
+ return
+
+ if paramsInfo.getAllArgs() == ():
+ msg = 'Must have at least one parameter (any name, with or without default value, or *arg)'
+ raise ListenerMismatchError(msg, listener, [])
+
+ assert paramsInfo.getAllArgs()
+ #assert not paramsInfo.acceptsAllUnnamedArgs
+
+ # verify at most one required arg
+ numReqdArgs = paramsInfo.numRequired
+ if numReqdArgs > 1:
+ allReqd = paramsInfo.getRequiredArgs()
+ msg = 'only one of %s can be a required agument' % (allReqd,)
+ raise ListenerMismatchError(msg, listener, allReqd)
+
+ # if no required args but listener has *args, then we
+ # don't care about anything else:
+ if numReqdArgs == 0 and paramsInfo.acceptsAllUnnamedArgs:
+ return
+
+ # if no policy set, any name ok; otherwise validate name:
+ needArgName = policies.msgDataArgName
+ firstArgName = paramsInfo.allParams[0]
+ if (needArgName is not None) and firstArgName != needArgName:
+ msg = 'listener arg name must be "%s" (is "%s")' % (needArgName, firstArgName)
+ effTopicArgs = [needArgName]
+ raise ListenerMismatchError(msg, listener, effTopicArgs)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/publisher.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/publisher.py
new file mode 100644
index 0000000..d36c0a4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/publisher.py
@@ -0,0 +1,40 @@
+"""
+Mixin for publishing messages to a topic's listeners. This will be
+mixed into topicobj.Topic so that a user can use a Topic object to
+send a message to the topic's listeners via a publish() method.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+
+from .publisherbase import PublisherBase
+
+
+class Publisher(PublisherBase):
+ """
+ Publisher that allows old-style Message.data messages to be sent
+ to listeners. Listeners take one arg (required, unless there is an
+ *arg), but can have kwargs (since they have default values).
+ """
+
+ def sendMessage(self, topicName, data=None):
+ """Send message of type topicName to all subscribed listeners,
+ with message data. If topicName is a subtopic, listeners
+ of topics more general will also get the message.
+
+ Note that any listener that lets a raised exception escape will
+ interrupt the send operation, unless an exception handler was
+ specified via pub.setListenerExcHandler().
+ """
+ topicMgr = self.getTopicMgr()
+ topicObj = topicMgr.getOrCreateTopic(topicName)
+
+ # don't care if topic not final: topicObj.getListeners()
+ # will return nothing if not final but notification will still work
+
+ topicObj.publish(data)
+
+ def getMsgProtocol(self):
+ return 'arg1'
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/publishermixin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/publishermixin.py
new file mode 100644
index 0000000..942dee5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/publishermixin.py
@@ -0,0 +1,34 @@
+"""
+Mixin for publishing messages to a topic's listeners. This will be
+mixed into topicobj.Topic so that a user can use a Topic object to
+send a message to the topic's listeners via a publish() method.
+
+Note that it is important that the PublisherMixin NOT modify any
+state data during message sending, because in principle it could
+happen that a listener causes another message of same topic to be
+sent (presumably, the listener has a way of preventing infinite
+loop).
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+
+class PublisherMixin:
+ def __init__(self):
+ pass
+
+ def publish(self, data=None):
+ self._publish(data)
+
+ ############## IMPLEMENTATION ###############
+
+ def _mix_prePublish(self, data, topicObj=None, iterState=None):
+ """Called just before the __sendMessage, to perform any argument
+ checking, set iterState, etc"""
+ return None
+
+ def _mix_callListener(self, listener, data, iterState):
+ """Send the data to given listener."""
+ listener(self, data)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/topicargspecimpl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/topicargspecimpl.py
new file mode 100644
index 0000000..d274fa6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/topicargspecimpl.py
@@ -0,0 +1,66 @@
+"""
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+import weakref
+from .topicutils import WeakNone
+
+class SenderMissingReqdMsgDataError(RuntimeError):
+ """
+ Ignore: Not used for this message protocol.
+ """
+ pass
+
+
+class SenderUnknownMsgDataError(RuntimeError):
+ """
+ Ignore: Not used for this message protocol.
+ """
+ pass
+
+
+class ArgsInfo:
+ """
+ Encode the Message Data Specification (MDS) for a given
+ topic. In the arg1 protocol of pubsub, this MDS is the same for all
+ topics, so this is quite a simple class, required only because
+ the part of pubsub that uses ArgsInfos supports several API
+ versions using one common API. So the only difference between
+ an ArgsInfo and an ArgSpecGiven is that ArgsInfo refers to
+ parent topic's ArgsInfo; other data members are the same.
+
+ Note that the MDS is always complete because it is known:
+ it consists of one required argument named 'data' and no
+ optional arguments.
+ """
+
+ SPEC_MISSING = 10 # no args given
+ SPEC_COMPLETE = 12 # all args, but not confirmed via user spec
+
+ def __init__(self, topicNameTuple, specGiven, parentArgsInfo):
+ self.__argsDocs = specGiven.argsDocs or {'data':'message data'}
+
+ self.argsSpecType = self.SPEC_COMPLETE
+ self.allOptional = () # list of topic message optional argument names
+ self.allRequired = ('data',) # list of topic message required argument names
+
+ self.parentAI = WeakNone()
+ if parentArgsInfo is not None:
+ self.parentAI = weakref.ref(parentArgsInfo)
+
+ def isComplete(self):
+ return True
+
+ def getArgs(self):
+ return self.allOptional + self.allRequired
+
+ def numArgs(self):
+ return len(self.allOptional) + len(self.allRequired)
+
+ def getArgsDocs(self):
+ return self.__argsDocs.copy()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/topicmgrimpl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/topicmgrimpl.py
new file mode 100644
index 0000000..31167cb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/arg1/topicmgrimpl.py
@@ -0,0 +1,19 @@
+"""
+The root topic of all topics is different based on messaging protocol.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+from .. import policies
+
+
+def getRootTopicSpec():
+ """If using "arg1" messaging protocol, then root topic has one arg;
+ if policies.msgDataArgName is something, then use it as arg name."""
+ argName = policies.msgDataArgName or 'data'
+ argsDocs = {argName : 'data for message sent'}
+ reqdArgs = (argName,)
+ return argsDocs, reqdArgs
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/callables.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/callables.py
new file mode 100644
index 0000000..e94032e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/callables.py
@@ -0,0 +1,191 @@
+"""
+Low level functions and classes related to callables.
+
+The AUTO_TOPIC
+is the "marker" to use in callables to indicate that when a message
+is sent to those callables, the topic object for that message should be
+added to the data sent via the call arguments. See the docs in
+CallArgsInfo regarding its autoTopicArgName data member.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+from inspect import getargspec, ismethod, isfunction
+
+from .. import py2and3
+
+AUTO_TOPIC = '## your listener wants topic name ## (string unlikely to be used by caller)'
+
+
+def getModule(obj):
+ """Get the module in which an object was defined. Returns '__main__'
+ if no module defined (which usually indicates either a builtin, or
+ a definition within main script). """
+ if hasattr(obj, '__module__'):
+ module = obj.__module__
+ else:
+ module = '__main__'
+ return module
+
+
+def getID(callable_):
+ """Get name and module name for a callable, ie function, bound
+ method or callable instance, by inspecting the callable. E.g.
+ getID(Foo.bar) returns ('Foo.bar', 'a.b') if Foo.bar was
+ defined in module a.b. """
+ sc = callable_
+ if ismethod(sc):
+ module = getModule(sc.__self__)
+ id = '%s.%s' % (sc.__self__.__class__.__name__, sc.__func__.__name__)
+ elif isfunction(sc):
+ module = getModule(sc)
+ id = sc.__name__
+ else: # must be a functor (instance of a class that has __call__ method)
+ module = getModule(sc)
+ id = sc.__class__.__name__
+
+ return id, module
+
+
+def getRawFunction(callable_):
+ """Given a callable, return (offset, func) where func is the
+ function corresponding to callable, and offset is 0 or 1 to
+ indicate whether the function's first argument is 'self' (1)
+ or not (0). Raises ValueError if callable_ is not of a
+ recognized type (function, method or has __call__ method)."""
+ firstArg = 0
+ if isfunction(callable_):
+ #print 'Function', getID(callable_)
+ func = callable_
+ elif ismethod(callable_):
+ #print 'Method', getID(callable_)
+ func = callable_
+ if func.__self__ is not None:
+ # Method is bound, don't care about the self arg
+ firstArg = 1
+ elif hasattr(callable_, '__call__'):
+ #print 'Functor', getID(callable_)
+ func = callable_.__call__
+ firstArg = 1 # don't care about the self arg
+ else:
+ msg = 'type "%s" not supported' % type(callable_).__name__
+ raise ValueError(msg)
+
+ return func, firstArg
+
+
+class ListenerMismatchError(ValueError):
+ """
+ Raised when an attempt is made to subscribe a listener to
+ a topic, but listener does not satisfy the topic's message data
+ specification (MDS). This specification is inferred from the first
+ listener subscribed to a topic, or from an imported topic tree
+ specification (see pub.addTopicDefnProvider()).
+ """
+
+ def __init__(self, msg, listener, *args):
+ idStr, module = getID(listener)
+ msg = 'Listener "%s" (from module "%s") inadequate: %s' % (idStr, module, msg)
+ ValueError.__init__(self, msg)
+ self.msg = msg
+ self.args = args
+ self.module = module
+ self.idStr = idStr
+
+ def __str__(self):
+ return self.msg
+
+
+class CallArgsInfo:
+ """
+ Represent the "signature" or protocol of a listener in the context of
+ topics.
+ """
+
+ def __init__(self, func, firstArgIdx): #args, firstArgIdx, defaultVals, acceptsAllKwargs=False):
+ """Inputs:
+ - Args and defaultVals are the complete set of arguments and
+ default values as obtained form inspect.getargspec();
+ - The firstArgIdx points to the first item in
+ args that is of use, so it is typically 0 if listener is a function,
+ and 1 if listener is a method.
+ - The acceptsAllKwargs should be true
+ if the listener has **kwargs in its protocol.
+
+ After construction,
+ - self.allParams will contain the subset of 'args' without first
+ firstArgIdx items,
+ - self.numRequired will indicate number of required arguments
+ (ie self.allParams[:self.numRequired] are the required args names);
+ - self.acceptsAllKwargs = acceptsAllKwargs
+ - self.autoTopicArgName will be the name of argument
+ in which to put the topic object for which pubsub message is
+ sent, or None. This is identified by the argument that has a
+ default value of AUTO_TOPIC.
+
+ For instance, listener(self, arg1, arg2=AUTO_TOPIC, arg3=None) will
+ have self.allParams = (arg1, arg2, arg3), self.numRequired=1, and
+ self.autoTopicArgName = 'arg2', whereas
+ listener(self, arg1, arg3=None) will have
+ self.allParams = (arg1, arg3), self.numRequired=1, and
+ self.autoTopicArgName = None."""
+
+ #args, firstArgIdx, defaultVals, acceptsAllKwargs
+ (allParams, varParamName, varOptParamName, defaultVals) = getargspec(func)
+ if defaultVals is None:
+ defaultVals = []
+ else:
+ defaultVals = list(defaultVals)
+
+ self.acceptsAllKwargs = (varOptParamName is not None)
+ self.acceptsAllUnnamedArgs = (varParamName is not None)
+
+ self.allParams = allParams
+ del self.allParams[0:firstArgIdx] # does nothing if firstArgIdx == 0
+
+ self.numRequired = len(self.allParams) - len(defaultVals)
+ assert self.numRequired >= 0
+
+ # if listener wants topic, remove that arg from args/defaultVals
+ self.autoTopicArgName = None
+ if defaultVals:
+ self.__setupAutoTopic(defaultVals)
+
+ def getAllArgs(self):
+ return tuple( self.allParams )
+
+ def getOptionalArgs(self):
+ return tuple( self.allParams[self.numRequired:] )
+
+ def getRequiredArgs(self):
+ """Return a tuple of names indicating which call arguments
+ are required to be present when pub.sendMessage(...) is called. """
+ return tuple( self.allParams[:self.numRequired] )
+
+ def __setupAutoTopic(self, defaults):
+ """Does the listener want topic of message? Returns < 0 if not,
+ otherwise return index of topic kwarg within args."""
+ for indx, defaultVal in enumerate(defaults):
+ if defaultVal == AUTO_TOPIC:
+ #del self.defaults[indx]
+ firstKwargIdx = self.numRequired
+ self.autoTopicArgName = self.allParams.pop(firstKwargIdx + indx)
+ break
+
+
+def getArgs(callable_):
+ """Returns an instance of CallArgsInfo for the given callable_.
+ Raises ListenerMismatchError if callable_ is not a callable."""
+ # figure out what is the actual function object to inspect:
+ try:
+ func, firstArgIdx = getRawFunction(callable_)
+ except ValueError:
+ from .. import py2and3
+ exc = py2and3.getexcobj()
+ raise ListenerMismatchError(str(exc), callable_)
+
+ return CallArgsInfo(func, firstArgIdx)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/imp2.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/imp2.py
new file mode 100644
index 0000000..e9ba8b7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/imp2.py
@@ -0,0 +1,63 @@
+"""
+The _resolve_name and _import_module were taken from the backport of
+importlib.import_module from 3.x to 2.7. Thanks to the Python developers
+for making this available as a standalone module. This makes it possible
+to have an import module that mimics the "import" statement more
+closely.
+"""
+
+import sys
+from .. import py2and3
+
+def _resolve_name(name, package, level):
+ """Return the absolute name of the module to be imported."""
+ if not hasattr(package, 'rindex'):
+ raise ValueError("'package' not set to a string")
+ dot = len(package)
+ for x in py2and3.xrange(level, 1, -1):
+ try:
+ dot = package.rindex('.', 0, dot)
+ except ValueError:
+ raise ValueError("attempted relative import beyond top-level "
+ "package")
+ return "%s.%s" % (package[:dot], name)
+
+
+def _import_module(name, package=None):
+ """Import a module.
+
+ The 'package' argument is required when performing a relative import. It
+ specifies the package to use as the anchor point from which to resolve the
+ relative import to an absolute import.
+ """
+ if name.startswith('.'):
+ if not package:
+ raise TypeError("relative imports require the 'package' argument")
+ level = 0
+ for character in name:
+ if character != '.':
+ break
+ level += 1
+ name = _resolve_name(name[level:], package, level)
+ __import__(name)
+ return sys.modules[name]
+
+
+def load_module(moduleName, searchPath):
+ """Try to import moduleName. If this doesn't work, use the "imp" module
+ that is part of Python. """
+ try:
+ module = _import_module(moduleName)
+
+ except:
+ import imp
+ fp, pathname, description = imp.find_module(moduleName, searchPath)
+ try:
+ module = imp.load_module(moduleName, fp, pathname, description)
+
+ finally:
+ # Since we may exit via an exception, close fp explicitly.
+ if fp:
+ fp.close()
+
+ return module
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/itopicdefnprovider.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/itopicdefnprovider.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/itopicdefnprovider.py
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/__init__.py
new file mode 100644
index 0000000..8fde7a7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/__init__.py
@@ -0,0 +1,16 @@
+"""
+This is not really a package init file, it is only here to simplify the
+packaging and installation of pubsub.core's protocol-specific subfolders
+by setuptools. The python modules in this folder are automatically made
+part of pubsub.core via pubsub.core's __path__. Hence, this should not
+be imported directly, it is part of pubsub.core when the messaging
+protocol is "kwargs" (and not usable otherwise).
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+
+msg = 'Should not import this directly, used by pubsub.core if applicable'
+raise RuntimeError(msg) \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/datamsg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/datamsg.py
new file mode 100644
index 0000000..99fd30e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/datamsg.py
@@ -0,0 +1,27 @@
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+class Message:
+ """
+ A simple container object for the two components of a message in the
+ arg1 messaging protocol: the
+ topic and the user data. Each listener called by sendMessage(topic, data)
+ gets an instance of Message. The given 'data' is accessed
+ via Message.data, while the topic name is available in Message.topic::
+
+ def listener(msg):
+ print "data is ", msg.data
+ print "topic name is ", msg.topic
+ print msg
+
+ The example also shows (last line) how a message is convertible to a string.
+ """
+ def __init__(self, topic, data):
+ self.topic = topic
+ self.data = data
+
+ def __str__(self):
+ return '[Topic: '+repr(self.topic)+', Data: '+repr(self.data)+']'
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/listenerimpl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/listenerimpl.py
new file mode 100644
index 0000000..6a5e46a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/listenerimpl.py
@@ -0,0 +1,93 @@
+"""
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+from .listenerbase import ListenerBase, ValidatorBase
+from .callables import ListenerMismatchError
+
+
+class Listener(ListenerBase):
+ """
+ Wraps a callable so it can be stored by weak reference and introspected
+ to verify that it adheres to a topic's MDS.
+
+ A Listener instance
+ has the same hash value as the callable that it wraps.
+
+ Callables that have 'argName=pub.AUTO_TOPIC' as a kwarg will
+ be given the Topic object for the message sent by sendMessage().
+ Such a Listener will have wantsTopicObjOnCall() True.
+
+ Callables that have a '\**kargs' argument will receive all message
+ data, not just that for the topic they are subscribed to. Such a listener
+ will have wantsAllMessageData() True.
+ """
+
+ def __call__(self, kwargs, actualTopic, allKwargs=None):
+ """Call the listener with **kwargs. Note that it raises RuntimeError
+ if listener is dead. Should always return True (False would require
+ the callable_ be dead but self hasn't yet been notified of it...)."""
+ if self.acceptsAllKwargs:
+ kwargs = allKwargs or kwargs # if allKwargs is None then use kwargs
+
+ if self._autoTopicArgName is not None:
+ kwargs = kwargs.copy()
+ kwargs[self._autoTopicArgName] = actualTopic
+
+ cb = self._callable()
+ if cb is None:
+ self._calledWhenDead()
+ cb(**kwargs)
+
+ return True
+
+
+class ListenerValidator(ValidatorBase):
+ """
+ Do not accept any required args or *args; accept any **kwarg,
+ and require that the Listener have at least all the kwargs (can
+ have extra) of Topic.
+ """
+
+ def _validateArgs(self, listener, paramsInfo):
+ # accept **kwargs
+ # accept *args
+
+ # check if listener missing params (only possible if
+ # paramsInfo.acceptsAllKwargs is False)
+ allTopicMsgArgs = self._topicArgs | self._topicKwargs
+ allParams = set(paramsInfo.allParams)
+ if not paramsInfo.acceptsAllKwargs:
+ missingParams = allTopicMsgArgs - allParams
+ if missingParams:
+ msg = 'needs to accept %s more args (%s)' \
+ % (len(missingParams), ''.join(missingParams))
+ raise ListenerMismatchError(msg, listener, missingParams)
+ else:
+ # then can accept that some parameters missing from listener
+ # signature
+ pass
+
+ # check if there are unknown parameters in listener signature:
+ extraArgs = allParams - allTopicMsgArgs
+ if extraArgs:
+ if allTopicMsgArgs:
+ msg = 'args (%s) not allowed, should be (%s)' \
+ % (','.join(extraArgs), ','.join(allTopicMsgArgs))
+ else:
+ msg = 'no args allowed, has (%s)' % ','.join(extraArgs)
+ raise ListenerMismatchError(msg, listener, extraArgs)
+
+ # we accept listener that has fewer required paams than TMS
+ # since all args passed by name (previous showed that spec met
+ # for all parameters).
+
+ # now make sure listener doesn't require params that are optional in TMS:
+ extraArgs = set( paramsInfo.getRequiredArgs() ) - self._topicArgs
+ if extraArgs:
+ msg = 'params (%s) missing default values' % (','.join(extraArgs),)
+ raise ListenerMismatchError(msg, listener, extraArgs)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/publisher.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/publisher.py
new file mode 100644
index 0000000..7575be6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/publisher.py
@@ -0,0 +1,77 @@
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+
+from .publisherbase import PublisherBase
+from .datamsg import Message
+from .. import (policies, py2and3)
+
+
+
+class Publisher(PublisherBase):
+ """
+ Publisher used for kwargs protocol, ie when sending message data
+ via keyword arguments.
+ """
+
+ def sendMessage(self, topicName, **kwargs):
+ """Send a message.
+
+ :param topicName: name of message topic (dotted or tuple format)
+ :param kwargs: message data (must satisfy the topic's MDS)
+ """
+ topicMgr = self.getTopicMgr()
+ topicObj = topicMgr.getOrCreateTopic(topicName)
+ topicObj.publish(**kwargs)
+
+ def getMsgProtocol(self):
+ return 'kwargs'
+
+
+class PublisherArg1Stage2(Publisher):
+ """
+ This is used when transitioning from arg1 to kwargs
+ messaging protocol.
+ """
+
+ _base = Publisher
+
+ class SenderTooManyKwargs(RuntimeError):
+ def __init__(self, kwargs, commonArgName):
+ extra = kwargs.copy()
+ del extra[commonArgName]
+ msg = 'Sender has too many kwargs (%s)' % ( py2and3.keys(extra),)
+ RuntimeError.__init__(self, msg)
+
+ class SenderWrongKwargName(RuntimeError):
+ def __init__(self, actualKwargName, commonArgName):
+ msg = 'Sender uses wrong kwarg name ("%s" instead of "%s")' \
+ % (actualKwargName, commonArgName)
+ RuntimeError.__init__(self, msg)
+
+ def __init__(self, treeConfig = None):
+ self._base.__init__(self, treeConfig)
+ self.Msg = Message
+
+ def sendMessage(self, _topicName, **kwarg):
+ commonArgName = policies.msgDataArgName
+ if len(kwarg) > 1:
+ raise self.SenderTooManyKwargs(kwarg, commonArgName)
+ elif len(kwarg) == 1 and commonArgName not in kwarg:
+ raise self.SenderWrongKwargName( py2and3.keys(kwarg)[0], commonArgName)
+
+ data = kwarg.get(commonArgName, None)
+ kwargs = { commonArgName: self.Msg( _topicName, data) }
+ self._base.sendMessage( self, _topicName, **kwargs )
+
+ def getMsgProtocol(self):
+ return 'kwarg1'
+
+
+if policies.msgProtocolTransStage is not None:
+ Publisher = PublisherArg1Stage2
+ #print 'Using protocol', Publisher
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/publishermixin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/publishermixin.py
new file mode 100644
index 0000000..21c5cb7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/publishermixin.py
@@ -0,0 +1,65 @@
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+
+class PublisherMixin:
+ """
+ Mixin for publishing messages to a topic's listeners. This will be
+ mixed into topicobj.Topic so that a user can use a Topic object to
+ send a message to the topic's listeners via a publish() method.
+
+ Note that it is important that the PublisherMixin NOT modify any
+ state data during message sending, because in principle it could
+ happen that a listener causes another message of same topic to be
+ sent (presumably, the listener has a way of preventing infinite
+ loop).
+ """
+
+ def __init__(self):
+ pass
+
+ def publish(self, **msgKwargs):
+ self._publish(msgKwargs)
+
+ ############## IMPLEMENTATION ###############
+
+ class IterState:
+ def __init__(self, msgKwargs):
+ self.filteredArgs = msgKwargs
+ self.argsChecked = False
+
+ def checkMsgArgs(self, spec):
+ spec.check(self.filteredArgs)
+ self.argsChecked = True
+
+ def filterMsgArgs(self, topicObj):
+ if self.argsChecked:
+ self.filteredArgs = topicObj.filterMsgArgs(self.filteredArgs)
+ else:
+ self.filteredArgs = topicObj.filterMsgArgs(self.filteredArgs, True)
+ self.argsChecked = True
+
+ def _mix_prePublish(self, msgKwargs, topicObj=None, iterState=None):
+ if iterState is None:
+ # do a first check that all args are there, costly so only do once
+ iterState = self.IterState(msgKwargs)
+ if self.hasMDS():
+ iterState.checkMsgArgs( self._getListenerSpec() )
+ else:
+ assert not self.hasListeners()
+
+ else:
+ iterState.filterMsgArgs(topicObj)
+
+ assert iterState is not None
+ return iterState
+
+ def _mix_callListener(self, listener, msgKwargs, iterState):
+ """Send the message for given topic with data in msgKwargs.
+ This sends message to listeners of parent topics as well.
+ Note that at each level, msgKwargs is filtered so only those
+ args that are defined for the topic are sent to listeners. """
+ listener(iterState.filteredArgs, self, msgKwargs)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/topicargspecimpl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/topicargspecimpl.py
new file mode 100644
index 0000000..d167f95
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/topicargspecimpl.py
@@ -0,0 +1,217 @@
+"""
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+import weakref
+
+from .topicutils import (stringize, WeakNone)
+from .validatedefnargs import verifySubset
+from .. import py2and3
+
+### Exceptions raised during check() from sendMessage()
+
+class SenderMissingReqdMsgDataError(RuntimeError):
+ """
+ Raised when a sendMessage() is missing arguments tagged as
+ 'required' by pubsub topic of message.
+ """
+
+ def __init__(self, topicName, argNames, missing):
+ argsStr = ','.join(argNames)
+ missStr = ','.join(missing)
+ msg = "Some required args missing in call to sendMessage('%s', %s): %s" \
+ % (stringize(topicName), argsStr, missStr)
+ RuntimeError.__init__(self, msg)
+
+
+class SenderUnknownMsgDataError(RuntimeError):
+ """
+ Raised when a sendMessage() has arguments not listed among the topic's
+ message data specification (MDS).
+ """
+
+ def __init__(self, topicName, argNames, extra):
+ argsStr = ','.join(argNames)
+ extraStr = ','.join(extra)
+ msg = "Some optional args unknown in call to sendMessage('%s', %s): %s" \
+ % (topicName, argsStr, extraStr)
+ RuntimeError.__init__(self, msg)
+
+
+class ArgsInfo:
+ """
+ Encode the Message Data Specification (MDS) for a given
+ topic. ArgsInfos form a tree identical to that of Topics in that
+ ArgInfos have a reference to their parent and children ArgInfos,
+ created for the parent and children topics.
+
+ The only difference
+ between an ArgsInfo and an ArgSpecGiven is that the latter is
+ what "user thinks is ok" whereas former has been validated:
+ the specification for this topic is a strict superset of the
+ specification of its parent, and a strict subset of the
+ specification of each of its children. Also, the instance
+ can be used to check validity and filter arguments.
+
+ The MDS can be created "empty", ie "incomplete", meaning it cannot
+ yet be used to validate listener subscriptions to topics.
+ """
+
+ SPEC_MISSING = 10 # no args given
+ SPEC_COMPLETE = 12 # all args, but not confirmed via user spec
+
+
+ def __init__(self, topicNameTuple, specGiven, parentArgsInfo):
+ self.topicNameTuple = topicNameTuple
+ self.allOptional = () # topic message optional arg names
+ self.allDocs = {} # doc for each arg
+ self.allRequired = () # topic message required arg names
+ self.argsSpecType = self.SPEC_MISSING
+ self.parentAI = WeakNone()
+ if parentArgsInfo is not None:
+ self.parentAI = weakref.ref(parentArgsInfo)
+ parentArgsInfo.__addChildAI(self)
+ self.childrenAI = []
+
+ if specGiven.isComplete():
+ self.__setAllArgs(specGiven)
+
+ def isComplete(self):
+ return self.argsSpecType == self.SPEC_COMPLETE
+
+ def getArgs(self):
+ return self.allOptional + self.allRequired
+
+ def numArgs(self):
+ return len(self.allOptional) + len(self.allRequired)
+
+ def getReqdArgs(self):
+ return self.allRequired
+
+ def getOptArgs(self):
+ return self.allOptional
+
+ def getArgsDocs(self):
+ return self.allDocs.copy()
+
+ def setArgsDocs(self, docs):
+ """docs is a mapping from arg names to their documentation"""
+ if not self.isComplete():
+ raise
+ for arg, doc in py2and3.iteritems(docs):
+ self.allDocs[arg] = doc
+
+ def check(self, msgKwargs):
+ """Check that the message arguments given satisfy the topic message
+ data specification (MDS). Raises SenderMissingReqdMsgDataError if some required
+ args are missing or not known, and raises SenderUnknownMsgDataError if some
+ optional args are unknown. """
+ all = set(msgKwargs)
+ # check that it has all required args
+ needReqd = set(self.allRequired)
+ hasReqd = (needReqd <= all)
+ if not hasReqd:
+ raise SenderMissingReqdMsgDataError(
+ self.topicNameTuple, py2and3.keys(msgKwargs), needReqd - all)
+
+ # check that all other args are among the optional spec
+ optional = all - needReqd
+ ok = (optional <= set(self.allOptional))
+ if not ok:
+ raise SenderUnknownMsgDataError( self.topicNameTuple,
+ py2and3.keys(msgKwargs), optional - set(self.allOptional) )
+
+ def filterArgs(self, msgKwargs):
+ """Returns a dict which contains only those items of msgKwargs
+ which are defined for topic. E.g. if msgKwargs is {a:1, b:'b'}
+ and topic arg spec is ('a',) then return {a:1}. The returned dict
+ is valid only if check(msgKwargs) was called (or
+ check(superset of msgKwargs) was called)."""
+ assert self.isComplete()
+ if len(msgKwargs) == self.numArgs():
+ return msgKwargs
+
+ # only keep the keys from msgKwargs that are also in topic's kwargs
+ # method 1: SLOWEST
+ #newKwargs = dict( (k,msgKwargs[k]) for k in self.__msgArgs.allOptional if k in msgKwargs )
+ #newKwargs.update( (k,msgKwargs[k]) for k in self.__msgArgs.allRequired )
+
+ # method 2: FAST:
+ #argNames = self.__msgArgs.getArgs()
+ #newKwargs = dict( (key, val) for (key, val) in msgKwargs.iteritems() if key in argNames )
+
+ # method 3: FASTEST:
+ argNames = set(self.getArgs()).intersection(msgKwargs)
+ newKwargs = dict( (k,msgKwargs[k]) for k in argNames )
+
+ return newKwargs
+
+ def hasSameArgs(self, *argNames):
+ """Returns true if self has all the message arguments given, no
+ more and no less. Order does not matter. So if getArgs()
+ returns ('arg1', 'arg2') then self.hasSameArgs('arg2', 'arg1')
+ will return true. """
+ return set(argNames) == set( self.getArgs() )
+
+ def hasParent(self, argsInfo):
+ """return True if self has argsInfo object as parent"""
+ return self.parentAI() is argsInfo
+
+ def getCompleteAI(self):
+ """Get the closest arg spec, starting from self and moving to parent,
+ that is complete. So if self.isComplete() is True, then returns self,
+ otherwise returns parent (if parent.isComplete()), etc. """
+ AI = self
+ while AI is not None:
+ if AI.isComplete():
+ return AI
+ AI = AI.parentAI() # dereference weakref
+ return None
+
+ def updateAllArgsFinal(self, topicDefn):
+ """This can only be called once, if the construction was done
+ with ArgSpecGiven.SPEC_GIVEN_NONE"""
+ assert not self.isComplete()
+ assert topicDefn.isComplete()
+ self.__setAllArgs(topicDefn)
+
+ def __addChildAI(self, childAI):
+ assert childAI not in self.childrenAI
+ self.childrenAI.append(childAI)
+
+ def __notifyParentCompleted(self):
+ """Parent should call this when parent ArgsInfo has been completed"""
+ assert self.parentAI().isComplete()
+ if self.isComplete():
+ # verify that our spec is compatible with parent's
+ self.__validateArgsToParent()
+ return
+
+ def __validateArgsToParent(self):
+ # validate relative to parent arg spec
+ closestParentAI = self.parentAI().getCompleteAI()
+ if closestParentAI is not None:
+ # verify that parent args is a subset of spec given:
+ topicName = stringize(self.topicNameTuple)
+ verifySubset(self.getArgs(), closestParentAI.getArgs(), topicName)
+ verifySubset(self.allRequired, closestParentAI.getReqdArgs(),
+ topicName, ' required args')
+
+ def __setAllArgs(self, specGiven):
+ assert specGiven.isComplete()
+ self.allOptional = tuple( specGiven.getOptional() )
+ self.allRequired = specGiven.reqdArgs
+ self.allDocs = specGiven.argsDocs.copy() # doc for each arg
+ self.argsSpecType= self.SPEC_COMPLETE
+
+ if self.parentAI() is not None:
+ self.__validateArgsToParent()
+
+ # notify our children
+ for childAI in self.childrenAI:
+ childAI.__notifyParentCompleted()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/topicmgrimpl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/topicmgrimpl.py
new file mode 100644
index 0000000..716368b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/kwargs/topicmgrimpl.py
@@ -0,0 +1,13 @@
+"""
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+def getRootTopicSpec():
+ """If using kwargs protocol, then root topic takes no args."""
+ argsDocs = {}
+ reqdArgs = ()
+ return argsDocs, reqdArgs
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/listener.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/listener.py
new file mode 100644
index 0000000..524680d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/listener.py
@@ -0,0 +1,40 @@
+"""
+Top-level functionality related to message listeners.
+"""
+
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from .callables import (
+ getID,
+ getArgs,
+ getRawFunction,
+ ListenerMismatchError,
+ CallArgsInfo
+)
+
+from .listenerimpl import (
+ Listener,
+ ListenerValidator
+)
+
+class IListenerExcHandler:
+ """
+ Interface class base class for any handler given to pub.setListenerExcHandler()
+ Such handler is called whenever a listener raises an exception during a
+ pub.sendMessage(). Example::
+
+ from pubsub import pub
+
+ class MyHandler(pub.IListenerExcHandler):
+ def __call__(self, listenerID, topicObj):
+ ... do something with listenerID ...
+
+ pub.setListenerExcHandler(MyHandler())
+ """
+ def __call__(self, listenerID, topicObj):
+ raise NotImplementedError('%s must override __call__()' % self.__class__)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/listenerbase.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/listenerbase.py
new file mode 100644
index 0000000..424343b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/listenerbase.py
@@ -0,0 +1,185 @@
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from . import weakmethod
+
+from .callables import (
+ getID,
+ getArgs,
+ ListenerMismatchError,
+ CallArgsInfo,
+ AUTO_TOPIC as _AUTO_ARG
+)
+
+
+class ListenerBase:
+ """
+ Base class for listeners, ie. callables subscribed to pubsub.
+ """
+
+ AUTO_TOPIC = _AUTO_ARG
+
+ def __init__(self, callable_, argsInfo, onDead=None):
+ """Use callable_ as a listener of topicName. The argsInfo is the
+ return value from a Validator, ie an instance of callables.CallArgsInfo.
+ If given, the onDead will be called with self as parameter, if/when
+ callable_ gets garbage collected (callable_ is held only by weak
+ reference). """
+ # set call policies
+ self.acceptsAllKwargs = argsInfo.acceptsAllKwargs
+
+ self._autoTopicArgName = argsInfo.autoTopicArgName
+ self._callable = weakmethod.getWeakRef(callable_, self.__notifyOnDead)
+ self.__onDead = onDead
+
+ # save identity now in case callable dies:
+ name, mod = getID(callable_) #
+ self.__nameID = name
+ self.__module = mod
+ self.__id = str(id(callable_))[-4:] # only last four digits of id
+ self.__hash = hash(callable_)
+
+ def __call__(self, args, kwargs, actualTopic, allArgs=None):
+ raise NotImplementedError
+
+ def name(self):
+ """Return a human readable name for listener, based on the
+ listener's type name and its id (as obtained from id(listener)). If
+ caller just needs name based on type info, specify instance=False.
+ Note that the listener's id() was saved at construction time (since
+ it may get garbage collected at any time) so the return value of
+ name() is not necessarily unique if the callable has died (because
+ id's can be re-used after garbage collection)."""
+ return '%s_%s' % (self.__nameID, self.__id)
+
+ def typeName(self):
+ """Get a type name for the listener. This is a class name or
+ function name, as appropriate. """
+ return self.__nameID
+
+ def module(self):
+ """Get the module in which the callable was defined."""
+ return self.__module
+
+ def getCallable(self):
+ """Get the listener that was given at initialization. Note that
+ this could be None if it has been garbage collected (e.g. if it was
+ created as a wrapper of some other callable, and not stored
+ locally)."""
+ return self._callable()
+
+ def isDead(self):
+ """Return True if this listener died (has been garbage collected)"""
+ return self._callable() is None
+
+ def wantsTopicObjOnCall(self):
+ """True if this listener wants topic object: it has a arg=pub.AUTO_TOPIC"""
+ return self._autoTopicArgName is not None
+
+ def wantsAllMessageData(self):
+ """True if this listener wants all message data: it has a \**kwargs argument"""
+ return self.acceptsAllKwargs
+
+ def _unlinkFromTopic_(self):
+ """Tell self that it is no longer used by a Topic. This allows
+ to break some cyclical references."""
+ self.__onDead = None
+
+ def _calledWhenDead(self):
+ raise RuntimeError('BUG: Dead Listener called, still subscribed!')
+
+ def __notifyOnDead(self, ref):
+ """This gets called when listener weak ref has died. Propagate
+ info to Topic)."""
+ notifyDeath = self.__onDead
+ self._unlinkFromTopic_()
+ if notifyDeath is not None:
+ notifyDeath(self)
+
+ def __eq__(self, rhs):
+ """Compare for equality to rhs. This returns true if rhs has our id id(rhs) is
+ same as id(self) or id(callable in self). """
+ if id(self) == id(rhs):
+ return True
+
+ try:
+ c1 = self._callable()
+ c2 = rhs._callable()
+
+ except Exception:
+ # then rhs is not a Listener, compare with c1
+ return c1 == rhs
+
+ # both side of == are Listener, but always compare unequal if both dead
+ if c2 is None and c1 is None:
+ return False
+
+ return c1 == c2
+
+ def __ne__(self, rhs):
+ """Counterpart to __eq__ MUST be defined... equivalent to
+ 'not (self == rhs)'."""
+ return not self.__eq__(rhs)
+
+ def __hash__(self):
+ """Hash is an optimization for dict/set searches, it need not
+ return different numbers for every different object. """
+ return self.__hash
+
+ def __str__(self):
+ """String rep is the callable"""
+ return self.__nameID
+
+
+class ValidatorBase:
+ """
+ Validates listeners. It checks whether the listener given to
+ validate() method complies with required and optional arguments
+ specified for topic.
+ """
+
+ def __init__(self, topicArgs, topicKwargs):
+ """topicArgs is a list of argument names that will be required when sending
+ a message to listener. Hence order of items in topicArgs matters. The topicKwargs
+ is a list of argument names that will be optional, ie given as keyword arguments
+ when sending a message to listener. The list is unordered. """
+ self._topicArgs = set(topicArgs)
+ self._topicKwargs = set(topicKwargs)
+
+
+ def validate(self, listener):
+ """Validate that listener satisfies the requirements of
+ being a topic listener, if topic's kwargs keys are topicKwargKeys
+ (so only the list of keyword arg names for topic are necessary).
+ Raises ListenerMismatchError if listener not usable for topic.
+
+ Otherwise, returns an CallArgsInfo object containing information about
+ the listener's call arguments, such as whether listener wants topic
+ name (signified by a kwarg value = AUTO_TOPIC in listener protocol).
+ E.g. def fn1(msgTopic=Listener.AUTO_TOPIC) would
+ cause validate(fn1) to return True, whereas any other kwarg name or value
+ would cause a False to be returned.
+ """
+ paramsInfo = getArgs( listener )
+ self._validateArgs(listener, paramsInfo)
+ return paramsInfo
+
+
+ def isValid(self, listener):
+ """Return true only if listener can subscribe to messages where
+ topic has kwargs keys topicKwargKeys. Just calls validate() in
+ a try-except clause."""
+ try:
+ self.validate(listener)
+ return True
+ except ListenerMismatchError:
+ return False
+
+
+ def _validateArgs(self, listener, paramsInfo):
+ """Provide implementation in derived classes"""
+ raise NotImplementedError
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/notificationmgr.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/notificationmgr.py
new file mode 100644
index 0000000..83ffab6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/notificationmgr.py
@@ -0,0 +1,185 @@
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+import sys
+
+class NotificationMgr:
+ """
+ Manages notifications for tracing pubsub activity. When pubsub takes a
+ certain action such as sending a message or creating a topic, and
+ the notification flag for that activity is True, all registered
+ notification handlers get corresponding method called with information
+ about the activity, such as which listener subscribed to which topic.
+ See INotificationHandler for which method gets called for each activity.
+
+ If more than one notification handler has been registered, the order in
+ which they are notified is unspecified (do not rely on it).
+
+ Note that this manager automatically unregisters all handlers when
+ the Python interpreter exits, to help avoid NoneType exceptions during
+ shutdown. This "shutdown" starts when the last line of app "main" has
+ executed; the Python interpreter then starts cleaning up, garbage
+ collecting everything, which could lead to various pubsub notifications
+ -- by then they should be of no interest -- such as dead
+ listeners, etc.
+ """
+
+ def __init__(self, notificationHandler = None):
+ self.__notifyOnSend = False
+ self.__notifyOnSubscribe = False
+ self.__notifyOnUnsubscribe = False
+
+ self.__notifyOnNewTopic = False
+ self.__notifyOnDelTopic = False
+ self.__notifyOnDeadListener = False
+
+ self.__handlers = []
+ if notificationHandler is not None:
+ self.addHandler(notificationHandler)
+
+ self.__atExitRegistered = False
+
+ def addHandler(self, handler):
+ if not self.__atExitRegistered:
+ self.__registerForAppExit()
+ self.__handlers.append(handler)
+
+ def getHandlers(self):
+ return self.__handlers[:]
+
+ def clearHandlers(self):
+ self.__handlers = []
+
+ def notifySubscribe(self, *args, **kwargs):
+ if self.__notifyOnSubscribe and self.__handlers:
+ for handler in self.__handlers:
+ handler.notifySubscribe(*args, **kwargs)
+
+ def notifyUnsubscribe(self, *args, **kwargs):
+ if self.__notifyOnUnsubscribe and self.__handlers:
+ for handler in self.__handlers:
+ handler.notifyUnsubscribe(*args, **kwargs)
+
+ def notifySend(self, *args, **kwargs):
+ if self.__notifyOnSend and self.__handlers:
+ for handler in self.__handlers:
+ handler.notifySend(*args, **kwargs)
+
+ def notifyNewTopic(self, *args, **kwargs):
+ if self.__notifyOnNewTopic and self.__handlers:
+ for handler in self.__handlers:
+ handler.notifyNewTopic(*args, **kwargs)
+
+ def notifyDelTopic(self, *args, **kwargs):
+ if self.__notifyOnDelTopic and self.__handlers:
+ for handler in self.__handlers:
+ handler.notifyDelTopic(*args, **kwargs)
+
+ def notifyDeadListener(self, *args, **kwargs):
+ if self.__notifyOnDeadListener and self.__handlers:
+ for handler in self.__handlers:
+ handler.notifyDeadListener(*args, **kwargs)
+
+ def getFlagStates(self):
+ """Return state of each notification flag, as a dict."""
+ return dict(
+ subscribe = self.__notifyOnSubscribe,
+ unsubscribe = self.__notifyOnUnsubscribe,
+ deadListener = self.__notifyOnDeadListener,
+ sendMessage = self.__notifyOnSend,
+ newTopic = self.__notifyOnNewTopic,
+ delTopic = self.__notifyOnDelTopic,
+ )
+
+ def setFlagStates(self, subscribe=None, unsubscribe=None,
+ deadListener=None, sendMessage=None, newTopic=None,
+ delTopic=None, all=None):
+ """Set the notification flag on/off for various aspects of pubsub.
+ The kwargs that are None are left at their current value. The 'all',
+ if not None, is set first. E.g.
+
+ mgr.setFlagStates(all=True, delTopic=False)
+
+ will toggle all notifications on, but will turn off the 'delTopic'
+ notification.
+ """
+ if all is not None:
+ # ignore all other arg settings, and set all of them to true:
+ numArgs = 7 # how many args in this method
+ self.setFlagStates( all=None, * ((numArgs-1)*[all]) )
+
+ if sendMessage is not None:
+ self.__notifyOnSend = sendMessage
+ if subscribe is not None:
+ self.__notifyOnSubscribe = subscribe
+ if unsubscribe is not None:
+ self.__notifyOnUnsubscribe = unsubscribe
+
+ if newTopic is not None:
+ self.__notifyOnNewTopic = newTopic
+ if delTopic is not None:
+ self.__notifyOnDelTopic = delTopic
+ if deadListener is not None:
+ self.__notifyOnDeadListener = deadListener
+
+
+ def __registerForAppExit(self):
+ import atexit
+ atexit.register(self.clearHandlers)
+ self.__atExitRegistered = True
+
+
+
+class INotificationHandler:
+ """
+ Defines the interface expected by pubsub for pubsub activity
+ notifications. Any instance that supports the same methods, or
+ derives from this class, will work as a notification handler
+ for pubsub events (see pub.addNotificationHandler).
+ """
+
+ def notifySubscribe(self, pubListener, topicObj, newSub):
+ """Called when a listener is subscribed to a topic.
+ :param pubListener: the pubsub.core.Listener that wraps subscribed listener.
+ :param topicObj: the pubsub.core.Topic object subscribed to.
+ :param newSub: false if pubListener was already subscribed. """
+ raise NotImplementedError
+
+ def notifyUnsubscribe(self, pubListener, topicObj):
+ """Called when a listener is unsubscribed from given topic.
+ :param pubListener: the pubsub.core.Listener that wraps unsubscribed listener.
+ :param topicObj: the pubsub.core.Topic object unsubscribed from."""
+ raise NotImplementedError
+
+ def notifyDeadListener(self, pubListener, topicObj):
+ """Called when a listener has been garbage collected.
+ :param pubListener: the pubsub.core.Listener that wraps GC'd listener.
+ :param topicObj: the pubsub.core.Topic object it was subscribed to."""
+ raise NotImplementedError
+
+ def notifySend(self, stage, topicObj, pubListener=None):
+ """Called multiple times during a sendMessage: once before message
+ sending has started (pre), once for each listener about to be sent the
+ message, and once after all listeners have received the message (post).
+ :param stage: 'pre', 'post', or 'loop'.
+ :param topicObj: the Topic object for the message.
+ :param pubListener: None for pre and post stages; for loop, the listener
+ that is about to be sent the message."""
+ raise NotImplementedError
+
+ def notifyNewTopic(self, topicObj, description, required, argsDocs):
+ """Called whenever a new topic is added to the topic tree.
+ :param topicObj: the Topic object for the message.
+ :param description: docstring for the topic.
+ :param required: list of message data names (keys in argsDocs) that are required.
+ :param argsDocs: dictionary of all message data names, with the
+ corresponding docstring. """
+ raise NotImplementedError
+
+ def notifyDelTopic(self, topicName):
+ """Called whenever a topic is removed from topic tree.
+ :param topicName: name of topic removed."""
+ raise NotImplementedError
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/publisherbase.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/publisherbase.py
new file mode 100644
index 0000000..bfde2d5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/publisherbase.py
@@ -0,0 +1,191 @@
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from .topicmgr import (
+ TopicManager,
+ TreeConfig
+)
+
+from .. import py2and3
+
+
+class PublisherBase:
+ """
+ Represent the class that send messages to listeners of given
+ topics and that knows how to subscribe/unsubscribe listeners
+ from topics.
+ """
+
+ def __init__(self, treeConfig = None):
+ """If treeConfig is None, a default one is created from an
+ instance of TreeConfig."""
+ self.__treeConfig = treeConfig or TreeConfig()
+ self.__topicMgr = TopicManager(self.__treeConfig)
+
+ def getTopicMgr(self):
+ """Get the topic manager created for this publisher."""
+ return self.__topicMgr
+
+ def getListenerExcHandler(self):
+ """Get the listener exception handler that was registered
+ via setListenerExcHandler(), or None of none registered."""
+ return self.__treeConfig.listenerExcHandler
+
+ def setListenerExcHandler(self, handler):
+ """Set the function to call when a listener raises an exception
+ during a sendMessage(). The handler must adhere to the
+ IListenerExcHandler API. """
+ self.__treeConfig.listenerExcHandler = handler
+
+ def addNotificationHandler(self, handler):
+ """Add a handler for tracing pubsub activity. The handler should be
+ a class that adheres to the API of INotificationHandler. """
+ self.__treeConfig.notificationMgr.addHandler(handler)
+
+ def clearNotificationHandlers(self):
+ """Remove all notification handlers that were added via
+ self.addNotificationHandler(). """
+ self.__treeConfig.notificationMgr.clearHandlers()
+
+ def setNotificationFlags(self, **kwargs):
+ """Set the notification flags on or off for each type of
+ pubsub activity. The kwargs keys can be any of the following:
+
+ - subscribe: if True, get notified whenever a listener subscribes to a topic;
+ - unsubscribe: if True, get notified whenever a listener unsubscribes from a topic;
+ - deadListener: if True, get notified whenever a subscribed listener has been garbage-collected;
+ - sendMessage: if True, get notified whenever sendMessage() is called;
+ - newTopic: if True, get notified whenever a new topic is created;
+ - delTopic: if True, get notified whenever a topic is "deleted" from topic tree;
+ - all: set all of the above to the given value (True or False).
+
+ The kwargs that are None are left at their current value. Those that are
+ False will cause corresponding notification to be silenced. The 'all'
+ is set first, then the others. E.g.
+
+ mgr.setFlagStates(all=True, delTopic=False)
+
+ will toggle all notifications on, but will turn off the 'delTopic'
+ notification.
+ """
+ self.__treeConfig.notificationMgr.setFlagStates(**kwargs)
+
+ def getNotificationFlags(self):
+ """Return a dictionary with the notification flag states."""
+ return self.__treeConfig.notificationMgr.getFlagStates()
+
+ def setTopicUnspecifiedFatal(self, newVal=True, checkExisting=True):
+ """Changes the creation policy for topics.
+
+ By default, pubsub will accept topic names for topics that
+ don't have a message data specification (MDS). This default behavior
+ makes pubsub easier to use initially, but allows topic
+ names with typos to go uncaught in common operations such as
+ sendMessage() and subscribe(). In a large application, this
+ can lead to nasty bugs. Pubsub's default behavior is equivalent
+ to setTopicUnspecifiedFatal(false).
+
+ When called with newVal=True, any future pubsub operation that
+ requires a topic (such as subscribe and sendMessage) will require
+ an MDS; if none is available, pubsub will raise a TopicDefnError
+ exception.
+
+ If checkExisting is not given or True, all existing
+ topics are validated. A TopicDefnError exception is
+ raised if one is found to be incomplete (has hasMDS() false).
+
+ Returns previous value of newVal.
+
+ Note that this method can be used in several ways:
+
+ 1. Only use it in your application when something is not working
+ as expected: just add a call at the beginning of your app when
+ you have a problem with topic messages not being received
+ (for instance), and remove it when you have fixed the problem.
+
+ 2. Use it from the beginning of your app and never use newVal=False:
+ add a call at the beginning of your app and you leave it in
+ (forever), and use Topic Definition Providers to provide the
+ listener specifications. These are easy to use via the
+ pub.addTopicDefnProvider().
+
+ 3. Use it as in #1 during app development, and once stable, use
+ #2. This is easiest to do in combination with
+ pub.exportTopicTreeSpec().
+ """
+ oldVal = self.__treeConfig.raiseOnTopicUnspecified
+ self.__treeConfig.raiseOnTopicUnspecified = newVal
+
+ if newVal and checkExisting:
+ self.__topicMgr.checkAllTopicsHaveMDS()
+
+ return oldVal
+
+ def sendMessage(self, topicName, *args, **kwargs):
+ """Send a message for topic name with given data (args and kwargs).
+ This will be overridden by derived classes that implement
+ message-sending for different messaging protocols; not all
+ parameters may be accepted."""
+ raise NotImplementedError
+
+ def subscribe(self, listener, topicName):
+ """Subscribe listener to named topic. Raises ListenerMismatchError
+ if listener isn't compatible with the topic's MDS. Returns
+ (pubsub.core.Listener, success), where success is False if listener
+ was already subscribed. The pub.core.Listener wraps the callable
+ subscribed and provides introspection-based info about
+ the callable.
+
+ Note that if 'subscribe' notification is on, the handler's
+ 'notifySubscribe' method is called after subscription."""
+ topicObj = self.__topicMgr.getOrCreateTopic(topicName)
+ subscribedListener, success = topicObj.subscribe(listener)
+ return subscribedListener, success
+
+ def unsubscribe(self, listener, topicName):
+ """Unsubscribe from given topic. Returns the pubsub.core.Listener
+ instance that was used to wrap listener at subscription
+ time. Raises an TopicNameError if topicName doesn't exist.
+
+ Note that if 'unsubscribe' notification is on, the handler's
+ notifyUnsubscribe() method will be called after unsubscribing. """
+ topicObj = self.__topicMgr.getTopic(topicName)
+ unsubdLisnr = topicObj.unsubscribe(listener)
+
+ return unsubdLisnr
+
+ def unsubAll(self, topicName = None,
+ listenerFilter = None, topicFilter = None):
+ """By default (no args given), unsubscribe all listeners from all
+ topics. A listenerFilter can be given so that only the listeners
+ that satisfy listenerFilter(listener) == True will be unsubscribed
+ (with listener being a pub.Listener wrapper instance for each listener
+ subscribed). A topicFilter can also be given so that only topics
+ that satisfy topicFilter(topic name) == True will be affected.
+ If only one topic should have listeners unsubscribed, then a topic
+ name 'topicName' can be given *instead* instead of a topic filter.
+
+ Returns the list of all listeners (instances of pub.Listener) that
+ were unsubscribed from the topic tree).
+
+ Note: this method will generate one 'unsubcribe' notification message
+ (see pub.setNotificationFlags()) for each listener unsubscribed."""
+ unsubdListeners = []
+
+ if topicName is None:
+ # unsubscribe all listeners from all topics
+ topicsMap = self.__topicMgr._topicsMap
+ for topicName, topicObj in py2and3.iteritems(topicsMap):
+ if topicFilter is None or topicFilter(topicName):
+ tmp = topicObj.unsubscribeAllListeners(listenerFilter)
+ unsubdListeners.extend(tmp)
+
+ else:
+ topicObj = self.__topicMgr.getTopic(topicName)
+ unsubdListeners = topicObj.unsubscribeAllListeners(listenerFilter)
+
+ return unsubdListeners
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicargspec.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicargspec.py
new file mode 100644
index 0000000..ecbd82e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicargspec.py
@@ -0,0 +1,77 @@
+"""
+Definitions related to message data specification.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+
+from .listener import getArgs as getListenerArgs
+from .validatedefnargs import MessageDataSpecError
+from .topicargspecimpl import (
+ SenderMissingReqdMsgDataError,
+ SenderUnknownMsgDataError,
+ ArgsInfo
+)
+
+
+def topicArgsFromCallable(_callable):
+ """Get the topic message data names and list of those that are required,
+ by introspecting given callable. Returns a pair, (args, required)
+ where args is a dictionary of allowed message data names vs docstring,
+ and required states which ones are required rather than optional."""
+ argsInfo = getListenerArgs(_callable)
+ required = argsInfo.getRequiredArgs()
+ defaultDoc = 'UNDOCUMENTED'
+ args = dict.fromkeys(argsInfo.allParams, defaultDoc)
+ return args, required
+
+
+class ArgSpecGiven:
+ """
+ The message data specification (MDS) for a topic.
+ This consists of each argument name that listener should have in its
+ call protocol, plus which ones are required in any sendMessage(), and a
+ documentation string for each argument. This instance will be transformed
+ into an ArgsInfo object which is basically a superset of that information,
+ needed to ensure that the arguments specifications satisfy
+ pubsub policies for chosen API version.
+ """
+
+ SPEC_GIVEN_NONE = 1 # specification not given
+ SPEC_GIVEN_ALL = 3 # all args specified
+
+ def __init__(self, argsDocs=None, reqdArgs=None):
+ self.reqdArgs = tuple(reqdArgs or ())
+
+ if argsDocs is None:
+ self.argsSpecType = ArgSpecGiven.SPEC_GIVEN_NONE
+ self.argsDocs = {}
+ else:
+ self.argsSpecType = ArgSpecGiven.SPEC_GIVEN_ALL
+ self.argsDocs = argsDocs
+
+ # check that all args marked as required are in argsDocs
+ missingArgs = set(self.reqdArgs).difference(self.argsDocs.keys()) # py3: iter keys ok
+ if missingArgs:
+ msg = 'Params [%s] missing inherited required args [%%s]' % ','.join(argsDocs.keys()) # iter keys ok
+ raise MessageDataSpecError(msg, missingArgs)
+
+ def setAll(self, allArgsDocs, reqdArgs = None):
+ self.argsDocs = allArgsDocs
+ self.reqdArgs = reqdArgs or ()
+ self.argsSpecType = ArgSpecGiven.SPEC_GIVEN_ALL
+
+ def isComplete(self):
+ """Returns True if the definition is usable, false otherwise."""
+ return self.argsSpecType == ArgSpecGiven.SPEC_GIVEN_ALL
+
+ def getOptional(self):
+ return tuple( set( self.argsDocs.keys() ).difference( self.reqdArgs ) )
+
+ def __str__(self):
+ return "%s, %s, %s" % \
+ (self.argsDocs, self.reqdArgs, self.argsSpecType)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicdefnprovider.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicdefnprovider.py
new file mode 100644
index 0000000..6ba9665
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicdefnprovider.py
@@ -0,0 +1,636 @@
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+
+import os, re, inspect
+from textwrap import TextWrapper, dedent
+
+from .. import (
+ policies,
+ py2and3
+)
+from .topicargspec import (
+ topicArgsFromCallable,
+ ArgSpecGiven
+)
+from .topictreetraverser import TopicTreeTraverser
+from .topicexc import UnrecognizedSourceFormatError
+
+
+class ITopicDefnProvider:
+ """
+ All topic definition providers added via pub.addTopicDefnProvider()
+ must have this interface. Derived classes must override the getDefn(),
+ getTreeDoc() and topicNames() methods.
+ """
+
+ def getDefn(self, topicNameTuple):
+ """Must return a pair (string, ArgSpecGiven) for given topic.
+ The first item is a description for topic, the second item
+ contains the message data specification (MDS). Note topic name
+ is in tuple format ('a', 'b', 'c') rather than 'a.b.c'. """
+ msg = 'Must return (string, ArgSpecGiven), or (None, None)'
+ raise NotImplementedError(msg)
+
+ def topicNames(self):
+ """Return an iterator over topic names available from this provider.
+ Note that the topic names should be in tuple rather than dotted-string
+ format so as to be compatible with getDefn()."""
+ msg = 'Must return a list of topic names available from this provider'
+ raise NotImplementedError(msg)
+
+ def getTreeDoc(self):
+ """Get the docstring for the topic tree."""
+ msg = 'Must return documentation string for root topic (tree)'
+ raise NotImplementedError(msg)
+
+ def __iter__(self):
+ """Same as self.topicNames(), do NOT override."""
+ return self.topicNames()
+
+
+# name of method in class name assumed to represent topic's listener signature
+# which will get checked against topic's Message Data Specification (MDS)
+SPEC_METHOD_NAME = 'msgDataSpec'
+
+
+class ITopicDefnDeserializer:
+ """
+ Interface class for all topic definition de-serializers that can be
+ accepted by TopicDefnProvider. A deserializer
+ creates a topic tree from something such as file, module, or string.
+ """
+
+ class TopicDefn:
+ """Encapsulate date for a topic definition. Used by
+ getNextTopic()."""
+
+ def __init__(self, nameTuple, description, argsDocs, required):
+ self.nameTuple = nameTuple
+ self.description = description
+ self.argsDocs = argsDocs
+ self.required = required
+
+ def isComplete(self):
+ return (self.description is not None) and (self.argsDocs is not None)
+
+ def getTreeDoc(self):
+ """Get the docstring for the topic tree."""
+ raise NotImplementedError
+
+ def getNextTopic(self):
+ """Get the next topic definition available from the data. The return
+ must be an instance of TopicDefn. Must return None when no topics
+ are left."""
+ raise NotImplementedError
+
+ def doneIter(self):
+ """Called automatically by TopicDefnProvider once
+ it considers the iteration completed. Override this only if
+ deserializer needs to take action, such as closing a file."""
+ pass
+
+ def resetIter(self):
+ """Called by the TopicDefnProvider if it needs to
+ restart the topic iteration. Override this only if special action needed,
+ such as resetting a file pointer to beginning of file."""
+ pass
+
+
+class TopicDefnDeserialClass(ITopicDefnDeserializer):
+ """
+ Convert a nested class tree as a topic definition tree. Format: the class
+ name is the topic name, its doc string is its description. The topic's
+ message data specification is determined by inspecting a class method called
+ the same as SPEC_METHOD_NAME. The doc string of that method is parsed to
+ extract the description for each message data.
+ """
+
+ def __init__(self, pyClassObj=None):
+ """If pyClassObj is given, it is an object that contains nested
+ classes defining root topics; the root topics contain nested
+ classes defining subtopics; etc."""
+ self.__rootTopics = []
+ self.__iterStarted = False
+ self.__nextTopic = iter(self.__rootTopics)
+ self.__rootDoc = None
+
+ if pyClassObj is not None:
+ self.__rootDoc = pyClassObj.__doc__
+ topicClasses = self.__getTopicClasses(pyClassObj)
+ for topicName, pyClassObj in topicClasses:
+ self.__addDefnFromClassObj(pyClassObj)
+
+ def getTreeDoc(self):
+ return self.__rootDoc
+
+ def getNextTopic(self):
+ self.__iterStarted = True
+ try:
+ topicNameTuple, topicClassObj = py2and3.nextiter(self.__nextTopic)
+ except StopIteration:
+ return None
+
+ # ok get the info from class
+ if hasattr(topicClassObj, SPEC_METHOD_NAME):
+ protoListener = getattr(topicClassObj, SPEC_METHOD_NAME)
+ argsDocs, required = topicArgsFromCallable(protoListener)
+ if protoListener.__doc__:
+ self.__setArgsDocsFromProtoDocs(argsDocs, protoListener.__doc__)
+ else:
+ # assume definition is implicitly that listener has no args
+ argsDocs = {}
+ required = ()
+ desc = None
+ if topicClassObj.__doc__:
+ desc = dedent(topicClassObj.__doc__)
+ return self.TopicDefn(topicNameTuple, desc, argsDocs, required)
+
+ def resetIter(self):
+ self.__iterStarted = False
+ self.__nextTopic = iter(self.__rootTopics)
+
+ def getDefinedTopics(self):
+ return [nt for (nt, defn) in self.__rootTopics]
+
+ def __addDefnFromClassObj(self, pyClassObj):
+ """Extract a topic definition from a Python class: topic name,
+ docstring, and MDS, and docstring for each message data.
+ The class name is the topic name, assumed to be a root topic, and
+ descends recursively into nested classes to define subtopic etc. """
+ if self.__iterStarted:
+ raise RuntimeError('addDefnFromClassObj must be called before iteration started!')
+
+ parentNameTuple = (pyClassObj.__name__, )
+ if pyClassObj.__doc__ is not None:
+ self.__rootTopics.append( (parentNameTuple, pyClassObj) )
+ if self.__rootDoc is None:
+ self.__rootDoc = pyClassObj.__doc__
+ self.__findTopics(pyClassObj, parentNameTuple)
+ # iterator is now out of sync, so reset it; obviously this would
+ # screw up getNextTopic which is why we had to test for self.__iterStarted
+ self.__nextTopic = iter(self.__rootTopics)
+
+ def __findTopics(self, pyClassObj, parentNameTuple):
+ assert not self.__iterStarted
+ assert parentNameTuple
+ assert pyClassObj.__name__ == parentNameTuple[-1]
+
+ topicClasses = self.__getTopicClasses(pyClassObj, parentNameTuple)
+ pyClassObj._topicNameStr = '.'.join(parentNameTuple)
+
+ # make sure to update rootTopics BEFORE we recurse, so that toplevel
+ # topics come first in the list
+ for parentNameTuple2, topicClassObj in topicClasses:
+ # we only keep track of topics that are documented, so that
+ # multiple providers can co-exist without having to duplicate
+ # information
+ if topicClassObj.__doc__ is not None:
+ self.__rootTopics.append( (parentNameTuple2, topicClassObj) )
+ # now can find its subtopics
+ self.__findTopics(topicClassObj, parentNameTuple2)
+
+ def __getTopicClasses(self, pyClassObj, parentNameTuple=()):
+ """Returns a list of pairs, (topicNameTuple, memberClassObj)"""
+ memberNames = dir(pyClassObj)
+ topicClasses = []
+ for memberName in memberNames:
+ if memberName.startswith('_'):
+ continue # ignore special and non-public methods
+ member = getattr(pyClassObj, memberName)
+ if inspect.isclass( member ):
+ topicNameTuple = parentNameTuple + (memberName,)
+ topicClasses.append( (topicNameTuple, member) )
+ return topicClasses
+
+ def __setArgsDocsFromProtoDocs(self, argsDocs, protoDocs):
+ PAT_ITEM_STR = r'\A-\s*' # hyphen and any number of blanks
+ PAT_ARG_NAME = r'(?P<argName>\w*)'
+ PAT_DOC_STR = r'(?P<doc1>.*)'
+ PAT_BLANK = r'\s*'
+ PAT_ITEM_SEP = r':'
+ argNamePat = re.compile(
+ PAT_ITEM_STR + PAT_ARG_NAME + PAT_BLANK + PAT_ITEM_SEP
+ + PAT_BLANK + PAT_DOC_STR)
+ protoDocs = dedent(protoDocs)
+ lines = protoDocs.splitlines()
+ argName = None
+ namesFound = []
+ for line in lines:
+ match = argNamePat.match(line)
+ if match:
+ argName = match.group('argName')
+ namesFound.append(argName)
+ argsDocs[argName] = [match.group('doc1') ]
+ elif argName:
+ argsDocs[argName].append(line)
+
+ for name in namesFound:
+ argsDocs[name] = '\n'.join( argsDocs[name] )
+
+
+class TopicDefnDeserialModule(ITopicDefnDeserializer):
+ """
+ Deserialize a module containing Python source code defining a topic tree.
+ This loads the module and gives it to an instance of TopicDefnDeserialClass.
+ """
+
+ def __init__(self, moduleName, searchPath=None):
+ """Load the given named module, searched for in searchPath or, if not
+ specified, in sys.path. Give it to a TopicDefnDeserialClass."""
+ from . import imp2
+ module = imp2.load_module(moduleName, searchPath)
+ self.__classDeserial = TopicDefnDeserialClass(module)
+
+ def getTreeDoc(self):
+ return self.__classDeserial.getTreeDoc()
+
+ def getNextTopic(self):
+ return self.__classDeserial.getNextTopic()
+
+ def doneIter(self):
+ self.__classDeserial.doneIter()
+
+ def resetIter(self):
+ self.__classDeserial.resetIter()
+
+ def getDefinedTopics(self):
+ return self.__classDeserial.getDefinedTopics()
+
+
+class TopicDefnDeserialString(ITopicDefnDeserializer):
+ """
+ Deserialize a string containing Python source code defining a topic tree.
+ The string has the same format as expected by TopicDefnDeserialModule.
+ """
+
+ def __init__(self, source):
+ """This just saves the string into a temporary file created in
+ os.getcwd(), and the rest is delegated to TopicDefnDeserialModule.
+ The temporary file (module -- as well as its byte-compiled
+ version) will be deleted when the doneIter() method is called."""
+
+ def createTmpModule():
+ moduleNamePre = 'tmp_export_topics_'
+ import os, tempfile
+ creationDir = os.getcwd()
+ fileID, path = tempfile.mkstemp('.py', moduleNamePre, dir=creationDir)
+ stringFile = os.fdopen(fileID, 'w')
+ stringFile.write( dedent(source) )
+ stringFile.close()
+ return path, [creationDir]
+
+ self.__filename, searchPath = createTmpModule()
+ moduleName = os.path.splitext( os.path.basename(self.__filename) )[0]
+ self.__modDeserial = TopicDefnDeserialModule(moduleName, searchPath)
+
+ def getTreeDoc(self):
+ return self.__modDeserial.getTreeDoc()
+
+ def getNextTopic(self):
+ return self.__modDeserial.getNextTopic()
+
+ def doneIter(self):
+ self.__modDeserial.doneIter()
+ # remove the temporary module and its compiled version (*.pyc)
+ os.remove(self.__filename)
+ try: # py3.2+ uses special folder/filename for .pyc files
+ from imp import cache_from_source
+ os.remove(cache_from_source(self.__filename))
+ except ImportError:
+ os.remove(self.__filename + 'c')
+
+ def resetIter(self):
+ self.__modDeserial.resetIter()
+
+ def getDefinedTopics(self):
+ return self.__modDeserial.getDefinedTopics()
+
+
+TOPIC_TREE_FROM_MODULE = 'module'
+TOPIC_TREE_FROM_STRING = 'string'
+TOPIC_TREE_FROM_CLASS = 'class'
+
+
+class TopicDefnProvider(ITopicDefnProvider):
+ """
+ Default implementation of the ITopicDefnProvider API. This
+ implementation accepts several formats for the topic tree
+ source data and delegates to a registered ITopicDefnDeserializer
+ that converts source data into topic definitions.
+
+ This provider is instantiated automatically by
+ ``pub.addTopicDefnProvider(source, format)``
+ when source is *not* an ITopicDefnProvider.
+
+ Additional de-serializers can be registered via registerTypeForImport().
+ """
+
+ _typeRegistry = {}
+
+ def __init__(self, source, format, **providerKwargs):
+ """Find the correct de-serializer class from registry for the given
+ format; instantiate it with given source and providerKwargs; get
+ all available topic definitions."""
+ if format not in self._typeRegistry:
+ raise UnrecognizedSourceFormatError()
+ providerClassObj = self._typeRegistry[format]
+ provider = providerClassObj(source, **providerKwargs)
+ self.__topicDefns = {}
+ self.__treeDocs = provider.getTreeDoc()
+ try:
+ topicDefn = provider.getNextTopic()
+ while topicDefn is not None:
+ self.__topicDefns[topicDefn.nameTuple] = topicDefn
+ topicDefn = provider.getNextTopic()
+ finally:
+ provider.doneIter()
+
+ def getDefn(self, topicNameTuple):
+ desc, spec = None, None
+ defn = self.__topicDefns.get(topicNameTuple, None)
+ if defn is not None:
+ assert defn.isComplete()
+ desc = defn.description
+ spec = ArgSpecGiven(defn.argsDocs, defn.required)
+ return desc, spec
+
+ def topicNames(self):
+ return py2and3.iterkeys(self.__topicDefns)
+
+ def getTreeDoc(self):
+ return self.__treeDocs
+
+ @classmethod
+ def registerTypeForImport(cls, typeName, providerClassObj):
+ """If a new type of importer is defined for topic definitions, it
+ can be registered with pubsub by providing a name for the new
+ importer (typeName), and the class to instantiate when
+ pub.addTopicDefnProvider(obj, typeName) is called. For instance, ::
+
+ from pubsub.core.topicdefnprovider import ITopicDefnDeserializer
+ class SomeNewImporter(ITopicDefnDeserializer):
+ ...
+ TopicDefnProvider.registerTypeForImport('some name', SomeNewImporter)
+ # will instantiate SomeNewImporter(source)
+ pub.addTopicDefnProvider(source, 'some name')
+ """
+ assert issubclass(providerClassObj, ITopicDefnDeserializer)
+ cls._typeRegistry[typeName] = providerClassObj
+
+ @classmethod
+ def initTypeRegistry(cls):
+ cls.registerTypeForImport(TOPIC_TREE_FROM_MODULE, TopicDefnDeserialModule)
+ cls.registerTypeForImport(TOPIC_TREE_FROM_STRING, TopicDefnDeserialString)
+ cls.registerTypeForImport(TOPIC_TREE_FROM_CLASS, TopicDefnDeserialClass)
+
+
+TopicDefnProvider.initTypeRegistry()
+
+
+def _backupIfExists(filename, bak):
+ import os, shutil
+ if os.path.exists(filename):
+ backupName = '%s.%s' % (filename, bak)
+ shutil.copy(filename, backupName)
+
+
+defaultTopicTreeSpecHeader = \
+"""
+Topic tree for application.
+Used via pub.addTopicDefnProvider(thisModuleName).
+"""
+
+defaultTopicTreeSpecFooter = \
+"""\
+# End of topic tree definition. Note that application may load
+# more than one definitions provider.
+"""
+
+
+def exportTopicTreeSpec(moduleName = None, rootTopic=None, bak='bak', moduleDoc=None):
+ """Using TopicTreeSpecPrinter, exports the topic tree rooted at rootTopic to a
+ Python module (.py) file. This module will define module-level classes
+ representing root topics, nested classes for subtopics etc. Returns a string
+ representing the contents of the file. Parameters:
+
+ - If moduleName is given, the topic tree is written to moduleName.py in
+ os.getcwd(). By default, it is first backed up, it it already exists,
+ using bak as the filename extension. If bak is None, existing module file
+ gets overwritten.
+ - If rootTopic is specified, the export only traverses tree from
+ corresponding topic. Otherwise, complete tree, using
+ pub.getDefaultTopicTreeRoot() as starting point.
+ - The moduleDoc is the doc string for the module ie topic tree.
+ """
+
+ if rootTopic is None:
+ from .. import pub
+ rootTopic = pub.getDefaultTopicMgr().getRootAllTopics()
+ elif py2and3.isstring(rootTopic):
+ from .. import pub
+ rootTopic = pub.getDefaultTopicMgr().getTopic(rootTopic)
+
+ # create exporter
+ if moduleName is None:
+ capture = py2and3.StringIO()
+ TopicTreeSpecPrinter(rootTopic, fileObj=capture, treeDoc=moduleDoc)
+ return capture.getvalue()
+
+ else:
+ filename = '%s.py' % moduleName
+ if bak:
+ _backupIfExists(filename, bak)
+ moduleFile = open(filename, 'w')
+ try:
+ TopicTreeSpecPrinter(rootTopic, fileObj=moduleFile, treeDoc=moduleDoc)
+ finally:
+ moduleFile.close()
+
+##############################################################
+
+class TopicTreeSpecPrinter:
+ """
+ Helper class to print the topic tree using the Python class
+ syntax. The "printout" can be sent to any file object (object that has a
+ write() method). If printed to a module, the module can be imported and
+ given to pub.addTopicDefnProvider(module, 'module'). Importing the module
+ also provides code completion of topic names (rootTopic.subTopic can be
+ given to any pubsub function requiring a topic name).
+ """
+
+ INDENT_CH = ' '
+ #INDENT_CH = '.'
+
+ def __init__(self, rootTopic=None, fileObj=None, width=70, indentStep=4,
+ treeDoc = defaultTopicTreeSpecHeader, footer = defaultTopicTreeSpecFooter):
+ """For formatting, can specify the width of output, the indent step, the
+ header and footer to print to override defaults. The destination is fileObj;
+ if none is given, then sys.stdout is used. If rootTopic is given, calls
+ writeAll(rootTopic) at end of __init__."""
+ self.__traverser = TopicTreeTraverser(self)
+
+ import sys
+ fileObj = fileObj or sys.stdout
+
+ self.__destination = fileObj
+ self.__output = []
+ self.__header = self.__toDocString(treeDoc)
+ self.__footer = footer
+ self.__lastWasAll = False # True when last topic done was the ALL_TOPICS
+
+ self.__width = width
+ self.__wrapper = TextWrapper(width)
+ self.__indentStep = indentStep
+ self.__indent = 0
+
+ args = dict(width=width, indentStep=indentStep, treeDoc=treeDoc,
+ footer=footer, fileObj=fileObj)
+ def fmItem(argName, argVal):
+ if py2and3.isstring(argVal):
+ MIN_OFFSET = 5
+ lenAV = width - MIN_OFFSET - len(argName)
+ if lenAV > 0:
+ argVal = repr(argVal[:lenAV] + '...')
+ elif argName == 'fileObj':
+ argVal = fileObj.__class__.__name__
+ return '# - %s: %s' % (argName, argVal)
+ fmtArgs = [fmItem(key, args[key]) for key in sorted(py2and3.iterkeys(args))]
+ self.__comment = [
+ '# Automatically generated by %s(**kwargs).' % self.__class__.__name__,
+ '# The kwargs were:',
+ ]
+ self.__comment.extend(fmtArgs)
+ self.__comment.extend(['']) # two empty line after comment
+
+ if rootTopic is not None:
+ self.writeAll(rootTopic)
+
+ def getOutput(self):
+ """Each line that was sent to fileObj was saved in a list; returns a
+ string which is ``'\\n'.join(list)``."""
+ return '\n'.join( self.__output )
+
+ def writeAll(self, topicObj):
+ """Traverse each topic of topic tree, starting at topicObj, printing
+ each topic definition as the tree gets traversed. """
+ self.__traverser.traverse(topicObj)
+
+ def _accept(self, topicObj):
+ # accept every topic
+ return True
+
+ def _startTraversal(self):
+ # output comment
+ self.__wrapper.initial_indent = '# '
+ self.__wrapper.subsequent_indent = self.__wrapper.initial_indent
+ self.__output.extend( self.__comment )
+
+ # output header:
+ if self.__header:
+ self.__output.extend([''])
+ self.__output.append(self.__header)
+ self.__output.extend([''])
+
+ def _doneTraversal(self):
+ if self.__footer:
+ self.__output.append('')
+ self.__output.append('')
+ self.__output.append(self.__footer)
+
+ if self.__destination is not None:
+ self.__destination.write(self.getOutput())
+
+ def _onTopic(self, topicObj):
+ """This gets called for each topic. Print as per specified content."""
+ # don't print root of tree, it is the ALL_TOPICS builtin topic
+ if topicObj.isAll():
+ self.__lastWasAll = True
+ return
+ self.__lastWasAll = False
+
+ self.__output.append( '' ) # empty line
+ # topic name
+ self.__wrapper.width = self.__width
+ head = 'class %s:' % topicObj.getNodeName()
+ self.__formatItem(head)
+
+ # each extra content (assume constructor verified that chars are valid)
+ self.__printTopicDescription(topicObj)
+ if policies.msgDataProtocol != 'arg1':
+ self.__printTopicArgSpec(topicObj)
+
+ def _startChildren(self):
+ """Increase the indent"""
+ if not self.__lastWasAll:
+ self.__indent += self.__indentStep
+
+ def _endChildren(self):
+ """Decrease the indent"""
+ if not self.__lastWasAll:
+ self.__indent -= self.__indentStep
+
+ def __toDocString(self, msg):
+ if not msg:
+ return msg
+ if msg.startswith("'''") or msg.startswith('"""'):
+ return msg
+ return '"""\n%s\n"""' % msg.strip()
+
+ def __printTopicDescription(self, topicObj):
+ if topicObj.getDescription():
+ extraIndent = self.__indentStep
+ self.__formatItem('"""', extraIndent)
+ self.__formatItem( topicObj.getDescription(), extraIndent )
+ self.__formatItem('"""', extraIndent)
+
+ def __printTopicArgSpec(self, topicObj):
+ extraIndent = self.__indentStep
+
+ # generate the message data specification
+ reqdArgs, optArgs = topicObj.getArgs()
+ argsStr = []
+ if reqdArgs:
+ argsStr.append( ", ".join(reqdArgs) )
+ if optArgs:
+ optStr = ', '.join([('%s=None' % arg) for arg in optArgs])
+ argsStr.append(optStr)
+ argsStr = ', '.join(argsStr)
+
+ # print it only if there are args; ie if listener() don't print it
+ if argsStr:
+ # output a blank line and protocol
+ self.__formatItem('\n', extraIndent)
+ protoListener = 'def %s(%s):' % (SPEC_METHOD_NAME, argsStr)
+ self.__formatItem(protoListener, extraIndent)
+
+ # and finally, the args docs
+ extraIndent += self.__indentStep
+ self.__formatItem('"""', extraIndent)
+ # but ignore the arg keys that are in parent args docs:
+ parentMsgKeys = ()
+ if topicObj.getParent() is not None:
+ parentMsgKeys = topicObj.getParent().getArgDescriptions().keys() # keys iter ok
+ argsDocs = topicObj.getArgDescriptions()
+ for key in sorted(py2and3.iterkeys(argsDocs)):
+ if key not in parentMsgKeys:
+ argDesc = argsDocs[key]
+ msg = "- %s: %s" % (key, argDesc)
+ self.__formatItem(msg, extraIndent)
+ self.__formatItem('"""', extraIndent)
+
+ def __formatItem(self, item, extraIndent=0):
+ indent = extraIndent + self.__indent
+ indentStr = self.INDENT_CH * indent
+ lines = item.splitlines()
+ for line in lines:
+ self.__output.append( '%s%s' % (indentStr, line) )
+
+ def __formatBlock(self, text, extraIndent=0):
+ self.__wrapper.initial_indent = self.INDENT_CH * (self.__indent + extraIndent)
+ self.__wrapper.subsequent_indent = self.__wrapper.initial_indent
+ self.__output.append( self.__wrapper.fill(text) )
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicexc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicexc.py
new file mode 100644
index 0000000..76d7022
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicexc.py
@@ -0,0 +1,72 @@
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+
+
+class TopicNameError(ValueError):
+ """Raised when the topic name is not properly formatted or
+ no corresponding Topic object found. """
+ def __init__(self, name, msg):
+ ValueError.__init__(self, 'Topic name "%s": %s' % (name, msg))
+
+
+class TopicDefnError(RuntimeError):
+ """
+ Raised when an operation requires a topic have an MDS, but it doesn't.
+ See also pub.setTopicUnspecifiedFatal().
+ """
+ def __init__(self, topicNameTuple):
+ msg = "No topic specification for topic '%s'." \
+ % '.'.join(topicNameTuple)
+ RuntimeError.__init__(self, msg +
+ " See pub.addTopicDefnProvider() and/or pub.setTopicUnspecifiedFatal()")
+
+
+class MessageDataSpecError(RuntimeError):
+ """
+ Raised when an attempt is made to define a topic's Message Data
+ Specification (MDS) to something that is not valid.
+
+ The keyword names for invalid data go in the 'args' list,
+ and the msg should state the problem and contain "%s" for the
+ args, such as MessageDataSpecError('duplicate args %s', ('arg1', 'arg2')).
+ """
+
+ def __init__(self, msg, args):
+ argsMsg = msg % ','.join(args)
+ RuntimeError.__init__(self, 'Invalid message data spec: ' + argsMsg)
+
+
+class ExcHandlerError(RuntimeError):
+ """
+ Raised when a listener exception handler (see pub.setListenerExcHandler())
+ raises an exception. The original exception is contained.
+ """
+
+ def __init__(self, badExcListenerID, topicObj, origExc=None):
+ """The badExcListenerID is the name of the listener that raised
+ the original exception that handler was attempting to handle.
+ The topicObj is the Topic object for the topic of the
+ sendMessage that had an exception raised.
+ The origExc is currently not used. """
+ self.badExcListenerID = badExcListenerID
+ import traceback
+ self.exc = traceback.format_exc()
+ msg = 'The exception handler registered with pubsub raised an ' \
+ + 'exception, *while* handling an exception raised by listener ' \
+ + ' "%s" of topic "%s"):\n%s' \
+ % (self.badExcListenerID, topicObj.getName(), self.exc)
+ RuntimeError.__init__(self, msg)
+
+
+class UnrecognizedSourceFormatError(ValueError):
+ """
+ Raised when a topic definition provider doesn't recognize the format
+ of source input it was given.
+ """
+ def __init__(self):
+ ValueError.__init__(self, 'Source format not recognized')
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicmgr.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicmgr.py
new file mode 100644
index 0000000..11993f0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicmgr.py
@@ -0,0 +1,456 @@
+"""
+Code related to the concept of topic tree and its management: creating
+and removing topics, getting info about a particular topic, etc.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+__all__ = [
+ 'TopicManager',
+ 'TopicNameError',
+ 'TopicDefnError',
+ ]
+
+
+from .callables import getID
+
+from .topicutils import (
+ ALL_TOPICS,
+ tupleize,
+ stringize,
+)
+
+from .topicexc import (
+ TopicNameError,
+ TopicDefnError,
+)
+
+from .topicargspec import (
+ ArgSpecGiven,
+ ArgsInfo,
+ topicArgsFromCallable,
+)
+
+from .topicobj import (
+ Topic,
+)
+
+from .treeconfig import TreeConfig
+from .topicdefnprovider import ITopicDefnProvider
+from .topicmgrimpl import getRootTopicSpec
+
+from .. import py2and3
+
+
+# ---------------------------------------------------------
+
+ARGS_SPEC_ALL = ArgSpecGiven.SPEC_GIVEN_ALL
+ARGS_SPEC_NONE = ArgSpecGiven.SPEC_GIVEN_NONE
+
+
+# ---------------------------------------------------------
+
+class TopicManager:
+ """
+ Manages the registry of all topics and creation/deletion
+ of topics.
+
+ Note that any method that accepts a topic name can accept it in the
+ 'dotted' format such as ``'a.b.c.'`` or in tuple format such as
+ ``('a', 'b', 'c')``. Any such method will raise a ValueError
+ if name not valid (empty, invalid characters, etc).
+ """
+
+ # Allowed return values for isTopicSpecified()
+ TOPIC_SPEC_NOT_SPECIFIED = 0 # false
+ TOPIC_SPEC_ALREADY_CREATED = 1 # all other values equate to "true" but different reason
+ TOPIC_SPEC_ALREADY_DEFINED = 2
+
+
+ def __init__(self, treeConfig=None):
+ """The optional treeConfig is an instance of TreeConfig, used to
+ configure the topic tree such as notification settings, etc. A
+ default config is created if not given. This method should only be
+ called by an instance of Publisher (see Publisher.getTopicManager())."""
+ self.__allTopics = None # root of topic tree
+ self._topicsMap = {} # registry of all topics
+ self.__treeConfig = treeConfig or TreeConfig()
+ self.__defnProvider = _MasterTopicDefnProvider(self.__treeConfig)
+
+ # define root of all topics
+ assert self.__allTopics is None
+ argsDocs, reqdArgs = getRootTopicSpec()
+ desc = 'Root of all topics'
+ specGiven = ArgSpecGiven(argsDocs, reqdArgs)
+ self.__allTopics = self.__createTopic((ALL_TOPICS,), desc, specGiven=specGiven)
+
+ def getRootAllTopics(self):
+ """Get the topic that is parent of all root (ie top-level) topics,
+ for default TopicManager instance created when this module is imported.
+ Some notes:
+
+ - "root of all topics" topic satisfies isAll()==True, isRoot()==False,
+ getParent() is None;
+ - all root-level topics satisfy isAll()==False, isRoot()==True, and
+ getParent() is getDefaultTopicTreeRoot();
+ - all other topics satisfy neither. """
+ return self.__allTopics
+
+ def addDefnProvider(self, providerOrSource, format=None):
+ """Register a topic definition provider. After this method is called, whenever a topic must be created,
+ the first definition provider that has a definition
+ for the required topic is used to instantiate the topic.
+
+ If providerOrSource is an instance of ITopicDefnProvider, register
+ it as a provider of topic definitions. Otherwise, register a new
+ instance of TopicDefnProvider(providerOrSource, format). In that case,
+ if format is not given, it defaults to TOPIC_TREE_FROM_MODULE. Either
+ way, returns the instance of ITopicDefnProvider registered.
+ """
+ if isinstance(providerOrSource, ITopicDefnProvider):
+ provider = providerOrSource
+ else:
+ from .topicdefnprovider import (TopicDefnProvider, TOPIC_TREE_FROM_MODULE)
+ source = providerOrSource
+ provider = TopicDefnProvider(source, format or TOPIC_TREE_FROM_MODULE)
+ self.__defnProvider.addProvider(provider)
+ return provider
+
+ def clearDefnProviders(self):
+ """Remove all registered topic definition providers"""
+ self.__defnProvider.clear()
+
+ def getNumDefnProviders(self):
+ """Get how many topic definitions providers are registered."""
+ return self.__defnProvider.getNumProviders()
+
+ def getTopic(self, name, okIfNone=False):
+ """Get the Topic instance for the given topic name. By default, raises
+ an TopicNameError exception if a topic with given name doesn't exist. If
+ okIfNone=True, returns None instead of raising an exception."""
+ topicNameDotted = stringize(name)
+ #if not name:
+ # raise TopicNameError(name, 'Empty topic name not allowed')
+ obj = self._topicsMap.get(topicNameDotted, None)
+ if obj is not None:
+ return obj
+
+ if okIfNone:
+ return None
+
+ # NOT FOUND! Determine what problem is and raise accordingly:
+ # find the closest parent up chain that does exists:
+ parentObj, subtopicNames = self.__getClosestParent(topicNameDotted)
+ assert subtopicNames
+
+ subtopicName = subtopicNames[0]
+ if parentObj is self.__allTopics:
+ raise TopicNameError(name, 'Root topic "%s" doesn\'t exist' % subtopicName)
+
+ msg = 'Topic "%s" doesn\'t have "%s" as subtopic' % (parentObj.getName(), subtopicName)
+ raise TopicNameError(name, msg)
+
+ def newTopic(self, _name, _desc, _required=(), **_argDocs):
+ """Deprecated legacy method.
+ If topic _name already exists, just returns it and does nothing else.
+ Otherwise, uses getOrCreateTopic() to create it, then sets its
+ description (_desc) and its message data specification (_argDocs
+ and _required). Replaced by getOrCreateTopic()."""
+ topic = self.getTopic(_name, True)
+ if topic is None:
+ topic = self.getOrCreateTopic(_name)
+ topic.setDescription(_desc)
+ topic.setMsgArgSpec(_argDocs, _required)
+ return topic
+
+ def getOrCreateTopic(self, name, protoListener=None):
+ """Get the Topic instance for topic of given name, creating it
+ (and any of its missing parent topics) as necessary. Pubsub
+ functions such as subscribe() use this to obtain the Topic object
+ corresponding to a topic name.
+
+ The name can be in dotted or string format (``'a.b.'`` or ``('a','b')``).
+
+ This method always attempts to return a "complete" topic, i.e. one
+ with a Message Data Specification (MDS). So if the topic does not have
+ an MDS, it attempts to add it. It first tries to find an MDS
+ from a TopicDefnProvider (see addDefnProvider()). If none is available,
+ it attempts to set it from protoListener, if it has been given. If not,
+ the topic has no MDS.
+
+ Once a topic's MDS has been set, it is never again changed or accessed
+ by this method.
+
+ Examples::
+
+ # assume no topics exist
+ # but a topic definition provider has been added via
+ # pub.addTopicDefnProvider() and has definition for topics 'a' and 'a.b'
+
+ # creates topic a and a.b; both will have MDS from the defn provider:
+ t1 = topicMgr.getOrCreateTopic('a.b')
+ t2 = topicMgr.getOrCreateTopic('a.b')
+ assert(t1 is t2)
+ assert(t1.getParent().getName() == 'a')
+
+ def proto(req1, optarg1=None): pass
+ # creates topic c.d with MDS based on proto; creates c without an MDS
+ # since no proto for it, nor defn provider:
+ t1 = topicMgr.getOrCreateTopic('c.d', proto)
+
+ The MDS can also be defined via a call to subscribe(listener, topicName),
+ which indirectly calls getOrCreateTopic(topicName, listener).
+ """
+ obj = self.getTopic(name, okIfNone=True)
+ if obj:
+ # if object is not sendable but a proto listener was given,
+ # update its specification so that it is sendable
+ if (protoListener is not None) and not obj.hasMDS():
+ allArgsDocs, required = topicArgsFromCallable(protoListener)
+ obj.setMsgArgSpec(allArgsDocs, required)
+ return obj
+
+ # create missing parents
+ nameTuple = tupleize(name)
+ parentObj = self.__createParentTopics(nameTuple)
+
+ # now the final topic object, args from listener if provided
+ desc, specGiven = self.__defnProvider.getDefn(nameTuple)
+ # POLICY: protoListener is used only if no definition available
+ if specGiven is None:
+ if protoListener is None:
+ desc = 'UNDOCUMENTED: created without spec'
+ else:
+ allArgsDocs, required = topicArgsFromCallable(protoListener)
+ specGiven = ArgSpecGiven(allArgsDocs, required)
+ desc = 'UNDOCUMENTED: created from protoListener "%s" in module %s' % getID(protoListener)
+
+ return self.__createTopic(nameTuple, desc, parent = parentObj, specGiven = specGiven)
+
+ def isTopicInUse(self, name):
+ """Determine if topic 'name' is in use. True if a Topic object exists
+ for topic name (i.e. message has already been sent for that topic, or a
+ least one listener subscribed), false otherwise. Note: a topic may be in use
+ but not have a definition (MDS and docstring); or a topic may have a
+ definition, but not be in use."""
+ return self.getTopic(name, okIfNone=True) is not None
+
+ def hasTopicDefinition(self, name):
+ """Determine if there is a definition avaiable for topic 'name'. Return
+ true if there is, false otherwise. Note: a topic may have a
+ definition without being in use, and vice versa."""
+ # in already existing Topic object:
+ alreadyCreated = self.getTopic(name, okIfNone=True)
+ if alreadyCreated is not None and alreadyCreated.hasMDS():
+ return True
+
+ # from provider?
+ nameTuple = tupleize(name)
+ if self.__defnProvider.isDefined(nameTuple):
+ return True
+
+ return False
+
+ def checkAllTopicsHaveMDS(self):
+ """Check that all topics that have been created for their MDS.
+ Raise a TopicDefnError if one is found that does not have one."""
+ for topic in py2and3.itervalues(self._topicsMap):
+ if not topic.hasMDS():
+ raise TopicDefnError(topic.getNameTuple())
+
+ def delTopic(self, name):
+ """Delete the named topic, including all sub-topics. Returns False
+ if topic does not exist; True otherwise. Also unsubscribe any listeners
+ of topic and all subtopics. """
+ # find from which parent the topic object should be removed
+ dottedName = stringize(name)
+ try:
+ #obj = weakref( self._topicsMap[dottedName] )
+ obj = self._topicsMap[dottedName]
+ except KeyError:
+ return False
+
+ #assert obj().getName() == dottedName
+ assert obj.getName() == dottedName
+ # notification must be before deletion in case
+ self.__treeConfig.notificationMgr.notifyDelTopic(dottedName)
+
+ #obj()._undefineSelf_(self._topicsMap)
+ obj._undefineSelf_(self._topicsMap)
+ #assert obj() is None
+
+ return True
+
+ def getTopicsSubscribed(self, listener):
+ """Get the list of Topic objects that have given listener
+ subscribed. Note: the listener can also get messages from any
+ sub-topic of returned list."""
+ assocTopics = []
+ for topicObj in py2and3.itervalues(self._topicsMap):
+ if topicObj.hasListener(listener):
+ assocTopics.append(topicObj)
+ return assocTopics
+
+ def __getClosestParent(self, topicNameDotted):
+ """Returns a pair, (closest parent, tuple path from parent). The
+ first item is the closest parent Topic that exists.
+ The second one is the list of topic name elements that have to be
+ created to create the given topic.
+
+ So if topicNameDotted = A.B.C.D, but only A.B exists (A.B.C and
+ A.B.C.D not created yet), then return is (A.B, ['C','D']).
+ Note that if none of the branch exists (not even A), then return
+ will be [root topic, ['A',B','C','D']). Note also that if A.B.C
+ exists, the return will be (A.B.C, ['D']) regardless of whether
+ A.B.C.D exists. """
+ subtopicNames = []
+ headTail = topicNameDotted.rsplit('.', 1)
+ while len(headTail) > 1:
+ parentName = headTail[0]
+ subtopicNames.insert( 0, headTail[1] )
+ obj = self._topicsMap.get( parentName, None )
+ if obj is not None:
+ return obj, subtopicNames
+
+ headTail = parentName.rsplit('.', 1)
+
+ subtopicNames.insert( 0, headTail[0] )
+ return self.__allTopics, subtopicNames
+
+ def __createParentTopics(self, topicName):
+ """This will find which parents need to be created such that
+ topicName can be created (but doesn't create given topic),
+ and creates them. Returns the parent object."""
+ assert self.getTopic(topicName, okIfNone=True) is None
+ parentObj, subtopicNames = self.__getClosestParent(stringize(topicName))
+
+ # will create subtopics of parentObj one by one from subtopicNames
+ if parentObj is self.__allTopics:
+ nextTopicNameList = []
+ else:
+ nextTopicNameList = list(parentObj.getNameTuple())
+ for name in subtopicNames[:-1]:
+ nextTopicNameList.append(name)
+ desc, specGiven = self.__defnProvider.getDefn( tuple(nextTopicNameList) )
+ if desc is None:
+ desc = 'UNDOCUMENTED: created as parent without specification'
+ parentObj = self.__createTopic( tuple(nextTopicNameList),
+ desc, specGiven = specGiven, parent = parentObj)
+
+ return parentObj
+
+ def __createTopic(self, nameTuple, desc, specGiven, parent=None):
+ """Actual topic creation step. Adds new Topic instance to topic map,
+ and sends notification message (see ``Publisher.addNotificationMgr()``)
+ regarding topic creation."""
+ if specGiven is None:
+ specGiven = ArgSpecGiven()
+ parentAI = None
+ if parent:
+ parentAI = parent._getListenerSpec()
+ argsInfo = ArgsInfo(nameTuple, specGiven, parentAI)
+ if (self.__treeConfig.raiseOnTopicUnspecified
+ and not argsInfo.isComplete()):
+ raise TopicDefnError(nameTuple)
+
+ newTopicObj = Topic(self.__treeConfig, nameTuple, desc,
+ argsInfo, parent = parent)
+ # sanity checks:
+ assert newTopicObj.getName() not in self._topicsMap
+ if parent is self.__allTopics:
+ assert len( newTopicObj.getNameTuple() ) == 1
+ else:
+ assert parent.getNameTuple() == newTopicObj.getNameTuple()[:-1]
+ assert nameTuple == newTopicObj.getNameTuple()
+
+ # store new object and notify of creation
+ self._topicsMap[ newTopicObj.getName() ] = newTopicObj
+ self.__treeConfig.notificationMgr.notifyNewTopic(
+ newTopicObj, desc, specGiven.reqdArgs, specGiven.argsDocs)
+
+ return newTopicObj
+
+
+def validateNameHierarchy(topicTuple):
+ """Check that names in topicTuple are valid: no spaces, not empty.
+ Raise ValueError if fails check. E.g. ('',) and ('a',' ') would
+ both fail, but ('a','b') would be ok. """
+ if not topicTuple:
+ topicName = stringize(topicTuple)
+ errMsg = 'empty topic name'
+ raise TopicNameError(topicName, errMsg)
+
+ for indx, topic in enumerate(topicTuple):
+ errMsg = None
+ if topic is None:
+ topicName = list(topicTuple)
+ topicName[indx] = 'None'
+ errMsg = 'None at level #%s'
+
+ elif not topic:
+ topicName = stringize(topicTuple)
+ errMsg = 'empty element at level #%s'
+
+ elif topic.isspace():
+ topicName = stringize(topicTuple)
+ errMsg = 'blank element at level #%s'
+
+ if errMsg:
+ raise TopicNameError(topicName, errMsg % indx)
+
+
+class _MasterTopicDefnProvider:
+ """
+ Stores a list of topic definition providers. When queried for a topic
+ definition, queries each provider (registered via addProvider()) and
+ returns the first complete definition provided, or (None,None).
+
+ The providers must follow the ITopicDefnProvider protocol.
+ """
+
+ def __init__(self, treeConfig):
+ self.__providers = []
+ self.__treeConfig = treeConfig
+
+ def addProvider(self, provider):
+ """Add given provider IF not already added. """
+ assert(isinstance(provider, ITopicDefnProvider))
+ if provider not in self.__providers:
+ self.__providers.append(provider)
+
+ def clear(self):
+ """Remove all providers added."""
+ self.__providers = []
+
+ def getNumProviders(self):
+ """Return how many providers added."""
+ return len(self.__providers)
+
+ def getDefn(self, topicNameTuple):
+ """Returns a pair (docstring, MDS) for the topic. The first item is
+ a string containing the topic's "docstring", i.e. a description string
+ for the topic, or None if no docstring available for the topic. The
+ second item is None or an instance of ArgSpecGiven specifying the
+ required and optional message data for listeners of this topic. """
+ desc, defn = None, None
+ for provider in self.__providers:
+ tmpDesc, tmpDefn = provider.getDefn(topicNameTuple)
+ if (tmpDesc is not None) and (tmpDefn is not None):
+ assert tmpDefn.isComplete()
+ desc, defn = tmpDesc, tmpDefn
+ break
+
+ return desc, defn
+
+ def isDefined(self, topicNameTuple):
+ """Returns True only if a complete definition exists, ie topic
+ has a description and a complete message data specification (MDS)."""
+ desc, defn = self.getDefn(topicNameTuple)
+ if desc is None or defn is None:
+ return False
+ if defn.isComplete():
+ return True
+ return False
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicobj.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicobj.py
new file mode 100644
index 0000000..716fa21
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicobj.py
@@ -0,0 +1,472 @@
+"""
+Provide the Topic class.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+
+from weakref import ref as weakref
+
+from .listener import (
+ Listener,
+ ListenerValidator,
+)
+
+from .topicutils import (
+ ALL_TOPICS,
+ stringize,
+ tupleize,
+ validateName,
+ smartDedent,
+)
+
+from .topicexc import (
+ TopicDefnError,
+ TopicNameError,
+ ExcHandlerError,
+)
+
+from .publishermixin import PublisherMixin
+
+from .topicargspec import (
+ ArgsInfo,
+ ArgSpecGiven,
+ topicArgsFromCallable,
+ SenderMissingReqdMsgDataError,
+ SenderUnknownMsgDataError,
+ MessageDataSpecError,
+)
+
+from .. import py2and3
+
+
+class Topic(PublisherMixin):
+ """
+ Represent topics in pubsub. Contains information about a topic,
+ including topic's message data specification (MDS), the list of
+ subscribed listeners, docstring for the topic. It allows Python-like
+ access to subtopics (e.g. A.B is subtopic B of topic A).
+ """
+
+ def __init__(self, treeConfig, nameTuple, description,
+ msgArgsInfo, parent=None):
+ """Create a topic. Should only be called by TopicManager via its
+ getOrCreateTopic() method (which gets called in several places
+ in pubsub, such as sendMessage, subscribe, and newTopic).
+
+ :param treeConfig: topic tree configuration settings
+ :param nameTuple: topic name, in tuple format (no dots)
+ :param description: "docstring" for topic
+ :param ArgsInfo msgArgsInfo: object that defines MDS for topic
+ :param parent: parent of topic
+
+ :raises ValueError: invalid topic name
+ """
+ if parent is None:
+ if nameTuple != (ALL_TOPICS,):
+ msg = 'Only one topic, named %s, can be root of topic tree'
+ raise ValueError(msg % 'pub.ALL_TOPICS')
+ else:
+ validateName(nameTuple)
+ self.__tupleName = nameTuple
+
+ self.__handlingUncaughtListenerExc = False
+ self._treeConfig = treeConfig
+ PublisherMixin.__init__(self)
+
+ self.__validator = None
+ # Registered listeners were originally kept in a Python list; however
+ # a few methods require lookup of the Listener for the given callable,
+ # which is an O(n) operation. A set() could have been more suitable but
+ # there is no way of retrieving an element from a set without iterating
+ # over the set, again an O(n) operation. A dict() is ok too. Because
+ # Listener.__eq__(callable) returns true if the Listener instance wraps
+ # the given callable, and because Listener.__hash__ produces the hash
+ # value of the wrapped callable, calling dict[callable] on a
+ # dict(Listener -> Listener) mapping will be O(1) in most cases:
+ # the dict will take the callables hash, find the list of Listeners that
+ # have that hash, and then iterate over that inner list to find the
+ # Listener instance which satisfies Listener == callable, and will return
+ # the Listener.
+ self.__listeners = dict()
+
+ # specification:
+ self.__description = None
+ self.setDescription(description)
+ self.__msgArgs = msgArgsInfo
+ if msgArgsInfo.isComplete():
+ self.__finalize()
+ else:
+ assert not self._treeConfig.raiseOnTopicUnspecified
+
+ # now that we know the args are fine, we can link to parent
+ self.__parentTopic = None
+ self.__subTopics = {}
+ if parent is None:
+ assert self.hasMDS()
+ else:
+ self.__parentTopic = weakref(parent)
+ assert self.__msgArgs.parentAI() is parent._getListenerSpec()
+ parent.__adoptSubtopic( self )
+
+ def setDescription(self, desc):
+ """Set the 'docstring' of topic"""
+ self.__description = desc
+
+ def getDescription(self):
+ """Return the 'docstring' of topic"""
+ if self.__description is None:
+ return None
+ return smartDedent(self.__description)
+
+ def setMsgArgSpec(self, argsDocs, required=()):
+ """Specify the message data for topic messages.
+ :param argsDocs: a dictionary of keyword names (message data name) and data 'docstring'; cannot be None
+ :param required: a list of those keyword names, appearing in argsDocs,
+ which are required (all others are assumed optional)
+
+ Can only be called if this info has not been already set at construction
+ or in a previous call.
+ :raise RuntimeError: if MDS already set at construction or previous call."""
+ assert self.__parentTopic is not None # for root of tree, this method never called!
+ if argsDocs is None:
+ raise ValueError('Cannot set listener spec to None')
+
+ if self.__msgArgs is None or not self.__msgArgs.isComplete():
+ try:
+ specGiven = ArgSpecGiven(argsDocs, required)
+ self.__msgArgs = ArgsInfo(self.__tupleName, specGiven,
+ self.__parentTopic()._getListenerSpec())
+ except MessageDataSpecError:
+ # discard the lower part of the stack trace
+ exc = py2and3.getexcobj()
+ raise exc
+ self.__finalize()
+
+ else:
+ raise RuntimeError('Not allowed to call this: msg spec already set!')
+
+ def getArgs(self):
+ """Returns a pair (reqdArgs, optArgs) where reqdArgs is tuple
+ of names of required message arguments, optArgs is tuple
+ of names for optional arguments. If topic args not specified
+ yet, returns (None, None)."""
+ sendable = self.__msgArgs.isComplete()
+ assert sendable == self.hasMDS()
+ if sendable:
+ return (self.__msgArgs.allRequired ,
+ self.__msgArgs.allOptional)
+ return None, None
+
+ def getArgDescriptions(self):
+ """Get a map of keyword names to docstrings: documents each MDS element. """
+ return self.__msgArgs.getArgsDocs()
+
+ def setArgDescriptions(self, **docs):
+ """Set the docstring for each MDS datum."""
+ self.__msgArgs.setArgsDocs(docs)
+
+ def hasMDS(self):
+ """Return true if this topic has a message data specification (MDS)."""
+ return self.__validator is not None
+
+ def filterMsgArgs(self, msgKwargs, check=False):
+ """Get the MDS docstrings for each of the spedified kwargs."""
+ filteredArgs = self.__msgArgs.filterArgs(msgKwargs)
+ # if no check of args yet, do it now:
+ if check:
+ self.__msgArgs.check(filteredArgs)
+ return filteredArgs
+
+ def isAll(self):
+ """Returns true if this topic is the 'all topics' topic. All root
+ topics behave as though they are child of that topic. """
+ return self.__tupleName == (ALL_TOPICS,)
+
+ def isRoot(self):
+ """Returns true if this is a "root" topic, false otherwise. A
+ root topic is a topic whose name contains no dots and which
+ has pub.ALL_TOPICS as parent."""
+ parent = self.getParent()
+ if parent:
+ return parent.isAll()
+ assert self.isAll()
+ return False
+
+ def getName(self):
+ """Return dotted form of full topic name"""
+ return stringize(self.__tupleName)
+
+ def getNameTuple(self):
+ """Return tuple form of full topic name"""
+ return self.__tupleName
+
+ def getNodeName(self):
+ """Return the last part of the topic name (has no dots)"""
+ name = self.__tupleName[-1]
+ return name
+
+ def getParent(self):
+ """Get Topic object that is parent of self (i.e. self is a subtopic
+ of parent). Return none if self is the "all topics" topic."""
+ if self.__parentTopic is None:
+ return None
+ return self.__parentTopic()
+
+ def hasSubtopic(self, name=None):
+ """Return true only if name is a subtopic of self. If name not
+ specified, return true only if self has at least one subtopic."""
+ if name is None:
+ return len(self.__subTopics) > 0
+
+ return name in self.__subTopics
+
+ def getSubtopic(self, relName):
+ """Get the specified subtopic object. The relName can be a valid
+ subtopic name, a dotted-name string, or a tuple. """
+ if not relName:
+ raise ValueError("getSubtopic() arg can't be empty")
+ topicTuple = tupleize(relName)
+ assert topicTuple
+
+ topicObj = self
+ for topicName in topicTuple:
+ child = topicObj.__subTopics.get(topicName)
+ if child is None:
+ msg = 'Topic "%s" doesn\'t have "%s" as subtopic' % (topicObj.getName(), topicName)
+ raise TopicNameError(relName, msg)
+ topicObj = child
+
+ return topicObj
+
+ def getSubtopics(self):
+ """Get a list of Topic instances that are subtopics of self."""
+ return py2and3.values(self.__subTopics)
+
+ def getNumListeners(self):
+ """Return number of listeners currently subscribed to topic. This is
+ different from number of listeners that will get notified since more
+ general topics up the topic tree may have listeners."""
+ return len(self.__listeners)
+
+ def hasListener(self, listener):
+ """Return true if listener is subscribed to this topic."""
+ return listener in self.__listeners
+
+ def hasListeners(self):
+ """Return true if there are any listeners subscribed to
+ this topic, false otherwise."""
+ return bool(self.__listeners)
+
+ def getListeners(self):
+ """Get a copy of list of listeners subscribed to this topic. Safe to iterate over while listeners
+ get un/subscribed from this topics (such as while sending a message)."""
+ return py2and3.keys(self.__listeners)
+
+ def getListenersIter(self):
+ """Get an iterator over listeners subscribed to this topic. Do not use if listeners can be
+ un/subscribed while iterating. """
+ return py2and3.iterkeys(self.__listeners)
+
+ def validate(self, listener):
+ """Checks whether listener could be subscribed to this topic:
+ if yes, just returns; if not, raises ListenerMismatchError.
+ Note that method raises TopicDefnError if self not
+ hasMDS()."""
+ if not self.hasMDS():
+ raise TopicDefnError(self.__tupleName)
+ return self.__validator.validate(listener)
+
+ def isValid(self, listener):
+ """Return True only if listener could be subscribed to this topic,
+ otherwise returns False. Note that method raises TopicDefnError
+ if self not hasMDS()."""
+ if not self.hasMDS():
+ raise TopicDefnError(self.__tupleName)
+ return self.__validator.isValid(listener)
+
+ def subscribe(self, listener):
+ """Subscribe listener to this topic. Returns a pair
+ (pub.Listener, success). The success is true only if listener
+ was not already subscribed and is now subscribed. """
+ if listener in self.__listeners:
+ assert self.hasMDS()
+ subdLisnr, newSub = self.__listeners[listener], False
+
+ else:
+ if self.__validator is None:
+ args, reqd = topicArgsFromCallable(listener)
+ self.setMsgArgSpec(args, reqd)
+ argsInfo = self.__validator.validate(listener)
+ weakListener = Listener(
+ listener, argsInfo, onDead=self.__onDeadListener)
+ self.__listeners[weakListener] = weakListener
+ subdLisnr, newSub = weakListener, True
+
+ # notify of subscription
+ self._treeConfig.notificationMgr.notifySubscribe(subdLisnr, self, newSub)
+
+ return subdLisnr, newSub
+
+ def unsubscribe(self, listener):
+ """Unsubscribe the specified listener from this topic. Returns
+ the pub.Listener object associated with the listener that was
+ unsubscribed, or None if the specified listener was not
+ subscribed to this topic. Note that this method calls
+ ``notifyUnsubscribe(listener, self)`` on all registered notification
+ handlers (see pub.addNotificationHandler)."""
+ unsubdLisnr = self.__listeners.pop(listener, None)
+ if unsubdLisnr is None:
+ return None
+
+ unsubdLisnr._unlinkFromTopic_()
+ assert listener == unsubdLisnr.getCallable()
+
+ # notify of unsubscription
+ self._treeConfig.notificationMgr.notifyUnsubscribe(unsubdLisnr, self)
+
+ return unsubdLisnr
+
+ def unsubscribeAllListeners(self, filter=None):
+ """Clears list of subscribed listeners. If filter is given, it must
+ be a function that takes a listener and returns true if the listener
+ should be unsubscribed. Returns the list of Listener for listeners
+ that were unsubscribed."""
+ unsubd = []
+ if filter is None:
+ for listener in self.__listeners:
+ listener._unlinkFromTopic_()
+ unsubd = py2and3.keys(self.__listeners)
+ self.__listeners = {}
+ else:
+ unsubd = []
+ for listener in py2and3.keys(self.__listeners):
+ if filter(listener):
+ unsubd.append(listener)
+ listener._unlinkFromTopic_()
+ del self.__listeners[listener]
+
+ # send notification regarding all listeners actually unsubscribed
+ notificationMgr = self._treeConfig.notificationMgr
+ for unsubdLisnr in unsubd:
+ notificationMgr.notifyUnsubscribe(unsubdLisnr, self)
+
+ return unsubd
+
+ #############################################################
+ #
+ # Impementation
+ #
+ #############################################################
+
+ def _getListenerSpec(self):
+ """Only to be called by pubsub package"""
+ return self.__msgArgs
+
+ def _publish(self, data):
+ """This sends message to listeners of parent topics as well.
+ If an exception is raised in a listener, the publish is
+ aborted, except if there is a handler (see
+ pub.setListenerExcHandler)."""
+ self._treeConfig.notificationMgr.notifySend('pre', self)
+
+ # send to ourself
+ iterState = self._mix_prePublish(data)
+ self.__sendMessage(data, self, iterState)
+
+ # send up the chain
+ topicObj = self.getParent()
+ while topicObj is not None:
+ if topicObj.hasListeners():
+ iterState = self._mix_prePublish(data, topicObj, iterState)
+ self.__sendMessage(data, topicObj, iterState)
+
+ # done for this topic, continue up branch to parent towards root
+ topicObj = topicObj.getParent()
+
+ self._treeConfig.notificationMgr.notifySend('post', self)
+
+ def __sendMessage(self, data, topicObj, iterState):
+ # now send message data to each listener for current topic;
+ # use list of listeners rather than iterator, so that if listeners added/removed during
+ # send loop, no runtime exception:
+ for listener in topicObj.getListeners():
+ try:
+ self._treeConfig.notificationMgr.notifySend('in', topicObj, pubListener=listener)
+ self._mix_callListener(listener, data, iterState)
+
+ except Exception:
+ # if exception handling is on, handle, otherwise re-raise
+ handler = self._treeConfig.listenerExcHandler
+ if handler is None or self.__handlingUncaughtListenerExc:
+ raise
+
+ # try handling the exception so we can continue the send:
+ try:
+ self.__handlingUncaughtListenerExc = True
+ handler( listener.name(), topicObj )
+ self.__handlingUncaughtListenerExc = False
+ except Exception:
+ exc = py2and3.getexcobj()
+ #print 'exception raised', exc
+ self.__handlingUncaughtListenerExc = False
+ raise ExcHandlerError(listener.name(), topicObj, exc)
+
+ def __finalize(self):
+ """Finalize the topic specification, which currently means
+ creating the listener validator for this topic. This allows
+ calls to subscribe() to validate that listener adheres to
+ topic's message data specification (MDS)."""
+ assert self.__msgArgs.isComplete()
+ assert not self.hasMDS()
+
+ # must make sure can adopt a validator
+ required = self.__msgArgs.allRequired
+ optional = self.__msgArgs.allOptional
+ self.__validator = ListenerValidator(required, list(optional) )
+ assert not self.__listeners
+
+ def _undefineSelf_(self, topicsMap):
+ """Called by topic manager when deleting a topic."""
+ if self.__parentTopic is not None:
+ self.__parentTopic().__abandonSubtopic(self.__tupleName[-1])
+ self.__undefineBranch(topicsMap)
+
+ def __undefineBranch(self, topicsMap):
+ """Unsubscribe all our listeners, remove all subtopics from self,
+ then detach from parent. Parent is not notified, because method
+ assumes it has been called by parent"""
+ #print 'Remove %s listeners (%s)' % (self.getName(), self.getNumListeners())
+ self.unsubscribeAllListeners()
+ self.__parentTopic = None
+
+ for subName, subObj in py2and3.iteritems(self.__subTopics):
+ assert isinstance(subObj, Topic)
+ #print 'Unlinking %s from parent' % subObj.getName()
+ subObj.__undefineBranch(topicsMap)
+
+ self.__subTopics = {}
+ del topicsMap[self.getName()]
+
+ def __adoptSubtopic(self, topicObj):
+ """Add topicObj as child topic."""
+ assert topicObj.__parentTopic() is self
+ attrName = topicObj.getNodeName()
+ self.__subTopics[attrName] = topicObj
+
+ def __abandonSubtopic(self, name):
+ """The given subtopic becomes orphan (no parent)."""
+ topicObj = self.__subTopics.pop(name)
+ assert topicObj.__parentTopic() is self
+
+ def __onDeadListener(self, weakListener):
+ """One of our subscribed listeners has died, so remove it and notify"""
+ pubListener = self.__listeners.pop(weakListener)
+ # notify:
+ self._treeConfig.notificationMgr.notifyDeadListener(pubListener, self)
+
+ def __str__(self):
+ return "%s(%s)" % (self.getName(), self.getNumListeners())
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topictreetraverser.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topictreetraverser.py
new file mode 100644
index 0000000..e31732f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topictreetraverser.py
@@ -0,0 +1,143 @@
+"""
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+class TopicTreeTraverser:
+ """
+ Supports taking action on every topic in the topic tree. The traverse() method
+ traverses a topic tree and calls visitor._onTopic() for each topic in the tree
+ that satisfies visitor._accept(). Additionally it calls visitor._startChildren()
+ whenever it starts traversing the subtopics of a topic, and
+ visitor._endChildren() when it is done with the subtopics. Finally, it calls
+ visitor._doneTraversal() when traversal has been completed. The visitor must
+ therefore adhere to the ITopicTreeVisitor interface.
+ """
+ DEPTH = 'Depth first through topic tree'
+ BREADTH = 'Breadth first through topic tree'
+ MAP = 'Sequential through topic manager\'s topics map'
+
+ def __init__(self, visitor = None):
+ """The visitor, if given, must adhere to API of
+ ITopicTreeVisitor. The visitor can be changed or
+ set via setVisitor(visitor) before calling traverse()."""
+ self.__handler = visitor
+
+ def setVisitor(self, visitor):
+ """The visitor must adhere to API of ITopicTreeVisitor. """
+ self.__handler = visitor
+
+ def traverse(self, topicObj, how=DEPTH, onlyFiltered=True):
+ """Start traversing tree at topicObj. Note that topicObj is a
+ Topic object, not a topic name. The how defines if tree should
+ be traversed breadth or depth first. If onlyFiltered is
+ False, then all nodes are accepted (_accept(node) not called).
+
+ This method can be called multiple times.
+ """
+ if how == self.MAP:
+ raise NotImplementedError('not yet available')
+
+ self.__handler._startTraversal()
+
+ if how == self.BREADTH:
+ self.__traverseBreadth(topicObj, onlyFiltered)
+ else:
+ assert how == self.DEPTH
+ self.__traverseDepth(topicObj, onlyFiltered)
+
+ self.__handler._doneTraversal()
+
+ def __traverseBreadth(self, topicObj, onlyFiltered):
+ visitor = self.__handler
+
+ def extendQueue(subtopics):
+ topics.append(visitor._startChildren)
+ topics.extend(subtopics)
+ topics.append(visitor._endChildren)
+
+ topics = [topicObj]
+ while topics:
+ topicObj = topics.pop(0)
+
+ if topicObj in (visitor._startChildren, visitor._endChildren):
+ topicObj()
+ continue
+
+ if onlyFiltered:
+ if visitor._accept(topicObj):
+ extendQueue( topicObj.getSubtopics() )
+ visitor._onTopic(topicObj)
+ else:
+ extendQueue( topicObj.getSubtopics() )
+ visitor._onTopic(topicObj)
+
+ def __traverseDepth(self, topicObj, onlyFiltered):
+ visitor = self.__handler
+
+ def extendStack(topicTreeStack, subtopics):
+ topicTreeStack.insert(0, visitor._endChildren) # marker functor
+ # put subtopics in list in alphabetical order
+ subtopicsTmp = subtopics
+ subtopicsTmp.sort(reverse=True, key=topicObj.__class__.getName)
+ for sub in subtopicsTmp:
+ topicTreeStack.insert(0, sub) # this puts them in reverse order
+ topicTreeStack.insert(0, visitor._startChildren) # marker functor
+
+ topics = [topicObj]
+ while topics:
+ topicObj = topics.pop(0)
+
+ if topicObj in (visitor._startChildren, visitor._endChildren):
+ topicObj()
+ continue
+
+ if onlyFiltered:
+ if visitor._accept(topicObj):
+ extendStack( topics, topicObj.getSubtopics() )
+ visitor._onTopic(topicObj)
+ else:
+ extendStack( topics, topicObj.getSubtopics() )
+ visitor._onTopic(topicObj)
+
+
+class ITopicTreeVisitor:
+ """
+ Derive from ITopicTreeVisitor and override one or more of the
+ self._*() methods. Give an instance to an instance of
+ TopicTreeTraverser.
+ """
+
+ def _accept(self, topicObj):
+ """Override this to filter nodes of topic tree. Must return
+ True (accept node) of False (reject node). Note that rejected
+ nodes cause traversal to move to next branch (no children
+ traversed)."""
+ return True
+
+ def _startTraversal(self):
+ """Override this to define what to do when traversal() starts."""
+ pass
+
+ def _onTopic(self, topicObj):
+ """Override this to define what to do for each node."""
+ pass
+
+ def _startChildren(self):
+ """Override this to take special action whenever a
+ new level of the topic hierarchy is started (e.g., indent
+ some output). """
+ pass
+
+ def _endChildren(self):
+ """Override this to take special action whenever a
+ level of the topic hierarchy is completed (e.g., dedent
+ some output). """
+ pass
+
+ def _doneTraversal(self):
+ """Override this to take special action when traversal done."""
+ pass
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicutils.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicutils.py
new file mode 100644
index 0000000..35f4ccb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/topicutils.py
@@ -0,0 +1,118 @@
+"""
+Various utilities used by topic-related modules.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+from textwrap import TextWrapper, dedent
+
+from .topicexc import TopicNameError
+
+from .. import py2and3
+
+__all__ = []
+
+
+UNDERSCORE = '_' # topic name can't start with this
+# just want something unlikely to clash with user's topic names
+ALL_TOPICS = 'ALL_TOPICS'
+
+
+class WeakNone:
+ """Pretend to be a weak reference to nothing. Used by ArgsInfos to
+ refer to parent when None so no if-else blocks needed. """
+ def __call__(self):
+ return None
+
+
+def smartDedent(paragraph):
+ """Dedent paragraph using textwrap.dedent(), but properly dedents
+ even if the first line of paragraph does not contain blanks.
+ This handles the case where a user types a documentation string as
+ '''A long string spanning
+ several lines.'''
+ """
+ if paragraph.startswith(' '):
+ para = dedent(paragraph)
+ else:
+ lines = paragraph.split('\n')
+ exceptFirst = dedent('\n'.join(lines[1:]))
+ para = lines[0]+exceptFirst
+ return para
+
+
+import re
+_validNameRE = re.compile(r'[-0-9a-zA-Z]\w*')
+
+
+def validateName(topicName):
+ """Raise TopicNameError if nameTuple not valid as topic name."""
+ topicNameTuple = tupleize(topicName)
+ if not topicNameTuple:
+ reason = 'name tuple must have at least one item!'
+ raise TopicNameError(None, reason)
+
+ class topic: pass
+ for subname in topicNameTuple:
+ if not subname:
+ reason = 'can\'t contain empty string or None'
+ raise TopicNameError(topicNameTuple, reason)
+
+ if subname.startswith(UNDERSCORE):
+ reason = 'must not start with "%s"' % UNDERSCORE
+ raise TopicNameError(topicNameTuple, reason)
+
+ if subname == ALL_TOPICS:
+ reason = 'string "%s" is reserved for root topic' % ALL_TOPICS
+ raise TopicNameError(topicNameTuple, reason)
+
+ if _validNameRE.match(subname) is None:
+ reason = 'element #%s ("%s") has invalid characters' % \
+ (1+list(topicNameTuple).index(subname), subname)
+ raise TopicNameError(topicNameTuple, reason)
+
+
+def stringize(topicName):
+ """If topicName is a string, just return it
+ as is. If it is a topic definition object (ie an object that has
+ 'msgDataSpec' as data member), return the dotted name of corresponding
+ topic. Otherwise, assume topicName is a tuple and convert it to to a
+ dotted name i.e. ('a','b','c') => 'a.b.c'. Empty name is not allowed
+ (ValueError). The reverse operation is tupleize(topicName)."""
+ if py2and3.isstring(topicName):
+ return topicName
+
+ if hasattr(topicName, "msgDataSpec"):
+ return topicName._topicNameStr
+
+ try:
+ name = '.'.join(topicName)
+ except Exception:
+ exc = py2and3.getexcobj()
+ raise TopicNameError(topicName, str(exc))
+
+ return name
+
+
+def tupleize(topicName):
+ """If topicName is a tuple of strings, just return it as is. Otherwise,
+ convert it to tuple, assuming dotted notation used for topicName. I.e.
+ 'a.b.c' => ('a','b','c'). Empty topicName is not allowed (ValueError).
+ The reverse operation is stringize(topicNameTuple)."""
+ # assume name is most often str; if more often tuple,
+ # then better use isinstance(name, tuple)
+ if hasattr(topicName, "msgDataSpec"):
+ topicName = topicName._topicNameStr
+ if py2and3.isstring(topicName):
+ topicTuple = tuple(topicName.split('.'))
+ else:
+ topicTuple = tuple(topicName) # assume already tuple of strings
+
+ if not topicTuple:
+ raise TopicNameError(topicTuple, "Topic name can't be empty!")
+
+ return topicTuple
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/treeconfig.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/treeconfig.py
new file mode 100644
index 0000000..51b4087
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/treeconfig.py
@@ -0,0 +1,21 @@
+"""
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from .notificationmgr import NotificationMgr
+
+
+class TreeConfig:
+ """
+ Each topic tree has its own topic manager and configuration,
+ such as notification and exception handling.
+ """
+
+ def __init__(self, notificationHandler=None, listenerExcHandler=None):
+ self.notificationMgr = NotificationMgr(notificationHandler)
+ self.listenerExcHandler = listenerExcHandler
+ self.raiseOnTopicUnspecified = False
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/validatedefnargs.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/validatedefnargs.py
new file mode 100644
index 0000000..8b701cd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/validatedefnargs.py
@@ -0,0 +1,29 @@
+"""
+Some topic definition validation functions.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from .topicexc import MessageDataSpecError
+
+
+def verifyArgsDifferent(allArgs, allParentArgs, topicName):
+ """Verify that allArgs does not contain any of allParentArgs. Raise
+ MessageDataSpecError if fail. """
+ extra = set(allArgs).intersection(allParentArgs)
+ if extra:
+ msg = 'Args %%s already used in parent of "%s"' % topicName
+ raise MessageDataSpecError( msg, tuple(extra) )
+
+
+def verifySubset(all, sub, topicName, extraMsg=''):
+ """Verify that sub is a subset of all for topicName. Raise
+ MessageDataSpecError if fail. """
+ notInAll = set(sub).difference(all)
+ if notInAll:
+ args = ','.join(all)
+ msg = 'Params [%s] missing inherited [%%s] for topic "%s"%s' % (args, topicName, extraMsg)
+ raise MessageDataSpecError(msg, tuple(notInAll) )
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/weakmethod.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/weakmethod.py
new file mode 100644
index 0000000..d78af75
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/core/weakmethod.py
@@ -0,0 +1,102 @@
+"""
+This module provides a basic "weak method" implementation, WeakMethod. It uses
+weakref.WeakRef which, used on its own, produces weak methods that are dead on
+creation, not very useful. Use the getWeakRef(object) module function to create the
+proper type of weak reference (weakref.WeakRef or WeakMethod) for given object.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+# for function and method parameter counting:
+from inspect import ismethod
+# for weakly bound methods:
+from types import MethodType
+from weakref import ref as WeakRef
+
+
+class WeakMethod:
+ """Represent a weak bound method, i.e. a method which doesn't keep alive the
+ object that it is bound to. """
+
+ def __init__(self, method, notifyDead = None):
+ """The method must be bound. notifyDead will be called when
+ object that method is bound to dies. """
+ assert ismethod(method)
+ if method.__self__ is None:
+ raise ValueError('Unbound methods cannot be weak-referenced.')
+
+ self.notifyDead = None
+ if notifyDead is None:
+ self.objRef = WeakRef(method.__self__)
+ else:
+ self.notifyDead = notifyDead
+ self.objRef = WeakRef(method.__self__, self.__onNotifyDeadObj)
+
+ self.fun = method.__func__
+ self.cls = method.__self__.__class__
+
+ def __onNotifyDeadObj(self, ref):
+ if self.notifyDead:
+ try:
+ self.notifyDead(self)
+ except Exception:
+ import traceback
+ traceback.print_exc()
+
+ def __call__(self):
+ """Returns a MethodType if object for method still alive.
+ Otherwise return None. Note that MethodType causes a
+ strong reference to object to be created, so shouldn't save
+ the return value of this call. Note also that this __call__
+ is required only for compatibility with WeakRef.ref(), otherwise
+ there would be more efficient ways of providing this functionality."""
+ if self.objRef() is None:
+ return None
+ else:
+ return MethodType(self.fun, self.objRef())
+
+ def __eq__(self, method2):
+ """Two WeakMethod objects compare equal if they refer to the same method
+ of the same instance. Thanks to Josiah Carlson for patch and clarifications
+ on how dict uses eq/cmp and hashing. """
+ if not isinstance(method2, WeakMethod):
+ return False
+
+ return ( self.fun is method2.fun
+ and self.objRef() is method2.objRef()
+ and self.objRef() is not None )
+
+ def __hash__(self):
+ """Hash is an optimization for dict searches, it need not
+ return different numbers for every different object. Some objects
+ are not hashable (eg objects of classes derived from dict) so no
+ hash(objRef()) in there, and hash(self.cls) would only be useful
+ in the rare case where instance method was rebound. """
+ return hash(self.fun)
+
+ def __repr__(self):
+ dead = ''
+ if self.objRef() is None:
+ dead = '; DEAD'
+ obj = '<%s at %s%s>' % (self.__class__, id(self), dead)
+ return obj
+
+ def refs(self, weakRef):
+ """Return true if we are storing same object referred to by weakRef."""
+ return self.objRef == weakRef
+
+
+def getWeakRef(obj, notifyDead=None):
+ """Get a weak reference to obj. If obj is a bound method, a WeakMethod
+ object, that behaves like a WeakRef, is returned; if it is
+ anything else a WeakRef is returned. If obj is an unbound method,
+ a ValueError will be raised."""
+ if ismethod(obj):
+ createRef = WeakMethod
+ else:
+ createRef = WeakRef
+
+ return createRef(obj, notifyDead)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/policies.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/policies.py
new file mode 100644
index 0000000..bc296ce
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/policies.py
@@ -0,0 +1,24 @@
+"""
+Aggregates policies for pubsub. Mainly, related to messaging protocol.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+msgProtocolTransStage = None
+
+msgDataProtocol = 'kwargs'
+msgDataArgName = None
+senderKwargNameAny = False
+
+
+def setMsgDataArgName(stage, listenerArgName, senderArgNameAny=False):
+ global senderKwargNameAny
+ global msgDataArgName
+ global msgProtocolTransStage
+ senderKwargNameAny = senderArgNameAny
+ msgDataArgName = listenerArgName
+ msgProtocolTransStage = stage
+ #print `policies.msgProtocolTransStage`, `policies.msgDataProtocol`, \
+ # `policies.senderKwargNameAny`, `policies.msgDataArgName`
+ #print 'override "arg1" protocol arg name:', argName
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/pub.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/pub.py
new file mode 100644
index 0000000..b75f4e7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/pub.py
@@ -0,0 +1,199 @@
+"""
+This is the main entry-point to pubsub's core functionality. The :mod:`~pubsub.pub`
+module supports:
+
+* messaging: publishing and receiving messages of a given topic
+* tracing: tracing pubsub activity in an application
+* trapping exceptions: dealing with "badly behaved" listeners (ie that leak exceptions)
+* specificatio of topic tree: defining (or just documenting) the topic tree of an
+ application; message data specification (MDS)
+
+The recommended usage is ::
+
+ from pubsub import pub
+
+ // use pub functions:
+ pub.sendMessage(...)
+
+Note that this module creates a "default" instance of
+pubsub.core.Publisher and binds several local functions to some of its methods
+and those of the pubsub.core.TopicManager instance that it contains. However, an
+application may create as many independent instances of Publisher as
+required (for instance, one in each thread; with a custom queue to mediate
+message transfer between threads).
+"""
+
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+VERSION_API = 3 #: major API version
+
+VERSION_SVN = "$Rev: 243 $".split()[1] # DO NOT CHANGE: automatically updated by VCS
+
+from .core import (
+ Publisher as _Publisher,
+
+ AUTO_TOPIC,
+
+ ListenerMismatchError,
+ TopicDefnError,
+
+ IListenerExcHandler,
+ ExcHandlerError,
+
+ SenderMissingReqdMsgDataError,
+ SenderUnknownMsgDataError,
+
+ TopicDefnError,
+ TopicNameError,
+ UnrecognizedSourceFormatError,
+
+ ALL_TOPICS,
+
+ MessageDataSpecError,
+ exportTopicTreeSpec,
+ TOPIC_TREE_FROM_MODULE,
+ TOPIC_TREE_FROM_STRING,
+ TOPIC_TREE_FROM_CLASS,
+
+ TopicTreeTraverser,
+
+ INotificationHandler,
+)
+
+__all__ = [
+ # listener stuff:
+ 'subscribe',
+ 'unsubscribe',
+ 'unsubAll',
+ 'isSubscribed',
+
+ 'isValid',
+ 'validate',
+ 'ListenerMismatchError',
+ 'AUTO_TOPIC',
+
+ 'IListenerExcHandler',
+ 'getListenerExcHandler',
+ 'setListenerExcHandler',
+ 'ExcHandlerError',
+
+ # topic stuff:
+
+ 'ALL_TOPICS',
+ 'topicTreeRoot',
+ 'topicsMap',
+
+ 'getDefaultTopicMgr',
+
+ # topioc defn provider stuff
+
+ 'addTopicDefnProvider',
+ 'clearTopicDefnProviders',
+ 'getNumTopicDefnProviders',
+ 'TOPIC_TREE_FROM_MODULE',
+ 'TOPIC_TREE_FROM_CLASS',
+ 'TOPIC_TREE_FROM_STRING',
+ 'exportTopicTreeSpec',
+ 'instantiateAllDefinedTopics'
+
+ 'TopicDefnError',
+ 'TopicNameError',
+
+ 'setTopicUnspecifiedFatal',
+
+ # publisher stuff:
+
+ 'sendMessage',
+ 'SenderMissingReqdMsgDataError',
+ 'SenderUnknownMsgDataError',
+
+ # misc:
+
+ 'addNotificationHandler',
+ 'setNotificationFlags',
+ 'getNotificationFlags',
+ 'clearNotificationHandlers',
+
+ 'TopicTreeTraverser',
+
+]
+
+
+# --------- Publisher singleton and bound methods ------------------------------------
+
+_publisher = _Publisher()
+
+subscribe = _publisher.subscribe
+unsubscribe = _publisher.unsubscribe
+unsubAll = _publisher.unsubAll
+sendMessage = _publisher.sendMessage
+
+getListenerExcHandler = _publisher.getListenerExcHandler
+setListenerExcHandler = _publisher.setListenerExcHandler
+
+addNotificationHandler = _publisher.addNotificationHandler
+clearNotificationHandlers = _publisher.clearNotificationHandlers
+setNotificationFlags = _publisher.setNotificationFlags
+getNotificationFlags = _publisher.getNotificationFlags
+
+setTopicUnspecifiedFatal = _publisher.setTopicUnspecifiedFatal
+
+getMsgProtocol = _publisher.getMsgProtocol
+
+def getDefaultPublisher():
+ """Get the Publisher instance created by default when this module
+ is imported. See the module doc for details about this instance."""
+ return _publisher
+
+
+# ---------- default TopicManager instance and bound methods ------------------------
+
+_topicMgr = _publisher.getTopicMgr()
+
+topicTreeRoot = _topicMgr.getRootAllTopics()
+topicsMap = _topicMgr._topicsMap
+
+
+def isValid(listener, topicName):
+ """Return true only if listener can subscribe to messages of given topic."""
+ return _topicMgr.getTopic(topicName).isValid(listener)
+
+
+def validate(listener, topicName):
+ """Checks if listener can subscribe to topicName. If not, raises
+ ListenerMismatchError, otherwise just returns."""
+ _topicMgr.getTopic(topicName).validate(listener)
+
+
+def isSubscribed(listener, topicName):
+ """Returns true if listener has subscribed to topicName, false otherwise.
+ WARNING: a false return is not a guarantee that listener won't get
+ messages of topicName: it could receive messages of a subtopic of
+ topicName. """
+ return _topicMgr.getTopic(topicName).hasListener(listener)
+
+
+def getDefaultTopicMgr():
+ """Get the TopicManager instance created by default when this
+ module is imported. This function is a shortcut for
+ ``pub.getDefaultPublisher().getTopicMgr()``."""
+ return _topicMgr
+
+
+addTopicDefnProvider = _topicMgr.addDefnProvider
+clearTopicDefnProviders = _topicMgr.clearDefnProviders
+getNumTopicDefnProviders = _topicMgr.getNumDefnProviders
+
+def instantiateAllDefinedTopics(provider):
+ """Loop over all topics of given provider and "instantiate" each topic, thus
+ forcing a parse of the topics documentation, message data specification (MDS),
+ comparison with parent MDS, and MDS documentation. Without this function call,
+ an error among any of those characteristics will manifest only if the a
+ listener is registered on it. """
+ for topicName in provider:
+ _topicMgr.getOrCreateTopic(topicName)
+
+#---------------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/py2and3.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/py2and3.py
new file mode 100644
index 0000000..66eb312
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/py2and3.py
@@ -0,0 +1,608 @@
+"""Utilities for writing code that runs on Python 2 and 3"""
+
+# Copyright (c) 2010-2013 Benjamin Peterson
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import operator
+import sys
+import types
+
+__author__ = "Benjamin Peterson <benjamin@python.org>"
+__version__ = "1.4.1"
+
+
+# Useful for very coarse version differentiation.
+PY2 = sys.version_info[0] == 2
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+ string_types = str,
+ integer_types = int,
+ class_types = type,
+ text_type = str
+ binary_type = bytes
+
+ MAXSIZE = sys.maxsize
+else:
+ string_types = basestring,
+ integer_types = (int, long)
+ class_types = (type, types.ClassType)
+ text_type = unicode
+ binary_type = str
+
+ if sys.platform.startswith("java"):
+ # Jython always uses 32 bits.
+ MAXSIZE = int((1 << 31) - 1)
+ else:
+ # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
+ class X(object):
+ def __len__(self):
+ return 1 << 31
+ try:
+ len(X())
+ except OverflowError:
+ # 32-bit
+ MAXSIZE = int((1 << 31) - 1)
+ else:
+ # 64-bit
+ MAXSIZE = int((1 << 63) - 1)
+ del X
+
+
+def _add_doc(func, doc):
+ """Add documentation to a function."""
+ func.__doc__ = doc
+
+
+def _import_module(name):
+ """Import module, returning the module after the last dot."""
+ __import__(name)
+ return sys.modules[name]
+
+
+class _LazyDescr(object):
+
+ def __init__(self, name):
+ self.name = name
+
+ def __get__(self, obj, tp):
+ result = self._resolve()
+ setattr(obj, self.name, result)
+ # This is a bit ugly, but it avoids running this again.
+ delattr(tp, self.name)
+ return result
+
+
+class MovedModule(_LazyDescr):
+
+ def __init__(self, name, old, new=None):
+ super(MovedModule, self).__init__(name)
+ if PY3:
+ if new is None:
+ new = name
+ self.mod = new
+ else:
+ self.mod = old
+
+ def _resolve(self):
+ return _import_module(self.mod)
+
+
+class MovedAttribute(_LazyDescr):
+
+ def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
+ super(MovedAttribute, self).__init__(name)
+ if PY3:
+ if new_mod is None:
+ new_mod = name
+ self.mod = new_mod
+ if new_attr is None:
+ if old_attr is None:
+ new_attr = name
+ else:
+ new_attr = old_attr
+ self.attr = new_attr
+ else:
+ self.mod = old_mod
+ if old_attr is None:
+ old_attr = name
+ self.attr = old_attr
+
+ def _resolve(self):
+ module = _import_module(self.mod)
+ return getattr(module, self.attr)
+
+
+
+class _MovedItems(types.ModuleType):
+ """Lazy loading of moved objects"""
+
+
+_moved_attributes = [
+ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
+ MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
+ MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
+ MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
+ MovedAttribute("map", "itertools", "builtins", "imap", "map"),
+ MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
+ MovedAttribute("reload_module", "__builtin__", "imp", "reload"),
+ MovedAttribute("reduce", "__builtin__", "functools"),
+ MovedAttribute("StringIO", "StringIO", "io"),
+ MovedAttribute("UserString", "UserString", "collections"),
+ MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
+ MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
+ MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
+
+ MovedModule("builtins", "__builtin__"),
+ MovedModule("configparser", "ConfigParser"),
+ MovedModule("copyreg", "copy_reg"),
+ MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
+ MovedModule("http_cookies", "Cookie", "http.cookies"),
+ MovedModule("html_entities", "htmlentitydefs", "html.entities"),
+ MovedModule("html_parser", "HTMLParser", "html.parser"),
+ MovedModule("http_client", "httplib", "http.client"),
+ MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
+ MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
+ MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
+ MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
+ MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
+ MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
+ MovedModule("cPickle", "cPickle", "pickle"),
+ MovedModule("queue", "Queue"),
+ MovedModule("reprlib", "repr"),
+ MovedModule("socketserver", "SocketServer"),
+ MovedModule("tkinter", "Tkinter"),
+ MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
+ MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
+ MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
+ MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
+ MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
+ MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
+ MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
+ MovedModule("tkinter_colorchooser", "tkColorChooser",
+ "tkinter.colorchooser"),
+ MovedModule("tkinter_commondialog", "tkCommonDialog",
+ "tkinter.commondialog"),
+ MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
+ MovedModule("tkinter_font", "tkFont", "tkinter.font"),
+ MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
+ MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
+ "tkinter.simpledialog"),
+ MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
+ MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
+ MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
+ MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
+ MovedModule("winreg", "_winreg"),
+]
+for attr in _moved_attributes:
+ setattr(_MovedItems, attr.name, attr)
+del attr
+
+moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves")
+
+
+
+class Module_six_moves_urllib_parse(types.ModuleType):
+ """Lazy loading of moved objects in six.moves.urllib_parse"""
+
+
+_urllib_parse_moved_attributes = [
+ MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
+ MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
+ MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
+ MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
+ MovedAttribute("urljoin", "urlparse", "urllib.parse"),
+ MovedAttribute("urlparse", "urlparse", "urllib.parse"),
+ MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
+ MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
+ MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
+ MovedAttribute("quote", "urllib", "urllib.parse"),
+ MovedAttribute("quote_plus", "urllib", "urllib.parse"),
+ MovedAttribute("unquote", "urllib", "urllib.parse"),
+ MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
+ MovedAttribute("urlencode", "urllib", "urllib.parse"),
+]
+for attr in _urllib_parse_moved_attributes:
+ setattr(Module_six_moves_urllib_parse, attr.name, attr)
+del attr
+
+sys.modules[__name__ + ".moves.urllib_parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse")
+sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib.parse")
+
+
+class Module_six_moves_urllib_error(types.ModuleType):
+ """Lazy loading of moved objects in six.moves.urllib_error"""
+
+
+_urllib_error_moved_attributes = [
+ MovedAttribute("URLError", "urllib2", "urllib.error"),
+ MovedAttribute("HTTPError", "urllib2", "urllib.error"),
+ MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
+]
+for attr in _urllib_error_moved_attributes:
+ setattr(Module_six_moves_urllib_error, attr.name, attr)
+del attr
+
+sys.modules[__name__ + ".moves.urllib_error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib_error")
+sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error")
+
+
+class Module_six_moves_urllib_request(types.ModuleType):
+ """Lazy loading of moved objects in six.moves.urllib_request"""
+
+
+_urllib_request_moved_attributes = [
+ MovedAttribute("urlopen", "urllib2", "urllib.request"),
+ MovedAttribute("install_opener", "urllib2", "urllib.request"),
+ MovedAttribute("build_opener", "urllib2", "urllib.request"),
+ MovedAttribute("pathname2url", "urllib", "urllib.request"),
+ MovedAttribute("url2pathname", "urllib", "urllib.request"),
+ MovedAttribute("getproxies", "urllib", "urllib.request"),
+ MovedAttribute("Request", "urllib2", "urllib.request"),
+ MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
+ MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
+ MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
+ MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
+ MovedAttribute("FileHandler", "urllib2", "urllib.request"),
+ MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
+ MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
+ MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
+ MovedAttribute("urlretrieve", "urllib", "urllib.request"),
+ MovedAttribute("urlcleanup", "urllib", "urllib.request"),
+ MovedAttribute("URLopener", "urllib", "urllib.request"),
+ MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
+]
+for attr in _urllib_request_moved_attributes:
+ setattr(Module_six_moves_urllib_request, attr.name, attr)
+del attr
+
+sys.modules[__name__ + ".moves.urllib_request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib_request")
+sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request")
+
+
+class Module_six_moves_urllib_response(types.ModuleType):
+ """Lazy loading of moved objects in six.moves.urllib_response"""
+
+
+_urllib_response_moved_attributes = [
+ MovedAttribute("addbase", "urllib", "urllib.response"),
+ MovedAttribute("addclosehook", "urllib", "urllib.response"),
+ MovedAttribute("addinfo", "urllib", "urllib.response"),
+ MovedAttribute("addinfourl", "urllib", "urllib.response"),
+]
+for attr in _urllib_response_moved_attributes:
+ setattr(Module_six_moves_urllib_response, attr.name, attr)
+del attr
+
+sys.modules[__name__ + ".moves.urllib_response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib_response")
+sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response")
+
+
+class Module_six_moves_urllib_robotparser(types.ModuleType):
+ """Lazy loading of moved objects in six.moves.urllib_robotparser"""
+
+
+_urllib_robotparser_moved_attributes = [
+ MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
+]
+for attr in _urllib_robotparser_moved_attributes:
+ setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
+del attr
+
+sys.modules[__name__ + ".moves.urllib_robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib_robotparser")
+sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser")
+
+
+class Module_six_moves_urllib(types.ModuleType):
+ """Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
+ parse = sys.modules[__name__ + ".moves.urllib_parse"]
+ error = sys.modules[__name__ + ".moves.urllib_error"]
+ request = sys.modules[__name__ + ".moves.urllib_request"]
+ response = sys.modules[__name__ + ".moves.urllib_response"]
+ robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"]
+
+
+sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib")
+
+
+def add_move(move):
+ """Add an item to six.moves."""
+ setattr(_MovedItems, move.name, move)
+
+
+def remove_move(name):
+ """Remove item from six.moves."""
+ try:
+ delattr(_MovedItems, name)
+ except AttributeError:
+ try:
+ del moves.__dict__[name]
+ except KeyError:
+ raise AttributeError("no such move, %r" % (name,))
+
+
+if PY3:
+ _meth_func = "__func__"
+ _meth_self = "__self__"
+
+ _func_closure = "__closure__"
+ _func_code = "__code__"
+ _func_defaults = "__defaults__"
+ _func_globals = "__globals__"
+
+ _iterkeys = "keys"
+ _itervalues = "values"
+ _iteritems = "items"
+ _iterlists = "lists"
+else:
+ _meth_func = "im_func"
+ _meth_self = "im_self"
+
+ _func_closure = "func_closure"
+ _func_code = "func_code"
+ _func_defaults = "func_defaults"
+ _func_globals = "func_globals"
+
+ _iterkeys = "iterkeys"
+ _itervalues = "itervalues"
+ _iteritems = "iteritems"
+ _iterlists = "iterlists"
+
+
+try:
+ advance_iterator = next
+except NameError:
+ def advance_iterator(it):
+ return it.next()
+next = advance_iterator
+
+
+try:
+ callable = callable
+except NameError:
+ def callable(obj):
+ return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
+
+
+if PY3:
+ def get_unbound_function(unbound):
+ return unbound
+
+ create_bound_method = types.MethodType
+
+ Iterator = object
+else:
+ def get_unbound_function(unbound):
+ return unbound.im_func
+
+ def create_bound_method(func, obj):
+ return types.MethodType(func, obj, obj.__class__)
+
+ class Iterator(object):
+
+ def next(self):
+ return type(self).__next__(self)
+
+ callable = callable
+_add_doc(get_unbound_function,
+ """Get the function out of a possibly unbound function""")
+
+
+get_method_function = operator.attrgetter(_meth_func)
+get_method_self = operator.attrgetter(_meth_self)
+get_function_closure = operator.attrgetter(_func_closure)
+get_function_code = operator.attrgetter(_func_code)
+get_function_defaults = operator.attrgetter(_func_defaults)
+get_function_globals = operator.attrgetter(_func_globals)
+
+
+def iterkeys(d, **kw):
+ """Return an iterator over the keys of a dictionary."""
+ return iter(getattr(d, _iterkeys)(**kw))
+
+def itervalues(d, **kw):
+ """Return an iterator over the values of a dictionary."""
+ return iter(getattr(d, _itervalues)(**kw))
+
+def iteritems(d, **kw):
+ """Return an iterator over the (key, value) pairs of a dictionary."""
+ return iter(getattr(d, _iteritems)(**kw))
+
+def iterlists(d, **kw):
+ """Return an iterator over the (key, [values]) pairs of a dictionary."""
+ return iter(getattr(d, _iterlists)(**kw))
+
+
+if PY3:
+ def b(s):
+ return s.encode("latin-1")
+ def u(s):
+ return s
+ unichr = chr
+ if sys.version_info[1] <= 1:
+ def int2byte(i):
+ return bytes((i,))
+ else:
+ # This is about 2x faster than the implementation above on 3.2+
+ int2byte = operator.methodcaller("to_bytes", 1, "big")
+ byte2int = operator.itemgetter(0)
+ indexbytes = operator.getitem
+ iterbytes = iter
+ import io
+ StringIO = io.StringIO
+ BytesIO = io.BytesIO
+else:
+ def b(s):
+ return s
+ def u(s):
+ return unicode(s, "unicode_escape")
+ unichr = unichr
+ int2byte = chr
+ def byte2int(bs):
+ return ord(bs[0])
+ def indexbytes(buf, i):
+ return ord(buf[i])
+ def iterbytes(buf):
+ return (ord(byte) for byte in buf)
+ import StringIO
+ StringIO = BytesIO = StringIO.StringIO
+_add_doc(b, """Byte literal""")
+_add_doc(u, """Text literal""")
+
+
+if PY3:
+ import builtins
+ exec_ = getattr(builtins, "exec")
+
+
+ def reraise(tp, value, tb=None):
+ if value.__traceback__ is not tb:
+ raise value.with_traceback(tb)
+ raise value
+
+
+ print_ = getattr(builtins, "print")
+ del builtins
+
+else:
+ def exec_(_code_, _globs_=None, _locs_=None):
+ """Execute code in a namespace."""
+ if _globs_ is None:
+ frame = sys._getframe(1)
+ _globs_ = frame.f_globals
+ if _locs_ is None:
+ _locs_ = frame.f_locals
+ del frame
+ elif _locs_ is None:
+ _locs_ = _globs_
+ exec("""exec _code_ in _globs_, _locs_""")
+
+
+ exec_("""def reraise(tp, value, tb=None):
+ raise tp, value, tb
+""")
+
+
+ def print_(*args, **kwargs):
+ """The new-style print function."""
+ fp = kwargs.pop("file", sys.stdout)
+ if fp is None:
+ return
+ def write(data):
+ if not isinstance(data, basestring):
+ data = str(data)
+ fp.write(data)
+ want_unicode = False
+ sep = kwargs.pop("sep", None)
+ if sep is not None:
+ if isinstance(sep, unicode):
+ want_unicode = True
+ elif not isinstance(sep, str):
+ raise TypeError("sep must be None or a string")
+ end = kwargs.pop("end", None)
+ if end is not None:
+ if isinstance(end, unicode):
+ want_unicode = True
+ elif not isinstance(end, str):
+ raise TypeError("end must be None or a string")
+ if kwargs:
+ raise TypeError("invalid keyword arguments to print()")
+ if not want_unicode:
+ for arg in args:
+ if isinstance(arg, unicode):
+ want_unicode = True
+ break
+ if want_unicode:
+ newline = unicode("\n")
+ space = unicode(" ")
+ else:
+ newline = "\n"
+ space = " "
+ if sep is None:
+ sep = space
+ if end is None:
+ end = newline
+ for i, arg in enumerate(args):
+ if i:
+ write(sep)
+ write(arg)
+ write(end)
+
+_add_doc(reraise, """Reraise an exception.""")
+
+
+def with_metaclass(meta, *bases):
+ """Create a base class with a metaclass."""
+ return meta("NewBase", bases, {})
+
+def add_metaclass(metaclass):
+ """Class decorator for creating a class with a metaclass."""
+ def wrapper(cls):
+ orig_vars = cls.__dict__.copy()
+ orig_vars.pop('__dict__', None)
+ orig_vars.pop('__weakref__', None)
+ for slots_var in orig_vars.get('__slots__', ()):
+ orig_vars.pop(slots_var)
+ return metaclass(cls.__name__, cls.__bases__, orig_vars)
+ return wrapper
+
+def getexcobj():
+ return sys.exc_info()[1]
+
+if PY3:
+ xrange = range
+else:
+ xrange = xrange
+
+if PY3:
+ def keys(dictObj):
+ return list(dictObj.keys())
+ def values(dictObj):
+ return list(dictObj.values())
+ def nextiter(container):
+ return next(container)
+else:
+ def keys(dictObj):
+ return dictObj.keys()
+ def values(dictObj):
+ return dictObj.values()
+ def nextiter(container):
+ return container.next()
+
+if PY3:
+ def isstring(obj):
+ return isinstance(obj, str)
+else:
+ def isstring(obj):
+ return isinstance(obj, (str, unicode))
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/setuparg1.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/setuparg1.py
new file mode 100644
index 0000000..da36a3a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/setuparg1.py
@@ -0,0 +1,33 @@
+"""
+Setup pubsub for the *arg1* message protocol. In a default pubsub installation
+the default protocol is *kargs*.
+
+This module must be imported before the first ``from pubsub import pub``
+statement in the application. Once :mod:pub has been imported, the messaging
+protocol cannot be changed (i.e., importing it after the first
+``from pubsub import pub`` statement has undefined behavior).
+::
+
+ from .. import setuparg1
+ from .. import pub
+
+The *arg1* protocol is identical to the legacy messaging protocol from
+first version of pubsub (when it was still part of wxPython) and
+is *deprecated*. This module is therefore *deprecated*.
+"""
+
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from . import policies
+policies.msgDataProtocol = 'arg1'
+
+
+def enforceArgName(commonName):
+ """This will configure pubsub to require that all listeners use
+ the same argument name (*commonName*) as first parameter. This
+ is a ueful first step in migrating an application that has been
+ using *arg1* protocol to the more powerful *kwargs* protocol. """
+ policies.setMsgDataArgName(1, commonName)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/setupkwargs.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/setupkwargs.py
new file mode 100644
index 0000000..7e3a7c1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/setupkwargs.py
@@ -0,0 +1,29 @@
+"""
+Setup pubsub for the kwargs message protocol. In a default installation
+this is the default protocol so this module is only needed if setupkargs
+utility functions are used, or in a custom installation where kwargs
+is not the default messaging protocol (such as in some versions of
+wxPython).
+
+This module must be imported before the first ``from pubsub import pub``
+statement in the application. Once :mod:pub has been imported, the messaging
+protocol cannot be changed (i.e., importing it after the first
+``from pubsub import pub`` statement has undefined behavior).
+"""
+
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from . import policies
+policies.msgDataProtocol = 'kwargs'
+
+
+def transitionFromArg1(commonName):
+ """Utility function to assist migrating an application from using
+ the arg1 messaging protocol to using the kwargs protocol. Call this
+ after having run and debugged your application with ``setuparg1.enforceArgName(commonName)``. See the migration docs
+ for more detais.
+ """
+ policies.setMsgDataArgName(2, commonName)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/__init__.py
new file mode 100644
index 0000000..b96cfd5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/__init__.py
@@ -0,0 +1,27 @@
+"""
+Provides utility functions and classes that are not required for using
+pubsub but are likely to be very useful.
+"""
+
+"""
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from .topictreeprinter import printTreeDocs
+
+from .notification import (
+ useNotifyByPubsubMessage,
+ useNotifyByWriteFile,
+ IgnoreNotificationsMixin,
+)
+
+from .exchandling import ExcPublisher
+
+__all__ = [
+ 'printTreeDocs',
+ 'useNotifyByPubsubMessage',
+ 'useNotifyByWriteFile',
+ 'IgnoreNotificationsMixin',
+ 'ExcPublisher'
+ ] \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/exchandling.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/exchandling.py
new file mode 100644
index 0000000..101fb7e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/exchandling.py
@@ -0,0 +1,100 @@
+"""
+Some utility classes for exception handling of exceptions raised
+within listeners:
+
+- TracebackInfo: convenient way of getting stack trace of latest
+ exception raised. The handler can create the instance to retrieve
+ the stack trace and then log it, present it to user, etc.
+- ExcPublisher: example handler that publishes a message containing
+ traceback info
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+
+"""
+
+
+import sys, traceback
+
+from ..core.listener import IListenerExcHandler
+
+
+class TracebackInfo:
+ """
+ Represent the traceback information for when an exception is
+ raised -- but not caught -- in a listener. The complete
+ traceback cannot be stored since this leads to circular
+ references (see docs for sys.exc_info()) which keeps
+ listeners alive even after the application is no longer
+ referring to them.
+
+ Instances of this object are given to listeners of the
+ 'uncaughtExcInListener' topic as the excTraceback kwarg.
+ The instance calls sys.exc_info() to get the traceback
+ info but keeps only the following info:
+
+ * self.ExcClass: the class of exception that was raised and not caught
+ * self.excArg: the argument given to exception when raised
+ * self.traceback: list of quadruples as returned by traceback.extract_tb()
+
+ Normally you just need to call one of the two getFormatted() methods.
+ """
+ def __init__(self):
+ tmpInfo = sys.exc_info()
+ self.ExcClass = tmpInfo[0]
+ self.excArg = tmpInfo[1]
+ # for the traceback, skip the first 3 entries, since they relate to
+ # implementation details for pubsub.
+ self.traceback = traceback.extract_tb(tmpInfo[2])[3:]
+ # help avoid circular refs
+ del tmpInfo
+
+ def getFormattedList(self):
+ """Get a list of strings as returned by the traceback module's
+ format_list() and format_exception_only() functions."""
+ tmp = traceback.format_list(self.traceback)
+ tmp.extend( traceback.format_exception_only(self.ExcClass, self.excArg) )
+ return tmp
+
+ def getFormattedString(self):
+ """Get a string similar to the stack trace that gets printed
+ to stdout by Python interpreter when an exception is not caught."""
+ return ''.join(self.getFormattedList())
+
+ def __str__(self):
+ return self.getFormattedString()
+
+
+class ExcPublisher(IListenerExcHandler):
+ """
+ Example exception handler that simply publishes the exception traceback
+ as a message of topic name given by topicUncaughtExc.
+ """
+
+ # name of the topic
+ topicUncaughtExc = 'uncaughtExcInListener'
+
+ def __init__(self, topicMgr=None):
+ """If topic manager is specified, will automatically call init().
+ Otherwise, caller must call init() after pubsub imported. See
+ pub.setListenerExcHandler()."""
+ if topicMgr is not None:
+ self.init(topicMgr)
+
+ def init(self, topicMgr):
+ """Must be called only after pubsub has been imported since this
+ handler creates a pubsub topic."""
+ obj = topicMgr.getOrCreateTopic(self.topicUncaughtExc)
+ obj.setDescription('generated when a listener raises an exception')
+ obj.setMsgArgSpec( dict(
+ listenerStr = 'string representation of listener',
+ excTraceback = 'instance of TracebackInfo containing exception info'))
+ self.__topicObj = obj
+
+ def __call__(self, listenerID, topicObj):
+ """Handle the exception raised by given listener. Send the
+ Traceback to all subscribers of topic self.topicUncaughtExc. """
+ tbInfo = TracebackInfo()
+ self.__topicObj.publish(listenerStr=listenerID, excTraceback=tbInfo)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/misc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/misc.py
new file mode 100644
index 0000000..6315a6d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/misc.py
@@ -0,0 +1,100 @@
+"""
+Provides useful functions and classes. Most useful are probably
+printTreeDocs and printTreeSpec.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+import sys
+from .. import py2and3
+
+__all__ = ('printImported', 'StructMsg', 'Callback', 'Enum' )
+
+
+def printImported():
+ """Output a list of pubsub modules imported so far"""
+ ll = [mod for mod in sys.modules.keys() if mod.find('pubsub') >= 0] # iter keys ok
+ ll.sort()
+ py2and3.print_('\n'.join(ll))
+
+
+class StructMsg:
+ """
+ This *can* be used to package message data. Each of the keyword
+ args given at construction will be stored as a member of the 'data'
+ member of instance. E.g. "m=Message2(a=1, b='b')" would succeed
+ "assert m.data.a==1" and "assert m.data.b=='b'". However, use of
+ Message2 makes your messaging code less documented and harder to
+ debug.
+ """
+
+ def __init__(self, **kwargs):
+ class Data: pass
+ self.data = Data()
+ self.data.__dict__.update(kwargs)
+
+
+class Callback:
+ """This can be used to wrap functions that are referenced by class
+ data if the data should be called as a function. E.g. given
+ >>> def func(): pass
+ >>> class A:
+ ....def __init__(self): self.a = func
+ then doing
+ >>> boo=A(); boo.a()
+ will fail since Python will try to call a() as a method of boo,
+ whereas a() is a free function. But if you have instead
+ "self.a = Callback(func)", then "boo.a()" works as expected.
+ """
+ def __init__(self, callable_):
+ self.__callable = callable_
+ def __call__(self, *args, **kwargs):
+ return self.__callable(*args, **kwargs)
+
+
+class Enum:
+ """Used only internally. Represent one value out of an enumeration
+ set. It is meant to be used as::
+
+ class YourAllowedValues:
+ enum1 = Enum()
+ # or:
+ enum2 = Enum(value)
+ # or:
+ enum3 = Enum(value, 'descriptionLine1')
+ # or:
+ enum3 = Enum(None, 'descriptionLine1', 'descriptionLine2', ...)
+
+ val = YourAllowedValues.enum1
+ ...
+ if val is YourAllowedValues.enum1:
+ ...
+ """
+ nextValue = 0
+ values = set()
+
+ def __init__(self, value=None, *desc):
+ """Use value if given, otherwise use next integer."""
+ self.desc = '\n'.join(desc)
+ if value is None:
+ assert Enum.nextValue not in Enum.values
+ self.value = Enum.nextValue
+ Enum.values.add(self.value)
+
+ Enum.nextValue += 1
+ # check that we haven't run out of integers!
+ if Enum.nextValue == 0:
+ raise RuntimeError('Ran out of enumeration values?')
+
+ else:
+ try:
+ value + Enum.nextValue
+ raise ValueError('Not allowed to assign integer to enumerations')
+ except TypeError:
+ pass
+ self.value = value
+ if self.value not in Enum.values:
+ Enum.values.add(self.value)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/notification.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/notification.py
new file mode 100644
index 0000000..1183473
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/notification.py
@@ -0,0 +1,331 @@
+"""
+Provide an interface class for handling pubsub notification messages,
+and an example class (though very useful in practice) showing how to
+use it.
+
+Notification messages are generated by pubsub
+
+- if a handler has been configured via pub.addNotificationHandler()
+- when pubsub does certain tasks, such as when a listener subscribes to
+ or unsubscribes from a topic
+
+Derive from this class to handle notification events from
+various parts of pubsub. E.g. when a listener subscribes,
+unsubscribes, or dies, a notification handler, if you
+specified one via pub.addNotificationHandler(), is given the
+relevant information.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from ..core import callables
+from ..core.notificationmgr import INotificationHandler
+
+
+class IgnoreNotificationsMixin(INotificationHandler):
+ """
+ Derive your Notifications handler from this class if your handler
+ just wants to be notified of one or two types of pubsub events.
+ Then just override the desired methods. The rest of the notifications
+ will automatically be ignored.
+ """
+
+ def notifySubscribe(self, pubListener, topicObj, newSub):
+ pass
+ def notifyUnsubscribe(self, pubListener, topicObj):
+ pass
+ def notifyDeadListener(self, pubListener, topicObj):
+ pass
+ def notifySend(self, stage, topicObj, pubListener=None):
+ pass
+
+ def notifyNewTopic(self, topicObj, description, required, argsDocs):
+ pass
+ def notifyDelTopic(self, topicName):
+ pass
+
+
+class NotifyByWriteFile(INotificationHandler):
+ """
+ Print a message to stdout when a notification is received.
+ """
+
+ defaultPrefix = 'PUBSUB:'
+
+ def __init__(self, fileObj = None, prefix = None):
+ """Will write to stdout unless fileObj given. Will use
+ defaultPrefix as prefix for each line output, unless prefix
+ specified. """
+ self.__pre = prefix or self.defaultPrefix
+
+ if fileObj is None:
+ import sys
+ self.__fileObj = sys.stdout
+ else:
+ self.__fileObj = fileObj
+
+ def changeFile(self, fileObj):
+ self.__fileObj = fileObj
+
+ def notifySubscribe(self, pubListener, topicObj, newSub):
+ if newSub:
+ msg = '%s Subscribed listener "%s" to topic "%s"\n'
+ else:
+ msg = '%s Subscription of "%s" to topic "%s" redundant\n'
+ msg = msg % (self.__pre, pubListener, topicObj.getName())
+ self.__fileObj.write(msg)
+
+ def notifyUnsubscribe(self, pubListener, topicObj):
+ msg = '%s Unsubscribed listener "%s" from topic "%s"\n'
+ msg = msg % (self.__pre, pubListener, topicObj.getName())
+ self.__fileObj.write(msg)
+
+ def notifyDeadListener(self, pubListener, topicObj):
+ msg = '%s Listener "%s" of Topic "%s" has died\n' \
+ % (self.__pre, pubListener, topicObj.getName())
+ # a bug apparently: sometimes on exit, the stream gets closed before
+ # and leads to a TypeError involving NoneType
+ self.__fileObj.write(msg)
+
+ def notifySend(self, stage, topicObj, pubListener=None):
+ if stage == 'in':
+ msg = '%s Sending message of topic "%s" to listener %s\n' % (self.__pre, topicObj.getName(), pubListener)
+ elif stage == 'pre':
+ msg = '%s Start sending message of topic "%s"\n' % (self.__pre, topicObj.getName())
+ else:
+ msg = '%s Done sending message of topic "%s"\n' % (self.__pre, topicObj.getName())
+ self.__fileObj.write(msg)
+
+ def notifyNewTopic(self, topicObj, description, required, argsDocs):
+ msg = '%s New topic "%s" created\n' % (self.__pre, topicObj.getName())
+ self.__fileObj.write(msg)
+
+ def notifyDelTopic(self, topicName):
+ msg = '%s Topic "%s" destroyed\n' % (self.__pre, topicName)
+ self.__fileObj.write(msg)
+
+
+class NotifyByPubsubMessage(INotificationHandler):
+ """
+ Handle pubsub notification messages by generating
+ messages of a 'pubsub.' subtopic. Also provides
+ an example of how to create a notification handler.
+
+ Use it by calling::
+
+ import pubsub.utils
+ pubsub.utils.useNotifyByPubsubMessage()
+ ...
+ pub.setNotificationFlags(...) # optional
+
+ E.g. whenever a listener is unsubscribed, a 'pubsub.unsubscribe'
+ message is generated. If you have subscribed a listener of
+ this topic, your listener will be notified of what listener
+ unsubscribed from what topic.
+ """
+
+ topicRoot = 'pubsub'
+
+ topics = dict(
+ send = '%s.sendMessage' % topicRoot,
+ subscribe = '%s.subscribe' % topicRoot,
+ unsubscribe = '%s.unsubscribe' % topicRoot,
+ newTopic = '%s.newTopic' % topicRoot,
+ delTopic = '%s.delTopic' % topicRoot,
+ deadListener = '%s.deadListener' % topicRoot)
+
+ def __init__(self, topicMgr=None):
+ self._pubTopic = None
+ self.__sending = False # used to guard against infinite loop
+ if topicMgr is not None:
+ self.createNotificationTopics(topicMgr)
+
+ def createNotificationTopics(self, topicMgr):
+ """Create the notification topics. The root of the topics created
+ is self.topicRoot. The topicMgr is (usually) pub.topicMgr."""
+ # see if the special topics have already been defined
+ try:
+ topicMgr.getTopic(self.topicRoot)
+
+ except ValueError:
+ # no, so create them
+ self._pubTopic = topicMgr.getOrCreateTopic(self.topicRoot)
+ self._pubTopic.setDescription('root of all pubsub-specific topics')
+
+ _createTopics(self.topics, topicMgr)
+
+ def notifySubscribe(self, pubListener, topicObj, newSub):
+ if (self._pubTopic is None) or self.__sending:
+ return
+
+ pubTopic = self._pubTopic.getSubtopic('subscribe')
+ if topicObj is not pubTopic:
+ kwargs = dict(listener=pubListener, topic=topicObj, newSub=newSub)
+ self.__doNotification(pubTopic, kwargs)
+
+ def notifyUnsubscribe(self, pubListener, topicObj):
+ if (self._pubTopic is None) or self.__sending:
+ return
+
+ pubTopic = self._pubTopic.getSubtopic('unsubscribe')
+ if topicObj is not pubTopic:
+ kwargs = dict(
+ topic = topicObj,
+ listenerRaw = pubListener.getCallable(),
+ listener = pubListener)
+ self.__doNotification(pubTopic, kwargs)
+
+ def notifyDeadListener(self, pubListener, topicObj):
+ if (self._pubTopic is None) or self.__sending:
+ return
+
+ pubTopic = self._pubTopic.getSubtopic('deadListener')
+ kwargs = dict(topic=topicObj, listener=pubListener)
+ self.__doNotification(pubTopic, kwargs)
+
+ def notifySend(self, stage, topicObj, pubListener=None):
+ """Stage must be 'pre' or 'post'. Note that any pubsub sendMessage
+ operation resulting from this notification (which sends a message;
+ listener could handle by sending another message!) will NOT themselves
+ lead to a send notification. """
+ if (self._pubTopic is None) or self.__sending:
+ return
+
+ sendMsgTopic = self._pubTopic.getSubtopic('sendMessage')
+ if stage == 'pre' and (topicObj is sendMsgTopic):
+ msg = 'Not allowed to send messages of topic %s' % topicObj.getName()
+ raise ValueError(msg)
+
+ self.__doNotification(sendMsgTopic, dict(topic=topicObj, stage=stage))
+
+ def notifyNewTopic(self, topicObj, desc, required, argsDocs):
+ if (self._pubTopic is None) or self.__sending:
+ return
+
+ pubTopic = self._pubTopic.getSubtopic('newTopic')
+ kwargs = dict(topic=topicObj, description=desc, required=required, args=argsDocs)
+ self.__doNotification(pubTopic, kwargs)
+
+ def notifyDelTopic(self, topicName):
+ if (self._pubTopic is None) or self.__sending:
+ return
+
+ pubTopic = self._pubTopic.getSubtopic('delTopic')
+ self.__doNotification(pubTopic, dict(name=topicName) )
+
+ def __doNotification(self, pubTopic, kwargs):
+ self.__sending = True
+ try:
+ pubTopic.publish( **kwargs )
+ finally:
+ self.__sending = False
+
+
+def _createTopics(topicMap, topicMgr):
+ """
+ Create notification topics. These are used when
+ some of the notification flags have been set to True (see
+ pub.setNotificationFlags(). The topicMap is a dict where key is
+ the notification type, and value is the topic name to create.
+ Notification type is a string in ('send', 'subscribe',
+ 'unsubscribe', 'newTopic', 'delTopic', 'deadListener'.
+ """
+ def newTopic(_name, _desc, _required=None, **argsDocs):
+ topic = topicMgr.getOrCreateTopic(_name)
+ topic.setDescription(_desc)
+ topic.setMsgArgSpec(argsDocs, _required)
+
+ newTopic(
+ _name = topicMap['subscribe'],
+ _desc = 'whenever a listener is subscribed to a topic',
+ topic = 'topic that listener has subscribed to',
+ listener = 'instance of pub.Listener containing listener',
+ newSub = 'false if listener was already subscribed, true otherwise')
+
+ newTopic(
+ _name = topicMap['unsubscribe'],
+ _desc = 'whenever a listener is unsubscribed from a topic',
+ topic = 'instance of Topic that listener has been unsubscribed from',
+ listener = 'instance of pub.Listener unsubscribed; None if listener not found',
+ listenerRaw = 'listener unsubscribed')
+
+ newTopic(
+ _name = topicMap['send'],
+ _desc = 'sent at beginning and end of sendMessage()',
+ topic = 'instance of topic for message being sent',
+ stage = 'stage of send operation: "pre" or "post" or "in"',
+ listener = 'which listener being sent to')
+
+ newTopic(
+ _name = topicMap['newTopic'],
+ _desc = 'whenever a new topic is defined',
+ topic = 'instance of Topic created',
+ description = 'description of topic (use)',
+ args = 'the argument names/descriptions for arguments that listeners must accept',
+ required = 'which args are required (all others are optional)')
+
+ newTopic(
+ _name = topicMap['delTopic'],
+ _desc = 'whenever a topic is deleted',
+ name = 'full name of the Topic instance that was destroyed')
+
+ newTopic(
+ _name = topicMap['deadListener'],
+ _desc = 'whenever a listener dies without having unsubscribed',
+ topic = 'instance of Topic that listener was subscribed to',
+ listener = 'instance of pub.Listener containing dead listener')
+
+
+def useNotifyByPubsubMessage(publisher=None, all=True, **kwargs):
+ """Will cause all of pubsub's notifications of pubsub "actions" (such as
+ new topic created, message sent, listener subscribed, etc) to be sent
+ out as messages. Topic will be 'pubsub' subtopics, such as
+ 'pubsub.newTopic', 'pubsub.delTopic', 'pubsub.sendMessage', etc.
+
+ The 'all' and kwargs args are the same as pubsub's setNotificationFlags(),
+ except that 'all' defaults to True.
+
+ The publisher is rarely needed:
+
+ * The publisher must be specfied if pubsub is not installed
+ on the system search path (ie from pubsub import ... would fail or
+ import wrong pubsub -- such as if pubsub is within wxPython's
+ wx.lib package). Then pbuModule is the pub module to use::
+
+ from wx.lib.pubsub import pub
+ from wx.lib.pubsub.utils import notification
+ notification.useNotifyByPubsubMessage()
+
+ """
+ if publisher is None:
+ from .. import pub
+ publisher = pub.getDefaultPublisher()
+ topicMgr = publisher.getTopicMgr()
+ notifHandler = NotifyByPubsubMessage( topicMgr )
+
+ publisher.addNotificationHandler(notifHandler)
+ publisher.setNotificationFlags(all=all, **kwargs)
+
+
+def useNotifyByWriteFile(fileObj=None, prefix=None,
+ publisher=None, all=True, **kwargs):
+ """Will cause all pubsub notifications of pubsub "actions" (such as
+ new topic created, message sent, listener died etc) to be written to
+ specified file (or stdout if none given). The fileObj need only
+ provide a 'write(string)' method.
+
+ The first two arguments are the same as those of NotifyByWriteFile
+ constructor. The 'all' and kwargs arguments are those of pubsub's
+ setNotificationFlags(), except that 'all' defaults to True. See
+ useNotifyByPubsubMessage() for an explanation of pubModule (typically
+ only if pubsub inside wxPython's wx.lib)"""
+ notifHandler = NotifyByWriteFile(fileObj, prefix)
+
+ if publisher is None:
+ from .. import pub
+ publisher = pub.getDefaultPublisher()
+ publisher.addNotificationHandler(notifHandler)
+ publisher.setNotificationFlags(all=all, **kwargs)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/topictreeprinter.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/topictreeprinter.py
new file mode 100644
index 0000000..1ff673a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/topictreeprinter.py
@@ -0,0 +1,195 @@
+"""
+Output various aspects of topic tree to string or file.
+
+:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+from textwrap import TextWrapper
+
+from ..core.topictreetraverser import (ITopicTreeVisitor, TopicTreeTraverser)
+
+
+class TopicTreePrinter(ITopicTreeVisitor):
+ """
+ Example topic tree visitor that prints a prettified representation
+ of topic tree by doing a depth-first traversal of topic tree and
+ print information at each (topic) node of tree. Extra info to be
+ printed is specified via the 'extra' kwarg. Its value must be a
+ list of characters, the order determines output order:
+ - D: print description of topic
+ - a: print kwarg names only
+ - A: print topic kwargs and their description
+ - L: print listeners currently subscribed to topic
+
+ E.g. TopicTreePrinter(extra='LaDA') would print, for each topic,
+ the list of subscribed listeners, the topic's list of kwargs, the
+ topic description, and the description for each kwarg,
+
+ >>> Topic "delTopic"
+ >> Listeners:
+ > listener1_2880 (from yourModule)
+ > listener2_3450 (from yourModule)
+ >> Names of Message arguments:
+ > arg1
+ > arg2
+ >> Description: whenever a topic is deleted
+ >> Descriptions of Message arguments:
+ > arg1: (required) its description
+ > arg2: some other description
+
+ """
+
+ allowedExtras = frozenset('DAaL') # must NOT change
+ ALL_TOPICS_NAME = 'ALL_TOPICS' # output for name of 'all topics' topic
+
+ def __init__(self, extra=None, width=70, indentStep=4,
+ bulletTopic='\\--', bulletTopicItem='|==', bulletTopicArg='-', fileObj=None):
+ """Topic tree printer will print listeners for each topic only
+ if printListeners is True. The width will be used to limit
+ the width of text output, while indentStep is the number of
+ spaces added each time the text is indented further. The
+ three bullet parameters define the strings used for each
+ item (topic, topic items, and kwargs). """
+ self.__contentMeth = dict(
+ D = self.__printTopicDescription,
+ A = self.__printTopicArgsAll,
+ a = self.__printTopicArgNames,
+ L = self.__printTopicListeners)
+ assert self.allowedExtras == set(self.__contentMeth.keys())
+ import sys
+ self.__destination = fileObj or sys.stdout
+ self.__output = []
+
+ self.__content = extra or ''
+ unknownSel = set(self.__content) - self.allowedExtras
+ if unknownSel:
+ msg = 'These extra chars not known: %s' % ','.join(unknownSel)
+ raise ValueError(msg)
+
+ self.__width = width
+ self.__wrapper = TextWrapper(width)
+ self.__indent = 0
+ self.__indentStep = indentStep
+ self.__topicsBullet = bulletTopic
+ self.__topicItemsBullet = bulletTopicItem
+ self.__topicArgsBullet = bulletTopicArg
+
+ def getOutput(self):
+ return '\n'.join( self.__output )
+
+ def _doneTraversal(self):
+ if self.__destination is not None:
+ self.__destination.write(self.getOutput())
+
+ def _onTopic(self, topicObj):
+ """This gets called for each topic. Print as per specified content."""
+
+ # topic name
+ self.__wrapper.width = self.__width
+ indent = self.__indent
+ if topicObj.isAll():
+ topicName = self.ALL_TOPICS_NAME
+ else:
+ topicName = topicObj.getNodeName()
+ head = '%s Topic "%s"' % (self.__topicsBullet, topicName)
+ self.__output.append( self.__formatDefn(indent, head) )
+ indent += self.__indentStep
+
+ # each extra content (assume constructor verified that chars are valid)
+ for item in self.__content:
+ function = self.__contentMeth[item]
+ function(indent, topicObj)
+
+ def _startChildren(self):
+ """Increase the indent"""
+ self.__indent += self.__indentStep
+
+ def _endChildren(self):
+ """Decrease the indent"""
+ self.__indent -= self.__indentStep
+
+ def __formatDefn(self, indent, item, defn='', sep=': '):
+ """Print a definition: a block of text at a certain indent,
+ has item name, and an optional definition separated from
+ item by sep. """
+ if defn:
+ prefix = '%s%s%s' % (' '*indent, item, sep)
+ self.__wrapper.initial_indent = prefix
+ self.__wrapper.subsequent_indent = ' '*(indent+self.__indentStep)
+ return self.__wrapper.fill(defn)
+ else:
+ return '%s%s' % (' '*indent, item)
+
+ def __printTopicDescription(self, indent, topicObj):
+ # topic description
+ defn = '%s Description' % self.__topicItemsBullet
+ self.__output.append(
+ self.__formatDefn(indent, defn, topicObj.getDescription()) )
+
+ def __printTopicArgsAll(self, indent, topicObj, desc=True):
+ # topic kwargs
+ args = topicObj.getArgDescriptions()
+ if args:
+ #required, optional, complete = topicObj.getArgs()
+ headName = 'Names of Message arguments:'
+ if desc:
+ headName = 'Descriptions of message arguments:'
+ head = '%s %s' % (self.__topicItemsBullet, headName)
+ self.__output.append( self.__formatDefn(indent, head) )
+ tmpIndent = indent + self.__indentStep
+ required = topicObj.getArgs()[0]
+ for key, arg in args.items(): # iter in 3, list in 2 ok
+ if not desc:
+ arg = ''
+ elif key in required:
+ arg = '(required) %s' % arg
+ msg = '%s %s' % (self.__topicArgsBullet,key)
+ self.__output.append( self.__formatDefn(tmpIndent, msg, arg) )
+
+ def __printTopicArgNames(self, indent, topicObj):
+ self.__printTopicArgsAll(indent, topicObj, False)
+
+ def __printTopicListeners(self, indent, topicObj):
+ if topicObj.hasListeners():
+ item = '%s Listeners:' % self.__topicItemsBullet
+ self.__output.append( self.__formatDefn(indent, item) )
+ tmpIndent = indent + self.__indentStep
+ for listener in topicObj.getListenersIter():
+ item = '%s %s (from %s)' % (self.__topicArgsBullet, listener.name(), listener.module())
+ self.__output.append( self.__formatDefn(tmpIndent, item) )
+
+
+def printTreeDocs(rootTopic=None, topicMgr=None, **kwargs):
+ """Print out the topic tree to a file (or file-like object like a
+ StringIO), starting at rootTopic. If root topic should be root of
+ whole tree, get it from pub.getDefaultTopicTreeRoot().
+ The treeVisitor is an instance of pub.TopicTreeTraverser.
+
+ Printing the tree docs would normally involve this::
+
+ from pubsub import pub
+ from pubsub.utils.topictreeprinter import TopicTreePrinter
+ traverser = pub.TopicTreeTraverser( TopicTreePrinter(**kwargs) )
+ traverser.traverse( pub.getDefaultTopicTreeRoot() )
+
+ With printTreeDocs, it looks like this::
+
+ from pubsub import pub
+ from pubsub.utils import printTreeDocs
+ printTreeDocs()
+
+ The kwargs are the same as for TopicTreePrinter constructor:
+ extra(None), width(70), indentStep(4), bulletTopic, bulletTopicItem,
+ bulletTopicArg, fileObj(stdout). If fileObj not given, stdout is used."""
+ if rootTopic is None:
+ if topicMgr is None:
+ from .. import pub
+ topicMgr = pub.getDefaultTopicMgr()
+ rootTopic = topicMgr.getRootAllTopics()
+
+ printer = TopicTreePrinter(**kwargs)
+ traverser = TopicTreeTraverser(printer)
+ traverser.traverse(rootTopic)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/xmltopicdefnprovider.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/xmltopicdefnprovider.py
new file mode 100644
index 0000000..19f4200
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pubsub/utils/xmltopicdefnprovider.py
@@ -0,0 +1,286 @@
+"""
+Contributed by Joshua R English, adapted by Oliver Schoenborn to be
+consistent with pubsub API.
+
+An extension for pubsub (http://pubsub.sourceforge.net) so topic tree
+specification can be encoded in XML format rather than pubsub's default
+Python nested class format.
+
+To use:
+
+ xml = '''
+ <topicdefntree>
+ <description>Test showing topic hierarchy and inheritance</description>
+ <topic id="parent">
+ <description>Parent with a parameter and subtopics</description>
+ <listenerspec>
+ <arg id="name" optional="true">given name</arg>
+ <arg id="lastname">surname</arg>
+ </listenerspec>
+
+ <topic id="child">
+ <description>This is the first child</description>
+ <listenerspec>
+ <arg id="nick">A nickname</arg>
+ </listenerspec>
+ </topic>
+ </topic>
+ </topicdefntree>
+ '''
+
+These topic definitions are loaded through an XmlTopicDefnProvider:
+
+ pub.addTopicDefnProvider( XmlTopicDefnProvider(xml) )
+
+The XmlTopicDefnProvider also accepts a filename instead of XML string:
+
+ provider = XmlTopicDefnProvider("path/to/XMLfile.xml", TOPIC_TREE_FROM_FILE)
+ pub.addTopicDefnProvider( provider )
+
+Topics can be exported to an XML file using the exportTopicTreeSpecXml function.
+This will create a text file for the XML and return the string representation
+of the XML tree.
+
+:copyright: Copyright since 2013 by Oliver Schoenborn, all rights reserved.
+:license: BSD, see LICENSE_BSD_Simple.txt for details.
+"""
+
+__author__ = 'Joshua R English'
+__revision__ = 6
+__date__ = '2013-07-27'
+
+
+from ..core.topictreetraverser import ITopicTreeVisitor
+from ..core.topicdefnprovider import (
+ ITopicDefnProvider,
+ ArgSpecGiven,
+ TOPIC_TREE_FROM_STRING,
+ )
+from .. import py2and3
+
+try:
+ from elementtree import ElementTree as ET
+except ImportError:
+ try: # for Python 2.4, must use cElementTree:
+ from xml.etree import ElementTree as ET
+ except ImportError:
+ from cElementTree import ElementTree as ET
+
+__all__ = [
+ 'XmlTopicDefnProvider',
+ 'exportTopicTreeSpecXml',
+ 'TOPIC_TREE_FROM_FILE'
+ ]
+
+
+def _get_elem(elem):
+ """Assume an ETree.Element object or a string representation.
+ Return the ETree.Element object"""
+ if not ET.iselement(elem):
+ try:
+ elem = ET.fromstring(elem)
+ except:
+ py2and3.print_("Value Error", elem)
+ raise ValueError("Cannot convert to element")
+ return elem
+
+
+TOPIC_TREE_FROM_FILE = 'file'
+
+
+class XmlTopicDefnProvider(ITopicDefnProvider):
+
+ class XmlParserError(RuntimeError): pass
+
+ class UnrecognizedSourceFormatError(ValueError): pass
+
+ def __init__(self, xml, format=TOPIC_TREE_FROM_STRING):
+ self._topics = {}
+ self._treeDoc = ''
+ if format == TOPIC_TREE_FROM_FILE:
+ self._parse_tree(_get_elem(open(xml,mode="r").read()))
+ elif format == TOPIC_TREE_FROM_STRING:
+ self._parse_tree(_get_elem(xml))
+ else:
+ raise UnrecognizedSourceFormatError()
+
+ def _parse_tree(self, tree):
+ doc_node = tree.find('description')
+
+ if doc_node is None:
+ self._treeDoc = "UNDOCUMENTED"
+ else:
+ self._treeDoc = ' '.join(doc_node.text.split())
+
+ for node in tree.findall('topic'):
+ self._parse_topic(node)
+
+ def _parse_topic(self, node, parents=None, specs=None, reqlist=None):
+ parents = parents or []
+ specs = specs or {}
+ reqlist = reqlist or []
+
+ descNode = node.find('description')
+
+ if descNode is None:
+ desc = "UNDOCUMENTED"
+ else:
+ desc = ' '.join(descNode.text.split())
+
+ node_id = node.get('id')
+ if node_id is None:
+ raise XmlParserError("topic element must have an id attribute")
+
+ for this in (node.findall('listenerspec/arg')):
+ this_id = this.get('id')
+ if this_id is None:
+ raise XmlParserError("arg element must have an id attribute")
+
+ this_desc = this.text.strip()
+ this_desc = this_desc or "UNDOCUMENTED"
+ this_desc = ' '.join(this_desc.split())
+
+ specs[this_id] = this_desc
+
+ if this.get('optional', '').lower() not in ['true', 't','yes','y']:
+ reqlist.append(this_id)
+
+ defn = ArgSpecGiven(specs, tuple(reqlist))
+
+ parents.append(node.get('id'))
+
+ self._topics[tuple(parents)] = desc, defn
+
+ for subtopic in node.findall('topic'):
+ self._parse_topic(subtopic, parents[:], specs.copy(), reqlist[:])
+
+
+ def getDefn(self, topicNameTuple):
+ return self._topics.get(topicNameTuple, (None, None))
+
+ def topicNames(self):
+ return py2and3.iterkeys(self._topics) # dict_keys iter in 3, list in 2
+
+ def getTreeDoc(self):
+ return self._treeDoc
+
+
+class XmlVisitor(ITopicTreeVisitor):
+ def __init__(self, elem):
+ self.tree = elem
+ self.known_topics = []
+
+ def _startTraversal(self):
+ self.roots = [self.tree]
+
+ def _onTopic(self, topicObj):
+ if topicObj.isAll():
+ self.last_elem = self.tree
+ return
+ if self.roots:
+ this_elem = ET.SubElement(self.roots[-1], 'topic',
+ {'id':topicObj.getNodeName()})
+ else:
+ this_elem = ET.Element('topic', {'id':topicObj.getNodeName()})
+ req, opt = topicObj.getArgs()
+ req = req or ()
+ opt = opt or ()
+ desc_elem = ET.SubElement(this_elem, 'description')
+ topicDesc = topicObj.getDescription()
+ if topicDesc:
+ desc_elem.text = ' '.join(topicDesc.split())
+ else:
+ desc_elem.text = "UNDOCUMENTED"
+ argDescriptions = topicObj.getArgDescriptions()
+
+ # pubsub way of getting known_args
+ known_args = []
+ parent = topicObj.getParent()
+ while parent:
+ if parent in self.known_topics:
+ p_req, p_opt = parent.getArgs()
+ if p_req:
+ known_args.extend(p_req)
+ if p_opt:
+ known_args.extend(p_opt)
+ parent = parent.getParent()
+
+ # there is probably a cleaner way to do this
+ if req or opt:
+ spec = ET.SubElement(this_elem, 'listenerspec')
+ for arg in req:
+ if arg in known_args:
+ continue
+ arg_elem = ET.SubElement(spec, 'arg', {'id': arg})
+ arg_elem.text = ' '.join(argDescriptions.get(arg, 'UNDOCUMENTED').split())
+ for arg in opt:
+ if arg in known_args:
+ continue
+ arg_elem = ET.SubElement(spec, 'arg', {'id': arg, 'optional':'True'})
+ arg_elem.text = ' '.join(argDescriptions.get(arg, 'UNDOCUMENTED').split())
+
+ self.last_elem = this_elem
+ self.known_topics.append(topicObj)
+
+ def _startChildren(self):
+ self.roots.append(self.last_elem)
+
+ def _endChildren(self):
+ self.roots.pop()
+
+
+## http://infix.se/2007/02/06/gentlemen-indent-your-xml
+def indent(elem, level=0):
+ i = "\n" + level*" "
+ if len(elem):
+ if not elem.text or not elem.text.strip():
+ elem.text = i + " "
+ for e in elem:
+ indent(e, level+1)
+ if not e.tail or not e.tail.strip():
+ e.tail = i + " "
+ if not e.tail or not e.tail.strip():
+ e.tail = i
+ else:
+ if level and (not elem.tail or not elem.tail.strip()):
+ elem.tail = i
+ else:
+ elem.tail="\n"
+
+
+def exportTopicTreeSpecXml(moduleName=None, rootTopic=None, bak='bak', moduleDoc=None):
+ """
+ If rootTopic is None, then pub.getDefaultTopicTreeRoot() is assumed.
+ """
+
+ if rootTopic is None:
+ from .. import pub
+ rootTopic = pub.getDefaultTopicTreeRoot()
+ elif py2and3.isstring(rootTopic):
+ from .. import pub
+ rootTopic = pub.getTopic(rootTopic)
+
+ tree = ET.Element('topicdefntree')
+ if moduleDoc:
+ mod_desc = ET.SubElement(tree, 'description')
+ mod_desc.text = ' '.join(moduleDoc.split())
+
+ traverser = pub.TopicTreeTraverser(XmlVisitor(tree))
+ traverser.traverse(rootTopic)
+
+ indent(tree)
+
+ if moduleName:
+
+ filename = '%s.xml' % moduleName
+ if bak:
+ pub._backupIfExists(filename, bak)
+
+ fulltree= ET.ElementTree(tree)
+ fulltree.write(filename, "utf-8", True)
+
+ return ET.tostring(tree)
+
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pydocview.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pydocview.py
new file mode 100644
index 0000000..7e12918
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pydocview.py
@@ -0,0 +1,3298 @@
+#----------------------------------------------------------------------------
+# Name: pydocview.py
+# Purpose: Python extensions to the wxWindows docview framework
+#
+# Author: Peter Yared, Morgan Hua, Matt Fryer
+#
+# Created: 5/15/03
+# CVS-ID: $Id$
+# Copyright: (c) 2003-2006 ActiveGrid, Inc.
+# License: wxWindows license
+#----------------------------------------------------------------------------
+
+
+import wx
+import wx.lib.docview
+import sys
+import getopt
+from wx.lib.rcsizer import RowColSizer
+import os
+import os.path
+import time
+import string
+import pickle
+import tempfile
+import mmap
+_ = wx.GetTranslation
+if wx.Platform == '__WXMSW__':
+ _WINDOWS = True
+else:
+ _WINDOWS = False
+
+#----------------------------------------------------------------------------
+# Constants
+#----------------------------------------------------------------------------
+
+VIEW_TOOLBAR_ID = wx.NewId()
+VIEW_STATUSBAR_ID = wx.NewId()
+
+EMBEDDED_WINDOW_TOP = 1
+EMBEDDED_WINDOW_BOTTOM = 2
+EMBEDDED_WINDOW_LEFT = 4
+EMBEDDED_WINDOW_RIGHT = 8
+EMBEDDED_WINDOW_TOPLEFT = 16
+EMBEDDED_WINDOW_BOTTOMLEFT = 32
+EMBEDDED_WINDOW_TOPRIGHT = 64
+EMBEDDED_WINDOW_BOTTOMRIGHT = 128
+EMBEDDED_WINDOW_ALL = EMBEDDED_WINDOW_TOP | EMBEDDED_WINDOW_BOTTOM | EMBEDDED_WINDOW_LEFT | EMBEDDED_WINDOW_RIGHT | \
+ EMBEDDED_WINDOW_TOPLEFT | EMBEDDED_WINDOW_BOTTOMLEFT | EMBEDDED_WINDOW_TOPRIGHT | EMBEDDED_WINDOW_BOTTOMRIGHT
+
+SAVEALL_ID = wx.NewId()
+
+WINDOW_MENU_NUM_ITEMS = 9
+
+
+class DocFrameMixIn:
+ """
+ Class with common code used by DocMDIParentFrame, DocTabbedParentFrame, and
+ DocSDIFrame.
+ """
+
+
+ def GetDocumentManager(self):
+ """
+ Returns the document manager associated with the DocMDIParentFrame.
+ """
+ return self._docManager
+
+
+ def InitializePrintData(self):
+ """
+ Initializes the PrintData that is used when printing.
+ """
+ self._printData = wx.PrintData()
+ self._printData.SetPaperId(wx.PAPER_LETTER)
+
+
+ def CreateDefaultMenuBar(self, sdi=False):
+ """
+ Creates the default MenuBar. Contains File, Edit, View, Tools, and Help menus.
+ """
+ menuBar = wx.MenuBar()
+
+ fileMenu = wx.Menu()
+ fileMenu.Append(wx.ID_NEW, _("&New...\tCtrl+N"), _("Creates a new document"))
+ fileMenu.Append(wx.ID_OPEN, _("&Open...\tCtrl+O"), _("Opens an existing document"))
+ fileMenu.Append(wx.ID_CLOSE, _("&Close"), _("Closes the active document"))
+ if not sdi:
+ fileMenu.Append(wx.ID_CLOSE_ALL, _("Close A&ll"), _("Closes all open documents"))
+ fileMenu.AppendSeparator()
+ fileMenu.Append(wx.ID_SAVE, _("&Save\tCtrl+S"), _("Saves the active document"))
+ fileMenu.Append(wx.ID_SAVEAS, _("Save &As..."), _("Saves the active document with a new name"))
+ fileMenu.Append(SAVEALL_ID, _("Save All\tCtrl+Shift+A"), _("Saves the all active documents"))
+ wx.EVT_MENU(self, SAVEALL_ID, self.ProcessEvent)
+ wx.EVT_UPDATE_UI(self, SAVEALL_ID, self.ProcessUpdateUIEvent)
+ fileMenu.AppendSeparator()
+ fileMenu.Append(wx.ID_PRINT, _("&Print\tCtrl+P"), _("Prints the active document"))
+ fileMenu.Append(wx.ID_PREVIEW, _("Print Pre&view"), _("Displays full pages"))
+ fileMenu.Append(wx.ID_PRINT_SETUP, _("Page Set&up"), _("Changes page layout settings"))
+ fileMenu.AppendSeparator()
+ if wx.Platform == '__WXMAC__':
+ fileMenu.Append(wx.ID_EXIT, _("&Quit"), _("Closes this program"))
+ else:
+ fileMenu.Append(wx.ID_EXIT, _("E&xit"), _("Closes this program"))
+ self._docManager.FileHistoryUseMenu(fileMenu)
+ self._docManager.FileHistoryAddFilesToMenu()
+ menuBar.Append(fileMenu, _("&File"));
+
+ editMenu = wx.Menu()
+ editMenu.Append(wx.ID_UNDO, _("&Undo\tCtrl+Z"), _("Reverses the last action"))
+ editMenu.Append(wx.ID_REDO, _("&Redo\tCtrl+Y"), _("Reverses the last undo"))
+ editMenu.AppendSeparator()
+ #item = wxMenuItem(self.editMenu, wxID_CUT, _("Cu&t\tCtrl+X"), _("Cuts the selection and puts it on the Clipboard"))
+ #item.SetBitmap(getCutBitmap())
+ #editMenu.AppendItem(item)
+ editMenu.Append(wx.ID_CUT, _("Cu&t\tCtrl+X"), _("Cuts the selection and puts it on the Clipboard"))
+ wx.EVT_MENU(self, wx.ID_CUT, self.ProcessEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_CUT, self.ProcessUpdateUIEvent)
+ editMenu.Append(wx.ID_COPY, _("&Copy\tCtrl+C"), _("Copies the selection and puts it on the Clipboard"))
+ wx.EVT_MENU(self, wx.ID_COPY, self.ProcessEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_COPY, self.ProcessUpdateUIEvent)
+ editMenu.Append(wx.ID_PASTE, _("&Paste\tCtrl+V"), _("Inserts Clipboard contents"))
+ wx.EVT_MENU(self, wx.ID_PASTE, self.ProcessEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PASTE, self.ProcessUpdateUIEvent)
+ editMenu.Append(wx.ID_CLEAR, _("&Delete"), _("Erases the selection"))
+ wx.EVT_MENU(self, wx.ID_CLEAR, self.ProcessEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLEAR, self.ProcessUpdateUIEvent)
+ editMenu.AppendSeparator()
+ editMenu.Append(wx.ID_SELECTALL, _("Select A&ll\tCtrl+A"), _("Selects all available data"))
+ wx.EVT_MENU(self, wx.ID_SELECTALL, self.ProcessEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_SELECTALL, self.ProcessUpdateUIEvent)
+ menuBar.Append(editMenu, _("&Edit"))
+ if sdi:
+ if self.GetDocument() and self.GetDocument().GetCommandProcessor():
+ self.GetDocument().GetCommandProcessor().SetEditMenu(editMenu)
+
+ viewMenu = wx.Menu()
+ viewMenu.AppendCheckItem(VIEW_TOOLBAR_ID, _("&Toolbar"), _("Shows or hides the toolbar"))
+ wx.EVT_MENU(self, VIEW_TOOLBAR_ID, self.OnViewToolBar)
+ wx.EVT_UPDATE_UI(self, VIEW_TOOLBAR_ID, self.OnUpdateViewToolBar)
+ viewMenu.AppendCheckItem(VIEW_STATUSBAR_ID, _("&Status Bar"), _("Shows or hides the status bar"))
+ wx.EVT_MENU(self, VIEW_STATUSBAR_ID, self.OnViewStatusBar)
+ wx.EVT_UPDATE_UI(self, VIEW_STATUSBAR_ID, self.OnUpdateViewStatusBar)
+ menuBar.Append(viewMenu, _("&View"))
+
+ helpMenu = wx.Menu()
+ helpMenu.Append(wx.ID_ABOUT, _("&About" + " " + wx.GetApp().GetAppName()), _("Displays program information, version number, and copyright"))
+ menuBar.Append(helpMenu, _("&Help"))
+
+ wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
+ wx.EVT_UPDATE_UI(self, wx.ID_ABOUT, self.ProcessUpdateUIEvent) # Using ID_ABOUT to update the window menu, the window menu items are not triggering
+
+ if sdi: # TODO: Is this really needed?
+ wx.EVT_COMMAND_FIND_CLOSE(self, -1, self.ProcessEvent)
+
+ return menuBar
+
+
+ def CreateDefaultStatusBar(self):
+ """
+ Creates the default StatusBar.
+ """
+ wx.Frame.CreateStatusBar(self)
+ self.GetStatusBar().Show(wx.ConfigBase_Get().ReadInt("ViewStatusBar", True))
+ self.UpdateStatus()
+ return self.GetStatusBar()
+
+
+ def CreateDefaultToolBar(self):
+ """
+ Creates the default ToolBar.
+ """
+ self._toolBar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT)
+ self._toolBar.AddSimpleTool(wx.ID_NEW, New.GetBitmap(), _("New"), _("Creates a new document"))
+ self._toolBar.AddSimpleTool(wx.ID_OPEN, Open.GetBitmap(), _("Open"), _("Opens an existing document"))
+ self._toolBar.AddSimpleTool(wx.ID_SAVE, Save.GetBitmap(), _("Save"), _("Saves the active document"))
+ self._toolBar.AddSimpleTool(SAVEALL_ID, SaveAll.GetBitmap(), _("Save All"), _("Saves all the active documents"))
+ self._toolBar.AddSeparator()
+ self._toolBar.AddSimpleTool(wx.ID_PRINT, Print.GetBitmap(), _("Print"), _("Displays full pages"))
+ self._toolBar.AddSimpleTool(wx.ID_PREVIEW, PrintPreview.GetBitmap(), _("Print Preview"), _("Prints the active document"))
+ self._toolBar.AddSeparator()
+ self._toolBar.AddSimpleTool(wx.ID_CUT, Cut.GetBitmap(), _("Cut"), _("Cuts the selection and puts it on the Clipboard"))
+ self._toolBar.AddSimpleTool(wx.ID_COPY, Copy.GetBitmap(), _("Copy"), _("Copies the selection and puts it on the Clipboard"))
+ self._toolBar.AddSimpleTool(wx.ID_PASTE, Paste.GetBitmap(), _("Paste"), _("Inserts Clipboard contents"))
+ self._toolBar.AddSimpleTool(wx.ID_UNDO, Undo.GetBitmap(), _("Undo"), _("Reverses the last action"))
+ self._toolBar.AddSimpleTool(wx.ID_REDO, Redo.GetBitmap(), _("Redo"), _("Reverses the last undo"))
+ self._toolBar.Realize()
+ self._toolBar.Show(wx.ConfigBase_Get().ReadInt("ViewToolBar", True))
+
+ return self._toolBar
+
+
+ def OnFileSaveAll(self, event):
+ """
+ Saves all of the currently open documents.
+ """
+ docs = wx.GetApp().GetDocumentManager().GetDocuments()
+
+ # save child documents first
+ for doc in docs:
+ if isinstance(doc, wx.lib.pydocview.ChildDocument):
+ doc.Save()
+
+ # save parent and other documents later
+ for doc in docs:
+ if not isinstance(doc, wx.lib.pydocview.ChildDocument):
+ doc.Save()
+
+
+ def OnAbout(self, event):
+ """
+ Invokes the about dialog.
+ """
+ aboutService = wx.GetApp().GetService(AboutService)
+ if aboutService:
+ aboutService.ShowAbout()
+
+
+ def OnViewToolBar(self, event):
+ """
+ Toggles whether the ToolBar is visible.
+ """
+ self._toolBar.Show(not self._toolBar.IsShown())
+ self._LayoutFrame()
+
+
+ def OnUpdateViewToolBar(self, event):
+ """
+ Updates the View ToolBar menu item.
+ """
+ event.Check(self.GetToolBar().IsShown())
+
+
+ def OnViewStatusBar(self, event):
+ """
+ Toggles whether the StatusBar is visible.
+ """
+ self.GetStatusBar().Show(not self.GetStatusBar().IsShown())
+ self._LayoutFrame()
+
+
+ def OnUpdateViewStatusBar(self, event):
+ """
+ Updates the View StatusBar menu item.
+ """
+ event.Check(self.GetStatusBar().IsShown())
+
+
+ def UpdateStatus(self, message = _("Ready")):
+ """
+ Updates the StatusBar.
+ """
+ # wxBug: Menubar and toolbar help strings don't pop the status text back
+ if self.GetStatusBar().GetStatusText() != message:
+ self.GetStatusBar().PushStatusText(message)
+
+
+class DocMDIParentFrameMixIn:
+ """
+ Class with common code used by DocMDIParentFrame and DocTabbedParentFrame.
+ """
+
+
+ def _GetPosSizeFromConfig(self, pos, size):
+ """
+ Adjusts the position and size of the frame using the saved config position and size.
+ """
+ config = wx.ConfigBase_Get()
+ if pos == wx.DefaultPosition and size == wx.DefaultSize and config.ReadInt("MDIFrameMaximized", False):
+ pos = [0, 0]
+ size = wx.DisplaySize()
+ # wxBug: Need to set to fill screen to get around bug where maximize is leaving shadow of statusbar, check out maximize call at end of this function
+ else:
+ if pos == wx.DefaultPosition:
+ pos = config.ReadInt("MDIFrameXLoc", -1), config.ReadInt("MDIFrameYLoc", -1)
+
+ if wx.Display_GetFromPoint(pos) == -1: # Check if the frame position is offscreen
+ pos = wx.DefaultPosition
+
+ if size == wx.DefaultSize:
+ size = wx.Size(config.ReadInt("MDIFrameXSize", 450), config.ReadInt("MDIFrameYSize", 300))
+ return pos, size
+
+
+ def _InitFrame(self, embeddedWindows, minSize):
+ """
+ Initializes the frame and creates the default menubar, toolbar, and status bar.
+ """
+ self._embeddedWindows = []
+ self.SetDropTarget(_DocFrameFileDropTarget(self._docManager, self))
+
+ if wx.GetApp().GetDefaultIcon():
+ self.SetIcon(wx.GetApp().GetDefaultIcon())
+
+ wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
+ wx.EVT_SIZE(self, self.OnSize)
+
+ self.InitializePrintData()
+
+ toolBar = self.CreateDefaultToolBar()
+ self.SetToolBar(toolBar)
+ menuBar = self.CreateDefaultMenuBar()
+ statusBar = self.CreateDefaultStatusBar()
+
+ config = wx.ConfigBase_Get()
+ if config.ReadInt("MDIFrameMaximized", False):
+ # wxBug: On maximize, statusbar leaves a residual that needs to be refereshed, happens even when user does it
+ self.Maximize()
+
+ self.CreateEmbeddedWindows(embeddedWindows, minSize)
+ self._LayoutFrame()
+
+ if wx.Platform == '__WXMAC__':
+ self.SetMenuBar(menuBar) # wxBug: Have to set the menubar at the very end or the automatic MDI "window" menu doesn't get put in the right place when the services add new menus to the menubar
+
+ wx.GetApp().SetTopWindow(self) # Need to do this here in case the services are looking for wx.GetApp().GetTopWindow()
+ for service in wx.GetApp().GetServices():
+ service.InstallControls(self, menuBar = menuBar, toolBar = toolBar, statusBar = statusBar)
+ if hasattr(service, "ShowWindow"):
+ service.ShowWindow() # instantiate service windows for correct positioning, we'll hide/show them later based on user preference
+
+ if wx.Platform != '__WXMAC__':
+ self.SetMenuBar(menuBar) # wxBug: Have to set the menubar at the very end or the automatic MDI "window" menu doesn't get put in the right place when the services add new menus to the menubar
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ id = event.GetId()
+ if id == SAVEALL_ID:
+ self.OnFileSaveAll(event)
+ return True
+
+ return wx.GetApp().ProcessEvent(event)
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ id = event.GetId()
+ if id == wx.ID_CUT:
+ event.Enable(False)
+ return True
+ elif id == wx.ID_COPY:
+ event.Enable(False)
+ return True
+ elif id == wx.ID_PASTE:
+ event.Enable(False)
+ return True
+ elif id == wx.ID_CLEAR:
+ event.Enable(False)
+ return True
+ elif id == wx.ID_SELECTALL:
+ event.Enable(False)
+ return True
+ elif id == SAVEALL_ID:
+ filesModified = False
+ docs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for doc in docs:
+ if doc.IsModified():
+ filesModified = True
+ break
+
+ event.Enable(filesModified)
+ return True
+ else:
+ return wx.GetApp().ProcessUpdateUIEvent(event)
+
+
+ def CreateEmbeddedWindows(self, windows=0, minSize=20):
+ """
+ Create the specified embedded windows around the edges of the frame.
+ """
+ frameSize = self.GetSize() # TODO: GetClientWindow.GetSize is still returning 0,0 since the frame isn't fully constructed yet, so using full frame size
+ defaultHSize = max(minSize, int(frameSize[0] / 6))
+ defaultVSize = max(minSize, int(frameSize[1] / 7))
+ defaultSubVSize = int(frameSize[1] / 2)
+ config = wx.ConfigBase_Get()
+ if windows & (EMBEDDED_WINDOW_LEFT | EMBEDDED_WINDOW_TOPLEFT | EMBEDDED_WINDOW_BOTTOMLEFT):
+ self._leftEmbWindow = self._CreateEmbeddedWindow(self, (max(minSize,config.ReadInt("MDIEmbedLeftSize", defaultHSize)), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_LEFT, visible = config.ReadInt("MDIEmbedLeftVisible", 1), sash = wx.SASH_RIGHT)
+ else:
+ self._leftEmbWindow = None
+ if windows & EMBEDDED_WINDOW_TOPLEFT:
+ self._topLeftEmbWindow = self._CreateEmbeddedWindow(self._leftEmbWindow, (-1, config.ReadInt("MDIEmbedTopLeftSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopLeftVisible", 1), sash = wx.SASH_BOTTOM)
+ else:
+ self._topLeftEmbWindow = None
+ if windows & EMBEDDED_WINDOW_BOTTOMLEFT:
+ self._bottomLeftEmbWindow = self._CreateEmbeddedWindow(self._leftEmbWindow, (-1, config.ReadInt("MDIEmbedBottomLeftSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomLeftVisible", 1))
+ else:
+ self._bottomLeftEmbWindow = None
+ if windows & (EMBEDDED_WINDOW_RIGHT | EMBEDDED_WINDOW_TOPRIGHT | EMBEDDED_WINDOW_BOTTOMRIGHT):
+ self._rightEmbWindow = self._CreateEmbeddedWindow(self, (max(minSize,config.ReadInt("MDIEmbedRightSize", defaultHSize)), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_RIGHT, visible = config.ReadInt("MDIEmbedRightVisible", 1), sash = wx.SASH_LEFT)
+ else:
+ self._rightEmbWindow = None
+ if windows & EMBEDDED_WINDOW_TOPRIGHT:
+ self._topRightEmbWindow = self._CreateEmbeddedWindow(self._rightEmbWindow, (-1, config.ReadInt("MDIEmbedTopRightSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopRightVisible", 1), sash = wx.SASH_BOTTOM)
+ else:
+ self._topRightEmbWindow = None
+ if windows & EMBEDDED_WINDOW_BOTTOMRIGHT:
+ self._bottomRightEmbWindow = self._CreateEmbeddedWindow(self._rightEmbWindow, (-1, config.ReadInt("MDIEmbedBottomRightSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomRightVisible", 1))
+ else:
+ self._bottomRightEmbWindow = None
+ if windows & EMBEDDED_WINDOW_TOP:
+ self._topEmbWindow = self._CreateEmbeddedWindow(self, (-1, max(minSize,config.ReadInt("MDIEmbedTopSize", defaultVSize))), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopVisible", 1), sash = wx.SASH_BOTTOM)
+ else:
+ self._topEmbWindow = None
+ if windows & EMBEDDED_WINDOW_BOTTOM:
+ self._bottomEmbWindow = self._CreateEmbeddedWindow(self, (-1, max(minSize,config.ReadInt("MDIEmbedBottomSize", defaultVSize))), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomVisible", 1), sash = wx.SASH_TOP)
+ else:
+ self._bottomEmbWindow = None
+
+
+ def SaveEmbeddedWindowSizes(self):
+ """
+ Saves the sizes of the embedded windows.
+ """
+ config = wx.ConfigBase_Get()
+ if not self.IsMaximized():
+ config.WriteInt("MDIFrameXLoc", self.GetPositionTuple()[0])
+ config.WriteInt("MDIFrameYLoc", self.GetPositionTuple()[1])
+ config.WriteInt("MDIFrameXSize", self.GetSizeTuple()[0])
+ config.WriteInt("MDIFrameYSize", self.GetSizeTuple()[1])
+ config.WriteInt("MDIFrameMaximized", self.IsMaximized())
+ config.WriteInt("ViewToolBar", self._toolBar.IsShown())
+ config.WriteInt("ViewStatusBar", self.GetStatusBar().IsShown())
+
+ if self._leftEmbWindow:
+ config.WriteInt("MDIEmbedLeftSize", self._leftEmbWindow.GetSize()[0])
+ config.WriteInt("MDIEmbedLeftVisible", self._leftEmbWindow.IsShown())
+ if self._topLeftEmbWindow:
+ if self._topLeftEmbWindow._sizeBeforeHidden:
+ size = self._topLeftEmbWindow._sizeBeforeHidden[1]
+ else:
+ size = self._topLeftEmbWindow.GetSize()[1]
+ config.WriteInt("MDIEmbedTopLeftSize", size)
+ config.WriteInt("MDIEmbedTopLeftVisible", self._topLeftEmbWindow.IsShown())
+ if self._bottomLeftEmbWindow:
+ if self._bottomLeftEmbWindow._sizeBeforeHidden:
+ size = self._bottomLeftEmbWindow._sizeBeforeHidden[1]
+ else:
+ size = self._bottomLeftEmbWindow.GetSize()[1]
+ config.WriteInt("MDIEmbedBottomLeftSize", size)
+ config.WriteInt("MDIEmbedBottomLeftVisible", self._bottomLeftEmbWindow.IsShown())
+ if self._rightEmbWindow:
+ config.WriteInt("MDIEmbedRightSize", self._rightEmbWindow.GetSize()[0])
+ config.WriteInt("MDIEmbedRightVisible", self._rightEmbWindow.IsShown())
+ if self._topRightEmbWindow:
+ if self._topRightEmbWindow._sizeBeforeHidden:
+ size = self._topRightEmbWindow._sizeBeforeHidden[1]
+ else:
+ size = self._topRightEmbWindow.GetSize()[1]
+ config.WriteInt("MDIEmbedTopRightSize", size)
+ config.WriteInt("MDIEmbedTopRightVisible", self._topRightEmbWindow.IsShown())
+ if self._bottomRightEmbWindow:
+ if self._bottomRightEmbWindow._sizeBeforeHidden:
+ size = self._bottomRightEmbWindow._sizeBeforeHidden[1]
+ else:
+ size = self._bottomRightEmbWindow.GetSize()[1]
+ config.WriteInt("MDIEmbedBottomRightSize", size)
+ config.WriteInt("MDIEmbedBottomRightVisible", self._bottomRightEmbWindow.IsShown())
+ if self._topEmbWindow:
+ config.WriteInt("MDIEmbedTopSize", self._topEmbWindow.GetSize()[1])
+ config.WriteInt("MDIEmbedTopVisible", self._topEmbWindow.IsShown())
+ if self._bottomEmbWindow:
+ config.WriteInt("MDIEmbedBottomSize", self._bottomEmbWindow.GetSize()[1])
+ config.WriteInt("MDIEmbedBottomVisible", self._bottomEmbWindow.IsShown())
+
+
+ def GetEmbeddedWindow(self, loc):
+ """
+ Returns the instance of the embedded window specified by the embedded window location constant.
+ """
+ if loc == EMBEDDED_WINDOW_TOP:
+ return self._topEmbWindow
+ elif loc == EMBEDDED_WINDOW_BOTTOM:
+ return self._bottomEmbWindow
+ elif loc == EMBEDDED_WINDOW_LEFT:
+ return self._leftEmbWindow
+ elif loc == EMBEDDED_WINDOW_RIGHT:
+ return self._rightEmbWindow
+ elif loc == EMBEDDED_WINDOW_TOPLEFT:
+ return self._topLeftEmbWindow
+ elif loc == EMBEDDED_WINDOW_BOTTOMLEFT:
+ return self._bottomLeftEmbWindow
+ elif loc == EMBEDDED_WINDOW_TOPRIGHT:
+ return self._topRightEmbWindow
+ elif loc == EMBEDDED_WINDOW_BOTTOMRIGHT:
+ return self._bottomRightEmbWindow
+ return None
+
+
+ def _CreateEmbeddedWindow(self, parent, size, orientation, alignment, visible=True, sash=None):
+ """
+ Creates the embedded window with the specified size, orientation, and alignment. If the
+ window is not visible it will retain the size with which it was last viewed.
+ """
+ window = wx.SashLayoutWindow(parent, wx.NewId(), style = wx.NO_BORDER | wx.SW_3D)
+ window.SetDefaultSize(size)
+ window.SetOrientation(orientation)
+ window.SetAlignment(alignment)
+ if sash != None: # wx.SASH_TOP is 0 so check for None instead of just doing "if sash:"
+ window.SetSashVisible(sash, True)
+ ####
+ def OnEmbeddedWindowSashDrag(event):
+ if event.GetDragStatus() == wx.SASH_STATUS_OUT_OF_RANGE:
+ return
+ sashWindow = event.GetEventObject()
+ if sashWindow.GetAlignment() == wx.LAYOUT_TOP or sashWindow.GetAlignment() == wx.LAYOUT_BOTTOM:
+ size = wx.Size(-1, event.GetDragRect().height)
+ else:
+ size = wx.Size(event.GetDragRect().width, -1)
+ event.GetEventObject().SetDefaultSize(size)
+ self._LayoutFrame()
+ sashWindow.Refresh()
+ if isinstance(sashWindow.GetParent(), wx.SashLayoutWindow):
+ sashWindow.Show()
+ parentSashWindow = sashWindow.GetParent() # Force a refresh
+ parentSashWindow.Layout()
+ parentSashWindow.Refresh()
+ parentSashWindow.SetSize((parentSashWindow.GetSize().width + 1, parentSashWindow.GetSize().height + 1))
+ ####
+ wx.EVT_SASH_DRAGGED(window, window.GetId(), OnEmbeddedWindowSashDrag)
+ window._sizeBeforeHidden = None
+ if not visible:
+ window.Show(False)
+ if isinstance(parent, wx.SashLayoutWindow): # It's a window embedded in another sash window so remember its actual size to show it again
+ window._sizeBeforeHidden = size
+ return window
+
+
+ def ShowEmbeddedWindow(self, window, show=True):
+ """
+ Shows or hides the embedded window specified by the embedded window location constant.
+ """
+ window.Show(show)
+ if isinstance(window.GetParent(), wx.SashLayoutWindow): # It is a parent sashwindow with multiple embedded sashwindows
+ parentSashWindow = window.GetParent()
+ if show: # Make sure it is visible in case all of the subwindows were hidden
+ parentSashWindow.Show()
+ if show and window._sizeBeforeHidden:
+ if window._sizeBeforeHidden[1] == parentSashWindow.GetClientSize()[1]:
+ if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).IsShown():
+ window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).GetSize()[1]))
+ elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).IsShown():
+ window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).GetSize()[1]))
+ elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).IsShown():
+ window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).GetSize()[1]))
+ elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).IsShown():
+ window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).GetSize()[1]))
+ else:
+ window.SetDefaultSize(window._sizeBeforeHidden)
+ # If it is not the size of the full parent sashwindow set the other window's size so that if it gets shown it will have a cooresponding size
+ if window._sizeBeforeHidden[1] < parentSashWindow.GetClientSize()[1]:
+ otherWindowSize = (-1, parentSashWindow.GetClientSize()[1] - window._sizeBeforeHidden[1])
+ if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT):
+ self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).SetDefaultSize(otherWindowSize)
+ elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT):
+ self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).SetDefaultSize(otherWindowSize)
+ elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT):
+ self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).SetDefaultSize(otherWindowSize)
+ elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT):
+ self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).SetDefaultSize(otherWindowSize)
+
+ if not show:
+ if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).IsShown() \
+ or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).IsShown() \
+ or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).IsShown() \
+ or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).IsShown():
+ parentSashWindow.Hide() # Hide the parent sashwindow if all of the children are hidden
+ parentSashWindow.Layout() # Force a refresh
+ parentSashWindow.Refresh()
+ parentSashWindow.SetSize((parentSashWindow.GetSize().width + 1, parentSashWindow.GetSize().height + 1))
+ self._LayoutFrame()
+
+
+ def HideEmbeddedWindow(self, window):
+ """
+ Hides the embedded window specified by the embedded window location constant.
+ """
+ self.ShowEmbeddedWindow(window, show=False)
+
+
+class DocTabbedChildFrame(wx.Panel):
+ """
+ The wxDocMDIChildFrame class provides a default frame for displaying
+ documents on separate windows. This class can only be used for MDI child
+ frames.
+
+ The class is part of the document/view framework supported by wxWindows,
+ and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
+ classes.
+ """
+
+
+ def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
+ """
+ Constructor. Note that the event table must be rebuilt for the
+ frame since the EvtHandler is not virtual.
+ """
+ wx.Panel.__init__(self, frame.GetNotebook(), id)
+ self._childDocument = doc
+ self._childView = view
+ frame.AddNotebookPage(self, doc.GetPrintableName())
+ if view:
+ view.SetFrame(self)
+
+
+ def GetIcon(self):
+ """
+ Dummy method since the icon of tabbed frames are managed by the notebook.
+ """
+ return None
+
+
+ def SetIcon(self, icon):
+ """
+ Dummy method since the icon of tabbed frames are managed by the notebook.
+ """
+ pass
+
+
+ def Destroy(self):
+ """
+ Removes the current notebook page.
+ """
+ wx.GetApp().GetTopWindow().RemoveNotebookPage(self)
+
+
+ def SetFocus(self):
+ """
+ Activates the current notebook page.
+ """
+ wx.GetApp().GetTopWindow().ActivateNotebookPage(self)
+
+
+ def Activate(self): # Need this in case there are embedded sash windows and such, OnActivate is not getting called
+ """
+ Activates the current view.
+ """
+ # Called by Project Editor
+ if self._childView:
+ self._childView.Activate(True)
+
+
+ def GetTitle(self):
+ """
+ Returns the frame's title.
+ """
+ return wx.GetApp().GetTopWindow().GetNotebookPageTitle(self)
+
+
+ def SetTitle(self, title):
+ """
+ Sets the frame's title.
+ """
+ wx.GetApp().GetTopWindow().SetNotebookPageTitle(self, title)
+
+
+ def OnTitleIsModified(self):
+ """
+ Add/remove to the frame's title an indication that the document is dirty.
+ If the document is dirty, an '*' is appended to the title
+ """
+ title = self.GetTitle()
+ if title:
+ if self.GetDocument().IsModified():
+ if not title.endswith("*"):
+ title = title + "*"
+ self.SetTitle(title)
+ else:
+ if title.endswith("*"):
+ title = title[:-1]
+ self.SetTitle(title)
+
+
+ def ProcessEvent(event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if not self._childView or not self._childView.ProcessEvent(event):
+ if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
+ return False
+ else:
+ return True
+ else:
+ return True
+
+
+ def GetDocument(self):
+ """
+ Returns the document associated with this frame.
+ """
+ return self._childDocument
+
+
+ def SetDocument(self, document):
+ """
+ Sets the document for this frame.
+ """
+ self._childDocument = document
+
+
+ def GetView(self):
+ """
+ Returns the view associated with this frame.
+ """
+ return self._childView
+
+
+ def SetView(self, view):
+ """
+ Sets the view for this frame.
+ """
+ self._childView = view
+
+
+class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
+ """
+ The DocTabbedParentFrame class provides a default top-level frame for
+ applications using the document/view framework. This class can only be
+ used for MDI parent frames that use a tabbed interface.
+
+ It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
+ classes.
+ """
+
+
+ def __init__(self, docManager, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "DocTabbedParentFrame", embeddedWindows = 0, minSize=20):
+ """
+ Constructor. Note that the event table must be rebuilt for the
+ frame since the EvtHandler is not virtual.
+ """
+ pos, size = self._GetPosSizeFromConfig(pos, size)
+ wx.Frame.__init__(self, frame, id, title, pos, size, style, name)
+
+ # From docview.MDIParentFrame
+ self._docManager = docManager
+
+ wx.EVT_CLOSE(self, self.OnCloseWindow)
+
+ wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
+ wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
+
+ wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
+ wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
+
+ wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
+ wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
+ # End From docview.MDIParentFrame
+
+ self.CreateNotebook()
+ self._InitFrame(embeddedWindows, minSize)
+
+
+ def _LayoutFrame(self):
+ """
+ Lays out the frame.
+ """
+ wx.LayoutAlgorithm().LayoutFrame(self, self._notebook)
+
+
+ def CreateNotebook(self):
+ """
+ Creates the notebook to use for the tabbed document interface.
+ """
+ if wx.Platform != "__WXMAC__":
+ self._notebook = wx.Notebook(self, wx.NewId())
+ else:
+ self._notebook = wx.Listbook(self, wx.NewId(), style=wx.LB_LEFT)
+ # self._notebook.SetSizer(wx.NotebookSizer(self._notebook))
+ if wx.Platform != "__WXMAC__":
+ wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
+ else:
+ wx.EVT_LISTBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
+ wx.EVT_RIGHT_DOWN(self._notebook, self.OnNotebookRightClick)
+ wx.EVT_MIDDLE_DOWN(self._notebook, self.OnNotebookMiddleClick)
+
+ # wxBug: wx.Listbook does not implement HitTest the same way wx.Notebook
+ # does, so for now don't fire MouseOver events.
+ if wx.Platform != "__WXMAC__":
+ wx.EVT_MOTION(self._notebook, self.OnNotebookMouseOver)
+
+ templates = wx.GetApp().GetDocumentManager().GetTemplates()
+ iconList = wx.ImageList(16, 16, initialCount = len(templates))
+ self._iconIndexLookup = []
+ for template in templates:
+ icon = template.GetIcon()
+ if icon:
+ if icon.GetHeight() != 16 or icon.GetWidth() != 16:
+ icon.SetHeight(16)
+ icon.SetWidth(16)
+ if wx.GetApp().GetDebug():
+ print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template._docTypeName
+ iconIndex = iconList.AddIcon(icon)
+ self._iconIndexLookup.append((template, iconIndex))
+
+ icon = Blank.GetIcon()
+ if icon.GetHeight() != 16 or icon.GetWidth() != 16:
+ icon.SetHeight(16)
+ icon.SetWidth(16)
+ if wx.GetApp().GetDebug():
+ print "Warning: getBlankIcon isn't 16x16, not crossplatform"
+ self._blankIconIndex = iconList.AddIcon(icon)
+ self._notebook.AssignImageList(iconList)
+
+
+ def GetNotebook(self):
+ """
+ Returns the notebook used by the tabbed document interface.
+ """
+ return self._notebook
+
+
+ def GetActiveChild(self):
+ """
+ Returns the active notebook page, which to the framework is treated as
+ a document frame.
+ """
+ index = self._notebook.GetSelection()
+ if index == -1:
+ return None
+ return self._notebook.GetPage(index)
+
+
+ def OnNotebookPageChanged(self, event):
+ """
+ Activates a notebook page's view when it is selected.
+ """
+ index = self._notebook.GetSelection()
+ if index > -1:
+ self._notebook.GetPage(index).GetView().Activate()
+
+
+ def OnNotebookMouseOver(self, event):
+ # wxBug: On Windows XP the tooltips don't automatically disappear when you move the mouse and it is on a notebook tab, has nothing to do with this code!!!
+ index, type = self._notebook.HitTest(event.GetPosition())
+
+ if index > -1:
+ doc = self._notebook.GetPage(index).GetView().GetDocument()
+ # wxBug: Tooltips no longer appearing on tabs except on
+ # about a 2 pixel area between tab top and contents that will show tip.
+ self._notebook.GetParent().SetToolTip(wx.ToolTip(doc.GetFilename()))
+ else:
+ self._notebook.SetToolTip(wx.ToolTip(""))
+ event.Skip()
+
+
+ def OnNotebookMiddleClick(self, event):
+ """
+ Handles middle clicks for the notebook, closing the document whose tab was
+ clicked on.
+ """
+ index, type = self._notebook.HitTest(event.GetPosition())
+ if index > -1:
+ doc = self._notebook.GetPage(index).GetView().GetDocument()
+ if doc:
+ doc.DeleteAllViews()
+
+ def OnNotebookRightClick(self, event):
+ """
+ Handles right clicks for the notebook, enabling users to either close
+ a tab or select from the available documents if the user clicks on the
+ notebook's white space.
+ """
+ index, type = self._notebook.HitTest(event.GetPosition())
+ menu = wx.Menu()
+ x, y = event.GetX(), event.GetY()
+ if index > -1:
+ doc = self._notebook.GetPage(index).GetView().GetDocument()
+ id = wx.NewId()
+ menu.Append(id, _("Close"))
+ def OnRightMenuSelect(event):
+ doc.DeleteAllViews()
+ wx.EVT_MENU(self, id, OnRightMenuSelect)
+ if self._notebook.GetPageCount() > 1:
+ id = wx.NewId()
+ menu.Append(id, _("Close All but \"%s\"" % doc.GetPrintableName()))
+ def OnRightMenuSelect(event):
+ for i in range(self._notebook.GetPageCount()-1, -1, -1): # Go from len-1 to 0
+ if i != index:
+ doc = self._notebook.GetPage(i).GetView().GetDocument()
+ if not self.GetDocumentManager().CloseDocument(doc, False):
+ return
+ wx.EVT_MENU(self, id, OnRightMenuSelect)
+ menu.AppendSeparator()
+ tabsMenu = wx.Menu()
+ menu.AppendMenu(wx.NewId(), _("Select Tab"), tabsMenu)
+ else:
+ y = y - 25 # wxBug: It is offsetting click events in the blank notebook area
+ tabsMenu = menu
+
+ if self._notebook.GetPageCount() > 1:
+ selectIDs = {}
+ for i in range(0, self._notebook.GetPageCount()):
+ id = wx.NewId()
+ selectIDs[id] = i
+ tabsMenu.Append(id, self._notebook.GetPageText(i))
+ def OnRightMenuSelect(event):
+ self._notebook.SetSelection(selectIDs[event.GetId()])
+ wx.EVT_MENU(self, id, OnRightMenuSelect)
+
+ self._notebook.PopupMenu(menu, wx.Point(x, y))
+ menu.Destroy()
+
+
+ def AddNotebookPage(self, panel, title):
+ """
+ Adds a document page to the notebook.
+ """
+ self._notebook.AddPage(panel, title)
+ index = self._notebook.GetPageCount() - 1
+ self._notebook.SetSelection(index)
+
+ found = False # Now set the icon
+ template = panel.GetDocument().GetDocumentTemplate()
+ if template:
+ for t, iconIndex in self._iconIndexLookup:
+ if t is template:
+ self._notebook.SetPageImage(index, iconIndex)
+ found = True
+ break
+ if not found:
+ self._notebook.SetPageImage(index, self._blankIconIndex)
+
+ # wxBug: the wxListbook used on Mac needs its tabs list resized
+ # whenever a new tab is added, but the only way to do this is
+ # to resize the entire control
+ if wx.Platform == "__WXMAC__":
+ content_size = self._notebook.GetSize()
+ self._notebook.SetSize((content_size.x+2, -1))
+ self._notebook.SetSize((content_size.x, -1))
+
+ self._notebook.Layout()
+
+ windowMenuService = wx.GetApp().GetService(WindowMenuService)
+ if windowMenuService:
+ windowMenuService.BuildWindowMenu(wx.GetApp().GetTopWindow()) # build file menu list when we open a file
+
+
+ def RemoveNotebookPage(self, panel):
+ """
+ Removes a document page from the notebook.
+ """
+ index = self.GetNotebookPageIndex(panel)
+ if index > -1:
+ if self._notebook.GetPageCount() == 1 or index < 2:
+ pass
+ elif index >= 1:
+ self._notebook.SetSelection(index - 1)
+ elif index < self._notebook.GetPageCount():
+ self._notebook.SetSelection(index + 1)
+ self._notebook.DeletePage(index)
+ self._notebook.GetParent().SetToolTip(wx.ToolTip(""))
+
+ windowMenuService = wx.GetApp().GetService(WindowMenuService)
+ if windowMenuService:
+ windowMenuService.BuildWindowMenu(wx.GetApp().GetTopWindow()) # build file menu list when we open a file
+
+
+ def ActivateNotebookPage(self, panel):
+ """
+ Sets the notebook to the specified panel.
+ """
+ index = self.GetNotebookPageIndex(panel)
+ if index > -1:
+ self._notebook.SetFocus()
+ self._notebook.SetSelection(index)
+
+
+ def GetNotebookPageTitle(self, panel):
+ index = self.GetNotebookPageIndex(panel)
+ if index != -1:
+ return self._notebook.GetPageText(self.GetNotebookPageIndex(panel))
+ else:
+ return None
+
+
+ def SetNotebookPageTitle(self, panel, title):
+ self._notebook.SetPageText(self.GetNotebookPageIndex(panel), title)
+
+
+ def GetNotebookPageIndex(self, panel):
+ """
+ Returns the index of particular notebook panel.
+ """
+ index = -1
+ for i in range(self._notebook.GetPageCount()):
+ if self._notebook.GetPage(i) == panel:
+ index = i
+ break
+ return index
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if wx.GetApp().ProcessEventBeforeWindows(event):
+ return True
+ if self._docManager and self._docManager.ProcessEvent(event):
+ return True
+ return DocMDIParentFrameMixIn.ProcessEvent(self, event)
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
+ return True
+ if self._docManager and self._docManager.ProcessUpdateUIEvent(event):
+ return True
+ return DocMDIParentFrameMixIn.ProcessUpdateUIEvent(self, event)
+
+
+ def OnExit(self, event):
+ """
+ Called when File/Exit is chosen and closes the window.
+ """
+ self.Close()
+
+
+ def OnMRUFile(self, event):
+ """
+ Opens the appropriate file when it is selected from the file history
+ menu.
+ """
+ n = event.GetId() - wx.ID_FILE1
+ filename = self._docManager.GetHistoryFile(n)
+ if filename:
+ self._docManager.CreateDocument(filename, wx.lib.docview.DOC_SILENT)
+ else:
+ self._docManager.RemoveFileFromHistory(n)
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("File Error")
+ wx.MessageBox("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list" % FileNameFromPath(file),
+ msgTitle,
+ wx.OK | wx.ICON_EXCLAMATION,
+ self)
+
+
+ def OnSize(self, event):
+ """
+ Called when the frame is resized and lays out the client window.
+ """
+ # Needed in case there are splitpanels around the mdi frame
+ self._LayoutFrame()
+
+
+ def OnCloseWindow(self, event):
+ """
+ Called when the frame is closed. Remembers the frame size.
+ """
+ self.SaveEmbeddedWindowSizes()
+
+ # save and close services last
+ for service in wx.GetApp().GetServices():
+ if not service.OnCloseFrame(event):
+ return
+
+ # From docview.MDIParentFrame
+ if self._docManager.Clear(not event.CanVeto()):
+ self.Destroy()
+ else:
+ event.Veto()
+
+
+class DocMDIChildFrame(wx.MDIChildFrame):
+ """
+ The wxDocMDIChildFrame class provides a default frame for displaying
+ documents on separate windows. This class can only be used for MDI child
+ frames.
+
+ The class is part of the document/view framework supported by wxWindows,
+ and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
+ classes.
+ """
+
+
+ def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
+ """
+ Constructor. Note that the event table must be rebuilt for the
+ frame since the EvtHandler is not virtual.
+ """
+ wx.MDIChildFrame.__init__(self, frame, id, title, pos, size, style, name)
+ self._childDocument = doc
+ self._childView = view
+ if view:
+ view.SetFrame(self)
+ # self.Create(doc, view, frame, id, title, pos, size, style, name)
+ self._activeEvent = None
+ self._activated = 0
+ wx.EVT_ACTIVATE(self, self.OnActivate)
+ wx.EVT_CLOSE(self, self.OnCloseWindow)
+
+ if frame: # wxBug: For some reason the EVT_ACTIVATE event is not getting triggered for the first mdi client window that is opened so we have to do it manually
+ mdiChildren = filter(lambda x: isinstance(x, wx.MDIChildFrame), frame.GetChildren())
+ if len(mdiChildren) == 1:
+ self.Activate()
+
+
+## # Couldn't get this to work, but seems to work fine with single stage construction
+## def Create(self, doc, view, frame, id, title, pos, size, style, name):
+## self._childDocument = doc
+## self._childView = view
+## if wx.MDIChildFrame.Create(self, frame, id, title, pos, size, style, name):
+## if view:
+## view.SetFrame(self)
+## return True
+## return False
+
+
+
+ def Activate(self): # Need this in case there are embedded sash windows and such, OnActivate is not getting called
+ """
+ Activates the current view.
+ """
+ if self._childView:
+ self._childView.Activate(True)
+
+
+ def OnTitleIsModified(self):
+ """
+ Add/remove to the frame's title an indication that the document is dirty.
+ If the document is dirty, an '*' is appended to the title
+ """
+ title = self.GetTitle()
+ if title:
+ if self.GetDocument().IsModified():
+ if title.endswith("*"):
+ return
+ else:
+ title = title + "*"
+ self.SetTitle(title)
+ else:
+ if title.endswith("*"):
+ title = title[:-1]
+ self.SetTitle(title)
+ else:
+ return
+
+
+ def ProcessEvent(event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if self._activeEvent == event:
+ return False
+
+ self._activeEvent = event # Break recursion loops
+
+ if self._childView:
+ self._childView.Activate(True)
+
+ if not self._childView or not self._childView.ProcessEvent(event):
+ if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
+ ret = False
+ else:
+ ret = True
+ else:
+ ret = True
+
+ self._activeEvent = None
+ return ret
+
+
+ def OnActivate(self, event):
+ """
+ Sets the currently active view to be the frame's view. You may need to
+ override (but still call) this function in order to set the keyboard
+ focus for your subwindow.
+ """
+ event.Skip()
+ if self._activated != 0:
+ return True
+ self._activated += 1
+ wx.MDIChildFrame.Activate(self)
+ if event.GetActive() and self._childView:
+ self._childView.Activate(event.GetActive())
+ self._activated = 0
+
+
+ def OnCloseWindow(self, event):
+ """
+ Closes and deletes the current view and document.
+ """
+ if self._childView:
+ ans = False
+ if not event.CanVeto():
+ ans = True
+ else:
+ ans = self._childView.Close(deleteWindow = False)
+
+ if ans:
+ self._childView.Activate(False)
+ self._childView.Destroy()
+ self._childView = None
+ if self._childDocument:
+ self._childDocument.Destroy() # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
+ self._childDocument = None
+ self.Destroy()
+ else:
+ event.Veto()
+ else:
+ event.Veto()
+
+
+ def GetDocument(self):
+ """
+ Returns the document associated with this frame.
+ """
+ return self._childDocument
+
+
+ def SetDocument(self, document):
+ """
+ Sets the document for this frame.
+ """
+ self._childDocument = document
+
+
+ def GetView(self):
+ """
+ Returns the view associated with this frame.
+ """
+ return self._childView
+
+
+ def SetView(self, view):
+ """
+ Sets the view for this frame.
+ """
+ self._childView = view
+
+
+class DocService(wx.EvtHandler):
+ """
+ An abstract class used to add reusable services to a docview application.
+ """
+
+
+ def __init__(self):
+ """Initializes the DocService."""
+ pass
+
+
+ def GetDocumentManager(self):
+ """Returns the DocManager for the docview application."""
+ return self._docManager
+
+
+ def SetDocumentManager(self, docManager):
+ """Sets the DocManager for the docview application."""
+ self._docManager = docManager
+
+
+ def InstallControls(self, frame, menuBar=None, toolBar=None, statusBar=None, document=None):
+ """Called to install controls into the menubar and toolbar of a SDI or MDI window. Override this method for a particular service."""
+ pass
+
+
+ def ProcessEventBeforeWindows(self, event):
+ """
+ Processes an event before the main window has a chance to process the window.
+ Override this method for a particular service.
+ """
+ return False
+
+
+ def ProcessUpdateUIEventBeforeWindows(self, event):
+ """
+ Processes a UI event before the main window has a chance to process the window.
+ Override this method for a particular service.
+ """
+ return False
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ return False
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ return False
+
+
+ def OnCloseFrame(self, event):
+ """
+ Called when the a docview frame is being closed. Override this method
+ so a service can either do cleanup or veto the frame being closed by
+ returning false.
+ """
+ return True
+
+
+ def OnExit(self):
+ """
+ Called when the the docview application is being closed. Override this method
+ so a service can either do cleanup or veto the frame being closed by
+ returning false.
+ """
+ pass
+
+
+ def GetMenuItemPos(self, menu, id):
+ """
+ Utility method used to find the position of a menu item so that services can
+ easily find where to insert a menu item in InstallControls.
+ """
+ menuItems = menu.GetMenuItems()
+ for i, menuItem in enumerate(menuItems):
+ if menuItem.GetId() == id:
+ return i
+ return i
+
+
+ def GetView(self):
+ """
+ Called by WindowMenuService to get views for services that don't
+ have dedicated documents such as the Outline Service.
+ """
+ return None
+
+
+class DocOptionsService(DocService):
+ """
+ A service that implements an options menu item and an options dialog with
+ notebook tabs. New tabs can be added by other services by calling the
+ "AddOptionsPanel" method.
+ """
+
+
+ def __init__(self, showGeneralOptions=True, supportedModes=wx.lib.docview.DOC_SDI & wx.lib.docview.DOC_MDI):
+ """
+ Initializes the options service with the option of suppressing the default
+ general options pane that is included with the options service by setting
+ showGeneralOptions to False. It allowModeChanges is set to False, the
+ default general options pane will allow users to change the document
+ interface mode between SDI and MDI modes.
+ """
+ DocService.__init__(self)
+ self.ClearOptionsPanels()
+ self._supportedModes = supportedModes
+ self._toolOptionsID = wx.ID_PREFERENCES
+ if showGeneralOptions:
+ self.AddOptionsPanel(GeneralOptionsPanel)
+
+
+ def InstallControls(self, frame, menuBar=None, toolBar=None, statusBar=None, document=None):
+ """
+ Installs a "Tools" menu with an "Options" menu item.
+ """
+ toolsMenuIndex = menuBar.FindMenu(_("&Tools"))
+ if toolsMenuIndex > -1:
+ toolsMenu = menuBar.GetMenu(toolsMenuIndex)
+ else:
+ toolsMenu = wx.Menu()
+ if toolsMenuIndex == -1:
+ formatMenuIndex = menuBar.FindMenu(_("&Format"))
+ menuBar.Insert(formatMenuIndex + 1, toolsMenu, _("&Tools"))
+ if toolsMenu:
+ if toolsMenu.GetMenuItemCount():
+ toolsMenu.AppendSeparator()
+ toolsMenu.Append(self._toolOptionsID, _("&Options..."), _("Sets options"))
+ wx.EVT_MENU(frame, self._toolOptionsID, frame.ProcessEvent)
+
+
+ def ProcessEvent(self, event):
+ """
+ Checks to see if the "Options" menu item has been selected.
+ """
+ id = event.GetId()
+ if id == self._toolOptionsID:
+ self.OnOptions(event)
+ return True
+ else:
+ return False
+
+
+ def GetSupportedModes(self):
+ """
+ Return the modes supported by the application. Use docview.DOC_SDI and
+ docview.DOC_MDI flags to check if SDI and/or MDI modes are supported.
+ """
+ return self._supportedModes
+
+
+ def SetSupportedModes(self, _supportedModessupportedModes):
+ """
+ Sets the modes supported by the application. Use docview.DOC_SDI and
+ docview.DOC_MDI flags to set if SDI and/or MDI modes are supported.
+ """
+ self._supportedModes = supportedModes
+
+
+ def ClearOptionsPanels(self):
+ """
+ Clears all of the options panels that have been added into the
+ options dialog.
+ """
+ self._optionsPanels = []
+
+
+ def AddOptionsPanel(self, optionsPanel):
+ """
+ Adds an options panel to the options dialog.
+ """
+ self._optionsPanels.append(optionsPanel)
+
+
+ def OnOptions(self, event):
+ """
+ Shows the options dialog, called when the "Options" menu item is selected.
+ """
+ if len(self._optionsPanels) == 0:
+ return
+ optionsDialog = OptionsDialog(wx.GetApp().GetTopWindow(), self._optionsPanels, self._docManager)
+ optionsDialog.CenterOnParent()
+ if optionsDialog.ShowModal() == wx.ID_OK:
+ optionsDialog.OnOK(optionsDialog) # wxBug: wxDialog should be calling this automatically but doesn't
+ optionsDialog.Destroy()
+
+
+class OptionsDialog(wx.Dialog):
+ """
+ A default options dialog used by the OptionsService that hosts a notebook
+ tab of options panels.
+ """
+
+
+ def __init__(self, parent, optionsPanelClasses, docManager):
+ """
+ Initializes the options dialog with a notebook page that contains new
+ instances of the passed optionsPanelClasses.
+ """
+ wx.Dialog.__init__(self, parent, -1, _("Options"))
+
+ self._optionsPanels = []
+ self._docManager = docManager
+
+ HALF_SPACE = 5
+ SPACE = 10
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ if wx.Platform == "__WXMAC__":
+ optionsNotebook = wx.Listbook(self, wx.NewId(), style=wx.LB_DEFAULT)
+ else:
+ optionsNotebook = wx.Notebook(self, wx.NewId(), style=wx.NB_MULTILINE) # NB_MULTILINE is windows platform only
+ sizer.Add(optionsNotebook, 0, wx.ALL | wx.EXPAND, SPACE)
+
+ if wx.Platform == "__WXMAC__":
+ iconList = wx.ImageList(16, 16, initialCount = len(optionsPanelClasses))
+ self._iconIndexLookup = []
+
+ for optionsPanelClass in optionsPanelClasses:
+ optionsPanel = optionsPanelClass(optionsNotebook, -1)
+ self._optionsPanels.append(optionsPanel)
+
+ # We need to populate the image list before setting notebook images
+ if hasattr(optionsPanel, "GetIcon"):
+ icon = optionsPanel.GetIcon()
+ else:
+ icon = None
+ if icon:
+ if icon.GetHeight() != 16 or icon.GetWidth() != 16:
+ icon.SetHeight(16)
+ icon.SetWidth(16)
+ if wx.GetApp().GetDebug():
+ print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template._docTypeName
+ iconIndex = iconList.AddIcon(icon)
+ self._iconIndexLookup.append((optionsPanel, iconIndex))
+
+ else:
+ # use -1 to represent that this panel has no icon
+ self._iconIndexLookup.append((optionsPanel, -1))
+
+ optionsNotebook.AssignImageList(iconList)
+
+ # Add icons to notebook
+ for index in range(0, len(optionsPanelClasses)-1):
+ iconIndex = self._iconIndexLookup[index][1]
+ if iconIndex >= 0:
+ optionsNotebook.SetPageImage(index, iconIndex)
+ else:
+ for optionsPanelClass in optionsPanelClasses:
+ optionsPanel = optionsPanelClass(optionsNotebook, -1)
+ self._optionsPanels.append(optionsPanel)
+
+ sizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
+ self.SetSizer(sizer)
+ self.Layout()
+ self.Fit()
+ wx.CallAfter(self.DoRefresh)
+
+
+ def DoRefresh(self):
+ """
+ wxBug: On Windows XP when using a multiline notebook the default page doesn't get
+ drawn, but it works when using a single line notebook.
+ """
+ self.Refresh()
+
+
+ def GetDocManager(self):
+ """
+ Returns the document manager passed to the OptionsDialog constructor.
+ """
+ return self._docManager
+
+
+ def OnOK(self, event):
+ """
+ Calls the OnOK method of all of the OptionDialog's embedded panels
+ """
+ for optionsPanel in self._optionsPanels:
+ optionsPanel.OnOK(event)
+
+
+class GeneralOptionsPanel(wx.Panel):
+ """
+ A general options panel that is used in the OptionDialog to configure the
+ generic properties of a pydocview application, such as "show tips at startup"
+ and whether to use SDI or MDI for the application.
+ """
+
+
+ def __init__(self, parent, id):
+ """
+ Initializes the panel by adding an "Options" folder tab to the parent notebook and
+ populating the panel with the generic properties of a pydocview application.
+ """
+ wx.Panel.__init__(self, parent, id)
+ SPACE = 10
+ HALF_SPACE = 5
+ config = wx.ConfigBase_Get()
+ self._showTipsCheckBox = wx.CheckBox(self, -1, _("Show tips at start up"))
+ self._showTipsCheckBox.SetValue(config.ReadInt("ShowTipAtStartup", True))
+ if self._AllowModeChanges():
+ supportedModes = wx.GetApp().GetService(DocOptionsService).GetSupportedModes()
+ choices = []
+ self._sdiChoice = _("Show each document in its own window")
+ self._mdiChoice = _("Show all documents in a single window with tabs")
+ self._winMdiChoice = _("Show all documents in a single window with child windows")
+ if supportedModes & wx.lib.docview.DOC_SDI:
+ choices.append(self._sdiChoice)
+ choices.append(self._mdiChoice)
+ if wx.Platform == "__WXMSW__":
+ choices.append(self._winMdiChoice)
+ self._documentRadioBox = wx.RadioBox(self, -1, _("Document Display Style"),
+ choices = choices,
+ majorDimension=1,
+ )
+ if config.ReadInt("UseWinMDI", False):
+ self._documentRadioBox.SetStringSelection(self._winMdiChoice)
+ elif config.ReadInt("UseMDI", True):
+ self._documentRadioBox.SetStringSelection(self._mdiChoice)
+ else:
+ self._documentRadioBox.SetStringSelection(self._sdiChoice)
+ def OnDocumentInterfaceSelect(event):
+ if not self._documentInterfaceMessageShown:
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("Document Options")
+ wx.MessageBox(_("Document interface changes will not appear until the application is restarted."),
+ msgTitle,
+ wx.OK | wx.ICON_INFORMATION,
+ self.GetParent())
+ self._documentInterfaceMessageShown = True
+ wx.EVT_RADIOBOX(self, self._documentRadioBox.GetId(), OnDocumentInterfaceSelect)
+ optionsBorderSizer = wx.BoxSizer(wx.VERTICAL)
+ optionsSizer = wx.BoxSizer(wx.VERTICAL)
+ if self._AllowModeChanges():
+ optionsSizer.Add(self._documentRadioBox, 0, wx.ALL, HALF_SPACE)
+ optionsSizer.Add(self._showTipsCheckBox, 0, wx.ALL, HALF_SPACE)
+ optionsBorderSizer.Add(optionsSizer, 0, wx.ALL, SPACE)
+ self.SetSizer(optionsBorderSizer)
+ self.Layout()
+ self._documentInterfaceMessageShown = False
+ parent.AddPage(self, _("General"))
+
+
+ def _AllowModeChanges(self):
+ supportedModes = wx.GetApp().GetService(DocOptionsService).GetSupportedModes()
+ return supportedModes & wx.lib.docview.DOC_SDI and supportedModes & wx.lib.docview.DOC_MDI or wx.Platform == "__WXMSW__" and supportedModes & wx.lib.docview.DOC_MDI # More than one mode is supported, allow selection
+
+
+ def OnOK(self, optionsDialog):
+ """
+ Updates the config based on the selections in the options panel.
+ """
+ config = wx.ConfigBase_Get()
+ config.WriteInt("ShowTipAtStartup", self._showTipsCheckBox.GetValue())
+ if self._AllowModeChanges():
+ config.WriteInt("UseMDI", (self._documentRadioBox.GetStringSelection() == self._mdiChoice))
+ config.WriteInt("UseWinMDI", (self._documentRadioBox.GetStringSelection() == self._winMdiChoice))
+
+
+ def GetIcon(self):
+ """ Return icon for options panel on the Mac. """
+ return wx.GetApp().GetDefaultIcon()
+
+
+class DocApp(wx.App):
+ """
+ The DocApp class serves as the base class for pydocview applications and offers
+ functionality such as services, creation of SDI and MDI frames, show tips,
+ and a splash screen.
+ """
+
+
+ def OnInit(self):
+ """
+ Initializes the DocApp.
+ """
+ self._services = []
+ self._defaultIcon = None
+ self._registeredCloseEvent = False
+ self._useTabbedMDI = True
+
+ if not hasattr(self, "_debug"): # only set if not already initialized
+ self._debug = False
+ if not hasattr(self, "_singleInstance"): # only set if not already initialized
+ self._singleInstance = True
+
+ # if _singleInstance is TRUE only allow one single instance of app to run.
+ # When user tries to run a second instance of the app, abort startup,
+ # But if user also specifies files to open in command line, send message to running app to open those files
+ if self._singleInstance:
+ # create shared memory temporary file
+ if wx.Platform == '__WXMSW__':
+ tfile = tempfile.TemporaryFile(prefix="ag", suffix="tmp")
+ fno = tfile.fileno()
+ self._sharedMemory = mmap.mmap(fno, 1024, "shared_memory")
+ else:
+ tfile = file(os.path.join(tempfile.gettempdir(), tempfile.gettempprefix() + self.GetAppName() + '-' + wx.GetUserId() + "AGSharedMemory"), 'w+b')
+ tfile.write("*")
+ tfile.seek(1024)
+ tfile.write(" ")
+ tfile.flush()
+ fno = tfile.fileno()
+ self._sharedMemory = mmap.mmap(fno, 1024)
+
+ self._singleInstanceChecker = wx.SingleInstanceChecker(self.GetAppName() + '-' + wx.GetUserId(), tempfile.gettempdir())
+ if self._singleInstanceChecker.IsAnotherRunning():
+ # have running single instance open file arguments
+ data = pickle.dumps(sys.argv[1:])
+ while 1:
+ self._sharedMemory.seek(0)
+ marker = self._sharedMemory.read_byte()
+ if marker == '\0' or marker == '*': # available buffer
+ self._sharedMemory.seek(0)
+ self._sharedMemory.write_byte('-') # set writing marker
+ self._sharedMemory.write(data) # write files we tried to open to shared memory
+ self._sharedMemory.seek(0)
+ self._sharedMemory.write_byte('+') # set finished writing marker
+ self._sharedMemory.flush()
+ break
+ else:
+ time.sleep(1) # give enough time for buffer to be available
+
+ return False
+ else:
+ self._timer = wx.PyTimer(self.DoBackgroundListenAndLoad)
+ self._timer.Start(250)
+
+ return True
+
+
+ def OpenMainFrame(self):
+ docManager = self.GetDocumentManager()
+ if docManager.GetFlags() & wx.lib.docview.DOC_MDI:
+ if self.GetUseTabbedMDI():
+ frame = wx.lib.pydocview.DocTabbedParentFrame(docManager, None, -1, self.GetAppName())
+ else:
+ frame = wx.lib.pydocview.DocMDIParentFrame(docManager, None, -1, self.GetAppName())
+ frame.Show(True)
+
+ def MacOpenFile(self, filename):
+ self.GetDocumentManager().CreateDocument(os.path.normpath(filename), wx.lib.docview.DOC_SILENT)
+
+ # force display of running app
+ topWindow = wx.GetApp().GetTopWindow()
+ if topWindow.IsIconized():
+ topWindow.Iconize(False)
+ else:
+ topWindow.Raise()
+
+ def DoBackgroundListenAndLoad(self):
+ """
+ Open any files specified in the given command line argument passed in via shared memory
+ """
+ self._timer.Stop()
+
+ self._sharedMemory.seek(0)
+ if self._sharedMemory.read_byte() == '+': # available data
+ data = self._sharedMemory.read(1024-1)
+ self._sharedMemory.seek(0)
+ self._sharedMemory.write_byte("*") # finished reading, set buffer free marker
+ self._sharedMemory.flush()
+ args = pickle.loads(data)
+ for arg in args:
+ if (wx.Platform != "__WXMSW__" or arg[0] != "/") and arg[0] != '-' and os.path.exists(arg):
+ self.GetDocumentManager().CreateDocument(os.path.normpath(arg), wx.lib.docview.DOC_SILENT)
+
+ # force display of running app
+ topWindow = wx.GetApp().GetTopWindow()
+ if topWindow.IsIconized():
+ topWindow.Iconize(False)
+ else:
+ topWindow.Raise()
+
+
+ self._timer.Start(1000) # 1 second interval
+
+
+ def OpenCommandLineArgs(self):
+ """
+ Called to open files that have been passed to the application from the
+ command line.
+ """
+ args = sys.argv[1:]
+ for arg in args:
+ if (wx.Platform != "__WXMSW__" or arg[0] != "/") and arg[0] != '-' and os.path.exists(arg):
+ self.GetDocumentManager().CreateDocument(os.path.normpath(arg), wx.lib.docview.DOC_SILENT)
+
+
+ def GetDocumentManager(self):
+ """
+ Returns the document manager associated to the DocApp.
+ """
+ return self._docManager
+
+
+ def SetDocumentManager(self, docManager):
+ """
+ Sets the document manager associated with the DocApp and loads the
+ DocApp's file history into the document manager.
+ """
+ self._docManager = docManager
+ config = wx.ConfigBase_Get()
+ self.GetDocumentManager().FileHistoryLoad(config)
+
+
+ def ProcessEventBeforeWindows(self, event):
+ """
+ Enables services to process an event before the main window has a chance to
+ process the window.
+ """
+ for service in self._services:
+ if service.ProcessEventBeforeWindows(event):
+ return True
+ return False
+
+
+ def ProcessUpdateUIEventBeforeWindows(self, event):
+ """
+ Enables services to process a UI event before the main window has a chance
+ to process the window.
+ """
+ for service in self._services:
+ if service.ProcessUpdateUIEventBeforeWindows(event):
+ return True
+ return False
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ for service in self._services:
+ if service.ProcessEvent(event):
+ return True
+ return False
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ for service in self._services:
+ if service.ProcessUpdateUIEvent(event):
+ return True
+ return False
+
+
+ def InstallService(self, service):
+ """
+ Installs an instance of a DocService into the DocApp.
+ """
+ service.SetDocumentManager(self._docManager)
+ self._services.append(service)
+ return service
+
+
+ def GetServices(self):
+ """
+ Returns the DocService instances that have been installed into the DocApp.
+ """
+ return self._services
+
+
+ def GetService(self, type):
+ """
+ Returns the instance of a particular type of service that has been installed
+ into the DocApp. For example, "wx.GetApp().GetService(pydocview.OptionsService)"
+ returns the isntance of the OptionsService that is running within the DocApp.
+ """
+ for service in self._services:
+ if isinstance(service, type):
+ return service
+ return None
+
+
+ def OnExit(self):
+ """
+ Called when the DocApp is exited, enables the installed DocServices to exit
+ and saves the DocManager's file history.
+ """
+ for service in self._services:
+ service.OnExit()
+ config = wx.ConfigBase_Get()
+ self._docManager.FileHistorySave(config)
+
+ if hasattr(self, "_singleInstanceChecker"):
+ del self._singleInstanceChecker
+
+
+ def GetDefaultDocManagerFlags(self):
+ """
+ Returns the default flags to use when creating the DocManager.
+ """
+ config = wx.ConfigBase_Get()
+ if config.ReadInt("UseMDI", True) or config.ReadInt("UseWinMDI", False):
+ flags = wx.lib.docview.DOC_MDI | wx.lib.docview.DOC_OPEN_ONCE
+ if config.ReadInt("UseWinMDI", False):
+ self.SetUseTabbedMDI(False)
+ else:
+ flags = wx.lib.docview.DOC_SDI | wx.lib.docview.DOC_OPEN_ONCE
+ return flags
+
+
+ def ShowTip(self, frame, tipProvider):
+ """
+ Shows the tip window, generally this is called when an application starts.
+ A wx.TipProvider must be passed.
+ """
+ config = wx.ConfigBase_Get()
+ showTip = config.ReadInt("ShowTipAtStartup", 1)
+ if showTip:
+ index = config.ReadInt("TipIndex", 0)
+ showTipResult = wx.ShowTip(wx.GetApp().GetTopWindow(), tipProvider, showAtStartup = showTip)
+ if showTipResult != showTip:
+ config.WriteInt("ShowTipAtStartup", showTipResult)
+
+
+ def GetEditMenu(self, frame):
+ """
+ Utility method that finds the Edit menu within the menubar of a frame.
+ """
+ menuBar = frame.GetMenuBar()
+ if not menuBar:
+ return None
+ editMenuIndex = menuBar.FindMenu(_("&Edit"))
+ if editMenuIndex == -1:
+ return None
+ return menuBar.GetMenu(editMenuIndex)
+
+
+ def GetUseTabbedMDI(self):
+ """
+ Returns True if Windows MDI should use folder tabs instead of child windows.
+ """
+ return self._useTabbedMDI
+
+
+ def SetUseTabbedMDI(self, useTabbedMDI):
+ """
+ Set to True if Windows MDI should use folder tabs instead of child windows.
+ """
+ self._useTabbedMDI = useTabbedMDI
+
+
+ def CreateDocumentFrame(self, view, doc, flags, id = -1, title = "", pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
+ """
+ Called by the DocManager to create and return a new Frame for a Document.
+ Chooses whether to create an MDIChildFrame or SDI Frame based on the
+ DocManager's flags.
+ """
+ docflags = self.GetDocumentManager().GetFlags()
+ if docflags & wx.lib.docview.DOC_SDI:
+ frame = self.CreateSDIDocumentFrame(doc, view, id, title, pos, size, style)
+ frame.Show()
+
+ # wxBug: operating system bug, first window is set to the position of last window closed, ignoring passed in position on frame creation
+ # also, initial size is incorrect for the same reasons
+ if frame.GetPosition() != pos:
+ frame.Move(pos)
+ if frame.GetSize() != size:
+ frame.SetSize(size)
+
+ if doc and doc.GetCommandProcessor():
+ doc.GetCommandProcessor().SetEditMenu(self.GetEditMenu(frame))
+ elif docflags & wx.lib.docview.DOC_MDI:
+ if self.GetUseTabbedMDI():
+ frame = self.CreateTabbedDocumentFrame(doc, view, id, title, pos, size, style)
+ else:
+ frame = self.CreateMDIDocumentFrame(doc, view, id, title, pos, size, style)
+ if doc:
+ if doc.GetDocumentTemplate().GetIcon():
+ frame.SetIcon(doc.GetDocumentTemplate().GetIcon())
+ elif wx.GetApp().GetTopWindow().GetIcon():
+ frame.SetIcon(wx.GetApp().GetTopWindow().GetIcon())
+ if doc and doc.GetCommandProcessor():
+ doc.GetCommandProcessor().SetEditMenu(self.GetEditMenu(wx.GetApp().GetTopWindow()))
+ if not frame.GetIcon() and self._defaultIcon:
+ frame.SetIcon(self.GetDefaultIcon())
+ view.SetFrame(frame)
+ return frame
+
+
+ def CreateSDIDocumentFrame(self, doc, view, id=-1, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
+ """
+ Creates and returns an SDI Document Frame.
+ """
+ frame = DocSDIFrame(doc, view, None, id, title, pos, size, style)
+ return frame
+
+
+ def CreateTabbedDocumentFrame(self, doc, view, id=-1, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
+ """
+ Creates and returns an MDI Document Frame for a Tabbed MDI view
+ """
+ frame = DocTabbedChildFrame(doc, view, wx.GetApp().GetTopWindow(), id, title, pos, size, style)
+ return frame
+
+
+ def CreateMDIDocumentFrame(self, doc, view, id=-1, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
+ """
+ Creates and returns an MDI Document Frame.
+ """
+ # if any child windows are maximized, then user must want any new children maximized
+ # if no children exist, then use the default value from registry
+ # wxBug: Only current window is maximized, so need to check every child frame
+ parentFrame = wx.GetApp().GetTopWindow()
+ childrenMaximized = filter(lambda child: isinstance(child, wx.MDIChildFrame) and child.IsMaximized(), parentFrame.GetChildren())
+ if childrenMaximized:
+ maximize = True
+ else:
+ children = filter(lambda child: isinstance(child, wx.MDIChildFrame), parentFrame.GetChildren())
+ if children:
+ # other windows exist and none are maximized
+ maximize = False
+ else:
+ # get default setting from registry
+ maximize = wx.ConfigBase_Get().ReadInt("MDIChildFrameMaximized", False)
+
+ frame = wx.lib.docview.DocMDIChildFrame(doc, view, wx.GetApp().GetTopWindow(), id, title, pos, size, style)
+ if maximize: # wxBug: Should already be maximizing new child frames if one is maximized but it's not so we have to force it to
+ frame.Maximize(True)
+
+## wx.EVT_MAXIMIZE(frame, self.OnMaximize) # wxBug: This doesn't work, need to save MDIChildFrameMaximized state on close of windows instead
+ wx.EVT_CLOSE(frame, self.OnCloseChildWindow)
+ if not self._registeredCloseEvent:
+ wx.EVT_CLOSE(parentFrame, self.OnCloseMainWindow) # need to check on this, but only once
+ self._registeredCloseEvent = True
+
+ return frame
+
+
+ def SaveMDIDocumentFrameMaximizedState(self, maximized):
+ """
+ Remember in the config whether the MDI Frame is maximized so that it can be restored
+ on open.
+ """
+ config = wx.ConfigBase_Get()
+ maximizeFlag = config.ReadInt("MDIChildFrameMaximized", False)
+ if maximized != maximizeFlag:
+ config.WriteInt("MDIChildFrameMaximized", maximized)
+
+
+ def OnCloseChildWindow(self, event):
+ """
+ Called when an MDI Child Frame is closed. Calls SaveMDIDocumentFrameMaximizedState to
+ remember whether the MDI Frame is maximized so that it can be restored on open.
+ """
+ self.SaveMDIDocumentFrameMaximizedState(event.GetEventObject().IsMaximized())
+ event.Skip()
+
+
+ def OnCloseMainWindow(self, event):
+ """
+ Called when the MDI Parent Frame is closed. Remembers whether the MDI Parent Frame is
+ maximized.
+ """
+ children = event.GetEventObject().GetChildren()
+ childrenMaximized = filter(lambda child: isinstance(child, wx.MDIChildFrame)and child.IsMaximized(), children)
+ if childrenMaximized:
+ self.SaveMDIDocumentFrameMaximizedState(True)
+ else:
+ childrenNotMaximized = filter(lambda child: isinstance(child, wx.MDIChildFrame), children)
+
+ if childrenNotMaximized:
+ # other windows exist and none are maximized
+ self.SaveMDIDocumentFrameMaximizedState(False)
+
+ event.Skip()
+
+
+ def GetDefaultIcon(self):
+ """
+ Returns the application's default icon.
+ """
+ return self._defaultIcon
+
+
+ def SetDefaultIcon(self, icon):
+ """
+ Sets the application's default icon.
+ """
+ self._defaultIcon = icon
+
+
+ def GetDebug(self):
+ """
+ Returns True if the application is in debug mode.
+ """
+ return self._debug
+
+
+ def SetDebug(self, debug):
+ """
+ Sets the application's debug mode.
+ """
+ self._debug = debug
+
+
+ def GetSingleInstance(self):
+ """
+ Returns True if the application is in single instance mode. Used to determine if multiple instances of the application is allowed to launch.
+ """
+ return self._singleInstance
+
+
+ def SetSingleInstance(self, singleInstance):
+ """
+ Sets application's single instance mode.
+ """
+ self._singleInstance = singleInstance
+
+
+
+ def CreateChildDocument(self, parentDocument, documentType, objectToEdit, path=''):
+ """
+ Creates a child window of a document that edits an object. The child window
+ is managed by the parent document frame, so it will be prompted to close if its
+ parent is closed, etc. Child Documents are useful when there are complicated
+ Views of a Document and users will need to tunnel into the View.
+ """
+ for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
+ if isinstance(document, ChildDocument) and document.GetParentDocument() == parentDocument:
+ if document.GetData() == objectToEdit:
+ if hasattr(document.GetFirstView().GetFrame(), "SetFocus"):
+ document.GetFirstView().GetFrame().SetFocus()
+ return document
+ for temp in wx.GetApp().GetDocumentManager().GetTemplates():
+ if temp.GetDocumentType() == documentType:
+ break
+ temp = None
+ newDoc = temp.CreateDocument(path, 0, data = objectToEdit, parentDocument = parentDocument)
+ newDoc.SetDocumentName(temp.GetDocumentName())
+ newDoc.SetDocumentTemplate(temp)
+ if path == '':
+ newDoc.OnNewDocument()
+ else:
+ if not newDoc.OnOpenDocument(path):
+ newDoc.DeleteAllViews() # Implicitly deleted by DeleteAllViews
+ return None
+ return newDoc
+
+
+ def CloseChildDocuments(self, parentDocument):
+ """
+ Closes the child windows of a Document.
+ """
+ for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
+ if isinstance(document, ChildDocument) and document.GetParentDocument() == parentDocument:
+ if document.GetFirstView().GetFrame():
+ document.GetFirstView().GetFrame().SetFocus()
+ if not document.GetFirstView().OnClose():
+ return False
+ return True
+
+
+ def IsMDI(self):
+ """
+ Returns True if the application is in MDI mode.
+ """
+ return self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_MDI
+
+
+ def IsSDI(self):
+ """
+ Returns True if the application is in SDI mode.
+ """
+ return self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI
+
+
+ def ShowSplash(self, image):
+ """
+ Shows a splash window with the given image. Input parameter 'image' can either be a wx.Bitmap or a filename.
+ """
+ if isinstance(image, wx.Bitmap):
+ splash_bmp = image
+ else:
+ splash_bmp = wx.Image(image).ConvertToBitmap()
+ self._splash = wx.SplashScreen(splash_bmp, wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_NO_TIMEOUT, 0, None, -1, style=wx.SIMPLE_BORDER|wx.FRAME_NO_TASKBAR)
+ self._splash.Show()
+
+
+ def CloseSplash(self):
+ """
+ Closes the splash window.
+ """
+ if self._splash:
+ self._splash.Close(True)
+
+
+class _DocFrameFileDropTarget(wx.FileDropTarget):
+ """
+ Class used to handle drops into the document frame.
+ """
+
+ def __init__(self, docManager, docFrame):
+ """
+ Initializes the FileDropTarget class with the active docManager and the docFrame.
+ """
+ wx.FileDropTarget.__init__(self)
+ self._docManager = docManager
+ self._docFrame = docFrame
+
+
+ def OnDropFiles(self, x, y, filenames):
+ """
+ Called when files are dropped in the drop target and tells the docManager to open
+ the files.
+ """
+ try:
+ for file in filenames:
+ self._docManager.CreateDocument(file, wx.lib.docview.DOC_SILENT)
+ except:
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("File Error")
+ wx.MessageBox("Could not open '%s'. '%s'" % (wx.lib.docview.FileNameFromPath(file), sys.exc_value),
+ msgTitle,
+ wx.OK | wx.ICON_EXCLAMATION,
+ self._docManager.FindSuitableParent())
+
+
+class DocMDIParentFrame(wx.lib.docview.DocMDIParentFrame, DocFrameMixIn, DocMDIParentFrameMixIn):
+ """
+ The DocMDIParentFrame is the primary frame which the DocApp uses to host MDI child windows. It offers
+ features such as a default menubar, toolbar, and status bar, and a mechanism to manage embedded windows
+ on the edges of the DocMDIParentFrame.
+ """
+
+
+ def __init__(self, docManager, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="DocMDIFrame", embeddedWindows=0, minSize=20):
+ """
+ Initializes the DocMDIParentFrame with the default menubar, toolbar, and status bar. Use the
+ optional embeddedWindows parameter with the embedded window constants to create embedded
+ windows around the edges of the DocMDIParentFrame.
+ """
+ pos, size = self._GetPosSizeFromConfig(pos, size)
+ wx.lib.docview.DocMDIParentFrame.__init__(self, docManager, parent, id, title, pos, size, style, name)
+ self._InitFrame(embeddedWindows, minSize)
+
+
+ def _LayoutFrame(self):
+ """
+ Lays out the frame.
+ """
+ wx.LayoutAlgorithm().LayoutMDIFrame(self)
+ self.GetClientWindow().Refresh()
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if wx.GetApp().ProcessEventBeforeWindows(event):
+ return True
+ if wx.lib.docview.DocMDIParentFrame.ProcessEvent(self, event):
+ return True
+ return DocMDIParentFrameMixIn.ProcessEvent(self, event)
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
+ return True
+ if wx.lib.docview.DocMDIParentFrame.ProcessUpdateUIEvent(self, event): # Let the views handle the event before the services
+ return True
+ if event.GetId() == wx.ID_ABOUT: # Using ID_ABOUT to update the window menu, the window menu items are not triggering
+ self.UpdateWindowMenu()
+ return True
+ return DocMDIParentFrameMixIn.ProcessUpdateUIEvent(self, event)
+
+
+ def UpdateWindowMenu(self):
+ """
+ Updates the WindowMenu on Windows platforms.
+ """
+ if wx.Platform == '__WXMSW__':
+ children = filter(lambda child: isinstance(child, wx.MDIChildFrame), self.GetChildren())
+ windowCount = len(children)
+ hasWindow = windowCount >= 1
+ has2OrMoreWindows = windowCount >= 2
+
+ windowMenu = self.GetWindowMenu()
+ if windowMenu:
+ windowMenu.Enable(wx.IDM_WINDOWTILE, hasWindow)
+ windowMenu.Enable(wx.IDM_WINDOWTILEHOR, hasWindow)
+ windowMenu.Enable(wx.IDM_WINDOWCASCADE, hasWindow)
+ windowMenu.Enable(wx.IDM_WINDOWICONS, hasWindow)
+ windowMenu.Enable(wx.IDM_WINDOWTILEVERT, hasWindow)
+ wx.IDM_WINDOWPREV = 4006 # wxBug: Not defined for some reason
+ windowMenu.Enable(wx.IDM_WINDOWPREV, has2OrMoreWindows)
+ windowMenu.Enable(wx.IDM_WINDOWNEXT, has2OrMoreWindows)
+
+
+
+ def OnSize(self, event):
+ """
+ Called when the DocMDIParentFrame is resized and lays out the MDI client window.
+ """
+ # Needed in case there are splitpanels around the mdi frame
+ self._LayoutFrame()
+
+
+ def OnCloseWindow(self, event):
+ """
+ Called when the DocMDIParentFrame is closed. Remembers the frame size.
+ """
+ self.SaveEmbeddedWindowSizes()
+
+ # save and close services last.
+ for service in wx.GetApp().GetServices():
+ if not service.OnCloseFrame(event):
+ return
+
+ # save and close documents
+ # documents with a common view, e.g. project view, should save the document, but not close the window
+ # and let the service close the window.
+ wx.lib.docview.DocMDIParentFrame.OnCloseWindow(self, event)
+
+
+class DocSDIFrame(wx.lib.docview.DocChildFrame, DocFrameMixIn):
+ """
+ The DocSDIFrame host DocManager Document windows. It offers features such as a default menubar,
+ toolbar, and status bar.
+ """
+
+
+ def __init__(self, doc, view, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="DocSDIFrame"):
+ """
+ Initializes the DocSDIFrame with the default menubar, toolbar, and status bar.
+ """
+ wx.lib.docview.DocChildFrame.__init__(self, doc, view, parent, id, title, pos, size, style, name)
+ self._fileMenu = None
+ if doc:
+ self._docManager = doc.GetDocumentManager()
+ else:
+ self._docManager = None
+ self.SetDropTarget(_DocFrameFileDropTarget(self._docManager, self))
+
+ wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
+ wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
+ wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
+
+ self.InitializePrintData()
+
+ menuBar = self.CreateDefaultMenuBar(sdi=True)
+ toolBar = self.CreateDefaultToolBar()
+ self.SetToolBar(toolBar)
+ statusBar = self.CreateDefaultStatusBar()
+
+ for service in wx.GetApp().GetServices():
+ service.InstallControls(self, menuBar = menuBar, toolBar = toolBar, statusBar = statusBar, document = doc)
+
+ self.SetMenuBar(menuBar) # wxBug: Need to do this in SDI to mimic MDI... because have to set the menubar at the very end or the automatic MDI "window" menu doesn't get put in the right place when the services add new menus to the menubar
+
+
+ def _LayoutFrame(self):
+ """
+ Lays out the Frame.
+ """
+ self.Layout()
+
+
+ def OnExit(self, event):
+ """
+ Called when the application is exitting.
+ """
+ self._childView.GetDocumentManager().Clear(force = False)
+
+
+ def OnMRUFile(self, event):
+ """
+ Opens the appropriate file when it is selected from the file history
+ menu.
+ """
+ n = event.GetId() - wx.ID_FILE1
+ filename = self._docManager.GetHistoryFile(n)
+ if filename:
+ self._docManager.CreateDocument(filename, wx.lib.docview.DOC_SILENT)
+ else:
+ self._docManager.RemoveFileFromHistory(n)
+ msgTitle = wx.GetApp().GetAppName()
+ if not msgTitle:
+ msgTitle = _("File Error")
+ wx.MessageBox("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list" % docview.FileNameFromPath(file),
+ msgTitle,
+ wx.OK | wx.ICON_EXCLAMATION,
+ self)
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes an event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if wx.GetApp().ProcessEventBeforeWindows(event):
+ return True
+ if self._childView:
+ self._childView.Activate(True)
+
+ id = event.GetId()
+ if id == SAVEALL_ID:
+ self.OnFileSaveAll(event)
+ return True
+
+ if hasattr(self._childView, "GetDocumentManager") and self._childView.GetDocumentManager().ProcessEvent(event): # Need to call docmanager here since super class relies on DocParentFrame which we are not using
+ return True
+ else:
+ return wx.GetApp().ProcessEvent(event)
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Processes a UI event, searching event tables and calling zero or more
+ suitable event handler function(s). Note that the ProcessEvent
+ method is called from the wxPython docview framework directly since
+ wxPython does not have a virtual ProcessEvent function.
+ """
+ if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
+ return True
+ if self._childView:
+ if hasattr(self._childView, "GetDocumentManager"):
+ docMgr = self._childView.GetDocumentManager()
+ if docMgr:
+ if docMgr.GetCurrentDocument() != self._childView.GetDocument():
+ return False
+ if docMgr.ProcessUpdateUIEvent(event): # Let the views handle the event before the services
+ return True
+ id = event.GetId()
+ if id == wx.ID_CUT:
+ event.Enable(False)
+ return True
+ elif id == wx.ID_COPY:
+ event.Enable(False)
+ return True
+ elif id == wx.ID_PASTE:
+ event.Enable(False)
+ return True
+ elif id == wx.ID_CLEAR:
+ event.Enable(False)
+ return True
+ elif id == wx.ID_SELECTALL:
+ event.Enable(False)
+ return True
+ elif id == SAVEALL_ID:
+ filesModified = False
+ docs = wx.GetApp().GetDocumentManager().GetDocuments()
+ for doc in docs:
+ if doc.IsModified():
+ filesModified = True
+ break
+
+ event.Enable(filesModified)
+ return True
+ else:
+ return wx.GetApp().ProcessUpdateUIEvent(event)
+
+
+ def OnCloseWindow(self, event):
+ """
+ Called when the window is saved. Enables services to help close the frame.
+ """
+ for service in wx.GetApp().GetServices():
+ service.OnCloseFrame(event)
+ wx.lib.docview.DocChildFrame.OnCloseWindow(self, event)
+ if self._fileMenu and self._docManager:
+ self._docManager.FileHistoryRemoveMenu(self._fileMenu)
+
+
+class AboutService(DocService):
+ """
+ About Dialog Service that installs under the Help menu to show the properties of the current application.
+ """
+
+ def __init__(self, aboutDialog=None, image=None):
+ """
+ Initializes the AboutService.
+ """
+ if aboutDialog:
+ self._dlg = aboutDialog
+ self._image = None
+ else:
+ self._dlg = AboutDialog # use default AboutDialog
+ self._image = image
+
+
+ def ShowAbout(self):
+ """
+ Show the AboutDialog
+ """
+ if self._image:
+ dlg = self._dlg(wx.GetApp().GetTopWindow(), self._image)
+ else:
+ dlg = self._dlg(wx.GetApp().GetTopWindow())
+ dlg.CenterOnParent()
+ dlg.ShowModal()
+ dlg.Destroy()
+
+
+ def SetAboutDialog(self, dlg):
+ """
+ Customize the AboutDialog
+ """
+ self._dlg = dlg
+
+
+class AboutDialog(wx.Dialog):
+ """
+ Opens an AboutDialog. Shared by DocMDIParentFrame and DocSDIFrame.
+ """
+
+ def __init__(self, parent, image=None):
+ """
+ Initializes the about dialog.
+ """
+ wx.Dialog.__init__(self, parent, -1, _("About ") + wx.GetApp().GetAppName(), style = wx.DEFAULT_DIALOG_STYLE)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ if image:
+ imageItem = wx.StaticBitmap(self, -1, image.ConvertToBitmap(), (0,0), (image.GetWidth(), image.GetHeight()))
+ sizer.Add(imageItem, 0, wx.ALIGN_CENTER|wx.ALL, 0)
+ sizer.Add(wx.StaticText(self, -1, wx.GetApp().GetAppName()), 0, wx.ALIGN_CENTRE|wx.ALL, 5)
+
+ btn = wx.Button(self, wx.ID_OK)
+ sizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
+
+ self.SetSizer(sizer)
+ sizer.Fit(self)
+
+
+
+class FilePropertiesService(DocService):
+ """
+ Service that installs under the File menu to show the properties of the file associated
+ with the current document.
+ """
+
+ PROPERTIES_ID = wx.NewId()
+
+
+ def __init__(self):
+ """
+ Initializes the PropertyService.
+ """
+ self._customEventHandlers = []
+
+
+ def InstallControls(self, frame, menuBar=None, toolBar=None, statusBar=None, document=None):
+ """
+ Installs a File/Properties menu item.
+ """
+ fileMenu = menuBar.GetMenu(menuBar.FindMenu(_("&File")))
+ exitMenuItemPos = self.GetMenuItemPos(fileMenu, wx.ID_EXIT)
+ fileMenu.InsertSeparator(exitMenuItemPos)
+ fileMenu.Insert(exitMenuItemPos, FilePropertiesService.PROPERTIES_ID, _("&Properties"), _("Show file properties"))
+ wx.EVT_MENU(frame, FilePropertiesService.PROPERTIES_ID, self.ProcessEvent)
+ wx.EVT_UPDATE_UI(frame, FilePropertiesService.PROPERTIES_ID, self.ProcessUpdateUIEvent)
+
+
+ def ProcessEvent(self, event):
+ """
+ Detects when the File/Properties menu item is selected.
+ """
+ id = event.GetId()
+ if id == FilePropertiesService.PROPERTIES_ID:
+ for eventHandler in self._customEventHandlers:
+ if eventHandler.ProcessEvent(event):
+ return True
+
+ self.ShowPropertiesDialog()
+ return True
+ else:
+ return False
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Updates the File/Properties menu item.
+ """
+ id = event.GetId()
+ if id == FilePropertiesService.PROPERTIES_ID:
+ for eventHandler in self._customEventHandlers:
+ if eventHandler.ProcessUpdateUIEvent(event):
+ return True
+
+ event.Enable(wx.GetApp().GetDocumentManager().GetCurrentDocument() != None)
+ return True
+ else:
+ return False
+
+
+ def ShowPropertiesDialog(self, filename=None):
+ """
+ Shows the PropertiesDialog for the specified file.
+ """
+ if not filename:
+ filename = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
+
+ filePropertiesDialog = FilePropertiesDialog(wx.GetApp().GetTopWindow(), filename)
+ filePropertiesDialog.CenterOnParent()
+ if filePropertiesDialog.ShowModal() == wx.ID_OK:
+ pass # Handle OK
+ filePropertiesDialog.Destroy()
+
+
+ def GetCustomEventHandlers(self):
+ """
+ Returns the custom event handlers for the PropertyService.
+ """
+ return self._customEventHandlers
+
+
+ def AddCustomEventHandler(self, handler):
+ """
+ Adds a custom event handlers for the PropertyService. A custom event handler enables
+ a different dialog to be provided for a particular file.
+ """
+ self._customEventHandlers.append(handler)
+
+
+ def RemoveCustomEventHandler(self, handler):
+ """
+ Removes a custom event handler from the PropertyService.
+ """
+ self._customEventHandlers.remove(handler)
+
+
+ def chopPath(self, text, length=36):
+ """
+ Simple version of textwrap. textwrap.fill() unfortunately chops lines at spaces
+ and creates odd word boundaries. Instead, we will chop the path without regard to
+ spaces, but pay attention to path delimiters.
+ """
+ chopped = ""
+ textLen = len(text)
+ start = 0
+
+ while start < textLen:
+ end = start + length
+ if end > textLen:
+ end = textLen
+
+ # see if we can find a delimiter to chop the path
+ if end < textLen:
+ lastSep = text.rfind(os.sep, start, end + 1)
+ if lastSep != -1 and lastSep != start:
+ end = lastSep
+
+ if len(chopped):
+ chopped = chopped + '\n' + text[start:end]
+ else:
+ chopped = text[start:end]
+
+ start = end
+
+ return chopped
+
+
+class FilePropertiesDialog(wx.Dialog):
+ """
+ Dialog that shows the properties of a file. Invoked by the PropertiesService.
+ """
+
+
+ def __init__(self, parent, filename):
+ """
+ Initializes the properties dialog.
+ """
+ wx.Dialog.__init__(self, parent, -1, _("File Properties"), size=(310, 330))
+
+ HALF_SPACE = 5
+ SPACE = 10
+
+ filePropertiesService = wx.GetApp().GetService(FilePropertiesService)
+
+ fileExists = os.path.exists(filename)
+
+ notebook = wx.Notebook(self, -1)
+ tab = wx.Panel(notebook, -1)
+
+ gridSizer = RowColSizer()
+
+ gridSizer.Add(wx.StaticText(tab, -1, _("Filename:")), flag=wx.RIGHT, border=HALF_SPACE, row=0, col=0)
+ gridSizer.Add(wx.StaticText(tab, -1, os.path.basename(filename)), row=0, col=1)
+
+ gridSizer.Add(wx.StaticText(tab, -1, _("Location:")), flag=wx.RIGHT, border=HALF_SPACE, row=1, col=0)
+ gridSizer.Add(wx.StaticText(tab, -1, filePropertiesService.chopPath(os.path.dirname(filename))), flag=wx.BOTTOM, border=SPACE, row=1, col=1)
+
+ gridSizer.Add(wx.StaticText(tab, -1, _("Size:")), flag=wx.RIGHT, border=HALF_SPACE, row=2, col=0)
+ if fileExists:
+ gridSizer.Add(wx.StaticText(tab, -1, str(os.path.getsize(filename)) + ' ' + _("bytes")), row=2, col=1)
+
+ lineSizer = wx.BoxSizer(wx.VERTICAL) # let the line expand horizontally without vertical expansion
+ lineSizer.Add(wx.StaticLine(tab, -1, size = (10,-1)), 0, wx.EXPAND)
+ gridSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=HALF_SPACE, row=3, col=0, colspan=2)
+
+ gridSizer.Add(wx.StaticText(tab, -1, _("Created:")), flag=wx.RIGHT, border=HALF_SPACE, row=4, col=0)
+ if fileExists:
+ gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getctime(filename))), row=4, col=1)
+
+ gridSizer.Add(wx.StaticText(tab, -1, _("Modified:")), flag=wx.RIGHT, border=HALF_SPACE, row=5, col=0)
+ if fileExists:
+ gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getmtime(filename))), row=5, col=1)
+
+ gridSizer.Add(wx.StaticText(tab, -1, _("Accessed:")), flag=wx.RIGHT, border=HALF_SPACE, row=6, col=0)
+ if fileExists:
+ gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getatime(filename))), row=6, col=1)
+
+ # add a border around the inside of the tab
+ spacerGrid = wx.BoxSizer(wx.VERTICAL)
+ spacerGrid.Add(gridSizer, 0, wx.ALL, SPACE);
+ tab.SetSizer(spacerGrid)
+ notebook.AddPage(tab, _("General"))
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(notebook, 0, wx.ALL | wx.EXPAND, SPACE)
+ sizer.Add(self.CreateButtonSizer(wx.OK), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
+
+ sizer.Fit(self)
+ self.SetDimensions(-1, -1, 310, -1, wx.SIZE_USE_EXISTING)
+ self.SetSizer(sizer)
+ self.Layout()
+
+
+class ChildDocument(wx.lib.docview.Document):
+ """
+ A ChildDocument is a document that represents a portion of a Document. The child
+ document is managed by the parent document, so it will be prompted to close if its
+ parent is closed, etc. Child Documents are useful when there are complicated
+ Views of a Document and users will need to tunnel into the View.
+ """
+
+
+ def GetData(self):
+ """
+ Returns the data that the ChildDocument contains.
+ """
+ return self._data
+
+
+ def SetData(self, data):
+ """
+ Sets the data that the ChildDocument contains.
+ """
+ self._data = data
+
+
+ def GetParentDocument(self):
+ """
+ Returns the parent Document of the ChildDocument.
+ """
+ return self._parentDocument
+
+
+ def SetParentDocument(self, parentDocument):
+ """
+ Sets the parent Document of the ChildDocument.
+ """
+ self._parentDocument = parentDocument
+
+
+ def OnSaveDocument(self, filename):
+ """
+ Called when the ChildDocument is saved and does the minimum such that the
+ ChildDocument looks like a real Document to the framework.
+ """
+ self.SetFilename(filename, True)
+ self.Modify(False)
+ self.SetDocumentSaved(True)
+ return True
+
+
+ def OnOpenDocument(self, filename):
+ """
+ Called when the ChildDocument is opened and does the minimum such that the
+ ChildDocument looks like a real Document to the framework.
+ """
+ self.SetFilename(filename, True)
+ self.Modify(False)
+ self.SetDocumentSaved(True)
+ self.UpdateAllViews()
+ return True
+
+
+ def Save(self):
+ """
+ Called when the ChildDocument is saved and does the minimum such that the
+ ChildDocument looks like a real Document to the framework.
+ """
+ return self.OnSaveDocument(self._documentFile)
+
+
+ def SaveAs(self):
+ """
+ Called when the ChildDocument is saved and does the minimum such that the
+ ChildDocument looks like a real Document to the framework.
+ """
+ return self.OnSaveDocument(self._documentFile)
+
+
+class ChildDocTemplate(wx.lib.docview.DocTemplate):
+ """
+ A ChildDocTemplate is a DocTemplate subclass that enables the creation of ChildDocuments
+ that represents a portion of a Document. The child document is managed by the parent document,
+ so it will be prompted to close if its parent is closed, etc. Child Documents are useful
+ when there are complicated Views of a Document and users will need to tunnel into the View.
+ """
+
+
+ def __init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags=wx.lib.docview.TEMPLATE_INVISIBLE, icon=None):
+ """
+ Initializes the ChildDocTemplate.
+ """
+ wx.lib.docview.DocTemplate.__init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags=flags, icon=icon)
+
+
+ def CreateDocument(self, path, flags, data=None, parentDocument=None):
+ """
+ Called when a ChildDocument is to be created and does the minimum such that the
+ ChildDocument looks like a real Document to the framework.
+ """
+ doc = self._docType()
+ doc.SetFilename(path)
+ doc.SetData(data)
+ doc.SetParentDocument(parentDocument)
+ doc.SetDocumentTemplate(self)
+ self.GetDocumentManager().AddDocument(doc)
+ doc.SetCommandProcessor(doc.OnCreateCommandProcessor())
+ if doc.OnCreate(path, flags):
+ return doc
+ else:
+ if doc in self.GetDocumentManager().GetDocuments():
+ doc.DeleteAllViews()
+ return None
+
+
+class WindowMenuService(DocService):
+ """
+ The WindowMenuService is a service that implements a standard Window menu that is used
+ by the DocSDIFrame. The MDIFrame automatically includes a Window menu and does not use
+ the WindowMenuService.
+ """
+
+ #----------------------------------------------------------------------------
+ # Constants
+ #----------------------------------------------------------------------------
+ ARRANGE_WINDOWS_ID = wx.NewId()
+ SELECT_MORE_WINDOWS_ID = wx.NewId()
+ SELECT_NEXT_WINDOW_ID = wx.NewId()
+ SELECT_PREV_WINDOW_ID = wx.NewId()
+ CLOSE_CURRENT_WINDOW_ID = wx.NewId()
+
+
+ def __init__(self):
+ """
+ Initializes the WindowMenu and its globals.
+ """
+ self._selectWinIds = []
+ for i in range(0, 9):
+ self._selectWinIds.append(wx.NewId())
+
+
+ def InstallControls(self, frame, menuBar=None, toolBar=None, statusBar=None, document=None):
+ """
+ Installs the Window menu.
+ """
+
+ windowMenu = None
+ if hasattr(frame, "GetWindowMenu"):
+ windowMenu = frame.GetWindowMenu()
+ if not windowMenu:
+ needWindowMenu = True
+ windowMenu = wx.Menu()
+ else:
+ needWindowMenu = False
+
+ if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
+ if not _WINDOWS: # Arrange All and window navigation doesn't work on Linux
+ return
+
+ item = windowMenu.Append(self.ARRANGE_WINDOWS_ID, _("&Arrange All"), _("Arrange the open windows"))
+ wx.EVT_MENU(frame, self.ARRANGE_WINDOWS_ID, frame.ProcessEvent)
+ wx.EVT_UPDATE_UI(frame, self.ARRANGE_WINDOWS_ID, frame.ProcessUpdateUIEvent)
+ windowMenu.AppendSeparator()
+
+ for i, id in enumerate(self._selectWinIds):
+ wx.EVT_MENU(frame, id, frame.ProcessEvent)
+ wx.EVT_MENU(frame, self.SELECT_MORE_WINDOWS_ID, frame.ProcessEvent)
+ elif wx.GetApp().GetUseTabbedMDI():
+ item = windowMenu.Append(self.SELECT_PREV_WINDOW_ID, _("Previous"), _("Previous Tab"))
+ wx.EVT_MENU(frame, self.SELECT_PREV_WINDOW_ID, frame.ProcessEvent)
+ wx.EVT_UPDATE_UI(frame, self.SELECT_PREV_WINDOW_ID, frame.ProcessUpdateUIEvent)
+ item = windowMenu.Append(self.SELECT_NEXT_WINDOW_ID, _("Next"), _("Next Tab"))
+ wx.EVT_MENU(frame, self.SELECT_NEXT_WINDOW_ID, frame.ProcessEvent)
+ wx.EVT_UPDATE_UI(frame, self.SELECT_NEXT_WINDOW_ID, frame.ProcessUpdateUIEvent)
+ item = windowMenu.Append(self.CLOSE_CURRENT_WINDOW_ID, _("Close Current\tCtrl+F4"), _("Close Current Tab"))
+ wx.EVT_MENU(frame, self.CLOSE_CURRENT_WINDOW_ID, frame.ProcessEvent)
+ wx.EVT_UPDATE_UI(frame, self.CLOSE_CURRENT_WINDOW_ID, frame.ProcessUpdateUIEvent)
+ self._sep = None
+
+ for i, id in enumerate(self._selectWinIds):
+ wx.EVT_MENU(frame, id, self.OnCtrlKeySelect)
+
+ if needWindowMenu:
+ helpMenuIndex = menuBar.FindMenu(_("&Help"))
+ menuBar.Insert(helpMenuIndex, windowMenu, _("&Window"))
+
+ self._lastFrameUpdated = None
+
+
+ def OnCtrlKeySelect(self, event):
+ i = self._selectWinIds.index(event.GetId())
+ notebook = wx.GetApp().GetTopWindow()._notebook
+ if i < notebook.GetPageCount():
+ notebook.SetSelection(i)
+
+
+ def ProcessEvent(self, event):
+ """
+ Processes a Window menu event.
+ """
+ id = event.GetId()
+ if id == self.ARRANGE_WINDOWS_ID:
+ self.OnArrangeWindows(event)
+ return True
+ elif id == self.SELECT_MORE_WINDOWS_ID:
+ self.OnSelectMoreWindows(event)
+ return True
+ elif id in self._selectWinIds:
+ self.OnSelectWindowMenu(event)
+ return True
+ elif wx.GetApp().GetUseTabbedMDI():
+ if id == self.SELECT_NEXT_WINDOW_ID:
+ notebook = wx.GetApp().GetTopWindow()._notebook
+ i = notebook.GetSelection()
+ notebook.SetSelection(i+1)
+ return True
+ elif id == self.SELECT_PREV_WINDOW_ID:
+ notebook = wx.GetApp().GetTopWindow()._notebook
+ i = notebook.GetSelection()
+ notebook.SetSelection(i-1)
+ return True
+ elif id == self.CLOSE_CURRENT_WINDOW_ID:
+ notebook = wx.GetApp().GetTopWindow()._notebook
+ i = notebook.GetSelection()
+ if i != -1:
+ doc = notebook.GetPage(i).GetView().GetDocument()
+ wx.GetApp().GetDocumentManager().CloseDocument(doc, False)
+ return True
+ else:
+ return False
+
+
+ def ProcessUpdateUIEvent(self, event):
+ """
+ Updates the Window menu items.
+ """
+ id = event.GetId()
+ if id == self.ARRANGE_WINDOWS_ID:
+ frame = event.GetEventObject()
+ if not self._lastFrameUpdated or self._lastFrameUpdated != frame:
+ self.BuildWindowMenu(frame) # It's a new frame, so update the windows menu... this is as if the View::OnActivateMethod had been invoked
+ self._lastFrameUpdated = frame
+ return True
+ elif wx.GetApp().GetUseTabbedMDI():
+ if id == self.SELECT_NEXT_WINDOW_ID:
+ self.BuildWindowMenu(event.GetEventObject()) # build file list only when we are updating the windows menu
+
+ notebook = wx.GetApp().GetTopWindow()._notebook
+ i = notebook.GetSelection()
+ if i == -1:
+ event.Enable(False)
+ return True
+ i += 1
+ if i >= notebook.GetPageCount():
+ event.Enable(False)
+ return True
+ event.Enable(True)
+ return True
+ elif id == self.SELECT_PREV_WINDOW_ID:
+ notebook = wx.GetApp().GetTopWindow()._notebook
+ i = notebook.GetSelection()
+ if i == -1:
+ event.Enable(False)
+ return True
+ i -= 1
+ if i < 0:
+ event.Enable(False)
+ return True
+ event.Enable(True)
+ return True
+ elif id == self.CLOSE_CURRENT_WINDOW_ID:
+ event.Enable(wx.GetApp().GetTopWindow()._notebook.GetSelection() != -1)
+ return True
+
+ return False
+ else:
+ return False
+
+
+ def BuildWindowMenu(self, currentFrame):
+ """
+ Builds the Window menu and adds menu items for all of the open documents in the DocManager.
+ """
+ if wx.GetApp().GetUseTabbedMDI():
+ currentFrame = wx.GetApp().GetTopWindow()
+
+ windowMenuIndex = currentFrame.GetMenuBar().FindMenu(_("&Window"))
+ windowMenu = currentFrame.GetMenuBar().GetMenu(windowMenuIndex)
+
+ if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
+ frames = self._GetWindowMenuFrameList(currentFrame)
+ max = WINDOW_MENU_NUM_ITEMS
+ if max > len(frames):
+ max = len(frames)
+ i = 0
+ for i in range(0, max):
+ frame = frames[i]
+ item = windowMenu.FindItemById(self._selectWinIds[i])
+ label = '&' + str(i + 1) + ' ' + frame.GetTitle()
+ if not item:
+ item = windowMenu.AppendCheckItem(self._selectWinIds[i], label)
+ else:
+ windowMenu.SetLabel(self._selectWinIds[i], label)
+ windowMenu.Check(self._selectWinIds[i], (frame == currentFrame))
+ if len(frames) > WINDOW_MENU_NUM_ITEMS: # Add the more items item
+ if not windowMenu.FindItemById(self.SELECT_MORE_WINDOWS_ID):
+ windowMenu.Append(self.SELECT_MORE_WINDOWS_ID, _("&More Windows..."))
+ else: # Remove any extra items
+ if windowMenu.FindItemById(self.SELECT_MORE_WINDOWS_ID):
+ windowMenu.Remove(self.SELECT_MORE_WINDOWS_ID)
+
+ for j in range(i + 1, WINDOW_MENU_NUM_ITEMS):
+ if windowMenu.FindItemById(self._selectWinIds[j]):
+ windowMenu.Remove(self._selectWinIds[j])
+
+ elif wx.GetApp().GetUseTabbedMDI():
+ notebook = wx.GetApp().GetTopWindow()._notebook
+ numPages = notebook.GetPageCount()
+
+ for id in self._selectWinIds:
+ item = windowMenu.FindItemById(id)
+ if item:
+ windowMenu.DeleteItem(item)
+ if numPages == 0 and self._sep:
+ windowMenu.DeleteItem(self._sep)
+ self._sep = None
+
+ if numPages > len(self._selectWinIds):
+ for i in range(len(self._selectWinIds), numPages):
+ self._selectWinIds.append(wx.NewId())
+ wx.EVT_MENU(currentFrame, self._selectWinIds[i], self.OnCtrlKeySelect)
+
+ for i in range(0, numPages):
+ if i == 0 and not self._sep:
+ self._sep = windowMenu.AppendSeparator()
+ if i < 9:
+ menuLabel = "%s\tCtrl+%s" % (notebook.GetPageText(i), i+1)
+ else:
+ menuLabel = notebook.GetPageText(i)
+ windowMenu.Append(self._selectWinIds[i], menuLabel)
+
+
+ def _GetWindowMenuIDList(self):
+ """
+ Returns a list of the Window menu item IDs.
+ """
+ return self._selectWinIds
+
+
+ def _GetWindowMenuFrameList(self, currentFrame=None):
+ """
+ Returns the Frame associated with each menu item in the Window menu.
+ """
+ frameList = []
+ # get list of windows for documents
+ for doc in self._docManager.GetDocuments():
+ for view in doc.GetViews():
+ frame = view.GetFrame()
+ if frame not in frameList:
+ if frame == currentFrame and len(frameList) >= WINDOW_MENU_NUM_ITEMS:
+ frameList.insert(WINDOW_MENU_NUM_ITEMS - 1, frame)
+ else:
+ frameList.append(frame)
+ # get list of windows for general services
+ for service in wx.GetApp().GetServices():
+ view = service.GetView()
+ if view:
+ frame = view.GetFrame()
+ if frame not in frameList:
+ if frame == currentFrame and len(frameList) >= WINDOW_MENU_NUM_ITEMS:
+ frameList.insert(WINDOW_MENU_NUM_ITEMS - 1, frame)
+ else:
+ frameList.append(frame)
+
+ return frameList
+
+
+ def OnArrangeWindows(self, event):
+ """
+ Called by Window/Arrange and tiles the frames on the desktop.
+ """
+ currentFrame = event.GetEventObject()
+
+ tempFrame = wx.Frame(None, -1, "", pos = wx.DefaultPosition, size = wx.DefaultSize)
+ sizex = tempFrame.GetSize()[0]
+ sizey = tempFrame.GetSize()[1]
+ tempFrame.Destroy()
+
+ posx = 0
+ posy = 0
+ delta = 0
+ frames = self._GetWindowMenuFrameList()
+ frames.remove(currentFrame)
+ frames.append(currentFrame) # Make the current frame the last frame so that it is the last one to appear
+ for frame in frames:
+ if delta == 0:
+ delta = frame.GetClientAreaOrigin()[1]
+ frame.SetPosition((posx, posy))
+ frame.SetSize((sizex, sizey))
+ # TODO: Need to loop around if posx + delta + size > displaysize
+ frame.SetFocus()
+ posx = posx + delta
+ posy = posy + delta
+ if posx + sizex > wx.DisplaySize()[0] or posy + sizey > wx.DisplaySize()[1]:
+ posx = 0
+ posy = 0
+ currentFrame.SetFocus()
+
+
+ def OnSelectWindowMenu(self, event):
+ """
+ Called when the Window menu item representing a Frame is selected and brings the selected
+ Frame to the front of the desktop.
+ """
+ id = event.GetId()
+ index = self._selectWinIds.index(id)
+ if index > -1:
+ currentFrame = event.GetEventObject()
+ frame = self._GetWindowMenuFrameList(currentFrame)[index]
+ if frame:
+ wx.CallAfter(frame.Raise)
+
+
+ def OnSelectMoreWindows(self, event):
+ """
+ Called when the "Window/Select More Windows..." menu item is selected and enables user to
+ select from the Frames that do not in the Window list. Useful when there are more than
+ 10 open frames in the application.
+ """
+ frames = self._GetWindowMenuFrameList() # TODO - make the current window the first one
+ strings = map(lambda frame: frame.GetTitle(), frames)
+ # Should preselect the current window, but not supported by wx.GetSingleChoice
+ res = wx.GetSingleChoiceIndex(_("Select a window to show:"),
+ _("Select Window"),
+ strings,
+ self)
+ if res == -1:
+ return
+ frames[res].SetFocus()
+
+
+
+def getBlankIcon():
+ return Blank.GetIcon()
+
+#----------------------------------------------------------------------------
+# File generated by encode_bitmaps.py
+#----------------------------------------------------------------------------
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+New = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAQRJ"
+ "REFUOI2lk71qAkEQx397Z21l5WPkCYKFhYVvYeUr2FrYJ2X6gNjYWBlSxAeQBNFKCBcMclxW"
+ "4eT8gLU499i9D6I4MOzsMr//zsyyQjgu91jJ3HxMl0rHvgwB8NYBAFJGdFp1kVEQjpv45PNb"
+ "LXcq8a9t7M+DiRqtlOq+jJWZLxwX59pSyyV4aNRod1+VeW614MuQ6iUOT/G62cflvw/fWF3a"
+ "KRQwQQ0DPDZrbE/wd4R+78nKL2xBw0AC55lVgbcOqOztBBPeHP4RkDKyQMjCi9m8WMAENazB"
+ "IEpn5gjoKadv1bC/ywpkhngLnCtwCwypFn68X+ud0wPLM3Hvb7z6LxTZGR/7imGH8vcWAAAA"
+ "AElFTkSuQmCC")
+
+Open = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAWdJ"
+ "REFUOI2lkz1LQlEYx39Xbyk1FTk0REMEIdELTS3R0FSBurf4AVqa2/oIQUMQDrWGukRDYENN"
+ "YU7ZC1FGN+J6wWt6zcSX06DevFxvRf2nc87z/H/nec6LJLnc/EcyQPFiQwAYJc0SHF7cl34E"
+ "GOdLom9mBYD+jkDDyPJ6ShOsK+b6eChhgcqid4qGkYWqbkX3DODzzwNQfXwzl5MRVcyF0yZE"
+ "7vSIsvo1KasomSIAuYdjCzsZ8QuAuXBasgAA01TLpQAo5FVm17ZtvacO1onHosIEPF/f4xUa"
+ "tVa/Y6ubNlM3yUZJQ7/L4BUavullfK1AQ791NJ3sblGZ3GkCAOofGhVdYahwY0uuvz85ggLB"
+ "kCQbuoI86OuaXMsp3XwUchU8rbGrmZhiZGLUcafvZLsFp92PDi+dAYW8ClgrOEtcmeUCeBb2"
+ "ugIkyeU2H0Zb2otunnKnAsGQ7W9I7d8Yj0XFbwyOgL/qE6gYiTXnTLM6AAAAAElFTkSuQmCC")
+
+Copy = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAV9J"
+ "REFUOI2Nkr9LAmEYxz93+ifY0KDkdtAkTY1CERGlQn9AQ9BSQ3trOEWDNLQ1ChX9gGhoaNKt"
+ "SYKkIbiEytQ7pfJS4W3Q+/VeHn7h5V6ee76f9/u8d0qpogtGapjfANTqBgBm22Jvc1EhTKWK"
+ "LqpfIrCOzsui/CnETv5UKGqEsatU0UUsGXeAjZdXdz9BItVu8iqWjBNLxtFSGlpKY2FpHoD0"
+ "aprt/aLwAULnG6nZHT47A1jZWPdBVG9Ds+vGlmW2LR5u77k5OQPg6vJCAERrdYMpzYWMO31u"
+ "OQ2A0YdivgCzM8MEZttymjsDv0mGGv3gAapt7AyGDfaNe832OwCzJwHeP5o+upxINrcseH6q"
+ "Oj1Rn7nnH0Wut1y2H+CNFUgkmRs/EkDX39APCk4hkZie2AwQvT7eVexvCnD3+OtLFGZ2Rshk"
+ "c87/vbZ1KLyJvBf2nxRFjQSK3kRhymRzyh8MSdTaiEWdxAAAAABJRU5ErkJggg==")
+
+Paste = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAZBJ"
+ "REFUOI2Nkz9IAmEYh59Td7GpIXHIsD9C0JgQRFMQmIJD0RIazQ1iJq0aFDRGYFvUIGhCUEtD"
+ "g1CLNOSpdFCCmIhgJIKL2HDddael/ZZ7v+/9vc/3fnf3CoLBCEBN7HTRKHgSZWbKTi4vEVzc"
+ "06Zweo2CEguCwUhN7HQtY/eqIRDJ4F1yUqy0AcjlJeK7RjVffAypEAM9CkQyACTvnsnlJXJ5"
+ "Sd4/6Oh86atUF8DUC9gKbKhx/aMlt9l44a09wnG6wo77VefvAwCYbdbvp7IzydttBvuKj+B5"
+ "isDEEADAzUVCjZfXfWq8sOYhfplk0TEEoC1SJF0nqDRNNMoFcDh/B9Q/WphtcgeVppz2b3uw"
+ "zrsAsAPpw9jwK2g7ePn8y9ULaD5QencxPgtnpyldqlEuAGDbDA8AaE70b3t+PfmpDlmxindJ"
+ "8w5qBbCYHwB4LdWwzsPRfkxXmBWrzE2P/q8DAHcwzFP9Z237w9f3Kyt31RYPkgnk6XpOhr6n"
+ "Mar7TFmxOhAgKOMMPwPyX7lXPcIXHPiHmgMS17kAAAAASUVORK5CYII=")
+
+Save = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAR1J"
+ "REFUOI2dkz1Ow0AQhb/1oi3xEaCNQ4+CoOWnpuIEtHAAGvsCEVT0pKDBwVwBkFIixaSJUkQU"
+ "BCSiQAGxBEPhyLFgHUNeNTs/782MdpRyNPHFp1CCYf+3b/1AK5SjuW8iMqhLGIZShMGHyN3z"
+ "WHzfFxGRm2MkiiJx8oxaa6v60xge3xK67waA2xOVxRxrRQnWtvfsBEmSlKr/xFwd8NL9G0GZ"
+ "OsBC/rG78UAQBDPFjzavAOh1wF2eEAz7QG2SsL84zR61rG3bOxi1wF0lOH3NhSuZ1Y6/Mvv8"
+ "sGcfIVWs4Hle5jLGcNZoFI40c4nGpMtbqVb/R6C1zoqXalu047iQQCkn/b7X9eKD6nXsfncn"
+ "mhIAXDbD0qss7GBefAO233xRLqcViQAAAABJRU5ErkJggg==")
+
+SaveAll = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAVVJ"
+ "REFUOI2dk79Lw0Acxd8lAWfrIB2Ki4NNEekWiov/QKDdFCcXF0Ey6SwIyRSCbi5ubpreP+BS"
+ "O7g4mXboYIYKLiKBtrS0fh3SxF6SavUDx/1+9+5xxzwXhCmjHgSGM/3xMKy3j2UmLPJcEPkG"
+ "cc4pSX9M9NonMk2TiIgeLkCcc2KSjLh4LqhYNtB6smPRPzmJHPzXiYIE6586WvVsJzs54PHq"
+ "FMoSsOLraDggKSkAAMWygY7EsbVHQtk8IBT2CffvJipHYfaZAlkMJsDHCHjpAUEQoHnJFheY"
+ "3RxR0Y2fBTzPEzbPIxVixMnuGyzLivtBEMTt88MBAMBvA0qpJrOGY9NyIVvkNxQgfBTPtxNK"
+ "Tlo3q8Lp3W43nrs+ywGYyaBUk1mT20iiqio0TUO1Ws10IISY+ihT8vn83CswJsmpwYbzfR2/"
+ "DaxthPXCAgBQd+9SmWTxBXqU0GLLIFPzAAAAAElFTkSuQmCC")
+
+Print = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAadJ"
+ "REFUOI2lUz1Lw1AUPe+1IA72F7gkWBCngrQKXQVBB+tkJf4Cl4LgoIOjiLVF/QdqC3HqBxgo"
+ "ODo1FqJI8YtOEgl06YvdWp5DfGmT1A/wwOHmvtx73rnJe4TQEP6DsHg4bfa4afc9L/utB0+e"
+ "XZ8lAQVCQyA0hB29x/14sh1emZwf5o55tVrlol6QCqGDuTGyeztw8PzhxFfbiePLGaiqikq5"
+ "xIcN0OHEb/kvCAPAxfkZB4D7r53Fri02KDTtPppvQQF6cX7GFUWBoiju4tSEE+VIsME/BgWA"
+ "YrHoFrzaDlvMoWn3Mfx38vm8R4QUCgUei8Wg1a6xvZWBZVkjZ2232558Y3MfdzeXJGxabcQA"
+ "LC0uIJs/wXRUHinAGEMkEgFjzofpvuuolEucTkdlaLVrAIDRqCORSECW5QAlScLjSwuapkGS"
+ "JFc4vJJaJevpNW406gGrnU7H4yI5H0dyPu5Zc49yOp0GYwyGYXgKTMs7ux+E0BAq5RJXVRXN"
+ "N2Bm8sd6AICu68jlclhJrRIibmOlXOJ7Ryq67/qvAqLZdSDgP+ffQTQDwCfjgskYZ5COXQAA"
+ "AABJRU5ErkJggg==")
+
+PrintPreview = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAW1J"
+ "REFUOI2Nkr1LAmEcxz93GoVFBDU4OFhIYdEUIUFCDS69B20tQnkuTf4DTgUO7fkSNAQ1BBXc"
+ "2iY0tURDSoqBRQkugpE42PBwT3feGX3h4Xf3Oz7f38tzyt1DuUOXHotV+ZzYXVa6v5ulAvim"
+ "xi1nZT0MQHApzMHhpa2AzaCXhvtgNbrzp4nbKVn/FvEieyVztzfXnc2tbds4NgMDDkXCBNtQ"
+ "a8F5MkVkZtp5hObbk4SM2GiLU2v1atxkUGqOWGBDBpw/iuPvL6PrOrH9PdsuLCM02nYYLW0B"
+ "YtDJ5k7lLlRzy05weg6ifpELeAAtbelELVc+JWjAH1+/Fe/rkK/B4hh4PSKCuBXZgXlZZhjg"
+ "rCLAwBCExkQ0y/IjdcOybWB0ACYHRTTLXXguUUim7CQT+DNxXrQ0Xo+4pSJwnIijkeGdNQAU"
+ "RXXJeZyk67rlfbaaAWDBB/M5l6IoqqsXK9Vd4PVkQ5r8y8DJ0DD5ATHJh/O00XSvAAAAAElF"
+ "TkSuQmCC")
+
+Cut = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAUhJ"
+ "REFUOI2Fkk9LAlEUxX+jBX0bocCdtKpmNpNhEONeg2zfxqUbSUG0oJxN5SKEGP8QOLvwk7R2"
+ "FWiprxavhbxhdF7Tgbc599zzznv3YiSShE+n05GbXPjU67W1egINnh4fpI5vNRsSYNDvBXWt"
+ "QS6Xw3Xv10xazYa07WxEqzXQQQjBbDZlPl/EG4hvAUDeyQeRa9dVaZqW1nhrkygUzg1AHh4c"
+ "RcSe55FKpTjOnhh/GgAsF6uYtp1FCCFN04pEVzCMRFJbULFVo++PIrdDzCfuvXfxPC9ozkyG"
+ "Wp32CW8XuzJtOTB6xvchMxmSthzG3auINnaMacsJmhXCS6Q1ULcXbysALKafABRvK+yfFVi6"
+ "l/EJVEMc/l1lgHapzLjrMvv44vWuQbtU1uoiYxz0e3L7ZfVZP6fVgFfRdwo3a6PU7oGKGBbq"
+ "OIBfXKKLiCHSUwgAAAAASUVORK5CYII=")
+
+Undo = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAadJ"
+ "REFUOI2lkL9LW1EYhp9zI41/QnXI1snBoYPQFqFDQCqYxKIS2o41m4MEB0FwaBcpFt3UwaFa"
+ "G8UmOaZQuneom5ugU7Dij1wlMV6N3vo5hHPx6qUGPHCGw/me57zvUcoK8ZDVdN9AuhCVcs0B"
+ "YO71b9WwIF2ICkDXs14ALq/O2J0+EIAfQ1ueSAVVSBeichOsnV9QcY8BKDk23xbXWP+4rwIF"
+ "BjagKzXmswsc7lcAeNHzFICvk7/Yy7jqTgXT17ya0d8ZjExApH6fmuyjs6cNgHwuKz7B+9Xn"
+ "MvDyLVWn7INj8YTXOZ/LSmqpL/gTy+dVLq/OcKUGUI8d8SeMxRMqn8uKJ+hfbBeA5Tcb6tSu"
+ "x3f+OZQc24MeDzQJwF7GVUZi7qxT22H41Qjd00/EdDeruG2TWvJ3vv1nSmsts8URxt6NU5WK"
+ "17/k2Oyc7HKyU2Zt+Q8zyRXfy16CWDyhBiMTDH0aBiDc/Mg38D+4HsEKoawQWmvpGGuVn0dT"
+ "8qU4Kp83U9KSDIvWWsxM0PYdtNbSkgzL6t8PDcF3BDcljcCBAiNpBFZWiGuCvt7CsLLqpwAA"
+ "AABJRU5ErkJggg==")
+
+Redo = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAYhJ"
+ "REFUOI2lksFLAkEUxr9RCbwUdEr7DzIIukTdOuUh0q0kL4JGUAaZhwShg0QQC4XUqYwgKII8"
+ "rc6p/8Bb0im8dQmy0KW1lBR6HWSHXRtCaODB8N77fjPvm2HM4cR/lkuW3Nb8ZO5PlDvWN8AU"
+ "RmfXRa5+pVPj00Ah/igFMXOEbc1PViEANL8NAIDeruJCu5RCXAAQuZoS4ixXRXFjflPs15QY"
+ "qq9ZKmVebBCH9bQsV7E8mBZxmFeht6sAgEanDgAoFjSyAsAcTii5cVJy48Q5J+Zwwhoz+6N0"
+ "+7xL509bpFbC5EsO2/pcABDzHAAAAkFFapTRMVD/epOVuoBe4fTeCAFAKfPC3mstIa41dejP"
+ "LQCAZ2mAbB70rsRqFGOJITFvramL2sb1ChZ2JrsWyH5isaCR+hBHNLJoO73R/hA9/OgeZ5G8"
+ "/AaBoMLSE6c4Ob6R3s4UB4IKQ6/r1uCcky85TGolTKnyHKXKc+QNuW2v8CfAhHhDblIr4V/i"
+ "vgBWiOyf9AUwIbL8D+DEtq2XUuV6AAAAAElFTkSuQmCC")
+
+Blank = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAF1J"
+ "REFUOI3tkzEOwDAIA22S//84cYe2QxGJqFg61BMDOhsBpDVU1O9Cc2jXSGvcAgBAihkkoTkU"
+ "QSyV84JHKdMA8jT3kB52B+4e9DrBSj/gC4DHHfgdZ8TqN5ZHOACokRkohSNQfwAAAABJRU5E"
+ "rkJggg==")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pyshell.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pyshell.py
new file mode 100644
index 0000000..1dca90d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/pyshell.py
@@ -0,0 +1,349 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.pyshell
+# Purpose: A Python Interactive Interpreter running in a wxStyledTextCtrl
+# window.
+#
+# Author: Robin Dunn
+#
+# Created: 7-July-2000
+# RCS-ID: $Id$
+# Copyright: (c) 2000 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o Added deprecation warning.
+#
+
+"""
+PyShellWindow is a class that provides an Interactive Interpreter running
+inside a wxStyledTextCtrl, similar to the Python shell windows found in
+IDLE and PythonWin.
+
+There is still much to be done to improve this class, such as line
+buffering/recall, autoindent, calltips, autocomplete, fixing the colourizer,
+etc... But it's a good start.
+
+
+8-10-2001 THIS MODULE IS NOW DEPRECATED. Please see the most excellent
+ PyCrust package instead.
+
+"""
+
+import keyword
+import sys
+import warnings
+
+from code import InteractiveInterpreter
+
+import wx
+import wx.stc as stc
+
+warningmsg = r"""\
+
+########################################\
+# THIS MODULE IS NOW DEPRECATED |
+# |
+# Please see the most excellent PyCrust |
+# package instead. |
+########################################/
+
+"""
+
+warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
+
+#----------------------------------------------------------------------
+# default styles, etc. to use for the STC
+
+if wx.Platform == '__WXMSW__':
+ _defaultSize = 8
+else:
+ _defaultSize = 10
+
+
+_default_properties = {
+ 'selMargin' : 0,
+ 'marginWidth' : 1,
+ 'ps1' : '>>> ',
+ 'stdout' : 'fore:#0000FF',
+ 'stderr' : 'fore:#007f00',
+ 'trace' : 'fore:#FF0000',
+
+ 'default' : 'size:%d' % _defaultSize,
+ 'bracegood' : 'fore:#FFFFFF,back:#0000FF,bold',
+ 'bracebad' : 'fore:#000000,back:#FF0000,bold',
+
+ # properties for the various Python lexer styles
+ 'comment' : 'fore:#007F00',
+ 'number' : 'fore:#007F7F',
+ 'string' : 'fore:#7F007F,italic',
+ 'char' : 'fore:#7F007F,italic',
+ 'keyword' : 'fore:#00007F,bold',
+ 'triple' : 'fore:#7F0000',
+ 'tripledouble': 'fore:#7F0000',
+ 'class' : 'fore:#0000FF,bold,underline',
+ 'def' : 'fore:#007F7F,bold',
+ 'operator' : 'bold',
+
+ }
+
+
+# new style numbers
+_stdout_style = 15
+_stderr_style = 16
+_trace_style = 17
+
+
+#----------------------------------------------------------------------
+
+class PyShellWindow(stc.StyledTextCtrl, InteractiveInterpreter):
+ def __init__(self, parent, ID, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0,
+ locals=None, properties=None, banner=None):
+ stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style)
+ InteractiveInterpreter.__init__(self, locals)
+
+ self.lastPromptPos = 0
+
+ # the line cache is used to cycle through previous commands
+ self.lines = []
+ self.lastUsedLine = self.curLine = 0
+
+ # set defaults and then deal with any user defined properties
+ self.props = {}
+ self.props.update(_default_properties)
+ if properties:
+ self.props.update(properties)
+ self.UpdateProperties()
+
+ # copyright/banner message
+ if banner is None:
+ self.write("Python %s on %s\n" % #%s\n(%s)\n" %
+ (sys.version, sys.platform,
+ #sys.copyright, self.__class__.__name__
+ ))
+ else:
+ self.write("%s\n" % banner)
+
+ # write the initial prompt
+ self.Prompt()
+
+ # Event handlers
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKey)
+ self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI, id=ID)
+ #self.Bind(stc.EVT_STC_STYLENEEDED, self.OnStyle, id=ID)
+
+
+ def GetLocals(self): return self.locals
+ def SetLocals(self, locals): self.locals = locals
+
+ def GetProperties(self): return self.props
+ def SetProperties(self, properties):
+ self.props.update(properties)
+ self.UpdateProperties()
+
+
+ def UpdateProperties(self):
+ """
+ Reset the editor and other settings based on the contents of the
+ current properties dictionary.
+ """
+ p = self.props
+
+ #self.SetEdgeMode(stc.STC_EDGE_LINE)
+ #self.SetEdgeColumn(80)
+
+
+ # set the selection margin and window margin
+ self.SetMarginWidth(1, p['selMargin'])
+ self.SetMargins(p['marginWidth'], p['marginWidth'])
+
+ # styles
+ self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
+ self.StyleClearAll()
+ self.StyleSetSpec(_stdout_style, p['stdout'])
+ self.StyleSetSpec(_stderr_style, p['stderr'])
+ self.StyleSetSpec(_trace_style, p['trace'])
+
+ self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
+ self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
+ self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
+ self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
+ self.StyleSetSpec(stc.STC_P_STRING, p['string'])
+ self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
+ self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
+ self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
+ self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
+ self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
+ self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
+ self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
+ self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
+
+
+ # used for writing to stdout, etc.
+ def _write(self, text, style=_stdout_style):
+ self.lastPromptPos = 0
+ pos = self.GetCurrentPos()
+ self.AddText(text)
+ self.StartStyling(pos, 0xFF)
+ self.SetStyling(len(text), style)
+ self.EnsureCaretVisible()
+ wx.Yield()
+
+ write = _write
+
+ def writeTrace(self, text):
+ self._write(text, _trace_style)
+
+
+ def Prompt(self):
+ # is the current line non-empty?
+ text, pos = self.GetCurLine()
+ if pos != 0:
+ self.AddText('\n')
+ self.AddText(self.props['ps1'])
+ self.lastPromptPos = self.GetCurrentPos()
+ self.EnsureCaretVisible()
+ self.ScrollToColumn(0)
+
+
+ def PushLine(self, text):
+ # TODO: Add the text to the line cache, manage the cache so
+ # it doesn't get too big.
+ pass
+
+
+
+ def OnKey(self, evt):
+ key = evt.GetKeyCode()
+ if key == wx.WXK_RETURN:
+ pos = self.GetCurrentPos()
+ lastPos = self.GetTextLength()
+
+ # if not on the last line, duplicate the current line
+ if self.GetLineCount()-1 != self.GetCurrentLine():
+ text, col = self.GetCurLine()
+ prompt = self.props['ps1']
+ lp = len(prompt)
+ if text[:lp] == prompt:
+ text = text[lp:]
+
+ self.SetSelection(self.lastPromptPos, lastPos)
+ self.ReplaceSelection(text[:-1])
+
+ else: # try to execute the text from the prompt to the end
+ if lastPos == self.lastPromptPos:
+ self.AddText('\n')
+ self.Prompt()
+ return
+
+ text = self.GetTextRange(self.lastPromptPos, lastPos)
+ self.AddText('\n')
+
+ more = self.runsource(text)
+ if not more:
+ self.PushLine(text)
+ self.Prompt()
+
+ # TODO: Add handlers for Alt-P and Alt-N to cycle through entries
+ # in the line cache
+
+ else:
+ evt.Skip()
+
+
+ def OnStyle(self, evt):
+ # Only style from the prompt pos to the end
+ lastPos = self.GetTextLength()
+ if self.lastPromptPos and self.lastPromptPos != lastPos:
+ self.SetLexer(stc.STC_LEX_PYTHON)
+ self.SetKeywords(0, ' '.join(keyword.kwlist))
+
+ self.Colourise(self.lastPromptPos, lastPos)
+
+ self.SetLexer(0)
+
+
+ def OnUpdateUI(self, evt):
+ # check for matching braces
+ braceAtCaret = -1
+ braceOpposite = -1
+ charBefore = None
+ caretPos = self.GetCurrentPos()
+ if caretPos > 0:
+ charBefore = self.GetCharAt(caretPos - 1)
+ styleBefore = self.GetStyleAt(caretPos - 1)
+
+ # check before
+ if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
+ braceAtCaret = caretPos - 1
+
+ # check after
+ if braceAtCaret < 0:
+ charAfter = self.GetCharAt(caretPos)
+ styleAfter = self.GetStyleAt(caretPos)
+ if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
+ braceAtCaret = caretPos
+
+ if braceAtCaret >= 0:
+ braceOpposite = self.BraceMatch(braceAtCaret)
+
+ if braceAtCaret != -1 and braceOpposite == -1:
+ self.BraceBadlight(braceAtCaret)
+ else:
+ self.BraceHighlight(braceAtCaret, braceOpposite)
+
+
+
+ #----------------------------------------------
+ # overloaded methods from InteractiveInterpreter
+ def runsource(self, source):
+ stdout, stderr = sys.stdout, sys.stderr
+ sys.stdout = FauxFile(self, _stdout_style)
+ sys.stderr = FauxFile(self, _stderr_style)
+
+ more = InteractiveInterpreter.runsource(self, source)
+
+ sys.stdout, sys.stderr = stdout, stderr
+ return more
+
+ def showsyntaxerror(self, filename=None):
+ self.write = self.writeTrace
+ InteractiveInterpreter.showsyntaxerror(self, filename)
+ self.write = self._write
+
+ def showtraceback(self):
+ self.write = self.writeTrace
+ InteractiveInterpreter.showtraceback(self)
+ self.write = self._write
+
+#----------------------------------------------------------------------
+
+class FauxFile:
+ def __init__(self, psw, style):
+ self.psw = psw
+ self.style = style
+
+ def write(self, text):
+ self.psw.write(text, self.style)
+
+ def writelines(self, lst):
+ map(self.write, lst)
+
+ def flush(self):
+ pass
+
+
+#----------------------------------------------------------------------
+# test code
+
+if __name__ == '__main__':
+ app = wx.PyWidgetTester(size = (640, 480))
+ app.SetWidget(PyShellWindow, -1)
+ app.MainLoop()
+
+
+#----------------------------------------------------------------------
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rcsizer.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rcsizer.py
new file mode 100644
index 0000000..b262aee
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rcsizer.py
@@ -0,0 +1,228 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.rcsizer
+# Purpose: RowColSizer:
+#
+# Author: Robin Dunn, adapted from code by Niki Spahiev
+#
+# Created: 26-Feb-2002
+# RCS-ID: $Id$
+# Copyright: (c) 2002 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o There appears to be a prob with the wx.PySizer.GetSize() method.
+#
+# 12/23/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wx.PySizer.GetSize() method working right now.
+#
+
+"""
+A pure-Python Sizer that lays out items in a grid similar to
+wx.FlexGridSizer but item position is not implicit but explicitly
+specified by row and col, and row/col spanning is supported.
+
+Adapted from code by Niki Spahiev.
+
+NOTE: There is now a C++ version of this class that has been wrapped
+as wx.GridBagSizer. It is quicker and more capable so you are
+encouraged to switch.
+"""
+
+import operator
+import wx
+
+
+# After the lib and demo no longer uses this sizer enable this warning...
+
+## import warnings
+## warningmsg = r"""\
+
+## #####################################################\
+## # THIS MODULE IS NOW DEPRECATED |
+## # |
+## # The core wx library now contains a similar class |
+## # wrapped as wx.GridBagSizer. |
+## #####################################################/
+
+## """
+
+## warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
+
+#----------------------------------------------------------------------
+
+class RowColSizer(wx.PySizer):
+
+ # default sizes for cells with no item
+ col_w = 10
+ row_h = 22
+
+ def __init__(self):
+ wx.PySizer.__init__(self)
+ self.growableRows = []
+ self.growableCols = []
+
+
+ def AddGrowableRow(self, idx):
+ self.growableRows.append(idx)
+
+ def AddGrowableCol(self, idx):
+ self.growableCols.append(idx)
+
+
+
+ #--------------------------------------------------
+ def Add(self, item, option=0, flag=0, border=0,
+ # row, col and spanning can be specified individually...
+ row=-1, col=-1,
+ rowspan=1, colspan=1,
+ # or as tuples (row,col) and (rowspan,colspan)
+ pos=None, size=None,
+ ):
+
+ if pos is not None:
+ row, col = pos
+ if size is not None:
+ rowspan, colspan = size
+
+ assert row != -1, "Row must be specified"
+ assert col != -1, "Column must be specified"
+
+ # Do I really want to do this? Probably not...
+ #if rowspan > 1 or colspan > 1:
+ # flag = flag | wx.EXPAND
+
+ return wx.PySizer.Add(self, item, option, flag, border,
+ userData=(row, col, row+rowspan, col+colspan))
+
+ #AddWindow = Add
+ #AddSizer = Add
+
+ def AddSpacer(self, width, height, option=0, flag=0, border=0,
+ row=-1, col=-1,
+ rowspan=1, colspan=1,
+ pos=None, size=None,
+ ):
+ if pos is not None:
+ row, col = pos
+ if size is not None:
+ rowspan, colspan = size
+
+ assert row != -1, "Row must be specified"
+ assert col != -1, "Column must be specified"
+
+ return wx.PySizer.Add(self, (width, height), option, flag, border,
+ userData=(row, col, row+rowspan, col+colspan))
+
+ #--------------------------------------------------
+ def _add( self, size, dim ):
+ r, c, r2, c2 = dim # unpack coords and spanning
+
+ # are the widths and heights lists long enough?
+ if r2 > len(self.rowHeights):
+ x = [self.row_h] * (r2-len(self.rowHeights))
+ self.rowHeights.extend( x )
+ if c2 > len(self.colWidths):
+ x = [self.col_w] * (c2-len(self.colWidths))
+ self.colWidths.extend( x )
+
+ # set the widths and heights lists for this item
+ scale = (r2 - r)
+ for i in range(r, r2):
+ self.rowHeights[i] = max( self.rowHeights[i], size.height / scale )
+ scale = (c2 - c)
+ for i in range(c, c2):
+ self.colWidths[i] = max( self.colWidths[i], size.width / scale )
+
+
+ #--------------------------------------------------
+ def CalcMin( self ):
+ self.rowHeights = []
+ self.colWidths = []
+
+ items = self.GetChildren()
+ if not items:
+ return wx.Size(10, 10)
+
+ for item in items:
+ self._add( item.CalcMin(), item.GetUserData() )
+
+ size = wx.Size( reduce( operator.add, self.colWidths),
+ reduce( operator.add, self.rowHeights) )
+ return size
+
+
+ #--------------------------------------------------
+ def RecalcSizes( self ):
+ # save current dimensions, etc.
+ curWidth, curHeight = self.GetSize()
+ px, py = self.GetPosition()
+ minWidth, minHeight = self.CalcMin()
+
+ # Check for growables
+ if self.growableRows and curHeight > minHeight:
+ delta = (curHeight - minHeight) / len(self.growableRows)
+ extra = (curHeight - minHeight) % len(self.growableRows)
+ for idx in self.growableRows:
+ self.rowHeights[idx] += delta
+ self.rowHeights[self.growableRows[0]] += extra
+
+ if self.growableCols and curWidth > minWidth:
+ delta = (curWidth - minWidth) / len(self.growableCols)
+ extra = (curWidth - minWidth) % len(self.growableCols)
+ for idx in self.growableCols:
+ self.colWidths[idx] += delta
+ self.colWidths[self.growableCols[0]] += extra
+
+ rpos = [0] * len(self.rowHeights)
+ cpos = [0] * len(self.colWidths)
+
+ for i in range(len(self.rowHeights)):
+ height = self.rowHeights[i]
+ rpos[i] = py
+ py += height
+
+ for i in range(len(self.colWidths)):
+ width = self.colWidths[i]
+ cpos[i] = px
+ px += width
+
+ # iterate children and set dimensions...
+ for item in self.GetChildren():
+ r, c, r2, c2 = item.GetUserData()
+ width = reduce( operator.add, self.colWidths[c:c2] )
+ height = reduce( operator.add, self.rowHeights[r:r2] )
+ self.SetItemBounds( item, cpos[c], rpos[r], width, height )
+
+
+ #--------------------------------------------------
+ def SetItemBounds(self, item, x, y, w, h):
+ # calculate the item's actual size and position within
+ # its grid cell
+ ipt = wx.Point(x, y)
+ isz = item.CalcMin()
+ flag = item.GetFlag()
+
+ if flag & wx.EXPAND or flag & wx.SHAPED:
+ isz = wx.Size(w, h)
+ else:
+ if flag & wx.ALIGN_CENTER_HORIZONTAL:
+ ipt.x = x + (w - isz.width) / 2
+ elif flag & wx.ALIGN_RIGHT:
+ ipt.x = x + (w - isz.width)
+
+ if flag & wx.ALIGN_CENTER_VERTICAL:
+ ipt.y = y + (h - isz.height) / 2
+ elif flag & wx.ALIGN_BOTTOM:
+ ipt.y = y + (h - isz.height)
+
+ item.SetDimension(ipt, isz)
+
+
+#----------------------------------------------------------------------
+#----------------------------------------------------------------------
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/resizewidget.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/resizewidget.py
new file mode 100644
index 0000000..ba486d6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/resizewidget.py
@@ -0,0 +1,250 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.resizewidget
+# Purpose: Adds a resize handle to any widget, with support for
+# notifying parents when layout needs done.
+#
+# Author: Robin Dunn
+#
+# Created: 12-June-2008
+# RCS-ID: $Id: $
+# Copyright: (c) 2008 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""
+Reparents a given widget into a specialized panel that provides a resize
+handle for the widget. When the user drags the resize handle the widget is
+resized accordingly, and an event is sent to notify parents that they should
+recalculate their layout.
+"""
+
+import wx
+import wx.lib.newevent
+
+#-----------------------------------------------------------------------------
+
+# dimensions used for the handle
+RW_THICKNESS = 4
+RW_LENGTH = 12
+
+# colors for the handle
+RW_PEN = 'black'
+RW_FILL = '#A0A0A0'
+RW_FILL2 = '#E0E0E0'
+
+# An event and event binder that will notify the containers that they should
+# redo the layout in whatever way makes sense for their particular content.
+_RWLayoutNeededEvent, EVT_RW_LAYOUT_NEEDED = wx.lib.newevent.NewCommandEvent()
+
+
+# TODO: Add a style flag that indicates that the ResizeWidget should
+# try to adjust the layout itself by looking up the sizer and
+# containment hierachy. Maybe also a style that says that it is okay
+# to adjust the size of top-level windows too.
+
+#-----------------------------------------------------------------------------
+
+class ResizeWidget(wx.PyPanel):
+ def __init__(self, *args, **kw):
+ wx.PyPanel.__init__(self, *args, **kw)
+ self._init()
+
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def _init(self):
+ self._managedChild = None
+ self._bestSize = wx.Size(100,25)
+ self.InvalidateBestSize()
+ self._resizeCursor = False
+ self._dragPos = None
+ self._resizeEnabled = True
+ self._reparenting = False
+
+
+ def SetManagedChild(self, child):
+ self._reparenting = True
+ child.Reparent(self) # This calls AddChild, so do the rest of the init there
+ self._reparenting = False
+ self.AdjustToChild()
+
+ def GetManagedChild(self):
+ return self._managedChild
+
+ ManagedChild = property(GetManagedChild, SetManagedChild)
+
+
+ def AdjustToChild(self):
+ self.AdjustToSize(self._managedChild.GetEffectiveMinSize())
+
+
+ def AdjustToSize(self, size):
+ size = wx.Size(*size)
+ self._bestSize = size + (RW_THICKNESS, RW_THICKNESS)
+ self.InvalidateBestSize()
+ self.SetSize(self._bestSize)
+
+
+ def EnableResize(self, enable=True):
+ self._resizeEnabled = enable
+ self.Refresh(False)
+
+
+ def IsResizeEnabled(self):
+ return self._resizeEnabled
+
+
+ #=== Event handler methods ===
+ def OnLeftDown(self, evt):
+ if self._hitTest(evt.GetPosition()) and self._resizeEnabled:
+ self.CaptureMouse()
+ self._dragPos = evt.GetPosition()
+
+
+ def OnLeftUp(self, evt):
+ if self.HasCapture():
+ self.ReleaseMouse()
+ self._dragPos = None
+
+
+ def OnMouseMove(self, evt):
+ # set or reset the drag cursor
+ pos = evt.GetPosition()
+ if self._hitTest(pos) and self._resizeEnabled:
+ if not self._resizeCursor:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_SIZENWSE))
+ self._resizeCursor = True
+ else:
+ if self._resizeCursor:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ self._resizeCursor = False
+
+ # determine if a new size is needed
+ if evt.Dragging() and self._dragPos is not None:
+ delta = self._dragPos - pos
+ newSize = self.GetSize() - delta.Get()
+ self._adjustNewSize(newSize)
+ if newSize != self.GetSize():
+ self.SetSize(newSize)
+ self._dragPos = pos
+ self._bestSize = newSize
+ self.InvalidateBestSize()
+ self._sendEvent()
+
+
+ def _sendEvent(self):
+ event = _RWLayoutNeededEvent(self.GetId())
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+
+ def _adjustNewSize(self, newSize):
+ if newSize.width < RW_LENGTH:
+ newSize.width = RW_LENGTH
+ if newSize.height < RW_LENGTH:
+ newSize.height = RW_LENGTH
+
+ if self._managedChild:
+ minsize = self._managedChild.GetMinSize()
+ if minsize.width != -1 and newSize.width - RW_THICKNESS < minsize.width:
+ newSize.width = minsize.width + RW_THICKNESS
+ if minsize.height != -1 and newSize.height - RW_THICKNESS < minsize.height:
+ newSize.height = minsize.height + RW_THICKNESS
+ maxsize = self._managedChild.GetMaxSize()
+ if maxsize.width != -1 and newSize.width - RW_THICKNESS > maxsize.width:
+ newSize.width = maxsize.width + RW_THICKNESS
+ if maxsize.height != -1 and newSize.height - RW_THICKNESS > maxsize.height:
+ newSize.height = maxsize.height + RW_THICKNESS
+
+
+ def OnMouseLeave(self, evt):
+ if self._resizeCursor:
+ self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ self._resizeCursor = False
+
+
+ def OnSize(self, evt):
+ if not self._managedChild:
+ return
+ sz = self.GetSize()
+ cr = wx.RectPS((0,0), sz - (RW_THICKNESS, RW_THICKNESS))
+ self._managedChild.SetRect(cr)
+ r1 = wx.Rect(0, cr.height, sz.width, RW_THICKNESS)
+ r2 = wx.Rect(cr.width, 0, RW_THICKNESS, sz.height)
+ self.RefreshRect(r1)
+ self.RefreshRect(r2)
+
+
+
+ def OnPaint(self, evt):
+ # draw the resize handle
+ dc = wx.PaintDC(self)
+ w,h = self.GetSize()
+ points = [ (w - 1, h - RW_LENGTH),
+ (w - RW_THICKNESS, h - RW_LENGTH),
+ (w - RW_THICKNESS, h - RW_THICKNESS),
+ (w - RW_LENGTH, h - RW_THICKNESS),
+ (w - RW_LENGTH, h - 1),
+ (w - 1, h - 1),
+ (w - 1, h - RW_LENGTH),
+ ]
+ dc.SetPen(wx.Pen(RW_PEN, 1))
+ if self._resizeEnabled:
+ fill = RW_FILL
+ else:
+ fill = RW_FILL2
+ dc.SetBrush(wx.Brush(fill))
+ dc.DrawPolygon(points)
+
+
+ def _hitTest(self, pos):
+ # is the position in the area to be used for the resize handle?
+ w, h = self.GetSize()
+ if ( w - RW_THICKNESS <= pos.x <= w
+ and h - RW_LENGTH <= pos.y <= h ):
+ return True
+ if ( w - RW_LENGTH <= pos.x <= w
+ and h - RW_THICKNESS <= pos.y <= h ):
+ return True
+ return False
+
+
+ #=== Overriden virtuals from the base class ===
+ def AddChild(self, child):
+ assert self._managedChild is None, "Already managing a child widget, can only do one"
+ self._managedChild = child
+ wx.PyPanel.AddChild(self, child)
+
+ # This little hack is needed because if this AddChild was called when
+ # the widget was first created, then the OOR values will get reset
+ # after this function call, and so the Python proxy object saved in
+ # the window may be different than the child object we have now, so we
+ # need to reset which proxy object we're using. Look for it by ID.
+ def _doAfterAddChild(self, id):
+ if not self:
+ return
+ child = self.FindWindowById(id)
+ self._managedChild = child
+ self.AdjustToChild()
+ self._sendEvent()
+ if self._reparenting:
+ _doAfterAddChild(self, child.GetId())
+ else:
+ wx.CallAfter(_doAfterAddChild, self, child.GetId())
+
+ def RemoveChild(self, child):
+ self._init()
+ wx.PyPanel.RemoveChild(self, child)
+
+
+ def DoGetBestSize(self):
+ return self._bestSize
+
+
+#-----------------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rightalign.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rightalign.py
new file mode 100644
index 0000000..3609866
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rightalign.py
@@ -0,0 +1,109 @@
+# -*- coding: iso-8859-1 -*-
+#----------------------------------------------------------------------
+# Name: wxPython.lib.rightalign
+# Purpose: A class derived from wxTextCtrl that aligns the text
+# on the right side of the control, (except when editing.)
+#
+# Author: Josu Oyanguren
+#
+# Created: 19-October-2001
+# RCS-ID: $Id$
+# Copyright: (c) 2001 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/11/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o Added deprecation warning.
+#
+# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxRightTextCtrl -> RightTextCtrl
+#
+
+"""
+Some time ago, I asked about how to right-align
+wxTextCtrls. Answer was that it is not supported. I forgot it.
+
+Just a week ago, one of my clients asked me to have numbers right
+aligned. (Indeed it was that numbers MUST be right aligned).
+
+So the game begun. Hacking, hacking, ...
+
+At last, i succeed. Here is some code that someone may find
+useful. ubRightTextCtrl is right-aligned when you are not editing, but
+left-aligned if it has focus.
+
+Hope this can help someone, as much as this list helps me.
+
+Josu Oyanguren
+Ubera Servicios Informaticos.
+
+
+P.S. This only works well on wxMSW.
+"""
+
+import warnings
+import wx
+
+#----------------------------------------------------------------------
+
+warningmsg = r"""\
+
+##############################################################\
+# THIS MODULE IS DEPRECATED |
+# |
+# This control still functions, but it is deprecated because |
+# wx.TextCtrl now supports the wx.TE_RIGHT style flag |
+##############################################################/
+
+
+"""
+
+warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
+
+#----------------------------------------------------------------------
+
+class RightTextCtrl(wx.TextCtrl):
+ def __init__(self, parent, id, *args, **kwargs):
+ wx.TextCtrl.__init__(self, parent, id, *args, **kwargs)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+ def OnPaint(self, event):
+ dc = wx.PaintDC(self)
+ dc.SetFont(self.GetFont())
+ dc.Clear()
+ text = self.GetValue()
+ textwidth, textheight = dc.GetTextExtent(text)
+ dcwidth, dcheight = self.GetClientSize()
+
+ y = (dcheight - textheight) / 2
+ x = dcwidth - textwidth - 2
+
+ if self.IsEnabled():
+ fclr = self.GetForegroundColour()
+ else:
+ fclr = wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT)
+
+ dc.SetTextForeground(fclr)
+
+ dc.SetClippingRegion(0, 0, dcwidth, dcheight)
+ dc.DrawText(text, x, y)
+
+ if x < 0:
+ toofat = '...'
+ markwidth = dc.GetTextExtent(toofat)[0]
+ dc.SetPen(wx.Pen(dc.GetBackground().GetColour(), 1, wx.SOLID ))
+ dc.DrawRectangle(0,0, markwidth, dcheight)
+ dc.SetPen(wx.Pen(wx.RED, 1, wx.SOLID ))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(1, 1, dcwidth-2, dcheight-2)
+ dc.DrawText(toofat, 1, y)
+
+
+ def OnKillFocus(self, event):
+ if not self.GetParent(): return
+ self.Refresh()
+ event.Skip()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rpcMixin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rpcMixin.py
new file mode 100644
index 0000000..a053a4a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/rpcMixin.py
@@ -0,0 +1,422 @@
+#
+# This was modified from rpcMixin.py distributed with wxPython
+#
+#----------------------------------------------------------------------
+# Name: rpcMixin
+# Version: 0.2.0
+# Purpose: provides xmlrpc server functionality for wxPython
+# applications via a mixin class
+#
+# Requires: (1) Python with threading enabled.
+# (2) xmlrpclib from PythonWare
+# (http://www.pythonware.com/products/xmlrpc/)
+# the code was developed and tested using version 0.9.8
+#
+# Author: greg Landrum (Landrum@RationalDiscovery.com)
+#
+# Copyright: (c) 2000, 2001 by Greg Landrum and Rational Discovery LLC
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/11/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o xmlrpcserver not available.
+#
+
+"""provides xmlrpc server functionality for wxPython applications via a mixin class
+
+**Some Notes:**
+
+ 1) The xmlrpc server runs in a separate thread from the main GUI
+ application, communication between the two threads using a custom
+ event (see the Threads demo in the wxPython docs for more info).
+
+ 2) Neither the server nor the client are particularly smart about
+ checking method names. So it's easy to shoot yourself in the foot
+ by calling improper methods. It would be pretty easy to add
+ either a list of allowed methods or a list of forbidden methods.
+
+ 3) Authentication of xmlrpc clients is *not* performed. I think it
+ would be pretty easy to do this in a hacky way, but I haven't done
+ it yet.
+
+ 4) See the bottom of this file for an example of using the class.
+
+**Obligatory disclaimer:**
+ This is my first crack at both using xmlrpc and multi-threaded
+ programming, so there could be huge horrible bugs or design
+ flaws. If you see one, I'd love to hear about them.
+
+"""
+
+
+""" ChangeLog
+23 May 2001: Version bumped to 0.2.0
+ Numerous code and design changes
+
+21 Mar. 2001: Version bumped to 0.1.4
+ Updated rpcMixin.OnExternal to support methods with further references
+ (i.e. now you can do rpcClient.foo.bar() and have it work)
+ This probably ain't super legal in xmlrpc land, but it works just fine here
+ and we need it.
+
+6 Mar. 2001: Version bumped to 0.1.3
+ Documentation changes to make this compatible with happydoc
+
+21 Jan. 2001: Version bumped to 0.1.2
+ OnExternal() method in the mixin class now uses getattr() to check if
+ a desired method is present. It should have been done this way in
+ the first place.
+14 Dec. 2000: Version bumped to 0.1.1
+ rearranged locking code and made other changes so that multiple
+ servers in one application are possible.
+
+"""
+
+import new
+import SocketServer
+import sys
+import threading
+import xmlrpclib
+import xmlrpcserver
+
+import wx
+
+rpcPENDING = 0
+rpcDONE = 1
+rpcEXCEPT = 2
+
+class RPCRequest:
+ """A wrapper to use for handling requests and their responses"""
+ status = rpcPENDING
+ result = None
+
+# here's the ID for external events
+wxEVT_EXTERNAL_EVENT = wx.NewEventType()
+EVT_EXTERNAL_EVENT = wx.PyEventBinder(wxEVT_EXTERNAL_EVENT, 0)
+
+class ExternalEvent(wx.PyEvent):
+ """The custom event class used to pass xmlrpc calls from
+ the server thread into the GUI thread
+
+ """
+ def __init__(self,method,args):
+ wx.PyEvent.__init__(self)
+ self.SetEventType(wxEVT_EXTERNAL_EVENT)
+ self.method = method
+ self.args = args
+ self.rpcStatus = RPCRequest()
+ self.rpcStatusLock = threading.Lock()
+ self.rpcCondVar = threading.Condition()
+
+ def Destroy(self):
+ self.method=None
+ self.args=None
+ self.rpcStatus = None
+ self.rpcStatusLock = None
+ self.rpcondVar = None
+
+class Handler(xmlrpcserver.RequestHandler):
+ """The handler class that the xmlrpcserver actually calls
+ when a request comes in.
+
+ """
+ def log_message(self,*args):
+ """ causes the server to stop spewing messages every time a request comes in
+
+ """
+ pass
+ def call(self,method,params):
+ """When an xmlrpc request comes in, this is the method that
+ gets called.
+
+ **Arguments**
+
+ - method: name of the method to be called
+
+ - params: arguments to that method
+
+ """
+ if method == '_rpcPing':
+ # we just acknowledge these without processing them
+ return 'ack'
+
+ # construct the event
+ evt = ExternalEvent(method,params)
+
+ # update the status variable
+ evt.rpcStatusLock.acquire()
+ evt.rpcStatus.status = rpcPENDING
+ evt.rpcStatusLock.release()
+
+ evt.rpcCondVar.acquire()
+ # dispatch the event to the GUI
+ wx.PostEvent(self._app,evt)
+
+ # wait for the GUI to finish
+ while evt.rpcStatus.status == rpcPENDING:
+ evt.rpcCondVar.wait()
+ evt.rpcCondVar.release()
+ evt.rpcStatusLock.acquire()
+ if evt.rpcStatus.status == rpcEXCEPT:
+ # The GUI threw an exception, release the status lock
+ # and re-raise the exception
+ evt.rpcStatusLock.release()
+ raise evt.rpcStatus.result[0],evt.rpcStatus.result[1]
+ else:
+ # everything went through without problems
+ s = evt.rpcStatus.result
+
+ evt.rpcStatusLock.release()
+ evt.Destroy()
+ self._app = None
+ return s
+
+# this global Event is used to let the server thread
+# know when it should quit
+stopEvent = threading.Event()
+stopEvent.clear()
+
+class _ServerThread(threading.Thread):
+ """ this is the Thread class which actually runs the server
+
+ """
+ def __init__(self,server,verbose=0):
+ self._xmlServ = server
+ threading.Thread.__init__(self,verbose=verbose)
+
+ def stop(self):
+ stopEvent.set()
+
+ def shouldStop(self):
+ return stopEvent.isSet()
+
+ def run(self):
+ while not self.shouldStop():
+ self._xmlServ.handle_request()
+ self._xmlServ = None
+
+class rpcMixin:
+ """A mixin class to provide xmlrpc server functionality to wxPython
+ frames/windows
+
+ If you want to customize this, probably the best idea is to
+ override the OnExternal method, which is what's invoked when an
+ RPC is handled.
+
+ """
+
+ # we'll try a range of ports for the server, this is the size of the
+ # range to be scanned
+ nPortsToTry=20
+ if sys.platform == 'win32':
+ defPort = 800
+ else:
+ defPort = 8023
+
+ def __init__(self,host='',port=-1,verbose=0,portScan=1):
+ """Constructor
+
+ **Arguments**
+
+ - host: (optional) the hostname for the server
+
+ - port: (optional) the port the server will use
+
+ - verbose: (optional) if set, the server thread will be launched
+ in verbose mode
+
+ - portScan: (optional) if set, we'll scan across a number of ports
+ to find one which is avaiable
+
+ """
+ if port == -1:
+ port = self.defPort
+ self.verbose=verbose
+ self.Bind(EVT_EXTERNAL_EVENT,self.OnExternal)
+ if hasattr(self,'OnClose'):
+ self._origOnClose = self.OnClose
+ self.Disconnect(-1,-1,wx.EVT_CLOSE_WINDOW)
+ else:
+ self._origOnClose = None
+ self.OnClose = self.RPCOnClose
+ self.Bind(wx.EVT_CLOSE,self.RPCOnClose)
+
+ tClass = new.classobj('Handler%d'%(port),(Handler,),{})
+ tClass._app = self
+ if portScan:
+ self.rpcPort = -1
+ for i in xrange(self.nPortsToTry):
+ try:
+ xmlServ = SocketServer.TCPServer((host,port+i),tClass)
+ except:
+ pass
+ else:
+ self.rpcPort = port+i
+ else:
+ self.rpcPort = port
+ try:
+ xmlServ = SocketServer.TCPServer((host,port),tClass)
+ except:
+ self.rpcPort = -1
+
+ if self.rpcPort == -1:
+ raise Exception, 'RPCMixinError: Cannot initialize server'
+ self.servThread = _ServerThread(xmlServ,verbose=self.verbose)
+ self.servThread.setName('XML-RPC Server')
+ self.servThread.start()
+
+ def RPCOnClose(self,event):
+ """ callback for when the application is closed
+
+ be sure to shutdown the server and the server thread before
+ leaving
+
+ """
+ # by setting the global stopEvent we inform the server thread
+ # that it's time to shut down.
+ stopEvent.set()
+ if event is not None:
+ # if we came in here from a user event (as opposed to an RPC event),
+ # then we'll need to kick the server one last time in order
+ # to get that thread to terminate. do so now
+ s1 = xmlrpclib.Server('http://localhost:%d'%(self.rpcPort))
+ try:
+ s1._rpcPing()
+ except:
+ pass
+
+ if self._origOnClose is not None:
+ self._origOnClose(event)
+
+ def RPCQuit(self):
+ """ shuts down everything, including the rpc server
+
+ """
+ self.RPCOnClose(None)
+ def OnExternal(self,event):
+ """ this is the callback used to handle RPCs
+
+ **Arguments**
+
+ - event: an _ExternalEvent_ sent by the rpc server
+
+ Exceptions are caught and returned in the global _rpcStatus
+ structure. This allows the xmlrpc server to report the
+ exception to the client without mucking up any of the delicate
+ thread stuff.
+
+ """
+ event.rpcStatusLock.acquire()
+ doQuit = 0
+ try:
+ methsplit = event.method.split('.')
+ meth = self
+ for piece in methsplit:
+ meth = getattr(meth,piece)
+ except AttributeError,msg:
+ event.rpcStatus.result = 'No Such Method',msg
+ event.rpcStatus.status = rpcEXCEPT
+ else:
+ try:
+ res = apply(meth,event.args)
+ except:
+ import traceback
+ if self.verbose: traceback.print_exc()
+ event.rpcStatus.result = sys.exc_info()[:2]
+ event.rpcStatus.status = rpcEXCEPT
+ else:
+ if res is None:
+ # returning None across the xmlrpc interface is problematic
+ event.rpcStatus.result = []
+ else:
+ event.rpcStatus.result = res
+ event.rpcStatus.status = rpcDONE
+
+ event.rpcStatusLock.release()
+
+ # broadcast (using the condition var) that we're done with the event
+ event.rpcCondVar.acquire()
+ event.rpcCondVar.notify()
+ event.rpcCondVar.release()
+
+
+if __name__ == '__main__':
+ import time
+ if sys.platform == 'win32':
+ port = 800
+ else:
+ port = 8023
+
+ class rpcFrame(wx.Frame,rpcMixin):
+ """A simple wxFrame with the rpcMixin functionality added
+ """
+ def __init__(self,*args,**kwargs):
+ """ rpcHost or rpcPort keyword arguments will be passed along to
+ the xmlrpc server.
+ """
+ mixinArgs = {}
+ if kwargs.has_key('rpcHost'):
+ mixinArgs['host'] = kwargs['rpcHost']
+ del kwargs['rpcHost']
+ if kwargs.has_key('rpcPort'):
+ mixinArgs['port'] = kwargs['rpcPort']
+ del kwargs['rpcPort']
+ if kwargs.has_key('rpcPortScan'):
+ mixinArgs['portScan'] = kwargs['rpcPortScan']
+ del kwargs['rpcPortScan']
+
+ apply(wx.Frame.__init__,(self,)+args,kwargs)
+ apply(rpcMixin.__init__,(self,),mixinArgs)
+
+ self.Bind(wx.EVT_CHAR,self.OnChar)
+
+ def TestFunc(self,args):
+ """a demo method"""
+ return args
+
+ def OnChar(self,event):
+ key = event.GetKeyCode()
+ if key == ord('q'):
+ self.OnQuit(event)
+
+ def OnQuit(self,event):
+ self.OnClose(event)
+
+ def OnClose(self,event):
+ self.Destroy()
+
+
+
+ class MyApp(wx.App):
+ def OnInit(self):
+ self.frame = rpcFrame(None, -1, "wxPython RPCDemo", wx.DefaultPosition,
+ (300,300), rpcHost='localhost',rpcPort=port)
+ self.frame.Show(True)
+ return True
+
+
+ def testcon(port):
+ s1 = xmlrpclib.Server('http://localhost:%d'%(port))
+ s1.SetTitle('Munged')
+ s1._rpcPing()
+ if doQuit:
+ s1.RPCQuit()
+
+ doQuit = 1
+ if len(sys.argv)>1 and sys.argv[1] == '-q':
+ doQuit = 0
+ nT = threading.activeCount()
+ app = MyApp(0)
+ activePort = app.frame.rpcPort
+ t = threading.Thread(target=lambda x=activePort:testcon(x),verbose=0)
+ t.start()
+
+ app.MainLoop()
+ # give the threads time to shut down
+ if threading.activeCount() > nT:
+ print 'waiting for all threads to terminate'
+ while threading.activeCount() > nT:
+ time.sleep(0.5)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/scrolledpanel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/scrolledpanel.py
new file mode 100644
index 0000000..8f52aeb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/scrolledpanel.py
@@ -0,0 +1,136 @@
+#----------------------------------------------------------------------------
+# Name: scrolledpanel.py
+# Author: Will Sadkin
+# Created: 03/21/2003
+# Copyright: (c) 2003 by Will Sadkin
+# RCS-ID: $Id$
+# License: wxWindows license
+#----------------------------------------------------------------------------
+# 12/11/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o wxScrolledPanel -> ScrolledPanel
+#
+
+import wx
+import math
+
+class ScrolledPanel( wx.PyScrolledWindow ):
+
+ """ ScrolledPanel fills a "hole" in the implementation of
+ wx.ScrolledWindow, providing automatic scrollbar and scrolling
+ behavior and the tab traversal management that wxScrolledWindow
+ lacks. This code was based on the original demo code showing how
+ to do this, but is now available for general use as a proper class
+ (and the demo is now converted to just use it.)
+
+ It is assumed that the ScrolledPanel will have a sizer, as it is
+ used to calculate the minimal virtual size of the panel and etc.
+ """
+
+ def __init__(self, parent, id=-1, pos = wx.DefaultPosition,
+ size = wx.DefaultSize, style = wx.TAB_TRAVERSAL,
+ name = "scrolledpanel"):
+
+ wx.PyScrolledWindow.__init__(self, parent, id,
+ pos=pos, size=size,
+ style=style, name=name)
+ self.scrollIntoView = True
+ self.SetInitialSize(size)
+ self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus)
+
+
+ def SetupScrolling(self, scroll_x=True, scroll_y=True, rate_x=20, rate_y=20,
+ scrollToTop=True, scrollIntoView=True):
+ """
+ This function sets up the event handling necessary to handle
+ scrolling properly. It should be called within the __init__
+ function of any class that is derived from ScrolledPanel,
+ once the controls on the panel have been constructed and
+ thus the size of the scrolling area can be determined.
+
+ """
+ self.scrollIntoView = scrollIntoView
+
+ # The following is all that is needed to integrate the sizer and the scrolled window
+ if not scroll_x: rate_x = 0
+ if not scroll_y: rate_y = 0
+
+ # Round up the virtual size to be a multiple of the scroll rate
+ sizer = self.GetSizer()
+ if sizer:
+ w, h = sizer.GetMinSize()
+ if rate_x:
+ w += rate_x - (w % rate_x)
+ if rate_y:
+ h += rate_y - (h % rate_y)
+ self.SetVirtualSize( (w, h) )
+ self.SetScrollRate(rate_x, rate_y)
+ wx.CallAfter(self._SetupAfter, scrollToTop) # scroll back to top after initial events
+
+
+ def _SetupAfter(self, scrollToTop):
+ self.SetVirtualSize(self.GetBestVirtualSize())
+ if scrollToTop:
+ self.Scroll(0,0)
+
+
+ def OnChildFocus(self, evt):
+ """
+ If the child window that gets the focus is not fully visible,
+ this handler will try to scroll enough to see it.
+ """
+ child = evt.GetWindow()
+ if self.scrollIntoView:
+ self.ScrollChildIntoView(child)
+ evt.Skip()
+
+
+ def ScrollChildIntoView(self, child):
+ """
+ Scroll the panel so that the specified child window is in
+ view. NOTE. This method looks redundant if evt.Skip() is
+ called as well - the base wx.ScrolledWindow widget now seems
+ to be doing the same thing anyway
+ """
+ sppu_x, sppu_y = self.GetScrollPixelsPerUnit()
+ vs_x, vs_y = self.GetViewStart()
+ cr = child.GetRect()
+ clntsz = self.GetClientSize()
+ new_vs_x, new_vs_y = -1, -1
+
+ # is it before the left edge?
+ if cr.x < 0 and sppu_x > 0:
+ new_vs_x = vs_x + (cr.x / sppu_x)
+
+ # is it above the top?
+ if cr.y < 0 and sppu_y > 0:
+ new_vs_y = vs_y + (cr.y / sppu_y)
+
+ # For the right and bottom edges, scroll enough to show the
+ # whole control if possible, but if not just scroll such that
+ # the top/left edges are still visible
+
+ # is it past the right edge ?
+ if cr.right > clntsz.width and sppu_x > 0:
+ diff = math.ceil(1.0 * (cr.right - clntsz.width + 1) / sppu_x)
+ if cr.x - diff * sppu_x > 0:
+ new_vs_x = vs_x + diff
+ else:
+ new_vs_x = vs_x + (cr.x / sppu_x)
+
+ # is it below the bottom ?
+ if cr.bottom > clntsz.height and sppu_y > 0:
+ diff = math.ceil(1.0 * (cr.bottom - clntsz.height + 1) / sppu_y)
+ if cr.y - diff * sppu_y > 0:
+ new_vs_y = vs_y + diff
+ else:
+ new_vs_y = vs_y + (cr.y / sppu_y)
+
+ # if we need to adjust
+ if new_vs_x != -1 or new_vs_y != -1:
+ #print "%s: (%s, %s)" % (self.GetName(), new_vs_x, new_vs_y)
+ self.Scroll(new_vs_x, new_vs_y)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/sheet.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/sheet.py
new file mode 100644
index 0000000..fe8e77d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/sheet.py
@@ -0,0 +1,349 @@
+# sheet.py
+# CSheet - A wxPython spreadsheet class.
+# This is free software. Feel free to adapt it as you like.
+# Author: Mark F. Russo (russomf@hotmail.com) 2002/01/31
+#---------------------------------------------------------------------------
+# 12/11/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o Untested.
+#
+
+import string
+import wx
+import wx.grid
+
+#---------------------------------------------------------------------------
+class CTextCellEditor(wx.TextCtrl):
+ """ Custom text control for cell editing """
+ def __init__(self, parent, id, grid):
+ wx.TextCtrl.__init__(self, parent, id, "", style=wx.NO_BORDER)
+ self._grid = grid # Save grid reference
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+
+ def OnChar(self, evt): # Hook OnChar for custom behavior
+ """Customizes char events """
+ key = evt.GetKeyCode()
+ if key == wx.WXK_DOWN:
+ self._grid.DisableCellEditControl() # Commit the edit
+ self._grid.MoveCursorDown(False) # Change the current cell
+ elif key == wx.WXK_UP:
+ self._grid.DisableCellEditControl() # Commit the edit
+ self._grid.MoveCursorUp(False) # Change the current cell
+ elif key == wx.WXK_LEFT:
+ self._grid.DisableCellEditControl() # Commit the edit
+ self._grid.MoveCursorLeft(False) # Change the current cell
+ elif key == wx.WXK_RIGHT:
+ self._grid.DisableCellEditControl() # Commit the edit
+ self._grid.MoveCursorRight(False) # Change the current cell
+
+ evt.Skip() # Continue event
+
+#---------------------------------------------------------------------------
+class CCellEditor(wx.grid.PyGridCellEditor):
+ """ Custom cell editor """
+ def __init__(self, grid):
+ wx.grid.PyGridCellEditor.__init__(self)
+ self._grid = grid # Save a reference to the grid
+
+ def Create(self, parent, id, evtHandler):
+ """ Create the actual edit control. Must derive from wxControl.
+ Must Override
+ """
+ self._tc = CTextCellEditor(parent, id, self._grid)
+ self._tc.SetInsertionPoint(0)
+ self.SetControl(self._tc)
+ if evtHandler:
+ self._tc.PushEventHandler(evtHandler)
+
+ def SetSize(self, rect):
+ """ Position/size the edit control within the cell rectangle. """
+ # Size text control to exactly overlay in-cell editing
+ self._tc.SetDimensions(rect.x+3, rect.y+3, rect.width-2, rect.height-2)
+
+ def Show(self, show, attr):
+ """ Show or hide the edit control. Use the attr (if not None)
+ to set colors or fonts for the control.
+
+ NOTE: There is no need to everride this if you don't need
+ to do something out of the ordinary.
+ """
+ super(CCellEditor, self).Show(show, attr)
+
+ def PaintBackground(self, rect, attr):
+ """ Draws the part of the cell not occupied by the edit control. The
+ base class version just fills it with background colour from the
+ attribute.
+
+ NOTE: There is no need to everride this if you don't need
+ to do something out of the ordinary.
+ """
+ # Call base class method.
+ super(CCellEditor, self).PaintBackground(rect, attr)
+
+ def BeginEdit(self, row, col, grid):
+ """ Fetch the value from the table and prepare edit control to begin editing.
+ Set the focus to the edit control. Must Override.
+ """
+ self._startValue = grid.GetTable().GetValue(row, col)
+ self._tc.SetValue(self._startValue)
+ self._tc.SetFocus()
+
+ # Select the text when initiating an edit so that subsequent typing
+ # replaces the contents.
+ self._tc.SetSelection(0, self._tc.GetLastPosition())
+
+ def EndEdit(self, row, col, grid):
+ """ Commit editing the current cell. Returns True if the value has changed.
+ If necessary, the control may be destroyed. Must Override.
+ """
+ changed = False # Assume value not changed
+ val = self._tc.GetValue() # Get value in edit control
+ if val != self._startValue: # Compare
+ changed = True # If different then changed is True
+ grid.GetTable().SetValue(row, col, val) # Update the table
+ self._startValue = '' # Clear the class' start value
+ self._tc.SetValue('') # Clear contents of the edit control
+
+ return changed
+
+ def Reset(self):
+ """ Reset the value in the control back to its starting value. Must Override. """
+ self._tc.SetValue(self._startValue)
+ self._tc.SetInsertionPointEnd()
+
+ def IsAcceptedKey(self, evt):
+ """ Return True to allow the given key to start editing. The base class
+ version only checks that the event has no modifiers. F2 is special
+ and will always start the editor.
+ """
+ return (not (evt.ControlDown() or evt.AltDown())
+ and evt.GetKeyCode() != wx.WXK_SHIFT)
+
+ def StartingKey(self, evt):
+ """ If the editor is enabled by pressing keys on the grid, this will be
+ called to let the editor react to that first key.
+ """
+ key = evt.GetKeyCode() # Get the key code
+ ch = None # Handle num pad keys
+ if key in [ wx.WXK_NUMPAD0, wx.WXK_NUMPAD1, wx.WXK_NUMPAD2, wx.WXK_NUMPAD3,
+ wx.WXK_NUMPAD4, wx.WXK_NUMPAD5, wx.WXK_NUMPAD6, wx.WXK_NUMPAD7,
+ wx.WXK_NUMPAD8, wx.WXK_NUMPAD9]:
+ ch = chr(ord('0') + key - wx.WXK_NUMPAD0)
+
+ elif key == wx.WXK_BACK: # Empty text control when init w/ back key
+ ch = ""
+ # Handle normal keys
+ elif key < 256 and key >= 0 and chr(key) in string.printable:
+ ch = chr(key)
+ if not evt.ShiftDown():
+ ch = ch.lower()
+
+ if ch is not None: # If are at this point with a key,
+ self._tc.SetValue(ch) # replace the contents of the text control.
+ self._tc.SetInsertionPointEnd() # Move to the end so that subsequent keys are appended
+ else:
+ evt.Skip()
+
+ def StartingClick(self):
+ """ If the editor is enabled by clicking on the cell, this method will be
+ called to allow the editor to simulate the click on the control.
+ """
+ pass
+
+ def Destroy(self):
+ """ Final cleanup
+
+ NOTE: There is no need to everride this if you don't need
+ to do something out of the ordinary.
+ """
+ super(CCellEditor, self).Destroy()
+
+ def Clone(self):
+ """ Create a new object which is the copy of this one. Must Override. """
+ return CCellEditor()
+
+#---------------------------------------------------------------------------
+class CSheet(wx.grid.Grid):
+ def __init__(self, parent):
+ wx.grid.Grid.__init__(self, parent, -1)
+
+ # Init variables
+ self._lastCol = -1 # Init last cell column clicked
+ self._lastRow = -1 # Init last cell row clicked
+ self._selected = None # Init range currently selected
+ # Map string datatype to default renderer/editor
+ self.RegisterDataType(wx.grid.GRID_VALUE_STRING,
+ wx.grid.GridCellStringRenderer(),
+ CCellEditor(self))
+
+ self.CreateGrid(4, 3) # By default start with a 4 x 3 grid
+ self.SetColLabelSize(18) # Default sizes and alignment
+ self.SetRowLabelSize(50)
+ self.SetRowLabelAlignment(wx.ALIGN_RIGHT, wx.ALIGN_BOTTOM)
+ self.SetColSize(0, 75) # Default column sizes
+ self.SetColSize(1, 75)
+ self.SetColSize(2, 75)
+
+ # Sink events
+ self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnLeftClick)
+ self.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, self.OnRightClick)
+ self.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.OnLeftDoubleClick)
+ self.Bind(wx.grid.EVT_GRID_RANGE_SELECT, self.OnRangeSelect)
+ self.Bind(wx.grid.EVT_GRID_ROW_SIZE, self.OnRowSize)
+ self.Bind(wx.grid.EVT_GRID_COL_SIZE, self.OnColSize)
+ self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnCellChange)
+ self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnGridSelectCell)
+
+ def OnGridSelectCell(self, event):
+ """ Track cell selections """
+ # Save the last cell coordinates
+ self._lastRow, self._lastCol = event.GetRow(), event.GetCol()
+ event.Skip()
+
+ def OnRowSize(self, event):
+ event.Skip()
+
+ def OnColSize(self, event):
+ event.Skip()
+
+ def OnCellChange(self, event):
+ event.Skip()
+
+ def OnLeftClick(self, event):
+ """ Override left-click behavior to prevent left-click edit initiation """
+ # Save the cell clicked
+ currCell = (event.GetRow(), event.GetCol())
+
+ # Suppress event if same cell clicked twice in a row.
+ # This prevents a single-click from initiating an edit.
+ if currCell != (self._lastRow, self._lastCol): event.Skip()
+
+ def OnRightClick(self, event):
+ """ Move grid cursor when a cell is right-clicked """
+ self.SetGridCursor( event.GetRow(), event.GetCol() )
+ event.Skip()
+
+ def OnLeftDoubleClick(self, event):
+ """ Initiate the cell editor on a double-click """
+ # Move grid cursor to double-clicked cell
+ if self.CanEnableCellControl():
+ self.SetGridCursor( event.GetRow(), event.GetCol() )
+ self.EnableCellEditControl(True) # Show the cell editor
+ event.Skip()
+
+ def OnRangeSelect(self, event):
+ """ Track which cells are selected so that copy/paste behavior can be implemented """
+ # If a single cell is selected, then Selecting() returns False (0)
+ # and range coords are entire grid. In this case cancel previous selection.
+ # If more than one cell is selected, then Selecting() is True (1)
+ # and range accurately reflects selected cells. Save them.
+ # If more cells are added to a selection, selecting remains True (1)
+ self._selected = None
+ if event.Selecting():
+ self._selected = ((event.GetTopRow(), event.GetLeftCol()),
+ (event.GetBottomRow(), event.GetRightCol()))
+ event.Skip()
+
+ def Copy(self):
+ """ Copy the currently selected cells to the clipboard """
+ # TODO: raise an error when there are no cells selected?
+ if self._selected == None: return
+ ((r1, c1), (r2, c2)) = self._selected
+
+ # Build a string to put on the clipboard
+ # (Is there a faster way to do this in Python?)
+ crlf = chr(13) + chr(10)
+ tab = chr(9)
+ s = ""
+ for row in range(r1, r2+1):
+ for col in range(c1, c2):
+ s += self.GetCellValue(row,col)
+ s += tab
+ s += self.GetCellValue(row, c2)
+ s += crlf
+
+ # Put the string on the clipboard
+ if wx.TheClipboard.Open():
+ wx.TheClipboard.Clear()
+ wx.TheClipboard.SetData(wx.TextDataObject(s))
+ wx.TheClipboard.Close()
+
+ def Paste(self):
+ """ Paste the contents of the clipboard into the currently selected cells """
+ # (Is there a better way to do this?)
+ if wx.TheClipboard.Open():
+ td = wx.TextDataObject()
+ success = wx.TheClipboard.GetData(td)
+ wx.TheClipboard.Close()
+ if not success: return # Exit on failure
+ s = td.GetText() # Get the text
+
+ crlf = chr(13) + chr(10) # CrLf characters
+ tab = chr(9) # Tab character
+
+ rows = s.split(crlf) # split into rows
+ rows = rows[0:-1] # leave out last element, which is always empty
+ for i in range(0, len(rows)): # split rows into elements
+ rows[i] = rows[i].split(tab)
+
+ # Get the starting and ending cell range to paste into
+ if self._selected == None: # If no cells selected...
+ r1 = self.GetGridCursorRow() # Start the paste at the current location
+ c1 = self.GetGridCursorCol()
+ r2 = self.GetNumberRows()-1 # Go to maximum row and col extents
+ c2 = self.GetNumberCols()-1
+ else: # If cells selected, only paste there
+ ((r1, c1), (r2, c2)) = self._selected
+
+ # Enter data into spreadsheet cells one at a time
+ r = r1 # Init row and column counters
+ c = c1
+ for row in rows: # Loop over all rows
+ for element in row: # Loop over all row elements
+ self.SetCellValue(r, c, str(element)) # Set cell value
+ c += 1 # Increment the column counter
+ if c > c2: break # Do not exceed maximum column
+ r += 1
+ if r > r2: break # Do not exceed maximum row
+ c = c1
+
+ def Clear(self):
+ """ Clear the currently selected cells """
+ if self._selected == None: # If no selection...
+ r = self.GetGridCursorRow() # clear only current cell
+ c = self.GetGridCursorCol()
+ self.SetCellValue(r, c, "")
+ else: # Otherwise clear selected cells
+ ((r1, c1), (r2, c2)) = self._selected
+ for r in range(r1, r2+1):
+ for c in range(c1, c2+1):
+ self.SetCellValue(r, c, "")
+
+ def SetNumberRows(self, numRows=1):
+ """ Set the number of rows in the sheet """
+ # Check for non-negative number
+ if numRows < 0: return False
+
+ # Adjust number of rows
+ curRows = self.GetNumberRows()
+ if curRows < numRows:
+ self.AppendRows(numRows - curRows)
+ elif curRows > numRows:
+ self.DeleteRows(numRows, curRows - numRows)
+
+ return True
+
+ def SetNumberCols(self, numCols=1):
+ """ Set the number of columns in the sheet """
+ # Check for non-negative number
+ if numCols < 0: return False
+
+ # Adjust number of rows
+ curCols = self.GetNumberCols()
+ if curCols < numCols:
+ self.AppendCols(numCols - curCols)
+ elif curCols > numCols:
+ self.DeleteCols(numCols, curCols - numCols)
+
+ return True
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/shell.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/shell.py
new file mode 100644
index 0000000..049e9a8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/shell.py
@@ -0,0 +1,376 @@
+# shell.py
+#----------------------------------------------------------------------
+# 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o Added deprecation warning.
+#
+
+"""wxPython interactive shell
+
+Copyright (c) 1999 SIA "ANK"
+
+this module is free software. it may be used under same terms as Python itself
+
+Notes:
+i would like to use command completion (see rlcompleter library module),
+but i cannot load it because i don't have readline...
+
+History:
+
+* 03-oct-1999 [als] created
+* 04-oct-1999 [als] PyShellOutput.intro moved from __init__ parameters to class
+ attributes; html debug disabled
+* 04-oct-1999 [als] fixed bug with class attributes input prompts and output
+ styles added to customized demo some html cleanups
+* 04-oct-1999 [rpd] Changed to use the new sizers
+* 05-oct-1999 [als] changes inspired by code.InteractiveInterpreter()
+ from Python Library. if i knew about this class earlier,
+ i would rather inherit from it.
+ renamed to wxPyShell.py since i've renounced the 8.3 scheme
+* 8-10-2001: THIS MODULE IS NOW DEPRECATED. Please see the most excellent
+ PyCrust package instead.
+
+"""
+__version__ ="$Revision$"
+# $RCSfile$
+
+import code
+import sys
+import traceback
+import warnings
+
+import wx
+import wx.html
+
+warningmsg = r"""\
+
+########################################\
+# THIS MODULE IS NOW DEPRECATED |
+# |
+# Please see the most excellent PyCrust |
+# package instead. |
+########################################/
+
+"""
+
+warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
+
+#----------------------------------------------------------------------
+
+class PyShellInput(wx.Panel):
+ """PyShell input window
+
+ """
+ PS1 =" Enter Command:"
+ PS2 ="... continue:"
+ def __init__(self, parent, shell, id=-1):
+ """Create input window
+
+ shell must be a PyShell object.
+ it is used for exception handling, eval() namespaces,
+ and shell.output is used for output
+ (print's go to overridden stdout)
+ """
+ wx.Panel.__init__(self, parent, id)
+ self.shell =shell
+ # make a private copy of class attrs
+ self.PS1 =PyShellInput.PS1
+ self.PS2 =PyShellInput.PS2
+ # create controls
+ self.label =wx.StaticText(self, -1, self.PS1)
+ tid =wx.NewId()
+ self.entry =wx.TextCtrl(self, tid, style = wx.TE_MULTILINE)
+ self.entry.Bind(wx.EVT_CHAR, self.OnChar)
+ self.entry.SetFont(wx.Font(9, wx.MODERN, wx.NORMAL, wx.NORMAL, False))
+ sizer =wx.BoxSizer(wx.VERTICAL)
+ sizer.AddMany([(self.label, 0, wx.EXPAND), (self.entry, 1, wx.EXPAND)])
+ self.SetSizer(sizer)
+ self.SetAutoLayout(True)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ # when in "continuation" mode,
+ # two consecutive newlines are required
+ # to avoid execution of unfinished block
+ self.first_line =1
+
+ def OnSetFocus(self, event):
+ self.entry.SetFocus()
+
+
+ def Clear(self, event=None):
+ """reset input state"""
+ self.label.SetLabel(self.PS1)
+ self.label.Refresh()
+ self.entry.SetSelection(0, self.entry.GetLastPosition())
+ self.first_line =1
+ # self.entry.SetFocus()
+
+ def OnChar(self, event):
+ """called on CHARevent. executes input on newline"""
+ # print "On Char:", event.__dict__.keys()
+ if event.GetKeyCode() !=wx.WXK_RETURN:
+ # not of our business
+ event.Skip()
+ return
+ text =self.entry.GetValue()
+ # weird CRLF thingy
+ text = text.replace("\r\n", "\n")
+ # see if we've finished
+ if (not (self.first_line or text[-1] =="\n") # in continuation mode
+ or (text[-1] =="\\") # escaped newline
+ ):
+ # XXX should escaped newline put myself i "continuation" mode?
+ event.Skip()
+ return
+ # ok, we can try to execute this
+ rc =self.shell.TryExec(text)
+ if rc:
+ # code is incomplete; continue input
+ if self.first_line:
+ self.label.SetLabel(self.PS2)
+ self.label.Refresh()
+ self.first_line =0
+ event.Skip()
+ else:
+ self.Clear()
+
+class PyShellOutput(wx.Panel):
+ """PyShell output window
+
+ for now, it is based on simple wxTextCtrl,
+ but i'm looking at HTML classes to provide colorized output
+ """
+ # attributes for for different (input, output, exception) display styles:
+ # begin tag, end tag, newline
+ in_style =(" <font color=\"#000080\"><tt>&gt;&gt;&gt;&nbsp;",
+ "</tt></font><br>\n", "<br>\n...&nbsp;")
+ out_style =("<tt>", "</tt>\n", "<br>\n")
+ exc_style =("<font color=\"#FF0000\"><tt>",
+ "</tt></font>\n", "<br>\n")
+ intro ="<H3>wxPython Interactive Shell</H3>\n"
+ html_debug =0
+ # entity references
+ erefs =(("&", "&amp;"), (">", "&gt;"), ("<", "&lt;"), (" ", "&nbsp; "))
+ def __init__(self, parent, id=-1):
+ wx.Panel.__init__(self, parent, id)
+ # make a private copy of class attrs
+ self.in_style =PyShellOutput.in_style
+ self.out_style =PyShellOutput.out_style
+ self.exc_style =PyShellOutput.exc_style
+ self.intro =PyShellOutput.intro
+ self.html_debug =PyShellOutput.html_debug
+ # create windows
+ if self.html_debug:
+ # this was used in html debugging,
+ # but i don't want to delete it; it's funny
+ splitter =wx.SplitterWindow(self, -1)
+ self.view =wx.TextCtrl(splitter, -1,
+ style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
+ self.html =wx.html.HtmlWindow(splitter)
+ splitter.SplitVertically(self.view, self.html)
+ splitter.SetSashPosition(40)
+ splitter.SetMinimumPaneSize(3)
+ self.client =splitter
+ else:
+ self.view =None
+ self.html =wx.html.HtmlWindow(self)
+ self.client =self.html # used in OnSize()
+ self.text =self.intro
+ self.html.SetPage(self.text)
+ self.html.SetAutoLayout(True)
+ self.line_buffer =""
+ # refreshes are annoying
+ self.in_batch =0
+ self.dirty =0
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+ def OnSize(self, event):
+ self.client.SetSize(self.GetClientSize())
+
+ def OnIdle(self, event):
+ """when there's nothing to do, we can update display"""
+ if self.in_batch and self.dirty: self.UpdWindow()
+
+ def BeginBatch(self):
+ """do not refresh display till EndBatch()"""
+ self.in_batch =1
+
+ def EndBatch(self):
+ """end batch; start updating display immediately"""
+ self.in_batch =0
+ if self.dirty: self.UpdWindow()
+
+ def UpdWindow(self):
+ """sync display with text buffer"""
+ html =self.html
+ html.SetPage(self.text)
+ self.dirty =0
+ # scroll to the end
+ (x,y) =html.GetVirtualSize()
+ html.Scroll(0, y)
+
+ def AddText(self, text, style=None):
+ """write text to output window"""
+ # a trick needed to defer default from compile-time to execute-time
+ if style ==None: style =self.out_style
+ if 0 and __debug__: sys.__stdout__.write(text)
+ # handle entities
+ for (symbol, eref) in self.erefs:
+ text = text.replace(symbol, eref)
+ # replace newlines
+ text = text.replace("\n", style[2])
+ # add to contents
+ self.text =self.text +style[0] +text +style[1]
+ if not self.in_batch: self.UpdWindow()
+ else: self.dirty =1
+ if self.html_debug:
+ # html debug output needn't to be too large
+ self.view.SetValue(self.text[-4096:])
+
+ def write(self, str, style=None):
+ """stdout-like interface"""
+ if style ==None: style =self.out_style
+ # do not process incomplete lines
+ if len(str) <1:
+ # hm... what was i supposed to do?
+ return
+ elif str[-1] !="\n":
+ self.line_buffer =self.line_buffer +str
+ else:
+ self.AddText(self.line_buffer +str, style)
+ self.line_buffer =""
+
+ def flush(self, style=None):
+ """write out all that was left in line buffer"""
+ if style ==None: style =self.out_style
+ self.AddText(self.line_buffer +"\n", style)
+
+ def write_in(self, str, style=None):
+ """write text in "input" style"""
+ if style ==None: style =self.in_style
+ self.AddText(str, style)
+
+ def write_exc(self, str, style=None):
+ """write text in "exception" style"""
+ if style ==None: style =self.exc_style
+ self.AddText(str, style)
+
+class PyShell(wx.Panel):
+ """interactive Python shell with wxPython interface
+
+ """
+ def __init__(self, parent, globals=globals(), locals={},
+ id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.TAB_TRAVERSAL, name="shell"):
+ """create PyShell window"""
+ wx.Panel.__init__(self, parent, id, pos, size, style, name)
+ self.globals =globals
+ self.locals =locals
+ splitter =wx.SplitterWindow(self, -1)
+ self.output =PyShellOutput(splitter)
+ self.input =PyShellInput(splitter, self)
+ self.input.SetFocus()
+ splitter.SplitHorizontally(self.input, self.output)
+ splitter.SetSashPosition(100)
+ splitter.SetMinimumPaneSize(20)
+ self.splitter =splitter
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ def OnSetFocus(self, event):
+ self.input.SetFocus()
+
+ def TryExec(self, source, symbol="single"):
+ """Compile and run some source in the interpreter.
+
+ borrowed from code.InteractiveInterpreter().runsource()
+ as i said above, i would rather like to inherit from that class
+
+ returns 1 if more input is required, or 0, otherwise
+ """
+ try:
+ cc = code.compile_command(source, symbol=symbol)
+ except (OverflowError, SyntaxError):
+ # [als] hm... never seen anything of that kind
+ self.ShowSyntaxError()
+ return 0
+ if cc is None:
+ # source is incomplete
+ return 1
+ # source is sucessfully compiled
+ out =self.output
+ # redirect system stdout to the output window
+ prev_out =sys.stdout
+ sys.stdout =out
+ # begin printout batch (html updates are deferred until EndBatch())
+ out.BeginBatch()
+ out.write_in(source)
+ try:
+ exec cc in self.globals, self.locals
+ except SystemExit:
+ # SystemExit is not handled and has to be re-raised
+ raise
+ except:
+ # all other exceptions produce traceback output
+ self.ShowException()
+ # switch back to saved stdout
+ sys.stdout =prev_out
+ # commit printout
+ out.flush()
+ out.EndBatch()
+ return 0
+
+ def ShowException(self):
+ """display the traceback for the latest exception"""
+ (etype, value, tb) =sys.exc_info()
+ # remove myself from traceback
+ tblist =traceback.extract_tb(tb)[1:]
+ msg = ' '.join(traceback.format_exception_only(etype, value)
+ +traceback.format_list(tblist))
+ self.output.write_exc(msg)
+
+ def ShowSyntaxError(self):
+ """display message about syntax error (no traceback here)"""
+ (etype, value, tb) =sys.exc_info()
+ msg = ' '.join(traceback.format_exception_only(etype, value))
+ self.output.write_exc(msg)
+
+ def OnSize(self, event):
+ self.splitter.SetSize(self.GetClientSize())
+
+#----------------------------------------------------------------------
+if __name__ == '__main__':
+ class MyFrame(wx.Frame):
+ """Very standard Frame class. Nothing special here!"""
+ def __init__(self, parent=None, id =-1,
+ title="wxPython Interactive Shell"):
+ wx.Frame.__init__(self, parent, id, title)
+ self.shell =PyShell(self)
+
+ class MyApp(wx.App):
+ """Demonstrates usage of both default and customized shells"""
+ def OnInit(self):
+ frame = MyFrame()
+ frame.Show(True)
+ self.SetTopWindow(frame)
+## PyShellInput.PS1 =" let's get some work done..."
+## PyShellInput.PS2 =" ok, what do you really mean?"
+## PyShellOutput.in_style =(
+## "<I><font color=\"#008000\"><tt>&gt;&gt;&gt;&nbsp;",
+## "</tt></font></I><br>\n", "<br>\n...&nbsp;")
+## PyShellOutput.out_style =(
+## "<font color=\"#000080\"><tt>",
+## "</tt></font><br>\n", "<br>\n")
+## PyShellOutput.exc_style =("<B><font color=\"#FF0000\"><tt>",
+## "</tt></font></B>\n", "<br>\n")
+## PyShellOutput.intro ="<I><B>Customized wxPython Shell</B>" \
+## "<br>&lt;-- move this sash to see html debug output</I><br>\n"
+## PyShellOutput.html_debug =1
+## frame = MyFrame(title="Customized wxPython Shell")
+## frame.Show(True)
+ return True
+
+ app = MyApp(0)
+ app.MainLoop()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/sized_controls.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/sized_controls.py
new file mode 100644
index 0000000..78977d2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/sized_controls.py
@@ -0,0 +1,746 @@
+#----------------------------------------------------------------------
+# Name: sized_controls.py
+# Purpose: Implements default, HIG-compliant sizers under the hood
+# and provides a simple interface for customizing those sizers.
+#
+# Author: Kevin Ollivier
+#
+# Created: 26-May-2006
+# Copyright: (c) 2006 Kevin Ollivier
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import wx
+import wx.lib.scrolledpanel as sp
+
+# For HIG info: links to all the HIGs can be found here:
+# http://en.wikipedia.org/wiki/Human_Interface_Guidelines
+
+
+# useful defines for sizer prop values
+
+halign = { "left": wx.ALIGN_LEFT,
+ "center": wx.ALIGN_CENTER_HORIZONTAL,
+ "centre": wx.ALIGN_CENTRE_HORIZONTAL,
+ "right": wx.ALIGN_RIGHT,
+ }
+
+valign = { "top": wx.ALIGN_TOP,
+ "bottom": wx.ALIGN_BOTTOM,
+ "center": wx.ALIGN_CENTER_VERTICAL,
+ "centre": wx.ALIGN_CENTRE_VERTICAL,
+ }
+
+align = { "center": wx.ALIGN_CENTER,
+ "centre": wx.ALIGN_CENTRE,
+ }
+
+border = { "left": wx.LEFT,
+ "right": wx.RIGHT,
+ "top": wx.TOP,
+ "bottom": wx.BOTTOM,
+ "all": wx.ALL,
+ }
+
+minsize = { "fixed": wx.FIXED_MINSIZE,
+ }
+
+misc_flags = { "expand": wx.EXPAND, }
+
+
+# My attempt at creating a more intuitive replacement for nesting box sizers
+class TableSizer(wx.PySizer):
+ def __init__(self, rows=0, cols=0):
+ wx.PySizer.__init__(self)
+ self.rows = rows
+ self.cols = cols
+ self.fixed_width = 0
+ self.fixed_height = 0
+ self.hgrow = 0
+ self.vgrow = 0
+
+ self.row_widths = []
+ self.col_heights = []
+
+ # allow us to use 'old-style' proportions when emulating box sizers
+ self.isHorizontal = (self.rows == 1 and self.cols == 0)
+ self.isVertical = (self.cols == 1 and self.rows == 0)
+
+ def CalcNumRowsCols(self):
+ numrows = self.rows
+ numcols = self.cols
+ numchild = len(self.GetChildren())
+
+ if numrows == 0 and numcols == 0:
+ return 0, 0
+
+ if numrows == 0:
+ rows, mod = divmod(numchild, self.cols)
+ if mod > 0:
+ rows += 1
+ numrows = rows
+
+ if numcols == 0:
+ cols, mod = divmod(numchild, self.rows)
+ if mod > 0:
+ cols += 1
+ numcols = cols
+
+ return numrows, numcols
+
+ def CalcMin(self):
+ numrows, numcols = self.CalcNumRowsCols()
+ numchild = len(self.GetChildren())
+
+ if numchild == 0:
+ return wx.Size(10, 10)
+
+ if numrows == 0 and numcols == 0:
+ print "TableSizer must have the number of rows or columns set. Cannot continue."
+ return wx.Size(10, 10)
+
+ self.row_widths = [0 for x in range(0, numrows)]
+ self.col_heights = [0 for x in range(0, numcols)]
+ currentRow = 0
+ currentCol = 0
+ counter = 0
+ self.hgrow = 0
+ self.vgrow = 0
+
+ # get the max row width and max column height
+ for item in self.GetChildren():
+ if self.cols != 0:
+ currentRow, currentCol = divmod(counter, numcols)
+ else:
+ currentCol, currentRow = divmod(counter, numrows)
+
+ if item.IsShown():
+ width, height = item.CalcMin()
+
+ if self.isVertical and item.GetProportion() > 0:
+ self.hgrow += item.GetProportion()
+ elif self.isHorizontal and item.GetProportion() > 0:
+ self.vgrow += item.GetProportion()
+
+ if width > self.row_widths[currentRow]:
+ self.row_widths[currentRow] = width
+
+ if height > self.col_heights[currentCol]:
+ self.col_heights[currentCol] = height
+
+ counter += 1
+
+ minwidth = 0
+ for row_width in self.row_widths:
+ minwidth += row_width
+
+ minheight = 0
+ for col_height in self.col_heights:
+ minheight += col_height
+
+ self.fixed_width = minwidth
+ self.fixed_height = minheight
+
+ return wx.Size(minwidth, minheight)
+
+ def RecalcSizes(self):
+ numrows, numcols = self.CalcNumRowsCols()
+ numchild = len(self.GetChildren())
+
+ if numchild == 0:
+ return
+ currentRow = 0
+ currentCol = 0
+ counter = 0
+
+ print "cols %d, rows %d" % (self.cols, self.rows)
+ print "fixed_height %d, fixed_width %d" % (self.fixed_height, self.fixed_width)
+ #print "self.GetSize() = " + `self.GetSize()`
+
+ row_widths = [0 for x in range(0, numrows)]
+ col_heights = [0 for x in range(0, numcols)]
+ item_sizes = [0 for x in range(0, len(self.GetChildren()))]
+ grow_sizes = [0 for x in range(0, len(self.GetChildren()))]
+
+ curHPos = 0
+ curVPos = 0
+ curCol = 0
+ curRow = 0
+ # first, we set sizes for all children, and while doing so, calc
+ # the maximum row heights and col widths. Then, afterwards we handle
+ # the positioning of the controls
+
+ for item in self.GetChildren():
+ if self.cols != 0:
+ currentRow, currentCol = divmod(counter, numcols)
+ else:
+ currentCol, currentRow = divmod(counter, numrows)
+ if item.IsShown():
+ item_minsize = item.GetMinSizeWithBorder()
+ width = item_minsize[0]
+ height = item_minsize[1]
+
+ print "row_height %d, row_width %d" % (self.col_heights[currentCol], self.row_widths[currentRow])
+ growable_width = (self.GetSize()[0]) - width
+ growable_height = (self.GetSize()[1]) - height
+
+ #if not self.isVertical and not self.isHorizontal:
+ # growable_width = self.GetSize()[0] - self.row_widths[currentRow]
+ # growable_height = self.GetSize()[1] - self.col_heights[currentCol]
+
+ #print "grow_height %d, grow_width %d" % (growable_height, growable_width)
+
+ item_vgrow = 0
+ item_hgrow = 0
+ # support wx.EXPAND for box sizers to be compatible
+ if item.GetFlag() & wx.EXPAND:
+ if self.isVertical:
+ if self.hgrow > 0 and item.GetProportion() > 0:
+ item_hgrow = (growable_width * item.GetProportion()) / self.hgrow
+ item_vgrow = growable_height
+
+ elif self.isHorizontal:
+ if self.vgrow > 0 and item.GetProportion() > 0:
+ item_vgrow = (growable_height * item.GetProportion()) / self.vgrow
+ item_hgrow = growable_width
+
+ if growable_width > 0 and item.GetHGrow() > 0:
+ item_hgrow = (growable_width * item.GetHGrow()) / 100
+ print "hgrow = %d" % (item_hgrow)
+
+ if growable_height > 0 and item.GetVGrow() > 0:
+ item_vgrow = (growable_height * item.GetVGrow()) / 100
+ print "vgrow = %d" % (item_vgrow)
+
+ grow_size = wx.Size(item_hgrow, item_vgrow)
+ size = item_minsize #wx.Size(item_minsize[0] + item_hgrow, item_minsize[1] + item_vgrow)
+ if size[0] + grow_size[0] > row_widths[currentRow]:
+ row_widths[currentRow] = size[0] + grow_size[0]
+ if size[1] + grow_size[1] > col_heights[currentCol]:
+ col_heights[currentCol] = size[1] + grow_size[1]
+
+ grow_sizes[counter] = grow_size
+ item_sizes[counter] = size
+
+ counter += 1
+
+ counter = 0
+ for item in self.GetChildren():
+ if self.cols != 0:
+ currentRow, currentCol = divmod(counter, numcols)
+ else:
+ currentCol, currentRow = divmod(counter, numrows)
+
+ itempos = self.GetPosition()
+ if item.IsShown():
+ rowstart = itempos[0]
+ for row in range(0, currentRow):
+ rowstart += row_widths[row]
+
+ colstart = itempos[1]
+ for col in range(0, currentCol):
+ #print "numcols = %d, currentCol = %d, col = %d" % (numcols, currentCol, col)
+ colstart += col_heights[col]
+
+ itempos[0] += rowstart
+ itempos[1] += colstart
+
+ if item.GetFlag() & wx.ALIGN_RIGHT:
+ itempos[0] += (row_widths[currentRow] - item_sizes[counter][0])
+ elif item.GetFlag() & (wx.ALIGN_CENTER | wx.ALIGN_CENTER_HORIZONTAL):
+ itempos[0] += (row_widths[currentRow] - item_sizes[counter][0]) / 2
+
+ if item.GetFlag() & wx.ALIGN_BOTTOM:
+ itempos[1] += (col_heights[currentCol] - item_sizes[counter][1])
+ elif item.GetFlag() & (wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL):
+ itempos[1] += (col_heights[currentCol] - item_sizes[counter][1]) / 2
+
+ hgrowth = (grow_sizes[counter][0] - itempos[0])
+ if hgrowth > 0:
+ item_sizes[counter][0] += hgrowth
+
+ vgrowth = (grow_sizes[counter][1] - itempos[1])
+ if vgrowth > 0:
+ item_sizes[counter][1] += vgrowth
+ #item_sizes[counter][1] -= itempos[1]
+ item.SetDimension(itempos, item_sizes[counter])
+
+ counter += 1
+
+def GetDefaultBorder(self):
+ border = 4
+ if wx.Platform == "__WXMAC__":
+ border = 6
+ elif wx.Platform == "__WXMSW__":
+ # MSW HIGs use dialog units, not pixels
+ pnt = self.ConvertDialogPointToPixels(wx.Point(4, 4))
+ border = pnt[0] // 2
+ elif wx.Platform == "__WXGTK__":
+ border = 3
+
+ return border
+
+def SetDefaultSizerProps(self):
+ item = self.GetParent().GetSizer().GetItem(self)
+ item.SetProportion(0)
+ item.SetFlag(wx.ALL)
+ item.SetBorder(self.GetDefaultHIGBorder())
+
+def GetSizerProps(self):
+ """
+ Returns a dictionary of prop name + value
+ """
+
+ props = {}
+ item = self.GetParent().GetSizer().GetItem(self)
+ if item is None:
+ return None
+
+ props['proportion'] = item.GetProportion()
+ flags = item.GetFlag()
+
+ if flags & border['all'] == border['all']:
+ props['border'] = (['all'], item.GetBorder())
+ else:
+ borders = []
+ for key in border:
+ if flags & border[key]:
+ borders.append(key)
+
+ props['border'] = (borders, item.GetBorder())
+
+ if flags & align['center'] == align['center']:
+ props['align'] = 'center'
+ else:
+ for key in halign:
+ if flags & halign[key]:
+ props['halign'] = key
+
+ for key in valign:
+ if flags & valign[key]:
+ props['valign'] = key
+
+ for key in minsize:
+ if flags & minsize[key]:
+ props['minsize'] = key
+
+ for key in misc_flags:
+ if flags & misc_flags[key]:
+ props[key] = "true"
+
+ return props
+
+def SetSizerProp(self, prop, value):
+ """
+ Sets a sizer property
+
+ :param prop: valid strings are "proportion", "hgrow", "vgrow",
+ "align", "halign", "valign", "border", "minsize" and "expand"
+ :param value: corresponding value for the prop
+ """
+
+ lprop = prop.lower()
+ sizer = self.GetParent().GetSizer()
+ item = sizer.GetItem(self)
+ flag = item.GetFlag()
+ if lprop == "proportion":
+ item.SetProportion(int(value))
+ elif lprop == "hgrow":
+ item.SetHGrow(int(value))
+ elif lprop == "vgrow":
+ item.SetVGrow(int(value))
+ elif lprop == "align":
+ flag = flag | align[value]
+ elif lprop == "halign":
+ flag = flag | halign[value]
+ elif lprop == "valign":
+ flag = flag | valign[value]
+ # elif lprop == "border":
+ # # this arg takes a tuple (dir, pixels)
+ # dirs, amount = value
+ # if dirs == "all":
+ # dirs = ["all"]
+ # for dir in dirs:
+ # flag = flag | border[dir]
+ # item.SetBorder(amount)
+ elif lprop == "border":
+ # this arg takes a tuple (dir, pixels)
+ dirs, amount = value
+ if dirs == "all":
+ dirs = ["all"]
+ else:
+ flag &= ~(wx.ALL)
+ for dir in dirs:
+ flag = flag | border[dir]
+ item.SetBorder(amount)
+ elif lprop == "minsize":
+ flag = flag | minsize[value]
+ elif lprop in misc_flags:
+ if not value or str(value) == "" or str(value).lower() == "false":
+ flag = flag &~ misc_flags[lprop]
+ else:
+ flag = flag | misc_flags[lprop]
+
+ # auto-adjust growable rows/columns if expand or proportion is set
+ # on a sizer item in a FlexGridSizer
+ if lprop in ["expand", "proportion"] and isinstance(sizer, wx.FlexGridSizer):
+ cols = sizer.GetCols()
+ rows = sizer.GetRows()
+ # FIXME: I'd like to get the item index in the sizer instead, but
+ # doing sizer.GetChildren.index(item) always gives an error
+ itemnum = self.GetParent().GetChildren().index(self)
+
+ col = 0
+ row = 0
+ if cols == 0:
+ col, row = divmod( itemnum, rows )
+ else:
+ row, col = divmod( itemnum, cols )
+
+ if lprop == "expand" and not sizer.IsColGrowable(col):
+ sizer.AddGrowableCol(col)
+ elif lprop == "proportion" and int(value) != 0 and not sizer.IsRowGrowable(row):
+ sizer.AddGrowableRow(row)
+
+ item.SetFlag(flag)
+
+def SetSizerProps(self, props={}, **kwargs):
+ """
+ Allows to set multiple sizer properties
+
+ :param props: a dictionary of prop name + value
+ :param kwargs: key words can be used for properties, e.g. expand=True
+ """
+
+ allprops = {}
+ allprops.update(props)
+ allprops.update(kwargs)
+
+ for prop in allprops:
+ self.SetSizerProp(prop, allprops[prop])
+
+def GetDialogBorder(self):
+ border = 6
+ if wx.Platform == "__WXMAC__" or wx.Platform == "__WXGTK__":
+ border = 12
+ elif wx.Platform == "__WXMSW__":
+ pnt = self.ConvertDialogPointToPixels(wx.Point(7, 7))
+ border = pnt[0]
+
+ return border
+
+def SetHGrow(self, proportion):
+ data = self.GetUserData()
+ if "HGrow" in data:
+ data["HGrow"] = proportion
+ self.SetUserData(data)
+
+def GetHGrow(self):
+ if self.GetUserData() and "HGrow" in self.GetUserData():
+ return self.GetUserData()["HGrow"]
+ else:
+ return 0
+
+def SetVGrow(self, proportion):
+ data = self.GetUserData()
+ if "VGrow" in data:
+ data["VGrow"] = proportion
+ self.SetUserData(data)
+
+def GetVGrow(self):
+ if self.GetUserData() and "VGrow" in self.GetUserData():
+ return self.GetUserData()["VGrow"]
+ else:
+ return 0
+
+def GetDefaultPanelBorder(self):
+ # child controls will handle their borders, so don't pad the panel.
+ return 0
+
+# Why, Python?! Why do you make it so easy?! ;-)
+wx.Dialog.GetDialogBorder = GetDialogBorder
+wx.Panel.GetDefaultHIGBorder = GetDefaultPanelBorder
+wx.Notebook.GetDefaultHIGBorder = GetDefaultPanelBorder
+wx.SplitterWindow.GetDefaultHIGBorder = GetDefaultPanelBorder
+
+wx.Window.GetDefaultHIGBorder = GetDefaultBorder
+wx.Window.SetDefaultSizerProps = SetDefaultSizerProps
+wx.Window.SetSizerProp = SetSizerProp
+wx.Window.SetSizerProps = SetSizerProps
+wx.Window.GetSizerProps = GetSizerProps
+
+wx.SizerItem.SetHGrow = SetHGrow
+wx.SizerItem.GetHGrow = GetHGrow
+wx.SizerItem.SetVGrow = SetVGrow
+wx.SizerItem.GetVGrow = GetVGrow
+
+
+class SizedParent:
+ def AddChild(self, child):
+ # Note: The wx.LogNull is used here to suppress a log message
+ # on wxMSW that happens because when AddChild is called the
+ # widget's hwnd hasn't been set yet, so the GetWindowRect that
+ # happens as a result of sizer.Add (in wxSizerItem::SetWindow)
+ # fails. A better fix would be to defer this code somehow
+ # until after the child widget is fully constructed.
+ sizer = self.GetSizer()
+ nolog = wx.LogNull()
+ item = sizer.Add(child)
+ del nolog
+ item.SetUserData({"HGrow":0, "VGrow":0})
+
+ # Note: One problem is that the child class given to AddChild
+ # is the underlying wxWidgets control, not its Python subclass. So if
+ # you derive your own class, and override that class' GetDefaultBorder(),
+ # etc. methods, it will have no effect.
+ child.SetDefaultSizerProps()
+
+ def GetSizerType(self):
+ return self.sizerType
+
+ def SetSizerType(self, type, options={}):
+ """
+ Sets the sizer type and automatically re-assign any children
+ to it.
+
+ :param type: sizer type, valid values are "horizontal", "vertical",
+ "form", "table" and "grid"
+ :param options: dictionary of options depending on type
+ """
+
+ sizer = None
+ self.sizerType = type
+ if type == "horizontal":
+ sizer = wx.BoxSizer(wx.HORIZONTAL) # TableSizer(0, 1)
+
+ elif type == "vertical":
+ sizer = wx.BoxSizer(wx.VERTICAL) # TableSizer(1, 0)
+
+ elif type == "form":
+ #sizer = TableSizer(2, 0)
+ sizer = wx.FlexGridSizer(0, 2, 0, 0)
+ #sizer.AddGrowableCol(1)
+
+ elif type == "table":
+ rows = cols = 0
+ if options.has_key('rows'):
+ rows = int(options['rows'])
+
+ if options.has_key('cols'):
+ cols = int(options['cols'])
+
+ sizer = TableSizer(rows, cols)
+
+ elif type == "grid":
+ sizer = wx.FlexGridSizer(0, 0, 0, 0)
+ if options.has_key('rows'):
+ sizer.SetRows(int(options['rows']))
+ else:
+ sizer.SetRows(0)
+ if options.has_key('cols'):
+ sizer.SetCols(int(options['cols']))
+ else:
+ sizer.SetCols(0)
+
+ if options.has_key('growable_row'):
+ row, proportion = options['growable_row']
+ sizer.SetGrowableRow(row, proportion)
+
+ if options.has_key('growable_col'):
+ col, proportion = options['growable_col']
+ sizer.SetGrowableCol(col, proportion)
+
+ if options.has_key('hgap'):
+ sizer.SetHGap(options['hgap'])
+
+ if options.has_key('vgap'):
+ sizer.SetVGap(options['vgap'])
+ if sizer:
+ self._SetNewSizer(sizer)
+
+ def _DetachFromSizer(self, sizer):
+ props = {}
+ for child in self.GetChildren():
+ # On the Mac the scrollbars and corner gripper of a
+ # ScrolledWindow will be in the list of children, but
+ # should not be managed by a sizer. So if there is a
+ # child that is not in a sizer make sure we don't track
+ # info for it nor add it to the next sizer.
+ csp = child.GetSizerProps()
+ if csp is not None:
+ props[child.GetId()] = csp
+ self.GetSizer().Detach(child)
+
+ return props
+
+ def _AddToNewSizer(self, sizer, props):
+ for child in self.GetChildren():
+ csp = props.get(child.GetId(), None)
+ # See Mac comment above.
+ if csp is not None:
+ self.GetSizer().Add(child)
+ child.SetSizerProps(csp)
+
+
+class SizedPanel(wx.PyPanel, SizedParent):
+ def __init__(self, *args, **kwargs):
+ """
+ A sized panel
+
+ Controls added to it will automatically be added to its sizer.
+
+ Usage:
+ 'self' is a SizedPanel instance
+
+ self.SetSizerType("horizontal")
+
+ b1 = wx.Button(self, wx.ID_ANY)
+ t1 = wx.TextCtrl(self, -1)
+ t1.SetSizerProps(expand=True)
+ """
+
+ wx.PyPanel.__init__(self, *args, **kwargs)
+ sizer = wx.BoxSizer(wx.VERTICAL) #TableSizer(1, 0)
+ self.SetSizer(sizer)
+ self.sizerType = "vertical"
+
+ def AddChild(self, child):
+ """
+ Called automatically by wx, do not call it from user code
+ """
+
+ if wx.VERSION < (2,8):
+ wx.PyPanel.base_AddChild(self, child)
+ else:
+ wx.PyPanel.AddChild(self, child)
+
+ SizedParent.AddChild(self, child)
+
+ def _SetNewSizer(self, sizer):
+ props = self._DetachFromSizer(sizer)
+ wx.PyPanel.SetSizer(self, sizer)
+ self._AddToNewSizer(sizer, props)
+
+
+class SizedScrolledPanel(sp.ScrolledPanel, SizedParent):
+ def __init__(self, *args, **kwargs):
+ """A sized scrolled panel
+
+ Controls added to it will automatically be added to its sizer.
+
+ Usage:
+ 'self' is a SizedScrolledPanel instance
+
+ self.SetSizerType("horizontal")
+
+ b1 = wx.Button(self, wx.ID_ANY)
+ t1 = wx.TextCtrl(self, -1)
+ t1.SetSizerProps(expand=True)
+ """
+
+ sp.ScrolledPanel.__init__(self, *args, **kwargs)
+ sizer = wx.BoxSizer(wx.VERTICAL) #TableSizer(1, 0)
+ self.SetSizer(sizer)
+ self.sizerType = "vertical"
+ self.SetupScrolling()
+
+ def AddChild(self, child):
+ """
+ Called automatically by wx, should not be called from user code
+ """
+
+ if wx.VERSION < (2,8):
+ sp.ScrolledPanel.base_AddChild(self, child)
+ else:
+ sp.ScrolledPanel.AddChild(self, child)
+
+ SizedParent.AddChild(self, child)
+
+ def _SetNewSizer(self, sizer):
+ props = self._DetachFromSizer(sizer)
+ sp.ScrolledPanel.SetSizer(self, sizer)
+ self._AddToNewSizer(sizer, props)
+
+
+class SizedDialog(wx.Dialog):
+ def __init__(self, *args, **kwargs):
+ """A sized dialog
+
+ Controls added to its content pane will automatically be added to
+ the panes sizer.
+
+ Usage:
+ 'self' is a SizedDialog instance
+
+ pane = self.GetContentsPane()
+ pane.SetSizerType("horizontal")
+
+ b1 = wx.Button(pane, wx.ID_ANY)
+ t1 = wx.TextCtrl(pane, wx.ID_ANY)
+ t1.SetSizerProps(expand=True)
+ """
+
+ wx.Dialog.__init__(self, *args, **kwargs)
+
+ self.SetExtraStyle(wx.WS_EX_VALIDATE_RECURSIVELY)
+
+ self.borderLen = 12
+ self.mainPanel = SizedPanel(self, -1)
+
+ mysizer = wx.BoxSizer(wx.VERTICAL)
+ mysizer.Add(self.mainPanel, 1, wx.EXPAND | wx.ALL, self.GetDialogBorder())
+ self.SetSizer(mysizer)
+
+ self.SetAutoLayout(True)
+
+ def GetContentsPane(self):
+ """
+ Return the pane to add controls too
+ """
+ return self.mainPanel
+
+ def SetButtonSizer(self, sizer):
+ self.GetSizer().Add(sizer, 0, wx.EXPAND | wx.BOTTOM | wx.RIGHT, self.GetDialogBorder())
+
+ # Temporary hack to fix button ordering problems.
+ cancel = wx.FindWindowById(wx.ID_CANCEL, parent=self)
+ no = wx.FindWindowById(wx.ID_NO, parent=self)
+ if no and cancel:
+ cancel.MoveAfterInTabOrder(no)
+
+class SizedFrame(wx.Frame):
+ def __init__(self, *args, **kwargs):
+ """
+ A sized frame
+
+ Controls added to its content pane will automatically be added to
+ the panes sizer.
+
+ Usage:
+ 'self' is a SizedFrame instance
+
+ pane = self.GetContentsPane()
+ pane.SetSizerType("horizontal")
+
+ b1 = wx.Button(pane, wx.ID_ANY)
+ t1 = wx.TextCtrl(pane, -1)
+ t1.SetSizerProps(expand=True)
+ """
+ wx.Frame.__init__(self, *args, **kwargs)
+
+ self.borderLen = 12
+ # this probably isn't needed, but I thought it would help to make it consistent
+ # with SizedDialog, and creating a panel to hold things is often good practice.
+ self.mainPanel = SizedPanel(self, -1)
+
+ mysizer = wx.BoxSizer(wx.VERTICAL)
+ mysizer.Add(self.mainPanel, 1, wx.EXPAND)
+ self.SetSizer(mysizer)
+
+ self.SetAutoLayout(True)
+
+ def GetContentsPane(self):
+ """
+ Return the pane to add controls too
+ """
+ return self.mainPanel
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/softwareupdate.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/softwareupdate.py
new file mode 100644
index 0000000..0eac12f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/softwareupdate.py
@@ -0,0 +1,354 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.softwareupdate
+# Purpose: A mixin class using Esky that allows a frozen application
+# to update itself when new versions of the software become
+# available.
+#
+# Author: Robin Dunn
+#
+# Created: 1-Aug-2011
+# RCS-ID: $Id$
+# Copyright: (c) 2011 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""
+This module provides a class designed to be mixed with wx.App to form a
+derived class which is able to auto-self-update the application when new
+versions are released. It is built upon the Esky package, available in PyPi at
+http://pypi.python.org/pypi/esky.
+
+In order for the software update to work the application must be put into an
+esky bundle using the bdist_esky distutils command, which in turn will use
+py2app, py2exe or etc. to freeze the actual application. See Esky's docs for
+more details. The code in this module will only have effect if the application
+is frozen, and is silently ignored otherwise.
+"""
+
+import wx
+import sys
+import os
+import atexit
+import urllib2
+
+from wx.lib.dialogs import MultiMessageBox
+
+isFrozenApp = hasattr(sys, 'frozen')
+if isFrozenApp:
+ import esky
+ import esky.util
+
+# wx 2.8 doesn't have [SG]etAppDisplayname...
+try:
+ wx.App.GetAppDisplayName
+except AttributeError:
+ wx.App.GetAppDisplayName = wx.App.GetAppName
+ wx.App.SetAppDisplayName = wx.App.SetAppName
+
+
+SOT = 0
+#if 'wxMac' in wx.PlatformInfo:
+# SOT = wx.STAY_ON_TOP
+
+#----------------------------------------------------------------------
+
+
+class UpdateAbortedError(RuntimeError):
+ pass
+
+
+class SoftwareUpdate(object):
+ """
+ Mix this class with wx.App and call InitForUpdates from the derived class'
+ OnInit method. Be sure that the wx.App has set a display name
+ (self.SetAppDisplayName) as that value will be used in the update dialogs.
+ """
+
+ _caption = "Software Update"
+ _networkFailureMsg = (
+ "Unable to connect to %s to check for updates.\n\n"
+ "Perhaps your network is not enabled, the update server is down, or your"
+ "firewall is blocking the connection.")
+
+
+ def InitUpdates(self, updatesURL, changelogURL=None, icon=None):
+ """
+ Set up the Esky object for doing software updates. Passing either the
+ base URL (with a trailing '/') for the location of the update
+ packages, or an instance of a class derived from the
+ esky.finder.VersionFinder class is required. A custom VersionFinder
+ can be used to find and fetch the newer verison of the software in
+ some other way, if desired.
+
+ Call this method from the app's OnInit method.
+ """
+ if isFrozenApp:
+ self._esky = esky.Esky(sys.executable, updatesURL)
+ self._updatesURL = updatesURL
+ self._changelogURL = changelogURL
+ self._icon = icon
+ self._pd = None
+ self._checkInProgress = False
+ try:
+ # get rid of the prior version if it is still here.
+ if self._esky.needs_cleanup():
+ self._esky.cleanup()
+ except:
+ pass
+ self._fixSysExecutable()
+
+
+ def AutoCheckForUpdate(self, frequencyInDays, parentWindow=None, cfg=None):
+ """
+ If it has been frequencyInDays since the last auto-check then check if
+ a software update is available and prompt the user to download and
+ install it. This can be called after a application has started up, and
+ if there is no update available the user will not be bothered.
+ """
+ if not isFrozenApp:
+ return
+ if cfg is None:
+ cfg = wx.Config.Get()
+ oldPath = cfg.GetPath()
+ cfg.SetPath('/autoUpdate')
+ lastCheck = cfg.ReadInt('lastCheck', 0)
+ lastCheckVersion = cfg.Read('lastCheckVersion', '')
+ today = int(wx.DateTime.Today().GetJulianDayNumber())
+ active = self._esky.active_version
+
+ if (today - lastCheck >= frequencyInDays
+ or lastCheckVersion != active):
+ self.CheckForUpdate(True, parentWindow, cfg)
+ cfg.SetPath(oldPath)
+
+
+ def CheckForUpdate(self, silentUnlessUpdate=False, parentWindow=None, cfg=None):
+ """
+ This method will check for the availability of a new update, and will
+ prompt the user with details if there is one there. By default it will
+ also tell the user if there is not a new update, but you can pass
+ silentUnlessUpdate=True to not bother the user if there isn't a new
+ update available.
+
+ This method should be called from an event handler for a "Check for
+ updates" menu item, or something similar. The actual update check
+ will be run in a background thread and this function will return
+ immediately after starting the thread so the application is not
+ blocked if there is network communication problems. A callback to the
+ GUI thread will be made to do the update or report problems as
+ needed.
+ """
+ if not isFrozenApp or self._checkInProgress:
+ return
+ self._checkInProgress = True
+
+
+ def doFindUpdate():
+ try:
+ newest = self._esky.find_update()
+ chLogTxt = ''
+ if newest is not None and self._changelogURL:
+ req = urllib2.urlopen(self._changelogURL, timeout=4)
+ chLogTxt = req.read()
+ req.close()
+ return (newest, chLogTxt)
+
+ except urllib2.URLError:
+ return 'URLError'
+
+
+ def processResults(result):
+ result = result.get()
+ self._checkInProgress = False
+ if result == 'URLError':
+ if not silentUnlessUpdate:
+ MultiMessageBox(
+ self._networkFailureMsg % self._updatesURL,
+ self._caption, parent=parentWindow, icon=self._icon,
+ style=wx.OK|SOT)
+ return
+
+ active = self._esky.active_version
+ if cfg:
+ oldPath = cfg.GetPath()
+ cfg.SetPath('/autoUpdate')
+ today = int(wx.DateTime.Today().GetJulianDayNumber())
+ cfg.WriteInt('lastCheck', today)
+ cfg.Write('lastCheckVersion', active)
+ cfg.Flush()
+ cfg.SetPath(oldPath)
+
+ newest, chLogTxt = result
+ if newest is None:
+ if not silentUnlessUpdate:
+ MultiMessageBox("You are already running the newest verison of %s." %
+ self.GetAppDisplayName(),
+ self._caption, parent=parentWindow, icon=self._icon,
+ style=wx.OK|SOT)
+ return
+ self._parentWindow = parentWindow
+
+ resp = MultiMessageBox("A new version of %s is available.\n\n"
+ "You are currently running verison %s; version %s is now "
+ "available for download. Do you wish to install it now?"
+ % (self.GetAppDisplayName(), active, newest),
+ self._caption, msg2=chLogTxt, style=wx.YES_NO|SOT,
+ parent=parentWindow, icon=self._icon,
+ btnLabels={wx.ID_YES:"Yes, install now",
+ wx.ID_NO:"No, maybe later"})
+ if resp != wx.YES:
+ return
+
+ # Ok, there is a little trickery going on here. We don't know yet if
+ # the user wants to restart the application after the update is
+ # complete, but since atexit functions are executed in a LIFO order we
+ # need to registar our function before we call auto_update and Esky
+ # possibly registers its own atexit function, because we want ours to
+ # be run *after* theirs. So we'll create an instance of an info object
+ # and register its method now, and then fill in the details below
+ # once we decide what we want to do.
+ class RestartInfo(object):
+ def __init__(self):
+ self.exe = None
+ def restart(self):
+ if self.exe is not None:
+ # Execute the program, replacing this process
+ os.execv(self.exe, [self.exe] + sys.argv[1:])
+ info = RestartInfo()
+ atexit.register(info.restart)
+
+ try:
+ # Let Esky handle all the rest of the update process so we can
+ # take advantage of the error checking and priviledge elevation
+ # (if neccessary) that they have done so we don't have to worry
+ # about that ourselves like we would if we broke down the proccess
+ # into component steps.
+ self._esky.auto_update(self._updateProgress)
+
+ except UpdateAbortedError:
+ MultiMessageBox("Update canceled.", self._caption,
+ parent=parentWindow, icon=self._icon,
+ style=wx.OK|SOT)
+ if self._pd:
+ self._pd.Destroy()
+
+ self.InitUpdates(self._updatesURL, self._changelogURL, self._icon)
+ return
+
+ # Ask the user if they want the application to be restarted.
+ resp = MultiMessageBox("The upgrade to %s %s is ready to use; the application will "
+ "need to be restarted to begin using the new release.\n\n"
+ "Restart %s now?"
+ % (self.GetAppDisplayName(), newest, self.GetAppDisplayName()),
+ self._caption, style=wx.YES_NO|SOT,
+ parent=parentWindow, icon=self._icon,
+ btnLabels={wx.ID_YES:"Yes, restart now",
+ wx.ID_NO:"No, I'll restart later"})
+
+ if resp == wx.YES:
+ # Close all windows in this application...
+ for w in wx.GetTopLevelWindows():
+ if isinstance(w, wx.Dialog):
+ w.Destroy()
+ elif isinstance(w, wx.Frame):
+ w.Close(True) # force close (can't be cancelled)
+ wx.Yield()
+
+ # ...find the path of the esky bootstrap/wrapper program...
+ exe = esky.util.appexe_from_executable(sys.executable)
+
+ # ...and tell our RestartInfo object about it.
+ info.exe = exe
+
+ # Make sure the CWD not in the current version's appdir, so it can
+ # hopefully be cleaned up either as we exit or as the next verison
+ # is starting.
+ os.chdir(os.path.dirname(exe))
+
+ # With all the top level windows closed the MainLoop should exit
+ # automatically, but just in case tell it to exit so we can have a
+ # normal-as-possible shutdown of this process. Hopefully there
+ # isn't anything happening after we return from this function that
+ # matters.
+ self.ExitMainLoop()
+
+ return
+
+ # Start the worker thread that will check for an update, it will call
+ # processResults when it is finished.
+ import wx.lib.delayedresult as dr
+ dr.startWorker(processResults, doFindUpdate)
+
+
+
+ def _updateProgress(self, status):
+ # Show progress of the download and install. This function is passed to Esky
+ # functions to use as a callback.
+ if self._pd is None and status.get('status') != 'done':
+ self._pd = wx.ProgressDialog('Software Update', ' '*40,
+ style=wx.PD_CAN_ABORT|wx.PD_APP_MODAL,
+ parent=self._parentWindow)
+ self._pd.Update(0, '')
+
+ if self._parentWindow:
+ self._pd.CenterOnParent()
+
+ simpleMsgMap = { 'searching' : 'Searching...',
+ 'retrying' : 'Retrying...',
+ 'ready' : 'Download complete...',
+ 'installing' : 'Installing...',
+ 'cleaning up' : 'Cleaning up...',}
+
+ if status.get('status') in simpleMsgMap:
+ self._doUpdateProgress(True, simpleMsgMap[status.get('status')])
+
+ elif status.get('status') == 'found':
+ self._doUpdateProgress(True, 'Found version %s...' % status.get('new_version'))
+
+ elif status.get('status') == 'downloading':
+ received = status.get('received')
+ size = status.get('size')
+ currentPercentage = 1.0 * received / size * 100
+ if currentPercentage > 99.5:
+ self._doUpdateProgress(False, "Unzipping...", int(currentPercentage))
+ else:
+ self._doUpdateProgress(False, "Downloading...", int(currentPercentage))
+
+ elif status.get('status') == 'done':
+ if self._pd:
+ self._pd.Destroy()
+ self._pd = None
+
+ wx.Yield()
+
+
+ def _doUpdateProgress(self, pulse, message, value=0):
+ if pulse:
+ keepGoing, skip = self._pd.Pulse(message)
+ else:
+ keepGoing, skip = self._pd.Update(value, message)
+ if not keepGoing: # user pressed the cancel button
+ self._pd.Destroy()
+ self._pd = None
+ raise UpdateAbortedError()
+
+
+ def _fixSysExecutable(self):
+ # It looks like at least some versions of py2app are setting
+ # sys.executable to ApplicationName.app/Contents/MacOS/python instead
+ # of ApplicationName.app/Contents/MacOS/applicationname, which is what
+ # should be used to relaunch the application. Other freezer tools set
+ # sys.executable to the actual executable as expected, so we'll tweak
+ # the setting here for Macs too.
+ if sys.platform == "darwin" and hasattr(sys, 'frozen') \
+ and sys.frozen == 'macosx_app' and sys.executable.endswith('MacOS/python'):
+ names = os.listdir(os.path.dirname(sys.executable))
+ assert len(names) == 2 # there should be only 2
+ for name in names:
+ if name != 'python':
+ sys.executable = os.path.join(os.path.dirname(sys.executable), name)
+ break
+
+#----------------------------------------------------------------------
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/splashscreen.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/splashscreen.py
new file mode 100644
index 0000000..817ddf9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/splashscreen.py
@@ -0,0 +1,132 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.splashscreen
+# Purpose: A simple frame that can display a bitmap and closes itself
+# after a specified timeout or a mouse click.
+#
+# Author: Mike Fletcher, Robin Dunn
+#
+# Created: 19-Nov-1999
+# RCS-ID: $Id$
+# Copyright: (c) 1999 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/11/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o Untested.
+#
+
+"""
+A Splash Screen implemented in Python.
+
+NOTE: Now that wxWindows has a wxSplashScrren class and it is wrapped
+in wxPython this class is deprecated. See the docs for more details.
+"""
+
+import warnings
+import wx
+
+warningmsg = r"""\
+
+#####################################################\
+# THIS MODULE IS NOW DEPRECATED |
+# |
+# The core wx library now contains an implementation |
+# of the 'real' wx.SpashScreen. |
+#####################################################/
+
+"""
+
+warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
+
+
+#----------------------------------------------------------------------
+
+class SplashScreen(wx.Frame):
+ def __init__(self, parent, ID=-1, title="SplashScreen",
+ style=wx.SIMPLE_BORDER|wx.STAY_ON_TOP,
+ duration=1500, bitmapfile="bitmaps/splashscreen.bmp",
+ callback = None):
+ '''
+ parent, ID, title, style -- see wx.Frame
+ duration -- milliseconds to display the splash screen
+ bitmapfile -- absolute or relative pathname to image file
+ callback -- if specified, is called when timer completes, callback is
+ responsible for closing the splash screen
+ '''
+ ### Loading bitmap
+ self.bitmap = bmp = wx.Image(bitmapfile, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
+
+ ### Determine size of bitmap to size window...
+ size = (bmp.GetWidth(), bmp.GetHeight())
+
+ # size of screen
+ width = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_X)
+ height = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_Y)
+ pos = ((width-size[0])/2, (height-size[1])/2)
+
+ # check for overflow...
+ if pos[0] < 0:
+ size = (wx.SystemSettings_GetSystemMetric(wx.SYS_SCREEN_X), size[1])
+ if pos[1] < 0:
+ size = (size[0], wx.SystemSettings_GetSystemMetric(wx.SYS_SCREEN_Y))
+
+ wx.Frame.__init__(self, parent, ID, title, pos, size, style)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseClick)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBG)
+
+ self.Show(True)
+
+
+ class SplashTimer(wx.Timer):
+ def __init__(self, targetFunction):
+ self.Notify = targetFunction
+ wx.Timer.__init__(self)
+
+ if callback is None:
+ callback = self.OnSplashExitDefault
+
+ self.timer = SplashTimer(callback)
+ self.timer.Start(duration, 1) # one-shot only
+
+ def OnPaint(self, event):
+ dc = wx.PaintDC(self)
+ dc.DrawBitmap(self.bitmap, 0,0, False)
+
+ def OnEraseBG(self, event):
+ pass
+
+ def OnSplashExitDefault(self, event=None):
+ self.Close(True)
+
+ def OnCloseWindow(self, event=None):
+ self.Show(False)
+ self.timer.Stop()
+ del self.timer
+ self.Destroy()
+
+ def OnMouseClick(self, event):
+ self.timer.Notify()
+
+#----------------------------------------------------------------------
+
+
+if __name__ == "__main__":
+ class DemoApp(wx.App):
+ def OnInit(self):
+ wx.InitAllImageHandlers()
+ self.splash = SplashScreen(None, bitmapfile="splashscreen.jpg", callback=self.OnSplashExit)
+ self.splash.Show(True)
+ self.SetTopWindow(self.splash)
+ return True
+ def OnSplashExit(self, event=None):
+ print "Yay! Application callback worked!"
+ self.splash.Close(True)
+ del self.splash
+ ### Build working windows here...
+ def test(sceneGraph=None):
+ app = DemoApp(0)
+ app.MainLoop()
+ test()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/splitter.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/splitter.py
new file mode 100644
index 0000000..4912c69
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/splitter.py
@@ -0,0 +1,788 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.splitter
+# Purpose: A class similar to wx.SplitterWindow but that allows more
+# than a single split
+#
+# Author: Robin Dunn
+#
+# Created: 9-June-2005
+# RCS-ID: $Id$
+# Copyright: (c) 2005 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+"""
+This module provides the `MultiSplitterWindow` class, which is very
+similar to the standard `wx.SplitterWindow` except it can be split
+more than once.
+"""
+
+import wx
+
+_RENDER_VER = (2,6,1,1)
+
+#----------------------------------------------------------------------
+
+class MultiSplitterWindow(wx.PyPanel):
+ """
+ This class is very similar to `wx.SplitterWindow` except that it
+ allows for more than two windows and more than one sash. Many of
+ the same styles, constants, and methods behave the same as in
+ wx.SplitterWindow. The key differences are seen in the methods
+ that deal with the child windows managed by the splitter, and also
+ those that deal with the sash positions. In most cases you will
+ need to pass an index value to tell the class which window or sash
+ you are refering to.
+
+ The concept of the sash position is also different than in
+ wx.SplitterWindow. Since the wx.Splitterwindow has only one sash
+ you can think of it's position as either relative to the whole
+ splitter window, or as relative to the first window pane managed
+ by the splitter. Once there is more than one sash then the
+ distinciton between the two concepts needs to be clairified. I've
+ chosen to use the second definition, and sash positions are the
+ distance (either horizontally or vertically) from the origin of
+ the window just before the sash in the splitter stack.
+
+ NOTE: These things are not yet supported:
+
+ * Using negative sash positions to indicate a position offset
+ from the end.
+
+ * User controlled unsplitting (with double clicks on the sash
+ or dragging a sash until the pane size is zero.)
+
+ * Sash gravity
+
+ """
+ def __init__(self, parent, id=-1,
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = 0, name="multiSplitter"):
+ # always turn on tab traversal
+ style |= wx.TAB_TRAVERSAL
+
+ # and turn off any border styles
+ style &= ~wx.BORDER_MASK
+ style |= wx.BORDER_NONE
+
+ # initialize the base class
+ wx.PyPanel.__init__(self, parent, id, pos, size, style, name)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+
+ # initialize data members
+ self._windows = []
+ self._sashes = []
+ self._pending = {}
+ self._permitUnsplitAlways = self.HasFlag(wx.SP_PERMIT_UNSPLIT)
+ self._orient = wx.HORIZONTAL
+ self._dragMode = wx.SPLIT_DRAG_NONE
+ self._activeSash = -1
+ self._oldX = 0
+ self._oldY = 0
+ self._checkRequestedSashPosition = False
+ self._minimumPaneSize = 0
+ self._sashCursorWE = wx.StockCursor(wx.CURSOR_SIZEWE)
+ self._sashCursorNS = wx.StockCursor(wx.CURSOR_SIZENS)
+ self._sashTrackerPen = wx.Pen(wx.BLACK, 2, wx.SOLID)
+ self._needUpdating = False
+ self._isHot = False
+ self._drawSashInBackgroundColour = False
+
+ # Bind event handlers
+ self.Bind(wx.EVT_PAINT, self._OnPaint)
+ self.Bind(wx.EVT_IDLE, self._OnIdle)
+ self.Bind(wx.EVT_SIZE, self._OnSize)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self._OnMouse)
+
+
+
+ def SetOrientation(self, orient):
+ """
+ Set whether the windows managed by the splitter will be
+ stacked vertically or horizontally. The default is
+ horizontal.
+ """
+ assert orient in [ wx.VERTICAL, wx.HORIZONTAL ]
+ self._orient = orient
+
+ def GetOrientation(self):
+ """
+ Returns the current orientation of the splitter, either
+ wx.VERTICAL or wx.HORIZONTAL.
+ """
+ return self._orient
+
+ def SetBackgroundColour(self,color):
+ wx.PyPanel.SetBackgroundColour(self,color)
+ self._drawSashInBackgroundColour = True
+ if wx.NullColour == color:
+ self._drawSashInBackgroundColour = False
+
+
+ def SetMinimumPaneSize(self, minSize):
+ """
+ Set the smallest size that any pane will be allowed to be
+ resized to.
+ """
+ self._minimumPaneSize = minSize
+
+ def GetMinimumPaneSize(self):
+ """
+ Returns the smallest allowed size for a window pane.
+ """
+ return self._minimumPaneSize
+
+
+
+ def AppendWindow(self, window, sashPos=-1):
+ """
+ Add a new window to the splitter at the right side or bottom
+ of the window stack. If sashPos is given then it is used to
+ size the new window.
+ """
+ self.InsertWindow(len(self._windows), window, sashPos)
+
+
+ def InsertWindow(self, idx, window, sashPos=-1):
+ """
+ Insert a new window into the splitter at the position given in
+ ``idx``.
+ """
+ assert window not in self._windows, "A window can only be in the splitter once!"
+ self._windows.insert(idx, window)
+ self._sashes.insert(idx, -1)
+ if not window.IsShown():
+ window.Show()
+ if sashPos != -1:
+ self._pending[window] = sashPos
+ self._checkRequestedSashPosition = False
+ self._SizeWindows()
+
+
+ def DetachWindow(self, window):
+ """
+ Removes the window from the stack of windows managed by the
+ splitter. The window will still exist so you should `Hide` or
+ `Destroy` it as needed.
+ """
+ assert window in self._windows, "Unknown window!"
+ idx = self._windows.index(window)
+ del self._windows[idx]
+ del self._sashes[idx]
+ self._SizeWindows()
+
+
+ def ReplaceWindow(self, oldWindow, newWindow):
+ """
+ Replaces oldWindow (which is currently being managed by the
+ splitter) with newWindow. The oldWindow window will still
+ exist so you should `Hide` or `Destroy` it as needed.
+ """
+ assert oldWindow in self._windows, "Unknown window!"
+ idx = self._windows.index(oldWindow)
+ self._windows[idx] = newWindow
+ if not newWindow.IsShown():
+ newWindow.Show()
+ self._SizeWindows()
+
+
+ def ExchangeWindows(self, window1, window2):
+ """
+ Trade the positions in the splitter of the two windows.
+ """
+ assert window1 in self._windows, "Unknown window!"
+ assert window2 in self._windows, "Unknown window!"
+ idx1 = self._windows.index(window1)
+ idx2 = self._windows.index(window2)
+ self._windows[idx1] = window2
+ self._windows[idx2] = window1
+ self._SizeWindows()
+
+
+ def GetWindow(self, idx):
+ """
+ Returns the idx'th window being managed by the splitter.
+ """
+ assert idx < len(self._windows)
+ return self._windows[idx]
+
+
+ def GetSashPosition(self, idx):
+ """
+ Returns the position of the idx'th sash, measured from the
+ left/top of the window preceding the sash.
+ """
+ assert idx < len(self._sashes)
+ return self._sashes[idx]
+
+
+ def SetSashPosition(self, idx, pos):
+ """
+ Set the psition of the idx'th sash, measured from the left/top
+ of the window preceding the sash.
+ """
+ assert idx < len(self._sashes)
+ self._sashes[idx] = pos
+ self._SizeWindows()
+
+
+ def SizeWindows(self):
+ """
+ Reposition and size the windows managed by the splitter.
+ Useful when windows have been added/removed or when styles
+ have been changed.
+ """
+ self._SizeWindows()
+
+
+ def DoGetBestSize(self):
+ """
+ Overridden base class virtual. Determines the best size of
+ the control based on the best sizes of the child windows.
+ """
+ best = wx.Size(0,0)
+ if not self._windows:
+ best = wx.Size(10,10)
+
+ sashsize = self._GetSashSize()
+ if self._orient == wx.HORIZONTAL:
+ for win in self._windows:
+ winbest = win.GetEffectiveMinSize()
+ best.width += max(self._minimumPaneSize, winbest.width)
+ best.height = max(best.height, winbest.height)
+ best.width += sashsize * (len(self._windows)-1)
+
+ else:
+ for win in self._windows:
+ winbest = win.GetEffectiveMinSize()
+ best.height += max(self._minimumPaneSize, winbest.height)
+ best.width = max(best.width, winbest.width)
+ best.height += sashsize * (len(self._windows)-1)
+
+ border = 2 * self._GetBorderSize()
+ best.width += border
+ best.height += border
+ return best
+
+ # -------------------------------------
+ # Event handlers
+
+ def _OnPaint(self, evt):
+ dc = wx.PaintDC(self)
+ self._DrawSash(dc)
+
+
+ def _OnSize(self, evt):
+ parent = wx.GetTopLevelParent(self)
+ if parent.IsIconized():
+ evt.Skip()
+ return
+ self._SizeWindows()
+
+
+ def _OnIdle(self, evt):
+ evt.Skip()
+ # if this is the first idle time after a sash position has
+ # potentially been set, allow _SizeWindows to check for a
+ # requested size.
+ if not self._checkRequestedSashPosition:
+ self._checkRequestedSashPosition = True
+ self._SizeWindows()
+
+ if self._needUpdating:
+ self._SizeWindows()
+
+
+
+ def _OnMouse(self, evt):
+ if self.HasFlag(wx.SP_NOSASH):
+ return
+
+ x, y = evt.GetPosition()
+ isLive = self.HasFlag(wx.SP_LIVE_UPDATE)
+ adjustNeighbor = evt.ShiftDown()
+
+ # LeftDown: set things up for dragging the sash
+ if evt.LeftDown() and self._SashHitTest(x, y) != -1:
+ self._activeSash = self._SashHitTest(x, y)
+ self._dragMode = wx.SPLIT_DRAG_DRAGGING
+
+ self.CaptureMouse()
+ self._SetResizeCursor()
+
+ if not isLive:
+ self._pendingPos = (self._sashes[self._activeSash],
+ self._sashes[self._activeSash+1])
+ self._DrawSashTracker(x, y)
+
+ self._oldX = x
+ self._oldY = y
+ return
+
+ # LeftUp: Finsish the drag
+ elif evt.LeftUp() and self._dragMode == wx.SPLIT_DRAG_DRAGGING:
+ self._dragMode = wx.SPLIT_DRAG_NONE
+ self.ReleaseMouse()
+ self.SetCursor(wx.STANDARD_CURSOR)
+
+ if not isLive:
+ # erase the old tracker
+ self._DrawSashTracker(self._oldX, self._oldY)
+
+ diff = self._GetMotionDiff(x, y)
+
+ # determine if we can change the position
+ if isLive:
+ oldPos1, oldPos2 = (self._sashes[self._activeSash],
+ self._sashes[self._activeSash+1])
+ else:
+ oldPos1, oldPos2 = self._pendingPos
+ newPos1, newPos2 = self._OnSashPositionChanging(self._activeSash,
+ oldPos1 + diff,
+ oldPos2 - diff,
+ adjustNeighbor)
+ if newPos1 == -1:
+ # the change was not allowed
+ return
+
+ # TODO: check for unsplit?
+
+ self._SetSashPositionAndNotify(self._activeSash, newPos1, newPos2, adjustNeighbor)
+ self._activeSash = -1
+ self._pendingPos = (-1, -1)
+ self._SizeWindows()
+
+ # Entering or Leaving a sash: Change the cursor
+ elif (evt.Moving() or evt.Leaving() or evt.Entering()) and self._dragMode == wx.SPLIT_DRAG_NONE:
+ if evt.Leaving() or self._SashHitTest(x, y) == -1:
+ self._OnLeaveSash()
+ else:
+ self._OnEnterSash()
+
+ # Dragging the sash
+ elif evt.Dragging() and self._dragMode == wx.SPLIT_DRAG_DRAGGING:
+ diff = self._GetMotionDiff(x, y)
+ if not diff:
+ return # mouse didn't move far enough
+
+ # determine if we can change the position
+ if isLive:
+ oldPos1, oldPos2 = (self._sashes[self._activeSash],
+ self._sashes[self._activeSash+1])
+ else:
+ oldPos1, oldPos2 = self._pendingPos
+ newPos1, newPos2 = self._OnSashPositionChanging(self._activeSash,
+ oldPos1 + diff,
+ oldPos2 - diff,
+ adjustNeighbor)
+ if newPos1 == -1:
+ # the change was not allowed
+ return
+
+ if newPos1 == self._sashes[self._activeSash]:
+ return # nothing was changed
+
+ if not isLive:
+ # erase the old tracker
+ self._DrawSashTracker(self._oldX, self._oldY)
+
+ if self._orient == wx.HORIZONTAL:
+ x = self._SashToCoord(self._activeSash, newPos1)
+ else:
+ y = self._SashToCoord(self._activeSash, newPos1)
+
+ # Remember old positions
+ self._oldX = x
+ self._oldY = y
+
+ if not isLive:
+ # draw a new tracker
+ self._pendingPos = (newPos1, newPos2)
+ self._DrawSashTracker(self._oldX, self._oldY)
+ else:
+ self._DoSetSashPosition(self._activeSash, newPos1, newPos2, adjustNeighbor)
+ self._needUpdating = True
+
+
+ # -------------------------------------
+ # Internal helpers
+
+ def _RedrawIfHotSensitive(self, isHot):
+ if not wx.VERSION >= _RENDER_VER:
+ return
+ if wx.RendererNative.Get().GetSplitterParams(self).isHotSensitive:
+ self._isHot = isHot
+ dc = wx.ClientDC(self)
+ self._DrawSash(dc)
+
+
+ def _OnEnterSash(self):
+ self._SetResizeCursor()
+ self._RedrawIfHotSensitive(True)
+
+
+ def _OnLeaveSash(self):
+ self.SetCursor(wx.STANDARD_CURSOR)
+ self._RedrawIfHotSensitive(False)
+
+
+ def _SetResizeCursor(self):
+ if self._orient == wx.HORIZONTAL:
+ self.SetCursor(self._sashCursorWE)
+ else:
+ self.SetCursor(self._sashCursorNS)
+
+
+ def _OnSashPositionChanging(self, idx, newPos1, newPos2, adjustNeighbor):
+ # TODO: check for possibility of unsplit (pane size becomes zero)
+
+ # make sure that minsizes are honored
+ newPos1, newPos2 = self._AdjustSashPosition(idx, newPos1, newPos2, adjustNeighbor)
+
+ # sanity check
+ if newPos1 <= 0:
+ newPos2 += newPos1
+ newPos1 = 0
+
+ # send the events
+ evt = MultiSplitterEvent(
+ wx.wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, self)
+ evt.SetSashIdx(idx)
+ evt.SetSashPosition(newPos1)
+ if not self._DoSendEvent(evt):
+ # the event handler vetoed the change
+ newPos1 = -1
+ else:
+ # or it might have changed the value
+ newPos1 = evt.GetSashPosition()
+
+ if adjustNeighbor and newPos1 != -1:
+ evt.SetSashIdx(idx+1)
+ evt.SetSashPosition(newPos2)
+ if not self._DoSendEvent(evt):
+ # the event handler vetoed the change
+ newPos2 = -1
+ else:
+ # or it might have changed the value
+ newPos2 = evt.GetSashPosition()
+ if newPos2 == -1:
+ newPos1 = -1
+
+ return (newPos1, newPos2)
+
+
+ def _AdjustSashPosition(self, idx, newPos1, newPos2=-1, adjustNeighbor=False):
+ total = newPos1 + newPos2
+
+ # these are the windows on either side of the sash
+ win1 = self._windows[idx]
+ win2 = self._windows[idx+1]
+
+ # make adjustments for window min sizes
+ minSize = self._GetWindowMin(win1)
+ if minSize == -1 or self._minimumPaneSize > minSize:
+ minSize = self._minimumPaneSize
+ minSize += self._GetBorderSize()
+ if newPos1 < minSize:
+ newPos1 = minSize
+ newPos2 = total - newPos1
+
+ if adjustNeighbor:
+ minSize = self._GetWindowMin(win2)
+ if minSize == -1 or self._minimumPaneSize > minSize:
+ minSize = self._minimumPaneSize
+ minSize += self._GetBorderSize()
+ if newPos2 < minSize:
+ newPos2 = minSize
+ newPos1 = total - newPos2
+
+ return (newPos1, newPos2)
+
+
+ def _DoSetSashPosition(self, idx, newPos1, newPos2=-1, adjustNeighbor=False):
+ newPos1, newPos2 = self._AdjustSashPosition(idx, newPos1, newPos2, adjustNeighbor)
+ if newPos1 == self._sashes[idx]:
+ return False
+ self._sashes[idx] = newPos1
+ if adjustNeighbor:
+ self._sashes[idx+1] = newPos2
+ return True
+
+
+ def _SetSashPositionAndNotify(self, idx, newPos1, newPos2=-1, adjustNeighbor=False):
+ # TODO: what is the thing about _requestedSashPosition for?
+
+ self._DoSetSashPosition(idx, newPos1, newPos2, adjustNeighbor)
+
+ evt = MultiSplitterEvent(
+ wx.wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, self)
+ evt.SetSashIdx(idx)
+ evt.SetSashPosition(newPos1)
+ self._DoSendEvent(evt)
+
+ if adjustNeighbor:
+ evt.SetSashIdx(idx+1)
+ evt.SetSashPosition(newPos2)
+ self._DoSendEvent(evt)
+
+
+ def _GetMotionDiff(self, x, y):
+ # find the diff from the old pos
+ if self._orient == wx.HORIZONTAL:
+ diff = x - self._oldX
+ else:
+ diff = y - self._oldY
+ return diff
+
+
+ def _SashToCoord(self, idx, sashPos):
+ coord = 0
+ for i in range(idx):
+ coord += self._sashes[i]
+ coord += self._GetSashSize()
+ coord += sashPos
+ return coord
+
+
+ def _GetWindowMin(self, window):
+ # NOTE: Should this use GetEffectiveMinSize?
+ if self._orient == wx.HORIZONTAL:
+ return window.GetMinWidth()
+ else:
+ return window.GetMinHeight()
+
+
+ def _GetSashSize(self):
+ if self.HasFlag(wx.SP_NOSASH):
+ return 0
+ if wx.VERSION >= _RENDER_VER:
+ return wx.RendererNative.Get().GetSplitterParams(self).widthSash
+ else:
+ return 5
+
+
+ def _GetBorderSize(self):
+ if wx.VERSION >= _RENDER_VER:
+ return wx.RendererNative.Get().GetSplitterParams(self).border
+ else:
+ return 0
+
+
+ def _DrawSash(self, dc):
+ if wx.VERSION >= _RENDER_VER:
+ if self.HasFlag(wx.SP_3DBORDER):
+ wx.RendererNative.Get().DrawSplitterBorder(
+ self, dc, self.GetClientRect())
+
+ # if there are no splits then we're done.
+ if len(self._windows) < 2:
+ return
+
+ # if we are not supposed to use a sash then we're done.
+ if self.HasFlag(wx.SP_NOSASH):
+ return
+
+ # Reverse the sense of the orientation, in this case it refers
+ # to the direction to draw the sash not the direction that
+ # windows are stacked.
+ orient = { wx.HORIZONTAL : wx.VERTICAL,
+ wx.VERTICAL : wx.HORIZONTAL }[self._orient]
+
+ flag = 0
+ if self._isHot:
+ flag = wx.CONTROL_CURRENT
+
+ pos = 0
+ for sash in self._sashes[:-1]:
+ pos += sash
+ if wx.VERSION >= _RENDER_VER and not self._drawSashInBackgroundColour:
+ wx.RendererNative.Get().DrawSplitterSash(self, dc,
+ self.GetClientSize(),
+ pos, orient, flag)
+ else:
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetBrush(wx.Brush(self.GetBackgroundColour()))
+ sashsize = self._GetSashSize()
+ if orient == wx.VERTICAL:
+ x = pos
+ y = 0
+ w = sashsize
+ h = self.GetClientSize().height
+ else:
+ x = 0
+ y = pos
+ w = self.GetClientSize().width
+ h = sashsize
+ dc.DrawRectangle(x, y, w, h)
+
+ pos += self._GetSashSize()
+
+
+ def _DrawSashTracker(self, x, y):
+ # Draw a line to represent the dragging sash, for when not
+ # doing live updates
+ w, h = self.GetClientSize()
+ dc = wx.ScreenDC()
+
+ if self._orient == wx.HORIZONTAL:
+ x1 = x
+ y1 = 2
+ x2 = x
+ y2 = h-2
+ if x1 > w:
+ x1 = w
+ x2 = w
+ elif x1 < 0:
+ x1 = 0
+ x2 = 0
+ else:
+ x1 = 2
+ y1 = y
+ x2 = w-2
+ y2 = y
+ if y1 > h:
+ y1 = h
+ y2 = h
+ elif y1 < 0:
+ y1 = 0
+ y2 = 0
+
+ x1, y1 = self.ClientToScreenXY(x1, y1)
+ x2, y2 = self.ClientToScreenXY(x2, y2)
+
+ dc.SetLogicalFunction(wx.INVERT)
+ dc.SetPen(self._sashTrackerPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawLine(x1, y1, x2, y2)
+ dc.SetLogicalFunction(wx.COPY)
+
+
+ def _SashHitTest(self, x, y, tolerance=5):
+ # if there are no splits then we're done.
+ if len(self._windows) < 2:
+ return -1
+
+ if self._orient == wx.HORIZONTAL:
+ z = x
+ else:
+ z = y
+
+ pos = 0
+ for idx, sash in enumerate(self._sashes[:-1]):
+ pos += sash
+ hitMin = pos - tolerance
+ hitMax = pos + self._GetSashSize() + tolerance
+
+ if z >= hitMin and z <= hitMax:
+ return idx
+
+ pos += self._GetSashSize()
+
+ return -1
+
+
+ def _SizeWindows(self):
+ # no windows yet?
+ if not self._windows:
+ return
+
+ # are there any pending size settings?
+ for window, spos in self._pending.items():
+ idx = self._windows.index(window)
+ # TODO: this may need adjusted to make sure they all fit
+ # in the current client size
+ self._sashes[idx] = spos
+ del self._pending[window]
+
+ # are there any that still have a -1?
+ for idx, spos in enumerate(self._sashes[:-1]):
+ if spos == -1:
+ # TODO: this should also be adjusted
+ self._sashes[idx] = 100
+
+ cw, ch = self.GetClientSize()
+ border = self._GetBorderSize()
+ sash = self._GetSashSize()
+
+ if len(self._windows) == 1:
+ # there's only one, it's an easy layout
+ self._windows[0].SetDimensions(border, border,
+ cw - 2*border, ch - 2*border)
+ else:
+ if 'wxMSW' in wx.PlatformInfo:
+ self.Freeze()
+ if self._orient == wx.HORIZONTAL:
+ x = y = border
+ h = ch - 2*border
+ for idx, spos in enumerate(self._sashes[:-1]):
+ self._windows[idx].SetDimensions(x, y, spos, h)
+ x += spos + sash
+ # last one takes the rest of the space. TODO make this configurable
+ last = cw - 2*border - x
+ self._windows[idx+1].SetDimensions(x, y, last, h)
+ if last > 0:
+ self._sashes[idx+1] = last
+ else:
+ x = y = border
+ w = cw - 2*border
+ for idx, spos in enumerate(self._sashes[:-1]):
+ self._windows[idx].SetDimensions(x, y, w, spos)
+ y += spos + sash
+ # last one takes the rest of the space. TODO make this configurable
+ last = ch - 2*border - y
+ self._windows[idx+1].SetDimensions(x, y, w, last)
+ if last > 0:
+ self._sashes[idx+1] = last
+ if 'wxMSW' in wx.PlatformInfo:
+ self.Thaw()
+
+ self._DrawSash(wx.ClientDC(self))
+ self._needUpdating = False
+
+
+ def _DoSendEvent(self, evt):
+ return not self.GetEventHandler().ProcessEvent(evt) or evt.IsAllowed()
+
+#----------------------------------------------------------------------
+
+class MultiSplitterEvent(wx.PyCommandEvent):
+ """
+ This event class is almost the same as `wx.SplitterEvent` except
+ it adds an accessor for the sash index that is being changed. The
+ same event type IDs and event binders are used as with
+ `wx.SplitterEvent`.
+ """
+ def __init__(self, type=wx.wxEVT_NULL, splitter=None):
+ wx.PyCommandEvent.__init__(self, type)
+ if splitter:
+ self.SetEventObject(splitter)
+ self.SetId(splitter.GetId())
+ self.sashIdx = -1
+ self.sashPos = -1
+ self.isAllowed = True
+
+ def SetSashIdx(self, idx):
+ self.sashIdx = idx
+
+ def SetSashPosition(self, pos):
+ self.sashPos = pos
+
+ def GetSashIdx(self):
+ return self.sashIdx
+
+ def GetSashPosition(self):
+ return self.sashPos
+
+ # methods from wx.NotifyEvent
+ def Veto(self):
+ self.isAllowed = False
+ def Allow(self):
+ self.isAllowed = True
+ def IsAllowed(self):
+ return self.isAllowed
+
+
+
+#----------------------------------------------------------------------
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/statbmp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/statbmp.py
new file mode 100644
index 0000000..3585446
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/statbmp.py
@@ -0,0 +1,89 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.statbmp
+# Purpose: A generic StaticBitmap class.
+#
+# Author: Robin Dunn
+#
+# Created: 12-May-2004
+# RCS-ID: $Id$
+# Copyright: (c) 2004 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import wx
+
+#----------------------------------------------------------------------
+
+class GenStaticBitmap(wx.PyControl):
+ labelDelta = 1
+
+ def __init__(self, parent, ID, bitmap,
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = 0,
+ name = "genstatbmp"):
+ if not style & wx.BORDER_MASK:
+ style = style | wx.BORDER_NONE
+ wx.PyControl.__init__(self, parent, ID, pos, size, style,
+ wx.DefaultValidator, name)
+ self._bitmap = bitmap
+ self.InheritAttributes()
+ self.SetInitialSize(size)
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def SetBitmap(self, bitmap):
+ self._bitmap = bitmap
+ self.SetInitialSize( (bitmap.GetWidth(), bitmap.GetHeight()) )
+ self.Refresh()
+
+
+ def GetBitmap(self):
+ return self._bitmap
+
+
+ def DoGetBestSize(self):
+ """
+ Overridden base class virtual. Determines the best size of the
+ control based on the bitmap size.
+ """
+ return wx.Size(self._bitmap.GetWidth(), self._bitmap.GetHeight())
+
+
+ def AcceptsFocus(self):
+ """Overridden base class virtual."""
+ return False
+
+
+ def GetDefaultAttributes(self):
+ """
+ Overridden base class virtual. By default we should use
+ the same font/colour attributes as the native StaticBitmap.
+ """
+ return wx.StaticBitmap.GetClassDefaultAttributes()
+
+
+ def ShouldInheritColours(self):
+ """
+ Overridden base class virtual. If the parent has non-default
+ colours then we want this control to inherit them.
+ """
+ return True
+
+
+ def OnPaint(self, event):
+ dc = wx.PaintDC(self)
+ if self._bitmap:
+ dc.DrawBitmap(self._bitmap, 0, 0, True)
+
+
+ def OnEraseBackground(self, event):
+ pass
+
+
+
+
+#----------------------------------------------------------------------
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/stattext.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/stattext.py
new file mode 100644
index 0000000..076a996
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/stattext.py
@@ -0,0 +1,189 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.stattext
+# Purpose: A generic wxGenStaticText class. Using this should
+# eliminate some of the platform differences in wxStaticText,
+# such as background colours and mouse sensitivity.
+#
+# Author: Robin Dunn
+#
+# Created: 8-July-2002
+# RCS-ID: $Id$
+# Copyright: (c) 2002 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/12/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+# o Untested.
+#
+
+import wx
+
+BUFFERED = 0 # In unbuffered mode we can let the theme shine through,
+ # otherwise we draw the background ourselves.
+
+if wx.Platform == "__WXMAC__":
+ from Carbon.Appearance import kThemeBrushDialogBackgroundActive
+
+#----------------------------------------------------------------------
+
+class GenStaticText(wx.PyControl):
+ labelDelta = 1
+
+ def __init__(self, parent, ID=-1, label="",
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0,
+ name="genstattext"):
+ wx.PyControl.__init__(self, parent, ID, pos, size, style|wx.NO_BORDER,
+ wx.DefaultValidator, name)
+
+ wx.PyControl.SetLabel(self, label) # don't check wx.ST_NO_AUTORESIZE yet
+ self.InheritAttributes()
+ self.SetInitialSize(size)
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ if BUFFERED:
+ self.defBackClr = self.GetBackgroundColour()
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ else:
+ self.SetBackgroundStyle(wx.BG_STYLE_SYSTEM)
+
+
+
+ def SetLabel(self, label):
+ """
+ Sets the static text label and updates the control's size to exactly
+ fit the label unless the control has wx.ST_NO_AUTORESIZE flag.
+ """
+ wx.PyControl.SetLabel(self, label)
+ style = self.GetWindowStyleFlag()
+ self.InvalidateBestSize()
+ if not style & wx.ST_NO_AUTORESIZE:
+ self.SetSize(self.GetBestSize())
+ self.Refresh()
+
+
+ def SetFont(self, font):
+ """
+ Sets the static text font and updates the control's size to exactly
+ fit the label unless the control has wx.ST_NO_AUTORESIZE flag.
+ """
+ wx.PyControl.SetFont(self, font)
+ style = self.GetWindowStyleFlag()
+ self.InvalidateBestSize()
+ if not style & wx.ST_NO_AUTORESIZE:
+ self.SetSize(self.GetBestSize())
+ self.Refresh()
+
+
+ def DoGetBestSize(self):
+ """
+ Overridden base class virtual. Determines the best size of
+ the control based on the label size and the current font.
+ """
+ label = self.GetLabel()
+ font = self.GetFont()
+ if not font:
+ font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ dc = wx.ClientDC(self)
+ dc.SetFont(font)
+
+ maxWidth = totalHeight = 0
+ for line in label.split('\n'):
+ if line == '':
+ w, h = dc.GetTextExtent('W') # empty lines have height too
+ else:
+ w, h = dc.GetTextExtent(line)
+ totalHeight += h
+ maxWidth = max(maxWidth, w)
+ best = wx.Size(maxWidth, totalHeight)
+ self.CacheBestSize(best)
+ return best
+
+
+ def Enable(self, enable=True):
+ """Overridden Enable() method to properly refresh the widget. """
+
+ wx.PyControl.Enable(self, enable)
+ self.Refresh()
+
+
+ def Disable(self):
+ """Overridden Disable() method to properly refresh the widget. """
+
+ wx.PyControl.Disable(self)
+ self.Refresh()
+
+
+ def AcceptsFocus(self):
+ """Overridden base class virtual."""
+ return False
+
+
+ def GetDefaultAttributes(self):
+ """
+ Overridden base class virtual. By default we should use
+ the same font/colour attributes as the native StaticText.
+ """
+ return wx.StaticText.GetClassDefaultAttributes()
+
+
+ def ShouldInheritColours(self):
+ """
+ Overridden base class virtual. If the parent has non-default
+ colours then we want this control to inherit them.
+ """
+ return True
+
+
+ def OnPaint(self, event):
+ if BUFFERED:
+ dc = wx.BufferedPaintDC(self)
+ else:
+ dc = wx.PaintDC(self)
+ width, height = self.GetClientSize()
+ if not width or not height:
+ return
+
+ if BUFFERED:
+ clr = self.GetBackgroundColour()
+ if wx.Platform == "__WXMAC__" and clr == self.defBackClr:
+ # if colour is still the default then use the theme's background on Mac
+ themeColour = wx.MacThemeColour(kThemeBrushDialogBackgroundActive)
+ backBrush = wx.Brush(themeColour)
+ else:
+ backBrush = wx.Brush(clr, wx.SOLID)
+ dc.SetBackground(backBrush)
+ dc.Clear()
+
+ if self.IsEnabled():
+ dc.SetTextForeground(self.GetForegroundColour())
+ else:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+
+ dc.SetFont(self.GetFont())
+ label = self.GetLabel()
+ style = self.GetWindowStyleFlag()
+ x = y = 0
+ for line in label.split('\n'):
+ if line == '':
+ w, h = self.GetTextExtent('W') # empty lines have height too
+ else:
+ w, h = self.GetTextExtent(line)
+ if style & wx.ALIGN_RIGHT:
+ x = width - w
+ if style & wx.ALIGN_CENTER:
+ x = (width - w)/2
+ dc.DrawText(line, x, y)
+ y += h
+
+
+ def OnEraseBackground(self, event):
+ pass
+
+
+
+
+#----------------------------------------------------------------------
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/throbber.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/throbber.py
new file mode 100644
index 0000000..2812cdd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/throbber.py
@@ -0,0 +1,322 @@
+"""
+A throbber displays an animated image that can be
+started, stopped, reversed, etc. Useful for showing
+an ongoing process (like most web browsers use) or
+simply for adding eye-candy to an application.
+
+Throbbers utilize a wxTimer so that normal processing
+can continue unencumbered.
+"""
+
+#
+# throbber.py - Cliff Wells <clifford.wells@comcast.net>
+#
+# Thanks to Harald Massa <harald.massa@suedvers.de> for
+# suggestions and sample code.
+#
+# $Id$
+#
+# 12/12/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o 2.5 compatability update.
+#
+
+
+import os
+import wx
+
+# ------------------------------------------------------------------------------
+
+THROBBER_EVENT = wx.NewEventType()
+EVT_UPDATE_THROBBER = wx.PyEventBinder(THROBBER_EVENT, 0)
+
+class UpdateThrobberEvent(wx.PyEvent):
+ def __init__(self):
+ wx.PyEvent.__init__(self)
+ self.SetEventType(THROBBER_EVENT)
+
+# ------------------------------------------------------------------------------
+
+class Throbber(wx.PyPanel):
+ """
+ The first argument is either the name of a file that will be split into frames
+ (a composite image) or a list of strings of image names that will be treated
+ as individual frames. If a single (composite) image is given, then additional
+ information must be provided: the number of frames in the image and the width
+ of each frame. The first frame is treated as the "at rest" frame (it is not
+ shown during animation, but only when Throbber.Rest() is called.
+ A second, single image may be optionally specified to overlay on top of the
+ animation. A label may also be specified to show on top of the animation.
+ """
+ def __init__(self, parent, id,
+ bitmap, # single (composite) bitmap or list of bitmaps
+ pos = wx.DefaultPosition,
+ size = wx.DefaultSize,
+ frameDelay = 0.1,# time between frames
+ frames = 0, # number of frames (only necessary for composite image)
+ frameWidth = 0, # width of each frame (only necessary for composite image)
+ label = None, # optional text to be displayed
+ overlay = None, # optional image to overlay on animation
+ reverse = 0, # reverse direction at end of animation
+ style = 0, # window style
+ name = "throbber",
+ rest = 0,
+ current = 0,
+ direction = 1,
+ sequence = None
+ ):
+ wx.PyPanel.__init__(self, parent, id, pos, size, style, name)
+ self.name = name
+ self.label = label
+ self.running = (1 != 1)
+ _seqTypes = (type([]), type(()))
+
+ # set size, guessing if necessary
+ width, height = size
+ if width == -1:
+ if type(bitmap) in _seqTypes:
+ width = bitmap[0].GetWidth()
+ else:
+ if frameWidth:
+ width = frameWidth
+ if height == -1:
+ if type(bitmap) in _seqTypes:
+ height = bitmap[0].GetHeight()
+ else:
+ height = bitmap.GetHeight()
+ self.width, self.height = width, height
+
+ # double check it
+ assert width != -1 and height != -1, "Unable to guess size"
+
+ if label:
+ extentX, extentY = self.GetTextExtent(label)
+ self.labelX = (width - extentX)/2
+ self.labelY = (height - extentY)/2
+ self.frameDelay = frameDelay
+ self.rest = rest
+ self.current = current
+ self.direction = direction
+ self.autoReverse = reverse
+ self.overlay = overlay
+ if overlay is not None:
+ self.overlay = overlay
+ self.overlayX = (width - self.overlay.GetWidth()) / 2
+ self.overlayY = (height - self.overlay.GetHeight()) / 2
+ self.showOverlay = overlay is not None
+ self.showLabel = label is not None
+
+ # do we have a sequence of images?
+ if type(bitmap) in _seqTypes:
+ self.submaps = bitmap
+ self.frames = len(self.submaps)
+ # or a composite image that needs to be split?
+ else:
+ self.frames = frames
+ self.submaps = []
+ for chunk in range(frames):
+ rect = (chunk * frameWidth, 0, width, height)
+ self.submaps.append(bitmap.GetSubBitmap(rect))
+
+ # self.sequence can be changed, but it's not recommended doing it
+ # while the throbber is running. self.sequence[0] should always
+ # refer to whatever frame is to be shown when 'resting' and be sure
+ # that no item in self.sequence >= self.frames or < 0!!!
+ self.SetSequence(sequence)
+
+ self.SetClientSize((width, height))
+
+ timerID = wx.NewId()
+ self.timer = wx.Timer(self, timerID)
+
+ self.Bind(EVT_UPDATE_THROBBER, self.Update)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroyWindow)
+
+
+ def DoGetBestSize(self):
+ return (self.width, self.height)
+
+
+ def OnTimer(self, event):
+ wx.PostEvent(self, UpdateThrobberEvent())
+
+
+ def OnDestroyWindow(self, event):
+ self.Stop()
+ event.Skip()
+
+
+ def Draw(self, dc):
+ dc.DrawBitmap(self.submaps[self.sequence[self.current]], 0, 0, True)
+ if self.overlay and self.showOverlay:
+ dc.DrawBitmap(self.overlay, self.overlayX, self.overlayY, True)
+ if self.label and self.showLabel:
+ dc.DrawText(self.label, self.labelX, self.labelY)
+ dc.SetTextForeground(wx.WHITE)
+ dc.DrawText(self.label, self.labelX-1, self.labelY-1)
+
+
+ def OnPaint(self, event):
+ self.Draw(wx.PaintDC(self))
+ event.Skip()
+
+
+ def Update(self, event):
+ self.Next()
+
+
+ def Wrap(self):
+ if self.current >= len(self.sequence):
+ if self.autoReverse:
+ self.Reverse()
+ self.current = len(self.sequence) - 1
+ else:
+ self.current = 0
+ if self.current < 0:
+ if self.autoReverse:
+ self.Reverse()
+ self.current = 0
+ else:
+ self.current = len(self.sequence) - 1
+ self.Draw(wx.ClientDC(self))
+
+
+ # --------- public methods ---------
+ def SetFont(self, font):
+ """Set the font for the label"""
+ wx.Panel.SetFont(self, font)
+ self.SetLabel(self.label)
+ self.Draw(wx.ClientDC(self))
+
+
+ def Rest(self):
+ """Stop the animation and return to frame 0"""
+ self.Stop()
+ self.current = self.rest
+ self.Draw(wx.ClientDC(self))
+
+
+ def Reverse(self):
+ """Change the direction of the animation"""
+ self.direction = -self.direction
+
+
+ def Running(self):
+ """Returns True if the animation is running"""
+ return self.running
+
+
+ def Start(self):
+ """Start the animation"""
+ if not self.running:
+ self.running = not self.running
+ self.timer.Start(int(self.frameDelay * 1000))
+
+
+ def Stop(self):
+ """Stop the animation"""
+ if self.running:
+ self.timer.Stop()
+ self.running = not self.running
+
+
+ def SetCurrent(self, current):
+ """Set current image"""
+ running = self.Running()
+ if not running:
+ #FIXME: need to make sure value is within range!!!
+ self.current = current
+ self.Draw(wx.ClientDC(self))
+
+
+ def SetRest(self, rest):
+ """Set rest image"""
+ self.rest = rest
+
+
+ def SetSequence(self, sequence = None):
+ """Order to display images"""
+
+ # self.sequence can be changed, but it's not recommended doing it
+ # while the throbber is running. self.sequence[0] should always
+ # refer to whatever frame is to be shown when 'resting' and be sure
+ # that no item in self.sequence >= self.frames or < 0!!!
+
+ running = self.Running()
+ self.Stop()
+
+ if sequence is not None:
+ #FIXME: need to make sure values are within range!!!
+ self.sequence = sequence
+ else:
+ self.sequence = range(self.frames)
+
+ if running:
+ self.Start()
+
+
+ def Increment(self):
+ """Display next image in sequence"""
+ self.current += 1
+ self.Wrap()
+
+
+ def Decrement(self):
+ """Display previous image in sequence"""
+ self.current -= 1
+ self.Wrap()
+
+
+ def Next(self):
+ """Display next image in sequence according to direction"""
+ self.current += self.direction
+ self.Wrap()
+
+
+ def Previous(self):
+ """Display previous image in sequence according to direction"""
+ self.current -= self.direction
+ self.Wrap()
+
+
+ def SetFrameDelay(self, frameDelay = 0.05):
+ """Delay between each frame"""
+ self.frameDelay = frameDelay
+ if self.running:
+ self.Stop()
+ self.Start()
+
+
+ def ToggleOverlay(self, state = None):
+ """Toggle the overlay image"""
+ if state is None:
+ self.showOverlay = not self.showOverlay
+ else:
+ self.showOverlay = state
+ self.Draw(wx.ClientDC(self))
+
+
+ def ToggleLabel(self, state = None):
+ """Toggle the label"""
+ if state is None:
+ self.showLabel = not self.showLabel
+ else:
+ self.showLabel = state
+ self.Draw(wx.ClientDC(self))
+
+
+ def SetLabel(self, label):
+ """Change the text of the label"""
+ self.label = label
+ if label:
+ extentX, extentY = self.GetTextExtent(label)
+ self.labelX = (self.width - extentX)/2
+ self.labelY = (self.height - extentY)/2
+ self.Draw(wx.ClientDC(self))
+
+
+
+# ------------------------------------------------------------------------------
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ticker.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ticker.py
new file mode 100644
index 0000000..32c73e1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ticker.py
@@ -0,0 +1,215 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.ticker
+# Purpose: A news-ticker style scrolling text control
+#
+# Author: Chris Mellon
+#
+# Created: 29-Aug-2004
+# RCS-ID: $Id$
+# Copyright: (c) 2004 by Chris Mellon
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""News-ticker style scrolling text control
+
+ * Can scroll from right to left or left to right.
+
+ * Speed of the ticking is controlled by two parameters:
+
+ - Frames per Second(FPS): How many times per second the ticker updates
+
+ - Pixels per Frame(PPF): How many pixels the text moves each update
+
+Low FPS with high PPF will result in "jumpy" text, lower PPF with higher FPS
+is smoother (but blurrier and more CPU intensive) text.
+"""
+
+import wx
+
+#----------------------------------------------------------------------
+
+class Ticker(wx.PyControl):
+ def __init__(self,
+ parent,
+ id=-1,
+ text=wx.EmptyString, #text in the ticker
+ fgcolor = wx.BLACK, #text/foreground color
+ bgcolor = wx.WHITE, #background color
+ start=True, #if True, the ticker starts immediately
+ ppf=2, #pixels per frame
+ fps=20, #frames per second
+ direction="rtl", #direction of ticking, rtl or ltr
+ pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.NO_BORDER,
+ name="Ticker"
+ ):
+ wx.PyControl.__init__(self, parent, id=id, pos=pos, size=size, style=style, name=name)
+ self.timer = wx.Timer(owner=self)
+ self._extent = (-1, -1) #cache value for the GetTextExtent call
+ self._offset = 0
+ self._fps = fps #frames per second
+ self._ppf = ppf #pixels per frame
+ self.SetDirection(direction)
+ self.SetText(text)
+ self.SetInitialSize(size)
+ self.SetForegroundColour(fgcolor)
+ self.SetBackgroundColour(bgcolor)
+ wx.EVT_TIMER(self, -1, self.OnTick)
+ wx.EVT_PAINT(self, self.OnPaint)
+ wx.EVT_ERASE_BACKGROUND(self, self.OnErase)
+ if start:
+ self.Start()
+
+
+ def Stop(self):
+ """Stop moving the text"""
+ self.timer.Stop()
+
+
+ def Start(self):
+ """Starts the text moving"""
+ if not self.timer.IsRunning():
+ self.timer.Start(1000 / self._fps)
+
+
+ def IsTicking(self):
+ """Is the ticker ticking? ie, is the text moving?"""
+ return self.timer.IsRunning()
+
+
+ def SetFPS(self, fps):
+ """Adjust the update speed of the ticker"""
+ self._fps = fps
+ self.Stop()
+ self.Start()
+
+
+ def GetFPS(self):
+ """Update speed of the ticker"""
+ return self._fps
+
+
+ def SetPPF(self, ppf):
+ """Set the number of pixels per frame the ticker moves - ie, how "jumpy" it is"""
+ self._ppf = ppf
+
+
+ def GetPPF(self):
+ """Pixels per frame"""
+ return self._ppf
+
+
+ def SetFont(self, font):
+ self._extent = (-1, -1)
+ wx.Control.SetFont(self, font)
+
+
+ def SetDirection(self, dir):
+ """Sets the direction of the ticker: right to left(rtl) or left to right (ltr)"""
+ if dir == "ltr" or dir == "rtl":
+ if self._offset <> 0:
+ #Change the offset so it's correct for the new direction
+ self._offset = self._extent[0] + self.GetSize()[0] - self._offset
+ self._dir = dir
+ else:
+ raise TypeError
+
+
+ def GetDirection(self):
+ return self._dir
+
+
+ def SetText(self, text):
+ """Set the ticker text."""
+ self._text = text
+ self._extent = (-1, -1)
+ if not self._text:
+ self.Refresh() #Refresh here to clear away the old text.
+
+
+ def GetText(self):
+ return self._text
+
+
+ def UpdateExtent(self, dc):
+ """Updates the cached text extent if needed"""
+ if not self._text:
+ self._extent = (-1, -1)
+ return
+ if self._extent == (-1, -1):
+ self._extent = dc.GetTextExtent(self.GetText())
+
+
+ def DrawText(self, dc):
+ """Draws the ticker text at the current offset using the provided DC"""
+ dc.SetTextForeground(self.GetForegroundColour())
+ dc.SetFont(self.GetFont())
+ self.UpdateExtent(dc)
+ if self._dir == "ltr":
+ offx = self._offset - self._extent[0]
+ else:
+ offx = self.GetSize()[0] - self._offset
+ offy = (self.GetSize()[1] - self._extent[1]) / 2 #centered vertically
+ dc.DrawText(self._text, offx, offy)
+
+
+ def OnTick(self, evt):
+ self._offset += self._ppf
+ w1 = self.GetSize()[0]
+ w2 = self._extent[0]
+ if self._offset >= w1+w2:
+ self._offset = 0
+ self.Refresh()
+
+
+ def OnPaint(self, evt):
+ dc = wx.BufferedPaintDC(self)
+ brush = wx.Brush(self.GetBackgroundColour())
+ dc.SetBackground(brush)
+ dc.Clear()
+ self.DrawText(dc)
+
+
+ def OnErase(self, evt):
+ """Noop because of double buffering"""
+ pass
+
+
+ def AcceptsFocus(self):
+ """Non-interactive, so don't accept focus"""
+ return False
+
+
+ def DoGetBestSize(self):
+ """Width we don't care about, height is either -1, or the character
+ height of our text with a little extra padding
+ """
+ if self._extent == (-1, -1):
+ if not self._text:
+ h = self.GetCharHeight()
+ else:
+ h = self.GetTextExtent(self.GetText())[1]
+ else:
+ h = self._extent[1]
+ return (100, h+5)
+
+
+ def ShouldInheritColours(self):
+ """Don't get colours from our parent..."""
+ return False
+
+
+
+#testcase/demo
+if __name__ == '__main__':
+ app = wx.App()
+ f = wx.Frame(None)
+ p = wx.Panel(f)
+ t = Ticker(p, text="Some sample ticker text")
+ #set ticker properties here if you want
+ s = wx.BoxSizer(wx.VERTICAL)
+ s.Add(t, flag=wx.GROW, proportion=0)
+ p.SetSizer(s)
+ f.Show()
+ app.MainLoop()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ticker_xrc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ticker_xrc.py
new file mode 100644
index 0000000..3834596
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/ticker_xrc.py
@@ -0,0 +1,49 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.ticker_xrc
+# Purpose: A XRC handler for wx.lib.ticker
+#
+# Author: Chris Mellon
+#
+# Created: 17-May-2005
+# RCS-ID: $Id$
+# Copyright: (c) 2005 by Chris Mellon
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import wx
+import wx.xrc as xrc
+from wx.lib.ticker import Ticker
+
+class wxTickerXmlHandler(xrc.XmlResourceHandler):
+ def __init__(self):
+ xrc.XmlResourceHandler.__init__(self)
+ self.AddWindowStyles()
+
+ def CanHandle(self, node):
+ return self.IsOfClass(node, "wxTicker")
+
+ def DoCreateResource(self):
+ t = Ticker(
+ self.GetParentAsWindow(),
+ self.GetID(),
+ pos = self.GetPosition(),
+ size = self.GetSize(),
+ style=self.GetStyle()
+ )
+ if self.HasParam("text"):
+ t.SetText(self.GetText("text"))
+ if self.HasParam("start"):
+ if self.GetBool("start"):
+ t.Start()
+ else:
+ t.Stop()
+ if self.HasParam("ppf"):
+ t.SetPPF(self.GetLong("ppf"))
+ if self.HasParam("fps"):
+ t.SetFPS(self.GetLong("fps"))
+ if self.HasParam("direction"):
+ t.SetDirection(self.GetText("direction"))
+
+ self.SetupWindow(t) # handles font, bg/fg color
+ return t
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/utils.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/utils.py
new file mode 100644
index 0000000..25d8380
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/utils.py
@@ -0,0 +1,79 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.utils
+# Purpose: Miscelaneous utility functions
+#
+# Author: Robin Dunn
+#
+# Created: 18-Jan-2009
+# RCS-ID: $Id$
+# Copyright: (c) 2009 Total Control Software
+# Licence: wxWidgets license
+#----------------------------------------------------------------------
+
+"""
+A few useful functions. (Ok, only one so far...)
+"""
+
+import wx
+
+#---------------------------------------------------------------------------
+
+def AdjustRectToScreen(rect, adjust=(0,0)):
+ """
+ Compare the rect with the dinmensions of the display that the rect's
+ upper left corner is positioned on. If it doesn't fit entirely on
+ screen then attempt to make it do so either by repositioning the
+ rectangle, resizing it, or both. Returns the adjusted rectangle.
+
+ If the adjustment value is given then it will be used to ensure that
+ the rectangle is at least that much smaller than the display's client
+ area.
+ """
+ assert isinstance(rect, wx.Rect)
+ if -1 in rect.Get():
+ # bail out if there are any -1's in the dimensions
+ return rect
+
+ dispidx = wx.Display.GetFromPoint(rect.Position)
+ if dispidx == wx.NOT_FOUND:
+ dispidx = 0
+ ca = wx.Display(dispidx).GetClientArea()
+ assert isinstance(ca, wx.Rect)
+
+ # is it already fully visible?
+ if ca.ContainsRect(rect):
+ return rect
+
+ # if not then try adjusting the position
+ if not ca.Contains(rect.Position):
+ rect.Position = ca.Position
+ if ca.ContainsRect(rect):
+ return rect
+ dx = dy = 0
+ if rect.right > ca.right:
+ dx = ca.right - rect.right
+ if rect.bottom > ca.bottom:
+ dy = ca.bottom - rect.bottom
+ rect.OffsetXY(dx, dy)
+
+ # if the rectangle has been moved too far, then readjust the position
+ # and also adjust the size
+ if rect.left < ca.left:
+ rect.width -= (ca.left - rect.left)
+ rect.left = ca.left
+ if rect.top < ca.top:
+ rect.height -= (ca.top - rect.top)
+ rect.top = ca.top
+
+ # make final adjustments if needed
+ adjust = wx.Size(*adjust)
+ if rect.width > (ca.width - adjust.width):
+ rect.width = ca.width - adjust.width
+ if rect.height > (ca.height - adjust.height):
+ rect.height = ca.height - adjust.height
+
+ # return the result
+ return rect
+
+
+#---------------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wordwrap.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wordwrap.py
new file mode 100644
index 0000000..d8aa81e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wordwrap.py
@@ -0,0 +1,97 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.wordwrap
+# Purpose: Contains a function to aid in word-wrapping some text
+#
+# Author: Robin Dunn
+#
+# Created: 15-Oct-2006
+# RCS-ID: $Id$
+# Copyright: (c) 2006 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+def wordwrap(text, width, dc, breakLongWords=True, margin=0):
+ """
+ Returns a copy of text with newline characters inserted where long
+ lines should be broken such that they will fit within the given
+ width, with the given margin left and right, on the given `wx.DC`
+ using its current font settings. By default words that are wider
+ than the margin-adjusted width will be broken at the nearest
+ character boundary, but this can be disabled by passing ``False``
+ for the ``breakLongWords`` parameter.
+ """
+
+ wrapped_lines = []
+ text = text.split('\n')
+ for line in text:
+ pte = dc.GetPartialTextExtents(line)
+ wid = ( width - (2*margin+1)*dc.GetTextExtent(' ')[0]
+ - max([0] + [pte[i]-pte[i-1] for i in range(1,len(pte))]) )
+ idx = 0
+ start = 0
+ startIdx = 0
+ spcIdx = -1
+ while idx < len(pte):
+ # remember the last seen space
+ if line[idx] == ' ':
+ spcIdx = idx
+
+ # have we reached the max width?
+ if pte[idx] - start > wid and (spcIdx != -1 or breakLongWords):
+ if spcIdx != -1:
+ idx = min(spcIdx + 1, len(pte) - 1)
+ wrapped_lines.append(' '*margin + line[startIdx : idx] + ' '*margin)
+ start = pte[idx]
+ startIdx = idx
+ spcIdx = -1
+
+ idx += 1
+
+ wrapped_lines.append(' '*margin + line[startIdx : idx] + ' '*margin)
+
+ return '\n'.join(wrapped_lines)
+
+
+
+if __name__ == '__main__':
+ import wx
+ class TestPanel(wx.Panel):
+ def __init__(self, parent):
+ wx.Panel.__init__(self, parent)
+
+ self.tc = wx.TextCtrl(self, -1, "", (20,20), (150,150), wx.TE_MULTILINE)
+ self.Bind(wx.EVT_TEXT, self.OnDoUpdate, self.tc)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+
+ def OnSize(self, evt):
+ wx.CallAfter(self.OnDoUpdate, None)
+
+
+ def OnDoUpdate(self, evt):
+ WIDTH = self.GetSize().width - 220
+ HEIGHT = 200
+ bmp = wx.EmptyBitmap(WIDTH, HEIGHT)
+ mdc = wx.MemoryDC(bmp)
+ mdc.SetBackground(wx.Brush("white"))
+ mdc.Clear()
+ mdc.SetPen(wx.Pen("black"))
+ mdc.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
+ mdc.DrawRectangle(0,0, WIDTH, HEIGHT)
+
+ text = wordwrap(self.tc.GetValue(), WIDTH-2, mdc, False)
+ #print repr(text)
+ mdc.DrawLabel(text, (1,1, WIDTH-2, HEIGHT-2))
+
+ del mdc
+ dc = wx.ClientDC(self)
+ dc.DrawBitmap(bmp, 200, 20)
+
+
+ app = wx.App(False)
+ frm = wx.Frame(None, title="Test wordWrap")
+ pnl = TestPanel(frm)
+ frm.Show()
+ app.MainLoop()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxPlotCanvas.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxPlotCanvas.py
new file mode 100644
index 0000000..8b96c6e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxPlotCanvas.py
@@ -0,0 +1,489 @@
+"""
+This is a port of Konrad Hinsen's tkPlotCanvas.py plotting module.
+After thinking long and hard I came up with the name "wxPlotCanvas.py".
+
+This file contains two parts; first the re-usable library stuff, then, after
+a "if __name__=='__main__'" test, a simple frame and a few default plots
+for testing.
+
+Harm van der Heijden, feb 1999
+
+Original comment follows below:
+# This module defines a plot widget for Tk user interfaces.
+# It supports only elementary line plots at the moment.
+# See the example at the end for documentation...
+#
+# Written by Konrad Hinsen <hinsen@cnrs-orleans.fr>
+# With contributions from RajGopal Srinivasan <raj@cherubino.med.jhmi.edu>
+# Last revision: 1998-7-28
+#
+"""
+# 12/13/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for V2.5 compatability
+# o wx.SpinCtl has some issues that cause the control to
+# lock up. Noted in other places using it too, it's not this module
+# that's at fault.
+# o Added deprecation warning.
+#
+
+import warnings
+import wx
+
+warningmsg = r"""\
+
+THIS MODULE IS NOW DEPRECATED
+
+This module has been replaced by wxPyPlot, which in wxPython
+can be found in wx.lib.plot.py.
+
+"""
+
+warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
+
+# Not everybody will have Numeric, so let's be cool about it...
+try:
+ import Numeric
+except:
+ # bummer!
+ msg = """This module requires the Numeric module, which could not be
+imported. It probably is not installed (it's not part of the standard
+Python distribution). See the Python site (http://www.python.org) for
+information on downloading source or binaries."""
+
+ print msg
+ if wx.Platform == '__WXMSW__' and wx.GetApp() is not None:
+ d = wx.MessageDialog(None, msg, "Numeric not found")
+ if d.ShowModal() == wx.ID_CANCEL:
+ d = wx.MessageDialog(None, "I kid you not! Pressing Cancel won't help you!", "Not a joke", wx.OK)
+ d.ShowModal()
+ raise
+
+#
+# Plotting classes...
+#
+class PolyPoints:
+
+ def __init__(self, points, attr):
+ self.points = Numeric.array(points)
+ self.scaled = self.points
+ self.attributes = {}
+ for name, value in self._attributes.items():
+ try:
+ value = attr[name]
+ except KeyError: pass
+ self.attributes[name] = value
+
+ def boundingBox(self):
+ return Numeric.minimum.reduce(self.points), \
+ Numeric.maximum.reduce(self.points)
+
+ def scaleAndShift(self, scale=1, shift=0):
+ self.scaled = scale*self.points+shift
+
+
+class PolyLine(PolyPoints):
+
+ def __init__(self, points, **attr):
+ PolyPoints.__init__(self, points, attr)
+
+ _attributes = {'color': 'black',
+ 'width': 1}
+
+ def draw(self, dc):
+ color = self.attributes['color']
+ width = self.attributes['width']
+ arguments = []
+ dc.SetPen(wx.Pen(wx.NamedColour(color), width))
+ dc.DrawLines(map(tuple,self.scaled))
+
+
+class PolyMarker(PolyPoints):
+
+ def __init__(self, points, **attr):
+
+ PolyPoints.__init__(self, points, attr)
+
+ _attributes = {'color': 'black',
+ 'width': 1,
+ 'fillcolor': None,
+ 'size': 2,
+ 'fillstyle': wx.SOLID,
+ 'outline': 'black',
+ 'marker': 'circle'}
+
+ def draw(self, dc):
+ color = self.attributes['color']
+ width = self.attributes['width']
+ size = self.attributes['size']
+ fillcolor = self.attributes['fillcolor']
+ fillstyle = self.attributes['fillstyle']
+ marker = self.attributes['marker']
+
+ dc.SetPen(wx.Pen(wx.NamedColour(color),width))
+ if fillcolor:
+ dc.SetBrush(wx.Brush(wx.NamedColour(fillcolor),fillstyle))
+ else:
+ dc.SetBrush(wx.Brush(wx.NamedColour('black'), wx.TRANSPARENT))
+
+ self._drawmarkers(dc, self.scaled, marker, size)
+
+ def _drawmarkers(self, dc, coords, marker,size=1):
+ f = eval('self._' +marker)
+ for xc, yc in coords:
+ f(dc, xc, yc, size)
+
+ def _circle(self, dc, xc, yc, size=1):
+ dc.DrawEllipse(xc-2.5*size,yc-2.5*size, 5.*size,5.*size)
+
+ def _dot(self, dc, xc, yc, size=1):
+ dc.DrawPoint(xc,yc)
+
+ def _square(self, dc, xc, yc, size=1):
+ dc.DrawRectangle(xc-2.5*size,yc-2.5*size,5.*size,5.*size)
+
+ def _triangle(self, dc, xc, yc, size=1):
+ dc.DrawPolygon([(-0.5*size*5,0.2886751*size*5),
+ (0.5*size*5,0.2886751*size*5),
+ (0.0,-0.577350*size*5)],xc,yc)
+
+ def _triangle_down(self, dc, xc, yc, size=1):
+ dc.DrawPolygon([(-0.5*size*5,-0.2886751*size*5),
+ (0.5*size*5,-0.2886751*size*5),
+ (0.0,0.577350*size*5)],xc,yc)
+
+ def _cross(self, dc, xc, yc, size=1):
+ dc.DrawLine(xc-2.5*size, yc-2.5*size, xc+2.5*size,yc+2.5*size)
+ dc.DrawLine(xc-2.5*size,yc+2.5*size, xc+2.5*size,yc-2.5*size)
+
+ def _plus(self, dc, xc, yc, size=1):
+ dc.DrawLine(xc-2.5*size,yc, xc+2.5*size,yc)
+ dc.DrawLine(xc,yc-2.5*size,xc, yc+2.5*size)
+
+class PlotGraphics:
+
+ def __init__(self, objects):
+ self.objects = objects
+
+ def boundingBox(self):
+ p1, p2 = self.objects[0].boundingBox()
+ for o in self.objects[1:]:
+ p1o, p2o = o.boundingBox()
+ p1 = Numeric.minimum(p1, p1o)
+ p2 = Numeric.maximum(p2, p2o)
+ return p1, p2
+
+ def scaleAndShift(self, scale=1, shift=0):
+ for o in self.objects:
+ o.scaleAndShift(scale, shift)
+
+ def draw(self, canvas):
+ for o in self.objects:
+ o.draw(canvas)
+
+ def __len__(self):
+ return len(self.objects)
+
+ def __getitem__(self, item):
+ return self.objects[item]
+
+
+class PlotCanvas(wx.Window):
+
+ def __init__(self, parent, id=-1,
+ pos = wx.DefaultPosition, size = wx.DefaultSize,
+ style = 0, name = 'plotCanvas'):
+ wx.Window.__init__(self, parent, id, pos, size, style, name)
+ self.border = (1,1)
+ self.SetClientSize((400,400))
+ self.SetBackgroundColour("white")
+
+ self.Bind(wx.EVT_SIZE,self.reconfigure)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self._setsize()
+ self.last_draw = None
+# self.font = self._testFont(font)
+
+ def OnPaint(self, event):
+ pdc = wx.PaintDC(self)
+ if self.last_draw is not None:
+ apply(self.draw, self.last_draw + (pdc,))
+
+ def reconfigure(self, event):
+ (new_width,new_height) = self.GetClientSize()
+ if new_width == self.width and new_height == self.height:
+ return
+ self._setsize()
+ # self.redraw()
+
+ def _testFont(self, font):
+ if font is not None:
+ bg = self.canvas.cget('background')
+ try:
+ item = CanvasText(self.canvas, 0, 0, anchor=NW,
+ text='0', fill=bg, font=font)
+ self.canvas.delete(item)
+ except TclError:
+ font = None
+ return font
+
+ def _setsize(self):
+ (self.width,self.height) = self.GetClientSize();
+ self.plotbox_size = 0.97*Numeric.array([self.width, -self.height])
+ xo = 0.5*(self.width-self.plotbox_size[0])
+ yo = self.height-0.5*(self.height+self.plotbox_size[1])
+ self.plotbox_origin = Numeric.array([xo, yo])
+
+ def draw(self, graphics, xaxis = None, yaxis = None, dc = None):
+ if dc == None: dc = wx.ClientDC(self)
+ dc.BeginDrawing()
+ dc.Clear()
+ self.last_draw = (graphics, xaxis, yaxis)
+ p1, p2 = graphics.boundingBox()
+ xaxis = self._axisInterval(xaxis, p1[0], p2[0])
+ yaxis = self._axisInterval(yaxis, p1[1], p2[1])
+ text_width = [0., 0.]
+ text_height = [0., 0.]
+ if xaxis is not None:
+ p1[0] = xaxis[0]
+ p2[0] = xaxis[1]
+ xticks = self._ticks(xaxis[0], xaxis[1])
+ bb = dc.GetTextExtent(xticks[0][1])
+ text_height[1] = bb[1]
+ text_width[0] = 0.5*bb[0]
+ bb = dc.GetTextExtent(xticks[-1][1])
+ text_width[1] = 0.5*bb[0]
+ else:
+ xticks = None
+ if yaxis is not None:
+ p1[1] = yaxis[0]
+ p2[1] = yaxis[1]
+ yticks = self._ticks(yaxis[0], yaxis[1])
+ for y in yticks:
+ bb = dc.GetTextExtent(y[1])
+ text_width[0] = max(text_width[0],bb[0])
+ h = 0.5*bb[1]
+ text_height[0] = h
+ text_height[1] = max(text_height[1], h)
+ else:
+ yticks = None
+ text1 = Numeric.array([text_width[0], -text_height[1]])
+ text2 = Numeric.array([text_width[1], -text_height[0]])
+ scale = (self.plotbox_size-text1-text2) / (p2-p1)
+ shift = -p1*scale + self.plotbox_origin + text1
+ self._drawAxes(dc, xaxis, yaxis, p1, p2,
+ scale, shift, xticks, yticks)
+ graphics.scaleAndShift(scale, shift)
+ graphics.draw(dc)
+ dc.EndDrawing()
+
+ def _axisInterval(self, spec, lower, upper):
+ if spec is None:
+ return None
+ if spec == 'minimal':
+ if lower == upper:
+ return lower-0.5, upper+0.5
+ else:
+ return lower, upper
+ if spec == 'automatic':
+ range = upper-lower
+ if range == 0.:
+ return lower-0.5, upper+0.5
+ log = Numeric.log10(range)
+ power = Numeric.floor(log)
+ fraction = log-power
+ if fraction <= 0.05:
+ power = power-1
+ grid = 10.**power
+ lower = lower - lower % grid
+ mod = upper % grid
+ if mod != 0:
+ upper = upper - mod + grid
+ return lower, upper
+ if type(spec) == type(()):
+ lower, upper = spec
+ if lower <= upper:
+ return lower, upper
+ else:
+ return upper, lower
+ raise ValueError, str(spec) + ': illegal axis specification'
+
+ def _drawAxes(self, dc, xaxis, yaxis,
+ bb1, bb2, scale, shift, xticks, yticks):
+ dc.SetPen(wx.Pen(wx.NamedColour('BLACK'),1))
+ if xaxis is not None:
+ lower, upper = xaxis
+ text = 1
+ for y, d in [(bb1[1], -3), (bb2[1], 3)]:
+ p1 = scale*Numeric.array([lower, y])+shift
+ p2 = scale*Numeric.array([upper, y])+shift
+ dc.DrawLine(p1[0],p1[1], p2[0],p2[1])
+ for x, label in xticks:
+ p = scale*Numeric.array([x, y])+shift
+ dc.DrawLine(p[0],p[1], p[0],p[1]+d)
+ if text:
+ dc.DrawText(label, p[0],p[1])
+ text = 0
+
+ if yaxis is not None:
+ lower, upper = yaxis
+ text = 1
+ h = dc.GetCharHeight()
+ for x, d in [(bb1[0], -3), (bb2[0], 3)]:
+ p1 = scale*Numeric.array([x, lower])+shift
+ p2 = scale*Numeric.array([x, upper])+shift
+ dc.DrawLine(p1[0],p1[1], p2[0],p2[1])
+ for y, label in yticks:
+ p = scale*Numeric.array([x, y])+shift
+ dc.DrawLine(p[0],p[1], p[0]-d,p[1])
+ if text:
+ dc.DrawText(label,
+ p[0]-dc.GetTextExtent(label)[0], p[1]-0.5*h)
+ text = 0
+
+ def _ticks(self, lower, upper):
+ ideal = (upper-lower)/7.
+ log = Numeric.log10(ideal)
+ power = Numeric.floor(log)
+ fraction = log-power
+ factor = 1.
+ error = fraction
+ for f, lf in self._multiples:
+ e = Numeric.fabs(fraction-lf)
+ if e < error:
+ error = e
+ factor = f
+ grid = factor * 10.**power
+ if power > 3 or power < -3:
+ format = '%+7.0e'
+ elif power >= 0:
+ digits = max(1, int(power))
+ format = '%' + `digits`+'.0f'
+ else:
+ digits = -int(power)
+ format = '%'+`digits+2`+'.'+`digits`+'f'
+ ticks = []
+ t = -grid*Numeric.floor(-lower/grid)
+ while t <= upper:
+ ticks.append( (t, format % (t,)) )
+ t = t + grid
+ return ticks
+
+ _multiples = [(2., Numeric.log10(2.)), (5., Numeric.log10(5.))]
+
+ def redraw(self,dc=None):
+ if self.last_draw is not None:
+ apply(self.draw, self.last_draw + (dc,))
+
+ def clear(self):
+ self.canvas.delete('all')
+
+#---------------------------------------------------------------------------
+# if running standalone...
+#
+# ...a sample implementation using the above
+#
+
+
+if __name__ == '__main__':
+ def _InitObjects():
+ # 100 points sin function, plotted as green circles
+ data1 = 2.*Numeric.pi*Numeric.arange(200)/200.
+ data1.shape = (100, 2)
+ data1[:,1] = Numeric.sin(data1[:,0])
+ markers1 = PolyMarker(data1, color='green', marker='circle',size=1)
+
+ # 50 points cos function, plotted as red line
+ data1 = 2.*Numeric.pi*Numeric.arange(100)/100.
+ data1.shape = (50,2)
+ data1[:,1] = Numeric.cos(data1[:,0])
+ lines = PolyLine(data1, color='red')
+
+ # A few more points...
+ pi = Numeric.pi
+ markers2 = PolyMarker([(0., 0.), (pi/4., 1.), (pi/2, 0.),
+ (3.*pi/4., -1)], color='blue',
+ fillcolor='green', marker='cross')
+
+ return PlotGraphics([markers1, lines, markers2])
+
+
+ class AppFrame(wx.Frame):
+ def __init__(self, parent, id, title):
+ wx.Frame.__init__(self, parent, id, title,
+ wx.DefaultPosition, (400, 400))
+
+ # Now Create the menu bar and items
+ self.mainmenu = wx.MenuBar()
+
+ menu = wx.Menu()
+ menu.Append(200, '&Print...', 'Print the current plot')
+ self.Bind(wx.EVT_MENU, self.OnFilePrint, id=200)
+ menu.Append(209, 'E&xit', 'Enough of this already!')
+ self.Bind(wx.EVT_MENU, self.OnFileExit, id=209)
+ self.mainmenu.Append(menu, '&File')
+
+ menu = wx.Menu()
+ menu.Append(210, '&Draw', 'Draw plots')
+ self.Bind(wx.EVT_MENU,self.OnPlotDraw, id=210)
+ menu.Append(211, '&Redraw', 'Redraw plots')
+ self.Bind(wx.EVT_MENU,self.OnPlotRedraw, id=211)
+ menu.Append(212, '&Clear', 'Clear canvas')
+ self.Bind(wx.EVT_MENU,self.OnPlotClear, id=212)
+ self.mainmenu.Append(menu, '&Plot')
+
+ menu = wx.Menu()
+ menu.Append(220, '&About', 'About this thing...')
+ self.Bind(wx.EVT_MENU, self.OnHelpAbout, id=220)
+ self.mainmenu.Append(menu, '&Help')
+
+ self.SetMenuBar(self.mainmenu)
+
+ # A status bar to tell people what's happening
+ self.CreateStatusBar(1)
+
+ self.client = PlotCanvas(self)
+
+ def OnFilePrint(self, event):
+ d = wx.MessageDialog(self,
+"""As of this writing, printing support in wxPython is shaky at best.
+Are you sure you want to do this?""", "Danger!", wx.YES_NO)
+ if d.ShowModal() == wx.ID_YES:
+ psdc = wx.PostScriptDC("out.ps", True, self)
+ self.client.redraw(psdc)
+
+ def OnFileExit(self, event):
+ self.Close()
+
+ def OnPlotDraw(self, event):
+ self.client.draw(_InitObjects(),'automatic','automatic');
+
+ def OnPlotRedraw(self,event):
+ self.client.redraw()
+
+ def OnPlotClear(self,event):
+ self.client.last_draw = None
+ dc = wx.ClientDC(self.client)
+ dc.Clear()
+
+ def OnHelpAbout(self, event):
+ about = wx.MessageDialog(self, __doc__, "About...", wx.OK)
+ about.ShowModal()
+
+
+
+ class MyApp(wx.App):
+ def OnInit(self):
+ frame = AppFrame(None, -1, "wxPlotCanvas")
+ frame.Show(True)
+ self.SetTopWindow(frame)
+ return True
+
+
+ app = MyApp(0)
+ app.MainLoop()
+
+
+
+
+#----------------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxcairo.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxcairo.py
new file mode 100644
index 0000000..adaeafb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxcairo.py
@@ -0,0 +1,487 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.wxcairo
+# Purpose: Glue code to allow the pycairo package to be used
+# with a wx.DC as the cairo surface.
+#
+# Author: Robin Dunn
+#
+# Created: 3-Sept-2008
+# RCS-ID: $Id$
+# Copyright: (c) 2008 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""
+This module provides some glue code that allows the pycairo package to
+be used for drawing direclty on wx.DCs. In cairo terms, the DC is the
+drawing surface. The `CairoContextFromDC` function in this module
+will return an instance of the pycairo Context class that is ready for
+drawing, using the native cairo surface type for the current platform.
+
+This module requires the pycairo pacakge, and makes use of ctypes for
+fetching the pycairo C API and also for digging into the cairo library
+itself.
+
+To use Cairo with wxPython you will need to have a few dependencies
+installed. On Linux and other unix-like systems you may already have
+them, or can easily get them with your system's package manager. Just
+check if libcairo and pycairo are installed.
+
+On Mac you can get Cairo from MacPorts or Fink. If you are also using
+MacPorts or Fink for your Python installation then you should be able
+to get pycairo the same way. Otherwise it's real easy to build and
+install pycairo for the Python framework installation. Just get the
+source tarball from http://pypi.python.org/pypi/pycairo and do the
+normal 'python setup.py install' dance.
+
+On Windows you can get a Cairo DLL from here:
+
+ http://www.gtk.org/download/win32.php
+
+You'll also want to get the zlib and libpng binaries from the same
+page. Once you get those files extract the DLLs from each of the zip
+files and copy them to some place on your PATH. Finally, there is an
+installer for the pycairo pacakge here:
+
+ http://wxpython.org/cairo/
+
+"""
+
+# TODO: Support printer surfaces?
+
+
+import wx
+import cairo
+import ctypes
+import ctypes.util
+
+
+#----------------------------------------------------------------------------
+
+# A reference to the cairo shared lib via ctypes.CDLL
+cairoLib = None
+
+# A reference to the pycairo C API structure
+pycairoAPI = None
+
+
+# a convenience funtion, just to save a bit of typing below
+def voidp(ptr):
+ """Convert a SWIGged void* type to a ctypes c_void_p"""
+ return ctypes.c_void_p(long(ptr))
+
+#----------------------------------------------------------------------------
+
+def ContextFromDC(dc):
+ """
+ Creates and returns a Cairo context object using the wxDC as the
+ surface. (Only window, client, paint and memory DC's are allowed
+ at this time.)
+ """
+ if not isinstance(dc, wx.WindowDC) and not isinstance(dc, wx.MemoryDC):
+ raise TypeError, "Only window and memory DC's are supported at this time."
+
+ if 'wxMac' in wx.PlatformInfo:
+ width, height = dc.GetSize()
+
+ # use the CGContextRef of the DC to make the cairo surface
+ cgc = dc.GetHandle()
+ assert cgc is not None, "Unable to get CGContext from DC."
+ cgref = voidp( cgc )
+ surface_create = cairoLib.cairo_quartz_surface_create_for_cg_context
+ surface_create.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
+ surface_create.restype = ctypes.c_void_p
+ surfaceptr = voidp(surface_create(cgref, width, height))
+
+ # create a cairo context for that surface
+ cairo_create = cairoLib.cairo_create
+ cairo_create.argtypes = [ctypes.c_void_p]
+ cairo_create.restype = ctypes.c_void_p
+ ctxptr = voidp(cairo_create(surfaceptr))
+
+ # Turn it into a pycairo context object
+ ctx = pycairoAPI.Context_FromContext(ctxptr, pycairoAPI.Context_Type, None)
+
+ # The context keeps its own reference to the surface
+ cairoLib.cairo_surface_destroy(surfaceptr)
+
+
+ elif 'wxMSW' in wx.PlatformInfo:
+ # This one is easy, just fetch the HDC and use PyCairo to make
+ # the surface and context.
+ hdc = dc.GetHandle()
+ # Ensure the pointer value is clampped into the range of a C signed long
+ hdc = ctypes.c_long(hdc)
+ surface = cairo.Win32Surface(hdc.value)
+ ctx = cairo.Context(surface)
+
+
+ elif 'wxGTK' in wx.PlatformInfo:
+ if 'gtk3' in wx.PlatformInfo:
+ # With wxGTK3, GetHandle() returns a cairo context directly
+ ctxptr = voidp( dc.GetHandle() )
+
+ # pyCairo will try to destroy it so we need to increase ref count
+ cairoLib.cairo_reference(ctxptr)
+ else:
+ gdkLib = _findGDKLib()
+
+ # Get the GdkDrawable from the dc
+ drawable = voidp( dc.GetHandle() )
+
+ # Call a GDK API to create a cairo context
+ gdkLib.gdk_cairo_create.restype = ctypes.c_void_p
+ ctxptr = gdkLib.gdk_cairo_create(drawable)
+
+ # Turn it into a pycairo context object
+ ctx = pycairoAPI.Context_FromContext(ctxptr, pycairoAPI.Context_Type, None)
+
+ else:
+ raise NotImplementedError, "Help me, I'm lost..."
+
+ return ctx
+
+
+#----------------------------------------------------------------------------
+
+def FontFaceFromFont(font):
+ """
+ Creates and returns a cairo.FontFace object from the native
+ information in a wx.Font.
+ """
+
+ if 'wxMac' in wx.PlatformInfo:
+ font_face_create = cairoLib.cairo_quartz_font_face_create_for_cgfont
+ font_face_create.argtypes = [ctypes.c_void_p]
+ font_face_create.restype = ctypes.c_void_p
+
+ fontfaceptr = font_face_create(voidp(font.OSXGetCGFont()))
+ fontface = pycairoAPI.FontFace_FromFontFace(fontfaceptr)
+
+
+ elif 'wxMSW' in wx.PlatformInfo:
+ cairoLib.cairo_win32_font_face_create_for_hfont.restype = ctypes.c_void_p
+ fontfaceptr = voidp( cairoLib.cairo_win32_font_face_create_for_hfont(
+ ctypes.c_ulong(font.GetHFONT())) )
+ fontface = pycairoAPI.FontFace_FromFontFace(fontfaceptr)
+
+
+ elif 'wxGTK' in wx.PlatformInfo:
+ gdkLib = _findGDKLib()
+ pcLib = _findPangoCairoLib()
+
+ # wow, this is a hell of a lot of steps...
+ desc = voidp( font.GetPangoFontDescription() )
+
+ pcLib.pango_cairo_font_map_get_default.restype = ctypes.c_void_p
+ pcfm = voidp(pcLib.pango_cairo_font_map_get_default())
+
+ gdkLib.gdk_pango_context_get.restype = ctypes.c_void_p
+ pctx = voidp(gdkLib.gdk_pango_context_get())
+
+ pcLib.pango_font_map_load_font.restype = ctypes.c_void_p
+ pfnt = voidp( pcLib.pango_font_map_load_font(pcfm, pctx, desc) )
+
+ pcLib.pango_cairo_font_get_scaled_font.restype = ctypes.c_void_p
+ scaledfontptr = voidp( pcLib.pango_cairo_font_get_scaled_font(pfnt) )
+
+ cairoLib.cairo_scaled_font_get_font_face.restype = ctypes.c_void_p
+ fontfaceptr = voidp(cairoLib.cairo_scaled_font_get_font_face(scaledfontptr))
+ cairoLib.cairo_font_face_reference(fontfaceptr)
+
+ fontface = pycairoAPI.FontFace_FromFontFace(fontfaceptr)
+
+ gdkLib.g_object_unref(pctx)
+
+ else:
+ raise NotImplementedError, "Help me, I'm lost..."
+
+ return fontface
+
+
+#----------------------------------------------------------------------------
+# wxBitmap <--> ImageSurface
+
+def BitmapFromImageSurface(surface):
+ """
+ Create a wx.Bitmap from a Cairo ImageSurface.
+ """
+ format = surface.get_format()
+ if format not in [cairo.FORMAT_ARGB32, cairo.FORMAT_RGB24]:
+ raise TypeError("Unsupported format")
+
+ width = surface.get_width()
+ height = surface.get_height()
+ stride = surface.get_stride()
+ data = surface.get_data()
+ if format == cairo.FORMAT_ARGB32:
+ fmt = wx.BitmapBufferFormat_ARGB32
+ else:
+ fmt = wx.BitmapBufferFormat_RGB32
+
+ bmp = wx.EmptyBitmap(width, height, 32)
+ bmp.CopyFromBuffer(data, fmt, stride)
+ return bmp
+
+
+def ImageSurfaceFromBitmap(bitmap):
+ """
+ Create an ImageSurface from a wx.Bitmap
+ """
+ width, height = bitmap.GetSize()
+ if bitmap.HasAlpha():
+ format = cairo.FORMAT_ARGB32
+ fmt = wx.BitmapBufferFormat_ARGB32
+ else:
+ format = cairo.FORMAT_RGB24
+ fmt = wx.BitmapBufferFormat_RGB32
+
+ try:
+ stride = cairo.ImageSurface.format_stride_for_width(format, width)
+ except AttributeError:
+ stride = width * 4
+
+ surface = cairo.ImageSurface(format, width, height)
+ bitmap.CopyToBuffer(surface.get_data(), fmt, stride)
+ surface.mark_dirty()
+ return surface
+
+
+#----------------------------------------------------------------------------
+# Only implementation helpers after this point
+#----------------------------------------------------------------------------
+
+def _findCairoLib():
+ """
+ Try to locate the Cairo shared library and make a CDLL for it.
+ """
+ global cairoLib
+ if cairoLib is not None:
+ return
+
+ names = ['cairo', 'cairo-2', 'libcairo', 'libcairo-2']
+
+ # first look using just the base name
+ for name in names:
+ try:
+ cairoLib = ctypes.CDLL(name)
+ return
+ except:
+ pass
+
+ # if that didn't work then use the ctypes util to search the paths
+ # appropriate for the system
+ for name in names:
+ location = ctypes.util.find_library(name)
+ if location:
+ try:
+ cairoLib = ctypes.CDLL(location)
+ return
+ except:
+ pass
+
+ # If the above didn't find it on OS X then we still have a
+ # trick up our sleeve...
+ if 'wxMac' in wx.PlatformInfo:
+ # look at the libs linked to by the pycairo extension module
+ import macholib.MachO
+ m = macholib.MachO.MachO(cairo._cairo.__file__)
+ for h in m.headers:
+ for idx, name, path in h.walkRelocatables():
+ if 'libcairo' in path:
+ try:
+ cairoLib = ctypes.CDLL(path)
+ return
+ except:
+ pass
+
+ if not cairoLib:
+ raise RuntimeError, "Unable to find the Cairo shared library"
+
+
+
+#----------------------------------------------------------------------------
+
+# For other DLLs we'll just use a dictionary to track them, as there
+# probably isn't any need to use them outside of this module.
+_dlls = dict()
+
+def _findHelper(names, key, msg):
+ dll = _dlls.get(key, None)
+ if dll is not None:
+ return dll
+ location = None
+ for name in names:
+ location = ctypes.util.find_library(name)
+ if location:
+ break
+ if not location:
+ raise RuntimeError, msg
+ dll = ctypes.CDLL(location)
+ _dlls[key] = dll
+ return dll
+
+
+def _findGDKLib():
+ if 'gtk3' in wx.PlatformInfo:
+ libname = 'gdk-3'
+ else:
+ libname = 'gdk-x11-2.0'
+ return _findHelper([libname], 'gdk',
+ "Unable to find the GDK shared library")
+
+def _findPangoCairoLib():
+ return _findHelper(['pangocairo-1.0'], 'pangocairo',
+ "Unable to find the pangocairo shared library")
+def _findAppSvcLib():
+ return _findHelper(['ApplicationServices'], 'appsvc',
+ "Unable to find the ApplicationServices Framework")
+
+
+#----------------------------------------------------------------------------
+
+# Pycairo exports a C API in a structure via a PyCObject. Using
+# ctypes will let us use that API from Python too. We'll use it to
+# convert a C pointer value to pycairo objects. The information about
+# this API structure is gleaned from pycairo.h.
+
+class Pycairo_CAPI(ctypes.Structure):
+ if cairo.version_info < (1,8): # This structure is known good with pycairo 1.6.4
+ _fields_ = [
+ ('Context_Type', ctypes.py_object),
+ ('Context_FromContext', ctypes.PYFUNCTYPE(ctypes.py_object,
+ ctypes.c_void_p,
+ ctypes.py_object,
+ ctypes.py_object)),
+ ('FontFace_Type', ctypes.py_object),
+ ('FontFace_FromFontFace', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('FontOptions_Type', ctypes.py_object),
+ ('FontOptions_FromFontOptions', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Matrix_Type', ctypes.py_object),
+ ('Matrix_FromMatrix', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Path_Type', ctypes.py_object),
+ ('Path_FromPath', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Pattern_Type', ctypes.py_object),
+ ('SolidPattern_Type', ctypes.py_object),
+ ('SurfacePattern_Type', ctypes.py_object),
+ ('Gradient_Type', ctypes.py_object),
+ ('LinearGradient_Type', ctypes.py_object),
+ ('RadialGradient_Type', ctypes.py_object),
+ ('Pattern_FromPattern', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('ScaledFont_Type', ctypes.py_object),
+ ('ScaledFont_FromScaledFont', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Surface_Type', ctypes.py_object),
+ ('ImageSurface_Type', ctypes.py_object),
+ ('PDFSurface_Type', ctypes.py_object),
+ ('PSSurface_Type', ctypes.py_object),
+ ('SVGSurface_Type', ctypes.py_object),
+ ('Win32Surface_Type', ctypes.py_object),
+ ('XlibSurface_Type', ctypes.py_object),
+ ('Surface_FromSurface', ctypes.PYFUNCTYPE(ctypes.py_object,
+ ctypes.c_void_p,
+ ctypes.py_object)),
+ ('Check_Status', ctypes.PYFUNCTYPE(ctypes.c_int, ctypes.c_int))]
+
+ # This structure is known good with pycairo 1.8.4.
+ # We have to also test for (1,10,8) because pycairo 1.8.10 has an
+ # incorrect version_info value
+ elif cairo.version_info < (1,9) or cairo.version_info == (1,10,8):
+ _fields_ = [
+ ('Context_Type', ctypes.py_object),
+ ('Context_FromContext', ctypes.PYFUNCTYPE(ctypes.py_object,
+ ctypes.c_void_p,
+ ctypes.py_object,
+ ctypes.py_object)),
+ ('FontFace_Type', ctypes.py_object),
+ ('ToyFontFace_Type', ctypes.py_object), #** new in 1.8.4
+ ('FontFace_FromFontFace', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('FontOptions_Type', ctypes.py_object),
+ ('FontOptions_FromFontOptions', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Matrix_Type', ctypes.py_object),
+ ('Matrix_FromMatrix', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Path_Type', ctypes.py_object),
+ ('Path_FromPath', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Pattern_Type', ctypes.py_object),
+ ('SolidPattern_Type', ctypes.py_object),
+ ('SurfacePattern_Type', ctypes.py_object),
+ ('Gradient_Type', ctypes.py_object),
+ ('LinearGradient_Type', ctypes.py_object),
+ ('RadialGradient_Type', ctypes.py_object),
+ ('Pattern_FromPattern', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p,
+ ctypes.py_object)), #** changed in 1.8.4
+ ('ScaledFont_Type', ctypes.py_object),
+ ('ScaledFont_FromScaledFont', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Surface_Type', ctypes.py_object),
+ ('ImageSurface_Type', ctypes.py_object),
+ ('PDFSurface_Type', ctypes.py_object),
+ ('PSSurface_Type', ctypes.py_object),
+ ('SVGSurface_Type', ctypes.py_object),
+ ('Win32Surface_Type', ctypes.py_object),
+ ('XlibSurface_Type', ctypes.py_object),
+ ('Surface_FromSurface', ctypes.PYFUNCTYPE(ctypes.py_object,
+ ctypes.c_void_p,
+ ctypes.py_object)),
+ ('Check_Status', ctypes.PYFUNCTYPE(ctypes.c_int, ctypes.c_int))]
+
+ # This structure is known good with pycairo 1.10.0. They keep adding stuff
+ # to the middle of the structure instead of only adding to the end!
+ elif cairo.version_info < (1,11):
+ _fields_ = [
+ ('Context_Type', ctypes.py_object),
+ ('Context_FromContext', ctypes.PYFUNCTYPE(ctypes.py_object,
+ ctypes.c_void_p,
+ ctypes.py_object,
+ ctypes.py_object)),
+ ('FontFace_Type', ctypes.py_object),
+ ('ToyFontFace_Type', ctypes.py_object),
+ ('FontFace_FromFontFace', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('FontOptions_Type', ctypes.py_object),
+ ('FontOptions_FromFontOptions', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Matrix_Type', ctypes.py_object),
+ ('Matrix_FromMatrix', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Path_Type', ctypes.py_object),
+ ('Path_FromPath', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Pattern_Type', ctypes.py_object),
+ ('SolidPattern_Type', ctypes.py_object),
+ ('SurfacePattern_Type', ctypes.py_object),
+ ('Gradient_Type', ctypes.py_object),
+ ('LinearGradient_Type', ctypes.py_object),
+ ('RadialGradient_Type', ctypes.py_object),
+ ('Pattern_FromPattern', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p,
+ ctypes.py_object)), #** changed in 1.8.4
+ ('ScaledFont_Type', ctypes.py_object),
+ ('ScaledFont_FromScaledFont', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+ ('Surface_Type', ctypes.py_object),
+ ('ImageSurface_Type', ctypes.py_object),
+ ('PDFSurface_Type', ctypes.py_object),
+ ('PSSurface_Type', ctypes.py_object),
+ ('SVGSurface_Type', ctypes.py_object),
+ ('Win32Surface_Type', ctypes.py_object),
+ ('Win32PrintingSurface_Type', ctypes.py_object), #** new
+ ('XCBSurface_Type', ctypes.py_object), #** new
+ ('XlibSurface_Type', ctypes.py_object),
+ ('Surface_FromSurface', ctypes.PYFUNCTYPE(ctypes.py_object,
+ ctypes.c_void_p,
+ ctypes.py_object)),
+ ('Check_Status', ctypes.PYFUNCTYPE(ctypes.c_int, ctypes.c_int))]
+
+
+def _loadPycairoAPI():
+ global pycairoAPI
+ if pycairoAPI is not None:
+ return
+
+ PyCObject_AsVoidPtr = ctypes.pythonapi.PyCObject_AsVoidPtr
+ PyCObject_AsVoidPtr.argtypes = [ctypes.py_object]
+ PyCObject_AsVoidPtr.restype = ctypes.c_void_p
+ ptr = PyCObject_AsVoidPtr(cairo.CAPI)
+ pycairoAPI = ctypes.cast(ptr, ctypes.POINTER(Pycairo_CAPI)).contents
+
+#----------------------------------------------------------------------------
+
+# Load these at import time. That seems a bit better than doing it at
+# first use...
+_findCairoLib()
+_loadPycairoAPI()
+
+#----------------------------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxpTag.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxpTag.py
new file mode 100644
index 0000000..651b56d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/lib/wxpTag.py
@@ -0,0 +1,275 @@
+#----------------------------------------------------------------------
+# Name: wxPython.lib.wxpTag
+# Purpose: A wxHtmlTagHandler that knows how to build and place
+# wxPython widgets onto web pages.
+#
+# Author: Robin Dunn
+#
+# Created: 13-Sept-1999
+# RCS-ID: $Id$
+# Copyright: (c) 1999 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/13/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o Updated for V2.5 compatability
+#
+
+'''
+wx.lib.wxpTag
+
+This module contains a wxHtmlTagHandler that knows how to build
+and place wxPython widgets onto wxHtmlWindow web pages.
+
+You don\'t need to use anything in this module directly, just
+importing it will create the tag handler and add it to any
+wxHtmlWinParsers created from that time forth.
+
+Tags of the following form are recognised::
+
+ <WXP class="classname" [module="modulename"] [width="num"] [height="num"]>
+ <PARAM name="parameterName" value="parameterValue>
+ ...
+ </WXP>
+
+where modulename is the name of a module (possibly in package
+notation) to import and classname is the name of a class in that
+module to create an instance of. If the module tag-attribute is not
+given or is an empty string, then wx is used. The width and height
+attributes are expected to be integers and will be passed to the
+__init__ method of the class as a wxSize object named size. However,
+if the width attribute ends with the percent (%) symbol then the value
+will be used as a percentage of the available width and the
+wxHtmlWindow will manage the size.
+
+The name-value pairs in all the nested PARAM tags are packaged up as
+strings into a python dictionary and passed to the __init__ method of
+the class as keyword arguments. This means that they are all
+accessible from the __init__ method as regular parameters, or you use
+the special Python \*\*kw syntax in your __init__ method to get the
+dictionary directly.
+
+Some parameter values are special and if they are present then they will
+be converted from strings to alternate datatypes. They are:
+
+ id If the value of id can be converted to an integer, it will
+ be. Otherwise it is assumed to be the name of an integer
+ variable in the module.
+
+ colours Any value of the form "#123ABC" will automatically be
+ converted to a wxColour object.
+
+ Py Types Any value begining with "(", "[" or "{" are expected to
+ be a Python tuple, list, or dictionary and eval()
+ will be used to convert them to that type. If the
+ eval() fails then the original string value will be
+ preserved.
+
+ wx Types Any value begining with "wx" is expected to be an attempt
+ to create a wxPython object, such as a wxSize, etc.
+ The eval() will be used to try and construct the
+ object and if it fails then the original string value
+ will be used instead.
+
+An example::
+
+ <wxp module="wx" class="Button">
+ <param name="label" value="Click here">
+ <param name="id" value="ID_OK">
+ </wxp>
+
+Both the begining and ending WXP tags are required.
+
+In the future support will be added for another tag that can be
+embedded between the two begining and ending WXP tags and will
+facilitate calling methods of the widget to help initialize it.
+Additionally, support may be added to fetch the module from a web
+server as is done with java applets.
+
+'''
+#----------------------------------------------------------------------
+
+import types
+
+import wx
+import wx.html
+
+
+#----------------------------------------------------------------------
+
+WXPTAG = 'WXP'
+PARAMTAG = 'PARAM'
+
+#----------------------------------------------------------------------
+
+class wxpTagHandler(wx.html.HtmlWinTagHandler):
+ def __init__(self):
+ wx.html.HtmlWinTagHandler.__init__(self)
+ self.ctx = None
+
+ def GetSupportedTags(self):
+ return WXPTAG+','+PARAMTAG
+
+
+ def HandleTag(self, tag):
+ name = tag.GetName()
+ if name == WXPTAG:
+ return self.HandleWxpTag(tag)
+ elif name == PARAMTAG:
+ return self.HandleParamTag(tag)
+ else:
+ raise ValueError, 'unknown tag: ' + name
+
+
+ def HandleWxpTag(self, tag):
+ # create a new context object
+ self.ctx = _Context()
+
+ # find and import the module
+ modName = ''
+ if tag.HasParam('MODULE'):
+ modName = tag.GetParam('MODULE')
+ if modName:
+ self.ctx.classMod = _my_import(modName)
+ else:
+ self.ctx.classMod = wx
+
+ # find and verify the class
+ if not tag.HasParam('CLASS'):
+ raise AttributeError, "WXP tag requires a CLASS attribute"
+
+ className = tag.GetParam('CLASS')
+ self.ctx.classObj = getattr(self.ctx.classMod, className)
+ if type(self.ctx.classObj) not in [ types.ClassType, types.TypeType]:
+ raise TypeError, "WXP tag attribute CLASS must name a class"
+
+ # now look for width and height
+ width = -1
+ height = -1
+ if tag.HasParam('WIDTH'):
+ width = tag.GetParam('WIDTH')
+ if width[-1] == '%':
+ self.ctx.floatWidth = int(width[:-1], 0)
+ width = self.ctx.floatWidth
+ else:
+ width = int(width)
+ if tag.HasParam('HEIGHT'):
+ height = int(tag.GetParam('HEIGHT'))
+ self.ctx.kwargs['size'] = wx.Size(width, height)
+
+ # parse up to the closing tag, and gather any nested Param tags.
+ self.ParseInner(tag)
+
+ # create the object
+ parent = self.GetParser().GetWindowInterface().GetHTMLWindow()
+ if parent:
+ obj = self.ctx.classObj(parent, **self.ctx.kwargs)
+ obj.Show(True)
+
+ # add it to the HtmlWindow
+ self.GetParser().GetContainer().InsertCell(
+ wx.html.HtmlWidgetCell(obj, self.ctx.floatWidth))
+ self.ctx = None
+ return True
+
+
+ def HandleParamTag(self, tag):
+ if not tag.HasParam('NAME'):
+ return False
+
+ name = tag.GetParam('NAME')
+ value = ""
+ if tag.HasParam('VALUE'):
+ value = tag.GetParam('VALUE')
+
+ # check for a param named 'id'
+ if name == 'id':
+ theID = -1
+ try:
+ theID = int(value)
+ except ValueError:
+ theID = getattr(self.ctx.classMod, value)
+ value = theID
+
+
+ # check for something that should be evaluated
+ elif value and value[0] in '[{(' or value[:2] == 'wx':
+ saveVal = value
+ try:
+ value = eval(value, self.ctx.classMod.__dict__)
+ except:
+ value = saveVal
+
+ # convert to wx.Colour
+ elif value and value[0] == '#':
+ try:
+ red = int('0x'+value[1:3], 16)
+ green = int('0x'+value[3:5], 16)
+ blue = int('0x'+value[5:], 16)
+ value = wx.Colour(red, green, blue)
+ except:
+ pass
+
+ if self.ctx:
+ self.ctx.kwargs[str(name)] = value
+ return False
+
+
+#----------------------------------------------------------------------
+# just a place to hold some values
+class _Context:
+ def __init__(self):
+ self.kwargs = {}
+ self.width = -1
+ self.height = -1
+ self.classMod = None
+ self.classObj = None
+ self.floatWidth = 0
+
+
+#----------------------------------------------------------------------
+# Function to assist with importing packages
+def _my_import(name):
+ mod = __import__(name)
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+
+
+#----------------------------------------------------------------------
+# Function to parse a param string (of the form 'item=value item2="value etc"'
+# and creates a dictionary
+def _param2dict(param):
+ i = 0; j = 0; s = len(param); d = {}
+ while 1:
+ while i<s and param[i] == " " : i = i+1
+ if i>=s: break
+ j = i
+ while j<s and param[j] != "=": j=j+1
+ if j+1>=s:
+ break
+ word = param[i:j]
+ i=j+1
+ if (param[i] == '"'):
+ j=i+1
+ while j<s and param[j] != '"' : j=j+1
+ if j == s: break
+ val = param[i+1:j]
+ elif (param[i] != " "):
+ j=i+1
+ while j<s and param[j] != " " : j=j+1
+ val = param[i:j]
+ else:
+ val = ""
+ i=j+1
+ d[word] = val
+ return d
+
+#----------------------------------------------------------------------
+
+
+# Add our handler class to the collection of tag handlers maintained
+# by wxWidgets.
+wx.html.HtmlWinParser_AddTagHandler(wxpTagHandler)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/af/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/af/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..c047483
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/af/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/an/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/an/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..bfe5786
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/an/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ar/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ar/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..7eb01aa
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ar/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ca/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ca/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..7b04f94
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ca/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ca@valencia/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ca@valencia/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..3622cec
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ca@valencia/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/cs/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/cs/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..8670bf3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/cs/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/da/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/da/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..83b1284
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/da/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/de/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/de/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..e4da29f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/de/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/el/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/el/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..72f9eca
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/el/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/es/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/es/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..5507690
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/es/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/eu/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/eu/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..c474beb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/eu/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/fi/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/fi/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..356edd3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/fi/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/fr/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/fr/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..c7fc345
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/fr/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/gl_ES/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/gl_ES/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..3a6831e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/gl_ES/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/hi/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/hi/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..f38547a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/hi/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/hu/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/hu/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..dee8e93
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/hu/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/id/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/id/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..ab9b69a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/id/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/it/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/it/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..86035f8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/it/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ja/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ja/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..234c47c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ja/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ko_KR/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ko_KR/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..318fb12
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ko_KR/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/lt/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/lt/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..7162c3f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/lt/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/lv/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/lv/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..34c53bc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/lv/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ms/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ms/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..244a6ff
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ms/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/nb/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/nb/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..17f6883
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/nb/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ne/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ne/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..7acfb2e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ne/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/nl/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/nl/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..c568831
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/nl/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pl/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pl/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..9d76b23
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pl/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pt/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pt/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..b054df1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pt/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pt_BR/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pt_BR/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..7612bc6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/pt_BR/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ro/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ro/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..c0bdf28
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ro/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ru/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ru/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..59b73f9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ru/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sk/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sk/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..0ae402c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sk/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sl/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sl/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..f5f5137
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sl/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sq/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sq/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..58a5e2d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sq/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sv/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sv/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..f2ce00e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/sv/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ta/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ta/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..7887a5f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/ta/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/tr/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/tr/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..239d101
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/tr/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/uk/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/uk/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..8b0e99b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/uk/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/vi/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/vi/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..d84d8b9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/vi/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/zh_CN/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/zh_CN/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..771aa9a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/zh_CN/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/zh_TW/LC_MESSAGES/wxstd.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/zh_TW/LC_MESSAGES/wxstd.mo
new file mode 100644
index 0000000..c62c4ff
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/locale/zh_TW/LC_MESSAGES/wxstd.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/media.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/media.py
new file mode 100644
index 0000000..414ca24
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/media.py
@@ -0,0 +1,205 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+Classes for a media player control
+"""
+
+import _media
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+MEDIASTATE_STOPPED = _media.MEDIASTATE_STOPPED
+MEDIASTATE_PAUSED = _media.MEDIASTATE_PAUSED
+MEDIASTATE_PLAYING = _media.MEDIASTATE_PLAYING
+MEDIACTRLPLAYERCONTROLS_NONE = _media.MEDIACTRLPLAYERCONTROLS_NONE
+MEDIACTRLPLAYERCONTROLS_STEP = _media.MEDIACTRLPLAYERCONTROLS_STEP
+MEDIACTRLPLAYERCONTROLS_VOLUME = _media.MEDIACTRLPLAYERCONTROLS_VOLUME
+MEDIACTRLPLAYERCONTROLS_DEFAULT = _media.MEDIACTRLPLAYERCONTROLS_DEFAULT
+class MediaEvent(_core.NotifyEvent):
+ """Proxy of C++ MediaEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=wxEVT_NULL, int id=0) -> MediaEvent"""
+ _media.MediaEvent_swiginit(self,_media.new_MediaEvent(*args, **kwargs))
+_media.MediaEvent_swigregister(MediaEvent)
+cvar = _media.cvar
+MEDIABACKEND_DIRECTSHOW = cvar.MEDIABACKEND_DIRECTSHOW
+MEDIABACKEND_MCI = cvar.MEDIABACKEND_MCI
+MEDIABACKEND_QUICKTIME = cvar.MEDIABACKEND_QUICKTIME
+MEDIABACKEND_GSTREAMER = cvar.MEDIABACKEND_GSTREAMER
+MEDIABACKEND_REALPLAYER = cvar.MEDIABACKEND_REALPLAYER
+MEDIABACKEND_WMP10 = cvar.MEDIABACKEND_WMP10
+
+class MediaCtrl(_core.Control):
+ """Proxy of C++ MediaCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String fileName=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String szBackend=EmptyString,
+ Validator validator=DefaultValidator,
+ String name=MediaCtrlNameStr) -> MediaCtrl
+ """
+ _media.MediaCtrl_swiginit(self,_media.new_MediaCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String fileName=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, String szBackend=EmptyString,
+ Validator validator=DefaultValidator,
+ String name=MediaCtrlNameStr) -> bool
+ """
+ return _media.MediaCtrl_Create(*args, **kwargs)
+
+ def Play(*args, **kwargs):
+ """Play(self) -> bool"""
+ return _media.MediaCtrl_Play(*args, **kwargs)
+
+ def Pause(*args, **kwargs):
+ """Pause(self) -> bool"""
+ return _media.MediaCtrl_Pause(*args, **kwargs)
+
+ def Stop(*args, **kwargs):
+ """Stop(self) -> bool"""
+ return _media.MediaCtrl_Stop(*args, **kwargs)
+
+ def GetState(*args, **kwargs):
+ """GetState(self) -> int"""
+ return _media.MediaCtrl_GetState(*args, **kwargs)
+
+ def GetPlaybackRate(*args, **kwargs):
+ """GetPlaybackRate(self) -> double"""
+ return _media.MediaCtrl_GetPlaybackRate(*args, **kwargs)
+
+ def SetPlaybackRate(*args, **kwargs):
+ """SetPlaybackRate(self, double dRate) -> bool"""
+ return _media.MediaCtrl_SetPlaybackRate(*args, **kwargs)
+
+ def Seek(*args, **kwargs):
+ """Seek(self, wxFileOffset where, int mode=FromStart) -> wxFileOffset"""
+ return _media.MediaCtrl_Seek(*args, **kwargs)
+
+ def Tell(*args, **kwargs):
+ """Tell(self) -> wxFileOffset"""
+ return _media.MediaCtrl_Tell(*args, **kwargs)
+
+ def Length(*args, **kwargs):
+ """Length(self) -> wxFileOffset"""
+ return _media.MediaCtrl_Length(*args, **kwargs)
+
+ def GetVolume(*args, **kwargs):
+ """GetVolume(self) -> double"""
+ return _media.MediaCtrl_GetVolume(*args, **kwargs)
+
+ def SetVolume(*args, **kwargs):
+ """SetVolume(self, double dVolume) -> bool"""
+ return _media.MediaCtrl_SetVolume(*args, **kwargs)
+
+ def ShowPlayerControls(*args, **kwargs):
+ """ShowPlayerControls(self, int flags=MEDIACTRLPLAYERCONTROLS_DEFAULT) -> bool"""
+ return _media.MediaCtrl_ShowPlayerControls(*args, **kwargs)
+
+ def Load(*args, **kwargs):
+ """Load(self, String fileName) -> bool"""
+ return _media.MediaCtrl_Load(*args, **kwargs)
+
+ def LoadURI(*args, **kwargs):
+ """LoadURI(self, String fileName) -> bool"""
+ return _media.MediaCtrl_LoadURI(*args, **kwargs)
+
+ def LoadURIWithProxy(*args, **kwargs):
+ """LoadURIWithProxy(self, String fileName, String proxy) -> bool"""
+ return _media.MediaCtrl_LoadURIWithProxy(*args, **kwargs)
+
+ LoadFromURI = LoadURI
+ def GetDownloadProgress(*args, **kwargs):
+ """GetDownloadProgress(self) -> wxFileOffset"""
+ return _media.MediaCtrl_GetDownloadProgress(*args, **kwargs)
+
+ def GetDownloadTotal(*args, **kwargs):
+ """GetDownloadTotal(self) -> wxFileOffset"""
+ return _media.MediaCtrl_GetDownloadTotal(*args, **kwargs)
+
+ DownloadProgress = property(GetDownloadProgress,doc="See `GetDownloadProgress`")
+ DownloadTotal = property(GetDownloadTotal,doc="See `GetDownloadTotal`")
+ PlaybackRate = property(GetPlaybackRate,SetPlaybackRate,doc="See `GetPlaybackRate` and `SetPlaybackRate`")
+ State = property(GetState,doc="See `GetState`")
+ Volume = property(GetVolume,SetVolume,doc="See `GetVolume` and `SetVolume`")
+_media.MediaCtrl_swigregister(MediaCtrl)
+MediaCtrlNameStr = cvar.MediaCtrlNameStr
+
+def PreMediaCtrl(*args, **kwargs):
+ """PreMediaCtrl() -> MediaCtrl"""
+ val = _media.new_PreMediaCtrl(*args, **kwargs)
+ return val
+
+wxEVT_MEDIA_FINISHED = _media.wxEVT_MEDIA_FINISHED
+wxEVT_MEDIA_STOP = _media.wxEVT_MEDIA_STOP
+wxEVT_MEDIA_LOADED = _media.wxEVT_MEDIA_LOADED
+wxEVT_MEDIA_STATECHANGED = _media.wxEVT_MEDIA_STATECHANGED
+wxEVT_MEDIA_PLAY = _media.wxEVT_MEDIA_PLAY
+wxEVT_MEDIA_PAUSE = _media.wxEVT_MEDIA_PAUSE
+EVT_MEDIA_FINISHED = wx.PyEventBinder( wxEVT_MEDIA_FINISHED, 1)
+EVT_MEDIA_STOP = wx.PyEventBinder( wxEVT_MEDIA_STOP, 1)
+EVT_MEDIA_LOADED = wx.PyEventBinder( wxEVT_MEDIA_LOADED, 1)
+EVT_MEDIA_STATECHANGED = wx.PyEventBinder( wxEVT_MEDIA_STATECHANGED, 1)
+EVT_MEDIA_PLAY = wx.PyEventBinder( wxEVT_MEDIA_PLAY, 1)
+EVT_MEDIA_PAUSE = wx.PyEventBinder( wxEVT_MEDIA_PAUSE, 1)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/propgrid.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/propgrid.py
new file mode 100644
index 0000000..fc2888d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/propgrid.py
@@ -0,0 +1,4657 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+The `PropertyGrid` provides a specialized grid for editing
+properties such as strings, numbers, colours, and string lists.
+"""
+
+import _propgrid
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+import _windows
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+PG_XBEFORETEXT = _propgrid.PG_XBEFORETEXT
+PG_XBEFOREWIDGET = _propgrid.PG_XBEFOREWIDGET
+PG_ICON_WIDTH = _propgrid.PG_ICON_WIDTH
+PG_USE_RENDERER_NATIVE = _propgrid.PG_USE_RENDERER_NATIVE
+PG_SUPPORT_TOOLTIPS = _propgrid.PG_SUPPORT_TOOLTIPS
+PG_CUSTOM_IMAGE_WIDTH = _propgrid.PG_CUSTOM_IMAGE_WIDTH
+PG_NO_CHILD_EVT_MOTION = _propgrid.PG_NO_CHILD_EVT_MOTION
+PG_NAT_BUTTON_BORDER_ANY = _propgrid.PG_NAT_BUTTON_BORDER_ANY
+PG_NAT_BUTTON_BORDER_X = _propgrid.PG_NAT_BUTTON_BORDER_X
+PG_NAT_BUTTON_BORDER_Y = _propgrid.PG_NAT_BUTTON_BORDER_Y
+PG_REFRESH_CONTROLS = _propgrid.PG_REFRESH_CONTROLS
+PG_CONTROL_MARGIN = _propgrid.PG_CONTROL_MARGIN
+CC_CUSTOM_IMAGE_MARGIN1 = _propgrid.CC_CUSTOM_IMAGE_MARGIN1
+CC_CUSTOM_IMAGE_MARGIN2 = _propgrid.CC_CUSTOM_IMAGE_MARGIN2
+DEFAULT_IMAGE_OFFSET_INCREMENT = _propgrid.DEFAULT_IMAGE_OFFSET_INCREMENT
+PG_DRAG_MARGIN = _propgrid.PG_DRAG_MARGIN
+PG_SPLITTERX_DETECTMARGIN1 = _propgrid.PG_SPLITTERX_DETECTMARGIN1
+PG_SPLITTERX_DETECTMARGIN2 = _propgrid.PG_SPLITTERX_DETECTMARGIN2
+PG_SMALL_SCREEN = _propgrid.PG_SMALL_SCREEN
+PG_COMPATIBILITY_1_4 = _propgrid.PG_COMPATIBILITY_1_4
+PG_INCLUDE_ADVPROPS = _propgrid.PG_INCLUDE_ADVPROPS
+PG_INCLUDE_CHECKBOX = _propgrid.PG_INCLUDE_CHECKBOX
+PG_KEEP_STRUCTURE = _propgrid.PG_KEEP_STRUCTURE
+PG_RECURSE = _propgrid.PG_RECURSE
+PG_INC_ATTRIBUTES = _propgrid.PG_INC_ATTRIBUTES
+PG_RECURSE_STARTS = _propgrid.PG_RECURSE_STARTS
+PG_FORCE = _propgrid.PG_FORCE
+PG_SORT_TOP_LEVEL_ONLY = _propgrid.PG_SORT_TOP_LEVEL_ONLY
+PG_DONT_RECURSE = _propgrid.PG_DONT_RECURSE
+PG_FULL_VALUE = _propgrid.PG_FULL_VALUE
+PG_REPORT_ERROR = _propgrid.PG_REPORT_ERROR
+PG_PROPERTY_SPECIFIC = _propgrid.PG_PROPERTY_SPECIFIC
+PG_EDITABLE_VALUE = _propgrid.PG_EDITABLE_VALUE
+PG_COMPOSITE_FRAGMENT = _propgrid.PG_COMPOSITE_FRAGMENT
+PG_UNEDITABLE_COMPOSITE_FRAGMENT = _propgrid.PG_UNEDITABLE_COMPOSITE_FRAGMENT
+PG_VALUE_IS_CURRENT = _propgrid.PG_VALUE_IS_CURRENT
+PG_PROGRAMMATIC_VALUE = _propgrid.PG_PROGRAMMATIC_VALUE
+PG_SETVAL_REFRESH_EDITOR = _propgrid.PG_SETVAL_REFRESH_EDITOR
+PG_SETVAL_AGGREGATED = _propgrid.PG_SETVAL_AGGREGATED
+PG_SETVAL_FROM_PARENT = _propgrid.PG_SETVAL_FROM_PARENT
+PG_SETVAL_BY_USER = _propgrid.PG_SETVAL_BY_USER
+class PGPaintData(object):
+ """Proxy of C++ PGPaintData class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ m_parent = property(_propgrid.PGPaintData_m_parent_get, _propgrid.PGPaintData_m_parent_set)
+ m_choiceItem = property(_propgrid.PGPaintData_m_choiceItem_get, _propgrid.PGPaintData_m_choiceItem_set)
+ m_drawnWidth = property(_propgrid.PGPaintData_m_drawnWidth_get, _propgrid.PGPaintData_m_drawnWidth_set)
+ m_drawnHeight = property(_propgrid.PGPaintData_m_drawnHeight_get, _propgrid.PGPaintData_m_drawnHeight_set)
+_propgrid.PGPaintData_swigregister(PGPaintData)
+
+PG_CUSTOM_IMAGE_SPACINGY = _propgrid.PG_CUSTOM_IMAGE_SPACINGY
+PG_CAPRECTXMARGIN = _propgrid.PG_CAPRECTXMARGIN
+PG_CAPRECTYMARGIN = _propgrid.PG_CAPRECTYMARGIN
+class PGCell(_core.Object):
+ """Proxy of C++ PGCell class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> PGCell
+ __init__(self, PGCell other) -> PGCell
+ __init__(self, String text, Bitmap bitmap=wxNullBitmap, Colour fgCol=wxNullColour,
+ Colour bgCol=wxNullColour) -> PGCell
+ """
+ _propgrid.PGCell_swiginit(self,_propgrid.new_PGCell(*args))
+ __swig_destroy__ = _propgrid.delete_PGCell
+ __del__ = lambda self : None;
+ def GetData(*args):
+ """
+ GetData(self)
+ GetData(self)
+ """
+ return _propgrid.PGCell_GetData(*args)
+
+ def HasText(*args, **kwargs):
+ """HasText(self) -> bool"""
+ return _propgrid.PGCell_HasText(*args, **kwargs)
+
+ def SetEmptyData(*args, **kwargs):
+ """SetEmptyData(self)"""
+ return _propgrid.PGCell_SetEmptyData(*args, **kwargs)
+
+ def MergeFrom(*args, **kwargs):
+ """MergeFrom(self, PGCell srcCell)"""
+ return _propgrid.PGCell_MergeFrom(*args, **kwargs)
+
+ def SetText(*args, **kwargs):
+ """SetText(self, String text)"""
+ return _propgrid.PGCell_SetText(*args, **kwargs)
+
+ def SetBitmap(*args, **kwargs):
+ """SetBitmap(self, Bitmap bitmap)"""
+ return _propgrid.PGCell_SetBitmap(*args, **kwargs)
+
+ def SetFgCol(*args, **kwargs):
+ """SetFgCol(self, Colour col)"""
+ return _propgrid.PGCell_SetFgCol(*args, **kwargs)
+
+ def SetFont(*args, **kwargs):
+ """SetFont(self, Font font)"""
+ return _propgrid.PGCell_SetFont(*args, **kwargs)
+
+ def SetBgCol(*args, **kwargs):
+ """SetBgCol(self, Colour col)"""
+ return _propgrid.PGCell_SetBgCol(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self) -> String"""
+ return _propgrid.PGCell_GetText(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self) -> Bitmap"""
+ return _propgrid.PGCell_GetBitmap(*args, **kwargs)
+
+ def GetFgCol(*args, **kwargs):
+ """GetFgCol(self) -> Colour"""
+ return _propgrid.PGCell_GetFgCol(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """GetFont(self) -> Font"""
+ return _propgrid.PGCell_GetFont(*args, **kwargs)
+
+ def GetBgCol(*args, **kwargs):
+ """GetBgCol(self) -> Colour"""
+ return _propgrid.PGCell_GetBgCol(*args, **kwargs)
+
+ def IsInvalid(*args, **kwargs):
+ """IsInvalid(self) -> bool"""
+ return _propgrid.PGCell_IsInvalid(*args, **kwargs)
+
+_propgrid.PGCell_swigregister(PGCell)
+
+PG_PROP_MODIFIED = _propgrid.PG_PROP_MODIFIED
+PG_PROP_DISABLED = _propgrid.PG_PROP_DISABLED
+PG_PROP_HIDDEN = _propgrid.PG_PROP_HIDDEN
+PG_PROP_CUSTOMIMAGE = _propgrid.PG_PROP_CUSTOMIMAGE
+PG_PROP_NOEDITOR = _propgrid.PG_PROP_NOEDITOR
+PG_PROP_COLLAPSED = _propgrid.PG_PROP_COLLAPSED
+PG_PROP_INVALID_VALUE = _propgrid.PG_PROP_INVALID_VALUE
+PG_PROP_WAS_MODIFIED = _propgrid.PG_PROP_WAS_MODIFIED
+PG_PROP_AGGREGATE = _propgrid.PG_PROP_AGGREGATE
+PG_PROP_CHILDREN_ARE_COPIES = _propgrid.PG_PROP_CHILDREN_ARE_COPIES
+PG_PROP_PROPERTY = _propgrid.PG_PROP_PROPERTY
+PG_PROP_CATEGORY = _propgrid.PG_PROP_CATEGORY
+PG_PROP_MISC_PARENT = _propgrid.PG_PROP_MISC_PARENT
+PG_PROP_READONLY = _propgrid.PG_PROP_READONLY
+PG_PROP_COMPOSED_VALUE = _propgrid.PG_PROP_COMPOSED_VALUE
+PG_PROP_USES_COMMON_VALUE = _propgrid.PG_PROP_USES_COMMON_VALUE
+PG_PROP_AUTO_UNSPECIFIED = _propgrid.PG_PROP_AUTO_UNSPECIFIED
+PG_PROP_CLASS_SPECIFIC_1 = _propgrid.PG_PROP_CLASS_SPECIFIC_1
+PG_PROP_CLASS_SPECIFIC_2 = _propgrid.PG_PROP_CLASS_SPECIFIC_2
+PG_PROP_BEING_DELETED = _propgrid.PG_PROP_BEING_DELETED
+class PGChoices(object):
+ """Proxy of C++ PGChoices class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> PGChoices
+ __init__(self, PGChoices a) -> PGChoices
+ __init__(self, wxChar labels, long values=None) -> PGChoices
+ __init__(self, wxArrayString labels, wxArrayInt values=wxArrayInt()) -> PGChoices
+ __init__(self, data) -> PGChoices
+ """
+ _propgrid.PGChoices_swiginit(self,_propgrid.new_PGChoices(*args))
+ __swig_destroy__ = _propgrid.delete_PGChoices
+ __del__ = lambda self : None;
+ def Add(*args):
+ """
+ Add(self, wxChar labels, ValArrItem values=None)
+ Add(self, wxArrayString arr, wxArrayInt arrint=wxArrayInt())
+ Add(self, String label, int value=INT_MAX)
+ Add(self, String label, Bitmap bitmap, int value=INT_MAX)
+ Add(self, entry)
+ """
+ return _propgrid.PGChoices_Add(*args)
+
+ def AddAsSorted(*args, **kwargs):
+ """AddAsSorted(self, String label, int value=INT_MAX)"""
+ return _propgrid.PGChoices_AddAsSorted(*args, **kwargs)
+
+ def Assign(*args, **kwargs):
+ """Assign(self, PGChoices a)"""
+ return _propgrid.PGChoices_Assign(*args, **kwargs)
+
+ def AssignData(*args, **kwargs):
+ """AssignData(self, data)"""
+ return _propgrid.PGChoices_AssignData(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """Clear(self)"""
+ return _propgrid.PGChoices_Clear(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self) -> PGChoices"""
+ return _propgrid.PGChoices_Copy(*args, **kwargs)
+
+ def EnsureData(*args, **kwargs):
+ """EnsureData(self)"""
+ return _propgrid.PGChoices_EnsureData(*args, **kwargs)
+
+ def GetId(*args, **kwargs):
+ """GetId(self) -> PGChoicesId"""
+ return _propgrid.PGChoices_GetId(*args, **kwargs)
+
+ def GetLabel(*args, **kwargs):
+ """GetLabel(self, int ind) -> String"""
+ return _propgrid.PGChoices_GetLabel(*args, **kwargs)
+
+ def GetCount(*args, **kwargs):
+ """GetCount(self) -> int"""
+ return _propgrid.PGChoices_GetCount(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self, int ind) -> int"""
+ return _propgrid.PGChoices_GetValue(*args, **kwargs)
+
+ def GetValuesForStrings(*args, **kwargs):
+ """GetValuesForStrings(self, wxArrayString strings) -> wxArrayInt"""
+ return _propgrid.PGChoices_GetValuesForStrings(*args, **kwargs)
+
+ def GetIndicesForStrings(*args, **kwargs):
+ """GetIndicesForStrings(self, wxArrayString strings, wxArrayString unmatched=None) -> wxArrayInt"""
+ return _propgrid.PGChoices_GetIndicesForStrings(*args, **kwargs)
+
+ def Index(*args):
+ """
+ Index(self, String str) -> int
+ Index(self, int val) -> int
+ """
+ return _propgrid.PGChoices_Index(*args)
+
+ def Insert(*args):
+ """
+ Insert(self, String label, int index, int value=INT_MAX)
+ Insert(self, entry, int index)
+ """
+ return _propgrid.PGChoices_Insert(*args)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _propgrid.PGChoices_IsOk(*args, **kwargs)
+
+ def Item(*args):
+ """
+ Item(self, int i)
+ Item(self, int i)
+ """
+ return _propgrid.PGChoices_Item(*args)
+
+ def RemoveAt(*args, **kwargs):
+ """RemoveAt(self, size_t nIndex, size_t count=1)"""
+ return _propgrid.PGChoices_RemoveAt(*args, **kwargs)
+
+ def Set(*args):
+ """
+ Set(self, wxChar labels, long values=None)
+ Set(self, wxArrayString labels, wxArrayInt values=wxArrayInt())
+ """
+ return _propgrid.PGChoices_Set(*args)
+
+ def AllocExclusive(*args, **kwargs):
+ """AllocExclusive(self)"""
+ return _propgrid.PGChoices_AllocExclusive(*args, **kwargs)
+
+ def GetData(*args, **kwargs):
+ """GetData(self)"""
+ return _propgrid.PGChoices_GetData(*args, **kwargs)
+
+ def GetDataPtr(*args, **kwargs):
+ """GetDataPtr(self)"""
+ return _propgrid.PGChoices_GetDataPtr(*args, **kwargs)
+
+ def ExtractData(*args, **kwargs):
+ """ExtractData(self)"""
+ return _propgrid.PGChoices_ExtractData(*args, **kwargs)
+
+ def GetLabels(*args, **kwargs):
+ """GetLabels(self) -> wxArrayString"""
+ return _propgrid.PGChoices_GetLabels(*args, **kwargs)
+
+_propgrid.PGChoices_swigregister(PGChoices)
+
+class PGProperty(_core.Object):
+ """Proxy of C++ PGProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> PGProperty
+ __init__(self, String label, String name) -> PGProperty
+ """
+ _propgrid.PGProperty_swiginit(self,_propgrid.new_PGProperty(*args))
+ __swig_destroy__ = _propgrid.delete_PGProperty
+ __del__ = lambda self : None;
+ def OnSetValue(*args, **kwargs):
+ """OnSetValue(self)"""
+ return _propgrid.PGProperty_OnSetValue(*args, **kwargs)
+
+ def DoGetValue(*args, **kwargs):
+ """DoGetValue(self) -> wxVariant"""
+ return _propgrid.PGProperty_DoGetValue(*args, **kwargs)
+
+ def ValueToString(*args, **kwargs):
+ """ValueToString(self, wxVariant value, int argFlags=0) -> String"""
+ return _propgrid.PGProperty_ValueToString(*args, **kwargs)
+
+ def SetValueFromString(*args, **kwargs):
+ """SetValueFromString(self, String text, int flags=PG_PROGRAMMATIC_VALUE) -> bool"""
+ return _propgrid.PGProperty_SetValueFromString(*args, **kwargs)
+
+ def SetValueFromInt(*args, **kwargs):
+ """SetValueFromInt(self, long value, int flags=0) -> bool"""
+ return _propgrid.PGProperty_SetValueFromInt(*args, **kwargs)
+
+ def OnMeasureImage(*args, **kwargs):
+ """OnMeasureImage(self, int item=-1) -> Size"""
+ return _propgrid.PGProperty_OnMeasureImage(*args, **kwargs)
+
+ def OnEvent(*args, **kwargs):
+ """OnEvent(self, PropertyGrid propgrid, Window wnd_primary, Event event) -> bool"""
+ return _propgrid.PGProperty_OnEvent(*args, **kwargs)
+
+ def ChildChanged(*args, **kwargs):
+ """ChildChanged(self, wxVariant thisValue, int childIndex, wxVariant childValue) -> wxVariant"""
+ return _propgrid.PGProperty_ChildChanged(*args, **kwargs)
+
+ def DoGetEditorClass(*args, **kwargs):
+ """DoGetEditorClass(self) -> PGEditor"""
+ return _propgrid.PGProperty_DoGetEditorClass(*args, **kwargs)
+
+ def DoGetValidator(*args, **kwargs):
+ """DoGetValidator(self) -> Validator"""
+ return _propgrid.PGProperty_DoGetValidator(*args, **kwargs)
+
+ def OnCustomPaint(*args, **kwargs):
+ """OnCustomPaint(self, DC dc, Rect rect, PGPaintData paintdata)"""
+ return _propgrid.PGProperty_OnCustomPaint(*args, **kwargs)
+
+ def GetCellRenderer(*args, **kwargs):
+ """GetCellRenderer(self, int column)"""
+ return _propgrid.PGProperty_GetCellRenderer(*args, **kwargs)
+
+ def GetChoiceSelection(*args, **kwargs):
+ """GetChoiceSelection(self) -> int"""
+ return _propgrid.PGProperty_GetChoiceSelection(*args, **kwargs)
+
+ def RefreshChildren(*args, **kwargs):
+ """RefreshChildren(self)"""
+ return _propgrid.PGProperty_RefreshChildren(*args, **kwargs)
+
+ def DoSetAttribute(*args, **kwargs):
+ """DoSetAttribute(self, String name, wxVariant value) -> bool"""
+ return _propgrid.PGProperty_DoSetAttribute(*args, **kwargs)
+
+ def DoGetAttribute(*args, **kwargs):
+ """DoGetAttribute(self, String name) -> wxVariant"""
+ return _propgrid.PGProperty_DoGetAttribute(*args, **kwargs)
+
+ def GetEditorDialog(*args, **kwargs):
+ """GetEditorDialog(self) -> PGEditorDialogAdapter"""
+ return _propgrid.PGProperty_GetEditorDialog(*args, **kwargs)
+
+ def OnValidationFailure(*args, **kwargs):
+ """OnValidationFailure(self, wxVariant pendingValue)"""
+ return _propgrid.PGProperty_OnValidationFailure(*args, **kwargs)
+
+ def AddChoice(*args, **kwargs):
+ """AddChoice(self, String label, int value=INT_MAX) -> int"""
+ return _propgrid.PGProperty_AddChoice(*args, **kwargs)
+
+ def AreChildrenComponents(*args, **kwargs):
+ """AreChildrenComponents(self) -> bool"""
+ return _propgrid.PGProperty_AreChildrenComponents(*args, **kwargs)
+
+ def DeleteChildren(*args, **kwargs):
+ """DeleteChildren(self)"""
+ return _propgrid.PGProperty_DeleteChildren(*args, **kwargs)
+
+ def DeleteChoice(*args, **kwargs):
+ """DeleteChoice(self, int index)"""
+ return _propgrid.PGProperty_DeleteChoice(*args, **kwargs)
+
+ def Enable(*args, **kwargs):
+ """Enable(self, bool enable=True)"""
+ return _propgrid.PGProperty_Enable(*args, **kwargs)
+
+ def EnableCommonValue(*args, **kwargs):
+ """EnableCommonValue(self, bool enable=True)"""
+ return _propgrid.PGProperty_EnableCommonValue(*args, **kwargs)
+
+ def GenerateComposedValue(*args, **kwargs):
+ """GenerateComposedValue(self) -> String"""
+ return _propgrid.PGProperty_GenerateComposedValue(*args, **kwargs)
+
+ def GetLabel(*args, **kwargs):
+ """GetLabel(self) -> String"""
+ return _propgrid.PGProperty_GetLabel(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _propgrid.PGProperty_GetName(*args, **kwargs)
+
+ def GetBaseName(*args, **kwargs):
+ """GetBaseName(self) -> String"""
+ return _propgrid.PGProperty_GetBaseName(*args, **kwargs)
+
+ def GetChoices(*args, **kwargs):
+ """GetChoices(self) -> PGChoices"""
+ return _propgrid.PGProperty_GetChoices(*args, **kwargs)
+
+ def GetY(*args, **kwargs):
+ """GetY(self) -> int"""
+ return _propgrid.PGProperty_GetY(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> wxVariant"""
+ return _propgrid.PGProperty_GetValue(*args, **kwargs)
+
+ def GetValuePlain(*args, **kwargs):
+ """GetValuePlain(self) -> wxVariant"""
+ return _propgrid.PGProperty_GetValuePlain(*args, **kwargs)
+
+ def GetValueAsString(*args, **kwargs):
+ """GetValueAsString(self, int argFlags=0) -> String"""
+ return _propgrid.PGProperty_GetValueAsString(*args, **kwargs)
+
+ def GetCell(*args):
+ """
+ GetCell(self, int column) -> PGCell
+ GetCell(self, int column) -> PGCell
+ """
+ return _propgrid.PGProperty_GetCell(*args)
+
+ def GetOrCreateCell(*args, **kwargs):
+ """GetOrCreateCell(self, int column) -> PGCell"""
+ return _propgrid.PGProperty_GetOrCreateCell(*args, **kwargs)
+
+ def GetDisplayedCommonValueCount(*args, **kwargs):
+ """GetDisplayedCommonValueCount(self) -> int"""
+ return _propgrid.PGProperty_GetDisplayedCommonValueCount(*args, **kwargs)
+
+ def GetDisplayedString(*args, **kwargs):
+ """GetDisplayedString(self) -> String"""
+ return _propgrid.PGProperty_GetDisplayedString(*args, **kwargs)
+
+ def GetHintText(*args, **kwargs):
+ """GetHintText(self) -> String"""
+ return _propgrid.PGProperty_GetHintText(*args, **kwargs)
+
+ def GetGrid(*args, **kwargs):
+ """GetGrid(self) -> PropertyGrid"""
+ return _propgrid.PGProperty_GetGrid(*args, **kwargs)
+
+ def GetGridIfDisplayed(*args, **kwargs):
+ """GetGridIfDisplayed(self) -> PropertyGrid"""
+ return _propgrid.PGProperty_GetGridIfDisplayed(*args, **kwargs)
+
+ def GetMainParent(*args, **kwargs):
+ """GetMainParent(self) -> PGProperty"""
+ return _propgrid.PGProperty_GetMainParent(*args, **kwargs)
+
+ def GetParent(*args, **kwargs):
+ """GetParent(self) -> PGProperty"""
+ return _propgrid.PGProperty_GetParent(*args, **kwargs)
+
+ def IsTextEditable(*args, **kwargs):
+ """IsTextEditable(self) -> bool"""
+ return _propgrid.PGProperty_IsTextEditable(*args, **kwargs)
+
+ def IsValueUnspecified(*args, **kwargs):
+ """IsValueUnspecified(self) -> bool"""
+ return _propgrid.PGProperty_IsValueUnspecified(*args, **kwargs)
+
+ def HasFlag(*args, **kwargs):
+ """HasFlag(self, int flag) -> FlagType"""
+ return _propgrid.PGProperty_HasFlag(*args, **kwargs)
+
+ def GetAttributes(*args, **kwargs):
+ """GetAttributes(self)"""
+ return _propgrid.PGProperty_GetAttributes(*args, **kwargs)
+
+ def GetAttributesAsList(*args, **kwargs):
+ """GetAttributesAsList(self) -> wxVariant"""
+ return _propgrid.PGProperty_GetAttributesAsList(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> FlagType"""
+ return _propgrid.PGProperty_GetFlags(*args, **kwargs)
+
+ def GetEditorClass(*args, **kwargs):
+ """GetEditorClass(self) -> PGEditor"""
+ return _propgrid.PGProperty_GetEditorClass(*args, **kwargs)
+
+ def GetValueType(*args, **kwargs):
+ """GetValueType(self) -> String"""
+ return _propgrid.PGProperty_GetValueType(*args, **kwargs)
+
+ def GetColumnEditor(*args, **kwargs):
+ """GetColumnEditor(self, int column) -> PGEditor"""
+ return _propgrid.PGProperty_GetColumnEditor(*args, **kwargs)
+
+ def GetCommonValue(*args, **kwargs):
+ """GetCommonValue(self) -> int"""
+ return _propgrid.PGProperty_GetCommonValue(*args, **kwargs)
+
+ def HasVisibleChildren(*args, **kwargs):
+ """HasVisibleChildren(self) -> bool"""
+ return _propgrid.PGProperty_HasVisibleChildren(*args, **kwargs)
+
+ def InsertChild(*args, **kwargs):
+ """InsertChild(self, int index, PGProperty childProperty) -> PGProperty"""
+ return _propgrid.PGProperty_InsertChild(*args, **kwargs)
+
+ def InsertChoice(*args, **kwargs):
+ """InsertChoice(self, String label, int index, int value=INT_MAX) -> int"""
+ return _propgrid.PGProperty_InsertChoice(*args, **kwargs)
+
+ def IsCategory(*args, **kwargs):
+ """IsCategory(self) -> bool"""
+ return _propgrid.PGProperty_IsCategory(*args, **kwargs)
+
+ def IsRoot(*args, **kwargs):
+ """IsRoot(self) -> bool"""
+ return _propgrid.PGProperty_IsRoot(*args, **kwargs)
+
+ def IsSubProperty(*args, **kwargs):
+ """IsSubProperty(self) -> bool"""
+ return _propgrid.PGProperty_IsSubProperty(*args, **kwargs)
+
+ def GetLastVisibleSubItem(*args, **kwargs):
+ """GetLastVisibleSubItem(self) -> PGProperty"""
+ return _propgrid.PGProperty_GetLastVisibleSubItem(*args, **kwargs)
+
+ def GetDefaultValue(*args, **kwargs):
+ """GetDefaultValue(self) -> wxVariant"""
+ return _propgrid.PGProperty_GetDefaultValue(*args, **kwargs)
+
+ def GetMaxLength(*args, **kwargs):
+ """GetMaxLength(self) -> int"""
+ return _propgrid.PGProperty_GetMaxLength(*args, **kwargs)
+
+ def AreAllChildrenSpecified(*args, **kwargs):
+ """AreAllChildrenSpecified(self, wxVariant pendingList=None) -> bool"""
+ return _propgrid.PGProperty_AreAllChildrenSpecified(*args, **kwargs)
+
+ def UpdateParentValues(*args, **kwargs):
+ """UpdateParentValues(self) -> PGProperty"""
+ return _propgrid.PGProperty_UpdateParentValues(*args, **kwargs)
+
+ def UsesAutoUnspecified(*args, **kwargs):
+ """UsesAutoUnspecified(self) -> bool"""
+ return _propgrid.PGProperty_UsesAutoUnspecified(*args, **kwargs)
+
+ def GetValueImage(*args, **kwargs):
+ """GetValueImage(self) -> Bitmap"""
+ return _propgrid.PGProperty_GetValueImage(*args, **kwargs)
+
+ def GetAttribute(*args):
+ """
+ GetAttribute(self, String name) -> wxVariant
+ GetAttribute(self, String name, String defVal) -> String
+ """
+ return _propgrid.PGProperty_GetAttribute(*args)
+
+ def GetAttributeAsLong(*args, **kwargs):
+ """GetAttributeAsLong(self, String name, long defVal) -> long"""
+ return _propgrid.PGProperty_GetAttributeAsLong(*args, **kwargs)
+
+ def GetAttributeAsDouble(*args, **kwargs):
+ """GetAttributeAsDouble(self, String name, double defVal) -> double"""
+ return _propgrid.PGProperty_GetAttributeAsDouble(*args, **kwargs)
+
+ def GetDepth(*args, **kwargs):
+ """GetDepth(self) -> int"""
+ return _propgrid.PGProperty_GetDepth(*args, **kwargs)
+
+ def GetFlagsAsString(*args, **kwargs):
+ """GetFlagsAsString(self, FlagType flagsMask) -> String"""
+ return _propgrid.PGProperty_GetFlagsAsString(*args, **kwargs)
+
+ def GetIndexInParent(*args, **kwargs):
+ """GetIndexInParent(self) -> int"""
+ return _propgrid.PGProperty_GetIndexInParent(*args, **kwargs)
+
+ def Hide(*args, **kwargs):
+ """Hide(self, bool hide, int flags=PG_RECURSE) -> bool"""
+ return _propgrid.PGProperty_Hide(*args, **kwargs)
+
+ def IsExpanded(*args, **kwargs):
+ """IsExpanded(self) -> bool"""
+ return _propgrid.PGProperty_IsExpanded(*args, **kwargs)
+
+ def IsVisible(*args, **kwargs):
+ """IsVisible(self) -> bool"""
+ return _propgrid.PGProperty_IsVisible(*args, **kwargs)
+
+ def IsEnabled(*args, **kwargs):
+ """IsEnabled(self) -> bool"""
+ return _propgrid.PGProperty_IsEnabled(*args, **kwargs)
+
+ def RecreateEditor(*args, **kwargs):
+ """RecreateEditor(self) -> bool"""
+ return _propgrid.PGProperty_RecreateEditor(*args, **kwargs)
+
+ def RefreshEditor(*args, **kwargs):
+ """RefreshEditor(self)"""
+ return _propgrid.PGProperty_RefreshEditor(*args, **kwargs)
+
+ def SetAttribute(*args, **kwargs):
+ """SetAttribute(self, String name, wxVariant value)"""
+ return _propgrid.PGProperty_SetAttribute(*args, **kwargs)
+
+ def SetAttributes(*args, **kwargs):
+ """SetAttributes(self, attributes)"""
+ return _propgrid.PGProperty_SetAttributes(*args, **kwargs)
+
+ def SetAutoUnspecified(*args, **kwargs):
+ """SetAutoUnspecified(self, bool enable=True)"""
+ return _propgrid.PGProperty_SetAutoUnspecified(*args, **kwargs)
+
+ def SetBackgroundColour(*args, **kwargs):
+ """SetBackgroundColour(self, Colour colour, int flags=PG_RECURSE)"""
+ return _propgrid.PGProperty_SetBackgroundColour(*args, **kwargs)
+
+ def SetTextColour(*args, **kwargs):
+ """SetTextColour(self, Colour colour, int flags=PG_RECURSE)"""
+ return _propgrid.PGProperty_SetTextColour(*args, **kwargs)
+
+ def SetDefaultValue(*args, **kwargs):
+ """SetDefaultValue(self, wxVariant value)"""
+ return _propgrid.PGProperty_SetDefaultValue(*args, **kwargs)
+
+ def SetEditor(*args, **kwargs):
+ """SetEditor(self, String editorName)"""
+ return _propgrid.PGProperty_SetEditor(*args, **kwargs)
+
+ def SetCell(*args, **kwargs):
+ """SetCell(self, int column, PGCell cell)"""
+ return _propgrid.PGProperty_SetCell(*args, **kwargs)
+
+ def SetCommonValue(*args, **kwargs):
+ """SetCommonValue(self, int commonValue)"""
+ return _propgrid.PGProperty_SetCommonValue(*args, **kwargs)
+
+ def SetFlagsFromString(*args, **kwargs):
+ """SetFlagsFromString(self, String str)"""
+ return _propgrid.PGProperty_SetFlagsFromString(*args, **kwargs)
+
+ def SetModifiedStatus(*args, **kwargs):
+ """SetModifiedStatus(self, bool modified)"""
+ return _propgrid.PGProperty_SetModifiedStatus(*args, **kwargs)
+
+ def SetValueInEvent(*args, **kwargs):
+ """SetValueInEvent(self, wxVariant value)"""
+ return _propgrid.PGProperty_SetValueInEvent(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, wxVariant value, wxVariant pList=None, int flags=PG_SETVAL_REFRESH_EDITOR)"""
+ return _propgrid.PGProperty_SetValue(*args, **kwargs)
+
+ def SetValueImage(*args, **kwargs):
+ """SetValueImage(self, Bitmap bmp)"""
+ return _propgrid.PGProperty_SetValueImage(*args, **kwargs)
+
+ def SetChoiceSelection(*args, **kwargs):
+ """SetChoiceSelection(self, int newValue)"""
+ return _propgrid.PGProperty_SetChoiceSelection(*args, **kwargs)
+
+ def SetExpanded(*args, **kwargs):
+ """SetExpanded(self, bool expanded)"""
+ return _propgrid.PGProperty_SetExpanded(*args, **kwargs)
+
+ def ChangeFlag(*args, **kwargs):
+ """ChangeFlag(self, int flag, bool set)"""
+ return _propgrid.PGProperty_ChangeFlag(*args, **kwargs)
+
+ def SetFlagRecursively(*args, **kwargs):
+ """SetFlagRecursively(self, int flag, bool set)"""
+ return _propgrid.PGProperty_SetFlagRecursively(*args, **kwargs)
+
+ def SetHelpString(*args, **kwargs):
+ """SetHelpString(self, String helpString)"""
+ return _propgrid.PGProperty_SetHelpString(*args, **kwargs)
+
+ def SetLabel(*args, **kwargs):
+ """SetLabel(self, String label)"""
+ return _propgrid.PGProperty_SetLabel(*args, **kwargs)
+
+ def SetName(*args, **kwargs):
+ """SetName(self, String newName)"""
+ return _propgrid.PGProperty_SetName(*args, **kwargs)
+
+ def SetParentalType(*args, **kwargs):
+ """SetParentalType(self, int flag)"""
+ return _propgrid.PGProperty_SetParentalType(*args, **kwargs)
+
+ def SetValueToUnspecified(*args, **kwargs):
+ """SetValueToUnspecified(self)"""
+ return _propgrid.PGProperty_SetValueToUnspecified(*args, **kwargs)
+
+ def SetValuePlain(*args, **kwargs):
+ """SetValuePlain(self, wxVariant value)"""
+ return _propgrid.PGProperty_SetValuePlain(*args, **kwargs)
+
+ def SetValidator(*args, **kwargs):
+ """SetValidator(self, Validator validator)"""
+ return _propgrid.PGProperty_SetValidator(*args, **kwargs)
+
+ def GetValidator(*args, **kwargs):
+ """GetValidator(self) -> Validator"""
+ return _propgrid.PGProperty_GetValidator(*args, **kwargs)
+
+ def SetMaxLength(*args, **kwargs):
+ """SetMaxLength(self, int maxLen) -> bool"""
+ return _propgrid.PGProperty_SetMaxLength(*args, **kwargs)
+
+ def SetWasModified(*args, **kwargs):
+ """SetWasModified(self, bool set=True)"""
+ return _propgrid.PGProperty_SetWasModified(*args, **kwargs)
+
+ def GetHelpString(*args, **kwargs):
+ """GetHelpString(self) -> String"""
+ return _propgrid.PGProperty_GetHelpString(*args, **kwargs)
+
+ def IsSomeParent(*args, **kwargs):
+ """IsSomeParent(self, PGProperty candidate_parent) -> bool"""
+ return _propgrid.PGProperty_IsSomeParent(*args, **kwargs)
+
+ def AdaptListToValue(*args, **kwargs):
+ """AdaptListToValue(self, wxVariant list, wxVariant value)"""
+ return _propgrid.PGProperty_AdaptListToValue(*args, **kwargs)
+
+ def AddPrivateChild(*args, **kwargs):
+ """AddPrivateChild(self, PGProperty prop)"""
+ return _propgrid.PGProperty_AddPrivateChild(*args, **kwargs)
+
+ def AppendChild(*args, **kwargs):
+ """AppendChild(self, PGProperty prop) -> PGProperty"""
+ return _propgrid.PGProperty_AppendChild(*args, **kwargs)
+
+ def GetChildrenHeight(*args, **kwargs):
+ """GetChildrenHeight(self, int lh, int iMax=-1) -> int"""
+ return _propgrid.PGProperty_GetChildrenHeight(*args, **kwargs)
+
+ def GetChildCount(*args, **kwargs):
+ """GetChildCount(self) -> int"""
+ return _propgrid.PGProperty_GetChildCount(*args, **kwargs)
+
+ def Item(*args, **kwargs):
+ """Item(self, int i) -> PGProperty"""
+ return _propgrid.PGProperty_Item(*args, **kwargs)
+
+ def Last(*args, **kwargs):
+ """Last(self) -> PGProperty"""
+ return _propgrid.PGProperty_Last(*args, **kwargs)
+
+ def Index(*args, **kwargs):
+ """Index(self, PGProperty p) -> int"""
+ return _propgrid.PGProperty_Index(*args, **kwargs)
+
+ def FixIndicesOfChildren(*args, **kwargs):
+ """FixIndicesOfChildren(self, int starthere=0)"""
+ return _propgrid.PGProperty_FixIndicesOfChildren(*args, **kwargs)
+
+ def GetImageOffset(*args, **kwargs):
+ """GetImageOffset(self, int imageWidth) -> int"""
+ return _propgrid.PGProperty_GetImageOffset(*args, **kwargs)
+
+ def GetItemAtY(*args, **kwargs):
+ """GetItemAtY(self, int y) -> PGProperty"""
+ return _propgrid.PGProperty_GetItemAtY(*args, **kwargs)
+
+ def GetPropertyByName(*args, **kwargs):
+ """GetPropertyByName(self, String name) -> PGProperty"""
+ return _propgrid.PGProperty_GetPropertyByName(*args, **kwargs)
+
+ def SetPyChoices(*args):
+ """
+ SetPyChoices(self, PGChoices chs) -> bool
+ SetPyChoices(self, wxArrayString labels, wxArrayInt values=wxArrayInt()) -> bool
+ """
+ return _propgrid.PGProperty_SetPyChoices(*args)
+
+ def PyBase_StringToValue(*args, **kwargs):
+ """PyBase_StringToValue(self, String text, int argFlags=0) -> wxPGVariantAndBool"""
+ return _propgrid.PGProperty_PyBase_StringToValue(*args, **kwargs)
+
+ def PyBase_IntToValue(*args, **kwargs):
+ """PyBase_IntToValue(self, wxVariant value, int number, int argFlags=0) -> wxPGVariantAndBool"""
+ return _propgrid.PGProperty_PyBase_IntToValue(*args, **kwargs)
+
+ m_value = property(GetValuePlain,SetValuePlain)
+ def GetPyClientData(*args, **kwargs):
+ """
+ GetPyClientData(self) -> PyObject
+
+ Returns the client data object for a property
+ """
+ return _propgrid.PGProperty_GetPyClientData(*args, **kwargs)
+
+ def SetPyClientData(*args, **kwargs):
+ """
+ SetPyClientData(self, PyObject clientData)
+
+ Associate the given client data.
+ """
+ return _propgrid.PGProperty_SetPyClientData(*args, **kwargs)
+
+ SetChoices = SetPyChoices
+ StringToValue = PyBase_StringToValue
+ IntToValue = PyBase_IntToValue
+ GetClientObject = GetPyClientData
+ SetClientObject = SetPyClientData
+ GetClientData = GetPyClientData
+ SetClientData = SetPyClientData
+
+_propgrid.PGProperty_swigregister(PGProperty)
+
+class PropertyGridHitTestResult(object):
+ """Proxy of C++ PropertyGridHitTestResult class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PropertyGridHitTestResult"""
+ _propgrid.PropertyGridHitTestResult_swiginit(self,_propgrid.new_PropertyGridHitTestResult(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_PropertyGridHitTestResult
+ __del__ = lambda self : None;
+ def GetColumn(*args, **kwargs):
+ """GetColumn(self) -> int"""
+ return _propgrid.PropertyGridHitTestResult_GetColumn(*args, **kwargs)
+
+ def GetProperty(*args, **kwargs):
+ """GetProperty(self) -> PGProperty"""
+ return _propgrid.PropertyGridHitTestResult_GetProperty(*args, **kwargs)
+
+ def GetSplitter(*args, **kwargs):
+ """GetSplitter(self) -> int"""
+ return _propgrid.PropertyGridHitTestResult_GetSplitter(*args, **kwargs)
+
+ def GetSplitterHitOffset(*args, **kwargs):
+ """GetSplitterHitOffset(self) -> int"""
+ return _propgrid.PropertyGridHitTestResult_GetSplitterHitOffset(*args, **kwargs)
+
+_propgrid.PropertyGridHitTestResult_swigregister(PropertyGridHitTestResult)
+
+PG_ITERATE_PROPERTIES = _propgrid.PG_ITERATE_PROPERTIES
+PG_ITERATE_HIDDEN = _propgrid.PG_ITERATE_HIDDEN
+PG_ITERATE_FIXED_CHILDREN = _propgrid.PG_ITERATE_FIXED_CHILDREN
+PG_ITERATE_CATEGORIES = _propgrid.PG_ITERATE_CATEGORIES
+PG_ITERATE_ALL_PARENTS = _propgrid.PG_ITERATE_ALL_PARENTS
+PG_ITERATE_ALL_PARENTS_RECURSIVELY = _propgrid.PG_ITERATE_ALL_PARENTS_RECURSIVELY
+PG_ITERATOR_FLAGS_ALL = _propgrid.PG_ITERATOR_FLAGS_ALL
+PG_ITERATOR_MASK_OP_ITEM = _propgrid.PG_ITERATOR_MASK_OP_ITEM
+PG_ITERATOR_MASK_OP_PARENT = _propgrid.PG_ITERATOR_MASK_OP_PARENT
+PG_ITERATE_VISIBLE = _propgrid.PG_ITERATE_VISIBLE
+PG_ITERATE_ALL = _propgrid.PG_ITERATE_ALL
+PG_ITERATE_NORMAL = _propgrid.PG_ITERATE_NORMAL
+PG_ITERATE_DEFAULT = _propgrid.PG_ITERATE_DEFAULT
+class PropertyGridIteratorBase(object):
+ """Proxy of C++ PropertyGridIteratorBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PropertyGridIteratorBase"""
+ _propgrid.PropertyGridIteratorBase_swiginit(self,_propgrid.new_PropertyGridIteratorBase(*args, **kwargs))
+ def Assign(*args, **kwargs):
+ """Assign(self, PropertyGridIteratorBase it)"""
+ return _propgrid.PropertyGridIteratorBase_Assign(*args, **kwargs)
+
+ def AtEnd(*args, **kwargs):
+ """AtEnd(self) -> bool"""
+ return _propgrid.PropertyGridIteratorBase_AtEnd(*args, **kwargs)
+
+ def GetProperty(*args, **kwargs):
+ """GetProperty(self) -> PGProperty"""
+ return _propgrid.PropertyGridIteratorBase_GetProperty(*args, **kwargs)
+
+ def Init(*args):
+ """
+ Init(self, state, int flags, PGProperty property, int dir=1)
+ Init(self, state, int flags, int startPos=TOP, int dir=0)
+ """
+ return _propgrid.PropertyGridIteratorBase_Init(*args)
+
+ def Next(*args, **kwargs):
+ """Next(self, bool iterateChildren=True)"""
+ return _propgrid.PropertyGridIteratorBase_Next(*args, **kwargs)
+
+ def Prev(*args, **kwargs):
+ """Prev(self)"""
+ return _propgrid.PropertyGridIteratorBase_Prev(*args, **kwargs)
+
+ def SetBaseParent(*args, **kwargs):
+ """SetBaseParent(self, PGProperty baseParent)"""
+ return _propgrid.PropertyGridIteratorBase_SetBaseParent(*args, **kwargs)
+
+_propgrid.PropertyGridIteratorBase_swigregister(PropertyGridIteratorBase)
+
+class PropertyGridIterator(PropertyGridIteratorBase):
+ """Proxy of C++ PropertyGridIterator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, state, int flags=PG_ITERATE_DEFAULT, PGProperty property=None,
+ int dir=1) -> PropertyGridIterator
+ __init__(self, state, int flags, int startPos, int dir=0) -> PropertyGridIterator
+ __init__(self) -> PropertyGridIterator
+ __init__(self, PropertyGridIterator it) -> PropertyGridIterator
+ """
+ _propgrid.PropertyGridIterator_swiginit(self,_propgrid.new_PropertyGridIterator(*args))
+ __swig_destroy__ = _propgrid.delete_PropertyGridIterator
+ __del__ = lambda self : None;
+ def __ref__(*args, **kwargs):
+ """__ref__(self) -> PGProperty"""
+ return _propgrid.PropertyGridIterator___ref__(*args, **kwargs)
+
+ def OneStep(*args, **kwargs):
+ """
+ OneStep( state, int flags=PG_ITERATE_DEFAULT, PGProperty property=None,
+ int dir=1) -> PGProperty
+ """
+ return _propgrid.PropertyGridIterator_OneStep(*args, **kwargs)
+
+ OneStep = staticmethod(OneStep)
+_propgrid.PropertyGridIterator_swigregister(PropertyGridIterator)
+
+def PropertyGridIterator_OneStep(*args, **kwargs):
+ """
+ PropertyGridIterator_OneStep( state, int flags=PG_ITERATE_DEFAULT, PGProperty property=None,
+ int dir=1) -> PGProperty
+ """
+ return _propgrid.PropertyGridIterator_OneStep(*args, **kwargs)
+
+class PropertyGridConstIterator(PropertyGridIteratorBase):
+ """Proxy of C++ PropertyGridConstIterator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ __swig_destroy__ = _propgrid.delete_PropertyGridConstIterator
+ __del__ = lambda self : None;
+ def __ref__(*args, **kwargs):
+ """__ref__(self) -> PGProperty"""
+ return _propgrid.PropertyGridConstIterator___ref__(*args, **kwargs)
+
+ def OneStep(*args, **kwargs):
+ """
+ OneStep( state, int flags=PG_ITERATE_DEFAULT, PGProperty property=None,
+ int dir=1) -> PGProperty
+ """
+ return _propgrid.PropertyGridConstIterator_OneStep(*args, **kwargs)
+
+ OneStep = staticmethod(OneStep)
+ def __init__(self, *args):
+ """
+ __init__(self, state, int flags=PG_ITERATE_DEFAULT, PGProperty property=None,
+ int dir=1) -> PropertyGridConstIterator
+ __init__(self, state, int flags, int startPos, int dir=0) -> PropertyGridConstIterator
+ __init__(self) -> PropertyGridConstIterator
+ __init__(self, PropertyGridConstIterator it) -> PropertyGridConstIterator
+ __init__(self, PropertyGridIterator other) -> PropertyGridConstIterator
+ """
+ _propgrid.PropertyGridConstIterator_swiginit(self,_propgrid.new_PropertyGridConstIterator(*args))
+_propgrid.PropertyGridConstIterator_swigregister(PropertyGridConstIterator)
+
+def PropertyGridConstIterator_OneStep(*args, **kwargs):
+ """
+ PropertyGridConstIterator_OneStep( state, int flags=PG_ITERATE_DEFAULT, PGProperty property=None,
+ int dir=1) -> PGProperty
+ """
+ return _propgrid.PropertyGridConstIterator_OneStep(*args, **kwargs)
+
+class PGVIteratorBase(_core.RefCounter):
+ """Proxy of C++ PGVIteratorBase class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Next(*args, **kwargs):
+ """Next(self)"""
+ return _propgrid.PGVIteratorBase_Next(*args, **kwargs)
+
+_propgrid.PGVIteratorBase_swigregister(PGVIteratorBase)
+
+class PGVIterator(object):
+ """Proxy of C++ PGVIterator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ __swig_destroy__ = _propgrid.delete_PGVIterator
+ __del__ = lambda self : None;
+ def UnRef(*args, **kwargs):
+ """UnRef(self)"""
+ return _propgrid.PGVIterator_UnRef(*args, **kwargs)
+
+ def __init__(self, *args):
+ """
+ __init__(self) -> PGVIterator
+ __init__(self, PGVIteratorBase obj) -> PGVIterator
+ __init__(self, PGVIterator it) -> PGVIterator
+ """
+ _propgrid.PGVIterator_swiginit(self,_propgrid.new_PGVIterator(*args))
+ def Next(*args, **kwargs):
+ """Next(self)"""
+ return _propgrid.PGVIterator_Next(*args, **kwargs)
+
+ def AtEnd(*args, **kwargs):
+ """AtEnd(self) -> bool"""
+ return _propgrid.PGVIterator_AtEnd(*args, **kwargs)
+
+ def GetProperty(*args, **kwargs):
+ """GetProperty(self) -> PGProperty"""
+ return _propgrid.PGVIterator_GetProperty(*args, **kwargs)
+
+_propgrid.PGVIterator_swigregister(PGVIterator)
+
+
+def PGTypeOperationFailed(*args, **kwargs):
+ """PGTypeOperationFailed(PGProperty p, String typestr, String op)"""
+ return _propgrid.PGTypeOperationFailed(*args, **kwargs)
+
+def PGGetFailed(*args, **kwargs):
+ """PGGetFailed(PGProperty p, String typestr)"""
+ return _propgrid.PGGetFailed(*args, **kwargs)
+class PropertyGridInterface(object):
+ """Proxy of C++ PropertyGridInterface class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _propgrid.delete_PropertyGridInterface
+ __del__ = lambda self : None;
+ def Append(*args, **kwargs):
+ """Append(self, PGProperty property) -> PGProperty"""
+ return _propgrid.PropertyGridInterface_Append(*args, **kwargs)
+
+ def AppendIn(*args, **kwargs):
+ """AppendIn(self, PGPropArg id, PGProperty newproperty) -> PGProperty"""
+ return _propgrid.PropertyGridInterface_AppendIn(*args, **kwargs)
+
+ def BeginAddChildren(*args, **kwargs):
+ """BeginAddChildren(self, PGPropArg id)"""
+ return _propgrid.PropertyGridInterface_BeginAddChildren(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """Clear(self)"""
+ return _propgrid.PropertyGridInterface_Clear(*args, **kwargs)
+
+ def ClearSelection(*args, **kwargs):
+ """ClearSelection(self, bool validation=False) -> bool"""
+ return _propgrid.PropertyGridInterface_ClearSelection(*args, **kwargs)
+
+ def ClearModifiedStatus(*args, **kwargs):
+ """ClearModifiedStatus(self)"""
+ return _propgrid.PropertyGridInterface_ClearModifiedStatus(*args, **kwargs)
+
+ def Collapse(*args, **kwargs):
+ """Collapse(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_Collapse(*args, **kwargs)
+
+ def CollapseAll(*args, **kwargs):
+ """CollapseAll(self) -> bool"""
+ return _propgrid.PropertyGridInterface_CollapseAll(*args, **kwargs)
+
+ def ChangePropertyValue(*args, **kwargs):
+ """ChangePropertyValue(self, PGPropArg id, wxVariant newValue) -> bool"""
+ return _propgrid.PropertyGridInterface_ChangePropertyValue(*args, **kwargs)
+
+ def DeleteProperty(*args, **kwargs):
+ """DeleteProperty(self, PGPropArg id)"""
+ return _propgrid.PropertyGridInterface_DeleteProperty(*args, **kwargs)
+
+ def RemoveProperty(*args, **kwargs):
+ """RemoveProperty(self, PGPropArg id) -> PGProperty"""
+ return _propgrid.PropertyGridInterface_RemoveProperty(*args, **kwargs)
+
+ def DisableProperty(*args, **kwargs):
+ """DisableProperty(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_DisableProperty(*args, **kwargs)
+
+ def EditorValidate(*args, **kwargs):
+ """EditorValidate(self) -> bool"""
+ return _propgrid.PropertyGridInterface_EditorValidate(*args, **kwargs)
+
+ def EnableProperty(*args, **kwargs):
+ """EnableProperty(self, PGPropArg id, bool enable=True) -> bool"""
+ return _propgrid.PropertyGridInterface_EnableProperty(*args, **kwargs)
+
+ def EndAddChildren(*args, **kwargs):
+ """EndAddChildren(self, PGPropArg id)"""
+ return _propgrid.PropertyGridInterface_EndAddChildren(*args, **kwargs)
+
+ def Expand(*args, **kwargs):
+ """Expand(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_Expand(*args, **kwargs)
+
+ def ExpandAll(*args, **kwargs):
+ """ExpandAll(self, bool expand=True) -> bool"""
+ return _propgrid.PropertyGridInterface_ExpandAll(*args, **kwargs)
+
+ def GetFirstChild(*args, **kwargs):
+ """GetFirstChild(self, PGPropArg id) -> PGProperty"""
+ return _propgrid.PropertyGridInterface_GetFirstChild(*args, **kwargs)
+
+ def GetIterator(*args):
+ """
+ GetIterator(self, int flags=PG_ITERATE_DEFAULT, PGProperty firstProp=None) -> PropertyGridIterator
+ GetIterator(self, int flags=PG_ITERATE_DEFAULT, PGProperty firstProp=None) -> PropertyGridConstIterator
+ GetIterator(self, int flags, int startPos) -> PropertyGridIterator
+ GetIterator(self, int flags, int startPos) -> PropertyGridConstIterator
+ """
+ return _propgrid.PropertyGridInterface_GetIterator(*args)
+
+ def GetFirst(*args):
+ """
+ GetFirst(self, int flags=PG_ITERATE_ALL) -> PGProperty
+ GetFirst(self, int flags=PG_ITERATE_ALL) -> PGProperty
+ """
+ return _propgrid.PropertyGridInterface_GetFirst(*args)
+
+ def GetProperty(*args, **kwargs):
+ """GetProperty(self, String name) -> PGProperty"""
+ return _propgrid.PropertyGridInterface_GetProperty(*args, **kwargs)
+
+ def GetPropertyAttributes(*args, **kwargs):
+ """GetPropertyAttributes(self, PGPropArg id)"""
+ return _propgrid.PropertyGridInterface_GetPropertyAttributes(*args, **kwargs)
+
+ def GetPropertiesWithFlag(*args, **kwargs):
+ """
+ GetPropertiesWithFlag(self, wxArrayPGProperty targetArr, FlagType flags, bool inverse=False,
+ int iterFlags=wxPG_ITERATE_PROPERTIES|wxPG_ITERATE_HIDDEN|wxPG_ITERATE_CATEGORIES)
+ """
+ return _propgrid.PropertyGridInterface_GetPropertiesWithFlag(*args, **kwargs)
+
+ def GetPropertyAttribute(*args, **kwargs):
+ """GetPropertyAttribute(self, PGPropArg id, String attrName) -> wxVariant"""
+ return _propgrid.PropertyGridInterface_GetPropertyAttribute(*args, **kwargs)
+
+ def GetPropertyCategory(*args, **kwargs):
+ """GetPropertyCategory(self, PGPropArg id)"""
+ return _propgrid.PropertyGridInterface_GetPropertyCategory(*args, **kwargs)
+
+ def GetPropertyByLabel(*args, **kwargs):
+ """GetPropertyByLabel(self, String label) -> PGProperty"""
+ return _propgrid.PropertyGridInterface_GetPropertyByLabel(*args, **kwargs)
+
+ def GetPropertyByName(*args):
+ """
+ GetPropertyByName(self, String name) -> PGProperty
+ GetPropertyByName(self, String name, String subname) -> PGProperty
+ """
+ return _propgrid.PropertyGridInterface_GetPropertyByName(*args)
+
+ def GetPropertyEditor(*args, **kwargs):
+ """GetPropertyEditor(self, PGPropArg id) -> PGEditor"""
+ return _propgrid.PropertyGridInterface_GetPropertyEditor(*args, **kwargs)
+
+ def GetPropertyHelpString(*args, **kwargs):
+ """GetPropertyHelpString(self, PGPropArg id) -> String"""
+ return _propgrid.PropertyGridInterface_GetPropertyHelpString(*args, **kwargs)
+
+ def GetPropertyImage(*args, **kwargs):
+ """GetPropertyImage(self, PGPropArg id) -> Bitmap"""
+ return _propgrid.PropertyGridInterface_GetPropertyImage(*args, **kwargs)
+
+ def GetPropertyLabel(*args, **kwargs):
+ """GetPropertyLabel(self, PGPropArg id) -> String"""
+ return _propgrid.PropertyGridInterface_GetPropertyLabel(*args, **kwargs)
+
+ def GetPropertyName(*args, **kwargs):
+ """GetPropertyName(self, PGProperty property) -> String"""
+ return _propgrid.PropertyGridInterface_GetPropertyName(*args, **kwargs)
+
+ def GetPropertyParent(*args, **kwargs):
+ """GetPropertyParent(self, PGPropArg id) -> PGProperty"""
+ return _propgrid.PropertyGridInterface_GetPropertyParent(*args, **kwargs)
+
+ def GetPropertyValidator(*args, **kwargs):
+ """GetPropertyValidator(self, PGPropArg id) -> Validator"""
+ return _propgrid.PropertyGridInterface_GetPropertyValidator(*args, **kwargs)
+
+ def GetPropertyValue(*args, **kwargs):
+ """GetPropertyValue(self, PGPropArg id) -> wxVariant"""
+ return _propgrid.PropertyGridInterface_GetPropertyValue(*args, **kwargs)
+
+ def GetPropertyValueAsString(*args, **kwargs):
+ """GetPropertyValueAsString(self, PGPropArg id) -> String"""
+ return _propgrid.PropertyGridInterface_GetPropertyValueAsString(*args, **kwargs)
+
+ def GetPropertyValueAsLong(*args, **kwargs):
+ """GetPropertyValueAsLong(self, PGPropArg id) -> long"""
+ return _propgrid.PropertyGridInterface_GetPropertyValueAsLong(*args, **kwargs)
+
+ def GetPropertyValueAsULong(*args, **kwargs):
+ """GetPropertyValueAsULong(self, PGPropArg id) -> long"""
+ return _propgrid.PropertyGridInterface_GetPropertyValueAsULong(*args, **kwargs)
+
+ def GetPropertyValueAsBool(*args, **kwargs):
+ """GetPropertyValueAsBool(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_GetPropertyValueAsBool(*args, **kwargs)
+
+ def GetPropertyValueAsDouble(*args, **kwargs):
+ """GetPropertyValueAsDouble(self, PGPropArg id) -> double"""
+ return _propgrid.PropertyGridInterface_GetPropertyValueAsDouble(*args, **kwargs)
+
+ def GetPropertyValueAsArrayString(*args, **kwargs):
+ """GetPropertyValueAsArrayString(self, PGPropArg id) -> wxArrayString"""
+ return _propgrid.PropertyGridInterface_GetPropertyValueAsArrayString(*args, **kwargs)
+
+ def GetPropertyValueAsArrayInt(*args, **kwargs):
+ """GetPropertyValueAsArrayInt(self, PGPropArg id) -> wxArrayInt"""
+ return _propgrid.PropertyGridInterface_GetPropertyValueAsArrayInt(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> PGProperty"""
+ return _propgrid.PropertyGridInterface_GetSelection(*args, **kwargs)
+
+ def GetSelectedProperties(*args, **kwargs):
+ """GetSelectedProperties(self) -> wxArrayPGProperty"""
+ return _propgrid.PropertyGridInterface_GetSelectedProperties(*args, **kwargs)
+
+ def GetVIterator(*args, **kwargs):
+ """GetVIterator(self, int flags) -> PGVIterator"""
+ return _propgrid.PropertyGridInterface_GetVIterator(*args, **kwargs)
+
+ def HideProperty(*args, **kwargs):
+ """HideProperty(self, PGPropArg id, bool hide=True, int flags=PG_RECURSE) -> bool"""
+ return _propgrid.PropertyGridInterface_HideProperty(*args, **kwargs)
+
+ def InitAllTypeHandlers(*args, **kwargs):
+ """InitAllTypeHandlers()"""
+ return _propgrid.PropertyGridInterface_InitAllTypeHandlers(*args, **kwargs)
+
+ InitAllTypeHandlers = staticmethod(InitAllTypeHandlers)
+ def Insert(*args):
+ """
+ Insert(self, PGPropArg priorThis, PGProperty newproperty) -> PGProperty
+ Insert(self, PGPropArg parent, int index, PGProperty newproperty) -> PGProperty
+ """
+ return _propgrid.PropertyGridInterface_Insert(*args)
+
+ def IsPropertyCategory(*args, **kwargs):
+ """IsPropertyCategory(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_IsPropertyCategory(*args, **kwargs)
+
+ def IsPropertyEnabled(*args, **kwargs):
+ """IsPropertyEnabled(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_IsPropertyEnabled(*args, **kwargs)
+
+ def IsPropertyExpanded(*args, **kwargs):
+ """IsPropertyExpanded(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_IsPropertyExpanded(*args, **kwargs)
+
+ def IsPropertyModified(*args, **kwargs):
+ """IsPropertyModified(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_IsPropertyModified(*args, **kwargs)
+
+ def IsPropertySelected(*args, **kwargs):
+ """IsPropertySelected(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_IsPropertySelected(*args, **kwargs)
+
+ def IsPropertyShown(*args, **kwargs):
+ """IsPropertyShown(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_IsPropertyShown(*args, **kwargs)
+
+ def IsPropertyValueUnspecified(*args, **kwargs):
+ """IsPropertyValueUnspecified(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridInterface_IsPropertyValueUnspecified(*args, **kwargs)
+
+ def LimitPropertyEditing(*args, **kwargs):
+ """LimitPropertyEditing(self, PGPropArg id, bool limit=True)"""
+ return _propgrid.PropertyGridInterface_LimitPropertyEditing(*args, **kwargs)
+
+ def RefreshGrid(*args, **kwargs):
+ """RefreshGrid(self, state=None)"""
+ return _propgrid.PropertyGridInterface_RefreshGrid(*args, **kwargs)
+
+ def RegisterAdditionalEditors(*args, **kwargs):
+ """RegisterAdditionalEditors()"""
+ return _propgrid.PropertyGridInterface_RegisterAdditionalEditors(*args, **kwargs)
+
+ RegisterAdditionalEditors = staticmethod(RegisterAdditionalEditors)
+ def ReplaceProperty(*args, **kwargs):
+ """ReplaceProperty(self, PGPropArg id, PGProperty property) -> PGProperty"""
+ return _propgrid.PropertyGridInterface_ReplaceProperty(*args, **kwargs)
+
+ SelectionState = _propgrid.PropertyGridInterface_SelectionState
+ ExpandedState = _propgrid.PropertyGridInterface_ExpandedState
+ ScrollPosState = _propgrid.PropertyGridInterface_ScrollPosState
+ PageState = _propgrid.PropertyGridInterface_PageState
+ SplitterPosState = _propgrid.PropertyGridInterface_SplitterPosState
+ DescBoxState = _propgrid.PropertyGridInterface_DescBoxState
+ AllStates = _propgrid.PropertyGridInterface_AllStates
+ def RestoreEditableState(*args, **kwargs):
+ """RestoreEditableState(self, String src, int restoreStates=AllStates) -> bool"""
+ return _propgrid.PropertyGridInterface_RestoreEditableState(*args, **kwargs)
+
+ def SaveEditableState(*args, **kwargs):
+ """SaveEditableState(self, int includedStates=AllStates) -> String"""
+ return _propgrid.PropertyGridInterface_SaveEditableState(*args, **kwargs)
+
+ def SetBoolChoices(*args, **kwargs):
+ """SetBoolChoices(String trueChoice, String falseChoice)"""
+ return _propgrid.PropertyGridInterface_SetBoolChoices(*args, **kwargs)
+
+ SetBoolChoices = staticmethod(SetBoolChoices)
+ def SetColumnProportion(*args, **kwargs):
+ """SetColumnProportion(self, int column, int proportion) -> bool"""
+ return _propgrid.PropertyGridInterface_SetColumnProportion(*args, **kwargs)
+
+ def GetColumnProportion(*args, **kwargs):
+ """GetColumnProportion(self, int column) -> int"""
+ return _propgrid.PropertyGridInterface_GetColumnProportion(*args, **kwargs)
+
+ def SetPropertyAttribute(*args, **kwargs):
+ """SetPropertyAttribute(self, PGPropArg id, String attrName, wxVariant value, long argFlags=0)"""
+ return _propgrid.PropertyGridInterface_SetPropertyAttribute(*args, **kwargs)
+
+ def SetPropertyAttributeAll(*args, **kwargs):
+ """SetPropertyAttributeAll(self, String attrName, wxVariant value)"""
+ return _propgrid.PropertyGridInterface_SetPropertyAttributeAll(*args, **kwargs)
+
+ def SetPropertyBackgroundColour(*args, **kwargs):
+ """SetPropertyBackgroundColour(self, PGPropArg id, Colour colour, int flags=PG_RECURSE)"""
+ return _propgrid.PropertyGridInterface_SetPropertyBackgroundColour(*args, **kwargs)
+
+ def SetPropertyColoursToDefault(*args, **kwargs):
+ """SetPropertyColoursToDefault(self, PGPropArg id)"""
+ return _propgrid.PropertyGridInterface_SetPropertyColoursToDefault(*args, **kwargs)
+
+ def SetPropertyTextColour(*args, **kwargs):
+ """SetPropertyTextColour(self, PGPropArg id, Colour col, int flags=PG_RECURSE)"""
+ return _propgrid.PropertyGridInterface_SetPropertyTextColour(*args, **kwargs)
+
+ def GetPropertyBackgroundColour(*args, **kwargs):
+ """GetPropertyBackgroundColour(self, PGPropArg id) -> Colour"""
+ return _propgrid.PropertyGridInterface_GetPropertyBackgroundColour(*args, **kwargs)
+
+ def GetPropertyTextColour(*args, **kwargs):
+ """GetPropertyTextColour(self, PGPropArg id) -> Colour"""
+ return _propgrid.PropertyGridInterface_GetPropertyTextColour(*args, **kwargs)
+
+ def SetPropertyCell(*args, **kwargs):
+ """
+ SetPropertyCell(self, PGPropArg id, int column, String text=wxEmptyString,
+ Bitmap bitmap=wxNullBitmap, Colour fgCol=wxNullColour,
+ Colour bgCol=wxNullColour)
+ """
+ return _propgrid.PropertyGridInterface_SetPropertyCell(*args, **kwargs)
+
+ def SetPropertyEditor(*args, **kwargs):
+ """SetPropertyEditor(self, PGPropArg id, String editorName)"""
+ return _propgrid.PropertyGridInterface_SetPropertyEditor(*args, **kwargs)
+
+ def SetPropertyLabel(*args, **kwargs):
+ """SetPropertyLabel(self, PGPropArg id, String newproplabel)"""
+ return _propgrid.PropertyGridInterface_SetPropertyLabel(*args, **kwargs)
+
+ def SetPropertyName(*args, **kwargs):
+ """SetPropertyName(self, PGPropArg id, String newName)"""
+ return _propgrid.PropertyGridInterface_SetPropertyName(*args, **kwargs)
+
+ def SetPropertyReadOnly(*args, **kwargs):
+ """SetPropertyReadOnly(self, PGPropArg id, bool set=True, int flags=PG_RECURSE)"""
+ return _propgrid.PropertyGridInterface_SetPropertyReadOnly(*args, **kwargs)
+
+ def SetPropertyValueUnspecified(*args, **kwargs):
+ """SetPropertyValueUnspecified(self, PGPropArg id)"""
+ return _propgrid.PropertyGridInterface_SetPropertyValueUnspecified(*args, **kwargs)
+
+ def SetPropertyHelpString(*args, **kwargs):
+ """SetPropertyHelpString(self, PGPropArg id, String helpString)"""
+ return _propgrid.PropertyGridInterface_SetPropertyHelpString(*args, **kwargs)
+
+ def SetPropertyImage(*args, **kwargs):
+ """SetPropertyImage(self, PGPropArg id, Bitmap bmp)"""
+ return _propgrid.PropertyGridInterface_SetPropertyImage(*args, **kwargs)
+
+ def SetPropertyMaxLength(*args, **kwargs):
+ """SetPropertyMaxLength(self, PGPropArg id, int maxLen) -> bool"""
+ return _propgrid.PropertyGridInterface_SetPropertyMaxLength(*args, **kwargs)
+
+ def SetPropertyValidator(*args, **kwargs):
+ """SetPropertyValidator(self, PGPropArg id, Validator validator)"""
+ return _propgrid.PropertyGridInterface_SetPropertyValidator(*args, **kwargs)
+
+ def SetPropertyValueString(*args, **kwargs):
+ """SetPropertyValueString(self, PGPropArg id, String value)"""
+ return _propgrid.PropertyGridInterface_SetPropertyValueString(*args, **kwargs)
+
+ def SetPropertyValue(*args, **kwargs):
+ """SetPropertyValue(self, PGPropArg id, wxVariant value)"""
+ return _propgrid.PropertyGridInterface_SetPropertyValue(*args, **kwargs)
+
+ def SetValidationFailureBehavior(*args, **kwargs):
+ """SetValidationFailureBehavior(self, int vfbFlags)"""
+ return _propgrid.PropertyGridInterface_SetValidationFailureBehavior(*args, **kwargs)
+
+ def Sort(*args, **kwargs):
+ """Sort(self, int flags=0)"""
+ return _propgrid.PropertyGridInterface_Sort(*args, **kwargs)
+
+ def SortChildren(*args, **kwargs):
+ """SortChildren(self, PGPropArg id, int flags=0)"""
+ return _propgrid.PropertyGridInterface_SortChildren(*args, **kwargs)
+
+ def GetPropertyByNameA(*args, **kwargs):
+ """GetPropertyByNameA(self, String name) -> PGProperty"""
+ return _propgrid.PropertyGridInterface_GetPropertyByNameA(*args, **kwargs)
+
+ def GetEditorByName(*args, **kwargs):
+ """GetEditorByName(String editorName) -> PGEditor"""
+ return _propgrid.PropertyGridInterface_GetEditorByName(*args, **kwargs)
+
+ GetEditorByName = staticmethod(GetEditorByName)
+ def RefreshProperty(*args, **kwargs):
+ """RefreshProperty(self, PGProperty p)"""
+ return _propgrid.PropertyGridInterface_RefreshProperty(*args, **kwargs)
+
+ def MapType(class_,factory):
+ "Registers Python type/class to property mapping.\n\nfactory: "
+ "Property builder function/class."
+ global _type2property
+ try:
+ mappings = _type2property
+ except NameError:
+ raise AssertionError("call only after a propertygrid or "
+ "manager instance constructed")
+
+ mappings[class_] = factory
+
+
+ def DoDefaultTypeMappings(self):
+ "Map built-in properties."
+ global _type2property
+ try:
+ mappings = _type2property
+
+ return
+ except NameError:
+ mappings = {}
+ _type2property = mappings
+
+ mappings[str] = StringProperty
+ mappings[unicode] = StringProperty
+ mappings[int] = IntProperty
+ mappings[float] = FloatProperty
+ mappings[bool] = BoolProperty
+ mappings[list] = ArrayStringProperty
+ mappings[tuple] = ArrayStringProperty
+ mappings[wx.Font] = FontProperty
+ mappings[wx.Colour] = ColourProperty
+ "mappings[wx.Size] = SizeProperty"
+ "mappings[wx.Point] = PointProperty"
+ "mappings[wx.FontData] = FontDataProperty"
+
+ def DoDefaultValueTypeMappings(self):
+ "Map pg value type ids to getter methods."
+ global _vt2getter
+ try:
+ vt2getter = _vt2getter
+
+ return
+ except NameError:
+ vt2getter = {}
+ _vt2getter = vt2getter
+
+ def GetPropertyValues(self,dict_=None, as_strings=False,
+ inc_attributes=False):
+ "Returns values in the grid."
+ ""
+ "dict_: if not given, then a new one is created. dict_ can be"
+ " object as well, in which case it's __dict__ is used."
+ "as_strings: if True, then string representations of values"
+ " are fetched instead of native types. Useful for config and "
+ "such."
+ "inc_attributes: if True, then property attributes are added"
+ " as @<propname>@<attr>."
+ ""
+ "Return value: dictionary with values. It is always a dictionary,"
+ "so if dict_ was object with __dict__ attribute, then that "
+ "attribute is returned."
+
+ if dict_ is None:
+ dict_ = {}
+ elif hasattr(dict_,'__dict__'):
+ dict_ = dict_.__dict__
+
+ if not as_strings:
+ getter = self.GetPropertyValue
+ else:
+ getter = self.GetPropertyValueAsString
+
+ it = self.GetVIterator(PG_ITERATE_PROPERTIES)
+ while not it.AtEnd():
+ p = it.GetProperty()
+ name = p.GetName()
+
+ dict_[name] = getter(p)
+
+ if inc_attributes:
+ attrs = p.GetAttributes()
+ if attrs and len(attrs):
+ dict_['@%s@attr'%name] = attrs
+
+ it.Next()
+
+ return dict_
+
+ GetValues = GetPropertyValues
+
+
+ def SetPropertyValues(self,dict_):
+ "Sets property values from dict_, which can be either\ndictionary "
+ "or an object with __dict__ attribute."
+ ""
+ "autofill: If true, keys with not relevant properties"
+ " are auto-created. For more info, see AutoFill."
+ ""
+ "Notes:"
+ " * Keys starting with underscore are ignored."
+ " * Attributes can be set with entries named @<propname>@<attr>."
+ ""
+
+ autofill = False
+
+ if dict_ is None:
+ dict_ = {}
+ elif hasattr(dict_,'__dict__'):
+ dict_ = dict_.__dict__
+
+ attr_dicts = []
+
+ def set_sub_obj(k0,dict_):
+ for k,v in dict_.iteritems():
+ if k[0] != '_':
+ if k.endswith('@attr'):
+ attr_dicts.append((k[1:-5],v))
+ else:
+ try:
+ self.SetPropertyValue(k,v)
+ except:
+ try:
+ if autofill:
+ self._AutoFillOne(k0,k,v)
+ continue
+ except:
+ if isinstance(v,dict):
+ set_sub_obj(k,v)
+ elif hasattr(v,'__dict__'):
+ set_sub_obj(k,v.__dict__)
+
+
+ for k,v in attr_dicts:
+ p = GetPropertyByName(k)
+ if not p:
+ raise AssertionError("No such property: '%s'"%k)
+ for an,av in v.iteritems():
+ p.SetAttribute(an, av)
+
+
+ cur_page = False
+ is_manager = isinstance(self,PropertyGridManager)
+
+ try:
+ set_sub_obj(self.GetGrid().GetRoot(),dict_)
+ except:
+ import traceback
+ traceback.print_exc()
+
+ self.Refresh()
+
+ SetValues = SetPropertyValues
+
+ def _AutoFillMany(self,cat,dict_):
+ for k,v in dict_.iteritems():
+ self._AutoFillOne(cat,k,v)
+
+
+ def _AutoFillOne(self,cat,k,v):
+ global _type2property
+
+ factory = _type2property.get(v.__class__,None)
+
+ if factory:
+ self.AppendIn( cat, factory(k,k,v) )
+ elif hasattr(v,'__dict__'):
+ cat2 = self.AppendIn( cat, PropertyCategory(k) )
+ self._AutoFillMany(cat2,v.__dict__)
+ elif isinstance(v,dict):
+ cat2 = self.AppendIn( cat, PropertyCategory(k) )
+ self._AutoFillMany(cat2,v)
+ elif not k.startswith('_'):
+ raise AssertionError("member '%s' is of unregisted type/"
+ "class '%s'"%(k,v.__class__))
+
+
+ def AutoFill(self,obj,parent=None):
+ "Clears properties and re-fills to match members and\nvalues of "
+ "given object or dictionary obj."
+
+ self.edited_objects[parent] = obj
+
+ cur_page = False
+ is_manager = isinstance(self,PropertyGridManager)
+
+ if not parent:
+ if is_manager:
+ page = self.GetCurrentPage()
+ page.Clear()
+ parent = page.GetRoot()
+ else:
+ self.Clear()
+ parent = self.GetGrid().GetRoot()
+ else:
+ it = self.GetIterator(PG_ITERATE_PROPERTIES, parent)
+ it.Next() # Skip the parent
+ while not it.AtEnd():
+ p = it.GetProperty()
+ if not p.IsSomeParent(parent):
+ break
+
+ self.DeleteProperty(p)
+
+ name = p.GetName()
+ it.Next()
+
+ if not is_manager or page == self.GetCurrentPage():
+ self.Freeze()
+ cur_page = True
+
+ try:
+ self._AutoFillMany(parent,obj.__dict__)
+ except:
+ import traceback
+ traceback.print_exc()
+
+ if cur_page:
+ self.Thaw()
+
+ def RegisterEditor(self, editor, editorName=None):
+ "Transform class into instance, if necessary."
+ if not isinstance(editor, PGEditor):
+ editor = editor()
+ if not editorName:
+ editorName = editor.__class__.__name__
+ try:
+ self._editor_instances.append(editor)
+ except:
+ self._editor_instances = [editor]
+ RegisterEditor(editor, editorName)
+
+ def GetPropertyClientData(self, p):
+ if isinstance(p, basestring):
+ p = self.GetPropertyByName(p)
+ return p.GetClientData()
+
+ def SetPropertyClientData(self, p, data):
+ if isinstance(p, basestring):
+ p = self.GetPropertyByName(p)
+ return p.SetClientData(data)
+
+ def GetPyIterator(self, flags=PG_ITERATE_DEFAULT,
+ firstProperty=None):
+ """
+ Returns a pythonic property iterator for a single `PropertyGrid`
+ or page in `PropertyGridManager`. Arguments are same as for
+ `GetIterator`. Following example demonstrates iterating absolutely
+ all items in a single grid::
+
+ iterator = propGrid.GetPyIterator(wx.propgrid.PG_ITERATE_ALL)
+ for prop in iterator:
+ print(prop)
+
+ :see: `wx.propgrid.PropertyGridInterface.Properties`
+ `wx.propgrid.PropertyGridInterface.Items`
+ """
+ it = self.GetIterator(flags, firstProperty)
+ while not it.AtEnd():
+ yield it.GetProperty()
+ it.Next()
+
+ def GetPyVIterator(self, flags=PG_ITERATE_DEFAULT):
+ """
+ Returns a pythonic property iterator for a single `PropertyGrid`
+ or entire `PropertyGridManager`. Arguments are same as for
+ `GetIterator`. Following example demonstrates iterating absolutely
+ all items in an entire `PropertyGridManager`::
+
+ iterator = propGridManager.GetPyVIterator(wx.propgrid.PG_ITERATE_ALL)
+ for prop in iterator:
+ print(prop)
+
+ :see: `wx.propgrid.PropertyGridInterface.Properties`
+ `wx.propgrid.PropertyGridInterface.Items`
+ """
+ it = self.GetVIterator(flags)
+ while not it.AtEnd():
+ yield it.GetProperty()
+ it.Next()
+
+ @property
+ def Properties(self):
+ """
+ This attribute is a pythonic iterator over all properties in
+ this `PropertyGrid` property container. It will only skip
+ categories and private child properties. Usage is simple::
+
+ for prop in propGrid.Properties:
+ print(prop)
+
+ :see: `wx.propgrid.PropertyGridInterface.Items`
+ `wx.propgrid.PropertyGridInterface.GetPyIterator`
+ """
+ it = self.GetVIterator(PG_ITERATE_NORMAL)
+ while not it.AtEnd():
+ yield it.GetProperty()
+ it.Next()
+
+ @property
+ def Items(self):
+ """
+ This attribute is a pythonic iterator over all items in this
+ `PropertyGrid` property container, excluding only private child
+ properties. Usage is simple::
+
+ for prop in propGrid.Items:
+ print(prop)
+
+ :see: `wx.propgrid.PropertyGridInterface.Properties`
+ `wx.propgrid.PropertyGridInterface.GetPyIterator`
+ """
+ it = self.GetVIterator(PG_ITERATE_NORMAL | PG_ITERATE_CATEGORIES)
+ while not it.AtEnd():
+ yield it.GetProperty()
+ it.Next()
+
+_propgrid.PropertyGridInterface_swigregister(PropertyGridInterface)
+
+def PropertyGridInterface_InitAllTypeHandlers(*args):
+ """PropertyGridInterface_InitAllTypeHandlers()"""
+ return _propgrid.PropertyGridInterface_InitAllTypeHandlers(*args)
+
+def PropertyGridInterface_RegisterAdditionalEditors(*args):
+ """PropertyGridInterface_RegisterAdditionalEditors()"""
+ return _propgrid.PropertyGridInterface_RegisterAdditionalEditors(*args)
+
+def PropertyGridInterface_SetBoolChoices(*args, **kwargs):
+ """PropertyGridInterface_SetBoolChoices(String trueChoice, String falseChoice)"""
+ return _propgrid.PropertyGridInterface_SetBoolChoices(*args, **kwargs)
+
+def PropertyGridInterface_GetEditorByName(*args, **kwargs):
+ """PropertyGridInterface_GetEditorByName(String editorName) -> PGEditor"""
+ return _propgrid.PropertyGridInterface_GetEditorByName(*args, **kwargs)
+
+PG_AUTO_SORT = _propgrid.PG_AUTO_SORT
+PG_HIDE_CATEGORIES = _propgrid.PG_HIDE_CATEGORIES
+PG_ALPHABETIC_MODE = _propgrid.PG_ALPHABETIC_MODE
+PG_BOLD_MODIFIED = _propgrid.PG_BOLD_MODIFIED
+PG_SPLITTER_AUTO_CENTER = _propgrid.PG_SPLITTER_AUTO_CENTER
+PG_TOOLTIPS = _propgrid.PG_TOOLTIPS
+PG_HIDE_MARGIN = _propgrid.PG_HIDE_MARGIN
+PG_STATIC_SPLITTER = _propgrid.PG_STATIC_SPLITTER
+PG_STATIC_LAYOUT = _propgrid.PG_STATIC_LAYOUT
+PG_LIMITED_EDITING = _propgrid.PG_LIMITED_EDITING
+PG_TOOLBAR = _propgrid.PG_TOOLBAR
+PG_DESCRIPTION = _propgrid.PG_DESCRIPTION
+PG_NO_INTERNAL_BORDER = _propgrid.PG_NO_INTERNAL_BORDER
+PG_EX_INIT_NOCAT = _propgrid.PG_EX_INIT_NOCAT
+PG_EX_NO_FLAT_TOOLBAR = _propgrid.PG_EX_NO_FLAT_TOOLBAR
+PG_EX_MODE_BUTTONS = _propgrid.PG_EX_MODE_BUTTONS
+PG_EX_HELP_AS_TOOLTIPS = _propgrid.PG_EX_HELP_AS_TOOLTIPS
+PG_EX_NATIVE_DOUBLE_BUFFERING = _propgrid.PG_EX_NATIVE_DOUBLE_BUFFERING
+PG_EX_AUTO_UNSPECIFIED_VALUES = _propgrid.PG_EX_AUTO_UNSPECIFIED_VALUES
+PG_EX_WRITEONLY_BUILTIN_ATTRIBUTES = _propgrid.PG_EX_WRITEONLY_BUILTIN_ATTRIBUTES
+PG_EX_HIDE_PAGE_BUTTONS = _propgrid.PG_EX_HIDE_PAGE_BUTTONS
+PG_EX_MULTIPLE_SELECTION = _propgrid.PG_EX_MULTIPLE_SELECTION
+PG_EX_ENABLE_TLP_TRACKING = _propgrid.PG_EX_ENABLE_TLP_TRACKING
+PG_EX_NO_TOOLBAR_DIVIDER = _propgrid.PG_EX_NO_TOOLBAR_DIVIDER
+PG_EX_TOOLBAR_SEPARATOR = _propgrid.PG_EX_TOOLBAR_SEPARATOR
+PG_DEFAULT_STYLE = _propgrid.PG_DEFAULT_STYLE
+PGMAN_DEFAULT_STYLE = _propgrid.PGMAN_DEFAULT_STYLE
+PG_SUBID1 = _propgrid.PG_SUBID1
+PG_SUBID2 = _propgrid.PG_SUBID2
+PG_SUBID_TEMP1 = _propgrid.PG_SUBID_TEMP1
+class PGCommonValue(object):
+ """Proxy of C++ PGCommonValue class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String label, renderer) -> PGCommonValue"""
+ _propgrid.PGCommonValue_swiginit(self,_propgrid.new_PGCommonValue(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_PGCommonValue
+ __del__ = lambda self : None;
+ def GetEditableText(*args, **kwargs):
+ """GetEditableText(self) -> String"""
+ return _propgrid.PGCommonValue_GetEditableText(*args, **kwargs)
+
+ def GetLabel(*args, **kwargs):
+ """GetLabel(self) -> String"""
+ return _propgrid.PGCommonValue_GetLabel(*args, **kwargs)
+
+ def GetRenderer(*args, **kwargs):
+ """GetRenderer(self)"""
+ return _propgrid.PGCommonValue_GetRenderer(*args, **kwargs)
+
+_propgrid.PGCommonValue_swigregister(PGCommonValue)
+
+PG_VFB_STAY_IN_PROPERTY = _propgrid.PG_VFB_STAY_IN_PROPERTY
+PG_VFB_BEEP = _propgrid.PG_VFB_BEEP
+PG_VFB_MARK_CELL = _propgrid.PG_VFB_MARK_CELL
+PG_VFB_SHOW_MESSAGE = _propgrid.PG_VFB_SHOW_MESSAGE
+PG_VFB_SHOW_MESSAGEBOX = _propgrid.PG_VFB_SHOW_MESSAGEBOX
+PG_VFB_SHOW_MESSAGE_ON_STATUSBAR = _propgrid.PG_VFB_SHOW_MESSAGE_ON_STATUSBAR
+PG_VFB_DEFAULT = _propgrid.PG_VFB_DEFAULT
+PG_VFB_UNDEFINED = _propgrid.PG_VFB_UNDEFINED
+class PGValidationInfo(object):
+ """Proxy of C++ PGValidationInfo class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PGValidationInfo"""
+ _propgrid.PGValidationInfo_swiginit(self,_propgrid.new_PGValidationInfo(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_PGValidationInfo
+ __del__ = lambda self : None;
+ def GetFailureBehavior(*args, **kwargs):
+ """GetFailureBehavior(self) -> char"""
+ return _propgrid.PGValidationInfo_GetFailureBehavior(*args, **kwargs)
+
+ def GetFailureMessage(*args, **kwargs):
+ """GetFailureMessage(self) -> String"""
+ return _propgrid.PGValidationInfo_GetFailureMessage(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> wxVariant"""
+ return _propgrid.PGValidationInfo_GetValue(*args, **kwargs)
+
+ def SetFailureBehavior(*args, **kwargs):
+ """SetFailureBehavior(self, char failureBehavior)"""
+ return _propgrid.PGValidationInfo_SetFailureBehavior(*args, **kwargs)
+
+ def SetFailureMessage(*args, **kwargs):
+ """SetFailureMessage(self, String message)"""
+ return _propgrid.PGValidationInfo_SetFailureMessage(*args, **kwargs)
+
+_propgrid.PGValidationInfo_swigregister(PGValidationInfo)
+
+PG_ACTION_INVALID = _propgrid.PG_ACTION_INVALID
+PG_ACTION_NEXT_PROPERTY = _propgrid.PG_ACTION_NEXT_PROPERTY
+PG_ACTION_PREV_PROPERTY = _propgrid.PG_ACTION_PREV_PROPERTY
+PG_ACTION_EXPAND_PROPERTY = _propgrid.PG_ACTION_EXPAND_PROPERTY
+PG_ACTION_COLLAPSE_PROPERTY = _propgrid.PG_ACTION_COLLAPSE_PROPERTY
+PG_ACTION_CANCEL_EDIT = _propgrid.PG_ACTION_CANCEL_EDIT
+PG_ACTION_EDIT = _propgrid.PG_ACTION_EDIT
+PG_ACTION_PRESS_BUTTON = _propgrid.PG_ACTION_PRESS_BUTTON
+PG_ACTION_MAX = _propgrid.PG_ACTION_MAX
+PG_SEL_FOCUS = _propgrid.PG_SEL_FOCUS
+PG_SEL_FORCE = _propgrid.PG_SEL_FORCE
+PG_SEL_NONVISIBLE = _propgrid.PG_SEL_NONVISIBLE
+PG_SEL_NOVALIDATE = _propgrid.PG_SEL_NOVALIDATE
+PG_SEL_DELETING = _propgrid.PG_SEL_DELETING
+PG_SEL_SETUNSPEC = _propgrid.PG_SEL_SETUNSPEC
+PG_SEL_DIALOGVAL = _propgrid.PG_SEL_DIALOGVAL
+PG_SEL_DONT_SEND_EVENT = _propgrid.PG_SEL_DONT_SEND_EVENT
+PG_SEL_NO_REFRESH = _propgrid.PG_SEL_NO_REFRESH
+PG_SPLITTER_REFRESH = _propgrid.PG_SPLITTER_REFRESH
+PG_SPLITTER_ALL_PAGES = _propgrid.PG_SPLITTER_ALL_PAGES
+PG_SPLITTER_FROM_EVENT = _propgrid.PG_SPLITTER_FROM_EVENT
+PG_SPLITTER_FROM_AUTO_CENTER = _propgrid.PG_SPLITTER_FROM_AUTO_CENTER
+PG_FL_INITIALIZED = _propgrid.PG_FL_INITIALIZED
+PG_FL_ACTIVATION_BY_CLICK = _propgrid.PG_FL_ACTIVATION_BY_CLICK
+PG_FL_DONT_CENTER_SPLITTER = _propgrid.PG_FL_DONT_CENTER_SPLITTER
+PG_FL_FOCUSED = _propgrid.PG_FL_FOCUSED
+PG_FL_MOUSE_CAPTURED = _propgrid.PG_FL_MOUSE_CAPTURED
+PG_FL_MOUSE_INSIDE = _propgrid.PG_FL_MOUSE_INSIDE
+PG_FL_VALUE_MODIFIED = _propgrid.PG_FL_VALUE_MODIFIED
+PG_FL_PRIMARY_FILLS_ENTIRE = _propgrid.PG_FL_PRIMARY_FILLS_ENTIRE
+PG_FL_CUR_USES_CUSTOM_IMAGE = _propgrid.PG_FL_CUR_USES_CUSTOM_IMAGE
+PG_FL_CELL_OVERRIDES_SEL = _propgrid.PG_FL_CELL_OVERRIDES_SEL
+PG_FL_SCROLLED = _propgrid.PG_FL_SCROLLED
+PG_FL_ADDING_HIDEABLES = _propgrid.PG_FL_ADDING_HIDEABLES
+PG_FL_NOSTATUSBARHELP = _propgrid.PG_FL_NOSTATUSBARHELP
+PG_FL_CREATEDSTATE = _propgrid.PG_FL_CREATEDSTATE
+PG_FL_SCROLLBAR_DETECTED = _propgrid.PG_FL_SCROLLBAR_DETECTED
+PG_FL_DESC_REFRESH_REQUIRED = _propgrid.PG_FL_DESC_REFRESH_REQUIRED
+PG_FL_IN_MANAGER = _propgrid.PG_FL_IN_MANAGER
+PG_FL_GOOD_SIZE_SET = _propgrid.PG_FL_GOOD_SIZE_SET
+PG_FL_IN_SELECT_PROPERTY = _propgrid.PG_FL_IN_SELECT_PROPERTY
+PG_FL_STRING_IN_STATUSBAR = _propgrid.PG_FL_STRING_IN_STATUSBAR
+PG_FL_CATMODE_AUTO_SORT = _propgrid.PG_FL_CATMODE_AUTO_SORT
+PG_MAN_FL_PAGE_INSERTED = _propgrid.PG_MAN_FL_PAGE_INSERTED
+PG_FL_ABNORMAL_EDITOR = _propgrid.PG_FL_ABNORMAL_EDITOR
+PG_FL_IN_HANDLECUSTOMEDITOREVENT = _propgrid.PG_FL_IN_HANDLECUSTOMEDITOREVENT
+PG_FL_VALUE_CHANGE_IN_EVENT = _propgrid.PG_FL_VALUE_CHANGE_IN_EVENT
+PG_FL_FIXED_WIDTH_EDITOR = _propgrid.PG_FL_FIXED_WIDTH_EDITOR
+PG_FL_HAS_VIRTUAL_WIDTH = _propgrid.PG_FL_HAS_VIRTUAL_WIDTH
+PG_FL_RECALCULATING_VIRTUAL_SIZE = _propgrid.PG_FL_RECALCULATING_VIRTUAL_SIZE
+class PropertyGrid(_core.Control,_windows.ScrollHelper,PropertyGridInterface):
+ """Proxy of C++ PropertyGrid class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=(0),
+ String name=wxPropertyGridNameStr) -> PropertyGrid
+ """
+ _propgrid.PropertyGrid_swiginit(self,_propgrid.new_PropertyGrid(*args, **kwargs))
+
+ self._setOORInfo(self)
+ self.DoDefaultTypeMappings()
+ self.edited_objects = {}
+ self.DoDefaultValueTypeMappings()
+ if not hasattr(self.__class__,'_vt2setter'):
+ self.__class__._vt2setter = {}
+
+
+ __swig_destroy__ = _propgrid.delete_PropertyGrid
+ __del__ = lambda self : None;
+ def AddActionTrigger(*args, **kwargs):
+ """AddActionTrigger(self, int action, int keycode, int modifiers=0)"""
+ return _propgrid.PropertyGrid_AddActionTrigger(*args, **kwargs)
+
+ def DedicateKey(*args, **kwargs):
+ """DedicateKey(self, int keycode)"""
+ return _propgrid.PropertyGrid_DedicateKey(*args, **kwargs)
+
+ def AutoGetTranslation(*args, **kwargs):
+ """AutoGetTranslation(bool enable)"""
+ return _propgrid.PropertyGrid_AutoGetTranslation(*args, **kwargs)
+
+ AutoGetTranslation = staticmethod(AutoGetTranslation)
+ def ChangePropertyValue(*args, **kwargs):
+ """ChangePropertyValue(self, PGPropArg id, wxVariant newValue) -> bool"""
+ return _propgrid.PropertyGrid_ChangePropertyValue(*args, **kwargs)
+
+ def CenterSplitter(*args, **kwargs):
+ """CenterSplitter(self, bool enableAutoResizing=False)"""
+ return _propgrid.PropertyGrid_CenterSplitter(*args, **kwargs)
+
+ def ClearActionTriggers(*args, **kwargs):
+ """ClearActionTriggers(self, int action)"""
+ return _propgrid.PropertyGrid_ClearActionTriggers(*args, **kwargs)
+
+ def CommitChangesFromEditor(*args, **kwargs):
+ """CommitChangesFromEditor(self, int flags=0) -> bool"""
+ return _propgrid.PropertyGrid_CommitChangesFromEditor(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=(0),
+ String name=wxPropertyGridNameStr) -> bool
+ """
+ return _propgrid.PropertyGrid_Create(*args, **kwargs)
+
+ def EditorsValueWasModified(*args, **kwargs):
+ """EditorsValueWasModified(self)"""
+ return _propgrid.PropertyGrid_EditorsValueWasModified(*args, **kwargs)
+
+ def EditorsValueWasNotModified(*args, **kwargs):
+ """EditorsValueWasNotModified(self)"""
+ return _propgrid.PropertyGrid_EditorsValueWasNotModified(*args, **kwargs)
+
+ def EnableCategories(*args, **kwargs):
+ """EnableCategories(self, bool enable) -> bool"""
+ return _propgrid.PropertyGrid_EnableCategories(*args, **kwargs)
+
+ def EnsureVisible(*args, **kwargs):
+ """EnsureVisible(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGrid_EnsureVisible(*args, **kwargs)
+
+ def FitColumns(*args, **kwargs):
+ """FitColumns(self) -> Size"""
+ return _propgrid.PropertyGrid_FitColumns(*args, **kwargs)
+
+ def GetPanel(*args, **kwargs):
+ """GetPanel(self) -> Window"""
+ return _propgrid.PropertyGrid_GetPanel(*args, **kwargs)
+
+ def GetCaptionBackgroundColour(*args, **kwargs):
+ """GetCaptionBackgroundColour(self) -> Colour"""
+ return _propgrid.PropertyGrid_GetCaptionBackgroundColour(*args, **kwargs)
+
+ def GetCaptionFont(*args):
+ """
+ GetCaptionFont(self) -> Font
+ GetCaptionFont(self) -> Font
+ """
+ return _propgrid.PropertyGrid_GetCaptionFont(*args)
+
+ def GetCaptionForegroundColour(*args, **kwargs):
+ """GetCaptionForegroundColour(self) -> Colour"""
+ return _propgrid.PropertyGrid_GetCaptionForegroundColour(*args, **kwargs)
+
+ def GetCellBackgroundColour(*args, **kwargs):
+ """GetCellBackgroundColour(self) -> Colour"""
+ return _propgrid.PropertyGrid_GetCellBackgroundColour(*args, **kwargs)
+
+ def GetCellDisabledTextColour(*args, **kwargs):
+ """GetCellDisabledTextColour(self) -> Colour"""
+ return _propgrid.PropertyGrid_GetCellDisabledTextColour(*args, **kwargs)
+
+ def GetCellTextColour(*args, **kwargs):
+ """GetCellTextColour(self) -> Colour"""
+ return _propgrid.PropertyGrid_GetCellTextColour(*args, **kwargs)
+
+ def GetColumnCount(*args, **kwargs):
+ """GetColumnCount(self) -> int"""
+ return _propgrid.PropertyGrid_GetColumnCount(*args, **kwargs)
+
+ def GetEmptySpaceColour(*args, **kwargs):
+ """GetEmptySpaceColour(self) -> Colour"""
+ return _propgrid.PropertyGrid_GetEmptySpaceColour(*args, **kwargs)
+
+ def GetFontHeight(*args, **kwargs):
+ """GetFontHeight(self) -> int"""
+ return _propgrid.PropertyGrid_GetFontHeight(*args, **kwargs)
+
+ def GetGrid(*args, **kwargs):
+ """GetGrid(self) -> PropertyGrid"""
+ return _propgrid.PropertyGrid_GetGrid(*args, **kwargs)
+
+ def GetImageRect(*args, **kwargs):
+ """GetImageRect(self, PGProperty p, int item) -> Rect"""
+ return _propgrid.PropertyGrid_GetImageRect(*args, **kwargs)
+
+ def GetImageSize(*args, **kwargs):
+ """GetImageSize(self, PGProperty p=None, int item=-1) -> Size"""
+ return _propgrid.PropertyGrid_GetImageSize(*args, **kwargs)
+
+ def GetLastItem(*args):
+ """
+ GetLastItem(self, int flags=PG_ITERATE_DEFAULT) -> PGProperty
+ GetLastItem(self, int flags=PG_ITERATE_DEFAULT) -> PGProperty
+ """
+ return _propgrid.PropertyGrid_GetLastItem(*args)
+
+ def GetLineColour(*args, **kwargs):
+ """GetLineColour(self) -> Colour"""
+ return _propgrid.PropertyGrid_GetLineColour(*args, **kwargs)
+
+ def GetMarginColour(*args, **kwargs):
+ """GetMarginColour(self) -> Colour"""
+ return _propgrid.PropertyGrid_GetMarginColour(*args, **kwargs)
+
+ def GetMarginWidth(*args, **kwargs):
+ """GetMarginWidth(self) -> int"""
+ return _propgrid.PropertyGrid_GetMarginWidth(*args, **kwargs)
+
+ def GetUncommittedPropertyValue(*args, **kwargs):
+ """GetUncommittedPropertyValue(self) -> wxVariant"""
+ return _propgrid.PropertyGrid_GetUncommittedPropertyValue(*args, **kwargs)
+
+ def GetRoot(*args, **kwargs):
+ """GetRoot(self) -> PGProperty"""
+ return _propgrid.PropertyGrid_GetRoot(*args, **kwargs)
+
+ def GetRowHeight(*args, **kwargs):
+ """GetRowHeight(self) -> int"""
+ return _propgrid.PropertyGrid_GetRowHeight(*args, **kwargs)
+
+ def GetSelectedProperty(*args, **kwargs):
+ """GetSelectedProperty(self) -> PGProperty"""
+ return _propgrid.PropertyGrid_GetSelectedProperty(*args, **kwargs)
+
+ def GetSelectionBackgroundColour(*args, **kwargs):
+ """GetSelectionBackgroundColour(self) -> Colour"""
+ return _propgrid.PropertyGrid_GetSelectionBackgroundColour(*args, **kwargs)
+
+ def GetSelectionForegroundColour(*args, **kwargs):
+ """GetSelectionForegroundColour(self) -> Colour"""
+ return _propgrid.PropertyGrid_GetSelectionForegroundColour(*args, **kwargs)
+
+ def GetSplitterPosition(*args, **kwargs):
+ """GetSplitterPosition(self, int splitterIndex=0) -> int"""
+ return _propgrid.PropertyGrid_GetSplitterPosition(*args, **kwargs)
+
+ def GetEditorTextCtrl(*args, **kwargs):
+ """GetEditorTextCtrl(self) -> wxTextCtrl"""
+ return _propgrid.PropertyGrid_GetEditorTextCtrl(*args, **kwargs)
+
+ def GetValidationInfo(*args, **kwargs):
+ """GetValidationInfo(self) -> PGValidationInfo"""
+ return _propgrid.PropertyGrid_GetValidationInfo(*args, **kwargs)
+
+ def GetVerticalSpacing(*args, **kwargs):
+ """GetVerticalSpacing(self) -> int"""
+ return _propgrid.PropertyGrid_GetVerticalSpacing(*args, **kwargs)
+
+ def IsEditorFocused(*args, **kwargs):
+ """IsEditorFocused(self) -> bool"""
+ return _propgrid.PropertyGrid_IsEditorFocused(*args, **kwargs)
+
+ def IsEditorsValueModified(*args, **kwargs):
+ """IsEditorsValueModified(self) -> bool"""
+ return _propgrid.PropertyGrid_IsEditorsValueModified(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(self, Point pt) -> PropertyGridHitTestResult
+
+ Test where the given (in client coords) point lies
+ """
+ return _propgrid.PropertyGrid_HitTest(*args, **kwargs)
+
+ def IsAnyModified(*args, **kwargs):
+ """IsAnyModified(self) -> bool"""
+ return _propgrid.PropertyGrid_IsAnyModified(*args, **kwargs)
+
+ def IsFrozen(*args, **kwargs):
+ """
+ IsFrozen(self) -> bool
+
+ Returns ``True`` if the window has been frozen and not thawed yet.
+
+ :see: `Freeze` and `Thaw`
+ """
+ return _propgrid.PropertyGrid_IsFrozen(*args, **kwargs)
+
+ def OnTLPChanging(*args, **kwargs):
+ """OnTLPChanging(self, Window newTLP)"""
+ return _propgrid.PropertyGrid_OnTLPChanging(*args, **kwargs)
+
+ def ResetColours(*args, **kwargs):
+ """ResetColours(self)"""
+ return _propgrid.PropertyGrid_ResetColours(*args, **kwargs)
+
+ def ResetColumnSizes(*args, **kwargs):
+ """ResetColumnSizes(self, bool enableAutoResizing=False)"""
+ return _propgrid.PropertyGrid_ResetColumnSizes(*args, **kwargs)
+
+ def SelectProperty(*args, **kwargs):
+ """SelectProperty(self, PGPropArg id, bool focus=False) -> bool"""
+ return _propgrid.PropertyGrid_SelectProperty(*args, **kwargs)
+
+ def SetSelection(*args, **kwargs):
+ """SetSelection(self, wxArrayPGProperty newSelection)"""
+ return _propgrid.PropertyGrid_SetSelection(*args, **kwargs)
+
+ def AddToSelection(*args, **kwargs):
+ """AddToSelection(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGrid_AddToSelection(*args, **kwargs)
+
+ def RemoveFromSelection(*args, **kwargs):
+ """RemoveFromSelection(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGrid_RemoveFromSelection(*args, **kwargs)
+
+ def MakeColumnEditable(*args, **kwargs):
+ """MakeColumnEditable(self, int column, bool editable=True)"""
+ return _propgrid.PropertyGrid_MakeColumnEditable(*args, **kwargs)
+
+ def BeginLabelEdit(*args, **kwargs):
+ """BeginLabelEdit(self, int column=0)"""
+ return _propgrid.PropertyGrid_BeginLabelEdit(*args, **kwargs)
+
+ def EndLabelEdit(*args, **kwargs):
+ """EndLabelEdit(self, bool commit=True)"""
+ return _propgrid.PropertyGrid_EndLabelEdit(*args, **kwargs)
+
+ def GetLabelEditor(*args, **kwargs):
+ """GetLabelEditor(self) -> wxTextCtrl"""
+ return _propgrid.PropertyGrid_GetLabelEditor(*args, **kwargs)
+
+ def SetCaptionBackgroundColour(*args, **kwargs):
+ """SetCaptionBackgroundColour(self, Colour col)"""
+ return _propgrid.PropertyGrid_SetCaptionBackgroundColour(*args, **kwargs)
+
+ def SetCaptionTextColour(*args, **kwargs):
+ """SetCaptionTextColour(self, Colour col)"""
+ return _propgrid.PropertyGrid_SetCaptionTextColour(*args, **kwargs)
+
+ def SetCellBackgroundColour(*args, **kwargs):
+ """SetCellBackgroundColour(self, Colour col)"""
+ return _propgrid.PropertyGrid_SetCellBackgroundColour(*args, **kwargs)
+
+ def SetCellDisabledTextColour(*args, **kwargs):
+ """SetCellDisabledTextColour(self, Colour col)"""
+ return _propgrid.PropertyGrid_SetCellDisabledTextColour(*args, **kwargs)
+
+ def SetCellTextColour(*args, **kwargs):
+ """SetCellTextColour(self, Colour col)"""
+ return _propgrid.PropertyGrid_SetCellTextColour(*args, **kwargs)
+
+ def SetColumnCount(*args, **kwargs):
+ """SetColumnCount(self, int colCount)"""
+ return _propgrid.PropertyGrid_SetColumnCount(*args, **kwargs)
+
+ def SetCurrentCategory(*args, **kwargs):
+ """SetCurrentCategory(self, PGPropArg id)"""
+ return _propgrid.PropertyGrid_SetCurrentCategory(*args, **kwargs)
+
+ def SetEmptySpaceColour(*args, **kwargs):
+ """SetEmptySpaceColour(self, Colour col)"""
+ return _propgrid.PropertyGrid_SetEmptySpaceColour(*args, **kwargs)
+
+ def SetLineColour(*args, **kwargs):
+ """SetLineColour(self, Colour col)"""
+ return _propgrid.PropertyGrid_SetLineColour(*args, **kwargs)
+
+ def SetMarginColour(*args, **kwargs):
+ """SetMarginColour(self, Colour col)"""
+ return _propgrid.PropertyGrid_SetMarginColour(*args, **kwargs)
+
+ def SetSelectionBackgroundColour(*args, **kwargs):
+ """SetSelectionBackgroundColour(self, Colour col)"""
+ return _propgrid.PropertyGrid_SetSelectionBackgroundColour(*args, **kwargs)
+
+ def SetSelectionTextColour(*args, **kwargs):
+ """SetSelectionTextColour(self, Colour col)"""
+ return _propgrid.PropertyGrid_SetSelectionTextColour(*args, **kwargs)
+
+ def SetSplitterPosition(*args, **kwargs):
+ """SetSplitterPosition(self, int newXPos, int col=0)"""
+ return _propgrid.PropertyGrid_SetSplitterPosition(*args, **kwargs)
+
+ def SetSortFunction(*args, **kwargs):
+ """SetSortFunction(self, PGSortCallback sortFunction)"""
+ return _propgrid.PropertyGrid_SetSortFunction(*args, **kwargs)
+
+ def GetSortFunction(*args, **kwargs):
+ """GetSortFunction(self) -> PGSortCallback"""
+ return _propgrid.PropertyGrid_GetSortFunction(*args, **kwargs)
+
+ def SetUnspecifiedValueAppearance(*args, **kwargs):
+ """SetUnspecifiedValueAppearance(self, PGCell cell)"""
+ return _propgrid.PropertyGrid_SetUnspecifiedValueAppearance(*args, **kwargs)
+
+ def GetUnspecifiedValueAppearance(*args, **kwargs):
+ """GetUnspecifiedValueAppearance(self) -> PGCell"""
+ return _propgrid.PropertyGrid_GetUnspecifiedValueAppearance(*args, **kwargs)
+
+ def GetUnspecifiedValueText(*args, **kwargs):
+ """GetUnspecifiedValueText(self, int argFlags=0) -> String"""
+ return _propgrid.PropertyGrid_GetUnspecifiedValueText(*args, **kwargs)
+
+ def SetVirtualWidth(*args, **kwargs):
+ """SetVirtualWidth(self, int width)"""
+ return _propgrid.PropertyGrid_SetVirtualWidth(*args, **kwargs)
+
+ def SetSplitterLeft(*args, **kwargs):
+ """SetSplitterLeft(self, bool privateChildrenToo=False)"""
+ return _propgrid.PropertyGrid_SetSplitterLeft(*args, **kwargs)
+
+ def SetVerticalSpacing(*args, **kwargs):
+ """SetVerticalSpacing(self, int vspacing)"""
+ return _propgrid.PropertyGrid_SetVerticalSpacing(*args, **kwargs)
+
+ def ShowPropertyError(*args, **kwargs):
+ """ShowPropertyError(self, PGPropArg id, String msg)"""
+ return _propgrid.PropertyGrid_ShowPropertyError(*args, **kwargs)
+
+ def HasVirtualWidth(*args, **kwargs):
+ """HasVirtualWidth(self) -> bool"""
+ return _propgrid.PropertyGrid_HasVirtualWidth(*args, **kwargs)
+
+ def GetCommonValue(*args, **kwargs):
+ """GetCommonValue(self, int i) -> PGCommonValue"""
+ return _propgrid.PropertyGrid_GetCommonValue(*args, **kwargs)
+
+ def GetCommonValueCount(*args, **kwargs):
+ """GetCommonValueCount(self) -> int"""
+ return _propgrid.PropertyGrid_GetCommonValueCount(*args, **kwargs)
+
+ def GetCommonValueLabel(*args, **kwargs):
+ """GetCommonValueLabel(self, int i) -> String"""
+ return _propgrid.PropertyGrid_GetCommonValueLabel(*args, **kwargs)
+
+ def GetUnspecifiedCommonValue(*args, **kwargs):
+ """GetUnspecifiedCommonValue(self) -> int"""
+ return _propgrid.PropertyGrid_GetUnspecifiedCommonValue(*args, **kwargs)
+
+ def SetUnspecifiedCommonValue(*args, **kwargs):
+ """SetUnspecifiedCommonValue(self, int index)"""
+ return _propgrid.PropertyGrid_SetUnspecifiedCommonValue(*args, **kwargs)
+
+ def GenerateEditorButton(*args, **kwargs):
+ """GenerateEditorButton(self, Point pos, Size sz) -> Window"""
+ return _propgrid.PropertyGrid_GenerateEditorButton(*args, **kwargs)
+
+ def FixPosForTextCtrl(*args, **kwargs):
+ """FixPosForTextCtrl(self, Window ctrl, int forColumn=1, Point offset=wxPoint(0, 0))"""
+ return _propgrid.PropertyGrid_FixPosForTextCtrl(*args, **kwargs)
+
+ def GenerateEditorTextCtrl(*args, **kwargs):
+ """
+ GenerateEditorTextCtrl(self, Point pos, Size sz, String value, Window secondary,
+ int extraStyle=0, int maxLen=0, int forColumn=1) -> Window
+ """
+ return _propgrid.PropertyGrid_GenerateEditorTextCtrl(*args, **kwargs)
+
+ def GenerateEditorTextCtrlAndButton(*args, **kwargs):
+ """
+ GenerateEditorTextCtrlAndButton(self, Point pos, Size sz, Window psecondary, int limited_editing,
+ PGProperty property) -> Window
+ """
+ return _propgrid.PropertyGrid_GenerateEditorTextCtrlAndButton(*args, **kwargs)
+
+ def GetGoodEditorDialogPosition(*args, **kwargs):
+ """GetGoodEditorDialogPosition(self, PGProperty p, Size sz) -> Point"""
+ return _propgrid.PropertyGrid_GetGoodEditorDialogPosition(*args, **kwargs)
+
+ def ExpandEscapeSequences(*args, **kwargs):
+ """ExpandEscapeSequences(String dst_str, String src_str) -> String"""
+ return _propgrid.PropertyGrid_ExpandEscapeSequences(*args, **kwargs)
+
+ ExpandEscapeSequences = staticmethod(ExpandEscapeSequences)
+ def CreateEscapeSequences(*args, **kwargs):
+ """CreateEscapeSequences(String dst_str, String src_str) -> String"""
+ return _propgrid.PropertyGrid_CreateEscapeSequences(*args, **kwargs)
+
+ CreateEscapeSequences = staticmethod(CreateEscapeSequences)
+ def GetPropertyRect(*args, **kwargs):
+ """GetPropertyRect(self, PGProperty p1, PGProperty p2) -> Rect"""
+ return _propgrid.PropertyGrid_GetPropertyRect(*args, **kwargs)
+
+ def GetEditorControl(*args, **kwargs):
+ """GetEditorControl(self) -> Window"""
+ return _propgrid.PropertyGrid_GetEditorControl(*args, **kwargs)
+
+ def GetPrimaryEditor(*args, **kwargs):
+ """GetPrimaryEditor(self) -> Window"""
+ return _propgrid.PropertyGrid_GetPrimaryEditor(*args, **kwargs)
+
+ def GetEditorControlSecondary(*args, **kwargs):
+ """GetEditorControlSecondary(self) -> Window"""
+ return _propgrid.PropertyGrid_GetEditorControlSecondary(*args, **kwargs)
+
+ def RefreshEditor(*args, **kwargs):
+ """RefreshEditor(self)"""
+ return _propgrid.PropertyGrid_RefreshEditor(*args, **kwargs)
+
+ def HandleCustomEditorEvent(*args, **kwargs):
+ """HandleCustomEditorEvent(self, Event event) -> bool"""
+ return _propgrid.PropertyGrid_HandleCustomEditorEvent(*args, **kwargs)
+
+ def GetInternalFlags(*args, **kwargs):
+ """GetInternalFlags(self) -> long"""
+ return _propgrid.PropertyGrid_GetInternalFlags(*args, **kwargs)
+
+ def HasInternalFlag(*args, **kwargs):
+ """HasInternalFlag(self, long flag) -> bool"""
+ return _propgrid.PropertyGrid_HasInternalFlag(*args, **kwargs)
+
+ def SetInternalFlag(*args, **kwargs):
+ """SetInternalFlag(self, long flag)"""
+ return _propgrid.PropertyGrid_SetInternalFlag(*args, **kwargs)
+
+ def ClearInternalFlag(*args, **kwargs):
+ """ClearInternalFlag(self, long flag)"""
+ return _propgrid.PropertyGrid_ClearInternalFlag(*args, **kwargs)
+
+ def DoubleToString(*args, **kwargs):
+ """
+ DoubleToString(String target, double value, int precision, bool removeZeroes,
+ String precTemplate=None) -> String
+ """
+ return _propgrid.PropertyGrid_DoubleToString(*args, **kwargs)
+
+ DoubleToString = staticmethod(DoubleToString)
+ def ValueChangeInEvent(*args, **kwargs):
+ """ValueChangeInEvent(self, wxVariant variant)"""
+ return _propgrid.PropertyGrid_ValueChangeInEvent(*args, **kwargs)
+
+ def WasValueChangedInEvent(*args, **kwargs):
+ """WasValueChangedInEvent(self) -> bool"""
+ return _propgrid.PropertyGrid_WasValueChangedInEvent(*args, **kwargs)
+
+ def IsMainButtonEvent(*args, **kwargs):
+ """IsMainButtonEvent(self, Event event) -> bool"""
+ return _propgrid.PropertyGrid_IsMainButtonEvent(*args, **kwargs)
+
+ def DoHidePropertyError(*args, **kwargs):
+ """DoHidePropertyError(self, PGProperty property)"""
+ return _propgrid.PropertyGrid_DoHidePropertyError(*args, **kwargs)
+
+ def GetSpacingY(*args, **kwargs):
+ """GetSpacingY(self) -> int"""
+ return _propgrid.PropertyGrid_GetSpacingY(*args, **kwargs)
+
+ def SetupTextCtrlValue(*args, **kwargs):
+ """SetupTextCtrlValue(self, String text)"""
+ return _propgrid.PropertyGrid_SetupTextCtrlValue(*args, **kwargs)
+
+ def UnfocusEditor(*args, **kwargs):
+ """UnfocusEditor(self) -> bool"""
+ return _propgrid.PropertyGrid_UnfocusEditor(*args, **kwargs)
+
+ def GetPropertyDefaultCell(*args, **kwargs):
+ """GetPropertyDefaultCell(self) -> PGCell"""
+ return _propgrid.PropertyGrid_GetPropertyDefaultCell(*args, **kwargs)
+
+ def GetCategoryDefaultCell(*args, **kwargs):
+ """GetCategoryDefaultCell(self) -> PGCell"""
+ return _propgrid.PropertyGrid_GetCategoryDefaultCell(*args, **kwargs)
+
+ def GetItemAtY(*args, **kwargs):
+ """GetItemAtY(self, int y) -> PGProperty"""
+ return _propgrid.PropertyGrid_GetItemAtY(*args, **kwargs)
+
+_propgrid.PropertyGrid_swigregister(PropertyGrid)
+
+def PropertyGrid_AutoGetTranslation(*args, **kwargs):
+ """PropertyGrid_AutoGetTranslation(bool enable)"""
+ return _propgrid.PropertyGrid_AutoGetTranslation(*args, **kwargs)
+
+def PropertyGrid_ExpandEscapeSequences(*args, **kwargs):
+ """PropertyGrid_ExpandEscapeSequences(String dst_str, String src_str) -> String"""
+ return _propgrid.PropertyGrid_ExpandEscapeSequences(*args, **kwargs)
+
+def PropertyGrid_CreateEscapeSequences(*args, **kwargs):
+ """PropertyGrid_CreateEscapeSequences(String dst_str, String src_str) -> String"""
+ return _propgrid.PropertyGrid_CreateEscapeSequences(*args, **kwargs)
+
+def PropertyGrid_DoubleToString(*args, **kwargs):
+ """
+ PropertyGrid_DoubleToString(String target, double value, int precision, bool removeZeroes,
+ String precTemplate=None) -> String
+ """
+ return _propgrid.PropertyGrid_DoubleToString(*args, **kwargs)
+
+PG_BASE_EVT_PRE_ID = _propgrid.PG_BASE_EVT_PRE_ID
+wxEVT_PG_SELECTED = _propgrid.wxEVT_PG_SELECTED
+wxEVT_PG_CHANGING = _propgrid.wxEVT_PG_CHANGING
+wxEVT_PG_CHANGED = _propgrid.wxEVT_PG_CHANGED
+wxEVT_PG_HIGHLIGHTED = _propgrid.wxEVT_PG_HIGHLIGHTED
+wxEVT_PG_RIGHT_CLICK = _propgrid.wxEVT_PG_RIGHT_CLICK
+wxEVT_PG_PAGE_CHANGED = _propgrid.wxEVT_PG_PAGE_CHANGED
+wxEVT_PG_ITEM_COLLAPSED = _propgrid.wxEVT_PG_ITEM_COLLAPSED
+wxEVT_PG_ITEM_EXPANDED = _propgrid.wxEVT_PG_ITEM_EXPANDED
+wxEVT_PG_DOUBLE_CLICK = _propgrid.wxEVT_PG_DOUBLE_CLICK
+wxEVT_PG_LABEL_EDIT_BEGIN = _propgrid.wxEVT_PG_LABEL_EDIT_BEGIN
+wxEVT_PG_LABEL_EDIT_ENDING = _propgrid.wxEVT_PG_LABEL_EDIT_ENDING
+wxEVT_PG_COL_BEGIN_DRAG = _propgrid.wxEVT_PG_COL_BEGIN_DRAG
+wxEVT_PG_COL_DRAGGING = _propgrid.wxEVT_PG_COL_DRAGGING
+wxEVT_PG_COL_END_DRAG = _propgrid.wxEVT_PG_COL_END_DRAG
+class PropertyGridEvent(_core.CommandEvent):
+ """Proxy of C++ PropertyGridEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=0, int id=0) -> PropertyGridEvent"""
+ _propgrid.PropertyGridEvent_swiginit(self,_propgrid.new_PropertyGridEvent(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_PropertyGridEvent
+ __del__ = lambda self : None;
+ def GetColumn(*args, **kwargs):
+ """GetColumn(self) -> int"""
+ return _propgrid.PropertyGridEvent_GetColumn(*args, **kwargs)
+
+ def GetMainParent(*args, **kwargs):
+ """GetMainParent(self) -> PGProperty"""
+ return _propgrid.PropertyGridEvent_GetMainParent(*args, **kwargs)
+
+ def GetProperty(*args, **kwargs):
+ """GetProperty(self) -> PGProperty"""
+ return _propgrid.PropertyGridEvent_GetProperty(*args, **kwargs)
+
+ def GetValidationInfo(*args, **kwargs):
+ """GetValidationInfo(self) -> PGValidationInfo"""
+ return _propgrid.PropertyGridEvent_GetValidationInfo(*args, **kwargs)
+
+ def CanVeto(*args, **kwargs):
+ """CanVeto(self) -> bool"""
+ return _propgrid.PropertyGridEvent_CanVeto(*args, **kwargs)
+
+ def Veto(*args, **kwargs):
+ """Veto(self, bool veto=True)"""
+ return _propgrid.PropertyGridEvent_Veto(*args, **kwargs)
+
+ def GetPropertyName(*args, **kwargs):
+ """GetPropertyName(self) -> String"""
+ return _propgrid.PropertyGridEvent_GetPropertyName(*args, **kwargs)
+
+ def GetPropertyValue(*args, **kwargs):
+ """GetPropertyValue(self) -> wxVariant"""
+ return _propgrid.PropertyGridEvent_GetPropertyValue(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> wxVariant"""
+ return _propgrid.PropertyGridEvent_GetValue(*args, **kwargs)
+
+ def SetValidationFailureBehavior(*args, **kwargs):
+ """SetValidationFailureBehavior(self, char flags)"""
+ return _propgrid.PropertyGridEvent_SetValidationFailureBehavior(*args, **kwargs)
+
+ def SetValidationFailureMessage(*args, **kwargs):
+ """SetValidationFailureMessage(self, String message)"""
+ return _propgrid.PropertyGridEvent_SetValidationFailureMessage(*args, **kwargs)
+
+ def SetColumn(*args, **kwargs):
+ """SetColumn(self, int column)"""
+ return _propgrid.PropertyGridEvent_SetColumn(*args, **kwargs)
+
+ def SetCanVeto(*args, **kwargs):
+ """SetCanVeto(self, bool canVeto)"""
+ return _propgrid.PropertyGridEvent_SetCanVeto(*args, **kwargs)
+
+ def WasVetoed(*args, **kwargs):
+ """WasVetoed(self) -> bool"""
+ return _propgrid.PropertyGridEvent_WasVetoed(*args, **kwargs)
+
+ def SetProperty(*args, **kwargs):
+ """SetProperty(self, PGProperty p)"""
+ return _propgrid.PropertyGridEvent_SetProperty(*args, **kwargs)
+
+_propgrid.PropertyGridEvent_swigregister(PropertyGridEvent)
+
+class PropertyGridPopulator(object):
+ """Proxy of C++ PropertyGridPopulator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _propgrid.delete_PropertyGridPopulator
+ __del__ = lambda self : None;
+ def SetState(*args, **kwargs):
+ """SetState(self, state)"""
+ return _propgrid.PropertyGridPopulator_SetState(*args, **kwargs)
+
+ def SetGrid(*args, **kwargs):
+ """SetGrid(self, PropertyGrid pg)"""
+ return _propgrid.PropertyGridPopulator_SetGrid(*args, **kwargs)
+
+ def Add(*args, **kwargs):
+ """
+ Add(self, String propClass, String propLabel, String propName,
+ String propValue, PGChoices pChoices=None) -> PGProperty
+ """
+ return _propgrid.PropertyGridPopulator_Add(*args, **kwargs)
+
+ def AddChildren(*args, **kwargs):
+ """AddChildren(self, PGProperty property)"""
+ return _propgrid.PropertyGridPopulator_AddChildren(*args, **kwargs)
+
+ def AddAttribute(*args, **kwargs):
+ """AddAttribute(self, String name, String type, String value) -> bool"""
+ return _propgrid.PropertyGridPopulator_AddAttribute(*args, **kwargs)
+
+ def DoScanForChildren(*args, **kwargs):
+ """DoScanForChildren(self)"""
+ return _propgrid.PropertyGridPopulator_DoScanForChildren(*args, **kwargs)
+
+ def GetCurParent(*args, **kwargs):
+ """GetCurParent(self) -> PGProperty"""
+ return _propgrid.PropertyGridPopulator_GetCurParent(*args, **kwargs)
+
+ def GetState(*args):
+ """
+ GetState(self)
+ GetState(self)
+ """
+ return _propgrid.PropertyGridPopulator_GetState(*args)
+
+ def ToLongPCT(*args, **kwargs):
+ """ToLongPCT(String s, long pval, long max) -> bool"""
+ return _propgrid.PropertyGridPopulator_ToLongPCT(*args, **kwargs)
+
+ ToLongPCT = staticmethod(ToLongPCT)
+ def ParseChoices(*args, **kwargs):
+ """ParseChoices(self, String choicesString, String idString) -> PGChoices"""
+ return _propgrid.PropertyGridPopulator_ParseChoices(*args, **kwargs)
+
+ def ProcessError(*args, **kwargs):
+ """ProcessError(self, String msg)"""
+ return _propgrid.PropertyGridPopulator_ProcessError(*args, **kwargs)
+
+_propgrid.PropertyGridPopulator_swigregister(PropertyGridPopulator)
+
+def PropertyGridPopulator_ToLongPCT(*args, **kwargs):
+ """PropertyGridPopulator_ToLongPCT(String s, long pval, long max) -> bool"""
+ return _propgrid.PropertyGridPopulator_ToLongPCT(*args, **kwargs)
+
+class PGWindowList(object):
+ """Proxy of C++ PGWindowList class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PGWindowList"""
+ _propgrid.PGWindowList_swiginit(self,_propgrid.new_PGWindowList(*args, **kwargs))
+ def SetSecondary(*args, **kwargs):
+ """SetSecondary(self, Window secondary)"""
+ return _propgrid.PGWindowList_SetSecondary(*args, **kwargs)
+
+ m_primary = property(_propgrid.PGWindowList_m_primary_get, _propgrid.PGWindowList_m_primary_set)
+ m_secondary = property(_propgrid.PGWindowList_m_secondary_get, _propgrid.PGWindowList_m_secondary_set)
+_propgrid.PGWindowList_swigregister(PGWindowList)
+
+class PGEditor(_core.Object):
+ """Proxy of C++ PGEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _propgrid.delete_PGEditor
+ __del__ = lambda self : None;
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _propgrid.PGEditor_GetName(*args, **kwargs)
+
+ def CreateControls(*args, **kwargs):
+ """
+ CreateControls(self, PropertyGrid propgrid, PGProperty property, Point pos,
+ Size size) -> PGWindowList
+ """
+ return _propgrid.PGEditor_CreateControls(*args, **kwargs)
+
+ def UpdateControl(*args, **kwargs):
+ """UpdateControl(self, PGProperty property, Window ctrl)"""
+ return _propgrid.PGEditor_UpdateControl(*args, **kwargs)
+
+ def DrawValue(*args, **kwargs):
+ """DrawValue(self, DC dc, Rect rect, PGProperty property, String text)"""
+ return _propgrid.PGEditor_DrawValue(*args, **kwargs)
+
+ def OnEvent(*args, **kwargs):
+ """
+ OnEvent(self, PropertyGrid propgrid, PGProperty property, Window wnd_primary,
+ Event event) -> bool
+ """
+ return _propgrid.PGEditor_OnEvent(*args, **kwargs)
+
+ def SetControlAppearance(*args, **kwargs):
+ """
+ SetControlAppearance(self, PropertyGrid pg, PGProperty property, Window ctrl,
+ PGCell appearance, PGCell oldAppearance, bool unspecified)
+ """
+ return _propgrid.PGEditor_SetControlAppearance(*args, **kwargs)
+
+ def SetValueToUnspecified(*args, **kwargs):
+ """SetValueToUnspecified(self, PGProperty property, Window ctrl)"""
+ return _propgrid.PGEditor_SetValueToUnspecified(*args, **kwargs)
+
+ def SetControlStringValue(*args, **kwargs):
+ """SetControlStringValue(self, PGProperty property, Window ctrl, String txt)"""
+ return _propgrid.PGEditor_SetControlStringValue(*args, **kwargs)
+
+ def SetControlIntValue(*args, **kwargs):
+ """SetControlIntValue(self, PGProperty property, Window ctrl, int value)"""
+ return _propgrid.PGEditor_SetControlIntValue(*args, **kwargs)
+
+ def InsertItem(*args, **kwargs):
+ """InsertItem(self, Window ctrl, String label, int index) -> int"""
+ return _propgrid.PGEditor_InsertItem(*args, **kwargs)
+
+ def DeleteItem(*args, **kwargs):
+ """DeleteItem(self, Window ctrl, int index)"""
+ return _propgrid.PGEditor_DeleteItem(*args, **kwargs)
+
+ def OnFocus(*args, **kwargs):
+ """OnFocus(self, PGProperty property, Window wnd)"""
+ return _propgrid.PGEditor_OnFocus(*args, **kwargs)
+
+ def CanContainCustomImage(*args, **kwargs):
+ """CanContainCustomImage(self) -> bool"""
+ return _propgrid.PGEditor_CanContainCustomImage(*args, **kwargs)
+
+ m_clientData = property(_propgrid.PGEditor_m_clientData_get, _propgrid.PGEditor_m_clientData_set)
+_propgrid.PGEditor_swigregister(PGEditor)
+
+class PGTextCtrlEditor(PGEditor):
+ """Proxy of C++ PGTextCtrlEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PGTextCtrlEditor"""
+ _propgrid.PGTextCtrlEditor_swiginit(self,_propgrid.new_PGTextCtrlEditor(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_PGTextCtrlEditor
+ __del__ = lambda self : None;
+ def OnTextCtrlEvent(*args, **kwargs):
+ """
+ OnTextCtrlEvent(PropertyGrid propgrid, PGProperty property, Window ctrl,
+ Event event) -> bool
+ """
+ return _propgrid.PGTextCtrlEditor_OnTextCtrlEvent(*args, **kwargs)
+
+ OnTextCtrlEvent = staticmethod(OnTextCtrlEvent)
+ def GetTextCtrlValueFromControl(*args, **kwargs):
+ """GetTextCtrlValueFromControl(wxVariant variant, PGProperty property, Window ctrl) -> bool"""
+ return _propgrid.PGTextCtrlEditor_GetTextCtrlValueFromControl(*args, **kwargs)
+
+ GetTextCtrlValueFromControl = staticmethod(GetTextCtrlValueFromControl)
+_propgrid.PGTextCtrlEditor_swigregister(PGTextCtrlEditor)
+
+def PGTextCtrlEditor_OnTextCtrlEvent(*args, **kwargs):
+ """
+ PGTextCtrlEditor_OnTextCtrlEvent(PropertyGrid propgrid, PGProperty property, Window ctrl,
+ Event event) -> bool
+ """
+ return _propgrid.PGTextCtrlEditor_OnTextCtrlEvent(*args, **kwargs)
+
+def PGTextCtrlEditor_GetTextCtrlValueFromControl(*args, **kwargs):
+ """PGTextCtrlEditor_GetTextCtrlValueFromControl(wxVariant variant, PGProperty property, Window ctrl) -> bool"""
+ return _propgrid.PGTextCtrlEditor_GetTextCtrlValueFromControl(*args, **kwargs)
+
+class PGChoiceEditor(PGEditor):
+ """Proxy of C++ PGChoiceEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PGChoiceEditor"""
+ _propgrid.PGChoiceEditor_swiginit(self,_propgrid.new_PGChoiceEditor(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_PGChoiceEditor
+ __del__ = lambda self : None;
+ def CreateControlsBase(*args, **kwargs):
+ """
+ CreateControlsBase(self, PropertyGrid propgrid, PGProperty property, Point pos,
+ Size sz, long extraStyle) -> Window
+ """
+ return _propgrid.PGChoiceEditor_CreateControlsBase(*args, **kwargs)
+
+_propgrid.PGChoiceEditor_swigregister(PGChoiceEditor)
+
+class PGComboBoxEditor(PGChoiceEditor):
+ """Proxy of C++ PGComboBoxEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PGComboBoxEditor"""
+ _propgrid.PGComboBoxEditor_swiginit(self,_propgrid.new_PGComboBoxEditor(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_PGComboBoxEditor
+ __del__ = lambda self : None;
+_propgrid.PGComboBoxEditor_swigregister(PGComboBoxEditor)
+
+class PGEditorDialogAdapter(_core.Object):
+ """Proxy of C++ PGEditorDialogAdapter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _propgrid.delete_PGEditorDialogAdapter
+ __del__ = lambda self : None;
+ def ShowDialog(*args, **kwargs):
+ """ShowDialog(self, PropertyGrid propGrid, PGProperty property) -> bool"""
+ return _propgrid.PGEditorDialogAdapter_ShowDialog(*args, **kwargs)
+
+ def DoShowDialog(*args, **kwargs):
+ """DoShowDialog(self, PropertyGrid propGrid, PGProperty property) -> bool"""
+ return _propgrid.PGEditorDialogAdapter_DoShowDialog(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, wxVariant value)"""
+ return _propgrid.PGEditorDialogAdapter_SetValue(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> wxVariant"""
+ return _propgrid.PGEditorDialogAdapter_GetValue(*args, **kwargs)
+
+ m_clientData = property(_propgrid.PGEditorDialogAdapter_m_clientData_get, _propgrid.PGEditorDialogAdapter_m_clientData_set)
+_propgrid.PGEditorDialogAdapter_swigregister(PGEditorDialogAdapter)
+
+class PGMultiButton(_core.Window):
+ """Proxy of C++ PGMultiButton class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, PropertyGrid pg, Size sz) -> PGMultiButton"""
+ _propgrid.PGMultiButton_swiginit(self,_propgrid.new_PGMultiButton(*args, **kwargs))
+
+ self._setOORInfo(self)
+
+
+ __swig_destroy__ = _propgrid.delete_PGMultiButton
+ __del__ = lambda self : None;
+ def GetButton(*args):
+ """
+ GetButton(self, int i) -> Window
+ GetButton(self, int i) -> Window
+ """
+ return _propgrid.PGMultiButton_GetButton(*args)
+
+ def GetButtonId(*args, **kwargs):
+ """GetButtonId(self, int i) -> int"""
+ return _propgrid.PGMultiButton_GetButtonId(*args, **kwargs)
+
+ def GetCount(*args, **kwargs):
+ """GetCount(self) -> int"""
+ return _propgrid.PGMultiButton_GetCount(*args, **kwargs)
+
+ def Add(*args, **kwargs):
+ """Add(self, String label, int id=-2)"""
+ return _propgrid.PGMultiButton_Add(*args, **kwargs)
+
+ def GetPrimarySize(*args, **kwargs):
+ """GetPrimarySize(self) -> Size"""
+ return _propgrid.PGMultiButton_GetPrimarySize(*args, **kwargs)
+
+ def Finalize(*args, **kwargs):
+ """Finalize(self, PropertyGrid propGrid, Point pos)"""
+ return _propgrid.PGMultiButton_Finalize(*args, **kwargs)
+
+ def AddBitmapButton(*args, **kwargs):
+ """AddBitmapButton(self, Bitmap bitmap, int id=-2)"""
+ return _propgrid.PGMultiButton_AddBitmapButton(*args, **kwargs)
+
+ def AddButton(self, *args, **kwargs):
+ return self.Add(*args, **kwargs)
+
+_propgrid.PGMultiButton_swigregister(PGMultiButton)
+
+class StringProperty(PGProperty):
+ """Proxy of C++ StringProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> StringProperty
+ """
+ _propgrid.StringProperty_swiginit(self,_propgrid.new_StringProperty(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_StringProperty
+ __del__ = lambda self : None;
+_propgrid.StringProperty_swigregister(StringProperty)
+
+PG_PROPERTY_VALIDATION_ERROR_MESSAGE = _propgrid.PG_PROPERTY_VALIDATION_ERROR_MESSAGE
+PG_PROPERTY_VALIDATION_SATURATE = _propgrid.PG_PROPERTY_VALIDATION_SATURATE
+PG_PROPERTY_VALIDATION_WRAP = _propgrid.PG_PROPERTY_VALIDATION_WRAP
+class NumericPropertyValidator(object):
+ """Proxy of C++ NumericPropertyValidator class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ Signed = _propgrid.NumericPropertyValidator_Signed
+ Unsigned = _propgrid.NumericPropertyValidator_Unsigned
+ Float = _propgrid.NumericPropertyValidator_Float
+ def __init__(self, *args, **kwargs):
+ """__init__(self, int numericType, int base=10) -> NumericPropertyValidator"""
+ _propgrid.NumericPropertyValidator_swiginit(self,_propgrid.new_NumericPropertyValidator(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_NumericPropertyValidator
+ __del__ = lambda self : None;
+ def Validate(*args, **kwargs):
+ """Validate(self, Window parent) -> bool"""
+ return _propgrid.NumericPropertyValidator_Validate(*args, **kwargs)
+
+_propgrid.NumericPropertyValidator_swigregister(NumericPropertyValidator)
+
+class IntProperty(PGProperty):
+ """Proxy of C++ IntProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ __swig_destroy__ = _propgrid.delete_IntProperty
+ __del__ = lambda self : None;
+ def __init__(self, *args):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ long value=0) -> IntProperty
+ __init__(self, String label, String name, wxLongLong value) -> IntProperty
+ """
+ _propgrid.IntProperty_swiginit(self,_propgrid.new_IntProperty(*args))
+ def GetClassValidator(*args, **kwargs):
+ """GetClassValidator() -> Validator"""
+ return _propgrid.IntProperty_GetClassValidator(*args, **kwargs)
+
+ GetClassValidator = staticmethod(GetClassValidator)
+ def DoValidation(*args, **kwargs):
+ """
+ DoValidation(PGProperty property, wxLongLong_t value, PGValidationInfo pValidationInfo,
+ int mode=PG_PROPERTY_VALIDATION_ERROR_MESSAGE) -> bool
+ """
+ return _propgrid.IntProperty_DoValidation(*args, **kwargs)
+
+ DoValidation = staticmethod(DoValidation)
+_propgrid.IntProperty_swigregister(IntProperty)
+
+def IntProperty_GetClassValidator(*args):
+ """IntProperty_GetClassValidator() -> Validator"""
+ return _propgrid.IntProperty_GetClassValidator(*args)
+
+def IntProperty_DoValidation(*args, **kwargs):
+ """
+ IntProperty_DoValidation(PGProperty property, wxLongLong_t value, PGValidationInfo pValidationInfo,
+ int mode=PG_PROPERTY_VALIDATION_ERROR_MESSAGE) -> bool
+ """
+ return _propgrid.IntProperty_DoValidation(*args, **kwargs)
+
+class UIntProperty(PGProperty):
+ """Proxy of C++ UIntProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ __swig_destroy__ = _propgrid.delete_UIntProperty
+ __del__ = lambda self : None;
+ def __init__(self, *args):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ long value=0) -> UIntProperty
+ __init__(self, String label, String name, wxULongLong value) -> UIntProperty
+ """
+ _propgrid.UIntProperty_swiginit(self,_propgrid.new_UIntProperty(*args))
+_propgrid.UIntProperty_swigregister(UIntProperty)
+
+class FloatProperty(PGProperty):
+ """Proxy of C++ FloatProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ double value=0.0) -> FloatProperty
+ """
+ _propgrid.FloatProperty_swiginit(self,_propgrid.new_FloatProperty(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_FloatProperty
+ __del__ = lambda self : None;
+ def DoValidation(*args, **kwargs):
+ """
+ DoValidation(PGProperty property, double value, PGValidationInfo pValidationInfo,
+ int mode=PG_PROPERTY_VALIDATION_ERROR_MESSAGE) -> bool
+ """
+ return _propgrid.FloatProperty_DoValidation(*args, **kwargs)
+
+ DoValidation = staticmethod(DoValidation)
+ def GetClassValidator(*args, **kwargs):
+ """GetClassValidator() -> Validator"""
+ return _propgrid.FloatProperty_GetClassValidator(*args, **kwargs)
+
+ GetClassValidator = staticmethod(GetClassValidator)
+_propgrid.FloatProperty_swigregister(FloatProperty)
+
+def FloatProperty_DoValidation(*args, **kwargs):
+ """
+ FloatProperty_DoValidation(PGProperty property, double value, PGValidationInfo pValidationInfo,
+ int mode=PG_PROPERTY_VALIDATION_ERROR_MESSAGE) -> bool
+ """
+ return _propgrid.FloatProperty_DoValidation(*args, **kwargs)
+
+def FloatProperty_GetClassValidator(*args):
+ """FloatProperty_GetClassValidator() -> Validator"""
+ return _propgrid.FloatProperty_GetClassValidator(*args)
+
+class EnumProperty(PGProperty):
+ """Proxy of C++ EnumProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString labels=wxArrayString(),
+ wxArrayInt values=wxArrayInt(),
+ int value=0) -> EnumProperty
+ """
+ _propgrid.EnumProperty_swiginit(self,_propgrid.new_EnumProperty(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_EnumProperty
+ __del__ = lambda self : None;
+ def GetItemCount(*args, **kwargs):
+ """GetItemCount(self) -> size_t"""
+ return _propgrid.EnumProperty_GetItemCount(*args, **kwargs)
+
+ def GetIndexForValue(*args, **kwargs):
+ """GetIndexForValue(self, int value) -> int"""
+ return _propgrid.EnumProperty_GetIndexForValue(*args, **kwargs)
+
+_propgrid.EnumProperty_swigregister(EnumProperty)
+
+class EditEnumProperty(EnumProperty):
+ """Proxy of C++ EditEnumProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, String label, String name, wxChar labels, long values,
+ String value) -> EditEnumProperty
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString labels=wxArrayString(),
+ wxArrayInt values=wxArrayInt(),
+ String value=wxEmptyString) -> EditEnumProperty
+ __init__(self, String label, String name, PGChoices choices, String value=wxEmptyString) -> EditEnumProperty
+ __init__(self, String label, String name, wxChar labels, long values,
+ PGChoices choicesCache, String value) -> EditEnumProperty
+ """
+ _propgrid.EditEnumProperty_swiginit(self,_propgrid.new_EditEnumProperty(*args))
+ __swig_destroy__ = _propgrid.delete_EditEnumProperty
+ __del__ = lambda self : None;
+_propgrid.EditEnumProperty_swigregister(EditEnumProperty)
+
+class FlagsProperty(PGProperty):
+ """Proxy of C++ FlagsProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString labels=wxArrayString(),
+ wxArrayInt values=wxArrayInt(),
+ int value=0) -> FlagsProperty
+ """
+ _propgrid.FlagsProperty_swiginit(self,_propgrid.new_FlagsProperty(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_FlagsProperty
+ __del__ = lambda self : None;
+ def GetItemCount(*args, **kwargs):
+ """GetItemCount(self) -> size_t"""
+ return _propgrid.FlagsProperty_GetItemCount(*args, **kwargs)
+
+ def GetLabel(*args, **kwargs):
+ """GetLabel(self, size_t ind) -> String"""
+ return _propgrid.FlagsProperty_GetLabel(*args, **kwargs)
+
+_propgrid.FlagsProperty_swigregister(FlagsProperty)
+
+class PGFileDialogAdapter(PGEditorDialogAdapter):
+ """Proxy of C++ PGFileDialogAdapter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+_propgrid.PGFileDialogAdapter_swigregister(PGFileDialogAdapter)
+
+class FileProperty(PGProperty):
+ """Proxy of C++ FileProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> FileProperty
+ """
+ _propgrid.FileProperty_swiginit(self,_propgrid.new_FileProperty(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_FileProperty
+ __del__ = lambda self : None;
+ def GetClassValidator(*args, **kwargs):
+ """GetClassValidator() -> Validator"""
+ return _propgrid.FileProperty_GetClassValidator(*args, **kwargs)
+
+ GetClassValidator = staticmethod(GetClassValidator)
+ def GetFileName(*args, **kwargs):
+ """GetFileName(self) -> wxFileName"""
+ return _propgrid.FileProperty_GetFileName(*args, **kwargs)
+
+_propgrid.FileProperty_swigregister(FileProperty)
+
+def FileProperty_GetClassValidator(*args):
+ """FileProperty_GetClassValidator() -> Validator"""
+ return _propgrid.FileProperty_GetClassValidator(*args)
+
+class PGLongStringDialogAdapter(PGEditorDialogAdapter):
+ """Proxy of C++ PGLongStringDialogAdapter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+_propgrid.PGLongStringDialogAdapter_swigregister(PGLongStringDialogAdapter)
+
+class LongStringProperty(PGProperty):
+ """Proxy of C++ LongStringProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> LongStringProperty
+ """
+ _propgrid.LongStringProperty_swiginit(self,_propgrid.new_LongStringProperty(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_LongStringProperty
+ __del__ = lambda self : None;
+ def OnButtonClick(*args, **kwargs):
+ """OnButtonClick(self, PropertyGrid propgrid, String value) -> bool"""
+ return _propgrid.LongStringProperty_OnButtonClick(*args, **kwargs)
+
+ def DisplayEditorDialog(*args, **kwargs):
+ """DisplayEditorDialog(PGProperty prop, PropertyGrid propGrid, String value) -> bool"""
+ return _propgrid.LongStringProperty_DisplayEditorDialog(*args, **kwargs)
+
+ DisplayEditorDialog = staticmethod(DisplayEditorDialog)
+_propgrid.LongStringProperty_swigregister(LongStringProperty)
+
+def LongStringProperty_DisplayEditorDialog(*args, **kwargs):
+ """LongStringProperty_DisplayEditorDialog(PGProperty prop, PropertyGrid propGrid, String value) -> bool"""
+ return _propgrid.LongStringProperty_DisplayEditorDialog(*args, **kwargs)
+
+class ArrayStringProperty(PGProperty):
+ """Proxy of C++ ArrayStringProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString value=wxArrayString()) -> ArrayStringProperty
+ """
+ _propgrid.ArrayStringProperty_swiginit(self,_propgrid.new_ArrayStringProperty(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_ArrayStringProperty
+ __del__ = lambda self : None;
+ def ConvertArrayToString(*args, **kwargs):
+ """ConvertArrayToString(self, wxArrayString arr, String pString, wxUniChar delimiter)"""
+ return _propgrid.ArrayStringProperty_ConvertArrayToString(*args, **kwargs)
+
+ def OnCustomStringEdit(*args, **kwargs):
+ """OnCustomStringEdit(self, Window parent, String value) -> bool"""
+ return _propgrid.ArrayStringProperty_OnCustomStringEdit(*args, **kwargs)
+
+ def OnButtonClick(*args, **kwargs):
+ """OnButtonClick(self, PropertyGrid propgrid, Window primary, wxChar cbt) -> bool"""
+ return _propgrid.ArrayStringProperty_OnButtonClick(*args, **kwargs)
+
+ Escape = _propgrid.ArrayStringProperty_Escape
+ QuoteStrings = _propgrid.ArrayStringProperty_QuoteStrings
+ def ArrayStringToString(*args, **kwargs):
+ """
+ ArrayStringToString(String dst, wxArrayString src, wxUniChar delimiter,
+ int flags)
+ """
+ return _propgrid.ArrayStringProperty_ArrayStringToString(*args, **kwargs)
+
+ ArrayStringToString = staticmethod(ArrayStringToString)
+_propgrid.ArrayStringProperty_swigregister(ArrayStringProperty)
+
+def ArrayStringProperty_ArrayStringToString(*args, **kwargs):
+ """
+ ArrayStringProperty_ArrayStringToString(String dst, wxArrayString src, wxUniChar delimiter,
+ int flags)
+ """
+ return _propgrid.ArrayStringProperty_ArrayStringToString(*args, **kwargs)
+
+class PGArrayEditorDialog(_windows.Dialog):
+ """Proxy of C++ PGArrayEditorDialog class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _propgrid.delete_PGArrayEditorDialog
+ __del__ = lambda self : None;
+ def Init(*args, **kwargs):
+ """Init(self)"""
+ return _propgrid.PGArrayEditorDialog_Init(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, String message, String caption, long style=(wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxOK|wxCANCEL|wxCENTRE),
+ Point pos=DefaultPosition,
+ Size sz=DefaultSize) -> bool
+ """
+ return _propgrid.PGArrayEditorDialog_Create(*args, **kwargs)
+
+ def EnableCustomNewAction(*args, **kwargs):
+ """EnableCustomNewAction(self)"""
+ return _propgrid.PGArrayEditorDialog_EnableCustomNewAction(*args, **kwargs)
+
+ def SetDialogValue(*args, **kwargs):
+ """SetDialogValue(self, wxVariant value)"""
+ return _propgrid.PGArrayEditorDialog_SetDialogValue(*args, **kwargs)
+
+ def GetDialogValue(*args, **kwargs):
+ """GetDialogValue(self) -> wxVariant"""
+ return _propgrid.PGArrayEditorDialog_GetDialogValue(*args, **kwargs)
+
+ def GetTextCtrlValidator(*args, **kwargs):
+ """GetTextCtrlValidator(self) -> Validator"""
+ return _propgrid.PGArrayEditorDialog_GetTextCtrlValidator(*args, **kwargs)
+
+ def IsModified(*args, **kwargs):
+ """IsModified(self) -> bool"""
+ return _propgrid.PGArrayEditorDialog_IsModified(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> int"""
+ return _propgrid.PGArrayEditorDialog_GetSelection(*args, **kwargs)
+
+ def OnAddClick(*args, **kwargs):
+ """OnAddClick(self, CommandEvent event)"""
+ return _propgrid.PGArrayEditorDialog_OnAddClick(*args, **kwargs)
+
+ def OnDeleteClick(*args, **kwargs):
+ """OnDeleteClick(self, CommandEvent event)"""
+ return _propgrid.PGArrayEditorDialog_OnDeleteClick(*args, **kwargs)
+
+ def OnUpClick(*args, **kwargs):
+ """OnUpClick(self, CommandEvent event)"""
+ return _propgrid.PGArrayEditorDialog_OnUpClick(*args, **kwargs)
+
+ def OnDownClick(*args, **kwargs):
+ """OnDownClick(self, CommandEvent event)"""
+ return _propgrid.PGArrayEditorDialog_OnDownClick(*args, **kwargs)
+
+ def OnEndLabelEdit(*args, **kwargs):
+ """OnEndLabelEdit(self, ListEvent event)"""
+ return _propgrid.PGArrayEditorDialog_OnEndLabelEdit(*args, **kwargs)
+
+ def OnIdle(*args, **kwargs):
+ """OnIdle(self, IdleEvent event)"""
+ return _propgrid.PGArrayEditorDialog_OnIdle(*args, **kwargs)
+
+_propgrid.PGArrayEditorDialog_swigregister(PGArrayEditorDialog)
+
+class PGArrayStringEditorDialog(PGArrayEditorDialog):
+ """Proxy of C++ PGArrayStringEditorDialog class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PGArrayStringEditorDialog"""
+ _propgrid.PGArrayStringEditorDialog_swiginit(self,_propgrid.new_PGArrayStringEditorDialog(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_PGArrayStringEditorDialog
+ __del__ = lambda self : None;
+ def Init(*args, **kwargs):
+ """Init(self)"""
+ return _propgrid.PGArrayStringEditorDialog_Init(*args, **kwargs)
+
+ def SetCustomButton(*args, **kwargs):
+ """SetCustomButton(self, String custBtText, ArrayStringProperty pcc)"""
+ return _propgrid.PGArrayStringEditorDialog_SetCustomButton(*args, **kwargs)
+
+ def OnCustomNewAction(*args, **kwargs):
+ """OnCustomNewAction(self, String resString) -> bool"""
+ return _propgrid.PGArrayStringEditorDialog_OnCustomNewAction(*args, **kwargs)
+
+_propgrid.PGArrayStringEditorDialog_swigregister(PGArrayStringEditorDialog)
+
+PG_COLOUR_WEB_BASE = _propgrid.PG_COLOUR_WEB_BASE
+PG_COLOUR_CUSTOM = _propgrid.PG_COLOUR_CUSTOM
+PG_COLOUR_UNSPECIFIED = _propgrid.PG_COLOUR_UNSPECIFIED
+class ColourPropertyValue(_core.Object):
+ """Proxy of C++ ColourPropertyValue class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ m_type = property(_propgrid.ColourPropertyValue_m_type_get, _propgrid.ColourPropertyValue_m_type_set)
+ m_colour = property(_propgrid.ColourPropertyValue_m_colour_get, _propgrid.ColourPropertyValue_m_colour_set)
+ __swig_destroy__ = _propgrid.delete_ColourPropertyValue
+ __del__ = lambda self : None;
+ def Init(*args, **kwargs):
+ """Init(self, int type, Colour colour)"""
+ return _propgrid.ColourPropertyValue_Init(*args, **kwargs)
+
+ def __init__(self, *args):
+ """
+ __init__(self) -> ColourPropertyValue
+ __init__(self, ColourPropertyValue v) -> ColourPropertyValue
+ __init__(self, Colour colour) -> ColourPropertyValue
+ __init__(self, int type) -> ColourPropertyValue
+ __init__(self, int type, Colour colour) -> ColourPropertyValue
+ """
+ _propgrid.ColourPropertyValue_swiginit(self,_propgrid.new_ColourPropertyValue(*args))
+_propgrid.ColourPropertyValue_swigregister(ColourPropertyValue)
+
+class FontProperty(PGProperty):
+ """Proxy of C++ FontProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ Font value=wxFont()) -> FontProperty
+ """
+ _propgrid.FontProperty_swiginit(self,_propgrid.new_FontProperty(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_FontProperty
+ __del__ = lambda self : None;
+_propgrid.FontProperty_swigregister(FontProperty)
+
+class SystemColourProperty(EnumProperty):
+ """Proxy of C++ SystemColourProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ ColourPropertyValue value=wxColourPropertyValue()) -> SystemColourProperty
+ """
+ _propgrid.SystemColourProperty_swiginit(self,_propgrid.new_SystemColourProperty(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_SystemColourProperty
+ __del__ = lambda self : None;
+ def ColourToString(*args, **kwargs):
+ """ColourToString(self, Colour col, int index, int argFlags=0) -> String"""
+ return _propgrid.SystemColourProperty_ColourToString(*args, **kwargs)
+
+ def GetCustomColourIndex(*args, **kwargs):
+ """GetCustomColourIndex(self) -> int"""
+ return _propgrid.SystemColourProperty_GetCustomColourIndex(*args, **kwargs)
+
+ def QueryColourFromUser(*args, **kwargs):
+ """QueryColourFromUser(self, wxVariant variant) -> bool"""
+ return _propgrid.SystemColourProperty_QueryColourFromUser(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """GetColour(self, int index) -> Colour"""
+ return _propgrid.SystemColourProperty_GetColour(*args, **kwargs)
+
+ def GetVal(*args, **kwargs):
+ """GetVal(self, wxVariant pVariant=None) -> ColourPropertyValue"""
+ return _propgrid.SystemColourProperty_GetVal(*args, **kwargs)
+
+_propgrid.SystemColourProperty_swigregister(SystemColourProperty)
+
+class ColourProperty(SystemColourProperty):
+ """Proxy of C++ ColourProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ Colour value=*wxWHITE) -> ColourProperty
+ """
+ _propgrid.ColourProperty_swiginit(self,_propgrid.new_ColourProperty(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_ColourProperty
+ __del__ = lambda self : None;
+_propgrid.ColourProperty_swigregister(ColourProperty)
+
+class PropertyGridPage(_core.EvtHandler,PropertyGridInterface,):
+ """Proxy of C++ PropertyGridPage class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PropertyGridPage"""
+ _propgrid.PropertyGridPage_swiginit(self,_propgrid.new_PropertyGridPage(*args, **kwargs))
+ __swig_destroy__ = _propgrid.delete_PropertyGridPage
+ __del__ = lambda self : None;
+ def FitColumns(*args, **kwargs):
+ """FitColumns(self) -> Size"""
+ return _propgrid.PropertyGridPage_FitColumns(*args, **kwargs)
+
+ def GetIndex(*args, **kwargs):
+ """GetIndex(self) -> int"""
+ return _propgrid.PropertyGridPage_GetIndex(*args, **kwargs)
+
+ def GetSplitterPosition(*args, **kwargs):
+ """GetSplitterPosition(self, int col=0) -> int"""
+ return _propgrid.PropertyGridPage_GetSplitterPosition(*args, **kwargs)
+
+ def GetRoot(*args, **kwargs):
+ """GetRoot(self) -> PGProperty"""
+ return _propgrid.PropertyGridPage_GetRoot(*args, **kwargs)
+
+ def GetStatePtr(*args):
+ """
+ GetStatePtr(self)
+ GetStatePtr(self)
+ """
+ return _propgrid.PropertyGridPage_GetStatePtr(*args)
+
+ def GetToolId(*args, **kwargs):
+ """GetToolId(self) -> int"""
+ return _propgrid.PropertyGridPage_GetToolId(*args, **kwargs)
+
+ def Init(*args, **kwargs):
+ """Init(self)"""
+ return _propgrid.PropertyGridPage_Init(*args, **kwargs)
+
+ def IsHandlingAllEvents(*args, **kwargs):
+ """IsHandlingAllEvents(self) -> bool"""
+ return _propgrid.PropertyGridPage_IsHandlingAllEvents(*args, **kwargs)
+
+ def OnShow(*args, **kwargs):
+ """OnShow(self)"""
+ return _propgrid.PropertyGridPage_OnShow(*args, **kwargs)
+
+ def SetSplitterPosition(*args, **kwargs):
+ """SetSplitterPosition(self, int splitterPos, int col=0)"""
+ return _propgrid.PropertyGridPage_SetSplitterPosition(*args, **kwargs)
+
+_propgrid.PropertyGridPage_swigregister(PropertyGridPage)
+
+class PropertyGridManager(_windows.Panel,PropertyGridInterface):
+ """Proxy of C++ PropertyGridManager class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=(0),
+ String name=wxPropertyGridManagerNameStr) -> PropertyGridManager
+ """
+ _propgrid.PropertyGridManager_swiginit(self,_propgrid.new_PropertyGridManager(*args, **kwargs))
+
+ self._setOORInfo(self)
+ self.DoDefaultTypeMappings()
+ self.edited_objects = {}
+ self.DoDefaultValueTypeMappings()
+ if not hasattr(self.__class__,'_vt2setter'):
+ self.__class__._vt2setter = {}
+
+
+ __swig_destroy__ = _propgrid.delete_PropertyGridManager
+ __del__ = lambda self : None;
+ def AddPage(*args, **kwargs):
+ """
+ AddPage(self, String label=wxEmptyString, Bitmap bmp=wxNullBitmap,
+ PropertyGridPage pageObj=None) -> PropertyGridPage
+ """
+ return _propgrid.PropertyGridManager_AddPage(*args, **kwargs)
+
+ def ClearPage(*args, **kwargs):
+ """ClearPage(self, int page)"""
+ return _propgrid.PropertyGridManager_ClearPage(*args, **kwargs)
+
+ def CommitChangesFromEditor(*args, **kwargs):
+ """CommitChangesFromEditor(self, int flags=0) -> bool"""
+ return _propgrid.PropertyGridManager_CommitChangesFromEditor(*args, **kwargs)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=(0),
+ String name=wxPropertyGridManagerNameStr) -> bool
+ """
+ return _propgrid.PropertyGridManager_Create(*args, **kwargs)
+
+ def EnableCategories(*args, **kwargs):
+ """EnableCategories(self, bool enable) -> bool"""
+ return _propgrid.PropertyGridManager_EnableCategories(*args, **kwargs)
+
+ def EnsureVisible(*args, **kwargs):
+ """EnsureVisible(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridManager_EnsureVisible(*args, **kwargs)
+
+ def GetColumnCount(*args, **kwargs):
+ """GetColumnCount(self, int page=-1) -> int"""
+ return _propgrid.PropertyGridManager_GetColumnCount(*args, **kwargs)
+
+ def GetDescBoxHeight(*args, **kwargs):
+ """GetDescBoxHeight(self) -> int"""
+ return _propgrid.PropertyGridManager_GetDescBoxHeight(*args, **kwargs)
+
+ def GetGrid(*args):
+ """
+ GetGrid(self) -> PropertyGrid
+ GetGrid(self) -> PropertyGrid
+ """
+ return _propgrid.PropertyGridManager_GetGrid(*args)
+
+ def GetIterator(*args):
+ """
+ GetIterator(self, int flags=PG_ITERATE_DEFAULT, PGProperty firstProp=None) -> PropertyGridIterator
+ GetIterator(self, int flags=PG_ITERATE_DEFAULT, PGProperty firstProp=None) -> PropertyGridConstIterator
+ GetIterator(self, int flags, int startPos) -> PropertyGridIterator
+ GetIterator(self, int flags, int startPos) -> PropertyGridConstIterator
+ """
+ return _propgrid.PropertyGridManager_GetIterator(*args)
+
+ def GetCurrentPage(*args, **kwargs):
+ """GetCurrentPage(self) -> PropertyGridPage"""
+ return _propgrid.PropertyGridManager_GetCurrentPage(*args, **kwargs)
+
+ def GetPage(*args):
+ """
+ GetPage(self, int ind) -> PropertyGridPage
+ GetPage(self, String name) -> PropertyGridPage
+ """
+ return _propgrid.PropertyGridManager_GetPage(*args)
+
+ def GetPageByName(*args, **kwargs):
+ """GetPageByName(self, String name) -> int"""
+ return _propgrid.PropertyGridManager_GetPageByName(*args, **kwargs)
+
+ def GetPageByState(*args, **kwargs):
+ """GetPageByState(self, pstate) -> int"""
+ return _propgrid.PropertyGridManager_GetPageByState(*args, **kwargs)
+
+ def GetPageCount(*args, **kwargs):
+ """GetPageCount(self) -> size_t"""
+ return _propgrid.PropertyGridManager_GetPageCount(*args, **kwargs)
+
+ def GetPageName(*args, **kwargs):
+ """GetPageName(self, int index) -> String"""
+ return _propgrid.PropertyGridManager_GetPageName(*args, **kwargs)
+
+ def GetPageRoot(*args, **kwargs):
+ """GetPageRoot(self, int index) -> PGProperty"""
+ return _propgrid.PropertyGridManager_GetPageRoot(*args, **kwargs)
+
+ def GetSelectedPage(*args, **kwargs):
+ """GetSelectedPage(self) -> int"""
+ return _propgrid.PropertyGridManager_GetSelectedPage(*args, **kwargs)
+
+ def GetSelectedProperty(*args, **kwargs):
+ """GetSelectedProperty(self) -> PGProperty"""
+ return _propgrid.PropertyGridManager_GetSelectedProperty(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> PGProperty"""
+ return _propgrid.PropertyGridManager_GetSelection(*args, **kwargs)
+
+ def GetToolBar(*args, **kwargs):
+ """GetToolBar(self) -> wxToolBar"""
+ return _propgrid.PropertyGridManager_GetToolBar(*args, **kwargs)
+
+ def InsertPage(*args, **kwargs):
+ """InsertPage(self, int index, String label, Bitmap bmp=wxNullBitmap, PropertyGridPage pageObj=None) -> PropertyGridPage"""
+ return _propgrid.PropertyGridManager_InsertPage(*args, **kwargs)
+
+ def IsAnyModified(*args, **kwargs):
+ """IsAnyModified(self) -> bool"""
+ return _propgrid.PropertyGridManager_IsAnyModified(*args, **kwargs)
+
+ def IsFrozen(*args, **kwargs):
+ """
+ IsFrozen(self) -> bool
+
+ Returns ``True`` if the window has been frozen and not thawed yet.
+
+ :see: `Freeze` and `Thaw`
+ """
+ return _propgrid.PropertyGridManager_IsFrozen(*args, **kwargs)
+
+ def IsPageModified(*args, **kwargs):
+ """IsPageModified(self, size_t index) -> bool"""
+ return _propgrid.PropertyGridManager_IsPageModified(*args, **kwargs)
+
+ def IsPropertySelected(*args, **kwargs):
+ """IsPropertySelected(self, PGPropArg id) -> bool"""
+ return _propgrid.PropertyGridManager_IsPropertySelected(*args, **kwargs)
+
+ def RemovePage(*args, **kwargs):
+ """RemovePage(self, int page) -> bool"""
+ return _propgrid.PropertyGridManager_RemovePage(*args, **kwargs)
+
+ def SelectPage(*args):
+ """
+ SelectPage(self, int index)
+ SelectPage(self, String label)
+ SelectPage(self, PropertyGridPage ptr)
+ """
+ return _propgrid.PropertyGridManager_SelectPage(*args)
+
+ def SelectProperty(*args, **kwargs):
+ """SelectProperty(self, PGPropArg id, bool focus=False) -> bool"""
+ return _propgrid.PropertyGridManager_SelectProperty(*args, **kwargs)
+
+ def SetColumnTitle(*args, **kwargs):
+ """SetColumnTitle(self, int idx, String title)"""
+ return _propgrid.PropertyGridManager_SetColumnTitle(*args, **kwargs)
+
+ def SetColumnCount(*args, **kwargs):
+ """SetColumnCount(self, int colCount, int page=-1)"""
+ return _propgrid.PropertyGridManager_SetColumnCount(*args, **kwargs)
+
+ def SetDescription(*args, **kwargs):
+ """SetDescription(self, String label, String content)"""
+ return _propgrid.PropertyGridManager_SetDescription(*args, **kwargs)
+
+ def SetDescBoxHeight(*args, **kwargs):
+ """SetDescBoxHeight(self, int ht, bool refresh=True)"""
+ return _propgrid.PropertyGridManager_SetDescBoxHeight(*args, **kwargs)
+
+ def SetSplitterLeft(*args, **kwargs):
+ """SetSplitterLeft(self, bool subProps=False, bool allPages=True)"""
+ return _propgrid.PropertyGridManager_SetSplitterLeft(*args, **kwargs)
+
+ def SetPageSplitterLeft(*args, **kwargs):
+ """SetPageSplitterLeft(self, int page, bool subProps=False)"""
+ return _propgrid.PropertyGridManager_SetPageSplitterLeft(*args, **kwargs)
+
+ def SetPageSplitterPosition(*args, **kwargs):
+ """SetPageSplitterPosition(self, int page, int pos, int column=0)"""
+ return _propgrid.PropertyGridManager_SetPageSplitterPosition(*args, **kwargs)
+
+ def SetSplitterPosition(*args, **kwargs):
+ """SetSplitterPosition(self, int pos, int column=0)"""
+ return _propgrid.PropertyGridManager_SetSplitterPosition(*args, **kwargs)
+
+ def SetId(*args, **kwargs):
+ """
+ SetId(self, int winid)
+
+ Sets the identifier of the window. Each window has an integer
+ identifier. If the application has not provided one, an identifier
+ will be generated. Normally, the identifier should be provided on
+ creation and should not be modified subsequently.
+ """
+ return _propgrid.PropertyGridManager_SetId(*args, **kwargs)
+
+ def Freeze(*args, **kwargs):
+ """
+ Freeze(self)
+
+ Freezes the window or, in other words, prevents any updates from
+ taking place on screen, the window is not redrawn at all. Thaw must be
+ called to reenable window redrawing. Calls to Freeze/Thaw may be
+ nested, with the actual Thaw being delayed until all the nesting has
+ been undone.
+
+ This method is useful for visual appearance optimization (for example,
+ it is a good idea to use it before inserting large amount of text into
+ a wxTextCtrl under wxGTK) but is not implemented on all platforms nor
+ for all controls so it is mostly just a hint to wxWindows and not a
+ mandatory directive.
+ """
+ return _propgrid.PropertyGridManager_Freeze(*args, **kwargs)
+
+ def Thaw(*args, **kwargs):
+ """
+ Thaw(self)
+
+ Reenables window updating after a previous call to Freeze. Calls to
+ Freeze/Thaw may be nested, so Thaw must be called the same number of
+ times that Freeze was before the window will be updated.
+ """
+ return _propgrid.PropertyGridManager_Thaw(*args, **kwargs)
+
+ def Reparent(*args, **kwargs):
+ """Reparent(self, wxWindowBase newParent) -> bool"""
+ return _propgrid.PropertyGridManager_Reparent(*args, **kwargs)
+
+ def GetValuesFromPage(self,
+ page,
+ dict_=None,
+ as_strings=False,
+ inc_attributes=False):
+ "Same as GetValues, but returns values from specific page only."
+ "For argument descriptions, see GetValues."
+ return page.GetPropertyValues(dict_, as_strings, inc_attributes)
+
+_propgrid.PropertyGridManager_swigregister(PropertyGridManager)
+
+
+def NewPropertyCategory(*args, **kwargs):
+ """NewPropertyCategory(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL)) -> PGProperty"""
+ return _propgrid.NewPropertyCategory(*args, **kwargs)
+
+def NewStringProperty(*args, **kwargs):
+ """
+ NewStringProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> PGProperty
+ """
+ return _propgrid.NewStringProperty(*args, **kwargs)
+
+def NewUIntProperty(*args, **kwargs):
+ """
+ NewUIntProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ long value=0) -> PGProperty
+ """
+ return _propgrid.NewUIntProperty(*args, **kwargs)
+
+def NewIntProperty(*args, **kwargs):
+ """
+ NewIntProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ long value=0) -> PGProperty
+ """
+ return _propgrid.NewIntProperty(*args, **kwargs)
+
+def NewFloatProperty(*args, **kwargs):
+ """
+ NewFloatProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ double value=0.0) -> PGProperty
+ """
+ return _propgrid.NewFloatProperty(*args, **kwargs)
+
+def NewBoolProperty(*args, **kwargs):
+ """
+ NewBoolProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ bool value=False) -> PGProperty
+ """
+ return _propgrid.NewBoolProperty(*args, **kwargs)
+
+def NewEnumProperty(*args, **kwargs):
+ """
+ NewEnumProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString labels=wxArrayString(),
+ wxArrayInt values=wxArrayInt(),
+ int value=0) -> PGProperty
+ """
+ return _propgrid.NewEnumProperty(*args, **kwargs)
+
+def NewEditEnumProperty(*args, **kwargs):
+ """
+ NewEditEnumProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString labels=wxArrayString(),
+ wxArrayInt values=wxArrayInt(),
+ String value=wxEmptyString) -> PGProperty
+ """
+ return _propgrid.NewEditEnumProperty(*args, **kwargs)
+
+def NewFlagsProperty(*args, **kwargs):
+ """
+ NewFlagsProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString labels=wxArrayString(),
+ wxArrayInt values=wxArrayInt(),
+ int value=0) -> PGProperty
+ """
+ return _propgrid.NewFlagsProperty(*args, **kwargs)
+
+def NewLongStringProperty(*args, **kwargs):
+ """
+ NewLongStringProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> PGProperty
+ """
+ return _propgrid.NewLongStringProperty(*args, **kwargs)
+
+def NewFileProperty(*args, **kwargs):
+ """
+ NewFileProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> PGProperty
+ """
+ return _propgrid.NewFileProperty(*args, **kwargs)
+
+def NewDirProperty(*args, **kwargs):
+ """
+ NewDirProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> PGProperty
+ """
+ return _propgrid.NewDirProperty(*args, **kwargs)
+
+def NewArrayStringProperty(*args, **kwargs):
+ """
+ NewArrayStringProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString value=wxArrayString()) -> PGProperty
+ """
+ return _propgrid.NewArrayStringProperty(*args, **kwargs)
+
+def NewFontProperty(*args, **kwargs):
+ """
+ NewFontProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ Font value=wxFont()) -> PGProperty
+ """
+ return _propgrid.NewFontProperty(*args, **kwargs)
+
+def NewSystemColourProperty(*args, **kwargs):
+ """
+ NewSystemColourProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ ColourPropertyValue value=wxColourPropertyValue()) -> PGProperty
+ """
+ return _propgrid.NewSystemColourProperty(*args, **kwargs)
+
+def NewColourProperty(*args, **kwargs):
+ """
+ NewColourProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ Colour value=wxColour()) -> PGProperty
+ """
+ return _propgrid.NewColourProperty(*args, **kwargs)
+
+def NewCursorProperty(*args, **kwargs):
+ """
+ NewCursorProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ int value=0) -> PGProperty
+ """
+ return _propgrid.NewCursorProperty(*args, **kwargs)
+
+def NewImageFileProperty(*args, **kwargs):
+ """
+ NewImageFileProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> PGProperty
+ """
+ return _propgrid.NewImageFileProperty(*args, **kwargs)
+
+def NewMultiChoiceProperty(*args, **kwargs):
+ """
+ NewMultiChoiceProperty(String label, String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString choices=wxArrayString(),
+ wxArrayString value=wxArrayString()) -> PGProperty
+ """
+ return _propgrid.NewMultiChoiceProperty(*args, **kwargs)
+
+def NewDateProperty(*args, **kwargs):
+ """
+ NewDateProperty(String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ DateTime value=wxDateTime()) -> PGProperty
+ """
+ return _propgrid.NewDateProperty(*args, **kwargs)
+class PyFloatProperty(FloatProperty):
+ """Proxy of C++ PyFloatProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ double value=0.0) -> PyFloatProperty
+ """
+ _propgrid.PyFloatProperty_swiginit(self,_propgrid.new_PyFloatProperty(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyFloatProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyFloatProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyFloatProperty_swigregister(PyFloatProperty)
+
+class PyEditorDialogAdapter(PGEditorDialogAdapter):
+ """Proxy of C++ PyEditorDialogAdapter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyEditorDialogAdapter"""
+ _propgrid.PyEditorDialogAdapter_swiginit(self,_propgrid.new_PyEditorDialogAdapter(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyEditorDialogAdapter, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyEditorDialogAdapter__SetSelf(*args, **kwargs)
+
+_propgrid.PyEditorDialogAdapter_swigregister(PyEditorDialogAdapter)
+
+class PyEnumProperty(EnumProperty):
+ """Proxy of C++ PyEnumProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString labels=wxArrayString(),
+ wxArrayInt values=wxArrayInt(),
+ int value=0) -> PyEnumProperty
+ """
+ _propgrid.PyEnumProperty_swiginit(self,_propgrid.new_PyEnumProperty(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyEnumProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyEnumProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyEnumProperty_swigregister(PyEnumProperty)
+
+class PyArrayStringProperty(ArrayStringProperty):
+ """Proxy of C++ PyArrayStringProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString value=wxArrayString()) -> PyArrayStringProperty
+ """
+ _propgrid.PyArrayStringProperty_swiginit(self,_propgrid.new_PyArrayStringProperty(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyArrayStringProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyArrayStringProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyArrayStringProperty_swigregister(PyArrayStringProperty)
+
+class PyComboBoxEditor(PGComboBoxEditor):
+ """Proxy of C++ PyComboBoxEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyComboBoxEditor"""
+ _propgrid.PyComboBoxEditor_swiginit(self,_propgrid.new_PyComboBoxEditor(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyComboBoxEditor, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyComboBoxEditor__SetSelf(*args, **kwargs)
+
+_propgrid.PyComboBoxEditor_swigregister(PyComboBoxEditor)
+
+class PyFileDialogAdapter(PGFileDialogAdapter):
+ """Proxy of C++ PyFileDialogAdapter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyFileDialogAdapter"""
+ _propgrid.PyFileDialogAdapter_swiginit(self,_propgrid.new_PyFileDialogAdapter(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyFileDialogAdapter, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyFileDialogAdapter__SetSelf(*args, **kwargs)
+
+_propgrid.PyFileDialogAdapter_swigregister(PyFileDialogAdapter)
+
+class PyStringProperty(StringProperty):
+ """Proxy of C++ PyStringProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> PyStringProperty
+ """
+ _propgrid.PyStringProperty_swiginit(self,_propgrid.new_PyStringProperty(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyStringProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyStringProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyStringProperty_swigregister(PyStringProperty)
+
+class PyLongStringDialogAdapter(PGLongStringDialogAdapter):
+ """Proxy of C++ PyLongStringDialogAdapter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyLongStringDialogAdapter"""
+ _propgrid.PyLongStringDialogAdapter_swiginit(self,_propgrid.new_PyLongStringDialogAdapter(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyLongStringDialogAdapter, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyLongStringDialogAdapter__SetSelf(*args, **kwargs)
+
+_propgrid.PyLongStringDialogAdapter_swigregister(PyLongStringDialogAdapter)
+
+class PyEditEnumProperty(EditEnumProperty):
+ """Proxy of C++ PyEditEnumProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, String label, String name, wxChar labels, long values,
+ String value) -> PyEditEnumProperty
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString labels=wxArrayString(),
+ wxArrayInt values=wxArrayInt(),
+ String value=wxEmptyString) -> PyEditEnumProperty
+ __init__(self, String label, String name, PGChoices choices, String value=wxEmptyString) -> PyEditEnumProperty
+ __init__(self, String label, String name, wxChar labels, long values,
+ PGChoices choicesCache, String value) -> PyEditEnumProperty
+ """
+ _propgrid.PyEditEnumProperty_swiginit(self,_propgrid.new_PyEditEnumProperty(*args))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyEditEnumProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyEditEnumProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyEditEnumProperty_swigregister(PyEditEnumProperty)
+
+class PyTextCtrlEditor(PGTextCtrlEditor):
+ """Proxy of C++ PyTextCtrlEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyTextCtrlEditor"""
+ _propgrid.PyTextCtrlEditor_swiginit(self,_propgrid.new_PyTextCtrlEditor(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyTextCtrlEditor, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyTextCtrlEditor__SetSelf(*args, **kwargs)
+
+_propgrid.PyTextCtrlEditor_swigregister(PyTextCtrlEditor)
+
+class PySystemColourProperty(SystemColourProperty):
+ """Proxy of C++ PySystemColourProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ ColourPropertyValue value=wxColourPropertyValue()) -> PySystemColourProperty
+ __init__(self, String label, String name, wxChar labels, long values,
+ PGChoices choicesCache, ColourPropertyValue value) -> PySystemColourProperty
+ __init__(self, String label, String name, wxChar labels, long values,
+ PGChoices choicesCache, Colour value) -> PySystemColourProperty
+ """
+ _propgrid.PySystemColourProperty_swiginit(self,_propgrid.new_PySystemColourProperty(*args))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PySystemColourProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PySystemColourProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PySystemColourProperty_swigregister(PySystemColourProperty)
+
+class PyFlagsProperty(FlagsProperty):
+ """Proxy of C++ PyFlagsProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ wxArrayString labels=wxArrayString(),
+ wxArrayInt values=wxArrayInt(),
+ int value=0) -> PyFlagsProperty
+ """
+ _propgrid.PyFlagsProperty_swiginit(self,_propgrid.new_PyFlagsProperty(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyFlagsProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyFlagsProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyFlagsProperty_swigregister(PyFlagsProperty)
+
+class PyFontProperty(FontProperty):
+ """Proxy of C++ PyFontProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ Font value=wxFont()) -> PyFontProperty
+ """
+ _propgrid.PyFontProperty_swiginit(self,_propgrid.new_PyFontProperty(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyFontProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyFontProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyFontProperty_swigregister(PyFontProperty)
+
+class PyColourProperty(ColourProperty):
+ """Proxy of C++ PyColourProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ Colour value=*wxWHITE) -> PyColourProperty
+ """
+ _propgrid.PyColourProperty_swiginit(self,_propgrid.new_PyColourProperty(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyColourProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyColourProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyColourProperty_swigregister(PyColourProperty)
+
+class PyFileProperty(FileProperty):
+ """Proxy of C++ PyFileProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> PyFileProperty
+ """
+ _propgrid.PyFileProperty_swiginit(self,_propgrid.new_PyFileProperty(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyFileProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyFileProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyFileProperty_swigregister(PyFileProperty)
+
+class PyIntProperty(IntProperty):
+ """Proxy of C++ PyIntProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ long value=0) -> PyIntProperty
+ __init__(self, String label, String name, wxLongLong value) -> PyIntProperty
+ """
+ _propgrid.PyIntProperty_swiginit(self,_propgrid.new_PyIntProperty(*args))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyIntProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyIntProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyIntProperty_swigregister(PyIntProperty)
+
+class PyEditor(PGEditor):
+ """Proxy of C++ PyEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyEditor"""
+ _propgrid.PyEditor_swiginit(self,_propgrid.new_PyEditor(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyEditor, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyEditor__SetSelf(*args, **kwargs)
+
+_propgrid.PyEditor_swigregister(PyEditor)
+
+class PyChoiceEditor(PGChoiceEditor):
+ """Proxy of C++ PyChoiceEditor class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> PyChoiceEditor"""
+ _propgrid.PyChoiceEditor_swiginit(self,_propgrid.new_PyChoiceEditor(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyChoiceEditor, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyChoiceEditor__SetSelf(*args, **kwargs)
+
+_propgrid.PyChoiceEditor_swigregister(PyChoiceEditor)
+
+class PyProperty(PGProperty):
+ """Proxy of C++ PyProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> PyProperty
+ __init__(self, String label, String name) -> PyProperty
+ """
+ _propgrid.PyProperty_swiginit(self,_propgrid.new_PyProperty(*args))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyProperty_swigregister(PyProperty)
+
+class PyUIntProperty(UIntProperty):
+ """Proxy of C++ PyUIntProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ long value=0) -> PyUIntProperty
+ __init__(self, String label, String name, wxULongLong value) -> PyUIntProperty
+ """
+ _propgrid.PyUIntProperty_swiginit(self,_propgrid.new_PyUIntProperty(*args))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyUIntProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyUIntProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyUIntProperty_swigregister(PyUIntProperty)
+
+class PyLongStringProperty(LongStringProperty):
+ """Proxy of C++ PyLongStringProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String label=(*wxPGProperty::sm_wxPG_LABEL), String name=(*wxPGProperty::sm_wxPG_LABEL),
+ String value=wxEmptyString) -> PyLongStringProperty
+ """
+ _propgrid.PyLongStringProperty_swiginit(self,_propgrid.new_PyLongStringProperty(*args, **kwargs))
+ self._SetSelf(self); self._RegisterMethods()
+
+ def CallSuperMethod(self, *args, **kwargs):
+ funcname = args[0]
+ args2 = list(args)
+ args2[0] = self
+ self._super_call = True
+ try:
+ res = getattr(PyLongStringProperty, funcname)(*args2, **kwargs)
+ finally:
+ del self._super_call
+ return res
+
+ def _RegisterMethods(self):
+ cls = self.__class__
+ if not hasattr(cls,'_pyswig_methods_registered'):
+ cls._pyswig_methods_registered = True
+ ls = [ab for ab in cls.__dict__.iteritems()]
+ for a, b in ls:
+ if not a.startswith('_'):
+ setattr(cls, '%s_t_'%a, b)
+
+ def _SetSelf(*args, **kwargs):
+ """_SetSelf(self, PyObject self)"""
+ return _propgrid.PyLongStringProperty__SetSelf(*args, **kwargs)
+
+_propgrid.PyLongStringProperty_swigregister(PyLongStringProperty)
+
+
+def RegisterEditor(*args, **kwargs):
+ """RegisterEditor(PGEditor editor, String editorName)"""
+ return _propgrid.RegisterEditor(*args, **kwargs)
+EVT_PG_CHANGED = wx.PyEventBinder( wxEVT_PG_CHANGED, 1 )
+EVT_PG_CHANGING = wx.PyEventBinder( wxEVT_PG_CHANGING, 1 )
+EVT_PG_SELECTED = wx.PyEventBinder( wxEVT_PG_SELECTED, 1 )
+EVT_PG_HIGHLIGHTED = wx.PyEventBinder( wxEVT_PG_HIGHLIGHTED, 1 )
+EVT_PG_RIGHT_CLICK = wx.PyEventBinder( wxEVT_PG_RIGHT_CLICK, 1 )
+EVT_PG_PAGE_CHANGED = wx.PyEventBinder( wxEVT_PG_PAGE_CHANGED, 1 )
+EVT_PG_ITEM_COLLAPSED = wx.PyEventBinder( wxEVT_PG_ITEM_COLLAPSED, 1 )
+EVT_PG_ITEM_EXPANDED = wx.PyEventBinder( wxEVT_PG_ITEM_EXPANDED, 1 )
+EVT_PG_DOUBLE_CLICK = wx.PyEventBinder( wxEVT_PG_DOUBLE_CLICK, 1 )
+EVT_PG_LABEL_EDIT_BEGIN = wx.PyEventBinder( wxEVT_PG_LABEL_EDIT_BEGIN, 1 )
+EVT_PG_LABEL_EDIT_ENDING = wx.PyEventBinder( wxEVT_PG_LABEL_EDIT_ENDING, 1 )
+EVT_PG_COL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_PG_COL_BEGIN_DRAG, 1 )
+EVT_PG_COL_DRAGGING = wx.PyEventBinder( wxEVT_PG_COL_DRAGGING, 1 )
+EVT_PG_COL_END_DRAG = wx.PyEventBinder( wxEVT_PG_COL_END_DRAG, 1 )
+
+LABEL_AS_NAME = "@!"
+DEFAULT_IMAGE_SIZE = (-1,-1)
+NO_IMAGE_SIZE = (0,0)
+
+PG_BOOL_USE_CHECKBOX = "UseCheckbox"
+PG_BOOL_USE_DOUBLE_CLICK_CYCLING = "UseDClickCycling"
+PG_FLOAT_PRECISION = "Precision"
+PG_STRING_PASSWORD = "Password"
+PG_UINT_BASE = "Base"
+PG_UINT_PREFIX = "Prefix"
+PG_FILE_WILDCARD = "Wildcard"
+PG_FILE_SHOW_FULL_PATH = "ShowFullPath"
+PG_FILE_SHOW_RELATIVE_PATH = "ShowRelativePath"
+PG_FILE_INITIAL_PATH = "InitialPath"
+PG_FILE_DIALOG_TITLE = "DialogTitle"
+PG_DIR_DIALOG_MESSAGE = "DialogMessage"
+PG_DATE_FORMAT = "DateFormat"
+PG_DATE_PICKER_STYLE = "PickerStyle"
+
+
+PropertyCategory = NewPropertyCategory
+StringProperty = NewStringProperty
+IntProperty = NewIntProperty
+UIntProperty = NewUIntProperty
+FloatProperty = NewFloatProperty
+BoolProperty = NewBoolProperty
+EnumProperty = NewEnumProperty
+EditEnumProperty = NewEditEnumProperty
+FlagsProperty = NewFlagsProperty
+LongStringProperty = NewLongStringProperty
+FileProperty = NewFileProperty
+DirProperty = NewDirProperty
+ArrayStringProperty = NewArrayStringProperty
+FontProperty = NewFontProperty
+SystemColourProperty = NewSystemColourProperty
+ColourProperty = NewColourProperty
+CursorProperty = NewCursorProperty
+ImageFileProperty = NewImageFileProperty
+MultiChoiceProperty = NewMultiChoiceProperty
+DateProperty = NewDateProperty
+
+
+
+
+
+
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/CHANGES.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/CHANGES.txt
new file mode 100644
index 0000000..501c091
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/CHANGES.txt
@@ -0,0 +1,796 @@
+0.9.7.9 (9/8/09)
+-------------------
+Finalized the naming convention so that references to shell in the new "slices"
+shell are renamed to "sliceshell" (likewise, Shell becomes SlicesShell)
+
+Also, renamed the file "slices.py" to "sliceshell.py".
+Since my goal is to keep PySlices.py as the equivalent to PyCrust.py,
+ I think this new convention makes the most sense...
+
+Now (Finally):
+ shell.py contains the classes: Shell, ShellFacade, and ShellFrame
+ sliceshell.py contains the classes: SlicesShell, SlicesShellFacade,
+ and SlicesShellFrame
+ crust.py contains: Crust and CrustFrame
+ crustslices.py contains: CrustSlices and CrustSlicesFrame
+ PyShell.py and PySlicesShell.py are the respective standalone shell apps
+ PyCrust.py and PySlices.py are the respective apps that also include Filling
+
+ frame.py etc. still continue to service both PyCrust and PySlices.
+
+0.9.7.8 (9/8/09)
+-------------------
+Added open/save abilities to PySlices (PyCrust remains the same).
+ This uses a special format with extension .pyslices.
+ A file, *.pyslices will contain a text header and
+ also a line denoting the beginning of each new slice,
+ naming the type of slice as well (grouping, input, output)
+ All output is commented with a single '#' which is removed upon loading.
+ This ensures that a well contstucted .pyslices file is also
+ a valid python script!
+
+Added the ability to load an entire python file into a new Input slice
+ with Ctrl-L
+Added the ability to load pyslices files from the command line.
+
+Split the functionality of crust.py (functioning for both PyCrust and PySlices)
+ into crust.py (only PyCrust) and crustslices.py (only for PySlices).
+
+After revising the naming conventions:
+ shell.py contains the classes: Shell, ShellFacade, and ShellFrame
+ slice.py contains the classes: Shell, ShellFacade, and ShellFrame
+ crust.py contains: Crust and CrustFrame
+ crustslices.py contains: CrustSlices and CrustSlicesFrame
+ PyShell.py and PySlicesShell.py are the respective standalone shell apps
+ PyCrust.py and PySlices.py are the respective apps that also include Filling
+
+ frame.py etc. still continue to service both PyCrust and PySlices.
+
+0.9.7.7 (8/25/2009) (Current--Still Need to SVNAdd the new file PySlicesShell.py)
+-------------------
+Added code to introspect.py to check for Enthought's "Traits" attributes.
+Added PySlicesShell.py. PySlices shell is PySlices without Filling
+ and other crust attributes.
+Fixed a bug with Output_BG
+
+0.9.7.6 (7/18/2009)
+-------------------
+Made output have a slight-blue background
+Added a tutorial that can be disabled in Options->Startup.
+Added "Shell Mode" which uses >>> and ... markers for input slices and uses two returns for command execution
+Changed manual completion keybindings.
+Cleaned up keybinding help.
+Made Items in Options->Startup menu automatically save to the config file (since they don't affect anything until startup)
+Major code cleanup, removal of much dead code, shortening of very long lines, etc...
+
+0.9.6.9 (7/9/2009)
+-------------------
+Fixed Undo marker issues and a bug in selection overwrite.
+
+0.9.6.8 (7/1/2009)
+-------------------
+Merged changes with SVN trunk.
+
+0.9.6.4 thru 0.9.6.6 (10/22/2008-4/27/2009)
+-------------------
+Added magic.py to handle some very simple "magic" commands:
+
+Now the command:
+"f 1"
+will be re-interpreted as:
+"f(1)"
+
+The command:
+"f 1,2,3,4"
+will be interpreted as:
+f(1,2,3,4)
+
+Special commands "ls","cd", and "pwd" are interpreted separately
+
+Works with slices.py and shell.py
+
+Also fixed auto-indent magic.
+
+0.9.6.1 thru 0.9.6.3 (10/21/2008)
+---------------------------------
+Added PySlices (slices.py and PySlices.py), a modified version of PyCrust.
+PySlices is a "notebook interface" multi-line shell, ala Sage or Mathematica.
+It uses Scintilla markers extensively, with red for input and blue for output.
+
+Modified crust.py to use a switch so it can load either a Shell or a Slices_Shell
+
+0.9.5 (12/23/2005)
+------------------
+
+Applied a series of enhancments by Franz Steinaeusler, Adi Sieker, and
+Sebastian Haase, up until their 7-31-2005 version. (Their next
+version broke some existing functionality, and added some confusing
+hacks, and I didn't feel that the incremental gains were worth the
+loss at that point so I stopped at 7-31-2005.)
+
+Their changes include the following:
+
+* The Autocomplete and Calltip windows can now be opened manually with
+ Ctrl-Space and Ctrl-Shift-Space.
+
+* In the stand alone PyCrust app the various option settings, window
+ size and position, and etc. are saved and restored at the next run.
+
+* Added a help dialog bound to the F1 key that shows the key bindings.
+
+* Added a new text completion function that suggests words from the
+ history. Bound to Shift-Return.
+
+* F11 will toggle the maximized state of the frame.
+
+* switched to Bind() from wx.EVT_*().
+
+* Display of line numbers can be toggled.
+
+* F12 toggles a "free edit" mode of the shell buffer. This mode is
+ useful, for example, if you would like to remove some output or
+ errors or etc. from the buffer before doing a copy/paste. The free
+ edit mode is designated by the use of a red, non-flashing caret.
+
+* Ctrl-Shift-F will fold/unfold (hide/show) the selected lines.
+
+
+
+On top of these changes I (Robin Dunn) added the following:
+
+* General code cleanup and fixes.
+
+* Use wx.StandardPaths to determine the location of the config files.
+
+* Remove Orbtech attributions from the UI, they've been there long
+ enough.
+
+* Use wx.SP_LIVE_UPDATE on crust and filling windows.
+
+* Extended the saving of the config info and other new features to the
+ PyShell app too. Additionally, other apps that embed a PyCrust or a
+ PyShell can pass their own wx.Config object and have the Py code
+ save/restore its settings to/from there.
+
+* All of the classes with config info get an opportunity to save/load
+ their own settings instead of putting all the save/load code in one
+ place that then has to reach all over the place to do anything.
+
+* Enable editing of the startup python code, which will either be the
+ file pointed to by PYTHONSTARTUP or a file in the config dir if
+ PYTHONSTARTUP is not set in the environment.
+
+* Added an option to skip the running of the startup code when
+ PyShell or PyCrust starts.
+
+* PyCrust adds a pp(item) function to the shell's namespace that
+ pretty prints the item in the Display tab of the notebook. Added
+ code to raise that tab when pp() is called.
+
+* Added an option for whether to insert text for function parameters
+ when popping up the call tip.
+
+* Added Find and Find-Next functions that use the wx.FindReplaceDialog.
+
+
+
+
+
+
+0.9.4 (1/25/2004 to //2004)
+------------------------------
+
+Removed wxd decorators in favor of new SWIG-generated docstrings.
+
+Removed docs tabs from crust interface:
+* wxPython Docs
+* wxSTC Docs
+
+Fixed Calltip tab refresh problem on Windows.
+
+shell.autoCompleteAutoHide added with default of False.
+
+Changed default namespace of Shell to __main__.__dict__, instead of an
+empty dictionary.
+
+
+0.9.3 (9/25/2003 to 1/24/2004)
+------------------------------
+
+Fun and games with dynamic renaming. Details of any other changes
+were lost in the confusion. I'll try to do better in the future.
+
+
+0.9.2 (5/3/2003 to 9/25/2003)
+-----------------------------
+
+Changed to the new prefix-less "wx" package::
+
+ import wx
+
+instead of::
+
+ from wxPython import wx
+
+Fixed typo in ``PyWrap.py``::
+
+ if __name__ == '__main__':
+ main(sys.argv)
+
+should have been::
+
+ if __name__ == '__main__':
+ main()
+
+Added pretty-print Display tab to Crust, based on suggestion from
+Jason Whitlark.
+
+Improved ``Can*`` checks in ``EditWindow``, since STC is too lenient,
+particularly when it is set to read-only but returns True for
+CanPaste() (seems like an STC bug to me)::
+
+ def CanCopy(self):
+ """Return True if text is selected and can be copied."""
+ return self.GetSelectionStart() != self.GetSelectionEnd()
+
+ def CanCut(self):
+ """Return True if text is selected and can be cut."""
+ return self.CanCopy() and self.CanEdit()
+
+ def CanEdit(self):
+ """Return True if editing should succeed."""
+ return not self.GetReadOnly()
+
+ def CanPaste(self):
+ """Return True if pasting should succeed."""
+ return stc.StyledTextCtrl.CanPaste(self) and self.CanEdit()
+
+
+0.9.1 (3/21/2003 to 5/2/2003)
+-----------------------------
+
+PyCrust is dead! Long live Py!
+
+* Renamed ``PyCrust`` package to ``py``.
+* Moved code to wxPython's CVS repository.
+
+Fixed bug in ``introspect.py`` on introspecting objects occurring
+immediately after a secondary prompt, like this::
+
+ >>> l = [1, 2, 3]
+ >>> for n in range(3):
+ ... l. <-- failed to popup autocomplete list
+
+Added documentation files:
+
+* PyManual.txt
+* wxPythonManual.txt
+* wxPythonPackage.txt
+* wxPythonExamples.txt
+
+Added PyAlaMode and PyAlaCarte code editors.
+
+Major refactoring to support ``editor`` and ``shell`` from the same
+base.
+
+Renamed program files:
+
+* ``PyCrustApp.py`` to ``PyCrust.py``
+* ``PyFillingApp.py`` to ``PyFilling.py``
+* ``PyShellApp.py`` to ``PyShell.py``
+* ``wrap.py`` to ``PyWrap.py``
+
+Removed disabling of autocomplete for lists of 2000 items or more.
+The current implementation of wxSTC can now handle lists this big.
+
+Improved handling of ``sys.path`` to mimic the standard Python shell.
+
+
+0.9 (2/27/2003 to 3/20/2003)
+----------------------------
+
+Added fontIncrease, fontDecrease, fontDefault signals, receivers and
+keybindings::
+
+ Ctrl+] Increase font size.
+ Ctrl+[ Decrease font size.
+ Ctrl+= Default font size.
+
+Continued enhancement of the decorator capability to provide better
+documentation and docstrings for wxPython classes and functions.
+
+Introduced new tabbed interface:
+
+* Namespace
+* Calltip
+* Session
+* Dispatcher
+* wxPython Docs
+* wxSTC Docs
+
+``Filling.tree`` now expands tuples as well as lists. (It should have
+done this all along, I just never noticed this omission before.)
+
+Added this True/False test to all modules::
+
+ try:
+ True
+ except NameError:
+ True = 1==1
+ False = 1==0
+
+Added ``wxd`` directory with decoration classes.
+
+
+0.8.2 (1/5/2003 to 2/26/2003)
+-----------------------------
+
+Wrapped ``sys.ps1``, ``sys.ps2``, and ``sys.ps3`` in ``str()``.
+(Thanks, Kieran Holland.)
+
+Fixed minor things found by PyChecker.
+
+Changed locals to use ``__main__.__dict__`` and added code to clean up
+the namespace, making it as close to the regular Python environment as
+possible. This solves the problem of pickling and unpickling
+instances of classes defined in the shell.
+
+Made ``shell.PasteAndRun()`` a little more forgiving when it finds a
+ps2 prompt line with no trailing space, such when you copy code from a
+web page.
+
+Improved autocomplete behavior by adding these to shell::
+
+ self.AutoCompSetAutoHide(False)
+ self.AutoCompStops(' .,;:([)]}\'"\\<>%^&+-=*/|`')
+
+Added ``decor`` directory, ``decorator.py``, ``stcDecor.py``, and
+``stcConstants.py``. These all serve the purpose of adding docstrings
+to existing wxPython classes, in particular the ``wxStyledTextCtrl``.
+
+Added ``wrap.py``, a command line utility for running a wxPython app
+with additional runtime-tools loaded, such as PyCrust (the only tool
+at this point).
+
+Flushed the clipboard Cut/Copy operations so that selections will
+exist in the clipboard even after PyCrust has been closed.
+
+Improved the suppression of docstrings for simple data types appearing
+in the namespace viewer.
+
+Better handling of autocompletion with numeric types; no
+autocompletion when typing a dot after an integer. If the
+autocompletion is desired, type a space before the dot::
+
+ func = 3 .
+
+More Filling!!! The namespace tree is now dynamically updated.
+
+
+0.8.1 (12/20/2002 to 12/25/2002)
+--------------------------------
+
+Improved keyboard handling with Autocomplete active. You can now use
+Enter as well as Tab to select an item from the list.
+
+Disabled autocomplete for lists of 2000 items or more. The current
+implementation of wxSTC can't handle lists this big.
+
+Changed ``filling`` to always display docstrings for objects. This is
+useful for objects whose docstrings have been decorated, rather than
+coming directly from the source code. (Hmmm. Sounds like someone is
+doing some decorating. I wonder where that would be helpful? <wink>)
+
+Fixed handling of icon. Added ``images.py`` file.
+
+
+0.8 (10/29/2002 to 12/16/2002)
+------------------------------
+
+Added "help" to startup banner info.
+
+Made all ``wx`` and ``stc`` imports explicit. No more ``import *``.
+
+Replaced use of the ``wx`` module's ``true`` and ``false`` with
+Python's ``True`` and ``False``.
+
+Changed ``introspect.getRoot()`` to use ``tokenize`` module. This
+does a slightly better job than the previous parsing routine and the
+code is clearer.
+
+Improved handling of whitespace and empty types during introspection.
+
+Fixed cut/copy clipboard problem under Linux. (Robin Dunn rocks!!!)
+
+Added shell.about() which works like this::
+
+ >>> shell.about()
+ PyCrust Version: 0.8
+ Shell Revision: 1.80
+ Interpreter Revision: 1.15
+ Python Version: 2.2.2
+ wxPython Version: 2.3.3.1
+ Platform: linux2
+
+Added copy plus and paste plus to shell menu.
+
+Moved shell menu from ``shell.py`` to ``shellmenu.py``.
+
+Added ``sys.stdin.readlines()`` support.
+
+Added ``time.sleep()`` in ``readline()`` and ``OnIdle()`` event
+handler to free up the CPU.
+
+
+0.7.2 (2/22/2002 to 8/27/2002)
+------------------------------
+
+Tweaked ``getAttributeNames()`` to pick up a few more attributes::
+
+ '__bases__', '__class__', '__dict__', '__name__', 'func_closure',
+ 'func_code', 'func_defaults', 'func_dict', 'func_doc',
+ 'func_globals', 'func_name'
+
+Added a tests directory and unit tests.
+
+Improved support for empty types in the shell: ``[]``, ``()`` and
+``{}`` as far as when call tips and autocompletion are available.
+
+Added support for the other triple string - ``''''''``.
+
+Refactored ``introspect.py`` to improve testability.
+
+Improved call tips for unbound methods by leaving the "self"
+parameter, since unbound methods require an instance be passed.
+
+Fixed call tip bug where a tip was displayed when a "(" was typed
+after an object that wasn't callable.
+
+Fixed ``getAllAttributeNames`` when ``str(object)`` fails.
+
+Added brace highlighting. (Thank you, Kevin Altis.)
+
+Fixed problem displaying unicode objects in ``PyFilling``.
+
+Changed how ``filling.py`` checks for expandable objects. Lists are
+now expandable objects.
+
+Made the key handling more robust when there is an active text
+selection that includes text prior to the last primary prompt. Thanks
+to Raul Cota for pointing this out.
+
+Fixed wxSTC problem with brace highlighting and non-us keyboards.
+(Thank you for the patch, Jean-Michel Fauth.)
+
+Added ``busy = wxBusyCursor()`` to key points in ``shell`` and
+``filling``.
+
+Added ``OnCloseWindow`` handler to ``ShellFrame`` and ``CrustFrame``.
+
+Default to ``SetWrapMode(1)`` for shell and namespace viewer.
+
+Added ``shell.wrap()`` and ``shell.zoom()``.
+
+Added autoCompleteKeys hooks for Raul Cota.
+
+Cleaned up various little key handling bugs.
+
+Changed input methods to get values from shell, rather than dialog
+boxes. Renamed ``readIn`` to ``readline`` and ``readRaw`` to
+``raw_input``.
+
+
+0.7.1 (12/12/2001 to 2/21/2002)
+-------------------------------
+
+Fixed ``OnChar()`` issues effecting European keyboards, as reported by
+Jean-Michel Fauth.
+
+Fixed ``introspect.py`` issue with xmlrpc objects reported by Kevin
+Altis.
+
+Fixed some introspect/PyFilling issues with regard to Python 2.2.
+
+Fixed font background color as reported by Keith J. Farmer. (Thanks)
+
+Fixed problem with call tips and autocompletion inside multiline
+commands as report by Kevin Altis.
+
+Improved ``OnKeyDown`` handling of cut/copy/paste operations based on
+feedback from Syver Enstad. (Thanks)
+
+Added a ``shell.help()`` method to display some help info.
+
+Changed sort of items in the namespace viewer to case insensitive.
+
+Changed ``attributes.sort(lambda x, y: cmp(x.upper(), y.upper()))`` in
+advance of an upcoming fix to an autocompletion matching bug in wxSTC.
+
+Improved support for ZODB by allowing namespace drilldown into BTrees.
+
+Added ``shell.PasteAndRun()`` to support pasting multiple commands into
+the shell from the clipboard. Ctrl+Shift+V or v.
+
+Enter now always processes a command (or copies down a previous one.)
+To insert a line break, press Ctrl+Enter.
+
+Escape key clears the current, unexecuted command.
+
+History retrieval changed to replace current command. Added new keys
+to insert from history - Shift+Up and Shift+Down.
+
+Better call tips on objects with ``__call__`` methods.
+
+Improved call tip positioning calculation.
+
+
+0.7 (10/15/2001 to 12/11/2001)
+------------------------------
+
+Changed how command history retrieval functions work. Added Alt-P,
+Alt-N as keybindings for Retrieve-Previous, Retrieve-Next.
+
+Added full support for multi-line commands, similar to IDLE.
+
+Changed ``introspect.getAttributeNames()`` to do a case insensitive
+sort.
+
+Changed Cut/Copy/Paste to deal with prompts intelligently. Cut and
+Copy remove all prompts. Paste can handle prompted or not-prompted
+text.
+
+Added ``CopyWithPrompts()`` method attached to Ctrl-Shift-C for those
+times when you really do want all the prompts left intact.
+
+Improved handling of the shell's read-only zone.
+
+Changed ``CrustFrame.__init__`` parameter spec to include all
+parameters allowed by a ``wxFrame``.
+
+Changed ``FillingText`` to be read-only.
+
+Renamed ``PyCrust.py`` to ``PyCrustApp.py`` to eliminate
+package/module name conflicts that kept you from doing ``from PyCrust
+import shell`` inside files located in the ``PyCrust`` directory.
+
+Renamed ``PyFilling.py`` to ``PyFillingApp.py`` and ``PyShell.py`` to
+``PyShellApp.py`` to maintain consistency.
+
+Removed the ``__date__`` property from all modules.
+
+Fixed bug in ``introspect.getCallTip()``, reported by Kevin Altis.
+
+
+0.6.1 (9/19/2001 to 10/12/2001)
+-------------------------------
+
+Changed ``Shell.run()`` to always position to the end of existing
+text, as suggested by Raul Cota.
+
+Changed ``introspect.getAllAttributeNames()`` to break circular
+references in ``object.__class__``, which occurs in Zope/ZODB
+extension classes.
+
+Changed ``filling.FillingTree.getChildren()`` to introspect extension
+classes.
+
+Fixed minor bugs in ``introspect.getCallTip()`` that were interfering
+with call tips for Zope/ZODB extension class methods.
+
+In preparation for wxPython 2.3.2, added code to fix a font sizing
+problem. Versions of wxPython prior to 2.3.2 had a sizing bug on Win
+platform where the font was 2 points larger than what was specified.
+
+Added a hack to ``introspect.getAllAttributeNames()`` to "wake up"
+ZODB objects that are asleep - in a "ghost" state. Otherwise it
+returns incomplete info.
+
+
+0.6 (8/21/2001 to 9/12/2001)
+----------------------------
+
+Added ``PyFilling.py`` and ``filling.py``.
+
+``PyShell.py`` and ``PyFilling.py`` can now be run standalone, as well
+as ``PyCrust.py``.
+
+Added ``crust.py`` and moved some code from ``PyCrust.py`` to it.
+
+Added command history retrieval features submitted by Richie Hindle.
+
+Changed ``shell.write()`` to replace line endings with OS-specific
+endings. Changed ``shell.py`` and ``interpreter.py`` to use
+``os.linesep`` in strings having hardcoded line endings.
+
+Added ``shell.redirectStdin()``, ``shell.redirectStdout()`` and
+``shell.redirectStderr()`` to allow the surrounding app to toggle
+requests that the specified ``sys.std*`` be redirected to the shell.
+These can also be run from within the shell itself, of course.
+
+The shell now adds the current working directory "." to the search
+path::
+
+ sys.path.insert(0, os.curdir)
+
+Added support for distutils installations.
+
+
+0.5.4 (8/17/2001 to 8/20/2001)
+------------------------------
+
+Changed default font size under Linux to::
+
+ 'size' : 12,
+ 'lnsize' : 10,
+
+Changed ``Shell`` to expect a parameter referencing an Interpreter
+class, rather than an intepreter instance, to facilitate subclassing
+of Interpreter, which effectively broke when the Editor class was
+eliminated.
+
+Fixed ``PyCrustAlaCarte.py``, which had been broken by previous
+changes.
+
+Created ``InterpreterAlaCarte`` class as an example for use in the
+demo.
+
+Split ``PyCrust.py`` into ``PyCrust.py`` and ``PyShell.py`` in
+anticipation of ``PyFilling.py``.
+
+
+0.5.3 (8/16/2001)
+-----------------
+
+Added patch to ``PyCrust.py`` to fix wxPython bug::
+
+ wxID_SELECTALL = NewId() # This *should* be defined by wxPython.
+
+
+0.5.2 (8/14/2001 to 8/15/2001)
+------------------------------
+
+Shortened module names by dropping "PyCrust" as a prefix.
+
+Changed ``version`` to ``VERSION`` in ``version`` module.
+
+Added Options menu to PyCrust application.
+
+Eliminated the Editor class (and editor module) by merging with Shell.
+This means that Shell "is a" wxStyledTextCtrl rather than "has a".
+There just wasn't enough non-gui code to justify the separation.
+Plus, Shell will be much easier for gui toolkits/designers to deal
+with now.
+
+
+0.5.1 (8/10/2001 to 8/14/2001)
+------------------------------
+
+Added ``introspect`` module.
+
+Moved some functionality from ``PyCrustInterp`` to ``introspect``.
+
+Changed ``introspect.getRoot()`` to no longer remove whitespace from
+the command. This was a remnant of a previous approach that, when
+left as part of the current approach, turned out to be a really bad
+thing.
+
+Changed ``introspect.getRoot()`` to allow commands of ``''``, ``""``,
+``""""""``, ``[]``, ``()``, and ``{}`` to pass through. This allows
+you to type them, followed by a dot, and get autocomplete options on
+them.
+
+Changed ``introspect.getRoot()`` to identify some situations where
+strings shouldn't be considered roots. For example::
+
+ >>> import PyCrust # To illustrate the potential problem.
+ >>> len('PyCrust.py')
+
+Typing the dot at the end of "PyCrust" in the second line above should
+NOT result in an autocompletion list because "PyCrust" is part of a
+string in this context, not a reference to the PyCrust module object.
+Similar reasoning applies to call tips. For example::
+
+ >>> len('dir(')
+
+Typing the left paren at the end of "dir" should NOT result in a call
+tip.
+
+Both features now behave properly in the examples given. However,
+there is still the case where whitespace precedes the potential root
+and that is NOT handled properly. For example::
+
+ >>> len('this is a dir(')
+
+and::
+
+ >>> len('This is PyCrust.py')
+
+More code needs to be written to handle more complex situations.
+
+Added ``locals=None`` parameter to ``Shell.__init__()``.
+
+Added support for magic attribute retrieval. Users can change this
+with::
+
+ >>> shell.editor.autoCompleteIncludeMagic = 0
+
+Added the ability to set filters on auto completion to exclude
+attributes prefixed with a single or double underscore. Users can
+exclude one or the other or both with::
+
+ >>> shell.editor.autoCompleteExcludeSingle = 1
+ >>> shell.editor.autoCompleteExcludeDouble = 1
+
+
+0.5 (8/8/2001)
+--------------
+
+Mostly just a final version change before creating a release.
+
+
+0.4 (8/4/2001 to 8/7/2001)
+--------------------------
+
+Changed version/revision handling.
+
+Fixed bugs.
+
+
+0.3 (8/2/2001 to 8/3/2001)
+--------------------------
+
+Removed lots of cruft.
+
+Added lots of docstrings.
+
+Imported to CVS repository at SourceForge.
+
+Added call tips.
+
+
+0.2 (7/30/2001 to 8/2/2001)
+---------------------------
+
+Renamed several files.
+
+Added command autocompletion.
+
+Added menus to PyCrust.py: File, Edit and Help.
+
+Added sample applications: ``PyCrustAlaCarte.py``,
+``PyCrustAlaMode.py``, and ``PyCrustMinimus.py``.
+
+
+0.1 (7/1/2001 to 7/19/2001)
+---------------------------
+
+Added basic syntax coloring much like Boa.
+
+Added read-only logging much like IDLE.
+
+Can retrieve a previous command by putting the cursor back on that
+line and hitting enter.
+
+Stdin and raw_input operate properly so you can now do ``help()`` and
+``license()`` without hanging.
+
+Redefined "quit", "exit", and "close" to display a better-than-nothing
+response.
+
+Home key honors the prompt.
+
+Created SourceForge account, but nothing was posted.
+
+
+In the beginning, there was pie... (7/1/2001)
+---------------------------------------------
+
+Blame it all on IDLE, Boa and PythonWin. I was using all three, got
+frustrated with their dissimilarities, and began to let everyone know
+how I felt. At the same time, Scintilla looked like an interesting
+tool to build a shell around. And while I didn't receive much in the
+way of positive feedback, let alone encouragement, I just couldn't let
+go of the idea of a Scintilla-based Python shell. Then the PythonCard
+project got to the point where they were talking about including a
+shell in their development environment. That was all the incentive I
+needed. PyCrust had to happen...
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/Py.ico b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/Py.ico
new file mode 100644
index 0000000..eae6180
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/Py.ico
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaCarte.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaCarte.py
new file mode 100644
index 0000000..53e0282
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaCarte.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python2
+"""PyAlaCarte is a simple programmer's editor."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+from wx import py
+
+import os
+import sys
+
+class App(wx.App):
+ """PyAlaCarte standalone application."""
+
+ def __init__(self, filename=None):
+ self.filename = filename
+ wx.App.__init__(self, redirect=False)
+
+ def OnInit(self):
+ wx.InitAllImageHandlers()
+ self.frame = py.editor.EditorFrame(filename=self.filename)
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ return True
+
+def main(filename=None):
+ if not filename and len(sys.argv) > 1:
+ filename = sys.argv[1]
+ if filename:
+ filename = os.path.realpath(filename)
+ app = App(filename)
+ app.MainLoop()
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaMode.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaMode.py
new file mode 100644
index 0000000..71c51a7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaMode.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python2
+"""PyAlaMode is a programmer's editor."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+from wx import py
+
+import os
+import sys
+
+class App(wx.App):
+ """PyAlaMode standalone application."""
+
+ def __init__(self, filename=None):
+ self.filename = filename
+ wx.App.__init__(self, redirect=False)
+
+ def OnInit(self):
+ wx.InitAllImageHandlers()
+ self.frame = py.editor.EditorNotebookFrame(filename=self.filename)
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ return True
+
+def main(filename=None):
+ if not filename and len(sys.argv) > 1:
+ filename = sys.argv[1]
+ if filename:
+ filename = os.path.realpath(filename)
+ app = App(filename)
+ app.MainLoop()
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaModeTest.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaModeTest.py
new file mode 100644
index 0000000..78cffdf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyAlaModeTest.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python2
+"""PyAlaModeTest is a programmer's editor."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+from wx import py
+
+import os
+import sys
+
+class App(wx.App):
+ """PyAlaModeTest standalone application."""
+
+ def __init__(self, filename=None):
+ self.filename = filename
+ wx.App.__init__(self, redirect=False)
+
+ def OnInit(self):
+ wx.InitAllImageHandlers()
+ self.frame = py.editor.EditorShellNotebookFrame(filename=self.filename)
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ return True
+
+def main(filename=None):
+ app = App(filename)
+ app.MainLoop()
+
+if __name__ == '__main__':
+ filename = None
+ if len(sys.argv) > 1:
+ filename = os.path.realpath(sys.argv[1])
+ main(filename)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyCrust.ico b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyCrust.ico
new file mode 100644
index 0000000..eae6180
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyCrust.ico
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyCrust.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyCrust.py
new file mode 100644
index 0000000..3ecbcc4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyCrust.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python2
+"""PyCrust is a python shell and namespace browser application."""
+
+# The next two lines, and the other code below that makes use of
+# ``__main__`` and ``original``, serve the purpose of cleaning up the
+# main namespace to look as much as possible like the regular Python
+# shell environment.
+import __main__
+original = __main__.__dict__.keys()
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+
+class App(wx.App):
+ """PyCrust standalone application."""
+
+ def OnInit(self):
+ import os
+ import wx
+ from wx import py
+
+ self.SetAppName("pycrust")
+ confDir = wx.StandardPaths.Get().GetUserDataDir()
+ if not os.path.exists(confDir):
+ os.mkdir(confDir)
+ fileName = os.path.join(confDir, 'config')
+ self.config = wx.FileConfig(localFilename=fileName)
+ self.config.SetRecordDefaults(True)
+
+ self.frame = py.crust.CrustFrame(config=self.config, dataDir=confDir)
+## self.frame.startupFileName = os.path.join(confDir,'pycrust_startup')
+## self.frame.historyFileName = os.path.join(confDir,'pycrust_history')
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ return True
+
+
+'''
+The main() function needs to handle being imported, such as with the
+pycrust script that wxPython installs:
+
+ #!/usr/bin/env python2
+
+ from wx.py.PyCrust import main
+ main()
+'''
+
+def main():
+ """The main function for the PyCrust program."""
+ # Cleanup the main namespace, leaving the App class.
+ import __main__
+ md = __main__.__dict__
+ keepers = original
+ keepers.append('App')
+ for key in md.keys():
+ if key not in keepers:
+ del md[key]
+ # Create an application instance.
+ app = App(0)
+ # Mimic the contents of the standard Python shell's sys.path.
+ import sys
+ if sys.path[0]:
+ sys.path[0] = ''
+ # Add the application object to the sys module's namespace.
+ # This allows a shell user to do:
+ # >>> import sys
+ # >>> sys.app.whatever
+ sys.app = app
+ del sys
+ # Cleanup the main namespace some more.
+ if md.has_key('App') and md['App'] is App:
+ del md['App']
+ if md.has_key('__main__') and md['__main__'] is __main__:
+ del md['__main__']
+ # Start the wxPython event loop.
+ app.MainLoop()
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyFilling.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyFilling.py
new file mode 100644
index 0000000..d5893c1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyFilling.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python2
+"""PyFilling is a python namespace inspection application."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+# We use this object to get more introspection when run standalone.
+app = None
+
+import filling
+
+# These are imported just to have something interesting to inspect.
+import crust
+import interpreter
+import introspect
+import pseudo
+import shell
+import sys
+import wx
+
+class App(filling.App):
+ def OnInit(self):
+ filling.App.OnInit(self)
+ self.root = self.fillingFrame.filling.tree.root
+ return True
+
+def main():
+ """Create and run the application."""
+ global app
+ app = App(0)
+ app.fillingFrame.filling.tree.Expand(app.root)
+ app.MainLoop()
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyShell.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyShell.py
new file mode 100644
index 0000000..d48409c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyShell.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python2
+"""PyShell is a python shell application."""
+
+# The next two lines, and the other code below that makes use of
+# ``__main__`` and ``original``, serve the purpose of cleaning up the
+# main namespace to look as much as possible like the regular Python
+# shell environment.
+import __main__
+original = __main__.__dict__.keys()
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+import os
+
+class App(wx.App):
+ """PyShell standalone application."""
+
+ def OnInit(self):
+ import os
+ import wx
+ from wx import py
+
+ self.SetAppName("pyshell")
+ confDir = wx.StandardPaths.Get().GetUserDataDir()
+ if not os.path.exists(confDir):
+ os.mkdir(confDir)
+ fileName = os.path.join(confDir, 'config')
+ self.config = wx.FileConfig(localFilename=fileName)
+ self.config.SetRecordDefaults(True)
+
+ self.frame = py.shell.ShellFrame(config=self.config, dataDir=confDir)
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ return True
+
+'''
+The main() function needs to handle being imported, such as with the
+pyshell script that wxPython installs:
+
+ #!/usr/bin/env python2
+
+ from wx.py.PyShell import main
+ main()
+'''
+
+def main():
+ """The main function for the PyShell program."""
+ # Cleanup the main namespace, leaving the App class.
+ import __main__
+ md = __main__.__dict__
+ keepers = original
+ keepers.append('App')
+ for key in md.keys():
+ if key not in keepers:
+ del md[key]
+ # Create an application instance.
+ app = App(0)
+ # Cleanup the main namespace some more.
+ if md.has_key('App') and md['App'] is App:
+ del md['App']
+ if md.has_key('__main__') and md['__main__'] is __main__:
+ del md['__main__']
+ # Mimic the contents of the standard Python shell's sys.path.
+ import sys
+ if sys.path[0]:
+ sys.path[0] = ''
+ # Add the application object to the sys module's namespace.
+ # This allows a shell user to do:
+ # >>> import sys
+ # >>> sys.app.whatever
+ sys.app = app
+ del sys
+ # Start the wxPython event loop.
+ app.MainLoop()
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlices.ico b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlices.ico
new file mode 100644
index 0000000..b237a84
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlices.ico
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlices.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlices.py
new file mode 100644
index 0000000..d47c900
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlices.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python2
+"""PySlices is a python block code editor / shell and namespace browser application."""
+
+# The next two lines, and the other code below that makes use of
+# ``__main__`` and ``original``, serve the purpose of cleaning up the
+# main namespace to look as much as possible like the regular Python
+# shell environment.
+import __main__
+original = __main__.__dict__.keys()
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com> / "
+__author__ += "David N. Mashburn <david.n.mashburn@gmail.com>"
+__cvsid__ = "$Id: PySlices.py 36607 2005-12-30 23:02:03Z RD $" # Hmmm...
+__revision__ = "$Revision: 36607 $"[11:-2] #Hmmm...
+
+import wx
+import os
+
+class App(wx.App):
+ """PySlices standalone application."""
+
+ def __init__(self, filename=None):
+ self.filename = filename
+ import wx
+ wx.App.__init__(self, redirect=False)
+
+
+ def OnInit(self):
+ import os
+ import wx
+ from wx import py
+
+ self.SetAppName("pyslices")
+ confDir = wx.StandardPaths.Get().GetUserDataDir()
+ if not os.path.exists(confDir):
+ os.mkdir(confDir)
+ fileName = os.path.join(confDir, 'config')
+ self.config = wx.FileConfig(localFilename=fileName)
+ self.config.SetRecordDefaults(True)
+
+ self.frame = py.crustslices.CrustSlicesFrame(config=self.config, dataDir=confDir,
+ filename=self.filename)
+## self.frame.startupFileName = os.path.join(confDir,'pycrust_startup')
+## self.frame.historyFileName = os.path.join(confDir,'pycrust_history')
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ return True
+
+
+'''
+The main() function needs to handle being imported, such as with the
+pycrust script that wxPython installs:
+
+ #!/usr/bin/env python2
+
+ from wx.py.PySlices import main
+ main()
+'''
+
+def main(filename=None):
+ """The main function for the PySlices program."""
+ # Cleanup the main namespace, leaving the App class.
+ import sys
+ if not filename and len(sys.argv) > 1:
+ filename = sys.argv[1]
+ if filename:
+ filename = os.path.realpath(filename)
+
+ import __main__
+ md = __main__.__dict__
+ keepers = original
+ keepers.append('App')
+ keepers.append('filename')
+ for key in md.keys():
+ if key not in keepers:
+ del md[key]
+ # Create an application instance.
+ app = App(filename=filename)
+ # Mimic the contents of the standard Python shell's sys.path.
+ import sys
+ if sys.path[0]:
+ sys.path[0] = ''
+ # Add the application object to the sys module's namespace.
+ # This allows a shell user to do:
+ # >>> import sys
+ # >>> sys.app.whatever
+ sys.app = app
+ del sys
+ # Cleanup the main namespace some more.
+ if md.has_key('App') and md['App'] is App:
+ del md['App']
+ if md.has_key('filename') and md['filename'] is filename:
+ del md['filename']
+ if md.has_key('__main__') and md['__main__'] is __main__:
+ del md['__main__']
+ # Start the wxPython event loop.
+ app.MainLoop()
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlicesShell.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlicesShell.py
new file mode 100644
index 0000000..28b500e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PySlicesShell.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python2
+"""PySlicesShell is a python shell application."""
+
+# The next two lines, and the other code below that makes use of
+# ``__main__`` and ``original``, serve the purpose of cleaning up the
+# main namespace to look as much as possible like the regular Python
+# shell environment.
+import __main__
+original = __main__.__dict__.keys()
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id: PySlicesShell.py 41078 2006-09-09 00:38:53Z RD $"
+__revision__ = "$Revision: 41078 $"[11:-2]
+
+import wx
+import os
+
+class App(wx.App):
+ """PySlicesShell standalone application."""
+
+ def __init__(self, filename=None):
+ self.filename = filename
+ import wx
+ wx.App.__init__(self, redirect=False)
+
+ def OnInit(self):
+ import os
+ import wx
+ from wx import py
+
+ self.SetAppName("pysliceshell")
+ confDir = wx.StandardPaths.Get().GetUserDataDir()
+ if not os.path.exists(confDir):
+ os.mkdir(confDir)
+ fileName = os.path.join(confDir, 'config')
+ self.config = wx.FileConfig(localFilename=fileName)
+ self.config.SetRecordDefaults(True)
+
+ self.frame = py.sliceshell.SlicesShellFrame(config=self.config,
+ dataDir=confDir,
+ filename=self.filename)
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ return True
+
+'''
+The main() function needs to handle being imported, such as with the
+pyshell script that wxPython installs:
+
+ #!/usr/bin/env python2
+
+ from wx.py.PySlicesShell import main
+ main()
+'''
+
+def main(filename=None):
+ """The main function for the PySlicesShell program."""
+ # Cleanup the main namespace, leaving the App class.
+ import sys
+ if not filename and len(sys.argv) > 1:
+ filename = sys.argv[1]
+ if filename:
+ filename = os.path.realpath(filename)
+
+ import __main__
+ md = __main__.__dict__
+ keepers = original
+ keepers.append('App')
+ keepers.append('filename')
+ for key in md.keys():
+ if key not in keepers:
+ del md[key]
+ # Create an application instance.
+ app = App(filename=filename)
+ # Cleanup the main namespace some more.
+ if md.has_key('App') and md['App'] is App:
+ del md['App']
+ if md.has_key('filename') and md['filename'] is filename:
+ del md['filename']
+ if md.has_key('__main__') and md['__main__'] is __main__:
+ del md['__main__']
+ # Mimic the contents of the standard Python shell's sys.path.
+ import sys
+ if sys.path[0]:
+ sys.path[0] = ''
+ # Add the application object to the sys module's namespace.
+ # This allows a shell user to do:
+ # >>> import sys
+ # >>> sys.app.whatever
+ sys.app = app
+ del sys
+ # Start the wxPython event loop.
+ app.MainLoop()
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyWrap.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyWrap.py
new file mode 100644
index 0000000..fafa382
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/PyWrap.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python2
+"""PyWrap is a command line utility that runs a wxPython program with
+additional runtime-tools, such as PyCrust."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+from wx import py
+
+import os
+import sys
+
+def wrap(app):
+ wx.InitAllImageHandlers()
+ frame = py.crust.CrustFrame()
+ frame.SetSize((750, 525))
+ frame.Show(True)
+ frame.shell.interp.locals['app'] = app
+ app.MainLoop()
+
+def main(modulename=None):
+ sys.path.insert(0, os.curdir)
+ if not modulename:
+ if len(sys.argv) < 2:
+ print "Please specify a module name."
+ raise SystemExit
+ modulename = sys.argv[1]
+ if modulename.endswith('.py'):
+ modulename = modulename[:-3]
+ module = __import__(modulename)
+ # Find the App class.
+ App = None
+ d = module.__dict__
+ for item in d.keys():
+ try:
+ if issubclass(d[item], wx.App):
+ App = d[item]
+ except (NameError, TypeError):
+ pass
+ if App is None:
+ print "No App class was found."
+ raise SystemExit
+ app = App()
+ wrap(app)
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/README.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/README.txt
new file mode 100644
index 0000000..2d70db7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/README.txt
@@ -0,0 +1,83 @@
+=====================================
+ PyCrust - The Flakiest Python Shell
+=====================================
+
+Half-baked by Patrick K. O'Brien (pobrien@orbtech.com)
+
+Orbtech - "Your source for Python programming expertise."
+Sample all our half-baked Python goods at www.orbtech.com.
+
+
+What is PyCrust?
+----------------
+
+PyCrust is an interactive Python environment written in Python.
+PyCrust components can run standalone or be integrated into other
+development environments and/or other Python applications.
+
+PyCrust comes with an interactive Python shell (PyShell), an
+interactive namespace/object tree control (PyFilling) and an
+integrated, split-window combination of the two (PyCrust).
+
+
+What is PyCrust good for?
+-------------------------
+
+Have you ever tried to bake a pie without one? Well, you shouldn't
+build a Python program without a PyCrust either.
+
+
+What else do I need to use PyCrust?
+-----------------------------------
+
+PyCrust requires Python 2.2 or later, and wxPython 2.4 or later.
+PyCrust uses wxPython and the Scintilla wrapper (wxStyledTextCtrl).
+Python is available at http://www.python.org/. wxPython is available
+at http://www.wxpython.org/.
+
+
+Where can I get the latest version of PyCrust?
+----------------------------------------------
+
+The latest production version ships with wxPython. The latest
+developer version is available in the wxWindows CVS at:
+http://cvs.wxwindows.org/viewcvs.cgi/
+
+
+Where is the PyCrust project hosted?
+------------------------------------
+
+The old answer was "At SourceForge, of course." The SourceForge
+summary page is still available at:
+http://sourceforge.net/projects/pycrust/
+
+The new answer is that there is no longer a need for a separate
+project. Simply install wxPython and you'll have everything you need.
+
+
+I found a bug in PyCrust, what do I do with it?
+-----------------------------------------------
+
+You can send it to me at pobrien@orbtech.com.
+
+
+I want a new feature added to PyCrust. Will you do it?
+------------------------------------------------------
+
+Flattery and money will get you anything. Short of that, you can send
+me a request and I'll see what I can do.
+
+
+Does PyCrust have a mailing list full of wonderful people?
+----------------------------------------------------------
+
+As a matter of fact, we do. Join the PyCrust mailing lists at:
+http://sourceforge.net/mail/?group_id=31263
+
+
+What is the CVS information for this README file?
+-------------------------------------------------
+
+$Date$
+$Revision$
+$Id$
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/__init__.py
new file mode 100644
index 0000000..edf6fb5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/__init__.py
@@ -0,0 +1,22 @@
+"""The py package, formerly the PyCrust package."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import buffer
+import crust
+import crustslices
+import dispatcher
+import document
+import editor
+import editwindow
+import filling
+import frame
+import images
+import interpreter
+import introspect
+import pseudo
+import shell
+import sliceshell
+import version
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/buffer.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/buffer.py
new file mode 100644
index 0000000..7766694
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/buffer.py
@@ -0,0 +1,138 @@
+"""Buffer class."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+from interpreter import Interpreter
+import imp
+import os
+import sys
+
+import document
+
+
+class Buffer:
+ """Buffer class."""
+
+ id = 0
+
+ def __init__(self, filename=None):
+ """Create a Buffer instance."""
+ Buffer.id += 1
+ self.id = Buffer.id
+ self.interp = Interpreter(locals={})
+ self.name = ''
+ self.editors = {}
+ self.editor = None
+ self.modules = sys.modules.keys()
+ self.syspath = sys.path[:]
+ while True:
+ try:
+ self.syspath.remove('')
+ except ValueError:
+ break
+ while True:
+ try:
+ self.syspath.remove('.')
+ except ValueError:
+ break
+ self.open(filename)
+
+ def addEditor(self, editor):
+ """Add an editor."""
+ self.editor = editor
+ self.editors[editor.id] = editor
+
+ def hasChanged(self):
+ """Return True if text in editor has changed since last save."""
+ if self.editor:
+ return self.editor.hasChanged()
+ else:
+ return False
+
+ def new(self, filepath):
+ """New empty buffer."""
+ if not filepath:
+ return
+ if os.path.exists(filepath):
+ self.confirmed = self.overwriteConfirm(filepath)
+ else:
+ self.confirmed = True
+
+ def open(self, filename):
+ """Open file into buffer."""
+ self.doc = document.Document(filename)
+ self.name = self.doc.filename or ('Untitled:' + str(self.id))
+ self.modulename = self.doc.filebase
+ # XXX This should really make sure filedir is first item in syspath.
+ # XXX Or maybe this should be moved to the update namespace method.
+ if self.doc.filedir and self.doc.filedir not in self.syspath:
+ # To create the proper context for updateNamespace.
+ self.syspath.insert(0, self.doc.filedir)
+ if self.doc.filepath and os.path.exists(self.doc.filepath):
+ self.confirmed = True
+ if self.editor:
+ text = self.doc.read()
+ self.editor._setBuffer(buffer=self, text=text)
+
+ def overwriteConfirm(self, filepath):
+ """Confirm overwriting an existing file."""
+ return False
+
+ def save(self):
+ """Save buffer."""
+ filepath = self.doc.filepath
+ if not filepath:
+ return # XXX Get filename
+ if not os.path.exists(filepath):
+ self.confirmed = True
+ if not self.confirmed:
+ self.confirmed = self.overwriteConfirm(filepath)
+ if self.confirmed:
+ self.doc.write(self.editor.getText())
+ if self.editor:
+ self.editor.setSavePoint()
+
+ def saveAs(self, filename):
+ """Save buffer."""
+ self.doc = document.Document(filename)
+ self.name = self.doc.filename
+ self.modulename = self.doc.filebase
+ self.save()
+
+ def updateNamespace(self):
+ """Update the namespace for autocompletion and calltips.
+
+ Return True if updated, False if there was an error."""
+ if not self.interp or not hasattr(self.editor, 'getText'):
+ return False
+ syspath = sys.path
+ sys.path = self.syspath
+ text = self.editor.getText()
+ text = text.replace('\r\n', '\n')
+ text = text.replace('\r', '\n')
+ name = self.modulename or self.name
+ module = imp.new_module(name)
+ newspace = module.__dict__.copy()
+ try:
+ try:
+ code = compile(text, name, 'exec')
+ except:
+ raise
+# return False
+ try:
+ exec code in newspace
+ except:
+ raise
+# return False
+ else:
+ # No problems, so update the namespace.
+ self.interp.locals.clear()
+ self.interp.locals.update(newspace)
+ return True
+ finally:
+ sys.path = syspath
+ for m in sys.modules.keys():
+ if m not in self.modules:
+ del sys.modules[m]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/crust.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/crust.py
new file mode 100644
index 0000000..aed30a1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/crust.py
@@ -0,0 +1,379 @@
+"""Crust combines the shell and filling into one control."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+
+import os
+import pprint
+import re
+import sys
+
+import dispatcher
+import editwindow
+from filling import Filling
+import frame
+from shell import Shell
+from version import VERSION
+
+
+class Crust(wx.SplitterWindow):
+ """Crust based on SplitterWindow."""
+
+ name = 'Crust'
+ revision = __revision__
+ sashoffset = 300
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.SP_3D|wx.SP_LIVE_UPDATE,
+ name='Crust Window', rootObject=None, rootLabel=None,
+ rootIsNamespace=True, intro='', locals=None,
+ InterpClass=None,
+ startupScript=None, execStartupScript=True,
+ *args, **kwds):
+ """Create Crust instance."""
+ wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name)
+
+ # Turn off the tab-traversal style that is automatically
+ # turned on by wx.SplitterWindow. We do this because on
+ # Windows the event for Ctrl-Enter is stolen and used as a
+ # navigation key, but the Shell window uses it to insert lines.
+ style = self.GetWindowStyle()
+ self.SetWindowStyle(style & ~wx.TAB_TRAVERSAL)
+
+ self.shell = Shell(parent=self, introText=intro,
+ locals=locals, InterpClass=InterpClass,
+ startupScript=startupScript,
+ execStartupScript=execStartupScript,
+ *args, **kwds)
+
+ self.editor = self.shell
+ if rootObject is None:
+ rootObject = self.shell.interp.locals
+ self.notebook = wx.Notebook(parent=self, id=-1)
+ self.shell.interp.locals['notebook'] = self.notebook
+ self.filling = Filling(parent=self.notebook,
+ rootObject=rootObject,
+ rootLabel=rootLabel,
+ rootIsNamespace=rootIsNamespace)
+ # Add 'filling' to the interpreter's locals.
+ self.shell.interp.locals['filling'] = self.filling
+ self.notebook.AddPage(page=self.filling, text='Namespace', select=True)
+
+ self.display = Display(parent=self.notebook)
+ self.notebook.AddPage(page=self.display, text='Display')
+ # Add 'pp' (pretty print) to the interpreter's locals.
+ self.shell.interp.locals['pp'] = self.display.setItem
+ self.display.nbTab = self.notebook.GetPageCount()-1
+
+ self.calltip = Calltip(parent=self.notebook)
+ self.notebook.AddPage(page=self.calltip, text='Calltip')
+
+ self.sessionlisting = SessionListing(parent=self.notebook)
+ self.notebook.AddPage(page=self.sessionlisting, text='History')
+
+ self.dispatcherlisting = DispatcherListing(parent=self.notebook)
+ self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher')
+
+
+ # Initialize in an unsplit mode, and check later after loading
+ # settings if we should split or not.
+ self.shell.Hide()
+ self.notebook.Hide()
+ self.Initialize(self.shell)
+ self._shouldsplit = True
+ wx.CallAfter(self._CheckShouldSplit)
+ self.SetMinimumPaneSize(100)
+
+ self.Bind(wx.EVT_SIZE, self.SplitterOnSize)
+ self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnChanged)
+ self.Bind(wx.EVT_SPLITTER_DCLICK, self.OnSashDClick)
+
+ def _CheckShouldSplit(self):
+ if self._shouldsplit:
+ self.SplitHorizontally(self.shell, self.notebook, -self.sashoffset)
+ self.lastsashpos = self.GetSashPosition()
+ else:
+ self.lastsashpos = -1
+ self.issplit = self.IsSplit()
+
+ def ToggleTools(self):
+ """Toggle the display of the filling and other tools"""
+ if self.issplit:
+ self.Unsplit()
+ else:
+ self.SplitHorizontally(self.shell, self.notebook, -self.sashoffset)
+ self.lastsashpos = self.GetSashPosition()
+ self.issplit = self.IsSplit()
+
+ def ToolsShown(self):
+ return self.issplit
+
+ def OnChanged(self, event):
+ """update sash offset from the bottom of the window"""
+ self.sashoffset = self.GetSize().height - event.GetSashPosition()
+ self.lastsashpos = event.GetSashPosition()
+ event.Skip()
+
+ def OnSashDClick(self, event):
+ self.Unsplit()
+ self.issplit = False
+
+ # Make the splitter expand the top window when resized
+ def SplitterOnSize(self, event):
+ splitter = event.GetEventObject()
+ sz = splitter.GetSize()
+ splitter.SetSashPosition(sz.height - self.sashoffset, True)
+ event.Skip()
+
+
+ def LoadSettings(self, config):
+ self.shell.LoadSettings(config)
+ self.filling.LoadSettings(config)
+
+ pos = config.ReadInt('Sash/CrustPos', 400)
+ wx.CallAfter(self.SetSashPosition, pos)
+ def _updateSashPosValue():
+ sz = self.GetSize()
+ self.sashoffset = sz.height - self.GetSashPosition()
+ wx.CallAfter(_updateSashPosValue)
+ zoom = config.ReadInt('View/Zoom/Display', -99)
+ if zoom != -99:
+ self.display.SetZoom(zoom)
+ self.issplit = config.ReadInt('Sash/IsSplit', True)
+ if not self.issplit:
+ self._shouldsplit = False
+
+ def SaveSettings(self, config):
+ self.shell.SaveSettings(config)
+ self.filling.SaveSettings(config)
+
+ if self.lastsashpos != -1:
+ config.WriteInt('Sash/CrustPos', self.lastsashpos)
+ config.WriteInt('Sash/IsSplit', self.issplit)
+ config.WriteInt('View/Zoom/Display', self.display.GetZoom())
+
+class Display(editwindow.EditWindow):
+ """STC used to display an object using Pretty Print."""
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize,
+ style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER,
+ static=False):
+ """Create Display instance."""
+ editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
+ # Configure various defaults and user preferences.
+ self.SetReadOnly(True)
+ self.SetWrapMode(False)
+ if not static:
+ dispatcher.connect(receiver=self.push, signal='Interpreter.push')
+
+ def push(self, command, more):
+ """Receiver for Interpreter.push signal."""
+ self.Refresh()
+
+ def Refresh(self):
+ if not hasattr(self, "item"):
+ return
+ self.SetReadOnly(False)
+ text = pprint.pformat(self.item)
+ self.SetText(text)
+ self.SetReadOnly(True)
+
+ def setItem(self, item):
+ """Set item to pretty print in the notebook Display tab."""
+ self.item = item
+ self.Refresh()
+ if self.GetParent().GetSelection() != self.nbTab:
+ focus = wx.Window.FindFocus()
+ self.GetParent().SetSelection(self.nbTab)
+ wx.CallAfter(focus.SetFocus)
+
+
+# TODO: Switch this to a editwindow.EditWindow
+class Calltip(wx.TextCtrl):
+ """Text control containing the most recent shell calltip."""
+
+ def __init__(self, parent=None, id=-1,ShellClassName='Shell'):
+ style = (wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2)
+ wx.TextCtrl.__init__(self, parent, id, style=style)
+ self.SetBackgroundColour(wx.Colour(255, 255, 208))
+ self.ShellClassName=ShellClassName
+ dispatcher.connect(receiver=self.display, signal=self.ShellClassName+'.calltip')
+
+ df = self.GetFont()
+ font = wx.Font(df.GetPointSize(), wx.TELETYPE, wx.NORMAL, wx.NORMAL)
+ self.SetFont(font)
+
+ def display(self, calltip):
+ """Receiver for """+self.ShellClassName+""".calltip signal."""
+ ## self.SetValue(calltip) # Caused refresh problem on Windows.
+ self.Clear()
+ self.AppendText(calltip)
+ self.SetInsertionPoint(0)
+
+
+# TODO: Switch this to a editwindow.EditWindow
+class SessionListing(wx.TextCtrl):
+ """Text control containing all commands for session."""
+
+ def __init__(self, parent=None, id=-1,ShellClassName='Shell'):
+ style = (wx.TE_MULTILINE | wx.TE_READONLY |
+ wx.TE_RICH2 | wx.TE_DONTWRAP)
+ wx.TextCtrl.__init__(self, parent, id, style=style)
+ dispatcher.connect(receiver=self.addHistory,
+ signal=ShellClassName+".addHistory")
+ dispatcher.connect(receiver=self.clearHistory,
+ signal=ShellClassName+".clearHistory")
+ dispatcher.connect(receiver=self.loadHistory,
+ signal=ShellClassName+".loadHistory")
+
+ df = self.GetFont()
+ font = wx.Font(df.GetPointSize(), wx.TELETYPE, wx.NORMAL, wx.NORMAL)
+ self.SetFont(font)
+
+ def loadHistory(self, history):
+ # preload the existing history, if any
+ hist = history[:]
+ hist.reverse()
+ self.SetValue('\n'.join(hist) + '\n')
+ self.SetInsertionPointEnd()
+
+ def addHistory(self, command):
+ if command:
+ self.SetInsertionPointEnd()
+ self.AppendText(command + '\n')
+
+ def clearHistory(self):
+ self.SetValue("")
+
+
+class DispatcherListing(wx.TextCtrl):
+ """Text control containing all dispatches for session."""
+
+ def __init__(self, parent=None, id=-1):
+ style = (wx.TE_MULTILINE | wx.TE_READONLY |
+ wx.TE_RICH2 | wx.TE_DONTWRAP)
+ wx.TextCtrl.__init__(self, parent, id, style=style)
+ dispatcher.connect(receiver=self.spy)
+
+ df = self.GetFont()
+ font = wx.Font(df.GetPointSize(), wx.TELETYPE, wx.NORMAL, wx.NORMAL)
+ self.SetFont(font)
+
+ def spy(self, signal, sender):
+ """Receiver for Any signal from Any sender."""
+ text = '%r from %s' % (signal, sender)
+ self.SetInsertionPointEnd()
+ start, end = self.GetSelection()
+ if start != end:
+ self.SetSelection(0, 0)
+ self.AppendText(text + '\n')
+
+
+
+class CrustFrame(frame.Frame, frame.ShellFrameMixin):
+ """Frame containing all the PyCrust components."""
+
+ name = 'CrustFrame'
+ revision = __revision__
+
+
+ def __init__(self, parent=None, id=-1, title='PyCrust',
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_FRAME_STYLE,
+ rootObject=None, rootLabel=None, rootIsNamespace=True,
+ locals=None, InterpClass=None,
+ config=None, dataDir=None,
+ *args, **kwds):
+ """Create CrustFrame instance."""
+ frame.Frame.__init__(self, parent, id, title, pos, size, style,
+ shellName='PyCrust')
+ frame.ShellFrameMixin.__init__(self, config, dataDir)
+
+ if size == wx.DefaultSize:
+ self.SetSize((800, 600))
+
+ intro = 'PyCrust %s - The Flakiest Python Shell' % VERSION
+
+ self.SetStatusText(intro.replace('\n', ', '))
+ self.crust = Crust(parent=self, intro=intro,
+ rootObject=rootObject,
+ rootLabel=rootLabel,
+ rootIsNamespace=rootIsNamespace,
+ locals=locals,
+ InterpClass=InterpClass,
+ startupScript=self.startupScript,
+ execStartupScript=self.execStartupScript,
+ *args, **kwds)
+ self.shell = self.crust.shell
+
+ # Override the filling so that status messages go to the status bar.
+ self.crust.filling.tree.setStatusText = self.SetStatusText
+
+ # Override the shell so that status messages go to the status bar.
+ self.shell.setStatusText = self.SetStatusText
+
+ self.shell.SetFocus()
+ self.LoadSettings()
+
+
+ def OnClose(self, event):
+ """Event handler for closing."""
+ self.SaveSettings()
+ self.crust.shell.destroy()
+ self.Destroy()
+
+
+ def OnAbout(self, event):
+ """Display an About window."""
+ title = 'About PyCrust'
+ text = 'PyCrust %s\n\n' % VERSION + \
+ 'Yet another Python shell, only flakier.\n\n' + \
+ 'Half-baked by Patrick K. O\'Brien,\n' + \
+ 'the other half is still in the oven.\n\n' + \
+ 'Shell Revision: %s\n' % self.shell.revision + \
+ 'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
+ 'Platform: %s\n' % sys.platform + \
+ 'Python Version: %s\n' % sys.version.split()[0] + \
+ 'wxPython Version: %s\n' % wx.VERSION_STRING + \
+ ('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:]))
+ dialog = wx.MessageDialog(self, text, title,
+ wx.OK | wx.ICON_INFORMATION)
+ dialog.ShowModal()
+ dialog.Destroy()
+
+
+ def ToggleTools(self):
+ """Toggle the display of the filling and other tools"""
+ return self.crust.ToggleTools()
+
+ def ToolsShown(self):
+ return self.crust.ToolsShown()
+
+ def OnHelp(self, event):
+ """Show a help dialog."""
+ frame.ShellFrameMixin.OnHelp(self, event)
+
+ def LoadSettings(self):
+ if self.config is not None:
+ frame.ShellFrameMixin.LoadSettings(self)
+ frame.Frame.LoadSettings(self, self.config)
+ self.crust.LoadSettings(self.config)
+
+
+ def SaveSettings(self, force=False):
+ if self.config is not None:
+ frame.ShellFrameMixin.SaveSettings(self,force)
+ if self.autoSaveSettings or force:
+ frame.Frame.SaveSettings(self, self.config)
+ self.crust.SaveSettings(self.config)
+
+
+ def DoSaveSettings(self):
+ if self.config is not None:
+ self.SaveSettings(force=True)
+ self.config.Flush()
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/crustslices.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/crustslices.py
new file mode 100644
index 0000000..aa7bd23
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/crustslices.py
@@ -0,0 +1,416 @@
+"""PySlices combines the slices and filling into one control."""
+
+__author__ = "David N. Mashburn <david.n.mashburn@gmail.com> / "
+__author__ += "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id: crustslices.py 44235 2007-01-17 23:05:14Z RD $"
+__revision__ = "$Revision: 44235 $"[11:-2]
+
+import wx
+
+import os
+import pprint
+import re
+import sys
+
+import dispatcher
+import crust
+import document
+import editwindow
+import editor
+from filling import Filling
+import frame
+from sliceshell import SlicesShell
+from version import VERSION
+
+
+class CrustSlices(crust.Crust):
+ """Slices based on SplitterWindow."""
+
+ name = 'Slices'
+ revision = __revision__
+ sashoffset = 300
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.SP_3D|wx.SP_LIVE_UPDATE,
+ name='Slices Window', rootObject=None, rootLabel=None,
+ rootIsNamespace=True, intro='', locals=None,
+ InterpClass=None,
+ startupScript=None, execStartupScript=True,
+ showPySlicesTutorial=True,
+ enableShellMode=False, hideFoldingMargin=False,
+ *args, **kwds):
+ """Create CrustSlices instance."""
+ wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name)
+
+ # Turn off the tab-traversal style that is automatically
+ # turned on by wx.SplitterWindow. We do this because on
+ # Windows the event for Ctrl-Enter is stolen and used as a
+ # navigation key, but the SlicesShell window uses it to insert lines.
+ style = self.GetWindowStyle()
+ self.SetWindowStyle(style & ~wx.TAB_TRAVERSAL)
+
+ self.sliceshell = SlicesShell(parent=self, introText=intro,
+ locals=locals, InterpClass=InterpClass,
+ startupScript=startupScript,
+ execStartupScript=execStartupScript,
+ showPySlicesTutorial=showPySlicesTutorial,
+ enableShellMode=enableShellMode,
+ hideFoldingMargin=hideFoldingMargin,
+ *args, **kwds)
+
+ self.editor = self.sliceshell
+ self.shell = self.sliceshell
+ if rootObject is None:
+ rootObject = self.sliceshell.interp.locals
+ self.notebook = wx.Notebook(parent=self, id=-1)
+ self.sliceshell.interp.locals['notebook'] = self.notebook
+ self.filling = Filling(parent=self.notebook,
+ rootObject=rootObject,
+ rootLabel=rootLabel,
+ rootIsNamespace=rootIsNamespace)
+ # Add 'filling' to the interpreter's locals.
+ self.sliceshell.interp.locals['filling'] = self.filling
+ self.notebook.AddPage(page=self.filling, text='Namespace', select=True)
+
+ self.display = crust.Display(parent=self.notebook)
+ self.notebook.AddPage(page=self.display, text='Display')
+ # Add 'pp' (pretty print) to the interpreter's locals.
+ self.sliceshell.interp.locals['pp'] = self.display.setItem
+ self.display.nbTab = self.notebook.GetPageCount()-1
+
+ self.calltip = crust.Calltip(parent=self.notebook,ShellClassName='SlicesShell')
+ self.notebook.AddPage(page=self.calltip, text='Calltip')
+
+ self.sessionlisting = crust.SessionListing(parent=self.notebook,ShellClassName='SlicesShell')
+ self.notebook.AddPage(page=self.sessionlisting, text='History')
+
+ self.dispatcherlisting = crust.DispatcherListing(parent=self.notebook)
+ self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher')
+
+
+ # Initialize in an unsplit mode, and check later after loading
+ # settings if we should split or not.
+ self.sliceshell.Hide()
+ self.notebook.Hide()
+ self.Initialize(self.sliceshell)
+ self._shouldsplit = True
+ wx.CallAfter(self._CheckShouldSplit)
+ self.SetMinimumPaneSize(100)
+
+ self.Bind(wx.EVT_SIZE, self.SplitterOnSize)
+ self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnChanged)
+ self.Bind(wx.EVT_SPLITTER_DCLICK, self.OnSashDClick)
+
+class CrustSlicesFrame(crust.CrustFrame):
+ """Frame containing all the PySlices components."""
+
+ name = 'SliceFrame'
+ revision = __revision__
+
+
+ def __init__(self, parent=None, id=-1, title='PySlices',
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_FRAME_STYLE,
+ rootObject=None, rootLabel=None, rootIsNamespace=True,
+ locals=None, InterpClass=None,
+ config=None, dataDir=None, filename=None,
+ *args, **kwds):
+ """Create CrustFrame instance."""
+ frame.Frame.__init__(self, parent, id, title, pos, size, style,
+ shellName='PySlices')
+ frame.ShellFrameMixin.__init__(self, config, dataDir)
+
+ if size == wx.DefaultSize:
+ self.SetSize((800, 600))
+
+ intro = 'PySlices %s - The Flakiest Python Shell... Cut up!' % VERSION
+
+ self.SetStatusText(intro.replace('\n', ', '))
+ self.crust = CrustSlices(parent=self, intro=intro,
+ rootObject=rootObject,
+ rootLabel=rootLabel,
+ rootIsNamespace=rootIsNamespace,
+ locals=locals,
+ InterpClass=InterpClass,
+ startupScript=self.startupScript,
+ execStartupScript=self.execStartupScript,
+ showPySlicesTutorial=self.showPySlicesTutorial,
+ enableShellMode=self.enableShellMode,
+ hideFoldingMargin=self.hideFoldingMargin,
+ *args, **kwds)
+ self.sliceshell = self.crust.sliceshell
+ self.buffer = self.sliceshell.buffer
+ # Override the filling so that status messages go to the status bar.
+ self.crust.filling.tree.setStatusText = self.SetStatusText
+
+ # Override the shell so that status messages go to the status bar.
+ self.sliceshell.setStatusText = self.SetStatusText
+
+ self.sliceshell.SetFocus()
+ self.LoadSettings()
+
+ self.currentDirectory = os.path.expanduser('~')
+
+ if filename!=None:
+ self.bufferOpen(filename)
+
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+ def OnClose(self, event):
+ """Event handler for closing."""
+ self.bufferClose()
+
+ def OnAbout(self, event):
+ """Display an About window."""
+ title = 'About PySlices'
+ text = 'PySlices %s\n\n' % VERSION + \
+ 'Yet another Python shell, only flakier.\n\n' + \
+ 'Half-baked by Patrick K. O\'Brien,\n' + \
+ 'the other half is still in the oven.\n\n' + \
+ 'Shell Revision: %s\n' % self.sliceshell.revision + \
+ 'Interpreter Revision: %s\n\n' % self.sliceshell.interp.revision + \
+ 'Platform: %s\n' % sys.platform + \
+ 'Python Version: %s\n' % sys.version.split()[0] + \
+ 'wxPython Version: %s\n' % wx.VERSION_STRING + \
+ ('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:]))
+ dialog = wx.MessageDialog(self, text, title,
+ wx.OK | wx.ICON_INFORMATION)
+ dialog.ShowModal()
+ dialog.Destroy()
+
+ def OnEnableShellMode(self,event):
+ """Change between Slices Mode and Shell Mode"""
+ frame.Frame.OnEnableShellMode(self,event)
+ self.sliceshell.ToggleShellMode(self.enableShellMode)
+
+ def OnHideFoldingMargin(self,event):
+ """Change between Slices Mode and Shell Mode"""
+ frame.Frame.OnHideFoldingMargin(self,event)
+ self.sliceshell.ToggleFoldingMargin(self.hideFoldingMargin)
+
+ # Stolen Straight from editor.EditorFrame
+ # Modified a little... :)
+ # ||
+ # \/
+ def OnIdle(self, event):
+ """Event handler for idle time."""
+ self._updateTitle()
+ event.Skip()
+
+ def _updateTitle(self):
+ """Show current title information."""
+ title = self.GetTitle()
+ if self.bufferHasChanged():
+ if title.startswith('* '):
+ pass
+ else:
+ self.SetTitle('* ' + title)
+ else:
+ if title.startswith('* '):
+ self.SetTitle(title[2:])
+
+ def hasBuffer(self):
+ """Return True if there is a current buffer."""
+ if self.buffer:
+ return True
+ else:
+ return False
+
+ def bufferClose(self):
+ """Close buffer."""
+ if self.buffer.hasChanged():
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ #event.Veto()
+ return cancel
+ self.SaveSettings()
+ self.crust.sliceshell.destroy()
+ self.bufferDestroy()
+ self.Destroy()
+
+ return False
+
+ def bufferCreate(self, filename=None):
+ """Create new buffer."""
+ self.bufferDestroy()
+ buffer = Buffer()
+ self.panel = panel = wx.Panel(parent=self, id=-1)
+ panel.Bind (wx.EVT_ERASE_BACKGROUND, lambda x: x)
+ editor = Editor(parent=panel)
+ panel.editor = editor
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(editor.window, 1, wx.EXPAND)
+ panel.SetSizer(sizer)
+ panel.SetAutoLayout(True)
+ sizer.Layout()
+ buffer.addEditor(editor)
+ buffer.open(filename)
+ self.setEditor(editor)
+ self.editor.setFocus()
+ self.SendSizeEvent()
+
+
+ def bufferDestroy(self):
+ """Destroy the current buffer."""
+ if self.buffer:
+ self.editor = None
+ self.buffer = None
+
+
+ def bufferHasChanged(self):
+ """Return True if buffer has changed since last save."""
+ if self.buffer:
+ return self.buffer.hasChanged()
+ else:
+ return False
+
+ def bufferNew(self):
+ """Create new buffer."""
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+ self.sliceshell.clear()
+ self.SetTitle( 'PySlices')
+ self.sliceshell.NeedsCheckForSave=False
+ self.sliceshell.SetSavePoint()
+ self.buffer.doc = document.Document()
+ self.buffer.name = 'This shell'
+ self.buffer.modulename = self.buffer.doc.filebase
+ #self.bufferCreate()
+ cancel = False
+ return cancel
+
+ def bufferOpen(self,file=None):
+ """Open file in buffer."""
+ if self.bufferHasChanged():
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+
+ if file==None:
+ file=wx.FileSelector('Open a PySlices File',
+ wildcard='*.pyslices',
+ default_path=self.currentDirectory)
+ if file!=None and file!=u'':
+ fid=open(file,'r')
+ self.sliceshell.LoadPySlicesFile(fid)
+ fid.close()
+ self.currentDirectory = os.path.split(file)[0]
+ self.SetTitle( os.path.split(file)[1] + ' - PySlices')
+ self.sliceshell.NeedsCheckForSave=False
+ self.sliceshell.SetSavePoint()
+ self.buffer.doc = document.Document(file)
+ self.buffer.name = self.buffer.doc.filename
+ self.buffer.modulename = self.buffer.doc.filebase
+ self.sliceshell.ScrollToLine(0)
+ return
+
+## def bufferPrint(self):
+## """Print buffer."""
+## pass
+
+## def bufferRevert(self):
+## """Revert buffer to version of file on disk."""
+## pass
+
+ # was self.buffer.save(self): # """Save buffer."""
+ def simpleSave(self,confirmed=False):
+ filepath = self.buffer.doc.filepath
+ self.buffer.confirmed = confirmed
+ if not filepath:
+ return # XXX Get filename
+ if not os.path.exists(filepath):
+ self.buffer.confirmed = True
+ if not self.buffer.confirmed:
+ self.buffer.confirmed = self.buffer.overwriteConfirm(filepath)
+ if self.buffer.confirmed:
+ try:
+ fid = open(filepath, 'wb')
+ self.sliceshell.SavePySlicesFile(fid)
+ finally:
+ if fid:
+ fid.close()
+ self.sliceshell.SetSavePoint()
+ self.SetTitle( os.path.split(filepath)[1] + ' - PySlices')
+ self.sliceshell.NeedsCheckForSave=False
+
+ def bufferSave(self):
+ """Save buffer to its file."""
+ if self.buffer.doc.filepath:
+ # self.buffer.save()
+ self.simpleSave(confirmed=True)
+ cancel = False
+ else:
+ cancel = self.bufferSaveAs()
+ return cancel
+
+ def bufferSaveAs(self):
+ """Save buffer to a new filename."""
+ if self.bufferHasChanged() and self.buffer.doc.filepath:
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+ filedir = ''
+ if self.buffer and self.buffer.doc.filedir:
+ filedir = self.buffer.doc.filedir
+ result = editor.saveSingle(title='Save PySlices File',directory=filedir,
+ wildcard='PySlices Files (*.pyslices)|*.pyslices')
+ if result.path not in ['',None]:
+ if result.path[-9:]!=".pyslices":
+ result.path+=".pyslices"
+
+ self.buffer.doc = document.Document(result.path)
+ self.buffer.name = self.buffer.doc.filename
+ self.buffer.modulename = self.buffer.doc.filebase
+ self.simpleSave(confirmed=True) # allow overwrite
+ cancel = False
+ else:
+ cancel = True
+ return cancel
+
+ def bufferSaveACopy(self):
+ """Save buffer to a new filename."""
+ filedir = ''
+ if self.buffer and self.buffer.doc.filedir:
+ filedir = self.buffer.doc.filedir
+ result = editor.saveSingle(title='Save a Copy of PySlices File',directory=filedir,
+ wildcard='PySlices Files (*.pyslices)|*.pyslices')
+
+ if result.path not in ['',None]:
+ if result.path[-9:]!=".pyslices":
+ result.path+=".pyslices"
+
+ # if not os.path.exists(result.path):
+ try: # Allow overwrite...
+ fid = open(result.path, 'wb')
+ self.sliceshell.SavePySlicesFile(fid)
+ finally:
+ if fid:
+ fid.close()
+
+ cancel = False
+ else:
+ cancel = True
+ return cancel
+
+ def bufferSuggestSave(self):
+ """Suggest saving changes. Return True if user selected Cancel."""
+ result = editor.messageDialog(parent=None,
+ message='%s has changed.\n'
+ 'Would you like to save it first'
+ '?' % self.buffer.name,
+ title='Save current file?',
+ style=wx.YES_NO | wx.CANCEL | wx.NO_DEFAULT |
+ wx.CENTRE | wx.ICON_QUESTION )
+ if result.positive:
+ cancel = self.bufferSave()
+ else:
+ cancel = result.text == 'Cancel'
+ return cancel
+
+ def updateNamespace(self):
+ """Update the buffer namespace for autocompletion and calltips."""
+ if self.buffer.updateNamespace():
+ self.SetStatusText('Namespace updated')
+ else:
+ self.SetStatusText('Error executing, unable to update namespace')
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/dispatcher.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/dispatcher.py
new file mode 100644
index 0000000..c2a4673
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/dispatcher.py
@@ -0,0 +1,262 @@
+"""Provides global signal dispatching services."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import exceptions
+import types
+import weakref
+
+
+class DispatcherError(exceptions.Exception):
+ def __init__(self, args=None):
+ self.args = args
+
+
+class Parameter:
+ """Used to represent default parameter values."""
+ def __repr__(self):
+ return self.__class__.__name__
+
+class Any(Parameter): pass
+Any = Any()
+
+class Anonymous(Parameter): pass
+Anonymous = Anonymous()
+
+
+connections = {}
+senders = {}
+_boundMethods = weakref.WeakKeyDictionary()
+
+
+def connect(receiver, signal=Any, sender=Any, weak=True):
+ """
+ Connect receiver to sender for signal.
+
+ * If sender is Any, receiver will receive signal from any sender.
+ * If signal is Any, receiver will receive any signal from sender.
+ * If sender is None, receiver will receive signal from Anonymous.
+ * If signal is Any and sender is None, receiver will receive any
+ signal from Anonymous.
+ * If signal is Any and sender is Any, receiver will receive any
+ signal from any sender.
+ * If weak is true, weak references will be used.
+ """
+ if signal is None:
+ raise DispatcherError, 'signal cannot be None'
+ if weak:
+ receiver = safeRef(receiver)
+ senderkey = id(sender)
+ signals = {}
+ if connections.has_key(senderkey):
+ signals = connections[senderkey]
+ else:
+ connections[senderkey] = signals
+ # Keep track of senders for cleanup.
+ if sender not in (None, Any):
+ def remove(object, senderkey=senderkey):
+ _removeSender(senderkey=senderkey)
+ # Skip objects that can not be weakly referenced, which means
+ # they won't be automatically cleaned up, but that's too bad.
+ try:
+ weakSender = weakref.ref(sender, remove)
+ senders[senderkey] = weakSender
+ except:
+ pass
+ receivers = []
+ if signals.has_key(signal):
+ receivers = signals[signal]
+ else:
+ signals[signal] = receivers
+ try:
+ receivers.remove(receiver)
+ except ValueError:
+ pass
+ receivers.append(receiver)
+
+def disconnect(receiver, signal=Any, sender=Any, weak=True):
+ """Disconnect receiver from sender for signal.
+
+ Disconnecting is not required. The use of disconnect is the same as for
+ connect, only in reverse. Think of it as undoing a previous connection."""
+ if signal is None:
+ raise DispatcherError, 'signal cannot be None'
+ if weak:
+ receiver = safeRef(receiver)
+ senderkey = id(sender)
+ try:
+ receivers = connections[senderkey][signal]
+ except KeyError:
+ raise DispatcherError, \
+ 'No receivers for signal %r from sender %s' % (signal, sender)
+ try:
+ receivers.remove(receiver)
+ except ValueError:
+ raise DispatcherError, \
+ 'No connection to receiver %s for signal %r from sender %s' % \
+ (receiver, signal, sender)
+ _cleanupConnections(senderkey, signal)
+
+def send(signal, sender=Anonymous, **kwds):
+ """Send signal from sender to all connected receivers.
+
+ Return a list of tuple pairs [(receiver, response), ... ].
+ If sender is not specified, signal is sent anonymously."""
+ senderkey = id(sender)
+ anykey = id(Any)
+ # Get receivers that receive *this* signal from *this* sender.
+ receivers = []
+ try:
+ receivers.extend(connections[senderkey][signal])
+ except KeyError:
+ pass
+ # Add receivers that receive *any* signal from *this* sender.
+ anyreceivers = []
+ try:
+ anyreceivers = connections[senderkey][Any]
+ except KeyError:
+ pass
+ for receiver in anyreceivers:
+ if receivers.count(receiver) == 0:
+ receivers.append(receiver)
+ # Add receivers that receive *this* signal from *any* sender.
+ anyreceivers = []
+ try:
+ anyreceivers = connections[anykey][signal]
+ except KeyError:
+ pass
+ for receiver in anyreceivers:
+ if receivers.count(receiver) == 0:
+ receivers.append(receiver)
+ # Add receivers that receive *any* signal from *any* sender.
+ anyreceivers = []
+ try:
+ anyreceivers = connections[anykey][Any]
+ except KeyError:
+ pass
+ for receiver in anyreceivers:
+ if receivers.count(receiver) == 0:
+ receivers.append(receiver)
+ # Call each receiver with whatever arguments it can accept.
+ # Return a list of tuple pairs [(receiver, response), ... ].
+ responses = []
+ for receiver in receivers:
+ if type(receiver) is weakref.ReferenceType \
+ or isinstance(receiver, BoundMethodWeakref):
+ # Dereference the weak reference.
+ receiver = receiver()
+ if receiver is None:
+ # This receiver is dead, so skip it.
+ continue
+ response = _call(receiver, signal=signal, sender=sender, **kwds)
+ responses += [(receiver, response)]
+ return responses
+
+def _call(receiver, **kwds):
+ """Call receiver with only arguments it can accept."""
+## if type(receiver) is types.InstanceType:
+ if hasattr(receiver, '__call__') and \
+ (hasattr(receiver.__call__, 'im_func') or hasattr(receiver.__call__, 'im_code')):
+ # receiver is a class instance; assume it is callable.
+ # Reassign receiver to the actual method that will be called.
+ receiver = receiver.__call__
+ if hasattr(receiver, 'im_func'):
+ # receiver is a method. Drop the first argument, usually 'self'.
+ fc = receiver.im_func.func_code
+ acceptable = fc.co_varnames[1:fc.co_argcount]
+ elif hasattr(receiver, 'func_code'):
+ # receiver is a function.
+ fc = receiver.func_code
+ acceptable = fc.co_varnames[0:fc.co_argcount]
+ else:
+ raise DispatcherError, 'Unknown receiver %s of type %s' % (receiver, type(receiver))
+ if not (fc.co_flags & 8):
+ # fc does not have a **kwds type parameter, therefore
+ # remove unacceptable arguments.
+ for arg in kwds.keys():
+ if arg not in acceptable:
+ del kwds[arg]
+ return receiver(**kwds)
+
+
+def safeRef(object):
+ """Return a *safe* weak reference to a callable object."""
+ if hasattr(object, 'im_self'):
+ if object.im_self is not None:
+ # Turn a bound method into a BoundMethodWeakref instance.
+ # Keep track of these instances for lookup by disconnect().
+ selfkey = object.im_self
+ funckey = object.im_func
+ if not _boundMethods.has_key(selfkey):
+ _boundMethods[selfkey] = weakref.WeakKeyDictionary()
+ if not _boundMethods[selfkey].has_key(funckey):
+ _boundMethods[selfkey][funckey] = \
+ BoundMethodWeakref(boundMethod=object)
+ return _boundMethods[selfkey][funckey]
+ return weakref.ref(object, _removeReceiver)
+
+
+class BoundMethodWeakref:
+ """BoundMethodWeakref class."""
+
+ def __init__(self, boundMethod):
+ """Return a weak-reference-like instance for a bound method."""
+ self.isDead = 0
+ def remove(object, self=self):
+ """Set self.isDead to true when method or instance is destroyed."""
+ self.isDead = 1
+ _removeReceiver(receiver=self)
+ self.weakSelf = weakref.ref(boundMethod.im_self, remove)
+ self.weakFunc = weakref.ref(boundMethod.im_func, remove)
+
+ def __repr__(self):
+ """Return the closest representation."""
+ return '<bound method weakref for %s.%s>' % (self.weakSelf, self.weakFunc)
+
+ def __call__(self):
+ """Return a strong reference to the bound method."""
+ if self.isDead:
+ return None
+ else:
+ object = self.weakSelf()
+ method = self.weakFunc().__name__
+ try: # wxPython hack to handle wxDead objects.
+ return getattr(object, method)
+ except AttributeError:
+## _removeReceiver(receiver=self)
+ return None
+
+
+def _removeReceiver(receiver):
+ """Remove receiver from connections."""
+ for senderkey in connections.keys():
+ for signal in connections[senderkey].keys():
+ receivers = connections[senderkey][signal]
+ try:
+ receivers.remove(receiver)
+ except:
+ pass
+ _cleanupConnections(senderkey, signal)
+
+def _cleanupConnections(senderkey, signal):
+ """Delete any empty signals for senderkey. Delete senderkey if empty."""
+ receivers = connections[senderkey][signal]
+ if not receivers:
+ # No more connected receivers. Therefore, remove the signal.
+ signals = connections[senderkey]
+ del signals[signal]
+ if not signals:
+ # No more signal connections. Therefore, remove the sender.
+ _removeSender(senderkey)
+
+def _removeSender(senderkey):
+ """Remove senderkey from connections."""
+ del connections[senderkey]
+ # Senderkey will only be in senders dictionary if sender
+ # could be weakly referenced.
+ try:
+ del senders[senderkey]
+ except:
+ pass
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/document.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/document.py
new file mode 100644
index 0000000..ab00ca0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/document.py
@@ -0,0 +1,43 @@
+"""Document class."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import os
+
+
+class Document:
+ """Document class."""
+
+ def __init__(self, filename=None):
+ """Create a Document instance."""
+ self.filename = filename
+ self.filepath = None
+ self.filedir = None
+ self.filebase = None
+ self.fileext = None
+ if self.filename:
+ self.filepath = os.path.realpath(self.filename)
+ self.filedir, self.filename = os.path.split(self.filepath)
+ self.filebase, self.fileext = os.path.splitext(self.filename)
+
+ def read(self):
+ """Return contents of file."""
+ if self.filepath and os.path.exists(self.filepath):
+ f = file(self.filepath, 'rb')
+ try:
+ return f.read()
+ finally:
+ f.close()
+ else:
+ return ''
+
+ def write(self, text):
+ """Write text to file."""
+ try:
+ f = file(self.filepath, 'wb')
+ f.write(text)
+ finally:
+ if f:
+ f.close()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/editor.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/editor.py
new file mode 100644
index 0000000..8c66de8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/editor.py
@@ -0,0 +1,838 @@
+"""PyAlaCarte and PyAlaMode editors."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+
+from buffer import Buffer
+import crust
+import dispatcher
+import editwindow
+import frame
+from shell import Shell
+import version
+
+
+class EditorFrame(frame.Frame):
+ """Frame containing one editor."""
+
+ def __init__(self, parent=None, id=-1, title='PyAlaCarte',
+ pos=wx.DefaultPosition, size=(800, 600),
+ style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE,
+ filename=None):
+ """Create EditorFrame instance."""
+ frame.Frame.__init__(self, parent, id, title, pos, size, style)
+ self.buffers = {}
+ self.buffer = None # Current buffer.
+ self.editor = None
+ self._defaultText = title + ' - the tastiest Python editor.'
+ self._statusText = self._defaultText
+ self.SetStatusText(self._statusText)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+ self._setup()
+ if filename:
+ self.bufferCreate(filename)
+
+ def _setup(self):
+ """Setup prior to first buffer creation.
+
+ Useful for subclasses."""
+ pass
+
+ def setEditor(self, editor):
+ self.editor = editor
+ self.buffer = self.editor.buffer
+ self.buffers[self.buffer.id] = self.buffer
+
+ def OnAbout(self, event):
+ """Display an About window."""
+ title = 'About PyAlaCarte'
+ text = 'Another fine, flaky program.'
+ dialog = wx.MessageDialog(self, text, title,
+ wx.OK | wx.ICON_INFORMATION)
+ dialog.ShowModal()
+ dialog.Destroy()
+
+ def OnClose(self, event):
+ """Event handler for closing."""
+ for buffer in self.buffers.values():
+ self.buffer = buffer
+ if buffer.hasChanged():
+ cancel = self.bufferSuggestSave()
+ if cancel and event.CanVeto():
+ event.Veto()
+ return
+ self.Destroy()
+
+ def OnIdle(self, event):
+ """Event handler for idle time."""
+ self._updateStatus()
+ if hasattr(self, 'notebook'):
+ self._updateTabText()
+ self._updateTitle()
+ event.Skip()
+
+ def _updateStatus(self):
+ """Show current status information."""
+ if self.editor and hasattr(self.editor, 'getStatus'):
+ status = self.editor.getStatus()
+ text = 'File: %s | Line: %d | Column: %d' % status
+ else:
+ text = self._defaultText
+ if text != self._statusText:
+ self.SetStatusText(text)
+ self._statusText = text
+
+ def _updateTabText(self):
+ """Show current buffer information on notebook tab."""
+## suffix = ' **'
+## notebook = self.notebook
+## selection = notebook.GetSelection()
+## if selection == -1:
+## return
+## text = notebook.GetPageText(selection)
+## window = notebook.GetPage(selection)
+## if window.editor and window.editor.buffer.hasChanged():
+## if text.endswith(suffix):
+## pass
+## else:
+## notebook.SetPageText(selection, text + suffix)
+## else:
+## if text.endswith(suffix):
+## notebook.SetPageText(selection, text[:len(suffix)])
+
+ def _updateTitle(self):
+ """Show current title information."""
+ title = self.GetTitle()
+ if self.bufferHasChanged():
+ if title.startswith('* '):
+ pass
+ else:
+ self.SetTitle('* ' + title)
+ else:
+ if title.startswith('* '):
+ self.SetTitle(title[2:])
+
+ def hasBuffer(self):
+ """Return True if there is a current buffer."""
+ if self.buffer:
+ return True
+ else:
+ return False
+
+ def bufferClose(self):
+ """Close buffer."""
+ if self.bufferHasChanged():
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+ self.bufferDestroy()
+ cancel = False
+ return cancel
+
+ def bufferCreate(self, filename=None):
+ """Create new buffer."""
+ self.bufferDestroy()
+ buffer = Buffer()
+ self.panel = panel = wx.Panel(parent=self, id=-1)
+ panel.Bind (wx.EVT_ERASE_BACKGROUND, lambda x: x)
+ editor = Editor(parent=panel)
+ panel.editor = editor
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(editor.window, 1, wx.EXPAND)
+ panel.SetSizer(sizer)
+ panel.SetAutoLayout(True)
+ sizer.Layout()
+ buffer.addEditor(editor)
+ buffer.open(filename)
+ self.setEditor(editor)
+ self.editor.setFocus()
+ self.SendSizeEvent()
+
+
+ def bufferDestroy(self):
+ """Destroy the current buffer."""
+ if self.buffer:
+ for editor in self.buffer.editors.values():
+ editor.destroy()
+ self.editor = None
+ del self.buffers[self.buffer.id]
+ self.buffer = None
+ self.panel.Destroy()
+
+
+ def bufferHasChanged(self):
+ """Return True if buffer has changed since last save."""
+ if self.buffer:
+ return self.buffer.hasChanged()
+ else:
+ return False
+
+ def bufferNew(self):
+ """Create new buffer."""
+ if self.bufferHasChanged():
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+ self.bufferCreate()
+ cancel = False
+ return cancel
+
+ def bufferOpen(self):
+ """Open file in buffer."""
+ if self.bufferHasChanged():
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+ filedir = ''
+ if self.buffer and self.buffer.doc.filedir:
+ filedir = self.buffer.doc.filedir
+ result = openSingle(directory=filedir)
+ if result.path:
+ self.bufferCreate(result.path)
+ cancel = False
+ return cancel
+
+## def bufferPrint(self):
+## """Print buffer."""
+## pass
+
+## def bufferRevert(self):
+## """Revert buffer to version of file on disk."""
+## pass
+
+ def bufferSave(self):
+ """Save buffer to its file."""
+ if self.buffer.doc.filepath:
+ self.buffer.save()
+ cancel = False
+ else:
+ cancel = self.bufferSaveAs()
+ return cancel
+
+ def bufferSaveAs(self):
+ """Save buffer to a new filename."""
+ if self.bufferHasChanged() and self.buffer.doc.filepath:
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+ filedir = ''
+ if self.buffer and self.buffer.doc.filedir:
+ filedir = self.buffer.doc.filedir
+ result = saveSingle(directory=filedir)
+ if result.path:
+ self.buffer.saveAs(result.path)
+ cancel = False
+ else:
+ cancel = True
+ return cancel
+
+ def bufferSuggestSave(self):
+ """Suggest saving changes. Return True if user selected Cancel."""
+ result = messageDialog(parent=None,
+ message='%s has changed.\n'
+ 'Would you like to save it first'
+ '?' % self.buffer.name,
+ title='Save current file?')
+ if result.positive:
+ cancel = self.bufferSave()
+ else:
+ cancel = result.text == 'Cancel'
+ return cancel
+
+ def updateNamespace(self):
+ """Update the buffer namespace for autocompletion and calltips."""
+ if self.buffer.updateNamespace():
+ self.SetStatusText('Namespace updated')
+ else:
+ self.SetStatusText('Error executing, unable to update namespace')
+
+
+class EditorNotebookFrame(EditorFrame):
+ """Frame containing one or more editors in a notebook."""
+
+ def __init__(self, parent=None, id=-1, title='PyAlaMode',
+ pos=wx.DefaultPosition, size=(800, 600),
+ style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE,
+ filename=None):
+ """Create EditorNotebookFrame instance."""
+ self.notebook = None
+ EditorFrame.__init__(self, parent, id, title, pos,
+ size, style, filename)
+ if self.notebook:
+ dispatcher.connect(receiver=self._editorChange,
+ signal='EditorChange', sender=self.notebook)
+
+ def _setup(self):
+ """Setup prior to first buffer creation.
+
+ Called automatically by base class during init."""
+ self.notebook = EditorNotebook(parent=self)
+ intro = 'Py %s' % version.VERSION
+ import imp
+ module = imp.new_module('__main__')
+ import __builtin__
+ module.__dict__['__builtins__'] = __builtin__
+ namespace = module.__dict__.copy()
+ self.crust = crust.Crust(parent=self.notebook, intro=intro, locals=namespace)
+ self.shell = self.crust.shell
+ # Override the filling so that status messages go to the status bar.
+ self.crust.filling.tree.setStatusText = self.SetStatusText
+ # Override the shell so that status messages go to the status bar.
+ self.shell.setStatusText = self.SetStatusText
+ # Fix a problem with the sash shrinking to nothing.
+ self.crust.filling.SetSashPosition(200)
+ self.notebook.AddPage(page=self.crust, text='*Shell*', select=True)
+ self.setEditor(self.crust.editor)
+ self.crust.editor.SetFocus()
+
+ def _editorChange(self, editor):
+ """Editor change signal receiver."""
+ self.setEditor(editor)
+
+ def OnAbout(self, event):
+ """Display an About window."""
+ title = 'About PyAlaMode'
+ text = 'Another fine, flaky program.'
+ dialog = wx.MessageDialog(self, text, title,
+ wx.OK | wx.ICON_INFORMATION)
+ dialog.ShowModal()
+ dialog.Destroy()
+
+ def _updateTitle(self):
+ """Show current title information."""
+ pass
+## title = self.GetTitle()
+## if self.bufferHasChanged():
+## if title.startswith('* '):
+## pass
+## else:
+## self.SetTitle('* ' + title)
+## else:
+## if title.startswith('* '):
+## self.SetTitle(title[2:])
+
+ def bufferCreate(self, filename=None):
+ """Create new buffer."""
+ buffer = Buffer()
+ panel = wx.Panel(parent=self.notebook, id=-1)
+ panel.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: x)
+ editor = Editor(parent=panel)
+ panel.editor = editor
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(editor.window, 1, wx.EXPAND)
+ panel.SetSizer(sizer)
+ panel.SetAutoLayout(True)
+ sizer.Layout()
+ buffer.addEditor(editor)
+ buffer.open(filename)
+ self.setEditor(editor)
+ self.notebook.AddPage(page=panel, text=self.buffer.name, select=True)
+ self.editor.setFocus()
+
+ def bufferDestroy(self):
+ """Destroy the current buffer."""
+ selection = self.notebook.GetSelection()
+## print "Destroy Selection:", selection
+ if selection > 0: # Don't destroy the PyCrust tab.
+ if self.buffer:
+ del self.buffers[self.buffer.id]
+ self.buffer = None # Do this before DeletePage().
+ self.notebook.DeletePage(selection)
+
+ def bufferNew(self):
+ """Create new buffer."""
+ self.bufferCreate()
+ cancel = False
+ return cancel
+
+ def bufferOpen(self):
+ """Open file in buffer."""
+ filedir = ''
+ if self.buffer and self.buffer.doc.filedir:
+ filedir = self.buffer.doc.filedir
+ result = openMultiple(directory=filedir)
+ for path in result.paths:
+ self.bufferCreate(path)
+ cancel = False
+ return cancel
+
+
+class EditorNotebook(wx.Notebook):
+ """A notebook containing a page for each editor."""
+
+ def __init__(self, parent):
+ """Create EditorNotebook instance."""
+ wx.Notebook.__init__(self, parent, id=-1, style=wx.CLIP_CHILDREN)
+ self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPageChanging, id=self.GetId())
+ self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged, id=self.GetId())
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+ def OnIdle(self, event):
+ """Event handler for idle time."""
+ self._updateTabText()
+ event.Skip()
+
+ def _updateTabText(self):
+ """Show current buffer display name on all but first tab."""
+ size = 3
+ changed = ' **'
+ unchanged = ' --'
+ selection = self.GetSelection()
+ if selection < 1:
+ return
+ text = self.GetPageText(selection)
+ window = self.GetPage(selection)
+ if not window.editor:
+ return
+ if text.endswith(changed) or text.endswith(unchanged):
+ name = text[:-size]
+ else:
+ name = text
+ if name != window.editor.buffer.name:
+ text = window.editor.buffer.name
+ if window.editor.buffer.hasChanged():
+ if text.endswith(changed):
+ text = None
+ elif text.endswith(unchanged):
+ text = text[:-size] + changed
+ else:
+ text += changed
+ else:
+ if text.endswith(changed):
+ text = text[:-size] + unchanged
+ elif text.endswith(unchanged):
+ text = None
+ else:
+ text += unchanged
+ if text is not None:
+ self.SetPageText(selection, text)
+ self.Refresh() # Needed on Win98.
+
+ def OnPageChanging(self, event):
+ """Page changing event handler."""
+ event.Skip()
+
+ def OnPageChanged(self, event):
+ """Page changed event handler."""
+ new = event.GetSelection()
+ window = self.GetPage(new)
+ dispatcher.send(signal='EditorChange', sender=self,
+ editor=window.editor)
+ window.SetFocus()
+ event.Skip()
+
+
+class EditorShellNotebookFrame(EditorNotebookFrame):
+ """Frame containing a notebook containing EditorShellNotebooks."""
+
+ def __init__(self, parent=None, id=-1, title='PyAlaModeTest',
+ pos=wx.DefaultPosition, size=(600, 400),
+ style=wx.DEFAULT_FRAME_STYLE,
+ filename=None, singlefile=False):
+ """Create EditorShellNotebookFrame instance."""
+ self._singlefile = singlefile
+ EditorNotebookFrame.__init__(self, parent, id, title, pos,
+ size, style, filename)
+
+ def _setup(self):
+ """Setup prior to first buffer creation.
+
+ Called automatically by base class during init."""
+ if not self._singlefile:
+ self.notebook = EditorNotebook(parent=self)
+
+ def OnAbout(self, event):
+ """Display an About window."""
+ title = 'About PyAlaModePlus'
+ text = 'Another fine, flaky program.'
+ dialog = wx.MessageDialog(self, text, title,
+ wx.OK | wx.ICON_INFORMATION)
+ dialog.ShowModal()
+ dialog.Destroy()
+
+ def bufferCreate(self, filename=None):
+ """Create new buffer."""
+ if self._singlefile:
+ self.bufferDestroy()
+ notebook = EditorShellNotebook(parent=self,
+ filename=filename)
+ self.notebook = notebook
+ else:
+ notebook = EditorShellNotebook(parent=self.notebook,
+ filename=filename)
+ self.setEditor(notebook.editor)
+ if not self._singlefile:
+ self.notebook.AddPage(page=notebook, text=self.buffer.name,
+ select=True)
+ self.editor.setFocus()
+
+ def bufferDestroy(self):
+ """Destroy the current buffer."""
+ if self.buffer:
+ self.editor = None
+ del self.buffers[self.buffer.id]
+ self.buffer = None # Do this before DeletePage().
+ if self._singlefile:
+ self.notebook.Destroy()
+ self.notebook = None
+ else:
+ selection = self.notebook.GetSelection()
+## print "Destroy Selection:", selection
+ self.notebook.DeletePage(selection)
+
+ def bufferNew(self):
+ """Create new buffer."""
+ if self._singlefile and self.bufferHasChanged():
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+ self.bufferCreate()
+ cancel = False
+ return cancel
+
+ def bufferOpen(self):
+ """Open file in buffer."""
+ if self._singlefile and self.bufferHasChanged():
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+ filedir = ''
+ if self.buffer and self.buffer.doc.filedir:
+ filedir = self.buffer.doc.filedir
+ if self._singlefile:
+ result = openSingle(directory=filedir)
+ if result.path:
+ self.bufferCreate(result.path)
+ else:
+ result = openMultiple(directory=filedir)
+ for path in result.paths:
+ self.bufferCreate(path)
+ cancel = False
+ return cancel
+
+
+class EditorShellNotebook(wx.Notebook):
+ """A notebook containing an editor page and a shell page."""
+
+ def __init__(self, parent, filename=None):
+ """Create EditorShellNotebook instance."""
+ wx.Notebook.__init__(self, parent, id=-1)
+ usePanels = True
+ if usePanels:
+ editorparent = editorpanel = wx.Panel(self, -1)
+ shellparent = shellpanel = wx.Panel(self, -1)
+ else:
+ editorparent = self
+ shellparent = self
+ self.buffer = Buffer()
+ self.editor = Editor(parent=editorparent)
+ self.buffer.addEditor(self.editor)
+ self.buffer.open(filename)
+ self.shell = Shell(parent=shellparent, locals=self.buffer.interp.locals,
+ style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER)
+ self.buffer.interp.locals.clear()
+ if usePanels:
+ self.AddPage(page=editorpanel, text='Editor', select=True)
+ self.AddPage(page=shellpanel, text='Shell')
+ # Setup sizers
+ editorsizer = wx.BoxSizer(wx.VERTICAL)
+ editorsizer.Add(self.editor.window, 1, wx.EXPAND)
+ editorpanel.SetSizer(editorsizer)
+ editorpanel.SetAutoLayout(True)
+ shellsizer = wx.BoxSizer(wx.VERTICAL)
+ shellsizer.Add(self.shell, 1, wx.EXPAND)
+ shellpanel.SetSizer(shellsizer)
+ shellpanel.SetAutoLayout(True)
+ else:
+ self.AddPage(page=self.editor.window, text='Editor', select=True)
+ self.AddPage(page=self.shell, text='Shell')
+ self.editor.setFocus()
+ self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged, id=self.GetId())
+
+ def OnPageChanged(self, event):
+ """Page changed event handler."""
+ selection = event.GetSelection()
+ if selection == 0:
+ self.editor.setFocus()
+ else:
+ self.shell.SetFocus()
+ event.Skip()
+
+ def SetFocus(self):
+ wx.Notebook.SetFocus(self)
+ selection = self.GetSelection()
+ if selection == 0:
+ self.editor.setFocus()
+ else:
+ self.shell.SetFocus()
+
+
+class Editor:
+ """Editor having an EditWindow."""
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize,
+ style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER):
+ """Create Editor instance."""
+ self.window = EditWindow(self, parent, id, pos, size, style)
+ self.id = self.window.GetId()
+ self.buffer = None
+ # Assign handlers for keyboard events.
+ self.window.Bind(wx.EVT_CHAR, self.OnChar)
+ self.window.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+
+ def _setBuffer(self, buffer, text):
+ """Set the editor to a buffer. Private callback called by buffer."""
+ self.buffer = buffer
+ self.autoCompleteKeys = buffer.interp.getAutoCompleteKeys()
+ self.clearAll()
+ self.setText(text)
+ self.emptyUndoBuffer()
+ self.setSavePoint()
+
+ def destroy(self):
+ """Destroy all editor objects."""
+ self.window.Destroy()
+
+ def clearAll(self):
+ self.window.ClearAll()
+
+ def emptyUndoBuffer(self):
+ self.window.EmptyUndoBuffer()
+
+ def getStatus(self):
+ """Return (filepath, line, column) status tuple."""
+ if self.window:
+ pos = self.window.GetCurrentPos()
+ line = self.window.LineFromPosition(pos) + 1
+ col = self.window.GetColumn(pos)
+ if self.buffer:
+ name = self.buffer.doc.filepath or self.buffer.name
+ else:
+ name = ''
+ status = (name, line, col)
+ return status
+ else:
+ return ('', 0, 0)
+
+ def getText(self):
+ """Return contents of editor."""
+ return self.window.GetText()
+
+ def hasChanged(self):
+ """Return True if contents have changed."""
+ return self.window.GetModify()
+
+ def setFocus(self):
+ """Set the input focus to the editor window."""
+ self.window.SetFocus()
+
+ def setSavePoint(self):
+ self.window.SetSavePoint()
+
+ def setText(self, text):
+ """Set contents of editor."""
+ self.window.SetText(text)
+
+ def OnChar(self, event):
+ """Keypress event handler.
+
+ Only receives an event if OnKeyDown calls event.Skip() for the
+ corresponding event."""
+
+ key = event.GetKeyCode()
+ if key in self.autoCompleteKeys:
+ # Usually the dot (period) key activates auto completion.
+ if self.window.AutoCompActive():
+ self.window.AutoCompCancel()
+ self.window.ReplaceSelection('')
+ self.window.AddText(chr(key))
+ text, pos = self.window.GetCurLine()
+ text = text[:pos]
+ if self.window.autoComplete:
+ self.autoCompleteShow(text)
+ elif key == ord('('):
+ # The left paren activates a call tip and cancels an
+ # active auto completion.
+ if self.window.AutoCompActive():
+ self.window.AutoCompCancel()
+ self.window.ReplaceSelection('')
+ self.window.AddText('(')
+ text, pos = self.window.GetCurLine()
+ text = text[:pos]
+ self.autoCallTipShow(text)
+ else:
+ # Allow the normal event handling to take place.
+ event.Skip()
+
+ def OnKeyDown(self, event):
+ """Key down event handler."""
+
+ key = event.GetKeyCode()
+ # If the auto-complete window is up let it do its thing.
+ if self.window.AutoCompActive():
+ event.Skip()
+ return
+ controlDown = event.ControlDown()
+ altDown = event.AltDown()
+ shiftDown = event.ShiftDown()
+ # Let Ctrl-Alt-* get handled normally.
+ if controlDown and altDown:
+ event.Skip()
+ # Increase font size.
+ elif controlDown and key in (ord(']'),):
+ dispatcher.send(signal='FontIncrease')
+ # Decrease font size.
+ elif controlDown and key in (ord('['),):
+ dispatcher.send(signal='FontDecrease')
+ # Default font size.
+ elif controlDown and key in (ord('='),):
+ dispatcher.send(signal='FontDefault')
+ else:
+ event.Skip()
+
+ def autoCompleteShow(self, command):
+ """Display auto-completion popup list."""
+ list = self.buffer.interp.getAutoCompleteList(command,
+ includeMagic=self.window.autoCompleteIncludeMagic,
+ includeSingle=self.window.autoCompleteIncludeSingle,
+ includeDouble=self.window.autoCompleteIncludeDouble)
+ if list:
+ options = ' '.join(list)
+ offset = 0
+ self.window.AutoCompShow(offset, options)
+
+ def autoCallTipShow(self, command):
+ """Display argument spec and docstring in a popup window."""
+ if self.window.CallTipActive():
+ self.window.CallTipCancel()
+ (name, argspec, tip) = self.buffer.interp.getCallTip(command)
+ if tip:
+ dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip)
+ if not self.window.autoCallTip:
+ return
+ startpos = self.window.GetCurrentPos()
+ if argspec:
+ self.window.AddText(argspec + ')')
+ endpos = self.window.GetCurrentPos()
+ self.window.SetSelection(startpos, endpos)
+ if tip:
+ tippos = startpos - (len(name) + 1)
+ fallback = startpos - self.GetColumn(startpos)
+ # In case there isn't enough room, only go back to the
+ # fallback.
+ tippos = max(tippos, fallback)
+ self.CallTipShow(tippos, tip)
+
+
+class EditWindow(editwindow.EditWindow):
+ """EditWindow based on StyledTextCtrl."""
+
+ def __init__(self, editor, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize,
+ style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER):
+ """Create EditWindow instance."""
+ editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
+ self.editor = editor
+
+
+class DialogResults:
+ """DialogResults class."""
+
+ def __init__(self, returned):
+ """Create wrapper for results returned by dialog."""
+ self.returned = returned
+ self.positive = returned in (wx.ID_OK, wx.ID_YES)
+ self.text = self._asString()
+
+
+ def __repr__(self):
+ return str(self.__dict__)
+
+ def _asString(self):
+ returned = self.returned
+ if returned == wx.ID_OK:
+ return "Ok"
+ elif returned == wx.ID_CANCEL:
+ return "Cancel"
+ elif returned == wx.ID_YES:
+ return "Yes"
+ elif returned == wx.ID_NO:
+ return "No"
+
+
+def fileDialog(parent=None, title='Open', directory='', filename='',
+ wildcard='All Files (*.*)|*.*',
+ style=wx.OPEN | wx.MULTIPLE):
+ """File dialog wrapper function."""
+ dialog = wx.FileDialog(parent, title, directory, filename,
+ wildcard, style)
+ result = DialogResults(dialog.ShowModal())
+ if result.positive:
+ result.paths = dialog.GetPaths()
+ else:
+ result.paths = []
+ dialog.Destroy()
+ return result
+
+
+def openSingle(parent=None, title='Open', directory='', filename='',
+ wildcard='All Files (*.*)|*.*', style=wx.OPEN):
+ """File dialog wrapper function."""
+ dialog = wx.FileDialog(parent, title, directory, filename,
+ wildcard, style)
+ result = DialogResults(dialog.ShowModal())
+ if result.positive:
+ result.path = dialog.GetPath()
+ else:
+ result.path = None
+ dialog.Destroy()
+ return result
+
+
+def openMultiple(parent=None, title='Open', directory='', filename='',
+ wildcard='All Files (*.*)|*.*',
+ style=wx.OPEN | wx.MULTIPLE):
+ """File dialog wrapper function."""
+ return fileDialog(parent, title, directory, filename, wildcard, style)
+
+
+def saveSingle(parent=None, title='Save', directory='', filename='',
+ wildcard='All Files (*.*)|*.*',
+ style=wx.SAVE | wx.OVERWRITE_PROMPT):
+ """File dialog wrapper function."""
+ dialog = wx.FileDialog(parent, title, directory, filename,
+ wildcard, style)
+ result = DialogResults(dialog.ShowModal())
+ if result.positive:
+ result.path = dialog.GetPath()
+ else:
+ result.path = None
+ dialog.Destroy()
+ return result
+
+
+def directory(parent=None, message='Choose a directory', path='', style=0,
+ pos=wx.DefaultPosition, size=wx.DefaultSize):
+ """Dir dialog wrapper function."""
+ dialog = wx.DirDialog(parent, message, path, style, pos, size)
+ result = DialogResults(dialog.ShowModal())
+ if result.positive:
+ result.path = dialog.GetPath()
+ else:
+ result.path = None
+ dialog.Destroy()
+ return result
+
+
+def messageDialog(parent=None, message='', title='Message box',
+ style=wx.YES_NO | wx.CANCEL | wx.CENTRE | wx.ICON_QUESTION,
+ pos=wx.DefaultPosition):
+ """Message dialog wrapper function."""
+ dialog = wx.MessageDialog(parent, message, title, style, pos)
+ result = DialogResults(dialog.ShowModal())
+ dialog.Destroy()
+ return result
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/editwindow.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/editwindow.py
new file mode 100644
index 0000000..dadd003
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/editwindow.py
@@ -0,0 +1,297 @@
+"""EditWindow class."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+from wx import stc
+
+import keyword
+import os
+import sys
+import time
+
+import dispatcher
+from version import VERSION
+
+
+if 'wxMSW' in wx.PlatformInfo:
+ FACES = { 'times' : 'Times New Roman',
+ 'mono' : 'Courier New',
+ 'helv' : 'Arial',
+ 'lucida' : 'Lucida Console',
+ 'other' : 'Comic Sans MS',
+ 'size' : 10,
+ 'lnsize' : 8,
+ 'backcol' : '#FFFFFF',
+ 'calltipbg' : '#FFFFB8',
+ 'calltipfg' : '#404040',
+ }
+
+elif 'wxGTK' in wx.PlatformInfo and ('gtk2' in wx.PlatformInfo or
+ 'gtk3' in wx.PlatformInfo):
+ FACES = { 'times' : 'Serif',
+ 'mono' : 'Monospace',
+ 'helv' : 'Sans',
+ 'other' : 'new century schoolbook',
+ 'size' : 10,
+ 'lnsize' : 9,
+ 'backcol' : '#FFFFFF',
+ 'calltipbg' : '#FFFFB8',
+ 'calltipfg' : '#404040',
+ }
+
+elif 'wxMac' in wx.PlatformInfo:
+ FACES = { 'times' : 'Lucida Grande',
+ 'mono' : 'Monaco',
+ 'helv' : 'Geneva',
+ 'other' : 'new century schoolbook',
+ 'size' : 12,
+ 'lnsize' : 10,
+ 'backcol' : '#FFFFFF',
+ 'calltipbg' : '#FFFFB8',
+ 'calltipfg' : '#404040',
+ }
+
+else: # GTK1, etc.
+ FACES = { 'times' : 'Times',
+ 'mono' : 'Courier',
+ 'helv' : 'Helvetica',
+ 'other' : 'new century schoolbook',
+ 'size' : 12,
+ 'lnsize' : 10,
+ 'backcol' : '#FFFFFF',
+ 'calltipbg' : '#FFFFB8',
+ 'calltipfg' : '#404040',
+ }
+
+
+class EditWindow(stc.StyledTextCtrl):
+ """EditWindow based on StyledTextCtrl."""
+
+ revision = __revision__
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER):
+ """Create EditWindow instance."""
+ stc.StyledTextCtrl.__init__(self, parent, id, pos, size, style)
+ self.__config()
+ stc.EVT_STC_UPDATEUI(self, id, self.OnUpdateUI)
+ dispatcher.connect(receiver=self._fontsizer, signal='FontIncrease')
+ dispatcher.connect(receiver=self._fontsizer, signal='FontDecrease')
+ dispatcher.connect(receiver=self._fontsizer, signal='FontDefault')
+
+ def _fontsizer(self, signal):
+ """Receiver for Font* signals."""
+ size = self.GetZoom()
+ if signal == 'FontIncrease':
+ size += 1
+ elif signal == 'FontDecrease':
+ size -= 1
+ elif signal == 'FontDefault':
+ size = 0
+ self.SetZoom(size)
+
+
+ def __config(self):
+ self.setDisplayLineNumbers(False)
+
+ self.SetLexer(stc.STC_LEX_PYTHON)
+ self.SetKeyWords(0, ' '.join(keyword.kwlist))
+
+ self.setStyles(FACES)
+ self.SetViewWhiteSpace(False)
+ self.SetTabWidth(4)
+ self.SetUseTabs(False)
+ # Do we want to automatically pop up command completion options?
+ self.autoComplete = True
+ self.autoCompleteIncludeMagic = True
+ self.autoCompleteIncludeSingle = True
+ self.autoCompleteIncludeDouble = True
+ self.autoCompleteCaseInsensitive = True
+ self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
+ self.autoCompleteAutoHide = False
+ self.AutoCompSetAutoHide(self.autoCompleteAutoHide)
+ self.AutoCompStops(' .,;:([)]}\'"\\<>%^&+-=*/|`')
+ # Do we want to automatically pop up command argument help?
+ self.autoCallTip = True
+ self.callTipInsert = True
+ self.CallTipSetBackground(FACES['calltipbg'])
+ self.CallTipSetForeground(FACES['calltipfg'])
+ self.SetWrapMode(False)
+ try:
+ self.SetEndAtLastLine(False)
+ except AttributeError:
+ pass
+
+ def setDisplayLineNumbers(self, state):
+ self.lineNumbers = state
+ if state:
+ self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
+ self.SetMarginWidth(1, 40)
+ else:
+ # Leave a small margin so the feature hidden lines marker can be seen
+ self.SetMarginType(1, 0)
+ self.SetMarginWidth(1, 10)
+
+ def setStyles(self, faces):
+ """Configure font size, typeface and color for lexer."""
+
+ # Default style
+ self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
+ "face:%(mono)s,size:%(size)d,back:%(backcol)s" % \
+ faces)
+
+ self.StyleClearAll()
+ self.SetSelForeground(True, wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
+ self.SetSelBackground(True, wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT))
+
+ # Built in styles
+ self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,
+ "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % FACES)
+ self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR,
+ "face:%(mono)s" % faces)
+ self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
+ "fore:#0000FF,back:#FFFF88")
+ self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
+ "fore:#FF0000,back:#FFFF88")
+
+ # Python styles
+ self.StyleSetSpec(stc.STC_P_DEFAULT,
+ "face:%(mono)s" % faces)
+ self.StyleSetSpec(stc.STC_P_COMMENTLINE,
+ "fore:#007F00,face:%(mono)s" % faces)
+ self.StyleSetSpec(stc.STC_P_NUMBER,
+ "")
+ self.StyleSetSpec(stc.STC_P_STRING,
+ "fore:#7F007F,face:%(mono)s" % faces)
+ self.StyleSetSpec(stc.STC_P_CHARACTER,
+ "fore:#7F007F,face:%(mono)s" % faces)
+ self.StyleSetSpec(stc.STC_P_WORD,
+ "fore:#00007F,bold")
+ self.StyleSetSpec(stc.STC_P_TRIPLE,
+ "fore:#7F0000")
+ self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE,
+ "fore:#000033,back:#FFFFE8")
+ self.StyleSetSpec(stc.STC_P_CLASSNAME,
+ "fore:#0000FF,bold")
+ self.StyleSetSpec(stc.STC_P_DEFNAME,
+ "fore:#007F7F,bold")
+ self.StyleSetSpec(stc.STC_P_OPERATOR,
+ "")
+ self.StyleSetSpec(stc.STC_P_IDENTIFIER,
+ "")
+ self.StyleSetSpec(stc.STC_P_COMMENTBLOCK,
+ "fore:#7F7F7F")
+ self.StyleSetSpec(stc.STC_P_STRINGEOL,
+ "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
+
+ def OnUpdateUI(self, event):
+ """Check for matching braces."""
+ # If the auto-complete window is up let it do its thing.
+ if self.AutoCompActive() or self.CallTipActive():
+ return
+ braceAtCaret = -1
+ braceOpposite = -1
+ charBefore = None
+ caretPos = self.GetCurrentPos()
+ if caretPos > 0:
+ charBefore = self.GetCharAt(caretPos - 1)
+ styleBefore = self.GetStyleAt(caretPos - 1)
+
+ # Check before.
+ if charBefore and chr(charBefore) in '[]{}()' \
+ and styleBefore == stc.STC_P_OPERATOR:
+ braceAtCaret = caretPos - 1
+
+ # Check after.
+ if braceAtCaret < 0:
+ charAfter = self.GetCharAt(caretPos)
+ styleAfter = self.GetStyleAt(caretPos)
+ if charAfter and chr(charAfter) in '[]{}()' \
+ and styleAfter == stc.STC_P_OPERATOR:
+ braceAtCaret = caretPos
+
+ if braceAtCaret >= 0:
+ braceOpposite = self.BraceMatch(braceAtCaret)
+
+ if braceAtCaret != -1 and braceOpposite == -1:
+ self.BraceBadLight(braceAtCaret)
+ else:
+ self.BraceHighlight(braceAtCaret, braceOpposite)
+
+ def CanCopy(self):
+ """Return True if text is selected and can be copied."""
+ return self.GetSelectionStart() != self.GetSelectionEnd()
+
+ def CanCut(self):
+ """Return True if text is selected and can be cut."""
+ return self.CanCopy() and self.CanEdit()
+
+ def CanEdit(self):
+ """Return True if editing should succeed."""
+ return not self.GetReadOnly()
+
+ def CanPaste(self):
+ """Return True if pasting should succeed."""
+ return stc.StyledTextCtrl.CanPaste(self) and self.CanEdit()
+
+
+ def GetLastPosition(self):
+ return self.GetLength()
+
+ def GetRange(self, start, end):
+ return self.GetTextRange(start, end)
+
+ def GetSelection(self):
+ return self.GetAnchor(), self.GetCurrentPos()
+
+ def ShowPosition(self, pos):
+ line = self.LineFromPosition(pos)
+ #self.EnsureVisible(line)
+ self.GotoLine(line)
+
+ def DoFindNext(self, findData, findDlg=None):
+ backward = not (findData.GetFlags() & wx.FR_DOWN)
+ matchcase = (findData.GetFlags() & wx.FR_MATCHCASE) != 0
+ end = self.GetLastPosition()
+ # Changed to reflect the fact that StyledTextControl is in UTF-8 encoding
+ textstring = self.GetRange(0, end).encode('utf-8')
+ findstring = findData.GetFindString().encode('utf-8')
+ if not matchcase:
+ textstring = textstring.lower()
+ findstring = findstring.lower()
+ if backward:
+ start = self.GetSelection()[0]
+ loc = textstring.rfind(findstring, 0, start)
+ else:
+ start = self.GetSelection()[1]
+ loc = textstring.find(findstring, start)
+
+ # if it wasn't found then restart at begining
+ if loc == -1 and start != 0:
+ if backward:
+ start = end
+ loc = textstring.rfind(findstring, 0, start)
+ else:
+ start = 0
+ loc = textstring.find(findstring, start)
+
+ # was it still not found?
+ if loc == -1:
+ dlg = wx.MessageDialog(self, 'Unable to find the search text.',
+ 'Not found!',
+ wx.OK | wx.ICON_INFORMATION)
+ dlg.ShowModal()
+ dlg.Destroy()
+ if findDlg:
+ if loc == -1:
+ wx.CallAfter(findDlg.SetFocus)
+ return
+ else:
+ findDlg.Close()
+
+ # show and select the found text
+ self.ShowPosition(loc)
+ self.SetSelection(loc, loc + len(findstring))
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/filling.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/filling.py
new file mode 100644
index 0000000..4ffe662
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/filling.py
@@ -0,0 +1,360 @@
+"""Filling is the gui tree control through which a user can navigate
+the local namespace or any object."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+
+import dispatcher
+import editwindow
+import inspect
+import introspect
+import keyword
+import sys
+import types
+from version import VERSION
+
+
+COMMONTYPES = [getattr(types, t) for t in dir(types) \
+ if not t.startswith('_') \
+ and t not in ('ClassType', 'InstanceType', 'ModuleType')]
+
+DOCTYPES = ('BuiltinFunctionType', 'BuiltinMethodType', 'ClassType',
+ 'FunctionType', 'GeneratorType', 'InstanceType',
+ 'LambdaType', 'MethodType', 'ModuleType',
+ 'UnboundMethodType', 'method-wrapper')
+
+SIMPLETYPES = [getattr(types, t) for t in dir(types) \
+ if not t.startswith('_') and t not in DOCTYPES]
+
+del t
+
+try:
+ COMMONTYPES.append(type(''.__repr__)) # Method-wrapper in version 2.2.x.
+except AttributeError:
+ pass
+
+
+class FillingTree(wx.TreeCtrl):
+ """FillingTree based on TreeCtrl."""
+
+ name = 'Filling Tree'
+ revision = __revision__
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.TR_DEFAULT_STYLE,
+ rootObject=None, rootLabel=None, rootIsNamespace=False,
+ static=False):
+ """Create FillingTree instance."""
+ wx.TreeCtrl.__init__(self, parent, id, pos, size, style)
+ self.rootIsNamespace = rootIsNamespace
+ import __main__
+ if rootObject is None:
+ rootObject = __main__.__dict__
+ self.rootIsNamespace = True
+ if rootObject is __main__.__dict__ and rootLabel is None:
+ rootLabel = 'locals()'
+ if not rootLabel:
+ rootLabel = 'Ingredients'
+ rootData = wx.TreeItemData(rootObject)
+ self.item = self.root = self.AddRoot(rootLabel, -1, -1, rootData)
+ self.SetItemHasChildren(self.root, self.objHasChildren(rootObject))
+ self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding, id=self.GetId())
+ self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=self.GetId())
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=self.GetId())
+ self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated, id=self.GetId())
+ if not static:
+ dispatcher.connect(receiver=self.push, signal='Interpreter.push')
+
+ def push(self, command, more):
+ """Receiver for Interpreter.push signal."""
+ self.display()
+
+ def OnItemExpanding(self, event):
+ """Add children to the item."""
+ busy = wx.BusyCursor()
+ item = event.GetItem()
+ if self.IsExpanded(item):
+ return
+ self.addChildren(item)
+# self.SelectItem(item)
+
+ def OnItemCollapsed(self, event):
+ """Remove all children from the item."""
+ busy = wx.BusyCursor()
+ item = event.GetItem()
+# self.CollapseAndReset(item)
+# self.DeleteChildren(item)
+# self.SelectItem(item)
+
+ def OnSelChanged(self, event):
+ """Display information about the item."""
+ busy = wx.BusyCursor()
+ self.item = event.GetItem()
+ self.display()
+
+ def OnItemActivated(self, event):
+ """Launch a DirFrame."""
+ item = event.GetItem()
+ text = self.getFullName(item)
+ obj = self.GetPyData(item)
+ frame = FillingFrame(parent=self, size=(600, 100), rootObject=obj,
+ rootLabel=text, rootIsNamespace=False)
+ frame.Show()
+
+ def objHasChildren(self, obj):
+ """Return true if object has children."""
+ if self.objGetChildren(obj):
+ return True
+ else:
+ return False
+
+ def objGetChildren(self, obj):
+ """Return dictionary with attributes or contents of object."""
+ busy = wx.BusyCursor()
+ otype = type(obj)
+ if otype is types.DictType \
+ or str(otype)[17:23] == 'BTrees' and hasattr(obj, 'keys'):
+ return obj
+ d = {}
+ if otype is types.ListType or otype is types.TupleType:
+ for n in range(len(obj)):
+ key = '[' + str(n) + ']'
+ d[key] = obj[n]
+ if otype not in COMMONTYPES:
+ for key in introspect.getAttributeNames(obj):
+ # Believe it or not, some attributes can disappear,
+ # such as the exc_traceback attribute of the sys
+ # module. So this is nested in a try block.
+ try:
+ d[key] = getattr(obj, key)
+ except:
+ pass
+ return d
+
+ def addChildren(self, item):
+ self.DeleteChildren(item)
+ obj = self.GetPyData(item)
+ children = self.objGetChildren(obj)
+ if not children:
+ return
+ keys = children.keys()
+ keys.sort(lambda x, y: cmp(str(x).lower(), str(y).lower()))
+ for key in keys:
+ itemtext = str(key)
+ # Show string dictionary items with single quotes, except
+ # for the first level of items, if they represent a
+ # namespace.
+ if type(obj) is types.DictType \
+ and type(key) is types.StringType \
+ and (item != self.root \
+ or (item == self.root and not self.rootIsNamespace)):
+ itemtext = repr(key)
+ child = children[key]
+ data = wx.TreeItemData(child)
+ branch = self.AppendItem(parent=item, text=itemtext, data=data)
+ self.SetItemHasChildren(branch, self.objHasChildren(child))
+
+ def display(self):
+ item = self.item
+ if not item:
+ return
+ if self.IsExpanded(item):
+ self.addChildren(item)
+ self.setText('')
+ obj = self.GetPyData(item)
+ if wx.Platform == '__WXMSW__':
+ if obj is None: # Windows bug fix.
+ return
+ self.SetItemHasChildren(item, self.objHasChildren(obj))
+ otype = type(obj)
+ text = ''
+ text += self.getFullName(item)
+ text += '\n\nType: ' + str(otype)
+ try:
+ value = str(obj)
+ except:
+ value = ''
+ if otype is types.StringType or otype is types.UnicodeType:
+ value = repr(obj)
+ text += u'\n\nValue: ' + value
+ if otype not in SIMPLETYPES:
+ try:
+ text += '\n\nDocstring:\n\n"""' + \
+ inspect.getdoc(obj).strip() + '"""'
+ except:
+ pass
+ if otype is types.InstanceType:
+ try:
+ text += '\n\nClass Definition:\n\n' + \
+ inspect.getsource(obj.__class__)
+ except:
+ pass
+ else:
+ try:
+ text += '\n\nSource Code:\n\n' + \
+ inspect.getsource(obj)
+ except:
+ pass
+ self.setText(text)
+
+ def getFullName(self, item, partial=''):
+ """Return a syntactically proper name for item."""
+ name = self.GetItemText(item)
+ parent = None
+ obj = None
+ if item != self.root:
+ parent = self.GetItemParent(item)
+ obj = self.GetPyData(parent)
+ # Apply dictionary syntax to dictionary items, except the root
+ # and first level children of a namepace.
+ if (type(obj) is types.DictType \
+ or str(type(obj))[17:23] == 'BTrees' \
+ and hasattr(obj, 'keys')) \
+ and ((item != self.root and parent != self.root) \
+ or (parent == self.root and not self.rootIsNamespace)):
+ name = '[' + name + ']'
+ # Apply dot syntax to multipart names.
+ if partial:
+ if partial[0] == '[':
+ name += partial
+ else:
+ name += '.' + partial
+ # Repeat for everything but the root item
+ # and first level children of a namespace.
+ if (item != self.root and parent != self.root) \
+ or (parent == self.root and not self.rootIsNamespace):
+ name = self.getFullName(parent, partial=name)
+ return name
+
+ def setText(self, text):
+ """Display information about the current selection."""
+
+ # This method will likely be replaced by the enclosing app to
+ # do something more interesting, like write to a text control.
+ print text
+
+ def setStatusText(self, text):
+ """Display status information."""
+
+ # This method will likely be replaced by the enclosing app to
+ # do something more interesting, like write to a status bar.
+ print text
+
+
+class FillingText(editwindow.EditWindow):
+ """FillingText based on StyledTextCtrl."""
+
+ name = 'Filling Text'
+ revision = __revision__
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
+ static=False):
+ """Create FillingText instance."""
+ editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
+ # Configure various defaults and user preferences.
+ self.SetReadOnly(True)
+ self.SetWrapMode(True)
+ self.SetMarginWidth(1, 0)
+ if not static:
+ dispatcher.connect(receiver=self.push, signal='Interpreter.push')
+
+ def push(self, command, more):
+ """Receiver for Interpreter.push signal."""
+ self.Refresh()
+
+ def SetText(self, *args, **kwds):
+ self.SetReadOnly(False)
+ editwindow.EditWindow.SetText(self, *args, **kwds)
+ self.SetReadOnly(True)
+
+
+class Filling(wx.SplitterWindow):
+ """Filling based on wxSplitterWindow."""
+
+ name = 'Filling'
+ revision = __revision__
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.SP_3D|wx.SP_LIVE_UPDATE,
+ name='Filling Window', rootObject=None,
+ rootLabel=None, rootIsNamespace=False, static=False):
+ """Create a Filling instance."""
+ wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name)
+
+ self.tree = FillingTree(parent=self, rootObject=rootObject,
+ rootLabel=rootLabel,
+ rootIsNamespace=rootIsNamespace,
+ static=static)
+ self.text = FillingText(parent=self, static=static)
+
+ wx.FutureCall(1, self.SplitVertically, self.tree, self.text, 200)
+
+ self.SetMinimumPaneSize(1)
+
+ # Override the filling so that descriptions go to FillingText.
+ self.tree.setText = self.text.SetText
+
+ # Display the root item.
+ self.tree.SelectItem(self.tree.root)
+ self.tree.display()
+
+ self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnChanged)
+
+ def OnChanged(self, event):
+ #this is important: do not evaluate this event=> otherwise,
+ # splitterwindow behaves strangely
+ #event.Skip()
+ pass
+
+
+ def LoadSettings(self, config):
+ pos = config.ReadInt('Sash/FillingPos', 200)
+ wx.FutureCall(250, self.SetSashPosition, pos)
+ zoom = config.ReadInt('View/Zoom/Filling', -99)
+ if zoom != -99:
+ self.text.SetZoom(zoom)
+
+ def SaveSettings(self, config):
+ config.WriteInt('Sash/FillingPos', self.GetSashPosition())
+ config.WriteInt('View/Zoom/Filling', self.text.GetZoom())
+
+
+
+class FillingFrame(wx.Frame):
+ """Frame containing the namespace tree component."""
+
+ name = 'Filling Frame'
+ revision = __revision__
+
+ def __init__(self, parent=None, id=-1, title='PyFilling',
+ pos=wx.DefaultPosition, size=(600, 400),
+ style=wx.DEFAULT_FRAME_STYLE, rootObject=None,
+ rootLabel=None, rootIsNamespace=False, static=False):
+ """Create FillingFrame instance."""
+ wx.Frame.__init__(self, parent, id, title, pos, size, style)
+ intro = 'PyFilling - The Tastiest Namespace Inspector'
+ self.CreateStatusBar()
+ self.SetStatusText(intro)
+ import images
+ self.SetIcon(images.getPyIcon())
+ self.filling = Filling(parent=self, rootObject=rootObject,
+ rootLabel=rootLabel,
+ rootIsNamespace=rootIsNamespace,
+ static=static)
+ # Override so that status messages go to the status bar.
+ self.filling.tree.setStatusText = self.SetStatusText
+
+
+class App(wx.App):
+ """PyFilling standalone application."""
+
+ def OnInit(self):
+ wx.InitAllImageHandlers()
+ self.fillingFrame = FillingFrame()
+ self.fillingFrame.Show(True)
+ self.SetTopWindow(self.fillingFrame)
+ return True
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/frame.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/frame.py
new file mode 100644
index 0000000..2bece97
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/frame.py
@@ -0,0 +1,984 @@
+"""Base frame with menu."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+import os
+from version import VERSION
+import editwindow
+import dispatcher
+
+ID_NEW = wx.ID_NEW
+ID_OPEN = wx.ID_OPEN
+ID_REVERT = wx.ID_REVERT
+ID_CLOSE = wx.ID_CLOSE
+ID_SAVE = wx.ID_SAVE
+ID_SAVEAS = wx.ID_SAVEAS
+ID_PRINT = wx.ID_PRINT
+ID_EXIT = wx.ID_EXIT
+ID_UNDO = wx.ID_UNDO
+ID_REDO = wx.ID_REDO
+ID_CUT = wx.ID_CUT
+ID_COPY = wx.ID_COPY
+ID_PASTE = wx.ID_PASTE
+ID_CLEAR = wx.ID_CLEAR
+ID_SELECTALL = wx.ID_SELECTALL
+ID_EMPTYBUFFER = wx.NewId()
+ID_ABOUT = wx.ID_ABOUT
+ID_HELP = wx.NewId()
+ID_AUTOCOMP = wx.NewId()
+ID_AUTOCOMP_SHOW = wx.NewId()
+ID_AUTOCOMP_MAGIC = wx.NewId()
+ID_AUTOCOMP_SINGLE = wx.NewId()
+ID_AUTOCOMP_DOUBLE = wx.NewId()
+ID_CALLTIPS = wx.NewId()
+ID_CALLTIPS_SHOW = wx.NewId()
+ID_CALLTIPS_INSERT = wx.NewId()
+ID_COPY_PLUS = wx.NewId()
+ID_NAMESPACE = wx.NewId()
+ID_PASTE_PLUS = wx.NewId()
+ID_WRAP = wx.NewId()
+ID_TOGGLE_MAXIMIZE = wx.NewId()
+ID_SHOW_LINENUMBERS = wx.NewId()
+ID_ENABLESHELLMODE = wx.NewId()
+ID_ENABLEAUTOSYMPY = wx.NewId()
+ID_AUTO_SAVESETTINGS = wx.NewId()
+ID_SAVEACOPY = wx.NewId()
+ID_SAVEHISTORY = wx.NewId()
+ID_SAVEHISTORYNOW = wx.NewId()
+ID_CLEARHISTORY = wx.NewId()
+ID_SAVESETTINGS = wx.NewId()
+ID_DELSETTINGSFILE = wx.NewId()
+ID_EDITSTARTUPSCRIPT = wx.NewId()
+ID_EXECSTARTUPSCRIPT = wx.NewId()
+ID_SHOWPYSLICESTUTORIAL = wx.NewId()
+ID_STARTUP = wx.NewId()
+ID_SETTINGS = wx.NewId()
+ID_FIND = wx.ID_FIND
+ID_FINDNEXT = wx.NewId()
+ID_FINDPREVIOUS = wx.NewId()
+ID_SHOWTOOLS = wx.NewId()
+ID_HIDEFOLDINGMARGIN = wx.NewId()
+
+
+
+class Frame(wx.Frame):
+ """Frame with standard menu items."""
+
+ revision = __revision__
+
+ def __init__(self, parent=None, id=-1, title='Editor',
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_FRAME_STYLE,shellName='PyCrust'):
+ """Create a Frame instance."""
+ wx.Frame.__init__(self, parent, id, title, pos, size, style)
+ self.CreateStatusBar()
+ self.SetStatusText('Frame')
+ self.shellName=shellName
+ import images
+ self.SetIcon(images.getPyIcon(shellName=shellName))
+ self.__createMenus()
+
+ self.iconized = False
+ self.findDlg = None
+ self.findData = wx.FindReplaceData()
+ self.findData.SetFlags(wx.FR_DOWN)
+
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.Bind(wx.EVT_ICONIZE, self.OnIconize)
+
+
+ def OnIconize(self, event):
+ """Event handler for Iconize."""
+ self.iconized = event.Iconized()
+
+
+ def OnClose(self, event):
+ """Event handler for closing."""
+ self.Destroy()
+
+
+ def __createMenus(self):
+ # File Menu
+ m = self.fileMenu = wx.Menu()
+ m.Append(ID_NEW, '&New \tCtrl+N',
+ 'New file')
+ m.Append(ID_OPEN, '&Open... \tCtrl+O',
+ 'Open file')
+ m.AppendSeparator()
+ m.Append(ID_REVERT, '&Revert \tCtrl+R',
+ 'Revert to last saved version')
+ m.Append(ID_CLOSE, '&Close \tCtrl+W',
+ 'Close file')
+ m.AppendSeparator()
+ m.Append(ID_SAVE, '&Save... \tCtrl+S',
+ 'Save file')
+ m.Append(ID_SAVEAS, 'Save &As \tCtrl+Shift+S',
+ 'Save file with new name')
+ if self.shellName in ['PySlices','SymPySlices']:
+ m.Append(ID_SAVEACOPY, 'Save A Cop&y',
+ 'Save a copy of the file without changing the current file')
+ m.AppendSeparator()
+ m.Append(ID_PRINT, '&Print... \tCtrl+P',
+ 'Print file')
+ m.AppendSeparator()
+ m.Append(ID_NAMESPACE, '&Update Namespace \tCtrl+Shift+N',
+ 'Update namespace for autocompletion and calltips')
+ m.AppendSeparator()
+ m.Append(ID_EXIT, 'E&xit\tCtrl+Q', 'Exit Program')
+
+ # Edit
+ m = self.editMenu = wx.Menu()
+ m.Append(ID_UNDO, '&Undo \tCtrl+Z',
+ 'Undo the last action')
+ m.Append(ID_REDO, '&Redo \tCtrl+Y',
+ 'Redo the last undone action')
+ m.AppendSeparator()
+ m.Append(ID_CUT, 'Cu&t \tCtrl+X',
+ 'Cut the selection')
+ m.Append(ID_COPY, '&Copy \tCtrl+C',
+ 'Copy the selection')
+ m.Append(ID_COPY_PLUS, 'Cop&y Plus \tCtrl+Shift+C',
+ 'Copy the selection - retaining prompts')
+ m.Append(ID_PASTE, '&Paste \tCtrl+V', 'Paste from clipboard')
+ m.Append(ID_PASTE_PLUS, 'Past&e Plus \tCtrl+Shift+V',
+ 'Paste and run commands')
+ m.AppendSeparator()
+ m.Append(ID_CLEAR, 'Cle&ar',
+ 'Delete the selection')
+ m.Append(ID_SELECTALL, 'Select A&ll \tCtrl+A',
+ 'Select all text')
+ m.AppendSeparator()
+ m.Append(ID_EMPTYBUFFER, 'E&mpty Buffer...',
+ 'Delete all the contents of the edit buffer')
+ m.Append(ID_FIND, '&Find Text... \tCtrl+F',
+ 'Search for text in the edit buffer')
+ m.Append(ID_FINDNEXT, 'Find &Next \tCtrl+G',
+ 'Find next instance of the search text')
+ m.Append(ID_FINDPREVIOUS, 'Find Pre&vious \tCtrl+Shift+G',
+ 'Find previous instance of the search text')
+
+ # View
+ m = self.viewMenu = wx.Menu()
+ m.Append(ID_WRAP, '&Wrap Lines\tCtrl+Shift+W',
+ 'Wrap lines at right edge', wx.ITEM_CHECK)
+ m.Append(ID_SHOW_LINENUMBERS, '&Show Line Numbers\tCtrl+Shift+L',
+ 'Show Line Numbers', wx.ITEM_CHECK)
+ m.Append(ID_TOGGLE_MAXIMIZE, '&Toggle Maximize\tF11',
+ 'Maximize/Restore Application')
+ if hasattr(self, 'ToggleTools'):
+ m.Append(ID_SHOWTOOLS,
+ 'Show &Tools\tF4',
+ 'Show the filling and other tools', wx.ITEM_CHECK)
+ if self.shellName==['PySlices','SymPySlices']:
+ m.Append(ID_HIDEFOLDINGMARGIN,
+ '&Hide Folding Margin',
+ 'Hide Folding Margin', wx.ITEM_CHECK)
+
+ # Options
+ m = self.autocompMenu = wx.Menu()
+ m.Append(ID_AUTOCOMP_SHOW, 'Show &Auto Completion\tCtrl+Shift+A',
+ 'Show auto completion list', wx.ITEM_CHECK)
+ m.Append(ID_AUTOCOMP_MAGIC, 'Include &Magic Attributes\tCtrl+Shift+M',
+ 'Include attributes visible to __getattr__ and __setattr__',
+ wx.ITEM_CHECK)
+ m.Append(ID_AUTOCOMP_SINGLE, 'Include Single &Underscores\tCtrl+Shift+U',
+ 'Include attibutes prefixed by a single underscore', wx.ITEM_CHECK)
+ m.Append(ID_AUTOCOMP_DOUBLE, 'Include &Double Underscores\tCtrl+Shift+D',
+ 'Include attibutes prefixed by a double underscore', wx.ITEM_CHECK)
+ m = self.calltipsMenu = wx.Menu()
+ m.Append(ID_CALLTIPS_SHOW, 'Show Call &Tips\tCtrl+Shift+T',
+ 'Show call tips with argument signature and docstring', wx.ITEM_CHECK)
+ m.Append(ID_CALLTIPS_INSERT, '&Insert Call Tips\tCtrl+Shift+I',
+ '&Insert Call Tips', wx.ITEM_CHECK)
+
+ m = self.optionsMenu = wx.Menu()
+ m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu,
+ 'Auto Completion Options')
+ m.AppendMenu(ID_CALLTIPS, '&Call Tips', self.calltipsMenu,
+ 'Call Tip Options')
+
+ m.AppendSeparator()
+
+ self.historyMenu = wx.Menu()
+ self.historyMenu.Append(ID_SAVEHISTORY, '&Autosave History',
+ 'Automatically save history on close', wx.ITEM_CHECK)
+ self.historyMenu.Append(ID_SAVEHISTORYNOW, '&Save History Now',
+ 'Save history')
+ self.historyMenu.Append(ID_CLEARHISTORY, '&Clear History ',
+ 'Clear history')
+ m.AppendMenu(-1, "&History", self.historyMenu, "History Options")
+
+ self.startupMenu = wx.Menu()
+ self.startupMenu.Append(ID_EXECSTARTUPSCRIPT,
+ 'E&xecute Startup Script',
+ 'Execute Startup Script', wx.ITEM_CHECK)
+ self.startupMenu.Append(ID_EDITSTARTUPSCRIPT,
+ '&Edit Startup Script...',
+ 'Edit Startup Script')
+ if self.shellName in ['PySlices','SymPySlices']:
+ self.startupMenu.Append(ID_SHOWPYSLICESTUTORIAL,
+ '&Show PySlices Tutorial',
+ 'Show PySlices Tutorial', wx.ITEM_CHECK)
+ m.AppendMenu(ID_STARTUP, '&Startup', self.startupMenu, 'Startup Options')
+
+ self.settingsMenu = wx.Menu()
+ if self.shellName in ['PySlices','SymPySlices']:
+ self.settingsMenu.Append(ID_ENABLESHELLMODE,
+ '&Enable Shell Mode',
+ 'Enable Shell Mode', wx.ITEM_CHECK)
+ if self.shellName == 'SymPySlices':
+ self.settingsMenu.Append(ID_ENABLEAUTOSYMPY,
+ '&Enable "Auto-Sympy" Conversions for Undefined Variables',
+ 'Enable "Auto-Sympy" Conversions', wx.ITEM_CHECK)
+ self.settingsMenu.Append(ID_AUTO_SAVESETTINGS,
+ '&Auto Save Settings',
+ 'Automatically save settings on close', wx.ITEM_CHECK)
+ self.settingsMenu.Append(ID_SAVESETTINGS,
+ '&Save Settings',
+ 'Save settings now')
+ self.settingsMenu.Append(ID_DELSETTINGSFILE,
+ '&Revert to default',
+ 'Revert to the default settings')
+ m.AppendMenu(ID_SETTINGS, '&Settings', self.settingsMenu, 'Settings Options')
+
+ m = self.helpMenu = wx.Menu()
+ m.Append(ID_HELP, '&Help\tF1', 'Help!')
+ m.AppendSeparator()
+ m.Append(ID_ABOUT, '&About...', 'About this program')
+
+ b = self.menuBar = wx.MenuBar()
+ b.Append(self.fileMenu, '&File')
+ b.Append(self.editMenu, '&Edit')
+ b.Append(self.viewMenu, '&View')
+ b.Append(self.optionsMenu, '&Options')
+ b.Append(self.helpMenu, '&Help')
+ self.SetMenuBar(b)
+
+ self.Bind(wx.EVT_MENU, self.OnFileNew, id=ID_NEW)
+ self.Bind(wx.EVT_MENU, self.OnFileOpen, id=ID_OPEN)
+ self.Bind(wx.EVT_MENU, self.OnFileRevert, id=ID_REVERT)
+ self.Bind(wx.EVT_MENU, self.OnFileClose, id=ID_CLOSE)
+ self.Bind(wx.EVT_MENU, self.OnFileSave, id=ID_SAVE)
+ self.Bind(wx.EVT_MENU, self.OnFileSaveAs, id=ID_SAVEAS)
+ self.Bind(wx.EVT_MENU, self.OnFileSaveACopy, id=ID_SAVEACOPY)
+ self.Bind(wx.EVT_MENU, self.OnFileUpdateNamespace, id=ID_NAMESPACE)
+ self.Bind(wx.EVT_MENU, self.OnFilePrint, id=ID_PRINT)
+ self.Bind(wx.EVT_MENU, self.OnExit, id=ID_EXIT)
+ self.Bind(wx.EVT_MENU, self.OnUndo, id=ID_UNDO)
+ self.Bind(wx.EVT_MENU, self.OnRedo, id=ID_REDO)
+ self.Bind(wx.EVT_MENU, self.OnCut, id=ID_CUT)
+ self.Bind(wx.EVT_MENU, self.OnCopy, id=ID_COPY)
+ self.Bind(wx.EVT_MENU, self.OnCopyPlus, id=ID_COPY_PLUS)
+ self.Bind(wx.EVT_MENU, self.OnPaste, id=ID_PASTE)
+ self.Bind(wx.EVT_MENU, self.OnPastePlus, id=ID_PASTE_PLUS)
+ self.Bind(wx.EVT_MENU, self.OnClear, id=ID_CLEAR)
+ self.Bind(wx.EVT_MENU, self.OnSelectAll, id=ID_SELECTALL)
+ self.Bind(wx.EVT_MENU, self.OnEmptyBuffer, id=ID_EMPTYBUFFER)
+ self.Bind(wx.EVT_MENU, self.OnAbout, id=ID_ABOUT)
+ self.Bind(wx.EVT_MENU, self.OnHelp, id=ID_HELP)
+ self.Bind(wx.EVT_MENU, self.OnAutoCompleteShow, id=ID_AUTOCOMP_SHOW)
+ self.Bind(wx.EVT_MENU, self.OnAutoCompleteMagic, id=ID_AUTOCOMP_MAGIC)
+ self.Bind(wx.EVT_MENU, self.OnAutoCompleteSingle, id=ID_AUTOCOMP_SINGLE)
+ self.Bind(wx.EVT_MENU, self.OnAutoCompleteDouble, id=ID_AUTOCOMP_DOUBLE)
+ self.Bind(wx.EVT_MENU, self.OnCallTipsShow, id=ID_CALLTIPS_SHOW)
+ self.Bind(wx.EVT_MENU, self.OnCallTipsInsert, id=ID_CALLTIPS_INSERT)
+ self.Bind(wx.EVT_MENU, self.OnWrap, id=ID_WRAP)
+ self.Bind(wx.EVT_MENU, self.OnToggleMaximize, id=ID_TOGGLE_MAXIMIZE)
+ self.Bind(wx.EVT_MENU, self.OnShowLineNumbers, id=ID_SHOW_LINENUMBERS)
+ self.Bind(wx.EVT_MENU, self.OnEnableShellMode, id=ID_ENABLESHELLMODE)
+ self.Bind(wx.EVT_MENU, self.OnEnableAutoSympy, id=ID_ENABLEAUTOSYMPY)
+ self.Bind(wx.EVT_MENU, self.OnAutoSaveSettings, id=ID_AUTO_SAVESETTINGS)
+ self.Bind(wx.EVT_MENU, self.OnSaveHistory, id=ID_SAVEHISTORY)
+ self.Bind(wx.EVT_MENU, self.OnSaveHistoryNow, id=ID_SAVEHISTORYNOW)
+ self.Bind(wx.EVT_MENU, self.OnClearHistory, id=ID_CLEARHISTORY)
+ self.Bind(wx.EVT_MENU, self.OnSaveSettings, id=ID_SAVESETTINGS)
+ self.Bind(wx.EVT_MENU, self.OnDelSettingsFile, id=ID_DELSETTINGSFILE)
+ self.Bind(wx.EVT_MENU, self.OnEditStartupScript, id=ID_EDITSTARTUPSCRIPT)
+ self.Bind(wx.EVT_MENU, self.OnExecStartupScript, id=ID_EXECSTARTUPSCRIPT)
+ self.Bind(wx.EVT_MENU, self.OnShowPySlicesTutorial, id=ID_SHOWPYSLICESTUTORIAL)
+ self.Bind(wx.EVT_MENU, self.OnFindText, id=ID_FIND)
+ self.Bind(wx.EVT_MENU, self.OnFindNext, id=ID_FINDNEXT)
+ self.Bind(wx.EVT_MENU, self.OnFindPrevious, id=ID_FINDPREVIOUS)
+ self.Bind(wx.EVT_MENU, self.OnToggleTools, id=ID_SHOWTOOLS)
+ self.Bind(wx.EVT_MENU, self.OnHideFoldingMargin, id=ID_HIDEFOLDINGMARGIN)
+
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_NEW)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_OPEN)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_REVERT)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CLOSE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVEAS)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_NAMESPACE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_PRINT)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_UNDO)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_REDO)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CUT)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_COPY)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_COPY_PLUS)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_PASTE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_PASTE_PLUS)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CLEAR)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SELECTALL)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EMPTYBUFFER)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_SHOW)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_MAGIC)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_SINGLE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_DOUBLE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CALLTIPS_SHOW)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CALLTIPS_INSERT)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_WRAP)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SHOW_LINENUMBERS)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_ENABLESHELLMODE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_ENABLEAUTOSYMPY)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTO_SAVESETTINGS)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVESETTINGS)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_DELSETTINGSFILE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EXECSTARTUPSCRIPT)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SHOWPYSLICESTUTORIAL)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVEHISTORY)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVEHISTORYNOW)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CLEARHISTORY)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EDITSTARTUPSCRIPT)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FIND)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FINDNEXT)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FINDPREVIOUS)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SHOWTOOLS)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_HIDEFOLDINGMARGIN)
+
+ self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
+ self.Bind(wx.EVT_FIND, self.OnFindNext)
+ self.Bind(wx.EVT_FIND_NEXT, self.OnFindNext)
+ self.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose)
+
+
+
+ def OnShowLineNumbers(self, event):
+ win = wx.Window.FindFocus()
+ if hasattr(win, 'lineNumbers'):
+ win.lineNumbers = event.IsChecked()
+ win.setDisplayLineNumbers(win.lineNumbers)
+
+ def OnToggleMaximize(self, event):
+ self.Maximize(not self.IsMaximized())
+
+ def OnFileNew(self, event):
+ self.bufferNew()
+
+ def OnFileOpen(self, event):
+ self.bufferOpen()
+
+ def OnFileRevert(self, event):
+ self.bufferRevert()
+
+ def OnFileClose(self, event):
+ self.bufferClose()
+
+ def OnFileSave(self, event):
+ self.bufferSave()
+
+ def OnFileSaveAs(self, event):
+ self.bufferSaveAs()
+
+ def OnFileSaveACopy(self, event):
+ self.bufferSaveACopy()
+
+ def OnFileUpdateNamespace(self, event):
+ self.updateNamespace()
+
+ def OnFilePrint(self, event):
+ self.bufferPrint()
+
+ def OnExit(self, event):
+ self.Close(False)
+
+ def OnUndo(self, event):
+ win = wx.Window.FindFocus()
+ win.Undo()
+
+ def OnRedo(self, event):
+ win = wx.Window.FindFocus()
+ win.Redo()
+
+ def OnCut(self, event):
+ win = wx.Window.FindFocus()
+ win.Cut()
+
+ def OnCopy(self, event):
+ win = wx.Window.FindFocus()
+ win.Copy()
+
+ def OnCopyPlus(self, event):
+ win = wx.Window.FindFocus()
+ win.CopyWithPrompts()
+
+ def OnPaste(self, event):
+ win = wx.Window.FindFocus()
+ win.Paste()
+
+ def OnPastePlus(self, event):
+ win = wx.Window.FindFocus()
+ win.PasteAndRun()
+
+ def OnClear(self, event):
+ win = wx.Window.FindFocus()
+ win.Clear()
+
+ def OnEmptyBuffer(self, event):
+ win = wx.Window.FindFocus()
+ d = wx.MessageDialog(self,
+ "Are you sure you want to clear the edit buffer,\n"
+ "deleting all the text?",
+ "Empty Buffer", wx.OK | wx.CANCEL | wx.ICON_QUESTION)
+ answer = d.ShowModal()
+ d.Destroy()
+ if (answer == wx.ID_OK):
+ win.ClearAll()
+ if hasattr(win,'prompt'):
+ win.prompt()
+
+ def OnSelectAll(self, event):
+ win = wx.Window.FindFocus()
+ win.SelectAll()
+
+ def OnAbout(self, event):
+ """Display an About window."""
+ title = 'About'
+ text = 'Your message here.'
+ dialog = wx.MessageDialog(self, text, title,
+ wx.OK | wx.ICON_INFORMATION)
+ dialog.ShowModal()
+ dialog.Destroy()
+
+ def OnHelp(self, event):
+ """Display a Help window."""
+ title = 'Help'
+ text = "Type 'shell.help()' in the shell window."
+ dialog = wx.MessageDialog(self, text, title,
+ wx.OK | wx.ICON_INFORMATION)
+ dialog.ShowModal()
+ dialog.Destroy()
+
+ def OnAutoCompleteShow(self, event):
+ win = wx.Window.FindFocus()
+ win.autoComplete = event.IsChecked()
+
+ def OnAutoCompleteMagic(self, event):
+ win = wx.Window.FindFocus()
+ win.autoCompleteIncludeMagic = event.IsChecked()
+
+ def OnAutoCompleteSingle(self, event):
+ win = wx.Window.FindFocus()
+ win.autoCompleteIncludeSingle = event.IsChecked()
+
+ def OnAutoCompleteDouble(self, event):
+ win = wx.Window.FindFocus()
+ win.autoCompleteIncludeDouble = event.IsChecked()
+
+ def OnCallTipsShow(self, event):
+ win = wx.Window.FindFocus()
+ win.autoCallTip = event.IsChecked()
+
+ def OnCallTipsInsert(self, event):
+ win = wx.Window.FindFocus()
+ win.callTipInsert = event.IsChecked()
+
+ def OnWrap(self, event):
+ win = wx.Window.FindFocus()
+ win.SetWrapMode(event.IsChecked())
+ wx.FutureCall(1, self.shell.EnsureCaretVisible)
+
+ def OnSaveHistory(self, event):
+ self.autoSaveHistory = event.IsChecked()
+
+ def OnSaveHistoryNow(self, event):
+ self.SaveHistory()
+
+ def OnClearHistory(self, event):
+ self.shell.clearHistory()
+
+ def OnEnableShellMode(self, event):
+ self.enableShellMode = event.IsChecked()
+
+ def OnEnableAutoSympy(self, event):
+ self.enableAutoSympy = event.IsChecked()
+
+ def OnHideFoldingMargin(self, event):
+ self.hideFoldingMargin = event.IsChecked()
+
+ def OnAutoSaveSettings(self, event):
+ self.autoSaveSettings = event.IsChecked()
+
+ def OnSaveSettings(self, event):
+ self.DoSaveSettings()
+
+ def OnDelSettingsFile(self, event):
+ if self.config is not None:
+ d = wx.MessageDialog(
+ self, "Do you want to revert to the default settings?\n" +
+ "A restart is needed for the change to take effect",
+ "Warning", wx.OK | wx.CANCEL | wx.ICON_QUESTION)
+ answer = d.ShowModal()
+ d.Destroy()
+ if (answer == wx.ID_OK):
+ self.config.DeleteAll()
+ self.LoadSettings()
+
+
+ def OnEditStartupScript(self, event):
+ if hasattr(self, 'EditStartupScript'):
+ self.EditStartupScript()
+
+ def OnExecStartupScript(self, event):
+ self.execStartupScript = event.IsChecked()
+ self.SaveSettings(force=True)
+
+ def OnShowPySlicesTutorial(self,event):
+ self.showPySlicesTutorial = event.IsChecked()
+ self.SaveSettings(force=True)
+
+ def OnFindText(self, event):
+ if self.findDlg is not None:
+ return
+ win = wx.Window.FindFocus()
+ if self.shellName == 'PyCrust':
+ self.findDlg = wx.FindReplaceDialog(win, self.findData,
+ "Find",wx.FR_NOWHOLEWORD)
+ else:
+ self.findDlg = wx.FindReplaceDialog(win, self.findData,
+ "Find & Replace", wx.FR_NOWHOLEWORD|wx.FR_REPLACEDIALOG)
+ self.findDlg.Show()
+
+ def OnFindNext(self, event,backward=False):
+ if backward and (self.findData.GetFlags() & wx.FR_DOWN):
+ self.findData.SetFlags( self.findData.GetFlags() ^ wx.FR_DOWN )
+ elif not backward and not (self.findData.GetFlags() & wx.FR_DOWN):
+ self.findData.SetFlags( self.findData.GetFlags() ^ wx.FR_DOWN )
+
+ if not self.findData.GetFindString():
+ self.OnFindText(event)
+ return
+ if isinstance(event, wx.FindDialogEvent):
+ win = self.findDlg.GetParent()
+ else:
+ win = wx.Window.FindFocus()
+ win.DoFindNext(self.findData, self.findDlg)
+ if self.findDlg is not None:
+ self.OnFindClose(None)
+
+ def OnFindPrevious(self, event):
+ self.OnFindNext(event,backward=True)
+
+ def OnFindClose(self, event):
+ self.findDlg.Destroy()
+ self.findDlg = None
+
+ def OnToggleTools(self, event):
+ self.ToggleTools()
+
+
+ def OnUpdateMenu(self, event):
+ """Update menu items based on current status and context."""
+ win = wx.Window.FindFocus()
+ id = event.GetId()
+ event.Enable(True)
+ try:
+ if id == ID_NEW:
+ event.Enable(hasattr(self, 'bufferNew'))
+ elif id == ID_OPEN:
+ event.Enable(hasattr(self, 'bufferOpen'))
+ elif id == ID_REVERT:
+ event.Enable(hasattr(self, 'bufferRevert')
+ and self.hasBuffer())
+ elif id == ID_CLOSE:
+ event.Enable(hasattr(self, 'bufferClose')
+ and self.hasBuffer())
+ elif id == ID_SAVE:
+ event.Enable(hasattr(self, 'bufferSave')
+ and self.bufferHasChanged())
+ elif id == ID_SAVEAS:
+ event.Enable(hasattr(self, 'bufferSaveAs')
+ and self.hasBuffer())
+ elif id == ID_SAVEACOPY:
+ event.Enable(hasattr(self, 'bufferSaveACopy')
+ and self.hasBuffer())
+ elif id == ID_NAMESPACE:
+ event.Enable(hasattr(self, 'updateNamespace')
+ and self.hasBuffer())
+ elif id == ID_PRINT:
+ event.Enable(hasattr(self, 'bufferPrint')
+ and self.hasBuffer())
+ elif id == ID_UNDO:
+ event.Enable(win.CanUndo())
+ elif id == ID_REDO:
+ event.Enable(win.CanRedo())
+ elif id == ID_CUT:
+ event.Enable(win.CanCut())
+ elif id == ID_COPY:
+ event.Enable(win.CanCopy())
+ elif id == ID_COPY_PLUS:
+ event.Enable(win.CanCopy() and hasattr(win, 'CopyWithPrompts'))
+ elif id == ID_PASTE:
+ event.Enable(win.CanPaste())
+ elif id == ID_PASTE_PLUS:
+ event.Enable(win.CanPaste() and hasattr(win, 'PasteAndRun'))
+ elif id == ID_CLEAR:
+ event.Enable(win.CanCut())
+ elif id == ID_SELECTALL:
+ event.Enable(hasattr(win, 'SelectAll'))
+ elif id == ID_EMPTYBUFFER:
+ event.Enable(hasattr(win, 'ClearAll') and not win.GetReadOnly())
+ elif id == ID_AUTOCOMP_SHOW:
+ event.Check(win.autoComplete)
+ elif id == ID_AUTOCOMP_MAGIC:
+ event.Check(win.autoCompleteIncludeMagic)
+ elif id == ID_AUTOCOMP_SINGLE:
+ event.Check(win.autoCompleteIncludeSingle)
+ elif id == ID_AUTOCOMP_DOUBLE:
+ event.Check(win.autoCompleteIncludeDouble)
+ elif id == ID_CALLTIPS_SHOW:
+ event.Check(win.autoCallTip)
+ elif id == ID_CALLTIPS_INSERT:
+ event.Check(win.callTipInsert)
+ elif id == ID_WRAP:
+ event.Check(win.GetWrapMode())
+
+ elif id == ID_SHOW_LINENUMBERS:
+ event.Check(win.lineNumbers)
+ elif id == ID_ENABLESHELLMODE:
+ event.Check(self.enableShellMode)
+ event.Enable(self.config is not None)
+ elif id == ID_ENABLEAUTOSYMPY:
+ event.Check(self.enableAutoSympy)
+ event.Enable(self.config is not None)
+ elif id == ID_AUTO_SAVESETTINGS:
+ event.Check(self.autoSaveSettings)
+ event.Enable(self.config is not None)
+ elif id == ID_SAVESETTINGS:
+ event.Enable(self.config is not None and
+ hasattr(self, 'DoSaveSettings'))
+ elif id == ID_DELSETTINGSFILE:
+ event.Enable(self.config is not None)
+
+ elif id == ID_EXECSTARTUPSCRIPT:
+ event.Check(self.execStartupScript)
+ event.Enable(self.config is not None)
+
+ elif id == ID_SHOWPYSLICESTUTORIAL:
+ event.Check(self.showPySlicesTutorial)
+ event.Enable(self.config is not None)
+
+ elif id == ID_SAVEHISTORY:
+ event.Check(self.autoSaveHistory)
+ event.Enable(self.dataDir is not None)
+ elif id == ID_SAVEHISTORYNOW:
+ event.Enable(self.dataDir is not None and
+ hasattr(self, 'SaveHistory'))
+ elif id == ID_CLEARHISTORY:
+ event.Enable(self.dataDir is not None)
+
+ elif id == ID_EDITSTARTUPSCRIPT:
+ event.Enable(hasattr(self, 'EditStartupScript'))
+ event.Enable(self.dataDir is not None)
+
+ elif id == ID_FIND:
+ event.Enable(hasattr(win, 'DoFindNext'))
+ elif id == ID_FINDNEXT:
+ event.Enable(hasattr(win, 'DoFindNext'))
+ elif id == ID_FINDPREVIOUS:
+ event.Enable(hasattr(win, 'DoFindNext'))
+
+ elif id == ID_SHOWTOOLS:
+ event.Check(self.ToolsShown())
+
+ elif id == ID_HIDEFOLDINGMARGIN:
+ event.Check(self.hideFoldingMargin)
+ event.Enable(self.config is not None)
+
+ else:
+ event.Enable(False)
+ except AttributeError:
+ # This menu option is not supported in the current context.
+ event.Enable(False)
+
+
+ def OnActivate(self, event):
+ """
+ Event Handler for losing the focus of the Frame. Should close
+ Autocomplete listbox, if shown.
+ """
+ if not event.GetActive():
+ # If autocomplete active, cancel it. Otherwise, the
+ # autocomplete list will stay visible on top of the
+ # z-order after switching to another application
+ win = wx.Window.FindFocus()
+ if hasattr(win, 'AutoCompActive') and win.AutoCompActive():
+ win.AutoCompCancel()
+ event.Skip()
+
+
+
+ def LoadSettings(self, config):
+ """Called by derived classes to load settings specific to the Frame"""
+ pos = wx.Point(config.ReadInt('Window/PosX', -1),
+ config.ReadInt('Window/PosY', -1))
+
+ size = wx.Size(config.ReadInt('Window/Width', -1),
+ config.ReadInt('Window/Height', -1))
+
+ self.SetSize(size)
+ self.Move(pos)
+
+
+ def SaveSettings(self, config):
+ """Called by derived classes to save Frame settings to a wx.Config object"""
+
+ # TODO: track position/size so we can save it even if the
+ # frame is maximized or iconized.
+ if not self.iconized and not self.IsMaximized():
+ w, h = self.GetSize()
+ config.WriteInt('Window/Width', w)
+ config.WriteInt('Window/Height', h)
+
+ px, py = self.GetPosition()
+ config.WriteInt('Window/PosX', px)
+ config.WriteInt('Window/PosY', py)
+
+
+
+
+class ShellFrameMixin:
+ """
+ A mix-in class for frames that will have a Shell or a Crust window
+ and that want to add history, startupScript and other common
+ functionality.
+ """
+ def __init__(self, config, dataDir):
+ self.config = config
+ self.dataDir = dataDir
+ self.startupScript = os.environ.get('PYTHONSTARTUP')
+ if not self.startupScript and self.dataDir:
+ self.startupScript = os.path.join(self.dataDir, 'startup')
+
+ self.autoSaveSettings = False
+ self.autoSaveHistory = False
+
+ # We need this one before we have a chance to load the settings...
+ self.execStartupScript = True
+ self.showPySlicesTutorial = True
+ self.enableShellMode = False
+ self.enableAutoSympy = True
+ self.hideFoldingMargin = False
+ if self.config:
+ self.execStartupScript = \
+ self.config.ReadBool('Options/ExecStartupScript', True)
+ self.showPySlicesTutorial = \
+ self.config.ReadBool('Options/ShowPySlicesTutorial', True)
+ self.enableShellMode = \
+ self.config.ReadBool('Options/EnableShellMode', False)
+ self.enableAutoSympy = \
+ self.config.ReadBool('Options/EnableAutoSympy', True)
+ self.hideFoldingMargin = \
+ self.config.ReadBool('Options/HideFoldingMargin', True)
+
+ def OnHelp(self, event):
+ """Display a Help window."""
+ import wx.lib.dialogs
+ title = 'Help on key bindings'
+
+ text = wx.py.shell.HELP_TEXT
+
+ dlg = wx.lib.dialogs.ScrolledMessageDialog(self, text, title,
+ size = ((700, 540)))
+ fnt = wx.Font(10, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
+ dlg.GetChildren()[0].SetFont(fnt)
+ dlg.GetChildren()[0].SetInsertionPoint(0)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+
+ def LoadSettings(self):
+ if self.config is not None:
+ self.autoSaveSettings = \
+ self.config.ReadBool('Options/AutoSaveSettings', False)
+ self.execStartupScript = \
+ self.config.ReadBool('Options/ExecStartupScript', True)
+ self.autoSaveHistory = \
+ self.config.ReadBool('Options/AutoSaveHistory', False)
+
+ self.showPySlicesTutorial = \
+ self.config.ReadBool('Options/ShowPySlicesTutorial', True)
+ self.enableShellMode = \
+ self.config.ReadBool('Options/EnableShellMode', False)
+ self.enableAutoSympy = \
+ self.config.ReadBool('Options/EnableAutoSympy', True)
+ self.hideFoldingMargin = \
+ self.config.ReadBool('Options/HideFoldingMargin', True)
+
+ self.LoadHistory()
+
+
+ def SaveSettings(self, force=False):
+ if self.config is not None:
+ # always save these
+ self.config.WriteBool('Options/AutoSaveSettings',
+ self.autoSaveSettings)
+
+ if self.autoSaveSettings or force:
+ self.config.WriteBool('Options/AutoSaveHistory',
+ self.autoSaveHistory)
+ self.config.WriteBool('Options/ExecStartupScript',
+ self.execStartupScript)
+ self.config.WriteBool('Options/ShowPySlicesTutorial',
+ self.showPySlicesTutorial)
+ self.config.WriteBool('Options/EnableShellMode',
+ self.enableShellMode)
+ self.config.WriteBool('Options/EnableAutoSympy',
+ self.enableAutoSympy)
+ self.config.WriteBool('Options/HideFoldingMargin',
+ self.hideFoldingMargin)
+ if self.autoSaveHistory:
+ self.SaveHistory()
+
+
+
+ def SaveHistory(self):
+ if self.dataDir:
+ try:
+ name = os.path.join(self.dataDir, 'history')
+ f = file(name, 'w')
+ hist = []
+ enc = wx.GetDefaultPyEncoding()
+ for h in self.shell.history:
+ if isinstance(h, unicode):
+ h = h.encode(enc)
+ hist.append(h)
+ hist = '\x00\n'.join(hist)
+ f.write(hist)
+ f.close()
+ except:
+ d = wx.MessageDialog(self, "Error saving history file.",
+ "Error", wx.ICON_EXCLAMATION|wx.OK)
+ d.ShowModal()
+ d.Destroy()
+ raise
+
+ def LoadHistory(self):
+ if self.dataDir:
+ name = os.path.join(self.dataDir, 'history')
+ if os.path.exists(name):
+ try:
+ f = file(name, 'U')
+ hist = f.read()
+ f.close()
+ self.shell.history = hist.split('\x00\n')
+ dispatcher.send(signal="Shell.loadHistory",
+ history=self.shell.history)
+ except:
+ d = wx.MessageDialog(self, "Error loading history file.",
+ "Error", wx.ICON_EXCLAMATION|wx.OK)
+ d.ShowModal()
+ d.Destroy()
+
+
+ def bufferHasChanged(self):
+ # the shell buffers can always be saved
+ return True
+
+ def bufferSave(self):
+ import time
+ appname = wx.GetApp().GetAppName()
+ default = appname + '-' + time.strftime("%Y%m%d-%H%M.py")
+ fileName = wx.FileSelector("Save File As", "Saving",
+ default_filename=default,
+ default_extension="py",
+ wildcard="*.py",
+ flags = wx.SAVE | wx.OVERWRITE_PROMPT)
+ if not fileName:
+ return
+
+ text = self.shell.GetText()
+
+## This isn't working currently...
+## d = wx.MessageDialog(self,u'Save source code only?\n' + \
+## 'Answering yes will only save lines starting with >>> and ...',
+## u'Question', wx.YES_NO | wx.ICON_QUESTION)
+## yes_no = d.ShowModal()
+## if yes_no == wx.ID_YES:
+## m = re.findall('^[>\.]{3,3} (.*)\r', text, re.MULTILINE | re.LOCALE)
+## text = '\n'.join(m)
+## d.Destroy()
+
+ try:
+ f = open(fileName, "w")
+ f.write(text)
+ f.close()
+ except:
+ d = wx.MessageDialog(self, u'Error saving session',u'Error',
+ wx.OK | wx.ICON_ERROR)
+ d.ShowModal()
+ d.Destroy()
+
+
+ def EditStartupScript(self):
+ if os.path.exists(self.startupScript):
+ text = file(self.startupScript, 'U').read()
+ else:
+ text = ''
+
+ dlg = EditStartupScriptDialog(self, self.startupScript, text)
+ if dlg.ShowModal() == wx.ID_OK:
+ text = dlg.GetText()
+ try:
+ f = file(self.startupScript, 'w')
+ f.write(text)
+ f.close()
+ except:
+ d = wx.MessageDialog(self, "Error saving startup file.",
+ "Error", wx.ICON_EXCLAMATION|wx.OK)
+ d.ShowModal()
+ d.Destroy()
+
+
+
+class EditStartupScriptDialog(wx.Dialog):
+ def __init__(self, parent, fileName, text):
+ wx.Dialog.__init__(self, parent, size=(425,350),
+ title="Edit Startup Script",
+ style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
+
+ pst = wx.StaticText(self, -1, "Path:")
+ ptx = wx.TextCtrl(self, -1, fileName, style=wx.TE_READONLY)
+ self.editor = editwindow.EditWindow(self)
+ self.editor.SetText(text)
+ wx.CallAfter(self.editor.SetFocus)
+
+ ok = wx.Button(self, wx.ID_OK)
+ cancel = wx.Button(self, wx.ID_CANCEL)
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ pthSizer = wx.BoxSizer(wx.HORIZONTAL)
+ pthSizer.Add(pst, flag=wx.ALIGN_CENTER_VERTICAL)
+ pthSizer.Add((5,5))
+ pthSizer.Add(ptx, 1)
+ mainSizer.Add(pthSizer, 0, wx.EXPAND|wx.ALL, 10)
+
+ mainSizer.Add(self.editor, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
+
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+ btnSizer.Add((5,5), 1)
+ btnSizer.Add(ok)
+ btnSizer.Add((5,5), 1)
+ btnSizer.Add(cancel)
+ btnSizer.Add((5,5), 1)
+ mainSizer.Add(btnSizer, 0, wx.EXPAND|wx.ALL, 10)
+
+ self.SetSizer(mainSizer)
+ self.Layout()
+
+
+ def GetText(self):
+ return self.editor.GetText()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/images.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/images.py
new file mode 100644
index 0000000..f3cb5a1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/images.py
@@ -0,0 +1,215 @@
+"""Support for icons."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com> / David Mashburn <david.n.mashburn@gmail.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+import cStringIO
+
+
+def getPyIcon(shellName='PyCrust'):
+ icon = wx.EmptyIcon()
+ icon.CopyFromBitmap(getPyBitmap(shellName))
+ return icon
+
+def getPyBitmap(shellName='PyCrust'):
+ return wx.BitmapFromImage(getPyImage(shellName))
+
+def getPyImage(shellName='PyCrust'):
+ stream = cStringIO.StringIO(getPyData(shellName))
+ return wx.ImageFromStream(stream)
+
+def getPyData(shellName='PyCrust'):
+ if shellName=='PyCrust':
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
+\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x04\
+\x95IDATx\x9c\xed\x97?lSG\x1c\xc7?\x97\x98\xd8Q\xa3\xdeY\xa2j\x06\xa4\xf7"QJ\
+\xbb<3@\x01\xa9\xc2\x0c\xa8!\x1d\x1c6\xcaB\xa8D[uI2\xf4\x8f\xe8\x103\xb4\xa2\
+,5\x0b\x03\x032C\xab\xc0\x92dh:t\xc0)*E\xcd@<Q\x01Rl\t\xd4D\xaa\xe4{R\xd0{&\
+\xa5\xd7\xe1\xfc\xec\xe7\xfciR\x08e\xe9O\xb2\xee|\xfe\xbd\xfb}~\xdf\xdf\xbd\
+\xbb\xb3PJ\xf1"\xad\xe3\x85F\xff\x1f\xe0y\x03h\xad\xcdA\xc7~\xb4\xd6f-\x9f\
+\xc4\xf3\x0c>Y\x1c#\x97\xddCUk\xf4B\x8d3\x9f\x8d\x9a\x9bU%\xe2~b\xab\xdf\x82\
+\x83N+\xd3\xe92\\\x1f\xcf\x93\xdd\x9f\xa1\xaa5\x95\xf9\n\xe7\xf3y\xe2\x10[V\
+\x82H\xe6\xd3G\x1dN\xf7\xc3\xa7\xc7a\xc0\x83\xc3\xc7\xf3\xcc\xcc\xcd\xe3(\
+\x85\xdb\xe7\xf2\xc9\xe8X\x1b\xe43+\x10\xd5\xb6\x94\x87Z\xe8\x90NU\x91I@\x00\
+\x06\xbe\x18\xb7J\x98\xca$`\x98\xb9]&{,\x8fRV\x85\xa7V@k\x9bq)o\x83+\t\xe9T\
+\xd5f\x95\x02\x91\xb4~_\r\xd9\xb6\xbaP\x03\x04n\x9f\xcbDa\xb8\t\xfe\xaf\x17a\
+<\xe3\xc8\x94lo\x9b\xd6\xa8\xf4\x80\x07\xb7o\xcd\xe0\x0c\x0e\xa2R\x8a\xb4\
+\x93n\xbal\x1a`e\xe0U\xc1\xd6\xb0\xb8\n\x99\x91"\x93\xaf\xba\xe4\x0ed\xda|6,\
+\x81\xd6\xda\x9c|\xab]\xea\xcd\x04\x8f\x9b\t\xad\nz\xa1\x02\x80\xdb\xe7R\x1a\
+\xcf\xa3\xb56\xeb\x02D5\x9e\xf8\xdc\xe1T\xff\xd3\x05\x8e\x82\x83U\xe1Z\xb1\
+\x18\x9b\xbf\x06\xacQ\x82H\xea\x01/Z@Ut\x08R\xb4$}\x16\xd3\x81A&%\xde\xee\
+\xbev\x80x\xe0]{\xb2\x1cR\xa5\xe6C*\xb5\xf1\xc4Q\xa6"e\xfbQ\x1b\x8dE\xe6\x87\
+>\xaa[Q\xadi\x0b\xb0r\x8f\x9e.\xc3t\xb9\xc4]\xaf5\xf6\xfe\xdb\xddt&\x02\xfa\
+\x9c\xf5\x01\xe2A\xa2\xbeX\x01>]ntR\x12\xe3[\x00\x01\x98\x89\x11[_\xed\xafn\
+\xab\x81U\xa0\xe7I7\x00\x97o\x04\xcd\x89\x06<;\xe9\x80\x07]i\x97\xc17\x1f\
+\xd2\xd3\x91`\xe9\xaf?\x01p^Y\x06Z\n\xfau8?a\xfb]i\x97\xec\xa1\x8c\x05(|\xd8\
+N\xba\xb3\xab\x87\xfb\x8f\x97\xd8\xd9\xd5\x03\xc0\xfd\xc7K\xec\xd8\xd6\xdd\
+\xfc\xfd\xc1r\xd0\xf4\x01\xda~\x03H\xf4\x04\xd4j :\xb75\xc7\xae\xfd\xbcLW\
+\xda\xa5\xf0M\x1e\t\xcc\xcc\xcdq\xa9P@\x8c\xf5fL\xdaHF\x16g\x9a\x19\xad\xcc\
+\xee\xcb\xa3\n\xad\xa1\xda\xf1\x08\xef\xe5\x97x\xf8\xc8f\xf8\xc7\x93:\xdb;\
+\x93M\xc8\x08j\xc7\xb6n\x1e,\x07m`\x97o\x04|;>\xd1T\xc4\x17\x8a\x13\xb9\xc3\
+\x88\x01\x0fs\xa4\x9cc}\xf3A\x190\x82\x1f\xddR{-\x1bV\xfc\xd8f\xba\xbd3\xd9\
+\x06\x15\x07\xbb\xf8\xd3\x12\xdf]-"\x93\xb2\xb1C*\xde\xcd\x1d\xde\xccN(\xc1\
+\xae\x17"\xd0#+<j\x17m{\xcd\x9bj\x00.\xaf\xf0Xb\xb8\xdfA\xa6\x14\x18\x03\x06\
+\xb4o\xcf\x8d\xc4\xbervc\x86M\xdaz\x80\x00\x95T\x19?\xd0 @&%~c\xbc\xe3W\xaf\
+\xb4e\x00\xffh\xc6@\xbd\x11\xbc\xde\x1a\xfe\xef.\xa5\xa2q4\n0\x81\xad\xe9\
+\xae7<\x12\xaf\xf5\xc2hy\xaa\xe97\x9cS\\\x98\xb2\x0e\x03\xb1\xcdhW\xdaC\x1a\
+\xa0\xa2\xa0\x0e"\x14`\xb0Y\x85\x1b\x1f\x12\xaa7\x03)\xd9\x84\xa8\xccW\xb8{\
+\xa7L\xe2\xde\x02\x94\xc6Gp_\xcf\x80\x90\x98\xd0g\xf4\xac\x82Pc\x82\x1a\xd5\
+\x10\x08}&\xa7J\xcc\xde.1]m\x80\xf6+\xee\xfd\xae\x9bo\xc4\xf0;\x80\xef\x90\
+\x0e\x04\x06`Q!\x02\x05\xc2 \xb5\xc2\x95\x15d\xb4C&[\xf7\xd2\x04\x80\xbb\xdb\
+\x9e\xd1\x8e\x02\x90\xd8\xd4$ I\x87\x80\xf1\xf1\xdc!4\xc3\x88\x94}\xd8,TH\
+\xbb.5m\xf0C\x9f3\x1f\r\x01\x96.\x82\x1a9\xe9Q\xb8\xd2\xf8\xf25\x0c\xbe\xe7#\
+\x92\x12\x1d[\x03\t\x00E\xf4\xa6\t\xaaZ7`$\x18\x90\xf8\xf8\x80JK\x94\xa1\x01\
+\x07\xb8\x0e~X\xc3\xed\x16\xf8)\xf8~j\x12B\rI\x89_\xf7!0 \x04\xf9Q\xc0\x18\
+\x0c\xd1i\xea\x13\xb7\x04\xc0\x89\x93C\xabj\xb6\xf7@\x96\xd9_J|0:\x86R\n\xb7\
+\xd7@\xaa%\x9d\xa3$\xba.\x90RA]\xe3\x87\x1a\x89\xdd\xefeR\xc2\x1a\'\xa8\x1f\
+\x82\x0e-@m\xd1\xde\x076\xbc\x15\x97~(\x9a\x89b\x9e\xd9[s\xab!\xf7g\xd6\x1c\
+\x8f\xdb\xbel\x8e\xa1S\xc7\xda\xc6\xe6\xee\xccs\xe9\xdcYnV\x95\xd8\xf2?&q+\
+\x9c\x1b1\xf3\xbf\xcd3{\xfdJ\xdb\xf8\xde\xfd\x19.\\\xad\x08\x80\xbf\x01\xd1\
+\x86\xfa\x8b\xc7\xc0\xc8\xb7\x00\x00\x00\x00IEND\xaeB`\x82'
+ elif shellName=='PySlices':
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\
+\x00szz\xf4\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x06bKGD\x00\xff\
+\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\tpHYs\x00\x00\x0b\x13\x00\x00\x0b\
+\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xd8\n\x16\x03#\x0eV,\xc0?\x00\
+\x00\x06\xb8IDATX\xc3\xbd\x97\x7flS\xd7\x15\xc7?\xd7v\xe2\x17\x12x\xcf\x04X(\xb4\
+vT\n\x94L}\xde\xd6\x1f\x012\x91Pe\xd0LZ\x82\x80\xf2\xa3\x1a\t\xd2\xc6\xd0\xa4)\
+\xc9\xb4\x9f\x19\x1bN\xd6N\x1bRGZ\r\xb6vR\x15\xa6u\xb0I[b\x952\xf6C\xc2\xd01\xca\
+"Z\xa7\x82\xb2-lq\x10\xac\x89`\xf2{4\x89\xed8\xf1\xdd\x1f\xd7v\xe2\xfc\xa2H\xed\
+\x8ed\xbd\xfb\xae\xcf\xbd\xe7{\xce=\xdfs\xcf\x13\xcc,K\x97\x15\xf3\x9f#_\x04\xa3\
+\xd0Ar\\b\xc5\x04\xef\xf4\xbb\xa8*\x1b\xe7\xd0\xeb\xc5\xa9\x84X\xc4\xdem\x15\x94\
+,6p9\x1d\xa2x\xa1!*w>\x0b\xc0\xfaG\x1f>\xfa\xe7\xf3=G\xe2\xf1\xd1w\xb9\x8b\x88\x99\
+&\x1f{\x90\xe1\xf2\x95D?\xf7\x04K\x8cB\xf2\x1c\x0ep:@\x02\x89\xa4@\xcb\x93\x9c\xbc\
+\x94\xc7\xf9\xde"\xecQCn\xaaX!?\xfeP\tK\x97\xadHY\xc3Iy<x>\x15\xfc\xe3E\xc7\x9d\xf7\
+G6\x00\x17\xee\x15\x80o\xdf\x93\\\xae-\xc7Y\xe2A\x13\x0e@\x82\xc3\x91\xab4:\x06\xe3\
+)\xc1\xa0\r{\x8f\x14\x12\xb5\x87\xd8\xb3}\xe3\xf8W\xf7\xd5\x8e\xcf\x9b\xa7\xc5\xae\
+\xfc\xfbfd\xcb\xe7\xdbL`3\xf0\x87{\x01\xb0rc\x19\xe1gw\x93\xafi8\xa7\x1a\x9e,\xef\x8f\
+\xc0_\xae@b\x0c\xd6\xafv\xf2\xf4\x0b\x05D\xed!\xaew\xbf\xc2B\xbd\x88\xdb##\xf8\xfc\r\
+\x00\x07\x81\xb6\x0f\x04\xa0r\r\xe3\xa6\x8f\xe4\x9e\x8d\xe4;\x1c\x08!f\x07p\xee2|\xaa\
+\x14\x9c.\x88\xc7\xc1\x99\x0f\xd7n\xeb\x1c\xbb\xe8\xa5\xe5+;\xa8./\xa3\xdf\xb2x\xb7\
+\xe7_\xd4\xd4\x7f?\x04TM\xddc\x9a\x7f+\xefCT\x9bs\x1b\xbfz\x03~z\x1a\x8a\xe7\x83p\x80\
+\xe6\x06C\x87\xf9\x05\xf0\x89\xfbm\xda\xb7\xbd\xc3gv~\x87`\xe8m\xbc\x86\xc1\x1a\xf3A\
+\xc2\xa7\x0fW\xd6\x98\xc8\xbb\x02\xb0c\xe0\xce\x03)\xd5o&y\xeb\x1al}\x0c\x96\x190\xaf\
+`f\x9d\x1a\x13\xea\x1aZ\t\xbd\x19\xc6k\x18\x18%\x1e\xbe\x11\x080\x15\x84s\xf2\xcb\xaa\
+\xfb\x90;\xd6#|\x1fC\xb8\\\n@&\n\x89$<\xfa5\xb8u\x07\x9e\xa9\x00-\x0f\x16,\x98\xfdx\x9e\
+\xf4\xc3\xf5\x018p$DU\xe5\x13\x98\xbe\xa5\x88\x02\x8d5\xa5&\xb7\xfa\xce\x06z\x07i\x05pM^T\
+\xb1\x1a\xca\x1e\x80\xfc\xbc)Q\x19\x81\x17O\xc2\x1bm\x8a\x8a.\xd7\xec\x9e\x03\xc8\xb8\xca\
+\xae\xe7v\xa6\xf3\xaa\xae\x19\x19\xe9\xe2\xec\x990\xe1\x7f\xf4s\xaag\x86#x\xe6\xd3\xc8\xe5\
+\xc50\xcf\x9d\xceN1A\xbdC\x9d\xb0c-\x8c\xa7\xd4y\x17hw).\x1a\x087\xfc\xee-\xb0\x13j\xee\x97\
+\x9d!\xaa*L\x1a\xf7\xd7\xd2\xd9\xde\x88"\xf7\xa4\x08\xdc\xf8/|\xa1Z%\x95\x10*\xfc\xf6\x1d\
+\xa8\x0c@(\x00yy\xca\xb8\xd39\xb7\xf1_\x9c\x81\x01\x1b\x12\xa3p`+l]\x07-\x1dP$,\x84t\xe0\
+5t(\xf7g\xf5\xb3\x00\x16\xce\x87"\rR)H\x8e\xc3\xf3A\x05"\xf8Me\xd8\xe5\x9an\xfc\xf2ux\xf5\
+\x1c\xfc\xfe\x12|{+\xdc\xbf\x18\xf6TM\x07\xf5\x83\x06\xf07u\xd0u\xdc\xc7\xf2%~"\xef\xf5\
+\xe7\x1e\xc1S\x9fD.1\x94\x97c)\xd8\xdc\x06\x8f<\x00\r\x1b\xc0(\x84\x94T\x002\xf2\xbd\xe3\
+\xe0o\x86A\x0b\xea\xab\xe0\xe4\x01\xd8Q\x01\xebV\xcd\x9e\x135&X\x03\x11UjK}\x84N\x04\x00\
+\xa4\x0b@\xd7`\xd7Z\xa5\xfc\xd2i\x08~]\x8d\xc7Rp\xcb\x86\xfd?\x87M~\xe5qO\x04\xc2\x87\xa1\
+m\x17\x1fHd|"\n-\x1d\x1d\xd4o\xa9\x03\xc0\xb2\xa2\xea\x08\xb6\xaf\xa3\xfb\xc4_\xe1[\xdb\x95\
+W\xa1\x80Z\xb0\xed\xc7\xb0\xa1\x0c~{A\x19\xfc\xb0\xc4\x8aIt\xb7\x8e\xb9\xba4\x9d\x03)J\x1f\
+\xf1*\xe3Ue\xf0\xfck\xf0\xda\xa5\t\xa3\xdf}\xfa\xde<\x15\x9a\x1ag\x9e\x99\xb9,\xa5\xe36F\
+\x81A\x7f\xd4R\x00.\xf62\x1cKR\x0cp\xe6\xca\x84bK\xc7\xc48\xc3\xdb\xb9"1\xd9Hf,\xa6\xd05\
+\xcb\x7fMG\xdaV\xf62\x92\x9dM\xaa\x96[\xf6\xf4g\x7f\x0c\x0c\r\x8a\xc6\x0b\xd8\xf6\x93\x185\
+\xe6\xc4F\x99q\x8d\t\xf9\x1e\x1fuknR\xe4p1\x94\x1a\x03\xc0\xbb8\t\xa8\xf5\xa0j\xc2\xa1N5\
+\xce\xf7\xf8\xa8\xdc\xe0W\x00\xda\xbf\x94\x8btE~\x11\xd7F\x87X\x91_\x04\xc0\xb5\xd1!\x96\
+\xe7M\x94\xbe\x1b\xc9XV\x07\xc8\xf9\x0f\xc0U\x14#\x1a\x05\xe1\x9c(\xa9\xbf9\x9f$\xdf\xe3\
+\xa3\xfdp\x00\x1d8\x1b\x0e\xf3r{;\xe2`\x89_z\xa4N\xd3\xe0\xd9Y\xbd{\xee)\x03\xcb\x82~\xc70\
+\xe6\x82Bn\x0e+\x0fo\x8f\'X\xe4tgAf@-\xcf+\xe0F2\x96\x03\xec\x957b\xbcz\xa23\x1b\x11[\x18\
+\xec\xae\xadB\xd4\x98\xc8\xea\x9e\xda9\xd2\xcb\x06C\x82\x14\xfc\xc9\x17\xca=\xcb\xb4t|Yy\xba\
+\xc8\xe9\xce\x015\x19\xd8\xd1sC\xfc\xea\xd7\x1d\xe8n=\xdd\x85\x18|\xb6\xb6*\xf72\x9aYtP\
+\xf9B\x06h\xf5\x14\x8d\xe8\xd1t\x98\xcd`\x1a`r\x8a\xc6\x10\x8d\x9b\xbd\xe8\x9a\x91\xbe\xe7\
+\xc1\xb2U5t=\xdeS\xf9\xa1q|6\x80\x00\x11\xad\x07;f\x81\x00\xdd\xadcgJ\xf1\xdf\xcc\x10\xff\
+\x17\x91\x12\x12i\xe3\x899:\xa2\x8fL2\x9d\x8d\x00\x19Sg\xba\xf2a\x13\xd7C%\xd0\xdc\x13\xcc\
+\xea5\xd6\x1a\xbc\x10\xb4\xb2L\xc8\xf6\x8a\x1e\x13]\x02\x11\x03\x12 \xe2"\xfd\xa1\x00z\\\xbf\
+\xab}\xa3\xc4\x0f\x9a\x9e\x05\x11\xe9\x8b\xf0\xcf\xab=\xb8z\x07 t\xa2\t\xdf*?\x08\x1d\x19\
+\xb7in5 n!cQ\xfa\xe3@\xdc\xa6+\x18\xa2\xfb\xed\x10\xa7\xd27i\xe3f\x83\xde\xf7\xac,#\x1a7\x01\
+\xb6\x17OL\xa8Nc\xd0@\xc4\x0c\x10\x12\xdd2\xf0\xe9\x11\xf4L\x85t\x8b\xdc~\xc0\xb7Z5\x08^#\x9d\
+\xf5\xc8\xf4S\xc7\x13\x07\xa4\x8d\xe9k\xc0\xa2\x11\xa1\xa9\xc5r \x82\xc7\xe7#jI\xec\xb8M\xcb\
+\xfe\x06\xa0?\x87\xa6M\xf5&\xed\xc7\xd2/?\x82\xba]6\xc2\xadcM\xca\x01\x97bd\x86i\x82~\xcbJ\x83\
+\xd1A\x82\x8e\x8d\r\x18\x1e\x1dCf;)\xf0y\xb1\xe3Q|\x05\x02[\x83\xd7\x83]\x10\xb7\xc0\xadc\'l\x88\
+\xa9\x8e6\xd0\xac\x12P\xa2\xda4\xb2\xf9?\t\xc0\xee\xfa\x86\xe9\xdf\x87k+\xe9\xbe\x10b_\xf3A\x0c\
+\xc3\xc0W"A\x9b\x08\x9d\xd7\xd0\xb1\x12\x02]7 aa\xc7-\xf4t\xbd\xd7\xdd:\xcc\xd07\xdaq\xb0\xe2\
+\n@t0:\xfb\xc7\xe9d\t_\xe8\x92\x9d\x1d\x01\xba\xdf\x0cO\x07Y\xee\x9fq~\xb2<^YK\xc3\xde-\xb9{^\
+\xed\xe3\xe5\x1f\xb6r\xaa\x07!>J\xe6u\xfc, \xfb\xfe\xdeG\xf7\x99c\xd3\x80\xb7\xbe\x14\x16\x00\
+\xff\x03\x07\x06\x80\xbbd\xd4\xb0\x14\x00\x00\x00\x00IEND\xaeB`\x82'
+ elif shellName=='SymPySlices':
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
+\x00\x00szz\xf4\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x06bKGD\
+\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\tpHYs\x00\x00\x0b\x13\x00\
+\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xd9\n\x10\x10\x0c\
+\x119od\xf7\x00\x00\x07\xa2IDATX\xc3\xb5\x97{PT\xd7\x1d\xc7?wY\x96\xbb\xb0\xcb\
+\xbd\x08\x08\xa8\x19V\x05\xe2\xab\xd95\xc1\x88\xa2\x03\x98\xf1\x11\'-\xda\x98h\
+\x92\xa9b\x1fN:mG\xb0\xb13\xd5v\x80\xc4\xa9m\x98\x04\x8cQcfj \xcdL\x9c\xfc\
+\x03$\xea\x18k\'\xc4\x91\xa8\xa5Iv\x93\xf8H\xa0e7\xf1\x01\xa3v\xef\x85\x95\xbd\
+\xeb\n\xb7\x7f\xdc\xdd\x85\xe5\xa1If\xfa\x9b\xb9s~\xf7\xbc~\xdfs~\xdf\xf3;\xbf\
+#0\xbe\xe4LM\xe7\xea\xbe_\x80\x9cb"<\xa8\xa3\x04\x05>\xf3\x99)\x9b;\xc8\x8bG\
+\xd3\x87BB\x06\x9b\xd7-!;S\xc6\x9c`\x12\xd2\'\xc9B\xe9\x86]\x00\x14\x17\xce\xde\
+\x7f\xb2\xdd\xb3O\xd3n_\xe0\x1e"\x8cW\xb9`&\xb7\x8a\n\xf0\xffh!\x93\xe5\x14\x12\
+M&H0\x81\x0e\x84\xc2\x02b\xa2\xce\x91\x8f\x13i\xef\xb4\xa1\xde\x96\xf5\x95K\xf2\
+\xf4y\xf9\xd9\xe4L\xcd\x1bRn\x85\xf5\xb7[\xdb\x87ZO\x9c3\xf5\xf5\x0f\x94\x00g\
+\xbe+\x00\xc7\x96G\xf8\xa2\xbc\x88\x84\xec4D\xc1\x04\xe8`2\xc5w\xba}\x07\x06\x87\
+\x04zU\xd8\xbc/\x05\xbf\x1a`\xe3\x13\xcb\x06\xb7m)\x1fLN\x16\x83\xe7\xffs\xc5\
+\xbb\xf6\'\xcf;\x81U\xc0\xfb\xdf\x05@\xc1\xb2\xb9\xb8w=\x8dE\x14I\x18mx\xa4\xf4\
+\x0f\xc0\xe9\xf3\x10\xba\x03\xc5\xb3\x12xr\x8f\x15\xbf\x1a\xe0\xeb\x8eCL\x92l\xdc\
+\x18\x18\xc0\xe1\xaa\x00\xa8\x06\x9e\xffV\x00J\xe70\xe8t\x10\xde\xb8\x0c\x8b\xc9\
+\x84 \x08\x13\x038\xf5\x05<4\x1d\x12\xcc\xa0i\x90`\x81\xae\x1b\x12M\xe7r\xd9\xf1\
+\x9b\xf5,/\x9a\x8bOQ\xb8\xe0\xf97\xab7\xbd\xd0\x06\x94\x8d\x9ec\xcc\xfa\n\xa6 ,w\
+\xde\xdd\xf8\xc5\xcbp\xe08\xa4\xdbA0\x81\x98\x04\xb2\x04v+\xcc\xbfO\xa5a\xddg\xac\
+\xd8\xb0\x93\xd6\xb6O\xc9\x95e\xe68g\xe2>^_\xba\xda\x89~O\x00j\x10\x92\x12A\xd7\
+\x8do<\xf9\xa4\x0b\x1e_\x00SeH\xb6\x8e\xdfg\xb5\x13\xd6T\xd4\xd2v\xd6M\xae,#g\xa7\
+\xf1\xbb\x9a\x1aF\x83H\x18\xf9s\xff\x14\xf4\xf5\xc5\x08\x8e,\x04\xb3\xd9\x00\x10\
+\xdd\x85P\x18\n\x9f\x83\xeb}\xf0\xcc\x12\x10\x13!5ub\xf7<\xe2\x82\xaf{\xe0\x0f\xfb\
+\xda(+]\x88\xd3\x91\x83`\x15\x993\xdd\xc9\xf5\xee\x0fk:{\xa9\x1d\xc3\x81\x9f-C\xdf\
+X\x06\xf6d\xc3\xb0\x1ea\xff\x81\xe3p\xf0}\xbe\x97d\xda\xe1z?\xe8\xde\x16\xdeln\xc3\
+\xfd\xa5\x8f\xfa\xd7\x9ac\xb6c.xf)\xfa\xb4tHN\x8a\xb0S0\x8c\xff\xf5\xe4\xf77\x0e\
+\x90\x96S\xc0\x91#Gx\xab\xb9\x8d\xb2%N\xb6>[Ns\xc3V\x8c\xc3=\x02\xc0\xe5\x9bP\xfa\
+\x03\x83T\xd1\xd5+*\xec=:\xf1\xe4\xc9\xc9\xc9$\'\'#\x8ab\xbc\xd1\xb44222\xc8\xcc\
+\xcc\xa4\xae\xae\x0e\xd7\xbc|l\x82\x82\xa0\x9b\xc8\x95e\xe6\x17\xb9b}\xcdQe\x92\x1d\
+l"\x0c\rAx\x10^j\x85\xf6\x8bF\x9b\x1eac \x10\xc0n\xb7\xc7\xd5i\xda\x00CC\x90\x92\
+\x92\x02@__\x1fv\xbb\x9d;\x9a\x1f\xf4A\xd0u\xbe9\xf9s\xd6V\xbeK\xcb\xdb\x0e\xa6Mv\
+\xe1\xbd\xe6\x8b\x07\xf0\xe8\x83\xe8\x93eHL\x84\x81\x10<\xfa\x02\xfc\xf6\x87p\xe6\
+\x12\xdc\xf8\xf2]\x00<\r\x02\xdd\xbd\xf1;\xf0\xf2O\x05\xa6\xa6\x1b\xc0\xa3b\xb7\xdb\
+\xf9|_*C\xe1\xfeX\x9d\xae\x19\xa7B\xe9\xf1\x02.\x1c\xd3\x1d\xb4\x1d\xae\xa1tC\x8dn\
+\x06\x90Dxj\x91\xd1\xf9\xe0qh\xddn\xe8\x8b\x0b\xc0"\x17\x90)\t\xactA\xfb\xa5QL\x7f\
+`|\xd7\x8c6\x0e\xf0\xa7\n\xd8\xd1\xd8\xc8\xa6\xb5k\x00P\x14\xbf\x11\x07\x9eXL\xc7\
+\xe1\x8f\x8c@\xe2\xaa\x82\xcd\xa5\xc6\x80u/\xc3\x81\xbfCj\xd6,N\xd6\xc2\xf6\xb5\xb0\
+n\xf1\xf8\x06\xff\xdb\xff\xedI\xa9\x04u\xa4$\t\xe7\xac\xe9\x11\x17\x0c1\xfd\x81\\\
+\xc3x\xd9\\x\xe9=x\xefcp\xd7\x1b\x03\xfe\xf8\xe4\xf0\xe0\xce\xabF\x99\x95\x95\x157\
+\xa9\xefz\xbc\x11]\x03A\x1c^\xbd0\xc2E\xaa\xa6"[e|~\xc5\x00p\xae\x93[\xc10\xe9\x00\
+\x1f\x9c\x1f\xee\xb8\xa3qX?\xe61\xca\xfc\x1c\xa3,,,$|k\x98\x10\xa3\xb9\x115(\xc4\
+\x1f\x8e\xd8<\x88\x12\xba\xaa\xc4.#\xbd\xb9\xd2p\x81\xa2\x8e-}A\x90E\xb0\rZY\xf7j\
+\x10\x80\xba\xba:f\xcf\x9e\xcd\xfe\x9d\x8fq\xcc\x03yY\xd0\xd5;|b\x9a~e\x01 73\x0c\
+\x18\xe3\x01\xd4\x10\xbc\xd8l\xe8\x964\x07\xa5%.\xe3\x14\xf8\x82\xc6\x17\xd5\xf3,6\
+<=\x01\xf2,6\xf2,\xd0\xa5\x05\xb0%\x0e\xaf\xa4\xa4\xa4\x04\xdb\x95\x16V\x14\xc1\x8a\
+"8y6\x81\xae\xdeA\xa6M\x9bf\x18L\r\xe3\xf7\x83\xef\xba1\xc8\x07\xbc\xd3\x1e\xc6\x92\
+\xe6`\x7fc\r\x12\xf0\xa1\xdb\xcd\xeb\r\r\x98\xaa\xb3]\xd0RB\xe5A8q\x16*\x0f\xc2c{\
+\x03\x9c8k\x94\xfbO\x05(I\x93\t\xde0\x0fgL\x0b\x16p\xb3\xeb4rB"y\x16\x9b\x912\x01\
+\xaa\xaa\xd2\xef\xbf\xcc\x9d\x80\x15\x15\xb0\x99\xcc\xb1\x0f\xe0\x8d\x03\xf5H\xa2\
+\x84,K\x94\x96\x95\x1b\x1c\xe8\xc8r\xb3\xdcSN=\xe5\xe0\x81\xe5Q+Q\xdd\xa3\xd2\xe6\
+\xd3\xd9\xd5w.\xce\x9fK\xb7\x9f\x8aha\xd6/2\x00\xf4\xf7\xf7#Z%D!\x81<\x8b\x8d\x81\
+\xdb:\xa7\xae\xdeb\x95\xc3\x16\t\xef*R\x92\x04\x02H\xa3#\xe1\xc4"\xe1V\xaep\x13-\xae\
+\xb6\x9e\xf2\x98~\xfeL\x0f`\x00\xdc\xfdb=\xd5{\x03\xb16Q\x14\xf9|\xe1C\xb8r\xbcH\xa2\
+\x1c\xb9\xe7AQ\x8dhhz\xd8SzO\x08M\xfc+\xa6\x17\x17\x17\x8fi\xcf\'#\xa6WWW\xc7\xb5}\
+\xd3q\x89\x9d3\x1f\x07Q@\r*\xa8!\xd5pW4!\xf9\xa7\xb3\xed\xae\xc6\xaf\xd1\x17\xf7\xbf\
+{\xf7n\xaeF/\x89\x88X&\xd8\xc8\xbc\xbc<2\xe6\xe5r\xfe\xd0?\x8c\x95\x87@J\x92PCw\xc9\
+\x88\xc6<\x10H\x8d\xdb\xce\xa5K\x97r\xfa\xf7\x7f\x1b\xd3o\x1b%q\xffV\xab\x95\xce\xce\
+N\x94\xaek\xc3\xf7{\xe4\xe0\xebA#\x06\x14\xccvb\xce\xcf\x86*Okl\xe0\xd6r\x99=\xadJ,\
+\xad\x02X\r\xecz\xe3\x13\xe6\xcf\x9fOX\x0bq\xa1\xf3#\x04Y\x88<\x14@\xd2$\xeeC\xe6\xad\
+\x07\xab\xc8\xdd\xf3cf\xcc\x98\xc1\x94)S\xb8\x13\x0c\xd1\x98\xffK\xe3hf\xbb@\x94b \
+\xbc\xdd^\xbe\xba\xe8\xc1\xdc\xd9\x03m\x87+q\xdc\xef\x02AB\xd7T\xaaje\xd0\x14\xf4\xa0\
+\x1f\x9f\x06h*o\xbe\xb2\x8dC\x03*\xaf\xbe\xf3\xa9\x01t\x95L\xe75%\x16\xdd\xb6\xae\x04\
+\xaf\x9aK\xd7\xaf\x9b\xf9\xcaU\x88\xdf\xad\x12\xf0\x86A\xd6\x91\x14\x19\x87\xe4E\x8aF\
+\xc8$!\xfe:v\xcc2\x12\x84\\\xd9`\xbd\xb14\t\x90H\xd3\x00]\xc5\xe9\xa8@A\xe2\xb9Zc\xb0\
+\xde\xe3%\xcd\xe1\xc0\xaf\xe8\xa8\x9a\xca\x8eg+"!\x07j\x9a\xbc\x00Tnr\xd2\xd0\x14A\xf8\
+\x17X\xf3\x94\x8a\x90$\xa1\x8c\xe0\x80\x19@\x06\xa2\x91\xd9\xa7(\x110\x12\xe8 \xa1\xa2\
+\x02r\x9a\x84\xac\xc72)p\xe4\xa2j~\x1cV\x01U\x84\xa3\xad-\xa0)\x90$\x19L\x0f\x1a\x19\
+mM\x15\xa0\xeb\xe8\x80\x904\x92\xff#\x00<\xbd\xa9b\xec\xfbpQ)\x1dg\xda\xd8RU\x8d,\xcb\
+8\xb2u\x10\x87\xb7.W\x96PB\x02\x92$CHA\xd5\x14\xa4H\xbc\x97\x92$\x10\xc7\x12Z\xd5@\xd1\
+\x0c\x00\xfe^\xff\xc4\x8f\xd3\x91\xe2>\xd3\xa277\xd6\xd0q\xd6=\x16d\x91k\xdc\xfa\x91\
+\xf2pi9\x15\x9b\xd7\xc6\xcfy\xb1\x9b\xd7\xff\\\xcb1\x0f\x82\xc0\xffQ\x1a_\xab\xd1\xbb\
+/u\xd3\xf1A\xd3\x18\xe0\xb5\x07\xdd\x02\xc0\xff\x00+\xe4\xca\x93\x95`\xa8\xfa\x00\x00\
+\x00\x00IEND\xaeB`\x82'
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/interpreter.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/interpreter.py
new file mode 100644
index 0000000..35468a1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/interpreter.py
@@ -0,0 +1,170 @@
+"""Interpreter executes Python commands."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com> / "
+__author__ += "David N. Mashburn <david.n.mashburn@gmail.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import os
+import sys
+from code import InteractiveInterpreter, compile_command
+import dispatcher
+import introspect
+import wx
+
+class Interpreter(InteractiveInterpreter):
+ """Interpreter based on code.InteractiveInterpreter."""
+
+ revision = __revision__
+
+ def __init__(self, locals=None, rawin=None,
+ stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr,
+ showInterpIntro=True):
+ """Create an interactive interpreter object."""
+ InteractiveInterpreter.__init__(self, locals=locals)
+ self.stdin = stdin
+ self.stdout = stdout
+ self.stderr = stderr
+ if rawin:
+ import __builtin__
+ __builtin__.raw_input = rawin
+ del __builtin__
+ if showInterpIntro:
+ copyright = 'Type "help", "copyright", "credits" or "license"'
+ copyright += ' for more information.'
+ self.introText = 'Python %s on %s%s%s' % \
+ (sys.version, sys.platform, os.linesep, copyright)
+ try:
+ sys.ps1
+ except AttributeError:
+ sys.ps1 = '>>> '
+ try:
+ sys.ps2
+ except AttributeError:
+ sys.ps2 = '... '
+ self.more = 0
+ # List of lists to support recursive push().
+ self.commandBuffer = []
+ self.startupScript = None
+
+ def push(self, command, astMod=None):
+ """Send command to the interpreter to be executed.
+
+ Because this may be called recursively, we append a new list
+ onto the commandBuffer list and then append commands into
+ that. If the passed in command is part of a multi-line
+ command we keep appending the pieces to the last list in
+ commandBuffer until we have a complete command. If not, we
+ delete that last list."""
+
+ # In case the command is unicode try encoding it
+ if type(command) == unicode:
+ try:
+ command = command.encode(wx.GetDefaultPyEncoding())
+ except UnicodeEncodeError:
+ pass # otherwise leave it alone
+
+ if not self.more:
+ try: del self.commandBuffer[-1]
+ except IndexError: pass
+ if not self.more: self.commandBuffer.append([])
+ self.commandBuffer[-1].append(command)
+ source = '\n'.join(self.commandBuffer[-1])
+
+ # If an ast code module is passed, pass it to runModule instead
+ more=False
+ if astMod != None:
+ self.runModule(astMod)
+ self.more=False
+ else:
+ more = self.more = self.runsource(source)
+ dispatcher.send(signal='Interpreter.push', sender=self,
+ command=command, more=more, source=source)
+ return more
+
+ def runsource(self, source):
+ """Compile and run source code in the interpreter."""
+ stdin, stdout, stderr = sys.stdin, sys.stdout, sys.stderr
+ sys.stdin, sys.stdout, sys.stderr = \
+ self.stdin, self.stdout, self.stderr
+ more = InteractiveInterpreter.runsource(self, source)
+ # this was a cute idea, but didn't work...
+ #more = self.runcode(compile(source,'',
+ # ('exec' if self.useExecMode else 'single')))
+
+
+ # If sys.std* is still what we set it to, then restore it.
+ # But, if the executed source changed sys.std*, assume it was
+ # meant to be changed and leave it. Power to the people.
+ if sys.stdin == self.stdin:
+ sys.stdin = stdin
+ else:
+ self.stdin = sys.stdin
+ if sys.stdout == self.stdout:
+ sys.stdout = stdout
+ else:
+ self.stdout = sys.stdout
+ if sys.stderr == self.stderr:
+ sys.stderr = stderr
+ else:
+ self.stderr = sys.stderr
+ return more
+
+ def runModule(self, mod):
+ """Compile and run an ast module in the interpreter."""
+ stdin, stdout, stderr = sys.stdin, sys.stdout, sys.stderr
+ sys.stdin, sys.stdout, sys.stderr = \
+ self.stdin, self.stdout, self.stderr
+ self.runcode(compile(mod,'','single'))
+ # If sys.std* is still what we set it to, then restore it.
+ # But, if the executed source changed sys.std*, assume it was
+ # meant to be changed and leave it. Power to the people.
+ if sys.stdin == self.stdin:
+ sys.stdin = stdin
+ else:
+ self.stdin = sys.stdin
+ if sys.stdout == self.stdout:
+ sys.stdout = stdout
+ else:
+ self.stdout = sys.stdout
+ if sys.stderr == self.stderr:
+ sys.stderr = stderr
+ else:
+ self.stderr = sys.stderr
+ return False
+
+ def getAutoCompleteKeys(self):
+ """Return list of auto-completion keycodes."""
+ return [ord('.')]
+
+ def getAutoCompleteList(self, command='', *args, **kwds):
+ """Return list of auto-completion options for a command.
+
+ The list of options will be based on the locals namespace."""
+ stdin, stdout, stderr = sys.stdin, sys.stdout, sys.stderr
+ sys.stdin, sys.stdout, sys.stderr = \
+ self.stdin, self.stdout, self.stderr
+ l = introspect.getAutoCompleteList(command, self.locals,
+ *args, **kwds)
+ sys.stdin, sys.stdout, sys.stderr = stdin, stdout, stderr
+ return l
+
+ def getCallTip(self, command='', *args, **kwds):
+ """Return call tip text for a command.
+
+ Call tip information will be based on the locals namespace."""
+ return introspect.getCallTip(command, self.locals, *args, **kwds)
+
+
+class InterpreterAlaCarte(Interpreter):
+ """Demo Interpreter."""
+
+ def __init__(self, locals, rawin, stdin, stdout, stderr,
+ ps1='main prompt', ps2='continuation prompt'):
+ """Create an interactive interpreter object."""
+ Interpreter.__init__(self, locals=locals, rawin=rawin,
+ stdin=stdin, stdout=stdout, stderr=stderr)
+ sys.ps1 = ps1
+ sys.ps2 = ps2
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/introspect.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/introspect.py
new file mode 100644
index 0000000..0a14f89
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/introspect.py
@@ -0,0 +1,389 @@
+"""Provides a variety of introspective-type support functions for
+things like call tips and command auto completion."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import cStringIO
+import inspect
+import sys
+import tokenize
+import types
+import wx
+
+def getAutoCompleteList(command='', locals=None, includeMagic=1,
+ includeSingle=1, includeDouble=1):
+ """Return list of auto-completion options for command.
+
+ The list of options will be based on the locals namespace."""
+ attributes = []
+ # Get the proper chunk of code from the command.
+ root = getRoot(command, terminator='.')
+ try:
+ if locals is not None:
+ object = eval(root, locals)
+ else:
+ object = eval(root)
+ except:
+ pass
+ else:
+ attributes = getAttributeNames(object, includeMagic,
+ includeSingle, includeDouble)
+ return attributes
+
+def getAttributeNames(object, includeMagic=1, includeSingle=1,
+ includeDouble=1):
+ """Return list of unique attributes, including inherited, for object."""
+ attributes = []
+ dict = {}
+ if not hasattrAlwaysReturnsTrue(object):
+ # Add some attributes that don't always get picked up.
+ special_attrs = ['__bases__', '__class__', '__dict__', '__name__',
+ 'func_closure', 'func_code', 'func_defaults',
+ 'func_dict', 'func_doc', 'func_globals', 'func_name']
+ attributes += [attr for attr in special_attrs \
+ if hasattr(object, attr)]
+ if includeMagic:
+ try: attributes += object._getAttributeNames()
+ except: pass
+ # Special code to allow traits to be caught by autocomplete
+ if hasattr(object,'trait_get'):
+ try:
+ for i in object.trait_get().keys():
+ if i not in attributes:
+ if hasattr(object, i):
+ attributes += i
+ except:
+ pass
+ # Get all attribute names.
+ str_type = str(type(object))
+ if str_type == "<type 'array'>":
+ attributes += dir(object)
+ else:
+ attrdict = getAllAttributeNames(object)
+ # Store the object's dir.
+ object_dir = dir(object)
+ for (obj_type_name, technique, count), attrlist in attrdict.items():
+ # This complexity is necessary to avoid accessing all the
+ # attributes of the object. This is very handy for objects
+ # whose attributes are lazily evaluated.
+ if type(object).__name__ == obj_type_name and technique == 'dir':
+ attributes += attrlist
+ else:
+ attributes += [attr for attr in attrlist \
+ if attr not in object_dir and hasattr(object, attr)]
+
+ # Remove duplicates from the attribute list.
+ for item in attributes:
+ dict[item] = None
+ attributes = dict.keys()
+ # new-style swig wrappings can result in non-string attributes
+ # e.g. ITK http://www.itk.org/
+ attributes = [attribute for attribute in attributes \
+ if type(attribute) == str]
+ attributes.sort(lambda x, y: cmp(x.upper(), y.upper()))
+ if not includeSingle:
+ attributes = filter(lambda item: item[0]!='_' \
+ or item[1:2]=='_', attributes)
+ if not includeDouble:
+ attributes = filter(lambda item: item[:2]!='__', attributes)
+ return attributes
+
+def hasattrAlwaysReturnsTrue(object):
+ return hasattr(object, 'bogu5_123_aTTri8ute')
+
+def getAllAttributeNames(object):
+ """Return dict of all attributes, including inherited, for an object.
+
+ Recursively walk through a class and all base classes.
+ """
+ attrdict = {} # (object, technique, count): [list of attributes]
+ # !!!
+ # Do Not use hasattr() as a test anywhere in this function,
+ # because it is unreliable with remote objects: xmlrpc, soap, etc.
+ # They always return true for hasattr().
+ # !!!
+ try:
+ # This could(?) fail if the type is poorly defined without
+ # even a name.
+ key = type(object).__name__
+ except:
+ key = 'anonymous'
+ # Wake up sleepy objects - a hack for ZODB objects in "ghost" state.
+ wakeupcall = dir(object)
+ del wakeupcall
+ # Get attributes available through the normal convention.
+ attributes = dir(object)
+ attrdict[(key, 'dir', len(attributes))] = attributes
+ # Get attributes from the object's dictionary, if it has one.
+ try:
+ attributes = object.__dict__.keys()
+ attributes.sort()
+ except: # Must catch all because object might have __getattr__.
+ pass
+ else:
+ attrdict[(key, '__dict__', len(attributes))] = attributes
+ # For a class instance, get the attributes for the class.
+ try:
+ klass = object.__class__
+ except: # Must catch all because object might have __getattr__.
+ pass
+ else:
+ if klass is object:
+ # Break a circular reference. This happens with extension
+ # classes.
+ pass
+ else:
+ attrdict.update(getAllAttributeNames(klass))
+ # Also get attributes from any and all parent classes.
+ try:
+ bases = object.__bases__
+ except: # Must catch all because object might have __getattr__.
+ pass
+ else:
+ if isinstance(bases, types.TupleType):
+ for base in bases:
+ if type(base) is types.TypeType:
+ # Break a circular reference. Happens in Python 2.2.
+ pass
+ else:
+ attrdict.update(getAllAttributeNames(base))
+ return attrdict
+
+def getCallTip(command='', locals=None):
+ """For a command, return a tuple of object name, argspec, tip text.
+
+ The call tip information will be based on the locals namespace."""
+ calltip = ('', '', '') # object name, argspec, tip text.
+ # Get the proper chunk of code from the command.
+ root = getRoot(command, terminator='(')
+ try:
+ if locals is not None:
+ object = eval(root, locals)
+ else:
+ object = eval(root)
+ except:
+ return calltip
+ name = ''
+ object, dropSelf = getBaseObject(object)
+ try:
+ name = object.__name__
+ except AttributeError:
+ pass
+ tip1 = ''
+ argspec = ''
+ if inspect.isbuiltin(object):
+ # Builtin functions don't have an argspec that we can get.
+ pass
+ elif inspect.isfunction(object):
+ # tip1 is a string like: "getCallTip(command='', locals=None)"
+ argspec = apply(inspect.formatargspec, inspect.getargspec(object))
+ if dropSelf:
+ # The first parameter to a method is a reference to an
+ # instance, usually coded as "self", and is usually passed
+ # automatically by Python; therefore we want to drop it.
+ temp = argspec.split(',')
+ if len(temp) == 1: # No other arguments.
+ argspec = '()'
+ elif temp[0][:2] == '(*': # first param is like *args, not self
+ pass
+ else: # Drop the first argument.
+ argspec = '(' + ','.join(temp[1:]).lstrip()
+ tip1 = name + argspec
+ doc = ''
+ if callable(object):
+ try:
+ doc = inspect.getdoc(object)
+ except:
+ pass
+ if doc:
+ # tip2 is the first separated line of the docstring, like:
+ # "Return call tip text for a command."
+ # tip3 is the rest of the docstring, like:
+ # "The call tip information will be based on ... <snip>
+ firstline = doc.split('\n')[0].lstrip()
+ if tip1 == firstline or firstline[:len(name)+1] == name+'(':
+ tip1 = ''
+ else:
+ tip1 += '\n\n'
+ docpieces = doc.split('\n\n')
+ tip2 = docpieces[0]
+ tip3 = '\n\n'.join(docpieces[1:])
+ tip = '%s%s\n\n%s' % (tip1, tip2, tip3)
+ else:
+ tip = tip1
+ calltip = (name, argspec[1:-1], tip.strip())
+ return calltip
+
+def getRoot(command, terminator=None):
+ """Return the rightmost root portion of an arbitrary Python command.
+
+ Return only the root portion that can be eval()'d without side
+ effects. The command would normally terminate with a '(' or
+ '.'. The terminator and anything after the terminator will be
+ dropped."""
+ command = command.split('\n')[-1]
+ if command.startswith(sys.ps2):
+ command = command[len(sys.ps2):]
+ command = command.lstrip()
+ command = rtrimTerminus(command, terminator)
+ tokens = getTokens(command)
+ if not tokens:
+ return ''
+ if tokens[-1][0] is tokenize.ENDMARKER:
+ # Remove the end marker.
+ del tokens[-1]
+ if not tokens:
+ return ''
+ if terminator == '.' and \
+ (tokens[-1][1] <> '.' or tokens[-1][0] is not tokenize.OP):
+ # Trap decimals in numbers, versus the dot operator.
+ return ''
+ else:
+ # Strip off the terminator.
+ if terminator and command.endswith(terminator):
+ size = 0 - len(terminator)
+ command = command[:size]
+ command = command.rstrip()
+ tokens = getTokens(command)
+ tokens.reverse()
+ line = ''
+ start = None
+ prefix = ''
+ laststring = '.'
+ emptyTypes = ('[]', '()', '{}')
+ for token in tokens:
+ tokentype = token[0]
+ tokenstring = token[1]
+ line = token[4]
+ if tokentype is tokenize.ENDMARKER:
+ continue
+ if tokentype in (tokenize.NAME, tokenize.STRING, tokenize.NUMBER) \
+ and laststring != '.':
+ # We've reached something that's not part of the root.
+ if prefix and line[token[3][1]] != ' ':
+ # If it doesn't have a space after it, remove the prefix.
+ prefix = ''
+ break
+ if tokentype in (tokenize.NAME, tokenize.STRING, tokenize.NUMBER) \
+ or (tokentype is tokenize.OP and tokenstring == '.'):
+ if prefix:
+ # The prefix isn't valid because it comes after a dot.
+ prefix = ''
+ break
+ else:
+ # start represents the last known good point in the line.
+ start = token[2][1]
+ elif len(tokenstring) == 1 and tokenstring in ('[({])}'):
+ # Remember, we're working backwords.
+ # So prefix += tokenstring would be wrong.
+ if prefix in emptyTypes and tokenstring in ('[({'):
+ # We've already got an empty type identified so now we
+ # are in a nested situation and we can break out with
+ # what we've got.
+ break
+ else:
+ prefix = tokenstring + prefix
+ else:
+ # We've reached something that's not part of the root.
+ break
+ laststring = tokenstring
+ if start is None:
+ start = len(line)
+ root = line[start:]
+ if prefix in emptyTypes:
+ # Empty types are safe to be eval()'d and introspected.
+ root = prefix + root
+ return root
+
+def getTokens(command):
+ """Return list of token tuples for command."""
+
+ # In case the command is unicode try encoding it
+ if type(command) == unicode:
+ try:
+ command = command.encode(wx.GetDefaultPyEncoding())
+ except UnicodeEncodeError:
+ pass # otherwise leave it alone
+
+ f = cStringIO.StringIO(command)
+ # tokens is a list of token tuples, each looking like:
+ # (type, string, (srow, scol), (erow, ecol), line)
+ tokens = []
+ # Can't use list comprehension:
+ # tokens = [token for token in tokenize.generate_tokens(f.readline)]
+ # because of need to append as much as possible before TokenError.
+ try:
+## This code wasn't backward compatible with Python 2.1.3.
+##
+## for token in tokenize.generate_tokens(f.readline):
+## tokens.append(token)
+
+ # This works with Python 2.1.3 (with nested_scopes).
+ def eater(*args):
+ tokens.append(args)
+ tokenize.tokenize_loop(f.readline, eater)
+ except tokenize.TokenError:
+ # This is due to a premature EOF, which we expect since we are
+ # feeding in fragments of Python code.
+ pass
+ return tokens
+
+def rtrimTerminus(command, terminator=None):
+ """Return command minus anything that follows the final terminator."""
+ if terminator:
+ pieces = command.split(terminator)
+ if len(pieces) > 1:
+ command = terminator.join(pieces[:-1]) + terminator
+ return command
+
+def getBaseObject(object):
+ """Return base object and dropSelf indicator for an object."""
+ if inspect.isbuiltin(object):
+ # Builtin functions don't have an argspec that we can get.
+ dropSelf = 0
+ elif inspect.ismethod(object):
+ # Get the function from the object otherwise
+ # inspect.getargspec() complains that the object isn't a
+ # Python function.
+ try:
+ if object.im_self is None:
+ # This is an unbound method so we do not drop self
+ # from the argspec, since an instance must be passed
+ # as the first arg.
+ dropSelf = 0
+ else:
+ dropSelf = 1
+ object = object.im_func
+ except AttributeError:
+ dropSelf = 0
+ elif inspect.isclass(object):
+ # Get the __init__ method function for the class.
+ constructor = getConstructor(object)
+ if constructor is not None:
+ object = constructor
+ dropSelf = 1
+ else:
+ dropSelf = 0
+ elif callable(object):
+ # Get the __call__ method instead.
+ try:
+ object = object.__call__.im_func
+ dropSelf = 1
+ except AttributeError:
+ dropSelf = 0
+ else:
+ dropSelf = 0
+ return object, dropSelf
+
+def getConstructor(object):
+ """Return constructor for class object, or None if there isn't one."""
+ try:
+ return object.__init__.im_func
+ except AttributeError:
+ for base in object.__bases__:
+ constructor = getConstructor(base)
+ if constructor is not None:
+ return constructor
+ return None
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/magic.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/magic.py
new file mode 100644
index 0000000..9625f87
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/magic.py
@@ -0,0 +1,92 @@
+"""magic.py is a utility that allows a simple line from the interpreter
+be translated from a more bash-like form to a python form.
+For instance, 'plot a' is transformed to 'plot(a)'
+Special exceptions are made for predefined ls,cd, and pwd functions"""
+
+__author__ = "David N. Mashburn <david.n.mashburn@gmail.com>"
+# created 07/01/2009
+
+import keyword
+
+from parse import testForContinuations
+
+aliasDict = {}
+
+#DNM
+# TODO : Still Refining this... seems to be ok for now... still finding gotchas, though!
+# TODO : Multi-line strings seem to be correctly broken into commands by PyCrust(PySlices)
+# TODO : Is there a better version of ls, cd, pwd, etc that could be used?
+def magicSingle(command):
+ if command=='': # Pass if command is blank
+ return command
+
+ first_space=command.find(' ')
+
+ if command[0]==' ': # Pass if command begins with a space
+ pass
+ elif command[0]=='?': # Do help if starts with ?
+ command='help('+command[1:]+')'
+ elif command[0]=='!': # Use os.system if starts with !
+ command='sx("'+command[1:]+'")'
+ elif command in ('ls','pwd'): # automatically use ls and pwd with no arguments
+ command=command+'()'
+ elif command[:3] in ('ls ','cd '): # when using the 'ls ' or 'cd ' constructs, fill in both parentheses and quotes
+ command=command[:2]+'("'+command[3:]+'")'
+ elif command[:6] == 'alias ':
+ c = command[6:].lstrip().split(' ')
+ if len(c)<2:
+ #print 'Not enough arguments for alias!'
+ command = ''
+ else:
+ n,v = c[0],' '.join(c[1:])
+ aliasDict[n]=v
+ command = ''
+ elif command.split(' ')[0] in aliasDict.keys():
+ c = command.split(' ')
+ if len(c)<2:
+ command = 'sx("'+aliasDict[c[0]]+'")'
+ else:
+ command = 'sx("'+aliasDict[c[0]]+' '+' '.join(c[1:])+'")'
+ elif first_space!=-1: # if there is at least one space, add parentheses at beginning and end
+ cmds=command.split(' ')
+ if len(cmds)>1:
+ wd1=cmds[0]
+ wd2=cmds[1]
+ i=1
+ while wd2=='':
+ i+=1
+ if len(cmds)==i:
+ break
+ wd2=cmds[i]
+ if wd2=='':
+ return command
+ if (wd1[0].isalpha() or wd1[0]=='_') and (wd2[0].isalnum() or (wd2[0] in """."'_""")) and not keyword.iskeyword(wd1) and not keyword.iskeyword(wd2):
+ if wd1.replace('.','').replace('_','').isalnum():
+ command=wd1+'('+command[(first_space+1):]+')' # add parentheses where the first space was and at the end... hooray!
+ return command
+
+def magic(command):
+ continuations = testForContinuations(command)
+
+ if len(continuations)==2: # Error case...
+ return command
+ elif len(continuations)==4:
+ stringContinuationList,indentationBlockList, \
+ lineContinuationList,parentheticalContinuationList = continuations
+
+ commandList=[]
+ firstLine = True
+ for i in command.split('\n'):
+ if firstLine:
+ commandList.append(magicSingle(i))
+ elif stringContinuationList.pop(0)==False and \
+ indentationBlockList.pop(0)==False and \
+ lineContinuationList.pop(0)==False and \
+ parentheticalContinuationList.pop(0)==False:
+ commandList.append(magicSingle(i)) # unless this is in a larger expression, use magic
+ else:
+ commandList.append(i)
+
+ firstLine=False
+
+ return '\n'.join(commandList)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/parse.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/parse.py
new file mode 100644
index 0000000..bb6c819
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/parse.py
@@ -0,0 +1,128 @@
+"""parse.py is a utility that allows simple checking for line continuations
+to give the shell information about where text is commented and where it is
+not and also how to appropriately break up a sequence of commands into
+separate multi-line commands...
+"""
+
+__author__ = "David N. Mashburn <david.n.mashburn@gmail.com>"
+# created 12/20/2009
+
+import re
+
+# change this to testForContinuations
+
+def testForContinuations(codeBlock,ignoreErrors=False):
+ """ Test 4 different types of continuations:""" + \
+ """ String Continuations (ie with ''')""" + \
+ """ Indentation Block Continuations (ie "if 1:" )""" + \
+ """ Line Continuations (ie with \\ character )""" + \
+ """ Parenthetical continuations (, [, or {"""
+
+ stringMark = None
+ paraList = []
+ indentNumber=[0]
+
+ stringMarks = ['"""',"'''",'"',"'"]
+ openMarks = ['(','[','{']
+ closeMarks = [')',']','}']
+ paraMarkDict = { '(':')', '[':']', '{':'}' }
+
+ stringContinuationList=[]
+ lineContinuationList=[] # For \ continuations ... False because cannot start as line Continuation...
+ indentationBlockList=[]
+ parentheticalContinuationList=[]
+ newIndent=False
+ lspContinuation=False
+ for i,l in enumerate(codeBlock.split('\n')):
+ currentIndentation = len(l)-len(l.lstrip())
+
+ if i>0:
+ lspContinuation = lineContinuationList[-1] or \
+ stringContinuationList[-1] or \
+ parentheticalContinuationList[-1]
+ # first, check for non-executing lines (whitespace and/or comments only)
+ if l.lstrip()=='':
+ emptyLine=True
+ elif l.strip()[0]=='#':
+ emptyLine=True
+ else: # otherwise, check the indentation...
+ emptyLine=False
+ if newIndent and currentIndentation>indentNumber[-1]:
+ newIndent=False
+ indentNumber.append(currentIndentation)
+ elif lspContinuation:
+ pass
+ elif not newIndent and currentIndentation in indentNumber:
+ while currentIndentation<indentNumber[-1]:
+ indentNumber.pop() # This is the end of an indentation block
+ elif not ignoreErrors:
+ #print 'Invalid Indentation!!'
+ return ['Invalid Indentation Error',i]
+
+ firstWord = re.match(' *\w*',l).group().lstrip()
+ if firstWord in ['if','else','elif','for','while',
+ 'def','class','try','except','finally']:
+ hasContinuationWord = True
+ else:
+ hasContinuationWord = False
+
+
+ commented=False
+ nonCommentLength=len(l)
+
+ result = re.finditer('"""'+'|'+"'''" + r'''|"|'|\"|\'|\(|\)|\[|\]|\{|\}|#''',l)
+ for r in result:
+ j = r.group()
+
+ if stringMark == None:
+ if j=='#': # If it is a legitimate comment, ignore everything after
+ commented=True
+ # get length up to last non-comment character
+ nonCommentLength = r.start()
+ break
+ elif j in stringMarks:
+ stringMark=j
+ else:
+ if paraList != [] and j in closeMarks:
+ if paraMarkDict[paraList[-1]]==j:
+ paraList.pop()
+ elif not ignoreErrors:
+ #print 'Invalid Syntax!!'
+ return ['Invalid Syntax Error',i]
+ if j in openMarks:
+ paraList.append(j)
+ elif stringMark==j:
+ stringMark=None
+
+ stringContinuationList.append(stringMark!=None)
+
+ indentationBlockList.append(False)
+ nonCommentString = l[:nonCommentLength].rstrip()
+ if nonCommentString!='' and stringContinuationList[-1]==False:
+ if nonCommentString[-1]==':':
+ indentationBlockList[-1]=True
+ newIndent=True
+
+ lineContinuationList.append(False)
+ if len(l)>0 and not commented:
+ if l[-1]=='\\':
+ lineContinuationList[-1]=True
+
+ parentheticalContinuationList.append( paraList != [] )
+
+ # Now stringContinuationList (et al) is line by line key for magic
+ # telling it whether or not each next line is part of a string continuation
+
+ if (stringContinuationList[-1] or indentationBlockList[-1] or \
+ lineContinuationList[-1] or parentheticalContinuationList[-1]) \
+ and not ignoreErrors:
+ #print 'Incomplete Syntax!!'
+ return ['Incomplete Syntax Error',i]
+
+ if newIndent and not ignoreErrors:
+ #print 'Incomplete Indentation!'
+ return ['Incomplete Indentation Error',i]
+
+ # Note that if one of these errors above gets thrown, the best solution is to pass the resulting block
+ # to the interpreter as exec instead of interp
+ return stringContinuationList,indentationBlockList,lineContinuationList,parentheticalContinuationList
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/path.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/path.py
new file mode 100644
index 0000000..ccc8177
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/path.py
@@ -0,0 +1,36 @@
+"""path.py is a utility containing some very simple path utilities for Py to use"""
+
+__author__ = "David N. Mashburn <david.n.mashburn@gmail.com>"
+# 07/01/2009
+
+import os
+import glob
+import commands
+
+def pwd():
+ print os.getcwd()
+
+def cd(path,usePrint=True):
+ os.chdir(os.path.expandvars(os.path.expanduser(path)))
+ if usePrint:
+ pwd()
+
+def ls(str='*',fullpath=False):
+ g=glob.glob(os.path.expandvars(os.path.expanduser(str)))
+ if fullpath:
+ for i in g:
+ print i
+ else:
+ for i in g:
+ print os.path.split(i)[1]
+
+# This prints the results of running a command in the GUI shell but be warned!
+# This is a blocking call, and if you open any kind of interactive
+# command-line program like python or bash, the shell will permanantly
+# freeze!
+# If you want this kind of behavior to be available, please use ipython
+# This is NOT a feature or goal of the Py project!
+def sx(str=''):
+ print commands.getoutput(str)
+
+#cd('~',usePrint=False)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/pseudo.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/pseudo.py
new file mode 100644
index 0000000..482be6c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/pseudo.py
@@ -0,0 +1,101 @@
+"""Provides a variety of classes to create pseudo keywords and pseudo files."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+
+class PseudoKeyword:
+ """A callable class that calls a method passed as a parameter.
+
+ Good for creating a pseudo keyword in the python runtime
+ environment. The keyword is really an object that has a repr()
+ that calls itself which calls the method that was passed in the
+ init of the object. All this just to avoid having to type in the
+ closing parens on a method. So, for example:
+
+ >>> quit = PseudoKeyword(SomeObject.someMethod)
+ >>> quit
+
+ SomeObject.someMethod gets executed as if it had been called
+ directly and the user didn't have to type the parens, like
+ 'quit()'. This technique is most applicable for pseudo keywords
+ like quit, exit and help.
+
+ If SomeObject.someMethod can take parameters, they can still be
+ passed by using the keyword in the traditional way with parens."""
+
+ def __init__(self, method):
+ """Create a callable object that executes method when called."""
+
+ if callable(method):
+ self.method = method
+ else:
+ raise ValueError, 'method must be callable'
+
+ def __call__(self, *args, **kwds):
+ self.method(*args, **kwds)
+
+ def __repr__(self):
+ self()
+ return ''
+
+
+class PseudoFile:
+
+ def __init__(self):
+ """Create a file-like object."""
+ pass
+
+ def readline(self):
+ pass
+
+ def write(self, s):
+ pass
+
+ def writelines(self, l):
+ map(self.write, l)
+
+ def flush(self):
+ pass
+
+ def isatty(self):
+ pass
+
+
+class PseudoFileIn(PseudoFile):
+
+ def __init__(self, readline, readlines=None):
+ if callable(readline):
+ self.readline = readline
+ else:
+ raise ValueError, 'readline must be callable'
+ if callable(readlines):
+ self.readlines = readlines
+
+ def isatty(self):
+ return 1
+
+
+class PseudoFileOut(PseudoFile):
+
+ def __init__(self, write):
+ if callable(write):
+ self.write = write
+ else:
+ raise ValueError, 'write must be callable'
+
+ def isatty(self):
+ return 1
+
+
+class PseudoFileErr(PseudoFile):
+
+ def __init__(self, write):
+ if callable(write):
+ self.write = write
+ else:
+ raise ValueError, 'write must be callable'
+
+ def isatty(self):
+ return 1
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/shell.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/shell.py
new file mode 100644
index 0000000..1009f6a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/shell.py
@@ -0,0 +1,1575 @@
+"""Shell is an interactive text control in which a user types in
+commands to be sent to the interpreter. This particular shell is
+based on wxPython's wxStyledTextCtrl.
+
+Sponsored by Orbtech - Your source for Python programming expertise."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+from wx import stc
+
+import keyword
+import os
+import sys
+import time
+
+from buffer import Buffer
+import dispatcher
+import editwindow
+import frame
+from pseudo import PseudoFileIn
+from pseudo import PseudoFileOut
+from pseudo import PseudoFileErr
+from version import VERSION
+from magic import magic
+from path import ls,cd,pwd,sx
+
+sys.ps3 = '<-- ' # Input prompt.
+USE_MAGIC=True
+# Force updates from long-running commands after this many seconds
+PRINT_UPDATE_MAX_TIME=2
+
+NAVKEYS = (wx.WXK_END, wx.WXK_LEFT, wx.WXK_RIGHT,
+ wx.WXK_UP, wx.WXK_DOWN, wx.WXK_PRIOR, wx.WXK_NEXT)
+
+
+class ShellFrame(frame.Frame, frame.ShellFrameMixin):
+ """Frame containing the shell component."""
+
+ name = 'Shell Frame'
+ revision = __revision__
+
+ def __init__(self, parent=None, id=-1, title='PyShell',
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_FRAME_STYLE, locals=None,
+ InterpClass=None,
+ config=None, dataDir=None,
+ *args, **kwds):
+ """Create ShellFrame instance."""
+ frame.Frame.__init__(self, parent, id, title, pos, size, style)
+ frame.ShellFrameMixin.__init__(self, config, dataDir)
+
+ if size == wx.DefaultSize:
+ self.SetSize((750, 525))
+
+ intro = 'PyShell %s - The Flakiest Python Shell' % VERSION
+ self.SetStatusText(intro.replace('\n', ', '))
+ self.shell = Shell(parent=self, id=-1, introText=intro,
+ locals=locals, InterpClass=InterpClass,
+ startupScript=self.startupScript,
+ execStartupScript=self.execStartupScript,
+ *args, **kwds)
+
+ # Override the shell so that status messages go to the status bar.
+ self.shell.setStatusText = self.SetStatusText
+
+ self.shell.SetFocus()
+ self.LoadSettings()
+
+
+ def OnClose(self, event):
+ """Event handler for closing."""
+ # This isn't working the way I want, but I'll leave it for now.
+ if self.shell.waiting:
+ if event.CanVeto():
+ event.Veto(True)
+ else:
+ self.SaveSettings()
+ self.shell.destroy()
+ self.Destroy()
+
+ def OnAbout(self, event):
+ """Display an About window."""
+ title = 'About PyShell'
+ text = 'PyShell %s\n\n' % VERSION + \
+ 'Yet another Python shell, only flakier.\n\n' + \
+ 'Half-baked by Patrick K. O\'Brien,\n' + \
+ 'the other half is still in the oven.\n\n' + \
+ 'Shell Revision: %s\n' % self.shell.revision + \
+ 'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
+ 'Platform: %s\n' % sys.platform + \
+ 'Python Version: %s\n' % sys.version.split()[0] + \
+ 'wxPython Version: %s\n' % wx.VERSION_STRING + \
+ ('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:]))
+ dialog = wx.MessageDialog(self, text, title,
+ wx.OK | wx.ICON_INFORMATION)
+ dialog.ShowModal()
+ dialog.Destroy()
+
+
+ def OnHelp(self, event):
+ """Show a help dialog."""
+ frame.ShellFrameMixin.OnHelp(self, event)
+
+
+ def LoadSettings(self):
+ if self.config is not None:
+ frame.ShellFrameMixin.LoadSettings(self)
+ frame.Frame.LoadSettings(self, self.config)
+ self.shell.LoadSettings(self.config)
+
+ def SaveSettings(self, force=False):
+ if self.config is not None:
+ frame.ShellFrameMixin.SaveSettings(self)
+ if self.autoSaveSettings or force:
+ frame.Frame.SaveSettings(self, self.config)
+ self.shell.SaveSettings(self.config)
+
+ def DoSaveSettings(self):
+ if self.config is not None:
+ self.SaveSettings(force=True)
+ self.config.Flush()
+
+
+
+
+HELP_TEXT = """\
+* Key bindings:
+Home Go to the beginning of the command or line.
+Shift+Home Select to the beginning of the command or line.
+Shift+End Select to the end of the line.
+End Go to the end of the line.
+Ctrl+C Copy selected text, removing prompts.
+Ctrl+Shift+C Copy selected text, retaining prompts.
+Alt+C Copy to the clipboard, including prefixed prompts.
+Ctrl+X Cut selected text.
+Ctrl+V Paste from clipboard.
+Ctrl+Shift+V Paste and run multiple commands from clipboard.
+Ctrl+Up Arrow Retrieve Previous History item.
+Alt+P Retrieve Previous History item.
+Ctrl+Down Arrow Retrieve Next History item.
+Alt+N Retrieve Next History item.
+Shift+Up Arrow Insert Previous History item.
+Shift+Down Arrow Insert Next History item.
+F8 Command-completion of History item.
+ (Type a few characters of a previous command and press F8.)
+Ctrl+Enter Insert new line into multiline command.
+Ctrl+] Increase font size.
+Ctrl+[ Decrease font size.
+Ctrl+= Default font size.
+Ctrl-Space Show Auto Completion.
+Ctrl-Alt-Space Show Call Tip.
+Shift+Enter Complete Text from History.
+Ctrl+F Search
+F3 Search next
+Ctrl+H "hide" lines containing selection / "unhide"
+F12 on/off "free-edit" mode
+"""
+
+class ShellFacade:
+ """Simplified interface to all shell-related functionality.
+
+ This is a semi-transparent facade, in that all attributes of other
+ are accessible, even though only some are visible to the user."""
+
+ name = 'Shell Interface'
+ revision = __revision__
+
+ def __init__(self, other):
+ """Create a ShellFacade instance."""
+ d = self.__dict__
+ d['other'] = other
+ d['helpText'] = HELP_TEXT
+ d['this'] = other.this
+
+ def help(self):
+ """Display some useful information about how to use the shell."""
+ self.write(self.helpText)
+
+ def __getattr__(self, name):
+ if hasattr(self.other, name):
+ return getattr(self.other, name)
+ else:
+ raise AttributeError, name
+
+ def __setattr__(self, name, value):
+ if self.__dict__.has_key(name):
+ self.__dict__[name] = value
+ elif hasattr(self.other, name):
+ setattr(self.other, name, value)
+ else:
+ raise AttributeError, name
+
+ def _getAttributeNames(self):
+ """Return list of magic attributes to extend introspection."""
+ list = [
+ 'about',
+ 'ask',
+ 'autoCallTip',
+ 'autoComplete',
+ 'autoCompleteAutoHide',
+ 'autoCompleteCaseInsensitive',
+ 'autoCompleteIncludeDouble',
+ 'autoCompleteIncludeMagic',
+ 'autoCompleteIncludeSingle',
+ 'callTipInsert',
+ 'clear',
+ 'pause',
+ 'prompt',
+ 'quit',
+ 'redirectStderr',
+ 'redirectStdin',
+ 'redirectStdout',
+ 'run',
+ 'runfile',
+ 'wrap',
+ 'zoom',
+ ]
+ list.sort()
+ return list
+
+
+#DNM
+DISPLAY_TEXT="""
+Author: %r
+Py Version: %s
+Py Shell Revision: %s
+Py Interpreter Revision: %s
+Python Version: %s
+wxPython Version: %s
+wxPython PlatformInfo: %s
+Platform: %s"""
+
+class Shell(editwindow.EditWindow):
+ """Shell based on StyledTextCtrl."""
+
+ name = 'Shell'
+ revision = __revision__
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
+ introText='', locals=None, InterpClass=None,
+ startupScript=None, execStartupScript=True,
+ *args, **kwds):
+ """Create Shell instance."""
+ editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
+ self.wrap()
+ if locals is None:
+ import __main__
+ locals = __main__.__dict__
+
+ # Grab these so they can be restored by self.redirect* methods.
+ self.stdin = sys.stdin
+ self.stdout = sys.stdout
+ self.stderr = sys.stderr
+
+ # Import a default interpreter class if one isn't provided.
+ if InterpClass == None:
+ from interpreter import Interpreter
+ else:
+ Interpreter = InterpClass
+
+ # Create a replacement for stdin.
+ self.reader = PseudoFileIn(self.readline, self.readlines)
+ self.reader.input = ''
+ self.reader.isreading = False
+
+ # Set up the interpreter.
+ self.interp = Interpreter(locals=locals,
+ rawin=self.raw_input,
+ stdin=self.reader,
+ stdout=PseudoFileOut(self.writeOut),
+ stderr=PseudoFileErr(self.writeErr),
+ *args, **kwds)
+
+ # Set up the buffer.
+ self.buffer = Buffer()
+
+ # Find out for which keycodes the interpreter will autocomplete.
+ self.autoCompleteKeys = self.interp.getAutoCompleteKeys()
+
+ # Keep track of the last non-continuation prompt positions.
+ self.promptPosStart = 0
+ self.promptPosEnd = 0
+
+ # Keep track of multi-line commands.
+ self.more = False
+
+ # For use with forced updates during long-running scripts
+ self.lastUpdate=None
+
+ # Create the command history. Commands are added into the
+ # front of the list (ie. at index 0) as they are entered.
+ # self.historyIndex is the current position in the history; it
+ # gets incremented as you retrieve the previous command,
+ # decremented as you retrieve the next, and reset when you hit
+ # Enter. self.historyIndex == -1 means you're on the current
+ # command, not in the history.
+ self.history = []
+ self.historyIndex = -1
+
+ #seb add mode for "free edit"
+ self.noteMode = 0
+ self.MarkerDefine(0,stc.STC_MARK_ROUNDRECT) # marker for hidden
+ self.searchTxt = ""
+
+ # Assign handlers for keyboard events.
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+
+ # Assign handler for the context menu
+ self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI)
+
+ # Assign handlers for edit events
+ self.Bind(wx.EVT_MENU, lambda evt: self.Cut(), id=wx.ID_CUT)
+ self.Bind(wx.EVT_MENU, lambda evt: self.Copy(), id=wx.ID_COPY)
+ self.Bind(wx.EVT_MENU, lambda evt: self.CopyWithPrompts(), id=frame.ID_COPY_PLUS)
+ self.Bind(wx.EVT_MENU, lambda evt: self.Paste(), id=wx.ID_PASTE)
+ self.Bind(wx.EVT_MENU, lambda evt: self.PasteAndRun(), id=frame.ID_PASTE_PLUS)
+ self.Bind(wx.EVT_MENU, lambda evt: self.SelectAll(), id=wx.ID_SELECTALL)
+ self.Bind(wx.EVT_MENU, lambda evt: self.Clear(), id=wx.ID_CLEAR)
+ self.Bind(wx.EVT_MENU, lambda evt: self.Undo(), id=wx.ID_UNDO)
+ self.Bind(wx.EVT_MENU, lambda evt: self.Redo(), id=wx.ID_REDO)
+
+
+ # Assign handler for idle time.
+ self.waiting = False
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+ # Display the introductory banner information.
+ self.showIntro(introText)
+
+ # Assign some pseudo keywords to the interpreter's namespace.
+ self.setBuiltinKeywords()
+
+ # Add 'shell' to the interpreter's local namespace.
+ self.setLocalShell()
+
+ ## NOTE: See note at bottom of this file...
+ ## #seb: File drag and drop
+ ## self.SetDropTarget( FileDropTarget(self) )
+
+ # Do this last so the user has complete control over their
+ # environment. They can override anything they want.
+ if execStartupScript:
+ if startupScript is None:
+ startupScript = os.environ.get('PYTHONSTARTUP')
+ self.execStartupScript(startupScript)
+ else:
+ self.prompt()
+
+ wx.CallAfter(self.ScrollToLine, 0)
+
+
+ def clearHistory(self):
+ self.history = []
+ self.historyIndex = -1
+ dispatcher.send(signal="Shell.clearHistory")
+
+
+ def destroy(self):
+ del self.interp
+
+ def setFocus(self):
+ """Set focus to the shell."""
+ self.SetFocus()
+
+ def OnIdle(self, event):
+ """Free the CPU to do other things."""
+ if self.waiting:
+ time.sleep(0.05)
+ event.Skip()
+
+ def showIntro(self, text=''):
+ """Display introductory text in the shell."""
+ if text:
+ self.write(text)
+ try:
+ if self.interp.introText:
+ if text and not text.endswith(os.linesep):
+ self.write(os.linesep)
+ self.write(self.interp.introText)
+ except AttributeError:
+ pass
+
+ def setBuiltinKeywords(self):
+ """Create pseudo keywords as part of builtins.
+
+ This sets "close", "exit" and "quit" to a helpful string.
+ """
+ import __builtin__
+ __builtin__.close = __builtin__.exit = __builtin__.quit = \
+ 'Click on the close button to leave the application.'
+ __builtin__.cd = cd
+ __builtin__.ls = ls
+ __builtin__.pwd = pwd
+ __builtin__.sx = sx
+
+
+ def quit(self):
+ """Quit the application."""
+ # XXX Good enough for now but later we want to send a close event.
+ # In the close event handler we can make sure they want to
+ # quit. Other applications, like PythonCard, may choose to
+ # hide rather than quit so we should just post the event and
+ # let the surrounding app decide what it wants to do.
+ self.write('Click on the close button to leave the application.')
+
+
+ def setLocalShell(self):
+ """Add 'shell' to locals as reference to ShellFacade instance."""
+ self.interp.locals['shell'] = ShellFacade(other=self)
+
+
+ def execStartupScript(self, startupScript):
+ """Execute the user's PYTHONSTARTUP script if they have one."""
+ if startupScript and os.path.isfile(startupScript):
+ text = 'Startup script executed: ' + startupScript
+ self.push('print %r; execfile(%r)' % (text, startupScript))
+ self.interp.startupScript = startupScript
+ else:
+ self.push('')
+
+
+ def about(self):
+ """Display information about Py."""
+ #DNM
+ text = DISPLAY_TEXT % \
+ (__author__, VERSION, self.revision, self.interp.revision,
+ sys.version.split()[0], wx.VERSION_STRING, str(wx.PlatformInfo),
+ sys.platform)
+ self.write(text.strip())
+
+
+ def OnChar(self, event):
+ """Keypress event handler.
+
+ Only receives an event if OnKeyDown calls event.Skip() for the
+ corresponding event."""
+
+ if self.noteMode:
+ event.Skip()
+ return
+
+ # Prevent modification of previously submitted
+ # commands/responses.
+ if not self.CanEdit():
+ return
+ key = event.GetKeyCode()
+ currpos = self.GetCurrentPos()
+ stoppos = self.promptPosEnd
+ # Return (Enter) needs to be ignored in this handler.
+ if key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
+ pass
+ elif key in self.autoCompleteKeys:
+ # Usually the dot (period) key activates auto completion.
+ # Get the command between the prompt and the cursor. Add
+ # the autocomplete character to the end of the command.
+ if self.AutoCompActive():
+ self.AutoCompCancel()
+ command = self.GetTextRange(stoppos, currpos) + chr(key)
+ self.write(chr(key))
+ if self.autoComplete:
+ self.autoCompleteShow(command)
+ elif key == ord('('):
+ # The left paren activates a call tip and cancels an
+ # active auto completion.
+ if self.AutoCompActive():
+ self.AutoCompCancel()
+ # Get the command between the prompt and the cursor. Add
+ # the '(' to the end of the command.
+ self.ReplaceSelection('')
+ command = self.GetTextRange(stoppos, currpos) + '('
+ self.write('(')
+ self.autoCallTipShow(command, self.GetCurrentPos() == self.GetTextLength())
+ else:
+ # Allow the normal event handling to take place.
+ event.Skip()
+
+
+ def OnKeyDown(self, event):
+ """Key down event handler."""
+
+ key = event.GetKeyCode()
+ # If the auto-complete window is up let it do its thing.
+ if self.AutoCompActive():
+ event.Skip()
+ return
+
+ # Prevent modification of previously submitted
+ # commands/responses.
+ controlDown = event.ControlDown()
+ rawControlDown = event.RawControlDown()
+ altDown = event.AltDown()
+ shiftDown = event.ShiftDown()
+ currpos = self.GetCurrentPos()
+ endpos = self.GetTextLength()
+ selecting = self.GetSelectionStart() != self.GetSelectionEnd()
+
+ if (rawControlDown or controlDown) and shiftDown and key in (ord('F'), ord('f')):
+ li = self.GetCurrentLine()
+ m = self.MarkerGet(li)
+ if m & 1<<0:
+ startP = self.PositionFromLine(li)
+ self.MarkerDelete(li, 0)
+ maxli = self.GetLineCount()
+ li += 1 # li stayed visible as header-line
+ li0 = li
+ while li<maxli and self.GetLineVisible(li) == 0:
+ li += 1
+ endP = self.GetLineEndPosition(li-1)
+ self.ShowLines(li0, li-1)
+ # select reappearing text to allow "hide again"
+ self.SetSelection( startP, endP )
+ return
+ startP,endP = self.GetSelection()
+ endP-=1
+ startL = self.LineFromPosition(startP)
+ endL = self.LineFromPosition(endP)
+
+ # never hide last prompt
+ if endL == self.LineFromPosition(self.promptPosEnd):
+ endL -= 1
+
+ m = self.MarkerGet(startL)
+ self.MarkerAdd(startL, 0)
+ self.HideLines(startL+1,endL)
+ self.SetCurrentPos( startP ) # to ensure caret stays visible !
+
+ if key == wx.WXK_F12: #seb
+ if self.noteMode:
+ # self.promptPosStart not used anyway - or ?
+ self.promptPosEnd = \
+ self.PositionFromLine( self.GetLineCount()-1 ) + \
+ len(str(sys.ps1))
+ self.GotoLine(self.GetLineCount())
+ self.GotoPos(self.promptPosEnd)
+ self.prompt() #make sure we have a prompt
+ self.SetCaretForeground("black")
+ self.SetCaretWidth(1) #default
+ self.SetCaretPeriod(500) #default
+ else:
+ self.SetCaretForeground("red")
+ self.SetCaretWidth(4)
+ self.SetCaretPeriod(0) #steady
+
+ self.noteMode = not self.noteMode
+ return
+ if self.noteMode:
+ event.Skip()
+ return
+
+ # Return (Enter) is used to submit a command to the
+ # interpreter.
+ if (not (rawControlDown or controlDown) and not shiftDown and not altDown) and \
+ key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
+ if self.CallTipActive():
+ self.CallTipCancel()
+ self.processLine()
+
+ # Complete Text (from already typed words)
+ elif shiftDown and key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
+ self.OnShowCompHistory()
+
+ # Ctrl+Return (Ctrl+Enter) is used to insert a line break.
+ elif (rawControlDown or controlDown) and key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
+ if self.CallTipActive():
+ self.CallTipCancel()
+ if currpos == endpos:
+ self.processLine()
+ else:
+ self.insertLineBreak()
+
+ # Let Ctrl-Alt-* get handled normally.
+ elif (rawControlDown or controlDown) and altDown:
+ event.Skip()
+
+ # Clear the current, unexecuted command.
+ elif key == wx.WXK_ESCAPE:
+ if self.CallTipActive():
+ event.Skip()
+ else:
+ self.clearCommand()
+
+ # Clear the current command
+ elif key == wx.WXK_BACK and (rawControlDown or controlDown) and shiftDown:
+ self.clearCommand()
+
+ # Increase font size.
+ elif (rawControlDown or controlDown) and key in (ord(']'), wx.WXK_NUMPAD_ADD):
+ dispatcher.send(signal='FontIncrease')
+
+ # Decrease font size.
+ elif (rawControlDown or controlDown) and key in (ord('['), wx.WXK_NUMPAD_SUBTRACT):
+ dispatcher.send(signal='FontDecrease')
+
+ # Default font size.
+ elif (rawControlDown or controlDown) and key in (ord('='), wx.WXK_NUMPAD_DIVIDE):
+ dispatcher.send(signal='FontDefault')
+
+ # Cut to the clipboard.
+ elif ((rawControlDown or controlDown) and key in (ord('X'), ord('x'))) \
+ or (shiftDown and key == wx.WXK_DELETE):
+ self.Cut()
+
+ # Copy to the clipboard.
+ elif (rawControlDown or controlDown) and not shiftDown \
+ and key in (ord('C'), ord('c'), wx.WXK_INSERT):
+ self.Copy()
+
+ # Copy to the clipboard, including prompts.
+ elif (rawControlDown or controlDown) and shiftDown \
+ and key in (ord('C'), ord('c'), wx.WXK_INSERT):
+ self.CopyWithPrompts()
+
+ # Copy to the clipboard, including prefixed prompts.
+ elif altDown and not controlDown \
+ and key in (ord('C'), ord('c'), wx.WXK_INSERT):
+ self.CopyWithPromptsPrefixed()
+
+ # Home needs to be aware of the prompt.
+ elif (rawControlDown or controlDown) and key == wx.WXK_HOME:
+ home = self.promptPosEnd
+ if currpos > home:
+ self.SetCurrentPos(home)
+ if not selecting and not shiftDown:
+ self.SetAnchor(home)
+ self.EnsureCaretVisible()
+ else:
+ event.Skip()
+
+ # Home needs to be aware of the prompt.
+ elif key == wx.WXK_HOME:
+ home = self.promptPosEnd
+ if currpos > home:
+ [line_str,line_len] = self.GetCurLine()
+ pos=self.GetCurrentPos()
+ if line_str[:4] in [sys.ps1,sys.ps2,sys.ps3]:
+ self.SetCurrentPos(pos+4-line_len)
+ #self.SetCurrentPos(home)
+ if not selecting and not shiftDown:
+ self.SetAnchor(pos+4-line_len)
+ self.EnsureCaretVisible()
+ else:
+ event.Skip()
+ else:
+ event.Skip()
+
+ #
+ # The following handlers modify text, so we need to see if
+ # there is a selection that includes text prior to the prompt.
+ #
+ # Don't modify a selection with text prior to the prompt.
+ elif selecting and key not in NAVKEYS and not self.CanEdit():
+ pass
+
+ # Paste from the clipboard.
+ elif ((rawControlDown or controlDown) and not shiftDown and key in (ord('V'), ord('v'))) \
+ or (shiftDown and not controlDown and key == wx.WXK_INSERT):
+ self.Paste()
+
+ # manually invoke AutoComplete and Calltips
+ elif (rawControlDown or controlDown) and key == wx.WXK_SPACE:
+ self.OnCallTipAutoCompleteManually(shiftDown)
+
+ # Paste from the clipboard, run commands.
+ elif (rawControlDown or controlDown) and shiftDown and key in (ord('V'), ord('v')):
+ self.PasteAndRun()
+
+ # Replace with the previous command from the history buffer.
+ elif ((rawControlDown or controlDown) and not shiftDown and key == wx.WXK_UP) \
+ or (altDown and key in (ord('P'), ord('p'))):
+ self.OnHistoryReplace(step=+1)
+
+ # Replace with the next command from the history buffer.
+ elif ((rawControlDown or controlDown) and not shiftDown and key == wx.WXK_DOWN) \
+ or (altDown and key in (ord('N'), ord('n'))):
+ self.OnHistoryReplace(step=-1)
+
+ # Insert the previous command from the history buffer.
+ elif ((rawControlDown or controlDown) and shiftDown and key == wx.WXK_UP) and self.CanEdit():
+ self.OnHistoryInsert(step=+1)
+
+ # Insert the next command from the history buffer.
+ elif ((rawControlDown or controlDown) and shiftDown and key == wx.WXK_DOWN) and self.CanEdit():
+ self.OnHistoryInsert(step=-1)
+
+ # Search up the history for the text in front of the cursor.
+ elif key == wx.WXK_F8:
+ self.OnHistorySearch()
+
+ # Don't backspace over the latest non-continuation prompt.
+ elif key == wx.WXK_BACK:
+ if selecting and self.CanEdit():
+ event.Skip()
+ elif currpos > self.promptPosEnd:
+ event.Skip()
+
+ # Only allow these keys after the latest prompt.
+ elif key in (wx.WXK_TAB, wx.WXK_DELETE):
+ if self.CanEdit():
+ event.Skip()
+
+ # Don't toggle between insert mode and overwrite mode.
+ elif key == wx.WXK_INSERT:
+ pass
+
+ # Don't allow line deletion.
+ elif controlDown and key in (ord('L'), ord('l')):
+ # TODO : Allow line deletion eventually...
+ #event.Skip()
+ pass
+
+ # Don't allow line transposition.
+ elif controlDown and key in (ord('T'), ord('t')):
+ # TODO : Allow line transposition eventually...
+ # TODO : Will have to adjust markers accordingly and test if allowed...
+ #event.Skip()
+ pass
+
+ # Basic navigation keys should work anywhere.
+ elif key in NAVKEYS:
+ event.Skip()
+
+ # Protect the readonly portion of the shell.
+ elif not self.CanEdit():
+ pass
+
+ else:
+ event.Skip()
+
+
+ def OnShowCompHistory(self):
+ """Show possible autocompletion Words from already typed words."""
+
+ #copy from history
+ his = self.history[:]
+
+ #put together in one string
+ joined = " ".join (his)
+ import re
+
+ #sort out only "good" words
+ newlist = re.split("[ \.\[\]=}(\)\,0-9\"]", joined)
+
+ #length > 1 (mix out "trash")
+ thlist = []
+ for i in newlist:
+ if len (i) > 1:
+ thlist.append (i)
+
+ #unique (no duplicate words
+ #oneliner from german python forum => unique list
+ unlist = [thlist[i] for i in xrange(len(thlist)) if thlist[i] not in thlist[:i]]
+
+ #sort lowercase
+ unlist.sort(lambda a, b: cmp(a.lower(), b.lower()))
+
+ #this is more convenient, isn't it?
+ self.AutoCompSetIgnoreCase(True)
+
+ #join again together in a string
+ stringlist = " ".join(unlist)
+
+ #pos von 0 noch ausrechnen
+
+ #how big is the offset?
+ cpos = self.GetCurrentPos() - 1
+ while chr (self.GetCharAt (cpos)).isalnum():
+ cpos -= 1
+
+ #the most important part
+ self.AutoCompShow(self.GetCurrentPos() - cpos -1, stringlist)
+
+
+ def clearCommand(self):
+ """Delete the current, unexecuted command."""
+ startpos = self.promptPosEnd
+ endpos = self.GetTextLength()
+ self.SetSelection(startpos, endpos)
+ self.ReplaceSelection('')
+ self.more = False
+
+ def OnHistoryReplace(self, step):
+ """Replace with the previous/next command from the history buffer."""
+ self.clearCommand()
+ self.replaceFromHistory(step)
+
+ def replaceFromHistory(self, step):
+ """Replace selection with command from the history buffer."""
+ ps2 = str(sys.ps2)
+ self.ReplaceSelection('')
+ newindex = self.historyIndex + step
+ if -1 <= newindex <= len(self.history):
+ self.historyIndex = newindex
+ if 0 <= newindex <= len(self.history)-1:
+ command = self.history[self.historyIndex]
+ command = command.replace('\n', os.linesep + ps2)
+ self.ReplaceSelection(command)
+
+ def OnHistoryInsert(self, step):
+ """Insert the previous/next command from the history buffer."""
+ if not self.CanEdit():
+ return
+ startpos = self.GetCurrentPos()
+ self.replaceFromHistory(step)
+ endpos = self.GetCurrentPos()
+ self.SetSelection(endpos, startpos)
+
+ def OnHistorySearch(self):
+ """Search up the history buffer for the text in front of the cursor."""
+ if not self.CanEdit():
+ return
+ startpos = self.GetCurrentPos()
+ # The text up to the cursor is what we search for.
+ numCharsAfterCursor = self.GetTextLength() - startpos
+ searchText = self.getCommand(rstrip=False)
+ if numCharsAfterCursor > 0:
+ searchText = searchText[:-numCharsAfterCursor]
+ if not searchText:
+ return
+ # Search upwards from the current history position and loop
+ # back to the beginning if we don't find anything.
+ if (self.historyIndex <= -1) \
+ or (self.historyIndex >= len(self.history)-2):
+ searchOrder = range(len(self.history))
+ else:
+ searchOrder = range(self.historyIndex+1, len(self.history)) + \
+ range(self.historyIndex)
+ for i in searchOrder:
+ command = self.history[i]
+ if command[:len(searchText)] == searchText:
+ # Replace the current selection with the one we found.
+ self.ReplaceSelection(command[len(searchText):])
+ endpos = self.GetCurrentPos()
+ self.SetSelection(endpos, startpos)
+ # We've now warped into middle of the history.
+ self.historyIndex = i
+ break
+
+ def setStatusText(self, text):
+ """Display status information."""
+
+ # This method will likely be replaced by the enclosing app to
+ # do something more interesting, like write to a status bar.
+ print text
+
+ def insertLineBreak(self):
+ """Insert a new line break."""
+ if self.CanEdit():
+ self.write(os.linesep)
+ self.more = True
+ self.prompt()
+
+ def processLine(self):
+ """Process the line of text at which the user hit Enter."""
+
+ # The user hit ENTER and we need to decide what to do. They
+ # could be sitting on any line in the shell.
+
+ thepos = self.GetCurrentPos()
+ startpos = self.promptPosEnd
+ endpos = self.GetTextLength()
+ ps2 = str(sys.ps2)
+ # If they hit RETURN inside the current command, execute the
+ # command.
+ if self.CanEdit():
+ self.SetCurrentPos(endpos)
+ self.interp.more = False
+ command = self.GetTextRange(startpos, endpos)
+ lines = command.split(os.linesep + ps2)
+ lines = [line.rstrip() for line in lines]
+ command = '\n'.join(lines)
+ if self.reader.isreading:
+ if not command:
+ # Match the behavior of the standard Python shell
+ # when the user hits return without entering a
+ # value.
+ command = '\n'
+ self.reader.input = command
+ self.write(os.linesep)
+ else:
+ self.push(command)
+ wx.FutureCall(1, self.EnsureCaretVisible)
+ # Or replace the current command with the other command.
+ else:
+ # If the line contains a command (even an invalid one).
+ if self.getCommand(rstrip=False):
+ command = self.getMultilineCommand()
+ self.clearCommand()
+ self.write(command)
+ # Otherwise, put the cursor back where we started.
+ else:
+ self.SetCurrentPos(thepos)
+ self.SetAnchor(thepos)
+
+ def getMultilineCommand(self, rstrip=True):
+ """Extract a multi-line command from the editor.
+
+ The command may not necessarily be valid Python syntax."""
+ # XXX Need to extract real prompts here. Need to keep track of
+ # the prompt every time a command is issued.
+ ps1 = str(sys.ps1)
+ ps1size = len(ps1)
+ ps2 = str(sys.ps2)
+ ps2size = len(ps2)
+ # This is a total hack job, but it works.
+ text = self.GetCurLine()[0]
+ line = self.GetCurrentLine()
+ while text[:ps2size] == ps2 and line > 0:
+ line -= 1
+ self.GotoLine(line)
+ text = self.GetCurLine()[0]
+ if text[:ps1size] == ps1:
+ line = self.GetCurrentLine()
+ self.GotoLine(line)
+ startpos = self.GetCurrentPos() + ps1size
+ line += 1
+ self.GotoLine(line)
+ while self.GetCurLine()[0][:ps2size] == ps2:
+ line += 1
+ self.GotoLine(line)
+ stoppos = self.GetCurrentPos()
+ command = self.GetTextRange(startpos, stoppos)
+ command = command.replace(os.linesep + ps2, '\n')
+ command = command.rstrip()
+ command = command.replace('\n', os.linesep + ps2)
+ else:
+ command = ''
+ if rstrip:
+ command = command.rstrip()
+ return command
+
+ def getCommand(self, text=None, rstrip=True):
+ """Extract a command from text which may include a shell prompt.
+
+ The command may not necessarily be valid Python syntax."""
+ if not text:
+ text = self.GetCurLine()[0]
+ # Strip the prompt off the front leaving just the command.
+ command = self.lstripPrompt(text)
+ if command == text:
+ command = '' # Real commands have prompts.
+ if rstrip:
+ command = command.rstrip()
+ return command
+
+ def lstripPrompt(self, text):
+ """Return text without a leading prompt."""
+ ps1 = str(sys.ps1)
+ ps1size = len(ps1)
+ ps2 = str(sys.ps2)
+ ps2size = len(ps2)
+ # Strip the prompt off the front of text.
+ if text[:ps1size] == ps1:
+ text = text[ps1size:]
+ elif text[:ps2size] == ps2:
+ text = text[ps2size:]
+ return text
+
+ def push(self, command, silent = False):
+ """Send command to the interpreter for execution."""
+ if not silent:
+ self.write(os.linesep)
+
+ #DNM
+ if USE_MAGIC:
+ command=magic(command)
+
+ busy = wx.BusyCursor()
+ self.waiting = True
+ self.lastUpdate=None
+ self.more = self.interp.push(command)
+ self.lastUpdate=None
+ self.waiting = False
+ del busy
+ if not self.more:
+ self.addHistory(command.rstrip())
+ if not silent:
+ self.prompt()
+
+ def addHistory(self, command):
+ """Add command to the command history."""
+ # Reset the history position.
+ self.historyIndex = -1
+ # Insert this command into the history, unless it's a blank
+ # line or the same as the last command.
+ if command != '' \
+ and (len(self.history) == 0 or command != self.history[0]):
+ self.history.insert(0, command)
+ dispatcher.send(signal="Shell.addHistory", command=command)
+
+ def write(self, text):
+ """Display text in the shell.
+
+ Replace line endings with OS-specific endings."""
+ text = self.fixLineEndings(text)
+ self.AddText(text)
+ self.EnsureCaretVisible()
+
+ if self.waiting:
+ if self.lastUpdate==None:
+ self.lastUpdate=time.time()
+ if time.time()-self.lastUpdate > PRINT_UPDATE_MAX_TIME:
+ self.Update()
+ self.lastUpdate=time.time()
+
+ def fixLineEndings(self, text):
+ """Return text with line endings replaced by OS-specific endings."""
+ lines = text.split('\r\n')
+ for l in range(len(lines)):
+ chunks = lines[l].split('\r')
+ for c in range(len(chunks)):
+ chunks[c] = os.linesep.join(chunks[c].split('\n'))
+ lines[l] = os.linesep.join(chunks)
+ text = os.linesep.join(lines)
+ return text
+
+ def prompt(self):
+ """Display proper prompt for the context: ps1, ps2 or ps3.
+
+ If this is a continuation line, autoindent as necessary."""
+ isreading = self.reader.isreading
+ skip = False
+ if isreading:
+ prompt = str(sys.ps3)
+ elif self.more:
+ prompt = str(sys.ps2)
+ else:
+ prompt = str(sys.ps1)
+ pos = self.GetCurLine()[1]
+ if pos > 0:
+ if isreading:
+ skip = True
+ else:
+ self.write(os.linesep)
+ if not self.more:
+ self.promptPosStart = self.GetCurrentPos()
+ if not skip:
+ self.write(prompt)
+ if not self.more:
+ self.promptPosEnd = self.GetCurrentPos()
+ # Keep the undo feature from undoing previous responses.
+ self.EmptyUndoBuffer()
+
+ if self.more:
+ line_num=self.GetCurrentLine()
+ currentLine=self.GetLine(line_num)
+ previousLine=self.GetLine(line_num-1)[len(prompt):]
+ pstrip=previousLine.strip()
+ lstrip=previousLine.lstrip()
+
+ # Get the first alnum word:
+ first_word=[]
+ for i in pstrip:
+ if i.isalnum():
+ first_word.append(i)
+ else:
+ break
+ first_word = ''.join(first_word)
+
+ if pstrip == '':
+ # because it is all whitespace!
+ indent=previousLine.strip('\n').strip('\r')
+ else:
+ indent=previousLine[:(len(previousLine)-len(lstrip))]
+ if pstrip[-1]==':' and \
+ first_word in ['if','else','elif','for','while',
+ 'def','class','try','except','finally']:
+ indent+=' '*4
+
+ self.write(indent)
+ self.EnsureCaretVisible()
+ self.ScrollToColumn(0)
+
+ def readline(self):
+ """Replacement for stdin.readline()."""
+ input = ''
+ reader = self.reader
+ reader.isreading = True
+ self.prompt()
+ try:
+ while not reader.input:
+ wx.YieldIfNeeded()
+ input = reader.input
+ finally:
+ reader.input = ''
+ reader.isreading = False
+ input = str(input) # In case of Unicode.
+ return input
+
+ def readlines(self):
+ """Replacement for stdin.readlines()."""
+ lines = []
+ while lines[-1:] != ['\n']:
+ lines.append(self.readline())
+ return lines
+
+ def raw_input(self, prompt=''):
+ """Return string based on user input."""
+ if prompt:
+ self.write(prompt)
+ return self.readline()
+
+ def ask(self, prompt='Please enter your response:'):
+ """Get response from the user using a dialog box."""
+ dialog = wx.TextEntryDialog(None, prompt,
+ 'Input Dialog (Raw)', '')
+ try:
+ if dialog.ShowModal() == wx.ID_OK:
+ text = dialog.GetValue()
+ return text
+ finally:
+ dialog.Destroy()
+ return ''
+
+ def pause(self):
+ """Halt execution pending a response from the user."""
+ self.ask('Press enter to continue:')
+
+ def clear(self):
+ """Delete all text from the shell."""
+ self.ClearAll()
+
+ def run(self, command, prompt=True, verbose=True):
+ """Execute command as if it was typed in directly.
+ >>> shell.run('print "this"')
+ >>> print "this"
+ this
+ >>>
+ """
+ # Go to the very bottom of the text.
+ endpos = self.GetTextLength()
+ self.SetCurrentPos(endpos)
+ command = command.rstrip()
+ if prompt: self.prompt()
+ if verbose: self.write(command)
+ self.push(command)
+
+ def runfile(self, filename):
+ """Execute all commands in file as if they were typed into the
+ shell."""
+ file = open(filename)
+ try:
+ self.prompt()
+ for command in file.readlines():
+ if command[:6] == 'shell.':
+ # Run shell methods silently.
+ self.run(command, prompt=False, verbose=False)
+ else:
+ self.run(command, prompt=False, verbose=True)
+ finally:
+ file.close()
+
+ def autoCompleteShow(self, command, offset = 0):
+ """Display auto-completion popup list."""
+ self.AutoCompSetAutoHide(self.autoCompleteAutoHide)
+ self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
+ list = self.interp.getAutoCompleteList(command,
+ includeMagic=self.autoCompleteIncludeMagic,
+ includeSingle=self.autoCompleteIncludeSingle,
+ includeDouble=self.autoCompleteIncludeDouble)
+ if list:
+ options = ' '.join(list)
+ #offset = 0
+ self.AutoCompShow(offset, options)
+
+ def autoCallTipShow(self, command, insertcalltip = True, forceCallTip = False):
+ """Display argument spec and docstring in a popup window."""
+ if self.CallTipActive():
+ self.CallTipCancel()
+ (name, argspec, tip) = self.interp.getCallTip(command)
+ if tip:
+ dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip)
+ if not self.autoCallTip and not forceCallTip:
+ return
+ startpos = self.GetCurrentPos()
+ if argspec and insertcalltip and self.callTipInsert:
+ self.write(argspec + ')')
+ endpos = self.GetCurrentPos()
+ self.SetSelection(startpos, endpos)
+ if tip:
+ tippos = startpos - (len(name) + 1)
+ fallback = startpos - self.GetColumn(startpos)
+ # In case there isn't enough room, only go back to the
+ # fallback.
+ tippos = max(tippos, fallback)
+ self.CallTipShow(tippos, tip)
+
+ def OnCallTipAutoCompleteManually (self, shiftDown):
+ """AutoComplete and Calltips manually."""
+ if self.AutoCompActive():
+ self.AutoCompCancel()
+ currpos = self.GetCurrentPos()
+ stoppos = self.promptPosEnd
+
+ cpos = currpos
+ #go back until '.' is found
+ pointavailpos = -1
+ while cpos >= stoppos:
+ if self.GetCharAt(cpos) == ord ('.'):
+ pointavailpos = cpos
+ break
+ cpos -= 1
+
+ #word from non whitespace until '.'
+ if pointavailpos != -1:
+ #look backward for first whitespace char
+ textbehind = self.GetTextRange (pointavailpos + 1, currpos)
+ pointavailpos += 1
+
+ if not shiftDown:
+ #call AutoComplete
+ stoppos = self.promptPosEnd
+ textbefore = self.GetTextRange(stoppos, pointavailpos)
+ self.autoCompleteShow(textbefore, len (textbehind))
+ else:
+ #call CallTips
+ cpos = pointavailpos
+ begpos = -1
+ while cpos > stoppos:
+ if chr(self.GetCharAt(cpos)).isspace():
+ begpos = cpos
+ break
+ cpos -= 1
+ if begpos == -1:
+ begpos = cpos
+ ctips = self.GetTextRange (begpos, currpos)
+ ctindex = ctips.find ('(')
+ if ctindex != -1 and not self.CallTipActive():
+ #insert calltip, if current pos is '(', otherwise show it only
+ self.autoCallTipShow(ctips[:ctindex + 1],
+ self.GetCharAt(currpos - 1) == ord('(') and \
+ self.GetCurrentPos() == self.GetTextLength(),
+ True)
+
+
+ def writeOut(self, text):
+ """Replacement for stdout."""
+ self.write(text)
+
+ def writeErr(self, text):
+ """Replacement for stderr."""
+ self.write(text)
+
+ def redirectStdin(self, redirect=True):
+ """If redirect is true then sys.stdin will come from the shell."""
+ if redirect:
+ sys.stdin = self.reader
+ else:
+ sys.stdin = self.stdin
+
+ def redirectStdout(self, redirect=True):
+ """If redirect is true then sys.stdout will go to the shell."""
+ if redirect:
+ sys.stdout = PseudoFileOut(self.writeOut)
+ else:
+ sys.stdout = self.stdout
+
+ def redirectStderr(self, redirect=True):
+ """If redirect is true then sys.stderr will go to the shell."""
+ if redirect:
+ sys.stderr = PseudoFileErr(self.writeErr)
+ else:
+ sys.stderr = self.stderr
+
+ def CanCut(self):
+ """Return true if text is selected and can be cut."""
+ if self.GetSelectionStart() != self.GetSelectionEnd() \
+ and self.GetSelectionStart() >= self.promptPosEnd \
+ and self.GetSelectionEnd() >= self.promptPosEnd:
+ return True
+ else:
+ return False
+
+ def CanPaste(self):
+ """Return true if a paste should succeed."""
+ if self.CanEdit() and editwindow.EditWindow.CanPaste(self):
+ return True
+ else:
+ return False
+
+ def CanEdit(self):
+ """Return true if editing should succeed."""
+ if self.GetSelectionStart() != self.GetSelectionEnd():
+ if self.GetSelectionStart() >= self.promptPosEnd \
+ and self.GetSelectionEnd() >= self.promptPosEnd:
+ return True
+ else:
+ return False
+ else:
+ return self.GetCurrentPos() >= self.promptPosEnd
+
+ def Cut(self):
+ """Remove selection and place it on the clipboard."""
+ if self.CanCut() and self.CanCopy():
+ if self.AutoCompActive():
+ self.AutoCompCancel()
+ if self.CallTipActive():
+ self.CallTipCancel()
+ self.Copy()
+ self.ReplaceSelection('')
+
+ def Copy(self):
+ """Copy selection and place it on the clipboard."""
+ if self.CanCopy():
+ ps1 = str(sys.ps1)
+ ps2 = str(sys.ps2)
+ command = self.GetSelectedText()
+ command = command.replace(os.linesep + ps2, os.linesep)
+ command = command.replace(os.linesep + ps1, os.linesep)
+ command = self.lstripPrompt(text=command)
+ data = wx.TextDataObject(command)
+ self._clip(data)
+
+ def CopyWithPrompts(self):
+ """Copy selection, including prompts, and place it on the clipboard."""
+ if self.CanCopy():
+ command = self.GetSelectedText()
+ data = wx.TextDataObject(command)
+ self._clip(data)
+
+ def CopyWithPromptsPrefixed(self):
+ """Copy selection, including prompts prefixed with four
+ spaces, and place it on the clipboard."""
+ if self.CanCopy():
+ command = self.GetSelectedText()
+ spaces = ' ' * 4
+ command = spaces + command.replace(os.linesep,
+ os.linesep + spaces)
+ data = wx.TextDataObject(command)
+ self._clip(data)
+
+ def _clip(self, data):
+ if wx.TheClipboard.Open():
+ wx.TheClipboard.UsePrimarySelection(False)
+ wx.TheClipboard.SetData(data)
+ wx.TheClipboard.Flush()
+ wx.TheClipboard.Close()
+
+ def Paste(self):
+ """Replace selection with clipboard contents."""
+ if self.CanPaste() and wx.TheClipboard.Open():
+ ps2 = str(sys.ps2)
+ if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)):
+ data = wx.TextDataObject()
+ if wx.TheClipboard.GetData(data):
+ self.ReplaceSelection('')
+ command = data.GetText()
+ command = command.rstrip()
+ command = self.fixLineEndings(command)
+ command = self.lstripPrompt(text=command)
+ command = command.replace(os.linesep + ps2, '\n')
+ command = command.replace(os.linesep, '\n')
+ command = command.replace('\n', os.linesep + ps2)
+ self.write(command)
+ wx.TheClipboard.Close()
+
+
+ def PasteAndRun(self):
+ """Replace selection with clipboard contents, run commands."""
+ text = ''
+ if wx.TheClipboard.Open():
+ if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)):
+ data = wx.TextDataObject()
+ if wx.TheClipboard.GetData(data):
+ text = data.GetText()
+ wx.TheClipboard.Close()
+ if text:
+ self.Execute(text)
+
+
+ def Execute(self, text):
+ """Replace selection with text and run commands."""
+ ps1 = str(sys.ps1)
+ ps2 = str(sys.ps2)
+ endpos = self.GetTextLength()
+ self.SetCurrentPos(endpos)
+ startpos = self.promptPosEnd
+ self.SetSelection(startpos, endpos)
+ self.ReplaceSelection('')
+ text = text.lstrip()
+ text = self.fixLineEndings(text)
+ text = self.lstripPrompt(text)
+ text = text.replace(os.linesep + ps1, '\n')
+ text = text.replace(os.linesep + ps2, '\n')
+ text = text.replace(os.linesep, '\n')
+ lines = text.split('\n')
+ commands = []
+ command = ''
+ for line in lines:
+ if line.strip() == ps2.strip():
+ # If we are pasting from something like a
+ # web page that drops the trailing space
+ # from the ps2 prompt of a blank line.
+ line = ''
+ lstrip = line.lstrip()
+ if line.strip() != '' and lstrip == line and \
+ lstrip[:4] not in ['else','elif'] and \
+ lstrip[:6] != 'except':
+ # New command.
+ if command:
+ # Add the previous command to the list.
+ commands.append(command)
+ # Start a new command, which may be multiline.
+ command = line
+ else:
+ # Multiline command. Add to the command.
+ command += '\n'
+ command += line
+ commands.append(command)
+ for command in commands:
+ command = command.replace('\n', os.linesep + ps2)
+ self.write(command)
+ self.processLine()
+
+
+ def wrap(self, wrap=True):
+ """Sets whether text is word wrapped."""
+ try:
+ self.SetWrapMode(wrap)
+ except AttributeError:
+ return 'Wrapping is not available in this version.'
+
+ def zoom(self, points=0):
+ """Set the zoom level.
+
+ This number of points is added to the size of all fonts. It
+ may be positive to magnify or negative to reduce."""
+ self.SetZoom(points)
+
+
+
+ def LoadSettings(self, config):
+ self.autoComplete = \
+ config.ReadBool('Options/AutoComplete', True)
+ self.autoCompleteIncludeMagic = \
+ config.ReadBool('Options/AutoCompleteIncludeMagic', True)
+ self.autoCompleteIncludeSingle = \
+ config.ReadBool('Options/AutoCompleteIncludeSingle', True)
+ self.autoCompleteIncludeDouble = \
+ config.ReadBool('Options/AutoCompleteIncludeDouble', True)
+
+ self.autoCallTip = config.ReadBool('Options/AutoCallTip', True)
+ self.callTipInsert = config.ReadBool('Options/CallTipInsert', True)
+ self.SetWrapMode(config.ReadBool('View/WrapMode', True))
+
+ self.lineNumbers = config.ReadBool('View/ShowLineNumbers', True)
+ self.setDisplayLineNumbers (self.lineNumbers)
+ zoom = config.ReadInt('View/Zoom/Shell', -99)
+ if zoom != -99:
+ self.SetZoom(zoom)
+
+
+ def SaveSettings(self, config):
+ config.WriteBool('Options/AutoComplete', self.autoComplete)
+ config.WriteBool('Options/AutoCompleteIncludeMagic',
+ self.autoCompleteIncludeMagic)
+ config.WriteBool('Options/AutoCompleteIncludeSingle',
+ self.autoCompleteIncludeSingle)
+ config.WriteBool('Options/AutoCompleteIncludeDouble',
+ self.autoCompleteIncludeDouble)
+ config.WriteBool('Options/AutoCallTip', self.autoCallTip)
+ config.WriteBool('Options/CallTipInsert', self.callTipInsert)
+ config.WriteBool('View/WrapMode', self.GetWrapMode())
+ config.WriteBool('View/ShowLineNumbers', self.lineNumbers)
+ config.WriteInt('View/Zoom/Shell', self.GetZoom())
+
+ def GetContextMenu(self):
+ """
+ Create and return a context menu for the shell.
+ This is used instead of the scintilla default menu
+ in order to correctly respect our immutable buffer.
+ """
+ menu = wx.Menu()
+ menu.Append(wx.ID_UNDO, "Undo")
+ menu.Append(wx.ID_REDO, "Redo")
+
+ menu.AppendSeparator()
+
+ menu.Append(wx.ID_CUT, "Cut")
+ menu.Append(wx.ID_COPY, "Copy")
+ menu.Append(frame.ID_COPY_PLUS, "Copy Plus")
+ menu.Append(wx.ID_PASTE, "Paste")
+ menu.Append(frame.ID_PASTE_PLUS, "Paste Plus")
+ menu.Append(wx.ID_CLEAR, "Clear")
+
+ menu.AppendSeparator()
+
+ menu.Append(wx.ID_SELECTALL, "Select All")
+ return menu
+
+ def OnContextMenu(self, evt):
+ menu = self.GetContextMenu()
+ self.PopupMenu(menu)
+
+ def OnUpdateUI(self, evt):
+ id = evt.Id
+ if id in (wx.ID_CUT, wx.ID_CLEAR):
+ evt.Enable(self.CanCut())
+ elif id in (wx.ID_COPY, frame.ID_COPY_PLUS):
+ evt.Enable(self.CanCopy())
+ elif id in (wx.ID_PASTE, frame.ID_PASTE_PLUS):
+ evt.Enable(self.CanPaste())
+ elif id == wx.ID_UNDO:
+ evt.Enable(self.CanUndo())
+ elif id == wx.ID_REDO:
+ evt.Enable(self.CanRedo())
+
+
+
+
+## NOTE: The DnD of file names is disabled until we can figure out how
+## best to still allow DnD of text.
+
+
+## #seb : File drag and drop
+## class FileDropTarget(wx.FileDropTarget):
+## def __init__(self, obj):
+## wx.FileDropTarget.__init__(self)
+## self.obj = obj
+## def OnDropFiles(self, x, y, filenames):
+## if len(filenames) == 1:
+## txt = 'r\"%s\"' % filenames[0]
+## else:
+## txt = '( '
+## for f in filenames:
+## txt += 'r\"%s\" , ' % f
+## txt += ')'
+## self.obj.AppendText(txt)
+## pos = self.obj.GetCurrentPos()
+## self.obj.SetCurrentPos( pos )
+## self.obj.SetSelection( pos, pos )
+
+
+
+## class TextAndFileDropTarget(wx.DropTarget):
+## def __init__(self, shell):
+## wx.DropTarget.__init__(self)
+## self.shell = shell
+## self.compdo = wx.DataObjectComposite()
+## self.textdo = wx.TextDataObject()
+## self.filedo = wx.FileDataObject()
+## self.compdo.Add(self.textdo)
+## self.compdo.Add(self.filedo, True)
+
+## self.SetDataObject(self.compdo)
+
+## def OnDrop(self, x, y):
+## return True
+
+## def OnData(self, x, y, result):
+## self.GetData()
+## if self.textdo.GetTextLength() > 1:
+## text = self.textdo.GetText()
+## # *** Do somethign with the dragged text here...
+## self.textdo.SetText('')
+## else:
+## filenames = str(self.filename.GetFilenames())
+## if len(filenames) == 1:
+## txt = 'r\"%s\"' % filenames[0]
+## else:
+## txt = '( '
+## for f in filenames:
+## txt += 'r\"%s\" , ' % f
+## txt += ')'
+## self.shell.AppendText(txt)
+## pos = self.shell.GetCurrentPos()
+## self.shell.SetCurrentPos( pos )
+## self.shell.SetSelection( pos, pos )
+
+## return result
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/sliceshell.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/sliceshell.py
new file mode 100644
index 0000000..437fce7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/sliceshell.py
@@ -0,0 +1,3789 @@
+"""Slices is an interactive text control in which a user types in
+commands to be sent to the interpreter. This particular shell is
+based on wxPython's wxStyledTextCtrl.
+
+Sponsored by Orbtech - Your source for Python programming expertise.
+Slices is a version of shell modified by David Mashburn."""
+
+__author__ = "David N. Mashburn <david.n.mashburn@gmail.com> / "
+__author__ += "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id: sliceshell.py 60100 2009-04-12 02:56:29Z RD $"
+__revision__ = "$Revision: 60100 $"[11:-2]
+
+import wx
+from wx import stc
+
+import keyword
+import os
+import sys
+import time
+
+from buffer import Buffer
+import dispatcher
+import editor
+import editwindow
+import document
+import frame
+from pseudo import PseudoFileIn
+from pseudo import PseudoFileOut
+from pseudo import PseudoFileErr
+from version import VERSION
+from magic import magic
+from parse import testForContinuations
+from path import ls,cd,pwd,sx
+
+
+sys.ps3 = '<-- ' # Input prompt.
+USE_MAGIC=True
+# Force updates from long-running commands after this many seconds
+PRINT_UPDATE_MAX_TIME=2
+
+NAVKEYS = (wx.WXK_HOME, wx.WXK_END, wx.WXK_LEFT, wx.WXK_RIGHT,
+ wx.WXK_UP, wx.WXK_DOWN, wx.WXK_PRIOR, wx.WXK_NEXT)
+
+GROUPING_SELECTING=0
+IO_SELECTING = 1
+
+GROUPING_START = 2
+GROUPING_START_FOLDED = 3
+GROUPING_MIDDLE = 4
+GROUPING_END = 5
+INPUT_START = 6
+INPUT_START_FOLDED = 7
+INPUT_MIDDLE = 8
+INPUT_END = 9
+OUTPUT_START = 10
+OUTPUT_START_FOLDED = 11
+OUTPUT_MIDDLE = 12
+OUTPUT_END = 13
+
+OUTPUT_BG = 14
+READLINE_BG = 15
+INPUT_READLINE = 16
+
+# Could add C integration right into the markers...
+# Non-editable file marker for auto-loaded files...
+# Weave VariableInput = 15
+# Weave C code = 16
+# C code = 17 (only for use with Pyrex)
+# Pyrex / Cython code = 18
+
+GROUPING_MASK = ( 1<<GROUPING_START | 1<<GROUPING_START_FOLDED |
+ 1<<GROUPING_MIDDLE | 1<<GROUPING_END )
+
+INPUT_MASK = ( 1<<INPUT_START | 1<<INPUT_START_FOLDED |
+ 1<<INPUT_MIDDLE | 1<<INPUT_END )
+OUTPUT_MASK = ( 1<<OUTPUT_START | 1<<OUTPUT_START_FOLDED |
+ 1<<OUTPUT_MIDDLE | 1<<OUTPUT_END )
+IO_MASK = ( INPUT_MASK | OUTPUT_MASK )
+
+IO_START_MASK = ( 1<<INPUT_START | 1<<OUTPUT_START )
+IO_START_FOLDED_MASK = ( 1<<INPUT_START_FOLDED | 1<<OUTPUT_START_FOLDED )
+IO_ANY_START_MASK = ( 1<<INPUT_START | 1<<OUTPUT_START |
+ 1<<INPUT_START_FOLDED | 1<<OUTPUT_START_FOLDED )
+IO_MIDDLE_MASK = ( 1<<INPUT_MIDDLE | 1<<OUTPUT_MIDDLE )
+IO_END_MASK = ( 1<<INPUT_END | 1<<OUTPUT_END )
+
+usrBinEnvPythonText = '#!/usr/bin/env python2\n'
+pyslicesFormatHeaderText = ['#PySlices Save Format Version 1.1 (PySlices v0.9.7.8 and later)\n',
+ '#PySlices Save Format Version 1.2 (PySlices v0.9.8 and later)\n']
+groupingStartText = '#PySlices Marker Information -- Begin Grouping Slice\n'
+inputStartText = '#PySlices Marker Information -- Begin Input Slice\n'
+outputStartText = '#PySlices Marker Information -- Begin Output Slice\n'
+
+tutorialText = """
+
+ Tutorial!!!
+------------------------------------------------------------------------
+PySlices is the newest member of the Py suite!
+It is a modified version of PyCrust that supports multi-line commands.
+
+Input and output are contained in "Slices" shown as markers in the left margin.
+Input Slices have RED margins (active, editable).
+Output Slices have BLUE margins (frozen, not editable).
+
+Commands in slices can be on more than one line, as with Sage or Mathematica.
+For example, the command:
+a=1
+b=2
+print a+b
+will all run in sequence, much like a script.
+Try running the above Input Slice by clicking somewhere in its text and
+using Ctrl-Return, Shift-Return, or Numpad Enter to execute.
+Previous commands (Old Slices) can be re-edited and run again in place.
+
+Slices can also be:
+ * selceted (click on the margin, Shift-click for multiple selection)
+ * folded (click the margin twice)
+ * selected and deleted (hit delete while selected)
+ * divided (Ctrl-D)
+ * merged (Ctrl-M while selecting adjacent, like-colored slices)
+
+Try deleting the slice above this one by clicking on the red margin.
+
+If you want a more traditional shell feel, try enabling "Shell Mode" in
+"Options->Settings->Shell Mode" (or try PyCrust).
+In Shell Mode, two returns in a row executes the command, and
+ Ctrl-Return and Shift-Return always print newlines.
+
+Saving and opening "sessions" is now supported! This is a little
+different to other shells where the history is saved. With PySlices,
+the whole document is saved in a simple text format!
+
+To disable this Tutorial on startup, uncheck it in the menu at:
+"Options->Startup->Show PySlices tutorial"
+
+PySlices may not be the best thing since sliced bread, but
+I hope it makes using Python a little bit sweeter!
+"""
+
+class SlicesShellFrame(frame.Frame, frame.ShellFrameMixin):
+ """Frame containing the sliceshell component."""
+
+ name = 'SlicesShell Frame'
+ revision = __revision__
+
+ def __init__(self, parent=None, id=-1, title='PySlicesShell',
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_FRAME_STYLE, locals=None,
+ InterpClass=None,
+ config=None, dataDir=None, filename=None,
+ *args, **kwds):
+ """Create SlicesShellFrame instance."""
+ frame.Frame.__init__(self, parent, id, title, pos, size, style,shellName='PySlices')
+ frame.ShellFrameMixin.__init__(self, config, dataDir)
+
+ if size == wx.DefaultSize:
+ self.SetSize((750, 525))
+
+ intro = 'PySlices %s - The Flakiest Python Shell... Cut Up!' % VERSION
+ self.SetStatusText(intro.replace('\n', ', '))
+ self.sliceshell = SlicesShell(parent=self, id=-1, introText=intro,
+ locals=locals, InterpClass=InterpClass,
+ startupScript=self.startupScript,
+ execStartupScript=self.execStartupScript,
+ showPySlicesTutorial=self.showPySlicesTutorial,
+ enableShellMode=self.enableShellMode,
+ hideFoldingMargin=self.hideFoldingMargin,
+ *args, **kwds)
+ self.buffer = self.sliceshell.buffer
+
+ # Override the shell so that status messages go to the status bar.
+ self.sliceshell.setStatusText = self.SetStatusText
+
+ self.sliceshell.SetFocus()
+ self.LoadSettings()
+
+ self.currentDirectory = os.path.expanduser('~')
+
+ if filename!=None:
+ self.bufferOpen(filename)
+
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+
+ def OnClose(self, event):
+ """Event handler for closing."""
+ self.bufferClose()
+ # This isn't working the way I want, but I'll leave it for now.
+ #if self.sliceshell.waiting:
+ # if event.CanVeto():
+ # event.Veto(True)
+ #else:
+ # # TODO: Add check for saving
+ # self.SaveSettings()
+ # self.sliceshell.destroy()
+ # self.Destroy()
+
+ def OnAbout(self, event):
+ """Display an About window."""
+ title = 'About PySliceShell'
+ text = 'PySliceShell %s\n\n' % VERSION + \
+ 'Yet another Python shell, only flakier.\n\n' + \
+ 'Half-baked by Patrick K. O\'Brien,\n' + \
+ 'the other half is still in the oven.\n\n' + \
+ 'Shell Revision: %s\n' % self.shell.revision + \
+ 'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
+ 'Platform: %s\n' % sys.platform + \
+ 'Python Version: %s\n' % sys.version.split()[0] + \
+ 'wxPython Version: %s\n' % wx.VERSION_STRING + \
+ ('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:]))
+ dialog = wx.MessageDialog(self, text, title,
+ wx.OK | wx.ICON_INFORMATION)
+ dialog.ShowModal()
+ dialog.Destroy()
+
+
+ def OnHelp(self, event):
+ """Show a help dialog."""
+ frame.ShellFrameMixin.OnHelp(self, event)
+
+
+ def LoadSettings(self):
+ if self.config is not None:
+ frame.ShellFrameMixin.LoadSettings(self)
+ frame.Frame.LoadSettings(self, self.config)
+ self.sliceshell.LoadSettings(self.config)
+
+ def SaveSettings(self, force=False):
+ if self.config is not None:
+ frame.ShellFrameMixin.SaveSettings(self,force)
+ if self.autoSaveSettings or force:
+ frame.Frame.SaveSettings(self, self.config)
+ self.sliceshell.SaveSettings(self.config)
+
+ def DoSaveSettings(self):
+ if self.config is not None:
+ self.SaveSettings(force=True)
+ self.config.Flush()
+
+ def OnEnableShellMode(self,event):
+ """Change between Slices Mode and Shell Mode"""
+ frame.Frame.OnEnableShellMode(self,event)
+ self.sliceshell.ToggleShellMode(self.enableShellMode)
+
+ def OnHideFoldingMargin(self,event):
+ """Change between Slices Mode and Shell Mode"""
+ frame.Frame.OnHideFoldingMargin(self,event)
+ self.sliceshell.ToggleFoldingMargin(self.hideFoldingMargin)
+ # Copied Straight from crustslices.py (update both with any changes...)
+ # Stolen Straight from editor.EditorFrame
+ # Modified a little... :)
+ # ||
+ # \/
+ def OnIdle(self, event):
+ """Event handler for idle time."""
+ self._updateTitle()
+ event.Skip()
+
+ def _updateTitle(self):
+ """Show current title information."""
+ title = self.GetTitle()
+ if self.bufferHasChanged():
+ if title.startswith('* '):
+ pass
+ else:
+ self.SetTitle('* ' + title)
+ else:
+ if title.startswith('* '):
+ self.SetTitle(title[2:])
+
+ def hasBuffer(self):
+ """Return True if there is a current buffer."""
+ if self.buffer:
+ return True
+ else:
+ return False
+
+ def bufferClose(self):
+ """Close buffer."""
+ if self.buffer.hasChanged():
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ #event.Veto()
+ return cancel
+ self.SaveSettings()
+ self.sliceshell.destroy()
+ self.bufferDestroy()
+ self.Destroy()
+
+ return False
+
+ def bufferCreate(self, filename=None):
+ """Create new buffer."""
+ self.bufferDestroy()
+ buffer = Buffer()
+ self.panel = panel = wx.Panel(parent=self, id=-1)
+ panel.Bind (wx.EVT_ERASE_BACKGROUND, lambda x: x)
+ editor = Editor(parent=panel)
+ panel.editor = editor
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(editor.window, 1, wx.EXPAND)
+ panel.SetSizer(sizer)
+ panel.SetAutoLayout(True)
+ sizer.Layout()
+ buffer.addEditor(editor)
+ buffer.open(filename)
+ self.setEditor(editor)
+ self.editor.setFocus()
+ self.SendSizeEvent()
+
+
+ def bufferDestroy(self):
+ """Destroy the current buffer."""
+ if self.buffer:
+ self.editor = None
+ self.buffer = None
+
+
+ def bufferHasChanged(self):
+ """Return True if buffer has changed since last save."""
+ if self.buffer:
+ return self.buffer.hasChanged()
+ else:
+ return False
+
+ def bufferNew(self):
+ """Create new buffer."""
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+ #self.bufferCreate()
+ self.clear()
+ self.SetTitle( 'PySlices')
+ self.sliceshell.NeedsCheckForSave=False
+ self.sliceshell.SetSavePoint()
+ self.buffer.doc = document.Document()
+ self.buffer.name = 'This shell'
+ self.buffer.modulename = self.buffer.doc.filebase
+ cancel = False
+ return cancel
+
+ def bufferOpen(self,file=None):
+ """Open file in buffer."""
+ if self.bufferHasChanged():
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+
+ if file==None:
+ file=wx.FileSelector('Open a PySlices File',
+ wildcard='*.pyslices',
+ default_path=self.currentDirectory)
+ if file!=None and file!=u'':
+ fid=open(file,'r')
+ self.sliceshell.LoadPySlicesFile(fid)
+ fid.close()
+ self.currentDirectory = os.path.split(file)[0]
+ self.SetTitle( os.path.split(file)[1] + ' - PySlices')
+ self.sliceshell.NeedsCheckForSave=False
+ self.sliceshell.SetSavePoint()
+ self.buffer.doc = document.Document(file)
+ self.buffer.name = self.buffer.doc.filename
+ self.buffer.modulename = self.buffer.doc.filebase
+ self.sliceshell.ScrollToLine(0)
+ return
+
+## def bufferPrint(self):
+## """Print buffer."""
+## pass
+
+## def bufferRevert(self):
+## """Revert buffer to version of file on disk."""
+## pass
+
+ # was self.buffer.save(self): # """Save buffer."""
+ def simpleSave(self,confirmed=False):
+ filepath = self.buffer.doc.filepath
+ self.buffer.confirmed = confirmed
+ if not filepath:
+ return # XXX Get filename
+ if not os.path.exists(filepath):
+ self.buffer.confirmed = True
+ if not self.buffer.confirmed:
+ self.buffer.confirmed = self.buffer.overwriteConfirm(filepath)
+ if self.buffer.confirmed:
+ try:
+ fid = open(filepath, 'wb')
+ self.sliceshell.SavePySlicesFile(fid)
+ finally:
+ if fid:
+ fid.close()
+ self.sliceshell.SetSavePoint()
+ self.SetTitle( os.path.split(filepath)[1] + ' - PySlices')
+ self.sliceshell.NeedsCheckForSave=False
+
+ def bufferSave(self):
+ """Save buffer to its file."""
+ if self.buffer.doc.filepath:
+ # self.buffer.save()
+ self.simpleSave(confirmed=True)
+ cancel = False
+ else:
+ cancel = self.bufferSaveAs()
+ return cancel
+
+ def bufferSaveAs(self):
+ """Save buffer to a new filename."""
+ if self.bufferHasChanged() and self.buffer.doc.filepath:
+ cancel = self.bufferSuggestSave()
+ if cancel:
+ return cancel
+ filedir = ''
+ if self.buffer and self.buffer.doc.filedir:
+ filedir = self.buffer.doc.filedir
+ result = editor.saveSingle(title='Save PySlices File',directory=filedir,
+ wildcard='PySlices Files (*.pyslices)|*.pyslices')
+ if result.path not in ['',None]:
+ if result.path[-9:]!=".pyslices":
+ result.path+=".pyslices"
+
+ self.buffer.doc = document.Document(result.path)
+ self.buffer.name = self.buffer.doc.filename
+ self.buffer.modulename = self.buffer.doc.filebase
+ self.simpleSave(confirmed=True) # allow overwrite
+ cancel = False
+ else:
+ cancel = True
+ return cancel
+
+ def bufferSaveACopy(self):
+ """Save buffer to a new filename."""
+ filedir = ''
+ if self.buffer and self.buffer.doc.filedir:
+ filedir = self.buffer.doc.filedir
+ result = editor.saveSingle(title='Save a Copy of PySlices File',directory=filedir,
+ wildcard='PySlices Files (*.pyslices)|*.pyslices')
+
+ if result.path not in ['',None]:
+ if result.path[-9:]!=".pyslices":
+ result.path+=".pyslices"
+
+ # if not os.path.exists(result.path):
+ try: # Allow overwrite...
+ fid = open(result.path, 'wb')
+ self.sliceshell.SavePySlicesFile(fid)
+ finally:
+ if fid:
+ fid.close()
+
+ cancel = False
+ else:
+ cancel = True
+ return cancel
+
+ def bufferSuggestSave(self):
+ """Suggest saving changes. Return True if user selected Cancel."""
+ result = editor.messageDialog(parent=None,
+ message='%s has changed.\n'
+ 'Would you like to save it first'
+ '?' % self.buffer.name,
+ title='Save current file?',
+ style=wx.YES_NO | wx.CANCEL | wx.NO_DEFAULT |
+ wx.CENTRE | wx.ICON_QUESTION )
+ if result.positive:
+ cancel = self.bufferSave()
+ else:
+ cancel = result.text == 'Cancel'
+ return cancel
+
+ def updateNamespace(self):
+ """Update the buffer namespace for autocompletion and calltips."""
+ if self.buffer.updateNamespace():
+ self.SetStatusText('Namespace updated')
+ else:
+ self.SetStatusText('Error executing, unable to update namespace')
+
+
+
+# TODO : Update the help text
+HELP_TEXT = """\
+* Key bindings:
+Home Go to the beginning of the line.
+End Go to the end of the line.
+Shift+Home Select to the beginning of the line.
+Shift+End Select to the end of the line.
+Ctrl-Home Jump to the beginning of the slice;
+ If already there, jump to beginning of previous slice
+Ctrl-End Jump to the end of the slice;
+ If already there, jump to end of next slice
+Ctrl-PageUp Jump to the beginning of the shell
+Ctrl-PageDown Jump to the end of the shell
+Ctrl+C Copy selected text, removing prompts.
+Ctrl+Shift+C Copy selected text, retaining prompts.
+Alt+C Copy to the clipboard, including prefixed prompts.
+Ctrl+X Cut selected text.
+Ctrl+V Paste from clipboard.
+Ctrl+Shift+V Paste and run multiple commands from clipboard.
+Ctrl+Up Arrow Retrieve Previous History item.
+Alt+P Retrieve Previous History item.
+Ctrl+Down Arrow Retrieve Next History item.
+Alt+N Retrieve Next History item.
+Shift+Up Arrow Insert Previous History item.
+Shift+Down Arrow Insert Next History item.
+F8 Command-completion of History item.
+ (Type a few characters of a previous command and press F8.)
+Ctrl+] Increase font size.
+Ctrl+[ Decrease font size.
+Ctrl+= Default font size.
+
+Ctrl-Space Show Auto Completion.
+Ctrl-Shift-Space Show Call Tip.
+Ctrl-Shift-H Complete Text from History.
+
+Ctrl+F Search
+Ctrl+G Search next
+F12 on/off "free-edit" mode
+ For testing only -- This does not preserve markers!
+
+In "Slices Mode":
+Return Insert new line
+Enter (Numpad) Run command in slice
+Ctrl+Return ""
+Shift+Return ""
+
+In "Shell Mode":
+Return or Enter Insert a new line
+Ctrl+Return ""
+Shift+Return ""
+2 Returns in a row Run command in slice
+"""
+
+class SlicesShellFacade:
+ """Simplified interface to all shell-related functionality.
+
+ This is a semi-transparent facade, in that all attributes of other
+ are accessible, even though only some are visible to the user."""
+
+ name = 'SlicesShell Interface'
+ revision = __revision__
+
+ def __init__(self, other):
+ """Create a SlicesShellFacade instance."""
+ d = self.__dict__
+ d['other'] = other
+ d['helpText'] = HELP_TEXT
+ d['this'] = other.this
+
+ def help(self):
+ """Display some useful information about how to use the slices shell."""
+ self.write(self.helpText,type='Output')
+
+ def __getattr__(self, name):
+ if hasattr(self.other, name):
+ return getattr(self.other, name)
+ else:
+ raise AttributeError, name
+
+ def __setattr__(self, name, value):
+ if self.__dict__.has_key(name):
+ self.__dict__[name] = value
+ elif hasattr(self.other, name):
+ setattr(self.other, name, value)
+ else:
+ raise AttributeError, name
+
+ def _getAttributeNames(self):
+ """Return list of magic attributes to extend introspection."""
+ list = [
+ 'about',
+ 'ask',
+ 'autoCallTip',
+ 'autoComplete',
+ 'autoCompleteAutoHide',
+ 'autoCompleteCaseInsensitive',
+ 'autoCompleteIncludeDouble',
+ 'autoCompleteIncludeMagic',
+ 'autoCompleteIncludeSingle',
+ 'callTipInsert',
+ 'clear',
+ 'pause',
+ 'prompt',
+ 'quit',
+ 'redirectStderr',
+ 'redirectStdin',
+ 'redirectStdout',
+ 'run',
+ 'runfile',
+ 'wrap',
+ 'zoom',
+ ]
+ list.sort()
+ return list
+
+DISPLAY_TEXT="""
+Author: %r
+Py Version: %s
+Py Slices Shell Revision: %s
+Py Interpreter Revision: %s
+Python Version: %s
+wxPython Version: %s
+wxPython PlatformInfo: %s
+Platform: %s"""
+
+class SlicesShell(editwindow.EditWindow):
+ """Notebook Shell based on StyledTextCtrl."""
+
+ name = 'SlicesShell'
+ revision = __revision__
+
+ def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
+ introText='', locals=None, InterpClass=None,
+ startupScript=None, execStartupScript=True,
+ showPySlicesTutorial=True,enableShellMode=False,
+ hideFoldingMargin=False, *args, **kwds):
+ """Create Shell instance."""
+ editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
+ self.wrap()
+ if locals is None:
+ import __main__
+ locals = __main__.__dict__
+
+ # Grab these so they can be restored by self.redirect* methods.
+ self.stdin = sys.stdin
+ self.stdout = sys.stdout
+ self.stderr = sys.stderr
+
+ # Import a default interpreter class if one isn't provided.
+ if InterpClass == None:
+ from interpreter import Interpreter
+ else:
+ Interpreter = InterpClass
+
+ # Create a replacement for stdin.
+ self.reader = PseudoFileIn(self.readline, self.readlines)
+ self.reader.input = ''
+ self.reader.isreading = False
+
+ # Set up the interpreter.
+ self.interp = Interpreter(locals=locals,
+ rawin=self.raw_input,
+ stdin=self.reader,
+ stdout=PseudoFileOut(self.writeOut),
+ stderr=PseudoFileErr(self.writeErr),
+ *args, **kwds)
+
+ # Set up the buffer.
+ self.buffer = Buffer()
+ self.id = self.GetId()
+ self.buffer.addEditor(self)
+ self.buffer.name='This shell'
+ self.NeedsCheckForSave=False
+
+ # Find out for which keycodes the interpreter will autocomplete.
+ self.autoCompleteKeys = self.interp.getAutoCompleteKeys()
+
+ # Keep track of the last non-continuation prompt positions.
+ # Removed all references to these... solved a lot of odd bugs...
+ # self.promptPosStart = 0
+ # self.promptPosEnd = 0
+
+ # Keep track of multi-line commands.
+ self.more = False
+
+ # Use Margins to track input / output / slice number
+ self.margins = True
+
+ # For use with forced updates during long-running scripts
+ self.lastUpdate=None
+
+ if self.margins:
+ # margin 1 is already defined for the line numbers
+ # may eventually change it back to 0 like it ought to be...
+ self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
+ self.SetMarginType(3, stc.STC_MARGIN_SYMBOL)
+ self.SetMarginType(4, stc.STC_MARGIN_SYMBOL)
+ self.SetMarginWidth(2, 22)
+ self.SetMarginWidth(3, 22)
+ self.SetMarginWidth(4, 12)
+ self.SetMarginSensitive(2,True)
+ self.SetMarginSensitive(3,True)
+ self.SetMarginSensitive(4,True)
+ self.SetProperty("fold", "1")
+ # tabs are bad, use spaces
+ self.SetProperty("tab.timmy.whinge.level", "4")
+ self.SetMargins(0,0)
+
+
+ self.SetMarginMask(2, GROUPING_MASK | 1<<GROUPING_SELECTING )
+ # Display Markers -24...
+ self.SetMarginMask(3, IO_MASK | 1<<IO_SELECTING | 1<<READLINE_BG | 1<<INPUT_READLINE )
+ self.SetMarginMask(4, stc.STC_MASK_FOLDERS)
+ # Set the mask for the line markers, too...
+ self.SetMarginMask(1, 0)
+
+ if hideFoldingMargin:
+ self.SetMarginWidth(4, 0)
+ self.hideFoldingMargin=hideFoldingMargin
+
+ sel_color="#E0E0E0"
+ grouping_color="black"
+ input_color="red"
+ output_color="blue"
+
+ self.MarkerDefine(GROUPING_SELECTING, stc.STC_MARK_FULLRECT,
+ sel_color, sel_color)
+ self.MarkerDefine(IO_SELECTING, stc.STC_MARK_FULLRECT,
+ sel_color, sel_color)
+
+ self.MarkerDefine(GROUPING_START, stc.STC_MARK_BOXMINUS,
+ "white", grouping_color)
+ self.MarkerDefine(GROUPING_START_FOLDED, stc.STC_MARK_BOXPLUS,
+ "white", grouping_color)
+ self.MarkerDefine(GROUPING_MIDDLE, stc.STC_MARK_VLINE,
+ "white", grouping_color)
+ self.MarkerDefine(GROUPING_END, stc.STC_MARK_LCORNER,
+ "white", grouping_color)
+
+ self.MarkerDefine(READLINE_BG, stc.STC_MARK_FULLRECT,
+ wx.Colour(191,191,191), wx.Colour(191,191,191))
+ self.MarkerDefine(INPUT_READLINE, stc.STC_MARK_CHARACTER+ord('<'),
+ input_color, wx.Colour(191,191,191))
+
+ if enableShellMode:
+ self.mode='ShellMode'
+ else:
+ self.mode='SlicesMode'
+
+ self.execOnNextReturn=False
+ if self.mode=='SlicesMode':
+ self.MarkerDefine(INPUT_START, stc.STC_MARK_BOXMINUS,
+ "white", input_color)
+ self.MarkerDefine(INPUT_START_FOLDED, stc.STC_MARK_BOXPLUS,
+ "white", input_color)
+ self.MarkerDefine(INPUT_MIDDLE, stc.STC_MARK_VLINE,
+ "white", input_color)
+ self.MarkerDefine(INPUT_END, stc.STC_MARK_LCORNER,
+ "white", input_color)
+ elif self.mode=='ShellMode':
+ self.MarkerDefine(INPUT_START, stc.STC_MARK_ARROWS,
+ input_color, "white")
+ self.MarkerDefine(INPUT_START_FOLDED, stc.STC_MARK_BOXPLUS,
+ "white", input_color)
+ self.MarkerDefine(INPUT_MIDDLE, stc.STC_MARK_DOTDOTDOT,
+ input_color, "white")
+ self.MarkerDefine(INPUT_END, stc.STC_MARK_DOTDOTDOT,
+ input_color, "white")
+
+ self.MarkerDefine(OUTPUT_START, stc.STC_MARK_BOXMINUS,
+ "white", output_color)
+ self.MarkerDefine(OUTPUT_START_FOLDED, stc.STC_MARK_BOXPLUS,
+ "white", output_color)
+ self.MarkerDefine(OUTPUT_MIDDLE, stc.STC_MARK_VLINE,
+ "white", output_color)
+ self.MarkerDefine(OUTPUT_END, stc.STC_MARK_LCORNER,
+ "white", output_color)
+
+ self.MarkerDefine(OUTPUT_BG, stc.STC_MARK_BACKGROUND,
+ "white", wx.Colour(242,242,255))
+
+ # Markers for folding margin...
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS,
+ "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS,
+ "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE,
+ "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER,
+ "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED,
+ "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED,
+ "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,
+ "white", "#808080")
+
+ # Create the command history. Commands are added into the
+ # front of the list (ie. at index 0) as they are entered.
+ # self.historyIndex is the current position in the history; it
+ # gets incremented as you retrieve the previous command,
+ # decremented as you retrieve the next, and reset when you hit
+ # Enter. self.historyIndex == -1 means you're on the current
+ # command, not in the history.
+ self.history = []
+ self.historyIndex = -1
+
+ #DNM -- disable these markers...
+ #seb add mode for "free edit"
+ self.noteMode = 0
+ #self.MarkerDefine(0,stc.STC_MARK_ROUNDRECT) # marker for hidden
+ self.searchTxt = ""
+
+ # Assign handlers for keyboard events.
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+
+ self.Bind(wx.stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
+ # TODO : Add a general functions to handle mouse clicks in the
+ # TODO: STC window whose sole purpose is to make it so
+ # TODO: that margin selection becomes unselected...
+
+ # Assign handler for the context menu
+ self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI)
+
+ # Assign handlers for edit events
+ self.Bind(wx.EVT_MENU, lambda evt: self.Cut(), id=wx.ID_CUT)
+ self.Bind(wx.EVT_MENU, lambda evt: self.Copy(), id=wx.ID_COPY)
+ self.Bind(wx.EVT_MENU, lambda evt: self.CopyWithPrompts(), id=frame.ID_COPY_PLUS)
+ self.Bind(wx.EVT_MENU, lambda evt: self.Paste(), id=wx.ID_PASTE)
+ self.Bind(wx.EVT_MENU, lambda evt: self.PasteAndRun(), id=frame.ID_PASTE_PLUS)
+ self.Bind(wx.EVT_MENU, lambda evt: self.SelectAll(), id=wx.ID_SELECTALL)
+ self.Bind(wx.EVT_MENU, lambda evt: self.Clear(), id=wx.ID_CLEAR)
+ self.Bind(wx.EVT_MENU, lambda evt: self.Undo(), id=wx.ID_UNDO)
+ self.Bind(wx.EVT_MENU, lambda evt: self.Redo(), id=wx.ID_REDO)
+
+ # Assign handler for idle time.
+ self.waiting = False
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+ # Display the introductory banner information.
+ self.showIntro(introText)
+
+ outStart,outEnd,inStart,inMiddle,inEnd = [[],[],[],[],[]]
+
+ # Make "executed startup script move to the top..."
+ if showPySlicesTutorial:
+ self.write(tutorialText,'Output')
+ tutStart=5
+ testStart=16
+ outStart=[tutStart,testStart+3]
+ outEnd=[tutStart-1,testStart-1]
+ inStart=[testStart]
+ inMiddle=[testStart+1]
+ inEnd=[testStart+2]
+
+ # Assign some pseudo keywords to the interpreter's namespace.
+ self.setBuiltinKeywords()
+
+ # Add 'shell' to the interpreter's local namespace.
+ self.setLocalShell()
+
+ # Do this last so the user has complete control over their
+ # environment. They can override anything they want.
+ if execStartupScript:
+ if startupScript is None:
+ startupScript = os.environ.get('PYTHONSTARTUP')
+ self.execStartupScript(startupScript)
+ else:
+ self.prompt()
+
+ outStart+=[0]
+ outEnd+=[self.GetLineCount()-2]
+ inStart+=[self.GetLineCount()-1]
+ # Set all the line markers to the proper initial states...
+ for i in range(self.GetLineCount()):
+ self.clearGroupingMarkers(i)
+ self.clearIOMarkers(i)
+ if i in outStart:
+ self.MarkerAdd(i,GROUPING_START)
+ self.MarkerAdd(i,OUTPUT_START)
+ # Background color is confusing for tutorial... skip it!
+ #self.MarkerAdd(i,OUTPUT_BG)
+ elif i in outEnd:
+ self.MarkerAdd(i,GROUPING_END)
+ self.MarkerAdd(i,OUTPUT_END)
+ #self.MarkerAdd(i,OUTPUT_BG)
+ elif i in inStart:
+ self.MarkerAdd(i,GROUPING_START)
+ self.MarkerAdd(i,INPUT_START)
+ elif i in inMiddle:
+ self.MarkerAdd(i,GROUPING_MIDDLE)
+ self.MarkerAdd(i,INPUT_MIDDLE)
+ elif i in inEnd:
+ self.MarkerAdd(i,GROUPING_END)
+ self.MarkerAdd(i,INPUT_END)
+ else:
+ self.MarkerAdd(i,GROUPING_MIDDLE)
+ self.MarkerAdd(i,OUTPUT_MIDDLE)
+ #self.MarkerAdd(i,OUTPUT_BG)
+
+ self.SliceSelection=False
+ self.runningSlice=None
+
+ ## NOTE: See note at bottom of this file...
+ ## #seb: File drag and drop
+ ## self.SetDropTarget( FileDropTarget(self) )
+
+ #ADD UNDO
+ # Everywhere "ADD UNDO" appears, there is new code to handle markers
+ self.EmptyUndoBuffer()
+
+ wx.CallAfter(self.ScrollToLine, 0)
+
+ def ToggleShellMode(self,enableShellMode=None):
+ if enableShellMode==None:
+ if self.mode=='ShellMode': self.mode='SlicesMode'
+ elif self.mode=='SlicesMode': self.mode='ShellMode'
+ elif enableShellMode:
+ self.mode='ShellMode'
+ else:
+ self.mode='SlicesMode'
+
+ input_color="red"
+ if self.mode=='SlicesMode':
+ self.MarkerDefine(INPUT_START, stc.STC_MARK_BOXMINUS,
+ "white", input_color)
+ self.MarkerDefine(INPUT_START_FOLDED, stc.STC_MARK_BOXPLUS,
+ "white", input_color)
+ self.MarkerDefine(INPUT_MIDDLE, stc.STC_MARK_VLINE,
+ "white", input_color)
+ self.MarkerDefine(INPUT_END, stc.STC_MARK_LCORNER,
+ "white", input_color)
+ elif self.mode=='ShellMode':
+ self.MarkerDefine(INPUT_START, stc.STC_MARK_ARROWS,
+ input_color, "white")
+ self.MarkerDefine(INPUT_START_FOLDED, stc.STC_MARK_BOXPLUS,
+ "white", input_color)
+ self.MarkerDefine(INPUT_MIDDLE, stc.STC_MARK_DOTDOTDOT,
+ input_color, "white")
+ self.MarkerDefine(INPUT_END, stc.STC_MARK_DOTDOTDOT,
+ input_color, "white")
+
+ def ToggleFoldingMargin(self,hideFoldingMargin=None):
+ if hideFoldingMargin==None:
+ self.hideFoldingMargin = not self.hideFoldingMargin
+ else:
+ self.hideFoldingMargin = hideFoldingMargin
+
+ if self.hideFoldingMargin:
+ self.SetMarginWidth(4, 0)
+ else:
+ self.SetMarginWidth(4, 12)
+
+ def clearHistory(self):
+ self.history = []
+ self.historyIndex = -1
+ dispatcher.send(signal="SlicesShell.clearHistory")
+
+
+ def destroy(self):
+ del self.interp
+
+ def setFocus(self):
+ """Set focus to the slices shell."""
+ self.SetFocus()
+
+ def OnIdle(self, event):
+ """Free the CPU to do other things."""
+ if self.waiting:
+ time.sleep(0.05)
+ event.Skip()
+
+ def showIntro(self, text=''):
+ """Display introductory text in the slices shell."""
+ if text:
+ self.write(text,type='Output')
+ try:
+ if self.interp.introText:
+ if text and not text.endswith(os.linesep):
+ self.write(os.linesep,type='Output')
+ self.write(self.interp.introText,type='Output')
+ except AttributeError:
+ pass
+
+ def setBuiltinKeywords(self):
+ """Create pseudo keywords as part of builtins.
+
+ This sets "close", "exit" and "quit" to a helpful string.
+ """
+ import __builtin__
+ __builtin__.close = __builtin__.exit = __builtin__.quit = \
+ 'Click on the close button to leave the application.'
+ __builtin__.cd = cd
+ __builtin__.ls = ls
+ __builtin__.pwd = pwd
+ __builtin__.sx = sx
+
+
+ def quit(self):
+ """Quit the application."""
+ # XXX Good enough for now but later we want to send a close event.
+ # In the close event handler we can make sure they want to
+ # quit. Other applications, like PythonCard, may choose to
+ # hide rather than quit so we should just post the event and
+ # let the surrounding app decide what it wants to do.
+ self.write('Click on the close button to leave the application.',
+ type='Output')
+
+
+ def setLocalShell(self):
+ """Add 'slicesshell' to locals as reference to ShellFacade instance."""
+ self.interp.locals['slicesshell'] = SlicesShellFacade(other=self)
+
+
+ def execStartupScript(self, startupScript):
+ """Execute the user's PYTHONSTARTUP script if they have one."""
+ if startupScript and os.path.isfile(startupScript):
+ text = 'Startup script executed: ' + startupScript
+ self.push('print %r; execfile(%r)' % (text, startupScript))
+ self.interp.startupScript = startupScript
+ else:
+ self.push('')
+
+
+ def about(self):
+ """Display information about Py."""
+ text = DISPLAY_TEXT % \
+ (__author__, VERSION, self.revision, self.interp.revision,
+ sys.version.split()[0], wx.VERSION_STRING, str(wx.PlatformInfo),
+ sys.platform)
+ self.write(text.strip(),type='Output')
+
+ def BreakTextIntoCommands(self,text):
+ """Turn a text block into multiple multi-line commands."""
+
+ #text = text.lstrip() # This should not be done!
+ text = self.fixLineEndings(text)
+ text = self.lstripPrompt(text)
+ text = text.replace(os.linesep, '\n')
+ lines = text.split('\n')
+
+ continuations = testForContinuations(text)
+
+ if len(continuations)==2: # Error case...
+ return None,continuations[1]
+ elif len(continuations)==4:
+ stringContinuationList,indentationBlockList, \
+ lineContinuationList,parentheticalContinuationList = continuations
+
+ commands = []
+ command = ''
+ for j,line in enumerate(lines):
+ lstrip = line.lstrip()
+
+ # Get the first alnum word:
+ first_word=[]
+ for i in lstrip:
+ if i.isalnum():
+ first_word.append(i)
+ else:
+ break
+ first_word = ''.join(first_word)
+
+ # Continue the command if it is blank, has indentation,
+ # starts with else, elif,except, or finally
+ # or previous line had a line continuation \
+
+ if j==0:
+ stringCont = False
+ lineCont=False
+ else:
+ stringCont = stringContinuationList[j-1]
+ lineCont = lineContinuationList[j-1]
+
+ if line.strip() == '' or lstrip != line or \
+ first_word in ['else','elif','except','finally'] or \
+ stringCont or lineCont:
+ # Multiline command. Add to the command.
+ command += '\n'
+ command += line
+ else:
+ # New command.
+ if command:
+ # Add the previous command to the list.
+ commands.append(command)
+ # Start a new command, which may be multiline.
+ command = line
+
+ commands.append(command)
+
+ return commands
+
+ def MarkerSet(self,line,markerBitsSet):
+ """MarkerSet is the Set command for MarkerGet"""
+ markerBits=self.MarkerGet(line)
+
+ numMarkers=14
+ for i in range(numMarkers):
+ if (markerBitsSet & (1<<i)) and not (markerBits & (1<<i)):
+ self.MarkerAdd(line,i)
+ elif not (markerBitsSet & (1<<i)) and (markerBits & (1<<i)):
+ self.MarkerDelete(line,i)
+ def GetGroupingSlice(self,line_num=None):
+ """Get the start/stop lines for the slice based on any line in the slice"""
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+
+ num_lines=self.GetLineCount()
+
+ for i in range(line_num,-1,-1):
+ if self.MarkerGet(i) & (1<<GROUPING_START | 1<<GROUPING_START_FOLDED):
+ break
+ start_line=i
+
+ addition=0
+
+ for i in range(line_num,num_lines):
+ if self.MarkerGet(i) & 1<<GROUPING_END:
+ break
+ elif (i>line_num) and ( self.MarkerGet(i)
+ & (1<<GROUPING_START | 1<<GROUPING_START_FOLDED) ):
+ addition=-1
+ break # the solo case...
+ stop_line=i+addition
+
+ return start_line,stop_line
+
+ def GetIOSlice(self,line_num=None):
+ """Get the start/stop lines for the slice based on any line in the slice"""
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+
+ num_lines=self.GetLineCount()
+
+ for i in range(line_num,-1,-1):
+ if self.MarkerGet(i) & IO_ANY_START_MASK:
+ break
+ start_line=i
+
+ addition=0
+
+ for i in range(line_num,num_lines):
+ if self.MarkerGet(i) & IO_END_MASK:
+ break
+ elif (i>line_num) and (self.MarkerGet(i) & IO_ANY_START_MASK):
+ addition=-1
+ break # the solo case...
+ stop_line=i+addition
+
+ return start_line,stop_line
+
+ def FoldGroupingSlice(self,line_num=None):
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+
+ start,end=self.GetGroupingSlice(line_num)
+ self.HideLines(start+1,end)
+ marker=self.MarkerGet(start)
+ self.clearGroupingMarkers(start)
+ self.MarkerAdd(start,GROUPING_START_FOLDED)
+ self.clearIOMarkers(start)
+ if marker & ( 1<<INPUT_START | 1<<INPUT_START_FOLDED ):
+ self.MarkerAdd(start,INPUT_START_FOLDED)
+ elif marker & ( 1<<OUTPUT_START | 1<<OUTPUT_START_FOLDED ):
+ self.MarkerAdd(start,OUTPUT_START_FOLDED)
+ self.MarkerAdd(start,OUTPUT_BG)
+ else:
+ pass #print 'Bad Markers!!!'
+ def FoldIOSlice(self,line_num=None):
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+
+ start,end=self.GetIOSlice(line_num)
+ self.HideLines(start+1,end)
+ marker=self.MarkerGet(start)
+ if (self.MarkerGet(start) & \
+ (1<<GROUPING_START | 1<<GROUPING_START_FOLDED )) and \
+ (self.MarkerGet(end) & 1<<GROUPING_END):
+ self.clearGroupingMarkers(start)
+ self.MarkerAdd(start,GROUPING_START_FOLDED)
+ self.clearIOMarkers(start)
+ if marker & ( 1<<INPUT_START | 1<<INPUT_START_FOLDED ):
+ self.MarkerAdd(start,INPUT_START_FOLDED)
+ elif marker & ( 1<<OUTPUT_START | 1<<OUTPUT_START_FOLDED ):
+ self.MarkerAdd(start,OUTPUT_START_FOLDED)
+ self.MarkerAdd(start,OUTPUT_BG)
+ else:
+ pass #print 'Bad Markers!!!'
+ def UnFoldGroupingSlice(self,line_num=None):
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+
+ start,end=self.GetGroupingSlice(line_num)
+ self.ShowLines(start+1,end)
+ self.clearGroupingMarkers(start)
+ self.MarkerAdd(start,GROUPING_START)
+ for i in range(start,end):
+ marker=self.MarkerGet(i)
+ if marker & (1<<INPUT_START | 1<<INPUT_START_FOLDED):
+ self.clearIOMarkers(i)
+ self.MarkerAdd(i,INPUT_START)
+ elif marker & (1<<OUTPUT_START | 1<<OUTPUT_START_FOLDED):
+ self.clearIOMarkers(i)
+ self.MarkerAdd(i,OUTPUT_START)
+ self.MarkerAdd(i,OUTPUT_BG)
+
+ def UnFoldIOSlice(self,line_num=None):
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+
+ start,end=self.GetIOSlice(line_num)
+ self.ShowLines(start+1,end)
+ marker=self.MarkerGet(start)
+ if (self.MarkerGet(start) & \
+ (1<<GROUPING_START | 1<<GROUPING_START_FOLDED )) and \
+ (self.MarkerGet(end) & 1<<GROUPING_END):
+ self.clearGroupingMarkers(start)
+ self.MarkerAdd(start,GROUPING_START)
+ self.clearIOMarkers(start)
+ if marker & 1<<INPUT_START_FOLDED:
+ self.MarkerAdd(start,INPUT_START)
+ elif marker & 1<<OUTPUT_START_FOLDED:
+ self.MarkerAdd(start,OUTPUT_START)
+ self.MarkerAdd(start,OUTPUT_BG)
+
+ def DeleteOutputSlicesAfter(self,line_num=None):
+ """Delete all outputs after an input"""
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+
+ num_lines=self.GetLineCount()
+
+ if self.MarkerGet(line_num) & OUTPUT_MASK:
+ #print 'You can only run "DeleteOutputSlicesAfter" from an Input slice!'
+ return
+
+ startIn,endIn=self.GetIOSlice(line_num)
+ startGrouping,endGrouping=self.GetGroupingSlice(line_num)
+
+ if endIn<endGrouping:
+ self.SetSelection(self.PositionFromLine(endIn+1),
+ self.PositionFromLine(endGrouping+1))
+ self.ReplaceSelection('',sliceDeletion=True)
+
+ new_pos=self.GetLineEndPosition(line_num)
+ self.SetCurrentPos(new_pos)
+ self.SetSelection(new_pos,new_pos)
+
+ def SplitSlice(self,line_num=None):
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+
+ start_num,end_num=self.GetIOSlice(line_num)
+
+ if self.MarkerGet(line_num) & INPUT_MASK:
+ type='Input'
+ start=INPUT_START
+ end=INPUT_END
+ splitGrouping=True
+ elif self.MarkerGet(line_num) & OUTPUT_MASK:
+ type='Output'
+ start=OUTPUT_START
+ end=OUTPUT_END
+ splitGrouping=False
+
+ if start_num==end_num:
+ return # Can't split one line!
+ elif start_num==line_num:
+ self.clearIOMarkers(line_num+1)
+ self.MarkerAdd(line_num+1,start)
+ if type=='Output': self.MarkerAdd(line_num+1,OUTPUT_BG)
+ if splitGrouping:
+ self.clearGroupingMarkers(line_num+1)
+ self.MarkerAdd(line_num+1,GROUPING_START)
+ else:
+ self.clearIOMarkers(line_num)
+ self.MarkerAdd(line_num,start)
+ if type=='Output': self.MarkerAdd(line_num,OUTPUT_BG)
+ if splitGrouping:
+ self.clearGroupingMarkers(line_num)
+ self.MarkerAdd(line_num,GROUPING_START)
+ if line_num-1>start_num:
+ self.clearIOMarkers(line_num-1)
+ self.MarkerAdd(line_num-1,end)
+ if type=='Output': self.MarkerAdd(line_num-1,OUTPUT_BG)
+ if splitGrouping:
+ self.clearGroupingMarkers(line_num-1)
+ self.MarkerAdd(line_num-1,GROUPING_END)
+
+ def BackspaceWMarkers(self,force=False):
+ # Warning: This is not good at checking for bad markers!
+ c_before=self.GetCharAt(self.GetCurrentPos() - 1)
+ c_after=self.GetCharAt(self.GetCurrentPos())
+
+ if c_before==0:
+ # Disallow deleting the first line or it will destroy the markers...
+ return False
+ elif c_before in (ord('\n'),ord('\r')):
+ line_num=self.GetCurrentLine()
+
+ marker=self.MarkerGet(line_num)
+ marker_before=self.MarkerGet(line_num-1)
+ marker_after=self.MarkerGet(line_num+1)
+ if marker_before & ( 1<<GROUPING_END ) :
+ return False # Disallow deleting lines between slices...
+ elif marker & ( 1<<GROUPING_START | 1<<GROUPING_START_FOLDED ) :
+ return False # Disallow deleting lines between slices...
+ else:
+ if marker_before & ( 1<<GROUPING_START | 1<<GROUPING_START_FOLDED ) :
+ self.clearGroupingMarkers(line_num)
+ elif marker & ( 1<<GROUPING_END ) :
+ self.clearGroupingMarkers(line_num-1)
+
+ if (marker_before & 1<<INPUT_END) and force:
+ # Special case for use in processLine
+ self.clearIOMarkers(line_num)
+ elif marker_before & (1<<INPUT_END | 1<<OUTPUT_END):
+ return False # Disallow deleting lines between slices...
+ elif marker & ( 1<<INPUT_START | 1<<INPUT_START_FOLDED ) :
+ return False # Disallow deleting lines between slices...
+ else:
+ if marker_before & (1<<INPUT_START | 1<<INPUT_START_FOLDED |
+ 1<<OUTPUT_START | 1<<OUTPUT_START_FOLDED):
+ self.clearIOMarkers(line_num)
+ elif marker & ( 1<<INPUT_END | 1<<OUTPUT_END ) :
+ self.clearIOMarkers(line_num-1)
+
+ return True # If everything went well, return True and do the delete...
+
+ def ForwardDeleteWMarkers(self):
+ c_before=self.GetCharAt(self.GetCurrentPos() - 1)
+ c_after=self.GetCharAt(self.GetCurrentPos())
+ if c_after==0:
+ # Disallow deleting the first line or it will destroy the markers...
+ return False
+ elif c_after in (ord('\n'),ord('\r')):
+ line_num=self.GetCurrentLine()
+
+ marker=self.MarkerGet(line_num)
+ marker_before=self.MarkerGet(line_num-1)
+ marker_after=self.MarkerGet(line_num+1)
+ if marker & ( 1<<GROUPING_END ) :
+ return False # Disallow deleting lines between slices...
+ elif marker_after & ( 1<<GROUPING_START | 1<<GROUPING_START_FOLDED ) :
+ return False # Disallow deleting lines between slices...
+ else:
+ if marker & ( 1<<GROUPING_START | 1<<GROUPING_START_FOLDED ) :
+ self.clearGroupingMarkers(line_num+1)
+ elif marker_after & ( 1<<GROUPING_END ) :
+ self.clearGroupingMarkers(line_num)
+
+ if marker & ( 1<<INPUT_END | 1<<OUTPUT_END ) :
+ return False # Disallow deleting lines between slices...
+ elif marker_after & ( 1<<INPUT_START | 1<<INPUT_START_FOLDED ) :
+ return False # Disallow deleting lines between slices...
+ else:
+ if marker & (1<<INPUT_START | 1<<INPUT_START_FOLDED |
+ 1<<OUTPUT_START | 1<<OUTPUT_START_FOLDED) :
+ self.clearIOMarkers(line_num+1)
+ elif marker_after & ( 1<<INPUT_END | 1<<OUTPUT_END ) :
+ self.clearIOMarkers(line_num)
+
+ return True
+
+ def GetIOSelection(self):
+ started=False
+ start=0
+ end=self.GetLineCount()-1
+ type=None
+ for i in range(self.GetLineCount()):
+ if self.MarkerGet(i) & 1<<IO_SELECTING:
+ if started==False:
+ start=i
+ if self.MarkerGet(i) & INPUT_MASK:
+ type='input'
+ elif self.MarkerGet(i) & OUTPUT_MASK:
+ type='output'
+ else:
+ if self.MarkerGet(i) & INPUT_MASK:
+ if type=='output':
+ end=i-1
+ break
+ elif self.MarkerGet(i) & OUTPUT_MASK:
+ if type=='input':
+ end=i-1
+ break
+ started=True
+ elif started==True:
+ end=i-1
+ break
+
+ if started==False:
+ #print 'No Selection!!'
+ self.SliceSelection=False
+
+ return start,end
+
+ def MergeAdjacentSlices(self):
+ """This function merges all adjacent selected slices.\n""" + \
+ """Right now, only IO Merging is allowed."""
+ started=False
+ start=0
+ end=self.GetLineCount()-1
+ type=None
+ for i in range(self.GetLineCount()):
+ if self.MarkerGet(i) & 1<<IO_SELECTING:
+ if started==False:
+ start=i
+ if self.MarkerGet(i) & INPUT_MASK:
+ type='input'
+ elif self.MarkerGet(i) & OUTPUT_MASK:
+ type='output'
+ else:
+ if self.MarkerGet(i) & INPUT_MASK:
+ if type=='output':
+ end=i-1
+ break
+ else:
+ self.clearIOMarkers(i)
+ self.clearGroupingMarkers(i)
+ self.MarkerAdd(i,INPUT_MIDDLE)
+ self.MarkerAdd(i,GROUPING_MIDDLE)
+ elif self.MarkerGet(i) & OUTPUT_MASK:
+ if type=='input':
+ end=i-1
+ break
+ else:
+ self.clearIOMarkers(i)
+ self.clearGroupingMarkers(i)
+ self.MarkerAdd(i,OUTPUT_MIDDLE)
+ self.MarkerAdd(i,OUTPUT_BG)
+ self.MarkerAdd(i,GROUPING_MIDDLE)
+ started=True
+ elif started==True:
+ end=i-1
+ break
+
+ if started and end!=start:
+ self.clearIOMarkers(end)
+ self.clearGroupingMarkers(end)
+ if type=='input':
+ self.MarkerAdd(end,INPUT_END)
+ if end+1<self.GetLineCount():
+ if self.MarkerGet(end+1) & OUTPUT_MASK:
+ self.MarkerAdd(end,GROUPING_MIDDLE)
+ else:
+ self.MarkerAdd(end,GROUPING_END)
+ else:
+ self.MarkerAdd(end,GROUPING_END)
+ else:
+ if self.MarkerGet(start) & 1<<GROUPING_END:
+ self.clearGroupingMarkers(start)
+ self.MarkerAdd(start,GROUPING_MIDDLE)
+ self.MarkerAdd(end,OUTPUT_END)
+ self.MarkerAdd(end,OUTPUT_BG)
+ self.MarkerAdd(end,GROUPING_END)
+
+
+ def SliceSelectionDelete(self):
+ """Deletion of any selected and possibly discontinuous slices."""
+ if not self.SliceSelection:
+ return
+
+ # collect the line numbers to be deleted...
+ selectedSlices=[]
+ start,end=None,None
+ for i in range(self.GetLineCount()):
+ if self.MarkerGet(i) & (1<<GROUPING_SELECTING | 1<<IO_SELECTING):
+ if start==None:
+ start=i
+ end=i
+ elif start!=None:
+ selectedSlices.append([start,end])
+ start,end=None,None
+ if start!=None:
+ selectedSlices.append([start,end])
+
+ # Unselect everything
+ self.MarginUnselectAll()
+ self.SliceSelection=False
+
+ # Going in reverse, delete the selections, fixing the markers as we go...
+ for i in range(len(selectedSlices)-1,-1,-1):
+ self.SetSelection(self.PositionFromLine(selectedSlices[i][0]),
+ self.GetLineEndPosition(selectedSlices[i][1])+1)
+
+ markerNext = self.MarkerGet(selectedSlices[i][1]+1)
+
+ self.ReplaceSelection('',sliceDeletion=True)
+
+ cur_line=self.GetCurrentLine()
+
+ # If we've made a mess of the grouping markers, clean it up...
+ if ((self.MarkerGet(cur_line-1) & 1<<GROUPING_END) and
+ (self.MarkerGet(cur_line) & ( 1<<GROUPING_MIDDLE | 1<<GROUPING_END ) )):
+ self.clearGroupingMarkers(cur_line)
+ self.MarkerAdd(cur_line,GROUPING_START)
+ elif (( self.MarkerGet(cur_line-1) & 1<<GROUPING_MIDDLE ) and
+ ( self.MarkerGet(cur_line) &
+ ( 1<<GROUPING_START | 1<<GROUPING_START_FOLDED ) )):
+ self.clearGroupingMarkers(cur_line-1)
+ self.MarkerAdd(cur_line-1,GROUPING_END)
+
+ if markerNext & 1<<OUTPUT_START:
+ self.clearIOMarkers(cur_line)
+ self.MarkerAdd(cur_line,OUTPUT_START)
+ self.MarkerAdd(cur_line,OUTPUT_BG)
+ elif markerNext & 1<<OUTPUT_START_FOLDED:
+ self.clearIOMarkers(cur_line)
+ self.MarkerAdd(cur_line,OUTPUT_START_FOLDED)
+ self.MarkerAdd(cur_line,OUTPUT_BG)
+
+ return
+
+ def OnChar(self, event):
+ """Keypress event handler.
+
+ Only receives an event if OnKeyDown calls event.Skip() for the
+ corresponding event."""
+
+ if self.noteMode:
+ event.Skip()
+ return
+
+ # Prevent modification of output slices
+ if not self.CanEdit():
+ return
+ key = event.GetKeyCode()
+ currpos = self.GetCurrentPos()
+ stoppos = self.PositionFromLine(self.GetCurrentLine())
+
+ # Return (Enter) needs to be ignored in this handler.
+ if key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
+ pass
+ elif key in self.autoCompleteKeys:
+ # Usually the dot (period) key activates auto completion.
+ # Get the command between the prompt and the cursor. Add
+ # the autocomplete character to the end of the command.
+ if self.AutoCompActive():
+ self.AutoCompCancel()
+ command = self.GetTextRange(stoppos, currpos) + chr(key)
+
+ # write with undo wrapper...
+ cpos=self.GetCurrentPos()
+ s=chr(key)
+ #ADD UNDO
+ self.UpdateUndoHistoryBefore('insert',s,cpos,cpos+len(s),
+ forceNewAction=False)
+ self.write(s,type='Input')
+ self.UpdateUndoHistoryAfter()
+
+ if self.autoComplete:
+ self.autoCompleteShow(command)
+ elif key == ord('('):
+ # The left paren activates a call tip and cancels an
+ # active auto completion.
+ if self.AutoCompActive():
+ self.AutoCompCancel()
+ # Get the command between the prompt and the cursor. Add
+ # the '(' to the end of the command.
+ self.ReplaceSelection('')
+ command = self.GetTextRange(stoppos, currpos) + '('
+
+ # write with undo wrapper...
+ cpos=self.GetCurrentPos()
+ s='('
+ self.UpdateUndoHistoryBefore('insert',s,cpos,cpos+len(s),
+ forceNewAction=True)
+ self.undoHistory[self.undoIndex]['allowsAppend']=True
+ self.write(s,type='Input')
+ self.UpdateUndoHistoryAfter()
+
+ self.autoCallTipShow(command,
+ self.GetCurrentPos() == self.GetTextLength())
+ else:
+ # Allow the normal event handling to take place.
+ # Use undo wrapper
+ cpos=self.GetCurrentPos()
+ try:
+ s=chr(key)
+ self.UpdateUndoHistoryBefore('insert',s,cpos,cpos+len(s))
+ event.Skip()
+ self.UpdateUndoHistoryAfter()
+ except:
+ event.Skip()
+
+ def AutoCompActiveCallback(self):
+ numChars=self.GetTextLength()-self.TotalLengthForAutoCompActiveCallback
+ if numChars==0:
+ self.undoIndex-=1
+ del(self.undoHistory[-1])
+ else:
+ uH=self.undoHistory
+ uI=self.undoIndex
+ cpos=uH[uI]['posStart']
+ s=''.join([chr(self.GetCharAt(cpos+i)) for i in range(numChars)])
+ s.replace(os.linesep,'\n')
+ self.undoHistory[self.undoIndex]['charList'] = s
+ self.undoHistory[self.undoIndex]['posEnd'] = cpos + numChars
+ self.undoHistory[self.undoIndex]['numLines'] = len(s.split('\n'))
+ self.UpdateUndoHistoryAfter()
+
+ def OnKeyDown(self, event):
+ """Key down event handler."""
+
+ key = event.GetKeyCode()
+ # If the auto-complete window is up let it do its thing.
+ if self.AutoCompActive():
+ if key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
+ cpos=self.GetCurrentPos()
+ self.UpdateUndoHistoryBefore('insert','dummy',cpos,cpos+5,
+ forceNewAction=True)
+ self.undoHistory[self.undoIndex]['allowsAppend'] = True
+ self.TotalLengthForAutoCompActiveCallback=self.GetTextLength()
+ event.Skip()
+ wx.CallAfter(self.AutoCompActiveCallback)
+ if key in [wx.WXK_DELETE,wx.WXK_BACK]:
+ self.AutoCompCancel()
+ else:
+ event.Skip()
+ return
+
+ #DNM
+ # Prevent modification of output slices
+ controlDown = event.ControlDown()
+ altDown = event.AltDown()
+ shiftDown = event.ShiftDown()
+ currpos = self.GetCurrentPos()
+ endpos = self.GetTextLength()
+ selecting = self.GetSelectionStart() != self.GetSelectionEnd()
+
+ if key == wx.WXK_F12: #seb
+ if self.noteMode:
+ # self.promptPosStart not used anyway - or ?
+## # We don't need to do this any more!
+## self.promptPosEnd = self.PositionFromLine(self.GetLineCount()-1 ) +
+## len(str(sys.ps1))
+## self.GotoLine(self.GetLineCount())
+## self.GotoPos(self.promptPosEnd)
+## self.prompt() #make sure we have a prompt
+ self.SetCaretForeground("black")
+ self.SetCaretWidth(1) #default
+ self.SetCaretPeriod(500) #default
+ else:
+ self.SetCaretForeground("red")
+ self.SetCaretWidth(4)
+ self.SetCaretPeriod(0) #steady
+
+ self.noteMode = not self.noteMode
+ return
+ if self.noteMode:
+ event.Skip()
+ return
+
+ doLineBreak=False
+ doSubmitCommand=False
+ doPass=False
+ # Return is used to insert a line break.
+ # In Shell Mode, hit Return or Enter twice to submit a command
+ if ((not controlDown and not shiftDown and not altDown) and
+ key in [wx.WXK_RETURN,]):
+ if self.mode=='SlicesMode':
+ doLineBreak=True
+ elif self.mode=='ShellMode':
+ startLine,endLine = self.GetIOSlice()
+ startpos = self.PositionFromLine(startLine)
+ endpos = self.GetLineEndPosition(endLine)
+ command = self.GetTextRange(startpos, endpos)
+ strCont,indentBlock,lineCont,parenCont = testForContinuations(command,ignoreErrors=True)
+
+ lastLine = command.split('\n')[-1]
+ if lastLine.lstrip()=='': # all whitespace...
+ stillIndented=False
+ elif lastLine[0]==' ':
+ stillIndented=True
+ else:
+ stillIndented=False
+
+ if strCont[-1] or indentBlock[-1] or lineCont[-1] or \
+ parenCont[-1]:
+ doLineBreak=True
+ elif stillIndented:
+ new_pos=self.GetLineEndPosition(endLine)
+ self.SetCurrentPos(new_pos)
+ self.SetSelection(new_pos,new_pos)
+ doLineBreak=True
+ elif self.GetCurrentLine()!=endLine:
+ new_pos=self.GetLineEndPosition(endLine)
+ self.SetCurrentPos(new_pos)
+ self.SetSelection(new_pos,new_pos)
+ doPass = True
+ else:
+ doSubmitCommand=True
+ # Enter (Shift/Ctrl + Enter/Return) submits a command to the interpreter.
+ # In Shell Mode, hit Return or Enter twice to submit a command
+ elif ( key in [wx.WXK_NUMPAD_ENTER,] or
+ ( (shiftDown or controlDown) and key in [wx.WXK_RETURN,
+ wx.WXK_NUMPAD_ENTER] ) ):
+ if self.mode=='SlicesMode':
+ doSubmitCommand=True
+ elif self.mode=='ShellMode':
+ doLineBreak=True
+
+ #Only relevant in ShellMode...
+
+ if doPass:
+ pass
+ elif doLineBreak or doSubmitCommand:
+ if self.CallTipActive():
+ self.CallTipCancel()
+ elif self.SliceSelection:
+ for i in range(self.GetLineCount()):
+ if self.MarkerGet(i) & 1<<GROUPING_SELECTING:
+ self.DoMarginClick(i, 2, shiftDown, controlDown)
+ break
+ elif self.MarkerGet(i) & 1<<IO_SELECTING:
+ self.DoMarginClick(i, 3, shiftDown, controlDown)
+ break
+ elif doLineBreak:
+ self.insertLineBreak()
+ #Only relevant in ShellMode...
+ elif doSubmitCommand:
+ self.DeleteOutputSlicesAfter()
+ self.processLine()
+
+ # Let Ctrl-Alt-* get handled normally.
+ elif controlDown and altDown:
+ event.Skip()
+
+ # Clear the current, unexecuted command.
+ elif key == wx.WXK_ESCAPE:
+ if self.CallTipActive():
+ event.Skip()
+ # Clear the current command
+ elif key == wx.WXK_BACK and controlDown and shiftDown:
+ self.clearCommand()
+
+ # Increase font size.
+ elif controlDown and key in (ord(']'), wx.WXK_NUMPAD_ADD):
+ dispatcher.send(signal='FontIncrease')
+
+ # Decrease font size.
+ elif controlDown and key in (ord('['), wx.WXK_NUMPAD_SUBTRACT):
+ dispatcher.send(signal='FontDecrease')
+
+ # Default font size.
+ elif controlDown and key in (ord('='), wx.WXK_NUMPAD_DIVIDE):
+ dispatcher.send(signal='FontDefault')
+
+ # Cut to the clipboard.
+ elif (controlDown and key in (ord('X'), ord('x'))) \
+ or (shiftDown and key == wx.WXK_DELETE):
+ self.Cut()
+
+ # Copy to the clipboard.
+ elif controlDown and not shiftDown \
+ and key in (ord('C'), ord('c'), wx.WXK_INSERT):
+ self.Copy()
+
+ # Copy to the clipboard, including prompts.
+ elif controlDown and shiftDown \
+ and key in (ord('C'), ord('c'), wx.WXK_INSERT):
+ self.CopyWithPrompts()
+
+ # Copy to the clipboard, including prefixed prompts.
+ elif altDown and not controlDown \
+ and key in (ord('C'), ord('c'), wx.WXK_INSERT):
+ self.CopyWithPromptsPrefixed()
+
+ # Home needs to be aware of the prompt.
+ elif controlDown and key == wx.WXK_HOME:
+ # Go to the beginning of the IO Slice
+ curLine = self.GetCurrentLine()
+ IOstart = self.GetIOSlice(curLine)[0]
+ home = self.PositionFromLine(IOstart)
+ if currpos == home and \
+ IOstart > 0:
+ home = self.PositionFromLine(self.GetIOSlice(curLine-1)[0])
+ self.SetCurrentPos(home)
+ if not selecting and not shiftDown:
+ self.SetAnchor(home)
+ self.EnsureCaretVisible()
+
+ elif controlDown and key == wx.WXK_END:
+ curLine = self.GetCurrentLine()
+ IOend = self.GetIOSlice(curLine)[1]
+ end = self.GetLineEndPosition(IOend)
+ if currpos == end and \
+ IOend < self.GetLineCount()-1:
+ end = self.GetLineEndPosition(self.GetIOSlice(curLine+1)[1])
+ self.SetCurrentPos(end)
+ if not selecting and not shiftDown:
+ self.SetAnchor(end)
+ self.EnsureCaretVisible()
+
+ elif controlDown and key == wx.WXK_PAGEUP:
+ pos=0
+ if currpos > pos:
+ self.SetCurrentPos(pos)
+ if not selecting and not shiftDown:
+ self.SetAnchor(pos)
+ self.EnsureCaretVisible()
+
+ elif controlDown and key == wx.WXK_PAGEDOWN:
+ pos = self.GetLineEndPosition(self.GetLineCount()-1)
+ if currpos < pos:
+ self.SetCurrentPos(pos)
+ if not selecting and not shiftDown:
+ self.SetAnchor(pos)
+ self.EnsureCaretVisible()
+
+ elif selecting and key not in NAVKEYS and not self.CanEdit():
+ pass
+
+ # Paste from the clipboard.
+ elif (controlDown and not shiftDown and key in (ord('V'), ord('v'))) \
+ or (shiftDown and not controlDown and key == wx.WXK_INSERT):
+ self.Paste()
+
+ # Paste from the clipboard, run commands.
+ elif controlDown and shiftDown and \
+ key in (ord('V'), ord('v')) and self.CanEdit():
+ self.PasteAndRun()
+
+ # Replace with the previous command from the history buffer.
+ elif (controlDown and not shiftDown and key == wx.WXK_UP) \
+ or (altDown and key in (ord('P'), ord('p'))) and self.CanEdit():
+ self.OnHistoryReplace(step=+1)
+
+ # Replace with the next command from the history buffer.
+ elif (controlDown and not shiftDown and key == wx.WXK_DOWN) \
+ or (altDown and key in (ord('N'), ord('n'))) and self.CanEdit():
+ self.OnHistoryReplace(step=-1)
+
+ # Insert the previous command from the history buffer.
+ elif (controlDown and shiftDown and key == wx.WXK_UP) and \
+ self.CanEdit():
+ self.OnHistoryInsert(step=+1)
+
+ # Insert the next command from the history buffer.
+ elif (controlDown and shiftDown and key == wx.WXK_DOWN) and \
+ self.CanEdit():
+ self.OnHistoryInsert(step=-1)
+
+ # Ctrl-Space shows Auto Completion
+ # Ctrl-Shift-Space shows CallTips
+ elif controlDown and key == wx.WXK_SPACE:
+ self.OnCallTipAutoCompleteManually(shiftDown)
+
+ # Ctrl+Shift+H is used to complete Text (from already typed words)
+ elif controlDown and shiftDown and key in [ord('H')]:
+ self.OnShowCompHistory()
+
+ # Search up the history for the text in front of the cursor.
+ elif key == wx.WXK_F8:
+ self.OnHistorySearch()
+
+ # Don't backspace over the latest non-continuation prompt.
+ elif key == wx.WXK_BACK:
+ if self.SliceSelection:
+ self.SliceSelectionDelete()
+ wx.CallAfter(self.RestoreFirstMarker)
+ elif selecting and self.CanEdit():
+ self.ReplaceSelection('')
+ #event.Skip()
+ elif self.CanEdit():
+ doDelete=True
+ cur_line=self.GetCurrentLine()
+ if not cur_line==0 and \
+ self.GetCurrentPos()==self.PositionFromLine(cur_line):
+ if self.MarkerGet(cur_line-1) & OUTPUT_MASK:
+ doDelete=False
+
+ if doDelete:
+ cpos=self.GetCurrentPos()
+ s=chr(self.GetCharAt(cpos-1))
+ self.UpdateUndoHistoryBefore('delete',s,cpos-1,cpos)
+ if self.BackspaceWMarkers():
+ event.Skip()
+
+ wx.CallAfter(self.RestoreFirstMarker)
+
+ elif key == wx.WXK_DELETE:
+ if self.SliceSelection:
+ self.SliceSelectionDelete()
+ wx.CallAfter(self.RestoreFirstMarker)
+ elif selecting and self.CanEdit():
+ self.ReplaceSelection('')
+ #event.Skip()
+ elif self.CanEdit():
+ doDelete=True
+ cur_line=self.GetCurrentLine()
+ if not cur_line==self.GetLineCount()-1 and \
+ self.GetCurrentPos()==self.GetLineEndPosition(cur_line):
+ if self.MarkerGet(cur_line+1) & OUTPUT_MASK:
+ doDelete=False
+
+ if doDelete:
+ cpos=self.GetCurrentPos()
+ s=chr(self.GetCharAt(cpos))
+ self.UpdateUndoHistoryBefore('delete',s,cpos,cpos+1)
+ if self.ForwardDeleteWMarkers():
+ event.Skip()
+
+ wx.CallAfter(self.RestoreFirstMarker)
+
+ # Only allow these keys after the latest prompt.
+ elif key == wx.WXK_TAB and self.CanEdit():
+ # use the same mechanism as with autocmplete...
+ cpos=self.GetCurrentPos()
+ self.UpdateUndoHistoryBefore('insert','dummy',cpos,cpos+5,
+ forceNewAction=True)
+ self.undoHistory[self.undoIndex]['allowsAppend'] = True
+ self.TotalLengthForAutoCompActiveCallback=self.GetTextLength()
+ event.Skip()
+ wx.CallAfter(self.AutoCompActiveCallback)
+
+ # Don't toggle between insert mode and overwrite mode.
+ elif key == wx.WXK_INSERT:
+ pass
+
+ # Don't allow line deletion.
+ #elif controlDown and key in (ord('L'), ord('l')):
+ # TODO : Allow line deletion eventually ??
+ #event.Skip()
+ # pass
+
+ # Don't allow line transposition.
+ # Toggle Shell Mode / Slices Mode
+ elif controlDown and key in (ord('T'), ord('t')):
+ self.ToggleShellMode()
+
+ #Open and Save now work when using CrustSlicesFrames
+ elif controlDown and key in (ord('L'), ord('l')):
+ #print 'Load it'
+ file=wx.FileSelector("Load File As New Slice")
+ if file!=u'':
+ fid=open(file,'r')
+ self.LoadPyFileAsSlice(fid)
+ fid.close()
+
+ elif controlDown and key in (ord('D'), ord('d')):
+ #Disallow line duplication in favor of divide slices
+ if self.MarkerGet(self.GetCurrentLine()) & INPUT_MASK:
+ #ADD UNDO
+ cpos=self.GetCurrentPos()
+ start,end = map(self.PositionFromLine,
+ self.GetGroupingSlice(self.LineFromPosition(cpos)))
+ self.UpdateUndoHistoryBefore('marker','',start,end,
+ forceNewAction=True)
+ self.SplitSlice()
+ # Turn off selecting
+ self.SetSelection(cpos,cpos)
+ self.ReplaceSelection('')
+ self.UpdateUndoHistoryAfter()
+
+ elif controlDown and key in (ord('M'), ord('m')):
+ #ADD UNDO
+ if self.SliceSelection:
+ cpos=self.GetCurrentPos()
+ ioSel=self.GetIOSelection()
+ if self.SliceSelection:
+ start,end = map(self.PositionFromLine,ioSel)
+ self.UpdateUndoHistoryBefore('marker','',start,end,
+ forceNewAction=True)
+ self.MergeAdjacentSlices()
+ # Turn off selecting
+ self.SetSelection(cpos,cpos)
+ self.ReplaceSelection('')
+ self.UpdateUndoHistoryAfter()
+
+
+ # Change arrow keys to allow margin behaviors...
+ elif self.SliceSelection and \
+ key in [wx.WXK_UP,wx.WXK_DOWN,wx.WXK_RIGHT,wx.WXK_LEFT]:
+ # TODO : This is useful, but not optimal!
+ if key==wx.WXK_UP:
+ for i in range(self.GetLineCount()):
+ if self.MarkerGet(i) & 1<<GROUPING_SELECTING:
+ if i>0: #Grouping
+ self.DoMarginClick(i-1, 2, shiftDown, controlDown)
+ break
+ elif self.MarkerGet(i) & 1<<IO_SELECTING:
+ if i>0: #IO
+ self.DoMarginClick(i-1, 3, shiftDown, controlDown)
+ break
+ elif key==wx.WXK_DOWN:
+ for i in range(self.GetLineCount()-1,-1,-1):
+ if self.MarkerGet(i) & 1<<GROUPING_SELECTING:
+ if i<self.GetLineCount()-1: #Grouping
+ self.DoMarginClick(i+1, 2, shiftDown, controlDown)
+ break
+ elif self.MarkerGet(i) & 1<<IO_SELECTING:
+ if i<self.GetLineCount()-1: #IO
+ self.DoMarginClick(i+1, 3, shiftDown, controlDown)
+ break
+ elif key==wx.WXK_RIGHT:
+ for i in range(self.GetLineCount()):
+ if self.MarkerGet(i) & 1<<GROUPING_SELECTING:
+ self.DoMarginClick(i, 3, shiftDown, controlDown)
+ break
+ elif self.MarkerGet(i) & 1<<IO_SELECTING:
+ self.MarginUnselectAll()
+ # Go to the beginning of the IO Slice
+ self.SetCurrentPos(self.PositionFromLine(i))
+ if not selecting and not shiftDown:
+ self.SetAnchor(self.PositionFromLine(i))
+ self.EnsureCaretVisible()
+ break
+ elif key==wx.WXK_LEFT:
+ for i in range(self.GetLineCount()):
+ if self.MarkerGet(i) & 1<<GROUPING_SELECTING:
+ break
+ elif self.MarkerGet(i) & 1<<IO_SELECTING:
+ self.DoMarginClick(i, 2, shiftDown, controlDown)
+ break
+ # Basic navigation keys should work anywhere.
+ elif key in NAVKEYS:
+ event.Skip()
+ # Protect the readonly portion of the slices shell.
+ elif not self.CanEdit():
+ pass
+ else:
+ # Check to see if we're selecting
+ if self.GetSelectionEnd()>self.GetSelectionStart():
+ # Check to see if a normal input took place
+ if not controlDown and not altDown and key<256:
+ self.ReplaceSelection('') # This seems to work...
+ event.Skip()
+
+ if self.SliceSelection:
+ if key not in [wx.WXK_UP,wx.WXK_DOWN,wx.WXK_RIGHT,wx.WXK_LEFT,
+ wx.WXK_ALT,wx.WXK_COMMAND,wx.WXK_CONTROL,wx.WXK_SHIFT]:
+ self.MarginUnselectAll()
+
+
+ def MarginSelectAll(self):
+ num_lines=self.GetLineCount()
+ for i in range(num_lines):
+ self.MarkerAdd(i,GROUPING_SELECTING)
+ self.MarkerDelete(i,IO_SELECTING)
+
+ def MarginUnselectAll(self):
+ num_lines=self.GetLineCount()
+ for i in range(num_lines):
+ self.MarkerDelete(i,IO_SELECTING)
+ self.MarkerDelete(i,GROUPING_SELECTING)
+ self.SliceSelection=False
+
+ def DoMarginClick(self, lineClicked, margin, shiftDown, controlDown):
+ num_lines=self.GetLineCount()
+
+ if margin==1:
+ pass # these events are not sent right now...
+ if margin==2:
+ self.SliceSelection=True
+ start,end=self.GetGroupingSlice(lineClicked)
+ startPos=self.PositionFromLine(start)
+ self.SetCurrentPos(startPos)
+ self.SetSelection(startPos,startPos)
+ start_marker=self.MarkerGet(start)
+ if self.MarkerGet(lineClicked) & 1<<GROUPING_SELECTING:
+ toggle=self.MarkerDelete
+ if not shiftDown:
+ if start_marker & 1<<GROUPING_START:
+ self.FoldGroupingSlice(lineClicked)
+ elif start_marker & 1<<GROUPING_START_FOLDED:
+ self.UnFoldGroupingSlice(lineClicked)
+ else:
+ toggle=self.MarkerAdd
+
+ if not shiftDown:
+ self.MarginUnselectAll()
+
+ for i in range(start,end+1):
+ toggle(i,GROUPING_SELECTING)
+ elif margin==3:
+ self.SliceSelection=True
+ start,end=self.GetIOSlice(lineClicked)
+ startPos=self.PositionFromLine(start)
+ self.SetCurrentPos(startPos)
+ self.SetSelection(startPos,startPos)
+ start_marker=self.MarkerGet(start)
+ if self.MarkerGet(lineClicked) & 1<<IO_SELECTING:
+ toggle=self.MarkerDelete
+ if not shiftDown:
+ if start_marker & IO_START_MASK:
+ self.FoldIOSlice(lineClicked)
+ elif start_marker & IO_START_FOLDED_MASK:
+ self.UnFoldIOSlice(lineClicked)
+ else:
+ toggle=self.MarkerAdd
+
+ if not shiftDown:
+ self.MarginUnselectAll()
+
+ for i in range(start,end+1):
+ toggle(i,IO_SELECTING)
+
+ #print start,end
+
+ elif margin==4:
+ # TODO : Folding ??
+ if 1:#self.MarkerGet(lineClicked) & ( 1<<7 | 1<<8 ):
+ if shiftDown:
+ self.SetFoldExpanded(lineClicked, True)
+ self.Expand(lineClicked, True, True, 1)
+ elif controlDown:
+ if self.GetFoldExpanded(lineClicked):
+ self.SetFoldExpanded(lineClicked, False)
+ self.Expand(lineClicked, False, True, 0)
+ else:
+ self.SetFoldExpanded(lineClicked, True)
+ self.Expand(lineClicked, True, True, 100)
+ else:
+ self.ToggleFold(lineClicked)
+ else:
+ self.MarginUnselectAll()
+ if margin in [2,3]:
+ if toggle==self.MarkerDelete and not shiftDown:
+ self.SliceSelection=False
+ else:
+ self.SliceSelection=True
+
+ def OnMarginClick(self, evt):
+
+ # fold and unfold as neededNAVKEYS
+ lineClicked = self.LineFromPosition(evt.GetPosition())
+ self.DoMarginClick(lineClicked,evt.GetMargin(),evt.GetShift(),evt.GetControl())
+ evt.Skip()
+
+ def OnShowCompHistory(self):
+ """Show possible autocompletion Words from already typed words."""
+
+ #copy from history
+ his = self.history[:]
+
+ #put together in one string
+ joined = " ".join (his)
+ import re
+
+ #sort out only "good" words
+ newlist = re.split("[ \.\[\]=}(\)\,0-9\"]", joined)
+
+ #length > 1 (mix out "trash")
+ thlist = []
+ for i in newlist:
+ if len (i) > 1:
+ thlist.append (i)
+
+ #unique (no duplicate words
+ #oneliner from german python forum => unique list
+ unlist = [thlist[i] for i in xrange(len(thlist)) if thlist[i] not in thlist[:i]]
+
+ #sort lowercase
+ unlist.sort(lambda a, b: cmp(a.lower(), b.lower()))
+
+ #this is more convenient, isn't it?
+ self.AutoCompSetIgnoreCase(True)
+
+ #join again together in a string
+ stringlist = " ".join(unlist)
+
+ #pos von 0 noch ausrechnen
+
+ #how big is the offset?
+ cpos = self.GetCurrentPos() - 1
+ while chr (self.GetCharAt (cpos)).isalnum():
+ cpos -= 1
+
+ #the most important part
+ self.AutoCompShow(self.GetCurrentPos() - cpos -1, stringlist)
+
+ def ReplaceSelection(self,text,sliceDeletion=False,*args,**kwds):
+ startIO,endIO=self.GetIOSlice()
+ startGrouping,endGrouping=self.GetGroupingSlice()
+ startSel = self.LineFromPosition(self.GetSelectionStart())
+ endSel = self.LineFromPosition(self.GetSelectionEnd())
+
+ #ADD UNDO
+ cpos=self.GetSelectionStart()
+ s=self.GetSelectedText()
+ if s!='':
+ self.UpdateUndoHistoryBefore('delete',s,cpos,cpos+len(s),
+ forceNewAction=True)
+ editwindow.EditWindow.ReplaceSelection(self,'',*args,**kwds)
+ if s!='' and not sliceDeletion:
+ self.UpdateUndoHistoryAfter()
+
+ if endSel-startSel>0 and not sliceDeletion:
+ if endSel==endIO and startIO!=self.GetCurrentLine():
+ self.clearIOMarkers()
+ self.MarkerAdd(self.GetCurrentLine(),INPUT_END)
+
+ if endSel==endGrouping and startGrouping!=self.GetCurrentLine():
+ self.clearGroupingMarkers()
+ self.MarkerAdd(self.GetCurrentLine(),GROUPING_END)
+
+ cpos=self.GetSelectionStart()
+ s=text
+ if s!='':
+ self.UpdateUndoHistoryBefore('insert',s,cpos,cpos+len(s),
+ forceNewAction=True)
+ self.write(text)
+ self.UpdateUndoHistoryAfter()
+
+ self.ensureSingleGroupingMarker()
+ self.ensureSingleIOMarker()
+
+
+ def clearCommand(self):
+ """Delete the current, unexecuted command."""
+ if not self.CanEdit():
+ return
+ start,end=self.GetIOSlice()
+ startpos = self.PositionFromLine(start)
+ endpos = self.GetLineEndPosition(end)
+ self.SetSelection(startpos, endpos)
+ self.ReplaceSelection('')
+ self.more = False
+
+ def OnHistoryReplace(self, step):
+ """Replace with the previous/next command from the history buffer."""
+ if not self.CanEdit():
+ return
+ self.clearCommand()
+ self.replaceFromHistory(step)
+
+ def replaceFromHistory(self, step):
+ """Replace selection with command from the history buffer."""
+ if not self.CanEdit():
+ return
+ self.ReplaceSelection('')
+ newindex = self.historyIndex + step
+ if -1 <= newindex <= len(self.history):
+ self.historyIndex = newindex
+ if 0 <= newindex <= len(self.history)-1:
+ command = self.history[self.historyIndex]
+ command = command.replace('\n', os.linesep)# + ps2)
+ self.ReplaceSelection(command)
+
+ def OnHistoryInsert(self, step):
+ """Insert the previous/next command from the history buffer."""
+ if not self.CanEdit():
+ return
+ startpos = self.GetCurrentPos()
+ self.replaceFromHistory(step)
+ endpos = self.GetCurrentPos()
+ self.SetSelection(endpos, startpos)
+
+ # TODO: Fix Me!
+ def OnHistorySearch(self):
+ """Search up the history buffer for the text in front of the cursor."""
+ if not self.CanEdit():
+ return
+ startpos = self.GetCurrentPos()
+ # The text up to the cursor is what we search for.
+ numCharsAfterCursor = self.GetTextLength() - startpos
+ searchText = self.getCommand(rstrip=False)
+ #print 'history search', startpos,numCharsAfterCursor,searchText
+ if numCharsAfterCursor > 0:
+ searchText = searchText[:-numCharsAfterCursor]
+ if not searchText:
+ return
+ # Search upwards from the current history position and loop
+ # back to the beginning if we don't find anything.
+ if (self.historyIndex <= -1) \
+ or (self.historyIndex >= len(self.history)-2):
+ searchOrder = range(len(self.history))
+ else:
+ searchOrder = range(self.historyIndex+1, len(self.history)) + \
+ range(self.historyIndex)
+ for i in searchOrder:
+ command = self.history[i]
+ if command[:len(searchText)] == searchText:
+ # Replace the current selection with the one we found.
+ self.ReplaceSelection(command[len(searchText):])
+ endpos = self.GetCurrentPos()
+ self.SetSelection(endpos, startpos)
+ # We've now warped into middle of the history.
+ self.historyIndex = i
+ break
+
+ def setStatusText(self, text):
+ """Display status information."""
+
+ # This method will likely be replaced by the enclosing app to
+ # do something more interesting, like write to a status bar.
+ print text
+
+ def insertLineBreak(self):
+ """Insert a new line break."""
+ if not self.CanEdit():
+ return
+ elif self.reader.isreading:
+ self.processLine()
+ return
+
+
+ # write with undo wrapper...
+ cpos=self.GetCurrentPos()
+ s=os.linesep
+ self.UpdateUndoHistoryBefore('insert',s,cpos,cpos+1)
+ self.write(s,type='Input')
+ self.UpdateUndoHistoryAfter()
+
+ self.more = True
+ self.prompt()
+
+ def processLine(self):
+ """Process the line of text at which the user hit Enter or Shift+RETURN."""
+ # The user hit ENTER (Shift+RETURN) (Shift+ENTER) and we need to
+ # decide what to do. They could be sitting on any line in the slices shell.
+ thepos = self.GetCurrentPos()
+ cur_line = self.GetCurrentLine()
+ marker=self.MarkerGet(cur_line)
+ if marker & INPUT_MASK:
+ pass
+ elif marker & OUTPUT_MASK:
+ return
+ else:
+ pass #print 'BLANK LINE!!'
+
+ startline,endline=self.GetIOSlice(cur_line)
+
+ if startline==0:
+ startpos=0
+ else:
+ startpos=self.PositionFromLine(startline)
+
+ endpos=self.GetLineEndPosition(endline)
+
+ # If they hit ENTER inside the current command, execute the command.
+ if self.CanEdit():
+ self.SetCurrentPos(endpos)
+ self.interp.more = False
+ command = self.GetTextRange(startpos, endpos)
+ lines = command.split(os.linesep)
+ lines = [line.rstrip() for line in lines]
+ command = '\n'.join(lines)
+ if self.reader.isreading:
+ if not command:
+ # Match the behavior of the standard Python shell
+ # when the user hits return without entering a value.
+ command = '\n'
+ self.reader.input = command
+ self.write(os.linesep,'Input')
+ self.MarkerSet(self.GetCurrentLine(),READLINE_BG)
+ self.MarkerSet(self.GetCurrentLine(),INPUT_READLINE)
+ else:
+ self.runningSlice = (startline,endline)
+ self.push(command,useMultiCommand=True)
+ #print 'command: ',command
+ wx.FutureCall(1, self.EnsureCaretVisible)
+ self.runningSlice=None
+
+ skip=self.BackspaceWMarkers(force=True)
+ if skip:
+ self.DeleteBack()
+
+ if self.GetCurrentLine()==self.GetLineCount()-1:
+ self.write(os.linesep,type='Input')
+ cpos=self.GetCurrentLine()
+ if self.MarkerGet(cpos-1) & OUTPUT_MASK:
+ self.MarkerAdd(cpos-1,OUTPUT_BG)
+ self.SplitSlice()
+ else:
+ cur_line=self.GetCurrentLine()
+ new_pos=self.GetLineEndPosition(cur_line+1)
+ self.SetSelection(new_pos,new_pos)
+ self.SetCurrentPos(new_pos)
+
+ self.EmptyUndoBuffer()
+ self.NeedsCheckForSave=True
+ if self.hasSyntaxError:
+ pos=self.GetLineEndPosition(self.syntaxErrorRealLine)
+ self.SetCurrentPos(pos)
+ self.SetSelection(pos,pos)
+
+ # Not Used!!
+ def getMultilineCommand(self, rstrip=True):
+ """Extract a multi-line command from the editor.
+
+ The command may not necessarily be valid Python syntax."""
+ # DNM
+ # XXX Need to extract real prompts here. Need to keep track of
+ # the prompt every time a command is issued.
+ text = self.GetCurLine()[0]
+ line = self.GetCurrentLine()
+ # Add Marker testing here...
+ while text == '' and line > 0: # Need to add markers handling...
+ line -= 1
+ self.GotoLine(line)
+ text = self.GetCurLine()[0]
+ if text=='':
+ line = self.GetCurrentLine()
+ self.GotoLine(line)
+ startpos = self.GetCurrentPos()
+ line += 1
+ self.GotoLine(line)
+ while self.GetCurLine()[0]=='':
+ line += 1
+ self.GotoLine(line)
+ stoppos = self.GetCurrentPos()
+ command = self.GetTextRange(startpos, stoppos)
+ command = command.replace(os.linesep, '\n')
+ command = command.rstrip()
+ command = command.replace('\n', os.linesep)
+ else:
+ command = ''
+ if rstrip:
+ command = command.rstrip()
+ return command
+
+ def getCommand(self, text=None, rstrip=True):
+ """Extract a command from text which may include a shell prompt.
+
+ The command may not necessarily be valid Python syntax."""
+ if not text:
+ text = self.GetCurLine()[0]
+ # Strip the prompt off the front leaving just the command.
+ command = self.lstripPrompt(text)
+ # Change this -- Nothing has prompts!
+ #if command == text:
+ # command = '' # Real commands have prompts.
+ if rstrip:
+ command = command.rstrip()
+ return command
+
+ def lstripPrompt(self, text):
+ """Return text without a leading prompt."""
+ ps1 = str(sys.ps1)
+ ps1size = len(ps1)
+ ps2 = str(sys.ps2)
+ ps2size = len(ps2)
+ # Strip the prompt off the front of text.
+ if text[:ps1size] == ps1:
+ text = text[ps1size:]
+ elif text[:ps2size] == ps2:
+ text = text[ps2size:]
+ return text
+
+ def push(self, command, silent = False,useMultiCommand=False):
+ """Send command to the interpreter for execution."""
+ if not silent:
+ self.write(os.linesep,type='Output')
+ # TODO : What other magic might we insert here?
+ # TODO : Is there a good reason not to include magic?
+ if USE_MAGIC:
+ command=magic(command)
+
+ # Allows multi-component commands...
+ self.hasSyntaxError=False
+ if useMultiCommand:
+ result = self.BreakTextIntoCommands(command)
+ if result[0] == None:
+ commands=[command]
+ self.hasSyntaxError=True
+ syntaxErrorLine=result[1]+1
+ self.syntaxErrorRealLine = self.GetCurrentLine()+result[1]-len(command.split('\n'))
+ else:
+ commands=result
+ else:
+ commands=[command]
+
+ busy = wx.BusyCursor()
+ self.waiting = True
+ self.lastUpdate=None
+
+ for i in commands:
+ if self.hasSyntaxError:
+ lineno=syntaxErrorLine
+ offset=0 # not sure how to easily recover this information...
+ self.write(' File "<input>", line '+str(lineno)+'\n '+i.split('\n')[lineno-1]+'\n'+' '*offset+' ^\nSyntaxError: invalid syntax\n','Error')
+ else:
+ self.more = self.interp.push(i+'\n')
+ # (the \n stops many things from bouncing at the interpreter)
+ # I could do the following, but I don't really like it!
+ #if useMultiCommand:
+ # self.SplitSlice()
+ self.lastUpdate=None
+
+ if not silent:
+ self.MarkerAdd(self.GetIOSlice()[0],OUTPUT_BG)
+
+ self.waiting = False
+ del busy
+ if not self.more: # could loop-add to history, too, but I don't like it!
+ self.addHistory(command.rstrip())
+
+ if not silent:
+ self.prompt()
+
+ def addHistory(self, command):
+ """Add command to the command history."""
+ # Reset the history position.
+ self.historyIndex = -1
+ # Insert this command into the history, unless it's a blank
+ # line or the same as the last command.
+ if command!='' and ( len(self.history)==0 or command!=self.history[0] ):
+ self.history.insert(0, command)
+ dispatcher.send(signal="SlicesShell.addHistory", command=command)
+
+ def clearGroupingMarkers(self,line_num=None):
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+ self.MarkerDelete(line_num,GROUPING_START)
+ self.MarkerDelete(line_num,GROUPING_START_FOLDED)
+ self.MarkerDelete(line_num,GROUPING_MIDDLE)
+ self.MarkerDelete(line_num,GROUPING_END)
+ def clearIOMarkers(self,line_num=None):
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+ self.MarkerDelete(line_num,INPUT_START)
+ self.MarkerDelete(line_num,INPUT_START_FOLDED)
+ self.MarkerDelete(line_num,INPUT_MIDDLE)
+ self.MarkerDelete(line_num,INPUT_END)
+ self.MarkerDelete(line_num,OUTPUT_START)
+ self.MarkerDelete(line_num,OUTPUT_START_FOLDED)
+ self.MarkerDelete(line_num,OUTPUT_MIDDLE)
+ self.MarkerDelete(line_num,OUTPUT_END)
+ self.MarkerDelete(line_num,OUTPUT_BG)
+ self.MarkerDelete(line_num,READLINE_BG)
+ self.MarkerDelete(line_num,INPUT_READLINE)
+ def ensureSingleGroupingMarker(self,line_num=None):
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+ marker=self.MarkerGet(line_num)
+ if marker & 1<<GROUPING_START:
+ self.MarkerDelete(line_num,GROUPING_START_FOLDED)
+ self.MarkerDelete(line_num,GROUPING_MIDDLE)
+ self.MarkerDelete(line_num,GROUPING_END)
+ elif marker & 1<<GROUPING_START_FOLDED:
+ self.MarkerDelete(line_num,GROUPING_MIDDLE)
+ self.MarkerDelete(line_num,GROUPING_END)
+ elif marker & 1<<GROUPING_MIDDLE:
+ self.MarkerDelete(line_num,GROUPING_END)
+ elif marker & 1<<GROUPING_END:
+ pass
+ else:
+ #print 'ERROR! NO GROUPING MARKERS!'
+ return 1 # Blank marker
+
+ return 0
+
+ def ensureSingleIOMarker(self,line_num=None):
+ if line_num==None:
+ line_num=self.GetCurrentLine()
+ marker=self.MarkerGet(line_num)
+ if marker & INPUT_MASK:
+ self.MarkerDelete(line_num,OUTPUT_START)
+ self.MarkerDelete(line_num,OUTPUT_START_FOLDED)
+ self.MarkerDelete(line_num,OUTPUT_MIDDLE)
+ self.MarkerDelete(line_num,OUTPUT_END)
+ self.MarkerDelete(line_num,OUTPUT_BG)
+ [start,start_folded] = [INPUT_START,INPUT_START_FOLDED]
+ [middle,end] = [INPUT_MIDDLE,INPUT_END]
+ elif marker & OUTPUT_MASK:
+ self.MarkerDelete(line_num,INPUT_START)
+ self.MarkerDelete(line_num,INPUT_START_FOLDED)
+ self.MarkerDelete(line_num,INPUT_MIDDLE)
+ self.MarkerDelete(line_num,INPUT_END)
+ [start,start_folded] = [OUTPUT_START,OUTPUT_START_FOLDED]
+ [middle,end] = [OUTPUT_MIDDLE,OUTPUT_END]
+ else:
+ #print 'ERROR! NO IO MARKERS!'
+ return 1 # Blank marker
+
+ if marker & 1<<start:
+ self.MarkerDelete(line_num,start_folded)
+ self.MarkerDelete(line_num,middle)
+ self.MarkerDelete(line_num,end)
+ elif marker & 1<<start_folded:
+ self.MarkerDelete(line_num,middle)
+ self.MarkerDelete(line_num,end)
+ elif marker & 1<<middle:
+ self.MarkerDelete(line_num,end)
+ elif marker & 1<<end:
+ pass
+
+ return 0
+
+ def RestoreFirstMarker(self):
+ first_marker=self.MarkerGet(0)
+ self.clearGroupingMarkers(0)
+ self.clearIOMarkers(0)
+
+ if first_marker & 1<<GROUPING_START :
+ self.MarkerAdd(0,GROUPING_START)
+ elif first_marker & 1<<GROUPING_START_FOLDED :
+ self.MarkerAdd(0,GROUPING_START_FOLDED)
+ else:
+ self.MarkerAdd(0,GROUPING_START)
+
+ if first_marker & 1<<INPUT_START :
+ self.MarkerAdd(0,INPUT_START)
+ elif first_marker & 1<<INPUT_START_FOLDED :
+ self.MarkerAdd(0,INPUT_START_FOLDED)
+ elif first_marker & 1<<OUTPUT_START :
+ self.MarkerAdd(0,OUTPUT_START)
+ #self.MarkerAdd(0,OUTPUT_BG) # More harm than good??
+ elif first_marker & 1<<OUTPUT_START_FOLDED :
+ self.MarkerAdd(0,OUTPUT_START_FOLDED)
+ #self.MarkerAdd(0,OUTPUT_BG) # More harm than good??
+ else:
+ self.MarkerAdd(0,INPUT_START)
+
+ if self.doHistUpdate:
+ self.UpdateUndoHistoryAfter()
+
+ def IsAllowedPair(self,m1,m2):
+ """This testing function ensures that two adjacent markers are valid"""
+ i_s = 1<<INPUT_START | 1<<INPUT_START_FOLDED
+ o_s = 1<<OUTPUT_START | 1<<OUTPUT_START_FOLDED
+ g_s = 1<<GROUPING_START | 1<<GROUPING_START_FOLDED
+ i_m,o_m,g_m = 1<<INPUT_MIDDLE, 1<<OUTPUT_MIDDLE, 1<<GROUPING_MIDDLE
+ i_e,o_e,g_e = 1<<INPUT_END, 1<<OUTPUT_END, 1<<GROUPING_END
+
+ if (m1 & i_s) and (m1 & g_s): #1
+ if (m2 & i_s) and (m2 & g_s): return True #1
+ elif (m2 & i_m) and (m2 & g_m): return True #2
+ elif (m2 & i_e) and (m2 & g_m): return True #3
+ elif (m2 & i_e) and (m2 & g_e): return True #4
+ elif (m2 & o_s) and (m2 & g_s): return False #5
+ elif (m2 & o_s) and (m2 & g_m): return True #6
+ elif (m2 & o_s) and (m2 & g_e): return True #7
+ elif (m2 & o_m) and (m2 & g_m): return False #8
+ elif (m2 & o_e) and (m2 & g_e): return False #9
+ else: return False
+ elif (m1 & i_m) and (m1 & g_m): #2
+ if (m2 & i_m) and (m2 & g_m): return True #2
+ elif (m2 & i_e) and (m2 & g_m): return True #3
+ elif (m2 & i_e) and (m2 & g_e): return True #4
+ else: return False
+ elif (m1 & i_e) and (m1 & g_m): #3
+ if (m2 & o_s) and (m2 & g_m): return True #6
+ elif (m2 & o_s) and (m2 & g_e): return True #7
+ else: return False
+ elif (m1 & i_e) and (m1 & g_e): #4
+ if (m2 & i_s) and (m2 & g_s): return True #1
+ elif (m2 & o_s) and (m2 & g_s): return True #5
+ else: return False
+ elif (m1 & o_s) and (m1 & g_s): #5
+ if (m2 & i_s) and (m2 & g_s): return True #1
+ elif (m2 & i_m) and (m2 & g_m): return False #2
+ elif (m2 & i_e) and (m2 & g_m): return False #3
+ elif (m2 & i_e) and (m2 & g_e): return False #4
+ elif (m2 & o_s) and (m2 & g_s): return True #5
+ elif (m2 & o_s) and (m2 & g_m): return False #6
+ elif (m2 & o_s) and (m2 & g_e): return False #7
+ elif (m2 & o_m) and (m2 & g_m): return True #8
+ elif (m2 & o_e) and (m2 & g_e): return True #9
+ else: return False
+ elif (m1 & o_s) and (m1 & g_m): #6
+ if (m2 & o_m) and (m2 & g_m): return True #8
+ elif (m2 & o_e) and (m2 & g_e): return True #9
+ else: return False
+ elif (m1 & o_s) and (m1 & g_e): #7
+ if (m2 & i_s) and (m2 & g_s): return True #1
+ elif (m2 & o_s) and (m2 & g_s): return True #5
+ else: return False
+ elif (m1 & o_m) and (m1 & g_m): #8
+ if (m2 & o_m) and (m2 & g_m): return True #8
+ elif (m2 & o_e) and (m2 & g_e): return True #9
+ else: return False
+ elif (m1 & o_e) and (m1 & g_e): #9
+ if (m2 & i_s) and (m2 & g_s): return True #1
+ elif (m2 & o_s) and (m2 & g_s): return True #5
+ else: return False
+ else:
+ return False
+
+
+ def CleanAllMarkers(self):
+ self.RestoreFirstMarker()
+ first_marker=self.MarkerGet(0)
+ last_line_num=self.GetLineCount()-1
+
+ for i in range(1,last_line_num):
+ self.ensureSingleGroupingMarker(i)
+ self.ensureSingleIOMarker(i)
+
+ previous_marker=self.MarkerGet(i-1)
+ marker=self.MarkerGet(i)
+
+ if not self.IsAllowedPair(previous_marker,marker):
+ pass # FIX MARKER!!
+ # FIX ME
+
+ def write(self, text,type='Input',silent=False):
+ """Display text in the slices shell.
+
+ Replace line endings with OS-specific endings."""
+ text = self.fixLineEndings(text)
+ split=text.split(os.linesep)
+ self.AddText(text)
+
+ # This part handles all the marker stuff that accompanies
+ # adding or removing new lines of text...
+ # Get the total number of lines in the Document == last line number
+ last_line_num=self.GetLineCount()-1
+ # Get the line number we ended on in the write
+ end_line_num=self.GetCurrentLine()
+ # Get the number of returns we are using == number of lines we pasted -1
+ num_new_lines=text.count(os.linesep)
+ # So if num_new_lines==0, start_line_num and end_line_num are the same
+ start_line_num=end_line_num-num_new_lines+1
+
+ # This is a little unnecessary because there will always
+ # be a line before if we just inserted a newline!
+ if start_line_num == 0:
+ previous_line_num=None
+ else:
+ previous_line_num=start_line_num-1
+
+ #However, this is very important...
+ if end_line_num == last_line_num:
+ next_line_num=None
+ else:
+ next_line_num=end_line_num+1
+
+ if type=='Input':
+ start = INPUT_START
+ start_folded = INPUT_START_FOLDED
+ middle = INPUT_MIDDLE
+ end = INPUT_END
+ # preparation for more io types...
+ opposite_start_mask = 1<<OUTPUT_START
+ opposite_start_folded_mask = 1<<OUTPUT_START_FOLDED
+ opposite_middle_mask = 1<<OUTPUT_MIDDLE # To test for bad writes...
+ opposite_end_mask = 1<<OUTPUT_END # To test for bad writes...
+ elif type in ['Output','Error']:
+ #self.MarkerAdd(start_line_num,GROUPING_START_FOLDED)
+ start=OUTPUT_START
+ start_folded=OUTPUT_START_FOLDED
+ middle=OUTPUT_MIDDLE
+ end=OUTPUT_END
+ # preparation for more io types...
+ opposite_start_mask = 1<<INPUT_START
+ opposite_start_folded_mask = 1<<INPUT_START_FOLDED
+ opposite_middle_mask = 1<<INPUT_MIDDLE # To test for bad writes...
+ opposite_end_mask = 1<<INPUT_END # To test for bad writes...
+
+ if num_new_lines>0: #Do nothing if typing within a line...
+ # Update the Grouping Markers
+ # For the previous line and the start_line
+ # Test to make sure we can write ... but not here ...
+ # test this before we call write or before we add text...
+ # So we assume it already obeys the rules
+
+ badMarkers=False
+ fixIOEnd=True
+
+ if previous_line_num==None:
+ # This is an impossible case, here just for completeness...
+ self.clearGroupingMarkers(start_line_num)
+ self.MarkerAdd(start_line_num,GROUPING_START)
+
+ self.clearIOMarkers(start_line_num)
+ self.MarkerAdd(start_line_num,start)
+ if type in ['Output','Error']: self.MarkerAdd(start_line_num,OUTPUT_BG)
+ else:
+ previous_marker=self.MarkerGet(previous_line_num)
+ if previous_marker & opposite_middle_mask:
+ badMarkers=True
+
+ if next_line_num==None:
+ self.MarkerAdd(end_line_num,GROUPING_END)
+ self.MarkerAdd(end_line_num,end)
+ if type in ['Output','Error']: self.MarkerAdd(end_line_num,OUTPUT_BG)
+ fixEndMarkers=False
+ # May be overwritten below if start_line_num==end_line_num...
+ else:
+ next_marker=self.MarkerGet(next_line_num)
+ fixEndMarkers=True
+ if next_marker & ( opposite_middle_mask | opposite_end_mask ):
+ badMarkers=True
+
+ if not badMarkers:
+ # ensure previous_line only has one marker & turn end into middle
+ if previous_line_num!=None:
+ # Adjust previous line appropriately, ensure only one marker
+ # Only print errors if we are on input!
+ blank=False
+ blank=blank or self.ensureSingleGroupingMarker(previous_line_num)
+ blank=blank or self.ensureSingleIOMarker(previous_line_num)
+
+ if blank:
+ #if type=='Input' and not silent: print 'BLANK LINE!' # BAD CASE
+ pass
+
+ if previous_marker & 1<<GROUPING_END :
+ # Make GROUPING slice continue unless we hit
+ # an output end and are starting a new input...
+ if (previous_marker & OUTPUT_MASK) and type=='Input':
+ pass
+ else:
+ self.MarkerDelete(previous_line_num,GROUPING_END)
+ # ONLY CHANGING CASE
+ self.MarkerAdd(previous_line_num,GROUPING_MIDDLE)
+
+ if previous_marker & 1<<end :
+ self.MarkerDelete(previous_line_num,end)
+ self.MarkerAdd(previous_line_num,middle) # ONLY CHANGING CASE
+ if type in ['Output','Error']: self.MarkerAdd(previous_line_num,OUTPUT_BG)
+ elif previous_marker & opposite_middle_mask :
+ # BAD CASE
+ if type=='Input' and not silent:
+ #print 'Should have been a bad marker!'
+ pass
+
+ # We can only add input to an input slice
+ # And can only add output to an output slice
+
+ if previous_marker & ( opposite_start_mask |
+ opposite_start_folded_mask |
+ opposite_end_mask ):
+ if type=='Input':
+ self.clearGroupingMarkers(start_line_num)
+ self.MarkerAdd(start_line_num,GROUPING_START)
+ if start_line_num==end_line_num:
+ fixEndMarkers=False
+ else:
+ if start_line_num==end_line_num:
+ fixIOEnd=False
+ self.clearIOMarkers(start_line_num)
+ self.MarkerAdd(start_line_num,start)
+ if type in ['Output','Error']: self.MarkerAdd(start_line_num,OUTPUT_BG)
+ else:
+ if next_line_num!=None:
+ self.clearGroupingMarkers(start_line_num)
+ self.clearIOMarkers(start_line_num)
+ self.MarkerAdd(start_line_num,GROUPING_MIDDLE)
+ self.MarkerAdd(start_line_num,middle)
+ if type in ['Output','Error']: self.MarkerAdd(start_line_num,OUTPUT_BG)
+ # This may be overwritten if start_line_num==end_line_num
+
+ # Take care of all the middle lines...
+ # Does nothing for only one line...
+ for i in range(start_line_num,end_line_num):
+ self.clearGroupingMarkers(i)
+ self.MarkerAdd(i,GROUPING_MIDDLE)
+
+ self.clearIOMarkers(i)
+ self.MarkerAdd(i,middle)
+ if type in ['Output','Error']: self.MarkerAdd(i,OUTPUT_BG)
+
+ if fixEndMarkers:
+ # Take care of the end_line if we haven't already done so...
+ blank=False
+ blank=blank or self.ensureSingleGroupingMarker(next_line_num)
+ blank=blank or self.ensureSingleIOMarker(next_line_num)
+
+ if blank:
+ if type=='Input' and not silent:
+ #print 'BLANK LINE!' # BAD CASE
+ pass
+
+ self.clearGroupingMarkers(end_line_num)
+ if fixIOEnd:
+ self.clearIOMarkers(end_line_num)
+
+ if next_marker & ( 1<<GROUPING_START | 1<<GROUPING_START_FOLDED ) :
+ self.MarkerAdd(end_line_num,GROUPING_END)
+ elif next_marker & ( 1<<GROUPING_MIDDLE | 1<<GROUPING_END ) :
+ self.MarkerAdd(end_line_num,GROUPING_MIDDLE)
+
+ if fixIOEnd:
+ if next_marker & ( 1<<start | 1<<start_folded ) :
+ self.MarkerAdd(end_line_num,end)
+ if type in ['Output','Error']: self.MarkerAdd(end_line_num,OUTPUT_BG)
+ elif next_marker & ( 1<<middle | 1<<end ) :
+ self.MarkerAdd(end_line_num,middle)
+ if type in ['Output','Error']: self.MarkerAdd(end_line_num,OUTPUT_BG)
+ elif next_marker & ( opposite_start_mask |
+ opposite_start_folded_mask ):
+ self.MarkerAdd(end_line_num,end)
+ if type in ['Output','Error']: self.MarkerAdd(end_line_num,OUTPUT_BG)
+ else:
+ self.MarkerAdd(end_line_num,start_folded)
+ if type in ['Output','Error']: self.MarkerAdd(end_line_num,OUTPUT_BG)
+ if type=='Input' and not silent:
+ #print 'BAD MARKERS!'
+ pass
+ else:
+ if type=='Input' and not silent:
+ #print 'BAD MARKERS!!!'
+ pass
+
+ self.EnsureCaretVisible()
+
+ if self.waiting:
+ if self.lastUpdate==None:
+ self.lastUpdate=time.time()
+ if time.time()-self.lastUpdate > PRINT_UPDATE_MAX_TIME:
+ self.Update()
+ self.lastUpdate=time.time()
+
+ def fixLineEndings(self, text):
+ """Return text with line endings replaced by OS-specific endings."""
+ lines = text.split('\r\n')
+ for l in range(len(lines)):
+ chunks = lines[l].split('\r')
+ for c in range(len(chunks)):
+ chunks[c] = os.linesep.join(chunks[c].split('\n'))
+ lines[l] = os.linesep.join(chunks)
+ text = os.linesep.join(lines)
+ return text
+
+ def prompt(self): # Autoindent added!!!
+ """Display proper prompt for the context: ps1, ps2 or ps3.
+
+ If this is a continuation line, autoindent as necessary."""
+ # TODO : How much of this can I do away with now without prompts??
+
+ isreading = self.reader.isreading
+
+ skip = True
+ if isreading:
+ prompt = str(sys.ps3)
+ elif self.more:
+ prompt = str(sys.ps2)
+ else:
+ prompt = str(sys.ps1)
+ pos = self.GetCurLine()[1]
+ if pos > 0:
+ if isreading:
+ skip = True
+ else:
+ self.write(os.linesep,type='Input')
+ if not self.more:
+ # Not needed anymore! # self.promptPosStart = self.GetCurrentPos()
+ pass
+ if not skip:
+ self.write(prompt,type='Input')
+ if not self.more:
+ # Not needed anymore! # self.promptPosEnd = self.GetCurrentPos()
+ # Clear the undo history after running a command.
+ self.EmptyUndoBuffer()
+
+ #DNM/CP
+ # Autoindent magic
+ # Match the indent of the line above
+ # UNLESS the line above ends in a colon...then add four spaces
+ # (after valid keywords (if, else, etc...) only)
+ if self.more:
+ line_num=self.GetCurrentLine()
+ currentLine=self.GetLine(line_num)
+ previousLine=self.GetLine(line_num-1)
+ pstrip=previousLine.strip()
+ lstrip=previousLine.lstrip()
+
+ if pstrip == '':
+ # because it is all whitespace!
+ indent=previousLine.strip('\n').strip('\r')
+ else:
+ indent=previousLine[:(len(previousLine)-len(lstrip))]
+ if testForContinuations(previousLine,ignoreErrors=True)[1][0]:
+ indent+=' '*4
+
+ #ADD UNDO
+ cpos=self.GetCurrentPos()
+ s=indent
+ self.UpdateUndoHistoryBefore('insert',s,cpos,cpos+len(s))
+ self.write(s,type='Input')
+ self.UpdateUndoHistoryAfter()
+
+
+ self.EnsureCaretVisible()
+ self.ScrollToColumn(0)
+
+ def readline(self):
+ """Replacement for stdin.readline()."""
+ input = ''
+ reader = self.reader
+ reader.isreading = True
+ self.prompt()
+
+ # Ensure that we get a new line and that it's got an input marker...
+ # Also need to temporarily block any other action...
+ cLine = self.GetCurrentLine()
+ self.clearIOMarkers(cLine)
+ self.MarkerAdd(cLine,INPUT_START)
+ self.MarkerAdd(cLine,READLINE_BG)
+ self.MarkerAdd(cLine,INPUT_READLINE)
+
+ try:
+ while not reader.input:
+ wx.YieldIfNeeded()
+ input = reader.input
+ finally:
+ start,end = self.GetIOSlice()
+ start = self.runningSlice[1] + 1
+ for i in range(start,end+1):
+ self.clearIOMarkers(i)
+ self.clearGroupingMarkers(i)
+ self.MarkerAdd(i,OUTPUT_BG)
+ if i == start: self.MarkerAdd(i,OUTPUT_START)
+ elif i==end: self.MarkerAdd(i,OUTPUT_END)
+ else: self.MarkerAdd(i,OUTPUT_MIDDLE)
+
+ if i==end: self.MarkerAdd(i,GROUPING_END)
+ else: self.MarkerAdd(i,GROUPING_MIDDLE)
+ reader.input = ''
+ reader.isreading = False
+ input = str(input) # In case of Unicode.
+ return input
+
+ def readlines(self):
+ """Replacement for stdin.readlines()."""
+ lines = []
+ while lines[-1:] != ['\n']:
+ lines.append(self.readline())
+ return lines
+
+ def raw_input(self, prompt=''):
+ """Return string based on user input."""
+ if prompt:
+ self.write(prompt,type='Output')
+ return self.readline()
+
+ def ask(self, prompt='Please enter your response:'):
+ """Get response from the user using a dialog box."""
+ dialog = wx.TextEntryDialog(None, prompt,
+ 'Input Dialog (Raw)', '')
+ try:
+ if dialog.ShowModal() == wx.ID_OK:
+ text = dialog.GetValue()
+ return text
+ finally:
+ dialog.Destroy()
+ return ''
+
+ def pause(self):
+ """Halt execution pending a response from the user."""
+ self.ask('Press enter to continue:')
+
+ def clear(self):
+ """Delete all text from the slices shell."""
+ self.ClearAll()
+ self.MarkerAdd(0,GROUPING_START)
+ self.MarkerAdd(0,INPUT_START)
+
+ def run(self, command, prompt=True, verbose=True):
+ """Execute command as if it was typed in directly.
+ >>> shell.run('print "this"')
+ >>> print "this"
+ this
+ >>>
+ """
+ # Go to the very bottom of the text.
+ endpos = self.GetTextLength()
+ self.SetCurrentPos(endpos)
+ command = command.rstrip()
+ if prompt: self.prompt()
+ if verbose: self.write(command,type='Input')
+ self.push(command)
+
+ # TODO : Will have to fix this to handle other kinds of errors mentioned before...
+ def runfile(self, filename):
+ """Execute all commands in file as if they were typed into the shell."""
+ file = open(filename)
+ try:
+ self.prompt()
+ for command in file.readlines():
+ if command[:6] == 'shell.':
+ # Run shell methods silently.
+ self.run(command, prompt=False, verbose=False)
+ else:
+ self.run(command, prompt=False, verbose=True)
+ finally:
+ file.close()
+
+ def autoCompleteShow(self, command, offset = 0):
+ """Display auto-completion popup list."""
+ self.AutoCompSetAutoHide(self.autoCompleteAutoHide)
+ self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
+ list = self.interp.getAutoCompleteList(command,
+ includeMagic=self.autoCompleteIncludeMagic,
+ includeSingle=self.autoCompleteIncludeSingle,
+ includeDouble=self.autoCompleteIncludeDouble)
+ if list:
+ options = ' '.join(list)
+ #offset = 0
+ self.AutoCompShow(offset, options)
+
+ def autoCallTipShow(self, command, insertcalltip = True, forceCallTip = False):
+ """Display argument spec and docstring in a popup window."""
+ if self.CallTipActive():
+ self.CallTipCancel()
+ (name, argspec, tip) = self.interp.getCallTip(command)
+ if tip:
+ dispatcher.send(signal='SlicesShell.calltip', sender=self, calltip=tip)
+ if not self.autoCallTip and not forceCallTip:
+ return
+ startpos = self.GetCurrentPos()
+ if argspec and insertcalltip and self.callTipInsert:
+ # write with undo history...
+ cpos=self.GetCurrentPos()
+ s=argspec + ')'
+ self.UpdateUndoHistoryBefore('insert',s,cpos,cpos+len(s))
+ self.write(s,type='Input')
+ self.UpdateUndoHistoryAfter()
+
+ endpos = self.GetCurrentPos()
+ self.SetSelection(startpos, endpos)
+ if tip:
+ tippos = startpos - (len(name) + 1)
+ fallback = startpos - self.GetColumn(startpos)
+ # In case there isn't enough room, only go back to the fallback.
+ tippos = max(tippos, fallback)
+ self.CallTipShow(tippos, tip)
+
+ def OnCallTipAutoCompleteManually (self, shiftDown):
+ """AutoComplete and Calltips manually."""
+ if self.AutoCompActive():
+ self.AutoCompCancel()
+ currpos = self.GetCurrentPos()
+ stoppos = self.PositionFromLine(self.GetIOSlice()[0])
+
+ cpos = currpos
+ #go back until '.' is found
+ pointavailpos = -1
+ while cpos >= stoppos:
+ if self.GetCharAt(cpos) == ord ('.'):
+ pointavailpos = cpos
+ break
+ cpos -= 1
+
+ #word from non whitespace until '.'
+ if pointavailpos != -1:
+ #look backward for first whitespace char
+ textbehind = self.GetTextRange (pointavailpos + 1, currpos)
+ pointavailpos += 1
+
+ if not shiftDown:
+ #call AutoComplete
+ stoppos = self.PositionFromLine(self.GetIOSlice()[0])
+ textbefore = self.GetTextRange(stoppos, pointavailpos)
+ self.autoCompleteShow(textbefore, len (textbehind))
+ else:
+ #call CallTips
+ cpos = pointavailpos
+ begpos = -1
+ while cpos > stoppos:
+ if chr(self.GetCharAt(cpos)).isspace():
+ begpos = cpos
+ break
+ cpos -= 1
+ if begpos == -1:
+ begpos = cpos
+ ctips = self.GetTextRange (begpos, currpos)
+ ctindex = ctips.find ('(')
+ if ctindex != -1 and not self.CallTipActive():
+ #insert calltip, if current pos is '(', otherwise show it only
+ self.autoCallTipShow( ctips[:ctindex + 1],
+ self.GetCharAt(currpos - 1) == ord('(') and
+ self.GetCurrentPos() == self.GetTextLength(),
+ True )
+
+
+ def writeOut(self, text):
+ """Replacement for stdout."""
+ self.write(text,type='Output')
+ # TODO : FLUSH?? How to make this update real-time...
+
+ def writeErr(self, text):
+ """Replacement for stderr."""
+ self.write(text,type='Error')
+
+ def redirectStdin(self, redirect=True):
+ """If redirect is true then sys.stdin will come from the shell."""
+ if redirect:
+ sys.stdin = self.reader
+ else:
+ sys.stdin = self.stdin
+
+ def redirectStdout(self, redirect=True):
+ """If redirect is true then sys.stdout will go to the shell."""
+ if redirect:
+ sys.stdout = PseudoFileOut(self.writeOut)
+ else:
+ sys.stdout = self.stdout
+
+ def redirectStderr(self, redirect=True):
+ """If redirect is true then sys.stderr will go to the shell."""
+ if redirect:
+ sys.stderr = PseudoFileErr(self.writeErr)
+ else:
+ sys.stderr = self.stderr
+
+ # Take a spashot of the WHOLE grouping slice (or slices)
+ # The argument s is either what got added or deleted
+ def UpdateUndoHistoryBefore(self,actionType,s,posStart,posEnd,
+ forceNewAction=False):
+ uH=self.undoHistory
+ uI=self.undoIndex
+
+ s=s.replace(os.linesep,'\n')
+ startLine=self.LineFromPosition(posStart)
+
+ if actionType=='marker':
+ numLines = self.LineFromPosition(posEnd) - startLine
+ else:
+ numLines=s.count('\n')
+
+ makeNewAction=forceNewAction
+
+ if forceNewAction:
+ makeNewAction=True
+ elif self.undoIndex==-1:
+ makeNewAction=True
+ elif not uH[uI]['allowsAppend']:
+ makeNewAction=True
+ elif actionType!=uH[uI]['actionType']:
+ makeNewAction=True
+ elif actionType=='insert':
+ if posStart!=uH[uI]['posEnd']:
+ makeNewAction=True
+ else: # This is a continuation of the previous insert
+ uH[uI]['charList'] = uH[uI]['charList']+s
+ uH[uI]['posEnd'] = posEnd # posStart cannot move
+ uH[uI]['numLines'] = uH[uI]['numLines']+numLines
+ elif actionType=='delete':
+ # This is a forward continuation of the previous delete
+ if posStart==uH[uI]['posStart']:
+ uH[uI]['charList'] = uH[uI]['charList']+s
+ uH[uI]['posEnd'] = posEnd
+ uH[uI]['numLines'] = uH[uI]['numLines']+numLines
+ # This is a backward continuation of the previous delete
+ elif posEnd==uH[uI]['posStart']:
+ uH[uI]['charList'] = s+uH[uI]['charList']
+ uH[uI]['posStart'] = posStart
+ uH[uI]['startLine'] = startLine
+ uH[uI]['numLines'] = uH[uI]['numLines']+numLines
+ else:
+ makeNewAction=True
+
+ elif actionType=='marker':
+ makeNewAction=True
+ else:
+ pass #print 'Unsupported Action Type!!'
+
+ if makeNewAction:
+ del(self.undoHistory[uI+1:]) # remove actions after undoIndex
+
+ uH.append({
+ 'actionType' : actionType, # Action type ('insert','delete','marker')
+ 'allowsAppend': not forceNewAction, # Can action be joined with others?
+ 'charList' : s, # Character list
+ 'posStart' : posStart, # Cursor poition at the start of the action
+ 'posEnd' : posEnd, # Cursor position at the end of the action
+ 'startLine' : startLine, # Start line number,
+ 'numLines' : numLines, # Number of newlines involved
+ 'mBStart' : None, # Starting line for markers BEFORE action
+ 'mAStart' : None, # Starting line for markers AFTER action
+ 'markersBefore' : None, # [markers BEFORE action]
+ 'markersAfter' : None # [markers AFTER action]
+ })
+
+ self.undoIndex+=1
+
+ # Only update the before when starting a new action
+ start = startLine
+ if actionType=='insert':
+ end = start
+ else:
+ end = start + numLines
+
+ # Update Marker Info
+ newStart=self.GetGroupingSlice(start)[0]
+ newEnd=self.GetGroupingSlice(end)[1]
+ self.undoHistory[self.undoIndex]['markersBefore'] = \
+ [self.MarkerGet(i) for i in range(newStart,newEnd+1)]
+ self.undoHistory[self.undoIndex]['mBStart']=newStart
+
+ self.doHistUpdate=True
+
+ def UpdateUndoHistoryAfter(self): # s is either what got added or deleted
+ start = self.undoHistory[self.undoIndex]['startLine']
+ if self.undoHistory[self.undoIndex]['actionType']=='delete':
+ end = start
+ else:
+ end = start + self.undoHistory[self.undoIndex]['numLines']
+
+ newStart=min(self.GetGroupingSlice(start)[0]-1, 0)
+ newEnd=max(self.GetGroupingSlice(end)[1]+1, self.GetLineCount()-1)
+ self.undoHistory[self.undoIndex]['markersAfter'] = \
+ [self.MarkerGet(i) for i in range(newStart,newEnd+1)]
+ self.undoHistory[self.undoIndex]['mAStart']=newStart
+
+ self.doHistUpdate=False
+
+ def Undo(self):
+ #ADD UNDO
+ #Skip undo if there are no actions...
+ if self.undoIndex==-1:
+ return
+
+ uHI=self.undoHistory[self.undoIndex]
+
+ if uHI['actionType'] in ['insert','delete']:
+ # This will perform the opposite of the action given
+ editwindow.EditWindow.Undo(self)
+ elif uHI['actionType']=='marker': # No text changed, don't pass to STC
+ pass
+ else:
+ #print 'Unsupported actionType in undoHistory!!'
+ return
+
+ numLines=len(uHI['markersBefore'])
+ for i in range(numLines):
+ self.MarkerSet( uHI['mBStart']+i , uHI['markersBefore'][i] )
+
+ self.undoIndex-=1
+
+ def Redo(self):
+ #ADD UNDO
+ # First check to see if there are any redo operations available
+ # Note that for redo, undoIndex=-1 is a valid input
+ if self.undoIndex >= len(self.undoHistory)-1:
+ return
+ self.undoIndex+=1
+ uHI=self.undoHistory[self.undoIndex]
+
+ if uHI['actionType'] in ['insert','delete']:
+ # This will re-perform the given action
+ editwindow.EditWindow.Redo(self)
+ elif uHI['actionType']=='marker': # No text changed, don't pass to STC
+ pass
+ else:
+ #print 'Unsupported actionType in undoHistory!!'
+ return
+
+ numLines=len(uHI['markersAfter'])
+ for i in range(numLines):
+ self.MarkerSet( uHI['mAStart']+i , uHI['markersAfter'][i] )
+
+ def EmptyUndoBuffer(self):
+ editwindow.EditWindow.EmptyUndoBuffer(self)
+ self.undoIndex=-1
+ self.undoHistory=[]
+ self.doHistUpdate=False
+
+ def CanCut(self):
+ return self.CanEdit() and \
+ (self.GetSelectionStart() != self.GetSelectionEnd())
+
+ def CanPaste(self):
+ """Return true if a paste should succeed."""
+ if self.CanEdit() and editwindow.EditWindow.CanPaste(self):
+ return True
+ else:
+ return False
+
+ def CanEdit(self):
+ """Return true if editing should succeed."""
+ marker=self.MarkerGet(self.GetCurrentLine())
+
+ if marker & OUTPUT_MASK:
+ return False
+ elif marker & INPUT_MASK:
+ if self.reader.isreading and not \
+ (self.MarkerGet(self.GetCurrentLine()) & 1<<INPUT_READLINE ):
+ return False
+ start,end=self.GetIOSlice()
+ sliceStartPos=self.PositionFromLine(start)
+ sliceEndPos=self.GetLineEndPosition(end)
+ """Return true if text is selected and can be cut."""
+ if self.GetSelectionStart() == self.GetSelectionEnd():
+ return True
+ elif self.GetSelectionStart() != self.GetSelectionEnd() \
+ and self.GetSelectionStart() >= sliceStartPos \
+ and self.GetSelectionEnd() >= sliceStartPos \
+ and self.GetSelectionStart() <= sliceEndPos \
+ and self.GetSelectionEnd() <= sliceEndPos:
+ return True
+ else:
+ return False
+
+ def Cut(self):
+ """Remove selection and place it on the clipboard."""
+ if self.CanCut() and self.CanCopy():
+ if self.AutoCompActive():
+ self.AutoCompCancel()
+ if self.CallTipActive():
+ self.CallTipCancel()
+ self.Copy()
+ self.ReplaceSelection('')
+
+ def Copy(self):
+ """Copy selection and place it on the clipboard."""
+ if self.CanCopy():
+ ps1 = str(sys.ps1)
+ ps2 = str(sys.ps2)
+ command = self.GetSelectedText()
+ command = command.replace(os.linesep + ps2, os.linesep)
+ command = command.replace(os.linesep + ps1, os.linesep)
+ command = self.lstripPrompt(text=command)
+ data = wx.TextDataObject(command)
+ self._clip(data)
+
+ def CopyWithPrompts(self):
+ """Copy selection, including prompts, and place it on the clipboard."""
+ if self.CanCopy():
+ command = self.GetSelectedText()
+ data = wx.TextDataObject(command)
+ self._clip(data)
+
+ def CopyWithPromptsPrefixed(self):
+ """Copy selection, including prompts prefixed with four
+ spaces, and place it on the clipboard."""
+ if self.CanCopy():
+ command = self.GetSelectedText()
+ spaces = ' ' * 4
+ command = spaces + command.replace(os.linesep,
+ os.linesep + spaces)
+ data = wx.TextDataObject(command)
+ self._clip(data)
+
+ def _clip(self, data):
+ if wx.TheClipboard.Open():
+ wx.TheClipboard.UsePrimarySelection(False)
+ wx.TheClipboard.SetData(data)
+ wx.TheClipboard.Flush()
+ wx.TheClipboard.Close()
+
+ def Paste(self):
+ """Replace selection with clipboard contents."""
+
+ #ADD UNDO
+ if self.CanPaste() and wx.TheClipboard.Open():
+ ps2 = str(sys.ps2)
+ if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)):
+ data = wx.TextDataObject()
+ if wx.TheClipboard.GetData(data):
+ self.ReplaceSelection('')
+ command = data.GetText()
+ command = command.rstrip()
+ command = self.fixLineEndings(command)
+ command = self.lstripPrompt(text=command)
+ # TODO : This is still useful... Add it back other places?
+ command = command.replace(os.linesep + ps2, '\n')
+ command = command.replace(os.linesep, '\n')
+ #DNM--Don't use '... '
+ command = command.replace('\n', os.linesep)# + ps2)
+
+ cpos=self.GetCurrentPos()
+ s=command
+ self.UpdateUndoHistoryBefore('insert', s, cpos,
+ cpos+len(s), forceNewAction=True)
+ self.write(s,type='Input')
+ self.UpdateUndoHistoryAfter()
+
+ # Makes paste -> type -> undo consistent with other STC apps
+ self.ReplaceSelection('')
+ wx.TheClipboard.Close()
+
+
+ def PasteAndRun(self):
+ """Replace selection with clipboard contents, run commands."""
+ text = ''
+ if wx.TheClipboard.Open():
+ if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)):
+ data = wx.TextDataObject()
+ if wx.TheClipboard.GetData(data):
+ text = data.GetText()
+ wx.TheClipboard.Close()
+ if text:
+ self.Execute(text)
+
+
+ def Execute(self, text):
+ """Replace selection with text and run commands."""
+ start,end=self.GetIOSlice()
+ startpos=self.PositionFromLine(start)
+ endpos=self.GetLineEndPosition(end)
+
+ self.SetCurrentPos(endpos)
+ self.SetSelection(startpos, endpos)
+ self.ReplaceSelection('')
+
+ hasSyntaxError=False
+ result = self.BreakTextIntoCommands(command)
+ if result[0] == None:
+ commands=[command]
+ hasSyntaxError=True
+ else:
+ commands=result
+
+ for command in commands:
+ command = command.replace('\n', os.linesep)
+ self.write(command)
+ self.processLine()
+
+ def wrap(self, wrap=True):
+ """Sets whether text is word wrapped."""
+ try:
+ self.SetWrapMode(wrap)
+ except AttributeError:
+ return 'Wrapping is not available in this version.'
+
+ def zoom(self, points=0):
+ """Set the zoom level.
+
+ This number of points is added to the size of all fonts. It
+ may be positive to magnify or negative to reduce."""
+ self.SetZoom(points)
+
+ def LoadSettings(self, config):
+ self.autoComplete = \
+ config.ReadBool('Options/AutoComplete', True)
+ self.autoCompleteIncludeMagic = \
+ config.ReadBool('Options/AutoCompleteIncludeMagic', True)
+ self.autoCompleteIncludeSingle = \
+ config.ReadBool('Options/AutoCompleteIncludeSingle', True)
+ self.autoCompleteIncludeDouble = \
+ config.ReadBool('Options/AutoCompleteIncludeDouble', True)
+ self.autoCallTip = \
+ config.ReadBool('Options/AutoCallTip', True)
+ self.callTipInsert = \
+ config.ReadBool('Options/CallTipInsert', True)
+
+ self.SetWrapMode(config.ReadBool('View/WrapMode', True))
+
+ self.lineNumbers = \
+ config.ReadBool('View/ShowLineNumbers', True)
+ self.setDisplayLineNumbers (self.lineNumbers)
+ zoom = config.ReadInt('View/Zoom/Shell', -99)
+ if zoom != -99:
+ self.SetZoom(zoom)
+
+
+
+ def SaveSettings(self, config):
+ config.WriteBool('Options/AutoComplete', self.autoComplete)
+ config.WriteBool('Options/AutoCompleteIncludeMagic',
+ self.autoCompleteIncludeMagic)
+ config.WriteBool('Options/AutoCompleteIncludeSingle',
+ self.autoCompleteIncludeSingle)
+ config.WriteBool('Options/AutoCompleteIncludeDouble',
+ self.autoCompleteIncludeDouble)
+ config.WriteBool('Options/AutoCallTip', self.autoCallTip)
+ config.WriteBool('Options/CallTipInsert', self.callTipInsert)
+ config.WriteBool('View/WrapMode', self.GetWrapMode())
+ config.WriteBool('View/ShowLineNumbers', self.lineNumbers)
+ config.WriteInt('View/Zoom/Shell', self.GetZoom())
+
+ def GetContextMenu(self):
+ """
+ Create and return a context menu for the slices shell.
+ This is used instead of the scintilla default menu
+ in order to correctly respect our immutable buffer.
+ """
+ menu = wx.Menu()
+ menu.Append(wx.ID_UNDO, "Undo")
+ menu.Append(wx.ID_REDO, "Redo")
+
+ menu.AppendSeparator()
+
+ menu.Append(wx.ID_CUT, "Cut")
+ menu.Append(wx.ID_COPY, "Copy")
+ menu.Append(frame.ID_COPY_PLUS, "Copy Plus")
+ menu.Append(wx.ID_PASTE, "Paste")
+ menu.Append(frame.ID_PASTE_PLUS, "Paste Plus")
+ menu.Append(wx.ID_CLEAR, "Clear")
+
+ menu.AppendSeparator()
+
+ menu.Append(wx.ID_SELECTALL, "Select All")
+ return menu
+
+ def OnContextMenu(self, evt):
+ menu = self.GetContextMenu()
+ self.PopupMenu(menu)
+
+ def OnUpdateUI(self, evt):
+ id = evt.Id
+ if id in (wx.ID_CUT, wx.ID_CLEAR):
+ evt.Enable(self.CanCut())
+ elif id in (wx.ID_COPY, frame.ID_COPY_PLUS):
+ evt.Enable(self.CanCopy())
+ elif id in (wx.ID_PASTE, frame.ID_PASTE_PLUS):
+ evt.Enable(self.CanPaste())
+ elif id == wx.ID_UNDO:
+ evt.Enable(self.CanUndo())
+ elif id == wx.ID_REDO:
+ evt.Enable(self.CanRedo())
+
+ def LoadPySlicesFile(self,fid):
+ invalidFileString = 'Not a valid input format'
+ lineCount=0
+ groupingStartLines=[0]
+ ioStartLines=[0]
+ ioStartTypes=[]
+ removeComment=False
+
+ # Read the initial three (or four) lines that have version and marker information
+ line=fid.readline()
+ if line == usrBinEnvPythonText:
+ line=fid.readline() # Add the option to place #!/usr/bin/env python2 at the top
+ if line not in pyslicesFormatHeaderText: print invalidFileString ; return
+ line=fid.readline()
+ if line != groupingStartText: print invalidFileString ; return
+ line=fid.readline()
+ if line == inputStartText: ioStartTypes.append('input');removeComment=False
+ elif line == outputStartText: ioStartTypes.append('output');removeComment=True
+ else: print invalidFileString ; return
+
+ self.ClearAll()
+
+ # Write the file's text to the text area
+ # Capture Marker information to
+ for i in fid:
+ if i==groupingStartText:
+ groupingStartLines.append(lineCount)
+ elif i==inputStartText:
+ ioStartLines.append(lineCount)
+ ioStartTypes.append('input')
+ removeComment=False
+ elif i==outputStartText:
+ ioStartLines.append(lineCount)
+ ioStartTypes.append('output')
+ removeComment=True
+ else:
+ if removeComment: w=i[1:].replace(os.linesep,'\n')
+ else: w=i.replace(os.linesep,'\n')
+ self.write(w,'Input',silent=True)
+ lineCount+=1
+
+ if w[-1]=='\n':
+ lineCount+=1
+
+ for i in range(lineCount+1):
+ self.clearGroupingMarkers(i)
+ self.clearIOMarkers(i)
+
+ doMiddle=False
+ doEnd=False
+ if groupingStartLines!=[]:
+ if i == groupingStartLines[0]:
+ self.MarkerAdd(i,GROUPING_START)
+ del groupingStartLines[0]
+ elif i+1 == groupingStartLines[0]:
+ doEnd=True
+ else:
+ doMiddle=True
+ elif i==lineCount-1:
+ doEnd=True
+ else:
+ doMiddle=True
+
+ if doMiddle:
+ self.MarkerAdd(i,GROUPING_MIDDLE)
+ elif doEnd:
+ self.MarkerAdd(i,GROUPING_END)
+
+ doMiddle=False
+ doEnd=False
+ if ioStartLines!=[]:
+ if i == ioStartLines[0]:
+ # Delete the old ioStartTypes (keep the current copy for later use)
+ if i>0: del ioStartTypes[0]
+
+ if ioStartTypes[0]=='input':
+ self.MarkerAdd(i,INPUT_START)
+ elif ioStartTypes[0]=='output':
+ self.MarkerAdd(i,OUTPUT_START)
+ self.MarkerAdd(i,OUTPUT_BG)
+ else:
+ #print 'Invalid Type!';
+ return
+
+ # Only delete markers we are totally finished with...
+ # Keep one more "StartTypes" than "StartLines"
+ del ioStartLines[0]
+ elif i+1 == ioStartLines[0]:
+ doEnd=True
+ else:
+ doMiddle=True
+ elif i==lineCount-1:
+ doEnd=True
+ else:
+ doMiddle=True
+
+ if doMiddle:
+ if ioStartTypes[0]=='input':
+ self.MarkerAdd(i,INPUT_MIDDLE)
+ elif ioStartTypes[0]=='output':
+ self.MarkerAdd(i,OUTPUT_MIDDLE)
+ self.MarkerAdd(i,OUTPUT_BG)
+ else:
+ #print 'Invalid Type!';
+ return
+ elif doEnd:
+ if ioStartTypes[0]=='input':
+ self.MarkerAdd(i,INPUT_END)
+ elif ioStartTypes[0]=='output':
+ self.MarkerAdd(i,OUTPUT_END)
+ self.MarkerAdd(i,OUTPUT_BG)
+ else:
+ #print 'Invalid Type!';
+ return
+
+ self.EmptyUndoBuffer() # maybe not?
+
+
+ def SavePySlicesFile(self,fid):
+ addComment=False
+ fid.write(usrBinEnvPythonText.replace('\n',os.linesep))
+ fid.write(pyslicesFormatHeaderText[-1].replace('\n',os.linesep))
+ for i in range(self.GetLineCount()):
+ markers=self.MarkerGet(i)
+ if markers & ( 1<<GROUPING_START | 1<<GROUPING_START_FOLDED ):
+ fid.write(groupingStartText.replace('\n',os.linesep))
+ if markers & ( 1<<INPUT_START | 1<<INPUT_START_FOLDED ):
+ fid.write(inputStartText.replace('\n',os.linesep))
+ addComment=False
+ if markers & ( 1<<OUTPUT_START | 1<<OUTPUT_START_FOLDED ):
+ fid.write(outputStartText.replace('\n',os.linesep))
+ addComment=True
+ if addComment: fid.write('#')
+ fid.write(self.GetLine(i).replace('\n',os.linesep))
+
+ # FIX ME!!
+ def LoadPyFileAsSlice(self,fid):
+ curpos=self.GetCurrentPos()
+ start,end = self.GetGroupingSlice()
+
+ endpos=self.GetLineEndPosition(end)
+ self.SetCurrentPos(endpos)
+ self.SetSelection(endpos, endpos)
+
+ text='\n'+fid.read()
+ self.write(text,'Input')
+ newpos=self.GetCurrentPos()
+
+ self.SetCurrentPos(curpos)
+ self.SetSelection(curpos,curpos)
+ self.SplitSlice()
+ #self.SetCurrentPos(newpos)
+ #self.SetSelection(newpos,newpos)
+
+ def hasChanged(self):
+ """Return True if contents have changed."""
+ return self.GetModify() or self.NeedsCheckForSave
+
+
+
+## NOTE: The DnD of file names is disabled until we can figure out how
+## best to still allow DnD of text.
+
+## #seb : File drag and drop
+## class FileDropTarget(wx.FileDropTarget):
+## def __init__(self, obj):
+## wx.FileDropTarget.__init__(self)
+## self.obj = obj
+## def OnDropFiles(self, x, y, filenames):
+## if len(filenames) == 1:
+## txt = 'r\"%s\"' % filenames[0]
+## else:
+## txt = '( '
+## for f in filenames:
+## txt += 'r\"%s\" , ' % f
+## txt += ')'
+## self.obj.AppendText(txt)
+## pos = self.obj.GetCurrentPos()
+## self.obj.SetCurrentPos( pos )
+## self.obj.SetSelection( pos, pos )
+
+
+
+## class TextAndFileDropTarget(wx.DropTarget):
+## def __init__(self, sliceshell):
+## wx.DropTarget.__init__(self)
+## self.sliceshell = sliceshell
+## self.compdo = wx.DataObjectComposite()
+## self.textdo = wx.TextDataObject()
+## self.filedo = wx.FileDataObject()
+## self.compdo.Add(self.textdo)
+## self.compdo.Add(self.filedo, True)
+
+## self.SetDataObject(self.compdo)
+
+## def OnDrop(self, x, y):
+## return True
+
+## def OnData(self, x, y, result):
+## self.GetData()
+## if self.textdo.GetTextLength() > 1:
+## text = self.textdo.GetText()
+## # *** Do somethign with the dragged text here...
+## self.textdo.SetText('')
+## else:
+## filenames = str(self.filename.GetFilenames())
+## if len(filenames) == 1:
+## txt = 'r\"%s\"' % filenames[0]
+## else:
+## txt = '( '
+## for f in filenames:
+## txt += 'r\"%s\" , ' % f
+## txt += ')'
+## self.sliceshell.AppendText(txt)
+## pos = self.sliceshell.GetCurrentPos()
+## self.sliceshell.SetCurrentPos( pos )
+## self.sliceshell.SetSelection( pos, pos )
+
+## return result
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/py/version.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/version.py
new file mode 100644
index 0000000..d47909d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/py/version.py
@@ -0,0 +1,9 @@
+"""Provides an object representing the current 'version' or 'release'
+of Py as a whole. Individual classes, such as the shell, filling and
+interpreter, each have a revision property based on the CVS Revision."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+VERSION = '0.9.8'
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/richtext.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/richtext.py
new file mode 100644
index 0000000..30a3b77
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/richtext.py
@@ -0,0 +1,4611 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+import _richtext
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _windows
+import _core
+import _controls
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+#---------------------------------------------------------------------------
+
+RICHTEXT_TYPE_ANY = _richtext.RICHTEXT_TYPE_ANY
+RICHTEXT_TYPE_TEXT = _richtext.RICHTEXT_TYPE_TEXT
+RICHTEXT_TYPE_XML = _richtext.RICHTEXT_TYPE_XML
+RICHTEXT_TYPE_HTML = _richtext.RICHTEXT_TYPE_HTML
+RICHTEXT_TYPE_RTF = _richtext.RICHTEXT_TYPE_RTF
+RICHTEXT_TYPE_PDF = _richtext.RICHTEXT_TYPE_PDF
+RICHTEXT_FIXED_WIDTH = _richtext.RICHTEXT_FIXED_WIDTH
+RICHTEXT_FIXED_HEIGHT = _richtext.RICHTEXT_FIXED_HEIGHT
+RICHTEXT_VARIABLE_WIDTH = _richtext.RICHTEXT_VARIABLE_WIDTH
+RICHTEXT_VARIABLE_HEIGHT = _richtext.RICHTEXT_VARIABLE_HEIGHT
+RICHTEXT_LAYOUT_SPECIFIED_RECT = _richtext.RICHTEXT_LAYOUT_SPECIFIED_RECT
+RICHTEXT_DRAW_IGNORE_CACHE = _richtext.RICHTEXT_DRAW_IGNORE_CACHE
+RICHTEXT_FORMATTED = _richtext.RICHTEXT_FORMATTED
+RICHTEXT_UNFORMATTED = _richtext.RICHTEXT_UNFORMATTED
+RICHTEXT_CACHE_SIZE = _richtext.RICHTEXT_CACHE_SIZE
+RICHTEXT_HEIGHT_ONLY = _richtext.RICHTEXT_HEIGHT_ONLY
+RICHTEXT_SETSTYLE_NONE = _richtext.RICHTEXT_SETSTYLE_NONE
+RICHTEXT_SETSTYLE_WITH_UNDO = _richtext.RICHTEXT_SETSTYLE_WITH_UNDO
+RICHTEXT_SETSTYLE_OPTIMIZE = _richtext.RICHTEXT_SETSTYLE_OPTIMIZE
+RICHTEXT_SETSTYLE_PARAGRAPHS_ONLY = _richtext.RICHTEXT_SETSTYLE_PARAGRAPHS_ONLY
+RICHTEXT_SETSTYLE_CHARACTERS_ONLY = _richtext.RICHTEXT_SETSTYLE_CHARACTERS_ONLY
+RICHTEXT_SETSTYLE_RENUMBER = _richtext.RICHTEXT_SETSTYLE_RENUMBER
+RICHTEXT_SETSTYLE_SPECIFY_LEVEL = _richtext.RICHTEXT_SETSTYLE_SPECIFY_LEVEL
+RICHTEXT_SETSTYLE_RESET = _richtext.RICHTEXT_SETSTYLE_RESET
+RICHTEXT_SETSTYLE_REMOVE = _richtext.RICHTEXT_SETSTYLE_REMOVE
+RICHTEXT_INSERT_NONE = _richtext.RICHTEXT_INSERT_NONE
+RICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE = _richtext.RICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE
+RICHTEXT_INSERT_INTERACTIVE = _richtext.RICHTEXT_INSERT_INTERACTIVE
+TEXT_ATTR_KEEP_FIRST_PARA_STYLE = _richtext.TEXT_ATTR_KEEP_FIRST_PARA_STYLE
+RICHTEXT_HITTEST_NONE = _richtext.RICHTEXT_HITTEST_NONE
+RICHTEXT_HITTEST_BEFORE = _richtext.RICHTEXT_HITTEST_BEFORE
+RICHTEXT_HITTEST_AFTER = _richtext.RICHTEXT_HITTEST_AFTER
+RICHTEXT_HITTEST_ON = _richtext.RICHTEXT_HITTEST_ON
+RICHTEXT_HITTEST_OUTSIDE = _richtext.RICHTEXT_HITTEST_OUTSIDE
+RICHTEXT_HITTEST_NO_NESTED_OBJECTS = _richtext.RICHTEXT_HITTEST_NO_NESTED_OBJECTS
+RICHTEXT_HITTEST_NO_FLOATING_OBJECTS = _richtext.RICHTEXT_HITTEST_NO_FLOATING_OBJECTS
+TEXT_BOX_ATTR_FLOAT = _richtext.TEXT_BOX_ATTR_FLOAT
+TEXT_BOX_ATTR_CLEAR = _richtext.TEXT_BOX_ATTR_CLEAR
+TEXT_BOX_ATTR_COLLAPSE_BORDERS = _richtext.TEXT_BOX_ATTR_COLLAPSE_BORDERS
+TEXT_BOX_ATTR_VERTICAL_ALIGNMENT = _richtext.TEXT_BOX_ATTR_VERTICAL_ALIGNMENT
+TEXT_BOX_ATTR_BOX_STYLE_NAME = _richtext.TEXT_BOX_ATTR_BOX_STYLE_NAME
+TEXT_ATTR_UNITS_TENTHS_MM = _richtext.TEXT_ATTR_UNITS_TENTHS_MM
+TEXT_ATTR_UNITS_PIXELS = _richtext.TEXT_ATTR_UNITS_PIXELS
+TEXT_ATTR_UNITS_PERCENTAGE = _richtext.TEXT_ATTR_UNITS_PERCENTAGE
+TEXT_ATTR_UNITS_POINTS = _richtext.TEXT_ATTR_UNITS_POINTS
+TEXT_ATTR_UNITS_MASK = _richtext.TEXT_ATTR_UNITS_MASK
+TEXT_BOX_ATTR_POSITION_STATIC = _richtext.TEXT_BOX_ATTR_POSITION_STATIC
+TEXT_BOX_ATTR_POSITION_RELATIVE = _richtext.TEXT_BOX_ATTR_POSITION_RELATIVE
+TEXT_BOX_ATTR_POSITION_ABSOLUTE = _richtext.TEXT_BOX_ATTR_POSITION_ABSOLUTE
+TEXT_BOX_ATTR_POSITION_MASK = _richtext.TEXT_BOX_ATTR_POSITION_MASK
+#---------------------------------------------------------------------------
+
+class TextAttrDimension(object):
+ """Proxy of C++ TextAttrDimension class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> TextAttrDimension
+ __init__(self, int value, int units=TEXT_ATTR_UNITS_TENTHS_MM) -> TextAttrDimension
+ """
+ _richtext.TextAttrDimension_swiginit(self,_richtext.new_TextAttrDimension(*args))
+ __swig_destroy__ = _richtext.delete_TextAttrDimension
+ __del__ = lambda self : None;
+ def Reset(*args, **kwargs):
+ """Reset(self)"""
+ return _richtext.TextAttrDimension_Reset(*args, **kwargs)
+
+ def EqPartial(*args, **kwargs):
+ """EqPartial(self, TextAttrDimension dim) -> bool"""
+ return _richtext.TextAttrDimension_EqPartial(*args, **kwargs)
+
+ def Apply(*args, **kwargs):
+ """Apply(self, TextAttrDimension dim, TextAttrDimension compareWith=None) -> bool"""
+ return _richtext.TextAttrDimension_Apply(*args, **kwargs)
+
+ def CollectCommonAttributes(*args, **kwargs):
+ """
+ CollectCommonAttributes(self, TextAttrDimension attr, TextAttrDimension clashingAttr,
+ TextAttrDimension absentAttr)
+ """
+ return _richtext.TextAttrDimension_CollectCommonAttributes(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """__eq__(self, TextAttrDimension dim) -> bool"""
+ return _richtext.TextAttrDimension___eq__(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> int"""
+ return _richtext.TextAttrDimension_GetValue(*args, **kwargs)
+
+ def GetValueMM(*args, **kwargs):
+ """GetValueMM(self) -> float"""
+ return _richtext.TextAttrDimension_GetValueMM(*args, **kwargs)
+
+ def SetValueMM(*args, **kwargs):
+ """SetValueMM(self, float value)"""
+ return _richtext.TextAttrDimension_SetValueMM(*args, **kwargs)
+
+ def SetValue(*args):
+ """
+ SetValue(self, int value)
+ SetValue(self, int value, TextAttrDimensionFlags flags)
+ SetValue(self, TextAttrDimension dim)
+ """
+ return _richtext.TextAttrDimension_SetValue(*args)
+
+ def GetUnits(*args, **kwargs):
+ """GetUnits(self) -> int"""
+ return _richtext.TextAttrDimension_GetUnits(*args, **kwargs)
+
+ def SetUnits(*args, **kwargs):
+ """SetUnits(self, int units)"""
+ return _richtext.TextAttrDimension_SetUnits(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> int"""
+ return _richtext.TextAttrDimension_GetPosition(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, int pos)"""
+ return _richtext.TextAttrDimension_SetPosition(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> TextAttrDimensionFlags"""
+ return _richtext.TextAttrDimension_GetFlags(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, TextAttrDimensionFlags flags)"""
+ return _richtext.TextAttrDimension_SetFlags(*args, **kwargs)
+
+ m_value = property(_richtext.TextAttrDimension_m_value_get, _richtext.TextAttrDimension_m_value_set)
+ m_flags = property(_richtext.TextAttrDimension_m_flags_get, _richtext.TextAttrDimension_m_flags_set)
+_richtext.TextAttrDimension_swigregister(TextAttrDimension)
+
+class TextAttrDimensions(object):
+ """Proxy of C++ TextAttrDimensions class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> TextAttrDimensions"""
+ _richtext.TextAttrDimensions_swiginit(self,_richtext.new_TextAttrDimensions(*args, **kwargs))
+ __swig_destroy__ = _richtext.delete_TextAttrDimensions
+ __del__ = lambda self : None;
+ def Reset(*args, **kwargs):
+ """Reset(self)"""
+ return _richtext.TextAttrDimensions_Reset(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """__eq__(self, TextAttrDimensions dims) -> bool"""
+ return _richtext.TextAttrDimensions___eq__(*args, **kwargs)
+
+ def EqPartial(*args, **kwargs):
+ """EqPartial(self, TextAttrDimensions dims) -> bool"""
+ return _richtext.TextAttrDimensions_EqPartial(*args, **kwargs)
+
+ def Apply(*args, **kwargs):
+ """Apply(self, TextAttrDimensions dims, TextAttrDimensions compareWith=None) -> bool"""
+ return _richtext.TextAttrDimensions_Apply(*args, **kwargs)
+
+ def CollectCommonAttributes(*args, **kwargs):
+ """
+ CollectCommonAttributes(self, TextAttrDimensions attr, TextAttrDimensions clashingAttr,
+ TextAttrDimensions absentAttr)
+ """
+ return _richtext.TextAttrDimensions_CollectCommonAttributes(*args, **kwargs)
+
+ def RemoveStyle(*args, **kwargs):
+ """RemoveStyle(self, TextAttrDimensions attr) -> bool"""
+ return _richtext.TextAttrDimensions_RemoveStyle(*args, **kwargs)
+
+ def GetLeft(*args, **kwargs):
+ """GetLeft(self) -> TextAttrDimension"""
+ return _richtext.TextAttrDimensions_GetLeft(*args, **kwargs)
+
+ def GetRight(*args, **kwargs):
+ """GetRight(self) -> TextAttrDimension"""
+ return _richtext.TextAttrDimensions_GetRight(*args, **kwargs)
+
+ def GetTop(*args, **kwargs):
+ """GetTop(self) -> TextAttrDimension"""
+ return _richtext.TextAttrDimensions_GetTop(*args, **kwargs)
+
+ def GetBottom(*args, **kwargs):
+ """GetBottom(self) -> TextAttrDimension"""
+ return _richtext.TextAttrDimensions_GetBottom(*args, **kwargs)
+
+ def IsValid(*args, **kwargs):
+ """IsValid(self) -> bool"""
+ return _richtext.TextAttrDimensions_IsValid(*args, **kwargs)
+
+ m_left = property(_richtext.TextAttrDimensions_m_left_get, _richtext.TextAttrDimensions_m_left_set)
+ m_top = property(_richtext.TextAttrDimensions_m_top_get, _richtext.TextAttrDimensions_m_top_set)
+ m_right = property(_richtext.TextAttrDimensions_m_right_get, _richtext.TextAttrDimensions_m_right_set)
+ m_bottom = property(_richtext.TextAttrDimensions_m_bottom_get, _richtext.TextAttrDimensions_m_bottom_set)
+_richtext.TextAttrDimensions_swigregister(TextAttrDimensions)
+
+class TextAttrDimensionConverter(object):
+ """Proxy of C++ TextAttrDimensionConverter class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, DC dc, double scale=1.0, Size parentSize=DefaultSize) -> TextAttrDimensionConverter
+ __init__(self, int ppi, double scale=1.0, Size parentSize=DefaultSize) -> TextAttrDimensionConverter
+ """
+ _richtext.TextAttrDimensionConverter_swiginit(self,_richtext.new_TextAttrDimensionConverter(*args))
+ __swig_destroy__ = _richtext.delete_TextAttrDimensionConverter
+ __del__ = lambda self : None;
+ def GetPixels(*args, **kwargs):
+ """GetPixels(self, TextAttrDimension dim, int direction=HORIZONTAL) -> int"""
+ return _richtext.TextAttrDimensionConverter_GetPixels(*args, **kwargs)
+
+ def GetTenthsMM(*args, **kwargs):
+ """GetTenthsMM(self, TextAttrDimension dim) -> int"""
+ return _richtext.TextAttrDimensionConverter_GetTenthsMM(*args, **kwargs)
+
+ def ConvertTenthsMMToPixels(*args, **kwargs):
+ """ConvertTenthsMMToPixels(self, int units) -> int"""
+ return _richtext.TextAttrDimensionConverter_ConvertTenthsMMToPixels(*args, **kwargs)
+
+ def ConvertPixelsToTenthsMM(*args, **kwargs):
+ """ConvertPixelsToTenthsMM(self, int pixels) -> int"""
+ return _richtext.TextAttrDimensionConverter_ConvertPixelsToTenthsMM(*args, **kwargs)
+
+ m_ppi = property(_richtext.TextAttrDimensionConverter_m_ppi_get, _richtext.TextAttrDimensionConverter_m_ppi_set)
+ m_scale = property(_richtext.TextAttrDimensionConverter_m_scale_get, _richtext.TextAttrDimensionConverter_m_scale_set)
+ m_parentSize = property(_richtext.TextAttrDimensionConverter_m_parentSize_get, _richtext.TextAttrDimensionConverter_m_parentSize_set)
+_richtext.TextAttrDimensionConverter_swigregister(TextAttrDimensionConverter)
+
+TEXT_BOX_ATTR_BORDER_NONE = _richtext.TEXT_BOX_ATTR_BORDER_NONE
+TEXT_BOX_ATTR_BORDER_SOLID = _richtext.TEXT_BOX_ATTR_BORDER_SOLID
+TEXT_BOX_ATTR_BORDER_DOTTED = _richtext.TEXT_BOX_ATTR_BORDER_DOTTED
+TEXT_BOX_ATTR_BORDER_DASHED = _richtext.TEXT_BOX_ATTR_BORDER_DASHED
+TEXT_BOX_ATTR_BORDER_DOUBLE = _richtext.TEXT_BOX_ATTR_BORDER_DOUBLE
+TEXT_BOX_ATTR_BORDER_GROOVE = _richtext.TEXT_BOX_ATTR_BORDER_GROOVE
+TEXT_BOX_ATTR_BORDER_RIDGE = _richtext.TEXT_BOX_ATTR_BORDER_RIDGE
+TEXT_BOX_ATTR_BORDER_INSET = _richtext.TEXT_BOX_ATTR_BORDER_INSET
+TEXT_BOX_ATTR_BORDER_OUTSET = _richtext.TEXT_BOX_ATTR_BORDER_OUTSET
+TEXT_BOX_ATTR_BORDER_STYLE = _richtext.TEXT_BOX_ATTR_BORDER_STYLE
+TEXT_BOX_ATTR_BORDER_COLOUR = _richtext.TEXT_BOX_ATTR_BORDER_COLOUR
+TEXT_BOX_ATTR_BORDER_THIN = _richtext.TEXT_BOX_ATTR_BORDER_THIN
+TEXT_BOX_ATTR_BORDER_MEDIUM = _richtext.TEXT_BOX_ATTR_BORDER_MEDIUM
+TEXT_BOX_ATTR_BORDER_THICK = _richtext.TEXT_BOX_ATTR_BORDER_THICK
+TEXT_BOX_ATTR_FLOAT_NONE = _richtext.TEXT_BOX_ATTR_FLOAT_NONE
+TEXT_BOX_ATTR_FLOAT_LEFT = _richtext.TEXT_BOX_ATTR_FLOAT_LEFT
+TEXT_BOX_ATTR_FLOAT_RIGHT = _richtext.TEXT_BOX_ATTR_FLOAT_RIGHT
+TEXT_BOX_ATTR_CLEAR_NONE = _richtext.TEXT_BOX_ATTR_CLEAR_NONE
+TEXT_BOX_ATTR_CLEAR_LEFT = _richtext.TEXT_BOX_ATTR_CLEAR_LEFT
+TEXT_BOX_ATTR_CLEAR_RIGHT = _richtext.TEXT_BOX_ATTR_CLEAR_RIGHT
+TEXT_BOX_ATTR_CLEAR_BOTH = _richtext.TEXT_BOX_ATTR_CLEAR_BOTH
+TEXT_BOX_ATTR_COLLAPSE_NONE = _richtext.TEXT_BOX_ATTR_COLLAPSE_NONE
+TEXT_BOX_ATTR_COLLAPSE_FULL = _richtext.TEXT_BOX_ATTR_COLLAPSE_FULL
+TEXT_BOX_ATTR_VERTICAL_ALIGNMENT_NONE = _richtext.TEXT_BOX_ATTR_VERTICAL_ALIGNMENT_NONE
+TEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP = _richtext.TEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
+TEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE = _richtext.TEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
+TEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM = _richtext.TEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
+class TextAttrBorder(object):
+ """Proxy of C++ TextAttrBorder class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> TextAttrBorder"""
+ _richtext.TextAttrBorder_swiginit(self,_richtext.new_TextAttrBorder(*args, **kwargs))
+ def __eq__(*args, **kwargs):
+ """__eq__(self, TextAttrBorder border) -> bool"""
+ return _richtext.TextAttrBorder___eq__(*args, **kwargs)
+
+ def Reset(*args, **kwargs):
+ """Reset(self)"""
+ return _richtext.TextAttrBorder_Reset(*args, **kwargs)
+
+ def EqPartial(*args, **kwargs):
+ """EqPartial(self, TextAttrBorder border) -> bool"""
+ return _richtext.TextAttrBorder_EqPartial(*args, **kwargs)
+
+ def Apply(*args, **kwargs):
+ """Apply(self, TextAttrBorder border, TextAttrBorder compareWith=None) -> bool"""
+ return _richtext.TextAttrBorder_Apply(*args, **kwargs)
+
+ def RemoveStyle(*args, **kwargs):
+ """RemoveStyle(self, TextAttrBorder attr) -> bool"""
+ return _richtext.TextAttrBorder_RemoveStyle(*args, **kwargs)
+
+ def CollectCommonAttributes(*args, **kwargs):
+ """CollectCommonAttributes(self, TextAttrBorder attr, TextAttrBorder clashingAttr, TextAttrBorder absentAttr)"""
+ return _richtext.TextAttrBorder_CollectCommonAttributes(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """SetStyle(self, int style)"""
+ return _richtext.TextAttrBorder_SetStyle(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self) -> int"""
+ return _richtext.TextAttrBorder_GetStyle(*args, **kwargs)
+
+ def SetColour(*args):
+ """
+ SetColour(self, unsigned long colour)
+ SetColour(self, Colour colour)
+ """
+ return _richtext.TextAttrBorder_SetColour(*args)
+
+ def GetColourLong(*args, **kwargs):
+ """GetColourLong(self) -> unsigned long"""
+ return _richtext.TextAttrBorder_GetColourLong(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """GetColour(self) -> Colour"""
+ return _richtext.TextAttrBorder_GetColour(*args, **kwargs)
+
+ def GetWidth(*args):
+ """
+ GetWidth(self) -> TextAttrDimension
+ GetWidth(self) -> TextAttrDimension
+ """
+ return _richtext.TextAttrBorder_GetWidth(*args)
+
+ def SetWidth(*args):
+ """
+ SetWidth(self, TextAttrDimension width)
+ SetWidth(self, int value, int units=TEXT_ATTR_UNITS_TENTHS_MM)
+ """
+ return _richtext.TextAttrBorder_SetWidth(*args)
+
+ def HasStyle(*args, **kwargs):
+ """HasStyle(self) -> bool"""
+ return _richtext.TextAttrBorder_HasStyle(*args, **kwargs)
+
+ def HasColour(*args, **kwargs):
+ """HasColour(self) -> bool"""
+ return _richtext.TextAttrBorder_HasColour(*args, **kwargs)
+
+ def HasWidth(*args, **kwargs):
+ """HasWidth(self) -> bool"""
+ return _richtext.TextAttrBorder_HasWidth(*args, **kwargs)
+
+ def IsValid(*args, **kwargs):
+ """IsValid(self) -> bool"""
+ return _richtext.TextAttrBorder_IsValid(*args, **kwargs)
+
+ def MakeValid(*args, **kwargs):
+ """MakeValid(self)"""
+ return _richtext.TextAttrBorder_MakeValid(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _richtext.TextAttrBorder_GetFlags(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _richtext.TextAttrBorder_SetFlags(*args, **kwargs)
+
+ def AddFlag(*args, **kwargs):
+ """AddFlag(self, int flag)"""
+ return _richtext.TextAttrBorder_AddFlag(*args, **kwargs)
+
+ def RemoveFlag(*args, **kwargs):
+ """RemoveFlag(self, int flag)"""
+ return _richtext.TextAttrBorder_RemoveFlag(*args, **kwargs)
+
+ m_borderStyle = property(_richtext.TextAttrBorder_m_borderStyle_get, _richtext.TextAttrBorder_m_borderStyle_set)
+ m_borderColour = property(_richtext.TextAttrBorder_m_borderColour_get, _richtext.TextAttrBorder_m_borderColour_set)
+ m_borderWidth = property(_richtext.TextAttrBorder_m_borderWidth_get, _richtext.TextAttrBorder_m_borderWidth_set)
+ m_flags = property(_richtext.TextAttrBorder_m_flags_get, _richtext.TextAttrBorder_m_flags_set)
+_richtext.TextAttrBorder_swigregister(TextAttrBorder)
+
+class TextAttrBorders(object):
+ """Proxy of C++ TextAttrBorders class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> TextAttrBorders"""
+ _richtext.TextAttrBorders_swiginit(self,_richtext.new_TextAttrBorders(*args, **kwargs))
+ def __eq__(*args, **kwargs):
+ """__eq__(self, TextAttrBorders borders) -> bool"""
+ return _richtext.TextAttrBorders___eq__(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """SetStyle(self, int style)"""
+ return _richtext.TextAttrBorders_SetStyle(*args, **kwargs)
+
+ def SetColour(*args):
+ """
+ SetColour(self, unsigned long colour)
+ SetColour(self, Colour colour)
+ """
+ return _richtext.TextAttrBorders_SetColour(*args)
+
+ def SetWidth(*args):
+ """
+ SetWidth(self, TextAttrDimension width)
+ SetWidth(self, int value, int units=TEXT_ATTR_UNITS_TENTHS_MM)
+ """
+ return _richtext.TextAttrBorders_SetWidth(*args)
+
+ def Reset(*args, **kwargs):
+ """Reset(self)"""
+ return _richtext.TextAttrBorders_Reset(*args, **kwargs)
+
+ def EqPartial(*args, **kwargs):
+ """EqPartial(self, TextAttrBorders borders) -> bool"""
+ return _richtext.TextAttrBorders_EqPartial(*args, **kwargs)
+
+ def Apply(*args, **kwargs):
+ """Apply(self, TextAttrBorders borders, TextAttrBorders compareWith=None) -> bool"""
+ return _richtext.TextAttrBorders_Apply(*args, **kwargs)
+
+ def RemoveStyle(*args, **kwargs):
+ """RemoveStyle(self, TextAttrBorders attr) -> bool"""
+ return _richtext.TextAttrBorders_RemoveStyle(*args, **kwargs)
+
+ def CollectCommonAttributes(*args, **kwargs):
+ """
+ CollectCommonAttributes(self, TextAttrBorders attr, TextAttrBorders clashingAttr,
+ TextAttrBorders absentAttr)
+ """
+ return _richtext.TextAttrBorders_CollectCommonAttributes(*args, **kwargs)
+
+ def IsValid(*args, **kwargs):
+ """IsValid(self) -> bool"""
+ return _richtext.TextAttrBorders_IsValid(*args, **kwargs)
+
+ def GetLeft(*args):
+ """
+ GetLeft(self) -> TextAttrBorder
+ GetLeft(self) -> TextAttrBorder
+ """
+ return _richtext.TextAttrBorders_GetLeft(*args)
+
+ def GetRight(*args):
+ """
+ GetRight(self) -> TextAttrBorder
+ GetRight(self) -> TextAttrBorder
+ """
+ return _richtext.TextAttrBorders_GetRight(*args)
+
+ def GetTop(*args):
+ """
+ GetTop(self) -> TextAttrBorder
+ GetTop(self) -> TextAttrBorder
+ """
+ return _richtext.TextAttrBorders_GetTop(*args)
+
+ def GetBottom(*args):
+ """
+ GetBottom(self) -> TextAttrBorder
+ GetBottom(self) -> TextAttrBorder
+ """
+ return _richtext.TextAttrBorders_GetBottom(*args)
+
+ m_left = property(_richtext.TextAttrBorders_m_left_get, _richtext.TextAttrBorders_m_left_set)
+ m_right = property(_richtext.TextAttrBorders_m_right_get, _richtext.TextAttrBorders_m_right_set)
+ m_top = property(_richtext.TextAttrBorders_m_top_get, _richtext.TextAttrBorders_m_top_set)
+ m_bottom = property(_richtext.TextAttrBorders_m_bottom_get, _richtext.TextAttrBorders_m_bottom_set)
+_richtext.TextAttrBorders_swigregister(TextAttrBorders)
+
+class TextBoxAttr(object):
+ """Proxy of C++ TextBoxAttr class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self) -> TextBoxAttr
+ __init__(self, TextBoxAttr attr) -> TextBoxAttr
+ """
+ _richtext.TextBoxAttr_swiginit(self,_richtext.new_TextBoxAttr(*args))
+ def Init(*args, **kwargs):
+ """Init(self)"""
+ return _richtext.TextBoxAttr_Init(*args, **kwargs)
+
+ def Reset(*args, **kwargs):
+ """Reset(self)"""
+ return _richtext.TextBoxAttr_Reset(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """__eq__(self, TextBoxAttr attr) -> bool"""
+ return _richtext.TextBoxAttr___eq__(*args, **kwargs)
+
+ def EqPartial(*args, **kwargs):
+ """EqPartial(self, TextBoxAttr attr) -> bool"""
+ return _richtext.TextBoxAttr_EqPartial(*args, **kwargs)
+
+ def Apply(*args, **kwargs):
+ """Apply(self, TextBoxAttr style, TextBoxAttr compareWith=None) -> bool"""
+ return _richtext.TextBoxAttr_Apply(*args, **kwargs)
+
+ def CollectCommonAttributes(*args, **kwargs):
+ """CollectCommonAttributes(self, TextBoxAttr attr, TextBoxAttr clashingAttr, TextBoxAttr absentAttr)"""
+ return _richtext.TextBoxAttr_CollectCommonAttributes(*args, **kwargs)
+
+ def RemoveStyle(*args, **kwargs):
+ """RemoveStyle(self, TextBoxAttr attr) -> bool"""
+ return _richtext.TextBoxAttr_RemoveStyle(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _richtext.TextBoxAttr_SetFlags(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _richtext.TextBoxAttr_GetFlags(*args, **kwargs)
+
+ def HasFlag(*args, **kwargs):
+ """HasFlag(self, int flag) -> bool"""
+ return _richtext.TextBoxAttr_HasFlag(*args, **kwargs)
+
+ def RemoveFlag(*args, **kwargs):
+ """RemoveFlag(self, int flag)"""
+ return _richtext.TextBoxAttr_RemoveFlag(*args, **kwargs)
+
+ def AddFlag(*args, **kwargs):
+ """AddFlag(self, int flag)"""
+ return _richtext.TextBoxAttr_AddFlag(*args, **kwargs)
+
+ def GetFloatMode(*args, **kwargs):
+ """GetFloatMode(self) -> int"""
+ return _richtext.TextBoxAttr_GetFloatMode(*args, **kwargs)
+
+ def SetFloatMode(*args, **kwargs):
+ """SetFloatMode(self, int mode)"""
+ return _richtext.TextBoxAttr_SetFloatMode(*args, **kwargs)
+
+ def HasFloatMode(*args, **kwargs):
+ """HasFloatMode(self) -> bool"""
+ return _richtext.TextBoxAttr_HasFloatMode(*args, **kwargs)
+
+ def IsFloating(*args, **kwargs):
+ """IsFloating(self) -> bool"""
+ return _richtext.TextBoxAttr_IsFloating(*args, **kwargs)
+
+ def GetClearMode(*args, **kwargs):
+ """GetClearMode(self) -> int"""
+ return _richtext.TextBoxAttr_GetClearMode(*args, **kwargs)
+
+ def SetClearMode(*args, **kwargs):
+ """SetClearMode(self, int mode)"""
+ return _richtext.TextBoxAttr_SetClearMode(*args, **kwargs)
+
+ def HasClearMode(*args, **kwargs):
+ """HasClearMode(self) -> bool"""
+ return _richtext.TextBoxAttr_HasClearMode(*args, **kwargs)
+
+ def GetCollapseBorders(*args, **kwargs):
+ """GetCollapseBorders(self) -> int"""
+ return _richtext.TextBoxAttr_GetCollapseBorders(*args, **kwargs)
+
+ def SetCollapseBorders(*args, **kwargs):
+ """SetCollapseBorders(self, int collapse)"""
+ return _richtext.TextBoxAttr_SetCollapseBorders(*args, **kwargs)
+
+ def HasCollapseBorders(*args, **kwargs):
+ """HasCollapseBorders(self) -> bool"""
+ return _richtext.TextBoxAttr_HasCollapseBorders(*args, **kwargs)
+
+ def GetVerticalAlignment(*args, **kwargs):
+ """GetVerticalAlignment(self) -> int"""
+ return _richtext.TextBoxAttr_GetVerticalAlignment(*args, **kwargs)
+
+ def SetVerticalAlignment(*args, **kwargs):
+ """SetVerticalAlignment(self, int verticalAlignment)"""
+ return _richtext.TextBoxAttr_SetVerticalAlignment(*args, **kwargs)
+
+ def HasVerticalAlignment(*args, **kwargs):
+ """HasVerticalAlignment(self) -> bool"""
+ return _richtext.TextBoxAttr_HasVerticalAlignment(*args, **kwargs)
+
+ def GetMargins(*args):
+ """
+ GetMargins(self) -> TextAttrDimensions
+ GetMargins(self) -> TextAttrDimensions
+ """
+ return _richtext.TextBoxAttr_GetMargins(*args)
+
+ def GetLeftMargin(*args):
+ """
+ GetLeftMargin(self) -> TextAttrDimension
+ GetLeftMargin(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetLeftMargin(*args)
+
+ def GetRightMargin(*args):
+ """
+ GetRightMargin(self) -> TextAttrDimension
+ GetRightMargin(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetRightMargin(*args)
+
+ def GetTopMargin(*args):
+ """
+ GetTopMargin(self) -> TextAttrDimension
+ GetTopMargin(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetTopMargin(*args)
+
+ def GetBottomMargin(*args):
+ """
+ GetBottomMargin(self) -> TextAttrDimension
+ GetBottomMargin(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetBottomMargin(*args)
+
+ def GetPosition(*args):
+ """
+ GetPosition(self) -> TextAttrDimensions
+ GetPosition(self) -> TextAttrDimensions
+ """
+ return _richtext.TextBoxAttr_GetPosition(*args)
+
+ def GetLeft(*args):
+ """
+ GetLeft(self) -> TextAttrDimension
+ GetLeft(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetLeft(*args)
+
+ def GetRight(*args):
+ """
+ GetRight(self) -> TextAttrDimension
+ GetRight(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetRight(*args)
+
+ def GetTop(*args):
+ """
+ GetTop(self) -> TextAttrDimension
+ GetTop(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetTop(*args)
+
+ def GetBottom(*args):
+ """
+ GetBottom(self) -> TextAttrDimension
+ GetBottom(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetBottom(*args)
+
+ def GetPadding(*args):
+ """
+ GetPadding(self) -> TextAttrDimensions
+ GetPadding(self) -> TextAttrDimensions
+ """
+ return _richtext.TextBoxAttr_GetPadding(*args)
+
+ def GetLeftPadding(*args):
+ """
+ GetLeftPadding(self) -> TextAttrDimension
+ GetLeftPadding(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetLeftPadding(*args)
+
+ def GetRightPadding(*args):
+ """
+ GetRightPadding(self) -> TextAttrDimension
+ GetRightPadding(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetRightPadding(*args)
+
+ def GetTopPadding(*args):
+ """
+ GetTopPadding(self) -> TextAttrDimension
+ GetTopPadding(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetTopPadding(*args)
+
+ def GetBottomPadding(*args):
+ """
+ GetBottomPadding(self) -> TextAttrDimension
+ GetBottomPadding(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetBottomPadding(*args)
+
+ def GetBorder(*args):
+ """
+ GetBorder(self) -> TextAttrBorders
+ GetBorder(self) -> TextAttrBorders
+ """
+ return _richtext.TextBoxAttr_GetBorder(*args)
+
+ def GetLeftBorder(*args):
+ """
+ GetLeftBorder(self) -> TextAttrBorder
+ GetLeftBorder(self) -> TextAttrBorder
+ """
+ return _richtext.TextBoxAttr_GetLeftBorder(*args)
+
+ def GetTopBorder(*args):
+ """
+ GetTopBorder(self) -> TextAttrBorder
+ GetTopBorder(self) -> TextAttrBorder
+ """
+ return _richtext.TextBoxAttr_GetTopBorder(*args)
+
+ def GetRightBorder(*args):
+ """
+ GetRightBorder(self) -> TextAttrBorder
+ GetRightBorder(self) -> TextAttrBorder
+ """
+ return _richtext.TextBoxAttr_GetRightBorder(*args)
+
+ def GetBottomBorder(*args):
+ """
+ GetBottomBorder(self) -> TextAttrBorder
+ GetBottomBorder(self) -> TextAttrBorder
+ """
+ return _richtext.TextBoxAttr_GetBottomBorder(*args)
+
+ def GetOutline(*args):
+ """
+ GetOutline(self) -> TextAttrBorders
+ GetOutline(self) -> TextAttrBorders
+ """
+ return _richtext.TextBoxAttr_GetOutline(*args)
+
+ def GetLeftOutline(*args):
+ """
+ GetLeftOutline(self) -> TextAttrBorder
+ GetLeftOutline(self) -> TextAttrBorder
+ """
+ return _richtext.TextBoxAttr_GetLeftOutline(*args)
+
+ def GetTopOutline(*args):
+ """
+ GetTopOutline(self) -> TextAttrBorder
+ GetTopOutline(self) -> TextAttrBorder
+ """
+ return _richtext.TextBoxAttr_GetTopOutline(*args)
+
+ def GetRightOutline(*args):
+ """
+ GetRightOutline(self) -> TextAttrBorder
+ GetRightOutline(self) -> TextAttrBorder
+ """
+ return _richtext.TextBoxAttr_GetRightOutline(*args)
+
+ def GetBottomOutline(*args):
+ """
+ GetBottomOutline(self) -> TextAttrBorder
+ GetBottomOutline(self) -> TextAttrBorder
+ """
+ return _richtext.TextBoxAttr_GetBottomOutline(*args)
+
+ def GetSize(*args):
+ """
+ GetSize(self) -> wxTextAttrSize
+ GetSize(self) -> wxTextAttrSize
+ """
+ return _richtext.TextBoxAttr_GetSize(*args)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, wxTextAttrSize sz)"""
+ return _richtext.TextBoxAttr_SetSize(*args, **kwargs)
+
+ def GetWidth(*args):
+ """
+ GetWidth(self) -> TextAttrDimension
+ GetWidth(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetWidth(*args)
+
+ def GetHeight(*args):
+ """
+ GetHeight(self) -> TextAttrDimension
+ GetHeight(self) -> TextAttrDimension
+ """
+ return _richtext.TextBoxAttr_GetHeight(*args)
+
+ def GetBoxStyleName(*args, **kwargs):
+ """GetBoxStyleName(self) -> String"""
+ return _richtext.TextBoxAttr_GetBoxStyleName(*args, **kwargs)
+
+ def SetBoxStyleName(*args, **kwargs):
+ """SetBoxStyleName(self, String name)"""
+ return _richtext.TextBoxAttr_SetBoxStyleName(*args, **kwargs)
+
+ def HasBoxStyleName(*args, **kwargs):
+ """HasBoxStyleName(self) -> bool"""
+ return _richtext.TextBoxAttr_HasBoxStyleName(*args, **kwargs)
+
+ m_flags = property(_richtext.TextBoxAttr_m_flags_get, _richtext.TextBoxAttr_m_flags_set)
+ m_margins = property(_richtext.TextBoxAttr_m_margins_get, _richtext.TextBoxAttr_m_margins_set)
+ m_padding = property(_richtext.TextBoxAttr_m_padding_get, _richtext.TextBoxAttr_m_padding_set)
+ m_position = property(_richtext.TextBoxAttr_m_position_get, _richtext.TextBoxAttr_m_position_set)
+ m_size = property(_richtext.TextBoxAttr_m_size_get, _richtext.TextBoxAttr_m_size_set)
+ m_border = property(_richtext.TextBoxAttr_m_border_get, _richtext.TextBoxAttr_m_border_set)
+ m_outline = property(_richtext.TextBoxAttr_m_outline_get, _richtext.TextBoxAttr_m_outline_set)
+ m_floatMode = property(_richtext.TextBoxAttr_m_floatMode_get, _richtext.TextBoxAttr_m_floatMode_set)
+ m_clearMode = property(_richtext.TextBoxAttr_m_clearMode_get, _richtext.TextBoxAttr_m_clearMode_set)
+ m_collapseMode = property(_richtext.TextBoxAttr_m_collapseMode_get, _richtext.TextBoxAttr_m_collapseMode_set)
+ m_verticalAlignment = property(_richtext.TextBoxAttr_m_verticalAlignment_get, _richtext.TextBoxAttr_m_verticalAlignment_set)
+ m_boxStyleName = property(_richtext.TextBoxAttr_m_boxStyleName_get, _richtext.TextBoxAttr_m_boxStyleName_set)
+_richtext.TextBoxAttr_swigregister(TextBoxAttr)
+
+#---------------------------------------------------------------------------
+
+class RichTextAttr(_controls.TextAttr):
+ """Proxy of C++ RichTextAttr class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, TextAttr attr) -> RichTextAttr
+ __init__(self, RichTextAttr attr) -> RichTextAttr
+ __init__(self) -> RichTextAttr
+ """
+ _richtext.RichTextAttr_swiginit(self,_richtext.new_RichTextAttr(*args))
+ __swig_destroy__ = _richtext.delete_RichTextAttr
+ __del__ = lambda self : None;
+ def Copy(*args, **kwargs):
+ """Copy(self, RichTextAttr attr)"""
+ return _richtext.RichTextAttr_Copy(*args, **kwargs)
+
+ def __eq__(*args, **kwargs):
+ """__eq__(self, RichTextAttr attr) -> bool"""
+ return _richtext.RichTextAttr___eq__(*args, **kwargs)
+
+ def EqPartial(*args, **kwargs):
+ """EqPartial(self, RichTextAttr attr) -> bool"""
+ return _richtext.RichTextAttr_EqPartial(*args, **kwargs)
+
+ def Apply(*args, **kwargs):
+ """Apply(self, RichTextAttr style, RichTextAttr compareWith=None) -> bool"""
+ return _richtext.RichTextAttr_Apply(*args, **kwargs)
+
+ def CollectCommonAttributes(*args, **kwargs):
+ """CollectCommonAttributes(self, RichTextAttr attr, RichTextAttr clashingAttr, RichTextAttr absentAttr)"""
+ return _richtext.RichTextAttr_CollectCommonAttributes(*args, **kwargs)
+
+ def RemoveStyle(*args, **kwargs):
+ """RemoveStyle(self, RichTextAttr attr) -> bool"""
+ return _richtext.RichTextAttr_RemoveStyle(*args, **kwargs)
+
+ def GetTextBoxAttr(*args):
+ """
+ GetTextBoxAttr(self) -> TextBoxAttr
+ GetTextBoxAttr(self) -> TextBoxAttr
+ """
+ return _richtext.RichTextAttr_GetTextBoxAttr(*args)
+
+ def SetTextBoxAttr(*args, **kwargs):
+ """SetTextBoxAttr(self, TextBoxAttr attr)"""
+ return _richtext.RichTextAttr_SetTextBoxAttr(*args, **kwargs)
+
+ m_textBoxAttr = property(_richtext.RichTextAttr_m_textBoxAttr_get, _richtext.RichTextAttr_m_textBoxAttr_set)
+_richtext.RichTextAttr_swigregister(RichTextAttr)
+
+class RichTextFontTable(_core.Object):
+ """Proxy of C++ RichTextFontTable class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> RichTextFontTable"""
+ _richtext.RichTextFontTable_swiginit(self,_richtext.new_RichTextFontTable(*args, **kwargs))
+ __swig_destroy__ = _richtext.delete_RichTextFontTable
+ __del__ = lambda self : None;
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _richtext.RichTextFontTable_IsOk(*args, **kwargs)
+
+ def FindFont(*args, **kwargs):
+ """FindFont(self, RichTextAttr fontSpec) -> Font"""
+ return _richtext.RichTextFontTable_FindFont(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """Clear(self)"""
+ return _richtext.RichTextFontTable_Clear(*args, **kwargs)
+
+_richtext.RichTextFontTable_swigregister(RichTextFontTable)
+
+class RichTextRange(object):
+ """
+ RichTextRange is a data structure that represents a range of text
+ within a `RichTextCtrl`. It simply contains integer ``start`` and
+ ``end`` properties and a few operations useful for dealing with
+ ranges. In most places in wxPython where a RichTextRange is expected a
+ 2-tuple containing (start, end) can be used instead.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, long start=0, long end=0) -> RichTextRange
+
+ Creates a new range object.
+ """
+ _richtext.RichTextRange_swiginit(self,_richtext.new_RichTextRange(*args, **kwargs))
+ __swig_destroy__ = _richtext.delete_RichTextRange
+ __del__ = lambda self : None;
+ def __eq__(*args, **kwargs):
+ """
+ __eq__(self, PyObject other) -> bool
+
+ Test for equality of RichTextRange objects.
+ """
+ return _richtext.RichTextRange___eq__(*args, **kwargs)
+
+ def __sub__(*args, **kwargs):
+ """__sub__(self, RichTextRange range) -> RichTextRange"""
+ return _richtext.RichTextRange___sub__(*args, **kwargs)
+
+ def __add__(*args, **kwargs):
+ """__add__(self, RichTextRange range) -> RichTextRange"""
+ return _richtext.RichTextRange___add__(*args, **kwargs)
+
+ def SetRange(*args, **kwargs):
+ """SetRange(self, long start, long end)"""
+ return _richtext.RichTextRange_SetRange(*args, **kwargs)
+
+ def SetStart(*args, **kwargs):
+ """SetStart(self, long start)"""
+ return _richtext.RichTextRange_SetStart(*args, **kwargs)
+
+ def GetStart(*args, **kwargs):
+ """GetStart(self) -> long"""
+ return _richtext.RichTextRange_GetStart(*args, **kwargs)
+
+ start = property(GetStart, SetStart)
+ def SetEnd(*args, **kwargs):
+ """SetEnd(self, long end)"""
+ return _richtext.RichTextRange_SetEnd(*args, **kwargs)
+
+ def GetEnd(*args, **kwargs):
+ """GetEnd(self) -> long"""
+ return _richtext.RichTextRange_GetEnd(*args, **kwargs)
+
+ end = property(GetEnd, SetEnd)
+ def IsOutside(*args, **kwargs):
+ """
+ IsOutside(self, RichTextRange range) -> bool
+
+ Returns true if this range is completely outside 'range'
+ """
+ return _richtext.RichTextRange_IsOutside(*args, **kwargs)
+
+ def IsWithin(*args, **kwargs):
+ """
+ IsWithin(self, RichTextRange range) -> bool
+
+ Returns true if this range is completely within 'range'
+ """
+ return _richtext.RichTextRange_IsWithin(*args, **kwargs)
+
+ def Contains(*args, **kwargs):
+ """
+ Contains(self, long pos) -> bool
+
+ Returns true if the given position is within this range. Allow for the
+ possibility of an empty range - assume the position is within this
+ empty range.
+ """
+ return _richtext.RichTextRange_Contains(*args, **kwargs)
+
+ def LimitTo(*args, **kwargs):
+ """
+ LimitTo(self, RichTextRange range) -> bool
+
+ Limit this range to be within 'range'
+ """
+ return _richtext.RichTextRange_LimitTo(*args, **kwargs)
+
+ def GetLength(*args, **kwargs):
+ """
+ GetLength(self) -> long
+
+ Gets the length of the range
+ """
+ return _richtext.RichTextRange_GetLength(*args, **kwargs)
+
+ def Swap(*args, **kwargs):
+ """
+ Swap(self)
+
+ Swaps the start and end
+ """
+ return _richtext.RichTextRange_Swap(*args, **kwargs)
+
+ def ToInternal(*args, **kwargs):
+ """
+ ToInternal(self) -> RichTextRange
+
+ Convert to internal form: (n, n) is the range of a single character.
+ """
+ return _richtext.RichTextRange_ToInternal(*args, **kwargs)
+
+ def FromInternal(*args, **kwargs):
+ """
+ FromInternal(self) -> RichTextRange
+
+ Convert from internal to public API form: (n, n+1) is the range of a
+ single character.
+ """
+ return _richtext.RichTextRange_FromInternal(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """
+ Get() -> (start,end)
+
+ Returns the start and end properties as a tuple.
+ """
+ return _richtext.RichTextRange_Get(*args, **kwargs)
+
+ def __str__(self): return str(self.Get())
+ def __repr__(self): return 'RichTextRange'+str(self.Get())
+ def __len__(self): return len(self.Get())
+ def __getitem__(self, index): return self.Get()[index]
+ def __setitem__(self, index, val):
+ if index == 0: self.start = val
+ elif index == 1: self.end = val
+ else: raise IndexError
+ def __nonzero__(self): return self.Get() != (0,0)
+ __safe_for_unpickling__ = True
+ def __reduce__(self): return (RichTextRange, self.Get())
+
+ End = property(GetEnd,SetEnd,doc="See `GetEnd` and `SetEnd`")
+ Length = property(GetLength,doc="See `GetLength`")
+ Start = property(GetStart,SetStart,doc="See `GetStart` and `SetStart`")
+_richtext.RichTextRange_swigregister(RichTextRange)
+
+class RichTextDrawingContext(_core.Object):
+ """Proxy of C++ RichTextDrawingContext class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, RichTextBuffer buffer) -> RichTextDrawingContext"""
+ _richtext.RichTextDrawingContext_swiginit(self,_richtext.new_RichTextDrawingContext(*args, **kwargs))
+ def Init(*args, **kwargs):
+ """Init(self)"""
+ return _richtext.RichTextDrawingContext_Init(*args, **kwargs)
+
+ def HasVirtualAttributes(*args, **kwargs):
+ """HasVirtualAttributes(self, RichTextObject obj) -> bool"""
+ return _richtext.RichTextDrawingContext_HasVirtualAttributes(*args, **kwargs)
+
+ def GetVirtualAttributes(*args, **kwargs):
+ """GetVirtualAttributes(self, RichTextObject obj) -> RichTextAttr"""
+ return _richtext.RichTextDrawingContext_GetVirtualAttributes(*args, **kwargs)
+
+ def ApplyVirtualAttributes(*args, **kwargs):
+ """ApplyVirtualAttributes(self, RichTextAttr attr, RichTextObject obj) -> bool"""
+ return _richtext.RichTextDrawingContext_ApplyVirtualAttributes(*args, **kwargs)
+
+ m_buffer = property(_richtext.RichTextDrawingContext_m_buffer_get, _richtext.RichTextDrawingContext_m_buffer_set)
+_richtext.RichTextDrawingContext_swigregister(RichTextDrawingContext)
+cvar = _richtext.cvar
+RICHTEXT_ALL = cvar.RICHTEXT_ALL
+RICHTEXT_NONE = cvar.RICHTEXT_NONE
+
+class RichTextObject(_core.Object):
+ """
+ This is the base class for all drawable objects in a `RichTextCtrl`.
+
+ The data displayed in a `RichTextCtrl` is handled by `RichTextBuffer`,
+ and a `RichTextCtrl` always has one such buffer.
+
+ The content is represented by a hierarchy of objects, all derived from
+ `RichTextObject`. An object might be an image, a fragment of text, a
+ paragraph, or a whole buffer. Objects store a an attribute object
+ containing style information; a paragraph object can contain both
+ paragraph and character information, but content objects such as text
+ can only store character information. The final style displayed in the
+ control or in a printout is a combination of base style, paragraph
+ style and content (character) style.
+
+ The top of the hierarchy is the buffer, a kind of
+ `RichTextParagraphLayoutBox`. containing further `RichTextParagraph`
+ objects, each of which can include text, images and potentially other
+ types of objects.
+
+ Each object maintains a range (start and end position) measured from
+ the start of the main parent object.
+
+ When Layout is called on an object, it is given a size which the
+ object must limit itself to, or one or more flexible directions
+ (vertical or horizontal). So, for example, a centred paragraph is
+ given the page width to play with (minus any margins), but can extend
+ indefinitely in the vertical direction. The implementation of Layout
+ caches the calculated size and position.
+
+ When the buffer is modified, a range is invalidated (marked as
+ requiring layout), so that only the minimum amount of layout is
+ performed.
+
+ A paragraph of pure text with the same style contains just one further
+ object, a `RichTextPlainText` object. When styling is applied to part
+ of this object, the object is decomposed into separate objects, one
+ object for each different character style. So each object within a
+ paragraph always has just one attribute object to denote its character
+ style. Of course, this can lead to fragmentation after a lot of edit
+ operations, potentially leading to several objects with the same style
+ where just one would do. So a Defragment function is called when
+ updating the control's display, to ensure that the minimum number of
+ objects is used.
+
+ To implement your own RichTextObjects in Python you must derive a
+ class from `PyRichTextObject`, which has been instrumented to forward
+ the virtual C++ method calls to the Python methods in the derived
+ class. (This class hasn't been implemented yet!)
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _richtext.delete_RichTextObject
+ __del__ = lambda self : None;
+ def Draw(*args, **kwargs):
+ """
+ Draw(self, DC dc, RichTextDrawingContext context, RichTextRange range,
+ wxRichTextSelection selection, Rect rect,
+ int descent, int style) -> bool
+ """
+ return _richtext.RichTextObject_Draw(*args, **kwargs)
+
+ def Layout(*args, **kwargs):
+ """
+ Layout(self, DC dc, RichTextDrawingContext context, Rect rect, Rect parentRect,
+ int style) -> bool
+ """
+ return _richtext.RichTextObject_Layout(*args, **kwargs)
+
+ def HitTest(*args, **kwargs):
+ """
+ HitTest(self, DC dc, RichTextDrawingContext context, Point pt, long OUTPUT,
+ RichTextObject obj, RichTextObject contextObj,
+ int flags=0) -> int
+ """
+ return _richtext.RichTextObject_HitTest(*args, **kwargs)
+
+ def FindPosition(*args, **kwargs):
+ """
+ FindPosition(self, DC dc, RichTextDrawingContext context, long index,
+ Point OUTPUT, int OUTPUT, bool forceLineStart) -> bool
+ """
+ return _richtext.RichTextObject_FindPosition(*args, **kwargs)
+
+ def GetBestSize(*args, **kwargs):
+ """GetBestSize(self) -> Size"""
+ return _richtext.RichTextObject_GetBestSize(*args, **kwargs)
+
+ def GetRangeSize(*args, **kwargs):
+ """
+ GetRangeSize(self, RichTextRange range, Size OUTPUT, int OUTPUT, DC dc,
+ RichTextDrawingContext context, int flags,
+ Point position=wxPoint(0,0)) -> bool
+ """
+ return _richtext.RichTextObject_GetRangeSize(*args, **kwargs)
+
+ def DoSplit(*args, **kwargs):
+ """DoSplit(self, long pos) -> RichTextObject"""
+ return _richtext.RichTextObject_DoSplit(*args, **kwargs)
+
+ def CalculateRange(*args, **kwargs):
+ """CalculateRange(self, long start, long OUTPUT)"""
+ return _richtext.RichTextObject_CalculateRange(*args, **kwargs)
+
+ def DeleteRange(*args, **kwargs):
+ """DeleteRange(self, RichTextRange range) -> bool"""
+ return _richtext.RichTextObject_DeleteRange(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """IsEmpty(self) -> bool"""
+ return _richtext.RichTextObject_IsEmpty(*args, **kwargs)
+
+ def IsFloatable(*args, **kwargs):
+ """IsFloatable(self) -> bool"""
+ return _richtext.RichTextObject_IsFloatable(*args, **kwargs)
+
+ def IsFloating(*args, **kwargs):
+ """IsFloating(self) -> bool"""
+ return _richtext.RichTextObject_IsFloating(*args, **kwargs)
+
+ def GetFloatDirection(*args, **kwargs):
+ """GetFloatDirection(self) -> int"""
+ return _richtext.RichTextObject_GetFloatDirection(*args, **kwargs)
+
+ def GetTextForRange(*args, **kwargs):
+ """GetTextForRange(self, RichTextRange range) -> String"""
+ return _richtext.RichTextObject_GetTextForRange(*args, **kwargs)
+
+ def CanMerge(*args, **kwargs):
+ """CanMerge(self, RichTextObject object, RichTextDrawingContext context) -> bool"""
+ return _richtext.RichTextObject_CanMerge(*args, **kwargs)
+
+ def Merge(self, obj, context):
+ """Merge(self, RichTextObject object) -> bool"""
+ val = _richtext.RichTextObject_Merge(self, obj, context)
+ if val:
+ obj.this.own(True)
+ return val
+
+
+ def Dump(*args, **kwargs):
+ """Dump(self) -> String"""
+ return _richtext.RichTextObject_Dump(*args, **kwargs)
+
+ def CanEditProperties(*args, **kwargs):
+ """CanEditProperties(self) -> bool"""
+ return _richtext.RichTextObject_CanEditProperties(*args, **kwargs)
+
+ def EditProperties(*args, **kwargs):
+ """EditProperties(self, Window parent, RichTextBuffer buffer) -> bool"""
+ return _richtext.RichTextObject_EditProperties(*args, **kwargs)
+
+ def ImportFromXML(*args, **kwargs):
+ """
+ ImportFromXML(self, RichTextBuffer buffer, wxXmlNode node, RichTextXMLHandler handler,
+ bool recurse) -> bool
+ """
+ return _richtext.RichTextObject_ImportFromXML(*args, **kwargs)
+
+ def ExportXML(*args):
+ """
+ ExportXML(self, wxOutputStream stream, int indent, RichTextXMLHandler handler) -> bool
+ ExportXML(self, wxXmlNode parent, RichTextXMLHandler handler) -> bool
+ """
+ return _richtext.RichTextObject_ExportXML(*args)
+
+ def UsesParagraphAttributes(*args, **kwargs):
+ """UsesParagraphAttributes(self) -> bool"""
+ return _richtext.RichTextObject_UsesParagraphAttributes(*args, **kwargs)
+
+ def GetXMLNodeName(*args, **kwargs):
+ """GetXMLNodeName(self) -> String"""
+ return _richtext.RichTextObject_GetXMLNodeName(*args, **kwargs)
+
+ def GetCachedSize(*args, **kwargs):
+ """GetCachedSize(self) -> Size"""
+ return _richtext.RichTextObject_GetCachedSize(*args, **kwargs)
+
+ def SetCachedSize(*args, **kwargs):
+ """SetCachedSize(self, Size sz)"""
+ return _richtext.RichTextObject_SetCachedSize(*args, **kwargs)
+
+ CachedSize = property(GetCachedSize,SetCachedSize)
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point"""
+ return _richtext.RichTextObject_GetPosition(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, Point pos)"""
+ return _richtext.RichTextObject_SetPosition(*args, **kwargs)
+
+ Position = property(GetPosition,SetPosition)
+ def GetRect(*args, **kwargs):
+ """GetRect(self) -> Rect"""
+ return _richtext.RichTextObject_GetRect(*args, **kwargs)
+
+ Rect = property(GetRect)
+ def SetRange(*args, **kwargs):
+ """SetRange(self, RichTextRange range)"""
+ return _richtext.RichTextObject_SetRange(*args, **kwargs)
+
+ def GetRange(*args, **kwargs):
+ """GetRange(self) -> RichTextRange"""
+ return _richtext.RichTextObject_GetRange(*args, **kwargs)
+
+ Range = property(GetRange,SetRange)
+ def IsComposite(*args, **kwargs):
+ """IsComposite(self) -> bool"""
+ return _richtext.RichTextObject_IsComposite(*args, **kwargs)
+
+ def GetParent(*args, **kwargs):
+ """GetParent(self) -> RichTextObject"""
+ return _richtext.RichTextObject_GetParent(*args, **kwargs)
+
+ def SetParent(*args, **kwargs):
+ """SetParent(self, RichTextObject parent)"""
+ return _richtext.RichTextObject_SetParent(*args, **kwargs)
+
+ Parent = property(GetParent,SetParent)
+ def SetSameMargins(*args, **kwargs):
+ """SetSameMargins(self, int margin)"""
+ return _richtext.RichTextObject_SetSameMargins(*args, **kwargs)
+
+ def SetMargins(*args, **kwargs):
+ """SetMargins(self, int leftMargin, int rightMargin, int topMargin, int bottomMargin)"""
+ return _richtext.RichTextObject_SetMargins(*args, **kwargs)
+
+ def GetLeftMargin(*args, **kwargs):
+ """GetLeftMargin(self) -> int"""
+ return _richtext.RichTextObject_GetLeftMargin(*args, **kwargs)
+
+ def GetRightMargin(*args, **kwargs):
+ """GetRightMargin(self) -> int"""
+ return _richtext.RichTextObject_GetRightMargin(*args, **kwargs)
+
+ def GetTopMargin(*args, **kwargs):
+ """GetTopMargin(self) -> int"""
+ return _richtext.RichTextObject_GetTopMargin(*args, **kwargs)
+
+ def GetBottomMargin(*args, **kwargs):
+ """GetBottomMargin(self) -> int"""
+ return _richtext.RichTextObject_GetBottomMargin(*args, **kwargs)
+
+ def SetAttributes(*args, **kwargs):
+ """SetAttributes(self, RichTextAttr attr)"""
+ return _richtext.RichTextObject_SetAttributes(*args, **kwargs)
+
+ def GetAttributes(*args, **kwargs):
+ """GetAttributes(self) -> RichTextAttr"""
+ return _richtext.RichTextObject_GetAttributes(*args, **kwargs)
+
+ Attributes = property(GetAttributes,SetAttributes)
+ def SetDescent(*args, **kwargs):
+ """SetDescent(self, int descent)"""
+ return _richtext.RichTextObject_SetDescent(*args, **kwargs)
+
+ def GetDescent(*args, **kwargs):
+ """GetDescent(self) -> int"""
+ return _richtext.RichTextObject_GetDescent(*args, **kwargs)
+
+ Descent = property(GetDescent,SetDescent)
+ def GetBuffer(*args, **kwargs):
+ """GetBuffer(self) -> RichTextBuffer"""
+ return _richtext.RichTextObject_GetBuffer(*args, **kwargs)
+
+ def Clone(*args, **kwargs):
+ """Clone(self) -> RichTextObject"""
+ return _richtext.RichTextObject_Clone(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self, RichTextObject obj)"""
+ return _richtext.RichTextObject_Copy(*args, **kwargs)
+
+ def Reference(*args, **kwargs):
+ """Reference(self)"""
+ return _richtext.RichTextObject_Reference(*args, **kwargs)
+
+ def Dereference(*args, **kwargs):
+ """Dereference(self)"""
+ return _richtext.RichTextObject_Dereference(*args, **kwargs)
+
+ def ConvertTenthsMMToPixelsDC(*args, **kwargs):
+ """ConvertTenthsMMToPixelsDC(self, DC dc, int units) -> int"""
+ return _richtext.RichTextObject_ConvertTenthsMMToPixelsDC(*args, **kwargs)
+
+ def ConvertTenthsMMToPixels(*args, **kwargs):
+ """ConvertTenthsMMToPixels(int ppi, int units, double scale=1.0) -> int"""
+ return _richtext.RichTextObject_ConvertTenthsMMToPixels(*args, **kwargs)
+
+ ConvertTenthsMMToPixels = staticmethod(ConvertTenthsMMToPixels)
+ def ConvertPixelsToTenthsMM(*args):
+ """
+ ConvertPixelsToTenthsMM(DC dc, int pixels) -> int
+ ConvertPixelsToTenthsMM(int ppi, int pixels, double scale=1.0) -> int
+ """
+ return _richtext.RichTextObject_ConvertPixelsToTenthsMM(*args)
+
+ ConvertPixelsToTenthsMM = staticmethod(ConvertPixelsToTenthsMM)
+ def DrawBoxAttributes(*args, **kwargs):
+ """
+ DrawBoxAttributes(DC dc, RichTextBuffer buffer, RichTextAttr attr, Rect boxRect,
+ int flags=0) -> bool
+ """
+ return _richtext.RichTextObject_DrawBoxAttributes(*args, **kwargs)
+
+ DrawBoxAttributes = staticmethod(DrawBoxAttributes)
+ def DrawBorder(*args, **kwargs):
+ """
+ DrawBorder(DC dc, RichTextBuffer buffer, TextAttrBorders attr,
+ Rect rect, int flags=0) -> bool
+ """
+ return _richtext.RichTextObject_DrawBorder(*args, **kwargs)
+
+ DrawBorder = staticmethod(DrawBorder)
+ def GetBoxRects(*args, **kwargs):
+ """
+ GetBoxRects(DC dc, RichTextBuffer buffer, RichTextAttr attr, Rect marginRect,
+ Rect borderRect, Rect contentRect,
+ Rect paddingRect, Rect outlineRect) -> bool
+ """
+ return _richtext.RichTextObject_GetBoxRects(*args, **kwargs)
+
+ GetBoxRects = staticmethod(GetBoxRects)
+ def GetTotalMargin(*args, **kwargs):
+ """
+ GetTotalMargin(DC dc, RichTextBuffer buffer, RichTextAttr attr, int leftMargin,
+ int rightMargin, int topMargin,
+ int bottomMargin) -> bool
+ """
+ return _richtext.RichTextObject_GetTotalMargin(*args, **kwargs)
+
+ GetTotalMargin = staticmethod(GetTotalMargin)
+ def AdjustAvailableSpace(*args, **kwargs):
+ """
+ AdjustAvailableSpace(DC dc, RichTextBuffer buffer, RichTextAttr parentAttr,
+ RichTextAttr childAttr, Rect availableParentSpace,
+ Rect availableContainerSpace) -> Rect
+ """
+ return _richtext.RichTextObject_AdjustAvailableSpace(*args, **kwargs)
+
+ AdjustAvailableSpace = staticmethod(AdjustAvailableSpace)
+_richtext.RichTextObject_swigregister(RichTextObject)
+
+def RichTextObject_ConvertTenthsMMToPixels(*args, **kwargs):
+ """RichTextObject_ConvertTenthsMMToPixels(int ppi, int units, double scale=1.0) -> int"""
+ return _richtext.RichTextObject_ConvertTenthsMMToPixels(*args, **kwargs)
+
+def RichTextObject_ConvertPixelsToTenthsMM(*args):
+ """
+ ConvertPixelsToTenthsMM(DC dc, int pixels) -> int
+ RichTextObject_ConvertPixelsToTenthsMM(int ppi, int pixels, double scale=1.0) -> int
+ """
+ return _richtext.RichTextObject_ConvertPixelsToTenthsMM(*args)
+
+def RichTextObject_DrawBoxAttributes(*args, **kwargs):
+ """
+ RichTextObject_DrawBoxAttributes(DC dc, RichTextBuffer buffer, RichTextAttr attr, Rect boxRect,
+ int flags=0) -> bool
+ """
+ return _richtext.RichTextObject_DrawBoxAttributes(*args, **kwargs)
+
+def RichTextObject_DrawBorder(*args, **kwargs):
+ """
+ RichTextObject_DrawBorder(DC dc, RichTextBuffer buffer, TextAttrBorders attr,
+ Rect rect, int flags=0) -> bool
+ """
+ return _richtext.RichTextObject_DrawBorder(*args, **kwargs)
+
+def RichTextObject_GetBoxRects(*args, **kwargs):
+ """
+ RichTextObject_GetBoxRects(DC dc, RichTextBuffer buffer, RichTextAttr attr, Rect marginRect,
+ Rect borderRect, Rect contentRect,
+ Rect paddingRect, Rect outlineRect) -> bool
+ """
+ return _richtext.RichTextObject_GetBoxRects(*args, **kwargs)
+
+def RichTextObject_GetTotalMargin(*args, **kwargs):
+ """
+ RichTextObject_GetTotalMargin(DC dc, RichTextBuffer buffer, RichTextAttr attr, int leftMargin,
+ int rightMargin, int topMargin,
+ int bottomMargin) -> bool
+ """
+ return _richtext.RichTextObject_GetTotalMargin(*args, **kwargs)
+
+def RichTextObject_AdjustAvailableSpace(*args, **kwargs):
+ """
+ RichTextObject_AdjustAvailableSpace(DC dc, RichTextBuffer buffer, RichTextAttr parentAttr,
+ RichTextAttr childAttr, Rect availableParentSpace,
+ Rect availableContainerSpace) -> Rect
+ """
+ return _richtext.RichTextObject_AdjustAvailableSpace(*args, **kwargs)
+
+class RichTextObjectList_iterator(object):
+ """This class serves as an iterator for a wxRichTextObjectList object."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _richtext.delete_RichTextObjectList_iterator
+ __del__ = lambda self : None;
+ def next(*args, **kwargs):
+ """next(self) -> RichTextObject"""
+ return _richtext.RichTextObjectList_iterator_next(*args, **kwargs)
+
+_richtext.RichTextObjectList_iterator_swigregister(RichTextObjectList_iterator)
+
+class RichTextObjectList(object):
+ """
+ This class wraps a wxList-based class and gives it a Python
+ sequence-like interface. Sequence operations supported are length,
+ index access and iteration.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _richtext.delete_RichTextObjectList
+ __del__ = lambda self : None;
+ def __len__(*args, **kwargs):
+ """__len__(self) -> size_t"""
+ return _richtext.RichTextObjectList___len__(*args, **kwargs)
+
+ def __getitem__(*args, **kwargs):
+ """__getitem__(self, size_t index) -> RichTextObject"""
+ return _richtext.RichTextObjectList___getitem__(*args, **kwargs)
+
+ def __contains__(*args, **kwargs):
+ """__contains__(self, RichTextObject obj) -> bool"""
+ return _richtext.RichTextObjectList___contains__(*args, **kwargs)
+
+ def __iter__(*args, **kwargs):
+ """__iter__(self) -> RichTextObjectList_iterator"""
+ return _richtext.RichTextObjectList___iter__(*args, **kwargs)
+
+ def index(*args, **kwargs):
+ """index(self, RichTextObject obj) -> int"""
+ return _richtext.RichTextObjectList_index(*args, **kwargs)
+
+ def __repr__(self):
+ return "wxRichTextObjectList: " + repr(list(self))
+
+_richtext.RichTextObjectList_swigregister(RichTextObjectList)
+
+class RichTextCompositeObject(RichTextObject):
+ """Objects of this class can contain other rich text objects."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _richtext.delete_RichTextCompositeObject
+ __del__ = lambda self : None;
+ def GetChildren(*args, **kwargs):
+ """GetChildren(self) -> RichTextObjectList"""
+ return _richtext.RichTextCompositeObject_GetChildren(*args, **kwargs)
+
+ def GetChildCount(*args, **kwargs):
+ """GetChildCount(self) -> size_t"""
+ return _richtext.RichTextCompositeObject_GetChildCount(*args, **kwargs)
+
+ def GetChild(*args, **kwargs):
+ """GetChild(self, size_t n) -> RichTextObject"""
+ return _richtext.RichTextCompositeObject_GetChild(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self, RichTextCompositeObject obj)"""
+ return _richtext.RichTextCompositeObject_Copy(*args, **kwargs)
+
+ def AppendChild(*args, **kwargs):
+ """AppendChild(self, RichTextObject child) -> size_t"""
+ return _richtext.RichTextCompositeObject_AppendChild(*args, **kwargs)
+
+ def InsertChild(*args, **kwargs):
+ """InsertChild(self, RichTextObject child, RichTextObject inFrontOf) -> bool"""
+ return _richtext.RichTextCompositeObject_InsertChild(*args, **kwargs)
+
+ def RemoveChild(self, child, deleteChild=False):
+ val = _richtext.RichTextCompositeObject_RemoveChild(self, child, deleteChild)
+ self.this.own(not deleteChild)
+ return val
+
+
+ def DeleteChildren(*args, **kwargs):
+ """DeleteChildren(self) -> bool"""
+ return _richtext.RichTextCompositeObject_DeleteChildren(*args, **kwargs)
+
+ def Defragment(*args, **kwargs):
+ """Defragment(self, RichTextDrawingContext context, RichTextRange range=wxRICHTEXT_ALL) -> bool"""
+ return _richtext.RichTextCompositeObject_Defragment(*args, **kwargs)
+
+_richtext.RichTextCompositeObject_swigregister(RichTextCompositeObject)
+
+class RichTextParagraphLayoutBox(RichTextCompositeObject):
+ """This box knows how to lay out paragraphs."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, RichTextObject parent=None) -> RichTextParagraphLayoutBox
+ __init__(self, RichTextParagraphLayoutBox obj) -> RichTextParagraphLayoutBox
+
+ This box knows how to lay out paragraphs.
+ """
+ _richtext.RichTextParagraphLayoutBox_swiginit(self,_richtext.new_RichTextParagraphLayoutBox(*args))
+ __swig_destroy__ = _richtext.delete_RichTextParagraphLayoutBox
+ __del__ = lambda self : None;
+ def SetRichTextCtrl(*args, **kwargs):
+ """SetRichTextCtrl(self, RichTextCtrl ctrl)"""
+ return _richtext.RichTextParagraphLayoutBox_SetRichTextCtrl(*args, **kwargs)
+
+ def GetRichTextCtrl(*args, **kwargs):
+ """GetRichTextCtrl(self) -> RichTextCtrl"""
+ return _richtext.RichTextParagraphLayoutBox_GetRichTextCtrl(*args, **kwargs)
+
+ def SetPartialParagraph(*args, **kwargs):
+ """SetPartialParagraph(self, bool partialPara)"""
+ return _richtext.RichTextParagraphLayoutBox_SetPartialParagraph(*args, **kwargs)
+
+ def GetPartialParagraph(*args, **kwargs):
+ """GetPartialParagraph(self) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_GetPartialParagraph(*args, **kwargs)
+
+ def GetStyleSheet(*args, **kwargs):
+ """GetStyleSheet(self) -> wxRichTextStyleSheet"""
+ return _richtext.RichTextParagraphLayoutBox_GetStyleSheet(*args, **kwargs)
+
+ def DrawFloats(*args, **kwargs):
+ """
+ DrawFloats(self, DC dc, RichTextDrawingContext context, RichTextRange range,
+ wxRichTextSelection selection, Rect rect,
+ int descent, int style)
+ """
+ return _richtext.RichTextParagraphLayoutBox_DrawFloats(*args, **kwargs)
+
+ def MoveAnchoredObjectToParagraph(*args, **kwargs):
+ """MoveAnchoredObjectToParagraph(self, RichTextParagraph from, RichTextParagraph to, RichTextObject obj)"""
+ return _richtext.RichTextParagraphLayoutBox_MoveAnchoredObjectToParagraph(*args, **kwargs)
+
+ def Init(*args, **kwargs):
+ """Init(self)"""
+ return _richtext.RichTextParagraphLayoutBox_Init(*args, **kwargs)
+
+ def Clear(*args, **kwargs):
+ """Clear(self)"""
+ return _richtext.RichTextParagraphLayoutBox_Clear(*args, **kwargs)
+
+ def Reset(*args, **kwargs):
+ """Reset(self)"""
+ return _richtext.RichTextParagraphLayoutBox_Reset(*args, **kwargs)
+
+ def AddParagraph(*args, **kwargs):
+ """AddParagraph(self, String text, RichTextAttr paraStyle=None) -> RichTextRange"""
+ return _richtext.RichTextParagraphLayoutBox_AddParagraph(*args, **kwargs)
+
+ def AddImage(*args, **kwargs):
+ """AddImage(self, Image image, RichTextAttr paraStyle=None) -> RichTextRange"""
+ return _richtext.RichTextParagraphLayoutBox_AddImage(*args, **kwargs)
+
+ def AddParagraphs(*args, **kwargs):
+ """AddParagraphs(self, String text, RichTextAttr paraStyle=None) -> RichTextRange"""
+ return _richtext.RichTextParagraphLayoutBox_AddParagraphs(*args, **kwargs)
+
+ def GetLineAtPosition(*args, **kwargs):
+ """GetLineAtPosition(self, long pos, bool caretPosition=False) -> RichTextLine"""
+ return _richtext.RichTextParagraphLayoutBox_GetLineAtPosition(*args, **kwargs)
+
+ def GetLineAtYPosition(*args, **kwargs):
+ """GetLineAtYPosition(self, int y) -> RichTextLine"""
+ return _richtext.RichTextParagraphLayoutBox_GetLineAtYPosition(*args, **kwargs)
+
+ def GetParagraphAtPosition(*args, **kwargs):
+ """GetParagraphAtPosition(self, long pos, bool caretPosition=False) -> RichTextParagraph"""
+ return _richtext.RichTextParagraphLayoutBox_GetParagraphAtPosition(*args, **kwargs)
+
+ def GetLineSizeAtPosition(*args, **kwargs):
+ """GetLineSizeAtPosition(self, long pos, bool caretPosition=False) -> Size"""
+ return _richtext.RichTextParagraphLayoutBox_GetLineSizeAtPosition(*args, **kwargs)
+
+ def GetVisibleLineNumber(*args, **kwargs):
+ """GetVisibleLineNumber(self, long pos, bool caretPosition=False, bool startOfLine=False) -> long"""
+ return _richtext.RichTextParagraphLayoutBox_GetVisibleLineNumber(*args, **kwargs)
+
+ def GetLineForVisibleLineNumber(*args, **kwargs):
+ """GetLineForVisibleLineNumber(self, long lineNumber) -> RichTextLine"""
+ return _richtext.RichTextParagraphLayoutBox_GetLineForVisibleLineNumber(*args, **kwargs)
+
+ def GetLeafObjectAtPosition(*args, **kwargs):
+ """GetLeafObjectAtPosition(self, long position) -> RichTextObject"""
+ return _richtext.RichTextParagraphLayoutBox_GetLeafObjectAtPosition(*args, **kwargs)
+
+ def GetParagraphAtLine(*args, **kwargs):
+ """GetParagraphAtLine(self, long paragraphNumber) -> RichTextParagraph"""
+ return _richtext.RichTextParagraphLayoutBox_GetParagraphAtLine(*args, **kwargs)
+
+ def GetParagraphForLine(*args, **kwargs):
+ """GetParagraphForLine(self, RichTextLine line) -> RichTextParagraph"""
+ return _richtext.RichTextParagraphLayoutBox_GetParagraphForLine(*args, **kwargs)
+
+ def GetParagraphLength(*args, **kwargs):
+ """GetParagraphLength(self, long paragraphNumber) -> int"""
+ return _richtext.RichTextParagraphLayoutBox_GetParagraphLength(*args, **kwargs)
+
+ def GetParagraphCount(*args, **kwargs):
+ """GetParagraphCount(self) -> int"""
+ return _richtext.RichTextParagraphLayoutBox_GetParagraphCount(*args, **kwargs)
+
+ def GetLineCount(*args, **kwargs):
+ """GetLineCount(self) -> int"""
+ return _richtext.RichTextParagraphLayoutBox_GetLineCount(*args, **kwargs)
+
+ def GetParagraphText(*args, **kwargs):
+ """GetParagraphText(self, long paragraphNumber) -> String"""
+ return _richtext.RichTextParagraphLayoutBox_GetParagraphText(*args, **kwargs)
+
+ def XYToPosition(*args, **kwargs):
+ """XYToPosition(self, long x, long y) -> long"""
+ return _richtext.RichTextParagraphLayoutBox_XYToPosition(*args, **kwargs)
+
+ def PositionToXY(*args, **kwargs):
+ """PositionToXY(self, long pos, long x, long y) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_PositionToXY(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """SetStyle(self, RichTextRange range, RichTextAttr style, int flags=RICHTEXT_SETSTYLE_WITH_UNDO) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_SetStyle(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self, long position, RichTextAttr style) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_GetStyle(*args, **kwargs)
+
+ def GetUncombinedStyle(*args, **kwargs):
+ """GetUncombinedStyle(self, long position, RichTextAttr style) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_GetUncombinedStyle(*args, **kwargs)
+
+ def DoGetStyle(*args, **kwargs):
+ """DoGetStyle(self, long position, RichTextAttr style, bool combineStyles=True) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_DoGetStyle(*args, **kwargs)
+
+ def GetStyleForRange(*args, **kwargs):
+ """GetStyleForRange(self, RichTextRange range, RichTextAttr style) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_GetStyleForRange(*args, **kwargs)
+
+ def CollectStyle(*args, **kwargs):
+ """
+ CollectStyle(self, RichTextAttr currentStyle, RichTextAttr style, RichTextAttr clashingAttr,
+ RichTextAttr absentAttr) -> bool
+ """
+ return _richtext.RichTextParagraphLayoutBox_CollectStyle(*args, **kwargs)
+
+ def SetListStyle(*args):
+ """
+ SetListStyle(self, RichTextRange range, wxRichTextListStyleDefinition def,
+ int flags=RICHTEXT_SETSTYLE_WITH_UNDO, int startFrom=1,
+ int specifiedLevel=-1) -> bool
+ SetListStyle(self, RichTextRange range, String defName, int flags=RICHTEXT_SETSTYLE_WITH_UNDO,
+ int startFrom=1, int specifiedLevel=-1) -> bool
+ """
+ return _richtext.RichTextParagraphLayoutBox_SetListStyle(*args)
+
+ def ClearListStyle(*args, **kwargs):
+ """ClearListStyle(self, RichTextRange range, int flags=RICHTEXT_SETSTYLE_WITH_UNDO) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_ClearListStyle(*args, **kwargs)
+
+ def NumberList(*args):
+ """
+ NumberList(self, RichTextRange range, wxRichTextListStyleDefinition def=None,
+ int flags=RICHTEXT_SETSTYLE_WITH_UNDO,
+ int startFrom=1, int specifiedLevel=-1) -> bool
+ NumberList(self, RichTextRange range, String defName, int flags=RICHTEXT_SETSTYLE_WITH_UNDO,
+ int startFrom=1, int specifiedLevel=-1) -> bool
+ """
+ return _richtext.RichTextParagraphLayoutBox_NumberList(*args)
+
+ def PromoteList(*args):
+ """
+ PromoteList(self, int promoteBy, RichTextRange range, wxRichTextListStyleDefinition def=None,
+ int flags=RICHTEXT_SETSTYLE_WITH_UNDO,
+ int specifiedLevel=-1) -> bool
+ PromoteList(self, int promoteBy, RichTextRange range, String defName,
+ int flags=RICHTEXT_SETSTYLE_WITH_UNDO, int specifiedLevel=-1) -> bool
+ """
+ return _richtext.RichTextParagraphLayoutBox_PromoteList(*args)
+
+ def DoNumberList(*args, **kwargs):
+ """
+ DoNumberList(self, RichTextRange range, RichTextRange promotionRange,
+ int promoteBy, wxRichTextListStyleDefinition def,
+ int flags=RICHTEXT_SETSTYLE_WITH_UNDO, int startFrom=1,
+ int specifiedLevel=-1) -> bool
+ """
+ return _richtext.RichTextParagraphLayoutBox_DoNumberList(*args, **kwargs)
+
+ def FindNextParagraphNumber(*args, **kwargs):
+ """FindNextParagraphNumber(self, RichTextParagraph previousParagraph, RichTextAttr attr) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_FindNextParagraphNumber(*args, **kwargs)
+
+ def HasCharacterAttributes(*args, **kwargs):
+ """HasCharacterAttributes(self, RichTextRange range, RichTextAttr style) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_HasCharacterAttributes(*args, **kwargs)
+
+ def HasParagraphAttributes(*args, **kwargs):
+ """HasParagraphAttributes(self, RichTextRange range, RichTextAttr style) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_HasParagraphAttributes(*args, **kwargs)
+
+ def InsertFragment(*args, **kwargs):
+ """InsertFragment(self, long position, RichTextParagraphLayoutBox fragment) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_InsertFragment(*args, **kwargs)
+
+ def CopyFragment(*args, **kwargs):
+ """CopyFragment(self, RichTextRange range, RichTextParagraphLayoutBox fragment) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_CopyFragment(*args, **kwargs)
+
+ def ApplyStyleSheet(*args, **kwargs):
+ """ApplyStyleSheet(self, wxRichTextStyleSheet styleSheet) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_ApplyStyleSheet(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self, RichTextParagraphLayoutBox obj)"""
+ return _richtext.RichTextParagraphLayoutBox_Copy(*args, **kwargs)
+
+ def UpdateRanges(*args, **kwargs):
+ """UpdateRanges(self)"""
+ return _richtext.RichTextParagraphLayoutBox_UpdateRanges(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self) -> String"""
+ return _richtext.RichTextParagraphLayoutBox_GetText(*args, **kwargs)
+
+ def SetDefaultStyle(*args, **kwargs):
+ """SetDefaultStyle(self, RichTextAttr style) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_SetDefaultStyle(*args, **kwargs)
+
+ def GetDefaultStyle(*args, **kwargs):
+ """GetDefaultStyle(self) -> RichTextAttr"""
+ return _richtext.RichTextParagraphLayoutBox_GetDefaultStyle(*args, **kwargs)
+
+ def SetBasicStyle(*args, **kwargs):
+ """SetBasicStyle(self, RichTextAttr style)"""
+ return _richtext.RichTextParagraphLayoutBox_SetBasicStyle(*args, **kwargs)
+
+ def GetBasicStyle(*args, **kwargs):
+ """GetBasicStyle(self) -> RichTextAttr"""
+ return _richtext.RichTextParagraphLayoutBox_GetBasicStyle(*args, **kwargs)
+
+ def Invalidate(*args, **kwargs):
+ """Invalidate(self, RichTextRange invalidRange=wxRICHTEXT_ALL)"""
+ return _richtext.RichTextParagraphLayoutBox_Invalidate(*args, **kwargs)
+
+ def UpdateFloatingObjects(*args, **kwargs):
+ """UpdateFloatingObjects(self, Rect availableRect, RichTextObject untilObj=None) -> bool"""
+ return _richtext.RichTextParagraphLayoutBox_UpdateFloatingObjects(*args, **kwargs)
+
+ def GetInvalidRange(*args, **kwargs):
+ """GetInvalidRange(self, bool wholeParagraphs=False) -> RichTextRange"""
+ return _richtext.RichTextParagraphLayoutBox_GetInvalidRange(*args, **kwargs)
+
+ def GetFloatCollector(*args, **kwargs):
+ """GetFloatCollector(self) -> wxRichTextFloatCollector"""
+ return _richtext.RichTextParagraphLayoutBox_GetFloatCollector(*args, **kwargs)
+
+_richtext.RichTextParagraphLayoutBox_swigregister(RichTextParagraphLayoutBox)
+
+class RichTextBox(RichTextCompositeObject):
+ """Proxy of C++ RichTextBox class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, RichTextObject parent=None) -> RichTextBox
+ __init__(self, RichTextBox obj) -> RichTextBox
+ """
+ _richtext.RichTextBox_swiginit(self,_richtext.new_RichTextBox(*args))
+ def Copy(*args, **kwargs):
+ """Copy(self, RichTextBox obj)"""
+ return _richtext.RichTextBox_Copy(*args, **kwargs)
+
+_richtext.RichTextBox_swigregister(RichTextBox)
+
+class RichTextLine(object):
+ """
+ This object represents a line in a paragraph, and stores offsets from
+ the start of the paragraph representing the start and end positions of
+ the line.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, RichTextParagraph parent) -> RichTextLine
+
+ This object represents a line in a paragraph, and stores offsets from
+ the start of the paragraph representing the start and end positions of
+ the line.
+ """
+ _richtext.RichTextLine_swiginit(self,_richtext.new_RichTextLine(*args, **kwargs))
+ __swig_destroy__ = _richtext.delete_RichTextLine
+ __del__ = lambda self : None;
+ def SetRange(*args, **kwargs):
+ """SetRange(self, RichTextRange range)"""
+ return _richtext.RichTextLine_SetRange(*args, **kwargs)
+
+ def GetParent(*args, **kwargs):
+ """GetParent(self) -> RichTextParagraph"""
+ return _richtext.RichTextLine_GetParent(*args, **kwargs)
+
+ def GetRange(*args, **kwargs):
+ """GetRange(self) -> RichTextRange"""
+ return _richtext.RichTextLine_GetRange(*args, **kwargs)
+
+ def GetAbsoluteRange(*args, **kwargs):
+ """GetAbsoluteRange(self) -> RichTextRange"""
+ return _richtext.RichTextLine_GetAbsoluteRange(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(self) -> Size"""
+ return _richtext.RichTextLine_GetSize(*args, **kwargs)
+
+ def SetSize(*args, **kwargs):
+ """SetSize(self, Size sz)"""
+ return _richtext.RichTextLine_SetSize(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> Point"""
+ return _richtext.RichTextLine_GetPosition(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, Point pos)"""
+ return _richtext.RichTextLine_SetPosition(*args, **kwargs)
+
+ def GetAbsolutePosition(*args, **kwargs):
+ """GetAbsolutePosition(self) -> Point"""
+ return _richtext.RichTextLine_GetAbsolutePosition(*args, **kwargs)
+
+ def GetRect(*args, **kwargs):
+ """GetRect(self) -> Rect"""
+ return _richtext.RichTextLine_GetRect(*args, **kwargs)
+
+ def SetDescent(*args, **kwargs):
+ """SetDescent(self, int descent)"""
+ return _richtext.RichTextLine_SetDescent(*args, **kwargs)
+
+ def GetDescent(*args, **kwargs):
+ """GetDescent(self) -> int"""
+ return _richtext.RichTextLine_GetDescent(*args, **kwargs)
+
+ def Init(*args, **kwargs):
+ """Init(self, RichTextParagraph parent)"""
+ return _richtext.RichTextLine_Init(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self, RichTextLine obj)"""
+ return _richtext.RichTextLine_Copy(*args, **kwargs)
+
+ def Clone(*args, **kwargs):
+ """Clone(self) -> RichTextLine"""
+ return _richtext.RichTextLine_Clone(*args, **kwargs)
+
+_richtext.RichTextLine_swigregister(RichTextLine)
+
+class RichTextParagraph(RichTextBox):
+ """
+ This object represents a single paragraph (or in a straight text
+ editor, a line).
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String text, RichTextObject parent=None, RichTextAttr paraStyle=None,
+ RichTextAttr charStyle=None) -> RichTextParagraph
+
+ This object represents a single paragraph (or in a straight text
+ editor, a line).
+ """
+ _richtext.RichTextParagraph_swiginit(self,_richtext.new_RichTextParagraph(*args, **kwargs))
+ __swig_destroy__ = _richtext.delete_RichTextParagraph
+ __del__ = lambda self : None;
+ def GetLines(*args, **kwargs):
+ """GetLines(self) -> wxRichTextLineList"""
+ return _richtext.RichTextParagraph_GetLines(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self, RichTextParagraph obj)"""
+ return _richtext.RichTextParagraph_Copy(*args, **kwargs)
+
+ def ClearLines(*args, **kwargs):
+ """ClearLines(self)"""
+ return _richtext.RichTextParagraph_ClearLines(*args, **kwargs)
+
+ def ApplyParagraphStyle(*args, **kwargs):
+ """ApplyParagraphStyle(self, RichTextLine line, RichTextAttr attr, Rect rect, DC dc)"""
+ return _richtext.RichTextParagraph_ApplyParagraphStyle(*args, **kwargs)
+
+ def InsertText(*args, **kwargs):
+ """InsertText(self, long pos, String text) -> bool"""
+ return _richtext.RichTextParagraph_InsertText(*args, **kwargs)
+
+ def SplitAt(*args, **kwargs):
+ """SplitAt(self, long pos, RichTextObject previousObject=None) -> RichTextObject"""
+ return _richtext.RichTextParagraph_SplitAt(*args, **kwargs)
+
+ def MoveToList(*args, **kwargs):
+ """MoveToList(self, RichTextObject obj, wxList list)"""
+ return _richtext.RichTextParagraph_MoveToList(*args, **kwargs)
+
+ def MoveFromList(*args, **kwargs):
+ """MoveFromList(self, wxList list)"""
+ return _richtext.RichTextParagraph_MoveFromList(*args, **kwargs)
+
+ def GetContiguousPlainText(*args, **kwargs):
+ """GetContiguousPlainText(self, String text, RichTextRange range, bool fromStart=True) -> bool"""
+ return _richtext.RichTextParagraph_GetContiguousPlainText(*args, **kwargs)
+
+ def FindWrapPosition(*args, **kwargs):
+ """
+ FindWrapPosition(self, RichTextRange range, DC dc, RichTextDrawingContext context,
+ int availableSpace, long wrapPosition,
+ wxArrayInt partialExtents) -> bool
+ """
+ return _richtext.RichTextParagraph_FindWrapPosition(*args, **kwargs)
+
+ def FindObjectAtPosition(*args, **kwargs):
+ """FindObjectAtPosition(self, long position) -> RichTextObject"""
+ return _richtext.RichTextParagraph_FindObjectAtPosition(*args, **kwargs)
+
+ def GetBulletText(*args, **kwargs):
+ """GetBulletText(self) -> String"""
+ return _richtext.RichTextParagraph_GetBulletText(*args, **kwargs)
+
+ def AllocateLine(*args, **kwargs):
+ """AllocateLine(self, int pos) -> RichTextLine"""
+ return _richtext.RichTextParagraph_AllocateLine(*args, **kwargs)
+
+ def ClearUnusedLines(*args, **kwargs):
+ """ClearUnusedLines(self, int lineCount) -> bool"""
+ return _richtext.RichTextParagraph_ClearUnusedLines(*args, **kwargs)
+
+ def GetCombinedAttributes(*args, **kwargs):
+ """GetCombinedAttributes(self, RichTextAttr contentStyle=None) -> RichTextAttr"""
+ return _richtext.RichTextParagraph_GetCombinedAttributes(*args, **kwargs)
+
+ def GetFirstLineBreakPosition(*args, **kwargs):
+ """GetFirstLineBreakPosition(self, long pos) -> long"""
+ return _richtext.RichTextParagraph_GetFirstLineBreakPosition(*args, **kwargs)
+
+ def InitDefaultTabs(*args, **kwargs):
+ """InitDefaultTabs()"""
+ return _richtext.RichTextParagraph_InitDefaultTabs(*args, **kwargs)
+
+ InitDefaultTabs = staticmethod(InitDefaultTabs)
+ def ClearDefaultTabs(*args, **kwargs):
+ """ClearDefaultTabs()"""
+ return _richtext.RichTextParagraph_ClearDefaultTabs(*args, **kwargs)
+
+ ClearDefaultTabs = staticmethod(ClearDefaultTabs)
+ def GetDefaultTabs(*args, **kwargs):
+ """GetDefaultTabs() -> wxArrayInt"""
+ return _richtext.RichTextParagraph_GetDefaultTabs(*args, **kwargs)
+
+ GetDefaultTabs = staticmethod(GetDefaultTabs)
+_richtext.RichTextParagraph_swigregister(RichTextParagraph)
+
+def RichTextParagraph_InitDefaultTabs(*args):
+ """RichTextParagraph_InitDefaultTabs()"""
+ return _richtext.RichTextParagraph_InitDefaultTabs(*args)
+
+def RichTextParagraph_ClearDefaultTabs(*args):
+ """RichTextParagraph_ClearDefaultTabs()"""
+ return _richtext.RichTextParagraph_ClearDefaultTabs(*args)
+
+def RichTextParagraph_GetDefaultTabs(*args):
+ """RichTextParagraph_GetDefaultTabs() -> wxArrayInt"""
+ return _richtext.RichTextParagraph_GetDefaultTabs(*args)
+
+class RichTextPlainText(RichTextObject):
+ """This object represents a single piece of text."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String text=wxEmptyString, RichTextObject parent=None,
+ RichTextAttr style=None) -> RichTextPlainText
+
+ This object represents a single piece of text.
+ """
+ _richtext.RichTextPlainText_swiginit(self,_richtext.new_RichTextPlainText(*args, **kwargs))
+ def GetFirstLineBreakPosition(*args, **kwargs):
+ """GetFirstLineBreakPosition(self, long pos) -> long"""
+ return _richtext.RichTextPlainText_GetFirstLineBreakPosition(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self) -> String"""
+ return _richtext.RichTextPlainText_GetText(*args, **kwargs)
+
+ def SetText(*args, **kwargs):
+ """SetText(self, String text)"""
+ return _richtext.RichTextPlainText_SetText(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self, RichTextPlainText obj)"""
+ return _richtext.RichTextPlainText_Copy(*args, **kwargs)
+
+_richtext.RichTextPlainText_swigregister(RichTextPlainText)
+
+class RichTextImage(RichTextObject):
+ """This object represents an image."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args):
+ """
+ __init__(self, RichTextObject parent=None) -> RichTextImage
+ __init__(self, Image image, RichTextObject parent=None, RichTextAttr charStyle=None) -> RichTextImage
+ __init__(self, wxRichTextImageBlock imageBlock, RichTextObject parent=None,
+ RichTextAttr charStyle=None) -> RichTextImage
+ __init__(self, RichTextImage obj) -> RichTextImage
+
+ This object represents an image.
+ """
+ _richtext.RichTextImage_swiginit(self,_richtext.new_RichTextImage(*args))
+ def GetImageCache(*args, **kwargs):
+ """GetImageCache(self) -> Bitmap"""
+ return _richtext.RichTextImage_GetImageCache(*args, **kwargs)
+
+ def SetImageCache(*args, **kwargs):
+ """SetImageCache(self, Bitmap bitmap)"""
+ return _richtext.RichTextImage_SetImageCache(*args, **kwargs)
+
+ def ResetImageCache(*args, **kwargs):
+ """ResetImageCache(self)"""
+ return _richtext.RichTextImage_ResetImageCache(*args, **kwargs)
+
+ def GetImageBlock(*args, **kwargs):
+ """GetImageBlock(self) -> wxRichTextImageBlock"""
+ return _richtext.RichTextImage_GetImageBlock(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self, RichTextImage obj)"""
+ return _richtext.RichTextImage_Copy(*args, **kwargs)
+
+ def LoadImageCache(*args, **kwargs):
+ """LoadImageCache(self, DC dc, bool resetCache=False) -> bool"""
+ return _richtext.RichTextImage_LoadImageCache(*args, **kwargs)
+
+_richtext.RichTextImage_swigregister(RichTextImage)
+
+class RichTextFileHandlerList_iterator(object):
+ """This class serves as an iterator for a wxRichTextFileHandlerList object."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _richtext.delete_RichTextFileHandlerList_iterator
+ __del__ = lambda self : None;
+ def next(*args, **kwargs):
+ """next(self) -> RichTextFileHandler"""
+ return _richtext.RichTextFileHandlerList_iterator_next(*args, **kwargs)
+
+_richtext.RichTextFileHandlerList_iterator_swigregister(RichTextFileHandlerList_iterator)
+
+class RichTextFileHandlerList(object):
+ """
+ This class wraps a wxList-based class and gives it a Python
+ sequence-like interface. Sequence operations supported are length,
+ index access and iteration.
+ """
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _richtext.delete_RichTextFileHandlerList
+ __del__ = lambda self : None;
+ def __len__(*args, **kwargs):
+ """__len__(self) -> size_t"""
+ return _richtext.RichTextFileHandlerList___len__(*args, **kwargs)
+
+ def __getitem__(*args, **kwargs):
+ """__getitem__(self, size_t index) -> RichTextFileHandler"""
+ return _richtext.RichTextFileHandlerList___getitem__(*args, **kwargs)
+
+ def __contains__(*args, **kwargs):
+ """__contains__(self, RichTextFileHandler obj) -> bool"""
+ return _richtext.RichTextFileHandlerList___contains__(*args, **kwargs)
+
+ def __iter__(*args, **kwargs):
+ """__iter__(self) -> RichTextFileHandlerList_iterator"""
+ return _richtext.RichTextFileHandlerList___iter__(*args, **kwargs)
+
+ def __repr__(self):
+ return "wxRichTextFileHandlerList: " + repr(list(self))
+
+_richtext.RichTextFileHandlerList_swigregister(RichTextFileHandlerList)
+
+class RichTextBuffer(RichTextParagraphLayoutBox):
+ """This is a kind of box, used to represent the whole buffer."""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self) -> RichTextBuffer
+
+ This is a kind of box, used to represent the whole buffer.
+ """
+ _richtext.RichTextBuffer_swiginit(self,_richtext.new_RichTextBuffer(*args, **kwargs))
+ __swig_destroy__ = _richtext.delete_RichTextBuffer
+ __del__ = lambda self : None;
+ def GetCommandProcessor(*args, **kwargs):
+ """GetCommandProcessor(self) -> wxCommandProcessor"""
+ return _richtext.RichTextBuffer_GetCommandProcessor(*args, **kwargs)
+
+ def SetStyleSheet(*args, **kwargs):
+ """SetStyleSheet(self, wxRichTextStyleSheet styleSheet)"""
+ return _richtext.RichTextBuffer_SetStyleSheet(*args, **kwargs)
+
+ def SetStyleSheetAndNotify(*args, **kwargs):
+ """SetStyleSheetAndNotify(self, wxRichTextStyleSheet sheet) -> bool"""
+ return _richtext.RichTextBuffer_SetStyleSheetAndNotify(*args, **kwargs)
+
+ def PushStyleSheet(*args, **kwargs):
+ """PushStyleSheet(self, wxRichTextStyleSheet styleSheet) -> bool"""
+ return _richtext.RichTextBuffer_PushStyleSheet(*args, **kwargs)
+
+ def PopStyleSheet(*args, **kwargs):
+ """PopStyleSheet(self) -> wxRichTextStyleSheet"""
+ return _richtext.RichTextBuffer_PopStyleSheet(*args, **kwargs)
+
+ def GetFontTable(*args, **kwargs):
+ """GetFontTable(self) -> RichTextFontTable"""
+ return _richtext.RichTextBuffer_GetFontTable(*args, **kwargs)
+
+ def SetFontTable(*args, **kwargs):
+ """SetFontTable(self, RichTextFontTable table)"""
+ return _richtext.RichTextBuffer_SetFontTable(*args, **kwargs)
+
+ def Init(*args, **kwargs):
+ """Init(self)"""
+ return _richtext.RichTextBuffer_Init(*args, **kwargs)
+
+ def ResetAndClearCommands(*args, **kwargs):
+ """ResetAndClearCommands(self)"""
+ return _richtext.RichTextBuffer_ResetAndClearCommands(*args, **kwargs)
+
+ def LoadFile(*args, **kwargs):
+ """LoadFile(self, String filename, int type=RICHTEXT_TYPE_ANY) -> bool"""
+ return _richtext.RichTextBuffer_LoadFile(*args, **kwargs)
+
+ def SaveFile(*args, **kwargs):
+ """SaveFile(self, String filename, int type=RICHTEXT_TYPE_ANY) -> bool"""
+ return _richtext.RichTextBuffer_SaveFile(*args, **kwargs)
+
+ def LoadStream(*args, **kwargs):
+ """LoadStream(self, InputStream stream, int type=RICHTEXT_TYPE_ANY) -> bool"""
+ return _richtext.RichTextBuffer_LoadStream(*args, **kwargs)
+
+ def SaveStream(*args, **kwargs):
+ """SaveStream(self, wxOutputStream stream, int type=RICHTEXT_TYPE_ANY) -> bool"""
+ return _richtext.RichTextBuffer_SaveStream(*args, **kwargs)
+
+ def SetHandlerFlags(*args, **kwargs):
+ """SetHandlerFlags(self, int flags)"""
+ return _richtext.RichTextBuffer_SetHandlerFlags(*args, **kwargs)
+
+ def GetHandlerFlags(*args, **kwargs):
+ """GetHandlerFlags(self) -> int"""
+ return _richtext.RichTextBuffer_GetHandlerFlags(*args, **kwargs)
+
+ def BeginBatchUndo(*args, **kwargs):
+ """BeginBatchUndo(self, String cmdName) -> bool"""
+ return _richtext.RichTextBuffer_BeginBatchUndo(*args, **kwargs)
+
+ def EndBatchUndo(*args, **kwargs):
+ """EndBatchUndo(self) -> bool"""
+ return _richtext.RichTextBuffer_EndBatchUndo(*args, **kwargs)
+
+ def BatchingUndo(*args, **kwargs):
+ """BatchingUndo(self) -> bool"""
+ return _richtext.RichTextBuffer_BatchingUndo(*args, **kwargs)
+
+ def SubmitAction(*args, **kwargs):
+ """SubmitAction(self, RichTextAction action) -> bool"""
+ return _richtext.RichTextBuffer_SubmitAction(*args, **kwargs)
+
+ def GetBatchedCommand(*args, **kwargs):
+ """GetBatchedCommand(self) -> RichTextCommand"""
+ return _richtext.RichTextBuffer_GetBatchedCommand(*args, **kwargs)
+
+ def BeginSuppressUndo(*args, **kwargs):
+ """BeginSuppressUndo(self) -> bool"""
+ return _richtext.RichTextBuffer_BeginSuppressUndo(*args, **kwargs)
+
+ def EndSuppressUndo(*args, **kwargs):
+ """EndSuppressUndo(self) -> bool"""
+ return _richtext.RichTextBuffer_EndSuppressUndo(*args, **kwargs)
+
+ def SuppressingUndo(*args, **kwargs):
+ """SuppressingUndo(self) -> bool"""
+ return _richtext.RichTextBuffer_SuppressingUndo(*args, **kwargs)
+
+ def CopyToClipboard(*args, **kwargs):
+ """CopyToClipboard(self, RichTextRange range) -> bool"""
+ return _richtext.RichTextBuffer_CopyToClipboard(*args, **kwargs)
+
+ def PasteFromClipboard(*args, **kwargs):
+ """PasteFromClipboard(self, long position) -> bool"""
+ return _richtext.RichTextBuffer_PasteFromClipboard(*args, **kwargs)
+
+ def CanPasteFromClipboard(*args, **kwargs):
+ """CanPasteFromClipboard(self) -> bool"""
+ return _richtext.RichTextBuffer_CanPasteFromClipboard(*args, **kwargs)
+
+ def BeginStyle(*args, **kwargs):
+ """BeginStyle(self, RichTextAttr style) -> bool"""
+ return _richtext.RichTextBuffer_BeginStyle(*args, **kwargs)
+
+ def EndStyle(*args, **kwargs):
+ """EndStyle(self) -> bool"""
+ return _richtext.RichTextBuffer_EndStyle(*args, **kwargs)
+
+ def EndAllStyles(*args, **kwargs):
+ """EndAllStyles(self) -> bool"""
+ return _richtext.RichTextBuffer_EndAllStyles(*args, **kwargs)
+
+ def ClearStyleStack(*args, **kwargs):
+ """ClearStyleStack(self)"""
+ return _richtext.RichTextBuffer_ClearStyleStack(*args, **kwargs)
+
+ def GetStyleStackSize(*args, **kwargs):
+ """GetStyleStackSize(self) -> size_t"""
+ return _richtext.RichTextBuffer_GetStyleStackSize(*args, **kwargs)
+
+ def BeginBold(*args, **kwargs):
+ """BeginBold(self) -> bool"""
+ return _richtext.RichTextBuffer_BeginBold(*args, **kwargs)
+
+ def EndBold(*args, **kwargs):
+ """EndBold(self) -> bool"""
+ return _richtext.RichTextBuffer_EndBold(*args, **kwargs)
+
+ def BeginItalic(*args, **kwargs):
+ """BeginItalic(self) -> bool"""
+ return _richtext.RichTextBuffer_BeginItalic(*args, **kwargs)
+
+ def EndItalic(*args, **kwargs):
+ """EndItalic(self) -> bool"""
+ return _richtext.RichTextBuffer_EndItalic(*args, **kwargs)
+
+ def BeginUnderline(*args, **kwargs):
+ """BeginUnderline(self) -> bool"""
+ return _richtext.RichTextBuffer_BeginUnderline(*args, **kwargs)
+
+ def EndUnderline(*args, **kwargs):
+ """EndUnderline(self) -> bool"""
+ return _richtext.RichTextBuffer_EndUnderline(*args, **kwargs)
+
+ def BeginFontSize(*args, **kwargs):
+ """BeginFontSize(self, int pointSize) -> bool"""
+ return _richtext.RichTextBuffer_BeginFontSize(*args, **kwargs)
+
+ def EndFontSize(*args, **kwargs):
+ """EndFontSize(self) -> bool"""
+ return _richtext.RichTextBuffer_EndFontSize(*args, **kwargs)
+
+ def BeginFont(*args, **kwargs):
+ """BeginFont(self, Font font) -> bool"""
+ return _richtext.RichTextBuffer_BeginFont(*args, **kwargs)
+
+ def EndFont(*args, **kwargs):
+ """EndFont(self) -> bool"""
+ return _richtext.RichTextBuffer_EndFont(*args, **kwargs)
+
+ def BeginTextColour(*args, **kwargs):
+ """BeginTextColour(self, Colour colour) -> bool"""
+ return _richtext.RichTextBuffer_BeginTextColour(*args, **kwargs)
+
+ def EndTextColour(*args, **kwargs):
+ """EndTextColour(self) -> bool"""
+ return _richtext.RichTextBuffer_EndTextColour(*args, **kwargs)
+
+ def BeginAlignment(*args, **kwargs):
+ """BeginAlignment(self, int alignment) -> bool"""
+ return _richtext.RichTextBuffer_BeginAlignment(*args, **kwargs)
+
+ def EndAlignment(*args, **kwargs):
+ """EndAlignment(self) -> bool"""
+ return _richtext.RichTextBuffer_EndAlignment(*args, **kwargs)
+
+ def BeginLeftIndent(*args, **kwargs):
+ """BeginLeftIndent(self, int leftIndent, int leftSubIndent=0) -> bool"""
+ return _richtext.RichTextBuffer_BeginLeftIndent(*args, **kwargs)
+
+ def EndLeftIndent(*args, **kwargs):
+ """EndLeftIndent(self) -> bool"""
+ return _richtext.RichTextBuffer_EndLeftIndent(*args, **kwargs)
+
+ def BeginRightIndent(*args, **kwargs):
+ """BeginRightIndent(self, int rightIndent) -> bool"""
+ return _richtext.RichTextBuffer_BeginRightIndent(*args, **kwargs)
+
+ def EndRightIndent(*args, **kwargs):
+ """EndRightIndent(self) -> bool"""
+ return _richtext.RichTextBuffer_EndRightIndent(*args, **kwargs)
+
+ def BeginParagraphSpacing(*args, **kwargs):
+ """BeginParagraphSpacing(self, int before, int after) -> bool"""
+ return _richtext.RichTextBuffer_BeginParagraphSpacing(*args, **kwargs)
+
+ def EndParagraphSpacing(*args, **kwargs):
+ """EndParagraphSpacing(self) -> bool"""
+ return _richtext.RichTextBuffer_EndParagraphSpacing(*args, **kwargs)
+
+ def BeginLineSpacing(*args, **kwargs):
+ """BeginLineSpacing(self, int lineSpacing) -> bool"""
+ return _richtext.RichTextBuffer_BeginLineSpacing(*args, **kwargs)
+
+ def EndLineSpacing(*args, **kwargs):
+ """EndLineSpacing(self) -> bool"""
+ return _richtext.RichTextBuffer_EndLineSpacing(*args, **kwargs)
+
+ def BeginNumberedBullet(*args, **kwargs):
+ """
+ BeginNumberedBullet(self, int bulletNumber, int leftIndent, int leftSubIndent,
+ int bulletStyle=wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD) -> bool
+ """
+ return _richtext.RichTextBuffer_BeginNumberedBullet(*args, **kwargs)
+
+ def EndNumberedBullet(*args, **kwargs):
+ """EndNumberedBullet(self) -> bool"""
+ return _richtext.RichTextBuffer_EndNumberedBullet(*args, **kwargs)
+
+ def BeginSymbolBullet(*args, **kwargs):
+ """BeginSymbolBullet(self, String symbol, int leftIndent, int leftSubIndent, int bulletStyle=TEXT_ATTR_BULLET_STYLE_SYMBOL) -> bool"""
+ return _richtext.RichTextBuffer_BeginSymbolBullet(*args, **kwargs)
+
+ def EndSymbolBullet(*args, **kwargs):
+ """EndSymbolBullet(self) -> bool"""
+ return _richtext.RichTextBuffer_EndSymbolBullet(*args, **kwargs)
+
+ def BeginStandardBullet(*args, **kwargs):
+ """
+ BeginStandardBullet(self, String bulletName, int leftIndent, int leftSubIndent,
+ int bulletStyle=TEXT_ATTR_BULLET_STYLE_STANDARD) -> bool
+ """
+ return _richtext.RichTextBuffer_BeginStandardBullet(*args, **kwargs)
+
+ def EndStandardBullet(*args, **kwargs):
+ """EndStandardBullet(self) -> bool"""
+ return _richtext.RichTextBuffer_EndStandardBullet(*args, **kwargs)
+
+ def BeginCharacterStyle(*args, **kwargs):
+ """BeginCharacterStyle(self, String characterStyle) -> bool"""
+ return _richtext.RichTextBuffer_BeginCharacterStyle(*args, **kwargs)
+
+ def EndCharacterStyle(*args, **kwargs):
+ """EndCharacterStyle(self) -> bool"""
+ return _richtext.RichTextBuffer_EndCharacterStyle(*args, **kwargs)
+
+ def BeginParagraphStyle(*args, **kwargs):
+ """BeginParagraphStyle(self, String paragraphStyle) -> bool"""
+ return _richtext.RichTextBuffer_BeginParagraphStyle(*args, **kwargs)
+
+ def EndParagraphStyle(*args, **kwargs):
+ """EndParagraphStyle(self) -> bool"""
+ return _richtext.RichTextBuffer_EndParagraphStyle(*args, **kwargs)
+
+ def BeginListStyle(*args, **kwargs):
+ """BeginListStyle(self, String listStyle, int level=1, int number=1) -> bool"""
+ return _richtext.RichTextBuffer_BeginListStyle(*args, **kwargs)
+
+ def EndListStyle(*args, **kwargs):
+ """EndListStyle(self) -> bool"""
+ return _richtext.RichTextBuffer_EndListStyle(*args, **kwargs)
+
+ def BeginURL(*args, **kwargs):
+ """BeginURL(self, String url, String characterStyle=wxEmptyString) -> bool"""
+ return _richtext.RichTextBuffer_BeginURL(*args, **kwargs)
+
+ def EndURL(*args, **kwargs):
+ """EndURL(self) -> bool"""
+ return _richtext.RichTextBuffer_EndURL(*args, **kwargs)
+
+ def AddEventHandler(*args, **kwargs):
+ """AddEventHandler(self, EvtHandler handler) -> bool"""
+ return _richtext.RichTextBuffer_AddEventHandler(*args, **kwargs)
+
+ def RemoveEventHandler(*args, **kwargs):
+ """RemoveEventHandler(self, EvtHandler handler, bool deleteHandler=False) -> bool"""
+ return _richtext.RichTextBuffer_RemoveEventHandler(*args, **kwargs)
+
+ def ClearEventHandlers(*args, **kwargs):
+ """ClearEventHandlers(self)"""
+ return _richtext.RichTextBuffer_ClearEventHandlers(*args, **kwargs)
+
+ def SendEvent(*args, **kwargs):
+ """SendEvent(self, Event event, bool sendToAll=True) -> bool"""
+ return _richtext.RichTextBuffer_SendEvent(*args, **kwargs)
+
+ def Copy(*args, **kwargs):
+ """Copy(self, RichTextBuffer obj)"""
+ return _richtext.RichTextBuffer_Copy(*args, **kwargs)
+
+ def InsertParagraphsWithUndo(*args, **kwargs):
+ """
+ InsertParagraphsWithUndo(self, long pos, RichTextParagraphLayoutBox paragraphs, RichTextCtrl ctrl,
+ int flags=0) -> bool
+ """
+ return _richtext.RichTextBuffer_InsertParagraphsWithUndo(*args, **kwargs)
+
+ def InsertTextWithUndo(*args, **kwargs):
+ """InsertTextWithUndo(self, long pos, String text, RichTextCtrl ctrl, int flags=0) -> bool"""
+ return _richtext.RichTextBuffer_InsertTextWithUndo(*args, **kwargs)
+
+ def InsertNewlineWithUndo(*args, **kwargs):
+ """InsertNewlineWithUndo(self, long pos, RichTextCtrl ctrl, int flags=0) -> bool"""
+ return _richtext.RichTextBuffer_InsertNewlineWithUndo(*args, **kwargs)
+
+ def InsertImageWithUndo(*args, **kwargs):
+ """
+ InsertImageWithUndo(self, long pos, wxRichTextImageBlock imageBlock, RichTextCtrl ctrl,
+ int flags=0) -> bool
+ """
+ return _richtext.RichTextBuffer_InsertImageWithUndo(*args, **kwargs)
+
+ def DeleteRangeWithUndo(*args, **kwargs):
+ """DeleteRangeWithUndo(self, RichTextRange range, RichTextCtrl ctrl) -> bool"""
+ return _richtext.RichTextBuffer_DeleteRangeWithUndo(*args, **kwargs)
+
+ def Modify(*args, **kwargs):
+ """Modify(self, bool modify=True)"""
+ return _richtext.RichTextBuffer_Modify(*args, **kwargs)
+
+ def IsModified(*args, **kwargs):
+ """IsModified(self) -> bool"""
+ return _richtext.RichTextBuffer_IsModified(*args, **kwargs)
+
+ def GetStyleForNewParagraph(*args, **kwargs):
+ """
+ GetStyleForNewParagraph(self, RichTextBuffer buffer, long pos, bool caretPosition=False,
+ bool lookUpNewParaStyle=False) -> RichTextAttr
+ """
+ return _richtext.RichTextBuffer_GetStyleForNewParagraph(*args, **kwargs)
+
+ def GetHandlers(*args, **kwargs):
+ """GetHandlers() -> wxRichTextFileHandlerList_t"""
+ return _richtext.RichTextBuffer_GetHandlers(*args, **kwargs)
+
+ GetHandlers = staticmethod(GetHandlers)
+ def AddHandler(*args, **kwargs):
+ """AddHandler(RichTextFileHandler handler)"""
+ return _richtext.RichTextBuffer_AddHandler(*args, **kwargs)
+
+ AddHandler = staticmethod(AddHandler)
+ def InsertHandler(*args, **kwargs):
+ """InsertHandler(RichTextFileHandler handler)"""
+ return _richtext.RichTextBuffer_InsertHandler(*args, **kwargs)
+
+ InsertHandler = staticmethod(InsertHandler)
+ def RemoveHandler(*args, **kwargs):
+ """RemoveHandler(String name) -> bool"""
+ return _richtext.RichTextBuffer_RemoveHandler(*args, **kwargs)
+
+ RemoveHandler = staticmethod(RemoveHandler)
+ def FindHandlerByName(*args, **kwargs):
+ """FindHandlerByName(String name) -> RichTextFileHandler"""
+ return _richtext.RichTextBuffer_FindHandlerByName(*args, **kwargs)
+
+ FindHandlerByName = staticmethod(FindHandlerByName)
+ def FindHandlerByExtension(*args, **kwargs):
+ """FindHandlerByExtension(String extension, int imageType) -> RichTextFileHandler"""
+ return _richtext.RichTextBuffer_FindHandlerByExtension(*args, **kwargs)
+
+ FindHandlerByExtension = staticmethod(FindHandlerByExtension)
+ def FindHandlerByFilename(*args, **kwargs):
+ """FindHandlerByFilename(String filename, int imageType) -> RichTextFileHandler"""
+ return _richtext.RichTextBuffer_FindHandlerByFilename(*args, **kwargs)
+
+ FindHandlerByFilename = staticmethod(FindHandlerByFilename)
+ def FindHandlerByType(*args, **kwargs):
+ """FindHandlerByType(int imageType) -> RichTextFileHandler"""
+ return _richtext.RichTextBuffer_FindHandlerByType(*args, **kwargs)
+
+ FindHandlerByType = staticmethod(FindHandlerByType)
+ def GetExtWildcard(*args, **kwargs):
+ """
+ GetExtWildcard(self, bool combine=False, bool save=False) --> (wildcards, types)
+
+ Gets a wildcard string for the file dialog based on all the currently
+ loaded richtext file handlers, and a list that can be used to map
+ those filter types to the file handler type.
+ """
+ return _richtext.RichTextBuffer_GetExtWildcard(*args, **kwargs)
+
+ GetExtWildcard = staticmethod(GetExtWildcard)
+ def CleanUpHandlers(*args, **kwargs):
+ """CleanUpHandlers()"""
+ return _richtext.RichTextBuffer_CleanUpHandlers(*args, **kwargs)
+
+ CleanUpHandlers = staticmethod(CleanUpHandlers)
+ def InitStandardHandlers(*args, **kwargs):
+ """InitStandardHandlers()"""
+ return _richtext.RichTextBuffer_InitStandardHandlers(*args, **kwargs)
+
+ InitStandardHandlers = staticmethod(InitStandardHandlers)
+ def GetRenderer(*args, **kwargs):
+ """GetRenderer() -> RichTextRenderer"""
+ return _richtext.RichTextBuffer_GetRenderer(*args, **kwargs)
+
+ GetRenderer = staticmethod(GetRenderer)
+ def SetRenderer(*args, **kwargs):
+ """SetRenderer(RichTextRenderer renderer)"""
+ return _richtext.RichTextBuffer_SetRenderer(*args, **kwargs)
+
+ SetRenderer = staticmethod(SetRenderer)
+ def GetBulletRightMargin(*args, **kwargs):
+ """GetBulletRightMargin() -> int"""
+ return _richtext.RichTextBuffer_GetBulletRightMargin(*args, **kwargs)
+
+ GetBulletRightMargin = staticmethod(GetBulletRightMargin)
+ def SetBulletRightMargin(*args, **kwargs):
+ """SetBulletRightMargin(int margin)"""
+ return _richtext.RichTextBuffer_SetBulletRightMargin(*args, **kwargs)
+
+ SetBulletRightMargin = staticmethod(SetBulletRightMargin)
+ def GetBulletProportion(*args, **kwargs):
+ """GetBulletProportion() -> float"""
+ return _richtext.RichTextBuffer_GetBulletProportion(*args, **kwargs)
+
+ GetBulletProportion = staticmethod(GetBulletProportion)
+ def SetBulletProportion(*args, **kwargs):
+ """SetBulletProportion(float prop)"""
+ return _richtext.RichTextBuffer_SetBulletProportion(*args, **kwargs)
+
+ SetBulletProportion = staticmethod(SetBulletProportion)
+ def GetScale(*args, **kwargs):
+ """GetScale(self) -> double"""
+ return _richtext.RichTextBuffer_GetScale(*args, **kwargs)
+
+ def SetScale(*args, **kwargs):
+ """SetScale(self, double scale)"""
+ return _richtext.RichTextBuffer_SetScale(*args, **kwargs)
+
+ def GetFloatingLayoutMode(*args, **kwargs):
+ """GetFloatingLayoutMode() -> bool"""
+ return _richtext.RichTextBuffer_GetFloatingLayoutMode(*args, **kwargs)
+
+ GetFloatingLayoutMode = staticmethod(GetFloatingLayoutMode)
+ def SetFloatingLayoutMode(*args, **kwargs):
+ """SetFloatingLayoutMode(bool mode)"""
+ return _richtext.RichTextBuffer_SetFloatingLayoutMode(*args, **kwargs)
+
+ SetFloatingLayoutMode = staticmethod(SetFloatingLayoutMode)
+_richtext.RichTextBuffer_swigregister(RichTextBuffer)
+
+def RichTextBuffer_GetHandlers(*args):
+ """RichTextBuffer_GetHandlers() -> wxRichTextFileHandlerList_t"""
+ return _richtext.RichTextBuffer_GetHandlers(*args)
+
+def RichTextBuffer_AddHandler(*args, **kwargs):
+ """RichTextBuffer_AddHandler(RichTextFileHandler handler)"""
+ return _richtext.RichTextBuffer_AddHandler(*args, **kwargs)
+
+def RichTextBuffer_InsertHandler(*args, **kwargs):
+ """RichTextBuffer_InsertHandler(RichTextFileHandler handler)"""
+ return _richtext.RichTextBuffer_InsertHandler(*args, **kwargs)
+
+def RichTextBuffer_RemoveHandler(*args, **kwargs):
+ """RichTextBuffer_RemoveHandler(String name) -> bool"""
+ return _richtext.RichTextBuffer_RemoveHandler(*args, **kwargs)
+
+def RichTextBuffer_FindHandlerByName(*args, **kwargs):
+ """RichTextBuffer_FindHandlerByName(String name) -> RichTextFileHandler"""
+ return _richtext.RichTextBuffer_FindHandlerByName(*args, **kwargs)
+
+def RichTextBuffer_FindHandlerByExtension(*args, **kwargs):
+ """RichTextBuffer_FindHandlerByExtension(String extension, int imageType) -> RichTextFileHandler"""
+ return _richtext.RichTextBuffer_FindHandlerByExtension(*args, **kwargs)
+
+def RichTextBuffer_FindHandlerByFilename(*args, **kwargs):
+ """RichTextBuffer_FindHandlerByFilename(String filename, int imageType) -> RichTextFileHandler"""
+ return _richtext.RichTextBuffer_FindHandlerByFilename(*args, **kwargs)
+
+def RichTextBuffer_FindHandlerByType(*args, **kwargs):
+ """RichTextBuffer_FindHandlerByType(int imageType) -> RichTextFileHandler"""
+ return _richtext.RichTextBuffer_FindHandlerByType(*args, **kwargs)
+
+def RichTextBuffer_GetExtWildcard(*args, **kwargs):
+ """
+ GetExtWildcard(self, bool combine=False, bool save=False) --> (wildcards, types)
+
+ Gets a wildcard string for the file dialog based on all the currently
+ loaded richtext file handlers, and a list that can be used to map
+ those filter types to the file handler type.
+ """
+ return _richtext.RichTextBuffer_GetExtWildcard(*args, **kwargs)
+
+def RichTextBuffer_CleanUpHandlers(*args):
+ """RichTextBuffer_CleanUpHandlers()"""
+ return _richtext.RichTextBuffer_CleanUpHandlers(*args)
+
+def RichTextBuffer_InitStandardHandlers(*args):
+ """RichTextBuffer_InitStandardHandlers()"""
+ return _richtext.RichTextBuffer_InitStandardHandlers(*args)
+
+def RichTextBuffer_GetRenderer(*args):
+ """RichTextBuffer_GetRenderer() -> RichTextRenderer"""
+ return _richtext.RichTextBuffer_GetRenderer(*args)
+
+def RichTextBuffer_SetRenderer(*args, **kwargs):
+ """RichTextBuffer_SetRenderer(RichTextRenderer renderer)"""
+ return _richtext.RichTextBuffer_SetRenderer(*args, **kwargs)
+
+def RichTextBuffer_GetBulletRightMargin(*args):
+ """RichTextBuffer_GetBulletRightMargin() -> int"""
+ return _richtext.RichTextBuffer_GetBulletRightMargin(*args)
+
+def RichTextBuffer_SetBulletRightMargin(*args, **kwargs):
+ """RichTextBuffer_SetBulletRightMargin(int margin)"""
+ return _richtext.RichTextBuffer_SetBulletRightMargin(*args, **kwargs)
+
+def RichTextBuffer_GetBulletProportion(*args):
+ """RichTextBuffer_GetBulletProportion() -> float"""
+ return _richtext.RichTextBuffer_GetBulletProportion(*args)
+
+def RichTextBuffer_SetBulletProportion(*args, **kwargs):
+ """RichTextBuffer_SetBulletProportion(float prop)"""
+ return _richtext.RichTextBuffer_SetBulletProportion(*args, **kwargs)
+
+def RichTextBuffer_GetFloatingLayoutMode(*args):
+ """RichTextBuffer_GetFloatingLayoutMode() -> bool"""
+ return _richtext.RichTextBuffer_GetFloatingLayoutMode(*args)
+
+def RichTextBuffer_SetFloatingLayoutMode(*args, **kwargs):
+ """RichTextBuffer_SetFloatingLayoutMode(bool mode)"""
+ return _richtext.RichTextBuffer_SetFloatingLayoutMode(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+RICHTEXT_HANDLER_INCLUDE_STYLESHEET = _richtext.RICHTEXT_HANDLER_INCLUDE_STYLESHEET
+RICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY = _richtext.RICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY
+RICHTEXT_HANDLER_SAVE_IMAGES_TO_FILES = _richtext.RICHTEXT_HANDLER_SAVE_IMAGES_TO_FILES
+RICHTEXT_HANDLER_SAVE_IMAGES_TO_BASE64 = _richtext.RICHTEXT_HANDLER_SAVE_IMAGES_TO_BASE64
+RICHTEXT_HANDLER_NO_HEADER_FOOTER = _richtext.RICHTEXT_HANDLER_NO_HEADER_FOOTER
+RICHTEXT_HANDLER_CONVERT_FACENAMES = _richtext.RICHTEXT_HANDLER_CONVERT_FACENAMES
+class RichTextFileHandler(_core.Object):
+ """Base class for file handlers"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _richtext.delete_RichTextFileHandler
+ __del__ = lambda self : None;
+ def LoadStream(*args, **kwargs):
+ """LoadStream(self, RichTextBuffer buffer, InputStream stream) -> bool"""
+ return _richtext.RichTextFileHandler_LoadStream(*args, **kwargs)
+
+ def SaveStream(*args, **kwargs):
+ """SaveStream(self, RichTextBuffer buffer, wxOutputStream stream) -> bool"""
+ return _richtext.RichTextFileHandler_SaveStream(*args, **kwargs)
+
+ def LoadFile(*args, **kwargs):
+ """LoadFile(self, RichTextBuffer buffer, String filename) -> bool"""
+ return _richtext.RichTextFileHandler_LoadFile(*args, **kwargs)
+
+ def SaveFile(*args, **kwargs):
+ """SaveFile(self, RichTextBuffer buffer, String filename) -> bool"""
+ return _richtext.RichTextFileHandler_SaveFile(*args, **kwargs)
+
+ def CanHandle(*args, **kwargs):
+ """CanHandle(self, String filename) -> bool"""
+ return _richtext.RichTextFileHandler_CanHandle(*args, **kwargs)
+
+ def CanSave(*args, **kwargs):
+ """CanSave(self) -> bool"""
+ return _richtext.RichTextFileHandler_CanSave(*args, **kwargs)
+
+ def CanLoad(*args, **kwargs):
+ """CanLoad(self) -> bool"""
+ return _richtext.RichTextFileHandler_CanLoad(*args, **kwargs)
+
+ def IsVisible(*args, **kwargs):
+ """IsVisible(self) -> bool"""
+ return _richtext.RichTextFileHandler_IsVisible(*args, **kwargs)
+
+ def SetVisible(*args, **kwargs):
+ """SetVisible(self, bool visible)"""
+ return _richtext.RichTextFileHandler_SetVisible(*args, **kwargs)
+
+ def SetName(*args, **kwargs):
+ """SetName(self, String name)"""
+ return _richtext.RichTextFileHandler_SetName(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _richtext.RichTextFileHandler_GetName(*args, **kwargs)
+
+ Name = property(GetName,SetName)
+ def SetExtension(*args, **kwargs):
+ """SetExtension(self, String ext)"""
+ return _richtext.RichTextFileHandler_SetExtension(*args, **kwargs)
+
+ def GetExtension(*args, **kwargs):
+ """GetExtension(self) -> String"""
+ return _richtext.RichTextFileHandler_GetExtension(*args, **kwargs)
+
+ Extension = property(GetExtension,SetExtension)
+ def SetType(*args, **kwargs):
+ """SetType(self, int type)"""
+ return _richtext.RichTextFileHandler_SetType(*args, **kwargs)
+
+ def GetType(*args, **kwargs):
+ """GetType(self) -> int"""
+ return _richtext.RichTextFileHandler_GetType(*args, **kwargs)
+
+ Type = property(GetType,SetType)
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _richtext.RichTextFileHandler_SetFlags(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _richtext.RichTextFileHandler_GetFlags(*args, **kwargs)
+
+ Flags = property(GetFlags,SetFlags)
+ def SetEncoding(*args, **kwargs):
+ """SetEncoding(self, String encoding)"""
+ return _richtext.RichTextFileHandler_SetEncoding(*args, **kwargs)
+
+ def GetEncoding(*args, **kwargs):
+ """GetEncoding(self) -> String"""
+ return _richtext.RichTextFileHandler_GetEncoding(*args, **kwargs)
+
+ Encoding = property(GetEncoding,SetEncoding)
+_richtext.RichTextFileHandler_swigregister(RichTextFileHandler)
+
+class RichTextPlainTextHandler(RichTextFileHandler):
+ """Proxy of C++ RichTextPlainTextHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String name=TextName, String ext=TextExt, int type=RICHTEXT_TYPE_TEXT) -> RichTextPlainTextHandler"""
+ _richtext.RichTextPlainTextHandler_swiginit(self,_richtext.new_RichTextPlainTextHandler(*args, **kwargs))
+_richtext.RichTextPlainTextHandler_swigregister(RichTextPlainTextHandler)
+TextName = cvar.TextName
+TextExt = cvar.TextExt
+
+#---------------------------------------------------------------------------
+
+class RichTextRenderer(_core.Object):
+ """Proxy of C++ RichTextRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ __swig_destroy__ = _richtext.delete_RichTextRenderer
+ __del__ = lambda self : None;
+ def DrawStandardBullet(*args, **kwargs):
+ """
+ DrawStandardBullet(self, RichTextParagraph paragraph, DC dc, RichTextAttr attr,
+ Rect rect) -> bool
+ """
+ return _richtext.RichTextRenderer_DrawStandardBullet(*args, **kwargs)
+
+ def DrawTextBullet(*args, **kwargs):
+ """
+ DrawTextBullet(self, RichTextParagraph paragraph, DC dc, RichTextAttr attr,
+ Rect rect, String text) -> bool
+ """
+ return _richtext.RichTextRenderer_DrawTextBullet(*args, **kwargs)
+
+ def DrawBitmapBullet(*args, **kwargs):
+ """
+ DrawBitmapBullet(self, RichTextParagraph paragraph, DC dc, RichTextAttr attr,
+ Rect rect) -> bool
+ """
+ return _richtext.RichTextRenderer_DrawBitmapBullet(*args, **kwargs)
+
+ def EnumerateStandardBulletNames(*args, **kwargs):
+ """EnumerateStandardBulletNames(self, wxArrayString bulletNames) -> bool"""
+ return _richtext.RichTextRenderer_EnumerateStandardBulletNames(*args, **kwargs)
+
+_richtext.RichTextRenderer_swigregister(RichTextRenderer)
+
+class RichTextStdRenderer(RichTextRenderer):
+ """Proxy of C++ RichTextStdRenderer class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> RichTextStdRenderer"""
+ _richtext.RichTextStdRenderer_swiginit(self,_richtext.new_RichTextStdRenderer(*args, **kwargs))
+_richtext.RichTextStdRenderer_swigregister(RichTextStdRenderer)
+
+#---------------------------------------------------------------------------
+
+RE_READONLY = _richtext.RE_READONLY
+RE_MULTILINE = _richtext.RE_MULTILINE
+RE_CENTER_CARET = _richtext.RE_CENTER_CARET
+RE_CENTRE_CARET = _richtext.RE_CENTRE_CARET
+RICHTEXT_SHIFT_DOWN = _richtext.RICHTEXT_SHIFT_DOWN
+RICHTEXT_CTRL_DOWN = _richtext.RICHTEXT_CTRL_DOWN
+RICHTEXT_ALT_DOWN = _richtext.RICHTEXT_ALT_DOWN
+class RichTextCtrl(_core.Control,_core.TextCtrlIface,_windows.ScrollHelper):
+ """Proxy of C++ RichTextCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=RE_MULTILINE, Validator validator=DefaultValidator,
+ String name=RichTextCtrlNameStr) -> RichTextCtrl
+ """
+ _richtext.RichTextCtrl_swiginit(self,_richtext.new_RichTextCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String value=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=RE_MULTILINE, Validator validator=DefaultValidator,
+ String name=RichTextCtrlNameStr) -> bool
+ """
+ return _richtext.RichTextCtrl_Create(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> String"""
+ return _richtext.RichTextCtrl_GetValue(*args, **kwargs)
+
+ def IsSingleLine(*args, **kwargs):
+ """IsSingleLine(self) -> bool"""
+ return _richtext.RichTextCtrl_IsSingleLine(*args, **kwargs)
+
+ def IsMultiLine(*args, **kwargs):
+ """IsMultiLine(self) -> bool"""
+ return _richtext.RichTextCtrl_IsMultiLine(*args, **kwargs)
+
+ def GetFilename(*args, **kwargs):
+ """GetFilename(self) -> String"""
+ return _richtext.RichTextCtrl_GetFilename(*args, **kwargs)
+
+ def SetFilename(*args, **kwargs):
+ """SetFilename(self, String filename)"""
+ return _richtext.RichTextCtrl_SetFilename(*args, **kwargs)
+
+ def SetDelayedLayoutThreshold(*args, **kwargs):
+ """
+ SetDelayedLayoutThreshold(self, long threshold)
+
+ Set the threshold in character positions for doing layout optimization
+ during sizing.
+ """
+ return _richtext.RichTextCtrl_SetDelayedLayoutThreshold(*args, **kwargs)
+
+ def GetDelayedLayoutThreshold(*args, **kwargs):
+ """
+ GetDelayedLayoutThreshold(self) -> long
+
+ Get the threshold in character positions for doing layout optimization
+ during sizing.
+ """
+ return _richtext.RichTextCtrl_GetDelayedLayoutThreshold(*args, **kwargs)
+
+ def GetFullLayoutRequired(*args, **kwargs):
+ """GetFullLayoutRequired(self) -> bool"""
+ return _richtext.RichTextCtrl_GetFullLayoutRequired(*args, **kwargs)
+
+ def SetFullLayoutRequired(*args, **kwargs):
+ """SetFullLayoutRequired(self, bool b)"""
+ return _richtext.RichTextCtrl_SetFullLayoutRequired(*args, **kwargs)
+
+ def GetFullLayoutTime(*args, **kwargs):
+ """GetFullLayoutTime(self) -> wxLongLong"""
+ return _richtext.RichTextCtrl_GetFullLayoutTime(*args, **kwargs)
+
+ def SetFullLayoutTime(*args, **kwargs):
+ """SetFullLayoutTime(self, wxLongLong t)"""
+ return _richtext.RichTextCtrl_SetFullLayoutTime(*args, **kwargs)
+
+ def GetFullLayoutSavedPosition(*args, **kwargs):
+ """GetFullLayoutSavedPosition(self) -> long"""
+ return _richtext.RichTextCtrl_GetFullLayoutSavedPosition(*args, **kwargs)
+
+ def SetFullLayoutSavedPosition(*args, **kwargs):
+ """SetFullLayoutSavedPosition(self, long p)"""
+ return _richtext.RichTextCtrl_SetFullLayoutSavedPosition(*args, **kwargs)
+
+ def ForceDelayedLayout(*args, **kwargs):
+ """ForceDelayedLayout(self)"""
+ return _richtext.RichTextCtrl_ForceDelayedLayout(*args, **kwargs)
+
+ def SetTextCursor(*args, **kwargs):
+ """
+ SetTextCursor(self, Cursor cursor)
+
+ Set text cursor
+ """
+ return _richtext.RichTextCtrl_SetTextCursor(*args, **kwargs)
+
+ def GetTextCursor(*args, **kwargs):
+ """
+ GetTextCursor(self) -> Cursor
+
+ Get text cursor
+ """
+ return _richtext.RichTextCtrl_GetTextCursor(*args, **kwargs)
+
+ def SetURLCursor(*args, **kwargs):
+ """
+ SetURLCursor(self, Cursor cursor)
+
+ Set URL cursor
+ """
+ return _richtext.RichTextCtrl_SetURLCursor(*args, **kwargs)
+
+ def GetURLCursor(*args, **kwargs):
+ """
+ GetURLCursor(self) -> Cursor
+
+ Get URL cursor
+ """
+ return _richtext.RichTextCtrl_GetURLCursor(*args, **kwargs)
+
+ def GetCaretAtLineStart(*args, **kwargs):
+ """GetCaretAtLineStart(self) -> bool"""
+ return _richtext.RichTextCtrl_GetCaretAtLineStart(*args, **kwargs)
+
+ def SetCaretAtLineStart(*args, **kwargs):
+ """SetCaretAtLineStart(self, bool atStart)"""
+ return _richtext.RichTextCtrl_SetCaretAtLineStart(*args, **kwargs)
+
+ def GetDragging(*args, **kwargs):
+ """GetDragging(self) -> bool"""
+ return _richtext.RichTextCtrl_GetDragging(*args, **kwargs)
+
+ def SetDragging(*args, **kwargs):
+ """SetDragging(self, bool dragging)"""
+ return _richtext.RichTextCtrl_SetDragging(*args, **kwargs)
+
+ def GetPreDrag(*args, **kwargs):
+ """GetPreDrag(self) -> bool"""
+ return _richtext.RichTextCtrl_GetPreDrag(*args, **kwargs)
+
+ def SetPreDrag(*args, **kwargs):
+ """SetPreDrag(self, bool pd)"""
+ return _richtext.RichTextCtrl_SetPreDrag(*args, **kwargs)
+
+ def GetDragStartPoint(*args, **kwargs):
+ """GetDragStartPoint(self) -> Point"""
+ return _richtext.RichTextCtrl_GetDragStartPoint(*args, **kwargs)
+
+ def SetDragStartPoint(*args, **kwargs):
+ """SetDragStartPoint(self, Point sp)"""
+ return _richtext.RichTextCtrl_SetDragStartPoint(*args, **kwargs)
+
+ def GetDragStartTime(*args, **kwargs):
+ """GetDragStartTime(self) -> DateTime"""
+ return _richtext.RichTextCtrl_GetDragStartTime(*args, **kwargs)
+
+ def SetDragStartTime(*args, **kwargs):
+ """SetDragStartTime(self, DateTime st)"""
+ return _richtext.RichTextCtrl_SetDragStartTime(*args, **kwargs)
+
+ def GetBufferBitmap(*args, **kwargs):
+ """GetBufferBitmap(self) -> Bitmap"""
+ return _richtext.RichTextCtrl_GetBufferBitmap(*args, **kwargs)
+
+ def GetContextMenu(*args, **kwargs):
+ """GetContextMenu(self) -> Menu"""
+ return _richtext.RichTextCtrl_GetContextMenu(*args, **kwargs)
+
+ def SetContextMenu(*args, **kwargs):
+ """SetContextMenu(self, Menu menu)"""
+ return _richtext.RichTextCtrl_SetContextMenu(*args, **kwargs)
+
+ def GetSelectionAnchor(*args, **kwargs):
+ """GetSelectionAnchor(self) -> long"""
+ return _richtext.RichTextCtrl_GetSelectionAnchor(*args, **kwargs)
+
+ def SetSelectionAnchor(*args, **kwargs):
+ """SetSelectionAnchor(self, long anchor)"""
+ return _richtext.RichTextCtrl_SetSelectionAnchor(*args, **kwargs)
+
+ def LoadFile(*args, **kwargs):
+ """
+ LoadFile(self, String file, int type=RICHTEXT_TYPE_ANY) -> bool
+
+ Load the contents of the document from the given filename.
+ """
+ return _richtext.RichTextCtrl_LoadFile(*args, **kwargs)
+
+ def SaveFile(*args, **kwargs):
+ """
+ SaveFile(self, String file=EmptyString, int type=RICHTEXT_TYPE_ANY) -> bool
+
+ Save the contents of the document to the given filename, or if the
+ empty string is passed then to the filename set with `SetFilename`.
+ """
+ return _richtext.RichTextCtrl_SaveFile(*args, **kwargs)
+
+ def SetHandlerFlags(*args, **kwargs):
+ """
+ SetHandlerFlags(self, int flags)
+
+ Set the handler flags, controlling loading and saving.
+ """
+ return _richtext.RichTextCtrl_SetHandlerFlags(*args, **kwargs)
+
+ def GetHandlerFlags(*args, **kwargs):
+ """
+ GetHandlerFlags(self) -> int
+
+ Get the handler flags, controlling loading and saving.
+ """
+ return _richtext.RichTextCtrl_GetHandlerFlags(*args, **kwargs)
+
+ def SetMaxLength(*args, **kwargs):
+ """
+ SetMaxLength(self, unsigned long len)
+
+ Set the max number of characters which may be entered in a single line
+ text control.
+ """
+ return _richtext.RichTextCtrl_SetMaxLength(*args, **kwargs)
+
+ def SetStyle(*args, **kwargs):
+ """
+ SetStyle(self, RichTextRange range, RichTextAttr style) -> bool
+
+ Set the style for the text in ``range`` to ``style``
+ """
+ return _richtext.RichTextCtrl_SetStyle(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """
+ GetStyle(self, long position, RichTextAttr style) -> bool
+
+ Retrieve the style used at the given position. Copies the style
+ values at ``position`` into the ``style`` parameter and returns ``True``
+ if successful. Returns ``False`` otherwise.
+ """
+ return _richtext.RichTextCtrl_GetStyle(*args, **kwargs)
+
+ def GetStyleForRange(*args, **kwargs):
+ """
+ GetStyleForRange(self, RichTextRange range, RichTextAttr style) -> bool
+
+ Get the common set of styles for the range
+ """
+ return _richtext.RichTextCtrl_GetStyleForRange(*args, **kwargs)
+
+ def SetStyleEx(*args, **kwargs):
+ """
+ SetStyleEx(self, RichTextRange range, RichTextAttr style, int flags=RICHTEXT_SETSTYLE_WITH_UNDO) -> bool
+
+ Extended style setting operation with flags including:
+ RICHTEXT_SETSTYLE_WITH_UNDO, RICHTEXT_SETSTYLE_OPTIMIZE,
+ RICHTEXT_SETSTYLE_PARAGRAPHS_ONLY, RICHTEXT_SETSTYLE_CHARACTERS_ONLY
+ """
+ return _richtext.RichTextCtrl_SetStyleEx(*args, **kwargs)
+
+ def GetUncombinedStyle(*args, **kwargs):
+ """
+ GetUncombinedStyle(self, long position, RichTextAttr style) -> bool
+
+ Get the content (uncombined) attributes for this position. Copies the
+ style values at ``position`` into the ``style`` parameter and returns
+ ``True`` if successful. Returns ``False`` otherwise.
+ """
+ return _richtext.RichTextCtrl_GetUncombinedStyle(*args, **kwargs)
+
+ def SetDefaultStyle(*args, **kwargs):
+ """
+ SetDefaultStyle(self, RichTextAttr style) -> bool
+
+ Set the style used by default for the rich text document.
+ """
+ return _richtext.RichTextCtrl_SetDefaultStyle(*args, **kwargs)
+
+ def GetDefaultStyle(*args, **kwargs):
+ """
+ GetDefaultStyle(self) -> RichTextAttr
+
+ Retrieves a copy of the default style object.
+ """
+ return _richtext.RichTextCtrl_GetDefaultStyle(*args, **kwargs)
+
+ def SetListStyle(*args, **kwargs):
+ """
+ SetListStyle(self, RichTextRange range, String defName, int flags=RICHTEXT_SETSTYLE_WITH_UNDO,
+ int startFrom=1, int specifiedLevel=-1) -> bool
+ """
+ return _richtext.RichTextCtrl_SetListStyle(*args, **kwargs)
+
+ def ClearListStyle(*args, **kwargs):
+ """ClearListStyle(self, RichTextRange range, int flags=RICHTEXT_SETSTYLE_WITH_UNDO) -> bool"""
+ return _richtext.RichTextCtrl_ClearListStyle(*args, **kwargs)
+
+ def NumberList(*args, **kwargs):
+ """
+ NumberList(self, RichTextRange range, String defName, int flags=RICHTEXT_SETSTYLE_WITH_UNDO,
+ int startFrom=1, int specifiedLevel=-1) -> bool
+ """
+ return _richtext.RichTextCtrl_NumberList(*args, **kwargs)
+
+ def PromoteList(*args, **kwargs):
+ """
+ PromoteList(self, int promoteBy, RichTextRange range, String defName,
+ int flags=RICHTEXT_SETSTYLE_WITH_UNDO, int specifiedLevel=-1) -> bool
+ """
+ return _richtext.RichTextCtrl_PromoteList(*args, **kwargs)
+
+ def Delete(*args, **kwargs):
+ """Delete(self, RichTextRange range) -> bool"""
+ return _richtext.RichTextCtrl_Delete(*args, **kwargs)
+
+ def HitTestXY(*args, **kwargs):
+ """
+ HitTestRC(self, Point pt) --> (result, col, row)
+
+ Returns the column and row of the given point in pixels. Note that
+ ``pt`` should be given in device coordinates, and not be adjusted for
+ the client area origin nor for scrolling. The return value is a tuple
+ of the hit test result and the column and row values.
+ """
+ return _richtext.RichTextCtrl_HitTestXY(*args, **kwargs)
+
+ def FindContainerAtPoint(*args, **kwargs):
+ """
+ FindContainerAtPoint(self, Point pt, long position, int hit, RichTextObject hitObj,
+ int flags=0) -> RichTextParagraphLayoutBox
+ """
+ return _richtext.RichTextCtrl_FindContainerAtPoint(*args, **kwargs)
+
+ def DeleteSelection(*args, **kwargs):
+ """
+ DeleteSelection(self)
+
+ Remove the current selection.
+ """
+ return _richtext.RichTextCtrl_DeleteSelection(*args, **kwargs)
+
+ def CanDeleteSelection(*args, **kwargs):
+ """
+ CanDeleteSelection(self) -> bool
+
+ Returns ``True`` if the selection can be removed from the document.
+ """
+ return _richtext.RichTextCtrl_CanDeleteSelection(*args, **kwargs)
+
+ def HasSelection(*args, **kwargs):
+ """HasSelection(self) -> bool"""
+ return _richtext.RichTextCtrl_HasSelection(*args, **kwargs)
+
+ def WriteImage(*args, **kwargs):
+ """
+ WriteImage(self, Image image, int bitmapType=BITMAP_TYPE_PNG) -> bool
+
+ Write an image at the current insertion point. Supply optional type to
+ use for internal and file storage of the raw data.
+
+ """
+ return _richtext.RichTextCtrl_WriteImage(*args, **kwargs)
+
+ def WriteBitmap(*args, **kwargs):
+ """
+ WriteBitmap(self, Bitmap bitmap, int bitmapType=BITMAP_TYPE_PNG) -> bool
+
+ Write a bitmap at the current insertion point. Supply optional type to
+ use for internal and file storage of the raw data.
+ """
+ return _richtext.RichTextCtrl_WriteBitmap(*args, **kwargs)
+
+ def WriteImageFile(*args, **kwargs):
+ """
+ WriteImageFile(self, String filename, int bitmapType) -> bool
+
+ Load an image from file and write at the current insertion point.
+ """
+ return _richtext.RichTextCtrl_WriteImageFile(*args, **kwargs)
+
+ def WriteImageBlock(*args, **kwargs):
+ """
+ WriteImageBlock(self, wxRichTextImageBlock imageBlock) -> bool
+
+ Write an image block at the current insertion point.
+ """
+ return _richtext.RichTextCtrl_WriteImageBlock(*args, **kwargs)
+
+ def Newline(*args, **kwargs):
+ """
+ Newline(self) -> bool
+
+ Insert a newline (actually paragraph) at the current insertion point.
+ """
+ return _richtext.RichTextCtrl_Newline(*args, **kwargs)
+
+ def LineBreak(*args, **kwargs):
+ """
+ LineBreak(self) -> bool
+
+ Insert a line break at the current insertion point.
+ """
+ return _richtext.RichTextCtrl_LineBreak(*args, **kwargs)
+
+ def SetBasicStyle(*args, **kwargs):
+ """SetBasicStyle(self, RichTextAttr style)"""
+ return _richtext.RichTextCtrl_SetBasicStyle(*args, **kwargs)
+
+ def GetBasicStyle(*args, **kwargs):
+ """
+ GetBasicStyle(self) -> RichTextAttr
+
+ Get basic (overall) style
+ """
+ return _richtext.RichTextCtrl_GetBasicStyle(*args, **kwargs)
+
+ def BeginStyle(*args, **kwargs):
+ """
+ BeginStyle(self, RichTextAttr style) -> bool
+
+ Begin using a style
+ """
+ return _richtext.RichTextCtrl_BeginStyle(*args, **kwargs)
+
+ def EndStyle(*args, **kwargs):
+ """
+ EndStyle(self) -> bool
+
+ End the style
+ """
+ return _richtext.RichTextCtrl_EndStyle(*args, **kwargs)
+
+ def EndAllStyles(*args, **kwargs):
+ """
+ EndAllStyles(self) -> bool
+
+ End all styles
+ """
+ return _richtext.RichTextCtrl_EndAllStyles(*args, **kwargs)
+
+ def BeginBold(*args, **kwargs):
+ """
+ BeginBold(self) -> bool
+
+ Begin using bold
+ """
+ return _richtext.RichTextCtrl_BeginBold(*args, **kwargs)
+
+ def EndBold(*args, **kwargs):
+ """
+ EndBold(self) -> bool
+
+ End using bold
+ """
+ return _richtext.RichTextCtrl_EndBold(*args, **kwargs)
+
+ def BeginItalic(*args, **kwargs):
+ """
+ BeginItalic(self) -> bool
+
+ Begin using italic
+ """
+ return _richtext.RichTextCtrl_BeginItalic(*args, **kwargs)
+
+ def EndItalic(*args, **kwargs):
+ """
+ EndItalic(self) -> bool
+
+ End using italic
+ """
+ return _richtext.RichTextCtrl_EndItalic(*args, **kwargs)
+
+ def BeginUnderline(*args, **kwargs):
+ """
+ BeginUnderline(self) -> bool
+
+ Begin using underline
+ """
+ return _richtext.RichTextCtrl_BeginUnderline(*args, **kwargs)
+
+ def EndUnderline(*args, **kwargs):
+ """
+ EndUnderline(self) -> bool
+
+ End using underline
+ """
+ return _richtext.RichTextCtrl_EndUnderline(*args, **kwargs)
+
+ def BeginFontSize(*args, **kwargs):
+ """
+ BeginFontSize(self, int pointSize) -> bool
+
+ Begin using point size
+ """
+ return _richtext.RichTextCtrl_BeginFontSize(*args, **kwargs)
+
+ def EndFontSize(*args, **kwargs):
+ """
+ EndFontSize(self) -> bool
+
+ End using point size
+ """
+ return _richtext.RichTextCtrl_EndFontSize(*args, **kwargs)
+
+ def BeginFont(*args, **kwargs):
+ """
+ BeginFont(self, Font font) -> bool
+
+ Begin using this font
+ """
+ return _richtext.RichTextCtrl_BeginFont(*args, **kwargs)
+
+ def EndFont(*args, **kwargs):
+ """
+ EndFont(self) -> bool
+
+ End using a font
+ """
+ return _richtext.RichTextCtrl_EndFont(*args, **kwargs)
+
+ def BeginTextColour(*args, **kwargs):
+ """
+ BeginTextColour(self, Colour colour) -> bool
+
+ Begin using this colour
+ """
+ return _richtext.RichTextCtrl_BeginTextColour(*args, **kwargs)
+
+ def EndTextColour(*args, **kwargs):
+ """
+ EndTextColour(self) -> bool
+
+ End using a colour
+ """
+ return _richtext.RichTextCtrl_EndTextColour(*args, **kwargs)
+
+ def BeginAlignment(*args, **kwargs):
+ """
+ BeginAlignment(self, int alignment) -> bool
+
+ Begin using alignment
+ """
+ return _richtext.RichTextCtrl_BeginAlignment(*args, **kwargs)
+
+ def EndAlignment(*args, **kwargs):
+ """
+ EndAlignment(self) -> bool
+
+ End alignment
+ """
+ return _richtext.RichTextCtrl_EndAlignment(*args, **kwargs)
+
+ def BeginLeftIndent(*args, **kwargs):
+ """
+ BeginLeftIndent(self, int leftIndent, int leftSubIndent=0) -> bool
+
+ Begin left indent
+ """
+ return _richtext.RichTextCtrl_BeginLeftIndent(*args, **kwargs)
+
+ def EndLeftIndent(*args, **kwargs):
+ """
+ EndLeftIndent(self) -> bool
+
+ End left indent
+ """
+ return _richtext.RichTextCtrl_EndLeftIndent(*args, **kwargs)
+
+ def BeginRightIndent(*args, **kwargs):
+ """
+ BeginRightIndent(self, int rightIndent) -> bool
+
+ Begin right indent
+ """
+ return _richtext.RichTextCtrl_BeginRightIndent(*args, **kwargs)
+
+ def EndRightIndent(*args, **kwargs):
+ """
+ EndRightIndent(self) -> bool
+
+ End right indent
+ """
+ return _richtext.RichTextCtrl_EndRightIndent(*args, **kwargs)
+
+ def BeginParagraphSpacing(*args, **kwargs):
+ """
+ BeginParagraphSpacing(self, int before, int after) -> bool
+
+ Begin paragraph spacing
+ """
+ return _richtext.RichTextCtrl_BeginParagraphSpacing(*args, **kwargs)
+
+ def EndParagraphSpacing(*args, **kwargs):
+ """
+ EndParagraphSpacing(self) -> bool
+
+ End paragraph spacing
+ """
+ return _richtext.RichTextCtrl_EndParagraphSpacing(*args, **kwargs)
+
+ def BeginLineSpacing(*args, **kwargs):
+ """
+ BeginLineSpacing(self, int lineSpacing) -> bool
+
+ Begin line spacing
+ """
+ return _richtext.RichTextCtrl_BeginLineSpacing(*args, **kwargs)
+
+ def EndLineSpacing(*args, **kwargs):
+ """
+ EndLineSpacing(self) -> bool
+
+ End line spacing
+ """
+ return _richtext.RichTextCtrl_EndLineSpacing(*args, **kwargs)
+
+ def BeginNumberedBullet(*args, **kwargs):
+ """
+ BeginNumberedBullet(self, int bulletNumber, int leftIndent, int leftSubIndent,
+ int bulletStyle=wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD) -> bool
+
+ Begin numbered bullet
+ """
+ return _richtext.RichTextCtrl_BeginNumberedBullet(*args, **kwargs)
+
+ def EndNumberedBullet(*args, **kwargs):
+ """
+ EndNumberedBullet(self) -> bool
+
+ End numbered bullet
+ """
+ return _richtext.RichTextCtrl_EndNumberedBullet(*args, **kwargs)
+
+ def BeginSymbolBullet(*args, **kwargs):
+ """
+ BeginSymbolBullet(self, String symbol, int leftIndent, int leftSubIndent, int bulletStyle=TEXT_ATTR_BULLET_STYLE_SYMBOL) -> bool
+
+ Begin symbol bullet
+ """
+ return _richtext.RichTextCtrl_BeginSymbolBullet(*args, **kwargs)
+
+ def EndSymbolBullet(*args, **kwargs):
+ """
+ EndSymbolBullet(self) -> bool
+
+ End symbol bullet
+ """
+ return _richtext.RichTextCtrl_EndSymbolBullet(*args, **kwargs)
+
+ def BeginStandardBullet(*args, **kwargs):
+ """
+ BeginStandardBullet(self, String bulletName, int leftIndent, int leftSubIndent,
+ int bulletStyle=TEXT_ATTR_BULLET_STYLE_STANDARD) -> bool
+
+ Begin standard bullet
+ """
+ return _richtext.RichTextCtrl_BeginStandardBullet(*args, **kwargs)
+
+ def EndStandardBullet(*args, **kwargs):
+ """
+ EndStandardBullet(self) -> bool
+
+ End standard bullet
+ """
+ return _richtext.RichTextCtrl_EndStandardBullet(*args, **kwargs)
+
+ def BeginCharacterStyle(*args, **kwargs):
+ """
+ BeginCharacterStyle(self, String characterStyle) -> bool
+
+ Begin named character style
+ """
+ return _richtext.RichTextCtrl_BeginCharacterStyle(*args, **kwargs)
+
+ def EndCharacterStyle(*args, **kwargs):
+ """
+ EndCharacterStyle(self) -> bool
+
+ End named character style
+ """
+ return _richtext.RichTextCtrl_EndCharacterStyle(*args, **kwargs)
+
+ def BeginParagraphStyle(*args, **kwargs):
+ """
+ BeginParagraphStyle(self, String paragraphStyle) -> bool
+
+ Begin named paragraph style
+ """
+ return _richtext.RichTextCtrl_BeginParagraphStyle(*args, **kwargs)
+
+ def EndParagraphStyle(*args, **kwargs):
+ """
+ EndParagraphStyle(self) -> bool
+
+ End named character style
+ """
+ return _richtext.RichTextCtrl_EndParagraphStyle(*args, **kwargs)
+
+ def BeginListStyle(*args, **kwargs):
+ """
+ BeginListStyle(self, String listStyle, int level=1, int number=1) -> bool
+
+ Begin named list style.
+ """
+ return _richtext.RichTextCtrl_BeginListStyle(*args, **kwargs)
+
+ def EndListStyle(*args, **kwargs):
+ """
+ EndListStyle(self) -> bool
+
+ End named list style.
+ """
+ return _richtext.RichTextCtrl_EndListStyle(*args, **kwargs)
+
+ def BeginURL(*args, **kwargs):
+ """
+ BeginURL(self, String url, String characterStyle=wxEmptyString) -> bool
+
+ Begin URL.
+ """
+ return _richtext.RichTextCtrl_BeginURL(*args, **kwargs)
+
+ def EndURL(*args, **kwargs):
+ """
+ EndURL(self) -> bool
+
+ End URL.
+ """
+ return _richtext.RichTextCtrl_EndURL(*args, **kwargs)
+
+ def SetDefaultStyleToCursorStyle(*args, **kwargs):
+ """
+ SetDefaultStyleToCursorStyle(self) -> bool
+
+ Sets the default style to the style under the cursor
+ """
+ return _richtext.RichTextCtrl_SetDefaultStyleToCursorStyle(*args, **kwargs)
+
+ def SelectNone(*args, **kwargs):
+ """
+ SelectNone(self)
+
+ Clear the selection
+ """
+ return _richtext.RichTextCtrl_SelectNone(*args, **kwargs)
+
+ def SelectWord(*args, **kwargs):
+ """
+ SelectWord(self, long position) -> bool
+
+ Select the word at the given character position
+ """
+ return _richtext.RichTextCtrl_SelectWord(*args, **kwargs)
+
+ def GetSelectionRange(*args, **kwargs):
+ """
+ GetSelectionRange(self) -> RichTextRange
+
+ Get the selection range in character positions.
+ """
+ return _richtext.RichTextCtrl_GetSelectionRange(*args, **kwargs)
+
+ def SetSelectionRange(*args, **kwargs):
+ """
+ SetSelectionRange(self, RichTextRange range)
+
+ Set the selection range in character positions. The end point of range
+ is specified as the last character position of the span of text, plus
+ one. So, for example, to set the selection for a character at position
+ 5, use the range (5,6).
+ """
+ return _richtext.RichTextCtrl_SetSelectionRange(*args, **kwargs)
+
+ def GetInternalSelectionRange(*args, **kwargs):
+ """
+ GetInternalSelectionRange(self) -> RichTextRange
+
+ Get the selection range in character positions. The range is in
+ internal format, i.e. a single character selection is denoted by (n,n).
+
+ """
+ return _richtext.RichTextCtrl_GetInternalSelectionRange(*args, **kwargs)
+
+ def SetInternalSelectionRange(*args, **kwargs):
+ """
+ SetInternalSelectionRange(self, RichTextRange range)
+
+ Set the selection range in character positions. The range is in
+ internal format, i.e. a single character selection is denoted by (n,n).
+ """
+ return _richtext.RichTextCtrl_SetInternalSelectionRange(*args, **kwargs)
+
+ def AddParagraph(*args, **kwargs):
+ """
+ AddParagraph(self, String text) -> RichTextRange
+
+ Add a new paragraph of text to the end of the buffer
+ """
+ return _richtext.RichTextCtrl_AddParagraph(*args, **kwargs)
+
+ def AddImage(*args, **kwargs):
+ """
+ AddImage(self, Image image) -> RichTextRange
+
+ Add an image
+ """
+ return _richtext.RichTextCtrl_AddImage(*args, **kwargs)
+
+ def LayoutContent(*args, **kwargs):
+ """
+ LayoutContent(self, bool onlyVisibleRect=False) -> bool
+
+ Layout the buffer: which we must do before certain operations, such as
+ setting the caret position.
+ """
+ return _richtext.RichTextCtrl_LayoutContent(*args, **kwargs)
+
+ def MoveCaret(*args, **kwargs):
+ """
+ MoveCaret(self, long pos, bool showAtLineStart=False) -> bool
+
+ Move the caret to the given character position
+ """
+ return _richtext.RichTextCtrl_MoveCaret(*args, **kwargs)
+
+ def MoveRight(*args, **kwargs):
+ """
+ MoveRight(self, int noPositions=1, int flags=0) -> bool
+
+ Move right
+ """
+ return _richtext.RichTextCtrl_MoveRight(*args, **kwargs)
+
+ def MoveLeft(*args, **kwargs):
+ """
+ MoveLeft(self, int noPositions=1, int flags=0) -> bool
+
+ Move left
+ """
+ return _richtext.RichTextCtrl_MoveLeft(*args, **kwargs)
+
+ def MoveUp(*args, **kwargs):
+ """
+ MoveUp(self, int noLines=1, int flags=0) -> bool
+
+ Move up
+ """
+ return _richtext.RichTextCtrl_MoveUp(*args, **kwargs)
+
+ def MoveDown(*args, **kwargs):
+ """
+ MoveDown(self, int noLines=1, int flags=0) -> bool
+
+ Move down
+ """
+ return _richtext.RichTextCtrl_MoveDown(*args, **kwargs)
+
+ def MoveToLineEnd(*args, **kwargs):
+ """
+ MoveToLineEnd(self, int flags=0) -> bool
+
+ Move to the end of the line
+ """
+ return _richtext.RichTextCtrl_MoveToLineEnd(*args, **kwargs)
+
+ def MoveToLineStart(*args, **kwargs):
+ """
+ MoveToLineStart(self, int flags=0) -> bool
+
+ Move to the start of the line
+ """
+ return _richtext.RichTextCtrl_MoveToLineStart(*args, **kwargs)
+
+ def MoveToParagraphEnd(*args, **kwargs):
+ """
+ MoveToParagraphEnd(self, int flags=0) -> bool
+
+ Move to the end of the paragraph
+ """
+ return _richtext.RichTextCtrl_MoveToParagraphEnd(*args, **kwargs)
+
+ def MoveToParagraphStart(*args, **kwargs):
+ """
+ MoveToParagraphStart(self, int flags=0) -> bool
+
+ Move to the start of the paragraph
+ """
+ return _richtext.RichTextCtrl_MoveToParagraphStart(*args, **kwargs)
+
+ def MoveHome(*args, **kwargs):
+ """
+ MoveHome(self, int flags=0) -> bool
+
+ Move to the start of the buffer
+ """
+ return _richtext.RichTextCtrl_MoveHome(*args, **kwargs)
+
+ def MoveEnd(*args, **kwargs):
+ """
+ MoveEnd(self, int flags=0) -> bool
+
+ Move to the end of the buffer
+ """
+ return _richtext.RichTextCtrl_MoveEnd(*args, **kwargs)
+
+ def PageUp(*args, **kwargs):
+ """
+ PageUp(self, int noPages=1, int flags=0) -> bool
+
+ Move n pages up
+ """
+ return _richtext.RichTextCtrl_PageUp(*args, **kwargs)
+
+ def PageDown(*args, **kwargs):
+ """
+ PageDown(self, int noPages=1, int flags=0) -> bool
+
+ Move n pages down
+ """
+ return _richtext.RichTextCtrl_PageDown(*args, **kwargs)
+
+ def WordLeft(*args, **kwargs):
+ """
+ WordLeft(self, int noPages=1, int flags=0) -> bool
+
+ Move n words left
+ """
+ return _richtext.RichTextCtrl_WordLeft(*args, **kwargs)
+
+ def WordRight(*args, **kwargs):
+ """
+ WordRight(self, int noPages=1, int flags=0) -> bool
+
+ Move n words right
+ """
+ return _richtext.RichTextCtrl_WordRight(*args, **kwargs)
+
+ def GetBuffer(*args, **kwargs):
+ """
+ GetBuffer(self) -> RichTextBuffer
+
+ Returns the buffer associated with the control.
+
+ """
+ return _richtext.RichTextCtrl_GetBuffer(*args, **kwargs)
+
+ def BeginBatchUndo(*args, **kwargs):
+ """
+ BeginBatchUndo(self, String cmdName) -> bool
+
+ Start batching undo history for commands
+ """
+ return _richtext.RichTextCtrl_BeginBatchUndo(*args, **kwargs)
+
+ def EndBatchUndo(*args, **kwargs):
+ """
+ EndBatchUndo(self) -> bool
+
+ End batching undo history for commands.
+ """
+ return _richtext.RichTextCtrl_EndBatchUndo(*args, **kwargs)
+
+ def BatchingUndo(*args, **kwargs):
+ """
+ BatchingUndo(self) -> bool
+
+ Are we batching undo history for commands?
+ """
+ return _richtext.RichTextCtrl_BatchingUndo(*args, **kwargs)
+
+ def BeginSuppressUndo(*args, **kwargs):
+ """
+ BeginSuppressUndo(self) -> bool
+
+ Start suppressing undo history for commands.
+ """
+ return _richtext.RichTextCtrl_BeginSuppressUndo(*args, **kwargs)
+
+ def EndSuppressUndo(*args, **kwargs):
+ """
+ EndSuppressUndo(self) -> bool
+
+ End suppressing undo history for commands.
+ """
+ return _richtext.RichTextCtrl_EndSuppressUndo(*args, **kwargs)
+
+ def SuppressingUndo(*args, **kwargs):
+ """
+ SuppressingUndo(self) -> bool
+
+ Are we suppressing undo history for commands?
+ """
+ return _richtext.RichTextCtrl_SuppressingUndo(*args, **kwargs)
+
+ def HasCharacterAttributes(*args, **kwargs):
+ """
+ HasCharacterAttributes(self, RichTextRange range, RichTextAttr style) -> bool
+
+ Test if this whole range has character attributes of the specified
+ kind. If any of the attributes are different within the range, the
+ test fails. You can use this to implement, for example, bold button
+ updating. ``style`` must have flags indicating which attributes are of
+ interest.
+
+ """
+ return _richtext.RichTextCtrl_HasCharacterAttributes(*args, **kwargs)
+
+ def HasParagraphAttributes(*args, **kwargs):
+ """
+ HasParagraphAttributes(self, RichTextRange range, RichTextAttr style) -> bool
+
+ Test if this whole range has paragraph attributes of the specified
+ kind. If any of the attributes are different within the range, the
+ test fails. You can use this to implement, for example, centering
+ button updating. style must have flags indicating which attributes are
+ of interest.
+
+ """
+ return _richtext.RichTextCtrl_HasParagraphAttributes(*args, **kwargs)
+
+ def IsSelectionBold(*args, **kwargs):
+ """
+ IsSelectionBold(self) -> bool
+
+ Is all of the selection bold?
+ """
+ return _richtext.RichTextCtrl_IsSelectionBold(*args, **kwargs)
+
+ def IsSelectionItalics(*args, **kwargs):
+ """
+ IsSelectionItalics(self) -> bool
+
+ Is all of the selection italics?
+ """
+ return _richtext.RichTextCtrl_IsSelectionItalics(*args, **kwargs)
+
+ def IsSelectionUnderlined(*args, **kwargs):
+ """
+ IsSelectionUnderlined(self) -> bool
+
+ Is all of the selection underlined?
+ """
+ return _richtext.RichTextCtrl_IsSelectionUnderlined(*args, **kwargs)
+
+ def DoesSelectionHaveTextEffectFlag(*args, **kwargs):
+ """DoesSelectionHaveTextEffectFlag(self, int flag) -> bool"""
+ return _richtext.RichTextCtrl_DoesSelectionHaveTextEffectFlag(*args, **kwargs)
+
+ def IsSelectionAligned(*args, **kwargs):
+ """
+ IsSelectionAligned(self, int alignment) -> bool
+
+ Is all of the selection aligned according to the specified flag?
+ """
+ return _richtext.RichTextCtrl_IsSelectionAligned(*args, **kwargs)
+
+ def ApplyBoldToSelection(*args, **kwargs):
+ """
+ ApplyBoldToSelection(self) -> bool
+
+ Apply bold to the selection
+ """
+ return _richtext.RichTextCtrl_ApplyBoldToSelection(*args, **kwargs)
+
+ def ApplyItalicToSelection(*args, **kwargs):
+ """
+ ApplyItalicToSelection(self) -> bool
+
+ Apply italic to the selection
+ """
+ return _richtext.RichTextCtrl_ApplyItalicToSelection(*args, **kwargs)
+
+ def ApplyUnderlineToSelection(*args, **kwargs):
+ """
+ ApplyUnderlineToSelection(self) -> bool
+
+ Apply underline to the selection
+ """
+ return _richtext.RichTextCtrl_ApplyUnderlineToSelection(*args, **kwargs)
+
+ def ApplyTextEffectToSelection(*args, **kwargs):
+ """ApplyTextEffectToSelection(self, int flags) -> bool"""
+ return _richtext.RichTextCtrl_ApplyTextEffectToSelection(*args, **kwargs)
+
+ def ApplyAlignmentToSelection(*args, **kwargs):
+ """
+ ApplyAlignmentToSelection(self, int alignment) -> bool
+
+ Apply alignment to the selection
+ """
+ return _richtext.RichTextCtrl_ApplyAlignmentToSelection(*args, **kwargs)
+
+ def ApplyStyle(*args, **kwargs):
+ """
+ ApplyStyle(self, wxRichTextStyleDefinition def) -> bool
+
+ Apply a named style to the selection
+ """
+ return _richtext.RichTextCtrl_ApplyStyle(*args, **kwargs)
+
+ def SetStyleSheet(*args, **kwargs):
+ """
+ SetStyleSheet(self, wxRichTextStyleSheet styleSheet)
+
+ Set style sheet, if any.
+ """
+ return _richtext.RichTextCtrl_SetStyleSheet(*args, **kwargs)
+
+ def GetStyleSheet(*args, **kwargs):
+ """GetStyleSheet(self) -> wxRichTextStyleSheet"""
+ return _richtext.RichTextCtrl_GetStyleSheet(*args, **kwargs)
+
+ def PushStyleSheet(*args, **kwargs):
+ """
+ PushStyleSheet(self, wxRichTextStyleSheet styleSheet) -> bool
+
+ Push style sheet to top of stack
+ """
+ return _richtext.RichTextCtrl_PushStyleSheet(*args, **kwargs)
+
+ def PopStyleSheet(*args, **kwargs):
+ """
+ PopStyleSheet(self) -> wxRichTextStyleSheet
+
+ Pop style sheet from top of stack
+ """
+ return _richtext.RichTextCtrl_PopStyleSheet(*args, **kwargs)
+
+ def ApplyStyleSheet(*args, **kwargs):
+ """
+ ApplyStyleSheet(self, wxRichTextStyleSheet styleSheet=None) -> bool
+
+ Apply the style sheet to the buffer, for example if the styles have
+ changed.
+ """
+ return _richtext.RichTextCtrl_ApplyStyleSheet(*args, **kwargs)
+
+ def ShowContextMenu(*args, **kwargs):
+ """ShowContextMenu(self, Menu menu, Point pt, bool addPropertyCommands=True) -> bool"""
+ return _richtext.RichTextCtrl_ShowContextMenu(*args, **kwargs)
+
+ def PrepareContextMenu(*args, **kwargs):
+ """PrepareContextMenu(self, Menu menu, Point pt, bool addPropertyCommands=True) -> int"""
+ return _richtext.RichTextCtrl_PrepareContextMenu(*args, **kwargs)
+
+ Buffer = property(GetBuffer)
+ DelayedLayoutThreshold = property(GetDelayedLayoutThreshold,SetDelayedLayoutThreshold)
+ Filename = property(GetFilename,SetFilename)
+ InternalSelectionRange = property(GetInternalSelectionRange,SetInternalSelectionRange)
+ SelectionRange = property(GetSelectionRange,SetSelectionRange)
+ StyleSheet = property(GetStyleSheet,SetStyleSheet)
+ TextCursor = property(GetTextCursor,SetTextCursor)
+ URLCursor = property(GetURLCursor,SetURLCursor)
+ def SetupScrollbars(*args, **kwargs):
+ """SetupScrollbars(self, bool atTop=False)"""
+ return _richtext.RichTextCtrl_SetupScrollbars(*args, **kwargs)
+
+ def KeyboardNavigate(*args, **kwargs):
+ """KeyboardNavigate(self, int keyCode, int flags) -> bool"""
+ return _richtext.RichTextCtrl_KeyboardNavigate(*args, **kwargs)
+
+ def PositionCaret(*args, **kwargs):
+ """PositionCaret(self)"""
+ return _richtext.RichTextCtrl_PositionCaret(*args, **kwargs)
+
+ def ExtendSelection(*args, **kwargs):
+ """ExtendSelection(self, long oldPosition, long newPosition, int flags) -> bool"""
+ return _richtext.RichTextCtrl_ExtendSelection(*args, **kwargs)
+
+ def ScrollIntoView(*args, **kwargs):
+ """ScrollIntoView(self, long position, int keyCode) -> bool"""
+ return _richtext.RichTextCtrl_ScrollIntoView(*args, **kwargs)
+
+ def SetCaretPosition(*args, **kwargs):
+ """SetCaretPosition(self, long position, bool showAtLineStart=False)"""
+ return _richtext.RichTextCtrl_SetCaretPosition(*args, **kwargs)
+
+ def GetCaretPosition(*args, **kwargs):
+ """GetCaretPosition(self) -> long"""
+ return _richtext.RichTextCtrl_GetCaretPosition(*args, **kwargs)
+
+ def GetAdjustedCaretPosition(*args, **kwargs):
+ """GetAdjustedCaretPosition(self, long caretPos) -> long"""
+ return _richtext.RichTextCtrl_GetAdjustedCaretPosition(*args, **kwargs)
+
+ def MoveCaretForward(*args, **kwargs):
+ """MoveCaretForward(self, long oldPosition)"""
+ return _richtext.RichTextCtrl_MoveCaretForward(*args, **kwargs)
+
+ def MoveCaretBack(*args, **kwargs):
+ """MoveCaretBack(self, long oldPosition)"""
+ return _richtext.RichTextCtrl_MoveCaretBack(*args, **kwargs)
+
+ def GetCaretPositionForIndex(*args, **kwargs):
+ """GetCaretPositionForIndex(self, long position, Rect rect) -> bool"""
+ return _richtext.RichTextCtrl_GetCaretPositionForIndex(*args, **kwargs)
+
+ def GetVisibleLineForCaretPosition(*args, **kwargs):
+ """GetVisibleLineForCaretPosition(self, long caretPosition) -> RichTextLine"""
+ return _richtext.RichTextCtrl_GetVisibleLineForCaretPosition(*args, **kwargs)
+
+ def GetCommandProcessor(*args, **kwargs):
+ """GetCommandProcessor(self) -> wxCommandProcessor"""
+ return _richtext.RichTextCtrl_GetCommandProcessor(*args, **kwargs)
+
+ def DeleteSelectedContent(*args, **kwargs):
+ """DeleteSelectedContent(self, long OUTPUT) -> bool"""
+ return _richtext.RichTextCtrl_DeleteSelectedContent(*args, **kwargs)
+
+ def GetPhysicalPoint(*args, **kwargs):
+ """GetPhysicalPoint(self, Point ptLogical) -> Point"""
+ return _richtext.RichTextCtrl_GetPhysicalPoint(*args, **kwargs)
+
+ def GetLogicalPoint(*args, **kwargs):
+ """GetLogicalPoint(self, Point ptPhysical) -> Point"""
+ return _richtext.RichTextCtrl_GetLogicalPoint(*args, **kwargs)
+
+ def FindNextWordPosition(*args, **kwargs):
+ """FindNextWordPosition(self, int direction=1) -> long"""
+ return _richtext.RichTextCtrl_FindNextWordPosition(*args, **kwargs)
+
+ def IsPositionVisible(*args, **kwargs):
+ """IsPositionVisible(self, long pos) -> bool"""
+ return _richtext.RichTextCtrl_IsPositionVisible(*args, **kwargs)
+
+ def GetFirstVisiblePosition(*args, **kwargs):
+ """GetFirstVisiblePosition(self) -> long"""
+ return _richtext.RichTextCtrl_GetFirstVisiblePosition(*args, **kwargs)
+
+ def GetCaretPositionForDefaultStyle(*args, **kwargs):
+ """GetCaretPositionForDefaultStyle(self) -> long"""
+ return _richtext.RichTextCtrl_GetCaretPositionForDefaultStyle(*args, **kwargs)
+
+ def SetCaretPositionForDefaultStyle(*args, **kwargs):
+ """SetCaretPositionForDefaultStyle(self, long pos)"""
+ return _richtext.RichTextCtrl_SetCaretPositionForDefaultStyle(*args, **kwargs)
+
+ def IsDefaultStyleShowing(*args, **kwargs):
+ """IsDefaultStyleShowing(self) -> bool"""
+ return _richtext.RichTextCtrl_IsDefaultStyleShowing(*args, **kwargs)
+
+ def SetAndShowDefaultStyle(*args, **kwargs):
+ """SetAndShowDefaultStyle(self, RichTextAttr attr)"""
+ return _richtext.RichTextCtrl_SetAndShowDefaultStyle(*args, **kwargs)
+
+ def GetFirstVisiblePoint(*args, **kwargs):
+ """GetFirstVisiblePoint(self) -> Point"""
+ return _richtext.RichTextCtrl_GetFirstVisiblePoint(*args, **kwargs)
+
+ def GetScrollPageSize(*args, **kwargs):
+ """GetScrollPageSize(self, int orient) -> int"""
+ return _richtext.RichTextCtrl_GetScrollPageSize(*args, **kwargs)
+
+ def SetScrollPageSize(*args, **kwargs):
+ """SetScrollPageSize(self, int orient, int pageSize)"""
+ return _richtext.RichTextCtrl_SetScrollPageSize(*args, **kwargs)
+
+ def SetScrollRate(*args, **kwargs):
+ """SetScrollRate(self, int xstep, int ystep)"""
+ return _richtext.RichTextCtrl_SetScrollRate(*args, **kwargs)
+
+ def GetViewStart(*args, **kwargs):
+ """
+ GetViewStart() -> (x,y)
+
+ Get the view start
+ """
+ return _richtext.RichTextCtrl_GetViewStart(*args, **kwargs)
+
+ def SetScale(*args, **kwargs):
+ """SetScale(self, double xs, double ys)"""
+ return _richtext.RichTextCtrl_SetScale(*args, **kwargs)
+
+ def GetScaleX(*args, **kwargs):
+ """GetScaleX(self) -> double"""
+ return _richtext.RichTextCtrl_GetScaleX(*args, **kwargs)
+
+ def GetScaleY(*args, **kwargs):
+ """GetScaleY(self) -> double"""
+ return _richtext.RichTextCtrl_GetScaleY(*args, **kwargs)
+
+ def CalcScrolledPosition(*args):
+ """
+ CalcScrolledPosition(self, Point pt) -> Point
+ CalcScrolledPosition(int x, int y) -> (sx, sy)
+
+ Translate between scrolled and unscrolled coordinates.
+ """
+ return _richtext.RichTextCtrl_CalcScrolledPosition(*args)
+
+ def CalcUnscrolledPosition(*args):
+ """
+ CalcUnscrolledPosition(self, Point pt) -> Point
+ CalcUnscrolledPosition(int x, int y) -> (ux, uy)
+
+ Translate between scrolled and unscrolled coordinates.
+ """
+ return _richtext.RichTextCtrl_CalcUnscrolledPosition(*args)
+
+ def SetTargetRect(*args, **kwargs):
+ """SetTargetRect(self, Rect rect)"""
+ return _richtext.RichTextCtrl_SetTargetRect(*args, **kwargs)
+
+ def GetTargetRect(*args, **kwargs):
+ """GetTargetRect(self) -> Rect"""
+ return _richtext.RichTextCtrl_GetTargetRect(*args, **kwargs)
+
+ def IsEmpty(*args, **kwargs):
+ """
+ IsEmpty(self) -> bool
+
+ Returns True if the value in the text field is empty.
+ """
+ return _richtext.RichTextCtrl_IsEmpty(*args, **kwargs)
+
+ def SetModified(*args, **kwargs):
+ """SetModified(self, bool modified)"""
+ return _richtext.RichTextCtrl_SetModified(*args, **kwargs)
+
+_richtext.RichTextCtrl_swigregister(RichTextCtrl)
+RichTextCtrlNameStr = cvar.RichTextCtrlNameStr
+
+def PreRichTextCtrl(*args, **kwargs):
+ """PreRichTextCtrl() -> RichTextCtrl"""
+ val = _richtext.new_PreRichTextCtrl(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+wxEVT_COMMAND_RICHTEXT_LEFT_CLICK = _richtext.wxEVT_COMMAND_RICHTEXT_LEFT_CLICK
+wxEVT_COMMAND_RICHTEXT_RIGHT_CLICK = _richtext.wxEVT_COMMAND_RICHTEXT_RIGHT_CLICK
+wxEVT_COMMAND_RICHTEXT_MIDDLE_CLICK = _richtext.wxEVT_COMMAND_RICHTEXT_MIDDLE_CLICK
+wxEVT_COMMAND_RICHTEXT_LEFT_DCLICK = _richtext.wxEVT_COMMAND_RICHTEXT_LEFT_DCLICK
+wxEVT_COMMAND_RICHTEXT_RETURN = _richtext.wxEVT_COMMAND_RICHTEXT_RETURN
+wxEVT_COMMAND_RICHTEXT_CHARACTER = _richtext.wxEVT_COMMAND_RICHTEXT_CHARACTER
+wxEVT_COMMAND_RICHTEXT_DELETE = _richtext.wxEVT_COMMAND_RICHTEXT_DELETE
+wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGING = _richtext.wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGING
+wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGED = _richtext.wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGED
+wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING = _richtext.wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING
+wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACED = _richtext.wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACED
+wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED = _richtext.wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED
+wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED = _richtext.wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED
+wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED = _richtext.wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED
+wxEVT_COMMAND_RICHTEXT_SELECTION_CHANGED = _richtext.wxEVT_COMMAND_RICHTEXT_SELECTION_CHANGED
+wxEVT_COMMAND_RICHTEXT_BUFFER_RESET = _richtext.wxEVT_COMMAND_RICHTEXT_BUFFER_RESET
+EVT_RICHTEXT_LEFT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_RICHTEXT_LEFT_CLICK, 1)
+EVT_RICHTEXT_RIGHT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_RICHTEXT_RIGHT_CLICK, 1)
+EVT_RICHTEXT_MIDDLE_CLICK = wx.PyEventBinder(wxEVT_COMMAND_RICHTEXT_MIDDLE_CLICK, 1)
+EVT_RICHTEXT_LEFT_DCLICK = wx.PyEventBinder(wxEVT_COMMAND_RICHTEXT_LEFT_DCLICK, 1)
+EVT_RICHTEXT_RETURN = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_RETURN, 1)
+EVT_RICHTEXT_CHARACTER = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_CHARACTER, 1)
+EVT_RICHTEXT_DELETE = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_DELETE, 1)
+
+EVT_RICHTEXT_STYLESHEET_CHANGING = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGING, 1)
+EVT_RICHTEXT_STYLESHEET_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGED, 1)
+EVT_RICHTEXT_STYLESHEET_REPLACING = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING, 1)
+EVT_RICHTEXT_STYLESHEET_REPLACED = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACED, 1)
+
+EVT_RICHTEXT_CONTENT_INSERTED = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED, 1)
+EVT_RICHTEXT_CONTENT_DELETED = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED, 1)
+EVT_RICHTEXT_STYLE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED, 1)
+EVT_RICHTEXT_SELECTION_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_SELECTION_CHANGED, 1)
+EVT_RICHTEXT_BUFFER_RESET = wx.PyEventBinder( wxEVT_COMMAND_RICHTEXT_BUFFER_RESET, 1)
+
+class RichTextEvent(_core.NotifyEvent):
+ """Proxy of C++ RichTextEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=wxEVT_NULL, int winid=0) -> RichTextEvent"""
+ _richtext.RichTextEvent_swiginit(self,_richtext.new_RichTextEvent(*args, **kwargs))
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> int"""
+ return _richtext.RichTextEvent_GetPosition(*args, **kwargs)
+
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, int n)"""
+ return _richtext.RichTextEvent_SetPosition(*args, **kwargs)
+
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _richtext.RichTextEvent_GetFlags(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _richtext.RichTextEvent_SetFlags(*args, **kwargs)
+
+ def GetOldStyleSheet(*args, **kwargs):
+ """GetOldStyleSheet(self) -> wxRichTextStyleSheet"""
+ return _richtext.RichTextEvent_GetOldStyleSheet(*args, **kwargs)
+
+ def SetOldStyleSheet(*args, **kwargs):
+ """SetOldStyleSheet(self, wxRichTextStyleSheet sheet)"""
+ return _richtext.RichTextEvent_SetOldStyleSheet(*args, **kwargs)
+
+ def GetNewStyleSheet(*args, **kwargs):
+ """GetNewStyleSheet(self) -> wxRichTextStyleSheet"""
+ return _richtext.RichTextEvent_GetNewStyleSheet(*args, **kwargs)
+
+ def SetNewStyleSheet(*args, **kwargs):
+ """SetNewStyleSheet(self, wxRichTextStyleSheet sheet)"""
+ return _richtext.RichTextEvent_SetNewStyleSheet(*args, **kwargs)
+
+ def GetRange(*args, **kwargs):
+ """GetRange(self) -> RichTextRange"""
+ return _richtext.RichTextEvent_GetRange(*args, **kwargs)
+
+ def SetRange(*args, **kwargs):
+ """SetRange(self, RichTextRange range)"""
+ return _richtext.RichTextEvent_SetRange(*args, **kwargs)
+
+ def GetCharacter(*args, **kwargs):
+ """GetCharacter(self) -> wxChar"""
+ return _richtext.RichTextEvent_GetCharacter(*args, **kwargs)
+
+ def SetCharacter(*args, **kwargs):
+ """SetCharacter(self, wxChar ch)"""
+ return _richtext.RichTextEvent_SetCharacter(*args, **kwargs)
+
+ Flags = property(GetFlags,SetFlags)
+ Index = property(GetPosition,SetPosition)
+ OldStyleSheet = property(GetOldStyleSheet,SetOldStyleSheet)
+ NewStyleSheet = property(GetNewStyleSheet,SetNewStyleSheet)
+ Range = property(GetRange,SetRange)
+ Character = property(GetCharacter,SetCharacter)
+_richtext.RichTextEvent_swigregister(RichTextEvent)
+
+#---------------------------------------------------------------------------
+
+class RichTextHTMLHandler(RichTextFileHandler):
+ """Proxy of C++ RichTextHTMLHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String name=HtmlName, String ext=HtmlExt, int type=RICHTEXT_TYPE_HTML) -> RichTextHTMLHandler"""
+ _richtext.RichTextHTMLHandler_swiginit(self,_richtext.new_RichTextHTMLHandler(*args, **kwargs))
+ def SetTemporaryImageLocations(*args, **kwargs):
+ """
+ SetTemporaryImageLocations(self, wxArrayString locations)
+
+ Set the list of image locations generated by the last operation
+ """
+ return _richtext.RichTextHTMLHandler_SetTemporaryImageLocations(*args, **kwargs)
+
+ def GetTemporaryImageLocations(*args, **kwargs):
+ """
+ GetTemporaryImageLocations(self) -> wxArrayString
+
+ Get the list of image locations generated by the last operation
+ """
+ return _richtext.RichTextHTMLHandler_GetTemporaryImageLocations(*args, **kwargs)
+
+ TemporaryImageLocations = property(GetTemporaryImageLocations,SetTemporaryImageLocations)
+ def ClearTemporaryImageLocations(*args, **kwargs):
+ """
+ ClearTemporaryImageLocations(self)
+
+ Clear the image locations generated by the last operation
+ """
+ return _richtext.RichTextHTMLHandler_ClearTemporaryImageLocations(*args, **kwargs)
+
+ def DeleteTemporaryImages(*args, **kwargs):
+ """
+ DeleteTemporaryImages(self) -> bool
+
+ Delete the in-memory or temporary files generated by the last operation
+ """
+ return _richtext.RichTextHTMLHandler_DeleteTemporaryImages(*args, **kwargs)
+
+ def SetFileCounter(*args, **kwargs):
+ """
+ SetFileCounter(int counter)
+
+ Reset the file counter, in case, for example, the same names are required each
+ time
+ """
+ return _richtext.RichTextHTMLHandler_SetFileCounter(*args, **kwargs)
+
+ SetFileCounter = staticmethod(SetFileCounter)
+ def SetTempDir(*args, **kwargs):
+ """
+ SetTempDir(self, String tempDir)
+
+ Set the directory for storing temporary files. If empty, the system temporary
+ directory will be used.
+ """
+ return _richtext.RichTextHTMLHandler_SetTempDir(*args, **kwargs)
+
+ def GetTempDir(*args, **kwargs):
+ """
+ GetTempDir(self) -> String
+
+ Get the directory for storing temporary files. If empty, the system temporary
+ directory will be used.
+ """
+ return _richtext.RichTextHTMLHandler_GetTempDir(*args, **kwargs)
+
+ TempDir = property(GetTempDir,SetTempDir)
+ def SetFontSizeMapping(*args, **kwargs):
+ """
+ SetFontSizeMapping(self, wxArrayInt fontSizeMapping)
+
+ Set mapping from point size to HTML font size. There should be 7 elements, one
+ for each HTML font size, each element specifying the maximum point size for
+ that HTML font size. E.g. 8, 10, 13, 17, 22, 29, 100
+
+ """
+ return _richtext.RichTextHTMLHandler_SetFontSizeMapping(*args, **kwargs)
+
+ def GetFontSizeMapping(*args, **kwargs):
+ """
+ GetFontSizeMapping(self) -> wxArrayInt
+
+ Get mapping deom point size to HTML font size.
+ """
+ return _richtext.RichTextHTMLHandler_GetFontSizeMapping(*args, **kwargs)
+
+ FontSizeMapping = property(GetFontSizeMapping,SetFontSizeMapping)
+_richtext.RichTextHTMLHandler_swigregister(RichTextHTMLHandler)
+HtmlName = cvar.HtmlName
+HtmlExt = cvar.HtmlExt
+
+def RichTextHTMLHandler_SetFileCounter(*args, **kwargs):
+ """
+ RichTextHTMLHandler_SetFileCounter(int counter)
+
+ Reset the file counter, in case, for example, the same names are required each
+ time
+ """
+ return _richtext.RichTextHTMLHandler_SetFileCounter(*args, **kwargs)
+
+#---------------------------------------------------------------------------
+
+class RichTextXMLHandler(RichTextFileHandler):
+ """Proxy of C++ RichTextXMLHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String name=XmlName, String ext=XmlExt, int type=RICHTEXT_TYPE_XML) -> RichTextXMLHandler"""
+ _richtext.RichTextXMLHandler_swiginit(self,_richtext.new_RichTextXMLHandler(*args, **kwargs))
+_richtext.RichTextXMLHandler_swigregister(RichTextXMLHandler)
+XmlName = cvar.XmlName
+XmlExt = cvar.XmlExt
+
+#---------------------------------------------------------------------------
+
+RICHTEXT_PRINT_MAX_PAGES = _richtext.RICHTEXT_PRINT_MAX_PAGES
+RICHTEXT_PAGE_ODD = _richtext.RICHTEXT_PAGE_ODD
+RICHTEXT_PAGE_EVEN = _richtext.RICHTEXT_PAGE_EVEN
+RICHTEXT_PAGE_ALL = _richtext.RICHTEXT_PAGE_ALL
+RICHTEXT_PAGE_LEFT = _richtext.RICHTEXT_PAGE_LEFT
+RICHTEXT_PAGE_CENTRE = _richtext.RICHTEXT_PAGE_CENTRE
+RICHTEXT_PAGE_RIGHT = _richtext.RICHTEXT_PAGE_RIGHT
+class RichTextPrintout(_windows.Printout):
+ """Proxy of C++ RichTextPrintout class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String title=wxT("Printout")) -> RichTextPrintout"""
+ _richtext.RichTextPrintout_swiginit(self,_richtext.new_RichTextPrintout(*args, **kwargs))
+ __swig_destroy__ = _richtext.delete_RichTextPrintout
+ __del__ = lambda self : None;
+ def SetRichTextBuffer(*args, **kwargs):
+ """SetRichTextBuffer(self, RichTextBuffer buffer)"""
+ return _richtext.RichTextPrintout_SetRichTextBuffer(*args, **kwargs)
+
+ def GetRichTextBuffer(*args, **kwargs):
+ """GetRichTextBuffer(self) -> RichTextBuffer"""
+ return _richtext.RichTextPrintout_GetRichTextBuffer(*args, **kwargs)
+
+ def SetHeaderFooterData(*args, **kwargs):
+ """SetHeaderFooterData(self, wxRichTextHeaderFooterData data)"""
+ return _richtext.RichTextPrintout_SetHeaderFooterData(*args, **kwargs)
+
+ def GetHeaderFooterData(*args, **kwargs):
+ """GetHeaderFooterData(self) -> wxRichTextHeaderFooterData"""
+ return _richtext.RichTextPrintout_GetHeaderFooterData(*args, **kwargs)
+
+ def SetMargins(*args, **kwargs):
+ """SetMargins(self, int top=254, int bottom=254, int left=254, int right=254)"""
+ return _richtext.RichTextPrintout_SetMargins(*args, **kwargs)
+
+ def CalculateScaling(*args, **kwargs):
+ """CalculateScaling(self, DC dc, Rect textRect, Rect headerRect, Rect footerRect)"""
+ return _richtext.RichTextPrintout_CalculateScaling(*args, **kwargs)
+
+_richtext.RichTextPrintout_swigregister(RichTextPrintout)
+
+class RichTextPrinting(_core.Object):
+ """Proxy of C++ RichTextPrinting class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String name=wxT("Printing"), Window parentWindow=None) -> RichTextPrinting"""
+ _richtext.RichTextPrinting_swiginit(self,_richtext.new_RichTextPrinting(*args, **kwargs))
+ __swig_destroy__ = _richtext.delete_RichTextPrinting
+ __del__ = lambda self : None;
+ def PreviewFile(*args, **kwargs):
+ """PreviewFile(self, String richTextFile) -> bool"""
+ return _richtext.RichTextPrinting_PreviewFile(*args, **kwargs)
+
+ def PreviewBuffer(*args, **kwargs):
+ """PreviewBuffer(self, RichTextBuffer buffer) -> bool"""
+ return _richtext.RichTextPrinting_PreviewBuffer(*args, **kwargs)
+
+ def PrintFile(*args, **kwargs):
+ """PrintFile(self, String richTextFile) -> bool"""
+ return _richtext.RichTextPrinting_PrintFile(*args, **kwargs)
+
+ def PrintBuffer(*args, **kwargs):
+ """PrintBuffer(self, RichTextBuffer buffer) -> bool"""
+ return _richtext.RichTextPrinting_PrintBuffer(*args, **kwargs)
+
+ def PageSetup(*args, **kwargs):
+ """PageSetup(self)"""
+ return _richtext.RichTextPrinting_PageSetup(*args, **kwargs)
+
+ def SetHeaderFooterData(*args, **kwargs):
+ """SetHeaderFooterData(self, wxRichTextHeaderFooterData data)"""
+ return _richtext.RichTextPrinting_SetHeaderFooterData(*args, **kwargs)
+
+ def GetHeaderFooterData(*args, **kwargs):
+ """GetHeaderFooterData(self) -> wxRichTextHeaderFooterData"""
+ return _richtext.RichTextPrinting_GetHeaderFooterData(*args, **kwargs)
+
+ def SetHeaderText(*args, **kwargs):
+ """SetHeaderText(self, String text, int page=RICHTEXT_PAGE_ALL, int location=RICHTEXT_PAGE_CENTRE)"""
+ return _richtext.RichTextPrinting_SetHeaderText(*args, **kwargs)
+
+ def GetHeaderText(*args, **kwargs):
+ """GetHeaderText(self, int page=RICHTEXT_PAGE_EVEN, int location=RICHTEXT_PAGE_CENTRE) -> String"""
+ return _richtext.RichTextPrinting_GetHeaderText(*args, **kwargs)
+
+ def SetFooterText(*args, **kwargs):
+ """SetFooterText(self, String text, int page=RICHTEXT_PAGE_ALL, int location=RICHTEXT_PAGE_CENTRE)"""
+ return _richtext.RichTextPrinting_SetFooterText(*args, **kwargs)
+
+ def GetFooterText(*args, **kwargs):
+ """GetFooterText(self, int page=RICHTEXT_PAGE_EVEN, int location=RICHTEXT_PAGE_CENTRE) -> String"""
+ return _richtext.RichTextPrinting_GetFooterText(*args, **kwargs)
+
+ def SetShowOnFirstPage(*args, **kwargs):
+ """SetShowOnFirstPage(self, bool show)"""
+ return _richtext.RichTextPrinting_SetShowOnFirstPage(*args, **kwargs)
+
+ def SetHeaderFooterFont(*args, **kwargs):
+ """SetHeaderFooterFont(self, Font font)"""
+ return _richtext.RichTextPrinting_SetHeaderFooterFont(*args, **kwargs)
+
+ def SetHeaderFooterTextColour(*args, **kwargs):
+ """SetHeaderFooterTextColour(self, Colour font)"""
+ return _richtext.RichTextPrinting_SetHeaderFooterTextColour(*args, **kwargs)
+
+ def GetPrintData(*args, **kwargs):
+ """GetPrintData(self) -> PrintData"""
+ return _richtext.RichTextPrinting_GetPrintData(*args, **kwargs)
+
+ def GetPageSetupData(*args, **kwargs):
+ """GetPageSetupData(self) -> PageSetupDialogData"""
+ return _richtext.RichTextPrinting_GetPageSetupData(*args, **kwargs)
+
+ def SetPrintData(*args, **kwargs):
+ """SetPrintData(self, PrintData printData)"""
+ return _richtext.RichTextPrinting_SetPrintData(*args, **kwargs)
+
+ def SetPageSetupData(*args, **kwargs):
+ """SetPageSetupData(self, wxPageSetupData pageSetupData)"""
+ return _richtext.RichTextPrinting_SetPageSetupData(*args, **kwargs)
+
+ def SetRichTextBufferPreview(*args, **kwargs):
+ """SetRichTextBufferPreview(self, RichTextBuffer buf)"""
+ return _richtext.RichTextPrinting_SetRichTextBufferPreview(*args, **kwargs)
+
+ def GetRichTextBufferPreview(*args, **kwargs):
+ """GetRichTextBufferPreview(self) -> RichTextBuffer"""
+ return _richtext.RichTextPrinting_GetRichTextBufferPreview(*args, **kwargs)
+
+ def SetRichTextBufferPrinting(*args, **kwargs):
+ """SetRichTextBufferPrinting(self, RichTextBuffer buf)"""
+ return _richtext.RichTextPrinting_SetRichTextBufferPrinting(*args, **kwargs)
+
+ def GetRichTextBufferPrinting(*args, **kwargs):
+ """GetRichTextBufferPrinting(self) -> RichTextBuffer"""
+ return _richtext.RichTextPrinting_GetRichTextBufferPrinting(*args, **kwargs)
+
+ def SetParentWindow(*args, **kwargs):
+ """SetParentWindow(self, Window parent)"""
+ return _richtext.RichTextPrinting_SetParentWindow(*args, **kwargs)
+
+ def GetParentWindow(*args, **kwargs):
+ """GetParentWindow(self) -> Window"""
+ return _richtext.RichTextPrinting_GetParentWindow(*args, **kwargs)
+
+ def SetTitle(*args, **kwargs):
+ """SetTitle(self, String title)"""
+ return _richtext.RichTextPrinting_SetTitle(*args, **kwargs)
+
+ def GetTitle(*args, **kwargs):
+ """GetTitle(self) -> String"""
+ return _richtext.RichTextPrinting_GetTitle(*args, **kwargs)
+
+ def SetPreviewRect(*args, **kwargs):
+ """SetPreviewRect(self, Rect rect)"""
+ return _richtext.RichTextPrinting_SetPreviewRect(*args, **kwargs)
+
+ def GetPreviewRect(*args, **kwargs):
+ """GetPreviewRect(self) -> Rect"""
+ return _richtext.RichTextPrinting_GetPreviewRect(*args, **kwargs)
+
+_richtext.RichTextPrinting_swigregister(RichTextPrinting)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/stc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/stc.py
new file mode 100644
index 0000000..5ae4946
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/stc.py
@@ -0,0 +1,7318 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+The `StyledTextCtrl` provides a text editor that can used as a syntax
+highlighting source code editor, or similar. Lexers for several programming
+languages are built-in.
+"""
+
+import _stc
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+import _misc
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+USE_STC = _stc.USE_STC
+USE_TEXTCTRL = _stc.USE_TEXTCTRL
+STC_USE_DND = _stc.STC_USE_DND
+STC_INVALID_POSITION = _stc.STC_INVALID_POSITION
+STC_START = _stc.STC_START
+STC_OPTIONAL_START = _stc.STC_OPTIONAL_START
+STC_LEXER_START = _stc.STC_LEXER_START
+STC_WS_INVISIBLE = _stc.STC_WS_INVISIBLE
+STC_WS_VISIBLEALWAYS = _stc.STC_WS_VISIBLEALWAYS
+STC_WS_VISIBLEAFTERINDENT = _stc.STC_WS_VISIBLEAFTERINDENT
+STC_EOL_CRLF = _stc.STC_EOL_CRLF
+STC_EOL_CR = _stc.STC_EOL_CR
+STC_EOL_LF = _stc.STC_EOL_LF
+STC_CP_UTF8 = _stc.STC_CP_UTF8
+STC_MARKER_MAX = _stc.STC_MARKER_MAX
+STC_MARK_CIRCLE = _stc.STC_MARK_CIRCLE
+STC_MARK_ROUNDRECT = _stc.STC_MARK_ROUNDRECT
+STC_MARK_ARROW = _stc.STC_MARK_ARROW
+STC_MARK_SMALLRECT = _stc.STC_MARK_SMALLRECT
+STC_MARK_SHORTARROW = _stc.STC_MARK_SHORTARROW
+STC_MARK_EMPTY = _stc.STC_MARK_EMPTY
+STC_MARK_ARROWDOWN = _stc.STC_MARK_ARROWDOWN
+STC_MARK_MINUS = _stc.STC_MARK_MINUS
+STC_MARK_PLUS = _stc.STC_MARK_PLUS
+STC_MARK_VLINE = _stc.STC_MARK_VLINE
+STC_MARK_LCORNER = _stc.STC_MARK_LCORNER
+STC_MARK_TCORNER = _stc.STC_MARK_TCORNER
+STC_MARK_BOXPLUS = _stc.STC_MARK_BOXPLUS
+STC_MARK_BOXPLUSCONNECTED = _stc.STC_MARK_BOXPLUSCONNECTED
+STC_MARK_BOXMINUS = _stc.STC_MARK_BOXMINUS
+STC_MARK_BOXMINUSCONNECTED = _stc.STC_MARK_BOXMINUSCONNECTED
+STC_MARK_LCORNERCURVE = _stc.STC_MARK_LCORNERCURVE
+STC_MARK_TCORNERCURVE = _stc.STC_MARK_TCORNERCURVE
+STC_MARK_CIRCLEPLUS = _stc.STC_MARK_CIRCLEPLUS
+STC_MARK_CIRCLEPLUSCONNECTED = _stc.STC_MARK_CIRCLEPLUSCONNECTED
+STC_MARK_CIRCLEMINUS = _stc.STC_MARK_CIRCLEMINUS
+STC_MARK_CIRCLEMINUSCONNECTED = _stc.STC_MARK_CIRCLEMINUSCONNECTED
+STC_MARK_BACKGROUND = _stc.STC_MARK_BACKGROUND
+STC_MARK_DOTDOTDOT = _stc.STC_MARK_DOTDOTDOT
+STC_MARK_ARROWS = _stc.STC_MARK_ARROWS
+STC_MARK_PIXMAP = _stc.STC_MARK_PIXMAP
+STC_MARK_FULLRECT = _stc.STC_MARK_FULLRECT
+STC_MARK_LEFTRECT = _stc.STC_MARK_LEFTRECT
+STC_MARK_AVAILABLE = _stc.STC_MARK_AVAILABLE
+STC_MARK_UNDERLINE = _stc.STC_MARK_UNDERLINE
+STC_MARK_RGBAIMAGE = _stc.STC_MARK_RGBAIMAGE
+STC_MARK_CHARACTER = _stc.STC_MARK_CHARACTER
+STC_MARKNUM_FOLDEREND = _stc.STC_MARKNUM_FOLDEREND
+STC_MARKNUM_FOLDEROPENMID = _stc.STC_MARKNUM_FOLDEROPENMID
+STC_MARKNUM_FOLDERMIDTAIL = _stc.STC_MARKNUM_FOLDERMIDTAIL
+STC_MARKNUM_FOLDERTAIL = _stc.STC_MARKNUM_FOLDERTAIL
+STC_MARKNUM_FOLDERSUB = _stc.STC_MARKNUM_FOLDERSUB
+STC_MARKNUM_FOLDER = _stc.STC_MARKNUM_FOLDER
+STC_MARKNUM_FOLDEROPEN = _stc.STC_MARKNUM_FOLDEROPEN
+STC_MASK_FOLDERS = _stc.STC_MASK_FOLDERS
+STC_MARGIN_SYMBOL = _stc.STC_MARGIN_SYMBOL
+STC_MARGIN_NUMBER = _stc.STC_MARGIN_NUMBER
+STC_MARGIN_BACK = _stc.STC_MARGIN_BACK
+STC_MARGIN_FORE = _stc.STC_MARGIN_FORE
+STC_MARGIN_TEXT = _stc.STC_MARGIN_TEXT
+STC_MARGIN_RTEXT = _stc.STC_MARGIN_RTEXT
+STC_STYLE_DEFAULT = _stc.STC_STYLE_DEFAULT
+STC_STYLE_LINENUMBER = _stc.STC_STYLE_LINENUMBER
+STC_STYLE_BRACELIGHT = _stc.STC_STYLE_BRACELIGHT
+STC_STYLE_BRACEBAD = _stc.STC_STYLE_BRACEBAD
+STC_STYLE_CONTROLCHAR = _stc.STC_STYLE_CONTROLCHAR
+STC_STYLE_INDENTGUIDE = _stc.STC_STYLE_INDENTGUIDE
+STC_STYLE_CALLTIP = _stc.STC_STYLE_CALLTIP
+STC_STYLE_LASTPREDEFINED = _stc.STC_STYLE_LASTPREDEFINED
+STC_STYLE_MAX = _stc.STC_STYLE_MAX
+STC_CHARSET_ANSI = _stc.STC_CHARSET_ANSI
+STC_CHARSET_DEFAULT = _stc.STC_CHARSET_DEFAULT
+STC_CHARSET_BALTIC = _stc.STC_CHARSET_BALTIC
+STC_CHARSET_CHINESEBIG5 = _stc.STC_CHARSET_CHINESEBIG5
+STC_CHARSET_EASTEUROPE = _stc.STC_CHARSET_EASTEUROPE
+STC_CHARSET_GB2312 = _stc.STC_CHARSET_GB2312
+STC_CHARSET_GREEK = _stc.STC_CHARSET_GREEK
+STC_CHARSET_HANGUL = _stc.STC_CHARSET_HANGUL
+STC_CHARSET_MAC = _stc.STC_CHARSET_MAC
+STC_CHARSET_OEM = _stc.STC_CHARSET_OEM
+STC_CHARSET_RUSSIAN = _stc.STC_CHARSET_RUSSIAN
+STC_CHARSET_CYRILLIC = _stc.STC_CHARSET_CYRILLIC
+STC_CHARSET_SHIFTJIS = _stc.STC_CHARSET_SHIFTJIS
+STC_CHARSET_SYMBOL = _stc.STC_CHARSET_SYMBOL
+STC_CHARSET_TURKISH = _stc.STC_CHARSET_TURKISH
+STC_CHARSET_JOHAB = _stc.STC_CHARSET_JOHAB
+STC_CHARSET_HEBREW = _stc.STC_CHARSET_HEBREW
+STC_CHARSET_ARABIC = _stc.STC_CHARSET_ARABIC
+STC_CHARSET_VIETNAMESE = _stc.STC_CHARSET_VIETNAMESE
+STC_CHARSET_THAI = _stc.STC_CHARSET_THAI
+STC_CHARSET_8859_15 = _stc.STC_CHARSET_8859_15
+STC_CASE_MIXED = _stc.STC_CASE_MIXED
+STC_CASE_UPPER = _stc.STC_CASE_UPPER
+STC_CASE_LOWER = _stc.STC_CASE_LOWER
+STC_FONT_SIZE_MULTIPLIER = _stc.STC_FONT_SIZE_MULTIPLIER
+STC_WEIGHT_NORMAL = _stc.STC_WEIGHT_NORMAL
+STC_WEIGHT_SEMIBOLD = _stc.STC_WEIGHT_SEMIBOLD
+STC_WEIGHT_BOLD = _stc.STC_WEIGHT_BOLD
+STC_INDIC_PLAIN = _stc.STC_INDIC_PLAIN
+STC_INDIC_SQUIGGLE = _stc.STC_INDIC_SQUIGGLE
+STC_INDIC_TT = _stc.STC_INDIC_TT
+STC_INDIC_DIAGONAL = _stc.STC_INDIC_DIAGONAL
+STC_INDIC_STRIKE = _stc.STC_INDIC_STRIKE
+STC_INDIC_HIDDEN = _stc.STC_INDIC_HIDDEN
+STC_INDIC_BOX = _stc.STC_INDIC_BOX
+STC_INDIC_ROUNDBOX = _stc.STC_INDIC_ROUNDBOX
+STC_INDIC_STRAIGHTBOX = _stc.STC_INDIC_STRAIGHTBOX
+STC_INDIC_DASH = _stc.STC_INDIC_DASH
+STC_INDIC_DOTS = _stc.STC_INDIC_DOTS
+STC_INDIC_SQUIGGLELOW = _stc.STC_INDIC_SQUIGGLELOW
+STC_INDIC_DOTBOX = _stc.STC_INDIC_DOTBOX
+STC_INDIC_MAX = _stc.STC_INDIC_MAX
+STC_INDIC_CONTAINER = _stc.STC_INDIC_CONTAINER
+STC_INDIC0_MASK = _stc.STC_INDIC0_MASK
+STC_INDIC1_MASK = _stc.STC_INDIC1_MASK
+STC_INDIC2_MASK = _stc.STC_INDIC2_MASK
+STC_INDICS_MASK = _stc.STC_INDICS_MASK
+STC_IV_NONE = _stc.STC_IV_NONE
+STC_IV_REAL = _stc.STC_IV_REAL
+STC_IV_LOOKFORWARD = _stc.STC_IV_LOOKFORWARD
+STC_IV_LOOKBOTH = _stc.STC_IV_LOOKBOTH
+STC_PRINT_NORMAL = _stc.STC_PRINT_NORMAL
+STC_PRINT_INVERTLIGHT = _stc.STC_PRINT_INVERTLIGHT
+STC_PRINT_BLACKONWHITE = _stc.STC_PRINT_BLACKONWHITE
+STC_PRINT_COLOURONWHITE = _stc.STC_PRINT_COLOURONWHITE
+STC_PRINT_COLOURONWHITEDEFAULTBG = _stc.STC_PRINT_COLOURONWHITEDEFAULTBG
+STC_FIND_WHOLEWORD = _stc.STC_FIND_WHOLEWORD
+STC_FIND_MATCHCASE = _stc.STC_FIND_MATCHCASE
+STC_FIND_WORDSTART = _stc.STC_FIND_WORDSTART
+STC_FIND_REGEXP = _stc.STC_FIND_REGEXP
+STC_FIND_POSIX = _stc.STC_FIND_POSIX
+STC_FOLDLEVELBASE = _stc.STC_FOLDLEVELBASE
+STC_FOLDLEVELWHITEFLAG = _stc.STC_FOLDLEVELWHITEFLAG
+STC_FOLDLEVELHEADERFLAG = _stc.STC_FOLDLEVELHEADERFLAG
+STC_FOLDLEVELNUMBERMASK = _stc.STC_FOLDLEVELNUMBERMASK
+STC_FOLDFLAG_LINEBEFORE_EXPANDED = _stc.STC_FOLDFLAG_LINEBEFORE_EXPANDED
+STC_FOLDFLAG_LINEBEFORE_CONTRACTED = _stc.STC_FOLDFLAG_LINEBEFORE_CONTRACTED
+STC_FOLDFLAG_LINEAFTER_EXPANDED = _stc.STC_FOLDFLAG_LINEAFTER_EXPANDED
+STC_FOLDFLAG_LINEAFTER_CONTRACTED = _stc.STC_FOLDFLAG_LINEAFTER_CONTRACTED
+STC_FOLDFLAG_LEVELNUMBERS = _stc.STC_FOLDFLAG_LEVELNUMBERS
+STC_TIME_FOREVER = _stc.STC_TIME_FOREVER
+STC_WRAP_NONE = _stc.STC_WRAP_NONE
+STC_WRAP_WORD = _stc.STC_WRAP_WORD
+STC_WRAP_CHAR = _stc.STC_WRAP_CHAR
+STC_WRAPVISUALFLAG_NONE = _stc.STC_WRAPVISUALFLAG_NONE
+STC_WRAPVISUALFLAG_END = _stc.STC_WRAPVISUALFLAG_END
+STC_WRAPVISUALFLAG_START = _stc.STC_WRAPVISUALFLAG_START
+STC_WRAPVISUALFLAG_MARGIN = _stc.STC_WRAPVISUALFLAG_MARGIN
+STC_WRAPVISUALFLAGLOC_DEFAULT = _stc.STC_WRAPVISUALFLAGLOC_DEFAULT
+STC_WRAPVISUALFLAGLOC_END_BY_TEXT = _stc.STC_WRAPVISUALFLAGLOC_END_BY_TEXT
+STC_WRAPVISUALFLAGLOC_START_BY_TEXT = _stc.STC_WRAPVISUALFLAGLOC_START_BY_TEXT
+STC_WRAPINDENT_FIXED = _stc.STC_WRAPINDENT_FIXED
+STC_WRAPINDENT_SAME = _stc.STC_WRAPINDENT_SAME
+STC_WRAPINDENT_INDENT = _stc.STC_WRAPINDENT_INDENT
+STC_CACHE_NONE = _stc.STC_CACHE_NONE
+STC_CACHE_CARET = _stc.STC_CACHE_CARET
+STC_CACHE_PAGE = _stc.STC_CACHE_PAGE
+STC_CACHE_DOCUMENT = _stc.STC_CACHE_DOCUMENT
+STC_EFF_QUALITY_MASK = _stc.STC_EFF_QUALITY_MASK
+STC_EFF_QUALITY_DEFAULT = _stc.STC_EFF_QUALITY_DEFAULT
+STC_EFF_QUALITY_NON_ANTIALIASED = _stc.STC_EFF_QUALITY_NON_ANTIALIASED
+STC_EFF_QUALITY_ANTIALIASED = _stc.STC_EFF_QUALITY_ANTIALIASED
+STC_EFF_QUALITY_LCD_OPTIMIZED = _stc.STC_EFF_QUALITY_LCD_OPTIMIZED
+STC_MULTIPASTE_ONCE = _stc.STC_MULTIPASTE_ONCE
+STC_MULTIPASTE_EACH = _stc.STC_MULTIPASTE_EACH
+STC_EDGE_NONE = _stc.STC_EDGE_NONE
+STC_EDGE_LINE = _stc.STC_EDGE_LINE
+STC_EDGE_BACKGROUND = _stc.STC_EDGE_BACKGROUND
+STC_STATUS_OK = _stc.STC_STATUS_OK
+STC_STATUS_FAILURE = _stc.STC_STATUS_FAILURE
+STC_STATUS_BADALLOC = _stc.STC_STATUS_BADALLOC
+STC_CURSORNORMAL = _stc.STC_CURSORNORMAL
+STC_CURSORARROW = _stc.STC_CURSORARROW
+STC_CURSORWAIT = _stc.STC_CURSORWAIT
+STC_CURSORREVERSEARROW = _stc.STC_CURSORREVERSEARROW
+STC_VISIBLE_SLOP = _stc.STC_VISIBLE_SLOP
+STC_VISIBLE_STRICT = _stc.STC_VISIBLE_STRICT
+STC_CARET_SLOP = _stc.STC_CARET_SLOP
+STC_CARET_STRICT = _stc.STC_CARET_STRICT
+STC_CARET_JUMPS = _stc.STC_CARET_JUMPS
+STC_CARET_EVEN = _stc.STC_CARET_EVEN
+STC_SEL_STREAM = _stc.STC_SEL_STREAM
+STC_SEL_RECTANGLE = _stc.STC_SEL_RECTANGLE
+STC_SEL_LINES = _stc.STC_SEL_LINES
+STC_SEL_THIN = _stc.STC_SEL_THIN
+STC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE = _stc.STC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE
+STC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE = _stc.STC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE
+STC_CARETSTICKY_OFF = _stc.STC_CARETSTICKY_OFF
+STC_CARETSTICKY_ON = _stc.STC_CARETSTICKY_ON
+STC_CARETSTICKY_WHITESPACE = _stc.STC_CARETSTICKY_WHITESPACE
+STC_ALPHA_TRANSPARENT = _stc.STC_ALPHA_TRANSPARENT
+STC_ALPHA_OPAQUE = _stc.STC_ALPHA_OPAQUE
+STC_ALPHA_NOALPHA = _stc.STC_ALPHA_NOALPHA
+STC_CARETSTYLE_INVISIBLE = _stc.STC_CARETSTYLE_INVISIBLE
+STC_CARETSTYLE_LINE = _stc.STC_CARETSTYLE_LINE
+STC_CARETSTYLE_BLOCK = _stc.STC_CARETSTYLE_BLOCK
+STC_MARGINOPTION_NONE = _stc.STC_MARGINOPTION_NONE
+STC_MARGINOPTION_SUBLINESELECT = _stc.STC_MARGINOPTION_SUBLINESELECT
+STC_ANNOTATION_HIDDEN = _stc.STC_ANNOTATION_HIDDEN
+STC_ANNOTATION_STANDARD = _stc.STC_ANNOTATION_STANDARD
+STC_ANNOTATION_BOXED = _stc.STC_ANNOTATION_BOXED
+STC_UNDO_MAY_COALESCE = _stc.STC_UNDO_MAY_COALESCE
+STC_SCVS_NONE = _stc.STC_SCVS_NONE
+STC_SCVS_RECTANGULARSELECTION = _stc.STC_SCVS_RECTANGULARSELECTION
+STC_SCVS_USERACCESSIBLE = _stc.STC_SCVS_USERACCESSIBLE
+STC_TECHNOLOGY_DEFAULT = _stc.STC_TECHNOLOGY_DEFAULT
+STC_TECHNOLOGY_DIRECTWRITE = _stc.STC_TECHNOLOGY_DIRECTWRITE
+STC_KEYWORDSET_MAX = _stc.STC_KEYWORDSET_MAX
+STC_TYPE_BOOLEAN = _stc.STC_TYPE_BOOLEAN
+STC_TYPE_INTEGER = _stc.STC_TYPE_INTEGER
+STC_TYPE_STRING = _stc.STC_TYPE_STRING
+STC_MOD_INSERTTEXT = _stc.STC_MOD_INSERTTEXT
+STC_MOD_DELETETEXT = _stc.STC_MOD_DELETETEXT
+STC_MOD_CHANGESTYLE = _stc.STC_MOD_CHANGESTYLE
+STC_MOD_CHANGEFOLD = _stc.STC_MOD_CHANGEFOLD
+STC_PERFORMED_USER = _stc.STC_PERFORMED_USER
+STC_PERFORMED_UNDO = _stc.STC_PERFORMED_UNDO
+STC_PERFORMED_REDO = _stc.STC_PERFORMED_REDO
+STC_MULTISTEPUNDOREDO = _stc.STC_MULTISTEPUNDOREDO
+STC_LASTSTEPINUNDOREDO = _stc.STC_LASTSTEPINUNDOREDO
+STC_MOD_CHANGEMARKER = _stc.STC_MOD_CHANGEMARKER
+STC_MOD_BEFOREINSERT = _stc.STC_MOD_BEFOREINSERT
+STC_MOD_BEFOREDELETE = _stc.STC_MOD_BEFOREDELETE
+STC_MULTILINEUNDOREDO = _stc.STC_MULTILINEUNDOREDO
+STC_STARTACTION = _stc.STC_STARTACTION
+STC_MOD_CHANGEINDICATOR = _stc.STC_MOD_CHANGEINDICATOR
+STC_MOD_CHANGELINESTATE = _stc.STC_MOD_CHANGELINESTATE
+STC_MOD_CHANGEMARGIN = _stc.STC_MOD_CHANGEMARGIN
+STC_MOD_CHANGEANNOTATION = _stc.STC_MOD_CHANGEANNOTATION
+STC_MOD_CONTAINER = _stc.STC_MOD_CONTAINER
+STC_MOD_LEXERSTATE = _stc.STC_MOD_LEXERSTATE
+STC_MODEVENTMASKALL = _stc.STC_MODEVENTMASKALL
+STC_UPDATE_CONTENT = _stc.STC_UPDATE_CONTENT
+STC_UPDATE_SELECTION = _stc.STC_UPDATE_SELECTION
+STC_UPDATE_V_SCROLL = _stc.STC_UPDATE_V_SCROLL
+STC_UPDATE_H_SCROLL = _stc.STC_UPDATE_H_SCROLL
+STC_KEY_DOWN = _stc.STC_KEY_DOWN
+STC_KEY_UP = _stc.STC_KEY_UP
+STC_KEY_LEFT = _stc.STC_KEY_LEFT
+STC_KEY_RIGHT = _stc.STC_KEY_RIGHT
+STC_KEY_HOME = _stc.STC_KEY_HOME
+STC_KEY_END = _stc.STC_KEY_END
+STC_KEY_PRIOR = _stc.STC_KEY_PRIOR
+STC_KEY_NEXT = _stc.STC_KEY_NEXT
+STC_KEY_DELETE = _stc.STC_KEY_DELETE
+STC_KEY_INSERT = _stc.STC_KEY_INSERT
+STC_KEY_ESCAPE = _stc.STC_KEY_ESCAPE
+STC_KEY_BACK = _stc.STC_KEY_BACK
+STC_KEY_TAB = _stc.STC_KEY_TAB
+STC_KEY_RETURN = _stc.STC_KEY_RETURN
+STC_KEY_ADD = _stc.STC_KEY_ADD
+STC_KEY_SUBTRACT = _stc.STC_KEY_SUBTRACT
+STC_KEY_DIVIDE = _stc.STC_KEY_DIVIDE
+STC_KEY_WIN = _stc.STC_KEY_WIN
+STC_KEY_RWIN = _stc.STC_KEY_RWIN
+STC_KEY_MENU = _stc.STC_KEY_MENU
+STC_SCMOD_NORM = _stc.STC_SCMOD_NORM
+STC_SCMOD_SHIFT = _stc.STC_SCMOD_SHIFT
+STC_SCMOD_CTRL = _stc.STC_SCMOD_CTRL
+STC_SCMOD_ALT = _stc.STC_SCMOD_ALT
+STC_SCMOD_SUPER = _stc.STC_SCMOD_SUPER
+STC_SCMOD_META = _stc.STC_SCMOD_META
+STC_LEX_CONTAINER = _stc.STC_LEX_CONTAINER
+STC_LEX_NULL = _stc.STC_LEX_NULL
+STC_LEX_PYTHON = _stc.STC_LEX_PYTHON
+STC_LEX_CPP = _stc.STC_LEX_CPP
+STC_LEX_HTML = _stc.STC_LEX_HTML
+STC_LEX_XML = _stc.STC_LEX_XML
+STC_LEX_PERL = _stc.STC_LEX_PERL
+STC_LEX_SQL = _stc.STC_LEX_SQL
+STC_LEX_VB = _stc.STC_LEX_VB
+STC_LEX_PROPERTIES = _stc.STC_LEX_PROPERTIES
+STC_LEX_ERRORLIST = _stc.STC_LEX_ERRORLIST
+STC_LEX_MAKEFILE = _stc.STC_LEX_MAKEFILE
+STC_LEX_BATCH = _stc.STC_LEX_BATCH
+STC_LEX_XCODE = _stc.STC_LEX_XCODE
+STC_LEX_LATEX = _stc.STC_LEX_LATEX
+STC_LEX_LUA = _stc.STC_LEX_LUA
+STC_LEX_DIFF = _stc.STC_LEX_DIFF
+STC_LEX_CONF = _stc.STC_LEX_CONF
+STC_LEX_PASCAL = _stc.STC_LEX_PASCAL
+STC_LEX_AVE = _stc.STC_LEX_AVE
+STC_LEX_ADA = _stc.STC_LEX_ADA
+STC_LEX_LISP = _stc.STC_LEX_LISP
+STC_LEX_RUBY = _stc.STC_LEX_RUBY
+STC_LEX_EIFFEL = _stc.STC_LEX_EIFFEL
+STC_LEX_EIFFELKW = _stc.STC_LEX_EIFFELKW
+STC_LEX_TCL = _stc.STC_LEX_TCL
+STC_LEX_NNCRONTAB = _stc.STC_LEX_NNCRONTAB
+STC_LEX_BULLANT = _stc.STC_LEX_BULLANT
+STC_LEX_VBSCRIPT = _stc.STC_LEX_VBSCRIPT
+STC_LEX_BAAN = _stc.STC_LEX_BAAN
+STC_LEX_MATLAB = _stc.STC_LEX_MATLAB
+STC_LEX_SCRIPTOL = _stc.STC_LEX_SCRIPTOL
+STC_LEX_ASM = _stc.STC_LEX_ASM
+STC_LEX_CPPNOCASE = _stc.STC_LEX_CPPNOCASE
+STC_LEX_FORTRAN = _stc.STC_LEX_FORTRAN
+STC_LEX_F77 = _stc.STC_LEX_F77
+STC_LEX_CSS = _stc.STC_LEX_CSS
+STC_LEX_POV = _stc.STC_LEX_POV
+STC_LEX_LOUT = _stc.STC_LEX_LOUT
+STC_LEX_ESCRIPT = _stc.STC_LEX_ESCRIPT
+STC_LEX_PS = _stc.STC_LEX_PS
+STC_LEX_NSIS = _stc.STC_LEX_NSIS
+STC_LEX_MMIXAL = _stc.STC_LEX_MMIXAL
+STC_LEX_CLW = _stc.STC_LEX_CLW
+STC_LEX_CLWNOCASE = _stc.STC_LEX_CLWNOCASE
+STC_LEX_LOT = _stc.STC_LEX_LOT
+STC_LEX_YAML = _stc.STC_LEX_YAML
+STC_LEX_TEX = _stc.STC_LEX_TEX
+STC_LEX_METAPOST = _stc.STC_LEX_METAPOST
+STC_LEX_POWERBASIC = _stc.STC_LEX_POWERBASIC
+STC_LEX_FORTH = _stc.STC_LEX_FORTH
+STC_LEX_ERLANG = _stc.STC_LEX_ERLANG
+STC_LEX_OCTAVE = _stc.STC_LEX_OCTAVE
+STC_LEX_MSSQL = _stc.STC_LEX_MSSQL
+STC_LEX_VERILOG = _stc.STC_LEX_VERILOG
+STC_LEX_KIX = _stc.STC_LEX_KIX
+STC_LEX_GUI4CLI = _stc.STC_LEX_GUI4CLI
+STC_LEX_SPECMAN = _stc.STC_LEX_SPECMAN
+STC_LEX_AU3 = _stc.STC_LEX_AU3
+STC_LEX_APDL = _stc.STC_LEX_APDL
+STC_LEX_BASH = _stc.STC_LEX_BASH
+STC_LEX_ASN1 = _stc.STC_LEX_ASN1
+STC_LEX_VHDL = _stc.STC_LEX_VHDL
+STC_LEX_CAML = _stc.STC_LEX_CAML
+STC_LEX_BLITZBASIC = _stc.STC_LEX_BLITZBASIC
+STC_LEX_PUREBASIC = _stc.STC_LEX_PUREBASIC
+STC_LEX_HASKELL = _stc.STC_LEX_HASKELL
+STC_LEX_PHPSCRIPT = _stc.STC_LEX_PHPSCRIPT
+STC_LEX_TADS3 = _stc.STC_LEX_TADS3
+STC_LEX_REBOL = _stc.STC_LEX_REBOL
+STC_LEX_SMALLTALK = _stc.STC_LEX_SMALLTALK
+STC_LEX_FLAGSHIP = _stc.STC_LEX_FLAGSHIP
+STC_LEX_CSOUND = _stc.STC_LEX_CSOUND
+STC_LEX_FREEBASIC = _stc.STC_LEX_FREEBASIC
+STC_LEX_INNOSETUP = _stc.STC_LEX_INNOSETUP
+STC_LEX_OPAL = _stc.STC_LEX_OPAL
+STC_LEX_SPICE = _stc.STC_LEX_SPICE
+STC_LEX_D = _stc.STC_LEX_D
+STC_LEX_CMAKE = _stc.STC_LEX_CMAKE
+STC_LEX_GAP = _stc.STC_LEX_GAP
+STC_LEX_PLM = _stc.STC_LEX_PLM
+STC_LEX_PROGRESS = _stc.STC_LEX_PROGRESS
+STC_LEX_ABAQUS = _stc.STC_LEX_ABAQUS
+STC_LEX_ASYMPTOTE = _stc.STC_LEX_ASYMPTOTE
+STC_LEX_R = _stc.STC_LEX_R
+STC_LEX_MAGIK = _stc.STC_LEX_MAGIK
+STC_LEX_POWERSHELL = _stc.STC_LEX_POWERSHELL
+STC_LEX_MYSQL = _stc.STC_LEX_MYSQL
+STC_LEX_PO = _stc.STC_LEX_PO
+STC_LEX_TAL = _stc.STC_LEX_TAL
+STC_LEX_COBOL = _stc.STC_LEX_COBOL
+STC_LEX_TACL = _stc.STC_LEX_TACL
+STC_LEX_SORCUS = _stc.STC_LEX_SORCUS
+STC_LEX_POWERPRO = _stc.STC_LEX_POWERPRO
+STC_LEX_NIMROD = _stc.STC_LEX_NIMROD
+STC_LEX_SML = _stc.STC_LEX_SML
+STC_LEX_MARKDOWN = _stc.STC_LEX_MARKDOWN
+STC_LEX_TXT2TAGS = _stc.STC_LEX_TXT2TAGS
+STC_LEX_A68K = _stc.STC_LEX_A68K
+STC_LEX_MODULA = _stc.STC_LEX_MODULA
+STC_LEX_COFFEESCRIPT = _stc.STC_LEX_COFFEESCRIPT
+STC_LEX_TCMD = _stc.STC_LEX_TCMD
+STC_LEX_AVS = _stc.STC_LEX_AVS
+STC_LEX_ECL = _stc.STC_LEX_ECL
+STC_LEX_OSCRIPT = _stc.STC_LEX_OSCRIPT
+STC_LEX_VISUALPROLOG = _stc.STC_LEX_VISUALPROLOG
+STC_LEX_AUTOMATIC = _stc.STC_LEX_AUTOMATIC
+STC_P_DEFAULT = _stc.STC_P_DEFAULT
+STC_P_COMMENTLINE = _stc.STC_P_COMMENTLINE
+STC_P_NUMBER = _stc.STC_P_NUMBER
+STC_P_STRING = _stc.STC_P_STRING
+STC_P_CHARACTER = _stc.STC_P_CHARACTER
+STC_P_WORD = _stc.STC_P_WORD
+STC_P_TRIPLE = _stc.STC_P_TRIPLE
+STC_P_TRIPLEDOUBLE = _stc.STC_P_TRIPLEDOUBLE
+STC_P_CLASSNAME = _stc.STC_P_CLASSNAME
+STC_P_DEFNAME = _stc.STC_P_DEFNAME
+STC_P_OPERATOR = _stc.STC_P_OPERATOR
+STC_P_IDENTIFIER = _stc.STC_P_IDENTIFIER
+STC_P_COMMENTBLOCK = _stc.STC_P_COMMENTBLOCK
+STC_P_STRINGEOL = _stc.STC_P_STRINGEOL
+STC_P_WORD2 = _stc.STC_P_WORD2
+STC_P_DECORATOR = _stc.STC_P_DECORATOR
+STC_C_DEFAULT = _stc.STC_C_DEFAULT
+STC_C_COMMENT = _stc.STC_C_COMMENT
+STC_C_COMMENTLINE = _stc.STC_C_COMMENTLINE
+STC_C_COMMENTDOC = _stc.STC_C_COMMENTDOC
+STC_C_NUMBER = _stc.STC_C_NUMBER
+STC_C_WORD = _stc.STC_C_WORD
+STC_C_STRING = _stc.STC_C_STRING
+STC_C_CHARACTER = _stc.STC_C_CHARACTER
+STC_C_UUID = _stc.STC_C_UUID
+STC_C_PREPROCESSOR = _stc.STC_C_PREPROCESSOR
+STC_C_OPERATOR = _stc.STC_C_OPERATOR
+STC_C_IDENTIFIER = _stc.STC_C_IDENTIFIER
+STC_C_STRINGEOL = _stc.STC_C_STRINGEOL
+STC_C_VERBATIM = _stc.STC_C_VERBATIM
+STC_C_REGEX = _stc.STC_C_REGEX
+STC_C_COMMENTLINEDOC = _stc.STC_C_COMMENTLINEDOC
+STC_C_WORD2 = _stc.STC_C_WORD2
+STC_C_COMMENTDOCKEYWORD = _stc.STC_C_COMMENTDOCKEYWORD
+STC_C_COMMENTDOCKEYWORDERROR = _stc.STC_C_COMMENTDOCKEYWORDERROR
+STC_C_GLOBALCLASS = _stc.STC_C_GLOBALCLASS
+STC_C_STRINGRAW = _stc.STC_C_STRINGRAW
+STC_C_TRIPLEVERBATIM = _stc.STC_C_TRIPLEVERBATIM
+STC_C_HASHQUOTEDSTRING = _stc.STC_C_HASHQUOTEDSTRING
+STC_C_PREPROCESSORCOMMENT = _stc.STC_C_PREPROCESSORCOMMENT
+STC_D_DEFAULT = _stc.STC_D_DEFAULT
+STC_D_COMMENT = _stc.STC_D_COMMENT
+STC_D_COMMENTLINE = _stc.STC_D_COMMENTLINE
+STC_D_COMMENTDOC = _stc.STC_D_COMMENTDOC
+STC_D_COMMENTNESTED = _stc.STC_D_COMMENTNESTED
+STC_D_NUMBER = _stc.STC_D_NUMBER
+STC_D_WORD = _stc.STC_D_WORD
+STC_D_WORD2 = _stc.STC_D_WORD2
+STC_D_WORD3 = _stc.STC_D_WORD3
+STC_D_TYPEDEF = _stc.STC_D_TYPEDEF
+STC_D_STRING = _stc.STC_D_STRING
+STC_D_STRINGEOL = _stc.STC_D_STRINGEOL
+STC_D_CHARACTER = _stc.STC_D_CHARACTER
+STC_D_OPERATOR = _stc.STC_D_OPERATOR
+STC_D_IDENTIFIER = _stc.STC_D_IDENTIFIER
+STC_D_COMMENTLINEDOC = _stc.STC_D_COMMENTLINEDOC
+STC_D_COMMENTDOCKEYWORD = _stc.STC_D_COMMENTDOCKEYWORD
+STC_D_COMMENTDOCKEYWORDERROR = _stc.STC_D_COMMENTDOCKEYWORDERROR
+STC_D_STRINGB = _stc.STC_D_STRINGB
+STC_D_STRINGR = _stc.STC_D_STRINGR
+STC_D_WORD5 = _stc.STC_D_WORD5
+STC_D_WORD6 = _stc.STC_D_WORD6
+STC_D_WORD7 = _stc.STC_D_WORD7
+STC_TCL_DEFAULT = _stc.STC_TCL_DEFAULT
+STC_TCL_COMMENT = _stc.STC_TCL_COMMENT
+STC_TCL_COMMENTLINE = _stc.STC_TCL_COMMENTLINE
+STC_TCL_NUMBER = _stc.STC_TCL_NUMBER
+STC_TCL_WORD_IN_QUOTE = _stc.STC_TCL_WORD_IN_QUOTE
+STC_TCL_IN_QUOTE = _stc.STC_TCL_IN_QUOTE
+STC_TCL_OPERATOR = _stc.STC_TCL_OPERATOR
+STC_TCL_IDENTIFIER = _stc.STC_TCL_IDENTIFIER
+STC_TCL_SUBSTITUTION = _stc.STC_TCL_SUBSTITUTION
+STC_TCL_SUB_BRACE = _stc.STC_TCL_SUB_BRACE
+STC_TCL_MODIFIER = _stc.STC_TCL_MODIFIER
+STC_TCL_EXPAND = _stc.STC_TCL_EXPAND
+STC_TCL_WORD = _stc.STC_TCL_WORD
+STC_TCL_WORD2 = _stc.STC_TCL_WORD2
+STC_TCL_WORD3 = _stc.STC_TCL_WORD3
+STC_TCL_WORD4 = _stc.STC_TCL_WORD4
+STC_TCL_WORD5 = _stc.STC_TCL_WORD5
+STC_TCL_WORD6 = _stc.STC_TCL_WORD6
+STC_TCL_WORD7 = _stc.STC_TCL_WORD7
+STC_TCL_WORD8 = _stc.STC_TCL_WORD8
+STC_TCL_COMMENT_BOX = _stc.STC_TCL_COMMENT_BOX
+STC_TCL_BLOCK_COMMENT = _stc.STC_TCL_BLOCK_COMMENT
+STC_H_DEFAULT = _stc.STC_H_DEFAULT
+STC_H_TAG = _stc.STC_H_TAG
+STC_H_TAGUNKNOWN = _stc.STC_H_TAGUNKNOWN
+STC_H_ATTRIBUTE = _stc.STC_H_ATTRIBUTE
+STC_H_ATTRIBUTEUNKNOWN = _stc.STC_H_ATTRIBUTEUNKNOWN
+STC_H_NUMBER = _stc.STC_H_NUMBER
+STC_H_DOUBLESTRING = _stc.STC_H_DOUBLESTRING
+STC_H_SINGLESTRING = _stc.STC_H_SINGLESTRING
+STC_H_OTHER = _stc.STC_H_OTHER
+STC_H_COMMENT = _stc.STC_H_COMMENT
+STC_H_ENTITY = _stc.STC_H_ENTITY
+STC_H_TAGEND = _stc.STC_H_TAGEND
+STC_H_XMLSTART = _stc.STC_H_XMLSTART
+STC_H_XMLEND = _stc.STC_H_XMLEND
+STC_H_SCRIPT = _stc.STC_H_SCRIPT
+STC_H_ASP = _stc.STC_H_ASP
+STC_H_ASPAT = _stc.STC_H_ASPAT
+STC_H_CDATA = _stc.STC_H_CDATA
+STC_H_QUESTION = _stc.STC_H_QUESTION
+STC_H_VALUE = _stc.STC_H_VALUE
+STC_H_XCCOMMENT = _stc.STC_H_XCCOMMENT
+STC_H_SGML_DEFAULT = _stc.STC_H_SGML_DEFAULT
+STC_H_SGML_COMMAND = _stc.STC_H_SGML_COMMAND
+STC_H_SGML_1ST_PARAM = _stc.STC_H_SGML_1ST_PARAM
+STC_H_SGML_DOUBLESTRING = _stc.STC_H_SGML_DOUBLESTRING
+STC_H_SGML_SIMPLESTRING = _stc.STC_H_SGML_SIMPLESTRING
+STC_H_SGML_ERROR = _stc.STC_H_SGML_ERROR
+STC_H_SGML_SPECIAL = _stc.STC_H_SGML_SPECIAL
+STC_H_SGML_ENTITY = _stc.STC_H_SGML_ENTITY
+STC_H_SGML_COMMENT = _stc.STC_H_SGML_COMMENT
+STC_H_SGML_1ST_PARAM_COMMENT = _stc.STC_H_SGML_1ST_PARAM_COMMENT
+STC_H_SGML_BLOCK_DEFAULT = _stc.STC_H_SGML_BLOCK_DEFAULT
+STC_HJ_START = _stc.STC_HJ_START
+STC_HJ_DEFAULT = _stc.STC_HJ_DEFAULT
+STC_HJ_COMMENT = _stc.STC_HJ_COMMENT
+STC_HJ_COMMENTLINE = _stc.STC_HJ_COMMENTLINE
+STC_HJ_COMMENTDOC = _stc.STC_HJ_COMMENTDOC
+STC_HJ_NUMBER = _stc.STC_HJ_NUMBER
+STC_HJ_WORD = _stc.STC_HJ_WORD
+STC_HJ_KEYWORD = _stc.STC_HJ_KEYWORD
+STC_HJ_DOUBLESTRING = _stc.STC_HJ_DOUBLESTRING
+STC_HJ_SINGLESTRING = _stc.STC_HJ_SINGLESTRING
+STC_HJ_SYMBOLS = _stc.STC_HJ_SYMBOLS
+STC_HJ_STRINGEOL = _stc.STC_HJ_STRINGEOL
+STC_HJ_REGEX = _stc.STC_HJ_REGEX
+STC_HJA_START = _stc.STC_HJA_START
+STC_HJA_DEFAULT = _stc.STC_HJA_DEFAULT
+STC_HJA_COMMENT = _stc.STC_HJA_COMMENT
+STC_HJA_COMMENTLINE = _stc.STC_HJA_COMMENTLINE
+STC_HJA_COMMENTDOC = _stc.STC_HJA_COMMENTDOC
+STC_HJA_NUMBER = _stc.STC_HJA_NUMBER
+STC_HJA_WORD = _stc.STC_HJA_WORD
+STC_HJA_KEYWORD = _stc.STC_HJA_KEYWORD
+STC_HJA_DOUBLESTRING = _stc.STC_HJA_DOUBLESTRING
+STC_HJA_SINGLESTRING = _stc.STC_HJA_SINGLESTRING
+STC_HJA_SYMBOLS = _stc.STC_HJA_SYMBOLS
+STC_HJA_STRINGEOL = _stc.STC_HJA_STRINGEOL
+STC_HJA_REGEX = _stc.STC_HJA_REGEX
+STC_HB_START = _stc.STC_HB_START
+STC_HB_DEFAULT = _stc.STC_HB_DEFAULT
+STC_HB_COMMENTLINE = _stc.STC_HB_COMMENTLINE
+STC_HB_NUMBER = _stc.STC_HB_NUMBER
+STC_HB_WORD = _stc.STC_HB_WORD
+STC_HB_STRING = _stc.STC_HB_STRING
+STC_HB_IDENTIFIER = _stc.STC_HB_IDENTIFIER
+STC_HB_STRINGEOL = _stc.STC_HB_STRINGEOL
+STC_HBA_START = _stc.STC_HBA_START
+STC_HBA_DEFAULT = _stc.STC_HBA_DEFAULT
+STC_HBA_COMMENTLINE = _stc.STC_HBA_COMMENTLINE
+STC_HBA_NUMBER = _stc.STC_HBA_NUMBER
+STC_HBA_WORD = _stc.STC_HBA_WORD
+STC_HBA_STRING = _stc.STC_HBA_STRING
+STC_HBA_IDENTIFIER = _stc.STC_HBA_IDENTIFIER
+STC_HBA_STRINGEOL = _stc.STC_HBA_STRINGEOL
+STC_HP_START = _stc.STC_HP_START
+STC_HP_DEFAULT = _stc.STC_HP_DEFAULT
+STC_HP_COMMENTLINE = _stc.STC_HP_COMMENTLINE
+STC_HP_NUMBER = _stc.STC_HP_NUMBER
+STC_HP_STRING = _stc.STC_HP_STRING
+STC_HP_CHARACTER = _stc.STC_HP_CHARACTER
+STC_HP_WORD = _stc.STC_HP_WORD
+STC_HP_TRIPLE = _stc.STC_HP_TRIPLE
+STC_HP_TRIPLEDOUBLE = _stc.STC_HP_TRIPLEDOUBLE
+STC_HP_CLASSNAME = _stc.STC_HP_CLASSNAME
+STC_HP_DEFNAME = _stc.STC_HP_DEFNAME
+STC_HP_OPERATOR = _stc.STC_HP_OPERATOR
+STC_HP_IDENTIFIER = _stc.STC_HP_IDENTIFIER
+STC_HPHP_COMPLEX_VARIABLE = _stc.STC_HPHP_COMPLEX_VARIABLE
+STC_HPA_START = _stc.STC_HPA_START
+STC_HPA_DEFAULT = _stc.STC_HPA_DEFAULT
+STC_HPA_COMMENTLINE = _stc.STC_HPA_COMMENTLINE
+STC_HPA_NUMBER = _stc.STC_HPA_NUMBER
+STC_HPA_STRING = _stc.STC_HPA_STRING
+STC_HPA_CHARACTER = _stc.STC_HPA_CHARACTER
+STC_HPA_WORD = _stc.STC_HPA_WORD
+STC_HPA_TRIPLE = _stc.STC_HPA_TRIPLE
+STC_HPA_TRIPLEDOUBLE = _stc.STC_HPA_TRIPLEDOUBLE
+STC_HPA_CLASSNAME = _stc.STC_HPA_CLASSNAME
+STC_HPA_DEFNAME = _stc.STC_HPA_DEFNAME
+STC_HPA_OPERATOR = _stc.STC_HPA_OPERATOR
+STC_HPA_IDENTIFIER = _stc.STC_HPA_IDENTIFIER
+STC_HPHP_DEFAULT = _stc.STC_HPHP_DEFAULT
+STC_HPHP_HSTRING = _stc.STC_HPHP_HSTRING
+STC_HPHP_SIMPLESTRING = _stc.STC_HPHP_SIMPLESTRING
+STC_HPHP_WORD = _stc.STC_HPHP_WORD
+STC_HPHP_NUMBER = _stc.STC_HPHP_NUMBER
+STC_HPHP_VARIABLE = _stc.STC_HPHP_VARIABLE
+STC_HPHP_COMMENT = _stc.STC_HPHP_COMMENT
+STC_HPHP_COMMENTLINE = _stc.STC_HPHP_COMMENTLINE
+STC_HPHP_HSTRING_VARIABLE = _stc.STC_HPHP_HSTRING_VARIABLE
+STC_HPHP_OPERATOR = _stc.STC_HPHP_OPERATOR
+STC_PL_DEFAULT = _stc.STC_PL_DEFAULT
+STC_PL_ERROR = _stc.STC_PL_ERROR
+STC_PL_COMMENTLINE = _stc.STC_PL_COMMENTLINE
+STC_PL_POD = _stc.STC_PL_POD
+STC_PL_NUMBER = _stc.STC_PL_NUMBER
+STC_PL_WORD = _stc.STC_PL_WORD
+STC_PL_STRING = _stc.STC_PL_STRING
+STC_PL_CHARACTER = _stc.STC_PL_CHARACTER
+STC_PL_PUNCTUATION = _stc.STC_PL_PUNCTUATION
+STC_PL_PREPROCESSOR = _stc.STC_PL_PREPROCESSOR
+STC_PL_OPERATOR = _stc.STC_PL_OPERATOR
+STC_PL_IDENTIFIER = _stc.STC_PL_IDENTIFIER
+STC_PL_SCALAR = _stc.STC_PL_SCALAR
+STC_PL_ARRAY = _stc.STC_PL_ARRAY
+STC_PL_HASH = _stc.STC_PL_HASH
+STC_PL_SYMBOLTABLE = _stc.STC_PL_SYMBOLTABLE
+STC_PL_VARIABLE_INDEXER = _stc.STC_PL_VARIABLE_INDEXER
+STC_PL_REGEX = _stc.STC_PL_REGEX
+STC_PL_REGSUBST = _stc.STC_PL_REGSUBST
+STC_PL_LONGQUOTE = _stc.STC_PL_LONGQUOTE
+STC_PL_BACKTICKS = _stc.STC_PL_BACKTICKS
+STC_PL_DATASECTION = _stc.STC_PL_DATASECTION
+STC_PL_HERE_DELIM = _stc.STC_PL_HERE_DELIM
+STC_PL_HERE_Q = _stc.STC_PL_HERE_Q
+STC_PL_HERE_QQ = _stc.STC_PL_HERE_QQ
+STC_PL_HERE_QX = _stc.STC_PL_HERE_QX
+STC_PL_STRING_Q = _stc.STC_PL_STRING_Q
+STC_PL_STRING_QQ = _stc.STC_PL_STRING_QQ
+STC_PL_STRING_QX = _stc.STC_PL_STRING_QX
+STC_PL_STRING_QR = _stc.STC_PL_STRING_QR
+STC_PL_STRING_QW = _stc.STC_PL_STRING_QW
+STC_PL_POD_VERB = _stc.STC_PL_POD_VERB
+STC_PL_SUB_PROTOTYPE = _stc.STC_PL_SUB_PROTOTYPE
+STC_PL_FORMAT_IDENT = _stc.STC_PL_FORMAT_IDENT
+STC_PL_FORMAT = _stc.STC_PL_FORMAT
+STC_PL_STRING_VAR = _stc.STC_PL_STRING_VAR
+STC_PL_XLAT = _stc.STC_PL_XLAT
+STC_PL_REGEX_VAR = _stc.STC_PL_REGEX_VAR
+STC_PL_REGSUBST_VAR = _stc.STC_PL_REGSUBST_VAR
+STC_PL_BACKTICKS_VAR = _stc.STC_PL_BACKTICKS_VAR
+STC_PL_HERE_QQ_VAR = _stc.STC_PL_HERE_QQ_VAR
+STC_PL_HERE_QX_VAR = _stc.STC_PL_HERE_QX_VAR
+STC_PL_STRING_QQ_VAR = _stc.STC_PL_STRING_QQ_VAR
+STC_PL_STRING_QX_VAR = _stc.STC_PL_STRING_QX_VAR
+STC_PL_STRING_QR_VAR = _stc.STC_PL_STRING_QR_VAR
+STC_RB_DEFAULT = _stc.STC_RB_DEFAULT
+STC_RB_ERROR = _stc.STC_RB_ERROR
+STC_RB_COMMENTLINE = _stc.STC_RB_COMMENTLINE
+STC_RB_POD = _stc.STC_RB_POD
+STC_RB_NUMBER = _stc.STC_RB_NUMBER
+STC_RB_WORD = _stc.STC_RB_WORD
+STC_RB_STRING = _stc.STC_RB_STRING
+STC_RB_CHARACTER = _stc.STC_RB_CHARACTER
+STC_RB_CLASSNAME = _stc.STC_RB_CLASSNAME
+STC_RB_DEFNAME = _stc.STC_RB_DEFNAME
+STC_RB_OPERATOR = _stc.STC_RB_OPERATOR
+STC_RB_IDENTIFIER = _stc.STC_RB_IDENTIFIER
+STC_RB_REGEX = _stc.STC_RB_REGEX
+STC_RB_GLOBAL = _stc.STC_RB_GLOBAL
+STC_RB_SYMBOL = _stc.STC_RB_SYMBOL
+STC_RB_MODULE_NAME = _stc.STC_RB_MODULE_NAME
+STC_RB_INSTANCE_VAR = _stc.STC_RB_INSTANCE_VAR
+STC_RB_CLASS_VAR = _stc.STC_RB_CLASS_VAR
+STC_RB_BACKTICKS = _stc.STC_RB_BACKTICKS
+STC_RB_DATASECTION = _stc.STC_RB_DATASECTION
+STC_RB_HERE_DELIM = _stc.STC_RB_HERE_DELIM
+STC_RB_HERE_Q = _stc.STC_RB_HERE_Q
+STC_RB_HERE_QQ = _stc.STC_RB_HERE_QQ
+STC_RB_HERE_QX = _stc.STC_RB_HERE_QX
+STC_RB_STRING_Q = _stc.STC_RB_STRING_Q
+STC_RB_STRING_QQ = _stc.STC_RB_STRING_QQ
+STC_RB_STRING_QX = _stc.STC_RB_STRING_QX
+STC_RB_STRING_QR = _stc.STC_RB_STRING_QR
+STC_RB_STRING_QW = _stc.STC_RB_STRING_QW
+STC_RB_WORD_DEMOTED = _stc.STC_RB_WORD_DEMOTED
+STC_RB_STDIN = _stc.STC_RB_STDIN
+STC_RB_STDOUT = _stc.STC_RB_STDOUT
+STC_RB_STDERR = _stc.STC_RB_STDERR
+STC_RB_UPPER_BOUND = _stc.STC_RB_UPPER_BOUND
+STC_B_DEFAULT = _stc.STC_B_DEFAULT
+STC_B_COMMENT = _stc.STC_B_COMMENT
+STC_B_NUMBER = _stc.STC_B_NUMBER
+STC_B_KEYWORD = _stc.STC_B_KEYWORD
+STC_B_STRING = _stc.STC_B_STRING
+STC_B_PREPROCESSOR = _stc.STC_B_PREPROCESSOR
+STC_B_OPERATOR = _stc.STC_B_OPERATOR
+STC_B_IDENTIFIER = _stc.STC_B_IDENTIFIER
+STC_B_DATE = _stc.STC_B_DATE
+STC_B_STRINGEOL = _stc.STC_B_STRINGEOL
+STC_B_KEYWORD2 = _stc.STC_B_KEYWORD2
+STC_B_KEYWORD3 = _stc.STC_B_KEYWORD3
+STC_B_KEYWORD4 = _stc.STC_B_KEYWORD4
+STC_B_CONSTANT = _stc.STC_B_CONSTANT
+STC_B_ASM = _stc.STC_B_ASM
+STC_B_LABEL = _stc.STC_B_LABEL
+STC_B_ERROR = _stc.STC_B_ERROR
+STC_B_HEXNUMBER = _stc.STC_B_HEXNUMBER
+STC_B_BINNUMBER = _stc.STC_B_BINNUMBER
+STC_PROPS_DEFAULT = _stc.STC_PROPS_DEFAULT
+STC_PROPS_COMMENT = _stc.STC_PROPS_COMMENT
+STC_PROPS_SECTION = _stc.STC_PROPS_SECTION
+STC_PROPS_ASSIGNMENT = _stc.STC_PROPS_ASSIGNMENT
+STC_PROPS_DEFVAL = _stc.STC_PROPS_DEFVAL
+STC_PROPS_KEY = _stc.STC_PROPS_KEY
+STC_L_DEFAULT = _stc.STC_L_DEFAULT
+STC_L_COMMAND = _stc.STC_L_COMMAND
+STC_L_TAG = _stc.STC_L_TAG
+STC_L_MATH = _stc.STC_L_MATH
+STC_L_COMMENT = _stc.STC_L_COMMENT
+STC_L_TAG2 = _stc.STC_L_TAG2
+STC_L_MATH2 = _stc.STC_L_MATH2
+STC_L_COMMENT2 = _stc.STC_L_COMMENT2
+STC_L_VERBATIM = _stc.STC_L_VERBATIM
+STC_L_SHORTCMD = _stc.STC_L_SHORTCMD
+STC_L_SPECIAL = _stc.STC_L_SPECIAL
+STC_L_CMDOPT = _stc.STC_L_CMDOPT
+STC_L_ERROR = _stc.STC_L_ERROR
+STC_LUA_DEFAULT = _stc.STC_LUA_DEFAULT
+STC_LUA_COMMENT = _stc.STC_LUA_COMMENT
+STC_LUA_COMMENTLINE = _stc.STC_LUA_COMMENTLINE
+STC_LUA_COMMENTDOC = _stc.STC_LUA_COMMENTDOC
+STC_LUA_NUMBER = _stc.STC_LUA_NUMBER
+STC_LUA_WORD = _stc.STC_LUA_WORD
+STC_LUA_STRING = _stc.STC_LUA_STRING
+STC_LUA_CHARACTER = _stc.STC_LUA_CHARACTER
+STC_LUA_LITERALSTRING = _stc.STC_LUA_LITERALSTRING
+STC_LUA_PREPROCESSOR = _stc.STC_LUA_PREPROCESSOR
+STC_LUA_OPERATOR = _stc.STC_LUA_OPERATOR
+STC_LUA_IDENTIFIER = _stc.STC_LUA_IDENTIFIER
+STC_LUA_STRINGEOL = _stc.STC_LUA_STRINGEOL
+STC_LUA_WORD2 = _stc.STC_LUA_WORD2
+STC_LUA_WORD3 = _stc.STC_LUA_WORD3
+STC_LUA_WORD4 = _stc.STC_LUA_WORD4
+STC_LUA_WORD5 = _stc.STC_LUA_WORD5
+STC_LUA_WORD6 = _stc.STC_LUA_WORD6
+STC_LUA_WORD7 = _stc.STC_LUA_WORD7
+STC_LUA_WORD8 = _stc.STC_LUA_WORD8
+STC_LUA_LABEL = _stc.STC_LUA_LABEL
+STC_ERR_DEFAULT = _stc.STC_ERR_DEFAULT
+STC_ERR_PYTHON = _stc.STC_ERR_PYTHON
+STC_ERR_GCC = _stc.STC_ERR_GCC
+STC_ERR_MS = _stc.STC_ERR_MS
+STC_ERR_CMD = _stc.STC_ERR_CMD
+STC_ERR_BORLAND = _stc.STC_ERR_BORLAND
+STC_ERR_PERL = _stc.STC_ERR_PERL
+STC_ERR_NET = _stc.STC_ERR_NET
+STC_ERR_LUA = _stc.STC_ERR_LUA
+STC_ERR_CTAG = _stc.STC_ERR_CTAG
+STC_ERR_DIFF_CHANGED = _stc.STC_ERR_DIFF_CHANGED
+STC_ERR_DIFF_ADDITION = _stc.STC_ERR_DIFF_ADDITION
+STC_ERR_DIFF_DELETION = _stc.STC_ERR_DIFF_DELETION
+STC_ERR_DIFF_MESSAGE = _stc.STC_ERR_DIFF_MESSAGE
+STC_ERR_PHP = _stc.STC_ERR_PHP
+STC_ERR_ELF = _stc.STC_ERR_ELF
+STC_ERR_IFC = _stc.STC_ERR_IFC
+STC_ERR_IFORT = _stc.STC_ERR_IFORT
+STC_ERR_ABSF = _stc.STC_ERR_ABSF
+STC_ERR_TIDY = _stc.STC_ERR_TIDY
+STC_ERR_JAVA_STACK = _stc.STC_ERR_JAVA_STACK
+STC_ERR_VALUE = _stc.STC_ERR_VALUE
+STC_BAT_DEFAULT = _stc.STC_BAT_DEFAULT
+STC_BAT_COMMENT = _stc.STC_BAT_COMMENT
+STC_BAT_WORD = _stc.STC_BAT_WORD
+STC_BAT_LABEL = _stc.STC_BAT_LABEL
+STC_BAT_HIDE = _stc.STC_BAT_HIDE
+STC_BAT_COMMAND = _stc.STC_BAT_COMMAND
+STC_BAT_IDENTIFIER = _stc.STC_BAT_IDENTIFIER
+STC_BAT_OPERATOR = _stc.STC_BAT_OPERATOR
+STC_TCMD_DEFAULT = _stc.STC_TCMD_DEFAULT
+STC_TCMD_COMMENT = _stc.STC_TCMD_COMMENT
+STC_TCMD_WORD = _stc.STC_TCMD_WORD
+STC_TCMD_LABEL = _stc.STC_TCMD_LABEL
+STC_TCMD_HIDE = _stc.STC_TCMD_HIDE
+STC_TCMD_COMMAND = _stc.STC_TCMD_COMMAND
+STC_TCMD_IDENTIFIER = _stc.STC_TCMD_IDENTIFIER
+STC_TCMD_OPERATOR = _stc.STC_TCMD_OPERATOR
+STC_TCMD_ENVIRONMENT = _stc.STC_TCMD_ENVIRONMENT
+STC_TCMD_EXPANSION = _stc.STC_TCMD_EXPANSION
+STC_TCMD_CLABEL = _stc.STC_TCMD_CLABEL
+STC_MAKE_DEFAULT = _stc.STC_MAKE_DEFAULT
+STC_MAKE_COMMENT = _stc.STC_MAKE_COMMENT
+STC_MAKE_PREPROCESSOR = _stc.STC_MAKE_PREPROCESSOR
+STC_MAKE_IDENTIFIER = _stc.STC_MAKE_IDENTIFIER
+STC_MAKE_OPERATOR = _stc.STC_MAKE_OPERATOR
+STC_MAKE_TARGET = _stc.STC_MAKE_TARGET
+STC_MAKE_IDEOL = _stc.STC_MAKE_IDEOL
+STC_DIFF_DEFAULT = _stc.STC_DIFF_DEFAULT
+STC_DIFF_COMMENT = _stc.STC_DIFF_COMMENT
+STC_DIFF_COMMAND = _stc.STC_DIFF_COMMAND
+STC_DIFF_HEADER = _stc.STC_DIFF_HEADER
+STC_DIFF_POSITION = _stc.STC_DIFF_POSITION
+STC_DIFF_DELETED = _stc.STC_DIFF_DELETED
+STC_DIFF_ADDED = _stc.STC_DIFF_ADDED
+STC_DIFF_CHANGED = _stc.STC_DIFF_CHANGED
+STC_CONF_DEFAULT = _stc.STC_CONF_DEFAULT
+STC_CONF_COMMENT = _stc.STC_CONF_COMMENT
+STC_CONF_NUMBER = _stc.STC_CONF_NUMBER
+STC_CONF_IDENTIFIER = _stc.STC_CONF_IDENTIFIER
+STC_CONF_EXTENSION = _stc.STC_CONF_EXTENSION
+STC_CONF_PARAMETER = _stc.STC_CONF_PARAMETER
+STC_CONF_STRING = _stc.STC_CONF_STRING
+STC_CONF_OPERATOR = _stc.STC_CONF_OPERATOR
+STC_CONF_IP = _stc.STC_CONF_IP
+STC_CONF_DIRECTIVE = _stc.STC_CONF_DIRECTIVE
+STC_AVE_DEFAULT = _stc.STC_AVE_DEFAULT
+STC_AVE_COMMENT = _stc.STC_AVE_COMMENT
+STC_AVE_NUMBER = _stc.STC_AVE_NUMBER
+STC_AVE_WORD = _stc.STC_AVE_WORD
+STC_AVE_STRING = _stc.STC_AVE_STRING
+STC_AVE_ENUM = _stc.STC_AVE_ENUM
+STC_AVE_STRINGEOL = _stc.STC_AVE_STRINGEOL
+STC_AVE_IDENTIFIER = _stc.STC_AVE_IDENTIFIER
+STC_AVE_OPERATOR = _stc.STC_AVE_OPERATOR
+STC_AVE_WORD1 = _stc.STC_AVE_WORD1
+STC_AVE_WORD2 = _stc.STC_AVE_WORD2
+STC_AVE_WORD3 = _stc.STC_AVE_WORD3
+STC_AVE_WORD4 = _stc.STC_AVE_WORD4
+STC_AVE_WORD5 = _stc.STC_AVE_WORD5
+STC_AVE_WORD6 = _stc.STC_AVE_WORD6
+STC_ADA_DEFAULT = _stc.STC_ADA_DEFAULT
+STC_ADA_WORD = _stc.STC_ADA_WORD
+STC_ADA_IDENTIFIER = _stc.STC_ADA_IDENTIFIER
+STC_ADA_NUMBER = _stc.STC_ADA_NUMBER
+STC_ADA_DELIMITER = _stc.STC_ADA_DELIMITER
+STC_ADA_CHARACTER = _stc.STC_ADA_CHARACTER
+STC_ADA_CHARACTEREOL = _stc.STC_ADA_CHARACTEREOL
+STC_ADA_STRING = _stc.STC_ADA_STRING
+STC_ADA_STRINGEOL = _stc.STC_ADA_STRINGEOL
+STC_ADA_LABEL = _stc.STC_ADA_LABEL
+STC_ADA_COMMENTLINE = _stc.STC_ADA_COMMENTLINE
+STC_ADA_ILLEGAL = _stc.STC_ADA_ILLEGAL
+STC_BAAN_DEFAULT = _stc.STC_BAAN_DEFAULT
+STC_BAAN_COMMENT = _stc.STC_BAAN_COMMENT
+STC_BAAN_COMMENTDOC = _stc.STC_BAAN_COMMENTDOC
+STC_BAAN_NUMBER = _stc.STC_BAAN_NUMBER
+STC_BAAN_WORD = _stc.STC_BAAN_WORD
+STC_BAAN_STRING = _stc.STC_BAAN_STRING
+STC_BAAN_PREPROCESSOR = _stc.STC_BAAN_PREPROCESSOR
+STC_BAAN_OPERATOR = _stc.STC_BAAN_OPERATOR
+STC_BAAN_IDENTIFIER = _stc.STC_BAAN_IDENTIFIER
+STC_BAAN_STRINGEOL = _stc.STC_BAAN_STRINGEOL
+STC_BAAN_WORD2 = _stc.STC_BAAN_WORD2
+STC_LISP_DEFAULT = _stc.STC_LISP_DEFAULT
+STC_LISP_COMMENT = _stc.STC_LISP_COMMENT
+STC_LISP_NUMBER = _stc.STC_LISP_NUMBER
+STC_LISP_KEYWORD = _stc.STC_LISP_KEYWORD
+STC_LISP_KEYWORD_KW = _stc.STC_LISP_KEYWORD_KW
+STC_LISP_SYMBOL = _stc.STC_LISP_SYMBOL
+STC_LISP_STRING = _stc.STC_LISP_STRING
+STC_LISP_STRINGEOL = _stc.STC_LISP_STRINGEOL
+STC_LISP_IDENTIFIER = _stc.STC_LISP_IDENTIFIER
+STC_LISP_OPERATOR = _stc.STC_LISP_OPERATOR
+STC_LISP_SPECIAL = _stc.STC_LISP_SPECIAL
+STC_LISP_MULTI_COMMENT = _stc.STC_LISP_MULTI_COMMENT
+STC_EIFFEL_DEFAULT = _stc.STC_EIFFEL_DEFAULT
+STC_EIFFEL_COMMENTLINE = _stc.STC_EIFFEL_COMMENTLINE
+STC_EIFFEL_NUMBER = _stc.STC_EIFFEL_NUMBER
+STC_EIFFEL_WORD = _stc.STC_EIFFEL_WORD
+STC_EIFFEL_STRING = _stc.STC_EIFFEL_STRING
+STC_EIFFEL_CHARACTER = _stc.STC_EIFFEL_CHARACTER
+STC_EIFFEL_OPERATOR = _stc.STC_EIFFEL_OPERATOR
+STC_EIFFEL_IDENTIFIER = _stc.STC_EIFFEL_IDENTIFIER
+STC_EIFFEL_STRINGEOL = _stc.STC_EIFFEL_STRINGEOL
+STC_NNCRONTAB_DEFAULT = _stc.STC_NNCRONTAB_DEFAULT
+STC_NNCRONTAB_COMMENT = _stc.STC_NNCRONTAB_COMMENT
+STC_NNCRONTAB_TASK = _stc.STC_NNCRONTAB_TASK
+STC_NNCRONTAB_SECTION = _stc.STC_NNCRONTAB_SECTION
+STC_NNCRONTAB_KEYWORD = _stc.STC_NNCRONTAB_KEYWORD
+STC_NNCRONTAB_MODIFIER = _stc.STC_NNCRONTAB_MODIFIER
+STC_NNCRONTAB_ASTERISK = _stc.STC_NNCRONTAB_ASTERISK
+STC_NNCRONTAB_NUMBER = _stc.STC_NNCRONTAB_NUMBER
+STC_NNCRONTAB_STRING = _stc.STC_NNCRONTAB_STRING
+STC_NNCRONTAB_ENVIRONMENT = _stc.STC_NNCRONTAB_ENVIRONMENT
+STC_NNCRONTAB_IDENTIFIER = _stc.STC_NNCRONTAB_IDENTIFIER
+STC_FORTH_DEFAULT = _stc.STC_FORTH_DEFAULT
+STC_FORTH_COMMENT = _stc.STC_FORTH_COMMENT
+STC_FORTH_COMMENT_ML = _stc.STC_FORTH_COMMENT_ML
+STC_FORTH_IDENTIFIER = _stc.STC_FORTH_IDENTIFIER
+STC_FORTH_CONTROL = _stc.STC_FORTH_CONTROL
+STC_FORTH_KEYWORD = _stc.STC_FORTH_KEYWORD
+STC_FORTH_DEFWORD = _stc.STC_FORTH_DEFWORD
+STC_FORTH_PREWORD1 = _stc.STC_FORTH_PREWORD1
+STC_FORTH_PREWORD2 = _stc.STC_FORTH_PREWORD2
+STC_FORTH_NUMBER = _stc.STC_FORTH_NUMBER
+STC_FORTH_STRING = _stc.STC_FORTH_STRING
+STC_FORTH_LOCALE = _stc.STC_FORTH_LOCALE
+STC_MATLAB_DEFAULT = _stc.STC_MATLAB_DEFAULT
+STC_MATLAB_COMMENT = _stc.STC_MATLAB_COMMENT
+STC_MATLAB_COMMAND = _stc.STC_MATLAB_COMMAND
+STC_MATLAB_NUMBER = _stc.STC_MATLAB_NUMBER
+STC_MATLAB_KEYWORD = _stc.STC_MATLAB_KEYWORD
+STC_MATLAB_STRING = _stc.STC_MATLAB_STRING
+STC_MATLAB_OPERATOR = _stc.STC_MATLAB_OPERATOR
+STC_MATLAB_IDENTIFIER = _stc.STC_MATLAB_IDENTIFIER
+STC_MATLAB_DOUBLEQUOTESTRING = _stc.STC_MATLAB_DOUBLEQUOTESTRING
+STC_SCRIPTOL_DEFAULT = _stc.STC_SCRIPTOL_DEFAULT
+STC_SCRIPTOL_WHITE = _stc.STC_SCRIPTOL_WHITE
+STC_SCRIPTOL_COMMENTLINE = _stc.STC_SCRIPTOL_COMMENTLINE
+STC_SCRIPTOL_PERSISTENT = _stc.STC_SCRIPTOL_PERSISTENT
+STC_SCRIPTOL_CSTYLE = _stc.STC_SCRIPTOL_CSTYLE
+STC_SCRIPTOL_COMMENTBLOCK = _stc.STC_SCRIPTOL_COMMENTBLOCK
+STC_SCRIPTOL_NUMBER = _stc.STC_SCRIPTOL_NUMBER
+STC_SCRIPTOL_STRING = _stc.STC_SCRIPTOL_STRING
+STC_SCRIPTOL_CHARACTER = _stc.STC_SCRIPTOL_CHARACTER
+STC_SCRIPTOL_STRINGEOL = _stc.STC_SCRIPTOL_STRINGEOL
+STC_SCRIPTOL_KEYWORD = _stc.STC_SCRIPTOL_KEYWORD
+STC_SCRIPTOL_OPERATOR = _stc.STC_SCRIPTOL_OPERATOR
+STC_SCRIPTOL_IDENTIFIER = _stc.STC_SCRIPTOL_IDENTIFIER
+STC_SCRIPTOL_TRIPLE = _stc.STC_SCRIPTOL_TRIPLE
+STC_SCRIPTOL_CLASSNAME = _stc.STC_SCRIPTOL_CLASSNAME
+STC_SCRIPTOL_PREPROCESSOR = _stc.STC_SCRIPTOL_PREPROCESSOR
+STC_ASM_DEFAULT = _stc.STC_ASM_DEFAULT
+STC_ASM_COMMENT = _stc.STC_ASM_COMMENT
+STC_ASM_NUMBER = _stc.STC_ASM_NUMBER
+STC_ASM_STRING = _stc.STC_ASM_STRING
+STC_ASM_OPERATOR = _stc.STC_ASM_OPERATOR
+STC_ASM_IDENTIFIER = _stc.STC_ASM_IDENTIFIER
+STC_ASM_CPUINSTRUCTION = _stc.STC_ASM_CPUINSTRUCTION
+STC_ASM_MATHINSTRUCTION = _stc.STC_ASM_MATHINSTRUCTION
+STC_ASM_REGISTER = _stc.STC_ASM_REGISTER
+STC_ASM_DIRECTIVE = _stc.STC_ASM_DIRECTIVE
+STC_ASM_DIRECTIVEOPERAND = _stc.STC_ASM_DIRECTIVEOPERAND
+STC_ASM_COMMENTBLOCK = _stc.STC_ASM_COMMENTBLOCK
+STC_ASM_CHARACTER = _stc.STC_ASM_CHARACTER
+STC_ASM_STRINGEOL = _stc.STC_ASM_STRINGEOL
+STC_ASM_EXTINSTRUCTION = _stc.STC_ASM_EXTINSTRUCTION
+STC_ASM_COMMENTDIRECTIVE = _stc.STC_ASM_COMMENTDIRECTIVE
+STC_F_DEFAULT = _stc.STC_F_DEFAULT
+STC_F_COMMENT = _stc.STC_F_COMMENT
+STC_F_NUMBER = _stc.STC_F_NUMBER
+STC_F_STRING1 = _stc.STC_F_STRING1
+STC_F_STRING2 = _stc.STC_F_STRING2
+STC_F_STRINGEOL = _stc.STC_F_STRINGEOL
+STC_F_OPERATOR = _stc.STC_F_OPERATOR
+STC_F_IDENTIFIER = _stc.STC_F_IDENTIFIER
+STC_F_WORD = _stc.STC_F_WORD
+STC_F_WORD2 = _stc.STC_F_WORD2
+STC_F_WORD3 = _stc.STC_F_WORD3
+STC_F_PREPROCESSOR = _stc.STC_F_PREPROCESSOR
+STC_F_OPERATOR2 = _stc.STC_F_OPERATOR2
+STC_F_LABEL = _stc.STC_F_LABEL
+STC_F_CONTINUATION = _stc.STC_F_CONTINUATION
+STC_CSS_DEFAULT = _stc.STC_CSS_DEFAULT
+STC_CSS_TAG = _stc.STC_CSS_TAG
+STC_CSS_CLASS = _stc.STC_CSS_CLASS
+STC_CSS_PSEUDOCLASS = _stc.STC_CSS_PSEUDOCLASS
+STC_CSS_UNKNOWN_PSEUDOCLASS = _stc.STC_CSS_UNKNOWN_PSEUDOCLASS
+STC_CSS_OPERATOR = _stc.STC_CSS_OPERATOR
+STC_CSS_IDENTIFIER = _stc.STC_CSS_IDENTIFIER
+STC_CSS_UNKNOWN_IDENTIFIER = _stc.STC_CSS_UNKNOWN_IDENTIFIER
+STC_CSS_VALUE = _stc.STC_CSS_VALUE
+STC_CSS_COMMENT = _stc.STC_CSS_COMMENT
+STC_CSS_ID = _stc.STC_CSS_ID
+STC_CSS_IMPORTANT = _stc.STC_CSS_IMPORTANT
+STC_CSS_DIRECTIVE = _stc.STC_CSS_DIRECTIVE
+STC_CSS_DOUBLESTRING = _stc.STC_CSS_DOUBLESTRING
+STC_CSS_SINGLESTRING = _stc.STC_CSS_SINGLESTRING
+STC_CSS_IDENTIFIER2 = _stc.STC_CSS_IDENTIFIER2
+STC_CSS_ATTRIBUTE = _stc.STC_CSS_ATTRIBUTE
+STC_CSS_IDENTIFIER3 = _stc.STC_CSS_IDENTIFIER3
+STC_CSS_PSEUDOELEMENT = _stc.STC_CSS_PSEUDOELEMENT
+STC_CSS_EXTENDED_IDENTIFIER = _stc.STC_CSS_EXTENDED_IDENTIFIER
+STC_CSS_EXTENDED_PSEUDOCLASS = _stc.STC_CSS_EXTENDED_PSEUDOCLASS
+STC_CSS_EXTENDED_PSEUDOELEMENT = _stc.STC_CSS_EXTENDED_PSEUDOELEMENT
+STC_CSS_MEDIA = _stc.STC_CSS_MEDIA
+STC_CSS_VARIABLE = _stc.STC_CSS_VARIABLE
+STC_POV_DEFAULT = _stc.STC_POV_DEFAULT
+STC_POV_COMMENT = _stc.STC_POV_COMMENT
+STC_POV_COMMENTLINE = _stc.STC_POV_COMMENTLINE
+STC_POV_NUMBER = _stc.STC_POV_NUMBER
+STC_POV_OPERATOR = _stc.STC_POV_OPERATOR
+STC_POV_IDENTIFIER = _stc.STC_POV_IDENTIFIER
+STC_POV_STRING = _stc.STC_POV_STRING
+STC_POV_STRINGEOL = _stc.STC_POV_STRINGEOL
+STC_POV_DIRECTIVE = _stc.STC_POV_DIRECTIVE
+STC_POV_BADDIRECTIVE = _stc.STC_POV_BADDIRECTIVE
+STC_POV_WORD2 = _stc.STC_POV_WORD2
+STC_POV_WORD3 = _stc.STC_POV_WORD3
+STC_POV_WORD4 = _stc.STC_POV_WORD4
+STC_POV_WORD5 = _stc.STC_POV_WORD5
+STC_POV_WORD6 = _stc.STC_POV_WORD6
+STC_POV_WORD7 = _stc.STC_POV_WORD7
+STC_POV_WORD8 = _stc.STC_POV_WORD8
+STC_LOUT_DEFAULT = _stc.STC_LOUT_DEFAULT
+STC_LOUT_COMMENT = _stc.STC_LOUT_COMMENT
+STC_LOUT_NUMBER = _stc.STC_LOUT_NUMBER
+STC_LOUT_WORD = _stc.STC_LOUT_WORD
+STC_LOUT_WORD2 = _stc.STC_LOUT_WORD2
+STC_LOUT_WORD3 = _stc.STC_LOUT_WORD3
+STC_LOUT_WORD4 = _stc.STC_LOUT_WORD4
+STC_LOUT_STRING = _stc.STC_LOUT_STRING
+STC_LOUT_OPERATOR = _stc.STC_LOUT_OPERATOR
+STC_LOUT_IDENTIFIER = _stc.STC_LOUT_IDENTIFIER
+STC_LOUT_STRINGEOL = _stc.STC_LOUT_STRINGEOL
+STC_ESCRIPT_DEFAULT = _stc.STC_ESCRIPT_DEFAULT
+STC_ESCRIPT_COMMENT = _stc.STC_ESCRIPT_COMMENT
+STC_ESCRIPT_COMMENTLINE = _stc.STC_ESCRIPT_COMMENTLINE
+STC_ESCRIPT_COMMENTDOC = _stc.STC_ESCRIPT_COMMENTDOC
+STC_ESCRIPT_NUMBER = _stc.STC_ESCRIPT_NUMBER
+STC_ESCRIPT_WORD = _stc.STC_ESCRIPT_WORD
+STC_ESCRIPT_STRING = _stc.STC_ESCRIPT_STRING
+STC_ESCRIPT_OPERATOR = _stc.STC_ESCRIPT_OPERATOR
+STC_ESCRIPT_IDENTIFIER = _stc.STC_ESCRIPT_IDENTIFIER
+STC_ESCRIPT_BRACE = _stc.STC_ESCRIPT_BRACE
+STC_ESCRIPT_WORD2 = _stc.STC_ESCRIPT_WORD2
+STC_ESCRIPT_WORD3 = _stc.STC_ESCRIPT_WORD3
+STC_PS_DEFAULT = _stc.STC_PS_DEFAULT
+STC_PS_COMMENT = _stc.STC_PS_COMMENT
+STC_PS_DSC_COMMENT = _stc.STC_PS_DSC_COMMENT
+STC_PS_DSC_VALUE = _stc.STC_PS_DSC_VALUE
+STC_PS_NUMBER = _stc.STC_PS_NUMBER
+STC_PS_NAME = _stc.STC_PS_NAME
+STC_PS_KEYWORD = _stc.STC_PS_KEYWORD
+STC_PS_LITERAL = _stc.STC_PS_LITERAL
+STC_PS_IMMEVAL = _stc.STC_PS_IMMEVAL
+STC_PS_PAREN_ARRAY = _stc.STC_PS_PAREN_ARRAY
+STC_PS_PAREN_DICT = _stc.STC_PS_PAREN_DICT
+STC_PS_PAREN_PROC = _stc.STC_PS_PAREN_PROC
+STC_PS_TEXT = _stc.STC_PS_TEXT
+STC_PS_HEXSTRING = _stc.STC_PS_HEXSTRING
+STC_PS_BASE85STRING = _stc.STC_PS_BASE85STRING
+STC_PS_BADSTRINGCHAR = _stc.STC_PS_BADSTRINGCHAR
+STC_NSIS_DEFAULT = _stc.STC_NSIS_DEFAULT
+STC_NSIS_COMMENT = _stc.STC_NSIS_COMMENT
+STC_NSIS_STRINGDQ = _stc.STC_NSIS_STRINGDQ
+STC_NSIS_STRINGLQ = _stc.STC_NSIS_STRINGLQ
+STC_NSIS_STRINGRQ = _stc.STC_NSIS_STRINGRQ
+STC_NSIS_FUNCTION = _stc.STC_NSIS_FUNCTION
+STC_NSIS_VARIABLE = _stc.STC_NSIS_VARIABLE
+STC_NSIS_LABEL = _stc.STC_NSIS_LABEL
+STC_NSIS_USERDEFINED = _stc.STC_NSIS_USERDEFINED
+STC_NSIS_SECTIONDEF = _stc.STC_NSIS_SECTIONDEF
+STC_NSIS_SUBSECTIONDEF = _stc.STC_NSIS_SUBSECTIONDEF
+STC_NSIS_IFDEFINEDEF = _stc.STC_NSIS_IFDEFINEDEF
+STC_NSIS_MACRODEF = _stc.STC_NSIS_MACRODEF
+STC_NSIS_STRINGVAR = _stc.STC_NSIS_STRINGVAR
+STC_NSIS_NUMBER = _stc.STC_NSIS_NUMBER
+STC_NSIS_SECTIONGROUP = _stc.STC_NSIS_SECTIONGROUP
+STC_NSIS_PAGEEX = _stc.STC_NSIS_PAGEEX
+STC_NSIS_FUNCTIONDEF = _stc.STC_NSIS_FUNCTIONDEF
+STC_NSIS_COMMENTBOX = _stc.STC_NSIS_COMMENTBOX
+STC_MMIXAL_LEADWS = _stc.STC_MMIXAL_LEADWS
+STC_MMIXAL_COMMENT = _stc.STC_MMIXAL_COMMENT
+STC_MMIXAL_LABEL = _stc.STC_MMIXAL_LABEL
+STC_MMIXAL_OPCODE = _stc.STC_MMIXAL_OPCODE
+STC_MMIXAL_OPCODE_PRE = _stc.STC_MMIXAL_OPCODE_PRE
+STC_MMIXAL_OPCODE_VALID = _stc.STC_MMIXAL_OPCODE_VALID
+STC_MMIXAL_OPCODE_UNKNOWN = _stc.STC_MMIXAL_OPCODE_UNKNOWN
+STC_MMIXAL_OPCODE_POST = _stc.STC_MMIXAL_OPCODE_POST
+STC_MMIXAL_OPERANDS = _stc.STC_MMIXAL_OPERANDS
+STC_MMIXAL_NUMBER = _stc.STC_MMIXAL_NUMBER
+STC_MMIXAL_REF = _stc.STC_MMIXAL_REF
+STC_MMIXAL_CHAR = _stc.STC_MMIXAL_CHAR
+STC_MMIXAL_STRING = _stc.STC_MMIXAL_STRING
+STC_MMIXAL_REGISTER = _stc.STC_MMIXAL_REGISTER
+STC_MMIXAL_HEX = _stc.STC_MMIXAL_HEX
+STC_MMIXAL_OPERATOR = _stc.STC_MMIXAL_OPERATOR
+STC_MMIXAL_SYMBOL = _stc.STC_MMIXAL_SYMBOL
+STC_MMIXAL_INCLUDE = _stc.STC_MMIXAL_INCLUDE
+STC_CLW_DEFAULT = _stc.STC_CLW_DEFAULT
+STC_CLW_LABEL = _stc.STC_CLW_LABEL
+STC_CLW_COMMENT = _stc.STC_CLW_COMMENT
+STC_CLW_STRING = _stc.STC_CLW_STRING
+STC_CLW_USER_IDENTIFIER = _stc.STC_CLW_USER_IDENTIFIER
+STC_CLW_INTEGER_CONSTANT = _stc.STC_CLW_INTEGER_CONSTANT
+STC_CLW_REAL_CONSTANT = _stc.STC_CLW_REAL_CONSTANT
+STC_CLW_PICTURE_STRING = _stc.STC_CLW_PICTURE_STRING
+STC_CLW_KEYWORD = _stc.STC_CLW_KEYWORD
+STC_CLW_COMPILER_DIRECTIVE = _stc.STC_CLW_COMPILER_DIRECTIVE
+STC_CLW_RUNTIME_EXPRESSIONS = _stc.STC_CLW_RUNTIME_EXPRESSIONS
+STC_CLW_BUILTIN_PROCEDURES_FUNCTION = _stc.STC_CLW_BUILTIN_PROCEDURES_FUNCTION
+STC_CLW_STRUCTURE_DATA_TYPE = _stc.STC_CLW_STRUCTURE_DATA_TYPE
+STC_CLW_ATTRIBUTE = _stc.STC_CLW_ATTRIBUTE
+STC_CLW_STANDARD_EQUATE = _stc.STC_CLW_STANDARD_EQUATE
+STC_CLW_ERROR = _stc.STC_CLW_ERROR
+STC_CLW_DEPRECATED = _stc.STC_CLW_DEPRECATED
+STC_LOT_DEFAULT = _stc.STC_LOT_DEFAULT
+STC_LOT_HEADER = _stc.STC_LOT_HEADER
+STC_LOT_BREAK = _stc.STC_LOT_BREAK
+STC_LOT_SET = _stc.STC_LOT_SET
+STC_LOT_PASS = _stc.STC_LOT_PASS
+STC_LOT_FAIL = _stc.STC_LOT_FAIL
+STC_LOT_ABORT = _stc.STC_LOT_ABORT
+STC_YAML_DEFAULT = _stc.STC_YAML_DEFAULT
+STC_YAML_COMMENT = _stc.STC_YAML_COMMENT
+STC_YAML_IDENTIFIER = _stc.STC_YAML_IDENTIFIER
+STC_YAML_KEYWORD = _stc.STC_YAML_KEYWORD
+STC_YAML_NUMBER = _stc.STC_YAML_NUMBER
+STC_YAML_REFERENCE = _stc.STC_YAML_REFERENCE
+STC_YAML_DOCUMENT = _stc.STC_YAML_DOCUMENT
+STC_YAML_TEXT = _stc.STC_YAML_TEXT
+STC_YAML_ERROR = _stc.STC_YAML_ERROR
+STC_YAML_OPERATOR = _stc.STC_YAML_OPERATOR
+STC_TEX_DEFAULT = _stc.STC_TEX_DEFAULT
+STC_TEX_SPECIAL = _stc.STC_TEX_SPECIAL
+STC_TEX_GROUP = _stc.STC_TEX_GROUP
+STC_TEX_SYMBOL = _stc.STC_TEX_SYMBOL
+STC_TEX_COMMAND = _stc.STC_TEX_COMMAND
+STC_TEX_TEXT = _stc.STC_TEX_TEXT
+STC_METAPOST_DEFAULT = _stc.STC_METAPOST_DEFAULT
+STC_METAPOST_SPECIAL = _stc.STC_METAPOST_SPECIAL
+STC_METAPOST_GROUP = _stc.STC_METAPOST_GROUP
+STC_METAPOST_SYMBOL = _stc.STC_METAPOST_SYMBOL
+STC_METAPOST_COMMAND = _stc.STC_METAPOST_COMMAND
+STC_METAPOST_TEXT = _stc.STC_METAPOST_TEXT
+STC_METAPOST_EXTRA = _stc.STC_METAPOST_EXTRA
+STC_ERLANG_DEFAULT = _stc.STC_ERLANG_DEFAULT
+STC_ERLANG_COMMENT = _stc.STC_ERLANG_COMMENT
+STC_ERLANG_VARIABLE = _stc.STC_ERLANG_VARIABLE
+STC_ERLANG_NUMBER = _stc.STC_ERLANG_NUMBER
+STC_ERLANG_KEYWORD = _stc.STC_ERLANG_KEYWORD
+STC_ERLANG_STRING = _stc.STC_ERLANG_STRING
+STC_ERLANG_OPERATOR = _stc.STC_ERLANG_OPERATOR
+STC_ERLANG_ATOM = _stc.STC_ERLANG_ATOM
+STC_ERLANG_FUNCTION_NAME = _stc.STC_ERLANG_FUNCTION_NAME
+STC_ERLANG_CHARACTER = _stc.STC_ERLANG_CHARACTER
+STC_ERLANG_MACRO = _stc.STC_ERLANG_MACRO
+STC_ERLANG_RECORD = _stc.STC_ERLANG_RECORD
+STC_ERLANG_PREPROC = _stc.STC_ERLANG_PREPROC
+STC_ERLANG_NODE_NAME = _stc.STC_ERLANG_NODE_NAME
+STC_ERLANG_COMMENT_FUNCTION = _stc.STC_ERLANG_COMMENT_FUNCTION
+STC_ERLANG_COMMENT_MODULE = _stc.STC_ERLANG_COMMENT_MODULE
+STC_ERLANG_COMMENT_DOC = _stc.STC_ERLANG_COMMENT_DOC
+STC_ERLANG_COMMENT_DOC_MACRO = _stc.STC_ERLANG_COMMENT_DOC_MACRO
+STC_ERLANG_ATOM_QUOTED = _stc.STC_ERLANG_ATOM_QUOTED
+STC_ERLANG_MACRO_QUOTED = _stc.STC_ERLANG_MACRO_QUOTED
+STC_ERLANG_RECORD_QUOTED = _stc.STC_ERLANG_RECORD_QUOTED
+STC_ERLANG_NODE_NAME_QUOTED = _stc.STC_ERLANG_NODE_NAME_QUOTED
+STC_ERLANG_BIFS = _stc.STC_ERLANG_BIFS
+STC_ERLANG_MODULES = _stc.STC_ERLANG_MODULES
+STC_ERLANG_MODULES_ATT = _stc.STC_ERLANG_MODULES_ATT
+STC_ERLANG_UNKNOWN = _stc.STC_ERLANG_UNKNOWN
+STC_MSSQL_DEFAULT = _stc.STC_MSSQL_DEFAULT
+STC_MSSQL_COMMENT = _stc.STC_MSSQL_COMMENT
+STC_MSSQL_LINE_COMMENT = _stc.STC_MSSQL_LINE_COMMENT
+STC_MSSQL_NUMBER = _stc.STC_MSSQL_NUMBER
+STC_MSSQL_STRING = _stc.STC_MSSQL_STRING
+STC_MSSQL_OPERATOR = _stc.STC_MSSQL_OPERATOR
+STC_MSSQL_IDENTIFIER = _stc.STC_MSSQL_IDENTIFIER
+STC_MSSQL_VARIABLE = _stc.STC_MSSQL_VARIABLE
+STC_MSSQL_COLUMN_NAME = _stc.STC_MSSQL_COLUMN_NAME
+STC_MSSQL_STATEMENT = _stc.STC_MSSQL_STATEMENT
+STC_MSSQL_DATATYPE = _stc.STC_MSSQL_DATATYPE
+STC_MSSQL_SYSTABLE = _stc.STC_MSSQL_SYSTABLE
+STC_MSSQL_GLOBAL_VARIABLE = _stc.STC_MSSQL_GLOBAL_VARIABLE
+STC_MSSQL_FUNCTION = _stc.STC_MSSQL_FUNCTION
+STC_MSSQL_STORED_PROCEDURE = _stc.STC_MSSQL_STORED_PROCEDURE
+STC_MSSQL_DEFAULT_PREF_DATATYPE = _stc.STC_MSSQL_DEFAULT_PREF_DATATYPE
+STC_MSSQL_COLUMN_NAME_2 = _stc.STC_MSSQL_COLUMN_NAME_2
+STC_V_DEFAULT = _stc.STC_V_DEFAULT
+STC_V_COMMENT = _stc.STC_V_COMMENT
+STC_V_COMMENTLINE = _stc.STC_V_COMMENTLINE
+STC_V_COMMENTLINEBANG = _stc.STC_V_COMMENTLINEBANG
+STC_V_NUMBER = _stc.STC_V_NUMBER
+STC_V_WORD = _stc.STC_V_WORD
+STC_V_STRING = _stc.STC_V_STRING
+STC_V_WORD2 = _stc.STC_V_WORD2
+STC_V_WORD3 = _stc.STC_V_WORD3
+STC_V_PREPROCESSOR = _stc.STC_V_PREPROCESSOR
+STC_V_OPERATOR = _stc.STC_V_OPERATOR
+STC_V_IDENTIFIER = _stc.STC_V_IDENTIFIER
+STC_V_STRINGEOL = _stc.STC_V_STRINGEOL
+STC_V_USER = _stc.STC_V_USER
+STC_KIX_DEFAULT = _stc.STC_KIX_DEFAULT
+STC_KIX_COMMENT = _stc.STC_KIX_COMMENT
+STC_KIX_STRING1 = _stc.STC_KIX_STRING1
+STC_KIX_STRING2 = _stc.STC_KIX_STRING2
+STC_KIX_NUMBER = _stc.STC_KIX_NUMBER
+STC_KIX_VAR = _stc.STC_KIX_VAR
+STC_KIX_MACRO = _stc.STC_KIX_MACRO
+STC_KIX_KEYWORD = _stc.STC_KIX_KEYWORD
+STC_KIX_FUNCTIONS = _stc.STC_KIX_FUNCTIONS
+STC_KIX_OPERATOR = _stc.STC_KIX_OPERATOR
+STC_KIX_IDENTIFIER = _stc.STC_KIX_IDENTIFIER
+STC_GC_DEFAULT = _stc.STC_GC_DEFAULT
+STC_GC_COMMENTLINE = _stc.STC_GC_COMMENTLINE
+STC_GC_COMMENTBLOCK = _stc.STC_GC_COMMENTBLOCK
+STC_GC_GLOBAL = _stc.STC_GC_GLOBAL
+STC_GC_EVENT = _stc.STC_GC_EVENT
+STC_GC_ATTRIBUTE = _stc.STC_GC_ATTRIBUTE
+STC_GC_CONTROL = _stc.STC_GC_CONTROL
+STC_GC_COMMAND = _stc.STC_GC_COMMAND
+STC_GC_STRING = _stc.STC_GC_STRING
+STC_GC_OPERATOR = _stc.STC_GC_OPERATOR
+STC_SN_DEFAULT = _stc.STC_SN_DEFAULT
+STC_SN_CODE = _stc.STC_SN_CODE
+STC_SN_COMMENTLINE = _stc.STC_SN_COMMENTLINE
+STC_SN_COMMENTLINEBANG = _stc.STC_SN_COMMENTLINEBANG
+STC_SN_NUMBER = _stc.STC_SN_NUMBER
+STC_SN_WORD = _stc.STC_SN_WORD
+STC_SN_STRING = _stc.STC_SN_STRING
+STC_SN_WORD2 = _stc.STC_SN_WORD2
+STC_SN_WORD3 = _stc.STC_SN_WORD3
+STC_SN_PREPROCESSOR = _stc.STC_SN_PREPROCESSOR
+STC_SN_OPERATOR = _stc.STC_SN_OPERATOR
+STC_SN_IDENTIFIER = _stc.STC_SN_IDENTIFIER
+STC_SN_STRINGEOL = _stc.STC_SN_STRINGEOL
+STC_SN_REGEXTAG = _stc.STC_SN_REGEXTAG
+STC_SN_SIGNAL = _stc.STC_SN_SIGNAL
+STC_SN_USER = _stc.STC_SN_USER
+STC_AU3_DEFAULT = _stc.STC_AU3_DEFAULT
+STC_AU3_COMMENT = _stc.STC_AU3_COMMENT
+STC_AU3_COMMENTBLOCK = _stc.STC_AU3_COMMENTBLOCK
+STC_AU3_NUMBER = _stc.STC_AU3_NUMBER
+STC_AU3_FUNCTION = _stc.STC_AU3_FUNCTION
+STC_AU3_KEYWORD = _stc.STC_AU3_KEYWORD
+STC_AU3_MACRO = _stc.STC_AU3_MACRO
+STC_AU3_STRING = _stc.STC_AU3_STRING
+STC_AU3_OPERATOR = _stc.STC_AU3_OPERATOR
+STC_AU3_VARIABLE = _stc.STC_AU3_VARIABLE
+STC_AU3_SENT = _stc.STC_AU3_SENT
+STC_AU3_PREPROCESSOR = _stc.STC_AU3_PREPROCESSOR
+STC_AU3_SPECIAL = _stc.STC_AU3_SPECIAL
+STC_AU3_EXPAND = _stc.STC_AU3_EXPAND
+STC_AU3_COMOBJ = _stc.STC_AU3_COMOBJ
+STC_AU3_UDF = _stc.STC_AU3_UDF
+STC_APDL_DEFAULT = _stc.STC_APDL_DEFAULT
+STC_APDL_COMMENT = _stc.STC_APDL_COMMENT
+STC_APDL_COMMENTBLOCK = _stc.STC_APDL_COMMENTBLOCK
+STC_APDL_NUMBER = _stc.STC_APDL_NUMBER
+STC_APDL_STRING = _stc.STC_APDL_STRING
+STC_APDL_OPERATOR = _stc.STC_APDL_OPERATOR
+STC_APDL_WORD = _stc.STC_APDL_WORD
+STC_APDL_PROCESSOR = _stc.STC_APDL_PROCESSOR
+STC_APDL_COMMAND = _stc.STC_APDL_COMMAND
+STC_APDL_SLASHCOMMAND = _stc.STC_APDL_SLASHCOMMAND
+STC_APDL_STARCOMMAND = _stc.STC_APDL_STARCOMMAND
+STC_APDL_ARGUMENT = _stc.STC_APDL_ARGUMENT
+STC_APDL_FUNCTION = _stc.STC_APDL_FUNCTION
+STC_SH_DEFAULT = _stc.STC_SH_DEFAULT
+STC_SH_ERROR = _stc.STC_SH_ERROR
+STC_SH_COMMENTLINE = _stc.STC_SH_COMMENTLINE
+STC_SH_NUMBER = _stc.STC_SH_NUMBER
+STC_SH_WORD = _stc.STC_SH_WORD
+STC_SH_STRING = _stc.STC_SH_STRING
+STC_SH_CHARACTER = _stc.STC_SH_CHARACTER
+STC_SH_OPERATOR = _stc.STC_SH_OPERATOR
+STC_SH_IDENTIFIER = _stc.STC_SH_IDENTIFIER
+STC_SH_SCALAR = _stc.STC_SH_SCALAR
+STC_SH_PARAM = _stc.STC_SH_PARAM
+STC_SH_BACKTICKS = _stc.STC_SH_BACKTICKS
+STC_SH_HERE_DELIM = _stc.STC_SH_HERE_DELIM
+STC_SH_HERE_Q = _stc.STC_SH_HERE_Q
+STC_ASN1_DEFAULT = _stc.STC_ASN1_DEFAULT
+STC_ASN1_COMMENT = _stc.STC_ASN1_COMMENT
+STC_ASN1_IDENTIFIER = _stc.STC_ASN1_IDENTIFIER
+STC_ASN1_STRING = _stc.STC_ASN1_STRING
+STC_ASN1_OID = _stc.STC_ASN1_OID
+STC_ASN1_SCALAR = _stc.STC_ASN1_SCALAR
+STC_ASN1_KEYWORD = _stc.STC_ASN1_KEYWORD
+STC_ASN1_ATTRIBUTE = _stc.STC_ASN1_ATTRIBUTE
+STC_ASN1_DESCRIPTOR = _stc.STC_ASN1_DESCRIPTOR
+STC_ASN1_TYPE = _stc.STC_ASN1_TYPE
+STC_ASN1_OPERATOR = _stc.STC_ASN1_OPERATOR
+STC_VHDL_DEFAULT = _stc.STC_VHDL_DEFAULT
+STC_VHDL_COMMENT = _stc.STC_VHDL_COMMENT
+STC_VHDL_COMMENTLINEBANG = _stc.STC_VHDL_COMMENTLINEBANG
+STC_VHDL_NUMBER = _stc.STC_VHDL_NUMBER
+STC_VHDL_STRING = _stc.STC_VHDL_STRING
+STC_VHDL_OPERATOR = _stc.STC_VHDL_OPERATOR
+STC_VHDL_IDENTIFIER = _stc.STC_VHDL_IDENTIFIER
+STC_VHDL_STRINGEOL = _stc.STC_VHDL_STRINGEOL
+STC_VHDL_KEYWORD = _stc.STC_VHDL_KEYWORD
+STC_VHDL_STDOPERATOR = _stc.STC_VHDL_STDOPERATOR
+STC_VHDL_ATTRIBUTE = _stc.STC_VHDL_ATTRIBUTE
+STC_VHDL_STDFUNCTION = _stc.STC_VHDL_STDFUNCTION
+STC_VHDL_STDPACKAGE = _stc.STC_VHDL_STDPACKAGE
+STC_VHDL_STDTYPE = _stc.STC_VHDL_STDTYPE
+STC_VHDL_USERWORD = _stc.STC_VHDL_USERWORD
+STC_CAML_DEFAULT = _stc.STC_CAML_DEFAULT
+STC_CAML_IDENTIFIER = _stc.STC_CAML_IDENTIFIER
+STC_CAML_TAGNAME = _stc.STC_CAML_TAGNAME
+STC_CAML_KEYWORD = _stc.STC_CAML_KEYWORD
+STC_CAML_KEYWORD2 = _stc.STC_CAML_KEYWORD2
+STC_CAML_KEYWORD3 = _stc.STC_CAML_KEYWORD3
+STC_CAML_LINENUM = _stc.STC_CAML_LINENUM
+STC_CAML_OPERATOR = _stc.STC_CAML_OPERATOR
+STC_CAML_NUMBER = _stc.STC_CAML_NUMBER
+STC_CAML_CHAR = _stc.STC_CAML_CHAR
+STC_CAML_WHITE = _stc.STC_CAML_WHITE
+STC_CAML_STRING = _stc.STC_CAML_STRING
+STC_CAML_COMMENT = _stc.STC_CAML_COMMENT
+STC_CAML_COMMENT1 = _stc.STC_CAML_COMMENT1
+STC_CAML_COMMENT2 = _stc.STC_CAML_COMMENT2
+STC_CAML_COMMENT3 = _stc.STC_CAML_COMMENT3
+STC_HA_DEFAULT = _stc.STC_HA_DEFAULT
+STC_HA_IDENTIFIER = _stc.STC_HA_IDENTIFIER
+STC_HA_KEYWORD = _stc.STC_HA_KEYWORD
+STC_HA_NUMBER = _stc.STC_HA_NUMBER
+STC_HA_STRING = _stc.STC_HA_STRING
+STC_HA_CHARACTER = _stc.STC_HA_CHARACTER
+STC_HA_CLASS = _stc.STC_HA_CLASS
+STC_HA_MODULE = _stc.STC_HA_MODULE
+STC_HA_CAPITAL = _stc.STC_HA_CAPITAL
+STC_HA_DATA = _stc.STC_HA_DATA
+STC_HA_IMPORT = _stc.STC_HA_IMPORT
+STC_HA_OPERATOR = _stc.STC_HA_OPERATOR
+STC_HA_INSTANCE = _stc.STC_HA_INSTANCE
+STC_HA_COMMENTLINE = _stc.STC_HA_COMMENTLINE
+STC_HA_COMMENTBLOCK = _stc.STC_HA_COMMENTBLOCK
+STC_HA_COMMENTBLOCK2 = _stc.STC_HA_COMMENTBLOCK2
+STC_HA_COMMENTBLOCK3 = _stc.STC_HA_COMMENTBLOCK3
+STC_T3_DEFAULT = _stc.STC_T3_DEFAULT
+STC_T3_X_DEFAULT = _stc.STC_T3_X_DEFAULT
+STC_T3_PREPROCESSOR = _stc.STC_T3_PREPROCESSOR
+STC_T3_BLOCK_COMMENT = _stc.STC_T3_BLOCK_COMMENT
+STC_T3_LINE_COMMENT = _stc.STC_T3_LINE_COMMENT
+STC_T3_OPERATOR = _stc.STC_T3_OPERATOR
+STC_T3_KEYWORD = _stc.STC_T3_KEYWORD
+STC_T3_NUMBER = _stc.STC_T3_NUMBER
+STC_T3_IDENTIFIER = _stc.STC_T3_IDENTIFIER
+STC_T3_S_STRING = _stc.STC_T3_S_STRING
+STC_T3_D_STRING = _stc.STC_T3_D_STRING
+STC_T3_X_STRING = _stc.STC_T3_X_STRING
+STC_T3_LIB_DIRECTIVE = _stc.STC_T3_LIB_DIRECTIVE
+STC_T3_MSG_PARAM = _stc.STC_T3_MSG_PARAM
+STC_T3_HTML_TAG = _stc.STC_T3_HTML_TAG
+STC_T3_HTML_DEFAULT = _stc.STC_T3_HTML_DEFAULT
+STC_T3_HTML_STRING = _stc.STC_T3_HTML_STRING
+STC_T3_USER1 = _stc.STC_T3_USER1
+STC_T3_USER2 = _stc.STC_T3_USER2
+STC_T3_USER3 = _stc.STC_T3_USER3
+STC_T3_BRACE = _stc.STC_T3_BRACE
+STC_REBOL_DEFAULT = _stc.STC_REBOL_DEFAULT
+STC_REBOL_COMMENTLINE = _stc.STC_REBOL_COMMENTLINE
+STC_REBOL_COMMENTBLOCK = _stc.STC_REBOL_COMMENTBLOCK
+STC_REBOL_PREFACE = _stc.STC_REBOL_PREFACE
+STC_REBOL_OPERATOR = _stc.STC_REBOL_OPERATOR
+STC_REBOL_CHARACTER = _stc.STC_REBOL_CHARACTER
+STC_REBOL_QUOTEDSTRING = _stc.STC_REBOL_QUOTEDSTRING
+STC_REBOL_BRACEDSTRING = _stc.STC_REBOL_BRACEDSTRING
+STC_REBOL_NUMBER = _stc.STC_REBOL_NUMBER
+STC_REBOL_PAIR = _stc.STC_REBOL_PAIR
+STC_REBOL_TUPLE = _stc.STC_REBOL_TUPLE
+STC_REBOL_BINARY = _stc.STC_REBOL_BINARY
+STC_REBOL_MONEY = _stc.STC_REBOL_MONEY
+STC_REBOL_ISSUE = _stc.STC_REBOL_ISSUE
+STC_REBOL_TAG = _stc.STC_REBOL_TAG
+STC_REBOL_FILE = _stc.STC_REBOL_FILE
+STC_REBOL_EMAIL = _stc.STC_REBOL_EMAIL
+STC_REBOL_URL = _stc.STC_REBOL_URL
+STC_REBOL_DATE = _stc.STC_REBOL_DATE
+STC_REBOL_TIME = _stc.STC_REBOL_TIME
+STC_REBOL_IDENTIFIER = _stc.STC_REBOL_IDENTIFIER
+STC_REBOL_WORD = _stc.STC_REBOL_WORD
+STC_REBOL_WORD2 = _stc.STC_REBOL_WORD2
+STC_REBOL_WORD3 = _stc.STC_REBOL_WORD3
+STC_REBOL_WORD4 = _stc.STC_REBOL_WORD4
+STC_REBOL_WORD5 = _stc.STC_REBOL_WORD5
+STC_REBOL_WORD6 = _stc.STC_REBOL_WORD6
+STC_REBOL_WORD7 = _stc.STC_REBOL_WORD7
+STC_REBOL_WORD8 = _stc.STC_REBOL_WORD8
+STC_SQL_DEFAULT = _stc.STC_SQL_DEFAULT
+STC_SQL_COMMENT = _stc.STC_SQL_COMMENT
+STC_SQL_COMMENTLINE = _stc.STC_SQL_COMMENTLINE
+STC_SQL_COMMENTDOC = _stc.STC_SQL_COMMENTDOC
+STC_SQL_NUMBER = _stc.STC_SQL_NUMBER
+STC_SQL_WORD = _stc.STC_SQL_WORD
+STC_SQL_STRING = _stc.STC_SQL_STRING
+STC_SQL_CHARACTER = _stc.STC_SQL_CHARACTER
+STC_SQL_SQLPLUS = _stc.STC_SQL_SQLPLUS
+STC_SQL_SQLPLUS_PROMPT = _stc.STC_SQL_SQLPLUS_PROMPT
+STC_SQL_OPERATOR = _stc.STC_SQL_OPERATOR
+STC_SQL_IDENTIFIER = _stc.STC_SQL_IDENTIFIER
+STC_SQL_SQLPLUS_COMMENT = _stc.STC_SQL_SQLPLUS_COMMENT
+STC_SQL_COMMENTLINEDOC = _stc.STC_SQL_COMMENTLINEDOC
+STC_SQL_WORD2 = _stc.STC_SQL_WORD2
+STC_SQL_COMMENTDOCKEYWORD = _stc.STC_SQL_COMMENTDOCKEYWORD
+STC_SQL_COMMENTDOCKEYWORDERROR = _stc.STC_SQL_COMMENTDOCKEYWORDERROR
+STC_SQL_USER1 = _stc.STC_SQL_USER1
+STC_SQL_USER2 = _stc.STC_SQL_USER2
+STC_SQL_USER3 = _stc.STC_SQL_USER3
+STC_SQL_USER4 = _stc.STC_SQL_USER4
+STC_SQL_QUOTEDIDENTIFIER = _stc.STC_SQL_QUOTEDIDENTIFIER
+STC_ST_DEFAULT = _stc.STC_ST_DEFAULT
+STC_ST_STRING = _stc.STC_ST_STRING
+STC_ST_NUMBER = _stc.STC_ST_NUMBER
+STC_ST_COMMENT = _stc.STC_ST_COMMENT
+STC_ST_SYMBOL = _stc.STC_ST_SYMBOL
+STC_ST_BINARY = _stc.STC_ST_BINARY
+STC_ST_BOOL = _stc.STC_ST_BOOL
+STC_ST_SELF = _stc.STC_ST_SELF
+STC_ST_SUPER = _stc.STC_ST_SUPER
+STC_ST_NIL = _stc.STC_ST_NIL
+STC_ST_GLOBAL = _stc.STC_ST_GLOBAL
+STC_ST_RETURN = _stc.STC_ST_RETURN
+STC_ST_SPECIAL = _stc.STC_ST_SPECIAL
+STC_ST_KWSEND = _stc.STC_ST_KWSEND
+STC_ST_ASSIGN = _stc.STC_ST_ASSIGN
+STC_ST_CHARACTER = _stc.STC_ST_CHARACTER
+STC_ST_SPEC_SEL = _stc.STC_ST_SPEC_SEL
+STC_FS_DEFAULT = _stc.STC_FS_DEFAULT
+STC_FS_COMMENT = _stc.STC_FS_COMMENT
+STC_FS_COMMENTLINE = _stc.STC_FS_COMMENTLINE
+STC_FS_COMMENTDOC = _stc.STC_FS_COMMENTDOC
+STC_FS_COMMENTLINEDOC = _stc.STC_FS_COMMENTLINEDOC
+STC_FS_COMMENTDOCKEYWORD = _stc.STC_FS_COMMENTDOCKEYWORD
+STC_FS_COMMENTDOCKEYWORDERROR = _stc.STC_FS_COMMENTDOCKEYWORDERROR
+STC_FS_KEYWORD = _stc.STC_FS_KEYWORD
+STC_FS_KEYWORD2 = _stc.STC_FS_KEYWORD2
+STC_FS_KEYWORD3 = _stc.STC_FS_KEYWORD3
+STC_FS_KEYWORD4 = _stc.STC_FS_KEYWORD4
+STC_FS_NUMBER = _stc.STC_FS_NUMBER
+STC_FS_STRING = _stc.STC_FS_STRING
+STC_FS_PREPROCESSOR = _stc.STC_FS_PREPROCESSOR
+STC_FS_OPERATOR = _stc.STC_FS_OPERATOR
+STC_FS_IDENTIFIER = _stc.STC_FS_IDENTIFIER
+STC_FS_DATE = _stc.STC_FS_DATE
+STC_FS_STRINGEOL = _stc.STC_FS_STRINGEOL
+STC_FS_CONSTANT = _stc.STC_FS_CONSTANT
+STC_FS_WORDOPERATOR = _stc.STC_FS_WORDOPERATOR
+STC_FS_DISABLEDCODE = _stc.STC_FS_DISABLEDCODE
+STC_FS_DEFAULT_C = _stc.STC_FS_DEFAULT_C
+STC_FS_COMMENTDOC_C = _stc.STC_FS_COMMENTDOC_C
+STC_FS_COMMENTLINEDOC_C = _stc.STC_FS_COMMENTLINEDOC_C
+STC_FS_KEYWORD_C = _stc.STC_FS_KEYWORD_C
+STC_FS_KEYWORD2_C = _stc.STC_FS_KEYWORD2_C
+STC_FS_NUMBER_C = _stc.STC_FS_NUMBER_C
+STC_FS_STRING_C = _stc.STC_FS_STRING_C
+STC_FS_PREPROCESSOR_C = _stc.STC_FS_PREPROCESSOR_C
+STC_FS_OPERATOR_C = _stc.STC_FS_OPERATOR_C
+STC_FS_IDENTIFIER_C = _stc.STC_FS_IDENTIFIER_C
+STC_FS_STRINGEOL_C = _stc.STC_FS_STRINGEOL_C
+STC_CSOUND_DEFAULT = _stc.STC_CSOUND_DEFAULT
+STC_CSOUND_COMMENT = _stc.STC_CSOUND_COMMENT
+STC_CSOUND_NUMBER = _stc.STC_CSOUND_NUMBER
+STC_CSOUND_OPERATOR = _stc.STC_CSOUND_OPERATOR
+STC_CSOUND_INSTR = _stc.STC_CSOUND_INSTR
+STC_CSOUND_IDENTIFIER = _stc.STC_CSOUND_IDENTIFIER
+STC_CSOUND_OPCODE = _stc.STC_CSOUND_OPCODE
+STC_CSOUND_HEADERSTMT = _stc.STC_CSOUND_HEADERSTMT
+STC_CSOUND_USERKEYWORD = _stc.STC_CSOUND_USERKEYWORD
+STC_CSOUND_COMMENTBLOCK = _stc.STC_CSOUND_COMMENTBLOCK
+STC_CSOUND_PARAM = _stc.STC_CSOUND_PARAM
+STC_CSOUND_ARATE_VAR = _stc.STC_CSOUND_ARATE_VAR
+STC_CSOUND_KRATE_VAR = _stc.STC_CSOUND_KRATE_VAR
+STC_CSOUND_IRATE_VAR = _stc.STC_CSOUND_IRATE_VAR
+STC_CSOUND_GLOBAL_VAR = _stc.STC_CSOUND_GLOBAL_VAR
+STC_CSOUND_STRINGEOL = _stc.STC_CSOUND_STRINGEOL
+STC_INNO_DEFAULT = _stc.STC_INNO_DEFAULT
+STC_INNO_COMMENT = _stc.STC_INNO_COMMENT
+STC_INNO_KEYWORD = _stc.STC_INNO_KEYWORD
+STC_INNO_PARAMETER = _stc.STC_INNO_PARAMETER
+STC_INNO_SECTION = _stc.STC_INNO_SECTION
+STC_INNO_PREPROC = _stc.STC_INNO_PREPROC
+STC_INNO_INLINE_EXPANSION = _stc.STC_INNO_INLINE_EXPANSION
+STC_INNO_COMMENT_PASCAL = _stc.STC_INNO_COMMENT_PASCAL
+STC_INNO_KEYWORD_PASCAL = _stc.STC_INNO_KEYWORD_PASCAL
+STC_INNO_KEYWORD_USER = _stc.STC_INNO_KEYWORD_USER
+STC_INNO_STRING_DOUBLE = _stc.STC_INNO_STRING_DOUBLE
+STC_INNO_STRING_SINGLE = _stc.STC_INNO_STRING_SINGLE
+STC_INNO_IDENTIFIER = _stc.STC_INNO_IDENTIFIER
+STC_OPAL_SPACE = _stc.STC_OPAL_SPACE
+STC_OPAL_COMMENT_BLOCK = _stc.STC_OPAL_COMMENT_BLOCK
+STC_OPAL_COMMENT_LINE = _stc.STC_OPAL_COMMENT_LINE
+STC_OPAL_INTEGER = _stc.STC_OPAL_INTEGER
+STC_OPAL_KEYWORD = _stc.STC_OPAL_KEYWORD
+STC_OPAL_SORT = _stc.STC_OPAL_SORT
+STC_OPAL_STRING = _stc.STC_OPAL_STRING
+STC_OPAL_PAR = _stc.STC_OPAL_PAR
+STC_OPAL_BOOL_CONST = _stc.STC_OPAL_BOOL_CONST
+STC_OPAL_DEFAULT = _stc.STC_OPAL_DEFAULT
+STC_SPICE_DEFAULT = _stc.STC_SPICE_DEFAULT
+STC_SPICE_IDENTIFIER = _stc.STC_SPICE_IDENTIFIER
+STC_SPICE_KEYWORD = _stc.STC_SPICE_KEYWORD
+STC_SPICE_KEYWORD2 = _stc.STC_SPICE_KEYWORD2
+STC_SPICE_KEYWORD3 = _stc.STC_SPICE_KEYWORD3
+STC_SPICE_NUMBER = _stc.STC_SPICE_NUMBER
+STC_SPICE_DELIMITER = _stc.STC_SPICE_DELIMITER
+STC_SPICE_VALUE = _stc.STC_SPICE_VALUE
+STC_SPICE_COMMENTLINE = _stc.STC_SPICE_COMMENTLINE
+STC_CMAKE_DEFAULT = _stc.STC_CMAKE_DEFAULT
+STC_CMAKE_COMMENT = _stc.STC_CMAKE_COMMENT
+STC_CMAKE_STRINGDQ = _stc.STC_CMAKE_STRINGDQ
+STC_CMAKE_STRINGLQ = _stc.STC_CMAKE_STRINGLQ
+STC_CMAKE_STRINGRQ = _stc.STC_CMAKE_STRINGRQ
+STC_CMAKE_COMMANDS = _stc.STC_CMAKE_COMMANDS
+STC_CMAKE_PARAMETERS = _stc.STC_CMAKE_PARAMETERS
+STC_CMAKE_VARIABLE = _stc.STC_CMAKE_VARIABLE
+STC_CMAKE_USERDEFINED = _stc.STC_CMAKE_USERDEFINED
+STC_CMAKE_WHILEDEF = _stc.STC_CMAKE_WHILEDEF
+STC_CMAKE_FOREACHDEF = _stc.STC_CMAKE_FOREACHDEF
+STC_CMAKE_IFDEFINEDEF = _stc.STC_CMAKE_IFDEFINEDEF
+STC_CMAKE_MACRODEF = _stc.STC_CMAKE_MACRODEF
+STC_CMAKE_STRINGVAR = _stc.STC_CMAKE_STRINGVAR
+STC_CMAKE_NUMBER = _stc.STC_CMAKE_NUMBER
+STC_GAP_DEFAULT = _stc.STC_GAP_DEFAULT
+STC_GAP_IDENTIFIER = _stc.STC_GAP_IDENTIFIER
+STC_GAP_KEYWORD = _stc.STC_GAP_KEYWORD
+STC_GAP_KEYWORD2 = _stc.STC_GAP_KEYWORD2
+STC_GAP_KEYWORD3 = _stc.STC_GAP_KEYWORD3
+STC_GAP_KEYWORD4 = _stc.STC_GAP_KEYWORD4
+STC_GAP_STRING = _stc.STC_GAP_STRING
+STC_GAP_CHAR = _stc.STC_GAP_CHAR
+STC_GAP_OPERATOR = _stc.STC_GAP_OPERATOR
+STC_GAP_COMMENT = _stc.STC_GAP_COMMENT
+STC_GAP_NUMBER = _stc.STC_GAP_NUMBER
+STC_GAP_STRINGEOL = _stc.STC_GAP_STRINGEOL
+STC_PLM_DEFAULT = _stc.STC_PLM_DEFAULT
+STC_PLM_COMMENT = _stc.STC_PLM_COMMENT
+STC_PLM_STRING = _stc.STC_PLM_STRING
+STC_PLM_NUMBER = _stc.STC_PLM_NUMBER
+STC_PLM_IDENTIFIER = _stc.STC_PLM_IDENTIFIER
+STC_PLM_OPERATOR = _stc.STC_PLM_OPERATOR
+STC_PLM_CONTROL = _stc.STC_PLM_CONTROL
+STC_PLM_KEYWORD = _stc.STC_PLM_KEYWORD
+STC_4GL_DEFAULT = _stc.STC_4GL_DEFAULT
+STC_4GL_NUMBER = _stc.STC_4GL_NUMBER
+STC_4GL_WORD = _stc.STC_4GL_WORD
+STC_4GL_STRING = _stc.STC_4GL_STRING
+STC_4GL_CHARACTER = _stc.STC_4GL_CHARACTER
+STC_4GL_PREPROCESSOR = _stc.STC_4GL_PREPROCESSOR
+STC_4GL_OPERATOR = _stc.STC_4GL_OPERATOR
+STC_4GL_IDENTIFIER = _stc.STC_4GL_IDENTIFIER
+STC_4GL_BLOCK = _stc.STC_4GL_BLOCK
+STC_4GL_END = _stc.STC_4GL_END
+STC_4GL_COMMENT1 = _stc.STC_4GL_COMMENT1
+STC_4GL_COMMENT2 = _stc.STC_4GL_COMMENT2
+STC_4GL_COMMENT3 = _stc.STC_4GL_COMMENT3
+STC_4GL_COMMENT4 = _stc.STC_4GL_COMMENT4
+STC_4GL_COMMENT5 = _stc.STC_4GL_COMMENT5
+STC_4GL_COMMENT6 = _stc.STC_4GL_COMMENT6
+STC_4GL_DEFAULT_ = _stc.STC_4GL_DEFAULT_
+STC_4GL_NUMBER_ = _stc.STC_4GL_NUMBER_
+STC_4GL_WORD_ = _stc.STC_4GL_WORD_
+STC_4GL_STRING_ = _stc.STC_4GL_STRING_
+STC_4GL_CHARACTER_ = _stc.STC_4GL_CHARACTER_
+STC_4GL_PREPROCESSOR_ = _stc.STC_4GL_PREPROCESSOR_
+STC_4GL_OPERATOR_ = _stc.STC_4GL_OPERATOR_
+STC_4GL_IDENTIFIER_ = _stc.STC_4GL_IDENTIFIER_
+STC_4GL_BLOCK_ = _stc.STC_4GL_BLOCK_
+STC_4GL_END_ = _stc.STC_4GL_END_
+STC_4GL_COMMENT1_ = _stc.STC_4GL_COMMENT1_
+STC_4GL_COMMENT2_ = _stc.STC_4GL_COMMENT2_
+STC_4GL_COMMENT3_ = _stc.STC_4GL_COMMENT3_
+STC_4GL_COMMENT4_ = _stc.STC_4GL_COMMENT4_
+STC_4GL_COMMENT5_ = _stc.STC_4GL_COMMENT5_
+STC_4GL_COMMENT6_ = _stc.STC_4GL_COMMENT6_
+STC_ABAQUS_DEFAULT = _stc.STC_ABAQUS_DEFAULT
+STC_ABAQUS_COMMENT = _stc.STC_ABAQUS_COMMENT
+STC_ABAQUS_COMMENTBLOCK = _stc.STC_ABAQUS_COMMENTBLOCK
+STC_ABAQUS_NUMBER = _stc.STC_ABAQUS_NUMBER
+STC_ABAQUS_STRING = _stc.STC_ABAQUS_STRING
+STC_ABAQUS_OPERATOR = _stc.STC_ABAQUS_OPERATOR
+STC_ABAQUS_WORD = _stc.STC_ABAQUS_WORD
+STC_ABAQUS_PROCESSOR = _stc.STC_ABAQUS_PROCESSOR
+STC_ABAQUS_COMMAND = _stc.STC_ABAQUS_COMMAND
+STC_ABAQUS_SLASHCOMMAND = _stc.STC_ABAQUS_SLASHCOMMAND
+STC_ABAQUS_STARCOMMAND = _stc.STC_ABAQUS_STARCOMMAND
+STC_ABAQUS_ARGUMENT = _stc.STC_ABAQUS_ARGUMENT
+STC_ABAQUS_FUNCTION = _stc.STC_ABAQUS_FUNCTION
+STC_ASY_DEFAULT = _stc.STC_ASY_DEFAULT
+STC_ASY_COMMENT = _stc.STC_ASY_COMMENT
+STC_ASY_COMMENTLINE = _stc.STC_ASY_COMMENTLINE
+STC_ASY_NUMBER = _stc.STC_ASY_NUMBER
+STC_ASY_WORD = _stc.STC_ASY_WORD
+STC_ASY_STRING = _stc.STC_ASY_STRING
+STC_ASY_CHARACTER = _stc.STC_ASY_CHARACTER
+STC_ASY_OPERATOR = _stc.STC_ASY_OPERATOR
+STC_ASY_IDENTIFIER = _stc.STC_ASY_IDENTIFIER
+STC_ASY_STRINGEOL = _stc.STC_ASY_STRINGEOL
+STC_ASY_COMMENTLINEDOC = _stc.STC_ASY_COMMENTLINEDOC
+STC_ASY_WORD2 = _stc.STC_ASY_WORD2
+STC_R_DEFAULT = _stc.STC_R_DEFAULT
+STC_R_COMMENT = _stc.STC_R_COMMENT
+STC_R_KWORD = _stc.STC_R_KWORD
+STC_R_BASEKWORD = _stc.STC_R_BASEKWORD
+STC_R_OTHERKWORD = _stc.STC_R_OTHERKWORD
+STC_R_NUMBER = _stc.STC_R_NUMBER
+STC_R_STRING = _stc.STC_R_STRING
+STC_R_STRING2 = _stc.STC_R_STRING2
+STC_R_OPERATOR = _stc.STC_R_OPERATOR
+STC_R_IDENTIFIER = _stc.STC_R_IDENTIFIER
+STC_R_INFIX = _stc.STC_R_INFIX
+STC_R_INFIXEOL = _stc.STC_R_INFIXEOL
+STC_MAGIK_DEFAULT = _stc.STC_MAGIK_DEFAULT
+STC_MAGIK_COMMENT = _stc.STC_MAGIK_COMMENT
+STC_MAGIK_HYPER_COMMENT = _stc.STC_MAGIK_HYPER_COMMENT
+STC_MAGIK_STRING = _stc.STC_MAGIK_STRING
+STC_MAGIK_CHARACTER = _stc.STC_MAGIK_CHARACTER
+STC_MAGIK_NUMBER = _stc.STC_MAGIK_NUMBER
+STC_MAGIK_IDENTIFIER = _stc.STC_MAGIK_IDENTIFIER
+STC_MAGIK_OPERATOR = _stc.STC_MAGIK_OPERATOR
+STC_MAGIK_FLOW = _stc.STC_MAGIK_FLOW
+STC_MAGIK_CONTAINER = _stc.STC_MAGIK_CONTAINER
+STC_MAGIK_BRACKET_BLOCK = _stc.STC_MAGIK_BRACKET_BLOCK
+STC_MAGIK_BRACE_BLOCK = _stc.STC_MAGIK_BRACE_BLOCK
+STC_MAGIK_SQBRACKET_BLOCK = _stc.STC_MAGIK_SQBRACKET_BLOCK
+STC_MAGIK_UNKNOWN_KEYWORD = _stc.STC_MAGIK_UNKNOWN_KEYWORD
+STC_MAGIK_KEYWORD = _stc.STC_MAGIK_KEYWORD
+STC_MAGIK_PRAGMA = _stc.STC_MAGIK_PRAGMA
+STC_MAGIK_SYMBOL = _stc.STC_MAGIK_SYMBOL
+STC_POWERSHELL_DEFAULT = _stc.STC_POWERSHELL_DEFAULT
+STC_POWERSHELL_COMMENT = _stc.STC_POWERSHELL_COMMENT
+STC_POWERSHELL_STRING = _stc.STC_POWERSHELL_STRING
+STC_POWERSHELL_CHARACTER = _stc.STC_POWERSHELL_CHARACTER
+STC_POWERSHELL_NUMBER = _stc.STC_POWERSHELL_NUMBER
+STC_POWERSHELL_VARIABLE = _stc.STC_POWERSHELL_VARIABLE
+STC_POWERSHELL_OPERATOR = _stc.STC_POWERSHELL_OPERATOR
+STC_POWERSHELL_IDENTIFIER = _stc.STC_POWERSHELL_IDENTIFIER
+STC_POWERSHELL_KEYWORD = _stc.STC_POWERSHELL_KEYWORD
+STC_POWERSHELL_CMDLET = _stc.STC_POWERSHELL_CMDLET
+STC_POWERSHELL_ALIAS = _stc.STC_POWERSHELL_ALIAS
+STC_POWERSHELL_FUNCTION = _stc.STC_POWERSHELL_FUNCTION
+STC_POWERSHELL_USER1 = _stc.STC_POWERSHELL_USER1
+STC_POWERSHELL_COMMENTSTREAM = _stc.STC_POWERSHELL_COMMENTSTREAM
+STC_MYSQL_DEFAULT = _stc.STC_MYSQL_DEFAULT
+STC_MYSQL_COMMENT = _stc.STC_MYSQL_COMMENT
+STC_MYSQL_COMMENTLINE = _stc.STC_MYSQL_COMMENTLINE
+STC_MYSQL_VARIABLE = _stc.STC_MYSQL_VARIABLE
+STC_MYSQL_SYSTEMVARIABLE = _stc.STC_MYSQL_SYSTEMVARIABLE
+STC_MYSQL_KNOWNSYSTEMVARIABLE = _stc.STC_MYSQL_KNOWNSYSTEMVARIABLE
+STC_MYSQL_NUMBER = _stc.STC_MYSQL_NUMBER
+STC_MYSQL_MAJORKEYWORD = _stc.STC_MYSQL_MAJORKEYWORD
+STC_MYSQL_KEYWORD = _stc.STC_MYSQL_KEYWORD
+STC_MYSQL_DATABASEOBJECT = _stc.STC_MYSQL_DATABASEOBJECT
+STC_MYSQL_PROCEDUREKEYWORD = _stc.STC_MYSQL_PROCEDUREKEYWORD
+STC_MYSQL_STRING = _stc.STC_MYSQL_STRING
+STC_MYSQL_SQSTRING = _stc.STC_MYSQL_SQSTRING
+STC_MYSQL_DQSTRING = _stc.STC_MYSQL_DQSTRING
+STC_MYSQL_OPERATOR = _stc.STC_MYSQL_OPERATOR
+STC_MYSQL_FUNCTION = _stc.STC_MYSQL_FUNCTION
+STC_MYSQL_IDENTIFIER = _stc.STC_MYSQL_IDENTIFIER
+STC_MYSQL_QUOTEDIDENTIFIER = _stc.STC_MYSQL_QUOTEDIDENTIFIER
+STC_MYSQL_USER1 = _stc.STC_MYSQL_USER1
+STC_MYSQL_USER2 = _stc.STC_MYSQL_USER2
+STC_MYSQL_USER3 = _stc.STC_MYSQL_USER3
+STC_MYSQL_HIDDENCOMMAND = _stc.STC_MYSQL_HIDDENCOMMAND
+STC_PO_DEFAULT = _stc.STC_PO_DEFAULT
+STC_PO_COMMENT = _stc.STC_PO_COMMENT
+STC_PO_MSGID = _stc.STC_PO_MSGID
+STC_PO_MSGID_TEXT = _stc.STC_PO_MSGID_TEXT
+STC_PO_MSGSTR = _stc.STC_PO_MSGSTR
+STC_PO_MSGSTR_TEXT = _stc.STC_PO_MSGSTR_TEXT
+STC_PO_MSGCTXT = _stc.STC_PO_MSGCTXT
+STC_PO_MSGCTXT_TEXT = _stc.STC_PO_MSGCTXT_TEXT
+STC_PO_FUZZY = _stc.STC_PO_FUZZY
+STC_PAS_DEFAULT = _stc.STC_PAS_DEFAULT
+STC_PAS_IDENTIFIER = _stc.STC_PAS_IDENTIFIER
+STC_PAS_COMMENT = _stc.STC_PAS_COMMENT
+STC_PAS_COMMENT2 = _stc.STC_PAS_COMMENT2
+STC_PAS_COMMENTLINE = _stc.STC_PAS_COMMENTLINE
+STC_PAS_PREPROCESSOR = _stc.STC_PAS_PREPROCESSOR
+STC_PAS_PREPROCESSOR2 = _stc.STC_PAS_PREPROCESSOR2
+STC_PAS_NUMBER = _stc.STC_PAS_NUMBER
+STC_PAS_HEXNUMBER = _stc.STC_PAS_HEXNUMBER
+STC_PAS_WORD = _stc.STC_PAS_WORD
+STC_PAS_STRING = _stc.STC_PAS_STRING
+STC_PAS_STRINGEOL = _stc.STC_PAS_STRINGEOL
+STC_PAS_CHARACTER = _stc.STC_PAS_CHARACTER
+STC_PAS_OPERATOR = _stc.STC_PAS_OPERATOR
+STC_PAS_ASM = _stc.STC_PAS_ASM
+STC_SORCUS_DEFAULT = _stc.STC_SORCUS_DEFAULT
+STC_SORCUS_COMMAND = _stc.STC_SORCUS_COMMAND
+STC_SORCUS_PARAMETER = _stc.STC_SORCUS_PARAMETER
+STC_SORCUS_COMMENTLINE = _stc.STC_SORCUS_COMMENTLINE
+STC_SORCUS_STRING = _stc.STC_SORCUS_STRING
+STC_SORCUS_STRINGEOL = _stc.STC_SORCUS_STRINGEOL
+STC_SORCUS_IDENTIFIER = _stc.STC_SORCUS_IDENTIFIER
+STC_SORCUS_OPERATOR = _stc.STC_SORCUS_OPERATOR
+STC_SORCUS_NUMBER = _stc.STC_SORCUS_NUMBER
+STC_SORCUS_CONSTANT = _stc.STC_SORCUS_CONSTANT
+STC_POWERPRO_DEFAULT = _stc.STC_POWERPRO_DEFAULT
+STC_POWERPRO_COMMENTBLOCK = _stc.STC_POWERPRO_COMMENTBLOCK
+STC_POWERPRO_COMMENTLINE = _stc.STC_POWERPRO_COMMENTLINE
+STC_POWERPRO_NUMBER = _stc.STC_POWERPRO_NUMBER
+STC_POWERPRO_WORD = _stc.STC_POWERPRO_WORD
+STC_POWERPRO_WORD2 = _stc.STC_POWERPRO_WORD2
+STC_POWERPRO_WORD3 = _stc.STC_POWERPRO_WORD3
+STC_POWERPRO_WORD4 = _stc.STC_POWERPRO_WORD4
+STC_POWERPRO_DOUBLEQUOTEDSTRING = _stc.STC_POWERPRO_DOUBLEQUOTEDSTRING
+STC_POWERPRO_SINGLEQUOTEDSTRING = _stc.STC_POWERPRO_SINGLEQUOTEDSTRING
+STC_POWERPRO_LINECONTINUE = _stc.STC_POWERPRO_LINECONTINUE
+STC_POWERPRO_OPERATOR = _stc.STC_POWERPRO_OPERATOR
+STC_POWERPRO_IDENTIFIER = _stc.STC_POWERPRO_IDENTIFIER
+STC_POWERPRO_STRINGEOL = _stc.STC_POWERPRO_STRINGEOL
+STC_POWERPRO_VERBATIM = _stc.STC_POWERPRO_VERBATIM
+STC_POWERPRO_ALTQUOTE = _stc.STC_POWERPRO_ALTQUOTE
+STC_POWERPRO_FUNCTION = _stc.STC_POWERPRO_FUNCTION
+STC_SML_DEFAULT = _stc.STC_SML_DEFAULT
+STC_SML_IDENTIFIER = _stc.STC_SML_IDENTIFIER
+STC_SML_TAGNAME = _stc.STC_SML_TAGNAME
+STC_SML_KEYWORD = _stc.STC_SML_KEYWORD
+STC_SML_KEYWORD2 = _stc.STC_SML_KEYWORD2
+STC_SML_KEYWORD3 = _stc.STC_SML_KEYWORD3
+STC_SML_LINENUM = _stc.STC_SML_LINENUM
+STC_SML_OPERATOR = _stc.STC_SML_OPERATOR
+STC_SML_NUMBER = _stc.STC_SML_NUMBER
+STC_SML_CHAR = _stc.STC_SML_CHAR
+STC_SML_STRING = _stc.STC_SML_STRING
+STC_SML_COMMENT = _stc.STC_SML_COMMENT
+STC_SML_COMMENT1 = _stc.STC_SML_COMMENT1
+STC_SML_COMMENT2 = _stc.STC_SML_COMMENT2
+STC_SML_COMMENT3 = _stc.STC_SML_COMMENT3
+STC_MARKDOWN_DEFAULT = _stc.STC_MARKDOWN_DEFAULT
+STC_MARKDOWN_LINE_BEGIN = _stc.STC_MARKDOWN_LINE_BEGIN
+STC_MARKDOWN_STRONG1 = _stc.STC_MARKDOWN_STRONG1
+STC_MARKDOWN_STRONG2 = _stc.STC_MARKDOWN_STRONG2
+STC_MARKDOWN_EM1 = _stc.STC_MARKDOWN_EM1
+STC_MARKDOWN_EM2 = _stc.STC_MARKDOWN_EM2
+STC_MARKDOWN_HEADER1 = _stc.STC_MARKDOWN_HEADER1
+STC_MARKDOWN_HEADER2 = _stc.STC_MARKDOWN_HEADER2
+STC_MARKDOWN_HEADER3 = _stc.STC_MARKDOWN_HEADER3
+STC_MARKDOWN_HEADER4 = _stc.STC_MARKDOWN_HEADER4
+STC_MARKDOWN_HEADER5 = _stc.STC_MARKDOWN_HEADER5
+STC_MARKDOWN_HEADER6 = _stc.STC_MARKDOWN_HEADER6
+STC_MARKDOWN_PRECHAR = _stc.STC_MARKDOWN_PRECHAR
+STC_MARKDOWN_ULIST_ITEM = _stc.STC_MARKDOWN_ULIST_ITEM
+STC_MARKDOWN_OLIST_ITEM = _stc.STC_MARKDOWN_OLIST_ITEM
+STC_MARKDOWN_BLOCKQUOTE = _stc.STC_MARKDOWN_BLOCKQUOTE
+STC_MARKDOWN_STRIKEOUT = _stc.STC_MARKDOWN_STRIKEOUT
+STC_MARKDOWN_HRULE = _stc.STC_MARKDOWN_HRULE
+STC_MARKDOWN_LINK = _stc.STC_MARKDOWN_LINK
+STC_MARKDOWN_CODE = _stc.STC_MARKDOWN_CODE
+STC_MARKDOWN_CODE2 = _stc.STC_MARKDOWN_CODE2
+STC_MARKDOWN_CODEBK = _stc.STC_MARKDOWN_CODEBK
+STC_TXT2TAGS_DEFAULT = _stc.STC_TXT2TAGS_DEFAULT
+STC_TXT2TAGS_LINE_BEGIN = _stc.STC_TXT2TAGS_LINE_BEGIN
+STC_TXT2TAGS_STRONG1 = _stc.STC_TXT2TAGS_STRONG1
+STC_TXT2TAGS_STRONG2 = _stc.STC_TXT2TAGS_STRONG2
+STC_TXT2TAGS_EM1 = _stc.STC_TXT2TAGS_EM1
+STC_TXT2TAGS_EM2 = _stc.STC_TXT2TAGS_EM2
+STC_TXT2TAGS_HEADER1 = _stc.STC_TXT2TAGS_HEADER1
+STC_TXT2TAGS_HEADER2 = _stc.STC_TXT2TAGS_HEADER2
+STC_TXT2TAGS_HEADER3 = _stc.STC_TXT2TAGS_HEADER3
+STC_TXT2TAGS_HEADER4 = _stc.STC_TXT2TAGS_HEADER4
+STC_TXT2TAGS_HEADER5 = _stc.STC_TXT2TAGS_HEADER5
+STC_TXT2TAGS_HEADER6 = _stc.STC_TXT2TAGS_HEADER6
+STC_TXT2TAGS_PRECHAR = _stc.STC_TXT2TAGS_PRECHAR
+STC_TXT2TAGS_ULIST_ITEM = _stc.STC_TXT2TAGS_ULIST_ITEM
+STC_TXT2TAGS_OLIST_ITEM = _stc.STC_TXT2TAGS_OLIST_ITEM
+STC_TXT2TAGS_BLOCKQUOTE = _stc.STC_TXT2TAGS_BLOCKQUOTE
+STC_TXT2TAGS_STRIKEOUT = _stc.STC_TXT2TAGS_STRIKEOUT
+STC_TXT2TAGS_HRULE = _stc.STC_TXT2TAGS_HRULE
+STC_TXT2TAGS_LINK = _stc.STC_TXT2TAGS_LINK
+STC_TXT2TAGS_CODE = _stc.STC_TXT2TAGS_CODE
+STC_TXT2TAGS_CODE2 = _stc.STC_TXT2TAGS_CODE2
+STC_TXT2TAGS_CODEBK = _stc.STC_TXT2TAGS_CODEBK
+STC_TXT2TAGS_COMMENT = _stc.STC_TXT2TAGS_COMMENT
+STC_TXT2TAGS_OPTION = _stc.STC_TXT2TAGS_OPTION
+STC_TXT2TAGS_PREPROC = _stc.STC_TXT2TAGS_PREPROC
+STC_TXT2TAGS_POSTPROC = _stc.STC_TXT2TAGS_POSTPROC
+STC_A68K_DEFAULT = _stc.STC_A68K_DEFAULT
+STC_A68K_COMMENT = _stc.STC_A68K_COMMENT
+STC_A68K_NUMBER_DEC = _stc.STC_A68K_NUMBER_DEC
+STC_A68K_NUMBER_BIN = _stc.STC_A68K_NUMBER_BIN
+STC_A68K_NUMBER_HEX = _stc.STC_A68K_NUMBER_HEX
+STC_A68K_STRING1 = _stc.STC_A68K_STRING1
+STC_A68K_OPERATOR = _stc.STC_A68K_OPERATOR
+STC_A68K_CPUINSTRUCTION = _stc.STC_A68K_CPUINSTRUCTION
+STC_A68K_EXTINSTRUCTION = _stc.STC_A68K_EXTINSTRUCTION
+STC_A68K_REGISTER = _stc.STC_A68K_REGISTER
+STC_A68K_DIRECTIVE = _stc.STC_A68K_DIRECTIVE
+STC_A68K_MACRO_ARG = _stc.STC_A68K_MACRO_ARG
+STC_A68K_LABEL = _stc.STC_A68K_LABEL
+STC_A68K_STRING2 = _stc.STC_A68K_STRING2
+STC_A68K_IDENTIFIER = _stc.STC_A68K_IDENTIFIER
+STC_A68K_MACRO_DECLARATION = _stc.STC_A68K_MACRO_DECLARATION
+STC_A68K_COMMENT_WORD = _stc.STC_A68K_COMMENT_WORD
+STC_A68K_COMMENT_SPECIAL = _stc.STC_A68K_COMMENT_SPECIAL
+STC_A68K_COMMENT_DOXYGEN = _stc.STC_A68K_COMMENT_DOXYGEN
+STC_MODULA_DEFAULT = _stc.STC_MODULA_DEFAULT
+STC_MODULA_COMMENT = _stc.STC_MODULA_COMMENT
+STC_MODULA_DOXYCOMM = _stc.STC_MODULA_DOXYCOMM
+STC_MODULA_DOXYKEY = _stc.STC_MODULA_DOXYKEY
+STC_MODULA_KEYWORD = _stc.STC_MODULA_KEYWORD
+STC_MODULA_RESERVED = _stc.STC_MODULA_RESERVED
+STC_MODULA_NUMBER = _stc.STC_MODULA_NUMBER
+STC_MODULA_BASENUM = _stc.STC_MODULA_BASENUM
+STC_MODULA_FLOAT = _stc.STC_MODULA_FLOAT
+STC_MODULA_STRING = _stc.STC_MODULA_STRING
+STC_MODULA_STRSPEC = _stc.STC_MODULA_STRSPEC
+STC_MODULA_CHAR = _stc.STC_MODULA_CHAR
+STC_MODULA_CHARSPEC = _stc.STC_MODULA_CHARSPEC
+STC_MODULA_PROC = _stc.STC_MODULA_PROC
+STC_MODULA_PRAGMA = _stc.STC_MODULA_PRAGMA
+STC_MODULA_PRGKEY = _stc.STC_MODULA_PRGKEY
+STC_MODULA_OPERATOR = _stc.STC_MODULA_OPERATOR
+STC_MODULA_BADSTR = _stc.STC_MODULA_BADSTR
+STC_COFFEESCRIPT_DEFAULT = _stc.STC_COFFEESCRIPT_DEFAULT
+STC_COFFEESCRIPT_COMMENT = _stc.STC_COFFEESCRIPT_COMMENT
+STC_COFFEESCRIPT_COMMENTLINE = _stc.STC_COFFEESCRIPT_COMMENTLINE
+STC_COFFEESCRIPT_COMMENTDOC = _stc.STC_COFFEESCRIPT_COMMENTDOC
+STC_COFFEESCRIPT_NUMBER = _stc.STC_COFFEESCRIPT_NUMBER
+STC_COFFEESCRIPT_WORD = _stc.STC_COFFEESCRIPT_WORD
+STC_COFFEESCRIPT_STRING = _stc.STC_COFFEESCRIPT_STRING
+STC_COFFEESCRIPT_CHARACTER = _stc.STC_COFFEESCRIPT_CHARACTER
+STC_COFFEESCRIPT_UUID = _stc.STC_COFFEESCRIPT_UUID
+STC_COFFEESCRIPT_PREPROCESSOR = _stc.STC_COFFEESCRIPT_PREPROCESSOR
+STC_COFFEESCRIPT_OPERATOR = _stc.STC_COFFEESCRIPT_OPERATOR
+STC_COFFEESCRIPT_IDENTIFIER = _stc.STC_COFFEESCRIPT_IDENTIFIER
+STC_COFFEESCRIPT_STRINGEOL = _stc.STC_COFFEESCRIPT_STRINGEOL
+STC_COFFEESCRIPT_VERBATIM = _stc.STC_COFFEESCRIPT_VERBATIM
+STC_COFFEESCRIPT_REGEX = _stc.STC_COFFEESCRIPT_REGEX
+STC_COFFEESCRIPT_COMMENTLINEDOC = _stc.STC_COFFEESCRIPT_COMMENTLINEDOC
+STC_COFFEESCRIPT_WORD2 = _stc.STC_COFFEESCRIPT_WORD2
+STC_COFFEESCRIPT_COMMENTDOCKEYWORD = _stc.STC_COFFEESCRIPT_COMMENTDOCKEYWORD
+STC_COFFEESCRIPT_COMMENTDOCKEYWORDERROR = _stc.STC_COFFEESCRIPT_COMMENTDOCKEYWORDERROR
+STC_COFFEESCRIPT_GLOBALCLASS = _stc.STC_COFFEESCRIPT_GLOBALCLASS
+STC_COFFEESCRIPT_STRINGRAW = _stc.STC_COFFEESCRIPT_STRINGRAW
+STC_COFFEESCRIPT_TRIPLEVERBATIM = _stc.STC_COFFEESCRIPT_TRIPLEVERBATIM
+STC_COFFEESCRIPT_HASHQUOTEDSTRING = _stc.STC_COFFEESCRIPT_HASHQUOTEDSTRING
+STC_COFFEESCRIPT_COMMENTBLOCK = _stc.STC_COFFEESCRIPT_COMMENTBLOCK
+STC_COFFEESCRIPT_VERBOSE_REGEX = _stc.STC_COFFEESCRIPT_VERBOSE_REGEX
+STC_COFFEESCRIPT_VERBOSE_REGEX_COMMENT = _stc.STC_COFFEESCRIPT_VERBOSE_REGEX_COMMENT
+STC_AVS_DEFAULT = _stc.STC_AVS_DEFAULT
+STC_AVS_COMMENTBLOCK = _stc.STC_AVS_COMMENTBLOCK
+STC_AVS_COMMENTBLOCKN = _stc.STC_AVS_COMMENTBLOCKN
+STC_AVS_COMMENTLINE = _stc.STC_AVS_COMMENTLINE
+STC_AVS_NUMBER = _stc.STC_AVS_NUMBER
+STC_AVS_OPERATOR = _stc.STC_AVS_OPERATOR
+STC_AVS_IDENTIFIER = _stc.STC_AVS_IDENTIFIER
+STC_AVS_STRING = _stc.STC_AVS_STRING
+STC_AVS_TRIPLESTRING = _stc.STC_AVS_TRIPLESTRING
+STC_AVS_KEYWORD = _stc.STC_AVS_KEYWORD
+STC_AVS_FILTER = _stc.STC_AVS_FILTER
+STC_AVS_PLUGIN = _stc.STC_AVS_PLUGIN
+STC_AVS_FUNCTION = _stc.STC_AVS_FUNCTION
+STC_AVS_CLIPPROP = _stc.STC_AVS_CLIPPROP
+STC_AVS_USERDFN = _stc.STC_AVS_USERDFN
+STC_ECL_DEFAULT = _stc.STC_ECL_DEFAULT
+STC_ECL_COMMENT = _stc.STC_ECL_COMMENT
+STC_ECL_COMMENTLINE = _stc.STC_ECL_COMMENTLINE
+STC_ECL_NUMBER = _stc.STC_ECL_NUMBER
+STC_ECL_STRING = _stc.STC_ECL_STRING
+STC_ECL_WORD0 = _stc.STC_ECL_WORD0
+STC_ECL_OPERATOR = _stc.STC_ECL_OPERATOR
+STC_ECL_CHARACTER = _stc.STC_ECL_CHARACTER
+STC_ECL_UUID = _stc.STC_ECL_UUID
+STC_ECL_PREPROCESSOR = _stc.STC_ECL_PREPROCESSOR
+STC_ECL_UNKNOWN = _stc.STC_ECL_UNKNOWN
+STC_ECL_IDENTIFIER = _stc.STC_ECL_IDENTIFIER
+STC_ECL_STRINGEOL = _stc.STC_ECL_STRINGEOL
+STC_ECL_VERBATIM = _stc.STC_ECL_VERBATIM
+STC_ECL_REGEX = _stc.STC_ECL_REGEX
+STC_ECL_COMMENTLINEDOC = _stc.STC_ECL_COMMENTLINEDOC
+STC_ECL_WORD1 = _stc.STC_ECL_WORD1
+STC_ECL_COMMENTDOCKEYWORD = _stc.STC_ECL_COMMENTDOCKEYWORD
+STC_ECL_COMMENTDOCKEYWORDERROR = _stc.STC_ECL_COMMENTDOCKEYWORDERROR
+STC_ECL_WORD2 = _stc.STC_ECL_WORD2
+STC_ECL_WORD3 = _stc.STC_ECL_WORD3
+STC_ECL_WORD4 = _stc.STC_ECL_WORD4
+STC_ECL_WORD5 = _stc.STC_ECL_WORD5
+STC_ECL_COMMENTDOC = _stc.STC_ECL_COMMENTDOC
+STC_ECL_ADDED = _stc.STC_ECL_ADDED
+STC_ECL_DELETED = _stc.STC_ECL_DELETED
+STC_ECL_CHANGED = _stc.STC_ECL_CHANGED
+STC_ECL_MOVED = _stc.STC_ECL_MOVED
+STC_OSCRIPT_DEFAULT = _stc.STC_OSCRIPT_DEFAULT
+STC_OSCRIPT_LINE_COMMENT = _stc.STC_OSCRIPT_LINE_COMMENT
+STC_OSCRIPT_BLOCK_COMMENT = _stc.STC_OSCRIPT_BLOCK_COMMENT
+STC_OSCRIPT_DOC_COMMENT = _stc.STC_OSCRIPT_DOC_COMMENT
+STC_OSCRIPT_PREPROCESSOR = _stc.STC_OSCRIPT_PREPROCESSOR
+STC_OSCRIPT_NUMBER = _stc.STC_OSCRIPT_NUMBER
+STC_OSCRIPT_SINGLEQUOTE_STRING = _stc.STC_OSCRIPT_SINGLEQUOTE_STRING
+STC_OSCRIPT_DOUBLEQUOTE_STRING = _stc.STC_OSCRIPT_DOUBLEQUOTE_STRING
+STC_OSCRIPT_CONSTANT = _stc.STC_OSCRIPT_CONSTANT
+STC_OSCRIPT_IDENTIFIER = _stc.STC_OSCRIPT_IDENTIFIER
+STC_OSCRIPT_GLOBAL = _stc.STC_OSCRIPT_GLOBAL
+STC_OSCRIPT_KEYWORD = _stc.STC_OSCRIPT_KEYWORD
+STC_OSCRIPT_OPERATOR = _stc.STC_OSCRIPT_OPERATOR
+STC_OSCRIPT_LABEL = _stc.STC_OSCRIPT_LABEL
+STC_OSCRIPT_TYPE = _stc.STC_OSCRIPT_TYPE
+STC_OSCRIPT_FUNCTION = _stc.STC_OSCRIPT_FUNCTION
+STC_OSCRIPT_OBJECT = _stc.STC_OSCRIPT_OBJECT
+STC_OSCRIPT_PROPERTY = _stc.STC_OSCRIPT_PROPERTY
+STC_OSCRIPT_METHOD = _stc.STC_OSCRIPT_METHOD
+STC_VISUALPROLOG_DEFAULT = _stc.STC_VISUALPROLOG_DEFAULT
+STC_VISUALPROLOG_KEY_MAJOR = _stc.STC_VISUALPROLOG_KEY_MAJOR
+STC_VISUALPROLOG_KEY_MINOR = _stc.STC_VISUALPROLOG_KEY_MINOR
+STC_VISUALPROLOG_KEY_DIRECTIVE = _stc.STC_VISUALPROLOG_KEY_DIRECTIVE
+STC_VISUALPROLOG_COMMENT_BLOCK = _stc.STC_VISUALPROLOG_COMMENT_BLOCK
+STC_VISUALPROLOG_COMMENT_LINE = _stc.STC_VISUALPROLOG_COMMENT_LINE
+STC_VISUALPROLOG_COMMENT_KEY = _stc.STC_VISUALPROLOG_COMMENT_KEY
+STC_VISUALPROLOG_COMMENT_KEY_ERROR = _stc.STC_VISUALPROLOG_COMMENT_KEY_ERROR
+STC_VISUALPROLOG_IDENTIFIER = _stc.STC_VISUALPROLOG_IDENTIFIER
+STC_VISUALPROLOG_VARIABLE = _stc.STC_VISUALPROLOG_VARIABLE
+STC_VISUALPROLOG_ANONYMOUS = _stc.STC_VISUALPROLOG_ANONYMOUS
+STC_VISUALPROLOG_NUMBER = _stc.STC_VISUALPROLOG_NUMBER
+STC_VISUALPROLOG_OPERATOR = _stc.STC_VISUALPROLOG_OPERATOR
+STC_VISUALPROLOG_CHARACTER = _stc.STC_VISUALPROLOG_CHARACTER
+STC_VISUALPROLOG_CHARACTER_TOO_MANY = _stc.STC_VISUALPROLOG_CHARACTER_TOO_MANY
+STC_VISUALPROLOG_CHARACTER_ESCAPE_ERROR = _stc.STC_VISUALPROLOG_CHARACTER_ESCAPE_ERROR
+STC_VISUALPROLOG_STRING = _stc.STC_VISUALPROLOG_STRING
+STC_VISUALPROLOG_STRING_ESCAPE = _stc.STC_VISUALPROLOG_STRING_ESCAPE
+STC_VISUALPROLOG_STRING_ESCAPE_ERROR = _stc.STC_VISUALPROLOG_STRING_ESCAPE_ERROR
+STC_VISUALPROLOG_STRING_EOL_OPEN = _stc.STC_VISUALPROLOG_STRING_EOL_OPEN
+STC_VISUALPROLOG_STRING_VERBATIM = _stc.STC_VISUALPROLOG_STRING_VERBATIM
+STC_VISUALPROLOG_STRING_VERBATIM_SPECIAL = _stc.STC_VISUALPROLOG_STRING_VERBATIM_SPECIAL
+STC_VISUALPROLOG_STRING_VERBATIM_EOL = _stc.STC_VISUALPROLOG_STRING_VERBATIM_EOL
+STC_CMD_REDO = _stc.STC_CMD_REDO
+STC_CMD_SELECTALL = _stc.STC_CMD_SELECTALL
+STC_CMD_UNDO = _stc.STC_CMD_UNDO
+STC_CMD_CUT = _stc.STC_CMD_CUT
+STC_CMD_COPY = _stc.STC_CMD_COPY
+STC_CMD_PASTE = _stc.STC_CMD_PASTE
+STC_CMD_CLEAR = _stc.STC_CMD_CLEAR
+STC_CMD_LINEDOWN = _stc.STC_CMD_LINEDOWN
+STC_CMD_LINEDOWNEXTEND = _stc.STC_CMD_LINEDOWNEXTEND
+STC_CMD_LINEUP = _stc.STC_CMD_LINEUP
+STC_CMD_LINEUPEXTEND = _stc.STC_CMD_LINEUPEXTEND
+STC_CMD_CHARLEFT = _stc.STC_CMD_CHARLEFT
+STC_CMD_CHARLEFTEXTEND = _stc.STC_CMD_CHARLEFTEXTEND
+STC_CMD_CHARRIGHT = _stc.STC_CMD_CHARRIGHT
+STC_CMD_CHARRIGHTEXTEND = _stc.STC_CMD_CHARRIGHTEXTEND
+STC_CMD_WORDLEFT = _stc.STC_CMD_WORDLEFT
+STC_CMD_WORDLEFTEXTEND = _stc.STC_CMD_WORDLEFTEXTEND
+STC_CMD_WORDRIGHT = _stc.STC_CMD_WORDRIGHT
+STC_CMD_WORDRIGHTEXTEND = _stc.STC_CMD_WORDRIGHTEXTEND
+STC_CMD_HOME = _stc.STC_CMD_HOME
+STC_CMD_HOMEEXTEND = _stc.STC_CMD_HOMEEXTEND
+STC_CMD_LINEEND = _stc.STC_CMD_LINEEND
+STC_CMD_LINEENDEXTEND = _stc.STC_CMD_LINEENDEXTEND
+STC_CMD_DOCUMENTSTART = _stc.STC_CMD_DOCUMENTSTART
+STC_CMD_DOCUMENTSTARTEXTEND = _stc.STC_CMD_DOCUMENTSTARTEXTEND
+STC_CMD_DOCUMENTEND = _stc.STC_CMD_DOCUMENTEND
+STC_CMD_DOCUMENTENDEXTEND = _stc.STC_CMD_DOCUMENTENDEXTEND
+STC_CMD_PAGEUP = _stc.STC_CMD_PAGEUP
+STC_CMD_PAGEUPEXTEND = _stc.STC_CMD_PAGEUPEXTEND
+STC_CMD_PAGEDOWN = _stc.STC_CMD_PAGEDOWN
+STC_CMD_PAGEDOWNEXTEND = _stc.STC_CMD_PAGEDOWNEXTEND
+STC_CMD_EDITTOGGLEOVERTYPE = _stc.STC_CMD_EDITTOGGLEOVERTYPE
+STC_CMD_CANCEL = _stc.STC_CMD_CANCEL
+STC_CMD_DELETEBACK = _stc.STC_CMD_DELETEBACK
+STC_CMD_TAB = _stc.STC_CMD_TAB
+STC_CMD_BACKTAB = _stc.STC_CMD_BACKTAB
+STC_CMD_NEWLINE = _stc.STC_CMD_NEWLINE
+STC_CMD_FORMFEED = _stc.STC_CMD_FORMFEED
+STC_CMD_VCHOME = _stc.STC_CMD_VCHOME
+STC_CMD_VCHOMEEXTEND = _stc.STC_CMD_VCHOMEEXTEND
+STC_CMD_ZOOMIN = _stc.STC_CMD_ZOOMIN
+STC_CMD_ZOOMOUT = _stc.STC_CMD_ZOOMOUT
+STC_CMD_DELWORDLEFT = _stc.STC_CMD_DELWORDLEFT
+STC_CMD_DELWORDRIGHT = _stc.STC_CMD_DELWORDRIGHT
+STC_CMD_DELWORDRIGHTEND = _stc.STC_CMD_DELWORDRIGHTEND
+STC_CMD_LINECUT = _stc.STC_CMD_LINECUT
+STC_CMD_LINEDELETE = _stc.STC_CMD_LINEDELETE
+STC_CMD_LINETRANSPOSE = _stc.STC_CMD_LINETRANSPOSE
+STC_CMD_LINEDUPLICATE = _stc.STC_CMD_LINEDUPLICATE
+STC_CMD_LOWERCASE = _stc.STC_CMD_LOWERCASE
+STC_CMD_UPPERCASE = _stc.STC_CMD_UPPERCASE
+STC_CMD_LINESCROLLDOWN = _stc.STC_CMD_LINESCROLLDOWN
+STC_CMD_LINESCROLLUP = _stc.STC_CMD_LINESCROLLUP
+STC_CMD_DELETEBACKNOTLINE = _stc.STC_CMD_DELETEBACKNOTLINE
+STC_CMD_HOMEDISPLAY = _stc.STC_CMD_HOMEDISPLAY
+STC_CMD_HOMEDISPLAYEXTEND = _stc.STC_CMD_HOMEDISPLAYEXTEND
+STC_CMD_LINEENDDISPLAY = _stc.STC_CMD_LINEENDDISPLAY
+STC_CMD_LINEENDDISPLAYEXTEND = _stc.STC_CMD_LINEENDDISPLAYEXTEND
+STC_CMD_HOMEWRAP = _stc.STC_CMD_HOMEWRAP
+STC_CMD_HOMEWRAPEXTEND = _stc.STC_CMD_HOMEWRAPEXTEND
+STC_CMD_LINEENDWRAP = _stc.STC_CMD_LINEENDWRAP
+STC_CMD_LINEENDWRAPEXTEND = _stc.STC_CMD_LINEENDWRAPEXTEND
+STC_CMD_VCHOMEWRAP = _stc.STC_CMD_VCHOMEWRAP
+STC_CMD_VCHOMEWRAPEXTEND = _stc.STC_CMD_VCHOMEWRAPEXTEND
+STC_CMD_LINECOPY = _stc.STC_CMD_LINECOPY
+STC_CMD_WORDPARTLEFT = _stc.STC_CMD_WORDPARTLEFT
+STC_CMD_WORDPARTLEFTEXTEND = _stc.STC_CMD_WORDPARTLEFTEXTEND
+STC_CMD_WORDPARTRIGHT = _stc.STC_CMD_WORDPARTRIGHT
+STC_CMD_WORDPARTRIGHTEXTEND = _stc.STC_CMD_WORDPARTRIGHTEXTEND
+STC_CMD_DELLINELEFT = _stc.STC_CMD_DELLINELEFT
+STC_CMD_DELLINERIGHT = _stc.STC_CMD_DELLINERIGHT
+STC_CMD_PARADOWN = _stc.STC_CMD_PARADOWN
+STC_CMD_PARADOWNEXTEND = _stc.STC_CMD_PARADOWNEXTEND
+STC_CMD_PARAUP = _stc.STC_CMD_PARAUP
+STC_CMD_PARAUPEXTEND = _stc.STC_CMD_PARAUPEXTEND
+STC_CMD_LINEDOWNRECTEXTEND = _stc.STC_CMD_LINEDOWNRECTEXTEND
+STC_CMD_LINEUPRECTEXTEND = _stc.STC_CMD_LINEUPRECTEXTEND
+STC_CMD_CHARLEFTRECTEXTEND = _stc.STC_CMD_CHARLEFTRECTEXTEND
+STC_CMD_CHARRIGHTRECTEXTEND = _stc.STC_CMD_CHARRIGHTRECTEXTEND
+STC_CMD_HOMERECTEXTEND = _stc.STC_CMD_HOMERECTEXTEND
+STC_CMD_VCHOMERECTEXTEND = _stc.STC_CMD_VCHOMERECTEXTEND
+STC_CMD_LINEENDRECTEXTEND = _stc.STC_CMD_LINEENDRECTEXTEND
+STC_CMD_PAGEUPRECTEXTEND = _stc.STC_CMD_PAGEUPRECTEXTEND
+STC_CMD_PAGEDOWNRECTEXTEND = _stc.STC_CMD_PAGEDOWNRECTEXTEND
+STC_CMD_STUTTEREDPAGEUP = _stc.STC_CMD_STUTTEREDPAGEUP
+STC_CMD_STUTTEREDPAGEUPEXTEND = _stc.STC_CMD_STUTTEREDPAGEUPEXTEND
+STC_CMD_STUTTEREDPAGEDOWN = _stc.STC_CMD_STUTTEREDPAGEDOWN
+STC_CMD_STUTTEREDPAGEDOWNEXTEND = _stc.STC_CMD_STUTTEREDPAGEDOWNEXTEND
+STC_CMD_WORDLEFTEND = _stc.STC_CMD_WORDLEFTEND
+STC_CMD_WORDLEFTENDEXTEND = _stc.STC_CMD_WORDLEFTENDEXTEND
+STC_CMD_WORDRIGHTEND = _stc.STC_CMD_WORDRIGHTEND
+STC_CMD_WORDRIGHTENDEXTEND = _stc.STC_CMD_WORDRIGHTENDEXTEND
+STC_CMD_VERTICALCENTRECARET = _stc.STC_CMD_VERTICALCENTRECARET
+STC_CMD_MOVESELECTEDLINESUP = _stc.STC_CMD_MOVESELECTEDLINESUP
+STC_CMD_MOVESELECTEDLINESDOWN = _stc.STC_CMD_MOVESELECTEDLINESDOWN
+STC_CMD_SCROLLTOSTART = _stc.STC_CMD_SCROLLTOSTART
+STC_CMD_SCROLLTOEND = _stc.STC_CMD_SCROLLTOEND
+class StyledTextCtrl(_core.Control,_core.TextCtrlIface):
+ """Proxy of C++ StyledTextCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=STCNameStr) -> StyledTextCtrl
+ """
+ _stc.StyledTextCtrl_swiginit(self,_stc.new_StyledTextCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition,
+ Size size=DefaultSize, long style=0, String name=wxSTCNameStr) -> bool
+ """
+ return _stc.StyledTextCtrl_Create(*args, **kwargs)
+
+ def AddText(*args, **kwargs):
+ """
+ AddText(self, String text)
+
+ Add text to the document at current position.
+ """
+ return _stc.StyledTextCtrl_AddText(*args, **kwargs)
+
+ def AddStyledText(*args, **kwargs):
+ """
+ AddStyledText(self, wxMemoryBuffer data)
+
+ Add array of cells to document.
+ """
+ return _stc.StyledTextCtrl_AddStyledText(*args, **kwargs)
+
+ def InsertText(*args, **kwargs):
+ """
+ InsertText(self, int pos, String text)
+
+ Insert string at a position.
+ """
+ return _stc.StyledTextCtrl_InsertText(*args, **kwargs)
+
+ def ClearAll(*args, **kwargs):
+ """
+ ClearAll(self)
+
+ Delete all text in the document.
+ """
+ return _stc.StyledTextCtrl_ClearAll(*args, **kwargs)
+
+ def DeleteRange(*args, **kwargs):
+ """DeleteRange(self, int pos, int deleteLength)"""
+ return _stc.StyledTextCtrl_DeleteRange(*args, **kwargs)
+
+ def ClearDocumentStyle(*args, **kwargs):
+ """
+ ClearDocumentStyle(self)
+
+ Set all style bytes to 0, remove all folding information.
+ """
+ return _stc.StyledTextCtrl_ClearDocumentStyle(*args, **kwargs)
+
+ def GetLength(*args, **kwargs):
+ """
+ GetLength(self) -> int
+
+ Returns the number of bytes in the document.
+ """
+ return _stc.StyledTextCtrl_GetLength(*args, **kwargs)
+
+ def GetCharAt(*args, **kwargs):
+ """
+ GetCharAt(self, int pos) -> int
+
+ Returns the character byte at the position.
+ """
+ return _stc.StyledTextCtrl_GetCharAt(*args, **kwargs)
+
+ def GetCurrentPos(*args, **kwargs):
+ """
+ GetCurrentPos(self) -> int
+
+ Returns the position of the caret.
+ """
+ return _stc.StyledTextCtrl_GetCurrentPos(*args, **kwargs)
+
+ def GetAnchor(*args, **kwargs):
+ """
+ GetAnchor(self) -> int
+
+ Returns the position of the opposite end of the selection to the caret.
+ """
+ return _stc.StyledTextCtrl_GetAnchor(*args, **kwargs)
+
+ def GetStyleAt(*args, **kwargs):
+ """
+ GetStyleAt(self, int pos) -> int
+
+ Returns the style byte at the position.
+ """
+ return _stc.StyledTextCtrl_GetStyleAt(*args, **kwargs)
+
+ def SetUndoCollection(*args, **kwargs):
+ """
+ SetUndoCollection(self, bool collectUndo)
+
+ Choose between collecting actions into the undo
+ history and discarding them.
+ """
+ return _stc.StyledTextCtrl_SetUndoCollection(*args, **kwargs)
+
+ def SetSavePoint(*args, **kwargs):
+ """
+ SetSavePoint(self)
+
+ Remember the current position in the undo history as the position
+ at which the document was saved.
+ """
+ return _stc.StyledTextCtrl_SetSavePoint(*args, **kwargs)
+
+ def GetStyledText(*args, **kwargs):
+ """
+ GetStyledText(self, int startPos, int endPos) -> wxMemoryBuffer
+
+ Retrieve a buffer of cells.
+ """
+ return _stc.StyledTextCtrl_GetStyledText(*args, **kwargs)
+
+ def MarkerLineFromHandle(*args, **kwargs):
+ """
+ MarkerLineFromHandle(self, int handle) -> int
+
+ Retrieve the line number at which a particular marker is located.
+ """
+ return _stc.StyledTextCtrl_MarkerLineFromHandle(*args, **kwargs)
+
+ def MarkerDeleteHandle(*args, **kwargs):
+ """
+ MarkerDeleteHandle(self, int handle)
+
+ Delete a marker.
+ """
+ return _stc.StyledTextCtrl_MarkerDeleteHandle(*args, **kwargs)
+
+ def GetUndoCollection(*args, **kwargs):
+ """
+ GetUndoCollection(self) -> bool
+
+ Is undo history being collected?
+ """
+ return _stc.StyledTextCtrl_GetUndoCollection(*args, **kwargs)
+
+ def GetViewWhiteSpace(*args, **kwargs):
+ """
+ GetViewWhiteSpace(self) -> int
+
+ Are white space characters currently visible?
+ Returns one of SCWS_* constants.
+ """
+ return _stc.StyledTextCtrl_GetViewWhiteSpace(*args, **kwargs)
+
+ def SetViewWhiteSpace(*args, **kwargs):
+ """
+ SetViewWhiteSpace(self, int viewWS)
+
+ Make white space characters invisible, always visible or visible outside indentation.
+ """
+ return _stc.StyledTextCtrl_SetViewWhiteSpace(*args, **kwargs)
+
+ def PositionFromPoint(*args, **kwargs):
+ """
+ PositionFromPoint(self, Point pt) -> int
+
+ Find the position from a point within the window.
+ """
+ return _stc.StyledTextCtrl_PositionFromPoint(*args, **kwargs)
+
+ def PositionFromPointClose(*args, **kwargs):
+ """
+ PositionFromPointClose(self, int x, int y) -> int
+
+ Find the position from a point within the window but return
+ INVALID_POSITION if not close to text.
+ """
+ return _stc.StyledTextCtrl_PositionFromPointClose(*args, **kwargs)
+
+ def GotoLine(*args, **kwargs):
+ """
+ GotoLine(self, int line)
+
+ Set caret to start of a line and ensure it is visible.
+ """
+ return _stc.StyledTextCtrl_GotoLine(*args, **kwargs)
+
+ def GotoPos(*args, **kwargs):
+ """
+ GotoPos(self, int pos)
+
+ Set caret to a position and ensure it is visible.
+ """
+ return _stc.StyledTextCtrl_GotoPos(*args, **kwargs)
+
+ def SetAnchor(*args, **kwargs):
+ """
+ SetAnchor(self, int posAnchor)
+
+ Set the selection anchor to a position. The anchor is the opposite
+ end of the selection from the caret.
+ """
+ return _stc.StyledTextCtrl_SetAnchor(*args, **kwargs)
+
+ def GetCurLine(*args, **kwargs):
+ """
+ GetCurLine(self) -> (text, pos)
+
+ Retrieve the text of the line containing the caret, and also theindex
+ of the caret on the line.
+ """
+ return _stc.StyledTextCtrl_GetCurLine(*args, **kwargs)
+
+ def GetEndStyled(*args, **kwargs):
+ """
+ GetEndStyled(self) -> int
+
+ Retrieve the position of the last correctly styled character.
+ """
+ return _stc.StyledTextCtrl_GetEndStyled(*args, **kwargs)
+
+ def ConvertEOLs(*args, **kwargs):
+ """
+ ConvertEOLs(self, int eolMode)
+
+ Convert all line endings in the document to one mode.
+ """
+ return _stc.StyledTextCtrl_ConvertEOLs(*args, **kwargs)
+
+ def GetEOLMode(*args, **kwargs):
+ """
+ GetEOLMode(self) -> int
+
+ Retrieve the current end of line mode - one of CRLF, CR, or LF.
+ """
+ return _stc.StyledTextCtrl_GetEOLMode(*args, **kwargs)
+
+ def SetEOLMode(*args, **kwargs):
+ """
+ SetEOLMode(self, int eolMode)
+
+ Set the current end of line mode.
+ """
+ return _stc.StyledTextCtrl_SetEOLMode(*args, **kwargs)
+
+ def StartStyling(*args, **kwargs):
+ """
+ StartStyling(self, int pos, int mask)
+
+ Set the current styling position to pos and the styling mask to mask.
+ The styling mask can be used to protect some bits in each styling byte from modification.
+ """
+ return _stc.StyledTextCtrl_StartStyling(*args, **kwargs)
+
+ def SetStyling(*args, **kwargs):
+ """
+ SetStyling(self, int length, int style)
+
+ Change style from current styling position for length characters to a style
+ and move the current styling position to after this newly styled segment.
+ """
+ return _stc.StyledTextCtrl_SetStyling(*args, **kwargs)
+
+ def GetBufferedDraw(*args, **kwargs):
+ """
+ GetBufferedDraw(self) -> bool
+
+ Is drawing done first into a buffer or direct to the screen?
+ """
+ return _stc.StyledTextCtrl_GetBufferedDraw(*args, **kwargs)
+
+ def SetBufferedDraw(*args, **kwargs):
+ """
+ SetBufferedDraw(self, bool buffered)
+
+ If drawing is buffered then each line of text is drawn into a bitmap buffer
+ before drawing it to the screen to avoid flicker.
+ """
+ return _stc.StyledTextCtrl_SetBufferedDraw(*args, **kwargs)
+
+ def SetTabWidth(*args, **kwargs):
+ """
+ SetTabWidth(self, int tabWidth)
+
+ Change the visible size of a tab to be a multiple of the width of a space character.
+ """
+ return _stc.StyledTextCtrl_SetTabWidth(*args, **kwargs)
+
+ def GetTabWidth(*args, **kwargs):
+ """
+ GetTabWidth(self) -> int
+
+ Retrieve the visible size of a tab.
+ """
+ return _stc.StyledTextCtrl_GetTabWidth(*args, **kwargs)
+
+ def SetCodePage(*args, **kwargs):
+ """
+ SetCodePage(self, int codePage)
+
+ Set the code page used to interpret the bytes of the document as characters.
+ """
+ return _stc.StyledTextCtrl_SetCodePage(*args, **kwargs)
+
+ def MarkerDefine(*args, **kwargs):
+ """
+ MarkerDefine(self, int markerNumber, int markerSymbol, Colour foreground=wxNullColour,
+ Colour background=wxNullColour)
+
+ Set the symbol used for a particular marker number,
+ and optionally the fore and background colours.
+ """
+ return _stc.StyledTextCtrl_MarkerDefine(*args, **kwargs)
+
+ def MarkerSetForeground(*args, **kwargs):
+ """
+ MarkerSetForeground(self, int markerNumber, Colour fore)
+
+ Set the foreground colour used for a particular marker number.
+ """
+ return _stc.StyledTextCtrl_MarkerSetForeground(*args, **kwargs)
+
+ def MarkerSetBackground(*args, **kwargs):
+ """
+ MarkerSetBackground(self, int markerNumber, Colour back)
+
+ Set the background colour used for a particular marker number.
+ """
+ return _stc.StyledTextCtrl_MarkerSetBackground(*args, **kwargs)
+
+ def MarkerSetBackgroundSelected(*args, **kwargs):
+ """MarkerSetBackgroundSelected(self, int markerNumber, Colour back)"""
+ return _stc.StyledTextCtrl_MarkerSetBackgroundSelected(*args, **kwargs)
+
+ def MarkerEnableHighlight(*args, **kwargs):
+ """MarkerEnableHighlight(self, bool enabled)"""
+ return _stc.StyledTextCtrl_MarkerEnableHighlight(*args, **kwargs)
+
+ def MarkerAdd(*args, **kwargs):
+ """
+ MarkerAdd(self, int line, int markerNumber) -> int
+
+ Add a marker to a line, returning an ID which can be used to find or delete the marker.
+ """
+ return _stc.StyledTextCtrl_MarkerAdd(*args, **kwargs)
+
+ def MarkerDelete(*args, **kwargs):
+ """
+ MarkerDelete(self, int line, int markerNumber)
+
+ Delete a marker from a line.
+ """
+ return _stc.StyledTextCtrl_MarkerDelete(*args, **kwargs)
+
+ def MarkerDeleteAll(*args, **kwargs):
+ """
+ MarkerDeleteAll(self, int markerNumber)
+
+ Delete all markers with a particular number from all lines.
+ """
+ return _stc.StyledTextCtrl_MarkerDeleteAll(*args, **kwargs)
+
+ def MarkerGet(*args, **kwargs):
+ """
+ MarkerGet(self, int line) -> int
+
+ Get a bit mask of all the markers set on a line.
+ """
+ return _stc.StyledTextCtrl_MarkerGet(*args, **kwargs)
+
+ def MarkerNext(*args, **kwargs):
+ """
+ MarkerNext(self, int lineStart, int markerMask) -> int
+
+ Find the next line after lineStart that includes a marker in mask.
+ """
+ return _stc.StyledTextCtrl_MarkerNext(*args, **kwargs)
+
+ def MarkerPrevious(*args, **kwargs):
+ """
+ MarkerPrevious(self, int lineStart, int markerMask) -> int
+
+ Find the previous line before lineStart that includes a marker in mask.
+ """
+ return _stc.StyledTextCtrl_MarkerPrevious(*args, **kwargs)
+
+ def MarkerDefineBitmap(*args, **kwargs):
+ """
+ MarkerDefineBitmap(self, int markerNumber, Bitmap bmp)
+
+ Define a marker from a bitmap
+ """
+ return _stc.StyledTextCtrl_MarkerDefineBitmap(*args, **kwargs)
+
+ def MarkerAddSet(*args, **kwargs):
+ """
+ MarkerAddSet(self, int line, int set)
+
+ Add a set of markers to a line.
+ """
+ return _stc.StyledTextCtrl_MarkerAddSet(*args, **kwargs)
+
+ def MarkerSetAlpha(*args, **kwargs):
+ """
+ MarkerSetAlpha(self, int markerNumber, int alpha)
+
+ Set the alpha used for a marker that is drawn in the text area, not the margin.
+ """
+ return _stc.StyledTextCtrl_MarkerSetAlpha(*args, **kwargs)
+
+ def SetMarginType(*args, **kwargs):
+ """
+ SetMarginType(self, int margin, int marginType)
+
+ Set a margin to be either numeric or symbolic.
+ """
+ return _stc.StyledTextCtrl_SetMarginType(*args, **kwargs)
+
+ def GetMarginType(*args, **kwargs):
+ """
+ GetMarginType(self, int margin) -> int
+
+ Retrieve the type of a margin.
+ """
+ return _stc.StyledTextCtrl_GetMarginType(*args, **kwargs)
+
+ def SetMarginWidth(*args, **kwargs):
+ """
+ SetMarginWidth(self, int margin, int pixelWidth)
+
+ Set the width of a margin to a width expressed in pixels.
+ """
+ return _stc.StyledTextCtrl_SetMarginWidth(*args, **kwargs)
+
+ def GetMarginWidth(*args, **kwargs):
+ """
+ GetMarginWidth(self, int margin) -> int
+
+ Retrieve the width of a margin in pixels.
+ """
+ return _stc.StyledTextCtrl_GetMarginWidth(*args, **kwargs)
+
+ def SetMarginMask(*args, **kwargs):
+ """
+ SetMarginMask(self, int margin, int mask)
+
+ Set a mask that determines which markers are displayed in a margin.
+ """
+ return _stc.StyledTextCtrl_SetMarginMask(*args, **kwargs)
+
+ def GetMarginMask(*args, **kwargs):
+ """
+ GetMarginMask(self, int margin) -> int
+
+ Retrieve the marker mask of a margin.
+ """
+ return _stc.StyledTextCtrl_GetMarginMask(*args, **kwargs)
+
+ def SetMarginSensitive(*args, **kwargs):
+ """
+ SetMarginSensitive(self, int margin, bool sensitive)
+
+ Make a margin sensitive or insensitive to mouse clicks.
+ """
+ return _stc.StyledTextCtrl_SetMarginSensitive(*args, **kwargs)
+
+ def GetMarginSensitive(*args, **kwargs):
+ """
+ GetMarginSensitive(self, int margin) -> bool
+
+ Retrieve the mouse click sensitivity of a margin.
+ """
+ return _stc.StyledTextCtrl_GetMarginSensitive(*args, **kwargs)
+
+ def SetMarginCursor(*args, **kwargs):
+ """SetMarginCursor(self, int margin, int cursor)"""
+ return _stc.StyledTextCtrl_SetMarginCursor(*args, **kwargs)
+
+ def GetMarginCursor(*args, **kwargs):
+ """GetMarginCursor(self, int margin) -> int"""
+ return _stc.StyledTextCtrl_GetMarginCursor(*args, **kwargs)
+
+ def StyleClearAll(*args, **kwargs):
+ """
+ StyleClearAll(self)
+
+ Clear all the styles and make equivalent to the global default style.
+ """
+ return _stc.StyledTextCtrl_StyleClearAll(*args, **kwargs)
+
+ def StyleSetForeground(*args, **kwargs):
+ """
+ StyleSetForeground(self, int style, Colour fore)
+
+ Set the foreground colour of a style.
+ """
+ return _stc.StyledTextCtrl_StyleSetForeground(*args, **kwargs)
+
+ def StyleSetBackground(*args, **kwargs):
+ """
+ StyleSetBackground(self, int style, Colour back)
+
+ Set the background colour of a style.
+ """
+ return _stc.StyledTextCtrl_StyleSetBackground(*args, **kwargs)
+
+ def StyleSetBold(*args, **kwargs):
+ """
+ StyleSetBold(self, int style, bool bold)
+
+ Set a style to be bold or not.
+ """
+ return _stc.StyledTextCtrl_StyleSetBold(*args, **kwargs)
+
+ def StyleSetItalic(*args, **kwargs):
+ """
+ StyleSetItalic(self, int style, bool italic)
+
+ Set a style to be italic or not.
+ """
+ return _stc.StyledTextCtrl_StyleSetItalic(*args, **kwargs)
+
+ def StyleSetSize(*args, **kwargs):
+ """
+ StyleSetSize(self, int style, int sizePoints)
+
+ Set the size of characters of a style.
+ """
+ return _stc.StyledTextCtrl_StyleSetSize(*args, **kwargs)
+
+ def StyleSetFaceName(*args, **kwargs):
+ """
+ StyleSetFaceName(self, int style, String fontName)
+
+ Set the font of a style.
+ """
+ return _stc.StyledTextCtrl_StyleSetFaceName(*args, **kwargs)
+
+ def StyleSetEOLFilled(*args, **kwargs):
+ """
+ StyleSetEOLFilled(self, int style, bool filled)
+
+ Set a style to have its end of line filled or not.
+ """
+ return _stc.StyledTextCtrl_StyleSetEOLFilled(*args, **kwargs)
+
+ def StyleResetDefault(*args, **kwargs):
+ """
+ StyleResetDefault(self)
+
+ Reset the default style to its state at startup
+ """
+ return _stc.StyledTextCtrl_StyleResetDefault(*args, **kwargs)
+
+ def StyleSetUnderline(*args, **kwargs):
+ """
+ StyleSetUnderline(self, int style, bool underline)
+
+ Set a style to be underlined or not.
+ """
+ return _stc.StyledTextCtrl_StyleSetUnderline(*args, **kwargs)
+
+ def StyleGetForeground(*args, **kwargs):
+ """
+ StyleGetForeground(self, int style) -> Colour
+
+ Get the foreground colour of a style.
+ """
+ return _stc.StyledTextCtrl_StyleGetForeground(*args, **kwargs)
+
+ def StyleGetBackground(*args, **kwargs):
+ """
+ StyleGetBackground(self, int style) -> Colour
+
+ Get the background colour of a style.
+ """
+ return _stc.StyledTextCtrl_StyleGetBackground(*args, **kwargs)
+
+ def StyleGetBold(*args, **kwargs):
+ """
+ StyleGetBold(self, int style) -> bool
+
+ Get is a style bold or not.
+ """
+ return _stc.StyledTextCtrl_StyleGetBold(*args, **kwargs)
+
+ def StyleGetItalic(*args, **kwargs):
+ """
+ StyleGetItalic(self, int style) -> bool
+
+ Get is a style italic or not.
+ """
+ return _stc.StyledTextCtrl_StyleGetItalic(*args, **kwargs)
+
+ def StyleGetSize(*args, **kwargs):
+ """
+ StyleGetSize(self, int style) -> int
+
+ Get the size of characters of a style.
+ """
+ return _stc.StyledTextCtrl_StyleGetSize(*args, **kwargs)
+
+ def StyleGetFaceName(*args, **kwargs):
+ """
+ StyleGetFaceName(self, int style) -> String
+
+ Get the font facename of a style
+ """
+ return _stc.StyledTextCtrl_StyleGetFaceName(*args, **kwargs)
+
+ def StyleGetEOLFilled(*args, **kwargs):
+ """
+ StyleGetEOLFilled(self, int style) -> bool
+
+ Get is a style to have its end of line filled or not.
+ """
+ return _stc.StyledTextCtrl_StyleGetEOLFilled(*args, **kwargs)
+
+ def StyleGetUnderline(*args, **kwargs):
+ """
+ StyleGetUnderline(self, int style) -> bool
+
+ Get is a style underlined or not.
+ """
+ return _stc.StyledTextCtrl_StyleGetUnderline(*args, **kwargs)
+
+ def StyleGetCase(*args, **kwargs):
+ """
+ StyleGetCase(self, int style) -> int
+
+ Get is a style mixed case, or to force upper or lower case.
+ """
+ return _stc.StyledTextCtrl_StyleGetCase(*args, **kwargs)
+
+ def StyleGetCharacterSet(*args, **kwargs):
+ """
+ StyleGetCharacterSet(self, int style) -> int
+
+ Get the character set of the font in a style.
+ """
+ return _stc.StyledTextCtrl_StyleGetCharacterSet(*args, **kwargs)
+
+ def StyleGetVisible(*args, **kwargs):
+ """
+ StyleGetVisible(self, int style) -> bool
+
+ Get is a style visible or not.
+ """
+ return _stc.StyledTextCtrl_StyleGetVisible(*args, **kwargs)
+
+ def StyleGetChangeable(*args, **kwargs):
+ """
+ StyleGetChangeable(self, int style) -> bool
+
+ Get is a style changeable or not (read only).
+ Experimental feature, currently buggy.
+ """
+ return _stc.StyledTextCtrl_StyleGetChangeable(*args, **kwargs)
+
+ def StyleGetHotSpot(*args, **kwargs):
+ """
+ StyleGetHotSpot(self, int style) -> bool
+
+ Get is a style a hotspot or not.
+ """
+ return _stc.StyledTextCtrl_StyleGetHotSpot(*args, **kwargs)
+
+ def StyleSetCase(*args, **kwargs):
+ """
+ StyleSetCase(self, int style, int caseForce)
+
+ Set a style to be mixed case, or to force upper or lower case.
+ """
+ return _stc.StyledTextCtrl_StyleSetCase(*args, **kwargs)
+
+ def StyleSetSizeFractional(*args, **kwargs):
+ """StyleSetSizeFractional(self, int style, int caseForce)"""
+ return _stc.StyledTextCtrl_StyleSetSizeFractional(*args, **kwargs)
+
+ def StyleGetSizeFractional(*args, **kwargs):
+ """StyleGetSizeFractional(self, int style) -> int"""
+ return _stc.StyledTextCtrl_StyleGetSizeFractional(*args, **kwargs)
+
+ def StyleSetWeight(*args, **kwargs):
+ """StyleSetWeight(self, int style, int weight)"""
+ return _stc.StyledTextCtrl_StyleSetWeight(*args, **kwargs)
+
+ def StyleGetWeight(*args, **kwargs):
+ """StyleGetWeight(self, int style) -> int"""
+ return _stc.StyledTextCtrl_StyleGetWeight(*args, **kwargs)
+
+ def StyleSetHotSpot(*args, **kwargs):
+ """
+ StyleSetHotSpot(self, int style, bool hotspot)
+
+ Set a style to be a hotspot or not.
+ """
+ return _stc.StyledTextCtrl_StyleSetHotSpot(*args, **kwargs)
+
+ def SetSelForeground(*args, **kwargs):
+ """
+ SetSelForeground(self, bool useSetting, Colour fore)
+
+ Set the foreground colour of the main and additional selections and whether to use this setting.
+ """
+ return _stc.StyledTextCtrl_SetSelForeground(*args, **kwargs)
+
+ def SetSelBackground(*args, **kwargs):
+ """
+ SetSelBackground(self, bool useSetting, Colour back)
+
+ Set the background colour of the main and additional selections and whether to use this setting.
+ """
+ return _stc.StyledTextCtrl_SetSelBackground(*args, **kwargs)
+
+ def GetSelAlpha(*args, **kwargs):
+ """
+ GetSelAlpha(self) -> int
+
+ Get the alpha of the selection.
+ """
+ return _stc.StyledTextCtrl_GetSelAlpha(*args, **kwargs)
+
+ def SetSelAlpha(*args, **kwargs):
+ """
+ SetSelAlpha(self, int alpha)
+
+ Set the alpha of the selection.
+ """
+ return _stc.StyledTextCtrl_SetSelAlpha(*args, **kwargs)
+
+ def GetSelEOLFilled(*args, **kwargs):
+ """
+ GetSelEOLFilled(self) -> bool
+
+ Is the selection end of line filled?
+ """
+ return _stc.StyledTextCtrl_GetSelEOLFilled(*args, **kwargs)
+
+ def SetSelEOLFilled(*args, **kwargs):
+ """
+ SetSelEOLFilled(self, bool filled)
+
+ Set the selection to have its end of line filled or not.
+ """
+ return _stc.StyledTextCtrl_SetSelEOLFilled(*args, **kwargs)
+
+ def SetCaretForeground(*args, **kwargs):
+ """
+ SetCaretForeground(self, Colour fore)
+
+ Set the foreground colour of the caret.
+ """
+ return _stc.StyledTextCtrl_SetCaretForeground(*args, **kwargs)
+
+ def CmdKeyAssign(*args, **kwargs):
+ """
+ CmdKeyAssign(self, int key, int modifiers, int cmd)
+
+ When key+modifier combination km is pressed perform msg.
+ """
+ return _stc.StyledTextCtrl_CmdKeyAssign(*args, **kwargs)
+
+ def CmdKeyClear(*args, **kwargs):
+ """
+ CmdKeyClear(self, int key, int modifiers)
+
+ When key+modifier combination km is pressed do nothing.
+ """
+ return _stc.StyledTextCtrl_CmdKeyClear(*args, **kwargs)
+
+ def CmdKeyClearAll(*args, **kwargs):
+ """
+ CmdKeyClearAll(self)
+
+ Drop all key mappings.
+ """
+ return _stc.StyledTextCtrl_CmdKeyClearAll(*args, **kwargs)
+
+ def SetStyleBytes(*args, **kwargs):
+ """
+ SetStyleBytes(self, int length, char styleBytes)
+
+ Set the styles for a segment of the document.
+ """
+ return _stc.StyledTextCtrl_SetStyleBytes(*args, **kwargs)
+
+ def StyleSetVisible(*args, **kwargs):
+ """
+ StyleSetVisible(self, int style, bool visible)
+
+ Set a style to be visible or not.
+ """
+ return _stc.StyledTextCtrl_StyleSetVisible(*args, **kwargs)
+
+ def GetCaretPeriod(*args, **kwargs):
+ """
+ GetCaretPeriod(self) -> int
+
+ Get the time in milliseconds that the caret is on and off.
+ """
+ return _stc.StyledTextCtrl_GetCaretPeriod(*args, **kwargs)
+
+ def SetCaretPeriod(*args, **kwargs):
+ """
+ SetCaretPeriod(self, int periodMilliseconds)
+
+ Get the time in milliseconds that the caret is on and off. 0 = steady on.
+ """
+ return _stc.StyledTextCtrl_SetCaretPeriod(*args, **kwargs)
+
+ def SetWordChars(*args, **kwargs):
+ """
+ SetWordChars(self, String characters)
+
+ Set the set of characters making up words for when moving or selecting by word.
+ First sets defaults like SetCharsDefault.
+ """
+ return _stc.StyledTextCtrl_SetWordChars(*args, **kwargs)
+
+ def GetWordChars(*args, **kwargs):
+ """GetWordChars(self) -> String"""
+ return _stc.StyledTextCtrl_GetWordChars(*args, **kwargs)
+
+ def BeginUndoAction(*args, **kwargs):
+ """
+ BeginUndoAction(self)
+
+ Start a sequence of actions that is undone and redone as a unit.
+ May be nested.
+ """
+ return _stc.StyledTextCtrl_BeginUndoAction(*args, **kwargs)
+
+ def EndUndoAction(*args, **kwargs):
+ """
+ EndUndoAction(self)
+
+ End a sequence of actions that is undone and redone as a unit.
+ """
+ return _stc.StyledTextCtrl_EndUndoAction(*args, **kwargs)
+
+ def IndicatorSetStyle(*args, **kwargs):
+ """
+ IndicatorSetStyle(self, int indic, int style)
+
+ Set an indicator to plain, squiggle or TT.
+ """
+ return _stc.StyledTextCtrl_IndicatorSetStyle(*args, **kwargs)
+
+ def IndicatorGetStyle(*args, **kwargs):
+ """
+ IndicatorGetStyle(self, int indic) -> int
+
+ Retrieve the style of an indicator.
+ """
+ return _stc.StyledTextCtrl_IndicatorGetStyle(*args, **kwargs)
+
+ def IndicatorSetForeground(*args, **kwargs):
+ """
+ IndicatorSetForeground(self, int indic, Colour fore)
+
+ Set the foreground colour of an indicator.
+ """
+ return _stc.StyledTextCtrl_IndicatorSetForeground(*args, **kwargs)
+
+ def IndicatorGetForeground(*args, **kwargs):
+ """
+ IndicatorGetForeground(self, int indic) -> Colour
+
+ Retrieve the foreground colour of an indicator.
+ """
+ return _stc.StyledTextCtrl_IndicatorGetForeground(*args, **kwargs)
+
+ def IndicatorSetUnder(*args, **kwargs):
+ """
+ IndicatorSetUnder(self, int indic, bool under)
+
+ Set an indicator to draw under text or over(default).
+ """
+ return _stc.StyledTextCtrl_IndicatorSetUnder(*args, **kwargs)
+
+ def IndicatorGetUnder(*args, **kwargs):
+ """
+ IndicatorGetUnder(self, int indic) -> bool
+
+ Retrieve whether indicator drawn under or over text.
+ """
+ return _stc.StyledTextCtrl_IndicatorGetUnder(*args, **kwargs)
+
+ def SetWhitespaceForeground(*args, **kwargs):
+ """
+ SetWhitespaceForeground(self, bool useSetting, Colour fore)
+
+ Set the foreground colour of all whitespace and whether to use this setting.
+ """
+ return _stc.StyledTextCtrl_SetWhitespaceForeground(*args, **kwargs)
+
+ def SetWhitespaceBackground(*args, **kwargs):
+ """
+ SetWhitespaceBackground(self, bool useSetting, Colour back)
+
+ Set the background colour of all whitespace and whether to use this setting.
+ """
+ return _stc.StyledTextCtrl_SetWhitespaceBackground(*args, **kwargs)
+
+ def SetWhitespaceSize(*args, **kwargs):
+ """
+ SetWhitespaceSize(self, int size)
+
+ Set the size of the dots used to mark space characters.
+ """
+ return _stc.StyledTextCtrl_SetWhitespaceSize(*args, **kwargs)
+
+ def GetWhitespaceSize(*args, **kwargs):
+ """
+ GetWhitespaceSize(self) -> int
+
+ Get the size of the dots used to mark space characters.
+ """
+ return _stc.StyledTextCtrl_GetWhitespaceSize(*args, **kwargs)
+
+ def SetStyleBits(*args, **kwargs):
+ """
+ SetStyleBits(self, int bits)
+
+ Divide each styling byte into lexical class bits (default: 5) and indicator
+ bits (default: 3). If a lexer requires more than 32 lexical states, then this
+ is used to expand the possible states.
+ """
+ return _stc.StyledTextCtrl_SetStyleBits(*args, **kwargs)
+
+ def GetStyleBits(*args, **kwargs):
+ """
+ GetStyleBits(self) -> int
+
+ Retrieve number of bits in style bytes used to hold the lexical state.
+ """
+ return _stc.StyledTextCtrl_GetStyleBits(*args, **kwargs)
+
+ def SetLineState(*args, **kwargs):
+ """
+ SetLineState(self, int line, int state)
+
+ Used to hold extra styling information for each line.
+ """
+ return _stc.StyledTextCtrl_SetLineState(*args, **kwargs)
+
+ def GetLineState(*args, **kwargs):
+ """
+ GetLineState(self, int line) -> int
+
+ Retrieve the extra styling information for a line.
+ """
+ return _stc.StyledTextCtrl_GetLineState(*args, **kwargs)
+
+ def GetMaxLineState(*args, **kwargs):
+ """
+ GetMaxLineState(self) -> int
+
+ Retrieve the last line number that has line state.
+ """
+ return _stc.StyledTextCtrl_GetMaxLineState(*args, **kwargs)
+
+ def GetCaretLineVisible(*args, **kwargs):
+ """
+ GetCaretLineVisible(self) -> bool
+
+ Is the background of the line containing the caret in a different colour?
+ """
+ return _stc.StyledTextCtrl_GetCaretLineVisible(*args, **kwargs)
+
+ def SetCaretLineVisible(*args, **kwargs):
+ """
+ SetCaretLineVisible(self, bool show)
+
+ Display the background of the line containing the caret in a different colour.
+ """
+ return _stc.StyledTextCtrl_SetCaretLineVisible(*args, **kwargs)
+
+ def GetCaretLineBackground(*args, **kwargs):
+ """
+ GetCaretLineBackground(self) -> Colour
+
+ Get the colour of the background of the line containing the caret.
+ """
+ return _stc.StyledTextCtrl_GetCaretLineBackground(*args, **kwargs)
+
+ def SetCaretLineBackground(*args, **kwargs):
+ """
+ SetCaretLineBackground(self, Colour back)
+
+ Set the colour of the background of the line containing the caret.
+ """
+ return _stc.StyledTextCtrl_SetCaretLineBackground(*args, **kwargs)
+
+ def StyleSetChangeable(*args, **kwargs):
+ """
+ StyleSetChangeable(self, int style, bool changeable)
+
+ Set a style to be changeable or not (read only).
+ Experimental feature, currently buggy.
+ """
+ return _stc.StyledTextCtrl_StyleSetChangeable(*args, **kwargs)
+
+ def AutoCompShow(*args, **kwargs):
+ """
+ AutoCompShow(self, int lenEntered, String itemList)
+
+ Display a auto-completion list.
+ The lenEntered parameter indicates how many characters before
+ the caret should be used to provide context.
+ """
+ return _stc.StyledTextCtrl_AutoCompShow(*args, **kwargs)
+
+ def AutoCompCancel(*args, **kwargs):
+ """
+ AutoCompCancel(self)
+
+ Remove the auto-completion list from the screen.
+ """
+ return _stc.StyledTextCtrl_AutoCompCancel(*args, **kwargs)
+
+ def AutoCompActive(*args, **kwargs):
+ """
+ AutoCompActive(self) -> bool
+
+ Is there an auto-completion list visible?
+ """
+ return _stc.StyledTextCtrl_AutoCompActive(*args, **kwargs)
+
+ def AutoCompPosStart(*args, **kwargs):
+ """
+ AutoCompPosStart(self) -> int
+
+ Retrieve the position of the caret when the auto-completion list was displayed.
+ """
+ return _stc.StyledTextCtrl_AutoCompPosStart(*args, **kwargs)
+
+ def AutoCompComplete(*args, **kwargs):
+ """
+ AutoCompComplete(self)
+
+ User has selected an item so remove the list and insert the selection.
+ """
+ return _stc.StyledTextCtrl_AutoCompComplete(*args, **kwargs)
+
+ def AutoCompStops(*args, **kwargs):
+ """
+ AutoCompStops(self, String characterSet)
+
+ Define a set of character that when typed cancel the auto-completion list.
+ """
+ return _stc.StyledTextCtrl_AutoCompStops(*args, **kwargs)
+
+ def AutoCompSetSeparator(*args, **kwargs):
+ """
+ AutoCompSetSeparator(self, int separatorCharacter)
+
+ Change the separator character in the string setting up an auto-completion list.
+ Default is space but can be changed if items contain space.
+ """
+ return _stc.StyledTextCtrl_AutoCompSetSeparator(*args, **kwargs)
+
+ def AutoCompGetSeparator(*args, **kwargs):
+ """
+ AutoCompGetSeparator(self) -> int
+
+ Retrieve the auto-completion list separator character.
+ """
+ return _stc.StyledTextCtrl_AutoCompGetSeparator(*args, **kwargs)
+
+ def AutoCompSelect(*args, **kwargs):
+ """
+ AutoCompSelect(self, String text)
+
+ Select the item in the auto-completion list that starts with a string.
+ """
+ return _stc.StyledTextCtrl_AutoCompSelect(*args, **kwargs)
+
+ def AutoCompSetCancelAtStart(*args, **kwargs):
+ """
+ AutoCompSetCancelAtStart(self, bool cancel)
+
+ Should the auto-completion list be cancelled if the user backspaces to a
+ position before where the box was created.
+ """
+ return _stc.StyledTextCtrl_AutoCompSetCancelAtStart(*args, **kwargs)
+
+ def AutoCompGetCancelAtStart(*args, **kwargs):
+ """
+ AutoCompGetCancelAtStart(self) -> bool
+
+ Retrieve whether auto-completion cancelled by backspacing before start.
+ """
+ return _stc.StyledTextCtrl_AutoCompGetCancelAtStart(*args, **kwargs)
+
+ def AutoCompSetFillUps(*args, **kwargs):
+ """
+ AutoCompSetFillUps(self, String characterSet)
+
+ Define a set of characters that when typed will cause the autocompletion to
+ choose the selected item.
+ """
+ return _stc.StyledTextCtrl_AutoCompSetFillUps(*args, **kwargs)
+
+ def AutoCompSetChooseSingle(*args, **kwargs):
+ """
+ AutoCompSetChooseSingle(self, bool chooseSingle)
+
+ Should a single item auto-completion list automatically choose the item.
+ """
+ return _stc.StyledTextCtrl_AutoCompSetChooseSingle(*args, **kwargs)
+
+ def AutoCompGetChooseSingle(*args, **kwargs):
+ """
+ AutoCompGetChooseSingle(self) -> bool
+
+ Retrieve whether a single item auto-completion list automatically choose the item.
+ """
+ return _stc.StyledTextCtrl_AutoCompGetChooseSingle(*args, **kwargs)
+
+ def AutoCompSetIgnoreCase(*args, **kwargs):
+ """
+ AutoCompSetIgnoreCase(self, bool ignoreCase)
+
+ Set whether case is significant when performing auto-completion searches.
+ """
+ return _stc.StyledTextCtrl_AutoCompSetIgnoreCase(*args, **kwargs)
+
+ def AutoCompGetIgnoreCase(*args, **kwargs):
+ """
+ AutoCompGetIgnoreCase(self) -> bool
+
+ Retrieve state of ignore case flag.
+ """
+ return _stc.StyledTextCtrl_AutoCompGetIgnoreCase(*args, **kwargs)
+
+ def UserListShow(*args, **kwargs):
+ """
+ UserListShow(self, int listType, String itemList)
+
+ Display a list of strings and send notification when user chooses one.
+ """
+ return _stc.StyledTextCtrl_UserListShow(*args, **kwargs)
+
+ def AutoCompSetAutoHide(*args, **kwargs):
+ """
+ AutoCompSetAutoHide(self, bool autoHide)
+
+ Set whether or not autocompletion is hidden automatically when nothing matches.
+ """
+ return _stc.StyledTextCtrl_AutoCompSetAutoHide(*args, **kwargs)
+
+ def AutoCompGetAutoHide(*args, **kwargs):
+ """
+ AutoCompGetAutoHide(self) -> bool
+
+ Retrieve whether or not autocompletion is hidden automatically when nothing matches.
+ """
+ return _stc.StyledTextCtrl_AutoCompGetAutoHide(*args, **kwargs)
+
+ def AutoCompSetDropRestOfWord(*args, **kwargs):
+ """
+ AutoCompSetDropRestOfWord(self, bool dropRestOfWord)
+
+ Set whether or not autocompletion deletes any word characters
+ after the inserted text upon completion.
+ """
+ return _stc.StyledTextCtrl_AutoCompSetDropRestOfWord(*args, **kwargs)
+
+ def AutoCompGetDropRestOfWord(*args, **kwargs):
+ """
+ AutoCompGetDropRestOfWord(self) -> bool
+
+ Retrieve whether or not autocompletion deletes any word characters
+ after the inserted text upon completion.
+ """
+ return _stc.StyledTextCtrl_AutoCompGetDropRestOfWord(*args, **kwargs)
+
+ def RegisterImage(*args, **kwargs):
+ """
+ RegisterImage(self, int type, Bitmap bmp)
+
+ Register an image for use in autocompletion lists.
+ """
+ return _stc.StyledTextCtrl_RegisterImage(*args, **kwargs)
+
+ def ClearRegisteredImages(*args, **kwargs):
+ """
+ ClearRegisteredImages(self)
+
+ Clear all the registered images.
+ """
+ return _stc.StyledTextCtrl_ClearRegisteredImages(*args, **kwargs)
+
+ def AutoCompGetTypeSeparator(*args, **kwargs):
+ """
+ AutoCompGetTypeSeparator(self) -> int
+
+ Retrieve the auto-completion list type-separator character.
+ """
+ return _stc.StyledTextCtrl_AutoCompGetTypeSeparator(*args, **kwargs)
+
+ def AutoCompSetTypeSeparator(*args, **kwargs):
+ """
+ AutoCompSetTypeSeparator(self, int separatorCharacter)
+
+ Change the type-separator character in the string setting up an auto-completion list.
+ Default is '?' but can be changed if items contain '?'.
+ """
+ return _stc.StyledTextCtrl_AutoCompSetTypeSeparator(*args, **kwargs)
+
+ def AutoCompSetMaxWidth(*args, **kwargs):
+ """
+ AutoCompSetMaxWidth(self, int characterCount)
+
+ Set the maximum width, in characters, of auto-completion and user lists.
+ Set to 0 to autosize to fit longest item, which is the default.
+ """
+ return _stc.StyledTextCtrl_AutoCompSetMaxWidth(*args, **kwargs)
+
+ def AutoCompGetMaxWidth(*args, **kwargs):
+ """
+ AutoCompGetMaxWidth(self) -> int
+
+ Get the maximum width, in characters, of auto-completion and user lists.
+ """
+ return _stc.StyledTextCtrl_AutoCompGetMaxWidth(*args, **kwargs)
+
+ def AutoCompSetMaxHeight(*args, **kwargs):
+ """
+ AutoCompSetMaxHeight(self, int rowCount)
+
+ Set the maximum height, in rows, of auto-completion and user lists.
+ The default is 5 rows.
+ """
+ return _stc.StyledTextCtrl_AutoCompSetMaxHeight(*args, **kwargs)
+
+ def AutoCompGetMaxHeight(*args, **kwargs):
+ """
+ AutoCompGetMaxHeight(self) -> int
+
+ Set the maximum height, in rows, of auto-completion and user lists.
+ """
+ return _stc.StyledTextCtrl_AutoCompGetMaxHeight(*args, **kwargs)
+
+ def SetIndent(*args, **kwargs):
+ """
+ SetIndent(self, int indentSize)
+
+ Set the number of spaces used for one level of indentation.
+ """
+ return _stc.StyledTextCtrl_SetIndent(*args, **kwargs)
+
+ def GetIndent(*args, **kwargs):
+ """
+ GetIndent(self) -> int
+
+ Retrieve indentation size.
+ """
+ return _stc.StyledTextCtrl_GetIndent(*args, **kwargs)
+
+ def SetUseTabs(*args, **kwargs):
+ """
+ SetUseTabs(self, bool useTabs)
+
+ Indentation will only use space characters if useTabs is false, otherwise
+ it will use a combination of tabs and spaces.
+ """
+ return _stc.StyledTextCtrl_SetUseTabs(*args, **kwargs)
+
+ def GetUseTabs(*args, **kwargs):
+ """
+ GetUseTabs(self) -> bool
+
+ Retrieve whether tabs will be used in indentation.
+ """
+ return _stc.StyledTextCtrl_GetUseTabs(*args, **kwargs)
+
+ def SetLineIndentation(*args, **kwargs):
+ """
+ SetLineIndentation(self, int line, int indentSize)
+
+ Change the indentation of a line to a number of columns.
+ """
+ return _stc.StyledTextCtrl_SetLineIndentation(*args, **kwargs)
+
+ def GetLineIndentation(*args, **kwargs):
+ """
+ GetLineIndentation(self, int line) -> int
+
+ Retrieve the number of columns that a line is indented.
+ """
+ return _stc.StyledTextCtrl_GetLineIndentation(*args, **kwargs)
+
+ def GetLineIndentPosition(*args, **kwargs):
+ """
+ GetLineIndentPosition(self, int line) -> int
+
+ Retrieve the position before the first non indentation character on a line.
+ """
+ return _stc.StyledTextCtrl_GetLineIndentPosition(*args, **kwargs)
+
+ def GetColumn(*args, **kwargs):
+ """
+ GetColumn(self, int pos) -> int
+
+ Retrieve the column number of a position, taking tab width into account.
+ """
+ return _stc.StyledTextCtrl_GetColumn(*args, **kwargs)
+
+ def CountCharacters(*args, **kwargs):
+ """CountCharacters(self, int startPos, int endPos) -> int"""
+ return _stc.StyledTextCtrl_CountCharacters(*args, **kwargs)
+
+ def SetUseHorizontalScrollBar(*args, **kwargs):
+ """
+ SetUseHorizontalScrollBar(self, bool show)
+
+ Show or hide the horizontal scroll bar.
+ """
+ return _stc.StyledTextCtrl_SetUseHorizontalScrollBar(*args, **kwargs)
+
+ def GetUseHorizontalScrollBar(*args, **kwargs):
+ """
+ GetUseHorizontalScrollBar(self) -> bool
+
+ Is the horizontal scroll bar visible?
+ """
+ return _stc.StyledTextCtrl_GetUseHorizontalScrollBar(*args, **kwargs)
+
+ def SetIndentationGuides(*args, **kwargs):
+ """
+ SetIndentationGuides(self, int indentView)
+
+ Show or hide indentation guides.
+ """
+ return _stc.StyledTextCtrl_SetIndentationGuides(*args, **kwargs)
+
+ def GetIndentationGuides(*args, **kwargs):
+ """
+ GetIndentationGuides(self) -> int
+
+ Are the indentation guides visible?
+ """
+ return _stc.StyledTextCtrl_GetIndentationGuides(*args, **kwargs)
+
+ def SetHighlightGuide(*args, **kwargs):
+ """
+ SetHighlightGuide(self, int column)
+
+ Set the highlighted indentation guide column.
+ 0 = no highlighted guide.
+ """
+ return _stc.StyledTextCtrl_SetHighlightGuide(*args, **kwargs)
+
+ def GetHighlightGuide(*args, **kwargs):
+ """
+ GetHighlightGuide(self) -> int
+
+ Get the highlighted indentation guide column.
+ """
+ return _stc.StyledTextCtrl_GetHighlightGuide(*args, **kwargs)
+
+ def GetLineEndPosition(*args, **kwargs):
+ """
+ GetLineEndPosition(self, int line) -> int
+
+ Get the position after the last visible characters on a line.
+ """
+ return _stc.StyledTextCtrl_GetLineEndPosition(*args, **kwargs)
+
+ def GetCodePage(*args, **kwargs):
+ """
+ GetCodePage(self) -> int
+
+ Get the code page used to interpret the bytes of the document as characters.
+ """
+ return _stc.StyledTextCtrl_GetCodePage(*args, **kwargs)
+
+ def GetCaretForeground(*args, **kwargs):
+ """
+ GetCaretForeground(self) -> Colour
+
+ Get the foreground colour of the caret.
+ """
+ return _stc.StyledTextCtrl_GetCaretForeground(*args, **kwargs)
+
+ def GetReadOnly(*args, **kwargs):
+ """
+ GetReadOnly(self) -> bool
+
+ In read-only mode?
+ """
+ return _stc.StyledTextCtrl_GetReadOnly(*args, **kwargs)
+
+ def SetCurrentPos(*args, **kwargs):
+ """
+ SetCurrentPos(self, int pos)
+
+ Sets the position of the caret.
+ """
+ return _stc.StyledTextCtrl_SetCurrentPos(*args, **kwargs)
+
+ def SetSelectionStart(*args, **kwargs):
+ """
+ SetSelectionStart(self, int pos)
+
+ Sets the position that starts the selection - this becomes the anchor.
+ """
+ return _stc.StyledTextCtrl_SetSelectionStart(*args, **kwargs)
+
+ def GetSelectionStart(*args, **kwargs):
+ """
+ GetSelectionStart(self) -> int
+
+ Returns the position at the start of the selection.
+ """
+ return _stc.StyledTextCtrl_GetSelectionStart(*args, **kwargs)
+
+ def SetSelectionEnd(*args, **kwargs):
+ """
+ SetSelectionEnd(self, int pos)
+
+ Sets the position that ends the selection - this becomes the currentPosition.
+ """
+ return _stc.StyledTextCtrl_SetSelectionEnd(*args, **kwargs)
+
+ def GetSelectionEnd(*args, **kwargs):
+ """
+ GetSelectionEnd(self) -> int
+
+ Returns the position at the end of the selection.
+ """
+ return _stc.StyledTextCtrl_GetSelectionEnd(*args, **kwargs)
+
+ def SetEmptySelection(*args, **kwargs):
+ """SetEmptySelection(self, int pos)"""
+ return _stc.StyledTextCtrl_SetEmptySelection(*args, **kwargs)
+
+ def SetPrintMagnification(*args, **kwargs):
+ """
+ SetPrintMagnification(self, int magnification)
+
+ Sets the print magnification added to the point size of each style for printing.
+ """
+ return _stc.StyledTextCtrl_SetPrintMagnification(*args, **kwargs)
+
+ def GetPrintMagnification(*args, **kwargs):
+ """
+ GetPrintMagnification(self) -> int
+
+ Returns the print magnification.
+ """
+ return _stc.StyledTextCtrl_GetPrintMagnification(*args, **kwargs)
+
+ def SetPrintColourMode(*args, **kwargs):
+ """
+ SetPrintColourMode(self, int mode)
+
+ Modify colours when printing for clearer printed text.
+ """
+ return _stc.StyledTextCtrl_SetPrintColourMode(*args, **kwargs)
+
+ def GetPrintColourMode(*args, **kwargs):
+ """
+ GetPrintColourMode(self) -> int
+
+ Returns the print colour mode.
+ """
+ return _stc.StyledTextCtrl_GetPrintColourMode(*args, **kwargs)
+
+ def FindText(*args, **kwargs):
+ """
+ FindText(self, int minPos, int maxPos, String text, int flags=0) -> int
+
+ Find some text in the document.
+ """
+ return _stc.StyledTextCtrl_FindText(*args, **kwargs)
+
+ def FormatRange(*args, **kwargs):
+ """
+ FormatRange(self, bool doDraw, int startPos, int endPos, DC draw, DC target,
+ Rect renderRect, Rect pageRect) -> int
+
+ On Windows, will draw the document into a display context such as a printer.
+ """
+ return _stc.StyledTextCtrl_FormatRange(*args, **kwargs)
+
+ def GetFirstVisibleLine(*args, **kwargs):
+ """
+ GetFirstVisibleLine(self) -> int
+
+ Retrieve the display line at the top of the display.
+ """
+ return _stc.StyledTextCtrl_GetFirstVisibleLine(*args, **kwargs)
+
+ def GetLine(*args, **kwargs):
+ """
+ GetLine(self, int line) -> String
+
+ Retrieve the contents of a line.
+ """
+ return _stc.StyledTextCtrl_GetLine(*args, **kwargs)
+
+ def GetLineCount(*args, **kwargs):
+ """
+ GetLineCount(self) -> int
+
+ Returns the number of lines in the document. There is always at least one.
+ """
+ return _stc.StyledTextCtrl_GetLineCount(*args, **kwargs)
+
+ def SetMarginLeft(*args, **kwargs):
+ """
+ SetMarginLeft(self, int pixelWidth)
+
+ Sets the size in pixels of the left margin.
+ """
+ return _stc.StyledTextCtrl_SetMarginLeft(*args, **kwargs)
+
+ def GetMarginLeft(*args, **kwargs):
+ """
+ GetMarginLeft(self) -> int
+
+ Returns the size in pixels of the left margin.
+ """
+ return _stc.StyledTextCtrl_GetMarginLeft(*args, **kwargs)
+
+ def SetMarginRight(*args, **kwargs):
+ """
+ SetMarginRight(self, int pixelWidth)
+
+ Sets the size in pixels of the right margin.
+ """
+ return _stc.StyledTextCtrl_SetMarginRight(*args, **kwargs)
+
+ def GetMarginRight(*args, **kwargs):
+ """
+ GetMarginRight(self) -> int
+
+ Returns the size in pixels of the right margin.
+ """
+ return _stc.StyledTextCtrl_GetMarginRight(*args, **kwargs)
+
+ def GetModify(*args, **kwargs):
+ """
+ GetModify(self) -> bool
+
+ Is the document different from when it was last saved?
+ """
+ return _stc.StyledTextCtrl_GetModify(*args, **kwargs)
+
+ def GetSelectedText(*args, **kwargs):
+ """
+ GetSelectedText(self) -> String
+
+ Retrieve the selected text.
+ """
+ return _stc.StyledTextCtrl_GetSelectedText(*args, **kwargs)
+
+ def GetTextRange(*args, **kwargs):
+ """
+ GetTextRange(self, int startPos, int endPos) -> String
+
+ Retrieve a range of text.
+ """
+ return _stc.StyledTextCtrl_GetTextRange(*args, **kwargs)
+
+ def HideSelection(*args, **kwargs):
+ """
+ HideSelection(self, bool normal)
+
+ Draw the selection in normal style or with selection highlighted.
+ """
+ return _stc.StyledTextCtrl_HideSelection(*args, **kwargs)
+
+ def LineFromPosition(*args, **kwargs):
+ """
+ LineFromPosition(self, int pos) -> int
+
+ Retrieve the line containing a position.
+ """
+ return _stc.StyledTextCtrl_LineFromPosition(*args, **kwargs)
+
+ def PositionFromLine(*args, **kwargs):
+ """
+ PositionFromLine(self, int line) -> int
+
+ Retrieve the position at the start of a line.
+ """
+ return _stc.StyledTextCtrl_PositionFromLine(*args, **kwargs)
+
+ def LineScroll(*args, **kwargs):
+ """
+ LineScroll(self, int columns, int lines)
+
+ Scroll horizontally and vertically.
+ """
+ return _stc.StyledTextCtrl_LineScroll(*args, **kwargs)
+
+ def EnsureCaretVisible(*args, **kwargs):
+ """
+ EnsureCaretVisible(self)
+
+ Ensure the caret is visible.
+ """
+ return _stc.StyledTextCtrl_EnsureCaretVisible(*args, **kwargs)
+
+ def ReplaceSelection(*args, **kwargs):
+ """
+ ReplaceSelection(self, String text)
+
+ Replace the selected text with the argument text.
+ """
+ return _stc.StyledTextCtrl_ReplaceSelection(*args, **kwargs)
+
+ def SetReadOnly(*args, **kwargs):
+ """
+ SetReadOnly(self, bool readOnly)
+
+ Set to read only or read write.
+ """
+ return _stc.StyledTextCtrl_SetReadOnly(*args, **kwargs)
+
+ def EmptyUndoBuffer(*args, **kwargs):
+ """
+ EmptyUndoBuffer(self)
+
+ Delete the undo history.
+ """
+ return _stc.StyledTextCtrl_EmptyUndoBuffer(*args, **kwargs)
+
+ def SetText(*args, **kwargs):
+ """
+ SetText(self, String text)
+
+ Replace the contents of the document with the argument text.
+ """
+ return _stc.StyledTextCtrl_SetText(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """
+ GetText(self) -> String
+
+ Retrieve all the text in the document.
+ """
+ return _stc.StyledTextCtrl_GetText(*args, **kwargs)
+
+ def GetTextLength(*args, **kwargs):
+ """
+ GetTextLength(self) -> int
+
+ Retrieve the number of characters in the document.
+ """
+ return _stc.StyledTextCtrl_GetTextLength(*args, **kwargs)
+
+ def SetOvertype(*args, **kwargs):
+ """
+ SetOvertype(self, bool overtype)
+
+ Set to overtype (true) or insert mode.
+ """
+ return _stc.StyledTextCtrl_SetOvertype(*args, **kwargs)
+
+ def GetOvertype(*args, **kwargs):
+ """
+ GetOvertype(self) -> bool
+
+ Returns true if overtype mode is active otherwise false is returned.
+ """
+ return _stc.StyledTextCtrl_GetOvertype(*args, **kwargs)
+
+ def SetCaretWidth(*args, **kwargs):
+ """
+ SetCaretWidth(self, int pixelWidth)
+
+ Set the width of the insert mode caret.
+ """
+ return _stc.StyledTextCtrl_SetCaretWidth(*args, **kwargs)
+
+ def GetCaretWidth(*args, **kwargs):
+ """
+ GetCaretWidth(self) -> int
+
+ Returns the width of the insert mode caret.
+ """
+ return _stc.StyledTextCtrl_GetCaretWidth(*args, **kwargs)
+
+ def SetTargetStart(*args, **kwargs):
+ """
+ SetTargetStart(self, int pos)
+
+ Sets the position that starts the target which is used for updating the
+ document without affecting the scroll position.
+ """
+ return _stc.StyledTextCtrl_SetTargetStart(*args, **kwargs)
+
+ def GetTargetStart(*args, **kwargs):
+ """
+ GetTargetStart(self) -> int
+
+ Get the position that starts the target.
+ """
+ return _stc.StyledTextCtrl_GetTargetStart(*args, **kwargs)
+
+ def SetTargetEnd(*args, **kwargs):
+ """
+ SetTargetEnd(self, int pos)
+
+ Sets the position that ends the target which is used for updating the
+ document without affecting the scroll position.
+ """
+ return _stc.StyledTextCtrl_SetTargetEnd(*args, **kwargs)
+
+ def GetTargetEnd(*args, **kwargs):
+ """
+ GetTargetEnd(self) -> int
+
+ Get the position that ends the target.
+ """
+ return _stc.StyledTextCtrl_GetTargetEnd(*args, **kwargs)
+
+ def ReplaceTarget(*args, **kwargs):
+ """
+ ReplaceTarget(self, String text) -> int
+
+ Replace the target text with the argument text.
+ Text is counted so it can contain NULs.
+ Returns the length of the replacement text.
+ """
+ return _stc.StyledTextCtrl_ReplaceTarget(*args, **kwargs)
+
+ def ReplaceTargetRE(*args, **kwargs):
+ """
+ ReplaceTargetRE(self, String text) -> int
+
+ Replace the target text with the argument text after \d processing.
+ Text is counted so it can contain NULs.
+ Looks for \d where d is between 1 and 9 and replaces these with the strings
+ matched in the last search operation which were surrounded by \( and \).
+ Returns the length of the replacement text including any change
+ caused by processing the \d patterns.
+ """
+ return _stc.StyledTextCtrl_ReplaceTargetRE(*args, **kwargs)
+
+ def SearchInTarget(*args, **kwargs):
+ """
+ SearchInTarget(self, String text) -> int
+
+ Search for a counted string in the target and set the target to the found
+ range. Text is counted so it can contain NULs.
+ Returns length of range or -1 for failure in which case target is not moved.
+ """
+ return _stc.StyledTextCtrl_SearchInTarget(*args, **kwargs)
+
+ def SetSearchFlags(*args, **kwargs):
+ """
+ SetSearchFlags(self, int flags)
+
+ Set the search flags used by SearchInTarget.
+ """
+ return _stc.StyledTextCtrl_SetSearchFlags(*args, **kwargs)
+
+ def GetSearchFlags(*args, **kwargs):
+ """
+ GetSearchFlags(self) -> int
+
+ Get the search flags used by SearchInTarget.
+ """
+ return _stc.StyledTextCtrl_GetSearchFlags(*args, **kwargs)
+
+ def CallTipShow(*args, **kwargs):
+ """
+ CallTipShow(self, int pos, String definition)
+
+ Show a call tip containing a definition near position pos.
+ """
+ return _stc.StyledTextCtrl_CallTipShow(*args, **kwargs)
+
+ def CallTipCancel(*args, **kwargs):
+ """
+ CallTipCancel(self)
+
+ Remove the call tip from the screen.
+ """
+ return _stc.StyledTextCtrl_CallTipCancel(*args, **kwargs)
+
+ def CallTipActive(*args, **kwargs):
+ """
+ CallTipActive(self) -> bool
+
+ Is there an active call tip?
+ """
+ return _stc.StyledTextCtrl_CallTipActive(*args, **kwargs)
+
+ def CallTipPosAtStart(*args, **kwargs):
+ """
+ CallTipPosAtStart(self) -> int
+
+ Retrieve the position where the caret was before displaying the call tip.
+ """
+ return _stc.StyledTextCtrl_CallTipPosAtStart(*args, **kwargs)
+
+ def CallTipSetHighlight(*args, **kwargs):
+ """
+ CallTipSetHighlight(self, int start, int end)
+
+ Highlight a segment of the definition.
+ """
+ return _stc.StyledTextCtrl_CallTipSetHighlight(*args, **kwargs)
+
+ def CallTipSetBackground(*args, **kwargs):
+ """
+ CallTipSetBackground(self, Colour back)
+
+ Set the background colour for the call tip.
+ """
+ return _stc.StyledTextCtrl_CallTipSetBackground(*args, **kwargs)
+
+ def CallTipSetForeground(*args, **kwargs):
+ """
+ CallTipSetForeground(self, Colour fore)
+
+ Set the foreground colour for the call tip.
+ """
+ return _stc.StyledTextCtrl_CallTipSetForeground(*args, **kwargs)
+
+ def CallTipSetForegroundHighlight(*args, **kwargs):
+ """
+ CallTipSetForegroundHighlight(self, Colour fore)
+
+ Set the foreground colour for the highlighted part of the call tip.
+ """
+ return _stc.StyledTextCtrl_CallTipSetForegroundHighlight(*args, **kwargs)
+
+ def CallTipUseStyle(*args, **kwargs):
+ """
+ CallTipUseStyle(self, int tabSize)
+
+ Enable use of STYLE_CALLTIP and set call tip tab size in pixels.
+ """
+ return _stc.StyledTextCtrl_CallTipUseStyle(*args, **kwargs)
+
+ def CallTipSetPosition(*args, **kwargs):
+ """CallTipSetPosition(self, bool above)"""
+ return _stc.StyledTextCtrl_CallTipSetPosition(*args, **kwargs)
+
+ def VisibleFromDocLine(*args, **kwargs):
+ """
+ VisibleFromDocLine(self, int line) -> int
+
+ Find the display line of a document line taking hidden lines into account.
+ """
+ return _stc.StyledTextCtrl_VisibleFromDocLine(*args, **kwargs)
+
+ def DocLineFromVisible(*args, **kwargs):
+ """
+ DocLineFromVisible(self, int lineDisplay) -> int
+
+ Find the document line of a display line taking hidden lines into account.
+ """
+ return _stc.StyledTextCtrl_DocLineFromVisible(*args, **kwargs)
+
+ def WrapCount(*args, **kwargs):
+ """
+ WrapCount(self, int line) -> int
+
+ The number of display lines needed to wrap a document line
+ """
+ return _stc.StyledTextCtrl_WrapCount(*args, **kwargs)
+
+ def SetFoldLevel(*args, **kwargs):
+ """
+ SetFoldLevel(self, int line, int level)
+
+ Set the fold level of a line.
+ This encodes an integer level along with flags indicating whether the
+ line is a header and whether it is effectively white space.
+ """
+ return _stc.StyledTextCtrl_SetFoldLevel(*args, **kwargs)
+
+ def GetFoldLevel(*args, **kwargs):
+ """
+ GetFoldLevel(self, int line) -> int
+
+ Retrieve the fold level of a line.
+ """
+ return _stc.StyledTextCtrl_GetFoldLevel(*args, **kwargs)
+
+ def GetLastChild(*args, **kwargs):
+ """
+ GetLastChild(self, int line, int level) -> int
+
+ Find the last child line of a header line.
+ """
+ return _stc.StyledTextCtrl_GetLastChild(*args, **kwargs)
+
+ def GetFoldParent(*args, **kwargs):
+ """
+ GetFoldParent(self, int line) -> int
+
+ Find the parent line of a child line.
+ """
+ return _stc.StyledTextCtrl_GetFoldParent(*args, **kwargs)
+
+ def ShowLines(*args, **kwargs):
+ """
+ ShowLines(self, int lineStart, int lineEnd)
+
+ Make a range of lines visible.
+ """
+ return _stc.StyledTextCtrl_ShowLines(*args, **kwargs)
+
+ def HideLines(*args, **kwargs):
+ """
+ HideLines(self, int lineStart, int lineEnd)
+
+ Make a range of lines invisible.
+ """
+ return _stc.StyledTextCtrl_HideLines(*args, **kwargs)
+
+ def GetLineVisible(*args, **kwargs):
+ """
+ GetLineVisible(self, int line) -> bool
+
+ Is a line visible?
+ """
+ return _stc.StyledTextCtrl_GetLineVisible(*args, **kwargs)
+
+ def GetAllLinesVisible(*args, **kwargs):
+ """GetAllLinesVisible(self) -> bool"""
+ return _stc.StyledTextCtrl_GetAllLinesVisible(*args, **kwargs)
+
+ def SetFoldExpanded(*args, **kwargs):
+ """
+ SetFoldExpanded(self, int line, bool expanded)
+
+ Show the children of a header line.
+ """
+ return _stc.StyledTextCtrl_SetFoldExpanded(*args, **kwargs)
+
+ def GetFoldExpanded(*args, **kwargs):
+ """
+ GetFoldExpanded(self, int line) -> bool
+
+ Is a header line expanded?
+ """
+ return _stc.StyledTextCtrl_GetFoldExpanded(*args, **kwargs)
+
+ def ToggleFold(*args, **kwargs):
+ """
+ ToggleFold(self, int line)
+
+ Switch a header line between expanded and contracted.
+ """
+ return _stc.StyledTextCtrl_ToggleFold(*args, **kwargs)
+
+ def EnsureVisible(*args, **kwargs):
+ """
+ EnsureVisible(self, int line)
+
+ Ensure a particular line is visible by expanding any header line hiding it.
+ """
+ return _stc.StyledTextCtrl_EnsureVisible(*args, **kwargs)
+
+ def SetFoldFlags(*args, **kwargs):
+ """
+ SetFoldFlags(self, int flags)
+
+ Set some style options for folding.
+ """
+ return _stc.StyledTextCtrl_SetFoldFlags(*args, **kwargs)
+
+ def EnsureVisibleEnforcePolicy(*args, **kwargs):
+ """
+ EnsureVisibleEnforcePolicy(self, int line)
+
+ Ensure a particular line is visible by expanding any header line hiding it.
+ Use the currently set visibility policy to determine which range to display.
+ """
+ return _stc.StyledTextCtrl_EnsureVisibleEnforcePolicy(*args, **kwargs)
+
+ def SetTabIndents(*args, **kwargs):
+ """
+ SetTabIndents(self, bool tabIndents)
+
+ Sets whether a tab pressed when caret is within indentation indents.
+ """
+ return _stc.StyledTextCtrl_SetTabIndents(*args, **kwargs)
+
+ def GetTabIndents(*args, **kwargs):
+ """
+ GetTabIndents(self) -> bool
+
+ Does a tab pressed when caret is within indentation indent?
+ """
+ return _stc.StyledTextCtrl_GetTabIndents(*args, **kwargs)
+
+ def SetBackSpaceUnIndents(*args, **kwargs):
+ """
+ SetBackSpaceUnIndents(self, bool bsUnIndents)
+
+ Sets whether a backspace pressed when caret is within indentation unindents.
+ """
+ return _stc.StyledTextCtrl_SetBackSpaceUnIndents(*args, **kwargs)
+
+ def GetBackSpaceUnIndents(*args, **kwargs):
+ """
+ GetBackSpaceUnIndents(self) -> bool
+
+ Does a backspace pressed when caret is within indentation unindent?
+ """
+ return _stc.StyledTextCtrl_GetBackSpaceUnIndents(*args, **kwargs)
+
+ def SetMouseDwellTime(*args, **kwargs):
+ """
+ SetMouseDwellTime(self, int periodMilliseconds)
+
+ Sets the time the mouse must sit still to generate a mouse dwell event.
+ """
+ return _stc.StyledTextCtrl_SetMouseDwellTime(*args, **kwargs)
+
+ def GetMouseDwellTime(*args, **kwargs):
+ """
+ GetMouseDwellTime(self) -> int
+
+ Retrieve the time the mouse must sit still to generate a mouse dwell event.
+ """
+ return _stc.StyledTextCtrl_GetMouseDwellTime(*args, **kwargs)
+
+ def WordStartPosition(*args, **kwargs):
+ """
+ WordStartPosition(self, int pos, bool onlyWordCharacters) -> int
+
+ Get position of start of word.
+ """
+ return _stc.StyledTextCtrl_WordStartPosition(*args, **kwargs)
+
+ def WordEndPosition(*args, **kwargs):
+ """
+ WordEndPosition(self, int pos, bool onlyWordCharacters) -> int
+
+ Get position of end of word.
+ """
+ return _stc.StyledTextCtrl_WordEndPosition(*args, **kwargs)
+
+ def SetWrapMode(*args, **kwargs):
+ """
+ SetWrapMode(self, int mode)
+
+ Sets whether text is word wrapped.
+ """
+ return _stc.StyledTextCtrl_SetWrapMode(*args, **kwargs)
+
+ def GetWrapMode(*args, **kwargs):
+ """
+ GetWrapMode(self) -> int
+
+ Retrieve whether text is word wrapped.
+ """
+ return _stc.StyledTextCtrl_GetWrapMode(*args, **kwargs)
+
+ def SetWrapVisualFlags(*args, **kwargs):
+ """
+ SetWrapVisualFlags(self, int wrapVisualFlags)
+
+ Set the display mode of visual flags for wrapped lines.
+ """
+ return _stc.StyledTextCtrl_SetWrapVisualFlags(*args, **kwargs)
+
+ def GetWrapVisualFlags(*args, **kwargs):
+ """
+ GetWrapVisualFlags(self) -> int
+
+ Retrive the display mode of visual flags for wrapped lines.
+ """
+ return _stc.StyledTextCtrl_GetWrapVisualFlags(*args, **kwargs)
+
+ def SetWrapVisualFlagsLocation(*args, **kwargs):
+ """
+ SetWrapVisualFlagsLocation(self, int wrapVisualFlagsLocation)
+
+ Set the location of visual flags for wrapped lines.
+ """
+ return _stc.StyledTextCtrl_SetWrapVisualFlagsLocation(*args, **kwargs)
+
+ def GetWrapVisualFlagsLocation(*args, **kwargs):
+ """
+ GetWrapVisualFlagsLocation(self) -> int
+
+ Retrive the location of visual flags for wrapped lines.
+ """
+ return _stc.StyledTextCtrl_GetWrapVisualFlagsLocation(*args, **kwargs)
+
+ def SetWrapStartIndent(*args, **kwargs):
+ """
+ SetWrapStartIndent(self, int indent)
+
+ Set the start indent for wrapped lines.
+ """
+ return _stc.StyledTextCtrl_SetWrapStartIndent(*args, **kwargs)
+
+ def GetWrapStartIndent(*args, **kwargs):
+ """
+ GetWrapStartIndent(self) -> int
+
+ Retrive the start indent for wrapped lines.
+ """
+ return _stc.StyledTextCtrl_GetWrapStartIndent(*args, **kwargs)
+
+ def SetWrapIndentMode(*args, **kwargs):
+ """
+ SetWrapIndentMode(self, int mode)
+
+ Sets how wrapped sublines are placed. Default is fixed.
+ """
+ return _stc.StyledTextCtrl_SetWrapIndentMode(*args, **kwargs)
+
+ def GetWrapIndentMode(*args, **kwargs):
+ """
+ GetWrapIndentMode(self) -> int
+
+ Retrieve how wrapped sublines are placed. Default is fixed.
+ """
+ return _stc.StyledTextCtrl_GetWrapIndentMode(*args, **kwargs)
+
+ def SetLayoutCache(*args, **kwargs):
+ """
+ SetLayoutCache(self, int mode)
+
+ Sets the degree of caching of layout information.
+ """
+ return _stc.StyledTextCtrl_SetLayoutCache(*args, **kwargs)
+
+ def GetLayoutCache(*args, **kwargs):
+ """
+ GetLayoutCache(self) -> int
+
+ Retrieve the degree of caching of layout information.
+ """
+ return _stc.StyledTextCtrl_GetLayoutCache(*args, **kwargs)
+
+ def SetScrollWidth(*args, **kwargs):
+ """
+ SetScrollWidth(self, int pixelWidth)
+
+ Sets the document width assumed for scrolling.
+ """
+ return _stc.StyledTextCtrl_SetScrollWidth(*args, **kwargs)
+
+ def GetScrollWidth(*args, **kwargs):
+ """
+ GetScrollWidth(self) -> int
+
+ Retrieve the document width assumed for scrolling.
+ """
+ return _stc.StyledTextCtrl_GetScrollWidth(*args, **kwargs)
+
+ def SetScrollWidthTracking(*args, **kwargs):
+ """
+ SetScrollWidthTracking(self, bool tracking)
+
+ Sets whether the maximum width line displayed is used to set scroll width.
+ """
+ return _stc.StyledTextCtrl_SetScrollWidthTracking(*args, **kwargs)
+
+ def GetScrollWidthTracking(*args, **kwargs):
+ """
+ GetScrollWidthTracking(self) -> bool
+
+ Retrieve whether the scroll width tracks wide lines.
+ """
+ return _stc.StyledTextCtrl_GetScrollWidthTracking(*args, **kwargs)
+
+ def TextWidth(*args, **kwargs):
+ """
+ TextWidth(self, int style, String text) -> int
+
+ Measure the pixel width of some text in a particular style.
+ NUL terminated text argument.
+ Does not handle tab or control characters.
+ """
+ return _stc.StyledTextCtrl_TextWidth(*args, **kwargs)
+
+ def SetEndAtLastLine(*args, **kwargs):
+ """
+ SetEndAtLastLine(self, bool endAtLastLine)
+
+ Sets the scroll range so that maximum scroll position has
+ the last line at the bottom of the view (default).
+ Setting this to false allows scrolling one page below the last line.
+ """
+ return _stc.StyledTextCtrl_SetEndAtLastLine(*args, **kwargs)
+
+ def GetEndAtLastLine(*args, **kwargs):
+ """
+ GetEndAtLastLine(self) -> bool
+
+ Retrieve whether the maximum scroll position has the last
+ line at the bottom of the view.
+ """
+ return _stc.StyledTextCtrl_GetEndAtLastLine(*args, **kwargs)
+
+ def TextHeight(*args, **kwargs):
+ """
+ TextHeight(self, int line) -> int
+
+ Retrieve the height of a particular line of text in pixels.
+ """
+ return _stc.StyledTextCtrl_TextHeight(*args, **kwargs)
+
+ def SetUseVerticalScrollBar(*args, **kwargs):
+ """
+ SetUseVerticalScrollBar(self, bool show)
+
+ Show or hide the vertical scroll bar.
+ """
+ return _stc.StyledTextCtrl_SetUseVerticalScrollBar(*args, **kwargs)
+
+ def GetUseVerticalScrollBar(*args, **kwargs):
+ """
+ GetUseVerticalScrollBar(self) -> bool
+
+ Is the vertical scroll bar visible?
+ """
+ return _stc.StyledTextCtrl_GetUseVerticalScrollBar(*args, **kwargs)
+
+ def GetTwoPhaseDraw(*args, **kwargs):
+ """
+ GetTwoPhaseDraw(self) -> bool
+
+ Is drawing done in two phases with backgrounds drawn before foregrounds?
+ """
+ return _stc.StyledTextCtrl_GetTwoPhaseDraw(*args, **kwargs)
+
+ def SetTwoPhaseDraw(*args, **kwargs):
+ """
+ SetTwoPhaseDraw(self, bool twoPhase)
+
+ In twoPhaseDraw mode, drawing is performed in two phases, first the background
+ and then the foreground. This avoids chopping off characters that overlap the next run.
+ """
+ return _stc.StyledTextCtrl_SetTwoPhaseDraw(*args, **kwargs)
+
+ def SetFirstVisibleLine(*args, **kwargs):
+ """
+ SetFirstVisibleLine(self, int lineDisplay)
+
+ Scroll so that a display line is at the top of the display.
+ """
+ return _stc.StyledTextCtrl_SetFirstVisibleLine(*args, **kwargs)
+
+ def SetMultiPaste(*args, **kwargs):
+ """SetMultiPaste(self, int multiPaste)"""
+ return _stc.StyledTextCtrl_SetMultiPaste(*args, **kwargs)
+
+ def GetMultiPaste(*args, **kwargs):
+ """GetMultiPaste(self) -> int"""
+ return _stc.StyledTextCtrl_GetMultiPaste(*args, **kwargs)
+
+ def GetTag(*args, **kwargs):
+ """GetTag(self, int tagNumber) -> String"""
+ return _stc.StyledTextCtrl_GetTag(*args, **kwargs)
+
+ def TargetFromSelection(*args, **kwargs):
+ """
+ TargetFromSelection(self)
+
+ Make the target range start and end be the same as the selection range start and end.
+ """
+ return _stc.StyledTextCtrl_TargetFromSelection(*args, **kwargs)
+
+ def LinesJoin(*args, **kwargs):
+ """
+ LinesJoin(self)
+
+ Join the lines in the target.
+ """
+ return _stc.StyledTextCtrl_LinesJoin(*args, **kwargs)
+
+ def LinesSplit(*args, **kwargs):
+ """
+ LinesSplit(self, int pixelWidth)
+
+ Split the lines in the target into lines that are less wide than pixelWidth
+ where possible.
+ """
+ return _stc.StyledTextCtrl_LinesSplit(*args, **kwargs)
+
+ def SetFoldMarginColour(*args, **kwargs):
+ """
+ SetFoldMarginColour(self, bool useSetting, Colour back)
+
+ Set the colours used as a chequerboard pattern in the fold margin
+ """
+ return _stc.StyledTextCtrl_SetFoldMarginColour(*args, **kwargs)
+
+ def SetFoldMarginHiColour(*args, **kwargs):
+ """SetFoldMarginHiColour(self, bool useSetting, Colour fore)"""
+ return _stc.StyledTextCtrl_SetFoldMarginHiColour(*args, **kwargs)
+
+ def LineDown(*args, **kwargs):
+ """
+ LineDown(self)
+
+ Move caret down one line.
+ """
+ return _stc.StyledTextCtrl_LineDown(*args, **kwargs)
+
+
+ def LineDownExtend(*args, **kwargs):
+ """
+ LineDownExtend(self)
+
+ Move caret down one line extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_LineDownExtend(*args, **kwargs)
+
+ def LineUp(*args, **kwargs):
+ """
+ LineUp(self)
+
+ Move caret up one line.
+ """
+ return _stc.StyledTextCtrl_LineUp(*args, **kwargs)
+
+
+ def LineUpExtend(*args, **kwargs):
+ """
+ LineUpExtend(self)
+
+ Move caret up one line extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_LineUpExtend(*args, **kwargs)
+
+ def CharLeft(*args, **kwargs):
+ """
+ CharLeft(self)
+
+ Move caret left one character.
+ """
+ return _stc.StyledTextCtrl_CharLeft(*args, **kwargs)
+
+ def CharLeftExtend(*args, **kwargs):
+ """
+ CharLeftExtend(self)
+
+ Move caret left one character extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_CharLeftExtend(*args, **kwargs)
+
+ def CharRight(*args, **kwargs):
+ """
+ CharRight(self)
+
+ Move caret right one character.
+ """
+ return _stc.StyledTextCtrl_CharRight(*args, **kwargs)
+
+ def CharRightExtend(*args, **kwargs):
+ """
+ CharRightExtend(self)
+
+ Move caret right one character extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_CharRightExtend(*args, **kwargs)
+
+ def WordLeft(*args, **kwargs):
+ """
+ WordLeft(self)
+
+ Move caret left one word.
+ """
+ return _stc.StyledTextCtrl_WordLeft(*args, **kwargs)
+
+ def WordLeftExtend(*args, **kwargs):
+ """
+ WordLeftExtend(self)
+
+ Move caret left one word extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_WordLeftExtend(*args, **kwargs)
+
+ def WordRight(*args, **kwargs):
+ """
+ WordRight(self)
+
+ Move caret right one word.
+ """
+ return _stc.StyledTextCtrl_WordRight(*args, **kwargs)
+
+ def WordRightExtend(*args, **kwargs):
+ """
+ WordRightExtend(self)
+
+ Move caret right one word extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_WordRightExtend(*args, **kwargs)
+
+ def Home(*args, **kwargs):
+ """
+ Home(self)
+
+ Move caret to first position on line.
+ """
+ return _stc.StyledTextCtrl_Home(*args, **kwargs)
+
+ def HomeExtend(*args, **kwargs):
+ """
+ HomeExtend(self)
+
+ Move caret to first position on line extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_HomeExtend(*args, **kwargs)
+
+ def LineEnd(*args, **kwargs):
+ """
+ LineEnd(self)
+
+ Move caret to last position on line.
+ """
+ return _stc.StyledTextCtrl_LineEnd(*args, **kwargs)
+
+ def LineEndExtend(*args, **kwargs):
+ """
+ LineEndExtend(self)
+
+ Move caret to last position on line extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_LineEndExtend(*args, **kwargs)
+
+ def DocumentStart(*args, **kwargs):
+ """
+ DocumentStart(self)
+
+ Move caret to first position in document.
+ """
+ return _stc.StyledTextCtrl_DocumentStart(*args, **kwargs)
+
+ def DocumentStartExtend(*args, **kwargs):
+ """
+ DocumentStartExtend(self)
+
+ Move caret to first position in document extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_DocumentStartExtend(*args, **kwargs)
+
+ def DocumentEnd(*args, **kwargs):
+ """
+ DocumentEnd(self)
+
+ Move caret to last position in document.
+ """
+ return _stc.StyledTextCtrl_DocumentEnd(*args, **kwargs)
+
+ def DocumentEndExtend(*args, **kwargs):
+ """
+ DocumentEndExtend(self)
+
+ Move caret to last position in document extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_DocumentEndExtend(*args, **kwargs)
+
+ def PageUp(*args, **kwargs):
+ """
+ PageUp(self)
+
+ Move caret one page up.
+ """
+ return _stc.StyledTextCtrl_PageUp(*args, **kwargs)
+
+
+ def PageUpExtend(*args, **kwargs):
+ """
+ PageUpExtend(self)
+
+ Move caret one page up extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_PageUpExtend(*args, **kwargs)
+
+ def PageDown(*args, **kwargs):
+ """
+ PageDown(self)
+
+ Move caret one page down.
+ """
+ return _stc.StyledTextCtrl_PageDown(*args, **kwargs)
+
+
+ def PageDownExtend(*args, **kwargs):
+ """
+ PageDownExtend(self)
+
+ Move caret one page down extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_PageDownExtend(*args, **kwargs)
+
+ def EditToggleOvertype(*args, **kwargs):
+ """
+ EditToggleOvertype(self)
+
+ Switch from insert to overtype mode or the reverse.
+ """
+ return _stc.StyledTextCtrl_EditToggleOvertype(*args, **kwargs)
+
+ def Cancel(*args, **kwargs):
+ """
+ Cancel(self)
+
+ Cancel any modes such as call tip or auto-completion list display.
+ """
+ return _stc.StyledTextCtrl_Cancel(*args, **kwargs)
+
+ def DeleteBack(*args, **kwargs):
+ """
+ DeleteBack(self)
+
+ Delete the selection or if no selection, the character before the caret.
+ """
+ return _stc.StyledTextCtrl_DeleteBack(*args, **kwargs)
+
+ def Tab(*args, **kwargs):
+ """
+ Tab(self)
+
+ If selection is empty or all on one line replace the selection with a tab character.
+ If more than one line selected, indent the lines.
+ """
+ return _stc.StyledTextCtrl_Tab(*args, **kwargs)
+
+ def BackTab(*args, **kwargs):
+ """
+ BackTab(self)
+
+ Dedent the selected lines.
+ """
+ return _stc.StyledTextCtrl_BackTab(*args, **kwargs)
+
+ def NewLine(*args, **kwargs):
+ """
+ NewLine(self)
+
+ Insert a new line, may use a CRLF, CR or LF depending on EOL mode.
+ """
+ return _stc.StyledTextCtrl_NewLine(*args, **kwargs)
+
+ def FormFeed(*args, **kwargs):
+ """
+ FormFeed(self)
+
+ Insert a Form Feed character.
+ """
+ return _stc.StyledTextCtrl_FormFeed(*args, **kwargs)
+
+ def VCHome(*args, **kwargs):
+ """
+ VCHome(self)
+
+ Move caret to before first visible character on line.
+ If already there move to first character on line.
+ """
+ return _stc.StyledTextCtrl_VCHome(*args, **kwargs)
+
+ def VCHomeExtend(*args, **kwargs):
+ """
+ VCHomeExtend(self)
+
+ Like VCHome but extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_VCHomeExtend(*args, **kwargs)
+
+ def ZoomIn(*args, **kwargs):
+ """
+ ZoomIn(self)
+
+ Magnify the displayed text by increasing the sizes by 1 point.
+ """
+ return _stc.StyledTextCtrl_ZoomIn(*args, **kwargs)
+
+ def ZoomOut(*args, **kwargs):
+ """
+ ZoomOut(self)
+
+ Make the displayed text smaller by decreasing the sizes by 1 point.
+ """
+ return _stc.StyledTextCtrl_ZoomOut(*args, **kwargs)
+
+ def DelWordLeft(*args, **kwargs):
+ """
+ DelWordLeft(self)
+
+ Delete the word to the left of the caret.
+ """
+ return _stc.StyledTextCtrl_DelWordLeft(*args, **kwargs)
+
+ def DelWordRight(*args, **kwargs):
+ """
+ DelWordRight(self)
+
+ Delete the word to the right of the caret.
+ """
+ return _stc.StyledTextCtrl_DelWordRight(*args, **kwargs)
+
+ def DelWordRightEnd(*args, **kwargs):
+ """
+ DelWordRightEnd(self)
+
+ Delete the word to the right of the caret, but not the trailing non-word characters.
+ """
+ return _stc.StyledTextCtrl_DelWordRightEnd(*args, **kwargs)
+
+ def LineCut(*args, **kwargs):
+ """
+ LineCut(self)
+
+ Cut the line containing the caret.
+ """
+ return _stc.StyledTextCtrl_LineCut(*args, **kwargs)
+
+ def LineDelete(*args, **kwargs):
+ """
+ LineDelete(self)
+
+ Delete the line containing the caret.
+ """
+ return _stc.StyledTextCtrl_LineDelete(*args, **kwargs)
+
+ def LineTranspose(*args, **kwargs):
+ """
+ LineTranspose(self)
+
+ Switch the current line with the previous.
+ """
+ return _stc.StyledTextCtrl_LineTranspose(*args, **kwargs)
+
+ def LineDuplicate(*args, **kwargs):
+ """
+ LineDuplicate(self)
+
+ Duplicate the current line.
+ """
+ return _stc.StyledTextCtrl_LineDuplicate(*args, **kwargs)
+
+ def LowerCase(*args, **kwargs):
+ """
+ LowerCase(self)
+
+ Transform the selection to lower case.
+ """
+ return _stc.StyledTextCtrl_LowerCase(*args, **kwargs)
+
+ def UpperCase(*args, **kwargs):
+ """
+ UpperCase(self)
+
+ Transform the selection to upper case.
+ """
+ return _stc.StyledTextCtrl_UpperCase(*args, **kwargs)
+
+ def LineScrollDown(*args, **kwargs):
+ """
+ LineScrollDown(self)
+
+ Scroll the document down, keeping the caret visible.
+ """
+ return _stc.StyledTextCtrl_LineScrollDown(*args, **kwargs)
+
+ def LineScrollUp(*args, **kwargs):
+ """
+ LineScrollUp(self)
+
+ Scroll the document up, keeping the caret visible.
+ """
+ return _stc.StyledTextCtrl_LineScrollUp(*args, **kwargs)
+
+ def DeleteBackNotLine(*args, **kwargs):
+ """
+ DeleteBackNotLine(self)
+
+ Delete the selection or if no selection, the character before the caret.
+ Will not delete the character before at the start of a line.
+ """
+ return _stc.StyledTextCtrl_DeleteBackNotLine(*args, **kwargs)
+
+ def HomeDisplay(*args, **kwargs):
+ """
+ HomeDisplay(self)
+
+ Move caret to first position on display line.
+ """
+ return _stc.StyledTextCtrl_HomeDisplay(*args, **kwargs)
+
+ def HomeDisplayExtend(*args, **kwargs):
+ """
+ HomeDisplayExtend(self)
+
+ Move caret to first position on display line extending selection to
+ new caret position.
+ """
+ return _stc.StyledTextCtrl_HomeDisplayExtend(*args, **kwargs)
+
+ def LineEndDisplay(*args, **kwargs):
+ """
+ LineEndDisplay(self)
+
+ Move caret to last position on display line.
+ """
+ return _stc.StyledTextCtrl_LineEndDisplay(*args, **kwargs)
+
+ def LineEndDisplayExtend(*args, **kwargs):
+ """
+ LineEndDisplayExtend(self)
+
+ Move caret to last position on display line extending selection to new
+ caret position.
+ """
+ return _stc.StyledTextCtrl_LineEndDisplayExtend(*args, **kwargs)
+
+ def HomeWrap(*args, **kwargs):
+ """
+ HomeWrap(self)
+
+ These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)?
+ except they behave differently when word-wrap is enabled:
+ They go first to the start / end of the display line, like (Home|LineEnd)Display
+ The difference is that, the cursor is already at the point, it goes on to the start
+ or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?.
+ """
+ return _stc.StyledTextCtrl_HomeWrap(*args, **kwargs)
+
+ def HomeWrapExtend(*args, **kwargs):
+ """HomeWrapExtend(self)"""
+ return _stc.StyledTextCtrl_HomeWrapExtend(*args, **kwargs)
+
+ def LineEndWrap(*args, **kwargs):
+ """LineEndWrap(self)"""
+ return _stc.StyledTextCtrl_LineEndWrap(*args, **kwargs)
+
+ def LineEndWrapExtend(*args, **kwargs):
+ """LineEndWrapExtend(self)"""
+ return _stc.StyledTextCtrl_LineEndWrapExtend(*args, **kwargs)
+
+ def VCHomeWrap(*args, **kwargs):
+ """VCHomeWrap(self)"""
+ return _stc.StyledTextCtrl_VCHomeWrap(*args, **kwargs)
+
+ def VCHomeWrapExtend(*args, **kwargs):
+ """VCHomeWrapExtend(self)"""
+ return _stc.StyledTextCtrl_VCHomeWrapExtend(*args, **kwargs)
+
+ def LineCopy(*args, **kwargs):
+ """
+ LineCopy(self)
+
+ Copy the line containing the caret.
+ """
+ return _stc.StyledTextCtrl_LineCopy(*args, **kwargs)
+
+ def MoveCaretInsideView(*args, **kwargs):
+ """
+ MoveCaretInsideView(self)
+
+ Move the caret inside current view if it's not there already.
+ """
+ return _stc.StyledTextCtrl_MoveCaretInsideView(*args, **kwargs)
+
+ def LineLength(*args, **kwargs):
+ """
+ LineLength(self, int line) -> int
+
+ How many characters are on a line, including end of line characters?
+ """
+ return _stc.StyledTextCtrl_LineLength(*args, **kwargs)
+
+ def BraceHighlight(*args, **kwargs):
+ """
+ BraceHighlight(self, int pos1, int pos2)
+
+ Highlight the characters at two positions.
+ """
+ return _stc.StyledTextCtrl_BraceHighlight(*args, **kwargs)
+
+ def BraceHighlightIndicator(*args, **kwargs):
+ """BraceHighlightIndicator(self, bool useBraceHighlightIndicator, int indicator)"""
+ return _stc.StyledTextCtrl_BraceHighlightIndicator(*args, **kwargs)
+
+ def BraceBadLight(*args, **kwargs):
+ """
+ BraceBadLight(self, int pos)
+
+ Highlight the character at a position indicating there is no matching brace.
+ """
+ return _stc.StyledTextCtrl_BraceBadLight(*args, **kwargs)
+
+ def BraceBadLightIndicator(*args, **kwargs):
+ """BraceBadLightIndicator(self, bool useBraceBadLightIndicator, int indicator)"""
+ return _stc.StyledTextCtrl_BraceBadLightIndicator(*args, **kwargs)
+
+ def BraceMatch(*args, **kwargs):
+ """
+ BraceMatch(self, int pos) -> int
+
+ Find the position of a matching brace or INVALID_POSITION if no match.
+ """
+ return _stc.StyledTextCtrl_BraceMatch(*args, **kwargs)
+
+ def GetViewEOL(*args, **kwargs):
+ """
+ GetViewEOL(self) -> bool
+
+ Are the end of line characters visible?
+ """
+ return _stc.StyledTextCtrl_GetViewEOL(*args, **kwargs)
+
+ def SetViewEOL(*args, **kwargs):
+ """
+ SetViewEOL(self, bool visible)
+
+ Make the end of line characters visible or invisible.
+ """
+ return _stc.StyledTextCtrl_SetViewEOL(*args, **kwargs)
+
+ def GetDocPointer(*args, **kwargs):
+ """
+ GetDocPointer(self) -> void
+
+ Retrieve a pointer to the document object.
+ """
+ return _stc.StyledTextCtrl_GetDocPointer(*args, **kwargs)
+
+ def SetDocPointer(*args, **kwargs):
+ """
+ SetDocPointer(self, void docPointer)
+
+ Change the document object used.
+ """
+ return _stc.StyledTextCtrl_SetDocPointer(*args, **kwargs)
+
+ def SetModEventMask(*args, **kwargs):
+ """
+ SetModEventMask(self, int mask)
+
+ Set which document modification events are sent to the container.
+ """
+ return _stc.StyledTextCtrl_SetModEventMask(*args, **kwargs)
+
+ def GetEdgeColumn(*args, **kwargs):
+ """
+ GetEdgeColumn(self) -> int
+
+ Retrieve the column number which text should be kept within.
+ """
+ return _stc.StyledTextCtrl_GetEdgeColumn(*args, **kwargs)
+
+ def SetEdgeColumn(*args, **kwargs):
+ """
+ SetEdgeColumn(self, int column)
+
+ Set the column number of the edge.
+ If text goes past the edge then it is highlighted.
+ """
+ return _stc.StyledTextCtrl_SetEdgeColumn(*args, **kwargs)
+
+ def GetEdgeMode(*args, **kwargs):
+ """
+ GetEdgeMode(self) -> int
+
+ Retrieve the edge highlight mode.
+ """
+ return _stc.StyledTextCtrl_GetEdgeMode(*args, **kwargs)
+
+ def SetEdgeMode(*args, **kwargs):
+ """
+ SetEdgeMode(self, int mode)
+
+ The edge may be displayed by a line (EDGE_LINE) or by highlighting text that
+ goes beyond it (EDGE_BACKGROUND) or not displayed at all (EDGE_NONE).
+ """
+ return _stc.StyledTextCtrl_SetEdgeMode(*args, **kwargs)
+
+ def GetEdgeColour(*args, **kwargs):
+ """
+ GetEdgeColour(self) -> Colour
+
+ Retrieve the colour used in edge indication.
+ """
+ return _stc.StyledTextCtrl_GetEdgeColour(*args, **kwargs)
+
+ def SetEdgeColour(*args, **kwargs):
+ """
+ SetEdgeColour(self, Colour edgeColour)
+
+ Change the colour used in edge indication.
+ """
+ return _stc.StyledTextCtrl_SetEdgeColour(*args, **kwargs)
+
+ def SearchAnchor(*args, **kwargs):
+ """
+ SearchAnchor(self)
+
+ Sets the current caret position to be the search anchor.
+ """
+ return _stc.StyledTextCtrl_SearchAnchor(*args, **kwargs)
+
+ def SearchNext(*args, **kwargs):
+ """
+ SearchNext(self, int flags, String text) -> int
+
+ Find some text starting at the search anchor.
+ Does not ensure the selection is visible.
+ """
+ return _stc.StyledTextCtrl_SearchNext(*args, **kwargs)
+
+ def SearchPrev(*args, **kwargs):
+ """
+ SearchPrev(self, int flags, String text) -> int
+
+ Find some text starting at the search anchor and moving backwards.
+ Does not ensure the selection is visible.
+ """
+ return _stc.StyledTextCtrl_SearchPrev(*args, **kwargs)
+
+ def LinesOnScreen(*args, **kwargs):
+ """
+ LinesOnScreen(self) -> int
+
+ Retrieves the number of lines completely visible.
+ """
+ return _stc.StyledTextCtrl_LinesOnScreen(*args, **kwargs)
+
+ def UsePopUp(*args, **kwargs):
+ """
+ UsePopUp(self, bool allowPopUp)
+
+ Set whether a pop up menu is displayed automatically when the user presses
+ the wrong mouse button.
+ """
+ return _stc.StyledTextCtrl_UsePopUp(*args, **kwargs)
+
+ def SelectionIsRectangle(*args, **kwargs):
+ """
+ SelectionIsRectangle(self) -> bool
+
+ Is the selection rectangular? The alternative is the more common stream selection.
+ """
+ return _stc.StyledTextCtrl_SelectionIsRectangle(*args, **kwargs)
+
+ def SetZoom(*args, **kwargs):
+ """
+ SetZoom(self, int zoom)
+
+ Set the zoom level. This number of points is added to the size of all fonts.
+ It may be positive to magnify or negative to reduce.
+ """
+ return _stc.StyledTextCtrl_SetZoom(*args, **kwargs)
+
+ def GetZoom(*args, **kwargs):
+ """
+ GetZoom(self) -> int
+
+ Retrieve the zoom level.
+ """
+ return _stc.StyledTextCtrl_GetZoom(*args, **kwargs)
+
+ def CreateDocument(*args, **kwargs):
+ """
+ CreateDocument(self) -> void
+
+ Create a new document object.
+ Starts with reference count of 1 and not selected into editor.
+ """
+ return _stc.StyledTextCtrl_CreateDocument(*args, **kwargs)
+
+ def AddRefDocument(*args, **kwargs):
+ """
+ AddRefDocument(self, void docPointer)
+
+ Extend life of document.
+ """
+ return _stc.StyledTextCtrl_AddRefDocument(*args, **kwargs)
+
+ def ReleaseDocument(*args, **kwargs):
+ """
+ ReleaseDocument(self, void docPointer)
+
+ Release a reference to the document, deleting document if it fades to black.
+ """
+ return _stc.StyledTextCtrl_ReleaseDocument(*args, **kwargs)
+
+ def GetModEventMask(*args, **kwargs):
+ """
+ GetModEventMask(self) -> int
+
+ Get which document modification events are sent to the container.
+ """
+ return _stc.StyledTextCtrl_GetModEventMask(*args, **kwargs)
+
+ def SetSTCFocus(*args, **kwargs):
+ """
+ SetSTCFocus(self, bool focus)
+
+ Change internal focus flag.
+ """
+ return _stc.StyledTextCtrl_SetSTCFocus(*args, **kwargs)
+
+ def GetSTCFocus(*args, **kwargs):
+ """
+ GetSTCFocus(self) -> bool
+
+ Get internal focus flag.
+ """
+ return _stc.StyledTextCtrl_GetSTCFocus(*args, **kwargs)
+
+ def SetStatus(*args, **kwargs):
+ """
+ SetStatus(self, int statusCode)
+
+ Change error status - 0 = OK.
+ """
+ return _stc.StyledTextCtrl_SetStatus(*args, **kwargs)
+
+ def GetStatus(*args, **kwargs):
+ """
+ GetStatus(self) -> int
+
+ Get error status.
+ """
+ return _stc.StyledTextCtrl_GetStatus(*args, **kwargs)
+
+ def SetMouseDownCaptures(*args, **kwargs):
+ """
+ SetMouseDownCaptures(self, bool captures)
+
+ Set whether the mouse is captured when its button is pressed.
+ """
+ return _stc.StyledTextCtrl_SetMouseDownCaptures(*args, **kwargs)
+
+ def GetMouseDownCaptures(*args, **kwargs):
+ """
+ GetMouseDownCaptures(self) -> bool
+
+ Get whether mouse gets captured.
+ """
+ return _stc.StyledTextCtrl_GetMouseDownCaptures(*args, **kwargs)
+
+ def SetSTCCursor(*args, **kwargs):
+ """
+ SetSTCCursor(self, int cursorType)
+
+ Sets the cursor to one of the SC_CURSOR* values.
+ """
+ return _stc.StyledTextCtrl_SetSTCCursor(*args, **kwargs)
+
+ def GetSTCCursor(*args, **kwargs):
+ """
+ GetSTCCursor(self) -> int
+
+ Get cursor type.
+ """
+ return _stc.StyledTextCtrl_GetSTCCursor(*args, **kwargs)
+
+ def SetControlCharSymbol(*args, **kwargs):
+ """
+ SetControlCharSymbol(self, int symbol)
+
+ Change the way control characters are displayed:
+ If symbol is < 32, keep the drawn way, else, use the given character.
+ """
+ return _stc.StyledTextCtrl_SetControlCharSymbol(*args, **kwargs)
+
+ def GetControlCharSymbol(*args, **kwargs):
+ """
+ GetControlCharSymbol(self) -> int
+
+ Get the way control characters are displayed.
+ """
+ return _stc.StyledTextCtrl_GetControlCharSymbol(*args, **kwargs)
+
+ def WordPartLeft(*args, **kwargs):
+ """
+ WordPartLeft(self)
+
+ Move to the previous change in capitalisation.
+ """
+ return _stc.StyledTextCtrl_WordPartLeft(*args, **kwargs)
+
+ def WordPartLeftExtend(*args, **kwargs):
+ """
+ WordPartLeftExtend(self)
+
+ Move to the previous change in capitalisation extending selection
+ to new caret position.
+ """
+ return _stc.StyledTextCtrl_WordPartLeftExtend(*args, **kwargs)
+
+ def WordPartRight(*args, **kwargs):
+ """
+ WordPartRight(self)
+
+ Move to the change next in capitalisation.
+ """
+ return _stc.StyledTextCtrl_WordPartRight(*args, **kwargs)
+
+ def WordPartRightExtend(*args, **kwargs):
+ """
+ WordPartRightExtend(self)
+
+ Move to the next change in capitalisation extending selection
+ to new caret position.
+ """
+ return _stc.StyledTextCtrl_WordPartRightExtend(*args, **kwargs)
+
+ def SetVisiblePolicy(*args, **kwargs):
+ """
+ SetVisiblePolicy(self, int visiblePolicy, int visibleSlop)
+
+ Set the way the display area is determined when a particular line
+ is to be moved to by Find, FindNext, GotoLine, etc.
+ """
+ return _stc.StyledTextCtrl_SetVisiblePolicy(*args, **kwargs)
+
+ def DelLineLeft(*args, **kwargs):
+ """
+ DelLineLeft(self)
+
+ Delete back from the current position to the start of the line.
+ """
+ return _stc.StyledTextCtrl_DelLineLeft(*args, **kwargs)
+
+ def DelLineRight(*args, **kwargs):
+ """
+ DelLineRight(self)
+
+ Delete forwards from the current position to the end of the line.
+ """
+ return _stc.StyledTextCtrl_DelLineRight(*args, **kwargs)
+
+ def SetXOffset(*args, **kwargs):
+ """
+ SetXOffset(self, int newOffset)
+
+ Get and Set the xOffset (ie, horizonal scroll position).
+ """
+ return _stc.StyledTextCtrl_SetXOffset(*args, **kwargs)
+
+ def GetXOffset(*args, **kwargs):
+ """GetXOffset(self) -> int"""
+ return _stc.StyledTextCtrl_GetXOffset(*args, **kwargs)
+
+ def ChooseCaretX(*args, **kwargs):
+ """
+ ChooseCaretX(self)
+
+ Set the last x chosen value to be the caret x position.
+ """
+ return _stc.StyledTextCtrl_ChooseCaretX(*args, **kwargs)
+
+ def SetXCaretPolicy(*args, **kwargs):
+ """
+ SetXCaretPolicy(self, int caretPolicy, int caretSlop)
+
+ Set the way the caret is kept visible when going sideway.
+ The exclusion zone is given in pixels.
+ """
+ return _stc.StyledTextCtrl_SetXCaretPolicy(*args, **kwargs)
+
+ def SetYCaretPolicy(*args, **kwargs):
+ """
+ SetYCaretPolicy(self, int caretPolicy, int caretSlop)
+
+ Set the way the line the caret is on is kept visible.
+ The exclusion zone is given in lines.
+ """
+ return _stc.StyledTextCtrl_SetYCaretPolicy(*args, **kwargs)
+
+ def SetPrintWrapMode(*args, **kwargs):
+ """
+ SetPrintWrapMode(self, int mode)
+
+ Set printing to line wrapped (SC_WRAP_WORD) or not line wrapped (SC_WRAP_NONE).
+ """
+ return _stc.StyledTextCtrl_SetPrintWrapMode(*args, **kwargs)
+
+ def GetPrintWrapMode(*args, **kwargs):
+ """
+ GetPrintWrapMode(self) -> int
+
+ Is printing line wrapped?
+ """
+ return _stc.StyledTextCtrl_GetPrintWrapMode(*args, **kwargs)
+
+ def SetHotspotActiveForeground(*args, **kwargs):
+ """
+ SetHotspotActiveForeground(self, bool useSetting, Colour fore)
+
+ Set a fore colour for active hotspots.
+ """
+ return _stc.StyledTextCtrl_SetHotspotActiveForeground(*args, **kwargs)
+
+ def GetHotspotActiveForeground(*args, **kwargs):
+ """
+ GetHotspotActiveForeground(self) -> Colour
+
+ Get the fore colour for active hotspots.
+ """
+ return _stc.StyledTextCtrl_GetHotspotActiveForeground(*args, **kwargs)
+
+ def SetHotspotActiveBackground(*args, **kwargs):
+ """
+ SetHotspotActiveBackground(self, bool useSetting, Colour back)
+
+ Set a back colour for active hotspots.
+ """
+ return _stc.StyledTextCtrl_SetHotspotActiveBackground(*args, **kwargs)
+
+ def GetHotspotActiveBackground(*args, **kwargs):
+ """
+ GetHotspotActiveBackground(self) -> Colour
+
+ Get the back colour for active hotspots.
+ """
+ return _stc.StyledTextCtrl_GetHotspotActiveBackground(*args, **kwargs)
+
+ def SetHotspotActiveUnderline(*args, **kwargs):
+ """
+ SetHotspotActiveUnderline(self, bool underline)
+
+ Enable / Disable underlining active hotspots.
+ """
+ return _stc.StyledTextCtrl_SetHotspotActiveUnderline(*args, **kwargs)
+
+ def GetHotspotActiveUnderline(*args, **kwargs):
+ """
+ GetHotspotActiveUnderline(self) -> bool
+
+ Get whether underlining for active hotspots.
+ """
+ return _stc.StyledTextCtrl_GetHotspotActiveUnderline(*args, **kwargs)
+
+ def SetHotspotSingleLine(*args, **kwargs):
+ """
+ SetHotspotSingleLine(self, bool singleLine)
+
+ Limit hotspots to single line so hotspots on two lines don't merge.
+ """
+ return _stc.StyledTextCtrl_SetHotspotSingleLine(*args, **kwargs)
+
+ def GetHotspotSingleLine(*args, **kwargs):
+ """
+ GetHotspotSingleLine(self) -> bool
+
+ Get the HotspotSingleLine property
+ """
+ return _stc.StyledTextCtrl_GetHotspotSingleLine(*args, **kwargs)
+
+ def ParaDown(*args, **kwargs):
+ """
+ ParaDown(self)
+
+ Move caret between paragraphs (delimited by empty lines).
+ """
+ return _stc.StyledTextCtrl_ParaDown(*args, **kwargs)
+
+ def ParaDownExtend(*args, **kwargs):
+ """ParaDownExtend(self)"""
+ return _stc.StyledTextCtrl_ParaDownExtend(*args, **kwargs)
+
+ def ParaUp(*args, **kwargs):
+ """ParaUp(self)"""
+ return _stc.StyledTextCtrl_ParaUp(*args, **kwargs)
+
+ def ParaUpExtend(*args, **kwargs):
+ """ParaUpExtend(self)"""
+ return _stc.StyledTextCtrl_ParaUpExtend(*args, **kwargs)
+
+ def PositionBefore(*args, **kwargs):
+ """
+ PositionBefore(self, int pos) -> int
+
+ Given a valid document position, return the previous position taking code
+ page into account. Returns 0 if passed 0.
+ """
+ return _stc.StyledTextCtrl_PositionBefore(*args, **kwargs)
+
+ def PositionAfter(*args, **kwargs):
+ """
+ PositionAfter(self, int pos) -> int
+
+ Given a valid document position, return the next position taking code
+ page into account. Maximum value returned is the last position in the document.
+ """
+ return _stc.StyledTextCtrl_PositionAfter(*args, **kwargs)
+
+ def CopyRange(*args, **kwargs):
+ """
+ CopyRange(self, int start, int end)
+
+ Copy a range of text to the clipboard. Positions are clipped into the document.
+ """
+ return _stc.StyledTextCtrl_CopyRange(*args, **kwargs)
+
+ def CopyText(*args, **kwargs):
+ """
+ CopyText(self, int length, String text)
+
+ Copy argument text to the clipboard.
+ """
+ return _stc.StyledTextCtrl_CopyText(*args, **kwargs)
+
+ def SetSelectionMode(*args, **kwargs):
+ """
+ SetSelectionMode(self, int mode)
+
+ Set the selection mode to stream (SC_SEL_STREAM) or rectangular (SC_SEL_RECTANGLE/SC_SEL_THIN) or
+ by lines (SC_SEL_LINES).
+ """
+ return _stc.StyledTextCtrl_SetSelectionMode(*args, **kwargs)
+
+ def GetSelectionMode(*args, **kwargs):
+ """
+ GetSelectionMode(self) -> int
+
+ Get the mode of the current selection.
+ """
+ return _stc.StyledTextCtrl_GetSelectionMode(*args, **kwargs)
+
+ def GetLineSelStartPosition(*args, **kwargs):
+ """
+ GetLineSelStartPosition(self, int line) -> int
+
+ Retrieve the position of the start of the selection at the given line (INVALID_POSITION if no selection on this line).
+ """
+ return _stc.StyledTextCtrl_GetLineSelStartPosition(*args, **kwargs)
+
+ def GetLineSelEndPosition(*args, **kwargs):
+ """
+ GetLineSelEndPosition(self, int line) -> int
+
+ Retrieve the position of the end of the selection at the given line (INVALID_POSITION if no selection on this line).
+ """
+ return _stc.StyledTextCtrl_GetLineSelEndPosition(*args, **kwargs)
+
+ def LineDownRectExtend(*args, **kwargs):
+ """
+ LineDownRectExtend(self)
+
+ Move caret down one line, extending rectangular selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_LineDownRectExtend(*args, **kwargs)
+
+ def LineUpRectExtend(*args, **kwargs):
+ """
+ LineUpRectExtend(self)
+
+ Move caret up one line, extending rectangular selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_LineUpRectExtend(*args, **kwargs)
+
+ def CharLeftRectExtend(*args, **kwargs):
+ """
+ CharLeftRectExtend(self)
+
+ Move caret left one character, extending rectangular selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_CharLeftRectExtend(*args, **kwargs)
+
+ def CharRightRectExtend(*args, **kwargs):
+ """
+ CharRightRectExtend(self)
+
+ Move caret right one character, extending rectangular selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_CharRightRectExtend(*args, **kwargs)
+
+ def HomeRectExtend(*args, **kwargs):
+ """
+ HomeRectExtend(self)
+
+ Move caret to first position on line, extending rectangular selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_HomeRectExtend(*args, **kwargs)
+
+ def VCHomeRectExtend(*args, **kwargs):
+ """
+ VCHomeRectExtend(self)
+
+ Move caret to before first visible character on line.
+ If already there move to first character on line.
+ In either case, extend rectangular selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_VCHomeRectExtend(*args, **kwargs)
+
+ def LineEndRectExtend(*args, **kwargs):
+ """
+ LineEndRectExtend(self)
+
+ Move caret to last position on line, extending rectangular selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_LineEndRectExtend(*args, **kwargs)
+
+ def PageUpRectExtend(*args, **kwargs):
+ """
+ PageUpRectExtend(self)
+
+ Move caret one page up, extending rectangular selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_PageUpRectExtend(*args, **kwargs)
+
+ def PageDownRectExtend(*args, **kwargs):
+ """
+ PageDownRectExtend(self)
+
+ Move caret one page down, extending rectangular selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_PageDownRectExtend(*args, **kwargs)
+
+ def StutteredPageUp(*args, **kwargs):
+ """
+ StutteredPageUp(self)
+
+ Move caret to top of page, or one page up if already at top of page.
+ """
+ return _stc.StyledTextCtrl_StutteredPageUp(*args, **kwargs)
+
+ def StutteredPageUpExtend(*args, **kwargs):
+ """
+ StutteredPageUpExtend(self)
+
+ Move caret to top of page, or one page up if already at top of page, extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_StutteredPageUpExtend(*args, **kwargs)
+
+ def StutteredPageDown(*args, **kwargs):
+ """
+ StutteredPageDown(self)
+
+ Move caret to bottom of page, or one page down if already at bottom of page.
+ """
+ return _stc.StyledTextCtrl_StutteredPageDown(*args, **kwargs)
+
+ def StutteredPageDownExtend(*args, **kwargs):
+ """
+ StutteredPageDownExtend(self)
+
+ Move caret to bottom of page, or one page down if already at bottom of page, extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_StutteredPageDownExtend(*args, **kwargs)
+
+ def WordLeftEnd(*args, **kwargs):
+ """
+ WordLeftEnd(self)
+
+ Move caret left one word, position cursor at end of word.
+ """
+ return _stc.StyledTextCtrl_WordLeftEnd(*args, **kwargs)
+
+ def WordLeftEndExtend(*args, **kwargs):
+ """
+ WordLeftEndExtend(self)
+
+ Move caret left one word, position cursor at end of word, extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_WordLeftEndExtend(*args, **kwargs)
+
+ def WordRightEnd(*args, **kwargs):
+ """
+ WordRightEnd(self)
+
+ Move caret right one word, position cursor at end of word.
+ """
+ return _stc.StyledTextCtrl_WordRightEnd(*args, **kwargs)
+
+ def WordRightEndExtend(*args, **kwargs):
+ """
+ WordRightEndExtend(self)
+
+ Move caret right one word, position cursor at end of word, extending selection to new caret position.
+ """
+ return _stc.StyledTextCtrl_WordRightEndExtend(*args, **kwargs)
+
+ def SetWhitespaceChars(*args, **kwargs):
+ """
+ SetWhitespaceChars(self, String characters)
+
+ Set the set of characters making up whitespace for when moving or selecting by word.
+ Should be called after SetWordChars.
+ """
+ return _stc.StyledTextCtrl_SetWhitespaceChars(*args, **kwargs)
+
+ def GetWhitespaceChars(*args, **kwargs):
+ """GetWhitespaceChars(self) -> String"""
+ return _stc.StyledTextCtrl_GetWhitespaceChars(*args, **kwargs)
+
+ def SetPunctuationChars(*args, **kwargs):
+ """SetPunctuationChars(self, String characters)"""
+ return _stc.StyledTextCtrl_SetPunctuationChars(*args, **kwargs)
+
+ def GetPunctuationChars(*args, **kwargs):
+ """GetPunctuationChars(self) -> String"""
+ return _stc.StyledTextCtrl_GetPunctuationChars(*args, **kwargs)
+
+ def SetCharsDefault(*args, **kwargs):
+ """
+ SetCharsDefault(self)
+
+ Reset the set of characters for whitespace and word characters to the defaults.
+ """
+ return _stc.StyledTextCtrl_SetCharsDefault(*args, **kwargs)
+
+ def AutoCompGetCurrent(*args, **kwargs):
+ """
+ AutoCompGetCurrent(self) -> int
+
+ Get currently selected item position in the auto-completion list
+ """
+ return _stc.StyledTextCtrl_AutoCompGetCurrent(*args, **kwargs)
+
+ def AutoCompSetCaseInsensitiveBehaviour(*args, **kwargs):
+ """AutoCompSetCaseInsensitiveBehaviour(self, int behaviour)"""
+ return _stc.StyledTextCtrl_AutoCompSetCaseInsensitiveBehaviour(*args, **kwargs)
+
+ def AutoCompGetCaseInsensitiveBehaviour(*args, **kwargs):
+ """AutoCompGetCaseInsensitiveBehaviour(self) -> int"""
+ return _stc.StyledTextCtrl_AutoCompGetCaseInsensitiveBehaviour(*args, **kwargs)
+
+ def Allocate(*args, **kwargs):
+ """
+ Allocate(self, int bytes)
+
+ Enlarge the document to a particular size of text bytes.
+ """
+ return _stc.StyledTextCtrl_Allocate(*args, **kwargs)
+
+ def FindColumn(*args, **kwargs):
+ """
+ FindColumn(self, int line, int column) -> int
+
+ Find the position of a column on a line taking into account tabs and
+ multi-byte characters. If beyond end of line, return line end position.
+ """
+ return _stc.StyledTextCtrl_FindColumn(*args, **kwargs)
+
+ def GetCaretSticky(*args, **kwargs):
+ """
+ GetCaretSticky(self) -> int
+
+ Can the caret preferred x position only be changed by explicit movement commands?
+ """
+ return _stc.StyledTextCtrl_GetCaretSticky(*args, **kwargs)
+
+ def SetCaretSticky(*args, **kwargs):
+ """
+ SetCaretSticky(self, int useCaretStickyBehaviour)
+
+ Stop the caret preferred x position changing when the user types.
+ """
+ return _stc.StyledTextCtrl_SetCaretSticky(*args, **kwargs)
+
+ def ToggleCaretSticky(*args, **kwargs):
+ """
+ ToggleCaretSticky(self)
+
+ Switch between sticky and non-sticky: meant to be bound to a key.
+ """
+ return _stc.StyledTextCtrl_ToggleCaretSticky(*args, **kwargs)
+
+ def SetPasteConvertEndings(*args, **kwargs):
+ """
+ SetPasteConvertEndings(self, bool convert)
+
+ Enable/Disable convert-on-paste for line endings
+ """
+ return _stc.StyledTextCtrl_SetPasteConvertEndings(*args, **kwargs)
+
+ def GetPasteConvertEndings(*args, **kwargs):
+ """
+ GetPasteConvertEndings(self) -> bool
+
+ Get convert-on-paste setting
+ """
+ return _stc.StyledTextCtrl_GetPasteConvertEndings(*args, **kwargs)
+
+ def SelectionDuplicate(*args, **kwargs):
+ """
+ SelectionDuplicate(self)
+
+ Duplicate the selection. If selection empty duplicate the line containing the caret.
+ """
+ return _stc.StyledTextCtrl_SelectionDuplicate(*args, **kwargs)
+
+ def SetCaretLineBackAlpha(*args, **kwargs):
+ """
+ SetCaretLineBackAlpha(self, int alpha)
+
+ Set background alpha of the caret line.
+ """
+ return _stc.StyledTextCtrl_SetCaretLineBackAlpha(*args, **kwargs)
+
+ def GetCaretLineBackAlpha(*args, **kwargs):
+ """
+ GetCaretLineBackAlpha(self) -> int
+
+ Get the background alpha of the caret line.
+ """
+ return _stc.StyledTextCtrl_GetCaretLineBackAlpha(*args, **kwargs)
+
+ def SetCaretStyle(*args, **kwargs):
+ """
+ SetCaretStyle(self, int caretStyle)
+
+ Set the style of the caret to be drawn.
+ """
+ return _stc.StyledTextCtrl_SetCaretStyle(*args, **kwargs)
+
+ def GetCaretStyle(*args, **kwargs):
+ """
+ GetCaretStyle(self) -> int
+
+ Returns the current style of the caret.
+ """
+ return _stc.StyledTextCtrl_GetCaretStyle(*args, **kwargs)
+
+ def SetIndicatorCurrent(*args, **kwargs):
+ """
+ SetIndicatorCurrent(self, int indicator)
+
+ Set the indicator used for IndicatorFillRange and IndicatorClearRange
+ """
+ return _stc.StyledTextCtrl_SetIndicatorCurrent(*args, **kwargs)
+
+ def GetIndicatorCurrent(*args, **kwargs):
+ """
+ GetIndicatorCurrent(self) -> int
+
+ Get the current indicator
+ """
+ return _stc.StyledTextCtrl_GetIndicatorCurrent(*args, **kwargs)
+
+ def SetIndicatorValue(*args, **kwargs):
+ """
+ SetIndicatorValue(self, int value)
+
+ Set the value used for IndicatorFillRange
+ """
+ return _stc.StyledTextCtrl_SetIndicatorValue(*args, **kwargs)
+
+ def GetIndicatorValue(*args, **kwargs):
+ """
+ GetIndicatorValue(self) -> int
+
+ Get the current indicator vaue
+ """
+ return _stc.StyledTextCtrl_GetIndicatorValue(*args, **kwargs)
+
+ def IndicatorFillRange(*args, **kwargs):
+ """
+ IndicatorFillRange(self, int position, int fillLength)
+
+ Turn a indicator on over a range.
+ """
+ return _stc.StyledTextCtrl_IndicatorFillRange(*args, **kwargs)
+
+ def IndicatorClearRange(*args, **kwargs):
+ """
+ IndicatorClearRange(self, int position, int clearLength)
+
+ Turn a indicator off over a range.
+ """
+ return _stc.StyledTextCtrl_IndicatorClearRange(*args, **kwargs)
+
+ def IndicatorAllOnFor(*args, **kwargs):
+ """
+ IndicatorAllOnFor(self, int position) -> int
+
+ Are any indicators present at position?
+ """
+ return _stc.StyledTextCtrl_IndicatorAllOnFor(*args, **kwargs)
+
+ def IndicatorValueAt(*args, **kwargs):
+ """
+ IndicatorValueAt(self, int indicator, int position) -> int
+
+ What value does a particular indicator have at at a position?
+ """
+ return _stc.StyledTextCtrl_IndicatorValueAt(*args, **kwargs)
+
+ def IndicatorStart(*args, **kwargs):
+ """
+ IndicatorStart(self, int indicator, int position) -> int
+
+ Where does a particular indicator start?
+ """
+ return _stc.StyledTextCtrl_IndicatorStart(*args, **kwargs)
+
+ def IndicatorEnd(*args, **kwargs):
+ """
+ IndicatorEnd(self, int indicator, int position) -> int
+
+ Where does a particular indicator end?
+ """
+ return _stc.StyledTextCtrl_IndicatorEnd(*args, **kwargs)
+
+ def SetPositionCacheSize(*args, **kwargs):
+ """
+ SetPositionCacheSize(self, int size)
+
+ Set number of entries in position cache
+ """
+ return _stc.StyledTextCtrl_SetPositionCacheSize(*args, **kwargs)
+
+ def GetPositionCacheSize(*args, **kwargs):
+ """
+ GetPositionCacheSize(self) -> int
+
+ How many entries are allocated to the position cache?
+ """
+ return _stc.StyledTextCtrl_GetPositionCacheSize(*args, **kwargs)
+
+ def CopyAllowLine(*args, **kwargs):
+ """
+ CopyAllowLine(self)
+
+ Copy the selection, if selection empty copy the line with the caret
+ """
+ return _stc.StyledTextCtrl_CopyAllowLine(*args, **kwargs)
+
+ def GetRangePointer(*args, **kwargs):
+ """GetRangePointer(self, int position, int rangeLength) -> char"""
+ return _stc.StyledTextCtrl_GetRangePointer(*args, **kwargs)
+
+ def GetGapPosition(*args, **kwargs):
+ """GetGapPosition(self) -> int"""
+ return _stc.StyledTextCtrl_GetGapPosition(*args, **kwargs)
+
+ def SetKeysUnicode(*args, **kwargs):
+ """
+ SetKeysUnicode(self, bool keysUnicode)
+
+ Always interpret keyboard input as Unicode
+ """
+ return _stc.StyledTextCtrl_SetKeysUnicode(*args, **kwargs)
+
+ def GetKeysUnicode(*args, **kwargs):
+ """
+ GetKeysUnicode(self) -> bool
+
+ Are keys always interpreted as Unicode?
+ """
+ return _stc.StyledTextCtrl_GetKeysUnicode(*args, **kwargs)
+
+ def IndicatorSetAlpha(*args, **kwargs):
+ """
+ IndicatorSetAlpha(self, int indicator, int alpha)
+
+ Set the alpha fill colour of the given indicator.
+ """
+ return _stc.StyledTextCtrl_IndicatorSetAlpha(*args, **kwargs)
+
+ def IndicatorGetAlpha(*args, **kwargs):
+ """
+ IndicatorGetAlpha(self, int indicator) -> int
+
+ Get the alpha fill colour of the given indicator.
+ """
+ return _stc.StyledTextCtrl_IndicatorGetAlpha(*args, **kwargs)
+
+ def IndicatorSetOutlineAlpha(*args, **kwargs):
+ """IndicatorSetOutlineAlpha(self, int indicator, int alpha)"""
+ return _stc.StyledTextCtrl_IndicatorSetOutlineAlpha(*args, **kwargs)
+
+ def IndicatorGetOutlineAlpha(*args, **kwargs):
+ """IndicatorGetOutlineAlpha(self, int indicator) -> int"""
+ return _stc.StyledTextCtrl_IndicatorGetOutlineAlpha(*args, **kwargs)
+
+ def SetExtraAscent(*args, **kwargs):
+ """
+ SetExtraAscent(self, int extraAscent)
+
+ Set extra ascent for each line
+ """
+ return _stc.StyledTextCtrl_SetExtraAscent(*args, **kwargs)
+
+ def GetExtraAscent(*args, **kwargs):
+ """
+ GetExtraAscent(self) -> int
+
+ Get extra ascent for each line
+ """
+ return _stc.StyledTextCtrl_GetExtraAscent(*args, **kwargs)
+
+ def SetExtraDescent(*args, **kwargs):
+ """
+ SetExtraDescent(self, int extraDescent)
+
+ Set extra descent for each line
+ """
+ return _stc.StyledTextCtrl_SetExtraDescent(*args, **kwargs)
+
+ def GetExtraDescent(*args, **kwargs):
+ """
+ GetExtraDescent(self) -> int
+
+ Get extra descent for each line
+ """
+ return _stc.StyledTextCtrl_GetExtraDescent(*args, **kwargs)
+
+ def GetMarkerSymbolDefined(*args, **kwargs):
+ """
+ GetMarkerSymbolDefined(self, int markerNumber) -> int
+
+ Which symbol was defined for markerNumber with MarkerDefine
+ """
+ return _stc.StyledTextCtrl_GetMarkerSymbolDefined(*args, **kwargs)
+
+ def MarginSetText(*args, **kwargs):
+ """
+ MarginSetText(self, int line, String text)
+
+ Set the text in the text margin for a line
+ """
+ return _stc.StyledTextCtrl_MarginSetText(*args, **kwargs)
+
+ def MarginGetText(*args, **kwargs):
+ """
+ MarginGetText(self, int line) -> String
+
+ Get the text in the text margin for a line
+ """
+ return _stc.StyledTextCtrl_MarginGetText(*args, **kwargs)
+
+ def MarginSetStyle(*args, **kwargs):
+ """
+ MarginSetStyle(self, int line, int style)
+
+ Set the style number for the text margin for a line
+ """
+ return _stc.StyledTextCtrl_MarginSetStyle(*args, **kwargs)
+
+ def MarginGetStyle(*args, **kwargs):
+ """
+ MarginGetStyle(self, int line) -> int
+
+ Get the style number for the text margin for a line
+ """
+ return _stc.StyledTextCtrl_MarginGetStyle(*args, **kwargs)
+
+ def MarginSetStyles(*args, **kwargs):
+ """
+ MarginSetStyles(self, int line, String styles)
+
+ Set the style in the text margin for a line
+ """
+ return _stc.StyledTextCtrl_MarginSetStyles(*args, **kwargs)
+
+ def MarginGetStyles(*args, **kwargs):
+ """
+ MarginGetStyles(self, int line) -> String
+
+ Get the styles in the text margin for a line
+ """
+ return _stc.StyledTextCtrl_MarginGetStyles(*args, **kwargs)
+
+ def MarginTextClearAll(*args, **kwargs):
+ """
+ MarginTextClearAll(self)
+
+ Clear the margin text on all lines
+ """
+ return _stc.StyledTextCtrl_MarginTextClearAll(*args, **kwargs)
+
+ def MarginSetStyleOffset(*args, **kwargs):
+ """
+ MarginSetStyleOffset(self, int style)
+
+ Get the start of the range of style numbers used for margin text
+ """
+ return _stc.StyledTextCtrl_MarginSetStyleOffset(*args, **kwargs)
+
+ def MarginGetStyleOffset(*args, **kwargs):
+ """
+ MarginGetStyleOffset(self) -> int
+
+ Get the start of the range of style numbers used for margin text
+ """
+ return _stc.StyledTextCtrl_MarginGetStyleOffset(*args, **kwargs)
+
+ def SetMarginOptions(*args, **kwargs):
+ """SetMarginOptions(self, int marginOptions)"""
+ return _stc.StyledTextCtrl_SetMarginOptions(*args, **kwargs)
+
+ def GetMarginOptions(*args, **kwargs):
+ """GetMarginOptions(self) -> int"""
+ return _stc.StyledTextCtrl_GetMarginOptions(*args, **kwargs)
+
+ def AnnotationSetText(*args, **kwargs):
+ """
+ AnnotationSetText(self, int line, String text)
+
+ Set the annotation text for a line
+ """
+ return _stc.StyledTextCtrl_AnnotationSetText(*args, **kwargs)
+
+ def AnnotationGetText(*args, **kwargs):
+ """
+ AnnotationGetText(self, int line) -> String
+
+ Get the annotation text for a line
+ """
+ return _stc.StyledTextCtrl_AnnotationGetText(*args, **kwargs)
+
+ def AnnotationSetStyle(*args, **kwargs):
+ """
+ AnnotationSetStyle(self, int line, int style)
+
+ Set the style number for the annotations for a line
+ """
+ return _stc.StyledTextCtrl_AnnotationSetStyle(*args, **kwargs)
+
+ def AnnotationGetStyle(*args, **kwargs):
+ """
+ AnnotationGetStyle(self, int line) -> int
+
+ Get the style number for the annotations for a line
+ """
+ return _stc.StyledTextCtrl_AnnotationGetStyle(*args, **kwargs)
+
+ def AnnotationSetStyles(*args, **kwargs):
+ """
+ AnnotationSetStyles(self, int line, String styles)
+
+ Set the annotation styles for a line
+ """
+ return _stc.StyledTextCtrl_AnnotationSetStyles(*args, **kwargs)
+
+ def AnnotationGetStyles(*args, **kwargs):
+ """
+ AnnotationGetStyles(self, int line) -> String
+
+ Get the annotation styles for a line
+ """
+ return _stc.StyledTextCtrl_AnnotationGetStyles(*args, **kwargs)
+
+ def AnnotationGetLines(*args, **kwargs):
+ """
+ AnnotationGetLines(self, int line) -> int
+
+ Get the number of annotation lines for a line
+ """
+ return _stc.StyledTextCtrl_AnnotationGetLines(*args, **kwargs)
+
+ def AnnotationClearAll(*args, **kwargs):
+ """
+ AnnotationClearAll(self)
+
+ Clear the annotations from all lines
+ """
+ return _stc.StyledTextCtrl_AnnotationClearAll(*args, **kwargs)
+
+ def AnnotationSetVisible(*args, **kwargs):
+ """
+ AnnotationSetVisible(self, int visible)
+
+ Set the visibility for the annotations for a view
+ """
+ return _stc.StyledTextCtrl_AnnotationSetVisible(*args, **kwargs)
+
+ def AnnotationGetVisible(*args, **kwargs):
+ """
+ AnnotationGetVisible(self) -> int
+
+ Get the visibility for the annotations for a view
+ """
+ return _stc.StyledTextCtrl_AnnotationGetVisible(*args, **kwargs)
+
+ def AnnotationSetStyleOffset(*args, **kwargs):
+ """
+ AnnotationSetStyleOffset(self, int style)
+
+ Get the start of the range of style numbers used for annotations
+ """
+ return _stc.StyledTextCtrl_AnnotationSetStyleOffset(*args, **kwargs)
+
+ def AnnotationGetStyleOffset(*args, **kwargs):
+ """
+ AnnotationGetStyleOffset(self) -> int
+
+ Get the start of the range of style numbers used for annotations
+ """
+ return _stc.StyledTextCtrl_AnnotationGetStyleOffset(*args, **kwargs)
+
+ def AddUndoAction(*args, **kwargs):
+ """
+ AddUndoAction(self, int token, int flags)
+
+ Add a container action to the undo stack
+ """
+ return _stc.StyledTextCtrl_AddUndoAction(*args, **kwargs)
+
+ def CharPositionFromPoint(*args, **kwargs):
+ """
+ CharPositionFromPoint(self, int x, int y) -> int
+
+ Find the position of a character from a point within the window.
+ """
+ return _stc.StyledTextCtrl_CharPositionFromPoint(*args, **kwargs)
+
+ def CharPositionFromPointClose(*args, **kwargs):
+ """
+ CharPositionFromPointClose(self, int x, int y) -> int
+
+ Find the position of a character from a point within the window.
+ Return INVALID_POSITION if not close to text.
+ """
+ return _stc.StyledTextCtrl_CharPositionFromPointClose(*args, **kwargs)
+
+ def SetMultipleSelection(*args, **kwargs):
+ """
+ SetMultipleSelection(self, bool multipleSelection)
+
+ Set whether multiple selections can be made
+ """
+ return _stc.StyledTextCtrl_SetMultipleSelection(*args, **kwargs)
+
+ def GetMultipleSelection(*args, **kwargs):
+ """
+ GetMultipleSelection(self) -> bool
+
+ Whether multiple selections can be made
+ """
+ return _stc.StyledTextCtrl_GetMultipleSelection(*args, **kwargs)
+
+ def SetAdditionalSelectionTyping(*args, **kwargs):
+ """
+ SetAdditionalSelectionTyping(self, bool additionalSelectionTyping)
+
+ Set whether typing can be performed into multiple selections
+ """
+ return _stc.StyledTextCtrl_SetAdditionalSelectionTyping(*args, **kwargs)
+
+ def GetAdditionalSelectionTyping(*args, **kwargs):
+ """
+ GetAdditionalSelectionTyping(self) -> bool
+
+ Whether typing can be performed into multiple selections
+ """
+ return _stc.StyledTextCtrl_GetAdditionalSelectionTyping(*args, **kwargs)
+
+ def SetAdditionalCaretsBlink(*args, **kwargs):
+ """
+ SetAdditionalCaretsBlink(self, bool additionalCaretsBlink)
+
+ Set whether additional carets will blink
+ """
+ return _stc.StyledTextCtrl_SetAdditionalCaretsBlink(*args, **kwargs)
+
+ def GetAdditionalCaretsBlink(*args, **kwargs):
+ """
+ GetAdditionalCaretsBlink(self) -> bool
+
+ Whether additional carets will blink
+ """
+ return _stc.StyledTextCtrl_GetAdditionalCaretsBlink(*args, **kwargs)
+
+ def SetAdditionalCaretsVisible(*args, **kwargs):
+ """
+ SetAdditionalCaretsVisible(self, bool additionalCaretsBlink)
+
+ Set whether additional carets are visible
+ """
+ return _stc.StyledTextCtrl_SetAdditionalCaretsVisible(*args, **kwargs)
+
+ def GetAdditionalCaretsVisible(*args, **kwargs):
+ """
+ GetAdditionalCaretsVisible(self) -> bool
+
+ Whether additional carets are visible
+ """
+ return _stc.StyledTextCtrl_GetAdditionalCaretsVisible(*args, **kwargs)
+
+ def GetSelections(*args, **kwargs):
+ """
+ GetSelections(self) -> int
+
+ How many selections are there?
+ """
+ return _stc.StyledTextCtrl_GetSelections(*args, **kwargs)
+
+ def ClearSelections(*args, **kwargs):
+ """
+ ClearSelections(self)
+
+ Clear selections to a single empty stream selection
+ """
+ return _stc.StyledTextCtrl_ClearSelections(*args, **kwargs)
+
+ def AddSelection(*args, **kwargs):
+ """
+ AddSelection(self, int caret, int anchor) -> int
+
+ Add a selection
+ """
+ return _stc.StyledTextCtrl_AddSelection(*args, **kwargs)
+
+ def SetMainSelection(*args, **kwargs):
+ """
+ SetMainSelection(self, int selection)
+
+ Set the main selection
+ """
+ return _stc.StyledTextCtrl_SetMainSelection(*args, **kwargs)
+
+ def GetMainSelection(*args, **kwargs):
+ """
+ GetMainSelection(self) -> int
+
+ Which selection is the main selection
+ """
+ return _stc.StyledTextCtrl_GetMainSelection(*args, **kwargs)
+
+ def SetSelectionNCaret(*args, **kwargs):
+ """SetSelectionNCaret(self, int selection, int pos)"""
+ return _stc.StyledTextCtrl_SetSelectionNCaret(*args, **kwargs)
+
+ def GetSelectionNCaret(*args, **kwargs):
+ """GetSelectionNCaret(self, int selection) -> int"""
+ return _stc.StyledTextCtrl_GetSelectionNCaret(*args, **kwargs)
+
+ def SetSelectionNAnchor(*args, **kwargs):
+ """SetSelectionNAnchor(self, int selection, int posAnchor)"""
+ return _stc.StyledTextCtrl_SetSelectionNAnchor(*args, **kwargs)
+
+ def GetSelectionNAnchor(*args, **kwargs):
+ """GetSelectionNAnchor(self, int selection) -> int"""
+ return _stc.StyledTextCtrl_GetSelectionNAnchor(*args, **kwargs)
+
+ def SetSelectionNCaretVirtualSpace(*args, **kwargs):
+ """SetSelectionNCaretVirtualSpace(self, int selection, int space)"""
+ return _stc.StyledTextCtrl_SetSelectionNCaretVirtualSpace(*args, **kwargs)
+
+ def GetSelectionNCaretVirtualSpace(*args, **kwargs):
+ """GetSelectionNCaretVirtualSpace(self, int selection) -> int"""
+ return _stc.StyledTextCtrl_GetSelectionNCaretVirtualSpace(*args, **kwargs)
+
+ def SetSelectionNAnchorVirtualSpace(*args, **kwargs):
+ """SetSelectionNAnchorVirtualSpace(self, int selection, int space)"""
+ return _stc.StyledTextCtrl_SetSelectionNAnchorVirtualSpace(*args, **kwargs)
+
+ def GetSelectionNAnchorVirtualSpace(*args, **kwargs):
+ """GetSelectionNAnchorVirtualSpace(self, int selection) -> int"""
+ return _stc.StyledTextCtrl_GetSelectionNAnchorVirtualSpace(*args, **kwargs)
+
+ def SetSelectionNStart(*args, **kwargs):
+ """
+ SetSelectionNStart(self, int selection, int pos)
+
+ Sets the position that starts the selection - this becomes the anchor.
+ """
+ return _stc.StyledTextCtrl_SetSelectionNStart(*args, **kwargs)
+
+ def GetSelectionNStart(*args, **kwargs):
+ """
+ GetSelectionNStart(self, int selection) -> int
+
+ Returns the position at the start of the selection.
+ """
+ return _stc.StyledTextCtrl_GetSelectionNStart(*args, **kwargs)
+
+ def SetSelectionNEnd(*args, **kwargs):
+ """
+ SetSelectionNEnd(self, int selection, int pos)
+
+ Sets the position that ends the selection - this becomes the currentPosition.
+ """
+ return _stc.StyledTextCtrl_SetSelectionNEnd(*args, **kwargs)
+
+ def GetSelectionNEnd(*args, **kwargs):
+ """
+ GetSelectionNEnd(self, int selection) -> int
+
+ Returns the position at the end of the selection.
+ """
+ return _stc.StyledTextCtrl_GetSelectionNEnd(*args, **kwargs)
+
+ def SetRectangularSelectionCaret(*args, **kwargs):
+ """SetRectangularSelectionCaret(self, int pos)"""
+ return _stc.StyledTextCtrl_SetRectangularSelectionCaret(*args, **kwargs)
+
+ def GetRectangularSelectionCaret(*args, **kwargs):
+ """GetRectangularSelectionCaret(self) -> int"""
+ return _stc.StyledTextCtrl_GetRectangularSelectionCaret(*args, **kwargs)
+
+ def SetRectangularSelectionAnchor(*args, **kwargs):
+ """SetRectangularSelectionAnchor(self, int posAnchor)"""
+ return _stc.StyledTextCtrl_SetRectangularSelectionAnchor(*args, **kwargs)
+
+ def GetRectangularSelectionAnchor(*args, **kwargs):
+ """GetRectangularSelectionAnchor(self) -> int"""
+ return _stc.StyledTextCtrl_GetRectangularSelectionAnchor(*args, **kwargs)
+
+ def SetRectangularSelectionCaretVirtualSpace(*args, **kwargs):
+ """SetRectangularSelectionCaretVirtualSpace(self, int space)"""
+ return _stc.StyledTextCtrl_SetRectangularSelectionCaretVirtualSpace(*args, **kwargs)
+
+ def GetRectangularSelectionCaretVirtualSpace(*args, **kwargs):
+ """GetRectangularSelectionCaretVirtualSpace(self) -> int"""
+ return _stc.StyledTextCtrl_GetRectangularSelectionCaretVirtualSpace(*args, **kwargs)
+
+ def SetRectangularSelectionAnchorVirtualSpace(*args, **kwargs):
+ """SetRectangularSelectionAnchorVirtualSpace(self, int space)"""
+ return _stc.StyledTextCtrl_SetRectangularSelectionAnchorVirtualSpace(*args, **kwargs)
+
+ def GetRectangularSelectionAnchorVirtualSpace(*args, **kwargs):
+ """GetRectangularSelectionAnchorVirtualSpace(self) -> int"""
+ return _stc.StyledTextCtrl_GetRectangularSelectionAnchorVirtualSpace(*args, **kwargs)
+
+ def SetVirtualSpaceOptions(*args, **kwargs):
+ """SetVirtualSpaceOptions(self, int virtualSpaceOptions)"""
+ return _stc.StyledTextCtrl_SetVirtualSpaceOptions(*args, **kwargs)
+
+ def GetVirtualSpaceOptions(*args, **kwargs):
+ """GetVirtualSpaceOptions(self) -> int"""
+ return _stc.StyledTextCtrl_GetVirtualSpaceOptions(*args, **kwargs)
+
+ def SetRectangularSelectionModifier(*args, **kwargs):
+ """
+ SetRectangularSelectionModifier(self, int modifier)
+
+ On GTK+, allow selecting the modifier key to use for mouse-based
+ rectangular selection. Often the window manager requires Alt+Mouse Drag
+ for moving windows.
+ Valid values are SCMOD_CTRL(default), SCMOD_ALT, or SCMOD_SUPER.
+ """
+ return _stc.StyledTextCtrl_SetRectangularSelectionModifier(*args, **kwargs)
+
+ def GetRectangularSelectionModifier(*args, **kwargs):
+ """
+ GetRectangularSelectionModifier(self) -> int
+
+ Get the modifier key used for rectangular selection.
+ """
+ return _stc.StyledTextCtrl_GetRectangularSelectionModifier(*args, **kwargs)
+
+ def SetAdditionalSelForeground(*args, **kwargs):
+ """
+ SetAdditionalSelForeground(self, Colour fore)
+
+ Set the foreground colour of additional selections.
+ Must have previously called SetSelFore with non-zero first argument for this to have an effect.
+ """
+ return _stc.StyledTextCtrl_SetAdditionalSelForeground(*args, **kwargs)
+
+ def SetAdditionalSelBackground(*args, **kwargs):
+ """
+ SetAdditionalSelBackground(self, Colour back)
+
+ Set the background colour of additional selections.
+ Must have previously called SetSelBack with non-zero first argument for this to have an effect.
+ """
+ return _stc.StyledTextCtrl_SetAdditionalSelBackground(*args, **kwargs)
+
+ def SetAdditionalSelAlpha(*args, **kwargs):
+ """
+ SetAdditionalSelAlpha(self, int alpha)
+
+ Set the alpha of the selection.
+ """
+ return _stc.StyledTextCtrl_SetAdditionalSelAlpha(*args, **kwargs)
+
+ def GetAdditionalSelAlpha(*args, **kwargs):
+ """
+ GetAdditionalSelAlpha(self) -> int
+
+ Get the alpha of the selection.
+ """
+ return _stc.StyledTextCtrl_GetAdditionalSelAlpha(*args, **kwargs)
+
+ def SetAdditionalCaretForeground(*args, **kwargs):
+ """
+ SetAdditionalCaretForeground(self, Colour fore)
+
+ Set the foreground colour of additional carets.
+ """
+ return _stc.StyledTextCtrl_SetAdditionalCaretForeground(*args, **kwargs)
+
+ def GetAdditionalCaretForeground(*args, **kwargs):
+ """
+ GetAdditionalCaretForeground(self) -> Colour
+
+ Get the foreground colour of additional carets.
+ """
+ return _stc.StyledTextCtrl_GetAdditionalCaretForeground(*args, **kwargs)
+
+ def RotateSelection(*args, **kwargs):
+ """
+ RotateSelection(self)
+
+ Set the main selection to the next selection.
+ """
+ return _stc.StyledTextCtrl_RotateSelection(*args, **kwargs)
+
+ def SwapMainAnchorCaret(*args, **kwargs):
+ """
+ SwapMainAnchorCaret(self)
+
+ Swap that caret and anchor of the main selection.
+ """
+ return _stc.StyledTextCtrl_SwapMainAnchorCaret(*args, **kwargs)
+
+ def ChangeLexerState(*args, **kwargs):
+ """ChangeLexerState(self, int start, int end) -> int"""
+ return _stc.StyledTextCtrl_ChangeLexerState(*args, **kwargs)
+
+ def ContractedFoldNext(*args, **kwargs):
+ """ContractedFoldNext(self, int lineStart) -> int"""
+ return _stc.StyledTextCtrl_ContractedFoldNext(*args, **kwargs)
+
+ def VerticalCentreCaret(*args, **kwargs):
+ """VerticalCentreCaret(self)"""
+ return _stc.StyledTextCtrl_VerticalCentreCaret(*args, **kwargs)
+
+ def MoveSelectedLinesUp(*args, **kwargs):
+ """MoveSelectedLinesUp(self)"""
+ return _stc.StyledTextCtrl_MoveSelectedLinesUp(*args, **kwargs)
+
+ def MoveSelectedLinesDown(*args, **kwargs):
+ """MoveSelectedLinesDown(self)"""
+ return _stc.StyledTextCtrl_MoveSelectedLinesDown(*args, **kwargs)
+
+ def SetIdentifier(*args, **kwargs):
+ """SetIdentifier(self, int identifier)"""
+ return _stc.StyledTextCtrl_SetIdentifier(*args, **kwargs)
+
+ def GetIdentifier(*args, **kwargs):
+ """GetIdentifier(self) -> int"""
+ return _stc.StyledTextCtrl_GetIdentifier(*args, **kwargs)
+
+ def RGBAImageSetWidth(*args, **kwargs):
+ """RGBAImageSetWidth(self, int width)"""
+ return _stc.StyledTextCtrl_RGBAImageSetWidth(*args, **kwargs)
+
+ def RGBAImageSetHeight(*args, **kwargs):
+ """RGBAImageSetHeight(self, int height)"""
+ return _stc.StyledTextCtrl_RGBAImageSetHeight(*args, **kwargs)
+
+ def MarkerDefineRGBAImage(*args, **kwargs):
+ """MarkerDefineRGBAImage(self, int markerNumber, unsigned char pixels)"""
+ return _stc.StyledTextCtrl_MarkerDefineRGBAImage(*args, **kwargs)
+
+ def RegisterRGBAImage(*args, **kwargs):
+ """RegisterRGBAImage(self, int type, unsigned char pixels)"""
+ return _stc.StyledTextCtrl_RegisterRGBAImage(*args, **kwargs)
+
+ def ScrollToStart(*args, **kwargs):
+ """ScrollToStart(self)"""
+ return _stc.StyledTextCtrl_ScrollToStart(*args, **kwargs)
+
+ def ScrollToEnd(*args, **kwargs):
+ """ScrollToEnd(self)"""
+ return _stc.StyledTextCtrl_ScrollToEnd(*args, **kwargs)
+
+ def SetTechnology(*args, **kwargs):
+ """SetTechnology(self, int technology)"""
+ return _stc.StyledTextCtrl_SetTechnology(*args, **kwargs)
+
+ def GetTechnology(*args, **kwargs):
+ """GetTechnology(self) -> int"""
+ return _stc.StyledTextCtrl_GetTechnology(*args, **kwargs)
+
+ def CreateLoader(*args, **kwargs):
+ """CreateLoader(self, int bytes) -> void"""
+ return _stc.StyledTextCtrl_CreateLoader(*args, **kwargs)
+
+ def StartRecord(*args, **kwargs):
+ """
+ StartRecord(self)
+
+ Start notifying the container of all key presses and commands.
+ """
+ return _stc.StyledTextCtrl_StartRecord(*args, **kwargs)
+
+ def StopRecord(*args, **kwargs):
+ """
+ StopRecord(self)
+
+ Stop notifying the container of all key presses and commands.
+ """
+ return _stc.StyledTextCtrl_StopRecord(*args, **kwargs)
+
+ def SetLexer(*args, **kwargs):
+ """
+ SetLexer(self, int lexer)
+
+ Set the lexing language of the document.
+ """
+ return _stc.StyledTextCtrl_SetLexer(*args, **kwargs)
+
+ def GetLexer(*args, **kwargs):
+ """
+ GetLexer(self) -> int
+
+ Retrieve the lexing language of the document.
+ """
+ return _stc.StyledTextCtrl_GetLexer(*args, **kwargs)
+
+ def Colourise(*args, **kwargs):
+ """
+ Colourise(self, int start, int end)
+
+ Colourise a segment of the document using the current lexing language.
+ """
+ return _stc.StyledTextCtrl_Colourise(*args, **kwargs)
+
+ def SetProperty(*args, **kwargs):
+ """
+ SetProperty(self, String key, String value)
+
+ Set up a value that may be used by a lexer for some optional feature.
+ """
+ return _stc.StyledTextCtrl_SetProperty(*args, **kwargs)
+
+ def SetKeyWords(*args, **kwargs):
+ """
+ SetKeyWords(self, int keywordSet, String keyWords)
+
+ Set up the key words used by the lexer.
+ """
+ return _stc.StyledTextCtrl_SetKeyWords(*args, **kwargs)
+
+ def SetLexerLanguage(*args, **kwargs):
+ """
+ SetLexerLanguage(self, String language)
+
+ Set the lexing language of the document based on string name.
+ """
+ return _stc.StyledTextCtrl_SetLexerLanguage(*args, **kwargs)
+
+ def GetProperty(*args, **kwargs):
+ """
+ GetProperty(self, String key) -> String
+
+ Retrieve a 'property' value previously set with SetProperty.
+ """
+ return _stc.StyledTextCtrl_GetProperty(*args, **kwargs)
+
+ def GetPropertyExpanded(*args, **kwargs):
+ """
+ GetPropertyExpanded(self, String key) -> String
+
+ Retrieve a 'property' value previously set with SetProperty,
+ with '$()' variable replacement on returned buffer.
+ """
+ return _stc.StyledTextCtrl_GetPropertyExpanded(*args, **kwargs)
+
+ def GetPropertyInt(*args, **kwargs):
+ """
+ GetPropertyInt(self, String key) -> int
+
+ Retrieve a 'property' value previously set with SetProperty,
+ interpreted as an int AFTER any '$()' variable replacement.
+ """
+ return _stc.StyledTextCtrl_GetPropertyInt(*args, **kwargs)
+
+ def GetStyleBitsNeeded(*args, **kwargs):
+ """
+ GetStyleBitsNeeded(self) -> int
+
+ Retrieve the number of bits the current lexer needs for styling.
+ """
+ return _stc.StyledTextCtrl_GetStyleBitsNeeded(*args, **kwargs)
+
+ def PrivateLexerCall(*args, **kwargs):
+ """PrivateLexerCall(self, int operation, void pointer) -> void"""
+ return _stc.StyledTextCtrl_PrivateLexerCall(*args, **kwargs)
+
+ def PropertyNames(*args, **kwargs):
+ """PropertyNames(self) -> String"""
+ return _stc.StyledTextCtrl_PropertyNames(*args, **kwargs)
+
+ def PropertyType(*args, **kwargs):
+ """PropertyType(self, String name) -> int"""
+ return _stc.StyledTextCtrl_PropertyType(*args, **kwargs)
+
+ def DescribeProperty(*args, **kwargs):
+ """DescribeProperty(self, String name) -> String"""
+ return _stc.StyledTextCtrl_DescribeProperty(*args, **kwargs)
+
+ def DescribeKeyWordSets(*args, **kwargs):
+ """DescribeKeyWordSets(self) -> String"""
+ return _stc.StyledTextCtrl_DescribeKeyWordSets(*args, **kwargs)
+
+ def GetCurrentLine(*args, **kwargs):
+ """
+ GetCurrentLine(self) -> int
+
+ Returns the line number of the line with the caret.
+ """
+ return _stc.StyledTextCtrl_GetCurrentLine(*args, **kwargs)
+
+ def StyleSetSpec(*args, **kwargs):
+ """
+ StyleSetSpec(self, int styleNum, String spec)
+
+ Extract style settings from a spec-string which is composed of one or
+ more of the following comma separated elements::
+
+ bold turns on bold
+ italic turns on italics
+ fore:[name or #RRGGBB] sets the foreground colour
+ back:[name or #RRGGBB] sets the background colour
+ face:[facename] sets the font face name to use
+ size:[num] sets the font size in points
+ eol turns on eol filling
+ underline turns on underlining
+
+ """
+ return _stc.StyledTextCtrl_StyleSetSpec(*args, **kwargs)
+
+ def StyleGetFont(*args, **kwargs):
+ """StyleGetFont(self, int style) -> Font"""
+ return _stc.StyledTextCtrl_StyleGetFont(*args, **kwargs)
+
+ def StyleSetFont(*args, **kwargs):
+ """
+ StyleSetFont(self, int styleNum, Font font)
+
+ Set style size, face, bold, italic, and underline attributes from the
+ attributes of a `wx.Font`.
+ """
+ return _stc.StyledTextCtrl_StyleSetFont(*args, **kwargs)
+
+ def StyleSetFontAttr(*args, **kwargs):
+ """
+ StyleSetFontAttr(self, int styleNum, int size, String faceName, bool bold,
+ bool italic, bool underline, int encoding=wxFONTENCODING_DEFAULT)
+
+ Set all font style attributes at once.
+ """
+ return _stc.StyledTextCtrl_StyleSetFontAttr(*args, **kwargs)
+
+ def StyleSetCharacterSet(*args, **kwargs):
+ """
+ StyleSetCharacterSet(self, int style, int characterSet)
+
+ Set the character set of the font in a style. Converts the Scintilla
+ wx.stc.STC_CHARSET_* set values to a wxFontEncoding.
+ """
+ return _stc.StyledTextCtrl_StyleSetCharacterSet(*args, **kwargs)
+
+ def StyleSetFontEncoding(*args, **kwargs):
+ """
+ StyleSetFontEncoding(self, int style, int encoding)
+
+ Set the font encoding to be used by a style.
+ """
+ return _stc.StyledTextCtrl_StyleSetFontEncoding(*args, **kwargs)
+
+ def CmdKeyExecute(*args, **kwargs):
+ """
+ CmdKeyExecute(self, int cmd)
+
+ Perform one of the operations defined by the wx.stc.STC_CMD_* constants.
+ """
+ return _stc.StyledTextCtrl_CmdKeyExecute(*args, **kwargs)
+
+ def SetMargins(*args, **kwargs):
+ """
+ SetMargins(self, int left, int right)
+
+ Set the left and right margin in the edit area, measured in pixels.
+ """
+ return _stc.StyledTextCtrl_SetMargins(*args, **kwargs)
+
+ def PointFromPosition(*args, **kwargs):
+ """
+ PointFromPosition(self, int pos) -> Point
+
+ Retrieve the point in the window where a position is displayed.
+ """
+ return _stc.StyledTextCtrl_PointFromPosition(*args, **kwargs)
+
+ def ScrollToLine(*args, **kwargs):
+ """
+ ScrollToLine(self, int line)
+
+ Scroll enough to make the given line visible.
+ """
+ return _stc.StyledTextCtrl_ScrollToLine(*args, **kwargs)
+
+ def ScrollToColumn(*args, **kwargs):
+ """
+ ScrollToColumn(self, int column)
+
+ Scroll enough to make the given column visible
+ """
+ return _stc.StyledTextCtrl_ScrollToColumn(*args, **kwargs)
+
+ def SendMsg(*args, **kwargs):
+ """
+ SendMsg(self, int msg, UIntPtr wp=0, wxIntPtr lp=0) -> wxIntPtr
+
+ Send a message to Scintilla.
+ """
+ return _stc.StyledTextCtrl_SendMsg(*args, **kwargs)
+
+ def SetVScrollBar(*args, **kwargs):
+ """
+ SetVScrollBar(self, ScrollBar bar)
+
+ Set the vertical scrollbar to use instead of the one that's built-in.
+ """
+ return _stc.StyledTextCtrl_SetVScrollBar(*args, **kwargs)
+
+ def SetHScrollBar(*args, **kwargs):
+ """
+ SetHScrollBar(self, ScrollBar bar)
+
+ Set the horizontal scrollbar to use instead of the ont that's built-in.
+ """
+ return _stc.StyledTextCtrl_SetHScrollBar(*args, **kwargs)
+
+ def GetLastKeydownProcessed(*args, **kwargs):
+ """GetLastKeydownProcessed(self) -> bool"""
+ return _stc.StyledTextCtrl_GetLastKeydownProcessed(*args, **kwargs)
+
+ def SetLastKeydownProcessed(*args, **kwargs):
+ """SetLastKeydownProcessed(self, bool val)"""
+ return _stc.StyledTextCtrl_SetLastKeydownProcessed(*args, **kwargs)
+
+ def DoDragOver(*args, **kwargs):
+ """
+ DoDragOver(self, int x, int y, int def) -> int
+
+ Allow for simulating a DnD DragOver.
+ """
+ return _stc.StyledTextCtrl_DoDragOver(*args, **kwargs)
+
+ def DoDropText(*args, **kwargs):
+ """
+ DoDropText(self, long x, long y, String data) -> bool
+
+ Allow for simulating a DnD DropText.
+ """
+ return _stc.StyledTextCtrl_DoDropText(*args, **kwargs)
+
+ def SetUseAntiAliasing(*args, **kwargs):
+ """
+ SetUseAntiAliasing(self, bool useAA)
+
+ Specify whether anti-aliased fonts should be used. Will have no
+ effect on some platforms, but on some (wxMac for example) can greatly
+ improve performance.
+ """
+ return _stc.StyledTextCtrl_SetUseAntiAliasing(*args, **kwargs)
+
+ def GetUseAntiAliasing(*args, **kwargs):
+ """
+ GetUseAntiAliasing(self) -> bool
+
+ Returns the current UseAntiAliasing setting.
+ """
+ return _stc.StyledTextCtrl_GetUseAntiAliasing(*args, **kwargs)
+
+ def AnnotationClearLine(*args, **kwargs):
+ """AnnotationClearLine(self, int line)"""
+ return _stc.StyledTextCtrl_AnnotationClearLine(*args, **kwargs)
+
+ def AddTextRaw(*args, **kwargs):
+ """
+ AddTextRaw(self, char text, int length=-1)
+
+ Add text to the document at current position. The text should be
+ utf-8 encoded on unicode builds of wxPython, or can be any 8-bit text
+ in ansi builds.
+ """
+ return _stc.StyledTextCtrl_AddTextRaw(*args, **kwargs)
+
+ def InsertTextRaw(*args, **kwargs):
+ """
+ InsertTextRaw(self, int pos, char text)
+
+ Insert string at a position. The text should be utf-8 encoded on
+ unicode builds of wxPython, or can be any 8-bit text in ansi builds.
+ """
+ return _stc.StyledTextCtrl_InsertTextRaw(*args, **kwargs)
+
+ def GetCurLineRaw(*args, **kwargs):
+ """
+ GetCurLineRaw() -> (text, index)
+
+ Retrieve the text of the line containing the caret, and also the index
+ of the caret on the line. The returned value is a utf-8 encoded
+ string in unicode builds of wxPython, or raw 8-bit text otherwise.
+ """
+ return _stc.StyledTextCtrl_GetCurLineRaw(*args, **kwargs)
+
+ def GetLineRaw(*args, **kwargs):
+ """
+ GetLineRaw(self, int line) -> wxCharBuffer
+
+ Retrieve the contents of a line. The returned value is a utf-8
+ encoded string in unicode builds of wxPython, or raw 8-bit text
+ otherwise.
+ """
+ return _stc.StyledTextCtrl_GetLineRaw(*args, **kwargs)
+
+ def GetSelectedTextRaw(*args, **kwargs):
+ """
+ GetSelectedTextRaw(self) -> wxCharBuffer
+
+ Retrieve the selected text. The returned value is a utf-8 encoded
+ string in unicode builds of wxPython, or raw 8-bit text otherwise.
+ """
+ return _stc.StyledTextCtrl_GetSelectedTextRaw(*args, **kwargs)
+
+ def GetTextRangeRaw(*args, **kwargs):
+ """
+ GetTextRangeRaw(self, int startPos, int endPos) -> wxCharBuffer
+
+ Retrieve a range of text. The returned value is a utf-8 encoded
+ string in unicode builds of wxPython, or raw 8-bit text otherwise.
+ """
+ return _stc.StyledTextCtrl_GetTextRangeRaw(*args, **kwargs)
+
+ def SetTextRaw(*args, **kwargs):
+ """
+ SetTextRaw(self, char text)
+
+ Replace the contents of the document with the argument text. The text
+ should be utf-8 encoded on unicode builds of wxPython, or can be any
+ 8-bit text in ansi builds.
+ """
+ return _stc.StyledTextCtrl_SetTextRaw(*args, **kwargs)
+
+ def GetTextRaw(*args, **kwargs):
+ """
+ GetTextRaw(self) -> wxCharBuffer
+
+ Retrieve all the text in the document. The returned value is a utf-8
+ encoded string in unicode builds of wxPython, or raw 8-bit text
+ otherwise.
+ """
+ return _stc.StyledTextCtrl_GetTextRaw(*args, **kwargs)
+
+ def AppendTextRaw(*args, **kwargs):
+ """
+ AppendTextRaw(self, char text, int length=-1)
+
+ Append a string to the end of the document without changing the
+ selection. The text should be utf-8 encoded on unicode builds of
+ wxPython, or can be any 8-bit text in ansi builds.
+ """
+ return _stc.StyledTextCtrl_AppendTextRaw(*args, **kwargs)
+
+ def AddTextUTF8(self, text):
+ """
+ Add UTF8 encoded text to the document at the current position.
+ Works 'natively' in a unicode build of wxPython, and will also work
+ in an ansi build if the UTF8 text is compatible with the current
+ encoding.
+ """
+ if not wx.USE_UNICODE:
+ u = text.decode('utf-8')
+ text = u.encode(wx.GetDefaultPyEncoding())
+ self.AddTextRaw(text)
+
+
+ def InsertTextUTF8(self, pos, text):
+ """
+ Insert UTF8 encoded text at a position. Works 'natively' in a
+ unicode build of wxPython, and will also work in an ansi build if
+ the UTF8 text is compatible with the current encoding.
+ """
+ if not wx.USE_UNICODE:
+ u = text.decode('utf-8')
+ text = u.encode(wx.GetDefaultPyEncoding())
+ self.InsertTextRaw(pos, text)
+
+
+ def GetCurLineUTF8(self):
+ """
+ Retrieve the UTF8 text of the line containing the caret, and also
+ the index of the caret on the line. In an ansi build of wxPython
+ the text retrieved from the document is assumed to be in the
+ current default encoding.
+ """
+ text, pos = self.GetCurLineRaw()
+ if not wx.USE_UNICODE:
+ u = text.decode(wx.GetDefaultPyEncoding())
+ text = u.encode('utf-8')
+ return text, pos
+
+
+ def GetLineUTF8(self, line):
+ """
+ Retrieve the contents of a line as UTF8. In an ansi build of wxPython
+ the text retrieved from the document is assumed to be in the
+ current default encoding.
+ """
+ text = self.GetLineRaw(line)
+ if not wx.USE_UNICODE:
+ u = text.decode(wx.GetDefaultPyEncoding())
+ text = u.encode('utf-8')
+ return text
+
+
+ def GetSelectedTextUTF8(self):
+ """
+ Retrieve the selected text as UTF8. In an ansi build of wxPython
+ the text retrieved from the document is assumed to be in the
+ current default encoding.
+ """
+ text = self.GetSelectedTextRaw()
+ if not wx.USE_UNICODE:
+ u = text.decode(wx.GetDefaultPyEncoding())
+ text = u.encode('utf-8')
+ return text
+
+
+ def GetTextRangeUTF8(self, startPos, endPos):
+ """
+ Retrieve a range of text as UTF8. In an ansi build of wxPython
+ the text retrieved from the document is assumed to be in the
+ current default encoding.
+ """
+ text = self.GetTextRangeRaw(startPos, endPos)
+ if not wx.USE_UNICODE:
+ u = text.decode(wx.GetDefaultPyEncoding())
+ text = u.encode('utf-8')
+ return text
+
+
+ def SetTextUTF8(self, text):
+ """
+ Replace the contents of the document with the UTF8 text given.
+ Works 'natively' in a unicode build of wxPython, and will also
+ work in an ansi build if the UTF8 text is compatible with the
+ current encoding.
+ """
+ if not wx.USE_UNICODE:
+ u = text.decode('utf-8')
+ text = u.encode(wx.GetDefaultPyEncoding())
+ self.SetTextRaw(text)
+
+
+ def GetTextUTF8(self):
+ """
+ Retrieve all the text in the document as UTF8. In an ansi build
+ of wxPython the text retrieved from the document is assumed to be
+ in the current default encoding.
+ """
+ text = self.GetTextRaw()
+ if not wx.USE_UNICODE:
+ u = text.decode(wx.GetDefaultPyEncoding())
+ text = u.encode('utf-8')
+ return text
+
+
+ def AppendTextUTF8(self, text):
+ """
+ Append a UTF8 string to the end of the document without changing
+ the selection. Works 'natively' in a unicode build of wxPython,
+ and will also work in an ansi build if the UTF8 text is compatible
+ with the current encoding.
+ """
+ if not wx.USE_UNICODE:
+ u = text.decode('utf-8')
+ text = u.encode(wx.GetDefaultPyEncoding())
+ self.AppendTextRaw(text)
+
+
+ def SelectNone(*args, **kwargs):
+ """SelectNone(self)"""
+ return _stc.StyledTextCtrl_SelectNone(*args, **kwargs)
+
+ def PositionToXY(*args, **kwargs):
+ """PositionToXY(long pos) -> (x, y)"""
+ return _stc.StyledTextCtrl_PositionToXY(*args, **kwargs)
+
+ def GetLibraryVersionInfo(*args, **kwargs):
+ """GetLibraryVersionInfo() -> VersionInfo"""
+ return _stc.StyledTextCtrl_GetLibraryVersionInfo(*args, **kwargs)
+
+ GetLibraryVersionInfo = staticmethod(GetLibraryVersionInfo)
+ GetCaretLineBack = GetCaretLineBackground
+ SetCaretLineBack = SetCaretLineBackground
+
+ Anchor = property(GetAnchor,SetAnchor)
+ BackSpaceUnIndents = property(GetBackSpaceUnIndents,SetBackSpaceUnIndents)
+ BufferedDraw = property(GetBufferedDraw,SetBufferedDraw)
+ CaretForeground = property(GetCaretForeground,SetCaretForeground)
+ CaretLineBack = property(GetCaretLineBack,SetCaretLineBack)
+ CaretLineBackAlpha = property(GetCaretLineBackAlpha,SetCaretLineBackAlpha)
+ CaretLineBackground = property(GetCaretLineBackground,SetCaretLineBackground)
+ CaretLineVisible = property(GetCaretLineVisible,SetCaretLineVisible)
+ CaretPeriod = property(GetCaretPeriod,SetCaretPeriod)
+ CaretSticky = property(GetCaretSticky,SetCaretSticky)
+ CaretWidth = property(GetCaretWidth,SetCaretWidth)
+ CodePage = property(GetCodePage,SetCodePage)
+ ControlCharSymbol = property(GetControlCharSymbol,SetControlCharSymbol)
+ CurLine = property(GetCurLine)
+ CurLineRaw = property(GetCurLineRaw)
+ CurLineUTF8 = property(GetCurLineUTF8)
+ CurrentLine = property(GetCurrentLine)
+ CurrentPos = property(GetCurrentPos,SetCurrentPos)
+ DocPointer = property(GetDocPointer,SetDocPointer)
+ EOLMode = property(GetEOLMode,SetEOLMode)
+ EdgeColour = property(GetEdgeColour,SetEdgeColour)
+ EdgeColumn = property(GetEdgeColumn,SetEdgeColumn)
+ EdgeMode = property(GetEdgeMode,SetEdgeMode)
+ EndAtLastLine = property(GetEndAtLastLine,SetEndAtLastLine)
+ EndStyled = property(GetEndStyled)
+ FirstVisibleLine = property(GetFirstVisibleLine)
+ HighlightGuide = property(GetHighlightGuide,SetHighlightGuide)
+ Indent = property(GetIndent,SetIndent)
+ IndentationGuides = property(GetIndentationGuides,SetIndentationGuides)
+ LastKeydownProcessed = property(GetLastKeydownProcessed,SetLastKeydownProcessed)
+ LayoutCache = property(GetLayoutCache,SetLayoutCache)
+ Length = property(GetLength)
+ Lexer = property(GetLexer,SetLexer)
+ LineCount = property(GetLineCount)
+ MarginLeft = property(GetMarginLeft,SetMarginLeft)
+ MarginRight = property(GetMarginRight,SetMarginRight)
+ MaxLineState = property(GetMaxLineState)
+ ModEventMask = property(GetModEventMask,SetModEventMask)
+ Modify = property(GetModify)
+ MouseDownCaptures = property(GetMouseDownCaptures,SetMouseDownCaptures)
+ MouseDwellTime = property(GetMouseDwellTime,SetMouseDwellTime)
+ Overtype = property(GetOvertype,SetOvertype)
+ PasteConvertEndings = property(GetPasteConvertEndings,SetPasteConvertEndings)
+ PrintColourMode = property(GetPrintColourMode,SetPrintColourMode)
+ PrintMagnification = property(GetPrintMagnification,SetPrintMagnification)
+ PrintWrapMode = property(GetPrintWrapMode,SetPrintWrapMode)
+ ReadOnly = property(GetReadOnly,SetReadOnly)
+ STCCursor = property(GetSTCCursor,SetSTCCursor)
+ STCFocus = property(GetSTCFocus,SetSTCFocus)
+ ScrollWidth = property(GetScrollWidth,SetScrollWidth)
+ SearchFlags = property(GetSearchFlags,SetSearchFlags)
+ SelAlpha = property(GetSelAlpha,SetSelAlpha)
+ SelectedText = property(GetSelectedText)
+ SelectedTextRaw = property(GetSelectedTextRaw)
+ SelectedTextUTF8 = property(GetSelectedTextUTF8)
+ SelectionEnd = property(GetSelectionEnd,SetSelectionEnd)
+ SelectionMode = property(GetSelectionMode,SetSelectionMode)
+ SelectionStart = property(GetSelectionStart,SetSelectionStart)
+ Status = property(GetStatus,SetStatus)
+ StyleBits = property(GetStyleBits,SetStyleBits)
+ StyleBitsNeeded = property(GetStyleBitsNeeded)
+ TabIndents = property(GetTabIndents,SetTabIndents)
+ TabWidth = property(GetTabWidth,SetTabWidth)
+ TargetEnd = property(GetTargetEnd,SetTargetEnd)
+ TargetStart = property(GetTargetStart,SetTargetStart)
+ Text = property(GetText,SetText)
+ TextLength = property(GetTextLength)
+ TextRaw = property(GetTextRaw,SetTextRaw)
+ TextUTF8 = property(GetTextUTF8,SetTextUTF8)
+ TwoPhaseDraw = property(GetTwoPhaseDraw,SetTwoPhaseDraw)
+ UndoCollection = property(GetUndoCollection,SetUndoCollection)
+ UseAntiAliasing = property(GetUseAntiAliasing,SetUseAntiAliasing)
+ UseHorizontalScrollBar = property(GetUseHorizontalScrollBar,SetUseHorizontalScrollBar)
+ UseTabs = property(GetUseTabs,SetUseTabs)
+ UseVerticalScrollBar = property(GetUseVerticalScrollBar,SetUseVerticalScrollBar)
+ ViewEOL = property(GetViewEOL,SetViewEOL)
+ ViewWhiteSpace = property(GetViewWhiteSpace,SetViewWhiteSpace)
+ WrapMode = property(GetWrapMode,SetWrapMode)
+ WrapStartIndent = property(GetWrapStartIndent,SetWrapStartIndent)
+ WrapVisualFlags = property(GetWrapVisualFlags,SetWrapVisualFlags)
+ WrapVisualFlagsLocation = property(GetWrapVisualFlagsLocation,SetWrapVisualFlagsLocation)
+ XOffset = property(GetXOffset,SetXOffset)
+ Zoom = property(GetZoom,SetZoom)
+ SelEOLFilled = property(GetSelEOLFilled,SetSelEOLFilled)
+ ScrollWidthTracking = property(GetScrollWidthTracking,SetScrollWidthTracking)
+ HotspotActiveForeground = property(GetHotspotActiveForeground,SetHotspotActiveForeground)
+ HotspotActiveBackground = property(GetHotspotActiveBackground,SetHotspotActiveBackground)
+ HotspotActiveUnderline = property(GetHotspotActiveUnderline,SetHotspotActiveUnderline)
+ HotspotSingleLine = property(GetHotspotSingleLine,SetHotspotSingleLine)
+ CaretStyle = property(GetCaretStyle,SetCaretStyle)
+ IndicatorCurrent = property(GetIndicatorCurrent,SetIndicatorCurrent)
+ IndicatorValue = property(GetIndicatorValue,SetIndicatorValue)
+ PositionCacheSize = property(GetPositionCacheSize,SetPositionCacheSize)
+_stc.StyledTextCtrl_swigregister(StyledTextCtrl)
+cvar = _stc.cvar
+STCNameStr = cvar.STCNameStr
+
+def PreStyledTextCtrl(*args, **kwargs):
+ """PreStyledTextCtrl() -> StyledTextCtrl"""
+ val = _stc.new_PreStyledTextCtrl(*args, **kwargs)
+ return val
+
+def StyledTextCtrl_GetLibraryVersionInfo(*args):
+ """StyledTextCtrl_GetLibraryVersionInfo() -> VersionInfo"""
+ return _stc.StyledTextCtrl_GetLibraryVersionInfo(*args)
+
+class StyledTextEvent(_core.CommandEvent):
+ """Proxy of C++ StyledTextEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, EventType commandType=0, int id=0) -> StyledTextEvent"""
+ _stc.StyledTextEvent_swiginit(self,_stc.new_StyledTextEvent(*args, **kwargs))
+ __swig_destroy__ = _stc.delete_StyledTextEvent
+ __del__ = lambda self : None;
+ def SetPosition(*args, **kwargs):
+ """SetPosition(self, int pos)"""
+ return _stc.StyledTextEvent_SetPosition(*args, **kwargs)
+
+ def SetKey(*args, **kwargs):
+ """SetKey(self, int k)"""
+ return _stc.StyledTextEvent_SetKey(*args, **kwargs)
+
+ def SetModifiers(*args, **kwargs):
+ """SetModifiers(self, int m)"""
+ return _stc.StyledTextEvent_SetModifiers(*args, **kwargs)
+
+ def SetModificationType(*args, **kwargs):
+ """SetModificationType(self, int t)"""
+ return _stc.StyledTextEvent_SetModificationType(*args, **kwargs)
+
+ def SetText(*args, **kwargs):
+ """SetText(self, String t)"""
+ return _stc.StyledTextEvent_SetText(*args, **kwargs)
+
+ def SetLength(*args, **kwargs):
+ """SetLength(self, int len)"""
+ return _stc.StyledTextEvent_SetLength(*args, **kwargs)
+
+ def SetLinesAdded(*args, **kwargs):
+ """SetLinesAdded(self, int num)"""
+ return _stc.StyledTextEvent_SetLinesAdded(*args, **kwargs)
+
+ def SetLine(*args, **kwargs):
+ """SetLine(self, int val)"""
+ return _stc.StyledTextEvent_SetLine(*args, **kwargs)
+
+ def SetFoldLevelNow(*args, **kwargs):
+ """SetFoldLevelNow(self, int val)"""
+ return _stc.StyledTextEvent_SetFoldLevelNow(*args, **kwargs)
+
+ def SetFoldLevelPrev(*args, **kwargs):
+ """SetFoldLevelPrev(self, int val)"""
+ return _stc.StyledTextEvent_SetFoldLevelPrev(*args, **kwargs)
+
+ def SetMargin(*args, **kwargs):
+ """SetMargin(self, int val)"""
+ return _stc.StyledTextEvent_SetMargin(*args, **kwargs)
+
+ def SetMessage(*args, **kwargs):
+ """SetMessage(self, int val)"""
+ return _stc.StyledTextEvent_SetMessage(*args, **kwargs)
+
+ def SetWParam(*args, **kwargs):
+ """SetWParam(self, int val)"""
+ return _stc.StyledTextEvent_SetWParam(*args, **kwargs)
+
+ def SetLParam(*args, **kwargs):
+ """SetLParam(self, int val)"""
+ return _stc.StyledTextEvent_SetLParam(*args, **kwargs)
+
+ def SetListType(*args, **kwargs):
+ """SetListType(self, int val)"""
+ return _stc.StyledTextEvent_SetListType(*args, **kwargs)
+
+ def SetX(*args, **kwargs):
+ """SetX(self, int val)"""
+ return _stc.StyledTextEvent_SetX(*args, **kwargs)
+
+ def SetY(*args, **kwargs):
+ """SetY(self, int val)"""
+ return _stc.StyledTextEvent_SetY(*args, **kwargs)
+
+ def SetToken(*args, **kwargs):
+ """SetToken(self, int val)"""
+ return _stc.StyledTextEvent_SetToken(*args, **kwargs)
+
+ def SetAnnotationLinesAdded(*args, **kwargs):
+ """SetAnnotationLinesAdded(self, int val)"""
+ return _stc.StyledTextEvent_SetAnnotationLinesAdded(*args, **kwargs)
+
+ def SetUpdated(*args, **kwargs):
+ """SetUpdated(self, int val)"""
+ return _stc.StyledTextEvent_SetUpdated(*args, **kwargs)
+
+ def SetDragText(*args, **kwargs):
+ """SetDragText(self, String val)"""
+ return _stc.StyledTextEvent_SetDragText(*args, **kwargs)
+
+ def SetDragFlags(*args, **kwargs):
+ """SetDragFlags(self, int flags)"""
+ return _stc.StyledTextEvent_SetDragFlags(*args, **kwargs)
+
+ def SetDragResult(*args, **kwargs):
+ """SetDragResult(self, int val)"""
+ return _stc.StyledTextEvent_SetDragResult(*args, **kwargs)
+
+ def SetDragAllowMove(*args, **kwargs):
+ """SetDragAllowMove(self, bool allow)"""
+ return _stc.StyledTextEvent_SetDragAllowMove(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self) -> int"""
+ return _stc.StyledTextEvent_GetPosition(*args, **kwargs)
+
+ def GetKey(*args, **kwargs):
+ """GetKey(self) -> int"""
+ return _stc.StyledTextEvent_GetKey(*args, **kwargs)
+
+ def GetModifiers(*args, **kwargs):
+ """GetModifiers(self) -> int"""
+ return _stc.StyledTextEvent_GetModifiers(*args, **kwargs)
+
+ def GetModificationType(*args, **kwargs):
+ """GetModificationType(self) -> int"""
+ return _stc.StyledTextEvent_GetModificationType(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self) -> String"""
+ return _stc.StyledTextEvent_GetText(*args, **kwargs)
+
+ def GetLength(*args, **kwargs):
+ """GetLength(self) -> int"""
+ return _stc.StyledTextEvent_GetLength(*args, **kwargs)
+
+ def GetLinesAdded(*args, **kwargs):
+ """GetLinesAdded(self) -> int"""
+ return _stc.StyledTextEvent_GetLinesAdded(*args, **kwargs)
+
+ def GetLine(*args, **kwargs):
+ """GetLine(self) -> int"""
+ return _stc.StyledTextEvent_GetLine(*args, **kwargs)
+
+ def GetFoldLevelNow(*args, **kwargs):
+ """GetFoldLevelNow(self) -> int"""
+ return _stc.StyledTextEvent_GetFoldLevelNow(*args, **kwargs)
+
+ def GetFoldLevelPrev(*args, **kwargs):
+ """GetFoldLevelPrev(self) -> int"""
+ return _stc.StyledTextEvent_GetFoldLevelPrev(*args, **kwargs)
+
+ def GetMargin(*args, **kwargs):
+ """GetMargin(self) -> int"""
+ return _stc.StyledTextEvent_GetMargin(*args, **kwargs)
+
+ def GetMessage(*args, **kwargs):
+ """GetMessage(self) -> int"""
+ return _stc.StyledTextEvent_GetMessage(*args, **kwargs)
+
+ def GetWParam(*args, **kwargs):
+ """GetWParam(self) -> int"""
+ return _stc.StyledTextEvent_GetWParam(*args, **kwargs)
+
+ def GetLParam(*args, **kwargs):
+ """GetLParam(self) -> int"""
+ return _stc.StyledTextEvent_GetLParam(*args, **kwargs)
+
+ def GetListType(*args, **kwargs):
+ """GetListType(self) -> int"""
+ return _stc.StyledTextEvent_GetListType(*args, **kwargs)
+
+ def GetX(*args, **kwargs):
+ """GetX(self) -> int"""
+ return _stc.StyledTextEvent_GetX(*args, **kwargs)
+
+ def GetY(*args, **kwargs):
+ """GetY(self) -> int"""
+ return _stc.StyledTextEvent_GetY(*args, **kwargs)
+
+ def GetToken(*args, **kwargs):
+ """GetToken(self) -> int"""
+ return _stc.StyledTextEvent_GetToken(*args, **kwargs)
+
+ def GetAnnotationsLinesAdded(*args, **kwargs):
+ """GetAnnotationsLinesAdded(self) -> int"""
+ return _stc.StyledTextEvent_GetAnnotationsLinesAdded(*args, **kwargs)
+
+ def GetUpdated(*args, **kwargs):
+ """GetUpdated(self) -> int"""
+ return _stc.StyledTextEvent_GetUpdated(*args, **kwargs)
+
+ def GetDragText(*args, **kwargs):
+ """GetDragText(self) -> String"""
+ return _stc.StyledTextEvent_GetDragText(*args, **kwargs)
+
+ def GetDragFlags(*args, **kwargs):
+ """GetDragFlags(self) -> int"""
+ return _stc.StyledTextEvent_GetDragFlags(*args, **kwargs)
+
+ def GetDragResult(*args, **kwargs):
+ """GetDragResult(self) -> int"""
+ return _stc.StyledTextEvent_GetDragResult(*args, **kwargs)
+
+ def GetDragAllowMove(*args, **kwargs):
+ """GetDragAllowMove(self) -> bool"""
+ return _stc.StyledTextEvent_GetDragAllowMove(*args, **kwargs)
+
+ def GetShift(*args, **kwargs):
+ """GetShift(self) -> bool"""
+ return _stc.StyledTextEvent_GetShift(*args, **kwargs)
+
+ def GetControl(*args, **kwargs):
+ """GetControl(self) -> bool"""
+ return _stc.StyledTextEvent_GetControl(*args, **kwargs)
+
+ def GetAlt(*args, **kwargs):
+ """GetAlt(self) -> bool"""
+ return _stc.StyledTextEvent_GetAlt(*args, **kwargs)
+
+ Alt = property(GetAlt)
+ Control = property(GetControl)
+ DragAllowMove = property(GetDragAllowMove,SetDragAllowMove)
+ DragResult = property(GetDragResult,SetDragResult)
+ DragText = property(GetDragText,SetDragText)
+ FoldLevelNow = property(GetFoldLevelNow,SetFoldLevelNow)
+ FoldLevelPrev = property(GetFoldLevelPrev,SetFoldLevelPrev)
+ Key = property(GetKey,SetKey)
+ LParam = property(GetLParam,SetLParam)
+ Length = property(GetLength,SetLength)
+ Line = property(GetLine,SetLine)
+ LinesAdded = property(GetLinesAdded,SetLinesAdded)
+ ListType = property(GetListType,SetListType)
+ Margin = property(GetMargin,SetMargin)
+ Message = property(GetMessage,SetMessage)
+ ModificationType = property(GetModificationType,SetModificationType)
+ Modifiers = property(GetModifiers,SetModifiers)
+ Position = property(GetPosition,SetPosition)
+ Shift = property(GetShift)
+ Text = property(GetText,SetText)
+ WParam = property(GetWParam,SetWParam)
+ X = property(GetX,SetX)
+ Y = property(GetY,SetY)
+_stc.StyledTextEvent_swigregister(StyledTextEvent)
+
+wxEVT_STC_CHANGE = _stc.wxEVT_STC_CHANGE
+wxEVT_STC_STYLENEEDED = _stc.wxEVT_STC_STYLENEEDED
+wxEVT_STC_CHARADDED = _stc.wxEVT_STC_CHARADDED
+wxEVT_STC_SAVEPOINTREACHED = _stc.wxEVT_STC_SAVEPOINTREACHED
+wxEVT_STC_SAVEPOINTLEFT = _stc.wxEVT_STC_SAVEPOINTLEFT
+wxEVT_STC_ROMODIFYATTEMPT = _stc.wxEVT_STC_ROMODIFYATTEMPT
+wxEVT_STC_KEY = _stc.wxEVT_STC_KEY
+wxEVT_STC_DOUBLECLICK = _stc.wxEVT_STC_DOUBLECLICK
+wxEVT_STC_UPDATEUI = _stc.wxEVT_STC_UPDATEUI
+wxEVT_STC_MODIFIED = _stc.wxEVT_STC_MODIFIED
+wxEVT_STC_MACRORECORD = _stc.wxEVT_STC_MACRORECORD
+wxEVT_STC_MARGINCLICK = _stc.wxEVT_STC_MARGINCLICK
+wxEVT_STC_NEEDSHOWN = _stc.wxEVT_STC_NEEDSHOWN
+wxEVT_STC_PAINTED = _stc.wxEVT_STC_PAINTED
+wxEVT_STC_USERLISTSELECTION = _stc.wxEVT_STC_USERLISTSELECTION
+wxEVT_STC_URIDROPPED = _stc.wxEVT_STC_URIDROPPED
+wxEVT_STC_DWELLSTART = _stc.wxEVT_STC_DWELLSTART
+wxEVT_STC_DWELLEND = _stc.wxEVT_STC_DWELLEND
+wxEVT_STC_START_DRAG = _stc.wxEVT_STC_START_DRAG
+wxEVT_STC_DRAG_OVER = _stc.wxEVT_STC_DRAG_OVER
+wxEVT_STC_DO_DROP = _stc.wxEVT_STC_DO_DROP
+wxEVT_STC_ZOOM = _stc.wxEVT_STC_ZOOM
+wxEVT_STC_HOTSPOT_CLICK = _stc.wxEVT_STC_HOTSPOT_CLICK
+wxEVT_STC_HOTSPOT_DCLICK = _stc.wxEVT_STC_HOTSPOT_DCLICK
+wxEVT_STC_CALLTIP_CLICK = _stc.wxEVT_STC_CALLTIP_CLICK
+wxEVT_STC_AUTOCOMP_SELECTION = _stc.wxEVT_STC_AUTOCOMP_SELECTION
+wxEVT_STC_INDICATOR_CLICK = _stc.wxEVT_STC_INDICATOR_CLICK
+wxEVT_STC_INDICATOR_RELEASE = _stc.wxEVT_STC_INDICATOR_RELEASE
+wxEVT_STC_AUTOCOMP_CANCELLED = _stc.wxEVT_STC_AUTOCOMP_CANCELLED
+wxEVT_STC_AUTOCOMP_CHAR_DELETED = _stc.wxEVT_STC_AUTOCOMP_CHAR_DELETED
+wxEVT_STC_HOTSPOT_RELEASE_CLICK = _stc.wxEVT_STC_HOTSPOT_RELEASE_CLICK
+EVT_STC_CHANGE = wx.PyEventBinder( wxEVT_STC_CHANGE, 1 )
+EVT_STC_STYLENEEDED = wx.PyEventBinder( wxEVT_STC_STYLENEEDED, 1 )
+EVT_STC_CHARADDED = wx.PyEventBinder( wxEVT_STC_CHARADDED, 1 )
+EVT_STC_SAVEPOINTREACHED = wx.PyEventBinder( wxEVT_STC_SAVEPOINTREACHED, 1 )
+EVT_STC_SAVEPOINTLEFT = wx.PyEventBinder( wxEVT_STC_SAVEPOINTLEFT, 1 )
+EVT_STC_ROMODIFYATTEMPT = wx.PyEventBinder( wxEVT_STC_ROMODIFYATTEMPT, 1 )
+EVT_STC_KEY = wx.PyEventBinder( wxEVT_STC_KEY, 1 )
+EVT_STC_DOUBLECLICK = wx.PyEventBinder( wxEVT_STC_DOUBLECLICK, 1 )
+EVT_STC_UPDATEUI = wx.PyEventBinder( wxEVT_STC_UPDATEUI, 1 )
+EVT_STC_MODIFIED = wx.PyEventBinder( wxEVT_STC_MODIFIED, 1 )
+EVT_STC_MACRORECORD = wx.PyEventBinder( wxEVT_STC_MACRORECORD, 1 )
+EVT_STC_MARGINCLICK = wx.PyEventBinder( wxEVT_STC_MARGINCLICK, 1 )
+EVT_STC_NEEDSHOWN = wx.PyEventBinder( wxEVT_STC_NEEDSHOWN, 1 )
+EVT_STC_PAINTED = wx.PyEventBinder( wxEVT_STC_PAINTED, 1 )
+EVT_STC_USERLISTSELECTION = wx.PyEventBinder( wxEVT_STC_USERLISTSELECTION, 1 )
+EVT_STC_URIDROPPED = wx.PyEventBinder( wxEVT_STC_URIDROPPED, 1 )
+EVT_STC_DWELLSTART = wx.PyEventBinder( wxEVT_STC_DWELLSTART, 1 )
+EVT_STC_DWELLEND = wx.PyEventBinder( wxEVT_STC_DWELLEND, 1 )
+EVT_STC_START_DRAG = wx.PyEventBinder( wxEVT_STC_START_DRAG, 1 )
+EVT_STC_DRAG_OVER = wx.PyEventBinder( wxEVT_STC_DRAG_OVER, 1 )
+EVT_STC_DO_DROP = wx.PyEventBinder( wxEVT_STC_DO_DROP, 1 )
+EVT_STC_ZOOM = wx.PyEventBinder( wxEVT_STC_ZOOM, 1 )
+EVT_STC_HOTSPOT_CLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_CLICK, 1 )
+EVT_STC_HOTSPOT_DCLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_DCLICK, 1 )
+EVT_STC_CALLTIP_CLICK = wx.PyEventBinder( wxEVT_STC_CALLTIP_CLICK, 1 )
+EVT_STC_AUTOCOMP_SELECTION = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_SELECTION, 1 )
+EVT_STC_INDICATOR_CLICK = wx.PyEventBinder( wxEVT_STC_INDICATOR_CLICK, 1 )
+EVT_STC_INDICATOR_RELEASE = wx.PyEventBinder( wxEVT_STC_INDICATOR_RELEASE, 1 )
+EVT_STC_AUTOCOMP_CANCELLED = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_CANCELLED, 1 )
+EVT_STC_AUTOCOMP_CHAR_DELETED = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_CHAR_DELETED, 1 )
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/AUTHORS b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/AUTHORS
new file mode 100644
index 0000000..37722bb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/AUTHORS
@@ -0,0 +1,35 @@
+Editra
+Developer's Text Editor
+
+Author:
+Cody Precord <cprecord@editra.org>
+
+Translations:
+Angelo (Italian)
+Anri Ito (Japanese)
+Cody Precord (English/Japanese)
+DR0ID (German)
+gasolin (Traditional Chinese)
+Gerard Petersen (Dutch)
+heccj (Simplified Chinese)
+Igor Chomko (Ukrainian)
+Janis.sl (Latvian)
+JoNNeMaNN (Norwegian Nynorsk)
+mustafa (Turkish)
+Raul Gonzalez Duque (Spanish)
+Sergei Zivukov (Russian)
+shaohao (Simplified Chinese)
+slavOnic (Russian)
+Peter Magnusson (Swedish)
+Tomas Fryda (Czech)
+Vladimir Lazic (Serbian)
+And many more, see the launchpad site for a full list of contributors!
+
+Contributors:
+DR0ID (Comment Browser)
+Kevin Smith (Projects Plugin)
+Laurent Dufrenchou (IPyShell)
+Kurt Schelin (App Icon Design)
+shaohao (Statusbar improvement patch)
+Giuseppe "Cowo" Corbelli (various patches)
+quode (OCaml support for Launch plugin)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/CHANGELOG b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/CHANGELOG
new file mode 100644
index 0000000..89cc7ab
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/CHANGELOG
@@ -0,0 +1,163 @@
+# encoding: utf-8
+Editra
+Author: Cody Precord
+Copyright: (c) Cody Precord 2005-2013
+License: wxWindows
+
+Change Log:
+
+#-----------------------------------------------------------------------------#
+Changes since last release:
+
+VERSION 0.7.xx
+DATE xx/xx/2013
+54th Alpha Release
+
+NEW: [features/enhancements]
+
+BUG FIXES:
++Fix some keyboard issues on OSX when Shift key has been held down.
++Fix issue with characters incorrectly getting inserted into buffer when
+invoking a Redo action with nothing left to redo left in stack (OSX).
++Fix text alignment issue with PlateButton control when the button is expanded
+beyond its intended best size.
+
+#-----------------------------------------------------------------------------#
+
+VERSION 0.7.20
+DATE 01/05/2013
+53rd Alpha Release
+
+NEW: [features/enhancements]
++Extended CSS highlighting support. Near complete support for CSS3.
++Updated FileBrowser plugin to version 2.2 (bug fixes)
+
+BUG FIXES:
++Handle error in style manager when default font face name is unknown.
++Fix unwanted/invalid completion issue in HTML autocompletion for open brackets
+on lines with tabs in them.
++Fix PyDeadObject that could occur during reload file request.
++Fix crash that could occur during formatting of log messages.
++Handle PyDeadObject error that could occur when changing tab icons
++Don't handle Shift+Delete as forward delete on OSX (issue 721)
++Fix caret bouncing in TextCtrls on Windows (issue 664)
++Fix PyDeadObject errors related to notebook in multiple windows.
++Fix assertions caused by right clicks in certain areas of tree controls.
++Fix Line End command not working correctly in some cases on OSX.
+
+#-----------------------------------------------------------------------------#
+
+VERSION 0.7.12
+DATE 08/12/2012
+52nd Alpha Release
+
+NEW: [features/enhancements]
+
+BUG FIXES:
++Fix unable to edit file extension associations on Linux systems (issue 745).
++Fix issue with duplicated @ symbols inserted by generic completer (issue 743).
++Fix some Unicode handling issues in log handler.
++Fix bug in Tango art provider fallback code which could end up looking in
+Default theme instead of Tango theme directory for mime icons.
++Fix PyDeadObject errors related to failed destruction calls by AuiManger.
+
+#-----------------------------------------------------------------------------#
+
+VERSION 0.7.08
+DATE 07/15/2012
+51st Alpha Release
+
+NEW: [features/enhancements]
++New version of FileBrowser Plugin version 2.0. Nearly a complete re-write of
+the main part of the plugin to use a new file view. Adds ability to turn editor
+tab synchronization on and off. Adds configuration for filtering files out of the
+view and new configuration for showing hidden files.
++Choose directory dialog from Find Dialog will now automatically expand to the directory of the
+current file.
++Update embedded aui
+
+BUG FIXES:
++Fix major and apparently very long standing issue on Windows systems where
+application profiles were not getting updated correctly and settings would get
+lost between updates.
++Fix issues with sessions not getting updated properly under some use cases.
++Fix crash condition that could occur when reload of file fails.
++Fix file encoding detection issue that some systems experienced.
++Fix UTF-16 decoding issues / regressions due to change in behavior between
+python2.6 and 2.7.
++Fix error caused by empty file names getting into the file history which
+could cause startup failures.
++Fix crash in Find in Directory that could occur due to threaded access to GetTranslation.
+
+#-----------------------------------------------------------------------------#
+
+VERSION 0.7.01
+DATE 04/23/2012
+50th Alpha Release
+
+NEWS:
+Update to fix issue with translations.
+
+BUG FIXES:
++Fix localizations not loading correctly.
+
+#-----------------------------------------------------------------------------#
+VERSION 0.7.00
+DATE 04/22/2012
+49th Alpha Release
+
+NEWS:
+This is a stabilization and maintenance release targeting bugs that have been reported over the
+last several months. Biggest fix is to try to correct some utf-8 handling errors
+that were observed by some users of the 0.6.99 release. See release notes below
+for specific changes in this release.
+
+NEW: [features/enhancements]
++New version of CodeBrowser plugin (bug fixes for Python / XML / HTML)
++New version of Launch (configurable line buffering, bug fixes)
++Update all translations with current launchpad.
+
+BUG FIXES:
++Fix error that could occur when selecting text in some environments under
+certain cases.
++Fix crash that could occur during shutdown during page load.
++Fix crash that could occur when trying to retrieve binary data from clipboard to
+update clipboard ring.
++Fix crash that could happen when replace in selection action finds no matches.
++Fix crash that could occur when starting Editra again immediately after closing
+another running instance due to zombie IPC thread.
++Fix crash that could occur in vi emulation due to bad command mapping.
++Fix crashes that could occur when loading plugins that throw errors during
+creation.
++Fix crash when system fails to return control reference when print is requested.
++Ensure requested locale is available prior to trying to create it.
++Fix incorrect line getting deleted by line delete action with some encodings.
+
+
+#-----------------------------------------------------------------------------#
+
+For Alpha 0.6 Release Series Changelog see docs/CHANGELOG_7
+
+#-----------------------------------------------------------------------------#
+
+For Alpha 0.5 Release Series Changelog see docs/CHANGELOG_6
+
+#-----------------------------------------------------------------------------#
+
+For Alpha 0.4 Release Series Changelog see docs/CHANGELOG_5
+
+#-----------------------------------------------------------------------------#
+
+For Alpha 0.3 Release Series Changelog see docs/CHANGELOG_4
+
+#-----------------------------------------------------------------------------#
+
+For Alpha 0.2 Release Series Changelog see docs/CHANGELOG_3
+
+#-----------------------------------------------------------------------------#
+
+For Alpha 0.1 Release Series Changelog see docs/CHANGELOG_2
+
+#-----------------------------------------------------------------------------#
+
+For Pre-Alpha Changelog see docs/CHANGELOG_1 \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/COPYING b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/COPYING
new file mode 100644
index 0000000..e530475
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/COPYING
@@ -0,0 +1,54 @@
+ wxWindows Library Licence, Version 3.1
+ ======================================
+
+ Copyright (C) 1998-2005 Julian Smart, Robert Roebling et al
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this licence document, but changing it is not allowed.
+
+ WXWINDOWS LIBRARY LICENCE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public Licence as published by
+ the Free Software Foundation; either version 2 of the Licence, or (at
+ your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
+ General Public Licence for more details.
+
+ You should have received a copy of the GNU Library General Public Licence
+ along with this software, usually in a file named COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ EXCEPTION NOTICE
+
+ 1. As a special exception, the copyright holders of this library give
+ permission for additional uses of the text contained in this release of
+ the library as licenced under the wxWindows Library Licence, applying
+ either version 3.1 of the Licence, or (at your option) any later version of
+ the Licence as published by the copyright holders of version
+ 3.1 of the Licence document.
+
+ 2. The exception is that you may use, copy, link, modify and distribute
+ under your own terms, binary object code versions of works based
+ on the Library.
+
+ 3. If you copy code from files distributed under the terms of the GNU
+ General Public Licence or the GNU Library General Public Licence into a
+ copy of this library, as this licence permits, the exception does not
+ apply to the code that you add in this way. To avoid misleading anyone as
+ to the status of such modified files, you must delete this exception
+ notice from such code and/or adjust the licensing conditions notice
+ accordingly.
+
+ 4. If you write modifications of your own for this library, it is your
+ choice whether to permit this exception to apply to your modifications.
+ If you do not wish that, you must delete the exception notice from such
+ code and/or adjust the licensing conditions notice accordingly.
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Editra.pyw b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Editra.pyw
new file mode 100644
index 0000000..e70b17a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Editra.pyw
@@ -0,0 +1,79 @@
+#!/usr/bin/env python2
+###############################################################################
+# Name: Editra.pyw #
+# Purpose: Editra's main launch script #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+
+"""
+Main launch script for the Editor. It first tries to look for Editra on the
+local path and if it is not there it tries to import the Main method
+from where Editra would be installed if it was installed using distutils
+
+@summary: Editra's main launch script for Windows
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: Editra.pyw 63538 2010-02-23 03:39:03Z CJP $"
+__revision__ = "$Revision: 63538 $"
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import sys
+import os
+
+try:
+ import src as esrc
+ IS_LOCAL = True
+except ImportError:
+ try:
+ import Editra as esrc
+ IS_LOCAL = False
+ except ImportError, msg:
+ print "There was an error while tring to import Editra"
+ print ("Make sure that Editra is on your PYTHONPATH and that "
+ "you have wxPython installed.")
+ print "ERROR MSG: "
+ print str(msg)
+ os._exit(1)
+
+#--------------------------------------------------------------------------#
+# There are currently some necessary hacks for launching editra from this
+# script that will hopefully be removed in the not so distance future once
+# the plugin managers meta registry is redesigned.
+
+def main():
+ # The initial import above is necessary to get the path of where
+ # Editra is installed so that the src package can be put on the path.
+ # If the src module is not on the path the plugins are unable to import
+ # things from inside editras namespace properly. It also causes problems
+ # with recongnizing plugins in Extension registry of the Plugins metaclass.
+ SRC_DIR = os.path.dirname(esrc.__file__)
+ if not IS_LOCAL:
+ SRC_DIR = os.path.join(SRC_DIR, 'src')
+
+ # Cleanup any of Editras modules that are already present before
+ # importing Editra again so that the modules are imported with the
+ # correct signature (i.e ed_theme vs src.ed_theme). As the plugin
+ # manager currently registers the class objects metadata by using
+ # the classes module signature for identification.
+ if not IS_LOCAL:
+ torem = [ key for key in sys.modules.keys()
+ if key.startswith('Editra') ]
+ for key in torem:
+ del sys.modules[key]
+ else:
+ if 'src' in sys.modules:
+ del sys.modules['src']
+
+ sys.path.insert(0, SRC_DIR)
+ import Editra
+ Editra.Main()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/FAQ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/FAQ
new file mode 100644
index 0000000..fd3b5ac
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/FAQ
@@ -0,0 +1,6 @@
+Frequently Asked Questions:
+
+Most common questions are answered in the project documentation please see
+http://editra.org/?page=docs for a listing of how to's and other tips and tricks
+about how to use Editra.
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/INSTALL b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/INSTALL
new file mode 100644
index 0000000..669a7c0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/INSTALL
@@ -0,0 +1,63 @@
+Editra Installation Instructions for installing from source
+
+Base Dependencies:
+python 2.6 or higher (http://www.python.org)
+wxPython 2.8.6 or higher (http://www.wxpython.org) (Unicode build suggested)
+setuptools 0.6 or higher (http://peak.telecommunity.com/DevCenter/setuptools)
+
+#--------------------------------------------------------------------------#
+Option 1) Install Editra as a source package: [Linux/Macintosh/Unix/Windows]
+
+When using the source scripts Editra doesn't actually need to be installed it
+can be run by un-tarring the source package and executing the script called
+"Editra" in the the root of the un-tarred directory. Alternatively however, if
+you want the setup.py script will allow you to install it using distutils.
+
+To install Editra using distutils just do the usual python thing and type:
+
+python setup.py install
+
+at your shells command prompt.
+
+#--------------------------------------------------------------------------#
+Option 2) Installing from Pypi: [Linux/Macintosh/Unix/Windows]
+
+Editra is also available in the python package index and can be installed
+from source using easy_install (bundled with setuptools).
+
+easy_install editra
+
+#--------------------------------------------------------------------------#
+Option 3) Build a Windows exe: [Windows]
+
+To build an exe of Editra for Windows, py2exe (http://www.py2exe.org) must
+be installed. After installing py2exe just do the following.
+
+python setup.py py2exe --bundle 2
+
+This will build an exe and place it in .\dist\
+
+#--------------------------------------------------------------------------#
+Option 4) Build a MacOSX app: [Macintosh OSX]
+
+This requires having py2app (http://cheeseshop.python.org/pypi/py2app/)
+installed. If they are installed just issue the following command to
+build an applet.
+
+python setup.py py2app
+
+This will create a self contained applet in the ./dist/ directory
+
+#--------------------------------------------------------------------------#
+Option 5) Build as an egg: [Linux/Macintosh/Unix/Windows]
+
+To make an Python Egg from Editra, setuptools is required. If setuptools is
+installed the following command will build an egg that can be installed with
+easy install (ez_install.py).
+
+python setup.py bdist_egg
+
+The Egg will be placed in ./dist/ and can be installed by doing the following
+
+cd dist/
+ez_install Editra-x.x.xx-pyXX.egg
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/MANIFEST.in b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/MANIFEST.in
new file mode 100644
index 0000000..2f8b2c6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/MANIFEST.in
@@ -0,0 +1,25 @@
+include *.py *.pyw *.cfg
+include AUTHORS
+include CHANGELOG
+include COPYING
+include editra
+include FAQ
+include INSTALL
+include MANIFEST
+include NEWS
+include README
+include THANKS
+include TODO
+include docs/*.txt
+include plugins/*.egg
+include tests/controls/*.py
+include tests/syntax/*
+recursive-include tests/unittests *.py *.txt *.png
+recursive-include include *.h
+recursive-include ekeys *.ekeys
+recursive-include locale *.mo
+recursive-include pixmaps *.png *.ico *.icns [A-Z]
+recursive-include scripts *.sh *.po *.py
+recursive-include src *.py [A-Z]
+recursive-include styles *.ess
+recursive-include templates *
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Makefile b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Makefile
new file mode 100644
index 0000000..12ea6e7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Makefile
@@ -0,0 +1,85 @@
+# Editra Makefile
+#
+# Instructions:
+# To make source bundle: make sdist
+# To make eggs: make egg
+# To make plugins: make plugin
+#
+
+# Variables
+PYVERSION = 2.5
+EGGFILTER = *py2.4.egg *py2.6.egg
+
+# Paths
+PLUGINS = ./plugins
+FILEBROWSER = $(PLUGINS)/filebrowser
+PYSHELL = $(PLUGINS)/PyShell
+CODEBROWSER = $(PLUGINS)/codebrowser
+LAUNCH = $(PLUGINS)/Launch
+I18NDIR = ./scripts/i18n
+
+# Generated Paths
+OSXAPP = ./dist/Editra.app/
+OSXRESOURCES = $(OSXAPP)/Contents/Resources/
+
+# Commands
+PYTHON = python$(PYVERSION)
+MAKE_PLUGIN24 = python2.4 ./setup.py bdist_egg --dist-dir=../
+MAKE_PLUGIN25 = python2.5 ./setup.py bdist_egg --dist-dir=../
+MAKE_PLUGIN26 = python2.6 ./setup.py bdist_egg --dist-dir=../
+MAKE_EGG24 = python2.4 ./setup.py bdist_egg
+MAKE_EGG25 = python2.5 ./setup.py bdist_egg
+MAKE_EGG26 = python2.6 ./setup.py bdist_egg
+
+#---- Plugins ----#
+
+filebrowser:
+ cd $(FILEBROWSER) && $(MAKE_PLUGIN24)
+ cd $(FILEBROWSER) && $(MAKE_PLUGIN25)
+ cd $(FILEBROWSER) && $(MAKE_PLUGIN26)
+
+pyshell:
+ cd $(PYSHELL) && $(MAKE_PLUGIN24)
+ cd $(PYSHELL) && $(MAKE_PLUGIN25)
+ cd $(PYSHELL) && $(MAKE_PLUGIN26)
+
+codebrowser:
+ cd $(CODEBROWSER) && $(MAKE_PLUGIN24)
+ cd $(CODEBROWSER) && $(MAKE_PLUGIN25)
+ cd $(CODEBROWSER) && $(MAKE_PLUGIN26)
+
+launch:
+ cd $(LAUNCH) && $(MAKE_PLUGIN24)
+ cd $(LAUNCH) && $(MAKE_PLUGIN25)
+ cd $(LAUNCH) && $(MAKE_PLUGIN26)
+
+plugins: filebrowser codebrowser pyshell launch
+
+docs:
+ cd ./scripts/gendocs && ./gen_api_docs.sh
+
+i18n:
+ cd $(I18NDIR) && ./gen_lang.sh -all
+
+depfiles: plugins i18n
+
+sdist: depfiles
+ $(PYTHON) ./setup.py sdist
+
+osx_applet: depfiles osx_app_nodeps
+
+osx_app_nodeps:
+ $(PYTHON) ./setup.py py2app
+ cd $(OSXRESOURCES)/plugins && rm -f $(EGGFILTER)
+ cd $(OSXRESOURCES)/pixmaps && rm -f *.ico
+
+egg: depfiles
+ $(MAKE_EGG24)
+ $(MAKE_EGG25)
+ $(MAKE_EGG26)
+
+install: depfiles
+ python ./setup.py install
+
+clean:
+ rm -rf *.pyc build dist src/*.pyc src/*.pyo
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/NEWS b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/NEWS
new file mode 100644
index 0000000..19bf19e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/NEWS
@@ -0,0 +1,7 @@
+Editra Project News:
+
+This file contains general project news and announcements. News related to
+releases and current versions are contained in the CHANGELOG.
+
+@see CHANGELOG or docs CHANGELOG_* for latest release information
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/README b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/README
new file mode 100644
index 0000000..61647da
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/README
@@ -0,0 +1,40 @@
+Project Name: Editra
+Author: Cody Precord
+Email: cprecord@editra.org
+Licence: wxWindows (see COPYING)
+
+#----------------------------------------------------------------------------#
+
+Info:
+
+#----------------------------------------------------------------------------#
+
+Compatibility:
+It has been tested on the following systems, but it should run on any system
+that supports python and wxpython.
+
+Linux:
+Tested on Gentoo, Suse, and Ubuntu
+Receives testing when ever my vm doesn't eat my install
+
+Macintosh OS X:
+Primary development is on OS X so it receives the most direct testing.
+
+Windows XP / Windows 7
+Receives regression testing for before each release
+
+Dependencies:
+If you wish to run the source code you will need to have the following
+libraries installed.
+
+Required for all systems:
+Python 2.6 and higher ( http://python.org )
+wxPython 2.8.6 ( http://wxpython.org ) (Unicode version)
+setuptools 0.6 or higher (http://peak.telecommunity.com/DevCenter/setuptools)
+#----------------------------------------------------------------------------#
+
+INSTALLATION:
+
+see INSTALL
+
+#----------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/THANKS b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/THANKS
new file mode 100644
index 0000000..3729d17
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/THANKS
@@ -0,0 +1,12 @@
+Editra is made possible by the following "free" technologies and
+the communities that develop them.
+
+Python Programming Language (http://www.python.org)
+wxPython Class Library (http://www.wxpython.org)
+setuptools (http://peak.telecommunity.com/DevCenter/setuptools)
+py2app (http://undefined.org/python/#py2app)
+py2exe (http://py2exe.org)
+pygments (http://pygments.org)
+
+The primary icon theme 'Tango' is derived from the Tango set of icons
+http://tango.freedesktop.org
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/TODO b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/TODO
new file mode 100644
index 0000000..c7509ad
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/TODO
@@ -0,0 +1,17 @@
+This file serves as a scratch place for some ideas about things that are wanted
+in the editor or that would be nice to have. A more formal listing is available
+on the projects issue tracker page http://code.google.com/p/editra/issues/list
+
+This is a partial list of planned features that are yet to be implemented.
+
+Planned Features:
+
+Core:
+- Full command mode to remove need for mouse interaction (initial basic version to be available after 0.1.78)
+- Builtin help/documentation browser
+- Extensions to current syntax stylesheet language to allow for per language style definitions
+- Runtime loading/unloading of plugins (works for some plugins)
+
+Plugin:
+- Terminal, builtin system shell control (partially implemented osx/gtk)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/__init__.py
new file mode 100644
index 0000000..c5efd18
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/__init__.py
@@ -0,0 +1,13 @@
+###############################################################################
+# Name: __init__.py #
+# Purpose: Put the src package in the Editra packages namespace #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""Main package initializer"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: __init__.py 49807 2007-11-10 07:08:33Z CJP $"
+__revision__ = "$Revision: 49807 $"
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/docs/editra_style_sheets.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/docs/editra_style_sheets.txt
new file mode 100644
index 0000000..4d861ad
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/docs/editra_style_sheets.txt
@@ -0,0 +1,180 @@
+SPECIFICATION: Editra Style Sheet
+REVISION: 1.6
+
+PURPOSE: Define the format for writing custom style sheets that allow for the
+ customization of the color scheme used to highlight text in the editor
+ when Syntax Highlighting is enabled.
+
+VERSION INFO: In this initial incarnation the style sheets will only allow you
+ use the "Standard Tags" and "Standard Attributes" all other
+ definitions will be ignored by the parser. There are however
+ plans to make the style sheets extensible in the future to allow
+ for the setting of custom tags and subclassing styles to only
+ apply to a particular lexer. These features will likely be
+ introduced in the version 2 of this specification.
+
+FILE EXTENSION: ess
+
+SYNTAX: The syntax of an Editra Style Sheet is very similar to that of a
+ Cascading Style Sheet (CSS). It uses "tags" followed by the style
+ definition enclosed in {}'s. Attribute keywords are followed by a
+ colon and then the attribute values. A semicolon is used at the end of
+ each attribute definition as a delimiter between definitions. Comments
+ can be specified by placing text in between '/* */'.
+
+BEHAVIOR: The 'default_style' tag must be defined and must define all four of
+ the default attributes (fore, back, face, size). All other tags with
+ undefined values will inherit them from this style definition.
+
+STATEMENT FORMAT:
+
+ tag_name {
+ attribute1: value;
+ attribute2: value modifier;
+ }
+
+STYLE GUIDELINES:
+ Although the parser is rather flexible and will allow you to define
+ your entire set of style definitions on one line this is very poor for
+ readability, so the following specifications are suggested.
+
+ Tags should be un-indented and all in lower case. Following the tag
+ should be 1 space and an opening curly bracket '{'. The following
+ line should contain the first attribute definition. This definition
+ should start indented 1-4 spaces past the opening curly bracket and
+ be all in lower case. All following attribute definitions should be
+ on their own line and indented to the same level as first attribute
+ definition. The line immediately following the last attribute definition
+ contains the closing curly bracket '}' which should be unindented and
+ lined up with the beginning of the Tag definition.
+
+STANDARD TAGS:
+ - brace_good: This tag defines the style for highlighting matching braces
+ - brace_bad: This tag defines the style for highlighting unmatched braces
+ - calltip: Style to color calltip windows in
+ - ctrl_char: Style for control characters (Tabs, Spaces, ect...)
+ - line_num: Style of the line numbers in the outer left margin
+ - array_style: Style of arrays (currently used in perl documents)
+ - btick_style: Style of Back Ticks
+ - default_style: Style of all text not styled by other definitions
+ - caret_line: Sets caret line background highlight color
+ - char_style: Style of characters (i.e 'c')
+ - class_style: Style of class defs (i.e def MyClass)
+ - class2_style: Currently unused
+ - clear: Sets foreground to black, background to white
+ - comment_style: Style of code comment blocs
+ - decor_style: Style for decorators
+ - directive_style: Style of directives
+ - dockey_style: Style of documentation keywords
+ - error_style: Style of errors
+ - foldmargin_style: Style of code folding margin and markers
+ - funct_style: Style of Functions
+ - global_style: Style of global variables
+ - guide_style: indentation guide style
+ - here_style: Used to highlight HERE statements
+ - ideol_style: Id End of Line (used in Makefiles)
+ - keyword_style: Style of Primary Keywords
+ - keyword2_style: Style of Secondary/Type Keywords
+ - keyword3_style: Style of extra keywords
+ - keyword4_style: Style of extra/user defined keywords
+ - marker_style: Style for bookmarks/margin markers
+ - number_style: Style of numbers
+ - number2_style: Alternate style for numbers/verbatim defs
+ - operator_style: Style of Operators (i.e + = *)
+ - pre_style: Style of Preprocessor
+ - pre2_style: Alternate Preprocessor style
+ - regex_style: Style of Regular Expressions
+ - scalar_style: Style of Scalar Variables
+ - scalar2_style: Alternate style for Scalar Variables
+ - select_style: Style of text selection background
+ - string_style: Style of Strings (i.e "hello")
+ - stringeol_style: Style of unclosed strings (i.e "hello )
+ - unknown_style: Style of unknown statements
+ - userkw_style: Style for some builins and user defined keywords
+
+STANDARD ATTRIBUTES:
+ - back: Defines the style of the background for the tags text area. The
+ acceptable values are any 6 digit HEX color code (i.e #123456)
+ optionally followed by a modifier (see MODIFIERS).
+ - face: Defines the Font used by a fonts face name. The values accepted
+ by this attribute are either a Face name (i.e Monaco) or a
+ format expression (recommended) (i.e %(mono)s). The use of
+ format expressions is recommended because it will allow your
+ style sheet to work on all platforms, as it will let Editra's
+ Style Manager look up an appropriate/available system font.
+ See FONT KEYS for more information on available format
+ expressions.
+ - fore: Defines the foreground/face color/style of the tags text area.
+ The acceptable values are any 6 digit HEX color code (i.e #123456)
+ optionally followed by a modifier (see MODIFIERS).
+ - size: Defines the Point Size of the font in the tags text area. The
+ acceptable values are any system supported font size (i.e 12)
+ or a format expression (i.e %(size)d). See FONT KEYS for more
+ information on available format expressions.
+ - modifiers: Defines style modifiers 'bold underline italic eol'
+
+FONT KEYS:
+ The listed values below are used in format expressions to define what
+ font is used. To use these keys use the following expression in your
+ face definitions and substitute the 'xxx' with your chosen key.
+
+ Standard Expression: %(xxx)s
+
+ - primary: Users prefered primary font
+ - secondary: Users prefered secondary font
+
+ The next set of values are used in font size format expressions. To
+ use these values replace the 'xxx' in the following expression with
+ the chosen value.
+
+ Standard Expression: %(xxx)d
+
+ - size: The point size of the primary font
+ - size2: The point size of the secondary font
+ - size3: 2 point sizes smaller than "size"
+
+MODIFIERS:
+ These keywords are used to modify style attributes.
+
+ - bold: Makes the text in the tags text area bold
+ - italic: Makes the text in the tags text area italicized
+ - eol: Extends the given attributes style to the end of the line
+ - underline: Enables underlining for a text area
+
+ Modifiers can be either appended to the values defined in a standard
+ attribute or specifed in the _modifiers_ attribute.
+
+SPECIAL TAGS:
+ These tags are part of the standard tags but behave differently than
+ a typical tag. The differences in behavior are mostly transparent but
+ here is an explanation of each.
+
+ - calltip: Only Foreground and Background attributes are used
+ - caret_line: Only Background attribute is used
+ - clear: Used internally any definitions will be ignored
+ - foldmargin_style: Only Foreground and Background attributes are used
+ - marker_style: Only Foreground and Background attributes are used
+ - select_style: When defined only the Background attribute is used. If
+ this style is not defined then the default system colour
+ for selection highlight is used in its place.
+
+EXAMPLES:
+
+ /* Comment about this style */
+ default_style {
+ fore: #000000;
+ back: #FFFFFF; /* use a white background */
+ face: %(primary)s;
+ size: %(size)d;
+ }
+
+ keyword_style {
+ fore: #A52B2B bold;
+ face: Courier;
+ size: 14;
+ }
+
+ keyword2_style {
+ fore: #F0F660;
+ modifiers: italic underline;
+ }
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra
new file mode 100644
index 0000000..7bbf80e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra
@@ -0,0 +1,79 @@
+#!/usr/bin/env python2
+###############################################################################
+# Name: Editra #
+# Purpose: Editra's main launch script #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+
+"""
+Main launch script for the Editor. It first tries to look for Editra on the
+local path and if it is not there it tries to import the Main method
+from where Editra would be installed if it was installed using disutils
+
+@summary: Editra's main launch script
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: Exp $"
+__revision__ = "$Revision: $"
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import sys
+import os
+
+try:
+ import src as esrc
+ IS_LOCAL = True
+except ImportError:
+ try:
+ import Editra as esrc
+ IS_LOCAL = False
+ except ImportError, msg:
+ print "There was an error while tring to import Editra"
+ print ("Make sure that Editra is on your PYTHONPATH and that "
+ "you have wxPython installed.")
+ print "ERROR MSG: "
+ print str(msg)
+ os._exit(1)
+
+#--------------------------------------------------------------------------#
+# There are currently some necessary hacks for launching editra from this
+# script that will hopefully be removed in the not so distance future once
+# the plugin managers meta registry is redesigned.
+
+def main():
+ # The initial import above is necessary to get the path of where
+ # Editra is installed so that the src package can be put on the path.
+ # If the src module is not on the path the plugins are unable to import
+ # things from inside editras namespace properly. It also causes problems
+ # with recognizing plugins in Extension registry of the Plugins metaclass.
+ SRC_DIR = os.path.dirname(esrc.__file__)
+ if not IS_LOCAL:
+ SRC_DIR = os.path.join(SRC_DIR, 'src')
+
+ # Cleanup any of Editras modules that are already present before
+ # importing Editra again so that the modules are imported with the
+ # correct signature (i.e ed_theme vs src.ed_theme). As the plugin
+ # manager currently registers the class objects metadata by using
+ # the classes module signature for identification.
+ if not IS_LOCAL:
+ torem = [ key for key in sys.modules.keys()
+ if key.startswith('Editra') ]
+ for key in torem:
+ del sys.modules[key]
+ else:
+ if 'src' in sys.modules:
+ del sys.modules['src']
+
+ sys.path.insert(0, SRC_DIR)
+ import Editra
+ Editra.Main()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra-installer.nsi b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra-installer.nsi
new file mode 100644
index 0000000..1201779
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra-installer.nsi
@@ -0,0 +1,232 @@
+;------------------------------------------------------------------------------
+; Editra Windows Installer Build Script
+; Author: Cody Precord
+; Language: NSIS
+; Licence: wxWindows License
+;------------------------------------------------------------------------------
+
+
+;------------------------------ Start MUI Setup -------------------------------
+
+; Global Variables
+!define PRODUCT_NAME "Editra"
+!define PRODUCT_VERSION "0.7.20"
+!define PRODUCT_PUBLISHER "Cody Precord"
+!define PRODUCT_WEB_SITE "http://editra.org"
+!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\${PRODUCT_NAME}.exe"
+!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
+!define PRODUCT_UNINST_ROOT_KEY "HKLM"
+
+SetCompressor lzma
+
+; MUI 1.67 compatible ------
+!include "MUI.nsh"
+
+; MUI Settings
+!define MUI_ABORTWARNING
+!define MUI_ICON "pixmaps\editra.ico"
+!define MUI_UNICON "pixmaps\editra.ico"
+!define MUI_FILEICON "pixmaps\editra_doc.png"
+
+; Welcome page
+!insertmacro MUI_PAGE_WELCOME
+; License page (Read the Licence)
+!insertmacro MUI_PAGE_LICENSE "COPYING"
+; Components Page (Select what parts to install)
+!insertmacro MUI_PAGE_COMPONENTS
+; Directory page (Set Where to Install)
+!insertmacro MUI_PAGE_DIRECTORY
+; Instfiles page (Do the installation)
+!insertmacro MUI_PAGE_INSTFILES
+; Finish page (Post installation tasks)
+!define MUI_FINISHPAGE_RUN
+!define MUI_FINISHPAGE_RUN_TEXT "Run Editra"
+!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchEditra"
+!insertmacro MUI_PAGE_FINISH
+
+; Un-Installer pages
+!insertmacro MUI_UNPAGE_CONFIRM
+!insertmacro MUI_UNPAGE_COMPONENTS
+!insertmacro MUI_UNPAGE_INSTFILES
+!insertmacro MUI_UNPAGE_FINISH
+
+; Language files
+!insertmacro MUI_LANGUAGE "English"
+
+; Reserve files
+!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
+
+;------------------------------- End MUI Setup --------------------------------
+
+
+;------------------------------ Start Installer -------------------------------
+
+;---- Constants
+Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
+OutFile "editra.win32.${PRODUCT_VERSION}.exe"
+InstallDir "$PROGRAMFILES\${PRODUCT_NAME}"
+InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
+ShowInstDetails show
+ShowUnInstDetails show
+
+RequestExecutionLevel admin
+
+;---- !defines for use with SHChangeNotify
+!ifdef SHCNE_ASSOCCHANGED
+!undef SHCNE_ASSOCCHANGED
+!endif
+!define SHCNE_ASSOCCHANGED 0x08000000
+
+!ifdef SHCNF_FLUSH
+!undef SHCNF_FLUSH
+!endif
+!define SHCNF_FLUSH 0x1000
+
+; Prepare for installation
+Function .onInit
+ ; prevent running multiple instances of the installer
+ System::Call 'kernel32::CreateMutexA(i 0, i 0, t "editra_installer") i .r1 ?e'
+ Pop $R0
+ StrCmp $R0 0 +3
+ MessageBox MB_OK|MB_ICONEXCLAMATION "The installer is already running."
+ Abort
+
+ ; Check for existing installation warn before installing new one
+ ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString"
+ StrCmp $R0 "" done
+
+ MessageBox MB_YESNO|MB_ICONEXCLAMATION \
+ "An existing installation of Editra has been found. $\nDo you want to remove the previous version before installing $(^Name) ?" \
+ IDNO done
+
+ ; Run the uninstaller
+ ClearErrors
+ ExecWait '$R0 _?=$INSTDIR' ; Do not copy the uninstaller to a temp file
+
+ done:
+FunctionEnd
+
+; Extract the files from the installer to the install location
+Section "Editra Core" SEC01
+ SectionIn RO 1 2
+
+ ; Check that Editra is not running before starting to copy the files
+ FindProcDLL::FindProc "${PRODUCT_NAME}.exe"
+ StrCmp $R0 0 continueInstall
+ MessageBox MB_ICONSTOP|MB_OK "${PRODUCT_NAME} is still running please close all running instances and try to install again"
+ Abort
+ continueInstall:
+
+ ; Extract the files and make shortcuts
+ SetOverwrite try
+ SetOutPath "$INSTDIR\"
+ File /r ".\*.*"
+
+ ; Add the shortcuts to the start menu and desktop
+ SetShellVarContext all
+ CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
+ CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\${PRODUCT_NAME}.exe" "" "$INSTDIR\${MUI_ICON}"
+ CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\${PRODUCT_NAME}.exe" "" "$INSTDIR\${MUI_ICON}"
+SectionEnd
+
+; Enabled if Add openwith entry is checked
+Section "Context Menus" SEC02
+ SectionIn 1
+ WriteRegStr HKCR "*\shell\OpenWithEditra" "" "Edit with ${PRODUCT_NAME}"
+ WriteRegStr HKCR "*\shell\OpenWithEditra\command" "" '$INSTDIR\${PRODUCT_NAME}.exe "%1"'
+; WriteRegStr HKCR "*\shell\OpenWithEditra\DefaultIcon" "" "${MUI_FILEICON}"
+
+ ; Notify of the shell extension changes
+ System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_FLUSH}, i 0, i 0)'
+SectionEnd
+
+; Add QuickLaunch Icon (That small icon bar next to the start button)
+Section "Add Quick Launch Icon" SEC03
+ SectionIn 1
+ CreateShortCut "$QUICKLAUNCH\${PRODUCT_NAME}.lnk" "$INSTDIR\${PRODUCT_NAME}.exe"
+SectionEnd
+
+; Make/Install Shortcut links
+Section -AdditionalIcons
+ WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
+ SetShellVarContext all
+ CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
+ CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\uninst.exe" "" "$INSTDIR\${MUI_UNICON}"
+SectionEnd
+
+; Post installation setup
+Section -Post
+ ;---- Write registry keys for uninstaller
+ WriteUninstaller "$INSTDIR\uninst.exe"
+ WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\${PRODUCT_NAME}.exe"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\${MUI_UNICON}"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+SectionEnd
+
+; Called if Run Editra is checked on the last page of installer
+Function LaunchEditra
+ Exec '"$INSTDIR\${PRODUCT_NAME}.exe" "$INSTDIR\CHANGELOG" '
+FunctionEnd
+
+; Description Texts for Component page
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+ !insertmacro MUI_DESCRIPTION_TEXT ${SEC01} "Required core program files"
+ !insertmacro MUI_DESCRIPTION_TEXT ${SEC02} "Add context menu item 'Edit with ${PRODUCT_NAME}'"
+ !insertmacro MUI_DESCRIPTION_TEXT ${SEC03} "Add shortcut to Quick Launch Bar"
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+;------------------------------- End Installer --------------------------------
+
+;----------------------------- Start Uninstaller ------------------------------
+
+;Function un.onInit
+;FunctionEnd
+
+; Cleans up registry, links, and main program files
+Section "un.Program Data" UNSEC01
+ SectionIn RO 1
+
+ ; Ensure shortcuts are removed from user directory as well
+ RmDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
+ Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
+ Delete "$QUICKLAUNCH\${PRODUCT_NAME}.lnk"
+
+ ; Remove all shortcuts from All Users directory
+ SetShellVarContext all
+ RmDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
+ Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
+ Delete "$QUICKLAUNCH\${PRODUCT_NAME}.lnk"
+
+ ; Cleanup Registry
+ DeleteRegKey HKCR "*\shell\OpenWithEditra"
+ DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+ DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
+
+ ; Remove all Files
+ RmDir /r "$INSTDIR\"
+
+ SetAutoClose false
+SectionEnd
+
+; Optionally cleans up user data/plugins
+Section /o "un.User settings and plugins" UNSEC02
+ SectionIn 1
+ SetShellVarContext current ; Current user only
+ RmDir /r "$APPDATA\${PRODUCT_NAME}" ; Remove app generated config data/plugins
+ RmDir /r "$LOCALAPPDATA\${PRODUCT_NAME}" ; Remove app generated config data/plugins
+SectionEnd
+
+;Function un.onUninstSuccess
+;FunctionEnd
+
+; Description Texts for Component page
+!insertmacro MUI_UNFUNCTION_DESCRIPTION_BEGIN
+ !insertmacro MUI_DESCRIPTION_TEXT ${UNSEC01} "Core program files"
+ !insertmacro MUI_DESCRIPTION_TEXT ${UNSEC02} "User settings and plugins"
+!insertmacro MUI_UNFUNCTION_DESCRIPTION_END
+
+;------------------------------ End Uninstaller -------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra_pylintrc b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra_pylintrc
new file mode 100644
index 0000000..8da2463
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra_pylintrc
@@ -0,0 +1,26 @@
+# Pylint Configuration File for Editra
+# Allow for CamelCase nameing convention used for functions and other
+# conventions used in Editra.
+
+# To use this file either:
+# 1) Copy it to $HOME/.pylintrc and run pylint normally
+#
+# OR
+#
+# 2) When running pylint use the following command
+# pylint --rcfile=editra_pylintrc
+#
+
+[BASIC]
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z_][a-zA-Z0-9_]+))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-zA-Z_][a-zA-Z0-9]*$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-zA-Z_][a-zA-Z0-9]*|(__.*__)$
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/launcher.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/launcher.py
new file mode 100644
index 0000000..dffb818
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/launcher.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python2
+
+# This module provides an importable module that can do the same
+# things as the Editra script, namely, set up the sys.path and
+# sys.modules for Editra and then start Editra running. This is done
+# by using execfile() to execute the code in the Editra script as if
+# it was in this module, and then the importer of this module can call
+# the main() function defined there.
+
+import os
+launcher = os.path.join(os.path.dirname(__file__), 'Editra')
+execfile(launcher)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ca_ES@valencia/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ca_ES@valencia/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..c62fe72
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ca_ES@valencia/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/cs_CZ/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/cs_CZ/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..f506f91
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/cs_CZ/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/da_DK/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/da_DK/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..3e9a4d1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/da_DK/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/de_DE/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/de_DE/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..e6568f1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/de_DE/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/en_US/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/en_US/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..ca8d266
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/en_US/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/es_ES/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/es_ES/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..ad56138
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/es_ES/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/fr_FR/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/fr_FR/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..3f9c709
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/fr_FR/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/gl_ES/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/gl_ES/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..37720ac
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/gl_ES/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hr_HR/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hr_HR/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..77d9cab
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hr_HR/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hu_HU/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hu_HU/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..0bdf474
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hu_HU/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/it_IT/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/it_IT/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..ea92d3a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/it_IT/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ja_JP/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ja_JP/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..71c50de
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ja_JP/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/lv_LV/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/lv_LV/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..0e5c298
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/lv_LV/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nl_NL/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nl_NL/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..1ef3e60
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nl_NL/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nn_NO/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nn_NO/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..8b5468c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nn_NO/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pl_PL/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pl_PL/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..c2babb2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pl_PL/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pt_BR/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pt_BR/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..f046296
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pt_BR/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ro_RO/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ro_RO/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..84b6e0e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ro_RO/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ru_RU/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ru_RU/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..11ef554
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ru_RU/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sk_SK/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sk_SK/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..0f3ca66
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sk_SK/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sl_SI/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sl_SI/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..f4ee2ad
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sl_SI/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sr_RS/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sr_RS/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..e5ab0e5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sr_RS/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sv_SE/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sv_SE/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..3c562b8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sv_SE/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/tr_TR/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/tr_TR/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..02b4c5a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/tr_TR/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/uk_UA/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/uk_UA/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..414df4b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/uk_UA/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_CN/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_CN/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..fee93b9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_CN/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_TW/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_TW/LC_MESSAGES/Editra.mo
new file mode 100644
index 0000000..5f29fa2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_TW/LC_MESSAGES/Editra.mo
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/Editra.icns b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/Editra.icns
new file mode 100644
index 0000000..177778a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/Editra.icns
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.ico b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.ico
new file mode 100644
index 0000000..ce7555e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.ico
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.png
new file mode 100644
index 0000000..47e4894
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra256.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra256.png
new file mode 100644
index 0000000..67b2cd5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra256.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra64.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra64.png
new file mode 100644
index 0000000..1a5d33c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra64.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.icns b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.icns
new file mode 100644
index 0000000..a1f76a9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.icns
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.ico b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.ico
new file mode 100644
index 0000000..cf44d48
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.ico
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.png
new file mode 100644
index 0000000..1809a83
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/splashwarn.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/splashwarn.png
new file mode 100644
index 0000000..c11633b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/splashwarn.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Default/README b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Default/README
new file mode 100644
index 0000000..2b1ce62
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Default/README
@@ -0,0 +1,2 @@
+The Default theme is provided by the host operating system this directory is
+just here to provide uniformity in organizing the themes.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/AUTHORS b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/AUTHORS
new file mode 100644
index 0000000..c54ec5b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/AUTHORS
@@ -0,0 +1,9 @@
+Ulisse Perusin <uli.peru@gmail.com>
+Steven Garrity <sgarrity@silverorange.com>
+Lapo Calamandrei <calamandrei@gmail.com>
+Ryan Collier <rcollier@novell.com>
+Rodney Dawes <dobey@novell.com>
+Andreas Nilsson <nisses.mail@home.se>
+Tuomas Kuosmanen <tigert@tigert.com>
+Garrett LeSage <garrett@novell.com>
+Jakub Steiner <jimmac@novell.com>
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/COPYING b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/COPYING
new file mode 100644
index 0000000..e709d0c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/COPYING
@@ -0,0 +1,67 @@
+Creative Commons Attribution-ShareAlike 2.5 License Agreement
+
+CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE.
+
+License
+
+THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+
+BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
+
+1. Definitions
+
+ 1. "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License.
+ 2. "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered a Derivative Work for the purpose of this License.
+ 3. "Licensor" means the individual or entity that offers the Work under the terms of this License.
+ 4. "Original Author" means the individual or entity who created the Work.
+ 5. "Work" means the copyrightable work of authorship offered under the terms of this License.
+ 6. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
+ 7. "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike.
+
+2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws.
+
+3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
+
+ 1. to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works;
+ 2. to create and reproduce Derivative Works;
+ 3. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works;
+ 4. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission Derivative Works.
+ 5.
+
+ For the avoidance of doubt, where the work is a musical composition:
+ 1. Performance Royalties Under Blanket Licenses. Licensor waives the exclusive right to collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public digital performance (e.g. webcast) of the Work.
+ 2. Mechanical Rights and Statutory Royalties. Licensor waives the exclusive right to collect, whether individually or via a music rights society or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover version") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions).
+ 6. Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor waives the exclusive right to collect, whether individually or via a performance-rights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions).
+
+The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved.
+
+4. Restrictions.The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
+
+ 1. You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any credit as required by clause 4(c), as requested. If You create a Derivative Work, upon notice from any Licensor You must, to the extent practicable, remove from the Derivative Work any credit as required by clause 4(c), as requested.
+ 2. You may distribute, publicly display, publicly perform, or publicly digitally perform a Derivative Work only under the terms of this License, a later version of this License with the same License Elements as this License, or a Creative Commons iCommons license that contains the same License Elements as this License (e.g. Attribution-ShareAlike 2.5 Japan). You must include a copy of, or the Uniform Resource Identifier for, this License or other license specified in the previous sentence with every copy or phonorecord of each Derivative Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Derivative Works that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder, and You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Derivative Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Derivative Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Derivative Work itself to be made subject to the terms of this License.
+ 3. If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Derivative Works or Collective Works, You must keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or Licensor designate another party or parties (e.g. a sponsor institute, publishing entity, journal) for attribution in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and in the case of a Derivative Work, a credit identifying the use of the Work in the Derivative Work (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Derivative Work or Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit.
+
+5. Representations, Warranties and Disclaimer
+
+UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+
+6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. Termination
+
+ 1. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Derivative Works or Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
+ 2. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
+
+8. Miscellaneous
+
+ 1. Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
+ 2. Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
+ 3. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
+ 4. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
+ 5. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
+
+Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor.
+
+Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, neither party will use the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time.
+
+Creative Commons may be contacted at http://creativecommons.org/.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/about.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/about.png
new file mode 100644
index 0000000..f1f7e17
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/about.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/add.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/add.png
new file mode 100644
index 0000000..68cf2db
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/add.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/advanced.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/advanced.png
new file mode 100644
index 0000000..b4bce31
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/advanced.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/attribute.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/attribute.png
new file mode 100644
index 0000000..1c570d2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/attribute.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/backward.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/backward.png
new file mode 100644
index 0000000..a1604e7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/backward.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bin_file.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bin_file.png
new file mode 100644
index 0000000..eafb0e1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bin_file.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_add.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_add.png
new file mode 100644
index 0000000..ac8981c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_add.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_next.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_next.png
new file mode 100644
index 0000000..5cdc0b4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_next.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_pre.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_pre.png
new file mode 100644
index 0000000..b8a2414
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_pre.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cdrom.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cdrom.png
new file mode 100644
index 0000000..8881f4f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cdrom.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/class.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/class.png
new file mode 100644
index 0000000..34d7f0e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/class.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/computer.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/computer.png
new file mode 100644
index 0000000..be87e5a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/computer.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/copy.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/copy.png
new file mode 100644
index 0000000..94dd2f7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/copy.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cut.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cut.png
new file mode 100644
index 0000000..268aeff
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cut.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete.png
new file mode 100644
index 0000000..7bf849a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete_all.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete_all.png
new file mode 100644
index 0000000..57b9a8b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete_all.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/doc_props.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/doc_props.png
new file mode 100644
index 0000000..c20a00e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/doc_props.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/docs.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/docs.png
new file mode 100644
index 0000000..01dc4b6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/docs.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/down.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/down.png
new file mode 100644
index 0000000..e9ba46b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/down.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/element.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/element.png
new file mode 100644
index 0000000..5ae6644
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/element.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/file.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/file.png
new file mode 100644
index 0000000..7999cd8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/file.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/find.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/find.png
new file mode 100644
index 0000000..54c6257
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/find.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/findr.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/findr.png
new file mode 100644
index 0000000..f5ab368
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/findr.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/floppy.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/floppy.png
new file mode 100644
index 0000000..9f26ed9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/floppy.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/folder.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/folder.png
new file mode 100644
index 0000000..a185148
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/folder.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/font.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/font.png
new file mode 100644
index 0000000..9008b0f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/font.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/forward.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/forward.png
new file mode 100644
index 0000000..58da8ed
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/forward.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/function.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/function.png
new file mode 100644
index 0000000..d04c1a0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/function.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/harddisk.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/harddisk.png
new file mode 100644
index 0000000..968a61d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/harddisk.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/html_gen.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/html_gen.png
new file mode 100644
index 0000000..c5173fe
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/html_gen.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/indent.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/indent.png
new file mode 100644
index 0000000..5162a2e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/indent.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/log.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/log.png
new file mode 100644
index 0000000..9ad202b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/log.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/mail.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/mail.png
new file mode 100644
index 0000000..9987021
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/mail.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/method.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/method.png
new file mode 100644
index 0000000..d04c1a0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/method.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/new.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/new.png
new file mode 100644
index 0000000..55ffb50
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/new.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newfolder.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newfolder.png
new file mode 100644
index 0000000..e2f46a4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newfolder.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newwin.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newwin.png
new file mode 100644
index 0000000..5b9171b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newwin.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/open.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/open.png
new file mode 100644
index 0000000..c66fc78
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/open.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/outdent.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/outdent.png
new file mode 100644
index 0000000..103011e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/outdent.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/package.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/package.png
new file mode 100644
index 0000000..14d2c07
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/package.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/paste.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/paste.png
new file mode 100644
index 0000000..87183f1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/paste.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/plugin.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/plugin.png
new file mode 100644
index 0000000..0f66d8d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/plugin.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pref.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pref.png
new file mode 100644
index 0000000..66e456e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pref.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/print.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/print.png
new file mode 100644
index 0000000..5482803
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/print.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/printpre.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/printpre.png
new file mode 100644
index 0000000..9ace126
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/printpre.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/property.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/property.png
new file mode 100644
index 0000000..e10cea8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/property.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pyshell.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pyshell.png
new file mode 100644
index 0000000..178852e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pyshell.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/quit.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/quit.png
new file mode 100644
index 0000000..88dc4e6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/quit.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/readonly.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/readonly.png
new file mode 100644
index 0000000..0055c1e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/readonly.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/redo.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/redo.png
new file mode 100644
index 0000000..ade0639
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/redo.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/refresh.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/refresh.png
new file mode 100644
index 0000000..16c1259
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/refresh.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/remove.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/remove.png
new file mode 100644
index 0000000..84234d4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/remove.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/rtf_gen.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/rtf_gen.png
new file mode 100644
index 0000000..8d12869
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/rtf_gen.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/save.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/save.png
new file mode 100644
index 0000000..0909f37
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/save.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/saveas.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/saveas.png
new file mode 100644
index 0000000..49d8c19
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/saveas.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/selectall.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/selectall.png
new file mode 100644
index 0000000..1aebeba
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/selectall.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/stop.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/stop.png
new file mode 100644
index 0000000..a993581
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/stop.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/style_edit.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/style_edit.png
new file mode 100644
index 0000000..edc9815
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/style_edit.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/tex_gen.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/tex_gen.png
new file mode 100644
index 0000000..90ae6a3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/tex_gen.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/theme.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/theme.png
new file mode 100644
index 0000000..8df60d8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/theme.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/undo.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/undo.png
new file mode 100644
index 0000000..835da89
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/undo.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/up.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/up.png
new file mode 100644
index 0000000..50afa18
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/up.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/usb.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/usb.png
new file mode 100644
index 0000000..70ba6e3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/usb.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/variable.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/variable.png
new file mode 100644
index 0000000..7d35962
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/variable.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/web.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/web.png
new file mode 100644
index 0000000..e25daf1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/web.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/boo.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/boo.png
new file mode 100644
index 0000000..1256cdf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/boo.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/css.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/css.png
new file mode 100644
index 0000000..8df50ac
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/css.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/html.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/html.png
new file mode 100644
index 0000000..8df50ac
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/html.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/java.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/java.png
new file mode 100644
index 0000000..4dc6e8b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/java.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/php.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/php.png
new file mode 100644
index 0000000..3367c85
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/php.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/python.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/python.png
new file mode 100644
index 0000000..9ee9e1b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/python.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/ruby.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/ruby.png
new file mode 100644
index 0000000..4ffeb64
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/ruby.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/shell.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/shell.png
new file mode 100644
index 0000000..8b45d61
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/shell.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/text.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/text.png
new file mode 100644
index 0000000..7999cd8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/text.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/other/doc_props.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/other/doc_props.png
new file mode 100644
index 0000000..f04c55c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/other/doc_props.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/advanced.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/advanced.png
new file mode 100644
index 0000000..5e98ae2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/advanced.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/backward.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/backward.png
new file mode 100644
index 0000000..71bc112
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/backward.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/copy.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/copy.png
new file mode 100644
index 0000000..618fa52
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/copy.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/cut.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/cut.png
new file mode 100644
index 0000000..0496a6b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/cut.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/doc_props.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/doc_props.png
new file mode 100644
index 0000000..b71d771
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/doc_props.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/find.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/find.png
new file mode 100644
index 0000000..424708f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/find.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/findr.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/findr.png
new file mode 100644
index 0000000..38bb117
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/findr.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/forward.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/forward.png
new file mode 100644
index 0000000..bccdbbd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/forward.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/new.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/new.png
new file mode 100644
index 0000000..2ab0d6f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/new.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/open.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/open.png
new file mode 100644
index 0000000..db1cae6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/open.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/package.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/package.png
new file mode 100644
index 0000000..6c618c6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/package.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/paste.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/paste.png
new file mode 100644
index 0000000..a8b1d49
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/paste.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/pref.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/pref.png
new file mode 100644
index 0000000..4272f55
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/pref.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/print.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/print.png
new file mode 100644
index 0000000..bd24def
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/print.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/redo.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/redo.png
new file mode 100644
index 0000000..5668316
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/redo.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/save.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/save.png
new file mode 100644
index 0000000..70b950e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/save.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/theme.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/theme.png
new file mode 100644
index 0000000..aaa8229
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/theme.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/undo.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/undo.png
new file mode 100644
index 0000000..34dd7e6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/undo.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/web.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/web.png
new file mode 100644
index 0000000..ec8246b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/web.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.6.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.6.egg
new file mode 100644
index 0000000..c13ca10
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.6.egg
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.7.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.7.egg
new file mode 100644
index 0000000..47b5d90
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.7.egg
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.6.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.6.egg
new file mode 100644
index 0000000..39b7606
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.6.egg
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.7.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.7.egg
new file mode 100644
index 0000000..2228cb5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.7.egg
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.6.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.6.egg
new file mode 100644
index 0000000..5604b7d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.6.egg
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.7.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.7.egg
new file mode 100644
index 0000000..ff2a455
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.7.egg
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.6.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.6.egg
new file mode 100644
index 0000000..7b7f8c1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.6.egg
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.7.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.7.egg
new file mode 100644
index 0000000..90c8cfe
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.7.egg
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.cfg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.cfg
new file mode 100644
index 0000000..ee24731
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.cfg
@@ -0,0 +1,5 @@
+[easy_install]
+
+find_links = http://editra.org/uploads/src/
+ http://editra.org/uploads/egg/
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.py
new file mode 100644
index 0000000..dd49ac9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.py
@@ -0,0 +1,640 @@
+#!/usr/bin/env python2
+###############################################################################
+# Name: setup.py #
+# Purpose: Setup/build script for Editra #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008-2013 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+ Editra Setup Script
+
+ USAGE:
+
+ 1) Windows:
+ - python setup.py py2exe
+
+ 2) MacOSX:
+ - python setup.py py2app
+
+ 3) Boil an Egg
+ - python setup.py bdist_egg
+
+ 4) Install as a python package
+ - python setup.py install
+ - '--no-clean' can be specified to skip old file cleanup
+
+ @summary: Used for building the editra distribution files and installations
+
+"""
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: setup.py 73347 2013-01-05 19:58:31Z CJP $"
+__revision__ = "$Revision: 73347 $"
+
+#---- Imports ----#
+import os
+import sys
+import glob
+import shutil
+import zipfile
+import time
+import src.info as info
+import src.syntax.synextreg as synextreg # So we can get file extensions
+
+# Version Check(s)
+if sys.version_info < (2, 5):
+ sys.stderr.write("[ERROR] Not a supported Python version. Need 2.5+\n")
+ sys.exit(1)
+
+try:
+ import wx
+except ImportError:
+ if 'bdist_egg' not in sys.argv:
+ sys.stderr.write("[ERROR] wxPython2.8 is required.\n")
+ sys.exit(1)
+else:
+ if wx.VERSION < (2, 8, 8):
+ sys.stderr.write("[ERROR] wxPython 2.8.8+ is required.\n")
+ sys.exit(1)
+
+#---- System Platform ----#
+__platform__ = os.sys.platform
+
+#---- Global Settings ----#
+APP = ['src/Editra.py']
+AUTHOR = "Cody Precord"
+AUTHOR_EMAIL = "staff@editra.org"
+YEAR = 2013
+
+CLASSIFIERS = [
+ 'Development Status :: 3 - Alpha',
+ 'Environment :: MacOS X',
+ 'Environment :: Win32 (MS Windows)',
+ 'Environment :: X11 Applications :: GTK',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Information Technology',
+ 'Intended Audience :: End Users/Desktop',
+ 'License :: OSI Approved',
+ 'Natural Language :: English',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Chinese (Traditional)',
+ 'Natural Language :: Croatian',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Danish',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: French',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: German',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Latvian',
+ 'Natural Language :: Japanese',
+ 'Natural Language :: Norwegian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Serbian',
+ 'Natural Language :: Slovak',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Swedish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Operating System :: Microsoft :: Windows',
+ 'Operating System :: POSIX',
+ 'Programming Language :: Python',
+ 'Topic :: Software Development',
+ 'Topic :: Text Editors'
+ ]
+
+def GenerateBinPackageFiles():
+ """Generate the list of files needed for py2exe/py2app package files"""
+ data = [("include/python2.5",
+ glob.glob("include/python2.5/%s/*" % __platform__)),
+ ("pixmaps/theme/Default", ["pixmaps/theme/Default/README"]),
+ ("pixmaps/theme/Tango",["pixmaps/theme/Tango/AUTHORS",
+ "pixmaps/theme/Tango/COPYING"]),
+ ("pixmaps/theme/Tango/toolbar",
+ glob.glob("pixmaps/theme/Tango/toolbar/*.png")),
+ ("pixmaps/theme/Tango/menu",
+ glob.glob("pixmaps/theme/Tango/menu/*.png")),
+ ("pixmaps/theme/Tango/mime",
+ glob.glob("pixmaps/theme/Tango/mime/*.png")),
+ ("pixmaps/theme/Tango/other",
+ glob.glob("pixmaps/theme/Tango/other/*.png")),
+ ("styles", glob.glob("styles/*.ess")),
+ ("ekeys", glob.glob("ekeys/*.ekeys")),
+ ("tests/syntax", glob.glob("tests/syntax/*")),
+ ("docs", glob.glob("docs/*.txt")), "AUTHORS", "FAQ", "INSTALL",
+ "README","CHANGELOG","COPYING", "NEWS", "THANKS", "TODO",
+ "setup.cfg"
+ ]
+
+ # Get the locale files
+ for loc_dir in os.listdir("locale"):
+ tmp = "locale/" + loc_dir + "/LC_MESSAGES"
+ if os.path.isdir(tmp):
+ tmp2 = tmp + "/Editra.mo"
+ if os.path.exists(tmp2):
+ data.append((tmp, [tmp2]))
+
+ # Only bundle the plugins for the running version of python being used for
+ # the build.
+ data.append(("plugins",
+ glob.glob("plugins/*py%d.%d.egg" % sys.version_info[:2])))
+
+ # Get platform specific icons
+ pixlist = ["pixmaps/editra.png", "pixmaps/editra_doc.png"]
+
+ if "darwin" in sys.platform:
+ data.append("pixmaps/editra_doc.icns")
+ pixlist.extend(["pixmaps/editra.icns", "pixmaps/editra_doc.icns"])
+ elif sys.platform.startswith("win"):
+ data.extend(glob.glob("include/windows/*.*"))
+ pixlist.append("pixmaps/editra.ico")
+
+ data.append(("pixmaps", pixlist))
+
+ return data
+
+def GenerateSrcPackageFiles():
+ """Generate the list of files to include in a source package dist/install"""
+ data = [ "src/*.py", "src/syntax/*.py", "src/autocomp/*.py",
+ "src/eclib/*.py", "docs/*.txt", "pixmaps/*.png", "pixmaps/*.ico",
+ "src/ebmlib/*.py",
+ "ekeys/*.ekeys",
+ "Editra",
+ "src/extern/*.py",
+ "src/extern/aui/*.py",
+ "src/extern/dexml/*.py",
+ "src/extern/pygments/*.py",
+ "src/extern/pygments/formatters/*.py",
+ "src/extern/pygments/filters/*.py",
+ "src/extern/pygments/lexers/*.py",
+ "src/extern/pygments/styles/*.py",
+ "pixmaps/*.icns",
+ "pixmaps/theme/Default/README",
+ "pixmaps/theme/Tango/AUTHOR",
+ "pixmaps/theme/Tango/COPYING",
+ "pixmaps/theme/Tango/toolbar/*.png",
+ "pixmaps/theme/Tango/menu/*.png",
+ "pixmaps/theme/Tango/mime/*.png",
+ "pixmaps/theme/Default/README",
+ "pixmaps/theme/Tango/other/*.png",
+ "styles/*.ess", "tests/syntax/*",
+ "AUTHORS", "CHANGELOG","COPYING", "FAQ", "INSTALL", "NEWS",
+ "README", "THANKS", "TODO", "setup.cfg" ]
+
+ # Get the local files
+ for loc_dir in os.listdir("locale"):
+ tmp = "locale/" + loc_dir
+ if os.path.isdir(tmp):
+ tmp = tmp + "/LC_MESSAGES/Editra.mo"
+ if os.path.exists(tmp):
+ data.append(tmp)
+
+ # NOTE: plugins selected to package in build step
+
+ return data
+
+
+DESCRIPTION = "Developer's Text Editor"
+
+LONG_DESCRIPT = \
+r"""
+========
+Overview
+========
+Editra is a multi-platform text editor with an implementation that focuses on
+creating an easy to use interface and features that aid in code development.
+Currently it supports syntax highlighting and variety of other useful features
+for over 70 programing languages. For a more complete list of features and
+screenshots visit the projects homepage at `Editra.org
+<http://www.editra.org/>`_.
+
+============
+Dependencies
+============
+ * Python 2.6+
+ * wxPython 2.8.3+ (Unicode build suggested)
+ * setuptools 0.6+
+
+"""
+
+ICON = { 'Win' : "pixmaps/editra.ico",
+ 'WinDoc' : "pixmaps/editra_doc.ico",
+ 'Mac' : "pixmaps/Editra.icns"
+}
+
+# Explicitly include some libraries that are either loaded dynamically
+# or otherwise not able to be found by py2app/exe
+INCLUDES = ['syntax.*', 'ed_bookmark', 'ed_log', 'shutil', 'subprocess', 'zipfile',
+ 'pygments.*', 'pygments.lexers.*', 'pygments.formatters.*',
+ 'pygments.filters.*', 'pygments.styles.*', 'ftplib', 'xmlrpclib',
+ 'hmac', 'SimpleXMLRPCServer', 'SocketServer', 'commands',
+ 'BaseHTTPServer', 'wx.gizmos', 'wx.lib.intctrl',
+ 'extern.flatnotebook'] # temporary till all references can be removed
+if sys.platform.startswith('win'):
+ INCLUDES.extend(['ctypes', 'ctypes.wintypes'])
+else:
+ INCLUDES.extend(['pty', 'tty'])
+
+LICENSE = "wxWindows"
+
+NAME = "Editra"
+
+URL = "http://editra.org"
+
+VERSION = info.VERSION
+
+MANIFEST_TEMPLATE = """
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <assemblyIdentity
+ version="5.0.0.0"
+ processorArchitecture="x86"
+ name="%(prog)s"
+ type="win32"
+ />
+ <description>%(prog)s</description>
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel
+ level="asInvoker"
+ uiAccess="false">
+ </requestedExecutionLevel>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.VC90.CRT"
+ version="9.0.21022.8"
+ processorArchitecture="x86"
+ publicKeyToken="1fc8b3b9a1e18e3b">
+ </assemblyIdentity>
+ </dependentAssembly>
+ </dependency>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0"
+ processorArchitecture="X86"
+ publicKeyToken="6595b64144ccf1df"
+ language="*"
+ />
+ </dependentAssembly>
+ </dependency>
+</assembly>
+"""
+
+RT_MANIFEST = 24
+#---- End Global Settings ----#
+
+
+#---- Packaging Functions ----#
+
+def BuildPy2Exe():
+ """Generate the Py2exe files"""
+ from distutils.core import setup
+ try:
+ import py2exe
+ except ImportError:
+ print "\n!! You dont have py2exe installed. !!\n"
+ exit()
+
+ # put package on path for py2exe
+ sys.path.append(os.path.abspath('src/'))
+ sys.path.append(os.path.abspath('src/extern'))
+
+ DATA_FILES = GenerateBinPackageFiles()
+ try:
+ import enchant
+ except ImportError:
+ pass
+ else:
+ from enchant import utils as enutil
+ DATA_FILES += enutil.win32_data_files()
+
+ setup(
+ name = NAME,
+ version = VERSION,
+ options = {"py2exe" : {"compressed" : 1,
+ "optimize" : 1,
+ "bundle_files" : 2,
+ "includes" : INCLUDES,
+ "excludes" : ["Tkinter", "Tkconstants", "tcl"],
+ "dll_excludes": [ "MSVCP90.dll",
+ "tk85.dll",
+ "tcl85.dll" ] }},
+ windows = [{"script": "src/Editra.py",
+ "icon_resources": [(1, ICON['Win'])],
+ "other_resources" : [(RT_MANIFEST, 1,
+ MANIFEST_TEMPLATE % dict(prog=NAME))],
+ }],
+ description = NAME,
+ author = AUTHOR,
+ author_email = AUTHOR_EMAIL,
+ maintainer = AUTHOR,
+ maintainer_email = AUTHOR_EMAIL,
+ license = LICENSE,
+ url = URL,
+ data_files = DATA_FILES,
+ )
+ shutil.copy2(".\\editra-installer.nsi", ".\\dist\\editra-installer.nsi")
+
+def BuildOSXApp():
+ """Build the OSX Applet"""
+ # Check for setuptools and ask to download if it is not available
+ import src.extern.ez_setup as ez_setup
+ ez_setup.use_setuptools()
+ from setuptools import setup
+
+ CleanBuild()
+ fextents = synextreg.GetFileExtensions()
+ fextents.append("*")
+ PLIST = dict(CFBundleName = info.PROG_NAME,
+ CFBundleIconFile = 'Editra.icns',
+ CFBundleShortVersionString = info.VERSION,
+ CFBundleGetInfoString = info.PROG_NAME + " " + info.VERSION,
+ CFBundleExecutable = info.PROG_NAME,
+ CFBundleIdentifier = "org.editra.%s" % info.PROG_NAME.title(),
+ CFBundleDocumentTypes = [dict(CFBundleTypeExtensions=fextents,
+ CFBundleTypeIconFile='editra_doc',
+ CFBundleTypeRole="Editor"
+ ),
+ ],
+ CFBundleTypeMIMETypes = ['text/plain',],
+ CFBundleDevelopmentRegion = 'English',
+# TODO Causes errors with the system menu translations and text rendering
+# CFBundleLocalizations = ['English', 'Spanish', 'French', 'Japanese'],
+# ['de_DE', 'en_US', 'es_ES', 'fr_FR',
+# 'it_IT', 'ja_JP', 'nl_NL', 'nn_NO',
+# 'pt_BR', 'ru_RU', 'sr_SR', 'tr_TR',
+# 'uk_UA', 'zh_CN'],
+ # NSAppleScriptEnabled="YES",
+ NSHumanReadableCopyright = u"Copyright %s 2005-%d" % (AUTHOR, YEAR)
+ )
+
+ PY2APP_OPTS = dict(iconfile = ICON['Mac'],
+ argv_emulation = True,
+ optimize = True,
+ includes = INCLUDES,
+ plist = PLIST)
+
+ # Add extra mac specific files
+ DATA_FILES = GenerateBinPackageFiles()
+ DATA_FILES.append("scripts/editramac.sh")
+
+ # Put extern package on path for py2app
+ sys.path.append(os.path.abspath('src/extern'))
+
+ setup(
+ app = APP,
+ version = VERSION,
+ options = dict( py2app = PY2APP_OPTS),
+ description = DESCRIPTION,
+ author = AUTHOR,
+ author_email = AUTHOR_EMAIL,
+ maintainer = AUTHOR,
+ maintainer_email = AUTHOR_EMAIL,
+ license = LICENSE,
+ url = URL,
+ data_files = DATA_FILES,
+ setup_requires = ['py2app'],
+ )
+
+ CreateDMG(VERSION)
+
+def CreateDMG(version):
+ """Create an OSX DMG
+ @param version: version number string
+ @todo: cleanup and generalize
+
+ """
+ Log("Creating DMG for osx installer...")
+
+ assert os.path.exists('dist')
+ os.chdir('dist')
+ vname = "Editra-%s" % version
+ fname = vname + ".dmg"
+ mpath = "/Volumes/Editra-%s" % version
+ comp = "Editra-%s_2.dmg" % version
+
+ if os.path.exists("dist/%s" % fname):
+ Log("Found image from previous running")
+ os.remove("dist/%s" % fname)
+
+ # Create the temporary image
+ Log("Creating disk image...")
+ os.system("hdiutil create -size 75m -fs HFS+ -volname %s %s" % (vname, fname))
+ Log("Mounting disk image...")
+ os.system("hdiutil mount %s" % fname) # Mount the image
+
+ # Move installation files to the new image
+ Log("Copying installation files to installer image...")
+ if not os.path.exists(mpath + "/.bk"):
+ os.mkdir(mpath + "/.bk")
+ shutil.copy2("../pixmaps/installer/inst_bk.png", mpath + "/.bk/inst_bk.png")
+ os.system("ditto -rsrcFork Editra.app %s/Editra.app" % mpath)
+
+ Log("Configuring Finder View Options...")
+# shutil.copy2("../scripts/installer/INSTALLER_DS_Store", mpath + "/.DS_Store")
+# os.chmod(mpath + "/.DS_Store", 777)
+ f = open("tmpscript", 'w')
+ f.write(APPLE_SCRIPT % vname)
+ f.close()
+ status = os.system("osascript tmpscript")
+ os.remove("tmpscript")
+ Log("Applescript return status: %d" % status)
+
+ # Unmount the image
+ Log("Unmounting the installer image...")
+ os.system("hdiutil eject %s" % mpath)
+
+ # Create the compressed image
+ Log("Converting the disk image to a compressed format...")
+ os.system("hdiutil convert %s -format UDZO -imagekey zlib-level=9 -o %s" % (fname, comp))
+
+ # Cleanup
+ Log("Cleaning up temporary installer build files...")
+ os.remove(fname)
+ os.rename(comp, fname)
+
+# Template for controlling some finder options via apple script
+APPLE_SCRIPT = """
+tell application "Finder"
+ tell disk ("%s" as string)
+ open
+
+ tell container window
+ set current view to icon view
+ set toolbar visible to false
+ set statusbar visible to false
+ set the bounds to {10, 60, 522, 402}
+ set statusbar visible to false
+ end tell
+
+ set opts to the icon view options of container window
+ tell opts
+ set icon size to 128
+ end tell
+ set background picture of opts to file ".bk:inst_bk.png"
+ set position of item "Editra.app" to {260, 145}
+
+ update without registering applications
+ end tell
+end tell
+"""
+
+def DoSourcePackage():
+ """Build a source package or do a source install"""
+ # Get the package data
+ DATA = GenerateSrcPackageFiles()
+
+ # Force optimization
+ if 'install' in sys.argv and ('O1' not in sys.argv or '02' not in sys.argv):
+ sys.argv.append('-O2')
+
+ # Install the plugins for this version of Python
+ DATA.append("plugins/*py%d.%d.egg" % sys.version_info[:2])
+
+ # Import proper setup function
+ if 'bdist_egg' in sys.argv:
+ try:
+ from setuptools import setup
+
+ # Only bundle eggs for the given python version
+ DATA.append("plugins/*py%d.%d.egg" % sys.version_info[:2])
+ except ImportError:
+ print "To build an egg setuptools must be installed"
+ else:
+ from distutils.core import setup
+
+ # Try to remove possibly conflicting files from an old install
+ if '--no-clean' not in sys.argv:
+ try:
+ import Editra
+ path = Editra.__file__
+ if '__init__' in path:
+ path = os.path.dirname(path)
+ path = os.path.join(path, 'src')
+ del sys.modules['Editra']
+ shutil.rmtree(path)
+ except (ImportError, OSError):
+ pass
+ except:
+ sys.stderr.write("[ERROR] Failed to remove old source files")
+ else:
+ sys.argv.remove('--no-clean')
+
+ # Make sure to delete any existing MANIFEST file beforehand to
+ # prevent stale file lists
+ if os.path.exists('MANIFEST'):
+ try:
+ os.remove('MANIFEST')
+ except OSError:
+ pass
+
+ setup(
+ name = NAME,
+ scripts = ['editra',],
+ version = VERSION,
+ description = DESCRIPTION,
+ long_description = LONG_DESCRIPT,
+ author = AUTHOR,
+ author_email = AUTHOR_EMAIL,
+ maintainer = AUTHOR,
+ maintainer_email = AUTHOR_EMAIL,
+ url = URL,
+ download_url = "http://editra.org/download",
+ license = LICENSE,
+ platforms = [ "Many" ],
+ packages = [ NAME ],
+ package_dir = { NAME : '.' },
+ package_data = { NAME : DATA },
+ classifiers= CLASSIFIERS,
+ install_requires = ['wxPython',]
+ )
+
+def BuildECLibDemo():
+ """Build the Editra Control Library Demo package"""
+ assert 'eclib' in sys.argv, "Should only be called for eclib build"
+
+ DATA = [ "../src/eclib/*.py", "../tests/controls/*.py"]
+ OUT = 'dist/eclibdemo'
+
+ Log("Cleaning up files")
+ if not os.path.exists('dist'):
+ os.mkdir('dist')
+
+ if os.path.exists('dist/eclibdemo.zip'):
+ os.remove('dist/eclibdemo.zip')
+
+ if os.path.exists(OUT):
+ shutil.rmtree(OUT)
+
+ # Copy the Files
+ Log("Preparing output package...")
+ os.mkdir(OUT)
+ shutil.copytree('src/eclib', 'dist/eclibdemo/eclib')
+ shutil.copytree('tests/controls', 'dist/eclibdemo/demo')
+ shutil.copy('COPYING', 'dist/eclibdemo/')
+ f = open(os.path.abspath('./dist/eclibdemo/__init__.py'), 'wb')
+ f.close()
+
+ # Make the launcher
+ f = open(os.path.abspath('./dist/eclibdemo/RunDemo.py'), 'wb')
+ f.write("import os\nos.chdir('demo')\n"
+ "import demo.demo as demo\n"
+ "demo.Main()\nos.chdir('..')")
+ f.close()
+
+ # Zip it up
+ Log("Create zip file")
+ os.chdir('dist')
+ zfile = zipfile.ZipFile('eclibdemo.zip', 'w',
+ compression=zipfile.ZIP_DEFLATED)
+ files = list()
+ for dpath, dname, fnames in os.walk('eclibdemo'):
+ files.extend([ os.path.join(dpath, fname).\
+ lstrip(os.path.sep)
+ for fname in fnames])
+ for fname in files:
+ zfile.write(fname.encode(sys.getfilesystemencoding()))
+ os.chdir('../')
+ Log("ECLIB Demo build is complete")
+
+def CleanBuild():
+ """Cleanup all build related files"""
+ if os.path.exists('MANIFEST'):
+ os.remove('MANIFEST')
+ for path in ('dist', 'build', 'tmp'):
+ if os.path.exists(path):
+ Log("Cleaning %s..." % path)
+ shutil.rmtree(path)
+
+def Log(msg):
+ """Write to the build log"""
+ # TODO add log file, just write to console for now
+ print(msg)
+
+#----------------------------------------------------------------------------#
+
+if __name__ == '__main__':
+ if __platform__ == "win32" and 'py2exe' in sys.argv:
+ BuildPy2Exe()
+ elif __platform__ == "darwin" and 'py2app' in sys.argv:
+ BuildOSXApp()
+ elif 'eclib' in sys.argv:
+ BuildECLibDemo()
+ elif 'clean' in sys.argv:
+ CleanBuild()
+ else:
+ DoSourcePackage()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/Editra.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/Editra.py
new file mode 100644
index 0000000..db648de
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/Editra.py
@@ -0,0 +1,1188 @@
+#!/usr/bin/env python2
+###############################################################################
+# Name: Editra.py #
+# Purpose: Implements Editras App object and the Main method #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This module defines the Editra Application object and the Main method for
+running Editra.
+
+@summary: Editra's main application object and MainLoop
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: Editra.py 71718 2012-06-12 13:25:48Z CJP $"
+__revision__ = "$Revision: 71718 $"
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import os
+import sys
+
+# Due to some methods that were added in 2.8.3 being used in a large number
+# of places Editra has become incompatible with wxPython 2.8.1.1 and earlier.
+# So ensure correct version of wxPython can be loaded
+if not hasattr(sys, 'frozen') and 'wx' not in sys.modules:
+ import wxversion
+ wxversion.ensureMinimal('2.8')
+
+import codecs
+import base64
+import locale
+import getopt
+import shutil
+import wx
+
+# The event handler mixin is now part of wxPython proper, but there hasn't
+# been an official release with it yet, so try to import the official module
+# but fallback to our own copy if it fails.
+try:
+ import wx.lib.eventStack as events
+except:
+ import extern.events as events
+
+# Try and import a system installed version of pkg_resources else fallback to
+# the one bundled with Editra's source.
+try:
+ from pkg_resources import resource_filename
+except ImportError:
+ from extern.pkg_resources import resource_filename
+
+# Editra Libraries
+import ed_glob
+import ed_i18n
+import profiler
+import util
+import dev_tool
+import ed_main
+import ed_art
+import ed_txt
+import ed_event
+import updater
+import plugin
+import ed_ipc
+import ed_session
+import ebmlib
+from syntax import synglob
+
+#--------------------------------------------------------------------------#
+# Global Variables
+ID_UPDATE_CHECK = wx.NewId()
+
+_ = wx.GetTranslation
+#--------------------------------------------------------------------------#
+
+class Editra(wx.App, events.AppEventHandlerMixin):
+ """The Editra Application Object
+ @deprecated: L{GetMainWindow}
+
+ """
+ def __init__(self, *args, **kargs):
+ """Initialize that main app and its attributes
+ @postcondition: application is created and ready to be run in mainloop
+
+ """
+ wx.App.__init__(self, *args, **kargs)
+ events.AppEventHandlerMixin.__init__(self)
+
+ # Attributes
+ self._log = dev_tool.DEBUGP
+ self._lock = False
+ self._windows = dict()
+ self._isexiting = False
+
+ # Disable debug popups
+ wx.Log.EnableLogging(False)
+ # XXX: Temporary - disable assertions on OSX to work around
+ # upstream bug in drawing code "couldnt draw the rotated text"
+ if wx.Platform == '__WXMAC__':
+ self.SetAssertMode(wx.PYAPP_ASSERT_SUPPRESS)
+
+ # Purge old logs
+ logfile = dev_tool.EdLogFile()
+ logfile.PurgeOldLogs(7)
+
+ if ed_glob.SINGLE:
+ # Setup the instance checker
+ instance_name = u"%s-%s" % (self.GetAppName(), wx.GetUserId())
+ lockpath = wx.StandardPaths.Get().GetTempDir()
+ self._instance = wx.SingleInstanceChecker(instance_name, path=lockpath)
+ if self._instance.IsAnotherRunning():
+ try:
+ opts, args = ProcessCommandLine()
+ except getopt.GetoptError, msg:
+ self._log("[app][err] %s" % str(msg))
+ args = list()
+ opts = dict()
+
+ exml = ed_ipc.IPCCommand()
+ if len(args):
+ nargs = list()
+ for p in args:
+ try:
+ p = ebmlib.GetAbsPath(p)
+ except:
+ pass
+ fxml = ed_ipc.IPCFile()
+ fxml.value = p
+ nargs.append(fxml)
+ exml.filelist = nargs
+ arglist = list()
+ for arg, val in opts.items():
+ axml = ed_ipc.IPCArg()
+ axml.name = arg
+ axml.value = val
+ arglist.append(axml)
+ exml.arglist = arglist
+
+ # TODO: need to process other command line options as well i.e) -g
+ self._log("[app][info] Sending: %s" % exml.Xml)
+ key = profiler.Profile_Get('SESSION_KEY')
+ if ebmlib.IsUnicode(key):
+ key = key.encode(sys.getfilesystemencoding(), 'replace')
+ rval = ed_ipc.SendCommands(exml, key)
+ # If sending the command failed then let the editor startup
+ # a new instance
+ if not rval:
+ self._isfirst = True
+ else:
+ self._log("[app][info] Starting Ipc server...")
+ # Set the session key and save it to the users profile so
+ # that other instances can access the server
+ key = base64.b64encode(os.urandom(8), 'zZ')
+ uname = wx.GetUserName()
+ if ebmlib.IsUnicode(uname):
+ uname = uname.encode(sys.getfilesystemencoding(), 'replace')
+ key = uname + key
+ profiler.Profile_Set('SESSION_KEY', key)
+ profiler.Profile_Set('ISBINARY', hasattr(sys, 'frozen'))
+ path = profiler.Profile_Get('MYPROFILE')
+ profiler.TheProfile.Write(path)
+ try:
+ self._server = ed_ipc.EdIpcServer(self, key)
+ self._server.start()
+ except Exception, msg:
+ self._log("[app][err] Failed to start ipc server")
+ self._log("[app][err] %s" % str(msg))
+ self._server = None
+ self._isfirst = True
+ else:
+ self._isfirst = True
+
+ # Setup Plugins after locale as they may have resource that need to
+ # be loaded.
+ if self._isfirst:
+ self._pluginmgr = plugin.PluginManager()
+
+ self._log("[app][info] Registering Editra's ArtProvider")
+ wx.ArtProvider.PushProvider(ed_art.EditraArt())
+
+ # Check if libenchant has been loaded or need to be
+ import extern.stcspellcheck as stcspellcheck
+ checker = stcspellcheck.STCSpellCheck
+ if not checker.isEnchantOk():
+ spref = profiler.Profile_Get('SPELLCHECK', default=dict())
+ libpath = spref.get('epath', u'')
+ checker.reloadEnchant(libpath)
+ # TODO: log if load fails here
+
+ def AddMessageCatalog(self, name, path):
+ """Add a catalog lookup path to the app
+ @param name: name of catalog (i.e 'projects')
+ @param path: catalog lookup path
+
+ """
+ if self.locale is not None:
+ path = resource_filename(path, 'locale')
+ self.locale.AddCatalogLookupPathPrefix(path)
+ self.locale.AddCatalog(name)
+
+ def OnInit(self):
+ """Initialize the Editor
+ @note: this gets called before __init__
+ @postcondition: custom artprovider and plugins are loaded
+
+ """
+ self.SetAppName(ed_glob.PROG_NAME)
+
+ self._log = dev_tool.DEBUGP
+ self._log("[app][info] Editra is Initializing")
+
+ # Load user preferences
+ self.profile_updated = InitConfig()
+ self._isfirst = False # Is the first instance
+ self._instance = None
+
+ # Setup Locale
+ locale.setlocale(locale.LC_ALL, '')
+ langId = ed_i18n.GetLangId(profiler.Profile_Get('LANG'))
+ if wx.Locale.IsAvailable(langId):
+ self.locale = wx.Locale(langId)
+ if self.locale.GetCanonicalName() in ed_i18n.GetAvailLocales():
+ self._log("[app][info] Loaded Locale '%s'" % self.locale.CanonicalName)
+ self.locale.AddCatalogLookupPathPrefix(ed_glob.CONFIG['LANG_DIR'])
+ self.locale.AddCatalog(ed_glob.PROG_NAME)
+ else:
+ self._log("[app][err] Unknown Locale '%s'" % self.locale.CanonicalName)
+ del self.locale
+ self.locale = None
+ else:
+ self._log("[app][err] The locale %s is not available!" % profiler.Profile_Get('LANG'))
+ self.locale = None
+
+ # Check and set encoding if necessary
+ d_enc = profiler.Profile_Get('ENCODING')
+ if not d_enc:
+ profiler.Profile_Set('ENCODING', ed_txt.DEFAULT_ENCODING)
+ else:
+ # Ensure the default encoding is valid
+ # Fixes up older installs on some systems that may have an
+ # invalid encoding set.
+ try:
+ codecs.lookup(d_enc)
+ except (LookupError, TypeError):
+ self._log("[app][err] Resetting bad encoding: %s" % d_enc)
+ profiler.Profile_Set('ENCODING', ed_txt.DEFAULT_ENCODING)
+
+ # Setup the Error Reporter
+ if profiler.Profile_Get('REPORTER', 'bool', True):
+ sys.excepthook = dev_tool.ExceptionHook
+
+ #---- Bind Events ----#
+ self.Bind(wx.EVT_ACTIVATE_APP, self.OnActivate)
+ self.Bind(wx.EVT_MENU, self.OnNewWindow, id=ed_glob.ID_NEW_WINDOW)
+ self.Bind(wx.EVT_MENU, self.OnCloseWindow)
+ self.Bind(ed_event.EVT_NOTIFY, self.OnNotify)
+ self.Bind(ed_ipc.EVT_COMMAND_RECV, self.OnCommandReceived)
+
+ # Splash a warning if version is not a final version
+ if profiler.Profile_Get('APPSPLASH'):
+ import edimage
+ splash_img = edimage.splashwarn.GetBitmap()
+ self.splash = wx.SplashScreen(splash_img, wx.SPLASH_CENTRE_ON_PARENT | \
+ wx.SPLASH_NO_TIMEOUT, 0, None, wx.ID_ANY)
+ self.splash.Show()
+
+ return True
+
+ def Destroy(self):
+ """Destroy the application"""
+ try:
+ # Cleanup the instance checker
+ del self._instance
+ except AttributeError:
+ pass
+ wx.App.Destroy(self)
+
+ def DestroySplash(self):
+ """Destroy the splash screen"""
+ # If is created and not dead already
+ if getattr(self, 'splash', None) is not None and \
+ isinstance(self.splash, wx.SplashScreen):
+ self.splash.Destroy()
+ self.splash = None
+
+ def Exit(self, force=False):
+ """Exit the program
+ @postcondition: If no toplevel windows are present program will exit.
+ @postcondition: Program may remain open if an open window is locking.
+
+ """
+ self._isexiting = True
+ self._pluginmgr.WritePluginConfig()
+ profiler.TheProfile.Write(profiler.Profile_Get('MYPROFILE'))
+ if not self._lock or force:
+ if getattr(self, '_server', None):
+ self._server.Shutdown()
+
+ try:
+ # Cleanup the instance checker
+ del self._instance
+ except AttributeError:
+ pass
+
+ # Exit the app
+ wx.App.ExitMainLoop(self)
+
+ def GetLocaleObject(self):
+ """Get the locale object owned by this app. Use this method to add
+ extra catalogs for lookup.
+ @return: wx.Locale or None
+
+ """
+ return self.locale
+
+ def GetLog(self):
+ """Returns the logging function used by the app
+ @return: the logging function of this program instance
+
+ """
+ return self._log
+
+ def GetMainWindow(self):
+ """Returns reference to the instance of the MainWindow
+ that is running if available, and None if not.
+ @return: the L{MainWindow} of this app if it is open
+
+ """
+ self._log("[app][warn] Editra::GetMainWindow is deprecated")
+ for window in self._windows:
+ if isinstance(self._windows[window][0], ed_main.MainWindow):
+ return self._windows[window][0]
+ return None
+
+ def GetActiveWindow(self):
+ """Returns the active main window if there is one else it will
+ just return some main window or none if there are no main windows
+ @return: frame instance or None
+
+ """
+ awin = None
+ for win in self.GetMainWindows():
+ if win.IsActive():
+ awin = win
+ break
+
+ if awin is None:
+ awin = self.GetTopWindow()
+ if not isinstance(awin, ed_main.MainWindow):
+ if len(self.GetMainWindows()):
+ awin = self.GetMainWindows()[0]
+
+ return awin
+
+ def GetCurrentBuffer(self):
+ """Get the current buffer from the active window or None
+ @return: EditraStc
+
+ """
+ win = self.GetTopWindow()
+ if not isinstance(win, ed_main.MainWindow):
+ win = self.GetActiveWindow()
+ if win is None:
+ return None # UI dead?
+
+ if isinstance(win, ed_main.MainWindow):
+ nbook = win.GetNotebook()
+ if nbook:
+ return nbook.GetCurrentCtrl()
+ return None
+
+ def GetMainWindows(self):
+ """Returns a list of all open main windows
+ @return: list of L{MainWindow} instances of this app (list may be empty)
+
+ """
+ mainw = list()
+ for window in self._windows:
+ try:
+ if isinstance(self._windows[window][0], ed_main.MainWindow):
+ mainw.append(self._windows[window][0])
+ except AttributeError:
+ continue
+ return mainw
+
+ def GetOpenWindows(self):
+ """Returns a list of open windows
+ @return: list of all open windows owned by app
+
+ """
+ return self._windows
+
+ def GetPluginManager(self):
+ """Returns the plugin manager used by this application
+ @return: Apps plugin manager
+ @see: L{plugin}
+
+ """
+ return self._pluginmgr
+
+ def GetProfileUpdated(self):
+ """Was the profile updated
+ @return: bool
+
+ """
+ return self.profile_updated
+
+ def GetWindowInstance(self, wintype):
+ """Get an instance of an open window if one exists
+ @param wintype: Class type of window to look for
+ @precondition: Window must have called L{RegisterWindow}
+ @return: Instance of window or None
+
+ """
+ for win in self._windows:
+ if isinstance(self._windows[win][0], wintype):
+ return self._windows[win][0]
+ return None
+
+ def IsLocked(self):
+ """Returns whether the application is locked or not
+ @return: whether a window has locked the app from closing or not
+
+ """
+ return self._lock
+
+ def IsOnlyInstance(self):
+ """Check if this app is the the first instance that is running
+ @return: bool
+
+ """
+ return self._isfirst
+
+ def Lock(self):
+ """Locks the app from exiting
+ @postcondition: program is locked from exiting
+
+ """
+ self._lock = True
+
+ def OpenFile(self, filename, line=-1):
+ """Open a file in the currently active window
+ @param filename: file path
+ @keyword line: int
+
+ """
+ window = self.GetTopWindow()
+ if not isinstance(window, ed_main.MainWindow):
+ window = None
+
+ try:
+ encoding = sys.getfilesystemencoding()
+ fname = ed_txt.DecodeString(filename, encoding)
+
+ if profiler.Profile_Get('OPEN_NW', default=False):
+ self.OpenNewWindow(fname, window)
+ elif window:
+ window.DoOpen(ed_glob.ID_COMMAND_LINE_OPEN, fname, line)
+
+ # Make sure the window is brought to the front
+ if window.IsIconized():
+ window.Iconize(False)
+ window.Raise()
+ else:
+ # Some unlikely error condition
+ self._log("[app][err] OpenFile unknown error: %s" % filename)
+
+ except Exception, msg:
+ self._log("[app][err] Failed to open file: %s" % str(msg))
+
+ def MacNewFile(self):
+ """Stub for future use"""
+ pass
+
+ def MacOpenFile(self, filename):
+ """Macintosh Specific code for opening files that are associated
+ with the editor and double clicked on after the editor is already
+ running.
+ @param filename: file path string
+ @postcondition: if L{MainWindow} is open file will be opened in notebook
+
+ """
+ self._log("[app][info] MacOpenFile Fired")
+ self.OpenFile(filename, line=-1)
+
+ def MacPrintFile(self, filename):
+ """Stub for future use
+ @param filename: file to print
+
+ """
+ pass
+
+ def MacReopenApp(self):
+ """Handle kAEReopenApplication when dock icons is clicked on"""
+ frame = self.GetTopWindow()
+ if frame is not None:
+ if frame.IsIconized():
+ frame.Iconize(False)
+ frame.Raise()
+
+ def OnActivate(self, evt):
+ """Activation Event Handler
+ @param evt: wx.ActivateEvent
+
+ """
+ if evt.GetActive():
+ self._log("[app][info] I'm Awake!!")
+ # Refresh Clipboard Ring
+ ed_main.MainWindow.UpdateClipboardRing()
+
+# frame = self.GetTopWindow()
+# if frame is not None:
+# if frame.IsIconized():
+# frame.Iconize(False)
+# frame.Raise()
+ else:
+ self._log("[app][info] Going to sleep")
+ evt.Skip()
+
+ def OnExit(self, evt=None, force=False):
+ """Handle application exit request
+ @keyword evt: event that called this handler
+ @keyword force: Force an exit
+
+ """
+ e_id = -1
+ if evt:
+ e_id = evt.GetId()
+
+ if e_id == ed_glob.ID_EXIT:
+ self._isexiting = True
+ # First loop is to ensure current top window is
+ # closed first
+ for win in self.GetMainWindows():
+ if win.IsActive():
+ result = win.Close()
+ if result:
+ self._isexiting = False
+ break
+ return
+ for win in self.GetMainWindows():
+ win.Raise()
+ result = win.Close()
+ if not result:
+ self._isexiting = False
+ break
+ self.Exit(force)
+ else:
+ if evt:
+ evt.Skip()
+
+ def OnNewWindow(self, evt):
+ """Create a new editing window
+ @param evt: wx.EVT_MENU
+
+ """
+ if evt.GetId() == ed_glob.ID_NEW_WINDOW:
+ frame = evt.GetEventObject().GetMenuBar().GetFrame()
+ self.OpenNewWindow(caller=frame)
+ else:
+ evt.Skip()
+
+ def OnCommandReceived(self, evt):
+ """Receive commands from the IPC server
+ @todo: move command processing into own module
+
+ """
+ # Guard against events that come in after shutdown
+ # from server thread.
+ if not self or self._isexiting or not self.IsMainLoopRunning():
+ return
+
+ self._log("[app][info] IN OnCommandReceived")
+ cmds = evt.GetCommands()
+ if isinstance(cmds, ed_ipc.IPCCommand):
+ self._log("[app][info] OnCommandReceived %s" % cmds.Xml)
+ if not len(cmds.filelist):
+ self.OpenNewWindow()
+ else:
+ # TODO: change goto line handling to require one
+ # arg per file specified on the command line
+ # i.e) -g 23,44,100
+ line = -1
+ for argobj in cmds.arglist:
+ arg = argobj.name
+ if arg == '-g':
+ line = int(argobj.value)
+ if line > 0:
+ line -= 1
+ break
+
+ for fname in cmds.filelist:
+ self.OpenFile(fname.value, line)
+
+ def OnCloseWindow(self, evt):
+ """Close the currently active window
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.GetId() in [ed_glob.ID_CLOSE, ed_glob.ID_CLOSE_WINDOW]:
+ for window in wx.GetTopLevelWindows():
+ if hasattr(window, 'IsActive') and window.IsActive():
+ if hasattr(window, 'Close'):
+ window.Close()
+ break
+ else:
+ evt.Skip()
+
+ def OpenNewWindow(self, fname=u'', caller=None):
+ """Open a new window
+ @keyword fname: Open a file in the new window
+ @keyword caller: MainWindow that called to open this one
+ @return: the new window
+
+ """
+ frame = ed_main.MainWindow(None, wx.ID_ANY,
+ profiler.Profile_Get('WSIZE'),
+ ed_glob.PROG_NAME)
+ if caller:
+ pos = caller.GetPosition()
+ frame.SetPosition((pos.x + 22, pos.y + 22))
+
+ self.RegisterWindow(repr(frame), frame, True)
+ self.SetTopWindow(frame)
+ if isinstance(fname, basestring) and fname != u'':
+ frame.DoOpen(ed_glob.ID_COMMAND_LINE_OPEN, fname)
+ frame.Show(True)
+
+ # Ensure frame gets an Activate event when shown
+ # this doesn't happen automatically on windows
+ if wx.Platform == '__WXMSW__':
+ wx.PostEvent(frame, wx.ActivateEvent(wx.wxEVT_ACTIVATE, True))
+ return frame
+
+ def OnNotify(self, evt):
+ """Handle notification events
+ @param evt: L{ed_event.NotificationEvent}
+
+ """
+ e_val = evt.GetValue()
+ if evt.GetId() == ID_UPDATE_CHECK and \
+ isinstance(e_val, tuple) and e_val[0]:
+ self.DestroySplash()
+ mdlg = wx.MessageDialog(self.GetActiveWindow(),
+ _("An updated version of Editra is available\n"
+ "Would you like to download Editra %s now?") %\
+ e_val[1], _("Update Available"),
+ wx.YES_NO|wx.YES_DEFAULT|wx.CENTER|wx.ICON_INFORMATION)
+ if mdlg.ShowModal() == wx.ID_YES:
+ dl_dlg = updater.DownloadDialog(None, wx.ID_ANY,
+ _("Downloading Update"))
+ dp_sz = wx.GetDisplaySize()
+ dl_dlg.SetPosition(((dp_sz[0] - (dl_dlg.GetSize()[0] + 5)), 25))
+ dl_dlg.Show()
+ mdlg.Destroy()
+ else:
+ evt.Skip()
+
+ def RegisterWindow(self, name, window, can_lock=False):
+ """Registers winows with the app. The name should be the
+ repr of window. The can_lock parameter is a boolean stating
+ whether the window can keep the main app running after the
+ main frame has exited.
+ @param name: name of window
+ @param window: reference to window object
+ @keyword can_lock: whether window can lock exit or not
+
+ """
+ self._windows[name] = (window, can_lock)
+
+ def ReloadArtProvider(self):
+ """Reloads the custom art provider onto the artprovider stack
+ @postcondition: artprovider is removed and reloaded
+
+ """
+ try:
+ wx.ArtProvider.PopProvider()
+ finally:
+ wx.ArtProvider.PushProvider(ed_art.EditraArt())
+
+ def UnLock(self):
+ """Unlocks the application
+ @postcondition: application is unlocked so it can exit
+
+ """
+ self._lock = False
+
+ def UnRegisterWindow(self, name):
+ """Unregisters a named window with the app if the window
+ was the top window and if other windows that can lock are
+ registered in the window stack it will promote the next one
+ it finds to be the top window. If no windows that fit this
+ criteria are found it will close the application.
+ @param name: name of window to unregister
+
+ """
+ if name in self._windows:
+ self._windows.pop(name)
+
+ if not len(self._windows):
+ self._log("[app][info] No more open windows shutting down")
+ self.Exit()
+ return
+
+ # TODO: WXBUG? calling GetTopWindow when there are no more top
+ # level windows causes a crash under MSW. Moving this line
+ # above the previous check can reproduce the error.
+ cur_top = self.GetTopWindow()
+ if name == repr(cur_top):
+ found = False
+ for key in self._windows:
+ if self._windows[key][1]:
+ self._log("[app][info] Promoting %s to top" % key)
+ try:
+ self.SetTopWindow(self._windows[key][0])
+ except Exception:
+ continue
+ found = True
+ break
+
+ if not found:
+ self._log("[app][info] No more top windows exiting app")
+ self.UnLock()
+ self.Exit()
+ else:
+ self._log("[app][info] UnRegistered %s" % name)
+ else:
+ self._log("[app][warn] The window %s is not registered" % name)
+
+ def WindowCanLock(self, winname):
+ """Checks if a named window can lock the application or
+ not. The window must have been previously registered with
+ a call to RegisterWindow for this function to have any
+ real usefullness.
+ @param winname: name of window to query
+
+ """
+ if winname in self._windows:
+ return self._windows[winname][1]
+ else:
+ self._log("[app][warn] the window %s has "
+ "not been registered" % winname)
+ return False
+
+#--------------------------------------------------------------------------#
+
+def InitConfig():
+ """Initializes the configuration data
+ @postcondition: all configuration data is set
+
+ """
+ # Check if a custom config directory was specified on the commandline
+ if ed_glob.CONFIG['CONFIG_BASE'] is not None:
+ # TODO: there is a bug when the first time the config is created
+ # where the settings will not be saved until second launching.
+ config_base = os.path.abspath(ed_glob.CONFIG['CONFIG_BASE'])
+ else:
+ # Look for a profile directory on the system level. If this directory
+ # exists Use it instead of the user one. This will allow for running
+ # Editra from a portable drive or for system administrators to enforce
+ # settings on a system installed version.
+ config_base = util.ResolvConfigDir(u'.Editra', True)
+
+ if os.path.exists(config_base):
+ ed_glob.CONFIG['CONFIG_BASE'] = config_base
+ ed_glob.CONFIG['PROFILE_DIR'] = os.path.join(config_base, u"profiles")
+ ed_glob.CONFIG['PROFILE_DIR'] += os.sep
+ ed_glob.CONFIG['ISLOCAL'] = True
+ else:
+ config_base = wx.StandardPaths.Get().GetUserDataDir()
+ ed_glob.CONFIG['PROFILE_DIR'] = util.ResolvConfigDir(u"profiles")
+
+ # Check for if config directory exists and if profile is from the current
+ # running version of Editra.
+ profile_updated = False
+ if util.HasConfigDir() and os.path.exists(ed_glob.CONFIG['PROFILE_DIR']):
+ if profiler.ProfileIsCurrent():
+ pstr = profiler.GetProfileStr()
+ # If using local(portable) config the profile string is stored
+ # as a relative path that just names the config file.
+ if ed_glob.CONFIG['ISLOCAL']:
+ pstr = os.path.join(ed_glob.CONFIG['PROFILE_DIR'], pstr)
+ pstr = util.RepairConfigState(pstr)
+ dev_tool.DEBUGP("[InitConfig][info] Loading profile: %s" % repr(pstr))
+ profiler.TheProfile.Load(pstr)
+ else:
+ dev_tool.DEBUGP("[InitConfig][info] Updating Profile to current version")
+
+ # When upgrading from an older version make sure all
+ # config directories are available.
+ for cfg in ("cache", "styles", "plugins", "profiles", "sessions"):
+ if not util.HasConfigDir(cfg):
+ util.MakeConfigDir(cfg)
+
+ # Load and update profile
+ pstr = profiler.GetProfileStr()
+ pstr = util.RepairConfigState(pstr)
+ profiler.TheProfile.Load(pstr)
+ profiler.TheProfile.Update()
+
+ #---- Temporary Profile Adaption ----#
+
+ # Added after 0.5.32
+ mconfig = profiler.Profile_Get('LEXERMENU', default=None)
+ if mconfig is None:
+ mconfig = [ synglob.LANG_C, synglob.LANG_CPP,
+ synglob.LANG_BASH, synglob.LANG_CSS,
+ synglob.LANG_HTML, synglob.LANG_JAVA,
+ synglob.LANG_LISP, synglob.LANG_PERL,
+ synglob.LANG_PHP, synglob.LANG_PYTHON,
+ synglob.LANG_RUBY, synglob.LANG_SQL,
+ synglob.LANG_XML]
+ mconfig.sort()
+ profiler.Profile_Set('LEXERMENU', mconfig)
+
+ # GUI_DEBUG mode removed in 0.2.5
+ mode = profiler.Profile_Get('MODE')
+ if mode == 'GUI_DEBUG':
+ profiler.Profile_Set('MODE', 'DEBUG')
+
+ # This key has been removed so clean it from old profiles
+ profiler.Profile_Del('LASTCHECK')
+
+ # Print modes don't use strings anymore
+ if isinstance(profiler.Profile_Get('PRINT_MODE'), basestring):
+ profiler.Profile_Set('PRINT_MODE', ed_glob.PRINT_BLACK_WHITE)
+
+ # Simplifications to eol mode persistence (0.4.28)
+ # Keep for now till plugins are updated
+ #profiler.Profile_Del('EOL') # changed to EOL_MODE
+
+ # After 0.4.65 LAST_SESSION now points a session file and not
+ # to a list of files to open.
+ ed_glob.CONFIG['SESSION_DIR'] = util.ResolvConfigDir(u"sessions")
+ smgr = ed_session.EdSessionMgr()
+ sess = profiler.Profile_Get('LAST_SESSION')
+ if isinstance(sess, list) or not sess:
+ profiler.Profile_Set('LAST_SESSION', smgr.DefaultSession)
+ else:
+ # After 0.6.58 session is reduced to a name instead of path
+ if sess and os.path.sep in sess:
+ name = smgr.SessionNameFromPath(sess)
+ profiler.Profile_Set('LAST_SESSION', name)
+
+ #---- End Temporary Profile Adaption ----#
+
+ # Write out updated profile
+ profiler.TheProfile.Write(pstr)
+
+ profile_updated = True
+ else:
+ # Fresh install
+ util.CreateConfigDir()
+
+ # Check and upgrade installs from old location
+ success = True
+ try:
+ success = UpgradeOldInstall()
+ except Exception, msg:
+ dev_tool.DEBUGP("[InitConfig][err] %s" % msg)
+ success = False
+
+ if not success:
+ old_cdir = u"%s%s.%s%s" % (wx.GetHomeDir(), os.sep,
+ ed_glob.PROG_NAME, os.sep)
+ msg = ("Failed to upgrade your old installation\n"
+ "To retain your old settings you may need to copy some files:\n"
+ "\nFrom: %s\n\nTo: %s") % (old_cdir, config_base)
+ wx.MessageBox(msg, "Upgrade Failed", style=wx.ICON_WARNING|wx.OK)
+
+ # Set default eol for windows
+ if wx.Platform == '__WXMSW__':
+ profiler.Profile_Set('EOL_MODE', ed_glob.EOL_MODE_CRLF)
+ profiler.Profile_Set('ICONSZ', (16, 16))
+ elif wx.Platform == '__WXMAC__':
+ # Default to 32x32 toolbar icons on OSX
+ profiler.Profile_Set('ICONSZ', (32, 32))
+
+ #---- Profile Loaded / Installed ----#
+
+ # Set debug mode
+ emode = profiler.Profile_Get('MODE')
+ if 'DEBUG' in emode:
+ ed_glob.DEBUG = True
+ if emode.startswith('VERBOSE'):
+ ed_glob.VDEBUG = True
+
+ # Resolve resource locations
+ ed_glob.CONFIG['CONFIG_DIR'] = util.ResolvConfigDir(u"")
+ ed_glob.CONFIG['INSTALL_DIR'] = util.ResolvConfigDir(u"", True)
+ ed_glob.CONFIG['KEYPROF_DIR'] = util.ResolvConfigDir(u"ekeys", True)
+ ed_glob.CONFIG['SYSPIX_DIR'] = util.ResolvConfigDir(u"pixmaps", True)
+ ed_glob.CONFIG['PLUGIN_DIR'] = util.ResolvConfigDir(u"plugins")
+ ed_glob.CONFIG['THEME_DIR'] = util.ResolvConfigDir(os.path.join(u"pixmaps", u"theme"))
+ ed_glob.CONFIG['LANG_DIR'] = util.ResolvConfigDir(u"locale", True)
+ ed_glob.CONFIG['STYLES_DIR'] = util.ResolvConfigDir(u"styles")
+ ed_glob.CONFIG['SYS_PLUGIN_DIR'] = util.ResolvConfigDir(u"plugins", True)
+ ed_glob.CONFIG['SYS_STYLES_DIR'] = util.ResolvConfigDir(u"styles", True)
+ ed_glob.CONFIG['TEST_DIR'] = util.ResolvConfigDir(os.path.join(u"tests", u"syntax"), True)
+
+ # Make sure all standard config directories are there
+ for cfg in ("cache", "styles", "plugins", "profiles", "sessions"):
+ if not util.HasConfigDir(cfg):
+ util.MakeConfigDir(cfg)
+ ed_glob.CONFIG['CACHE_DIR'] = util.ResolvConfigDir(u"cache")
+ ed_glob.CONFIG['SESSION_DIR'] = util.ResolvConfigDir(u"sessions")
+
+ return profile_updated
+
+#--------------------------------------------------------------------------#
+
+def UpgradeOldInstall():
+ """Upgrade an old installation and transfer all files if they exist
+ @note: FOR INTERNAL USE ONLY
+ @return: bool (True if success, False if failure)
+
+ """
+ old_cdir = u"%s%s.%s%s" % (wx.GetHomeDir(), os.sep,
+ ed_glob.PROG_NAME, os.sep)
+ base = ed_glob.CONFIG['CONFIG_BASE']
+ if base is None:
+ base = wx.StandardPaths.Get().GetUserDataDir() + os.sep
+
+ err = 0
+ if os.path.exists(old_cdir) and \
+ base.lower().rstrip(os.sep) != old_cdir.lower().rstrip(os.sep):
+ for item in os.listdir(old_cdir):
+ try:
+ dest = os.path.join(base, item)
+ item = os.path.join(old_cdir, item)
+ if os.path.exists(dest):
+ if os.path.isdir(dest):
+ shutil.rmtree(dest, True)
+ else:
+ os.remove(dest)
+
+ shutil.move(item, dest)
+ except Exception, msg:
+ util.Log("[Upgrade][err] %s" % msg)
+ err += 1
+ continue
+
+ os.rmdir(old_cdir)
+
+ # Load the copied over profile
+ pstr = profiler.GetProfileStr()
+ prof = os.path.basename(pstr)
+ pstr = os.path.join(base, u"profiles", prof)
+ if os.path.exists(pstr):
+ profiler.TheProfile.Load(pstr)
+ profiler.TheProfile.Update()
+ profiler.UpdateProfileLoader()
+
+ if not err:
+ wx.MessageBox(_("Your profile has been updated to the latest "
+ "version") + u"\n" + \
+ _("Please check the preferences dialog to check "
+ "your preferences"),
+ _("Profile Updated"))
+
+ return not err
+
+#--------------------------------------------------------------------------#
+
+def PrintHelp(err=None):
+ """Print command line help
+ @postcondition: Help is printed and program exits
+
+ """
+ if err is not None:
+ sys.stderr.write(err + os.linesep)
+
+ print(("Editra - %s - Developers Text Editor\n"
+ "Cody Precord (2005-2012)\n\n"
+ "usage: Editra [arguments] [files... ]\n\n"
+ "Short Arguments:\n"
+ " -c Set custom configuration directory at runtime\n"
+ " -d Turn on console debugging (-dd for verbose debug)\n"
+ " -D Turn off console debugging (overrides preferences)\n"
+ " -g Open file to line (i.e Editra -g 10 file.txt)\n"
+ " -h Show this help message\n"
+ " -p Run Editra in the profiler (outputs to editra.prof).\n"
+ " -v Print version number and exit\n"
+ " -S Disable single instance checker\n"
+ "\nLong Arguments:\n"
+ " --confdir arg Set custom configuration directory at runtime\n"
+ " --debug Turn on console debugging\n"
+ " --help Show this help message\n"
+ " --auth Print the ipc server info\n"
+ " --version Print version number and exit\n"
+ " --profileOut arg Run Editra in the profiler (arg is output file)\n"
+ ) % ed_glob.VERSION)
+
+ if err is None:
+ os._exit(0)
+ else:
+ os._exit(1)
+
+#--------------------------------------------------------------------------#
+
+def ProcessCommandLine():
+ """Process the command line switches
+ @return: tuple ({switches,}, [args,])
+
+ """
+ try:
+ items, args = getopt.getopt(sys.argv[1:], "dg:hp:vDSc:",
+ ['debug', 'help', 'version', 'auth',
+ 'confdir=', 'profileOut='])
+ except getopt.GetoptError, msg:
+ # Raise error to console and exit
+ PrintHelp(str(msg))
+
+ # Process command line options
+ opts = dict(items)
+ for opt, value in dict(opts).items():
+ if opt in ['-h', '--help']:
+ PrintHelp()
+ elif opt in ['-v', '--version']:
+ print(ed_glob.VERSION)
+ os._exit(0)
+ elif opt in ['-d', '--debug'] and '-D' not in opts.keys():
+ # If the debug flag is set more than once go into verbose mode
+ if ed_glob.DEBUG:
+ ed_glob.VDEBUG = True
+ ed_glob.DEBUG = True
+ opts.pop(opt)
+ elif opt == '-D':
+ ed_glob.DEBUG = False
+ ed_glob.VDEBUG = False
+ opts.pop('-D')
+ elif opt == '-S':
+ # Disable single instance checker
+ ed_glob.SINGLE = False
+ opts.pop(opt)
+ elif opt in ['-c', '--confdir']:
+ ed_glob.CONFIG['CONFIG_BASE'] = value
+ opts.pop(opt)
+ elif opt == '--profileOut':
+ opts['-p'] = value
+ opts.pop('--profileOut')
+ elif opt == '-g':
+ # Validate argument passed to -g
+ if not value.isdigit():
+ PrintHelp("error: -g requires a number as an argument!")
+ else:
+ pass
+
+ # Return any unprocessed arguments
+ return opts, args
+
+#--------------------------------------------------------------------------#
+
+def Main():
+ """Configures and Runs an instance of Editra
+ @summary: Parses command line options, loads the user profile, creates
+ an instance of Editra and starts the main loop.
+
+ """
+ opts, args = ProcessCommandLine()
+
+ if '-p' in opts:
+ p_file = opts['-p']
+ opts.pop('-p')
+
+ if not len(p_file):
+ # Fall back to default output file
+ p_file = "editra.prof"
+
+ import hotshot
+ prof = hotshot.Profile(p_file)
+ prof.runcall(_Main, opts, args)
+ prof.close()
+ else:
+ _Main(opts, args)
+
+def _Main(opts, args):
+ """Main method
+ @param opts: Commandline options
+ @param args: Commandline arguments
+
+ """
+ # Put extern subpackage on path so that bundled external dependencies
+ # can be found if needed.
+ if not hasattr(sys, 'frozen'):
+ epath = os.path.join(os.path.dirname(__file__), 'extern')
+ if os.path.exists(epath):
+ sys.path.append(epath)
+
+ # Create Application
+ dev_tool.DEBUGP("[main][app] Initializing application...")
+ editra_app = Editra(False)
+
+ # Print ipc server authentication info
+ if '--auth' in opts:
+ opts.pop('--auth')
+ print "port=%d,key=%s" % (ed_ipc.EDPORT,
+ profiler.Profile_Get('SESSION_KEY'))
+
+ # Check if this is the only instance, if its not exit since
+ # any of the opening commands have already been passed to the
+ # master instance
+ if not editra_app.IsOnlyInstance():
+ dev_tool.DEBUGP("[main][info] Second instance exiting...")
+ editra_app.Destroy()
+ os._exit(0)
+
+ # Set the timeout on destroying the splash screen
+ wx.CallLater(2300, editra_app.DestroySplash)
+
+ if profiler.Profile_Get('SET_WSIZE'):
+ wsize = profiler.Profile_Get('WSIZE')
+ else:
+ wsize = (700, 450)
+ frame = ed_main.MainWindow(None, wx.ID_ANY, wsize, ed_glob.PROG_NAME)
+ frame.Maximize(profiler.Profile_Get('MAXIMIZED'))
+ editra_app.RegisterWindow(repr(frame), frame, True)
+ editra_app.SetTopWindow(frame)
+ frame.Show(True)
+
+ # Load Session Data
+ # But not if there are command line args for files to open
+ if profiler.Profile_Get('SAVE_SESSION', 'bool', False) and not len(args):
+ smgr = ed_session.EdSessionMgr()
+ session = profiler.Profile_Get('LAST_SESSION', default=u'')
+ if isinstance(session, list):
+ # Check for format conversion from previous versions
+ profiler.Profile_Set('LAST_SESSION', smgr.DefaultSession)
+ session = smgr.DefaultSession
+ frame.GetNotebook().LoadSessionFile(session)
+ del session
+
+ # Unlike wxMac/wxGTK Windows doesn't post an activate event when a window
+ # is first shown, so do it manually to make sure all event handlers get
+ # pushed.
+ if wx.Platform == '__WXMSW__':
+ wx.PostEvent(frame, wx.ActivateEvent(wx.wxEVT_ACTIVATE, True))
+
+ # Do update check if preferences say its ok to do so
+ isadmin = os.access(ed_glob.CONFIG['INSTALL_DIR'], os.R_OK|os.W_OK)
+ if isadmin and profiler.Profile_Get('CHECKUPDATE', default=True):
+ uthread = updater.UpdateThread(editra_app, ID_UPDATE_CHECK)
+ uthread.start()
+
+ if len(args):
+ line = -1
+ if '-g' in opts:
+ line = max(0, int(opts.pop('-g')) - 1)
+
+ # TODO: should line arg only be applied to the first file name or all?
+ # currently apply to all.
+ for arg in args:
+ try:
+ fname = ed_txt.DecodeString(arg, sys.getfilesystemencoding())
+ fname = ebmlib.GetAbsPath(fname)
+ frame.DoOpen(ed_glob.ID_COMMAND_LINE_OPEN, fname, line)
+ except IndexError:
+ dev_tool.DEBUGP("[main][err] IndexError on commandline args")
+
+ # Notify that profile was updated
+ if editra_app.GetProfileUpdated():
+ editra_app.DestroySplash()
+ # Make sure window iniliazes to default position
+ profiler.Profile_Del('WPOS')
+ wx.MessageBox(_("Your profile has been updated to the latest "
+ "version") + u"\n" + \
+ _("Please check the preferences dialog to verify "
+ "your preferences"),
+ _("Profile Updated"))
+
+ # 3. Start Applications Main Loop
+ dev_tool.DEBUGP("[main][info] Starting MainLoop...")
+ wx.CallAfter(frame.Raise)
+
+ # Install handlers to exit app if os is shutting down/restarting
+ ebmlib.InstallTermHandler(editra_app.Exit, force=True)
+
+ editra_app.MainLoop()
+ dev_tool.DEBUGP("[main][info] MainLoop finished exiting application")
+ os._exit(0)
+
+#-----------------------------------------------------------------------------#
+if __name__ == '__main__':
+ Main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/__init__.py
new file mode 100644
index 0000000..7902bda
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/__init__.py
@@ -0,0 +1,13 @@
+###############################################################################
+# Name: __init__.py #
+# Purpose: Import the required base modules needed for launching Editra into #
+# into the namespace. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+"""Main package module"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: __init__.py 49807 2007-11-10 07:08:33Z CJP $"
+__revision__ = "$Revision: 49807 $"
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/__init__.py
new file mode 100644
index 0000000..edf32b7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/__init__.py
@@ -0,0 +1,22 @@
+###############################################################################
+# Name: __init__.py #
+# Purpose: Initializes the autocomp package #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""Autocomp sub package
+@note: this may be removed when the autocomp system becomes part of the plugin
+ system
+
+"""
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: __init__.py 62467 2009-10-22 02:10:51Z CJP $"
+__revision__ = "$Revision: 62467 $"
+
+#-----------------------------------------------------------------------------#
+# Setup Public Namespace
+
+from autocomp import *
+from completer import *
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/autocomp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/autocomp.py
new file mode 100644
index 0000000..8913aba
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/autocomp.py
@@ -0,0 +1,112 @@
+###############################################################################
+# Name: autocomp.py #
+# Purpose: Provides the front end interface for autocompletion services for #
+# the editor. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides an interface/service for getting autocompletion/calltip data
+into an stc control. This is a data provider only it does not do provide
+any UI functionality or calls. The user called object from this library
+is intended to be the AutoCompService. This service provides the generic
+interface into the various language specific autocomplete services, and
+makes the calls to the other support objects/functions in this library.
+
+@summary: Autocompletion support interface implementation
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: autocomp.py 66207 2010-11-18 15:56:19Z CJP $"
+__revision__ = "$Revision: 66207 $"
+__all__ = ['AutoCompService',]
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import wx
+import wx.stc as stc
+
+# Local imports
+import simplecomp
+
+#--------------------------------------------------------------------------#
+
+class AutoCompService(object):
+ """Interface to retrieve and provide autocompletion and
+ calltip information to an stc control. The plain text
+ (empty) completion provider is built in. All other providers
+ are loaded from external modules on request.
+
+ """
+ def __init__(self):
+ """Initializes the autocompletion service"""
+ super(AutoCompService, self).__init__()
+
+ @staticmethod
+ def GetCompleter(buff, extended=False):
+ """Get the appropriate completer object for the given buffer.
+ @todo: implement dynamic loading mechanism for each comp class
+
+ """
+ lex_value = buff.GetLexer()
+ if lex_value == stc.STC_LEX_PYTHON:
+ import pycomp
+ compl = pycomp.Completer
+ elif lex_value in (stc.STC_LEX_HTML, stc.STC_LEX_XML):
+ import htmlcomp
+ compl = htmlcomp.Completer
+ elif lex_value == stc.STC_LEX_CSS:
+ import csscomp
+ compl = csscomp.Completer
+ else:
+ return simplecomp.Completer(buff)
+
+ if extended:
+ compl = CompleterFactory(compl, buff)
+ else:
+ compl = compl(buff)
+
+ return compl
+
+#--------------------------------------------------------------------------#
+
+class MetaCompleter(type):
+ """Meta class for creating custom completer classes at runtime"""
+ def __call__(mcs, base, buff):
+ """Modify the base class with our new methods at time of
+ instantiation.
+
+ """
+ obj = type.__call__(mcs, base, buff)
+
+ # Set/override attributes on the new completer object.
+ setattr(obj, 'BaseGetAutoCompList', obj.GetAutoCompList)
+ setattr(obj, 'GetAutoCompList', lambda cmd: GetAutoCompList(obj, cmd))
+ setattr(obj, 'scomp', simplecomp.Completer(buff))
+
+ # Return the new augmented completer
+ return obj
+
+def GetAutoCompList(self, command):
+ """Apply SimpleCompleter results to base results from the
+ 'smart' completer.
+
+ """
+ baseList = self.BaseGetAutoCompList(command)
+ scompList = self.scomp.GetAutoCompList(command)
+ # Wipeout duplicates by creating a set, then sort data alphabetically
+ baseList.extend(scompList)
+ rlist = list(set(baseList))
+ rlist.sort()
+ return rlist
+
+class CompleterFactory(object):
+ """Factory for creating composite completer objects"""
+ __metaclass__ = MetaCompleter
+ def __new__(cls, base, buff):
+ """Return an instance of the passed in class type"""
+ self = base(buff)
+ return self
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/completer.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/completer.py
new file mode 100644
index 0000000..77ad5cf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/completer.py
@@ -0,0 +1,304 @@
+###############################################################################
+# Name: completer.py #
+# Purpose: Autcompleter interface base class. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Base class for autocompletion providers to implement the completion interface.
+
+@summary: Autocompleter base class
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: completer.py 70211 2011-12-31 02:23:54Z CJP $"
+__revision__ = "$Revision: 70211 $"
+
+__all__ = [ 'TYPE_FUNCTION', 'TYPE_METHOD', 'TYPE_CLASS', 'TYPE_ATTRIBUTE',
+ 'TYPE_VARIABLE', 'TYPE_ELEMENT', 'TYPE_PROPERTY', 'TYPE_UNKNOWN',
+ 'BaseCompleter', 'Symbol', 'CreateSymbols' ]
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+
+#--------------------------------------------------------------------------#
+
+# Image Type Ids
+TYPE_FUNCTION, \
+TYPE_METHOD, \
+TYPE_CLASS, \
+TYPE_ATTRIBUTE, \
+TYPE_PROPERTY, \
+TYPE_VARIABLE, \
+TYPE_ELEMENT, \
+TYPE_UNKNOWN = range(1, 9)
+
+#--------------------------------------------------------------------------#
+class Symbol(object):
+ """ Defines a symbol as parsed by the autocompleter.
+ Symbols with the same name and different type are EQUAL
+ Symbol hash is based on symbol NAME
+
+ """
+ # we create lots of these so use slots as a performance tweak
+ __slots__ = ('_name', '_type')
+
+ def __init__(self, name, symtype):
+ """ Constructor
+ @param name: Symbol name
+ @param symtype: Symbol type, one of the TYPE_FUNCTION ... TYPE_UNKNOWN range
+
+ """
+ super(Symbol, self).__init__()
+
+ # Attributes
+ self._name = unicode(name)
+ self._type = symtype
+
+ def __eq__(self, other):
+ return (self.Name == other.Name)
+
+ def __lt__(self, other):
+ return (self.Name < other.Name)
+
+ def __le__(self, other):
+ return (self.Name <= other.Name)
+
+ def __ne__(self, other):
+ return (self.Name != other.Name)
+
+ def __gt__(self, other):
+ return (self.Name > other.Name)
+
+ def __ge__(self, other):
+ return (self.Name >= other.Name)
+
+ # TODO: this task should probably be delegated to the ui
+ def __str__(self):
+ if self.Type != TYPE_UNKNOWN:
+ return u'?'.join([self.Name, unicode(self.Type)])
+ else:
+ return self.Name
+
+ def __hash__(self):
+ return hash(self.Name)
+
+ Name = property(lambda self: self._name,
+ lambda self, n: setattr(self, '_name', n))
+ Type = property(lambda self: self._type,
+ lambda self, t: setattr(self, '_type', t))
+
+#--------------------------------------------------------------------------#
+
+def CreateSymbols(arglst, symtype=TYPE_UNKNOWN):
+ """Convert a list of strings to a list of Symbol objects
+ @param arglst: list of strings
+ @keyword symtype: TYPE_FOO
+ @return: list of Symbols
+
+ """
+ return [ Symbol(obj, symtype) for obj in arglst ]
+
+#--------------------------------------------------------------------------#
+
+class BaseCompleter(object):
+ """Base Autocomp provider class"""
+ def __init__(self, parent):
+ """Initializes the auto-completion service
+ @param parent: parent of this service object
+
+ """
+ super(BaseCompleter, self).__init__()
+
+ # Attributes
+ self._buffer = parent
+ self._log = wx.GetApp().GetLog()
+ self._case_sensitive = False
+ self._autocomp_after = False
+ self._choose_single = True
+
+ self._autocomp_keys = list()
+ self._autocomp_stop = u''
+ self._autocomp_fillup = u''
+ self._calltip_keys = list()
+ self._calltip_cancel = list()
+
+ #--- Override in subclass ----#
+
+ def GetAutoCompList(self, command):
+ """Retrieves the sorted autocomplete list for a command
+ @param command: command string to do lookup on
+ @return: list of strings
+
+ """
+ return list()
+
+ def GetCallTip(self, command):
+ """Returns the calltip string for a command
+ @param command: command to get calltip for (string)
+ @return: string
+
+ """
+ return u''
+
+ def OnCompletionInserted(self, pos, text):
+ """Called by the buffer when an autocomp selection has been inserted.
+ The completer can override this method to
+ @param pos: Position the caret was at before the insertion
+ @param text: text that was inserted at pos
+
+ """
+ pass
+
+ #--- End override in subclass ----#
+
+ def GetCommandString(self, stc, line, col):
+ """Get the command string found at the current location to use
+ for lookups.
+ @param stc: EditraStc
+ @param line: line text
+ @param col: position in line (column)
+
+ """
+ line = line.expandtabs(stc.GetTabWidth())
+ line = line[:col]
+ if line and ord(line[-1]) in (self.GetAutoCompKeys() + self.GetCallTipKeys()):
+ line = line[:-1]
+ cmd_lmt = list(self.GetAutoCompStops() + self.GetAutoCompFillups())
+ for key in self.GetAutoCompKeys():
+ kval = unichr(key)
+ if kval in cmd_lmt:
+ cmd_lmt.remove(kval)
+
+ cmd = u''
+ curr_pos = len(line) - 1
+ while curr_pos > -1:
+ cmd = line[curr_pos:]
+ if len(cmd) and cmd[0] not in cmd_lmt:
+ curr_pos -= 1
+ else:
+ break
+
+ for char in cmd_lmt:
+ cmd = cmd.replace(char, u'')
+
+ return cmd.strip()
+
+ def GetAutoCompKeys(self):
+ """Returns the list of key codes for activating the auto-completion.
+ @return: list of characters used for activating auto-completion
+
+ """
+ return self._autocomp_keys
+
+ def SetAutoCompKeys(self, key_list):
+ """Set the keys to provide completions on
+ @param key_list: List of key codes
+
+ """
+ self._autocomp_keys = key_list
+
+ def GetAutoCompStops(self):
+ """Returns a string of characters that should cancel
+ the auto-completion lookup.
+ @return: string of characters that will hide the autocomp/calltip
+
+ """
+ return self._autocomp_stop
+
+ def SetAutoCompStops(self, stops):
+ """Set the keys to cancel auto-completions on.
+ @param stops: string
+
+ """
+ self._autocomp_stop = stops
+
+ def GetAutoCompFillups(self):
+ """Get the list of characters to do a fillup on
+ @return: string
+
+ """
+ return self._autocomp_fillup
+
+ def SetAutoCompFillups(self, fillups):
+ """Set the list of characters to do a fillup on
+ @param fillups: string
+
+ """
+ self._autocomp_fillup = fillups
+
+ def GetCallTipKeys(self):
+ """Returns the list of keys to activate a calltip on
+ @return: list of calltip activation keys
+
+ """
+ return self._calltip_keys
+
+ def SetCallTipKeys(self, keys):
+ """Set the list of keys to activate calltips on
+ @return: list of calltip activation keys
+
+ """
+ self._calltip_keys = keys
+
+ def GetCallTipCancel(self):
+ """Get the list of key codes that should stop a calltip"""
+ return self._calltip_cancel
+
+ def SetCallTipCancel(self, key_list):
+ """Set the list of key codes that should stop a calltip"""
+ self._calltip_cancel = key_list
+
+ def GetBuffer(self):
+ """Get the reference to the buffer this autocomp object is owned by
+ @return: EditraStc
+
+ """
+ return self._buffer
+
+ def GetCaseSensitive(self):
+ """Are commands case sensitive or not
+ @return: bool
+
+ """
+ return self._case_sensitive
+
+ def SetCaseSensitive(self, sensitive):
+ """Set whether this completer is case sensitive or not
+ @param sensitive: bool
+
+ """
+ self._case_sensitive = sensitive
+
+ def GetChooseSingle(self):
+ """Get whether the completer should automatically choose a selection
+ when there is only one symbol in the completion list.
+ @return: bool
+
+ """
+ return self._choose_single
+
+ def SetChooseSingle(self, single):
+ """Set whether the completer should automatically choose a selection
+ when there is only one symbol in the completion list.
+ @param single: bool
+
+ """
+ self._choose_single = single
+
+ def ShouldCheck(self, cpos):
+ """Should completions be attempted
+ @param cpos: current buffer position
+ @return: bool
+
+ """
+ buff = self.GetBuffer()
+ rval = True
+ if buff is not None:
+ if buff.IsString(cpos) or buff.IsComment(cpos):
+ rval = False
+ return rval
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/csscomp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/csscomp.py
new file mode 100644
index 0000000..f28b693
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/csscomp.py
@@ -0,0 +1,169 @@
+###############################################################################
+# Name: csscomp.py #
+# Purpose: Simple input assistant for CSS #
+# Author: Cody Precord #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Simple autocompletion support for Cascading Style Sheets.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: csscomp.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import re
+import wx
+import wx.stc
+
+# Local Imports
+import completer
+
+#--------------------------------------------------------------------------#
+
+# Regular Expressions
+RE_LINK_PSEUDO = re.compile("a:(link|visited|active|hover|focus)*")
+RE_CSS_COMMENT = re.compile("\/\*[^*]*\*+([^/][^*]*\*+)*\/")
+RE_CSS_BLOCK = re.compile("\{[^}]*\}")
+
+PSUEDO_SYMBOLS = completer.CreateSymbols([ u'active', u'focus', u'hover',
+ u'link', u'visited' ],
+ )
+
+#--------------------------------------------------------------------------#
+
+class Completer(completer.BaseCompleter):
+ """CSS Code completion provider"""
+ def __init__(self, stc_buffer):
+ super(Completer, self).__init__(stc_buffer)
+
+ # Setup
+ self.SetAutoCompKeys([ord(':'), ord('.') ])
+ self.SetAutoCompStops(' {}#')
+ self.SetAutoCompFillups('')
+ self.SetCallTipKeys([ord('('), ])
+ self.SetCallTipCancel([ord(')'), wx.WXK_RETURN])
+
+ def GetAutoCompList(self, command):
+ """Returns the list of possible completions for a command string.
+ @param command: command lookup is done on
+
+ """
+ buff = self.GetBuffer()
+ keywords = buff.GetKeywords()
+ if command in [None, u'']:
+ return completer.CreateSymbols(keywords, completer.TYPE_UNKNOWN)
+
+ cpos = buff.GetCurrentPos()
+ cline = buff.GetCurrentLine()
+ lstart = buff.PositionFromLine(cline)
+ tmp = buff.GetTextRange(lstart, cpos).rstrip()
+
+ # Check for the case of a pseudo class
+ if IsPsuedoClass(command, tmp):
+ return PSUEDO_SYMBOLS
+
+ # Give some help on some common properties
+ if tmp.endswith(u':'):
+ word = GetWordLeft(tmp.rstrip().rstrip(u':'))
+ comps = PROP_OPTS.get(word, list())
+ comps = list(set(comps))
+ comps.sort()
+ return completer.CreateSymbols(comps, completer.TYPE_PROPERTY)
+
+ # Look for if we are completing a tag class
+ if tmp.endswith(u'.'):
+ classes = list()
+ if not buff.IsString(cpos):
+ txt = buff.GetText()
+ txt = RE_CSS_COMMENT.sub(u'', txt)
+ txt = RE_CSS_BLOCK.sub(u' ', txt)
+ for token in txt.split():
+ if u'.' in token:
+ classes.append(token.split(u'.', 1)[-1])
+
+ classes = list(set(classes))
+ classes.sort()
+ return completer.CreateSymbols(classes, completer.TYPE_CLASS)
+
+ return completer.CreateSymbols(keywords, completer.TYPE_UNKNOWN)
+
+ def GetCallTip(self, command):
+ """Returns the formated calltip string for the command."""
+ if command == u'url':
+ return u'url(\'../path\')'
+ else:
+ return u''
+
+ def ShouldCheck(self, cpos):
+ """Should completions be attempted
+ @param cpos: current buffer position
+ @return: bool
+
+ """
+ buff = self.GetBuffer()
+ rval = True
+ if buff is not None:
+ if buff.IsComment(cpos):
+ rval = False
+ return rval
+
+#--------------------------------------------------------------------------#
+
+def IsPsuedoClass(cmd, line):
+ """Check the line to see if its a link pseudo class
+ @param cmd: current command
+ @param line: line of the command
+ @return: bool
+
+ """
+ if cmd.endswith(u':'):
+ token = line.split()[-1]
+ pieces = token.split(u":")
+ if pieces[0] == 'a' or pieces[0].startswith('a.'):
+ return True
+ return False
+
+def GetWordLeft(line):
+ """Get the first valid word to the left of the end of line
+ @param line: Line text
+ @return: string
+
+ """
+ for idx in range(1, len(line)+1):
+ ch = line[idx*-1]
+ if ch.isspace() or ch in u'{;':
+ return line[-1*idx:].strip()
+ else:
+ return u''
+
+#--------------------------------------------------------------------------#
+
+# Properties to provide some input help on
+PROP_OPTS = { u'border-style' : [u'none', u'hidden', u'dotted', u'dashed',
+ u'solid', u'double', u'groove', u'ridge',
+ u'inset', u'outset'],
+ u'float' : [u'left', u'right', u'none'],
+ u'font-style' : [u'normal', u'italic', u'oblique'],
+ u'font-weight' : [u'normal', u'bold', u'lighter', u'bolder'],
+ u'list-style-type' : [u'none', u'disc', u'circle', u'square',
+ u'decimal', u'decimal-leading-zero',
+ u'lower-roman', u'upper-roman',
+ u'lower-alpha', u'upper-alpha',
+ u'lower-greek', u'lower-latin', u'hebrew',
+ u'armenian', u'georgian', u'cjk-ideographic',
+ u'hiragana', u'katakana',
+ u'hiragana-iroha', u'katakana-iroha'],
+ u'text-decoration' : [u'none', u'underline', u'line-through',
+ u'overline', u'blink'],
+ u'text-align' : [u'left', u'right', u'center', u'justify'],
+ u'vertical-align' : [u'baseline', u'sub', u'super', u'top',
+ u'text-top', u'middle', u'bottom',
+ u'text-bottom', ]
+ }
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/htmlcomp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/htmlcomp.py
new file mode 100644
index 0000000..4ca4dcd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/htmlcomp.py
@@ -0,0 +1,192 @@
+###############################################################################
+# Name: htmlcomp.py #
+# Purpose: Simple input assistant for html and xml. #
+# Author: Cody Precord #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Simple autocompletion support for HTML and XML documents.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: htmlcomp.py 72389 2012-08-28 16:53:09Z CJP $"
+__revision__ = "$Revision: 72389 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import re
+import wx
+import wx.stc
+
+# Local Imports
+import completer
+
+#--------------------------------------------------------------------------#
+# Standard Html Tags
+TAGS = ['!--', 'a', 'abbr', 'accept', 'accesskey', 'acronym', 'action',
+ 'address', 'align', 'alink', 'alt', 'applet', 'archive', 'area',
+ 'article', 'aside', 'audio', 'axis', 'b', 'background', 'base',
+ 'basefont', 'bdo', 'bgcolor', 'big', 'blockquote', 'body', 'border',
+ 'bordercolor', 'br', 'button', 'canvas', 'caption', 'cellpadding',
+ 'cellspacing', 'center', 'char', 'charoff', 'charset', 'checked',
+ 'cite', 'cite', 'class', 'classid', 'clear', 'code', 'codebase',
+ 'codetype', 'col', 'colgroup', 'color', 'cols', 'colspan', 'command',
+ 'compact', 'content', 'coords', 'data', 'datetime', 'datalist', 'dd',
+ 'declare', 'defer', 'del', 'details', 'dfn', 'dialog', 'dir', 'dir',
+ 'disabled', 'div', 'dl', 'dt', 'dtml-call', 'dtml-comment', 'dtml-if',
+ 'dtml-in', 'dtml-let', 'dtml-raise', 'dtml-tree', 'dtml-try',
+ 'dtml-unless', 'dtml-var', 'dtml-with', 'em', 'embed', 'enctype',
+ 'face', 'fieldset', 'figcaption', 'figure', 'font', 'for', 'form',
+ 'footer', 'frame', 'gutter', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head',
+ 'header', 'headers', 'height', 'hgroup', 'hr', 'href', 'hreflang',
+ 'hspace', 'html', 'http-equiv', 'i', 'id', 'iframe', 'img', 'input',
+ 'ins', 'isindex', 'ismap', 'kbd', 'keygen', 'label', 'lang', 'language',
+ 'legend', 'li', 'link', 'link', 'longdesc', 'lowsrc', 'map',
+ 'marginheight', 'marginwidth', 'mark', 'maxlength', 'menu', 'meta',
+ 'meter', 'method', 'multiple', 'name', 'nav', 'nohref', 'noscript',
+ 'nowrap', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param',
+ 'pre', 'profile', 'progress', 'prompt', 'q', 'readonly', 'rel', 'rev',
+ 'rows', 'rowspan', 'rp', 'rt', 'ruby', 'rules', 's', 'samp', 'scheme',
+ 'scope', 'script', 'scrolling', 'section', 'select', 'selected',
+ 'shape', 'size', 'small', 'source', 'span', 'src', 'standby', 'start',
+ 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'tabindex',
+ 'table', 'target', 'tbody', 'td', 'text', 'textarea', 'tfoot', 'th',
+ 'thead', 'time', 'title', 'tr', 'tt', 'type', 'u', 'ul', 'url',
+ 'usemap', 'valign', 'value', 'valuetype', 'var', 'version', 'video',
+ 'vlink', 'vspace', 'width', 'wrap', 'xmp']
+
+# Tags that usually have a new line inbetween them
+NLINE_TAGS = ('body', 'head', 'html', 'ol', 'style', 'table', 'tbody', 'ul')
+
+TAG_RE = re.compile("\<\s*([a-zA-Z][a-zA-Z0-9]*)")
+
+PHP_AREA = [wx.stc.STC_HPHP_COMMENT, wx.stc.STC_HPHP_COMMENTLINE,
+ wx.stc.STC_HPHP_COMPLEX_VARIABLE, wx.stc.STC_HPHP_DEFAULT,
+ wx.stc.STC_HPHP_HSTRING, wx.stc.STC_HPHP_HSTRING_VARIABLE,
+ wx.stc.STC_HPHP_NUMBER, wx.stc.STC_HPHP_OPERATOR,
+ wx.stc.STC_HPHP_SIMPLESTRING,
+ wx.stc.STC_HPHP_VARIABLE, wx.stc.STC_HPHP_WORD]
+
+HTML_AREA = [wx.stc.STC_H_ASP, wx.stc.STC_H_ASPAT, wx.stc.STC_H_ATTRIBUTE,
+ wx.stc.STC_H_ATTRIBUTEUNKNOWN, wx.stc.STC_H_CDATA,
+ wx.stc.STC_H_COMMENT, wx.stc.STC_H_DEFAULT,
+ wx.stc.STC_H_DOUBLESTRING, wx.stc.STC_H_ENTITY,
+ wx.stc.STC_H_NUMBER, wx.stc.STC_H_OTHER, wx.stc.STC_H_QUESTION,
+ wx.stc.STC_H_SCRIPT, wx.stc.STC_H_SGML_1ST_PARAM,
+ wx.stc.STC_H_SGML_1ST_PARAM_COMMENT,
+ wx.stc.STC_H_SGML_BLOCK_DEFAULT, wx.stc.STC_H_SGML_COMMAND,
+ wx.stc.STC_H_SGML_COMMENT, wx.stc.STC_H_SGML_DEFAULT,
+ wx.stc.STC_H_SGML_DOUBLESTRING, wx.stc.STC_H_SGML_ENTITY,
+ wx.stc.STC_H_SGML_ERROR, wx.stc.STC_H_SGML_SIMPLESTRING,
+ wx.stc.STC_H_SGML_SPECIAL, wx.stc.STC_H_SINGLESTRING,
+ wx.stc.STC_H_TAG, wx.stc.STC_H_TAGEND,
+ wx.stc.STC_H_TAGUNKNOWN, wx.stc.STC_H_VALUE,
+ wx.stc.STC_H_XCCOMMENT, wx.stc.STC_H_XMLEND,
+ wx.stc.STC_H_XMLSTART]
+
+#--------------------------------------------------------------------------#
+
+class Completer(completer.BaseCompleter):
+ """HTML/XML Code completion provider"""
+ def __init__(self, stc_buffer):
+ super(Completer, self).__init__(stc_buffer)
+
+ # Setup
+ self.SetAutoCompKeys([ord('>'), ord('<')])
+ self.SetAutoCompStops(' ')
+ self.SetAutoCompFillups('')
+
+ def GetAutoCompList(self, command):
+ """Returns the list of possible completions for a
+ command string.
+ @param command: command lookup is done on
+
+ """
+ if command in [None, u'', u'<']:
+ return list()
+
+ buff = self.GetBuffer()
+ cpos = buff.GetCurrentPos()
+
+ # Check if we are in a php region or not
+ if buff.GetStyleAt(cpos) not in HTML_AREA:
+ return list()
+
+ # Get current context
+ cline = buff.GetCurrentLine()
+ ccol = buff.GetColumn(cpos)
+ tmp = buff.GetLine(cline).rstrip()
+ if ccol < len(tmp):
+ tmp = tmp[:ccol].rstrip()
+
+ # Check if we are completing an open tag (i.e < was typed)
+ if tmp.endswith('<'):
+ if buff.GetLexer() == wx.stc.STC_LEX_XML:
+ taglst = _FindXmlTags(buff.GetText())
+ else:
+ taglst = TAGS
+ return completer.CreateSymbols(taglst, completer.TYPE_ELEMENT)
+
+ # Check for a self closing tag (i.e />)
+ endchk = tmp.strip().replace(u" ", u"").replace(u"\t", u"")
+ if endchk.endswith(u"/>"):
+ return list()
+
+ # Try to autocomplete a closing tag (if necessary)
+ tmp = tmp.rstrip('>').rstrip()
+ if len(tmp) and (tmp[-1] in '"\' \t' or tmp[-1].isalpha()):
+ # Walk backwards from the current line
+ for line in range(cline, -1, -1):
+ txt = buff.GetLine(line)
+ if line == cline:
+ txt = txt[:buff.GetColumn(cpos)]
+
+ idx = txt.rfind('<')
+ if idx != -1:
+ parts = txt[idx:].lstrip('<').strip().split()
+ if len(parts):
+ tag = parts[0].rstrip('>')
+ if len(tag) and \
+ tag not in ('img', 'br', '?php', '?xml', '?') and \
+ not tag[0] in ('!', '/'):
+ rtag = u"</" + tag + u">"
+
+ if not parts[-1].endswith('>'):
+ rtag = u">" + rtag
+ return [ completer.Symbol(rtag, completer.TYPE_ELEMENT) ]
+ break
+
+ return list()
+
+ def OnCompletionInserted(self, pos, text):
+ """Handle adjusting caret position after some insertions.
+ @param pos: position caret was at before insertion
+ @param text: text that was inserted
+
+ """
+ buff = self.GetBuffer()
+ if text.strip().startswith(u"</"):
+ buff.SetCurrentPos(pos) # move caret back between the tags
+ # HACK: SetCurrentPos causes text to be selected
+ buff.SetSelection(pos, pos)
+
+#--------------------------------------------------------------------------#
+
+def _FindXmlTags(text):
+ """Dynamically generate a list of possible xml tags based on tags found in
+ the given text.
+ @param text: string
+ @return: sorted list
+
+ """
+ matches = TAG_RE.findall(text)
+ if len(matches):
+ matches.append(u'!--')
+ matches = list(set(matches))
+ matches.sort()
+ else:
+ matches = [u'!--', ]
+ return matches
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/pycomp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/pycomp.py
new file mode 100644
index 0000000..e76ca32
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/pycomp.py
@@ -0,0 +1,1039 @@
+###############################################################################
+# Name: pycomp.py #
+# Purpose: Provides python autocompletion lists and calltips for the editor #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides completion and calltip support for python documents. To provide the
+completion lists and calltips a mix of parsing and introspection is used to
+deduct the requested information.
+
+@summary: Python autocompletion support
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: pycomp.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#--------------------------------------------------------------------------#
+# Dependancies
+import os
+import sys
+import time
+import tokenize
+import types
+from token import NAME, DEDENT, STRING
+
+import wx
+from wx.py import introspect
+
+from StringIO import StringIO
+
+# Local imports
+import completer
+
+#--------------------------------------------------------------------------#
+
+class Completer(completer.BaseCompleter):
+ """Python Code completion provider"""
+ def __init__(self, stc_buffer):
+ """Initializes the completer
+ @param stc_buffer: buffer that contains code
+
+ """
+ super(Completer, self).__init__(stc_buffer)
+
+ # Setup
+ self.SetAutoCompKeys([ord('.'), ])
+ self.SetAutoCompStops(' \'"\\`):')
+ self.SetAutoCompFillups('.,;([]}<>%^&+-=*/|')
+ self.SetCallTipKeys([ord('('), ])
+ self.SetCallTipCancel([ord(')'), wx.WXK_RETURN])
+
+ # Needed for introspect to run
+ try:
+ sys.ps1
+ except AttributeError:
+ sys.ps1 = '>>>'
+
+ try:
+ sys.ps2
+ except AttributeError:
+ sys.ps2 = '...'
+
+ def _GetCompletionInfo(self, command, calltip=False):
+ """Get Completion list or Calltip
+ @return: list or string
+
+ """
+ if command is None or (len(command) and command[0].isdigit()):
+ if calltip:
+ return u""
+ return list()
+
+ try:
+ cmpl = PyCompleter()
+
+ # Put the files directory on the path so eval has a better
+ # chance of getting the proper completions
+ fname = self._buffer.GetFileName()
+ if fname:
+ fpath = os.path.dirname(fname)
+ sys.path.insert(0, fpath)
+ snapshot = list(sys.modules.keys())
+
+ t1 = time.time()
+ cmpl.evalsource(self._buffer.GetText(),
+ self._buffer.GetCurrentLine())
+ dbg("[pycomp][info] Completion eval time: %f" % (time.time() - t1))
+
+ if fname:
+ sys.path.pop(0)
+
+ # Dump any other modules that got brought in during eval
+ # so that they get properly updated on next pass through.
+ nsnapshot = sys.modules.keys()
+ nimport = list(set(nsnapshot).difference(set(snapshot)))
+ for k in nimport:
+ del sys.modules[k]
+
+ if calltip:
+ return cmpl.get_completions(command + u'(', u'', calltip)
+ else:
+ # Get Auto-completion List
+ complst = cmpl.get_completions(command)
+ sigs = list()
+ tmap = {"function" : completer.TYPE_FUNCTION,
+ "method" : completer.TYPE_METHOD,
+ "class" : completer.TYPE_CLASS,
+ "attribute" : completer.TYPE_ATTRIBUTE,
+ "property" : completer.TYPE_PROPERTY}
+ for sig in complst:
+ word = sig['word'].rstrip(u'(.')
+ tval = tmap.get(sig['type'], completer.TYPE_UNKNOWN)
+ sigs.append(completer.Symbol(word, tval))
+ sigs.sort(key=lambda x: x.Name.upper())
+ return sigs
+
+ except BaseException, msg:
+ self._log("[pycomp][err] _GetCompletionInfo: %s, %s" % \
+ (sys.exc_info()[0], sys.exc_info()[1]))
+ if calltip:
+ return u""
+ else:
+ return list()
+
+ def GetAutoCompList(self, command):
+ """Returns the list of possible completions for a command string.
+ @param command: command lookup is done on
+
+ """
+ return self._GetCompletionInfo(command)
+
+ def GetCallTip(self, command):
+ """Returns the formatted calltip string for the command.
+ @param command: command to get calltip for
+
+ """
+ # get the relevant text
+ alltext = self._GetCompletionInfo(command, calltip=True)
+
+ # split the text into natural paragraphs (a blank line separated)
+ paratext = alltext.split("\n\n")
+
+ # add text by paragraph until text limit or all paragraphs
+ textlimit = 800
+ if len(paratext[0]) < textlimit:
+ numpara = len(paratext)
+ calltiptext = paratext[0]
+ ii = 1
+ while ii < numpara and \
+ (len(calltiptext) + len(paratext[ii])) < textlimit:
+ calltiptext = calltiptext + "\n\n" + paratext[ii]
+ ii = ii + 1
+
+ # if not all texts are added, add "[...]"
+ if ii < numpara:
+ calltiptext = calltiptext + "\n[...]"
+ # present the function signature only (first newline)
+ else:
+ calltiptext = alltext.split("\n")[0]
+
+ if type(calltiptext) != types.UnicodeType:
+ # Ensure it is unicode
+ try:
+ stcbuff = self.GetBuffer()
+ encoding = stcbuff.GetEncoding()
+ calltiptext = calltiptext.decode(encoding)
+ except Exception, msg:
+ dbg("%s" % msg)
+
+ return calltiptext
+
+#-----------------------------------------------------------------------------#
+# This code below is a modified and adapted version of the pythoncomplete
+# Omni completion script for vim. The original vimscript can be found at the
+# following address: http://www.vim.org/scripts/script.php?script_id=1542
+def dbg(msg):
+ wx.GetApp().GetLog()(msg)
+
+class PyCompleter(object):
+ """Python code completion provider"""
+ def __init__(self):
+ self.compldict = {}
+ self.parser = PyParser()
+
+ def evalsource(self, text, line=0):
+ """Evaluate source for introspection
+ @param text: Text to evaluate
+ @keyword line: current line of cursor
+
+ """
+ scope = self.parser.parse(text.replace('\r\n', '\n'), line)
+ src = scope.get_code()
+ # Test
+# f = open('pycompout.py', 'w')
+# f.write(src)
+# f.close()
+ # NOTE: keep commented out in production code can cause slow down
+ # when running in editra with DEBUG output.
+# dbg("[pycomp][info] Generated source: %s" % src)
+ try:
+ exec src in self.compldict
+ except Exception, msg:
+ dbg("[pycomp][err] src exec: %s" % msg)
+ else:
+ dbg("[pycomp][info] Successfully executed source code")
+
+ for loc in [ l[1] for l in scope.locals]:
+ try:
+ exec loc in self.compldict
+ except Exception, msg:
+ dbg("[pycomp][err] local exec %s [%s]" % (msg, loc))
+ else:
+ dbg("[pycomp][info] Successfully executed: %s" % loc)
+
+ def get_arguments(self, func_obj):
+ """Get the arguments of a given function obj
+ @param func_obj: function object to get parameters for
+
+ """
+ def _ctor(obj):
+ """Get the constructor for an object"""
+ try:
+ return obj.__init__.im_func
+ except AttributeError:
+ for base in obj.__bases__:
+ constructor = getattr(base, '__init__', None)
+ if constructor is not None:
+ return constructor
+ return None
+
+ arg_offset = 1
+ if type(func_obj) == types.ClassType:
+ func_obj = _ctor(func_obj)
+ elif type(func_obj) == types.MethodType:
+ func_obj = func_obj.im_func
+ else:
+ arg_offset = 0
+
+ arg_text = ''
+ if type(func_obj) in [types.FunctionType, types.LambdaType]:
+ try:
+ fcode = func_obj.func_code
+ real_args = fcode.co_varnames[arg_offset:fcode.co_argcount]
+ defaults = func_obj.func_defaults or ''
+ defaults = [ "=%s" % name for name in defaults ]
+ defaults = [""] * (len(real_args) - len(defaults)) + defaults
+ items = [ arg + default
+ for arg, default in zip(real_args, defaults) ]
+ if fcode.co_flags & 0x4:
+ items.append("...")
+ if fcode.co_flags & 0x8:
+ items.append("***")
+ arg_text = (','.join(items)) + ')'
+
+ except Exception, msg:
+ dbg("[pycomp][err] get_arguments: %s" % msg)
+
+ if len(arg_text) == 0:
+ # The doc string sometimes contains the function signature
+ # this works for alot of C modules that are part of the
+ # standard library
+ doc = getattr(func_obj, '__doc__', False)
+ if doc:
+ doc = str(doc)
+ doc = doc.lstrip()
+ pos = doc.find('\n')
+ if pos > 0:
+ sigline = doc[:pos]
+ lidx = sigline.find('(')
+ ridx = sigline.find(')')
+ if lidx > 0 and ridx > 0:
+ arg_text = sigline[lidx + 1 : ridx] + ')'
+
+ if len(arg_text) == 0:
+ arg_text = ')'
+
+ return arg_text
+
+ def get_completions(self, context, match='', ctip=False):
+ """Get the completions for the given context
+ @param context: command string to get completions for
+ @keyword match: for matching an incomplete command string
+ @keyword ctip: Get a calltip for the context instead of completion list
+ @return: list of dictionaries
+
+ """
+ dbg("[pycomp] get_completions('%s','%s')" % (context, match))
+ stmt = context + match
+
+ try:
+ result = None
+ compdict = {}
+ ridx = stmt.rfind('.')
+ if len(stmt) > 0 and stmt[-1] == '(':
+ if ctip:
+ # Try introspect.getCallTip since it is generally
+ # better at getting tips for c modules
+ tip = introspect.getCallTip(_sanitize(stmt),
+ self.compldict)[2]
+ if not isinstance(tip, basestring):
+ tip = u""
+ if not tip:
+ # Internal calltip code
+ result = eval(_sanitize(stmt.rstrip('(')), self.compldict)
+ doc = max(getattr(result, '__doc__', ''), ' ')
+ argval = context + _cleanstr(self.get_arguments(result))
+ tip = '\n'.join([argval, _cleanstr(doc)])
+ dbg("[pycomp][info] Used internal calltips")
+ return tip
+
+ elif ridx == -1:
+ match = stmt
+ compdict = self.compldict
+ else:
+ match = stmt[ridx+1:]
+ stmt = _sanitize(stmt[:ridx])
+ result = eval(stmt, self.compldict)
+ compdict = dir(result)
+
+ dbg("[pycomp] completing: stmt:%s" % stmt)
+ completions = []
+ isdict = isinstance(compdict, dict)
+ for meth in compdict:
+ if meth == "_PyCmplNoType":
+ continue #this is internal
+
+ try:
+# dbg('[pycomp] possible completion: %s' % meth)
+ if meth.find(match) == 0:
+ if result is None:
+ # NOTE: when result is none compdict is a list
+ inst = meth #compdict[meth]
+ else:
+ inst = getattr(result, meth, None)
+
+ # TODO: necessary check to handle some odd swig related
+ # errors. Find out why type 'swigvarlink' causes
+ # the exception Unknown C global variable.
+ if len(dir(inst)):
+ doc = getattr(inst, '__doc__', None)
+ if doc is None:
+ doc = max(getattr(result, '__doc__', ' '), ' ')
+ else:
+ doc = ' '
+
+ if isdict:
+ typestr = str(compdict[inst])
+ else:
+ typestr = str(inst)
+
+ comp = {'word' : meth,
+ 'abbr' : meth,
+ 'info' : _cleanstr(str(doc)),
+ 'type' : typestr}
+
+ if "function" in typestr:
+ comp['word'] += '('
+ comp['abbr'] += '(' + _cleanstr(self.get_arguments(inst))
+ comp['type'] = "function"
+ elif "method" in typestr or "slot wrapper" in typestr:
+ comp['word'] += '('
+ comp['abbr'] += '(' + _cleanstr(self.get_arguments(inst))
+ comp['type'] = "method"
+ elif "module" in typestr:
+ comp['word'] += '.'
+ comp['type'] = "module"
+ elif "class" in typestr:
+ comp['word'] += '('
+ comp['abbr'] += '('
+ comp['type'] = "class"
+ elif "attribute" in typestr or \
+ (not typestr.startswith('__') and \
+ not typestr.startswith('<')):
+ comp['type'] = "attribute"
+ elif "property" in typestr:
+ comp['type'] = "property"
+# else:
+# print typestr, meth
+
+ completions.append(comp)
+ except Exception, msg:
+ dbg("[pycomp][err] inner completion: %s [stmt='%s']:" % (msg, stmt))
+
+ return completions
+ except Exception, msg:
+ dbg("[pycomp][err] get_completions: %s [stmt='%s']" % (msg, stmt))
+ if ctip:
+ return u""
+ return list()
+
+#-----------------------------------------------------------------------------#
+# Code objects
+
+class Scope(object):
+ """Base class for representing code objects"""
+ def __init__(self, name, indent):
+ """Initialize the scope
+ @param name: name of this object
+ @param indent: the indentation/level of this scope
+
+ """
+ super(Scope, self).__init__()
+
+ # Attributes
+ self.subscopes = list()
+ self.docstr = u''
+ self.locals = list()
+ self.parent = None
+ self.name = name
+ self.indent = indent
+ self.objid = -1 # Tracks order of declaration
+
+ DocStr = property(lambda self: self.docstr,
+ lambda self, dstr: setattr(self, 'docstr', dstr))
+ Locals = property(lambda self: self.locals,
+ lambda self, loc: setattr(self, 'locals', loc))
+ Parent = property(lambda self: self.parent,
+ lambda self, parent: setattr(self, 'parent', parent))
+
+ def Clone(self, indent=0):
+ """Clone this scope object"""
+ obj = Scope(self.name, indent)
+ obj.DocStr = self.DocStr
+ obj.Locals = list(self.Locals)
+ obj.Parent = self.Parent
+ for scope in self.subscopes:
+ obj.subscopes.append((scope[0], scope[1].Clone(indent + 1)))
+ obj.objid = self.objid
+ return obj
+
+ def NextObjId(self):
+ self.objid += 1
+ return self.objid
+
+ def add(self, sub):
+ """Push a subscope into this scope
+ @param sub: sub scope to push
+
+ """
+ sub.parent = self
+ self.subscopes.append((self.NextObjId(), sub))
+ return sub
+
+ def doc(self, docstr):
+ """Format and set the doc string for this scope
+ @param docstr: Docstring to format and set
+
+ """
+ dstr = docstr
+ if len(dstr):
+ while len(dstr) and dstr[0] in '"\' ':
+ dstr = dstr[1:]
+
+ while len(dstr) and dstr[-1] in '"\' ':
+ dstr = dstr[:-1]
+ dstr = '\n'.join([d.lstrip() for d in dstr.split('\n')])
+ self.docstr = dstr.rstrip()
+
+ def local(self, loc):
+ """Add an object to the scopes locals
+ @param loc: local object to add to locals
+
+ """
+ self._checkexisting(loc)
+ self.locals.append((self.NextObjId(), loc))
+
+ def _checkexisting(self, test):
+ """Convenience function... keep out duplicates
+ @param test: assignment statement to check for existence of
+ variable in the scopes locals
+
+ """
+ if '=' in test:
+ var = test.split('=')[0].strip()
+ for loc in self.locals:
+ if '=' in loc[1] and var == loc[1].split('=')[0].strip():
+ self.locals.remove(loc)
+
+ def get_code(self):
+ """Get a string of code that represents this scope
+ @return: string
+
+ """
+ cstr = '"""' + self.docstr + '"""\n'
+ nonimport = list()
+ for loc in self.locals:
+ if loc[1].startswith('import') or loc[1].startswith('from'):
+ cstr += ("try:\n %s\nexcept ImportError:\n pass\n" % loc[1])
+ else:
+ nonimport.append(loc)
+
+ # we need to start with this, to fix up broken completions
+ # hopefully this name is unique enough...
+ cstr += 'class _PyCmplNoType:\n def __getattr__(self,name):\n return None\n'
+
+ decls = self.subscopes + nonimport
+ decls.sort(key=lambda x: x[0])
+ for decl in [d[1] for d in decls]:
+ if isinstance(decl, Scope):
+ cstr += decl.get_code()
+ else:
+ cstr += decl + '\n'
+
+ return cstr
+
+ def pop(self, indent):
+ """Pop the scope until it is at the level of the given
+ indent.
+ @param indent: indent level to pop scope to
+ @return: scope of given indent level
+
+ """
+ outer = self
+ while outer.parent != None and outer.indent >= indent:
+ outer = outer.parent
+ return outer
+
+ def currentindent(self):
+ """Return string of current scopes indent level
+ @return: string of spaces
+
+ """
+ return ' ' * self.indent
+
+ def childindent(self):
+ """Return string the next scopes indentation level
+ @return: string of spaces
+
+ """
+ return ' ' * (self.indent + 1)
+
+class Class(Scope):
+ """Class for representing a python class object for the parser"""
+ def __init__(self, name, supers, indent):
+ """initialize the class object
+ @param name: name of class
+ @param supers: classes super classes
+ @param indent: scope of indentation
+
+ """
+ super(Class, self).__init__(name, indent)
+ self.supers = supers
+
+ def Clone(self, indent=0):
+ """Create a clone of this object"""
+ obj = Class(self.name, self.supers, indent)
+ obj.DocStr = self.DocStr
+ obj.Locals = list(self.Locals)
+ obj.Parent = self.Parent
+ obj.objid = self.objid
+ for scope in self.subscopes:
+ obj.subscopes.append((scope[0], scope[1].Clone(indent + 1)))
+ return obj
+
+ def get_code(self):
+ """Get the code string representation of the Class object
+ @return: string
+
+ """
+ cstr = '%sclass %s' % (self.currentindent(), self.name)
+ if len(self.supers) > 0:
+ cstr += '(%s)' % ','.join(self.supers)
+
+ cstr += ':\n'
+ if len(self.docstr) > 0:
+ cstr += self.childindent() + '"""' + self.docstr + '"""\n'
+ need_pass = True
+ decls = self.locals + self.subscopes
+ decls.sort(key=lambda x: x[0])
+ for decl in [d[1] for d in decls]:
+ need_pass = False
+ if isinstance(decl, Scope):
+ cstr += decl.get_code()
+ else:
+ cstr += ('%s%s\n' % (self.childindent(), decl))
+
+ if need_pass:
+ cstr += '%spass\n' % self.childindent()
+ return cstr
+
+ def local(self, loc):
+ """Add an object to the scopes locals
+ @param loc: local object to add to locals
+
+ """
+ if loc and '.' not in loc:
+ super(Class, self).local(loc)
+
+class Function(Scope):
+ """Create a function object for representing a python function
+ definition in the parser.
+
+ """
+ def __init__(self, name, params, indent):
+ """Create the function object
+ @param name: name of function
+ @param params: the functions parameters
+ @param indent: indentation level of functions declaration (scope)
+
+ """
+ super(Function, self).__init__(name, indent)
+ self.params = params
+
+ def Clone(self, indent=0):
+ """Create a copy of the functions declaration at the given
+ scope of indentation.
+ @keyword indent: indentation level of the declaration
+
+ """
+ obj = Function(self.name, self.params, indent)
+ obj.DocStr = self.DocStr
+ obj.Locals = list(self.Locals)
+ obj.Parent = self.Parent
+ for scope in self.subscopes:
+ obj.subscopes.append((scope[0], scope[1].Clone(indent + 1)))
+ obj.objid = self.objid
+ return obj
+
+ def get_code(self):
+ """Get code string representation of the function object
+ @return: string
+
+ """
+ cstr = "%sdef %s(%s):\n" % \
+ (self.currentindent(), self.name, ','.join(self.params))
+ if len(self.docstr) > 0:
+ cstr += self.childindent() + '"""' + self.docstr + '"""\n'
+ cstr += "%spass\n" % self.childindent()
+ return cstr
+
+#-----------------------------------------------------------------------------#
+# Main Parser
+
+class PyParser(object):
+ """Python parsing class"""
+ def __init__(self):
+ """Initialize and create the PyParser"""
+ super(PyParser, self).__init__()
+
+ # Attributes
+ self.top = Scope('global', 0)
+ self.scope = self.top
+ self.gen = None # Token Generator
+ self.curline = 0 # Current parse line
+ self.currentscope = None # Current scope in parse
+
+ def _parsedotname(self, pre=None):
+ """Parse a dotted name string
+ @return: tuple of (dottedname, nexttoken)
+
+ """
+ name = list()
+ if pre is None:
+ tokentype, token = self.next()[:2]
+ if token == '(':
+ self._parenparse()
+ if tokentype != NAME and token != '*':
+ return ('', token)
+ else:
+ token = pre
+
+ name.append(token)
+ while True:
+ tokentype, token = self.next()[:2]
+ if token == '(':
+ # Handle 'self.foo(a,b,c)'
+ self._parenparse()
+ break
+
+ if token != '.':
+ break
+
+ tokentype, token = self.next()[:2]
+ if tokentype != NAME:
+ break
+ name.append(token)
+ return (".".join(name), token)
+
+ def _parseimportlist(self):
+ """Parse and collect import statements
+ @return: list of imports
+
+ """
+ imports = []
+ while True:
+ name, token = self._parsedotname()
+ if not name:
+ break
+
+ name2 = ''
+ if token == 'as':
+ name2, token = self._parsedotname()
+
+ imports.append((name, name2))
+ while token != "," and "\n" not in token:
+ token = self.next()[1]
+
+ if token != ",":
+ break
+
+ return imports
+
+ def _parenparse(self):
+ """Parse paren enclosed statement
+ @return: list of named items enclosed in the parens
+
+ """
+ name = ''
+ names = []
+ level = 1
+ while True:
+ token = self.next()[1]
+ if token in (')', ',') and level == 1:
+ # Remove keyword assignments as they can
+ # cause eval breakage when using undefined
+ # vars.
+ if '=' in name:
+ name = name.split('=')[0].strip()
+ names.append(name)
+ name = ''
+
+ if token == '(':
+ level += 1
+ elif token == ')':
+ level -= 1
+ if level == 0:
+ break
+ elif token == ',' and level == 1:
+ pass
+ else:
+ name += str(token)
+
+ return names
+
+ def _parsefunction(self, indent):
+ """Parse a function definition at the given scope of
+ indentation and create a class token object from the
+ results.
+ @param indent: scope of functions declaration
+
+ """
+ self.scope = self.scope.pop(indent)
+ tokentype, fname, findent = self.next()
+ if tokentype != NAME:
+ return None
+
+ tokentype, open_paren, tindent = self.next()
+ if open_paren != '(':
+ return None
+
+ params = self._parenparse()
+ tokentype, colon, tindent = self.next()
+ if colon != ':':
+ return None
+
+ return Function(fname, params, indent)
+
+ def _parseclass(self, indent):
+ """Parse a class definition at the given scope of
+ indentation and create a class token object from the
+ results.
+ @param indent: scope of classes declaration
+
+ """
+ self.scope = self.scope.pop(indent)
+ tokentype, cname = self.next()[:-1]
+ if tokentype != NAME:
+ return None
+
+ super_cls = []
+ tokentype, next = self.next()[:-1]
+ if next == '(':
+ super_cls = self._parenparse()
+ elif next != ':':
+ return None
+
+ return Class(cname, super_cls, indent)
+
+ def _parseassignment(self):
+ """Parse a variable assignment to resolve the variables type
+ for introspection.
+ @return: string of objects type
+
+ """
+ assign = ''
+ tokentype, token = self.next()[:-1]
+ tokens = {
+ # Dict
+ '{' : '{}', 'dict' : '{}',
+ 'locals' : '{}', 'globals' : '{}',
+ # File
+ 'open' : 'file', 'file' : 'file',
+ # List
+ '[' : '[]', 'list' : '[]',
+ 'dir' : '["",""]', 'zip' : '[]', 'map' : '[]',
+ 'sorted' : '[]', 'range' : '[]',
+ # NoneType
+ 'None' : '_PyCmplNoType()',
+ # Number
+ tokenize.NUMBER : '0', 'ord' : '0', 'id' : '0',
+ 'abs' : '0', 'sum' : '0', 'pow' : '0', 'len' : '0',
+ 'hash' : '0',
+ # Property
+ 'property' : 'property()',
+ # String
+ tokenize.STRING : '""', 'str' : '""',
+ 'repr' : '""', 'chr' : '""', 'unichr' : '""',
+ 'hex' : '""', 'oct' : '""', "'" : '""', '"' : '""',
+ # Type
+ 'type' : 'type(_PyCmplNoType)',
+ # Tuple
+ '(' : '()', 'tuple' : '()', 'coerce' : '()'
+ }
+
+ if tokentype == tokenize.NUMBER or tokentype == tokenize.STRING:
+ return token #token = tokentype
+
+ if token in tokens:
+ return tokens[token]
+ else:
+ # NOTE: This part of the parse is where the problem is happening
+ assign += token
+ level = 0
+ while True:
+ tokentype, token = self.next()[:-1]
+ if token in ('(', '{', '['):
+ level = level + 1
+ elif token in (']', '}', ')'):
+ level = level - 1
+ if level == 0 or level == -1:
+ break
+ elif level == 0:
+ # end of line
+ if token in (';', '\n', '='):
+ break
+ elif token in ('+', '*'):
+ # Attempt simple type deduction based on
+ # operator statement.
+ if assign.endswith('"') or assign.endswith("'"):
+ assign = '""'
+ else:
+ assign = '0'
+ break
+ elif token in ('/', '-'):
+ # assignment most likely returns an digit type
+ # this is the best guess we can make
+ assign = '0'
+ break
+ elif token in ('and', 'or', 'in', '==',
+ '<', '>', '!=', 'not', '>=', '<='):
+ # right side of assignment likely evaluates to bool
+ assign = 'bool'
+ break
+# elif token == ',':
+# assign = ''
+ else:
+ if token == '.' or assign.endswith('.'):
+ assign += token
+ else:
+ assign += (" %s" % token)
+
+ # Check syntax to filter out bad tokens
+ try:
+ compile(assign, '_pycomp', 'eval')
+ except:
+ dbg("[pycomp][err] parseassignment bad token: %s" % assign)
+ return '_PyCmplNoType()'
+ else:
+ return assign
+
+ def next(self):
+ """Get tokens of next line in parse
+ @return: tuple of (type, token, indent)
+
+ """
+ ttype, token, (lineno, indent) = self.gen.next()[:3]
+ if lineno == self.curline:
+ self.currentscope = self.scope
+ return (ttype, token, indent)
+
+ def _adjustvisibility(self):
+ """Adjust the visibility of the current contexts scope
+ @return: current scope
+
+ """
+ newscope = Scope('result', 0)
+ scopes = list()
+ tscp = self.currentscope.parent
+ while tscp != None:
+ scopes.append(tscp)
+ tscp = tscp.parent
+ scopes.append(self.currentscope)
+
+ for scp in scopes:
+ if type(scp) == Function:
+ cut = 0
+ # Handle 'self' params
+ if scp.parent != None and type(scp.parent) == Class:
+ cut = 1
+ params = scp.params[0]
+ ind = params.find('=')
+ if ind != -1:
+ params = params[:ind]
+ newscope.local('%s = %s' % (_sanitizeParam(scp.params[0]), scp.parent.name))
+
+ for param in scp.params[cut:]:
+ ind = param.find('=')
+ if len(param) == 0:
+ continue
+ if ind == -1:
+ newscope.local('%s = _PyCmplNoType()' % _sanitizeParam(param))
+ else:
+ newscope.local('%s = %s' % (_sanitizeParam(param[:ind]),
+ _sanitize(param[ind+1:])))
+
+ decls = scp.subscopes + scp.locals
+ decls.sort(key=lambda x: x[0])
+ for decl in [d[1] for d in decls]:
+ if isinstance(decl, Scope):
+ newscope.add(decl.Clone(0))
+ else:
+ newscope.local(decl)
+
+ self.currentscope = newscope
+ return self.currentscope
+
+ def parse(self, text, curline=0):
+ """Parse the given text
+ @param text: python code text to parse
+ @keyword curline: current line of cursor for context
+
+ """
+ self.curline = curline
+ buf = StringIO(text)
+ self.gen = tokenize.generate_tokens(buf.readline)
+ self.currentscope = self.scope
+
+ try:
+ freshscope = True
+ while True:
+ tokentype, token, indent = self.next()
+ if tokentype == DEDENT or token == "pass":
+ self.scope = self.scope.pop(indent)
+ elif token == 'def':
+ func = self._parsefunction(indent)
+ if func == None:
+ continue
+ freshscope = True
+ self.scope = self.scope.add(func)
+ elif token == 'class':
+ cls = self._parseclass(indent)
+ if cls == None:
+ continue
+ freshscope = True
+ self.scope = self.scope.add(cls)
+
+ elif token == 'import':
+ imports = self._parseimportlist()
+ for mod, alias in imports:
+ loc = "import %s" % mod
+ if len(alias) > 0:
+ loc += " as %s" % alias
+ self.scope.local(loc)
+ freshscope = False
+ elif token == 'from':
+ mod, token = self._parsedotname()
+ if not mod or token != "import":
+ continue
+ names = self._parseimportlist()
+ for name, alias in names:
+ loc = "from %s import %s" % (mod, name)
+ if len(alias) > 0:
+ loc += " as %s" % alias
+ self.scope.local(loc)
+ freshscope = False
+
+ elif tokentype == STRING:
+ if freshscope:
+ self.scope.doc(token)
+ elif tokentype == NAME:
+ name, token = self._parsedotname(token)
+ if token == '=':
+ stmt = self._parseassignment()
+ dbg("[pycomp] parseassignment: %s = %s" % (name, stmt))
+ if stmt != None:
+ # XXX Safety Check don't allow assignments to
+ # item attributes unless the attribute is self
+ if u'.' not in name or name.startswith('self.'):
+ self.scope.local("%s = %s" % (name, stmt))
+ freshscope = False
+ except StopIteration: #thrown on EOF
+ pass
+ except:
+ dbg("[pycomp][err] Pyparser.parse: %s, %s" %
+ (sys.exc_info()[0], sys.exc_info()[1]))
+ return self._adjustvisibility()
+
+#-----------------------------------------------------------------------------#
+# Utility Functions
+def _cleanstr(doc):
+ """Clean up a docstring by removing quotes
+ @param doc: docstring to clean up
+
+ """
+ return doc.replace('"', ' ').replace("'", ' ')
+
+def _sanitize(cstr):
+ """Sanitize a command string for namespace lookup
+ @param cstr: command string to cleanup
+
+ """
+ val = ''
+ level = 0
+ for char in cstr:
+ if char in ('(', '{', '['):
+ level += 1
+ elif char in (']', '}', ')'):
+ level -= 1
+ elif level == 0:
+ val += char
+ return val
+
+def _sanitizeParam(param):
+ """Cleanup a value string
+ value = foo
+ to ensure that 'value' is syntactically correct.
+
+ """
+ for i, c in enumerate(param):
+ if c.isalpha() or c == '_':
+ return param[i:]
+ else:
+ return param # something is wrong so let it bomb
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/simplecomp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/simplecomp.py
new file mode 100644
index 0000000..c2e0bdd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/simplecomp.py
@@ -0,0 +1,120 @@
+###############################################################################
+# Name: simplecomp.py #
+# Purpose: Simple autocompletion based on buffer words (SciTE docet) #
+# Author: Giuseppe "Cowo" Corbelli #
+# Copyright: (c) 2009 Giuseppe "Cowo" Corbelli #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Simple Generic autocompleter for completing words found in the current buffer.
+
+"""
+
+__author__ = "Giuseppe \"Cowo\" Corbelli"
+__cvsid__ = "$Id: simplecomp.py 72222 2012-07-28 15:43:38Z CJP $"
+__revision__ = "$Revision: 72222 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import string
+import wx.stc as stc
+
+# Local Imports
+import completer
+
+#--------------------------------------------------------------------------#
+
+class Completer(completer.BaseCompleter):
+ """Generic word completer provider"""
+ wordCharacters = "".join(['_', string.letters])
+
+ def __init__(self, stc_buffer):
+ super(Completer, self).__init__(stc_buffer)
+
+ # Setup
+ self.SetAutoCompKeys([])
+ self.SetAutoCompStops(' \'"\\`):')
+ self.SetAutoCompFillups('.,:;([]){}<>%^&+-=*/|$@')
+ self.SetCallTipKeys([])
+ self.SetCallTipCancel([])
+ self.SetCaseSensitive(False)
+
+ def _GetCompletionInfo(self, command, calltip=False):
+ """Get Completion list or Calltip
+ @return: list or string
+
+ """
+ bf = self.GetBuffer()
+ # A list of Symbol(keyword, TYPE_UNKNOWN)
+ kwlst = map(
+ lambda kw: completer.Symbol(kw, completer.TYPE_UNKNOWN),
+ bf.GetKeywords()
+ )
+
+ if command in (None, u''):
+ return kwlst
+
+ fillups = self.GetAutoCompFillups()
+ if command[0].isdigit() or (command[-1] in fillups):
+ return list()
+
+ currentPos = bf.GetCurrentPos()
+
+ # Get the real word: segment using autocompFillup
+ tmp = command
+ for ch in fillups:
+ tmp = command.strip(ch)
+ ls = list(tmp)
+ ls.reverse()
+
+ idx = 0
+ for c in ls:
+ if c in fillups:
+ break
+ idx += 1
+ ls2 = ls[:idx]
+ ls2.reverse()
+ command = u"".join(ls2)
+
+ # Available completions so far
+ wordsNear = []
+ maxWordLength = 0
+ nWords = 0
+ minPos = 0
+ maxPos = bf.GetLength()
+ flags = stc.STC_FIND_WORDSTART
+ if self.GetCaseSensitive():
+ flags |= stc.STC_FIND_MATCHCASE
+
+ posFind = bf.FindText(minPos, maxPos, command, flags)
+ while posFind >= 0 and posFind < maxPos:
+ wordEnd = posFind + len(command)
+ if posFind != currentPos:
+ while -1 != Completer.wordCharacters.find(chr(bf.GetCharAt(wordEnd))):
+ wordEnd += 1
+
+ wordLength = wordEnd - posFind
+ if wordLength > len(command):
+ word = bf.GetTextRange(posFind, wordEnd)
+ sym = completer.Symbol(word, completer.TYPE_UNKNOWN)
+ if not wordsNear.count(sym):
+ wordsNear.append(sym)
+ maxWordLength = max(maxWordLength, wordLength)
+ nWords += 1
+
+ minPos = wordEnd
+ posFind = bf.FindText(minPos, maxPos, command, flags)
+
+ if len(wordsNear) > 0 and (maxWordLength > len(command)):
+ return wordsNear
+
+ return kwlst
+
+ def GetAutoCompList(self, command):
+ """Returns the list of possible completions for a command string.
+ @param command: command lookup is done on
+
+ """
+ rlist = self._GetCompletionInfo(command)
+ return sorted(list(set(rlist)))
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/dev_tool.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/dev_tool.py
new file mode 100644
index 0000000..c572d80
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/dev_tool.py
@@ -0,0 +1,343 @@
+###############################################################################
+# Name: dev_tool.py #
+# Purpose: Provides logging and error tracking utilities #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+""" Editra Development Tools
+Tools and Utilities for debugging and helping with development of Editra.
+@summary: Utility function for debugging the editor
+
+"""
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: dev_tool.py 72623 2012-10-06 19:33:06Z CJP $"
+__revision__ = "$Revision: 72623 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import os
+import sys
+import re
+import traceback
+import time
+import urllib2
+import webbrowser
+import codecs
+import locale
+import wx
+
+# Editra Libraries
+import ed_glob
+import ed_msg
+import eclib
+from ebmlib import IsUnicode, LogFile
+
+#-----------------------------------------------------------------------------#
+# Globals
+_ = wx.GetTranslation
+RE_LOG_LBL = re.compile(r"\[(.+?)\]")
+
+# The default fallback encoding
+DEFAULT_ENCODING = locale.getpreferredencoding()
+try:
+ codecs.lookup(DEFAULT_ENCODING)
+except (LookupError, TypeError):
+ DEFAULT_ENCODING = 'utf-8'
+
+PYTHONW = 'pythonw' in sys.executable.lower()
+
+#-----------------------------------------------------------------------------#
+# General Debugging Helper Functions
+def DEBUGP(statement, *args):
+ """Prints debug messages and broadcasts them on the log message channel.
+ Subscribing a listener with any of the EDMSG_LOG_* types will recieve its
+ messages from this method.
+
+ 1. Formatting
+ - [object/module name][msg_type] message string
+
+ 2. Message Type:
+ - [err] : Notes an exception or error condition (high priority)
+ - [warn] : Notes a error that is not severe (medium priority)
+ - [info] : General information message (normal priority)
+ - [evt] : Event related message (normal priority)
+
+ Example:
+ >>> DEBUGP("[ed_main][err] File failed to open")
+
+ @param statement: Should be a formatted string that starts with two
+ identifier blocks. The first is used to indicate the
+ source of the message and is used as the primary means
+ of filtering. The second block is the type of message,
+ this is used to indicate the priority of the message and
+ is used as the secondary means of filtering.
+
+ """
+ # Check if formatting should be done here
+ if len(args):
+ try:
+ statement = statement % args
+ except:
+ pass
+
+ # Create a LogMsg object from the statement string
+ lbls = [lbl.strip() for lbl in RE_LOG_LBL.findall(statement)]
+ info = RE_LOG_LBL.sub('', statement, 2).rstrip()
+ if len(lbls) > 1:
+ msg = LogMsg(info, lbls[0], lbls[1])
+ elif len(lbls) == 1:
+ msg = LogMsg(info, lbls[0])
+ else:
+ msg = LogMsg(info)
+
+ # Only print to stdout when DEBUG is active
+ # Cant print to stdio if using pythonw
+ msg_type = msg.Type
+ if ed_glob.DEBUG:
+ mstr = unicode(msg)
+ mstr = mstr.encode('utf-8', 'replace')
+ if not PYTHONW:
+ print(mstr)
+
+ # Write to log file
+ logfile = EdLogFile()
+ logfile.WriteMessage(mstr)
+
+ # Check for trapped exceptions to print
+ if ed_glob.VDEBUG and msg_type in ('err', 'error'):
+ traceback.print_exc()
+ logfile.WriteMessage(traceback.format_exc())
+
+ # Dispatch message to all observers
+ if msg_type in ('err', 'error'):
+ mtype = ed_msg.EDMSG_LOG_ERROR
+ if ed_glob.VDEBUG:
+ msg = LogMsg(msg.Value + os.linesep + traceback.format_exc(),
+ msg.Origin, msg.Type)
+ elif msg_type in ('warn', 'warning'):
+ mtype = ed_msg.EDMSG_LOG_WARN
+ elif msg_type in ('evt', 'event'):
+ mtype = ed_msg.EDMSG_LOG_EVENT
+ elif msg.Type in ('info', 'information'):
+ mtype = ed_msg.EDMSG_LOG_INFO
+ else:
+ mtype = ed_msg.EDMSG_LOG_ALL
+
+ ed_msg.PostMessage(mtype, msg)
+
+#-----------------------------------------------------------------------------#
+
+class LogMsg(object):
+ """LogMsg is a container class for representing log messages. Converting
+ it to a string will yield a formatted log message with timestamp. Once a
+ message has been displayed once (converted to a string) it is marked as
+ being expired.
+
+ """
+ def __init__(self, msg, msrc=u"unknown", level=u"info"):
+ """Create a LogMsg object
+ @param msg: the log message string
+ @keyword msrc: Source of message
+ @keyword level: Priority of the message
+
+ """
+ assert isinstance(msg, basestring)
+ assert isinstance(msrc, basestring)
+ assert isinstance(level, basestring)
+ super(LogMsg, self).__init__()
+
+ # Attributes
+ self._msg = dict(mstr=DecodeString(msg),
+ msrc=DecodeString(msrc),
+ lvl=DecodeString(level),
+ tstamp=time.time())
+ self._ok = True
+
+ def __eq__(self, other):
+ """Define the equal to operation"""
+ return self.TimeStamp == other.TimeStamp
+
+ def __ge__(self, other):
+ """Define the greater than or equal to operation"""
+ return self.TimeStamp >= other.TimeStamp
+
+ def __gt__(self, other):
+ """Define the greater than operation"""
+ return self.TimeStamp > other.TimeStamp
+
+ def __le__(self, other):
+ """Define the less than or equal to operation"""
+ return self.TimeStamp <= other.TimeStamp
+
+ def __lt__(self, other):
+ """Define the less than operation"""
+ return self.TimeStamp < other.TimeStamp
+
+ def __repr__(self):
+ """String representation of the object"""
+ return '<LogMsg %s:%d>' % (self._msg['lvl'], self._msg['tstamp'])
+
+ def __str__(self):
+ """Returns a nice formatted string version of the message"""
+ s_lst = [u"[%s][%s][%s]%s" % (self.ClockTime, self.Origin,
+ self.Type, msg.rstrip())
+ for msg in self.Value.split(u"\n")
+ if len(msg.strip())]
+ try:
+ sys_enc = sys.getfilesystemencoding()
+ out = os.linesep.join([val.encode(sys_enc, 'replace')
+ for val in s_lst])
+ except UnicodeEncodeError:
+ out = repr(self)
+
+ # Mark Message as have being fetched (expired)
+ self._ok = False
+
+ return out
+
+ def __unicode__(self):
+ """Convert to unicode"""
+ rval = u""
+ try:
+ sval = str(self)
+ rval = sval.decode(sys.getfilesystemencoding(), 'replace')
+ except UnicodeDecodeError, msg:
+ pass
+ return rval
+
+ @property
+ def ClockTime(self):
+ """Formatted timestring of the messages timestamp"""
+ ltime = time.localtime(self._msg['tstamp'])
+ tstamp = u"%s:%s:%s" % (str(ltime[3]).zfill(2),
+ str(ltime[4]).zfill(2),
+ str(ltime[5]).zfill(2))
+ return tstamp
+
+ @property
+ def Expired(self):
+ """Has this message already been retrieved"""
+ return not self._ok
+
+ @property
+ def Origin(self):
+ """Where the message came from"""
+ return self._msg['msrc']
+
+ @property
+ def TimeStamp(self):
+ """Property for accessing timestamp"""
+ return self._msg['tstamp']
+
+ @property
+ def Type(self):
+ """The messages level type"""
+ return self._msg['lvl']
+
+ @property
+ def Value(self):
+ """Returns the message part of the log string"""
+ return self._msg['mstr']
+
+#-----------------------------------------------------------------------------#
+
+class EdLogFile(LogFile):
+ """Transient log file object"""
+ def __init__(self):
+ super(EdLogFile, self).__init__("editra")
+
+ def PurgeOldLogs(self, days):
+ try:
+ super(EdLogFile, self).PurgeOldLogs(days)
+ except OSError, msg:
+ DEBUGP("[dev_tool][err] PurgeOldLogs: %s" % msg)
+
+#-----------------------------------------------------------------------------#
+
+def DecodeString(string, encoding=None):
+ """Decode the given string to Unicode using the provided
+ encoding or the DEFAULT_ENCODING if None is provided.
+ @param string: string to decode
+ @keyword encoding: encoding to decode string with
+
+ """
+ if encoding is None:
+ encoding = DEFAULT_ENCODING
+
+ if not IsUnicode(string):
+ try:
+ rtxt = codecs.getdecoder(encoding)(string)[0]
+ except Exception, msg:
+ rtxt = string
+ return rtxt
+ else:
+ # The string is already Unicode so just return it
+ return string
+
+#-----------------------------------------------------------------------------#
+
+class EdErrorDialog(eclib.ErrorDialog):
+ """Error reporter dialog"""
+ def __init__(self, msg):
+ super(EdErrorDialog, self).__init__(None, title="Error Report",
+ message=msg)
+
+ # Setup
+ self.SetDescriptionLabel(_("Error: Something unexpected hapend\n"
+ "Help improve Editra by clicking on "
+ "Report Error\nto send the Error "
+ "Traceback shown below."))
+
+ def Abort(self):
+ """Abort the application"""
+ # Try a nice shutdown first time through
+ wx.CallLater(500, wx.GetApp().OnExit,
+ wx.MenuEvent(wx.wxEVT_MENU_OPEN, ed_glob.ID_EXIT),
+ True)
+
+ def GetProgramName(self):
+ """Get the program name to display in error report"""
+ return "%s Version: %s" % (ed_glob.PROG_NAME, ed_glob.VERSION)
+
+ def Send(self):
+ """Send the error report"""
+ msg = "mailto:%s?subject=Error Report&body=%s"
+ addr = "bugs@%s" % (ed_glob.HOME_PAGE.replace("http://", '', 1))
+ if wx.Platform != '__WXMAC__':
+ body = urllib2.quote(self.err_msg)
+ else:
+ body = self.err_msg
+ msg = msg % (addr, body)
+ msg = msg.replace("'", '')
+ webbrowser.open(msg)
+
+#-----------------------------------------------------------------------------#
+
+def ExceptionHook(exctype, value, trace):
+ """Handler for all unhandled exceptions
+ @param exctype: Exception Type
+ @param value: Error Value
+ @param trace: Trace back info
+
+ """
+ # Format the traceback
+ exc = traceback.format_exception(exctype, value, trace)
+ exc.insert(0, u"*** %s ***%s" % (eclib.TimeStamp(), os.linesep))
+ ftrace = u"".join(exc)
+
+ # Ensure that error gets raised to console as well
+ print ftrace
+
+ # If abort has been set and we get here again do a more forcefull shutdown
+ if EdErrorDialog.ABORT:
+ os._exit(1)
+
+ # Prevent multiple reporter dialogs from opening at once
+ if not EdErrorDialog.REPORTER_ACTIVE and not EdErrorDialog.ABORT:
+ dlg = EdErrorDialog(ftrace)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+#-----------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/doctools.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/doctools.py
new file mode 100644
index 0000000..ae08f5a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/doctools.py
@@ -0,0 +1,244 @@
+###############################################################################
+# Name: doctools.py #
+# Purpose: Tools for managing document services #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides helper functions and classes for managing documents and their services.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: doctools.py 70230 2012-01-01 01:47:42Z CJP $"
+__revision__ = "$Revision: 70230 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import sys
+
+# Editra Libraries
+import util
+from profiler import Profile_Get
+import ebmlib
+
+#--------------------------------------------------------------------------#
+
+class DocPositionMgr(object):
+ """Object for managing the saving and setting of a collection of
+ documents positions between sessions. Through the use of an in memory
+ dictionary during run time and on disk dictionary to use when starting
+ and stopping the editor.
+ @note: saves config to ~/.Editra/cache/
+
+ """
+ _poscache = ebmlib.HistoryCache(100)
+
+ def __init__(self):
+ """Creates the position manager object"""
+ super(DocPositionMgr, self).__init__()
+
+ # Attributes
+ self._init = False
+ self._book = None
+ self._records = dict()
+
+ def InitPositionCache(self, book_path):
+ """Initialize and load the on disk document position cache.
+ @param book_path: path to on disk cache
+
+ """
+ self._init = True
+ self._book = book_path
+ if Profile_Get('SAVE_POS'):
+ self.LoadBook(book_path)
+
+ @classmethod
+ def AddNaviPosition(cls, fname, pos):
+ """Add a new position to the navigation cache
+ @param fname: file name
+ @param pos: position
+
+ """
+ # Don't put two identical positions in the cache next to each other
+ pre = cls._poscache.PeekPrevious()
+ next = cls._poscache.PeekNext()
+ if (fname, pos) in (pre, next):
+ return
+
+ cls._poscache.PutItem((fname, pos))
+
+ def AddRecord(self, vals):
+ """Adds a record to the dictionary from a list of the
+ filename vals[0] and the position value vals[1].
+ @param vals: (file path, cursor position)
+
+ """
+ if len(vals) == 2:
+ self._records[vals[0]] = vals[1]
+ return True
+ else:
+ return False
+
+ @classmethod
+ def CanNavigateNext(cls):
+ """Are there more cached navigation positions?
+ @param cls: Class
+ @return: bool
+
+ """
+ return cls._poscache.HasNext()
+
+ @classmethod
+ def CanNavigatePrev(cls):
+ """Are there previous cached navigation positions?
+ @param cls: Class
+ @return: bool
+
+ """
+ return cls._poscache.HasPrevious()
+
+ @classmethod
+ def FlushNaviCache(cls):
+ """Clear the navigation cache"""
+ cls._poscache.Clear()
+
+ @classmethod
+ def GetNaviCacheSize(cls):
+ return cls._poscache.GetSize()
+
+ def GetBook(self):
+ """Returns the current book used by this object
+ @return: path to book used by this manager
+
+ """
+ return self._book
+
+ @classmethod
+ def GetNextNaviPos(cls, fname=None):
+ """Get the next stored navigation position
+ The optional fname parameter will get the next found position for
+ the given file.
+ @param cls: Class
+ @param fname: filename (note currently not supported)
+ @return: int or None
+ @note: fname is currently not used
+
+ """
+ item = cls._poscache.GetNextItem()
+ return item
+
+ @classmethod
+ def GetPreviousNaviPos(cls, fname=None):
+ """Get the last stored navigation position
+ The optional fname parameter will get the last found position for
+ the given file.
+ @param cls: Class
+ @param fname: filename (note currently not supported)
+ @return: int or None
+ @note: fname is currently not used
+
+ """
+ item = cls._poscache.GetPreviousItem()
+ return item
+
+ def GetPos(self, name):
+ """Get the position record for a given filename
+ returns 0 if record is not found.
+ @param name: file name
+ @return: position value for the given filename
+
+ """
+ return self._records.get(name, 0)
+
+ def IsInitialized(self):
+ """Has the cache been initialized
+ @return: bool
+
+ """
+ return self._init
+
+ def LoadBook(self, book):
+ """Loads a set of records from an on disk dictionary
+ the entries are formated as key=value with one entry
+ per line in the file.
+ @param book: path to saved file
+ @return: whether book was loaded or not
+
+ """
+ # If file does not exist create it and return
+ if not os.path.exists(book):
+ try:
+ tfile = util.GetFileWriter(book)
+ tfile.close()
+ except (IOError, OSError):
+ util.Log("[docpositionmgr][err] failed to load book: %s" % book)
+ return False
+ except AttributeError:
+ util.Log("[docpositionmgr][err] Failed to create: %s" % book)
+ return False
+
+ reader = util.GetFileReader(book, sys.getfilesystemencoding())
+ if reader != -1:
+ lines = list()
+ try:
+ lines = reader.readlines()
+ except:
+ reader.close()
+ return False
+ else:
+ reader.close()
+
+ for line in lines:
+ line = line.strip()
+ vals = line.rsplit(u'=', 1)
+ if len(vals) != 2 or not os.path.exists(vals[0]):
+ continue
+
+ try:
+ vals[1] = int(vals[1])
+ except (TypeError, ValueError), msg:
+ util.Log("[docpositionmgr][err] %s" % str(msg))
+ continue
+ else:
+ self._records[vals[0]] = vals[1]
+
+ util.Log("[docpositionmgr][info] successfully loaded book")
+ return True
+
+ @classmethod
+ def PeekNavi(cls, pre=False):
+ """Peek into the navigation cache
+ @param cls: Class
+ @keyword pre: bool
+
+ """
+ if pre:
+ if cls._poscache.HasPrevious():
+ return cls._poscache.PeekPrevious()
+ else:
+ if cls._poscache.HasNext():
+ return cls._poscache.PeekNext()
+ return None, None
+
+ def WriteBook(self):
+ """Writes the collection of files=pos to the config file
+ @postcondition: in memory doc data is written out to disk
+
+ """
+ writer = util.GetFileWriter(self.GetBook(), sys.getfilesystemencoding())
+ if writer != -1:
+ try:
+ for key, val in self._records.iteritems():
+ try:
+ writer.write(u"%s=%d\n" % (key, val))
+ except UnicodeDecodeError:
+ continue
+ writer.close()
+ except IOError, msg:
+ util.Log("[docpositionmgr][err] %s" % str(msg))
+ else:
+ util.Log("[docpositionmgr][err] Failed to open %s" % self.GetBook())
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/__init__.py
new file mode 100644
index 0000000..4b64463
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/__init__.py
@@ -0,0 +1,46 @@
+###############################################################################
+# Name: __init__.py #
+# Purpose: Editra Business Model Library #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library:
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: __init__.py 69798 2011-11-23 02:59:40Z CJP $"
+__revision__ = "$Revision: 69798 $"
+
+#-----------------------------------------------------------------------------#
+
+# Text Utils
+from searcheng import *
+from fchecker import *
+from fileutil import *
+from _dirmon import *
+from fileimpl import *
+from txtutil import *
+from logfile import *
+
+from backupmgr import *
+from calllock import *
+
+# Storage Classes
+from histcache import *
+from clipboard import *
+
+# Networking utilities
+from e_weblib import *
+
+# Misc
+from miscutil import *
+from _efactory import *
+from cmenumgr import *
+from efilehist import *
+from osutil import *
+from _threads import *
+from _trash import *
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_dirmon.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_dirmon.py
new file mode 100644
index 0000000..f5b3bb9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_dirmon.py
@@ -0,0 +1,331 @@
+###############################################################################
+# Name: _dirmon.py #
+# Purpose: Directory monitor object. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: DirectoryMonitor
+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: _dirmon.py 73166 2012-12-12 04:31:53Z CJP $"
+__revision__ = "$Revision: 73166 $"
+
+__all__ = ['DirectoryMonitor',]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import os
+import time
+import threading
+
+# Local imports
+import fileutil
+
+#-----------------------------------------------------------------------------#
+
+class DirectoryMonitor(object):
+ """Object to manage monitoring file system changes"""
+ def __init__(self, checkFreq=1000.0):
+ """@keyword checkFreq: check frequency in milliseconds"""
+ super(DirectoryMonitor, self).__init__()
+
+ # Attributes
+ self._watcher = WatcherThread(self._ThreadNotifier, checkFreq=checkFreq)
+ self._callbacks = list()
+ self._cbackLock = threading.Lock()
+ self._running = False
+
+ def __del__(self):
+ if self._running:
+ self._watcher.Shutdown()
+ self._watcher.join()
+
+ def _ThreadNotifier(self, added, deleted, modified):
+ """Notifier callback from background L{WatcherThread}
+ to call notifiers on main thread.
+ @note: this method is invoked from a background thread and
+ is not safe to make direct UI calls from.
+
+ """
+ with self._cbackLock:
+ for cback in self._callbacks:
+ wx.CallAfter(cback, added, deleted, modified)
+
+ #---- Properties ----#
+
+ # Is the monitor currently watching any directories
+ Monitoring = property(lambda self: self._running)
+ Frequency = property(lambda self: self._watcher.GetFrequency(),
+ lambda self, freq: self._watcher.SetFrequency(freq))
+
+ #---- End Properties ----#
+
+ def AddDirectory(self, dname):
+ """Add a directory to the monitor
+ @param dname: directory path
+ @return: bool - True if added, False if failed to add
+
+ """
+ return self._watcher.AddWatchDirectory(dname)
+
+ def SubscribeCallback(self, callback):
+ """Subscribe a callback method to be called when changes are
+ detected in one of the watched directories.
+ @param callback: callable([added,], [deleted,], [modified,])
+
+ """
+ with self._cbackLock:
+ if callback not in self._callbacks:
+ self._callbacks.append(callback)
+
+ def UnsubscribeCallback(self, callback):
+ """Remove a callback method from the monitor"""
+ with self._cbackLock:
+ if callback in self._callbacks:
+ self._callbacks.remove(callback)
+
+ def RemoveDirectory(self, dname):
+ """Remove a directory from the watch list
+ @param dname: directory path
+
+ """
+ self._watcher.RemoveWatchDirectory(dname)
+
+ def StartMonitoring(self):
+ """Start monitoring the directories in the watch list and
+ notifying target of changes.
+
+ """
+ self._running = True
+ self._watcher.start()
+
+ def Suspend(self, pause=True):
+ """Suspend background processing
+ @keyword pause: True (suspend) False (resume)
+
+ """
+ if pause:
+ self._watcher.Suspend()
+ else:
+ self._watcher.Continue()
+
+ def Refresh(self, paths=None):
+ """Force a recheck of the monitored directories. This method
+ is useful for doing manual control of the refresh cycle. It is
+ ignored and does nothing when WatcherThread is set up for automatic
+ refresh cycles.
+ @keyword paths: specific paths to refresh or None for all.
+
+ """
+ self._watcher.Refresh(paths)
+
+#-----------------------------------------------------------------------------#
+
+class WatcherThread(threading.Thread):
+ """Background thread to monitor a directory"""
+ def __init__(self, notifier, checkFreq=1000.0):
+ """Create the WatcherThread. Provide a callback notifier method
+ that will be called when changes are detected in the directory.
+ The notifier will be called in the context of this thread. Notifier
+ will be called with three lists of ebmlib.File objects to indicate
+ the changes that have occurred.
+ @param notifier: callable([added,], [deleted,], [modified,])
+ @keyword checkFreq: check frequency in milliseconds. If value is set
+ to zero or less update checks must be manually
+ controlled via the Refresh interface.
+
+ """
+ super(WatcherThread, self).__init__()
+
+ # Attributes
+ assert callable(notifier)
+ self._notifier = notifier
+ self._dirs = list() # Directories being monitored
+ self._refreshDirs = None
+
+ self._freq = checkFreq # Monitoring frequency in milliseconds
+ self._continue = True
+ self._changePending = False
+ self._lock = threading.Lock()
+ self._suspend = False
+ self._suspendcond = threading.Condition()
+ self._listEmptyCond = threading.Condition()
+ self._refreshCond = threading.Condition()
+
+ def run(self):
+ """Run the watcher"""
+ while self._continue:
+ deleted = list()
+ added = list()
+ modified = list()
+
+ # Watch is empty so wait on things to monitor before continuing
+ if not self._dirs:
+ with self._listEmptyCond:
+ self._listEmptyCond.wait()
+
+ # Suspend processing if requested
+ if self._suspend:
+ with self._suspendcond:
+ self._suspendcond.wait()
+
+ with self._lock:
+ for dobj in self._PendingRefresh:
+ if not self._continue:
+ return
+ elif self._changePending:
+ break
+
+ # Check if a watched directory has been deleted
+ if not os.path.exists(dobj.Path):
+ deleted.append(dobj)
+ self._dirs.remove(dobj)
+ continue
+
+ snapshot = fileutil.GetDirectoryObject(dobj.Path,
+ False, True)
+
+ # Check for deletions
+ dobjFiles = dobj.Files # optimization
+ dobjIndex = dobjFiles.index # optimization
+ snapFiles = snapshot.Files # optimization
+ for tobj in dobjFiles:
+ if not self._continue:
+ return
+ elif self._changePending:
+ break
+ if tobj not in snapFiles:
+ deleted.append(tobj)
+ dobjFiles.remove(tobj)
+
+ # Check for additions and modifications
+ for tobj in snapFiles:
+ if not self._continue:
+ return
+ elif self._changePending:
+ break
+ if tobj not in dobjFiles:
+ # new object was added
+ added.append(tobj)
+ dobjFiles.append(tobj)
+ else:
+ idx = dobjIndex(tobj)
+ existing = dobjFiles[idx]
+ # object was modified
+ if existing.ModTime < tobj.ModTime:
+ modified.append(tobj)
+ existing.ModTime = tobj.ModTime
+
+ # Call Notifier if anything changed
+ if any((added, deleted, modified)):
+ self._notifier(added, deleted, modified)
+
+ # Wait till next check
+ if self._freq > 0:
+ # Automatic updates
+ time.sleep(self._freq / 1000.0)
+ else:
+ # Manually controlled updates
+ with self._refreshCond:
+ self._refreshDirs = None
+ self._refreshCond.wait()
+
+ #---- Implementation ----#
+
+ @property
+ def _PendingRefresh(self):
+ """Get the list of directories pending refresh"""
+ if self._refreshDirs is None:
+ return self._dirs
+ else:
+ return self._refreshDirs
+
+ def AddWatchDirectory(self, dpath):
+ """Add a directory to the watch list
+ @param dpath: directory path (unicode)
+ @return: bool - True means watch was added, False means unable to list directory
+
+ """
+ assert os.path.isdir(dpath)
+ dobj = fileutil.Directory(dpath)
+ self._changePending = True
+ with self._lock:
+ if dobj not in self._dirs and os.access(dobj.Path, os.R_OK):
+ # Get current snapshot of the directory
+ try:
+ dobj = fileutil.GetDirectoryObject(dpath, False, True)
+ except OSError:
+ self._changePending = False
+ return False
+ self._dirs.append(dobj)
+ with self._listEmptyCond:
+ self._listEmptyCond.notify()
+ self._changePending = False
+ return True
+
+ def RemoveWatchDirectory(self, dpath):
+ """Remove a directory from the watch
+ @param dpath: directory path to remove (unicode)
+
+ """
+ dobj = fileutil.Directory(dpath)
+ self._changePending = True
+ with self._lock:
+ if dobj in self._dirs:
+ self._dirs.remove(dobj)
+ # Also remove any subpaths of dpath
+ toremove = list()
+ for d in self._dirs:
+ if fileutil.IsSubPath(d.Path, dpath):
+ toremove.append(d)
+ for todel in toremove:
+ self._dirs.remove(todel)
+ self._changePending = False
+
+ def GetFrequency(self):
+ """Get the update frequency
+ @return: int (milliseconds)
+
+ """
+ return self._freq
+
+ def SetFrequency(self, milli):
+ """Set the update frequency
+ @param milli: int (milliseconds)
+
+ """
+ self._freq = float(milli)
+
+ def Refresh(self, paths=None):
+ """Recheck the monitored directories
+ only useful when manually controlling refresh cycle of the monitor.
+ @keyword paths: if None refresh all, else list of specific directories
+
+ """
+ with self._refreshCond:
+ if paths is not None:
+ self._refreshDirs = list()
+ for dobj in paths:
+ self._refreshDirs.append(dobj)
+ self._refreshCond.notify()
+
+ def Shutdown(self):
+ """Shut the thread down"""
+ self._continue = False
+
+ def Suspend(self):
+ """Suspend the thread"""
+ self._suspend = True
+
+ def Continue(self):
+ """Continue the thread"""
+ self._suspend = False
+ with self._suspendcond:
+ self._suspendcond.notify()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_efactory.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_efactory.py
new file mode 100644
index 0000000..ff5b880
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_efactory.py
@@ -0,0 +1,124 @@
+###############################################################################
+# Name: _efactory.py #
+# Purpose: Generic Factory Pattern implementation. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: Factory
+
+Provides base functionality for implementing class factories.
+
+class FactoryMixin:
+
+class Meta:
+ - Don't use directly is used by classes that use the MetaData metaclass
+
+class MetaData:
+ - Meta data class - allows classes to be created with nested meta data
+ dynamically.
+ Example:
+ class FooBar(object):
+ __metaclass__ = MetaData
+ class MyFoo(FooBar):
+ class meta:
+ name = 'MyFoo'
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: _efactory.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+__all__ = [ 'FactoryMixin', 'MetaData' ]
+
+#-----------------------------------------------------------------------------#
+# imports
+import copy
+
+#-----------------------------------------------------------------------------#
+
+class Meta:
+ """Metadata namespace, acts as a container object for meta attributes
+ for classes using the FactoryMeta metaclass.
+ @see: FactoryMeta
+
+ """
+ def __init__(self, cls, meta_attrs):
+ assert hasattr(cls, 'GetMetaDefaults')
+ for (attr,default) in cls.GetMetaDefaults().items():
+ attr_val = meta_attrs.get(attr, default)
+ setattr(self, attr, copy.copy(attr_val))
+
+class MetaData(type):
+ """Metaclass for applying meta data to a class"""
+ def __new__(mcls,name,bases,attrs):
+ cls = super(MetaData,mcls).__new__(mcls,name,bases,attrs)
+ meta_attrs = { 'id' : None }
+ if hasattr(cls, 'meta'):
+ for attr in dir(cls.meta):
+ if not attr.startswith("_"):
+ meta_attrs[attr] = getattr(cls.meta,attr)
+ cls.meta = Meta(cls, meta_attrs)
+ return cls
+
+class FactoryMixin:
+ """Factory implementation.
+ All classes derived from classes using this mixin should declare a nested
+ subclass 'meta' that has at least one member 'id' that is used to identify
+ and instantiate the class in the factory.
+
+ Example:
+ class Foo(MyFactoryClass):
+ class meta:
+ id = 'foo'
+
+ Any arbitrary identifier may be specified. Additional meta data attributes
+ can be specified as well to suit the needs of the implementation. When
+ adding additional meta data to a class it is necessary that the base class
+ overrides the GetMetaDefaults method to return the appropriate default
+ values for each supported meta field.
+
+ Example:
+ class meta:
+ id = 'foo'
+ size = 100
+
+ In order to properly support the size meta field the factory base class must
+ override GetMetaDefaults and return a dictionary object as follows.
+
+ Example:
+ \@classmethod
+ def GetMetaDefaults(cls):
+ return dict(id=None, size=0)
+
+ """
+ __metaclass__ = MetaData
+ @classmethod
+ def FactoryCreate(cls, identifier, *args, **kwargs):
+ """Create an object of the appropriate type
+ @param identifier: id value (see meta)
+ @param args: Arguments to pass to object constructor
+ @param kwargs: Keyword arguments to pass to object constructor
+ @return: Subclass instance of cls or None if no appropriate constructor
+ is found in the factory.
+
+ """
+ obj = None
+ for scls in cls.__subclasses__():
+ if scls.meta.id == identifier:
+ obj = scls(*args, **kwargs)
+ break
+ else:
+ obj = cls(*args, **kwargs) # Return base class
+ return obj
+
+ @classmethod
+ def GetMetaDefaults(cls):
+ """Get all default meta values for this classes meta data.
+ @return: dict(string=value,...)
+
+ """
+ return dict()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_threads.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_threads.py
new file mode 100644
index 0000000..41609a9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_threads.py
@@ -0,0 +1,110 @@
+###############################################################################
+# Name: _threads.py #
+# Purpose: Threadpool implementation #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: ThreadPool
+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _threads.py 67422 2011-04-09 17:23:27Z CJP $"
+__revision__ = "$Revision: 67422 $"
+
+__all__ = [ 'ThreadPool', ]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import threading
+import Queue
+
+#-----------------------------------------------------------------------------#
+
+class ThreadPool(object):
+ """Object for managing a collection of threads and dispatching jobs
+ to them.
+
+ """
+ def __init__(self, tcount, qsize=-1):
+ """Create the ThreadPool
+ @param tcount: max number of threads to keep in the pool
+ @keyword qsize: size of job queue (-1 for unlimited)
+
+ """
+ super(ThreadPool, self).__init__()
+
+ # Attributes
+ self._poolsize = tcount
+ self._jobs = Queue.Queue(qsize)
+ self._threads = [ _WorkerThread(self._jobs) for t in range(self._poolsize) ]
+
+ ThreadCount = property(lambda self: self._poolsize)
+ JobCount = property(lambda self: self._jobs.qsize())
+
+ def QueueJob(self, funct, *args, **kwargs):
+ """Add a job to be processed
+ @param funct: callable
+ @param args: list of any positional arguments to funct
+ @param kwargs: map of any keyword arguments to funct
+
+ """
+ assert callable(funct)
+ self._jobs.put((funct, args, kwargs))
+
+ def Shutdown(self):
+ """Shutdown the ThreadPool
+ @note: Blocking call until all threads have exited
+
+ """
+ self._jobs.join()
+
+#-----------------------------------------------------------------------------#
+
+class _WorkerThread(threading.Thread):
+ """Worker thread class to be used by the ThreadPool"""
+ def __init__(self, jobs):
+ """Create the Thread object
+ @param jobs: Queue object
+
+ """
+ super(_WorkerThread, self).__init__()
+
+ # Attributes
+ self._jobs = jobs
+ self.daemon = True
+ self.start()
+
+ def run(self):
+ """Run and process jobs until requested to exit"""
+ while True:
+ funct, args, kwargs = self._jobs.get()
+ try:
+ funct(*args, **kwargs)
+ except Exception, msg:
+ pass # TODO add error to result data?
+ finally:
+ self._jobs.task_done()
+
+#-----------------------------------------------------------------------------#
+# Unittest
+if __name__ == '__main__':
+ pool = ThreadPool(5)
+ import time
+ import random
+ def Job(id_, length):
+ print "JOB: %d, begin" % id_
+ time.sleep(length)
+ print "JOB: %d, end" % id_
+
+ print "Start Jobs"
+ for x in range(8):
+ pool.QueueJob(Job, x, random.randint(1, 20))
+ print "All Jobs Queued"
+
+ pool.Shutdown() # blocks till pool is shutdown
+ print "All Done!"
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_trash.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_trash.py
new file mode 100644
index 0000000..e8e68b3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_trash.py
@@ -0,0 +1,205 @@
+#!/usr/bin/env python2
+###############################################################################
+# Name: _trash.py #
+# Purpose: Multiplatform recycle/trash implementation #
+# Author: Kevin D. Smith <Kevin.Smith@sixquickrun.com> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Platform independent Recycle Bin / Trash implementation
+
+The moveToTrash function in this module takes a path or list of
+paths and moves them to the Recycle Bin / Trash directory depending
+on the platform. For UNIX platforms, the FreeDesktop specification
+of Trash <http://www.ramendik.ru/docs/trashspec.html> is implemented.
+
+Any errors while moving files results in some form of TrashException.
+
+"""
+
+__author__ = "Kevin D. Smith <Kevin.Smith@sixquickrun.com>"
+__revision__ = "$Revision: 58361 $"
+__scid__ = "$Id: Trash.py 58361 2009-01-24 19:43:27Z CJP $"
+
+__all__ = ['MoveToTrash']
+
+#-----------------------------------------------------------------------------#
+# Imports
+import os
+import time
+import platform
+import shutil
+import stat
+
+OSX = WIN = False
+
+# Determine platform, if it's not one of these assume UNIX/Linux
+if platform.system().lower() in ['windows', 'microsoft']:
+ WIN = True
+ # Install recycle.exe binary
+ import _winrecycle
+ env = os.environ
+ recycleexe = os.path.join(env.get('TEMP', env.get('TMP', env.get('windir','.'))),'recycle.exe')
+ exe = open(recycleexe,'wb')
+ exe.write(_winrecycle.recycle)
+ exe.close()
+ del exe
+ del _winrecycle
+elif platform.mac_ver()[0]:
+ OSX = True
+
+#-----------------------------------------------------------------------------#
+
+class TrashError(Exception):
+ pass
+
+class TrashDirectoryError(TrashError):
+ pass
+
+class TrashMoveError(TrashError):
+ pass
+
+class TrashPermissionsError(TrashMoveError):
+ pass
+
+def MoveToTrash(paths):
+ """
+ Move the given paths to the trash can
+
+ Required Arguments:
+ paths -- path or list of paths to move to the trash can
+
+ """
+ # Make sure that we are always dealing with a list
+ if isinstance(paths, basestring):
+ paths = [paths]
+
+ # Get absolute paths and make sure files exist
+ paths = [os.path.abspath(x) for x in paths
+ if os.path.exists(os.path.abspath(x))]
+
+ # Run the correct trash function
+ if OSX:
+ return _osxTrash(paths)
+ elif WIN:
+ return _winTrash(paths)
+ else:
+ return _unixTrash(paths)
+
+def _ensurePermissions(path):
+ """ Make sure we have permissions to read and delete path """
+ if not os.access(path, os.R_OK|os.W_OK):
+ try: os.chmod(path, stat.S_IWRITE|stat.S_IREAD)
+ except (IOError, OSError): pass
+ if not os.access(path, os.R_OK):
+ raise TrashPermissionsError, ('You do not have permissions to read this path', path)
+ if not os.access(path, os.W_OK):
+ raise TrashPermissionsError, ('You do not have permissions to remove this path', path)
+
+def _winTrash(paths):
+ """ Move to windows recycle bin if possible """
+ for path in paths:
+ # See if we can even do this
+ _ensurePermissions(path)
+ try:
+ rc = os.spawnv(os.P_WAIT, recycleexe,
+ [os.path.basename(recycleexe)] + ['"%s"'%path])
+ if rc:
+ raise TrashMoveError, ('Could not move path', path, '%s' % rc)
+ except (IOError, OSError), msg:
+ raise TrashMoveError, ('Could not move path', path, msg)
+
+def _osxTrash(paths):
+ """ Move paths to OS X Trash can """
+ trashdir = os.path.join(os.path.expanduser('~'),'.Trash')
+ if not os.path.isdir(trashdir):
+ raise TrashDirectoryError, ('Could not locate trash directory', trashdir)
+
+ for path in paths:
+ # See if we can even do this
+ _ensurePermissions(path)
+
+ # Generate new filename in trash
+ origpath = newpath = os.path.join(trashdir, os.path.basename(path))
+ while os.path.exists(newpath):
+ newpath = origpath
+ base, ext = os.path.splitext(newpath)
+ newpath = '%s %s%s' % (base, time.strftime('%H-%M-%S'), ext)
+
+ # Move the path
+ try:
+ shutil.move(path, newpath)
+ except (OSError, IOError), msg:
+ raise TrashMoveError, ('Could not move path', path, msg)
+
+def _unixTrash(paths):
+ """
+ Move paths to FreeDesktop Trash can
+
+ See <http://www.ramendik.ru/docs/trashspec.html>
+
+ """
+ trashdir = os.path.join(os.environ.get('XDG_DATA_HOME',
+ os.path.join(os.path.expanduser('~'),'.local','share')), 'Trash')
+
+ # Create trash directories as needed
+ try:
+ os.makedirs(os.path.join(trashdir, 'files'))
+ except (IOError, OSError):
+ pass
+
+ try:
+ os.makedirs(os.path.join(trashdir, 'info'))
+ except (IOError, OSError):
+ pass
+
+ # Make sure that directories got created
+ if not os.path.isdir(os.path.join(trashdir, 'files')):
+ raise TrashDirectoryError, ('Could not locate trash directory', trashdir)
+ if not os.path.isdir(os.path.join(trashdir, 'info')):
+ raise TrashDirectoryError, ('Could not locate trash directory', trashdir)
+
+ for path in paths:
+ # See if we can even do this
+ _ensurePermissions(path)
+
+ # Create unique filename
+ origpath = newpath = os.path.join(trashdir, 'files',
+ os.path.basename(path))
+ while os.path.exists(newpath):
+ newpath = origpath
+ base, ext = os.path.splitext(newpath)
+ newpath = '%s %s%s' % (base, time.strftime('%H-%M-%S'), ext)
+
+ # Write info file
+ try:
+ root, base = os.path.split(newpath)
+ infopath = os.path.join(os.path.dirname(root),
+ 'info', base + '.trashinfo')
+ info = open(infopath,'w')
+ info.write('[Trash Info]\n')
+ info.write('Path=%s\n' % path)
+ info.write(time.strftime('DeletionDate=%Y%m%dT%H:%M:%S\n'))
+ info.close()
+ except (OSError, IOError), msg:
+ try:
+ os.remove(infopath)
+ except:
+ pass
+ raise TrashMoveError, ('Could not move path', path, msg)
+
+ # Move file
+ try:
+ shutil.move(path, newpath)
+ except (OSError, IOError), msg:
+ raise TrashMoveError, ('Could not move path', path, msg)
+
+#-----------------------------------------------------------------------------#
+
+if __name__ == '__main__':
+ import sys
+ args = sys.argv[1:]
+ if args:
+ moveToTrash(args)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_winrecycle.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_winrecycle.py
new file mode 100644
index 0000000..0c25d42
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_winrecycle.py
@@ -0,0 +1,338 @@
+#!/usr/bin/env python2
+###############################################################################
+# Name: _winrecycle.py #
+# Purpose: Windows recycle bin implementation. #
+# Author: Kevin D. Smith <Kevin.Smith@sixquickrun.com> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+""" This is a self generating file. Run it to refresh the recycle.exe data. """
+
+__author__ = "Kevin D. Smith <Kevin.Smith@sixquickrun.com>"
+__revision__ = "$Revision: 50825 $"
+__scid__ = "$Id: Recycle.py 50825 2007-12-19 07:57:23Z CJP $"
+
+import base64, re
+
+recycle = base64.b64decode(
+"TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZG"
+"UuDQ0KJAAAAAAAAABQRQAATAEFAJHDw0YAGAAADAIAAOAABwMLAQI4AAwAAAAUAAAAAgAAgBIAAAA"
+"QAAAAIAAAAABAAAAQAAAAAgAABAAAAAEAAAAEAAAAAAAAAABgAAAABAAAyEMBAAMAAAAAACAAABAA"
+"AAAAEAAAEAAAAAAAABAAAAAAAAAAAAAAAABQAAAUAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC50ZXh0AAAA9AoAAAAQAAAADAAAAAQAAAAAAAA"
+"AAAAAAAAAAGAAAGAuZGF0YQAAAEAAAAAAIAAAAAIAAAAQAAAAAAAAAAAAAAAAAABAAADALnJkYXRh"
+"AADwAAAAADAAAAACAAAAEgAAAAAAAAAAAAAAAAAAQAAAQC5ic3MAAAAAwAAAAABAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAIAAAMAuaWRhdGEAABQDAAAAUAAAAAQAAAAUAAAAAAAAAAAAAAAAAABAAADAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWJ5YPsGIld+ItFCDHbiX"
+"X8iwAx9osAPZEAAMB3Qz2NAADAclu+AQAAAMcEJAgAAAAx0olUJATodAkAAIP4AXR6hcB0DscEJAg"
+"AAAD/0Lv/////idiLdfyLXfiJ7F3CBAA9lAAAwHTCd0o9kwAAwHS0idiLdfyLXfiJ7F3CBACQPQUA"
+"AMB0Wz0dAADAdcXHBCQEAAAAMfaJdCQE6BAJAACD+AF0aoXAdKrHBCQEAAAA/9Drmj2WAADA69HHB"
+"CQIAAAAuAEAAACJRCQE6OAIAACF9g+Edv///+gjBQAA6Wz////HBCQLAAAAMcCJRCQE6LwIAACD+A"
+"F0MIXAD4RS////xwQkCwAAAP/Q6T/////HBCQEAAAAuQEAAACJTCQE6IwIAADpJf///8cEJAsAAAC"
+"4AQAAAIlEJATocggAAOkL////jbYAAAAAjbwnAAAAAFWJ5VOD7CTHBCQAEEAA6A0JAACD7ATolQMA"
+"AOiQBAAAx0X4AAAAAI1F+IlEJBChACBAAMcEJARAQACJRCQMjUX0iUQkCLgAQEAAiUQkBOg9CAAAo"
+"RBAQACFwHRkoxAgQACLFfxQQACF0g+FoQAAAIP64HQfoRBAQACJRCQEofxQQACLQDCJBCTo8wcAAI"
+"sV/FBAAIP6wHQooRBAQACJRCQEofxQQACLQFCJBCTozwcAAOsNkJCQkJCQkJCQkJCQkOirBwAAixU"
+"QIEAAiRDorgIAAIPk8OiGAgAA6HEHAACLAIlEJAihAEBAAIlEJAShBEBAAIkEJOilAAAAicPoPgcA"
+"AIkcJOgmCAAAjbYAAAAAiUQkBKH8UEAAi0AQiQQk6FwHAACLFfxQQADpQP///5BVieWD7AjHBCQBA"
+"AAA/xX0UEAA6Lj+//+QjbQmAAAAAFWJ5YPsCMcEJAIAAAD/FfRQQADomP7//5CNtCYAAAAAVYsNDF"
+"FAAInlXf/hjXQmAFWLDQBRQACJ5V3/4ZCQkJBVieVd6dcDAACQkJCQkJCQVYnlV1OB7FAIAACD5PC"
+"4AAAAAIPAD4PAD8HoBMHgBImFxPf//4uFxPf//+jgBQAA6IsBAACNlfj3//+4AAgAAIlEJAjHRCQE"
+"AAAAAIkUJOisBgAAjb3Y9////LkeAAAAsADzqoN9CAB1D8eF1Pf//wAAAADpqQAAAItFDIPABIsAi"
+"QQk6JcGAAA9AAgAAHYPx4XU9///AAAAAOmDAAAAx4XY9///AAAAAMeF3Pf//wMAAACNhfj3//+Jhe"
+"D3//9mx4Xo9///VAaLRQyDwASLAIlEJASNhfj3//+JBCToLgYAAI2d+Pf//4tFDIPABIsAiQQk6Cg"
+"GAACNBAPHRCQEADBAAIkEJOgFBgAAjYXY9///iQQk6LcGAACD7ASJhdT3//+LhdT3//+NZfhbX13D"
+"kFWJ5YPsCKEgIEAAgzgAdBf/EIsVICBAAI1CBItSBKMgIEAAhdJ16cnDjbQmAAAAAFWJ5VOD7ASh4"
+"BpAAIP4/3QphcCJw3QTifaNvCcAAAAA/xSd4BpAAEt19scEJCAUQADoOv7//1lbXcMxwIM95BpAAA"
+"DrCkCLHIXkGkAAhdt19Ou+jbYAAAAAjbwnAAAAAFWhIEBAAInlhcB0BF3DZpBduAEAAACjIEBAAOu"
+"DkJCQVbnwMEAAieXrFI22AAAAAItRBIsBg8EIAYIAAEAAgfnwMEAAcupdw5CQkJCQkJCQVYnlU5yc"
+"WInDNQAAIABQnZxYnTHYqQAAIAAPhMAAAAAxwA+ihcAPhLQAAAC4AQAAAA+i9sYBD4WnAAAAidAlA"
+"IAAAGaFwHQHgw0wQEAAAvfCAACAAHQHgw0wQEAABPfCAAAAAXQHgw0wQEAACPfCAAAAAnQHgw0wQE"
+"AAEIHiAAAABHQHgw0wQEAAIPbBAXQHgw0wQEAAQPbFIHQKgQ0wQEAAgAAAALgAAACAD6I9AAAAgHY"
+"suAEAAIAPoqEwQEAAicGByQABAACB4gAAAEB0Hw0AAwAAozBAQACNtgAAAABbXcODDTBAQAAB6U3/"
+"//9biQ0wQEAAXcOQkJCQkJCQkFWJ5dvjXcOQkJCQkJCQkJBVoYBAQACJ5V2LSAT/4Yn2VbpCAAAAi"
+"eVTD7fAg+xkiVQkCI1VqDHbiVQkBIkEJP8V2FBAALofAAAAuQEAAACD7AyFwHUH60YByUp4DoB8Kq"
+"hBdfQJywHJSnnygzs8dQeJ2Itd/MnDuTQwQAC66gAAAIlMJAyJVCQIxwQkYTBAALiAMEAAiUQkBOi"
+"SAgAAuKwwQAC75AAAAIlEJAyJXCQI69eNtCYAAAAAjbwnAAAAAFWJ5VdWU4HszAAAAIsNgEBAAIXJ"
+"dAiNZfRbXl9dw8dFmEFBQUGhEDBAAI11mMdFnEFBQUHHRaBBQUFBiUW4oRQwQADHRaRBQUFBx0WoQ"
+"UFBQYlFvKEYMEAAx0WsQUFBQcdFsEFBQUGJRcChHDBAAMdFtEFBQUGJRcShIDBAAIlFyKEkMEAAiU"
+"XMoSgwQACJRdChLDBAAIlF1A+3BTAwQABmiUXYiTQk/xXUUEAAD7fAg+wEhcCJhUT///8PhTsBAAD"
+"HBCQ8AAAA6KMCAACFwInDD4RZAQAA/InHi4VE////uQ8AAADzq8dDBEAaQAC5AQAAAMdDCBAWQACh"
+"UEBAAMcDPAAAAIsVVEBAAMdDKAAAAACJQxShMCBAAIlTGIsVNCBAAIlDHKFgQEAAiVMgx0Mw/////"
+"4lDLIsVPCBAAKE4IEAAiVM4uh8AAACJQzSJ9onYIciD+AEZwCQgAckEQYiEKkj///9KeeehEDBAAI"
+"mFaP///6EUMEAAiYVs////oRgwQACJhXD///+hHDBAAImFdP///6EgMEAAiYV4////oSQwQACJhXz"
+"///+hKDBAAIlFgKEsMEAAiUWED7cFMDBAAGaJRYiNhUj///+JBCT/FcxQQAAPt/iD7ASF/3VCMdKF"
+"0nUeiRwk6HMBAACJNCT/FdRQQACD7AQPt8DoX/3//4nDiR2AQEAAjUMEo3BAQACNQwijkEBAAI1l9"
+"FteX13DifjoOP3//znYifp1seux6EsBAACQkJCQkJCQkJCQkFGJ4YPBCD0AEAAAchCB6QAQAACDCQ"
+"AtABAAAOvpKcGDCQCJ4InMiwiLQAT/4JCQkFWJ5YPsGItFFIlEJBCLRRCJRCQMi0UMiUQkCItFCIl"
+"EJASh/FBAAIPAQIkEJOj+AAAAofxQQACDwECJBCTo3gAAAOjJAAAAkJCQkJCQkJCQ/yX0UEAAkJAA"
+"AAAAAAAAAP8l+FBAAJCQAAAAAAAAAAD/JexQQACQkAAAAAAAAAAA/yUkUUAAkJAAAAAAAAAAAP8l8"
+"FBAAJCQAAAAAAAAAAD/JQRRQACQkAAAAAAAAAAA/yXoUEAAkJAAAAAAAAAAAP8lIFFAAJCQAAAAAA"
+"AAAAD/JShRQACQkAAAAAAAAAAA/yUsUUAAkJAAAAAAAAAAAP8lGFFAAJCQAAAAAAAAAAD/JRxRQAC"
+"QkAAAAAAAAAAA/yUIUUAAkJAAAAAAAAAAAP8lEFFAAJCQAAAAAAAAAAD/JRRRQACQkAAAAAAAAAAA"
+"/yXcUEAAkJAAAAAAAAAAAP8l0FBAAJCQAAAAAAAAAAD/JdhQQACQkAAAAAAAAAAA/yXUUEAAkJAAA"
+"AAAAAAAAP8lzFBAAJCQAAAAAAAAAAD/JThRQACQkAAAAAAAAAAAVYnlXekH+P//kJCQkJCQkP////"
+"/QGkAAAAAAAP////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8"
+"AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAA8BpAAAAAAAAAAAAAAAAAAAAAAAD/////AAAAAP//"
+"//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAC1MSUJHQ0NXMzItRUgtMi1TSkxKLUdUSFItTUlOR1czMgAAAHczMl9zaGFyZWRwdHItPnNpe"
+"mUgPT0gc2l6ZW9mKFczMl9FSF9TSEFSRUQpACVzOiV1OiBmYWlsZWQgYXNzZXJ0aW9uIGAlcycKAA"
+"AuLi8uLi9nY2MvZ2NjL2NvbmZpZy9pMzg2L3czMi1zaGFyZWQtcHRyLmMAAEdldEF0b21OYW1lQSA"
+"oYXRvbSwgcywgc2l6ZW9mKHMpKSAhPSAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUUAAAAAAAAAAAAACgUgAAzFAAA"
+"HBQAAAAAAAAAAAAAPhSAADoUAAAwFAAAAAAAAAAAAAACFMAADhRAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAABAUQAATFEAAFxRAABoUQAAeFEAAAAAAAAAAAAAmFEAAKhRAAC4UQAAyFEAANxRAADoUQA"
+"A8FEAAPxRAAAIUgAAEFIAABxSAAAoUgAANFIAADxSAABIUgAAVFIAAGBSAABsUgAAAAAAAAAAAAB4"
+"UgAAAAAAAAAAAABAUQAATFEAAFxRAABoUQAAeFEAAAAAAAAAAAAAmFEAAKhRAAC4UQAAyFEAANxRA"
+"ADoUQAA8FEAAPxRAAAIUgAAEFIAABxSAAAoUgAANFIAADxSAABIUgAAVFIAAGBSAABsUgAAAAAAAA"
+"AAAAB4UgAAAAAAAAEAQWRkQXRvbUEAAJwARXhpdFByb2Nlc3MAAACwAEZpbmRBdG9tQQDdAEdldEF"
+"0b21OYW1lQQAA4wJTZXRVbmhhbmRsZWRFeGNlcHRpb25GaWx0ZXIAAAAnAF9fZ2V0bWFpbmFyZ3MA"
+"PABfX3BfX2Vudmlyb24AAD4AX19wX19mbW9kZQAAAABQAF9fc2V0X2FwcF90eXBlAAAAAHkAX2Nle"
+"Gl0AAAAAOkAX2lvYgAAXgFfb25leGl0AAAAhAFfc2V0bW9kZQAAFQJhYm9ydAAcAmF0ZXhpdAAAAA"
+"AwAmZmbHVzaAAAAAA5AmZwcmludGYAAAA/AmZyZWUAAHICbWFsbG9jAAAAAHoCbWVtc2V0AAAAAJA"
+"Cc2lnbmFsAAAAAJsCc3RyY3B5AAAAAJ8Cc3RybGVuAAAAAEoAU0hGaWxlT3BlcmF0aW9uQQAAAFAA"
+"AABQAAAAUAAAAFAAAABQAABLRVJORUwzMi5kbGwAAAAAFFAAABRQAAAUUAAAFFAAABRQAAAUUAAAF"
+"FAAABRQAAAUUAAAFFAAABRQAAAUUAAAFFAAABRQAAAUUAAAFFAAABRQAAAUUAAAbXN2Y3J0LmRsbA"
+"AAKFAAAFNIRUxMMzIuRExMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAAAPAAAA/v8AAGcBY3J0MS5jAAAAAAAAAAAAAAA"
+"AAAAAAAQAAAAAAAAAAQAgAAMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAABQAQAAAQAgAAMAAAAA"
+"ADIAAACAAgAAAQAgAAIAAAAAAEIAAACgAgAAAQAgAAIAX2F0ZXhpdADAAgAAAQAgAAIAX19vbmV4a"
+"XTQAgAAAQAgAAIALnRleHQAAAAAAAAAAQAAAAMB3AIAACoAAAAAAAAAAAAAAAAALmRhdGEAAAAAAA"
+"AAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAAAAAAAABAAAAAMBCAAAAAAAAAAAAAAAAAA"
+"AAAAALmZpbGUAAAAZAAAA/v8AAGcBY3J0c3R1ZmYuYwAAAAAAAAAAAAAAAFUAAADgAgAAAQAgAAIB"
+"AAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAADgAgAAAQAAAAMBCQAAAAEAAAAAAAAAAAAAAAAALmRhd"
+"GEAAAAAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAAAQAAAABAAAAAMBAAAAAAAAAA"
+"AAAAAAAAAAAAAALmZpbGUAAAAkAAAA/v8AAGcBcmVjeWNsZS5jAAAAAAAAAAAAX21haW4AAADwAgA"
+"AAQAgAAIALnRleHQAAADwAgAAAQAAAAMBLwEAAAkAAAAAAAAAAAAAAAAALmRhdGEAAAAAAAAAAgAA"
+"AAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAAAQAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAAL"
+"nJkYXRhAAAAAAAAAwAAAAMBAwAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAAAsAAAA/v8AAGcBQ1JUZ2"
+"xvYi5jAAAAAAAAAAAALnRleHQAAAAgBAAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAAA"
+"AAAAAAgAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAAAQAAAABAAAAAMBAAAAAAAAAAAAAAAA"
+"AAAAAAAALmZpbGUAAAA0AAAA/v8AAGcBQ1JUZm1vZGUuYwAAAAAAAAAALnRleHQAAAAgBAAAAQAAA"
+"AMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAAAQAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALm"
+"JzcwAAAAAQAAAABAAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAAA8AAAA/v8AAGcBdHh0bW9"
+"kZS5jAAAAAAAAAAAALnRleHQAAAAgBAAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAAAQ"
+"AAAAAgAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAAAgAAAABAAAAAMBAAAAAAAAAAAAAAAAA"
+"AAAAAAALmZpbGUAAABKAAAA/v8AAGcBZ2NjbWFpbi5jAAAAAAAAAAAAAAAAAGUAAAAgAAAABAAAAA"
+"MAcC4wAAAAAAAgAAAAAgAAAAMAAAAAAHIAAAAgBAAAAQAgAAIBAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"AAIUAAABQBAAAAQAgAAIAX19fbWFpbgCwBAAAAQAgAAIALnRleHQAAAAgBAAAAQAAAAMBrQAAAAsA"
+"AAAAAAAAAAAAAAAALmRhdGEAAAAgAAAAAgAAAAMBBAAAAAEAAAAAAAAAAAAAAAAALmJzcwAAAAAgA"
+"AAABAAAAAMBEAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAABUAAAA/v8AAGcBcHNldWRvLXJlbG9jLm"
+"MAAAAAAAAAAJgAAADQBAAAAQAgAAIBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAADQBAAAAQAAAAM"
+"BKAAAAAMAAAAAAAAAAAAAAAAALmRhdGEAAAAwAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJz"
+"cwAAAAAwAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAABeAAAA/v8AAGcBY3B1X2ZlY"
+"XR1cmVzLmMAAAAAAAAAALMAAAAABQAAAQAgAAIBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAAAABQ"
+"AAAQAAAAMB+AAAAAsAAAAAAAAAAAAAAAAALmRhdGEAAAAwAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAA"
+"AAAAALmJzcwAAAAAwAAAABAAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAABpAAAA/v8AAGcB"
+"Q1JUX2ZwMTAuYwAAAAAAAAAAX2ZwcmVzZXQABgAAAQAgAAIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+"MgAAAAABgAAAQAgAAIALnRleHQAAAAABgAAAQAAAAMBBwAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAA"
+"AwAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABAAAAABAAAAAMBAAAAAAAAAAAAAAA"
+"AAAAAAAAALmZpbGUAAAAWAQAA/v8AAGcBAAAAANIAAAAAAAAAAAAAAAAALnRleHQAAAAQBgAAAQAA"
+"AAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAAAwAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAAL"
+"mJzcwAAAABAAAAABAAAAAMBAgAAAAAAAAAAAAAAAAAAAAAAAAAAAOYAAAAQAAAAAwAAAAMAAAAAAP"
+"cAAAAQBgAAAQAgAAMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsBAAAgBgAAAQAgAAMAAAAAADABAAB"
+"QAAAABAAAAAMAAAAAAEMBAAAwAAAAAgAAAAMAAAAAAE4BAABgAAAABAAAAAMAAAAAAFsBAAA4AAAA"
+"AgAAAAMAAAAAAGYBAADABgAAAQAgAAIALnRleHQAAAAQBgAAAQAAAAMB5QIAACwAAAAAAAAAAAAAA"
+"AAALmRhdGEAAAAwAAAAAgAAAAMBEAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABQAAAABAAAAAMBIA"
+"AAAAAAAAAAAAAAAAAAAAAALnJkYXRhAAAQAAAAAwAAAAMBwwAAAAAAAAAAAAAAAAAAAAAAcHJvYmU"
+"AAAAGCQAAAQAAAAYAZG9uZQAAAAAdCQAAAQAAAAYALnRleHQAAAAACQAAAQAAAAMBLQAAAAAAAAAA"
+"AAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAAB"
+"AAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAAAwCQAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAA"
+"AALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBAAA"
+"AAAAAAAAAAAAAAAAAAAAAAAAAAIIBAAAwCQAAAQAgAAIBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQA"
+"AAAwCQAAAQAAAAMBRwAAAAUAAAAAAAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAA"
+"AAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAACACQAAAQ"
+"AAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfEAgAABQAAAAM"
+"ALmlkYXRhJDX8AAAABQAAAAMALmlkYXRhJDSEAAAABQAAAAMALmlkYXRhJDboAQAABQAAAAMALnRl"
+"eHQAAACACQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJ"
+"De8AgAABQAAAAMALmlkYXRhJDX0AAAABQAAAAMALmlkYXRhJDR8AAAABQAAAAMALmlkYXRhJDbIAQ"
+"AABQAAAAMALnRleHQAAACQCQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAA"
+"AAAMALmlkYXRhJDfUAgAABQAAAAMALmlkYXRhJDUMAQAABQAAAAMALmlkYXRhJDSUAAAABQAAAAMA"
+"LmlkYXRhJDYQAgAABQAAAAMALnRleHQAAACQCQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzc"
+"wAAAABwAAAABAAAAAMALmlkYXRhJDfIAgAABQAAAAMALmlkYXRhJDUAAQAABQAAAAMALmlkYXRhJD"
+"SIAAAABQAAAAMALmlkYXRhJDbwAQAABQAAAAMALnRleHQAAACQCQAAAQAAAAMALmRhdGEAAABAAAA"
+"AAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfAAgAABQAAAAMALmlkYXRhJDX4AAAABQAA"
+"AAMALmlkYXRhJDSAAAAABQAAAAMALmlkYXRhJDbcAQAABQAAAAMALnRleHQAAACgCQAAAQAAAAMAL"
+"mRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDe0AgAABQAAAAMALmlkYX"
+"RhJDXsAAAABQAAAAMALmlkYXRhJDR0AAAABQAAAAMALmlkYXRhJDaoAQAABQAAAAMALnRleHQAAAC"
+"wCQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfsAgAA"
+"BQAAAAMALmlkYXRhJDUkAQAABQAAAAMALmlkYXRhJDSsAAAABQAAAAMALmlkYXRhJDZUAgAABQAAA"
+"AMALnRleHQAAADACQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALm"
+"lkYXRhJDe4AgAABQAAAAMALmlkYXRhJDXwAAAABQAAAAMALmlkYXRhJDR4AAAABQAAAAMALmlkYXR"
+"hJDa4AQAABQAAAAMALnRleHQAAADQCQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABw"
+"AAAABAAAAAMALmlkYXRhJDfMAgAABQAAAAMALmlkYXRhJDUEAQAABQAAAAMALmlkYXRhJDSMAAAAB"
+"QAAAAMALmlkYXRhJDb8AQAABQAAAAMALnRleHQAAADgCQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAA"
+"MALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDewAgAABQAAAAMALmlkYXRhJDXoAAAABQAAAAMALml"
+"kYXRhJDRwAAAABQAAAAMALmlkYXRhJDaYAQAABQAAAAMALnRleHQAAADwCQAAAQAAAAMALmRhdGEA"
+"AABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfoAgAABQAAAAMALmlkYXRhJDUgA"
+"QAABQAAAAMALmlkYXRhJDSoAAAABQAAAAMALmlkYXRhJDZIAgAABQAAAAMALnRleHQAAAAACgAAAQ"
+"AAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfwAgAABQAAAAM"
+"ALmlkYXRhJDUoAQAABQAAAAMALmlkYXRhJDSwAAAABQAAAAMALmlkYXRhJDZgAgAABQAAAAMALnRl"
+"eHQAAAAQCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJ"
+"Df0AgAABQAAAAMALmlkYXRhJDUsAQAABQAAAAMALmlkYXRhJDS0AAAABQAAAAMALmlkYXRhJDZsAg"
+"AABQAAAAMALnRleHQAAAAgCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAA"
+"AAAMALmlkYXRhJDfgAgAABQAAAAMALmlkYXRhJDUYAQAABQAAAAMALmlkYXRhJDSgAAAABQAAAAMA"
+"LmlkYXRhJDY0AgAABQAAAAMALnRleHQAAAAwCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzc"
+"wAAAABwAAAABAAAAAMALmlkYXRhJDfkAgAABQAAAAMALmlkYXRhJDUcAQAABQAAAAMALmlkYXRhJD"
+"SkAAAABQAAAAMALmlkYXRhJDY8AgAABQAAAAMALnRleHQAAABACgAAAQAAAAMALmRhdGEAAABAAAA"
+"AAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfQAgAABQAAAAMALmlkYXRhJDUIAQAABQAA"
+"AAMALmlkYXRhJDSQAAAABQAAAAMALmlkYXRhJDYIAgAABQAAAAMALnRleHQAAABQCgAAAQAAAAMAL"
+"mRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfYAgAABQAAAAMALmlkYX"
+"RhJDUQAQAABQAAAAMALmlkYXRhJDSYAAAABQAAAAMALmlkYXRhJDYcAgAABQAAAAMALnRleHQAAAB"
+"gCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfcAgAA"
+"BQAAAAMALmlkYXRhJDUUAQAABQAAAAMALmlkYXRhJDScAAAABQAAAAMALmlkYXRhJDYoAgAABQAAA"
+"AMALmZpbGUAAAAmAQAA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAAaG5hbWUAAABwAAAABQAAAAMAZn"
+"RodW5rAADoAAAABQAAAAMALnRleHQAAABwCgAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGE"
+"AAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBAAAAAAAAAAAA"
+"AAAAAAAAAAAALmlkYXRhJDIUAAAABQAAAAMBFAAAAAMAAAAAAAAAAAAAAAAALmlkYXRhJDXkAAAAB"
+"QAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDRsAAAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAA"
+"AALmZpbGUAAABXAQAA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAALnRleHQAAABwCgAAAQAAAAMBAAA"
+"AAAAAAAAAAAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAA"
+"AABwAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDS4AAAABQAAAAMBBAAAAAAAAAAAA"
+"AAAAAAAAAAALmlkYXRhJDUwAQAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDf4AgAABQ"
+"AAAAMBCwAAAAAAAAAAAAAAAAAAAAAALnRleHQAAABwCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAM"
+"ALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDecAgAABQAAAAMALmlkYXRhJDXcAAAABQAAAAMALmlk"
+"YXRhJDRkAAAABQAAAAMALmlkYXRhJDZ4AQAABQAAAAMALnRleHQAAACACgAAAQAAAAMALmRhdGEAA"
+"ABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDeQAgAABQAAAAMALmlkYXRhJDXQAA"
+"AABQAAAAMALmlkYXRhJDRYAAAABQAAAAMALmlkYXRhJDZMAQAABQAAAAMALnRleHQAAACQCgAAAQA"
+"AAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDeYAgAABQAAAAMA"
+"LmlkYXRhJDXYAAAABQAAAAMALmlkYXRhJDRgAAAABQAAAAMALmlkYXRhJDZoAQAABQAAAAMALnRle"
+"HQAAACgCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJD"
+"eUAgAABQAAAAMALmlkYXRhJDXUAAAABQAAAAMALmlkYXRhJDRcAAAABQAAAAMALmlkYXRhJDZcAQA"
+"ABQAAAAMALnRleHQAAACwCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAA"
+"AAMALmlkYXRhJDeMAgAABQAAAAMALmlkYXRhJDXMAAAABQAAAAMALmlkYXRhJDRUAAAABQAAAAMAL"
+"mlkYXRhJDZAAQAABQAAAAMALmZpbGUAAABnAQAA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAAaG5hbW"
+"UAAABUAAAABQAAAAMAZnRodW5rAADMAAAABQAAAAMALnRleHQAAADACgAAAQAAAAMBAAAAAAAAAAA"
+"AAAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAA"
+"BAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDIAAAAABQAAAAMBFAAAAAMAAAAAAAAAAAAAA"
+"AAALmlkYXRhJDXIAAAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDRQAAAABQAAAAMBBA"
+"AAAAAAAAAAAAAAAAAAAAAALmZpbGUAAAB8AQAA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAALnRleHQ"
+"AAADACgAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAA"
+"AAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDRoAAAAB"
+"QAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDXgAAAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAA"
+"AALmlkYXRhJDegAgAABQAAAAMBDQAAAAAAAAAAAAAAAAAAAAAALnRleHQAAADACgAAAQAAAAMALmR"
+"hdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDcEAwAABQAAAAMALmlkYXRh"
+"JDU4AQAABQAAAAMALmlkYXRhJDTAAAAABQAAAAMALmlkYXRhJDZ4AgAABQAAAAMALmZpbGUAAACMA"
+"QAA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAAaG5hbWUAAADAAAAABQAAAAMAZnRodW5rAAA4AQAABQ"
+"AAAAMALnRleHQAAADQCgAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAM"
+"BAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmlk"
+"YXRhJDIoAAAABQAAAAMBFAAAAAMAAAAAAAAAAAAAAAAALmlkYXRhJDU0AQAABQAAAAMBBAAAAAAAA"
+"AAAAAAAAAAAAAAALmlkYXRhJDS8AAAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAACaAQ"
+"AA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAALnRleHQAAADQCgAAAQAAAAMBAAAAAAAAAAAAAAAAAAA"
+"AAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMB"
+"AAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDTEAAAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkY"
+"XRhJDU8AQAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDcIAwAABQAAAAMBDAAAAAAAAA"
+"AAAAAAAAAAAAAALmZpbGUAAACmAQAA/v8AAGcBY3J0c3R1ZmYuYwAAAAAAAAAAAAAAAI0BAADQCgA"
+"AAQAgAAMBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAADQCgAAAQAAAAMBCQAAAAEAAAAAAAAAAAAA"
+"AAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBA"
+"AAAAAAAAAAAAAAAAAAAAAAALmN0b3JzAADkCgAAAQAAAAMBBAAAAAEAAAAAAAAAAAAAAAAAX19jZX"
+"hpdACQCQAAAQAgAAIAAAAAAJ8BAADwAAAAAwAAAAIAAAAAAL4BAAAEAQAABQAAAAIAAAAAAM4BAAA"
+"AAAAAAgAAAAIAAAAAAN0BAADsCgAAAQAAAAIAX2ZyZWUAAAAgCgAAAQAgAAIAAAAAAOwBAAAAAQAA"
+"BQAAAAIAAAAAAPsBAADACQAAAQAgAAIAAAAAAAcCAABwCgAAAQAAAAIAAAAAACYCAABwAAAABAAAA"
+"AIAAAAAAEECAAAAYEAA//8AAAIAAAAAAFACAAD4AgAABQAAAAIAAAAAAGQCAADUAAAABQAAAAIAAA"
+"AAAHcCAAAIAQAABQAAAAIAAAAAAIQCAAAAEAAA//8AAAIAAAAAAJ0CAAAAACAA//8AAAIAAAAAALc"
+"CAAAEAAAA//8AAAIAAAAAANMCAAAAYEAA//8AAAIAAAAAAOUCAACwCgAAAQAAAAIAAAAAAPECAAAA"
+"YEAA//8AAAIAAAAAAAMDAAAACQAAAQAAAAIAAAAAAA0DAAAAYEAA//8AAAIAAAAAAB0DAADsAAAAB"
+"QAAAAIAAAAAADEDAAD8AAAABQAAAAIAAAAAAD0DAAAAAAAABAAAAAIAAAAAAEsDAADwAAAAAwAAAA"
+"IAAAAAAG4DAAAAEAAA//8AAAIAAAAAAIYDAAA4AQAABQAAAAIAAAAAAKADAACgCQAAAQAgAAIAAAA"
+"AAK4DAAAAYEAA//8AAAIAAAAAAMADAAAAYEAA//8AAAIAAAAAANADAAAkAQAABQAAAAIAX19kbGxf"
+"XwAAAAAA//8AAAIAAAAAAN4DAAAAAAAA//8AAAIAAAAAAPMDAAAMAQAABQAAAAIAAAAAAAEEAAAUA"
+"AAABQAAAAIAAAAAABQEAAAAAEAA//8AAAIAAAAAACMEAAAoAAAABQAAAAIAAAAAADcEAAAAEAAA//"
+"8AAAIAAAAAAE0EAADwAAAAAwAAAAIAX21lbXNldADwCQAAAQAgAAIAAAAAAGsEAADwAAAABQAAAAI"
+"AX19hcmdjAAAEAAAABAAAAAIAAAAAAH0EAACACgAAAQAAAAIAAAAAAIwEAABAAAAAAgAAAAIAAAAA"
+"AJkEAADgCQAAAQAgAAIAAAAAAKgEAACAAAAABAAAAAIAAAAAALkEAADgCgAAAQAAAAIAAAAAAMcEA"
+"ACACQAAAQAAAAIAX2ZmbHVzaABQCgAAAQAgAAIAAAAAANcEAADAAAAABAAAAAIAAAAAAOMEAAAQAA"
+"AABAAAAAIAAAAAAO8EAAAAYEAA//8AAAIAX2ZwcmludGZgCgAAAQAgAAIAX19hbGxvY2EACQAAAQA"
+"AAAIAAAAAAP8EAAAAYEAA//8AAAIAX19hcmd2AAAAAAAABAAAAAIAAAAAABEFAADgCgAAAQAAAAIA"
+"AAAAACAFAADYAAAABQAAAAIAX19mbW9kZQAQAAAAAgAAAAIAAAAAADcFAAAAAgAA//8AAAIAAAAAA"
+"EoFAAAcAQAABQAAAAIAAAAAAFgFAAAEAAAA//8AAAIAX19lbmRfXwAAYEAA//8AAAIAX3NpZ25hbA"
+"CwCQAAAQAgAAIAX21hbGxvYwAwCgAAAQAgAAIAAAAAAG0FAADsCgAAAQAAAAIAAAAAAHsFAAAUAQA"
+"ABQAAAAIAX3N0cmNweQAACgAAAQAgAAIAAAAAAIoFAAAgAQAABQAAAAIAAAAAAJgFAAAAABAA//8A"
+"AAIAAAAAALEFAAAAYEAA//8AAAIAAAAAAMMFAAADAAAA//8AAAIAAAAAANEFAAAsAQAABQAAAAIAA"
+"AAAAN8FAAAQAQAABQAAAAIAAAAAAO0FAAAoAQAABQAAAAIAX2Fib3J0AABACgAAAQAgAAIAAAAAAP"
+"sFAACQAAAABAAAAAIAAAAAABcGAADoAAAABQAAAAIAAAAAACwGAAAAYEAA//8AAAIAAAAAADkGAAD"
+"QAAAABQAAAAIAAAAAAE4GAAAwAAAABAAAAAIAAAAAAF4GAAAYAQAABQAAAAIAAAAAAGoGAADcAAAA"
+"BQAAAAIAAAAAAI8GAAABAAAA//8AAAIAAAAAAKcGAAAAAAAA//8AAAIAAAAAALgGAAAAAAAAAgAAA"
+"AIAAAAAAMMGAADQCQAAAQAgAAIAAAAAAM0GAADMAAAABQAAAAIAAAAAAN8GAAAAAAAABQAAAAIAAA"
+"AAAPQGAAD4AAAABQAAAAIAAAAAAAIHAAAAAAAA//8AAAIAAAAAAB4HAAAAAAAA//8AAAIAX3N0cmx"
+"lbgAQCgAAAQAgAAIAAAAAADYHAAD0AAAABQAAAAIAAAAAAEwHAADACgAAAQAAAAIAAAAAAGAHAACg"
+"CgAAAQAAAAIAAAAAAG0HAAAIAwAABQAAAAIAAAAAAIIHAACQCgAAAQAAAAIAAAAAAJMHAADwAAAAA"
+"wAAAAIAAAAAALUHAACgAgAABQAAAAIAAAAAAMsHAAAAYEAA//8AAAIA2wcAAF9fZ251X2V4Y2VwdG"
+"lvbl9oYW5kbGVyQDQAX19fbWluZ3dfQ1JUU3RhcnR1cABfbWFpbkNSVFN0YXJ0dXAAX1dpbk1haW5"
+"DUlRTdGFydHVwAF9fX2RvX3NqbGpfaW5pdABfaW5pdGlhbGl6ZWQAX19fZG9fZ2xvYmFsX2R0b3Jz"
+"AF9fX2RvX2dsb2JhbF9jdG9ycwBfX3BlaTM4Nl9ydW50aW1lX3JlbG9jYXRvcgBfX19jcHVfZmVhd"
+"HVyZXNfaW5pdABfX2ZwcmVzZXQAcHNldWRvLXJlbG9jLWxpc3QuYwBfdzMyX2F0b21fc3VmZml4AF"
+"9fX3czMl9zaGFyZWRwdHJfZGVmYXVsdF91bmV4cGVjdGVkAF9fX3czMl9zaGFyZWRwdHJfZ2V0AGR"
+"3Ml9vYmplY3RfbXV0ZXguMABkdzJfb25jZS4xAHNqbF9mY19rZXkuMgBzamxfb25jZS4zAF9fX3cz"
+"Ml9zaGFyZWRwdHJfaW5pdGlhbGl6ZQBfX19lcHJpbnRmAF9fX3NqbGpfaW5pdF9jdG9yAF9fX1JVT"
+"lRJTUVfUFNFVURPX1JFTE9DX0xJU1RfXwBfX2ltcF9fX3NldG1vZGUAX19kYXRhX3N0YXJ0X18AX1"
+"9fRFRPUl9MSVNUX18AX19pbXBfX19vbmV4aXQAX19fcF9fZm1vZGUAX1NldFVuaGFuZGxlZEV4Y2V"
+"wdGlvbkZpbHRlckA0AF9fX3czMl9zaGFyZWRwdHJfdGVybWluYXRlAF9fX3Rsc19zdGFydF9fAF9f"
+"bGlibXN2Y3J0X2FfaW5hbWUAX19pbXBfX0ZpbmRBdG9tQUA0AF9faW1wX19hYm9ydABfX3NpemVfb"
+"2Zfc3RhY2tfY29tbWl0X18AX19zaXplX29mX3N0YWNrX3Jlc2VydmVfXwBfX21ham9yX3N1YnN5c3"
+"RlbV92ZXJzaW9uX18AX19fY3J0X3hsX3N0YXJ0X18AX0FkZEF0b21BQDQAX19fY3J0X3hpX3N0YXJ"
+"0X18AX19fY2hrc3RrAF9fX2NydF94aV9lbmRfXwBfX2ltcF9fX19wX19lbnZpcm9uAF9faW1wX19f"
+"aW9iAF9fYnNzX3N0YXJ0X18AX19fUlVOVElNRV9QU0VVRE9fUkVMT0NfTElTVF9FTkRfXwBfX3Npe"
+"mVfb2ZfaGVhcF9jb21taXRfXwBfX2ltcF9fU0hGaWxlT3BlcmF0aW9uQUA0AF9fX3BfX2Vudmlyb2"
+"4AX19fY3J0X3hwX3N0YXJ0X18AX19fY3J0X3hwX2VuZF9fAF9faW1wX19zaWduYWwAX19taW5vcl9"
+"vc192ZXJzaW9uX18AX19pbXBfX2F0ZXhpdABfX2hlYWRfbGlibXN2Y3J0X2EAX19pbWFnZV9iYXNl"
+"X18AX19oZWFkX2xpYnNoZWxsMzJfYQBfX3NlY3Rpb25fYWxpZ25tZW50X18AX19SVU5USU1FX1BTR"
+"VVET19SRUxPQ19MSVNUX18AX19pbXBfX19fcF9fZm1vZGUAX0V4aXRQcm9jZXNzQDQAX19kYXRhX2"
+"VuZF9fAF9fX2dldG1haW5hcmdzAF9fX3czMl9zaGFyZWRwdHIAX19DVE9SX0xJU1RfXwBfX19zZXR"
+"fYXBwX3R5cGUAX19ic3NfZW5kX18AX19DUlRfZm1vZGUAX19fY3J0X3hjX2VuZF9fAF9fX2NydF94"
+"Y19zdGFydF9fAF9fX0NUT1JfTElTVF9fAF9faW1wX19HZXRBdG9tTmFtZUFAMTIAX19maWxlX2Fsa"
+"WdubWVudF9fAF9faW1wX19tYWxsb2MAX19tYWpvcl9vc192ZXJzaW9uX18AX19EVE9SX0xJU1RfXw"
+"BfX2ltcF9fZnByaW50ZgBfX2ltcF9fbWVtc2V0AF9fc2l6ZV9vZl9oZWFwX3Jlc2VydmVfXwBfX19"
+"jcnRfeHRfc3RhcnRfXwBfX3N1YnN5c3RlbV9fAF9faW1wX19zdHJsZW4AX19pbXBfX2ZmbHVzaABf"
+"X2ltcF9fc3RyY3B5AF9fX3czMl9zaGFyZWRwdHJfdW5leHBlY3RlZABfX2ltcF9fX19nZXRtYWluY"
+"XJncwBfX190bHNfZW5kX18AX19pbXBfX0V4aXRQcm9jZXNzQDQAX19fY3B1X2ZlYXR1cmVzAF9faW"
+"1wX19mcmVlAF9faW1wX19TZXRVbmhhbmRsZWRFeGNlcHRpb25GaWx0ZXJANABfX21ham9yX2ltYWd"
+"lX3ZlcnNpb25fXwBfX2xvYWRlcl9mbGFnc19fAF9fQ1JUX2dsb2IAX19zZXRtb2RlAF9faW1wX19B"
+"ZGRBdG9tQUA0AF9faGVhZF9saWJrZXJuZWwzMl9hAF9faW1wX19fY2V4aXQAX19taW5vcl9zdWJze"
+"XN0ZW1fdmVyc2lvbl9fAF9fbWlub3JfaW1hZ2VfdmVyc2lvbl9fAF9faW1wX19fX3NldF9hcHBfdH"
+"lwZQBfU0hGaWxlT3BlcmF0aW9uQUA0AF9GaW5kQXRvbUFANABfX2xpYnNoZWxsMzJfYV9pbmFtZQB"
+"fR2V0QXRvbU5hbWVBQDEyAF9fUlVOVElNRV9QU0VVRE9fUkVMT0NfTElTVF9FTkRfXwBfX2xpYmtl"
+"cm5lbDMyX2FfaW5hbWUAX19fY3J0X3h0X2VuZF9fAA==")
+
+# Embed the recycle program for windows into this module
+if __name__ == '__main__':
+ s = base64.b64encode(open('recycle.exe').read())
+ lines = list()
+ for piece in xrange(0, (len(s)/77)):
+ lines.append(s[(piece*77):(piece*77)+77])
+ lines.append(s[(len(s)/77)*77:])
+ line = [ "\"%s\"" % x for x in lines ]
+ prog = "\n".join(line)
+ module = open('_winrecycle.py').read()
+ module = re.compile(r'^recycle = .+$\)', re.M).sub(r"recycle = base64.b64decode(\n%s)" % prog, module)
+ open('_winrecycle.py','w').write(module)
+ print "Embedding was ok?", ''.join(lines) == s
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/backupmgr.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/backupmgr.py
new file mode 100644
index 0000000..069bb6d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/backupmgr.py
@@ -0,0 +1,179 @@
+###############################################################################
+# Name: backupmgr.py #
+# Purpose: File Backup Manager #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: FileBackupMgr
+
+Helper class for managing and creating backups of files.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: backupmgr.py 67646 2011-04-29 03:07:20Z CJP $"
+__revision__ = "$Revision: 67646 $"
+
+__all__ = [ 'FileBackupMgr', ]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import os
+import shutil
+
+# Local Imports
+import fileutil
+import fchecker
+
+#-----------------------------------------------------------------------------#
+
+class FileBackupMgr(object):
+ """File backup creator and manager"""
+ def __init__(self, header=None, template=u"%s~"):
+ """Create a BackupManager
+ @keyword header: header to id backups with (Text files only!!)
+ @keyword template: template string for naming backup file with
+
+ """
+ super(FileBackupMgr, self).__init__()
+
+ # Attributes
+ self.checker = fchecker.FileTypeChecker()
+ self.header = header # Backup id header
+ self.template = template # Filename template
+ self.bkupdir = u""
+
+ def _CheckHeader(self, fname):
+ """Check if the backup file has a header that matches the
+ header used to identify backup files.
+ @param fname: name of file to check
+ @return: bool (True if header is ok, False otherwise)
+
+ """
+ isok = False
+ handle = None
+ try:
+ handle = open(fname, 'r')
+ line = handle.readline()
+ handle.close()
+ isok = line.startswith(self.header)
+ except Exception, msg:
+ isok = False
+ if handle:
+ handle.close()
+ return isok
+
+ def GetBackupFilename(self, fname):
+ """Get the unique name for the files backup copy
+ @param fname: string (file path)
+ @return: string
+
+ """
+ if self.bkupdir:
+ tmp = fileutil.GetFileName(fname)
+ fname = os.path.join(self.bkupdir, tmp)
+
+ rname = self.template % fname
+ if self.header is not None and \
+ not self.checker.IsBinary(fname) and \
+ os.path.exists(rname):
+ # Make sure that the template backup name does not match
+ # an existing file that is not a backup file.
+ while os.path.exists(rname):
+ if not self._CheckHeader(rname):
+ rname = self.template % rname
+ else:
+ break
+
+ return rname
+
+ def GetBackupWriter(self, fileobj):
+ """Create a backup filewriter method to backup a files contents
+ with.
+ @param fileobj: object implementing fileimpl.FileObjectImpl interface
+ @return: callable(text) to create backup with
+
+ """
+ nfile = fileobj.Clone()
+ fname = self.GetBackupFilename(nfile.GetPath())
+ nfile.SetPath(fname)
+ # Write the header if it is enabled
+ if self.header and not self.checker.IsBinary(fname):
+ nfile.Write(self.header + os.linesep)
+ return nfile.Write
+
+ def HasBackup(self, fname):
+ """Check if a given file has a backup file available or not
+ @param fname: string (file path)
+
+ """
+ backup = self.GetBackupFilename(fname)
+ return os.path.exists(backup)
+
+ def IsBackupNewer(self, fname):
+ """Is the backup of this file newer than the saved version
+ of the file?
+ @param fname: string (file path)
+ @return: bool
+
+ """
+ backup = self.GetBackupFilename(fname)
+ if os.path.exists(fname) and os.path.exists(backup):
+ mod1 = fileutil.GetFileModTime(backup)
+ mod2 = fileutil.GetFileModTime(fname)
+ return mod1 > mod2
+ else:
+ return False
+
+ def MakeBackupCopy(self, fname):
+ """Create a backup copy of the given filename
+ @param fname: string (file path)
+ @return: bool (True == Success)
+
+ """
+ backup = self.GetBackupFilename(fname)
+ try:
+ if os.path.exists(backup):
+ os.remove(backup)
+
+ shutil.copy2(fname, backup)
+ if self.header:
+ handle = open(backup, 'r')
+ txt = handle.read()
+ handle.close()
+ handle = open(backup, 'w')
+ handle.write(self.header + os.linesep)
+ handle.write(txt)
+ handle.close()
+ except:
+ return False
+ else:
+ return True
+
+ def SetBackupDirectory(self, path):
+ """Set the backup directory to use for all backups created by this
+ manager instance. Setting the path to an empty string will set the
+ default behavior to write the backup to the same directory as the
+ where the file that is being backedup is located.
+
+ """
+ self.bkupdir = path
+
+ def SetBackupFileTemplate(self, tstr):
+ """Set the filename template for generating the backupfile name
+ @param tstr: template string i.e) %s~
+
+ """
+ assert tstr.count("%s") == 1, "Format statment must only have one arg"
+ self.template = tstr
+
+ def SetHeader(self, header):
+ """Set the header string for identifying a file as a backup
+ @param header: string (single line only)
+
+ """
+ assert '\n' not in header, "Header must only be a single line"
+ self.header = header
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/calllock.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/calllock.py
new file mode 100644
index 0000000..b644b8e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/calllock.py
@@ -0,0 +1,95 @@
+###############################################################################
+# Name: calllock.py #
+# Purpose: Manager to lock the context of a function call. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2010 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: CallLock
+
+Provides a Lock class for managing a lock during the duration of a function
+call.
+
+Example:
+
+lock = CallLock(DoSomething)
+lock.Lock() # Executes DoSomething
+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: calllock.py 65794 2010-10-13 14:10:09Z CJP $"
+__revision__ = "$Revision: 65794 $"
+
+__all__ = [ 'CallLock', 'StaticCallLock', 'LockCall']
+
+#-----------------------------------------------------------------------------#
+
+class CallLock(object):
+ """Class to lock a context around a function call"""
+ def __init__(self, callable=None, args=[], kwargs={}):
+ super(CallLock, self).__init__()
+
+ # Attributes
+ self._locked = False
+ self.funct = callable
+ self.args = args
+ self.kwargs = kwargs
+
+ def Discard(self):
+ """Clear callable"""
+ assert not self.IsLocked(), "Failed to obtain lock!"
+ self.funct = None
+ self.args = []
+ self.kwargs = {}
+
+ def IsLocked(self):
+ return self._locked
+
+ def Lock(self):
+ assert not self.IsLocked(), "Failed to obtain lock!"
+ assert callable(self.funct), "No Callable to Lock!"
+ self._locked = True
+ rval = self.funct(*self.args, **self.kwargs)
+ self._locked = False
+ return rval
+
+ def SetManagedCall(self, callable, args=[], kwargs={}):
+ """Set the call that will be managed by this lock"""
+ assert not self.IsLocked(), "Failed to obtain lock!"
+ self.funct = callable
+ self.args = args
+ self.kwargs = kwargs
+
+#-----------------------------------------------------------------------------#
+
+class StaticCallLock(CallLock):
+ """Provides a static lock around a function call"""
+ _staticlock = False
+
+ def IsLocked(self):
+ return StaticCallLock._staticlock
+
+ def Lock(self):
+ """Lock the static class member"""
+ StaticCallLock._staticlock = True
+ super(StaticCallLock, self).Lock()
+ StaticCallLock._staticlock = False
+
+#-----------------------------------------------------------------------------#
+
+def LockCall(lock, callable, args=[], kwargs={}):
+ """Convenience function for locking an function call with
+ the provided CallLock object.
+
+ """
+ if not isinstance(lock, CallLock):
+ raise TypeError("lock is not of type CallLock")
+
+ lock.SetManagedCall(callable, args, kwargs)
+ rval = lock.Lock()
+ lock.Discard()
+ return rval
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/clipboard.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/clipboard.py
new file mode 100644
index 0000000..199837a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/clipboard.py
@@ -0,0 +1,151 @@
+###############################################################################
+# Name: clipboard.py #
+# Purpose: Vim like clipboard #
+# Author: Hasan Aljudy #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: Clipboard
+
+Clipboard helper class
+
+"""
+
+__author__ = "Hasan Aljudy"
+__cvsid__ = "$Id: clipboard.py 67123 2011-03-04 00:02:35Z CJP $"
+__revision__ = "$Revision: 67123 $"
+
+__all__ = [ 'Clipboard', 'ClipboardException']
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+#-----------------------------------------------------------------------------#
+
+class ClipboardException(Exception):
+ """Thrown for errors in the Clipboard class"""
+ pass
+
+#-----------------------------------------------------------------------------#
+
+class Clipboard(object):
+ """Multiple clipboards as named registers (as per vim)
+
+ " is an alias for system clipboard and is also the default clipboard.
+
+ @note: The only way to access multiple clipboards right now is through
+ Normal mode when Vi(m) emulation is enabled.
+
+ """
+ NAMES = list(u'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_')
+ registers = {}
+ current = u'"'
+
+ @classmethod
+ def ClearAll(cls):
+ """Clear all registers"""
+ for reg in cls.registers:
+ cls.registers[reg] = u''
+
+ @classmethod
+ def DeleteAll(cls):
+ """Delete all registers"""
+ cls.registers.clear()
+
+ @classmethod
+ def Switch(cls, reg):
+ """Switch to register
+ @param reg: char
+
+ """
+ if reg in cls.NAMES or reg == u'"':
+ cls.current = reg
+ else:
+ raise ClipboardException(u"Switched to invalid register name")
+
+ @classmethod
+ def NextFree(cls):
+ """Switch to the next free register. If current register is free, no
+ switching happens.
+
+ A free register is one that's either unused or has no content
+
+ @note: This is not used yet.
+
+ """
+ if cls.Get() == u'':
+ return
+
+ for name in cls.NAMES:
+ if cls.registers.get(name, u'') == u'':
+ cls.Switch(name)
+ break
+
+ @classmethod
+ def AllUsed(cls):
+ """Get a dictionary mapping all used clipboards (plus the system
+ clipboard) to their content.
+ @note: This is not used yet.
+ @return: dict
+
+ """
+ cmd_map = { u'"': cls.SystemGet() }
+ for name in cls.NAMES:
+ if cls.registers.get(name, u''):
+ cmd_map[name] = cls.registers[name]
+ return cmd_map
+
+ @classmethod
+ def Get(cls):
+ """Get the content of the current register. Used for pasting"""
+ if cls.current == u'"':
+ return cls.SystemGet()
+ else:
+ return cls.registers.get(cls.current, u'')
+
+ @classmethod
+ def Set(cls, text):
+ """Set the content of the current register
+ @param text: string
+
+ """
+ if cls.current == u'"':
+ return cls.SystemSet(text)
+ else:
+ cls.registers[cls.current] = text
+
+ @classmethod
+ def SystemGet(cls):
+ """Get text from the system clipboard
+ @return: string
+
+ """
+ text = None
+ if wx.TheClipboard.Open():
+ if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)):
+ text = wx.TextDataObject()
+ wx.TheClipboard.GetData(text)
+
+ wx.TheClipboard.Close()
+
+ if text is not None:
+ return text.GetText()
+ else:
+ return u''
+
+ @classmethod
+ def SystemSet(cls, text):
+ """Set text into the system clipboard
+ @param text: string
+ @return: bool
+
+ """
+ ok = False
+ if wx.TheClipboard.Open():
+ wx.TheClipboard.SetData(wx.TextDataObject(text))
+ wx.TheClipboard.Close()
+ ok = True
+ return ok
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/cmenumgr.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/cmenumgr.py
new file mode 100644
index 0000000..57c8095
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/cmenumgr.py
@@ -0,0 +1,114 @@
+###############################################################################
+# Name: cmenumgr.py #
+# Purpose: ContextMenu Manager #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2010 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: ContextMenuManager
+
+Helper class for managing context menu callbacks
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: cmenumgr.py 69118 2011-09-17 18:46:15Z CJP $"
+__revision__ = "$Revision: 69118 $"
+
+__all__ = [ 'ContextMenuManager', ]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+#-----------------------------------------------------------------------------#
+
+class ContextMenuManager(object):
+ """Class for registering and managing context menu callbacks"""
+ def __init__(self):
+ super(ContextMenuManager, self).__init__()
+
+ # Attributes
+ self._menu = None # Context Menu
+ self._pos = (0, 0) # Menu position
+ self._handlers = dict() # {ID : callable(event)}
+ self._userdata = dict()
+
+ Menu = property(lambda self: self.GetMenu(),
+ lambda self, menu: self.SetMenu(menu))
+
+ Position = property(lambda self: self.GetPosition(),
+ lambda self, pos: self.SetPosition(pos))
+
+ def __del__(self):
+ """Cleanup when it goes out of scope"""
+ self.Clear()
+
+ def AddHandler(self, evt_id, handler):
+ """Add an event handler
+ @param evt_id: int
+ @param handler: callable(event)
+
+ """
+ self._handlers[evt_id] = handler
+
+ def Clear(self):
+ """Clear all handlers and destroy the menu"""
+ self._handlers.clear()
+ self._userdata.clear()
+ if self._menu:
+ self._menu.Destroy()
+
+ def GetHandler(self, evt_id):
+ """Get the event handler for the provided ID or None
+ @param evt_id: int
+ @return: callable or None
+
+ """
+ return self._handlers.get(evt_id, None)
+
+ def GetMenu(self):
+ """Get the menu that is being managed by this manager
+ @return: wxMenu
+
+ """
+ return self._menu
+
+ def GetPosition(self):
+ """Get the menu position
+ @return: tuple (int, int)
+
+ """
+ return self._pos
+
+ def GetUserData(self, key):
+ """Get user data
+ @param key: data id key
+
+ """
+ return self._userdata.get(key, None)
+
+ def SetMenu(self, menu):
+ """Set the menu that this manager should manage
+ @param menu: wxMenu
+
+ """
+ assert isinstance(menu, wx.Menu), "menu must be a wxMenu"
+ self._menu = menu
+
+ def SetPosition(self, pos):
+ """Set the menu position
+ @param pos: tuple (int, int)
+
+ """
+ self._pos = pos
+
+ def SetUserData(self, key, data):
+ """Add custom user data to the manager
+ @param key: unique key used to retrieve the data later
+ @param data: user data
+
+ """
+ self._userdata[key] = data
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/e_weblib.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/e_weblib.py
new file mode 100644
index 0000000..a079479
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/e_weblib.py
@@ -0,0 +1,100 @@
+###############################################################################
+# Name: weblib.py #
+# Purpose: Web an network utilties #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2010 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Buisness Model Library: Web Utilities
+
+Utility functions for working with web and other networking protocols
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: e_weblib.py 66131 2010-11-13 05:22:48Z CJP $"
+__revision__ = "$Revision: 66131 $"
+
+__all__ = ['SOAP12Message',]
+
+#-----------------------------------------------------------------------------#
+# imports
+import urllib2
+import httplib
+
+#-----------------------------------------------------------------------------#
+_SOAP_TPL = """<?xml version=\"1.0\" encoding=\"utf-8\"?>
+<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">
+<soap12:Body>
+ %(msg)s
+</soap12:Body>
+</soap12:Envelope>
+
+"""
+
+_SM_TPL = """<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope
+SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
+<SOAP-ENV:Body>
+ %(msg)s
+</SOAP-ENV:Body>
+</SOAP-ENV:Envelope>
+"""
+
+#-----------------------------------------------------------------------------#
+
+class SOAP12Message(object):
+ """Class for creating and sending a message
+ using the SOAP protocol.
+
+ """
+ def __init__(self, host, request, msg, action=""):
+ """Create the message object
+ @param host: host the message will be sent to (url)
+ @param request: POST request
+ @param msg: XML Body text
+ @keyword action: SoapAction
+
+ """
+ assert len(host), "Must specify a valid host"
+ super(SOAP12Message, self).__init__()
+
+ # Attributes
+ self._host = host
+ self._request = request
+ self._msg = msg
+ self._action = action
+ self._http = httplib.HTTP(self._host, 80)
+
+ @property
+ def MessageBody(self):
+ soapmsg = _SOAP_TPL % dict(msg=self._msg)
+ soapmsg = soapmsg.replace("\n", "\r\n")
+ return soapmsg
+
+ def Send(self):
+ """Send the message"""
+ # Create the SOAP message
+ soapmsg = self.MessageBody
+
+ # Setup Headers
+ self._http.putrequest("POST", self._request)
+ self._http.putheader("Host", self._host)
+# self._http.putheader("User-Agent", "Python post")
+ self._http.putheader("Content-Type", "application/soap+xml; charset=utf-8")
+ self._http.putheader("Content-Length", "%d" % len(soapmsg))
+ self._http.putheader("SOAPAction", '"%s"' % self._action)
+ self._http.endheaders()
+
+ # Send it
+ self._http.send(soapmsg)
+
+ def GetReply(self):
+ """Get the reply (may block for a long time)
+ @return: (statuscode, statusmessage, header)
+
+ """
+ return self._http.getreply()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/efilehist.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/efilehist.py
new file mode 100644
index 0000000..8684697
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/efilehist.py
@@ -0,0 +1,135 @@
+###############################################################################
+# Name: efilehist.py #
+# Purpose: Enhanced FileHistory #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model: EFileHistory
+
+Enhanced File History - Provides more consistent behavior than wxFileHistory
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: efilehist.py 71668 2012-06-06 18:32:07Z CJP $"
+__revision__ = "$Revision: 71668 $"
+
+__all__ = ['EFileHistory',]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import os
+import wx
+
+# Local Imports
+import txtutil
+
+#-----------------------------------------------------------------------------#
+
+class EFileHistory(object):
+ """FileHistory Menu Manager"""
+ def __init__(self, maxFile=9):
+ assert maxFile <= 9, "supports at most 9 files"
+ super(EFileHistory, self).__init__()
+
+ # Attributes
+ self._history = list()
+ self._maxFiles = maxFile
+ self._menu = None
+
+ def _UpdateMenu(self):
+ """Update the filehistory menu"""
+ menu = self.Menu # optimization
+ assert menu is not None
+ for item in menu.GetMenuItems():
+ menu.RemoveItem(item)
+
+ # Validate and cleanup any bad entries
+ to_remove = list()
+ for item in self.History:
+ if not item:
+ to_remove.append(item)
+ elif not os.path.exists(item):
+ to_remove.append(item)
+ for item in to_remove:
+ self.History.remove(item)
+
+ for index, histfile in enumerate(self.History):
+ menuid = wx.ID_FILE1 + index
+ if menuid <= wx.ID_FILE9:
+ menu.Append(menuid, histfile)
+ else:
+ break
+
+ Count = property(lambda self: self.GetCount())
+ History = property(lambda self: self._history,
+ lambda self, hist: self.SetHistory(hist))
+ MaxFiles = property(lambda self: self._maxFiles)
+ Menu = property(lambda self: self._menu,
+ lambda self, menu: self.UseMenu(menu))
+
+ def AddFileToHistory(self, fname):
+ """Add a file to the history
+ @param fname: Unicode
+
+ """
+ if not fname:
+ return
+ assert txtutil.IsUnicode(fname)
+ assert self.Menu is not None
+ # Shuffle to top of history if already in there
+ if fname in self.History:
+ self.History.remove(fname)
+ self.History.insert(0, fname)
+ # Maintain set length
+ if self.Count > self.MaxFiles:
+ self._history.pop()
+ # Update menu object for new history list
+ self._UpdateMenu()
+
+ def GetCount(self):
+ """Get the number of files in the history
+ @return: int
+
+ """
+ return len(self._history)
+
+ def GetHistoryFile(self, index):
+ """Get the history file at the given index
+ @param index: int
+ @return: Unicode
+
+ """
+ assert self.MaxFiles > index, "Index out of range"
+ return self.History[index]
+
+ def RemoveFileFromHistory(self, index):
+ """Remove a file from the history"""
+ assert self.MaxFiles > index, "Index out of range"
+ self.History.pop(index)
+ self._UpdateMenu()
+
+ def SetHistory(self, hist):
+ """Set the file history from a list
+ @param hist: list of Unicode
+
+ """
+ # Ensure list is unique
+ hist = list(set(hist))
+ assert len(hist) <= self.MaxFiles
+ self._history = hist
+ self._UpdateMenu()
+
+ def UseMenu(self, menu):
+ """Set the menu for the file history to use
+ @param menu: wx.Menu
+
+ """
+ assert isinstance(menu, wx.Menu)
+ if self.Menu is not None:
+ self._menu.Destroy()
+ self._menu = menu
+ self._UpdateMenu()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fchecker.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fchecker.py
new file mode 100644
index 0000000..4786cf5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fchecker.py
@@ -0,0 +1,89 @@
+###############################################################################
+# Name: fchecker.py #
+# Purpose: Filetype checker object. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Buisness Model Library: FileTypeChecker
+
+Helper class for checking what kind of a content a file contains.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: fchecker.py 65147 2010-07-31 05:59:58Z CJP $"
+__revision__ = "$Revision: 65147 $"
+
+__all__ = [ 'FileTypeChecker', ]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import os
+
+#-----------------------------------------------------------------------------#
+
+class FileTypeChecker(object):
+ """File type checker and recognizer"""
+ TXTCHARS = ''.join(map(chr, [7, 8, 9, 10, 12, 13, 27] + range(0x20, 0x100)))
+ ALLBYTES = ''.join(map(chr, range(256)))
+
+ def __init__(self, preread=4096):
+ """Create the FileTypeChecker
+ @keyword preread: number of bytes to read for checking file type
+
+ """
+ super(FileTypeChecker, self).__init__()
+
+ # Attributes
+ self._preread = preread
+
+ @staticmethod
+ def _GetHandle(fname):
+ """Get a file handle for reading
+ @param fname: filename
+ @return: file object or None
+
+ """
+ try:
+ handle = open(fname, 'rb')
+ except:
+ handle = None
+ return handle
+
+ def IsBinary(self, fname):
+ """Is the file made up of binary data
+ @param fname: filename to check
+ @return: bool
+
+ """
+ handle = self._GetHandle(fname)
+ if handle is not None:
+ bytes = handle.read(self._preread)
+ handle.close()
+ return self.IsBinaryBytes(bytes)
+ else:
+ return False
+
+ def IsBinaryBytes(self, bytes):
+ """Check if the given string is composed of binary bytes
+ @param bytes: string
+
+ """
+ nontext = bytes.translate(FileTypeChecker.ALLBYTES,
+ FileTypeChecker.TXTCHARS)
+ return bool(nontext)
+
+ def IsReadableText(self, fname):
+ """Is the given path readable as text. Will return True if the
+ file is accessable by current user and is plain text.
+ @param fname: filename
+ @return: bool
+
+ """
+ f_ok = False
+ if os.access(fname, os.R_OK):
+ f_ok = not self.IsBinary(fname)
+ return f_ok
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileimpl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileimpl.py
new file mode 100644
index 0000000..0130dfa
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileimpl.py
@@ -0,0 +1,226 @@
+###############################################################################
+# Name: Cody Precord #
+# Purpose: File Object Interface Implementation #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Business Model Library: FileObjectImpl
+
+Implementation of a file object interface class. Objects and methods inside
+of this library expect a file object that derives from this interface.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: fileimpl.py 70309 2012-01-10 00:09:26Z CJP $"
+__revision__ = "$Revision: 70309 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import sys
+
+# Editra Business Model Imports
+import txtutil
+import fileutil
+
+#--------------------------------------------------------------------------#
+
+class FileObjectImpl(object):
+ """File Object Interface implementation base class"""
+ def __init__(self, path=u'', modtime=0):
+ super(FileObjectImpl, self).__init__()
+
+ # Attributes
+ self._path = fileutil.GetPathFromURI(path)
+ self._modtime = modtime
+
+ self._handle = None
+ self.open = False
+
+ self.last_err = None
+
+ # Properties
+ Path = property(lambda self: self.GetPath(),
+ lambda self, path: self.SetPath(path))
+ Handle = property(lambda self: self._handle)
+ ModTime = property(lambda self: self.GetModTime(),
+ lambda self, tstamp: self.SetModTime(tstamp))
+ ReadOnly = property(lambda self: self.IsReadOnly())
+
+ def ClearLastError(self):
+ """Reset the error marker on this file"""
+ del self.last_err
+ self.last_err = None
+
+ def Clone(self):
+ """Clone the file object
+ @return: FileObject
+
+ """
+ fileobj = FileObjectImpl(self._path, self._modtime)
+ fileobj.SetLastError(self.last_err)
+ return fileobj
+
+ def Close(self):
+ """Close the file handle
+ @note: this is normally done automatically after a read/write operation
+
+ """
+ try:
+ self._handle.close()
+ except:
+ pass
+
+ self.open = False
+
+ def DoOpen(self, mode):
+ """Opens and creates the internal file object
+ @param mode: mode to open file in
+ @return: True if opened, False if not
+ @postcondition: self._handle is set to the open handle
+
+ """
+ if not len(self._path):
+ return False
+
+ try:
+ file_h = open(self._path, mode)
+ except (IOError, OSError), msg:
+ self.SetLastError(unicode(msg))
+ return False
+ else:
+ self._handle = file_h
+ self.open = True
+ return True
+
+ def Exists(self):
+ """Does the file exist on disk?
+ @return: bool
+
+ """
+ if self._path:
+ return fileutil.PathExists(self._path)
+ else:
+ return False
+
+ def GetExtension(self):
+ """Get the files extension if it has one else simply return the
+ filename minus the path.
+ @return: string file extension (no dot)
+
+ """
+ fname = os.path.split(self._path)
+ return fname[-1].split(os.extsep)[-1].lower()
+
+ def GetHandle(self):
+ """Get this files handle"""
+ return self._handle
+
+ def GetLastError(self):
+ """Return the last error that occurred when using this file
+ @return: err traceback or None
+
+ """
+ errstr = u"None"
+ if self.last_err:
+ if not txtutil.IsUnicode(self.last_err):
+ errstr = unicode(self.last_err)
+ else:
+ errstr = self.last_err
+ return errstr
+
+ def GetModTime(self):
+ """Get the timestamp of this files last modification"""
+ return self._modtime
+
+ def GetPath(self):
+ """Get the path of the file
+ @return: string
+
+ """
+ return self._path
+
+ def GetSize(self):
+ """Get the size of the file
+ @return: int
+
+ """
+ if self._path:
+ return fileutil.GetFileSize(self._path)
+ else:
+ return 0
+
+ def IsOpen(self):
+ """Check if file is open or not
+ @return: bool
+
+ """
+ return self.open
+
+ def IsReadOnly(self):
+ """Is the file Read Only
+ @return: bool
+
+ """
+ if os.path.exists(self._path):
+ return not os.access(self._path, os.R_OK|os.W_OK)
+ else:
+ return False
+
+ def ResetAll(self):
+ """Reset all file attributes"""
+ self._handle = None
+ self.open = False
+ self._path = u''
+ self._modtime = 0
+ self.last_err = None
+
+ def SetLastError(self, err):
+ """Set the last error
+ @param err: exception object / msg
+
+ """
+ self.last_err = err
+
+ def SetPath(self, path):
+ """Set the path of the file
+ @param path: absolute path to file
+
+ """
+ self._path = fileutil.GetPathFromURI(path)
+
+ def SetModTime(self, mtime):
+ """Set the modtime of this file
+ @param mtime: long int to set modtime to
+
+ """
+ self._modtime = mtime
+
+ #--- SHould be overridden by subclass ---#
+
+ def Read(self):
+ """Open/Read the file
+ @return: string (file contents)
+
+ """
+ txt = u''
+ if self.DoOpen('rb'):
+ try:
+ txt = self._handle.read()
+ except:
+ pass
+
+ return txt
+
+ def Write(self, value):
+ """Open/Write the value to disk
+ @param value: string
+
+ """
+ if self.DoOpen('wb'):
+ self._handle.write(value)
+ self._handle.close()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileutil.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileutil.py
new file mode 100644
index 0000000..cc0b43f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileutil.py
@@ -0,0 +1,453 @@
+###############################################################################
+# Name: fileutil.py #
+# Purpose: File Management Utilities. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: File Utilities
+
+Utility functions for managing and working with files.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: fileutil.py 71689 2012-06-07 18:55:45Z CJP $"
+__revision__ = "$Revision: 71689 $"
+
+__all__ = [ 'GetAbsPath', 'GetFileExtension', 'GetFileModTime', 'GetFileName',
+ 'GetFileSize', 'GetPathName', 'GetPathFromURI', 'GetUniqueName',
+ 'IsLink', 'MakeNewFile', 'MakeNewFolder', 'PathExists',
+ 'ResolveRealPath', 'IsExecutable', 'Which', 'ComparePaths',
+ 'AddFileExtension', 'GetDirectoryObject', 'File', 'Directory',
+ 'GetFileManagerCmd', 'OpenWithFileManager', 'IsHidden', 'IsSubPath' ]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import ctypes
+import os
+import platform
+import urllib2
+import stat
+import subprocess
+
+UNIX = WIN = False
+if wx.Platform == '__WXMSW__':
+ WIN = True
+ try:
+ # Check for if win32 extensions are available
+ import win32com.client as win32client
+ except ImportError:
+ win32client = None
+
+ try:
+ # Check for win32api
+ import win32api
+ except ImportError:
+ win32api = None
+else:
+ UNIX = True
+
+#-----------------------------------------------------------------------------#
+
+def uri2path(func):
+ """Decorator method to convert path arguments that may be uri's to
+ real file system paths. Arg 0 must be a file path or uri.
+
+ """
+ def WrapURI(*args, **kwargs):
+ args = list(args)
+ args[0] = GetPathFromURI(args[0])
+ return func(*args, **kwargs)
+
+ WrapURI.__name__ = func.__name__
+ WrapURI.__doc__ = func.__doc__
+ return WrapURI
+
+#-----------------------------------------------------------------------------#
+
+def AddFileExtension(path, ext):
+ """Add a file extension to a path if it doesn't already exist
+ @param path: file path
+ @param ext: file extension
+
+ """
+ assert isinstance(ext, basestring)
+ if not ext.startswith('.'):
+ ext = '.' + ext
+ if not path.endswith(ext):
+ path = path + ext
+ return path
+
+def ComparePaths(path1, path2):
+ """Determine whether the two given paths are equivalent
+ @param path1: unicode
+ @param path2: unicode
+ @return: bool
+
+ """
+ path1 = GetAbsPath(path1)
+ path2 = GetAbsPath(path2)
+ if WIN:
+ path1 = path1.lower()
+ path2 = path2.lower()
+ return path1 == path2
+
+def CopyFile(orig, dest):
+ """Copy the given file to the destination
+ @param orig: file to copy (full path)
+ @param dest: where to copy to
+
+ """
+ raise NotImplementedError
+
+@uri2path
+def GetAbsPath(path):
+ """Get the absolute path of a file of a file.
+ @param path: string
+ @return: string
+ @note: on windows if win32api is available short notation paths will be
+ converted to the proper long name.
+
+ """
+ rpath = os.path.abspath(path)
+ # Resolve short path notation on Windows when possible
+ if WIN and win32api is not None and u"~" in rpath:
+ try:
+ rpath = win32api.GetLongPathNameW(rpath)
+ except Exception:
+ # Ignore errors from win32api calls
+ pass
+ return rpath
+
+def GetFileExtension(file_str):
+ """Gets last atom at end of string as extension if
+ no extension whole string is returned
+ @param file_str: path or file name to get extension from
+
+ """
+ return file_str.split('.')[-1]
+
+def GetFileModTime(file_name):
+ """Returns the time that the given file was last modified on
+ @param file_name: path of file to get mtime of
+
+ """
+ try:
+ mod_time = os.path.getmtime(file_name)
+ except (OSError, EnvironmentError):
+ mod_time = 0
+ return mod_time
+
+def GetFileName(path):
+ """Gets last atom on end of string as filename
+ @param path: full path to get filename from
+
+ """
+ return os.path.split(path)[-1]
+
+@uri2path
+def GetFileSize(path):
+ """Get the size of the file at a given path
+ @param path: Path to file
+ @return: long
+
+ """
+ try:
+ return os.stat(path)[stat.ST_SIZE]
+ except:
+ return 0
+
+def GetPathFromURI(path):
+ """Get a local path from a file:// uri
+ @return: normalized path
+
+ """
+ if path.startswith(u"file:"):
+ path = path.replace(u"file:", u"")
+ path = path.lstrip(u"/")
+ if platform.system().lower() in ('windows', 'microsoft'):
+ path = path.replace(u"/", u"\\")
+ if len(path) >= 2 and path[1] != u':':
+ # A valid windows file uri should start with the drive
+ # letter. If not make the assumption that it should be
+ # the C: drive.
+ path = u"C:\\\\" + path
+ else:
+ path = u"/" + path
+ path = urllib2.unquote(path)
+
+ return path
+
+@uri2path
+def GetPathName(path):
+ """Gets the path minus filename
+ @param path: full path to get base of
+
+ """
+ return os.path.split(path)[0]
+
+@uri2path
+def IsLink(path):
+ """Is the file a link
+ @return: bool
+
+ """
+ if WIN:
+ return path.endswith(".lnk") or os.path.islink(path)
+ else:
+ return os.path.islink(path)
+
+def IsSubPath(path1, path2):
+ """Is path1 a subpath of path2
+ i.e) /usr/bin/foo is a subpath of /usr/bin
+ @return: bool
+
+ """
+ if WIN:
+ path1 = path1.lower()
+ path2 = path2.lower()
+ path1 = GetAbsPath(path1)
+ path2 = GetAbsPath(path2)
+ return path1.startswith(path2)
+
+@uri2path
+def IsHidden(path):
+ """Is the path a hidden path
+ @param path: path to check
+ @return: bool
+
+ """
+ bHidden = False
+ if PathExists(path):
+ if WIN:
+ try:
+ attrs = ctypes.windll.kernel32.GetFileAttributesW(path)
+ assert attrs != -1
+ bHidden = bool(attrs & 2)
+ except (AttributeError, AssertionError):
+ bHidden = False
+ else:
+ dname = GetFileName(path)
+ bHidden = dname.startswith('.')
+ return bHidden
+
+@uri2path
+def PathExists(path):
+ """Does the path exist.
+ @param path: file path or uri
+ @return: bool
+
+ """
+ return os.path.exists(path)
+
+@uri2path
+def IsExecutable(path):
+ """Is the file at the given path an executable file
+ @param path: file path
+ @return: bool
+
+ """
+ return os.path.isfile(path) and os.access(path, os.X_OK)
+
+@uri2path
+def ResolveRealPath(link):
+ """Return the real path of the link file
+ @param link: path of link file
+ @return: string
+
+ """
+ assert IsLink(link), "ResolveRealPath expects a link file!"
+ realpath = link
+ if WIN and win32client is not None:
+ shell = win32client.Dispatch("WScript.Shell")
+ shortcut = shell.CreateShortCut(link)
+ realpath = shortcut.Targetpath
+ else:
+ realpath = os.path.realpath(link)
+ return realpath
+
+def GetFileManagerCmd():
+ """Get the file manager open command for the current os. Under linux
+ it will check for xdg-open, nautilus, konqueror, and Thunar, it will then
+ return which one it finds first or 'nautilus' it finds nothing.
+ @return: string
+
+ """
+ if wx.Platform == '__WXMAC__':
+ return 'open'
+ elif wx.Platform == '__WXMSW__':
+ return 'explorer'
+ else:
+ # Check for common linux filemanagers returning first one found
+ # Gnome/ubuntu KDE/kubuntu xubuntu
+ for cmd in ('xdg-open', 'nautilus', 'konqueror', 'Thunar'):
+ result = os.system("which %s > /dev/null" % cmd)
+ if result == 0:
+ return cmd
+ else:
+ return 'nautilus'
+
+def OpenWithFileManager(path):
+ """Open the given path with the systems file manager
+ @param path: file/directory path
+
+ """
+ cmd = GetFileManagerCmd()
+ subprocess.call([cmd, path])
+
+def Which(program):
+ """Find the path of the given executable
+ @param program: executable name (i.e 'python')
+ @return: executable path or None
+
+ """
+ # Check local directory first
+ if IsExecutable(program):
+ return program
+ else:
+ # Start looking on the $PATH
+ for path in os.environ["PATH"].split(os.pathsep):
+ exe_file = os.path.join(path, program)
+ if IsExecutable(exe_file):
+ return exe_file
+ return None
+
+def GetDirectoryObject(path, recurse=True, includedot=False):
+ """Gets a L{Directory} object representing the filesystem of the
+ given path.
+ @param path: base path to list
+ @keyword recurse: recurse into subdirectories
+ @keyword includedot: include '.' files
+ @return: L{Directory} object instance
+
+ """
+ assert os.path.isdir(path)
+ def _BuildDir(thedir):
+ dirAddFile = thedir.Files.append
+ isdir = os.path.isdir
+ pjoin = os.path.join
+ for fname in os.listdir(thedir.Path):
+ if not includedot and fname.startswith('.'):
+ continue
+ fpath = pjoin(thedir.Path, fname)
+ if isdir(fpath):
+ newobj = Directory(fpath)
+ if recurse:
+ _BuildDir(newobj)
+ else:
+ newobj = File(fpath)
+ dirAddFile(newobj)
+
+ dobj = Directory(path)
+ _BuildDir(dobj)
+ return dobj
+
+#-----------------------------------------------------------------------------#
+
+class File(object):
+ """Basic file data structure"""
+ __slots__ = ('path', 'modtime')
+ def __init__(self, path):
+ super(File, self).__init__()
+
+ self.path = path
+ self.modtime = GetFileModTime(self.path)
+
+ Path = property(lambda self: self.path)
+ Name = property(lambda self: os.path.basename(self.Path))
+ ModTime = property(lambda self: self.modtime,
+ lambda self, mod: setattr(self, 'modtime', mod))
+
+ def __str__(self):
+ return self.Path
+
+ def __eq__(self, other):
+ assert isinstance(other, File)
+ return ComparePaths(self.Path, other.Path)
+
+class Directory(File):
+ """Basic directory data structure.
+ Is a container class that provides a simple in memory representation of
+ a file system.
+
+ """
+ __slots__ = ('files',)
+ def __init__(self, path):
+ super(Directory, self).__init__(path)
+
+ self.files = list()
+
+ Files = property(lambda self: self.files)
+
+#-----------------------------------------------------------------------------#
+
+def GetUniqueName(path, name):
+ """Make a file name that will be unique in case a file of the
+ same name already exists at that path.
+ @param path: Root path to folder of files destination
+ @param name: desired file name base
+ @return: string
+
+ """
+ tmpname = os.path.join(path, name)
+ if os.path.exists(tmpname):
+ if '.' not in name:
+ ext = ''
+ fbase = name
+ else:
+ ext = '.' + name.split('.')[-1]
+ fbase = name[:-1 * len(ext)]
+
+ inc = len([x for x in os.listdir(path) if x.startswith(fbase)])
+ tmpname = os.path.join(path, "%s-%d%s" % (fbase, inc, ext))
+ while os.path.exists(tmpname):
+ inc = inc + 1
+ tmpname = os.path.join(path, "%s-%d%s" % (fbase, inc, ext))
+
+ return tmpname
+
+
+#-----------------------------------------------------------------------------#
+
+def MakeNewFile(path, name):
+ """Make a new file at the given path with the given name.
+ If the file already exists, the given name will be changed to
+ a unique name in the form of name + -NUMBER + .extension
+ @param path: path to directory to create file in
+ @param name: desired name of file
+ @return: Tuple of (success?, Path of new file OR Error message)
+
+ """
+ if not os.path.isdir(path):
+ path = os.path.dirname(path)
+ fname = GetUniqueName(path, name)
+
+ try:
+ open(fname, 'w').close()
+ except (IOError, OSError), msg:
+ return (False, str(msg))
+
+ return (True, fname)
+
+def MakeNewFolder(path, name):
+ """Make a new folder at the given path with the given name.
+ If the folder already exists, the given name will be changed to
+ a unique name in the form of name + -NUMBER.
+ @param path: path to create folder on
+ @param name: desired name for folder
+ @return: Tuple of (success?, new dirname OR Error message)
+
+ """
+ if not os.path.isdir(path):
+ path = os.path.dirname(path)
+ folder = GetUniqueName(path, name)
+ try:
+ os.mkdir(folder)
+ except (OSError, IOError), msg:
+ return (False, str(msg))
+
+ return (True, folder)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/histcache.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/histcache.py
new file mode 100644
index 0000000..3bb0736
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/histcache.py
@@ -0,0 +1,262 @@
+###############################################################################
+# Name: histcache.py #
+# Purpose: History Cache #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Buisness Model Library: HistoryCache
+
+History cache that acts as a stack for managing a history list o
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: histcache.py 67123 2011-03-04 00:02:35Z CJP $"
+__revision__ = "$Revision: 67123 $"
+
+__all__ = [ 'HistoryCache', 'HIST_CACHE_UNLIMITED',
+ 'CycleCache']
+
+#-----------------------------------------------------------------------------#
+# Imports
+
+#-----------------------------------------------------------------------------#
+# Globals
+HIST_CACHE_UNLIMITED = -1
+
+#-----------------------------------------------------------------------------#
+
+class HistoryCache(object):
+ """Data management cache.
+ Maintains a positional list of objects that remembers the last access
+ position in the cache.
+
+ """
+ def __init__(self, max_size=HIST_CACHE_UNLIMITED):
+ """@param max_size: size of history cache (int)"""
+ super(HistoryCache, self).__init__()
+
+ # Attributes
+ self._list = list()
+ self.cpos = -1
+ self.max_size = max_size
+
+ def _Resize(self):
+ """Adjust cache size based on max size setting"""
+ if self.max_size != HIST_CACHE_UNLIMITED:
+ lsize = len(self._list)
+ if lsize:
+ adj = self.max_size - lsize
+ if adj < 0:
+ self._list.pop(0)
+ self.cpos = len(self._list) - 1
+
+ def Clear(self):
+ """Clear the history cache"""
+ del self._list
+ self._list = list()
+ self.cpos = -1
+
+ def GetSize(self):
+ """Get the current size of the cache
+ @return: int (number of items in the cache)
+
+ """
+ return len(self._list)
+
+ def GetMaxSize(self):
+ """Get the max size of the cache
+ @return: int
+
+ """
+ return self.max_size
+
+ def GetNextItem(self):
+ """Get the next item in the history cache, moving the
+ current position towards the end of the cache.
+ @return: object or None if at end of list
+
+ """
+ item = None
+ if self.cpos < len(self._list) - 1:
+ self.cpos += 1
+ item = self._list[self.cpos]
+ return item
+
+ def GetPreviousItem(self):
+ """Get the previous item in the history cache, moving the
+ current position towards the beginning of the cache.
+ @return: object or None if at start of list
+
+ """
+ item = None
+ if self.cpos >= 0 and len(self._list) > 0:
+ if self.cpos == len(self._list):
+ self.cpos -= 1
+ item = self._list[self.cpos]
+ self.cpos -= 1
+ return item
+
+ def HasPrevious(self):
+ """Are there more items to the left of the current position
+ @return: bool
+
+ """
+ llen = len(self._list)
+ more = ((self.cpos >= 0) and llen and (self.cpos < llen))
+ return more
+
+ def HasNext(self):
+ """Are there more items to the right of the current position
+ @return: bool
+
+ """
+ if self.cpos == -1 and len(self._list):
+ more = True
+ else:
+ more = self.cpos >= 0 and self.cpos < (len(self._list) - 1)
+ return more
+
+ def PeekNext(self):
+ """Return the next item in the cache without modifying the
+ currently managed position.
+ @return: cache object
+
+ """
+ if self.HasNext():
+ return self._list[self.cpos+1]
+ else:
+ return None
+
+ def PeekPrevious(self):
+ """Return the previous item in the cache without modifying the
+ currently managed position.
+ @return: cache object
+
+ """
+ if self.HasPrevious():
+ return self._list[self.cpos]
+ else:
+ return None
+
+ def PutItem(self, item):
+ """Put an item on the top of the cache
+ @param item: object
+
+ """
+ if self.cpos != len(self._list) - 1:
+ self._list = self._list[:self.cpos]
+ self._list.append(item)
+ self.cpos += 1
+ self._Resize()
+
+ def SetMaxSize(self, max_size):
+ """Set the maximum size of the cache
+ @param max_size: int (HIST_CACHE_UNLIMITED for unlimited size)
+
+ """
+ assert max_size > 0 or max_size == 1, "Invalid max size"
+ self.max_size = max_size
+ self._Resize()
+
+#-----------------------------------------------------------------------------#
+
+class CycleCache(object):
+ """A simple circular cache. All items are added to the end of the cache
+ regardless of the current reference position. As items are accessed from
+ the cache the cache reference pointer is incremented, if it passes the
+ end it will go back to the beginning.
+
+ """
+ def __init__(self, size):
+ """Initialize the cache.
+ @param size: cache size
+
+ """
+ super(CycleCache, self).__init__()
+
+ # Attributes
+ self._list = list()
+ self._cpos = -1
+ self._size = size
+
+ def __len__(self):
+ return len(self._list)
+
+ def NextIndex(self):
+ """Get the next index in the cache
+ @return: int
+
+ """
+ idx = self._cpos
+ idx -= 1
+ if abs(idx) > len(self._list):
+ idx = -1
+ return idx
+
+ def Clear(self):
+ """Clear the cache"""
+ del self._list
+ self._list = list()
+
+ def GetCurrentSize(self):
+ """Get the size of the cache
+ @return: int
+
+ """
+ return len(self._list)
+
+ def GetNext(self):
+ """Get the next item in the cache and increment the
+ current position.
+ @return: object
+
+ """
+ item = None
+ if len(self._list):
+ item = self._list[self._cpos]
+ self._cpos = self.NextIndex()
+ return item
+
+ def PeekNext(self):
+ """Look the next item in the cache
+ @return: object
+
+ """
+ item = None
+ if abs(self._cpos) < len(self._list):
+ item = self._list[self._cpos]
+ return item
+
+ def PeekPrev(self):
+ """Look the next item in the cache
+ @return: object
+
+ """
+ idx = self._cpos + 1
+ if idx == 0:
+ idx = -1 * len(self._list)
+
+ llen = len(self._list)
+ if llen and abs(idx) <= llen:
+ item = self._list[idx]
+ else:
+ item = None
+ return item
+
+ def PutItem(self, item):
+ """Put an item in the cache
+ @param item: object
+
+ """
+ llen = len(self._list)
+ if llen and (llen == self._size):
+ del self._list[0]
+ self._list.append(item)
+
+ def Reset(self):
+ """Reset the list reference pointer"""
+ self._cpos = -1
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/logfile.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/logfile.py
new file mode 100644
index 0000000..ce5f4a4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/logfile.py
@@ -0,0 +1,104 @@
+###############################################################################
+# Name: Cody Precord #
+# Purpose: Log File #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2010 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Business Model Library: LogFile
+
+Log file class for managing log files or other transient files that should
+be purged after a given period of time.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: logfile.py 66868 2011-02-09 16:01:49Z CJP $"
+__revision__ = "$Revision: 66868 $"
+
+__all__ = ['LogFile',]
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import time
+import datetime
+import re
+import tempfile
+
+#--------------------------------------------------------------------------#
+
+class LogFile(object):
+ """Log file class"""
+ def __init__(self, prefix, logdir=None):
+ """Create a log file
+ @param prefix: filename prefix
+ @keyword logdir: abs path to log output dir
+ @note: if logdir is None then the system temp directory will be used
+
+ """
+ super(LogFile, self).__init__()
+
+ # Attributes
+ self.prefix = prefix
+ self.logdir = logdir
+
+ # Setup
+ if self.logdir is None:
+ self.logdir = tempfile.gettempdir()
+
+ #---- Properties ----#
+ LogDirectory = property(lambda self: self.logdir,
+ lambda self, dname: setattr(self, 'logdir', dname))
+ Prefix = property(lambda self: self.prefix,
+ lambda self, prefix: setattr(self, 'prefix', prefix))
+
+ #---- Public Interface ----#
+ def WriteMessage(self, msg):
+ """Append the message to the current log file
+ @param msg: string object
+
+ """
+ # Files are named as prefix_YYYY_MM_DD.log
+ logstamp = "%d_%d_%d" % time.localtime()[:3]
+ logname = "%s_%s.log" % (self.prefix, logstamp)
+ logpath = os.path.join(self.logdir, logname)
+ if os.path.exists(logpath):
+ opencmd = "ab"
+ else:
+ opencmd = "wb"
+
+# with open(logpath, opencmd) as handle:
+# handle.write(msg.rstrip() + os.linesep)
+ try:
+ handle = open(logpath, opencmd)
+ handle.write(msg.rstrip() + os.linesep)
+ handle.close()
+ except IOError:
+ pass
+
+ def PurgeOldLogs(self, days):
+ """Purge all log files older than n days
+ @param days: number of days
+
+ """
+ logpattern = re.compile("%s_[0-9]{4}_[0-9]{1,2}_[0-9]{1,2}.log" % self.prefix)
+ paths = list()
+ cdate = datetime.date(*time.localtime()[:3])
+ for path in os.listdir(self.logdir):
+ if logpattern.match(path):
+ ymd = [int(x) for x in path[len(self.prefix)+1:-4].split('_')]
+ fdate = datetime.date(*ymd)
+ span = cdate - fdate
+ if span.days > days:
+ fpath = os.path.join(self.logdir, path)
+ paths.append(fpath)
+
+ # Attempt to cleanup the old files
+ for log in paths:
+ try:
+ os.remove(log)
+ except OSError:
+ pass
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/miscutil.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/miscutil.py
new file mode 100644
index 0000000..88e9349
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/miscutil.py
@@ -0,0 +1,52 @@
+###############################################################################
+# Name: miscutil.py #
+# Purpose: Various helper functions. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: MiscUtil
+
+Various helper functions
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: miscutil.py 67329 2011-03-28 23:40:48Z CJP $"
+__revision__ = "$Revision: 67329 $"
+
+__all__ = [ 'MinMax', 'Singleton']
+
+#-----------------------------------------------------------------------------#
+# Imports
+
+#-----------------------------------------------------------------------------#
+
+class Singleton(type):
+ """Singleton metaclass for creating singleton classes
+ @note: class being applied to must have a SetupWindow method
+
+ """
+ def __init__(cls, name, bases, dict):
+ super(Singleton, cls).__init__(name, bases, dict)
+ cls.instance = None
+
+ def __call__(cls, *args, **kw):
+ if not cls.instance:
+ # Not created or has been Destroyed
+ obj = super(Singleton, cls).__call__(*args, **kw)
+ cls.instance = obj
+
+ return cls.instance
+
+#-----------------------------------------------------------------------------#
+
+def MinMax(arg1, arg2):
+ """Return an ordered tuple of the minimum and maximum value
+ of the two args.
+ @return: tuple
+
+ """
+ return min(arg1, arg2), max(arg1, arg2)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/osutil.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/osutil.py
new file mode 100644
index 0000000..e6d98a3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/osutil.py
@@ -0,0 +1,129 @@
+###############################################################################
+# Name: osutil.py #
+# Purpose: Text Utilities. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2010 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: Operating System Utilities
+
+Utilities for handling OS related interactions.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: $"
+__revision__ = "$Revision: $"
+
+__all__ = ['InstallTermHandler',
+ 'GetWindowsDrives', 'GetWindowsDriveType',
+ 'GenericDrive', 'FixedDrive', 'CDROMDrive', 'RamDiskDrive', 'RemoteDrive',
+ 'RemovableDrive' ]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import ctypes
+import signal
+import collections
+
+HASWIN32 = False
+if wx.Platform == '__WXMSW__':
+ try:
+ import win32api
+ except ImportError:
+ HASWIN32 = False
+ else:
+ HASWIN32 = True
+
+#-----------------------------------------------------------------------------#
+# Windows Drive Utilities
+
+class GenericDrive(object):
+ def __init__(self, name):
+ super(GenericDrive, self).__init__()
+
+ # Attributes
+ self._name = name
+
+ Name = property(lambda self: self._name,
+ lambda self, v: setattr(self, '_name', v))
+
+class RemovableDrive(GenericDrive):
+ pass
+class FixedDrive(GenericDrive):
+ pass
+class RemoteDrive(GenericDrive):
+ pass
+class CDROMDrive(GenericDrive):
+ pass
+class RamDiskDrive(GenericDrive):
+ pass
+
+def GetWindowsDrives():
+ """Get a list of all available windows drives
+ @return: list of strings
+
+ """
+ assert wx.Platform == '__WXMSW__', "Windows Only API Method"
+ drives = list()
+ try:
+ dletters = list()
+ bmask = ctypes.windll.kernel32.GetLogicalDrives()
+ for dletter in u"ABCDEFGHIJKLMNOPQRSTUVWXYZ":
+ if bmask & 1:
+ dletters.append(dletter)
+ bmask >>= 1
+
+ for dletter in dletters:
+ dname = dletter + u":\\"
+ dtype = GetWindowsDriveType(dname)
+ if type(dtype) != GenericDrive:
+ drives.append(dtype)
+ except Exception, err:
+ pass
+ return drives
+
+def GetWindowsDriveType(dname):
+ """Get the drive type for the given letter"""
+ assert wx.Platform == '__WXMSW__', "Windows Only API Method"
+ dtype = GenericDrive(dname)
+ try:
+ dtypes = [None, None, RemovableDrive, FixedDrive, RemoteDrive, CDROMDrive, RamDiskDrive]
+ idx = ctypes.windll.kernel32.GetDriveTypeW(dname)
+ if idx < len(dtypes):
+ drive = dtypes[idx]
+ if drive:
+ dtype = drive(dname)
+ except:
+ pass
+ return dtype
+
+#-----------------------------------------------------------------------------#
+
+def InstallTermHandler(callback, *args, **kwargs):
+ """Install exit app handler for sigterm (unix/linux)
+ and uses SetConsoleCtrlHandler on Windows.
+ @param callback: callable(*args, **kwargs)
+ @param args: positional arguments to pass to callback
+ @param kwargs: keyword arguments to pass to callback
+ @return: bool (installed or not)
+
+ """
+ assert isinstance(callback, collections.Callable), "callback must be callable!"
+
+ installed = True
+ if wx.Platform == '__WXMSW__':
+ if HASWIN32:
+ win32api.SetConsoleCtrlHandler(lambda dummy : callback(*args, **kwargs),
+ True)
+ else:
+ installed = False
+ else:
+ signal.signal(signal.SIGTERM,
+ lambda signum, frame : callback(*args, **kwargs))
+
+ return installed
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/searcheng.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/searcheng.py
new file mode 100644
index 0000000..cecf67c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/searcheng.py
@@ -0,0 +1,418 @@
+###############################################################################
+# Name: searcheng.py #
+# Purpose: Text search engine and utilities #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: SearchEngine
+
+Text Search Engine for finding text and grepping files
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: searcheng.py 70206 2011-12-30 20:41:02Z CJP $"
+__revision__ = "$Revision: 70206 $"
+
+__all__ = [ 'SearchEngine', ]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import os
+import re
+import fnmatch
+import types
+import unicodedata
+from StringIO import StringIO
+
+# Local imports
+import fchecker
+
+#-----------------------------------------------------------------------------#
+
+class SearchEngine(object):
+ """Text Search Engine
+ All Search* methods are iterable generators
+ All Find* methods do a complete search and return the match collection
+ @summary: Text Search Engine
+ @todo: Add file filter support
+
+ """
+ def __init__(self, query, regex=True, down=True,
+ matchcase=True, wholeword=False):
+ """Initialize a search engine object
+ @param query: search string
+ @keyword regex: Is a regex search
+ @keyword down: Search down or up
+ @keyword matchcase: Match case
+ @keyword wholeword: Match whole word
+
+ """
+ super(SearchEngine, self).__init__()
+
+ # Attributes
+ self._isregex = regex
+ self._next = down
+ self._matchcase = matchcase
+ self._wholeword = wholeword
+ self._query = query
+ self._regex = u''
+ self._pool = u''
+ self._lmatch = None # Last match object
+ self._filters = None # File Filters
+ self._formatter = lambda f, l, m: u"%s %d: %s" % (f, l+1, m)
+ self._CompileRegex()
+
+ def _CompileRegex(self):
+ """Prepare and compile the regex object based on the current state
+ and settings of the engine.
+ @postcondition: the engines regular expression is created
+
+ """
+ tmp = self._query
+
+ uquery = type(tmp) is types.UnicodeType
+ upool = type(self._pool) is types.UnicodeType
+ if uquery and upool:
+ tmp = unicodedata.normalize("NFC", tmp)
+
+ if not self._isregex:
+ tmp = re.escape(tmp)
+
+ if self._wholeword:
+ if uquery:
+ tmp = u"\\b%s\\b" % tmp
+ else:
+ tmp = "\\b%s\\b" % tmp
+
+ flags = re.MULTILINE
+ if not self._matchcase:
+ flags |= re.IGNORECASE
+
+ if upool:
+ flags |= re.UNICODE
+ # Normalize
+ self._pool = unicodedata.normalize("NFC", self._pool)
+ else:
+ # If the pools is not Unicode also make sure that the
+ # query is a string too.
+ if uquery:
+ try:
+ tmp = tmp.encode('utf-8')
+ except UnicodeEncodeError:
+ # TODO: better error reporting about encoding issue
+ self._regex = None
+ return
+ try:
+ self._regex = re.compile(tmp, flags)
+ except:
+ self._regex = None
+ self._data = (tmp, self._pool)
+
+ def ClearPool(self):
+ """Clear the search pool"""
+ del self._pool
+ self._pool = u""
+
+ def Find(self, spos=0):
+ """Find the next match based on the state of the search engine
+ @keyword spos: search start position
+ @return: tuple (match start pos, match end pos) or None if no match
+ @note: L{SetSearchPool} has been called to set search string
+
+ """
+ if self._regex is None:
+ return None
+
+ if self._next:
+ return self.FindNext(spos)
+ else:
+ if spos == 0:
+ spos = -1
+ return self.FindPrev(spos)
+
+ def FindAll(self):
+ """Find all the matches in the current context
+ @return: list of tuples [(start1, end1), (start2, end2), ]
+
+ """
+ if self._regex is None:
+ return list()
+
+ matches = [match for match in self._regex.finditer(self._pool)]
+ return matches
+
+ def FindAllLines(self):
+ """Find all the matches in the current context
+ @return: list of strings
+
+ """
+ rlist = list()
+ if self._regex is None:
+ return rlist
+
+ for lnum, line in enumerate(StringIO(self._pool)):
+ if self._regex.search(line) is not None:
+ rlist.append(self._formatter(u"Untitled", lnum, line))
+
+ return rlist
+
+ def FindNext(self, spos=0):
+ """Find the next match of the query starting at spos
+ @keyword spos: search start position in string
+ @return: tuple (match start pos, match end pos) or None if no match
+ @note: L{SetSearchPool} has been called to set the string to search in.
+
+ """
+ if self._regex is None:
+ return None
+
+ if spos < len(self._pool):
+ match = self._regex.search(self._pool[spos:])
+ if match is not None:
+ self._lmatch = match
+ return match.span()
+ return None
+
+ def FindPrev(self, spos=-1):
+ """Find the previous match of the query starting at spos
+ @keyword spos: search start position in string
+ @return: tuple (match start pos, match end pos)
+
+ """
+ if self._regex is None:
+ return None
+
+ if spos+1 < len(self._pool):
+ matches = [match for match in
+ self._regex.finditer(self._pool[:spos])]
+ if len(matches):
+ lmatch = matches[-1]
+ self._lmatch = lmatch
+ return (lmatch.start(), lmatch.end())
+ return None
+
+ def GetLastMatch(self):
+ """Get the last found match object from the previous L{FindNext} or
+ L{FindPrev} action.
+ @return: match object or None
+
+ """
+ return self._lmatch
+
+ def GetOptionsString(self):
+ """Get a string describing the search engines options"""
+ rstring = u"\"%s\" [ " % self._query
+ for desc, attr in (("regex: %s", self._isregex),
+ ("match case: %s", self._matchcase),
+ ("whole word: %s", self._wholeword)):
+ if attr:
+ rstring += (desc % u"on; ")
+ else:
+ rstring += (desc % u"off; ")
+ rstring += u"]"
+
+ return rstring
+
+ def GetQuery(self):
+ """Get the raw query string used by the search engine
+ @return: string
+
+ """
+ return self._query
+
+ def GetQueryObject(self):
+ """Get the regex object used for the search. Will return None if
+ there was an error in creating the object.
+ @return: pattern object
+
+ """
+ return self._regex
+
+ def GetSearchPool(self):
+ """Get the search pool string for this L{SearchEngine}.
+ @return: string
+
+ """
+ return self._pool
+
+ def IsMatchCase(self):
+ """Is the engine set to a case sensitive search
+ @return: bool
+
+ """
+ return self._matchcase
+
+ def IsRegEx(self):
+ """Is the engine searching with the query as a regular expression
+ @return: bool
+
+ """
+ return self._isregex
+
+ def IsWholeWord(self):
+ """Is the engine set to search for wholeword matches
+ @return: bool
+
+ """
+ return self._wholeword
+
+ def SearchInBuffer(self, sbuffer):
+ """Search in the buffer
+ @param sbuffer: buffer like object
+ @todo: implement
+
+ """
+ raise NotImplementedError
+
+ def SearchInDirectory(self, directory, recursive=True):
+ """Search in all the files found in the given directory
+ @param directory: directory path
+ @keyword recursive: search recursivly
+
+ """
+ if self._regex is None:
+ return
+
+ # Get all files in the directories
+ paths = [os.path.join(directory, fname)
+ for fname in os.listdir(directory) if not fname.startswith('.')]
+
+ # Filter out files that don't match the current filter(s)
+ if self._filters is not None and len(self._filters):
+ filtered = list()
+ for fname in paths:
+ if os.path.isdir(fname):
+ filtered.append(fname)
+ continue
+
+ for pat in self._filters:
+ if fnmatch.fnmatch(fname, pat):
+ filtered.append(fname)
+ paths = filtered
+
+ # Begin searching in the paths
+ for path in paths:
+ if recursive and os.path.isdir(path):
+ # Recursive call to decend into directories
+ for match in self.SearchInDirectory(path, recursive):
+ yield match
+ else:
+ for match in self.SearchInFile(path):
+ yield match
+ return
+
+ def SearchInFile(self, fname):
+ """Search in a file for all lines with matches of the set query and
+ yield the results as they are found.
+ @param fname: filename
+ @todo: unicode handling
+
+ """
+ if self._regex is None:
+ return
+
+ checker = fchecker.FileTypeChecker()
+ if checker.IsReadableText(fname):
+ try:
+ fobj = open(fname, 'rb')
+ except (IOError, OSError):
+ return
+ else:
+ # Special token to signify start of a search
+ yield (None, fname)
+
+ for lnum, line in enumerate(fobj):
+ if self._regex.search(line) is not None:
+ yield self._formatter(fname, lnum, line)
+ fobj.close()
+ return
+
+ def SearchInFiles(self, flist):
+ """Search in a list of files and yield results as they are found.
+ @param flist: list of file names
+
+ """
+ if self._regex is None:
+ return
+
+ for fname in flist:
+ for match in self.SearchInFile(fname):
+ yield match
+ return
+
+ def SearchInString(self, sstring, startpos=0):
+ """Search in a string
+ @param sstring: string to search in
+ @keyword startpos: search start position
+
+ """
+ raise NotImplementedError
+
+ def SetFileFilters(self, filters):
+ """Set the file filters to specify what type of files to search in
+ the filter should be a list of wild card patterns to match.
+ @param filters: list of strings ['*.py', '*.pyw']
+
+ """
+ self._filters = filters
+
+ def SetFlags(self, isregex=None, matchcase=None, wholeword=None, down=None):
+ """Set the search engine flags. Leaving the parameter set to None
+ will not change the flag. Setting it to non None will change the value.
+ @keyword isregex: is regex search
+ @keyword matchcase: matchcase search
+ @keyword wholeword: wholeword search
+ @keyword down: search down or up
+
+ """
+ for attr, val in (('_isregex', isregex), ('_matchcase', matchcase),
+ ('_wholeword', wholeword), ('_next', down)):
+ if val is not None:
+ setattr(self, attr, val)
+ self._CompileRegex()
+
+ def SetMatchCase(self, case=True):
+ """Set whether the engine will use case sensative searches
+ @keyword case: bool
+
+ """
+ self._matchcase = case
+ self._CompileRegex()
+
+ def SetResultFormatter(self, funct):
+ """Set the result formatter function
+ @param funct: callable(filename, linenum, matchstr)
+
+ """
+ assert callable(funct)
+ self._formatter = funct
+
+ def SetSearchPool(self, pool):
+ """Set the search pool used by the Find methods
+ @param pool: string to search in
+
+ """
+ del self._pool
+ self._pool = pool
+ self._CompileRegex()
+
+ def SetQuery(self, query):
+ """Set the search query
+ @param query: string
+
+ """
+ self._query = query
+ self._CompileRegex()
+
+ def SetUseRegex(self, use=True):
+ """Set whether the engine is using regular expresion searches or
+ not.
+ @keyword use: bool
+
+ """
+ self._isregex = use
+ self._CompileRegex()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/txtutil.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/txtutil.py
new file mode 100644
index 0000000..1d10e60
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/txtutil.py
@@ -0,0 +1,46 @@
+###############################################################################
+# Name: txtutil.py #
+# Purpose: Text Utilities. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Business Model Library: Text Utilities
+
+Utility functions for managing and working with text.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: txtutil.py 67991 2011-06-20 23:48:01Z CJP $"
+__revision__ = "$Revision: 67991 $"
+
+__all__ = [ 'IsUnicode', 'DecodeString']
+
+#-----------------------------------------------------------------------------#
+# Imports
+import types
+
+#-----------------------------------------------------------------------------#
+
+def IsUnicode(txt):
+ """Is the given string a unicode string
+ @param txt: object
+ @return: bool
+
+ """
+ return isinstance(txt, types.UnicodeType)
+
+def DecodeString(txt, enc):
+ """Decode the given string with the given encoding,
+ only attempts to decode if the given txt is not already Unicode
+ @param txt: string
+ @param enc: encoding 'utf-8'
+ @return: unicode
+
+ """
+ if IsUnicode(txt):
+ txt = txt.decode(enc)
+ return txt
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/__init__.py
new file mode 100644
index 0000000..8f52d56
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/__init__.py
@@ -0,0 +1,50 @@
+###############################################################################
+# Name: __init__.py #
+# Purpose: Editra Control Library #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Control Library
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: __init__.py 70469 2012-01-27 19:27:02Z CJP $"
+__revision__ = "$Revision: 70469 $"
+
+
+__all__ = ['auinavi', 'choicedlg', 'colorsetter', 'ctrlbox', 'eclutil',
+ 'ecpickers', 'elistmix', 'encdlg', 'errdlg', 'finddlg', 'infodlg',
+ 'panelbox', 'outbuff', 'platebtn', 'pstatbar', 'segmentbk',
+ 'txtentry']
+
+#-----------------------------------------------------------------------------#
+from ecbasewin import *
+
+from auinavi import *
+from choicedlg import *
+from colorsetter import *
+from ctrlbox import *
+from eclutil import *
+from ecpickers import *
+from elistmix import *
+from encdlg import *
+from errdlg import *
+from filterdlg import *
+from finddlg import *
+from infodlg import *
+from outbuff import *
+from panelbox import *
+from platebtn import *
+from pstatbar import *
+from segmentbk import *
+from txtentry import *
+from elistctrl import *
+from _filetree import *
+from _infobar import *
+
+# TODO: Delete module entries once all plugins have been updated to not
+# import them separately.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_filetree.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_filetree.py
new file mode 100644
index 0000000..0b84547
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_filetree.py
@@ -0,0 +1,458 @@
+###############################################################################
+# Name: _dirtree.py #
+# Purpose: Directory Tree #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011-2013 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Control Library: FileTree
+
+Base class control for displaying a file system in a hierarchical manor.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _filetree.py 73347 2013-01-05 19:58:31Z CJP $"
+__revision__ = "$Revision: 73347 $"
+
+__all__ = ['FileTree',]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import sys
+import os
+import types
+import wx
+
+#-----------------------------------------------------------------------------#
+
+class FileTree(wx.TreeCtrl):
+ """Simple base control for displaying directories and files in a
+ hierarchical view.
+
+ """
+ def __init__(self, parent):
+ super(FileTree, self).__init__(parent,
+ style=wx.TR_HIDE_ROOT|
+ wx.TR_FULL_ROW_HIGHLIGHT|
+ wx.TR_LINES_AT_ROOT|
+ wx.TR_HAS_BUTTONS|
+ wx.TR_MULTIPLE|
+ wx.TR_EDIT_LABELS)
+
+ # Attributes
+ self._watch = list() # Root directories to watch
+ self._il = None
+ self._editlabels = True
+
+ # Setup
+ self.SetupImageList()
+ self.AddRoot('root')
+ self.SetPyData(self.RootItem, "root")
+
+ # Event Handlers
+ self.Bind(wx.EVT_TREE_ITEM_GETTOOLTIP, self._OnGetToolTip)
+ self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._OnItemActivated)
+ self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self._OnItemCollapsed)
+ self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self._OnItemExpanding)
+ self.Bind(wx.EVT_TREE_ITEM_MENU, self._OnMenu)
+ self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self._OnBeginEdit)
+ self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self._OnEndEdit)
+
+ def _OnBeginEdit(self, evt):
+ if not self._editlabels:
+ evt.Veto()
+ else:
+ item = evt.GetItem()
+ if self.DoBeginEdit(item):
+ evt.Skip()
+ else:
+ evt.Veto()
+
+ def _OnEndEdit(self, evt):
+ if self._editlabels:
+ item = evt.GetItem()
+ newlabel = evt.GetLabel()
+ if self.DoEndEdit(item, newlabel):
+ evt.Skip()
+ return
+ evt.Veto()
+
+ def _OnGetToolTip(self, evt):
+ item = evt.GetItem()
+ tt = self.DoGetToolTip(item)
+ if tt:
+ evt.ToolTip = tt
+ else:
+ evt.Skip()
+
+ def _OnItemActivated(self, evt):
+ item = evt.GetItem()
+ self.DoItemActivated(item)
+ evt.Skip()
+
+ def _OnItemCollapsed(self, evt):
+ item = evt.GetItem()
+ self.DoItemCollapsed(item)
+ evt.Skip()
+
+ def _OnItemExpanding(self, evt):
+ item = evt.GetItem()
+ self.DoItemExpanding(item)
+ evt.Skip()
+
+ def _OnMenu(self, evt):
+ try:
+ item = evt.GetItem()
+ self.DoShowMenu(item)
+ except:
+ pass
+
+ #---- Properties ----#
+
+ SelectedFiles = property(lambda self: self.GetSelectedFiles())
+
+ #---- Overridable methods ----#
+
+ def DoBeginEdit(self, item):
+ """Overridable method that will be called when
+ a user has started to edit an item.
+ @param item: TreeItem
+ return: bool (True == Allow Edit)
+
+ """
+ return False
+
+ def DoEndEdit(self, item, newlabel):
+ """Overridable method that will be called when
+ a user has finished editing an item.
+ @param item: TreeItem
+ @param newlabel: unicode (newly entered value)
+ return: bool (True == Change Accepted)
+
+ """
+ return False
+
+ def DoGetToolTip(self, item):
+ """Get the tooltip to show for an item
+ @return: string or None
+
+ """
+ data = self.GetItemPyData(item)
+ return data
+
+ def DoItemActivated(self, item):
+ """Override to handle item activation
+ @param item: TreeItem
+
+ """
+ pass
+
+ def DoItemCollapsed(self, item):
+ """Handle when an item is collapsed
+ @param item: TreeItem
+
+ """
+ self.DeleteChildren(item)
+
+ def DoItemExpanding(self, item):
+ """Handle when an item is expanding
+ @param item: TreeItem
+
+ """
+ d = self.GetPyData(item)
+ if d and os.path.exists(d):
+ contents = FileTree.GetDirContents(d)
+ for p in contents:
+ self.AppendFileNode(item, p)
+
+ def DoShowMenu(self, item):
+ """Context menu has been requested for the given item.
+ @param item: wx.TreeItem
+
+ """
+ pass
+
+ def DoSetupImageList(self):
+ """Add the images to the control's ImageList. It is guaranteed
+ that self.ImageList is valid and empty when this is called.
+
+ """
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_MENU, (16,16))
+ self.ImageList.Add(bmp)
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_MENU, (16,16))
+ self.ImageList.Add(bmp)
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_MENU, (16,16))
+ self.ImageList.Add(bmp)
+
+ def DoGetFileImage(self, path):
+ """Get the index of the image from the image list to use
+ for the file.
+ @param path: Absolute path of file
+ @return: long
+
+ """
+ # TODO: image handling
+ if not os.access(path, os.R_OK):
+ img = 2
+ else:
+ if os.path.isdir(path):
+ img = 0 # Directory image
+ else:
+ img = 1 # Normal file image
+ return img
+
+ #---- End Overrides ----#
+
+ #---- Properties ----#
+
+ WatchDirs = property(lambda self: self._watch)
+
+ #---- FileTree Api ---#
+
+ def AddWatchDirectory(self, dname):
+ """Add a directory to the controls top level view
+ @param dname: directory path
+ @return: TreeItem or None
+ @todo: add additional api for getting already existing nodes based
+ on path.
+
+ """
+ assert os.path.exists(dname), "Path(%s) doesn't exist!" % dname
+ if dname not in self._watch:
+ self._watch.append(dname)
+ return self.AppendFileNode(self.RootItem, dname)
+
+ def RemoveWatchDirectory(self, dname):
+ """Remove a directory from the watch list
+ @param dname: directory path
+
+ """
+ if dname in self._watch:
+ self._watch.remove(dname)
+ nodes = self.GetChildNodes(self.RootItem)
+ for node in nodes:
+ data = self.GetPyData(node)
+ if dname == data:
+ self.Delete(node)
+ break
+
+ def SetupImageList(self):
+ """Setup/Refresh the control's ImageList.
+ Override DoSetupImageList to customize the behavior of this method.
+
+ """
+ if self._il:
+ self._il.Destroy()
+ self._il = None
+ self._il = wx.ImageList(16, 16)
+ self.SetImageList(self._il)
+ self.DoSetupImageList()
+
+ def AppendFileNode(self, item, path):
+ """Append a child node to the tree
+ @param item: TreeItem parent node
+ @param path: path to add to node
+ @return: new node
+
+ """
+ img = self.DoGetFileImage(path)
+ name = os.path.basename(path)
+ if not name:
+ name = path
+ child = self.AppendItem(item, name, img)
+ self.SetPyData(child, path)
+ if os.path.isdir(path):
+ self.SetItemHasChildren(child, True)
+ return child
+
+ def AppendFileNodes(self, item, paths):
+ """Append a list of child node to the tree. This
+ method can be used instead of looping on AppendFileNode
+ to get slightly better performance for large sets.
+ @param item: TreeItem parent node
+ @param paths: list of file paths
+ @return: None
+
+ """
+ getBaseName = os.path.basename
+ isDir = os.path.isdir
+ getImg = self.DoGetFileImage
+ appendNode = self.AppendItem
+ setData = self.SetPyData
+ for path in paths:
+ img = getImg(path)
+ name = getBaseName(path)
+ if not name:
+ name = path
+ child = appendNode(item, name, img)
+ setData(child, path)
+ if isDir(path):
+ self.SetItemHasChildren(child, True)
+
+ def GetChildNodes(self, parent):
+ """Get all the TreeItemIds under the given parent
+ @param parent: TreeItem
+ @return: list of TreeItems
+
+ """
+ rlist = list()
+ child, cookie = self.GetFirstChild(parent)
+ if not child or not child.IsOk():
+ return rlist
+
+ rlist.append(child)
+ while True:
+ child, cookie = self.GetNextChild(parent, cookie)
+ if not child or not child.IsOk():
+ return rlist
+ rlist.append(child)
+ return rlist
+
+ def GetExpandedNodes(self):
+ """Get all nodes that are currently expanded in the view
+ this logically corresponds to all parent directory nodes which
+ are expanded.
+ @return: list of TreeItems
+
+ """
+
+ def NodeWalker(parent, rlist):
+ """Recursively find expanded nodes
+ @param parent: parent node
+ @param rlist: list (outparam)
+
+ """
+ children = self.GetChildNodes(parent)
+ for node in children:
+ if self.IsExpanded(node):
+ rlist.append(node)
+ NodeWalker(node, rlist)
+
+ nodes = list()
+ NodeWalker(self.RootItem, nodes)
+ return nodes
+
+ def GetSelectedFiles(self):
+ """Get a list of the selected files
+ @return: list of strings
+
+ """
+ nodes = self.GetSelections()
+ files = [ self.GetPyData(node) for node in nodes ]
+ return files
+
+ def EnableLabelEditing(self, enable=True):
+ """Enable/Disable label editing. This functionality is
+ enabled by default.
+ @keyword enable: bool
+
+ """
+ self._editlabels = enable
+
+ def SelectFile(self, filename):
+ """Select the given path
+ @param filename: full path to select
+ @return: bool
+
+ """
+ bSelected = False
+ # Find the root
+ for node in self.GetChildNodes(self.RootItem):
+ dname = self.GetPyData(node)
+ if not os.path.isdir(dname):
+ dname = os.path.dirname(dname)
+ if not dname.endswith(os.sep):
+ dname += os.sep
+ if filename.startswith(dname):
+ filename = filename[len(dname):].split(os.sep)
+ if not self.IsExpanded(node):
+ self.Expand(node)
+ folder = node
+ try:
+ while filename:
+ name = filename.pop(0)
+ for item in self.GetChildNodes(folder):
+ if self.GetItemText(item) == name:
+ if not self.IsExpanded(item):
+ self.Expand(item)
+ folder = item
+ continue
+ except:
+ pass
+
+ self.UnselectAll()
+ self.EnsureVisible(folder)
+ self.SelectItem(folder)
+ break
+
+ #---- Static Methods ----#
+
+ @staticmethod
+ def GetDirContents(directory):
+ """Get the list of files contained in the given directory"""
+ assert os.path.isdir(directory)
+ files = list()
+ try:
+ joinPath = os.path.join
+ fappend = files.append
+ fs_encoding = sys.getfilesystemencoding()
+ for p in os.listdir(directory):
+ fullpath = joinPath(directory, p)
+ if type(fullpath) != types.UnicodeType:
+ fullpath = fullpath.decode(fs_encoding)
+ fappend(fullpath)
+ except OSError:
+ pass
+ return files
+
+ def GetNodePaths(self, dirNode):
+ """Get a list of paths contained below the given
+ directory node.
+ @param dirNode: wx.TreeItemId
+ @return: list of paths
+
+ """
+ paths = list()
+ if self.ItemHasChildren(dirNode):
+ append = paths.append
+ getData = self.GetPyData
+ for node in self.GetChildNodes(dirNode):
+ try:
+ append(getData(node))
+ except wx.PyAssertionError:
+ pass
+ return paths
+
+ def GetPyData(self, item):
+ """Get data from given tree item
+ @param item: TreeItemId
+
+ """
+ data = None
+ # avoid assertions in base class when retrieving data...
+ if item and item.IsOk():
+ try:
+ data = super(FileTree, self).GetPyData(item)
+ except wx.PyAssertionError:
+ pass
+ return data
+
+ def SortParentDirectory(self, item):
+ """Sort the parent directory of the given item"""
+ parent = self.GetItemParent(item)
+ if parent.IsOk():
+ self.SortChildren(parent)
+
+#-----------------------------------------------------------------------------#
+# Test
+if __name__ == '__main__':
+ app = wx.App(False)
+ f = wx.Frame(None)
+ ft = FileTree(f)
+ d = wx.GetUserHome()
+ ft.AddWatchDirectory(d)
+ f.Show()
+ app.MainLoop()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_infobar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_infobar.py
new file mode 100644
index 0000000..f3cd4c8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_infobar.py
@@ -0,0 +1,148 @@
+###############################################################################
+# Name: _infobar.py #
+# Purpose: Information Panel Class #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2012 Cody Precord <staff@editra.org> #
+# Licence: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: InfoBar
+
+Small information panel that can be used to replace popup modal dialogs.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: $"
+__revision__ = "$Revision: $"
+
+__all__ = [ 'InfoBar', 'INFOBAR_INFO', 'INFOBAR_WARN', 'INFOBAR_ERROR' ]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+# Local Imports
+import eclutil
+
+#-----------------------------------------------------------------------------#
+
+INFOBAR_INFO, \
+INFOBAR_WARN, \
+INFOBAR_ERROR = range(3)
+
+#-----------------------------------------------------------------------------#
+
+class InfoBar(wx.PyPanel):
+ """Information popup panel"""
+ def __init__(self, parent, title=u"", message=u"",
+ msgType=INFOBAR_INFO,
+ style=wx.TAB_TRAVERSAL|wx.NO_BORDER):
+ """Create the InfoBar"""
+ super(InfoBar, self).__init__(parent, style=style)
+ self.Hide() # Initially hidden
+
+ # Attributes
+ self._msgType = msgType
+
+ # Controls
+ self._bmp = wx.StaticBitmap(self)
+ self._title = wx.StaticText(self, label=title)
+ self._msg = wx.StaticText(self, label=message)
+ self._okBtn = wx.Button(self, wx.ID_OK)
+ self._cancelBtn = wx.Button(self, wx.ID_CANCEL)
+
+ # Setup
+ self.SetMessageType(msgType)
+ tfont = self._title.Font
+ tfont.SetWeight(wx.FONTWEIGHT_BOLD)
+ tfont.SetPointSize(tfont.PointSize + 1)
+ self._title.SetFont(tfont)
+ self.__DoLayout()
+
+ # Events
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+
+ def __DoLayout(self):
+ """Layout the panel"""
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ # Bitmap
+ sizer.Add(self.Bitmap, 0, wx.ALL|wx.ALIGN_CENTER, 8)
+ # Text
+ txt_sz = wx.BoxSizer(wx.VERTICAL)
+ txt_sz.Add(self.Title, 0, wx.ALL, 3)
+ txt_sz.Add(self.Message, 0, wx.ALL, 3)
+ sizer.Add(txt_sz, 0)
+ # Padding
+ sizer.AddStretchSpacer()
+ # Buttons
+ btnsz = wx.BoxSizer(wx.VERTICAL)
+ btnsz.Add(self._okBtn, 0, wx.ALL|wx.ALIGN_CENTER, 3)
+ btnsz.Add(self._cancelBtn, 0, wx.ALL|wx.ALIGN_CENTER, 3)
+ sizer.Add(btnsz, 0, wx.ALIGN_RIGHT)
+
+ self.SetSizer(sizer)
+
+ def _UpdateParent(self):
+ """Update parent for layout changes"""
+ self.Parent.Layout()
+ self.Parent.SendSizeEvent()
+
+ #---- Properties ----#
+
+ Bitmap = property(lambda self: self._bmp)
+ Title = property (lambda self: self._title)
+ Message = property(lambda self: self._msg)
+ MessageType = property(lambda self: self._msgType,
+ lambda self, mtype: self.SetMessageType(mtype))
+ ButtonOk = property(lambda self: self._okBtn)
+ ButtonCancel = property(lambda self: self._cancelBtn)
+
+ #---- Event Handlers ---#
+
+ def OnButton(self, evt):
+ """Handle button clicks"""
+ self.Show(False)
+ evt.Skip()
+
+ #---- Implementation ----#
+
+ def SetMessageType(self, msgType):
+ """Set the message type
+ @param msgType: INFOBAR_FOO identifier
+
+ """
+ bmp = wx.NullBitmap
+ if msgType == INFOBAR_INFO:
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_CMN_DIALOG)
+ self.SetBackgroundColour(wx.BLUE)
+ elif msgType == INFOBAR_ERROR:
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_CMN_DIALOG)
+ self.SetBackgroundColour(wx.Colour(230, 43, 29))
+ elif msgType == INFOBAR_WARN:
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_CMN_DIALOG)
+ self.SetBackgroundColour(wx.Colour(228, 165, 40))
+ else:
+ raise TypeError("Unknown message type: %s" % repr(msgType))
+ self._msgType = msgType
+ self.Bitmap.SetBitmap(bmp)
+
+ tcolour = eclutil.BestLabelColour(self.BackgroundColour)
+ self.Title.SetOwnForegroundColour(tcolour)
+ self.Message.SetOwnForegroundColour(tcolour)
+
+ self.Refresh()
+
+ def Show(self, show=True):
+ """Override to handle parent update"""
+ super(InfoBar, self).Show(show)
+ self._UpdateParent()
+ self.Refresh()
+
+ def ShowMessage(self, title=u"", message=u"", msgType=INFOBAR_INFO):
+ """Update the message and show the bar"""
+ self.Title.SetLabel(title)
+ self.Message.SetLabel(message)
+ self.MessageType = msgType
+ self.Show(True)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/auinavi.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/auinavi.py
new file mode 100644
index 0000000..a213d5b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/auinavi.py
@@ -0,0 +1,231 @@
+###############################################################################
+# Name: auinavi.py #
+# Purpose: AuiMgr Pane navigator #
+# Author: Giuseppe "Cowo" Corbelli #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Control Library: AuiPaneNavigator
+
+Popup navigation window for quickly navigating through AuiPanes in an AuiMgr.
+Activating the dialog will cause a modal popup dialog with a list of all panes
+managed by the aui manager. Changing the selection in the dialog will highlight
+the pane in the managed frame. Selecting the choice in the list will move the
+focus to that pane.
+
++---------------------+
+| bmp title |
++---------------------+
+| pane list |
+| |
+| |
+| |
+| |
+| |
++---------------------+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: auinavi.py 65794 2010-10-13 14:10:09Z CJP $"
+__revision__ = "$Revision: 65794 $"
+
+__all__ = ['AuiPaneNavigator',]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+# Editra Control Libray Imports
+import ctrlbox
+
+#-----------------------------------------------------------------------------#
+
+class AuiPaneNavigator(wx.Dialog):
+ """Navigate through Aui Panes"""
+ def __init__(self, parent, auiMgr, icon=None, title=''):
+ """Initialize the navigator window
+ @param parent: parent window
+ @param auiMgr: wx.aui.AuiManager
+ @keyword icon: wx.Bitmap or None
+ @keyword title: string (dialog title)
+
+ """
+ super(AuiPaneNavigator, self).__init__(parent, wx.ID_ANY,
+ "", style=wx.STAY_ON_TOP)
+
+ # Attributes
+ self._auimgr = auiMgr
+ self._selectedItem = -1
+ self._indexMap = list()
+ self._sel = 0
+ self._tabed = 0
+ self._close_keys = [wx.WXK_ALT, wx.WXK_CONTROL, wx.WXK_RETURN]
+ self._navi_keys = [wx.WXK_TAB, ord('1')] # <- TEMP
+ self._listBox = None
+ self._panel = None
+
+ # Setup
+ self.__DoLayout(icon, title)
+
+ # Get the panes
+ self.PopulateListControl()
+
+ # Event Handlers
+ self._listBox.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self._listBox.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
+ self._listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnItemSelected)
+ self._listBox.Bind(wx.EVT_LISTBOX, lambda evt: self.HighlightPane())
+
+ def __del__(self):
+ self._auimgr.HideHint()
+
+ def __DoLayout(self, icon, title):
+ """Layout the dialog controls
+ @param icon: wx.Bitmap or None
+ @param title: string
+
+ """
+ sz = wx.BoxSizer(wx.VERTICAL)
+ self._listBox = wx.ListBox(self, wx.ID_ANY, wx.DefaultPosition,
+ wx.Size(200, 150), list(),
+ wx.LB_SINGLE | wx.NO_BORDER)
+
+ self._panel = ctrlbox.ControlBar(self,
+ style=ctrlbox.CTRLBAR_STYLE_GRADIENT)
+ self._panel.SetVMargin(2, 2)
+
+ if icon is not None:
+ bmp = wx.StaticBitmap(self._panel, bitmap=icon)
+ self._panel.AddControl(bmp, wx.ALIGN_LEFT)
+
+ txt = wx.StaticText(self._panel, label=title)
+ self._panel.AddControl(txt, wx.ALIGN_LEFT)
+
+ sz.Add(self._panel, 0, wx.EXPAND)
+ sz.Add(self._listBox, 1, wx.EXPAND)
+ sz.Fit(self)
+ sz.SetSizeHints(self)
+ sz.Layout()
+ self.Centre()
+ self.SetSizer(sz)
+ self.SetAutoLayout(True)
+
+ def OnKeyUp(self, event):
+ """Handles wx.EVT_KEY_UP"""
+ self._auimgr.HideHint()
+ key_code = event.GetKeyCode()
+ # TODO: add setter method for setting the navigation key
+ if key_code in self._navi_keys:
+ self._tabed += 1
+
+ # Don't move selection on initial show
+ if self._tabed == 1:
+ self.HighlightPane()
+ event.Skip()
+ return
+
+ selected = self._listBox.GetSelection() + 1
+ if selected >= self._listBox.GetCount():
+ selected = 0
+
+ self._listBox.SetSelection(selected)
+ self.HighlightPane()
+ event.Skip()
+ elif key_code in self._close_keys:
+ self.CloseDialog()
+ elif key_code == wx.WXK_ESCAPE:
+ self.CloseDialog()
+ else:
+ event.Skip()
+
+ def OnNavigationKey(self, event):
+ """Handles wx.EVT_NAVIGATION_KEY"""
+ selected = self._listBox.GetSelection()
+ maxItems = self._listBox.GetCount()
+
+ if event.GetDirection():
+ # Select next pane
+ if selected == maxItems - 1:
+ itemToSelect = 0
+ else:
+ itemToSelect = selected + 1
+ else:
+ # Previous pane
+ if selected == 0:
+ itemToSelect = maxItems - 1
+ else:
+ itemToSelect = selected - 1
+
+ self._listBox.SetSelection(itemToSelect)
+ self.HighlightPane()
+
+ def PopulateListControl(self):
+ """Populates the L{AuiPaneNavigator} with the panes in the AuiMgr"""
+ self._panes = self._auimgr.GetAllPanes()
+ names = [pane.name for pane in self._panes]
+ self._listBox.AppendItems(sorted(names))
+
+ def OnItemSelected(self, event):
+ """Handles the wx.EVT_LISTBOX_DCLICK event"""
+ self.CloseDialog()
+
+ def CloseDialog(self):
+ """Closes the L{AuiPaneNavigator} dialog"""
+ self._selectedItem = self._listBox.GetStringSelection()
+ self._auimgr.HideHint()
+ self.EndModal(wx.ID_OK)
+
+ def GetCloseKeys(self):
+ """Get the list of keys that can dismiss the dialog
+ @return: list of long (wx.WXK_*)
+
+ """
+ return self._close_keys
+
+ def GetNavigationKeys(self):
+ """Get the list of navigation key(s)
+ @return: list of long (wx.WXK_*)
+
+ """
+ return self._navi_keys
+
+ def GetSelection(self):
+ """Get the index of the selected page"""
+ return self._selectedItem
+
+ def HighlightPane(self):
+ """Highlight the currently selected pane"""
+ sel = self._listBox.GetStringSelection()
+ pane = self._auimgr.GetPane(sel)
+ if pane.IsOk():
+ self._auimgr.ShowHint(pane.window.GetScreenRect())
+ # NOTE: this is odd but it is the only way for the focus to
+ # work correctly on wxMac...
+ wx.CallAfter(self._listBox.SetFocus)
+ self._listBox.SetFocus()
+
+ def SetCloseKeys(self, keylist):
+ """Set the keys that can be used to dismiss the L{AuiPaneNavigator}
+ window.
+ @param keylist: list of key codes
+
+ """
+ self._close_keys = keylist
+
+ def SetNavigationKeys(self, keylist):
+ """Set the key(s) to advance the selection in the pane list
+ @param keylist: list of key codes
+
+ """
+ self._navi_keys = keylist
+
+ def ShowModal(self):
+ # Set focus on the list box to avoid having to click on it to change
+ # the tab selection under GTK.
+ self._listBox.SetFocus()
+ self._listBox.SetSelection(0)
+ return super(AuiPaneNavigator, self).ShowModal() \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/choicedlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/choicedlg.py
new file mode 100644
index 0000000..6c4e219
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/choicedlg.py
@@ -0,0 +1,249 @@
+###############################################################################
+# Name: choicedlg.py #
+# Purpose: Generic Choice Dialog #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: Choice Dialog
+
+A generic choice dialog that uses a wx.Choice control to display its choices.
+
+@summary: Generic Choice Dialog
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: choicedlg.py 70230 2012-01-01 01:47:42Z CJP $"
+__revision__ = "$Revision: 70230 $"
+
+__all__ = ['ChoiceDialog',]
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+
+import ecbasewin
+
+#--------------------------------------------------------------------------#
+# Globals
+ChoiceDialogNameStr = u"ChoiceDialog"
+
+#--------------------------------------------------------------------------#
+
+class ChoiceDialog(ecbasewin.ECBaseDlg):
+ """Dialog with a wx.Choice control for showing a list of choices"""
+ def __init__(self, parent, id=wx.ID_ANY,
+ msg=u'', title=u'',
+ choices=None, default=u'',
+ pos=wx.DefaultPosition,
+ size=wx.DefaultSize,
+ style=0,
+ name=ChoiceDialogNameStr):
+ """Create the choice dialog
+ @param parent: Parent Window
+ @keyword id: Dialog ID
+ @keyword msg: Dialog Message
+ @keyword title: Dialog Title
+ @keyword choices: list of strings
+ @keyword default: Default selection
+ @keyword pos: Dialog Position
+ @keyword size: Dialog Size
+ @keyword style: Dialog Style bitmask
+ @keyword name: Dialog Name
+
+ """
+ super(ChoiceDialog, self).__init__(parent, id, title,
+ style=wx.CAPTION, pos=pos,
+ size=size, name=name)
+
+ # Attributes
+ panel = ChoicePanel(self, msg=msg,
+ choices=choices,
+ default=default,
+ style=style)
+ self.SetPanel(panel)
+ self.SetInitialSize()
+
+#--------------------------------------------------------------------------#
+
+class ChoicePanel(wx.Panel):
+ """Generic Choice dialog panel"""
+ def __init__(self, parent, msg=u'', choices=list(),
+ default=u'', style=wx.OK|wx.CANCEL):
+ """Create the panel
+ @param parent: Parent Window
+ @keyword msg: Display message
+ @keyword choices: list of strings
+ @keyword default: default selection
+ @keyword style: panel style
+
+ """
+ super(ChoicePanel, self).__init__(parent)
+
+ # Attributes
+ self._msg = msg
+ self._choices = wx.Choice(self, wx.ID_ANY)
+ self._selection = default
+ self._selidx = 0
+ self._bmp = None
+ self._buttons = list()
+
+ # Setup
+ self._choices.SetItems(choices)
+ if default in choices:
+ self._choices.SetStringSelection(default)
+ self._selidx = self._choices.GetSelection()
+ else:
+ self._choices.SetSelection(0)
+ self._selidx = 0
+ self._selection = self._choices.GetStringSelection()
+
+ # Setup Buttons
+ for btn, id_ in ((wx.OK, wx.ID_OK), (wx.CANCEL, wx.ID_CANCEL),
+ (wx.YES, wx.ID_YES), (wx.NO, wx.ID_NO)):
+ if btn & style:
+ button = wx.Button(self, id_)
+ self._buttons.append(button)
+
+ if not len(self._buttons):
+ self._buttons.append(wx.Button(self, wx.ID_OK))
+ self._buttons.append(wx.Button(self, wx.ID_CANCEL))
+
+ # Layout
+ self.__DoLayout(style)
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHOICE, self.OnChoice, self._choices)
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+
+ def __DoLayout(self, style):
+ """Layout the panel"""
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ caption = wx.StaticText(self, label=self._msg)
+
+ # Layout the buttons
+ bsizer = wx.StdDialogButtonSizer()
+ for button in self._buttons:
+ bsizer.AddButton(button)
+ bid = button.GetId()
+ if bid in (wx.ID_NO, wx.ID_YES):
+ if wx.NO_DEFAULT & style:
+ if bid == wx.ID_NO:
+ button.SetDefault()
+ else:
+ if bid == wx.ID_YES:
+ button.SetDefault()
+ elif bid == wx.ID_OK:
+ button.SetDefault()
+
+ bsizer.Realize()
+
+ vsizer.AddMany([((10, 10), 0), (caption, 0), ((20, 20), 0),
+ (self._choices, 1, wx.EXPAND), ((10, 10), 0),
+ (bsizer, 1, wx.EXPAND),
+ ((10, 10), 0)])
+
+ icon_id = wx.ART_INFORMATION
+ for i_id, a_id in ((wx.ICON_ERROR, wx.ART_ERROR),
+ (wx.ICON_WARNING, wx.ART_WARNING)):
+ if i_id & style:
+ icon_id = a_id
+ break
+
+ icon = wx.ArtProvider.GetBitmap(icon_id, wx.ART_MESSAGE_BOX, (64, 64))
+ self._bmp = wx.StaticBitmap(self, bitmap=icon)
+ bmpsz = wx.BoxSizer(wx.VERTICAL)
+ bmpsz.AddMany([((10, 10), 0), (self._bmp, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((10, 30), 0, wx.EXPAND)])
+ hsizer.AddMany([((10, 10), 0), (bmpsz, 0, wx.ALIGN_TOP),
+ ((10, 10), 0), (vsizer, 1), ((10, 10), 0)])
+
+ self.SetSizer(hsizer)
+ self.SetInitialSize()
+ self.SetAutoLayout(True)
+
+ def GetChoiceControl(self):
+ """Get the dialogs choice control
+ @return: wx.Choice
+
+ """
+ return self._choices
+
+ @ecbasewin.expose(ChoiceDialog)
+ def GetSelection(self):
+ """Get the chosen index
+ @return: int
+
+ """
+ return self._selidx
+
+ @ecbasewin.expose(ChoiceDialog)
+ def GetStringSelection(self):
+ """Get the chosen string
+ @return: string
+
+ """
+ return self._selection
+
+ def OnButton(self, evt):
+ """Handle button events
+ @param evt: wx.EVT_BUTTON
+
+ """
+ self.GetParent().EndModal(evt.GetId())
+
+ def OnChoice(self, evt):
+ """Update the selection
+ @param evt: wx.EVT_CHOICE
+
+ """
+ if evt.GetEventObject() == self._choices:
+ self._selection = self._choices.GetStringSelection()
+ self._selidx = self._choices.GetSelection()
+ else:
+ evt.Skip()
+
+ @ecbasewin.expose(ChoiceDialog)
+ def SetBitmap(self, bmp):
+ """Set the dialogs bitmap
+ @param bmp: wx.Bitmap
+
+ """
+ self._bmp.SetBitmap(bmp)
+ self.Layout()
+
+ @ecbasewin.expose(ChoiceDialog)
+ def SetChoices(self, choices):
+ """Set the dialogs choices
+ @param choices: list of strings
+
+ """
+ self._choices.SetItems(choices)
+ self._choices.SetSelection(0)
+ self._selection = self._choices.GetStringSelection()
+
+ @ecbasewin.expose(ChoiceDialog)
+ def SetSelection(self, sel):
+ """Set the selected choice
+ @param sel: int
+
+ """
+ self._choices.SetSelection(sel)
+ self._selection = self._choices.GetStringSelection()
+ self._selidx = self._choices.GetSelection()
+
+ @ecbasewin.expose(ChoiceDialog)
+ def SetStringSelection(self, sel):
+ """Set the selected choice
+ @param sel: string
+
+ """
+ self._choices.SetStringSelection(sel)
+ self._selection = self._choices.GetStringSelection()
+ self._selidx = self._choices.GetSelection()
+
+#--------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/colorsetter.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/colorsetter.py
new file mode 100644
index 0000000..5bb555a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/colorsetter.py
@@ -0,0 +1,263 @@
+###############################################################################
+# Name: colorsetter.py #
+# Purpose: Color Picker/Setter Control #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: ColorSetter
+
+Color picker control that has a text entry section for entering hex color codes,
+there is also a button that previews the color and can be used to open a color
+choice dialog.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: colorsetter.py 70230 2012-01-01 01:47:42Z CJP $"
+__revision__ = "$Revision: 70230 $"
+
+__all__ = ["ColorSetter", "ColorSetterEvent",
+ "EVT_COLORSETTER", "csEVT_COLORSETTER"]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.lib.colourselect as csel
+
+from eclutil import HexToRGB, Freezer
+
+#-----------------------------------------------------------------------------#
+# Globals
+# NOTE: # is expected at end
+HEX_CHARS = "0123456789ABCDEFabcdef#"
+
+_ = wx.GetTranslation
+#-----------------------------------------------------------------------------#
+
+csEVT_COLORSETTER = wx.NewEventType()
+EVT_COLORSETTER = wx.PyEventBinder(csEVT_COLORSETTER, 1)
+class ColorSetterEvent(wx.PyCommandEvent):
+ """Event to signal that text needs updating"""
+ def __init__(self, etype, eid, value=None):
+ """Creates the event object"""
+ wx.PyCommandEvent.__init__(self, etype, eid)
+ self._value = value
+
+ def GetValue(self):
+ """Returns the value from the event.
+ @return: the value of this event
+
+ """
+ return self._value
+
+#-----------------------------------------------------------------------------#
+
+class ColorSetter(wx.Panel):
+ """Control for setting a hex color value or selecting it from a
+ Color Dialog.
+
+ """
+ def __init__(self, parent, id_, color=wx.NullColour):
+ """Create the control, it is a composite of a colourSelect and
+ and a text control.
+ @param parent: Parent Window
+ @param id_: Control ID
+ @keyword color: Initial Colour
+
+ """
+ super(ColorSetter, self).__init__(parent, id_)
+
+ if isinstance(color, tuple):
+ color = wx.Colour(*color)
+
+ # Attributes
+ self._label = color.GetAsString(wx.C2S_HTML_SYNTAX)
+ self._txt = wx.TextCtrl(self,
+ value=self._label,
+ style=wx.TE_CENTER,
+ validator=HexValidator())
+ txtheight = self._txt.GetTextExtent('#000000')[1]
+ self._txt.SetMaxSize((-1, txtheight + 4))
+ self._txt.SetToolTip(wx.ToolTip(_("Enter a hex color value")))
+ self._cbtn = csel.ColourSelect(self, colour=color, size=(20, 20))
+ self._preval = color
+ self._DoLayout()
+
+ # Event Handlers
+ self.Bind(csel.EVT_COLOURSELECT, self.OnColour)
+ self._txt.Bind(wx.EVT_KEY_UP, self.OnTextChange)
+ self._txt.Bind(wx.EVT_TEXT_PASTE, self.OnTextChange)
+ self._txt.Bind(wx.EVT_KEY_DOWN, self.OnValidateTxt)
+
+ def __PostEvent(self):
+ """Notify the parent window of any value changes to the control"""
+ value = self._cbtn.GetValue()
+ if not isinstance(value, wx.Colour):
+ value = wx.Colour(*value)
+
+ # Don't post update if value hasn't changed
+ if value == self._preval:
+ return
+
+ self._preval = value
+ evt = ColorSetterEvent(csEVT_COLORSETTER, self.GetId(), value)
+ evt.SetEventObject(self)
+ wx.PostEvent(self.GetParent(), evt)
+
+ def __UpdateValues(self):
+ """Update the values based on the current state of the text control"""
+ with Freezer(self._txt) as _tmp:
+ cpos = self._txt.GetInsertionPoint()
+ hexstr = self._txt.GetValue().replace('#', '').strip()
+ valid = ''
+ for char in hexstr:
+ if char in HEX_CHARS[:-1]:
+ valid = valid + char
+
+ if len(valid) > 6:
+ valid = valid[:6]
+
+ valid = '#' + valid
+ self._txt.SetValue(valid)
+ self._txt.SetInsertionPoint(cpos)
+ valid = valid + (u'0' * (6 - len(valid)))
+ self._cbtn.SetValue(HexToRGB(valid))
+
+ def _DoLayout(self):
+ """Layout the controls"""
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(self._txt, 0, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL)
+ sizer.Add((5, 5), 0)
+ sizer.Add(self._cbtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL)
+ self.SetSizer(sizer)
+
+ def GetColour(self):
+ """Returns the colour value of the control
+ @return: wxColour object
+
+ """
+ return self._cbtn.GetValue()
+
+ def GetLabel(self):
+ """Gets the hex value from the text control
+ @return: string '#123456'
+ @note: ensures a full 6 digit hex value is returned, padding
+ with zero's where necessary
+
+ """
+ hexstr = self._txt.GetValue()
+ hexstr = hexstr.replace('#', '').replace(' ', '')
+ hexstr = '#' + hexstr + ('0' * (6 - len(hexstr)))
+ return hexstr
+
+ def OnColour(self, evt):
+ """Update the button and text control value
+ when a choice is made in the colour dialog.
+ @param evt: EVT_COLOURSELECT
+
+ """
+ e_val = evt.GetValue()[0:3]
+ red, green, blue = (hex(val)[2:].upper() for val in e_val)
+ hex_str = u"#%s%s%s" % (red.zfill(2), green.zfill(2), blue.zfill(2))
+ self._txt.SetValue(hex_str)
+ self._cbtn.SetValue(wx.Colour(*e_val))
+ self.__PostEvent()
+
+ def OnTextChange(self, evt=None):
+ """Catch when text changes in the text control and update
+ button accordingly.
+ @keyword evt: event that called this handler
+
+ """
+ self.__UpdateValues()
+ self.__PostEvent()
+
+ def OnValidateTxt(self, evt):
+ """Validate text to ensure only valid hex characters are entered
+ @param evt: wxEVT_KEY_DOWN
+
+ """
+ code = evt.GetKeyCode()
+ if code in (wx.WXK_DELETE, wx.WXK_BACK, wx.WXK_LEFT,
+ wx.WXK_RIGHT, wx.WXK_TAB) or evt.CmdDown():
+ evt.Skip()
+ return
+
+ key = unichr(code)
+ if (key.isdigit() and evt.ShiftDown()) or \
+ evt.AltDown() or evt.MetaDown():
+ return
+
+ if key in HEX_CHARS and \
+ (len(self._txt.GetValue().lstrip(u"#")) < 6 or \
+ self._txt.GetStringSelection()):
+ evt.Skip()
+
+ def SetLabel(self, label):
+ """Set the label value of the text control
+ @param label: hex string to set label to
+
+ """
+ self._txt.SetValue(label)
+ self.__UpdateValues()
+
+ def SetValue(self, colour):
+ """Set the color value of the button
+ @param colour: wxColour or 3 tuple to set color value to
+
+ """
+ self._cbtn.SetValue(colour)
+ self._preval = colour
+ red, green, blue = (hex(val)[2:].zfill(2).upper() for val in colour[0:3])
+ hex_str = u"#%s%s%s" % (red, green, blue)
+ self._txt.SetValue(hex_str)
+
+#-----------------------------------------------------------------------------#
+
+class HexValidator(wx.PyValidator):
+ """Validate Hex strings for the color setter"""
+ def __init__(self):
+ """Initialize the validator
+
+ """
+ super(HexValidator, self).__init__()
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+
+ def Clone(self):
+ """Clones the current validator
+ @return: clone of this object
+
+ """
+ return HexValidator()
+
+ def Validate(self, win):
+ """Validate an window value
+ @param win: window to validate
+
+ """
+ for char in val:
+ if char not in HEX_CHARS:
+ return False
+ else:
+ return True
+
+ def OnChar(self, event):
+ """Process values as they are entered into the control
+ @param event: event that called this handler
+
+ """
+ key = event.GetKeyCode()
+ if event.CmdDown() or key < wx.WXK_SPACE or key == wx.WXK_DELETE or \
+ key > 255 or chr(key) in HEX_CHARS[:-1]:
+ event.Skip()
+ return
+
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+
+ return
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ctrlbox.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ctrlbox.py
new file mode 100644
index 0000000..9b1678b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ctrlbox.py
@@ -0,0 +1,1186 @@
+###############################################################################
+# Name: ctrlbox.py #
+# Purpose: Container Window helper class #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: ControlBox
+
+Sizer managed panel class with support for a toolbar like control that can be
+placed on the top/bottom of the main window area, multiple control bars are also
+possible.
+
+Class ControlBar:
+
+Toolbar like control with automatic item spacing and layout.
+
+Styles:
+ - CTRLBAR_STYLE_DEFAULT: Plain background
+ - CTRLBAR_STYLE_GRADIENT: Draw the bar with a vertical gradient.
+ - CTRLBAR_STYLE_BORDER_BOTTOM: add a border to the bottom
+ - CTRLBAR_STYLE_BORDER: add a border to the top
+ - CTRLBAR_STYLE_VERTICAL = Vertical ControlBar tool layout
+
+Class ControlBox:
+
+The ControlBox is a sizer managed panel that supports easy creation of windows
+that require a sandwich like layout.
+
++---------------------------------------+
+| ControlBar |
++---------------------------------------+
+| |
+| |
+| MainWindow Area |
+| |
+| |
+| |
++---------------------------------------+
+| ControlBar |
++---------------------------------------+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ctrlbox.py 71187 2012-04-11 23:38:30Z CJP $"
+__revision__ = "$Revision: 71187 $"
+
+__all__ = ["ControlBox", "CTRLBOX_NAME_STR",
+
+ "ControlBar", "ControlBarEvent",
+ "CTRLBAR_STYLE_DEFAULT", "CTRLBAR_STYLE_GRADIENT",
+ "CTRLBAR_STYLE_BORDER_TOP", "CTRLBAR_STYLE_BORDER_BOTTOM",
+ "CTRLBAR_STYLE_VERTICAL",
+ "EVT_CTRLBAR", "edEVT_CTRLBAR", "CTRLBAR_NAME_STR",
+
+ "SegmentBar", "SegmentBarEvent",
+ "EVT_SEGMENT_SELECTED", "edEVT_SEGMENT_SELECTED",
+ "EVT_SEGMENT_CLOSE", "edEVT_SEGMENT_CLOSE",
+ "CTRLBAR_STYLE_LABELS", "CTRLBAR_STYLE_NO_DIVIDERS",
+ "SEGBTN_OPT_CLOSEBTNL", "SEGBTN_OPT_CLOSEBTNR",
+ "SEGBAR_NAME_STR", "SEGMENT_HT_NOWHERE",
+ "SEGMENT_HT_SEG", "SEGMENT_HT_X_BTN"
+]
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import wx
+
+# Local Imports
+from eclutil import AdjustColour, DrawCircleCloseBmp
+
+#--------------------------------------------------------------------------#
+# Globals
+
+#-- Control Name Strings --#
+CTRLBAR_NAME_STR = u'EditraControlBar'
+CTRLBOX_NAME_STR = u'EditraControlBox'
+SEGBAR_NAME_STR = u'EditraSegmentBar'
+
+#-- Control Style Flags --#
+
+# ControlBar / SegmentBar Style Flags
+CTRLBAR_STYLE_DEFAULT = 0
+CTRLBAR_STYLE_GRADIENT = 1 # Paint the bar with a gradient
+CTRLBAR_STYLE_BORDER_BOTTOM = 2 # Add a border to the bottom
+CTRLBAR_STYLE_BORDER_TOP = 4 # Add a border to the top
+CTRLBAR_STYLE_LABELS = 8 # Draw labels under the icons (SegmentBar)
+CTRLBAR_STYLE_NO_DIVIDERS = 16 # Don't draw dividers between segments
+CTRLBAR_STYLE_VERTICAL = 32 # Control bar in vertical orientation
+
+# Segment Button Options
+SEGBTN_OPT_NONE = 1 # No options set.
+SEGBTN_OPT_CLOSEBTNL = 2 # Close button on the segments left side.
+SEGBTN_OPT_CLOSEBTNR = 4 # Close button on the segment right side.
+
+# Hit test locations
+SEGMENT_HT_NOWHERE = 0
+SEGMENT_HT_SEG = 1
+SEGMENT_HT_X_BTN = 2
+
+# Segment States
+SEGMENT_STATE_NONE = 0 # Hover no where
+SEGMENT_STATE_SEG = 1 # Hover on segment
+SEGMENT_STATE_X = 2 # Hover on segment x button
+
+# ControlBar event for items added by AddTool
+edEVT_CTRLBAR = wx.NewEventType()
+EVT_CTRLBAR = wx.PyEventBinder(edEVT_CTRLBAR, 1)
+class ControlBarEvent(wx.PyCommandEvent):
+ """ControlBar Button Event"""
+
+edEVT_SEGMENT_SELECTED = wx.NewEventType()
+EVT_SEGMENT_SELECTED = wx.PyEventBinder(edEVT_SEGMENT_SELECTED, 1)
+edEVT_SEGMENT_CLOSE = wx.NewEventType()
+EVT_SEGMENT_CLOSE = wx.PyEventBinder(edEVT_SEGMENT_CLOSE, 1)
+class SegmentBarEvent(wx.PyCommandEvent):
+ """SegmentBar Button Event"""
+ def __init__(self, etype, id=0):
+ super(SegmentBarEvent, self).__init__(etype, id)
+
+ # Attributes
+ self.notify = wx.NotifyEvent(etype, id)
+ self._pre = -1
+ self._cur = -1
+
+ def GetPreviousSelection(self):
+ """Get the previously selected segment
+ @return: int
+
+ """
+ return self._pre
+
+ def GetCurrentSelection(self):
+ """Get the currently selected segment
+ @return: int
+
+ """
+ return self._cur
+
+ def IsAllowed(self):
+ """Is the event allowed to propagate
+ @return: bool
+
+ """
+ return self.notify.IsAllowed()
+
+ def SetSelections(self, previous=-1, current=-1):
+ """Set the events selection
+ @keyword previous: previously selected button index (int)
+ @keyword current: currently selected button index (int)
+
+ """
+ self._pre = previous
+ self._cur = current
+
+ def Veto(self):
+ """Veto the event"""
+ self.notify.Veto()
+
+#--------------------------------------------------------------------------#
+
+class ControlBox(wx.PyPanel):
+ """Simple managed panel helper class that allows for adding and
+ managing the position of a small toolbar like panel.
+ @see: L{ControlBar}
+
+ """
+ def __init__(self, parent, id=wx.ID_ANY,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.TAB_TRAVERSAL|wx.NO_BORDER,
+ name=CTRLBOX_NAME_STR):
+ super(ControlBox, self).__init__(parent, id, pos, size, style, name)
+
+ # Attributes
+ self._vsizer = wx.BoxSizer(wx.VERTICAL)
+ self._hsizer = wx.BoxSizer(wx.HORIZONTAL)
+ self._cbars = dict()
+ self._main = None
+
+ # Layout
+ self._hsizer.Add(self._vsizer, 1, wx.EXPAND)
+ self.SetSizer(self._hsizer)
+
+ #---- Properties ----#
+ Window = property(lambda self: self.GetWindow())
+
+ def _GetCtrlBarSizer(self, pos):
+ """Get the correct sizer for the ControlBar at the given pos
+ @param pos: wx.TOP/LEFT/RIGHT/BOTTOM
+
+ """
+ if pos in (wx.TOP, wx.BOTTOM):
+ sizer = self._vsizer
+ else:
+ sizer = self._hsizer
+ return sizer
+
+ def ChangeWindow(self, window):
+ """Change the main window area, and return the current window
+ @param window: Any window/panel like object
+ @return: the old window or None
+
+ """
+ rwindow = None
+ if self.GetWindow() is None or not isinstance(self._main, wx.Window):
+ del self._main
+ topb = self.GetControlBar(wx.TOP)
+ if topb is None:
+ self._vsizer.Add(window, 1, wx.EXPAND)
+ else:
+ self._vsizer.Insert(1, window, 1, wx.EXPAND)
+ else:
+ self._vsizer.Replace(self._main, window)
+ rwindow = self._main
+
+ self._main = window
+ return rwindow
+
+ def CreateControlBar(self, pos=wx.TOP):
+ """Create a ControlBar at the given position if one does not
+ already exist.
+ @keyword pos: wx.TOP (default), BOTTOM, LEFT, RIGHT
+ @postcondition: A top aligned L{ControlBar} is created.
+ @return: ControlBar
+
+ """
+ cbar = self.GetControlBar(pos)
+ if cbar is None:
+ style=CTRLBAR_STYLE_GRADIENT
+ if pos in (wx.LEFT, wx.RIGHT):
+ style |= CTRLBAR_STYLE_VERTICAL
+ cbar = ControlBar(self, style=style)
+ self.SetControlBar(cbar, pos)
+ return cbar
+
+ def GetControlBar(self, pos=wx.TOP):
+ """Get the L{ControlBar} used by this window
+ @param pos: wx.TOP, BOTTOM, LEFT, RIGHT
+ @return: ControlBar or None
+
+ """
+ assert pos in (wx.TOP, wx.LEFT, wx.BOTTOM, wx.RIGHT)
+ cbar = self._cbars.get(pos, None)
+ return cbar
+
+ def GetWindow(self):
+ """Get the main display window
+ @return: Window or None
+
+ """
+ return self._main
+
+ def ReplaceControlBar(self, ctrlbar, pos=wx.TOP):
+ """Replace the L{ControlBar} at the given position
+ with the given ctrlbar and return the bar that was
+ replaced or None.
+ @param ctrlbar: L{ControlBar}
+ @keyword pos: Position
+ @return: L{ControlBar} or None
+
+ """
+ assert isinstance(ctrlbar, ControlBar)
+ assert pos in (wx.TOP, wx.BOTTOM, wx.LEFT, wx.RIGHT)
+ tbar = self.GetControlBar(pos)
+ rbar = None
+ sizer = self._GetCtrlBarSizer(pos)
+ if tbar is None and pos in (wx.TOP, wx.LEFT):
+ sizer.Insert(0, ctrlbar, 0, wx.EXPAND)
+ elif tbar is None and pos in (wx.BOTTOM, wx.RIGHT):
+ sizer.Add(ctrlbar, 0, wx.EXPAND)
+ else:
+ sizer.Replace(tbar, ctrlbar)
+ rbar = tbar
+
+ self._cbars[pos] = ctrlbar
+
+ return rbar
+
+ def SetControlBar(self, ctrlbar, pos=wx.TOP):
+ """Set the ControlBar used by this ControlBox
+ @param ctrlbar: L{ControlBar}
+ @keyword pos: wx.TOP/wx.BOTTOM/wx.LEFT/wx.RIGHT
+
+ """
+ assert isinstance(ctrlbar, ControlBar)
+ assert pos in (wx.TOP, wx.BOTTOM, wx.LEFT, wx.RIGHT)
+ tbar = self.GetControlBar(pos)
+ if tbar is ctrlbar:
+ return # ignore setting same bar again
+ sizer = self._GetCtrlBarSizer(pos)
+ if tbar is None and pos in (wx.TOP, wx.LEFT):
+ sizer.Insert(0, ctrlbar, 0, wx.EXPAND)
+ elif tbar is None and pos in (wx.BOTTOM, wx.RIGHT):
+ sizer.Add(ctrlbar, 0, wx.EXPAND)
+ else:
+ sizer.Replace(tbar, ctrlbar)
+
+ try:
+ tbar.Destroy()
+ except wx.PyDeadObjectError:
+ pass
+
+ self._cbars[pos] = ctrlbar
+
+ def SetWindow(self, window):
+ """Set the main window control portion of the box. This will be the
+ main central item shown in the box
+ @param window: Any window/panel like object
+
+ """
+ if self.GetWindow() is None:
+ topb = self.GetControlBar(wx.TOP)
+ botb = self.GetControlBar(wx.BOTTOM)
+ if (topb and botb is None) or (topb is None and botb is None):
+ self._vsizer.Add(window, 1, wx.EXPAND)
+ elif botb and topb is None:
+ self._vsizer.Insert(0, window, 1, wx.EXPAND)
+ else:
+ self._vsizer.Insert(1, window, 1, wx.EXPAND)
+ else:
+ self._vsizer.Replace(self._main, window)
+
+ try:
+ self._main.Destroy()
+ except wx.PyDeadObjectError:
+ pass
+
+ self._main = window
+
+#--------------------------------------------------------------------------#
+
+class ControlBar(wx.PyPanel):
+ """Toolbar like control container for use with a L{ControlBox}. It
+ uses a panel with a managed sizer as a convenient way to add a small
+ bar with various controls in it to any window.
+
+ """
+ def __init__(self, parent, id=wx.ID_ANY,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=CTRLBAR_STYLE_DEFAULT,
+ name=CTRLBAR_NAME_STR):
+ super(ControlBar, self).__init__(parent, id, pos, size,
+ wx.TAB_TRAVERSAL|wx.NO_BORDER, name)
+
+ tsz_orient = wx.HORIZONTAL
+ msz_orient = wx.VERTICAL
+ if style & CTRLBAR_STYLE_VERTICAL:
+ tsz_orient = wx.VERTICAL
+ msz_orient = wx.HORIZONTAL
+
+ # Attributes
+ self._style = style
+ self._sizer = wx.BoxSizer(tsz_orient)
+ self._tools = dict(simple=list())
+ self._spacing = (5, 5)
+
+ # Drawing related
+ color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+ if wx.Platform != '__WXMAC__':
+ self._color2 = AdjustColour(color, 15)
+ self._color = AdjustColour(color, -10)
+ else:
+ self._color2 = AdjustColour(color, 15)
+ self._color = AdjustColour(color, -20)
+
+ pcolor = tuple([min(190, x) for x in AdjustColour(self._color, -25)])
+ self._pen = wx.Pen(pcolor, 1)
+
+ # Setup
+ msizer = wx.BoxSizer(msz_orient)
+ spacer = (0, 0)
+ msizer.Add(spacer, 0)
+ msizer.Add(self._sizer, 1, wx.EXPAND)
+ msizer.Add(spacer, 0)
+ self.SetSizer(msizer)
+
+ # Event Handlers
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_BUTTON, self._DispatchEvent)
+
+ def _DispatchEvent(self, evt):
+ """Translate the button events generated by the controls added by
+ L{AddTool} to L{ControlBarEvent}'s.
+
+ """
+ e_id = evt.GetId()
+ if e_id in self._tools['simple']:
+ cb_evt = ControlBarEvent(edEVT_CTRLBAR, e_id)
+ self.GetEventHandler().ProcessEvent(cb_evt)
+ else:
+ # Allow to propagate
+ evt.Skip()
+
+ def _GetAlignment(self):
+ """Verify and get the proper secondary alignment based on the
+ control bar alignment.
+
+ """
+ if not self.IsVerticalMode():
+ align2 = wx.ALIGN_CENTER_VERTICAL
+ else:
+ align2 = wx.ALIGN_CENTER_HORIZONTAL
+ return align2
+
+ def AddControl(self, control, align=-1, stretch=0):
+ """Add a control to the bar
+ @param control: The control to add to the bar
+ @keyword align: wx.ALIGN_**
+ @keyword stretch: The controls proportions 0 for normal, 1 for expand
+
+ """
+ if wx.Platform == '__WXMAC__':
+ if hasattr(control, 'SetWindowVariant'):
+ control.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+
+ # Default to proper alignment when -1 specified
+ if align not in (wx.ALIGN_LEFT, wx.ALIGN_RIGHT,
+ wx.ALIGN_BOTTOM, wx.ALIGN_TOP):
+ if self.IsVerticalMode():
+ align = wx.ALIGN_TOP
+ else:
+ align = wx.ALIGN_LEFT
+
+ align2 = self._GetAlignment()
+ if align in (wx.ALIGN_LEFT, wx.ALIGN_TOP):
+ self._sizer.Add(self._spacing, 0)
+ self._sizer.Add(control, stretch, align|align2)
+ else:
+ self._sizer.Add(control, stretch, align|align2)
+ self._sizer.Add(self._spacing, 0)
+
+ self.Layout()
+
+ def AddSpacer(self, width, height):
+ """Add a fixed size spacer to the control bar
+ @param width: width of the spacer
+ @param height: height of the spacer
+
+ """
+ self._sizer.Add((width, height), 0)
+
+ def AddStretchSpacer(self):
+ """Add an expanding spacer to the bar that will stretch and
+ contract when the window changes size.
+
+ """
+ self._sizer.AddStretchSpacer(2)
+
+ def AddTool(self, tid, bmp, help=u'', align=-1):
+ """Add a simple bitmap button tool to the control bar
+ @param tid: Tool Id
+ @param bmp: Tool bitmap
+ @keyword help: Short help string
+ @keyword align: wx.ALIGN_**
+
+ """
+ tool = wx.BitmapButton(self, tid, bmp, style=wx.NO_BORDER)
+ if wx.Platform == '__WXGTK__':
+ # SetMargins not available in wxPython 2.9+
+ getattr(tool, 'SetMargins', lambda x,y: False)(0, 0)
+ spacer = (0, 0)
+ else:
+ spacer = self._spacing
+ tool.SetToolTipString(help)
+
+ # Default to proper alignment when unknown is specified
+ if align not in (wx.ALIGN_LEFT, wx.ALIGN_RIGHT,
+ wx.ALIGN_BOTTOM, wx.ALIGN_TOP):
+ if self.IsVerticalMode():
+ align = wx.ALIGN_TOP
+ else:
+ align = wx.ALIGN_LEFT
+
+ align2 = self._GetAlignment()
+ self._tools['simple'].append(tool.GetId())
+ if align in (wx.ALIGN_TOP, wx.ALIGN_LEFT):
+ self._sizer.Add(spacer, 0)
+ self._sizer.Add(tool, 0, align|align2)
+ else:
+ self._sizer.Add(spacer, 0)
+ self._sizer.Add(tool, 0, align|align2)
+
+ def GetControlSizer(self):
+ """Get the sizer that is used to layout the contols (horizontal sizer)
+ @return: wx.BoxSizer
+
+ """
+ return self._sizer
+
+ def GetControlSpacing(self):
+ """Get the spacing used between controls
+ @return: size tuple
+
+ """
+ return self._spacing
+
+ def IsVerticalMode(self):
+ """Is the ControlBar in vertical orientation
+ @return: bool
+
+ """
+ return self._style & CTRLBAR_STYLE_VERTICAL
+
+ def DoPaintBackground(self, dc, rect, color, color2):
+ """Paint the background of the given rect based on the style of
+ the control bar.
+ @param dc: DC to draw on
+ @param rect: wx.Rect
+ @param color: Pen/Base gradient color
+ @param color2: Gradient end color
+
+ """
+ # Paint the gradient
+ if self._style & CTRLBAR_STYLE_GRADIENT:
+ if isinstance(dc, wx.GCDC):
+ gc = dc.GetGraphicsContext()
+ else:
+ gc = wx.GraphicsContext.Create(dc)
+
+ if gc is None:
+ return
+
+ if not self.IsVerticalMode():
+ grad = gc.CreateLinearGradientBrush(rect.x, rect.y, rect.x,
+ rect.x+rect.height,
+ color2, color)
+ else:
+ grad = gc.CreateLinearGradientBrush(rect.x, rect.y,
+ rect.x+rect.width,
+ rect.y,
+ color2, color)
+
+ gc.SetPen(gc.CreatePen(self._pen))
+ gc.SetBrush(grad)
+ gc.DrawRectangle(rect.x, rect.y, rect.Width - 0.5, rect.Height - 0.5)
+
+ dc.SetPen(wx.Pen(color, 1))
+
+ # TODO: handle vertical mode
+ if not self.IsVerticalMode():
+ # Add a border to the bottom
+ if self._style & CTRLBAR_STYLE_BORDER_BOTTOM:
+ dc.DrawLine(rect.x, rect.GetHeight() - 1,
+ rect.GetWidth(), rect.GetHeight() - 1)
+
+ # Add a border to the top
+ if self._style & CTRLBAR_STYLE_BORDER_TOP:
+ dc.DrawLine(rect.x, 1, rect.GetWidth(), 1)
+
+ def OnPaint(self, evt):
+ """Paint the background to match the current style
+ @param evt: wx.PaintEvent
+
+ """
+ dc = wx.AutoBufferedPaintDCFactory(self)
+ gc = wx.GCDC(dc)
+ rect = self.GetClientRect()
+
+ self.DoPaintBackground(gc, rect, self._color, self._color2)
+
+ evt.Skip()
+
+ def SetToolSpacing(self, px):
+ """Set the spacing to use between tools/controls.
+ @param px: int (number of pixels)
+ @todo: dynamically update existing layouts
+
+ """
+ self._spacing = (px, px)
+
+ def SetVMargin(self, top, bottom):
+ """WARNING this method is Deprecated use SetMargins instead!!
+ @param top: Top margin in pixels
+ @param bottom: Bottom margin in pixels
+
+ """
+ # TODO: Remove all usage of this method
+ self.SetMargins(top, bottom)
+
+ def SetMargins(self, param1, param2):
+ """Setup the margins on the edges of the ControlBar
+ @param param1: left/top margin depending on orientation
+ @param param2: right/bottom margin depending on orientation
+
+ """
+ sizer = self.GetSizer()
+ if wx.VERSION < (2, 9, 0, 0, ''):
+ sizer.GetItem(0).SetSpacer((param1, param1))
+ sizer.GetItem(2).SetSpacer((param2, param2))
+ else:
+ sizer.GetItem(0).AssignSpacer((param1, param1))
+ sizer.GetItem(2).AssignSpacer((param2, param2))
+ sizer.Layout()
+
+ def SetWindowStyle(self, style):
+ """Set the style flags of this window
+ @param style: long
+
+ """
+ if self.IsVerticalMode() and not (CTRLBAR_STYLE_VERTICAL & style):
+ # Switching from vertical to HORIZONTAL
+ self._sizer.SetOrientation(wx.HORIZONTAL)
+ elif not self.IsVerticalMode() and (CTRLBAR_STYLE_VERTICAL & style):
+ # Switching from horizontal to vertical
+ self._sizer.SetOrientation(wx.VERTICAL)
+ self._style = style
+ self.Layout()
+ self.Refresh()
+
+#--------------------------------------------------------------------------#
+
+class _SegmentButton(object):
+ """Class for managing segment button data"""
+ def __init__(self, id_, bmp, label, lbl_size):
+ super(_SegmentButton, self).__init__()
+
+ # Attributes
+ self._id = id_
+ self._bmp = bmp
+ self._lbl = label
+ self._lbl_size = lbl_size
+ self._rect = wx.Rect()
+ self._bx1 = 0
+ self._bx2 = 0
+ self._opts = 0
+ self._selected = False
+ self._x_button = wx.Rect()
+ self._x_state = SEGMENT_STATE_NONE
+
+ Id = property(lambda self: self._id,
+ lambda self, id_: setattr(self, '_id', id_))
+ Bitmap = property(lambda self: self._bmp,
+ lambda self, bmp: setattr(self, '_bmp', bmp))
+ Label = property(lambda self: self._lbl,
+ lambda self, label: setattr(self, '_lbl', label))
+ LabelSize = property(lambda self: self._lbl_size,
+ lambda self, size: setattr(self, '_lbl_size', size))
+ Rect = property(lambda self: self._rect,
+ lambda self, rect: setattr(self, '_rect', rect))
+ Selected = property(lambda self: self._selected,
+ lambda self, sel: setattr(self, '_selected', sel))
+ XState = property(lambda self: self._x_state,
+ lambda self, state: setattr(self, '_x_state', state))
+ XButton = property(lambda self: self._x_button,
+ lambda self, rect: setattr(self, '_x_button', rect))
+ BX1 = property(lambda self: self._bx1,
+ lambda self, x1: setattr(self, '_bx1', x1))
+ BX2 = property(lambda self: self._bx2,
+ lambda self, x2: setattr(self, '_bx2', x2))
+ Options = property(lambda self: self._opts,
+ lambda self, opt: setattr(self, '_opts', opt))
+
+class SegmentBar(ControlBar):
+ """Simple toolbar like control that displays bitmaps and optionally
+ labels below each bitmap. The bitmaps are turned into a toggle button
+ where only one segment in the bar can be selected at one time.
+
+ """
+ HPAD = 5
+ VPAD = 3
+ def __init__(self, parent, id=wx.ID_ANY,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=CTRLBAR_STYLE_DEFAULT,
+ name=SEGBAR_NAME_STR):
+ super(SegmentBar, self).__init__(parent, id, pos, size, style, name)
+
+ # Attributes
+ self._buttons = list() # list of _SegmentButtons
+ self._segsize = (0, 0)
+ self._selected = -1
+ self._scolor1 = AdjustColour(self._color, -20)
+ self._scolor2 = AdjustColour(self._color2, -20)
+ self._spen = wx.Pen(AdjustColour(self._pen.GetColour(), -25))
+ self._x_clicked_before = False
+ self._tip_timer = wx.Timer(self)
+
+ if wx.Platform == '__WXMAC__':
+ self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+
+ # Event Handlers
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnLeave)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_TIMER, self.OnTipTimer, self._tip_timer)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+
+ def _RestartTimer(self):
+ """Reset the tip timer for showing tooltips when
+ the segments have their labels hidden.
+
+ """
+ if not (self._style & CTRLBAR_STYLE_LABELS):
+ if self._tip_timer.IsRunning():
+ self._tip_timer.Stop()
+ self._tip_timer.Start(1000, True)
+
+ def OnDestroy(self, evt):
+ """Cleanup on Destroy"""
+ if evt.GetEventObject() is self:
+ if self._tip_timer.IsRunning():
+ self._tip_timer.Stop()
+ evt.Skip()
+
+ def AddSegment(self, id, bmp, label=u''):
+ """Add a segment to the bar
+ @param id: button id
+ @param bmp: wx.Bitmap
+ @param label: string
+
+ """
+ assert bmp.IsOk()
+ lsize = self.GetTextExtent(label)
+ segment = _SegmentButton(id, bmp, label, lsize)
+ self._buttons.append(segment)
+ self.InvalidateBestSize()
+ self.Refresh()
+
+ def DoDrawButton(self, dc, pos, bidx, selected=False, draw_label=False):
+ """Draw a button
+ @param dc: DC to draw on
+ @param pos: X coordinate (horizontal mode) / Y coordinate (vertical mode)
+ @param bidx: button dict
+ @keyword selected: is this the selected button (bool)
+ @keyword draw_label: draw the label (bool)
+ return: int (next xpos)
+
+ """
+ button = self._buttons[bidx]
+ height = self.Rect.height
+ bVertical = self.IsVerticalMode()
+
+ # Draw the background of the button
+ if not bVertical:
+ rside = pos + self._segsize[0]
+ brect = wx.Rect(pos, 0, rside - pos, height)
+ else:
+ rside = pos + self._segsize[1]
+ brect = wx.Rect(0, pos, self.Rect.Width, rside - pos)
+
+ button.Rect = brect
+ if selected:
+ self.DoPaintBackground(dc, brect, self._scolor1, self._scolor2)
+
+ # Draw the bitmap
+ bmp = button.Bitmap
+ bsize = button.Bitmap.Size
+ if not bVertical:
+ bxpos = ((self._segsize[0] / 2) - (bsize.width / 2)) + pos
+ bpos = (bxpos, SegmentBar.VPAD)
+ else:
+ bxpos = ((self._segsize[0] / 2) - (bsize.width / 2))
+ bpos = (bxpos, pos + SegmentBar.VPAD)
+ dc.DrawBitmap(bmp, bpos[0], bpos[1], bmp.Mask != None)
+
+ if draw_label:
+ lcolor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+ dc.SetTextForeground(lcolor)
+ twidth, theight = button.LabelSize
+ if not bVertical:
+ lxpos = pos
+ typos = height - theight - 2
+ else:
+ lxpos = 0
+ typos = pos + (self._segsize[1] - theight - 2)
+ trect = wx.Rect(lxpos, typos, self._segsize[0], theight + 3)
+ dc.DrawLabel(button.Label, trect, wx.ALIGN_CENTER)
+
+ if not selected:
+ if not (self._style & CTRLBAR_STYLE_NO_DIVIDERS):
+ dc.SetPen(self._pen)
+ if not bVertical:
+ dc.DrawLine(pos, 0, pos, height)
+ dc.DrawLine(rside, 0, rside, height)
+ else:
+ dc.DrawLine(0, pos, self.Rect.Width, pos)
+ dc.DrawLine(0, rside, self.Rect.Width, rside)
+ else:
+ dc.SetPen(self._spen)
+ tmpx = pos + 1
+ trside = rside - 1
+ if not bVertical:
+ dc.DrawLine(tmpx, 0, tmpx, height)
+ dc.DrawLine(trside, 0, trside, height)
+ else:
+ dc.DrawLine(0, tmpx, self.Rect.Width, tmpx)
+ dc.DrawLine(0, trside, self.Rect.Width, trside)
+
+ tpen = wx.Pen(self._spen.Colour)
+ tpen.SetJoin(wx.JOIN_BEVEL)
+ if not bVertical:
+ mpoint = height / 2
+ dc.DrawLine(tmpx + 1, mpoint, tmpx, 0)
+ dc.DrawLine(tmpx + 1, mpoint, tmpx, height)
+ dc.DrawLine(trside - 1, mpoint, trside, 0)
+ dc.DrawLine(trside - 1, mpoint, trside, height)
+ else:
+ mpoint = self.Rect.Width / 2
+ dc.DrawLine(mpoint, tmpx + 1, 0, tmpx)
+ dc.DrawLine(mpoint, tmpx + 1, self.Rect.Width, tmpx)
+ dc.DrawLine(mpoint, trside - 1, 0, trside)
+ dc.DrawLine(mpoint, trside - 1, self.Rect.Width, trside)
+
+ # Update derived button data
+ button.BX1 = pos + 1
+ button.BX2 = rside - 1
+ button.Selected = selected
+
+ # Draw delete button if button has one
+ if self.SegmentHasCloseButton(bidx):
+ if not bVertical:
+ brect = wx.Rect(button.BX1, 0, button.BX2 - (pos - 1), height)
+ else:
+ brect = wx.Rect(0, button.BX1, self.Rect.Width,
+ button.BX2 - (pos - 1))
+ self.DoDrawCloseBtn(dc, button, brect)
+ return rside # right/bottom of button just drawn
+
+ def DoDrawCloseBtn(self, gcdc, button, rect):
+ """Draw the close button on the segment
+ @param gcdc: Device Context
+ @param button: Segment Dict
+ @param rect: Segment Rect
+
+ """
+ if button.Options & SEGBTN_OPT_CLOSEBTNL:
+ x = rect.x + 8
+ y = rect.y + 6
+ else:
+ x = (rect.x + rect.Width) - 8
+ y = rect.y + 6
+
+ color = self._scolor2
+ if button.Selected:
+ color = AdjustColour(color, -25)
+
+ if button.XState == SEGMENT_STATE_X:
+ color = AdjustColour(color, -20)
+
+ gcdc.SetPen(wx.Pen(AdjustColour(color, -30)))
+
+ brect = wx.Rect(x-3, y-3, 8, 8)
+ bmp = DrawCircleCloseBmp(color, wx.WHITE)
+ gcdc.DrawBitmap(bmp, brect.x, brect.y)
+ button.XButton = brect
+ return
+
+ # Square style button
+# gcdc.DrawRectangleRect(brect)
+# gcdc.SetPen(wx.BLACK_PEN)
+# gcdc.DrawLine(brect.x+1, brect.y+1,
+# brect.x + brect.GetWidth() - 1, brect.y + brect.GetHeight() - 1)
+# gcdc.DrawLine(brect.x + brect.GetWidth() - 1, brect.y + 1,
+# brect.x + 1, brect.y + brect.GetHeight() - 1)
+# gcdc.SetBrush(brush)
+# gcdc.SetPen(pen)
+# button['xbtn'] = brect
+
+ def DoGetBestSize(self):
+ """Get the best size for the control"""
+ mwidth, mheight = 0, 0
+ draw_label = self._style & CTRLBAR_STYLE_LABELS
+ for btn in self._buttons:
+ bwidth, bheight = btn.Bitmap.Size
+ twidth = btn.LabelSize[0]
+ if bheight > mheight:
+ mheight = bheight
+
+ if bwidth > mwidth:
+ mwidth = bwidth
+
+ if draw_label:
+ if twidth > mwidth:
+ mwidth = twidth
+
+ # Adjust for label text
+ if draw_label and len(self._buttons):
+ mheight += self._buttons[0].LabelSize[1]
+
+ if self.IsVerticalMode():
+ height = (mheight + (SegmentBar.VPAD * 2) * len(self._buttons))
+ width = mwidth
+ else:
+ width = (mwidth + (SegmentBar.HPAD * 2)) * len(self._buttons)
+ height = mheight
+
+ size = wx.Size(width + (SegmentBar.HPAD * 2),
+ height + (SegmentBar.VPAD * 2))
+ self.CacheBestSize(size)
+ self._segsize = (mwidth + (SegmentBar.HPAD * 2),
+ mheight + (SegmentBar.VPAD * 2))
+ return size
+
+ def GetIndexFromPosition(self, pos):
+ """Get the segment index closest to the given position"""
+ if not self.IsVerticalMode():
+ cur_x = pos[0]
+ else:
+ cur_x = pos[1]
+ for idx, button in enumerate(self._buttons):
+ xpos = button.BX1
+ xpos2 = button.BX2
+ if cur_x >= xpos and cur_x <= xpos2 + 1:
+ return idx
+ else:
+ return wx.NOT_FOUND
+
+ def GetSegmentCount(self):
+ """Get the number segments in the control
+ @return: int
+
+ """
+ return len(self._buttons)
+
+ def GetSegmentLabel(self, index):
+ """Get the label of the given segment
+ @param index: segment index
+ @return: string
+
+ """
+ return self._buttons[index].Label
+
+ def GetSelection(self):
+ """Get the currently selected index"""
+ return self._selected
+
+ def HitTest(self, pos):
+ """Find where the position is in the window
+ @param pos: (x, y) in client cords
+ @return: int
+
+ """
+ index = self.GetIndexFromPosition(pos)
+ where = SEGMENT_HT_NOWHERE
+ if index != wx.NOT_FOUND:
+ button = self._buttons[index]
+ if self.SegmentHasCloseButton(index):
+ brect = button.XButton
+ trect = wx.Rect(brect.x, brect.y, brect.Width+4, brect.Height+4)
+ if trect.Contains(pos):
+ where = SEGMENT_HT_X_BTN
+ else:
+ where = SEGMENT_HT_SEG
+ else:
+ where = SEGMENT_HT_SEG
+
+ return where, index
+
+ def OnEraseBackground(self, evt):
+ """Handle the erase background event"""
+ pass
+
+ def OnLeftDown(self, evt):
+ """Handle clicks on the bar
+ @param evt: wx.MouseEvent
+
+ """
+ epos = evt.GetPosition()
+ index = self.GetIndexFromPosition(epos)
+ if index != wx.NOT_FOUND:
+ button = self._buttons[index]
+ pre = self._selected
+ self._selected = index
+
+ if self._selected != pre:
+ self.Refresh()
+ sevt = SegmentBarEvent(edEVT_SEGMENT_SELECTED, button.Id)
+ sevt.SetSelections(pre, index)
+ sevt.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(sevt)
+
+ self._x_clicked_before = False
+
+ # Check for click on close btn
+ if self.SegmentHasCloseButton(index):
+ if self.HitTest(epos)[0] == SEGMENT_HT_X_BTN:
+ self._x_clicked_before = True
+
+ evt.Skip()
+
+ def OnLeftUp(self, evt):
+ """Handle clicks on the bar
+ @param evt: wx.MouseEvent
+
+ """
+ epos = evt.GetPosition()
+ where, index = self.HitTest(epos)
+
+ # Check for click on close btn
+ if self.SegmentHasCloseButton(index) and self._x_clicked_before:
+ if where == SEGMENT_HT_X_BTN:
+ event = SegmentBarEvent(edEVT_SEGMENT_CLOSE, self.GetId())
+ event.SetSelections(index, index)
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+ if not event.IsAllowed():
+ return False
+ removed = self.RemoveSegment(index)
+
+ evt.Skip()
+
+ def OnEnter(self, evt):
+ """Mouse has entered the SegmentBar, update state info"""
+ evt.Skip()
+
+ def OnLeave(self, evt):
+ """Mouse has left the SegmentBar, update state info"""
+ if self._tip_timer.IsRunning():
+ self._tip_timer.Stop()
+ evt.Skip()
+
+ def OnMouseMove(self, evt):
+ """Handle when the mouse moves over the bar"""
+ epos = evt.GetPosition()
+ where, index = self.HitTest(epos)
+ if index == -1:
+ return
+ if not self.SegmentHasCloseButton(index):
+ self._RestartTimer()
+ return
+
+ # Update button state
+ button = self._buttons[index]
+ x_state = button.XState
+ button.XState = SEGMENT_STATE_NONE
+
+ if where != SEGMENT_HT_NOWHERE:
+ if where == SEGMENT_HT_X_BTN:
+ button.XState = SEGMENT_STATE_X
+ elif where == SEGMENT_HT_SEG:
+ # TODO: add highlight option for hover on segment
+ pass
+ else:
+ self._RestartTimer()
+ evt.Skip()
+ return
+
+ # If the hover state over a segments close button
+ # has changed redraw the close button to reflect the
+ # proper state.
+ if button.XState != x_state:
+ crect = self.GetClientRect()
+ if not self.IsVerticalMode():
+ brect = wx.Rect(button.BX1, 0,
+ button.BX2 - (button.BX1 - 2),
+ crect.Height)
+ else:
+ brect = wx.Rect(button.BX1, 0,
+ crect.Width,
+ button.BX2 - (button.BX1 - 2))
+ self.Refresh(False, brect)
+ self._RestartTimer()
+ evt.Skip()
+
+ def OnTipTimer(self, evt):
+ """Show the tooltip for the current SegmentButton"""
+ pos = self.ScreenToClient(wx.GetMousePosition())
+ where, index = self.HitTest(pos)
+ if index != -1:
+ button = self._buttons[index]
+ if button.Label:
+ rect = button.Rect
+ x,y = self.ClientToScreenXY(rect.x, rect.y)
+ rect.x = x
+ rect.y = y
+ wx.TipWindow(self, button.Label, rectBound=rect) # Transient
+
+ def OnPaint(self, evt):
+ """Paint the control"""
+ dc = wx.AutoBufferedPaintDCFactory(self)
+ gc = wx.GCDC(dc)
+
+ # Setup
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ gc.SetBrush(wx.TRANSPARENT_BRUSH)
+ gc.SetFont(self.GetFont())
+ gc.SetBackgroundMode(wx.TRANSPARENT)
+ gc.Clear()
+
+ # Paint the background
+ rect = self.GetClientRect()
+ self.DoPaintBackground(gc, rect, self._color, self._color2)
+
+ # Draw the buttons
+ # TODO: would be more efficient to just redraw the buttons that
+ # need redrawing.
+ npos = SegmentBar.HPAD
+ if self.IsVerticalMode():
+ npos = SegmentBar.VPAD
+ use_labels = self._style & CTRLBAR_STYLE_LABELS
+ for idx, button in enumerate(self._buttons):
+ npos = self.DoDrawButton(gc, npos, idx,
+ self._selected == idx,
+ use_labels)
+
+ def RemoveSegment(self, index):
+ """Remove a segment from the bar
+ @param index: int
+ @return: bool
+
+ """
+ button = self._buttons[index]
+
+ # TODO: wxPython 2.8.9.2 this causes a crash...
+# if button['bmp']:
+# button['bmp'].Destroy()
+ del self._buttons[index]
+
+ if self.GetSelection() == index:
+ count = self.GetSegmentCount()
+ if index >= count:
+ self.SetSelection(count-1)
+
+ self.Refresh()
+ return True
+
+ def SegmentHasCloseButton(self, index):
+ """Does the segment at index have a close button
+ @param index: int
+
+ """
+ button = self._buttons[index]
+ if button.Options & SEGBTN_OPT_CLOSEBTNL or \
+ button.Options & SEGBTN_OPT_CLOSEBTNR:
+ return True
+ return False
+
+ def SetSegmentImage(self, index, bmp):
+ """Set the image to use on the given segment
+ @param index: int
+ @param bmp: Bitmap
+
+ """
+ assert bmp.IsOk()
+ segment = self._buttons[index]
+ if segment.Bitmap.IsOk():
+ segment.Bitmap.Destroy()
+ segment.Bitmap = None
+ segment.Bitmap = bmp
+ self.InvalidateBestSize()
+ self.Refresh()
+
+ def SetSegmentLabel(self, index, label):
+ """Set the label for a given segment
+ @param index: segment index
+ @param label: string
+
+ """
+ segment = self._buttons[index]
+ lsize = self.GetTextExtent(label)
+ segment.Label = label
+ segment.LabelSize = lsize
+ self.InvalidateBestSize()
+ self.Refresh()
+
+ def SetSegmentOption(self, index, option):
+ """Set an option on a given segment
+ @param index: segment index
+ @param option: option to set
+
+ """
+ button = self._buttons[index]
+ button.Options = button.Options|option
+ self.Refresh()
+
+ def SetSelection(self, index):
+ """Set the selection
+ @param index: int
+
+ """
+ self._selected = index
+ self.Refresh()
+
+# Cleanup namespace
+#del SegmentBar.__dict__['AddControl']
+#del SegmentBar.__dict__['AddSpacer']
+#del SegmentBar.__dict__['AddTool']
+#del SegmentBar.__dict__['SetToolSpacing']
+#del SegmentBar.__dict__['SetVMargin']
+
+#--------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecbasewin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecbasewin.py
new file mode 100644
index 0000000..cff2c23
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecbasewin.py
@@ -0,0 +1,78 @@
+###############################################################################
+# Name: ecbasewin.py #
+# Purpose: Eclib Base Window Classes #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: Base Window Classes
+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ecbasewin.py 69410 2011-10-13 14:20:12Z CJP $"
+__revision__ = "$Revision: 69410 $"
+
+__all__ = ["ECBaseDlg", "expose"]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+#-----------------------------------------------------------------------------#
+# Decorators
+
+class expose(object):
+ """Expose a panels method to a to a specified class
+ The specified class must have a GetPanel method
+
+ """
+ def __init__(self, cls):
+ """@param cls: class to expose the method to"""
+ super(expose, self).__init__()
+ self.cls = cls
+
+ def __call__(self, funct):
+ fname = funct.func_name
+ def parentmeth(*args, **kwargs):
+ self = args[0]
+ return getattr(self.GetPanel(), fname)(*args[1:], **kwargs)
+ parentmeth.__name__ = funct.__name__
+ parentmeth.__doc__ = funct.__doc__
+ setattr(self.cls, fname, parentmeth)
+
+ return funct
+
+#-----------------------------------------------------------------------------#
+
+class ECBaseDlg(wx.Dialog):
+ """Editra Control Library Base Dialog Class"""
+ def __init__(self, parent, id=wx.ID_ANY, title=u"",
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_DIALOG_STYLE, name=u"ECBaseDialog"):
+ super(ECBaseDlg, self).__init__(parent, id, title, pos,
+ size, style, name)
+
+ # Attributes
+ self._panel = None
+
+ # Setup
+ self.SetSizer(wx.BoxSizer(wx.VERTICAL))
+
+ Panel = property(lambda self: self.GetPanel(),
+ lambda self, val: self.SetPanel(val))
+
+ def GetPanel(self):
+ """Get the dialogs main panel"""
+ return self._panel
+
+ def SetPanel(self, panel):
+ """Set the dialogs main panel"""
+ assert isinstance(panel, wx.Panel)
+ if self._panel is not None:
+ self._panel.Destroy()
+ self._panel = panel
+ self.Sizer.Add(self._panel, 1, wx.EXPAND)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/eclutil.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/eclutil.py
new file mode 100644
index 0000000..8c5f958
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/eclutil.py
@@ -0,0 +1,221 @@
+###############################################################################
+# Name: eclutil.py #
+# Purpose: Common library utilities. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Control Library: Editra Control Library Utility
+
+Miscellaneous utility functions and gui helpers
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: eclutil.py 71178 2012-04-11 22:42:28Z CJP $"
+__revision__ = "$Revision: 71178 $"
+
+__all__ = ['AdjustAlpha', 'AdjustColour', 'BestLabelColour', 'HexToRGB',
+ 'GetHighlightColour', 'EmptyBitmapRGBA', 'Freezer',
+
+ 'DRAW_CIRCLE_SMALL', 'DRAW_CIRCLE_NORMAL', 'DRAW_CIRCLE_LARGE',
+ 'DrawCircleCloseBmp' ]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+if wx.Platform == '__WXMAC__':
+ try:
+ import Carbon.Appearance
+ except ImportError:
+ CARBON = False
+ else:
+ CARBON = True
+
+#-----------------------------------------------------------------------------#
+
+# DrawCircleCloseBmp options
+DRAW_CIRCLE_SMALL = 0
+DRAW_CIRCLE_NORMAL = 1
+DRAW_CIRCLE_LARGE = 2
+
+__CircleDefs = { DRAW_CIRCLE_SMALL : dict(size=(8, 8),
+ xpath=((1.75, 2), (4.75, 5),
+ (1.75, 5), (4.75, 2))),
+ DRAW_CIRCLE_NORMAL : dict(size=(16, 16),
+ xpath=((4.5, 4), (10.5, 10),
+ (4.5, 10), (10.5, 4))),
+ DRAW_CIRCLE_LARGE : dict(size=(32, 32),
+ xpath=((8, 8), (20, 20),
+ (8, 20), (20, 8))) }
+
+#-----------------------------------------------------------------------------#
+# Colour Utilities
+
+def AdjustAlpha(colour, alpha):
+ """Adjust the alpha of a given colour"""
+ return wx.Colour(colour.Red(), colour.Green(), colour.Blue(), alpha)
+
+def AdjustColour(color, percent, alpha=wx.ALPHA_OPAQUE):
+ """ Brighten/Darken input colour by percent and adjust alpha
+ channel if needed. Returns the modified color.
+ @param color: color object to adjust
+ @param percent: percent to adjust +(brighten) or -(darken)
+ @keyword alpha: amount to adjust alpha channel
+
+ """
+ radj, gadj, badj = [ int(val * (abs(percent) / 100.0))
+ for val in color.Get() ]
+
+ if percent < 0:
+ radj, gadj, badj = [ val * -1 for val in [radj, gadj, badj] ]
+ else:
+ radj, gadj, badj = [ val or 255 for val in [radj, gadj, badj] ]
+
+ red = min(color.Red() + radj, 255)
+ green = min(color.Green() + gadj, 255)
+ blue = min(color.Blue() + badj, 255)
+ return wx.Colour(red, green, blue, alpha)
+
+def BestLabelColour(color):
+ """Get the best color to use for the label that will be drawn on
+ top of the given color.
+ @param color: background color that text will be drawn on
+
+ """
+ avg = sum(color.Get()) // 3
+ if avg > 128:
+ txt_color = wx.BLACK
+ else:
+ txt_color = wx.WHITE
+ return txt_color
+
+def GetHighlightColour():
+ """Get the default highlight color
+ @return: wx.Colour
+
+ """
+ if wx.Platform == '__WXMAC__':
+ if CARBON:
+ if hasattr(wx, 'MacThemeColour'):
+ color = wx.MacThemeColour(Carbon.Appearance.kThemeBrushFocusHighlight)
+ return color
+ else:
+ # kThemeBrushButtonPressedLightHighlight
+ brush = wx.Brush(wx.BLACK)
+ brush.MacSetTheme(Carbon.Appearance.kThemeBrushFocusHighlight)
+ return brush.GetColour()
+
+ # Fallback to text highlight color
+ return wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+
+def HexToRGB(hex_str):
+ """Returns a list of red/green/blue values from a
+ hex string.
+ @param hex_str: hex string to convert to rgb
+
+ """
+ hexval = hex_str
+ if hexval[0] == u"#":
+ hexval = hexval[1:]
+ ldiff = 6 - len(hexval)
+ hexval += ldiff * u"0"
+ # Convert hex values to integer
+ red = int(hexval[0:2], 16)
+ green = int(hexval[2:4], 16)
+ blue = int(hexval[4:], 16)
+ return [red, green, blue]
+
+#-----------------------------------------------------------------------------#
+
+def EmptyBitmapRGBA(width, height):
+ """Create an empty bitmap with an alpha channel"""
+ if hasattr(wx, 'EmptyBitmapRGBA'):
+ bmp = wx.EmptyBitmapRGBA(width, height, alpha=0)
+ else:
+ bmp = wx.EmptyBitmap(width, height, -1)
+ if hasattr(bmp, 'UseAlpha'):
+ bmp.UseAlpha()
+ return bmp
+
+#-----------------------------------------------------------------------------#
+
+class Freezer(object):
+ """Context manager for freezing window redraws"""
+ def __init__(self, window):
+ super(Freezer, self).__init__()
+
+ # Attributes
+ self.window = window
+
+ def __enter__(self):
+ if self.window:
+ self.window.Freeze()
+
+ def __exit__( self, type, value, tb):
+ if self.window:
+ self.window.Thaw()
+
+#-----------------------------------------------------------------------------#
+# Drawing helpers
+
+def DrawCircleCloseBmp(colour, backColour=None, option=DRAW_CIRCLE_SMALL):
+ """
+ Draws a small circular close button.
+ @param colour: Circle's background colour
+ @keyword backColour: pen colour for border and X
+ @keyword option: DRAW_CIRCLE_* value
+ @return: wxBitmap
+
+ """
+ assert option in __CircleDefs, "Invalid DRAW option!"
+
+ defs = __CircleDefs.get(option)
+ size = defs['size']
+ if option != DRAW_CIRCLE_SMALL:
+ # Adjust for border
+ diameter = size[0] - 1
+ else:
+ diameter = size[0]
+ radius = float(diameter) / 2.0
+ xpath = defs['xpath']
+
+ bmp = EmptyBitmapRGBA(size[0], size[1])
+ dc = wx.MemoryDC()
+ dc.SelectObject(bmp)
+ dc.Clear()
+
+ gc = wx.GraphicsContext.Create(dc)
+ gc.SetBrush(wx.Brush(colour))
+ if option > DRAW_CIRCLE_SMALL:
+ gc.SetPen(wx.Pen(AdjustColour(colour, -30)))
+ else:
+ gc.SetPen(wx.TRANSPARENT_PEN)
+
+ path = gc.CreatePath()
+ path.AddCircle(radius, radius, radius)
+ path.CloseSubpath()
+ gc.FillPath(path)
+ gc.StrokePath(path)
+
+ path = gc.CreatePath()
+ if backColour is not None:
+ pen = wx.Pen(backColour, 1)
+ else:
+ pen = wx.Pen("white", 1)
+
+ pen.SetCap(wx.CAP_BUTT)
+ pen.SetJoin(wx.JOIN_BEVEL)
+ gc.SetPen(pen)
+ path.MoveToPoint(*xpath[0])
+ path.AddLineToPoint(*xpath[1])
+ path.MoveToPoint(*xpath[2])
+ path.AddLineToPoint(*xpath[3])
+ path.CloseSubpath()
+ gc.DrawPath(path)
+
+ dc.SelectObject(wx.NullBitmap)
+ return bmp
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecpickers.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecpickers.py
new file mode 100644
index 0000000..cc587fa
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecpickers.py
@@ -0,0 +1,154 @@
+###############################################################################
+# Name: ecpickers.py #
+# Purpose: Custom picker controls #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: Editra Control Pickers
+
+Collection of various custom picker controls
+
+Class: PyFontPicker
+Custom font picker control
+
+@summary: Various custom picker controls
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ecpickers.py 70230 2012-01-01 01:47:42Z CJP $"
+__revision__ = "$Revision: 70230 $"
+
+__all__ = ['PyFontPicker', 'FontChangeEvent',
+ 'EVT_FONT_CHANGED', 'edEVT_FONT_CHANGED']
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+_ = wx.GetTranslation
+#-----------------------------------------------------------------------------#
+
+edEVT_FONT_CHANGED = wx.NewEventType()
+EVT_FONT_CHANGED = wx.PyEventBinder(edEVT_FONT_CHANGED, 1)
+class FontChangeEvent(wx.PyCommandEvent):
+ """General notification event"""
+ def __init__(self, etype, eid, value=None, obj=None):
+ super(FontChangeEvent, self).__init__(etype, eid)
+
+ # Attributes
+ self._value = value
+
+ # Setup
+ self.SetEventObject(obj)
+
+ def GetValue(self):
+ """Returns the value from the event.
+ @return: the value of this event
+
+ """
+ return self._value
+
+#-----------------------------------------------------------------------------#
+
+class PyFontPicker(wx.Panel):
+ """A slightly enhanced wx.FontPickerCtrl that displays the choosen font in
+ the label text using the choosen font as well as the font's size using
+ nicer formatting.
+
+ """
+ def __init__(self, parent, id_=wx.ID_ANY, default=wx.NullFont):
+ """Initializes the PyFontPicker
+ @param parent: Parent Window
+ @keyword id_: Control ID
+ @keyword default: The font to initialize as selected in the control
+
+ """
+ super(PyFontPicker, self).__init__(parent, id_, style=wx.NO_BORDER)
+
+ # Attributes
+ if default == wx.NullFont:
+ self._font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
+ else:
+ self._font = default
+
+ self._text = wx.StaticText(self)
+ self._text.SetFont(default)
+ self._text.SetLabel(u"%s - %dpt" % (self._font.GetFaceName(), \
+ self._font.GetPointSize()))
+ self._button = wx.Button(self, label=_("Set Font") + u'...')
+
+ # Layout
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.AddStretchSpacer()
+ sizer.Add(self._text, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddStretchSpacer()
+ sizer.Add(self._button, 0, wx.ALIGN_CENTER_VERTICAL)
+ vsizer.AddMany([((1, 1), 0), (sizer, 0, wx.EXPAND), ((1, 1), 0)])
+ self.SetSizer(vsizer)
+ self.SetAutoLayout(True)
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, lambda evt: self.ShowFontDlg(), self._button)
+ self.Bind(wx.EVT_FONTPICKER_CHANGED, self.OnChange)
+
+ def GetFontValue(self):
+ """Gets the currently choosen font
+ @return: wx.Font
+
+ """
+ return self._font
+
+ def GetTextCtrl(self):
+ """Gets the widgets text control
+ @return: wx.StaticText
+
+ """
+ return self._text
+
+ def OnChange(self, evt):
+ """Updates the text control using our custom stylings after
+ the font is changed.
+ @param evt: The event that called this handler
+
+ """
+ font = evt.GetFont()
+ if font.IsNull():
+ return
+ self._font = font
+ self._text.SetFont(self._font)
+ self._text.SetLabel(u"%s - %dpt" % (font.GetFaceName(), \
+ font.GetPointSize()))
+ self.Layout()
+ evt = FontChangeEvent(edEVT_FONT_CHANGED, self.GetId(), self._font, self)
+ wx.PostEvent(self.GetParent(), evt)
+
+ def SetButtonLabel(self, label):
+ """Sets the buttons label"""
+ self._button.SetLabel(label)
+ self._button.Refresh()
+ self.Layout()
+
+ def SetToolTipString(self, tip):
+ """Sets the tooltip of the window
+ @param tip: string
+
+ """
+ self._text.SetToolTipString(tip)
+ self._button.SetToolTipString(tip)
+ wx.Panel.SetToolTipString(self, tip)
+
+ def ShowFontDlg(self):
+ """Opens the FontDialog and processes the result"""
+ fdata = wx.FontData()
+ fdata.SetInitialFont(self._font)
+ fdlg = wx.FontDialog(self.GetParent(), fdata)
+ if fdlg.ShowModal() == wx.ID_OK:
+ fdata = fdlg.GetFontData()
+ wx.PostEvent(self, wx.FontPickerEvent(self, self.GetId(),
+ fdata.GetChosenFont()))
+ fdlg.Destroy()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistctrl.py
new file mode 100644
index 0000000..143e3fc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistctrl.py
@@ -0,0 +1,198 @@
+###############################################################################
+# Name: elistctrl.py #
+# Purpose: Base ListCtrl #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2010 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: EListCtrl
+
+Class EBaseListCtrl:
+Base Report mode ListCtrl class that highlights alternate rows
+
+Class ECheckListCtrl:
+Child class of L{EBaseListCtrl} that also provides CheckBoxes in the first
+column of the control.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: elistctrl.py 72221 2012-07-28 15:28:31Z CJP $"
+__revision__ = "$Revision: 72221 $"
+
+__all__ = ["EBaseListCtrl", "ECheckListCtrl", "EEditListCtrl",
+ "EToggleEditListCtrl"]
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import wx
+import wx.lib.mixins.listctrl as listmix
+
+# Local Imports
+import elistmix
+
+#--------------------------------------------------------------------------#
+
+class EBaseListCtrl(elistmix.ListRowHighlighter,
+ listmix.ListCtrlAutoWidthMixin,
+ wx.ListCtrl):
+ """Base listctrl class that provides automatic row highlighting"""
+ def __init__(self, parent, _id=wx.ID_ANY,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.LC_REPORT, validator=wx.DefaultValidator,
+ name="EListCtrl"):
+ wx.ListCtrl.__init__(self, parent, _id, pos, size,
+ style, validator, name)
+ elistmix.ListRowHighlighter.__init__(self)
+ listmix.ListCtrlAutoWidthMixin.__init__(self)
+
+ def EnableRow(self, idx, enable=True):
+ """Enable/Disable a row in the ListCtrl
+ @param idx: row index
+ @keyword enable: bool
+
+ """
+ state = 0
+ txtcolour = wx.SYS_COLOUR_LISTBOXTEXT
+ if not enable:
+ state = wx.LIST_STATE_DISABLED
+ txtcolour = wx.SYS_COLOUR_GRAYTEXT
+ self.SetItemState(idx, state, wx.LIST_STATE_DONTCARE)
+ colour = wx.SystemSettings.GetColour(txtcolour)
+ self.SetItemTextColour(idx, colour)
+
+ def GetRowData(self, idx):
+ """Get the values from each cell in the given row
+ @param idx: row index
+ @return: tuple
+
+ """
+ data = list()
+ if idx >= 0 and idx < self.GetItemCount():
+ for col in range(self.GetColumnCount()):
+ item = self.GetItem(idx, col)
+ data.append(item.Text)
+ return tuple(data)
+
+ def GetSelections(self):
+ """Get a list of all the selected items in the list
+ @return: list of ints
+
+ """
+ items = [ idx for idx in range(self.GetItemCount())
+ if self.IsSelected(idx) ]
+ return items
+
+ def HasSelection(self):
+ """Are any items selected in the list"""
+ return bool(len(self.GetSelections()))
+
+class ECheckListCtrl(listmix.CheckListCtrlMixin,
+ EBaseListCtrl):
+ """ListCtrl with CheckBoxes in the first column"""
+ def __init__(self, *args, **kwargs):
+ EBaseListCtrl.__init__(self, *args, **kwargs)
+ listmix.CheckListCtrlMixin.__init__(self)
+
+class EEditListCtrl(listmix.TextEditMixin,
+ EBaseListCtrl):
+ """ListCtrl with Editable cells"""
+ def __init__(self, *args, **kwargs):
+ EBaseListCtrl.__init__(self, *args, **kwargs)
+ listmix.TextEditMixin.__init__(self)
+
+ def OpenEditor(self, col, row):
+ """Work around limitation of TextEditMixin on Linux
+ where if the horizontal scroll bar is present it is not
+ possible to open the editor.
+ @param col: column to open editor at
+ @param row: row to pen editor at
+
+ """
+ # give the derived class a chance to Allow/Veto this edit.
+ evt = wx.ListEvent(wx.wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, self.Id)
+ evt.m_itemIndex = row
+ evt.m_col = col
+ item = self.GetItem(row, col)
+ evt.m_item.SetId(item.GetId())
+ evt.m_item.SetColumn(item.GetColumn())
+ evt.m_item.SetData(item.GetData())
+ evt.m_item.SetText(item.GetText())
+ ret = self.GetEventHandler().ProcessEvent(evt)
+ if ret and not evt.IsAllowed():
+ return # user code doesn't allow the edit.
+
+ if self.GetColumn(col).m_format != self.col_style:
+ self.make_editor(self.GetColumn(col).m_format)
+
+ x0 = self.col_locs[col]
+ x1 = self.col_locs[col+1] - x0
+
+ scrolloffset = self.GetScrollPos(wx.HORIZONTAL)
+
+ # scroll forward
+ if wx.Platform == "__WXMSW__" and x0+x1-scrolloffset > self.GetSize()[0]:
+ # don't start scrolling unless we really need to
+ offset = x0+x1-self.GetSize()[0]-scrolloffset
+ # scroll a bit more than what is minimum required
+ # so we don't have to scroll everytime the user presses TAB
+ # which is very tireing to the eye
+ addoffset = self.GetSize()[0]/4
+ # but be careful at the end of the list
+ if addoffset + scrolloffset < self.GetSize()[0]:
+ offset += addoffset
+
+ self.ScrollList(offset, 0)
+ scrolloffset = self.GetScrollPos(wx.HORIZONTAL)
+
+ y0 = self.GetItemRect(row)[1]
+
+ editor = self.editor
+ editor.SetDimensions(x0-scrolloffset,y0, x1,-1)
+
+ editor.SetValue(self.GetItem(row, col).GetText())
+ editor.Show()
+ editor.Raise()
+ editor.SetSelection(-1,-1)
+ editor.SetFocus()
+
+ self.curRow = row
+ self.curCol = col
+
+class EToggleEditListCtrl(listmix.CheckListCtrlMixin,
+ listmix.TextEditMixin,
+ EBaseListCtrl):
+ """ListCtrl with Editable cells and images that can be toggled in the
+ the first column.
+
+ """
+ def __init__(self, *args, **kwargs):
+ EBaseListCtrl.__init__(self, *args, **kwargs)
+ listmix.TextEditMixin.__init__(self)
+ listmix.CheckListCtrlMixin.__init__(self)
+ self.Unbind(wx.EVT_LEFT_DCLICK)
+
+ def GetCheckedItems(self):
+ """Get the list of checked indexes"""
+ count = self.GetItemCount()
+ return [item for item in range(count) if self.IsChecked(item)]
+
+ def SetCheckedBitmap(self, bmp):
+ """Set the bitmap to use for the Checked state
+ @param bmp: wx.Bitmap
+
+ """
+ assert isinstance(bmp, wx.Bitmap) and bmp.IsOk()
+ imgl = self.GetImageList(wx.IMAGE_LIST_SMALL)
+ imgl.Replace(self.check_image, bmp)
+
+ def SetUnCheckedBitmap(self, bmp):
+ """Set the bitmap to use for the un-Checked state
+ @param bmp: wx.Bitmap
+
+ """
+ assert isinstance(bmp, wx.Bitmap) and bmp.IsOk()
+ imgl = self.GetImageList(wx.IMAGE_LIST_SMALL)
+ imgl.Replace(self.uncheck_image, bmp)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistmix.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistmix.py
new file mode 100644
index 0000000..5f1eb85
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistmix.py
@@ -0,0 +1,103 @@
+###############################################################################
+# Name: elistmix.py #
+# Purpose: Custom Mixins for a wxListCtrl #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: EListMixins
+
+Class ListRowHighlighter:
+This mixin class can be used to add automatic highlighting of alternate rows
+in a ListCtrl.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: elistmix.py 66204 2010-11-18 14:00:28Z CJP $"
+__revision__ = "$Revision: 66204 $"
+
+__all__ = ["ListRowHighlighter", "HIGHLIGHT_EVEN", "HIGHLIGHT_ODD"]
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import wx
+
+#--------------------------------------------------------------------------#
+# Globals
+HIGHLIGHT_ODD = 1 # Highlight the Odd rows
+HIGHLIGHT_EVEN = 2 # Highlight the Even rows
+
+#--------------------------------------------------------------------------#
+
+class ListRowHighlighter:
+ """This mixin can be used to add automatic highlighting of alternate rows
+ in a list control.
+
+ """
+ def __init__(self, color=None, mode=HIGHLIGHT_EVEN):
+ """Initialize the highlighter
+ @keyword color: Set a custom highlight color (default uses system color)
+ @keyword mode: HIGHLIGHT_EVEN (default) or HIGHLIGHT_ODD
+
+ """
+ # Attributes
+ self._color = color
+ self._defaultb = wx.SystemSettings.GetColour(wx.SYS_COLOUR_LISTBOX)
+ self._mode = mode
+ self._refresh_timer = wx.Timer(self)
+
+ # Event Handlers
+ self.Bind(wx.EVT_LIST_INSERT_ITEM, lambda evt: self._RestartTimer())
+ self.Bind(wx.EVT_LIST_DELETE_ITEM, lambda evt: self._RestartTimer())
+ self.Bind(wx.EVT_TIMER,
+ lambda evt: self.RefreshRows(),
+ self._refresh_timer)
+
+ def _RestartTimer(self):
+ if self._refresh_timer.IsRunning():
+ self._refresh_timer.Stop()
+ self._refresh_timer.Start(100, oneShot=True)
+
+ def RefreshRows(self):
+ """Re-color all the rows"""
+ for row in range(self.GetItemCount()):
+ if self._defaultb is None:
+ self._defaultb = self.GetItemBackgroundColour(row)
+
+ if self._mode & HIGHLIGHT_EVEN:
+ dohlight = not row % 2
+ else:
+ dohlight = row % 2
+
+ if dohlight:
+ if self._color is None:
+ if wx.Platform in ['__WXGTK__', '__WXMSW__']:
+ color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DLIGHT)
+ else:
+ color = wx.Colour(237, 243, 254)
+ else:
+ color = self._color
+ else:
+ color = self._defaultb
+
+ self.SetItemBackgroundColour(row, color)
+
+ def SetHighlightColor(self, color):
+ """Set the color used to highlight the rows. Call L{RefreshRows} after
+ this if you wish to update all the rows highlight colors.
+ @param color: wx.Colour or None to set default
+
+ """
+ self._color = color
+
+ def SetHighlightMode(self, mode):
+ """Set the highlighting mode to either HIGHLIGHT_EVEN or to
+ HIGHLIGHT_ODD. Call L{RefreshRows} afterwards to update the list
+ state.
+ @param mode: HIGHLIGHT_* mode value
+
+ """
+ self._mode = mode
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/encdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/encdlg.py
new file mode 100644
index 0000000..a738840
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/encdlg.py
@@ -0,0 +1,97 @@
+###############################################################################
+# Name: encdlg.py #
+# Purpose: Encoding Dialog #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: Encoding Dialog
+
+A simple choice dialog for selecting a file encoding type from. The dialog
+can work with either a passed in list of choices to display or by default will
+list all encodings found on the system using their normalized names.
+
+@summary: Encoding choice dialog
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: encdlg.py 70230 2012-01-01 01:47:42Z CJP $"
+__revision__ = "$Revision: 70230 $"
+
+__all__ = ['EncodingDialog', 'GetAllEncodings']
+
+#--------------------------------------------------------------------------#
+# Imports
+import locale
+import encodings
+import wx
+
+# Editra Control Library Imports
+import choicedlg
+
+#--------------------------------------------------------------------------#
+# Globals
+EncodingDialogNameStr = u"EncodingDialog"
+
+#--------------------------------------------------------------------------#
+
+class EncodingDialog(choicedlg.ChoiceDialog):
+ """Dialog for choosing an file encoding from the list of available
+ encodings on the system.
+
+ """
+ def __init__(self, parent, id=wx.ID_ANY, msg=u'', title=u'',
+ elist=list(), default=u'',
+ style=wx.CAPTION, pos=wx.DefaultPosition,
+ size=wx.DefaultSize,
+ name=EncodingDialogNameStr):
+ """Create the encoding dialog
+ @param parent: Parent Window
+ @keyword id: Dialog ID
+ @keyword msg: Dialog Message
+ @keyword title: Dialog Title
+ @keyword elist: list of encodings to use or None to use all
+ @keyword default: Default selected encoding
+ @keyword style: Dialog Style bitmask
+ @keyword pos: Dialog Postion
+ @keyword size: Dialog Size
+ @keyword name: Dialog Name
+
+ """
+ if not len(elist):
+ elist = GetAllEncodings()
+
+ default = encodings.normalize_encoding(default)
+ if default and default.lower() in elist:
+ sel = default.lower()
+ else:
+ sel = locale.getpreferredencoding(False)
+
+ super(EncodingDialog, self).__init__(parent, id, msg, title,
+ elist, sel, pos, size, style)
+
+ def GetEncoding(self):
+ """Get the selected encoding
+ @return: string
+
+ """
+ return self.GetStringSelection()
+
+#--------------------------------------------------------------------------#
+# Utilities
+
+def GetAllEncodings():
+ """Get all encodings found on the system
+ @return: list of strings
+
+ """
+ elist = encodings.aliases.aliases.values()
+ elist = list(set(elist))
+ elist.sort()
+ elist = [ enc for enc in elist if not enc.endswith('codec') ]
+ return elist
+
+#--------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/errdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/errdlg.py
new file mode 100644
index 0000000..e4d78ca
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/errdlg.py
@@ -0,0 +1,370 @@
+###############################################################################
+# Name: errdlg.py #
+# Purpose: Error Reporter Dialog #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: Error Reporter Dialog
+
+Dialog for displaying exceptions and reporting errors to application maintainer.
+This dialog is intended as a base class and should be subclassed to fit the
+applications needs.
+
+This dialog should be initiated inside of a sys.excepthook handler.
+
+Example:
+
+sys.excepthook = ExceptHook
+...
+def ExceptionHook(exctype, value, trace):
+ # Format the traceback
+ ftrace = ErrorDialog.FormatTrace(exctype, value, trace)
+
+ # Ensure that error gets raised to console as well
+ print ftrace
+
+ # If abort has been set and we get here again do a more forceful shutdown
+ if ErrorDialog.ABORT:
+ os._exit(1)
+
+ # Prevent multiple reporter dialogs from opening at once
+ if not ErrorDialog.REPORTER_ACTIVE and not ErrorDialog.ABORT:
+ dlg = ErrorDialog(ftrace)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+@summary: Error Reporter Dialog
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: errdlg.py 70230 2012-01-01 01:47:42Z CJP $"
+__revision__ = "$Revision: 70230 $"
+
+__all__ = [# Classes
+ 'ErrorDialog', 'ErrorReporter',
+ # Functions
+ 'TimeStamp']
+
+#----------------------------------------------------------------------------#
+# Dependencies
+import os
+import sys
+import platform
+import time
+import traceback
+import wx
+
+# Local Imports
+import ecbasewin
+
+#----------------------------------------------------------------------------#
+# Globals
+_ = wx.GetTranslation
+
+#----------------------------------------------------------------------------#
+
+class ErrorReporter(object):
+ """Crash/Error Reporter Service
+ @summary: Stores all errors caught during the current session.
+ @note: singleton class
+
+ """
+ instance = None
+ _first = True
+ def __init__(self):
+ """Initialize the reporter
+ @note: The ErrorReporter is a singleton.
+
+ """
+ # Ensure init only happens once
+ if self._first:
+ super(ErrorReporter, self).__init__()
+ self._first = False
+ self._sessionerr = list()
+ else:
+ pass
+
+ def __new__(cls, *args, **kargs):
+ """Maintain only a single instance of this object
+ @return: instance of this class
+
+ """
+ if not cls.instance:
+ cls.instance = object.__new__(cls, *args, **kargs)
+ return cls.instance
+
+ def AddMessage(self, msg):
+ """Adds a message to the reporters list of session errors
+ @param msg: The Error Message to save
+
+ """
+ if msg not in self._sessionerr:
+ self._sessionerr.append(msg)
+
+ def GetErrorStack(self):
+ """Returns all the errors caught during this session
+ @return: formatted log message of errors
+
+ """
+ return (os.linesep * 2).join(self._sessionerr)
+
+ def GetLastError(self):
+ """Gets the last error from the current session
+ @return: Error Message String
+
+ """
+ if len(self._sessionerr):
+ return self._sessionerr[-1]
+
+#-----------------------------------------------------------------------------#
+
+class ErrorDialog(ecbasewin.ECBaseDlg):
+ """Dialog for showing errors and and notifying Editra.org should the
+ user choose so.
+
+ """
+ ID_SEND = wx.NewId()
+ ABORT = False
+ REPORTER_ACTIVE = False
+ def __init__(self, parent, id=wx.ID_ANY, title=u'',
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+ name="ErrorReporterDlg", message=u''):
+ """Initialize the dialog
+ @param parent: Parent Window
+ @keyword id: Dialog ID
+ @keyword title: Dialog Title
+ @keyword pos: Dialog Postion
+ @keyword size: Dialog Size
+ @keyword style: Dialog Style bitmask
+ @keyword name: Dialog Name
+ @param message: Error message to display
+
+ """
+ ErrorDialog.REPORTER_ACTIVE = True
+ super(ErrorDialog, self).__init__(parent, id, title, pos,
+ size, style, name)
+
+ # Give message to ErrorReporter
+ ErrorReporter().AddMessage(message)
+
+ # Attributes
+ self.err_msg = os.linesep.join((self.GetEnvironmentInfo(),
+ "#---- Traceback Info ----#",
+ ErrorReporter().GetErrorStack(),
+ "#---- End Traceback Info ----#"))
+
+ # Layout
+ self.SetPanel(ErrorPanel(self, self.err_msg))
+ self.SetMinSize(wx.Size(450, 300))
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+ # Auto show at end of init
+ self.CenterOnParent()
+
+ #---- Override in Subclass ----#
+
+ def Abort(self):
+ """Called to abort the application
+ @note: needs to be overridden in subclasses
+
+ """
+ raise NotImplementedError("Abort must be implemented!")
+
+ def GetEnvironmentInfo(self):
+ """Get the environmental info / Header of error report
+ @return: string
+
+ """
+ info = list()
+ info.append("#---- Notes ----#")
+ info.append("Please provide additional information about the crash here")
+ info.extend(["", ""])
+ info.append("#---- System Information ----#")
+ info.append(self.GetProgramName())
+ info.append("Operating System: %s" % wx.GetOsDescription())
+ if sys.platform == 'darwin':
+ info.append("Mac OSX: %s" % platform.mac_ver()[0])
+ info.append("Python Version: %s" % sys.version)
+ info.append("wxPython Version: %s" % wx.version())
+ info.append("wxPython Info: (%s)" % ", ".join(wx.PlatformInfo))
+ info.append("Python Encoding: Default=%s File=%s" % \
+ (sys.getdefaultencoding(), sys.getfilesystemencoding()))
+ info.append("wxPython Encoding: %s" % wx.GetDefaultPyEncoding())
+ info.append("System Architecture: %s %s" % (platform.architecture()[0], \
+ platform.machine()))
+ info.append("Byte order: %s" % sys.byteorder)
+ info.append("Frozen: %s" % str(getattr(sys, 'frozen', 'False')))
+ info.append("#---- End System Information ----#")
+ info.append("")
+ return os.linesep.join(info)
+
+ def GetProgramName(self):
+ """Get the program name/version info to include in error report
+ @return: string
+
+ """
+ return wx.GetApp().GetAppName()
+
+ def Send(self):
+ """Called to send error report
+ @note: needs to be overridden in subclasses
+
+ """
+ raise NotImplementedError("Send must be implemented!")
+
+ #---- End Required overrides ----#
+
+ @staticmethod
+ def FormatTrace(exctype, value, trace):
+ """Format the traceback
+ @return: string
+
+ """
+ exc = traceback.format_exception(exctype, value, trace)
+ exc.insert(0, u"*** %s ***%s" % (TimeStamp(), os.linesep))
+ ftrace = u"".join(exc)
+ return ftrace
+
+ def SetDescriptionLabel(self, label):
+ """Set the dialogs main description text
+ @param label: string
+
+ """
+ self._panel.SetDescriptionText(label)
+
+ def ShowAbortButton(self, show=True):
+ """Show/Hide the Abort button
+ @keyword show: bool
+
+ """
+ btn = self._panel.FindWindowById(wx.ID_ABORT)
+ if btn is not None:
+ btn.Show(show)
+ self._panel.Layout()
+
+ def ShowSendButton(self, show=True):
+ """Show/Hide the Send button
+ @keyword show: bool
+
+ """
+ btn = self._panel.FindWindowById(ErrorDialog.ID_SEND)
+ if btn is not None:
+ btn.Show(show)
+ self._panel.Layout()
+
+ #---- Event Handlers ----#
+
+ def OnButton(self, evt):
+ """Handles button events
+ @param evt: event that called this handler
+ @postcondition: Dialog is closed
+ @postcondition: If Report Event then email program is opened
+
+ """
+ e_id = evt.GetId()
+ if e_id == wx.ID_CLOSE:
+ self.Close()
+ elif e_id == ErrorDialog.ID_SEND:
+ self.Send()
+ self.Close()
+ elif e_id == wx.ID_ABORT:
+ ErrorDialog.ABORT = True
+ self.Abort()
+ self.Close()
+ else:
+ evt.Skip()
+
+ def OnClose(self, evt):
+ """Cleans up the dialog when it is closed
+ @param evt: Event that called this handler
+
+ """
+ ErrorDialog.REPORTER_ACTIVE = False
+ evt.Skip()
+
+#-----------------------------------------------------------------------------#
+
+class ErrorPanel(wx.Panel):
+ """Error Reporter panel"""
+ def __init__(self, parent, msg):
+ """Create the panel
+ @param parent: wx.Window
+ @param msg: Error message to display
+
+ """
+ super(ErrorPanel, self).__init__(parent)
+
+ # Attributes
+ self.err_msg = msg
+ self.desc = wx.StaticText(self, label=u'')
+
+ # Layout
+ self.__DoLayout()
+
+ def __DoLayout(self):
+ """Layout the control"""
+ icon = wx.StaticBitmap(self,
+ bitmap=wx.ArtProvider.GetBitmap(wx.ART_ERROR))
+ t_lbl = wx.StaticText(self, label=_("Error Traceback:"))
+ tctrl = wx.TextCtrl(self, value=self.err_msg, style=wx.TE_MULTILINE |
+ wx.TE_READONLY)
+
+ abort_b = wx.Button(self, wx.ID_ABORT, _("Abort"))
+ abort_b.SetToolTipString(_("Exit the application"))
+ send_b = wx.Button(self, ErrorDialog.ID_SEND, _("Report Error"))
+ send_b.SetDefault()
+ close_b = wx.Button(self, wx.ID_CLOSE)
+
+ # Layout
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+
+ hsizer1 = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer1.AddMany([((5, 5), 0), (icon, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((12, 5), 0), (self.desc, 0, wx.EXPAND), ((5, 5), 0)])
+
+ hsizer2 = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer2.AddMany([((5, 5), 0), (tctrl, 1, wx.EXPAND), ((5, 5), 0)])
+
+ bsizer = wx.BoxSizer(wx.HORIZONTAL)
+ bsizer.AddMany([((5, 5), 0), (abort_b, 0), ((-1, -1), 1, wx.EXPAND),
+ (send_b, 0), ((5, 5), 0), (close_b, 0), ((5, 5), 0)])
+
+ vsizer.AddMany([((5, 5), 0),
+ (hsizer1, 0),
+ ((10, 10), 0),
+ (t_lbl, 0, wx.ALIGN_LEFT|wx.LEFT, 5),
+ ((3, 3), 0),
+ (hsizer2, 1, wx.EXPAND),
+ ((8, 8), 0),
+ (bsizer, 0, wx.EXPAND),
+ ((8, 8), 0)])
+
+ self.SetSizer(vsizer)
+ self.SetAutoLayout(True)
+
+ def SetDescriptionText(self, text):
+ """Set the description label text
+ @param text: string
+
+ """
+ self.desc.SetLabel(text)
+ self.Layout()
+
+#-----------------------------------------------------------------------------#
+
+def TimeStamp():
+ """Create a formatted time stamp of current time
+ @return: Time stamp of the current time (Day Month Date HH:MM:SS Year)
+
+ """
+ now = time.localtime(time.time())
+ now = time.asctime(now)
+ return now
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filemgrdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filemgrdlg.py
new file mode 100644
index 0000000..1d8dda5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filemgrdlg.py
@@ -0,0 +1,259 @@
+###############################################################################
+# Name: filemgrdlg.py #
+# Purpose: Simple File Management Dialog #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: FileMgrDialog
+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: filemgrdlg.py 63361 2010-02-03 04:03:45Z CJP $"
+__revision__ = "$Revision: 63361 $"
+
+__all__ = ["FileMgrDialog",
+ "FMD_DEFAULT_STYLE", "FMD_NO_DELETE"]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import os
+import fnmatch
+import wx
+import wx.lib.mixins.listctrl as listmix
+
+# Eclib Imports
+import ecbasewin
+import elistmix
+
+#-----------------------------------------------------------------------------#
+# Globals
+
+# Style Flags
+FMD_DEFAULT_STYLE = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER
+FMD_NO_DELETE = 1
+
+
+_ = wx.GetTranslation
+
+#-----------------------------------------------------------------------------#
+
+class FileMgrDialog(ecbasewin.ECBaseDlg):
+ def __init__(self, parent, id=wx.ID_ANY, title=u"",
+ defaultPath=os.curdir, defaultFile=u'', filter="*",
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=FMD_DEFAULT_STYLE,
+ name=u"FileMgrDialog"):
+ ecbasewin.ECBaseDlg.__init__(self, parent, id, title,
+ pos, size, style, name)
+
+ # Attributes
+
+ # Setup
+ panel = FileMgrPanel(self, defaultPath, defaultFile, filter)
+ self.SetPanel(panel)
+ panel.EnableDeleteOption(not (FMD_NO_DELETE & style))
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnSave, id=wx.ID_SAVE)
+
+ def OnSave(self, evt):
+ """Exit the dialog"""
+ self.EndModal(wx.ID_OK)
+
+#-----------------------------------------------------------------------------#
+
+class FileMgrPanel(wx.Panel):
+ def __init__(self, parent, path, fname, filter):
+ wx.Panel.__init__(self, parent)
+
+ # Attributes
+ self._entry = wx.TextCtrl(self)
+ self._flist = None
+ self._path = path
+ self._filter = filter
+
+ # Setup
+ self.__DoLayout(fname)
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnDelete, id=wx.ID_DELETE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SAVE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_DELETE)
+ self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnFileSelected)
+
+ def __DoLayout(self, fname):
+ """Layout the panel
+ @param fname: default filename
+
+ """
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ statbox = wx.StaticBox(self)
+ sbsizer = wx.StaticBoxSizer(statbox, wx.VERTICAL)
+
+ # File List
+ self._flist = FileList(self)
+ self._flist.LoadFiles(self._path, self._filter)
+ sbsizer.Add(self._flist, 1, wx.EXPAND)
+ item = self._flist.FindItem(0, fname)
+ if item != wx.NOT_FOUND:
+ self._flist.Select(item)
+
+ fbtnsz = wx.BoxSizer(wx.HORIZONTAL)
+ dbtn = wx.Button(self, wx.ID_DELETE)
+ if wx.Platform == '__WXMAC__':
+ dbtn.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+ fbtnsz.AddStretchSpacer()
+ fbtnsz.Add(dbtn, 0, wx.ALIGN_RIGHT|wx.RIGHT, 5)
+ sbsizer.Add((5, 5), 0)
+ sbsizer.Add(fbtnsz, 0, wx.EXPAND)
+
+ vsizer.Add((10, 10), 0)
+ vsizer.Add(sbsizer, 1, wx.EXPAND|wx.ALL, 5)
+ vsizer.Add((10, 10), 0)
+
+ # File Name
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+ sa_lbl = wx.StaticText(self, label=_("Save As"))
+ hsizer.AddMany([(sa_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5), 0),
+ (self._entry, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL)])
+ self._entry.SetValue(fname)
+ vsizer.Add(hsizer, 0, wx.EXPAND|wx.ALL, 10)
+ vsizer.Add((10, 10), 0)
+
+ # Buttons
+ save = wx.Button(self, wx.ID_SAVE)
+ cancel = wx.Button(self, wx.ID_CANCEL)
+ cancel.SetDefault()
+ bsizer = wx.StdDialogButtonSizer()
+ bsizer.AddButton(save)
+ bsizer.AddButton(cancel)
+ bsizer.Realize()
+ vsizer.Add(bsizer, 0, wx.EXPAND|wx.BOTTOM, 8)
+
+ self.SetSizer(vsizer)
+
+ def EnableDeleteOption(self, enable=True):
+ """Enable/Disable the Delete Option
+ @keyword enable: bool
+
+ """
+ del_btn = self.FindWindowById(wx.ID_DELETE)
+ del_btn.Show(enable)
+ self.Layout()
+
+ @ecbasewin.expose(FileMgrDialog)
+ def GetSelectedFile(self):
+ """Get the selected filename
+ @return: string
+
+ """
+ item = self._flist.GetFocusedItem()
+ if item != -1:
+ item = self._flist.GetItem(item, 0)
+ fname = item.GetText()
+ return fname
+ return u""
+
+ def OnDelete(self, evt):
+ """Prompt to delete file the selected file"""
+ fname = self.GetSelectedFile()
+ if fname and os.path.exists(fname):
+ if wx.MessageBox(_("Are you sure want to delete %s?") % fname,
+ _("Delete File?"),
+ wx.ICON_WARNING|wx.OK|wx.CANCEL|wx.CENTER,
+ self) == wx.OK:
+ try:
+ os.remove(fname)
+ except OSError:
+ wx.MessageBox(_("Unable to delete %s") % fname,
+ _("Delete Error"),
+ wx.ICON_ERROR|wx.OK|wx.CENTER)
+ else:
+ # Refresh the list
+ self._flist.DeleteAllItems()
+ self._flist.LoadFiles(self._path, self._filter)
+
+ def OnFileSelected(self, evt):
+ """Update the name in the save as field when a selection is made
+ in the list control.
+
+ """
+ fname = self.GetSelectedFile()
+ self._entry.SetValue(fname)
+
+ def OnUpdateUI(self, evt):
+ """Enable/Disable the Save button depending on what is entered in the
+ filename dialog.
+
+ """
+ e_id = evt.GetId()
+ if e_id == wx.ID_SAVE:
+ evt.Enable(bool(self._entry.GetValue()))
+ elif e_id == wx.ID_DELETE:
+ evt.Enable(self._flist.GetFirstSelected() != -1)
+
+#-----------------------------------------------------------------------------#
+
+class FileList(wx.ListCtrl,
+ listmix.ListCtrlAutoWidthMixin,
+ elistmix.ListRowHighlighter):
+ def __init__(self, parent):
+ wx.ListCtrl.__init__(self, parent,
+ style=wx.LC_REPORT|
+ wx.LC_SORT_ASCENDING|
+ wx.LC_VRULES|
+ wx.LC_SINGLE_SEL)
+ listmix.ListCtrlAutoWidthMixin.__init__(self)
+ elistmix.ListRowHighlighter.__init__(self)
+
+ # Attributes
+
+ # Setup
+ self.InsertColumn(0, _("Files"))
+ il = wx.ImageList(16, 16)
+ self.imgidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_MENU, (16, 16)))
+ self.AssignImageList(il, wx.IMAGE_LIST_SMALL)
+ self.setResizeColumn(0)
+
+ def LoadFiles(self, path, wildcards="*"):
+ """Load all files from the given path
+ @param path: directory to list
+ @keyword wildcards: ; separated string of wildcard patterns
+
+ """
+ assert os.path.exists(path), "Invalid Path"
+ flist = list()
+ patterns = wildcards.split(';')
+ for fname in os.listdir(path):
+ for pattern in patterns:
+ if fnmatch.fnmatchcase(fname, pattern):
+ flist.append(fname)
+ break
+ flist.sort()
+ self.SetFiles(flist)
+
+ def SetFiles(self, files):
+ """Set the files in the list
+ @param files: list of files
+
+ """
+ for idx, fname in enumerate(files):
+ self.Append((fname,))
+ self.SetItemImage(self.GetItemCount() - 1, self.imgidx)
+
+#-----------------------------------------------------------------------------#
+
+if __name__ == '__main__':
+ app = wx.App(False)
+ frame = wx.Frame(None)
+ dlg = FileMgrDialog(frame, title="HELLO", defaultFile=u'eclutil.py',
+ style=FMD_DEFAULT_STYLE)
+ dlg.ShowModal()
+ frame.Destroy()
+ app.MainLoop()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filterdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filterdlg.py
new file mode 100644
index 0000000..05a7ddf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filterdlg.py
@@ -0,0 +1,179 @@
+###############################################################################
+# Name: filterdlg.py #
+# Purpose: Filter dialog #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: FilterDialog
+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: filterdlg.py 65202 2010-08-06 15:49:23Z CJP $"
+__revision__ = "$Revision: 65202 $"
+
+__all__ = ["FilterDialog",]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+# Eclib Imports
+import ecbasewin
+
+#-----------------------------------------------------------------------------#
+# Globals
+
+_ = wx.GetTranslation
+
+#-----------------------------------------------------------------------------#
+
+class FilterDialog(ecbasewin.ECBaseDlg):
+ """Dialog that allows adding and removing items from a filter list"""
+ def __init__(self, parent, id=wx.ID_ANY, title=u"",
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_DIALOG_STYLE, name=u"FilterDialog"):
+ super(FilterDialog, self).__init__(parent, id, title,
+ pos, size, style, name)
+
+ # Attributes
+ self.SetPanel(FilterPanel(self))
+
+ # Event Handlers
+
+#-----------------------------------------------------------------------------#
+
+class FilterPanel(wx.Panel):
+ """Filter dialog panel"""
+ def __init__(self, parent):
+ super(FilterPanel, self).__init__(parent)
+
+ # Attributes
+ self._left = wx.ListBox(self, style=wx.LB_EXTENDED|wx.LB_SORT)
+ self._right = wx.ListBox(self, style=wx.LB_EXTENDED)
+
+ self.__DoLayout()
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateButton, id=wx.ID_ADD)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateButton, id=wx.ID_REMOVE)
+
+ def __DoLayout(self):
+ """Layout the panel"""
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ hsizer.Add(self._left, 1, wx.EXPAND|wx.ALL, 10)
+
+ # Add buttons
+ bvsizer = wx.BoxSizer(wx.VERTICAL)
+ addb = wx.Button(self, wx.ID_ADD, label=_("Add >>"))
+ removeb = wx.Button(self, wx.ID_REMOVE, label=_("<< Remove"))
+ bvsizer.AddStretchSpacer()
+ bvsizer.AddMany([(addb, 0, wx.EXPAND),
+ ((10, 15), 0),
+ (removeb, 0, wx.EXPAND)])
+ bvsizer.AddStretchSpacer()
+
+ hsizer.Add(bvsizer, 0, wx.ALIGN_CENTER)
+ hsizer.Add(self._right, 1, wx.EXPAND|wx.ALL, 10)
+
+ vsizer.Add(hsizer, 1, wx.EXPAND)
+
+ # Add main dialog buttons
+ bsizer = wx.StdDialogButtonSizer()
+ bsizer.AddButton(wx.Button(self, wx.ID_OK))
+ btn = wx.Button(self, wx.ID_CANCEL)
+ bsizer.AddButton(btn)
+ btn.SetDefault()
+ bsizer.Realize()
+ vsizer.Add(bsizer, 0, wx.ALIGN_RIGHT)
+ vsizer.AddSpacer(8)
+
+ self.SetSizer(vsizer)
+ self.SetAutoLayout(True)
+
+ @ecbasewin.expose(FilterDialog)
+ def GetIncludes(self):
+ """Get the items from the includes list
+ @return: list of strings
+
+ """
+ return self._right.GetItems()
+
+ @ecbasewin.expose(FilterDialog)
+ def SetIncludes(self, items):
+ """Set the items in the includes list
+ @param items: list of strings
+
+ """
+ return self._right.SetItems(items)
+
+ @ecbasewin.expose(FilterDialog)
+ def GetExcludes(self):
+ """Get the items from the excludes list
+ @return: list of strings
+
+ """
+ return self._left.GetItems()
+
+ @ecbasewin.expose(FilterDialog)
+ def SetExcludes(self, items):
+ """set the items in the excludes list
+ @param items: list of strings
+
+ """
+ return self._left.SetItems(items)
+
+ @ecbasewin.expose(FilterDialog)
+ def SetListValues(self, valuemap):
+ """Set the values of the filter lists
+ @param valuemap: dict(item=bool)
+
+ """
+ includes = list()
+ excludes = list()
+ for item, include in valuemap.iteritems():
+ if include:
+ includes.append(item)
+ else:
+ excludes.append(item)
+ includes.sort()
+ excludes.sort()
+ self.SetIncludes(includes)
+ self.SetExcludes(excludes)
+
+ def OnButton(self, evt):
+ e_id = evt.GetId()
+ if e_id in (wx.ID_ADD, wx.ID_REMOVE):
+ cmap = { wx.ID_ADD : (self._left, self._right),
+ wx.ID_REMOVE : (self._right, self._left) }
+ idxs = list()
+ for sel in cmap[e_id][0].GetSelections():
+ selstr = cmap[e_id][0].GetString(sel)
+ cmap[e_id][1].Append(selstr)
+ idxs.append(sel)
+ idxs.sort()
+ idxs.reverse()
+ for idx in idxs:
+ cmap[e_id][0].Delete(idx)
+ else:
+ evt.Skip()
+
+ def OnUpdateButton(self, evt):
+ """Enable/Disable the Add/Remove buttons based on
+ selections in the list.
+
+ """
+ e_id = evt.GetId()
+ if e_id == wx.ID_ADD:
+ evt.Enable(len(self._left.GetSelections()))
+ elif e_id == wx.ID_REMOVE:
+ evt.Enable(len(self._right.GetSelections()))
+ else:
+ evt.Skip()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/finddlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/finddlg.py
new file mode 100644
index 0000000..8e1f73d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/finddlg.py
@@ -0,0 +1,1347 @@
+###############################################################################
+# Name: finddlg.py #
+# Purpose: Custom advanced find dialog #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: Advanced Find Replace Dialog
+
+The AdvancedFindReplaceDialog is a custom FindReplaceDlg that functions
+similarly to the standard wx.FindReplaceDialog but provides more search
+configuration and presentation options.
+
+The following items are the options that the AdvancedFindReplaceDialog offers
+over the basic FindReplaceDialog.
+
+ * Hide/Show each option or section individually (basic dialog only disables them)
+ * Multi-Find/Replace event action for Find All / Replace All actions
+ * Switch dialog from Find mode to Replace mode or visa-versa once its already
+ been created.
+ * Options for specifying the location to look in.
+ * Regular Expression option
+ * Use standard dialog or a floating MiniFrame (default)
+
+Requirements:
+python 2.4+
+wxPython 2.8+
+eclib.platebtn
+eclib.ctrlbox
+
+@todo: Make Look In location strings configurable
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: finddlg.py 71666 2012-06-06 17:55:42Z CJP $"
+__revision__ = "$Revision: 71666 $"
+
+__all__ = ["FindBox", "FindEvent", "FindPanel", "FindReplaceDlg",
+ "MiniFindReplaceDlg", "AdvFindReplaceDlg",
+
+ "AFR_STYLE_FINDDIALOG", "AFR_STYLE_REPLACEDIALOG",
+ "AFR_STYLE_NON_FLOATING", "AFR_STYLE_NO_MODE_SELECT",
+
+ "AFR_UP", "AFR_WHOLEWORD",
+ "AFR_MATCHCASE", "AFR_REGEX", "AFR_RECURSIVE", "AFR_NOLOOKIN",
+ "AFR_NOUPDOWN", "AFR_NOWHOLEWORD", "AFR_NOMATCHCASE", "AFR_NOREGEX",
+ "AFR_NOFILTER", "AFR_NOOPTIONS", "AFR_NO_COUNT", "AFR_NO_ALL_BTN",
+ "AFR_SIMPLE",
+
+ "LOCATION_CURRENT_DOC", "LOCATION_IN_SELECTION",
+ "LOCATION_OPEN_DOCS", "LOCATION_IN_CURRENT_DIR",
+ "LOCATION_IN_FILES", "LOCATION_MAX",
+
+ "edEVT_FIND_CLOSE", "EVT_FIND_CLOSE", "edEVT_FIND", "EVT_FIND",
+ "edEVT_FIND_NEXT", "EVT_FIND_NEXT", "edEVT_FIND_ALL", "EVT_FIND_ALL",
+ "edEVT_REPLACE", "EVT_REPLACE", "edEVT_REPLACE_ALL",
+ "EVT_REPLACE_ALL", "EVT_OPTION_CHANGED", "edEVT_OPTION_CHANGED",
+ "EVT_COUNT", "edEVT_COUNT"]
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import wx
+
+# Local Imports
+import ctrlbox
+import platebtn
+
+#--------------------------------------------------------------------------#
+# Globals
+
+# Style Flags
+AFR_STYLE_FINDDIALOG = 0 # Start dialog in Find mode
+AFR_STYLE_REPLACEDIALOG = 1 # Start dialog in Replace mode
+AFR_STYLE_NON_FLOATING = 2 # Use a standard dialog as the tlw
+AFR_STYLE_NO_MODE_SELECT = 4 # Hide the mode selector buttons
+
+# FindReplaceData Flags
+AFR_UP = 1 # Set dialogs Search Up flag
+AFR_WHOLEWORD = 2 # Set dialogs whole word search flag
+AFR_MATCHCASE = 4 # Set dialogs match case search flag
+AFR_REGEX = 8 # Set dialogs use regular expression flag
+AFR_RECURSIVE = 16 # Set dialogs recursive directory search flag
+AFR_NOLOOKIN = 32 # Hide the Looking combobox in the dialog
+AFR_NOUPDOWN = 64 # Hide the Direction options in the dialog
+AFR_NOWHOLEWORD = 128 # Hide the Whole Word option in the dialog
+AFR_NOMATCHCASE = 256 # Hide the Match Case option in the dialog
+AFR_NOREGEX = 512 # Hide the Regular Expression option
+AFR_NOFILTER = 1024 # Hide the File Filter option
+AFR_NOOPTIONS = 2048 # Hide all options in the dialog
+AFR_NO_COUNT = 4096 # Hide Count Button
+AFR_NO_ALL_BTN = 8192 # Hide Find All / Replace All buttons
+
+# Convenience Flags
+AFR_SIMPLE = (AFR_NOLOOKIN | AFR_NOOPTIONS | AFR_NOUPDOWN | \
+ AFR_NO_COUNT | AFR_NO_ALL_BTN)
+
+# Search Location Parameters (NOTE: must be kept in sync with Lookin List)
+LOCATION_CURRENT_DOC = 0
+LOCATION_IN_SELECTION = 1
+LOCATION_OPEN_DOCS = 2
+LOCATION_IN_CURRENT_DIR = 3
+LOCATION_IN_FILES = 4
+LOCATION_MAX = LOCATION_IN_CURRENT_DIR
+
+# Control Names
+FindBoxName = "EdFindBox"
+FindPanelName = "EdFindPanel"
+
+# Find Panel Control Ids
+ID_LOOKIN = wx.NewId()
+ID_FIND_LBL = wx.NewId()
+ID_REPLACE_LBL = wx.NewId()
+ID_MATCH_CASE = wx.NewId()
+ID_WHOLE_WORD = wx.NewId()
+ID_REGEX = wx.NewId()
+ID_RECURSE = wx.NewId()
+ID_COUNT = wx.NewId()
+ID_FIND_ALL = wx.NewId()
+ID_REPLACE_ALL = wx.NewId()
+ID_OPTION_CHANGE = wx.NewId()
+ID_CHOOSE_DIR = wx.NewId()
+ID_DIR_BOX = wx.NewId()
+
+_ = wx.GetTranslation
+
+#--------------------------------------------------------------------------#
+
+# Events Definitions
+
+# Find dialog has been closed
+edEVT_FIND_CLOSE = wx.NewEventType()
+EVT_FIND_CLOSE = wx.PyEventBinder(edEVT_FIND_CLOSE, 1)
+
+# Find cutton clicked
+edEVT_FIND = wx.NewEventType()
+EVT_FIND = wx.PyEventBinder(edEVT_FIND, 1)
+
+# Find cutton clicked again with the same search string
+edEVT_FIND_NEXT = wx.NewEventType()
+EVT_FIND_NEXT = wx.PyEventBinder(edEVT_FIND_NEXT, 1)
+
+# Find All button clicked
+edEVT_FIND_ALL = wx.NewEventType()
+EVT_FIND_ALL = wx.PyEventBinder(edEVT_FIND_ALL, 1)
+
+# Replace button clicked
+edEVT_REPLACE = wx.NewEventType()
+EVT_REPLACE = wx.PyEventBinder(edEVT_REPLACE, 1)
+
+# Replace button clicked
+edEVT_COUNT = wx.NewEventType()
+EVT_COUNT = wx.PyEventBinder(edEVT_COUNT, 1)
+
+# Replace All button clicked
+edEVT_REPLACE_ALL = wx.NewEventType()
+EVT_REPLACE_ALL = wx.PyEventBinder(edEVT_REPLACE_ALL, 1)
+
+# Find option has changed
+edEVT_OPTION_CHANGED = wx.NewEventType()
+EVT_OPTION_CHANGED = wx.PyEventBinder(edEVT_OPTION_CHANGED, 1)
+
+# Convenience for generating events
+_EVENT_MAP = { wx.ID_FIND : edEVT_FIND,
+ wx.ID_REPLACE : edEVT_REPLACE,
+ ID_COUNT : edEVT_COUNT,
+ ID_FIND_ALL : edEVT_FIND_ALL,
+ ID_REPLACE_ALL : edEVT_REPLACE_ALL,
+ ID_OPTION_CHANGE : edEVT_OPTION_CHANGED }
+
+class FindEvent(wx.PyCommandEvent):
+ """Event sent by the FindReplaceDialog that contains all
+ options of the FindReplaceData and requested action of the
+ find dialog
+
+ """
+ def __init__(self, etype, eid=wx.ID_ANY, flags=0):
+ """Creates the event object
+ @param etype: Event Type
+ @keyword eid: Event ID
+ @keyword flags: Find/Replace flags
+
+ """
+ super(FindEvent, self).__init__(etype, eid)
+
+ # Attributes
+ self._flags = flags
+ self._loc = 0
+ self._find = u''
+ self._replace = u''
+ self._dir = u''
+ self._filters = None
+ self._count = 0
+
+ def GetCount(self):
+ """Get the number of matches
+ @return: int
+
+ """
+ return self._count
+
+ def GetDirectory(self):
+ """Get the directory of files to search in
+ @return: string
+
+ """
+ return self._dir
+
+ def GetFileFilters(self):
+ """Get the filter to search with
+ @return: list or None
+
+ """
+ return self._filters
+
+ def GetFindString(self):
+ """Get the find string
+ @return: string
+
+ """
+ return self._find
+
+ def GetFlags(self):
+ """Get the search flags
+ @return: long
+
+ """
+ return self._flags
+
+ def GetReplaceString(self):
+ """Set the find String
+ @return: string
+
+ """
+ return self._replace
+
+ def GetSearchType(self):
+ """Get the type of search (current buffer, open documents, ect...)
+ @return: int (see LOCATION_* flags)
+
+ """
+ return self._loc
+
+ def SetCount(self, count):
+ """Set the count
+ @param count: int
+
+ """
+ self._count = count
+
+ def SetDirectory(self, directory):
+ """Set the directory of files to search in
+ @param directory: string
+
+ """
+ self._dir = directory
+
+ def SetFileFilters(self, filters):
+ """Set the file filters to use for a Search In Files event
+ @param filters: string or list of strings
+
+ """
+ if isinstance(filters, basestring):
+ self._filters = filters.split()
+ else:
+ self._filters = filters
+
+ if self._filters is not None:
+ self._filters = [ f.strip() for f in self._filters ]
+
+ def SetFindString(self, find):
+ """Set the find String
+ @param find: string
+
+ """
+ self._find = find
+
+ def SetFlags(self, flags):
+ """Returns the value from the event.
+ @return: the value of this event
+
+ """
+ self._flags = flags
+
+ def SetReplaceString(self, rstring):
+ """Set the find String
+ @param rstring: string
+
+ """
+ self._replace = rstring
+
+ def SetSearchType(self, stype):
+ """Set the type of search (current buffer, open documents, ect...)
+ @param stype: int (see LOCATION_* flags)
+
+ """
+ self._loc = stype
+
+ def IsMatchCase(self):
+ """Is this a match case search
+ @return: bool
+
+ """
+ return bool(self._flags & AFR_MATCHCASE)
+
+ def IsRecursive(self):
+ """Is the search option for recursive directory search enabled
+ @return: bool
+
+ """
+ return bool(self._flags & AFR_RECURSIVE)
+
+ def IsRegEx(self):
+ """Is RegEx enabled in the dialog
+ @return: bool
+
+ """
+ return bool(self._flags & AFR_REGEX)
+
+ def IsWholeWord(self):
+ """Is this a whole word search
+ @return: bool
+
+ """
+ return bool(self._flags & AFR_WHOLEWORD)
+
+ def IsUp(self):
+ """Is the search searching up
+ @return: bool
+
+ """
+ return bool(self._flags & AFR_UP)
+
+#--------------------------------------------------------------------------#
+
+def AdvFindReplaceDlg(parent, fdata, title, style=AFR_STYLE_FINDDIALOG):
+ """Advanced FindReplaceDialog. Create and return the requested dialog type
+ @param parent: parent
+ @param fdata: FindReplaceData
+ @param title: Dialog Title. Pass a single string to set the title for both
+ modes of the dialog or a tuple of two strings to set the title
+ for (find, replace) modes.
+ @keyword style: Dialog Style and type
+ @note: this is a function not a class
+
+ """
+ if style & AFR_STYLE_NON_FLOATING:
+ dlg = FindReplaceDlg(parent, fdata, title, style)
+ else:
+ dlg = MiniFindReplaceDlg(parent, fdata, title, style)
+
+ return dlg
+
+#--------------------------------------------------------------------------#
+
+class FindReplaceDlgBase:
+ """Delegate mixin base class for deriving FindReplaceDialogs, delegates
+ calls to the widgets and containers that make up the dialog.
+ @note: The mixin must be initialized after the class its being mixed into
+
+ """
+ def __init__(self, parent, fdata, title, style=AFR_STYLE_FINDDIALOG):
+ """Create the base object
+ @param title: string or tuple (findstr, replacestr)
+
+ """
+ # Attributes
+ if isinstance(title, basestring):
+ self._ftitle = title
+ self._rtitle = title
+ else:
+ self._ftitle, self._rtitle = title[:2]
+
+ self._box = FindBox(self, fdata, style=style)
+ self._panel = self._box.GetWindow()
+ self._accl = wx.AcceleratorTable([(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, wx.ID_CLOSE),])
+ self.SetAcceleratorTable(self._accl)
+
+ # Layout
+ self.__DoLayout()
+ tmp_title = self._ftitle
+ if style & AFR_STYLE_REPLACEDIALOG:
+ tmp_title = self._rtitle
+ self.SetTitle(tmp_title)
+
+ # Event handlers
+ self.Bind(_EVT_MODE_CHANGE, self._OnModeChange)
+ self.Bind(_EVT_DO_CLOSE_DLG, lambda evt: self._SendCloseEvent())
+ self.Bind(wx.EVT_MENU, lambda evt: self._SendCloseEvent(), id=wx.ID_CLOSE)
+ self.Bind(wx.EVT_SET_FOCUS, self._OnSetFocus)
+ self.Bind(wx.EVT_SHOW, self._OnShow)
+
+ def __DoLayout(self):
+ """Layout the dialog"""
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ vsizer.Add(self._box, 1, wx.EXPAND)
+ self.SetSizer(vsizer)
+ self.SetAutoLayout(True)
+ self.Fit()
+
+ def _SendCloseEvent(self):
+ """Send a dialog close event and hide the dialog"""
+ data = self._panel.GetData()
+ data.SetFindString(self._panel._ftxt.GetValue())
+ data.SetReplaceString(self._panel._rtxt.GetValue())
+ evt = FindEvent(edEVT_FIND_CLOSE, self.GetId())
+ self.Hide()
+ wx.PostEvent(self.GetParent(), evt)
+
+ def _OnModeChange(self, evt):
+ """Update the the dialog when the mode changes"""
+ self.Fit()
+ title = self._ftitle
+ if self.GetDialogMode() != AFR_STYLE_FINDDIALOG:
+ title = self._rtitle
+ self.SetTitle(title)
+
+ def _OnSetFocus(self, evt):
+ if self and self._panel:
+ self._panel.SetFocus()
+ evt.Skip()
+
+ def _OnShow(self, evt):
+ if self and self._panel:
+ self._panel.SetFocus()
+
+ def GetData(self):
+ """Get the FindReplaceData used by this dialog"""
+ return self._panel.GetData()
+
+ def GetDialogMode(self):
+ """Get the current mode of the dialog
+ @return: AFR_STYLE_FINDDIALOG or AFR_STYLE_REPLACEDIALOG
+
+ """
+ return self._panel.GetPanelMode()
+
+ def GetFileFilters(self):
+ """Get the file filters field value
+ @return: string
+
+ """
+ return self._panel.GetFileFilters()
+
+ def GetLookinChoices(self):
+ """Get the set choices from the looking choice list
+ @return: list of strings
+
+ """
+ return self._panel.GetLookinChoices()
+
+ def GetLookinSelection(self):
+ """Get the index of the selected item in the lookin choice list
+ @return: int
+
+ """
+ return self._panel.GetLookinSelection()
+
+ def RefreshFindReplaceFields(self):
+ """Refresh the values of the Find and Replace fields with the
+ values that are currently in the FindReplaceData.
+
+ """
+ data = self.GetData()
+ self._panel.SetFindString(data.GetFindString())
+ self._panel.SetReplaceString(data.GetReplaceString())
+
+ def RefreshFindOptions(self):
+ """Refresh the find options controls based on the current
+ values of the FindData owned by this window.
+
+ """
+ self._panel.RefreshControls()
+
+ def SetData(self, data):
+ """Set the dialogs FindReplaceData
+ @param data: FindReplaceData
+ @note: causes updates in dialog
+
+ """
+ self._panel.SetData(data)
+
+ def SetDialogMode(self, mode):
+ """Set the dialog mode between find and find/replace
+ @param mode: AFR_STYLE_FINDDIALOG or AFR_STYLE_REPLACEDIALOG
+
+ """
+ self._box.SetBoxMode(mode == AFR_STYLE_FINDDIALOG)
+
+ def SetDirectoryGetter(self, dgetter):
+ """Set a callback for retrieving the current directory. This method
+ is used for providing context when popping up dialogs such as the
+ Choose Directory dialog.
+ @param dgetter: callable() => unicode
+
+ """
+ self._panel.SetDirectoryGetter(dgetter)
+
+ def SetFileFilters(self, filters):
+ """Set the file filters field value
+ @param filters: string
+
+ """
+ self._panel.SetFileFilters(filters)
+
+ def SetFindBitmap(self, bmp):
+ """Set the find Bitmap
+ @param bmp: wx.Bitmap
+
+ """
+ self._box.SetFindBitmap(bmp)
+
+ def SetFlag(self, flags):
+ """Set a search dialog flag.
+ @param flags: AFR_*
+
+ """
+ self._panel.SetFlag(flags)
+
+ def SetFlags(self, flags):
+ """Set the search dialog flags.
+ @param flags: bitmask of AFR_ values
+
+ """
+ self._panel.SetFlags(flags)
+
+ def SetLookinChoices(self, paths):
+ """Set the looking choices
+ @param paths: list of strings
+
+ """
+ self._panel.SetLookinChoices(paths)
+
+ def SetLookinPath(self, path):
+ """Set the lookin path, adding it to the collection if it is
+ not in there.
+ @param path: string (path of directory)
+
+ """
+ idx = self._panel.AddLookinPath(path)
+ self.SetLookinSelection(idx)
+
+ def SetLookinSelection(self, sel):
+ """Set the looking choices selection
+ @param sel: int
+
+ """
+ self._panel.SetLookinSelection(sel)
+
+ def SetReplaceBitmap(self, bmp):
+ """Set the replace bitmap
+ @param bmp: wx.Bitmap
+
+ """
+ self._box.SetReplaceBitmap(bmp)
+
+ def SetFindDirectory(self, path):
+ """Set the directory selection for find in files
+ @param path: path to set for lookin data
+
+ """
+ self._panel.SetLookinSelection(path)
+
+ def SetFindString(self, query):
+ """Set the find controls search string
+ @param query: string
+
+ """
+ self._panel.SetFindString(query)
+
+ def SetReplaceString(self, rstring):
+ """Set the replace controls search string
+ @param rstring: string
+
+ """
+ self._panel.SetReplaceString(rstring)
+
+#--------------------------------------------------------------------------#
+
+class MiniFindReplaceDlg(wx.MiniFrame, FindReplaceDlgBase):
+ """Advanced Find Replace Dialog this version of the dialog uses a
+ MiniFrame that will float on top of its parent
+
+ """
+ def __init__(self, parent, fdata, title, style=AFR_STYLE_FINDDIALOG):
+ """Create the Dialog
+ @param parent: Parent Window
+ @param fdata: wx.FindReplaceData
+ @param title: Dialog Title. Pass a single string to set the title for
+ both modes of the dialog or a tuple of two strings to set
+ the title for (find, replace) modes.
+ @keyword style: Dialog Style
+
+ """
+ wx.MiniFrame.__init__(self, parent, wx.ID_ANY, u'',
+ style=wx.DEFAULT_DIALOG_STYLE)
+ FindReplaceDlgBase.__init__(self, parent, fdata, title, style)
+
+ # Event handlers
+ self.Bind(wx.EVT_CLOSE, lambda evt: self._SendCloseEvent())
+
+#--------------------------------------------------------------------------#
+
+class FindReplaceDlg(wx.Dialog, FindReplaceDlgBase):
+ """Advanced Find Replace Dialog this version of the dialog uses a standard
+ dialog window.
+
+ """
+ def __init__(self, parent, fdata, title, style=AFR_STYLE_FINDDIALOG):
+ """Create the Dialog
+ @param parent: Parent Window
+ @param fdata: wx.FindReplaceData
+ @param title: Dialog Title can be a string to set the title for both
+ modes or a tuple of two strings to set the (find, replace)
+ mode titles.
+ @keyword style: Dialog Style
+
+ """
+ wx.Dialog.__init__(self, parent, wx.ID_ANY, u'',
+ style=wx.DEFAULT_DIALOG_STYLE)
+ FindReplaceDlgBase.__init__(self, parent, fdata, title, style)
+
+ # Event handlers
+ self.Bind(wx.EVT_CLOSE, lambda evt: self._SendCloseEvent())
+
+#--------------------------------------------------------------------------#
+
+class FindBox(ctrlbox.ControlBox):
+ """Container box that allows for switching the L{FindPanel}'s mode
+ through the ui. Contains a L{FindPanel} and two PlateButtons for switching
+ the mode.
+
+ """
+ def __init__(self, parent, fdata, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=AFR_STYLE_FINDDIALOG,
+ name=FindBoxName):
+ """Create the container box
+ @param fdata: wx.FindReplaceData
+
+ """
+ super(FindBox, self).__init__(parent, id, pos, size,
+ wx.TAB_TRAVERSAL|wx.NO_BORDER, name)
+
+ # Attributes
+ self._fpanel = FindPanel(self, fdata, style=style)
+ ctrlbar = ctrlbox.ControlBar(self, style=ctrlbox.CTRLBAR_STYLE_GRADIENT)
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_FIND, wx.ART_MENU)
+ self.find = platebtn.PlateButton(ctrlbar, label=_("Find"), bmp=bmp,
+ style=platebtn.PB_STYLE_NOBG)
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_FIND_AND_REPLACE, wx.ART_MENU)
+ self.replace = platebtn.PlateButton(ctrlbar, label=_("Replace"),
+ bmp=bmp,
+ style=platebtn.PB_STYLE_NOBG)
+
+ # Setup
+ if wx.Platform == '__WXGTK__':
+ ctrlbar.SetWindowStyle(ctrlbox.CTRLBAR_STYLE_BORDER_BOTTOM)
+
+ ctrlbar.SetVMargin(2, 2)
+ ctrlbar.AddControl(self.find, wx.ALIGN_LEFT)
+ ctrlbar.AddControl(self.replace, wx.ALIGN_LEFT)
+ self.SetControlBar(ctrlbar)
+ self.SetWindow(self._fpanel)
+
+ if style & AFR_STYLE_NO_MODE_SELECT:
+ self.GetControlBar().Hide()
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+
+ def OnButton(self, evt):
+ """Change the mode
+ @param evt: wx.EVT_BUTTON
+
+ """
+ eobj = evt.GetEventObject()
+ if eobj in (self.find, self.replace):
+ self.SetBoxMode(eobj == self.find)
+ else:
+ evt.Skip()
+
+ def SetFindBitmap(self, bmp):
+ """Set the bitmap of the Find Button
+ @param bmp: wx.Bitmap
+
+ """
+ self.find.SetBitmap(bmp)
+ self.GetControlBar().Layout()
+
+ def SetBoxMode(self, find=True):
+ """Set the box to find or find/replace mode
+ @keyword find: set to find mode
+
+ """
+ self._fpanel.SetFindMode(find)
+ self.Layout()
+ evt = _AdvFindDlgInternalEvent(self.GetId(), _edEVT_MODE_CHANGE)
+ wx.PostEvent(self.GetParent(), evt)
+
+ def SetReplaceBitmap(self, bmp):
+ """Set the bitmap of the Replace Button
+ @param bmp: wx.Bitmap
+
+ """
+ self.replace.SetBitmap(bmp)
+ self.GetControlBar().Layout()
+
+#--------------------------------------------------------------------------#
+
+class FindPanel(wx.Panel):
+ """Find controls panel"""
+ def __init__(self, parent, fdata, id=wx.ID_ANY,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=AFR_STYLE_FINDDIALOG, name=FindPanelName):
+ """Create the panel
+ @param fdata: wx.FindReplaceData
+
+ """
+ super(FindPanel, self).__init__(parent, id, pos, size,
+ wx.TAB_TRAVERSAL|wx.NO_BORDER, name)
+
+ # Attributes
+ # TODO: change to editable combo box when wxMac has native widget
+ # so that we can set a search history to choose from.
+ self._mode = style
+ self._ftxt = wx.TextCtrl(self, value=fdata.GetFindString())
+ self._rtxt = wx.TextCtrl(self, value=fdata.GetReplaceString())
+ locations = [_("Current Document"), _("Selected Text"),
+ _("Open Documents"), _("Current Directory")]
+ self._lookin = wx.Choice(self, ID_LOOKIN, choices=locations)
+ self._lookin.SetSelection(0)
+ self._filterlbl = wx.StaticText(self, label=_("File Filters:"))
+ self._filters = None # Created in __DoLayout
+ self._sizers = dict()
+ self._paths = dict()
+ self._fdata = fdata
+ self._dgetter = lambda : u""
+ self._lastSearch = u''
+
+ # Layout
+ self.__DoLayout()
+ self.SetInitialSize()
+ self._ConfigureControls()
+
+ # Setup
+ self.SetFindMode(not (self._mode & AFR_STYLE_REPLACEDIALOG))
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnChooseDir, id=ID_CHOOSE_DIR)
+ self.Bind(wx.EVT_BUTTON,
+ lambda evt: self.FireEvent(evt.GetId()) or evt.Skip())
+ self.Bind(wx.EVT_CHECKBOX, self.OnOption)
+ self.Bind(wx.EVT_RADIOBUTTON, self.OnOption)
+ self.Bind(wx.EVT_CHOICE, self.OnChoice, id=ID_LOOKIN)
+ for bid in (wx.ID_FIND, wx.ID_REPLACE, ID_COUNT,
+ ID_FIND_ALL, ID_REPLACE_ALL):
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=bid)
+ self.Bind(wx.EVT_SET_FOCUS, lambda evt: self.__SetFocus())
+ self._ftxt.Bind(wx.EVT_SET_FOCUS, lambda evt: self._ftxt.SelectAll())
+ self._rtxt.Bind(wx.EVT_SET_FOCUS, lambda evt: self._rtxt.SelectAll())
+
+ # Key handling HACK for windows
+ if wx.Platform == '__WXMSW__':
+ for child in self.GetChildren():
+ child.Bind(wx.EVT_KEY_UP, self._OnKeyUp)
+
+ def __SetFocus(self):
+ """Set the focus to the find box"""
+ self._ftxt.SetFocus()
+ self._ftxt.SelectAll()
+
+ def __DoLayout(self):
+ """Layout the panel"""
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+
+ # Top Section
+ topvsizer = wx.BoxSizer(wx.VERTICAL)
+
+ # Platform dependant labels
+ if wx.Platform == '__WXMSW__':
+ findlbl = wx.StaticText(self, ID_FIND_LBL, _("Find what") + u":")
+ else:
+ findlbl = wx.StaticText(self, ID_FIND_LBL, _("Find") + u":")
+
+ # Search Field
+ fhsizer = wx.BoxSizer(wx.HORIZONTAL)
+ fhsizer.Add(self._ftxt, 1, wx.EXPAND)
+ topvsizer.AddMany([(findlbl, 0, wx.ALIGN_LEFT), ((3, 3), 0),
+ (fhsizer, 0, wx.EXPAND)])
+
+ # Replace field
+ rhsizer = wx.BoxSizer(wx.HORIZONTAL)
+ rhsizer.Add(self._rtxt, 1, wx.EXPAND)
+ rlbl = wx.StaticText(self, ID_REPLACE_LBL, _("Replace with") + u":")
+ self._sizers[ID_REPLACE_LBL] = wx.BoxSizer(wx.VERTICAL)
+ self._sizers[ID_REPLACE_LBL].AddMany([((5, 5), 0),
+ (rlbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((3, 3), 0), (rhsizer, 0, wx.EXPAND)])
+ topvsizer.AddMany([(self._sizers[ID_REPLACE_LBL], 0, wx.EXPAND),
+ ((5, 5), 0)])
+
+ # Look in field
+ self._sizers['look'] = wx.BoxSizer(wx.VERTICAL)
+ li_sz = wx.BoxSizer(wx.HORIZONTAL)
+ dirbtn = wx.Button(self, ID_CHOOSE_DIR, u"...", style=wx.BU_EXACTFIT)
+ dirbtn.SetToolTipString(_("Choose Folder"))
+ li_sz.AddMany([(self._lookin, 1, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (dirbtn, 0, wx.ALIGN_CENTER_VERTICAL)])
+ li_lbl = wx.StaticText(self, label=_("Look in") + u":")
+ self._sizers['look'].AddMany([(li_lbl, 0, wx.ALIGN_LEFT),
+ ((3, 3), 0),
+ (li_sz, 0, wx.EXPAND),
+ ((5, 5), 0)])
+ topvsizer.Add(self._sizers['look'], 0, wx.EXPAND)
+
+ # Search Direction Box
+ self._sizers['dir'] = wx.BoxSizer(wx.VERTICAL)
+ dbox = wx.StaticBox(self, id=ID_DIR_BOX, label=_("Direction"))
+ dboxsz = wx.StaticBoxSizer(dbox, wx.HORIZONTAL)
+ dboxsz.AddMany([(wx.RadioButton(self, wx.ID_UP, _("Up")), 0),
+ ((20, 5), 0),
+ (wx.RadioButton(self, wx.ID_DOWN, _("Down")), 0),
+ ((5, 5), 1)])
+ self._sizers['dir'].AddMany([((5, 5), 0), (dboxsz, 0, wx.EXPAND)])
+
+ # Search Options Box
+ self._sizers['opt'] = wx.BoxSizer(wx.VERTICAL)
+ statbox = wx.StaticBox(self, label=_("Find Options"))
+ sboxsz = wx.StaticBoxSizer(statbox, wx.VERTICAL)
+ for cid, clbl in [(ID_MATCH_CASE, _("Match case")),
+ (ID_WHOLE_WORD, _("Whole word")),
+ (ID_REGEX, _("Regular expression")),
+ (ID_RECURSE, _("Search Recursively"))]:
+ sboxsz.AddMany([((3, 3), 0), (wx.CheckBox(self, cid, clbl), 0)])
+
+ # File Filters
+ self._sizers['filter'] = wx.BoxSizer(wx.VERTICAL)
+ self._filters = wx.TextCtrl(self)
+ tt_txt = _("Wildcard shell patterns for matching files (*.txt *.html).")
+ self._filters.SetToolTipString(tt_txt)
+
+ # Disable spell checking on mac for this control
+ if wx.Platform == '__WXMAC__':
+ self._filters.MacCheckSpelling(False)
+
+ f_sz = wx.BoxSizer(wx.HORIZONTAL)
+ f_sz.Add(self._filters, 1, wx.EXPAND)
+ self._sizers['filter'].AddMany([(self._filterlbl, 0, wx.ALIGN_LEFT),
+ ((3, 3), 0), (f_sz, 0, wx.EXPAND),
+ ((5, 5), 0)])
+ sboxsz.AddMany([((3, 3), 0), (self._sizers['filter'], 0, wx.EXPAND)])
+
+ self._sizers['opt'].AddMany([((5, 5), 0), (sboxsz, 0, wx.EXPAND)])
+
+ # Buttons
+ bsizer = wx.BoxSizer(wx.HORIZONTAL)
+ self._sizers['fspacer'] = bsizer.Add((100, 1), 1)
+ self._sizers['frspacer'] = bsizer.Add((50, 1), 1)
+ for bid, blbl in [(wx.ID_FIND, _("Find")),
+ (wx.ID_REPLACE, _("Replace")),
+ (ID_COUNT, _("Count")),
+ (ID_FIND_ALL, _("Find All")),
+ (ID_REPLACE_ALL, _("Replace All"))]:
+ self._sizers[bid] = wx.BoxSizer(wx.HORIZONTAL)
+ self._sizers[bid].Add((3, 3), 0)
+ self._sizers[bid].Add(wx.Button(self, bid, blbl), 0, wx.ALIGN_RIGHT)
+ bsizer.Add(self._sizers[bid], 0)
+ self.FindWindowById(wx.ID_FIND).SetDefault()
+
+ # Final Layout
+ vsizer.AddMany([((5, 5), 0), (topvsizer, 0, wx.EXPAND),
+ (self._sizers['dir'], 0, wx.EXPAND),
+ (self._sizers['opt'], 0, wx.EXPAND), ((10, 10), 0),
+ (bsizer, 0), ((10, 10), 0)])
+ hsizer.AddMany([((10, 10), 0), (vsizer, 0, wx.EXPAND), ((10, 10), 0)])
+ self.SetSizer(hsizer)
+ self.SetAutoLayout(True)
+
+ def _ConfigureControls(self):
+ """Configure the state of the controls based on the FindReplaceData"""
+ flags = self._fdata.GetFlags()
+ self._ftxt.SelectAll()
+ self.FindWindowById(ID_MATCH_CASE).SetValue(flags & AFR_MATCHCASE)
+ self.FindWindowById(ID_WHOLE_WORD).SetValue(flags & AFR_WHOLEWORD)
+ self.FindWindowById(ID_REGEX).SetValue(flags & AFR_REGEX)
+ self.FindWindowById(wx.ID_DOWN).SetValue(not (flags & AFR_UP))
+ self.FindWindowById(wx.ID_UP).SetValue(flags & AFR_UP)
+ self.ShowLookinCombo(not (flags & AFR_NOLOOKIN))
+ self.ShowDirectionBox(not (flags & AFR_NOUPDOWN))
+ self.ShowOptionsBox(not (flags & AFR_NOOPTIONS))
+ self.FindWindowById(ID_WHOLE_WORD).Enable(not (flags & AFR_NOWHOLEWORD))
+ self.FindWindowById(ID_MATCH_CASE).Enable(not (flags & AFR_NOMATCHCASE))
+ self.FindWindowById(ID_REGEX).Enable(not (flags & AFR_NOREGEX))
+ in_files = bool(self._lookin.GetSelection() >= LOCATION_MAX)
+ recurse = self.FindWindowById(ID_RECURSE)
+ recurse.SetValue(flags & AFR_RECURSIVE)
+ recurse.Enable(in_files)
+ self.ShowFileFilters(in_files and not (flags & AFR_NOFILTER))
+
+ def _OnKeyUp(self, evt):
+ """Check if the dialog should be closed
+ @note: msw only
+
+ """
+ if evt.GetKeyCode() == wx.WXK_ESCAPE:
+ evt = _AdvFindDlgInternalEvent(self.GetId(), _edEVT_DO_CLOSE_DLG)
+ wx.PostEvent(self.GetTopLevelParent(), evt)
+ evt.Skip()
+
+ def _ShowButtons(self, find=True):
+ """Toggle the visiblity of a button set
+ @param find: Show Find Buttons or Show Replace Buttons
+
+ """
+ if find:
+ show = [wx.ID_FIND, ID_COUNT, ID_FIND_ALL, 'fspacer']
+ hide = [wx.ID_REPLACE, ID_REPLACE_ALL, 'frspacer']
+ else:
+ show = [wx.ID_REPLACE, ID_REPLACE_ALL, 'frspacer']
+ hide = [ID_FIND_ALL, ID_COUNT, 'fspacer']
+
+ # Hide extra buttons as per configured preference
+ flags = self._fdata.GetFlags()
+ if flags & AFR_NO_COUNT and ID_COUNT in show:
+ show.remove(ID_COUNT)
+ hide.append(ID_COUNT)
+
+ if flags & AFR_NO_ALL_BTN:
+ if ID_FIND_ALL in show:
+ show.remove(ID_FIND_ALL)
+ hide.append(ID_FIND_ALL)
+ if ID_REPLACE_ALL in show:
+ show.remove(ID_REPLACE_ALL)
+ hide.append(ID_REPLACE_ALL)
+
+ for ctrl in show:
+ if isinstance(ctrl, basestring):
+ self._sizers[ctrl].Show(True)
+ else:
+ self._sizers[ctrl].ShowItems(True)
+
+ for ctrl in hide:
+ if isinstance(ctrl, basestring):
+ self._sizers[ctrl].Show(False)
+ else:
+ self._sizers[ctrl].ShowItems(False)
+
+ def _UpdateContext(self):
+ """Update available dialog options based on the selected search context
+
+ """
+ self._UpdateDefaultBtn()
+ in_files = bool(self._lookin.GetSelection() >= LOCATION_MAX)
+ self.FindWindowById(ID_RECURSE).Enable(in_files)
+ flags = self._fdata.GetFlags()
+
+ # Disable direction settings when searcing in file since they
+ # are ignored anyway.
+ for cid in (wx.ID_UP, wx.ID_DOWN, ID_DIR_BOX):
+ self.FindWindowById(cid).Enable(not in_files)
+
+ # Only update visibility of file filter field if it is enabled
+ if not (flags & AFR_NOFILTER):
+ self.ShowFileFilters(in_files)
+
+ def _UpdateDefaultBtn(self):
+ """Change the default button depending on what the search context
+ has been changed to.
+
+ """
+ find = self.FindWindowById(wx.ID_FIND)
+ find_all = self.FindWindowById(ID_FIND_ALL)
+ replace = self.FindWindowById(wx.ID_REPLACE)
+ replace_all = self.FindWindowById(ID_REPLACE_ALL)
+ count = self.FindWindowById(ID_COUNT)
+
+ lookin = self._lookin.GetSelection()
+ if lookin > LOCATION_IN_SELECTION:
+ if self._mode == AFR_STYLE_FINDDIALOG:
+ find_all.SetDefault()
+ else:
+ replace_all.SetDefault()
+ find.Disable()
+ replace.Disable()
+ count.Disable()
+ elif lookin == LOCATION_IN_SELECTION:
+ find.Disable()
+ replace.Disable()
+ replace_all.SetDefault()
+ else:
+ find.SetDefault()
+ find.Enable()
+ replace.Enable()
+ count.Enable()
+
+ #------------------------------------------------------#
+
+ def AddLookinPath(self, path):
+ """Add a path to the lookin path collection
+ @param path: string
+ @return: index of the items location
+
+ """
+ if not len(path):
+ return None
+
+ # If its a path we already have then just return its index
+ if path in self._paths.values():
+ for idx, pname in self._paths.iteritems():
+ if path == pname:
+ return idx
+
+ # Get the short directory name
+ the_dir = u''
+ for dname in reversed(path.split(os.sep)):
+ if len(dname):
+ the_dir = dname
+ break
+
+ self._paths[self._lookin.GetCount()] = path
+ self._lookin.Append(the_dir)
+ rval = self._lookin.GetCount() - 1
+
+ return rval
+
+ def ClearFlag(self, flag):
+ """Clear a search flag
+ @param flag: AFR_*
+
+ """
+ flags = self._fdata.GetFlags()
+ flags &= ~flag
+ self.SetFlags(flags)
+
+ def FireEvent(self, eid):
+ """Fire an event
+ @param eid: Event id
+
+ """
+ etype = _EVENT_MAP.get(eid, None)
+ query = self._ftxt.GetValue()
+ if eid == wx.ID_FIND:
+ if self._lastSearch == query:
+ etype = edEVT_FIND_NEXT
+ self._lastSearch = query
+ self._fdata.SetFindString(query)
+
+ if etype is not None:
+ evt = FindEvent(etype, eid, self._fdata.GetFlags())
+ evt.SetEventObject(self)
+ lookin_idx = self._lookin.GetSelection()
+ stype = min(LOCATION_IN_FILES, max(LOCATION_CURRENT_DOC, lookin_idx))
+ evt.SetSearchType(stype)
+ evt.SetFindString(query)
+
+ if self._mode & AFR_STYLE_REPLACEDIALOG:
+ rstring = self._rtxt.GetValue()
+ self._fdata.SetReplaceString(rstring)
+ evt.SetReplaceString(rstring)
+ else:
+ evt.SetReplaceString(None)
+
+ if stype >= LOCATION_IN_FILES or stype == LOCATION_IN_CURRENT_DIR:
+ evt.SetFileFilters(self.GetFileFilters())
+ if stype >= LOCATION_IN_FILES:
+ # For IN_CURRENT_DIR it is up to client to determine directory
+ # based on what current means to the application.
+ evt.SetDirectory(self._paths.get(lookin_idx, u''))
+
+ wx.PostEvent(self.GetParent(), evt)
+ return True
+ else:
+ return False
+
+ def GetData(self):
+ """Get the FindReplaceData used by this panel
+ @return: wx.FindReplaceData
+
+ """
+ return self._fdata
+
+ def GetFileFilters(self):
+ """Get the currently set file filters
+ @return: string
+
+ """
+ return self._filters.GetValue()
+
+ def GetLookinChoices(self):
+ """Get the looking choices
+ @return: list of strings
+
+ """
+ choices = list()
+ for key in sorted(self._paths.keys()):
+ choices.append(self._paths[key])
+ return choices
+
+ def GetLookinSelection(self):
+ """Get the index of the currently selected lookin choice
+ @return: int
+
+ """
+ return self._lookin.GetSelection()
+
+ def GetPanelMode(self):
+ """Get the current display mode of the panel
+ @return: AFR_STYLE_FINDDIALOG or AFR_STYLE_REPLACEDIALOG
+
+ """
+ return self._mode
+
+ def OnChoice(self, evt):
+ """Handle choice control events
+ @param evt: wx.EVT_CHOICE
+
+ """
+ e_id = evt.Id
+ if e_id == ID_LOOKIN:
+ self._UpdateContext()
+ choice = self._lookin.GetSelection()
+ if choice >= LOCATION_IN_FILES:
+ tts = self._paths.get(choice, u'')
+ self._lookin.SetToolTipString(tts)
+ else:
+ self._lookin.SetToolTipString(u'')
+ else:
+ evt.Skip()
+
+ def OnChooseDir(self, evt):
+ """Open the choose directory dialog for selecting what
+ path to do a search in files in.
+ @param evt: wx.EVT_BUTTON
+
+ """
+ if evt.Id == ID_CHOOSE_DIR:
+ dname = self._dgetter()
+ dlg = wx.DirDialog(self, _("Choose Search Folder"), defaultPath=dname)
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ if path is not None and len(path):
+ idx = self.AddLookinPath(path)
+ self.SetLookinSelection(idx)
+ self._UpdateContext()
+ dlg.Destroy()
+ else:
+ evt.Skip()
+
+ def OnOption(self, evt):
+ """Update search flags
+ @param evt: wx.EVT_CHECKBOX
+
+ """
+ fmap = { ID_MATCH_CASE : AFR_MATCHCASE,
+ ID_WHOLE_WORD : AFR_WHOLEWORD,
+ ID_REGEX : AFR_REGEX,
+ ID_RECURSE : AFR_RECURSIVE,
+ wx.ID_UP : AFR_UP }
+ eid = evt.Id
+ eobj = evt.EventObject
+ if eid in fmap:
+ if eobj.GetValue():
+ self.SetFlag(fmap[eid])
+ else:
+ self.ClearFlag(fmap[eid])
+ self.FireEvent(ID_OPTION_CHANGE)
+ elif eid == wx.ID_DOWN:
+ self.ClearFlag(fmap[wx.ID_UP])
+ self.FireEvent(ID_OPTION_CHANGE)
+ else:
+ evt.Skip()
+
+ def OnUpdateUI(self, evt):
+ """Enable and disable buttons depending on state of find entry box.
+ @param evt: wx.UpdateUIEvent
+
+ """
+ # TODO: support count in files?
+ if evt.Id in (wx.ID_FIND, ID_COUNT, wx.ID_REPLACE) and \
+ self._lookin.GetSelection() > LOCATION_CURRENT_DOC:
+ evt.Enable(False)
+ else:
+ txt = len(self._ftxt.GetValue())
+ evt.Enable(txt)
+
+ def SetFindMode(self, find=True):
+ """Set the mode of the dialog Replace
+ @param find: Set Find Mode or Replace Mode
+
+ """
+ self._rtxt.Show(not find)
+ self._sizers[ID_REPLACE_LBL].ShowItems(not find)
+ if find:
+ self._mode = AFR_STYLE_FINDDIALOG
+ else:
+ self._mode = AFR_STYLE_REPLACEDIALOG
+
+ self._UpdateDefaultBtn()
+ self._ShowButtons(find)
+ self.Layout()
+
+ def SetFindString(self, query):
+ """Set the find fields string
+ @param query: string
+
+ """
+ self._ftxt.SetValue(query)
+ self._fdata.SetFindString(query)
+
+ def RefreshControls(self):
+ """Refresh the state of the controls from the current FindData."""
+ self._ConfigureControls()
+
+ def SetData(self, data):
+ """Set the FindReplaceData and update the dialog with that data
+ @param data: wxFindReplaceData
+
+ """
+ self._fdata.Destroy()
+ self._fdata = None
+ self._fdata = data
+ self._ConfigureControls()
+
+ def SetDirectoryGetter(self, dgetter):
+ """Set a callback for retrieving the current directory. This method
+ is used for providing context when popping up dialogs such as the
+ Choose Directory dialog.
+ @param dgetter: callable() => unicode
+
+ """
+ if not callable(dgetter):
+ dgetter = lambda : u""
+ self._dgetter = dgetter
+
+ def SetFileFilters(self, filters):
+ """Set the file filters field values
+ @param filters: string
+
+ """
+ self._filters.SetValue(filters)
+
+ def SetFlag(self, flag):
+ """Set a search flag
+ @param flag: AFR_* flag value
+
+ """
+ flags = self._fdata.GetFlags()
+ flags |= flag
+ self.SetFlags(flags)
+
+ def SetFlags(self, flags):
+ """Set the search flags
+ @param flags: Bitmask of AFR_* values
+
+ """
+ self._fdata.SetFlags(flags)
+ self._ConfigureControls()
+
+ def SetLookinChoices(self, paths):
+ """Set the looking choices
+ @param paths: list of strings
+
+ """
+ for path in paths:
+ self.AddLookinPath(path)
+
+ def SetLookinSelection(self, idx):
+ """Set the selection of the lookin control.
+ @param idx: int
+
+ """
+ if idx <= self._lookin.GetCount():
+ self._lookin.SetSelection(idx)
+
+ # If the selection is a Look in Files make sure the filter
+ # field is shown
+ flags = self._fdata.GetFlags()
+ in_files = bool(idx >= LOCATION_MAX)
+ self.ShowFileFilters(in_files and not (flags & AFR_NOFILTER))
+
+ def SetReplaceString(self, rstring):
+ """Set the replace fields string
+ @param rstring: string
+
+ """
+ self._rtxt.SetValue(rstring)
+ self._fdata.SetReplaceString(rstring)
+
+ def ShowDirectionBox(self, show=True):
+ """Show or hide the Direction group box
+ @keyword show: bool
+
+ """
+ if 'dir' in self._sizers:
+ self._sizers['dir'].ShowItems(show)
+ self.Layout()
+
+ def ShowFileFilters(self, show=True):
+ """Show or hide the File Filters filed
+ @keyword show: bool
+
+ """
+ if 'filter' in self._sizers:
+ self._sizers['filter'].ShowItems(show)
+ self.Layout()
+
+ # Require additional resizing
+ evt = _AdvFindDlgInternalEvent(self.GetId(), _edEVT_MODE_CHANGE)
+ wx.PostEvent(self.GetTopLevelParent(), evt)
+
+ def ShowLookinCombo(self, show=True):
+ """Show the lookin choice and directory chooser control
+ @keyword show: bool
+
+ """
+ if 'look' in self._sizers:
+ self._sizers['look'].ShowItems(show)
+ self.Layout()
+
+ def ShowOptionsBox(self, show=True):
+ """Show the find options group box
+ @keyword show: bool
+
+ """
+ if 'opt' in self._sizers:
+ self._sizers['opt'].ShowItems(show)
+ self.Layout()
+
+#--------------------------------------------------------------------------#
+# Private Module Api
+
+_edEVT_MODE_CHANGE = wx.NewEventType()
+_EVT_MODE_CHANGE = wx.PyEventBinder(_edEVT_MODE_CHANGE, 1)
+
+_edEVT_DO_CLOSE_DLG = wx.NewEventType()
+_EVT_DO_CLOSE_DLG = wx.PyEventBinder(_edEVT_DO_CLOSE_DLG, 1)
+
+class _AdvFindDlgInternalEvent(wx.PyEvent):
+ def __init__(self, winid=wx.ID_ANY, etype=wx.wxEVT_NULL):
+ """Create the Event"""
+ wx.PyEvent.__init__(self, winid, etype)
+
+#--------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/infodlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/infodlg.py
new file mode 100644
index 0000000..c450468
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/infodlg.py
@@ -0,0 +1,299 @@
+###############################################################################
+# Name: FileInfo.py #
+# Purpose: Display information about files/folders #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FileInfo.py
+
+Dialog for displaying file information.
+
+Displays information on:
+ * Filename and Path
+ * File Size
+ * Read/Write/Execute permissions
+ * Creation/Modification times
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: infodlg.py 66025 2010-11-05 19:18:08Z CJP $"
+__revision__ = "$Revision: 66025 $"
+
+__all__ = ["FileInfoDlg", "CalcSize", "GetFileType"]
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import time
+import stat
+import mimetypes
+import wx
+
+#--------------------------------------------------------------------------#
+# Globals
+
+_ = wx.GetTranslation
+
+PERM_MAP = { '0' : '---', '1' : '--x', '2' : '-w-', '3' : '-wx',
+ '4' : 'r--', '5' : 'r-x', '6' : 'rw-', '7' : 'rwx'}
+
+#--------------------------------------------------------------------------#
+
+class FileInfoDlg(wx.MiniFrame):
+ """Dialog for displaying information about a file"""
+ def __init__(self, parent, fname='', ftype=None, bmp=wx.NullBitmap):
+ """Create the dialog with the information of the given file
+ @param parent: Parent Window
+ @keyword fname: File Path
+ @keyword ftype: Filetype label (leave None to automatically determine)
+ @keyword bmp: wxBitmap
+
+ """
+ self._fname = fname.split(os.path.sep)[-1]
+ super(FileInfoDlg, self).__init__(parent,
+ title="%s %s" % (self._fname, _("Info")),
+ style=wx.DEFAULT_DIALOG_STYLE)
+
+ # Attributes
+ self._file = fname
+ self._ftype = ftype
+ self.panel = wx.Panel(self)
+ if bmp.IsNull():
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_CMN_DIALOG)
+ self._bmp = wx.StaticBitmap(self.panel, bitmap=bmp)
+ self._ftxt = wx.StaticText(self.panel)
+
+ try:
+ fstat = os.stat(fname)
+ perm = oct(stat.S_IMODE(fstat[stat.ST_MODE])).lstrip('0')
+ permstr = ''
+ for bit in perm:
+ permstr += (PERM_MAP.get(bit, '---') + " ")
+ self._fstat = dict(mtime=time.asctime(time.localtime(fstat[stat.ST_MTIME])),
+ ctime=time.asctime(time.localtime(fstat[stat.ST_CTIME])),
+ size=CalcSize(fstat[stat.ST_SIZE]),
+ perm=permstr)
+ except Exception, msg:
+ self.__DoErrorLayout(str(msg))
+ else:
+ self.__DoLayout()
+
+ self.panel.SetAutoLayout(True)
+ fsizer = wx.BoxSizer(wx.VERTICAL)
+ fsizer.Add(self.panel, 1, wx.EXPAND)
+ self.SetSizer(fsizer)
+ self.SetAutoLayout(True)
+ self.SetInitialSize()
+
+ # Event Handlers
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+ def __DoErrorLayout(self, msg):
+ """Set the dialogs display up for when an error happened in
+ the stat call.
+
+ """
+ # Top Info
+ top = wx.BoxSizer(wx.HORIZONTAL)
+ head = wx.BoxSizer(wx.VERTICAL)
+ err = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_CMN_DIALOG)
+ bmp = wx.StaticBitmap(self.panel, bitmap=err)
+ lbl = wx.StaticText(self.panel, label=self._fname)
+ font = self.GetFont()
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ if wx.Platform == '__WXMSW__':
+ font.SetPointSize(12)
+ else:
+ font.SetPointSize(13)
+ lbl.SetFont(font)
+ head.Add(lbl, 0, wx.ALIGN_LEFT)
+
+ errlbl = wx.StaticText(self.panel, label=_("File Stat Failed"))
+ if wx.Platform == '__WXMSW__':
+ font.SetPointSize(10)
+ else:
+ font.SetPointSize(11)
+ font.SetWeight(wx.FONTWEIGHT_LIGHT)
+ errlbl.SetFont(font)
+ head.Add((5, 5), 0)
+ head.Add(errlbl, 0, wx.ALIGN_LEFT)
+ top.AddMany([((5, 5),), (bmp, 0, wx.ALIGN_LEFT), ((12, 12),),
+ (head, 0, wx.ALIGN_LEFT), ((5, 5),)])
+
+ # Central Area
+ csizer = wx.BoxSizer(wx.VERTICAL)
+ errbmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_CMN_DIALOG)
+ errbmp = wx.StaticBitmap(self.panel, bitmap=errbmp)
+ errmsg = wx.StaticText(self.panel, label=msg)
+ errmsg.SetFont(font)
+ errmsg.Wrap(225)
+ errsz = wx.BoxSizer(wx.HORIZONTAL)
+ errsz.AddMany([((8, 8)), (errmsg, 0, wx.ALIGN_LEFT), ((8, 8))])
+ csizer.AddMany([((10, 10)), (top, 1, wx.EXPAND), ((10, 10)),
+ (wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL), 0, wx.EXPAND),
+ ((20, 20)), (errbmp, 0, wx.ALIGN_CENTER),
+ ((10, 10)), (errsz, 0, wx.ALIGN_CENTER), ((10, 10)),
+ (wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL), 0, wx.EXPAND),
+ ((10, 10))])
+ self.panel.SetSizer(csizer)
+
+ def __DoLayout(self):
+ """Layout the dialog"""
+ # Top Info
+ top = wx.BoxSizer(wx.HORIZONTAL)
+ head = wx.BoxSizer(wx.HORIZONTAL)
+ lbl = wx.StaticText(self.panel, label=self._fname)
+ fszlbl = wx.StaticText(self.panel, label=self._fstat['size'])
+ font = self.GetFont()
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ if wx.Platform == '__WXMSW__':
+ font.SetPointSize(12)
+ else:
+ font.SetPointSize(13)
+ lbl.SetFont(font)
+ fszlbl.SetFont(font)
+ head.Add(lbl, 0, wx.ALIGN_LEFT)
+ head.AddStretchSpacer(2)
+ head.Add(fszlbl, 1, wx.ALIGN_RIGHT)
+
+ modlbl = wx.StaticText(self.panel, label="%s: %s" % (_("Modified"),
+ self._fstat['mtime']))
+ if wx.Platform == '__WXMSW__':
+ font.SetPointSize(10)
+ else:
+ font.SetPointSize(11)
+
+ font.SetWeight(wx.FONTWEIGHT_LIGHT)
+ modlbl.SetFont(font)
+ lblsize = wx.BoxSizer(wx.VERTICAL)
+ lblsize.AddMany([(head, 1, wx.ALIGN_LEFT), ((3, 3),),
+ (modlbl, 0, wx.ALIGN_LEFT | wx.ALIGN_BOTTOM)])
+
+ top.AddMany([((5, 5)),
+ (self._bmp, 0, wx.ALIGN_LEFT),
+ ((12, 12)), (lblsize, 0, wx.ALIGN_LEFT), ((5, 5))])
+
+ # Central Info
+ center = wx.FlexGridSizer(6, 2, 3, 5)
+ tlbl = wx.StaticText(self.panel, label=_("Kind") + ":")
+
+ if self._ftype is None:
+ self._ftxt.SetLabel(GetFileType(self._file))
+ else:
+ self._ftxt.SetLabel(self._ftype)
+
+ szlbl = wx.StaticText(self.panel, label=_("Size") + ":")
+ szval = wx.StaticText(self.panel, label=self._fstat['size'])
+ loclbl = wx.StaticText(self.panel, label=_("Where") + ":")
+ locval = wx.StaticText(self.panel, label=self._FormatLabel(self._file))
+ ctime = wx.StaticText(self.panel, label=_("Created") + ":")
+ cval = wx.StaticText(self.panel, label=self._fstat['ctime'])
+ mtime = wx.StaticText(self.panel, label=_("Modified") + ":")
+ mval = wx.StaticText(self.panel, label=self._fstat['mtime'])
+ perm = wx.StaticText(self.panel, label=_("Permissions") + ":")
+ pval = wx.StaticText(self.panel, label=self._fstat['perm'])
+ for lbl in (tlbl, self._ftxt, szlbl, szval, loclbl,
+ locval, ctime, cval, mtime, mval, perm, pval):
+ lbl.SetFont(font)
+ lbl.Wrap(200)
+ center.AddMany([(tlbl, 0, wx.ALIGN_RIGHT), (self._ftxt, 0, wx.ALIGN_LEFT),
+ (szlbl, 0, wx.ALIGN_RIGHT), (szval, 0, wx.ALIGN_LEFT),
+ (loclbl, 0, wx.ALIGN_RIGHT), (locval, 0, wx.ALIGN_LEFT),
+ (ctime, 0, wx.ALIGN_RIGHT), (cval, 0, wx.ALIGN_LEFT),
+ (mtime, 0, wx.ALIGN_RIGHT), (mval, 0, wx.ALIGN_LEFT),
+ (perm, 0, wx.ALIGN_RIGHT), (pval, 0, wx.ALIGN_LEFT)])
+ cmain = wx.BoxSizer(wx.HORIZONTAL)
+ cmain.AddMany([((8, 8),), (center, 0, wx.ALIGN_CENTER), ((8, 8),)])
+
+ # Main Layout
+ msizer = wx.BoxSizer(wx.VERTICAL)
+ msizer.AddMany([((10, 10)), (top, 0, wx.ALIGN_CENTER), ((10, 10),),
+ (wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL), 1,
+ wx.EXPAND|wx.ALIGN_CENTER),
+ ((10, 10),), (cmain, 0, wx.ALIGN_TOP|wx.ALIGN_CENTER),
+ ((10, 10),),
+ (wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL), 1,
+ wx.EXPAND|wx.ALIGN_CENTER),
+ ((10, 10),),
+ ])
+ self.panel.SetSizer(msizer)
+
+ def _FormatLabel(self, lbl):
+ """Format the label to a suitable width wrapping as necessary"""
+ lbl_len = len(lbl)
+ part = self.GetTextExtent(lbl)[0] / 200
+ if part > 1:
+ split = lbl_len / part
+ pieces = list()
+ for chunk in xrange(part):
+ if chunk == part - 1:
+ pieces.append(lbl[chunk * split:])
+ else:
+ pieces.append(lbl[chunk * split:(chunk * split + split)])
+ return os.linesep.join(pieces)
+ return lbl
+
+ def OnClose(self, evt):
+ """Destroy ourselves on closer"""
+ self.Destroy()
+ evt.Skip()
+
+ def SetBitmap(self, bmp):
+ """Set the dialog bitmap
+ @param bmp: wxBitmap
+
+ """
+ self._bmp.SetBitmap(bmp)
+ self._bmp.Refresh()
+ self.panel.Layout()
+
+ def SetFileTypeLabel(self, lbl):
+ """Set the file type label
+ @param lbl: string
+
+ """
+ self._ftype = lbl
+ self._ftxt.SetLabel(lbl)
+ self.panel.Layout()
+
+#-----------------------------------------------------------------------------#
+# Utility Functions
+
+def CalcSize(bits):
+ """Calculate the best display version of the size of a given file
+ 1024 = 1KB, 1024KB = 1MB, ...
+ @param bits: size of file returned by stat
+ @return: formatted string representation of value
+
+ """
+ val = ('bytes', 'KB', 'MB', 'GB', 'TB')
+ ind = 0
+ while bits > 1024:
+ bits = float(bits) / 1024.0
+ ind += 1
+
+ rval = "%.2f" % bits
+ rval = rval.rstrip('.0')
+ if not rval:
+ rval = '0'
+ rval = "%s %s" % (rval, val[min(ind, 4)])
+ return rval
+
+def GetFileType(fname):
+ """Get what the type of the file is
+ @param fname: file path
+
+ """
+ if os.path.isdir(fname):
+ return _("Folder")
+
+ mtype = mimetypes.guess_type(fname)[0]
+ if mtype is not None:
+ return mtype
+ else:
+ return _("Unknown")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/outbuff.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/outbuff.py
new file mode 100644
index 0000000..6b708fe
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/outbuff.py
@@ -0,0 +1,1077 @@
+###############################################################################
+# Name: outbuff.py #
+# Purpose: Gui and helper classes for running processes and displaying output #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: OutputBuffer
+
+This module contains classes that are useful for displaying output from running
+tasks and processes. The classes are divided into three main categories, gui
+classes, mixins, and thread classes. All the classes can be used together to
+easily create multithreaded gui display classes without needing to worry about
+the details and thread safety of the gui.
+
+For example usage of these classes see ed_log and the Editra's Launch plugin
+
+Class OutputBuffer:
+This is the main class exported by this module. It provides a readonly output
+display buffer that when used with the other classes in this module provides an
+easy way to display continuous output from other processes and threads. It
+provides two methods for subclasses to override if they wish to perform custom
+handling.
+
+ - Override the ApplyStyles method to do any processing and coloring of the
+ text as it is put in the buffer.
+ - Override the DoHotSpotClicked method to handle any actions to take when a
+ hotspot has been clicked in the buffer.
+ - Override the DoUpdatesEmpty method to perform any idle processing when no
+ new text is waiting to be processed.
+
+Class ProcessBufferMixin:
+Mixin class for the L{OutputBuffer} class that provides handling for when an
+OutputBuffer is used with a L{ProcessThread}. It provides three methods that can
+be overridden in subclasses to perform extra processing.
+
+ - DoProcessStart: Called as the process is being started in the ProcessThread,
+ it receives the process command string as an argument.
+ - DoFilterInput: Called as each chunk of output comes from the running process
+ use it to filter the results before displaying them in the
+ buffer.
+ - DoProcessExit: Called when the running process has exited. It receives the
+ processes exit code as a parameter.
+
+Class ProcessThread:
+Thread class for running subprocesses and posting the output to an
+L{OutputBuffer} via events.
+
+Class TaskThread:
+Thread class for running a callable. For optimal performance and responsiveness
+the callable should be a generator object. All results are directed to an
+L{OutputBuffer} through its AppendUpdate method.
+
+Requirements:
+ * wxPython 2.8
+ * Macintosh/Linux/Unix Python 2.4+
+ * Windows Python 2.5+ (ctypes is needed)
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: outbuff.py 69743 2011-11-12 20:22:48Z CJP $"
+__revision__ = "$Revision: 69743 $"
+
+__all__ = ["OutputBuffer", "OutputBufferEvent", "ProcessBufferMixin",
+ "ProcessThreadBase", "ProcessThread", "TaskThread", "TaskObject",
+ "OPB_STYLE_DEFAULT", "OPB_STYLE_INFO",
+ "OPB_STYLE_WARN", "OPB_STYLE_ERROR", "OPB_STYLE_MAX",
+
+ "OPB_ERROR_NONE", "OPB_ERROR_INVALID_COMMAND",
+
+ "edEVT_PROCESS_START", "EVT_PROCESS_START", "edEVT_TASK_START",
+ "EVT_TASK_START", "edEVT_UPDATE_TEXT", "EVT_UPDATE_TEXT",
+ "edEVT_PROCESS_EXIT", "EVT_PROCESS_EXIT", "edEVT_TASK_COMPLETE",
+ "EVT_TASK_COMPLETE", "edEVT_PROCESS_ERROR", "EVT_PROCESS_ERROR"]
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import sys
+import time
+import errno
+import signal
+import threading
+import types
+import subprocess
+import wx
+import wx.stc
+
+# Platform specific modules needed for killing processes
+if subprocess.mswindows:
+ import msvcrt
+ import ctypes
+else:
+ import shlex
+ import select
+ import fcntl
+
+#--------------------------------------------------------------------------#
+# Globals
+OUTPUTBUFF_NAME_STR = u'EditraOutputBuffer'
+THREADEDBUFF_NAME_STR = u'EditraThreadedBuffer'
+
+# Style Codes
+OPB_STYLE_DEFAULT = 0 # Default Black text styling
+OPB_STYLE_INFO = 1 # Default Blue text styling
+OPB_STYLE_WARN = 2 # Default Red text styling
+OPB_STYLE_ERROR = 3 # Default Red/Hotspot text styling
+OPB_STYLE_MAX = 3 # Highest style byte used by outputbuffer
+
+# All Styles
+OPB_ALL_STYLES = (wx.stc.STC_STYLE_DEFAULT, wx.stc.STC_STYLE_CONTROLCHAR,
+ OPB_STYLE_DEFAULT, OPB_STYLE_ERROR, OPB_STYLE_INFO,
+ OPB_STYLE_WARN)
+
+# Error Codes
+OPB_ERROR_NONE = 0
+OPB_ERROR_INVALID_COMMAND = -1
+
+#--------------------------------------------------------------------------#
+
+# Event for notifying that the process has started running
+# GetValue will return the command line string that started the process
+edEVT_PROCESS_START = wx.NewEventType()
+EVT_PROCESS_START = wx.PyEventBinder(edEVT_PROCESS_START, 1)
+
+# Event for notifying that a task is starting to run
+edEVT_TASK_START = wx.NewEventType()
+EVT_TASK_START = wx.PyEventBinder(edEVT_TASK_START, 1)
+
+# Event for passing output data to buffer
+# GetValue returns the output text retrieved from the process
+edEVT_UPDATE_TEXT = wx.NewEventType()
+EVT_UPDATE_TEXT = wx.PyEventBinder(edEVT_UPDATE_TEXT, 1)
+
+# Event for notifying that the the process has finished and no more update
+# events will be sent. GetValue will return the processes exit code
+edEVT_PROCESS_EXIT = wx.NewEventType()
+EVT_PROCESS_EXIT = wx.PyEventBinder(edEVT_PROCESS_EXIT, 1)
+
+# Event to notify that a process has completed
+edEVT_TASK_COMPLETE = wx.NewEventType()
+EVT_TASK_COMPLETE = wx.PyEventBinder(edEVT_TASK_COMPLETE, 1)
+
+# Event to notify that an error occurred in the process
+edEVT_PROCESS_ERROR = wx.NewEventType()
+EVT_PROCESS_ERROR = wx.PyEventBinder(edEVT_PROCESS_ERROR, 1)
+
+class OutputBufferEvent(wx.PyCommandEvent):
+ """Event for data transfer and signaling actions in the L{OutputBuffer}"""
+ def __init__(self, etype, eid=wx.ID_ANY, value=''):
+ """Creates the event object"""
+ super(OutputBufferEvent, self).__init__(etype, eid)
+
+ # Attributes
+ self._value = value
+ self._errmsg = None
+
+ #---- Properties ----#
+ Value = property(lambda self: self.GetValue(),
+ lambda self, v: setattr(self, '_value', v))
+ ErrorMessage = property(lambda self: self.GetErrorMessage(),
+ lambda self, msg: self.SetErrorMessage(msg))
+
+ def GetValue(self):
+ """Returns the value from the event.
+ @return: the value of this event
+
+ """
+ return self._value
+
+ def GetErrorMessage(self):
+ """Get the error message value
+ @return: Exception traceback string or None
+
+ """
+ return self._errmsg
+
+ def SetErrorMessage(self, msg):
+ """Set the error message value
+ @param msg: Exception traceback string
+
+ """
+ try:
+ tmsg = unicode(msg)
+ except:
+ tmsg = None
+ self._errmsg = msg
+
+#--------------------------------------------------------------------------#
+
+class OutputBuffer(wx.stc.StyledTextCtrl):
+ """OutputBuffer is a general purpose output display for showing text. It
+ provides an easy interface for the buffer to interact with multiple threads
+ that may all be sending updates to the buffer at the same time. Methods for
+ styling and filtering output are also available.
+
+ """
+ def __init__(self, parent, id=wx.ID_ANY,
+ pos=wx.DefaultPosition,
+ size=wx.DefaultSize,
+ style=wx.BORDER_SUNKEN,
+ name=OUTPUTBUFF_NAME_STR):
+ super(OutputBuffer, self).__init__(parent, id, pos,
+ size, style, name)
+
+ # Attributes
+ self._mutex = threading.Lock()
+ self._updating = threading.Condition(self._mutex)
+ self._updates = list()
+ self._timer = wx.Timer(self)
+ self._line_buffer = -1
+ self._colors = dict(defaultb=(255, 255, 255), defaultf=(0, 0, 0),
+ errorb=(255, 255, 255), errorf=(255, 0, 0),
+ infob=(255, 255, 255), infof=(0, 0, 255),
+ warnb=(255, 255, 255), warnf=(255, 0, 0))
+
+ # Setup
+ self.__ConfigureSTC()
+
+ # Event Handlers
+ self.Bind(wx.EVT_TIMER, self.OnTimer)
+ self.Bind(wx.stc.EVT_STC_HOTSPOT_CLICK, self._OnHotSpot)
+
+ def __del__(self):
+ """Ensure timer is cleaned up when we are deleted"""
+ if self._timer.IsRunning():
+ self._timer.Stop()
+
+ def __ConfigureSTC(self):
+ """Setup the stc to behave/appear as we want it to
+ and define all styles used for giving the output context.
+ @todo: make more of this configurable
+
+ """
+ self.SetMargins(3, 3)
+ self.SetMarginWidth(0, 0)
+ self.SetMarginWidth(1, 0)
+
+ # To improve performance at cost of memory cache the document layout
+ self.SetLayoutCache(wx.stc.STC_CACHE_DOCUMENT)
+ self.SetUndoCollection(False) # Don't keep undo history
+ self.SetReadOnly(True)
+ self.SetCaretWidth(0)
+
+ if wx.Platform == '__WXMSW__':
+ self.SetEOLMode(wx.stc.STC_EOL_CRLF)
+ else:
+ self.SetEOLMode(wx.stc.STC_EOL_LF)
+
+ #self.SetEndAtLastLine(False)
+ self.SetVisiblePolicy(1, wx.stc.STC_VISIBLE_STRICT)
+
+ # Define Styles
+ highlight = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.SetSelBackground(True, highlight)
+ if sum(highlight.Get()) < 384:
+ self.SetSelForeground(True, wx.WHITE)
+ else:
+ self.SetSelForeground(True, wx.BLACK)
+ self.__SetupStyles()
+
+ def FlushBuffer(self):
+ """Flush the update buffer
+ @postcondition: The update buffer is empty
+
+ """
+ self._updating.acquire()
+ self.SetReadOnly(False)
+ txt = u''.join(self._updates[:])
+ start = self.GetLength()
+ if u'\0' in txt:
+ # HACK: handle displaying NULLs in the STC
+ self.AddStyledText('\0'.join(txt.encode('utf-8'))+'\0')
+ else:
+ self.AppendText(txt)
+ self.GotoPos(self.GetLength())
+ self._updates = list()
+ self.ApplyStyles(start, txt)
+ self.SetReadOnly(True)
+ self.RefreshBufferedLines()
+ self._updating.release()
+
+ def __SetupStyles(self, font=None):
+ """Setup the default styles of the text in the buffer
+ @keyword font: wx.Font to use or None to use default
+
+ """
+ if font is None:
+ if wx.Platform == '__WXMAC__':
+ fsize = 11
+ else:
+ fsize = 10
+
+ font = wx.Font(fsize, wx.FONTFAMILY_MODERN,
+ wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
+ style = (font.GetFaceName(), font.GetPointSize(), "#FFFFFF")
+ wx.stc.StyledTextCtrl.SetFont(self, font)
+
+ # Custom Styles
+ self.StyleSetSpec(OPB_STYLE_DEFAULT,
+ "face:%s,size:%d,fore:#000000,back:%s" % style)
+ self.StyleSetSpec(OPB_STYLE_INFO,
+ "face:%s,size:%d,fore:#0000FF,back:%s" % style)
+ self.StyleSetSpec(OPB_STYLE_WARN,
+ "face:%s,size:%d,fore:#FF0000,back:%s" % style)
+ self.StyleSetSpec(OPB_STYLE_ERROR,
+ "face:%s,size:%d,fore:#FF0000,back:%s" % style)
+ self.StyleSetHotSpot(OPB_STYLE_ERROR, True)
+
+ # Default Styles
+ self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, \
+ "face:%s,size:%d,fore:#000000,back:%s" % style)
+ self.StyleSetSpec(wx.stc.STC_STYLE_CONTROLCHAR, \
+ "face:%s,size:%d,fore:#000000,back:%s" % style)
+ self.Colourise(0, -1)
+
+ def _OnHotSpot(self, evt):
+ """Handle hotspot clicks"""
+ pos = evt.GetPosition()
+ self.DoHotSpotClicked(pos, self.LineFromPosition(pos))
+
+ #---- Public Member Functions ----#
+
+ def AppendUpdate(self, value):
+ """Buffer output before adding to window. This method can safely be
+ called from non gui threads to add updates to the buffer, that will
+ be displayed during the next idle period.
+ @param value: update string to append to stack
+
+ """
+ self._updating.acquire()
+ if not (type(value) is types.UnicodeType):
+ value = value.decode(sys.getfilesystemencoding())
+ self._updates.append(value)
+ self._updating.release()
+
+ def ApplyStyles(self, start, txt):
+ """Apply coloring to text starting at start position.
+ Override this function to do perform any styling that you want
+ done on the text.
+ @param start: Start position of text that needs styling in the buffer
+ @param txt: The string of text that starts at the start position in the
+ buffer.
+
+ """
+ pass
+
+ def CanCopy(self):
+ """Is it possible to copy text right now
+ @return: bool
+
+ """
+ sel = self.GetSelection()
+ return sel[0] != sel[1]
+
+ def CanCut(self):
+ """Is it possible to Cut
+ @return: bool
+
+ """
+ return not self.GetReadOnly()
+
+ def Clear(self):
+ """Clear the Buffer"""
+ self.SetReadOnly(False)
+ self.ClearAll()
+ self.EmptyUndoBuffer()
+ self.SetReadOnly(True)
+
+ def DoHotSpotClicked(self, pos, line):
+ """Action to perform when a hotspot region is clicked in the buffer.
+ Override this function to provide handling of hotspots.
+ @param pos: Position in buffer of where the click occurred.
+ @param line: Line in which the click occurred (zero based index)
+
+ """
+ pass
+
+ def DoUpdatesEmpty(self):
+ """Called when update stack is empty
+ Override this function to perform actions when there are no updates
+ to process. It can be used for things such as temporarily stopping
+ the timer or performing idle processing.
+
+ """
+ pass
+
+ def GetDefaultBackground(self):
+ """Get the default text style background color
+ @return: wx.Colour
+
+ """
+ return wx.Colour(*self._colors['defaultb'])
+
+ def GetDefaultForeground(self):
+ """Get the default text style foreground color
+ @return: wx.Colour
+
+ """
+ return wx.Colour(*self._colors['defaultf'])
+
+ def GetErrorBackground(self):
+ """Get the error text style background color
+ @return: wx.Colour
+
+ """
+ return wx.Colour(*self._colors['errorb'])
+
+ def GetErrorForeground(self):
+ """Get the error text style foreground color
+ @return: wx.Colour
+
+ """
+ return wx.Colour(*self._colors['errorf'])
+
+ def GetInfoBackground(self):
+ """Get the info text style background color
+ @return: wx.Colour
+
+ """
+ return wx.Colour(*self._colors['infob'])
+
+ def GetInfoForeground(self):
+ """Get the info text style foreground color
+ @return: wx.Colour
+
+ """
+ return wx.Colour(*self._colors['infof'])
+
+ def GetWarningBackground(self):
+ """Get the warning text style background color
+ @return: wx.Colour
+
+ """
+ return wx.Colour(*self._colors['warnb'])
+
+ def GetWarningForeground(self):
+ """Get the warning text style foreground color
+ @return: wx.Colour
+
+ """
+ return wx.Colour(*self._colors['warnf'])
+
+ def GetUpdateQueue(self):
+ """Gets a copy of the current update queue"""
+ self._updating.acquire()
+ val = list(self._updates)
+ self._updating.release()
+ return val
+
+ def IsRunning(self):
+ """Return whether the buffer is running and ready for output
+ @return: bool
+
+ """
+ return self._timer.IsRunning()
+
+ def OnTimer(self, evt):
+ """Process and display text from the update buffer
+ @note: this gets called many times while running thus needs to
+ return quickly to avoid blocking the ui.
+
+ """
+ if len(self._updates):
+ self.FlushBuffer()
+ elif evt is not None:
+ self.DoUpdatesEmpty()
+ else:
+ pass
+
+ def RefreshBufferedLines(self):
+ """Refresh and readjust the lines in the buffer to fit the current
+ line buffering limits.
+ @postcondition: Oldest lines are removed until we are back within the
+ buffer limit bounds.
+
+ """
+ if self._line_buffer < 0:
+ return
+
+ self.SetReadOnly(False)
+ while self.GetLineCount() > self._line_buffer:
+ self.SetCurrentPos(0)
+ self.LineDelete()
+ self.SetReadOnly(True)
+ self.SetCurrentPos(self.GetLength())
+
+ def SetDefaultColor(self, fore=None, back=None):
+ """Set the colors for the default text style
+ @keyword fore: Foreground Color
+ @keyword back: Background Color
+
+ """
+ if fore is not None:
+ self.StyleSetForeground(wx.stc.STC_STYLE_DEFAULT, fore)
+ self.StyleSetForeground(wx.stc.STC_STYLE_CONTROLCHAR, fore)
+ self.StyleSetForeground(OPB_STYLE_DEFAULT, fore)
+ self._colors['defaultf'] = fore.Get()
+
+ if back is not None:
+ self.StyleSetBackground(wx.stc.STC_STYLE_DEFAULT, back)
+ self.StyleSetBackground(wx.stc.STC_STYLE_CONTROLCHAR, back)
+ self.StyleSetBackground(OPB_STYLE_DEFAULT, back)
+ self._colors['defaultb'] = back.Get()
+
+ def SetErrorColor(self, fore=None, back=None):
+ """Set color for error text
+ @keyword fore: Foreground Color
+ @keyword back: Background Color
+
+ """
+ if fore is not None:
+ self.StyleSetForeground(OPB_STYLE_ERROR, fore)
+ self._colors['errorf'] = fore.Get()
+
+ if back is not None:
+ self.StyleSetBackground(OPB_STYLE_ERROR, back)
+ self._colors['errorb'] = back.Get()
+
+ def SetInfoColor(self, fore=None, back=None):
+ """Set color for info text
+ @keyword fore: Foreground Color
+ @keyword back: Background Color
+
+ """
+ if fore is not None:
+ self.StyleSetForeground(OPB_STYLE_INFO, fore)
+ self._colors['infof'] = fore.Get()
+
+ if back is not None:
+ self.StyleSetBackground(OPB_STYLE_INFO, back)
+ self._colors['infob'] = back.Get()
+
+ def SetWarningColor(self, fore=None, back=None):
+ """Set color for warning text
+ @keyword fore: Foreground Color
+ @keyword back: Background Color
+
+ """
+ if fore is not None:
+ self.StyleSetForeground(OPB_STYLE_WARN, fore)
+ self._colors['warnf'] = fore.Get()
+
+ if back is not None:
+ self.StyleSetBackground(OPB_STYLE_WARN, back)
+ self._colors['warnb'] = back.Get()
+
+ def SetFont(self, font):
+ """Set the font used by all text in the buffer
+ @param font: wxFont
+
+ """
+ for style in OPB_ALL_STYLES:
+ self.StyleSetFont(style, font)
+
+ def SetLineBuffering(self, num):
+ """Set how many lines the buffer should keep for display.
+ @param num: int (-1 == unlimited)
+
+ """
+ self._line_buffer = num
+ self.RefreshBufferedLines()
+
+ def SetText(self, text):
+ """Set the text that is shown in the buffer
+ @param text: text string to set as buffers current value
+
+ """
+ self.SetReadOnly(False)
+ wx.stc.StyledTextCtrl.SetText(self, text)
+ self.SetReadOnly(True)
+
+ def Start(self, interval):
+ """Start the window's timer to check for updates
+ @param interval: interval in milliseconds to do updates
+
+ """
+ self._timer.Start(interval)
+
+ def Stop(self):
+ """Stop the update process of the buffer"""
+ # Dump any output still left in tmp buffer before stopping
+ self.OnTimer(None)
+ self._timer.Stop()
+ self.SetReadOnly(True)
+
+#-----------------------------------------------------------------------------#
+
+class ProcessBufferMixin:
+ """Mixin class for L{OutputBuffer} to handle events
+ generated by a L{ProcessThread}.
+
+ """
+ def __init__(self, update=100):
+ """Initialize the mixin
+ @keyword update: The update interval speed in msec
+
+ """
+ # Attributes
+ self._rate = update
+
+ # Event Handlers
+ self.Bind(EVT_PROCESS_START, self._OnProcessStart)
+ self.Bind(EVT_UPDATE_TEXT, self._OnProcessUpdate)
+ self.Bind(EVT_PROCESS_EXIT, self._OnProcessExit)
+ self.Bind(EVT_PROCESS_ERROR, self._OnProcessError)
+
+ def _OnProcessError(self, evt):
+ """Handle EVT_PROCESS_ERROR"""
+ self.DoProcessError(evt.GetValue(), evt.GetErrorMessage())
+
+ def _OnProcessExit(self, evt):
+ """Handles EVT_PROCESS_EXIT"""
+ self.DoProcessExit(evt.GetValue())
+
+ def _OnProcessStart(self, evt):
+ """Handles EVT_PROCESS_START"""
+ self.DoProcessStart(evt.GetValue())
+ self.Start(self._rate)
+
+ def _OnProcessUpdate(self, evt):
+ """Handles EVT_UPDATE_TEXT"""
+ txt = self.DoFilterInput(evt.GetValue())
+ self.AppendUpdate(txt)
+
+ def DoFilterInput(self, txt):
+ """Override this method to do an filtering on input that is sent to
+ the buffer from the process text. The return text is what is put in
+ the buffer.
+ @param txt: incoming update text
+ @return: string
+
+ """
+ return txt
+
+ def DoProcessError(self, code, excdata=None):
+ """Override this method to do any ui notification of when errors happen
+ in running the process.
+ @param code: an OBP error code
+ @keyword excdata: Exception Data from process error
+ @return: None
+
+ """
+ pass
+
+ def DoProcessExit(self, code=0):
+ """Override this method to do any post processing after the running
+ task has exited. Typically this is a good place to call
+ L{OutputBuffer.Stop} to stop the buffers timer.
+ @keyword code: Exit code of program
+ @return: None
+
+ """
+ self.Stop()
+
+ def DoProcessStart(self, cmd=''):
+ """Override this method to do any pre-processing before starting
+ a processes output.
+ @keyword cmd: Command used to start program
+ @return: None
+
+ """
+ pass
+
+ def SetUpdateInterval(self, value):
+ """Set the rate at which the buffer outputs update messages. Set to
+ a higher number if the process outputs large amounts of text at a very
+ high rate.
+ @param value: rate in milliseconds to do updates on
+
+ """
+ self._rate = value
+
+#-----------------------------------------------------------------------------#
+
+class ProcessThreadBase(threading.Thread):
+ """Base Process Thread
+ Override DoPopen in subclasses.
+
+ """
+ def __init__(self, parent):
+ super(ProcessThreadBase, self).__init__()
+
+ # Attributes
+ self.abort = False # Abort Process
+ self._proc = None
+ self._parent = parent # Parent Window/Event Handler
+ self._sig_abort = signal.SIGTERM # default signal to kill process
+ self._last_cmd = u"" # Last run command
+
+ #---- Properties ----#
+ LastCommand = property(lambda self: self._last_cmd,
+ lambda self, val: setattr(self, '_last_cmd', val))
+ Parent = property(lambda self: self._parent)
+ Process = property(lambda self: self._proc)
+
+ def __DoOneRead(self):
+ """Read one line of output and post results.
+ @return: bool (True if more), (False if not)
+
+ """
+ if subprocess.mswindows:
+ # Windows nonblocking pipe read implementation
+ read = u''
+ try:
+ handle = msvcrt.get_osfhandle(self._proc.stdout.fileno())
+ avail = ctypes.c_long()
+ ctypes.windll.kernel32.PeekNamedPipe(handle, None, 0, 0,
+ ctypes.byref(avail), None)
+ if avail.value > 0:
+ read = self._proc.stdout.read(avail.value)
+ if read.endswith(os.linesep):
+ read = read[:-1 * len(os.linesep)]
+ else:
+ if self._proc.poll() is None:
+ time.sleep(1)
+ return True
+ else:
+ # Process has Exited
+ return False
+ except ValueError, msg:
+ return False
+ except (subprocess.pywintypes.error, Exception), msg:
+ if msg[0] in (109, errno.ESHUTDOWN):
+ return False
+ else:
+ # OSX and Unix nonblocking pipe read implementation
+ if self._proc.stdout is None:
+ return False
+
+ flags = fcntl.fcntl(self._proc.stdout, fcntl.F_GETFL)
+ if not self._proc.stdout.closed:
+ fcntl.fcntl(self._proc.stdout,
+ fcntl.F_SETFL,
+ flags|os.O_NONBLOCK)
+
+ try:
+ try:
+ if not select.select([self._proc.stdout], [], [], 1)[0]:
+ return True
+
+ read = self._proc.stdout.read(4096)
+ if read == '':
+ return False
+ except IOError, msg:
+ return False
+ finally:
+ if not self._proc.stdout.closed:
+ fcntl.fcntl(self._proc.stdout, fcntl.F_SETFL, flags)
+
+ # Ignore encoding errors and return an empty line instead
+ try:
+ result = read.decode(sys.getfilesystemencoding())
+ except UnicodeDecodeError:
+ result = os.linesep
+
+ if self.Parent:
+ evt = OutputBufferEvent(edEVT_UPDATE_TEXT, self.Parent.GetId(), result)
+ wx.PostEvent(self.Parent, evt)
+ return True
+ else:
+ return False # Parent is dead no need to keep running
+
+ def __KillPid(self, pid):
+ """Kill a process by process id, causing the run loop to exit
+ @param pid: Id of process to kill
+
+ """
+ # Dont kill if the process if it is the same one we
+ # are running under (i.e we are running a shell command)
+ if pid == os.getpid():
+ return
+
+ if wx.Platform != '__WXMSW__':
+ # Close output pipe(s)
+ try:
+ try:
+ self._proc.stdout.close()
+ except Exception, msg:
+ pass
+ finally:
+ self._proc.stdout = None
+
+ # Try to kill the group
+ try:
+ os.kill(pid, self._sig_abort)
+ except OSError, msg:
+ pass
+
+ # If still alive shoot it again
+ if self._proc.poll() is not None:
+ try:
+ os.kill(-pid, signal.SIGKILL)
+ except OSError, msg:
+ pass
+
+ # Try and wait for it to cleanup
+ try:
+ os.waitpid(pid, os.WNOHANG)
+ except OSError, msg:
+ pass
+
+ else:
+ # 1 == PROCESS_TERMINATE
+ handle = ctypes.windll.kernel32.OpenProcess(1, False, pid)
+ ctypes.windll.kernel32.TerminateProcess(handle, -1)
+ ctypes.windll.kernel32.CloseHandle(handle)
+
+ #---- Public Member Functions ----#
+ def Abort(self, sig=signal.SIGTERM):
+ """Abort the running process and return control to the main thread"""
+ self._sig_abort = sig
+ self.abort = True
+
+ def DoPopen(self):
+ """Open the process
+ Override in a subclass to implement custom process opening
+ @return: subprocess.Popen instance
+
+ """
+ raise NotImplementedError("Must implement DoPopen in subclasses!")
+
+ def run(self):
+ """Run the process until finished or aborted. Don't call this
+ directly instead call self.start() to start the thread else this will
+ run in the context of the current thread.
+ @note: overridden from Thread
+
+ """
+ err = None
+ try:
+ self._proc = self.DoPopen()
+ except OSError, msg:
+ # NOTE: throws WindowsError on Windows which is a subclass of
+ # OSError, so it will still get caught here.
+ if self.Parent:
+ err = OutputBufferEvent(edEVT_PROCESS_ERROR,
+ self.Parent.GetId(),
+ OPB_ERROR_INVALID_COMMAND)
+ err.SetErrorMessage(msg)
+
+ if self.Parent:
+ evt = OutputBufferEvent(edEVT_PROCESS_START,
+ self.Parent.GetId(),
+ self.LastCommand)
+ wx.PostEvent(self.Parent, evt)
+
+ # Read from stdout while there is output from process
+ while not err and True:
+ if self.abort:
+ self.__KillPid(self.Process.pid)
+ self.__DoOneRead()
+ more = False
+ break
+ else:
+ more = False
+ try:
+ more = self.__DoOneRead()
+ except wx.PyDeadObjectError:
+ # Our parent window is dead so kill process and return
+ self.__KillPid(self.Process.pid)
+ return
+
+ if not more:
+ break
+
+ # Notify of error in running the process
+ if err is not None:
+ if self.Parent:
+ wx.PostEvent(self.Parent, err)
+ result = -1
+ else:
+ try:
+ result = self.Process.wait()
+ except OSError:
+ result = -1
+
+ # Notify that process has exited
+ # Pack the exit code as the events value
+ if self.Parent:
+ evt = OutputBufferEvent(edEVT_PROCESS_EXIT, self.Parent.GetId(), result)
+ wx.PostEvent(self.Parent, evt)
+
+class ProcessThread(ProcessThreadBase):
+ """Run a subprocess in a separate thread. Thread posts events back
+ to parent object on main thread for processing in the ui.
+ @see: EVT_PROCESS_START, EVT_PROCESS_END, EVT_UPDATE_TEXT
+
+ """
+ def __init__(self, parent, command, fname='',
+ args=list(), cwd=None, env=dict(),
+ use_shell=True):
+ """Initialize the ProcessThread object
+ Example:
+ >>> myproc = ProcessThread(myframe, '/usr/local/bin/python',
+ 'hello.py', '--version', '/Users/me/home/')
+ >>> myproc.start()
+
+ @param parent: Parent Window/EventHandler to receive the events
+ generated by the process.
+ @param command: Command string to execute as a subprocess.
+ @keyword fname: Filename or path to file to run command on.
+ @keyword args: Argument list or string to pass to use with fname arg.
+ @keyword cwd: Directory to execute process from or None to use current
+ @keyword env: Environment to run the process in (dictionary) or None to
+ use default.
+ @keyword use_shell: Specify whether a shell should be used to launch
+ program or run directly
+
+ """
+ super(ProcessThread, self).__init__(parent)
+
+ if isinstance(args, list):
+ args = u' '.join([arg.strip() for arg in args])
+
+ # Attributes
+ self._cwd = cwd # Path at which to run from
+ self._cmd = dict(cmd=command, file=fname, args=args)
+ self._use_shell = use_shell
+
+ # Make sure the environment is sane it must be all strings
+ nenv = dict(env) # make a copy to manipulate
+ for k, v in env.iteritems():
+ if isinstance(v, types.UnicodeType):
+ nenv[k] = v.encode(sys.getfilesystemencoding())
+ elif not isinstance(v, basestring):
+ nenv.pop(k)
+ self._env = nenv
+
+ # Setup
+ self.setDaemon(True)
+
+ def DoPopen(self):
+ """Open the process
+ @return: subprocess.Popen instance
+
+ """
+ # using shell, Popen will need a string, else it must be a sequence
+ # use shlex for complex command line tokenization/parsing
+ command = u' '.join([item.strip() for item in [self._cmd['cmd'],
+ self._cmd['file'],
+ self._cmd['args']]])
+ command = command.strip()
+ # TODO: exception handling and notification to main thread
+ # when encoding fails.
+ command = command.encode(sys.getfilesystemencoding())
+ if not self._use_shell and not subprocess.mswindows:
+ # Note: shlex does not support Unicode
+ command = shlex.split(command)
+
+ # TODO: if a file path to the exe has any spaces in it on Windows
+ # and use_shell is True then the command will fail. Must force
+ # to False under this condition.
+ use_shell = self._use_shell
+ # TODO: See about supporting use_shell on Windows it causes lots of
+ # issues with gui apps and killing processes when it is True.
+ if use_shell and subprocess.mswindows:
+ suinfo = subprocess.STARTUPINFO()
+ # Don't set this flag if we are not using the shell on
+ # Windows as it will cause any gui app to not show on the
+ # display!
+ #TODO: move this into common library as it is needed
+ # by most code that uses subprocess
+ if hasattr(subprocess, 'STARTF_USESHOWWINDOW'):
+ suinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+ else:
+ try:
+ from win32process import STARTF_USESHOWWINDOW
+ suinfo.dwFlags |= STARTF_USESHOWWINDOW
+ except ImportError:
+ # Give up and try hard coded value from Windows.h
+ suinfo.dwFlags |= 0x00000001
+ else:
+ suinfo = None
+
+ proc = subprocess.Popen(command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell=use_shell,
+ cwd=self._cwd,
+ env=self._env,
+ startupinfo=suinfo)
+ self.LastCommand = command # Set last run command
+ return proc
+
+ def SetArgs(self, args):
+ """Set the args to pass to the command
+ @param args: list or string of program arguments
+
+ """
+ if isinstance(args, list):
+ u' '.join(item.strip() for item in args)
+ self._cmd['args'] = args.strip()
+
+ def SetCommand(self, cmd):
+ """Set the command to execute
+ @param cmd: Command string
+
+ """
+ self._cmd['cmd'] = cmd
+
+ def SetFilename(self, fname):
+ """Set the filename to run the command on
+ @param fname: string or Unicode
+
+ """
+ self._cmd['file'] = fname
+
+#-----------------------------------------------------------------------------#
+
+class TaskThread(threading.Thread):
+ """Run a task in its own thread."""
+ def __init__(self, parent, task, *args, **kwargs):
+ """Initialize the TaskThread. All *args and **kwargs are passed
+ to the task.
+
+ @param parent: Parent Window/EventHandler to receive the events
+ generated by the process.
+ @param task: callable should be a generator object and must be iterable
+
+ """
+ super(TaskThread, self).__init__()
+ assert isinstance(parent, OutputBuffer)
+
+ self._task = TaskObject(parent, task, *args, **kwargs)
+
+ def run(self):
+ self._task.DoTask()
+
+ def Cancel(self):
+ self._task.Cancel()
+
+class TaskObject(object):
+ """Run a task in its own thread."""
+ def __init__(self, parent, task, *args, **kwargs):
+ """Initialize the TaskObject. All *args and **kwargs are passed
+ to the task.
+
+ @param parent: Parent Window/EventHandler to receive the events
+ generated by the process.
+ @param task: callable should be a generator object and must be iterable
+
+ """
+ super(TaskObject, self).__init__()
+
+ assert isinstance(parent, OutputBuffer)
+
+ # Attributes
+ self.cancel = False # Abort task
+ self._parent = parent # Parent Window/Event Handler
+ self.task = task # Task method to run
+ self._args = args
+ self._kwargs = kwargs
+
+ def DoTask(self):
+ """Start running the task"""
+ # Notify that task is beginning
+ evt = OutputBufferEvent(edEVT_TASK_START, self._parent.GetId())
+ wx.PostEvent(self._parent, evt)
+ time.sleep(.5) # Give the event a chance to be processed
+
+ # Run the task and post the results
+ for result in self.task(*self._args, **self._kwargs):
+ self._parent.AppendUpdate(result)
+ if self.cancel:
+ break
+
+ # Notify that the task is finished
+ evt = OutputBufferEvent(edEVT_TASK_COMPLETE, self._parent.GetId())
+ wx.PostEvent(self._parent, evt)
+
+ def Cancel(self):
+ """Cancel the running task"""
+ self.cancel = True
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/panelbox.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/panelbox.py
new file mode 100644
index 0000000..c3f421a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/panelbox.py
@@ -0,0 +1,445 @@
+###############################################################################
+# Name: panelbox.py #
+# Purpose: Advanced listbox control #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: PanelBox
+
+Class PanelBox:
+
+ListBox like container class that accepts custom panels as items in the list.
+
+Class PanelBoxItemBase:
+
+Base class for all PanelBoxItems. Provides the basic functionality for a custom
+subclass to interact with the PanelBox container list.
+
+Class PanelBoxItem:
+
+Simple PanelBoxItem that has support for displaying an Icon, Main text, and a
+a user defined sub item.
+
++-------------------------+
+| |
+| ICON label |
+| sub item |
++-------------------------+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: panelbox.py 67123 2011-03-04 00:02:35Z CJP $"
+__revision__ = "$Revision: 67123 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.lib.scrolledpanel as scrolled
+
+#--------------------------------------------------------------------------#
+
+edEVT_ITEM_SELECTED = wx.NewEventType()
+EVT_ITEM_SELECTED = wx.PyEventBinder(edEVT_ITEM_SELECTED, 1)
+
+class PanelBoxEventEvent(wx.PyCommandEvent):
+ """Panel Box Event Object"""
+ pass
+
+#--------------------------------------------------------------------------#
+
+class PanelBox(scrolled.ScrolledPanel):
+ """Scrolled container window for managing and displaying PanelBox items"""
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.HSCROLL|wx.VSCROLL,
+ name=u"PanelBox"):
+ super(PanelBox, self).__init__(parent, id, pos, size, style, name)
+
+ # Attributes
+ self._items = list()
+ self._last_sel = -1
+ self._sizer = wx.BoxSizer(wx.VERTICAL)
+
+ # Setup
+ bkgrnd = wx.SystemSettings.GetColour(wx.SYS_COLOUR_LISTBOX)
+ self.SetBackgroundColour(bkgrnd)
+
+ self.SetSizer(self._sizer)
+ self.SetAutoLayout(True)
+
+ self.SetupScrolling()
+
+ # Event Handlers
+# self.Bind(wx.EVT_KEY_UP, self.OnNavigate)
+ self.GetParent().Bind(wx.EVT_KEY_UP, self.OnNavigate)
+
+ #---- Event Handlers ----#
+
+ def OnItemClicked(self, evt):
+ """Callback from when children are clicked on
+ @param evt: wx.MouseEvent
+
+ """
+ item = evt.GetEventObject()
+ selected = item.IsSelected()
+ idx = self.FindIndex(item)
+ if idx == -1:
+ return
+
+ if evt.CmdDown():
+ # Add/Remove from selection
+ item.SetSelection(not selected)
+ elif evt.ShiftDown():
+ # Select all items between this item and the next selected one
+ if idx < self._last_sel:
+ inc = -1
+ else:
+ inc = 1
+
+ for index in range(self._last_sel, idx + inc, inc):
+ self.SetSelection(index, True)
+ else:
+ # Move selection to this item
+ self.ClearSelections()
+
+ if not selected:
+ item.SetSelection(True)
+
+ if not selected:
+ self._last_sel = idx
+ else:
+ self._last_sel = -1
+
+ def OnNavigate(self, evt):
+ """Handle navigation key events"""
+ key_code = evt.GetKeyCode()
+ nsel = None
+ isup = False
+ if key_code == wx.WXK_UP:
+ if self._last_sel in (0, -1):
+ nsel = len(self._items) - 1
+ else:
+ nsel = self._last_sel - 1
+ isup = True
+ elif key_code == wx.WXK_DOWN:
+ if self._last_sel in (-1, len(self._items) - 1):
+ nsel = 0
+ else:
+ nsel = self._last_sel + 1
+ else:
+ evt.Skip()
+ return
+
+ if evt.ShiftDown():
+ self.SetSelection(nsel, True)
+ else:
+ self.ClearSelections()
+ self.SetSelection(nsel, True)
+
+ evt.Skip()
+
+ #---- Public Api ----#
+ def AppendItem(self, item):
+ """Append an item to the list
+ @param item: PanelBoxItem
+
+ """
+ self._items.append(item)
+ self._sizer.Add(item, 0, wx.EXPAND)
+ item.Realize()
+
+ def ClearSelections(self):
+ """Unselect all items"""
+ for item in self._items:
+ item.SetSelection(False)
+
+ def DeleteAllItems(self):
+ """Delete all the items in the list"""
+ for item in self._items:
+ self._sizer.Remove(item)
+ try:
+ item.Destroy()
+ except wx.PyDeadObjectError:
+ pass
+
+ del self._items
+ self._items = list()
+ self.Layout()
+
+ def FindIndex(self, item):
+ """Find the index of a given L{PanelBoxItem}
+ @param item: instance of PanelBoxItemBase
+ @return: int (-1 on failure)
+
+ """
+ for idx, pbitem in enumerate(self._items):
+ if pbitem is item:
+ return idx
+ else:
+ return -1
+
+ def GetItemCount(self):
+ """Get the number of items in the control
+ @return: int
+
+ """
+ return len(self._items)
+
+ def GetItems(self):
+ """Get the list of items held by this control
+ @return: list of PanelBoxItems
+ @todo: should probably return a list of shadow items so that orignals
+ are not modified.
+
+ """
+ return self._items
+
+ def GetSelection(self):
+ """Get the (first) selected item"""
+ for item in self._items:
+ if item.IsSelected():
+ return item
+ else:
+ return None
+
+ def GetSelections(self):
+ """Get the list of selected items
+ @return: list
+
+ """
+ return [item for item in self._items if item.IsSelected()]
+
+ def InsertItem(self, index, item):
+ """Insert an item into the list
+ @param index: index to insert at
+ @param item: PanelBoxItem
+
+ """
+ if index <= len(self._items):
+ self._items.insert(index, item)
+ self._sizer.Insert(index, item, 0, wx.EXPAND)
+ else:
+ raise IndexError, "Index %d: out of range" % index
+
+ def Remove(self, index):
+ """Remove an item from the list
+ @param index: item index
+
+ """
+ if index < len(self._items):
+ item = self._items.pop(index)
+ self._sizer.Remove(item)
+ self.Layout()
+ else:
+ raise IndexError, "Index %d: out of range" % index
+
+ def RemoveAll(self):
+ """Remove all items from the list"""
+ for item in self._items:
+ self._sizer.Remove(item)
+
+ del self._items
+ self._items = list()
+
+ self.Layout()
+
+ def SetSelection(self, idx, select=True):
+ """Set the selection on a given index
+ @param idx: int
+ @keyword select: bool
+
+ """
+ if idx < len(self._items):
+ item = self._items[idx]
+ item.SetSelection(select)
+ self._last_sel = idx
+ else:
+ raise IndexError, "Index out of range: %d > %d" (idx, len(self._items))
+
+#--------------------------------------------------------------------------#
+
+class PanelBoxItemBase(wx.PyPanel):
+ """Base L{PanelBox} Item"""
+ def __init__(self, parent):
+ """Create a PanelBoxItem"""
+ super(PanelBoxItemBase, self).__init__(parent,
+ style=wx.NO_BORDER|wx.TAB_TRAVERSAL)
+
+ # Attributes
+ self._selected = False
+
+ # Event Handlers
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+# self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
+
+ def _UpdateForeground(self, color):
+ """Update foreground colors when selection changes
+ @param color: selection color
+ @todo: should cache text's original color to restore
+ on de-selection.
+
+ """
+ if sum(color.Get()[:3]) < (127 * 3):
+ ncolor = wx.WHITE
+ else:
+ ncolor = wx.BLACK
+
+ for child in self.GetChildren():
+ if hasattr(child, 'SetForegroundColour') and \
+ not isinstance(child, wx.Button):
+ child.SetForegroundColour(ncolor)
+
+ def OnKeyUp(self, evt):
+ """Handle key navigation events"""
+ self.GetParent().OnNavigate(evt)
+ evt.Skip()
+
+ def OnLeftUp(self, evt):
+ """Handle when the item is clicked on"""
+ e_obj = evt.GetEventObject()
+ evt.SetEventObject(self)
+ self.GetParent().OnItemClicked(evt)
+ evt.SetEventObject(e_obj)
+ evt.Skip()
+
+ def OnMouseWheel(self, evt):
+ """Relay the mouse wheel events to the panel box"""
+ self.GetParent().GetEventHandler().ProcessEvent(evt)
+ evt.Skip()
+
+ def OnPaint(self, evt):
+ """Paint the items background"""
+ dc = wx.PaintDC(self)
+ rect = self.GetClientRect()
+
+# if self.IsSelected():
+# color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+# dc.SetBrush(wx.Brush(color))
+# dc.SetPen(wx.TRANSPARENT_PEN)
+# dc.DrawRectangle(*rect)
+# else:
+# col2 = wx.SystemSettings_GetColour(wx.SYS_COLOUR_LISTBOX)
+# dc.SetBackground(wx.Brush(col2))
+# dc.SetBrush(wx.Brush(col2))
+# dc.SetPen(wx.TRANSPARENT_PEN)
+# dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height - 1)
+
+ pcolor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
+ dc.SetPen(wx.Pen(pcolor))
+ dc.DrawLine(rect.x, rect.bottom, rect.right, rect.bottom)
+
+ def IsSelected(self):
+ """Is this item selected
+ @return: bool
+
+ """
+ return self._selected
+
+ def Realize(self):
+ """Finalize initialization of the panel item"""
+ for child in self.GetChildren():
+ child.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+
+ def SetSelection(self, select=False):
+ """Set the selection state on this item
+ @keyword select: bool
+
+ """
+ self._selected = select
+ if self._selected:
+ color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ else:
+ color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_LISTBOX)
+ self.SetBackgroundColour(color)
+ self._UpdateForeground(color)
+ self.Refresh()
+
+#--------------------------------------------------------------------------#
+
+class PanelBoxItem(PanelBoxItemBase):
+ """L{PanelBox} Item that has an icon, main label text and sub label
+ +-------------------------+
+ | |
+ | ICON label |
+ | sub item |
+ +-------------------------+
+
+ """
+ def __init__(self, parent, bmp=None, label=u'', sub=None):
+ """Create teh PanelBoxItem
+ @param parent: L{PanelBox}
+ @keyword bmp: wx.Bitmap
+ @keyword label: string
+ @keyword sub: Window object or None
+
+ """
+ super(PanelBoxItem, self).__init__(parent)
+
+ # Attributes
+ self._bmp = bmp
+ self._label = label
+ self._sub = sub
+
+ # Layout
+ self.__DoLayout()
+ self.SetAutoLayout(True)
+
+ def __DoLayout(self):
+ """Layout the control"""
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ hsizer.Add((8, 8), 0)
+ if self._bmp is not None:
+ self._bmp = wx.StaticBitmap(self, bitmap=self._bmp)
+ hsizer.Add(self._bmp, 0, wx.ALIGN_CENTER_VERTICAL)
+ hsizer.Add((5, 5), 0)
+
+ # Add Label Text
+ isizer = wx.BoxSizer(wx.VERTICAL)
+ self._label = wx.StaticText(self, label=self._label)
+ isizer.Add(self._label, 0, wx.ALIGN_LEFT)
+ if self._sub is not None:
+ isizer.Add((3, 3), 0)
+
+ # Add Subwindow if one is defined
+ if self._sub is not None:
+ self._sub.Reparent(self)
+ s_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ s_sizer.Add(self._sub, 1, wx.EXPAND)
+ isizer.Add(s_sizer, 1, wx.EXPAND)
+
+ hsizer.Add(isizer, 1, wx.ALIGN_CENTER_VERTICAL)
+ hsizer.Add((8, 8), 0)
+ vsizer.AddMany([((8, 8), 0), (hsizer, 0, wx.EXPAND), ((8, 8), 0)])
+ self.SetSizer(vsizer)
+
+ def SetBitmap(self, bmp):
+ """Set the items image
+ param bmp: wx.Bitmap
+
+ """
+ self._bmp.SetBitmap(bmp)
+ self._bmp.Refresh()
+ self.Layout()
+
+ def SetLabel(self, lbl):
+ """Set the label text
+ @param lbl: string
+
+ """
+ self._lbl.SetLabel(lbl)
+ self._lbl.Refresh()
+ self.Layout()
+
+ def SetSecondaryCtrl(self, ctrl):
+ """Set the secondary control
+ @param ctrl: wxWindow
+
+ """
+ pass
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/platebtn.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/platebtn.py
new file mode 100644
index 0000000..8577c5d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/platebtn.py
@@ -0,0 +1,724 @@
+###############################################################################
+# Name: platebtn.py #
+# Purpose: PlateButton is a flat label button with support for bitmaps and #
+# drop menu. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Control Library: PlateButton
+
+The PlateButton is a custom owner drawn flat button, that in many ways emulates
+the buttons found the bookmark bar of the Safari browser. It can be used as a
+drop in replacement for wx.Button/wx.BitmapButton under most circumstances. It
+also offers a wide range of options for customizing its appearance, a
+description of each of the main style settings is listed below.
+
+Main Button Styles:
+Any combination of the following values may be passed to the constructor's style
+keyword parameter.
+
+PB_STYLE_DEFAULT:
+Creates a flat label button with rounded corners, the highlight for mouse over
+and press states is based off of the hightlight color from the systems current
+theme.
+
+PB_STYLE_GRADIENT:
+The highlight and press states are drawn with gradient using the current
+highlight color.
+
+PB_STYLE_SQUARE:
+Instead of the default rounded shape use a rectangular shaped button with
+square edges.
+
+PB_STYLE_NOBG:
+This style only has an effect on Windows but does not cause harm to use on the
+platforms. It should only be used when the control is shown on a panel or other
+window that has a non solid color for a background. i.e a gradient or image is
+painted on the background of the parent window. If used on a background with
+a solid color it may cause the control to loose its transparent appearance.
+
+PB_STYLE_DROPARROW:
+Add a drop button arrow to the button that will send a separate event when
+clicked on.
+
+Other attributes can be configured after the control has been created. The
+settings that are currently available are as follows:
+
+ - SetBitmap: Change/Add the bitmap at any time and the control will resize and
+ refresh to display it.
+ - SetLabelColor: Explicitly set text colors
+ - SetMenu: Set the button to have a popupmenu. When a menu is set a small drop
+ arrow will be drawn on the button that can then be clicked to show
+ a menu.
+ - SetPressColor: Use a custom highlight color
+
+
+Overridden Methods Inherited from PyControl:
+
+ - SetFont: Changing the font is one way to set the size of the button, by
+ default the control will inherit its font from its parent.
+
+ - SetWindowVariant: Setting the window variant will cause the control to
+ resize to the corresponding variant size. However if the
+ button is using a bitmap the bitmap will remain unchanged
+ and only the font will be adjusted.
+
+Requirements:
+ - python2.4 or higher
+ - wxPython2.8 or higher
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: platebtn.py 74797 2013-09-12 14:40:48Z CJP $"
+__revision__ = "$Revision: 74797 $"
+
+__all__ = ["PlateButton",
+ "PLATE_NORMAL", "PLATE_PRESSED", "PLATE_HIGHLIGHT",
+
+ "PB_STYLE_DEFAULT", "PB_STYLE_GRADIENT", "PB_STYLE_SQUARE",
+ "PB_STYLE_NOBG", "PB_STYLE_DROPARROW", "PB_STYLE_TOGGLE",
+
+ "EVT_PLATEBTN_DROPARROW_PRESSED"]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.lib.newevent
+
+# Local Imports
+from eclutil import *
+
+#-----------------------------------------------------------------------------#
+# Button States
+PLATE_NORMAL = 0
+PLATE_PRESSED = 1
+PLATE_HIGHLIGHT = 2
+
+# Button Styles
+PB_STYLE_DEFAULT = 1 # Normal Flat Background
+PB_STYLE_GRADIENT = 2 # Gradient Filled Background
+PB_STYLE_SQUARE = 4 # Use square corners instead of rounded
+PB_STYLE_NOBG = 8 # Usefull on Windows to get a transparent appearance
+ # when the control is shown on a non solid background
+PB_STYLE_DROPARROW = 16 # Draw drop arrow and fire EVT_PLATEBTN_DROPRROW_PRESSED event
+PB_STYLE_TOGGLE = 32 # Stay pressed untill clicked again
+
+#-----------------------------------------------------------------------------#
+
+# EVT_BUTTON used for normal event notification
+# EVT_TOGGLE_BUTTON used for toggle button mode notification
+PlateBtnDropArrowPressed, EVT_PLATEBTN_DROPARROW_PRESSED = wx.lib.newevent.NewEvent()
+
+#-----------------------------------------------------------------------------#
+
+class PlateButton(wx.PyControl):
+ """PlateButton is a custom type of flat button with support for
+ displaying bitmaps and having an attached dropdown menu.
+
+ """
+ def __init__(self, parent, id=wx.ID_ANY, label='', bmp=None,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=PB_STYLE_DEFAULT, name=wx.ButtonNameStr):
+ """Create a PlateButton
+ @keyword label: Buttons label text
+ @keyword bmp: Buttons bitmap
+ @keyword style: Button style
+
+ """
+ super(PlateButton, self).__init__(parent, id, pos, size,
+ wx.BORDER_NONE|wx.TRANSPARENT_WINDOW,
+ name=name)
+
+ # Attributes
+ self.InheritAttributes()
+ self._bmp = dict(enable=None, disable=None)
+ if bmp is not None:
+ assert isinstance(bmp, wx.Bitmap) and bmp.IsOk()
+ self._bmp['enable'] = bmp
+ img = bmp.ConvertToImage()
+ img = img.ConvertToGreyscale(.795, .073, .026) #(.634, .224, .143)
+ self._bmp['disable'] = wx.BitmapFromImage(img)
+
+ self._menu = None
+ self.SetLabel(label)
+ self._style = style
+ self._state = dict(pre=PLATE_NORMAL, cur=PLATE_NORMAL)
+ self._color = self.__InitColors()
+ self._pressed = False
+
+ # Setup Initial Size
+ self.SetInitialSize(size)
+
+ # Event Handlers
+ self.Bind(wx.EVT_PAINT, lambda evt: self.__DrawButton())
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+ # Mouse Events
+ self.Bind(wx.EVT_LEFT_DCLICK, lambda evt: self._ToggleState())
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_ENTER_WINDOW,
+ lambda evt: self._SetState(PLATE_HIGHLIGHT))
+ self.Bind(wx.EVT_LEAVE_WINDOW,
+ lambda evt: wx.CallLater(80, self.__LeaveWindow))
+
+ # Other events
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self.Bind(wx.EVT_CONTEXT_MENU, lambda evt: self.ShowMenu())
+
+ def __DrawBitmap(self, gc):
+ """Draw the bitmap if one has been set
+ @param gc: GCDC to draw with
+ @return: x cordinate to draw text at
+
+ """
+ if self.IsEnabled():
+ bmp = self._bmp['enable']
+ else:
+ bmp = self._bmp['disable']
+
+ if bmp is not None and bmp.IsOk():
+ bw, bh = bmp.GetSize()
+ ypos = (self.GetSize()[1] - bh) // 2
+ gc.DrawBitmap(bmp, 6, ypos, bmp.GetMask() != None)
+ return bw + 6
+ else:
+ return 6
+
+ def __DrawDropArrow(self, gc, xpos, ypos):
+ """Draw a drop arrow if needed and restore pen/brush after finished
+ @param gc: GCDC to draw with
+ @param xpos: x cord to start at
+ @param ypos: y cord to start at
+
+ """
+ if self._menu is not None or self._style & PB_STYLE_DROPARROW:
+ # Positioning needs a little help on Windows
+ if wx.Platform == '__WXMSW__':
+ xpos -= 2
+ tripoints = [(xpos, ypos), (xpos + 6, ypos), (xpos + 3, ypos + 5)]
+ brush_b = gc.GetBrush()
+ pen_b = gc.GetPen()
+ gc.SetPen(wx.TRANSPARENT_PEN)
+ gc.SetBrush(wx.Brush(gc.GetTextForeground()))
+ gc.DrawPolygon(tripoints)
+ gc.SetBrush(brush_b)
+ gc.SetPen(pen_b)
+ else:
+ pass
+
+ def __DrawHighlight(self, gc, width, height):
+ """Draw the main highlight/pressed state
+ @param gc: GCDC to draw with
+ @param width: width of highlight
+ @param height: height of highlight
+
+ """
+ if self._state['cur'] == PLATE_PRESSED:
+ color = self._color['press']
+ else:
+ color = self._color['hlight']
+
+ if self._style & PB_STYLE_SQUARE:
+ rad = 0
+ else:
+ rad = (height - 3) / 2
+
+ if self._style & PB_STYLE_GRADIENT:
+ gc.SetBrush(wx.TRANSPARENT_BRUSH)
+ rgc = gc.GetGraphicsContext()
+ brush = rgc.CreateLinearGradientBrush(0, 1, 0, height,
+ color, AdjustAlpha(color, 55))
+ rgc.SetBrush(brush)
+ else:
+ gc.SetBrush(wx.Brush(color))
+
+ gc.DrawRoundedRectangle(1, 1, width - 2, height - 2, rad)
+
+ def __PostEvent(self):
+ """Post a button event to parent of this control"""
+ if self._style & PB_STYLE_TOGGLE:
+ etype = wx.wxEVT_COMMAND_TOGGLEBUTTON_CLICKED
+ else:
+ etype = wx.wxEVT_COMMAND_BUTTON_CLICKED
+ bevt = wx.CommandEvent(etype, self.GetId())
+ bevt.SetEventObject(self)
+ bevt.SetString(self.GetLabel())
+ self.GetEventHandler().ProcessEvent(bevt)
+
+ def __DrawButton(self):
+ """Draw the button"""
+ dc = wx.PaintDC(self)
+ gc = wx.GCDC(dc)
+
+ # Setup
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ gc.SetBrush(wx.TRANSPARENT_BRUSH)
+ gc.SetFont(self.Font)
+ dc.SetFont(self.Font)
+ gc.SetBackgroundMode(wx.TRANSPARENT)
+
+ # The background needs some help to look transparent on
+ # on Gtk and Windows
+ if wx.Platform in ['__WXGTK__', '__WXMSW__']:
+ gc.SetBackground(self.GetBackgroundBrush(gc))
+ gc.Clear()
+
+ # Calc Object Positions
+ width, height = self.GetSize()
+ if wx.Platform == '__WXGTK__':
+ tw, th = dc.GetTextExtent(self.Label)
+ else:
+ tw, th = gc.GetTextExtent(self.Label)
+ txt_y = max((height - th) // 2, 1)
+
+ if self._state['cur'] == PLATE_HIGHLIGHT:
+ gc.SetTextForeground(self._color['htxt'])
+ gc.SetPen(wx.TRANSPARENT_PEN)
+ self.__DrawHighlight(gc, width, height)
+
+ elif self._state['cur'] == PLATE_PRESSED:
+ gc.SetTextForeground(self._color['htxt'])
+ if wx.Platform == '__WXMAC__':
+ pen = wx.Pen(GetHighlightColour(), 1, wx.SOLID)
+ else:
+ pen = wx.Pen(AdjustColour(self._color['press'], -80, 220), 1)
+ gc.SetPen(pen)
+
+ self.__DrawHighlight(gc, width, height)
+ txt_x = self.__DrawBitmap(gc)
+ t_x = max((width - tw - (txt_x + 2)) // 2, txt_x + 2)
+ if wx.Platform == '__WXGTK__':
+ dc.DrawText(self.Label, t_x, txt_y)
+ else:
+ gc.DrawText(self.Label, t_x, txt_y)
+ self.__DrawDropArrow(gc, width - 10, (height // 2) - 2)
+
+ else:
+ if self.IsEnabled():
+ gc.SetTextForeground(self.GetForegroundColour())
+ else:
+ txt_c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)
+ gc.SetTextForeground(txt_c)
+
+ # Draw bitmap and text
+ if self._state['cur'] != PLATE_PRESSED:
+ txt_x = self.__DrawBitmap(gc)
+ t_x = max((width - tw - (txt_x + 2)) // 2, txt_x + 2)
+ if wx.Platform == '__WXGTK__':
+ dc.DrawText(self.Label, t_x, txt_y)
+ else:
+ gc.DrawText(self.Label, t_x, txt_y)
+ self.__DrawDropArrow(gc, width - 10, (height // 2) - 2)
+
+ def __InitColors(self):
+ """Initialize the default colors"""
+ color = GetHighlightColour()
+ pcolor = AdjustColour(color, -12)
+ colors = dict(default=True,
+ hlight=color,
+ press=pcolor,
+ htxt=BestLabelColour(self.GetForegroundColour()))
+ return colors
+
+ def __LeaveWindow(self):
+ """Handle updating the buttons state when the mouse cursor leaves"""
+ # Invoked via CallLater so possible that the C++ object may
+ # may have been yanked out from under us in the meantime.
+ if self:
+ if (self._style & PB_STYLE_TOGGLE) and self._pressed:
+ self._SetState(PLATE_PRESSED)
+ else:
+ self._SetState(PLATE_NORMAL)
+ self._pressed = False
+
+ def _SetState(self, state):
+ """Manually set the state of the button
+ @param state: one of the PLATE_* values
+ @note: the state may be altered by mouse actions
+ @note: Internal use only!
+
+ """
+ if self:
+ self._state['pre'] = self._state['cur']
+ self._state['cur'] = state
+ if wx.Platform == '__WXMSW__':
+ self.Parent.RefreshRect(self.Rect, False)
+ else:
+ self.Refresh()
+
+ def _ToggleState(self):
+ """Toggle button state
+ @note: Internal Use Only!
+
+ """
+ if self._state['cur'] != PLATE_PRESSED:
+ self._SetState(PLATE_PRESSED)
+ else:
+ self._SetState(PLATE_HIGHLIGHT)
+
+ #---- End Private Member Function ----#
+
+ #---- Public Member Functions ----#
+
+ BitmapDisabled = property(lambda self: self.GetBitmapDisabled(),
+ lambda self, bmp: self.SetBitmapDisabled(bmp))
+ BitmapLabel = property(lambda self: self.GetBitmapLabel(),
+ lambda self, bmp: self.SetBitmap(bmp))
+
+ # Aliases
+ BitmapFocus = BitmapLabel
+ BitmapHover = BitmapLabel
+ BitmapSelected = BitmapLabel
+
+ LabelText = property(lambda self: self.GetLabel(),
+ lambda self, lbl: self.SetLabel(lbl))
+
+ def AcceptsFocus(self):
+ """Can this window have the focus?"""
+ return self.IsEnabled()
+
+ def Disable(self):
+ """Disable the control"""
+ super(PlateButton, self).Disable()
+ self.Refresh()
+
+ def DoGetBestSize(self):
+ """Calculate the best size of the button
+ @return: wx.Size
+
+ """
+ width = 4
+ height = 6
+ if self.Label:
+ # NOTE: Should measure with a GraphicsContext to get right
+ # size, but due to random segfaults on linux special
+ # handling is done in the drawing instead...
+ lsize = self.GetFullTextExtent(self.Label)
+ width += lsize[0]
+ height += lsize[1]
+
+ if self._bmp['enable'] is not None:
+ bsize = self._bmp['enable'].Size
+ width += (bsize[0] + 10)
+ if height <= bsize[1]:
+ height = bsize[1] + 6
+ else:
+ height += 3
+ else:
+ width += 10
+
+ if self._menu is not None or self._style & PB_STYLE_DROPARROW:
+ width += 12
+
+ best = wx.Size(width, height)
+ self.CacheBestSize(best)
+ return best
+
+ def Enable(self, enable=True):
+ """Enable/Disable the control"""
+ super(PlateButton, self).Enable(enable)
+ self.Refresh()
+
+ def GetBackgroundBrush(self, dc):
+ """Get the brush for drawing the background of the button
+ @return: wx.Brush
+ @note: used internally when on gtk
+
+ """
+ if wx.Platform == '__WXMAC__' or self._style & PB_STYLE_NOBG:
+ return wx.TRANSPARENT_BRUSH
+
+ bkgrd = self.GetBackgroundColour()
+ brush = wx.Brush(bkgrd, wx.SOLID)
+ my_attr = self.GetDefaultAttributes()
+ p_attr = self.Parent.GetDefaultAttributes()
+ my_def = bkgrd == my_attr.colBg
+ p_def = self.Parent.GetBackgroundColour() == p_attr.colBg
+ if my_def and not p_def:
+ bkgrd = self.Parent.GetBackgroundColour()
+ brush = wx.Brush(bkgrd, wx.SOLID)
+ return brush
+
+ def GetBitmapDisabled(self):
+ """Get the bitmap of the disable state
+ @return: wx.Bitmap or None
+
+ """
+ return self.BitmapDisabled
+
+ def GetBitmapLabel(self):
+ """Get the label bitmap
+ @return: wx.Bitmap or None
+
+ """
+ return self.BitmapLabel
+
+ # GetBitmap Aliases for BitmapButton api
+ GetBitmapFocus = GetBitmapLabel
+ GetBitmapHover = GetBitmapLabel
+
+ # Alias for GetLabel
+ GetLabelText = wx.PyControl.GetLabel
+
+ def GetMenu(self):
+ """Return the menu associated with this button or None if no
+ menu is associated with it.
+
+ """
+ return self._menu
+
+ def GetState(self):
+ """Get the current state of the button
+ @return: int
+ @see: PLATE_NORMAL, PLATE_HIGHLIGHT, PLATE_PRESSED
+
+ """
+ return self._state['cur']
+
+ def HasTransparentBackground(self):
+ """Override setting of background fill"""
+ return True
+
+ def IsPressed(self):
+ """Return if button is pressed (PB_STYLE_TOGGLE)
+ @return: bool
+
+ """
+ return self._pressed
+
+ #---- Event Handlers ----#
+
+ def OnErase(self, evt):
+ """Trap the erase event to keep the background transparent
+ on windows.
+ @param evt: wx.EVT_ERASE_BACKGROUND
+
+ """
+ if not (PB_STYLE_NOBG & self._style):
+ evt.Skip()
+
+ def OnFocus(self, evt):
+ """Set the visual focus state if need be"""
+ if self._state['cur'] == PLATE_NORMAL:
+ self._SetState(PLATE_HIGHLIGHT)
+
+ def OnKeyUp(self, evt):
+ """Execute a single button press action when the Return key is pressed
+ and this control has the focus.
+ @param evt: wx.EVT_KEY_UP
+
+ """
+ if evt.GetKeyCode() == wx.WXK_SPACE:
+ self._SetState(PLATE_PRESSED)
+ self.__PostEvent()
+ wx.CallLater(100, self._SetState, PLATE_HIGHLIGHT)
+ else:
+ evt.Skip()
+
+ def OnKillFocus(self, evt):
+ """Set the visual state back to normal when focus is lost
+ unless the control is currently in a pressed state.
+
+ """
+ # Note: this delay needs to be at least as much as the on in the KeyUp
+ # handler to prevent ghost highlighting from happening when
+ # quickly changing focus and activating buttons
+ if self._state['cur'] != PLATE_PRESSED:
+ self._SetState(PLATE_NORMAL)
+
+ def OnLeftDown(self, evt):
+ """Sets the pressed state and depending on the click position will
+ show the popup menu if one has been set.
+
+ """
+ if (self._style & PB_STYLE_TOGGLE):
+ self._pressed = not self._pressed
+
+ pos = evt.GetPositionTuple()
+ self._SetState(PLATE_PRESSED)
+ size = self.GetSizeTuple()
+ if pos[0] >= size[0] - 16:
+ if self._menu is not None:
+ self.ShowMenu()
+ elif self._style & PB_STYLE_DROPARROW:
+ event = PlateBtnDropArrowPressed()
+ event.SetEventObject(self)
+ self.EventHandler.ProcessEvent(event)
+
+ self.SetFocus()
+
+ def OnLeftUp(self, evt):
+ """Post a button event if the control was previously in a
+ pressed state.
+ @param evt: wx.MouseEvent
+
+ """
+ if self._state['cur'] == PLATE_PRESSED:
+ pos = evt.GetPositionTuple()
+ size = self.GetSizeTuple()
+ if not (self._style & PB_STYLE_DROPARROW and pos[0] >= size[0] - 16):
+ self.__PostEvent()
+
+ if self._pressed:
+ self._SetState(PLATE_PRESSED)
+ else:
+ self._SetState(PLATE_HIGHLIGHT)
+
+ def OnMenuClose(self, evt):
+ """Refresh the control to a proper state after the menu has been
+ dismissed.
+ @param evt: wx.EVT_MENU_CLOSE
+
+ """
+ mpos = wx.GetMousePosition()
+ if self.HitTest(self.ScreenToClient(mpos)) != wx.HT_WINDOW_OUTSIDE:
+ self._SetState(PLATE_HIGHLIGHT)
+ else:
+ self._SetState(PLATE_NORMAL)
+ evt.Skip()
+
+ #---- End Event Handlers ----#
+
+ def SetBitmap(self, bmp):
+ """Set the bitmap displayed in the button
+ @param bmp: wx.Bitmap
+
+ """
+ self._bmp['enable'] = bmp
+ img = bmp.ConvertToImage()
+ img = img.ConvertToGreyscale(.795, .073, .026) #(.634, .224, .143)
+ self._bmp['disable'] = img.ConvertToBitmap()
+ self.InvalidateBestSize()
+
+ def SetBitmapDisabled(self, bmp):
+ """Set the bitmap for the disabled state
+ @param bmp: wx.Bitmap
+
+ """
+ self._bmp['disable'] = bmp
+
+ # Aliases for SetBitmap* functions from BitmapButton
+ SetBitmapFocus = SetBitmap
+ SetBitmapHover = SetBitmap
+ SetBitmapLabel = SetBitmap
+ SetBitmapSelected = SetBitmap
+
+ def SetFocus(self):
+ """Set this control to have the focus"""
+ if self._state['cur'] != PLATE_PRESSED:
+ self._SetState(PLATE_HIGHLIGHT)
+ super(PlateButton, self).SetFocus()
+
+ def SetFont(self, font):
+ """Adjust size of control when font changes"""
+ super(PlateButton, self).SetFont(font)
+ self.InvalidateBestSize()
+
+ def SetLabel(self, label):
+ """Set the label of the button
+ @param label: lable string
+
+ """
+ super(PlateButton, self).SetLabel(label)
+ self.InvalidateBestSize()
+
+ def SetLabelColor(self, normal, hlight=wx.NullColour):
+ """Set the color of the label. The optimal label color is usually
+ automatically selected depending on the button color. In some
+ cases the colors that are chosen may not be optimal.
+
+ The normal state must be specified, if the other two params are left
+ Null they will be automatically guessed based on the normal color. To
+ prevent this automatic color choices from happening either specify
+ a color or None for the other params.
+
+ @param normal: Label color for normal state (wx.Colour)
+ @keyword hlight: Color for when mouse is hovering over
+
+ """
+ assert isinstance(normal, wx.Colour), "Must supply a colour object"
+ self._color['default'] = False
+ self.SetForegroundColour(normal)
+
+ if hlight is not None:
+ if hlight.IsOk():
+ self._color['htxt'] = hlight
+ else:
+ self._color['htxt'] = BestLabelColour(normal)
+
+ if wx.Platform == '__WXMSW__':
+ self.Parent.RefreshRect(self.GetRect(), False)
+ else:
+ self.Refresh()
+
+ def SetMenu(self, menu):
+ """Set the menu that can be shown when clicking on the
+ drop arrow of the button.
+ @param menu: wxMenu to use as a PopupMenu
+ @note: Arrow is not drawn unless a menu is set
+
+ """
+ if self._menu is not None:
+ self.Unbind(wx.EVT_MENU_CLOSE)
+
+ self._menu = menu
+ self.Bind(wx.EVT_MENU_CLOSE, self.OnMenuClose)
+ self.InvalidateBestSize()
+
+ def SetPressColor(self, color):
+ """Set the color used for highlighting the pressed state
+ @param color: wx.Colour
+ @note: also resets all text colours as necessary
+
+ """
+ self._color['default'] = False
+ if color.Alpha() == 255:
+ self._color['hlight'] = AdjustAlpha(color, 200)
+ else:
+ self._color['hlight'] = color
+ self._color['press'] = AdjustColour(color, -10, 160)
+ self._color['htxt'] = BestLabelColour(self._color['hlight'])
+ self.Refresh()
+
+ def SetWindowStyle(self, style):
+ """Sets the window style bytes, the updates take place
+ immediately no need to call refresh afterwards.
+ @param style: bitmask of PB_STYLE_* values
+
+ """
+ self._style = style
+ self.Refresh()
+
+ def SetWindowVariant(self, variant):
+ """Set the variant/font size of this control"""
+ super(PlateButton, self).SetWindowVariant(variant)
+ self.InvalidateBestSize()
+
+ def ShouldInheritColours(self):
+ """Overridden base class virtual. If the parent has non-default
+ colours then we want this control to inherit them.
+
+ """
+ return True
+
+ def ShowMenu(self):
+ """Show the dropdown menu if one is associated with this control"""
+ if self._menu is not None:
+ size = self.GetSizeTuple()
+ adj = wx.Platform == '__WXMAC__' and 3 or 0
+
+ if self._style & PB_STYLE_SQUARE:
+ xpos = 1
+ else:
+ xpos = size[1] / 2
+
+ self.PopupMenu(self._menu, (xpos, size[1] + adj))
+
+ #---- End Public Member Functions ----#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/pstatbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/pstatbar.py
new file mode 100644
index 0000000..4fda8fb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/pstatbar.py
@@ -0,0 +1,299 @@
+###############################################################################
+# Name: pstatbar.py #
+# Purpose: Custom statusbar with builtin progress indicator #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: ProgressStatusBar
+
+Custom StatusBar that has a builtin progress gauge to indicate busy status and
+progress of long running tasks in a window.
+
+The Progress Gauge is only shown when it is active. When shown it is shown in
+the far rightmost field of the StatusBar. The size of the progress Guage is
+also determined by the size of the right most field.When created the StatusBar
+will creates two fields by default, field 0 is expanding, field 1 is set as a
+small fixed field on the right. To change this behavior simply call SetFields
+after creating the bar to change it.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: pstatbar.py 66840 2011-02-03 21:05:28Z CJP $"
+__revision__ = "$Revision: 66840 $"
+
+__all__ = ["ProgressStatusBar",]
+
+#--------------------------------------------------------------------------#
+# Dependancies
+import wx
+
+#--------------------------------------------------------------------------#
+# Globals
+
+#--------------------------------------------------------------------------#
+class ProgressStatusBar(wx.StatusBar):
+ """Custom StatusBar with a built-in progress bar"""
+ def __init__(self, parent, id_=wx.ID_ANY,
+ style=wx.SB_FLAT,
+ name="ProgressStatusBar"):
+ """Creates a status bar that can hide and show a progressbar
+ in the far right section. The size of the progressbar is also
+ determined by the size of the right most section.
+ @param parent: Frame this status bar belongs to
+
+ """
+ super(ProgressStatusBar, self).__init__(parent, id_, style, name)
+
+ # Attributes
+ self._changed = False # position has changed ?
+ self.busy = False # Bar in busy mode ?
+ self.stop = False # Stop flag to stop progress from other threads
+ self.progress = 0 # Current progress value of the bar
+ self.range = 0 # Range of progress indicator
+ self.tmp = None # Temp for text that may be pushed when busy
+ self.timer = wx.Timer(self)
+ self.prog = wx.Gauge(self, style=wx.GA_HORIZONTAL)
+ self.prog.Hide()
+
+ # Layout
+ self.SetFieldsCount(2)
+ self.SetStatusWidths([-1, 155])
+
+ # Event Handlers
+ self.Bind(wx.EVT_IDLE, lambda evt: self.__Reposition())
+ self.Bind(wx.EVT_TIMER, self.OnTimer)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ def __del__(self):
+ """Make sure the timer is stopped
+ @postcondition: timer is cleaned up
+
+ """
+ if self.timer.IsRunning():
+ self.timer.Stop()
+
+ def __Reposition(self):
+ """Does the actual repositioning of progress bar
+ @postcondition: Progress bar is repostioned inside right most field
+
+ """
+ if self._changed:
+ rect = self.GetFieldRect(self.GetFieldsCount() - 1)
+ self.prog.SetPosition((rect.x + 2, rect.y + 2))
+ self.prog.SetSize((rect.width - 8, rect.height - 4))
+ self._changed = False
+
+ def _UpdateRange(self, range):
+ """Update the internal progress gauges range
+ @param range: int
+
+ """
+ self.range = range
+ try:
+ self.prog.SetRange(range)
+ except OverflowError:
+ # range too large, scale everything to 100
+ self.prog.SetRange(100)
+
+ def _UpdateValue(self, value):
+ """Update the internal progress gauges value
+ @param range: int
+
+ """
+ # Ensure value is within range
+ range = self.prog.GetRange()
+ if range != self.range: # need to scale value
+ value = int((float(value) / float(range)) * 100)
+ self.progress = value
+ self.prog.SetValue(value)
+
+ #---- Public Methods ----#
+
+ def Destroy(self):
+ """Destroy the control"""
+ if self.timer.IsRunning():
+ self.timer.Stop()
+ del self.timer
+ super(ProgressStatusBar, self).Destroy()
+
+ def DoStop(self):
+ """Stop any progress indication action and hide the bar"""
+ self.timer.Stop()
+ self.ShowProgress(False)
+ self.prog.SetValue(0) # Reset progress value
+ self.busy = False
+ self.stop = False
+
+ # Restore any status text that was sent while busy
+ if self.tmp is not None:
+ self.SetStatusText(self.tmp, self.GetFieldsCount() - 1)
+ self.tmp = None
+
+ def GetGauge(self):
+ """Return the wx.Gauge used by this window
+ @return: wx.Gauge
+
+ """
+ return self.prog
+
+ def GetProgress(self):
+ """Get the progress of the progress bar
+ @return: int
+
+ """
+ return self.prog.GetValue()
+
+ def GetRange(self):
+ """Get the what the range of the progress bar is
+ @return: int
+
+ """
+ return self.prog.GetRange()
+
+ def IsBusy(self):
+ """Is the progress indicator busy or not
+ @return: bool
+
+ """
+ return self.timer.IsRunning()
+
+ def OnSize(self, evt):
+ """Reposition progress bar on resize
+ @param evt: wx.EVT_SIZE
+
+ """
+ self.__Reposition()
+ self._changed = True
+ evt.Skip()
+
+ def OnTimer(self, evt):
+ """Update the progress bar while the timer is running
+ @param evt: wx.EVT_TIMER
+
+ """
+ # Check stop flag that can be set from non main thread
+ if self.stop:
+ self.DoStop()
+ return
+
+ if not self.prog.IsShown():
+ self.Stop()
+
+ if self.busy or self.progress < 0:
+ self.prog.Pulse()
+ else:
+ # Update the Range if it has changed
+ if self.range >= 0 and self.range != self.prog.GetRange():
+ self._UpdateRange(self.range)
+
+ # Update the progress value if it is less than the range
+ if self.progress <= self.range:
+ self._UpdateValue(self.progress)
+
+ def Run(self, rate=100):
+ """Start the bar's timer to check for updates to progress
+ @keyword rate: rate at which to check for updates in msec
+
+ """
+ if not self.timer.IsRunning():
+ self.timer.Start(rate)
+
+ def SetProgress(self, val):
+ """Set the controls internal progress value that is reflected in the
+ progress bar when the timer next updates. Be sure to call Start before
+ calling this method if you want the changes to be visible. This method
+ can be called from non gui threads.
+ @param val: int
+
+ """
+ self.progress = val
+ if val > 0 and wx.Thread_IsMain():
+ self._UpdateValue(val)
+
+ def SetRange(self, val):
+ """Set the what the range of the progress bar is. This method can safely
+ be called from non gui threads.
+ @param val: int
+
+ """
+ self.range = val
+ if val > 0 and wx.Thread_IsMain():
+ self._UpdateRange(val)
+
+ def ShowProgress(self, show=True):
+ """Manually show or hide the progress bar
+ @keyword show: bool
+
+ """
+ # If showing make sure bar is positioned properly
+ if show:
+ self.__Reposition()
+ self.prog.Show(show)
+ wx.GetApp().ProcessPendingEvents()
+
+ def SetStatusText(self, txt, number=0):
+ """Override wx.StatusBar method to prevent text from being
+ put in when the progress indicator is running. Any text that
+ comes when it is running is buffered to be displayed afterwords.
+ @param txt: Text to put on status bar
+ @keyword number: Section number to put text in
+
+ """
+ if number == self.GetFieldsCount() - 1 and self.IsBusy():
+ if self.tmp is None:
+ self.tmp = txt
+ else:
+ try:
+ super(ProgressStatusBar, self).SetStatusText(txt, number)
+ except wx.PyAssertionError:
+ pass
+
+ # Alias for SetStatusText
+ PushStatusText = SetStatusText
+
+ def Start(self, rate=100):
+ """Show and the progress indicator and start the timer
+ @keyword rate: rate to update progress bar in msec
+
+ """
+ self.__Reposition()
+ bfield = self.GetFieldsCount() - 1
+ self.tmp = self.GetStatusText(bfield)
+ # Clear the progress field so the text doesn't show behind
+ # the progress indicator.
+ super(ProgressStatusBar, self).SetStatusText(u'', bfield)
+ self.stop = False
+ self.ShowProgress(True)
+ self.Run(rate)
+
+ def StartBusy(self, rate=100):
+ """Show and start the progress indicator in pulse mode
+ @keyword rate: interval to pulse indicator at in msec
+
+ """
+ self.busy = True
+ self.Start(rate)
+
+ def Stop(self):
+ """Stop and hide the progress bar. This method may safely be called
+ from background threads.
+ @precondition: Bar is already running
+
+ """
+ if wx.Thread_IsMain():
+ self.DoStop()
+ else:
+ self.stop = True # Set flag from non main thread
+ self.progress = 0
+
+ def StopBusy(self):
+ """Stop and hide the progress indicator
+ @postcondition: Progress bar is hidden from view
+
+ """
+ self.busy = False
+ self.Stop()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/segmentbk.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/segmentbk.py
new file mode 100644
index 0000000..9612609
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/segmentbk.py
@@ -0,0 +1,438 @@
+###############################################################################
+# Name: segmentbk.py #
+# Purpose: SegmentBook Implementation #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Editra Control Library: SegmentBook
+
+A L{SegmentBook} is a Toolbook like class derived from a ControlBox and
+SegmentBar. Allows for a multi page control with Icons w/ optional text as
+page buttons.
+
++-----------------------------------------+
+| @^@ *> |
+| <-> /|D |
+| frog bird |
++-----------------------------------------+
+| |
+| Main Page Area |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
++-----------------------------------------+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: segmentbk.py 69065 2011-09-11 19:18:25Z CJP $"
+__revision__ = "$Revision: 69065 $"
+
+__all__ = ['SegmentBook', 'SegmentBookEvent', 'SEGBOOK_STYLE_DEFAULT',
+ 'SEGBOOK_STYLE_NO_DIVIDERS', 'SEGBOOK_STYLE_LABELS',
+ 'SEGBOOK_STYLE_LEFT', 'SEGBOOK_STYLE_RIGHT',
+ 'SEGBOOK_STYLE_TOP', 'SEGBOOK_STYLE_BOTTOM',
+ 'SEGBOOK_NAME_STR',
+ 'edEVT_SB_PAGE_CHANGING', 'EVT_SB_PAGE_CHANGING',
+ 'edEVT_SB_PAGE_CHANGED', 'EVT_SB_PAGE_CHANGED',
+ 'edEVT_SB_PAGE_CLOSED', 'EVT_SB_PAGE_CLOSED',
+ 'edEVT_SB_PAGE_CONTEXT_MENU', 'EVT_SB_PAGE_CONTEXT_MENU',
+ 'edEVT_SB_PAGE_CLOSING', 'EVT_SB_PAGE_CLOSING' ]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+# Local Imports
+import ctrlbox
+from eclutil import Freezer
+
+#-----------------------------------------------------------------------------#
+# Events
+edEVT_SB_PAGE_CHANGING = wx.NewEventType()
+EVT_SB_PAGE_CHANGING = wx.PyEventBinder(edEVT_SB_PAGE_CHANGING, 1)
+
+edEVT_SB_PAGE_CHANGED = wx.NewEventType()
+EVT_SB_PAGE_CHANGED = wx.PyEventBinder(edEVT_SB_PAGE_CHANGED, 1)
+
+edEVT_SB_PAGE_CLOSING = wx.NewEventType()
+EVT_SB_PAGE_CLOSING = wx.PyEventBinder(edEVT_SB_PAGE_CLOSING, 1)
+
+edEVT_SB_PAGE_CLOSED = wx.NewEventType()
+EVT_SB_PAGE_CLOSED = wx.PyEventBinder(edEVT_SB_PAGE_CLOSED, 1)
+
+edEVT_SB_PAGE_CONTEXT_MENU = wx.NewEventType()
+EVT_SB_PAGE_CONTEXT_MENU = wx.PyEventBinder(edEVT_SB_PAGE_CONTEXT_MENU, 1)
+class SegmentBookEvent(wx.NotebookEvent):
+ """SegmentBook event"""
+ def __init__(self, etype=wx.wxEVT_NULL, id=-1, sel=-1, old_sel=-1):
+ super(SegmentBookEvent, self).__init__(etype, id, sel, old_sel)
+
+#-----------------------------------------------------------------------------#
+# Global constants
+
+# Styles
+SEGBOOK_STYLE_NO_DIVIDERS = 1 # Don't put dividers between segments
+SEGBOOK_STYLE_LABELS = 2 # Use labels below the icons
+SEGBOOK_STYLE_TOP = 4 # Segments at top
+SEGBOOK_STYLE_BOTTOM = 8 # Segments at top
+SEGBOOK_STYLE_LEFT = 16 # Segments at top
+SEGBOOK_STYLE_RIGHT = 32 # Segments at top
+SEGBOOK_STYLE_DEFAULT = SEGBOOK_STYLE_TOP # Default Style
+
+# Misc
+SEGBOOK_NAME_STR = u"EditraSegmentBook"
+
+#-----------------------------------------------------------------------------#
+
+class SegmentBook(ctrlbox.ControlBox):
+ """Notebook Class"""
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=SEGBOOK_STYLE_DEFAULT,
+ name=SEGBOOK_NAME_STR):
+ """Initialize the SegmentBook"""
+ super(SegmentBook, self).__init__(parent, id, pos, size,
+ wx.TAB_TRAVERSAL|wx.NO_BORDER, name)
+
+ # Attributes
+ self._pages = list()
+ self._imglist = None
+ self._use_pylist = False
+ self._style = style
+
+ # Setup
+ bstyle = ctrlbox.CTRLBAR_STYLE_BORDER_BOTTOM
+
+ # Disable gradient on GTK due to coloring issues and having
+ # to deal with various themes.
+ if wx.Platform != '__WXGTK__':
+ bstyle |= ctrlbox.CTRLBAR_STYLE_GRADIENT
+
+ if style & SEGBOOK_STYLE_NO_DIVIDERS:
+ bstyle |= ctrlbox.CTRLBAR_STYLE_NO_DIVIDERS
+ if style & SEGBOOK_STYLE_LABELS:
+ bstyle |= ctrlbox.CTRLBAR_STYLE_LABELS
+ if style & SEGBOOK_STYLE_LEFT or style & SEGBOOK_STYLE_RIGHT:
+ bstyle |= ctrlbox.CTRLBAR_STYLE_VERTICAL
+
+ self._segbar = ctrlbox.SegmentBar(self, style=bstyle)
+ self.SetControlBar(self._segbar, self._GetSegBarPos())
+
+ # Event Handlers
+ self.Bind(ctrlbox.EVT_SEGMENT_SELECTED, self._OnSegmentSel)
+ self._segbar.Bind(wx.EVT_RIGHT_DOWN, self._OnRightDown)
+ self._segbar.Bind(ctrlbox.EVT_SEGMENT_CLOSE, self._OnSegClose)
+
+ def _GetSegBarPos(self):
+ pos = wx.TOP
+ if self._style & SEGBOOK_STYLE_LEFT:
+ pos = wx.LEFT
+ elif self._style & SEGBOOK_STYLE_RIGHT:
+ pos = wx.RIGHT
+ elif self._style & SEGBOOK_STYLE_BOTTOM:
+ pos = wx.BOTTOM
+ return pos
+
+ def _DoPageChange(self, psel, csel):
+ """Change the page and post events
+ @param psel: previous selection (int)
+ @param csel: current selection (int)
+
+ """
+ # Post page changing event
+ event = SegmentBookEvent(edEVT_SB_PAGE_CHANGING,
+ self.GetId(), csel, psel)
+ event.SetEventObject(self)
+ handler = self.GetEventHandler()
+ if not handler.ProcessEvent(event) or event.IsAllowed():
+ # Do the actual page change
+ with Freezer(self) as _tmp:
+ self.ChangePage(csel)
+
+ # Post page changed event
+ event.SetEventType(edEVT_SB_PAGE_CHANGED)
+ handler.ProcessEvent(event)
+ changed = True
+ else:
+ # Reset the segment selection
+ self._segbar.SetSelection(max(psel, 0))
+ changed = False
+ return changed
+
+ def _OnRightDown(self, evt):
+ """Handle right click events"""
+ pos = evt.GetPosition()
+ where, index = self._segbar.HitTest(pos)
+ print where, index
+ if where in (ctrlbox.SEGMENT_HT_SEG, ctrlbox.SEGMENT_HT_X_BTN):
+ if where == ctrlbox.SEGMENT_HT_SEG:
+ self._segbar.SetSelection(index)
+ changed = self._DoPageChange(self.GetSelection(), index)
+ if changed:
+ # Send Context Menu Event
+ event = SegmentBookEvent(edEVT_SB_PAGE_CONTEXT_MENU,
+ self.GetId())
+ event.SetSelection(index)
+ event.SetOldSelection(index)
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+ else:
+ # TODO: Handle other right clicks
+ pass
+
+ evt.Skip()
+
+ def _OnSegClose(self, evt):
+ """Handle clicks on segment close buttons"""
+ index = evt.GetPreviousSelection()
+ change = -1
+ segcnt = self._segbar.GetSegmentCount() - 1
+ if index == 0 and segcnt:
+ change = 1
+ elif index > 0 and segcnt > 1:
+ change = index - 1
+
+ if change != -1:
+ self._DoPageChange(index, change)
+
+ self._pages[index]['page'].Destroy()
+ del self._pages[index]
+
+ def _OnSegmentSel(self, evt):
+ """Change the page in the book"""
+ psel = evt.GetPreviousSelection()
+ csel = evt.GetCurrentSelection()
+ self._DoPageChange(psel, csel)
+
+ def AddPage(self, page, text, select=False, img_id=-1):
+ """Add a page to the notebook
+ @param page: wxWindow object
+ @param text: Page text
+ @keyword select: should the page be selected
+ @keyword img_id: Image to use
+
+ """
+ page.Hide()
+ self._pages.append(dict(page=page, img=img_id))
+ segbar = self.GetControlBar(self._GetSegBarPos())
+ if self._use_pylist:
+ bmp = self._imglist[img_id]
+ else:
+ bmp = self._imglist.GetBitmap(img_id)
+ segbar.AddSegment(wx.ID_ANY, bmp, text)
+ idx = len(self._pages) - 1
+
+ if select or idx == 0:
+ segbar.SetSelection(idx)
+ self._DoPageChange(segbar.GetSelection(), idx)
+
+ def ChangePage(self, index):
+ """Change the page to the given index"""
+ cpage = self._pages[index]['page']
+ page = self.ChangeWindow(cpage)
+ if page is not None:
+ page.Hide()
+ cpage.Show()
+ self.Layout()
+
+ def DeleteAllPages(self):
+ """Remove all pages from the control"""
+ for page in reversed(range(len(self._pages))):
+ self.DeletePage()
+
+ def DeletePage(self, index):
+ """Delete the page at the given index
+ @param index: int
+
+ """
+ cpage = self._segbar.GetSelection()
+ self._segbar.RemoveSegment(index)
+ npage = self._segbar.GetSelection()
+ self._DoPageChange(cpage, npage)
+
+ self._pages[index]['page'].Destroy()
+ del self._pages[index]
+
+ def CurrentPage(self):
+ """Get the currently selected page
+ @return: wxWindow or None
+
+ """
+ idx = self._segbar.GetSelection()
+ if idx != -1:
+ return self._pages[idx]['page']
+ else:
+ return None
+
+ def GetImageList(self):
+ """Get the notebooks image list
+ @return: wxImageList or None
+
+ """
+ return self._imglist
+
+ def GetPage(self, index):
+ """Get the page at the given index
+ @param index: int
+
+ """
+ return self._pages[index]['page']
+
+ def GetPageCount(self):
+ """Get the number of pages in the book
+ @return: int
+
+ """
+ return len(self._pages)
+
+ def GetPageImage(self, index):
+ """Get the image index of the current page
+ @param index: page index
+ @return: int
+
+ """
+ return self._pages[index]['img']
+
+ def SetPageCloseButton(self, index):
+ """Set the property of a page
+ @param index: Segment index
+
+ """
+ if wx.Platform != '__WXMAC__':
+ self._segbar.SetSegmentOption(index, ctrlbox.SEGBTN_OPT_CLOSEBTNR)
+ else:
+ self._segbar.SetSegmentOption(index, ctrlbox.SEGBTN_OPT_CLOSEBTNL)
+
+ def GetPageText(self, index):
+ """Get the text of the current page
+ @param index: page index
+ @return: string
+
+ """
+ return self._segbar.GetSegmentLabel(index)
+
+ def SetSegmentCanClose(self, index, can_close=True):
+ """Add a close button to the given segment
+ @param index: segment index
+ @keyword can_close: Enable/Disable
+
+ """
+ if not can_close:
+ opt = ctrlbox.SEGBTN_OPT_NONE
+
+ elif wx.Platform == '__WXMAC__':
+ opt = ctrlbox.SEGBTN_OPT_CLOSEBTNL
+ else:
+ opt = ctrlbox.SEGBTN_OPT_CLOSEBTNR
+ self._segbar.SetSegmentOption(index, opt)
+
+ def GetSelection(self):
+ """Get the current selection
+ @return: int
+
+ """
+ return self._segbar.GetSelection()
+
+ def GetSegmentBar(self):
+ """Get the segment bar used by this control
+ @return: SegmentBar
+
+ """
+ return self._segbar
+
+ def HasMultiplePages(self):
+ """Does the book have multiple pages
+ @return: bool
+
+ """
+ return bool(self.GetPageCount())
+
+ def HitTest(self, pt):
+ """Find if/where the given point is in the window
+ @param pt: wxPoint
+ @return: where, index
+
+ """
+ where, index = (SEGBOOK_NO_WHERE, -1)
+ index = self._segbar.GetIndexFromPosition(pt)
+ if index != wx.NOT_FOUND:
+ where = SEGBOOK_ON_SEGMENT
+
+ # TOOD check for clicks elsewhere on bar
+ return where, index
+
+ def InsertPage(self, index, page, text, select=False, image_id=-1):
+ """Insert a page a the given index
+ @param index: index to insert page at
+ @param page: page to add to book
+ @param text: page text
+ @keyword select: bool
+ @keyword image_id: image list index
+
+ """
+ raise NotImplementedError
+
+ def Refresh(self):
+ """Refresh the segmentbar
+ @todo: temporary HACK till rework of SegmentBar class image handling
+
+ """
+ segbar = self.GetSegmentBar()
+ for page in range(self.GetPageCount()):
+ idx = self.GetPageImage(page)
+ bmp = self._imglist[idx]
+ segbar.SetSegmentImage(page, bmp)
+ segbar.Refresh()
+ super(SegmentBook, self).Refresh()
+
+ def SetImageList(self, imglist):
+ """Set the notebooks image list
+ @param imglist: wxImageList
+
+ """
+ self._imglist = imglist
+
+ def SetPageImage(self, index, img_id):
+ """Set the image to use on the given page
+ @param index: page index
+ @param img_id: image list index
+
+ """
+ page = self._pages[index]
+ page['img'] = img_id
+ self._segbar.SetSegmentImage(self._imglst.GetBitmap(img_id))
+ self.Layout()
+
+ def SetPageText(self, index, text):
+ """Set the text to use on the given page
+ @param index: page index
+ @param text: string
+
+ """
+ self._segbar.SetSegmentLabel(index, text)
+
+ def SetSelection(self, index):
+ """Set the selected page
+ @param index: index of page to select
+
+ """
+ csel = self._segbar.GetSelection()
+ if csel != index:
+ self._segbar.SetSelection(index)
+ self._DoPageChange(csel, index)
+
+ def SetUsePyImageList(self, use_pylist):
+ """Set whether the control us using a regular python list for
+ storing images or a wxImageList.
+ @param use_pylist: bool
+
+ """
+ self._use_pylist = use_pylist
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/txtentry.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/txtentry.py
new file mode 100644
index 0000000..bd296be
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/txtentry.py
@@ -0,0 +1,96 @@
+###############################################################################
+# Name: txtentry.py #
+# Purpose: Text entry control base clases #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra Control Library: TextEntry
+
+Text entry base and helper classes.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: txtentry.py 67500 2011-04-15 22:51:55Z CJP $"
+__revision__ = "$Revision: 67500 $"
+
+__all__ = ["CommandEntryBase",]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+#-----------------------------------------------------------------------------#
+
+class CommandEntryBase(wx.SearchCtrl):
+ """Base single line text control with key event handling callbacks."""
+ def __init__(self, parent, id=wx.ID_ANY, value='', pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, validator=wx.DefaultValidator,
+ name="CommandEntryBase"):
+
+ clone = None
+ if validator != wx.DefaultValidator:
+ clone = validator.Clone()
+
+ super(CommandEntryBase, self).__init__(parent, id, value, pos,
+ size, style, validator, name)
+
+ # Attributes
+ self._txtctrl = None # For msw/gtk
+ self._enterhook = None
+
+ # Hide the search button and text by default
+ self.ShowSearchButton(False)
+ self.ShowCancelButton(False)
+ self.SetDescriptiveText(wx.EmptyString)
+
+ # MSW/GTK HACK need to bind directly to the text control component
+ if wx.Platform in ['__WXGTK__', '__WXMSW__']:
+ for child in self.GetChildren():
+ if isinstance(child, wx.TextCtrl):
+ if clone is not None:
+ child.SetValidator(clone)
+ self._txtctrl = child
+ child.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ child.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ break
+ else:
+ self._txtctrl = self
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+
+ # Event management
+ self.Bind(wx.EVT_TEXT_ENTER, self.OnEnter)
+
+ EnterCallback = property(lambda self: self._enterhook,
+ lambda self, cback: setattr(self, '_enterhook', cback))
+
+ def GetTextControl(self):
+ """Get the wx.TextCtrl window.
+ @note: only for msw/gtk
+
+ """
+ return self._txtctrl
+
+ def OnKeyDown(self, evt):
+ """Handle KeyDown events"""
+ evt.Skip()
+
+ def OnKeyUp(self, evt):
+ """Handle KeyUp events"""
+ evt.Skip()
+
+ def OnEnter(self, evt):
+ """Handle the Enter key event"""
+ if self.EnterCallback:
+ self.EnterCallback()
+ else:
+ evt.Skip()
+
+ def SetFocus(self):
+ """Set the focus and select the text in the field"""
+ super(CommandEntryBase, self).SetFocus()
+ self.SelectAll()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_art.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_art.py
new file mode 100644
index 0000000..00aef7a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_art.py
@@ -0,0 +1,148 @@
+###############################################################################
+# Name: ed_art.py #
+# Purpose: Provides artwork for Editra based on object ids #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides and ArtProvider class that works off of object ID's to return an
+associated art resource. The provider works hand in hand with Editra's theme
+framework that allows for themes to be provided as plugins that act as the
+resource providers for the ArtProvider.
+
+@summary: Editra's ArtProvider, supplies icons based off of object ids
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: ed_art.py 66815 2011-01-29 20:46:20Z CJP $"
+__revision__ = "$Revision: 66815 $"
+
+#--------------------------------------------------------------------------#
+# Dependancies
+import wx
+import ed_glob
+from profiler import Profile_Get
+import syntax.syntax as syntax
+import ed_theme
+
+#--------------------------------------------------------------------------#
+
+# Map for default system/wx provided graphic resources.
+# For toolbar ones fall back to ones provided by the default Tango theme
+DEFAULT = {
+ ed_glob.ID_ADD_BM : wx.ART_ADD_BOOKMARK,
+ ed_glob.ID_BIN_FILE : wx.ART_EXECUTABLE_FILE,
+ ed_glob.ID_CDROM : wx.ART_CDROM,
+ ed_glob.ID_COPY : wx.ART_COPY,
+ ed_glob.ID_CUT : wx.ART_CUT,
+ ed_glob.ID_DELETE : wx.ART_DELETE,
+ ed_glob.ID_DEL_BM : wx.ART_DEL_BOOKMARK,
+# ed_glob.ID_DOCPROP : wx.ART_NORMAL_FILE, # Bad match
+ ed_glob.ID_DOWN : wx.ART_GO_DOWN,
+ ed_glob.ID_EXIT : wx.ART_QUIT,
+ ed_glob.ID_FILE : wx.ART_NORMAL_FILE,
+ ed_glob.ID_FIND : wx.ART_FIND,
+ ed_glob.ID_FIND_REPLACE : wx.ART_FIND_AND_REPLACE,
+ ed_glob.ID_FLOPPY : wx.ART_FLOPPY,
+ ed_glob.ID_FOLDER : wx.ART_FOLDER,
+ ed_glob.ID_HARDDISK : wx.ART_HARDDISK,
+ ed_glob.ID_NEW : wx.ART_NEW,
+ ed_glob.ID_NEXT_MARK : wx.ART_GO_FORWARD,
+ ed_glob.ID_OPEN : wx.ART_FILE_OPEN,
+# ed_glob.ID_PACKAGE : wx.ART_HARDDISK, # Poor match
+ ed_glob.ID_PASTE : wx.ART_PASTE,
+# ed_glob.ID_PREF : wx.ART_EXECUTABLE_FILE, # Bad match
+ ed_glob.ID_PRE_MARK : wx.ART_GO_BACK,
+ ed_glob.ID_PRINT : wx.ART_PRINT,
+ ed_glob.ID_REDO : wx.ART_REDO,
+ ed_glob.ID_SAVE : wx.ART_FILE_SAVE,
+ ed_glob.ID_SAVEAS : wx.ART_FILE_SAVE_AS,
+ ed_glob.ID_STOP : wx.ART_ERROR,
+# ed_glob.ID_THEME : wx.ART_INFORMATION, # Bad match
+ ed_glob.ID_UNDO : wx.ART_UNDO,
+ ed_glob.ID_UP : wx.ART_GO_UP,
+ ed_glob.ID_USB : wx.ART_REMOVABLE,
+# ed_glob.ID_WEB : wx.ART_HARDDISK # Bad match
+}
+
+#--------------------------------------------------------------------------#
+
+class EditraArt(wx.ArtProvider):
+ """Editras Art Provider. Provides the mimetype images and loads any custom
+ user defined icon sets as well. Editra theme specific icons are looked up
+ by passing an objects related id as a string to this providers CreateBitmap
+ function for it to talk to the theme resource provider. If the id is not
+ a defined object ID it is simply ignored or passed to the the next
+ ArtProvider in the chain to handle.
+
+ """
+ def __init__(self):
+ """Initializes Editra's art provider"""
+ super(EditraArt, self).__init__()
+ self._library = ed_theme.BitmapProvider(wx.GetApp().GetPluginManager())
+
+ def CreateBitmap(self, art_id, client, size):
+ """Lookup and return an associated bitmap from the current theme if
+ one exisists. If the art_id is not a theme defined id and is a wx
+ defined art resource then it is passed to the next ArtProvider in the
+ stack to evaluate.
+
+ @return: Requested bitmap from current theme if one exists
+ @rtype: wx.Bitmap
+
+ """
+ # All art ids we can handle can be converted to int
+ try:
+ art_id = int(art_id)
+ except ValueError:
+ return wx.NullBitmap
+
+ # If using default theme let the system provide the art when possible
+ # this is mostly for GTK where there is a native art provider that can
+ # provide theme icons.
+ if Profile_Get('ICONS', 'str').lower() == u'default' and art_id in DEFAULT:
+ if client == wx.ART_MENU:
+ size = (16, 16)
+ elif client == wx.ART_TOOLBAR:
+ size = Profile_Get('ICON_SZ', default=(24, 24))
+ return wx.ArtProvider.GetBitmap(DEFAULT[art_id], client, size)
+
+ # If a custom theme is set fetch the requested bitmap
+ bmp = self._library.GetBitmap(art_id, client)
+ if not bmp.IsNull() and bmp.IsOk():
+ # Dont scale toolbar icons on wxMac as the toolbar handles it
+ # internally and produces much nicer results.
+ if client == wx.ART_TOOLBAR and not wx.Platform == '__WXMAC__':
+ if size == wx.DefaultSize:
+ size = Profile_Get('ICON_SZ', default=(24, 24))
+
+ img_sz = bmp.GetSize()
+ if size[0] < img_sz[0]:
+ img = wx.ImageFromBitmap(bmp)
+ img.Rescale(size[0], size[1], wx.IMAGE_QUALITY_HIGH)
+ bmp = wx.BitmapFromImage(img)
+
+ elif client == wx.ART_MENU and bmp.GetSize() != (16, 16):
+ img = wx.ImageFromBitmap(bmp)
+ img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH)
+ bmp = wx.BitmapFromImage(img)
+ elif client == wx.ART_TOOLBAR:
+ # Dont fail on a toolbar icon return a warning icon when nothing is
+ # found in the bitmap provider.
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_WARNING, client, size)
+ elif art_id in syntax.SYNTAX_IDS:
+ # Dont fail when requesting mime type icons, fallback to the system
+ # icon for a normal file in this case.
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE,
+ wx.ART_MENU, (16, 16))
+
+ if bmp.IsOk() and not bmp.IsNull():
+ return bmp
+
+ # All failed so return a Null
+ return wx.NullBitmap
+
+#-----------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basestc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basestc.py
new file mode 100644
index 0000000..029f30e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basestc.py
@@ -0,0 +1,1337 @@
+###############################################################################
+# Name: ed_basestc.py #
+# Purpose: Editra's base StyledTextCtrl. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+The EditraBaseStc is the base StyledTextCtrl that provides automatic styling and
+syntax highlighting of all supported filetypes.
+
+@summary: Editra's base styled text ctrl.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_basestc.py 73711 2013-03-23 14:19:01Z CJP $"
+__revision__ = "$Revision: 73711 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc
+
+# Editra Imports
+import ed_glob
+import ed_style
+import eclib
+import ebmlib
+import ed_msg
+import ed_txt
+from syntax import syntax
+from syntax import synglob
+import autocomp
+from extern import vertedit
+from profiler import Profile_Get
+import plugin
+import iface
+import util
+import ed_marker
+
+#-----------------------------------------------------------------------------#
+
+# Margins
+MARK_MARGIN = 0
+NUM_MARGIN = 1
+FOLD_MARGIN = 2
+
+# Markers (3rd party)
+MARKER_VERT_EDIT = ed_marker.NewMarkerId()
+
+# Key code additions
+ALT_SHIFT = wx.stc.STC_SCMOD_ALT|wx.stc.STC_SCMOD_SHIFT
+CTRL_SHIFT = wx.stc.STC_SCMOD_CTRL|wx.stc.STC_SCMOD_SHIFT
+
+#-----------------------------------------------------------------------------#
+
+class EditraBaseStc(wx.stc.StyledTextCtrl, ed_style.StyleMgr):
+ """Base StyledTextCtrl that provides all the base code editing
+ functionality.
+
+ """
+ ED_STC_MASK_MARKERS = ~wx.stc.STC_MASK_FOLDERS
+ def __init__(self, parent, id_=wx.ID_ANY,
+ pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
+ wx.stc.StyledTextCtrl.__init__(self, parent, id_, pos, size, style)
+ ed_style.StyleMgr.__init__(self, self.GetStyleSheet())
+
+ # Attributes
+ self.file = ed_txt.EdFile()
+ self._code = dict(compsvc=autocomp.AutoCompService.GetCompleter(self),
+ synmgr=syntax.SyntaxMgr(ed_glob.CONFIG['CACHE_DIR']),
+ keywords=[ ' ' ],
+ comment=list(),
+ clexer=None, # Container lexer method
+ indenter=None, # Auto indenter
+ lang_id=0) # Language ID from syntax module
+
+ self.vert_edit = vertedit.VertEdit(self, markerNumber=MARKER_VERT_EDIT)
+ self._line_num = True # Show line numbers
+ self._last_cwidth = 1 # one pixel
+
+ # Set Up Margins
+ ## Outer Left Margin Bookmarks
+ self.SetMarginType(MARK_MARGIN, wx.stc.STC_MARGIN_SYMBOL)
+ self.SetMarginMask(MARK_MARGIN, EditraBaseStc.ED_STC_MASK_MARKERS)
+ self.SetMarginSensitive(MARK_MARGIN, True)
+ self.SetMarginWidth(MARK_MARGIN, 16)
+
+ ## Middle Left Margin Line Number Indication
+ self.SetMarginType(NUM_MARGIN, wx.stc.STC_MARGIN_NUMBER)
+ self.SetMarginMask(NUM_MARGIN, 0)
+
+ ## Inner Left Margin Setup Folders
+ self.SetMarginType(FOLD_MARGIN, wx.stc.STC_MARGIN_SYMBOL)
+ self.SetMarginMask(FOLD_MARGIN, wx.stc.STC_MASK_FOLDERS)
+ self.SetMarginSensitive(FOLD_MARGIN, True)
+
+ # Set Mac specific keybindings
+ if wx.Platform == '__WXMAC__':
+ for keys in _GetMacKeyBindings():
+ self.CmdKeyAssign(*keys)
+
+ # Set default EOL format
+ if wx.Platform != '__WXMSW__':
+ self.SetEOLMode(wx.stc.STC_EOL_LF)
+
+ # Setup Auto-comp images
+ # TODO: should be called on theme change messages
+ self.RegisterImages()
+
+ # Event Handlers
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+ self.Bind(wx.stc.EVT_STC_CHANGE, self.OnChanged)
+ self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModified)
+ self.Bind(wx.stc.EVT_STC_AUTOCOMP_SELECTION, self.OnAutoCompSel)
+
+ def OnDestroy(self, evt):
+ if evt.GetId() == self.GetId():
+ # Cleanup the file object callbacks
+ self.file.RemoveModifiedCallback(self.FireModified)
+ self.file.CleanUp()
+ evt.Skip()
+
+ #---- Public Methods ----#
+
+ # General marker api
+ def AddMarker(self, marker, line=-1):
+ """Add a bookmark and return its handle
+ @param marker: ed_marker.Marker instance
+ @keyword line: if < 0 bookmark will be added to current line
+
+ """
+ assert isinstance(marker, ed_marker.Marker)
+ if line < 0:
+ line = self.GetCurrentLine()
+ marker.Set(self, line)
+ return marker.Handle
+
+ def RemoveMarker(self, marker, line):
+ """Remove the book mark from the given line
+ @param marker: ed_marker.Marker instance
+ @param line: int
+
+ """
+ assert isinstance(marker, ed_marker.Marker)
+ marker.Set(self, line, delete=True)
+
+ def RemoveAllMarkers(self, marker):
+ """Remove all the bookmarks in the buffer
+ @param marker: ed_marker.Marker instance
+
+ """
+ assert isinstance(marker, ed_marker.Marker)
+ marker.DeleteAll(self)
+
+ #-- Breakpoint marker api --#
+ def DeleteAllBreakpoints(self):
+ """Delete all the breakpoints in the buffer"""
+ ed_marker.Breakpoint().DeleteAll(self)
+ ed_marker.BreakpointDisabled().DeleteAll(self)
+ ed_marker.BreakpointStep().DeleteAll(self)
+
+ def DeleteBreakpoint(self, line):
+ """Delete the breakpoint from the given line"""
+ ed_marker.Breakpoint().Set(self, line, delete=True)
+ ed_marker.BreakpointDisabled().Set(self, line, delete=True)
+
+ def _SetBreakpoint(self, mobj, line=-1):
+ """Set the breakpoint state
+ @param mtype: Marker object
+ @return: int (-1 if already set)
+
+ """
+ handle = -1
+ if line < 0:
+ line = self.GetCurrentLine()
+ if not mobj.IsSet(self, line):
+ # Clear other set breakpoint marker states on same line
+ ed_marker.Breakpoint().Set(self, line, delete=True)
+ ed_marker.BreakpointDisabled().Set(self, line, delete=True)
+ mobj.Set(self, line, delete=False)
+ handle = mobj.Handle
+ return handle
+
+ def SetBreakpoint(self, line=-1, disabled=False):
+ """Set a breakpoint marker on the given line
+ @keyword line: line number
+ @keyword disabled: bool
+ @return: breakpoint handle
+
+ """
+ if not disabled:
+ handle = self._SetBreakpoint(ed_marker.Breakpoint(), line)
+ else:
+ handle = self._SetBreakpoint(ed_marker.BreakpointDisabled(), line)
+ return handle
+
+ def ShowStepMarker(self, line=-1, show=True):
+ """Show the step (arrow) marker to the given line."""
+ if line < 0:
+ line = self.GetCurrentLine()
+ mark = ed_marker.BreakpointStep()
+ if show:
+ mark.Set(self, line, delete=False)
+ else:
+ mark.DeleteAll(self)
+
+ def AddLine(self, before=False, indent=False):
+ """Add a new line to the document
+ @keyword before: whether to add the line before current pos or not
+ @keyword indent: autoindent the new line
+ @postcondition: a new line is added to the document
+
+ """
+ if before:
+ self.LineUp()
+
+ self.LineEnd()
+
+ if indent:
+ self.AutoIndent()
+ else:
+ self.InsertText(self.GetCurrentPos(), self.GetEOLChar())
+ self.LineDown()
+
+ def AutoIndent(self):
+ """Indent from the current position to match the indentation
+ of the previous line. Unless the current file type has registered
+ a custom AutoIndenter in which case it will implement its own
+ behavior.
+
+ """
+ cpos = self.GetCurrentPos()
+
+ # Check if a special purpose indenter has been registered
+ if self._code['indenter'] is not None:
+ self.BeginUndoAction()
+ self._code['indenter'](self, cpos, self.GetIndentChar())
+ self.EndUndoAction()
+ else:
+ # Default Indenter
+ line = self.GetCurrentLine()
+ text = self.GetTextRange(self.PositionFromLine(line), cpos)
+ if text.strip() == u'':
+ self.AddText(self.GetEOLChar() + text)
+ self.EnsureCaretVisible()
+ return
+ indent = self.GetLineIndentation(line)
+ i_space = indent / self.GetTabWidth()
+ ndent = self.GetEOLChar() + self.GetIndentChar() * i_space
+ txt = ndent + ((indent - (self.GetTabWidth() * i_space)) * u' ')
+ self.AddText(txt)
+
+ self.EnsureCaretVisible()
+
+ def BackTab(self):
+ """Unindent or remove excess whitespace to left of cursor"""
+ sel = self.GetSelection()
+ if sel[0] == sel[1]:
+ # There is no selection
+ cpos = self.GetCurrentPos()
+ cline = self.GetCurrentLine()
+ cipos = self.GetLineIndentPosition(cline)
+ if cpos <= cipos:
+ # In indentation so simply backtab
+ super(EditraBaseStc, self).BackTab()
+ else:
+ # In middle of line somewhere
+ text = self.GetLine(cline)
+ column = max(0, self.GetColumn(cpos) - 1)
+ if len(text) > column and text[column].isspace():
+
+ # Find the end of the whitespace
+ end = column
+ while end < len(text) and \
+ text[end].isspace() and \
+ text[end] not in '\r\n':
+ end += 1
+
+ # Find the start of the whitespace
+ end -= 1
+ start = end
+ while end > 0 and text[start].isspace():
+ start -= 1
+
+ diff = end - start
+ if diff > 1:
+ # There is space to compress
+ isize = self.GetIndent()
+ if isize < diff:
+ # More space than indent to remove
+ repeat = isize
+ else:
+ # Less than one indent width to remove
+ repeat = end - (start + 1)
+
+ # Update the control
+ self.BeginUndoAction()
+ self.SetCurrentPos(cpos + (end - column))
+ for x in range(repeat):
+ self.DeleteBack()
+ self.EndUndoAction()
+
+ else:
+ # There is a selection
+ super(EditraBaseStc, self).BackTab()
+
+ def SetBlockCaret(self):
+ """Change caret style to block"""
+ if hasattr(self, 'SetCaretStyle'): # wxPython 2.9 or greater
+ self.SetCaretStyle(wx.stc.STC_CARETSTYLE_BLOCK)
+ else:
+ # Alternatively, just make the caret a bit thicker!
+ # best we can do on 2.8
+ self.SetCaretWidth(3)
+
+ def SetLineCaret(self):
+ """Change caret style to line"""
+ if hasattr(self, 'SetCaretStyle'):
+ self.SetCaretStyle(wx.stc.STC_CARETSTYLE_LINE)
+ else:
+ pwidth = Profile_Get('CARETWIDTH', default=1)
+ self.SetCaretWidth(pwidth)
+
+ def BraceBadLight(self, pos):
+ """Highlight the character at the given position
+ @param pos: position of character to highlight with STC_STYLE_BRACEBAD
+
+ """
+ # Check if we are still alive or not, as this may be called
+ # after we have been deleted.
+ if self:
+ super(EditraBaseStc, self).BraceBadLight(pos)
+
+ def BraceHighlight(self, pos1, pos2):
+ """Highlight characters at pos1 and pos2
+ @param pos1: position of char 1
+ @param pos2: position of char 2
+
+ """
+ # Check if we are still alive or not, as this may be called
+ # after we have been deleted.
+ if self:
+ super(EditraBaseStc, self).BraceHighlight(pos1, pos2)
+
+ def CanCopy(self):
+ """Check if copy/cut is possible"""
+ return self.HasSelection()
+
+ CanCut = CanCopy
+
+ def Comment(self, start, end, uncomment=False):
+ """(Un)Comments a line or a selected block of text
+ in a document.
+ @param start: beginning line (int)
+ @param end: end line (int)
+ @keyword uncomment: uncomment selection
+
+ """
+ if len(self._code['comment']):
+ sel = self.GetSelection()
+ c_start = self._code['comment'][0]
+ c_end = u''
+ if len(self._code['comment']) > 1:
+ c_end = self._code['comment'][1]
+
+ # Modify the selected line(s)
+ self.BeginUndoAction()
+ try:
+ nchars = 0
+ lines = range(start, end+1)
+ lines.reverse()
+ for line_num in lines:
+ lstart = self.PositionFromLine(line_num)
+ lend = self.GetLineEndPosition(line_num)
+ text = self.GetTextRange(lstart, lend)
+ tmp = text.strip()
+ if len(tmp):
+ if uncomment:
+ if tmp.startswith(c_start):
+ text = text.replace(c_start, u'', 1)
+ if c_end and tmp.endswith(c_end):
+ text = text.replace(c_end, u'', 1)
+ nchars = nchars - len(c_start + c_end)
+ else:
+ text = c_start + text + c_end
+ nchars = nchars + len(c_start + c_end)
+
+ self.SetTargetStart(lstart)
+ self.SetTargetEnd(lend)
+ self.ReplaceTarget(text)
+ finally:
+ self.EndUndoAction()
+ if sel[0] != sel[1]:
+ self.SetSelection(sel[0], sel[1] + nchars)
+ else:
+ if len(self._code['comment']) > 1:
+ nchars = nchars - len(self._code['comment'][1])
+ self.GotoPos(sel[0] + nchars)
+
+ def ConfigureAutoComp(self):
+ """Sets up the Autocompleter, the autocompleter
+ configuration depends on the currently set lexer
+ @postcondition: autocomp is configured
+
+ """
+ self.AutoCompSetAutoHide(False)
+ self.InitCompleter()
+ self.AutoCompSetChooseSingle(self._code['compsvc'].GetChooseSingle())
+ self.AutoCompSetIgnoreCase(not self._code['compsvc'].GetCaseSensitive())
+ self.AutoCompStops(self._code['compsvc'].GetAutoCompStops())
+ # TODO: come back to this it can cause some annoying behavior where
+ # it automatically completes strings that you don't want to be
+ # inserted in the buffer. (i.e typing self._value will bring up
+ # the autocomp list but if self._value is not in the list and you
+ # hit space it will automatically insert something from the list.)
+# self.AutoCompSetFillUps(self._code['compsvc'].GetAutoCompFillups())
+
+ def ConfigureLexer(self, file_ext):
+ """Sets Lexer and Lexer Keywords for the specified file extension
+ @param file_ext: a file extension to configure the lexer from
+
+ """
+ syn_data = self._code['synmgr'].GetSyntaxData(file_ext)
+
+ # Set the ID of the selected lexer
+ self._code['lang_id'] = syn_data.LangId
+
+ lexer = syn_data.Lexer
+ # Check for special cases
+ # TODO: add fetch method to check if container lexer requires extra
+ # style bytes beyond the default 5.
+ if lexer in [ wx.stc.STC_LEX_HTML, wx.stc.STC_LEX_XML]:
+ self.SetStyleBits(7)
+ elif lexer == wx.stc.STC_LEX_NULL:
+ self.SetStyleBits(5)
+ self.SetLexer(lexer)
+ self.ClearDocumentStyle()
+ self.UpdateBaseStyles()
+ return True
+ else:
+ self.SetStyleBits(5)
+
+ # Set Lexer
+ self.SetLexer(lexer)
+ # Set Keywords
+ self.SetKeyWords(syn_data.Keywords)
+ # Set Lexer/Syntax Specifications
+ self.SetSyntax(syn_data.SyntaxSpec)
+ # Set Extra Properties
+ self.SetProperties(syn_data.Properties)
+ # Set Comment Pattern
+ self._code['comment'] = syn_data.CommentPattern
+
+ # Get Extension Features
+ clexer = syn_data.GetFeature(synglob.FEATURE_STYLETEXT)
+ indenter = syn_data.GetFeature(synglob.FEATURE_AUTOINDENT)
+
+ # Set the Container Lexer Method
+ self._code['clexer'] = clexer
+ # Auto-indenter function
+ self._code['indenter'] = indenter
+
+ def DefineMarkers(self):
+ """Defines the folder and bookmark icons for this control
+ @postcondition: all margin markers are defined
+
+ """
+ # Get the colours for the various markers
+ style = self.GetItemByName('foldmargin_style')
+ back = style.GetFore()
+ rgb = eclib.HexToRGB(back[1:])
+ back = wx.Colour(red=rgb[0], green=rgb[1], blue=rgb[2])
+
+ fore = style.GetBack()
+ rgb = eclib.HexToRGB(fore[1:])
+ fore = wx.Colour(red=rgb[0], green=rgb[1], blue=rgb[2])
+
+ # Buffer background highlight
+ caret_line = self.GetItemByName('caret_line').GetBack()
+ rgb = eclib.HexToRGB(caret_line[1:])
+ clback = wx.Colour(*rgb)
+
+ # Code Folding markers
+ folder = ed_marker.FoldMarker()
+ folder.Foreground = fore
+ folder.Background = back
+ folder.RegisterWithStc(self)
+
+ # Bookmarks
+ ed_marker.Bookmark().RegisterWithStc(self)
+
+ # Breakpoints
+ ed_marker.Breakpoint().RegisterWithStc(self)
+ ed_marker.BreakpointDisabled().RegisterWithStc(self)
+ step = ed_marker.BreakpointStep()
+ step.Background = clback
+ step.RegisterWithStc(self)
+ ed_marker.StackMarker().RegisterWithStc(self)
+
+ # Other markers
+ errmk = ed_marker.ErrorMarker()
+ errsty = self.GetItemByName('error_style')
+ rgb = eclib.HexToRGB(errsty.GetBack()[1:])
+ errmk.Background = wx.Colour(*rgb)
+ rgb = eclib.HexToRGB(errsty.GetFore()[1:])
+ errmk.Foreground = wx.Colour(*rgb)
+ errmk.RegisterWithStc(self)
+ # Lint Marker
+ ed_marker.LintMarker().RegisterWithStc(self)
+ ed_marker.LintMarkerWarning().RegisterWithStc(self)
+ ed_marker.LintMarkerError().RegisterWithStc(self)
+
+ def DoZoom(self, mode):
+ """Zoom control in or out
+ @param mode: either zoom in or out
+
+ """
+ id_type = mode
+ zoomlevel = self.GetZoom()
+ if id_type == ed_glob.ID_ZOOM_OUT:
+ if zoomlevel > -9:
+ self.ZoomOut()
+ elif id_type == ed_glob.ID_ZOOM_IN:
+ if zoomlevel < 19:
+ self.ZoomIn()
+ else:
+ self.SetZoom(0)
+ return self.GetZoom()
+
+ def EnableLineNumbers(self, enable=True):
+ """Enable/Disable line number margin
+ @keyword enable: bool
+
+ """
+ if enable:
+ self.SetMarginWidth(NUM_MARGIN, 30)
+ else:
+ self.SetMarginWidth(NUM_MARGIN, 0)
+ self._line_num = enable
+
+ def FindChar(self, char, repeat=1, reverse=False, extra_offset=0):
+ """Find the position of the next (ith) 'char' character
+ on the current line and move caret to it
+
+ @note: used by vim motions for finding a character on a line (f,F,t,T)
+ @param char: the character to be found
+ @keyword repeat: how many times to repeat the search
+ @keyword reverse: whether to search backwards
+ @keyword extra_offset: extra offset to be applied to the movement
+
+ """
+ text, pos = self.GetCurLine()
+ oldpos = pos
+ if not reverse:
+ # search forward
+ for i in range(repeat):
+ pos = text.find(char, pos+1)
+ if pos == -1:
+ return
+ else:
+ # search backward
+ for i in range(repeat):
+ pos = text.rfind(char, 0, pos)
+ if pos == -1:
+ return
+
+ newpos = pos + extra_offset
+ if newpos in range(len(text)):
+ self.MoveCaretPos(newpos - oldpos)
+
+ @property
+ def File(self):
+ """Reference to this buffers file object"""
+ return self.file
+
+ def FindLexer(self, set_ext=u''):
+ """Sets Text Controls Lexer Based on File Extension
+ @param set_ext: explicit extension to use in search
+ @postcondition: lexer is configured for file
+
+ """
+ if set_ext != u'':
+ ext = set_ext.lower()
+ else:
+ ext = self.file.GetExtension().lower()
+
+ if ext == u'':
+ fname = self.GetFileName()
+ ext = ebmlib.GetFileName(fname).lower()
+
+ self.ClearDocumentStyle()
+
+ # Configure Lexer from File Extension
+ self.ConfigureLexer(ext)
+
+ # If syntax auto detection fails from file extension try to
+ # see if there is an interpreter line that can be parsed.
+ if self.GetLexer() == wx.stc.STC_LEX_NULL:
+ interp = self.GetLine(0)
+ if interp != wx.EmptyString:
+ interp = interp.split(u"/")[-1]
+ interp = interp.strip().split()
+ if len(interp) and interp[-1][0] != u"-":
+ interp = interp[-1]
+ elif len(interp):
+ interp = interp[0]
+ else:
+ interp = u''
+ # TODO: should check user config to ensure the explict
+ # extension is still associated with the expected
+ # file type.
+ ex_map = { "python" : "py", "wish" : "tcl", "ruby" : "rb",
+ "bash" : "sh", "csh" : "csh", "perl" : "pl",
+ "ksh" : "ksh", "php" : "php", "booi" : "boo",
+ "pike" : "pike"}
+ self.ConfigureLexer(ex_map.get(interp, interp))
+ self.Colourise(0, -1)
+
+ def FireModified(self):
+ """Fire a modified event"""
+ self.OnChanged(wx.stc.StyledTextEvent(wx.stc.wxEVT_STC_CHANGE,
+ self.GetId()))
+
+ def GetCommandStr(self, line=None, col=None):
+ """Gets the command string to the left of the autocomp
+ activation character.
+ @keyword line: optional if None current cursor position used
+ @keyword col: optional if None current cursor position used
+ @return: the command string to the left of the autocomp char
+
+ """
+ if None in (line, col):
+ # NOTE: the column position returned by GetCurLine is not correct
+ # for multibyte characters.
+ line, col = self.GetCurLine()
+ col = self.GetColumn(self.GetCurrentPos())
+ cmd = self._code['compsvc'].GetCommandString(self, line, col)
+ return cmd
+
+ def GetCommentChars(self):
+ """Return the list of characters used to comment a string in the
+ current language.
+ @return: list of strings
+
+ """
+ return self._code['comment']
+
+ def GetCompleter(self):
+ """Get this buffers completer object
+ @return: Completer
+
+ """
+ return self._code['compsvc']
+
+ def GetDocument(self):
+ """Return a reference to the document object represented in this buffer.
+ @return: EdFile
+ @see: L{ed_txt.EdFile}
+
+ """
+ return self.file
+
+ def GetEOLChar(self):
+ """Gets the eol character used in document
+ @return: the character used for eol in this document
+
+ """
+ m_id = self.GetEOLMode()
+ if m_id == wx.stc.STC_EOL_CR:
+ return u'\r'
+ elif m_id == wx.stc.STC_EOL_CRLF:
+ return u'\r\n'
+ else:
+ return u'\n'
+
+ def GetFileName(self):
+ """Returns the full path name of the current file
+ @return: full path name of document
+
+ """
+ return self.file.GetPath()
+
+ def GetIndentChar(self):
+ """Gets the indentation char used in document
+ @return: indentation char used either space or tab
+
+ """
+ if self.GetUseTabs():
+ return u'\t'
+ else:
+ return u' ' * self.GetIndent()
+
+ def GetKeywords(self):
+ """Get the keyword set for the current document.
+ @return: list of strings
+
+ """
+ return self._code['keywords']
+
+ def GetLangId(self):
+ """Returns the language identifier of this control
+ @return: language identifier of document
+
+ """
+ return self._code['lang_id']
+
+ def GetModTime(self):
+ """Get the value of the buffers file last modtime"""
+ return self.file.ModTime
+
+ def GetPos(self):
+ """Update Line/Column information
+ @return: tuple (line, column)
+
+ """
+ return (self.GetCurrentLine() + 1, self.GetColumn(self.GetCurrentPos()))
+
+ GetRange = wx.stc.StyledTextCtrl.GetTextRange
+
+ def GetWordFromPosition(self, pos):
+ """Get the word at the given position
+ @param pos: int
+ @return: (string, int_start, int_end)
+
+ """
+ end = self.WordEndPosition(pos, True)
+ start = self.WordStartPosition(pos, True)
+ word = self.GetTextRange(start, end)
+ return (word, start, end)
+
+ def IsColumnMode(self):
+ """Is the buffer in column edit mode
+ @return: bool
+
+ """
+ return self.VertEdit.Enabled
+
+ def IsComment(self, pos):
+ """Is the given position in a comment region of the current buffer
+ @param pos: int position in buffer
+ @return: bool
+
+ """
+ pos = max(0, pos-1)
+ return 'comment' in self.FindTagById(self.GetStyleAt(pos))
+
+ def IsString(self, pos):
+ """Is the given position in a string region of the current buffer
+ @param pos: int position in buffer
+ @return: bool
+
+ """
+ style = self.GetStyleAt(pos)
+ return self.FindTagById(style) in ('string_style', 'char_style')
+
+ def IsNonCode(self, pos):
+ """Is the passed in position in a non code region
+ @param pos: buffer position
+ @return: bool
+
+ """
+ return self.IsComment(pos) or self.IsString(pos)
+
+ def HasMarker(self, line, marker):
+ """Check if the given line has the given marker set
+ @param line: line number
+ @param marker: marker id
+
+ """
+ mask = self.MarkerGet(line)
+ return bool(1<<marker & mask)
+
+ def HasSelection(self):
+ """Check if there is a selection in the buffer
+ @return: bool
+
+ """
+ sel = super(EditraBaseStc, self).GetSelection()
+ return sel[0] != sel[1]
+
+ def HasMultilineSelection(self):
+ """Is the selection over multiple lines?
+ @return: bool
+
+ """
+ bMulti = False
+ sel = super(EditraBaseStc, self).GetSelection()
+ if sel[0] != sel[1]:
+ sline = self.LineFromPosition(sel[0])
+ eline = self.LineFromPosition(sel[1])
+ bMulti = sline != eline
+ return bMulti
+
+ def CallTipCancel(self):
+ """Cancel any active calltip(s)"""
+ if self.CallTipActive():
+ super(EditraBaseStc, self).CallTipCancel()
+
+ def CallTipShow(self, position, tip):
+ """Show a calltip at the given position in the control
+ @param position: int
+ @param tip: unicode
+
+ """
+ self.CallTipCancel()
+ super(EditraBaseStc, self).CallTipShow(position, tip)
+
+ def HidePopups(self):
+ """Hide autocomp/calltip popup windows if any are active"""
+ if self.AutoCompActive():
+ self.AutoCompCancel()
+
+ self.CallTipCancel()
+
+ def InitCompleter(self):
+ """(Re)Initialize a completer object for this buffer
+ @todo: handle extended autocomp for plugins?
+
+ """
+ # Check for plugins that may extend or override functionality for this
+ # file type.
+ autocomp_ext = AutoCompExtension(wx.GetApp().GetPluginManager())
+ completer = autocomp_ext.GetCompleter(self)
+ if completer is not None:
+ self._code['compsvc'] = completer
+ else:
+ extend = Profile_Get('AUTO_COMP_EX') # Using extended autocomp?
+ self._code['compsvc'] = autocomp.AutoCompService.GetCompleter(self, extend)
+
+ def LoadFile(self, path):
+ """Load the file at the given path into the buffer. Returns
+ True if no errors and False otherwise. To retrieve the errors
+ check the last error that was set in the file object returned by
+ L{GetDocument}.
+ @param path: path to file
+
+ """
+ # Post notification that a file load is starting
+ ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENING, path)
+ self.file.SetPath(path)
+ txt = self.file.Read()
+ if txt is not None:
+ if self.file.IsRawBytes() and not ebmlib.IsUnicode(txt):
+ self.AddStyledText(txt)
+ self.SetReadOnly(True) # Don't allow editing of raw bytes
+ else:
+ self.SetText(txt)
+ else:
+ self.file.SetPath('')
+ return False
+
+ if self.file.GetLastError() != 'None':
+ # Return false if there was an encoding error and a fallback
+ # was used. So the caller knows to check the error status
+ return False
+ else:
+ return True
+
+ def MoveCaretPos(self, offset):
+ """Move caret by the given offset
+ @param offset: int (+ move right, - move left)
+
+ """
+ pos = max(self.GetCurrentPos() + offset, 0)
+ pos = min(pos, self.GetLength())
+ self.GotoPos(pos)
+ self.ChooseCaretX()
+
+ def OnAutoCompSel(self, evt):
+ """Handle when an item is inserted from the autocomp list"""
+ text = evt.GetText()
+ cpos = evt.GetPosition()
+ self._code['compsvc'].OnCompletionInserted(cpos, text)
+
+ def OnChanged(self, evt):
+ """Handles updates that need to take place after
+ the control has been modified.
+ @param evt: wx.stc.StyledTextEvent
+
+ """
+ if self._line_num:
+ # Adjust line number margin width to expand as needed when line
+ # number width over fills the area.
+ lines = self.GetLineCount()
+ mwidth = self.GetTextExtent(str(lines))[0]
+
+ adj = 8
+ if wx.Platform == '__WXMAC__':
+ adj = 2
+
+ nwidth = max(15, mwidth + adj)
+ if self.GetMarginWidth(NUM_MARGIN) != nwidth:
+ self.SetMarginWidth(NUM_MARGIN, nwidth)
+
+ wx.PostEvent(self.GetParent(), evt)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_CHANGED, context=self)
+
+ def OnModified(self, evt):
+ """Handle modify events, includes style changes!"""
+ if self.VertEdit.Enabled:
+ self.VertEdit.OnModified(evt)
+ else:
+ evt.Skip()
+
+ def OnStyleNeeded(self, evt):
+ """Perform custom styling when registered for a container lexer"""
+ if self._code['clexer'] is not None:
+ self._code['clexer'](self, self.GetEndStyled(), evt.GetPosition())
+ else:
+ evt.Skip()
+
+ def PutText(self, text):
+ """Put text in the buffer. Like AddText but does the right thing
+ depending upon the input mode and buffer state.
+ @param text: string
+
+ """
+ if not self.HasSelection():
+ cpos = self.GetCurrentPos()
+ lepos = self.GetLineEndPosition(self.GetCurrentLine())
+ if self.GetOvertype() and cpos != lepos:
+ self.CharRight()
+ self.DeleteBack()
+ self.AddText(text)
+ else:
+ self.ReplaceSelection(text)
+
+ def RegisterImages(self):
+ """Register the images for the autocomp popup list"""
+ images = [(autocomp.TYPE_FUNCTION, ed_glob.ID_FUNCT_TYPE),
+ (autocomp.TYPE_METHOD, ed_glob.ID_METHOD_TYPE),
+ (autocomp.TYPE_PROPERTY, ed_glob.ID_PROPERTY_TYPE),
+ (autocomp.TYPE_ATTRIBUTE, ed_glob.ID_ATTR_TYPE),
+ (autocomp.TYPE_CLASS, ed_glob.ID_CLASS_TYPE),
+ (autocomp.TYPE_VARIABLE, ed_glob.ID_VARIABLE_TYPE),
+ (autocomp.TYPE_ELEMENT, ed_glob.ID_ELEM_TYPE)]
+ for idx, img in images:
+ bmp = wx.ArtProvider.GetBitmap(str(img), wx.ART_MENU)
+ if bmp.IsOk():
+ self.RegisterImage(idx, bmp)
+
+ def SearchText(self, text, regex=False, back=False):
+ """Search for text forward or backward
+ @param text: string
+ @keyword regex: bool
+ @keyword back: bool
+
+ """
+ flags = wx.stc.STC_FIND_MATCHCASE
+ if regex:
+ flags = flags | wx.stc.STC_FIND_REGEXP
+
+ self.SearchAnchor()
+ if not back:
+ # Search forward
+ res = self.SearchNext(flags, text)
+ if res == -1:
+ # Nothing found, search from top
+ self.DocumentStart()
+ self.SearchAnchor()
+ res = self.SearchNext(flags, text)
+ else:
+ # Search backward
+ res = self.SearchPrev(flags, text)
+ if res == -1:
+ # Nothing found, search from bottom
+ self.DocumentEnd()
+ self.SearchAnchor()
+ res = self.SearchPrev(flags, text)
+ return res # returns -1 if nothing found even after wrapping around
+
+ def SetDocument(self, doc):
+ """Change the document object used.
+ @param doc: an L{ed_txt.EdFile} instance
+
+ """
+ del self.file
+ self.file = doc
+
+ def SetEncoding(self, enc):
+ """Sets the encoding of the document
+ @param enc: encoding to set for document
+
+ """
+ self.file.SetEncoding(enc)
+
+ def GetEncoding(self):
+ """Get the document objects encoding
+ @return: string
+
+ """
+ return self.file.GetEncoding()
+
+ def SetFileName(self, path):
+ """Set the buffers filename attributes from the given path"""
+ self.file.SetPath(path)
+
+ def SetKeyWords(self, kw_lst):
+ """Sets the keywords from a list of keyword sets
+ @param kw_lst: [ (KWLVL, "KEWORDS"), (KWLVL2, "KEYWORDS2"), ect...]
+
+ """
+ # Parse Keyword Settings List simply ignoring bad values and badly
+ # formed lists
+ self._code['keywords'] = list()
+ kwlist = ""
+ for keyw in kw_lst:
+ if len(keyw) != 2:
+ continue
+ else:
+ if not isinstance(keyw[0], int) or \
+ not isinstance(keyw[1], basestring):
+ continue
+ else:
+ kwlist += keyw[1]
+ super(EditraBaseStc, self).SetKeyWords(keyw[0], keyw[1])
+
+ # Can't have ? in scintilla autocomp list unless specifying an image
+ # TODO: this should be handled by the autocomp service
+ if '?' in kwlist:
+ kwlist.replace('?', '')
+
+ kwlist = kwlist.split() # Split into a list of words
+ kwlist = list(set(kwlist)) # Remove duplicates from the list
+ kwlist.sort() # Sort into alphabetical order
+
+ self._code['keywords'] = kwlist
+
+ def SetLexer(self, lexer):
+ """Set the buffers lexer
+ @param lexer: lexer to use
+ @note: Overrides StyledTextCtrl.SetLexer
+
+ """
+ if lexer == wx.stc.STC_LEX_CONTAINER:
+ # If setting a container lexer only bind the event if it hasn't
+ # been done yet.
+ if self._code['clexer'] is None:
+ self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyleNeeded)
+ else:
+ # If changing from a container lexer to a non container
+ # lexer we need to unbind the event.
+ if self._code['clexer'] is not None:
+ self.Unbind(wx.stc.EVT_STC_STYLENEEDED)
+ self._code['clexer'] = None
+
+ super(EditraBaseStc, self).SetLexer(lexer)
+
+ def SetModTime(self, modtime):
+ """Set the value of the files last modtime"""
+ self.file.SetModTime(modtime)
+
+ def SetProperties(self, prop_lst):
+ """Sets the Lexer Properties from a list of specifications
+ @param prop_lst: [ ("PROPERTY", "VAL"), ("PROPERTY2", "VAL2) ]
+
+ """
+ # Parses Property list, ignoring all bad values
+ for prop in prop_lst:
+ if len(prop) != 2:
+ continue
+ else:
+ if not isinstance(prop[0], basestring) or not \
+ isinstance(prop[1], basestring):
+ continue
+ else:
+ self.SetProperty(prop[0], prop[1])
+ return True
+
+ def BaseSetSelection(self, start, end):
+ """Call base STC SetSelection method, for use with internal utf-8
+ indexes in use by derived classes, STC hell...
+
+ """
+ super(EditraBaseStc, self).SetSelection(start, end)
+
+ def SetSelection(self, start, end):
+ """Override base method to make it work correctly using
+ Unicode character positions instead of UTF-8.
+
+ """
+ # STC HELL - some methods require UTF-8 offsets while others work
+ # with Unicode...
+ # Calculate UTF-8 offsets in buffer
+ unicode_txt = self.GetText()
+ if start != 0:
+ start = len(ed_txt.EncodeString(unicode_txt[0:start], 'utf-8'))
+ if end != 0:
+ end = len(ed_txt.EncodeString(unicode_txt[0:end], 'utf-8'))
+ del unicode_txt
+ super(EditraBaseStc, self).SetSelection(start, end)
+
+ def GetSelection(self):
+ """Get the selection positions in Unicode instead of UTF-8"""
+ # STC HELL
+ # Translate the UTF8 byte offsets to unicode
+ start, end = super(EditraBaseStc, self).GetSelection()
+ utf8_txt = self.GetTextUTF8()
+ if start != 0:
+ start = len(ed_txt.DecodeString(utf8_txt[0:start], 'utf-8'))
+ if end != 0:
+ end = len(ed_txt.DecodeString(utf8_txt[0:end], 'utf-8'))
+ del utf8_txt
+ return start, end
+
+ def ShowAutoCompOpt(self, command):
+ """Shows the autocompletion options list for the command
+ @param command: command to look for autocomp options for
+
+ """
+ pos = self.GetCurrentPos()
+ # symList is a list(completer.Symbol)
+ symList = self._code['compsvc'].GetAutoCompList(command)
+
+ # Build a list that can be feed to Scintilla
+ lst = map(unicode, symList)
+ if lst is not None and len(lst):
+ self.BeginUndoAction()
+ lst = u' '.join(lst)
+ if lst.isspace():
+ return
+ self.AutoCompShow(pos - self.WordStartPosition(pos, True), lst)
+
+ # Check if something was inserted due to there only being a
+ # single choice returned from the completer and allow the completer
+ # to adjust caret position as necessary.
+ curpos = self.GetCurrentPos()
+ if curpos != pos:
+ text = self.GetTextRange(pos, curpos)
+ self._code['compsvc'].OnCompletionInserted(pos, text)
+ self.EndUndoAction()
+ self.SetFocus()
+
+ def GetViewWhiteSpace(self):
+ """Get if view whitespace is turned on
+ @return: bool
+
+ """
+ val = super(EditraBaseStc, self).GetViewWhiteSpace()
+ return val != wx.stc.STC_WS_INVISIBLE
+
+ def SetViewWhiteSpace(self, viewws):
+ """Overrides base method to make it a simple bool toggle"""
+ if viewws:
+ val = wx.stc.STC_WS_VISIBLEALWAYS
+ else:
+ val = wx.stc.STC_WS_INVISIBLE
+ super(EditraBaseStc, self).SetViewWhiteSpace(val)
+
+ def GetWrapMode(self):
+ """Get if word wrap is turned on
+ @return: bool
+
+ """
+ val = super(EditraBaseStc, self).GetWrapMode()
+ return val != wx.stc.STC_WRAP_NONE
+
+ def SetWrapMode(self, wrap):
+ """Overrides base method to make it a simple toggle operation
+ @param wrap: bool
+
+ """
+ if wrap:
+ val = wx.stc.STC_WRAP_WORD
+ else:
+ val = wx.stc.STC_WRAP_NONE
+ super(EditraBaseStc, self).SetWrapMode(val)
+
+ def ShowCallTip(self, command):
+ """Shows call tip for given command
+ @param command: command to look for calltips for
+
+ """
+ self.CallTipCancel()
+
+ tip = self._code['compsvc'].GetCallTip(command)
+ if len(tip):
+ curr_pos = self.GetCurrentPos()
+ tip_pos = curr_pos - (len(command.split('.')[-1]) + 1)
+ fail_safe = curr_pos - self.GetColumn(curr_pos)
+ self.CallTipShow(max(tip_pos, fail_safe), tip)
+
+ def ToggleColumnMode(self):
+ """Toggle the column edit mode"""
+ self.VertEdit.enable(not self.VertEdit.Enabled)
+
+ def ToggleComment(self):
+ """Toggle the comment of the selected region"""
+ if len(self._code['comment']):
+ sel = self.GetSelection()
+ start = self.LineFromPosition(sel[0])
+ end = self.LineFromPosition(sel[1])
+ c_start = self._code['comment'][0]
+
+ if end > start and self.GetColumn(sel[1]) == 0:
+ end = end - 1
+
+ # Analyze the selected line(s)
+ comment = 0
+ for line in range(start, end+1):
+ txt = self.GetLine(line)
+ if txt.lstrip().startswith(c_start):
+ comment += 1
+
+ lcount = end - start
+ mod = 1
+ if lcount == 0:
+ mod = 0
+
+ if comment > (lcount / 2) + mod:
+ # Uncomment
+ self.Comment(start, end, True)
+ else:
+ self.Comment(start, end, False)
+
+ def ToggleLineNumbers(self, switch=None):
+ """Toggles the visibility of the line number margin
+ @keyword switch: force a particular setting
+
+ """
+ if (switch is None and \
+ not self.GetMarginWidth(NUM_MARGIN)) or switch:
+ self.EnableLineNumbers(True)
+ else:
+ self.EnableLineNumbers(False)
+
+ @property
+ def VertEdit(self):
+ """Vertical edit mode accessor."""
+ return self.vert_edit
+
+ #---- Style Function Definitions ----#
+
+ def RefreshStyles(self):
+ """Refreshes the colorization of the window by reloading any
+ style tags that may have been modified.
+ @postcondition: all style settings are refreshed in the control
+
+ """
+ with eclib.Freezer(self) as _tmp:
+ self.StyleClearAll()
+ self.SetSyntax(self.GetSyntaxParams())
+ self.DefineMarkers()
+ self.Refresh()
+
+ def UpdateBaseStyles(self):
+ """Update the controls basic styles"""
+ super(EditraBaseStc, self).UpdateBaseStyles()
+
+ # Set control specific styles
+ sback = self.GetItemByName('select_style')
+ if not sback.IsNull():
+ sback = sback.GetBack()
+ else:
+ sback = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+ self.VertEdit.SetBlockColor(sback)
+ self.DefineMarkers()
+
+#-----------------------------------------------------------------------------#
+
+class AutoCompExtension(plugin.Plugin):
+ """Plugin that Extends the autocomp feature"""
+ observers = plugin.ExtensionPoint(iface.AutoCompI)
+ def GetCompleter(self, buff):
+ """Get the completer for the specified file type id
+ @param buff: EditraStc instance
+
+ """
+ ftypeid = buff.GetLangId()
+ for observer in self.observers:
+ try:
+ if observer.GetFileTypeId() == ftypeid:
+ return observer.GetCompleter(buff)
+ except Exception, msg:
+ util.Log("[ed_basestc][err] GetCompleter Extension: %s" % str(msg))
+ else:
+ return None
+
+#-----------------------------------------------------------------------------#
+
+def _GetMacKeyBindings():
+ """Returns a list of 3-element tuples defining the standard key
+ bindings for Mac text editors -- i.e., the behavior of option-arrow,
+ shift-delete, and so on.
+
+ @return: list of (key code, modifier keys, STC action)
+
+ """
+ # A good reference for these: http://www.yellowbrain.com/stc/keymap.html
+ return [
+ # Move/select/delete by word
+ (wx.stc.STC_KEY_LEFT, wx.stc.STC_SCMOD_ALT,
+ wx.stc.STC_CMD_WORDLEFT),
+ (wx.stc.STC_KEY_RIGHT, wx.stc.STC_SCMOD_ALT,
+ wx.stc.STC_CMD_WORDRIGHT),
+ (wx.stc.STC_KEY_LEFT, ALT_SHIFT, wx.stc.STC_CMD_WORDLEFTEXTEND),
+ (wx.stc.STC_KEY_RIGHT, ALT_SHIFT, wx.stc.STC_CMD_WORDRIGHTEXTEND),
+ (wx.stc.STC_KEY_BACK, wx.stc.STC_SCMOD_ALT,
+ wx.stc.STC_CMD_DELWORDLEFT),
+ (wx.stc.STC_KEY_DELETE, wx.stc.STC_SCMOD_ALT,
+ wx.stc.STC_CMD_DELWORDRIGHT),
+ (wx.stc.STC_KEY_BACK, ALT_SHIFT, wx.stc.STC_CMD_DELWORDRIGHT),
+ (wx.stc.STC_KEY_DELETE, ALT_SHIFT, wx.stc.STC_CMD_DELWORDLEFT),
+
+ # Move/select/delete by line
+ (wx.stc.STC_KEY_LEFT, wx.stc.STC_SCMOD_CTRL,
+ wx.stc.STC_CMD_VCHOME),
+ (wx.stc.STC_KEY_LEFT, CTRL_SHIFT, wx.stc.STC_CMD_VCHOMEEXTEND),
+ (wx.stc.STC_KEY_RIGHT, wx.stc.STC_SCMOD_CTRL,
+ wx.stc.STC_CMD_LINEEND),
+ (wx.stc.STC_KEY_RIGHT, CTRL_SHIFT, wx.stc.STC_CMD_LINEENDEXTEND),
+ (wx.stc.STC_KEY_BACK, wx.stc.STC_SCMOD_CTRL,
+ wx.stc.STC_CMD_DELLINELEFT),
+ (wx.stc.STC_KEY_DELETE, wx.stc.STC_SCMOD_CTRL,
+ wx.stc.STC_CMD_DELLINERIGHT),
+ (wx.stc.STC_KEY_BACK, CTRL_SHIFT, wx.stc.STC_CMD_DELLINERIGHT),
+ (wx.stc.STC_KEY_DELETE, CTRL_SHIFT, wx.stc.STC_CMD_DELLINELEFT),
+
+ # By-character deletion behavior
+ (wx.stc.STC_KEY_BACK, wx.stc.STC_SCMOD_NORM,
+ wx.stc.STC_CMD_DELETEBACK),
+ (wx.stc.STC_KEY_DELETE, wx.stc.STC_SCMOD_SHIFT,
+ wx.stc.STC_CMD_DELETEBACK),
+
+ # NOTE: The following two are a special case, since Scintilla
+ # doesn't have a forward-delete action. So here we just cancel any
+ # tip our auto-completion display, and then implement forward
+ # delete in OnKeyDown.
+ #(wx.stc.STC_KEY_DELETE, 0, wx.stc.STC_CMD_CANCEL),
+ # Disabled as it breaks some keyboard functionality
+ # NOTE: forward delete on mac is Fn+Delete and works fine
+ # (wx.stc.STC_KEY_BACK, wx.stc.STC_SCMOD_SHIFT,
+ # wx.stc.STC_CMD_CANCEL),
+ ]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basewin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basewin.py
new file mode 100644
index 0000000..f3775bc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basewin.py
@@ -0,0 +1,200 @@
+###############################################################################
+# Name: ed_basewin.py #
+# Purpose: Common window base class(es) #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This module provides base classes for windows and dialogs to be used within
+Editra.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_basewin.py 71697 2012-06-08 15:20:22Z CJP $"
+__revision__ = "$Revision: 71697 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+
+# Local Imports
+import ed_msg
+import eclib
+import util
+
+#--------------------------------------------------------------------------#
+
+def FindMainWindow(window):
+ """Find the MainWindow of the given window
+ @return: MainWindow or None
+
+ """
+ def IsMainWin(win):
+ """Check if the given window is a main window"""
+ return getattr(win, '__name__', '') == 'MainWindow'
+
+ if IsMainWin(window):
+ return window
+ # else start looking up the parent hierarchy
+ tlw = window.GetTopLevelParent()
+ if IsMainWin(tlw):
+ return tlw
+ elif hasattr(tlw, 'GetParent'):
+ tlw = tlw.GetParent()
+ if IsMainWin(tlw):
+ return tlw
+
+ return None
+
+#--------------------------------------------------------------------------#
+
+class EDBaseFileTree(eclib.FileTree):
+ """Base file view control. Contains some common functionality
+ that should not be included in the low level control.
+
+ """
+ def __init__(self, parent):
+ super(EDBaseFileTree, self).__init__(parent)
+
+ # Message Handlers
+ ed_msg.Subscribe(self.OnActivateMsg, ed_msg.EDMSG_UI_MW_ACTIVATE)
+
+ # Events
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+
+ def OnDestroy(self, event):
+ """Cleanup message handlers"""
+ if self:
+ ed_msg.Unsubscribe(self.OnActivateMsg)
+ self.DoOnDestroy()
+ event.Skip()
+
+ def OnActivateMsg(self, msg):
+ """Handle activation messages"""
+ mw = FindMainWindow(self)
+ if mw and msg.Context == mw.Id:
+ self.DoOnActivate(msg.Data['active'])
+
+ #---- Interface ----#
+
+ def DoOnActivate(self, active):
+ """Handle activation event
+ @param active: bool - window active or inactive
+
+ """
+ pass
+
+ def DoOnDestroy(self):
+ """Handle window destruction"""
+ pass
+
+#--------------------------------------------------------------------------#
+
+class EdBaseDialog(eclib.ECBaseDlg):
+ """Editra Dialog Base Class"""
+ def __init__(self, parent, id=wx.ID_ANY, title=u"",
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_DIALOG_STYLE, name=u"EdBaseDialog"):
+ super(EdBaseDialog, self).__init__(parent, id, title, pos,
+ size, style, name)
+
+#--------------------------------------------------------------------------#
+
+class EdBaseFrame(wx.Frame):
+ """Editra Frame Base Class"""
+ def __init__(self, parent, id=wx.ID_ANY, title=u"",
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=wx.DEFAULT_FRAME_STYLE, name=u"EdBaseFrame"):
+ super(EdBaseFrame, self).__init__(parent, id, title, pos,
+ size, style, name)
+
+ # Setup
+ util.SetWindowIcon(self)
+
+ # Register with App
+ wx.GetApp().RegisterWindow(repr(self), self)
+
+ # Event Handlers
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+ def OnClose(self, event):
+ """Handle frame closure event"""
+ wx.GetApp().UnRegisterWindow(repr(self))
+ event.Skip()
+
+#--------------------------------------------------------------------------#
+
+class EdBaseCtrlBox(eclib.ControlBox):
+ """ControlBox base class to be used by all common components"""
+ def __init__(self, parent):
+ super(EdBaseCtrlBox, self).__init__(parent)
+
+ ed_msg.Subscribe(self._OnFontChange, ed_msg.EDMSG_DSP_FONT)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self._OnDestroy)
+
+ def _OnDestroy(self, evt):
+ if self and evt.GetEventObject is self:
+ ed_msg.Unsubscribe(self._OnFontChange)
+
+ def _OnFontChange(self, msg):
+ """Update font of all controls"""
+ if not self:
+ return
+ font = msg.GetData()
+ if isinstance(font, wx.Font):
+ for pos in (wx.TOP, wx.BOTTOM, wx.LEFT, wx.RIGHT):
+ cbar = self.GetControlBar(pos)
+ if cbar:
+ for child in cbar.GetChildren():
+ child.SetFont(font)
+
+ def AddPlateButton(self, lbl=u"", bmp=-1,
+ align=wx.ALIGN_LEFT, cbarpos=wx.TOP):
+ """Add an eclib.PlateButton to the ControlBar specified by
+ cbarpos.
+ @keyword lbl: Button Label
+ @keyword bmp: Bitmap or EditraArtProvider ID
+ @keyword align: button alignment
+ @keyword cbarpos: ControlBar position
+ @return: PlateButton instance
+
+ """
+ ctrlbar = self.GetControlBar(cbarpos)
+ assert ctrlbar is not None, "No ControlBar at cbarpos"
+ return ctrlbar.AddPlateButton(lbl, bmp, align)
+
+ def CreateControlBar(self, pos=wx.TOP):
+ """Override for CreateControlBar to automatically set the
+ flat non-gradient version of the control under GTK.
+
+ """
+ cbar = super(EdBaseCtrlBox, self).CreateControlBar(pos)
+ cbar.__class__ = EdBaseCtrlBar
+ if wx.Platform == '__WXGTK__':
+ cbar.SetWindowStyle(eclib.CTRLBAR_STYLE_DEFAULT|\
+ eclib.CTRLBAR_STYLE_BORDER_TOP|\
+ eclib.CTRLBAR_STYLE_BORDER_BOTTOM)
+ cbar.SetMargins(2,2)
+ return cbar
+
+class EdBaseCtrlBar(eclib.ControlBar):
+ def AddPlateButton(self, lbl=u"", bmp=-1, align=wx.ALIGN_LEFT):
+ """Add an eclib.PlateButton
+ @keyword lbl: Button Label
+ @keyword bmp: Bitmap or EditraArtProvider ID
+ @keyword align: button alignment
+ @return: PlateButton instance
+
+ """
+ if not isinstance(bmp, wx.Bitmap):
+ assert isinstance(bmp, int)
+ bmp = wx.ArtProvider.GetBitmap(str(bmp), wx.ART_MENU)
+ if bmp.IsNull() or not bmp.IsOk():
+ bmp = None
+ btn = eclib.PlateButton(self, wx.ID_ANY, lbl, bmp,
+ style=eclib.PB_STYLE_NOBG)
+ self.AddControl(btn, align)
+ return btn
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_book.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_book.py
new file mode 100644
index 0000000..cfd2bac
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_book.py
@@ -0,0 +1,123 @@
+###############################################################################
+# Name: ed_book.py #
+# Purpose: Editra notebook base class #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Base class for the main tab controls
+
+@summary: Tabbed book control base classes
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_book.py 69245 2011-09-30 17:52:23Z CJP $"
+__revision__ = "$Revision: 69245 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+# Editra Imports
+import extern.aui as aui
+import ed_msg
+from profiler import Profile_Get
+
+#-----------------------------------------------------------------------------#
+
+class EdBaseBook(aui.AuiNotebook):
+ """Base notebook control"""
+ def __init__(self, parent, style=0):
+ style |= self.GetBaseStyles()
+ super(EdBaseBook, self).__init__(parent, agwStyle=style)
+ if wx.Platform == '__WXGTK__':
+ self.SetArtProvider(GtkTabArt())
+
+ # Setup
+ self.UpdateFontSetting()
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.PointSize += 2
+ self.NavigatorProps.Font = font
+ self.NavigatorProps.MinSize = wx.Size(300, 250)
+ self.SetSashDClickUnsplit(True)
+
+ # Message Handlers
+ ed_msg.Subscribe(self.OnUpdateFont, ed_msg.EDMSG_DSP_FONT)
+
+ # Event Handlers
+ self.Bind(wx.EVT_WINDOW_DESTROY, self._OnDestroy, self)
+
+ def _OnDestroy(self, evt):
+ """Unsubscribe message handlers on delete"""
+ if self and evt.GetEventObject() is self:
+ ed_msg.Unsubscribe(self.OnUpdateFont)
+ evt.Skip()
+
+ @staticmethod
+ def GetBaseStyles():
+ """Get the common base style flags
+ @return: bitmask
+
+ """
+ style = aui.AUI_NB_NO_TAB_FOCUS
+ if wx.Platform == '__WXMAC__':
+ style |= aui.AUI_NB_CLOSE_ON_TAB_LEFT
+ return style
+
+ def OnUpdateFont(self, msg):
+ """Update the font settings for the control in response to
+ user settings change.
+
+ """
+ if self:
+ self.UpdateFontSetting()
+
+ def SetPageBitmap(self, pg, bmp):
+ """Set a tabs bitmap
+ @param pg: page index
+ @param bmp: Bitmap
+ @note: no action if user prefs have turned off bmp
+
+ """
+ if not self.UseIcons():
+ bmp = wx.NullBitmap
+ super(EdBaseBook, self).SetPageBitmap(pg, bmp)
+
+ def UpdateFontSetting(self):
+ """Update font setting using latest profile data"""
+ font = Profile_Get('FONT3', 'font', None)
+ if font:
+ self.SetFont(font)
+
+ def UseIcons(self):
+ """Is the book using tab icons?"""
+ bUseIcons = Profile_Get('TABICONS', default=True)
+ return bUseIcons
+
+#-----------------------------------------------------------------------------#
+
+class GtkTabArt(aui.VC71TabArt):
+ """Simple tab art with no gradients"""
+ def __init__(self):
+ super(GtkTabArt, self).__init__()
+
+ def DrawBackground(self, dc, wnd, rect):
+ """
+ Draws the tab area background.
+
+ :param `dc`: a `wx.DC` device context;
+ :param `wnd`: a `wx.Window` instance object;
+ :param `rect`: the tab control rectangle.
+ """
+ self._buttonRect = wx.Rect()
+
+ # draw background
+ r = wx.Rect(rect.x, rect.y, rect.width+2, rect.height)
+
+ # draw base lines
+ dc.SetPen(self._border_pen)
+ dc.SetBrush(self._base_colour_brush)
+ dc.DrawRectangleRect(r)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_bookmark.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_bookmark.py
new file mode 100644
index 0000000..782caae
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_bookmark.py
@@ -0,0 +1,296 @@
+###############################################################################
+# Name: Cody Precord #
+# Purpose: Bookmark Manager window and plugin interface #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2010 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Bookmark manager
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_bookmark.py 69115 2011-09-17 16:51:49Z CJP $"
+__revision__ = "$Revision: 69115 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import re
+import wx
+
+# Editra Libraries
+import ed_msg
+import iface
+import plugin
+from profiler import Profile_Get, Profile_Set
+import ed_glob
+import util
+import eclib
+import ebmlib
+import ed_basewin
+from ed_marker import Bookmark
+
+#-----------------------------------------------------------------------------#
+# Globals
+_ = wx.GetTranslation
+
+#-----------------------------------------------------------------------------#
+
+# Interface Implementation
+class EdBookmarks(plugin.Plugin):
+ """Shelf interface implementation for the bookmark manager"""
+ plugin.Implements(iface.ShelfI)
+
+ __name__ = u'Bookmarks'
+
+ @staticmethod
+ def AllowMultiple():
+ """EdBookmark only allows one instance"""
+ return False
+
+ @staticmethod
+ def CreateItem(parent):
+ """Returns a bookmark panel"""
+ return BookmarkWindow(parent)
+
+ def GetBitmap(self):
+ """Get the log viewers tab icon
+ @return: wx.Bitmap
+
+ """
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_ADD_BM), wx.ART_MENU)
+ return bmp
+
+ @staticmethod
+ def GetId():
+ """Plugin menu identifier ID"""
+ return ed_glob.ID_BOOKMARK_MGR
+
+ @staticmethod
+ def GetMenuEntry(menu):
+ """Get the menu entry for the bookmark viewer
+ @param menu: the menu items parent menu
+
+ """
+ item = wx.MenuItem(menu, ed_glob.ID_BOOKMARK_MGR,
+ _("Bookmarks"),
+ _("View all bookmarks"))
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_ADD_BM), wx.ART_MENU)
+ item.SetBitmap(bmp)
+ return item
+
+ def GetName(self):
+ """Return the name of this control"""
+ return self.__name__
+
+ @staticmethod
+ def IsStockable():
+ """EdBookmark can be saved in the shelf preference stack"""
+ return True
+
+ # Bookmark storage
+ _marks = list()
+ @classmethod
+ def OnStoreBM(cls, msg):
+ data = msg.GetData()
+ buf = data.get('stc')
+ line = data.get('line')
+ mark = Bookmark()
+ mark.Filename = buf.GetFileName()
+ mark.Line = line
+ if data.get('added', False):
+ if mark not in cls._marks:
+ # Store the stc bookmark handle
+ mark.Handle = data.get('handle', None)
+ # Store an alias for the bookmark
+ name = u""
+ cline = buf.GetCurrentLine()
+ if line == cline:
+ name = buf.GetSelectedText()
+ if not name:
+ name = buf.GetLine(line)
+ mark.Name = name.strip()
+ cls._marks.append(mark)
+ else:
+ if mark in cls._marks:
+ idx = cls._marks.index(mark)
+ cls._marks.pop(idx)
+
+ @classmethod
+ def GetMarks(cls):
+ return cls._marks
+
+ed_msg.Subscribe(EdBookmarks.OnStoreBM, ed_msg.EDMSG_UI_STC_BOOKMARK)
+
+#-----------------------------------------------------------------------------#
+
+class BookmarkWindow(ed_basewin.EdBaseCtrlBox):
+ """Shelf window for managing bookmarks"""
+ def __init__(self, parent):
+ super(BookmarkWindow, self).__init__(parent)
+
+ # Attributes
+ self._list = BookmarkList(self)
+
+ #Setup
+ self.SetWindow(self._list)
+ ctrlbar = self.CreateControlBar(wx.TOP)
+ ctrlbar.AddStretchSpacer()
+ self._delbtn = self.AddPlateButton(_("Delete"), ed_glob.ID_DELETE,
+ wx.ALIGN_RIGHT)
+ self._delbtn.ToolTip = wx.ToolTip(_("Delete Bookmark"))
+ self._delallbtn = self.AddPlateButton(_("Delete All"),
+ ed_glob.ID_DELETE_ALL,
+ wx.ALIGN_RIGHT)
+ self._delallbtn.ToolTip = wx.ToolTip(_("Delete all bookmarks"))
+
+ # Message Handlers
+ ed_msg.Subscribe(self.OnBookmark, ed_msg.EDMSG_UI_STC_BOOKMARK)
+
+ # Event Handlers
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+ self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivate, self._list)
+ self.Bind(wx.EVT_BUTTON, self.OnDelBm, self._delbtn)
+ self.Bind(wx.EVT_BUTTON, self.OnDelAllBm, self._delallbtn)
+ # BUG in wxAUI UpdateUI events not processed when docked
+ # TODO: renable when switch to agw aui
+# self.Bind(wx.EVT_UPDATE_UI,
+# lambda evt: evt.Enable(bool(len(self._list.GetSelections()))),
+# self._delbtn)
+
+ def OnDestroy(self, evt):
+ """Unsubscribe message handlers on delete"""
+ if evt.GetId() == self.GetId():
+ ed_msg.Unsubscribe(self.OnBookmark)
+ evt.Skip()
+
+ def OnBookmark(self, msg):
+ """Bookmark added or removed callback"""
+ # Update on next iteration to ensure that handler
+ # in the singleton data store have been updated.
+ wx.CallAfter(self.DoUpdateListCtrl)
+
+ def OnDelAllBm(self, evt):
+ """Delete all bookmarks"""
+ items = range(self._list.ItemCount)
+ self.DeleteBookmarks(items)
+
+ def OnDelBm(self, evt):
+ """Remove the selected bookmark(s) from the list and the buffer"""
+ items = self._list.GetSelections()
+ self.DeleteBookmarks(items)
+
+ def DeleteBookmarks(self, items):
+ """Delete the bookmarks from the passed in list
+ @param items: list of indexes in BookmarkList
+
+ """
+ assert isinstance(items, list)
+ if len(items):
+ items.reverse()
+ marks = EdBookmarks.GetMarks()
+ for item in items:
+ if item < len(marks):
+ mark = marks.pop(item)
+ app = wx.GetApp()
+ mw = app.GetActiveWindow()
+ if mw:
+ nb = mw.GetNotebook()
+ buf = nb.FindBuffer(mark.Filename)
+ if buf:
+ buf.MarkerDeleteHandle(mark.Handle)
+ self.DoUpdateListCtrl()
+
+ def DoUpdateListCtrl(self):
+ """Update the listctrl for changes in the cache"""
+ nMarks = len(EdBookmarks.GetMarks())
+ self._list.SetItemCount(nMarks)
+ # Refresh everything
+ # XXX: if optimization is needed only refresh visible items
+ self._list.RefreshItems(0, nMarks)
+ self._list.Refresh()
+
+ def OnItemActivate(self, evt):
+ """Handle double clicks on items to navigate to the
+ selected bookmark.
+
+ """
+ index = evt.m_itemIndex
+ marks = EdBookmarks.GetMarks()
+ if index < len(marks):
+ mark = marks[index]
+ self.GotoBookmark(mark)
+
+ def GotoBookmark(self, mark):
+ """Goto the bookmark in the editor
+ @param mark: BookMark
+
+ """
+ app = wx.GetApp()
+ mw = app.GetActiveWindow()
+ if mw:
+ nb = mw.GetNotebook()
+ buf = nb.FindBuffer(mark.Filename)
+ use_handle = True
+ if not buf:
+ nb.OpenPage(ebmlib.GetPathName(mark.Filename),
+ ebmlib.GetFileName(mark.Filename))
+ buf = nb.GetCurrentPage()
+ use_handle = False # Handle is invalid so use line number
+
+ if buf:
+ # Ensure the tab is the current one
+ nb.GotoPage(mark.Filename)
+ # Jump to the bookmark line
+ if use_handle:
+ lnum = buf.MarkerLineFromHandle(mark.Handle)
+ else:
+ lnum = mark.Line
+ buf.GotoLine(lnum)
+ else:
+ util.Log("[ed_bookmark][err] Failed to locate mainwindow")
+
+#-----------------------------------------------------------------------------#
+
+class BookmarkList(eclib.EBaseListCtrl):
+ """ListCtrl for displaying the bookmarks in"""
+ BOOKMARK = 0
+ FILE_NAME = 1
+ LINE_NUM = 2
+ def __init__(self, parent):
+ super(BookmarkList, self).__init__(parent,
+ style=wx.LC_REPORT|\
+ wx.LC_EDIT_LABELS|\
+ wx.LC_VIRTUAL)
+
+ # Setup
+ self._il = wx.ImageList(16,16)
+ self._idx = self._il.Add(Bookmark().Bitmap)
+ self.SetImageList(self._il, wx.IMAGE_LIST_SMALL)
+ self.InsertColumn(BookmarkList.BOOKMARK, _("Bookmark"))
+ self.InsertColumn(BookmarkList.FILE_NAME, _("File Location"))
+ self.InsertColumn(BookmarkList.LINE_NUM, _("Line Number"))
+ self.setResizeColumn(BookmarkList.FILE_NAME+1) #NOTE: +1 bug in mixin
+ self.SetItemCount(len(EdBookmarks.GetMarks()))
+
+ def OnGetItemImage(self, item):
+ return 0
+
+ def OnGetItemText(self, item, column):
+ """Override for virtual control"""
+ marks = EdBookmarks.GetMarks()
+ val = u""
+ if item < len(marks):
+ mark = marks[item]
+ if column == BookmarkList.BOOKMARK:
+ val = mark.Name
+ if not val:
+ val = _("Bookmark%d") % item
+ elif column == BookmarkList.FILE_NAME:
+ val = mark.Filename
+ elif column == BookmarkList.LINE_NUM:
+ val = unicode(mark.Line + 1)
+ return val
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_cmdbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_cmdbar.py
new file mode 100644
index 0000000..0bf9944
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_cmdbar.py
@@ -0,0 +1,1314 @@
+###############################################################################
+# Name: ed_cmdbar.py #
+# Purpose: Creates a small slit panel that holds small controls for searching #
+# and other actions. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This class creates a custom panel that can hide and show different controls
+based an id value. The panel is generally between 24-32 pixels in height but
+can grow to fit the controls inserted in it. The the background is painted with
+a gradient using system defined colors.
+
+@summary: The buffers CommandBar control with search/goto line/command entry
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_cmdbar.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import sys
+import re
+import wx
+
+# Local Imports
+import util
+import ed_glob
+import ed_search
+import ed_event
+import ed_msg
+import ebmlib
+import eclib
+import ed_basewin
+from profiler import Profile_Get
+
+_ = wx.GetTranslation
+#--------------------------------------------------------------------------#
+# Close Button Bitmap
+from extern.embeddedimage import PyEmbeddedImage
+
+XButton = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAIAAACQKrqGAAAAA3NCSVQICAjb4U/gAAAB6UlE"
+ "QVQokW2SvWsTYRjAn7tcctdLc7kmxtJqj8ZECIqi7eJHhywVxLWLSBctXQKFOhSE0IJKB0EH"
+ "wf/BwUkEBxEFFR0cSoei1ZaSJjQ56Zn0vDd3977v8zrcUTr0mZ6PH8+39Onxw97Xz0FnL2w1"
+ "4DhJnbLU4ZHs1Snpza0bk1cum0MFLvwoJmg/pmjs6bW7a5u7StDZM8Zu0v0W3W/HAGMAgJxF"
+ "pmYaxumc+nNLDlsNUBKceNJAKj27KI2OIWfImWKVcnMPuKr53QOmJsVfWz7sSZ+pqZWJ7L26"
+ "YpUUq5SfX1YrE4XZRR+pwikAKAAgBBMQkPevkuMVWdPz88sAIGs6+sR5+/IwlwIA0CXBrsM2"
+ "toPm/ZMrz2RNBwD0SaO+4G/9AACeG41R9o8wL6CuLwXs6Jow5Mz1OSJ3XMG4DAAiZIgidfb8"
+ "yOrzqC76RNb08Scv9HMXAAAoFyGNx0Kk2dt3I25nqbazVIvo/J05ABAsAMTETEYrX7pIbNv7"
+ "8iFZLLeePiKbG7TT9ta+y7lCY7UuM6oNGZ1mW3p9fXKqeq3/xz6wm8yNz8MRIyWRSg6amfTg"
+ "wHqzp+hW0XUcI3NCy6QBQGAYNRfVZYgJztxeH3LDilmd/vXxHVn/5m3/PvZd0mfKulU0q9P/"
+ "AeP28JG84F5KAAAAAElFTkSuQmCC")
+
+#-----------------------------------------------------------------------------#
+# Globals
+ID_CLOSE_BUTTON = wx.NewId()
+ID_SEARCH_NEXT = wx.NewId()
+ID_SEARCH_PRE = wx.NewId()
+ID_FIND_ALL = wx.NewId()
+ID_MATCH_CASE = wx.NewId()
+ID_WHOLE_WORD = wx.NewId()
+ID_REGEX = wx.NewId()
+
+#-----------------------------------------------------------------------------#
+
+class CommandBarBase(ed_basewin.EdBaseCtrlBar,
+ ebmlib.FactoryMixin):
+ """Base class for control bars"""
+ def __init__(self, parent):
+ super(CommandBarBase, self).__init__(parent,
+ style=eclib.CTRLBAR_STYLE_GRADIENT)
+
+ if wx.Platform == '__WXGTK__':
+ self.SetWindowStyle(eclib.CTRLBAR_STYLE_DEFAULT)
+
+ self.SetVMargin(2, 2)
+
+ # Attributes
+ self._parent = parent
+ self._menu = None
+ self._menu_enabled = True
+ self.ctrl = None
+ self.close_b = eclib.PlateButton(self, ID_CLOSE_BUTTON,
+ bmp=XButton.GetBitmap(),
+ style=eclib.PB_STYLE_NOBG)
+
+ # Setup
+ self.AddControl(self.close_b, wx.ALIGN_LEFT)
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnClose, self.close_b)
+ self.Bind(wx.EVT_CONTEXT_MENU, self.OnContext)
+ self.Bind(wx.EVT_MENU, self.OnContextMenu)
+ self.Bind(wx.EVT_SHOW, self.OnShowBar)
+
+ @classmethod
+ def GetMetaDefaults(cls):
+ return dict(id=-1, config_key=None)
+
+ #---- Properties ----#
+
+ MainControl = property(lambda self: self.ctrl,
+ lambda self, ctrl: self.SetControl(ctrl))
+
+ #---- Implementation ----#
+
+ def OnClose(self, evt):
+ """Handles events from the buttons on the bar
+ @param evt: Event that called this handler
+
+ """
+ if evt.Id == ID_CLOSE_BUTTON:
+ self.Hide()
+ else:
+ evt.Skip()
+
+ def OnContext(self, evt):
+ """Show the custom menu"""
+ if self._menu_enabled:
+ if self._menu is None:
+ # Lazy init the menu
+ self._menu = wx.Menu(_("Customize"))
+ # Ensure the label is disabled (wxMSW Bug)
+ if len(self._menu.MenuItems):
+ item = self._menu.MenuItems[0]
+ self._menu.Enable(item.GetId(), False)
+
+ to_menu = list()
+ for child in self.GetChildren():
+ if self.IsCustomizable(child):
+ to_menu.append(child)
+
+ if len(to_menu):
+ to_menu.sort(key=wx.Window.GetLabel)
+ for item in to_menu:
+ if not item.GetLabel():
+ continue
+
+ self._menu.Append(item.Id,
+ item.GetLabel(),
+ kind=wx.ITEM_CHECK)
+ self._menu.Check(item.Id, item.IsShown())
+
+ self.PopupMenu(self._menu)
+ else:
+ evt.Skip()
+
+ def OnContextMenu(self, evt):
+ """Hide and Show controls"""
+ ctrl = self.FindWindowById(evt.Id)
+ if ctrl is not None:
+ self.ShowControl(ctrl.GetName(), not ctrl.IsShown())
+ self.Layout()
+
+ # Update the persistent configuration
+ key = self.GetConfigKey()
+ if key is not None:
+ cfg = Profile_Get('CTRLBAR', default=dict())
+ state = self.GetControlStates()
+ cfg[key] = state
+
+ def OnShowBar(self, evt):
+ """Update the session list"""
+ if evt.IsShown():
+ if self and evt.EventObject is self:
+ self.OnBarShown()
+ evt.Skip()
+
+ def OnBarShown(self):
+ """virtual override for subclasses that wish to receive window show
+ event callbacks.
+
+ """
+ pass
+
+ def EnableMenu(self, enable=True):
+ """Enable the popup customization menu
+ @keyword enable: bool
+
+ """
+ self._menu_enabled = enable
+ if not enable and self._menu is not None:
+ self._menu.Destroy()
+ self._menu = None
+
+ def GetConfigKey(self):
+ """Get the key to use for the layout config persistence. This value
+ is set in the class definitions meta class.
+ @return: string
+
+ """
+ return self.meta.config_key
+
+ def GetControlStates(self):
+ """Get the map of control name id's to their shown state True/False
+ @return: dict()
+
+ """
+ state = dict()
+ for child in self.GetChildren():
+ if self.IsCustomizable(child):
+ state[child.GetName()] = child.IsShown()
+ return state
+
+ def SetControlStates(self, state):
+ """Set visibility state of the customizable controls
+ @param state: dict(ctrl_name=bool)
+
+ """
+ for name, show in state.iteritems():
+ self.ShowControl(name, show)
+ self.Layout()
+
+ def Hide(self):
+ """Hides the control and notifies the parent
+ @postcondition: CommandBar is hidden
+ @todo: don't reference nb directly here
+
+ """
+ super(CommandBarBase, self).Hide()
+ self._parent.SendSizeEvent()
+ nb = self._parent.GetNotebook()
+ ctrl = nb.GetCurrentCtrl()
+ if ctrl:
+ ctrl.SetFocus()
+ return True
+
+ def ShowControl(self, ctrl_name, show=True):
+ """Show/Hide a control
+ @param ctrl_name: string
+ @note: assumes all left aligned controls
+
+ """
+ sizer = self.GetControlSizer()
+ gonext = False
+ for item in sizer.GetChildren():
+ if gonext:
+ if item.IsSpacer():
+ item.Show(show)
+ break
+
+ if item.Window and item.Window.GetName() == ctrl_name:
+ item.Show(show)
+ gonext = True
+
+ def IsCustomizable(self, ctrl):
+ """Is the control of a type that can be customized
+ @param ctrl: wx.Window
+ @return: bool
+
+ """
+ ok = (ctrl is not self.close_b)
+ ok = ok and (isinstance(ctrl, wx.CheckBox) or \
+ isinstance(ctrl, eclib.PlateButton))
+ return ok
+
+ def SetControl(self, ctrl):
+ """Set the main control of this command bar
+ @param ctrl: window
+
+ """
+ self.ctrl = ctrl
+
+ def SetFocus(self):
+ """Set the focus to the bar and its main control"""
+ super(CommandBarBase, self).SetFocus()
+ if self.MainControl:
+ self.MainControl.SetFocus()
+
+#-----------------------------------------------------------------------------#
+
+class SearchBar(CommandBarBase):
+ """Commandbar for searching text in the current buffer."""
+ class meta:
+ id = ed_glob.ID_QUICK_FIND
+ config_key = 'SearchBar'
+
+ def __init__(self, parent):
+ super(SearchBar, self).__init__(parent)
+
+ # Attributes
+ self.SetControl(ed_search.EdSearchCtrl(self, wx.ID_ANY,
+ menulen=5, size=(180, -1)))
+ self._sctrl = self.MainControl.GetSearchController()
+
+ # Setup
+ f_lbl = wx.StaticText(self, label=_("Find") + u": ")
+ t_bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DOWN), wx.ART_MENU)
+ next_btn = eclib.PlateButton(self, ID_SEARCH_NEXT, _("Next"),
+ t_bmp, style=eclib.PB_STYLE_NOBG,
+ name="NextBtn")
+ self.AddControl(f_lbl, wx.ALIGN_LEFT)
+ self.AddControl(self.ctrl, wx.ALIGN_LEFT)
+ self.AddControl(next_btn, wx.ALIGN_LEFT)
+
+ t_bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_UP), wx.ART_MENU)
+ pre_btn = eclib.PlateButton(self, ID_SEARCH_PRE, _("Previous"),
+ t_bmp, style=eclib.PB_STYLE_NOBG,
+ name="PreBtn")
+ self.AddControl(pre_btn, wx.ALIGN_LEFT)
+
+ t_bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_FIND), wx.ART_MENU)
+ fa_btn = eclib.PlateButton(self, ID_FIND_ALL, _("Find All"),
+ t_bmp, style=eclib.PB_STYLE_NOBG,
+ name="FindAllBtn")
+ self.AddControl(fa_btn)
+ fa_btn.Show(False) # Hide this button by default
+
+ match_case = wx.CheckBox(self, ID_MATCH_CASE, _("Match Case"),
+ name="MatchCase")
+ match_case.SetValue(self.ctrl.IsMatchCase())
+ self.AddControl(match_case, wx.ALIGN_LEFT)
+ match_case.Show(False) # Hide by default
+
+ ww_cb = wx.CheckBox(self, ID_WHOLE_WORD,
+ _("Whole Word"), name="WholeWord")
+ ww_cb.SetValue(self.ctrl.IsWholeWord())
+ self.AddControl(ww_cb, wx.ALIGN_LEFT)
+
+ regex_cb = wx.CheckBox(self, ID_REGEX, _("Regular Expression"),
+ name="RegEx")
+ regex_cb.SetValue(self.ctrl.IsRegEx())
+ self.AddControl(regex_cb, wx.ALIGN_LEFT)
+
+ # HACK: workaround bug in mac control that resets size to
+ # that of the default variant after any text has been
+ # typed in it. Note it reports the best size as the default
+ # variant and causes layout issues. wxBUG
+ if wx.Platform == '__WXMAC__':
+ self.ctrl.SetSizeHints(180, 16, 180, 16)
+
+ # Event Handlers
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
+ ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED)
+ self._sctrl.RegisterClient(self)
+
+ # Set user customizable layout
+ state = Profile_Get('CTRLBAR', default=dict())
+ cfg = state.get(self.GetConfigKey(), dict())
+ self.SetControlStates(cfg)
+
+ def OnDestroy(self, evt):
+ """Cleanup message handlers on destroy"""
+ if evt.GetId() == self.GetId():
+ ed_msg.Unsubscribe(self.OnThemeChange)
+ self._sctrl.RemoveClient(self)
+
+ def OnButton(self, evt):
+ """Handle button clicks for the next/previous buttons
+ @param evt: wx.CommandEvent
+
+ """
+ e_id = evt.GetId()
+ if e_id in [ID_SEARCH_NEXT, ID_SEARCH_PRE]:
+ self.ctrl.DoSearch(e_id == ID_SEARCH_NEXT)
+ elif e_id == ID_FIND_ALL:
+ self.ctrl.FindAll()
+ else:
+ evt.Skip()
+
+ def OnCheck(self, evt):
+ """Set search options for match case, regex, ect...
+ @param evt: wx.CommandEvent
+
+ """
+ e_id = evt.GetId()
+ if e_id in (ID_MATCH_CASE, ID_REGEX, ID_WHOLE_WORD):
+ ctrl = self.FindWindowById(e_id)
+ if ctrl != None:
+ if e_id == ID_MATCH_CASE:
+ flag = eclib.AFR_MATCHCASE
+ elif e_id == ID_WHOLE_WORD:
+ flag = eclib.AFR_WHOLEWORD
+ else:
+ flag = eclib.AFR_REGEX
+
+ if self.ctrl != None:
+ if ctrl.GetValue():
+ self.ctrl.SetSearchFlag(flag)
+ else:
+ self.ctrl.ClearSearchFlag(flag)
+ else:
+ evt.Skip()
+
+ def NotifyOptionChanged(self, evt):
+ """Callback for L{ed_search.SearchController} to notify of update
+ to the find options.
+ @param evt: eclib.finddlg.FindEvent
+
+ """
+ self.FindWindowById(ID_MATCH_CASE).SetValue(evt.IsMatchCase())
+ self.FindWindowById(ID_REGEX).SetValue(evt.IsRegEx())
+ self.FindWindowById(ID_WHOLE_WORD).SetValue(evt.IsWholeWord())
+
+ def OnThemeChange(self, msg):
+ """Update icons when the theme has changed
+ @param msg: Message Object
+
+ """
+ next_btn = self.FindWindowById(ID_SEARCH_NEXT)
+ if next_btn:
+ t_bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DOWN), wx.ART_MENU)
+ next_btn.SetBitmapLabel(t_bmp)
+ next_btn.SetBitmapHover(t_bmp)
+ next_btn.Update()
+ next_btn.Refresh()
+
+ pre_btn = self.FindWindowById(ID_SEARCH_PRE)
+ if pre_btn:
+ t_bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_UP), wx.ART_MENU)
+ pre_btn.SetBitmapLabel(t_bmp)
+ pre_btn.SetBitmapHover(t_bmp)
+ pre_btn.Update()
+ pre_btn.Refresh()
+
+#-----------------------------------------------------------------------------#
+
+class CommandEntryBar(CommandBarBase):
+ """Commandbar for editor command entry and execution."""
+ class meta:
+ id = ed_glob.ID_COMMAND
+
+ def __init__(self, parent):
+ super(CommandEntryBar, self).__init__(parent)
+
+ # Attributes
+ self.SetControl(CommandExecuter(self, wx.ID_ANY, size=(150, -1)))
+
+ # Setup
+ cmd_lbl = wx.StaticText(self, label=_("Command") + ": ")
+ self.info_lbl = wx.StaticText(self, label="")
+ self.AddControl(cmd_lbl, wx.ALIGN_LEFT)
+ self.AddControl(self.ctrl, 1, wx.ALIGN_LEFT)
+ self.AddControl(self.info_lbl, wx.ALIGN_RIGHT)
+
+ # HACK: workaround bug in mac control that resets size to
+ # that of the default variant after any text has been
+ # typed in it. Note it reports the best size as the default
+ # variant and causes layout issues. wxBUG
+ if wx.Platform == '__WXMAC__':
+ self.ctrl.SetSizeHints(200, 16, -1, 16)
+
+ # Setup
+ self.EnableMenu(False)
+
+#-----------------------------------------------------------------------------#
+
+class GotoLineBar(CommandBarBase):
+ """Commandbar for Goto Line function"""
+ class meta:
+ id = ed_glob.ID_GOTO_LINE
+
+ def __init__(self, parent):
+ super(GotoLineBar, self).__init__(parent)
+
+ # Attributes
+ self.SetControl(LineCtrl(self, wx.ID_ANY,
+ self._parent.nb.GetCurrentCtrl,
+ size=(100, -1)))
+
+ # Setup
+ self.EnableMenu(False)
+ go_lbl = wx.StaticText(self, label=_("Goto Line") + ": ")
+ self.AddControl(go_lbl, wx.ALIGN_LEFT)
+ self.AddControl(self.ctrl, wx.ALIGN_LEFT)
+
+ # HACK: workaround bug in mac control that resets size to
+ # that of the default variant after any text has been
+ # typed in it. Note it reports the best size as the default
+ # variant and causes layout issues. wxBUG
+ if wx.Platform == '__WXMAC__':
+ self.ctrl.SetSizeHints(100, 16, 100, 16)
+
+#-----------------------------------------------------------------------------#
+
+class CommandExecuter(eclib.CommandEntryBase):
+ """Part of the Vi emulation, opens a minibuffer to execute EX commands.
+ @note: based on search ctrl so we get the nice rounded edges on wxmac.
+
+ """
+ RE_GO_BUFFER = re.compile('[0-9]*[nN]{1,1}')
+ RE_GO_WIN = re.compile('[0-9]*n[wW]{1,1}')
+ RE_WGO_BUFFER = re.compile('w[0-9]*[nN]')
+ RE_NGO_LINE = re.compile('[+-][0-9]+')
+
+ def __init__(self, parent, id_, size=wx.DefaultSize):
+ """Initializes the CommandExecuter"""
+ super(CommandExecuter, self).__init__(parent, id_, size=size,
+ style=wx.TE_PROCESS_ENTER|wx.WANTS_CHARS)
+
+ # Attributes
+ self._history = dict(cmds=[''], index=-1, lastval='')
+ if not hasattr(sys, 'frozen'):
+ self._curdir = os.path.abspath(os.curdir) + os.sep
+ else:
+ self._curdir = wx.GetHomeDir() + os.sep
+
+ if wx.Platform == '__WXMAC__':
+ self._popup = PopupList(self)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ else:
+ self._popup = PopupWinList(self)
+
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+ self.Bind(ed_event.EVT_NOTIFY, self.OnPopupNotify)
+
+ # Message handlers
+ ed_msg.Subscribe(self._UpdateCwd, ed_msg.EDMSG_UI_NB_CHANGED)
+ ed_msg.Subscribe(self._UpdateCwd, ed_msg.EDMSG_FILE_SAVED)
+
+ def OnDestroy(self, evt):
+ """Clean up message handlers on destroy"""
+ if evt.GetId() == self.GetId():
+ ed_msg.Unsubscribe(self._UpdateCwd)
+ evt.Skip()
+
+ def _AdjustSize(self):
+ """Checks width of text as its added and dynamically resizes
+ the control as needed.
+ @todo: re-enable after resizing issue can be resolved
+
+ """
+ pass
+# ext = self.GetTextExtent(self.GetValue())[0]
+# curr_w, curr_h = self.GetClientSizeTuple()
+# if ext > curr_w * .5:
+# max_w = self.GetParent().GetClientSize().GetWidth() * .8
+# nwidth = min(ext * 1.3, max_w)
+# pwidth = self._popup.GetBestSize()[0]
+# if pwidth > nwidth:
+# nwidth = pwidth
+# self.SetClientSize((nwidth, curr_h))
+# self._popup.SetSize((nwidth, -1))
+# self.GetParent().Layout()
+# elif ((curr_w > ext * 1.18) and curr_w > 150):
+# nwidth = max(ext * 1.18, 150)
+# self.SetClientSize((nwidth, curr_h))
+# self.GetParent().Layout()
+# else:
+# pass
+
+ def _AdjustValue(self, val):
+ """Adjust value of input string as autocomp provides new values
+ @param val: val to use as base for adjustment
+
+ """
+ cval = self.GetValue().split(' ', 1)
+ if val.startswith(cval[-1]) or val.startswith('~'):
+ self.AppendText(val.replace(cval[-1], '', 1))
+ else:
+ self.SetValue(" ".join([cval[0], val]))
+ self.SetInsertionPoint(self.GetLastPosition())
+
+ def _UpdateCwd(self, msg):
+ """Update the current working directory to that of the current
+ buffer.
+ @param msg: Message Object
+
+ """
+ # Only Update if we are the currently active window
+ tlp = self.GetTopLevelParent()
+ if tlp.IsActive():
+ ctrl = tlp.GetNotebook().GetCurrentCtrl()
+ fname = ctrl.GetFileName()
+ if len(fname):
+ self._curdir = os.path.dirname(fname)
+
+ def ChangeDir(self, cmd):
+ """Change to a directory based on cd command
+ @param cmd: cd path
+
+ """
+ path = cmd.replace('cd', '', 1).strip()
+ if not os.path.isabs(path):
+ if path.startswith('..'):
+ path = os.path.abspath(path)
+ elif path.startswith('~'):
+ path = path.replace('~', wx.GetHomeDir(), 1)
+ else:
+ path = os.path.join(self._curdir, path)
+
+ if os.path.exists(path) and os.path.isdir(path):
+ if os.access(path, os.R_OK):
+ os.chdir(path)
+ self._curdir = os.path.abspath(os.path.curdir) + os.sep
+ else:
+ # Doesn't have permissions
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT,
+ (ed_glob.SB_INFO,
+ _("Can't change directory to: %s") % path))
+ wx.Bell()
+ self.Clear()
+ else:
+ # Invalid path
+ self.Clear()
+ wx.Bell()
+
+ def CommandPush(self, cmd):
+ """Push a command to the stack popping as necessary to
+ keep stack size less than MAX (currently 25 commands).
+ @param cmd: command string to push
+ @todo: redo this to be more like the code in my terminal project
+
+ """
+ cmd = cmd.strip()
+ if not len(cmd):
+ return
+
+ if len(self._history['cmds']) > 25:
+ self._history['cmds'].pop()
+
+ if cmd != self._history['cmds'][0]:
+ self._history['cmds'].insert(0, cmd)
+
+ self._history['index'] = -1
+
+ def EditCommand(self, cmd):
+ """Perform an edit related command
+ @param cmd: command string to execute
+
+ """
+ # e fname: edit file
+ cmd = cmd[1:].strip()
+ frame = self.GetTopLevelParent()
+ cmd = ebmlib.GetPathFromURI(cmd)
+ if not os.path.isabs(cmd):
+ cmd = os.path.join(self._curdir, cmd)
+
+ if ebmlib.PathExists(cmd):
+ frame.DoOpen(ed_glob.ID_COMMAND_LINE_OPEN, cmd)
+ else:
+ frame.nb.OpenPage(ebmlib.GetPathName(cmd), ebmlib.GetFileName(cmd))
+
+ def ExecuteCommand(self, cmd_str):
+ """Interprets and executes a command then hides the control
+ @param cmd_str: Command string to execute
+
+ """
+ frame = self.GetTopLevelParent()
+ cmd = cmd_str.strip().lstrip(':')
+ if cmd in ['x', 'ZZ']:
+ cmd = 'wq'
+
+ if cmd.startswith(u'w'):
+ frame.OnSave(wx.MenuEvent(wx.wxEVT_COMMAND_MENU_SELECTED,
+ ed_glob.ID_SAVE))
+ if self.RE_WGO_BUFFER.match(cmd):
+ self.GoBuffer(cmd[1:])
+ elif cmd == 'wq':
+ self.Quit()
+ elif cmd.startswith(u'e '):
+ self.EditCommand(cmd)
+ elif cmd.rstrip() == u'e!':
+ ctrl = frame.nb.GetCurrentCtrl()
+ ctrl.RevertToSaved()
+ elif self.RE_GO_WIN.match(cmd):
+ self.GoWindow(cmd)
+ elif re.match(self.RE_GO_BUFFER, cmd):
+ self.GoBuffer(cmd)
+ elif cmd.isdigit() or self.RE_NGO_LINE.match(cmd):
+ ctrl = frame.nb.GetCurrentCtrl()
+ cline = ctrl.GetCurrentLine()
+ if cmd[0] in '+-':
+ line = eval("%s %s %s" % (str(cline), cmd[0], cmd[1:]))
+ else:
+ line = int(cmd) - 1
+ ctrl.GotoLine(line)
+ elif cmd.startswith('cd '):
+ self.ChangeDir(cmd)
+ elif cmd == 'q':
+ self.Quit()
+ else:
+ wx.Bell()
+ return
+
+ self.CommandPush(cmd_str)
+ self.GetParent().Hide()
+
+ def GetHistCommand(self, pre=True):
+ """Look up a command from the history of recent commands
+ @param pre: Get previous (default) or get Next
+ @note: pre moves right in stack, next moves left in stack
+
+ """
+ val = self.GetValue().strip()
+ if val not in self._history['cmds']:
+ self._history['lastval'] = val
+
+ if pre:
+ if self._history['index'] < len(self._history['cmds']) - 1\
+ and self._history['index'] < 25:
+ self._history['index'] += 1
+
+ index = self._history['index']
+ cmd = self._history['cmds'][index]
+ else:
+ if self._history['index'] > -1:
+ self._history['index'] -= 1
+
+ index = self._history['index']
+ if index == -1:
+ cmd = self._history['lastval']
+ else:
+ cmd = self._history['cmds'][index]
+
+ self.SetValue(cmd)
+ self.SelectAll()
+
+ def GoBuffer(self, cmd):
+ """Go to next/previous buffer in notebook
+ @param cmd: cmd string [0-9]*[nN]
+
+ """
+ count = cmd[0:-1]
+ cmd = cmd[-1]
+ if count.isdigit():
+ count = int(count)
+ else:
+ count = 1
+
+ frame = self.GetTopLevelParent()
+ numpage = frame.nb.GetPageCount()
+ for x in range(min(count, numpage)):
+ cpage = frame.nb.GetPageIndex(frame.nb.GetCurrentPage())
+ if (cpage == 0 and cmd == 'N') or \
+ (cpage + 1 == numpage and cmd == 'n'):
+ break
+ frame.nb.AdvanceSelection(cmd == 'n')
+
+ def GoWindow(self, cmd):
+ """Go to next/previous open window
+ @param cmd: cmd string [0-9]*n[wW]
+
+ """
+ count = cmd[0:-1]
+ cmd = cmd[-1]
+ if count.isdigit():
+ count = int(count)
+ else:
+ count = 1
+ wins = wx.GetApp().GetMainWindows()
+ pid = self.GetTopLevelParent().GetId()
+ widx = 0
+ win = 0
+ for nwin in xrange(len(wins)):
+ if pid == wins[nwin].GetId():
+ widx = pid
+ win = nwin
+ break
+
+ if cmd == 'W':
+ widx = win + count
+ else:
+ widx = win - count
+
+ if widx < 0:
+ widx = 0
+ elif widx >= len(wins):
+ widx = len(wins) - 1
+ self.GetParent().Hide()
+ wins[widx].Raise()
+ wx.CallAfter(wins[widx].nb.GetCurrentCtrl().SetFocus)
+
+ def GetPaths(self, path, files=False):
+ """Get a list of paths that are part of the given path by
+ default it will only return directories.
+ @param path: Path to enumerate
+ @keyword files: Get list of files too
+
+ """
+ def append_slash(path):
+ """Helper function that appends a slash to the path
+ if it's a directory.
+
+ """
+ if os.path.isdir(path) and not path.endswith(os.sep):
+ return path + os.sep
+ return path
+
+ curdir = self._curdir
+ head, tail = os.path.split(path)
+ head = os.path.expanduser(head)
+ head = os.path.expandvars(head)
+ head = os.path.join(curdir, head)
+ if not os.path.isdir(head):
+ return []
+
+ # Return empty list of user does not have
+ # read access to the directory
+ if not os.access(head, os.R_OK):
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT,
+ (ed_glob.SB_INFO,
+ _("Access Denied: %s") % head))
+ wx.Bell() # Beep to alert
+ return list()
+
+ # We expanded head, so trim the suggestion list of its head
+ # so we can add the tail of the suggestion back to the original head
+ try:
+ candidates = [os.path.basename(p) for p in os.listdir(head)
+ if p.startswith(tail)]
+ candidates = [append_slash(os.path.join(os.path.dirname(path), cand))
+ for cand in candidates]
+ if not files:
+ candidates = [cand for cand in candidates if os.path.isdir(cand)]
+ except OSError:
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT,
+ (ed_glob.SB_INFO, _("Invalid Path")))
+ candidates = list()
+
+ return sorted(list(set(candidates)))
+
+ def ListDir(self):
+ """List the next directory from the current cmd path"""
+ cmd = self.GetValue()
+ if cmd.startswith('cd '):
+ cstr = 'cd '
+ elif cmd.startswith('e '):
+ cstr = 'e '
+ else:
+ return
+
+ cmd = cmd.replace(cstr, u'', 1).strip()
+ paths = self.GetPaths(cmd, cstr == 'e ')
+ self._popup.SetChoices(paths)
+ if len(paths):
+ self._popup.SetupPosition(self)
+ if not self._popup.IsShown():
+ self._popup.Show()
+
+ self.SetInsertionPoint(self.GetLastPosition())
+
+ def OnEnter(self, evt):
+ """Get the currently entered command string and execute it.
+ @postcondition: ctrl is cleared and command is executed
+
+ """
+ if self._popup.HasSuggestions() and self._popup.HasSelection():
+ psel = self._popup.GetSelection()
+ if self.GetValue().split(' ', 1)[-1].strip() != psel:
+ self._AdjustValue(psel)
+ self._popup.Hide()
+ return
+
+ cmd = self.GetValue()
+ self.Clear()
+ self.ExecuteCommand(cmd)
+ if self._popup.IsShown():
+ self._popup.Hide()
+
+ def OnKeyDown(self, evt):
+ """Records the key sequence that has been entered and
+ performs actions based on that key sequence.
+ @param evt: event that called this handler
+
+ """
+ e_key = evt.GetKeyCode()
+ cmd = self.GetValue()
+
+ if e_key == wx.WXK_UP:
+ if self._popup.HasSuggestions():
+ self._popup.AdvanceSelection(False)
+ else:
+ self.GetHistCommand(pre=True)
+ elif e_key == wx.WXK_DOWN:
+ if self._popup.HasSuggestions():
+ self._popup.AdvanceSelection(True)
+ else:
+ self.GetHistCommand(pre=False)
+ elif e_key == wx.WXK_SPACE and not len(cmd):
+ # Swallow space key when command is empty
+ pass
+ elif e_key == wx.WXK_TAB:
+ # Provide Tab Completion or swallow key
+ if cmd.startswith('cd ') or cmd.startswith('e '):
+ if self._popup.HasSuggestions():
+ self._AdjustValue(self._popup.GetSelection())
+ self.ListDir()
+ else:
+ pass
+ elif e_key == wx.WXK_ESCAPE:
+ if self._popup.IsShown():
+ self._popup.Hide()
+ else:
+ self.Clear()
+ self.GetParent().Hide()
+ else:
+ evt.Skip()
+
+ def OnKeyUp(self, evt):
+ """Adjust size as needed when characters are entered
+ @param evt: event that called this handler
+
+ """
+ e_key = evt.GetKeyCode()
+ if e_key == wx.WXK_ESCAPE:
+ evt.Skip()
+ return
+
+ val = self.GetValue()
+ cwd_info = ""
+ if val.strip() in ['cwd', 'e', 'cd']:
+ cwd_info = " " + _(u"cwd: ") + self._curdir
+ self.Parent.info_lbl.SetLabel(cwd_info)
+ if self._popup.IsShown():
+ if not len(val):
+ self._popup.Hide()
+ else:
+ wx.CallAfter(self.UpdateAutoComp)
+ else:
+ if self._popup.HasSuggestions():
+ self._AdjustValue(self._popup.GetSelection())
+ self.ListDir()
+ self._AdjustSize()
+ evt.Skip()
+
+ def OnPopupNotify(self, evt):
+ """Receive the selections from the popup list
+ @param evt: event that called this handler
+
+ """
+ val = evt.GetValue()
+ self._AdjustValue(val)
+
+ def OnKillFocus(self, evt):
+ """Hide the popup when we look focus
+ @param evt: event that called this handler
+
+ """
+ self._popup.Hide()
+ evt.Skip()
+
+ def OnSetFocus(self, evt):
+ """Ensure caret is at end when focus is reset
+ @param evt: event that called this handler
+
+ """
+ self.SetInsertionPoint(self.GetLastPosition())
+ evt.Skip()
+
+ def RestoreFocus(self):
+ """Restore focus and cursor position
+ @postcondition: ctrl has focus and cursor is moved to last position
+
+ """
+ self.SetInsertionPoint(self.GetLastPosition())
+ self.SetFocus()
+
+ def Quit(self):
+ """Tell the editor to exit
+ @postcondition: Editor begins exit, confirming file saves
+
+ """
+ wx.PostEvent(self.GetTopLevelParent(),
+ wx.CloseEvent(wx.wxEVT_CLOSE_WINDOW))
+
+ def SetValue(self, value):
+ """Overrides the controls default function to allow for automatic
+ resizing of the control when text is added.
+ @param value: string to set value of control to
+
+ """
+ super(CommandExecuter, self).SetValue(value)
+ self._AdjustSize()
+
+ def UpdateAutoComp(self):
+ """Update the autocomp list for paths that best match current value"""
+ self.ListDir()
+
+ def WriteCommand(self, cstr):
+ """Perform a file write related command
+ @param cstr: The command string to execute
+
+ """
+ # wn: write and edit next
+ # wN: write and edit previous
+ # wq: write and quit
+
+#-----------------------------------------------------------------------------#
+
+class LineCtrl(eclib.CommandEntryBase):
+ """A custom int control for providing a go To line control
+ for the Command Bar.
+
+ """
+ def __init__(self, parent, id_, get_doc, size=wx.DefaultSize):
+ """Initializes the LineCtrl control and its attributes.
+ @param parent: Parent Window
+ @param id_: Control ID
+ @param get_doc: callback method for retrieving a reference to the
+ current document.
+ @keyword size: Control Size (tuple)
+
+ """
+ super(LineCtrl, self).__init__(parent, id_, u"", size=size,
+ style=wx.TE_PROCESS_ENTER,
+ validator=util.IntValidator(0, 65535))
+
+ # Attributes
+ self._last = 0
+ self.GetDoc = get_doc
+
+ def OnEnter(self, evt):
+ """Processes the entered line number
+ @param evt: wx.EVT_TEXT_ENTER
+
+ """
+ val = self.GetValue()
+ if not val.isdigit():
+ return
+
+ val = int(val) - 1
+ doc = self.GetDoc()
+ lines = doc.GetLineCount()
+ if val > lines:
+ val = lines
+ doc.GotoLine(val)
+ doc.SetFocus()
+ self.GetParent().Hide()
+
+ def OnKeyUp(self, evt):
+ """Handle keyup events"""
+ if evt.GetEventType() != wx.wxEVT_KEY_UP:
+ evt.Skip()
+ return
+
+ e_key = evt.GetKeyCode()
+ if e_key == wx.WXK_ESCAPE:
+ # TODO change to more safely determine the context
+ # Currently control is only used in command bar
+ self.GetParent().Hide()
+ else:
+ evt.Skip()
+
+#-----------------------------------------------------------------------------#
+# TODO: merge the common parts of these two classes into a single base class
+
+class PopupListBase(object):
+ """Common functionality between Popuplist GTK and Mac"""
+
+ def AdvanceSelection(self, next=True):
+ """Advance the list selection
+ @keyword next: goto the next or previous selection
+
+ """
+ sel = self._list.GetSelection()
+ if next:
+ count = self._list.GetCount()
+ sel += 1
+ if sel < count:
+ self._list.SetSelection(sel)
+ else:
+ sel -= 1
+ if sel >= 0:
+ self._list.SetSelection(sel)
+
+ def GetSelection(self):
+ """Get the string that is currently selected in the list
+ @return: string selection
+
+ """
+ return self._list.GetStringSelection()
+
+ def HasSelection(self):
+ """Tells whether anything in the list is selected"""
+ return self._list.GetSelection() != wx.NOT_FOUND
+
+ def HasSuggestions(self):
+ """Tell whether the list is showing suggestions"""
+ return self.IsShown() and self.ListCount() > 0
+
+ def ListCount(self):
+ """return the number of elements in the popup list"""
+ return self._list.GetCount()
+
+ def GetListCtrl(self):
+ """Get the ListBox control of the popupwindow"""
+ return self._list
+
+ def GetChoices(self):
+ """Get the items as a list
+ @return: list of strings
+
+ """
+ return self._list.GetStrings()
+
+ def SetSelection(self, index):
+ """Set the selection in the list by index
+ @param index: zero based index to set selection by
+
+ """
+ self._list.SetSelection(index)
+
+class PopupList(wx.MiniFrame, PopupListBase):
+ """Popup window with a listbox in it"""
+ def __init__(self, parent, choices=list(), pos=wx.DefaultPosition):
+
+ style = wx.FRAME_NO_TASKBAR | wx.FRAME_FLOAT_ON_PARENT
+ if wx.Platform == '__WXMAC__':
+ style = style | wx.BORDER_NONE | wx.POPUP_WINDOW
+ else:
+ style = style | wx.SIMPLE_BORDER
+
+ wx.MiniFrame.__init__(self, parent, pos=pos, style=style)
+ PopupListBase.__init__(self)
+
+ # Attributes
+ self._list = wx.ListBox(self, choices=choices,
+ style=wx.LC_REPORT | wx.LC_SINGLE_SEL |
+ wx.LC_NO_HEADER | wx.NO_BORDER)
+
+ # Layout
+ self._list.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+ self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(self._list, 1, wx.EXPAND)
+ self.SetSizer(sizer)
+ txt_h = self.GetTextExtent('/')[1]
+ self.SetMaxSize((-1, txt_h * 6))
+ self.SetAutoLayout(True)
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHAR, lambda evt: parent.GetEventHandler().ProcessEvent(evt))
+ self.Bind(wx.EVT_SET_FOCUS, self.OnFocus)
+ self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnSelection)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self._list.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+
+ self._list.SetFocus()
+ self.Hide()
+
+ def __PostEvent(self):
+ """Post notification of selection to parent
+ @postcondition: selected string is posted to parent
+
+ """
+ val = self._list.GetStringSelection()
+ evt = ed_event.NotificationEvent(ed_event.edEVT_NOTIFY,
+ self.GetId(), val, self._list)
+ wx.PostEvent(self.GetParent(), evt)
+ self.ActivateParent()
+
+ def ActivateParent(self):
+ """Activate the parent window
+ @postcondition: parent window is raised
+
+ """
+ parent = self.GetParent()
+ parent.Raise()
+ parent.SetFocus()
+
+ def OnFocus(self, evt):
+ """Raise and reset the focus to the parent window whenever
+ we get focus.
+ @param evt: event that called this handler
+
+ """
+ self.ActivateParent()
+ self.GetParent().SetFocus()
+ evt.Skip()
+
+ def OnKeyUp(self, evt):
+ """Process key up events in the control
+ @param evt: event that called this handler
+
+ """
+ if evt.GetKeyCode() == wx.WXK_RETURN:
+ self.__PostEvent()
+ else:
+ evt.Skip()
+
+ def OnSelection(self, evt):
+ """Handle a selection in list by posting the result to
+ the parent.
+ @param evt: Event that called this handler
+
+ """
+ self.__PostEvent()
+
+ def OnSize(self, evt):
+ """Resize the listbox"""
+ csz = self.GetClientSize()
+ csz.SetWidth(csz.x + wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X))
+ self._list.SetSize(csz)
+ evt.Skip()
+
+ def Show(self, show=True):
+ """Adjust size of popup and then show it
+ @keyword show: Should the window be shown or not
+
+ """
+ res = super(PopupList, self).Show(show)
+
+ if res and show:
+ self.ActivateParent()
+
+ if wx.Platform == '__WXMAC__':
+ self.GetParent().Refresh(False)
+
+ return res
+
+ def SetChoices(self, choices):
+ """Set the available choices that are shown in the list
+ @param choices: list of strings
+
+ """
+ selection = self._list.GetSelection()
+ self._list.SetItems(choices)
+ count = self._list.GetCount()
+ if selection == wx.NOT_FOUND or selection >= count:
+ selection = 0
+ if count > 0:
+ self._list.SetSelection(selection)
+
+ def SetStringSelection(self, text):
+ """Set the list selection by using a string value
+ @param text: string to select in list
+
+ """
+ self._list.SetStringSelection(text)
+
+ def SetupPosition(self, cmd_ex):
+ """Sets size and position of widget
+ @param cmd_ex: CommandExecuter window
+
+ """
+ cmd = cmd_ex.GetValue()
+ cmd = cmd.split(u' ', 1)[0]
+ xpos = cmd_ex.GetTextExtent(cmd + u' ')[0]
+ pos = cmd_ex.GetScreenPosition().Get()
+ csize = cmd_ex.GetSize()
+ self.SetPosition((pos[0] + xpos, pos[1] + csize[1]))
+ self.ActivateParent()
+
+#----------------------------------------------------------------------------#
+
+class PopupWinList(wx.PopupWindow, PopupListBase):
+ """Popuplist for Windows/GTK"""
+ def __init__(self, parent, choices=list(), pos=wx.DefaultPosition):
+ """Create the popup window and its list control"""
+ wx.PopupWindow.__init__(self, parent)
+ PopupListBase.__init__(self)
+
+ # Attributes
+ self._list = wx.ListBox(self, choices=choices, pos=(0, 0),
+ style=wx.LC_REPORT | wx.LC_SINGLE_SEL |
+ wx.LC_NO_HEADER)
+
+ # Layout
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(self._list, 0, wx.EXPAND)
+ self.SetSizer(sizer)
+ txt_h = self.GetTextExtent('/')[1]
+ self.SetMaxSize((-1, txt_h * 6))
+ self.SetAutoLayout(True)
+
+ # Event Handlers
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ def OnSize(self, evt):
+ """Resize the list box to the correct size to fit."""
+ csz = self.GetClientSize()
+ csz.SetWidth(csz.x + wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X))
+ self._list.SetSize(csz)
+ evt.Skip()
+
+ def SetupPosition(self, cmd_ex):
+ """Sets size and position of widget
+ @param cmd_ex: CommandExecuter window
+
+ """
+ cmd = cmd_ex.GetValue()
+ cmd = cmd.split(u' ', 1)[0]
+ pos = cmd_ex.GetScreenPosition().Get()
+ csize = cmd_ex.GetSize()
+ xpos = cmd_ex.GetTextExtent(cmd)[0]
+ self._list.SetInitialSize()
+ self.SetInitialSize()
+ self.SetPosition((pos[0] + xpos, pos[1] + csize[1]))
+
+ def SetChoices(self, choices):
+ """Set the available choices that are shown in the list
+ @param choices: list of strings
+
+ """
+ selection = self._list.GetSelection()
+ self._list.SetItems(choices)
+ count = self._list.GetCount()
+ if selection == wx.NOT_FOUND or selection >= count:
+ selection = 0
+ if count > 0:
+ self._list.SetSelection(selection)
+
+ def Show(self, show=True):
+ """Adjust size of popup and then show it
+ @keyword show: Should the window be shown or not
+
+ """
+ res = super(PopupWinList, self).Show(show)
+
+ self._list.Show()
+ self._list.SetInitialSize()
+ self.SetInitialSize()
+
+ return res
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_crypt.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_crypt.py
new file mode 100644
index 0000000..cec2215
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_crypt.py
@@ -0,0 +1,120 @@
+###############################################################################
+# Name: ed_crypt.py #
+# Purpose: Cryptography Library for encrypting/decrypting saved data #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This module provides utilities for encrypting and decrypting data. It is mostly
+used for saving passwords and other sensitive data in config files. The code in
+this file uses a fairly simple string transformation algorithm combined with a
+random salt for the encryption/decryption, and I also threw in a little code
+obfustication just for fun ;-).
+
+USAGE:
+
+Encrypt:
+ 1. Get the password string to encrypt
+ 2. Generate a new random salt with os.urandom() or some other randomly
+ generated string for each password to use as an encryption key
+ 3. Encrypt the password by calling Encrypt(password, salt)
+ 4. Save the salt somewhere else
+ 5. Write out the encrypted password to your config file
+
+Decrypt:
+ 1. Get the encrypted password string
+ 2. Get the associated salt
+ 3. Decrypt and get the orignal password by calling
+ Decrypt(encrypted_passwd, salt)
+
+EXAMPLE:
+
+ >>> salt = os.urandom(8)
+ >>> passwd = "HelloWorld"
+ >>> encrypted_passwd = Encrypt(passwd, salt)
+ >>> print encrypted_passwd
+ eNoNysERADAIArCVUAFx/8XauzyTqTEtdKEXoQIWCbCZjaM74qhPlhK4f+BVPKTTyQP7JQ5i
+ >>> decrypted_passwd = Decrypt(passwd, salt)
+ >>> print decrypted_passwd
+ HelloWorld
+
+Finally:
+This message will self destruct in 5 seconds ...
+
+@summary: Cryptographic routines for encrypting/decrypting text
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_crypt.py 52855 2008-03-27 14:53:06Z CJP $"
+__revision__ = "$Revision: 52855 $"
+
+__all__ = [ 'Encrypt', 'Decrypt' ]
+
+#-----------------------------------------------------------------------------#
+# Import
+import os
+import zlib
+import random
+import base64
+
+#-----------------------------------------------------------------------------#
+# Private Functions
+
+def _Encode(text):
+ g = lambda y: (y!='\\' and [y] or [str(8+(random.randint(0,100)%2))])[0]
+ return ''.join([g(y) for y in ''.join(['\\%o'%ord(x) for x in text])])
+
+def _Decode(text):
+ exec 's="'+text.replace('8','\\').replace('9','\\')+'"'
+ return s
+
+#-----------------------------------------------------------------------------#
+# Public Functions
+
+def Encrypt(passwd, salt):
+ """Encrypt the given password string using the supplied salt as the
+ cryptographic key. If either the passwd or salt strings are empty the
+ return value will be the same as the passwd parameter.
+ @param passwd: String to encrypt
+ @param salt: key to encrypt string with
+
+ """
+ if not len(passwd.strip()) or not len(salt.strip()):
+ return passwd
+ else:
+ return base64.b64encode(zlib.compress(str(long(_Encode(passwd))*\
+ long(_Encode(salt).replace('8','9'))),9))
+
+def Decrypt(passwd, salt):
+ """Decrypt the given password string using the supplied salt as a key
+ If either the passwd or salt strings are empty the return value will be
+ the same as the passwd parameter.
+ @param passwd: a non empty string
+ @param salt: a non empty string
+
+ """
+ if not len(passwd.strip()) or not len(salt.strip()):
+ return passwd
+ else:
+ return _Decode(str(long(zlib.decompress(base64.b64decode(passwd)))/\
+ long(str.replace(_Encode(salt),'8','9'))))
+
+#-----------------------------------------------------------------------------#
+# Test
+if __name__ == '__main__':
+ TEST_FILE = "TEST_passwd.crypt"
+ PASSWD = 'HelloWorld'
+ salt = os.urandom(8)
+ print "PASSWORD STR: ", PASSWD
+ es = Encrypt(PASSWD, salt)
+ print "ENCRYPTED STR: ", es
+ print "DECRYPTED STR: ", Decrypt(es, salt)
+
+ print "Empty String Test"
+ salt2 = os.urandom(8)
+ es = Encrypt('', salt2)
+ print "Encrypted String", es
+ print "Decrypted String", Decrypt(es, salt)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_editv.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_editv.py
new file mode 100644
index 0000000..9d7a024
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_editv.py
@@ -0,0 +1,641 @@
+###############################################################################
+# Name: ed_editv.py #
+# Purpose: Editor view notebook tab implementation #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Text editor buffer view control for the main notebook
+
+@summary: Editor view
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_editv.py 72901 2012-11-05 15:19:28Z CJP $"
+__revision__ = "$Revision: 72901 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+import os
+
+# Editra Libraries
+import ed_glob
+import ed_menu
+import ed_msg
+import ed_stc
+import ed_tab
+from doctools import DocPositionMgr
+from profiler import Profile_Get
+from util import Log, SetClipboardText
+import syntax.synglob as synglob
+from ebmlib import GetFileModTime, ContextMenuManager, GetFileName
+
+# External libs
+from extern.stcspellcheck import STCSpellCheck
+
+#--------------------------------------------------------------------------#
+
+ID_SPELL_1 = wx.NewId()
+ID_SPELL_2 = wx.NewId()
+ID_SPELL_3 = wx.NewId()
+
+_ = wx.GetTranslation
+
+def modalcheck(func):
+ """Decorator method to add extra modality guards to functions that
+ show modal dialogs. Arg 0 must be a Window instance.
+
+ """
+ def WrapModal(*args, **kwargs):
+ """Wrapper method to guard against multiple dialogs being shown"""
+ self = args[0]
+ self._has_dlg = True
+ func(*args, **kwargs)
+ self._has_dlg = False
+
+ WrapModal.__name__ = func.__name__
+ WrapModal.__doc__ = func.__doc__
+ return WrapModal
+
+#--------------------------------------------------------------------------#
+
+class EdEditorView(ed_stc.EditraStc, ed_tab.EdTabBase):
+ """Tab editor view for main notebook control."""
+ ID_NO_SUGGEST = wx.NewId()
+ ID_ADD_TO_DICT = wx.NewId()
+ ID_IGNORE = wx.NewId()
+ ID_SPELLING_MENU = wx.NewId()
+ ID_CLOSE_TAB = wx.NewId()
+ ID_CLOSE_ALL_TABS = wx.NewId()
+ DOCMGR = DocPositionMgr()
+
+ def __init__(self, parent, id_=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, use_dt=True):
+ """Initialize the editor view"""
+ ed_stc.EditraStc.__init__(self, parent, id_, pos, size, style, use_dt)
+ ed_tab.EdTabBase.__init__(self)
+
+ # Attributes
+ self._ro_img = False
+ self._ignore_del = False
+ self._has_dlg = False
+ self._lprio = 0 # Idle event priority counter
+ self._menu = ContextMenuManager()
+ self._spell = STCSpellCheck(self, check_region=self.IsNonCode)
+ self._caret_w = 1
+ self._focused = True
+ spref = Profile_Get('SPELLCHECK', default=dict())
+ self._spell_data = dict(choices=list(),
+ word=('', -1, -1),
+ enabled=spref.get('auto', False))
+
+ # Initialize the classes position manager for the first control
+ # that is created only.
+ if not EdEditorView.DOCMGR.IsInitialized():
+ EdEditorView.DOCMGR.InitPositionCache(ed_glob.CONFIG['CACHE_DIR'] + \
+ os.sep + u'positions')
+
+ self._spell.clearAll()
+ self._spell.setDefaultLanguage(spref.get('dict', 'en_US'))
+ self._spell.startIdleProcessing()
+
+ # Context Menu Events
+ self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
+
+ # Need to relay the menu events from the context menu to the top level
+ # window to be handled on gtk. Other platforms don't require this.
+ self.Bind(wx.EVT_MENU, self.OnMenuEvent)
+
+ # Hide autocomp/calltips when window looses focus
+ # TODO: decide on whether this belongs in base class or not
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_LEFT_UP, self.OnSetFocus)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+
+ # Subscribe for configuration updates
+ for opt in ('AUTOBACKUP', 'SYNTHEME', 'SYNTAX', 'BRACKETHL', 'GUIDES',
+ 'SHOW_EDGE', 'EDGE', 'CODE_FOLD', 'AUTO_COMP',
+ 'AUTO_INDENT', 'HLCARETLINE', 'SPELLCHECK', 'VI_EMU',
+ 'VI_NORMAL_DEFAULT', 'USETABS', 'TABWIDTH', 'INDENTWIDTH',
+ 'BSUNINDENT', 'EOL_MODE', 'AALIASING', 'SHOW_EOL', 'SHOW_LN',
+ 'SHOW_WS', 'WRAP', 'VIEWVERTSPACE'):
+ ed_msg.Subscribe(self.OnConfigMsg,
+ ed_msg.EDMSG_PROFILE_CHANGE + (opt,))
+
+ def OnDestroy(self, evt):
+ """Cleanup message handlers on destroy"""
+ if evt.Id == self.Id:
+ ed_msg.Unsubscribe(self.OnConfigMsg)
+ evt.Skip()
+
+ #---- EdTab Methods ----#
+
+ def DoDeactivateTab(self):
+ """Deactivate any active popups when the tab is no longer
+ the active tab.
+
+ """
+ self._menu.Clear()
+ self.HidePopups()
+
+ def DoOnIdle(self):
+ """Check if the file has been modified and prompt a warning"""
+ # Don't check while the file is loading
+ if self.IsLoading():
+ return
+
+ # Handle hiding and showing the caret when the window gets loses focus
+ cfocus = self.FindFocus()
+ if not self._focused and cfocus is self:
+ # Focus has just returned to the window
+ self.RestoreCaret()
+ self._focused = True
+ elif self._focused and cfocus is not self:
+ self.HideCaret() # Hide the caret when not active
+ self._focused = False
+ self.CallTipCancel()
+
+ # Check for changes to on disk file
+ if not self._has_dlg and Profile_Get('CHECKMOD'):
+ cfile = self.GetFileName()
+ lmod = GetFileModTime(cfile)
+ mtime = self.GetModTime()
+ if mtime and not lmod and not os.path.exists(cfile):
+ # File was deleted since last check
+ wx.CallAfter(self.PromptToReSave, cfile)
+ elif mtime < lmod:
+ # Check if we should automatically reload the file or not
+ if Profile_Get('AUTO_RELOAD', default=False) and \
+ not self.GetModify():
+ wx.CallAfter(self.DoReloadFile)
+ else:
+ wx.CallAfter(self.AskToReload, cfile)
+
+ # Check for changes to permissions
+ if self.File.IsReadOnly() != self._ro_img:
+ self._nb.SetPageBitmap(self.GetTabIndex(), self.GetTabImage())
+ self._nb.Refresh()
+ else:
+ pass
+
+ # Handle Low(er) priority idle events
+ self._lprio += 1
+ if self._lprio == 2:
+ self._lprio = 0 # Reset counter
+ # Do spell checking
+ # TODO: Add generic subscriber hook and move spell checking and
+ # and other low priority idle handling there
+ if self.IsShown():
+ if self._spell_data['enabled']:
+ self._spell.processCurrentlyVisibleBlock()
+ else:
+ # Ensure calltips are not shown when this is a background tab.
+ self.CallTipCancel()
+
+ @modalcheck
+ def DoReloadFile(self):
+ """Reload the current file"""
+ cfile = self.GetFileName()
+ ret = True
+ rmsg = u""
+ try:
+ ret, rmsg = self.ReloadFile()
+ except Exception, msg:
+ # Unexpected error
+ wx.MessageBox(_("Failed to reload file\n\nError:\n%s") % msg,
+ _("File read error"), wx.ICON_ERROR|wx.OK|wx.CENTER)
+ # Set modtime to prevent re-prompting of dialog regardless of error cases
+ self.SetModTime(GetFileModTime(cfile))
+ return
+
+ # Check for expected errors
+ if not ret:
+ errmap = dict(filename=cfile, errmsg=rmsg)
+ mdlg = wx.MessageDialog(self,
+ _("Failed to reload %(filename)s:\n"
+ "Error: %(errmsg)s") % errmap,
+ _("Error"),
+ wx.OK | wx.ICON_ERROR)
+ mdlg.ShowModal()
+ mdlg.Destroy()
+
+ # Set modtime to prevent re-prompting of dialog regardless of error cases
+ self.SetModTime(GetFileModTime(cfile))
+
+ def DoTabClosing(self):
+ """Save the current position in the buffer to reset on next load"""
+ if len(self.GetFileName()) > 1:
+ EdEditorView.DOCMGR.AddRecord([self.GetFileName(),
+ self.GetCurrentPos()])
+
+ def DoTabOpen(self, ):
+ """Called to open a new tab"""
+ pass
+
+ def DoTabSelected(self):
+ """Performs updates that need to happen when this tab is selected"""
+ Log("[ed_editv][info] Tab has file: %s" % self.GetFileName())
+ self.PostPositionEvent()
+
+ def GetName(self):
+ """Gets the unique name for this tab control.
+ @return: (unicode) string
+
+ """
+ return u"EditraTextCtrl"
+
+ def GetTabImage(self):
+ """Get the Bitmap to use for the tab
+ @return: wx.Bitmap (16x16)
+
+ """
+ if self.GetDocument().ReadOnly:
+ self._ro_img = True
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_READONLY), wx.ART_MENU)
+ else:
+ self._ro_img = False
+ lang_id = str(self.GetLangId())
+ bmp = wx.ArtProvider.GetBitmap(lang_id, wx.ART_MENU)
+ if bmp.IsNull():
+ bmp = wx.ArtProvider.GetBitmap(str(synglob.ID_LANG_TXT), wx.ART_MENU)
+ return bmp
+
+ def GetTabMenu(self):
+ """Get the tab menu
+ @return: wx.Menu
+ @todo: move logic from notebook to here
+ @todo: generalize generic actions to base class (close, new, etc..)
+
+ """
+ ptxt = self.GetTabLabel()
+
+ menu = ed_menu.EdMenu()
+ menu.Append(ed_glob.ID_NEW, _("New Tab"))
+ menu.Append(ed_glob.ID_MOVE_TAB, _("Move Tab to New Window"))
+ menu.AppendSeparator()
+ menu.Append(ed_glob.ID_SAVE, _("Save \"%s\"") % ptxt)
+ menu.Append(EdEditorView.ID_CLOSE_TAB, _("Close \"%s\"") % ptxt)
+ menu.Append(ed_glob.ID_CLOSE_OTHERS, _("Close Other Tabs"))
+ menu.Append(EdEditorView.ID_CLOSE_ALL_TABS, _("Close All"))
+ menu.AppendSeparator()
+ menu.Append(ed_glob.ID_COPY_FILE, _("Copy Filename"))
+ menu.Append(ed_glob.ID_COPY_PATH, _("Copy Full Path"))
+ return menu
+
+ def GetTitleString(self):
+ """Get the title string to display in the MainWindows title bar
+ @return: (unicode) string
+
+ """
+ fname = self.GetFileName()
+ title = os.path.split(fname)[-1]
+
+ # Its an unsaved buffer
+ if not len(title):
+ title = fname = self.GetTabLabel()
+
+ if self.GetModify() and not title.startswith(u'*'):
+ title = u"*" + title
+ return u"%s - file://%s" % (title, fname)
+
+ def CanCloseTab(self):
+ """Called when checking if tab can be closed or not
+ @return: bool
+
+ """
+ if self._ignore_del:
+ self._ignore_del = False
+ return True
+
+ result = True
+ if self.GetModify():
+ result = self.ModifySave()
+ result = result in (wx.ID_YES, wx.ID_OK, wx.ID_NO)
+ if result:
+ self._ignore_del = True
+
+ return result
+
+ def OnSetFocus(self, evt):
+ """Make sure that the currently selected tab is this one"""
+ evt.Skip()
+ parent = self.GetParent()
+ csel = parent.GetSelection()
+ idx = self.GetTabIndex()
+ if csel != idx:
+ parent.SetSelection(idx)
+
+ def OnSpelling(self, buff, evt):
+ """Context menu subscriber callback
+ @param buff: buffer menu event happened in
+ @param evt: MenuEvent
+
+ """
+ e_id = evt.Id
+ spelld = self._spell.getSpellingDictionary()
+ if e_id == EdEditorView.ID_ADD_TO_DICT:
+ # Permanently add to users spelling dictionary
+ if spelld:
+ spelld.add(self._spell_data['word'][0])
+ self.RefreshSpellcheck()
+ elif e_id == EdEditorView.ID_IGNORE:
+ # Ignore spelling for this session
+ if spelld:
+ spelld.add_to_session(self._spell_data['word'][0])
+ self.RefreshSpellcheck()
+ else:
+ replace = None
+ for choice in self._spell_data['choices']:
+ if e_id == choice[0]:
+ replace = choice[1]
+ break
+
+ if replace is not None:
+ buff.SetTargetStart(self._spell_data['word'][1])
+ buff.SetTargetEnd(self._spell_data['word'][2])
+ buff.ReplaceTarget(replace)
+
+ def RefreshSpellcheck(self):
+ """Refresh the visible text area for spellchecking"""
+ fline = self.GetFirstVisibleLine()
+ first = self.GetLineStartPosition(fline)
+ lline = self.GetLastVisibleLine()
+ last = self.GetLineEndPosition(lline)
+ self._spell.addDirtyRange(first, last, 0, False)
+
+ def OnTabMenu(self, evt):
+ """Tab menu event handler"""
+ e_id = evt.GetId()
+ if e_id in (ed_glob.ID_COPY_PATH, ed_glob.ID_COPY_FILE):
+ path = self.GetFileName()
+ if path is not None:
+ if e_id == ed_glob.ID_COPY_FILE:
+ path = GetFileName(path)
+ SetClipboardText(path)
+ elif e_id == ed_glob.ID_MOVE_TAB:
+ frame = wx.GetApp().OpenNewWindow()
+ nbook = frame.GetNotebook()
+ parent = self.GetParent()
+ pg_txt = parent.GetRawPageText(parent.GetSelection())
+ nbook.OpenDocPointer(self.GetDocPointer(),
+ self.GetDocument(), pg_txt)
+ self._ignore_del = True
+ wx.CallAfter(parent.ClosePage)
+ elif e_id == ed_glob.ID_CLOSE_OTHERS:
+ parent = self.GetParent()
+ if hasattr(parent, 'CloseOtherPages'):
+ parent.CloseOtherPages()
+ elif e_id in (EdEditorView.ID_CLOSE_TAB, EdEditorView.ID_CLOSE_ALL_TABS):
+ # Need to relay events up to toplevel window on GTK for them to
+ # be processed. On other platforms the propagate by themselves.
+ evt.SetId({ EdEditorView.ID_CLOSE_TAB : ed_glob.ID_CLOSE,
+ EdEditorView.ID_CLOSE_ALL_TABS : ed_glob.ID_CLOSEALL}.get(e_id))
+ wx.PostEvent(self.GetTopLevelParent(), evt)
+ else:
+ evt.Skip()
+
+ #---- End EdTab Methods ----#
+
+ def OnKillFocus(self, evt):
+ """Hide popups when focus is lost
+ @note: call to skip is necessary
+
+ """
+ self.HidePopups()
+ evt.Skip()
+
+ def OnConfigMsg(self, msg):
+ """Update config based on profile changes"""
+ mtype = msg.GetType()[-1]
+ mdata = msg.GetData()
+ if mtype == 'SPELLCHECK':
+ self._spell_data['enabled'] = mdata.get('auto', False)
+ self._spell.setDefaultLanguage(mdata.get('dict', 'en_US'))
+ if not self._spell_data['enabled']:
+ self._spell.clearAll()
+ return
+ elif mtype == 'AUTO_COMP_EX':
+ self.ConfigureAutoComp()
+ return
+ elif mtype == 'CARETWIDTH':
+ if self.GetCaretWidth(): # check that it is not hidden
+ self.RestoreCaret()
+ return
+ elif mtype in ('VI_EMU', 'VI_NORMAL_DEFAULT'):
+ self.SetViEmulationMode(Profile_Get('VI_EMU'),
+ Profile_Get('VI_NORMAL_DEFAULT'))
+ return
+ elif mtype == 'VIEWVERTSPACE':
+ self.SetEndAtLastLine(not Profile_Get('VIEWVERTSPACE'))
+
+ # Update other settings
+ cfgmap = { 'AUTOBACKUP' : self.EnableAutoBackup,
+ 'SYNTHEME' : self.UpdateAllStyles,
+ 'SYNTAX' : self.SyntaxOnOff,
+ 'BRACKETHL' : self.ToggleBracketHL,
+ 'GUIDES' : self.SetIndentationGuides,
+ 'SHOW_EDGE' : self.SetViewEdgeGuide,
+ 'EDGE' : self.SetViewEdgeGuide,
+ 'CODE_FOLD' : self.FoldingOnOff,
+ 'AUTO_COMP' : self.SetAutoComplete,
+ 'AUTO_INDENT': self.ToggleAutoIndent,
+ 'HLCARETLINE': self.SetCaretLineVisible,
+ 'USETABS' : self.SetUseTabs,
+ 'BSUNINDENT' : self.SetBackSpaceUnIndents,
+ 'EOL_MODE' : self.SetEOLMode,
+ 'AALIASING' : self.SetUseAntiAliasing,
+ 'SHOW_EOL' : self.SetViewEOL,
+ 'SHOW_LN' : self.ToggleLineNumbers,
+ 'SHOW_WS' : self.SetViewWhiteSpace,
+ 'WRAP' : self.SetWrapMode }
+
+ if mtype in cfgmap:
+ cfgmap[mtype](Profile_Get(mtype))
+ return
+
+ cfgmap2 = { 'TABWIDTH' : self.SetTabWidth,
+ 'INDENTWIDTH': self.SetIndent }
+ if mtype in cfgmap2:
+ cfgmap2[mtype](Profile_Get(mtype, 'int'))
+
+ def OnContextMenu(self, evt):
+ """Handle right click menu events in the buffer"""
+ self._menu.Clear()
+
+ menu = ed_menu.EdMenu()
+ menu.Append(ed_glob.ID_UNDO, _("Undo"))
+ menu.Append(ed_glob.ID_REDO, _("Redo"))
+ menu.AppendSeparator()
+ menu.Append(ed_glob.ID_CUT, _("Cut"))
+ menu.Append(ed_glob.ID_COPY, _("Copy"))
+ menu.Append(ed_glob.ID_PASTE, _("Paste"))
+ menu.AppendSeparator()
+ menu.Append(ed_glob.ID_TO_UPPER, _("To Uppercase"))
+ menu.Append(ed_glob.ID_TO_LOWER, _("To Lowercase"))
+ menu.AppendSeparator()
+ menu.Append(ed_glob.ID_SELECTALL, _("Select All"))
+
+ # Allow clients to customize the context menu
+ self._menu.SetMenu(menu)
+ pos = evt.GetPosition()
+ bpos = self.PositionFromPoint(self.ScreenToClient(pos))
+ self._menu.SetPosition(bpos)
+ self._menu.SetUserData('buffer', self)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_CONTEXT_MENU,
+ self._menu, self.GetId())
+
+ #### Spell checking ####
+ # TODO: de-couple to the forthcoming buffer service interface
+ menu.InsertSeparator(0)
+ words = self.GetWordFromPosition(bpos)
+ self._spell_data['word'] = words
+ sugg = self._spell.getSuggestions(words[0])
+
+ # Don't give suggestions if the selected word is in the suggestions list
+ if words[0] in sugg:
+ sugg = list()
+
+ if not len(sugg):
+ item = menu.Insert(0, EdEditorView.ID_NO_SUGGEST, _("No Suggestions"))
+ item.Enable(False)
+ else:
+ sugg = reversed(sugg[:min(len(sugg), 3)])
+ ids = (ID_SPELL_1, ID_SPELL_2, ID_SPELL_3)
+ del self._spell_data['choices']
+ self._spell_data['choices'] = list()
+ pos = 0
+ for idx, sug in enumerate(sugg):
+ id_ = ids[idx]
+ self._menu.AddHandler(id_, self.OnSpelling)
+ self._spell_data['choices'].append((id_, sug))
+ menu.Insert(0, id_, sug)
+ pos += 1
+ # Add spelling settings menu
+ smenu = wx.Menu()
+ smenu.Append(EdEditorView.ID_IGNORE, _("Ignore"))
+ self._menu.AddHandler(EdEditorView.ID_IGNORE, self.OnSpelling)
+ smenu.Append(EdEditorView.ID_ADD_TO_DICT,
+ _("Add '%s' to dictionary") % self._spell_data['word'][0])
+ self._menu.AddHandler(EdEditorView.ID_ADD_TO_DICT, self.OnSpelling)
+ menu.InsertSeparator(pos)
+ menu.InsertMenu(pos+1, EdEditorView.ID_SPELLING_MENU,
+ _("Spelling"), smenu)
+ #### End Spell Checking ####
+
+ self.PopupMenu(self._menu.Menu)
+ evt.Skip()
+
+ def OnMenuEvent(self, evt):
+ """Handle context menu events"""
+ e_id = evt.GetId()
+ handler = self._menu.GetHandler(e_id)
+
+ # Handle custom menu items
+ if handler is not None:
+ handler(self, evt)
+ else:
+ self.ControlDispatch(evt)
+ if evt.GetSkipped():
+ evt.Skip()
+
+ def OnModified(self, evt):
+ """Overrides EditraBaseStc.OnModified"""
+ super(EdEditorView, self).OnModified(evt)
+
+ # Handle word changes to update spell checking
+ # TODO: limit via preferences and move to buffer service once
+ # implemented.
+ mod = evt.GetModificationType()
+ if mod & wx.stc.STC_MOD_INSERTTEXT or mod & wx.stc.STC_MOD_DELETETEXT:
+ pos = evt.GetPosition()
+ last = pos + evt.GetLength()
+ self._spell.addDirtyRange(pos, last, evt.GetLinesAdded(),
+ mod & wx.stc.STC_MOD_DELETETEXT)
+
+ @modalcheck
+ def PromptToReSave(self, cfile):
+ """Show a dialog prompting to resave the current file
+ @param cfile: the file in question
+
+ """
+ mdlg = wx.MessageDialog(self,
+ _("%s has been deleted since its "
+ "last save point.\n\nWould you "
+ "like to save it again?") % cfile,
+ _("Resave File?"),
+ wx.YES_NO | wx.ICON_INFORMATION)
+ mdlg.CenterOnParent()
+ result = mdlg.ShowModal()
+ mdlg.Destroy()
+ if result == wx.ID_YES:
+ result = self.SaveFile(cfile)
+ else:
+ self.SetModTime(0)
+
+ @modalcheck
+ def AskToReload(self, cfile):
+ """Show a dialog asking if the file should be reloaded
+ @param cfile: the file to prompt for a reload of
+
+ """
+ if not self:
+ return
+ mdlg = wx.MessageDialog(self,
+ _("%s has been modified by another "
+ "application.\n\nWould you like "
+ "to reload it?") % cfile,
+ _("Reload File?"),
+ wx.YES_NO | wx.ICON_INFORMATION)
+ mdlg.CenterOnParent()
+ result = mdlg.ShowModal()
+ mdlg.Destroy()
+ if result == wx.ID_YES:
+ self.DoReloadFile()
+ else:
+ # Set modtime to prevent re-prompting of dialog
+ self.SetModTime(GetFileModTime(cfile))
+
+ def SetLexer(self, lexer):
+ """Override to toggle spell check context"""
+ super(EdEditorView, self).SetLexer(lexer)
+
+ if lexer == wx.stc.STC_LEX_NULL:
+ self._spell.setCheckRegion(lambda p: True)
+ else:
+ self._spell.setCheckRegion(self.IsNonCode)
+
+#-----------------------------------------------------------------------------#
+
+ def ModifySave(self):
+ """Called when document has been modified prompting
+ a message dialog asking if the user would like to save
+ the document before closing.
+ @return: Result value of whether the file was saved or not
+
+ """
+ name = self.GetFileName()
+ if name == u"":
+ name = self.GetTabLabel()
+
+ dlg = wx.MessageDialog(self,
+ _("The file: \"%s\" has been modified since "
+ "the last save point.\n\nWould you like to "
+ "save the changes?") % name,
+ _("Save Changes?"),
+ wx.YES_NO | wx.YES_DEFAULT | wx.CANCEL | \
+ wx.ICON_INFORMATION)
+ result = dlg.ShowModal()
+ dlg.Destroy()
+
+ # HACK
+ if result == wx.ID_YES:
+ evt = wx.MenuEvent(wx.wxEVT_COMMAND_MENU_SELECTED, ed_glob.ID_SAVE)
+ tlw = self.GetTopLevelParent()
+ if hasattr(tlw, 'OnSave'):
+ tlw.OnSave(evt)
+
+ return result
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_event.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_event.py
new file mode 100644
index 0000000..c30f92b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_event.py
@@ -0,0 +1,89 @@
+###############################################################################
+# Name: ed_event.py #
+# Purpose: Custom events used by Editra #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides custom events for the editors controls/objects to utilize
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_event.py 63789 2010-03-30 02:25:17Z CJP $"
+__revision__ = "$Revision: 63789 $"
+
+#-----------------------------------------------------------------------------#
+# Dependencies
+import wx
+
+#-----------------------------------------------------------------------------#
+
+edEVT_UPDATE_TEXT = wx.NewEventType()
+EVT_UPDATE_TEXT = wx.PyEventBinder(edEVT_UPDATE_TEXT, 1)
+class UpdateTextEvent(wx.PyCommandEvent):
+ """Event to signal that text needs updating"""
+ def __init__(self, etype, eid, value=None):
+ """Creates the event object"""
+ wx.PyCommandEvent.__init__(self, etype, eid)
+ self._value = value
+
+ def GetValue(self):
+ """Returns the value from the event.
+ @return: the value of this event
+
+ """
+ return self._value
+
+#--------------------------------------------------------------------------#
+
+edEVT_NOTIFY = wx.NewEventType()
+EVT_NOTIFY = wx.PyEventBinder(edEVT_NOTIFY, 1)
+class NotificationEvent(UpdateTextEvent):
+ """General notification event"""
+ def __init__(self, etype, eid, value=None, obj=None):
+ UpdateTextEvent.__init__(self, etype, eid, value)
+ self.SetEventObject(obj)
+
+#--------------------------------------------------------------------------#
+
+edEVT_MAINWINDOW_EXIT = wx.NewEventType()
+EVT_MAINWINDOW_EXIT = wx.PyEventBinder(edEVT_MAINWINDOW_EXIT, 1)
+class MainWindowExitEvent(wx.PyCommandEvent):
+ """Event to signal that the main window is exiting"""
+ pass
+
+#--------------------------------------------------------------------------#
+
+edEVT_STATUS = wx.NewEventType()
+EVT_STATUS = wx.PyEventBinder(edEVT_STATUS, 1)
+class StatusEvent(wx.PyCommandEvent):
+ """Event for posting status events"""
+ def __init__(self, etype, eid, msg=None, sec=0):
+ """Create an event that can be used to post status messages
+ to the main windows status bar.
+ @param etype: The type of event to create
+ @param eid: The event id
+ @keyword msg: The status message to post with the event
+ @keyword sec: The section of the status bar to post message to
+
+ """
+ wx.PyCommandEvent.__init__(self, etype, eid)
+ self._msg = msg
+ self._sec = sec
+
+ def GetMessage(self):
+ """Returns the value from the event.
+ @return: the value of this event
+
+ """
+ return self._msg
+
+ def GetSection(self):
+ """Returns the messages posting section
+ @return: int zero based index of where to post to statusbar
+
+ """
+ return self._sec
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_fmgr.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_fmgr.py
new file mode 100644
index 0000000..9aeaa79
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_fmgr.py
@@ -0,0 +1,81 @@
+###############################################################################
+# Name: ed_fmgr.py #
+# Purpose: Editra's Main Window Frame Manager #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: $"
+__revision__ = "$Revision: $"
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import wx
+#import wx.lib.agw.aui as aui
+import wx.aui as aui
+
+#--------------------------------------------------------------------------#
+# Events
+
+EVT_AUI_PANE_CLOSE = aui.EVT_AUI_PANE_CLOSE
+EVT_AUI_PANE_RESTORE = aui.EVT_AUI_PANE_RESTORE
+
+#--------------------------------------------------------------------------#
+
+class EdFrameManager(aui.AuiManager):
+ """Frame manager for external components to abstract underlying manager"""
+ def __init__(self, wnd=None, flags=0):
+ """Create the frame manager object
+ @param wnd: Frame to manage
+ @param flags: frame manager flags
+
+ """
+ super(EdFrameManager, self).__init__(wnd, flags)
+ self.Bind(aui.EVT_AUI_PANE_CLOSE, self.OnPaneClose)
+ self.Bind(aui.EVT_AUI_PANE_RESTORE, self.OnPaneRestore)
+
+ def OnPaneClose(self, evt):
+ """Notify pane it is being closed"""
+# pane = evt.GetPane()
+# print "Close", pane.window
+# nevt = wx.ShowEvent(pane.window.Id, False)
+# wx.PostEvent(pane.window, nevt)
+ evt.Skip()
+
+ def OnPaneRestore(self, evt):
+ """Notify pane it is being opened"""
+# pane = evt.GetPane()
+# print "Restore:", pane.window
+# nevt = wx.ShowEvent(pane.window.Id, True)
+# wx.PostEvent(pane.window, nevt)
+ evt.Skip()
+
+ def AddPane(self, wnd, info=None, caption=None):
+ return super(EdFrameManager, self).AddPane(wnd, info, caption)
+
+ def IsEditorMaximized(self):
+ """Is the editor pane maximized?
+ return: bool
+
+ """
+ bEditMax = True
+ # If any other pane is open then the editor is not maximized
+ for pane in self.GetAllPanes():
+ if pane.IsShown() and pane.name != "EditPane":
+ bEditMax = False
+ break
+ return bEditMax
+
+#--------------------------------------------------------------------------#
+
+EdPaneInfo = aui.AuiPaneInfo
+# """Frame manager panel info"""
+# def __init__(self):
+# super(EdPaneInfo, self).__init__()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_glob.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_glob.py
new file mode 100644
index 0000000..5126b17
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_glob.py
@@ -0,0 +1,403 @@
+###############################################################################
+# Name: ed_glob.py #
+# Purpose: Global IDs/objects used throughout Editra #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This file contains variables that are or may be used in multiple files and
+libraries within the project. Its purpose is to create a globally accessible
+access point for all common variables in the project.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_glob.py 70747 2012-02-29 01:33:35Z CJP $"
+__revision__ = "$Revision: 70747 $"
+
+__all__ = [ 'CONFIG', 'SB_INFO', 'VERSION', 'PROG_NAME', 'ID_NEW', 'ID_OPEN',
+ 'ID_CLOSE', 'ID_CLOSEALL', 'ID_SAVE', 'ID_SAVEAS', 'ID_SAVEALL',
+ 'ID_SAVE_PROFILE', 'ID_LOAD_PROFILE', 'ID_PRINT', 'ID_PRINT_PRE',
+ 'ID_PRINT_SU', 'ID_EXIT', 'ID_UNDO', 'ID_REDO', 'ID_CUT',
+ 'ID_COPY', 'ID_PASTE', 'ID_SELECTALL', 'ID_ADD_BM',
+ 'ID_DEL_ALL_BM', 'ID_LINE_AFTER', 'ID_LINE_BEFORE', 'ID_CUT_LINE',
+ 'ID_COPY_LINE', 'ID_JOIN_LINES', 'ID_TRANSPOSE', 'ID_DELETE_LINE',
+ 'ID_LINE_MOVE_UP', 'ID_LINE_MOVE_DOWN',
+ 'ID_QUICK_FIND', 'ID_PREF', 'ID_ZOOM_OUT',
+ 'HOME_PAGE', 'CONTACT_MAIL', 'ID_ZOOM_IN', 'ID_ZOOM_NORMAL',
+ 'ID_SHOW_EDGE', 'ID_SHOW_EOL', 'ID_SHOW_LN', 'ID_SHOW_WS',
+ 'ID_PERSPECTIVES', 'ID_INDENT_GUIDES', 'ID_VIEW_TOOL',
+ 'ID_GOTO_LINE', 'ID_NEXT_MARK', 'ID_PRE_MARK', 'ID_FONT',
+ 'ID_EOL_MAC', 'ID_EOL_UNIX', 'ID_EOL_WIN', 'ID_WORD_WRAP',
+ 'ID_INDENT', 'ID_UNINDENT', 'ID_TO_UPPER', 'ID_TO_LOWER',
+ 'ID_SPACE_TO_TAB', 'ID_TAB_TO_SPACE', 'ID_TRIM_WS',
+ 'ID_TOGGLECOMMENT', 'ID_AUTOCOMP', 'ID_AUTOINDENT', 'ID_SYNTAX',
+ 'ID_FOLDING', 'ID_BRACKETHL', 'ID_LEXER',
+ 'ID_PLUGMGR', 'ID_STYLE_EDIT', 'ID_MACRO_START', 'ID_MACRO_STOP',
+ 'ID_MACRO_PLAY', 'ID_ABOUT', 'ID_HOMEPAGE', 'ID_CONTACT',
+ 'ID_BUG_TRACKER', 'ID_DOCUMENTATION', 'ID_COMMAND',
+ 'ID_USE_SOFTTABS', 'ID_DUP_LINE', 'ID_TRANSLATE',
+ 'I18N_PAGE', 'ID_GOTO_MBRACE', 'ID_HLCARET_LINE', 'ID_SHOW_SB',
+ 'ID_REVERT_FILE', 'ID_RELOAD_ENC', 'ID_DOCPROP', 'ID_PASTE_AFTER',
+ 'ID_COLUMN_MODE', 'ID_PANELIST', 'ID_MAXIMIZE_EDITOR',
+ 'ID_NEW_WINDOW', 'ID_TOGGLE_FOLD', 'ID_TOGGLE_ALL_FOLDS',
+ 'ID_SAVE_SESSION', 'ID_LOAD_SESSION', 'ID_NEXT_POS', 'ID_PRE_POS',
+ 'ID_CYCLE_CLIPBOARD', 'ID_LEXER_CUSTOM', 'ID_SHOW_AUTOCOMP',
+ 'ID_SHOW_CALLTIP', 'ID_SESSION_BAR', 'ID_PREF_CARET_WIDTH' ]
+
+#---- Project Info ----#
+# The project info was moved to another module so it could be accessed
+# externally without needing to import anything else. It's imported
+# here with a * until there isn't anyplace left that expects to find
+# these values in this module.
+from info import *
+
+#---- End Project Info ----#
+
+#---- Imported Libs/Objects ----#
+import wx
+
+_ = wx.GetTranslation
+
+#---- WX Compatibility Hacks ----#
+import wxcompat
+
+#---- Configuration Locations ----#
+# Values set when main loads
+CONFIG = {
+ 'ISLOCAL' : False, # Using local config (no abs path)
+ 'CONFIG_BASE' : None, # Set if config base is in nonstandard location
+ 'INSTALL_DIR' : "", # Instal directory
+ 'CONFIG_DIR' : "", # Root configration directory
+ 'CACHE_DIR' : "", # Holds temp data about documents
+ 'KEYPROF_DIR' : "", # System Keybinding
+ 'PROFILE_DIR' : "", # User Profile Directory
+ 'PLUGIN_DIR' : "", # User Plugin Dir
+ 'SYSPIX_DIR' : "", # Editras non user graphics
+ 'THEME_DIR' : "", # Theme Directory
+ 'LANG_DIR' : "", # Locale Data Directory
+ 'SYS_PLUGIN_DIR' : "", # Editra base plugin dir
+ 'SYS_STYLES_DIR' : "", # Editra base style sheets
+ 'TEST_DIR' : "", # Test data files dir
+}
+
+# Global logging/application variables
+DEBUG = False
+VDEBUG = False
+SINGLE = True
+
+#---- Object ID's ----#
+# File Menu IDs
+ID_NEW = wx.ID_NEW
+ID_NEW_WINDOW = wx.NewId()
+ID_OPEN = wx.ID_OPEN
+ID_FHIST = wx.NewId()
+ID_CLOSE = wx.ID_CLOSE
+ID_CLOSEALL = wx.ID_CLOSE_ALL
+ID_CLOSE_OTHERS = wx.NewId()
+ID_CLOSE_WINDOW = wx.NewId()
+ID_SAVE = wx.ID_SAVE
+ID_SAVEAS = wx.ID_SAVEAS
+ID_SAVEALL = wx.NewId()
+ID_REVERT_FILE = wx.ID_REVERT_TO_SAVED
+ID_RELOAD_ENC = wx.NewId()
+ID_SAVE_PROFILE = wx.NewId()
+ID_LOAD_PROFILE = wx.NewId()
+ID_SAVE_SESSION = wx.NewId()
+ID_LOAD_SESSION = wx.NewId()
+ID_SESSION_BAR = wx.NewId()
+ID_PRINT = wx.ID_PRINT
+ID_PRINT_PRE = wx.ID_PREVIEW
+ID_PRINT_SU = wx.NewId()
+ID_EXIT = wx.ID_EXIT
+
+# Edit Menu IDs
+ID_UNDO = wx.ID_UNDO
+ID_REDO = wx.ID_REDO
+ID_CUT = wx.ID_CUT
+ID_COPY = wx.ID_COPY
+ID_PASTE = wx.ID_PASTE
+ID_CYCLE_CLIPBOARD = wx.NewId()
+ID_PASTE_AFTER = wx.NewId()
+ID_SELECTALL = wx.ID_SELECTALL
+ID_COLUMN_MODE = wx.NewId()
+ID_LINE_EDIT = wx.NewId()
+ID_BOOKMARK = wx.NewId()
+ID_ADD_BM = wx.NewId()
+ID_DEL_BM = wx.NewId() # Not used in menu anymore
+ID_DEL_ALL_BM = wx.NewId()
+ID_LINE_AFTER = wx.NewId()
+ID_LINE_BEFORE = wx.NewId()
+ID_CUT_LINE = wx.NewId()
+ID_DELETE_LINE = wx.NewId()
+ID_COPY_LINE = wx.NewId()
+ID_DUP_LINE = wx.NewId()
+ID_JOIN_LINES = wx.NewId()
+ID_TRANSPOSE = wx.NewId()
+ID_LINE_MOVE_UP = wx.NewId()
+ID_LINE_MOVE_DOWN= wx.NewId()
+ID_SHOW_AUTOCOMP = wx.NewId()
+ID_SHOW_CALLTIP = wx.NewId()
+ID_FIND = wx.ID_FIND
+ID_FIND_PREVIOUS = wx.NewId()
+ID_FIND_NEXT = wx.NewId()
+ID_FIND_REPLACE = wx.ID_REPLACE
+ID_FIND_SELECTED = wx.NewId()
+
+# Using the system ids automatically disables the menus items
+# when the dialog is open which is not wanted
+if wx.Platform == '__WXMAC__':
+ ID_FIND = wx.NewId()
+ ID_FIND_REPLACE = wx.NewId()
+ID_QUICK_FIND = wx.NewId()
+ID_PREF = wx.ID_PREFERENCES
+
+# Preference Dlg Ids
+ID_PREF_LANG = wx.NewId()
+ID_PREF_AALIAS = wx.NewId()
+ID_PREF_AUTOBKUP = wx.NewId()
+ID_PREF_AUTO_RELOAD = wx.NewId()
+ID_PREF_AUTOCOMPEX = wx.NewId()
+ID_PREF_AUTOTRIM = wx.NewId()
+ID_PREF_CHKMOD = wx.NewId()
+ID_PREF_CHKUPDATE = wx.NewId()
+ID_PREF_DLEXER = wx.NewId()
+ID_PREF_EDGE = wx.NewId()
+ID_PREF_ENCODING = wx.NewId()
+ID_PREF_SYNTHEME = wx.NewId()
+ID_PREF_TABS = wx.NewId()
+ID_PREF_UNINDENT = wx.NewId()
+ID_PREF_TABW = wx.NewId()
+ID_PREF_INDENTW = wx.NewId()
+ID_PREF_FHIST = wx.NewId()
+ID_PREF_WSIZE = wx.NewId()
+ID_PREF_WPOS = wx.NewId()
+ID_PREF_ICON = wx.NewId()
+ID_PREF_ICONSZ = wx.NewId()
+ID_PREF_MODE = wx.NewId()
+ID_PREF_TABICON = wx.NewId()
+ID_PRINT_MODE = wx.NewId()
+ID_TRANSPARENCY = wx.NewId()
+ID_PREF_SPOS = wx.NewId()
+ID_PREF_UPDATE_BAR = wx.NewId()
+ID_PREF_VIRT_SPACE = wx.NewId()
+ID_PREF_CARET_WIDTH = wx.NewId()
+ID_PREF_WARN_EOL = wx.NewId()
+ID_SESSION = wx.NewId()
+
+# View Menu IDs
+ID_ZOOM_OUT = wx.ID_ZOOM_OUT
+ID_ZOOM_IN = wx.ID_ZOOM_IN
+ID_ZOOM_NORMAL = wx.ID_ZOOM_100
+ID_HLCARET_LINE = wx.NewId()
+ID_SHOW_EDGE = wx.NewId()
+ID_SHOW_EOL = wx.NewId()
+ID_SHOW_LN = wx.NewId()
+ID_SHOW_WS = wx.NewId()
+ID_SHOW_SHELF = wx.NewId()
+ID_PERSPECTIVES = wx.NewId()
+ID_INDENT_GUIDES = wx.NewId()
+ID_SHOW_SB = wx.NewId()
+ID_VIEW_TOOL = wx.NewId()
+ID_SHELF = wx.NewId()
+ID_PANELIST = wx.NewId()
+ID_GOTO_LINE = wx.NewId()
+ID_GOTO_MBRACE = wx.NewId()
+ID_TOGGLE_FOLD = wx.NewId()
+ID_TOGGLE_ALL_FOLDS = wx.NewId()
+ID_NEXT_POS = wx.NewId()
+ID_PRE_POS = wx.NewId()
+ID_NEXT_MARK = wx.ID_FORWARD
+ID_PRE_MARK = wx.ID_BACKWARD
+ID_MAXIMIZE_EDITOR = wx.NewId()
+
+# Format Menu IDs
+ID_FONT = wx.NewId()
+ID_EOL_MODE = wx.NewId()
+ID_EOL_MAC = wx.NewId()
+ID_EOL_UNIX = wx.NewId()
+ID_EOL_WIN = wx.NewId()
+ID_USE_SOFTTABS = wx.NewId()
+ID_WORD_WRAP = wx.NewId()
+ID_INDENT = wx.ID_INDENT
+ID_UNINDENT = wx.ID_UNINDENT
+ID_TO_UPPER = wx.NewId()
+ID_TO_LOWER = wx.NewId()
+ID_WS_FORMAT = wx.NewId()
+ID_SPACE_TO_TAB = wx.NewId()
+ID_TAB_TO_SPACE = wx.NewId()
+ID_TRIM_WS = wx.NewId()
+ID_TOGGLECOMMENT = wx.NewId()
+
+# Settings Menu IDs
+ID_AUTOCOMP = wx.NewId()
+ID_AUTOINDENT = wx.NewId()
+ID_SYNTAX = wx.NewId()
+ID_SYN_ON = wx.NewId()
+ID_SYN_OFF = wx.NewId()
+ID_FOLDING = wx.NewId()
+ID_BRACKETHL = wx.NewId()
+ID_LEXER = wx.NewId()
+ID_LEXER_CUSTOM = wx.NewId()
+
+# Tool Menu IDs
+ID_COMMAND = wx.NewId()
+ID_PLUGMGR = wx.NewId()
+ID_STYLE_EDIT = wx.ID_EDIT
+ID_MACRO_START = wx.NewId()
+ID_MACRO_STOP = wx.NewId()
+ID_MACRO_PLAY = wx.NewId()
+ID_GENERATOR = wx.NewId()
+ID_HTML_GEN = wx.NewId()
+ID_TEX_GEN = wx.NewId()
+ID_RTF_GEN = wx.NewId()
+ID_RUN_LAUNCH = wx.NewId()
+ID_LAUNCH_LAST = wx.NewId()
+
+# Help Menu IDs
+ID_ABOUT = wx.ID_ABOUT
+ID_HOMEPAGE = wx.ID_HOME
+ID_DOCUMENTATION = wx.NewId()
+ID_TRANSLATE = wx.NewId()
+ID_CONTACT = wx.NewId()
+ID_BUG_TRACKER = wx.NewId()
+
+# Misc IDs
+ID_ADD = wx.ID_ADD
+ID_ADVANCED = wx.NewId()
+ID_APP_SPLASH = wx.NewId()
+ID_BACKWARD = wx.ID_BACKWARD
+ID_BIN_FILE = ID_COMMAND
+ID_CDROM = wx.NewId()
+ID_COMMAND_LINE_OPEN = wx.NewId()
+ID_COMPUTER = wx.NewId()
+ID_COPY_PATH = wx.NewId()
+ID_COPY_FILE = wx.NewId()
+ID_DELETE = wx.NewId()
+ID_DELETE_ALL = wx.NewId()
+ID_DOCPROP = wx.NewId()
+ID_DOWN = wx.ID_DOWN
+ID_DOWNLOAD_DLG = wx.NewId()
+ID_FILE = wx.ID_FILE
+ID_FIND_RESULTS = wx.NewId()
+ID_FLOPPY = wx.NewId()
+ID_FOLDER = wx.NewId()
+ID_FORWARD = wx.ID_FORWARD
+ID_HARDDISK = wx.NewId()
+ID_KEY_PROFILES = wx.NewId()
+ID_LOGGER = wx.NewId()
+ID_BOOKMARK_MGR = wx.NewId()
+ID_MOVE_TAB = wx.NewId()
+ID_PACKAGE = wx.NewId()
+ID_PYSHELL = wx.NewId()
+ID_REFRESH = wx.ID_REFRESH
+ID_REMOVE = wx.ID_REMOVE
+ID_REPORTER = wx.NewId()
+ID_STOP = wx.ID_STOP
+ID_THEME = wx.NewId()
+ID_USB = wx.NewId()
+ID_UP = wx.ID_UP
+ID_VI_MODE = wx.NewId()
+ID_VI_NORMAL_DEFAULT = wx.NewId()
+ID_WEB = wx.NewId()
+ID_READONLY = wx.NewId()
+ID_NEW_FOLDER = wx.NewId()
+
+# Code Elements (ids for art provider)
+ID_CLASS_TYPE = wx.NewId()
+ID_FUNCT_TYPE = wx.NewId()
+ID_ELEM_TYPE = wx.NewId()
+ID_VARIABLE_TYPE = wx.NewId()
+ID_ATTR_TYPE = wx.NewId()
+ID_PROPERTY_TYPE = wx.NewId()
+ID_METHOD_TYPE = wx.NewId()
+
+# Statusbar IDs
+SB_INFO = 0
+SB_BUFF = 1
+SB_LEXER = 2
+SB_ENCODING = 3
+SB_EOL = 4
+SB_ROWCOL = 5
+
+# Print Mode Identifiers
+PRINT_BLACK_WHITE = 0
+PRINT_COLOR_WHITE = 1
+PRINT_COLOR_DEF = 2
+PRINT_INVERT = 3
+PRINT_NORMAL = 4
+
+#---- Objects ----#
+
+# Dictionary to map object ids to Profile keys
+ID_2_PROF = {
+ ID_PREF_AALIAS : 'AALIASING',
+ ID_TRANSPARENCY : 'ALPHA',
+ ID_PREF_UNINDENT : 'BSUNINDENT',
+ ID_APP_SPLASH : 'APPSPLASH',
+ ID_PREF_AUTOBKUP : 'AUTOBACKUP',
+ ID_AUTOCOMP : 'AUTO_COMP',
+ ID_PREF_AUTOCOMPEX : 'AUTO_COMP_EX',
+ ID_AUTOINDENT : 'AUTO_INDENT',
+ ID_PREF_AUTO_RELOAD : 'AUTO_RELOAD',
+ ID_PREF_AUTOTRIM : 'AUTO_TRIM_WS',
+ ID_BRACKETHL : 'BRACKETHL',
+ ID_PREF_CHKMOD : 'CHECKMOD',
+ ID_PREF_CHKUPDATE : 'CHECKUPDATE',
+ ID_FOLDING : 'CODE_FOLD',
+ ID_PREF_DLEXER : 'DEFAULT_LEX',
+ ID_PERSPECTIVES : 'DEFAULT_VIEW',
+ ID_PREF_EDGE : 'EDGE',
+ ID_PREF_ENCODING : 'ENCODING',
+ ID_EOL_MODE : 'EOL_MODE',
+ ID_PREF_FHIST : 'FHIST_LVL',
+ ID_INDENT_GUIDES : 'GUIDES',
+ ID_HLCARET_LINE : 'HLCARETLINE',
+ ID_PREF_ICON : 'ICONS',
+ ID_PREF_ICONSZ : 'ICON_SZ',
+ ID_PREF_INDENTW : 'INDENTWIDTH',
+ ID_KEY_PROFILES : 'KEY_PROFILE',
+ ID_PREF_LANG : 'LANG',
+ ID_PREF_MODE : 'MODE',
+ ID_NEW_WINDOW : 'OPEN_NW',
+ ID_PRINT_MODE : 'PRINT_MODE',
+ ID_REPORTER : 'REPORTER',
+ ID_PREF_SPOS : 'SAVE_POS',
+ ID_SESSION : 'SAVE_SESSION',
+ ID_PREF_WPOS : 'SET_WPOS',
+ ID_PREF_WSIZE : 'SET_WSIZE',
+ ID_SHOW_EDGE : 'SHOW_EDGE',
+ ID_SHOW_EOL : 'SHOW_EOL',
+ ID_SHOW_LN : 'SHOW_LN',
+ ID_SHOW_WS : 'SHOW_WS',
+ ID_SHOW_SB : 'STATBAR',
+ ID_SYNTAX : 'SYNTAX',
+ ID_PREF_SYNTHEME : 'SYNTHEME',
+ ID_PREF_TABICON : 'TABICONS',
+ ID_PREF_TABW : 'TABWIDTH',
+ ID_VIEW_TOOL : 'TOOLBAR',
+ ID_PREF_TABS : 'USETABS',
+ ID_PREF_VIRT_SPACE : 'VIEWVERTSPACE',
+ ID_PREF_CARET_WIDTH : 'CARETWIDTH',
+ ID_VI_MODE : 'VI_EMU',
+ ID_VI_NORMAL_DEFAULT : 'VI_NORMAL_DEFAULT',
+ ID_PREF_WARN_EOL : 'WARN_EOL',
+ ID_WORD_WRAP : 'WRAP',
+}
+
+EOL_MODE_CR = 0
+EOL_MODE_LF = 1
+EOL_MODE_CRLF = 2
+def EOLModeMap():
+ """Get the eol mode map"""
+ # Maintenance Note: ints must be kept in sync with EDSTC_EOL_* in edstc
+ return { EOL_MODE_CR : _("Old Machintosh (\\r)"),
+ EOL_MODE_LF : _("Unix (\\n)"),
+ EOL_MODE_CRLF : _("Windows (\\r\\n)")}
+
+# Default Plugins
+DEFAULT_PLUGINS = ("generator.Html", "generator.LaTeX", "generator.Rtf",
+ "iface.Shelf", "ed_theme.TangoTheme", "ed_log.EdLogViewer",
+ "ed_search.EdFindResults", "ed_bookmark.EdBookmarks")
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_i18n.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_i18n.py
new file mode 100644
index 0000000..62ee00c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_i18n.py
@@ -0,0 +1,136 @@
+###############################################################################
+# Name: ed_i18n.py #
+# Purpose: I18n utilities and services #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This file is a module for managing translations and the internationalization of
+the program.
+
+METHODS:
+ - L{GetAvailLocales}: Returns a list of canonical names of available locales
+ - L{GetLocaleDict}: Returns a dictionary consisting of canonical names for
+ keys and language ids for values.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_i18n.py 71189 2012-04-12 00:37:04Z CJP $"
+__revision__ = "$Revision: 71189 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import wx
+import wx.lib.langlistctrl as langlist
+import wx.combo
+import glob
+
+# Editra Imports
+import ed_glob
+
+#----------------------------------------------------------------------------#
+# Global Variables
+OPT_NO_OP = 0
+OPT_DESCRIPT = 1
+
+#----------------------------------------------------------------------------#
+
+#---- Helper Functions used by the classes in this module ----#
+def GetAvailLocales():
+ """Gets a list of the available locales that have been installed
+ for the editor. Returning a list of strings that represent the
+ canonical names of each language.
+ @return: list of all available local/languages available
+
+ """
+ avail_loc = list()
+ loc = glob.glob(os.path.join(ed_glob.CONFIG['LANG_DIR'], "*"))
+ for path in loc:
+ the_path = os.path.join(path, "LC_MESSAGES", ed_glob.PROG_NAME + ".mo")
+ if os.path.exists(the_path):
+ avail_loc.append(os.path.basename(path))
+ return avail_loc
+
+def GetLocaleDict(loc_list, opt=OPT_NO_OP):
+ """Takes a list of cannonical locale names and by default returns a
+ dictionary of available language values using the canonical name as
+ the key. Supplying the Option OPT_DESCRIPT will return a dictionary
+ of language id's with languages description as the key.
+ @param loc_list: list of locals
+ @keyword opt: option for configuring return data
+ @return: dict of locales mapped to wx.LANGUAGE_*** values
+
+ """
+ lang_dict = dict()
+ for lang in [x for x in dir(wx) if x.startswith("LANGUAGE_")]:
+ langId = getattr(wx, lang)
+ langOk = False
+ try:
+ langOk = wx.Locale.IsAvailable(langId)
+ except wx.PyAssertionError:
+ continue
+
+ if langOk:
+ loc_i = wx.Locale.GetLanguageInfo(langId)
+ if loc_i:
+ if loc_i.CanonicalName in loc_list:
+ if opt == OPT_DESCRIPT:
+ lang_dict[loc_i.Description] = langId
+ else:
+ lang_dict[loc_i.CanonicalName] = langId
+ return lang_dict
+
+def GetLangId(lang_n):
+ """Gets the ID of a language from the description string. If the
+ language cannot be found the function simply returns the default language
+ @param lang_n: Canonical name of a language
+ @return: wx.LANGUAGE_*** id of language
+
+ """
+ if lang_n == "Default":
+ # No language set, default to English
+ return wx.LANGUAGE_ENGLISH_US
+ lang_desc = GetLocaleDict(GetAvailLocales(), OPT_DESCRIPT)
+ return lang_desc.get(lang_n, wx.LANGUAGE_DEFAULT)
+
+#---- Language List Combo Box----#
+class LangListCombo(wx.combo.BitmapComboBox):
+ """Combines a langlist and a BitmapComboBox"""
+ def __init__(self, parent, id_, default=None):
+ """Creates a combobox with a list of all translations for the
+ editor as well as displaying the countries flag next to the item
+ in the list.
+
+ @param default: The default item to show in the combo box
+
+ """
+ lang_ids = GetLocaleDict(GetAvailLocales()).values()
+ lang_items = langlist.CreateLanguagesResourceLists(langlist.LC_ONLY, \
+ lang_ids)
+ wx.combo.BitmapComboBox.__init__(self, parent, id_,
+ size=wx.Size(250, 26),
+ style=wx.CB_READONLY)
+ for lang_d in lang_items[1]:
+ bit_m = lang_items[0].GetBitmap(lang_items[1].index(lang_d))
+ self.Append(lang_d, bit_m)
+
+ if default:
+ self.SetValue(default)
+
+#-----------------------------------------------------------------------------#
+if __name__ == '__main__':
+ APP = wx.PySimpleApp(False)
+ # Print a list of Canonical names useful for seeing what codes to
+ # use when naming po files
+ OUT = list()
+ for LANG in [x for x in dir(wx) if x.startswith("LANGUAGE")]:
+ LOC_I = wx.Locale.GetLanguageInfo(getattr(wx, LANG))
+ if LOC_I:
+ OUT.append((LOC_I.Description, LOC_I.CanonicalName))
+
+ for LANG in sorted(OUT):
+ print LANG
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_ipc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_ipc.py
new file mode 100644
index 0000000..d772f4b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_ipc.py
@@ -0,0 +1,273 @@
+###############################################################################
+# Name: ed_ipc.py #
+# Purpose: Editra IPC client/server #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008-2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""@package Editra.src.ed_ipc
+
+Classes and utilities for handling IPC between running instances of Editra. The
+IPC is done through sockets using the TCP protocol. Message packets have a
+specified format and authentication method that is described in L{EdIpcServer}.
+
+@section protocol Remote Control Protocol:
+
+This server and its relationship with the main application object allows for
+some limited remote control of Editra. The server's basic message protocol
+requirements are as follows.
+
+@verbatim
+SESSION_KEY;xml;MSGEND
+@endverbatim
+
+Where the SESSION_KEY is the unique authentication key created by the app that
+started the server. This key is stored in the user profile and only valid for
+the current running session of Editra. The MSGEND indicator is the L{MSGEND}
+string defined in this file (*EDEND*). If both of these parts of the message
+are found and correct the server will forward the messages that are packed in
+between to the app.
+
+@section format Message Format:
+@verbatim
+<edipc>
+ <filelist>
+ <file name="absolute_filepath"/>
+ </filelist>
+ <arglist>
+ <arg name="g" value="2"/>
+ </arglist>
+</edipc>
+@endverbatim
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_ipc.py 72623 2012-10-06 19:33:06Z CJP $"
+__revision__ = "$Revision: 72623 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import sys
+import wx
+import threading
+import socket
+import time
+#import select
+
+# Editra Libs
+import util
+import ed_xml
+import ebmlib
+
+#-----------------------------------------------------------------------------#
+# Globals
+
+# Port choosing algorithm ;)
+EDPORT = (10 * int('ed', 16) + sum(ord(x) for x in "itr") + int('a', 16)) * 10
+MSGEND = "*EDEND*"
+
+# Xml Implementation
+EDXML_IPC = "edipc"
+EDXML_FILELIST = "filelist"
+EDXML_FILE = "file"
+EDXML_ARGLIST = "arglist"
+EDXML_ARG = "arg"
+
+#-----------------------------------------------------------------------------#
+
+edEVT_COMMAND_RECV = wx.NewEventType()
+EVT_COMMAND_RECV = wx.PyEventBinder(edEVT_COMMAND_RECV, 1)
+class IpcServerEvent(wx.PyCommandEvent):
+ """Event to signal the server has recieved some commands"""
+ def __init__(self, etype, eid, values=None):
+ """Creates the event object"""
+ wx.PyCommandEvent.__init__(self, etype, eid)
+ self._value = values
+
+ def GetCommands(self):
+ """Returns the list of commands sent to the server
+ @return: the value of this event
+
+ """
+ return self._value
+
+#-----------------------------------------------------------------------------#
+
+class EdIpcServer(threading.Thread):
+ """Create an instance of IPC server for Editra. IPC is handled through
+ a socket connection to an instance of this server listening on L{EDPORT}.
+ The server will receive commands and dispatch them to the app.
+ Messages sent to the server must be in the following format.
+
+ AuthenticationKey;Message Data;MSGEND
+
+ The _AuthenticationKey_ is the same as the key that started the server it
+ is used to validate that messages are coming from a legitimate source.
+
+ _Message Data_ is a string of data where items are separated by a single
+ ';' character. If you use L{SendCommands} to communicate with the server
+ then this message separators are handled internally by that method.
+
+ L{MSGEND} is the token to signify that the client is finished sending
+ commands to the server. When using L{SendCommands} this is also
+ automatically handled.
+
+ @todo: investigate possible security issues
+
+ """
+ def __init__(self, app, key, port=EDPORT):
+ """Create the server thread
+ @param app: Application object the server belongs to
+ @param key: Unique user authentication key (string)
+ @keyword port: TCP port to attempt to connect to
+
+ """
+ super(EdIpcServer, self).__init__()
+
+ # Attributes
+ self._exit = False
+ self.__key = key
+ self.app = app
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ # Setup
+ ## Try new ports till we find one that we can use
+ while True:
+ try:
+ self.socket.bind(('127.0.0.1', port))
+ break
+ except:
+ port += 1
+
+ global EDPORT
+ EDPORT = port
+ self.socket.listen(5)
+
+ def Shutdown(self):
+ """Tell the server to exit"""
+ self._exit = True
+ # Wake up the server in case its waiting
+ # TODO: should add a specific exit event message
+ SendCommands(IPCCommand(), self.__key)
+
+ def run(self):
+ """Start the server. The server runs in blocking mode, this
+ shouldn't be an issue as it should rarely need to respond to
+ anything.
+
+ """
+ while not self._exit:
+ try:
+ client, addr = self.socket.accept()
+
+ if self._exit:
+ break
+
+ # Block for up to 2 seconds while reading
+ start = time.time()
+ recieved = ''
+ while time.time() < start + 2:
+ recieved += client.recv(4096)
+ if recieved.endswith(MSGEND):
+ break
+
+ # If message key is correct and the message is ended, process
+ # the input and dispatch to the app.
+ if recieved.startswith(self.__key) and recieved.endswith(MSGEND):
+ # Strip the key
+ recieved = recieved.replace(self.__key, '', 1)
+ # Strip the end token
+ xmlstr = recieved.rstrip(MSGEND).strip(";")
+
+ # Parse the xml
+ exml = IPCCommand()
+ try:
+ # Well formed xml must be utf-8 string not Unicode
+ if not ebmlib.IsUnicode(xmlstr):
+ xmlstr = unicode(xmlstr, sys.getfilesystemencoding())
+ xmlstr = xmlstr.encode('utf-8')
+ exml = IPCCommand.parse(xmlstr)
+ except Exception, msg:
+ # Log and ignore parsing errors
+ logmsg = "[ed_ipc][err] Parsing failed: %s\n" % msg
+ xmlstr = xmlstr.replace('\n', '').strip()
+ logmsg += "Bad xml was: %s" % repr(xmlstr)
+ util.Log(logmsg)
+ continue
+
+ evt = IpcServerEvent(edEVT_COMMAND_RECV, wx.ID_ANY, exml)
+ wx.CallAfter(wx.PostEvent, self.app, evt)
+ except socket.error:
+ # TODO: Better error handling
+ self._exit = True
+
+ # Shutdown Server
+ try:
+ self.socket.shutdown(socket.SHUT_RDWR)
+ except:
+ pass
+
+ self.socket.close()
+
+#-----------------------------------------------------------------------------#
+
+def SendCommands(xmlobj, key):
+ """Send commands to the running instance of Editra
+ @param xmlobj: EditraXml Object
+ @param key: Server session authentication key
+ @return: bool
+
+ """
+ assert isinstance(xmlobj, ed_xml.EdXml), "SendCommands expects an xml object"
+
+ # Build the edipc protocol msg
+ cmds = list()
+ cmds.insert(0, key)
+ cmds.append(xmlobj.GetXml())
+ cmds.append(MSGEND)
+ try:
+ # Setup the client socket
+ client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ client.connect(('127.0.0.1', EDPORT))
+
+ # Server expects commands delimited by ;
+ message = ";".join(cmds)
+ client.send(message)
+ client.shutdown(socket.SHUT_RDWR)
+ client.close()
+ except Exception, msg:
+ util.Log("[ed_ipc][err] Failed in SendCommands: %s" % msg)
+ return False
+ else:
+ return True
+
+#-----------------------------------------------------------------------------#
+# Command Serialization
+
+class IPCFile(ed_xml.EdXml):
+ """Xml object for holding the list of files
+ @verbatim <file value="/path/to/file"/> @endverbatim
+
+ """
+ class meta:
+ tagname = EDXML_FILE
+ value = ed_xml.String(required=True)
+
+class IPCArg(ed_xml.EdXml):
+ """Xml object for holding the list of args
+ @verbatim <arg name="test" value="x"/> @endverbatim
+
+ """
+ class meta:
+ tagname = EDXML_ARG
+ name = ed_xml.String(required=True)
+ value = ed_xml.String(required=True)
+
+class IPCCommand(ed_xml.EdXml):
+ """IPC XML Command"""
+ class meta:
+ tagname = EDXML_IPC
+ filelist = ed_xml.List(ed_xml.Model(IPCFile))
+ arglist = ed_xml.List(ed_xml.Model(IPCArg))
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_keyh.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_keyh.py
new file mode 100644
index 0000000..00f88b7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_keyh.py
@@ -0,0 +1,286 @@
+###############################################################################
+# Name: ed_keyh.py #
+# Purpose: Editra's Vi Emulation Key Handler #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+KeyHandler interface for implementing extended key action handling in Editra's
+main text editting buffer.
+
+@summary: Custom keyhandler interface
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_keyh.py 70747 2012-02-29 01:33:35Z CJP $"
+__revision__ = "$Revision: 70747 $"
+
+#-------------------------------------------------------------------------#
+# Imports
+import re
+import wx
+import wx.stc
+
+# Editra Libraries
+import ed_event
+import ed_glob
+import ed_basestc
+import ed_stc
+import string
+import ed_vim
+
+#-------------------------------------------------------------------------#
+# Use this base class to derive any new keyhandlers from. The keyhandler is
+# called upon by the active buffer when ever a key press event happens. The
+# handler then has the responsibility of deciding what to do with the key.
+#
+class KeyHandler(object):
+ """KeyHandler base class"""
+ def __init__(self, stc):
+ super(KeyHandler, self).__init__()
+
+ # Attributes
+ self.stc = stc
+ self._blockmode = False
+
+ STC = property(lambda self: self.stc)
+ BlockMode = property(lambda self: self._blockmode,
+ lambda self,m:setattr(self,'_blockmode', m))
+
+ def ClearMode(self):
+ """Clear any key input modes to normal input mode"""
+ evt = ed_event.StatusEvent(ed_event.edEVT_STATUS, self.stc.Id,
+ '', ed_glob.SB_BUFF)
+ wx.PostEvent(self.stc.TopLevelParent, evt)
+
+ def GetHandlerName(self):
+ """Get the name of this handler
+ @return: string
+
+ """
+ return u'NULL'
+
+ def PreProcessKey(self, key_code, ctrldown=False,
+ cmddown=False, shiftdown=False, altdown=False):
+ """Pre process any keys before they get to the char handler
+ @param key_code: Raw keycode
+ @keyword ctrldown: Is the control key down
+ @keyword cmddown: Is the Command key down (Mac osx)
+ @keyword shiftdown: Is the Shift key down
+ @keyword altdown: Is the Alt key down
+ @return: bool
+
+ """
+ return False
+
+ def ProcessKey(self, key_code, ctrldown=False,
+ cmddown=False, shiftdown=False, altdown=False):
+ """Process the key and return True if it was processed and
+ false if it was not. The key is recieved at EVT_CHAR.
+ @param key_code: Raw keycode
+ @keyword ctrldown: Is the control key down
+ @keyword cmddown: Is the Command key down (Mac osx)
+ @keyword shiftdown: Is the Shift key down
+ @keyword altdown: Is the Alt key down
+ @return: bool
+
+ """
+ return False
+
+#-------------------------------------------------------------------------#
+
+class ViKeyHandler(KeyHandler):
+ """Defines a key handler for Vi emulation
+ @summary: Handles key presses according to Vi emulation.
+
+ """
+
+ # Vi Mode declarations
+ NORMAL, \
+ INSERT, \
+ VISUAL, \
+ = range(3)
+
+ def __init__(self, stc, use_normal_default=False):
+ super(ViKeyHandler, self).__init__(stc)
+
+ # Attributes
+ self.mode = 0
+ self.last = u''
+ self.last_find = u''
+ self.commander = ed_vim.EditraCommander(self)
+ self.buffer = u''
+
+ # Insert mode by default
+ if use_normal_default:
+ self.NormalMode()
+ else:
+ self.InsertMode()
+
+ def ClearMode(self):
+ """Clear the mode back to default input mode"""
+ # TODO:CJP when newer scintilla is available in 2.9 use
+ # blockcaret methods.
+ self.STC.SetLineCaret()
+ self.BlockMode = False
+ self.last = self.cmdcache = u''
+ super(ViKeyHandler, self).ClearMode()
+
+ def GetHandlerName(self):
+ """Get the name of this handler"""
+ return u'VI'
+
+ def _SetMode(self, newmode, msg):
+ """Set the keyhandlers mode
+ @param newmode: New mode name to change to
+
+ """
+ self.buffer = u'' # Clear buffer from last mode
+ self.mode = newmode
+ # Update status bar
+ evt = ed_event.StatusEvent(ed_event.edEVT_STATUS, self.stc.GetId(),
+ msg, ed_glob.SB_BUFF)
+ wx.PostEvent(self.stc.GetTopLevelParent(), evt)
+
+ def InsertMode(self):
+ """Change to insert mode"""
+ self.stc.SetLineCaret()
+ self.stc.SetOvertype(False)
+ self.BlockMode = False
+ self._SetMode(ViKeyHandler.INSERT, u"INSERT")
+
+ def ReplaceMode(self):
+ """Change to replace mode
+ This really just insert mode with overtype set to true
+
+ """
+ self.stc.SetLineCaret()
+ self.stc.SetOvertype(True)
+ self._SetMode(ViKeyHandler.INSERT, u"REPLACE")
+
+ def NormalMode(self):
+ """Change to normal (command) mode"""
+ if self.IsInsertMode():
+ self.commander.SetLastInsertedText(self.buffer)
+
+ self.stc.SetOvertype(False)
+ self.stc.SetBlockCaret()
+ self.BlockMode = True
+ self.commander.Deselect()
+ self.commander.InsertRepetition()
+ self._SetMode(ViKeyHandler.NORMAL, u'NORMAL')
+
+ def VisualMode(self):
+ """Change to visual (selection) mode"""
+ self.stc.SetBlockCaret()
+ self.BlockMode = True
+ self.stc.SetOvertype(False)
+ self._SetMode(ViKeyHandler.VISUAL, u'VISUAL')
+ self.commander.StartSelection()
+
+ def IsInsertMode(self):
+ """Test if we are in insert mode"""
+ return self.mode == ViKeyHandler.INSERT
+
+ def IsNormalMode(self):
+ """Test if we are in normal mode"""
+ return self.mode == ViKeyHandler.NORMAL
+
+ def IsVisualMode(self):
+ """Test if we are in visual mode"""
+ return self.mode == ViKeyHandler.VISUAL
+
+ def PreProcessKey(self, key_code, ctrldown=False,
+ cmddown=False, shiftdown=False, altdown=False):
+ """Pre process any keys before they get to the char handler
+ @param key_code: Raw keycode
+ @keyword ctrldown: Is the control key down
+ @keyword cmddown: Is the Command key down (Mac osx)
+ @keyword shiftdown: Is the Shift key down
+ @keyword altdown: Is the Alt key down
+ @return: bool
+
+ """
+ if not shiftdown and key_code == wx.WXK_ESCAPE:
+ # If Vi emulation is active go into Normal mode and
+ # pass the key event to the char handler by not processing
+ # the key.
+ self.NormalMode()
+ return False
+ elif (ctrldown or cmddown) and key_code == ord('['):
+ self.NormalMode()
+ return True
+ elif key_code in (wx.WXK_RETURN, wx.WXK_BACK,
+ wx.WXK_RIGHT, wx.WXK_LEFT) and \
+ not self.IsInsertMode():
+ # swallow enter key in normal and visual modes
+ # HACK: we have to do it form here because ProcessKey
+ # is only called on Char events, not Key events,
+ # and the Enter key does not generate a Char event.
+ self.ProcessKey(key_code)
+ return True
+ else:
+ return False
+
+ def ProcessKey(self, key_code, ctrldown=False,
+ cmddown=False, shiftdown=False, altdown=False):
+ """Processes keys and decided whether to interpret them as vim commands
+ or normal insert text
+
+ @param key_code: Raw key code
+ @keyword cmddown: Command/Ctrl key is down
+ @keyword shiftdown: Shift Key is down
+ @keyword altdown : Alt key is down
+
+ """
+ if ctrldown or cmddown or altdown:
+ return False
+
+ # Mode may change after processing the key, so we need to remember
+ # whether this was a command or not
+ f_cmd = self.IsNormalMode() or self.IsVisualMode()
+
+ self._ProcessKey(key_code)
+
+ # Update status bar
+ if self.IsNormalMode():
+ if self.stc.GetTopLevelParent():
+ evt = ed_event.StatusEvent(ed_event.edEVT_STATUS,
+ self.stc.GetId(),
+ u"NORMAL %s" % self.buffer,
+ ed_glob.SB_BUFF)
+ wx.PostEvent(self.stc.GetTopLevelParent(), evt)
+
+ if f_cmd:
+ return True
+ else:
+ # If we're in insert mode we must return False
+ # so the text gets inserted into the editor
+ return False
+
+ def _ProcessKey(self, key_code):
+ """The real processing of keys"""
+ char = unichr(key_code)
+ if self.IsNormalMode() or self.IsVisualMode():
+ self.buffer += char
+ if ed_vim.Parse(self.buffer, self.commander):
+ # command was handled (or invalid) so clear buffer
+ self.buffer = u''
+
+ if self.IsVisualMode():
+ self.commander.ExtendSelection()
+
+ elif self.IsInsertMode():
+ self.buffer += char
+
+ def InsertText(self, pos, text):
+ """Insert text and store it in the buffer if we're in insert mode
+ i.e. as if it was typed in
+
+ """
+ self.stc.InsertText(pos, text)
+ if self.IsInsertMode():
+ self.buffer += text \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_log.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_log.py
new file mode 100644
index 0000000..28ec57a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_log.py
@@ -0,0 +1,277 @@
+###############################################################################
+# Name: Cody Precord #
+# Purpose: Log output viewer for the shelf #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra LogViewer
+
+This module provides classes for managing the log display and filtering of its
+messages. The module also exports an implementation of a shelf plugin for
+displaying a L{LogViewer} in the Shelf.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_log.py 72223 2012-07-28 17:35:57Z CJP $"
+__revision__ = "$Revision: 72223 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import re
+import wx
+
+# Editra Libraries
+import ed_msg
+import eclib
+import iface
+import plugin
+from profiler import Profile_Get
+import ed_glob
+import ed_basewin
+
+#-----------------------------------------------------------------------------#
+# Globals
+_ = wx.GetTranslation
+
+SHOW_ALL_MSG = 'ALL'
+#-----------------------------------------------------------------------------#
+
+# Interface Implementation
+class EdLogViewer(plugin.Plugin):
+ """Shelf interface implementation for the log viewer"""
+ plugin.Implements(iface.ShelfI)
+
+ __name__ = u'Editra Log'
+
+ @staticmethod
+ def AllowMultiple():
+ """EdLogger allows multiple instances"""
+ return True
+
+ @staticmethod
+ def CreateItem(parent):
+ """Returns a log viewr panel"""
+ return LogViewer(parent)
+
+ def GetBitmap(self):
+ """Get the log viewers tab icon
+ @return: wx.Bitmap
+
+ """
+ bmp = wx.ArtProvider.GetBitmap(str(self.GetId()), wx.ART_MENU)
+ return bmp
+
+ @staticmethod
+ def GetId():
+ """Plugin menu identifier ID"""
+ return ed_glob.ID_LOGGER
+
+ @staticmethod
+ def GetMenuEntry(menu):
+ """Get the menu entry for the log viewer
+ @param menu: the menu items parent menu
+
+ """
+ return wx.MenuItem(menu, ed_glob.ID_LOGGER, _("Editra Log"),
+ _("View Editra's console log"))
+
+ def GetName(self):
+ """Return the name of this control"""
+ return self.__name__
+
+ @staticmethod
+ def IsStockable():
+ """EdLogViewer can be saved in the shelf preference stack"""
+ return True
+
+#-----------------------------------------------------------------------------#
+
+# LogViewer Ui Implementation
+class LogViewer(ed_basewin.EdBaseCtrlBox):
+ """LogViewer is a control for displaying and working with output
+ from Editra's log.
+
+ """
+ def __init__(self, parent):
+ super(LogViewer, self).__init__(parent)
+
+ # Attributes
+ self._buffer = LogBuffer(self)
+ self.SetWindow(self._buffer)
+ self._srcfilter = None
+ self._clear = None
+
+ # Layout
+ self.__DoLayout()
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON,
+ lambda evt: self._buffer.Clear(), self._clear)
+ self.Bind(wx.EVT_CHOICE, self.OnChoice, self._srcfilter)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+
+ # Message Handlers
+ ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED)
+
+ def OnDestroy(self, evt):
+ """Cleanup and unsubscribe from messages"""
+ if evt.GetId() == self.GetId():
+ ed_msg.Unsubscribe(self.OnThemeChange)
+
+ def __DoLayout(self):
+ """Layout the log viewer window"""
+ # Setup ControlBar
+ ctrlbar = self.CreateControlBar(wx.TOP)
+
+ # View Choice
+ self._srcfilter = wx.Choice(ctrlbar, wx.ID_ANY, choices=[])
+ ctrlbar.AddControl(wx.StaticText(ctrlbar,
+ label=_("Show output from") + ":"))
+ ctrlbar.AddControl(self._srcfilter)
+
+ # Clear Button
+ ctrlbar.AddStretchSpacer()
+ self._clear = self.AddPlateButton(_("Clear"), ed_glob.ID_DELETE,
+ wx.ALIGN_RIGHT)
+
+ def OnChoice(self, evt):
+ """Set the filter based on the choice controls value
+ @param evt: wx.CommandEvent
+
+ """
+ self._buffer.SetFilter(self._srcfilter.GetStringSelection())
+
+ def OnThemeChange(self, msg):
+ """Update the buttons icon when the icon theme changes
+ @param msg: Message Object
+
+ """
+ cbmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DELETE), wx.ART_MENU)
+ self._clear.SetBitmap(cbmp)
+ self._clear.Refresh()
+
+ def SetSources(self, srclist):
+ """Set the list of available log sources in the choice control
+ @param srclist: list of log sources
+
+ """
+ choice = self._srcfilter.GetStringSelection()
+ lst = sorted(srclist)
+ lst.insert(0, _("All"))
+ self._srcfilter.SetItems(lst)
+ if not self._srcfilter.SetStringSelection(choice):
+ self._srcfilter.SetSelection(0)
+
+#-----------------------------------------------------------------------------#
+class LogBuffer(eclib.OutputBuffer):
+ """Buffer for displaying log messages that are sent on Editra's
+ log channel.
+ @todo: make line buffering configurable through interface
+
+ """
+ RE_WARN_MSG = re.compile(r'\[err\]|\[error\]|\[warn\]')
+ ERROR_STYLE = eclib.OPB_STYLE_MAX + 1
+
+ def __init__(self, parent):
+ super(LogBuffer, self).__init__(parent)
+
+ # Attributes
+ self._filter = SHOW_ALL_MSG
+ self._srcs = list()
+ self.SetLineBuffering(2000)
+
+ # Setup
+ font = Profile_Get('FONT1', 'font', wx.Font(11, wx.FONTFAMILY_MODERN,
+ wx.FONTSTYLE_NORMAL,
+ wx.FONTWEIGHT_NORMAL))
+ self.SetFont(font)
+ style = (font.GetFaceName(), font.GetPointSize(), "#FF0000")
+ self.StyleSetSpec(LogBuffer.ERROR_STYLE,
+ "face:%s,size:%d,fore:#FFFFFF,back:%s" % style)
+
+ # Event Handlers
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+
+ # Subscribe to Editra's Log
+ ed_msg.Subscribe(self.UpdateLog, ed_msg.EDMSG_LOG_ALL)
+
+ def OnDestroy(self, evt):
+ """Unregister from receiving any more log messages"""
+ if evt.GetId() == self.GetId():
+ ed_msg.Unsubscribe(self.UpdateLog)
+ evt.Skip()
+
+ def AddFilter(self, src):
+ """Add a new filter source
+ @param src: filter source string
+ @postcondition: if src is new the parent window is updated
+
+ """
+ if src not in self._srcs:
+ self._srcs.append(src)
+ self.Parent.SetSources(self._srcs)
+
+ def ApplyStyles(self, start, txt):
+ """Apply coloring to error and warning messages
+ @note: overridden from L{outbuff.OutputBuffer}
+ @param start: Start position of text that needs styling in the buffer
+ @param txt: The string of text that starts at the start position in the
+ buffer.
+
+ """
+ for group in LogBuffer.RE_WARN_MSG.finditer(txt):
+ sty_s = start + group.start()
+ sty_e = start + group.end()
+ self.StartStyling(sty_s, 0xff)
+
+ # Highlight error messages with ERROR_STYLE
+ self.SetStyling(sty_e - sty_s, LogBuffer.ERROR_STYLE)
+
+ def SetFilter(self, src):
+ """Set the level of what is shown in the display
+ @param src: Only show messages from src
+ @return: bool
+
+ """
+ if src in self._srcs:
+ self._filter = src
+ return True
+ elif src == _("All"):
+ self._filter = SHOW_ALL_MSG
+ return True
+ else:
+ return False
+
+ def UpdateLog(self, msg):
+ """Add a new log message
+ @param msg: Message Object containing a LogMsg
+
+ """
+ if wx.Thread_IsMain():
+ self.DoUpdateLog(msg)
+ else:
+ # Delegate to main thread
+ wx.CallAfter(self.DoUpdateLog, msg)
+
+ def DoUpdateLog(self, msg):
+ if not self.IsRunning():
+ self.Start(200)
+
+ # Check filters
+ logmsg = msg.GetData()
+ org = logmsg.Origin
+ if org not in self._srcs:
+ self.AddFilter(org)
+
+ if self._filter == SHOW_ALL_MSG:
+ self.AppendUpdate(unicode(logmsg) + unicode(os.linesep))
+ elif self._filter == logmsg.Origin:
+ msg = u"[%s][%s]%s" % (logmsg.ClockTime, logmsg.Type, logmsg.Value)
+ self.AppendUpdate(msg + unicode(os.linesep))
+ else:
+ pass
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_main.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_main.py
new file mode 100644
index 0000000..2e7807d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_main.py
@@ -0,0 +1,1659 @@
+###############################################################################
+# Name: ed_main.py #
+# Purpose: Editra's Main Window #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""@package Editra.src.ed_main
+
+This module provides the L{MainWindow} class for Editra. The MainWindow is
+main Ui component of the editor that contains all the other components.
+
+@summary: MainWindow Component
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_main.py 72388 2012-08-28 16:06:31Z CJP $"
+__revision__ = "$Revision: 72388 $"
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import os
+import sys
+import time
+import wx
+
+# Editra Libraries
+from ed_glob import *
+import util
+import profiler
+import ed_toolbar
+import ed_mpane
+import ed_event
+import ed_msg
+import ed_menu
+import ed_print
+import ed_shelf
+import ed_statbar
+import ed_mdlg
+import prefdlg
+import syntax.syntax as syntax
+import generator
+import plugin
+import ed_fmgr
+import perspective as viewmgr
+import ed_session
+import iface
+import ebmlib
+import eclib
+
+# Function Aliases
+_ = wx.GetTranslation
+_PGET = profiler.Profile_Get
+_PSET = profiler.Profile_Set
+
+#--------------------------------------------------------------------------#
+
+class MainWindow(wx.Frame, viewmgr.PerspectiveManager):
+ """Editras Main Window"""
+ # Clipboard ring is limited to 25 entries
+ CLIPBOARD = util.EdClipboard(25)
+ PRINTER = None
+
+ def __init__(self, parent, id_, wsize, title):
+ """Initialize the Frame and Event Handlers.
+ @param wsize: Windows initial size
+ @param title: Windows Title
+
+ """
+ wx.Frame.__init__(self, parent, id_, title, size=wsize,
+ style=wx.DEFAULT_FRAME_STYLE)
+ viewmgr.PerspectiveManager.__init__(self, CONFIG['CACHE_DIR'])
+
+ # Setup app icon and title
+ util.SetWindowIcon(self)
+
+ # Attributes
+ self._loaded = False
+ self._initialized = False # for GTK OnActivate HACK
+ self._mlock = ebmlib.CallLock()
+ self._last_save = u''
+ self.LOG = wx.GetApp().GetLog()
+ self._exiting = False
+ self._handlers = dict(menu=list(), ui=list())
+
+ #---- Setup File History ----#
+ self.filehistory = ebmlib.EFileHistory(_PGET('FHIST_LVL', 'int', 9))
+
+ #---- Status bar on bottom of window ----#
+ self.SetStatusBar(ed_statbar.EdStatBar(self))
+ self.GetStatusBar().Show(_PGET('STATBAR', default=True))
+ #---- End Statusbar Setup ----#
+
+ #---- Notebook that contains the editing buffers ----#
+ self._mpane = ed_mpane.MainPanel(self)
+ self.nb = self._mpane.GetWindow()
+ self.PanelMgr.AddPane(self._mpane, ed_fmgr.EdPaneInfo(). \
+ Name("EditPane").Center().Layer(1).Dockable(False). \
+ CloseButton(False).MaximizeButton(False). \
+ CaptionVisible(False))
+
+ #---- Command Bar ----#
+ self._mpane.HideCommandBar()
+
+ #---- Pane Navigator ----#
+ self._paneNavi = None
+
+ # Printer Setup
+ if MainWindow.PRINTER is None:
+ MainWindow.PRINTER = ed_print.EdPrinter(self)
+
+ #---- Setup Toolbar ----#
+ self.SetupToolBar()
+ #---- End Toolbar Setup ----#
+
+ #---- Menus ----#
+ menbar = ed_menu.EdMenuBar()
+
+ # Todo this should not be hard coded
+ menbar.GetMenuByName("view").InsertMenu(5, ID_PERSPECTIVES,
+ _("Perspectives"), self.GetPerspectiveControls())
+
+ ## Setup additional menu items
+ self.filehistory.UseMenu(menbar.GetMenuByName("filehistory"))
+
+ # On mac, do this to make help menu appear in correct location
+ # Note it must be done before setting the menu bar and after the
+ # menus have been created.
+ if wx.Platform == '__WXMAC__':
+ wx.GetApp().SetMacHelpMenuTitleName(_("&Help"))
+
+ #---- Menu Bar ----#
+ self.SetMenuBar(menbar)
+
+ #---- Actions to take on menu events ----#
+
+ # Collect Menu Event handler pairs
+ self._handlers['menu'].extend([# File Menu
+ (ID_NEW, self.OnNew),
+ (ID_OPEN, self.OnOpen),
+ (ID_CLOSE, self.OnClosePage),
+ (ID_CLOSEALL, self.OnClosePage),
+ (ID_SAVE, self.OnSave),
+ (ID_SAVEAS, self.OnSaveAs),
+ (ID_SAVEALL, self.OnSave),
+ (ID_REVERT_FILE, self.DispatchToControl),
+ (ID_RELOAD_ENC, self.OnReloadWithEnc),
+ (ID_SAVE_PROFILE, self.OnSaveProfile),
+ (ID_LOAD_PROFILE, self.OnLoadProfile),
+ (ID_SAVE_SESSION, self.OnSaveSession),
+ (ID_LOAD_SESSION, self.OnLoadSession),
+ (ID_EXIT, wx.GetApp().OnExit),
+ (ID_PRINT, self.OnPrint),
+ (ID_PRINT_PRE, self.OnPrint),
+ (ID_PRINT_SU, self.OnPrint),
+
+ # Edit Menu
+ (ID_PASTE_AFTER, self.DispatchToControl),
+ (ID_CYCLE_CLIPBOARD, self.DispatchToControl),
+ (ID_COLUMN_MODE, self.DispatchToControl),
+ (ID_TOGGLE_FOLD, self.DispatchToControl),
+ (ID_TOGGLE_ALL_FOLDS, self.DispatchToControl),
+ (ID_SHOW_AUTOCOMP, self.DispatchToControl),
+ (ID_SHOW_CALLTIP, self.DispatchToControl),
+ (ID_QUICK_FIND, self.OnCommandBar),
+ (ID_PREF, OnPreferences),
+
+ # View Menu
+ (ID_GOTO_LINE, self.OnCommandBar),
+ (ID_GOTO_MBRACE, self.DispatchToControl),
+ (ID_SHOW_SB, self.OnShowStatusBar),
+ (ID_VIEW_TOOL, self.OnViewTb),
+ (ID_PANELIST, self.OnPaneList),
+ (ID_MAXIMIZE_EDITOR, self.OnMaximizeEditor),
+
+ # Format Menu
+ (ID_FONT, self.OnFont),
+
+ # Settings menu
+ (ID_LEXER_CUSTOM, self.OnCustomizeLangMenu),
+
+ # Tool Menu
+ (ID_COMMAND, self.OnCommandBar),
+ (ID_STYLE_EDIT, self.OnStyleEdit),
+ (ID_PLUGMGR, self.OnPluginMgr),
+ (ID_SESSION_BAR, self.OnCommandBar),
+
+ # Help Menu
+ (ID_ABOUT, OnAbout),
+ (ID_HOMEPAGE, self.OnHelp),
+ (ID_DOCUMENTATION, self.OnHelp),
+ (ID_TRANSLATE, self.OnHelp),
+ (ID_CONTACT, self.OnHelp),
+ (ID_BUG_TRACKER, self.OnHelp)])
+
+ self._handlers['menu'].extend([(l_id, self.DispatchToControl)
+ for l_id in syntax.SYNTAX_IDS])
+
+ # Extra menu handlers (need to work these into above system yet)
+ self.Bind(wx.EVT_MENU, self.DispatchToControl)
+ self.Bind(wx.EVT_MENU, self.OnGenerate)
+ self.Bind(wx.EVT_MENU_RANGE, self.OnFileHistory,
+ id=wx.ID_FILE1, id2=wx.ID_FILE9)
+
+ # Update UI Handlers
+ self._handlers['ui'].extend([# File Menu
+ (ID_REVERT_FILE, self.OnUpdateFileUI),
+ (ID_RELOAD_ENC, self.OnUpdateFileUI),
+ # Edit Menu
+ (ID_COPY, self.OnUpdateClipboardUI),
+ (ID_CUT, self.OnUpdateClipboardUI),
+ (ID_PASTE, self.OnUpdateClipboardUI),
+ (ID_PASTE_AFTER, self.OnUpdateClipboardUI),
+ (ID_CYCLE_CLIPBOARD, self.OnUpdateClipboardUI),
+ (ID_UNDO, self.OnUpdateClipboardUI),
+ (ID_REDO, self.OnUpdateClipboardUI),
+ (ID_COLUMN_MODE, self.OnUpdateClipboardUI),
+ # Format Menu
+ (ID_INDENT, self.OnUpdateFormatUI),
+ (ID_USE_SOFTTABS, self.OnUpdateFormatUI),
+ (ID_TO_UPPER, self.OnUpdateFormatUI),
+ (ID_TO_LOWER, self.OnUpdateFormatUI),
+ (ID_WORD_WRAP, self.OnUpdateFormatUI),
+ (ID_EOL_MAC, self.OnUpdateFormatUI),
+ (ID_EOL_WIN, self.OnUpdateFormatUI),
+ (ID_EOL_UNIX, self.OnUpdateFormatUI),
+ # Settings Menu
+ (ID_AUTOCOMP, self.OnUpdateSettingsUI),
+ (ID_AUTOINDENT, self.OnUpdateSettingsUI),
+ (ID_SYNTAX, self.OnUpdateSettingsUI),
+ (ID_FOLDING, self.OnUpdateSettingsUI),
+ (ID_BRACKETHL, self.OnUpdateSettingsUI)])
+
+ # View Menu
+ self._handlers['ui'].extend([(m_id, self.OnUpdateViewUI)
+ for m_id in [ID_ZOOM_NORMAL, ID_ZOOM_IN,
+ ID_ZOOM_OUT, ID_GOTO_MBRACE,
+ ID_HLCARET_LINE, ID_SHOW_SB,
+ ID_VIEW_TOOL, ID_SHOW_WS,
+ ID_SHOW_EDGE, ID_SHOW_EOL,
+ ID_SHOW_LN, ID_INDENT_GUIDES,
+ ID_MAXIMIZE_EDITOR]])
+
+ # Lexer Menu
+ self._handlers['ui'].extend([(l_id, self.OnUpdateLexerUI)
+ for l_id in syntax.SYNTAX_IDS])
+
+ # Perspectives
+ self._handlers['ui'].extend(self.GetPersectiveHandlers())
+
+ #---- End Menu Setup ----#
+
+ #---- Other Event Handlers ----#
+ # Frame
+ self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+ self.Bind(ed_event.EVT_STATUS, self.OnStatus)
+
+ # Find Dialog
+ self._handlers['menu'].extend(self.nb.GetMenuHandlers())
+ self._handlers['ui'].extend(self.nb.GetUiHandlers())
+
+ #---- End other event actions ----#
+
+ #---- Final Setup Calls ----#
+ self.LoadFileHistory(_PGET('FHIST_LVL', fmt='int'))
+
+ # Call add on plugins
+ self.LOG("[ed_main][info] Loading MainWindow Plugins")
+ plgmgr = wx.GetApp().GetPluginManager()
+ addons = MainWindowAddOn(plgmgr)
+ addons.Init(self)
+ self._handlers['menu'].extend(addons.GetEventHandlers())
+ self._handlers['ui'].extend(addons.GetEventHandlers(ui_evt=True))
+ shelf = ed_shelf.Shelf(plgmgr)
+ self._shelf = shelf.Init(self)
+ self._handlers['ui'].extend(shelf.GetUiHandlers(self._shelf))
+
+ self.LOG("[ed_main][info] Loading Generator plugins")
+ generator.Generator(plgmgr).InstallMenu(menbar.GetMenuByName("tools"))
+
+ # Set Perspective and other UI settings
+ self.SetPerspective(_PGET('DEFAULT_VIEW'))
+ self.PanelMgr.Update()
+ # Make sure all clients are updated to user specified display font.
+ ed_msg.PostMessage(ed_msg.EDMSG_DSP_FONT,
+ _PGET('FONT3', 'font', wx.NORMAL_FONT))
+
+ # Message Handlers
+ ed_msg.Subscribe(self.OnUpdateFileHistory, ed_msg.EDMSG_ADD_FILE_HISTORY)
+ ed_msg.Subscribe(self.OnDoSessionSave, ed_msg.EDMSG_SESSION_DO_SAVE)
+ ed_msg.Subscribe(self.OnDoSessionLoad, ed_msg.EDMSG_SESSION_DO_LOAD)
+
+ # HACK: for gtk as most linux window managers manage the windows alpha
+ # and set it when its created.
+ wx.CallAfter(self.InitWindowAlpha)
+
+ __name__ = u"MainWindow"
+
+ def OnDestroy(self, evt):
+ """Disconnect Message Handlers"""
+ if self and evt.Id == self.Id:
+ ed_msg.Unsubscribe(self.OnUpdateFileHistory)
+ ed_msg.Unsubscribe(self.OnDoSessionSave)
+ ed_msg.Unsubscribe(self.OnDoSessionLoad)
+ evt.Skip()
+
+ #---- End Private Member Functions/Variables ----#
+
+ #---- Begin Public Member Function ----#
+ def OnActivate(self, evt):
+ """Activation Event Handler
+ @param evt: wx.ActivateEvent
+
+ """
+ if self._mlock.IsLocked():
+ # Deactivated for popup, leave handlers hooked up
+ wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL)
+ evt.Skip()
+ return
+
+ app = wx.GetApp()
+ active = evt.GetActive()
+
+ # Add or remove handlers from the event stack
+ if active and not self._loaded:
+ self._loaded = True
+ app.SetTopWindow(self)
+
+ # Slow the update interval to reduce overhead
+ wx.UpdateUIEvent.SetUpdateInterval(215)
+ wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_SPECIFIED)
+ self.SetExtraStyle(wx.WS_EX_PROCESS_UI_UPDATES)
+
+ for handler in self._handlers['menu']:
+ app.AddHandlerForID(*handler)
+
+ for handler in self._handlers['ui']:
+ app.AddUIHandlerForID(*handler)
+
+ # HACK find better way to do this later. It seems that on gtk the
+ # window doesn't get activated until later than it does on the
+ # other platforms. So for panels that depend on updating their
+ # initial state we need to send out a fake update message here.
+ if wx.Platform == '__WXGTK__' and not self._initialized:
+ self._initialized = True
+ nb = self.GetNotebook()
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGED,
+ (nb, nb.GetSelection()))
+ elif not active:
+ self._loaded = False
+ self.DeActivate()
+
+ # Notify that window has become active/inactive
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_MW_ACTIVATE,
+ dict(active=active), self.Id)
+
+ evt.Skip()
+
+ def OnUpdateFileHistory(self, msg):
+ """Update filehistory menu for new files that were opened
+ @param msg: Message object (data == filename)
+
+ """
+ # May get notified after/during delete
+ if self:
+ try:
+ self.filehistory.AddFileToHistory(msg.GetData())
+ except wx.PyAssertionError:
+ # ignore errors that wxMac sometimes raises about unicode data
+ pass
+
+ def AddFileToHistory(self, fname):
+ """Add a file to the windows file history as well as any
+ other open windows history.
+ @param fname: name of file to add
+ @todo: change the file history to a centrally managed object that
+ all windows pull from to avoid this quick solution.
+
+ """
+ if _PGET('FHIST_LVL', 'int', 9) > 0:
+ ed_msg.PostMessage(ed_msg.EDMSG_ADD_FILE_HISTORY, fname)
+
+ def AddMenuHandler(self, menu_id, handler):
+ """Add a menu event handler to the handler stack
+ @param menu_id: Menu item id
+ @param handler: Handler callable
+ @postcondition: handler is added only if its not already in the set
+
+ """
+ for item in self._handlers['menu']:
+ if item[0] == menu_id:
+ return
+ else:
+ self._handlers['menu'].append((menu_id, handler))
+
+ def AddUIHandler(self, menu_id, handler):
+ """Add a UpdateUI event handler to the handler stack
+ @param menu_id: Menu item id
+ @param handler: Handler callable
+ @postcondition: handler is added only if its not already in the set
+
+ """
+ for item in self._handlers['ui']:
+ if item[0] == menu_id:
+ return
+ else:
+ self._handlers['ui'].append((menu_id, handler))
+
+ def DoOpen(self, evt, fname=u'', lnum=-1):
+ """ Do the work of opening a file and placing it
+ in a new notebook page.
+ @keyword fname: can be optionally specified to open
+ a file without opening a FileDialog
+ @keyword lnum: Explicitly set the line number to open the file to
+
+ """
+ try:
+ e_id = evt.GetId()
+ except AttributeError:
+ e_id = evt
+
+ if e_id == ID_OPEN:
+ fdir = self.GetNotebook().GetCurrentCtrl().GetFileName()
+ if len(fdir):
+ fdir = os.path.dirname(fdir)
+ elif not hasattr(sys, 'frozen'):
+ fdir = os.curdir
+
+ dlg = wx.FileDialog(self, _("Editra: Open"), fdir, "",
+ ''.join(syntax.GenFileFilters()),
+ wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR)
+ dlg.SetFilterIndex(_PGET('FFILTER', 'int', 0))
+
+ if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
+ _PSET('FFILTER', dlg.GetFilterIndex())
+ for path in dlg.GetPaths():
+ if _PGET('OPEN_NW', default=False):
+ wx.GetApp().OpenNewWindow(path)
+ else:
+ self.nb.OpenPage(ebmlib.GetPathName(path),
+ ebmlib.GetFileName(path))
+ self.nb.GoCurrentPage()
+
+ dlg.Destroy()
+ else:
+ self.LOG("[ed_main][info] CMD Open File: %s" % fname)
+ self.nb.OpenPage(ebmlib.GetPathName(fname),
+ ebmlib.GetFileName(fname), quiet=True)
+ self.nb.GoCurrentPage()
+
+ # lnum arg is only used with command line open
+ if lnum >= 0:
+ buff = self.nb.GetCurrentCtrl()
+ buff.GotoLine(lnum)
+
+ self.Raise()
+
+ def DeActivate(self):
+ """Helper method for the App to tell this window to remove
+ all its event handlers.
+
+ """
+ self.SetExtraStyle(0)
+
+ # HACK set update ui events back to process all here in case
+ # opened dialog needs them. Not sure why this is necessary but it
+ # is the only solution I could find to fix the external find
+ # dialogs so that their buttons become enabled when typing in the
+ # text control.
+ #
+ # If the windows that took the active position is another mainwindow
+ # it will set the events back to UPDATE_UI_PROCESS_SPECIFIED to
+ # prevent all the toolbars/menu items of each window from updating
+ # when they dont need to.
+ wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL)
+ self.FlushEventStack()
+
+ def FlushEventStack(self):
+ """Clear the Menu and UpdateUI event handler stack
+ @note: only unregisters this frames handlers from the app
+
+ """
+ app = wx.GetApp()
+ for handler in self._handlers['menu']:
+ app.RemoveHandlerForID(handler[0])
+
+ for handler in self._handlers['ui']:
+ app.RemoveUIHandlerForID(handler[0])
+
+ def GetCommandbar(self):
+ """Get this windows command bar
+ @return: ed_cmdbar.CommandBarBase
+
+ """
+ return self._mpane.GetControlBar(wx.BOTTOM)
+
+ def GetEditPane(self):
+ """Get the editor notebook/command bar control
+ @return: ed_mpane.MainPane
+
+ """
+ return self._mpane
+
+ def GetNotebook(self):
+ """Get the windows main notebook that contains the editing buffers
+ @return: reference to L{extern.flatnotebook.FlatNotebook} instance
+
+ """
+ return getattr(self, 'nb', None)
+
+ def GetShelf(self):
+ """Get this windows Shelf
+ @return: reference to L{iface.Shelf} instance
+ @note: returns the plugin instance not the actual notebook, if
+ a reference to the notebook is needed for parenting call
+ GetWindow on the object returned by this function.
+
+ """
+ return self._shelf
+
+ def IsExiting(self):
+ """Returns whether the windows is in the process of exiting
+ or not.
+ @return: boolean stating if the window is exiting or not
+
+ """
+ return self._exiting
+
+ def IsTopWindow(self):
+ """Is this main window 'the' current top window
+ @return: bool
+
+ """
+ return wx.GetApp().GetTopWindow() == self
+
+ def LoadFileHistory(self, size):
+ """Loads file history from profile
+ @return: None
+
+ """
+ try:
+ hist_list = _PGET('FHIST', default=list())
+ if len(hist_list) > size:
+ hist_list = hist_list[:size]
+ self.filehistory.History = hist_list
+ except (Exception, wx.PyAssertionError), msg:
+ self.LOG("[ed_main][err] Filehistory load failed: %s" % msg)
+
+ def OnNew(self, evt):
+ """Start a New File in a new tab
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.GetId() == ID_NEW:
+ self.nb.NewPage()
+ self.nb.GoCurrentPage()
+ else:
+ evt.Skip()
+
+ def OnOpen(self, evt):
+ """Open a File
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.GetId() == ID_OPEN:
+ self.DoOpen(evt)
+ else:
+ evt.Skip()
+
+ def OnFileHistory(self, evt):
+ """Open a File from the File History
+ @param evt: wx.MenuEvent
+
+ """
+ fnum = evt.GetId() - wx.ID_FILE1
+ fname = self.filehistory.GetHistoryFile(fnum)
+
+ # Check if file still exists
+ if not os.path.exists(fname):
+ mdlg = wx.MessageDialog(self, _("%s could not be found.\nPerhaps "
+ "it's been moved or deleted.") % \
+ fname, _("File Not Found"),
+ wx.OK | wx.ICON_WARNING)
+ mdlg.CenterOnParent()
+ ebmlib.LockCall(self._mlock, mdlg.ShowModal)
+ mdlg.Destroy()
+ # Remove offending file from history
+ self.filehistory.RemoveFileFromHistory(fnum)
+ else:
+ self.DoOpen(evt, fname)
+
+ def OnClosePage(self, evt):
+ """Close a page
+ @param evt: wx.MenuEvent
+
+ """
+ if not self.IsActive():
+ evt.Skip()
+ return
+
+ e_id = evt.Id
+ if e_id == ID_CLOSE:
+ self.nb.ClosePage()
+ elif e_id == ID_CLOSEALL:
+ self.nb.CloseAllPages()
+ else:
+ evt.Skip()
+
+ def SaveFile(self, tablbl, buf):
+ """Save the given page in the notebook
+ @param tablbl: main notebook tab label
+ @param buf: EdEditView instance
+ @note: intended for internal use! method signature may change
+
+ """
+ fname = ebmlib.GetFileName(buf.GetFileName())
+ if fname != u'':
+ fpath = buf.GetFileName()
+ result = buf.SaveFile(fpath)
+ self._last_save = fpath
+ if result:
+ self.PushStatusText(_("Saved File: %s") % fname, SB_INFO)
+ else:
+ err = buf.GetDocument().GetLastError()
+ self.PushStatusText(_("ERROR: %s") % err, SB_INFO)
+ ed_mdlg.SaveErrorDlg(self, fname, err)
+ buf.GetDocument().ResetAll()
+ else:
+ self.OnSaveAs(ID_SAVEAS, tablbl, buf)
+
+ def SaveCurrentBuffer(self):
+ """Save the file in the currently selected editor buffer"""
+ page = self.nb.GetSelection()
+ self.SaveFile(self.nb.GetPageText(page), self.nb.GetCurrentCtrl())
+
+ def SaveAllBuffers(self):
+ """Save all open editor buffers"""
+ for page in range(self.nb.GetPageCount()):
+ buff = self.nb.GetPage(page)
+ if isinstance(buff, wx.stc.StyledTextCtrl):
+ if buff.GetModify():
+ self.SaveFile(self.nb.GetPageText(page), buff)
+
+ def OnSave(self, evt):
+ """Save Current or All Buffers
+ @param evt: wx.MenuEvent
+
+ """
+ e_id = evt.Id
+ if e_id == ID_SAVE:
+ self.SaveCurrentBuffer()
+ elif e_id == ID_SAVEALL:
+ self.SaveAllBuffers()
+ else:
+ evt.Skip()
+ return
+
+ def OnSaveAs(self, evt, title=u'', page=None):
+ """Save File Using a new/different name
+ @param evt: wx.MenuEvent
+
+ """
+ if page:
+ ctrl = page
+ else:
+ ctrl = self.nb.GetCurrentCtrl()
+
+ if title == u'':
+ title = os.path.split(ctrl.GetFileName())[1]
+
+ sdir = ctrl.GetFileName()
+ if sdir is None or not len(sdir):
+ sdir = self._last_save
+
+ dlg = wx.FileDialog(self, _("Choose a Save Location"),
+ os.path.dirname(sdir),
+ title.lstrip(u"*"),
+ u''.join(syntax.GenFileFilters()),
+ wx.SAVE | wx.OVERWRITE_PROMPT)
+
+ if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
+ path = dlg.GetPath()
+ dlg.Destroy()
+
+ result = ctrl.SaveFile(path)
+ fname = ebmlib.GetFileName(ctrl.GetFileName())
+ if not result:
+ err = ctrl.GetDocument().GetLastError()
+ ed_mdlg.SaveErrorDlg(self, fname, err)
+ ctrl.GetDocument().ResetAll()
+ self.PushStatusText(_("ERROR: Failed to save %s") % fname, SB_INFO)
+ else:
+ self._last_save = path
+ self.PushStatusText(_("Saved File As: %s") % fname, SB_INFO)
+ self.SetTitle("%s - file://%s" % (fname, ctrl.GetFileName()))
+ self.nb.SetPageText(self.nb.GetSelection(), fname)
+ self.nb.GetCurrentCtrl().FindLexer()
+ self.nb.UpdatePageImage()
+ self.AddFileToHistory(ctrl.GetFileName())
+ else:
+ dlg.Destroy()
+
+ def OnSaveProfile(self, evt):
+ """Saves current settings as a profile
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.Id == ID_SAVE_PROFILE:
+ dlg = wx.FileDialog(self, _("Where to Save Profile?"), \
+ CONFIG['PROFILE_DIR'], "default.ppb", \
+ _("Profile") + " (*.ppb)|*.ppb",
+ wx.SAVE | wx.OVERWRITE_PROMPT)
+
+ if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
+ profiler.TheProfile.Write(dlg.GetPath())
+ self.PushStatusText(_("Profile Saved as: %s") % \
+ dlg.GetFilename(), SB_INFO)
+ dlg.Destroy()
+ else:
+ evt.Skip()
+
+ def OnLoadProfile(self, evt):
+ """Loads a profile and refreshes the editors state to match
+ the settings found in the profile file.
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.Id == ID_LOAD_PROFILE:
+ dlg = wx.FileDialog(self, _("Load a Custom Profile"),
+ CONFIG['PROFILE_DIR'], "default.ppb",
+ _("Profile") + " (*.ppb)|*.ppb", wx.OPEN)
+
+ if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
+ profiler.TheProfile.Load(dlg.GetPath())
+ self.PushStatusText(_("Loaded Profile: %s") % \
+ dlg.GetFilename(), SB_INFO)
+ dlg.Destroy()
+
+ # Update editor to reflect loaded profile
+ for win in wx.GetApp().GetMainWindows():
+ win.nb.UpdateTextControls()
+ else:
+ evt.Skip()
+
+ def OnDoSessionSave(self, msg):
+ """ed_msg interface for initiating a session save"""
+ if msg.Context == self.Id:
+ self.DoSaveSessionAs()
+
+ def OnSaveSession(self, evt):
+ """Save the current session of open files."""
+ if evt.Id == ID_SAVE_SESSION:
+ self.DoSaveSessionAs()
+ else:
+ evt.Skip()
+
+ def DoSaveSessionAs(self):
+ """Prompt the user to save the current session"""
+ mgr = ed_session.EdSessionMgr()
+ cses = _PGET('LAST_SESSION', default=u"")
+ if cses == mgr.DefaultSession:
+ cses = u""
+ fname = ebmlib.LockCall(self._mlock, wx.GetTextFromUser,
+ (_("Session Name"), _("Save Session"), cses))
+ fname = fname.strip()
+ if fname:
+ rval = self.nb.SaveSessionFile(fname)
+ if rval is not None:
+ wx.MessageBox(rval[1], rval[0], wx.OK|wx.ICON_ERROR)
+ return
+
+ _PSET('LAST_SESSION', fname)
+ self.PushStatusText(_("Session Saved as: %s") % fname, SB_INFO)
+
+ def OnDoSessionLoad(self, msg):
+ """Initiate the loading of a session"""
+ if msg.Context == self.Id:
+ ses = msg.GetData()
+ if ses:
+ self.DoLoadSession(ses)
+
+ def OnLoadSession(self, evt):
+ """Load a saved session."""
+ if evt.Id == ID_LOAD_SESSION:
+ mgr = ed_session.EdSessionMgr()
+ sessions = mgr.GetSavedSessions()
+ cses = _PGET('LAST_SESSION')
+ if cses in sessions:
+ sessions.remove(cses)
+ if len(sessions) and (sessions[0] == mgr.DefaultSession):
+ sessions[0] = _("Default")
+ if cses == mgr.DefaultSession:
+ cses = _("Default")
+ fname = ebmlib.LockCall(self._mlock, wx.GetSingleChoice,
+ (_("Session to Load:\nCurrent Session: '%s'") % cses,
+ _("Load Session"),
+ sessions))
+ if fname:
+ self.DoLoadSession(fname)
+ else:
+ evt.Skip()
+
+ def DoLoadSession(self, fname):
+ """Load the specified session
+ @param fname: session name
+
+ """
+ if fname:
+ mgr = ed_session.EdSessionMgr()
+ if fname == _("Default"):
+ fname = mgr.DefaultSession
+ nbook = self.GetNotebook()
+ rval = nbook.LoadSessionFile(fname)
+
+ # Check for an error during load
+ if rval is not None:
+ wx.MessageBox(rval[1], rval[0], wx.OK|wx.ICON_WARNING)
+ return
+
+ _PSET('LAST_SESSION', fname)
+ if fname == mgr.DefaultSession:
+ fname = _("Default")
+ self.PushStatusText(_("Loaded Session: %s") % fname, SB_INFO)
+
+ def OnStatus(self, evt):
+ """Update status text with messages from other controls
+ @param evt: event that called this handler
+
+ """
+ self.SetStatusText(evt.GetMessage(), evt.GetSection())
+
+ def OnPrint(self, evt):
+ """Handles sending the current document to the printer,
+ showing print previews, and opening the printer settings
+ dialog.
+ @todo: is any manual cleanup required for the printer objects?
+ @param evt: wxMenuEvent
+
+ """
+ e_id = evt.Id
+ printer = MainWindow.PRINTER
+ ctrl = self.nb.GetCurrentCtrl()
+ if not ctrl:
+ util.Log("[ed_main][warn] invalid control reference for printing: %s" % repr(ctrl))
+ wx.MessageBox(_("Failed to get control reference for printing"),
+ _("Print failure"), wx.CENTER|wx.ICON_ERROR|wx.OK)
+ return
+
+ printer.SetStc(ctrl)
+ printer.SetColourMode(_PGET('PRINT_MODE'))
+ if e_id == ID_PRINT:
+ printer.Print()
+ elif e_id == ID_PRINT_PRE:
+ printer.Preview()
+ elif e_id == ID_PRINT_SU:
+ printer.PageSetup()
+ else:
+ evt.Skip()
+
+ def Close(self, force=False):
+ """Close the window
+ @param force: force the closer by vetoing the event handler
+
+ """
+ if force:
+ return super(MainWindow, self).Close(True)
+ else:
+ result = self.OnClose()
+ return not result
+
+ def OnClose(self, evt=None):
+ """Close this frame and unregister it from the applications
+ mainloop.
+ @note: Closing the frame will write out all session data to the
+ users configuration directory.
+ @keyword evt: wx.MenuEvent
+ @return: None on destroy, or True on cancel
+
+ """
+ # Only auto-save session file if not using default session
+ mgr = ed_session.EdSessionMgr()
+ if _PGET('LAST_SESSION') == mgr.DefaultSession:
+ self.nb.SaveCurrentSession()
+
+ # Cleanup Controls
+ self._exiting = True
+ controls = self.nb.GetPageCount()
+ self.LOG("[ed_main][evt] OnClose: Number of controls: %d" % controls)
+ with eclib.Freezer(self) as _tmp:
+ while controls:
+ if controls <= 0:
+ self.Close(True) # Force exit since there is a problem
+
+ self.LOG("[ed_main][evt] OnClose: Requesting Page Close")
+ if not self.nb.ClosePage():
+ self._exiting = False
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGED,
+ (self.nb, self.nb.GetSelection()))
+ return True
+ controls -= 1
+
+ ### If we get to here there is no turning back so cleanup
+ ### additional items and save user settings
+
+ # Write out saved document information
+ self.nb.DocMgr.WriteBook()
+ syntax.SyntaxMgr().SaveState()
+
+ # Save Shelf contents
+ _PSET('SHELF_ITEMS', self._shelf.GetItemStack())
+ _PSET('SHELF_LAYOUT', self._shelf.GetPerspective())
+ _PSET('SHELF_SELECTION', self._shelf.GetSelection())
+
+ # Save Window Size/Position for next launch
+ self.UpdateAutoPerspective()
+
+ # XXX On wxMac the window size doesnt seem to take the toolbar
+ # into account so destroy it so that the window size is accurate.
+ if wx.Platform == '__WXMAC__' and self.GetToolBar():
+ self.ToolBar.Destroy()
+
+ # Raise the window from being iconized so that the size and position is
+ # correct for the next launch (msw).
+ if self.IsIconized():
+ self.Iconize(False)
+
+ _PSET('WSIZE', self.GetSizeTuple())
+ _PSET('MAXIMIZED', self.IsMaximized())
+ _PSET('WPOS', self.GetPositionTuple())
+
+ self.LOG("[ed_main][evt] OnClose: Closing editor at pos=%s size=%s" % \
+ (_PGET('WPOS', 'str'), _PGET('WSIZE', 'str')))
+
+ # Cleanup file history
+ # TODO: Find out why filehistory can be undefined by this point
+ # sometimes.
+ try:
+ _PSET('FHIST', self.filehistory.History)
+ except AttributeError:
+ self.LOG("[ed_main][err] OnClose: Trapped AttributeError OnExit")
+
+ # Update profile
+ ppath = _PGET('MYPROFILE')
+ profiler.TheProfile.Write(ppath)
+ self.LOG("[ed_main][info] Saving profile to %s" % ppath)
+
+ # Post exit notice to all aui panes
+ panes = self.PanelMgr.GetAllPanes()
+ exit_evt = ed_event.MainWindowExitEvent(ed_event.edEVT_MAINWINDOW_EXIT,
+ wx.ID_ANY)
+ for pane in panes:
+ if pane.window:
+ wx.PostEvent(pane.window, exit_evt)
+
+ # Finally close the window
+ self.LOG("[ed_main][evt] OnClose: Closing Main Frame")
+ wx.GetApp().UnRegisterWindow(repr(self))
+
+ # Ensure that event handlers have been un registered from the app
+ wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL)
+
+ # Cleanup
+ mpane = None
+ for pane in self.PanelMgr.AllPanes:
+ if pane and pane.window:
+ win = pane.window
+ if isinstance(win, ed_mpane.MainPanel):
+ mpane = win
+ continue
+ elif self.PanelMgr.DetachPane(win):
+ win.Destroy()
+
+ # NOTE: wxBUG? calling destroy on the center pane results in
+ # a pure virtual function call error. So just destroy
+ # the child Notebook.
+ if mpane:
+ if mpane.Book:
+ mpane.Book.Destroy()
+
+ self.PanelMgr.UnInit()
+ self.Destroy()
+
+ #---- End File Menu Functions ----#
+
+ #---- View Menu Functions ----#
+ def OnShowStatusBar(self, evt):
+ """Toggles visibility of status bar
+ @param evt: wxMenuEvent
+
+ """
+ if evt.Id == ID_SHOW_SB:
+ show = not self.GetStatusBar().IsShown()
+ _PSET('STATBAR', show)
+ self.GetStatusBar().Show(show)
+ self.SendSizeEvent()
+ else:
+ evt.Skip()
+
+ def OnViewTb(self, evt):
+ """Toggles visibility of toolbar
+ @param evt: wxMenuEvent
+
+ """
+ if evt.Id == ID_VIEW_TOOL:
+ size = self.GetSize()
+ toolbar = self.GetToolBar()
+ if _PGET('TOOLBAR', 'bool', False) or toolbar.IsShown():
+ _PSET('TOOLBAR', False)
+ toolbar.Hide()
+ if wx.Platform != '__WXMAC__':
+ self.SetSize((size[0], size[1] - toolbar.GetSize()[1]))
+ else:
+ _PSET('TOOLBAR', True)
+ toolbar.Show()
+ if wx.Platform != '__WXMAC__':
+ self.SetSize((size[0], size[1] + toolbar.GetSize()[1]))
+
+ self.SendSizeEvent()
+ self.Refresh()
+ self.Update()
+ else:
+ evt.Skip()
+
+ def OnMaximizeEditor(self, evt):
+ """Maximize the editor and hide the other panes. If the editor
+ is already maximized, it is un-maximized and the other panes are restored
+ @param evt: CommandEvent instance
+
+ """
+ paneInfo = self.PanelMgr.GetPane("EditPane")
+ if self.PanelMgr.IsEditorMaximized():
+ self.PanelMgr.RestorePane(paneInfo)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_RESTORE, context=self.GetId())
+ else:
+ self.PanelMgr.MaximizePane(paneInfo)
+ self.PanelMgr.Update()
+
+ #---- End View Menu Functions ----#
+
+ #---- Format Menu Functions ----#
+ def OnFont(self, evt):
+ """Open Font Settings Dialog for changing fonts on a per document
+ basis.
+ @note: This currently does not allow for font settings to stick
+ from one session to the next.
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.Id == ID_FONT:
+ ctrl = self.nb.GetCurrentCtrl()
+ fdata = wx.FontData()
+ fdata.SetInitialFont(ctrl.GetDefaultFont())
+ dlg = wx.FontDialog(self, fdata)
+ result = ebmlib.LockCall(self._mlock, dlg.ShowModal)
+ data = dlg.GetFontData()
+ dlg.Destroy()
+ if result == wx.ID_OK:
+ font = data.GetChosenFont()
+ ctrl.SetGlobalFont(self.nb.control.FONT_PRIMARY, \
+ font.GetFaceName(), font.GetPointSize())
+ ctrl.SetGlobalFont(self.nb.control.FONT_SECONDARY, \
+ font.GetFaceName(), font.GetPointSize())
+ ctrl.UpdateAllStyles()
+ else:
+ evt.Skip()
+
+ #---- End Format Menu Functions ----#
+
+ #---- Tools Menu Functions ----#
+ def OnStyleEdit(self, evt):
+ """Opens the style editor
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.Id == ID_STYLE_EDIT:
+ import style_editor
+ dlg = style_editor.StyleEditor(self)
+ dlg.CenterOnParent()
+ ebmlib.LockCall(self._mlock, dlg.ShowModal)
+ dlg.Destroy()
+ else:
+ evt.Skip()
+
+ def OnPluginMgr(self, evt):
+ """Opens and shows Plugin Manager window
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.Id == ID_PLUGMGR:
+ import plugdlg
+ win = wx.GetApp().GetWindowInstance(plugdlg.PluginDialog)
+ if win is not None:
+ win.Raise()
+ return
+ dlg = plugdlg.PluginDialog(self, wx.ID_ANY, PROG_NAME + " " \
+ + _("Plugin Manager"), \
+ size=wx.Size(550, 450))
+ dlg.CenterOnParent()
+ dlg.Show()
+ else:
+ evt.Skip()
+
+ def OnGenerate(self, evt):
+ """Generates a given document type
+ @pre: PluginMgr must be initialized and have active
+ plugins that implement the Generator Interface
+ @param evt: wx.MenuEvent
+
+ """
+ gen = generator.Generator(wx.GetApp().GetPluginManager())
+ doc = gen.GenerateText(evt.Id, self.nb.GetCurrentCtrl())
+ if doc:
+ self.nb.NewPage()
+ ctrl = self.nb.GetCurrentCtrl()
+ ctrl.SetText(doc[1])
+ ctrl.FindLexer(doc[0])
+ else:
+ evt.Skip()
+
+ #---- Misc Function Definitions ----#
+ def DispatchToControl(self, evt):
+ """Catches events that need to be passed to the current
+ text control for processing.
+ @param evt: wx.MenuEvent
+
+ """
+ if not self.IsActive():
+ evt.Skip()
+ return
+
+ e_id = evt.Id
+ ctrl = self.nb.GetCurrentCtrl()
+ active_only = [ ID_ZOOM_IN, ID_ZOOM_OUT, ID_ZOOM_NORMAL,
+ ID_JOIN_LINES, ID_CUT_LINE, ID_COPY_LINE, ID_INDENT,
+ ID_UNINDENT, ID_TRANSPOSE, ID_TOGGLECOMMENT,
+ ID_LINE_MOVE_UP, ID_LINE_MOVE_DOWN,
+ ID_SELECTALL, ID_UNDO, ID_REDO, ID_CUT, ID_COPY,
+ ID_PASTE, ID_LINE_BEFORE, ID_LINE_AFTER, ID_DUP_LINE,
+ ID_PASTE_AFTER, ID_COLUMN_MODE, ID_TOGGLE_FOLD,
+ ID_CYCLE_CLIPBOARD,
+ ID_TOGGLE_ALL_FOLDS, ID_DELETE_LINE,
+ ID_SHOW_AUTOCOMP, ID_SHOW_CALLTIP ]
+
+ # Special handling for common clipboard related actions
+ has_focus = self.FindFocus()
+ is_stc = isinstance(has_focus, wx.stc.StyledTextCtrl)
+ if has_focus is not None:
+ if e_id == ID_PASTE and hasattr(has_focus, 'Paste'):
+ has_focus.Paste()
+ return
+ elif e_id == ID_CYCLE_CLIPBOARD:
+ start, end = has_focus.GetSelection()
+ start, end = min(start, end), max(start, end)
+
+ if is_stc:
+ txt = has_focus.GetTextRange(start, end)
+ elif hasattr(has_focus, 'GetRange'):
+ txt = has_focus.GetRange(start, end)
+ else:
+ self.LOG("[ed_main][warn] no range meth in cycle clipboard")
+ return
+
+ if not MainWindow.CLIPBOARD.IsAtIndex(txt):
+ MainWindow.CLIPBOARD.Reset()
+
+ next = MainWindow.CLIPBOARD.GetNext()
+ if is_stc:
+ has_focus.ReplaceSelection(next)
+ elif hasattr(has_focus, 'Replace'):
+ has_focus.Replace(start, end, next)
+ else:
+ return
+
+ has_focus.SetSelection(start, start+len(next))
+ return
+ elif e_id == ID_CUT and hasattr(has_focus, 'Cut'):
+ start, end = has_focus.GetSelection()
+ if is_stc:
+ txt = has_focus.GetTextRange(start, end)
+ elif hasattr(has_focus, 'GetRange'):
+ txt = has_focus.GetRange(start, end)
+ MainWindow.CLIPBOARD.Put(txt)
+ has_focus.Cut()
+ return
+ elif e_id == ID_COPY and hasattr(has_focus, 'Copy'):
+ start, end = has_focus.GetSelection()
+ if is_stc:
+ txt = has_focus.GetTextRange(start, end)
+ elif hasattr(has_focus, 'GetRange'):
+ txt = has_focus.GetRange(start, end)
+ MainWindow.CLIPBOARD.Put(txt)
+ has_focus.Copy()
+ return
+ elif e_id == ID_REDO and hasattr(has_focus, 'Redo'):
+ has_focus.Redo()
+ return
+ elif e_id == ID_UNDO and hasattr(has_focus, 'Undo'):
+ has_focus.Undo()
+ return
+ elif e_id == ID_SELECTALL and hasattr(has_focus, 'SelectAll'):
+ has_focus.SelectAll()
+ return
+
+ menu_ids = list(syntax.SYNTAX_IDS)
+ menu_ids.extend([ID_SHOW_EOL, ID_SHOW_WS, ID_INDENT_GUIDES, ID_SYNTAX,
+ ID_WORD_WRAP, ID_BRACKETHL, ID_EOL_MAC, ID_EOL_UNIX,
+ ID_EOL_WIN, ID_NEXT_MARK, ID_PRE_MARK, ID_ADD_BM,
+ ID_DEL_ALL_BM, ID_FOLDING, ID_AUTOCOMP, ID_SHOW_LN,
+ ID_AUTOINDENT, ID_TAB_TO_SPACE, ID_SPACE_TO_TAB,
+ ID_TRIM_WS, ID_SHOW_EDGE, ID_MACRO_START,
+ ID_MACRO_STOP, ID_MACRO_PLAY, ID_TO_LOWER,
+ ID_TO_UPPER, ID_USE_SOFTTABS,
+ ID_GOTO_MBRACE, ID_HLCARET_LINE, ID_REVERT_FILE,
+ ])
+ menu_ids.extend(active_only)
+
+ if e_id in menu_ids:
+ ctrl.ControlDispatch(evt)
+ else:
+ evt.Skip()
+ return
+
+ def OnReloadWithEnc(self, evt):
+ """Reload the current file with a specified encoding
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.Id == ID_RELOAD_ENC:
+ ctrl = self.nb.GetCurrentCtrl()
+ doc = ctrl.GetDocument()
+ cenc = doc.GetEncoding()
+ dlg = eclib.EncodingDialog(self.GetNotebook(),
+ msg=_("Select an encoding to reload the file with"),
+ title=_("Reload with Encoding"),
+ default=cenc)
+ bmp = wx.ArtProvider.GetBitmap(str(ID_DOCPROP), wx.ART_OTHER)
+ if bmp.IsOk():
+ dlg.SetBitmap(bmp)
+ dlg.CenterOnParent()
+
+ if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
+ nenc = dlg.GetEncoding()
+ doc.SetEncoding(nenc)
+ success = ctrl.ReloadFile()[0]
+ if not success:
+ msg = _("Failed to reload the file with: %(encoding)s") % dict(encoding=nenc)
+ wx.MessageBox(msg, style=wx.OK|wx.ICON_ERROR)
+ # Revert to previous encoding
+ doc.SetEncoding(cenc)
+ ctrl.ReloadFile()
+ dlg.Destroy()
+ else:
+ evt.Skip()
+
+ def OnPaneList(self, evt):
+ """Navigates through panes
+ @param evt: CommandEvent instance
+
+ """
+ if evt.Id == ID_PANELIST:
+ if self._paneNavi is not None:
+ return
+
+ bmp = wx.ArtProvider.GetBitmap(str(ID_NEW_WINDOW), wx.ART_MENU)
+ self._paneNavi = eclib.AuiPaneNavigator(self, self.PanelMgr, bmp,
+ _("Aui Pane Navigator"))
+ self._paneNavi.SetReturnCode(wx.ID_OK)
+ ebmlib.LockCall(self._mlock, self._paneNavi.ShowModal)
+
+ sel = self._paneNavi.GetSelection()
+ self._paneNavi.Destroy()
+ self._paneNavi = None
+
+ if isinstance(sel, basestring):
+ paneInfo = self.PanelMgr.GetPane(sel)
+ if paneInfo.IsOk():
+ if not paneInfo.IsShown():
+ paneInfo.Show()
+ self.PanelMgr.Update()
+ # Notify activation if the window supports it
+ if hasattr(paneInfo.window, "OnShowAUIPane"):
+ paneInfo.window.OnShowAUIPane()
+ paneInfo.window.SetFocus()
+ else:
+ evt.Skip()
+
+ # Menu Update Handlers
+ def OnUpdateFileUI(self, evt):
+ """Update filemenu items
+ @param evt: EVT_UPDATE_UI
+
+ """
+ if not self.IsActive():
+ return
+
+ e_id = evt.Id
+ ctrl = self.nb.GetCurrentCtrl()
+ if e_id == ID_REVERT_FILE:
+ evt.Enable(ctrl.GetModify())
+ elif e_id == ID_RELOAD_ENC:
+ evt.Enable(len(ctrl.GetFileName()))
+ else:
+ evt.Skip()
+
+ def OnUpdateClipboardUI(self, evt):
+ """Update clipboard related menu/toolbar items
+ @param evt: EVT_UPDATE_UI
+
+ """
+ if not self.IsActive():
+ return
+
+ e_id = evt.Id
+ focus = self.FindFocus()
+ enable = False
+ if e_id == ID_UNDO:
+ if hasattr(focus, 'CanUndo'):
+ enable = focus.CanUndo()
+ evt.Enable(enable)
+ elif e_id == ID_REDO:
+ if hasattr(focus, 'CanRedo'):
+ enable = focus.CanRedo()
+ evt.Enable(enable)
+ elif e_id in (ID_PASTE, ID_PASTE_AFTER, ID_CYCLE_CLIPBOARD):
+ if hasattr(focus, 'CanPaste'):
+ enable = focus.CanPaste()
+ evt.Enable(enable)
+ elif e_id == ID_COPY:
+ if hasattr(focus, 'CanCopy'):
+ enable = focus.CanCopy()
+ evt.Enable(enable)
+ elif e_id == ID_CUT:
+ if hasattr(focus, 'CanCut'):
+ enable = focus.CanCut()
+ evt.Enable(enable)
+ elif e_id == ID_COLUMN_MODE:
+ if hasattr(focus, 'IsColumnMode'):
+ evt.Enable(True)
+ else:
+ evt.Enable(False)
+ evt.Check(enable)
+ else:
+ evt.Skip()
+
+ def OnUpdateFormatUI(self, evt):
+ """Update status of format menu items
+ @param evt: wxEVT_UPDATE_UI
+
+ """
+ if not self.IsActive():
+ return
+
+ e_id = evt.Id
+ ctrl = self.nb.GetCurrentCtrl()
+ if e_id == ID_USE_SOFTTABS:
+ evt.Check(not bool(ctrl.GetUseTabs()))
+ elif e_id == ID_WORD_WRAP:
+ evt.Check(bool(ctrl.GetWrapMode()))
+ elif e_id in [ID_EOL_MAC, ID_EOL_WIN, ID_EOL_UNIX]:
+ evt.Check(ctrl.GetEOLModeId() == e_id)
+ elif e_id in [ID_INDENT, ID_TO_UPPER, ID_TO_LOWER]:
+ evt.Enable(ctrl.GetSelectionStart() != ctrl.GetSelectionEnd())
+ else:
+ evt.Skip()
+
+ def OnUpdateLexerUI(self, evt):
+ """Update status of lexer menu
+ @param evt: wxEVT_UPDATE_UI
+
+ """
+ if not self.IsActive():
+ return
+
+ e_id = evt.Id
+ if e_id in syntax.SYNTAX_IDS:
+ lang = self.nb.GetCurrentCtrl().GetLangId()
+ evt.Check(lang == e_id)
+ else:
+ evt.Skip()
+
+ def OnUpdateSettingsUI(self, evt):
+ """Update settings menu items
+ @param evt: wxEVT_UPDATE_UI
+
+ """
+ if not self.IsActive():
+ return
+
+ e_id = evt.Id
+ ctrl = self.nb.GetCurrentCtrl()
+ if e_id == ID_AUTOCOMP:
+ evt.Check(ctrl.GetAutoComplete())
+ elif e_id == ID_AUTOINDENT:
+ evt.Check(ctrl.GetAutoIndent())
+ elif e_id == ID_SYNTAX:
+ evt.Check(ctrl.IsHighlightingOn())
+ elif e_id == ID_FOLDING:
+ evt.Check(ctrl.IsFoldingOn())
+ elif e_id == ID_BRACKETHL:
+ evt.Check(ctrl.IsBracketHlOn())
+ else:
+ evt.Skip()
+
+ def OnUpdateViewUI(self, evt):
+ """Update status of view menu items
+ @param evt: wxEVT_UPDATE_UI
+
+ """
+ if not self.IsActive():
+ return
+
+ e_id = evt.Id
+ ctrl = self.nb.GetCurrentCtrl()
+ zoom = ctrl.GetZoom()
+ if e_id == ID_ZOOM_NORMAL:
+ evt.Enable(zoom)
+ elif e_id == ID_ZOOM_IN:
+ evt.Enable(zoom < 18)
+ elif e_id == ID_ZOOM_OUT:
+ evt.Enable(zoom > -8)
+ elif e_id == ID_GOTO_MBRACE:
+ evt.Enable(-1 not in ctrl.GetBracePair())
+ elif e_id == ID_HLCARET_LINE:
+ evt.Check(ctrl.GetCaretLineVisible())
+ elif e_id == ID_SHOW_SB:
+ evt.Check(self.GetStatusBar().IsShown())
+ elif e_id == ID_VIEW_TOOL:
+ evt.Check(self.GetToolBar().IsShown())
+ elif e_id == ID_SHOW_WS:
+ evt.Check(bool(ctrl.GetViewWhiteSpace()))
+ elif e_id == ID_SHOW_EDGE:
+ evt.Check(bool(ctrl.GetEdgeMode()))
+ elif e_id == ID_SHOW_EOL:
+ evt.Check(bool(ctrl.GetViewEOL()))
+ elif e_id == ID_SHOW_LN:
+ evt.Check(bool(ctrl.GetMarginWidth(1)))
+ elif e_id == ID_INDENT_GUIDES:
+ evt.Check(bool(ctrl.GetIndentationGuides()))
+ elif e_id == ID_MAXIMIZE_EDITOR:
+ binder = self.MenuBar.GetKeyBinder()
+ binding = binder.GetBinding(ID_MAXIMIZE_EDITOR)
+ txt = _("Maximize Editor")
+ if self.PanelMgr.IsEditorMaximized():
+ txt = _("Restore Editor")
+ evt.SetText(txt + binding)
+ else:
+ evt.Skip()
+
+ def OnCommandBar(self, evt):
+ """Open the Commandbar
+ @param evt: wx.MenuEvent
+
+ """
+ e_id = evt.Id
+ if e_id in (ID_QUICK_FIND, ID_GOTO_LINE, ID_COMMAND, ID_SESSION_BAR):
+ self._mpane.ShowCommandControl(e_id)
+ else:
+ evt.Skip()
+
+ def OnCustomizeLangMenu(self, evt):
+ """Show the lexer menu customization dialog"""
+ if evt.Id == ID_LEXER_CUSTOM:
+ dlg = eclib.FilterDialog(self, title=_("Customize Menu"),
+ style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
+ mconfig = _PGET("LEXERMENU", default=list())
+ flters = dict()
+ for item in syntax.SyntaxNames():
+ if item in mconfig:
+ flters[item] = True
+ else:
+ flters[item] = False
+ dlg.SetListValues(flters)
+ dlg.SetInitialSize()
+ dlg.CenterOnParent()
+
+ if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
+ includes = dlg.GetIncludes()
+ includes.sort()
+ _PSET("LEXERMENU", includes)
+ ed_msg.PostMessage(ed_msg.EDMSG_CREATE_LEXER_MENU)
+ dlg.Destroy()
+ else:
+ evt.Skip()
+
+ def OnHelp(self, evt):
+ """Handles help related menu events
+ @param evt: wx.MenuEvent
+
+ """
+ import webbrowser
+ e_id = evt.Id
+ if e_id == ID_HOMEPAGE:
+ page = HOME_PAGE
+ elif e_id == ID_DOCUMENTATION:
+ page = HOME_PAGE + "/documentation"
+ elif e_id == ID_TRANSLATE:
+ page = I18N_PAGE
+ elif e_id == ID_CONTACT:
+ webbrowser.open("mailto:%s" % CONTACT_MAIL)
+ return
+ elif e_id == ID_BUG_TRACKER:
+ page = "http://code.google.com/p/editra/issues/list"
+ else:
+ evt.Skip()
+ return
+
+ # It seems under some cases when running under windows the call to
+ # subprocess in webbrowser will fail and raise an exception here. So
+ # simply trap and ignore it.
+ try:
+ self.PushStatusText(_("Opening %s") % page, SB_INFO)
+ webbrowser.open(page, 1)
+ except:
+ self.PushStatusText(_("Error: Unable to open %s") % page, SB_INFO)
+
+ def PushStatusText(self, txt, field):
+ """Override so that our custom status bar's method gets called
+ do to these wxFrame methods not being exposed as virtuals.
+
+ """
+ sb = self.GetStatusBar()
+ if sb:
+ sb.PushStatusText(txt, field)
+
+ SetStatusText = PushStatusText
+
+ def SetTitle(self, title=u''):
+ """Sets the windows title
+ @param title: The text to tag on to the default frame title
+
+ """
+ name = u"%s v%s" % (PROG_NAME, VERSION)
+ if len(title):
+ name = u" - " + name
+ super(MainWindow, self).SetTitle(title + name)
+
+ def SetupToolBar(self):
+ """Setup or reinitialize the windows ToolBar"""
+ tb = self.GetToolBar()
+ if tb:
+ tb.Destroy()
+ self.SetToolBar(ed_toolbar.EdToolBar(self))
+ self.ToolBar.Realize()
+ self.GetToolBar().Show(_PGET('TOOLBAR'))
+ self.Layout()
+
+ @classmethod
+ def UpdateClipboardRing(cls):
+ """Update the clipboard ring to sync it with the
+ system clipboard.
+ @note: for internal use only
+
+ """
+ try:
+ txt = util.GetClipboardText()
+ except wx.PyAssertionError:
+ txt = None
+
+ if txt is None or cls.CLIPBOARD.IsAtIndex(txt):
+ return
+
+ # Something new has come in from an external program
+ cls.CLIPBOARD.Reset()
+ cls.CLIPBOARD.Put(txt)
+
+#-----------------------------------------------------------------------------#
+# Event handlers that don't need to be part of the class
+
+def OnAbout(evt):
+ """Show the About Dialog
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.Id == ID_ABOUT:
+ info = wx.AboutDialogInfo()
+ year = time.localtime()
+ desc = [_("Editra is a programmers text editor."),
+ _("Written in 100%% Python."),
+ _("Homepage") + ": " + HOME_PAGE + "\n",
+ _("Platform Info") + ": (%s,%s)",
+ _("License: wxWindows (see COPYING.txt for full license)")]
+ desc = "\n".join(desc)
+ py_version = sys.platform + ", python " + sys.version.split()[0]
+ platform = list(wx.PlatformInfo[1:])
+ platform[0] += (" " + wx.VERSION_STRING)
+ wx_info = ", ".join(platform)
+ info.SetCopyright(_("Copyright") + "(C) 2005-%d Cody Precord" % year[0])
+ info.SetName(PROG_NAME.title())
+ info.SetDescription(desc % (py_version, wx_info))
+ info.SetVersion(VERSION)
+ wx.AboutBox(info)
+ else:
+ evt.Skip()
+
+def OnPreferences(evt):
+ """Open the Preference Panel
+ @param evt: wx.MenuEvent
+
+ """
+ if evt.Id == ID_PREF:
+ cursor = wx.BusyCursor()
+ win = wx.GetApp().GetWindowInstance(prefdlg.PreferencesDialog)
+ if win is not None:
+ win.Raise()
+ else:
+ dlg = prefdlg.PreferencesDialog(None)
+ dlg.CenterOnParent()
+ dlg.Show()
+ del cursor
+ else:
+ evt.Skip()
+
+#-----------------------------------------------------------------------------#
+# Plugin interface to the MainWindow
+
+class MainWindowAddOn(plugin.Plugin):
+ """Plugin that Extends the L{MainWindowI}"""
+ observers = plugin.ExtensionPoint(iface.MainWindowI)
+ def Init(self, window):
+ """Call all observers once to initialize
+ @param window: window that observers become children of
+
+ """
+ for observer in self.observers:
+ try:
+ observer.PlugIt(window)
+ except Exception, msg:
+ util.Log("[ed_main][err] MainWindowAddOn.Init: %s" % msg)
+
+ def GetEventHandlers(self, ui_evt=False):
+ """Get Event handlers and Id's from all observers
+ @keyword ui_evt: Get Update Ui handlers (default get menu handlers)
+ @return: list [(ID_FOO, foo.OnFoo), (ID_BAR, bar.OnBar)]
+
+ """
+ handlers = list()
+ for observer in self.observers:
+ try:
+ items = None
+ if ui_evt:
+ if hasattr(observer, 'GetUIHandlers'):
+ items = observer.GetUIHandlers()
+ assert isinstance(items, list), "Must be a list()!"
+ else:
+ if hasattr(observer, 'GetMenuHandlers'):
+ items = observer.GetMenuHandlers()
+ assert isinstance(items, list), "Must be a list()!"
+ except Exception, msg:
+ util.Log("[ed_main][err] MainWindowAddOn.GetEventHandlers: %s" % str(msg))
+ continue
+
+ if items is not None:
+ handlers.extend(items)
+
+ return handlers
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_marker.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_marker.py
new file mode 100644
index 0000000..3f7fbff
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_marker.py
@@ -0,0 +1,377 @@
+###############################################################################
+# Name: ed_marker.py #
+# Purpose: StyledTextCtrl Markers #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Classes to represent Markers and associated data in a StyledTextCtrl
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_marker.py 67626 2011-04-27 02:51:39Z CJP $"
+__revision__ = "$Revision: 67626 $"
+
+#-----------------------------------------------------------------------------#
+import wx
+import wx.stc
+from extern.embeddedimage import PyEmbeddedImage
+
+# NOTE: Must be 1 char per pixel for Scintilla to display
+_BookmarkBmp = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dE"
+ "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDAQA0GON3MFgAAAEG"
+ "SURBVDjL7ZK9SgNBFIW/nd1SO1EbBUHQgD+g+AKSN9E2nY+RztfxOSwCAUEIFlHUsLPB7L3H"
+ "YjdjTBqxFG91mLnzzTlzB/4rA+j2+vpJ893tTba8VszF/dU1uQRWg2cU7uAiyMFgfTig2+tr"
+ "GRLmIjeDmVGYKGojmBHMoXawmsnuHs8n5ytuE4AyEqoSjxGmEY8VXpUQI0wrqCLvW9uMD4+4"
+ "XICkCDZ6BAQmXI19JILUaBMB5y0PTDrHKU4C+OgB97bZmwuCOyaBQ46n/YOX1/SgCfAxHIAc"
+ "1LpzgQA5OWJmgMTp2sa3aXxFGD81Qu1BFzlqUzkIznY6K6NMgIvN/V/9gz9Qn2ObnTkNCjcr"
+ "AAAAAElFTkSuQmCC")
+
+_ArrowBmp = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAQCAYAAADJViUEAAAAAXNSR0IArs4c6QAAAAZiS0dE"
+ "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDAQEBO+Lj6asAAADR"
+ "SURBVCjPpZItEgIxDIUfTA+B3CNEItsbrOAQDIojLA6J4hSI3KDBIeOwOygEzOwNFgP7A/2B"
+ "Ia5pvte+eQH+qEmoycytqgIAiAhlWQbnpillEYGqgpnbn+GcgGHmtmmaUXN49n4H59adnaEF"
+ "o6oQkeTrMQEzHIgXwXv9EDDvQ2kBwLk+kRF8P+ezPewFi9XT8/DidsnDy62FtRZE1MPHTfzL"
+ "szlwPQGV9ODIcyU2CFZWgiAAGCJCURQfUF3XXYQhMLvbLzgEfrWeMTALp0AAeAAUy3GCxymX"
+ "vQAAAABJRU5ErkJggg==")
+
+_BreakpointBmp = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dE"
+ "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEgMQBqh6qrUAAAEf"
+ "SURBVDjLpZPNTsJQEIW/CxgJUStWJTRqEBZEiZqY6AOY2FdiaVz2Adz6IiY+gHFHGn82yI9V"
+ "UjUWFkKh1lUx1VKvYZZzc76cOzMHpiwR1axWND+qb5iW+BNQrWj+qrLE/maZQnYFgNeew63V"
+ "oGY9/IKIn+Kj3UP0wlak3fvnFudXlyGICIl3DtDzxdg/t95szq6/IalAnF9U0bMa9PuxgPXM"
+ "PMcbZQDfMC2RCh6214q89Bypye+peS6ad4wdAKhzCgnXl9vdaMTCzGwYMHCHdPsjaUAwvDGg"
+ "030n4yWlAc5wEAbU7UeU9LKUvvPRJXKNpVxJCvBkNzmpNUTkIeWS8S4cr8epWRexp4yXnpAc"
+ "F+OmLf4RpgT4gPicGKap6ws0jWfqOADTLwAAAABJRU5ErkJggg==")
+
+_BreakpointDisabledBmp = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dE"
+ "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEgMRGEtuppcAAABy"
+ "SURBVDjLY2TAAcq1pf4j8zuvPmPEpo6RGM2EDMHQjM0AXOIkKcIrT5QNuNQRqxmbekYYg6gA"
+ "whLQTAwUgoE3gOJAJCsaG3Xl/5OdkOq1FYlIjbqqmElZQ+l/uabMfxIzExMDw38GBgbGfzgz"
+ "EyOl2RkAwXRPWcN07zMAAAAASUVORK5CYII=")
+
+_StackMarker = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAd1J"
+ "REFUOI2Fk09rE1EUxX930jSZJIaBkGJcKBilC0uxG+kkuIhKKdn5EfoREvwO7jprV+LahSuL"
+ "CKEQqCO6cJNFQ1qEFBJJKYSaPx1Br4sx00xG64EH79377rnnHe4TMWLMw66LChKKqSquo+Hg"
+ "H8iMwK6JrtxNkMvluJ3eJF9chqFF99sxrX6T06MffNj9FSERMWJB1+qjp+RzK2ANaU8aAGST"
+ "eQrGOnv7bxh0vIgSw9cI+TvLfO6+5dXrF3QPz1hNPQbg/OKU9qRBdWOHVDKDXRMNEZTqhooI"
+ "o5M4g46HqtLqN+kenpFN5i9vWkNu3c8iEn6FMds0nn8X11FxHZVBx6PVb1Iw1um1xwC0Jw0K"
+ "y/ciJhqqihJSheuojE7iANxYTQckZvxalADxPVjE1BuHzr322Dd4AUvuru+qXRNNJTPhwqFF"
+ "7+s4UlSqG0FLmR8kuyYqIlQePuHm9SIAe19eBvnqxg5AMBuDjhcmmFey+cDmeHrAdPgzyJlW"
+ "jLXsNvsH75lcjHAdFYMFuI7KxBvx8ZPLWnYb07psUDTLfrE3CgYqoiBQUhdNJTJUylu0zt9R"
+ "NMu+7COPmW9XEszMMhNpKuWtkOz5O1cSzHsy9cZ//UyIEfvvKj1b0n/lfgPWHMMhVFXV8gAA"
+ "AABJRU5ErkJggg==")
+
+_ErrorBmp = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAc5J"
+ "REFUOI11kzFP20AUx3/nEBGLRFUr5CEIieoGhkRtVJVI3uIROiBgYWLzxgco3SulysjIF8iC"
+ "UJaspjOtRIEODKZZihBClcABW0I5d2h8shP3P53e6f977929J4RRIK3PahQLIciTEcd8NAqZ"
+ "S5EGtNUorklJy3VzAccHB/z0/QxEA9Lm3ycnPPt+xjxvmpTX16cgxqR50O3mZr8LQ4a9Hk3b"
+ "piYlbTWKAYzJzEUpebm/T1FKbS5KidXvc1+tonyflutqiKGEoOW6DHs9nn2fhZUVAMzNTYpS"
+ "amASuwtDBt0uTdtGCcFMusTkod4sLlJyHEqOo6uIPI+HTmf6ZyYDS5UKD50Okedl4nnmXEDS"
+ "czo7wNL2tj4PggA1/qUMYN40Mz1HnqcredrZwarXGQQBszc32jMD8HRxAcCv01MWdne1OV12"
+ "yXGIVleZPTqirJSOiy8Q16Skadv4h4cAvFpb40+/D8DQMCgrhdza4sfYXFleJri85DiK/k1i"
+ "W43iD40GVr2uIYkSQKLE/DUM2TMKIjPK7+bmeLuxMQVJ9LrR4PzsjO+Pj+yNRzl3md5bFvfV"
+ "Ki+urzOAb7e3nF9d8UkY08uUhqj/rLOIY5050V9UfNMzpyji5gAAAABJRU5ErkJggg==")
+
+_LintBmpGreen = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAZNJ"
+ "REFUOI3Fk00ow2Ecxz/P/ogtYxNRaDIvlykvO4yThHJzUBx3lLujg6O75OQkB4lSJKSUVsMO"
+ "qI1lW15aJv5/85KXbX8na48R5eBbz+H5Pd/ft2/f3+8RwqDwFxj+1P2TQMd8q94y1qgDdM+5"
+ "9F8JOGeaJGKBw5SufYhlIudzoTjfhHPSoSev3jAm8njKecWWW0m/vZfVuw18BCS++CrED7tu"
+ "+yAAi8draIpKf0kfs3dLAOwM7AtJoHvOpd/4VQzPOpZmKz3l7QBEosG0sFcNk7x6wzceEFkZ"
+ "rA95RIHDhKXZits+SCQaxHvpJ5ZKYKuoo6OuCwClJk9yK4X4svtAcdLCxXWYWCoBQGeZi0g0"
+ "iKbGuT3SuPWq1A5XpcOUQkzlCzRFTd+d1no8IS9ms2DxZgVLoZG9iWOR2SM58I0HhPb8yHx4"
+ "k84yF4dnpziqa4nHdULbFwgla2jZe7DrPhAYBVsxD2azYHp5AX/ohNOpcwHQNtog7cKXY8wk"
+ "qvdPFJWapOQlCIPy47GP2PRv3//9N74DHQaLgsqg1M8AAAAASUVORK5CYII=")
+
+_LintBmpRed = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAXJJ"
+ "REFUOI3Fk79Lw0AYhp9LhA4tFIyQQSg2oq2zRTPYrtLJjpLRVf8AxVnwD9C1o4OTBcVdC42i"
+ "jtpWjCIVGq1xsYiEek4NptQf0MEPDj7uvve9l+c4IRSVQUoZSP2bQbmwILdnZ2S3/5PBQS4b"
+ "DLZcl1FFYcVI9hUDDPVuxIeHKWam5ZuqMqLrACzqOgnLothoyKWzc/F1XvSD2I2bsCwA7nd2"
+ "ANBMk6ejI7yXFwoVW4QMyoUFeVirAZBPpdBMk/fHR14dh5hh8Oo4tFyXh48Plk9OgxQBg7m9"
+ "kphPJsmnUiQsKxB3SzNNAMYikVDaEMTdahUAz7YDsWaaQe/5PsfNJsXMdAA1BDHe4x4zDJ5t"
+ "G4BaqcRNu81m/ToEMZRg46oq9i8vuatUgptjhkHLdfF8n06nQ2/1fYWDXFb6vs+IrlNvNLjw"
+ "PLacW7E6OSFVVWXjqip+NABYn0pLgPFolJt2OyQKR1DUX9daOi2/Pf/33/gJL9aOTtHLtUIA"
+ "AAAASUVORK5CYII=")
+
+_LintBmpYellow = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAblJ"
+ "REFUOI3FkzFIG2EUx39frmCStgpqIw0pJKGEpErViEIHoYtQcOjSTkJ1ky7irLM6ScVFbBeL"
+ "FBxEBAUHl6IirVMKFdseXE5yjSVGCzW53ImXr0Mh9DRiwaEPvuG9773/e/y+9wnhUbiOea5V"
+ "fZXA7FibHB6ISoD5yQ75TwLPntytJOpGEZ9PYag/Ik3LqdrkxvnA054gj5INMpM1CYduUiie"
+ "8eB+LV3dfYwYphyf+Sb+zhfVIM5PdkjTcnjc8wKAnc13AMQTrWxs7ZD/aTMxowqXwOxYm9xT"
+ "f1GWks6H9cQTrZxax2jpDIHGGgDefzikVHKYmtMqU1QYDI6mxL2gn+ZYHV3dfRwffkFLZwC4"
+ "dTtA/Z04AMaP0uUQ978X8XsV8sYGumFiWg6xeAuf93TK0kHVCyBg5GWsAtoF0SMEuSObaOSP"
+ "Hw75SaU+4fcqLK9uEwx4mX6bFnBQfYKpOU181U5YXd8l2Z4kl7dpSYTJHdmoegHLLl8AfmEP"
+ "Xi/sCzVdYGllk0BjDa/efCSTNVlcOxAAQ/0R10JVfUaA4YGoLEtJNmcRavK5yLtMeJQrz/Pe"
+ "kLz0/r//xt8H26DcJVZnmgAAAABJRU5ErkJggg==")
+
+#-----------------------------------------------------------------------------#
+
+__markerId = -1
+def NewMarkerId():
+ """Get a new marker id
+ @note: limited by stc to 16 possible ids. will assert when this threshold
+ is passed.
+
+ """
+ global __markerId
+ __markerId += 1
+ assert __markerId < 24, "No more marker Ids available!"
+ return __markerId
+
+#-----------------------------------------------------------------------------#
+
+class Marker(object):
+ """Marker Base class"""
+ _ids = list()
+ _symbols = list()
+ def __init__(self):
+ super(Marker, self).__init__()
+
+ # Attributes
+ self._line = -1
+ self._handle = -1
+ self._bmp = wx.NullBitmap
+ self._fore = wx.NullColour # Foreground colour
+ self._back = wx.NullColour # Background colour
+
+ Line = property(lambda self: self._line,
+ lambda self, line: setattr(self, '_line', line))
+ Handle = property(lambda self: self._handle,
+ lambda self, handle: setattr(self, '_handle', handle))
+ Bitmap = property(lambda self: self._bmp,
+ lambda self, bmp: setattr(self, '_bmp', bmp))
+ Foreground = property(lambda self: self._fore,
+ lambda self, fore: setattr(self, '_fore', fore))
+ Background = property(lambda self: self._back,
+ lambda self, back: setattr(self, '_back', back))
+
+ @classmethod
+ def AnySet(cls, stc, line):
+ """Is any breakpoint set on the line"""
+ if not cls.IsSet(stc, line):
+ # Check subclasses
+ for bpoint in cls.__subclasses__():
+ if bpoint.IsSet(stc, line):
+ return True
+ return False
+ else:
+ return True
+
+ @classmethod
+ def GetIds(cls):
+ """Get the list of marker IDs."""
+ return cls._ids
+
+ @classmethod
+ def GetSymbols(cls):
+ """Get the list of symbols"""
+ return cls._symbols
+
+ @classmethod
+ def IsSet(cls, stc, line):
+ """Is the marker set on the given line"""
+ mask = stc.MarkerGet(line)
+ return True in [ bool(1<<marker & mask) for marker in cls.GetIds() ]
+
+ def Set(self, stc, line, delete=False):
+ """Add/Delete the marker to the stc at the given line"""
+ for marker in self.GetIds():
+ if delete:
+ mask = stc.MarkerGet(line)
+ if (1<<marker & mask):
+ stc.MarkerDelete(line, marker)
+ else:
+ handle = stc.MarkerAdd(line, marker)
+ if self.Handle < 0:
+ self.Line = line
+ self.Handle = handle
+
+ def DeleteAll(self, stc):
+ """Remove all instances of this bookmark from the stc"""
+ for marker in self.GetIds():
+ stc.MarkerDeleteAll(marker)
+
+ def RegisterWithStc(self, stc):
+ """Setup the STC to use this marker"""
+ ids = self.GetIds()
+ if self.Bitmap.IsNull():
+ symbols = self.GetSymbols()
+ if len(ids) == len(symbols):
+ markers = zip(ids, symbols)
+ for marker, symbol in markers:
+ stc.MarkerDefine(marker, symbol,
+ self.Foreground, self.Background)
+ elif len(ids) == 1 and not self.Bitmap.IsNull():
+ stc.MarkerDefineBitmap(ids[0], self.Bitmap)
+ else:
+ assert False, "Invalid Marker!"
+
+#-----------------------------------------------------------------------------#
+
+class Bookmark(Marker):
+ """Class to store bookmark data"""
+ _ids = [NewMarkerId(),]
+ def __init__(self):
+ super(Bookmark, self).__init__()
+
+ # Attributes
+ self._name = u"" # Bookmark alias name
+ self._fname = u"" # Filename
+ self.Bitmap = _BookmarkBmp.Bitmap
+
+ def __eq__(self, other):
+ return (self.Filename, self.Line) == (other.Filename, other.Line)
+
+ #---- Properties ----#
+ Name = property(lambda self: self._name,
+ lambda self, name: setattr(self, '_name', name))
+ Filename = property(lambda self: self._fname,
+ lambda self, name: setattr(self, '_fname', name))
+
+#-----------------------------------------------------------------------------#
+
+class Breakpoint(Marker):
+ """Marker object to represent a breakpoint in the EditraBaseStc"""
+ _ids = [NewMarkerId(),]
+ def __init__(self):
+ super(Breakpoint, self).__init__()
+ self.Bitmap = _BreakpointBmp.Bitmap
+
+class BreakpointDisabled(Breakpoint):
+ """Marker object to represent a disabled breakpoint in the EditraBaseStc"""
+ _ids = [NewMarkerId(),]
+ def __init__(self):
+ super(BreakpointDisabled, self).__init__()
+ self.Bitmap = _BreakpointDisabledBmp.Bitmap
+
+class BreakpointStep(Breakpoint):
+ """Marker object to represent debugger step breakpoint in the EditraBaseStc"""
+ _ids = [NewMarkerId(), NewMarkerId()]
+ def __init__(self):
+ super(BreakpointStep, self).__init__()
+ self.Bitmap = _ArrowBmp.Bitmap
+
+ def DeleteAll(self, stc):
+ """Overrode to handle refresh issue"""
+ super(BreakpointStep, self).DeleteAll(stc)
+ stc.Colourise(0, stc.GetLength())
+
+ def RegisterWithStc(self, stc):
+ """Register this compound marker with the given StyledTextCtrl"""
+ ids = self.GetIds()
+ stc.MarkerDefineBitmap(ids[0], self.Bitmap)
+ stc.MarkerDefine(ids[1], wx.stc.STC_MARK_BACKGROUND,
+ background=self.Background)
+
+ def Set(self, stc, line, delete=False):
+ """Add/Delete the marker to the stc at the given line
+ @note: overrode to ensure only one is set in a buffer at a time
+
+ """
+ self.DeleteAll(stc)
+ super(BreakpointStep, self).Set(stc, line, delete)
+ start = stc.GetLineEndPosition(max(line-1, 0))
+ end = stc.GetLineEndPosition(line)
+ if start == end:
+ start = 0
+ stc.Colourise(start, end) # Refresh for background marker
+
+class StackMarker(Marker):
+ """Marker object to mark a line in a callstack in the EditraBaseStc"""
+ _ids = [NewMarkerId(),]
+ def __init__(self):
+ super(StackMarker, self).__init__()
+ self.Bitmap = _StackMarker.Bitmap
+
+#-----------------------------------------------------------------------------#
+
+class FoldMarker(Marker):
+ """Marker object class for managing the code folding markers"""
+ _ids = [wx.stc.STC_MARKNUM_FOLDEROPEN, wx.stc.STC_MARKNUM_FOLDER,
+ wx.stc.STC_MARKNUM_FOLDERSUB, wx.stc.STC_MARKNUM_FOLDERTAIL,
+ wx.stc.STC_MARKNUM_FOLDEREND, wx.stc.STC_MARKNUM_FOLDEROPENMID,
+ wx.stc.STC_MARKNUM_FOLDERMIDTAIL]
+ _symbols = [wx.stc.STC_MARK_BOXMINUS, wx.stc.STC_MARK_BOXPLUS,
+ wx.stc.STC_MARK_VLINE, wx.stc.STC_MARK_LCORNER,
+ wx.stc.STC_MARK_BOXPLUSCONNECTED,
+ wx.stc.STC_MARK_BOXMINUSCONNECTED, wx.stc.STC_MARK_TCORNER]
+
+ def RegisterWithStc(self, stc):
+ super(FoldMarker, self).RegisterWithStc(stc)
+ stc.SetFoldMarginHiColour(True, self.Foreground)
+ stc.SetFoldMarginColour(True, self.Foreground)
+
+#-----------------------------------------------------------------------------#
+
+class ErrorMarker(Marker):
+ """Marker object to indicate an error line in the EditraBaseStc"""
+ _ids = [NewMarkerId(), NewMarkerId()]
+ def __init__(self):
+ super(ErrorMarker, self).__init__()
+ self.Bitmap = _ErrorBmp.Bitmap
+
+ def DeleteAll(self, stc):
+ """Overrode to handle refresh issue"""
+ super(ErrorMarker, self).DeleteAll(stc)
+ stc.Colourise(0, stc.GetLength())
+
+ def RegisterWithStc(self, stc):
+ """Register this compound marker with the given StyledTextCtrl"""
+ ids = self.GetIds()
+ stc.MarkerDefineBitmap(ids[0], self.Bitmap)
+ stc.MarkerDefine(ids[1], wx.stc.STC_MARK_BACKGROUND,
+ # foreground=self.Foreground, #TODO
+ background=self.Foreground)
+
+ def Set(self, stc, line, delete=False):
+ """Add/Delete the marker to the stc at the given line
+ @note: overrode to ensure only one is set in a buffer at a time
+
+ """
+ super(ErrorMarker, self).Set(stc, line, delete)
+ start = stc.GetLineEndPosition(max(line-1, 0))
+ end = stc.GetLineEndPosition(line)
+ if start == end:
+ start = 0
+ stc.Colourise(start, end) # Refresh for background marker
+
+#-----------------------------------------------------------------------------#
+
+class LintMarker(Marker):
+ """Marker object to represent a marker for coding issue in the EditraBaseStc"""
+ _ids = [NewMarkerId(),]
+ def __init__(self):
+ super(LintMarker, self).__init__()
+ self.Bitmap = _LintBmpGreen.Bitmap
+
+class LintMarkerWarning(Marker):
+ """Marker object to represent a marker for moderate severity
+ coding issue in the EditraBaseStc
+
+ """
+ _ids = [NewMarkerId(),]
+ def __init__(self):
+ super(LintMarkerWarning, self).__init__()
+ self.Bitmap = _LintBmpYellow.Bitmap
+
+class LintMarkerError(Marker):
+ """Marker object to represent a marker for a high severity
+ coding issue in the EditraBaseStc
+
+ """
+ _ids = [NewMarkerId(),]
+ def __init__(self):
+ super(LintMarkerError, self).__init__()
+ self.Bitmap = _LintBmpRed.Bitmap
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mdlg.py
new file mode 100644
index 0000000..a0ad749
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mdlg.py
@@ -0,0 +1,158 @@
+###############################################################################
+# Name: ed_mdlg.py #
+# Purpose: Commonly used message dialogs #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This module provides a number of message dialogs that are commonly used
+throughout Editra. Its purpose is to promote reuse of the common dialogs for
+consistancy and reduction in redundant code.
+
+@summary: Common dialogs and related convenience functions
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_mdlg.py 66817 2011-01-29 21:32:20Z CJP $"
+__revision__ = "$Revision: 66817 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc
+from extern.embeddedimage import PyEmbeddedImage
+
+# Editra Library
+import ed_glob
+import util
+import eclib
+
+#--------------------------------------------------------------------------#
+# Globals
+
+_ = wx.GetTranslation
+
+FileIcon = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABthJ"
+ "REFUWIW9l21sVFkZgJ/7Pd8zLdOWQloiIA2WbiqBLWhhdw3IAhuyRqMxq64uv1B/GMJqYvzK"
+ "qqkmfqx/3UiC7q4QN5o1UnbRPyVLgdYtCAjdju2Uwhbabmd6O9PpdO7H8Ud7h2lnaLv+8E1u"
+ "zj3vnXPe57znfd9zRqJcIseOHXsxGo1W5fP5nOu6xQ+OIwAXT+e6LrZtUygUdE3T3O7u7pP9"
+ "/f03K8y5egkGgy2maTpiBXEcR1iWJXK5nBgbGxPJZFJ0d3eL3bt3H/4w9qSlinA43NbT03O5"
+ "oaGBdDoNgBAC13WLreM4xb4QAtu2SaVSzMzMEI/HOX78+KGLFy+eWw2AXEYkSWKhLdWhKAqy"
+ "LCPLMoqiFPuSJKFpGrFYjImJCUzTpLOzs7O1tfXg/wTgGaz0eIZVVS2+eyC6rhOLxRgaGiIS"
+ "idDV1dXZ0tKyIkQZgGVZopJxb/XeqksBvCcQCCCEIJPJEIlEuHLlSueOHTuWhajogVJjnkG3"
+ "JA48AE3Tit7wtsHv99Pf38/g4CCWZXH27NnOtra2R0KoSxXV1dWKruvFrXDd+bRzhUC47iJv"
+ "2LZDKGigqgqTqSy1tbVks1nOnDnDyMgIwWCQXbt20dHR0XnixImn+/r63l5qrywLDh48uP/0"
+ "6dPnFUXBNE0cy0Lz+9Grq3EdB5jPfyc7Q33cRyo1zcR4hnhjPXmhUJjLk0gkGLpxA3t2ltm5"
+ "ORobGzEMI3306NHHUqnUvWU9sHXr1ng4HMY0TRRFwRcIYOdymAMDyJqGNZmm1nCItGzm0nWT"
+ "F37Yx8c32Jz8js34/TkwdOK2Q9W2baiBAIV8nkwmQ01NTVVTU9OnL126dHJZgLVr18a91DIM"
+ "A7/fz8TwMOaXn6chGmBNewsDH32Cb/xxlOvvJWleU8vVbD2dL/+Zw9fOM2FaCOHi/OznRJub"
+ "sSYmiMViyLJMLpfzrxgDmqb5AAzDQFEUAHyFAi2BAsqhw5xSW3n5wizbxACnmsdpbdV4IxNk"
+ "w2QM4wOTUP8gbjhM1tBxFgqVYRgEAgE0TVtqrhzAsqwcgKIoxYj3r1vLXz73I875d3H15k1+"
+ "teMuTwUNHiR0JmerOLAlTu+4Rr69HXfGxhEOuqZh6Dr5hSzy+/0YhlEWc2UAyWTyfXhYjKYn"
+ "U3z/lb9zJRVAQqLev4XaDQ5EFLJOlM0HdnI7rfLcrx/Q9ewetoyNku4fJuTzEfL7wedDCIGq"
+ "qchyedaXabq7uycymUyxPxeuYn+Dj4vSGxwI/pO3bmn8picMbU1sfuEQd2b8dLzyHx70K7yU"
+ "qIP9e1nf+jFq6msxAJ/Ph67rqIpK6cn6SIBkMlnI5/MAFCyLGl2ifUcz6X/0ccT3Lvvb5kik"
+ "6/nbhTR/Opei7bnXyZq3ee17Phx5kluBOq637OHUhQQaYPh8xYIFiBW3AJA8V3kb5kQi3Pv8"
+ "19i+r4Uv3XufjrONvPhbhTX2X3n1x4+z75Nb4NYgz1h3MXqv8qrSzC97E3zxQDPBUDXZhQJW"
+ "Sco8oKqqJMnzP/ZAFKDRdWBgki80zrK+apzEgxDPf7aVffubYFzCHpki2NWLoZnkwptI3A0x"
+ "en9s0TyVYqDMA7ZtC89RHrWwHXJ3htHyc4RrdL7ZrnAnHeP1y2v5RPRdmqU8qgY8+yl+/2+D"
+ "H/TYfGWPReO6mkXzrMoDpeIFjSRc3A8mcadSzF4e4EhdhiNtGW6PxXjtXzroM1ybinKgt56X"
+ "+mf5ae0Ffnd8O1owTi6XWxagUgwgxOJYEbYNd+8iWRZzcwX87wi++pEC4ztruJbaxTPnrzI2"
+ "PcxeaZQ3Iwl8l3sxx48SqlvsyVUBWJZVBChts/k8SiaDpRuEJoM0PxnDvHqf0fvDtFfd5CfG"
+ "NVpHhsjcGGFQ1YjrKhEe1hOgWFlX9IAnkiThAqFNm1j/1jkkSSJSFeK9xCjf+sXbhKI+/vDt"
+ "x2nZ+BnE0JOkbBc34KdOUQisW4dtO4sAVuWBpeLaNqphEN24sagbJc2e9ga++/XDoEQQgPtY"
+ "I1EPHLALBWyrgFR+4q8M4BF7rXcT9t73bt/EUzu3AGDbNm5Jnns3ZSHmxwtAkh4d66sCmL+O"
+ "C2D+WlawCsj24vshzOe5Bzs/VEIIgbxQV7xFfGiA+VYsTCYX/x94xh+CLh7vSaUCVPz2yC9L"
+ "JvBWWwq5VCfLi2/SlWCWSpkHVFWVFg6ORYMrXSaWg60kmqatfB+wbduZmpoiHA4zPT1d1Jf+"
+ "PxBCIFyBK9zyolXS9941TSMUClEoFMrO40r+qQ6FQk/Islznuq5NyREaCARkwzBk27ZFPp93"
+ "LcsqO14fIaokSblMJvMOkFzlmP+P/BeZah5l10evBAAAAABJRU5ErkJggg==")
+
+#--------------------------------------------------------------------------#
+
+def OpenErrorDlg(parent, fname, err):
+ """Show a file open error dialog
+ @param parent: parent window
+ @param fname: file that failed to open
+ @param err: error message
+
+ """
+ argmap = dict(filename=fname, errormsg=err)
+ dlg = wx.MessageDialog(parent,
+ _("Editra could not open %(filename)s\n\n"
+ "Error:\n%(errormsg)s") % \
+ argmap, _("Error Opening File"),
+ style=wx.OK|wx.CENTER|wx.ICON_ERROR)
+ dlg.CenterOnParent()
+ result = dlg.ShowModal()
+ dlg.Destroy()
+ return result
+
+def SaveErrorDlg(parent, fname, err):
+ """Show a file save error modal dialog
+ @param parent: window that the dialog is the child of
+ @param fname: name of file that error occured
+ @param err: the err message/description
+ @return: wxID_OK if dialog was shown and dismissed properly
+
+ """
+ argmap = dict(filename=fname, errormsg=err)
+ dlg = wx.MessageDialog(parent,
+ _("Failed to save file: %(filename)s\n\n"
+ "Error:\n%(errormsg)s") % argmap,
+ _("Save Error"), wx.OK|wx.ICON_ERROR)
+ dlg.CenterOnParent()
+ result = dlg.ShowModal()
+ dlg.Destroy()
+ return result
+
+#--------------------------------------------------------------------------#
+
+class EdFileInfoDlg(eclib.FileInfoDlg):
+ """File information dialog"""
+ def __init__(self, parent, fname):
+ """General file information dialog
+ @param parent: parent window
+ @param fname: file path
+
+ """
+ super(EdFileInfoDlg, self).__init__(parent, fname=fname, ftype=None,
+ bmp=FileIcon.GetBitmap())
+
+ # Setup
+ self.SetFileTypeLabel(util.GetFileType(fname))
+
+#--------------------------------------------------------------------------#
+
+class EdFormatEOLDlg(eclib.ChoiceDialog):
+ """Dialog for selecting EOL format"""
+ def __init__(self, parent, msg=u'', title=u'', selection=0):
+ """Create the dialog
+ @keyword selection: default selection (wx.stc.STC_EOL_*)
+
+ """
+ choices = [_("Old Machintosh (\\r)"), _("Unix (\\n)"),
+ _("Windows (\\r\\n)")]
+ self._eol = [wx.stc.STC_EOL_CR, wx.stc.STC_EOL_LF, wx.stc.STC_EOL_CRLF]
+ idx = self._eol.index(selection)
+ super(EdFormatEOLDlg, self).__init__(parent, msg=msg, title=title,
+ choices=choices,
+ style=wx.YES_NO|wx.YES_DEFAULT)
+ self.SetSelection(idx)
+
+ # Setup
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DOCPROP), wx.ART_OTHER)
+ if bmp.IsOk():
+ self.SetBitmap(bmp)
+ self.CenterOnParent()
+
+ def GetSelection(self):
+ """Get the selected eol mode
+ @return: wx.stc.STC_EOL_*
+
+ """
+ sel = super(EdFormatEOLDlg, self).GetSelection()
+ return self._eol[sel]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_menu.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_menu.py
new file mode 100644
index 0000000..f0255c2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_menu.py
@@ -0,0 +1,1228 @@
+###############################################################################
+# Name: ed_menu.py #
+# Purpose: Editra's Menubar and Menu related classes #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007-2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+@package: Editra.src.ed_menu
+
+Provides an advanced menu class for easily creating menus and setting their
+related bitmaps when available from Editra's ArtProvider. The Keybinder class
+for managing keybindings and profiles is also provided by this module.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_menu.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import os
+import wx
+
+# Editra Libraries
+import ed_glob
+import ed_msg
+import profiler
+import util
+from syntax import syntax
+from syntax import synglob
+
+#--------------------------------------------------------------------------#
+# Globals
+_ = wx.GetTranslation
+
+#--------------------------------------------------------------------------#
+
+class EdMenu(wx.Menu):
+ """Custom wxMenu class that makes it easier to customize and access items.
+
+ """
+ def __init__(self, title=wx.EmptyString, style=0):
+ """Initialize a Menu Object
+ @param title: menu title string
+ @param style: type of menu to create
+
+ """
+ super(EdMenu, self).__init__(title, style)
+
+ def Append(self, id_, text=u'', helpstr=u'', \
+ kind=wx.ITEM_NORMAL, use_bmp=True):
+ """Append a MenuItem
+ @param id_: New MenuItem ID
+ @keyword text: Menu Label
+ @keyword helpstr: Help String
+ @keyword kind: MenuItem type
+ @keyword use_bmp: try and set a bitmap if an appropriate one is
+ available in the ArtProvider
+
+ """
+ item = wx.MenuItem(self, id_, text, helpstr, kind)
+ self.AppendItem(item, use_bmp)
+ return item
+
+ def AppendEx(self, id_, text=u'', helpstr=u'',
+ kind=wx.ITEM_NORMAL, use_bmp=True):
+ """Like L{Append} but automatically applies keybindings to text
+ based on item id.
+
+ """
+ binding = EdMenuBar.keybinder.GetBinding(id_)
+ item = self.Append(id_, text+binding, helpstr, kind, use_bmp)
+ return item
+
+ def AppendItem(self, item, use_bmp=True):
+ """Appends a MenuItem to the menu and adds an associated
+ bitmap if one is available, unless use_bmp is set to false.
+ @param item: wx.MenuItem
+ @keyword use_bmp: try and set a bitmap if an appropriate one is
+ available in the ArtProvider
+
+ """
+ if use_bmp and item.GetKind() == wx.ITEM_NORMAL:
+ self.SetItemBitmap(item)
+ super(EdMenu, self).AppendItem(item)
+
+ def Insert(self, pos, id_, text=u'', helpstr=u'', \
+ kind=wx.ITEM_NORMAL, use_bmp=True):
+ """Insert an item at position and attach a bitmap
+ if one is available.
+ @param pos: Position to insert new item at
+ @param id_: New MenuItem ID
+ @keyword label: Menu Label
+ @keyword helpstr: Help String
+ @keyword kind: MenuItem type
+ @keyword use_bmp: try and set a bitmap if an appropriate one is
+ available in the ArtProvider
+
+ """
+ item = super(EdMenu, self).Insert(pos, id_, text, helpstr, kind)
+ if use_bmp and kind == wx.ITEM_NORMAL:
+ self.SetItemBitmap(item)
+ return item
+
+ def InsertAfter(self, item_id, id_, label=u'', helpstr=u'',
+ kind=wx.ITEM_NORMAL, use_bmp=True):
+ """Inserts the given item after the specified item id in
+ the menu. If the id cannot be found then the item will appended
+ to the end of the menu.
+ @param item_id: Menu ID to insert after
+ @param id_: New MenuItem ID
+ @keyword label: Menu Label
+ @keyword helpstr: Help String
+ @keyword kind: MenuItem type
+ @keyword use_bmp: try and set a bitmap if an appropriate one is
+ available in the ArtProvider
+ @return: the inserted menu item
+
+ """
+ pos = None
+ for item in xrange(self.GetMenuItemCount()):
+ mitem = self.FindItemByPosition(item)
+ if mitem.GetId() == item_id:
+ pos = item
+ break
+ if pos:
+ mitem = self.Insert(pos + 1, id_, label, helpstr, kind, use_bmp)
+ else:
+ mitem = self.Append(id_, label, helpstr, kind, use_bmp)
+ return mitem
+
+ def InsertBefore(self, item_id, id_, label=u'', helpstr=u'',
+ kind=wx.ITEM_NORMAL, use_bmp=True):
+ """Inserts the given item before the specified item id in
+ the menu. If the id cannot be found then the item will appended
+ to the end of the menu.
+ @param item_id: Menu ID to insert new item before
+ @param id_: New MenuItem ID
+ @keyword label: Menu Label
+ @keyword helpstr: Help String
+ @keyword kind: MenuItem type
+ @keyword use_bmp: try and set a bitmap if an appropriate one is
+ available in the ArtProvider
+ @return: menu item that was inserted
+
+ """
+ pos = None
+ for item in xrange(self.GetMenuItemCount()):
+ mitem = self.FindItemByPosition(item)
+ if mitem.GetId() == item_id:
+ pos = item
+ break
+ if pos:
+ mitem = self.Insert(pos, id_, label, helpstr, kind, use_bmp)
+ else:
+ mitem = self.Append(id_, label, helpstr, kind, use_bmp)
+ return mitem
+
+ def InsertAlpha(self, id_, label=u'', helpstr=u'',
+ kind=wx.ITEM_NORMAL, after=0, use_bmp=True):
+ """Attempts to insert the new menuitem into the menu
+ alphabetically. The optional parameter 'after' is used
+ specify an item id to start the alphabetical lookup after.
+ Otherwise the lookup begins from the first item in the menu.
+ @param id_: New MenuItem ID
+ @keyword label: Menu Label
+ @keyword helpstr: Help String
+ @keyword kind: MenuItem type
+ @keyword after: id of item to start alpha lookup after
+ @keyword use_bmp: try and set a bitmap if an appropriate one is
+ available in the ArtProvider
+ @return: menu item that was inserted
+
+ """
+ if after:
+ start = False
+ else:
+ start = True
+ last_ind = self.GetMenuItemCount() - 1
+ pos = last_ind
+ for item in range(self.GetMenuItemCount()):
+ mitem = self.FindItemByPosition(item)
+ if mitem.IsSeparator():
+ continue
+
+ mlabel = mitem.GetItemLabel()
+ if after and mitem.GetId() == after:
+ start = True
+ continue
+ if after and not start:
+ continue
+ if label < mlabel:
+ pos = item
+ break
+
+ l_item = self.FindItemByPosition(last_ind)
+ if pos == last_ind and (l_item.IsSeparator() or label > mlabel):
+ mitem = self.Append(id_, label, helpstr, kind, use_bmp)
+ else:
+ mitem = self.Insert(pos, id_, label, helpstr, kind, use_bmp)
+ return mitem
+
+ def RemoveItemByName(self, name):
+ """Removes an item by the label. It will remove the first
+ item matching the given name in the menu, the matching is
+ case sensitive. The return value is the either the id of the
+ removed item or None if the item was not found.
+ @param name: name of item to remove
+ @return: id of removed item or None if not found
+
+ """
+ menu_id = None
+ for pos in range(self.GetMenuItemCount()):
+ item = self.FindItemByPosition(pos)
+ if name == item.GetLabel():
+ menu_id = item.GetId()
+ self.Remove(menu_id)
+ break
+ return menu_id
+
+ def SetItemBitmap(self, item):
+ """Sets the MenuItems bitmap by getting the id from the
+ artprovider if one exists.
+ @param item: item to set bitmap for
+
+ """
+ bmp = wx.ArtProvider.GetBitmap(str(item.GetId()), wx.ART_MENU)
+ if not bmp.IsNull():
+ item.SetBitmap(bmp)
+
+#-----------------------------------------------------------------------------#
+
+class KeyBinder(object):
+ """Class for managing keybinding configurations"""
+ cprofile = None # Current Profile Name String
+ keyprofile = dict() # Active Profile (dict)
+
+ def __init__(self):
+ """Create the KeyBinder object"""
+ super(KeyBinder, self).__init__()
+
+ # Attributes
+ self.cache = ed_glob.CONFIG['CACHE_DIR'] # Resource Directory
+
+ def GetBinding(self, item_id):
+ """Get the keybinding string for use in a menu
+ @param item_id: Menu Item Id
+ @return: string
+
+ """
+ rbind = self.GetRawBinding(item_id)
+ shortcut = u''
+ if rbind is not None:
+ shortcut = u"+".join(rbind)
+ if len(shortcut):
+ shortcut = u"\t" + shortcut
+ return unicode(shortcut)
+
+ @classmethod
+ def GetCurrentProfile(cls):
+ """Get the name of the currently set key profile if one exists
+ @param cls: Class Object
+ @return: string or None
+
+ """
+ return cls.cprofile
+
+ @classmethod
+ def GetCurrentProfileDict(cls):
+ """Get the dictionary of keybindings
+ @param cls: Class Object
+ @return: dict
+
+ """
+ return cls.keyprofile
+
+ @staticmethod
+ def GetKeyProfiles():
+ """Get the list of available key profiles
+ @return: list of strings
+
+ """
+ recs = util.GetResourceFiles(u'cache', trim=True, get_all=False,
+ suffix='.ekeys', title=False)
+ if recs == -1:
+ recs = list()
+
+ tmp = util.GetResourceFiles(u'ekeys', True, True, '.ekeys', False)
+ if tmp != -1:
+ recs.extend(tmp)
+
+ return recs
+
+ def GetProfilePath(self, pname):
+ """Get the full path to the given keyprofile
+ @param pname: profile name
+ @return: string or None
+ @note: expects unique name for each profile in the case that
+ a name exists in both the user and system paths the one
+ found on the user path will be returned.
+
+ """
+ if pname is None:
+ return None
+
+ rname = None
+ for rec in self.GetKeyProfiles():
+ if rec.lower() == pname.lower():
+ rname = rec
+ break
+
+ # Must be a new profile
+ if rname is None:
+ rname = pname
+
+ kprof = u"%s%s.ekeys" % (ed_glob.CONFIG['CACHE_DIR'], rname)
+ if not os.path.exists(kprof):
+ # Must be a system supplied keyprofile
+ rname = u"%s%s.ekeys" % (ed_glob.CONFIG['KEYPROF_DIR'], rname)
+ if not os.path.exists(rname):
+ # Doesn't exist at syspath either so instead assume it is a new
+ # custom user defined key profile.
+ rname = kprof
+ else:
+ rname = kprof
+
+ return rname
+
+ @classmethod
+ def GetRawBinding(cls, item_id):
+ """Get the raw key binding tuple
+ @param cls: Class Object
+ @param item_id: MenuItem Id
+ @return: tuple
+
+ """
+ return cls.keyprofile.get(item_id, None)
+
+ @classmethod
+ def FindMenuId(cls, keyb):
+ """Find the menu item ID that the
+ keybinding is currently associated with.
+ @param cls: Class Object
+ @param keyb: tuple of unicode (u'Ctrl', u'C')
+ @return: int (-1 if not found)
+
+ """
+ menu_id = -1
+ for key, val in cls.keyprofile.iteritems():
+ if val == keyb:
+ menu_id = key
+ break
+ return menu_id
+
+ @classmethod
+ def LoadDefaults(cls):
+ """Load the default key profile"""
+ cls.keyprofile = dict(_DEFAULT_BINDING)
+ cls.cprofile = None
+
+ def LoadKeyProfile(self, pname):
+ """Load a key profile from profile directory into the binder
+ by name.
+ @param pname: name of key profile to load
+
+ """
+ if pname is None:
+ ppath = None
+ else:
+ ppath = self.GetProfilePath(pname)
+ self.LoadKeyProfileFile(ppath)
+
+ def LoadKeyProfileFile(self, path):
+ """Load a key profile from the given path
+ @param path: full path to file
+
+ """
+ keydict = dict()
+ pname = None
+ if path:
+ pname = os.path.basename(path)
+ pname = pname.rsplit('.', 1)[0]
+
+ if pname is not None and os.path.exists(path):
+ reader = util.GetFileReader(path)
+ if reader != -1:
+ util.Log("[keybinder][info] Loading KeyProfile: %s" % path)
+ for line in reader:
+ parts = line.split(u'=', 1)
+ # Check that the line was formatted properly
+ if len(parts) == 2:
+ # Try to find the ID value
+ item_id = _GetValueFromStr(parts[0])
+ if item_id is not None:
+ tmp = [ part.strip()
+ for part in parts[1].split(u'+')
+ if len(part.strip()) ]
+
+ # Do some checking if the binding is valid
+ nctrl = len([key for key in tmp
+ if key not in (u'Ctrl', u'Alt', u'Shift')])
+ if nctrl:
+ if parts[1].strip().endswith(u'++'):
+ tmp.append(u'+')
+ kb = tuple(tmp)
+ if kb in keydict.values():
+ for mid, b in keydict.iteritems():
+ if kb == b:
+ del keydict[mid]
+ break
+ keydict[item_id] = tuple(tmp)
+ else:
+ # Invalid key binding
+ continue
+
+ reader.close()
+ KeyBinder.keyprofile = keydict
+ KeyBinder.cprofile = pname
+ return
+ else:
+ util.Log("[keybinder][err] Couldn't read %s" % path)
+ elif pname is not None:
+ # Fallback to default keybindings
+ util.Log("[keybinder][err] Failed to load bindings from %s" % pname)
+
+ util.Log("[keybinder][info] Loading Default Keybindings")
+ KeyBinder.LoadDefaults()
+
+ def SaveKeyProfile(self):
+ """Save the current key profile to disk"""
+ if KeyBinder.cprofile is None:
+ util.Log("[keybinder][warn] No keyprofile is set, cant save")
+ else:
+ ppath = self.GetProfilePath(KeyBinder.cprofile)
+ writer = util.GetFileWriter(ppath)
+ if writer != -1:
+ itemlst = list()
+ for item in KeyBinder.keyprofile.keys():
+ itemlst.append(u"%s=%s%s" % (_FindStringRep(item),
+ self.GetBinding(item).lstrip(),
+ os.linesep))
+ writer.writelines(sorted(itemlst))
+ writer.close()
+ else:
+ util.Log("[keybinder][err] Failed to open %s for writing" % ppath)
+
+ @classmethod
+ def SetBinding(cls, item_id, keys):
+ """Set the keybinding of a menu id
+ @param cls: Class Object
+ @param item_id: item to set
+ @param keys: string or list of key strings ['Ctrl', 'S']
+
+ """
+ if isinstance(keys, basestring):
+ keys = [ key.strip() for key in keys.split(u'+')
+ if len(key.strip())]
+ keys = tuple(keys)
+
+ if len(keys):
+ # Check for an existing binding
+ menu_id = cls.FindMenuId(keys)
+ if menu_id != -1:
+ del cls.keyprofile[menu_id]
+ # Set the binding
+ cls.keyprofile[item_id] = keys
+ elif item_id in cls.keyprofile:
+ # Clear the binding
+ del cls.keyprofile[item_id]
+ else:
+ pass
+
+ @classmethod
+ def SetProfileName(cls, pname):
+ """Set the name of the current profile
+ @param cls: Class Object
+ @param pname: name to set profile to
+
+ """
+ cls.cprofile = pname
+
+ @classmethod
+ def SetProfileDict(cls, keyprofile):
+ """Set the keyprofile using a dictionary of id => bindings
+ @param cls: Class Object
+ @param keyprofile: { menu_id : (u'Ctrl', u'C'), }
+
+ """
+ cls.keyprofile = keyprofile
+
+#-----------------------------------------------------------------------------#
+
+class EdMenuBar(wx.MenuBar):
+ """Custom menubar to allow for easier access and updating
+ of menu components.
+ @todo: redo all of this
+
+ """
+ keybinder = KeyBinder()
+
+ def __init__(self, style=0):
+ """Initializes the Menubar
+ @keyword style: style to set for menu bar
+
+ """
+ super(EdMenuBar, self).__init__(style)
+
+ # Setup
+ if EdMenuBar.keybinder.GetCurrentProfile() is None:
+ kprof = profiler.Profile_Get('KEY_PROFILE', default='default')
+ EdMenuBar.keybinder.LoadKeyProfile(kprof)
+
+ # Attributes
+ self._menus = dict()
+ self.GenFileMenu()
+ self.GenEditMenu()
+ self.GenViewMenu()
+ self.GenFormatMenu()
+ self.GenSettingsMenu()
+ self.GenToolsMenu()
+ self.GenHelpMenu()
+
+ # Message handlers
+ ed_msg.Subscribe(self.OnRebind, ed_msg.EDMSG_MENU_REBIND)
+ ed_msg.Subscribe(self.OnLoadProfile, ed_msg.EDMSG_MENU_LOADPROFILE)
+ ed_msg.Subscribe(self.OnCreateLexerMenu, ed_msg.EDMSG_CREATE_LEXER_MENU)
+
+ def GenLexerMenu(self):
+ """Create the Lexer menu"""
+ settingsmenu = self._menus['settings']
+ item = settingsmenu.FindItemById(ed_glob.ID_LEXER)
+ if item:
+ settingsmenu.Remove(ed_glob.ID_LEXER)
+
+ # Create the menu
+ langmenu = wx.Menu()
+ langmenu.Append(ed_glob.ID_LEXER_CUSTOM, _("Customize..."),
+ _("Customize the items shown in this menu."))
+ langmenu.AppendSeparator()
+ EdMenuBar.PopulateLexerMenu(langmenu)
+ settingsmenu.AppendMenu(ed_glob.ID_LEXER, _("Lexers"),
+ langmenu,
+ _("Manually Set a Lexer/Syntax"))
+
+ @staticmethod
+ def PopulateLexerMenu(langmenu):
+ """Create a menu with all the lexer options
+ @return: wx.Menu
+
+ """
+ mconfig = profiler.Profile_Get('LEXERMENU', default=list())
+ mconfig.sort()
+ for label in mconfig:
+ lid = synglob.GetIdFromDescription(label)
+ langmenu.Append(lid, label,
+ _("Switch Lexer to %s") % label, wx.ITEM_CHECK)
+
+ @classmethod
+ def DeleteKeyProfile(cls, pname):
+ """Remove named keyprofile
+ @param cls: Class Object
+ @param pname: keyprofile name
+ @return: True if removed, False otherwise
+
+ """
+ ppath = cls.keybinder.GetProfilePath(pname)
+ if ppath is not None and os.path.exists(ppath):
+ try:
+ os.remove(ppath)
+ except:
+ return False
+ else:
+ return True
+ else:
+ return False
+
+ # TODO these Gen* functions should be broken up to the components
+ # that supply the functionality and inserted in the menus on
+ # init when the editor loads an associated widget.
+ def GenFileMenu(self):
+ """Makes and attaches the file menu
+ @return: None
+
+ """
+ filemenu = EdMenu()
+ filehist = self._menus['filehistory'] = EdMenu()
+ filemenu.AppendEx(ed_glob.ID_NEW, _("&New Tab"),
+ _("Start a new file in a new tab"))
+ filemenu.AppendEx(ed_glob.ID_NEW_WINDOW, _("New &Window"),
+ _("Start a new file in a new window"))
+ filemenu.AppendSeparator()
+ filemenu.AppendEx(ed_glob.ID_OPEN, _("&Open"), _("Open"))
+ ## Setup File History in the File Menu
+ filemenu.AppendMenu(ed_glob.ID_FHIST, _("Open &Recent"),
+ filehist, _("Recently Opened Files"))
+ filemenu.AppendSeparator()
+ filemenu.AppendEx(ed_glob.ID_CLOSE, _("&Close Tab"),
+ _("Close Current Tab"))
+ filemenu.AppendEx(ed_glob.ID_CLOSE_WINDOW,
+ _("Close Window") , _("Close the current window"))
+ filemenu.AppendEx(ed_glob.ID_CLOSEALL, _("Close All Tabs"),
+ _("Close all open tabs"))
+ filemenu.AppendSeparator()
+ filemenu.AppendEx(ed_glob.ID_SAVE, _("&Save"), _("Save Current File"))
+ filemenu.AppendEx(ed_glob.ID_SAVEAS, _("Save &As"), _("Save As"))
+ filemenu.AppendEx(ed_glob.ID_SAVEALL, _("Save All"),
+ _("Save all open pages"))
+ filemenu.AppendSeparator()
+ filemenu.AppendEx(ed_glob.ID_REVERT_FILE, _("Revert to Saved"),
+ _("Revert file to last save point"))
+ filemenu.AppendEx(ed_glob.ID_RELOAD_ENC, _("Reload with Encoding..."),
+ _("Reload the file with a specified encoding"))
+ filemenu.AppendSeparator()
+
+ # Profile
+ pmenu = EdMenu()
+ pmenu.AppendEx(ed_glob.ID_SAVE_PROFILE, _("Save Profile"),
+ _("Save Current Settings to a New Profile"))
+ pmenu.AppendEx(ed_glob.ID_LOAD_PROFILE, _("Load Profile"),
+ _("Load a Custom Profile"))
+ filemenu.AppendSubMenu(pmenu, _("Profile"),
+ _("Load and save custom Profiles"))
+
+ # Sessions
+ smenu = EdMenu()
+ smenu.AppendEx(ed_glob.ID_SAVE_SESSION, _("Save Session"),
+ _("Save the current session."))
+ smenu.AppendEx(ed_glob.ID_LOAD_SESSION, _("Load Session"),
+ _("Load a saved session."))
+ filemenu.AppendSubMenu(smenu, _("Sessions"),
+ _("Load and save custom sessions."))
+
+ filemenu.AppendSeparator()
+ filemenu.AppendEx(ed_glob.ID_PRINT_SU, _("Page Set&up"),
+ _("Configure Printer"))
+ filemenu.AppendEx(ed_glob.ID_PRINT_PRE, _("Print Pre&view"),
+ _("Preview Printout"))
+ filemenu.AppendEx(ed_glob.ID_PRINT, _("&Print"), _("Print Current File"))
+ filemenu.AppendSeparator()
+ filemenu.AppendEx(ed_glob.ID_EXIT, _("E&xit"), _("Exit the Program"))
+
+ # Attach to menubar and save reference
+ self.Append(filemenu, _("&File"))
+ self._menus['file'] = filemenu
+
+ def GenEditMenu(self):
+ """Makes and attaches the edit menu
+ @return: None
+
+ """
+ editmenu = EdMenu()
+ editmenu.AppendEx(ed_glob.ID_UNDO, _("&Undo"), _("Undo Last Action"))
+ editmenu.AppendEx(ed_glob.ID_REDO, _("Redo"), _("Redo Last Undo"))
+ editmenu.AppendSeparator()
+ editmenu.AppendEx(ed_glob.ID_CUT, _("Cu&t"),
+ _("Cut Selected Text from File"))
+ editmenu.AppendEx(ed_glob.ID_COPY, _("&Copy"),
+ _("Copy Selected Text to Clipboard"))
+ editmenu.AppendEx(ed_glob.ID_PASTE, _("&Paste"),
+ _("Paste Text from Clipboard to File"))
+ editmenu.AppendEx(ed_glob.ID_PASTE_AFTER, _("P&aste After"),
+ _("Paste Text from Clipboard to File after the cursor"))
+ editmenu.AppendEx(ed_glob.ID_CYCLE_CLIPBOARD, _("Cycle Clipboard"),
+ _("Cycle through recent clipboard text"))
+ editmenu.AppendSeparator()
+ editmenu.AppendEx(ed_glob.ID_SELECTALL, _("Select &All"),
+ _("Select All Text in Document"))
+ editmenu.AppendEx(ed_glob.ID_COLUMN_MODE, _("Column Edit"),
+ _("Enable column edit mode."), wx.ITEM_CHECK)
+ editmenu.AppendSeparator()
+ linemenu = EdMenu()
+ linemenu.AppendEx(ed_glob.ID_LINE_AFTER, _("New Line After"),
+ _("Add a new line after the current line"))
+ linemenu.AppendEx(ed_glob.ID_LINE_BEFORE, _("New Line Before"),
+ _("Add a new line before the current line"))
+ linemenu.AppendSeparator()
+ linemenu.AppendEx(ed_glob.ID_CUT_LINE, _("Cut Line"),
+ _("Cut Current Line"))
+ linemenu.AppendEx(ed_glob.ID_DELETE_LINE, _("Delete Line"),
+ _("Delete the selected line(s)"))
+ linemenu.AppendEx(ed_glob.ID_COPY_LINE, _("Copy Line"),
+ _("Copy Current Line"))
+ linemenu.AppendEx(ed_glob.ID_DUP_LINE, _("Duplicate Line"),
+ _("Duplicate the current line"))
+ linemenu.AppendSeparator()
+ linemenu.AppendEx(ed_glob.ID_JOIN_LINES, _("Join Lines"),
+ _("Join the Selected Lines"))
+ linemenu.AppendEx(ed_glob.ID_TRANSPOSE, _("Transpose Line"),
+ _("Transpose the current line with the previous one"))
+ linemenu.AppendEx(ed_glob.ID_LINE_MOVE_UP, _("Move Current Line Up"),
+ _("Move the current line up"))
+ linemenu.AppendEx(ed_glob.ID_LINE_MOVE_DOWN,
+ _("Move Current Line Down"),
+ _("Move the current line down"))
+ editmenu.AppendMenu(ed_glob.ID_LINE_EDIT, _("Line Edit"), linemenu,
+ _("Commands that affect an entire line"))
+ bookmenu = EdMenu()
+ bookmenu.AppendEx(ed_glob.ID_ADD_BM, _("Toggle Bookmark"),
+ _("Toggle bookmark of the current line"))
+ bookmenu.AppendEx(ed_glob.ID_DEL_ALL_BM, _("Remove All Bookmarks"),
+ _("Remove all bookmarks from the current document"))
+ editmenu.AppendMenu(ed_glob.ID_BOOKMARK, _("Bookmarks"), bookmenu,
+ _("Add and remove bookmarks"))
+ editmenu.AppendSeparator()
+ # Autocompletion shortcuts
+ editmenu.AppendEx(ed_glob.ID_SHOW_AUTOCOMP, _("Word Completion"),
+ _("Show autocompletion hints."))
+ editmenu.AppendEx(ed_glob.ID_SHOW_CALLTIP, _("Show Calltip"),
+ _("Show a calltip for the current word."))
+ editmenu.AppendSeparator()
+ editmenu.AppendEx(ed_glob.ID_FIND, _("&Find"), _("Find Text"))
+ editmenu.AppendEx(ed_glob.ID_FIND_REPLACE, _("Find/R&eplace"),
+ _("Find and Replace Text"))
+ editmenu.AppendEx(ed_glob.ID_QUICK_FIND, _("&Quick Find"),
+ _("Open the Quick Find Bar"))
+ editmenu.AppendEx(ed_glob.ID_FIND_PREVIOUS, _("Find Previous"),
+ _("Goto previous match"))
+ editmenu.AppendEx(ed_glob.ID_FIND_NEXT, _("Find Next"),
+ _("Goto the next match"))
+ editmenu.AppendEx(ed_glob.ID_FIND_SELECTED, _("Find Selected"),
+ _("Search for the currently selected phrase"))
+ editmenu.AppendSeparator()
+ editmenu.AppendEx(ed_glob.ID_PREF, _("Pr&eferences"),
+ _("Edit Preferences / Settings"))
+
+ # Attach to menubar and save ref
+ self.Append(editmenu, _("&Edit"))
+ self._menus['edit'] = editmenu
+
+ def GenViewMenu(self):
+ """Makes and attaches the view menu
+ @return: None
+
+ """
+ viewmenu = EdMenu()
+ viewmenu.AppendEx(ed_glob.ID_ZOOM_OUT, _("Zoom Out"), _("Zoom Out"))
+ viewmenu.AppendEx(ed_glob.ID_ZOOM_IN, _("Zoom In"), _("Zoom In"))
+ viewmenu.AppendEx(ed_glob.ID_ZOOM_NORMAL, _("Zoom Default"),
+ _("Zoom Default"))
+ viewmenu.AppendSeparator()
+ viewedit = self._menus['viewedit'] = EdMenu()
+ viewedit.AppendEx(ed_glob.ID_HLCARET_LINE, _("Highlight Caret Line"),
+ _("Highlight the background of the current line"),
+ wx.ITEM_CHECK)
+ viewedit.AppendEx(ed_glob.ID_INDENT_GUIDES, _("Indentation Guides"),
+ _("Show Indentation Guides"), wx.ITEM_CHECK)
+ viewedit.AppendEx(ed_glob.ID_SHOW_EDGE, _("Show Edge Guide"),
+ _("Show the edge column guide"), wx.ITEM_CHECK)
+ viewedit.AppendEx(ed_glob.ID_SHOW_EOL, _("Show EOL Markers"),
+ _("Show EOL Markers"), wx.ITEM_CHECK)
+ viewedit.AppendEx(ed_glob.ID_SHOW_LN, _("Show Line Numbers"),
+ _("Show Line Number Margin"), wx.ITEM_CHECK)
+ viewedit.AppendEx(ed_glob.ID_SHOW_WS, _("Show Whitespace"),
+ _("Show Whitespace Markers"), wx.ITEM_CHECK)
+ viewmenu.AppendSubMenu(self._menus['viewedit'], _("Editor"), \
+ _("Toggle Editor View Options"))
+ viewfold = self._menus['viewfold'] = EdMenu()
+ viewfold.AppendEx(ed_glob.ID_TOGGLE_FOLD, _("Toggle fold"),
+ _("Toggle current fold"))
+ viewfold.AppendEx(ed_glob.ID_TOGGLE_ALL_FOLDS, _("Toggle all folds"),
+ _("Toggle all folds"))
+ viewmenu.AppendSubMenu(self._menus['viewfold'], _("Code Folding"), \
+ _("Code folding toggle actions"))
+
+ viewmenu.AppendSeparator()
+ viewmenu.AppendEx(ed_glob.ID_PANELIST, _("Pane Navigator"),
+ _("View pane selection list"))
+ viewmenu.AppendEx(ed_glob.ID_MAXIMIZE_EDITOR, _("Maximize Editor"),
+ _("Toggle Editor Maximization"))
+ viewmenu.AppendSeparator()
+ viewmenu.AppendEx(ed_glob.ID_GOTO_LINE, _("&Goto Line"),
+ _("Goto Line Number"))
+ viewmenu.AppendEx(ed_glob.ID_GOTO_MBRACE, _("Goto Matching Brace"),
+ _("Move caret matching brace"))
+ viewmenu.AppendSeparator()
+ viewmenu.AppendEx(ed_glob.ID_NEXT_POS, _("Next Position"),
+ _("Goto next position in history."))
+ viewmenu.AppendEx(ed_glob.ID_PRE_POS, _("Previous Position"),
+ _("Goto previous position in history."))
+ viewmenu.AppendSeparator()
+ viewmenu.AppendEx(ed_glob.ID_NEXT_MARK, _("Next Bookmark"),
+ _("View Line of Next Bookmark"))
+ viewmenu.AppendEx(ed_glob.ID_PRE_MARK, _("Previous Bookmark"),
+ _("View Line of Previous Bookmark"))
+ viewmenu.AppendSeparator()
+ viewmenu.AppendEx(ed_glob.ID_SHOW_SB, ("Status &Bar"),
+ _("Show Status Bar"), wx.ITEM_CHECK)
+ viewmenu.AppendEx(ed_glob.ID_VIEW_TOOL, _("&Toolbar"),
+ _("Show Toolbar"), wx.ITEM_CHECK)
+
+ # Attach to menubar
+ self.Append(viewmenu, _("&View"))
+ self._menus['view'] = viewmenu
+
+ def GenFormatMenu(self):
+ """Makes and attaches the format menu
+ @return: None
+
+ """
+ formatmenu = EdMenu()
+ formatmenu.AppendEx(ed_glob.ID_FONT, _("&Font"),
+ _("Change Font Settings"))
+ formatmenu.AppendSeparator()
+ formatmenu.AppendEx(ed_glob.ID_TOGGLECOMMENT, _("Toggle Comment"),
+ _("Toggle comment on the selected line(s)"))
+ formatmenu.AppendSeparator()
+
+ formatmenu.AppendEx(ed_glob.ID_INDENT, _("Indent Lines"),
+ _("Indent the selected lines"))
+ formatmenu.AppendEx(ed_glob.ID_UNINDENT, _("Unindent Lines"),
+ _("Unindent the selected lines"))
+ formatmenu.AppendSeparator()
+ formatmenu.AppendEx(ed_glob.ID_TO_UPPER, _("Uppercase"),
+ _("Convert selected text to all uppercase letters"))
+ formatmenu.AppendEx(ed_glob.ID_TO_LOWER, _("Lowercase"),
+ _("Convert selected text to all lowercase letters"))
+ formatmenu.AppendSeparator()
+ formatmenu.AppendEx(ed_glob.ID_USE_SOFTTABS, _("Use Soft Tabs"),
+ _("Insert spaces instead of tab "
+ "characters with tab key"), wx.ITEM_CHECK)
+ formatmenu.AppendEx(ed_glob.ID_WORD_WRAP, _("Word Wrap"),
+ _("Wrap Text Horizontally"), wx.ITEM_CHECK)
+ formatmenu.AppendSeparator()
+
+ # Whitespace submenu
+ whitespace = self._menus['whitespaceformat'] = EdMenu()
+ whitespace.AppendEx(ed_glob.ID_SPACE_TO_TAB, _("Spaces to Tabs"),
+ _("Convert spaces to tabs in selected/all text"))
+ whitespace.AppendEx(ed_glob.ID_TAB_TO_SPACE, _("Tabs to Spaces"),
+ _("Convert tabs to spaces in selected/all text"))
+ whitespace.AppendEx(ed_glob.ID_TRIM_WS, _("Trim Trailing Whitespace"),
+ _("Remove trailing whitespace"))
+ formatmenu.AppendMenu(ed_glob.ID_WS_FORMAT, _("Whitespace"), whitespace,
+ _("Whitespace formating commands"))
+
+ # Line EOL formatting submenu
+ lineformat = self._menus['lineformat'] = EdMenu()
+ lineformat.AppendEx(ed_glob.ID_EOL_MAC, _("Old Macintosh (\\r)"),
+ _("Format all EOL characters to %s Mode") % \
+ _(u"Old Macintosh (\\r)"), wx.ITEM_CHECK)
+ lineformat.AppendEx(ed_glob.ID_EOL_UNIX, _("Unix (\\n)"),
+ _("Format all EOL characters to %s Mode") % \
+ _(u"Unix (\\n)"), wx.ITEM_CHECK)
+ lineformat.AppendEx(ed_glob.ID_EOL_WIN, _("Windows (\\r\\n)"),
+ _("Format all EOL characters to %s Mode") % \
+ _("Windows (\\r\\n)"), wx.ITEM_CHECK)
+ formatmenu.AppendMenu(ed_glob.ID_EOL_MODE, _("EOL Mode"), lineformat,
+ _("End of line character formatting"))
+
+ # Attach to menubar
+ self.Append(formatmenu, _("F&ormat"))
+ self._menus['format'] = formatmenu
+
+ def GenSettingsMenu(self):
+ """Makes and attaches the settings menu
+ @return: None
+
+ """
+ settingsmenu = EdMenu()
+ settingsmenu.AppendEx(ed_glob.ID_AUTOCOMP, _("Auto-Completion"),
+ _("Use Auto Completion when available"), wx.ITEM_CHECK)
+ settingsmenu.AppendEx(ed_glob.ID_AUTOINDENT, _("Auto-Indent"),
+ _("Toggle Auto-Indentation functionality"),
+ wx.ITEM_CHECK)
+ settingsmenu.AppendEx(ed_glob.ID_BRACKETHL, _("Bracket Highlighting"),
+ _("Highlight Brackets/Braces"), wx.ITEM_CHECK)
+ settingsmenu.AppendEx(ed_glob.ID_FOLDING, _("Code Folding"),
+ _("Toggle Code Folding"), wx.ITEM_CHECK)
+ settingsmenu.AppendEx(ed_glob.ID_SYNTAX, _("Syntax Highlighting"),
+ _("Color Highlight Code Syntax"), wx.ITEM_CHECK)
+
+ settingsmenu.AppendSeparator()
+
+ # Lexer Menu Appended later by main frame
+ self.Append(settingsmenu, _("&Settings"))
+ self._menus['settings'] = settingsmenu
+
+ self.GenLexerMenu()
+
+ def GenToolsMenu(self):
+ """Makes and attaches the tools menu
+ @return: None
+
+ """
+ toolsmenu = EdMenu()
+ toolsmenu.AppendEx(ed_glob.ID_COMMAND, _("Editor Command"),
+ _("Goto command buffer"))
+ toolsmenu.AppendEx(ed_glob.ID_SESSION_BAR, _("Session Manager"),
+ _("Show the session manager bar"))
+ toolsmenu.AppendEx(ed_glob.ID_PLUGMGR, _("Plugin Manager"),
+ _("Manage, Download, and Install plugins"))
+ toolsmenu.AppendEx(ed_glob.ID_STYLE_EDIT, _("Style Editor"),
+ _("Edit the way syntax is highlighted"))
+ toolsmenu.AppendSeparator()
+# macro = EdMenu()
+# macro.Append(ed_glob.ID_MACRO_START, _("Record Macro"),
+# _("Start macro recording"))
+# macro.Append(ed_glob.ID_MACRO_STOP, _("Stop Recording"),
+# _("Stop macro recording"))
+# macro.Append(ed_glob.ID_MACRO_PLAY, "Play Macro", "Play Macro")
+# toolsmenu.AppendMenu(wx.NewId(), _("Macros"), macro, _("Macro Tools"))
+
+ # Attach to menubar
+ self.Append(toolsmenu, _("&Tools"))
+ self._menus['tools'] = toolsmenu
+
+ def GenHelpMenu(self):
+ """Makes and attaches the help menu
+ @return: None
+
+ """
+ helpmenu = EdMenu()
+ helpmenu.AppendEx(ed_glob.ID_ABOUT, _("&About..."),
+ _("About") + u"...")
+ helpmenu.AppendEx(ed_glob.ID_HOMEPAGE, _("Project Homepage..."),
+ _("Visit the project homepage %s") % ed_glob.HOME_PAGE)
+ helpmenu.AppendEx(ed_glob.ID_DOCUMENTATION,
+ _("Online Documentation..."),
+ _("Online project documentation and help guides"))
+ helpmenu.AppendEx(ed_glob.ID_TRANSLATE, _("Translate Editra..."),
+ _("Editra translations project"))
+ helpmenu.AppendEx(ed_glob.ID_BUG_TRACKER, _("Bug Tracker..."))
+ helpmenu.AppendEx(ed_glob.ID_CONTACT, _("Feedback"),
+ _("Send bug reports and suggestions"))
+
+ # Attach to menubar
+ self.Append(helpmenu, _("&Help"))
+ self._menus['help'] = helpmenu
+
+ @classmethod
+ def GetKeyBinder(cls):
+ """Return the classes keybinder object
+ @param cls: Class Object
+ @return: KeyBinder
+
+ """
+ return cls.keybinder
+
+ def GetMenuByName(self, namestr):
+ """Find and return a menu by name
+ @param namestr: menuitems label
+ @return: menuitem or None if not found
+
+ """
+ return self._menus.get(namestr.lower(), None)
+
+ def GetMenuMap(self):
+ """Get a mapping of all menus to (menu id, menu label)
+ @return: list of dict
+
+ """
+ menumap = list()
+ for menu in self.GetMenus():
+ menumap.append(WalkMenu(menu[0], menu[1], dict()))
+ return menumap
+
+ @classmethod
+ def NewKeyProfile(cls, pname):
+ """Make a new key profile that is a clone of the current one
+ @param cls: Class Object
+ @param pname: Name to give new profile
+
+ """
+ cls.keybinder.SetProfileName(pname)
+ cls.keybinder.SaveKeyProfile()
+
+ def OnCreateLexerMenu(self, msg):
+ """Recreate the lexer menu"""
+ self.GenLexerMenu()
+
+ def OnLoadProfile(self, msg):
+ """Load and set the current key profile
+ @param msg: ed_msg.EDMSG_MENU_LOADPROFILE
+ @note: if message data is None the default bindings will be set
+
+ """
+ keyprof = msg.GetData()
+ if keyprof is not None:
+ self.SetKeyProfile(keyprof)
+ else:
+ EdMenuBar.keybinder.LoadDefaults()
+
+ def OnRebind(self, msg):
+ """Rebind all menu shortcuts when a rebind message is recieved
+ @param msg: ed_msg.EDMSG_MENU_REBIND
+
+ """
+ self.RebindKeys()
+
+ def RebindKeys(self):
+ """Reset all key bindings based on current binder profile"""
+ for menu in self.GetMenus():
+ for item in IterateMenuItems(menu[0]):
+ item_id = item.GetId()
+ binding = EdMenuBar.keybinder.GetBinding(item_id)
+ empty_binding = not len(binding)
+ if not empty_binding:
+ # Verify binding and clear invalid ones from binder
+ tmp = [key.title() for key in binding.strip().split(u'+')]
+ nctrl = len([key for key in tmp
+ if key not in (u'Ctrl', u'Alt', u'Shift')])
+ if len(tmp) > 3 or not nctrl:
+ EdMenuBar.keybinder.SetBinding(item_id, u'')
+ continue
+
+ # Reset the binding in the binder to ensure it is
+ # correctly formatted.
+ binding = u"\t" + u"+".join(tmp)
+ EdMenuBar.keybinder.SetBinding(item_id, binding)
+
+ clbl = item.GetText()
+ # Update the item if the shortcut has changed
+ if ('\t' in clbl and (not clbl.endswith(binding) or empty_binding)) or \
+ ('\t' not in clbl and not empty_binding):
+ # wxBug? Getting the text of a menuitem is supposed to
+ # return it with the accelerators but under gtk the string
+ # has underscores '_' where it was supposed to have '&'
+ if wx.Platform == '__WXGTK__':
+ clbl = clbl.replace('_', '&', 1)
+ item.SetText(clbl.split('\t')[0].strip() + binding)
+
+ def ResetIcons(self):
+ """Walk through each menu item in all of the bars menu and
+ reapply icons where possible.
+ @note: Don't use, sort of works on mac, does nothing on gtk, and causes
+ graphical glitches on msw.
+
+ """
+ for menu in self.GetMenus():
+ WalkAndSetBitmaps(menu[0])
+
+ @classmethod
+ def SaveKeyProfile(cls):
+ """Save the current key profile"""
+ cls.keybinder.SaveKeyProfile()
+
+ def SetKeyProfile(self, pname):
+ """Set the current key profile and update the bindings
+ @param pname: Name of keyprofile to load
+
+ """
+ EdMenuBar.keybinder.LoadKeyProfile(pname)
+ self.RebindKeys()
+
+#-----------------------------------------------------------------------------#
+
+#---- Private Objects/Functions ----#
+
+_DEFAULT_BINDING = { # File Menu
+ ed_glob.ID_NEW : (u"Ctrl", u"N"),
+ ed_glob.ID_NEW_WINDOW : (u"Ctrl", u"Shift", u"N"),
+ ed_glob.ID_OPEN : (u"Ctrl", u"O"),
+ ed_glob.ID_CLOSE : (u"Ctrl", u"W"),
+ ed_glob.ID_CLOSE_WINDOW : (u"Ctrl", u"Shift", u"W"),
+ ed_glob.ID_SAVE : (u"Ctrl", u"S"),
+ ed_glob.ID_SAVEAS : (u"Ctrl", u"Shift", u"S"),
+ ed_glob.ID_PRINT_SU : (u"Ctrl", u"Shift", u"P"),
+ ed_glob.ID_PRINT : (u"Ctrl", u"P"),
+ ed_glob.ID_EXIT : (u"Ctrl", u"Q"),
+
+ # Edit Menu
+ ed_glob.ID_UNDO : (u"Ctrl", u"Z"),
+ ed_glob.ID_REDO : (u"Ctrl", u"Shift", u"Z"),
+ ed_glob.ID_CUT : (u"Ctrl", u"X"),
+ ed_glob.ID_COPY : (u"Ctrl", u"C"),
+ ed_glob.ID_PASTE : (u"Ctrl", u"V"),
+ ed_glob.ID_PASTE_AFTER : (u"Ctrl", u"Shift", u"V"),
+ ed_glob.ID_CYCLE_CLIPBOARD : (u"Ctrl", u"I"),
+ ed_glob.ID_SELECTALL : (u"Ctrl", u"A"),
+ ed_glob.ID_COLUMN_MODE : (u"Ctrl", u"Shift", u"|"),
+ ed_glob.ID_LINE_AFTER : (u"Ctrl", u"L"),
+ ed_glob.ID_LINE_BEFORE : (u"Ctrl", u"Shift", u"L"),
+ ed_glob.ID_CUT_LINE : (u"Ctrl", u"D"),
+ ed_glob.ID_DELETE_LINE : (u"Ctrl", u"Shift", "D"),
+ ed_glob.ID_COPY_LINE : (u"Ctrl", u"Y"),
+ ed_glob.ID_DUP_LINE : (u"Ctrl", u"Shift", u"C"),
+ ed_glob.ID_JOIN_LINES : (u"Ctrl", u"J"),
+ ed_glob.ID_TRANSPOSE : (u"Ctrl", u"T"),
+ ed_glob.ID_LINE_MOVE_UP : (u"Ctrl", u"Shift", u"Up"),
+ ed_glob.ID_LINE_MOVE_DOWN : (u"Ctrl", u"Shift", u"Down"),
+ ed_glob.ID_ADD_BM : (u"Ctrl", u"B"),
+ ed_glob.ID_SHOW_AUTOCOMP : (u"Ctrl", u"Space"),
+ ed_glob.ID_SHOW_CALLTIP : (u"Ctrl", u"9"),
+ ed_glob.ID_FIND : (u"Ctrl", u"Shift", u"F"),
+ ed_glob.ID_FIND_PREVIOUS : (u"Shift", u"F3"),
+ ed_glob.ID_FIND_NEXT : (u"F3",),
+ ed_glob.ID_FIND_REPLACE : (u"Ctrl", u"R"),
+ ed_glob.ID_QUICK_FIND : (u"Ctrl", u"F"),
+ ed_glob.ID_FIND_SELECTED : (u"Ctrl", u"F3"),
+
+ # View Menu
+ ed_glob.ID_ZOOM_IN : (u"Ctrl", u"+"),
+ ed_glob.ID_ZOOM_OUT : (u"Ctrl", u"-"),
+ ed_glob.ID_ZOOM_NORMAL : (u"Ctrl", u"0"),
+ ed_glob.ID_GOTO_LINE : (u"Ctrl", u"G"),
+ ed_glob.ID_GOTO_MBRACE : (u"Ctrl", u"Shift", u"B"),
+ ed_glob.ID_TOGGLE_FOLD : (u"Ctrl", u"Shift", u"T"),
+ ed_glob.ID_NEXT_POS : (u"Ctrl", u"Shift", u">"),
+ ed_glob.ID_PRE_POS : (u"Ctrl", u"Shift", u"<"),
+ ed_glob.ID_NEXT_MARK : (u"Alt", u"Right"), # Win/Linux
+ ed_glob.ID_PRE_MARK : (u"Alt", u"Left"), # Win/Linux
+ ed_glob.ID_SHOW_SHELF : (u"Ctrl", u"Alt", u"S"),
+ ed_glob.ID_PANELIST : (u"Alt", u"1"), # Win/Linux
+ ed_glob.ID_MAXIMIZE_EDITOR : (u"Ctrl", u"M"),
+
+ # Format Menu
+ ed_glob.ID_TOGGLECOMMENT : (u"Ctrl", u"1"),
+ ed_glob.ID_INDENT : (u"Tab",),
+ ed_glob.ID_UNINDENT : (u"Shift", u"Tab"),
+ ed_glob.ID_USE_SOFTTABS : (u"Ctrl", u"Shift", u"I"),
+
+ # Tools Menu
+ ed_glob.ID_COMMAND : (u"Ctrl", u"E"),
+ ed_glob.ID_SESSION_BAR : (u"Ctrl", u"K"),
+ ed_glob.ID_RUN_LAUNCH : (u"F5",),
+ ed_glob.ID_LAUNCH_LAST : (u"Shift", u"F5")
+ }
+
+# Set some platform specific keybindings
+if wx.Platform == '__WXMAC__':
+ _DEFAULT_BINDING[ed_glob.ID_NEXT_MARK] = (u"Ctrl", u"Down")
+ _DEFAULT_BINDING[ed_glob.ID_PRE_MARK] = (u"Ctrl", u"Up")
+ _DEFAULT_BINDING[ed_glob.ID_FIND_PREVIOUS] = (u"Ctrl", u"Shift", u"G")
+ _DEFAULT_BINDING[ed_glob.ID_FIND_NEXT] = (u"Ctrl", u"G")
+ _DEFAULT_BINDING[ed_glob.ID_GOTO_LINE] = (u"Ctrl", u"Shift", u"E")
+ _DEFAULT_BINDING[ed_glob.ID_PANELIST] = (u"Alt", u"Tab")
+ _DEFAULT_BINDING[ed_glob.ID_MAXIMIZE_EDITOR] = (u"Alt", u"M")
+ _DEFAULT_BINDING[ed_glob.ID_FIND_SELECTED] = (u"Ctrl", u"3")
+elif wx.Platform == '__WXMSW__':
+ # FIXME: On Windows if Tab is bound to a menu item it is no longer
+ # usable elsewhere such as in the stc control. On Mac/Gtk there
+ # are not problems with it.
+ _DEFAULT_BINDING[ed_glob.ID_INDENT] = (u"",)
+else:
+ pass
+
+def _FindStringRep(item_id):
+ """Find the string representation of the given id value
+ @param item_id: int
+ @return: string or None
+
+ """
+ for obj in dir(ed_glob):
+ if getattr(ed_glob, obj) == item_id:
+ return obj
+ else:
+ return None
+
+def _GetValueFromStr(item_str):
+ """Get the id value from the string representation of the object
+ @param item_str: items variable string
+ @return: int or None
+
+ """
+ return getattr(ed_glob, item_str, None)
+
+#---- Public Functions ----#
+
+def IterateMenuItems(menu):
+ """Recursively walk and yield menu items as the are found. Only menu
+ items are yielded, not submenus or separators.
+ @param menu: menu to iterate
+
+ """
+ for item in menu.GetMenuItems():
+ if item.IsSubMenu():
+ for subitem in IterateMenuItems(item.GetSubMenu()):
+ yield subitem
+ if not item.IsSeparator():
+ yield item
+ else:
+ continue
+
+def WalkAndSetBitmaps(menu):
+ """Recursively walk a menu and its submenus setting bitmaps
+ as necessary/available, using the the current theme.
+
+ """
+ for item in menu.GetMenuItems():
+ if item.IsSubMenu():
+ WalkAndSetBitmaps(item.GetSubMenu())
+ else:
+ bmp = wx.ArtProvider.GetBitmap(str(item.GetId()), wx.ART_MENU)
+ if bmp.IsOk():
+ item.SetBitmap(bmp)
+ elif not item.GetBitmap().IsNull():
+ item.SetBitmap(wx.NullBitmap)
+ else:
+ continue
+
+def WalkMenu(menu, label, collection):
+ """Recursively walk a menu and collect all its sub items
+ @param menu: wxMenu to walk
+ @param label: the menu's label
+ @param collection: dictionary to collect results in
+ @return: dict {menulabel : [menu id, (item1 id, label1),]}
+
+ """
+ if label not in collection:
+ collection[label] = list()
+
+ for item in menu.GetMenuItems():
+ i_id = item.GetId()
+ if item.IsSubMenu():
+ # Ignore dynamically generated menus
+ if i_id not in (ed_glob.ID_FHIST, ed_glob.ID_LEXER,
+ ed_glob.ID_PERSPECTIVES):
+ ilbl = item.GetItemLabelText()
+ collection[ilbl] = [i_id, ]
+ WalkMenu(item.GetSubMenu(), ilbl, collection)
+ else:
+ continue
+ elif item.IsSeparator():
+ continue
+ elif _FindStringRep(i_id) is not None:
+ lbl = item.GetItemLabelText().split('\t')[0].strip()
+ # wxBug? Even the methods that are supposed to return the text
+ # without mnemonics or accelerators on gtk return the string with
+ # underscores where the mnemonics '&' are in the original strings
+ if wx.Platform == '__WXGTK__':
+ lbl = lbl.replace('_', '', 1)
+ collection[label].append((i_id, lbl))
+ else:
+ continue
+ return collection
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mpane.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mpane.py
new file mode 100644
index 0000000..2e27c90
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mpane.py
@@ -0,0 +1,100 @@
+###############################################################################
+# Name: ed_mpane.py #
+# Purpose: Main panel containing notebook and command bar. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This module provides the L{MainPanel} component. That contains the editors main
+notebook and command bar.
+
+@summary: Main Panel
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_mpane.py 72278 2012-08-02 14:24:23Z CJP $"
+__revision__ = "$Revision: 72278 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+# Editra Libraries
+import ed_glob
+import ed_pages
+import ed_cmdbar
+import eclib
+
+#-----------------------------------------------------------------------------#
+
+class MainPanel(eclib.ControlBox):
+ """Main panel view
+ @todo: Add interface for registering additional commandbars.
+
+ """
+ def __init__(self, parent):
+ """Initialize the panel"""
+ super(MainPanel, self).__init__(parent)
+
+ # Attributes
+ self.nb = ed_pages.EdPages(self)
+ self._bars = dict()
+
+ # Layout
+ self.SetWindow(self.nb)
+
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEB)
+
+ def OnEB(self, evt):
+ """Empty method to fix notebook flashing issue on MSW"""
+ pass
+
+ Book = property(lambda self: self.nb)
+
+ def GetNotebook(self):
+ """Get the main notebook control
+ @return: EdPages instance
+
+ """
+ return self.nb
+
+ def HideCommandBar(self):
+ """Hide the command bar"""
+ bar = self.GetControlBar(wx.BOTTOM)
+ if bar:
+ bar.Hide()
+ self.Layout()
+
+ def ShowCommandControl(self, ctrlid):
+ """Change the mode of the commandbar
+ @param ctrlid: CommandBar control id
+
+ """
+ cur_bar = self.GetControlBar(wx.BOTTOM)
+ if ctrlid in self._bars:
+ nbar = self._bars[ctrlid]
+ else:
+ nbar = ed_cmdbar.CommandBarBase.FactoryCreate(ctrlid, self)
+ if nbar:
+ self._bars[ctrlid] = nbar
+
+ if nbar and nbar is not cur_bar:
+ if cur_bar is None:
+ self.SetControlBar(nbar, wx.BOTTOM)
+ else:
+ cur_bar = self.ReplaceControlBar(nbar, wx.BOTTOM)
+
+ if cur_bar:
+ if cur_bar is not nbar:
+ cur_bar.Hide()
+
+ cbar = self.GetControlBar(wx.BOTTOM)
+ if cbar is not None:
+ cbar.Show()
+ cbar.Layout()
+ cbar.SetFocus()
+
+ self.Layout()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_msg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_msg.py
new file mode 100644
index 0000000..a59c119
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_msg.py
@@ -0,0 +1,496 @@
+###############################################################################
+# Name: ed_msg.py #
+# Purpose: Provide a messaging/notification system for actions performed in #
+# the editor. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This module provides a light wrapping of a slightly modified pubsub module
+to give it a lighter and simpler syntax for usage. It exports three main
+methods. The first L{PostMessage} which is used to post a message for all
+interested listeners. The second L{Subscribe} which allows an object to
+subscribe its own listener function for a particular message type, all of
+Editra's core message types are defined in this module using a naming
+convention that starts each identifier with I{EDMSG_}. These identifier
+constants can be used to identify the message type by comparing them with the
+value of msg.GetType in a listener method. The third method is L{Unsubscribe}
+which can be used to remove a listener from recieving messages.
+
+@summary: Message system api and message type definitions
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_msg.py 71697 2012-06-08 15:20:22Z CJP $"
+__revision__ = "$Revision: 71697 $"
+
+__all__ = ['PostMessage', 'Subscribe', 'Unsubscribe']
+
+#--------------------------------------------------------------------------#
+# Imports
+from wx import PyDeadObjectError
+from extern.pubsub import Publisher
+
+#--------------------------------------------------------------------------#
+# Message Type Definitions
+
+#---- General Messages ----#
+
+# Listen to all messages
+EDMSG_ALL = ('editra',)
+
+#---- End General Messages ----#
+
+#---- Log Messages ----#
+# Used internally by the log system. Listed by priority lowest -> highest
+# All message data from these functions are a LogMsg object which is a
+# container object for the message string / timestamp / type
+#
+# Using these message types with the PostMessage method is not suggested for
+# use in user code instead use the logging facilities (wx.GetApp().GetLog() or
+# util.Getlog() ) as they will handle the formatting that is expected by the
+# log messaging listeners.
+
+# Recieve all log messages (i.e anything put on the logging system)
+EDMSG_LOG_ALL = EDMSG_ALL + ('log',)
+
+# Recieve all messages that have been labled (info, events, warnings, errors)
+EDMSG_LOG_INFO = EDMSG_LOG_ALL + ('info',)
+
+# Messages generated by ui events
+EDMSG_LOG_EVENT = EDMSG_LOG_INFO + ('evt',)
+
+# Recieve only warning messages
+EDMSG_LOG_WARN = EDMSG_LOG_INFO + ('warn',)
+
+# Recieve only error messages
+EDMSG_LOG_ERROR = EDMSG_LOG_INFO + ('err',)
+
+#---- End Log Messages ----#
+
+#---- Configuration Messages ----#
+
+# These messages will be sent when there are configuration
+# changes in the current user profile. Messages will be in
+# the format of (editra,config,PROFILE_KEY)
+# mdata == Profile[PROFILE_KEY]
+EDMSG_PROFILE_CHANGE = EDMSG_ALL + ('config',)
+
+#---- End Configuration Messages ----#
+
+#---- File Action Messages ----#
+
+# Recieve notification of all file actions
+EDMSG_FILE_ALL = EDMSG_ALL + ('file',)
+
+# File open was just requested / msgdata == file path
+EDMSG_FILE_OPENING = EDMSG_FILE_ALL + ('opening',)
+
+# File was just opened / msgdata == file path
+# context == MainWindows ID
+EDMSG_FILE_OPENED = EDMSG_FILE_ALL + ('opened',)
+
+# Get a list of all opened files
+# msgdata == list of file paths (out param)
+EDMSG_FILE_GET_OPENED = EDMSG_FILE_ALL + ('allopened',)
+
+# TODO: using MainWindow as context for now, but may make more sense to use
+# the buffer instead.
+
+# File save requested / msgdata == (filename, filetypeId)
+# context == MainWindows ID
+# Note: All listeners of this message are processed *before* the save takes
+# place. Meaning the listeners block the save action until they are
+# finished.
+EDMSG_FILE_SAVE = EDMSG_FILE_ALL + ('save',)
+
+# File just written to disk / msgdata == (filename, filetypeId)
+# context == MainWindows ID
+EDMSG_FILE_SAVED = EDMSG_FILE_ALL + ('saved',)
+
+#---- End File Action Messages ----#
+
+#---- UI Action Messages ----#
+
+# Recieve notification of all ui typed messages
+EDMSG_UI_ALL = EDMSG_ALL + ('ui',)
+
+#- Receive all Main Notebook Messages
+EDMSG_UI_NB = EDMSG_UI_ALL + ('mnotebook',)
+
+# MainWindow Activated
+# msgdata == dict(active=bool)
+# context = MainWindow ID
+EDMSG_UI_MW_ACTIVATE = EDMSG_UI_ALL + ('mwactivate',)
+
+# Notebook page changing
+# msgdata == (ref to notebook,
+# index of previous selection,
+# index of current selection)
+# context == MainWindow ID
+EDMSG_UI_NB_CHANGING = EDMSG_UI_NB + ('pgchanging',)
+
+# Notebook page changed
+# msgdata == (ref to notebook, index of currently selected page)
+# context == MainWindow ID
+EDMSG_UI_NB_CHANGED = EDMSG_UI_NB + ('pgchanged',)
+
+# Page is about to close
+# msgdata == (ref to notebook, index of page that is closing)
+# context == MainWindow ID
+EDMSG_UI_NB_CLOSING = EDMSG_UI_NB + ('pgclosing',)
+
+# Page has just been closed
+# msgdata == (ref to notebook, index of page that is now selected)
+# context == MainWindow ID
+EDMSG_UI_NB_CLOSED = EDMSG_UI_NB + ('pgclosed',)
+
+# Tab Menu requested
+# msgdata == ContextMenuManager
+# menu = ContextMenuManager.GetMenu()
+# ContextMenuManager.AddHandler(ID_MENU_ID, handler(buffer, event))
+# page = ContextMenuManager.GetUserData("page")
+EDMSG_UI_NB_TABMENU = EDMSG_UI_NB + ('tabmenu',)
+
+# Post message to show the progress indicator of the MainWindow
+# msgdata == (frame id, True / False)
+EDMSG_PROGRESS_SHOW = EDMSG_UI_ALL + ('statbar', 'progbar', 'show')
+
+# Post this message to manipulate the state of the MainWindows status bar
+# progress indicator. The message data should be a three tuple of the recipient
+# frames id, current progress and the total range (current, total). If both
+# values are 0 then the bar will be hidden. If both are negative the bar will
+# be set into pulse mode. This message can safely be sent from background
+# threads.
+EDMSG_PROGRESS_STATE = EDMSG_UI_ALL + ('statbar', 'progbar', 'state')
+
+# Set the status text
+# msgdata == (field id, text)
+EDMSG_UI_SB_TXT = EDMSG_UI_ALL + ('statbar', 'text')
+
+## Text Buffer ##
+
+# Root message for the text buffer
+EDMSG_UI_STC_ALL = EDMSG_UI_ALL + ('stc',)
+
+# msgdata == ((x, y), keycode)
+# context == MainWindows ID
+EDMSG_UI_STC_KEYUP = EDMSG_UI_STC_ALL + ('keyup',)
+
+# msgdata == dict(lnum=line, cnum=column)
+# context == MainWindows ID
+EDMSG_UI_STC_POS_CHANGED = EDMSG_UI_STC_ALL + ('position',)
+
+# msgdata == dict(fname=fname,
+# prepos=pos, preline=line,
+# lnum=cline, pos=cpos)
+# context == MainWindow ID
+EDMSG_UI_STC_POS_JUMPED = EDMSG_UI_STC_ALL + ('jump',)
+
+# Editor control size restored (msgdata == None)
+EDMSG_UI_STC_RESTORE = EDMSG_UI_STC_ALL + ('restore',)
+
+# Lexer Changed
+# msgdata == (filename, filetype id)
+# context == MainWindows ID
+EDMSG_UI_STC_LEXER = EDMSG_UI_STC_ALL + ('lexer',)
+
+# Buffer Changed
+# NOTE: this gets called ALOT so be very efficient in any handlers of it!
+# msgdata == None
+EDMSG_UI_STC_CHANGED = EDMSG_UI_STC_ALL + ('changed',)
+
+# Customize Context Menu
+# Add custom menu items and handlers to the buffers right click menu
+# msgdata = ContextMenuManager
+# ContextMenuManager.AddHandler(menu_id, handler)
+# menu = ContextMenuManager.GetMenu()
+# def handler(buffer, event_obj)
+# ContextMenuManager.GetData('buffer')
+EDMSG_UI_STC_CONTEXT_MENU = EDMSG_UI_STC_ALL + ('custommenu',)
+
+# UserList Selection
+# msgdata == dict(ltype=int, text=string, stc=EditraStc)
+EDMSG_UI_STC_USERLIST_SEL = EDMSG_UI_STC_ALL + ('userlistsel',)
+
+# Mouse Dwell Start
+# mdata = dict(stc=self, pos=position,
+# line=line_number,
+# word=word_under_cursor
+# rdata="")
+# If the handler for this method wants to show a calltip
+# it should set the rdata value
+EDMSG_UI_STC_DWELL_START = EDMSG_UI_STC_ALL + ('dwellstart',)
+
+# Mouse Dwell End
+# mdata = None
+EDMSG_UI_STC_DWELL_END = EDMSG_UI_STC_ALL + ('dwellend',)
+
+# Bookmark (added/deleted)
+# mdata = dict(stc=EditraStc, added=bool, line=line, handle=bookmarkhandle)
+# NOTE: if line < 0, then all bookmarks removed
+EDMSG_UI_STC_BOOKMARK = EDMSG_UI_STC_ALL + ('bookmark',)
+
+# Margin Click
+# mdata = dict(stc=EditraStc, line=line, handled=bool)
+# handled is an out param in the message data. Set to True
+# to indicate that the click was handled.
+EDMSG_UI_STC_MARGIN_CLICK = EDMSG_UI_STC_ALL + ('marginclick',)
+
+#---- End UI Action Messages ----#
+
+#---- Menu Messages ----#
+EDMSG_MENU = EDMSG_ALL + ('menu',)
+
+# Signal to all windows to update keybindings (msgdata == None)
+EDMSG_MENU_REBIND = EDMSG_MENU + ('rebind',)
+
+# Message to set key profile
+# msgdata == keyprofile name
+EDMSG_MENU_LOADPROFILE = EDMSG_MENU + ('load',)
+
+# Message to recreate the lexer menu
+# msgdata == None
+EDMSG_CREATE_LEXER_MENU = EDMSG_MENU + ('lexer',)
+
+#---- End Menu Messages ----#
+
+#---- Find Actions ----#
+
+EDMSG_FIND_ALL = EDMSG_ALL + ('find',)
+
+# Show or modify an existing find dialog
+# msgdata = dict(mw, lookin, searchtxt, replacetxt)
+EDMSG_FIND_SHOW_DLG = EDMSG_FIND_ALL + ('show',)
+
+# Message to request a search job
+# msgdata == (callable, args, kwargs)
+# msgdata == (callable)
+EDMSG_START_SEARCH = EDMSG_FIND_ALL + ('results',)
+
+#---- End Find Actions ----#
+
+#---- Session Related Actions ----#
+
+# Root Session Message
+EDMSG_SESSION_ALL = ('session',)
+
+# Initiate a Session Save to save current session under new name.
+# Note: This invokes a UI action to prompt the user on what to name
+# the session. DO NOT call from background threads.
+# send(msgdata == None) | context - MainWindow
+EDMSG_SESSION_DO_SAVE = EDMSG_SESSION_ALL + ('dosave',)
+
+# Initiate loading a session
+# Causes all currently open files to be closed and the files from the
+# specified session to be loaded. Not thread safe.
+# send(msgdata == session_name)
+EDMSG_SESSION_DO_LOAD = EDMSG_SESSION_ALL + ('doload',)
+
+#---- End Session Related Actions ----#
+
+#---- Misc Messages ----#
+# Signal that the icon theme has changed. Respond to this to update icon
+# resources from the ArtProvider.
+EDMSG_THEME_CHANGED = EDMSG_ALL + ('theme',) # All theme listeners
+
+# Update the theme the notebook specifically to the current preferences
+EDMSG_THEME_NOTEBOOK = EDMSG_ALL + ('nb', 'theme')
+
+# Signal that the font preferences for the ui have changed (msgdata == font)
+EDMSG_DSP_FONT = EDMSG_ALL + ('dfont',)
+
+# Add file to file history
+# msgdata == filename
+EDMSG_ADD_FILE_HISTORY = EDMSG_ALL + ('filehistory',)
+
+#---- End Misc Messages ----#
+
+#--------------------------------------------------------------------------#
+# Public Api
+_ThePublisher = Publisher()
+
+def PostMessage(msgtype, msgdata=None, context=None):
+ """Post a message containing the msgdata to all listeners that are
+ interested in the given msgtype from the given context. If context
+ is None than default context is assumed.
+ Message is always propagated to the default context.
+ @param msgtype: Message Type EDMSG_*
+ @keyword msgdata: Message data to pass to listener (can be anything)
+ @keyword context: Context of the message.
+
+ """
+ _ThePublisher.sendMessage(msgtype, msgdata, context=context)
+
+def Subscribe(callback, msgtype=EDMSG_ALL):
+ """Subscribe your listener function to listen for an action of type msgtype.
+ The callback must be a function or a _bound_ method that accepts one
+ parameter for the actions message. The message that is sent to the callback
+ is a class object that has two attributes, one for the message type and the
+ other for the message data. See below example for how these two values can
+ be accessed.
+ >>> def MyCallback(msg):
+ print "Msg Type: ", msg.GetType(), "Msg Data: ", msg.GetData()
+
+ >>> class Foo:
+ def MyCallbackMeth(self, msg):
+ print "Msg Type: ", msg.GetType(), "Msg Data: ", msg.GetData()
+
+ >>> Subscribe(MyCallback, EDMSG_SOMETHING)
+ >>> myfoo = Foo()
+ >>> Subscribe(myfoo.MyCallBackMeth, EDMSG_SOMETHING)
+
+ @param callback: Callable function or bound method
+ @keyword msgtype: Message to subscribe to (default to all)
+
+ """
+ _ThePublisher.subscribe(callback, msgtype)
+
+def Unsubscribe(callback, messages=None):
+ """Remove a listener so that it doesn't get sent messages for msgtype. If
+ msgtype is not specified the listener will be removed for all msgtypes that
+ it is associated with.
+ @param callback: Function or bound method to remove subscription for
+ @keyword messages: EDMSG_* val or list of EDMSG_* vals
+
+ """
+ Publisher().unsubscribe(callback, messages)
+
+
+#---- Helper Decorators ----#
+
+def mwcontext(func):
+ """Helper decorator for checking if the message is in context of the
+ main window. Class that uses this to wrap its message handlers must
+ have a GetMainWindow method that returns a reference to the MainWindow
+ instance that owns the object.
+ @param funct: callable(self, msg)
+
+ """
+ def ContextWrap(self, msg):
+ """Check and only call the method if the message is in the
+ context of the main window or no context was specified.
+
+ """
+ if hasattr(self, 'GetMainWindow'):
+ mw = self.GetMainWindow()
+ elif hasattr(self, 'MainWindow'):
+ mw = self.MainWindow
+ else:
+ assert False, "Must declare a GetMainWindow method"
+ context = msg.GetContext()
+ if context is None or mw.GetId() == context:
+ func(self, msg)
+
+ ContextWrap.__name__ = func.__name__
+ ContextWrap.__doc__ = func.__doc__
+ return ContextWrap
+
+def wincontext(funct):
+ """Decorator to filter messages based on a window. Class must declare
+ a GetWindow method that returns the window that the messages context
+ should be filtered on.
+ @param funct: callable(self, msg)
+
+ """
+ def ContextWrap(self, msg):
+ assert hasattr(self, 'GetWindow'), "Must define a GetWindow method"
+ context = msg.GetContext()
+ if isinstance(context, wx.Window) and context is self.GetWindow():
+ funct(self, msg)
+
+ ContextWrap.__name__ = funct.__name__
+ ContextWrap.__doc__ = funct.__doc__
+ return ContextWrap
+
+#-----------------------------------------------------------------------------#
+
+# Request Messages
+EDREQ_ALL = ('editra', 'req')
+
+EDREQ_DOCPOINTER = EDREQ_ALL + ('docpointer',)
+
+#-----------------------------------------------------------------------------#
+
+class NullValue:
+ """Null value to signify that a callback method should be skipped or that
+ no callback could answer the request.
+
+ """
+ def __int__(self):
+ return 0
+
+ def __nonzero__(self):
+ return False
+
+def RegisterCallback(callback, msgtype):
+ """Register a callback method for the given message type
+ @param callback: callable
+ @param msgtype: message type
+
+ """
+ if isinstance(msgtype, tuple):
+ mtype = '.'.join(msgtype)
+ else:
+ mtype = msgtype
+
+ if mtype not in _CALLBACK_REGISTRY:
+ _CALLBACK_REGISTRY[mtype] = list()
+
+ if callback not in _CALLBACK_REGISTRY[mtype]:
+ _CALLBACK_REGISTRY[mtype].append(callback)
+
+def RequestResult(msgtype, args=list()):
+ """Request a return value result from a registered function/method.
+ If multiple callbacks have been registered for the given msgtype, the
+ first callback to return a non-NullValue will be used for the return
+ value. If L{NullValue} is returned then no callback could answer the
+ call.
+ @param msgtype: Request message
+ @keyword args: Arguments to pass to the callback
+
+ """
+ if isinstance(msgtype, tuple):
+ mtype = '.'.join(msgtype)
+ else:
+ mtype = msgtype
+
+ to_remove = list()
+ rval = NullValue()
+ for idx, meth in enumerate(_CALLBACK_REGISTRY.get(mtype, list())):
+ try:
+ if len(args):
+ rval = meth(args)
+ else:
+ rval = meth()
+ except PyDeadObjectError:
+ to_remove.append(meth)
+
+ if not isinstance(rval, NullValue):
+ break
+
+ # Remove any dead objects that may have been found
+ for val in reversed(to_remove):
+ try:
+ _CALLBACK_REGISTRY.get(mtype, list()).pop(val)
+ except:
+ pass
+
+ return rval
+
+def UnRegisterCallback(callback):
+ """Un-Register a callback method
+ @param callback: callable
+
+ """
+ for key, val in _CALLBACK_REGISTRY.iteritems():
+ if callback in val:
+ _CALLBACK_REGISTRY[key].remove(callback)
+
+# Callback Registry for storing the methods sent in with RegisterCallback
+_CALLBACK_REGISTRY = {}
+
+#-----------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_pages.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_pages.py
new file mode 100644
index 0000000..7c8662f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_pages.py
@@ -0,0 +1,1286 @@
+###############################################################################
+# Name: ed_pages.py #
+# Purpose: The main editor notebook #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This class implements Editra's main notebook control.
+@summary: Editra's main notebook class
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_pages.py 72278 2012-08-02 14:24:23Z CJP $"
+__revision__ = "$Revision: 72278 $"
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import os
+import sys
+import glob
+import wx
+
+# Editra Libraries
+import ed_glob
+from profiler import Profile_Get, Profile_Set
+import ed_editv
+import syntax.synglob as synglob
+import syntax.syntax as syntax
+import ed_search
+import util
+import ed_msg
+import ed_txt
+import ed_mdlg
+import ed_session
+import ebmlib
+import eclib
+from extern import aui
+import ed_book
+
+#--------------------------------------------------------------------------#
+# Globals
+ID_IDLE_TIMER = wx.NewId()
+SIMULATED_EVT_ID = -1
+_ = wx.GetTranslation
+
+#--------------------------------------------------------------------------#
+
+class EdPages(ed_book.EdBaseBook):
+ """Editra's editor buffer notebook
+ @todo: allow for tab styles to be configurable (maybe)
+
+ """
+ def __init__(self, parent):
+ """Initialize a notebook with a blank text control in it
+ @param parent: parent window of the notebook
+
+ """
+ style = aui.AUI_NB_DEFAULT_STYLE | \
+ aui.AUI_NB_WINDOWLIST_BUTTON | \
+ aui.AUI_NB_SMART_TABS | \
+ aui.AUI_NB_USE_IMAGES_DROPDOWN | \
+ aui.AUI_NB_TAB_EXTERNAL_MOVE | \
+ aui.AUI_NB_TAB_FIXED_WIDTH | \
+ aui.AUI_NB_ORDER_BY_ACCESS
+ super(EdPages, self).__init__(parent, style=style)
+
+ # Notebook attributes
+ self.LOG = wx.GetApp().GetLog()
+ self._idletimer = wx.Timer(self, ID_IDLE_TIMER)
+ self.DocMgr = ed_editv.EdEditorView.DOCMGR
+ self._searchctrl = ed_search.SearchController(self, self.GetCurrentCtrl)
+ self._searchctrl.SetLookinChoices(Profile_Get('SEARCH_LOC',
+ default=list()))
+ self._searchctrl.SetFileFilters(Profile_Get('SEARCH_FILTER', default=u''))
+
+ self.pg_num = -1 # Track new pages (aka untitled docs)
+ self.mdown = -1
+ self.control = None
+ self.frame = self.GetTopLevelParent() # MainWindow
+ self._ses_load = False
+ self._menu = ebmlib.ContextMenuManager()
+
+ # Setup Tab Navigator
+ ed_icon = ed_glob.CONFIG['SYSPIX_DIR'] + u"editra.png"
+ bmp = wx.Bitmap(ed_icon, wx.BITMAP_TYPE_PNG)
+ if bmp.IsOk():
+ self.SetNavigatorIcon(bmp)
+ else:
+ util.Log("[ed_pages][warn] Bad bitmap: %s" % ed_icon)
+
+ # Set custom options
+ self.SetMinMaxTabWidth(125, 135)
+
+ # Notebook Events
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+ self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CHANGING, self.OnPageChanging)
+ self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
+ self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnPageClosing)
+ self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSED, self.OnPageClosed)
+ self.Bind(aui.EVT_AUINOTEBOOK_TAB_DCLICK, self.OnTabLeftDClick)
+ self.Bind(aui.EVT_AUINOTEBOOK_BG_DCLICK, self.OnBGLeftDClick)
+ self.Bind(aui.EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, self.OnMClickDown)
+ self.Bind(aui.EVT_AUINOTEBOOK_TAB_MIDDLE_UP, self.OnMClickUp)
+ self.Bind(aui.EVT_AUINOTEBOOK_TAB_RIGHT_UP, self.OnTabMenu)
+ self.Bind(aui.EVT_AUINOTEBOOK_ALLOW_DND, self.OnAllowDnD)
+ self.Bind(aui.EVT_AUINOTEBOOK_END_DRAG, self.OnDragFinished)
+ self.Bind(aui.EVT_AUINOTEBOOK_DRAG_DONE, self.OnDragFinished)
+
+ self.Bind(wx.stc.EVT_STC_CHANGE, self.OnUpdatePageText)
+ self.Bind(wx.EVT_MENU, self.OnMenu)
+ self.Bind(wx.EVT_TIMER, self.OnIdle, id=ID_IDLE_TIMER)
+
+ # Message handlers
+ ed_msg.Subscribe(self.OnThemeChanged, ed_msg.EDMSG_THEME_CHANGED)
+ ed_msg.Subscribe(self.OnThemeChanged, ed_msg.EDMSG_THEME_NOTEBOOK)
+ ed_msg.Subscribe(self.OnUpdatePosCache, ed_msg.EDMSG_UI_STC_POS_JUMPED)
+ ed_msg.Subscribe(self.OnGetOpenFiles, ed_msg.EDMSG_FILE_GET_OPENED)
+ ed_msg.RegisterCallback(self.OnDocPointerRequest,
+ ed_msg.EDREQ_DOCPOINTER)
+
+ # Add a blank page
+ self.NewPage()
+ self._idletimer.Start(400)
+
+ #---- End Init ----#
+
+ #---- Implementation ----#
+
+ def OnDestroy(self, evt):
+ if self and evt.Id == self.Id:
+ ed_msg.Unsubscribe(self.OnThemeChanged)
+ ed_msg.Unsubscribe(self.OnUpdatePosCache)
+ ed_msg.Unsubscribe(self.OnGetOpenFiles)
+ ed_msg.UnRegisterCallback(self.OnDocPointerRequest)
+
+ def _HandleEncodingError(self, control):
+ """Handle trying to reload the file the file with a different encoding
+ Until it succeeds or gives up.
+ @param control: stc
+ @return: bool
+
+ """
+ # Loop while the load fails prompting to try a new encoding
+ tried = None
+ fname = control.GetFileName().strip(os.sep)
+ fname = fname.split(os.sep)[-1]
+ while True:
+ doc = control.GetDocument()
+ doc.ClearLastError()
+ if tried is None:
+ enc = doc.GetEncoding()
+ if enc is None:
+ enc = ed_txt.DEFAULT_ENCODING
+ else:
+ enc = tried
+
+ msg = _("The correct encoding of '%s' could not be determined.\n\n"
+ "Choose an encoding and select Ok to open the file with the chosen encoding.\n"
+ "Click Cancel to abort opening the file") % fname
+
+ # On some systems it seems that default encoding ends up being
+ # None so default to utf-8 for choices.
+ if enc is None:
+ enc = 'utf_8'
+
+ dlg = eclib.EncodingDialog(self, msg=msg,
+ title=_("Choose an Encoding"),
+ default=enc)
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DOCPROP),
+ wx.ART_OTHER)
+ if bmp.IsOk():
+ dlg.SetBitmap(bmp)
+ dlg.CenterOnParent()
+ result = dlg.ShowModal()
+ if dlg:
+ enc = dlg.GetEncoding()
+ dlg.Destroy()
+ else:
+ result = wx.ID_CANCEL
+
+ # Don't want to open it in another encoding
+ if result == wx.ID_CANCEL:
+ return False
+ else:
+ control.SetEncoding(enc)
+ tried = enc
+ ok = control.LoadFile(control.GetFileName())
+ if ok:
+ return True
+ else:
+ # Artificially add a short pause, because if its not there
+ # the dialog will be shown again so fast it wont seem
+ # like reloading the file was even tried.
+ wx.Sleep(1)
+
+ def _NeedOpen(self, path):
+ """Check if a file needs to be opened. If the file is already open in
+ the notebook a dialog will be opened to ask if the user wants to reopen
+ the file again. If the file is not open and exists or the user chooses
+ to reopen the file again the function will return True else it will
+ return False.
+ @param path: file to check for
+ @return: bool
+
+ """
+ result = wx.ID_YES
+ if self.HasFileOpen(path):
+ mdlg = wx.MessageDialog(self,
+ _("File is already open in an existing "
+ "page.\nDo you wish to open it again?"),
+ _("Open File") + u"?",
+ wx.YES_NO | wx.NO_DEFAULT | \
+ wx.ICON_INFORMATION)
+ result = mdlg.ShowModal()
+ mdlg.Destroy()
+ if result == wx.ID_NO:
+ self.GotoPage(path)
+ elif os.path.exists(path) and not os.path.isfile(path):
+ result = wx.ID_NO
+ else:
+ pass
+
+ return result == wx.ID_YES
+
+ def AddPage(self, page, text=u'', select=True, imgId=-1):
+ """Add a page to the notebook"""
+ bNewPage = False
+ if not len(text):
+ self.pg_num += 1
+ if self.pg_num != 0:
+ text = _("untitled %d") % self.pg_num
+ else:
+ text = _("untitled")
+ bNewPage = True
+ page.SetTabLabel(text)
+ bmp = wx.NullBitmap
+ if Profile_Get('TABICONS'):
+ bmp = page.GetTabImage()
+ super(EdPages, self).AddPage(page, text, select, bitmap=bmp)
+ self.UpdateIndexes()
+ if not self._ses_load and not bNewPage:
+ # Only auto save session when using default session
+ mgr = ed_session.EdSessionMgr()
+ if Profile_Get('LAST_SESSION') == mgr.DefaultSession:
+ self.SaveCurrentSession()
+
+ def DocDuplicated(self, path):
+ """Check for if the given path is open elsewhere and duplicate the
+ docpointer.
+ @param path: string
+
+ """
+ doc = ed_msg.RequestResult(ed_msg.EDREQ_DOCPOINTER, [self, path])
+ if hasattr(doc, 'GetDocPointer'):
+ self.OpenDocPointer(doc.GetDocPointer(), doc.GetDocument())
+ return True
+ else:
+ return False
+
+ def GetCurrentCtrl(self):
+ """Returns the control of the currently selected
+ page in the notebook.
+ @return: window object contained in current page or None
+
+ """
+ return self.control
+
+ def GetFileNames(self):
+ """Gets the name of all open files in the notebook
+ @return: list of file names
+
+ """
+ rlist = list()
+ for buff in self.GetTextControls():
+ fname = buff.GetFileName()
+ if fname != wx.EmptyString:
+ rlist.append(fname)
+ return rlist
+
+ def GetFindDialog(self):
+ """Get the active find dialog or None if one is not active
+ @return: FindDialog or None
+
+ """
+ return self._searchctrl.GetDialog()
+
+ def GetMenuHandlers(self):
+ """Get the (id, evt_handler) tuples that this window should
+ handle.
+ @return: list of tuples
+
+ """
+ rlist = [(ed_glob.ID_FIND, self._searchctrl.OnShowFindDlg),
+ (ed_glob.ID_FIND_REPLACE, self._searchctrl.OnShowFindDlg),
+ (ed_glob.ID_FIND_NEXT, self._searchctrl.OnFind),
+ (ed_glob.ID_FIND_PREVIOUS, self._searchctrl.OnFind),
+ (ed_glob.ID_FIND_SELECTED, self._searchctrl.OnFindSelected),
+ (ed_glob.ID_NEXT_POS, self.OnNavigateToPos),
+ (ed_glob.ID_PRE_POS, self.OnNavigateToPos)]
+
+ return rlist
+
+ def GetUiHandlers(self):
+ """Get the update ui handlers that this window supplies
+ @return: list of tuples
+
+ """
+ return [(ed_glob.ID_FIND_NEXT, self._searchctrl.OnUpdateFindUI),
+ (ed_glob.ID_FIND_PREVIOUS, self._searchctrl.OnUpdateFindUI),
+ (ed_glob.ID_NEXT_POS, self.OnUpdateNaviUI),
+ (ed_glob.ID_PRE_POS, self.OnUpdateNaviUI)]
+
+ def InsertPage(self, index, page, text, select=False,
+ bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap,
+ control=None):
+ """Insert a page into the notebook"""
+ super(EdPages, self).InsertPage(index, page, text, select,
+ bitmap, disabled_bitmap, control)
+ self.UpdateIndexes()
+
+ def SaveCurrentSession(self):
+ """Save the current session"""
+ if self._ses_load:
+ return
+
+ session = Profile_Get('LAST_SESSION')
+ # Compatibility with older session data
+ if not isinstance(session, basestring) or not len(session):
+ mgr = ed_session.EdSessionMgr()
+ session = mgr.DefaultSession
+ Profile_Set('LAST_SESSION', session)
+ self.SaveSessionFile(session)
+
+ def SaveSessionFile(self, session):
+ """Save the current open files to the given session file
+ @param session: path to session file
+ @return: tuple (error desc, error msg) or None
+
+ """
+ if self._ses_load:
+ return
+
+ try:
+ mgr = ed_session.EdSessionMgr()
+ flist = self.GetFileNames()
+ bSaved = mgr.SaveSession(session, flist)
+ except Exception, msg:
+ self.LOG("[ed_pages][err] SaveSession error %s" % msg)
+ return None
+
+ def LoadSessionFile(self, session):
+ """Load files from saved session data in profile
+ @param session: session filename
+ @return: tuple (error desc, error msg), or None if no error
+
+ """
+ self._ses_load = True
+
+ mgr = ed_session.EdSessionMgr()
+ flist = list()
+ try:
+ flist = mgr.LoadSession(session)
+ except Exception, msg:
+ self._ses_load = False
+ errdict = dict(sessionname=session, error=msg)
+ return (_("Session Load Error"),
+ _("Failed to load the session: %(sessionname)s\n\nError: %(error)s") % errdict)
+
+ if not len(flist):
+ self._ses_load = False
+ return (_("Empty File"), _("Session file is empty."))
+
+ # Close current files
+ self.CloseAllPages()
+
+ missingfns = []
+ for loadfn in flist:
+ if os.path.exists(loadfn) and os.access(loadfn, os.R_OK):
+ if not ebmlib.IsUnicode(loadfn):
+ try:
+ loadfn = loadfn.decode(sys.getfilesystemencoding())
+ except UnicodeDecodeError:
+ self.LOG("[ed_pages][err] LoadSessionFile: Failed to decode file name")
+ self.OpenPage(os.path.dirname(loadfn),
+ os.path.basename(loadfn))
+ else:
+ missingfns.append(loadfn)
+
+ if missingfns:
+ rmsg = (_("Missing session files"),
+ _("Some files in saved session could not be found on disk:\n")+
+ u'\n'.join(missingfns))
+ self._ses_load = False
+ return rmsg
+
+ self._ses_load = False
+
+ if self.GetPageCount() == 0:
+ self.NewPage()
+
+ self.Refresh()
+ return None
+
+ def NewPage(self):
+ """Create a new notebook page with a blank text control
+ @postcondition: a new page with an untitled document is opened
+
+ """
+ frame = self.TopLevelParent
+ with eclib.Freezer(frame) as _tmp:
+ self.control = ed_editv.EdEditorView(self)
+ self.LOG("[ed_pages][evt] New Page Created")
+ self.AddPage(self.control)
+
+ # Set the control up the the preferred default lexer
+ dlexer = Profile_Get('DEFAULT_LEX', 'str', synglob.LANG_TXT)
+ ext_reg = syntax.ExtensionRegister()
+ ext_lst = ext_reg.get(dlexer, ['txt', ])
+ self.control.FindLexer(ext_lst[0])
+ self.SetPageBitmap(self.GetSelection(), self.control.GetTabImage())
+
+ # Set the modified callback notifier
+ doc = self.control.GetDocument()
+ doc.AddModifiedCallback(self.control.FireModified)
+
+ def OnAllowDnD(self, evt):
+ """Handle allowing tab drag and drop events"""
+ dsource = evt.GetDragSource()
+ if isinstance(dsource, EdPages):
+ evt.Allow()
+ wx.CallAfter(self.UpdateIndexes)
+
+ def OnDragFinished(self, evt):
+ self.UpdateIndexes()
+ evt.Skip()
+
+ def OnMenu(self, evt):
+ """Handle context menu events
+ @param evt: wx.MenuEvent
+
+ """
+ ctab = self.GetCurrentPage()
+ handler = self._menu.GetHandler(evt.Id)
+ if handler is not None:
+ handler(ctab, evt)
+ elif ctab is not None:
+ ctab.OnTabMenu(evt)
+ else:
+ evt.Skip()
+
+ def OnDocPointerRequest(self, args):
+ """Get a buffer that has the same file open as the requested path.
+ @param args: [sender, path]
+ @return: EdEditorView reference or ed_msg.NullValue
+
+ """
+ sender, path = args
+ for buf in self.GetTextControls():
+ if buf.GetFileName() == path:
+ return buf
+ else:
+ return ed_msg.NullValue()
+
+ def OnTabLeftDClick(self, evt):
+ """Handle left double clicks and open new tab when in empty area.
+ @param evt: aui.EVT_AUINOTEBOOK_TAB_DCLICK
+
+ """
+ tlw = self.GetTopLevelParent()
+ if hasattr(tlw, 'OnMaximizeEditor'):
+ tlw.OnMaximizeEditor(None)
+
+ def OnBGLeftDClick(self, evt):
+ """Handle clicks on tab background area
+ @param evt: aui.EVT_AUINOTEBOOK_BG_DCLICK
+
+ """
+ self.NewPage()
+
+ def OnMClickDown(self, evt):
+ """Handle tab middle mouse button down click event
+ @param evt: aui.EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN
+
+ """
+ self.mdown = evt.Page
+ idx = self.GetPageIndex(self.mdown)
+ self.SetSelection(idx)
+ self.LOG("[ed_pages][evt] OnMClickDown: %d" % idx)
+
+ def OnMClickUp(self, evt):
+ """Handle tab middle click event
+ @param evt: aui.EVT_AUINOTEBOOK_TAB_MIDDLE_UP
+
+ """
+ sel = self.GetPageIndex(evt.Page)
+ self.LOG("[ed_pages][evt] OnMClickUp: %d" % sel)
+ if evt.Page is self.mdown:
+ self.ClosePage()
+ self.mdown = None
+
+ def OnNavigateToPos(self, evt):
+ """Handle buffer position history navigation events"""
+ e_id = evt.GetId()
+ fname, pos = (None, None)
+ cname = self.control.GetFileName()
+ cpos = self.control.GetCurrentPos()
+ if e_id == ed_glob.ID_NEXT_POS:
+ if self.DocMgr.CanNavigateNext():
+ fname, pos = self.DocMgr.GetNextNaviPos()
+ if (fname, pos) == (cname, cpos):
+ fname, pos = (None, None)
+ tmp = self.DocMgr.GetNextNaviPos()
+ if tmp is not None:
+ fname, pos = tmp
+ elif e_id == ed_glob.ID_PRE_POS:
+ if self.DocMgr.CanNavigatePrev():
+ fname, pos = self.DocMgr.GetPreviousNaviPos()
+ if (fname, pos) == (cname, cpos):
+ fname, pos = (None, None)
+ tmp = self.DocMgr.GetPreviousNaviPos()
+ if tmp is not None:
+ fname, pos = tmp
+ else:
+ evt.Skip()
+ return
+
+ ctrl = self.FindBuffer(fname)
+ if ctrl is None:
+ # Open the file in the editor
+ if fname is not None:
+ self.OpenPage(ebmlib.GetPathName(fname),
+ ebmlib.GetFileName(fname))
+ self.control.SetCaretPos(pos)
+ else:
+ # Raise page to top and goto position
+ pages = [self.GetPage(page) for page in range(self.GetPageCount())]
+ idx = pages.index(ctrl)
+ self.ChangePage(idx)
+ ctrl.SetCaretPos(pos)
+
+ def OnTabMenu(self, evt):
+ """Show the tab context menu"""
+ self._menu.Clear()
+
+ # Construct the menu
+ tab = self.GetPageIndex(evt.Page)
+ if tab != self.GetSelection():
+ self.SetSelection(tab)
+
+ ctab = self.GetCurrentPage()
+ if ctab is not None:
+ menu = ctab.GetTabMenu()
+ if menu is None:
+ return # Tab has no menu
+
+ self._menu.SetMenu(menu)
+ self._menu.SetUserData("page", ctab)
+
+ # Allow clients to customize the menu prior to showing it
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_TABMENU, self._menu)
+
+ # Show the menu
+ self.PopupMenu(self._menu.Menu)
+
+ def GetMainWindow(self):
+ return self.TopLevelParent
+
+ @ed_msg.mwcontext
+ def OnGetOpenFiles(self, msg):
+ """Report all opened files"""
+ if not self:
+ return
+
+ data = msg.GetData()
+ if not isinstance(data, list):
+ return
+ flist = self.GetFileNames()
+ data.extend(flist)
+
+ def OnThemeChanged(self, msg):
+ """Update icons when the theme has changed
+ @param msg: Message Object
+
+ """
+ self.UpdateAllImages()
+
+ def OnUpdatePosCache(self, msg):
+ """Update the position cache for buffer position changes
+ @param msg: message data
+
+ """
+ if not self or self._ses_load:
+ return
+
+ if self.TopLevelParent.Id == msg.GetContext():
+ data = msg.GetData()
+ self.DocMgr.AddNaviPosition(data['fname'], data['prepos'])
+ self.DocMgr.AddNaviPosition(data['fname'], data['pos'])
+
+ def OnUpdateNaviUI(self, evt):
+ """UpdateUI handler for position navigator"""
+ e_id = evt.Id
+ if e_id == ed_glob.ID_NEXT_POS:
+ evt.Enable(self.DocMgr.CanNavigateNext())
+ elif e_id == ed_glob.ID_PRE_POS:
+ evt.Enable(self.DocMgr.CanNavigatePrev())
+ else:
+ evt.Skip()
+
+ def OpenDocPointer(self, ptr, doc, title=u''):
+ """Open a page using an stc document poiner
+ @param ptr: EdEditorView document Pointer
+ @param doc: EdFile instance
+ @keyword title: tab title
+
+ """
+ with eclib.Freezer(self.TopLevelParent) as _tmp:
+ nbuff = self.GetCurrentPage()
+ need_add = False
+ if nbuff.GetFileName() or nbuff.GetLength():
+ need_add = True
+ nbuff = ed_editv.EdEditorView(self)
+
+ nbuff.SetDocPointer(ptr)
+ nbuff.SetDocument(doc)
+ doc.AddModifiedCallback(nbuff.FireModified)
+ nbuff.FindLexer()
+
+ path = nbuff.GetFileName()
+ if Profile_Get('SAVE_POS'):
+ pos = self.DocMgr.GetPos(path)
+ nbuff.SetCaretPos(pos)
+ nbuff.ScrollToColumn(0)
+
+ if title:
+ filename = title
+ else:
+ filename = ebmlib.GetFileName(path)
+
+ if need_add:
+ self.AddPage(nbuff, filename)
+ else:
+ self.SetPageText(self.GetSelection(), filename)
+
+ self.LOG("[ed_pages][evt] Opened Page: %s" % filename)
+
+ # Set tab image
+ self.SetPageBitmap(self.GetSelection(), nbuff.GetTabImage())
+
+ # Refocus on selected page
+ self.control = nbuff
+ self.GoCurrentPage()
+ ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENED,
+ nbuff.GetFileName(),
+ context=self.frame.Id)
+
+ def OpenFileObject(self, fileobj):
+ """Open a new text editor page with the given file object. The file
+ object must be an instance of ed_txt.EdFile.
+ @param fileobj: File Object
+
+ """
+ # Create the control
+ with eclib.Freezer(self.TopLevelParent) as _tmp:
+ control = ed_editv.EdEditorView(self)
+ control.Hide()
+
+ # Load the files data
+ path = fileobj.GetPath()
+ filename = ebmlib.GetFileName(path)
+ control.SetDocument(fileobj)
+ result = control.ReloadFile()
+
+ # Setup the buffer
+ fileobj.AddModifiedCallback(control.FireModified)
+
+ # Setup the notebook
+ self.control = control
+ self.control.FindLexer()
+ self.control.EmptyUndoBuffer()
+ self.control.Show()
+ self.AddPage(self.control, filename)
+
+ self.frame.AddFileToHistory(path)
+ self.SetPageText(self.GetSelection(), filename)
+ self.LOG("[ed_pages][evt] Opened Page: %s" % filename)
+
+ # Set tab image
+ cpage = self.GetSelection()
+ self.SetPageBitmap(cpage, self.control.GetTabImage())
+
+ # Refocus on selected page
+ self.GoCurrentPage()
+ ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENED,
+ self.control.GetFileName(),
+ context=self.frame.Id)
+
+ if Profile_Get('WARN_EOL', default=True) and not fileobj.IsRawBytes():
+ self.control.CheckEOL()
+
+ def OpenPage(self, path, filename, quiet=False):
+ """Open a File Inside of a New Page
+ @param path: files base path
+ @param filename: name of file to open
+ @keyword quiet: Open/Switch to the file quietly if
+ it is already open.
+
+ """
+ path2file = os.path.join(path, filename)
+
+ # Resolve links to real file
+ if ebmlib.IsLink(path2file):
+ path2file = ebmlib.ResolveRealPath(path2file)
+ path = ebmlib.GetPathName(path2file)
+ filename = ebmlib.GetFileName(path2file)
+
+ if self.DocDuplicated(path2file):
+ return
+
+ # Check if file needs to be opened
+ # TODO: these steps could be combined together with some
+ # refactoring of the _NeedOpen method. Requires extra
+ # testing though to check for dependencies on current
+ # behavior.
+ if quiet and self.HasFileOpen(path2file):
+ self.GotoPage(path2file)
+ return
+ elif not self._NeedOpen(path2file):
+ return
+
+ # Create new control to place text on if necessary
+ with eclib.Freezer(self.TopLevelParent) as _tmp:
+ new_pg = True
+ if self.GetPageCount():
+ if self.control.GetModify() or self.control.GetLength() or \
+ self.control.GetFileName() != u'':
+ control = ed_editv.EdEditorView(self, wx.ID_ANY)
+ control.Hide()
+ else:
+ new_pg = False
+ control = self.control
+ else:
+ control = ed_editv.EdEditorView(self, wx.ID_ANY)
+ control.Hide()
+
+ # Open file and get contents
+ result = False
+ if os.path.exists(path2file):
+ try:
+ result = control.LoadFile(path2file)
+ except Exception, msg:
+ self.LOG("[ed_pages][err] Failed to open file %s\n" % path2file)
+ self.LOG("[ed_pages][err] %s" % msg)
+
+ # File could not be opened/read give up
+ # Don't raise a dialog during a session load error as if the
+ # dialog is shown before the mainwindow is ready it can cause
+ # the app to freeze.
+ if not self._ses_load:
+ ed_mdlg.OpenErrorDlg(self, path2file, msg)
+ control.GetDocument().ClearLastError()
+ control.SetFileName('') # Reset the file name
+
+ if new_pg:
+ control.Destroy()
+
+ return
+ else:
+ control.SetFileName(path2file)
+ result = True
+
+ # Check if there was encoding errors
+ if not result and not self._ses_load:
+ result = self._HandleEncodingError(control)
+
+ # Cleanup after errors
+ if not result:
+ if new_pg:
+ # We created a new one so destroy it
+ control.Destroy()
+ else:
+ # We where using an existing buffer so reset it
+ control.SetText('')
+ control.SetDocument(ed_txt.EdFile())
+ control.SetSavePoint()
+
+ return
+
+ # Put control into page an place page in notebook
+ if new_pg:
+ control.Show()
+ self.control = control
+
+ # Setup Document
+ self.control.FindLexer()
+ self.control.EmptyUndoBuffer()
+ doc = self.control.GetDocument()
+ doc.AddModifiedCallback(self.control.FireModified)
+
+ # Add the buffer to the notebook
+ if new_pg:
+ self.AddPage(self.control, filename)
+ else:
+ self.frame.SetTitle(self.control.GetTitleString())
+
+ self.frame.AddFileToHistory(path2file)
+ self.SetPageText(self.GetSelection(), filename)
+
+ # Set tab image
+ cpage = self.GetSelection()
+ self.SetPageBitmap(cpage, self.control.GetTabImage())
+
+ if Profile_Get('WARN_EOL', default=True) and not doc.IsRawBytes():
+ self.control.CheckEOL()
+
+ if not control.IsLoading():
+ self.DoPostLoad()
+
+ # Refocus on selected page
+ self.GoCurrentPage()
+ self.LOG("[ed_pages][evt] Opened Page: %s" % filename)
+
+ def DoPostLoad(self):
+ """Perform post file open actions"""
+ # Ensure that document buffer is writable after an editable
+ # document is opened in the buffer.
+ doc = self.control.GetDocument()
+ if not doc.IsReadOnly() and not doc.IsRawBytes():
+ self.control.SetReadOnly(False)
+
+ # Set last known caret position if the user setting is enabled
+ # and the caret position has not been changed during a threaded
+ # file loading operation.
+ if Profile_Get('SAVE_POS') and self.control.GetCurrentPos() <= 0:
+ pos = self.DocMgr.GetPos(self.control.GetFileName())
+ self.control.SetCaretPos(pos)
+ self.control.ScrollToColumn(0)
+
+ ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENED,
+ self.control.GetFileName(),
+ context=self.frame.Id)
+
+ def GoCurrentPage(self):
+ """Move Focus to Currently Selected Page.
+ @postcondition: focus is set to current page
+
+ """
+ current_page = self.GetSelection()
+ if current_page >= 0:
+ control = self.GetPage(current_page)
+ self.control = control
+ return current_page
+
+ def GotoPage(self, fname):
+ """Go to the page containing the buffer with the given file.
+ @param fname: file path (string)
+
+ """
+ for page in xrange(self.GetPageCount()):
+ ctrl = self.GetPage(page)
+ if fname == ctrl.GetFileName():
+ self.ChangePage(page)
+ break
+
+ def GetPageText(self, pg_num):
+ """Gets the tab text from the given page number, stripping
+ the * mark if there is one.
+ @param pg_num: index of page to get tab text from
+ @return: the tabs text
+
+ """
+ # Used to be needed with flatnotebook under certain cases
+ # TODO: may not be necessary anymore
+ try:
+ txt = super(EdPages, self).GetPageText(pg_num)
+ except Exception:
+ txt = ''
+
+ if not txt or txt[0] != u"*":
+ return txt
+ return txt[1:]
+
+ def GetRawPageText(self, pg_num):
+ """Get the unformatted raw page text
+ @param pg_num: int
+ @return: string
+
+ """
+ try:
+ txt = super(EdPages, self).GetPageText(pg_num)
+ except Exception:
+ txt = ''
+ return txt
+
+ def ImageIsReadOnly(self, index):
+ """Does the given page currently have a ReadOnly Image
+ shown on it?
+ @return: bool
+
+ """
+ bReadOnly = False
+ try:
+ if index < self.GetPageCount():
+ bReadOnly = self.GetPageImage(index) == self._index[ed_glob.ID_READONLY]
+ else:
+ self.LOG("[ed_pages][warn] ImageIsReadOnly: Bad index: %d" % index)
+ except Exception, msg:
+ # TODO: investigate possible upstream issue
+ self.LOG("[ed_pages][err] ImageIsReadOnly: %s" % msg)
+ return bReadOnly
+
+ def SetPageText(self, pg_num, txt):
+ """Set the pages tab text
+ @param pg_num: page index
+ @param txt: string
+
+ """
+ super(EdPages, self).SetPageText(pg_num, txt)
+ page = self.GetPage(pg_num)
+ page.SetTabLabel(txt)
+
+ def GetTextControls(self):
+ """Gets all the currently opened text controls
+ @return: list containing reference to all stc controls opened in the
+ notebook.
+
+ """
+ pages = [self.GetPage(page) for page in xrange(self.GetPageCount())]
+ return [page for page in pages if page.GetName() == "EditraTextCtrl"]
+
+ def HasFileOpen(self, fpath):
+ """Checks if one of the currently active buffers has
+ the named file in it.
+ @param fpath: full path of file to check
+ @return: bool indicating whether file is currently open or not
+
+ """
+ for ctrl in self.GetTextControls():
+ if fpath == ctrl.GetFileName():
+ return True
+ return False
+
+ def FindBuffer(self, fpath):
+ """Find the buffer containing the given file
+ @param fpath: full path of file to look for
+ @return: EdStc or None
+ @todo: handle matching based on the buffer control itself
+
+ """
+ for ctrl in self.GetTextControls():
+ if fpath == ctrl.GetFileName():
+ return ctrl
+ return None
+
+ #---- Event Handlers ----#
+ def OnDrop(self, files):
+ """Opens dropped files
+ @param files: list of file paths
+ @postcondition: all files that could be properly opend are added to
+ the notebook
+
+ """
+ # Check file properties and make a "clean" list of file(s) to open
+ valid_files = list()
+ for fname in files:
+ self.LOG("[ed_pages][evt] File(s) Dropped: %s" % fname)
+ if not os.path.exists(fname):
+ self.frame.PushStatusText(_("Invalid file: %s") % fname, \
+ ed_glob.SB_INFO)
+ elif os.path.isdir(fname):
+ dcnt = glob.glob(os.path.join(fname, '*'))
+ dcnt = util.FilterFiles(dcnt)
+ dlg = None
+ if not len(dcnt):
+ dlg = wx.MessageDialog(self,
+ _("There are no files that Editra"
+ " can open in %s") % fname,
+ _("No Valid Files to Open"),
+ style=wx.OK | wx.CENTER | \
+ wx.ICON_INFORMATION)
+ elif len(dcnt) > 5:
+ # Warn when the folder contains many files
+ dlg = wx.MessageDialog(self,
+ _("Do you wish to open all %d files"
+ " in this directory?\n\nWarning:"
+ " opening many files at once may"
+ " cause the editor to temporarily "
+ " freeze.") % len(dcnt),
+ _("Open Directory?"),
+ style=wx.YES | wx.NO | \
+ wx.ICON_INFORMATION)
+ if dlg is not None:
+ result = dlg.ShowModal()
+ dlg.Destroy()
+ else:
+ result = wx.ID_YES
+
+ if result == wx.ID_YES:
+ valid_files.extend(dcnt)
+ else:
+ pass
+ else:
+ valid_files.append(fname)
+
+ for fname in valid_files:
+ pathname = ebmlib.GetPathName(fname)
+ the_file = ebmlib.GetFileName(fname)
+ self.OpenPage(pathname, the_file)
+ self.frame.PushStatusText(_("Opened file: %s") % fname, \
+ ed_glob.SB_INFO)
+ return
+
+ def OnIdle(self, evt):
+ """Update tabs and check if files have been modified
+ @param evt: wx.TimerEvent
+
+ """
+ if wx.GetApp().IsActive():
+ for idx in range(self.GetPageCount()):
+ page = self.GetPage(idx)
+ if page is not None and page.IsShown():
+ page.DoOnIdle()
+
+ def OnPageChanging(self, evt):
+ """Page changing event handler.
+ @param evt: aui.EVT_AUINOTEBOOK_PAGE_CHANGING
+
+ """
+ evt.Skip()
+ pages = (evt.GetOldSelection(), evt.GetSelection())
+ self.LOG("[ed_pages][evt] Control Changing from Page: "
+ "%d to Page: %d\n" % pages)
+
+ # Check if it has been destroyed already
+ if self.control:
+ self.control.DoDeactivateTab()
+
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGING,
+ (self,) + pages,
+ context=self.frame.Id)
+
+ def ChangePage(self, pg_num, old=-2):
+ """Change the page and focus to the the given page id
+ @param pg_num: Page number to change
+ @keyword old: previous selection
+
+ """
+ cpage = self.GetSelection()
+ if cpage != pg_num:
+ self.SetSelection(pg_num)
+
+ # Get the window that is the current page
+ window = self.GetPage(pg_num)
+ self.control = window
+
+ # Update Frame Title
+ self.frame.SetTitle(self.control.GetTitleString())
+
+ # Only post page changes when the change is not from the app exiting
+ # NOTE: -2 is used as default value, cant use -1 as it comes from
+ # page close events.
+ if old > -2:
+ cpage = old
+
+ if not self.frame.IsExiting() and cpage != pg_num:
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGED,
+ (self, pg_num),
+ context=self.frame.Id)
+
+ def OnPageChanged(self, evt):
+ """Actions to do after a page change
+ @param evt: aui.EVT_AUINOTEBOOK_PAGE_CHANGED
+
+ """
+ cpage = evt.GetSelection()
+ self.ChangePage(cpage, old=evt.GetOldSelection())
+ self.LOG("[ed_pages][evt] Page Changed to %d" % cpage)
+
+ # Call the tab specific selection handler
+ page = self.GetCurrentPage()
+ if page:
+ page.DoTabSelected()
+ self.GoCurrentPage()
+
+ def OnPageClosing(self, evt):
+ """Checks page status to flag warnings before closing
+ @param evt: aui.EVT_AUINOTEBOOK_PAGE_CLOSE
+
+ """
+ page = self.GetPage(evt.GetSelection())
+ if page and page.CanCloseTab():
+ sel = self.GetSelection()
+ self.LOG("[ed_pages][evt] Closing Page: #%d" % sel)
+
+ # Call the tab specific close handler
+ page.DoTabClosing()
+
+ evt.Skip()
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CLOSING,
+ (self, sel),
+ context=self.frame.Id)
+ else:
+ evt.Veto()
+
+ def OnPageClosed(self, evt):
+ """Handles Paged Closed Event
+ @param evt: aui.EVT_AUINOTEBOOK_PAGE_CLOSED
+
+ """
+ frame = self.TopLevelParent
+ with eclib.Freezer(frame) as _tmp:
+ cpage = evt.GetSelection()
+ evt.Skip()
+ self.LOG("[ed_pages][evt] Closed Page: #%d" % cpage)
+ self.UpdateIndexes()
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CLOSED,
+ (self, cpage),
+ context=self.frame.Id)
+
+ if not self.GetPageCount() and \
+ hasattr(frame, 'IsExiting') and not frame.IsExiting():
+ self.NewPage()
+ elif not self.frame.IsExiting():
+ self.SaveCurrentSession()
+
+ #---- End Event Handlers ----#
+
+ def _ClosePageNum(self, idx, deletepg=True):
+ """Close the given page
+ @param idx: int
+ @keyword deletepg: bool (Internal Use Only!)
+ @return bool: was page deleted?
+
+ """
+ result = True
+ try:
+ page = self.GetPage(idx)
+ result = page.CanCloseTab()
+
+ # TODO: this makes very little sense, why did this deletepg
+ # value get added, this function is useless when it
+ # is not true...
+ if result and deletepg:
+ evt = aui.AuiNotebookEvent(aui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE,
+ SIMULATED_EVT_ID)
+ evt.SetSelection(idx)
+ self.OnPageClosing(evt)
+ with eclib.Freezer(self.TopLevelParent) as _tmp:
+ self.DeletePage(idx)
+ evt = aui.AuiNotebookEvent(aui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED,
+ SIMULATED_EVT_ID)
+ evt.SetSelection(idx)
+ self.OnPageClosed(evt)
+ except Exception:
+ # TODO: workaround for crash in base on destruction
+ pass
+
+ return result
+
+ def CloseAllPages(self):
+ """Closes all open pages"""
+ for page in range(self.GetPageCount()):
+ if not self.ClosePage():
+ break
+
+ def CloseOtherPages(self):
+ """Close all but the currently selected tab"""
+ cpage = self.GetCurrentPage()
+ to_del = list()
+ for pnum in range(self.GetPageCount()):
+ page = self.GetPage(pnum)
+ if not page:
+ break
+ if not (page == cpage):
+ if page.CanCloseTab():
+ to_del.append(pnum)
+
+ if len(to_del):
+ to_del.sort()
+ to_del.reverse()
+ for pnum in to_del:
+ self._ClosePageNum(pnum)
+
+ def ClosePage(self, deletepg=True):
+ """Closes currently selected page
+ @keyword deletepg: bool (actually delete the page) internal use only
+ @return: bool
+
+ """
+ pnum = self.GetSelection()
+ result = self._ClosePageNum(pnum, deletepg)
+ return result
+
+ def CanClosePage(self):
+ """Can the current page be closed?
+ @return: bool
+
+ """
+ self.GoCurrentPage()
+ page = self.GetCurrentPage()
+ if page:
+ return page.CanCloseTab()
+ return False
+
+ def UpdateAllImages(self):
+ """Reload and Reset all images in the notebook pages and
+ the corresponding imagelist to match those of the current theme
+ @postcondition: all images in control are updated
+
+ """
+ bUseIcons = Profile_Get('TABICONS')
+ for page in range(self.GetPageCount()):
+ if bUseIcons:
+ tab = self.GetPage(page)
+ self.SetPageBitmap(page, tab.GetTabImage())
+ else:
+ self.SetPageBitmap(page, wx.NullBitmap)
+ self.Refresh()
+
+ def UpdateIndexes(self):
+ """Update all page indexes"""
+ pages = [self.GetPage(page) for page in range(self.GetPageCount())]
+ for idx, page in enumerate(pages):
+ page.SetTabIndex(idx)
+
+ def UpdatePageImage(self):
+ """Updates the page tab image
+ @postcondition: page image is updated to reflect any changes in ctrl
+
+ """
+ tab = self.GetCurrentPage()
+ self.SetPageBitmap(self.GetSelection(), tab.GetTabImage())
+
+ def OnUpdatePageText(self, evt):
+ """Update the title text of the current page
+ @param evt: stc.EVT_STC_MODIFY (unused)
+ @note: this method must complete its work very fast it gets
+ called every time a character is entered or removed from
+ the document.
+
+ """
+ try:
+ if self.control.Id == evt.Id:
+ # Wait till file is completely loaded before updating ui based
+ # on modification events.
+ if self.control.IsLoading():
+ return
+
+ pg_num = self.GetSelection()
+ title = self.GetPageText(pg_num)
+ if self.control.GetModify():
+ title = u"*" + title
+
+ # Only Update if the text has changed
+ if title != super(EdPages, self).GetPageText(pg_num):
+ self.SetPageText(pg_num, title)
+ ftitle = self.control.GetTitleString()
+ self.frame.SetTitle(ftitle)
+ else:
+ # A background page has changed
+ for page in range(self.GetPageCount()):
+ control = self.GetPage(page)
+ if control.Id == evt.Id:
+ title = self.GetPageText(page)
+ if control.GetModify():
+ title = u"*" + title
+ if title != super(EdPages, self).GetPageText(page):
+ self.SetPageText(page, title)
+ except wx.PyDeadObjectError:
+ pass
+
+ def UpdateTextControls(self):
+ """Updates all text controls to use any new settings that have
+ been changed since initialization.
+ @postcondition: all stc controls in the notebook are reconfigured
+ to match profile settings
+
+ """
+ for control in self.GetTextControls():
+ control.UpdateAllStyles()
+ control.Configure()
+
+#---- End Function Definitions ----#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_print.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_print.py
new file mode 100644
index 0000000..701f6c2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_print.py
@@ -0,0 +1,163 @@
+###############################################################################
+# Name: ed_print.py #
+# Purpose: Editra's printer class #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Printer class for creating and managing printouts from a StyledTextCtrl.
+
+Classes:
+ - L{EdPrinter}: Class for managing printing and providing print dialogs
+ - L{EdPrintout}: Scales and renders the given document to a printer.
+
+@summary: Printer Classes for printing text from an STC
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: ed_print.py 67499 2011-04-15 20:33:40Z CJP $"
+__revision__ = "$Revision: 67499 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc
+
+# Editra Imports
+import ed_glob
+import util
+import extern.stcprint as stcprint
+
+_ = wx.GetTranslation
+#--------------------------------------------------------------------------#
+
+# Globals
+COLOURMODES = { ed_glob.PRINT_BLACK_WHITE : wx.stc.STC_PRINT_BLACKONWHITE,
+ ed_glob.PRINT_COLOR_WHITE : wx.stc.STC_PRINT_COLOURONWHITE,
+ ed_glob.PRINT_COLOR_DEF : wx.stc.STC_PRINT_COLOURONWHITEDEFAULTBG,
+ ed_glob.PRINT_INVERT : wx.stc.STC_PRINT_INVERTLIGHT,
+ ed_glob.PRINT_NORMAL : wx.stc.STC_PRINT_NORMAL }
+
+#--------------------------------------------------------------------------#
+class EdPrinter(object):
+ """Printer Class for the editor
+ @note: current font size is fixed at 12 point for printing
+
+ """
+ def __init__(self, parent, mode=ed_glob.PRINT_NORMAL):
+ """Initializes the Printer
+ @param parent: parent window
+ @keyword mode: printer mode
+
+ """
+ super(EdPrinter, self).__init__()
+
+ # Attributes
+ self.stc = None
+ self.title = wx.EmptyString
+ self.parent = parent
+ self.print_mode = mode
+ self.print_data = wx.PrintData()
+ self.margins = (wx.Point(15,15), wx.Point(15,15))
+
+ def CreatePrintout(self):
+ """Creates a printout of the current stc window
+ @return: a printout object
+
+ """
+ colour = COLOURMODES[self.print_mode]
+ dlg_data = wx.PageSetupDialogData(self.print_data)
+ dlg_data.SetPrintData(self.print_data)
+ dlg_data.SetMarginTopLeft(self.margins[0])
+ dlg_data.SetMarginBottomRight(self.margins[1])
+ fname = self.stc.GetFileName()
+ printout = stcprint.STCPrintout(self.stc, page_setup_data=dlg_data,
+ print_mode=colour, title=self.title,
+ job_title=fname)
+ return printout
+
+ def PageSetup(self):
+ """Opens a print setup dialog and save print settings.
+ @return: None
+
+ """
+ dlg_data = wx.PageSetupDialogData(self.print_data)
+ dlg_data.SetPrintData(self.print_data)
+
+ dlg_data.SetDefaultMinMargins(True)
+ dlg_data.SetMarginTopLeft(self.margins[0])
+ dlg_data.SetMarginBottomRight(self.margins[1])
+
+ print_dlg = wx.PageSetupDialog(self.parent, dlg_data)
+ if print_dlg.ShowModal() == wx.ID_OK:
+ self.print_data = wx.PrintData(dlg_data.GetPrintData())
+ self.print_data.SetPaperId(dlg_data.GetPaperId())
+ self.margins = (dlg_data.GetMarginTopLeft(),
+ dlg_data.GetMarginBottomRight())
+ print_dlg.Destroy()
+
+ def Preview(self):
+ """Preview the Print
+ @return: None
+
+ """
+ printout = self.CreatePrintout()
+ printout2 = self.CreatePrintout()
+ preview = wx.PrintPreview(printout, printout2, self.print_data)
+ preview.SetZoom(150)
+ if preview.IsOk():
+ pre_frame = wx.PreviewFrame(preview, self.parent,
+ _("Print Preview"))
+ dsize = wx.GetDisplaySize()
+ pre_frame.SetInitialSize((self.stc.GetSize()[0],
+ dsize.GetHeight() - 100))
+ pre_frame.Initialize()
+ pre_frame.Show()
+ else:
+ wx.MessageBox(_("Failed to create print preview"),
+ _("Print Error"),
+ style=wx.ICON_ERROR|wx.OK)
+
+ def Print(self):
+ """Prints the document
+ @postcondition: the current document is printed
+
+ """
+ pdd = wx.PrintDialogData(self.print_data)
+ printer = wx.Printer(pdd)
+ printout = self.CreatePrintout()
+ result = printer.Print(self.parent, printout)
+ if result:
+ dlg_data = printer.GetPrintDialogData()
+ self.print_data = wx.PrintData(dlg_data.GetPrintData())
+ elif printer.GetLastError() == wx.PRINTER_ERROR:
+ wx.MessageBox(_("There was an error when printing.\n"
+ "Check that your printer is properly connected."),
+ _("Printer Error"),
+ style=wx.ICON_ERROR|wx.OK)
+ printout.Destroy()
+
+ def SetColourMode(self, mode):
+ """Sets the color mode that the text is to be rendered with
+ @param mode: mode to set the printer to use
+ @return: whether mode was set or not
+ @rtype: boolean
+
+ """
+ if mode in COLOURMODES:
+ self.print_mode = mode
+ ret = True
+ else:
+ ret = False
+ return ret
+
+ def SetStc(self, stc):
+ """Set the stc we are printing for
+ @param stc: instance of wx.stc.StyledTextCtrl
+ @note: MUST be called prior to any other print operations
+
+ """
+ self.stc = stc
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_search.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_search.py
new file mode 100644
index 0000000..b076022
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_search.py
@@ -0,0 +1,1550 @@
+###############################################################################
+# Name: ed_search.py #
+# Purpose: Text searching services and utilities #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007,2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""@package Editra.src.ed_search
+
+Provides text searching services, utilities, and ui components for searching
+text documents and files.
+
+@summary: Text searching and results presentation ui
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_search.py 71673 2012-06-06 20:12:42Z CJP $"
+__revision__ = "$Revision: 71673 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import sys
+import re
+import unicodedata
+import wx
+
+# Local imports
+import ed_glob
+import ed_txt
+import ed_msg
+import plugin
+import iface
+from profiler import Profile_Get, Profile_Set
+import eclib
+import ebmlib
+import ed_basewin
+import ed_thread
+
+#--------------------------------------------------------------------------#
+# Globals
+
+_ = wx.GetTranslation
+#--------------------------------------------------------------------------#
+
+class EdSearchEngine(ebmlib.SearchEngine):
+ """Text searching engine"""
+ def __init__(self, query, regex=True, down=True,
+ matchcase=True, wholeword=False):
+ super(EdSearchEngine, self).__init__(query, regex, down,
+ matchcase, wholeword)
+ # Attributes
+ self._offset = 0
+
+ def FormatResult(self, fname, lnum, match):
+ """Format the search result string for find all action that is performed
+ on a selection.
+ @return: string
+ @todo: better unicode handling
+
+ """
+ fname = ed_txt.DecodeString(fname, sys.getfilesystemencoding())
+ if not ebmlib.IsUnicode(fname):
+ fname = _("DECODING ERROR")
+
+ match = ed_txt.DecodeString(match)
+ if not ebmlib.IsUnicode(match):
+ match = _("DECODING ERROR")
+ else:
+ match = u" " + match.lstrip()
+
+ rstring = u"%(fname)s (%(lnum)d): %(match)s"
+ lnum = lnum + self._offset + 1
+ return rstring % dict(fname=fname, lnum=lnum, match=match)
+
+ def SetOffset(self, offset):
+ """Set the offset for a search in selection action
+ @param offset: int
+
+ """
+ self._offset = offset
+
+ def SetQuery(self, query):
+ """Set the query string"""
+ if not ebmlib.IsUnicode(query):
+ query = query.decode('utf-8')
+ query = unicodedata.normalize('NFC', query)
+ super(EdSearchEngine, self).SetQuery(query)
+
+ def SetSearchPool(self, pool):
+ """Set the search pool"""
+ if not ebmlib.IsUnicode(pool):
+ pool = pool.decode('utf-8')
+ pool = unicodedata.normalize('NFC', pool)
+ super(EdSearchEngine, self).SetSearchPool(pool)
+
+#--------------------------------------------------------------------------#
+
+class SearchController(object):
+ """Controls the interface to the text search engine"""
+ def __init__(self, owner, getstc):
+ """Create the controller
+ @param owner: View that owns this controller
+ @param getstc: Callable to get the current buffer with
+
+ """
+ super(SearchController, self).__init__()
+
+ # Attributes
+ self._parent = owner
+ self._stc = getstc
+ self._finddlg = None
+ self._posinfo = dict(scroll=0, start=0, found=-1, ldir=None)
+ self._data = self._InitFindData()
+ self._li_choices = list()
+ self._li_sel = 0
+ self._filters = None
+ self._clients = list()
+ self._engine = EdSearchEngine(u"") # For incremental searches
+
+ # Setup
+ self._engine.SetResultFormatter(self._engine.FormatResult)
+
+ # Event handlers
+ self._parent.Bind(eclib.EVT_FIND, self.OnFind)
+ self._parent.Bind(eclib.EVT_FIND_NEXT, self.OnFind)
+ self._parent.Bind(eclib.EVT_FIND_ALL, self.OnFindAll)
+ self._parent.Bind(eclib.EVT_COUNT, self.OnCount)
+ self._parent.Bind(eclib.EVT_REPLACE, self.OnReplace)
+ self._parent.Bind(eclib.EVT_REPLACE_ALL, self.OnReplaceAll)
+ self._parent.Bind(eclib.EVT_FIND_CLOSE, self.OnFindClose)
+ self._parent.Bind(eclib.EVT_OPTION_CHANGED, self.OnOptionChanged)
+
+ # Editra message handlers
+ ed_msg.Subscribe(self._OnShowFindMsg, ed_msg.EDMSG_FIND_SHOW_DLG)
+
+ def __del__(self):
+ """Cleanup message handlers"""
+ ed_msg.Unsubscribe(self._OnShowFindMsg)
+ if self._finddlg:
+ self._finddlg.Destroy()
+
+ def _CreateNewDialog(self, e_id):
+ """Create and set the controllers find dialog
+ @param e_id: Dialog Type Id
+
+ """
+ # TODO: find out why parent is not a Window in some cases...
+ if not isinstance(self._parent, wx.Window):
+ parent = wx.GetApp().GetActiveWindow()
+ self._parent = parent
+ else:
+ parent = self._parent
+
+ labels = (_("Find"), _("Find/Replace"))
+ if e_id == ed_glob.ID_FIND_REPLACE:
+ dlg = eclib.AdvFindReplaceDlg(parent, self._data, labels,
+ eclib.AFR_STYLE_REPLACEDIALOG)
+ elif e_id == ed_glob.ID_FIND:
+ dlg = eclib.AdvFindReplaceDlg(parent, self._data, labels)
+ else:
+ dlg = None
+
+ # Change the icons to use ones from Editra's ArtProvider
+ # Customize current context / state
+ if dlg is not None:
+ find = wx.ArtProvider.GetBitmap(str(ed_glob.ID_FIND), wx.ART_MENU)
+ replace = wx.ArtProvider.GetBitmap(str(ed_glob.ID_FIND_REPLACE),
+ wx.ART_MENU)
+ if find is not None and find.IsOk():
+ dlg.SetFindBitmap(find)
+
+ if replace is not None and replace.IsOk():
+ dlg.SetReplaceBitmap(replace)
+
+ # Set the persisted data from the last time the dialog was shown
+ def GetCurrentDir():
+ """Get current directory for dialog context
+ @return: unicode
+
+ """
+ fname = u""
+ if self:
+ cbuff = self._stc()
+ fname = getattr(cbuff, 'GetFileName', lambda: u"")()
+ return os.path.dirname(fname)
+
+ dlg.SetDirectoryGetter(GetCurrentDir)
+ dlg.SetLookinChoices(self._li_choices)
+ dlg.SetLookinSelection(self._li_sel)
+ dlg.SetFileFilters(self._filters)
+
+ return dlg
+
+ def _OnShowFindMsg(self, msg):
+ """Message handler for clients to request and setup the find dialog
+ with.
+ @param msg: dict(mainw, lookin, findtxt)
+
+ """
+ data = msg.GetData()
+ if data.get('mainw', None) == self._parent.TopLevelParent:
+
+ if 'findtxt' in data:
+ self.SetQueryString(data.get('findtxt'))
+ else:
+ query = self.GetClientString()
+ if len(query):
+ self.SetQueryString(query)
+
+ # Dialog is not currently open
+ if self._finddlg is None:
+ self._finddlg = self._CreateNewDialog(ed_glob.ID_FIND)
+ if self._finddlg is None:
+ return
+ self._finddlg.CenterOnParent()
+ self._finddlg.SetTransparent(240)
+ # self._finddlg.SetExtraStyle(wx.WS_EX_PROCESS_UI_UPDATES)
+ else:
+ # Dialog has been created already so just update it
+ self._UpdateDialogState(ed_glob.ID_FIND)
+
+ if 'lookin' in data:
+ self._finddlg.SetLookinPath(data.get('lookin'))
+
+ self._finddlg.Show()
+ self._finddlg.Raise()
+ self._finddlg.SetFocus()
+ else:
+ return
+
+ def _UpdateDialogState(self, e_id):
+ """Update the state of the existing dialog"""
+ if self._finddlg is None:
+ self._finddlg = self._CreateNewDialog(e_id)
+ self._finddlg.CenterOnParent()
+ else:
+ mode = self._finddlg.GetDialogMode()
+ if e_id == ed_glob.ID_FIND and mode != eclib.AFR_STYLE_FINDDIALOG:
+ self._finddlg.SetDialogMode(eclib.AFR_STYLE_FINDDIALOG)
+ elif e_id == ed_glob.ID_FIND_REPLACE and \
+ mode != eclib.AFR_STYLE_REPLACEDIALOG:
+ self._finddlg.SetDialogMode(eclib.AFR_STYLE_REPLACEDIALOG)
+ else:
+ pass
+
+ # Update the text that should be shown in the find replace fields
+ self._finddlg.RefreshFindReplaceFields()
+ self._finddlg.SetFocus()
+
+ def _InitFindData(self):
+ """Get the intial find data
+ @return: wx.FindReplaceData
+
+ """
+ fdata = Profile_Get('SEARCH_SETTINGS', default=None)
+ if fdata is not None:
+ fmap = dict(matchcase=eclib.AFR_MATCHCASE,
+ wholeword=eclib.AFR_WHOLEWORD,
+ regex=eclib.AFR_REGEX,
+ recurse=eclib.AFR_RECURSIVE)
+ flags = 0
+ for flag in fdata:
+ if fdata.get(flag, False):
+ flags |= fmap.get(flag, 0)
+ fdata = wx.FindReplaceData(flags)
+ else:
+ fdata = wx.FindReplaceData(eclib.AFR_RECURSIVE)
+ return fdata
+
+ def _StoreFindData(self):
+ """Serialize the find/replace settings into the user profile"""
+ fmap = dict(matchcase=eclib.AFR_MATCHCASE,
+ wholeword=eclib.AFR_WHOLEWORD,
+ regex=eclib.AFR_REGEX,
+ recurse=eclib.AFR_RECURSIVE)
+ tostore = dict()
+ flags = self._data.GetFlags()
+ for fname in fmap:
+ flag = fmap[fname]
+ tostore[fname] = False
+ if flags & flag:
+ tostore[fname] = True
+ Profile_Set('SEARCH_SETTINGS', tostore)
+
+ #---- Public Interface ----#
+
+ def GetClientString(self, multiline=False):
+ """Get the selected text in the current client buffer. By default
+ it will only return the selected text if its on a single line.
+ @keyword multiline: Return text if it is multiple lines
+ @return: string
+
+ """
+ cbuff = self._stc()
+ if cbuff is None:
+ return u''
+
+ start, end = cbuff.GetSelection()
+ rtext = cbuff.GetSelectedText()
+ if start != end:
+ sline = cbuff.LineFromPosition(start)
+ eline = cbuff.LineFromPosition(end)
+ if not multiline and (sline != eline):
+ rtext = u''
+ return rtext
+
+ def GetData(self):
+ """Get the controllers FindReplaceData
+ @return: wx.FindReplaceData
+
+ """
+ return self._data
+
+ def GetDialog(self):
+ """Return the active find dialog if one exists else return None
+ @return: FindDialog or None
+
+ """
+ return self._finddlg
+
+ def GetLastFound(self):
+ """Returns the position value of the last found search item
+ if the last search resulted in nothing being found then the
+ return value will -1.
+ @return: position of last search operation
+
+ """
+ return self._posinfo['found']
+
+ def OnUpdateFindUI(self, evt):
+ """Update ui handler for find related controls
+ @param evt: updateui event
+
+ """
+ if evt.GetId() in (ed_glob.ID_FIND_PREVIOUS, ed_glob.ID_FIND_NEXT):
+ evt.Enable(len(self.GetData().GetFindString()))
+ else:
+ evt.Skip()
+
+ def OnCount(self, evt):
+ """Count the number of matches"""
+ stc = self._stc()
+
+ # Create the search engine
+ query = evt.GetFindString()
+ mode = evt.GetSearchType()
+ engine = ebmlib.SearchEngine(query, evt.IsRegEx(),
+ True, evt.IsMatchCase(), evt.IsWholeWord())
+
+ if mode == eclib.LOCATION_CURRENT_DOC:
+ engine.SetSearchPool(stc.GetText())
+ elif mode == eclib.LOCATION_IN_SELECTION:
+ engine.SetSearchPool(stc.GetSelectedText())
+ else:
+ # TODO: report that this is not supported yet
+ # this case should not happen as the count button is currently
+ # disabled for any conditions that fall into this case.
+ return
+
+ matches = engine.FindAll()
+ if matches:
+ count = len(matches)
+ else:
+ count = 0
+
+ rmap = dict(term=query, count=count)
+ wx.MessageBox(_("The search term \'%(term)s\' was found %(count)d times.") % rmap,
+ _("Find Count"),
+ wx.ICON_INFORMATION|wx.OK)
+
+ def OnFind(self, evt, findnext=False, incremental=False):
+ """Do an incremental search in the currently buffer
+ @param evt: EVT_FIND, EVT_FIND_NEXT
+ @keyword findnext: force a find next action
+ @keyword incremental: perform an incremental search
+
+ """
+ data = self.GetData()
+
+ # Find next from menu event or called internally by replace
+ if findnext or evt.GetEventType() == wx.wxEVT_COMMAND_MENU_SELECTED:
+
+ # Adjust flags
+ flags = data.GetFlags()
+ if not findnext and evt.GetId() == ed_glob.ID_FIND_PREVIOUS:
+ flags |= eclib.AFR_UP
+ elif eclib.AFR_UP & flags:
+ # Not a find previous request so make sure that
+ # the search up flag is cleared.
+ flags ^= eclib.AFR_UP
+
+ evt = eclib.FindEvent(eclib.edEVT_FIND_NEXT, flags=flags)
+ evt.SetFindString(data.GetFindString())
+
+ stc = self._stc()
+ data.SetFindString(evt.GetFindString())
+
+ # Create the search engine
+ isdown = not evt.IsUp()
+ self._engine.SetQuery(data.GetFindString())
+ self._engine.SetFlags(isregex=evt.IsRegEx(),
+ matchcase=evt.IsMatchCase(),
+ wholeword=evt.IsWholeWord(),
+ down=isdown)
+
+ # Check if expression was valid or not
+ if self._engine.GetQueryObject() is None:
+ fail = ed_txt.DecodeString(self._engine.GetQuery(), 'utf-8')
+ wx.MessageBox(_("Invalid expression \"%s\"") % fail,
+ _("Regex Compile Error"),
+ style=wx.OK|wx.CENTER|wx.ICON_ERROR)
+ return
+
+ # XXX: may be inefficient to copy whole buffer each time for files
+ # that are large.
+ self._engine.SetSearchPool(stc.GetText())
+
+ # Get the search start position
+ if evt.GetEventType() == eclib.edEVT_FIND:
+ if not incremental:
+ spos = stc.CurrentPos
+ else:
+ # For incremental search redo search starting from last found
+ # position.
+ spos = self._posinfo['found']
+ if spos < 0:
+ spos = stc.CurrentPos
+ else:
+ spos = stc.CurrentPos
+ start, end = stc.GetSelection()
+ if start != end:
+ if isdown:
+ spos = max(start, end)
+ else:
+ spos = min(start, end)
+
+ # Do the find
+ match = self._engine.Find(spos)
+ if match is not None:
+ start, end = match
+ if isdown:
+ start = start + spos
+ end = end + spos
+ stc.SetSelection(start, end)
+ else:
+ stc.SetSelection(start, end)
+
+ # Ensure caret and the line its in is exposed
+ stc.EnsureCaretVisible()
+ line = stc.LineFromPosition(start)
+ stc.EnsureVisible(line)
+
+ self._posinfo['found'] = start
+
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT,
+ (ed_glob.SB_INFO, u""))
+ else:
+ # try search from top again
+ if isdown:
+ match = self._engine.Find(0)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT,
+ (ed_glob.SB_INFO, _("Search wrapped to top")))
+ else:
+ match = self._engine.Find(-1)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT,
+ (ed_glob.SB_INFO,
+ _("Search wrapped to bottom")))
+
+ if match is not None:
+ start, end = match
+ self._posinfo['found'] = start
+ stc.SetSelection(start, end)
+
+ # Ensure caret and the line its in is exposed
+ stc.EnsureCaretVisible()
+ line = stc.LineFromPosition(start)
+ stc.EnsureVisible(line)
+ else:
+ self._posinfo['found'] = -1
+ fail = ed_txt.DecodeString(self._engine.GetQuery(), 'utf-8')
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT,
+ (ed_glob.SB_INFO,
+ _("\"%s\" was not found") % fail))
+
+ def OnFindAll(self, evt):
+ """Find all results for the given query and display results in a
+ L{SearchResultScreen} in the Shelf.
+
+ """
+ smode = evt.GetSearchType()
+ query = evt.GetFindString()
+ if not query:
+ return
+
+ # Create a new search engine object
+ engine = EdSearchEngine(query, evt.IsRegEx(), True,
+ evt.IsMatchCase(), evt.IsWholeWord())
+ engine.SetResultFormatter(engine.FormatResult)
+
+ # Send the search function over to any interested parties that wish
+ # to process the results.
+ if smode == eclib.LOCATION_CURRENT_DOC:
+ stc = self._stc()
+ fname = stc.GetFileName()
+ if len(fname):
+ ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH,
+ (engine.SearchInFile, [fname,], dict()))
+ else:
+ engine.SetSearchPool(stc.GetText())
+ ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH,
+ (engine.FindAllLines,))
+ if smode == eclib.LOCATION_IN_SELECTION:
+ stc = self._stc()
+ sel_s = min(stc.GetSelection())
+ offset = stc.LineFromPosition(sel_s)
+ engine.SetOffset(offset)
+ engine.SetSearchPool(stc.GetSelectedText())
+ ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH,
+ (engine.FindAllLines,))
+ elif smode == eclib.LOCATION_OPEN_DOCS:
+ files = [fname.GetFileName()
+ for fname in self._parent.GetTextControls()]
+ ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH,
+ (engine.SearchInFiles, [files,], dict()))
+ elif smode == eclib.LOCATION_IN_CURRENT_DIR:
+ stc = self._stc()
+ path = ebmlib.GetPathName(stc.GetFileName())
+ engine.SetFileFilters(evt.GetFileFilters())
+ ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH,
+ (engine.SearchInDirectory,
+ [path,], dict(recursive=evt.IsRecursive())))
+ elif smode == eclib.LOCATION_IN_FILES:
+ path = evt.GetDirectory()
+ engine.SetFileFilters(evt.GetFileFilters())
+ ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH,
+ (engine.SearchInDirectory,
+ [path,], dict(recursive=evt.IsRecursive())))
+
+ def OnFindSelected(self, evt):
+ """Set the search query to the selected text and progress the search
+ to the next match.
+
+ """
+ stc = self._stc()
+
+ fstring = stc.GetSelectedText()
+ if fstring:
+ data = self.GetData()
+ data.SetFindString(fstring)
+ self.OnFind(evt)
+ else:
+ evt.Skip()
+
+ def OnFindClose(self, evt):
+ """Process storing search dialog state when it is closed
+ @param evt: findlg.EVT_FIND_CLOSE
+
+ """
+ if self._finddlg is not None:
+ # Save the lookin values for next time dialog is shown
+ self._li_choices = self._finddlg.GetLookinChoices()
+ self._li_sel = self._finddlg.GetLookinSelection()
+ self._filters = self._finddlg.GetFileFilters()
+
+ # Store in profile. Only save most recent 8 in history
+ if len(self._li_choices) > 8:
+ choices = self._li_choices[-8:]
+ else:
+ choices = self._li_choices
+
+ # Save the most recent choices of search locations
+ Profile_Set('SEARCH_LOC', choices)
+ Profile_Set('SEARCH_FILTER', self._filters)
+ self._StoreFindData()
+ self._finddlg.Destroy()
+ self._finddlg = None
+ buff = wx.GetApp().GetCurrentBuffer()
+ if buff:
+ buff.SetFocus()
+
+ def OnOptionChanged(self, evt):
+ """Handle when the find options are changed in the dialog"""
+ self._StoreFindData() # Persist new search settings from find dialog
+ dead = list()
+ for idx, client in enumerate(self._clients):
+ try:
+ client.NotifyOptionChanged(evt)
+ except wx.PyDeadObjectError:
+ dead.append(idx)
+
+ def OnReplace(self, evt):
+ """Replace the selected text in the current buffer
+ @param evt: finddlg.EVT_REPLACE
+
+ """
+ replacestring = evt.GetReplaceString()
+ if evt.IsRegEx() and self._engine is not None:
+ match = self._engine.GetLastMatch()
+ if match is not None:
+ try:
+ value = match.expand(replacestring)
+ except re.error, err:
+ msg = _("Error in regular expression expansion."
+ "The replace action cannot be completed.\n\n"
+ "Error Message: %s") % err.message
+ wx.MessageBox(msg, _("Replace Error"), wx.OK|wx.ICON_ERROR)
+ return
+ else:
+ value = replacestring
+ else:
+ value = replacestring
+
+ sel = self._stc().GetSelection()
+ if sel[0] == sel[1]:
+ return
+
+ self._stc().ReplaceSelection(value)
+
+ # Go to the next match
+ eid = ed_glob.ID_FIND_NEXT
+ if evt.IsUp():
+ eid = ed_glob.ID_FIND_PREVIOUS
+ tevt = eclib.FindEvent(eclib.edEVT_FIND_NEXT, eid)
+ tevt.SetFlags(evt.GetFlags())
+ tevt.SetFindString(evt.GetFindString())
+ self.OnFind(tevt)
+
+ def OnReplaceAll(self, evt):
+ """Replace all instance of the search string with the given
+ replace string for the given search context.
+
+ """
+ smode = evt.GetSearchType()
+ rstring = evt.GetReplaceString()
+ engine = EdSearchEngine(evt.GetFindString(), evt.IsRegEx(),
+ True, evt.IsMatchCase(), evt.IsWholeWord())
+ engine.SetResultFormatter(engine.FormatResult)
+
+ results = 0
+ if smode == eclib.LOCATION_CURRENT_DOC:
+ stc = self._stc()
+ engine.SetSearchPool(stc.GetText())
+ matches = engine.FindAll()
+ if matches is not None:
+ self.ReplaceInStc(stc, matches, rstring, evt.IsRegEx())
+ results = len(matches)
+ elif smode == eclib.LOCATION_IN_SELECTION:
+ stc = self._stc()
+ engine.SetSearchPool(stc.GetSelectedText())
+ matches = engine.FindAll()
+ if matches is not None:
+ self.ReplaceInStcSelection(stc, matches, rstring, evt.IsRegEx())
+ results = len(matches)
+# regex = engine.GetQueryObject()
+# if regex is not None:
+# text = engine.GetSearchPool()
+# def replaceString(match):
+# if evt.IsRegEx():
+# value = match.expand(rstring.encode('utf-8')).decode('utf-8')
+# else:
+# value = rstring
+# return value
+# text = regex.sub(replaceString, text)
+# stc.ReplaceSelection(text)
+ else:
+ pass # TODO: notify of no matches?
+ elif smode == eclib.LOCATION_OPEN_DOCS:
+ for ctrl in self._parent.GetTextControls():
+ engine.SetSearchPool(ctrl.GetText())
+ matches = engine.FindAll()
+ if matches is not None:
+ self.ReplaceInStc(ctrl, matches, rstring, evt.IsRegEx())
+ results += len(matches)
+ elif smode in (eclib.LOCATION_IN_CURRENT_DIR, eclib.LOCATION_IN_FILES):
+ dlg = wx.MessageDialog(self._parent,
+ _("Sorry will be ready for future version"),
+ _("Not implemented"),
+# _("Warning this cannot be undone!"),
+# _("Do Replace All?"),
+ style=wx.ICON_WARNING|wx.OK|wx.CANCEL|wx.CENTER)
+ result = dlg.ShowModal()
+ dlg.Destroy()
+
+ if result == wx.ID_OK:
+ pass
+# path = evt.GetDirectory()
+# ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH,
+# (engine.SearchInDirectory,
+# [path,], dict(recursive=evt.IsRecursive())))
+ else:
+ return
+
+ # Post number of matches that were replaced to the status bar
+ if results > 0:
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT,
+ (ed_glob.SB_INFO,
+ _("%d matches were replaced.") % results))
+
+ def OnShowFindDlg(self, evt):
+ """Catches the Find events and shows the appropriate find dialog
+ @param evt: event that called this handler
+ @postcondition: find dialog is shown
+
+ """
+ # Check for a selection in the buffer and load that text if
+ # there is any and it is at most one line.
+ query = self.GetClientString()
+ if len(query):
+ self.SetQueryString(query)
+
+ eid = evt.GetId()
+ # Dialog is not currently open
+ if self._finddlg is None:
+ self._finddlg = self._CreateNewDialog(eid)
+ if self._finddlg is None:
+ evt.Skip()
+ return
+ self._finddlg.CenterOnParent()
+ self._finddlg.SetTransparent(240)
+# self._finddlg.SetExtraStyle(wx.WS_EX_PROCESS_UI_UPDATES)
+ self._finddlg.Show()
+ else:
+ # Dialog is open already so just update it
+ self._UpdateDialogState(eid)
+ self._finddlg.Show()
+ self._finddlg.Raise()
+ self._finddlg.SetFocus()
+
+ def RegisterClient(self, client):
+ """Register a client object of this search controller. The client object
+ must implement a method called NotifyOptionChanged to be called when
+ search options are changed.
+
+ >>> def NotifyOptionChanged(self, evt)
+
+ @param client: object
+
+ """
+ if client not in self._clients:
+ self._clients.append(client)
+
+ def RemoveClient(self, client):
+ """Remove a client from this controller
+ @param client: object
+
+ """
+ if client in self._clients:
+ self._clients.remove(client)
+
+ @staticmethod
+ def ReplaceInStc(stc, matches, rstring, isregex=True):
+ """Replace the strings at the position in the given StyledTextCtrl
+ @param stc: StyledTextCtrl
+ @param matches: list of match objects
+ @param rstring: Replace string
+ @keyword isregex: Is it a regular expression operation (bool)
+
+ """
+ if not len(matches):
+ return
+ def GetSub(match):
+ """replace substitution callable for re.sub"""
+ value = rstring
+ if isregex:
+ try:
+ value = match.expand(rstring)
+ except:
+ pass
+ return value
+ text = re.sub(matches[0].re, GetSub, stc.GetText())
+ # Update the view
+ with eclib.Freezer(stc) as _tmp:
+ stc.BeginUndoAction()
+ cpos = stc.CurrentPos
+ stc.ClearAll()
+ stc.SetText(text)
+ stc.GotoPos(cpos)
+ stc.EndUndoAction()
+
+ @staticmethod
+ def ReplaceInStcSelection(stc, matches, rstring, isregex=True):
+ """Replace all the matches in the selection"""
+ if not len(matches):
+ return
+ def GetSub(match):
+ """replace substitution callable for re.sub"""
+ value = rstring
+ if isregex:
+ try:
+ value = match.expand(rstring)
+ except:
+ pass
+ return value
+ text = re.sub(matches[0].re, GetSub, stc.GetSelectedText())
+ # Update the view
+ with eclib.Freezer(stc) as _tmp:
+ stc.BeginUndoAction()
+ start, end = stc.GetSelection()
+ stc.ReplaceSelection(text)
+ stc.SetSelection(start, start+len(text))
+ stc.EndUndoAction()
+
+ def SetFileFilters(self, filters):
+ """Set the file filter to use
+ @param filters: string '*.py *.pyw'
+
+ """
+ self._filters = filters
+
+ def SetLookinChoices(self, choices):
+ """Set the list of locations to use for the recent search
+ locations.
+ @param choices: list of strings
+
+ """
+ self._li_choices = choices
+
+ def SetQueryString(self, query):
+ """Sets the search query value
+ @param query: string to search for
+
+ """
+ self._data.SetFindString(query)
+
+ def SetSearchFlags(self, flags):
+ """Set the find services search flags
+ @param flags: bitmask of parameters to set
+
+ """
+ self._data.SetFlags(flags)
+ if self._finddlg is not None:
+ self._finddlg.SetData(self._data)
+ self._StoreFindData() # Update persistence
+
+ def RefreshControls(self):
+ """Refresh controls that are associated with this controllers data."""
+ if self._finddlg is not None:
+ self._finddlg.RefreshFindOptions()
+ self._StoreFindData() # Update persistence
+
+#-----------------------------------------------------------------------------#
+
+class EdSearchCtrl(wx.SearchCtrl):
+ """Creates a simple search control for use in the toolbar
+ or a statusbar and the such. Supports incremental search,
+ and uses L{SearchController} to do the actual searching of the
+ document.
+
+ """
+ def __init__(self, parent, id_, value="", menulen=0, \
+ pos=wx.DefaultPosition, size=wx.DefaultSize, \
+ style=wx.TE_RICH2|wx.TE_PROCESS_ENTER):
+ """Initializes the Search Control
+ @param parent: parent window
+ @param id_: control id
+ @keyword value: default value
+ @keyword menulen: max length of history menu
+ @keyword pos: control position (tuple)
+ @keyword size: control size (tuple)
+ @keyword style: control style bitmask
+
+ """
+ super(EdSearchCtrl, self).__init__(parent, id_, value, pos, size, style)
+
+ # Attributes
+ self._parent = parent
+ # TEMP HACK
+ self.FindService = self.GetTopLevelParent().GetNotebook()._searchctrl
+ self._recent = list() # The History List
+ self._last = None
+ self.rmenu = wx.Menu()
+ self.max_menu = menulen + 2 # Max menu length + descript/separator
+ self._txtctrl = None # msw/gtk only
+
+ # Setup Recent Search Menu
+ lbl = self.rmenu.Append(wx.ID_ANY, _("Recent Searches"))
+ lbl.Enable(False)
+ self.rmenu.AppendSeparator()
+ self.SetMenu(self.rmenu)
+
+ # Bind Events
+ if wx.Platform in ['__WXMSW__', '__WXGTK__']:
+ for child in self.GetChildren():
+ if isinstance(child, wx.TextCtrl):
+ child.Bind(wx.EVT_KEY_UP, self.ProcessEvent)
+ child.Bind(wx.EVT_KEY_DOWN, self.ProcessEvent)
+ self._txtctrl = child
+ break
+ else:
+ self.Bind(wx.EVT_KEY_UP, self.ProcessEvent)
+ self.Bind(wx.EVT_KEY_DOWN, self.ProcessEvent)
+ self.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.OnCancel)
+ self.Bind(wx.EVT_MENU, self.OnHistMenu)
+
+ #---- Properties ----#
+ def __GetFlags(self):
+ flags = 0
+ data = self.GetSearchData()
+ if data:
+ flags = data.GetFlags()
+ return flags
+ def __SetFlags(self, flags):
+ data = self.GetSearchData()
+ if data:
+ data.SetFlags(flags)
+ SearchFlags = property(lambda self: self.__GetFlags(),
+ lambda self, flags: self.__SetFlags(flags))
+
+ #---- Functions ----#
+ def AutoSetQuery(self, multiline=False):
+ """Autoload a selected string from the controls client buffer"""
+ query = self.FindService.GetClientString(multiline)
+ if len(query):
+ self.FindService.SetQueryString(query)
+ self.SetValue(query)
+
+ def ClearSearchFlag(self, flag):
+ """Clears a previously set search flag
+ @param flag: flag to clear from search data
+
+ """
+ data = self.GetSearchData()
+ if data is not None:
+ c_flags = data.GetFlags()
+ c_flags ^= flag
+ self.SearchFlags = c_flags
+ self.FindService.RefreshControls()
+
+ def FindAll(self):
+ """Fire off a FindAll job in the current buffer"""
+ evt = eclib.FindEvent(eclib.edEVT_FIND_ALL, flags=self.SearchFlags)
+ evt.SetFindString(self.GetValue())
+ self.FindService.OnFindAll(evt)
+
+ def DoSearch(self, next=True, incremental=False):
+ """Do the search and move the selection
+ @keyword next: search next or previous
+ @keyword incremental: is this an incremental search
+
+ """
+ s_cmd = eclib.edEVT_FIND
+ if not next:
+ self.SetSearchFlag(eclib.AFR_UP)
+ else:
+ if eclib.AFR_UP & self.SearchFlags:
+ self.ClearSearchFlag(eclib.AFR_UP)
+
+ if self.GetValue() == self._last:
+ s_cmd = eclib.edEVT_FIND_NEXT
+
+ evt = eclib.FindEvent(s_cmd, flags=self.SearchFlags)
+ self._last = self.GetValue()
+ evt.SetFindString(self.GetValue())
+ self.FindService.OnFind(evt, incremental=incremental)
+
+ # Give feedback on whether text was found or not
+ if self.FindService.GetLastFound() < 0 and len(self.GetValue()) > 0:
+ if self._txtctrl is None:
+ self.SetForegroundColour(wx.RED)
+ else:
+ self._txtctrl.SetForegroundColour(wx.RED)
+ wx.Bell()
+ else:
+ # ?wxBUG? cant set text back to black after changing color
+ # But setting it to this almost black color works. Most likely its
+ # due to bit masking but I haven't looked at the source so I am not
+ # sure
+ if self._txtctrl is None:
+ self.SetForegroundColour(wx.ColourRGB(0 | 1 | 0))
+ else:
+ self._txtctrl.SetForegroundColour(wx.ColourRGB(0 | 1 | 0))
+ self.Refresh()
+
+ def GetSearchController(self):
+ """Get the L{SearchController} used by this control.
+ @return: L{SearchController}
+
+ """
+ return self.FindService
+
+ def GetSearchData(self):
+ """Gets the find data from the controls FindService
+ @return: wx.FindReplaceData
+
+ """
+ if hasattr(self.FindService, "GetData"):
+ return self.FindService.GetData()
+ else:
+ return None
+
+ def GetHistory(self):
+ """Gets and returns the history list of the control
+ @return: list of recent search items
+
+ """
+ return getattr(self, "_recent", list())
+
+ def InsertHistoryItem(self, value):
+ """Inserts a search query value into the top of the history stack
+ @param value: search string
+ @postcondition: the value is added to the history menu
+
+ """
+ if value == wx.EmptyString:
+ return
+
+ # Make sure menu only has unique items
+ m_items = list(self.rmenu.GetMenuItems())
+ for menu_i in m_items:
+ if value == menu_i.GetLabel():
+ self.rmenu.RemoveItem(menu_i)
+
+ # Create and insert the new item
+ n_item = wx.MenuItem(self.rmenu, wx.NewId(), value)
+ self.rmenu.InsertItem(2, n_item)
+
+ # Update History list
+ self._recent.insert(0, value)
+ if len(self._recent) > self.max_menu:
+ self._recent.pop()
+
+ # Check Menu Length
+ m_len = self.rmenu.GetMenuItemCount()
+ if m_len > self.max_menu:
+ try:
+ self.rmenu.RemoveItem(m_items[-1])
+ except IndexError, msg:
+ wx.GetApp().GetLog()("[ed_search][err] menu error: %s" % str(msg))
+
+ def IsMatchCase(self):
+ """Returns True if the search control is set to search
+ in Match Case mode.
+ @return: whether search is using match case or not
+
+ """
+ data = self.GetSearchData()
+ if data is not None:
+ return bool(eclib.AFR_MATCHCASE & data.GetFlags())
+ return False
+
+ def IsRegEx(self):
+ """Returns True if the search control is set to search
+ in regular expression mode.
+ @return: whether search is using regular expressions or not
+
+ """
+ data = self.GetSearchData()
+ if data is not None:
+ return bool(eclib.AFR_REGEX & data.GetFlags())
+ return False
+
+ def IsSearchPrevious(self):
+ """Returns True if the search control is set to search
+ in Previous mode.
+ @return: whether search is searching up or not
+
+ """
+ data = self.GetSearchData()
+ if data is not None:
+ return bool(eclib.AFR_UP & data.GetFlags())
+ return False
+
+ def IsWholeWord(self):
+ """Returns True if the search control is set to search
+ in Whole Word mode.
+ @return: whether search is using match whole word or not
+
+ """
+ data = self.GetSearchData()
+ if data is not None:
+ return bool(eclib.AFR_WHOLEWORD & data.GetFlags())
+ return False
+
+ def SetFocus(self):
+ """Set the focus and select the text"""
+ super(EdSearchCtrl, self).SetFocus()
+ self.AutoSetQuery()
+ self.SelectAll()
+
+ def SetHistory(self, hist_list):
+ """Populates the history list from a list of
+ string values.
+ @param hist_list: list of search items
+
+ """
+ hist_list.reverse()
+ for item in hist_list:
+ self.InsertHistoryItem(item)
+
+ def SetSearchFlag(self, flags):
+ """Sets the search data flags
+ @param flags: search flag to add
+
+ """
+ data = self.GetSearchData()
+ if data is not None:
+ c_flags = data.GetFlags()
+ c_flags |= flags
+ self.SearchFlags = c_flags
+ self.FindService.RefreshControls()
+
+ #---- End Functions ----#
+
+ #---- Event Handlers ----#
+ def ProcessEvent(self, evt):
+ """Processes Events for the Search Control
+ @param evt: the event that called this handler
+
+ """
+ e_key = evt.GetKeyCode()
+ if evt.GetEventType() != wx.wxEVT_KEY_UP:
+ if e_key in (wx.WXK_UP, wx.WXK_DOWN):
+ buff = wx.GetApp().GetCurrentBuffer()
+ if isinstance(buff, wx.stc.StyledTextCtrl):
+ val = -1
+ if e_key == wx.WXK_DOWN:
+ val = 1
+ buff.ScrollLines(val)
+ else:
+ evt.Skip()
+ return
+
+ if e_key == wx.WXK_ESCAPE:
+ # TODO change to more safely determine the context
+ # Currently control is only used in command bar
+ self.GetParent().Hide()
+ evt.Skip()
+ return
+ elif e_key == wx.WXK_SHIFT:
+ self.ClearSearchFlag(eclib.AFR_UP)
+ return
+ else:
+ pass
+
+ tmp = self.GetValue()
+ self.ShowCancelButton(len(tmp) > 0)
+
+ # Don't do search for navigation keys
+ if tmp == wx.EmptyString or evt.CmdDown() or evt.ControlDown() or \
+ e_key in [wx.WXK_COMMAND, wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_CONTROL,
+ wx.WXK_ALT, wx.WXK_UP, wx.WXK_DOWN, wx.WXK_F1, wx.WXK_F2,
+ wx.WXK_F3, wx.WXK_F4, wx.WXK_F5, wx.WXK_F6, wx.WXK_F7,
+ wx.WXK_F8, wx.WXK_F9, wx.WXK_F10, wx.WXK_F11, wx.WXK_F12]:
+ return
+
+ if e_key == wx.WXK_RETURN or e_key == wx.WXK_F3:
+ if evt.ShiftDown():
+ self.DoSearch(next=False)
+ else:
+ self.DoSearch(next=True)
+
+ # Add to search history
+ if e_key == wx.WXK_RETURN:
+ self.InsertHistoryItem(self.GetValue())
+ else:
+ # Don't do incremental searches when the RegEx flag is set in order
+ # to avoid errors in compiling the expression
+ if not self.IsRegEx():
+ self.DoSearch(next=True, incremental=True)
+
+ def OnCancel(self, evt):
+ """Cancels the Search Query
+ @param evt: SearchCtrl event
+
+ """
+ self.SetValue(u"")
+ self.ShowCancelButton(False)
+ evt.Skip()
+
+ def OnHistMenu(self, evt):
+ """Sets the search controls value to the selected menu item
+ @param evt: wx.MenuEvent
+
+ """
+ item_id = evt.GetId()
+ item = self.rmenu.FindItemById(item_id)
+ if item != None:
+ self.SetValue(item.GetLabel())
+ else:
+ evt.Skip()
+
+ #---- End Event Handlers ----#
+
+#-----------------------------------------------------------------------------#
+
+class EdFindResults(plugin.Plugin):
+ """Shelf interface implementation for the find results"""
+ plugin.Implements(iface.ShelfI)
+ SUBSCRIBED = False
+ RESULT_SCREENS = list()
+
+ def __init__(self, pmgr):
+ """Create the FindResults plugin
+ @param pmgr: This plugins manager
+
+ """
+ if not EdFindResults.SUBSCRIBED:
+ ed_msg.Subscribe(EdFindResults.StartResultsScreen,
+ ed_msg.EDMSG_START_SEARCH)
+ EdFindResults.SUBSCRIBED = True
+
+# def __del__(self):
+# if EdFindResults.SUBSCRIBED:
+# print "UNSUBSCRIBE"
+# ed_msg.Unsubscribe(self.StartResultsScreen)
+
+ @property
+ def __name__(self):
+ return u'Find Results'
+
+ def AllowMultiple(self):
+ """Find Results allows multiple instances"""
+ return True
+
+ def CreateItem(self, parent):
+ """Returns a log viewr panel"""
+ screen = SearchResultScreen(parent)
+ EdFindResults.RESULT_SCREENS.append(screen)
+ return screen
+
+ def GetBitmap(self):
+ """Get the find results bitmap
+ @return: wx.Bitmap
+
+ """
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_FIND), wx.ART_MENU)
+ return bmp
+
+ def GetId(self):
+ """Plugin menu identifier ID"""
+ return ed_glob.ID_FIND_RESULTS
+
+ def GetMenuEntry(self, menu):
+ """Get the menu entry for the log viewer
+ @param menu: the menu items parent menu
+
+ """
+ return None
+
+ def GetName(self):
+ """Return the name of this control"""
+ return self.__name__
+
+ def IsStockable(self):
+ """EdFindResults can be saved in the shelf preference stack"""
+ return False
+
+ @classmethod
+ def StartResultsScreen(cls, msg):
+ """Start a search in an existing window or open a new one
+ @param cls: this class
+ @param msg: message object
+
+ """
+ win = wx.GetApp().GetActiveWindow()
+
+ # Cleanup window list for dead objects
+ to_pop = list()
+ for idx, item in enumerate(list(EdFindResults.RESULT_SCREENS)):
+ if not isinstance(item, SearchResultScreen):
+ to_pop.append(idx)
+
+ for idx in reversed(to_pop):
+ EdFindResults.RESULT_SCREENS.pop(idx)
+
+ # Try to find an empty existing window to use for the new search
+ screen = None
+ if win is not None:
+ shelf = win.GetShelf()
+ s_mw = shelf.GetOwnerWindow()
+ shelf_nb = shelf.GetWindow()
+ for item in EdFindResults.RESULT_SCREENS:
+ if item.GetDisplayedLines() < 3 and \
+ s_mw is win and item.GetParent() is shelf_nb:
+ screen = shelf.RaiseWindow(item)
+ break
+
+ if screen is None:
+ shelf.PutItemOnShelf(ed_glob.ID_FIND_RESULTS)
+ screen = shelf_nb.GetCurrentPage()
+
+ # Fire off the search job
+ data = msg.GetData()
+ if len(data) > 1:
+ # Doing a file search operation
+ screen.StartSearch(data[0], *data[1], **data[2])
+ else:
+ # Doing a buffer find operation (in memory)
+ screen.StartSearch(data[0])
+
+#-----------------------------------------------------------------------------#
+
+class SearchResultScreen(ed_basewin.EdBaseCtrlBox):
+ """Screen for displaying search results and navigating to them"""
+ def __init__(self, parent):
+ """Create the result screen
+ @param parent: parent window
+
+ """
+ super(SearchResultScreen, self).__init__(parent)
+
+ # Attributes
+ self._meth = None
+ self._job = None
+ self._list = SearchResultList(self)
+ self._cancelb = None
+ self._clearb = None
+
+ # Layout
+ self.__DoLayout()
+ self._cancelb.Disable()
+
+ # Event Handlers
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+ self.Bind(wx.EVT_BUTTON,
+ lambda evt: self._list.Clear(), self._clearb)
+ self.Bind(wx.EVT_BUTTON,
+ lambda evt: self.CancelSearch(), self._cancelb)
+ self._list.Bind(eclib.EVT_TASK_START, self.OnTaskStart)
+ self._list.Bind(eclib.EVT_TASK_COMPLETE, self.OnTaskComplete)
+
+ # Message Handlers
+ ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED)
+
+ def OnDestroy(self, evt):
+ if evt.Id == self.Id:
+ ed_msg.Unsubscribe(self.OnThemeChange)
+ evt.Skip()
+
+ def __DoLayout(self):
+ """Layout and setup the results screen ui"""
+ ctrlbar = self.CreateControlBar(wx.TOP)
+ ctrlbar.AddStretchSpacer()
+
+ # Cancel Button
+ cancel = self.AddPlateButton(_("Cancel"), ed_glob.ID_STOP, wx.ALIGN_RIGHT)
+ self._cancelb = cancel
+
+ # Clear Button
+ clear = self.AddPlateButton(_("Clear"), ed_glob.ID_DELETE, wx.ALIGN_RIGHT)
+ self._clearb = clear
+
+ self.SetWindow(self._list)
+
+ def GetDisplayedLines(self):
+ """Get the number of lines displayed in the output window"""
+ return self._list.GetLineCount()
+
+ def OnTaskStart(self, evt):
+ """Start accepting results from the search thread
+ @param evt: UpdateBufferEvent
+
+ """
+ start = u">>> %s" % _("Search Started")
+ if self._meth is not None:
+ start += (u": " + self._meth.im_self.GetOptionsString())
+ self._list.SetStartEndText(start + os.linesep)
+ self._list.Start(250)
+
+ def OnTaskComplete(self, evt):
+ """Update when task is complete
+ @param evt: UpdateBufferEvent
+
+ """
+ self._meth = None
+
+ # Stop the timer
+ self._list.Stop()
+ self._cancelb.Disable()
+
+ # Update statusbar to show search is complete
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT,
+ (ed_glob.SB_INFO, _("Search complete")))
+
+ # Flush any remaining text to the output buffer
+ self._list.FlushBuffer()
+
+ # Add our end message
+ lines = max(0, self._list.GetLineCount() - 2)
+ msg = _("Search Complete: %d matching lines where found.") % lines
+ msg2 = _("Files Searched: %d" % self._list.GetFileCount())
+ end = u">>> %s \t%s" % (msg, msg2)
+ self._list.SetStartEndText(end + os.linesep)
+
+ def OnThemeChange(self, msg):
+ """Update the button icons after the theme has changed
+ @param msg: Message Object
+
+ """
+ cbmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DELETE), wx.ART_MENU)
+ self._clearb.SetBitmap(cbmp)
+ self._clearb.Refresh()
+
+ cbmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_STOP), wx.ART_MENU)
+ self._cancelb.SetBitmap(cbmp)
+ self._cancelb.Refresh()
+
+ def CancelSearch(self):
+ """Cancel the currently running search"""
+ if self._job is not None:
+ self._job.Cancel()
+ self._cancelb.Disable()
+
+ def StartSearch(self, searchmeth, *args, **kwargs):
+ """Start a search with the given method and display the results
+ @param searchmeth: callable
+ @param *args: positional arguments to pass to searchmeth
+ @param **kwargs: keyword arguments to pass to searchmeth
+
+ """
+ self._meth = searchmeth
+
+ if self._job is not None:
+ self._job.Cancel()
+
+ self._list.Clear()
+ self._job = eclib.TaskObject(self._list, searchmeth, *args, **kwargs)
+ ed_thread.EdThreadPool().QueueJob(self._job.DoTask)
+ self._cancelb.Enable()
+
+#-----------------------------------------------------------------------------#
+
+class SearchResultList(eclib.OutputBuffer):
+ """Outputbuffer for listing matching lines from the search results that
+ a L{ebmlib.SearchEngine} dispatches. The matching lines are turned into
+ hotspots that allow them to be clicked on for instant navigation to the
+ matching line.
+
+ """
+ STY_SEARCH_MATCH = eclib.OPB_STYLE_MAX + 1
+ RE_FIND_MATCH = re.compile('(.+) \(([0-9]+)\)\: .+')
+ def __init__(self, parent):
+ super(SearchResultList, self).__init__(parent)
+
+ # Attributes
+ self._files = 0
+
+ # Setup
+ font = Profile_Get('FONT1', 'font', wx.Font(11, wx.FONTFAMILY_MODERN,
+ wx.FONTSTYLE_NORMAL,
+ wx.FONTWEIGHT_NORMAL))
+ self.SetFont(font)
+ style = (font.GetFaceName(), font.GetPointSize(), "#FFFFFF")
+ self.StyleSetSpec(SearchResultList.STY_SEARCH_MATCH,
+ "face:%s,size:%d,fore:#000000,back:%s" % style)
+ self.StyleSetHotSpot(SearchResultList.STY_SEARCH_MATCH, True)
+
+ def AppendUpdate(self, value):
+ """Do a little filtering of updates as they arrive
+ @param value: search result from search method
+
+ """
+ if isinstance(value, basestring):
+ # Regular search result
+ super(SearchResultList, self).AppendUpdate(value)
+ else:
+ # Search in a new file has started
+ self._files += 1
+
+ # Only updated status bar for every 10 files to reduce the overhead
+ # of updating the status bar and to improve performance of search.
+ if self._files == 1 or \
+ ((self._files / 10) > ((self._files-1) / 10)):
+ wx.CallAfter(ed_msg.PostMessage, ed_msg.EDMSG_UI_SB_TXT,
+ (ed_glob.SB_INFO,
+ value[1])) # GetTranslation not thread safe (_("Searching in: %s") % )
+
+ def ApplyStyles(self, start, txt):
+ """Set a hotspot for each search result
+ Search matches strings should be formatted as follows
+ /file/name (line) match string
+ @param start: long
+ @param txt: string
+
+ """
+ self.StartStyling(start, 0x1f)
+ if re.match(SearchResultList.RE_FIND_MATCH, txt):
+ self.SetStyling(len(txt), SearchResultList.STY_SEARCH_MATCH)
+ else:
+ self.SetStyling(len(txt), eclib.OPB_STYLE_DEFAULT)
+
+ def Clear(self):
+ """Override OutputBuffer.Clear"""
+ self._files = 0
+ super(SearchResultList, self).Clear()
+
+ def DoHotSpotClicked(self, pos, line):
+ """Handle a click on a hotspot and open the file to the matched line
+ @param pos: long
+ @param line: int
+
+ """
+ txt = self.GetLine(line)
+ match = re.match(SearchResultList.RE_FIND_MATCH, txt)
+ if match is not None:
+ groups = match.groups()
+ if len(groups) == 2:
+ fname, lnum = groups
+ if lnum.isdigit():
+ lnum = int(lnum) - 1
+ else:
+ lnum = 0
+ self._OpenToLine(fname, lnum)
+
+ def GetFileCount(self):
+ """Get the number of files searched in the previous/current search job.
+ @return: int
+
+ """
+ return self._files
+
+ def SetStartEndText(self, txt):
+ """Add a start task or end task message to the output. Styled in
+ Info style.
+ @param txt: text to add
+
+ """
+ self.SetReadOnly(False)
+ cpos = self.GetLength()
+ self.AppendText(txt)
+ self.StartStyling(cpos, 0x1f)
+ self.SetStyling(self.GetLength() - cpos, eclib.OPB_STYLE_INFO)
+ self.SetReadOnly(True)
+
+ @staticmethod
+ def _OpenToLine(fname, line):
+ """Open the given filename to the given line number
+ @param fname: File name to open, relative paths will be converted to abs
+ paths.
+ @param line: Line number to set the cursor to after opening the file
+
+ """
+ mainw = wx.GetApp().GetActiveWindow()
+ nbook = mainw.GetNotebook()
+ buffers = [ page.GetFileName() for page in nbook.GetTextControls() ]
+ if fname in buffers:
+ page = buffers.index(fname)
+ nbook.ChangePage(page)
+ cpage = nbook.GetPage(page)
+ else:
+ nbook.OnDrop([fname])
+ cpage = nbook.GetPage(nbook.GetSelection())
+
+ cpage.GotoLine(line)
+ cpage.SetFocus()
+
+#-----------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_session.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_session.py
new file mode 100644
index 0000000..4f8e930
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_session.py
@@ -0,0 +1,290 @@
+###############################################################################
+# Name: ed_session.py #
+# Purpose: Object to help manage editor sessions #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Editra session file manager.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_session.py 70097 2011-12-22 21:36:43Z CJP $"
+__revision__ = "$Revision: 70097 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import os
+import cPickle
+
+# Editra Imports
+import util
+import ed_cmdbar
+import ed_glob
+import profiler
+import ed_msg
+import ebmlib
+
+#-----------------------------------------------------------------------------#
+# Globals
+_ = wx.GetTranslation
+
+#-----------------------------------------------------------------------------#
+
+class SessionManager(object):
+ """Simple editing session manager helper class"""
+ def __init__(self, savedir):
+ """@param savedir: directory to load/save session files at"""
+ super(SessionManager, self).__init__()
+
+ # Attributes
+ self.__default = '__default' # default session file name
+ self._sessiondir = savedir
+ self._sessionext = '.session'
+
+ #---- Properties ----#
+ DefaultSession = property(lambda self: self.__default)
+
+ SessionDir = property(lambda self: self._sessiondir,
+ lambda self, dpath: setattr(self, '_sessiondir', dpath))
+
+ def _SetExtension(self, ext):
+ assert ext.startswith('.')
+ self._sessionext = ext
+ SessionExtension = property(lambda self: self._sessionext,
+ lambda self, ext: self._SetExtension(ext))
+ Sessions = property(lambda self: self.GetSavedSessions())
+
+ #---- Implementation ----#
+
+ def DeleteSession(self, name):
+ """Delete the specified session name
+ @param name: session name
+ @return: bool
+
+ """
+ rval = True
+ session = self.PathFromSessionName(name)
+ if os.path.exists(session):
+ try:
+ os.remove(session)
+ except OSError:
+ rval = False
+ return rval
+
+ def GetSavedSessions(self):
+ """Get the list of available saved sessions by display name
+ @return: list of strings
+
+ """
+ sessions = list()
+ defaultSession = None
+ for session in os.listdir(self.SessionDir):
+ if session.endswith(self.SessionExtension):
+ path = os.path.join(self.SessionDir, session)
+ sName = self.SessionNameFromPath(path)
+ if session.startswith(self.__default):
+ defaultSession = sName
+ else:
+ sessions.append(sName)
+ sessions.sort()
+ if defaultSession:
+ sessions.insert(0, defaultSession)
+ return sessions
+
+ def LoadSession(self, name):
+ """Load a named session
+ @param name: session name
+ @return: list of paths
+
+ """
+ session = self.PathFromSessionName(name)
+ assert os.path.exists(session)
+ flist = list()
+ with open(session, 'rb') as f_handle:
+ # Load and validate file
+ try:
+ flist = cPickle.load(f_handle)
+ # TODO: Extend in future to support loading sessions
+ # for multiple windows.
+ flist = flist.get('win1', list())
+ for item in flist:
+ if type(item) not in (unicode, str):
+ raise TypeError("Invalid item in unpickled sequence")
+ except (cPickle.UnpicklingError, TypeError, EOFError), e:
+ util.Log("[ed_session][err] %s" % e)
+ raise e # Re throw
+ return flist
+
+ def SaveSession(self, name, paths):
+ """Save the given list of files as a session with the given name
+ @param name: session name
+ @param paths: list of file paths
+ @return: bool
+
+ """
+ session = self.PathFromSessionName(name)
+ bOk = False
+ with open(session, 'wb') as f_handle:
+ try:
+ # TODO multi window support
+ sdata = dict(win1=paths)
+ cPickle.dump(sdata, f_handle)
+ bOk = True
+ except Exception, msg:
+ util.Log("[ed_session][err] Failed to SaveSessionFile: %s" % msg)
+
+ return bOk
+
+ def PathFromSessionName(self, session):
+ """Get the full path to store a session file
+ @param session: string base name (no extension)
+
+ """
+ name = session + self.SessionExtension
+ path = os.path.join(self.SessionDir, name)
+ return path
+
+ def SessionNameFromPath(self, path):
+ """Get the sessions display name from its path"""
+ assert path.endswith(self.SessionExtension)
+ name = os.path.basename(path)
+ name = name.rsplit('.', 1)[0]
+ return name
+
+#-----------------------------------------------------------------------------#
+
+class EdSessionMgr(SessionManager):
+ """Editra specific session manager implementation"""
+ __metaclass__ = ebmlib.Singleton
+ def __init__(self):
+ super(EdSessionMgr, self).__init__(ed_glob.CONFIG['SESSION_DIR'])
+
+#-----------------------------------------------------------------------------#
+
+class EdSessionBar(ed_cmdbar.CommandBarBase):
+ """Command bar for managing editing sessions"""
+ class meta:
+ id = ed_glob.ID_SESSION_BAR
+
+ def __init__(self, parent):
+ super(EdSessionBar, self).__init__(parent)
+
+ # Attributes
+ self._sch = wx.Choice(self)
+
+ # Setup
+ self.__DoLayout()
+ self._saveb = self.AddPlateButton(_("Save"), ed_glob.ID_SAVE)
+ self._saveb.Name = "SaveButton"
+ self._saveasb = self.AddPlateButton(_("Save As"), ed_glob.ID_SAVEAS)
+ self._saveasb.Name = "SaveAsButton"
+ self._delb = self.AddPlateButton(_("Delete"), ed_glob.ID_DELETE)
+ self._delb.Name = "DeleteButton"
+ self.UpdateSessionList()
+
+ # Event Handlers
+ self._saveb.Bind(wx.EVT_BUTTON, self.OnSaveSession)
+ self._saveasb.Bind(wx.EVT_BUTTON, self.OnSaveSession)
+ self._delb.Bind(wx.EVT_BUTTON, self.OnDeleteSession)
+ self._sch.Bind(wx.EVT_CHOICE, self.OnChangeSession)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, self._delb)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+
+ # Message Handlers
+ ed_msg.Subscribe(self.OnConfigMsg,
+ ed_msg.EDMSG_PROFILE_CHANGE + ('LAST_SESSION',))
+
+ def __DoLayout(self):
+ self.AddControl(wx.StaticText(self, label=_("Session:")), wx.ALIGN_LEFT)
+ self.AddControl(self._sch, wx.ALIGN_LEFT)
+
+ def OnDestroy(self, evt):
+ """Cleanup message handlers"""
+ if self:
+ ed_msg.Unsubscribe(self.OnConfigMsg)
+ evt.Skip()
+
+ def GetSelectedSession(self):
+ """Get the currently selected session
+ @return: string (internal session name)
+
+ """
+ if self._sch.Selection == 0:
+ return EdSessionMgr().DefaultSession
+ else:
+ return self._sch.StringSelection
+
+ def OnChangeSession(self, evt):
+ """Current session changed in choice control"""
+ util.Log(u"[ed_session][info] OnChangeSession: %s" % self._sch.StringSelection)
+ ed_msg.PostMessage(ed_msg.EDMSG_SESSION_DO_LOAD,
+ self.GetSelectedSession(),
+ self.TopLevelParent.Id)
+
+ def OnConfigMsg(self, msg):
+ """Configuration update callback"""
+ if self:
+ self.UpdateSessionList()
+
+ def OnSaveSession(self, evt):
+ """Save the current session"""
+ ofiles = list()
+ util.Log("[ed_session][info] OnSaveSession")
+ if evt.EventObject is self._saveb:
+ ed_msg.PostMessage(ed_msg.EDMSG_FILE_GET_OPENED, ofiles,
+ self.TopLevelParent.Id)
+ util.Log("[ed_session][info] OnSaveSession: %d files" % len(ofiles))
+ EdSessionMgr().SaveSession(self.GetSelectedSession(), ofiles)
+ elif evt.EventObject is self._saveasb:
+ ed_msg.PostMessage(ed_msg.EDMSG_SESSION_DO_SAVE,
+ context=self.TopLevelParent.Id)
+ # Bar will be updated by config change if the save succeeds
+ else:
+ evt.Skip()
+
+ def OnDeleteSession(self, evt):
+ """Delete the current session"""
+ if evt.EventObject is self._delb:
+ ses = self.GetSelectedSession()
+ if ses != EdSessionMgr().DefaultSession:
+ EdSessionMgr().DeleteSession(ses)
+ # Switch back to default session
+ profiler.Profile_Set('LAST_SESSION',
+ EdSessionMgr().DefaultSession)
+ else:
+ evt.Skip()
+
+ def OnBarShown(self):
+ """Update the session list"""
+ self.UpdateSessionList()
+
+ def OnUpdateUI(self, evt):
+ """Handle UpdateUI events"""
+ if evt.EventObject is self._delb:
+ evt.Enable(self._sch.Selection > 0)
+ else:
+ evt.Skip()
+
+ def UpdateSessionList(self):
+ """Update the session list"""
+ sessions = EdSessionMgr().Sessions
+ if len(sessions):
+ sessions[0] = _("Default")
+ self._sch.Items = sessions
+ self.UpdateSelectedSession()
+ self.Layout()
+ self.Refresh()
+
+ def UpdateSelectedSession(self):
+ """Select the currently configured session"""
+ ses = profiler.Profile_Get('LAST_SESSION')
+ if ses:
+ if ses == EdSessionMgr().DefaultSession:
+ self._sch.SetSelection(0)
+ elif ses in self._sch.Items:
+ self._sch.SetStringSelection(ses)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_shelf.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_shelf.py
new file mode 100644
index 0000000..75b587c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_shelf.py
@@ -0,0 +1,677 @@
+###############################################################################
+# Name: ed_shelf.py #
+# Purpose: Editra Shelf container #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Shelf plugin and control implementation
+
+@summary: Shelf Implementation
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_shelf.py 72821 2012-10-29 22:48:49Z CJP $"
+__revision__ = "$Revision: 72821 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import re
+import wx
+
+# Editra Imports
+import ed_menu
+import ed_glob
+from profiler import Profile_Get
+import ed_msg
+import plugin
+import iface
+import ed_fmgr
+from extern import aui
+import ed_book
+import ebmlib
+
+#--------------------------------------------------------------------------#
+# Globals
+PGNUM_PAT = re.compile(' - [0-9]+')
+_ = wx.GetTranslation
+
+#-----------------------------------------------------------------------------#
+
+class Shelf(plugin.Plugin):
+ """Plugin that creates a notebook for holding the various Shelf items
+ implemented by L{ShelfI}.
+
+ """
+ SHELF_NAME = u'Shelf'
+ observers = plugin.ExtensionPoint(iface.ShelfI)
+
+ def GetUiHandlers(self, delegate):
+ """Gets the update ui handlers for the shelf's menu
+ @param delegate: L{EdShelfDelegate} instance
+ @return: [(ID, handler),]
+
+ """
+ handlers = [ (item.GetId(), delegate.UpdateShelfMenuUI)
+ for item in self.observers ]
+ return handlers
+
+ def Init(self, parent):
+ """Mixes the shelf into the parent window
+ @param parent: Reference to MainWindow
+ @return: L{EdShelfDelegate}
+
+ """
+ # First check if the parent has an instance already
+ mgr = parent.GetFrameManager()
+ if mgr.GetPane(Shelf.SHELF_NAME).IsOk():
+ return
+
+ # HACK - fixes mouse event issues that result in wrong
+ # tab indexes being reported in the notebook.
+ wrapper = ShelfWrapper(parent)
+ shelf = wrapper.GetShelf()
+ mgr.AddPane(wrapper,
+ ed_fmgr.EdPaneInfo().Name(Shelf.SHELF_NAME).\
+ Caption(_("Shelf")).Bottom().Layer(0).\
+ CloseButton(True).MaximizeButton(True).\
+ BestSize(wx.Size(500,250)))
+
+ # Hide the pane and let the perspective manager take care of it
+ mgr.GetPane(Shelf.SHELF_NAME).Hide()
+ mgr.Update()
+
+ # Create the delegate
+ delegate = EdShelfDelegate(shelf, self)
+
+ # Install Shelf menu under View and bind event handlers
+ view = parent.GetMenuBar().GetMenuByName("view")
+ menu = delegate.GetMenu()
+ pos = 0
+ for pos in range(view.GetMenuItemCount()):
+ mitem = view.FindItemByPosition(pos)
+ if mitem.GetId() == ed_glob.ID_PERSPECTIVES:
+ break
+
+ view.InsertMenu(pos + 1, ed_glob.ID_SHELF, _("Shelf"),
+ menu, _("Put an item on the Shelf"))
+
+ for item in menu.GetMenuItems():
+ if item.IsSeparator():
+ continue
+ parent.Bind(wx.EVT_MENU, delegate.OnGetShelfItem, item)
+
+ if menu.GetMenuItemCount() < 3:
+ view.Enable(ed_glob.ID_SHELF, False)
+
+ # Check for any other plugin specific install needs
+ for observer in self.observers:
+ if not observer.IsInstalled() and \
+ hasattr(observer, 'InstallComponents'):
+ observer.InstallComponents(parent)
+
+ # Only Load Perspective if all items are loaded
+ if delegate.StockShelf(Profile_Get('SHELF_ITEMS', 'list', [])):
+ delegate.SetPerspective(Profile_Get('SHELF_LAYOUT', 'str', u""))
+ delegate.SetSelection(Profile_Get('SHELF_SELECTION', 'int', -1))
+ return delegate
+
+#--------------------------------------------------------------------------#
+
+class EdShelfBook(ed_book.EdBaseBook):
+ ID_SHELF_SUBMENU = wx.NewId()
+ ID_CLOSE_LIKE_TABS = wx.NewId()
+ """Shelf notebook control"""
+ def __init__(self, parent):
+ style = aui.AUI_NB_BOTTOM | \
+ aui.AUI_NB_TAB_SPLIT | \
+ aui.AUI_NB_SCROLL_BUTTONS | \
+ aui.AUI_NB_CLOSE_ON_ACTIVE_TAB | \
+ aui.AUI_NB_TAB_MOVE | \
+ aui.AUI_NB_DRAW_DND_TAB
+ super(EdShelfBook, self).__init__(parent, style=style)
+
+ # Attributes
+ self._open = dict()
+ self._name2idx = dict() # For settings maintenance
+ self._menu = ebmlib.ContextMenuManager()
+ self._mcback = None
+ self._mw = None
+
+ # Event Handlers
+ # HACK: binding to self works differently than parent catching it
+ # binding here causes incorrect mouse coords to be sent to
+ # event handler during click events!
+# self.Bind(aui.EVT_AUINOTEBOOK_TAB_RIGHT_UP, self.OnTabRightUp)
+ self.Bind(aui.EVT_AUINOTEBOOK_BG_RIGHT_UP, self.OnBgRightUp)
+ self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnItemClose)
+ self.Bind(wx.EVT_MENU, self.OnTabMenu)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+
+ # Message handlers
+ ed_msg.Subscribe(self.OnUpdateTabs, ed_msg.EDMSG_THEME_NOTEBOOK)
+ ed_msg.Subscribe(self.OnUpdateTabs, ed_msg.EDMSG_THEME_CHANGED)
+
+ def OnDestroy(self, evt):
+ if evt.GetId() == self.GetId():
+ self._menu.Clear()
+ ed_msg.Unsubscribe(self.OnUpdateTabs)
+ evt.Skip()
+
+ def OnTabRightUp(self, evt):
+ """Tab right click handler"""
+ self._menu.Clear()
+ if self.MenuCallback:
+ sel = self.GetPageIndex(evt.Page)
+ s_lbl = self.GetPageText(sel)
+ s_lbl = s_lbl.rsplit('-')[0].strip()
+ tab_menu = ed_menu.EdMenu()
+ tab_menu.Append(EdShelfBook.ID_CLOSE_LIKE_TABS,
+ _("Close All '%s'") % s_lbl)
+ self._menu.AddHandler(EdShelfBook.ID_CLOSE_LIKE_TABS,
+ lambda tab, evt: self.CloseAll(s_lbl))
+ tab_menu.AppendSeparator()
+ shelf_menu = self.MenuCallback()
+ tab_menu.AppendMenu(EdShelfBook.ID_SHELF_SUBMENU,
+ _("Open"), shelf_menu)
+ self._menu.Menu = tab_menu
+ self.PopupMenu(self._menu.Menu)
+
+ def OnBgRightUp(self, evt):
+ """Show context menu"""
+ self._menu.Clear()
+ if self.MenuCallback:
+ self._menu.Menu = self.MenuCallback()
+ self.PopupMenu(self._menu.Menu)
+
+ def OnTabMenu(self, evt):
+ """Handle tab menu events"""
+ handler = self._menu.GetHandler(evt.Id)
+ if handler is not None:
+ handler(self.GetCurrentPage(), evt)
+ else:
+ evt.Skip()
+
+ MainWindow = property(lambda self: self._mw,
+ lambda self, mw: setattr(self, '_mw', mw))
+ BitmapCallbacks = property(lambda self: self._name2idx)
+ MenuCallback = property(lambda self: self._mcback,
+ lambda self, funct: setattr(self, '_mcback', funct))
+
+ def AddItem(self, item, name, bmp=wx.NullBitmap):
+ """Add an item to the shelf's notebook. This is useful for interacting
+ with the Shelf from outside its interface. It may be necessary to
+ call L{EnsureShelfVisible} before or after adding an item if you wish
+ the shelf to be shown when the item is added.
+ @param item: A panel like instance to add to the shelf's notebook
+ @param name: Items name used for page text in notebook
+ @keyword bmp: Tab bitmap to display
+
+ """
+ self.AddPage(item,
+ u"%s - %d" % (name, self._open.get(name, 0)),
+ select=True)
+
+ # Set the tab icon
+ self.SetPageBitmap(self.GetPageCount()-1, bmp)
+ self._open[name] = self._open.get(name, 0) + 1
+
+ def OnItemClose(self, evt):
+ """Callback for when pages are closed"""
+# name = self.GetPageText(evt.GetSelection())
+# name = name.rsplit('-')[0].strip()
+# self._open[name] = self._open.get(name, 1) - 1
+ evt.Skip()
+
+ def CloseAll(self, name):
+ """Close all of 'name' shelf items
+ @param name: shelf item name (string)
+
+ """
+ idxs = self.GetAllIndexes(name)
+ idxs.reverse()
+ for idx in idxs:
+ self.DeletePage(idx)
+
+ def GetAllIndexes(self, name):
+ """Get all the indexes of pages of the item identified
+ by 'name'.
+ @param name: shelf item name (string)
+
+ """
+ idxs = list()
+ for pg in range(self.GetPageCount()):
+ lbl = self.GetPageText(pg)
+ lbl = PGNUM_PAT.sub(u"", lbl)
+ if lbl == name:
+ idxs.append(pg)
+ return idxs
+
+ def EnsureShelfVisible(self):
+ """Make sure the Shelf is visible
+ @precondition: Shelf.Init has been called
+ @postcondition: Shelf is shown
+
+ """
+ mgr = self.MainWindow.GetFrameManager()
+ pane = mgr.GetPane(Shelf.SHELF_NAME)
+ if not pane.IsShown():
+ pane.Show()
+ mgr.Update()
+
+ def GetCount(self, item_name):
+ """Get the number of open instances of a given Shelf Item
+ @param item_name: Name of the Shelf item
+ @return: number of instances on the Shelf
+
+ """
+ count = 0
+ for page in range(self.GetPageCount()):
+ if self.GetPageText(page).startswith(item_name):
+ count = count + 1
+ return count
+
+ def GetMainWindow(self):
+ """Get the main window that this shelf instance was created for
+ @return: ed_main.MainWindow
+
+ """
+ return self.MainWindow
+
+ def GetOpen(self):
+ """Get the list of open shelf items
+ @return: list
+
+ """
+ return self._open
+
+ def Hide(self):
+ """Hide the shelf
+ @postcondition: Shelf is hidden by aui manager
+
+ """
+ mgr = self.MainWindow.GetFrameManager()
+ pane = mgr.GetPane(Shelf.SHELF_NAME)
+ if pane.IsOk():
+ pane.Hide()
+ mgr.Update()
+
+ def ItemIsOnShelf(self, item_name):
+ """Check if at least one instance of a given item
+ is currently on the Shelf.
+ @param item_name: name of Item to look for
+
+ """
+ for page in range(self.GetPageCount()):
+ if self.GetPageText(page).startswith(item_name):
+ return True
+ return False
+
+ def IsShown(self):
+ """Is the shelf visible?
+ @return: bool
+
+ """
+ mgr = self.MainWindow.GetFrameManager()
+ pane = mgr.GetPane(Shelf.SHELF_NAME)
+ if pane.IsOk():
+ return pane.IsShown()
+ else:
+ return False
+
+ def OnUpdateTabs(self, msg):
+ """Update all tab images depending upon current settings"""
+ if not self:
+ return
+
+ if not Profile_Get('TABICONS', default=True):
+ for page in range(self.GetPageCount()):
+ self.SetPageBitmap(page, wx.NullBitmap)
+ else:
+ # Show the icons
+ for pnum in range(self.GetPageCount()):
+ page = self.GetPage(pnum)
+ bmp = self.BitmapCallbacks.get(repr(page.__class__), lambda:wx.NullBitmap)()
+ self.SetPageBitmap(pnum, bmp)
+
+#--------------------------------------------------------------------------#
+
+class EdShelfDelegate(object):
+ """Delegate class to mediate between the plugin singleton object and the
+ UI implementation.
+
+ """
+ def __init__(self, shelf, pobject):
+ """Create the delegate object
+ @param shelf: Ui component instance
+ @param pobject: Reference to the plugin object
+
+ """
+ super(EdShelfDelegate, self).__init__()
+
+ # Attributes
+ self._log = wx.GetApp().GetLog()
+ self._shelf = shelf
+ self._pin = pobject
+
+ # Setup
+ self._shelf.MenuCallback = getattr(self, 'GetShelfObjectMenu')
+
+ @property
+ def observers(self):
+ return self._pin.observers
+
+ def AddItem(self, item, name, bmp=wx.NullBitmap):
+ """Add an item to the shelf"""
+ self._shelf.AddItem(item, name, bmp)
+
+ def CanStockItem(self, item_name):
+ """See if a named item can be stocked or not, meaning if it
+ can be saved and opened in the next session or not.
+ @param item_name: name of item to check
+ @return: bool whether item can be stocked or not
+
+ """
+ for item in self.observers:
+ if item_name == item.GetName():
+ if hasattr(item, 'IsStockable'):
+ return item.IsStockable()
+ else:
+ break
+ return False
+
+ def EnsureShelfVisible(self):
+ """Ensure the shelf is visible"""
+ self._shelf.EnsureShelfVisible()
+
+ def GetItemById(self, itemid):
+ """Get the shelf item by its id
+ @param itemid: Shelf item id
+ @return: reference to a ShelfI object
+
+ """
+ for item in self.observers:
+ if item.GetId() == itemid:
+ return item
+ return None
+
+ def GetItemId(self, item_name):
+ """Get the id that identifies a given item
+ @param item_name: name of item to get ID for
+ @return: integer id or None if not found
+
+ """
+ for item in self.observers:
+ if item_name == item.GetName():
+ return item.GetId()
+ return None
+
+ def GetItemStack(self):
+ """Returns a list of ordered named items that are open in the shelf
+ @return: list of strings
+
+ """
+ rval = list()
+ if self._shelf is not None:
+ for page in range(self._shelf.GetPageCount()):
+ rval.append(re.sub(PGNUM_PAT, u'',
+ self._shelf.GetPageText(page), 1))
+ return rval
+
+ def GetSelection(self):
+ """Get the index of the currently selected tab"""
+ if self._shelf:
+ return self._shelf.GetSelection()
+ return -1
+
+ def GetPerspective(self):
+ """Get the auinotebook perspective data
+ @return: string
+
+ """
+ return self._shelf.SavePerspective()
+
+ def SetPerspective(self, pdata):
+ """Set the aui notebooks perspective and layout
+ @param pdata: perspective data string
+
+ """
+ if pdata:
+ try:
+ self._shelf.LoadPerspective(pdata)
+ self._shelf.Update()
+ except Exception, msg:
+ self._log("[shelf][err] Failed LoadPerspective: %s" % msg)
+
+ def GetShelfObjectMenu(self):
+ """Get the minimal menu that lists all Shelf objects
+ without the 'Show Shelf' item.
+ @return: ed_menu.EdMenu
+
+ """
+ menu = ed_menu.EdMenu()
+ menu_items = list()
+ open_items = self._shelf.GetOpen()
+ for observer in self.observers:
+ # Register Observers
+ open_items[observer.GetName()] = 0
+ try:
+ menu_i = observer.GetMenuEntry(menu)
+ if menu_i is not None:
+ menu_items.append((menu_i.GetItemLabel(), menu_i))
+ except Exception, msg:
+ self._log("[shelf][err] %s" % str(msg))
+ menu_items.sort()
+
+ combo = 0
+ for item in menu_items:
+ combo += 1
+ shortcut = u""
+ if combo < 10:
+ shortcut = u"\tCtrl+Alt+" + unicode(combo)
+ nitem = menu.Append(item[1].Id, item[1].GetText() + shortcut)
+ if item[1].Bitmap.IsOk():
+ nitem.SetBitmap(item[1].Bitmap)
+ item[1].Destroy()
+ return menu
+
+ def GetMenu(self):
+ """Return the menu of this object
+ @return: ed_menu.EdMenu()
+
+ """
+ menu = self.GetShelfObjectMenu()
+ menu.Insert(0, wx.ID_SEPARATOR)
+ menu.Insert(0, ed_glob.ID_SHOW_SHELF, _("Show Shelf") + \
+ ed_menu.EdMenuBar.keybinder.GetBinding(ed_glob.ID_SHOW_SHELF),
+ _("Show the Shelf"))
+ return menu
+
+ def GetOwnerWindow(self):
+ """Return the L{ed_main.MainWindow} instance that owns/created
+ this Shelf.
+ @return: reference to ed_main.MainWindow or None
+
+ """
+ return self._shelf.GetMainWindow()
+
+ def GetWindow(self):
+ """Return reference to the Shelfs window component
+ @return: AuiNotebook
+
+ """
+ return self._shelf
+
+ def OnGetShelfItem(self, evt):
+ """Handles menu events that have been registered
+ by the Shelf Items on the Shelf.
+ @param evt: Event that called this handler
+
+ """
+ e_id = evt.GetId()
+ if e_id == ed_glob.ID_SHOW_SHELF:
+ parent = self.GetOwnerWindow()
+ if self._shelf.IsShown():
+ self._shelf.Hide()
+ nb = parent.GetNotebook()
+ nb.GetCurrentCtrl().SetFocus()
+ else:
+ self._shelf.EnsureShelfVisible()
+ mgr = parent.GetFrameManager()
+ pane = mgr.GetPane(Shelf.SHELF_NAME)
+ if pane is not None:
+ page = pane.window.Book.GetCurrentPage()
+ if hasattr(page, 'SetFocus'):
+ page.SetFocus()
+ else:
+ self.PutItemOnShelf(evt.GetId())
+
+ def OnPutShelfItemAway(self, evt):
+ """Handles when an item is closed
+ @param evt: event that called this handler
+ @todo: is this needed?
+
+ """
+ raise NotImplementedError
+
+ def PutItemOnShelf(self, shelfid):
+ """Put an item on the shelf by using its unique shelf id.
+ This is only for use with loading items implementing the
+ L{ShelfI} interface. See L{AddItem} if you wish to pass
+ a panel to the shelf to add.
+ @param shelfid: id of the ShelfItem to open
+
+ """
+ item = None
+ for shelfi in self.observers:
+ if shelfi.GetId() == shelfid:
+ item = shelfi
+ break
+
+ if item is None:
+ return
+
+ name = item.GetName()
+ if self._shelf.ItemIsOnShelf(name) and \
+ not item.AllowMultiple() or self._shelf is None:
+ return
+ else:
+ self.EnsureShelfVisible()
+ # Guard against crashes in creating plugin derived objects
+ # log error to log and continue running.
+ window = None
+ try:
+ window = item.CreateItem(self._shelf)
+ except Exception, msg:
+ self._log("[shelf][err] CreateItem failed: %s" % msg)
+ return
+
+ bmp = wx.NullBitmap
+ if hasattr(item, 'GetBitmap'):
+ self._shelf.BitmapCallbacks[repr(window.__class__)] = item.GetBitmap
+ bmp = item.GetBitmap()
+ else:
+ self._shelf.BitmapCallbacks[repr(window.__class__)] = lambda:wx.NullBitmap
+ self.AddItem(window, name, bmp)
+
+ def RaiseItem(self, item_name):
+ """Set the selection in the notebook to be the that of the first
+ instance of item_name that is found in the shelf.
+ @param item_name: ShelfI name
+ @return: reference to the selected page or None if no instance is
+
+ """
+ for page in range(self._shelf.GetPageCount()):
+ if self._shelf.GetPageText(page).startswith(item_name):
+ self._shelf.SetSelection(page)
+ return self._shelf.GetPage(page)
+ else:
+ return None
+
+ def RaiseWindow(self, window):
+ """Set the selection in the notebook to be the that of the given
+ window. Mostly used internally by items implementing L{ShelfI}.
+ @param window: Window object
+ @return: reference to the selected page or None if no instance is
+
+ """
+ for page in range(self._shelf.GetPageCount()):
+ ctrl = self._shelf.GetPage(page)
+ if window == ctrl:
+ self._shelf.SetSelection(page)
+ return ctrl
+ else:
+ return None
+
+ def SetSelection(self, index):
+ """Select an item in the Shelf window
+ @param index: shelf tab index
+
+ """
+ if self._shelf and index > 0 and index < self._shelf.GetPageCount():
+ try:
+ self._shelf.SetSelection(index)
+ except Exception, msg:
+ self._log("[shelf][err] Failed SetSelection: %s" % msg)
+
+ def StockShelf(self, i_list):
+ """Fill the shelf by opening an ordered list of items
+ @param i_list: List of named L{ShelfI} instances
+ @return: bool (True if all loaded / False otherwise)
+
+ """
+ bLoaded = True
+ for item in i_list:
+ if self.CanStockItem(item):
+ itemid = self.GetItemId(item)
+ if itemid:
+ self.PutItemOnShelf(itemid)
+ else:
+ bLoaded = False
+ else:
+ bLoaded = False
+ return bLoaded
+
+ def UpdateShelfMenuUI(self, evt):
+ """Enable/Disable shelf items based on whether they support
+ muliple instances or not.
+ @param evt: wxEVT_UPDATEUI
+
+ """
+ item = self.GetItemById(evt.GetId())
+ if item is None:
+ evt.Skip()
+ return
+
+ count = self._shelf.GetCount(item.GetName())
+ if count and not item.AllowMultiple():
+ evt.Enable(False)
+ else:
+ evt.Enable(True)
+
+#-----------------------------------------------------------------------------#
+
+class ShelfWrapper(wx.Panel):
+ def __init__(self, parent):
+ super(ShelfWrapper, self).__init__(parent)
+
+ self._shelf = EdShelfBook(self)
+ self._shelf.MainWindow = parent
+
+ # Setup
+ sizer = wx.BoxSizer()
+ sizer.Add(self._shelf, 1, wx.EXPAND)
+ self.SetSizer(sizer)
+
+ self.Bind(aui.EVT_AUINOTEBOOK_TAB_RIGHT_UP, self.OnTabRightUp)
+
+ Book = property(lambda self: self._shelf)
+
+ def GetShelf(self):
+ return self._shelf
+
+ def OnTabRightUp(self, evt):
+ self._shelf.OnTabRightUp(evt)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_statbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_statbar.py
new file mode 100644
index 0000000..3aef323
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_statbar.py
@@ -0,0 +1,326 @@
+###############################################################################
+# Name: ed_statbar.py #
+# Purpose: Custom statusbar with builtin progress indicator #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Custom StatusBar for Editra that contains a progress bar that responds to
+messages from ed_msg to display progress of different actions.
+
+@summary: Editra's StatusBar class
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_statbar.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc
+
+# Editra Libraries
+import ed_glob
+import util
+import ed_msg
+import ed_menu
+from syntax.synglob import GetDescriptionFromId
+from eclib import ProgressStatusBar, EncodingDialog
+from extern.decorlib import anythread
+
+#--------------------------------------------------------------------------#
+
+_ = wx.GetTranslation
+
+#--------------------------------------------------------------------------#
+
+class EdStatBar(ProgressStatusBar):
+ """Custom status bar that handles dynamic field width adjustment and
+ automatic expiration of status messages.
+
+ """
+ ID_CLEANUP_TIMER = wx.NewId()
+ def __init__(self, parent):
+ super(EdStatBar, self).__init__(parent, style=wx.ST_SIZEGRIP)
+
+ # Attributes
+ self._pid = parent.GetId() # Save parents id for filtering msgs
+ self._widths = list()
+ self._cleanup_timer = wx.Timer(self, EdStatBar.ID_CLEANUP_TIMER)
+ self._eolmenu = wx.Menu()
+ self._lexmenu = None
+ self._log = wx.GetApp().GetLog()
+
+ # Setup
+ self.SetFieldsCount(6) # Info, vi stuff, line/progress
+ self.SetStatusWidths([-1, 90, 40, 40, 40, 155])
+ self._eolmenu.Append(ed_glob.ID_EOL_MAC, u"CR",
+ _("Change line endings to %s") % u"CR",
+ kind=wx.ITEM_CHECK)
+ self._eolmenu.Append(ed_glob.ID_EOL_WIN, u"CRLF",
+ _("Change line endings to %s") % u"CRLF",
+ kind=wx.ITEM_CHECK)
+ self._eolmenu.Append(ed_glob.ID_EOL_UNIX, u"LF",
+ _("Change line endings to %s") % u"LF",
+ kind=wx.ITEM_CHECK)
+
+ # Event Handlers
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_TIMER, self.OnExpireMessage,
+ id=EdStatBar.ID_CLEANUP_TIMER)
+
+ # Messages
+ ed_msg.Subscribe(self.OnProgress, ed_msg.EDMSG_PROGRESS_SHOW)
+ ed_msg.Subscribe(self.OnProgress, ed_msg.EDMSG_PROGRESS_STATE)
+ ed_msg.Subscribe(self.OnUpdateText, ed_msg.EDMSG_UI_SB_TXT)
+ ed_msg.Subscribe(self.OnUpdateDoc, ed_msg.EDMSG_UI_NB_CHANGED)
+ ed_msg.Subscribe(self.OnUpdateDoc, ed_msg.EDMSG_FILE_SAVED)
+ ed_msg.Subscribe(self.OnUpdateDoc, ed_msg.EDMSG_FILE_OPENED)
+ ed_msg.Subscribe(self.OnUpdateDoc, ed_msg.EDMSG_UI_STC_LEXER)
+
+ def OnDestroy(self, evt):
+ """Unsubscribe from messages"""
+ if self._lexmenu:
+ self._lexmenu.Destroy()
+ if self._eolmenu:
+ self._eolmenu.Destroy()
+ if evt.GetId() == self.GetId():
+ ed_msg.Unsubscribe(self.OnProgress)
+ ed_msg.Unsubscribe(self.OnUpdateText)
+ ed_msg.Unsubscribe(self.OnUpdateDoc)
+ evt.Skip()
+
+ def __SetStatusText(self, txt, field):
+ """Safe method to use for setting status text with CallAfter.
+ @param txt: string
+ @param field: int
+
+ """
+ try:
+ super(EdStatBar, self).SetStatusText(txt, field)
+ self.AdjustFieldWidths()
+
+ if field == ed_glob.SB_INFO and txt != u'':
+ # Start the expiration countdown
+ if self._cleanup_timer.IsRunning():
+ self._cleanup_timer.Stop()
+ self._cleanup_timer.Start(10000, True)
+ except wx.PyDeadObjectError, wx.PyAssertionError:
+ # Getting some odd assertion errors on wxMac so just trap
+ # and ignore them for now
+ # glyphCount == (text.length()+1)" failed at graphics.cpp(2048)
+ # in GetPartialTextExtents()
+ pass
+ except TypeError, err:
+ self._log("[edstatbar][err] Bad status message: %s" % str(txt))
+ self._log("[edstatbar][err] %s" % err)
+
+ def AdjustFieldWidths(self):
+ """Adjust each field width of status bar basing on the field text
+ @return: None
+
+ """
+ widths = [-1]
+ # Calculate required widths
+ # NOTE: Order of fields is important
+ for field in [ed_glob.SB_BUFF,
+ ed_glob.SB_LEXER,
+ ed_glob.SB_ENCODING,
+ ed_glob.SB_EOL,
+ ed_glob.SB_ROWCOL]:
+ width = self.GetTextExtent(self.GetStatusText(field))[0] + 20
+ if width == 20:
+ width = 0
+ widths.append(width)
+
+ # Adjust widths
+ if widths[-1] < 155:
+ widths[-1] = 155
+
+ # Only update if there are changes
+ if widths != self._widths:
+ self._widths = widths
+ self.SetStatusWidths(self._widths)
+
+ def GetMainWindow(self):
+ """Method required for L{ed_msg.mwcontext}"""
+ return self.TopLevelParent
+
+ def OnExpireMessage(self, evt):
+ """Handle Expiring the status message when the oneshot timer
+ tells us it has expired.
+
+ """
+ if evt.GetId() == EdStatBar.ID_CLEANUP_TIMER:
+ wx.CallAfter(self.__SetStatusText, u'', ed_glob.SB_INFO)
+ else:
+ evt.Skip()
+
+ def OnLeftDClick(self, evt):
+ """Handlers mouse left double click on status bar
+ @param evt: wx.MouseEvent
+ @note: Assumes parent is MainWindow instance
+
+ """
+ pt = evt.GetPosition()
+ if self.GetFieldRect(ed_glob.SB_ROWCOL).Contains(pt):
+ mw = self.GetParent()
+ mpane = mw.GetEditPane()
+ mpane.ShowCommandControl(ed_glob.ID_GOTO_LINE)
+ else:
+ evt.Skip()
+
+ def OnLeftUp(self, evt):
+ """Handle left clicks on the status bar
+ @param evt: wx.MouseEvent
+
+ """
+ pt = evt.GetPosition()
+ if self.GetFieldRect(ed_glob.SB_EOL).Contains(pt):
+ rect = self.GetFieldRect(ed_glob.SB_EOL)
+ self.PopupMenu(self._eolmenu, (rect.x, rect.y))
+ elif self.GetFieldRect(ed_glob.SB_ENCODING).Contains(pt):
+ nb = self.GetTopLevelParent().GetNotebook()
+ buff = nb.GetCurrentCtrl()
+ dlg = EncodingDialog(nb,
+ msg=_("Change the encoding of the current document."),
+ title=_("Change Encoding"),
+ default=buff.GetEncoding())
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DOCPROP),
+ wx.ART_OTHER)
+ if bmp.IsOk():
+ dlg.SetBitmap(bmp)
+ dlg.CenterOnParent()
+
+ # TODO: should add EdFile callbacks for modification events instead
+ # of using explicit statusbar refresh.
+ if dlg.ShowModal() == wx.ID_OK:
+ buff.SetEncoding(dlg.GetEncoding())
+ self.UpdateFields()
+
+ # NOTE: Got an error report about a PyDeadObject error here. The
+ # error does not make any sense since the dialog is not
+ # destroyed or deleted by anything before this. Add validity
+ # check to ensure reference is still valid.
+ if dlg:
+ dlg.Destroy()
+ elif self.GetFieldRect(ed_glob.SB_LEXER).Contains(pt):
+ # Change Lexer popup menu
+ if self._lexmenu:
+ self._lexmenu.Destroy()
+ self._lexmenu = wx.Menu()
+ ed_menu.EdMenuBar.PopulateLexerMenu(self._lexmenu)
+ rect = self.GetFieldRect(ed_glob.SB_LEXER)
+ self.PopupMenu(self._lexmenu, (rect.x, rect.y))
+ else:
+ evt.Skip()
+
+ def OnProgress(self, msg):
+ """Set the progress bar's state
+ @param msg: Message Object
+
+ """
+ mdata = msg.GetData()
+ # Don't do anything if the message is not for this frame
+ if self._pid != mdata[0]:
+ return
+
+ mtype = msg.GetType()
+ if mtype == ed_msg.EDMSG_PROGRESS_STATE:
+ # May be called from non gui thread so don't do anything with
+ # the gui here.
+ self.SetProgress(mdata[1])
+ self.range = mdata[2]
+ if sum(mdata[1:]) == 0:
+ self.Stop()
+ elif mtype == ed_msg.EDMSG_PROGRESS_SHOW:
+ if mdata[1]:
+ self.Start(75)
+ else:
+ # TODO: findout where stray stop event is coming from...
+ self.Stop()
+
+ @ed_msg.mwcontext
+ def OnUpdateDoc(self, msg):
+ """Update document related fields
+ @param msg: Message Object
+
+ """
+ self.UpdateFields()
+ if msg.GetType() == ed_msg.EDMSG_UI_NB_CHANGED:
+ wx.CallAfter(self.__SetStatusText, u'', ed_glob.SB_INFO)
+
+ @anythread
+ def DoUpdateText(self, msg):
+ """Thread safe update of status text. Proxy for OnUpdateText because
+ pubsub seems to have issues with passing decorator methods for
+ listeners.
+ @param msg: Message Object
+
+ """
+ # Only process if this status bar is in the active window and shown
+ parent = self.GetTopLevelParent()
+ if (parent.IsActive() or wx.GetApp().GetTopWindow() == parent):
+ field, txt = msg.GetData()
+ self.UpdateFields()
+ wx.CallAfter(self.__SetStatusText, txt, field)
+
+ def OnUpdateText(self, msg):
+ """Update the status bar text based on the received message
+ @param msg: Message Object
+
+ """
+ self.DoUpdateText(msg)
+
+ def PushStatusText(self, txt, field):
+ """Set the status text
+ @param txt: Text to put in bar
+ @param field: int
+
+ """
+ wx.CallAfter(self.__SetStatusText, txt, field)
+
+ def SetStatusText(self, txt, field):
+ """Set the status text
+ @param txt: Text to put in bar
+ @param field: int
+
+ """
+ wx.CallAfter(self.__SetStatusText, txt, field)
+
+ def UpdateFields(self):
+ """Update document fields based on the currently selected
+ document in the editor.
+ @postcondition: encoding and lexer fields are updated
+ @todo: update when readonly hooks are implemented
+
+ """
+ nb = self.GetParent().GetNotebook()
+ if nb is None:
+ return
+
+ try:
+ cbuff = nb.GetCurrentCtrl()
+ doc = cbuff.GetDocument()
+ wx.CallAfter(self.__SetStatusText, doc.GetEncoding(),
+ ed_glob.SB_ENCODING)
+ wx.CallAfter(self.__SetStatusText,
+ GetDescriptionFromId(cbuff.GetLangId()),
+ ed_glob.SB_LEXER)
+
+ eol = { wx.stc.STC_EOL_CR : u"CR",
+ wx.stc.STC_EOL_LF : u"LF",
+ wx.stc.STC_EOL_CRLF : u"CRLF" }
+ wx.CallAfter(self.__SetStatusText,
+ eol[cbuff.GetEOLMode()],
+ ed_glob.SB_EOL)
+
+ except wx.PyDeadObjectError:
+ # May be called asyncronasly after the control is already dead
+ return
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_stc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_stc.py
new file mode 100644
index 0000000..1ee2178
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_stc.py
@@ -0,0 +1,1969 @@
+###############################################################################
+# Name: ed_stc.py #
+# Purpose: Editra's styled editing buffer #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This is the main component of the editor that manages all the information
+of the on disk file that it represents in memory. It works with the StyleManager
+and SyntaxManager to provide an editing pane that auto detects and configures
+itself for type of file that is in buffer to do highlighting and other language
+specific options such as commenting code.
+
+@summary: Editra's main text buffer class
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_stc.py 73712 2013-03-23 14:46:09Z CJP $"
+__revision__ = "$Revision: 73712 $"
+
+#-------------------------------------------------------------------------#
+# Imports
+
+import os
+import wx, wx.stc
+
+# Local Imports
+import ed_event
+import ed_glob
+from profiler import Profile_Get as _PGET
+from syntax import syntax
+import util
+import ed_basestc
+import ed_marker
+import ed_msg
+import ed_mdlg
+import ed_txt
+from ed_keyh import KeyHandler, ViKeyHandler
+import eclib
+import ebmlib
+import ed_thread
+
+#-------------------------------------------------------------------------#
+# Globals
+_ = wx.GetTranslation
+
+# EOL Constants
+EDSTC_EOL_CR = ed_glob.EOL_MODE_CR
+EDSTC_EOL_LF = ed_glob.EOL_MODE_LF
+EDSTC_EOL_CRLF = ed_glob.EOL_MODE_CRLF
+
+# Character sets
+SPACECHARS = " \t\r\n"
+NONSPACE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
+OPERATORS = "./\?[]{}<>!@#$%^&*():=-+\"';,"
+
+#-------------------------------------------------------------------------#
+
+def jumpaction(func):
+ """Decorator method to notify clients about jump actions"""
+ def WrapJump(*args, **kwargs):
+ """Wrapper for capturing before/after pos of a jump action"""
+ try:
+ stc = args[0]
+ pos = stc.GetCurrentPos()
+ line = stc.GetCurrentLine()
+ func(*args, **kwargs)
+ cpos = stc.GetCurrentPos()
+ cline = stc.GetCurrentLine()
+ fname = stc.GetFileName()
+
+ mdata = dict(fname=fname,
+ prepos=pos, preline=line,
+ lnum=cline, pos=cpos)
+ tlw = stc.TopLevelParent
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_POS_JUMPED, mdata, tlw.Id)
+ except wx.PyDeadObjectError:
+ pass
+
+ WrapJump.__name__ = func.__name__
+ WrapJump.__doc__ = func.__doc__
+ return WrapJump
+
+
+#-------------------------------------------------------------------------#
+
+class EditraStc(ed_basestc.EditraBaseStc):
+ """Defines a styled text control for editing text
+ @summary: Subclass of wx.stc.StyledTextCtrl and L{ed_style.StyleMgr}.
+ Manages the documents display and input.
+
+ """
+ def __init__(self, parent, id_,
+ pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, use_dt=True):
+ """Initializes a control and sets the default objects for
+ Tracking events that occur in the control.
+ @param parent: Parent Window
+ @param id_: Control ID
+ @keyword pos: Control position
+ @keyword size: Control size
+ @keyword style: Control style bitmask
+ @keyword use_dt: whether to use a drop target or not
+
+ """
+ super(EditraStc, self).__init__(parent, id_, pos, size, style)
+
+ self.SetModEventMask(wx.stc.STC_PERFORMED_UNDO | \
+ wx.stc.STC_PERFORMED_REDO | \
+ wx.stc.STC_MOD_DELETETEXT | \
+ wx.stc.STC_MOD_INSERTTEXT)
+
+ self.CmdKeyAssign(ord('-'), wx.stc.STC_SCMOD_CTRL, \
+ wx.stc.STC_CMD_ZOOMOUT)
+ self.CmdKeyAssign(ord('+'), wx.stc.STC_SCMOD_CTRL | \
+ wx.stc.STC_SCMOD_SHIFT, wx.stc.STC_CMD_ZOOMIN)
+
+ #---- Drop Target ----#
+ if use_dt and hasattr(parent, 'OnDrop'):
+ self.SetDropTarget(util.DropTargetFT(self, None, parent.OnDrop))
+
+ # Attributes
+ self.LOG = wx.GetApp().GetLog()
+ self._loading = None
+ self.key_handler = KeyHandler(self)
+ self._backup_done = True
+ self._bktimer = wx.Timer(self)
+ self._dwellsent = False
+
+ # Macro Attributes
+ self._macro = list()
+ self.recording = False
+
+ # Command/Settings Attributes
+ self._config = dict(autocomp=_PGET('AUTO_COMP'),
+ autoindent=_PGET('AUTO_INDENT'),
+ brackethl=_PGET('BRACKETHL'),
+ folding=_PGET('CODE_FOLD'),
+ highlight=_PGET('SYNTAX'),
+ autobkup=_PGET('AUTOBACKUP'))
+
+ # Set Default Styles used by all documents
+ self.Configure()
+ self.UpdateBaseStyles()
+
+ # Other Settings
+ self.SetMouseDwellTime(900)
+ self.UsePopUp(False)
+
+ #self.Bind(wx.stc.EVT_STC_MACRORECORD, self.OnRecordMacro)
+ self.Bind(wx.stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
+ self.Bind(wx.stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
+ self.Bind(wx.stc.EVT_STC_USERLISTSELECTION, self.OnUserListSel)
+ self.Bind(wx.stc.EVT_STC_DWELLSTART, self.OnDwellStart)
+ self.Bind(wx.stc.EVT_STC_DWELLEND, self.OnDwellEnd)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_TIMER, self.OnBackupTimer)
+
+ # Async file load events
+ self.Bind(ed_txt.EVT_FILE_LOAD, self.OnLoadProgress)
+
+ #---- End Init ----#
+
+ __name__ = u"EditraTextCtrl"
+
+ #---- Protected Member Functions ----#
+
+ def _BuildMacro(self):
+ """Constructs a macro script from items in the macro
+ record list.
+ @status: in limbo
+
+ """
+ if not len(self._macro):
+ return
+
+ # Get command mappings
+ cmds = list()
+ for x in dir(wx.stc):
+ if x.startswith('STC_CMD_'):
+ cmds.append(x)
+ cmdvals = [getattr(wx.stc, x) for x in cmds]
+ cmds = [x.replace('STC_CMD_', u'') for x in cmds]
+
+ # Get the commands names used in the macro
+ named = list()
+ for x in self._macro:
+ if x[0] in cmdvals:
+ named.append(cmds[cmdvals.index(x[0])])
+ code = list()
+
+ stc_dict = wx.stc.StyledTextCtrl.__dict__
+ for cmd in named:
+ for attr in stc_dict:
+ if attr.upper() == cmd:
+ code.append(attr)
+ break
+
+ code_txt = u''
+ for fun in code:
+ code_txt += " ctrl.%s()\n" % fun
+ code_txt += " print \"Executed\"" #TEST
+ code_txt = "def macro(ctrl):\n" + code_txt
+ self.Parent.NewPage()
+ self.Parent.GetCurrentPage().SetText(code_txt)
+ self.Parent.GetCurrentPage().FindLexer('py')
+# code = compile(code_txt, self.__module__, 'exec')
+# exec code in self.__dict__ # Inject new code into this namespace
+
+ def _MacHandleKey(self, k_code, shift_down, alt_down, ctrl_down, cmd_down):
+ """Handler for mac specific actions"""
+ handled = False
+ if alt_down:
+ return handled
+
+ if cmd_down and not ctrl_down:
+ # Jump line/start end are special on OSX and need to be
+ # white space aware.
+ line = self.GetCurrentLine()
+ if k_code == wx.WXK_RIGHT:
+ handled = True
+ pos = self.GetLineStartPosition(line)
+ # end pos is absolute end which includes NUL term
+ lpos = self.GetLineEndPosition(line) - 1
+ endsSpace = False
+ if lpos > 0:
+ endsSpace = unichr(self.GetCharAt(lpos)).isspace()
+
+ if not shift_down:
+ self.LineEnd()
+ if endsSpace:
+ self.WordLeftEnd()
+ else:
+ self.LineEndExtend()
+ if endsSpace:
+ self.WordLeftEndExtend()
+ elif k_code == wx.WXK_LEFT:
+ handled = True
+ cpos = self.GetCurrentPos()
+ self.GotoIndentPos(line)
+ if shift_down:
+ self.SetSelection(cpos, self.CurrentPos)
+
+ return handled
+
+ #---- Public Member Functions ----#
+
+ def AddBookmark(self, line=-1):
+ """Add a bookmark and return its handle
+ Sends notifications for bookmark added
+ @keyword line: if < 0 bookmark will be added to current line
+
+ """
+ rval = self.AddMarker(ed_marker.Bookmark(), line)
+ mdata = dict(stc=self, added=True, line=line, handle=rval)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_BOOKMARK, mdata)
+ return rval
+
+ def RemoveBookmark(self, line):
+ """Remove the book mark from the given line
+ Sends notifications for bookmark removal.
+ @param line: int
+
+ """
+ self.RemoveMarker(ed_marker.Bookmark(), line)
+ mdata = dict(stc=self, added=False, line=line)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_BOOKMARK, mdata)
+
+ def RemoveAllBookmarks(self):
+ """Remove all the bookmarks in the buffer
+ Sends notifications for bookmark removal.
+
+ """
+ self.RemoveAllMarkers(ed_marker.Bookmark())
+ mdata = dict(stc=self, added=False, line=-1)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_BOOKMARK, mdata)
+
+ def PlayMacro(self):
+ """Send the list of built up macro messages to the editor
+ to be played back.
+ @postcondition: the macro of this control has been played back
+
+ """
+ self.BeginUndoAction()
+ for msg in self._macro:
+ if msg[0] == 2170:
+ self.AddText(msg[2])
+ elif msg[0] == 2001:
+ self.AddText(self.GetEOLChar() + u' ' * (msg[1] - 1))
+ else:
+ self.SendMsg(msg[0], msg[1], msg[2])
+ self.EndUndoAction()
+
+ #---- Begin Function Definitions ----#
+
+ def Bookmark(self, action):
+ """Handles bookmark actions
+ @param action: An event ID that describes what is to be done
+ @return: None
+
+ """
+ lnum = self.GetCurrentLine()
+ mark = -1
+ if action == ed_glob.ID_ADD_BM:
+ if self.MarkerGet(lnum):
+ self.RemoveBookmark(lnum)
+ else:
+ self.AddBookmark(lnum)
+ elif action == ed_glob.ID_DEL_ALL_BM:
+ self.RemoveAllBookmarks()
+ elif action == ed_glob.ID_NEXT_MARK:
+ if self.MarkerGet(lnum):
+ lnum += 1
+ mark = self.MarkerNext(lnum, 1)
+ if mark == -1:
+ mark = self.MarkerNext(0, 1)
+ elif action == ed_glob.ID_PRE_MARK:
+ if self.MarkerGet(lnum):
+ lnum -= 1
+ mark = self.MarkerPrevious(lnum, 1)
+ if mark == -1:
+ mark = self.MarkerPrevious(self.GetLineCount(), 1)
+
+ if mark != -1:
+ self.GotoLine(mark)
+
+ # TODO: DO NOT use these methods anywhere new they will be removed soon
+ def ShowCommandBar(self):
+ """Open the command bar"""
+ self.TopLevelParent.GetEditPane().ShowCommandControl(ed_glob.ID_COMMAND)
+
+ def ShowFindBar(self):
+ """Open the quick-find bar"""
+ self.TopLevelParent.GetEditPane().ShowCommandControl(ed_glob.ID_QUICK_FIND)
+ # END TODO
+
+ def GetBookmarks(self):
+ """Gets a list of all lines containing bookmarks
+ @return: list of line numbers
+
+ """
+ MarkIsSet = ed_marker.Bookmark.IsSet
+ return [line for line in range(self.GetLineCount())
+ if MarkIsSet(self, line)]
+
+ def DoBraceHighlight(self):
+ """Perform a brace matching highlight
+ @note: intended for internal use only
+ """
+ brace_at_caret, brace_opposite = self.GetBracePair()
+ # CallAfter necessary to reduce CG warnings on Mac
+ if brace_at_caret != -1 and brace_opposite == -1:
+ wx.CallAfter(self.BraceBadLight, brace_at_caret)
+ else:
+ wx.CallAfter(self.BraceHighlight, brace_at_caret, brace_opposite)
+
+ def GetBracePair(self, pos=-1):
+ """Get a tuple of the positions in the buffer where the brace at the
+ current caret position and its match are. if a brace doesn't have a
+ match it will return -1 for the missing brace.
+ @keyword pos: -1 to use current cursor pos, else use to specify brace pos
+ @return: tuple (brace_at_caret, brace_opposite)
+
+ """
+ brace_at_caret = -1
+ brace_opposite = -1
+ char_before = None
+ if pos < 0:
+ # use current position
+ caret_pos = self.GetCurrentPos()
+ else:
+ caret_pos = pos
+
+ if caret_pos > 0:
+ char_before = self.GetCharAt(caret_pos - 1)
+
+ # check before
+ if char_before and unichr(char_before) in "[]{}()<>":
+ brace_at_caret = caret_pos - 1
+
+ # check after
+ if brace_at_caret < 0:
+ char_after = self.GetCharAt(caret_pos)
+ if char_after and chr(char_after) in "[]{}()<>":
+ brace_at_caret = caret_pos
+
+ if brace_at_caret >= 0:
+ brace_opposite = self.BraceMatch(brace_at_caret)
+
+ return (brace_at_caret, brace_opposite)
+
+ def Configure(self):
+ """Configures the editors settings by using profile values
+ @postcondition: all profile dependent attributes are configured
+
+ """
+# self.SetControlCharSymbol(172)
+ self.SetWrapMode(_PGET('WRAP', 'bool'))
+ self.SetViewWhiteSpace(_PGET('SHOW_WS', 'bool'))
+ self.SetUseAntiAliasing(_PGET('AALIASING'))
+ self.SetUseTabs(_PGET('USETABS'))
+ self.SetBackSpaceUnIndents(_PGET('BSUNINDENT'))
+ self.SetCaretLineVisible(_PGET('HLCARETLINE'))
+ self.SetIndent(_PGET('INDENTWIDTH', 'int'))
+ self.SetTabWidth(_PGET('TABWIDTH', 'int'))
+# self.SetTabIndents(True) # Add option for this too?
+ self.SetIndentationGuides(_PGET('GUIDES'))
+ self.SetEOLMode(_PGET('EOL_MODE'))
+ self.SetViewEOL(_PGET('SHOW_EOL'))
+ self.SetAutoComplete(_PGET('AUTO_COMP'))
+ self.FoldingOnOff(_PGET('CODE_FOLD'))
+ self.ToggleAutoIndent(_PGET('AUTO_INDENT'))
+ self.ToggleBracketHL(_PGET('BRACKETHL'))
+ self.ToggleLineNumbers(_PGET('SHOW_LN'))
+ self.SetViEmulationMode(_PGET('VI_EMU'), _PGET('VI_NORMAL_DEFAULT'))
+ self.SetViewEdgeGuide(_PGET('SHOW_EDGE'))
+ self.EnableAutoBackup(_PGET('AUTOBACKUP'))
+ self.SetEndAtLastLine(not _PGET('VIEWVERTSPACE', default=False))
+ self.SetCaretWidth(_PGET('CARETWIDTH', default=1))
+
+ def ConvertCase(self, upper=False):
+ """Converts the case of the selected text to either all lower
+ case(default) or all upper case.
+ @keyword upper: Flag whether conversion is to upper case or not.
+
+ """
+ sel = self.GetSelectedText()
+ if upper:
+ sel = sel.upper()
+ else:
+ sel = sel.lower()
+ self.ReplaceSelection(sel)
+
+ def EnableAutoBackup(self, enable):
+ """Enable automatic backups
+ @param enable: bool
+
+ """
+ if enable:
+ # TODO: make backup interval configurable
+ if not self._bktimer.IsRunning():
+ self._bktimer.Start(30000) # every 30 seconds
+ else:
+ if self._bktimer.IsRunning():
+ self._bktimer.Stop()
+
+ def InvertCase(self):
+ """Invert the case of the selected text
+ @postcondition: all text in selection has case inverted
+
+ """
+ text = self.GetSelectedText()
+ if len(text):
+ self.BeginUndoAction()
+ self.ReplaceSelection(text.swapcase())
+ self.EndUndoAction()
+
+ def GetAutoIndent(self):
+ """Returns whether auto-indent is being used
+ @return: whether autoindent is active or not
+
+ """
+ return self._config['autoindent']
+
+ def GetLineStartPosition(self, line):
+ """Get the starting position of the given line
+ @param line: int
+ @return: int
+
+ """
+ if line > 0:
+ spos = self.GetLineEndPosition(line-1)
+ if self.GetLine(line).endswith("\r\n"):
+ spos += 2
+ else:
+ spos += 1
+ else:
+ spos = 0
+ return spos
+
+ def GetLastVisibleLine(self):
+ """Return what the last visible line is
+ @return: int
+
+ """
+ return self.GetFirstVisibleLine() + self.LinesOnScreen() - 1
+
+ def GetMiddleVisibleLine(self):
+ """Return the number of the line that is in the middle of the display
+ @return: int
+
+ """
+ fline = self.GetFirstVisibleLine()
+ if self.LinesOnScreen() < self.GetLineCount():
+ mid = (fline + (self.LinesOnScreen() / 2))
+ else:
+ mid = (fline + (self.GetLineCount() / 2))
+ return mid
+
+ def GotoBraceMatch(self):
+ """Jump the caret to the brace opposite of the one the caret is
+ currently at. If there is no match or the caret currently is not next
+ to a brace no action is taken.
+ @return: bool
+
+ """
+ cbrace, brace_opposite = self.GetBracePair()
+ if -1 in (cbrace, brace_opposite):
+ return False
+ else:
+ self.GotoPos(brace_opposite)
+ return True
+
+ def GotoColumn(self, column):
+ """Move caret to column of current line
+ @param column: Column to move to
+
+ """
+ cline = self.GetCurrentLineNum()
+ lstart = self.PositionFromLine(cline)
+ lend = self.GetLineEndPosition(cline)
+ linelen = lend - lstart
+ if column > linelen:
+ column = linelen
+ self.GotoPos(lstart + column)
+
+ @jumpaction
+ def GotoLine(self, line):
+ """Move caret to beginning given line number
+ @param line: line to go to (int)
+
+ """
+ if line > self.GetLineCount():
+ line = self.GetLineCount()
+ elif line < 0:
+ line = 0
+ else:
+ pass
+
+ self.SetYCaretPolicy(wx.stc.STC_CARET_STRICT, 0)
+ super(EditraStc, self).GotoLine(line)
+ self.SetYCaretPolicy(wx.stc.STC_CARET_EVEN, 0)
+ self.PostPositionEvent()
+
+ @jumpaction
+ def GotoPos(self, pos):
+ """Override StyledTextCtrl.GotoPos
+ @param pos: position in buffer to move caret to (int)
+
+ """
+ super(EditraStc, self).GotoPos(pos)
+ self.PostPositionEvent()
+
+ def SetCaretPos(self, pos):
+ """Set the caret position without posting jump events
+ @param pos: position to go to
+
+ """
+ try:
+ super(EditraStc, self).GotoPos(pos)
+ self.PostPositionEvent()
+ except wx.PyAssertionError:
+ util.Log("[ed_stc][err] SetCaretPos - invalid position %s" % pos)
+
+ def GotoIndentPos(self, line=None):
+ """Move the caret to the end of the indentation
+ on the given line.
+ @param line: line to go to
+
+ """
+ if line is None:
+ line = self.GetCurrentLine()
+ self.GotoPos(self.GetLineIndentPosition(line))
+
+ def SetCurrentCol(self, column):
+ """Set the current column position on the currently line
+ extending the selection.
+ @param column: Column to move to
+
+ """
+ cline = self.GetCurrentLineNum()
+ lstart = self.PositionFromLine(cline)
+ lend = self.GetLineEndPosition(cline)
+ linelen = lend - lstart
+ if column > linelen:
+ column = linelen
+ self.SetCurrentPos(lstart + column)
+
+ def DeleteForward(self):
+ """Delete the selection, or if there is no selection, then
+ delete the character to the right of the cursor.
+
+ """
+ if self.GetSelectionStart() == self.GetSelectionEnd():
+ self.SetCurrentPos(self.GetCurrentPos() + 1)
+ self.DeleteBack()
+
+ def EnableKeyProcessor(self, enable=True):
+ """Enable specialized key handling
+ @keyword enable: bool
+
+ """
+ self.key_handler.EnableProcessing(enable)
+
+ def GetAutoComplete(self):
+ """Is Autocomplete being used by this instance
+ @return: whether autocomp is active or not
+
+ """
+ return self._config['autocomp']
+
+ def OnBackupTimer(self, evt):
+ """Backup the buffer to a backup file.
+ @param evt: wx.TimerEvent
+
+ """
+ fname = self.GetFileName()
+ # If the file is loading or is over 5MB don't do automatic backups.
+ if self.IsLoading() or ebmlib.GetFileSize(fname) > 5242880:
+ return
+
+ # If the file is different than the last save point make the backup.
+ suffix = _PGET('AUTOBACKUP_SUFFIX', default=u'.edbkup')
+ bkupmgr = ebmlib.FileBackupMgr(None, u"%s" + suffix)
+ path = _PGET('AUTOBACKUP_PATH', default=u"")
+ if path and os.path.exists(path):
+ bkupmgr.SetBackupDirectory(path)
+
+ if not self._backup_done and \
+ (not bkupmgr.HasBackup(fname) or bkupmgr.IsBackupNewer(fname)):
+ msg = _("File backup performed: %s") % fname
+ idval = self.Id
+ target = self.TopLevelParent
+ def BackupJob(fobj, text):
+ writer = bkupmgr.GetBackupWriter(fobj)
+ try:
+ writer(text)
+ except Exception, msg:
+ return
+ nevt = ed_event.StatusEvent(ed_event.edEVT_STATUS, idval,
+ msg, ed_glob.SB_INFO)
+ wx.PostEvent(target, nevt)
+ ed_thread.EdThreadPool().QueueJob(BackupJob, self.File, self.GetText())
+ self._backup_done = True
+
+ def OnModified(self, evt):
+ """Overrides base modified handler"""
+ super(EditraStc, self).OnModified(evt)
+ if not self.IsLoading():
+ self._backup_done = False
+
+ def OnKeyDown(self, evt):
+ """Handles keydown events, currently only deals with
+ auto indentation.
+ @param evt: event that called this handler
+
+ """
+ k_code = evt.GetKeyCode()
+ shift_down = evt.ShiftDown()
+ alt_down = evt.AltDown()
+ ctrl_down = evt.ControlDown()
+ cmd_down = evt.CmdDown()
+ if self.key_handler.PreProcessKey(k_code, ctrl_down,
+ cmd_down, shift_down,
+ alt_down):
+ return
+
+ if wx.Platform == '__WXMAC__' and self._MacHandleKey(k_code, shift_down,
+ alt_down, ctrl_down,
+ cmd_down):
+ pass
+ elif k_code == wx.WXK_RETURN:
+ if self._config['autoindent'] and not self.AutoCompActive():
+ if self.GetSelectedText():
+ self.CmdKeyExecute(wx.stc.STC_CMD_NEWLINE)
+ else:
+ self.AutoIndent()
+ else:
+ evt.Skip()
+
+ self.CallTipCancel()
+
+ elif self.VertEdit.Enabled:
+ # XXX: handle column mode
+ self.VertEdit.OnKeyDown(evt)
+ else:
+ evt.Skip()
+
+ def OnChar(self, evt):
+ """Handles Char events that aren't caught by the
+ KEY_DOWN event.
+ @param evt: event that called this handler
+ @todo: autocomp/calltip lookup can be very cpu intensive it may
+ be better to try and process it on a separate thread to
+ prevent a slow down in the input of text into the buffer
+
+ """
+ key_code = evt.GetKeyCode()
+ cpos = self.GetCurrentPos()
+ cmpl = self.GetCompleter()
+ if self.key_handler.ProcessKey(key_code, evt.ControlDown(),
+ evt.CmdDown(), evt.ShiftDown(),
+ evt.AltDown()):
+ # The key handler handled this keypress, we don't need to insert
+ # the character into the buffer.
+ pass
+
+ elif not self._config['autocomp'] or not cmpl.ShouldCheck(cpos):
+ evt.Skip()
+ return
+
+ elif key_code in cmpl.GetAutoCompKeys():
+ self.HidePopups()
+
+ uchr = unichr(key_code)
+ command = self.GetCommandStr() + uchr
+ self.PutText(uchr)
+
+ if self._config['autocomp']:
+ self.ShowAutoCompOpt(command)
+
+ elif key_code in cmpl.GetCallTipKeys():
+ self.HidePopups()
+ uchr = unichr(key_code)
+ command = self.GetCommandStr() + uchr
+ self.PutText(uchr)
+
+ if self._config['autocomp']:
+ self.ShowCallTip(command)
+
+ elif key_code in cmpl.GetCallTipCancel():
+ evt.Skip()
+ self.CallTipCancel()
+# elif key_code == wx.WXK_TAB and \
+# True not in (evt.ControlDown(), evt.CmdDown(),
+# evt.ShiftDown(), evt.AltDown()):
+# self.Tab() # <- So action can be overridden
+ elif wx.Platform == '__WXMAC__' and evt.CmdDown():
+ pass # Hack for issue on OSX where char events are received here
+ else:
+# print "IS TAB", key_code, wx.WXK_TAB
+ evt.Skip()
+
+ def DoAutoComplete(self):
+ """Attempt to perform an autocompletion event."""
+ self.HidePopups()
+ command = self.GetCommandStr()
+ self.ShowAutoCompOpt(command)
+
+ def DoCallTip(self):
+ """Attempt to show a calltip for the current cursor position"""
+ self.HidePopups()
+ command = self.GetCommandStr()
+ # TODO: GetCommandStr seems to be inadequate under some cases
+ self.ShowCallTip(command)
+
+
+ def OnKeyUp(self, evt):
+ """Update status bar of window
+ @param evt: wxEVT_KEY_UP
+
+ """
+ evt.Skip()
+ self.PostPositionEvent()
+ tlw = self.TopLevelParent
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_KEYUP,
+ (evt.GetPositionTuple(), evt.GetKeyCode()), tlw.Id)
+
+ def PostPositionEvent(self):
+ """Post an event to update the status of the line/column"""
+ line, column = self.GetPos()
+ pinfo = dict(lnum=line, cnum=column)
+ msg = _("Line: %(lnum)d Column: %(cnum)d") % pinfo
+ nevt = ed_event.StatusEvent(ed_event.edEVT_STATUS, self.GetId(),
+ msg, ed_glob.SB_ROWCOL)
+ tlw = self.TopLevelParent
+ wx.PostEvent(tlw, nevt)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_POS_CHANGED, pinfo, tlw.Id)
+
+ def OnRecordMacro(self, evt):
+ """Records macro events
+ @param evt: wx.stc.StyledTextEvent
+
+ """
+ if self.IsRecording():
+ msg = evt.GetMessage()
+ if msg == 2170:
+ lparm = self.GetTextRange(self.GetCurrentPos()-1, \
+ self.GetCurrentPos())
+ else:
+ lparm = evt.GetLParam()
+ mac = (msg, evt.GetWParam(), lparm)
+ self._macro.append(mac)
+# if mac[0] != 2170:
+# self._macro.append(mac)
+ else:
+ evt.Skip()
+
+ def ParaDown(self): # pylint: disable-msg=W0221
+ """Move the caret one paragraph down
+ @note: overrides the default function to set caret at end
+ of paragraph instead of jumping to start of next
+
+ """
+ self.WordPartRight()
+ super(EditraStc, self).ParaDown()
+ if self.GetCurrentPos() != self.GetLength():
+ self.WordPartLeft()
+ self.GotoPos(self.GetCurrentPos() + len(self.GetEOLChar()))
+
+ def ParaDownExtend(self): # pylint: disable-msg=W0221
+ """Extend the selection a paragraph down
+ @note: overrides the default function to set selection at end
+ of paragraph instead of jumping to start of next so that
+ extra blank lines don't get swallowed.
+
+ """
+ self.WordRightExtend()
+ super(EditraStc, self).ParaDownExtend()
+ if self.GetCurrentPos() != self.GetLength():
+ self.WordLeftExtend()
+ self.SetCurrentPos(self.GetCurrentPos() + len(self.GetEOLChar()))
+
+ @jumpaction
+ def OnLeftUp(self, evt):
+ """Set primary selection and inform mainwindow that cursor position
+ has changed.
+ @param evt: wx.MouseEvent()
+
+ """
+ evt.Skip()
+ # FIXME: there is problems with using the primary selection. Setting
+ # the primary selection causes anything else on the clipboard
+ # to get killed.
+# stxt = self.GetSelectedText()
+# if len(stxt):
+# util.SetClipboardText(stxt, primary=True)
+ self.PostPositionEvent()
+
+ def OnLoadProgress(self, evt):
+ """Receives file loading events from asynchronous file loading"""
+ pid = self.TopLevelParent.Id
+ if evt.GetState() == ed_txt.FL_STATE_READING:
+ if evt.HasText():
+ # TODO: get gauge updates working properly
+# sb = self.GetTopLevelParent().GetStatusBar()
+# gauge = sb.GetGauge()
+# gauge.SetValue(evt.GetProgress())
+# gauge.Show()
+# gauge.ProcessPendingEvents()
+# sb.ProcessPendingEvents()
+ self.SetReadOnly(False)
+ self.AppendText(evt.GetValue())
+ self.SetSavePoint()
+ self.SetReadOnly(True)
+ # wx.GetApp().Yield(True) # Too slow on windows...
+ elif evt.GetState() == ed_txt.FL_STATE_END:
+ self.SetReadOnly(False)
+ ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (pid, 0, 0))
+ self.SetSavePoint()
+ self.SetUndoCollection(True)
+ del self._loading
+ self._loading = None
+ parent = self.GetParent()
+ if hasattr(parent, 'DoPostLoad'):
+ parent.DoPostLoad()
+ elif evt.GetState() == ed_txt.FL_STATE_START:
+ ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (pid, True))
+ ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (pid, 0, self.File.GetSize()))
+ self.SetReadOnly(True)
+ self.SetUndoCollection(False)
+ elif evt.GetState() == ed_txt.FL_STATE_ABORTED:
+ self.SetReadOnly(False)
+ self.ClearAll()
+
+ def OnUpdateUI(self, evt):
+ """Check for matching braces
+ @param evt: wx.stc.StyledTextEvent
+
+ """
+ # If disabled just skip the event
+ if self._config['brackethl']:
+ self.DoBraceHighlight()
+
+ # XXX: handle when column mode is enabled
+ if self.VertEdit.Enabled:
+ self.VertEdit.OnUpdateUI(evt)
+ evt.Skip()
+
+ def OnUserListSel(self, evt):
+ """Callback hook for userlist selections"""
+ mdata = dict(ltype=evt.GetListType(),
+ text=evt.GetText(),
+ stc=self)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_USERLIST_SEL, mdata,
+ context=self.TopLevelParent.Id)
+ evt.Skip()
+
+ def OnDwellStart(self, evt):
+ """Callback hook for mouse dwell start"""
+ # Workaround issue where this event in incorrectly sent
+ # when the mouse has not dwelled within the buffer area
+ mpoint = wx.GetMousePosition()
+ brect = self.GetScreenRect()
+ if not brect.Contains(mpoint) or \
+ not self.IsShown() or \
+ not self.TopLevelParent.IsActive():
+ return
+
+ position = evt.Position
+ if not self._dwellsent and position >= 0:
+ dwellword = self.GetWordFromPosition(position)[0]
+ line_num = self.LineFromPosition(position) + 1
+ mdata = dict(stc=self, pos=position,
+ line=line_num,
+ word=dwellword)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_DWELL_START, mdata)
+
+ tip = mdata.get('rdata', None)
+ if tip:
+ self.CallTipShow(position, tip)
+ else:
+ # Clients did not need to make use of the calltip
+ # so check if auto-completion provider has anything to display.
+ if not self.IsNonCode(position):
+ endpos = self.WordEndPosition(position, True)
+ col = self.GetColumn(endpos)
+ line = self.GetLine(line_num-1)
+ command = self.GetCommandStr(line, col)
+ tip = self._code['compsvc'].GetCallTip(command)
+ if len(tip):
+ tip_pos = position - (len(dwellword.split('.')[-1]) + 1)
+ fail_safe = position - self.GetColumn(position)
+ self.CallTipShow(max(tip_pos, fail_safe), tip)
+ evt.Skip()
+
+ def OnDwellEnd(self, evt):
+ """Callback hook for mouse dwell end"""
+ self._dwellsent = False
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_DWELL_END)
+ self.CallTipCancel()
+ evt.Skip()
+
+ def OnMarginClick(self, evt):
+ """Open and Close Folders as Needed
+ @param evt: wx.stc.StyledTextEvent
+
+ """
+ margin_num = evt.GetMargin()
+ if margin_num == ed_basestc.FOLD_MARGIN:
+ if evt.GetShift() and \
+ (evt.GetControl() or (wx.Platform == '__WXMAC__' and evt.GetAlt())):
+ self.FoldAll()
+ else:
+ line_clicked = self.LineFromPosition(evt.GetPosition())
+ level = self.GetFoldLevel(line_clicked)
+ if level & wx.stc.STC_FOLDLEVELHEADERFLAG:
+
+ # Expand node and all Subnodes
+ if evt.GetShift():
+ self.SetFoldExpanded(line_clicked, True)
+ self.Expand(line_clicked, True, True, 100, level)
+ elif evt.GetControl() or \
+ (wx.Platform == '__WXMAC__' and evt.GetAlt()):
+ # Contract all subnodes of clicked one
+ # Note: using Alt as Ctrl can not be received for
+ # clicks on mac (Scintilla Bug).
+ if self.GetFoldExpanded(line_clicked):
+ self.SetFoldExpanded(line_clicked, False)
+ self.Expand(line_clicked, False, True, 0, level)
+ else:
+ # Expand all subnodes
+ self.SetFoldExpanded(line_clicked, True)
+ self.Expand(line_clicked, True, True, 100, level)
+ else:
+ self.ToggleFold(line_clicked)
+ elif margin_num == ed_basestc.MARK_MARGIN:
+ # Bookmarks ect...
+ line_clicked = self.LineFromPosition(evt.GetPosition())
+ # Hook for client code to interact with margin clicks
+ data = dict(stc=self, line=line_clicked)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_MARGIN_CLICK, msgdata=data)
+ if not data.get('handled', False):
+ # Default to internal bookmark handling
+ if ed_marker.Bookmark().IsSet(self, line_clicked):
+ self.RemoveBookmark(line_clicked)
+ else:
+ self.AddBookmark(line_clicked)
+
+ def FoldAll(self):
+ """Fold Tree In or Out
+ @postcondition: code tree is folded open or closed
+
+ """
+ line_count = self.GetLineCount()
+ expanding = True
+
+ # find out if we are folding or unfolding
+ for line_num in range(line_count):
+ if self.GetFoldLevel(line_num) & wx.stc.STC_FOLDLEVELHEADERFLAG:
+ expanding = not self.GetFoldExpanded(line_num)
+ break
+ line_num = 0
+
+ while line_num < line_count:
+ level = self.GetFoldLevel(line_num)
+
+ if level & wx.stc.STC_FOLDLEVELHEADERFLAG and \
+ (level & wx.stc.STC_FOLDLEVELNUMBERMASK) == \
+ wx.stc.STC_FOLDLEVELBASE:
+
+ if expanding:
+ self.SetFoldExpanded(line_num, True)
+ line_num = self.Expand(line_num, True) - 1
+ else:
+ last_child = self.GetLastChild(line_num, -1)
+ self.SetFoldExpanded(line_num, False)
+
+ if last_child > line_num:
+ self.HideLines(line_num + 1, last_child)
+ line_num = line_num + 1
+
+ def Expand(self, line, do_expand, force=False, vis_levels=0, level=-1):
+ """Open the Margin Folder
+ @postcondition: the selected folder is expanded
+
+ """
+ last_child = self.GetLastChild(line, level)
+ line = line + 1
+
+ while line <= last_child:
+ if force:
+ if vis_levels > 0:
+ self.ShowLines(line, line)
+ else:
+ self.HideLines(line, line)
+ else:
+ if do_expand:
+ self.ShowLines(line, line)
+
+ if level == -1:
+ level = self.GetFoldLevel(line)
+
+ if level & wx.stc.STC_FOLDLEVELHEADERFLAG:
+ if force:
+ self.SetFoldExpanded(line, vis_levels > 1)
+ line = self.Expand(line, do_expand, force, vis_levels - 1)
+ else:
+ if do_expand:
+ if self.GetFoldExpanded(line):
+ self.SetFoldExpanded(line, True)
+ line = self.Expand(line, do_expand, force, vis_levels - 1)
+ else:
+ line = line + 1
+ return line
+
+ def ExpandAll(self):
+ """Expand all folded code blocks"""
+ line_count = self.GetLineCount()
+ for line_num in xrange(line_count):
+ if self.GetFoldLevel(line_num) & wx.stc.STC_FOLDLEVELHEADERFLAG:
+ if not self.GetFoldExpanded(line_num):
+ self.Expand(line_num, True)
+
+ def FindLexer(self, set_ext=u''):
+ """Sets Text Controls Lexer Based on File Extension
+ @param set_ext: explicit extension to use in search
+ @postcondition: lexer is configured for file
+
+ """
+ if not self._config['highlight']:
+ return 2
+
+ super(EditraStc, self).FindLexer(set_ext)
+
+ # Configure Autocompletion
+ # NOTE: must be done after syntax configuration
+ if self._config['autocomp']:
+ self.ConfigureAutoComp()
+ return 0
+
+ def ControlDispatch(self, evt):
+ """Dispatches events caught from the mainwindow to the
+ proper functions in this module.
+ @param evt: event that was posted to this handler
+
+ """
+ e_id = evt.GetId()
+ e_obj = evt.GetEventObject()
+ e_map = { ed_glob.ID_COPY : self.Copy, ed_glob.ID_CUT : self.Cut,
+ ed_glob.ID_PASTE : self.Paste, ed_glob.ID_UNDO : self.Undo,
+ ed_glob.ID_REDO : self.Redo, ed_glob.ID_INDENT : self.Tab,
+ ed_glob.ID_REVERT_FILE : self.RevertToSaved,
+ ed_glob.ID_CUT_LINE : self.LineCut,
+ ed_glob.ID_DELETE_LINE : self.LineDelete,
+ ed_glob.ID_COLUMN_MODE : self.ToggleColumnMode,
+ ed_glob.ID_COPY_LINE : self.LineCopy,
+ ed_glob.ID_DUP_LINE : self.LineDuplicate,
+ ed_glob.ID_BRACKETHL : self.ToggleBracketHL,
+ ed_glob.ID_SYNTAX : self.SyntaxOnOff,
+ ed_glob.ID_UNINDENT : self.BackTab,
+ ed_glob.ID_TRANSPOSE : self.LineTranspose,
+ ed_glob.ID_LINE_MOVE_UP : self.LineMoveUp,
+ ed_glob.ID_LINE_MOVE_DOWN : self.LineMoveDown,
+ ed_glob.ID_SELECTALL: self.SelectAll,
+ ed_glob.ID_FOLDING : self.FoldingOnOff,
+ ed_glob.ID_SHOW_LN : self.ToggleLineNumbers,
+ ed_glob.ID_TOGGLECOMMENT : self.ToggleComment,
+ ed_glob.ID_AUTOINDENT : self.ToggleAutoIndent,
+ ed_glob.ID_LINE_AFTER : self.AddLine,
+ ed_glob.ID_TOGGLE_FOLD : self.ToggleFold,
+ ed_glob.ID_TOGGLE_ALL_FOLDS : self.FoldAll,
+ ed_glob.ID_TRIM_WS : self.TrimWhitespace,
+ ed_glob.ID_MACRO_START : self.StartRecord,
+ ed_glob.ID_MACRO_STOP : self.StopRecord,
+ ed_glob.ID_MACRO_PLAY : self.PlayMacro,
+ ed_glob.ID_GOTO_MBRACE : self.GotoBraceMatch,
+ ed_glob.ID_SHOW_AUTOCOMP : self.DoAutoComplete,
+ ed_glob.ID_SHOW_CALLTIP : self.DoCallTip
+ }
+
+ e_idmap = { ed_glob.ID_ZOOM_OUT : self.DoZoom,
+ ed_glob.ID_ZOOM_IN : self.DoZoom,
+ ed_glob.ID_ZOOM_NORMAL : self.DoZoom,
+ ed_glob.ID_EOL_MAC : self.ConvertLineMode,
+ ed_glob.ID_EOL_UNIX : self.ConvertLineMode,
+ ed_glob.ID_EOL_WIN : self.ConvertLineMode,
+ ed_glob.ID_SPACE_TO_TAB : self.ConvertWhitespace,
+ ed_glob.ID_TAB_TO_SPACE : self.ConvertWhitespace,
+ ed_glob.ID_NEXT_MARK : self.Bookmark,
+ ed_glob.ID_PRE_MARK : self.Bookmark,
+ ed_glob.ID_ADD_BM : self.Bookmark,
+ ed_glob.ID_DEL_ALL_BM : self.Bookmark}
+
+ # Hide autocomp popups
+ self.HidePopups()
+
+ if e_obj.GetClassName() == "wxToolBar" or e_id in e_map:
+ if e_id in e_map:
+ e_map[e_id]()
+ return
+
+ if e_id in e_idmap:
+ e_idmap[e_id](e_id)
+ elif e_id == ed_glob.ID_SHOW_EDGE:
+ self.SetViewEdgeGuide(not self.GetEdgeMode())
+ elif e_id == ed_glob.ID_SHOW_EOL:
+ self.SetViewEOL(not self.GetViewEOL())
+ elif e_id == ed_glob.ID_PASTE_AFTER:
+ cpos = self.GetCurrentPos()
+ self.Paste()
+ self.SetCurrentPos(cpos)
+ self.SetSelection(cpos, cpos)
+ elif e_id == ed_glob.ID_SHOW_WS:
+ self.SetViewWhiteSpace(not self.GetViewWhiteSpace())
+ elif e_id == ed_glob.ID_WORD_WRAP:
+ self.SetWrapMode(not self.GetWrapMode())
+ elif e_id == ed_glob.ID_JOIN_LINES:
+ self.LinesJoinSelected()
+ elif e_id == ed_glob.ID_INDENT_GUIDES:
+ self.SetIndentationGuides(not bool(self.GetIndentationGuides()))
+ elif e_id == ed_glob.ID_HLCARET_LINE:
+ self.SetCaretLineVisible(not self.GetCaretLineVisible())
+ elif e_id in syntax.SYNTAX_IDS:
+ f_ext = syntax.GetExtFromId(e_id)
+ self.LOG("[ed_stc][evt] Manually Setting Lexer to %s" % str(f_ext))
+ self.FindLexer(f_ext)
+ elif e_id == ed_glob.ID_AUTOCOMP:
+ self.SetAutoComplete(not self.GetAutoComplete())
+ elif e_id == ed_glob.ID_LINE_BEFORE:
+ self.AddLine(before=True)
+ elif e_id in [ed_glob.ID_TO_UPPER, ed_glob.ID_TO_LOWER]:
+ self.ConvertCase(e_id == ed_glob.ID_TO_UPPER)
+ elif e_id == ed_glob.ID_USE_SOFTTABS:
+ self.SetUseTabs(not self.GetUseTabs())
+ else:
+ evt.Skip()
+
+ def CheckEOL(self):
+ """Checks the EOL mode of the opened document. If the mode
+ that the document was saved in is different than the editors
+ current mode the editor will switch modes to preserve the eol
+ type of the file, if the eol chars are mixed then the editor
+ will toggle on eol visibility.
+ @postcondition: eol mode is configured to best match file
+ @todo: Is showing line endings the best way to show mixed?
+
+ """
+ mixed = diff = False
+ eol_map = {u"\n" : wx.stc.STC_EOL_LF,
+ u"\r\n" : wx.stc.STC_EOL_CRLF,
+ u"\r" : wx.stc.STC_EOL_CR}
+
+ eol = unichr(self.GetCharAt(self.GetLineEndPosition(0)))
+ if eol == u"\r":
+ tmp = unichr(self.GetCharAt(self.GetLineEndPosition(0) + 1))
+ if tmp == u"\n":
+ eol += tmp
+
+ # Is the eol used in the document the same as what is currently set.
+ if eol != self.GetEOLChar():
+ diff = True
+
+ # Check the lines to see if they are all matching or not.
+ LEPFunct = self.GetLineEndPosition
+ GCAFunct = self.GetCharAt
+ for line in range(self.GetLineCount() - 1):
+ end = LEPFunct(line)
+ tmp = unichr(GCAFunct(end))
+ if tmp == u"\r":
+ tmp2 = unichr(GCAFunct(LEPFunct(0) + 1))
+ if tmp2 == u"\n":
+ tmp += tmp2
+ if tmp != eol:
+ mixed = True
+ break
+
+ if mixed or diff:
+ if mixed:
+ # Warn about mixed end of line characters and offer to convert
+ msg = _("Mixed EOL characters detected.\n\n"
+ "Would you like to format them to all be the same?")
+ dlg = ed_mdlg.EdFormatEOLDlg(self.TopLevelParent, msg,
+ _("Format EOL?"),
+ eol_map.get(eol, self.GetEOLMode()))
+
+ if dlg.ShowModal() == wx.ID_YES:
+ sel = dlg.GetSelection()
+ self.ConvertEOLs(sel)
+ super(EditraStc, self).SetEOLMode(sel)
+ dlg.Destroy()
+ else:
+ # The end of line character is different from the preferred
+ # user setting for end of line. So change our eol mode to
+ # preserve that of what the document is using.
+ mode = eol_map.get(eol, wx.stc.STC_EOL_LF)
+ super(EditraStc, self).SetEOLMode(mode)
+ else:
+ pass
+
+ def ConvertLineMode(self, mode_id):
+ """Converts all line endings in a document to a specified
+ format.
+ @param mode_id: (menu) id of eol mode to set
+
+ """
+ eol_map = { ed_glob.ID_EOL_MAC : wx.stc.STC_EOL_CR,
+ ed_glob.ID_EOL_UNIX : wx.stc.STC_EOL_LF,
+ ed_glob.ID_EOL_WIN : wx.stc.STC_EOL_CRLF
+ }
+ self.ConvertEOLs(eol_map[mode_id])
+ super(EditraStc, self).SetEOLMode(eol_map[mode_id])
+
+ def ConvertWhitespace(self, mode_id):
+ """Convert whitespace from using tabs to spaces or visa versa
+ @param mode_id: id of conversion mode
+
+ """
+ if mode_id not in (ed_glob.ID_TAB_TO_SPACE, ed_glob.ID_SPACE_TO_TAB):
+ return
+ tabw = self.GetIndent()
+ pos = self.GetCurrentPos()
+ sel = self.GetSelectedText()
+ if mode_id == ed_glob.ID_TAB_TO_SPACE:
+ cmd = (u"\t", u" " * tabw)
+ tabs = False
+ else:
+ cmd = (" " * tabw, u"\t")
+ tabs = True
+
+ if sel != wx.EmptyString:
+ self.ReplaceSelection(sel.replace(cmd[0], cmd[1]))
+ else:
+ self.BeginUndoAction()
+ part1 = self.GetTextRange(0, pos).replace(cmd[0], cmd[1])
+ tmptxt = self.GetTextRange(pos, self.GetLength()).replace(cmd[0], \
+ cmd[1])
+ self.SetText(part1 + tmptxt)
+ self.GotoPos(len(part1))
+ self.SetUseTabs(tabs)
+ self.EndUndoAction()
+
+ def GetCurrentLineNum(self):
+ """Return the number of the line that the caret is currently at
+ @return: Line number (int)
+
+ """
+ return self.LineFromPosition(self.GetCurrentPos())
+
+ def GetEOLModeId(self):
+ """Gets the id of the eol format. Convenience for updating
+ menu ui.
+ @return: id of the eol mode of this document
+
+ """
+ eol_map = { wx.stc.STC_EOL_CR : ed_glob.ID_EOL_MAC,
+ wx.stc.STC_EOL_LF : ed_glob.ID_EOL_UNIX,
+ wx.stc.STC_EOL_CRLF : ed_glob.ID_EOL_WIN
+ }
+ return eol_map.get(self.GetEOLMode(), ed_glob.ID_EOL_UNIX)
+
+ def IsBracketHlOn(self):
+ """Returns whether bracket highlighting is being used by this
+ control or not.
+ @return: status of bracket highlight activation
+
+ """
+ return self._config['brackethl']
+
+ def IsFoldingOn(self):
+ """Returns whether code folding is being used by this
+ control or not.
+ @return: whether folding is on or not
+
+ """
+ return self._config['folding']
+
+ def IsHighlightingOn(self):
+ """Returns whether syntax highlighting is being used by this
+ control or not.
+ @return: whether syntax highlighting is on or not
+
+ """
+ return self._config['highlight']
+
+ def IsLoading(self):
+ """Is a background thread loading the text into the file
+ @return: bool
+
+ """
+ # NOTE: keep the getattr check here some cases
+ # are reporting a yet unexplainable AttributeError here
+ return getattr(self, '_loading', None) is not None
+
+ def IsRecording(self):
+ """Returns whether the control is in the middle of recording
+ a macro or not.
+ @return: whether recording macro or not
+
+ """
+ return self.recording
+
+ def GetSelectionLineStartEnd(self):
+ """Get the start and end positions of the lines in the current
+ fuzzy selection.
+ @return: tuple (int, int)
+
+ """
+ sline = self.LineFromPosition(self.GetSelectionStart())
+ eline = self.LineFromPosition(self.GetSelectionEnd())
+ last_line = self.GetLineCount() - 1
+ eol_len = len(self.GetEOLChar())
+ if sline < eline:
+ tstart = self.GetLineStartPosition(sline)
+ tend = self.GetLineEndPosition(eline)
+ else:
+ tstart = self.GetLineStartPosition(eline)
+ tend = self.GetLineEndPosition(sline)
+
+ if eline == last_line and tstart != 0:
+ tstart -= eol_len
+ else:
+ tend += eol_len
+
+ return (max(tstart, 0), min(tend, self.GetLength()))
+
+ def LineCut(self): # pylint: disable-msg=W0221
+ """Cut the selected lines into the clipboard"""
+ start, end = self.GetSelectionLineStartEnd()
+ self.BeginUndoAction()
+ self.BaseSetSelection(start, end)
+ self.Cut()
+ self.EndUndoAction()
+
+ def LineDelete(self): # pylint: disable-msg=W0221
+ """Delete the selected lines without modifying the clipboard"""
+ start, end = self.GetSelectionLineStartEnd()
+ self.BeginUndoAction()
+ self.SetTargetStart(start)
+ self.SetTargetEnd(end)
+ self.ReplaceTarget(u'')
+ self.EndUndoAction()
+
+ def LinesJoin(self): # pylint: disable-msg=W0221
+ """Join lines in target and compress whitespace
+ @note: overrides default function to allow for leading
+ whitespace in joined lines to be compressed to 1 space
+
+ """
+ sline = self.LineFromPosition(self.GetTargetStart())
+ eline = self.LineFromPosition(self.GetTargetEnd())
+ if not eline:
+ eline = 1
+ lines = list()
+ for line in xrange(sline, eline + 1):
+ if line != sline:
+ tmp = self.GetLine(line).strip()
+ else:
+ tmp = self.GetLine(line)
+ if not tmp.isspace():
+ tmp = tmp.rstrip()
+ else:
+ tmp = tmp.replace("\n", u'').replace("\r", u'')
+ if len(tmp):
+ lines.append(tmp)
+ self.SetTargetStart(self.PositionFromLine(sline))
+ self.SetTargetEnd(self.GetLineEndPosition(eline))
+ self.ReplaceTarget(u' '.join(lines))
+
+ def LinesJoinSelected(self):
+ """Similar to LinesJoin, but operates on selection
+ @see: LinesJoin
+
+ """
+ self.SetTargetStart(self.GetSelectionStart())
+ self.SetTargetEnd(self.GetSelectionEnd())
+ self.LinesJoin()
+
+ def LineMoveUp(self):
+ """Move the current line up"""
+ linenum = self.GetCurrentLine()
+ if linenum > 0 :
+ self.BeginUndoAction()
+ self.LineTranspose()
+ self.LineUp()
+ self.EndUndoAction()
+
+ def LineMoveDown(self):
+ """Move the current line down"""
+ linenum = self.GetCurrentLine()
+ col = self.GetColumn(self.GetCurrentPos())
+ if linenum < self.GetLineCount() - 1:
+ self.BeginUndoAction()
+ self.LineDown()
+ self.LineTranspose()
+ self.GotoColumn(col)
+ self.EndUndoAction()
+
+ def LineTranspose(self): # pylint: disable-msg=W0221
+ """Switch the current line with the previous one
+ @note: overrides base stc method to do transpose in single undo action
+
+ """
+ self.BeginUndoAction()
+ super(EditraStc, self).LineTranspose()
+ self.EndUndoAction()
+
+ def SetAutoComplete(self, value):
+ """Turns Autocompletion on and off
+ @param value: use autocomp or not
+
+ """
+ if isinstance(value, bool):
+ self._config['autocomp'] = value
+ if value:
+ self.InitCompleter()
+
+ def SetEOLMode(self, mode):
+ """Sets the EOL mode from a string description
+ @param mode: eol mode to set
+ @note: overrides StyledTextCtrl.SetEOLMode
+
+ """
+ mode_map = { EDSTC_EOL_CR : wx.stc.STC_EOL_CR,
+ EDSTC_EOL_LF : wx.stc.STC_EOL_LF,
+ EDSTC_EOL_CRLF : wx.stc.STC_EOL_CRLF
+ }
+
+ mode = mode_map.get(mode, wx.stc.STC_EOL_LF)
+ super(EditraStc, self).SetEOLMode(mode)
+
+ def SetViEmulationMode(self, use_vi, use_normal=False):
+ """Activate/Deactivate Vi emulation mode
+ @param use_vi: Turn vi emulation on/off
+ @keyword use_normal: Start in normal mode
+
+ """
+ self.key_handler.ClearMode()
+ if use_vi:
+ self.key_handler = ViKeyHandler(self, use_normal)
+ else:
+ self.key_handler = KeyHandler(self)
+
+ def SetViewEdgeGuide(self, switch=None):
+ """Toggles the visibility of the edge guide
+ @keyword switch: force a particular setting
+
+ """
+ if (switch is None and not self.GetEdgeMode()) or switch:
+ self.SetEdgeColumn(_PGET("EDGE", 'int', 80))
+ self.SetEdgeMode(wx.stc.STC_EDGE_LINE)
+ else:
+ self.SetEdgeMode(wx.stc.STC_EDGE_NONE)
+
+ def StartRecord(self): # pylint: disable-msg=W0221
+ """Starts recording all events
+ @return: None
+
+ """
+ self.recording = True
+ evt = ed_event.StatusEvent(ed_event.edEVT_STATUS, self.GetId(),
+ _("Recording Macro") + u"...",
+ ed_glob.SB_INFO)
+ wx.PostEvent(self.TopLevelParent, evt)
+ super(EditraStc, self).StartRecord()
+
+ def StopRecord(self): # pylint: disable-msg=W0221
+ """Stops the recording and builds the macro script
+ @postcondition: macro recording is stopped
+
+ """
+ self.recording = False
+ super(EditraStc, self).StopRecord()
+ evt = ed_event.StatusEvent(ed_event.edEVT_STATUS, self.GetId(),
+ _("Recording Finished"),
+ ed_glob.SB_INFO)
+ wx.PostEvent(self.TopLevelParent, evt)
+ self._BuildMacro()
+
+ def TrimWhitespace(self):
+ """Trims trailing whitespace from all lines in the document.
+ @postcondition: all trailing whitespace is removed from document
+
+ """
+ cpos = self.GetCurrentPos()
+ cline = self.GetCurrentLine()
+ cline_len = len(self.GetLine(cline))
+ epos = cline_len - (self.GetLineEndPosition(cline) - cpos)
+
+ # Begin stripping trailing whitespace
+ self.BeginUndoAction()
+ for line in xrange(self.GetLineCount()):
+ eol = u''
+ tmp = self.GetLine(line)
+
+ # Scintilla stores text in utf8 internally so we need to
+ # encode to utf8 to get the correct length of the text.
+ try:
+ tlen = len(tmp.encode('utf-8'))
+ except:
+ tlen = len(tmp)
+
+ if tlen:
+ if "\r\n" in tmp:
+ eol = "\r\n"
+ elif "\n" in tmp:
+ eol = "\n"
+ else:
+ eol = tmp[-1]
+
+ if not eol.isspace():
+ continue
+ elif eol in u' \t':
+ eol = u''
+ else:
+ continue
+
+ # Strip the extra whitespace from the line
+ end = self.GetLineEndPosition(line) + len(eol)
+ start = max(end - tlen, 0)
+ self.SetTargetStart(start)
+ self.SetTargetEnd(end)
+ rtxt = tmp.rstrip() + eol
+ if rtxt != self.GetTextRange(start, end):
+ self.ReplaceTarget(tmp.rstrip() + eol)
+ self.EndUndoAction()
+
+ # Restore carat position
+ cline_len = len(self.GetLine(cline))
+ end = self.GetLineEndPosition(cline)
+ if epos >= cline_len:
+ epos = end
+ else:
+ start = max(end - cline_len, 0)
+ epos += start
+
+ if epos != cpos:
+ self.GotoPos(epos)
+
+ def FoldingOnOff(self, switch=None):
+ """Turn code folding on and off
+ @keyword switch: force a particular setting
+
+ """
+ if (switch is None and not self._config['folding']) or switch:
+ self.LOG("[ed_stc][evt] Code Folding Turned On")
+ self._config['folding'] = True
+ self.SetMarginWidth(ed_basestc.FOLD_MARGIN, 12)
+ self.SetProperty("fold", "1")
+ else:
+ self.LOG("[ed_stc][evt] Code Folding Turned Off")
+ self._config['folding'] = False
+
+ # Ensure all code blocks have been expanded
+ self.ExpandAll()
+
+ self.SetMarginWidth(ed_basestc.FOLD_MARGIN, 0)
+ self.SetProperty("fold", "0")
+
+ def SyntaxOnOff(self, switch=None):
+ """Turn Syntax Highlighting on and off
+ @keyword switch: force a particular setting
+
+ """
+ if (switch is None and not self._config['highlight']) or switch:
+ self.LOG("[ed_stc][evt] Syntax Highlighting Turned On")
+ self._config['highlight'] = True
+ self.FindLexer()
+ else:
+ self.LOG("[ed_stc][evt] Syntax Highlighting Turned Off")
+ self._config['highlight'] = False
+ self.SetLexer(wx.stc.STC_LEX_NULL)
+ self.ClearDocumentStyle()
+ self.UpdateBaseStyles()
+ return 0
+
+ def Tab(self): # pylint: disable-msg=W0221
+ """Override base method to ensure that folded blocks get unfolded
+ prior to changing the indentation.
+
+ """
+ # TODO: unfolding of folded blocks during block indent
+# lines = list()
+# if self.HasSelection():
+# sel = self.GetSelection()
+# sline = self.LineFromPosition(sel[0])
+# eline = self.LineFromPosition(sel[1])
+# lines = range(sline, eline+1)
+# else:
+# cline = self.GetCurrentLine()
+# lines = [cline, cline+1]
+
+# for line_num in lines:
+# if self.GetFoldLevel(line_num) & wx.stc.STC_FOLDLEVELHEADERFLAG:
+# if not self.GetFoldExpanded(line_num):
+# self.Expand(line_num, True)
+ super(EditraStc, self).Tab()
+
+ def ToggleAutoIndent(self, switch=None):
+ """Toggles Auto-indent On and Off
+ @keyword switch: force a particular setting
+
+ """
+ if (switch is None and not self._config['autoindent']) or switch:
+ self._config['autoindent'] = True
+ else:
+ self._config['autoindent'] = False
+
+ def ToggleBracketHL(self, switch=None):
+ """Toggle Bracket Highlighting On and Off
+ @keyword switch: force a particular setting
+
+ """
+ if (switch is None and not self._config['brackethl']) or switch:
+ self.LOG("[ed_stc][evt] Bracket Highlighting Turned On")
+ self._config['brackethl'] = True
+ # Make sure to highlight a brace if next to on when turning it on
+ self.DoBraceHighlight()
+ else:
+ self.LOG("[ed_stc][evt] Bracket Highlighting Turned Off")
+ self._config['brackethl'] = False
+ # Make sure that if there was a highlighted brace it gets cleared
+ wx.CallAfter(self.BraceHighlight, -1, -1)
+
+ def ToggleFold(self, lineNum=None):
+ """Toggle the fold at the given line number. If lineNum is
+ None then the fold closest cursors current postions.
+ @keyword lineNum: int
+
+ """
+ if lineNum is None:
+ lineNum = self.GetCurrentLine()
+ super(EditraStc, self).ToggleFold(lineNum)
+
+ @jumpaction
+ def WordLeft(self): # pylint: disable-msg=W0221
+ """Move caret to beginning of previous word
+ @note: override builtin to include extra characters in word
+
+ """
+ self.SetWordChars(NONSPACE)
+ super(EditraStc, self).WordLeft()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos + 1) in SPACECHARS:
+ super(EditraStc, self).WordLeft()
+ self.SetWordChars('')
+
+ def WordLeftExtend(self): # pylint: disable-msg=W0221
+ """Extend selection to beginning of previous word
+ @note: override builtin to include extra characters in word
+
+ """
+ self.SetWordChars(NONSPACE)
+ super(EditraStc, self).WordLeftExtend()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos + 1) in SPACECHARS:
+ super(EditraStc, self).WordLeftExtend()
+ self.SetWordChars('')
+
+ @jumpaction
+ def WordPartLeft(self): # pylint: disable-msg=W0221
+ """Move the caret left to the next change in capitalization/punctuation
+ @note: overrides default function to not count whitespace as words
+
+ """
+ super(EditraStc, self).WordPartLeft()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos + 1) in SPACECHARS:
+ super(EditraStc, self).WordPartLeft()
+
+ def WordPartLeftExtend(self): # pylint: disable-msg=W0221
+ """Extend selection left to the next change in c
+ apitalization/punctuation.
+ @note: overrides default function to not count whitespace as words
+
+ """
+ super(EditraStc, self).WordPartLeftExtend()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos + 1) in SPACECHARS:
+ super(EditraStc, self).WordPartLeftExtend()
+
+ @jumpaction
+ def WordPartRight(self): # pylint: disable-msg=W0221
+ """Move the caret to the start of the next word part to the right
+ @note: overrides default function to exclude white space
+
+ """
+ super(EditraStc, self).WordPartRight()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos + 1) in SPACECHARS:
+ super(EditraStc, self).WordPartRight()
+
+ @jumpaction
+ def WordPartRightEnd(self): # pylint: disable-msg=W0221
+ """Move caret to end of next change in capitalization/punctuation
+ @postcondition: caret is moved
+
+ """
+ super(EditraStc, self).WordPartRight()
+ super(EditraStc, self).WordPartRight()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos - 1) in SPACECHARS:
+ self.CharLeft()
+
+ def WordPartRightEndExtend(self): # pylint: disable-msg=W0221
+ """Extend selection to end of next change in capitalization/punctuation
+ @postcondition: selection is extended
+
+ """
+ super(EditraStc, self).WordPartRightExtend()
+ super(EditraStc, self).WordPartRightExtend()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos - 1) in SPACECHARS:
+ self.CharLeftExtend()
+
+ def WordPartRightExtend(self): # pylint: disable-msg=W0221
+ """Extend selection to start of next change in
+ capitalization/punctuation
+ @postcondition: selection is extended
+
+ """
+ super(EditraStc, self).WordPartRightExtend()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos + 1) in SPACECHARS:
+ super(EditraStc, self).WordPartRightExtend()
+
+ @jumpaction
+ def WordRight(self): # pylint: disable-msg=W0221
+ """Move caret to beginning of next word
+ @note: override builtin to include extra characters in word
+
+ """
+ self.SetWordChars(NONSPACE)
+ super(EditraStc, self).WordRight()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos + 1) in SPACECHARS:
+ super(EditraStc, self).WordRight()
+ self.SetWordChars('')
+
+ @jumpaction
+ def WordRightEnd(self): # pylint: disable-msg=W0221
+ """Move caret to end of next change in word
+ @note: override builtin to include extra characters in word
+
+ """
+ self.SetWordChars(NONSPACE)
+ super(EditraStc, self).WordRightEnd()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos - 1) in SPACECHARS:
+ super(EditraStc, self).WordRightEnd()
+ self.SetWordChars('')
+
+ def WordRightExtend(self): # pylint: disable-msg=W0221
+ """Extend selection to beginning of next word
+ @note: override builtin to include extra characters in word
+
+ """
+ self.SetWordChars(NONSPACE)
+ super(EditraStc, self).WordRightExtend()
+ cpos = self.GetCurrentPos()
+ if self.GetTextRange(cpos, cpos + 1) in SPACECHARS:
+ super(EditraStc, self).WordRightExtend()
+ self.SetWordChars('')
+
+ def LoadFile(self, path):
+ """Load the file at the given path into the buffer. Returns
+ True if no errors and False otherwise. To retrieve the errors
+ check the last error that was set in the file object returned by
+ L{GetDocument}.
+ @param path: path to file
+
+ """
+ fsize = ebmlib.GetFileSize(path)
+ if fsize < 1048576: # 1MB
+ return super(EditraStc, self).LoadFile(path)
+ else:
+ ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENING, path)
+ self.file.SetPath(path)
+ self._loading = wx.BusyCursor()
+ self.file.ReadAsync(self)
+ return True
+
+ def ReloadFile(self):
+ """Reloads the current file, returns True on success and
+ False if there is a failure.
+ @return: whether file was reloaded or not
+
+ """
+ cfile = self.GetFileName()
+ if os.path.exists(cfile):
+ try:
+ self.BeginUndoAction()
+ marks = self.GetBookmarks()
+ cpos = self.GetCurrentPos()
+ # TODO: Handle async re-loads of large files
+ txt = self.File.Read()
+ self.SetReadOnly(False)
+ if txt is not None:
+ if self.File.IsRawBytes() and not ebmlib.IsUnicode(txt):
+ self.AddStyledText(txt)
+ self.SetReadOnly(True) # Don't allow editing of raw bytes
+ else:
+ self.SetText(txt)
+ else:
+ return False, _("Failed to reload: %s") % cfile
+
+ self.SetModTime(ebmlib.GetFileModTime(cfile))
+ for mark in marks:
+ self.AddBookmark(mark)
+ self.EndUndoAction()
+ self.SetSavePoint()
+ except (UnicodeDecodeError, AttributeError, OSError, IOError), msg:
+ self.LOG("[ed_stc][err] Failed to Reload %s" % cfile)
+ return False, msg
+ else:
+ self.GotoPos(cpos)
+ context = self.TopLevelParent.Id
+ ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENED,
+ self.GetFileName(), context)
+ return True, ''
+ else:
+ self.LOG("[ed_stc][err] %s does not exists, cant reload." % cfile)
+ return False, _("%s does not exist") % cfile
+
+ def RevertFile(self):
+ """Revert all the changes made to the file since it was opened
+ @postcondition: undo history is re-wound to initial state and file
+ is re-saved if it has an on disk file.
+
+ """
+ with eclib.Freezer(self) as _tmp:
+ while self.CanUndo():
+ self.Undo()
+
+ fname = self.GetFileName()
+ if len(fname):
+ self.SaveFile(fname)
+
+ def RevertToSaved(self):
+ """Revert the current buffer back to the last save point"""
+ with eclib.Freezer(self) as _tmp:
+ while self.CanUndo():
+ if self.GetModify():
+ self.Undo()
+ else:
+ break
+
+ def SaveFile(self, path):
+ """Save buffers contents to disk
+ @param path: path of file to save
+ @return: whether file was written or not
+
+ """
+ result = True
+ try:
+ tlw_id = self.TopLevelParent.Id
+ ed_msg.PostMessage(ed_msg.EDMSG_FILE_SAVE,
+ (path, self.GetLangId()), tlw_id)
+ self.File.SetPath(path)
+ self.LOG("[ed_stc][info] Writing file %s, with encoding %s" % \
+ (path, self.File.GetEncoding()))
+
+ if _PGET('AUTO_TRIM_WS', 'bool', False):
+ self.TrimWhitespace()
+
+ if self.File.IsReadOnly():
+ wx.MessageBox(_("File is Read Only and cannot be saved"),
+ _("Read Only"),
+ style=wx.OK|wx.CENTER|wx.ICON_WARNING)
+ return True
+ else:
+ if not self.File.IsRawBytes():
+ self.File.Write(self.GetText())
+ else:
+ nchars = self.GetTextLength()
+ txt = self.GetStyledText(0, nchars)[0:nchars*2:2]
+ self.File.Write(txt)
+ except Exception, msg:
+ result = False
+ self.LOG("[ed_stc][err] There was an error saving %s" % path)
+ self.LOG("[ed_stc][err] ERROR: %s" % str(msg))
+
+ if result:
+ self.SetSavePoint()
+ self.SetModTime(ebmlib.GetFileModTime(path))
+ self.File.FireModified()
+ self.SetFileName(path)
+
+ wx.CallAfter(ed_msg.PostMessage,
+ ed_msg.EDMSG_FILE_SAVED,
+ (path, self.GetLangId()),
+ tlw_id)
+
+ return result
+
+ def ConfigureLexer(self, file_ext):
+ """Sets Lexer and Lexer Keywords for the specified file extension
+ @param file_ext: a file extension to configure the lexer from
+
+ """
+ super(EditraStc, self).ConfigureLexer(file_ext)
+
+ if not self._config['folding']:
+ self.SetProperty("fold", "0")
+
+ # Notify that lexer has changed
+ pid = self.TopLevelParent.Id
+ self.LOG("[ed_stc][info] Lexer change notification for context %d" % pid)
+ ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_LEXER,
+ (self.GetFileName(), self.GetLangId()), pid)
+ return True
+
+ def HideCaret(self):
+ if hasattr(self, 'SetCaretStyle'):
+ self.SetCaretStyle(wx.stc.STC_CARETSTYLE_INVISIBLE)
+ else:
+ self.SetCaretWidth(0)
+
+ def RestoreCaret(self):
+ if self.key_handler.BlockMode:
+ self.SetBlockCaret()
+ else:
+ self.SetLineCaret()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_style.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_style.py
new file mode 100644
index 0000000..6e8f60d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_style.py
@@ -0,0 +1,1087 @@
+###############################################################################
+# Name: ed_style.py #
+# Purpose: Editra's style management system. Implements the interpretation of #
+# Editra Style Sheets to the StyledTextCtrl. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008-2011 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides a system for managing styles in the text control. Compiles the data
+in an Editra Style Sheet to a format that Scintilla can understand. The
+specification of Editra Style Sheets that this module implements can be found
+either in the _docs_ folder of the source distribution or on Editra's home page
+U{http://editra.org/editra_style_sheets}.
+
+@summary: Style management system for managing the syntax highlighting of all
+ buffers
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_style.py 72388 2012-08-28 16:06:31Z CJP $"
+__revision__ = "$Revision: 72388 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import re
+import wx
+
+# Editra Libraries
+import ed_glob
+import util
+from profiler import Profile_Get, Profile_Set
+import eclib
+import ebmlib
+
+# Globals
+STY_ATTRIBUTES = (u"face", u"fore", u"back", u"size", u"modifiers")
+STY_EX_ATTRIBUTES = (u"eol", u"bold", u"italic", u"underline")
+
+# Parser Values
+RE_ESS_COMMENT = re.compile("\/\*[^*]*\*+([^/][^*]*\*+)*\/")
+RE_ESS_SCALAR = re.compile("\%\([a-zA-Z0-9]+\)")
+RE_HEX_STR = re.compile("#[0-9a-fA-F]{3,6}")
+
+#--------------------------------------------------------------------------#
+
+class StyleItem(object):
+ """A storage class for holding styling information """
+ __slots__ = ('null', 'fore', 'face', 'back', 'size', '_exattr')
+ def __init__(self, fore=u"", back=u"", face=u"", size=u"", ex=None):
+ """Initializes the Style Object.
+
+ @keyword fore: Specifies the foreground color (hex string)
+ @keyword face: Specifies the font face (string face name)
+ @keyword back: Specifies the background color (hex string)
+ @keyword size: Specifies font point size (int/formatted string)
+ @keyword ex: Specify modifiers
+
+ SPECIFICATION:
+ - DATA FORMATS:
+ - #123456 = hex color code
+ - Monaco = Font Face Name
+ - %(primary)s = Format string to be swapped at runtime
+ - 10 = A font point size
+ - %(size)s = Format string to be swapped at runtime
+ - ex = bold underline italic eol
+
+ """
+ super(StyleItem, self).__init__()
+
+ if ex is None:
+ ex = list()
+
+ # Attributes
+ self.null = False
+ self.fore = fore # Foreground color hex code
+ self.face = face # Font face name
+ self.back = back # Background color hex code
+ self.size = size # Font point size
+ self._exattr = ex # Extra attributes
+
+ def __eq__(self, other):
+ """Defines the == operator for the StyleItem Class
+ @param other: style item to compare to
+ @return: whether the two items are equal
+
+ """
+ return unicode(self) == unicode(other)
+
+ def __ne__(self, other):
+ """Defines != operator for the StyleItem Class"""
+ return unicode(self) != unicode(other)
+
+ def __str__(self):
+ """Convert StyleItem to string"""
+ uni = unicode(self)
+ return uni.encode('utf-8')
+
+ def __unicode__(self):
+ """Converts StyleItem to Unicode
+ @note: This return string is in a format that can be accepted by
+ Scintilla. No spaces may be in the string after the ':'.
+ @return: Unicode representation of the StyleItem
+
+ """
+ style_str = list()
+ if self.fore:
+ style_str.append(u"fore:%s" % self.fore)
+ if self.back:
+ style_str.append(u"back:%s" % self.back)
+ if self.face:
+ style_str.append(u"face:%s" % self.face)
+ if self.size:
+ style_str.append(u"size:%s" % unicode(self.size))
+ if len(self._exattr):
+ style_str.append(u"modifiers:" + u','.join(self._exattr))
+
+ style_str = u",".join(style_str)
+ return style_str.rstrip(u",")
+
+ def Clone(self):
+ """Make and return a copy of this object"""
+ nitem = StyleItem(self.fore, self.back,
+ self.face, self.size,
+ self._exattr)
+ if self.null:
+ nitem.Nullify()
+ return nitem
+
+ #---- Get Functions ----#
+ def GetAsList(self):
+ """Returns a list of attr:value strings
+ this style item.
+ @return: list attribute values usable for building stc or ess values
+
+ """
+ retval = list()
+ for attr in ('fore', 'back', 'face', 'size'):
+ val = getattr(self, attr, None)
+ if val not in ( None, wx.EmptyString ):
+ retval.append(attr + ':' + val)
+
+ if len(self._exattr):
+ retval.append("modifiers:" + u",".join(self._exattr))
+ return retval
+
+ def GetBack(self):
+ """Returns the value of the back attribute
+ @return: style items background attribute
+
+ """
+ return self.back
+
+ def GetFace(self):
+ """Returns the value of the face attribute
+ @return: style items font face attribute
+
+ """
+ return self.face
+
+ def GetFore(self):
+ """Returns the value of the fore attribute
+ @return: style items foreground attribute
+
+ """
+ return self.fore
+
+ def GetSize(self):
+ """Returns the value of the size attribute as a string
+ @return: style items font size attribute
+
+ """
+ return self.size
+
+ def GetModifiers(self):
+ """Get the modifiers string
+ @return: string
+
+ """
+ return u",".join(self.GetModifierList())
+
+ def GetModifierList(self):
+ """Get the list of modifiers
+ @return: list
+
+ """
+ return self._exattr
+
+ def GetNamedAttr(self, attr):
+ """Get the value of the named attribute
+ @param attr: named attribute to get value of
+
+ """
+ return getattr(self, attr, None)
+
+ #---- Utilities ----#
+ def IsNull(self):
+ """Return whether the item is null or not
+ @return: bool
+
+ """
+ return self.null
+
+ def IsOk(self):
+ """Check if the style item is ok or not, if it has any of its
+ attributes set it is perceived as ok.
+ @return: bool
+
+ """
+ return len(unicode(self))
+
+ def Nullify(self):
+ """Clear all values and set item as Null
+ @postcondition: item is turned into a NullStyleItem
+
+ """
+ self.null = True
+ for attr in ('fore', 'face', 'back', 'size'):
+ setattr(self, attr, u'')
+ self._exattr = list()
+
+ #---- Set Functions ----#
+ def SetAttrFromStr(self, style_str):
+ """Takes style string and sets the objects attributes
+ by parsing the string for the values. Only sets or
+ overwrites values does not zero out previously set values.
+ Returning True if value(s) are set or false otherwise.
+ @param style_str: style information string (i.e fore:#888444)
+
+ """
+ self.null = False
+ last_set = wx.EmptyString
+ for atom in style_str.split(u','):
+ attrib = atom.split(u':')
+ if len(attrib) == 2 and attrib[0] in STY_ATTRIBUTES:
+ last_set = attrib[0]
+ if last_set == u"modifiers":
+ self.SetExAttr(attrib[1])
+ else:
+ setattr(self, attrib[0], attrib[1])
+ else:
+ for attr in attrib:
+ if attr in STY_EX_ATTRIBUTES:
+ self.SetExAttr(attr)
+
+ return last_set != wx.EmptyString
+
+ def SetBack(self, back, ex=wx.EmptyString):
+ """Sets the Background Value
+ @param back: hex color string, or None to clear attribute
+ @keyword ex: extra attribute (i.e bold, italic, underline)
+
+ """
+ self.null = False
+ if back is None:
+ back = u''
+ self.back = back
+ if ex and ex not in self._exattr:
+ self._exattr.append(ex)
+
+ def SetFace(self, face, ex=wx.EmptyString):
+ """Sets the Face Value
+ @param face: font name string, or None to clear attribute
+ @keyword ex: extra attribute (i.e bold, italic, underline)
+
+ """
+ self.null = False
+ if face is None:
+ face = u''
+ self.face = face
+ if ex and ex not in self._exattr:
+ self._exattr.append(ex)
+
+ def SetFore(self, fore, ex=wx.EmptyString):
+ """Sets the Foreground Value
+ @param fore: hex color string, or None to clear attribute
+ @keyword ex: extra attribute (i.e bold, italic, underline)
+
+ """
+ self.null = False
+ if fore is None:
+ fore = u''
+ self.fore = fore
+ if ex and ex not in self._exattr:
+ self._exattr.append(ex)
+
+ def SetSize(self, size, ex=wx.EmptyString):
+ """Sets the Font Size Value
+ @param size: font point size, or None to clear attribute
+ @keyword ex: extra attribute (i.e bold, italic, underline)
+
+ """
+ self.null = False
+ if size is None:
+ size = u''
+ self.size = unicode(size)
+ if ex and ex not in self._exattr:
+ self._exattr.append(ex)
+
+ def SetExAttr(self, ex_attr, add=True):
+ """Adds an extra text attribute to a StyleItem. Currently
+ (bold, eol, italic, underline) are supported. If the optional
+ add value is set to False the attribute will be removed from
+ the StyleItem.
+ @param ex_attr: extra style attribute (bold, eol, italic, underline)
+ @keyword add: Add a style (True) or remove a style (False)
+
+ """
+ # Get currently set attributes
+ self.null = False
+ if ex_attr not in STY_EX_ATTRIBUTES:
+ return
+
+ if add and ex_attr not in self._exattr:
+ self._exattr.append(ex_attr)
+ elif not add and ex_attr in self._exattr:
+ self._exattr.remove(ex_attr)
+ else:
+ pass
+
+ def SetNamedAttr(self, attr, value):
+ """Sets a StyleItem attribute by named string.
+ @note: This is not intended to be used for setting extra
+ attributes such as bold, eol, ect..
+ @param attr: a particular attribute to set (i.e fore, face, back, size)
+ @param value: value to set the attribute to contain. None to clear the
+ value.
+
+ """
+ self.null = False
+ if value is None:
+ value = u''
+ cur_val = getattr(self, attr, None)
+ if cur_val is not None:
+ if u"," in value:
+ modifiers = value.split(u",")
+ value = modifiers.pop(0)
+ for ex in modifiers:
+ self.SetExAttr(ex)
+ setattr(self, attr, value)
+
+#-----------------------------------------------------------------------------#
+
+class StyleMgr(object):
+ """Manages style definitions and provides them on request.
+ Also provides functionality for loading custom style sheets and
+ modifying styles during run time.
+
+ """
+ STYLES = dict() # Static cache for loaded style set(s)
+ FONT_PRIMARY = u"primary"
+ FONT_SECONDARY = u"secondary"
+ FONT_SIZE = u"size"
+ FONT_SIZE2 = u"size2"
+ FONT_SIZE3 = u"size3"
+
+ def __init__(self, custom=wx.EmptyString):
+ """Initializes the Style Manager
+ @keyword custom: path to custom style sheet to use
+
+ """
+ super(StyleMgr, self).__init__()
+
+ # Attributes
+ self.fonts = self.GetFontDictionary()
+ self.style_set = custom
+ self.syntax_set = list()
+ self.LOG = wx.GetApp().GetLog()
+
+ # Get the Style Set
+ if custom != wx.EmptyString and self.LoadStyleSheet(custom):
+ self.LOG("[ed_style][info] Loaded custom style sheet %s" % custom)
+ elif custom == wx.EmptyString:
+ self.SetStyles('default', DEF_STYLE_DICT)
+ else:
+ self.LOG("[ed_style][err] Failed to import styles from %s" % custom)
+
+ def BlankStyleDictionary(self):
+ """Returns a dictionary of unset style items based on the
+ tags defined in the current dictionary.
+ @return: dictionary of unset style items using the current tag set
+ as keys.
+
+ """
+ sty_dict = dict()
+ for key in DEF_STYLE_DICT.keys():
+ if key in ('select_style',): # special styles
+ sty_dict[key] = NullStyleItem()
+ else:
+ sty_dict[key] = StyleItem("#000000", "#FFFFFF",
+ "%(primary)s", "%(size)d")
+ return sty_dict
+
+ def FindTagById(self, style_id):
+ """Find the style tag that is associated with the given
+ Id. Return value defaults to default_style .
+ @param style_id: id of tag to look for
+ @return: style tag string
+
+ """
+ for data in self.syntax_set:
+ if style_id == data[0]:
+ return data[1]
+ return 'default_style'
+
+ def GetFontDictionary(self, default=True):
+ """Does a system lookup to build a default set of fonts using
+ ten point fonts as the standard size.
+ @keyword default: return the default dictionary of fonts, else return
+ the current running dictionary of fonts if it exists.
+ @return: font dictionary (primary, secondary) + (size, size2)
+
+ """
+ if hasattr(self, 'fonts') and not default:
+ return self.fonts
+
+ font = Profile_Get('FONT1', 'font', None)
+ if font is not None:
+ mfont = font
+ else:
+ mfont = wx.Font(10, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
+ wx.FONTWEIGHT_NORMAL)
+ Profile_Set('FONT1', mfont, 'font')
+ primary = mfont.GetFaceName()
+
+ font = Profile_Get('FONT2', 'font', None)
+ if font is None:
+ font = wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL,
+ wx.FONTWEIGHT_NORMAL)
+ Profile_Set('FONT2', font, 'font')
+ secondary = font.GetFaceName()
+ faces = {
+ self.FONT_PRIMARY : primary,
+ self.FONT_SECONDARY : secondary,
+ self.FONT_SIZE : mfont.GetPointSize(),
+ self.FONT_SIZE2 : font.GetPointSize(),
+ self.FONT_SIZE3 : mfont.GetPointSize() - 2
+ }
+ return faces
+
+ def GetDefaultFont(self):
+ """Constructs and returns a wxFont object from the settings
+ of the default_style object.
+ @return: wx.Font object of default style
+
+ """
+ if self.HasNamedStyle('default_style'):
+ style_item = self.GetItemByName('default_style')
+ face = style_item.GetFace()
+ if face and face[0] == u"%":
+ face = face % self.fonts
+ size = style_item.GetSize()
+ if isinstance(size, basestring):
+ size = size % self.fonts
+ font = wx.FFont(int(size), wx.MODERN, face=face)
+ else:
+ font = wx.FFont(self.fonts[self.FONT_SIZE], wx.MODERN)
+ return font
+
+ def GetDefaultForeColour(self, as_hex=False):
+ """Gets the foreground color of the default style and returns
+ a Colour object. Otherwise returns Black if the default
+ style is not found.
+ @keyword as_hex: return a hex string or colour object
+ @return: wx.Colour of default style foreground or hex value
+
+ """
+ fore = self.GetItemByName('default_style').GetFore()
+ if not fore:
+ fore = u"#000000"
+
+ if not as_hex:
+ rgb = eclib.HexToRGB(fore[1:])
+ fore = wx.Colour(red=rgb[0], green=rgb[1], blue=rgb[2])
+ return fore
+
+ def GetCurrentStyleSetName(self):
+ """Get the name of the currently set style
+ @return: string
+
+ """
+ return self.style_set
+
+ def GetDefaultBackColour(self, as_hex=False):
+ """Gets the background color of the default style and returns
+ a Colour object. Otherwise returns white if the default
+ style is not found.
+ @keyword as_hex: return a hex string or colour object
+ @return: wx.Colour of default style background or hex value
+
+ """
+ back = self.GetItemByName('default_style').GetBack()
+ if not back:
+ back = u"#FFFFFF"
+
+ if not as_hex:
+ rgb = eclib.HexToRGB(back[1:])
+ back = wx.Colour(red=rgb[0], green=rgb[1], blue=rgb[2])
+ return back
+
+ def GetItemByName(self, name):
+ """Gets and returns a style item using its name for the search
+ @param name: tag name of style item to get
+ @return: style item (may be empty/null style item)
+
+ """
+ scheme = self.GetStyleSet()
+ if name in scheme:
+ item = scheme[name]
+
+ # Set font value if need be
+ ival = unicode(item)
+ if u"%" in ival:
+ val = ival % self.fonts
+ item = StyleItem()
+ item.SetAttrFromStr(val)
+
+ return item
+ else:
+ return StyleItem()
+
+ def GetStyleFont(self, primary=True):
+ """Returns the primary font facename by default
+ @keyword primary: Get Primary(default) or Secondary Font
+ @return face name of current font in use
+
+ """
+ if primary:
+ font = wx.FFont(self.fonts[self.FONT_SIZE], wx.DEFAULT,
+ face=self.fonts[self.FONT_PRIMARY])
+ else:
+ font = wx.FFont(self.fonts[self.FONT_SIZE2], wx.DEFAULT,
+ face=self.fonts[self.FONT_SECONDARY])
+ return font
+
+ def GetStyleByName(self, name):
+ """Gets and returns a style string using its name for the search
+ @param name: tag name of style to get
+ @return: style item in string form
+
+ """
+ if self.HasNamedStyle(name):
+ stystr = unicode(self.GetItemByName(name))
+ return stystr.replace("modifiers:", "")
+ else:
+ return u""
+
+ def GetStyleSet(self):
+ """Returns the current set of styles or the default set if
+ there is no current set.
+ @return: current style set dictionary
+
+ """
+ return StyleMgr.STYLES.get(self.style_set, DEF_STYLE_DICT)
+
+ @staticmethod
+ def GetStyleSheet(sheet_name=None):
+ """Finds the current style sheet and returns its path. The
+ lookup is done by first looking in the users config directory
+ and if it is not found there it looks for one on the system
+ level and if that fails it returns None.
+ @param sheet_name: style sheet to look for
+ @return: full path to style sheet
+
+ """
+ if sheet_name:
+ style = sheet_name
+ else:
+ style = Profile_Get('SYNTHEME', 'str')
+ style = ebmlib.AddFileExtension(style, u'.ess').lower()
+
+ # Get Correct Filename if it exists
+ for sheet in util.GetResourceFiles(u'styles', trim=False,
+ get_all=True, title=False):
+ if sheet.lower() == style:
+ style = sheet
+ break
+
+ user = os.path.join(ed_glob.CONFIG['STYLES_DIR'], style)
+ sysp = os.path.join(ed_glob.CONFIG['SYS_STYLES_DIR'], style)
+ if os.path.exists(user):
+ return user
+ elif os.path.exists(sysp):
+ return sysp
+ else:
+ return None
+
+ def GetSyntaxParams(self):
+ """Get the set of syntax parameters
+ @return: list
+
+ """
+ return self.syntax_set
+
+ def HasNamedStyle(self, name):
+ """Checks if a style has been set/loaded or not
+ @param name: tag name of style to look for
+ @return: whether item is in style set or not
+
+ """
+ return name in self.GetStyleSet()
+
+ def LoadStyleSheet(self, style_sheet, force=False):
+ """Loads a custom style sheet and returns True on success
+ @param style_sheet: path to style sheet to load
+ @keyword force: Force re-parse of style sheet, default is to use cached
+ data when available
+ @return: whether style sheet was loaded or not
+
+ """
+ if isinstance(style_sheet, basestring) and \
+ os.path.exists(style_sheet) and \
+ ((force or style_sheet not in StyleMgr.STYLES) or \
+ style_sheet != self.style_set):
+ reader = util.GetFileReader(style_sheet)
+ if reader == -1:
+ self.LOG("[ed_style][err] Failed to open style sheet: %s" % style_sheet)
+ return False
+ style_data = None
+ try:
+ style_data = self.ParseStyleData(reader.read())
+ except Exception, msg:
+ self.LOG("[ed_style][err] Failed to parse style data for %s:" % style_sheet)
+ return False
+ ret_val = self.SetStyles(style_sheet, style_data)
+ reader.close()
+ return ret_val
+ elif style_sheet not in StyleMgr.STYLES:
+ self.LOG("[ed_style][warn] Style sheet %s does not exists" % style_sheet)
+ # Reset to default style
+ if Profile_Get('SYNTHEME') != 'default':
+ Profile_Set('SYNTHEME', 'default')
+ self.SetStyles('default', DEF_STYLE_DICT)
+ return False
+ else:
+ self.LOG("[ed_style][info] Using cached style data")
+ return True
+
+ def PackStyleSet(self, style_set):
+ """Checks the difference of each item in the style set as
+ compared to the default_style tag and packs any unset value
+ in the item to be equal to the default style.
+ @param style_set: style set to pack
+ @return: style_set with all unset attributes set to match default style
+
+ """
+ if isinstance(style_set, dict) and 'default_style' in style_set:
+ default = style_set['default_style']
+ for tag in style_set:
+ if style_set[tag].IsNull():
+ continue
+ if not style_set[tag].GetFace():
+ style_set[tag].SetFace(default.GetFace())
+ if not style_set[tag].GetFore():
+ style_set[tag].SetFore(default.GetFore())
+ if not style_set[tag].GetBack():
+ style_set[tag].SetBack(default.GetBack())
+ if not style_set[tag].GetSize():
+ style_set[tag].SetSize(default.GetSize())
+
+ # Now need to pack in undefined styles that are part of
+ # the standard set.
+ for tag in DEF_STYLE_DICT.keys():
+ if tag not in style_set:
+ if tag == 'select_style':
+ style_set[tag] = NullStyleItem()
+ else:
+ style_set[tag] = default.Clone()
+ else:
+ pass
+ return style_set
+
+ def ParseStyleData(self, style_data):
+ """Parses a string style definitions read from an Editra Style Sheet.
+ @param style_data: style sheet data string
+ @return: dictionary of StyleItems constructed from the style sheet data.
+
+ """
+ # Remove all comments
+ style_data = RE_ESS_COMMENT.sub(u'', style_data)
+
+ # Compact data into a contiguous string
+ style_data = style_data.replace(u"\r\n", u"").replace(u"\n", u"")
+ style_data = style_data.replace(u"\t", u"")
+# style_data = style_data.replace(u" ", u"") # support old style
+
+ ## Build style data tree
+ # Tree Level 1 split tag from data
+ style_tree = [style.split(u"{") for style in style_data.split(u'}')]
+ if len(style_tree) and len(style_tree[-1]) and not style_tree[-1][0]:
+ style_tree.pop()
+
+ # Tree Level 2 Build small trees of tag and style attributes
+ # Tree Level 3 Branch tree into TAG => Attr => Value String
+ ttree = list(style_tree)
+ for branch in ttree:
+ # Check for level 1 syntax errors
+ if len(branch) != 2:
+ self.LOG("[ed_style][err] There was an error parsing "
+ "the syntax data from " + self.style_set)
+ self.LOG("[ed_style][err] Missing a { or } in Def: " + repr(branch[0]))
+ ttree.remove(branch)
+ continue
+
+ tmp2 = [leaf.strip().split(u":")
+ for leaf in branch[1].strip().split(u";")]
+ if len(tmp2) and not tmp2[-1][0]:
+ tmp2.pop()
+ branch[1] = tmp2
+ style_tree = ttree
+
+ # Check for L2/L3 Syntax errors and build a clean dictionary
+ # of Tags => Valid Attributes
+ style_dict = dict()
+ for branch in style_tree:
+ value = list()
+ tag = branch[0].replace(u" ", u"")
+ for leaf in branch[1]:
+ # Remove any remaining whitespace
+ leaf = [part.strip() for part in leaf]
+ if len(leaf) != 2:
+ self.LOG("[ed_style][err] Missing a : or ; in the "
+ "declaration of %s" % tag)
+ elif leaf[0] not in STY_ATTRIBUTES:
+ self.LOG(("[ed_style][warn] Unknown style attribute: %s"
+ ", In declaration of %s") % (leaf[0], tag))
+ else:
+ value.append(leaf)
+
+ # Skip all leafless branches
+ if len(value) != 0:
+ style_dict[tag] = value
+
+ # Validate leaf values and format into style string
+ rdict = dict()
+ for style_def in style_dict:
+ if not style_def[0][0].isalpha():
+ self.LOG("[ed_style][err] The style def %s is not a "
+ "valid name" % style_def[0])
+ else:
+ style_str = u""
+ # Check each definition and validate its items
+ for attrib in style_dict[style_def]:
+ values = [ val for val in attrib[1].split()
+ if val != u"" ]
+
+ v1ok = v2ok = False
+ # Check that colors are a hex string
+ n_values = len(values)
+ if n_values and \
+ attrib[0] in "fore back" and RE_HEX_STR.match(values[0]):
+ v1ok = True
+ elif n_values and attrib[0] == "size":
+ if RE_ESS_SCALAR.match(values[0]) or values[0].isdigit():
+ v1ok = True
+ else:
+ self.LOG("[ed_style][warn] Bad value in %s"
+ " the value %s is invalid." % \
+ (attrib[0], values[0]))
+ elif n_values and attrib[0] == "face":
+ # Font names may have spaces in them so join the
+ # name of the font into one item.
+ if n_values > 1 and values[1] not in STY_EX_ATTRIBUTES:
+ tmp = list()
+ for val in list(values):
+ if val not in STY_EX_ATTRIBUTES:
+ tmp.append(val)
+ values.remove(val)
+ else:
+ break
+ values = [u' '.join(tmp),] + values
+ v1ok = True
+ elif n_values and attrib[0] == "modifiers":
+ v1ok = True
+
+ # Check extra attributes
+ if len(values) > 1:
+ for value in values[1:]:
+ if value not in STY_EX_ATTRIBUTES:
+ self.LOG("[ed_style][warn] Unknown extra " + \
+ "attribute '" + values[1] + \
+ "' in attribute: " + attrib[0])
+ break
+ else:
+ v2ok = True
+
+ if v1ok and v2ok:
+ value = u",".join(values)
+ elif v1ok:
+ value = values[0]
+ else:
+ continue
+
+ style_str = u",".join([style_str,
+ u":".join([attrib[0], value])])
+
+ # Build up the StyleItem Dictionary
+ if style_str != u"":
+ new_item = StyleItem()
+ value = style_str.strip(u",")
+ if isinstance(value, basestring):
+ new_item.SetAttrFromStr(value)
+ rdict[style_def] = new_item
+
+ return rdict
+
+ def SetGlobalFont(self, fonttag, fontface, size=-1):
+ """Sets one of the fonts in the global font set by tag
+ and sets it to the named font. Returns true on success.
+ @param fonttag: font type identifier key
+ @param fontface: face name to set global font to
+
+ """
+ if hasattr(self, 'fonts'):
+ self.fonts[fonttag] = fontface
+ if size > 0:
+ self.fonts[self.FONT_SIZE] = size
+ return True
+ else:
+ return False
+
+ def SetStyleFont(self, wx_font, primary=True):
+ """Sets the primary or secondary font and their respective
+ size values.
+ @param wx_font: font object to set styles font info from
+ @keyword primary: Set primary(default) or secondary font
+
+ """
+ if primary:
+ self.fonts[self.FONT_PRIMARY] = wx_font.GetFaceName()
+ self.fonts[self.FONT_SIZE] = wx_font.GetPointSize()
+ else:
+ self.fonts[self.FONT_SECONDARY] = wx_font.GetFaceName()
+ self.fonts[self.FONT_SIZE2] = wx_font.GetPointSize()
+
+ def SetStyleTag(self, style_tag, value):
+ """Sets the value of style tag by name
+ @param style_tag: desired tag name of style definition
+ @param value: style item to set tag to
+ @return: bool
+
+ """
+ if not isinstance(value, StyleItem):
+ self.LOG("[ed_style][warn] Bad data in SetStyleTag(%s)" % repr(value))
+ return False
+
+ StyleMgr.STYLES[self.style_set][style_tag] = value
+ return True
+
+ def SetStyles(self, name, style_dict, nomerge=False):
+ """Sets the managers style data and returns True on success.
+ @param name: name to store dictionary in cache under
+ @param style_dict: dictionary of style items to use as managers style
+ set.
+ @keyword nomerge: merge against default set or not
+
+ """
+ if nomerge:
+ self.style_set = name
+ StyleMgr.STYLES[name] = self.PackStyleSet(style_dict)
+ return True
+
+ # Merge the given style set with the default set to fill in any
+ # unset attributes/tags
+ if isinstance(style_dict, dict):
+ # Check for bad data
+ for style in style_dict.values():
+ if not isinstance(style, StyleItem):
+ self.LOG("[ed_style][err] Invalid data in style dictionary")
+ self.style_set = 'default'
+ return False
+
+ self.style_set = name
+ defaultd = DEF_STYLE_DICT
+ dstyle = style_dict.get('default_style', None)
+ if dstyle is None:
+ self.LOG("[ed_style][warn] default_style is undefined")
+ style_dict['default_style'] = defaultd['default_style'].Clone()
+
+ # Set any undefined styles to match the default_style
+ for tag in defaultd:
+ if tag not in style_dict:
+ if tag in ('select_style',):
+ style_dict[tag] = NullStyleItem()
+ else:
+ style_dict[tag] = style_dict['default_style'].Clone()
+
+ StyleMgr.STYLES[name] = self.PackStyleSet(style_dict)
+ return True
+ else:
+ self.LOG("[ed_style][err] SetStyles expects a " \
+ "dictionary of StyleItems")
+ return False
+
+ def SetSyntax(self, synlst):
+ """Sets the Syntax Style Specs from a list of specifications
+ @param synlst: [(STYLE_ID, "STYLE_TYPE"), (STYLE_ID2, "STYLE_TYPE2)]
+
+ """
+ # Parses Syntax Specifications list, ignoring all bad values
+ self.UpdateBaseStyles()
+ valid_settings = list()
+ for syn in synlst:
+ if len(syn) != 2:
+ self.LOG("[ed_style][warn] Bogus Syntax Spec %s" % repr(syn))
+ continue
+ else:
+ self.StyleSetSpec(syn[0], self.GetStyleByName(syn[1]))
+ valid_settings.append(syn)
+
+ self.syntax_set = valid_settings
+ return True
+
+ def StyleDefault(self):
+ """Clears the editor styles to default
+ @postcondition: style is reset to default
+
+ """
+ self.StyleClearAll()
+ self.SetCaretForeground(wx.BLACK)
+ self.Colourise(0, -1)
+
+ def UpdateAllStyles(self, spec_style=None):
+ """Refreshes all the styles and attributes of the control
+ @param spec_style: style scheme name
+ @postcondition: style scheme is set to specified style
+
+ """
+ if spec_style and (spec_style != self.style_set):
+ self.LoadStyleSheet(self.GetStyleSheet(spec_style), force=True)
+ self.SetSyntax(self.GetSyntaxParams())
+ self.Refresh()
+
+ def UpdateBaseStyles(self):
+ """Updates the base styles of editor to the current settings
+ @postcondition: base style info is updated
+
+ """
+ self.StyleDefault()
+ self.SetMargins(4, 0)
+
+ # Global default styles for all languages
+ self.StyleSetSpec(0, self.GetStyleByName('default_style'))
+ self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, \
+ self.GetStyleByName('default_style'))
+ self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER, \
+ self.GetStyleByName('line_num'))
+ self.StyleSetSpec(wx.stc.STC_STYLE_CONTROLCHAR, \
+ self.GetStyleByName('ctrl_char'))
+ self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT, \
+ self.GetStyleByName('brace_good'))
+ self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD, \
+ self.GetStyleByName('brace_bad'))
+ self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, \
+ self.GetStyleByName('guide_style'))
+
+ # wx.stc.STC_STYLE_CALLTIP doesn't seem to do anything
+ calltip = self.GetItemByName('calltip')
+ self.CallTipSetBackground(calltip.GetBack())
+ self.CallTipSetForeground(calltip.GetFore())
+
+ sback = self.GetItemByName('select_style')
+ if not sback.IsNull() and len(sback.GetBack()):
+ sback = sback.GetBack()
+ sback = eclib.HexToRGB(sback)
+ sback = wx.Colour(*sback)
+ else:
+ sback = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+
+ # If selection colour is dark make the foreground white
+ # else use the default settings.
+ if sum(sback.Get()) < 384:
+ self.SetSelForeground(True, wx.WHITE)
+ else:
+ self.SetSelForeground(True, wx.BLACK)
+ self.SetSelBackground(True, sback)
+
+ # Causes issues with selecting text when view whitespace is on
+# wspace = self.GetItemByName('whitespace_style')
+# self.SetWhitespaceBackground(True, wspace.GetBack())
+# self.SetWhitespaceForeground(True, wspace.GetFore())
+
+ default_fore = self.GetDefaultForeColour()
+ edge_colour = self.GetItemByName('edge_style')
+ self.SetEdgeColour(edge_colour.GetFore())
+ self.SetCaretForeground(default_fore)
+ self.SetCaretLineBack(self.GetItemByName('caret_line').GetBack())
+ self.Colourise(0, -1)
+
+#-----------------------------------------------------------------------------#
+# Utility Functions
+
+def NullStyleItem():
+ """Create a null style item
+ @return: empty style item that cannot be merged
+
+ """
+ item = StyleItem()
+ item.null = True
+ return item
+
+DEF_STYLE_DICT = \
+ {'brace_good' : StyleItem("#FFFFFF", "#0000FF", ex=["bold",]),
+ 'brace_bad' : StyleItem(back="#FF0000", ex=["bold",]),
+ 'calltip' : StyleItem("#404040", "#FFFFB8"),
+ 'caret_line' : StyleItem(back="#D8F8FF"),
+ 'ctrl_char' : StyleItem(),
+ 'line_num' : StyleItem(back="#C0C0C0", face="%(secondary)s", \
+ size="%(size3)d"),
+ 'array_style': StyleItem("#EE8B02",
+ face="%(secondary)s",
+ ex=["bold",]),
+ 'btick_style': StyleItem("#8959F6", size="%(size)d", ex=["bold",]),
+ 'default_style': StyleItem("#000000", "#F6F6F6", \
+ "%(primary)s", "%(size)d"),
+ 'char_style' : StyleItem("#FF3AFF"),
+ 'class_style' : StyleItem("#2E8B57", ex=["bold",]),
+ 'class2_style' : StyleItem("#2E8B57", ex=["bold",]),
+ 'comment_style' : StyleItem("#838383"),
+ 'decor_style' : StyleItem("#BA0EEA", face="%(secondary)s",
+ ex=["italic",]),
+ 'directive_style' : StyleItem("#0000FF", face="%(secondary)s",
+ ex=["bold",]),
+ 'dockey_style' : StyleItem("#0000FF"),
+ 'edge_style' : StyleItem(), # inherit from default
+ 'error_style' : StyleItem("#DD0101", face="%(secondary)s",
+ ex=["bold",]),
+ 'foldmargin_style' : StyleItem(back="#D1D1D1"),
+ 'funct_style' : StyleItem("#008B8B", ex=["italic",]),
+ 'global_style' : StyleItem("#007F7F", face="%(secondary)s",
+ ex=["bold",]),
+ 'guide_style' : StyleItem("#838383"),
+ 'here_style' : StyleItem("#CA61CA", face="%(secondary)s",
+ ex=["bold",]),
+ 'ideol_style' : StyleItem("#E0C0E0", face="%(secondary)s"),
+ 'keyword_style' : StyleItem("#A52B2B", ex=["bold",]),
+ 'keyword2_style' : StyleItem("#2E8B57", ex=["bold",]),
+ 'keyword3_style' : StyleItem("#008B8B", ex=["bold",]),
+ 'keyword4_style' : StyleItem("#9D2424"),
+ 'marker_style' : StyleItem("#FFFFFF", "#000000"),
+ 'number_style' : StyleItem("#DD0101"),
+ 'number2_style' : StyleItem("#DD0101", ex=["bold",]),
+ 'operator_style' : StyleItem("#000000", face="%(primary)s",
+ ex=["bold",]),
+ 'pre_style' : StyleItem("#AB39F2", ex=["bold",]),
+ 'pre2_style' : StyleItem("#AB39F2", "#FFFFFF", ex=["bold",]),
+ 'regex_style' : StyleItem("#008B8B"),
+ 'scalar_style' : StyleItem("#AB37F2", face="%(secondary)s",
+ ex=["bold",]),
+ 'scalar2_style' : StyleItem("#AB37F2", face="%(secondary)s"),
+ 'select_style' : NullStyleItem(), # Use system default colour
+ 'string_style' : StyleItem("#FF3AFF", ex=["bold",]),
+ 'stringeol_style' : StyleItem("#000000", "#EEC0EE",
+ "%(secondary)s", ex=["bold", "eol"]),
+ 'unknown_style' : StyleItem("#FFFFFF", "#DD0101", ex=["bold", "eol"]),
+ 'userkw_style' : StyleItem()
+ }
+
+def MergeFonts(style_dict, font_dict):
+ """Does any string substitution that the style dictionary
+ may need to have fonts and their sizes set.
+ @param style_dict: dictionary of L{StyleItem}
+ @param font_dict: dictionary of font data
+ @return: style dictionary with all font format strings substituted in
+
+ """
+ for style in style_dict:
+ st_str = unicode(style_dict[style])
+ if u'%' in st_str:
+ style_dict[style].SetAttrFromStr(st_str % font_dict)
+ return style_dict
+
+def MergeStyles(styles1, styles2):
+ """Merges the styles from styles2 into styles1 overwriting
+ any duplicate values already set in styles1 with the new
+ data from styles2.
+ @param styles1: dictionary of StyleItems to receive merge
+ @param styles2: dictionary of StyleItems to merge from
+ @return: style1 with all values from styles2 merged into it
+
+ """
+ for style in styles2:
+ styles1[style] = styles2[style]
+ return styles1
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_tab.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_tab.py
new file mode 100644
index 0000000..c2de86e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_tab.py
@@ -0,0 +1,157 @@
+###############################################################################
+# Name: ed_tab.py #
+# Purpose: Notebook tab inteface class #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Base class for all views that want to be able to be viewable in the main
+notebook.
+
+@summary: Main notebook tab base class
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_tab.py 67542 2011-04-19 00:26:29Z CJP $"
+__revision__ = "$Revision: 67542 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+
+#--------------------------------------------------------------------------#
+
+class EdTabBase(object):
+ """Base class for all tab views to derive from, this class just defines
+ the abstract interface and some common basic methods. Initialize this
+ base class after initializing the wx control instance of the subclass.
+
+ """
+ def __init__(self):
+ """Initialize the tab base class"""
+ super(EdTabBase, self).__init__()
+
+ # Attributes
+ self._lbl = u''
+ self._idx = -1
+
+ @property
+ def _nb(self):
+ """Get the notebook that owns this tab"""
+ return self.GetParent()
+
+ #---- Methods to override in subclasses ----#
+
+ def DoDeactivateTab(self):
+ """Called when the tab is moved from the foreground to background"""
+ pass
+
+ def DoOnIdle(self):
+ """Called when the notebook is idle and this instance is the active
+ tab.
+
+ """
+ pass
+
+ def DoTabClosing(self):
+ """Called when the tab has been selected to be closed in the notebook"""
+ pass
+
+ def DoTabOpen(self, ):
+ """Called to open a new tab"""
+ pass
+
+ def DoTabSelected(self):
+ """Called when the page is selected in the notebook"""
+ pass
+
+ def GetName(self):
+ """Get the unique name for this tab control.
+ @return: (unicode) string
+
+ """
+ raise NotImplementedError, "GetName Must be implemented!!"
+
+ def GetTabImage(self):
+ """Get the Bitmap to use for the tab
+ @return: wx.Bitmap (16x16)
+
+ """
+ return wx.NullBitmap
+
+ def GetTabMenu(self):
+ """Get the context menu to show on the tab
+ @return: wx.Menu or None
+
+ """
+ return None
+
+ def GetTitleString(self):
+ """Get the title string to display in the MainWindows title bar
+ @return: (unicode) string
+
+ """
+ return u''
+
+ def CanCloseTab(self):
+ """Called when checking if tab can be closed or not
+ @return: bool
+
+ """
+ return True
+
+ def OnTabMenu(self, evt):
+ """Handle events from this tabs menu
+ @param evt: menu event
+
+ """
+ evt.Skip()
+
+ #---- Common Base Methods ----#
+
+ def GetTabIndex(self):
+ """Return the index of the tab in the notebook
+ @return: int
+
+ """
+ return self._idx
+
+ def GetTabLabel(self):
+ """Get the tabs label
+ @return: string
+
+ """
+ return self._lbl
+
+ def SetTabIndex(self, idx):
+ """Set the tab index
+ @param idx: int
+
+ """
+ self._idx = idx
+
+ def SetTabLabel(self, lbl):
+ """Set the tabs label
+ @param lbl: string
+
+ """
+ self._lbl = lbl
+
+ def SetTabTitle(self, title):
+ """Set the notebooks title text for this tab"""
+ obj_id = self.GetId()
+
+ # Find which page we are and update the text
+ for page in range(self._nb.GetPageCount()):
+ ctrl = self._nb.GetPage(page)
+ if ctrl.GetId() == obj_id:
+ self._nb.SetPageText(page, title)
+ break
+ else:
+ # TODO: notify of error?
+ pass
+
+#--------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_theme.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_theme.py
new file mode 100644
index 0000000..73310a5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_theme.py
@@ -0,0 +1,418 @@
+###############################################################################
+# Name: ed_theme.py #
+# Purpose: Icon theme management for Editra #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provide an interface for creating icon themes for Editra. This will allow for
+themes to be created, installed, and managed as plugins, which means that they
+can be installed as single file instead of dozens of individual image files.
+
+@summary: Editra's theme interface and implementation
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_theme.py 72247 2012-07-28 22:32:37Z CJP $"
+__revision__ = "$Revision: 72247 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import wx
+
+# Local Imports
+import ed_glob
+import util
+import plugin
+from profiler import Profile_Get, Profile_Set
+import syntax.synglob as synglob
+from syntax.syntax import SYNTAX_IDS
+
+#--------------------------------------------------------------------------#
+
+class ThemeI(plugin.Interface):
+ """Interface for defining an icon theme in Editra
+ When a icon theme is active Editra's ArtProvider will ask the active
+ theme that implements this interface to give it a bitmap. The requests
+ for bitmaps will be numerical ID values that come from ed_glob. These
+ ID's are associated with different objects in the interface. The names
+ are descriptive of the object they represent, for reference however
+ see the implementation of the two main themes (Tango and Nuovo).
+
+ @see: L{ed_glob}
+ @see: L{syntax.synglob}
+
+ """
+ def GetName(self):
+ """Return the name of this theme. This is used to identify the
+ theme when the provider looks for resources based on user preferences
+
+ @return: name string
+
+ """
+
+ def GetMenuBitmap(self, bmp_id):
+ """Get the menu bitmap associated with the object id
+ If this theme does not have a resource to provide for this
+ object return a wx.NullBitmap.
+
+ @return: 16x16 pixel bitmap
+
+ """
+ return wx.NullBitmap
+
+ def GetFileBitmap(self, bmp_id):
+ """Get the filetype bitmap associated with the object id, the
+ valid object ids are defined in the module syntax.synglob and
+ are used to request images for menu's and page tabs. The theme
+ implimenting this interface should at least be able to
+ provide an image for plain text files and return that for any
+ unmapped types.
+
+ If this theme does not have a resource to provide for this
+ object return a wx.NullBitmap.
+
+ @return: 16x16 pixel bitmap
+
+ """
+ return wx.NullBitmap
+
+ def GetOtherBitmap(self, bmp_id):
+ """Get the bitmap from the 'other' icon resources. Valid id's are
+ identified by a mapping in the ART dictionary.
+
+ If this theme does not have a resource to provide for this
+ object return a wx.NullBitmap.
+
+ @return: wx.Bitmap
+
+ """
+ return wx.NullBitmap
+
+ def GetToolbarBitmap(self, bmp_id):
+ """Get the toolbar bitmap associated with the object id. The
+ toolbar icons must be returned as a 32x32 pixel bitmap any
+ scaling that is needed will be handled by the art provider that
+ requests the resource.
+
+ If this theme does not have a resource to provide for this
+ object return a wx.NullBitmap.
+
+ @return: 32x32 pixel bitmap
+
+ """
+ return wx.NullBitmap
+
+#-----------------------------------------------------------------------------#
+
+class BitmapProvider(plugin.Plugin):
+ """Plugin that fetches requested icons from the current active theme.
+
+ """
+ observers = plugin.ExtensionPoint(ThemeI)
+
+ def __GetCurrentProvider(self):
+ """Gets the provider of the current theme resources
+ @return: ThemeI object
+
+ """
+ theme = Profile_Get('ICONS', 'str', u'')
+ for prov in self.observers:
+ if theme == prov.GetName():
+ return prov
+
+ # Case if a theme was deleted while it was the active theme
+ if theme.lower() != u'default':
+ Profile_Set('ICONS', u'Default')
+
+ return None
+
+ def _GetTango(self, bmp_id, client):
+ """Try to get the icon from the default tango theme"""
+ theme = None
+ bmp = wx.NullBitmap
+ for prov in self.observers:
+ if prov.GetName() == TangoTheme.name:
+ theme = prov
+ break
+ else:
+ return bmp
+
+ if client == wx.ART_TOOLBAR:
+ bmp = theme.GetToolbarBitmap(bmp_id)
+ elif client == wx.ART_MENU:
+ bmp = theme.GetMenuBitmap(bmp_id)
+ elif client == wx.ART_OTHER:
+ bmp = theme.GetOtherBitmap(bmp_id)
+ else:
+ pass
+
+ return bmp
+
+ def GetThemes(self):
+ """Gets a list of the installed and activated themes
+ @return: list of strings
+
+ """
+ return [ name.GetName() for name in self.observers ]
+
+ def GetBitmap(self, bmp_id, client):
+ """Gets a 16x16 or 32x32 pixel bitmap depending on client value.
+ May return a NullBitmap if no suitable bitmap can be
+ found.
+
+ @param bmp_id: id of bitmap to lookup
+ @param client: wxART_MENU, wxART_TOOLBAR
+ @see: L{ed_glob}
+
+ """
+ prov = self.__GetCurrentProvider()
+ if prov is not None:
+ if client == wx.ART_MENU:
+ bmp = prov.GetMenuBitmap(bmp_id)
+ elif client == wx.ART_OTHER:
+ # Backwards compatibility for older interface
+ if hasattr(prov, 'GetOtherBitmap'):
+ bmp = prov.GetOtherBitmap(bmp_id)
+ else:
+ bmp = wx.NullBitmap
+ else:
+ bmp = prov.GetToolbarBitmap(bmp_id)
+
+ if bmp.IsOk():
+ return bmp
+
+ # Try to fallback to tango theme when icon lookup fails
+ bmp = self._GetTango(bmp_id, client)
+ if bmp.IsOk():
+ return bmp
+
+ return wx.NullBitmap
+
+#-----------------------------------------------------------------------------#
+# Default theme data maps
+ART = { ed_glob.ID_ABOUT : u'about.png',
+ ed_glob.ID_ADD : u'add.png',
+ ed_glob.ID_ADD_BM : u'bmark_add.png',
+ ed_glob.ID_ADVANCED : u'advanced.png',
+ ed_glob.ID_BACKWARD : u'backward.png',
+ ed_glob.ID_BIN_FILE : u'bin_file.png',
+ ed_glob.ID_CDROM : u'cdrom.png',
+ ed_glob.ID_CONTACT : u'mail.png',
+ ed_glob.ID_COPY : u'copy.png',
+ ed_glob.ID_COMPUTER : u'computer.png',
+ ed_glob.ID_CUT : u'cut.png',
+ ed_glob.ID_DELETE : u'delete.png',
+ ed_glob.ID_DELETE_ALL : u'delete_all.png',
+ ed_glob.ID_DOCPROP : u'doc_props.png',
+ ed_glob.ID_DOCUMENTATION : u'docs.png',
+ ed_glob.ID_DOWN : u'down.png',
+ ed_glob.ID_EXIT : u'quit.png',
+ ed_glob.ID_FILE : u'file.png',
+ ed_glob.ID_FIND : u'find.png',
+ ed_glob.ID_FIND_REPLACE : u'findr.png',
+ ed_glob.ID_FIND_RESULTS : u'find.png',
+ ed_glob.ID_FLOPPY : u'floppy.png',
+ ed_glob.ID_FOLDER : u'folder.png',
+ ed_glob.ID_FONT : u'font.png',
+ ed_glob.ID_FORWARD : u'forward.png',
+ ed_glob.ID_HARDDISK : u'harddisk.png',
+ ed_glob.ID_HOMEPAGE : u'web.png',
+ ed_glob.ID_HTML_GEN : u'html_gen.png',
+ ed_glob.ID_INDENT : u'indent.png',
+ ed_glob.ID_LOGGER : u'log.png',
+ ed_glob.ID_NEW : u'new.png',
+ ed_glob.ID_NEW_FOLDER : u'newfolder.png',
+ ed_glob.ID_NEW_WINDOW: u'newwin.png',
+ ed_glob.ID_NEXT_MARK : u'bmark_next.png',
+ ed_glob.ID_NEXT_POS : u'forward.png',
+ ed_glob.ID_OPEN : u'open.png',
+ ed_glob.ID_PACKAGE : u'package.png',
+ ed_glob.ID_PASTE : u'paste.png',
+ ed_glob.ID_PLUGMGR : u'plugin.png',
+ ed_glob.ID_PRE_MARK : u'bmark_pre.png',
+ ed_glob.ID_PRE_POS : u'backward.png',
+ ed_glob.ID_PREF : u'pref.png',
+ ed_glob.ID_PRINT : u'print.png',
+ ed_glob.ID_PRINT_PRE : u'printpre.png',
+ ed_glob.ID_PYSHELL : u'pyshell.png',
+ ed_glob.ID_REDO : u'redo.png',
+ ed_glob.ID_REFRESH : u'refresh.png',
+ ed_glob.ID_REMOVE : u'remove.png',
+ ed_glob.ID_RTF_GEN : u'rtf_gen.png',
+ ed_glob.ID_SAVE : u'save.png',
+ ed_glob.ID_SAVEALL : u'saveall.png',
+ ed_glob.ID_SAVEAS : u'saveas.png',
+ ed_glob.ID_SELECTALL : u'selectall.png',
+ ed_glob.ID_STOP : u'stop.png',
+ ed_glob.ID_STYLE_EDIT : u'style_edit.png',
+ ed_glob.ID_TEX_GEN : u'tex_gen.png',
+ ed_glob.ID_THEME : u'theme.png',
+ ed_glob.ID_UNDO : u'undo.png',
+ ed_glob.ID_UNINDENT : u'outdent.png',
+ ed_glob.ID_UP : u'up.png',
+ ed_glob.ID_USB : u'usb.png',
+ ed_glob.ID_WEB : u'web.png',
+ ed_glob.ID_ZOOM_IN : u'zoomi.png',
+ ed_glob.ID_ZOOM_OUT : u'zoomo.png',
+ ed_glob.ID_ZOOM_NORMAL : u'zoomd.png',
+ ed_glob.ID_READONLY : u'readonly.png',
+
+ # code elements
+ ed_glob.ID_CLASS_TYPE : u'class.png',
+ ed_glob.ID_FUNCT_TYPE : u'function.png',
+ ed_glob.ID_ELEM_TYPE : u'element.png',
+ ed_glob.ID_VARIABLE_TYPE : u'variable.png',
+ ed_glob.ID_ATTR_TYPE : u'attribute.png',
+ ed_glob.ID_PROPERTY_TYPE : u'property.png',
+ ed_glob.ID_METHOD_TYPE : u'method.png'
+}
+
+# File Type Art
+MIME_ART = { synglob.ID_LANG_ADA : u'ada.png',
+ synglob.ID_LANG_BASH : u'shell.png',
+ synglob.ID_LANG_BOO : u'boo.png',
+ synglob.ID_LANG_BOURNE : u'shell.png',
+ synglob.ID_LANG_C : u'c.png',
+ synglob.ID_LANG_CPP : u'cpp.png',
+ synglob.ID_LANG_CSH : u'shell.png',
+ synglob.ID_LANG_CSS : u'css.png',
+ synglob.ID_LANG_DIFF : u'diff.png',
+ synglob.ID_LANG_HTML : u'html.png',
+ synglob.ID_LANG_JAVA : u'java.png',
+ synglob.ID_LANG_KSH : u'shell.png',
+ synglob.ID_LANG_LATEX : u'tex.png',
+ synglob.ID_LANG_MAKE : u'makefile.png',
+ synglob.ID_LANG_PASCAL : u'pascal.png',
+ synglob.ID_LANG_PERL : u'perl.png',
+ synglob.ID_LANG_PHP : u'php.png',
+ synglob.ID_LANG_PS : u'postscript.png',
+ synglob.ID_LANG_PYTHON : u'python.png',
+ synglob.ID_LANG_RUBY : u'ruby.png',
+ synglob.ID_LANG_TCL : u'tcl.png',
+ synglob.ID_LANG_TEX : u'tex.png',
+ synglob.ID_LANG_TXT : u'text.png',
+ synglob.ID_LANG_XML : u'xml.png'
+ }
+
+#-----------------------------------------------------------------------------#
+
+class TangoTheme(plugin.Plugin):
+ """Represents the Tango Icon theme for Editra"""
+ plugin.Implements(ThemeI)
+
+ name = u'Tango'
+
+ def __GetArtPath(self, client, mime=False):
+ """Gets the path of the resource directory to get
+ the bitmaps from.
+ @param client: wx.ART_MENU/wx.ART_TOOLBAR
+ @keyword mime: is this a filetype icon lookup
+ @return: path of art resource
+ @rtype: string
+
+ """
+ clients = { wx.ART_MENU : u"menu",
+ wx.ART_TOOLBAR : u"toolbar",
+ wx.ART_OTHER : u"other" }
+
+ # Get the path
+ if ed_glob.CONFIG['THEME_DIR'] == u'':
+ theme = util.ResolvConfigDir(os.path.join(u"pixmaps", u"theme"))
+ ed_glob.CONFIG['THEME_DIR'] = theme
+
+ if mime:
+ path = os.path.join(ed_glob.CONFIG['THEME_DIR'],
+ self.GetName(), u'mime')
+ else:
+ path = os.path.join(ed_glob.CONFIG['THEME_DIR'],
+ self.GetName(),
+ clients.get(client, u"menu"))
+
+ path += os.sep
+ if os.path.exists(path):
+ return path
+ else:
+ return None
+
+ def GetName(self):
+ """Get the name of this theme
+ @return: string
+
+ """
+ return TangoTheme.name
+
+ def GetMenuBitmap(self, bmp_id):
+ """Get a menu bitmap
+ @param bmp_id: Id of bitmap to look for
+
+ """
+ if bmp_id in ART:
+ path = self.__GetArtPath(wx.ART_MENU, mime=False)
+ if path is not None:
+ path = path + ART[bmp_id]
+ if os.path.exists(path):
+ return wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
+ else:
+ return self.GetFileBitmap(bmp_id)
+
+ return wx.NullBitmap
+
+ def GetFileBitmap(self, bmp_id):
+ """Get a mime type bitmap from the theme
+ @param bmp_id: Id of filetype bitmap to look up
+ @see: L{syntax.synglob}
+
+ """
+ path = self.__GetArtPath(wx.ART_MENU, mime=True)
+ if path is not None and bmp_id in SYNTAX_IDS:
+ if bmp_id in MIME_ART:
+ req = path + MIME_ART[bmp_id]
+ if os.path.exists(req):
+ return wx.Bitmap(req, wx.BITMAP_TYPE_PNG)
+
+ # Try to fall back to bmp for plain text when above is not found
+ bkup = path + MIME_ART[synglob.ID_LANG_TXT]
+ if os.path.exists(bkup):
+ return wx.Bitmap(bkup, wx.BITMAP_TYPE_PNG)
+
+ return wx.NullBitmap
+
+ def GetOtherBitmap(self, bmp_id):
+ """Get a other catagory bitmap.
+ @param bmp_id: Id of art resource
+
+ """
+ if bmp_id in ART:
+ path = self.__GetArtPath(wx.ART_OTHER, mime=False)
+ if path is not None:
+ path = path + ART[bmp_id]
+ if os.path.exists(path):
+ return wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
+
+ return wx.NullBitmap
+
+ def GetToolbarBitmap(self, bmp_id):
+ """Get a toolbar bitmap
+ @param bmp_id: Id of bitmap to look for
+ @return: wx.NullBitmap or a 32x32 bitmap
+
+ """
+ if bmp_id in ART:
+# size = Profile_Get('ICON_SZ', default=(24, 24))
+ path = self.__GetArtPath(wx.ART_TOOLBAR, mime=False)
+ if path is not None:
+# tpath = os.path.join(path, '24', ART[bmp_id])
+# if size[0] == 24 and os.path.exists(tpath):
+# path = tpath
+# else:
+ path = path + ART[bmp_id]
+
+ if os.path.exists(path):
+ return wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
+
+ return wx.NullBitmap
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_thread.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_thread.py
new file mode 100644
index 0000000..e4c0cec
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_thread.py
@@ -0,0 +1,35 @@
+###############################################################################
+# Name: ed_thread.py #
+# Purpose: Provides Thread Pool interface and access #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Implements and provides the interface for dispatching asynchronous jobs through
+the Editra Threadpool.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_thread.py 67397 2011-04-05 20:46:23Z CJP $"
+__revision__ = "$Revision: 67397 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+
+# Local Imports
+import ebmlib
+
+#-----------------------------------------------------------------------------#
+
+class EdThreadPool(ebmlib.ThreadPool):
+ """Singleton ThreadPool"""
+ __metaclass__ = ebmlib.Singleton
+ def __init__(self):
+ super(EdThreadPool, self).__init__(5) # 5 Threads
+
+#-----------------------------------------------------------------------------#
+ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_toolbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_toolbar.py
new file mode 100644
index 0000000..91a18e4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_toolbar.py
@@ -0,0 +1,149 @@
+###############################################################################
+# Name: ed_toolbar.py #
+# Purpose: Editra's Toolbar #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This module creates Editra's toolbar. This toolbar is very simple and only adds
+automatic icon theming to whats already available in the base toolbar class.
+
+@summary: Editra's ToolBar class
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_toolbar.py 68340 2011-07-23 14:33:07Z CJP $"
+__revision__ = "$Revision: 68340 $"
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import wx
+import ed_glob
+import ed_msg
+from profiler import Profile_Get
+
+_ = wx.GetTranslation
+#--------------------------------------------------------------------------#
+# Global Variables
+TOOL_ID = [ ed_glob.ID_NEW, ed_glob.ID_OPEN, ed_glob.ID_SAVE, ed_glob.ID_PRINT,
+ ed_glob.ID_UNDO, ed_glob.ID_REDO, ed_glob.ID_COPY, ed_glob.ID_CUT,
+ ed_glob.ID_PASTE, ed_glob.ID_FIND, ed_glob.ID_FIND_REPLACE ]
+
+#--------------------------------------------------------------------------#
+
+class EdToolBar(wx.ToolBar):
+ """Toolbar wrapper class
+ @todo: make it more dynamic/configurable
+
+ """
+ def __init__(self, parent):
+ """Initializes the toolbar
+ @param parent: parent window of this toolbar
+
+ """
+ sstyle = wx.TB_HORIZONTAL | wx.NO_BORDER
+ if wx.Platform == '__WXGTK__':
+ sstyle = sstyle | wx.TB_DOCKABLE
+ super(EdToolBar, self).__init__(parent, style=sstyle)
+
+ # Attributes
+ self._theme = Profile_Get('ICONS')
+ self.SetToolBitmapSize(Profile_Get('ICON_SZ', 'size_tuple'))
+ self._PopulateTools()
+
+ # Event Handlers
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+
+ # Message Handlers
+ ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED)
+
+ def OnDestroy(self, evt):
+ if evt.GetId() == self.GetId():
+ ed_msg.Unsubscribe(self.OnThemeChange)
+ evt.Skip()
+
+ #---- End Init ----#
+
+ #---- Function Definitions----#
+ def _PopulateTools(self):
+ """Sets the tools in the toolbar
+ @postcondition: all default tools are added to toolbar
+
+ """
+ # Place Icons in toolbar
+ self.AddSimpleTool(ed_glob.ID_NEW, _("New"), _("Start a New File"))
+ self.AddSimpleTool(ed_glob.ID_OPEN, _("Open"), _("Open"))
+ self.AddSimpleTool(ed_glob.ID_SAVE, _("Save"), _("Save Current File"))
+ self.AddSimpleTool(ed_glob.ID_PRINT, _("Print"),
+ _("Print Current File"))
+ self.AddSeparator()
+ self.AddSimpleTool(ed_glob.ID_UNDO, _("Undo"), _("Undo Last Action"))
+ self.AddSimpleTool(ed_glob.ID_REDO, _("Redo"), _("Redo Last Undo"))
+ self.AddSeparator()
+ self.AddSimpleTool(ed_glob.ID_CUT, _("Cut"),
+ _("Cut Selected Text from File"))
+ self.AddSimpleTool(ed_glob.ID_COPY, _("Copy"),
+ _("Copy Selected Text to Clipboard"))
+ self.AddSimpleTool(ed_glob.ID_PASTE, _("Paste"),
+ _("Paste Text from Clipboard to File"))
+ self.AddSeparator()
+ self.AddSimpleTool(ed_glob.ID_FIND, _("Find"), _("Find Text"))
+ self.AddSimpleTool(ed_glob.ID_FIND_REPLACE, _("Find/Replace"),
+ _("Find and Replace Text"))
+ self.AddSeparator()
+
+ def AddSimpleTool(self, tool_id, lbl, helpstr):
+ """Overides the default function to allow for easier tool
+ generation/placement by automatically getting an appropriate icon from
+ the art provider.
+ @param tool_id: Id of tool to add
+ @param lbl: tool label
+ @param helpstr: tool help string
+
+ """
+ if self.GetToolBitmapSize() == (16, 16):
+ client = wx.ART_MENU
+ else:
+ client = wx.ART_TOOLBAR
+ tool_bmp = wx.ArtProvider.GetBitmap(str(tool_id), client)
+ wx.ToolBar.AddSimpleTool(self, tool_id, tool_bmp, _(lbl), _(helpstr))
+
+ def GetToolTheme(self):
+ """Returns the name of the current toolsets theme
+ @return: name of icon theme used by this toolbar
+
+ """
+ return self._theme
+
+ def OnThemeChange(self, msg):
+ """Update the icons when the icon theme has changed
+ @param msg: Message object
+
+ """
+ self.ReInit()
+
+ def ReInit(self):
+ """Re-Initializes the tools in the toolbar
+ @postcondition: all tool icons are changed to match current theme
+
+ """
+ self._theme = Profile_Get('ICONS')
+ csize = self.GetToolBitmapSize()
+ nsize = Profile_Get('ICON_SZ', 'size_tuple')
+ if nsize != csize:
+ # Size changed must recreate toolbar
+ wx.CallAfter(self.GetParent().SetupToolBar)
+ return
+
+ # Change Bitmaps
+ if self.GetToolBitmapSize() == (16, 16):
+ client = wx.ART_MENU
+ else:
+ client = wx.ART_TOOLBAR
+
+ for tool_id in TOOL_ID:
+ bmp = wx.ArtProvider.GetBitmap(str(tool_id), client)
+ self.SetToolNormalBitmap(tool_id, bmp)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_txt.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_txt.py
new file mode 100644
index 0000000..a7994f4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_txt.py
@@ -0,0 +1,836 @@
+###############################################################################
+# Name: Cody Precord #
+# Purpose: File abstraction layer and text utilities #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Text/Unicode handling functions and File wrapper class
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_txt.py 72103 2012-07-15 15:02:42Z CJP $"
+__revision__ = "$Revision: 72103 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import sys
+import re
+import time
+import wx
+import codecs
+import encodings as enclib
+import locale
+from StringIO import StringIO
+
+# Local Imports
+from util import Log
+from profiler import Profile_Get
+import ed_msg
+import ebmlib
+import ed_thread
+
+#--------------------------------------------------------------------------#
+# Globals
+
+# The default fallback encoding
+DEFAULT_ENCODING = locale.getpreferredencoding()
+try:
+ codecs.lookup(DEFAULT_ENCODING)
+except (LookupError, TypeError):
+ DEFAULT_ENCODING = 'utf-8'
+
+# File Helper Functions
+# NOTE: keep in synch with CheckBom function
+BOM = { 'utf-8' : codecs.BOM_UTF8,
+ 'utf-16' : codecs.BOM,
+ 'utf-32' : codecs.BOM_UTF32 }
+
+# Regex for extracting magic comments from source files
+# i.e *-* coding: utf-8 *-*, encoding=utf-8, ect...
+# The first group from this expression will be the encoding.
+RE_MAGIC_COMMENT = re.compile("coding[:=]\s*\"*([-\w.]+)\"*")
+
+# File Load States
+FL_STATE_START = 0
+FL_STATE_READING = 1
+FL_STATE_PAUSED = 2
+FL_STATE_END = 3
+FL_STATE_ABORTED = 4
+
+#--------------------------------------------------------------------------#
+
+class ReadError(Exception):
+ """Error happened while trying to read the file"""
+ pass
+
+class WriteError(Exception):
+ """Error happened while trying to write the file"""
+ pass
+
+#--------------------------------------------------------------------------#
+
+class EdFile(ebmlib.FileObjectImpl):
+ """Wrapper for representing a file object that stores data
+ about the file encoding and path.
+
+ """
+ _Checker = ebmlib.FileTypeChecker()
+
+ def __init__(self, path=u'', modtime=0):
+ """Create the file wrapper object
+ @keyword path: the absolute path to the file
+ @keyword modtime: file modification time
+
+ """
+ super(EdFile, self).__init__(path, modtime)
+
+ # Attributes
+ self._magic = dict(comment=None, bad=False)
+ self.encoding = None
+ self.bom = None
+ self._mcallback = list()
+ self.__buffer = None
+ self._raw = False # Raw bytes?
+ self._fuzzy_enc = False
+ self._job = None # async file read job
+
+ def _SanitizeBOM(self, bstring):
+ """Remove byte order marks that get automatically added by some codecs"""
+ for enc in ('utf-8', 'utf-32', 'utf-16'):
+ bmark = BOM.get(enc)
+ if bstring.startswith(bmark):
+ bstring = bstring.lstrip(bmark)
+ break
+ return bstring
+
+ def _HandleRawBytes(self, bytes_value):
+ """Handle prepping raw bytes for return to the buffer
+ @param bytes_value: raw read bytes
+ @return: string
+
+ """
+ Log("[ed_txt][info] HandleRawBytes called")
+ if self._magic['comment']:
+ self._magic['bad'] = True
+ # Return the raw bytes to put into the buffer
+ self._raw = True
+ return '\0'.join(bytes_value)+'\0'
+
+ def _ResetBuffer(self):
+ Log("[ed_txt][info] Resetting buffer")
+ if self.__buffer is not None:
+ self.__buffer.close()
+ del self.__buffer
+ self.__buffer = StringIO()
+
+ Encoding = property(lambda self: self.GetEncoding())
+
+ def AddModifiedCallback(self, callback):
+ """Set modified callback method
+ @param callback: callable
+
+ """
+ self._mcallback.append(callback)
+
+ def CleanUp(self):
+ """Cleanup callback"""
+ pass
+
+ def Clone(self):
+ """Clone the file object
+ @return: EdFile
+
+ """
+ fileobj = EdFile(self.Path, self.ModTime)
+ fileobj.SetLastError(self.last_err)
+ fileobj.SetEncoding(self.encoding)
+ fileobj.bom = self.bom
+ fileobj._magic = dict(self._magic)
+ fileobj._fuzzy_enc = self._fuzzy_enc
+ for cback in self._mcallback:
+ fileobj.AddModifiedCallback(cback)
+ return fileobj
+
+ def DecodeText(self):
+ """Decode the text in the buffer and return a unicode string.
+ @return: unicode or str
+
+ """
+ assert self.__buffer is not None, "No buffer!"
+ assert self.encoding is not None, "Encoding Not Set!"
+
+ bytes_value = self.__buffer.getvalue()
+ ustr = u""
+ try:
+ if not self._fuzzy_enc or not EdFile._Checker.IsBinaryBytes(bytes_value):
+ if self.bom is not None:
+ Log("[ed_txt][info] Stripping %s BOM from text" % self.encoding)
+ bytes_value = bytes_value.replace(self.bom, '', 1)
+
+ Log("[ed_txt][info] Attempting to decode with: %s" % self.encoding)
+ ustr = bytes_value.decode(self.encoding)
+ # TODO: temporary...maybe
+ # Check for utf-16 encodings which use double bytes
+ # can result in NULLs in the string if decoded with
+ # other encodings.
+ if str('\0') in ustr:
+ Log("[ed_txt][info] NULL terminators found in decoded str")
+ Log("[ed_txt][info] Attempting UTF-16/32 detection...")
+ for utf_encoding in ('utf_16', 'utf_32'):
+ try:
+ tmpstr = bytes_value.decode(utf_encoding)
+ except UnicodeDecodeError:
+ pass
+ else:
+ self.encoding = utf_encoding
+ ustr = tmpstr
+ Log("[ed_txt][info] %s detected" % utf_encoding)
+ break
+ else:
+ Log("[ed_txt][info] No valid UTF-16/32 bytes detected")
+ else:
+ # Binary data was read
+ Log("[ed_txt][info] Binary bytes where read")
+ ustr = self._HandleRawBytes(bytes_value)
+ except (UnicodeDecodeError, LookupError), msg:
+ Log("[ed_txt][err] Error while reading with %s" % self.encoding)
+ Log("[ed_txt][err] %s" % msg)
+ self.SetLastError(unicode(msg))
+ self.Close()
+ # Decoding failed so convert to raw bytes for display
+ ustr = self._HandleRawBytes(bytes_value)
+ else:
+ # Log success
+ if not self._raw:
+ Log("[ed_txt][info] Decoded %s with %s" % \
+ (self.GetPath(), self.encoding))
+
+ # Scintilla bug, SetText will quit at first null found in the
+ # string. So join the raw bytes and stuff them in the buffer instead.
+ # TODO: are there other control characters that need to be checked
+ # for besides NUL?
+ if not self._raw and '\0' in ustr:
+ # Return the raw bytes to put into the buffer
+ Log("[ed_txt][info] DecodeText - joining nul terminators")
+ ustr = '\0'.join(bytes_value)+'\0'
+ self._raw = True
+
+ if self._raw:
+ # TODO: wx/Scintilla Bug?
+ # Replace \x05 with a space as it causes the buffer
+ # to crash when its inserted.
+ Log("[ed_txt][info] DecodeText - raw - set encoding to binary")
+ ustr = ustr.replace('\x05', ' ')
+ self.SetEncoding('binary')
+ self._raw = True
+
+ return ustr
+
+ def DetectEncoding(self):
+ """Try to determine the files encoding
+ @precondition: File handle has been opened and is valid
+ @postcondition: encoding and bom attributes will be set
+
+ """
+ if self.encoding != None:
+ msg = ("[ed_txt][info] DetectEncoding, skipping do to user set "
+ "encoding: %s") % self.encoding
+ Log(msg)
+ return
+
+ assert self.Handle is not None, "File handle not initialized"
+ lines = [ self.Handle.readline() for x in range(2) ]
+ self.Handle.seek(0)
+ enc = None
+ if len(lines):
+ # First check for a Byte Order Mark
+ enc = CheckBom(lines[0])
+
+ # If no byte-order mark check for an encoding comment
+ if enc is None:
+ Log("[ed_txt][info] DetectEncoding - Check magic comment")
+ self.bom = None
+ if not self._magic['bad']:
+ enc = CheckMagicComment(lines)
+ if enc:
+ self._magic['comment'] = enc
+ else:
+ Log("[ed_txt][info] File Has %s BOM" % enc)
+ self.bom = BOM.get(enc, None)
+
+ if enc is None:
+ Log("[ed_txt][info] Doing brute force encoding check")
+ enc = GuessEncoding(self.GetPath(), 4096)
+
+ if enc is None:
+ self._fuzzy_enc = True
+ enc = Profile_Get('ENCODING', default=DEFAULT_ENCODING)
+
+ Log("[ed_txt][info] DetectEncoding - Set Encoding to %s" % enc)
+ self.encoding = enc
+
+ def EncodeText(self):
+ """Do a trial run of encoding all the text to ensure that we can
+ determine an encoding that will correctly be able to write the data
+ to disk.
+ @return: bool
+
+ """
+ bOk = True
+ txt = self.__buffer.read(8)
+ self.__buffer.seek(0)
+ if not ebmlib.IsUnicode(txt):
+ # Already a string so nothing to do
+ return bOk
+
+ encs = GetEncodings()
+ if self.encoding is None:
+ self.encoding = Profile_Get('ENCODING', default=DEFAULT_ENCODING)
+ encs.insert(0, self.encoding)
+ cenc = self.encoding
+
+ readsize = min(self.__buffer.len, 4096)
+ for enc in encs:
+ self.__buffer.seek(0)
+ try:
+ tmpchars = self.__buffer.read(readsize)
+ while len(tmpchars):
+ tmpchars.encode(enc)
+ tmpchars = self.__buffer.read(readsize)
+ self.encoding = enc
+ self.__buffer.seek(0)
+ self.ClearLastError()
+ except LookupError, msg:
+ Log("[ed_txt][err] Invalid encoding: %s" % enc)
+ Log("[ed_txt][err] %s" % msg)
+ self.SetLastError(unicode(msg))
+ except UnicodeEncodeError, msg:
+ Log("[ed_txt][err] Failed to encode text with %s" % enc)
+ Log("[ed_txt][err] %s" % msg)
+ self.SetLastError(unicode(msg))
+ else:
+ break
+ else:
+ bOk = False
+ raise WriteError("Failed to encode text to byte string")
+
+ # Log if the encoding changed due to encoding errors
+ if self.encoding != cenc:
+ Log("[ed_txt][warn] Used encoding %s differs from original %s" %\
+ (self.encoding, cenc))
+
+ self.__buffer.seek(0)
+ return bOk
+
+ def FireModified(self):
+ """Fire the modified callback(s)"""
+ remove = list()
+ for idx, mcallback in enumerate(self._mcallback):
+ try:
+ mcallback()
+ except:
+ remove.append(idx)
+
+ # Cleanup any bad callbacks
+ if len(remove):
+ remove.reverse()
+ for idx in remove:
+ self._mcallback.pop(idx)
+
+ def GetEncoding(self):
+ """Get the encoding used by the file it may not be the
+ same as the encoding requested at construction time
+ @return: string encoding name
+
+ """
+ if self.encoding is None:
+ # Guard against early entry
+ return Profile_Get('ENCODING', default=DEFAULT_ENCODING)
+ return self.encoding
+
+ def GetMagic(self):
+ """Get the magic comment if one was present
+ @return: string or None
+
+ """
+ return self._magic['comment']
+
+ def HasBom(self):
+ """Return whether the file has a bom byte or not
+ @return: bool
+
+ """
+ return self.bom is not None
+
+ def IsRawBytes(self):
+ """Were only raw bytes read during the last read operation?
+ @return: bool
+
+ """
+ return self._raw
+
+ def IsReadOnly(self):
+ """Return as read only when file is read only or if raw bytes"""
+ return super(EdFile, self).IsReadOnly() or self.IsRawBytes()
+
+ def Read(self, chunk=512):
+ """Get the contents of the file as a string, automatically handling
+ any decoding that may be needed.
+ @keyword chunk: read size
+ @return: unicode str
+ @throws: ReadError Failed to open file for reading
+
+ """
+ if self.DoOpen('rb'):
+ self.DetectEncoding()
+
+ if self.encoding is None:
+ # fall back to user setting
+ self.encoding = Profile_Get('ENCODING', default=DEFAULT_ENCODING)
+ Log(("[ed_txt][warn] Failed to detect encoding "
+ "falling back to default: %s") % self.encoding)
+
+ self._ResetBuffer()
+ self._raw = False
+
+ Log("[ed_txt][info] Read - Start reading")
+ tmp = self.Handle.read(chunk)
+ while len(tmp):
+ self.__buffer.write(tmp)
+ tmp = self.Handle.read(chunk)
+ Log("[ed_txt][info] Read - End reading")
+
+ self.Close()
+ txt = self.DecodeText()
+ self.SetModTime(ebmlib.GetFileModTime(self.GetPath()))
+ self._ResetBuffer()
+ return txt
+ else:
+ Log("[ed_txt][err] Read Error: %s" % self.GetLastError())
+ raise ReadError, self.GetLastError()
+
+ def ReadAsync(self, control):
+ """Read the file asynchronously on a separate thread
+ @param control: text control to send text to
+
+ """
+ Log("[ed_txt][info] EdFile.ReadAsync()")
+ pid = control.GetTopLevelParent().Id
+ filesize = ebmlib.GetFileSize(self.GetPath())
+ ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (pid, 1, filesize))
+ # Fork off async job to threadpool
+ self._job = FileReadJob(control, self.ReadGenerator, 4096)
+ ed_thread.EdThreadPool().QueueJob(self._job.run)
+
+ def ReadGenerator(self, chunk=512):
+ """Get the contents of the file as a string, automatically handling
+ any decoding that may be needed.
+
+ @keyword chunk: read size
+ @return: unicode (generator)
+ @throws: ReadError Failed to open file for reading.
+
+ """
+ if self.DoOpen('rb'):
+ # Throttle yielded text to reduce event over head
+ filesize = ebmlib.GetFileSize(self.Path)
+ throttle = max(chunk, filesize/100)
+
+ self.DetectEncoding()
+ try:
+ # Must use codec reader to ensure correct number of
+ # bytes are read in to be decoded.
+ reader = codecs.getreader(self.Encoding)(self.Handle)
+ buffered_data = StringIO()
+ while True:
+ tmp = reader.read(chunk)
+ if not len(tmp):
+ if buffered_data.len:
+ yield buffered_data.getvalue()
+ buffered_data.close()
+ break
+
+ buffered_data.write(tmp)
+ if buffered_data.len >= throttle:
+ yield buffered_data.getvalue()
+ buffered_data.close()
+ buffered_data = StringIO()
+ except Exception, msg:
+ Log("[ed_txt][err] Error while reading with %s" % self.Encoding)
+ Log("[ed_txt][err] %s" % msg)
+ self.SetLastError(unicode(msg))
+ self.Close()
+ if self._magic['comment']:
+ self._magic['bad'] = True
+
+ Log("[ed_txt][info] Decoded %s with %s" % (self.Path, self.Encoding))
+ self.SetModTime(ebmlib.GetFileModTime(self.Path))
+ else:
+ raise ReadError, self.GetLastError()
+
+ def RemoveModifiedCallback(self, callback):
+ """Remove a registered callback
+ @param callback: callable to remove
+
+ """
+ if callback in self._mcallback:
+ self._mcallback.remove(callback)
+
+ def ResetAll(self):
+ """Reset all attributes of this file"""
+ super(EdFile, self).ResetAll()
+ self._ResetBuffer()
+ self._magic = dict(comment=None, bad=False)
+ self.encoding = Profile_Get('ENCODING', default=DEFAULT_ENCODING)
+ self.bom = None
+
+ def SetEncoding(self, enc):
+ """Explicitly set/change the encoding of the file
+ @param enc: encoding to change to
+
+ """
+ if enc is None:
+ enc = DEFAULT_ENCODING
+ self.encoding = enc
+
+ def ReadLines(self):
+ """Get the contents of the file as a list of lines
+ @return: list of strings
+
+ """
+ raise NotImplementedError
+
+ def Write(self, value):
+ """Write the given value to the file
+ @param value: (Unicode) String of text to write to disk
+ @note: exceptions are allowed to be raised for the writing
+ @throws: WriteError Failed to open file for writing
+ @throws: UnicodeEncodeError Failed to encode text using set encoding
+
+ """
+ ctime = time.time()
+ Log("[ed_txt][info] Write - Called: %s - Time: %d" % (self.Path, ctime))
+
+ # Check if a magic comment was added or changed
+ self._ResetBuffer()
+ self.__buffer.write(value)
+ self.__buffer.seek(0)
+ enc = CheckMagicComment([ self.__buffer.readline() for x in range(2) ])
+ self.__buffer.seek(0)
+
+ # Update encoding if necessary
+ if enc is not None:
+ Log("[ed_txt][info] Write: found magic comment: %s" % enc)
+ self.encoding = enc
+
+ # Encode to byte string
+ # Do before opening file so that encoding failures don't cause file
+ # data to get lost!
+ if self.EncodeText():
+ Log("[ed_txt][info] Write Successful test encode with %s" % self.Encoding)
+
+ # Open and write the file
+ if self.DoOpen('wb'):
+ Log("[ed_txt][info] Opened %s, writing as %s" % (self.Path, self.Encoding))
+
+ if self.HasBom():
+ Log("[ed_txt][info] Adding BOM back to text")
+ self.Handle.write(self.bom)
+
+ # Write the file to disk
+ chunk = min(self.__buffer.len, 4096)
+ buffer_read = self.__buffer.read
+ filewrite = self.Handle.write
+ fileflush = self.Handle.flush
+ sanitize = self._SanitizeBOM
+ tmp = buffer_read(chunk)
+ while len(tmp):
+ tmp_bytes = sanitize(tmp.encode(self.Encoding))
+ filewrite(tmp_bytes)
+ fileflush()
+ tmp = buffer_read(chunk)
+
+ self._ResetBuffer() # Free buffer
+ self.Close()
+ Log("[ed_txt][info] %s was written successfully" % self.Path)
+ else:
+ self._ResetBuffer()
+ raise WriteError, self.GetLastError()
+
+ Log("[ed_txt][info] Write - Complete: %s - Time: %d" %
+ (self.Path, time.time() - ctime))
+
+#-----------------------------------------------------------------------------#
+
+class FileReadJob(object):
+ """Job for running an async file read in a background thread"""
+ def __init__(self, receiver, task, *args, **kwargs):
+ """Create the thread
+ @param receiver: Window to receive events
+ @param task: generator method to call
+ @param *args: positional arguments to pass to task
+ @param **kwargs: keyword arguments to pass to task
+
+ """
+ super(FileReadJob, self).__init__()
+
+ # Attributes
+ self.cancel = False
+ self._task = task
+ self.receiver = receiver
+ self._args = args
+ self._kwargs = kwargs
+ self.pid = receiver.TopLevelParent.Id
+
+ def run(self):
+ """Read the text"""
+ evt = FileLoadEvent(edEVT_FILE_LOAD, wx.ID_ANY, None, FL_STATE_START)
+ wx.PostEvent(self.receiver, evt)
+ time.sleep(.75) # give ui a chance to get ready
+
+ count = 1
+ for txt in self._task(*self._args, **self._kwargs):
+ if self.cancel:
+ break
+
+ evt = FileLoadEvent(edEVT_FILE_LOAD, wx.ID_ANY, txt)
+ evt.SetProgress(count * self._args[0])
+ wx.PostEvent(self.receiver, evt)
+ count += 1
+
+ evt = FileLoadEvent(edEVT_FILE_LOAD, wx.ID_ANY, None, FL_STATE_END)
+ wx.PostEvent(self.receiver, evt)
+
+ def Cancel(self):
+ """Cancel the running task"""
+ self.cancel = True
+
+#-----------------------------------------------------------------------------#
+
+edEVT_FILE_LOAD = wx.NewEventType()
+EVT_FILE_LOAD = wx.PyEventBinder(edEVT_FILE_LOAD, 1)
+class FileLoadEvent(wx.PyEvent):
+ """Event to signal that a chunk of text haes been read"""
+ def __init__(self, etype, eid, value=None, state=FL_STATE_READING):
+ """Creates the event object"""
+ super(FileLoadEvent, self).__init__(eid, etype)
+
+ # Attributes
+ self._state = state
+ self._value = value
+ self._prog = 0
+
+ def HasText(self):
+ """Returns true if the event has text
+ @return: bool whether the event contains text
+
+ """
+ return self._value is not None
+
+ def GetProgress(self):
+ """Get the current progress of the load"""
+ return self._prog
+
+ def GetState(self):
+ """Get the state of the file load action
+ @return: int (FL_STATE_FOO)
+
+ """
+ return self._state
+
+ def GetValue(self):
+ """Returns the value from the event.
+ @return: the value of this event
+
+ """
+ return self._value
+
+ def SetProgress(self, progress):
+ """Set the number of bytes that have been read
+ @param progress: int
+
+ """
+ self._prog = progress
+
+#-----------------------------------------------------------------------------#
+# Utility Function
+def CheckBom(line):
+ """Try to look for a bom byte at the beginning of the given line
+ @param line: line (first line) of a file
+ @return: encoding or None
+
+ """
+ Log("[ed_txt][info] CheckBom called")
+ has_bom = None
+ # NOTE: MUST check UTF-32 BEFORE utf-16
+ for enc in ('utf-8', 'utf-32', 'utf-16'):
+ bom = BOM[enc]
+ if line.startswith(bom):
+ has_bom = enc
+ break
+ return has_bom
+
+def CheckMagicComment(lines):
+ """Try to decode the given text on the basis of a magic
+ comment if one is present.
+ @param lines: list of lines to check for a magic comment
+ @return: encoding or None
+
+ """
+ Log("[ed_txt][info] CheckMagicComment: %s" % str(lines))
+ enc = None
+ for line in lines:
+ match = RE_MAGIC_COMMENT.search(line)
+ if match:
+ enc = match.group(1)
+ try:
+ codecs.lookup(enc)
+ except LookupError:
+ enc = None
+ break
+
+ Log("[ed_txt][info] MagicComment is %s" % enc)
+ return enc
+
+def DecodeString(string, encoding=None):
+ """Decode the given string to Unicode using the provided
+ encoding or the DEFAULT_ENCODING if None is provided.
+ @param string: string to decode
+ @keyword encoding: encoding to decode string with
+
+ """
+ if encoding is None:
+ encoding = DEFAULT_ENCODING
+
+ if not ebmlib.IsUnicode(string):
+ try:
+ rtxt = string.decode(encoding)
+ except Exception, msg:
+ Log("[ed_txt][err] DecodeString with %s failed" % encoding)
+ Log("[ed_txt][err] %s" % msg)
+ rtxt = string
+ return rtxt
+ else:
+ # The string is already unicode so just return it
+ return string
+
+def EncodeString(string, encoding=None):
+ """Try and encode a given unicode object to a string
+ with the provided encoding returning that string. The
+ default encoding will be used if None is given for the
+ encoding.
+ @param string: unicode object to encode into a string
+ @keyword encoding: encoding to use for conversion
+
+ """
+ if not encoding:
+ encoding = DEFAULT_ENCODING
+
+ if ebmlib.IsUnicode(string):
+ try:
+ rtxt = string.encode(encoding)
+ except LookupError:
+ rtxt = string
+ return rtxt
+ else:
+ return string
+
+def FallbackReader(fname):
+ """Guess the encoding of a file by brute force by trying one
+ encoding after the next until something succeeds.
+ @param fname: file path to read from
+ @todo: deprecate this method
+
+ """
+ txt = None
+ with open(fname, 'rb') as handle:
+ byte_str = handle.read()
+ for enc in GetEncodings():
+ try:
+ txt = byte_str.decode(enc)
+ except Exception, msg:
+ continue
+ else:
+ return (enc, txt)
+
+ return (None, None)
+
+def GuessEncoding(fname, sample):
+ """Attempt to guess an encoding
+ @param fname: filename
+ @param sample: pre-read amount
+ @return: encoding or None
+
+ """
+ for enc in GetEncodings():
+ try:
+ with open(fname, 'rb') as handle:
+ with codecs.getreader(enc)(handle) as reader:
+ value = reader.read(sample)
+ if str('\0') in value:
+ continue
+ else:
+ return enc
+ except Exception, msg:
+ continue
+ return None
+
+def GetEncodings():
+ """Get a list of possible encodings to try from the locale information
+ @return: list of strings
+
+ """
+ encodings = list()
+ encodings.append(Profile_Get('ENCODING', None))
+
+ try:
+ encodings.append(locale.getpreferredencoding())
+ except:
+ pass
+
+ encodings.append('utf-8')
+
+ try:
+ if hasattr(locale, 'nl_langinfo'):
+ encodings.append(locale.nl_langinfo(locale.CODESET))
+ except:
+ pass
+ try:
+ encodings.append(locale.getlocale()[1])
+ except:
+ pass
+ try:
+ encodings.append(locale.getdefaultlocale()[1])
+ except:
+ pass
+ encodings.append(sys.getfilesystemencoding())
+ encodings.append('utf-16')
+ encodings.append('utf-16-le') # for files without BOM...
+ encodings.append('latin-1')
+
+ # Normalize all names
+ normlist = [ enclib.normalize_encoding(enc) for enc in encodings if enc]
+
+ # Clean the list for duplicates and None values
+ rlist = list()
+ codec_list = list()
+ for enc in normlist:
+ if enc is not None and len(enc):
+ enc = enc.lower()
+ if enc not in rlist:
+ # Ascii is useless so ignore it (ascii, us_ascii, ...)
+ if 'ascii' in enc:
+ continue
+
+ try:
+ ctmp = codecs.lookup(enc)
+ if ctmp.name not in codec_list:
+ codec_list.append(ctmp.name)
+ rlist.append(enc)
+ except LookupError:
+ pass
+ return rlist
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_vim.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_vim.py
new file mode 100644
index 0000000..2fea948
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_vim.py
@@ -0,0 +1,1421 @@
+###############################################################################
+# Name: ed_vim.py #
+# Purpose: Vim emulation #
+# Author: Hasan Aljudy #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+Vim emulation class and helper methods to implement vim emulation in Editra's
+text buffer.
+
+"""
+
+__author__ = "Hasan Aljudy"
+__cvsid__ = "$Id: ed_vim.py 71184 2012-04-11 23:17:52Z CJP $"
+__revision__ = "$Revision: 71184 $"
+
+# ---------------------------------------------------------------------------- #
+# Imports
+import wx
+import re
+import string
+
+# Local Imports
+import ebmlib
+
+# ---------------------------------------------------------------------------- #
+
+# TODO:CJP maybe replace all repeatable methods with this decorator to reduce
+# repeated code. NOTE: may need to name different as the word repeat
+# is used in this module in many places.
+#def repeat(funct, count=1):
+# def rwrap(*args, **kwargs):
+# for i in range(count):
+# funct()
+# return rwrap
+
+# ---------------------------------------------------------------------------- #
+
+def Parse(cmd, editor):
+ """Parses a command and (if applicable) executes it on an editor
+ @param cmd: the command string
+ @param editor: a proxy object used to issue commands to the editor
+ @return: boolean as a signal to the caller as to whether it should
+ clear its command buffer.
+ i.e. True if command is handled or invalid
+ False if we need more input before we can execute the command
+
+ """
+ handled = True
+ handler = GetHandler(cmd)
+ if handler is None:
+ if cmd.isdigit():
+ handled = False
+ else:
+ need_more = DoHandle(handler, cmd, editor)
+ if need_more:
+ handled = False
+ return handled
+
+# ---------------------------------------------------------------------------- #
+
+class EditraCommander(object):
+ """Proxy object that sends commands to the editor
+
+ The purpose of this class is to make vim support more abstract and portable
+ so in theory one could add Vim Emulation to another editor using this module
+ by just creating a commander object for it and re-implementing all of these
+ methods defined below.
+
+ The methods are based on turtle geometry. Everything is relative to the
+ position of the cursor. Commands shouldn't take a position argument; they
+ should all work on the current position of the cursor.
+
+ """
+ def __init__(self, keyprocessor):
+ super(EditraCommander, self).__init__()
+
+ # Attributes
+ self.keyprocessor = keyprocessor
+ self.stc = keyprocessor.stc
+ self.LastChangeCommand = None
+ self.LastInsertedText = None
+ self.InsertRepeat = 1
+ self.CaretStack = []
+ self.ColumnStack = []
+ self.ScrollStack = []
+ self.LastFindChar = None
+ self._Bookmarks = {}
+
+ @property
+ def STC(self):
+ return self.stc
+
+ def InsertMode(self):
+ """Put editor in insert mode"""
+ self.keyprocessor.InsertMode()
+
+ def ReplaceMode(self):
+ """Put editor in replace mode"""
+ self.keyprocessor.ReplaceMode()
+
+ def VisualMode(self):
+ """Put editor in visual (selection) mode"""
+ self.keyprocessor.VisualMode()
+
+ def NormalMode(self):
+ """Put editor in normal (command) mode"""
+ self.keyprocessor.NormalMode()
+
+ def IsNormalMode(self):
+ return self.keyprocessor.IsNormalMode()
+
+ def IsInsertMode(self):
+ return self.keyprocessor.IsInsertMode()
+
+ def InsertRepetition(self):
+ """Repeat last inserted text according to the value that was set
+ in SetInsertRepeat
+
+ """
+ if self.InsertRepeat > 1:
+ self.RepeatChangeCommand(self.InsertRepeat - 1)
+ self.InsertRepeat = 1
+
+ def IsAtLineEnd(self):
+ lnum = self.stc.GetCurrentLine()
+ epos = self.stc.GetLineEndPosition(lnum)
+ return epos == self._GetPos()
+
+ def IsAtLineStart(self):
+ """Is the cursor currently at the start of a line
+ @return: bool
+
+ """
+ return self._GetCol() == 0
+
+ def Undo(self, repeat):
+ """Undo actions in the buffer
+ @param repeat: int
+
+ """
+ for i in range(repeat):
+ self.stc.Undo()
+
+ def Redo(self, repeat):
+ """Redo actions in the buffer
+ @param repeat: int
+
+ """
+ for i in range(repeat):
+ self.stc.Redo()
+
+ def _GetPos(self):
+ """Get caret position"""
+ return self.stc.GetCurrentPos()
+
+ def _SetPos(self, pos):
+ """Set caret position"""
+ self.stc.GotoPos(pos)
+
+ def SelectLines(self, repeat):
+ """Select specified number of lines starting with current line
+ and going down
+ @param repeat: int
+
+ """
+ cline = self.stc.GetCurrentLine()
+ lline = self.stc.GetLineCount() - 1
+ self.GotoLineStart()
+ if cline == lline:
+ cpos = self.stc.GetCurrentPos() - len(self.stc.GetEOLChar())
+ cpos = max(0, cpos)
+ self.stc.GotoPos(cpos)
+ self.PushCaret()
+ self.MoveDown(repeat)
+ self.StartSelection()
+ self.PopCaret()
+ self.EndSelection()
+
+ def PushCaret(self):
+ """Pushes caret position for later restoration"""
+ self.CaretStack += [self._GetPos()]
+
+ def PopCaret(self, restore=True):
+ """If no parameters are sent, restores caret position. If on the
+ other hand, the restore keyword is set to false, the caret is not
+ restored, but the last pushed value is discarded
+ @keyword restore: bool
+
+ """
+ pos = self.CaretStack[-1]
+ self.CaretStack = self.CaretStack[:-1]
+ if restore:
+ self._SetPos(pos)
+
+ def PushColumn(self):
+ """Push column position for later restoration"""
+ self.ColumnStack += [self._GetCol()]
+
+ def PopColumn(self, restore=True):
+ """Pop caret position, and optionally discard it
+ @keyword restore: if set to False, column will be discarded
+
+ """
+ column = self.ColumnStack[-1]
+ self.ColumnStack = self.ColumnStack[:-1]
+ if restore:
+ self.GotoColumn(column)
+
+ def PushScroll(self):
+ """Push current scrolling state for later restoration"""
+ self.ScrollStack += [self.stc.GetFirstVisibleLine()]
+
+ def PopScroll(self, restore=True):
+ """If not parameters are sent, restores the scrolling state. If on the
+ other hadn, the restore keywords it set to false, then the last pushed
+ scroll state is discarded
+ @keyword restore: bool
+
+ """
+ line = self.ScrollStack[-1]
+ self.ScrollStack[:-1]
+ if restore:
+ self.stc.ScrollToLine(line)
+
+ def _IsLine(self, text):
+ """Check if text ends with EOL
+ @param text: string
+
+ """
+ eol = self.stc.GetEOLChar()
+ eol_len = len(eol)
+ if len(text) > eol_len:
+ return text[-len(eol):] == eol
+ else:
+ return False
+
+ def _GetCol(self):
+ """Get the X position of the caret, aka column"""
+ return self.stc.GetColumn(self._GetPos())
+
+ def _SetCol(self, col):
+ """Set the X position of the caret
+ @param col: int
+
+ """
+ self.stc.GotoColumn(col)
+
+ def GotoColumn(self, column):
+ """Goto the specified column number on the current line"""
+ self._SetCol(column)
+ self.stc.ChooseCaretX()
+
+ def StartSelection(self):
+ """Record the starting place for selection
+ Nothing is sent to the actual text control, just some internal
+ state is recorded.
+ @see: EndSelection
+
+ """
+ self._Anchor = self._GetPos()
+
+ def EndSelection(self):
+ """Set the selection to start from the starting position as it was set
+ by StartSelection to the current caret position
+
+ It doesn't matter whether the starting position is before or after the
+ ending position
+
+ """
+ self.stc.SetSelection(self._Anchor, self._GetPos())
+
+ def ExtendSelection(self):
+ """If the selection was already ended, and the caret moved, this method
+ will extend the selection to the new caret position.
+
+ """
+ self.EndSelection() # happens to be the same implementation ..
+
+ def Deselect(self):
+ """Unselect. Puts caret to the (visual) start of selection"""
+ start, end = self._GetSelectionRange()
+ self._SetPos(start)
+ self.StartSelection()
+ self.EndSelection()
+
+ def GotoLine(self, line):
+ """Goto the start of indentation of given line"""
+ # PostionFromLine returns the position past the last character on the
+ # line. So need to look at previous line to get the correct position.
+ pos = self.stc.PositionFromLine(max(0,line-1))
+ self._SetPos(pos)
+ self.GotoIndentStart()
+
+ def GotoLastLine(self):
+ self.GotoLine(self.stc.GetLineCount())
+
+ def GotoLineStart(self):
+ """Goto the beginning of the current line"""
+ self.stc.Home()
+
+ def GotoIndentStart(self):
+ """Goto to the first non-space character on the current line"""
+ self.stc.GotoIndentPos()
+
+ def GotoLineEnd(self):
+ """Goto the end of the current line"""
+ self.stc.LineEnd()
+
+ def OpenLine(self):
+ """Open a new line below the current line"""
+ # TODO: watch out if AutoIndent gets "fixed" so that it doesn't
+ # open a new line by itself!
+ self.GotoLineEnd()
+ self.stc.AutoIndent()
+
+ def OpenLineUp(self):
+ """Open a new line above the current line"""
+ self.MoveUp()
+ self.OpenLine()
+
+ def BeginUndoAction(self):
+ self.stc.BeginUndoAction()
+
+ def EndUndoAction(self):
+ self.stc.EndUndoAction()
+
+ def MoveUp(self, repeat=1):
+ """Move caret up
+ @keyword repeat: int
+
+ """
+ for i in range(repeat):
+ self.stc.LineUp()
+
+ def MoveDown(self, repeat=1):
+ """Move caret down
+ @keyword repeat: int
+
+ """
+ for i in range(repeat):
+ self.stc.LineDown()
+
+ def MoveRight(self, repeat=1):
+ """Move position to the right
+ @keyword repeat: int
+
+ """
+ self.stc.MoveCaretPos(repeat)
+
+ def MoveLeft(self, repeat=1):
+ """Move the caret postion to the left
+ @keyword repeat: int
+
+ """
+ self.stc.MoveCaretPos(-repeat)
+
+ def MoveForward(self, repeat=1):
+ """Move the caret position to the right"""
+ self.MoveRight(repeat)
+
+ def MoveBack(self, repeat=1):
+ """Move the caret position to the left"""
+ self.MoveLeft(repeat)
+
+ def NextWord(self, repeat=1):
+ """Move to beginning of next word"""
+ for i in range(repeat):
+ self.stc.WordRight()
+
+ def NextWordBig(self, repeat=1):
+ """Move to beginning of next Word (words are separated by space)"""
+ # TODO:CJP Test on empty document, possible error condition
+ for i in range(repeat):
+ self.stc.WordRight()
+ while self.GetChar(-1) and not self.GetChar(-1).isspace():
+ self.stc.WordRight()
+
+ def WordEnd(self, repeat=1):
+ """Move to end of this word"""
+ for i in range(repeat):
+ self.stc.WordRightEnd()
+
+ def WordEndBig(self, repeat=1):
+ """Move to end of this Word (words are separated by space)"""
+ # TODO:CJP Test on empty document, possible error condition
+ for i in range(repeat):
+ self.stc.WordRightEnd()
+ while self.GetChar() and not self.GetChar().isspace():
+ self.stc.WordRightEnd()
+
+ def BackWord(self, repeat=1):
+ """Move back to start of word"""
+ for i in range(repeat):
+ self.stc.WordLeft()
+
+ def BackWordBig(self, repeat=1):
+ """Move back to start of Word (words are separated by space)"""
+ # TODO:CJP Test on empty document, possible error condition
+ for i in range(repeat):
+ self.stc.WordLeft()
+ while self.GetChar(-1) and not self.GetChar(-1).isspace():
+ self.stc.WordLeft()
+
+ def BackWordPart(self, repeat=1):
+ """Move back to start of word part"""
+ for i in range(repeat):
+ self.stc.WordPartLeft()
+
+ def WordPartEnd(self, repeat=1):
+ """Move to the end of the word part"""
+ for i in range(repeat):
+ self.stc.WordPartRight()
+
+ def ParaUp(self, repeat=1):
+ """Move the caret one paragraph up"""
+ for i in range(repeat):
+ self.stc.ParaUp()
+
+ def ParaDown(self, repeat=1):
+ """Move the caret one paragraph down"""
+ for i in range(repeat):
+ self.stc.ParaDown()
+
+ def RegexSearch(self, text, back=False):
+ """Search for a regex expression
+ @param text: search string
+ @keyword back: seach in reverse
+
+ """
+ # TODO:CJP using the StyledTextCtrl's regex searching is not as
+ # powerful as using Editras SearchEngine.
+ self.stc.SearchText(text, regex=True, back=back)
+ if back and self.HasSelection():
+ # Let the caret pos be at the end of the selection
+ start, end = self._GetSelectionRange()
+ self.stc.SetSelection(start, end)
+
+ def GotoScreenTop(self):
+ """Goto first visible line"""
+ self.stc.GotoIndentPos(self.stc.GetFirstVisibleLine())
+
+ def GotoScreenMiddle(self):
+ """Goto to the middle line on the screen"""
+ self.stc.GotoIndentPos(self.stc.GetMiddleVisibleLine())
+
+ def GotoScreenLast(self):
+ """Goto last visible line"""
+ self.stc.GotoIndentPos(self.stc.GetLastVisibleLine())
+
+ def _EnsureCaretVisible(self):
+ """Smartly scroll view to make caret visible if it's out of view"""
+ first = self.stc.GetFirstVisibleLine()
+ lines = self.stc.LinesOnScreen()
+ current = self.stc.GetCurrentLine()
+ if current in range(first, first + lines):
+ # supposedly visible! XXX: doesn't account for folding
+ # TODO:CJP to ensure caret is visible call EnsureCaretVisible
+ return None
+
+ if current < first:
+ amt = 0.7
+ else:
+ amt = 0.3
+ self._Scroll(amt)
+
+ def _Scroll(self, amt):
+ """Scroll to the current line. For example _Scroll(0.5) scrolls the
+ current line to the middle of the screen
+ @param amt: number between 0 and 1 signifying percentage
+
+ """
+ lines = self.stc.LinesOnScreen() - 1
+ current = self.stc.GetCurrentLine()
+ diff = int(lines * amt)
+ self.stc.ScrollToLine(current - diff)
+
+ def ScrollTop(self):
+ """Scroll such that the current line is the first visible line"""
+ self._Scroll(0)
+
+ def ScrollMiddle(self):
+ """Scroll such that the current line is in the middle of the screen"""
+ self._Scroll(0.5)
+
+ def ScrollBottom(self):
+ """Scroll such that the current line is the last visible line"""
+ self._Scroll(1)
+
+ def _SelectIdentifierUnderCaret(self):
+ """If nothing is selected, select the identifier under caret, otherwise
+ keeps selection as is.
+ @return: selected text
+
+ """
+ ident = self.GetSelectedText()
+ if ident:
+ return ident
+
+ self.WordEnd()
+ self.StartSelection()
+ self.BackWord()
+ self.EndSelection()
+ ident = self.GetSelectedText()
+ return ident
+
+ def _NextIdent(self, repeat=1, back=False):
+ """Jump to the next (or previous) occurance of identifier
+ under caret or selected text.
+
+ @note: Holds common code between NextIdent and PrevIdent
+ @see: NextIdent
+ @see: PrevIdent
+
+ """
+ ident = self._SelectIdentifierUnderCaret()
+ self.PushCaret()
+ self.PushScroll()
+ if not ident:
+ return
+
+ for i in range(repeat):
+ if back:
+ self._GotoSelectionStart()
+ else:
+ self._GotoSelectionEnd()
+
+ result = self.stc.SearchText(ident, back=back)
+ if result == -1:
+ break
+
+ self.PopCaret(result == -1)
+ self.PopScroll()
+ self._EnsureCaretVisible()
+
+ def NextIdent(self, repeat=1):
+ """Find next occurance of identifier under cursor"""
+ self._NextIdent(repeat)
+
+ def PrevIdent(self, repeat=1):
+ """Find the previous occurrence of identifier under cursor"""
+ self._NextIdent(repeat, back=True)
+
+ def InsertText(self, text):
+ """Insert some text at the current caret position and advance caret
+ The inserted text is remembered so it can be repeated.
+ @param text: string
+
+ """
+ self.keyprocessor.InsertText(self._GetPos(), text)
+ self.MoveForward(len(text))
+
+ def SetInsertRepeat(self, repeat):
+ """Set how many times to repeat the last inserted text when
+ InsertRepetition is called.
+
+ """
+ self.InsertRepeat = repeat
+
+ def SetLastChangeCommand(self, cmd):
+ """Rememer this command as the last change cmmand so that it gets
+ repeated when RepeatChangeCommand is called.
+
+ """
+ self.LastChangeCommand = cmd
+
+ def SetLastInsertedText(self, text):
+ """Set this as the last inserted text so it gets repeated when
+ InsertRepetition is called.
+
+ """
+ self.LastInsertedText = text
+
+ def RepeatChangeCommand(self, repeat=1):
+ """Repeat the last change command as set by SetLastChangeCommand"""
+ if not self.LastChangeCommand:
+ return
+
+ self.BeginUndoAction()
+ for i in range(repeat):
+ self.LastChangeCommand()
+ self.InsertText(self.LastInsertedText)
+ self.EndUndoAction()
+
+ def GetChar(self, dist=1):
+ """Get the character (or text) under caret
+ @param dist: length of text to get, negative values can be used to get
+ the text before the caret
+
+ """
+ pos = self._GetPos()
+ start, end = minmax(pos, pos + dist)
+ start = max(0, start)
+ end = min(end, self.stc.GetLength())
+ return self.stc.GetTextRange(start, end)
+
+ def GetSelectedText(self):
+ """Get the selected text
+ @return: Unicode
+
+ """
+ return self.stc.GetSelectedText()
+
+ def HasSelection(self):
+ """Detects if there's anything selected
+ @return: bool
+
+ """
+ return len(self.GetSelectedText()) > 0
+
+ def SetRegister(self, reg='"'):
+ """Set the current working clipboard (aka register) to given name"""
+ ebmlib.Clipboard.Switch(reg)
+
+ def YankSelection(self):
+ """Copy the current selection to the clipboard"""
+ ebmlib.Clipboard.Set(self.GetSelectedText())
+
+ def DeleteSelection(self):
+ """Yank selection and delete it"""
+ start, end = self._GetSelectionRange()
+ self.stc.BeginUndoAction()
+ self.YankSelection()
+ self.stc.Clear()
+ self._SetPos(start)
+ self.stc.EndUndoAction()
+
+ def ChangeSelection(self):
+ """Yank selection, delete it, and enter insert mode"""
+ # HACK: need to adjust selection behavior for change command
+ # to better match vi behavior by not including trailing
+ # whitespace in the selection from the motion.
+ stext = self.STC.GetSelectedText()
+ clen = len(stext)
+ slen = len(stext.rstrip())
+ if slen < clen and slen > 0:
+ start, end = self._GetSelectionRange()
+ new_end = end - (clen - slen)
+ self.STC.SetSelectionStart(start)
+ self.STC.SetSelectionEnd(new_end)
+ self.DeleteSelection()
+ self.InsertMode()
+
+ def Put(self, before=False, repeat=1):
+ """Paste text
+
+ If there's selection, the pasted text replaces it
+
+ If text to be pasted ends with EOL it's assumed to be a line, and is
+ pasted on a new line below the current line, or if the before keyword
+ is set to True, then it's pasted on a new line above the current line
+
+ """
+ text = ebmlib.Clipboard.Get()
+ if not text:
+ return
+
+ bIsLine = self._IsLine(text)
+ if bIsLine:
+ self.GotoLineStart()
+ if not before:
+ self.MoveDown()
+
+ self.BeginUndoAction()
+ if self.HasSelection():
+ # paste over selection, if any
+ self.stc.Clear()
+ elif not bIsLine:
+ self.stc.CharRight()
+
+ for i in range(repeat):
+ self.InsertText(text)
+ self.EndUndoAction()
+
+ def InvertCase(self, repeat):
+ """Invert the case of the following characters"""
+ if not self.HasSelection():
+ for i in range(repeat):
+ self.StartSelection()
+ self.MoveForward()
+ self.EndSelection()
+ self.stc.InvertCase()
+ self.Deselect()
+
+ def JoinLines(self, repeat):
+ """Join lines into a single line.
+ @param repeat: number of lines below the current line to join with
+
+ """
+ self.SelectLines(repeat)
+ self.stc.LinesJoinSelected()
+
+ def _DeleteChars(self, repeat, back=False):
+ """Delete characters under caret.
+ @keyword back: If set to true, delete character before the caret
+
+ """
+ if back:
+ move = self.MoveBack
+ else:
+ move = self.MoveForward
+
+ self.BeginUndoAction()
+ self.StartSelection()
+ move(repeat)
+ self.EndSelection()
+ self.DeleteSelection()
+ self.EndUndoAction()
+
+ def DeleteForward(self, repeat):
+ """Delete characters after the caret"""
+ self._DeleteChars(repeat)
+
+ def DeleteBackward(self, repeat):
+ """Delete characters before the caret"""
+ self._DeleteChars(repeat, back=True)
+
+ def ReplaceChar(self, char, repeat):
+ """Replace the next character under cursor with the given char"""
+ self.BeginUndoAction()
+ self.DeleteForward(repeat)
+ for i in range(repeat):
+ self.InsertText(char)
+ self.EndUndoAction()
+
+ def FindNextChar(self, char, repeat):
+ """Find next occurance of char on the current line"""
+ self.stc.FindChar(char, repeat)
+
+ def FindPrevChar(self, char, repeat):
+ """Find the previos occurance of char on the current line"""
+ self.stc.FindChar(char, repeat, reverse=True)
+
+ def FindTillNextChar(self, char, repeat):
+ """Similar to FindNextChar, but stop one character short"""
+ self.stc.FindChar(char, repeat, extra_offset=-1)
+
+ def FindTillPrevChar(self, char, repeat):
+ """Similar to FindPrevChar, but stop one character short"""
+ self.stc.FindChar(char, repeat, reverse=True, extra_offset=1)
+
+ def SetFindCharCmd(self, *args):
+ """Remember last find-char command (raw unparsed command, e.g. 'f')
+ for repeating later on.
+
+ """
+ self.LastFindChar = args
+
+ def GetFindCharCmd(self):
+ """@see SetFindCharCmd"""
+ return self.LastFindChar
+
+ def Mark(self, mark):
+ """Create a bookmark on current line and give it a char label
+ @param mark: the character label of the bookmark.
+
+ """
+ #TODO: handle global bookmarks
+ bm_handle, column = self.stc.AddBookmark(), self._GetCol()
+ if mark in string.ascii_lowercase:
+ # Local bookmarks
+ self._Bookmarks[mark] = (bm_handle, column)
+ elif mark in string.ascii_uppercase:
+ # Global bookmarks
+ pass
+
+ def GotoMark(self, mark):
+ """Goto the position of the bookmark associated with the given
+ character label.
+ @param mark: the character label of the book mark
+ @todo: hook into Bookmark Manager ed_bookmark?
+
+ """
+ if not mark in self._Bookmarks:
+ return
+
+ bm_handle, col = self._Bookmarks[mark]
+ #TODO: handle global bookmarks
+ line = self.stc.MarkerLineFromHandle(bm_handle)
+ if line != -1:
+ pos = self.stc.FindColumn(line, col)
+ self.stc.GotoPos(pos)
+ else: #line == -1 means the bookmark was deleted by the user
+ del self._Bookmarks[mark]
+
+ def _GetSelectionRange(self):
+ """Get the range of selection such that the start is the visual start
+ of the selection, not the logical start.
+
+ """
+ start, end = minmax(self.stc.GetSelectionStart(),
+ self.stc.GetSelectionEnd())
+ return start, end
+
+ def _GotoSelectionStart(self):
+ """Goto the visual start of the current selection and deselect"""
+ start, end = self._GetSelectionRange()
+ self._SetPos(start)
+ self.StartSelection()
+ self.EndSelection()
+
+ def _GotoSelectionEnd(self):
+ """Goto the visual end of the current selection and deselect"""
+ start, end = self._GetSelectionRange()
+ self._SetPos(end)
+ self.StartSelection()
+ self.EndSelection()
+
+ def _GetSelectedLines(self):
+ """Get the first and last line (exclusive) of selection"""
+ start, end = self._GetSelectionRange()
+ start_line, end_line = (self.stc.LineFromPosition(start),
+ self.stc.LineFromPosition(end - 1) + 1)
+ return start_line, end_line
+
+ def SelectFullLines(self):
+ """Extends selection so it covers entire lines"""
+ start, end = self._GetSelectedLines()
+ self.GotoLine(start)
+ self.StartSelection()
+ self.GotoLine(end)
+ self.EndSelection()
+
+ def IndentSelection(self, forward=True):
+ """Indent the lines of the current selection forward (or backward)"""
+ if not self.GetSelectedText():
+ return
+
+ self.PushScroll()
+ self.PushCaret()
+ self.BeginUndoAction()
+ if forward:
+ indent = self.stc.Tab
+ else:
+ indent = self.stc.BackTab
+
+ for line in range(*self._GetSelectedLines()):
+ self.stc.GotoLine(line)
+ indent()
+ self.EndUndoAction()
+ self.PopCaret()
+ self.PopScroll()
+
+ def DedentSelection(self):
+ """Indent lines of current selection backward"""
+ self.IndentSelection(forward=False)
+
+ def ShowCommandBar(self):
+ """Open the command bar for the user to enter commands"""
+ self.stc.ShowCommandBar()
+
+ def ShowFindBar(self):
+ """Open the find bar"""
+ self.stc.ShowFindBar()
+
+# ---------------------------------------------------------------------------- #
+
+def minmax(a,b):
+ return min(a,b), max(a,b)
+# Internal functions, other modules should not bother with any of this
+
+REPEAT_RE = re.compile("([1-9][0-9]*)*(.*)")
+
+def SplitRepeat(cmd):
+ """Split the command strings into a pair (repeat, rest)
+
+ >>>SplitRepeat( '3ab' )
+ (3, 'ab')
+ >>>SplitRepeat( '13ab' )
+ (13, 'ab')
+ >>>SplitRepeat( 'abc' )
+ (None, 'abc')
+ >>>SplitRepeat( 'ab2' )
+ (None, 'ab2')
+ >>>SplitRepeat( '0' )
+ (None, '0')
+ >>>SplitRepeat( '0ab' )
+ (None, '0ab')
+ >>>SplitRepeat('8')
+ (8, '')
+
+ """
+ repeat, rest = re.match( REPEAT_RE, cmd ).groups()
+ if repeat:
+ repeat = int(repeat)
+ return (repeat, rest)
+
+def GetHandler(cmd, h_list=None):
+ """Finds the function that handles command cmd
+ @param cmd: the command string
+ @keyword h_list: alternative list of handler functions
+
+ """
+ if h_list is None:
+ h_list = HANDLERS
+
+ repeat, cmd = SplitRepeat(cmd)
+ if not cmd:
+ return None
+
+ for handler in h_list:
+ if cmd[0] in handler.start_chars:
+ return handler
+
+def DoHandle(handler, cmd, editor):
+ """Call handler for command
+ It's necessary to use this function instead of calling the handler
+ directly.
+
+ """
+ repeat, cmd = SplitRepeat(cmd)
+ if handler.generic_repeat: # generic_repeat means that if no repeat
+ repeat = repeat or 1 # parameter is supplied, use 1
+ return handler(editor, repeat, cmd)
+
+def GetMotion(editor, cmd):
+ """Move cursor of editor to a new location according to motion
+ Returns a method that handles this motion, or None
+
+ """
+ if not cmd:
+ return None
+
+ handler = GetHandler(cmd, MOTION_HANDLERS)
+ if handler is None:
+ return None
+
+ def motion_function():
+ return DoHandle(handler, cmd, editor)
+ return motion_function
+
+# ---------------------------------------------------------------------------- #
+# Vim commands
+
+def vim_parser(start_chars, generic_repeat=True, is_motion=False):
+ """Decorator for function that handle vim commands
+
+ Command Handling functions must follow the signature:
+
+ function( editor, repeat, cmd )
+
+ These functions should never be called directly, but instead
+ be called through the GetHandler and DoHandle functions.
+
+ The handler functions should always decorate themselves with this
+ decorator.
+
+ The purpose of this decorator is to indicate:
+ * What is the first char of commands that the handler can handle
+ - So that GetHandler can find the correct handler for a vim command
+ * Whether it's a motion
+ - Some commands operate on motions
+ * How to handle the repeat parameter
+ - For most command, no repeat is the same as 1 repeat, but for
+ some commands, this is not the case
+
+ """
+ def decorator(handler):
+ handler.is_parser = True
+ handler.start_chars = start_chars
+ handler.generic_repeat = generic_repeat
+ handler.is_motion = is_motion
+ return handler
+ return decorator
+
+# TODO replace with a special objects
+# TODO:CJP ok if these become classes but, if they remain as flags then they
+# need to be uppercase.
+NeedMore = True
+InvalidOp = False
+
+@vim_parser( u'iIaAoO' )
+def InsertMode(editor, repeat, cmd):
+ """Handler for basic commands that put vim in INSERT mode"""
+ cmd_map = {
+ u'i': (lambda:None),
+ u'I': editor.GotoIndentStart,
+ u'A': editor.GotoLineEnd,
+ u'a': editor.MoveForward,
+ u'o': editor.OpenLine,
+ u'O': editor.OpenLineUp
+ }
+ func = cmd_map[cmd]
+ func()
+ editor.SetLastChangeCommand(func) # Let the editor remember to repeat
+ editor.SetInsertRepeat(repeat) # insertion if and when needed
+ editor.InsertMode()
+
+#TODO:CJP Documentation for below methods please
+@vim_parser( u'v' )
+def VisualMode(editor, repeat, cmd):
+ """Enter visual mode
+ @see: vim_parser
+
+ """
+ editor.VisualMode()
+
+@vim_parser('.')
+def Dot(editor, repeat, cmd):
+ """Repeat last insert command
+ @see: vim_parser
+
+ """
+ editor.RepeatChangeCommand(repeat)
+ if editor.IsInsertMode():
+ editor.NormalMode() # in case it was a 'c' command
+
+@vim_parser(u'hjkl\r \x08\u013c\u013a', is_motion=True)
+def Arrows(editor, repeat, cmd):
+ """Basic arrow movement in vim.
+ @see: vim_parser
+
+ """
+ cmd_map = {
+ u'h': editor.MoveLeft,
+ u'j': editor.MoveDown,
+ u'k': editor.MoveUp,
+ u'l': editor.MoveRight,
+ u'\r': editor.MoveDown,
+ u' ' : editor.MoveRight,
+ u'\x08' : editor.MoveLeft
+ }
+ if cmd in cmd_map:
+ cmd_map[cmd](repeat)
+ else:
+ # Handle motion for actual arrow keys
+ if cmd == u'\u013c' and not editor.IsAtLineEnd():
+ # Right arrow
+ editor.MoveRight()
+ elif cmd == u'\u013a' and not editor.IsAtLineStart():
+ # Left Arrow
+ editor.MoveLeft()
+
+@vim_parser('wbeWBE[]', is_motion=True)
+def Words(editor,repeat, cmd):
+ """Word motions.
+ @note: [] is based on what scintilla calls "word parts", these motions
+ are not in vim
+ @see: vim_parser
+
+ """
+ cmd_map = {
+ u'w': editor.NextWord,
+ u'e': editor.WordEnd,
+ u'b': editor.BackWord,
+ u'W': editor.NextWordBig,
+ u'E': editor.WordEndBig,
+ u'B': editor.BackWordBig,
+ u'[': editor.BackWordPart,
+ u']': editor.WordPartEnd,
+ }
+ cmd_map.get(cmd, lambda x: None)(repeat)
+
+@vim_parser(u'$^0', is_motion=True)
+def Line(editor, repeat, cmd):
+ """Motions to beginning/end of a line.
+ @see: vim_parser
+
+ """
+ cmd_map = { u'0': editor.GotoLineStart,
+ u'^': editor.GotoIndentStart,
+ u'$': editor.GotoLineEnd,
+ }
+ cmd_map.get(cmd, lambda:None)()
+
+@vim_parser(u'{}', is_motion=True)
+def Para(editor, repeat, cmd):
+ """Paragraph motions.
+ @see: vim_parser
+
+ """
+ cmd_map = { u'{': editor.ParaUp,
+ u'}': editor.ParaDown,
+ }
+ cmd_map.get(cmd, lambda x: None)(repeat)
+
+@vim_parser(u'uU')
+def Undo(editor, repeat, cmd):
+ """Undo/Redo commands.
+ @note: unlike vim, U is used for redo.
+ @see: vim_parser
+
+ """
+ if cmd == u'u':
+ editor.Undo(repeat)
+ elif cmd == u'U':
+ editor.Redo(repeat)
+
+# TODO:CJP Scintilla lexing bug, check if fixed in 2.9
+@vim_parser(u'*#', is_motion=True)
+def FindIdent(editor, repeat, cmd):
+ """Find the next/previous occurance of identifier under caret
+ @note: There's a sublte difference from vim: if some text is already
+ selected, it's used as the search term instead of the identifier
+ under the caret
+ @see: vim_parser
+
+ """
+ cmd_map = { u'#': editor.PrevIdent,
+ u'*': editor.NextIdent,
+ }
+ cmd_map.get(cmd, lambda x: None)(repeat)
+
+@vim_parser(u'~')
+def Tilde(editor, repeat, cmd):
+ """Invert case of character(s) under caret. Also operates on selection.
+ @see: vim_parser
+
+ """
+ editor.InvertCase(repeat)
+ editor.NormalMode() # In case this command was applied in visual mode
+
+@vim_parser(u'J')
+def Join(editor, repeat, cmd):
+ """Join lines command.
+ @see: vim_parser
+
+ """
+ editor.PushCaret()
+ editor.JoinLines(repeat)
+ editor.PopCaret()
+
+@vim_parser(u'xXsSCDY')
+def Delete(editor, repeat, cmd):
+ """Simple delete/change commands that are implemented in terms of more
+ advanced c/d commands.
+ @see: vim_parser
+
+ """
+ cmd_map = {
+ u'x': u'dl', u'X': u'dh',
+ u's': u'cl', u'S': u'cc',
+ u'C': u'c$', u'D': u'd$', u'Y': u'y$',
+ }
+ if cmd in cmd_map:
+ Change(editor, repeat, cmd_map[cmd])
+
+@vim_parser(u'cdy<>')
+def Change(editor, repeat, cmd):
+ """Implementations for c/d/y commands. Also for <> (indentation) commands.
+ @todo: This method is quite larger than other methods in this module,
+ needs to be simplified.
+ @see: vim_parser
+
+ """
+ editor.PushColumn()
+ editor.PushCaret()
+ def ret(return_value, restore=True):
+ """Needed because we have to pop what we pushed before we return"""
+ editor.PopCaret(restore)
+ editor.PopColumn(restore)
+ return return_value
+ pre_selected = False
+ line_motion = False
+ if editor.HasSelection():
+ pre_selected = True
+ if len(cmd) > 1:
+ motion = cmd[1:]
+ else:
+ motion = ''
+ cmd = cmd[0]
+ else:
+ if len(cmd) == 1:
+ return ret(NeedMore, False)
+
+ cmd, motion = cmd[0], cmd[1:]
+ if motion.isdigit():
+ return ret(NeedMore)
+
+ motion_repeat, motion_cmd = SplitRepeat(motion)
+ if motion_repeat:
+ repeat = repeat * motion_repeat
+
+ if motion_cmd == cmd:
+ # Operate on whole line
+ line_motion = True
+ editor.PushColumn()
+ editor.SelectLines(repeat)
+ else:
+ motion_function = GetMotion(editor, motion_cmd)
+ if motion_function is None:
+ # Invalid motion; cancel operation
+ return ret(InvalidOp)
+
+ editor.PushCaret()
+ editor.PushColumn()
+ for i in range(repeat):
+ if motion_function() == NeedMore:
+ # This motion is incomplete .. (catch on first iteration)
+ editor.Deselect()
+ return ret(NeedMore)
+ editor.StartSelection()
+ editor.PopCaret()
+ editor.EndSelection()
+
+ if motion_cmd[0] in LINE_MOTION_PREFIXES:
+ line_motion = True
+ editor.SelectFullLines()
+
+ cmd_map = {
+ u'y': editor.YankSelection,
+ u'd': editor.DeleteSelection,
+ u'c': editor.ChangeSelection,
+ u'<': editor.DedentSelection,
+ u'>': editor.IndentSelection,
+ }
+
+ cmd_map[cmd]()
+
+ restore_x = cmd in (u'y', u'<', u'>') or cmd == u'd' and line_motion
+ editor.PopColumn(restore_x)
+
+ # XXX: Some special case handling
+ # Not the most elegant way though ..
+ if cmd == u'c':
+ pass
+ else:
+ # Repeating delete/yank/indent commands doesn't insert any text
+ editor.SetLastInsertedText(u'')
+ # Applying them in visual mode ends visual mode
+ editor.NormalMode()
+
+ if not pre_selected:
+ # Remember this command as last change
+ # However, if we're operating on a selection, then remembering
+ # doesn't make much sense
+ editor.SetLastChangeCommand(lambda : Change(editor, repeat, cmd+motion))
+
+@vim_parser(u'pP')
+def Put(editor, repeat, cmd):
+ """Paste commands.
+ @see: vim_parser
+
+ """
+ before = cmd == u'P'
+ editor.Put(before, repeat)
+ editor.NormalMode() # for pasting in visual mode
+
+@vim_parser(u'"')
+def Reg(editor, repeat, cmd):
+ """Switch register (clipboard) command
+ @note: This command is stand-alone, not prefix to other commands.
+ @see: vim_parser
+
+ """
+ if len(cmd) == 1:
+ return NeedMore
+
+ cmd, char = cmd
+ try:
+ editor.SetRegister(char)
+ except ebmlib.ClipboardException:
+ # Attempted to switch to invalid register
+ wx.Bell()
+
+@vim_parser(u'r')
+def ReplaceChar(editor, repeat, cmd):
+ """Replace character under caret with another one.
+ @note: Does not enter into Insert mode.
+ @see: vim_parser
+
+ """
+ if len(cmd) == 1:
+ return NeedMore
+
+ r, char = cmd
+ f = lambda: editor.ReplaceChar(char, repeat)
+ f()
+ editor.SetLastChangeCommand(f)
+ editor.SetLastInsertedText(u'')
+
+@vim_parser(u'R')
+def ReplaceMode(editor, repeat, cmd):
+ """Enter into Replace Mode.
+ @see: vim_parser
+
+ """
+ # TODO handle repetition
+ editor.ReplaceMode()
+
+@vim_parser(u'fFtT', is_motion=True)
+def FindChar(editor, repeat, cmd):
+ """Find character on current line and move the caret to it (if found).
+ @see: vim_parser
+
+ """
+ if len(cmd) == 1:
+ return NeedMore
+
+ cmd, char = cmd
+ cmd_map = {
+ u'f' : editor.FindNextChar,
+ u'F' : editor.FindPrevChar,
+ u't' : editor.FindTillNextChar,
+ u'T' : editor.FindTillPrevChar,
+ }
+ if cmd in cmd_map:
+ cmd_map[cmd](char, repeat)
+ editor.SetFindCharCmd(cmd, char)
+
+@vim_parser(u',;', is_motion=True)
+def RepeatFindChar(editor, repeat, cmd):
+ """Repeat the last FindChar motion.
+ @see: vim_parser
+
+ """
+ prev_cmd = editor.GetFindCharCmd()
+ if not prev_cmd:
+ return
+
+ pcmd, char = prev_cmd
+ if cmd == u',':
+ pcmd = pcmd.swapcase()
+
+ FindChar(editor, repeat, pcmd+char)
+ editor.SetFindCharCmd(*prev_cmd)
+
+@vim_parser(u'm')
+def Mark(editor, repeat, cmd):
+ """Create a bookmark and associate it with a character label.
+ @see: vim_parser
+
+ """
+ if len(cmd) == 1:
+ return NeedMore
+
+ cmd, mark = cmd
+ editor.Mark(mark)
+
+@vim_parser(u"`'", is_motion=True)
+def Jump(editor, repeat, cmd):
+ """Jump to a bookmark specified by a character label.
+ @see: vim_parser
+
+ """
+ if len(cmd) == 1:
+ return NeedMore
+
+ cmd, mark = cmd
+ editor.GotoMark(mark)
+ if cmd == u"'":
+ editor.GotoIndentStart()
+
+@vim_parser(u'HLMGgz', is_motion=True, generic_repeat=False)
+def NavExtra(editor, repeat, cmd):
+ """Commands for navigating visible lines or scrolling.
+ @see: vim_parser
+
+ """
+ if cmd == u'H':
+ editor.GotoScreenTop()
+ if repeat:
+ editor.MoveDown(repeat)
+ elif cmd == u'M':
+ editor.GotoScreenMiddle()
+ elif cmd == u'L':
+ editor.GotoScreenLast()
+ if repeat:
+ editor.MoveUp(repeat)
+ elif cmd == u'G':
+ if repeat:
+ editor.GotoLine(repeat)
+ else:
+ editor.GotoLastLine()
+ else: # g or z command
+ if len(cmd) < 2:
+ return NeedMore
+
+ if cmd == u'gg':
+ editor.GotoLine(0)
+ elif cmd == u'zz':
+ editor.ScrollMiddle()
+ elif cmd == u'zt':
+ editor.ScrollTop()
+ elif cmd == u'zb':
+ editor.ScrollBottom()
+
+@vim_parser(u'/?', is_motion=True)
+def RegexSearch(editor, repeat, cmd):
+ """Incremental search commands.
+ @note: Uses the find bar in editra.
+ @see: vim_parser
+
+ """
+ # XXX: findbar is not regex!
+ # TODO:CJP it is if you set the regex search flag or the user's previous
+ # search was done using regular expressions.
+ editor.ShowFindBar()
+
+@vim_parser(u'|', is_motion=True)
+def Column(editor, repeat, cmd):
+ """Goto specified column, with 1 being the default.
+ @see: vim_parser
+
+ """
+ editor.GotoColumn(repeat)
+
+@vim_parser(u':')
+def Ex(editor, repeat, cmd):
+ """Command for opening the command bar.
+ @see: vim_parser
+
+ """
+ editor.ShowCommandBar()
+
+# Cannonical list of handlers
+HANDLERS = (
+ InsertMode, ReplaceMode, VisualMode, Dot, Undo,
+ Arrows, Words, Line, Para, Column, FindChar, RepeatFindChar,
+ FindIdent, Change, Delete, Tilde, ReplaceChar, Put, Join,
+ Mark, Jump, Ex, Reg, NavExtra, RegexSearch,
+ )
+MOTION_HANDLERS = [h for h in HANDLERS if h.is_motion]
+# HACK: The following is a sign of improper design! but doing it properly
+# would probably require yet another huge rewrite of this module.
+# So watch out if things get out of control with many such hacks.
+# These are motions that, if operated on, the operation should happen
+# on whole lines.
+LINE_MOTION_PREFIXES = [u'\'', u'G', u'{', u'}', u'H', u'L', u'M']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_xml.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_xml.py
new file mode 100644
index 0000000..266b246
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_xml.py
@@ -0,0 +1,108 @@
+###############################################################################
+# Name: ed_thread.py #
+# Purpose: Provides a base class for managing XML files and data. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2011 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+XML base class
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: ed_xml.py 72624 2012-10-06 19:38:14Z CJP $"
+__revision__ = "$Revision: 72624 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import types
+from xml.dom import minidom
+import extern.dexml as dexml
+from extern.dexml.fields import *
+
+import util
+
+#-----------------------------------------------------------------------------#
+
+class EdXml(dexml.Model):
+ """XML base class"""
+ def __init__(self, **kwds):
+ super(EdXml, self).__init__(**kwds)
+
+ Xml = property(lambda self: self.GetXml(),
+ lambda self, xstr: self.parse(xstr))
+ PrettyXml = property(lambda self: self.GetPrettyXml(),
+ lambda self, xstr: self.parse(xstr))
+
+ def GetPrettyXml(self):
+ """Get a nicely formatted version of the rendered xml string
+ @return: string
+
+ """
+ txt = ""
+ try:
+ txt = self.render()
+ txt = minidom.parseString(txt).toprettyxml()
+ txt = txt.replace('\t', ' ') # DeTabify
+ except UnicodeEncodeError, err:
+ util.Log("[EdXml][err] GetPrettyXml %s" % err)
+ return txt
+
+ def GetXml(self):
+ """Get the XML string for this object
+ @return: string
+
+ """
+ xstr = ""
+ try:
+ xstr = self.render()
+ except UnicodeEncodeError, err:
+ util.Log("[EdXml][err] GetXml %s" % err)
+ return xstr
+
+ def Write(self, path):
+ """Write the xml to a file
+ @param path: string
+ @return: success (bool)
+
+ """
+ suceeded = True
+ try:
+ xmlstr = self.PrettyXml
+ if isinstance(xmlstr, types.UnicodeType):
+ xmlstr = xmlstr.encode('utf-8')
+ handle = open(path, 'wb')
+ handle.write(xmlstr)
+ handle.close()
+ except (IOError, OSError, UnicodeEncodeError):
+ suceeded = False
+ return suceeded
+
+ @classmethod
+ def Load(cls, path):
+ """Load this object from a file
+ @param path: path to xml file
+ @return: instance
+
+ """
+ instance = None
+ try:
+ handle = open(path, 'rb')
+ xmlstr = handle.read()
+ handle.close()
+ instance = cls.parse(xmlstr)
+ except (IOError, OSError):
+ instance = None
+ return instance
+
+ @classmethod
+ def LoadString(cls, xmlstr):
+ """Load an object from an XML string
+ @param cls: Class object
+ @param xmlstr: string
+
+ """
+ instance = cls.parse(xmlstr)
+ return instance
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/edimage.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/edimage.py
new file mode 100644
index 0000000..e86fd74
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/edimage.py
@@ -0,0 +1,923 @@
+###############################################################################
+# Name: ed_image.py #
+# Purpose: Encoded art resources for Editra #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""This file is an image data file that provides some of the base icons
+@note: image data generated with img2py
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: edimage.py 54209 2008-06-14 04:57:51Z CJP $"
+__revision__ = "$Revision: 54209 $"
+
+#-----------------------------------------------------------------------------#
+from extern.embeddedimage import PyEmbeddedImage
+
+catalog = {}
+index = []
+
+splashwarn = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAASwAAADICAYAAABS39xVAAAABHNCSVQICAgIfAhkiAAAIABJ"
+ "REFUeJzsvWmMbdl1HvatPZzpTjW/sedm020O4iDJkqAxkOAEdhQDAZIfTmwEzoAkCPwjiIIg"
+ "P5IYcaAYsGRBkKzYlixLESHHlKGBhCKZEtUUx261mqTIZotkT+zhdfcbq+pO55w95Mdea99T"
+ "jyKLMoWnfkptoPBe3Tr33nP22nsN3/rW2gTgN3E2zsbZOBt3wVB/3jdwNs7G2Tgb3+g4U1hn"
+ "42ycjbtmnCmss3E2zsZdM84U1tk4G2fjrhlnCutsnI2zcdeMM4V1Ns7G2bhrxpnCOhtn42zc"
+ "NcOcdsHrL7/8HX3bonMOighGawBAjBE+BJRlCe8cYoww1sL1PWxZgpRCDAGkFIL36NsWRARb"
+ "logxAjHCFgWs1vAhoOt7+L6HMgZaa4QQ8vvlehCBiNLvQP6/sRYEIISAEAJ836Pve/gYURgD"
+ "W5ZQSsF7D8QIpXW+P/msGAKU1gjewzsHbS36tkXVNOkaImi+l77rELyHrSoE56C0xnw+R2lt"
+ "vh8ACN6nefIeEUBZlnB9jxACyrqG6zoQEUgpaGPS9w+emwAs53NYa6G0Bojg+x7O+ywHeRal"
+ "VHp+59LrxkAbgxgjgvcAANd1af75uddtC02ECMBoDSKC0hrKGATv070R4Uz+Z/K/U/K/9OCD"
+ "n/ymFJZMZsE3icG/IkAiytcHniAKIV2jNUxRADGiXa+h+h6aBdu1LaiqQAC0MVnIXd+DiGCK"
+ "AiEEKKUAohMLTL5TKQXECB8jAk8cAFhrUcrkhgDP96OMScL1Pi0YpWDLEt1qBe8cTFFAaY0Y"
+ "Aoqqgut7FDzJXdvm62OMaYPxgil4cfS8OOQefQhpsfPCNEWByPcynLu8KWNMr8eIONignjcG"
+ "EUENXo8hnNzEg2fzfQ9TFOk9SiEagxgCurZNcx0CtNbpe/ke5DMRIyJviDP5n8n/Tsn/tHHq"
+ "VYoIkT9MtLXcpFIqaeGBtjcsQNHO8lAggrUWpFSazBBgtEbXdTBsVYuyRO892tUK3nsQWwvw"
+ "58V0E/nz8wQPhIXBBCpj4HiRiSXD4BmUMSiKAs77bIV7tnrGWnTrdVoAvOjy9/LGIaWwXq2g"
+ "WanHEKB4wYYYYZRKz0wE79zGavHnGJ6P9IhpU4oXAaSNZozJi1DmmJRKr/EGlcUushgu4Lw5"
+ "lEpWWr4LQMHfFQZKIM8T/34m/zP530n5nzZOVVgRAMliYG0+1KiOrWG+fjhRSsGLxSBKmjWE"
+ "7CKLJfMsSK01rNagukbbtvDObb6PJx4sDJkwDP4eeZKDXCv3xPcytCSKF1nXdVBaw3sP731y"
+ "h51Du1ohxggtC4oIZG2yXn2fBWTZ/bdFkeaCF5YPIbnQ7OoDyXsAu/qy4OV+vPeA92kz8IYY"
+ "hhfDIfMtMrn9dXCIkDcKbxbF9yJWPnssg41/YrEqdSb/M/nfUfmfNk73w4YuuFIZpb/dPfSD"
+ "hxm6q67vodlKeH64sq7z30Qgfd/DOYeiKGC0RuBJFVyB2EJIbCwCKzgG7kX7i+uvNQhAWdfo"
+ "uw6u79MitTZPTOSYfxhKAMkyy/d553Lc3vV9jsvFUhtr00Jnq2e0TjgA/+66DqYooNm6yPfI"
+ "M2W8RhaOPBuHE3KdWDeZ2zwvty2W4QIUdx4cUkhoFBnryYsvRgQOq7Ks+Ufk/Wchf+ccKSJU"
+ "o1HGmrTW8Uz+//+Q/zey/08b31DgGAc3Jq6xaHYRvriVsqjCQGvKZBFRxhDESgnAKZPqlEoL"
+ "hjYAIMTFF5dcLCvwVZgBSSzMVsvwZ8iDijUT17esa6yXS2gGGru2RVlVqNk9dewyO3kGsYr8"
+ "fX3bJiyAn4vKMoctngHW4Fx27aNz2SuQhS33FWOEEs8BAPF3npDFIAQCkDZLjAkj0Tp5Gre5"
+ "+IrxFSAtDM3zqHmxKH6PGn62bB6t/8zkz14NaaXgQkAgiiEEUkTxTP5/8eX/jez/08aptAbR"
+ "lPlf1vriPor7HWNMVpMtlmQOFFtEsZbipgLI4OUQTA0hwLF7r9g6GGNgJOMhC5+F2vd9miye"
+ "SGNMjpV936PjidHW5s87YcW8R1nX4gFAEcF1HY6Pj9O9DYQh2EGevEGGRj5PEWW8Yd11STgy"
+ "XwPBk1JQbEU9z5dnCy7POdwg8vm3/wwXPHi+xbJqDj8UUZYBYkx/s/bkffNzaH4mURJ/JvKP"
+ "kaCUssYoY4wiIm2KQldVpSndhAop8jiT/19E+f8p9v9p41QPSyZOXFIv2ng4aVpD80LiGcgT"
+ "13ddnhzvHPrVCtqY5AoOXMe+6/IikActrMViuYQuSxBRchljhNEaRin0Yin5PgO75pq/W2md"
+ "3FC1AV01g6BDADHGiLosobXGernMQmydQ7tcYjydQhuDVdsiOJczGpK5iQMhiIsuFrpdr+EG"
+ "1iYDxbwxlQCaIrQQkgchi0VAXAl1brPItiwRvM8/2RsBEIlgtUbnPRx/TsQmk9SLlRuEFrcD"
+ "2t+0/PuerLVktKZIpGKMSmlNJlnuCKVC33UhOBeFInAm/79A8v9T7v/TBuGUfljXrlz5jqE7"
+ "HGPMKL+ilOlYrdcAEpdDrBtiTDfKEyGTslouM1Cpjcn8jKEbK24jEaEwBo5jbwKy0P1QkByv"
+ "A4lrIsCiYnc+hyRaJ9ecEjDrnMv8HKIEkMr14O/y3qcMBr+vZ3BWJtoWBVaLRRa4xOsxRjRV"
+ "heVqla19UVUIIaBvWxRVlZ9B8JAslIFVlfsGEu4h1loyU33XJbC6LDMuEbzP4YZ3DmVZAkQ4"
+ "unUrP1fZNJgfH0MLVnGbtc5WmBXFv438DSsqaK0QoyKtleudGo0bRaTQrtfRud6H3vneex+9"
+ "j4gxnsn/L4b8/232/+WHHvrmeFgS0xulsGrbTHYrmN/hnUNVFCmF3HXoOU2pjAEBWC+X2dqR"
+ "SmleAf36vkdRFBvLMrA+kunwMcJy9kisBAGZlzO0ljm+RspexBBgWLtHnkRZpIoIhbUIMWUw"
+ "HIN+VVEgKIW26+CdS9kf57Bmzo6iTTbDOYf1cpm5O+1yiXa5RGEtTFGg9x62KEBAIhbWdZov"
+ "JiMaYzLQKFZvaFVzpmbgLisiBAwyRYPnF4svCxaMU/Tew7M1Favmug4xBOiiyJ8ji1X+lQ3y"
+ "p5G/63vSCTgnrRT1fa80oLTRqndezbZG6ur1uTo6XuPcbhN8RARRIIAiUcyhy5n870r5f7P7"
+ "/7RxKoYlLvq675P1UgpFVUFpnYGzGBNpLzD2AADBufz3zPjlLIG4/DT4HsnKAMiclTCwpAAQ"
+ "kDS1LDJxX0Eb/orgDDlL0/cJD1GbVK/gEs57WH4+WeirtkVg6ygWRX6IEq/Eap1dYiHmec5C"
+ "FUyKg9wrz8loNAIBKMoSjtP1w2cfPn+IMXkVvGAkyyX3cHsINHThhylxsdqRsQXZaGKFc8pe"
+ "sm/xJKAr1v0blT+IiJKiUgSoSKS1tRpEOkbore2pfvIzz6u/9d/+FP03P/Jz9NobN1XfdeSc"
+ "VyAQKUVQis7kf3fK/89q/3+9cTpxlN1iyYQAyDciv6/bFgrJ1RR324cAw66lZ+xhmMaU2P0E"
+ "Ec0YaNqQ7EAEzSFB5PeDF5cxBkZrrNilHApG7k3AwxhCBmZloTnnkmvLLrNnK0tK5RRrXZaY"
+ "z+cn7teFkN3ywBY0hIBuvU5EQF4M8i8AkLWoyxI+RhgitEPBySKKEQEbjIJY+BJ+aK2hGS8g"
+ "DkuEfAfgxAaQBSPzWlQVIs97u1xu8IdBOJRT54xFyGvfiPy7riOlNRljSGlNSilFRBRJKWuU"
+ "qppCrZZL9X/8+Afp//6VT2K+6tF3HT73+S/j2979AIVoqCosKVKktY6Szj+T/90h/z/L/X/a"
+ "OPUKTQSHDbYUvIdngExbm1K2SsEWRbJ0srCAzGPx4qLyyKCj39REgYUl1kaEWWidFgk/dAbq"
+ "RBgcMwsmIYIL3oMSjpKtEZAYvzKxYiX6rkM9GqGpa6zaNrvKbd+japq8SQBsSjxYmOvlElXT"
+ "pDKOrsucHKtUivM5W9P2Pawx6HyqQRuCwcPnUcZAMY7iQ8iYjZLFymGJ8JHEIgZeVABO/Cs1"
+ "ZgKEEpBCK8Z+xFuRlLaPXBYSY84wOf6OLP++T3hSUVBIYVcC1q1VREpFgup6r2aVVtoo+sjH"
+ "vkj/60/8Dr34yjF2t2bY2rF49bU5Pvbki3TxfKO2ZzvBaK1Kq6NSCfWIMUZSCobDQgnxSBQQ"
+ "h43CJA+DdQcgk06lvCfLX+u/UPI/sadu+xH5iwcpoXAQBR5TPaBSA37VYO8T0R3f/6eNUxWW"
+ "ZyVBwAlSnixcxfiCFG4CSLVDHM/KTQytjiw6wibkzBkHtqoyYVljDwUcEukMRLDyGgvUSAaH"
+ "syY5pKANQ1fuU7g3Simsl0u4okBZluidQ79e5xqogGTxxIYJ6CvWwUkKl59FvkMbk65jjyDE"
+ "lOFywsURN1xwG75H4fgQC1EWoJcMlTyLUidif8+LMCsn3rCRX9dao2katBz2CCAqi1RCniGe"
+ "EXixU9yUf+j0LMS1aGSMUaYoVCRSFKNSitRk2qgvfvlV+vn3P0X/6oN/jNGowWjrPiyCQfA9"
+ "RtMGv/NEix/8zmtU1xM1BoIpS+gYEZSKw/txfY/g3AmPyTuHnhUDEcHxfAugK/IRWdPguTKz"
+ "+m6WP++rYXbRhQDZ/oJ/icKOrDxrriIIMULxdYGNlLwvyz4EeKXu6P4/bZwOuq9WsGWZ2Mes"
+ "PW+va7qdmzGMq4k26VzJyAjXw4j2Zwwi8ubJWp6FIFoa/F7wNa7v4YCT1f2cmcgu70DbDxnD"
+ "YAWnrd0UgzqHNcftZV2f8D5OVKknySKGgKKu0a1WeQMMuSWK3WHvPaqiwLrrYLVGy5tEFkDG"
+ "DWLM9XIyL3GwkEIIIO+z6zw/PKQbL72kFCsf1/e5rktquLQxOXskVq5r28wBuv07ZKOkFcoZ"
+ "I2vz8wfvCUQwhSVrCzJVRbYoSFe1qse1msxGqnU9/eTPPU7v/8Cn8dwVYDy5gGUoURiLUVNh"
+ "3QYU9QJufRPPvniLpuNbynqvVzdvAl0XfNuGvutiVsTOZXBacBcAUEoDhBPepjYmP1uMAcFt"
+ "MnHQGrOLF8NkZycKz+uulX/cMN+F36SZRwYgkztzaEqbzhau72FV4odZVliS9RODJUrUc/eF"
+ "O7X/TxunKixpodF5n6q2yxKhKCQjBMOov+JsjLSSiDGiappcHJqti/cnmLBDljBviKx8An9n"
+ "ZEGK+ypcmqHGlolznCkBkL0tN9D2Ur8k17SrVW7f4Z1DFAsAoBSOTNxkTnoOpbRSMGWJlrMm"
+ "EqtrY3JmKYTUfiPEmMBc7+G0RlkUaNmtlufIwoonU9xSUS/WR+lNdf1zjz1mn/jRH20OJlPY"
+ "w0NE50CKQPGka4/bDVfM+mjz9zi4bvB/AoGMhi4rmMkYxWyGcmsb1d4uyr09VPsHMAfncOnR"
+ "BwG1g9/41HP4qV96Ak8/vwb0DOfOTXDPxR10DvjB77oXz710hI88dYi6HGMVPT76mSUePf+K"
+ "uv6CV/jKC3b15S9j8fzzWL/+Ovr5Asjha+DnphMPEvl3Gj4Lv55CS6Ss2/4+Xlut8Lb/8r9Y"
+ "ffvf/ttt5I1/N8pflIH3PjPotdYwvLdy6AygW68TRcGYjNERpexhhgycg4+DUh5ssKU7vf9P"
+ "G6cqLNe2MGWZ+vD0fb4ZW5YwtCGIZfaxMfDsCscQUFZVztA453I1t1YKq9UKFffnCdikLEVZ"
+ "ycQBybIWnIJ1XZf7BwHIFfbDUgcpp/B9n3oPMZckfx57HjK6tk28mxASKbFt4ZRCU1WZ6ax5"
+ "ggVDscagqSqsaAOwxhixXi7hvcd4OkXX9ykcYEERETyHZ1KWIKAk2NIQLyJhfYt775xD6HuU"
+ "xkAXBUpj4n1K462XLuH83/27QNciesdb9WsN0US3a7XBiJtLSSmQ0SBTQNUVVFNDNSOoUfqx"
+ "swnGezN88vOv4p/+5MfxKx96BaPRCJcunMfBwXlMx4SibFA1W/jKG8Bzr3R48CLhpTdG0LbD"
+ "zfkahz3hvsuXsH/fPSje8x7Q4RHC8TFC2yYFAg51459ww6LD4uBXAhAJ7K9ATca49sEP4ulP"
+ "fxqNNtnTiHep/KuyzPCHcw4qpFpK8VykQFtwtSFlAjFmmCB3mFAK5ZB1zoa/KMs/l/3/9cbp"
+ "GJb3UAOuyAmwl+PqPBmyzkV5sDWQh9QDj4cokQLlvcLMHX5GXpMxZrZwtjAhoHcut+jI+JRY"
+ "w4G77dxXF7gKLmCMSYxfIqy7DlVRYLlYoLAWWiksVys0dZ0WtfcwDKBqa+G8zxZWsI/gfUp1"
+ "9z2W8znq0Qg9c15sWcIxrmatBaxNz601AnDi/nIafpC61loDPjGUhXG8VVUYXbuG+stfxuQ/"
+ "+GHA2OSN5LgOoIEn8icN8USy6wX2WCnV5pHWiNaCCotYlgi2RDVtQE2BWzeP8SM//Rje9+vP"
+ "oOsCHn14F9vbB+i9wa054ait8dq1DkVxDfvbEUftFnZHhIcvtejdFK4nfO6FJe6/h4DpAcYX"
+ "DYregboW6B0Q/EZZ/UkK6+sNDotWH/oQFs8+h1lRwvA0CNfrrpQ/f2cIIfGa4gBsD5si5CCR"
+ "hChcY1BydNLzOiKlcu8qYLPHRTH8ee3/rzVOzxJy/Bm8P+EBRb55DMIrsTwZ6CRCwR0JhxZG"
+ "AMoMUsrDyg0PXHAJCaVAMwN0A8BZDSfS+6/+nAEwnZUeZ0aIeTQAciMxzVkNudfDw0OMp1MU"
+ "WuP4+DiRApndO5lMsFyt0Epzt6JAYQw6ziD1bOGG4LEpS1it0Xv/VQs112uFTabPhZCATbHQ"
+ "nAHTRClDowjtv/k3cB95LFnoP2lfn4gBv8YgAhUWVFZAXYPGI9BsBpptQe3vARcvIhycx+6j"
+ "9+Ha6wv8yodfwI/97CdwvGwx2znAg5cnOFpqvPRGAJFD6xWsJdx/PqL1JTpXYFYeYdVV+EsP"
+ "1vjUZ1eYHxuMtMO3P/gaipevw16/Bvvii6Dnn0d8/XWExTwpLu+B4BE9h4e3hYZf/Ts/NAGh"
+ "d8kjUAoUmfIA3oB3ofwFk5TWNZI4AJBJoxnYln0hmBoD7MM9KviWXC+wSWC86Y7v/68zTudh"
+ "sdsoNySTSCEkgJfdQhpM2LBIsmMtrolOcEMA5Ja4cqNDoG64t5TWMDIhEtJJZsJvQFVRTJkJ"
+ "LZ91O7jJ/1dKYbVYJMvHGNdyuURZFOgkzOR7Wc7nKKoKk8kEt27dQlFVaFerRBFgDEOA777r"
+ "UJQlptMpOn5mwRuUtWjbFkvn0NQ11l2XFTGATVlGSFwWO8Aa5Hk1z7sMIgU9qtPrxpyQe966"
+ "vKfz1o4nryGtQWUBqhvQbAqazkBbM9DODmh3Dzh3gPKeiygv7uMDH30BP/kvHscf/tGLmG3v"
+ "473fchEeEzx/ZY0QIrSJMNrh0uwGQlBwbQPSBxjXEQ/fW+ILzwf85kcdHrk34MHzGsu5wfNX"
+ "O5y/p0I/naLY2YE6OgK6Ls1/t0Z0AeRDUlrBD+7/dmV123MhgqoayntQ3+cHj4xD3a3yv53C"
+ "MCzfyQmnrkvJAuJODhyuyndJ58/8nUTZk5XXhvSJO7H/TxunN/DjLxatLWPYQTFfO7gZeYC+"
+ "bZOLrFSykoO/hRAQBviTxPASx+eU/UCY8m1ZualBtTq/PhRAGCwGYeLGGKFjTBlFtaluFwuT"
+ "M2UxZcikKVvftlgvl9ja2kqlFlWVQEXmo3i+H0LqIiDtTUinTozDRen7HusBbyjfO1F2jYmt"
+ "kh4sBoAJe7KgJK/KiQlCBLTNqej0tzwdkJfSe4FICspqoKpAozHUbAu0uwO1twvs7iLu7WN8"
+ "7wWoc7t45uVj/L0f+QB+6/dfwLgCvuUdD6MZbeH5V1u07SE6V2Br3OIvnfsSKrNCXSpMm4De"
+ "G3iM8fzRW/Hk0/sg9HjnW0ocbCs8+3yL164Cz+yu8bYLI4zKEvV4DDWegJpDxNUK8B4Uk7Lh"
+ "4AHwA+M0fKjb12+ihW8Y2DFluiiEXJR7t8lfDUKrTE4VL0miECBjS1KWpLROYWtM3VANG3Np"
+ "5yMeUmQ8LCqV9/kd2/+njG+op7vEuGH4hbd5LcN/iQjR+696AMtV94G9IcmsiFs6ePI8eYYt"
+ "g0yshIjEGntYa5UV1fDeBy40iIDApDm36ZHdr9epFqzvYbXGsm0zv8dYi57vRVK/12/exO72"
+ "NtbMlB4+NxGha9vEiVGpoVtZ1ymdzcDlqGngiwKL+RxW2sKymy4KV8JWP1jUw/B3g9vJDz8z"
+ "KE0l85FuXwKbbBoBWkMVNnlV0yloewu0tws6OIe4swva28XsvvN4+ajHz/3sk/i/3vck6rLH"
+ "pYvn8eB953Dj5hyvvngDvbfYGS9xz/bLuGf3CJNxja3pDkb1GIUpoShg3a1xef5FfP61OV68"
+ "OoFrCzz1OYd7LxhsjzQ++2zA972jxXQ0xmg8hp5NQEdj0HIJcFlKUsJ+8ySe8a0hDwP01Zgd"
+ "xU2YHBO3DJyNvhvlL+HfMLMmYVsQ+ITXyDCxpNhjFAWYQz0OkeXz/ABW+XPZ/19nnI5hMecD"
+ "SM3SCIAZTNQJ7TgA/iIvDMMupQ+banm5jlQithE2zevz56pEVhyCfGL5JAiQWHuIa2USnnyG"
+ "Sk3TMptXXGeJ6/WmH3XhPbS1KMImlRxCgCnLtKhZqAUR3rh2Dfu7u5ktvW5bFMbAFEUqP+j7"
+ "BM4qlcFXseadc4gAqqbZtPZQCtH7zNAXIUpzs+ECk8zPMMRNskj/Zk/LFgnGGSYEFYEUh451"
+ "BWpGKQTc3QXt7QF7+6D9PYwvHcCPRvinv/Z5/Nz7H8czz97E3sFFPHL/Nuoi4PFnjjCrHUrj"
+ "8dZzb+De/UMcbJeYjC5hUtcYj8fYrmvUiqAi0HqPo+0O53Zv4Nc+1eHmfILLBwWid/jj51d4"
+ "7WqPD/3hHH/nhyZYuwblZII4GgFVBayWadMI/i7PG4EYOMMG2qzBnAjlzBvrtDTNie3dA3e1"
+ "/GUND0/oCaxQY4z5NB/Xbw7KkH0m/CcJ0YL3iIKJiZLj1/+89v/XGqeHhGLZBpqZiHIRqmUe"
+ "COFkXZA2BhobjTvsOilaNw5cdXlQABvy2W2bMvhN3x9TFCnDI9k/VnDCgs9cE+8zzkDYxMku"
+ "BKi+R+89mqbJfJBuvUZRlug4s5NbktR1ZvY6ziYdHx+j7XvMZjNszWZo2xZHR0fQWmM0GmX3"
+ "3HBXgMDWROgWVdNAsj8EwLFFlQyWzGluWicHGgguwJst2ybezEPQncwgPNQaZC1QlqCmAo0n"
+ "Cava3QXOHYD29zG+dA6YjPCJz7+KH/2ZX8cfPv06ujjBD33PI7g+r/HKGyt0XYum0Ngf38RD"
+ "567h0p7B9ngfu80EO1YjdD1KRJzTCmMiUPDojcZ2Oca4bvCf/tBN/PonjvCRzxCs0eh7j+A7"
+ "fPqZQyx+8CKaokBoRtB1DZQlYG2y2PJMgkMBICSjJUorZTxZS2f8gNfXYF17Xid3o/wFwJbO"
+ "B0O8Vtj7QneQxJVSibHuWOmA93NGCcKGOJrnSbJ/d3j/f71xegM/jl8ds4FtWaLnljPL1Qpt"
+ "36MZAGcAcgkFcQhm2erIhCxXq5xpGWYMhrVq4v4CKWa3VbVhM6vEK1l3XWIkM84mcTyQygPE"
+ "ElXsdkt8TpSya13foyyKzCHpGADtui5ldWLMvX7kuTop2WBF2XCL3RAjtmYzlFWFmzduZP6X"
+ "CEGySnJfxlqsl8t0WstgoYShl8gKe2hFM87xNYQ7YDMAiImaUJUgW6R/R2NgPAKNUgZQ7eyg"
+ "395Fcek8Rhd28NyrN/C///jj+O3HPgOlazz8wCVs7ZzDS29cR9+vcf2oxLmZw3vvfwEHs4id"
+ "2Q526wn2rcZ2iLDzBa7dugkQUNsCIyLoGOC1Rq0UyqKEVvv49771Jl545Sa+8HyPGAmVXuO9"
+ "by2xXq0RVYGgCNAWZDSiNoA27F1H9hj9JvFJEh4yZpU1d56G/EsGnO9m+QsQLgaLjbNwpZRK"
+ "2Ur5btf3qKxF3/epFQxzwHK7ZL5uzSRTOaOQ+D13cv+fNk69wrCXMhqNQJS6ME4mE8znc+zt"
+ "7MBxJsD3qdm8nDoSmBQnNypV77PZLH+meFIC7EsIJ6drxBCSqy1C59SqNAkLIXUqzATSts3N"
+ "/5bLZT7YUvCHIXiv2XLGGBMbmHsYgTEIaa1rjUHbtqlvj/coGGiVwwZWqxVG4zH6tsUb16+j"
+ "Lgrs7e6iY2vaD4p2hcBqubslgFzy4MXdthaerahYVwF9RbgZLwhfg6fAODxIgYyBqmtgOoOa"
+ "TUGzKTCdgSYTYGsb2NnG9n3ncX3l8BM/+wTe96tP4uqNNe6/7xIunZ/i+pHC8y9ewevHMzyw"
+ "dwPf/dbXcf/eMbanW9iZbGG/qrGHiFnfo14u4Y6P8PrVq/BNAzWZwGgNDUCzoTEmgKoCttzH"
+ "f/7DGv/8176CdevwzocI3/ZIDVp00NaD2hYI3ONb69SrPYe8G8wj66SIxNk6MQ8bT0u8zhyq"
+ "EEEzgfKuk7+EXBxpiGKSVjdyrRzt5ZlnJtnKTIsQJ4FJqgghdyGVvvZpWu/c/j9tfENZQiGb"
+ "rTkrsXQulTX0fS5Mbvse5Bxq7pUzzPpJZ0LvXGomxoWs+TQNdhclnUq0aVLWjEYpGxJCPqxy"
+ "3XUAu6MxBMxXK4xGowScrtdpkyiuleLJyZkWdj27EE6ceosY0a1WWVjBeywHRz0RbdqP5FIO"
+ "Zh3LQQQ1M/Ffv3oV5/b304LXm2r0W4eH2JrNcPPWLVR1nTouunRAgSbu7z0ANomtE8SjChvW"
+ "M2kNpXIecJAB5FDI2nRI5XgM2t6G2tsD7e2DdncQpzPorSnKvS2oSYP3/+6X8BP//OP4wvNH"
+ "GE/28O/+wAN47grhuVfWWKw8mqrEdzz0Ii5vH+LyfolRcxkXplPsFQbbMWK8WqFcLqEXcyyP"
+ "j9EfHgKc3YPSiVoQAlSfsMSpMSBTgPZ38Xd+WGG1vAkbPEYosO06VGu0EMmuAAAgAElEQVQP"
+ "fTwH1olwCK0BazaKJ+NYw9AQAEXmaQ3ToBhcieyd9iHAMpZ0t8lf6kWHe0fC19vJ1/JsCgAZ"
+ "g8ilNiFs+m3FyG2nB5Uk7WqFbr1G1TR3dP+fNr4hpvuy71PrjeUSBbvQvu95c9CJ03JlCLjp"
+ "Q4AH0NR1bhPj+h4lt+3IoZ/66mZpsgsD4w+5zoktjLE2g50iBMtKzXuPsiiSSzsQoqLBySo8"
+ "ur6Hcg7loGkbkPpyt7woPQP3cny5F6GHVH4gKfHFYgGlFN64dg0729sIAAoGWieTCQBgPJnk"
+ "tiTiAUZWnpnARwTD/bqHWVMBRE9gDUCShSKgKKBGTcKmZlPQ1hbU3j7o3D7o3Hn0s22MDrZR"
+ "zGo8/rkr+N9++nfx2c89i3K0g+98zwPQ5Q7+4OmrqMsIFwu868EjHIxew8GMsDPdx+54hoOm"
+ "wo42mHiPul3DrlYwqxXiugW6Dr7rEuCtNcia9P+QOFS671EpORxBoZqNcKwi4nqNcQyY9g7V"
+ "eg3Vdwmr4gQBImf+WDsTh363s7ASED9c/OKJbWgvxqQWLrkY/C6TfyY/y5pmD3SI92amPFLk"
+ "seIOEbIH5O9SSO36HuvVKpFnB9HHnd7/p41v6FzCGAKOj48xnkyyi7tq29S4n8M3Uiqf3Nq1"
+ "LYJKdVg+JKZunizWrIgxa1pZSJkFO7j5GGNeEB1T/EklXsl8sUinpPAhliI81/co2AqWEj46"
+ "lw7nDIkqIf2+1eC+JFSUfkERqX6s4x7WTV0jsnAF5/Bh06N7Pp+nlLVLvYwOj44wnU5xfHyc"
+ "BGptxgma0ShliooCq7bdVMWb1Kdb5iF3ljAGFDZV8SKbvDG1BpUVFNMT1O4uaHsHtLMD7O+D"
+ "zp+D2t/D9oUdfOmlI/zUz3wUH/zQZ6CLBt/3PW/Dcm1x88jh1ZeuYjyZ4vzkdTxwcAXTYo6t"
+ "yTb2JzMcNA12C4uZVmj6HsW6hV2tQOsW1PcIiACp5FVpk3Aza1OygwuL4T1016EMAYoUCu8w"
+ "VQRYCxsCCh1QEEDBQ/Wpdi5KrR0/s/iVyZnceJkb2D2x4uW4d7kWEbnxHeKmQ8HdJv/N1oxZ"
+ "aeTfeS/FGNH3PdrVKhdsS7mROAUhhKyQC8bbAntA3nv4GFFzFHOn9v9p4xs6l7CqaywXi8zp"
+ "WCyXqfd1CIiDqvN+IHjEiLbv8031PBmWSWTDm80ZAtowhsVllT5IXirKkVx4VRQoYjyxgXNs"
+ "TISirlNFedtmz0yxOy34Q+RJKwWI5NYZpihS47J+0xmyKgr0XQfLhaBFUcA7h8IY+BBwxIvT"
+ "9316fwhYrlaJk+McSrNp8xK8x6rr4JzDZDqFtTZzUobkRbGu4EwSzKZ7o7jbubxkNGZFtQc6"
+ "2Ic6dw60t4e4tYPi/D6qC7tYKIsf/4Un8P984I/w2i2Dhx84h+lkgtbVeOHVBTw07rvUYL/6"
+ "Ei5tH2I6arC/fR/OsaLaJoVRDKjbFrbtoNo1qG0R+z7djtZQ1iYP1qQwjqzlXkusWrwH9S4x"
+ "pZWGUYRQlkDTQGkLbXT62+EtRG2ggge6HiH4TObMyum20HBDeUnUhijzx4OY1pC7dHKYctfJ"
+ "fzCEQwWk7iSigF1I5yFaa2HipmdXx99RMhBuZA+FDYFUPEeBUe7k/j9tnB4SOoc2RkynU1y/"
+ "cQNVVWE6m23+zmCbKBcwaziw5ZFDHDO4lvEFyqUGw/Dv9vRzUVX54IBSgHbnoLzP3UQLxhza"
+ "9Ro1nyrccgZms1gpnSzC1qNnULRgDGLY/VCKM01RZExMYnbN/BY9WDyKKFvS8XgMrTWOl0s0"
+ "dX2CbHf1jTdw8eJFzI+PYYsinbiyXKIejVAohRWzh/Ww3UncHEowJAqKRTKTCfT2NtTuDvTB"
+ "AdT5C1AXL4IuXEA3nWL7nn2sSONXPvYq/tkvfxzPv9rjXX95HzvnG8xm2/DO4eUr1/HAffuo"
+ "43PY0V/EzqzB3vZFHMy2cFAV2FYa4xBQ9x0K56D7HtR2qUBZwFIyid9VeqCwiedlbeKCIYLI"
+ "JQycCJEApS2oKBLPqiwQihKuKNDMRmgXLcLVOoWR6xVouUwe2sCDGFIWuGQww3fyMiDhYcjK"
+ "TXoy9c7BAHel/MUTCT7VIopRV1rD8/0LFULKeww2nlfHe6DrezSjEbxz6PoeNiRqx/DI+Du9"
+ "/08bpzfw63sUAJbrNWp2iY1SWHFNUuZYxEERMpiIZy0i0tlsxKCeZEIUZ1CATS9o6eUtgDsR"
+ "5cp0Ulw8ylo+xIh126K0Fh0zlVUIuWWHgKvapNM8QhxUi3sPRZQXjID0kbEWOTJpzSCsZwpF"
+ "xW1zC16shrOQXddhvVqh4dDV9X0ORcHAf7taYWs2S2HDZIIVYx0A0v9N6pYp3QOEa6U4XS3x"
+ "PvN2iJSKdjQiv7cPe+E89ME+1MVLUJcvgS5dBvb3sHNxC5946gp+6deexGNPXMFbHjqP++61"
+ "+NQzBS5d3MZkVqFqPFRh0B4/i3tnT2H/4F5c3t3HuckYu2WBaQQa71CyotJ9D/Q9yDPDm0mJ"
+ "iewUQMElZcW4SvawGHeKxCz9qgSNx8B4jFg3aLbGMDtjPPXpV3Df+S1YCnDzOejwCDieA20H"
+ "GnCxBlTYE8oqDtZ9viIAiXWKLH/ECGvt3Sl/9qqGvpYkY1zfY9V1sEqhHo/R8jmLopBNUeRS"
+ "Gde2+Zgta1JH1Mi0iJxBv8P7/7RxOtOdtbRbrVA1Dawx6H06LbfnrIFoyhhjzhhI75vJbJb7"
+ "7+SfQRyu+AHF/ZbPyinbmOqahF/iQupXFAEUanPqR991GzDU++S6O5f7bNuiwHK1QmFMCgGM"
+ "SdaBP7PgrGLJRa1lXSchcmhqxFrpTdsMSTsLbwVAZgfLsUfCMi7YYiqkpoGGwcvgfcYsEBOv"
+ "xzJIK8+c69uI4L2nEAJZa6meTInuuwfm8mWoi5cQL19C9cC9sAd7uLZc4f/88Q/jgx95GUYB"
+ "Dz70MK7ctLhyU+PbvmULF89v48OP30BTW1zcVdhqX8Du3iXcd3AO90wn2LUWEwBl38P0PXTX"
+ "gbhrAqVJ36ShhWgeY8oMFgWiMYjGpuxeREoIgDk6WoOqGhiN4CdTjM/v4JmvXMP//D/+Mj7+"
+ "xBfxX/2t78N//Te+BRg1sJMx6GgEWq8BDodPAO0DsmwUx2sYKoo3FkImkJZFkfGgu07+4oUN"
+ "WOnCYRKqQ10U2VALGD6sR5TSGm1t6h/f97kTqTT6M6wo7/T+/+YVltZYdR1q5nv0XZcYs22b"
+ "aoPUpqdQy4dG1lWVFkrc9Mu57ejy3DYDSN7SdDKBZQ+oB6CsxXqxSBPnPYqyRLtapZ7kq1VS"
+ "YuLGy+fwIlRIRlWyFiL0kgl4ADLXJpP2IvNz+B5kM8qicCGkDUOEAptTWSomrgpWImFL8B6d"
+ "c9C8WGTBibcYnMt9yOvRCMvFAhrA0dERqqZJpxeXZU40KGuJP4cIUMZa1FszZR99FOryPVD3"
+ "XML0wXvw2sLjsQ99Dv/o55/CqDGYznbR+glevqpx76UG7333Ft776B5+/SNHeOByhYMdjTdu"
+ "rGGqA+xtR+xvbWG3LDALAVXvYJxLRbiRe45rA+i4cV8G0RlCBDkPMjbhWcYw0x4gxyG/0iCj"
+ "E3vdWoz3ZnjfB57C//D3fgl1ZVHYiF94/xP46999L7a0xng8RjmdAut18uwGvb4yMsZh4aBQ"
+ "chNhkE94VuCEAF+07vuEid4t8jcm467DH+Dk4SBDvqEpikz4PDEG79fGpCwse2iSoczK2Jg7"
+ "vv+/3jhdYVkL1XWJSMcgo/A1uvUazXiMxfFxag5W11gsFqmHdVVhtV5ja2sLQW9awQjpbZip"
+ "KIsC8/k8N0eryxLaGIwmEzjnMitZW4vlYpHIfF068VawBOcT2VDc0aG3BiCfVutDQF1VMEAG"
+ "9wXs1ww6GmNQaI1+kKXRDCQG8CEWjF945zJJsLQWpizTBuAFJq593koCltPm6PTlfI56PIbr"
+ "utQjfL1OBwaUpbTbpeA949qatDGKjKF6d0+Ft70du4/cj2XR4Bd/+3P40Mefw+N/dBMwU5hm"
+ "H0cLg3e9fYa2DXj4vgP89e+/B194scWiW8C1CoXpsVxF2POPoKhfQtU0qK1F2Xcw3kMR9zDS"
+ "GqR0DruGYVjWDTHNC9m0CaJl4F2wKwBQiZsFzbQMrfD5P34RN48dvvXdj+DWAjg6WuB3Pvks"
+ "/up7LkAXJcx4BL0cA4KZZSL7AO+McUAO3XCzok8F06QDSFGuabMqnS94N8i/Z/BaQHvBmG6v"
+ "hwWYiMpeofInqz8GN5G+n+9fJk1aSYnSlgMv7uT+P22cjmGt12g41Mqkza7DqGlSecxqtTl9"
+ "BOnAyK5tsVqvUVdVehghkgE57rXWolAq12xpInTOYXd3N58Zd/PGDYzGY0QkTowPAdPZLB3P"
+ "zVp9wYz2pmlSXM5uqiwI+M0RQ9raFLPzdc57bG9vY3F8nEPQXCSN1CJEOjqKyZbz4uSYpJLj"
+ "emlj49oWfTx5gMDQBZZFm1tsOJfY04tFyjKFkLCJGGUOiYyhGCORUoq0VgFQpVJq5+K+jjtj"
+ "/P4zV/FP3vdBfPZLR1isa+zsX0AzmuG737OLm8eEv/Luy7C2woVz2/Ah4rc++ixm4xpqtoeH"
+ "LnRA/wY+/pRFERs8en9AryvAJuUkSoDU5gi1E3h33OBGFCLIuURa1RqkbfKwgNw9Qco2oFKf"
+ "b7+a49L5XTx0/yVAFbh4oHDjMOC3P/YavuvtUyhVohmNoMeJPhF7l7AyAIHThUQDRhanCgeU"
+ "2nRzIeTTpCVrFWN808u/ZOMt2eEYY+6/rlQ6Ak0iiXyiDitUUWYSrg05XrkxgHiEnEzo+x6W"
+ "M6BAwu/u5P4/bZyqsKqmwXq5xLrrMG6aRCBbrTbxNYPX3qfm8yQuML9/qN0ja36hJ0AEz+5j"
+ "U1W4evUqRrwISCksFwsAgOPUsyx4ab4v59KBKBenDosrJVWbFwoLS1GqJ1xx2GnZaqwWCyzX"
+ "a4zHY4zZw8ukvZi4O8KOFgxCahOl9Q3CphXOarHIR5fJIhZmct68PM+LxQIxRtSjUQIqlaJV"
+ "21JZVcpaqyKg2rbX00mlQF498ZkX6Rf/9eP4yOOv4Gg9wqWLB3j72/exahVeuqrw4SdbjMcj"
+ "XLy0wktXFvj45w/x8KUF/vIjF/GWy4Q/eLrFk08voELEG7cMfudGhXe/ZY33PDBFhxK2USBS"
+ "gFaA85l8efvYhIQB5PqUHeQ0fPKwCHBJRlFRagDDQP2twyXuOT/Cwf4Mz77cw9gCpGu88IbH"
+ "7z15A//+t5/HwtfQkzFM14Jcx1Y6R4ZAz4RS0EZ5UmRP0COCkvenNUixZ8NK800tfyKslkvY"
+ "qko91zlDLokpOdZMuFEZAtE6JQ4kQynfGzedRkVxyIlBPgQUMZ04bVghSkuYO7n/TxunKqz5"
+ "8TGqssTOeIzj42M45zAejdKXMbbUdR2MMSibBovj4/TwxmC5WmXmuWh5WxQoOEYWMLPrexit"
+ "0XYdZtNp7tET2zaDfkJU69drNJMJNLvgvfeZY+K9hzWbtrGSCYo8Wa7vc2mOUB7E45ofH6cM"
+ "Blup5XKZ4+2cneHFJaGlZ8sKwT544mVRBsbYNr2reDOpzdHkwbmcBpZ2IfPjY0wmEzjvs2cV"
+ "QtRak97e3VZPPfUF+ulf+Ch99PEvQ9ld1M0e3v3wNrpe4+XXljhuR9BG452PlHj92hpP/NEK"
+ "IQY01QzvefsBKrPG7z7e4vkrCn3foO+A6djjlVcLfPyzN/CWSyNU1TaqSkETQFqB+tT0LsZh"
+ "R1dg6MVQCKmrJyssMjrjI4nOMCAH8hFd3kfs75RYdQpdKNH2WyACVm6Bzz63xve+aw1rRxiN"
+ "J9Ad0ymcB2LY1DTLfUjfK/G8onAePGJMTQ9lLRS2ABX2TS1/6UQS2euS+4vs0cSQWORyBDxJ"
+ "CDtQEEprQG2aAOaQjPdjwYdPaFa8CoMwEYklcCf3/2njVIU1mc1weHiYOiNYi4o1t/zeMqXA"
+ "MUlte2sLi+USy9Uqu425YJetQERKs/Yu1XLVnC4mAEs+4y20LUZcR9hyStlxdqLjLMtysciY"
+ "13g8xlrSozzhxlpYrfMpJdlFF7DPD9phsEAdu7aaKGdZAE4bGwPFm7JnUDJiY0X0AHiNIZ0E"
+ "IpX1YfC34eIXEh0A1KMR1lz+sFgsaDweI6ZT3ykgquC8+qmf/Jfqp37+EyAzxlseugerdY/x"
+ "eIRX3ujgo8HBdsCD545xc7WFzzxD2Ntp0NQejzywhRdfC3jh5TmOl4RXb1QACD50KC2w0zgc"
+ "zGrcWE/wyrU5mgtjNHUNzVgPdQnDIOmnPlBc2d0JAeiLpKR0wrHIcMvmgZcbYgBIgZRGCMD+"
+ "dgUyY7TO4J5zQBcrXDqw+KPnb+GpL8/xA28foaUGZtJBt2uQ61Ohc9jQRjd6i0AkrzPni5Bb"
+ "+mrOmoUYcmPAN6P858fHGI3HOWyTziOWMTLiz2p5vwz7et2eiTuRfVObTr5DSoJ0XJUQWPpw"
+ "lU1zR/f/aeP0Y77YFWzX63SYJWviqigwXy4xbppMIej71LHRWAvVtui7LqWMJRsxcKHlSCBr"
+ "LVYy6RLXx1SMOV8sMKprGO/hGCwPzuU0qdyHcw7Hx8dYdx0m0+lXuZaCQTgpedA6lxHICb5F"
+ "VYGIUu9ua3OpxXgyyQtQhC8hgAdQsjs8XLiyQPJJvdgcOjnENkSYMnpmSUv7ka7ryBQFRaVo"
+ "1DT0o//oX9H/8vd/Fe94z1sQ0OArr64wGRl4dwNvOdfjvv0VSt0BpHCxdnh47xKu03tQ2hU+"
+ "+8cEHxSuz0foQ42yABADzu+nUGO/GaH3I7z+Wovf+tQNXP5rxzjSJcq6yG1+ybnbWhMPKQYc"
+ "dnUdyFpErVJGMXtYPoP3uYjXaBAIijS2pwbKFFiGHVzYWeOVqwakGnz0M3N8y0MzlNUE5XgM"
+ "3fWA84DnHu9Zxqw7aZi2TDcXiRjD0llOtiwTteVNKn/LfeXBeA8xruT6HoG9s8IYtEAuj5Hu"
+ "nQLOF1WFfpAlHIZnJ7iNMUJjc1q16/vMaYwx3vH9//XGqQpLyF3W2sQw5w+W8Ms5B88dFYP3"
+ "aJ1LBaKDJmhinYRlrgaC67ruRL+qzGcJIWVqui53SOwlM6jT8dgrbFjJAFAYg/nxMVbsAnd9"
+ "j54XzYiPahJy2mI+R+8calm4zqGqKjSTSeZvNU2zqYKXlK9SuQTI9z1WbQurdcrmcCaybprc"
+ "vlmeJTiHajSC4xBEGM3y+zCTJKcHh5h4LUk99PHgYBu6aXDl9QUunLd454MKD1zosFW3KEyB"
+ "wk5RFyXKwiKQhg9H+PQLn8PvP30fdBER9QSjUY/9WcTRusb9l2ooFTEbKTz9zBwqLtD1AZ/8"
+ "gsG7Hj7E9717jGUwMEViXsvpNeT9BtweKofgE3vdMGnSqORpqYQXgZWVihGBCFAahY547mUH"
+ "pQwO5xaqDFi5CbYmS9zCCJ//SosvfGWO2aNjNPUIduqhXQ/qO8D1yVOSTTjcmFEoD6zAfAC0"
+ "Slk+7zFfrRCAN6385T2yJ6y18KJw2PhSUaBsmpQBd5sDhKVjqefvABL04UPIDfeCT+RpUdS5"
+ "n5x4Way87vT+P22c3g9L63xCSMVdF4FU0qAGhLOeewqJ5hY3t5SeQ6tVVhZDQWp2JzMQxyGG"
+ "5u9dLhYpFGThxLBpXyuEt65tE+dFpeOvJU09qesE8klNGBIRVhuDyM/RO4eKS3xanmAAJ6wh"
+ "EaEuSxweHmbCnCkKxLZFxc8nYH/JFlIssWAGxhg45tQ4zj4pvTkzDoPFmP5JFEilVETw8fr1"
+ "o/hD3/2W8D/9dz+gb928ifsvqkhuAaw8jcstbFUFJtai4RAuFhZLexGzt8/x5TeO8MI1g9GI"
+ "4PsG73i4wWu3gO0thU8/fYyD2QKtL1HpDlFv46g1+MAnr+PRBw5R7FSorIVmpUWisCRFx+QC"
+ "kuyUbZNXpTSgTKI4MCUgdWxINIIQASoUJrXCx379NXzu2Q6PPDjCjXnE7vYIh4fplOVlH/D+"
+ "3zvCOx9ZYl7soByPoPoOqu0Qu+6El5WnT2hiksYkStdpk8tqNHsWb2b5C8dJQP+CW81ICxpF"
+ "6VDWfPJMPHmCjrid4TYlIR6uY4Ne2M1J6vm9fP0d3/+n6aPTLlBaYzGfo26adCQSx7iSJRCC"
+ "Wddz50Egx8Nl0+DWzZupET+zbzOBjF+TmikKIT9I51xq+qY1dnd2AACrts1dG13XQXPBqBDr"
+ "NFsh4b7IhJ0osJQsD5f4yNHZOQvEC02a5ccYcyX+uutQVBW69Rq2KBBcKprt2BUeq8SULqoK"
+ "br1Oi4DpE+KI986lolm21LdX3scQhgdKRiIiH0JUREERESlNf+Ovvh03blylw+NlPL56A/Xq"
+ "dX0Aj0nXolmtUPikuGMzQjubYTbdxt/83jn+5cev4/x5A1PNsOpK9Os5Xnv1Ju4/UJivFEAW"
+ "t5YTBE+4sN/i8y8U+NTTh9j69gnKokxpaFMmJrv3Ob0PDKgPMYBsAWUTw11Zm0pzRGHxz7r3"
+ "aMYFyET841/+DP7Jr7yAS+e2ceVwAhdKXD8ucGsxQVkuURqLq4fAb37yEP/RvzPBAhXMeJwa"
+ "/K3XqcYw+A0H64TnJ+Eh37PR+dQcH+ObXf7JaA0UWcLoYj66q+M9qDnr7Zzb4Ip8rQDeooxk"
+ "/xFRqqccUA6kS4OE+dJZ4U7v/683Tsew+h4lpzbr0Qh922ZATrJxhTGIoky47sl5j5Io86oE"
+ "4D5x6otocU4pS42U7jZntc15sobM3J5j7FHT5GLNGGP2oLzWqa1G16HijEa2rGHTYF9pDcXu"
+ "tLSaGWaF2tUqufrc8UGwj46zl0Tp9Nps2diiIsaT9VXYuLtKaxS8EKUUQqwbBgLj1yLze6LS"
+ "OhTWUlM3Mcz2aLJF8RhE8Utf1HtGYxICbNencElpYDZFSYCqSjywO8H3v7PHY0+vUFbX8Pmv"
+ "9HjHgx2ianBjXuLGvGYgnNCUBmNLmC/H+NXfv4p3vfUIVTVBXZYw2uTThxEiA/AQIlTynsoS"
+ "pqmhqgpKiqCVRowJeA4xYrZV4yuvXMeP/exH8cHHrsDUF3BjOYIuDIqywNWbAaUlnNvxuHqr"
+ "xHw5xe/9wXX8lbfdwiPnD9BWNXTTQDUN0LaAk97jfDtxo7jSxiXAp8JcU/IhESEdLvFmlr94"
+ "R5D3x5jZ50DKDkZh5tNtxcQsF3kW2WtDpXB75lBItIrvR/CsO7n/TxunH/PFrmPBh02WzMQt"
+ "uBK9Xa9TfB24Olsl9q7lPkiZsMYWxLN1lhtvua+QlAUIf8VL2pOP9waSxl+tVohIXSEBoLQW"
+ "LoTMRQG3n62ZSKqJsAZSVksplDwp0gJXrCbxs7Zc3lCWJdZdh9F4jA6DI454sQ1b6BZsdWQh"
+ "5cZsbL2NtSmMYAFrY3LRaQwnD6SM4omwwrJao+u6GIFQFgUwGpHVGqqqIl59Va+uXEFtDUof"
+ "krLyIbV3cT2UsZiMRuiqPbz7AcIHP3YNV/0SW43Bazca9CjRhwrWBDy4P0fvAl56o0HXO5zb"
+ "6fHCyzV+51M38Df/2gzHrkJR2MR8F+A8SuYLyZkJEaquUE4mMONxWojGwHNrmaoyAAX8xm89"
+ "ib//j5/Ac6/02Nk9j62tGbStcLQkxEiwBqjKgDeOG+xObiH4AvMF4X2/eRX//X8ygdUVirqG"
+ "HTWpY0QQj09OVYqZiZ+wMwUiQDUNyjJxmpDoIvHNLH+lUn+ubr1O/bK4pUu7Wm04iTGewIXk"
+ "M8EKLDKOJUpJDk+NIWRKgjzXkOAp5TR3ev9/0wqr41hfJuXo8BDNaISjw0OU1qKQeiLv0Xuf"
+ "PBiktOWaewEZY1CVZUp/clYGQHZlpV6rdw5FjKmfELuPhA1JD9amODqEXP/V9n0SqPf5lFxp"
+ "5mesRcfaPS82Y3K3RaN15roILibWodY6NSCLqbPpsm1Tdwdm/q9Xqw0gWlUnwVSxgAy8yuk9"
+ "UqQtgivKEo5T69JSVha6pIKJCMbaELwnANEYQ0VZorA2YLmg8MorUFUKYRA4e1cWIK1SL/ej"
+ "KSbjCcLWCP/h963xMx9wUL4FdSWapsPB1ONgy+FwWUFRwM4s4LWrDWZVjXvPzfH/Pq7xjkeu"
+ "4b1vH2PpbMIpFIE012XGTXdYioCOAaPtbdjJJIHKMcLqZD0/9enn8GP/7BN44jMvo41TXL58"
+ "Hy5f2MayJbxyrcOosXDBYW+2gPcKC29xvCpAWKPDNn7vqWv4zne8jh9892XYosJ4MoHxKZyI"
+ "4bYTw5UGFVagHWiXcFAzGhFiJK01FUWBNsk/vlnlb7jcJ/hhpwqe+hAyPhiwoTRIgbPU09Jt"
+ "r0uEoa3NuFgUkN9v+scDyAev3qn9/00rLCBl33qXuiiWRYEl9/pZrlawkgUYxN1R8AHnsLW1"
+ "lTCDgdttpBVtCCjrOnVhcC6RE+VzwL2LXCo4nTNpTQqYlVIo+L3GWti0ieFDQMsgPAGp86ja"
+ "HPMd2dPKJ6XEDUcrxohKiHRaA5yuRUyEt47b2cQQMgC5HJyqIiRAz1hF5IVGQD4dWCmFno3A"
+ "cL5ylkawNrZuMYQohwvExB6FTeB17BeL4G7eQGxGgEm1flHrBGGs18B8AXV0hGprhn7c4Fsf"
+ "HuOB88d49rVbGFUau6Meq26GWwuL3ekaL16dYG98jKPa4KgtcWHvPFS5wKe/fIiH7rmJ0lQo"
+ "jYHCxqWPIJCSbBxBEzBmhaWUwmRc4OhoiX/w07+JX/zXn8XNZYHZ9gW88/59+Kjx8pU5ls7C"
+ "2gLrXsOaHldulGiKFuNijnVLWDuNEDR2p8BvPHYV73zLFvRoinI0hg4ByoUB3SJy99XIveAt"
+ "ojbQiGiWW7Db2wpEWmtNyphAfR+1tYjexzep/PPhEgKeQxQiY15Dr0gymcJ8F88mUykGSmFI"
+ "OPXO5SygZgdB8b6/k/v/m1ZYgvIX3DVBaosCKw+ZiGGzvK7vc8x1RBIAACAASURBVObBcaim"
+ "FJ8byO6u1mlzrebzrDDkRA+J/4WPFbxP2pzTqFprlExKE9hSWs+4roNSCiN2y4cLQt6rgNT2"
+ "ljldhnGK3jmMJpN8bc8V6aBUnZ7dYQb2bVnCcjpZW4t2uQQRJfIrA64S3go/xhQFOi436roO"
+ "BTcVlHkcFmwDiVYSvIcPIdZNkyrj1+vU4imk/kXR9cyOVLm9CroecbUCHR/DHB2hHk8w3R7j"
+ "P/7eJf7h+49RU4HD+Q6qeo2Xru5he9xif3KEzhXQpoAyO/C0xt5Wj4/8YYv7Dq7hB79rhpWz"
+ "sCbNYdTcSxxMkOSQZLI1w87eFopC48O//zn8g5/5PXzqszcx297D2x49h7Iscf1mi1sLgo8F"
+ "xk2PvfoKZvZVTKslQAWutffi2WuXEKNCXXRoqg4maHzppTl+47FX8J/98ARLlLDjEahjmoNP"
+ "B4JSDKmGsa5ATYNY1dBaYewcyksXlSlL063XqaDemGCJYrdavdnlD5H/mj2h3F6GcTA5Hk+b"
+ "1I9MMDLhg0mXCAAZn5IwUhuTS48kstGcWLiT+/+bVlhSLqC0Tr2plULHjfjFdfUclgmoVzGP"
+ "BCy8pq5zvdHx8THGUu3NDdLEVRblIv2r4Fwmtwk4Z6tqA2ry5Eo8LNlDJRuIPSrJAoFSgWXk"
+ "UgANoF0u0+dKkSlX198eTyv+fCllCCGg4w6n3WqVF5B3LvF3Bm6+504TluvBpKeQ4eSAZDe/"
+ "qoiVCGoQzopCl1YjOX/PP7mODpy6blvQfA51eIRiMkFVV3j08gTf9bYOH/7MAju7DTQIB5Ob"
+ "uHlsQHqMdzy6g++ZRHz2mSNcuXIDpIGLF/fw9Iu38LaHr0OfL1FaA6UNiNLhATAGURH63qOs"
+ "CzTjCl96/gr+4T/7FH77sS/C0wgPPfQW7O2McetoiTeuO8zXFjuTHiN7HW89eBG7kw6TyRhN"
+ "vcXW+SouvrbA41/eh40Rq46w6hX2ZoT3//aLeNvD2/j+d1xG5wvougItq2Shk2sOqmtgNktH"
+ "mU0n2Luwiy2l4CbbqlUwAYiaKHZtGxUR2bKMd438OYEkBGOtdTpoom1hjcmnSYUYUbAyExKn"
+ "1Xw6DjsExOB/BuqRcGFRdHd6/3/TCsuH1LdZ2K2iBbvVKgNluYdO5MJP4XywZ+Qdn0hChJ2d"
+ "HRwfHsIxZiBZC0nZghg45QkHu5Ka8QWxRpnfwpOfMy3yXqSMRT4dmVKdFBj7Ehd22FJEcUjp"
+ "/j/q3izIsiwr0/v23me+k/v1ITyGjIwcKwdqoqCgqqhuxFQmGkyYJDPJWg964En9qDfJTDJD"
+ "kslM6gce6JbUtEmgbiQVjZqWgBZQdAFFQUENSVZmZWZVzlNkRmREuIf7Hc+4tx72cI9HAZ5m"
+ "1RZkHDMP9/Dx3LPPXmetf/3r/10ZmuS5DWiuRS3ZtJ/9hTbaSjQDlKsVrdanjCWVW1BvboCw"
+ "w6KNV7M0xg6bui6Rf92m95p8O9xfHw++9qVsrYAehIlgY2w3ryoRiwXRfE42HJJGY376kwXP"
+ "vrpA6Nu8cyPlYK+hGG7z4JUJb19bc+vmHINkurPDE1c6vvXtQ7727Rn37d7iZ6djlnXq3FPE"
+ "ZoBXwHiac/XqIf/sX/wFv/avvsnVW5L777vMpfNbrEvNG1eXVI1EKsN92zd5cPca9+8vGYz2"
+ "2Znusj2ZkOc5kYooq4r7Lx+xMznmt/5MIiWM0prbJx1V1XB8MrdqBkbaQerISTJjrCzzcATb"
+ "U5L7LlANx/zm11/l2W+/xdvXDuU/+PmfFJcv7uu6aaWS0hgwkVJCxrG5J9bfZTtRkoSZPCEl"
+ "scvmlosFWZoyHI38EL3VUnelqB/z8a42voSL4xjlHvK+yrnr+/+M430RR310T/Lccl+ElTcV"
+ "QoS6XUkZNIICYNx1QTKicyL9SkoyJ8JXjEahW6Kk3NT1vb/vyWv+aRUCln/z8se+XevTTreh"
+ "S9ed8UL/sNERgg22ULvWtf/etm3D3+rL1fj2s7jj4kopSbIMWdes12s6Y8hcWuxlbTwW0Tgs"
+ "pOs668QbbVxEfPtbuTKjc21lL/1stGY1n5M4UmxIsLTByB7b275QaBpYLRGzOcl4TJEXXNoZ"
+ "86MfX/GFvzQ8fkXSkPPkQ5J3rl8jiwXLKufKhYxWw58+dZVIaC5fHPPajTVvXbtFfLkgyzMb"
+ "G6QgSyXadPz6b36FX/rVr/Lcyyu2t7f4zCcvsSw17x1WHJ20tCazgWrvXc5vN+xOJ0x3H2Rv"
+ "d8rO1hajoiCLE5SAqm2ZLXbY3roJXOfzv3/CsTZsD2v+vZ8ec2lHsV6s2bIdP5Bu7MdYnXgx"
+ "KFBbE+rBmP/xV/6A//mf/SHrNmN965jJZCz+wX/6IyKOU5lnqdZai85NUdwT679YEPe6dl5R"
+ "InYgets0G/lhR8cwEByk+1WHx5rMHa/Hn7fHle/m/v8b49FZ39Bnv3ZNQ9tZWVmNJXjGvQym"
+ "z6PwWYv/zHK9pnSkuziKqIUbL/BcDNdJCT8vpXULjnpqiKY3XOrS8r6Coa+Z/UVSQgRrJuNS"
+ "+P5r8tPyIRh2HbXr8viFTiA8xei6kNUYY22UurJkOBpZb0RjSLKMzOEQUinaurZgbZYFMmvs"
+ "1FM9kBvR44mxGcr2oGjbOLMA1wENpUWS0GCojX2TaKtJZZwprdZQN8j1GjE7Qd4ekAwGJPk2"
+ "P/6JKd++umQ+nxPnipdenvPqexP+g5/cYTiQfOErCzI1RyYjnriS8M6Ngm+8cBuhb/Kf/YeH"
+ "aJFy/zgD0fGn33iD/+F/+RpPfettomTCk08+ymSYcf3mgvlasFxLLu+tubT1Old25+zsTJnu"
+ "nGN3d4+96TZb4zHDPCNVCiUsY77ThkGWcrxI+KlPpUTqXd6+PuOjD0SMB0OGUWQdwasqgLpe"
+ "BllKZzSbxhwt1zz/8jVkssP9F88x3y35k2+8y8/91Ltid++cUEqKNI6FkVJoranr2twr618M"
+ "BtYrMMtCddC5+1e4bpzXnfd7KgD7YqPJFbIcD6A7ysSp/XGX9/9fd5wdsHwJ5WtmZfWm/Xyf"
+ "F66/k8Ph1RR9rV1kmR1mdl2MNM8tb0NZ+QuvUeXTXowJc1A+NfYGqv5z2gUl6YOQ6zb0SaRL"
+ "JxMSu86H6C1O08O/8E8dT3BzmaU/h+CUq62XneeY5HluSapVReQY0uVyGcQGOyktl6eqgtxz"
+ "6W4y3zXyKbh/Xf3DlwNrh7UZbaV2BsMh67rh3eUS2pYiju2TWlmFBGKvlhAjlgvUakXSNNbz"
+ "TwjG0xGffdLwa//mJoOthAsPT7jYaX79C0t+4JE5B9sFFw52kUrx1HMz3ny7ZG9ieP3mmOde"
+ "PuSHPp7zZ3+54Etfvcpv/O7LHM0jHnv4EYaDlHVpeOnNOU2nGGclD126yUMHtzm/mzGZPszu"
+ "7i7j8ZjhsCBNMhrTcbJcOhZ9C51xXSqFkoIkG/PZHxTMT4as1jWZVERCsFiuaFqbQerFGtPY"
+ "hkuKtaYaNTVrI2kZkeYr0iSiajKOjte8e+0GaZaLPE1lrJQWQgijtfFZ1Qd5/VdlSTEYULms"
+ "zQXaoElfFAV111G785KOymOMCTOFkcvg6rI8RSb1AL7RmsYpMdzV/f9vI2C1tfVji/wJLBaB"
+ "KlCWZchwItMbugSE60T4lDqN46DiqJRCudTQE0bpBSPTC1T9OSjj+TJCIO/gbXj5j9gFvDhJ"
+ "rHqAu+F8RqYcaO0zq8aP97jPdW1L47qNaVEESV3ZNMGeO3Y3QeVSWgm07ubwppSeTFeu18HH"
+ "DiECsXAwGFC50qOp64BLhXOMIlIhgmmBb1kXrlvVjUe898QTdIMhkdFO5VPZdr5UCOVMTSOF"
+ "SlLSomAoBIOmJW3hyUdG/J3DE24uG9brmsPDFZ98LOJgf5vJeMi3Xu147e0l61Lx8cdi5osx"
+ "126s+ZUvwJ996y2eeaXl7Wsr9nYu8cTjYw6P19y63XLjqCaKEx7cfYdH9t/j/K5ksn2e7e1d"
+ "JqOBBYLLNYvZCcdlSbde06zXtKsVXVli2o4kicmLgnQwQKQJTWfQ6zVquaBerzlalxwu5nQn"
+ "M5rjY7qVDdxxljO6cJ6tBx/iwLSsdw+oGsmwSFi3GUWhaSrBsy8di/Pn90XdtCJWjUDY1vy9"
+ "sP55UVCXpcXFHJ8qShJkZ+dmFw7kz4qC2r0OYDMn6YJtf2QnZJFsOpVaW6OKu73/v6eA1fkh"
+ "UcdiBTYAIi6ddFlRUDP0F8R/TxSFafXlfA5AU9cWuHVf82S2IKWqdYi8yr0ZetHbtUV9Bhg4"
+ "JcJqDbWdZep6QT8Pgvq/UzveSZFl4eL7jk7tOkWxoxD4dF261q1vHSMEMVC6oBg5jKFpmuCl"
+ "mGQZqZSn2MHLxYI0SZg73Ew4IBZ383gg07fXjTH2qeye4P0b6IH77uOhhx5mcvkSpnKdFhe0"
+ "hJRW4VPYoCXimKgokHmOTlIWbcUnn9D8439xle3dfR65coH7DiLeuBHxh08tkGgevliBTLh6"
+ "PaNaQ5Joqkrw1Zdj2q7jsUfPMczh6nsnnMwNWsPDB3Pu23qXy/st0+k+093znNvbYWsypshz"
+ "UimQXk65tkPMuq4xzpSVpnXNPmt8i5R0bUc7HNCNR9ZpuqoQ5RpWa8x6jWkqRGeQSUI83SY5"
+ "f55iOuWaVCQxdGLAdBxzNM+IYsnRcclqMRfVdi2KLBWxUkIIIdq6Nh/09feUir7Uku6s9rwn"
+ "mequo3Z0BLDgPlqHsrPP9fKvqc8Bw72eu73/v+eAJYQItHyw3JHMuSr7J00QKetlMT6t9NFa"
+ "usXP89wOTioV0t36DmxK+MDkampPlAtBzV61QHgzZjOXBZyaGvdehr5M9MzaSKlTowOV44v4"
+ "CXmMoSxLS3aT1glExXEoEWCjZ5S4p23jBl2zPCdKkhBEO/d9Qlj+iR/lCOMIsmeQaTZcFf8z"
+ "ouvCQG5fBiRRir0s40BJzj/yKOnDj4D03VIRjEu9FIwREoNN46um5dbxCY8lhh988oQ/+uaa"
+ "tKj4468vOVkseeKhjHPTiDdvJDRVSdkkTMc1qzJn3WTEWUNiSjo0r1xd0umc3fEtzg2u8ujB"
+ "ETvTMdPdBzk4d479/T2m0ynj0ZA8z0niOEwvWCkU1+F0NA0/j+ebJ1obtO4w2qrIWgEG1/V1"
+ "AznCbEZatBBoKTGR4a2Xr7OuBUmSsCozdieG+TLj2lFD1y2pqoa2a9HGCOzfFVEUmXth/ZWb"
+ "7PAVh98jQthALx2QnTgsqYLA1fKYU13XFkOTloDtH9q+LPYjPHdr/3/vAUu6MRbX4fBt7LKu"
+ "UULQdF3Qs/GyLXEvygfwrsfk9UBicNZ17VnZy5j6ZZsSgtZhCOGJ4tJtqaxwftT/G1pbCzBc"
+ "KQhWRdI9KT2O5dNd32UU0lk6OWAxdSqnGGO7iO6J5iUxtDsfT62oy5KhGxCN0zTMbUmlQjtZ"
+ "RVHoGvkAKoyxnm9K0fgnpVJWc95hH75c0FqTDQbuZ6W9GZuG5R9/ifpb3woGpkhl2e++RFTK"
+ "kinTBJHnmCyjiBSlTvjpT0/5g6/f5unnD5nuwg89kfHKe4quXSO0YlhINB03jicYWjoadzMb"
+ "DmcNcZrx6Oib3Dd5l/N7OaOtB9jd3eVgf5/dnR22tiYUaUoqJaqqEMulVdRoGmuQ2tSYusHU"
+ "NaaxJgemqqwiaNNC29ivVxXUFaaqMVUJlf2YxmZptJ01aN3bhfsuEz/+CO1Ksi5bBkXO+Qvb"
+ "zGczxltTTpY3WC1LmroWuuuEctIz3oHpA73+RbGhPkAISnVdW5zJ7RHglOtUnqY0YsN17FyW"
+ "40H8ruuCDhZChDnBu7n/v+eAVZYleVHYRXAn3Tr5YrCuOh6o9hPsuuvsMLKP0mx0omNXb3eu"
+ "do+cTrsPTt5IwpsC+DS0KstTCo4+lRVSkrqyrnKaO4lrTQuXsuMCl8/EfAno8THtblJcOekB"
+ "RT8IGysVPNOqsgRjB139hRbCSs3macpitSLrDcO2oXu1Od/IpdGNI/7FSRK6Ld7qSGtNYwx5"
+ "mlK1bXgqF1lGWVWWfd1YN2QpLKlWzBf2hoojhIqsprpSQa6YSCFaKxGjtCbNMkYqYm8y4T/5"
+ "yRO+8I1jtqYZL7yqaZAcz8c8ef+C2TpjXqZorEKoEZI46ejamP3JnEvRF7gwbdg7d4mDg4tM"
+ "xkOGg4KD/T3LrcoyYqWshHBjteG9TI3pWkzbQlMj6tpaeVW9t7LC1BWirFyAKq20jAtaoqox"
+ "tf0/WkNR2LemRSpBZzqqBvbPbTPIFSo6x2pdUTfw3lEnzl+sqJsOqbpgwPNBX//K7S2vnCCE"
+ "CFZbHoQXQrBaLsmczHWepqzKEt22DAaDMIurlKJcLq2YpVM/8eoUg+GQ2cnJXd3/33PAyrKM"
+ "rmnIBgMaR0IDWC2XJO5i9zV2QpprLBlutV5baZLYCX35ut11EUJnQDjyplIhrVUOk2ocHnXn"
+ "4dvGfjDa1+dCSpqypHY3kYpjG4QcLuAP35pGWB5IZ0zQKpJCoNwF7rSmapowrGmw0srG2Da2"
+ "kJI0TanqmpEDR2P3N0Ng9ek+NghLp3QpIOjOe9zDuI/BjmZUZblRinQCcVGWOakXjWlbTFsj"
+ "4sQRb72RqDhtNGosN4aug9qW0FmSMEgKPvPRbf702Zu8+OoRW9NzbE+WyBiO5inXjgcoKYgi"
+ "Q9sqdsYlio7ZUiLr2+xPl5y78CGuXL6Pc/v7aN2hBAyShDyOSYTDrIRBSuFkjO0coscpvaoC"
+ "vYzQqAgRdaA7TGwhArSblzOWpa3N5rUCiKJADIaYQYFOU4ysqdqIm7c1J8s1IkopVxVtnXKy"
+ "WFHXlei6DmHsL9JaYxwA/4Fd/x5zfr1cBva9v7+1KyE976l0FYjfMytHWs0c4VWnaTBnQakg"
+ "99LU9V3f/2cdZypmBbat6wb4ujlNksAIlq5eNsaEFDBJU+I0pcjzYKPtf5d/A2vbDXYos23b"
+ "YG66Xi5ZV5WVXHX6WMAGjGyakFb6WttzOjqXRQ2KgtKlyf4p4H+HH+tRSpEkCUma2u6Vb/F6"
+ "ANJ1e/yW8K1cv/h+gZaLBYvlMphflqsVx8fH1sDBZW2RUrZz1FjB/cxhOZ2xypee8OeJgF5d"
+ "NXedKhXHQdq5XC4x3SZTEa125ZPNWEzTYtrGkh9b//nOfo/LVGRVEbctuZFsFRN+9tMJwlTE"
+ "zLh5LFmXHW/dzBB0SGmzhA5JkRqqJiZSHSftOYrxfZzf3+bg3Dl2trds8K9qlNbWjLVtEW3r"
+ "3G7c5e13sE2g6IdNbTymhcN0jMEYTfii/z+eBGwQSmLiGJIEkSRopXj7RuXGtwSLaojQaxpd"
+ "kMZwNDPorqLTRvgn/D2x/k1DuVyiu458MCDwmFwm50vO/kCycsHEy0G3TUNZlizmc6IoYjIe"
+ "27lGny2pjQb93dz/Zx1nOz9HG6mMTutgBxQ5uQgPLPaDBmz4W/25LI8R1E4Dx9f43oixrb3n"
+ "nKuxtUY1G6kY32qld+NUZRmY8KazThxtZ0cCQvrtLkifw+Xft227GboUtvXqHXDbxkrA+uzO"
+ "d3T864uiiHK1YuSMCrKioHIdj7ZtGYzHNC49bpWyhLuuQ7vujLdJrxweEpQ5/fXTltUcub8r"
+ "HaNY+YzE8jVc1tS6ssO4jMMZRLhYYBAQMm73SSlRUpCnOSkxn3h8j08/8QZfe2lNFzdUbcbu"
+ "9oLGFJRtagHluOPaccHB+Jiq1CyE4Km3H+H7P1wSxylZmln1y7q2+FJa21IU6c4DF3DcJQ/q"
+ "VYTP2c/7SyFOf65vjooItl52PCdGZinkGeQ5lRa8+MZtyjZnNxbOvCEhSzXlKmGxXtI1JXVd"
+ "h3Z7nCQhCH1Q1z+QQYWwYzhZZoFxhxX5zqI/10gpNFa7S0lJ7UwfVus1aRwzm80wWjMYDoOB"
+ "i9ePN27/3K39f9ZxtkSylGgpGY1GoQZWDvFX0UY9QTnAWvrtYE63TZUboOxcJBVRRCSsCH4Y"
+ "omxbG4CiiMSlov0g48mjob3qQDzPShZSkiQJqWsUtHUdDFfv7KScUoT0Tx+lwjCpBHSWYYyh"
+ "lhtHaY99Ga2tKUYcs3LGkh58lVFEmmWhc+nnw6I0tU8mVwr4Gcn+hvByJrBhHtetlfhYLhZB"
+ "sSJ2Wkrozg55OwwOlDMO3exy09pIEazdBdDUtqMoFUoqRlFMo3J+6lM7/PGzSzK1QJiIIpao"
+ "WPPeTJEmgkHWEcmGo1lOKlrKOuOl2wXPv1Hz4JWSVltJn05KG0TbxhpASNc+d3+eEEg3nzuV"
+ "dfnzNBuvweAejTmVgSGwzYUshTyHwQCKHFLFXzx7xM4kRkWC/VHN8bJgXCy5dTvjeKHouppO"
+ "G4QUIlJKJA5a+ECvf7PxMvBcrOPjY/I0JclzC4Goja0dLoPzJZfPhgxspkLc96/Wa2onC11k"
+ "mbUzu4v7/6zjzIC1WizIh0OqtrV1uruQifMHVK4DInolV9t1SJcpJXlOW1XhqZLmOWme2+6d"
+ "I73125naWAG1Pj+kaq2wnyeAGuxQthIi2HWtnQtK4gB7Iza8ED+Q6f9W21hfOeO6K/7veMKg"
+ "X1QVRcGbTydJkPj13Rnf7fCYgcfH6vU6tKExJoCVHpPzr9N3W8Jr950U9/9gQuADt7+R3XvP"
+ "N6N1paGw5qZh33scy9jMxIh+lmIDPMpiColSDJOUhy5u83M/suDffOMGgyTi5Xf2uHyg2R2t"
+ "2Js0VF3C4SxhXStm7YDt0RHbWccffEPw8ceOeSjfsuTJOLZyIk0HonO4lfDMBRtkTNAGDefk"
+ "jxCPPP7W/3zvP8aCQnbwOc8RoxGMRjAa8Mp7DddvrihG+5ysByzbjHHRcrLMgTVKNKzLRmjd"
+ "CaPt2pZlKYzW5l5Y//6MbeoAbm9lp6S1IWuahixJEFJSrlaAVURtO+st6NUctNYhQTDGdjTn"
+ "jhJ0N/f/Wcf7wrD8RWgdkzbxwmZgRfTEZmwmpIKuru5nSZ0D3bp+QHJtVOFap4PhECWtyJnX"
+ "a/csXOkWUPnUWVjZDN11JHHMwImBrcsygPH9NL4vauado6W0lkVlXVvRPyEC/QGXNs/nc2az"
+ "mR2vkDIMtfobIHFibp44GCWJZfC6IBgra0vWak3VttQOp/DaX34+zTuSKMfriZLE6iFhQd5i"
+ "MAhZoQ+sFsdqra55a0tD09rum2g7i2e5r9O2DvPS9v+OVkBVEbUtOZJhNuLHP7nF9lBQlzOG"
+ "yZKThWGUrjiax7x6bcjtZYySkCeG6VgjoiFXbwl+7yszVqtjtCEAt3TuHJomkERx5aJuGgue"
+ "u6hkeinWncmWCWmZ/6rLrKIIkeUwHCImW4jplGa8Rb63xRe/fhUVpzQmp9EpnYk4XOR0nWSY"
+ "1czXkrbt0J2mbVsROsX3yPr7vVa5bMcfscOX2tYSpys3a+mzHOVw3uFwGGg82uFTSZaFDnug"
+ "INzF/X/W8X6cdVitViwXC44ODxmNRoAV9vPpnNeTilwtqs1GoH7tB46lpOyB58vlkrqqNoC4"
+ "i7h98T4vHzudTqmbJvx87WeXeqVcYKsDuUvl/eGZy967zT/xjEvfoygijeMQwDxz2NfeWVFY"
+ "eQwpabqOVVmGdF93HdVqFTI36W6cNM/DojSdlY/t3Gv0zGmtNbP5nMY9gTyW1rVt0PHGYR1C"
+ "SpbLZSAyhmFw7agBXWuDlcezWidFGz7XoxGEANe6oFUhm5rEdGQy4sL+Lp/74YSTWckoOUbq"
+ "incPFa+/l6M7p3Ipoe5SyjZhsY547KFt3r4lee2tW7RtY01UhcAYbf9+0+NR1Z5P5ZjtHnfz"
+ "DSPwTNJTGVXA5DAYYTErkWeI0cgGq90d2N0jPrfLrVbw1WevcbScEMcRRRoKTwZZRdsZlGhp"
+ "O/tL3bypuCfWvwf2CyGCoornSLVtz1DVlWp9oLvpnMW8g1+UlIG2sV6tQgfPf//d3P9nHe8L"
+ "w0IIsjSl05qbh4dB+tTzQsCmqbWr1/2TZVWWjIZDK3TvTsaXe34Y2bvHyijacLBS63nWdtas"
+ "MXFBJVIqqBnWbYtyT0P/Qr2yoT98TZ044FRrHTSno9g6zvoMSykVwHaf7gcbbxfItNa0Tqfa"
+ "Bw1fdvrF9d0lhG3fex5KCMb+JnMEwt3dXWYnJ0ghSJ1Tr+jX9qJfD20s0AN47TMmlx0EsFoI"
+ "rByrwqI+7l9jN71RvkITCCURZYVKUnIVszQpn/34Dl9//i1euramizRxC9PxkpaMdZ2ilCSS"
+ "LS0TfuJTCZKYL35lxf/xuyf8lz8/oDEDe54Ga1Huszt7cq4/4EpCj1WxaQKeArRM783elIg0"
+ "BhI77J1nsLUF+/vICweMruzyD3/5Gf7yJTg4yEgTA9IwLw1dp4llxWItGKY1sRoZaxgkNpQa"
+ "FwA+sOvvmk8ed3InsBnr6T2s57MZsWOwG9jwD4VgPB5TtS3lakVVVeRsnHR8Ceex37u1/886"
+ "zp4l7LqA8/hSzE9gqzjm1uEheZ6TZplNNd1C+lksL0TvxzE8fyVOU/tUq+ugpIhbWONulKjH"
+ "Cdnb2eHW4aH1gmsam0VpHcA6z6mKHKCZuCec56n4i+EX0xsAAIG5XLoyMomiwEj2N2MwgXRj"
+ "Dv3ux52tWv93POaGf8L1Oi79mcjCsaPrqrKYhTF2Ot8tqj/6uJ5x+EigNrSd3fzGgDIhCPQx"
+ "Lf+xPTMHcBrsvKGyTPhIKYZxQpuN+Zkf2eYXfrVia3uGNILtoqQ2ms4oYgWpWvFjPzTmuVcE"
+ "335pxaIa0QrNl5+6xd/9RErZJQwjY6+X1puSlDuwKHonCKfrQQ9mCSxtIYkRsVMUiBNEmsJw"
+ "gJ5OYf8cowfP84//1Uv8yv/zBgfndtge1szqgkWZcm5rybrsuHYY8cDONR65VCPiAWkaGcBU"
+ "Vn3UPgg/6OvvPhekYHygcRwo474vjuOgg+X3Xtd1dEIEt5o0y1CuxNRtG/wZvaPQ3dz/Zx1n"
+ "0xrURsEgdgCbMsaChXWNdDiSDx5pmhIVRViYxlEMoiiyL8jFjgAAIABJREFUYJxwUsdRZNUZ"
+ "XV0uhAjkOD+47Dt4jbvJhZRBCN/X0F4uWCqFqGs7QV5VyKqicdlS5FLwrttYFwkhyAcD5vM5"
+ "eZZtiIDu9/mU/866Ovwt9/o8SOnf/FPOfrPsbUK7CYxrBde1tTUvioI8TQMT2WeJ4Rx67N+Q"
+ "+kNQs/BdQktrAIPafJ3T3Tf/segvvcBiSlIhojUqjsiEYCBjnnxwix/7+Lt885WbxGnM829O"
+ "eeBCy954ycVdw9Wbkt//8zWTYczF82MeOIh46ls1X/rLYz76yJxsO6M2ELtztoKCLeg7U39/"
+ "xv1Pmc1XpLe8l8g0C7LMZCkUA8x4TH5hn2465r/935/llz7/ElcujkBFHK8KlDLsj2ecLBSx"
+ "rNnN3uETD7zD/s4FUxQDnaWpkVIaYw0/jAfTP6jrL6W0jST3f7DBSff4W31eWesgEQ+DeEWI"
+ "xo3rGClZOg6Yx87auqZcr4N4wN3a/2cd78v5uW/4OJvPiePYjgy4TMeTzeq6DguTRhHFcBgu"
+ "aO3qV+lOvn+hgaALLaU8pa/ugbzC6fw0VWWF07QO1kG+c9N2HcpYy+skTUkdaFp5xq7WdK6D"
+ "UlcVSZJQFIWdl4oiIjfqEEUR2s1j+fkvv9idG5JWLs32T99OW50kZTb8F7Q+ler6JyoudfYY"
+ "XOeaAHmaWo9FB6hng0HgpvSf3qHscCWCxamcDngonQTgraF8p3BzCDccDQKhDcjK+vdFEZFU"
+ "ZGnCKBnwM58e8MzLJ+jqhMlgwJVL25zfVXz1eU2UjDg4UDx4QfDSay3ffr1Ba8NTrxR89blD"
+ "/t1PD1l3MalyBEQDQjuwX5s7XJp75+fKRoTARApEYln8UlpOV2wdaUxRMNjfJtrf4uVbNf/F"
+ "f/Nl/uhr13jg8h7T7RFHi5y2hTRuqGuBbtZc3Hqexy7cZu/cZXNw4ZLZ29k2o9FIp2lq0Nqo"
+ "SBGpD/b6Cxew/PkFsmv/6w4u8TOPwgc4F7iUEGilKJuGLI5tRVJVrMvSTntACFZ3c/+fdbwv"
+ "52fYqCBGruMhpCSNY9YuZVRxjKnrMGulJpNA2gRIkoTMtYY7t+FihxvV3UaHxxinJOpSaOOI"
+ "dgBZkhBFEbOTk8D70I5tq6KIzOkQ+fLQGEOeZVazxz31lJQuqbAXN3IaPf4JWa5WpE5RoHak"
+ "uL6kch8v83wY5QNH/6bplQD+d3ujAvzXtGY2m7G1tQXSaitFrpXedJ01zIyi0BH1N5turc69"
+ "7rrNqI0vCVUvM2HzsT3MHeWhjWImUoimsVmWKlEqIlWSXEU8eGGHn/iBFb/79YqPPbpCMuT3"
+ "vtIw2Zrwo58c8/Rzt3jltTnXbymOTobsD0sun6/5vb9Y8pFHjonP5eQysWUWJgDwtB3eotls"
+ "TtgeUtjh7cSJEgrsJo9jyDJMmtFlGVsXdri+avn8b73EL/7zF+i05KOP71EMt/nO2xEHW0uU"
+ "TCgrwSi6yUfue53zu4rdc4+aSxcvmP39vW57e9pFSmlhjNbGmHK5Mh/09fdNKeErD3c+p77e"
+ "trTu87ETC9RdF8oyT5SNhKBsmqDllbvmgm43BjB3c/+fdbwveRlvg7WuKvI0pes61k4fp3Aa"
+ "P57xGjsyWdM01HrjQBtJK1urhB2O9Axfz/6N45jYBay165ogRNC1ns/noUOxM50ym82smJrD"
+ "Cqr1GtzTLnYdRN/p8KWmF13zIwC115N2qbWKIlIIg6F+zMBjDr6741OCrrMStP539EsDIaz8"
+ "SX8kCNjIgWC5OEWec3x8zKAoKPLcjml0nR2GdfLOfSa+kHa8QrWtpQNo3QPdNyVhWD8HuNt/"
+ "IozwPswbHGRTYtYYZYenVRKTRRGRyPncp6dcPTzk+ZdOaFXKdDphOT/huRcW5JHmeD7giQda"
+ "nn4pomwL9qcLnv7ONv/XF+b8539/yKyZEBlDYox1gWkdoVS7gOrBdyksoI6CWCKSHIQr/9LE"
+ "8qyKgnR7RDwu+I0/eI5f/LXnePbFYx69MkamO4g458ZRzSitma8TMnnMY7tvcnG6ZH93n53d"
+ "A3Ph4nmzvbXVjUYjnWeZTuJYqygyxhiTpukHfv0FoLqNuoHnbhntTFP1xo/Qd8bvLF0xdtav"
+ "cY2QyL3uyrHgPdTiu4B3a/+fdZxtQuFS4yhJiFzrVbvugH9qtA40MxCkYBJXzwN2ENnYQVEP"
+ "agOcHB+HIOTdSnwKnqSptZn3AGCe2/NxUXswHJJ0XXDcbTyrvW3DoKXuOuqmsd5qvQ6ir6vr"
+ "tiVydfyqLGmc9LCnTniAX/SCn+4sZiQdR6yPY3hft8BDURv9b7A1vd8EcZIQxTEn7gnbNg03"
+ "Dw8p8pyBwwA8d8dnnf5n/YaRSmI6RxvQHXQuFAlbDvbDkce0wONbtnsoXOkopLBBpJZQVkg3"
+ "pjJMU7rJNj/w2JwvPdPw4JWa7UHJYql5+e0xP/KxlNoobh3X7E00N2/nvHO8S5TO+OoLK77x"
+ "wk0++5GcVYstl5xwn6kbSzZ05xiAf2GDFh5QzzJIM3SeMdjdQhQpz7x6nf/6v/p9/vyZ94jj"
+ "hE9+7CG0abh1Irh13LA1bDFG8+DOy1yazjnYK9jZfpTdPGV6bt9Mzx20gyzVKoq0EEJnSWLW"
+ "VWXulfUXgPF4r9sfntvUVz3wEk2+M+lpGL7zV7m95oNd5/5O5MjYlZNyvpv7/8x4dNY3+FZv"
+ "uVqROiKbFILavUdsHC8KV8+mDtTz9bUPel6KuHUSE7u7u2htB0cTt4Cdxwo6a5Lq6/7w1Os9"
+ "nXx7N3G8qsVyGYA7f5PlbhA0imOWqxWxUtapRCkGaUpVltaaPE1Di7Z2Ed/fbF6HSCoVps19"
+ "YMUttncR8cCkEJaFHrkmgpTSmiv42SvXSZlub7N0fm+j8Zi2qlgsFqR5TiRl6FhpCMQ9n2W1"
+ "db0ZzWl9903aiOQ1DwEhekB86L6b3ueM5ziAqJ1jckSUpuRJSh0P+OSH9/l7b17n6Zeu8fqy"
+ "4+NPbNNFY64fVhTxguMOlnVKoxWGlofvyyiyA559/ZAHLx5x/2hCgnWJlsYg2g7d2mthZa+t"
+ "Hj1JYmcBiwGmGNBlGXI0ZLg34Y3rx/xPv/wVPv87z7FqMh64/xIPXhrx0lsN85UijQ1F2rJb"
+ "3OTRc9fY30nY3brE3nDMbixRszmD/X29vbfbyqYxcRzrpmlMq7XJ09TcK+svIyuf7K22gI1o"
+ "nguOYbg/3mhygZNxdnvSkz2llEGZFCFCEhC7fXI39//3HLDK5TIMhPoXGVqQrvujtSaJNg6z"
+ "Ko5ZzedkDiT3AaQPtLV1TWMMSZoyGA6t0aPvZrg6f7VYMByNrMRG01A5EfwkTa3YfpZRRxHz"
+ "2YxiMGA4HFpNrLYNEsja1coAuQPp67pGaE3rh0CXS6I4DjIdoW53C96/KTtth41DG7nbWEDh"
+ "rkXn/qaf1JdaB+zs1OFurjDY3XWhBK7Wa9o4JnY3a+LKkRr7xJJxTJSkVJ1GdE52xcFCKJ9d"
+ "bWgCxvRKPwDU6dk90SsUHZZFkhCnGYPBgHY84bMfO+Zbry25eGDIcoVub/D6dYGWOUeLgrrW"
+ "JBFc2B/w4Ycirl074Q++CrvD2+x+JidRlk8XUn9tLB9MSkySILJsMws4GiFGQ8Z7W8ybll/6"
+ "/Ff5lf/7aV58o+KhBy7x+ME269Lw1HfWKKmJpGRveIsru4dc3m3ZmuyzN95iL47Z7loGt2fM"
+ "rl1DXbyoI2O6tusom0YbMOt7bP39PkmL4hRdp0++9PstWNM73MmrioaGQdNglMJIeWp/+p9r"
+ "6vqu7v+zjjMDVmD9epDX/eHIXxBHYKvb1ioPio19j9E6RM1TSgvaysLqrrM4kuOC9JUT1ssl"
+ "aZaxmM9txyJJSJPELlpVBR5LnKbsTKdh4j11YxKep+Wdaz1r3ncTB0URsrbG3YB9kNAAjdYb"
+ "lchoo+HdeKY9GzUL5X53J8Qpz7qu6+zkuyt/lHtSG1ff+/LXs37jXlANXao4RkAgKyZZZtP4"
+ "tsEYDbqFTm1OnH425fQQIjCd/X/4OgIROomudDEKIWqrTbWKkak1TU2TlEfu3+FzP1zzh08v"
+ "uHUMWo5Q8YBZlSHQ/NCTiscfSHjh9ZoX3pBcf+c9Lp/Peerlho8/eky6t0eapqg0RVU1GG3x"
+ "qTyHokAMB+h8QLQ9Id/bZmHg17/4PP/080/z7ItHpMWEv/PpR1iXLTcOS24caYYFnBve5sH9"
+ "99jbEuxPh2wPdjiXp0yNYbJcUMzmiKMjjt+5SvPgg7pcrbo8SYRRytyT6+/A679pg/erkTAu"
+ "AwHE9ziXp0Y0rtRryjIQqft77W7t/7OOMwNW7PCfTmuradQDGFvfdXCBQUURdVkG2dTgoeYA"
+ "TL+QQYJCWL5LnCR2yHowsJ0H5+PWVFUwkdSdNY5IsBiUnzxfLRasjGFra4tOWinYrCjshdbW"
+ "yqsPhBpjiNzF8gvru4pl09inojs3f2N5DWqv5tA41rzHFnDnpFx67Al5xhha1yLG38i+JvNP"
+ "uNa64uo4tpmfu0F9MPWKqEtHwIuUIs0ykiSxT/9OWxyr7Xrguqvw2g3nytAFBYcwaGzsx2Kz"
+ "v9znassqkBKR2PS9iBRFOuRjDw/40tevs6gFrRpSdS0X9xd86mMDplsRoOjaOccLwZMf2ue9"
+ "6+/w1AsD/vWfl1z42RKpMsvT8dlLliFGQ8xwSJ0P2L6wQ6UU/9/XXue//+Wv89Zb7xBlUy5f"
+ "eZgr5zNu3Drm6u2UpjZc3FnxwO51ruyX7GxtMR1OmKYZu6ZjvFwyXCxIj49Rx7dpjm7TvHed"
+ "bjYzbv2N6IHR99L6Z0VhG0lJEigQAfvzQcG9Lo+99buUAXh3wcO4ElX5TNc93P3evJv7/6zj"
+ "7AyrTwdw3QOfLnZdR+pUDzOXLnpzxbKy7rbebcMLkOE7Ff5FKmWVDYuCqiypwArvuVrfj9QY"
+ "LAgZJUmYTO9c2RcpxeHt20zGY/I0ZenmoYQQpMnG1t3fYMqdn/96FMc0dW0VFV1bVxongxtF"
+ "YcC6a1viLAs4WdO2bq5OBjVKrTWtKwGC0au7kftjP31eTeOeXN4Kqu8AVLqU2muMe+qFlSFh"
+ "0yXUncXZ+8EnwhLae1kX9AiloV+4eY8A2YIRNZQSsVwiXGlSJClXLm7zqY/O+dXfa0nyJZ/4"
+ "voS6WfPm9TFVNePFNzWXzsX8nU/kvPmO4aQ+4LGHl7w7O+HpV475zON7LMkYju0JqWGBGU9I"
+ "d7bIhgV//M3X+T9/5zv86y9+mzgZ88DDj7sbX/Hym8ecrFOKpOT77r/Bo+dPmG6NmE7uZ68o"
+ "2AEmVcngZE52ckx0coy6fQzzOfXshOb4mLixw8alGxi+V9e/jSKLc8Vx0GKHDTUgdCeN2Yxx"
+ "sWkA4M9DbqRmJBtqUddYpQZ5l/f/WceZActf9DAU6qfAXYnWOdq956p40LE/Y+UxKd9+FWBd"
+ "PVzbNHbT7dIBlJ7CECkVOFLr1Qqh1Ebky/0+31FZr9fcPj5ma2uLLMtYLZfEWUZbVfbGEiKY"
+ "UeSDgcUsksTiV+4pUbdtYOPK3gJFSWJr9a4L+tNCCNuihyDNDBuCHBBYykrY2a1OiNPll/ue"
+ "ptcZrbF0C+maDf4m9efnX4d9YrpRF925krAnL+MahcZzMFu4E9MK5aJwbPjWfca/GFFjVmuE"
+ "siXRYCSpVcqP/8A2f/7sNaIsI0slaQLPv7omftjwuc9MuXar4yvP1CgZ8fhDBbKreOYF+PU/"
+ "FFzen/HA7jbDrW3SNMWkBdFkwHNvHPK//cs/5rf+8CoRFQ9eucTe/jnevVkSseLt64JVU/Dh"
+ "S1d5eP+Ig92ErfEl9odjduOIadsyWC3Jjo+JDw9Rx8cwm8F8jlmXUK4xTYPuWtutMoZsOLwn"
+ "19//fKc1qStV26bZYGR+zzngHTYzhJtvcbm3e+3GmNAlxGzkju/2/j/rOJsL37u4teNNdFqT"
+ "iI1NUOzFxByDt6kqy8foOpIkCWmwj/j+ovoUe7lYhMgbOwmMwPlQisgFqthNmEspretKZ3V3"
+ "PBkvjawCZJymjEYjDo+OrBpjbHW5E2k5WNV6Td22rMuSPMtAiCDyD7bFKt35rlYriqKwAc7Z"
+ "G+HATCklVdMgmo3qYuxmplRsFU+bsrRP2Ciy/CM4NfsVuQ6UX0ipVJgn8+fi2+O4j4W7ySpH"
+ "iA1qDOBZVxtlg8hACyYCuh4vK7AjVKCTCmV1qTzKZWoQotww4FXEoMiZDob8/c+N+eI3a159"
+ "/RZb2xM++5GG1mT80VM1b17r+MiHcsYDQSI0f/aNmNF4C91V/JPfvs3PfOaEhy5FRBLm5ZLf"
+ "/tJT/OlT15Fmxfm9Ibt7DwOaN9++zqwcYEzGfdMjnrjwHnvThO2tA6aDLc5lMVNjGFUl+XxO"
+ "fHyCun2EuH0bZnPEaoWprDGrx3DAGpOWVUWl9T25/p59vpzPkePxKRD8zn3bJ74KtTF58ZlV"
+ "3WwUfX1W2LatLd965eXd2v9nHe9r+NmT1aS7wP6Pe3ut1XrNYDAgUoqybW3k1Rvd9P5IgOd8"
+ "eAa71laa1WsDCSFCZ8EvrhKWkZ74FNNhC/1WrlcfBWwHQikmkwknsxmpS5u92J8xhixJTn0/"
+ "YFU86/pU+qykZOV0j7YmE/s7jKF055p5wf62tWNB7kb0AbV1Tyx/LQEibRUXwCoxZklC4/A2"
+ "IdykvmuBx66D1LnfU7dtGJVI4pja2C6h0V0vVG06gnaXdojQOOxRyj2Tgf69LjDCBz9h5wyV"
+ "FchTaUIaKYZpwmOXx3z5mevU64YHntxGCvjmizXFIOHn//1dvvLMkm+/VvPeTc3f+8yUG4cr"
+ "3nrrFjfnUz7/RxWz2dvsjGrKqub4pCTJd9kedWwP4aW31whTUrYDtvITnrj4Hg8ctAxG59jb"
+ "2mY3S5kimNQ1g7IkWcxRt2+jjk8wsxOYz6FcQ9vacSBs8DZm0/7PosiqlN6D69950qZzTvbB"
+ "MkxCuI5j13VWrM8PNncdVdMQax2cpGVvP3ssSghr7JqkKYvZ7K7u/7OOMwNWmudBtrhuW5S7"
+ "sFme09Q1ZV3baOoGIJMso1qv7XwftjWcio3xo++6eECQ1qp8+tTRk0Q9e9YYQ7lckua5JaTl"
+ "OWkUsVwuw3yTn3L3voV1WYK7iFtbWyxmM/v0aK2vnJQyyHjUjhsSRRGr5dJ2Il36XDuMIs8y"
+ "ajcM6s/b1/r+iKMotHxDd0aI4NlW1/UpX0RPVl0sFiR5TrVahZ+TSpFnGYvaWlcFfXtheT6R"
+ "u1Zd27qZsm7TJRQ+ixJ/RRsdTCQQ3UYqOcgPCxu9/M/0J2WoG1iXiNRapmcqYrso+JEPD6ia"
+ "klffOObtQ81HHp/yfY8ofv33jjiaC4pM8HM/sc+168dcvVby0EPnefOdJSdHN/noE7u8816N"
+ "Mku2pttsjRXXbrTcODwmjgXrSvHh86/y4PmS/b1tJuNzHIwKplIyrmuK5ZJsuSBerpDLJWI2"
+ "w8xmiNXaGm147MburtA1VUrae9rZrd+L6x/3Am2nrZlp67K8JMsCTcLAqQd853hhwnXyuq6z"
+ "Wu8u0wmZn7S8Kt22d33/n3WcXRL26tEsscaSRZ6zXi5RSjFwL6hx0Rwh7BPJGIqiCM7LnngX"
+ "uXnA1g2Rap/munTSc0k8ftA1DflwaPkmrjw8Oj5murXFcrkEaVVIA33BAXhNVbF0gW4ymdjp"
+ "cpfK13VN2uOIpI61W7ha2ge/1NXmQHjvVVA7x3j27Vvf0bkT1PTzZk3bkrjSwj9pPZGuWyzC"
+ "oCrCKqFWTROegsp1lwQbCWncExRtu4SBe2WZCe7DO7KtwMVSoTyy3+sE9FQfne+l57XY0Bzi"
+ "hDSKieOUT3xowjOvVDz9zTX/zqemRKnmT772HoNsxI//8DnyeMWrb97mK89pPv2RC9w6XvPa"
+ "1YZL+1OSpAGpGY8LBpnitTcPOZwpJqlhb3CDJz90yM50zM72BfaGE/ZixbhrGc7npPMF0WJO"
+ "tFgg1mtMaQUB6eku0Q/Xmy6DLYOcbbyXjLnX1t8ri/hRmL7PQbVeBy6UPxfP7/J0Cd/di+ON"
+ "c3RfV95nRJ7Jfzf3/1nH2aM5ccwwiljM55YNawzr9To8OTxYJpViPpuROoBSRZHt1glBEkWB"
+ "NetdPeD0sGMguPU6KEFudrUKC1K3LTvb2yxXK6I0JZKSk9nMpqtJYv3jPG8GS3zDDV4ClK7F"
+ "6stPf5F16yy/HA8GJ1Xjb4wgY9ubK4vdXFXQRfJApwu4UWxVTOuyDM4qWmvbWXFC/4vFwmJ0"
+ "TYMSFg33zsFeAsS30HHgrbcji6OIWmuE7jAuw+p50Hx3hqU2JaAxnKYz0DlKg3CAvUXhjREI"
+ "02JkZeWI4wQZxwwjRS0LfvT7c24sNMv5bb75TMv+uW0un5McH99mhubG7RaIWawMlw4yFqsx"
+ "tw+Pqao1Fw5GvPPujLKsmC9rHtm9zn07t7lvP2Jrcpm9yYTdNGXatYzmK7L5nGh2YgPVYgll"
+ "aQ1Y2w5jNMJoN5a0ef2hM2pZHBsCZF0jouieXH9PZvX7KVAUXDDrj+gIIajrmspNeZwqMdl0"
+ "/0T/vSsBzd/G/j/jeF/Dz13XMRqPA5mzruvwNGi1psgy5vM5k8mExXzOcDRi4cYNlBBWcN8F"
+ "CB+QtNZ0jnOCMYEI6kcWPLHO4wtRmloxe605OTkJ7Nv1asXW1hZaa27dusWwKOwTj40Vfde2"
+ "xG5mKQSuug5+aa2Tlenc06PTOmBcret8JEkSPOQ6rYndAjdS0ti75VSZ4GVmkygiGQ7tzW4M"
+ "VVWxXi6DHXrmgqx/D7arVK7XFIOBtVPqrAVS07Z0wg7VCixugnYifmoD3G5oCr11/K4P7BF+"
+ "phflLOCMnTcUAiMM1ICqEPEKmcREacJgUHD/uTGFeo8X31L82A9uc1xFvPDKMZcPJHmW0nVw"
+ "sJtT5JJbtyuOj1eMxzlxqnj97QU3b83Zzd7hh6+8xaX9mPFkn93xNvtpyrYxjBZzivmcZDZD"
+ "nZwgFkvEemVdoTunotAv/zCnAxXYrqqLw0pFthxzD7Z7cf29KmjVNEFs0ttwJc78ws8Y+mwK"
+ "s/FT7LTVcc+z7LswppAsuDd5l/f/Wcf7YrpHURRam+DccN0Fil3nYZDnVOs1QzcPVRSF5a8Y"
+ "69DbF6fvKzXinhw+hQ0loYvanplbuhQ0imPKqiIWgtnxMcPRiHK9ZlAU7O7u0mlNuVpZh163"
+ "aDKKWK3XFG6AGjbpbaQUpkeuA6sB75VLO1d69blgRlhmcNu2YQjUQLC4B0KZcOPwMNzwUm18"
+ "3Jq2hcjKPo/HY05OTkIwXa7XjNyYUeTmrqIoQrq5R+Vek/TX0ji1hh7hqp9p9aB1+7/oNChv"
+ "OtddjMwG3+KOFMxgAfiyhDRF1TVpnjNMC77/sYyjKuL27RlPv6r5/g/vU67X3Lq2ZjDZ4Yce"
+ "y3nxlWMOb93k3KRiPB7w9Hdq7t96m8sXXmQ6bNnf2WNnPGUvT5kazXgxp5gvSGYzopMTxNzi"
+ "U6IqrdyyNo6IuXl1m1M1pz4S4ZpsjjTLMELck+sf+QDj9mfgYLlg0C9LfQLgYZPOdfp80AtU"
+ "B2NOUyB6VIa7uf/POt4XDytLEpZucrtcreykeY8Ri7twfiDZp69KqdDi9JHUXxgVx6FsC3pD"
+ "PgK7C+g5IQirDooQLFzauVqtyNKUcrWyNtoBu7DdnNV6fUrUXkgrZyEdcAk2Q1ksFrZV6/gg"
+ "vvNRl2XQefcL6gdc+1ydum2DxI3uXXDdWXfqIk2tjrUnDgpBXhSUVRXa39oY0jg+9dQNrjjG"
+ "hKe5yHNws5Kmdf512rWftd7UevjykJAxWW6DAaEsmdSvvNgEL/vjjsDlvii8lLIytuxsO0Tb"
+ "ITqNAoZFyqWDEe/+/hHDIuVznxljpODFWcql+0a89EbN4eFVlquWv/vxjC8/k1AuXuFDW6+z"
+ "m73D7nSHva0d9vOCXQzj5ZJisSCdzYhOZsj5DLFcWC5V09hskk2gsqnTJhoFKzNX3vpMwUc0"
+ "bTY4yb26/l522ZjNYHZoQDkVUG+26s1efcCpmoY0ju28nysT+3skaMK7/ec7oXdt/59xnE1r"
+ "aFuWrruWRhGtGxJdzGZBHXSxWFiziCShyDJuLBbkECRh2ralriowhtQZPfq0NUrTTfvTpdG4"
+ "KOy7ekFCo2kYjkb2RshzKjfCM3fUhfF4bOcRtVNwkNKmr3UdjFm1tIxkL+rnp/LbO9jCbdva"
+ "lNt3MxzO0QjbNo7S1FqCu8DR+bZs76I3XYd0dAr/BNWAKEtyLzbozrWGQNYzxgSjzJULUHGa"
+ "ntJnAmcQYtzN62SHrVOvDnZIBhfD3Eb2wcq0IBwTftNNs5vcl4T2Ux74ctiGGwkRaYrKMtIi"
+ "o24laSLY2hry/CsLHrws+fijKbdnNZG+yZULkrZTPPfiMY8Mv8kkuspkoNjdeoCDPGNXSbbL"
+ "NYPFgvRkRjzzgWqJWK2grp3N/abbZzub9BoJftf513say/LJosdvVosFIoruyfX3ILgfTzuV"
+ "UfmyzmUv3u7OBzCtNauyJNM6NBX6A9x9+SKjrQHs3dz/Zx3vS16ma6yvWeeeCMHYoW1ZLpcU"
+ "ec5qvSYfDDg5OWE4GLAuS0RZbqKttCx2P+Lg26it65T0sasAdLoL6tPF4HYMpybq09gK7S8W"
+ "CwaDQXCzTZUiT1PW2JnDNMsQQlC5Vq92iyKkJMtz+1SVTvlRKdA6zC8G77Qosq7GLq33Drta"
+ "u5kzB+qKOCZ2C+7b254tLYSgKsvgZtJpTZrnrBYLjLRtd2/BlKcpjRuMTbLMAsbuqe7uKpt1"
+ "SINx7B6LSTn0RjhMy7PeERvdrM6WiZYF7z7uWhsIXKmIB2HjGLIcMRoitiawvYUZDGmV4OkX"
+ "F0Rxyp987QaPPDAmT4Z85akjVuuax64ojo5r6uNvsRs9x8Vtyc5kj/1izJ4wbFcVo3JNPl8Q"
+ "z05QszliPof1ylrdeyZ/qO3EpuQLAvW+iPUlhn9q/HETAAAgAElEQVQ97tt634Fbf6WsQsG9"
+ "uP6mV77BxjH6Tg5XAN+jyHYkgSLPKcuSsq4ZDofguoC1C7yRcjZ4UoYmxd3c/99zwPJ8CeP4"
+ "F0Agp3XaynoslktbwzqW+Xw+D26zUkpwnQ6f9SjX1sRdENhYcnnKvq/N++3OznVnjLHOHcJh"
+ "C15GJlLK8rNiqxtdNg2pW3RvBlmXJdoY8qKwN5prT+uus1SHsqQYDlnN58FaDAiMZ9+FqV3K"
+ "XnfWxFUphXQgZrlehye37GEKUkpSl/X5VvpisWA8mZDFMZ1z+qndnFtfoE0qFUh32m0Euz7a"
+ "Ba2esYMAo52VlraBywLxrmwUTs9ddJt93XW9ja4tbC8lQthgJYocRkPE1jZMd2jHE7YvTPjN"
+ "L77Er/3OOzx0eUwcbdN0EX/5rWso0VHWBcc3XiMqX+DxvRnT7QP2xlvsK8m0qRnPF+SzGcls"
+ "jlrMkfM5YrmEsoKmsU47/nX2Y9MdHYV+yWevyZ03MS5rsJ59dV2TxnFQDLjn1t/d9z4ba5zs"
+ "Ur+7/td14BrHB0udhpyQ0noguPPUWoeA7YPj3dz/Zx3vO8PyEi3+aVSu16H2D+qD2jramMGA"
+ "uqpo6toqh7rg4uty5S5Gn7fST2v7Eq/9ye7+4RcR2KS7btN6c0aplJ2il5LYSdXkWYZuGtar"
+ "Vci40jynXK3CPd+UJZkLaP4JAlC5etyXZb4u9zNYPqVO3Ll5YqoPkh73iNzTpC5LxpMJbVWx"
+ "cuWELweAwAkCm1FKx6eJkoTWMam1dgxloTdlH7hSyYSa0KI5/ia2AL3HCgP/CoNQxr23CqCk"
+ "KWIwQIzHyJ0d2t0dsnO7DM9N+F//5fP8wj/6Gp/5xC5H85huVfPK67e5/9KI3eGSovpzzseH"
+ "nL80YWfyGOeymB3dMZkvKU6OSRw7Xc4XsFqiy/WGS7WpScEzXO9se5q/4r37WsgmXT7WaY1m"
+ "w0RfrdfBJOFeXH/jzFhSd25+f/gSL0g5O8A7ctmkf9j1wXr/8/7NuK83VXXK1fpu7f+/6Tgb"
+ "dHcL4/kmopfCtm1LtVjQOmDes4VVHFMMh9RlaXEmV+93nZWI6YyxhqbGBBfmOwE3IeyG8eVh"
+ "f0Ewp+UxkHJjne0unmfeek5LnqYwHHL79m3Go1GYigf71ImSZMNhiTZSsoPBwNbeTourqioi"
+ "Y1vYbV1bImBr7ZWU78Y4ENaDov3XtK4qlJQM05TM3QyeZ9NnAgtXGqyd0mPArtyQq9MqEjer"
+ "mlQIchW5tFqAkKGU8zrp9v/Kfqxc+S2V+1jZ8Rul7AhOntuNJQRRmhAPhyTTKWJ7yvTSAbrI"
+ "+If/9Mv8o3/+TfLhAW9eE1bSKq340HlJs3iOdP4dHryUszM5YJoWbDdripMj4tmc6vZt6pNj"
+ "zMkMs1hgytJa2HedxeTuvHfv5Gi8j8Pc8XFlNDeahtHhkfhQHGPu4fUP2vJsHtw+6/F7w89O"
+ "+jJVKjuDKqRE+kTAUwzcvsRsAjrGAgzR39L+/+uO9+Wak7qyzBMuu7alGAysHEaakuY5TdOE"
+ "sku69DFKEqrl0j41lCLJMpRnvjqgUvQvqM+merXsX5mB9boR3jfOd0n8DeKfFNrNXZWNtf3e"
+ "39vj1uFheCp4NnLszFY907f1ZWaSEMcxq8ZqxCeuk7T23Q+zUWcUDtDHbDgvxWBgMQPHBu6z"
+ "k417+uWDAevlMshrxK67IoQgd2NKXmYkdx2erm2ZPv54V//H/1EppKKTEi1ASgfKCpuVGETY"
+ "hL4LG94QiMiObWis/buKYqIsJSqGQo4GQk4mMpruiGg4ENP9LfHauyfiF/67/5cvf/0qly9N"
+ "qXXCu7cMF/Yatgc1o+477OwcMd25xN50x0yHAzNJUlMoqaO6NmaxMO18brqypKsqaFqED1Ji"
+ "s7E3a+3vZfsNvoPlqQRSKvCZpLCjNyDQ2g5y665DqQiFYbpei0s/+qPtYrkkc1n5vbj+PsMO"
+ "MuGumgikTxeEvmvv9LIof3E95BI52obPAn3Q+9vY/3/TIYDf/Zu+4Z3XXvvhruuCdXYfzc+K"
+ "guV8TuwGQj2d32NFYaP0bkIviOaF9byWdHhSSHnqht3cuH3QYqPn7hfA6/SUbng1iePQxWib"
+ "hiRNQ0pa5Dnv3bxJkWWBEewJqp6Nm+a5rbPduQhhp9OXs1mYCVut14HPJYQIk/T+fPubQQg7"
+ "1N06Xo9SitwNr8aOpuFvmGIwCDdh6xjX/tr51Fu6MteTaT1oqeLYGmq6my12jGR/3fy5eQyi"
+ "z4kJ1zKOpVJKRkmikixTSRSpKI7Fb/z2X4hf/CdfEFffq9k/uIxw3daqG/DE+Ws8cO6Y/Z0R"
+ "u3uXzLn9Hb2zu6snW9vdcDzSeVHoWGvdta1p69r8ba5/mqbhoXWvrr9S6hSZ+t/m+gNB1ytz"
+ "mefd2v8Xrlz5i+9a/N5xNtNdWvF8fwFD17DrKFcrJpNJ+N7OWDNFo+2QMu7i+sgbudRWOD4U"
+ "rgb2h3QL4Vur4UW6p2r4nBDfBdBJpQInxT/d/EUBgqGkH985t7fHcrXazC26tDrY3rsJ9/Vq"
+ "xc50Clh2vL9ZddeROKa0Ngbl/oaXuzGubAhPK3djZM66yUvPJk5ZNXLnX9Z14Mf4823rOgij"
+ "RXG8aTaUpTWg0BojZfCqCxtZa1tquWvouzFA+LnOWAVWAUJIKZRSMlFKyiRRBlSeSnX92v/f"
+ "3pcHV3Hd6X693FVX+4YALWgDIVYBYsesZjO7sQ2243gZ25PEdubVJM9TU5l6NZVUZqYmmZfn"
+ "LJPEsZMJGGICAWOD2cUiFoEkhASShSS0S2hf73673x/dfdR9tdzWgpCgvypV6d7bffrsfc7v"
+ "9zvf10z9759+iZy8e3ByZiyYk4i7pR1wuRmkxliRPLEeIUEGBAXF8eHhUXxoSCAXEhzssfhZ"
+ "OL1ex1FuN+/u6OAhBiDyHg/Fc4LGl1PGzCFn66S82t/bNCDFnkkeQIlEj+V5eABwLhecPA+P"
+ "xMjpEbX4TCa4PZ4nov0lQRISmCmfgMTJg0CqQ6luOY54kxmvl4Q0OUuSEKM5/n1BFR+WTnSt"
+ "StzSbp4nVBwPGxvhb7HAIMq9mwwGQW3ZaiWnxj0eD4kF0TOMsCQW99hdnZ3E3sDxPHi3SNPB"
+ "iPYWsbLllU4qlhbOWknfMzodDGKHcDkcRJJIxzDo6OhASEgIWJpGZ2cnbN3dCAoKQrfVKhxQ"
+ "ldkJdAYDuru7YRJliax2uxBxzDCwcRwgumXddjsRLpCil3kI21NpQpA6iOTdlBwDjOj+Bs/D"
+ "KosBMsuMqE6nIAdO3OK0IH3uFtPQ6/XgpS0wLbBRgGEAj0fgr5I9T9quSNsGmuPAiG9MiqJE"
+ "tgYePE2DMRhommUZP4uJOfJlNvWjfz8MN6fDpKjJcLk9yL7bgElhPFKinYif6ILJL4yPiJjA"
+ "h4eG8qGhIZzZaPTojUbOoNdzNEXxvMfD0zTN64xGXs+yAiVwH+0PCMdoKFqwp0ntT/HyqH0B"
+ "tPi91P4e0SBtCggg7e92OuGmhEDhTrv9iWt/yZBO+K24HvIAoiso266SVZT0P91zppYX65Cw"
+ "N0iTk1gfozX+fUHVCkuaMaWlps5gIG8HkilOkNhmxGWp2WSCXewIjLTSESubA8iKSfJySMFj"
+ "0lEIqVNKjSfc0kOeL30nr1jO7SarM4ZlYRaNmICgmONyOsFJB6PdbtQ3NCAsNBScXo/Ojg74"
+ "BwQQg6dRPCnPSm8UlwtmPz/4WSwkfybxjJjU2Xiv/AJQCmCI19EsC3g8gkwTwwjxMBQFW3c3"
+ "2UZQfbz5pHv1ACmv1EbyOvLIJikAimBA8SKSH8n2h576pHiKokwmPfX1+Xzqze//BmHBBvgH"
+ "xaKmkQdLO5CWBKTGehAabISfZRI/ITKcCw0N4fwtFi4wIJBjdSxnNhh4t8fD0TTNeziOh/hG"
+ "92jtPzbbHyCrQcmOR9M0uFEe/76g2ksoxUQZWIEXR35YkTUYwHEcdHq9oBACgVWBoijxwClD"
+ "jKRSRLC0IpIq1uNyCZLa4hEAl+i2ZcU3rVSp0ol4qXGcbjeMotHO7RLYH1kx3kPyuHR2dSEw"
+ "MJB0XolC2aDTCVHyRiMCAgOFYwoUBXt3N2lAAOTtyYlbKj0rsCnyEGWQxPgbMyvwAnVbrQKT"
+ "JN+jByd1HJplhXNcPE8MmHq9Hk4ploYWWB/1siBZ6W3r4QQ5JaPZDEYMBpRiZaT2kTqbtITn"
+ "5V4fTw8tieSCd4kBicTtzjDgOB4OhxMTwsy8yaij2rpoOLgWxE/2w4LpOkSF0jBbwvjg4FAu"
+ "PCyEDwkO8fhbLJzRaOB1ej1HAzzH8zxF0zxF0zxLUUKQptb+Y7b9SewWRSkmwtEe/77gOw6L"
+ "ZYl4o46m4eI4EsAJ9JyZkmZK6fS3NMtL/ONkW4c+JH8gBoV6PMJxBsk4Ktvfg6LAezwkeI0V"
+ "bQl6ADa7HUa9nnh6OI8QzCedT/K3WAQSMvFNzJhMcLpcxAPjFJkbJMoNvckEu/i2AwTaGqPZ"
+ "LNgoGAZWu52IW5iMRjg9Ahm/5OUx6vVwOJ3Qi+e19Dqd8FbihIPZjNhZpDSlYDrJ7sGKHj3p"
+ "qJJTzDsjXtfd2Qm9wUBCOCiaJgyW8npWgOqJW5Mbks0Wi0CAqNPxbrebcjgcvMFo5KzdNi56"
+ "YgD1g79fTZ3OyENKUiQSJ/E8eJa3BATx4eFhfEhQMGex+HFGo5HzM5s5lmF4HuBpmubF9uUl"
+ "vnCt/cd8+wvbaLcbenEFJQm2jub49wVVgaNOux16sdO47HYSWk8KBcGrYDIY4OCFGCiDwSAc"
+ "gRD3vVKMCABiKJQHrklMDDqGgdvjIft0ctZJms1F4yjP84QJkRUriDQ8x8HpEuSDJKOudDqd"
+ "1ethd7nAQwgeNBmN0LMsidJlWRZutxsmPz84xahnGj1vBo4TzjjyeoGrmgNgEDu7XozVcbsE"
+ "mXOPOHCkRpK2GJLtwCa+haTfJIpcAIRtlRdjfYgcks0mHM4VjcJSKIckGMDL6ljoET0ubYh2"
+ "KuItgmAoljxYBpOJ97jdPOfxcCzLejo6rFj3zHRMTwyF3doGq53jLX5mLjAggA8KCuTMJhNn"
+ "MBo5HcvyDE3zRr2ed7jdcLtcvNb+46/99SYTeVlYLBZYbTZBYXoUx78v+J6wxAoBJfDieMSl"
+ "seQ2Nfr5wWmzCVqA4hKXoihCTCbJH3loWiE9JNknpOWry+UCbDbCP8SIRjppWSwVTrIxeFwu"
+ "QWFXdCcT6gy251wVw7Iwi8cdurq6oBMPSgcEBMAsuq0pcQnM6gTFXYnKleM46AwGwhVvFxtP"
+ "2ma4XC7oxMEBhhGknagetRUSjSxGMCsMnuLAkuwVkquY43vOiEmePuKe1uuJaIbLKdDSSkGF"
+ "UicgnkCGIZ1I+l4O0qnF+nS6XNALy3EeFMXTNM15hPAA3qgzcmGhwZTD4ge9XsczNM0Z9XrO"
+ "bDbzFEXxJoOBd7lcPGsw8E7RrqK1//hsf0pMh2FZ2BwOOBwO+InHjkZr/PuCKnoZKThT6jxy"
+ "Inqe4+Dv7w+H2w0Dy0LPssKSWVJelvbM8sqSz7S0QPIldUopcA0AKby0/HS7XISCQ+qMAAin"
+ "O0XTsIvLZ73RKBwYFbng/fz80NbeLhgDrVYEBASgU6xgjuNAcaJYpOQWpoRIe7v4JpMqF+g5"
+ "wAqKAkvTsIlBflYx9oTV64VtickExuWCy+kkCsCsOBAlSGWlWRasuKqQKHAhDkaKomCz24Wz"
+ "bOLy22m3E3klyuMROoC8Y8qW/QpIb1lZeaQBKg4SzuPxwOlweCiOQ3BQIIICA0i5pcFF0TTh"
+ "4g6wWIT21+kAnU5r//Hd/kKslBjPNtrj3xd8hpZKvOc8L7iQyaFb0T7gtNuFpSNFwSG+Hcxi"
+ "ZyGRseKeVR55K++IOpaFn9kMo8kEg9FIgs0km4HcHSwVXBo88kA2TurMMld/t8gv7RR/AwTP"
+ "jU1crkqxSXbpyIuYZ3I8Q7yH0engtAkiDPLB4hI7l8vhELYNHg85FsSJ9gCdXhA20DEMyZvL"
+ "6YTNbodDYpIUtyk8L0YA0zKCNp6HSeQiomiaHDeSB+N5B1ZKniCJa0hubKXESYGmaSGoUq8n"
+ "b3YpCpsRAy+19tfafzTb3xd8TlgeWWGlBpceLH1mxH0/LZvNzX5+QoXyPMkw0BNRCwjbTVZc"
+ "CrtkdguaFs5RWQICSFiFNPtLDe52u+EU9/ms+IbweHok7KWK1ukFySGaEqhaadHGQDOMEOlM"
+ "03A4nTCKbz0pwM1ltwuzv1fHISyoEOJGnOLbVWKCZBhG8JDQgiKLrbsbnMcDncEg8HSLS2AA"
+ "0LOscHBWrCNp5cDQtMBQSQsacJJdhKJp2EQWSqkTyjmEpPNh5E+sb8mASzMMaSNpC2USPTNG"
+ "kZ/JKW6TrN3dxKujtb/W/qPZ/gPBtwiFuCSVaFKdoidEcoFK8RMULYiU8jwvRABLBRMzLe2n"
+ "pX056RysQAND3qCULIhNNOoBAC2+Zd0eD/Gs6MVzdRI7pE50D0v5dtrtxEWuN5kIEylFieRh"
+ "DENc5/LO7hDpQXieF9RBxA5i8feHQ1wqdzkcJDhPSkvi4dKJ7mLpVLpLPLEvvVVohoHD5RI8"
+ "YmLDeTiuZzByHHQ8D4fLJfB7iXXOsoI6MDlGInZCed1JHYGiKHCUcG5NOvIhiWBKB1l5CF4c"
+ "hqLQbbXC7nAIAZlUjzyVlK7W/lr7j0b7+4LPCSt9+fKA6MmThQcA5G3Ta28sK5yUGYiZo6R7"
+ "pXtkBYE8He89uFQw8bny7+SQ54cE7/WdOeWz+knP+/nSZwo90bje6RNDJtUjR44+viN7efTU"
+ "pTx9yH5HP+Xi0Uf5+mkPkg/pjStLW8q3tzyV9L23p0lrf639H2X7h4hHoAaCKl3C7Tt2qOHW"
+ "0qBBg4Yh4+yZMz6t7j4nIu+ZV4MGDRoeBdTMNT4nrP6Wfho0aNAwkhiRCUtbX2nQoGE0oGZx"
+ "5HuFNSJZ0aBBg4aBoWZxpBnTNWjQMCagZkuoisBvpNDS1ASHeEbJ6XBAp9NhSmKiqnvramrQ"
+ "3taGxORkVYckH1eaGgaH5sZGOJ1O0icYlkVCUtLjztZThbEyDtTs5oY8YTU3NiroTX2BYRhk"
+ "XryIe/n55AT9pOhovKliwrp75w4Of/YZACB2yhS89s47Q8v0I05Tw+Bx4fRpfFNYSI6GREZF"
+ "IeGDDx5zrp4ejLdx4FtItZ/v9/3hD2hva4PZzw+ToqMBAPeLisjvSdOmAQBqqqpg7e5GYFAQ"
+ "PvjwQ0yOicGXR44MKpPlZWXk/8ryckLiPxw8ijQ1DB7Pv/wycm/exPHDhx93Vp5KjKVxoMbo"
+ "7psieYDf/AMC8HfvvQeLvz9ampoUE9b6555DSFgYujo78dtf/IJ8HyAjrVeLBYsXo6SoCJ0d"
+ "HVixZs2IVOijSHMkcL+oCAf/9CcAQEJyMva+/voT9by+EKwiwlnDo8FYGgcjY8MaYNZ7dvNm"
+ "WPz9B7zd4u+PZzdvxvlTp3w+qj9EREbigw8/HNHZ/1GkORKQDtkC6ug2xtvzNIwtjNVx0B+G"
+ "bMOaM38+ps+cqera1Nmz0dzU1O/vHe3tKLt/H06HA1GTJyM6Npb8ZrfZYLVa4RSN9S6XC4nJ"
+ "yYr73S4XHpSWoqW5GQzDICwiAv4BAeju6kJMXFyv5z2KNOWora5GfW0t7DYb9AYDwiMjERMX"
+ "53PJ21Bfj/a2NvLZ6XSiob4eABAYHAyDeCDVYbejrKQE7a2tYFgWERMm9Jm+rzKofZ4Eh90O"
+ "a3c3cZy4XS4kJCeju6sLpcXFMBiNSE5JUeRDbV4HwmDSGEzdq23jwZbB4XCgubGx1/cBgYGw"
+ "+PujuamJ0CkDgt1Omix8PWuwbTBQGSMiI32OA0DoFxVlZWhtbgYPIDAoCHEJCTDKONj7y5fd"
+ "ZkNJcTG6OzsREh6OxKSk/gVTR2JL2N/h0GfWrvV5qwSaprFy3bo+f8u6ehWnv/pKcVp7+erV"
+ "WPXsswCA7KwsZGZkwC6yEVIUhR/99Kfk2qqKChzatw82qxUr1qyBn8WCC6dPo7qiAulLlvQ5"
+ "uTyKNAFhwjly8CAa6uuxZuNGBAUH4+svvkB3VxeiY2PxyptvQieSofWFw599BodMp6++tpYY"
+ "RDds3YopiYm4df06zp48iaDgYKxYswbZ16/j5LFjiIyKwouvvoogcXulpgxqnifHvfx8nPv6"
+ "a1hFkQaGYbBzzx4c+/xzwpKwct06rFizBgBU53UgqE1jsHWvto2HUgZbdzdOffklqsrLyXeT"
+ "Y2KwdtMmWPz9UVFWhkvnz6ND9MztevllMAyj6lmDaQNfZayqqBhwHEjlP3/qFDiOw9qNG8Ew"
+ "DI4fPgy3y4Vlq1Zh2apVoCiqz3y9+NprOHLgAEkfAJJTUvDit77V92SvYkvIAHhloAsC/P0T"
+ "Fi5c6HPqs1mtyLp6lXxOX7IEJrO513Utzc3Iv30bAIRZfsIE7HjxRUycPBlFBQUAhM60YNEi"
+ "6PR6xMTFIXHaNGRfFwRhKYoikyXPcfjkN79BV2cn4pOS8NzOnYiaNAmz09JQV1MDmmEwdfr0"
+ "Xnl4FGkCwKH9+1FbXQ0AWLR8OaalpqK7qwvVFRXoaG+HxWLBpJiYfutwweLFCAgKwr38fACC"
+ "1+bN730PCxYvRnBICG7fuoUvjxyBx+PBzpdeQnJKCsIjI5GTlSU8p7ISaenpqsvg63neiJo0"
+ "CfFJSci+cUOoK56H0WhE0rRpKC8tFb4DMGfePNV5BYC21lbk5eQAEEwI8xctAoBBpTGYuldb"
+ "P4N5vhxGkwlz0tJwv6gIXZ2dAIC09HTMSksj9cjzgkrR3jfeAMuyqp+ltg1mz53rs4zrNm3q"
+ "dxwAwmR14uhRuN1urN6wAQuXLkXUpEkwm80oLChAeWkpeJ7HlISEPvPF8zx2vPgiZs6di7t5"
+ "efB4PGhuakJcQgKCgoN71VtpaSn/oLy8tN8BgsccOBoxYQLWbNiAwKAgzJwzBwFBQQCEDtUk"
+ "W1IH91E4ALBarejs6AAgeDuyrl6FzWoFTdPYtH07wsLD+332o0gzdsoUAILai9Qg8km7sY9t"
+ "glq43W6cOXGCfJY8syGhoeS7mqoqtDQ1DasMviDvaAzD4LmdOxEbH0+W80nTpg0qryNRXmBw"
+ "da+mfoZbBoqmsfSZZ8jnW9evK8KA8nNz8Yy46xjss9S0gdo+0N84cLlcOPf11+SzfKsYL4uT"
+ "y7x4Ed1dXb3yRTMMtr/wAkLDwzE5JkZxT6NodvDGiHgJHyW8jXwG2ZJdDaGX2WyGxd8fXZ2d"
+ "8Ljd+PqLL3Dqyy8RGxeH+YsXY4msw6jFcNJc9eyzWLZyJWiaRsPDh7h49ixuZ2eT34dj1K6p"
+ "rITNaiWf/7p/P2HZlKO9vR1xISEjXi8DISYuDu//8Iewdndj4uTJqCgrU53XkLCwPtMcTHlD"
+ "wsIGVfdq2ngkyjBtxgwEhYSgraUFXZ2duJuXh1lpaaiqqIDRaCQT02DL2he820AiHBxqH6ip"
+ "rFTY2eTONf+AAPI/5/Gg4sGDXvZsClCwoepl9lDPMMbBsLyEjxsUTWP7iy/i0L59pHJ5jkN5"
+ "WRnKy8qweMUKrNu0adTSdNjtuHrpEvJycuBxu7F6/XrMmjsXl8+fB9B7gh4MrLIODQDbXnih"
+ "zzeSwWh8JPXiC0HBweQNO5i89ofBpjGYuldTP5O9tu5DKQNN01i0bBm+/uILAMDVS5cwKy0N"
+ "N65cUUwYI1FfgLINhtsHbF4KNgpBWJEPXqI9tqtQuxkpjOuzhG0tLQgJCcF7P/gBNmzZgimJ"
+ "iQoPxPXLl2GXvSUeZZqcx4M//va3uCwaU195803MXbBAMVAYdugLWvlbDRBEDMx+fr3+GIZ5"
+ "JPXyqPI6EmkMtu7V1I+3c2QoZQAEb7okrtBQX4+crCy0NDcjcerUEa0vbwy3D3jnSS4jLxdC"
+ "BQSv4WjB94Q1hgn8qquqcOLoUZj9/JC+dClefestvP/DHxKDsaSdNhpp1tbU4GFdHQCBezsy"
+ "KopcL4FVMWHJ36wu2XOiJk2Cn8VCPt+9c6fXvQV5eairqRlUGfp73nAwmLyORBqDrXs19RMe"
+ "ETHsMgCAXq8nTgQA+OroUSxevnzIZVWL4Y6NiZMnE5syIDhG+vrf7OdH7IejgRFbYbW3tys+"
+ "NzY09HmdfFDIXeoAFKoZ8tlfctcCQkVLrlOWZVFSXIyLZ8+S3wODghAWEQFAMF72F9g60mnK"
+ "B4Tb7UZOVhYqy8tRKHo+ASHezBfk3rn62lqUl5aiq7MTTocDG7duJb9lnD2LW9evo7OjA+1t"
+ "bbh07hwyTp9GQGDgoMrQ3/NsXtsUCfJ64ziOnAuVg2EY1XkFlH3CbrMJMlODSGOwda+mfgKD"
+ "ggZVhoGQvmQJ2VJZLBakzpo1rPpS0wZq+0B/44CmaWzZuZOsyu7JJlFSrxSFzTt2kAPTvfIl"
+ "++yWrdAc/azs1CyNhh3W0Nbaij9//DGuX7miMGzezcvD3Tt3kDR1KlkSZ168iHNff01mdmt3"
+ "N+4XFSEtPR3/8/vfo172BikuKoJer0dHezsOf/aZYgK7nZ2N8AkTwDIM6mtq0PjwIe7k5KCj"
+ "vR13cnNxLz8fCUlJ2LlnT6/gR0CIJxrpNC3+/mhva0N9ba2Q/8JCNDc2Yu3GjSguLITb7cbD"
+ "ujrk3rqF1Fmz+kxDSqezowN1NTXgOA55OTnIy8nBxMmTMS01FRMnT0ZdTQ26u7pwv6gI1y9f"
+ "xo3MTJjNZjz/8ss9+VBZhoGeF+pl4L2Xn4/DBw4oOtzt7Gx0d3UpvEAAEB4ZqSqv1y9fxpkT"
+ "J8ik5bDbUXD7NpJTUhAdF6cqjcHWvd1mU1U/asvgC3qDAS3NzXhYV4cFixcjoY/gTLXPUtsG"
+ "avpAaXFxv+MgNCwMIaGhiIuPx8O6OhTdvYvu7m6UlZQg8+JFREZFYcdLL5Ezw33lqyAvD9NS"
+ "U3H+1Cnk5+aSFW9leTm6OzvJvRLKysr4B0tMTvAAABxqSURBVA8eDBjWQAE4OdAFkyZOfPa9"
+ "998fk7YuSQnYaDSipakJzc3NoGka4RERQzqzOBJpNjU2oqOtDQGBgeRtZrfbUV9TA4qiEDlx"
+ "oiJCuD+0tbaio70dRpMJYeHhCo8LIFD1tIlR6hGRkYqBM5Qy+HrecDBQXkcyDbV1P5T6GW4Z"
+ "3G43nA4HDAaDT1vmSNTXSI+NtpYWtLS0gAIQEhb2SOxWZ06f5s6dP396oGvG9YSlQYOGJwen"
+ "T53izl+4MOCE5XsiGsNhDRo0aHi6oK2cNGjQMCagiVBo0KBh3GBEJqyxG4WlQYOGpw3allCD"
+ "Bg1jAmNONWc0cOTgQRSI9DUStuzahbkLFjymHGnQoEENxv2Etf+TT/CgpKTXuSWD0YjWlhaB"
+ "QTE8HCkzZ2LBokVgdTrsfOklzJw7Fwc+/ZTco6YixhP2ffwxHpSVKQJ1A4OCoNfr0dLSApZl"
+ "ER4RgekzZ2L+4sWqjgQ9yfjs009RVlKiYAAJDAqC0WQix0yCQ0KQOHUqFi9f3iePm4axgSEz"
+ "jo4GXn7jDTQ+fIjf/Nd/ke+Wr16NtPR0OBwOHN6/HyXFxaiurMT9oiK8+uaboGi6T5rXJwmv"
+ "vPUWGh4+xH/3US/dXV346/79qHjwgNTLK2K9PAnIycpSqC79y7/9m8979r7+OhobGvCbn/+c"
+ "fCfVl8vlwrHPP8e9/HzU19aisKAAb7//PnTjRKdyKPUxnuHbS/iY47DCIyP7/N5gMGDV+vXk"
+ "c3lpKSpFStrHnefRQEQ/9eJnsWCD7FzaA1m9PM0IFyPfvaHT6bBu82byubmxEWX3749WtjQM"
+ "Er69hGN4O+U9mckFFZ5meA9O+el6Db1hkTElABg0w4eG0cO4Nm54M3j6qzwjxfM88rKzkX3j"
+ "Bhx2O7q6uhAUHIx5Cxdi3sKFimtbW1pw9eJFPCgtBcuyaG5qQkBgIFJmzMDKtWt7SXvfvXMH"
+ "t65dQ31dHSwWC/QGA/wDAtDR3o7V69cTHqTB5GGwkJ+SBwCLF7eRmmefP3UKVy5cUNy3duNG"
+ "tDQ3o7CgAC6XC3Hx8Vi/ZUuvQ9KAcAA5+8YN1NfWwuznB2t3NyZMnIi09HQFJ37GmTO4dO6c"
+ "4t4tu3aB4zhcyciAzWrFhi1bMGf+fPz+o48Im4CE33/0EQDg7957b5C11IMakQseEPjYpUPE"
+ "NzIzcfbECQXz55ZduxAZFYX9n3yiYLTwduzYrFZkZmSg6N49OOx2uN1ucjBYp9cjLDwcQcHB"
+ "2P2KwD2gtt94l11tfahtj8cKFTsj32wNAQGqRCgeJeQUGckpKYiaNAmAsN3Jz80FILAtPrtp"
+ "E7HV9HcPABz9/HNcPn8eRpMJ73zwAYKCg3Hr2jXcLyqCy+kkHba1uRm/++gjVFVUIGriRLzx"
+ "ne+go60ND0pKUFVRAavViuSUFJLulYwMnPjb39De1oZ5Cxdi7+uvIy09HXarFbdv3cLMuXMJ"
+ "xa3aPAylXkqKiwmnklQv8sPMap49JTERsfHxyJPRDDscDixcuhQBgYEou39fmLzy8zF73jwF"
+ "4d1XR4/izFdfoaOtDd9+9108s2YN4hMTcU48td/e1kYGSVxCAkLDwhRUMO1tbWhvbUV9bS08"
+ "Hg8qy8ux9JlnMG/hQuj1ehQXFpJr/9c//7PqCb6v+qqrqcGxQ4dgs1oxYeJE7H7lFQSLXOqT"
+ "Y2KQOHUqcrKyFPclp6RgxuzZuHHlSp/173Q68Ydf/QrFhYWwWa349jvvYFpqKhHaAM/jje98"
+ "hwhYDKbfyKG2PgbTHo8TZaWlPtkaxm2ke2V5Ob76298ACOyIL7z6qoLGtT/k5+aSSW5aaioY"
+ "hkG8TM7q2uXLhLy/rraWvBWrKioAQDHxeROtXbt0qeeDuJWmKAoLlizBgsWLh5SHwaK2uhqn"
+ "jh8HAISFh2PP668r2AEG8+y4+HhF2nMXLMCUxEQsX72akLZ1dXbiqqzcednZRIVl2owZxNYW"
+ "GRWFZJFO5PatW7h96xa5J3X2bMVzEqdOxcy5c4dUfrW4kpGBX/3nf+LjX/4SzY2NSJkxA9te"
+ "eEHRvoBAZNcXBmIrKPnmG4UuYWRUlEItieM4VD54QD6r7TdDwVDaYyzD55ZwrFmwrly4gOtX"
+ "rgA8j4jISCxetgxzFiyAfgC9PzluXrtG/pdoYE0iXxcgbJeqKiowfeZMTJ0+HSvWrEFzUxOm"
+ "paYCAFEIAXpzWcvDL7KuXkVNVRVSZ89GyowZ2Lht25DyoBaXL1zA2ZMnSZ6mTp+O3S+/3GsS"
+ "H6lnx8bHo0IcdPcLC7F248Ze6UvMnxIiJkwgK6nsGzcwZ/58AL2dJFKIwcTJk9Hw8CFWy5wr"
+ "I4VlK1cKqxi7HZkZGcjMyEBhQQGmz5yJbS+8MCwvofe9bre7VxnllDFq+81QMJT2GMsY02EN"
+ "fWHZqlV9asGpRb1IpQsIogDSlkehBCJ2IIZhsHLdOtRUVeFefj4yzpwZkCdq/qJFyMzIIJ9r"
+ "qqpQU1WF0199hTnz5mHTtm1gdbpB5UEtlq9ahcryctwRtx3FhYWoqqzsRV87Us+WD7jWlhby"
+ "f8PDh+R/b94vOQ3ww36knuTXvvW97/nMx3BhNBqxZsMGPKytRUlxMe7l58MSEIANW7YMOc3E"
+ "5GSkzJhBJoPysjLQsgkrNj5esXpV22+GgpFqj7GCca2aM1wsXr58wCV3S3Mz/nbwIGqqqmDx"
+ "98erb72FqooKRdyLHKvXr4fZbMa1y5eJgCYAgOdx+9YtmMzmXkolvvIwGGzesQP1tbVoqK8H"
+ "z/M4cuAA3n7/fUXHfBTPlr/S1PYWeoz1q/ikJJQUFwMACm7fHtaERdE0dr/yCr65dw9fHjmC"
+ "r7/4AjRFYXJMDKalpiJ9yRJFXNxQ+o3qvKi8bqy1R38Ydyus4SI8IoKQ+fviWD/6l7+gpqoK"
+ "gMDLHR4ZSWxZfeH//vSneP+HP8Si5ctRX1uL4sJC5GRlEZuQFN8zmDwMBjqdDrv27MHvP/oI"
+ "brcbnR0dOPqXv2DvG2+QLclIPVvunZILs0ZMmEDqzJuzX35Pf7ahwYLn+RGJu5Nvnb29rENB"
+ "SXExjh8+jIjISHzr7bcHvFZtv1ED7/oY7fZ41Hjq2BrmzJtH/i8V36hy1FRVkUmpVubulo63"
+ "DLRd6uzowJWMDFAUhahJk/DM2rV487vfJb9LK53B5GGwCI+MxJoNG3rSv39fETYwnGfL3fty"
+ "BZfZsjTlKzaJY11Cg2zbsWDJkgHL0R+87UPebv2hQt7WE70M7/KjOi5xMpOLKvSFS2fPwtrd"
+ "jbbWVlRXVqKpoUH4a2xU2EEB9f2mL/iqj0fdHiMJNXPNmPcSekuB11ZX+wxm9dZbk3vc5i1a"
+ "RMjv62trcfXiRZLew/p6nDh6lAg0yOOLrmdm4vypUwoXNyB4YeQrlYvnzuHqpUtkYpOCWWmZ"
+ "dPlg8tAfvFWJHspsU+lLlyI6Lq4nT2fPEi/QcJ6dl51NBB3uf/MNAEFxOF02KGalpZHOX1hQ"
+ "QAbFw/p6fHPvHgBgyYoVSJkxg9zjrdDjLSwqx6SYGIWZ4uSxY7hx5YpPMU9vr6vctlNcVIR8"
+ "8cC8wWjEs889p7hWHgN1Lz8fzU1NOPPVV4pr5F5BAJgiel7bWlvxya9/jV///OfC389+hp/9"
+ "+Mf47NNPFXlW02/6gq/6GEp7PC6omWuGrZrzKPHpb36D86dPKyaoupoa3Lx2DRGRkX0GLJYW"
+ "F+OzTz5RLH8ryspIrAlFUUidNQt+FgtsVivu5efj1vXrqCgrQ2dHBzZt306kr2Li4lBbXY3u"
+ "ri6id7d19250dnSgtbkZHM+job4egUFBiIyKwqVz57Dt+edRWlyMy+fPI+fmTeRlZyMhKQnb"
+ "du9GjDiJDCYPfeEPv/oVLpw5o9iu11ZXI+vqVSRPmwY/iwXRMTHIycoidffNvXvIy85GWno6"
+ "ZqWlqX62PHaps6MDWVev4tb16zCbzUhbuBBbnn++l0E4aepUTJg4EdauLly9dAn5ubnIvXkT"
+ "sVOmYOPWrZgn0+krLizEgT/+USFVVV5Who5+YoNMZjP8AwJQV1MDl8sFp9MJ/4AAxCcn9ys0"
+ "+tf9+3H25ElFBHtNVRVu37qF7Bs3UHD7NsIjIjArLQ3bdu8mAhYSYuLi0FBXh/b2dmHV1NKC"
+ "5atX4+bVq+Sa6spKlBYXk+DRuClToNPrUV1ZqTh0LaGluRk2mw3JKSmq+01fUFMfg2mPxwk1"
+ "cViaCIWGAfGvH35I/n9u585heWifFuRkZeHc11/DZrUiISmJ2BA5jweFBQU4fOAAACHM4J0P"
+ "PnjMuR07OH36NHfeh2rOuD6ao0HDWMTXx4+T1VxSSgoxgtMMg2TZqlHurNCgbkuoqeZo6Bfe"
+ "BlxvY7GGvhEr28Ll5+YqbHRS1HlgcLDCOaJBHbQVloY+cfXSJVy9eFHx3YUzZ3D3zh28/MYb"
+ "ikBTDUrsfvVV3LhyBfeLitDc1IT/9x//geCQEPA8Lxj1N29GWno69D4cK08b1HgJn7o4LA3q"
+ "sGTFCixZseJxZ2NcQq/XY/nq1Vi+evXjzsq4grYl1KBBwxMFzfunQYOGMYERCRzVtoQaNGgY"
+ "DajZyz2xRvd9H3+MspISxXex8fF4zce5Lg1DR0FeHo6IMUZy9FXv0sFgQIjvGgsEchrGPp7Y"
+ "LeErb72Fbbt3K7/UVouPFKkzZ+K7//iPmJWWpvyhj3o/fvgwuru60N3V1S/7hQYN3nhiV1gA"
+ "MHPuXBw7dOhxZ2PU0NnRgbycHJQWF6OlqQk0TcPj8cBgNCIuPp4wTjwqUDSN0LAwbNy6lfBy"
+ "9Xut5szRMAT4Zhwdx6uSgcj2niS43W5cPHsWNzIzMS01FSvXrUN0TAyhTOnu6kJxYSH+un8/"
+ "kqdPx+r16x/phGHwIorrC5t37MCXR46Aoihs3rGj1+/yI0GxU6bgtXfeGdE8ahifeKJXWE8D"
+ "bFYrPvv0U7S2tGDvt7+NuISEXtf4WSyYu2ABZs6Zg2OHDuHsyZNDJoQbKUxLTSW00xo0qMWY"
+ "F1LV0D/cbjc++/RTNDc14bW33+5zspKD1emw/YUXUFpcrOCz0qBhTEDFXPPUrbDqampw9sQJ"
+ "VFZUwGg0YvrMmVi9fj3Zxhz9/PNe9hfJy5Vx5gwuX7ig0EPsywPmcrmQfeMGCvPz0fDwIViW"
+ "VZ7DoygEihqKH8i2PqX37+P6pUuoqa6Gx+1GYFAQQsPD4bDbMW3GDKR7kaxlnD6Nmqoq7Nqz"
+ "h9imnE4nLp07h/zcXHAch6nTp6OyvBxNDQ2YFB2NN7/7XSxevhw3r13D1uef71U/rc3NuHr5"
+ "Mkq/+QYejwc2mw1h4eGYOXcu0hcvVijwAAKtzeXz51Hx4AE4jwfBoaG9xA7keFhXh9/+4he9"
+ "vpck1n/Rh9R6dWUl+f6DDz/EX/fvx738fMU1sfHx2LJzJ059+SUelJYiMDAQu199lajENDc1"
+ "4ea1a3hQUgKb1QqHwwGWZREeGYm58+crSAjVoLmpCVmZmSi7fx82mw0URcFoNCI+KQnpS5cq"
+ "qI+Gkt+h9qHxDG+d0b7gkw/L32JJWLho0bhdZsn5nNxuN+pqauBnsaCxoQFOhwO11dUoLy3F"
+ "nHnzQNE0pqWmIjwyUtHBgoKCMGf+fMQlJCA+MVEhiST9JsHa3Y1Pfv1r5OfmoqO9HWs3bMDu"
+ "V14BTdMoL+2h+tm1dy82yRRR7uTk4NC+fWhtaYHBaMT3fvADLFq+HDVVVbh75w4Sp07FpOho"
+ "cn1HezsOHzyIqEmTiDR9R3s7Pv3v/0bxvXtYt2kTdu3di7t37pDnLn3mGUyKiYHZzw8ZZ89i"
+ "4dKliroqLCjA/3z8MWoqK7F+yxZsf/FF8DyPgrw8lN2/j6rycsyYM4fYBu/k5ODAn/6EpoYG"
+ "REZF4e/eew/pS5eiqqIC1ZWVPXUUHEzqyOLvj4TkZNzJzVV00GfWrgUALFq2DIuWLVO0W0xc"
+ "HN75/vexaNkyAEDKjBkwGI1K6mCRm+xBaSncLhdsVius3d2YPmsWigsL8T+/+x2qKypA0zS+"
+ "/+GHmD1vHq5fuYLW5mZ8c+8e9Ho9omNj++lFShTcvo39f/gDqisrMSUhAa+/+y4WLVuGqspK"
+ "5GVnIycrC8HBwWTiHmx+h9qHxjtKSkr48vLyYeoSPkGGaz+LBd96+23s2rsXz8kMvTVVVciV"
+ "TUIDsS9OlunL9YVL58+jScYGKrn45arAAJDnpQN34cwZRT7Nfn6gaRrPbt7c54rl9q1b4Dwe"
+ "wk/FcRw+//Of0dzYiITkZCKm6efnB0DY2k+fNYuk3+nF597U2IgjBw/C43bDz2IhKw75yqO8"
+ "rIyo7NTX1uKLv/6VTDobt22DyWwGTdNYuW7dgHU0OSamFw3xYEDRNBZ6rTYpmsbze/fCI6Mu"
+ "ltg7s2/cIPTOVqsVNMMIpIsTJpBr5XJYA6GupgZHP/+cpPfsc8+BYVkwLEvsgh63G0cPHSLb"
+ "7sHmd6h9aLxDjfnJN6f7IOWmxjJMJhOplJlz5hCedkB4a0oYqOJ8VWqTF3WxRDdsFicOCd6C"
+ "AHIK34b6ehw5eBD1tbWgabpPZZtS8W0dK8pF5efmEl5y+fWS1NSUhAQizeV2uXqxc2ZmZJDB"
+ "I2cclct5AT088FcyMsgAM/v5KUQM1GhEDteD6623GBgYCIZlsXz1augNBgQGB2PFmjUAgDnz"
+ "58NoMgEUhdmyGDF5+0uUxL6QKSt3UEgIAsRtGSCIq0r1xXMcMmVsF4PJ71D70HjHiLA1PEkr"
+ "LDkYlkVIWJiC43okEB0bq1j6d7S3IygkpBe3lFxtGRCED+TbqILbt1Fw+zYiJkzAM2vX9lr1"
+ "NYqc5NLkcluSlKcoYnyvrqwkA3HGnDnk3uampl7S53JBirqaGoUtSR6mIIkvyLcmQcHBvSvi"
+ "MeGZtWvJ9lJCyowZSJkxAxzHgeM4FBcVoTA/H9WimgygPnynQqbYbOlDHMI/IIBIdVWUlQ0p"
+ "v0PtQ08Dnmp6Gbmw5Ei9rZatXIm21laydcq6dg3rNm1SbDniEhJ6qZRs3rEDf/74416dsqG+"
+ "Hof27cOWXbsUWwK73Q6apslKRVpd+fv7kxXO3bw8AIIgrHzCu19UhOSUFMVz5M+dMHGiQrWl"
+ "L9hkAgosO/Z9N3U1Nbh+5Qq+uXsXeoMBazZsQHNjo+IloQZyMj7vVROgVLHxFtdQi6H2ofGO"
+ "ETlL+OROV0rZKrlc+3DAsCy27d6NRcuW4dTx48i9eRP5ubmgaRpTEhMxY/ZszJ43r9eWKDIq"
+ "Cn//D/+A7Bs3cPfOHbKCknDp/HnFhKXT6eByOuF2u4UJQ3yxSFs9juOI4yA6Npaskrq7ulBw"
+ "+za+/e67ivTNfn5kZdDW2uqznGazmXitbD4Uax437uTk4OihQwDPg2YYvP3uuwgJDVU4T9RC"
+ "Xk99iUvI5b+8t9NqMdQ+9DTA95ZwNHLxmCC3G3krk1A0PWT7XUFeHs6ePAmX04kf/Mu/qOpY"
+ "//5//g++/0//hBVr1mDFmjVobmrChVOnyKTjLVMVGhaG+tpatDQ1IWLCBCQkJ6Po7l20tbbi"
+ "1vXrqCwvJyEILpcLHrcb9XV1OHnsGNZv2dJL6y4mLo48q7urC+VlZQo5dQCw22zIy87GwmXL"
+ "EB0bi6K7dwGAaO0NpJ83HAykBakGF06fJhP6hKgohISG+rzn3p07+PJvf4PZzw8vvfYa4V+f"
+ "kpiI/NxcAH1TRsvbKT4pach5Hkofehow9tfyIwiXTOapo71doSe4aPlyxbVBwcFobW4GAIV8"
+ "uEJKvB8cO3SIGLB/9uMfwywT4gRFITg4GItXrCDadQDgsNtx7uRJbNq+HYAwIW19/nkyiXgL"
+ "FkxJSEB9bS3K7t9HxIQJ2LR9O9wuF8ofPEDmxYvYsGULVq1bh6+PH0dleTl+9pOfIDo2Fpt3"
+ "7EBUHx66xStWoLCggNhyvjh0CM+//DIxpjc1NODIwYOIED1rCxYvJhMWz3E4cfQodrz0EliW"
+ "xf2iIp915AsGoxEOUV9SzYpvIMgnEZvVKpSR53utDDmOIxPDiWPHYLfZYLfZkHHmDJ7fuxeA"
+ "sF27e+cOOI8HrS0taG9rQ2BQkJDPlhbyLJZlsWQAPUFfGEofehrw1GwJWZZFbXU1KsvLER0b"
+ "q4jzWbtpU68V1qy5c8k1zU1NuHHlCkLCwnq5vxsbGnqtLmanpRHBVZvV2suW0dzYiJL79/HS"
+ "t76lsCXdun4dDMNg5bPPwmAwEHociqKwev16RRrzFi7E9cxM3Lx2DelLl8Li74+9b7zRq9x7"
+ "vv1tVfUzKToam3fswFdHj4LnOLS1tuLjX/4SfhYLWJZFe1sbkqZNI+f+piQmYvGKFbh26RIA"
+ "wRtZ+q//CqPJ1Gs12NTYCGt3N/FycRyHTq+Jv7y0VBGpn5icjLt37gAQJpyDf/oTzH5+JNjV"
+ "26vX0dEBj8fTpzZhdFwcMYC3trTgT7/7XZ+r54wzZ5A4dSpi4uKURnjZ/+GRkdjx4os49vnn"
+ "cLvdOHPiBHa88AJ4AGdPCop5Or0eu/bsUbxkBpNfYOh9aDxDTVjDmBZSHQlcOncOG7ZuxYat"
+ "W+FyuXDt0iVkZmSgvq4OMVOmYPP27QpXt4To2Fg4HQ60NDfD43ajsbEROp0O6597TiHO4HK5"
+ "kJWZCf+AALJySU5JQWBQEBobGgY0vDY2NGC+KGJ58exZ7NyzB00NDTh/6hSuXryIort3EZ+Y"
+ "iC27dvXaXpjMZnjcbhQXFoKmaRLeMBxETZqElNRUuN1u2O12spUMCQ3Fmg0bsGbDBsUAS0hK"
+ "QlBwMDra22Gz2cCyLKJjY7Ft927k3rzZU0dOJ65fuQKHw4GEpCT86mc/66XonZeTA4qiSDli"
+ "p0xBc2Mj2tvbQdE0dDodEpOTMSkmBtcuX8ahffsUW0W7zYacrCwkTZtGYs8kxCcmoqmxEe1t"
+ "bWBYFsEhIVi3aRPS0tPxsK4OXV1d4AF0dXTAz98f0bGxCAwKwoPSUgQEBmLzzp2KNCMiIzF9"
+ "1ixwHg+qKipw+cIFZGVmwul0YuacOdjx0kuKIN/B5hcYWh8a7ygdCSHViVFRz77/wQfjdgNt"
+ "s1phki+nHzEelJTg+JEjaGtpgd5gwA9+9CNiS3I6ncgSJe8BwUD+zz/5yZCfxXEcjhw4gHsF"
+ "BVj/3HO9Ite9UVNVhTs5Odj4BEVHP4kYzT40lnD61Cnu/IULAwqpjtuJSC1Gc7ICgCMHD6Kt"
+ "pQUAEB4RoTh7p9frFbay4Upl0TSNXXv2YNW6dTh78iT++NvforiwUCH77nK5UF5aisMHDuDk"
+ "sWO9ziNqGHsYzT403uDbS6ixNQwKimW/aDSWQ27fkZ9BHCoomsby1asxZ/585N68iUvnzuHQ"
+ "vn3QibFYHo8Hk2NikJaejukzZ2rtOQ4w2n1oPOGpMbqPFpatWoUzX30FQDCMXjh9GivWrAHD"
+ "MLBZrTh1/DgAIfJ86cqVI/Zc/4AAEhLBc1wPg4DsOJKG8YHH1YfGA554G9bjwIOSEuTeuoXa"
+ "6mrhkDFFwWKxgKIoTIyOxpz585/KYxUa1ONp7ENqbFjalvARYEpi4lMXH6NhZKH1ob6hrZw0"
+ "aNAwbqBNWBo0aBgTGBE+LA0aNGgYDYyMVL0GDRo0jAZUUFlpE5YGDRrGDXyGNQAY+pFzDRo0"
+ "aFAJk8kEm812caBr1ExYGjRo0DAmoG0JNWjQMG6gTVgaNGgYN9AmLA0aNIwbaBOWBg0axg20"
+ "CUuDBg3jBtqEpUGDhnGD/w8mANBHiJ4GhAAAAABJRU5ErkJggg==")
+
+index.append('splashwarn')
+catalog['splashwarn'] = splashwarn
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/README b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/README
new file mode 100644
index 0000000..c17a088
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/README
@@ -0,0 +1,11 @@
+This directory contains python modules that are distributed as part of Editra
+but were not originally written as part of this project.
+
+See each module for their individual licensing and other related information.
+
+
+pygments 1.0 (BSD)
+
+# Modifications notes for updates
+
+1) In lexers/web.py remove + from (r'[{}\[\]();.]+', Punctuation),
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/__init__.py
new file mode 100644
index 0000000..b641bb1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/__init__.py
@@ -0,0 +1,22 @@
+###############################################################################
+# Name: __init__.py #
+# Purpose: Puts external modules in the namespace #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+"""External Module Package
+Modules that Editra depends on that are where not developed for the project but
+are distributed with it, either because of slight customizations made to them
+or to reduce what is needed to be installed when installing Editra.
+
+@note: modules in this directory are dependancies and addons that are not
+ part of the core code.
+
+"""
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: __init__.py 52855 2008-03-27 14:53:06Z CJP $"
+__revision__ = "$Revision: 52855 $"
+
+__all__ = ['ez_setup', 'pkg_resources', 'events', 'flatnotebook']
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/decorlib.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/decorlib.py
new file mode 100644
index 0000000..de0d06c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/decorlib.py
@@ -0,0 +1,105 @@
+"""
+Collection of helpful decorator methods
+
+"""
+
+__all__ = ['anythread',]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import threading
+
+#-----------------------------------------------------------------------------#
+
+#
+# <Found on PyPi: License: Public Domain>
+# Author: Ryan Kelly
+#
+# wxAnyThread: allow methods on wxPython objects to be called from any thread
+#
+# In wxPython, methods that alter the state of the GUI are only safe to call from
+# the thread running the main event loop. Other threads must typically post
+# events to the GUI thread instead of invoking methods directly.
+#
+# While there are builtin shortcuts for this (e.g. wx.CallAfter) they do not
+# capture the full semantics of a function call. This module provides an easy
+# way to invoke methods from any thread *transparently*, propagating return
+# values and exceptions back to the calling thread.
+#
+# The main interface is a decorator named "anythread", which can be applied
+# to methods to make them safe to call from any thread, like so:
+#
+# class MyFrame(wx.Frame):
+#
+# @anythread
+# def ShowFancyStuff():
+# dlg = MyQueryDialog(self,"Enter some data")
+# if dlg.ShowModal() == wx.ID_OK:
+# resp = dlg.GetResponse()
+# return int(resp)
+# else:
+# raise NoDataEnteredError()
+#
+# The ShowFancyStuff method can now be directly invoked from any thread.
+# The calling thread will block while the main GUI thread shows the dialog,
+# and will then receive a return value or exception as appropriate.
+#
+
+_EVT_INVOKE_METHOD = wx.NewEventType()
+
+class MethodInvocationEvent(wx.PyEvent):
+ """Event fired to the GUI thread indicating a method invocation."""
+ def __init__(self, func, args, kwds):
+ wx.PyEvent.__init__(self)
+ self.SetEventType(_EVT_INVOKE_METHOD)
+ self.func = func
+ self.args = args
+ self.kwds = kwds
+ # The calling thread will block on this semaphore, which the GUI
+ # thread will release when the results are available.
+ # TODO: how expensive are these to create? Should we re-use them?
+ self.blocker = threading.Semaphore(0)
+
+ def invoke(self):
+ wx.PostEvent(self.args[0], self)
+ self.blocker.acquire()
+ try:
+ return self.result
+ except AttributeError:
+ raise self.exception
+
+ def process(self):
+ try:
+ self.result = self.func(*self.args, **self.kwds)
+ except Exception, e:
+ self.exception = e
+ self.blocker.release()
+
+def handler(evt):
+ evt.process()
+
+def anythread(func):
+ """Method decorator allowing call from any thread.
+ The method is replaced by one that posts a MethodInvocationEvent to the
+ object, then blocks waiting for it to be completed. The target object
+ if automatically connected to the _EVT_INVOKE_METHOD event if it wasn't
+ alread connected.
+
+ """
+ def invoker(*args, **kwds):
+ if wx.Thread_IsMain():
+ return func(*args, **kwds)
+ else:
+ self = args[0]
+ if not hasattr(self, "_AnyThread__connected"):
+ self.Connect(-1, -1, _EVT_INVOKE_METHOD,handler)
+ self._AnyThread__connected = True
+ evt = MethodInvocationEvent(func, args, kwds)
+ return evt.invoke()
+
+ invoker.__name__ = func.__name__
+ invoker.__doc__ = func.__doc__
+ return invoker
+
+#-----------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/embeddedimage.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/embeddedimage.py
new file mode 100644
index 0000000..8fb9cc6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/embeddedimage.py
@@ -0,0 +1,69 @@
+#----------------------------------------------------------------------
+# Name: wx.lib.embeddedimage
+# Purpose: Defines a class used for embedding PNG images in Python
+# code. The primary method of using this module is via
+# the code generator in wx.tools.img2py.
+#
+# Author: Anthony Tuininga
+#
+# Created: 26-Nov-2007
+# RCS-ID: $Id: embeddedimage.py 51067 2008-01-07 09:01:14Z CJP $
+# Copyright: (c) 2007 by Anthony Tuininga
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import base64
+import cStringIO
+import wx
+
+class PyEmbeddedImage(object):
+ """
+ PyEmbeddedImage is primarily intended to be used by code generated
+ by img2py as a means of embedding image data in a python module so
+ the image can be used at runtime without needing to access the
+ image from an image file. This makes distributing icons and such
+ that an application uses simpler since tools like py2exe will
+ automatically bundle modules that are imported, and the
+ application doesn't have to worry about how to locate the image
+ files on the user's filesystem.
+
+ The class can also be used for image data that may be acquired
+ from some other source at runtime, such as over the network or
+ from a database. In this case pass False for isBase64 (unless the
+ data actually is base64 encoded.) Any image type that
+ wx.ImageFromStream can handle should be okay.
+ """
+
+ def __init__(self, data, isBase64=True):
+ self.data = data
+ self.isBase64 = isBase64
+
+ def GetBitmap(self):
+ return wx.BitmapFromImage(self.GetImage())
+
+ def GetData(self):
+ return self.data
+
+ def GetIcon(self):
+ icon = wx.EmptyIcon()
+ icon.CopyFromBitmap(self.GetBitmap())
+ return icon
+
+ def GetImage(self):
+ data = self.data
+ if self.isBase64:
+ data = base64.b64decode(self.data)
+ stream = cStringIO.StringIO(data)
+ return wx.ImageFromStream(stream)
+
+ # added for backwards compatibility
+ getBitmap = GetBitmap
+ getData = GetData
+ getIcon = GetIcon
+ getImage = GetImage
+
+ # define properties, for convenience
+ Bitmap = property(GetBitmap)
+ Icon = property(GetIcon)
+ Image = property(GetImage)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/events.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/events.py
new file mode 100644
index 0000000..f0312ad
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/events.py
@@ -0,0 +1,128 @@
+#----------------------------------------------------------------------
+# Name: wxblox/events.py
+# Purpose: These mixins implement a push and pop menu/UI update event
+# handler system at the wx.App level. This is useful for resolving
+# cases where multiple views may want to respond to an event
+# (say, wx.ID_COPY) and where you also want a "default" handler
+# for the event (and UI update status) when there is no active
+# view which wishes to handle the event.
+#
+# Author: Kevin Ollivier
+#
+# Created: -Mar-
+# Copyright: (c) Kevin Ollivier
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import sys, os
+import wx
+
+class AppEventManager:
+ ui_events = [
+ wx.ID_NEW, wx.ID_OPEN, wx.ID_CLOSE_ALL, wx.ID_CLOSE,
+ wx.ID_REVERT, wx.ID_SAVE, wx.ID_SAVEAS, wx.ID_UNDO,
+ wx.ID_REDO, wx.ID_PRINT, wx.ID_PRINT_SETUP, wx.ID_PREVIEW,
+ wx.ID_EXIT
+ ]
+
+ def __init__(self):
+ pass
+
+ def RegisterEvents(self):
+ app = wx.GetApp()
+ #app.AddHandlerForID(wx.ID_EXIT, self.OnExit)
+ #app.AddHandlerForID(wx.ID_ABOUT, self.OnAbout)
+
+ for eventID in self.ui_events:
+ app.AddHandlerForID(eventID, self.ProcessEvent)
+ app.AddUIHandlerForID(eventID, self.ProcessUpdateUIEvent)
+
+class AppEventHandlerMixin:
+ """
+ The purpose of the AppEventHandlerMixin is to provide a centralized
+ location to manage menu and toolbar events. In an IDE which may have
+ any number of file editors and services open that may want to respond
+ to certain menu and toolbar events (e.g. copy, paste, select all),
+ we need this to efficiently make sure that the right handler is handling
+ the event.
+
+ To work with this system, views must call
+ Add(UI)HandlerForID(ID, handlerFunc)
+ in their EVT_SET_FOCUS handler, and call Remove(UI)HandlerForID(ID) in their
+ EVT_KILL_FOCUS handler.
+ """
+
+ def __init__(self):
+ self.handlers = {}
+ self.uihandlers = {}
+
+ # When a view changes the handler, move the old one here.
+ # Then "pop" the handler when the view loses the focus
+ self.pushed_handlers = {}
+ self.pushed_uihandlers = {}
+
+ def AddHandlerForIDs(self, eventID_list, handlerFunc):
+ for eventID in eventID_list:
+ self.AddHandlerForID(eventID, handlerFunc)
+
+ def AddHandlerForID(self, eventID, handlerFunc):
+ self.Bind(wx.EVT_MENU, self.HandleEvent, id=eventID)
+
+ if eventID in self.handlers:
+ self.pushed_handlers[eventID] = self.handlers[eventID]
+
+ self.handlers[eventID] = handlerFunc
+
+ def AddUIHandlerForID(self, eventID, handlerFunc):
+ self.Bind(wx.EVT_UPDATE_UI, self.HandleUpdateUIEvent, id=eventID)
+
+ if eventID in self.uihandlers:
+ self.pushed_uihandlers[eventID] = self.uihandlers[eventID]
+
+ self.uihandlers[eventID] = handlerFunc
+
+ def RemoveHandlerForIDs(self, eventID_list):
+ for eventID in eventID_list:
+ self.RemoveHandlerForID(eventID)
+
+ def RemoveHandlerForID(self, eventID):
+ self.Unbind(wx.EVT_MENU, id=eventID)
+ self.handlers[eventID] = None
+
+ if eventID in self.pushed_handlers:
+ self.handlers[eventID] = self.pushed_handlers[eventID]
+
+ def RemoveUIHandlerForID(self, eventID):
+ self.Unbind(wx.EVT_UPDATE_UI, id=eventID)
+ self.uihandlers[eventID] = None
+
+ if eventID in self.pushed_uihandlers:
+ self.uihandlers[eventID] = self.pushed_uihandlers[eventID]
+
+ def HandleEvent(self, event):
+ e_id = event.GetId()
+ if e_id in self.handlers:
+ handler = self.handlers[e_id]
+ try:
+ if handler:
+ return handler(event)
+ except wx.PyDeadObjectError:
+ self.RemoveHandlerForID(e_id)
+ else:
+ event.Skip()
+
+ return False
+
+ def HandleUpdateUIEvent(self, event):
+ e_id = event.GetId()
+ if e_id in self.uihandlers:
+ handler = self.uihandlers[e_id]
+ try:
+ if handler:
+ return handler(event)
+ except wx.PyDeadObjectError:
+ self.RemoveUIHandlerForID(e_id)
+ else:
+ event.Skip()
+
+ return False
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/ez_setup.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/ez_setup.py
new file mode 100644
index 0000000..38c09c6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/ez_setup.py
@@ -0,0 +1,228 @@
+#!python
+"""Bootstrap setuptools installation
+
+If you want to use setuptools in your package's setup.py, just include this
+file in the same directory with it, and add this to the top of your setup.py::
+
+ from ez_setup import use_setuptools
+ use_setuptools()
+
+If you want to require a specific version of setuptools, set a download
+mirror, or use an alternate download directory, you can do so by supplying
+the appropriate options to ``use_setuptools()``.
+
+This file can also be run as a script to install or upgrade setuptools.
+"""
+import sys
+DEFAULT_VERSION = "0.6c5"
+DEFAULT_URL = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3]
+
+md5_data = {
+ 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
+ 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
+ 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
+ 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
+ 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
+ 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
+ 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
+ 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
+ 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
+ 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
+ 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
+ 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
+ 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
+ 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
+ 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
+ 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
+ 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
+ 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
+ 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
+ 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
+ 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
+}
+
+import sys, os
+
+def _validate_md5(egg_name, data):
+ if egg_name in md5_data:
+ from md5 import md5
+ digest = md5(data).hexdigest()
+ if digest != md5_data[egg_name]:
+ print >>sys.stderr, (
+ "md5 validation of %s failed! (Possible download problem?)"
+ % egg_name
+ )
+ sys.exit(2)
+ return data
+
+
+def use_setuptools(
+ version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
+ download_delay=15
+):
+ """Automatically find/download setuptools and make it available on sys.path
+
+ `version` should be a valid setuptools version number that is available
+ as an egg for download under the `download_base` URL (which should end with
+ a '/'). `to_dir` is the directory where setuptools will be downloaded, if
+ it is not already available. If `download_delay` is specified, it should
+ be the number of seconds that will be paused before initiating a download,
+ should one be required. If an older version of setuptools is installed,
+ this routine will print a message to ``sys.stderr`` and raise SystemExit in
+ an attempt to abort the calling script.
+ """
+ try:
+ import setuptools
+ if setuptools.__version__ == '0.0.1':
+ print >>sys.stderr, (
+ "You have an obsolete version of setuptools installed. Please\n"
+ "remove it from your system entirely before rerunning this script."
+ )
+ sys.exit(2)
+ except ImportError:
+ egg = download_setuptools(version, download_base, to_dir, download_delay)
+ sys.path.insert(0, egg)
+ import setuptools; setuptools.bootstrap_install_from = egg
+
+ import pkg_resources
+ try:
+ pkg_resources.require("setuptools>="+version)
+
+ except pkg_resources.VersionConflict, e:
+ # XXX could we install in a subprocess here?
+ print >>sys.stderr, (
+ "The required version of setuptools (>=%s) is not available, and\n"
+ "can't be installed while this script is running. Please install\n"
+ " a more recent version first.\n\n(Currently using %r)"
+ ) % (version, e.args[0])
+ sys.exit(2)
+
+def download_setuptools(
+ version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
+ delay = 15
+):
+ """Download setuptools from a specified location and return its filename
+
+ `version` should be a valid setuptools version number that is available
+ as an egg for download under the `download_base` URL (which should end
+ with a '/'). `to_dir` is the directory where the egg will be downloaded.
+ `delay` is the number of seconds to pause before an actual download attempt.
+ """
+ import urllib2, shutil
+ egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
+ url = download_base + egg_name
+ saveto = os.path.join(to_dir, egg_name)
+ src = dst = None
+ if not os.path.exists(saveto): # Avoid repeated downloads
+ try:
+ from distutils import log
+ if delay:
+ log.warn("""
+---------------------------------------------------------------------------
+This script requires setuptools version %s to run (even to display
+help). I will attempt to download it for you (from
+%s), but
+you may need to enable firewall access for this script first.
+I will start the download in %d seconds.
+
+(Note: if this machine does not have network access, please obtain the file
+
+ %s
+
+and place it in this directory before rerunning this script.)
+---------------------------------------------------------------------------""",
+ version, download_base, delay, url
+ ); from time import sleep; sleep(delay)
+ log.warn("Downloading %s", url)
+ src = urllib2.urlopen(url)
+ # Read/write all in one block, so we don't create a corrupt file
+ # if the download is interrupted.
+ data = _validate_md5(egg_name, src.read())
+ dst = open(saveto,"wb"); dst.write(data)
+ finally:
+ if src: src.close()
+ if dst: dst.close()
+ return os.path.realpath(saveto)
+
+def main(argv, version=DEFAULT_VERSION):
+ """Install or upgrade setuptools and EasyInstall"""
+
+ try:
+ import setuptools
+ except ImportError:
+ egg = None
+ try:
+ egg = download_setuptools(version, delay=0)
+ sys.path.insert(0,egg)
+ from setuptools.command.easy_install import main
+ return main(list(argv)+[egg]) # we're done here
+ finally:
+ if egg and os.path.exists(egg):
+ os.unlink(egg)
+ else:
+ if setuptools.__version__ == '0.0.1':
+ # tell the user to uninstall obsolete version
+ use_setuptools(version)
+
+ req = "setuptools>="+version
+ import pkg_resources
+ try:
+ pkg_resources.require(req)
+ except pkg_resources.VersionConflict:
+ try:
+ from setuptools.command.easy_install import main
+ except ImportError:
+ from easy_install import main
+ main(list(argv)+[download_setuptools(delay=0)])
+ sys.exit(0) # try to force an exit
+ else:
+ if argv:
+ from setuptools.command.easy_install import main
+ main(argv)
+ else:
+ print "Setuptools version",version,"or greater has been installed."
+ print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
+
+
+
+def update_md5(filenames):
+ """Update our built-in md5 registry"""
+
+ import re
+ from md5 import md5
+
+ for name in filenames:
+ base = os.path.basename(name)
+ f = open(name,'rb')
+ md5_data[base] = md5(f.read()).hexdigest()
+ f.close()
+
+ data = [" %r: %r,\n" % it for it in md5_data.items()]
+ data.sort()
+ repl = "".join(data)
+
+ import inspect
+ srcfile = inspect.getsourcefile(sys.modules[__name__])
+ f = open(srcfile, 'rb'); src = f.read(); f.close()
+
+ match = re.search("\nmd5_data = {\n([^}]+)}", src)
+ if not match:
+ print >>sys.stderr, "Internal error!"
+ sys.exit(2)
+
+ src = src[:match.start(1)] + repl + src[match.end(1):]
+ f = open(srcfile,'w')
+ f.write(src)
+ f.close()
+
+
+if __name__=='__main__':
+ if len(sys.argv)>2 and sys.argv[1]=='--md5update':
+ update_md5(sys.argv[2:])
+ else:
+ main(sys.argv[1:])
+
+
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/flatnotebook.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/flatnotebook.py
new file mode 100644
index 0000000..bf22bc9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/flatnotebook.py
@@ -0,0 +1,4987 @@
+# --------------------------------------------------------------------------- #
+# FLATNOTEBOOK Widget wxPython IMPLEMENTATION
+#
+# Original C++ Code From Eran. You Can Find It At:
+#
+# http://wxforum.shadonet.com/viewtopic.php?t=5761&start=0
+#
+# License: wxWidgets license
+#
+#
+# Python Code By:
+#
+# Andrea Gavana, @ 02 Oct 2006
+# Latest Revision: 22 Nov 2007, 14.00 GMT
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@gmail.com
+# gavana@kpo.kz
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+"""
+The FlatNotebook is a full implementation of the wx.Notebook, and designed to be
+a drop-in replacement for wx.Notebook. The API functions are similar so one can
+expect the function to behave in the same way.
+
+Some features:
+
+ - The buttons are highlighted a la Firefox style
+ - The scrolling is done for bulks of tabs (so, the scrolling is faster and better)
+ - The buttons area is never overdrawn by tabs (unlike many other implementations I saw)
+ - It is a generic control
+ - Currently there are 5 differnt styles - VC8, VC 71, Standard, Fancy and Firefox 2;
+ - Mouse middle click can be used to close tabs
+ - A function to add right click menu for tabs (simple as SetRightClickMenu)
+ - All styles has bottom style as well (they can be drawn in the bottom of screen)
+ - An option to hide 'X' button or navigation buttons (separately)
+ - Gradient coloring of the selected tabs and border
+ - Support for drag 'n' drop of tabs, both in the same notebook or to another notebook
+ - Possibility to have closing button on the active tab directly
+ - Support for disabled tabs
+ - Colours for active/inactive tabs, and captions
+ - Background of tab area can be painted in gradient (VC8 style only)
+ - Colourful tabs - a random gentle colour is generated for each new tab (very cool, VC8 style only)
+
+
+And much more.
+
+
+License And Version:
+
+FlatNotebook Is Freeware And Distributed Under The wxPython License.
+
+Latest Revision: Andrea Gavana @ 22 Nov 2007, 14.00 GMT
+
+Version 2.4.
+
+@undocumented: FNB_HEIGHT_SPACER, VERTICAL_BORDER_PADDING, VC8_SHAPE_LEN,
+ wxEVT*, left_arrow_*, right_arrow*, x_button*, down_arrow*,
+ FNBDragInfo, FNBDropTarget, GetMondrian*
+"""
+
+__docformat__ = "epytext"
+
+
+#----------------------------------------------------------------------
+# Beginning Of FLATNOTEBOOK wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+import random
+import math
+import weakref
+import cPickle
+
+# Used on OSX to get access to carbon api constants
+if wx.Platform == '__WXMAC__':
+ import Carbon.Appearance
+
+# Check for the new method in 2.7 (not present in 2.6.3.3)
+if wx.VERSION_STRING < "2.7":
+ wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point)
+
+FNB_HEIGHT_SPACER = 10
+
+# Use Visual Studio 2003 (VC7.1) style for tabs
+FNB_VC71 = 1
+"""Use Visual Studio 2003 (VC7.1) style for tabs"""
+
+# Use fancy style - square tabs filled with gradient coloring
+FNB_FANCY_TABS = 2
+"""Use fancy style - square tabs filled with gradient coloring"""
+
+# Draw thin border around the page
+FNB_TABS_BORDER_SIMPLE = 4
+"""Draw thin border around the page"""
+
+# Do not display the 'X' button
+FNB_NO_X_BUTTON = 8
+"""Do not display the 'X' button"""
+
+# Do not display the Right / Left arrows
+FNB_NO_NAV_BUTTONS = 16
+"""Do not display the right/left arrows"""
+
+# Use the mouse middle button for cloing tabs
+FNB_MOUSE_MIDDLE_CLOSES_TABS = 32
+"""Use the mouse middle button for cloing tabs"""
+
+# Place tabs at bottom - the default is to place them
+# at top
+FNB_BOTTOM = 64
+"""Place tabs at bottom - the default is to place them at top"""
+
+# Disable dragging of tabs
+FNB_NODRAG = 128
+"""Disable dragging of tabs"""
+
+# Use Visual Studio 2005 (VC8) style for tabs
+FNB_VC8 = 256
+"""Use Visual Studio 2005 (VC8) style for tabs"""
+
+# Firefox 2 tabs style
+FNB_FF2 = 131072
+"""Use Firefox 2 style for tabs"""
+
+# Place 'X' on a tab
+FNB_X_ON_TAB = 512
+"""Place 'X' close button on the active tab"""
+
+FNB_BACKGROUND_GRADIENT = 1024
+"""Use gradients to paint the tabs background"""
+
+FNB_COLORFUL_TABS = 2048
+"""Use colourful tabs (VC8 style only)"""
+
+# Style to close tab using double click - styles 1024, 2048 are reserved
+FNB_DCLICK_CLOSES_TABS = 4096
+"""Style to close tab using double click"""
+
+FNB_SMART_TABS = 8192
+"""Use Smart Tabbing, like Alt+Tab on Windows"""
+
+FNB_DROPDOWN_TABS_LIST = 16384
+"""Use a dropdown menu on the left in place of the arrows"""
+
+FNB_ALLOW_FOREIGN_DND = 32768
+"""Allows drag 'n' drop operations between different L{FlatNotebook}s"""
+
+FNB_HIDE_ON_SINGLE_TAB = 65536
+"""Hides the Page Container when there is one or fewer tabs"""
+
+VERTICAL_BORDER_PADDING = 4
+
+# Button size is a 16x16 xpm bitmap
+BUTTON_SPACE = 16
+"""Button size is a 16x16 xpm bitmap"""
+
+VC8_SHAPE_LEN = 16
+
+MASK_COLOR = wx.Colour(0, 128, 128)
+"""Mask colour for the arrow bitmaps"""
+
+# Button status
+FNB_BTN_PRESSED = 2
+"""Navigation button is pressed"""
+FNB_BTN_HOVER = 1
+"""Navigation button is hovered"""
+FNB_BTN_NONE = 0
+"""No navigation"""
+
+# Hit Test results
+FNB_TAB = 1 # On a tab
+"""Indicates mouse coordinates inside a tab"""
+FNB_X = 2 # On the X button
+"""Indicates mouse coordinates inside the I{X} region"""
+FNB_TAB_X = 3 # On the 'X' button (tab's X button)
+"""Indicates mouse coordinates inside the I{X} region in a tab"""
+FNB_LEFT_ARROW = 4 # On the rotate left arrow button
+"""Indicates mouse coordinates inside the left arrow region"""
+FNB_RIGHT_ARROW = 5 # On the rotate right arrow button
+"""Indicates mouse coordinates inside the right arrow region"""
+FNB_DROP_DOWN_ARROW = 6 # On the drop down arrow button
+"""Indicates mouse coordinates inside the drop down arrow region"""
+FNB_NOWHERE = 0 # Anywhere else
+"""Indicates mouse coordinates not on any tab of the notebook"""
+
+FNB_DEFAULT_STYLE = FNB_MOUSE_MIDDLE_CLOSES_TABS | FNB_HIDE_ON_SINGLE_TAB
+"""L{FlatNotebook} default style"""
+
+# FlatNotebook Events:
+# wxEVT_FLATNOTEBOOK_PAGE_CHANGED: Event Fired When You Switch Page;
+# wxEVT_FLATNOTEBOOK_PAGE_CHANGING: Event Fired When You Are About To Switch
+# Pages, But You Can Still "Veto" The Page Changing By Avoiding To Call
+# event.Skip() In Your Event Handler;
+# wxEVT_FLATNOTEBOOK_PAGE_CLOSING: Event Fired When A Page Is Closing, But
+# You Can Still "Veto" The Page Changing By Avoiding To Call event.Skip()
+# In Your Event Handler;
+# wxEVT_FLATNOTEBOOK_PAGE_CLOSED: Event Fired When A Page Is Closed.
+# wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU: Event Fired When A Menu Pops-up In A Tab.
+
+wxEVT_FLATNOTEBOOK_PAGE_CHANGED = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
+wxEVT_FLATNOTEBOOK_PAGE_CHANGING = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
+wxEVT_FLATNOTEBOOK_PAGE_CLOSING = wx.NewEventType()
+wxEVT_FLATNOTEBOOK_PAGE_CLOSED = wx.NewEventType()
+wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.NewEventType()
+
+#-----------------------------------#
+# FlatNotebookEvent
+#-----------------------------------#
+
+EVT_FLATNOTEBOOK_PAGE_CHANGED = wx.EVT_NOTEBOOK_PAGE_CHANGED
+"""Notify client objects when the active page in L{FlatNotebook}
+has changed."""
+EVT_FLATNOTEBOOK_PAGE_CHANGING = wx.EVT_NOTEBOOK_PAGE_CHANGING
+"""Notify client objects when the active page in L{FlatNotebook}
+is about to change."""
+EVT_FLATNOTEBOOK_PAGE_CLOSING = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, 1)
+"""Notify client objects when a page in L{FlatNotebook} is closing."""
+EVT_FLATNOTEBOOK_PAGE_CLOSED = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, 1)
+"""Notify client objects when a page in L{FlatNotebook} has been closed."""
+EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, 1)
+"""Notify client objects when a pop-up menu should appear next to a tab."""
+
+
+# Some icons in XPM format
+
+left_arrow_disabled_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #555555",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````.```````",
+ "```````..```````",
+ "``````.`.```````",
+ "`````.``.```````",
+ "````.```.```````",
+ "`````.``.```````",
+ "``````.`.```````",
+ "```````..```````",
+ "````````.```````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+x_button_pressed_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #9e9ede",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.############.`",
+ "`.############.`",
+ "`.###aa####aa#.`",
+ "`.####aa##aa##.`",
+ "`.#####aaaa###.`",
+ "`.######aa####.`",
+ "`.#####aaaa###.`",
+ "`.####aa##aa##.`",
+ "`.###aa####aa#.`",
+ "`.############.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+
+left_arrow_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #555555",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````.```````",
+ "```````..```````",
+ "``````...```````",
+ "`````....```````",
+ "````.....```````",
+ "`````....```````",
+ "``````...```````",
+ "```````..```````",
+ "````````.```````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+x_button_hilite_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #c9dafb",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.############.`",
+ "`.##aa####aa##.`",
+ "`.###aa##aa###.`",
+ "`.####aaaa####.`",
+ "`.#####aa#####.`",
+ "`.####aaaa####.`",
+ "`.###aa##aa###.`",
+ "`.##aa####aa##.`",
+ "`.############.`",
+ "`.############.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+x_button_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #555555",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````..````..````",
+ "`````..``..`````",
+ "``````....``````",
+ "```````..```````",
+ "``````....``````",
+ "`````..``..`````",
+ "````..````..````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+left_arrow_pressed_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #9e9ede",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.############.`",
+ "`.#######a####.`",
+ "`.######aa####.`",
+ "`.#####aaa####.`",
+ "`.####aaaa####.`",
+ "`.###aaaaa####.`",
+ "`.####aaaa####.`",
+ "`.#####aaa####.`",
+ "`.######aa####.`",
+ "`.#######a####.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+left_arrow_hilite_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #c9dafb",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.######a#####.`",
+ "`.#####aa#####.`",
+ "`.####aaa#####.`",
+ "`.###aaaa#####.`",
+ "`.##aaaaa#####.`",
+ "`.###aaaa#####.`",
+ "`.####aaa#####.`",
+ "`.#####aa#####.`",
+ "`.######a#####.`",
+ "`.############.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+right_arrow_disabled_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #555555",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "```````.````````",
+ "```````..```````",
+ "```````.`.``````",
+ "```````.``.`````",
+ "```````.```.````",
+ "```````.``.`````",
+ "```````.`.``````",
+ "```````..```````",
+ "```````.````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+right_arrow_hilite_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #c9dafb",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.####a#######.`",
+ "`.####aa######.`",
+ "`.####aaa#####.`",
+ "`.####aaaa####.`",
+ "`.####aaaaa###.`",
+ "`.####aaaa####.`",
+ "`.####aaa#####.`",
+ "`.####aa######.`",
+ "`.####a#######.`",
+ "`.############.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+right_arrow_pressed_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #9e9ede",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "`..............`",
+ "`.############.`",
+ "`.############.`",
+ "`.#####a######.`",
+ "`.#####aa#####.`",
+ "`.#####aaa####.`",
+ "`.#####aaaa###.`",
+ "`.#####aaaaa##.`",
+ "`.#####aaaa###.`",
+ "`.#####aaa####.`",
+ "`.#####aa#####.`",
+ "`.#####a######.`",
+ "`..............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+
+right_arrow_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #555555",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "```````.````````",
+ "```````..```````",
+ "```````...``````",
+ "```````....`````",
+ "```````.....````",
+ "```````....`````",
+ "```````...``````",
+ "```````..```````",
+ "```````.````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+down_arrow_hilite_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #c9dafb",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "``.............`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.#aaaaaaaaa#.`",
+ "``.##aaaaaaa##.`",
+ "``.###aaaaa###.`",
+ "``.####aaa####.`",
+ "``.#####a#####.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+down_arrow_pressed_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #4766e0",
+ "# c #9e9ede",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "``.............`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.###########.`",
+ "``.#aaaaaaaaa#.`",
+ "``.##aaaaaaa##.`",
+ "``.###aaaaa###.`",
+ "``.####aaa####.`",
+ "``.#####a#####.`",
+ "``.###########.`",
+ "``.............`",
+ "````````````````",
+ "````````````````"
+ ]
+
+
+down_arrow_xpm = [
+ " 16 16 8 1",
+ "` c #008080",
+ ". c #000000",
+ "# c #000000",
+ "a c #000000",
+ "b c #000000",
+ "c c #000000",
+ "d c #000000",
+ "e c #000000",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````.........```",
+ "`````.......````",
+ "``````.....`````",
+ "```````...``````",
+ "````````.```````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````",
+ "````````````````"
+ ]
+
+
+#----------------------------------------------------------------------
+def GetMondrianData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
+\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00qID\
+ATX\x85\xed\xd6;\n\x800\x10E\xd1{\xc5\x8d\xb9r\x97\x16\x0b\xad$\x8a\x82:\x16\
+o\xda\x84pB2\x1f\x81Fa\x8c\x9c\x08\x04Z{\xcf\xa72\xbcv\xfa\xc5\x08 \x80r\x80\
+\xfc\xa2\x0e\x1c\xe4\xba\xfaX\x1d\xd0\xde]S\x07\x02\xd8>\xe1wa-`\x9fQ\xe9\
+\x86\x01\x04\x10\x00\\(Dk\x1b-\x04\xdc\x1d\x07\x14\x98;\x0bS\x7f\x7f\xf9\x13\
+\x04\x10@\xf9X\xbe\x00\xc9 \x14K\xc1<={\x00\x00\x00\x00IEND\xaeB`\x82'
+
+
+def GetMondrianBitmap():
+ return wx.BitmapFromImage(GetMondrianImage().Scale(16, 16))
+
+
+def GetMondrianImage():
+ import cStringIO
+ stream = cStringIO.StringIO(GetMondrianData())
+ return wx.ImageFromStream(stream)
+
+
+def GetMondrianIcon():
+ icon = wx.EmptyIcon()
+ icon.CopyFromBitmap(GetMondrianBitmap())
+ return icon
+#----------------------------------------------------------------------
+
+
+def LightColour(color, percent):
+ """ Brighten input colour by percent. """
+
+ end_color = wx.WHITE
+
+ rd = end_color.Red() - color.Red()
+ gd = end_color.Green() - color.Green()
+ bd = end_color.Blue() - color.Blue()
+
+ high = 100
+
+ # We take the percent way of the color from color -. white
+ i = percent
+ r = color.Red() + ((i*rd*100)/high)/100
+ g = color.Green() + ((i*gd*100)/high)/100
+ b = color.Blue() + ((i*bd*100)/high)/100
+ return wx.Colour(r, g, b)
+
+
+def RandomColour():
+ """ Creates a random colour. """
+
+ r = random.randint(0, 255) # Random value betweem 0-255
+ g = random.randint(0, 255) # Random value betweem 0-255
+ b = random.randint(0, 255) # Random value betweem 0-255
+
+ return wx.Colour(r, g, b)
+
+
+def PaintStraightGradientBox(dc, rect, startColor, endColor, vertical=True):
+ """ Draws a gradient colored box from startColor to endColor. """
+ rd = endColor.Red() - startColor.Red()
+ gd = endColor.Green() - startColor.Green()
+ bd = endColor.Blue() - startColor.Blue()
+
+ # Save the current pen and brush
+ savedPen = dc.GetPen()
+ savedBrush = dc.GetBrush()
+ if vertical:
+ high = rect.GetHeight()-1
+ else:
+ high = rect.GetWidth()-1
+
+ if high < 1:
+ return
+
+ for i in xrange(high+1):
+
+ r = startColor.Red() + ((i*rd*100)/high)/100
+ g = startColor.Green() + ((i*gd*100)/high)/100
+ b = startColor.Blue() + ((i*bd*100)/high)/100
+
+ p = wx.Pen(wx.Colour(r, g, b))
+ dc.SetPen(p)
+
+ if vertical:
+ # TODO: Serious problem and potentially bug in wxPython2.8.9.2
+ # some odd cases can cause the width attribute to be an
+ # empty tuple!! The repr and GetWidth however have the
+ # correct value.
+ dc.DrawLine(rect.x, rect.y+i, rect.x+rect.GetWidth(), rect.y+i)
+ else:
+ dc.DrawLine(rect.x+i, rect.y, rect.x+i, rect.y+rect.height)
+
+ # Restore the pen and brush
+ dc.SetPen(savedPen)
+ dc.SetBrush(savedBrush)
+
+# -----------------------------------------------------------------------------
+# Util functions
+# -----------------------------------------------------------------------------
+
+def DrawButton(dc, rect, focus, upperTabs):
+
+ # Define the rounded rectangle base on the given rect
+ # we need an array of 9 points for it
+ regPts = [wx.Point() for indx in xrange(9)]
+
+ if focus:
+ if upperTabs:
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*8)
+ rightPt = wx.Point(rect.x + rect.GetWidth() - 2, rect.y + (rect.height / 10)*8)
+ else:
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*5)
+ rightPt = wx.Point(rect.x + rect.GetWidth() - 2, rect.y + (rect.height / 10)*5)
+ else:
+ leftPt = wx.Point(rect.x, rect.y + (rect.height / 2))
+ rightPt = wx.Point(rect.x + rect.GetWidth() - 2, rect.y + (rect.height / 2))
+
+ # Define the top region
+ top = wx.RectPP(rect.GetTopLeft(), rightPt)
+ bottom = wx.RectPP(leftPt, rect.GetBottomRight())
+
+ topEndColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+
+ if wx.Platform != '__WXGTK__':
+ # This type of gradient causes visibility issues with some dark
+ # GTK themes so don't use on GTK for now.
+ topStartColor = wx.WHITE
+ if not focus:
+ topStartColor = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 50)
+
+ bottomStartColor = topEndColor
+ bottomEndColor = topEndColor
+ else:
+ # Make whole tab same color on gtk
+ if not focus:
+ topEndColour = LightColour(topEndColor, 30)
+ bottomEndColor = bottomStartColor = topStartColor = topEndColor
+
+ # Incase we use bottom tabs, switch the colors
+ if upperTabs:
+ if focus:
+ PaintStraightGradientBox(dc, top, topStartColor, topEndColor)
+ PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor)
+ else:
+ PaintStraightGradientBox(dc, top, topEndColor , topStartColor)
+ PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor)
+
+ else:
+ if focus:
+ PaintStraightGradientBox(dc, bottom, topEndColor, bottomEndColor)
+ PaintStraightGradientBox(dc, top,topStartColor, topStartColor)
+ else:
+ PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor)
+ PaintStraightGradientBox(dc, top, topEndColor, topStartColor)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBDropSource
+# Gives Some Custom UI Feedback during the DnD Operations
+# ---------------------------------------------------------------------------- #
+
+class FNBDropSource(wx.DropSource):
+ """
+ Give some custom UI feedback during the drag and drop operation in this
+ function. It is called on each mouse move, so your implementation must
+ not be too slow.
+ """
+
+ def __init__(self, win):
+ """ Default class constructor. Used internally. """
+
+ wx.DropSource.__init__(self, win)
+ self._win = win
+
+
+ def GiveFeedback(self, effect):
+ """ Provides user with a nice feedback when tab is being dragged. """
+
+ self._win.DrawDragHint()
+ return False
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBDragInfo
+# Stores All The Information To Allow Drag And Drop Between Different
+# FlatNotebooks.
+# ---------------------------------------------------------------------------- #
+
+class FNBDragInfo:
+
+ _map = weakref.WeakValueDictionary()
+
+ def __init__(self, container, pageindex):
+ """ Default class constructor. """
+
+ self._id = id(container)
+ FNBDragInfo._map[self._id] = container
+ self._pageindex = pageindex
+
+
+ def GetContainer(self):
+ """ Returns the L{FlatNotebook} page (usually a panel). """
+
+ return FNBDragInfo._map.get(self._id, None)
+
+
+ def GetPageIndex(self):
+ """ Returns the page index associated with a page. """
+
+ return self._pageindex
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBDropTarget
+# Simply Used To Handle The OnDrop() Method When Dragging And Dropping Between
+# Different FlatNotebooks.
+# ---------------------------------------------------------------------------- #
+
+class FNBDropTarget(wx.DropTarget):
+
+ def __init__(self, parent):
+ """ Default class constructor. """
+
+ wx.DropTarget.__init__(self)
+
+ self._parent = parent
+ self._dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook"))
+ self.SetDataObject(self._dataobject)
+
+
+ def OnData(self, x, y, dragres):
+ """ Handles the OnData() method to call the real DnD routine. """
+ try:
+ if not self.GetData():
+ return wx.DragNone
+
+ draginfo = self._dataobject.GetData()
+ drginfo = cPickle.loads(draginfo)
+
+ return self._parent.OnDropTarget(x, y, drginfo.GetPageIndex(), drginfo.GetContainer())
+ except wx.PyAssertionError:
+ return wx.DragCancel
+
+
+# ---------------------------------------------------------------------------- #
+# Class PageInfo
+# Contains parameters for every FlatNotebook page
+# ---------------------------------------------------------------------------- #
+
+class PageInfo:
+ """
+ This class holds all the information (caption, image, etc...) belonging to a
+ single tab in L{FlatNotebook}.
+ """
+
+ def __init__(self, caption="", imageindex=-1, tabangle=0, enabled=True):
+ """
+ Default Class Constructor.
+
+ Parameters:
+ @param caption: the tab caption;
+ @param imageindex: the tab image index based on the assigned (set) wx.ImageList (if any);
+ @param tabangle: the tab angle (only on standard tabs, from 0 to 15 degrees);
+ @param enabled: sets enabled or disabled the tab.
+ """
+
+ self._strCaption = caption
+ self._TabAngle = tabangle
+ self._ImageIndex = imageindex
+ self._bEnabled = enabled
+ self._pos = wx.Point(-1, -1)
+ self._size = wx.Size(-1, -1)
+ self._region = wx.Region()
+ self._xRect = wx.Rect()
+ self._color = None
+ self._hasFocus = False
+
+
+ def SetCaption(self, value):
+ """ Sets the tab caption. """
+
+ self._strCaption = value
+
+
+ def GetCaption(self):
+ """ Returns the tab caption. """
+
+ return self._strCaption
+
+
+ def SetPosition(self, value):
+ """ Sets the tab position. """
+
+ self._pos = value
+
+
+ def GetPosition(self):
+ """ Returns the tab position. """
+
+ return self._pos
+
+
+ def SetSize(self, value):
+ """ Sets the tab size. """
+
+ self._size = value
+
+
+ def GetSize(self):
+ """ Returns the tab size. """
+
+ return self._size
+
+
+ def SetTabAngle(self, value):
+ """ Sets the tab header angle (0 <= tab <= 15 degrees). """
+
+ self._TabAngle = min(45, value)
+
+
+ def GetTabAngle(self):
+ """ Returns the tab angle. """
+
+ return self._TabAngle
+
+
+ def SetImageIndex(self, value):
+ """ Sets the tab image index. """
+
+ self._ImageIndex = value
+
+
+ def GetImageIndex(self):
+ """ Returns the tab umage index. """
+
+ return self._ImageIndex
+
+
+ def GetEnabled(self):
+ """ Returns whether the tab is enabled or not. """
+
+ return self._bEnabled
+
+
+ def EnableTab(self, enabled):
+ """ Sets the tab enabled or disabled. """
+
+ self._bEnabled = enabled
+
+
+ def SetRegion(self, points=[]):
+ """ Sets the tab region. """
+
+ self._region = wx.RegionFromPoints(points)
+
+
+ def GetRegion(self):
+ """ Returns the tab region. """
+
+ return self._region
+
+
+ def SetXRect(self, xrect):
+ """ Sets the button 'X' area rect. """
+
+ self._xRect = xrect
+
+
+ def GetXRect(self):
+ """ Returns the button 'X' area rect. """
+
+ return self._xRect
+
+
+ def GetColour(self):
+ """ Returns the tab colour. """
+
+ return self._color
+
+
+ def SetColour(self, color):
+ """ Sets the tab colour. """
+
+ self._color = color
+
+
+# ---------------------------------------------------------------------------- #
+# Class FlatNotebookEvent
+# ---------------------------------------------------------------------------- #
+
+class FlatNotebookEvent(wx.PyCommandEvent):
+ """
+ This events will be sent when a EVT_FLATNOTEBOOK_PAGE_CHANGED,
+ EVT_FLATNOTEBOOK_PAGE_CHANGING, EVT_FLATNOTEBOOK_PAGE_CLOSING,
+ EVT_FLATNOTEBOOK_PAGE_CLOSED and EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU is
+ mapped in the parent.
+ """
+
+ def __init__(self, eventType, id=1, nSel=-1, nOldSel=-1):
+ """ Default class constructor. """
+
+ wx.PyCommandEvent.__init__(self, eventType, id)
+ self._eventType = eventType
+
+ self.notify = wx.NotifyEvent(eventType, id)
+
+
+ def GetNotifyEvent(self):
+ """Returns the actual wx.NotifyEvent."""
+
+ return self.notify
+
+
+ def IsAllowed(self):
+ """Returns whether the event is allowed or not."""
+
+ return self.notify.IsAllowed()
+
+
+ def Veto(self):
+ """Vetos the event."""
+
+ self.notify.Veto()
+
+
+ def Allow(self):
+ """The event is allowed."""
+
+ self.notify.Allow()
+
+
+ def SetSelection(self, nSel):
+ """ Sets event selection. """
+
+ self._selection = nSel
+
+
+ def SetOldSelection(self, nOldSel):
+ """ Sets old event selection. """
+
+ self._oldselection = nOldSel
+
+
+ def GetSelection(self):
+ """ Returns event selection. """
+
+ return self._selection
+
+
+ def GetOldSelection(self):
+ """ Returns old event selection """
+
+ return self._oldselection
+
+
+# ---------------------------------------------------------------------------- #
+# Class TabNavigatorWindow
+# ---------------------------------------------------------------------------- #
+
+class TabNavigatorWindow(wx.Dialog):
+ """
+ This class is used to create a modal dialog that enables "Smart Tabbing",
+ similar to what you would get by hitting Alt+Tab on Windows.
+ """
+
+ def __init__(self, parent=None, icon=None):
+ """ Default class constructor. Used internally."""
+
+ wx.Dialog.__init__(self, parent, wx.ID_ANY, "", style=0)
+
+ self._selectedItem = -1
+ self._indexMap = []
+ self._sel = 0
+
+ if icon is None:
+ self._bmp = GetMondrianBitmap()
+ else:
+ self._bmp = icon
+
+ sz = wx.BoxSizer(wx.VERTICAL)
+
+ self._listBox = wx.ListBox(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, 150), [], wx.LB_SINGLE | wx.NO_BORDER)
+
+ mem_dc = wx.MemoryDC()
+ mem_dc.SelectObject(wx.EmptyBitmap(1,1))
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetWeight(wx.BOLD)
+ mem_dc.SetFont(font)
+
+ panelHeight = mem_dc.GetCharHeight()
+ panelHeight += 4 # Place a spacer of 2 pixels
+
+ # Out signpost bitmap is 24 pixels
+ if panelHeight < 24:
+ panelHeight = 24
+
+ self._panel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, panelHeight))
+
+ sz.Add(self._panel)
+ sz.Add(self._listBox, 1, wx.EXPAND)
+
+ self.SetSizer(sz)
+
+ # Connect events to the list box
+ self._listBox.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+ self._listBox.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
+ self._listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnItemSelected)
+
+ # Connect paint event to the panel
+ self._panel.Bind(wx.EVT_PAINT, self.OnPanelPaint)
+ self._panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnPanelEraseBg)
+
+ self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
+ self._listBox.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
+ self.PopulateListControl(parent)
+
+ self.GetSizer().Fit(self)
+ self.GetSizer().SetSizeHints(self)
+ self.GetSizer().Layout()
+ self.Centre()
+
+ # Set focus on the list box to avoid having to click on it to change
+ # the tab selection under GTK.
+ self._listBox.SetFocus()
+
+
+ def OnKeyUp(self, event):
+ """Handles the wx.EVT_KEY_UP for the L{TabNavigatorWindow}."""
+
+ if event.GetKeyCode() == wx.WXK_CONTROL:
+ self.CloseDialog()
+
+
+ def OnNavigationKey(self, event):
+ """Handles the wx.EVT_NAVIGATION_KEY for the L{TabNavigatorWindow}. """
+
+ selected = self._listBox.GetSelection()
+ bk = self.GetParent()
+ maxItems = bk.GetPageCount()
+
+ if event.GetDirection():
+
+ # Select next page
+ if selected == maxItems - 1:
+ itemToSelect = 0
+ else:
+ itemToSelect = selected + 1
+
+ else:
+
+ # Previous page
+ if selected == 0:
+ itemToSelect = maxItems - 1
+ else:
+ itemToSelect = selected - 1
+
+ self._listBox.SetSelection(itemToSelect)
+
+
+ def PopulateListControl(self, book):
+ """Populates the L{TabNavigatorWindow} listbox with a list of tabs."""
+
+ selection = book.GetSelection()
+ count = book.GetPageCount()
+
+ self._listBox.Append(book.GetPageText(selection))
+ self._indexMap.append(selection)
+
+ prevSel = book.GetPreviousSelection()
+
+ if prevSel != wx.NOT_FOUND:
+
+ # Insert the previous selection as second entry
+ self._listBox.Append(book.GetPageText(prevSel))
+ self._indexMap.append(prevSel)
+
+ for c in xrange(count):
+
+ # Skip selected page
+ if c == selection:
+ continue
+
+ # Skip previous selected page as well
+ if c == prevSel:
+ continue
+
+ self._listBox.Append(book.GetPageText(c))
+ self._indexMap.append(c)
+
+ # Select the next entry after the current selection
+ self._listBox.SetSelection(0)
+ dummy = wx.NavigationKeyEvent()
+ dummy.SetDirection(True)
+ self.OnNavigationKey(dummy)
+
+
+ def OnItemSelected(self, event):
+ """Handles the wx.EVT_LISTBOX_DCLICK event for the wx.ListBox inside L{TabNavigatorWindow}. """
+
+ self.CloseDialog()
+
+
+ def CloseDialog(self):
+ """Closes the L{TabNavigatorWindow} dialog, setting selection in L{FlatNotebook}."""
+
+ bk = self.GetParent()
+ self._selectedItem = self._listBox.GetSelection()
+ self._sel = self._indexMap[self._selectedItem]
+ self.EndModal(wx.ID_OK)
+
+
+ def GetSelection(self):
+ """Get the index of the selected page"""
+ return self._sel
+
+
+ def OnPanelPaint(self, event):
+ """Handles the wx.EVT_PAINT event for L{TabNavigatorWindow} top panel. """
+
+ dc = wx.PaintDC(self._panel)
+ rect = self._panel.GetClientRect()
+
+ bmp = wx.EmptyBitmap(rect.GetWidth(), rect.height)
+
+ mem_dc = wx.MemoryDC()
+ mem_dc.SelectObject(bmp)
+
+ endColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+ startColour = LightColour(endColour, 50)
+ PaintStraightGradientBox(mem_dc, rect, startColour, endColour)
+
+ # Draw the caption title and place the bitmap
+ # get the bitmap optimal position, and draw it
+ bmpPt, txtPt = wx.Point(), wx.Point()
+ bmpPt.y = (rect.height - self._bmp.GetHeight())/2
+ bmpPt.x = 3
+ mem_dc.DrawBitmap(self._bmp, bmpPt.x, bmpPt.y, True)
+
+ # get the text position, and draw it
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetWeight(wx.BOLD)
+ mem_dc.SetFont(font)
+ fontHeight = mem_dc.GetCharHeight()
+
+ txtPt.x = bmpPt.x + self._bmp.GetWidth() + 4
+ txtPt.y = (rect.height - fontHeight)/2
+ mem_dc.SetTextForeground(wx.WHITE)
+ mem_dc.DrawText("Opened tabs:", txtPt.x, txtPt.y)
+ mem_dc.SelectObject(wx.NullBitmap)
+
+ dc.DrawBitmap(bmp, 0, 0)
+
+
+ def OnPanelEraseBg(self, event):
+ """Handles the wx.EVT_ERASE_BACKGROUND event for L{TabNavigatorWindow} top panel. """
+
+ pass
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBRenderer
+# ---------------------------------------------------------------------------- #
+
+class FNBRenderer:
+ """
+ Parent class for the 4 renderers defined: I{Standard}, I{VC71}, I{Fancy}
+ and I{VC8}. This class implements the common methods of all 4 renderers.
+ """
+
+ def __init__(self):
+ """Default class constructor. """
+
+ self._tabHeight = None
+
+ if wx.Platform == "__WXMAC__":
+ # Hack to get proper highlight color for focus rectangle from
+ # current theme by creating a theme brush and getting its color.
+ # kThemeBrushFocusHighlight is available on Mac OS 8.5 and higher
+ brush = wx.Brush(wx.BLACK)
+ brush.MacSetTheme(Carbon.Appearance.kThemeBrushFocusHighlight)
+ self._focusPen = wx.Pen(brush.GetColour(), 2, wx.SOLID)
+ else:
+ self._focusPen = wx.Pen(wx.BLACK, 1, wx.USER_DASH)
+ self._focusPen.SetDashes([1, 1])
+ self._focusPen.SetCap(wx.CAP_BUTT)
+
+
+ def GetLeftButtonPos(self, pageContainer):
+ """ Returns the left button position in the navigation area. """
+ return 2
+
+
+ def GetRightButtonPos(self, pageContainer):
+ """ Returns the right button position in the navigation area. """
+
+ pc = pageContainer
+ style = pc.GetParent().GetWindowStyleFlag()
+ rect = pc.GetClientRect()
+ clientWidth = rect.GetWidth()
+
+ if style & FNB_NO_X_BUTTON:
+ return clientWidth - 20
+ else:
+ return clientWidth - 36
+
+
+ def GetDropArrowButtonPos(self, pageContainer):
+ """ Returns the drop down button position in the navigation area. """
+ pc = pageContainer
+ style = pc.GetParent().GetWindowStyleFlag()
+ rect = pc.GetClientRect()
+ clientWidth = rect.GetWidth()
+
+ if style & FNB_NO_X_BUTTON and style & FNB_NO_NAV_BUTTONS:
+ return clientWidth - 20
+ elif style & FNB_NO_X_BUTTON or style & FNB_NO_NAV_BUTTONS:
+ return clientWidth - 36
+ else:
+ return clientWidth - 52
+
+
+ def GetXPos(self, pageContainer):
+ """ Returns the 'X' button position in the navigation area. """
+
+ pc = pageContainer
+ style = pc.GetParent().GetWindowStyleFlag()
+ rect = pc.GetClientRect()
+ clientWidth = rect.GetWidth()
+
+ if style & FNB_NO_X_BUTTON:
+ return clientWidth
+ else:
+ return clientWidth - 20
+
+
+ def GetButtonsAreaLength(self, pageContainer):
+ """ Returns the navigation area width. """
+
+ pc = pageContainer
+ style = pc.GetParent().GetWindowStyleFlag()
+
+ # ''
+ if style & FNB_NO_NAV_BUTTONS and style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST:
+ return 0
+
+ # 'x'
+ elif style & FNB_NO_NAV_BUTTONS and not style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST:
+ return 22
+
+ # '<>'
+ if not style & FNB_NO_NAV_BUTTONS and style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST:
+ return 53 - 16
+
+ # 'vx'
+ if style & FNB_DROPDOWN_TABS_LIST and not style & FNB_NO_X_BUTTON:
+ return 22 + 16
+
+ # 'v'
+ if style & FNB_DROPDOWN_TABS_LIST and style & FNB_NO_X_BUTTON:
+ return 22
+
+ # '<>x'
+ return 53
+
+ def DrawArrowAccordingToState(self, dc, pc, rect):
+ lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
+ PaintStraightGradientBox(dc, rect, pc._tabAreaColor, LightColour(pc._tabAreaColor, lightFactor))
+
+ def DrawLeftArrow(self, pageContainer, dc):
+ """ Draw the left navigation arrow. """
+
+ pc = pageContainer
+
+ style = pc.GetParent().GetWindowStyleFlag()
+ if style & FNB_NO_NAV_BUTTONS:
+ return
+
+ # Make sure that there are pages in the container
+ if not pc._pagesInfoVec:
+ return
+
+ # Set the bitmap according to the button status
+ if pc._nLeftButtonStatus == FNB_BTN_HOVER:
+ arrowBmp = wx.BitmapFromXPMData(left_arrow_hilite_xpm)
+ elif pc._nLeftButtonStatus == FNB_BTN_PRESSED:
+ arrowBmp = wx.BitmapFromXPMData(left_arrow_pressed_xpm)
+ else:
+ arrowBmp = wx.BitmapFromXPMData(left_arrow_xpm)
+
+ if pc._nFrom == 0:
+ # Handle disabled arrow
+ arrowBmp = wx.BitmapFromXPMData(left_arrow_disabled_xpm)
+
+ arrowBmp.SetMask(wx.Mask(arrowBmp, MASK_COLOR))
+
+ # Erase old bitmap
+ posx = self.GetLeftButtonPos(pc)
+ self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(arrowBmp, posx + 2, 6, True)
+
+
+ def DrawRightArrow(self, pageContainer, dc):
+ """ Draw the right navigation arrow. """
+
+ pc = pageContainer
+
+ style = pc.GetParent().GetWindowStyleFlag()
+ if style & FNB_NO_NAV_BUTTONS:
+ return
+
+ # Make sure that there are pages in the container
+ if not pc._pagesInfoVec:
+ return
+
+ # Set the bitmap according to the button status
+ if pc._nRightButtonStatus == FNB_BTN_HOVER:
+ arrowBmp = wx.BitmapFromXPMData(right_arrow_hilite_xpm)
+ elif pc._nRightButtonStatus == FNB_BTN_PRESSED:
+ arrowBmp = wx.BitmapFromXPMData(right_arrow_pressed_xpm)
+ else:
+ arrowBmp = wx.BitmapFromXPMData(right_arrow_xpm)
+
+ # Check if the right most tab is visible, if it is
+ # don't rotate right anymore
+ if pc._pagesInfoVec[-1].GetPosition() != wx.Point(-1, -1):
+ arrowBmp = wx.BitmapFromXPMData(right_arrow_disabled_xpm)
+
+ arrowBmp.SetMask(wx.Mask(arrowBmp, MASK_COLOR))
+
+ # erase old bitmap
+ posx = self.GetRightButtonPos(pc)
+ self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(arrowBmp, posx, 6, True)
+
+
+ def DrawDropDownArrow(self, pageContainer, dc):
+ """ Draws the drop-down arrow in the navigation area. """
+
+ pc = pageContainer
+
+ # Check if this style is enabled
+ style = pc.GetParent().GetWindowStyleFlag()
+ if not style & FNB_DROPDOWN_TABS_LIST:
+ return
+
+ # Make sure that there are pages in the container
+ if not pc._pagesInfoVec:
+ return
+
+ if pc._nArrowDownButtonStatus == FNB_BTN_HOVER:
+ downBmp = wx.BitmapFromXPMData(down_arrow_hilite_xpm)
+ elif pc._nArrowDownButtonStatus == FNB_BTN_PRESSED:
+ downBmp = wx.BitmapFromXPMData(down_arrow_pressed_xpm)
+ else:
+ downBmp = wx.BitmapFromXPMData(down_arrow_xpm)
+
+ downBmp.SetMask(wx.Mask(downBmp, MASK_COLOR))
+
+ # erase old bitmap
+ posx = self.GetDropArrowButtonPos(pc)
+ self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(downBmp, posx, 6, True)
+
+
+ def DrawX(self, pageContainer, dc):
+ """ Draw the 'X' navigation button in the navigation area. """
+
+ pc = pageContainer
+
+ # Check if this style is enabled
+ style = pc.GetParent().GetWindowStyleFlag()
+ if style & FNB_NO_X_BUTTON:
+ return
+
+ # Make sure that there are pages in the container
+ if not pc._pagesInfoVec:
+ return
+
+ # Set the bitmap according to the button status
+ if pc._nXButtonStatus == FNB_BTN_HOVER:
+ xbmp = wx.BitmapFromXPMData(x_button_hilite_xpm)
+ elif pc._nXButtonStatus == FNB_BTN_PRESSED:
+ xbmp = wx.BitmapFromXPMData(x_button_pressed_xpm)
+ else:
+ xbmp = wx.BitmapFromXPMData(x_button_xpm)
+
+ xbmp.SetMask(wx.Mask(xbmp, MASK_COLOR))
+
+ # erase old bitmap
+ posx = self.GetXPos(pc)
+ self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(xbmp, posx, 6, True)
+
+
+ def DrawTabX(self, pageContainer, dc, rect, tabIdx, btnStatus):
+ """ Draws the 'X' in the selected tab. """
+
+ pc = pageContainer
+ if not pc.HasFlag(FNB_X_ON_TAB):
+ return
+
+ # We draw the 'x' on the active tab only
+ if tabIdx != pc.GetSelection() or tabIdx < 0:
+ return
+
+ # Set the bitmap according to the button status
+
+ if btnStatus == FNB_BTN_HOVER:
+ xBmp = wx.BitmapFromXPMData(x_button_hilite_xpm)
+ elif btnStatus == FNB_BTN_PRESSED:
+ xBmp = wx.BitmapFromXPMData(x_button_pressed_xpm)
+ else:
+ xBmp = wx.BitmapFromXPMData(x_button_xpm)
+
+ # Set the masking
+ xBmp.SetMask(wx.Mask(xBmp, MASK_COLOR))
+
+ # Draw the new bitmap
+ dc.DrawBitmap(xBmp, rect.x, rect.y, True)
+
+ # Update the vector
+ rr = wx.Rect(rect.x, rect.y, 14, 13)
+ pc._pagesInfoVec[tabIdx].SetXRect(rr)
+
+
+ def DrawTabsLine(self, pageContainer, dc, selTabX1=-1, selTabX2=-1):
+ """ Draws a line over the tabs. """
+
+ pc = pageContainer
+
+ clntRect = pc.GetClientRect()
+ clientRect3 = wx.Rect(0, 0, clntRect.GetWidth(), clntRect.height)
+
+ if pc.HasFlag(FNB_FF2):
+ if not pc.HasFlag(FNB_BOTTOM):
+ fillColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+ else:
+ fillColor = wx.WHITE
+
+ dc.SetPen(wx.Pen(fillColor))
+
+ if pc.HasFlag(FNB_BOTTOM):
+
+ dc.DrawLine(1, 0, clntRect.GetWidth()-1, 0)
+ dc.DrawLine(1, 1, clntRect.GetWidth()-1, 1)
+
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+ dc.DrawLine(1, 2, clntRect.GetWidth()-1, 2)
+
+ dc.SetPen(wx.Pen(fillColor))
+ dc.DrawLine(selTabX1 + 2, 2, selTabX2 - 1, 2)
+
+ else:
+
+ dc.DrawLine(1, clntRect.height, clntRect.GetWidth()-1, clntRect.height)
+ dc.DrawLine(1, clntRect.height-1, clntRect.GetWidth()-1, clntRect.height-1)
+
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+ dc.DrawLine(1, clntRect.height-2, clntRect.GetWidth()-1, clntRect.height-2)
+
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.DrawLine(selTabX1 + 2, clntRect.height-2, selTabX2-1, clntRect.height-2)
+
+ else:
+
+ if pc.HasFlag(FNB_BOTTOM):
+
+ clientRect = wx.Rect(0, 2, clntRect.GetWidth(), clntRect.height - 2)
+ clientRect2 = wx.Rect(0, 1, clntRect.GetWidth(), clntRect.height - 1)
+
+ else:
+
+ clientRect = wx.Rect(0, 0, clntRect.GetWidth(), clntRect.height - 2)
+ clientRect2 = wx.Rect(0, 0, clntRect.GetWidth(), clntRect.height - 1)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(wx.Pen(pc.GetSingleLineBorderColour()))
+ dc.DrawRectangleRect(clientRect2)
+ dc.DrawRectangleRect(clientRect3)
+
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+ dc.DrawRectangleRect(clientRect)
+
+ if not pc.HasFlag(FNB_TABS_BORDER_SIMPLE):
+
+ dc.SetPen(wx.Pen((pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc._tabAreaColor])[0]))
+ dc.DrawLine(0, 0, 0, clientRect.height+1)
+
+ if pc.HasFlag(FNB_BOTTOM):
+
+ dc.DrawLine(0, clientRect.height+1, clientRect.GetWidth(), clientRect.height+1)
+
+ else:
+
+ dc.DrawLine(0, 0, clientRect.GetWidth(), 0)
+
+ dc.DrawLine(clientRect.GetWidth() - 1, 0, clientRect.GetWidth() - 1, clientRect.height+1)
+
+
+ def CalcTabWidth(self, pageContainer, tabIdx, tabHeight):
+ """ Calculates the width of the input tab. """
+
+ pc = pageContainer
+ dc = wx.MemoryDC()
+ dc.SelectObject(wx.EmptyBitmap(1,1))
+
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+
+ if pc.IsDefaultTabs():
+ shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+
+ # Calculate the text length using the bold font, so when selecting a tab
+ # its width will not change
+ dc.SetFont(boldFont)
+ width, pom = dc.GetTextExtent(pc.GetPageText(tabIdx))
+
+ # Set a minimum size to a tab
+ if width < 20:
+ width = 20
+
+ tabWidth = 2*pc._pParent.GetPadding() + width
+
+ # Style to add a small 'x' button on the top right
+ # of the tab
+ if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+ # The xpm image that contains the 'x' button is 9 pixels
+ spacer = 9
+ if pc.HasFlag(FNB_VC8):
+ spacer = 4
+
+ tabWidth += pc._pParent.GetPadding() + spacer
+
+ if pc.IsDefaultTabs():
+ # Default style
+ tabWidth += 2*shapePoints
+
+ hasImage = pc._ImageList != None and pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+
+ # For VC71 style, we only add the icon size (16 pixels)
+ if hasImage:
+
+ if not pc.IsDefaultTabs():
+ tabWidth += 16 + pc._pParent.GetPadding()
+ else:
+ # Default style
+ tabWidth += 16 + pc._pParent.GetPadding() + shapePoints/2
+
+ return tabWidth
+
+
+ def CalcTabHeight(self, pageContainer):
+ """ Calculates the height of the input tab. """
+
+ if self._tabHeight:
+ return self._tabHeight
+
+ pc = pageContainer
+ dc = wx.MemoryDC()
+ dc.SelectObject(wx.EmptyBitmap(1,1))
+
+ # For GTK it seems that we must do this steps in order
+ # for the tabs will get the proper height on initialization
+ # on MSW, preforming these steps yields wierd results
+ normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont = normalFont
+
+# if "__WXGTK__" in wx.PlatformInfo:
+# boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+# dc.SetFont(boldFont)
+
+ height = dc.GetCharHeight()
+
+ tabHeight = height + FNB_HEIGHT_SPACER # We use 8 pixels as padding
+
+ self._tabHeight = tabHeight
+
+ return tabHeight
+
+
+ def DrawTabs(self, pageContainer, dc):
+ """ Actually draws the tabs in L{FlatNotebook}."""
+
+ pc = pageContainer
+ if "__WXMAC__" in wx.PlatformInfo:
+ # Works well on MSW & GTK, however this lines should be skipped on MAC
+ if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec):
+ pc.Hide()
+ return
+
+ # Get the text hight
+ tabHeight = self.CalcTabHeight(pageContainer)
+ style = pc.GetParent().GetWindowStyleFlag()
+
+ # Calculate the number of rows required for drawing the tabs
+ rect = pc.GetClientRect()
+ clientWidth = rect.GetWidth()
+
+ # Set the maximum client size
+ pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight)
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+
+ if style & FNB_VC71:
+ backBrush = wx.Brush(wx.Colour(247, 243, 233))
+ else:
+ backBrush = wx.Brush(pc._tabAreaColor)
+
+ noselBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE))
+ selBrush = wx.Brush(pc._activeTabColor)
+
+ size = pc.GetSize()
+
+ # Background
+ dc.SetTextBackground((style & FNB_VC71 and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0])
+ dc.SetTextForeground(pc._activeTextColor)
+ dc.SetBrush(backBrush)
+
+ # If border style is set, set the pen to be border pen
+ if pc.HasFlag(FNB_TABS_BORDER_SIMPLE):
+ dc.SetPen(borderPen)
+ else:
+ colr = (pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0]
+ dc.SetPen(wx.Pen(colr))
+
+ if pc.HasFlag(FNB_FF2):
+ lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
+ rect = pc.GetClientRect()
+ PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColor, LightColour(pc._tabAreaColor, lightFactor))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+ dc.DrawRectangle(0, 0, size.x, size.y)
+
+ # We always draw the bottom/upper line of the tabs
+ # regradless the style
+ dc.SetPen(borderPen)
+
+ if not pc.HasFlag(FNB_FF2):
+ self.DrawTabsLine(pc, dc)
+
+ # Restore the pen
+ dc.SetPen(borderPen)
+
+ if pc.HasFlag(FNB_VC71):
+
+ greyLineYVal = (pc.HasFlag(FNB_BOTTOM) and [0] or [size.y - 2])[0]
+ whiteLineYVal = (pc.HasFlag(FNB_BOTTOM) and [3] or [size.y - 3])[0]
+
+ pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
+ dc.SetPen(pen)
+
+ # Draw thik grey line between the windows area and
+ # the tab area
+ for num in xrange(3):
+ dc.DrawLine(0, greyLineYVal + num, size.x, greyLineYVal + num)
+
+ wbPen = (pc.HasFlag(FNB_BOTTOM) and [wx.BLACK_PEN] or [wx.WHITE_PEN])[0]
+ dc.SetPen(wbPen)
+ dc.DrawLine(1, whiteLineYVal, size.x - 1, whiteLineYVal)
+
+ # Restore the pen
+ dc.SetPen(borderPen)
+
+ # Draw labels
+ normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+ dc.SetFont(boldFont)
+
+ posx = pc._pParent.GetPadding()
+
+ # Add padding for LeftArrow button if necessary
+ if not pc.HasFlag(FNB_NO_NAV_BUTTONS):
+ posx += 12
+
+ # Update all the tabs from 0 to 'pc._nFrom' to be non visible
+ for i in xrange(pc._nFrom):
+
+ pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ count = pc._nFrom
+
+ #----------------------------------------------------------
+ # Go over and draw the visible tabs
+ #----------------------------------------------------------
+ x1 = x2 = -1
+ for i in xrange(pc._nFrom, len(pc._pagesInfoVec)):
+
+ dc.SetPen(borderPen)
+
+ if not pc.HasFlag(FNB_FF2):
+ dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0])
+
+ # Now set the font to the correct font
+ dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0])
+
+ # Add the padding to the tab width
+ # Tab width:
+ # +-----------------------------------------------------------+
+ # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
+ # +-----------------------------------------------------------+
+ tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
+
+ # Check if we can draw more
+ if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth:
+ break
+
+ count = count + 1
+
+ # By default we clean the tab region
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ # Clean the 'x' buttn on the tab.
+ # A 'Clean' rectangle, is a rectangle with width or height
+ # with values lower than or equal to 0
+ pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1))
+
+ # Draw the tab (border, text, image & 'x' on tab)
+ self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus)
+
+ if pc.GetSelection() == i:
+ x1 = posx
+ x2 = posx + tabWidth + 2
+
+ # Restore the text forground
+ dc.SetTextForeground(pc._activeTextColor)
+
+ # Update the tab position & size
+ posy = (pc.HasFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0]
+
+ pc._pagesInfoVec[i].SetPosition(wx.Point(posx, posy))
+ pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
+ self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[i])
+
+ posx += tabWidth
+
+ # Update all tabs that can not fit into the screen as non-visible
+ for i in xrange(count, len(pc._pagesInfoVec)):
+ pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ # Draw the left/right/close buttons
+ # Left arrow
+ self.DrawLeftArrow(pc, dc)
+ self.DrawRightArrow(pc, dc)
+ self.DrawX(pc, dc)
+ self.DrawDropDownArrow(pc, dc)
+
+ if pc.HasFlag(FNB_FF2):
+ self.DrawTabsLine(pc, dc, x1, x2)
+
+
+ def DrawFocusRectangle(self, dc, pageContainer, page):
+ """ Draws a focus rectangle like the native Notebooks. """
+
+ if not page._hasFocus:
+ return
+
+ tabPos = page.GetPosition()
+ if pageContainer.GetParent().GetWindowStyleFlag() & FNB_VC8:
+ vc8ShapeLen = self.CalcTabHeight(pageContainer) - VERTICAL_BORDER_PADDING - 2
+ tabPos.x += vc8ShapeLen
+
+ rect = wx.RectPS(tabPos, page.GetSize())
+ rect = wx.Rect(rect.x+5, rect.y+2, rect.GetWidth()-6, rect.height-8)
+
+ if wx.Platform == '__WXMAC__':
+ rect.SetWidth(rect.GetWidth() + 3)
+ rect.SetX(rect.GetX() - 2)
+
+ if pageContainer.GetParent().GetWindowStyleFlag() & FNB_BOTTOM:
+ rect.SetY(rect.GetY() + 3)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(self._focusPen)
+ dc.DrawRoundedRectangleRect(rect, 2)
+
+
+ def DrawDragHint(self, pc, tabIdx):
+ """
+ Draws tab drag hint, the default implementation is to do nothing.
+ You can override this function to provide a nice feedback to user.
+ """
+
+ pass
+
+
+ def NumberTabsCanFit(self, pageContainer, fr=-1):
+
+ pc = pageContainer
+
+ rect = pc.GetClientRect()
+ clientWidth = rect.GetWidth()
+
+ vTabInfo = []
+
+ tabHeight = self.CalcTabHeight(pageContainer)
+
+ # The drawing starts from posx
+ posx = pc._pParent.GetPadding()
+
+ if fr < 0:
+ fr = pc._nFrom
+
+ for i in xrange(fr, len(pc._pagesInfoVec)):
+
+ tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
+ if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth:
+ break;
+
+ # Add a result to the returned vector
+ tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth , tabHeight)
+ vTabInfo.append(tabRect)
+
+ # Advance posx
+ posx += tabWidth + FNB_HEIGHT_SPACER
+
+ return vTabInfo
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBRendererMgr
+# A manager that handles all the renderers defined below and calls the
+# appropriate one when drawing is needed
+# ---------------------------------------------------------------------------- #
+
+class FNBRendererMgr:
+ """
+ This class represents a manager that handles all the 4 renderers defined
+ and calls the appropriate one when drawing is needed.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ # register renderers
+
+ self._renderers = {}
+ self._renderers.update({-1: FNBRendererDefault()})
+ self._renderers.update({FNB_VC71: FNBRendererVC71()})
+ self._renderers.update({FNB_FANCY_TABS: FNBRendererFancy()})
+ self._renderers.update({FNB_VC8: FNBRendererVC8()})
+ self._renderers.update({FNB_FF2: FNBRendererFirefox2()})
+
+
+ def GetRenderer(self, style):
+ """ Returns the current renderer based on the style selected. """
+
+ if style & FNB_VC71:
+ return self._renderers[FNB_VC71]
+
+ if style & FNB_FANCY_TABS:
+ return self._renderers[FNB_FANCY_TABS]
+
+ if style & FNB_VC8:
+ return self._renderers[FNB_VC8]
+
+ if style & FNB_FF2:
+ return self._renderers[FNB_FF2]
+
+ # the default is to return the default renderer
+ return self._renderers[-1]
+
+
+#------------------------------------------
+# Default renderer
+#------------------------------------------
+
+class FNBRendererDefault(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the I{Standard} renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """ Draws a tab using the I{Standard} style. """
+
+ # Default style
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ pc = pageContainer
+
+ tabPoints = [wx.Point() for ii in xrange(7)]
+ tabPoints[0].x = posx
+ tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
+
+ tabPoints[1].x = int(posx+(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+ tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+ tabPoints[2].x = tabPoints[1].x+2
+ tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[3].x = int(posx+tabWidth-(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))-2
+ tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[4].x = tabPoints[3].x+2
+ tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+ tabPoints[5].x = int(tabPoints[4].x+(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+ tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
+
+ tabPoints[6].x = tabPoints[0].x
+ tabPoints[6].y = tabPoints[0].y
+
+ if tabIdx == pc.GetSelection():
+
+ # Draw the tab as rounded rectangle
+ dc.DrawPolygon(tabPoints)
+
+ else:
+
+ if tabIdx != pc.GetSelection() - 1:
+
+ # Draw a vertical line to the right of the text
+ pt1x = tabPoints[5].x
+ pt1y = (pc.HasFlag(FNB_BOTTOM) and [4] or [tabHeight - 6])[0]
+ pt2x = tabPoints[5].x
+ pt2y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 4] or [4])[0]
+ dc.DrawLine(pt1x, pt1y, pt2x, pt2y)
+
+ if tabIdx == pc.GetSelection():
+
+ savePen = dc.GetPen()
+ whitePen = wx.Pen(wx.WHITE)
+ whitePen.SetWidth(1)
+ dc.SetPen(whitePen)
+
+ secPt = wx.Point(tabPoints[5].x + 1, tabPoints[5].y)
+ dc.DrawLine(tabPoints[0].x, tabPoints[0].y, secPt.x, secPt.y)
+
+ # Restore the pen
+ dc.SetPen(savePen)
+
+ # -----------------------------------
+ # Text and image drawing
+ # -----------------------------------
+
+ # Text drawing offset from the left border of the
+ # rectangle
+
+ # The width of the images are 16 pixels
+ padding = pc.GetParent().GetPadding()
+ shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+ hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+ imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
+
+ if hasImage:
+ textOffset = 2*pc._pParent._nPadding + 16 + shapePoints/2
+ else:
+ textOffset = pc._pParent._nPadding + shapePoints/2
+
+ textOffset += 2
+
+ if tabIdx != pc.GetSelection():
+
+ # Set the text background to be like the vertical lines
+ dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
+
+ if hasImage:
+
+ imageXOffset = textOffset - 16 - padding
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+
+#------------------------------------------
+# Firefox2 renderer
+#------------------------------------------
+class FNBRendererFirefox2(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the I{Firefox 2} renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """ Draws a tab using the I{Firefox 2} style. """
+
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ pc = pageContainer
+
+ tabPoints = [wx.Point() for indx in xrange(7)]
+ tabPoints[0].x = posx + 2
+ tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
+
+ tabPoints[1].x = tabPoints[0].x
+ tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+ tabPoints[2].x = tabPoints[1].x+2
+ tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[3].x = posx + tabWidth - 2
+ tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[4].x = tabPoints[3].x + 2
+ tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+ tabPoints[5].x = tabPoints[4].x
+ tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
+
+ tabPoints[6].x = tabPoints[0].x
+ tabPoints[6].y = tabPoints[0].y
+
+ #------------------------------------
+ # Paint the tab with gradient
+ #------------------------------------
+ rr = wx.RectPP(tabPoints[2], tabPoints[5])
+ DrawButton(dc, rr, pc.GetSelection() == tabIdx , not pc.HasFlag(FNB_BOTTOM))
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(borderPen)
+
+ # Draw the tab as rounded rectangle
+ dc.DrawPolygon(tabPoints)
+
+ # -----------------------------------
+ # Text and image drawing
+ # -----------------------------------
+
+ # The width of the images are 16 pixels
+ padding = pc.GetParent().GetPadding()
+ shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+ hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+ imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
+
+ if hasImage:
+ textOffset = 2*padding + 16 + shapePoints/2
+ else:
+ textOffset = padding + shapePoints/2
+
+ textOffset += 2
+
+ if tabIdx != pc.GetSelection():
+
+ # Set the text background to be like the vertical lines
+ dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
+
+ if hasImage:
+ imageXOffset = textOffset - 16 - padding
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+
+#------------------------------------------------------------------
+# Visual studio 7.1
+#------------------------------------------------------------------
+
+class FNBRendererVC71(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the I{VC71} renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """ Draws a tab using the I{VC71} style. """
+
+ # Visual studio 7.1 style
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ pc = pageContainer
+
+ dc.SetPen((tabIdx == pc.GetSelection() and [wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))] or [borderPen])[0])
+ dc.SetBrush((tabIdx == pc.GetSelection() and [wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))] or [wx.Brush(wx.Colour(247, 243, 233))])[0])
+
+ if tabIdx == pc.GetSelection():
+
+ posy = (pc.HasFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0]
+ tabH = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 5] or [tabHeight - 3])[0]
+ dc.DrawRectangle(posx, posy, tabWidth, tabH)
+
+ # Draw a black line on the left side of the
+ # rectangle
+ dc.SetPen(wx.BLACK_PEN)
+
+ blackLineY1 = VERTICAL_BORDER_PADDING
+ blackLineY2 = tabH
+ dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2)
+
+ # To give the tab more 3D look we do the following
+ # Incase the tab is on top,
+ # Draw a thik white line on topof the rectangle
+ # Otherwise, draw a thin (1 pixel) black line at the bottom
+
+ pen = wx.Pen((pc.HasFlag(FNB_BOTTOM) and [wx.BLACK] or [wx.WHITE])[0])
+ dc.SetPen(pen)
+ whiteLinePosY = (pc.HasFlag(FNB_BOTTOM) and [blackLineY2] or [VERTICAL_BORDER_PADDING ])[0]
+ dc.DrawLine(posx , whiteLinePosY, posx + tabWidth + 1, whiteLinePosY)
+
+ # Draw a white vertical line to the left of the tab
+ dc.SetPen(wx.WHITE_PEN)
+ if not pc.HasFlag(FNB_BOTTOM):
+ blackLineY2 += 1
+
+ dc.DrawLine(posx, blackLineY1, posx, blackLineY2)
+
+ else:
+
+ # We dont draw a rectangle for non selected tabs, but only
+ # vertical line on the left
+
+ blackLineY1 = (pc.HasFlag(FNB_BOTTOM) and [VERTICAL_BORDER_PADDING + 2] or [VERTICAL_BORDER_PADDING + 1])[0]
+ blackLineY2 = pc.GetSize().y - 5
+ dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2)
+
+ # -----------------------------------
+ # Text and image drawing
+ # -----------------------------------
+
+ # Text drawing offset from the left border of the
+ # rectangle
+
+ # The width of the images are 16 pixels
+ padding = pc.GetParent().GetPadding()
+ hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+ imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [5] or [8])[0]
+
+ if hasImage:
+ textOffset = 2*pc._pParent._nPadding + 16
+ else:
+ textOffset = pc._pParent._nPadding
+
+ if tabIdx != pc.GetSelection():
+
+ # Set the text background to be like the vertical lines
+ dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
+
+ if hasImage:
+
+ imageXOffset = textOffset - 16 - padding
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+
+#------------------------------------------------------------------
+# Fancy style
+#------------------------------------------------------------------
+
+class FNBRendererFancy(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the I{Fancy} renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """ Draws a tab using the I{Fancy} style, similar to VC71 but with gradients. """
+
+ # Fancy tabs - like with VC71 but with the following differences:
+ # - The Selected tab is colored with gradient color
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ pc = pageContainer
+
+ pen = (tabIdx == pc.GetSelection() and [wx.Pen(pc._pParent.GetBorderColour())] or [wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))])[0]
+
+ if tabIdx == pc.GetSelection():
+
+ posy = (pc.HasFlag(FNB_BOTTOM) and [2] or [VERTICAL_BORDER_PADDING])[0]
+ th = tabHeight - 5
+
+ rect = wx.Rect(posx, posy, tabWidth, th)
+
+ col2 = (pc.HasFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourTo()] or [pc._pParent.GetGradientColourFrom()])[0]
+ col1 = (pc.HasFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourFrom()] or [pc._pParent.GetGradientColourTo()])[0]
+
+ PaintStraightGradientBox(dc, rect, col1, col2)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetPen(pen)
+ dc.DrawRectangleRect(rect)
+
+ # erase the bottom/top line of the rectangle
+ dc.SetPen(wx.Pen(pc._pParent.GetGradientColourFrom()))
+ if pc.HasFlag(FNB_BOTTOM):
+ dc.DrawLine(rect.x, 2, rect.x + rect.GetWidth(), 2)
+ else:
+ dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.GetWidth(), rect.y + rect.height - 1)
+
+ else:
+
+ # We dont draw a rectangle for non selected tabs, but only
+ # vertical line on the left
+ dc.SetPen(borderPen)
+ dc.DrawLine(posx + tabWidth, VERTICAL_BORDER_PADDING + 3, posx + tabWidth, tabHeight - 4)
+
+
+ # -----------------------------------
+ # Text and image drawing
+ # -----------------------------------
+
+ # Text drawing offset from the left border of the
+ # rectangle
+
+ # The width of the images are 16 pixels
+ padding = pc.GetParent().GetPadding()
+ hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+ imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
+
+ if hasImage:
+ textOffset = 2*pc._pParent._nPadding + 16
+ else:
+ textOffset = pc._pParent._nPadding
+
+ textOffset += 2
+
+ if tabIdx != pc.GetSelection():
+
+ # Set the text background to be like the vertical lines
+ dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
+
+ if hasImage:
+
+ imageXOffset = textOffset - 16 - padding
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+
+#------------------------------------------------------------------
+# Visual studio 2005 (VS8)
+#------------------------------------------------------------------
+class FNBRendererVC8(FNBRenderer):
+ """
+ This class handles the drawing of tabs using the I{VC8} renderer.
+ """
+
+ def __init__(self):
+ """ Default class constructor. """
+
+ FNBRenderer.__init__(self)
+ self._first = True
+ self._factor = 1
+
+
+ def DrawTabs(self, pageContainer, dc):
+ """ Draws all the tabs using VC8 style. Overloads The DrawTabs method in parent class. """
+
+ pc = pageContainer
+
+ if "__WXMAC__" in wx.PlatformInfo:
+ # Works well on MSW & GTK, however this lines should be skipped on MAC
+ if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec):
+ pc.Hide()
+ return
+
+ # Get the text hight
+ tabHeight = self.CalcTabHeight(pageContainer)
+
+ # Set the font for measuring the tab height
+ normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+
+ # Calculate the number of rows required for drawing the tabs
+ rect = pc.GetClientRect()
+
+ # Set the maximum client size
+ pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight)
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+
+ # Create brushes
+ backBrush = wx.Brush(pc._tabAreaColor)
+ noselBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE))
+ selBrush = wx.Brush(pc._activeTabColor)
+ size = pc.GetSize()
+
+ # Background
+ dc.SetTextBackground(pc.GetBackgroundColour())
+ dc.SetTextForeground(pc._activeTextColor)
+
+ # If border style is set, set the pen to be border pen
+ if pc.HasFlag(FNB_TABS_BORDER_SIMPLE):
+ dc.SetPen(borderPen)
+ else:
+ dc.SetPen(wx.TRANSPARENT_PEN)
+
+ lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
+
+ # For VC8 style, we color the tab area in gradient coloring
+ lightcolour = LightColour(pc._tabAreaColor, lightFactor)
+ PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColor, lightcolour)
+
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(0, 0, size.x, size.y)
+
+ # We always draw the bottom/upper line of the tabs
+ # regradless the style
+ dc.SetPen(borderPen)
+ self.DrawTabsLine(pc, dc)
+
+ # Restore the pen
+ dc.SetPen(borderPen)
+
+ # Draw labels
+ dc.SetFont(boldFont)
+
+ # Update all the tabs from 0 to 'pc.self._nFrom' to be non visible
+ for i in xrange(pc._nFrom):
+
+ pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ # Draw the visible tabs, in VC8 style, we draw them from right to left
+ vTabsInfo = self.NumberTabsCanFit(pc)
+
+ activeTabPosx = 0
+ activeTabWidth = 0
+ activeTabHeight = 0
+
+ for cur in xrange(len(vTabsInfo)-1, -1, -1):
+
+ # 'i' points to the index of the currently drawn tab
+ # in pc.GetPageInfoVector() vector
+ i = pc._nFrom + cur
+ dc.SetPen(borderPen)
+ dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0])
+
+ # Now set the font to the correct font
+ dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0])
+
+ # Add the padding to the tab width
+ # Tab width:
+ # +-----------------------------------------------------------+
+ # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
+ # +-----------------------------------------------------------+
+
+ tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
+ posx = vTabsInfo[cur].x
+
+ # By default we clean the tab region
+ # incase we use the VC8 style which requires
+ # the region, it will be filled by the function
+ # drawVc8Tab
+ pc._pagesInfoVec[i].GetRegion().Clear()
+
+ # Clean the 'x' buttn on the tab
+ # 'Clean' rectanlge is a rectangle with width or height
+ # with values lower than or equal to 0
+ pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1))
+
+ # Draw the tab
+ # Incase we are drawing the active tab
+ # we need to redraw so it will appear on top
+ # of all other tabs
+
+ # when using the vc8 style, we keep the position of the active tab so we will draw it again later
+ if i == pc.GetSelection() and pc.HasFlag(FNB_VC8):
+
+ activeTabPosx = posx
+ activeTabWidth = tabWidth
+ activeTabHeight = tabHeight
+
+ else:
+
+ self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus)
+
+ # Restore the text forground
+ dc.SetTextForeground(pc._activeTextColor)
+
+ # Update the tab position & size
+ pc._pagesInfoVec[i].SetPosition(wx.Point(posx, VERTICAL_BORDER_PADDING))
+ pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
+
+ # Incase we are in VC8 style, redraw the active tab (incase it is visible)
+ if pc.GetSelection() >= pc._nFrom and pc.GetSelection() < pc._nFrom + len(vTabsInfo):
+
+ self.DrawTab(pc, dc, activeTabPosx, pc.GetSelection(), activeTabWidth, activeTabHeight, pc._nTabXButtonStatus)
+
+ # Update all tabs that can not fit into the screen as non-visible
+ for xx in xrange(pc._nFrom + len(vTabsInfo), len(pc._pagesInfoVec)):
+
+ pc._pagesInfoVec[xx].SetPosition(wx.Point(-1, -1))
+ pc._pagesInfoVec[xx].GetRegion().Clear()
+
+ # Draw the left/right/close buttons
+ # Left arrow
+ self.DrawLeftArrow(pc, dc)
+ self.DrawRightArrow(pc, dc)
+ self.DrawX(pc, dc)
+ self.DrawDropDownArrow(pc, dc)
+
+
+ def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+ """ Draws a tab using VC8 style. """
+
+ pc = pageContainer
+ borderPen = wx.Pen(pc._pParent.GetBorderColour())
+ tabPoints = [wx.Point() for ii in xrange(8)]
+
+ # If we draw the first tab or the active tab,
+ # we draw a full tab, else we draw a truncated tab
+ #
+ # X(2) X(3)
+ # X(1) X(4)
+ #
+ # X(5)
+ #
+ # X(0),(7) X(6)
+ #
+ #
+
+ tabPoints[0].x = (pc.HasFlag(FNB_BOTTOM) and [posx] or [posx+self._factor])[0]
+ tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 3])[0]
+
+ tabPoints[1].x = tabPoints[0].x + tabHeight - VERTICAL_BORDER_PADDING - 3 - self._factor
+ tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+ tabPoints[2].x = tabPoints[1].x + 4
+ tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[3].x = tabPoints[2].x + tabWidth - 2
+ tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+ tabPoints[4].x = tabPoints[3].x + 1
+ tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabPoints[3].y - 1] or [tabPoints[3].y + 1])[0]
+
+ tabPoints[5].x = tabPoints[4].x + 1
+ tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [(tabPoints[4].y - 1)] or [tabPoints[4].y + 1])[0]
+
+ tabPoints[6].x = tabPoints[2].x + tabWidth
+ tabPoints[6].y = tabPoints[0].y
+
+ tabPoints[7].x = tabPoints[0].x
+ tabPoints[7].y = tabPoints[0].y
+
+ pc._pagesInfoVec[tabIdx].SetRegion(tabPoints)
+
+ # Draw the polygon
+ br = dc.GetBrush()
+ dc.SetBrush(wx.Brush((tabIdx == pc.GetSelection() and [pc._activeTabColor] or [pc._colorTo])[0]))
+ dc.SetPen(wx.Pen((tabIdx == pc.GetSelection() and [wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)] or [pc._colorBorder])[0]))
+ dc.DrawPolygon(tabPoints)
+
+ # Restore the brush
+ dc.SetBrush(br)
+ rect = pc.GetClientRect()
+
+ if tabIdx != pc.GetSelection() and not pc.HasFlag(FNB_BOTTOM):
+
+ # Top default tabs
+ dc.SetPen(wx.Pen(pc._pParent.GetBorderColour()))
+ lineY = rect.height
+ curPen = dc.GetPen()
+ curPen.SetWidth(1)
+ dc.SetPen(curPen)
+ dc.DrawLine(posx, lineY, posx+rect.GetWidth(), lineY)
+
+ # Incase we are drawing the selected tab, we draw the border of it as well
+ # but without the bottom (upper line incase of wxBOTTOM)
+ if tabIdx == pc.GetSelection():
+
+ borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+ dc.SetPen(borderPen)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawPolygon(tabPoints)
+
+ # Delete the bottom line (or the upper one, incase we use wxBOTTOM)
+ dc.SetPen(wx.WHITE_PEN)
+ dc.DrawLine(tabPoints[0].x, tabPoints[0].y, tabPoints[6].x, tabPoints[6].y)
+
+ self.FillVC8GradientColour(pc, dc, tabPoints, tabIdx == pc.GetSelection(), tabIdx)
+
+ # Draw a thin line to the right of the non-selected tab
+ if tabIdx != pc.GetSelection():
+
+ dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+ dc.DrawLine(tabPoints[4].x-1, tabPoints[4].y, tabPoints[5].x-1, tabPoints[5].y)
+ dc.DrawLine(tabPoints[5].x-1, tabPoints[5].y, tabPoints[6].x-1, tabPoints[6].y)
+
+ # Text drawing offset from the left border of the
+ # rectangle
+
+ # The width of the images are 16 pixels
+ vc8ShapeLen = tabHeight - VERTICAL_BORDER_PADDING - 2
+ if pc.TabHasImage(tabIdx):
+ textOffset = 2*pc._pParent.GetPadding() + 16 + vc8ShapeLen
+ else:
+ textOffset = pc._pParent.GetPadding() + vc8ShapeLen
+
+ # Draw the image for the tab if any
+ imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
+
+ if pc.TabHasImage(tabIdx):
+
+ imageXOffset = textOffset - 16 - pc._pParent.GetPadding()
+ pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+ posx + imageXOffset, imageYCoord,
+ wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+ boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+ # if selected tab, draw text in bold
+ if tabIdx == pc.GetSelection():
+ boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+
+ dc.SetFont(boldFont)
+ dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+ # draw 'x' on tab (if enabled)
+ if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+
+ textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+ tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+ # take a bitmap from the position of the 'x' button (the x on tab button)
+ # this bitmap will be used later to delete old buttons
+ tabCloseButtonYCoord = imageYCoord
+ x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+
+ # Draw the tab
+ self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+
+ self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[tabIdx])
+
+
+ def FillVC8GradientColour(self, pageContainer, dc, tabPoints, bSelectedTab, tabIdx):
+ """ Fills a tab with a gradient shading. """
+
+ # calculate gradient coefficients
+ pc = pageContainer
+
+ if self._first:
+ self._first = False
+ pc._colorTo = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 0)
+ pc._colorFrom = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 60)
+
+ col2 = pc._pParent.GetGradientColourTo()
+ col1 = pc._pParent.GetGradientColourFrom()
+
+ # If colorful tabs style is set, override the tab color
+ if pc.HasFlag(FNB_COLORFUL_TABS):
+
+ if not pc._pagesInfoVec[tabIdx].GetColour():
+
+ # First time, generate color, and keep it in the vector
+ tabColor = RandomColour()
+ pc._pagesInfoVec[tabIdx].SetColour(tabColor)
+
+ if pc.HasFlag(FNB_BOTTOM):
+
+ col2 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 50)
+ col1 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 80)
+
+ else:
+
+ col1 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 50)
+ col2 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 80)
+
+ size = abs(tabPoints[2].y - tabPoints[0].y) - 1
+
+ rf, gf, bf = 0, 0, 0
+ rstep = float(col2.Red() - col1.Red())/float(size)
+ gstep = float(col2.Green() - col1.Green())/float(size)
+ bstep = float(col2.Blue() - col1.Blue())/float(size)
+
+ y = tabPoints[0].y
+
+ # If we are drawing the selected tab, we need also to draw a line
+ # from 0.tabPoints[0].x and tabPoints[6].x . end, we achieve this
+ # by drawing the rectangle with transparent brush
+ # the line under the selected tab will be deleted by the drwaing loop
+ if bSelectedTab:
+ self.DrawTabsLine(pc, dc)
+
+ while 1:
+
+ if pc.HasFlag(FNB_BOTTOM):
+
+ if y > tabPoints[0].y + size:
+ break
+
+ else:
+
+ if y < tabPoints[0].y - size:
+ break
+
+ currCol = wx.Colour(col1.Red() + rf, col1.Green() + gf, col1.Blue() + bf)
+
+ dc.SetPen((bSelectedTab and [wx.Pen(pc._activeTabColor)] or [wx.Pen(currCol)])[0])
+ startX = self.GetStartX(tabPoints, y, pc.GetParent().GetWindowStyleFlag())
+ endX = self.GetEndX(tabPoints, y, pc.GetParent().GetWindowStyleFlag())
+ dc.DrawLine(startX, y, endX, y)
+
+ # Draw the border using the 'edge' point
+ dc.SetPen(wx.Pen((bSelectedTab and [wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)] or [pc._colorBorder])[0]))
+
+ dc.DrawPoint(startX, y)
+ dc.DrawPoint(endX, y)
+
+ # Progress the color
+ rf += rstep
+ gf += gstep
+ bf += bstep
+
+ if pc.HasFlag(FNB_BOTTOM):
+ y = y + 1
+ else:
+ y = y - 1
+
+
+ def GetStartX(self, tabPoints, y, style):
+ """ Returns the x start position of a tab. """
+
+ x1, x2, y1, y2 = 0.0, 0.0, 0.0, 0.0
+
+ # We check the 3 points to the left
+
+ bBottomStyle = (style & FNB_BOTTOM and [True] or [False])[0]
+ match = False
+
+ if bBottomStyle:
+
+ for i in xrange(3):
+
+ if y >= tabPoints[i].y and y < tabPoints[i+1].y:
+
+ x1 = tabPoints[i].x
+ x2 = tabPoints[i+1].x
+ y1 = tabPoints[i].y
+ y2 = tabPoints[i+1].y
+ match = True
+ break
+
+ else:
+
+ for i in xrange(3):
+
+ if y <= tabPoints[i].y and y > tabPoints[i+1].y:
+
+ x1 = tabPoints[i].x
+ x2 = tabPoints[i+1].x
+ y1 = tabPoints[i].y
+ y2 = tabPoints[i+1].y
+ match = True
+ break
+
+ if not match:
+ return tabPoints[2].x
+
+ # According to the equation y = ax + b => x = (y-b)/a
+ # We know the first 2 points
+
+ if x2 == x1:
+ return x2
+ else:
+ a = (y2 - y1)/(x2 - x1)
+
+ b = y1 - ((y2 - y1)/(x2 - x1))*x1
+
+ if a == 0:
+ return int(x1)
+
+ x = (y - b)/a
+
+ return int(x)
+
+
+ def GetEndX(self, tabPoints, y, style):
+ """ Returns the x end position of a tab. """
+
+ x1, x2, y1, y2 = 0.0, 0.0, 0.0, 0.0
+
+ # We check the 3 points to the left
+ bBottomStyle = (style & FNB_BOTTOM and [True] or [False])[0]
+ match = False
+
+ if bBottomStyle:
+
+ for i in xrange(7, 3, -1):
+
+ if y >= tabPoints[i].y and y < tabPoints[i-1].y:
+
+ x1 = tabPoints[i].x
+ x2 = tabPoints[i-1].x
+ y1 = tabPoints[i].y
+ y2 = tabPoints[i-1].y
+ match = True
+ break
+
+ else:
+
+ for i in xrange(7, 3, -1):
+
+ if y <= tabPoints[i].y and y > tabPoints[i-1].y:
+
+ x1 = tabPoints[i].x
+ x2 = tabPoints[i-1].x
+ y1 = tabPoints[i].y
+ y2 = tabPoints[i-1].y
+ match = True
+ break
+
+ if not match:
+ return tabPoints[3].x
+
+ # According to the equation y = ax + b => x = (y-b)/a
+ # We know the first 2 points
+
+ # Vertical line
+ if x1 == x2:
+ return int(x1)
+
+ a = (y2 - y1)/(x2 - x1)
+ b = y1 - ((y2 - y1)/(x2 - x1))*x1
+
+ if a == 0:
+ return int(x1)
+
+ x = (y - b)/a
+
+ return int(x)
+
+
+ def NumberTabsCanFit(self, pageContainer, fr=-1):
+ """ Returns the number of tabs that can fit in the visible area. """
+
+ pc = pageContainer
+
+ rect = pc.GetClientRect()
+ clientWidth = rect.GetWidth()
+
+ # Empty results
+ vTabInfo = []
+ tabHeight = self.CalcTabHeight(pageContainer)
+
+ # The drawing starts from posx
+ posx = pc._pParent.GetPadding()
+
+ if fr < 0:
+ fr = pc._nFrom
+
+ for i in xrange(fr, len(pc._pagesInfoVec)):
+
+ vc8glitch = tabHeight + FNB_HEIGHT_SPACER
+ tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
+
+ if posx + tabWidth + vc8glitch + self.GetButtonsAreaLength(pc) >= clientWidth:
+ break
+
+ # Add a result to the returned vector
+ tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth, tabHeight)
+ vTabInfo.append(tabRect)
+
+ # Advance posx
+ posx += tabWidth + FNB_HEIGHT_SPACER
+
+ return vTabInfo
+
+
+# ---------------------------------------------------------------------------- #
+# Class FlatNotebook
+# ---------------------------------------------------------------------------- #
+
+class FlatNotebook(wx.PyPanel):
+ """
+ Display one or more windows in a notebook.
+
+ B{Events}:
+ - B{EVT_FLATNOTEBOOK_PAGE_CHANGING}: sent when the active
+ page in the notebook is changing
+ - B{EVT_FLATNOTEBOOK_PAGE_CHANGED}: sent when the active
+ page in the notebook has changed
+ - B{EVT_FLATNOTEBOOK_PAGE_CLOSING}: sent when a page in the
+ notebook is closing
+ - B{EVT_FLATNOTEBOOK_PAGE_CLOSED}: sent when a page in the
+ notebook has been closed
+ - B{EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU}: sent when the user
+ clicks a tab in the notebook with the right mouse
+ button
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
+ style=0, name="FlatNotebook"):
+ """
+ Default class constructor.
+
+ All the parameters are as in wxPython class construction, except the
+ 'style': this can be assigned to whatever combination of FNB_* styles.
+
+ """
+
+ self._bForceSelection = False
+ self._nPadding = 6
+ self._nFrom = 0
+ style |= wx.TAB_TRAVERSAL
+ self._pages = None
+ self._windows = []
+ self._popupWin = None
+ self._naviIcon = None
+
+ wx.PyPanel.__init__(self, parent, id, pos, size, style)
+
+ self._pages = PageContainer(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, style)
+
+ self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
+
+ self.Init()
+
+
+ def Init(self):
+ """ Initializes all the class attributes. """
+
+ self._pages._colorBorder = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+
+ self._mainSizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self._mainSizer)
+
+ # The child panels will inherit this bg color, so leave it at the default value
+ #self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_APPWORKSPACE))
+
+ # Set default page height
+ dc = wx.ClientDC(self)
+
+# if "__WXGTK__" in wx.PlatformInfo:
+# # For GTK it seems that we must do this steps in order
+# # for the tabs will get the proper height on initialization
+# # on MSW, preforming these steps yields wierd results
+# boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+# boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+# dc.SetFont(boldFont)
+
+ height = dc.GetCharHeight()
+
+ tabHeight = height + FNB_HEIGHT_SPACER # We use 8 pixels as padding
+
+ self._pages.SetSizeHints(-1, tabHeight)
+ # Add the tab container to the sizer
+ self._mainSizer.Insert(0, self._pages, 0, wx.EXPAND)
+ self._mainSizer.Layout()
+
+ self._pages._nFrom = self._nFrom
+ self._pDropTarget = FNBDropTarget(self)
+ self.SetDropTarget(self._pDropTarget)
+
+
+ def DoGetBestSize(self):
+ """ Overrides DoGetBestSize to handle sizers nicely. """
+
+ if not self._windows:
+ # Something is better than nothing... no pages!
+ return wx.Size(20, 20)
+
+ maxWidth = maxHeight = 0
+ tabHeight = self.GetPageBestSize().height
+
+ for win in self._windows:
+ # Loop over all the windows to get their best size
+ width, height = win.GetBestSize()
+ maxWidth, maxHeight = max(maxWidth, width), max(maxHeight, height)
+
+ return wx.Size(maxWidth, maxHeight+tabHeight)
+
+
+ def SetActiveTabTextColour(self, textColour):
+ """ Sets the text colour for the active tab. """
+
+ self._pages._activeTextColor = textColour
+
+
+ def OnDropTarget(self, x, y, nTabPage, wnd_oldContainer):
+ """ Handles the drop action from a DND operation. """
+
+ return self._pages.OnDropTarget(x, y, nTabPage, wnd_oldContainer)
+
+
+ def GetPreviousSelection(self):
+ """ Returns the previous selection. """
+
+ return self._pages._iPreviousActivePage
+
+
+ def AddPage(self, page, text, select=True, imageId=-1):
+ """
+ Add a page to the L{FlatNotebook}.
+
+ @param page: Specifies the new page.
+ @param text: Specifies the text for the new page.
+ @param select: Specifies whether the page should be selected.
+ @param imageId: Specifies the optional image index for the new page.
+
+ Return value:
+ True if successful, False otherwise.
+ """
+
+ # sanity check
+ if not page:
+ return False
+
+ # reparent the window to us
+ page.Reparent(self)
+
+ # Add tab
+ bSelected = select or len(self._windows) == 0
+
+ if bSelected:
+
+ bSelected = False
+
+ # Check for selection and send events
+ oldSelection = self._pages._iActivePage
+ tabIdx = len(self._windows)
+
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetId())
+ event.SetSelection(tabIdx)
+ event.SetOldSelection(oldSelection)
+ event.SetEventObject(self)
+
+ if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0:
+ bSelected = True
+
+ curSel = self._pages.GetSelection()
+
+ if not self._pages.IsShown():
+ self._pages.Show()
+
+ self._pages.AddPage(text, bSelected, imageId)
+ self._windows.append(page)
+
+ self.Freeze()
+
+ # Check if a new selection was made
+ if bSelected:
+
+ if curSel >= 0:
+
+ # Remove the window from the main sizer
+ self._mainSizer.Detach(self._windows[curSel])
+ self._windows[curSel].Hide()
+
+ if self.GetWindowStyleFlag() & FNB_BOTTOM:
+
+ self._mainSizer.Insert(0, page, 1, wx.EXPAND)
+
+ else:
+
+ # We leave a space of 1 pixel around the window
+ self._mainSizer.Add(page, 1, wx.EXPAND)
+
+ # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
+ event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
+ event.SetOldSelection(oldSelection)
+ self.GetEventHandler().ProcessEvent(event)
+
+ else:
+
+ # Hide the page
+ page.Hide()
+
+ self.Thaw()
+ self._mainSizer.Layout()
+ self.Refresh()
+
+ return True
+
+
+ def SetImageList(self, imageList):
+ """ Sets the image list for the page control. """
+
+ self._pages.SetImageList(imageList)
+
+
+ def AssignImageList(self, imageList):
+ """ Assigns the image list for the page control. """
+
+ self._pages.AssignImageList(imageList)
+
+
+ def GetImageList(self):
+ """ Returns the associated image list. """
+
+ return self._pages.GetImageList()
+
+
+ def InsertPage(self, indx, page, text, select=True, imageId=-1):
+ """
+ Inserts a new page at the specified position.
+
+ @param indx: Specifies the position of the new page.
+ @param page: Specifies the new page.
+ @param text: Specifies the text for the new page.
+ @param select: Specifies whether the page should be selected.
+ @param imageId: Specifies the optional image index for the new page.
+
+ Return value:
+ True if successful, False otherwise.
+ """
+
+ # sanity check
+ if not page:
+ return False
+
+ # reparent the window to us
+ page.Reparent(self)
+
+ if not self._windows:
+
+ self.AddPage(page, text, select, imageId)
+ return True
+
+ # Insert tab
+ bSelected = select or not self._windows
+ curSel = self._pages.GetSelection()
+
+ indx = max(0, min(indx, len(self._windows)))
+
+ if indx <= len(self._windows):
+
+ self._windows.insert(indx, page)
+
+ else:
+
+ self._windows.append(page)
+
+ if bSelected:
+
+ bSelected = False
+
+ # Check for selection and send events
+ oldSelection = self._pages._iActivePage
+
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetId())
+ event.SetSelection(indx)
+ event.SetOldSelection(oldSelection)
+ event.SetEventObject(self)
+
+ if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0:
+ bSelected = True
+
+ self._pages.InsertPage(indx, text, bSelected, imageId)
+
+ if indx <= curSel:
+ curSel = curSel + 1
+
+ self.Freeze()
+
+ # Check if a new selection was made
+ if bSelected:
+
+ if curSel >= 0:
+
+ # Remove the window from the main sizer
+ self._mainSizer.Detach(self._windows[curSel])
+ self._windows[curSel].Hide()
+
+ self._pages.SetSelection(indx)
+
+ # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
+ event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
+ event.SetOldSelection(oldSelection)
+ self.GetEventHandler().ProcessEvent(event)
+
+ else:
+
+ # Hide the page
+ page.Hide()
+
+ self.Thaw()
+ self._mainSizer.Layout()
+ self.Refresh()
+
+ return True
+
+
+ def SetSelection(self, page):
+ """
+ Sets the selection for the given page.
+ The call to this function generates the page changing events
+ """
+
+ if page >= len(self._windows) or not self._windows:
+ return
+
+ # Support for disabed tabs
+ if not self._pages.GetEnabled(page) and len(self._windows) > 1 and not self._bForceSelection:
+ return
+
+ curSel = self._pages.GetSelection()
+
+ # program allows the page change
+ self.Freeze()
+ if curSel >= 0:
+
+ # Remove the window from the main sizer
+ self._mainSizer.Detach(self._windows[curSel])
+ self._windows[curSel].Hide()
+
+ if self.GetWindowStyleFlag() & FNB_BOTTOM:
+
+ self._mainSizer.Insert(0, self._windows[page], 1, wx.EXPAND)
+
+ else:
+
+ # We leave a space of 1 pixel around the window
+ self._mainSizer.Add(self._windows[page], 1, wx.EXPAND)
+
+ self._windows[page].Show()
+ self.Thaw()
+
+ self._mainSizer.Layout()
+
+ if page != self._pages._iActivePage:
+ # there is a real page changing
+ self._pages._iPreviousActivePage = self._pages._iActivePage
+
+ self._pages._iActivePage = page
+ self._pages.DoSetSelection(page)
+
+
+ def DeletePage(self, page):
+ """
+ Deletes the specified page, and the associated window.
+ The call to this function generates the page changing events.
+ """
+
+ if page >= len(self._windows) or page < 0:
+ return
+
+ # Fire a closing event
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, self.GetId())
+ event.SetSelection(page)
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ # The event handler allows it?
+ if not event.IsAllowed():
+ return
+
+ self.Freeze()
+
+ # Delete the requested page
+ pageRemoved = self._windows[page]
+
+ # If the page is the current window, remove it from the sizer
+ # as well
+ if page == self._pages.GetSelection():
+ self._mainSizer.Detach(pageRemoved)
+
+ # Remove it from the array as well
+ self._windows.pop(page)
+
+ # Now we can destroy it in wxWidgets use Destroy instead of delete
+ pageRemoved.Destroy()
+
+ self.Thaw()
+
+ self._pages.DoDeletePage(page)
+ self.Refresh()
+ self.Update()
+
+ # Fire a closed event
+ closedEvent = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, self.GetId())
+ closedEvent.SetSelection(page)
+ closedEvent.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(closedEvent)
+
+
+ def DeleteAllPages(self):
+ """ Deletes all the pages. """
+
+ if not self._windows:
+ return False
+
+ self.Freeze()
+
+ for page in self._windows:
+ page.Destroy()
+
+ self._windows = []
+ self.Thaw()
+
+ # Clear the container of the tabs as well
+ self._pages.DeleteAllPages()
+ return True
+
+
+ def GetCurrentPage(self):
+ """ Returns the currently selected notebook page or None. """
+
+ sel = self._pages.GetSelection()
+ if sel < 0 or sel >= len(self._windows):
+ return None
+
+ return self._windows[sel]
+
+
+ def GetPage(self, page):
+ """ Returns the window at the given page position, or None. """
+
+ if page >= len(self._windows):
+ return None
+
+ return self._windows[page]
+
+
+ def GetPageIndex(self, win):
+ """ Returns the index at which the window is found. """
+
+ try:
+ return self._windows.index(win)
+ except:
+ return -1
+
+
+ def GetSelection(self):
+ """ Returns the currently selected page, or -1 if none was selected. """
+
+ return self._pages.GetSelection()
+
+
+ def AdvanceSelection(self, forward=True):
+ """
+ Cycles through the tabs.
+ The call to this function generates the page changing events.
+ """
+
+ self._pages.AdvanceSelection(forward)
+
+
+ def GetPageCount(self):
+ """ Returns the number of pages in the L{FlatNotebook} control. """
+
+ return self._pages.GetPageCount()
+
+ def SetNavigatorIcon(self, bmp):
+ """ Set the icon used by the L{TabNavigatorWindow} """
+ if isinstance(bmp, wx.Bitmap) and bmp.IsOk():
+ # Make sure image is proper size
+ if bmp.GetSize() != (16, 16):
+ img = bmp.ConvertToImage()
+ img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH)
+ bmp = wx.BitmapFromImage(img)
+ self._naviIcon = bmp
+ else:
+ raise TypeError, "SetNavigatorIcon requires a valid bitmap"
+
+ def OnNavigationKey(self, event):
+ """ Handles the wx.EVT_NAVIGATION_KEY event for L{FlatNotebook}. """
+
+ if event.IsWindowChange():
+ if len(self._windows) == 0:
+ return
+ # change pages
+ if self.HasFlag(FNB_SMART_TABS):
+ if not self._popupWin:
+ self._popupWin = TabNavigatorWindow(self, self._naviIcon)
+ self._popupWin.SetReturnCode(wx.ID_OK)
+ self._popupWin.ShowModal()
+ self._pages.FireEvent(self._popupWin.GetSelection())
+ self._popupWin.Destroy()
+ self._popupWin = None
+ else:
+ # a dialog is already opened
+ self._popupWin.OnNavigationKey(event)
+ return
+ else:
+ # change pages
+ self.AdvanceSelection(event.GetDirection())
+
+ else:
+ event.Skip()
+
+
+ def GetPageShapeAngle(self, page_index):
+ """ Returns the angle associated to a tab. """
+
+ if page_index < 0 or page_index >= len(self._pages._pagesInfoVec):
+ return None, False
+
+ result = self._pages._pagesInfoVec[page_index].GetTabAngle()
+ return result, True
+
+
+ def SetPageShapeAngle(self, page_index, angle):
+ """ Sets the angle associated to a tab. """
+
+ if page_index < 0 or page_index >= len(self._pages._pagesInfoVec):
+ return
+
+ if angle > 15:
+ return
+
+ self._pages._pagesInfoVec[page_index].SetTabAngle(angle)
+
+
+ def SetAllPagesShapeAngle(self, angle):
+ """ Sets the angle associated to all the tab. """
+
+ if angle > 15:
+ return
+
+ for ii in xrange(len(self._pages._pagesInfoVec)):
+ self._pages._pagesInfoVec[ii].SetTabAngle(angle)
+
+ self.Refresh()
+
+
+ def GetPageBestSize(self):
+ """ Return the page best size. """
+
+ return self._pages.GetClientSize()
+
+
+ def SetPageText(self, page, text):
+ """ Sets the text for the given page. """
+
+ bVal = self._pages.SetPageText(page, text)
+ self._pages.Refresh()
+
+ return bVal
+
+
+ def SetPadding(self, padding):
+ """
+ Sets the amount of space around each page's icon and label, in pixels.
+ NB: only the horizontal padding is considered.
+ """
+
+ self._nPadding = padding.GetWidth()
+
+
+ def GetTabArea(self):
+ """ Returns the associated page. """
+
+ return self._pages
+
+
+ def GetPadding(self):
+ """ Returns the amount of space around each page's icon and label, in pixels. """
+
+ return self._nPadding
+
+
+ def SetWindowStyleFlag(self, style):
+ """ Sets the L{FlatNotebook} window style flags. """
+
+ wx.PyPanel.SetWindowStyleFlag(self, style)
+ renderer = self._pages._mgr.GetRenderer(self.GetWindowStyleFlag())
+ renderer._tabHeight = None
+
+ if self._pages:
+
+ # For changing the tab position (i.e. placing them top/bottom)
+ # refreshing the tab container is not enough
+ self.SetSelection(self._pages._iActivePage)
+
+ if not self._pages.HasFlag(FNB_HIDE_ON_SINGLE_TAB):
+ #For Redrawing the Tabs once you remove the Hide tyle
+ self._pages._ReShow()
+
+
+ def RemovePage(self, page):
+ """ Deletes the specified page, without deleting the associated window. """
+
+ if page >= len(self._windows):
+ return False
+
+ # Fire a closing event
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, self.GetId())
+ event.SetSelection(page)
+ event.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(event)
+
+ # The event handler allows it?
+ if not event.IsAllowed():
+ return False
+
+ self.Freeze()
+
+ # Remove the requested page
+ pageRemoved = self._windows[page]
+
+ # If the page is the current window, remove it from the sizer
+ # as well
+ if page == self._pages.GetSelection():
+ self._mainSizer.Detach(pageRemoved)
+
+ # Remove it from the array as well
+ self._windows.pop(page)
+ self.Thaw()
+
+ self._pages.DoDeletePage(page)
+
+ return True
+
+
+ def SetRightClickMenu(self, menu):
+ """ Sets the popup menu associated to a right click on a tab. """
+
+ self._pages._pRightClickMenu = menu
+
+
+ def GetPageText(self, nPage):
+ """ Returns the tab caption. """
+
+ return self._pages.GetPageText(nPage)
+
+
+ def SetGradientColours(self, fr, to, border):
+ """ Sets the gradient colours for the tab. """
+
+ self._pages._colorFrom = fr
+ self._pages._colorTo = to
+ self._pages._colorBorder = border
+
+
+ def SetGradientColourFrom(self, fr):
+ """ Sets the starting colour for the gradient. """
+
+ self._pages._colorFrom = fr
+
+
+ def SetGradientColourTo(self, to):
+ """ Sets the ending colour for the gradient. """
+
+ self._pages._colorTo = to
+
+
+ def SetGradientColourBorder(self, border):
+ """ Sets the tab border colour. """
+
+ self._pages._colorBorder = border
+
+
+ def GetGradientColourFrom(self):
+ """ Gets first gradient colour. """
+
+ return self._pages._colorFrom
+
+
+ def GetGradientColourTo(self):
+ """ Gets second gradient colour. """
+
+ return self._pages._colorTo
+
+
+ def GetGradientColourBorder(self):
+ """ Gets the tab border colour. """
+
+ return self._pages._colorBorder
+
+
+ def GetBorderColour(self):
+ """ Returns the border colour. """
+
+ return self._pages._colorBorder
+
+
+ def GetActiveTabTextColour(self):
+ """ Get the active tab text colour. """
+
+ return self._pages._activeTextColor
+
+
+ def SetPageImage(self, page, image):
+ """
+ Sets the image index for the given page. Image is an index into the
+ image list which was set with SetImageList.
+ """
+
+ self._pages.SetPageImage(page, image)
+
+
+ def GetPageImage(self, nPage):
+ """
+ Returns the image index for the given page. Image is an index into the
+ image list which was set with SetImageList.
+ """
+
+ return self._pages.GetPageImage(nPage)
+
+
+ def GetEnabled(self, page):
+ """ Returns whether a tab is enabled or not. """
+
+ return self._pages.GetEnabled(page)
+
+
+ def EnableTab(self, page, enabled=True):
+ """ Enables or disables a tab. """
+
+ if page >= len(self._windows):
+ return
+
+ self._windows[page].Enable(enabled)
+ self._pages.EnableTab(page, enabled)
+
+
+ def GetNonActiveTabTextColour(self):
+ """ Returns the non active tabs text colour. """
+
+ return self._pages._nonActiveTextColor
+
+
+ def SetNonActiveTabTextColour(self, color):
+ """ Sets the non active tabs text colour. """
+
+ self._pages._nonActiveTextColor = color
+
+
+ def SetTabAreaColour(self, color):
+ """ Sets the area behind the tabs colour. """
+
+ self._pages._tabAreaColor = color
+
+
+ def GetTabAreaColour(self):
+ """ Returns the area behind the tabs colour. """
+
+ return self._pages._tabAreaColor
+
+
+ def SetActiveTabColour(self, color):
+ """ Sets the active tab colour. """
+
+ self._pages._activeTabColor = color
+
+
+ def GetActiveTabColour(self):
+ """ Returns the active tab colour. """
+
+ return self._pages._activeTabColor
+
+ def EnsureVisible(self, page):
+ """ Ensures that a tab is visible. """
+ self._pages.DoSetSelection(page)
+
+# ---------------------------------------------------------------------------- #
+# Class PageContainer
+# Acts as a container for the pages you add to FlatNotebook
+# ---------------------------------------------------------------------------- #
+
+class PageContainer(wx.Panel):
+ """
+ This class acts as a container for the pages you add to L{FlatNotebook}.
+ """
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0):
+ """ Default class constructor. """
+
+ self._ImageList = None
+ self._iActivePage = -1
+ self._pDropTarget = None
+ self._nLeftClickZone = FNB_NOWHERE
+ self._iPreviousActivePage = -1
+
+ self._pRightClickMenu = None
+ self._nXButtonStatus = FNB_BTN_NONE
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+ self._pParent = parent
+ self._nRightButtonStatus = FNB_BTN_NONE
+ self._nLeftButtonStatus = FNB_BTN_NONE
+ self._nTabXButtonStatus = FNB_BTN_NONE
+
+ self._setCursor = False
+
+ self._pagesInfoVec = []
+
+ self._colorTo = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
+ self._colorFrom = wx.WHITE
+ self._activeTabColor = wx.WHITE
+ self._activeTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT)
+ self._nonActiveTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT)
+ self._tabAreaColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
+
+ self._nFrom = 0
+ self._isdragging = False
+
+ # Set default page height, this is done according to the system font
+ memDc = wx.MemoryDC()
+ memDc.SelectObject(wx.EmptyBitmap(1,1))
+
+# if "__WXGTK__" in wx.PlatformInfo:
+# boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+# boldFont.SetWeight(wx.BOLD)
+# memDc.SetFont(boldFont)
+
+ height = memDc.GetCharHeight()
+ tabHeight = height + FNB_HEIGHT_SPACER # We use 10 pixels as padding
+
+ wx.Panel.__init__(self, parent, id, pos, wx.Size(size.x, tabHeight),
+ style|wx.NO_BORDER|wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS)
+
+ self._pDropTarget = FNBDropTarget(self)
+ self.SetDropTarget(self._pDropTarget)
+ self._mgr = FNBRendererMgr()
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
+ self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown)
+ self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
+ self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+
+
+ def OnEraseBackground(self, event):
+ """ Handles the wx.EVT_ERASE_BACKGROUND event for L{PageContainer} (does nothing)."""
+
+ pass
+
+
+ def _ReShow(self):
+ """ Handles the Redraw of the tabs when the FNB_HIDE_ON_SINGLE_TAB has been removed """
+ self.Show()
+ self.GetParent()._mainSizer.Layout()
+ self.Refresh()
+
+
+ def OnPaint(self, event):
+ """ Handles the wx.EVT_PAINT event for L{PageContainer}."""
+
+ dc = wx.BufferedPaintDC(self)
+ renderer = self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag())
+ renderer.DrawTabs(self, dc)
+
+ if self.HasFlag(FNB_HIDE_ON_SINGLE_TAB) and len(self._pagesInfoVec) <= 1:
+ self.Hide()
+ self.GetParent()._mainSizer.Layout()
+ self.Refresh()
+
+
+ def AddPage(self, caption, selected=True, imgindex=-1):
+ """
+ Add a page to the L{FlatNotebook}.
+
+ @param window: Specifies the new page.
+ @param caption: Specifies the text for the new page.
+ @param selected: Specifies whether the page should be selected.
+ @param imgindex: Specifies the optional image index for the new page.
+
+ Return value:
+ True if successful, False otherwise.
+ """
+
+ if selected:
+
+ self._iPreviousActivePage = self._iActivePage
+ self._iActivePage = len(self._pagesInfoVec)
+
+ # Create page info and add it to the vector
+ pageInfo = PageInfo(caption, imgindex)
+ self._pagesInfoVec.append(pageInfo)
+ self.Refresh()
+
+
+ def InsertPage(self, indx, text, selected=True, imgindex=-1):
+ """
+ Inserts a new page at the specified position.
+
+ @param indx: Specifies the position of the new page.
+ @param page: Specifies the new page.
+ @param text: Specifies the text for the new page.
+ @param select: Specifies whether the page should be selected.
+ @param imgindex: Specifies the optional image index for the new page.
+
+ Return value:
+ True if successful, False otherwise.
+ """
+
+ if selected:
+
+ self._iPreviousActivePage = self._iActivePage
+ self._iActivePage = len(self._pagesInfoVec)
+
+ self._pagesInfoVec.insert(indx, PageInfo(text, imgindex))
+
+ self.Refresh()
+ return True
+
+
+ def OnSize(self, event):
+ """ Handles the wx.EVT_SIZE events for L{PageContainer}. """
+
+ # When resizing the control, try to fit to screen as many tabs as we can
+ style = self.GetParent().GetWindowStyleFlag()
+ renderer = self._mgr.GetRenderer(style)
+
+ fr = 0
+ page = self.GetSelection()
+
+ for fr in xrange(self._nFrom):
+ vTabInfo = renderer.NumberTabsCanFit(self, fr)
+ if page - fr >= len(vTabInfo):
+ continue
+ break
+
+ self._nFrom = fr
+
+ self.Refresh() # Call on paint
+ event.Skip()
+
+
+ def OnMiddleDown(self, event):
+ """ Handles the wx.EVT_MIDDLE_DOWN events for L{PageContainer}. """
+
+ # Test if this style is enabled
+ style = self.GetParent().GetWindowStyleFlag()
+
+ if not style & FNB_MOUSE_MIDDLE_CLOSES_TABS:
+ return
+
+ where, tabIdx = self.HitTest(event.GetPosition())
+
+ if where == FNB_TAB:
+ self.DeletePage(tabIdx)
+
+ event.Skip()
+
+
+ def OnMouseWheel(self, event):
+ """ Scroll tabs when the mouse whee """
+ delta = event.GetWheelRotation()
+ for tab in range(abs(delta/event.GetWheelDelta())):
+ if delta > 0:
+ before = self._nLeftButtonStatus
+ self._nLeftButtonStatus = FNB_BTN_PRESSED
+ self.RotateLeft()
+ self._nLeftButtonStatus = before
+ else:
+ before = self._nRightButtonStatus
+ self._nRightButtonStatus = FNB_BTN_PRESSED
+ self.RotateRight()
+ self._nRightButtonStatus = before
+
+ event.Skip()
+
+
+ def OnRightDown(self, event):
+ """ Handles the wx.EVT_RIGHT_DOWN events for L{PageContainer}. """
+
+ where, tabIdx = self.HitTest(event.GetPosition())
+
+ if where in [FNB_TAB, FNB_TAB_X] and tabIdx < len(self._pagesInfoVec):
+
+ if self._pagesInfoVec[tabIdx].GetEnabled():
+ # Fire events and eventually (if allowed) change selection
+ self.FireEvent(tabIdx)
+
+ # send a message to popup a custom menu
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, self.GetParent().GetId())
+ event.SetSelection(tabIdx)
+ event.SetOldSelection(self._iActivePage)
+ event.SetEventObject(self.GetParent())
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+
+ if self._pRightClickMenu:
+ self.PopupMenu(self._pRightClickMenu)
+
+ event.Skip()
+
+
+ def OnLeftDown(self, event):
+ """ Handles the wx.EVT_LEFT_DOWN events for L{PageContainer}. """
+
+ # Reset buttons status
+ self._nXButtonStatus = FNB_BTN_NONE
+ self._nLeftButtonStatus = FNB_BTN_NONE
+ self._nRightButtonStatus = FNB_BTN_NONE
+ self._nTabXButtonStatus = FNB_BTN_NONE
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+
+ self._nLeftClickZone, tabIdx = self.HitTest(event.GetPosition())
+
+ if self._nLeftClickZone == FNB_DROP_DOWN_ARROW:
+ self._nArrowDownButtonStatus = FNB_BTN_PRESSED
+ self.Refresh()
+ elif self._nLeftClickZone == FNB_LEFT_ARROW:
+ self._nLeftButtonStatus = FNB_BTN_PRESSED
+ self.Refresh()
+ elif self._nLeftClickZone == FNB_RIGHT_ARROW:
+ self._nRightButtonStatus = FNB_BTN_PRESSED
+ self.Refresh()
+ elif self._nLeftClickZone == FNB_X:
+ self._nXButtonStatus = FNB_BTN_PRESSED
+ self.Refresh()
+ elif self._nLeftClickZone == FNB_TAB_X:
+ self._nTabXButtonStatus = FNB_BTN_PRESSED
+ self.Refresh()
+
+ elif self._nLeftClickZone == FNB_TAB:
+
+ if self._iActivePage != tabIdx:
+
+ # In case the tab is disabled, we dont allow to choose it
+ if len(self._pagesInfoVec) > tabIdx and \
+ self._pagesInfoVec[tabIdx].GetEnabled():
+ self.FireEvent(tabIdx)
+
+
+ def RotateLeft(self):
+
+ if self._nFrom == 0:
+ return
+
+ # Make sure that the button was pressed before
+ if self._nLeftButtonStatus != FNB_BTN_PRESSED:
+ return
+
+ self._nLeftButtonStatus = FNB_BTN_HOVER
+
+ # We scroll left with bulks of 5
+ scrollLeft = self.GetNumTabsCanScrollLeft()
+
+ self._nFrom -= scrollLeft
+ if self._nFrom < 0:
+ self._nFrom = 0
+
+ self.Refresh()
+
+
+ def RotateRight(self):
+
+ if self._nFrom >= len(self._pagesInfoVec) - 1:
+ return
+
+ # Make sure that the button was pressed before
+ if self._nRightButtonStatus != FNB_BTN_PRESSED:
+ return
+
+ self._nRightButtonStatus = FNB_BTN_HOVER
+
+ # Check if the right most tab is visible, if it is
+ # don't rotate right anymore
+ if self._pagesInfoVec[len(self._pagesInfoVec)-1].GetPosition() != wx.Point(-1, -1):
+ return
+
+ self._nFrom += 1
+ self.Refresh()
+
+
+ def OnLeftUp(self, event):
+ """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """
+
+ # forget the zone that was initially clicked
+ self._nLeftClickZone = FNB_NOWHERE
+
+ where, tabIdx = self.HitTest(event.GetPosition())
+
+ # Make sure selected tab has focus
+# self.SetFocus()
+
+ if where == FNB_LEFT_ARROW:
+ self.RotateLeft()
+
+ elif where == FNB_RIGHT_ARROW:
+ self.RotateRight()
+
+ elif where == FNB_X:
+
+ # Make sure that the button was pressed before
+ if self._nXButtonStatus != FNB_BTN_PRESSED:
+ return
+
+ self._nXButtonStatus = FNB_BTN_HOVER
+
+ self.DeletePage(self._iActivePage)
+
+ elif where == FNB_TAB_X:
+
+ # Make sure that the button was pressed before
+ if self._nTabXButtonStatus != FNB_BTN_PRESSED:
+ return
+
+ self._nTabXButtonStatus = FNB_BTN_HOVER
+
+ self.DeletePage(self._iActivePage)
+
+ elif where == FNB_DROP_DOWN_ARROW:
+
+ # Make sure that the button was pressed before
+ if self._nArrowDownButtonStatus != FNB_BTN_PRESSED:
+ return
+
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+
+ # Refresh the button status
+ renderer = self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag())
+ dc = wx.ClientDC(self)
+ renderer.DrawDropDownArrow(self, dc)
+
+ self.PopupTabsMenu()
+
+ event.Skip()
+
+
+ def HitTest(self, pt):
+ """
+ HitTest method for L{PageContainer}.
+ Returns the flag (if any) and the hit page (if any).
+ """
+
+ style = self.GetParent().GetWindowStyleFlag()
+ render = self._mgr.GetRenderer(style)
+
+ fullrect = self.GetClientRect()
+ btnLeftPos = render.GetLeftButtonPos(self)
+ btnRightPos = render.GetRightButtonPos(self)
+ btnXPos = render.GetXPos(self)
+
+ tabIdx = -1
+
+ if len(self._pagesInfoVec) == 0:
+ return FNB_NOWHERE, tabIdx
+
+ rect = wx.Rect(btnXPos, 8, 16, 16)
+ if rect.Contains(pt):
+ return (style & FNB_NO_X_BUTTON and [FNB_NOWHERE] or [FNB_X])[0], tabIdx
+
+ rect = wx.Rect(btnRightPos, 8, 16, 16)
+ if style & FNB_DROPDOWN_TABS_LIST:
+ ddrect = wx.Rect(render.GetDropArrowButtonPos(self), 8, 16, 16)
+ if ddrect.Contains(pt):
+ return FNB_DROP_DOWN_ARROW, tabIdx
+
+ if rect.Contains(pt):
+ return (style & FNB_NO_NAV_BUTTONS and [FNB_NOWHERE] or [FNB_RIGHT_ARROW])[0], tabIdx
+
+ rect = wx.Rect(btnLeftPos, 8, 16, 16)
+ if rect.Contains(pt):
+ return (style & FNB_NO_NAV_BUTTONS and [FNB_NOWHERE] or [FNB_LEFT_ARROW])[0], tabIdx
+
+ # Test whether a left click was made on a tab
+ bFoundMatch = False
+
+ for cur in xrange(self._nFrom, len(self._pagesInfoVec)):
+
+ pgInfo = self._pagesInfoVec[cur]
+
+ if pgInfo.GetPosition() == wx.Point(-1, -1):
+ continue
+
+ if style & FNB_X_ON_TAB and cur == self.GetSelection():
+ # 'x' button exists on a tab
+ if self._pagesInfoVec[cur].GetXRect().Contains(pt):
+ return FNB_TAB_X, cur
+
+ if style & FNB_VC8:
+
+ if self._pagesInfoVec[cur].GetRegion().Contains(pt.x, pt.y):
+ if bFoundMatch or cur == self.GetSelection():
+ return FNB_TAB, cur
+
+ tabIdx = cur
+ bFoundMatch = True
+
+ else:
+
+ tabRect = wx.Rect(pgInfo.GetPosition().x, pgInfo.GetPosition().y,
+ pgInfo.GetSize().x, pgInfo.GetSize().y)
+
+ if tabRect.Contains(pt):
+ # We have a match
+ return FNB_TAB, cur
+
+ if bFoundMatch:
+ return FNB_TAB, tabIdx
+
+ if self._isdragging:
+ # We are doing DND, so check also the region outside the tabs
+ # try before the first tab
+ pgInfo = self._pagesInfoVec[0]
+ tabRect = wx.Rect(0, pgInfo.GetPosition().y, pgInfo.GetPosition().x, self.GetParent().GetSize().y)
+ if tabRect.Contains(pt):
+ return FNB_TAB, 0
+
+ # try after the last tab
+ pgInfo = self._pagesInfoVec[-1]
+ startpos = pgInfo.GetPosition().x+pgInfo.GetSize().x
+ tabRect = wx.Rect(startpos, pgInfo.GetPosition().y, fullrect.GetWidth()-startpos, self.GetParent().GetSize().y)
+
+ if tabRect.Contains(pt):
+ return FNB_TAB, len(self._pagesInfoVec)
+
+ # Default
+ return FNB_NOWHERE, -1
+
+
+ def SetSelection(self, page):
+ """ Sets the selected page. """
+
+ book = self.GetParent()
+ book.SetSelection(page)
+ self.DoSetSelection(page)
+
+
+ def DoSetSelection(self, page):
+ """ Does the actual selection of a page. """
+
+ if page < len(self._pagesInfoVec):
+ #! fix for tabfocus
+ da_page = self._pParent.GetPage(page)
+
+ if da_page != None:
+ da_page.SetFocus()
+
+ if not self.IsTabVisible(page):
+ # Try to remove one tab from start and try again
+
+ if not self.CanFitToScreen(page):
+
+ if self._nFrom > page:
+ self._nFrom = page
+ else:
+ while self._nFrom < page:
+ self._nFrom += 1
+ if self.CanFitToScreen(page):
+ break
+
+ self.Refresh()
+
+
+ def DeletePage(self, page):
+ """ Delete the specified page from L{FlatNotebook}. """
+
+ book = self.GetParent()
+ book.DeletePage(page)
+ book.Refresh()
+
+
+ def IsTabVisible(self, page):
+ """ Returns whether a tab is visible or not. """
+
+ iLastVisiblePage = self.GetLastVisibleTab()
+ return page <= iLastVisiblePage and page >= self._nFrom
+
+
+ def DoDeletePage(self, page):
+ """ Does the actual page deletion. """
+
+ # Remove the page from the vector
+ book = self.GetParent()
+ self._pagesInfoVec.pop(page)
+
+ # Thanks to Yiaanis AKA Mandrav
+ if self._iActivePage >= page:
+ self._iActivePage = self._iActivePage - 1
+ self._iPreviousActivePage = -1
+
+ # The delete page was the last first on the array,
+ # but the book still has more pages, so we set the
+ # active page to be the first one (0)
+ if self._iActivePage < 0 and len(self._pagesInfoVec) > 0:
+ self._iActivePage = 0
+ self._iPreviousActivePage = -1
+
+ # Refresh the tabs
+ if self._iActivePage >= 0:
+
+ book._bForceSelection = True
+
+ # Check for selection and send event
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
+ event.SetSelection(self._iActivePage)
+ event.SetOldSelection(self._iPreviousActivePage)
+ event.SetEventObject(self.GetParent())
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+
+ book.SetSelection(self._iActivePage)
+ book._bForceSelection = False
+
+ # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
+ event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
+ event.SetOldSelection(self._iPreviousActivePage)
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+
+# if not self._pagesInfoVec:
+# # Erase the page container drawings
+# dc = wx.ClientDC(self)
+# dc.Clear()
+
+
+ def DeleteAllPages(self):
+ """ Deletes all the pages. """
+
+ self._iActivePage = -1
+ self._iPreviousActivePage = -1
+ self._nFrom = 0
+ self._pagesInfoVec = []
+
+ # Erase the page container drawings
+ dc = wx.ClientDC(self)
+ dc.Clear()
+
+
+ def OnMouseMove(self, event):
+ """ Handles the wx.EVT_MOTION for L{PageContainer}. """
+
+ if self._pagesInfoVec and self.IsShown():
+
+ xButtonStatus = self._nXButtonStatus
+ xTabButtonStatus = self._nTabXButtonStatus
+ rightButtonStatus = self._nRightButtonStatus
+ leftButtonStatus = self._nLeftButtonStatus
+ dropDownButtonStatus = self._nArrowDownButtonStatus
+
+ style = self.GetParent().GetWindowStyleFlag()
+
+ self._nXButtonStatus = FNB_BTN_NONE
+ self._nRightButtonStatus = FNB_BTN_NONE
+ self._nLeftButtonStatus = FNB_BTN_NONE
+ self._nTabXButtonStatus = FNB_BTN_NONE
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+
+ where, tabIdx = self.HitTest(event.GetPosition())
+
+ if where == FNB_X:
+ if event.LeftIsDown():
+
+ self._nXButtonStatus = (self._nLeftClickZone==FNB_X and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
+
+ else:
+
+ self._nXButtonStatus = FNB_BTN_HOVER
+
+ elif where == FNB_DROP_DOWN_ARROW:
+ if event.LeftIsDown():
+
+ self._nArrowDownButtonStatus = (self._nLeftClickZone==FNB_DROP_DOWN_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
+
+ else:
+
+ self._nArrowDownButtonStatus = FNB_BTN_HOVER
+
+ elif where == FNB_TAB_X:
+ if event.LeftIsDown():
+
+ self._nTabXButtonStatus = (self._nLeftClickZone==FNB_TAB_X and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
+
+ else:
+
+ self._nTabXButtonStatus = FNB_BTN_HOVER
+
+ elif where == FNB_RIGHT_ARROW:
+ if event.LeftIsDown():
+
+ self._nRightButtonStatus = (self._nLeftClickZone==FNB_RIGHT_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
+
+ else:
+
+ self._nRightButtonStatus = FNB_BTN_HOVER
+
+ elif where == FNB_LEFT_ARROW:
+ if event.LeftIsDown():
+
+ self._nLeftButtonStatus = (self._nLeftClickZone==FNB_LEFT_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
+
+ else:
+
+ self._nLeftButtonStatus = FNB_BTN_HOVER
+
+ elif where == FNB_TAB:
+ # Call virtual method for showing tooltip
+ self.ShowTabTooltip(tabIdx)
+
+ if not self.GetEnabled(tabIdx):
+ # Set the cursor to be 'No-entry'
+ wx.SetCursor(wx.StockCursor(wx.CURSOR_NO_ENTRY))
+ self._setCursor = True
+ else:
+ if self._setCursor:
+ wx.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ self._setCursor = False
+
+ # Support for drag and drop
+ if event.Dragging() and not (style & FNB_NODRAG):
+
+ self._isdragging = True
+ draginfo = FNBDragInfo(self, tabIdx)
+ drginfo = cPickle.dumps(draginfo)
+ dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook"))
+ dataobject.SetData(drginfo)
+ dragSource = FNBDropSource(self)
+ dragSource.SetData(dataobject)
+ dragSource.DoDragDrop(wx.Drag_DefaultMove)
+
+ bRedrawX = self._nXButtonStatus != xButtonStatus
+ bRedrawRight = self._nRightButtonStatus != rightButtonStatus
+ bRedrawLeft = self._nLeftButtonStatus != leftButtonStatus
+ bRedrawTabX = self._nTabXButtonStatus != xTabButtonStatus
+ bRedrawDropArrow = self._nArrowDownButtonStatus != dropDownButtonStatus
+
+ render = self._mgr.GetRenderer(style)
+
+ if (bRedrawX or bRedrawRight or bRedrawLeft or bRedrawTabX or bRedrawDropArrow):
+
+ dc = wx.ClientDC(self)
+
+ if bRedrawX:
+
+ render.DrawX(self, dc)
+
+ if bRedrawLeft:
+
+ render.DrawLeftArrow(self, dc)
+
+ if bRedrawRight:
+
+ render.DrawRightArrow(self, dc)
+
+ if bRedrawTabX:
+
+ self.Refresh()
+
+ if bRedrawDropArrow:
+
+ render.DrawDropDownArrow(self, dc)
+
+ event.Skip()
+
+
+ def GetLastVisibleTab(self):
+ """ Returns the last visible tab. """
+
+ if self._nFrom < 0:
+ return -1
+
+ ii = 0
+
+ for ii in xrange(self._nFrom, len(self._pagesInfoVec)):
+
+ if self._pagesInfoVec[ii].GetPosition() == wx.Point(-1, -1):
+ break
+
+ return ii-1
+
+
+ def GetNumTabsCanScrollLeft(self):
+ """ Returns the number of tabs than can be scrolled left. """
+
+ if self._nFrom - 1 >= 0:
+ return 1
+
+ return 0
+
+
+ def IsDefaultTabs(self):
+ """ Returns whether a tab has a default style. """
+
+ style = self.GetParent().GetWindowStyleFlag()
+ res = (style & FNB_VC71) or (style & FNB_FANCY_TABS) or (style & FNB_VC8)
+ return not res
+
+
+ def AdvanceSelection(self, bForward=True):
+ """
+ Cycles through the tabs.
+ The call to this function generates the page changing events.
+ """
+
+ nSel = self.GetSelection()
+
+ if nSel < 0:
+ return
+
+ nMax = self.GetPageCount() - 1
+
+ if bForward:
+ newSelection = (nSel == nMax and [0] or [nSel + 1])[0]
+ else:
+ newSelection = (nSel == 0 and [nMax] or [nSel - 1])[0]
+
+ if not self._pagesInfoVec[newSelection].GetEnabled():
+ return
+
+ self.FireEvent(newSelection)
+
+
+ def OnMouseLeave(self, event):
+ """ Handles the wx.EVT_LEAVE_WINDOW event for L{PageContainer}. """
+
+ self._nLeftButtonStatus = FNB_BTN_NONE
+ self._nXButtonStatus = FNB_BTN_NONE
+ self._nRightButtonStatus = FNB_BTN_NONE
+ self._nTabXButtonStatus = FNB_BTN_NONE
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+
+ style = self.GetParent().GetWindowStyleFlag()
+ render = self._mgr.GetRenderer(style)
+
+ dc = wx.ClientDC(self)
+
+ render.DrawX(self, dc)
+ render.DrawLeftArrow(self, dc)
+ render.DrawRightArrow(self, dc)
+
+ selection = self.GetSelection()
+
+ if selection == -1:
+ event.Skip()
+ return
+
+ if not self.IsTabVisible(selection):
+ if selection == len(self._pagesInfoVec) - 1:
+ if not self.CanFitToScreen(selection):
+ event.Skip()
+ return
+ else:
+ event.Skip()
+ return
+
+ render.DrawTabX(self, dc, self._pagesInfoVec[selection].GetXRect(), selection, self._nTabXButtonStatus)
+ render.DrawFocusRectangle(dc, self, self._pagesInfoVec[selection])
+
+ event.Skip()
+
+
+ def OnMouseEnterWindow(self, event):
+ """ Handles the wx.EVT_ENTER_WINDOW event for L{PageContainer}. """
+
+ self._nLeftButtonStatus = FNB_BTN_NONE
+ self._nXButtonStatus = FNB_BTN_NONE
+ self._nRightButtonStatus = FNB_BTN_NONE
+ self._nLeftClickZone = FNB_BTN_NONE
+ self._nArrowDownButtonStatus = FNB_BTN_NONE
+
+ event.Skip()
+
+
+ def ShowTabTooltip(self, tabIdx):
+ """ Shows a tab tooltip. """
+
+ pWindow = self._pParent.GetPage(tabIdx)
+
+ if pWindow:
+ pToolTip = pWindow.GetToolTip()
+ if pToolTip and pToolTip.GetWindow() == pWindow:
+ self.SetToolTipString(pToolTip.GetTip())
+
+
+ def SetPageImage(self, page, imgindex):
+ """ Sets the image index associated to a page. """
+
+ if page < len(self._pagesInfoVec):
+
+ self._pagesInfoVec[page].SetImageIndex(imgindex)
+ self.Refresh()
+
+
+ def GetPageImage(self, page):
+ """ Returns the image index associated to a page. """
+
+ if page < len(self._pagesInfoVec):
+
+ return self._pagesInfoVec[page].GetImageIndex()
+
+ return -1
+
+
+ def OnDropTarget(self, x, y, nTabPage, wnd_oldContainer):
+ """ Handles the drop action from a DND operation. """
+
+ # Disable drag'n'drop for disabled tab
+ if len(wnd_oldContainer._pagesInfoVec) > nTabPage and \
+ not wnd_oldContainer._pagesInfoVec[nTabPage].GetEnabled():
+ return wx.DragCancel
+
+ self._isdragging = True
+ oldContainer = wnd_oldContainer
+ nIndex = -1
+
+ where, nIndex = self.HitTest(wx.Point(x, y))
+
+ oldNotebook = oldContainer.GetParent()
+ newNotebook = self.GetParent()
+
+ if oldNotebook == newNotebook:
+
+ if nTabPage >= 0:
+
+ if where == FNB_TAB:
+ self.MoveTabPage(nTabPage, nIndex)
+
+ elif self.GetParent().GetWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND:
+
+ if wx.Platform in ["__WXMSW__", "__WXGTK__", "__WXMAC__"]:
+ if nTabPage >= 0:
+
+ window = oldNotebook.GetPage(nTabPage)
+
+ if window:
+ where, nIndex = newNotebook._pages.HitTest(wx.Point(x, y))
+ caption = oldContainer.GetPageText(nTabPage)
+ imageindex = oldContainer.GetPageImage(nTabPage)
+ oldNotebook.RemovePage(nTabPage)
+ window.Reparent(newNotebook)
+
+ if imageindex >= 0:
+
+ bmp = oldNotebook.GetImageList().GetBitmap(imageindex)
+ newImageList = newNotebook.GetImageList()
+
+ if not newImageList:
+ xbmp, ybmp = bmp.GetWidth(), bmp.GetHeight()
+ newImageList = wx.ImageList(xbmp, ybmp)
+ imageindex = 0
+ else:
+ imageindex = newImageList.GetImageCount()
+
+ newImageList.Add(bmp)
+ newNotebook.SetImageList(newImageList)
+
+ newNotebook.InsertPage(nIndex, window, caption, True, imageindex)
+
+ self._isdragging = False
+
+ return wx.DragMove
+
+
+ def MoveTabPage(self, nMove, nMoveTo):
+ """ Moves a tab inside the same L{FlatNotebook}. """
+
+ if nMove == nMoveTo:
+ return
+
+ elif nMoveTo < len(self._pParent._windows):
+ nMoveTo = nMoveTo + 1
+
+ self._pParent.Freeze()
+
+ # Remove the window from the main sizer
+ nCurSel = self._pParent._pages.GetSelection()
+ self._pParent._mainSizer.Detach(self._pParent._windows[nCurSel])
+ self._pParent._windows[nCurSel].Hide()
+
+ pWindow = self._pParent._windows[nMove]
+ self._pParent._windows.pop(nMove)
+ self._pParent._windows.insert(nMoveTo-1, pWindow)
+
+ pgInfo = self._pagesInfoVec[nMove]
+
+ self._pagesInfoVec.pop(nMove)
+ self._pagesInfoVec.insert(nMoveTo - 1, pgInfo)
+
+ # Add the page according to the style
+ pSizer = self._pParent._mainSizer
+ style = self.GetParent().GetWindowStyleFlag()
+
+ if style & FNB_BOTTOM:
+
+ pSizer.Insert(0, pWindow, 1, wx.EXPAND)
+
+ else:
+
+ # We leave a space of 1 pixel around the window
+ pSizer.Add(pWindow, 1, wx.EXPAND)
+
+ pWindow.Show()
+
+ pSizer.Layout()
+ self._iActivePage = nMoveTo - 1
+ self._iPreviousActivePage = -1
+ self.DoSetSelection(self._iActivePage)
+ self.Refresh()
+ self._pParent.Thaw()
+
+
+ def CanFitToScreen(self, page):
+ """ Returns wheter a tab can fit in the left space in the screen or not. """
+
+ # Incase the from is greater than page,
+ # we need to reset the self._nFrom, so in order
+ # to force the caller to do so, we return false
+ if self._nFrom > page:
+ return False
+
+ style = self.GetParent().GetWindowStyleFlag()
+ render = self._mgr.GetRenderer(style)
+
+ vTabInfo = render.NumberTabsCanFit(self)
+
+ if page - self._nFrom >= len(vTabInfo):
+ return False
+
+ return True
+
+
+ def GetNumOfVisibleTabs(self):
+ """ Returns the number of visible tabs. """
+
+ count = 0
+ for ii in xrange(self._nFrom, len(self._pagesInfoVec)):
+ if self._pagesInfoVec[ii].GetPosition() == wx.Point(-1, -1):
+ break
+ count = count + 1
+
+ return count
+
+
+ def GetEnabled(self, page):
+ """ Returns whether a tab is enabled or not. """
+
+ if page >= len(self._pagesInfoVec):
+ return True # Seems strange, but this is the default
+
+ return self._pagesInfoVec[page].GetEnabled()
+
+
+ def EnableTab(self, page, enabled=True):
+ """ Enables or disables a tab. """
+
+ if page >= len(self._pagesInfoVec):
+ return
+
+ self._pagesInfoVec[page].EnableTab(enabled)
+
+
+ def GetSingleLineBorderColour(self):
+ """ Returns the colour for the single line border. """
+
+ if self.HasFlag(FNB_FANCY_TABS):
+ return self._colorFrom
+
+ return wx.WHITE
+
+
+ def HasFlag(self, flag):
+ """ Returns whether a flag is present in the L{FlatNotebook} style. """
+
+ style = self.GetParent().GetWindowStyleFlag()
+ res = (style & flag and [True] or [False])[0]
+ return res
+
+
+ def ClearFlag(self, flag):
+ """ Deletes a flag from the L{FlatNotebook} style. """
+
+ style = self.GetParent().GetWindowStyleFlag()
+ style &= ~flag
+ self.SetWindowStyleFlag(style)
+
+
+ def TabHasImage(self, tabIdx):
+ """ Returns whether a tab has an associated image index or not. """
+
+ if self._ImageList:
+ return self._pagesInfoVec[tabIdx].GetImageIndex() != -1
+
+ return False
+
+
+ def OnLeftDClick(self, event):
+ """ Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """
+
+ where, tabIdx = self.HitTest(event.GetPosition())
+
+ if where == FNB_RIGHT_ARROW:
+ self._nRightButtonStatus = FNB_BTN_PRESSED
+ self.RotateRight()
+
+ elif where == FNB_LEFT_ARROW:
+ self._nLeftButtonStatus = FNB_BTN_PRESSED
+ self.RotateLeft()
+
+ elif self.HasFlag(FNB_DCLICK_CLOSES_TABS):
+
+ if where == FNB_TAB:
+ self.DeletePage(tabIdx)
+
+ else:
+
+ event.Skip()
+
+
+ def OnSetFocus(self, event):
+ """ Handles the wx.EVT_SET_FOCUS event for L{PageContainer}. """
+
+ if self._iActivePage < 0:
+ event.Skip()
+ return
+
+ self.SetFocusedPage(self._iActivePage)
+
+
+ def OnKillFocus(self, event):
+ """ Handles the wx.EVT_KILL_FOCUS event for L{PageContainer}. """
+
+ self.SetFocusedPage()
+
+
+ def OnKeyDown(self, event):
+ """
+ When the PageContainer has the focus tabs can be changed with
+ the left/right arrow keys.
+ """
+ key = event.GetKeyCode()
+ if key == wx.WXK_LEFT:
+ self.GetParent().AdvanceSelection(False)
+ self.SetFocus()
+ elif key == wx.WXK_RIGHT:
+ self.GetParent().AdvanceSelection(True)
+ self.SetFocus()
+ elif key == wx.WXK_TAB and not event.ControlDown():
+ flags = 0
+ if not event.ShiftDown(): flags |= wx.NavigationKeyEvent.IsForward
+ if event.CmdDown(): flags |= wx.NavigationKeyEvent.WinChange
+ self.Navigate(flags)
+ else:
+ event.Skip()
+
+
+ def SetFocusedPage(self, pageIndex=-1):
+ """
+ Sets/Unsets the focus on the appropriate page.
+ If pageIndex is defaulted, we have lost focus and no focus indicator is drawn.
+ """
+
+ for indx, page in enumerate(self._pagesInfoVec):
+ if indx == pageIndex:
+ page._hasFocus = True
+ else:
+ page._hasFocus = False
+
+ self.Refresh()
+
+
+ def PopupTabsMenu(self):
+ """ Pops up the menu activated with the drop down arrow in the navigation area. """
+
+ popupMenu = wx.Menu()
+
+ longest = 0
+ has_bmp = False
+ for i in xrange(len(self._pagesInfoVec)):
+ pi = self._pagesInfoVec[i]
+ caption = pi.GetCaption()
+ item = wx.MenuItem(popupMenu, i+1, caption, caption, wx.ITEM_NORMAL)
+
+ # Save longest caption width for calculating menu width with
+ width = self.GetTextExtent(caption)[0]
+ if width > longest:
+ longest = width
+
+ self.Bind(wx.EVT_MENU, self.OnTabMenuSelection, item)
+
+ # There is an alignment problem with wx2.6.3 & Menus so only use
+ # images for versions above 2.6.3
+ if wx.VERSION > (2, 6, 3, 0) and self.TabHasImage(i):
+ has_bmp = True
+ item.SetBitmap(self.GetImageList().GetBitmap(pi.GetImageIndex()))
+
+ popupMenu.AppendItem(item)
+ item.Enable(pi.GetEnabled())
+
+ # Calculate the approximate size of the popupmenu for setting the
+ # position of the menu when its shown.
+ # Account for extra padding on left/right of text on mac menus
+ if wx.Platform in ['__WXMAC__', '__WXMSW__']:
+ longest += 32
+
+ # Bitmap width + padding
+ if has_bmp:
+ longest += 20
+
+ if not self.HasFlag(FNB_NO_X_BUTTON) or \
+ not self.HasFlag(FNB_NO_NAV_BUTTONS):
+ longest += 16
+
+ rect = self.GetClientRect()
+ self.PopupMenu(popupMenu,
+ wx.Point(rect.x + rect.GetWidth() - longest,
+ rect.y + rect.height))
+
+
+ def OnTabMenuSelection(self, event):
+ """ Handles the wx.EVT_MENU event for L{PageContainer}. """
+
+ selection = event.GetId() - 1
+ self.FireEvent(selection)
+
+
+ def FireEvent(self, selection):
+ """
+ Fires the wxEVT_FLATNOTEBOOK_PAGE_CHANGING and wxEVT_FLATNOTEBOOK_PAGE_CHANGED events
+ called from other methods (from menu selection or Smart Tabbing).
+ Utility function.
+ """
+
+ if selection == self._iActivePage:
+ # No events for the same selection
+ return
+
+ oldSelection = self._iActivePage
+
+ event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
+ event.SetSelection(selection)
+ event.SetOldSelection(oldSelection)
+ event.SetEventObject(self.GetParent())
+
+ if not self.GetParent().GetEventHandler().ProcessEvent(event) or event.IsAllowed():
+
+ self.SetSelection(selection)
+
+ # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
+ event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
+ event.SetOldSelection(oldSelection)
+ self.GetParent().GetEventHandler().ProcessEvent(event)
+# self.SetFocus()
+
+
+ def SetImageList(self, imglist):
+ """ Sets the image list for the page control. """
+
+ self._ImageList = imglist
+
+
+ def AssignImageList(self, imglist):
+ """ Assigns the image list for the page control. """
+
+ self._ImageList = imglist
+
+
+ def GetImageList(self):
+ """ Returns the image list for the page control. """
+
+ return self._ImageList
+
+
+ def GetSelection(self):
+ """ Returns the current selected page. """
+
+ return self._iActivePage
+
+
+ def GetPageCount(self):
+ """ Returns the number of tabs in the L{FlatNotebook} control. """
+
+ return len(self._pagesInfoVec)
+
+
+ def GetPageText(self, page):
+ """ Returns the tab caption of the page. """
+ if page < len(self._pagesInfoVec):
+ return self._pagesInfoVec[page].GetCaption()
+ else:
+ return u''
+
+
+ def SetPageText(self, page, text):
+ """ Sets the tab caption of the page. """
+ if page < len(self._pagesInfoVec):
+ self._pagesInfoVec[page].SetCaption(text)
+ return True
+ else:
+ return False
+
+
+ def DrawDragHint(self):
+ """ Draws small arrow at the place that the tab will be placed. """
+
+ # get the index of tab that will be replaced with the dragged tab
+ pt = wx.GetMousePosition()
+ client_pt = self.ScreenToClient(pt)
+ where, tabIdx = self.HitTest(client_pt)
+ self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag()).DrawDragHint(self, tabIdx)
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pkg_resources.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pkg_resources.py
new file mode 100644
index 0000000..1cbfec4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pkg_resources.py
@@ -0,0 +1,2507 @@
+"""Package resource API
+--------------------
+
+A resource is a logical file contained within a package, or a logical
+subdirectory thereof. The package resource API expects resource names
+to have their path parts separated with ``/``, *not* whatever the local
+path separator is. Do not use os.path operations to manipulate resource
+names being passed into the API.
+
+The package resource API is designed to work with normal filesystem packages,
+.egg files, and unpacked .egg files. It can also work in a limited way with
+.zip files and with custom PEP 302 loaders that support the ``get_data()``
+method.
+"""
+
+import sys, os, zipimport, time, re, imp, new
+
+# Fix for Python 2.6 deprecation warning
+try:
+ ImmutableSet = frozenset
+except NameError:
+ from sets import ImmutableSet
+
+from os import utime, rename, unlink # capture these to bypass sandboxing
+from os import open as os_open
+
+def get_supported_platform():
+ """Return this platform's maximum compatible version.
+
+ distutils.util.get_platform() normally reports the minimum version
+ of Mac OS X that would be required to *use* extensions produced by
+ distutils. But what we want when checking compatibility is to know the
+ version of Mac OS X that we are *running*. To allow usage of packages that
+ explicitly require a newer version of Mac OS X, we must also know the
+ current version of the OS.
+
+ If this condition occurs for any other platform with a version in its
+ platform strings, this function should be extended accordingly.
+ """
+ plat = get_build_platform(); m = macosVersionString.match(plat)
+ if m is not None and sys.platform == "darwin":
+ try:
+ plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3))
+ except ValueError:
+ pass # not Mac OS X
+ return plat
+
+__all__ = [
+ # Basic resource access and distribution/entry point discovery
+ 'require', 'run_script', 'get_provider', 'get_distribution',
+ 'load_entry_point', 'get_entry_map', 'get_entry_info', 'iter_entry_points',
+ 'resource_string', 'resource_stream', 'resource_filename',
+ 'resource_listdir', 'resource_exists', 'resource_isdir',
+
+ # Environmental control
+ 'declare_namespace', 'working_set', 'add_activation_listener',
+ 'find_distributions', 'set_extraction_path', 'cleanup_resources',
+ 'get_default_cache',
+
+ # Primary implementation classes
+ 'Environment', 'WorkingSet', 'ResourceManager',
+ 'Distribution', 'Requirement', 'EntryPoint',
+
+ # Exceptions
+ 'ResolutionError','VersionConflict','DistributionNotFound','UnknownExtra',
+ 'ExtractionError',
+
+ # Parsing functions and string utilities
+ 'parse_requirements', 'parse_version', 'safe_name', 'safe_version',
+ 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections',
+ 'safe_extra', 'to_filename',
+
+ # filesystem utilities
+ 'ensure_directory', 'normalize_path',
+
+ # Distribution "precedence" constants
+ 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST',
+
+ # "Provider" interfaces, implementations, and registration/lookup APIs
+ 'IMetadataProvider', 'IResourceProvider', 'FileMetadata',
+ 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider',
+ 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider',
+ 'register_finder', 'register_namespace_handler', 'register_loader_type',
+ 'fixup_namespace_packages', 'get_importer',
+
+ # Deprecated/backward compatibility only
+ 'run_main', 'AvailableDistributions',
+]
+class ResolutionError(Exception):
+ """Abstract base for dependency resolution errors"""
+ def __repr__(self): return self.__class__.__name__+repr(self.args)
+
+class VersionConflict(ResolutionError):
+ """An already-installed version conflicts with the requested version"""
+
+class DistributionNotFound(ResolutionError):
+ """A requested distribution was not found"""
+
+class UnknownExtra(ResolutionError):
+ """Distribution doesn't have an "extra feature" of the given name"""
+_provider_factories = {}
+PY_MAJOR = sys.version[:3]
+EGG_DIST = 3
+BINARY_DIST = 2
+SOURCE_DIST = 1
+CHECKOUT_DIST = 0
+DEVELOP_DIST = -1
+
+def register_loader_type(loader_type, provider_factory):
+ """Register `provider_factory` to make providers for `loader_type`
+
+ `loader_type` is the type or class of a PEP 302 ``module.__loader__``,
+ and `provider_factory` is a function that, passed a *module* object,
+ returns an ``IResourceProvider`` for that module.
+ """
+ _provider_factories[loader_type] = provider_factory
+
+def get_provider(moduleOrReq):
+ """Return an IResourceProvider for the named module or requirement"""
+ if isinstance(moduleOrReq,Requirement):
+ return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
+ try:
+ module = sys.modules[moduleOrReq]
+ except KeyError:
+ __import__(moduleOrReq)
+ module = sys.modules[moduleOrReq]
+ loader = getattr(module, '__loader__', None)
+ return _find_adapter(_provider_factories, loader)(module)
+
+def _macosx_vers(_cache=[]):
+ if not _cache:
+ info = os.popen('/usr/bin/sw_vers').read().splitlines()
+ for line in info:
+ key, value = line.split(None, 1)
+ if key == 'ProductVersion:':
+ _cache.append(value.strip().split("."))
+ break
+ else:
+ raise ValueError, "What?!"
+ return _cache[0]
+
+def _macosx_arch(machine):
+ return {'PowerPC':'ppc', 'Power_Macintosh':'ppc'}.get(machine,machine)
+
+def get_build_platform():
+ """Return this platform's string for platform-specific distributions
+
+ XXX Currently this is the same as ``distutils.util.get_platform()``, but it
+ needs some hacks for Linux and Mac OS X.
+ """
+ from distutils.util import get_platform
+ plat = get_platform()
+ if sys.platform == "darwin" and not plat.startswith('macosx-'):
+ try:
+ version = _macosx_vers()
+ machine = os.uname()[4].replace(" ", "_")
+ return "macosx-%d.%d-%s" % (int(version[0]), int(version[1]),
+ _macosx_arch(machine))
+ except ValueError:
+ # if someone is running a non-Mac darwin system, this will fall
+ # through to the default implementation
+ pass
+ return plat
+
+macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)")
+darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)")
+get_platform = get_build_platform # XXX backward compat
+
+
+
+def compatible_platforms(provided,required):
+ """Can code for the `provided` platform run on the `required` platform?
+
+ Returns true if either platform is ``None``, or the platforms are equal.
+
+ XXX Needs compatibility checks for Linux and other unixy OSes.
+ """
+ if provided is None or required is None or provided==required:
+ return True # easy case
+
+ # Mac OS X special cases
+ reqMac = macosVersionString.match(required)
+ if reqMac:
+ provMac = macosVersionString.match(provided)
+
+ # is this a Mac package?
+ if not provMac:
+ # this is backwards compatibility for packages built before
+ # setuptools 0.6. All packages built after this point will
+ # use the new macosx designation.
+ provDarwin = darwinVersionString.match(provided)
+ if provDarwin:
+ dversion = int(provDarwin.group(1))
+ macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2))
+ if dversion == 7 and macosversion >= "10.3" or \
+ dversion == 8 and macosversion >= "10.4":
+
+ #import warnings
+ #warnings.warn("Mac eggs should be rebuilt to "
+ # "use the macosx designation instead of darwin.",
+ # category=DeprecationWarning)
+ return True
+ return False # egg isn't macosx or legacy darwin
+
+ # are they the same major version and machine type?
+ if provMac.group(1) != reqMac.group(1) or \
+ provMac.group(3) != reqMac.group(3):
+ return False
+
+
+
+ # is the required OS major update >= the provided one?
+ if int(provMac.group(2)) > int(reqMac.group(2)):
+ return False
+
+ return True
+
+ # XXX Linux and other platforms' special cases should go here
+ return False
+
+
+def run_script(dist_spec, script_name):
+ """Locate distribution `dist_spec` and run its `script_name` script"""
+ ns = sys._getframe(1).f_globals
+ name = ns['__name__']
+ ns.clear()
+ ns['__name__'] = name
+ require(dist_spec)[0].run_script(script_name, ns)
+
+run_main = run_script # backward compatibility
+
+def get_distribution(dist):
+ """Return a current distribution object for a Requirement or string"""
+ if isinstance(dist,basestring): dist = Requirement.parse(dist)
+ if isinstance(dist,Requirement): dist = get_provider(dist)
+ if not isinstance(dist,Distribution):
+ raise TypeError("Expected string, Requirement, or Distribution", dist)
+ return dist
+
+def load_entry_point(dist, group, name):
+ """Return `name` entry point of `group` for `dist` or raise ImportError"""
+ return get_distribution(dist).load_entry_point(group, name)
+
+def get_entry_map(dist, group=None):
+ """Return the entry point map for `group`, or the full entry map"""
+ return get_distribution(dist).get_entry_map(group)
+
+def get_entry_info(dist, group, name):
+ """Return the EntryPoint object for `group`+`name`, or ``None``"""
+ return get_distribution(dist).get_entry_info(group, name)
+
+
+class IMetadataProvider:
+
+ def has_metadata(name):
+ """Does the package's distribution contain the named metadata?"""
+
+ def get_metadata(name):
+ """The named metadata resource as a string"""
+
+ def get_metadata_lines(name):
+ """Yield named metadata resource as list of non-blank non-comment lines
+
+ Leading and trailing whitespace is stripped from each line, and lines
+ with ``#`` as the first non-blank character are omitted."""
+
+ def metadata_isdir(name):
+ """Is the named metadata a directory? (like ``os.path.isdir()``)"""
+
+ def metadata_listdir(name):
+ """List of metadata names in the directory (like ``os.listdir()``)"""
+
+ def run_script(script_name, namespace):
+ """Execute the named script in the supplied namespace dictionary"""
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class IResourceProvider(IMetadataProvider):
+ """An object that provides access to package resources"""
+
+ def get_resource_filename(manager, resource_name):
+ """Return a true filesystem path for `resource_name`
+
+ `manager` must be an ``IResourceManager``"""
+
+ def get_resource_stream(manager, resource_name):
+ """Return a readable file-like object for `resource_name`
+
+ `manager` must be an ``IResourceManager``"""
+
+ def get_resource_string(manager, resource_name):
+ """Return a string containing the contents of `resource_name`
+
+ `manager` must be an ``IResourceManager``"""
+
+ def has_resource(resource_name):
+ """Does the package contain the named resource?"""
+
+ def resource_isdir(resource_name):
+ """Is the named resource a directory? (like ``os.path.isdir()``)"""
+
+ def resource_listdir(resource_name):
+ """List of resource names in the directory (like ``os.listdir()``)"""
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class WorkingSet(object):
+ """A collection of active distributions on sys.path (or a similar list)"""
+
+ def __init__(self, entries=None):
+ """Create working set from list of path entries (default=sys.path)"""
+ self.entries = []
+ self.entry_keys = {}
+ self.by_key = {}
+ self.callbacks = []
+
+ if entries is None:
+ entries = sys.path
+
+ for entry in entries:
+ self.add_entry(entry)
+
+
+ def add_entry(self, entry):
+ """Add a path item to ``.entries``, finding any distributions on it
+
+ ``find_distributions(entry,False)`` is used to find distributions
+ corresponding to the path entry, and they are added. `entry` is
+ always appended to ``.entries``, even if it is already present.
+ (This is because ``sys.path`` can contain the same value more than
+ once, and the ``.entries`` of the ``sys.path`` WorkingSet should always
+ equal ``sys.path``.)
+ """
+ self.entry_keys.setdefault(entry, [])
+ self.entries.append(entry)
+ for dist in find_distributions(entry, True):
+ self.add(dist, entry, False)
+
+
+ def __contains__(self,dist):
+ """True if `dist` is the active distribution for its project"""
+ return self.by_key.get(dist.key) == dist
+
+
+
+
+
+ def find(self, req):
+ """Find a distribution matching requirement `req`
+
+ If there is an active distribution for the requested project, this
+ returns it as long as it meets the version requirement specified by
+ `req`. But, if there is an active distribution for the project and it
+ does *not* meet the `req` requirement, ``VersionConflict`` is raised.
+ If there is no active distribution for the requested project, ``None``
+ is returned.
+ """
+ dist = self.by_key.get(req.key)
+ if dist is not None and dist not in req:
+ raise VersionConflict(dist,req) # XXX add more info
+ else:
+ return dist
+
+ def iter_entry_points(self, group, name=None):
+ """Yield entry point objects from `group` matching `name`
+
+ If `name` is None, yields all entry points in `group` from all
+ distributions in the working set, otherwise only ones matching
+ both `group` and `name` are yielded (in distribution order).
+ """
+ for dist in self:
+ entries = dist.get_entry_map(group)
+ if name is None:
+ for ep in entries.values():
+ yield ep
+ elif name in entries:
+ yield entries[name]
+
+ def run_script(self, requires, script_name):
+ """Locate distribution for `requires` and run `script_name` script"""
+ ns = sys._getframe(1).f_globals
+ name = ns['__name__']
+ ns.clear()
+ ns['__name__'] = name
+ self.require(requires)[0].run_script(script_name, ns)
+
+
+
+ def __iter__(self):
+ """Yield distributions for non-duplicate projects in the working set
+
+ The yield order is the order in which the items' path entries were
+ added to the working set.
+ """
+ seen = {}
+ for item in self.entries:
+ for key in self.entry_keys[item]:
+ if key not in seen:
+ seen[key]=1
+ yield self.by_key[key]
+
+ def add(self, dist, entry=None, insert=True):
+ """Add `dist` to working set, associated with `entry`
+
+ If `entry` is unspecified, it defaults to the ``.location`` of `dist`.
+ On exit from this routine, `entry` is added to the end of the working
+ set's ``.entries`` (if it wasn't already present).
+
+ `dist` is only added to the working set if it's for a project that
+ doesn't already have a distribution in the set. If it's added, any
+ callbacks registered with the ``subscribe()`` method will be called.
+ """
+ if insert:
+ dist.insert_on(self.entries, entry)
+
+ if entry is None:
+ entry = dist.location
+ keys = self.entry_keys.setdefault(entry,[])
+ keys2 = self.entry_keys.setdefault(dist.location,[])
+ if dist.key in self.by_key:
+ return # ignore hidden distros
+
+ self.by_key[dist.key] = dist
+ if dist.key not in keys:
+ keys.append(dist.key)
+ if dist.key not in keys2:
+ keys2.append(dist.key)
+ self._added_new(dist)
+
+ def resolve(self, requirements, env=None, installer=None):
+ """List all distributions needed to (recursively) meet `requirements`
+
+ `requirements` must be a sequence of ``Requirement`` objects. `env`,
+ if supplied, should be an ``Environment`` instance. If
+ not supplied, it defaults to all distributions available within any
+ entry or distribution in the working set. `installer`, if supplied,
+ will be invoked with each requirement that cannot be met by an
+ already-installed distribution; it should return a ``Distribution`` or
+ ``None``.
+ """
+
+ requirements = list(requirements)[::-1] # set up the stack
+ processed = {} # set of processed requirements
+ best = {} # key -> dist
+ to_activate = []
+
+ while requirements:
+ req = requirements.pop(0) # process dependencies breadth-first
+ if req in processed:
+ # Ignore cyclic or redundant dependencies
+ continue
+ dist = best.get(req.key)
+ if dist is None:
+ # Find the best distribution and add it to the map
+ dist = self.by_key.get(req.key)
+ if dist is None:
+ if env is None:
+ env = Environment(self.entries)
+ dist = best[req.key] = env.best_match(req, self, installer)
+ if dist is None:
+ raise DistributionNotFound(req) # XXX put more info here
+ to_activate.append(dist)
+ if dist not in req:
+ # Oops, the "best" so far conflicts with a dependency
+ raise VersionConflict(dist,req) # XXX put more info here
+ requirements.extend(dist.requires(req.extras)[::-1])
+ processed[req] = True
+
+ return to_activate # return list of distros to activate
+
+ def find_plugins(self,
+ plugin_env, full_env=None, installer=None, fallback=True
+ ):
+ """Find all activatable distributions in `plugin_env`
+
+ Example usage::
+
+ distributions, errors = working_set.find_plugins(
+ Environment(plugin_dirlist)
+ )
+ map(working_set.add, distributions) # add plugins+libs to sys.path
+ print "Couldn't load", errors # display errors
+
+ The `plugin_env` should be an ``Environment`` instance that contains
+ only distributions that are in the project's "plugin directory" or
+ directories. The `full_env`, if supplied, should be an ``Environment``
+ contains all currently-available distributions. If `full_env` is not
+ supplied, one is created automatically from the ``WorkingSet`` this
+ method is called on, which will typically mean that every directory on
+ ``sys.path`` will be scanned for distributions.
+
+ `installer` is a standard installer callback as used by the
+ ``resolve()`` method. The `fallback` flag indicates whether we should
+ attempt to resolve older versions of a plugin if the newest version
+ cannot be resolved.
+
+ This method returns a 2-tuple: (`distributions`, `error_info`), where
+ `distributions` is a list of the distributions found in `plugin_env`
+ that were loadable, along with any other distributions that are needed
+ to resolve their dependencies. `error_info` is a dictionary mapping
+ unloadable plugin distributions to an exception instance describing the
+ error that occurred. Usually this will be a ``DistributionNotFound`` or
+ ``VersionConflict`` instance.
+ """
+
+ plugin_projects = list(plugin_env)
+ plugin_projects.sort() # scan project names in alphabetic order
+
+ error_info = {}
+ distributions = {}
+
+ if full_env is None:
+ env = Environment(self.entries)
+ env += plugin_env
+ else:
+ env = full_env + plugin_env
+
+ shadow_set = self.__class__([])
+ map(shadow_set.add, self) # put all our entries in shadow_set
+
+ for project_name in plugin_projects:
+
+ for dist in plugin_env[project_name]:
+
+ req = [dist.as_requirement()]
+
+ try:
+ resolvees = shadow_set.resolve(req, env, installer)
+
+ except ResolutionError,v:
+ error_info[dist] = v # save error info
+ if fallback:
+ continue # try the next older version of project
+ else:
+ break # give up on this project, keep going
+
+ else:
+ map(shadow_set.add, resolvees)
+ distributions.update(dict.fromkeys(resolvees))
+
+ # success, no need to try any more versions of this project
+ break
+
+ distributions = list(distributions)
+ distributions.sort()
+
+ return distributions, error_info
+
+
+
+
+
+ def require(self, *requirements):
+ """Ensure that distributions matching `requirements` are activated
+
+ `requirements` must be a string or a (possibly-nested) sequence
+ thereof, specifying the distributions and versions required. The
+ return value is a sequence of the distributions that needed to be
+ activated to fulfill the requirements; all relevant distributions are
+ included, even if they were already activated in this working set.
+ """
+
+ needed = self.resolve(parse_requirements(requirements))
+
+ for dist in needed:
+ self.add(dist)
+
+ return needed
+
+
+ def subscribe(self, callback):
+ """Invoke `callback` for all distributions (including existing ones)"""
+ if callback in self.callbacks:
+ return
+ self.callbacks.append(callback)
+ for dist in self:
+ callback(dist)
+
+
+ def _added_new(self, dist):
+ for callback in self.callbacks:
+ callback(dist)
+
+
+
+
+
+
+
+
+
+
+
+class Environment(object):
+ """Searchable snapshot of distributions on a search path"""
+
+ def __init__(self, search_path=None, platform=get_supported_platform(), python=PY_MAJOR):
+ """Snapshot distributions available on a search path
+
+ Any distributions found on `search_path` are added to the environment.
+ `search_path` should be a sequence of ``sys.path`` items. If not
+ supplied, ``sys.path`` is used.
+
+ `platform` is an optional string specifying the name of the platform
+ that platform-specific distributions must be compatible with. If
+ unspecified, it defaults to the current platform. `python` is an
+ optional string naming the desired version of Python (e.g. ``'2.4'``);
+ it defaults to the current version.
+
+ You may explicitly set `platform` (and/or `python`) to ``None`` if you
+ wish to map *all* distributions, not just those compatible with the
+ running platform or Python version.
+ """
+ self._distmap = {}
+ self._cache = {}
+ self.platform = platform
+ self.python = python
+ self.scan(search_path)
+
+ def can_add(self, dist):
+ """Is distribution `dist` acceptable for this environment?
+
+ The distribution must match the platform and python version
+ requirements specified when this environment was created, or False
+ is returned.
+ """
+ return (self.python is None or dist.py_version is None
+ or dist.py_version==self.python) \
+ and compatible_platforms(dist.platform,self.platform)
+
+ def remove(self, dist):
+ """Remove `dist` from the environment"""
+ self._distmap[dist.key].remove(dist)
+
+ def scan(self, search_path=None):
+ """Scan `search_path` for distributions usable in this environment
+
+ Any distributions found are added to the environment.
+ `search_path` should be a sequence of ``sys.path`` items. If not
+ supplied, ``sys.path`` is used. Only distributions conforming to
+ the platform/python version defined at initialization are added.
+ """
+ if search_path is None:
+ search_path = sys.path
+
+ for item in search_path:
+ for dist in find_distributions(item):
+ self.add(dist)
+
+ def __getitem__(self,project_name):
+ """Return a newest-to-oldest list of distributions for `project_name`
+ """
+ try:
+ return self._cache[project_name]
+ except KeyError:
+ project_name = project_name.lower()
+ if project_name not in self._distmap:
+ return []
+
+ if project_name not in self._cache:
+ dists = self._cache[project_name] = self._distmap[project_name]
+ _sort_dists(dists)
+
+ return self._cache[project_name]
+
+ def add(self,dist):
+ """Add `dist` if we ``can_add()`` it and it isn't already added"""
+ if self.can_add(dist) and dist.has_version():
+ dists = self._distmap.setdefault(dist.key,[])
+ if dist not in dists:
+ dists.append(dist)
+ if dist.key in self._cache:
+ _sort_dists(self._cache[dist.key])
+
+
+ def best_match(self, req, working_set, installer=None):
+ """Find distribution best matching `req` and usable on `working_set`
+
+ This calls the ``find(req)`` method of the `working_set` to see if a
+ suitable distribution is already active. (This may raise
+ ``VersionConflict`` if an unsuitable version of the project is already
+ active in the specified `working_set`.) If a suitable distribution
+ isn't active, this method returns the newest distribution in the
+ environment that meets the ``Requirement`` in `req`. If no suitable
+ distribution is found, and `installer` is supplied, then the result of
+ calling the environment's ``obtain(req, installer)`` method will be
+ returned.
+ """
+ dist = working_set.find(req)
+ if dist is not None:
+ return dist
+ for dist in self[req.key]:
+ if dist in req:
+ return dist
+ return self.obtain(req, installer) # try and download/install
+
+ def obtain(self, requirement, installer=None):
+ """Obtain a distribution matching `requirement` (e.g. via download)
+
+ Obtain a distro that matches requirement (e.g. via download). In the
+ base ``Environment`` class, this routine just returns
+ ``installer(requirement)``, unless `installer` is None, in which case
+ None is returned instead. This method is a hook that allows subclasses
+ to attempt other ways of obtaining a distribution before falling back
+ to the `installer` argument."""
+ if installer is not None:
+ return installer(requirement)
+
+ def __iter__(self):
+ """Yield the unique project names of the available distributions"""
+ for key in self._distmap.keys():
+ if self[key]: yield key
+
+
+
+
+ def __iadd__(self, other):
+ """In-place addition of a distribution or environment"""
+ if isinstance(other,Distribution):
+ self.add(other)
+ elif isinstance(other,Environment):
+ for project in other:
+ for dist in other[project]:
+ self.add(dist)
+ else:
+ raise TypeError("Can't add %r to environment" % (other,))
+ return self
+
+ def __add__(self, other):
+ """Add an environment or distribution to an environment"""
+ new = self.__class__([], platform=None, python=None)
+ for env in self, other:
+ new += env
+ return new
+
+
+AvailableDistributions = Environment # XXX backward compatibility
+
+
+class ExtractionError(RuntimeError):
+ """An error occurred extracting a resource
+
+ The following attributes are available from instances of this exception:
+
+ manager
+ The resource manager that raised this exception
+
+ cache_path
+ The base directory for resource extraction
+
+ original_error
+ The exception instance that caused extraction to fail
+ """
+
+
+
+
+class ResourceManager:
+ """Manage resource extraction and packages"""
+ extraction_path = None
+
+ def __init__(self):
+ self.cached_files = {}
+
+ def resource_exists(self, package_or_requirement, resource_name):
+ """Does the named resource exist?"""
+ return get_provider(package_or_requirement).has_resource(resource_name)
+
+ def resource_isdir(self, package_or_requirement, resource_name):
+ """Is the named resource an existing directory?"""
+ return get_provider(package_or_requirement).resource_isdir(
+ resource_name
+ )
+
+ def resource_filename(self, package_or_requirement, resource_name):
+ """Return a true filesystem path for specified resource"""
+ return get_provider(package_or_requirement).get_resource_filename(
+ self, resource_name
+ )
+
+ def resource_stream(self, package_or_requirement, resource_name):
+ """Return a readable file-like object for specified resource"""
+ return get_provider(package_or_requirement).get_resource_stream(
+ self, resource_name
+ )
+
+ def resource_string(self, package_or_requirement, resource_name):
+ """Return specified resource as a string"""
+ return get_provider(package_or_requirement).get_resource_string(
+ self, resource_name
+ )
+
+ def resource_listdir(self, package_or_requirement, resource_name):
+ """List the contents of the named resource directory"""
+ return get_provider(package_or_requirement).resource_listdir(
+ resource_name
+ )
+
+ def extraction_error(self):
+ """Give an error message for problems extracting file(s)"""
+
+ old_exc = sys.exc_info()[1]
+ cache_path = self.extraction_path or get_default_cache()
+
+ err = ExtractionError("""Can't extract file(s) to egg cache
+
+The following error occurred while trying to extract file(s) to the Python egg
+cache:
+
+ %s
+
+The Python egg cache directory is currently set to:
+
+ %s
+
+Perhaps your account does not have write access to this directory? You can
+change the cache directory by setting the PYTHON_EGG_CACHE environment
+variable to point to an accessible directory.
+""" % (old_exc, cache_path)
+ )
+ err.manager = self
+ err.cache_path = cache_path
+ err.original_error = old_exc
+ raise err
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def get_cache_path(self, archive_name, names=()):
+ """Return absolute location in cache for `archive_name` and `names`
+
+ The parent directory of the resulting path will be created if it does
+ not already exist. `archive_name` should be the base filename of the
+ enclosing egg (which may not be the name of the enclosing zipfile!),
+ including its ".egg" extension. `names`, if provided, should be a
+ sequence of path name parts "under" the egg's extraction location.
+
+ This method should only be called by resource providers that need to
+ obtain an extraction location, and only for names they intend to
+ extract, as it tracks the generated names for possible cleanup later.
+ """
+ extract_path = self.extraction_path or get_default_cache()
+ target_path = os.path.join(extract_path, archive_name+'-tmp', *names)
+ try:
+ ensure_directory(target_path)
+ except:
+ self.extraction_error()
+
+ self.cached_files[target_path] = 1
+ return target_path
+
+
+ def postprocess(self, tempname, filename):
+ """Perform any platform-specific postprocessing of `tempname`
+
+ This is where Mac header rewrites should be done; other platforms don't
+ have anything special they should do.
+
+ Resource providers should call this method ONLY after successfully
+ extracting a compressed resource. They must NOT call it on resources
+ that are already in the filesystem.
+
+ `tempname` is the current (temporary) name of the file, and `filename`
+ is the name it will be renamed to by the caller after this routine
+ returns.
+ """
+ # XXX
+
+
+ def set_extraction_path(self, path):
+ """Set the base path where resources will be extracted to, if needed.
+
+ If you do not call this routine before any extractions take place, the
+ path defaults to the return value of ``get_default_cache()``. (Which
+ is based on the ``PYTHON_EGG_CACHE`` environment variable, with various
+ platform-specific fallbacks. See that routine's documentation for more
+ details.)
+
+ Resources are extracted to subdirectories of this path based upon
+ information given by the ``IResourceProvider``. You may set this to a
+ temporary directory, but then you must call ``cleanup_resources()`` to
+ delete the extracted files when done. There is no guarantee that
+ ``cleanup_resources()`` will be able to remove all extracted files.
+
+ (Note: you may not change the extraction path for a given resource
+ manager once resources have been extracted, unless you first call
+ ``cleanup_resources()``.)
+ """
+ if self.cached_files:
+ raise ValueError(
+ "Can't change extraction path, files already extracted"
+ )
+
+ self.extraction_path = path
+
+ def cleanup_resources(self, force=False):
+ """
+ Delete all extracted resource files and directories, returning a list
+ of the file and directory names that could not be successfully removed.
+ This function does not have any concurrency protection, so it should
+ generally only be called when the extraction path is a temporary
+ directory exclusive to a single process. This method is not
+ automatically called; you must call it explicitly or register it as an
+ ``atexit`` function if you wish to ensure cleanup of a temporary
+ directory used for extractions.
+ """
+ # XXX
+
+
+
+def get_default_cache():
+ """Determine the default cache location
+
+ This returns the ``PYTHON_EGG_CACHE`` environment variable, if set.
+ Otherwise, on Windows, it returns a "Python-Eggs" subdirectory of the
+ "Application Data" directory. On all other systems, it's "~/.python-eggs".
+ """
+ try:
+ return os.environ['PYTHON_EGG_CACHE']
+ except KeyError:
+ pass
+
+ if os.name!='nt':
+ return os.path.expanduser('~/.python-eggs')
+
+ app_data = 'Application Data' # XXX this may be locale-specific!
+ app_homes = [
+ (('APPDATA',), None), # best option, should be locale-safe
+ (('USERPROFILE',), app_data),
+ (('HOMEDRIVE','HOMEPATH'), app_data),
+ (('HOMEPATH',), app_data),
+ (('HOME',), None),
+ (('WINDIR',), app_data), # 95/98/ME
+ ]
+
+ for keys, subdir in app_homes:
+ dirname = ''
+ for key in keys:
+ if key in os.environ:
+ dirname = os.path.join(os.environ[key])
+ else:
+ break
+ else:
+ if subdir:
+ dirname = os.path.join(dirname,subdir)
+ return os.path.join(dirname, 'Python-Eggs')
+ else:
+ raise RuntimeError(
+ "Please set the PYTHON_EGG_CACHE enviroment variable"
+ )
+
+def safe_name(name):
+ """Convert an arbitrary string to a standard distribution name
+
+ Any runs of non-alphanumeric/. characters are replaced with a single '-'.
+ """
+ return re.sub('[^A-Za-z0-9.]+', '-', name)
+
+
+def safe_version(version):
+ """Convert an arbitrary string to a standard version string
+
+ Spaces become dots, and all other non-alphanumeric characters become
+ dashes, with runs of multiple dashes condensed to a single dash.
+ """
+ version = version.replace(' ','.')
+ return re.sub('[^A-Za-z0-9.]+', '-', version)
+
+
+def safe_extra(extra):
+ """Convert an arbitrary string to a standard 'extra' name
+
+ Any runs of non-alphanumeric characters are replaced with a single '_',
+ and the result is always lowercased.
+ """
+ return re.sub('[^A-Za-z0-9.]+', '_', extra).lower()
+
+
+def to_filename(name):
+ """Convert a project or version name to its filename-escaped form
+
+ Any '-' characters are currently replaced with '_'.
+ """
+ return name.replace('-','_')
+
+
+
+
+
+
+
+
+class NullProvider:
+ """Try to implement resources and metadata for arbitrary PEP 302 loaders"""
+
+ egg_name = None
+ egg_info = None
+ loader = None
+
+ def __init__(self, module):
+ self.loader = getattr(module, '__loader__', None)
+ self.module_path = os.path.dirname(getattr(module, '__file__', ''))
+
+ def get_resource_filename(self, manager, resource_name):
+ return self._fn(self.module_path, resource_name)
+
+ def get_resource_stream(self, manager, resource_name):
+ return StringIO(self.get_resource_string(manager, resource_name))
+
+ def get_resource_string(self, manager, resource_name):
+ return self._get(self._fn(self.module_path, resource_name))
+
+ def has_resource(self, resource_name):
+ return self._has(self._fn(self.module_path, resource_name))
+
+ def has_metadata(self, name):
+ return self.egg_info and self._has(self._fn(self.egg_info,name))
+
+ def get_metadata(self, name):
+ if not self.egg_info:
+ return ""
+ return self._get(self._fn(self.egg_info,name))
+
+ def get_metadata_lines(self, name):
+ return yield_lines(self.get_metadata(name))
+
+ def resource_isdir(self,resource_name):
+ return self._isdir(self._fn(self.module_path, resource_name))
+
+ def metadata_isdir(self,name):
+ return self.egg_info and self._isdir(self._fn(self.egg_info,name))
+
+
+ def resource_listdir(self,resource_name):
+ return self._listdir(self._fn(self.module_path,resource_name))
+
+ def metadata_listdir(self,name):
+ if self.egg_info:
+ return self._listdir(self._fn(self.egg_info,name))
+ return []
+
+ def run_script(self,script_name,namespace):
+ script = 'scripts/'+script_name
+ if not self.has_metadata(script):
+ raise ResolutionError("No script named %r" % script_name)
+ script_text = self.get_metadata(script).replace('\r\n','\n')
+ script_text = script_text.replace('\r','\n')
+ script_filename = self._fn(self.egg_info,script)
+ namespace['__file__'] = script_filename
+ if os.path.exists(script_filename):
+ execfile(script_filename, namespace, namespace)
+ else:
+ from linecache import cache
+ cache[script_filename] = (
+ len(script_text), 0, script_text.split('\n'), script_filename
+ )
+ script_code = compile(script_text,script_filename,'exec')
+ exec script_code in namespace, namespace
+
+ def _has(self, path):
+ raise NotImplementedError(
+ "Can't perform this operation for unregistered loader type"
+ )
+
+ def _isdir(self, path):
+ raise NotImplementedError(
+ "Can't perform this operation for unregistered loader type"
+ )
+
+ def _listdir(self, path):
+ raise NotImplementedError(
+ "Can't perform this operation for unregistered loader type"
+ )
+
+ def _fn(self, base, resource_name):
+ return os.path.join(base, *resource_name.split('/'))
+
+ def _get(self, path):
+ if hasattr(self.loader, 'get_data'):
+ return self.loader.get_data(path)
+ raise NotImplementedError(
+ "Can't perform this operation for loaders without 'get_data()'"
+ )
+
+register_loader_type(object, NullProvider)
+
+
+class EggProvider(NullProvider):
+ """Provider based on a virtual filesystem"""
+
+ def __init__(self,module):
+ NullProvider.__init__(self,module)
+ self._setup_prefix()
+
+ def _setup_prefix(self):
+ # we assume here that our metadata may be nested inside a "basket"
+ # of multiple eggs; that's why we use module_path instead of .archive
+ path = self.module_path
+ old = None
+ while path!=old:
+ if path.lower().endswith('.egg'):
+ self.egg_name = os.path.basename(path)
+ self.egg_info = os.path.join(path, 'EGG-INFO')
+ self.egg_root = path
+ break
+ old = path
+ path, base = os.path.split(path)
+
+
+
+
+
+
+
+
+class DefaultProvider(EggProvider):
+ """Provides access to package resources in the filesystem"""
+
+ def _has(self, path):
+ return os.path.exists(path)
+
+ def _isdir(self,path):
+ return os.path.isdir(path)
+
+ def _listdir(self,path):
+ return os.listdir(path)
+
+ def get_resource_stream(self, manager, resource_name):
+ return open(self._fn(self.module_path, resource_name), 'rb')
+
+ def _get(self, path):
+ stream = open(path, 'rb')
+ try:
+ return stream.read()
+ finally:
+ stream.close()
+
+register_loader_type(type(None), DefaultProvider)
+
+
+class EmptyProvider(NullProvider):
+ """Provider that returns nothing for all requests"""
+
+ _isdir = _has = lambda self,path: False
+ _get = lambda self,path: ''
+ _listdir = lambda self,path: []
+ module_path = None
+
+ def __init__(self):
+ pass
+
+empty_provider = EmptyProvider()
+
+
+
+
+class ZipProvider(EggProvider):
+ """Resource support for zips and eggs"""
+
+ eagers = None
+
+ def __init__(self, module):
+ EggProvider.__init__(self,module)
+ self.zipinfo = zipimport._zip_directory_cache[self.loader.archive]
+ self.zip_pre = self.loader.archive+os.sep
+
+ def _zipinfo_name(self, fspath):
+ # Convert a virtual filename (full path to file) into a zipfile subpath
+ # usable with the zipimport directory cache for our target archive
+ if fspath.startswith(self.zip_pre):
+ return fspath[len(self.zip_pre):]
+ raise AssertionError(
+ "%s is not a subpath of %s" % (fspath,self.zip_pre)
+ )
+
+ def _parts(self,zip_path):
+ # Convert a zipfile subpath into an egg-relative path part list
+ fspath = self.zip_pre+zip_path # pseudo-fs path
+ if fspath.startswith(self.egg_root+os.sep):
+ return fspath[len(self.egg_root)+1:].split(os.sep)
+ raise AssertionError(
+ "%s is not a subpath of %s" % (fspath,self.egg_root)
+ )
+
+ def get_resource_filename(self, manager, resource_name):
+ if not self.egg_name:
+ raise NotImplementedError(
+ "resource_filename() only supported for .egg, not .zip"
+ )
+ # no need to lock for extraction, since we use temp names
+ zip_path = self._resource_to_zip(resource_name)
+ eagers = self._get_eager_resources()
+ if '/'.join(self._parts(zip_path)) in eagers:
+ for name in eagers:
+ self._extract_resource(manager, self._eager_to_zip(name))
+ return self._extract_resource(manager, zip_path)
+
+ def _extract_resource(self, manager, zip_path):
+
+ if zip_path in self._index():
+ for name in self._index()[zip_path]:
+ last = self._extract_resource(
+ manager, os.path.join(zip_path, name)
+ )
+ return os.path.dirname(last) # return the extracted directory name
+
+ zip_stat = self.zipinfo[zip_path]
+ t,d,size = zip_stat[5], zip_stat[6], zip_stat[3]
+ date_time = (
+ (d>>9)+1980, (d>>5)&0xF, d&0x1F, # ymd
+ (t&0xFFFF)>>11, (t>>5)&0x3F, (t&0x1F) * 2, 0, 0, -1 # hms, etc.
+ )
+ timestamp = time.mktime(date_time)
+
+ try:
+ real_path = manager.get_cache_path(
+ self.egg_name, self._parts(zip_path)
+ )
+
+ if os.path.isfile(real_path):
+ stat = os.stat(real_path)
+ if stat.st_size==size and stat.st_mtime==timestamp:
+ # size and stamp match, don't bother extracting
+ return real_path
+
+ outf, tmpnam = _mkstemp(".$extract", dir=os.path.dirname(real_path))
+ os.write(outf, self.loader.get_data(zip_path))
+ os.close(outf)
+ utime(tmpnam, (timestamp,timestamp))
+ manager.postprocess(tmpnam, real_path)
+
+ try:
+ rename(tmpnam, real_path)
+
+ except os.error:
+ if os.path.isfile(real_path):
+ stat = os.stat(real_path)
+
+ if stat.st_size==size and stat.st_mtime==timestamp:
+ # size and stamp match, somebody did it just ahead of
+ # us, so we're done
+ return real_path
+ elif os.name=='nt': # Windows, del old file and retry
+ unlink(real_path)
+ rename(tmpnam, real_path)
+ return real_path
+ raise
+
+ except os.error:
+ manager.extraction_error() # report a user-friendly error
+
+ return real_path
+
+ def _get_eager_resources(self):
+ if self.eagers is None:
+ eagers = []
+ for name in ('native_libs.txt', 'eager_resources.txt'):
+ if self.has_metadata(name):
+ eagers.extend(self.get_metadata_lines(name))
+ self.eagers = eagers
+ return self.eagers
+
+ def _index(self):
+ try:
+ return self._dirindex
+ except AttributeError:
+ ind = {}
+ for path in self.zipinfo:
+ parts = path.split(os.sep)
+ while parts:
+ parent = os.sep.join(parts[:-1])
+ if parent in ind:
+ ind[parent].append(parts[-1])
+ break
+ else:
+ ind[parent] = [parts.pop()]
+ self._dirindex = ind
+ return ind
+
+ def _has(self, fspath):
+ zip_path = self._zipinfo_name(fspath)
+ return zip_path in self.zipinfo or zip_path in self._index()
+
+ def _isdir(self,fspath):
+ return self._zipinfo_name(fspath) in self._index()
+
+ def _listdir(self,fspath):
+ return list(self._index().get(self._zipinfo_name(fspath), ()))
+
+ def _eager_to_zip(self,resource_name):
+ return self._zipinfo_name(self._fn(self.egg_root,resource_name))
+
+ def _resource_to_zip(self,resource_name):
+ return self._zipinfo_name(self._fn(self.module_path,resource_name))
+
+register_loader_type(zipimport.zipimporter, ZipProvider)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class FileMetadata(EmptyProvider):
+ """Metadata handler for standalone PKG-INFO files
+
+ Usage::
+
+ metadata = FileMetadata("/path/to/PKG-INFO")
+
+ This provider rejects all data and metadata requests except for PKG-INFO,
+ which is treated as existing, and will be the contents of the file at
+ the provided location.
+ """
+
+ def __init__(self,path):
+ self.path = path
+
+ def has_metadata(self,name):
+ return name=='PKG-INFO'
+
+ def get_metadata(self,name):
+ if name=='PKG-INFO':
+ return open(self.path,'rU').read()
+ raise KeyError("No metadata except PKG-INFO is available")
+
+ def get_metadata_lines(self,name):
+ return yield_lines(self.get_metadata(name))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class PathMetadata(DefaultProvider):
+ """Metadata provider for egg directories
+
+ Usage::
+
+ # Development eggs:
+
+ egg_info = "/path/to/PackageName.egg-info"
+ base_dir = os.path.dirname(egg_info)
+ metadata = PathMetadata(base_dir, egg_info)
+ dist_name = os.path.splitext(os.path.basename(egg_info))[0]
+ dist = Distribution(basedir,project_name=dist_name,metadata=metadata)
+
+ # Unpacked egg directories:
+
+ egg_path = "/path/to/PackageName-ver-pyver-etc.egg"
+ metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO'))
+ dist = Distribution.from_filename(egg_path, metadata=metadata)
+ """
+
+ def __init__(self, path, egg_info):
+ self.module_path = path
+ self.egg_info = egg_info
+
+
+class EggMetadata(ZipProvider):
+ """Metadata provider for .egg files"""
+
+ def __init__(self, importer):
+ """Create a metadata provider from a zipimporter"""
+
+ self.zipinfo = zipimport._zip_directory_cache[importer.archive]
+ self.zip_pre = importer.archive+os.sep
+ self.loader = importer
+ if importer.prefix:
+ self.module_path = os.path.join(importer.archive, importer.prefix)
+ else:
+ self.module_path = importer.archive
+ self._setup_prefix()
+
+
+class ImpWrapper:
+ """PEP 302 Importer that wraps Python's "normal" import algorithm"""
+
+ def __init__(self, path=None):
+ self.path = path
+
+ def find_module(self, fullname, path=None):
+ subname = fullname.split(".")[-1]
+ if subname != fullname and self.path is None:
+ return None
+ if self.path is None:
+ path = None
+ else:
+ path = [self.path]
+ try:
+ file, filename, etc = imp.find_module(subname, path)
+ except ImportError:
+ return None
+ return ImpLoader(file, filename, etc)
+
+
+class ImpLoader:
+ """PEP 302 Loader that wraps Python's "normal" import algorithm"""
+
+ def __init__(self, file, filename, etc):
+ self.file = file
+ self.filename = filename
+ self.etc = etc
+
+ def load_module(self, fullname):
+ try:
+ mod = imp.load_module(fullname, self.file, self.filename, self.etc)
+ finally:
+ if self.file: self.file.close()
+ # Note: we don't set __loader__ because we want the module to look
+ # normal; i.e. this is just a wrapper for standard import machinery
+ return mod
+
+
+
+
+def get_importer(path_item):
+ """Retrieve a PEP 302 "importer" for the given path item
+
+ If there is no importer, this returns a wrapper around the builtin import
+ machinery. The returned importer is only cached if it was created by a
+ path hook.
+ """
+ try:
+ importer = sys.path_importer_cache[path_item]
+ except KeyError:
+ for hook in sys.path_hooks:
+ try:
+ importer = hook(path_item)
+ except ImportError:
+ pass
+ else:
+ break
+ else:
+ importer = None
+
+ sys.path_importer_cache.setdefault(path_item,importer)
+ if importer is None:
+ try:
+ importer = ImpWrapper(path_item)
+ except ImportError:
+ pass
+ return importer
+
+try:
+ from pkgutil import get_importer, ImpImporter
+except ImportError:
+ pass # Python 2.3 or 2.4, use our own implementation
+else:
+ ImpWrapper = ImpImporter # Python 2.5, use pkgutil's implementation
+ del ImpLoader, ImpImporter
+
+
+
+
+
+
+_distribution_finders = {}
+
+def register_finder(importer_type, distribution_finder):
+ """Register `distribution_finder` to find distributions in sys.path items
+
+ `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item
+ handler), and `distribution_finder` is a callable that, passed a path
+ item and the importer instance, yields ``Distribution`` instances found on
+ that path item. See ``pkg_resources.find_on_path`` for an example."""
+ _distribution_finders[importer_type] = distribution_finder
+
+
+def find_distributions(path_item, only=False):
+ """Yield distributions accessible via `path_item`"""
+ importer = get_importer(path_item)
+ finder = _find_adapter(_distribution_finders, importer)
+ return finder(importer, path_item, only)
+
+def find_in_zip(importer, path_item, only=False):
+ metadata = EggMetadata(importer)
+ if metadata.has_metadata('PKG-INFO'):
+ yield Distribution.from_filename(path_item, metadata=metadata)
+ if only:
+ return # don't yield nested distros
+ for subitem in metadata.resource_listdir('/'):
+ if subitem.endswith('.egg'):
+ subpath = os.path.join(path_item, subitem)
+ for dist in find_in_zip(zipimport.zipimporter(subpath), subpath):
+ yield dist
+
+register_finder(zipimport.zipimporter, find_in_zip)
+
+def StringIO(*args, **kw):
+ """Thunk to load the real StringIO on demand"""
+ global StringIO
+ try:
+ from cStringIO import StringIO
+ except ImportError:
+ from StringIO import StringIO
+ return StringIO(*args,**kw)
+
+def find_nothing(importer, path_item, only=False):
+ return ()
+register_finder(object,find_nothing)
+
+def find_on_path(importer, path_item, only=False):
+ """Yield distributions accessible on a sys.path directory"""
+ path_item = _normalize_cached(path_item)
+
+ if os.path.isdir(path_item):
+ if path_item.lower().endswith('.egg'):
+ # unpacked egg
+ yield Distribution.from_filename(
+ path_item, metadata=PathMetadata(
+ path_item, os.path.join(path_item,'EGG-INFO')
+ )
+ )
+ else:
+ # scan for .egg and .egg-info in directory
+ for entry in os.listdir(path_item):
+ lower = entry.lower()
+ if lower.endswith('.egg-info'):
+ fullpath = os.path.join(path_item, entry)
+ if os.path.isdir(fullpath):
+ # egg-info directory, allow getting metadata
+ metadata = PathMetadata(path_item, fullpath)
+ else:
+ metadata = FileMetadata(fullpath)
+ yield Distribution.from_location(
+ path_item,entry,metadata,precedence=DEVELOP_DIST
+ )
+ elif not only and lower.endswith('.egg'):
+ for dist in find_distributions(os.path.join(path_item, entry)):
+ yield dist
+ elif not only and lower.endswith('.egg-link'):
+ for line in file(os.path.join(path_item, entry)):
+ if not line.strip(): continue
+ for item in find_distributions(line.rstrip()):
+ yield item
+
+register_finder(ImpWrapper,find_on_path)
+
+_namespace_handlers = {}
+_namespace_packages = {}
+
+def register_namespace_handler(importer_type, namespace_handler):
+ """Register `namespace_handler` to declare namespace packages
+
+ `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item
+ handler), and `namespace_handler` is a callable like this::
+
+ def namespace_handler(importer,path_entry,moduleName,module):
+ # return a path_entry to use for child packages
+
+ Namespace handlers are only called if the importer object has already
+ agreed that it can handle the relevant path item, and they should only
+ return a subpath if the module __path__ does not already contain an
+ equivalent subpath. For an example namespace handler, see
+ ``pkg_resources.file_ns_handler``.
+ """
+ _namespace_handlers[importer_type] = namespace_handler
+
+def _handle_ns(packageName, path_item):
+ """Ensure that named package includes a subpath of path_item (if needed)"""
+ importer = get_importer(path_item)
+ if importer is None:
+ return None
+ loader = importer.find_module(packageName)
+ if loader is None:
+ return None
+ module = sys.modules.get(packageName)
+ if module is None:
+ module = sys.modules[packageName] = new.module(packageName)
+ module.__path__ = []; _set_parent_ns(packageName)
+ elif not hasattr(module,'__path__'):
+ raise TypeError("Not a package:", packageName)
+ handler = _find_adapter(_namespace_handlers, importer)
+ subpath = handler(importer,path_item,packageName,module)
+ if subpath is not None:
+ path = module.__path__; path.append(subpath)
+ loader.load_module(packageName); module.__path__ = path
+ return subpath
+
+def declare_namespace(packageName):
+ """Declare that package 'packageName' is a namespace package"""
+
+ imp.acquire_lock()
+ try:
+ if packageName in _namespace_packages:
+ return
+
+ path, parent = sys.path, None
+ if '.' in packageName:
+ parent = '.'.join(packageName.split('.')[:-1])
+ declare_namespace(parent)
+ __import__(parent)
+ try:
+ path = sys.modules[parent].__path__
+ except AttributeError:
+ raise TypeError("Not a package:", parent)
+
+ # Track what packages are namespaces, so when new path items are added,
+ # they can be updated
+ _namespace_packages.setdefault(parent,[]).append(packageName)
+ _namespace_packages.setdefault(packageName,[])
+
+ for path_item in path:
+ # Ensure all the parent's path items are reflected in the child,
+ # if they apply
+ _handle_ns(packageName, path_item)
+
+ finally:
+ imp.release_lock()
+
+def fixup_namespace_packages(path_item, parent=None):
+ """Ensure that previously-declared namespace packages include path_item"""
+ imp.acquire_lock()
+ try:
+ for package in _namespace_packages.get(parent,()):
+ subpath = _handle_ns(package, path_item)
+ if subpath: fixup_namespace_packages(subpath,package)
+ finally:
+ imp.release_lock()
+
+def file_ns_handler(importer, path_item, packageName, module):
+ """Compute an ns-package subpath for a filesystem or zipfile importer"""
+
+ subpath = os.path.join(path_item, packageName.split('.')[-1])
+ normalized = _normalize_cached(subpath)
+ for item in module.__path__:
+ if _normalize_cached(item)==normalized:
+ break
+ else:
+ # Only return the path if it's not already there
+ return subpath
+
+register_namespace_handler(ImpWrapper,file_ns_handler)
+register_namespace_handler(zipimport.zipimporter,file_ns_handler)
+
+
+def null_ns_handler(importer, path_item, packageName, module):
+ return None
+
+register_namespace_handler(object,null_ns_handler)
+
+
+def normalize_path(filename):
+ """Normalize a file/dir name for comparison purposes"""
+ return os.path.normcase(os.path.realpath(filename))
+
+def _normalize_cached(filename,_cache={}):
+ try:
+ return _cache[filename]
+ except KeyError:
+ _cache[filename] = result = normalize_path(filename)
+ return result
+
+def _set_parent_ns(packageName):
+ parts = packageName.split('.')
+ name = parts.pop()
+ if parts:
+ parent = '.'.join(parts)
+ setattr(sys.modules[parent], name, sys.modules[packageName])
+
+
+def yield_lines(strs):
+ """Yield non-empty/non-comment lines of a ``basestring`` or sequence"""
+ if isinstance(strs,basestring):
+ for s in strs.splitlines():
+ s = s.strip()
+ if s and not s.startswith('#'): # skip blank lines/comments
+ yield s
+ else:
+ for ss in strs:
+ for s in yield_lines(ss):
+ yield s
+
+LINE_END = re.compile(r"\s*(#.*)?$").match # whitespace and comment
+CONTINUE = re.compile(r"\s*\\\s*(#.*)?$").match # line continuation
+DISTRO = re.compile(r"\s*((\w|[-.])+)").match # Distribution or extra
+VERSION = re.compile(r"\s*(<=?|>=?|==|!=)\s*((\w|[-.])+)").match # ver. info
+COMMA = re.compile(r"\s*,").match # comma between items
+OBRACKET = re.compile(r"\s*\[").match
+CBRACKET = re.compile(r"\s*\]").match
+MODULE = re.compile(r"\w+(\.\w+)*$").match
+EGG_NAME = re.compile(
+ r"(?P<name>[^-]+)"
+ r"( -(?P<ver>[^-]+) (-py(?P<pyver>[^-]+) (-(?P<plat>.+))? )? )?",
+ re.VERBOSE | re.IGNORECASE
+).match
+
+component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE)
+replace = {'pre':'c', 'preview':'c','-':'final-','rc':'c'}.get
+
+def _parse_version_parts(s):
+ for part in component_re.split(s):
+ part = replace(part,part)
+ if not part or part=='.':
+ continue
+ if part[:1] in '0123456789':
+ yield part.zfill(8) # pad for numeric comparison
+ else:
+ yield '*'+part
+
+ yield '*final' # ensure that alpha/beta/candidate are before final
+
+def parse_version(s):
+ """Convert a version string to a chronologically-sortable key
+
+ This is a rough cross between distutils' StrictVersion and LooseVersion;
+ if you give it versions that would work with StrictVersion, then it behaves
+ the same; otherwise it acts like a slightly-smarter LooseVersion. It is
+ *possible* to create pathological version coding schemes that will fool
+ this parser, but they should be very rare in practice.
+
+ The returned value will be a tuple of strings. Numeric portions of the
+ version are padded to 8 digits so they will compare numerically, but
+ without relying on how numbers compare relative to strings. Dots are
+ dropped, but dashes are retained. Trailing zeros between alpha segments
+ or dashes are suppressed, so that e.g. "2.4.0" is considered the same as
+ "2.4". Alphanumeric parts are lower-cased.
+
+ The algorithm assumes that strings like "-" and any alpha string that
+ alphabetically follows "final" represents a "patch level". So, "2.4-1"
+ is assumed to be a branch or patch of "2.4", and therefore "2.4.1" is
+ considered newer than "2.4-1", whic in turn is newer than "2.4".
+
+ Strings like "a", "b", "c", "alpha", "beta", "candidate" and so on (that
+ come before "final" alphabetically) are assumed to be pre-release versions,
+ so that the version "2.4" is considered newer than "2.4a1".
+
+ Finally, to handle miscellaneous cases, the strings "pre", "preview", and
+ "rc" are treated as if they were "c", i.e. as though they were release
+ candidates, and therefore are not as new as a version string that does not
+ contain them.
+ """
+ parts = []
+ for part in _parse_version_parts(s.lower()):
+ if part.startswith('*'):
+ if part<'*final': # remove '-' before a prerelease tag
+ while parts and parts[-1]=='*final-': parts.pop()
+ # remove trailing zeros from each series of numeric parts
+ while parts and parts[-1]=='00000000':
+ parts.pop()
+ parts.append(part)
+ return tuple(parts)
+
+class EntryPoint(object):
+ """Object representing an advertised importable object"""
+
+ def __init__(self, name, module_name, attrs=(), extras=(), dist=None):
+ if not MODULE(module_name):
+ raise ValueError("Invalid module name", module_name)
+ self.name = name
+ self.module_name = module_name
+ self.attrs = tuple(attrs)
+ self.extras = Requirement.parse(("x[%s]" % ','.join(extras))).extras
+ self.dist = dist
+
+ def __str__(self):
+ s = "%s = %s" % (self.name, self.module_name)
+ if self.attrs:
+ s += ':' + '.'.join(self.attrs)
+ if self.extras:
+ s += ' [%s]' % ','.join(self.extras)
+ return s
+
+ def __repr__(self):
+ return "EntryPoint.parse(%r)" % str(self)
+
+ def load(self, require=True, env=None, installer=None):
+ if require: self.require(env, installer)
+ entry = __import__(self.module_name, globals(),globals(), ['__name__'])
+ for attr in self.attrs:
+ try:
+ entry = getattr(entry,attr)
+ except AttributeError:
+ raise ImportError("%r has no %r attribute" % (entry,attr))
+ return entry
+
+ def require(self, env=None, installer=None):
+ if self.extras and not self.dist:
+ raise UnknownExtra("Can't require() without a distribution", self)
+ map(working_set.add,
+ working_set.resolve(self.dist.requires(self.extras),env,installer))
+
+
+
+ #@classmethod
+ def parse(cls, src, dist=None):
+ """Parse a single entry point from string `src`
+
+ Entry point syntax follows the form::
+
+ name = some.module:some.attr [extra1,extra2]
+
+ The entry name and module name are required, but the ``:attrs`` and
+ ``[extras]`` parts are optional
+ """
+ try:
+ attrs = extras = ()
+ name,value = src.split('=',1)
+ if '[' in value:
+ value,extras = value.split('[',1)
+ req = Requirement.parse("x["+extras)
+ if req.specs: raise ValueError
+ extras = req.extras
+ if ':' in value:
+ value,attrs = value.split(':',1)
+ if not MODULE(attrs.rstrip()):
+ raise ValueError
+ attrs = attrs.rstrip().split('.')
+ except ValueError:
+ raise ValueError(
+ "EntryPoint must be in 'name=module:attrs [extras]' format",
+ src
+ )
+ else:
+ return cls(name.strip(), value.strip(), attrs, extras, dist)
+
+ parse = classmethod(parse)
+
+
+
+
+
+
+
+
+ #@classmethod
+ def parse_group(cls, group, lines, dist=None):
+ """Parse an entry point group"""
+ if not MODULE(group):
+ raise ValueError("Invalid group name", group)
+ this = {}
+ for line in yield_lines(lines):
+ ep = cls.parse(line, dist)
+ if ep.name in this:
+ raise ValueError("Duplicate entry point", group, ep.name)
+ this[ep.name]=ep
+ return this
+
+ parse_group = classmethod(parse_group)
+
+ #@classmethod
+ def parse_map(cls, data, dist=None):
+ """Parse a map of entry point groups"""
+ if isinstance(data,dict):
+ data = data.items()
+ else:
+ data = split_sections(data)
+ maps = {}
+ for group, lines in data:
+ if group is None:
+ if not lines:
+ continue
+ raise ValueError("Entry points must be listed in groups")
+ group = group.strip()
+ if group in maps:
+ raise ValueError("Duplicate group name", group)
+ maps[group] = cls.parse_group(group, lines, dist)
+ return maps
+
+ parse_map = classmethod(parse_map)
+
+
+
+
+
+
+class Distribution(object):
+ """Wrap an actual or potential sys.path entry w/metadata"""
+ def __init__(self,
+ location=None, metadata=None, project_name=None, version=None,
+ py_version=PY_MAJOR, platform=None, precedence = EGG_DIST
+ ):
+ self.project_name = safe_name(project_name or 'Unknown')
+ if version is not None:
+ self._version = safe_version(version)
+ self.py_version = py_version
+ self.platform = platform
+ self.location = location
+ self.precedence = precedence
+ self._provider = metadata or empty_provider
+
+ #@classmethod
+ def from_location(cls,location,basename,metadata=None,**kw):
+ project_name, version, py_version, platform = [None]*4
+ basename, ext = os.path.splitext(basename)
+ if ext.lower() in (".egg",".egg-info"):
+ match = EGG_NAME(basename)
+ if match:
+ project_name, version, py_version, platform = match.group(
+ 'name','ver','pyver','plat'
+ )
+ return cls(
+ location, metadata, project_name=project_name, version=version,
+ py_version=py_version, platform=platform, **kw
+ )
+ from_location = classmethod(from_location)
+
+ hashcmp = property(
+ lambda self: (
+ getattr(self,'parsed_version',()), self.precedence, self.key,
+ -len(self.location or ''), self.location, self.py_version,
+ self.platform
+ )
+ )
+ def __cmp__(self, other): return cmp(self.hashcmp, other)
+ def __hash__(self): return hash(self.hashcmp)
+
+ # These properties have to be lazy so that we don't have to load any
+ # metadata until/unless it's actually needed. (i.e., some distributions
+ # may not know their name or version without loading PKG-INFO)
+
+ #@property
+ def key(self):
+ try:
+ return self._key
+ except AttributeError:
+ self._key = key = self.project_name.lower()
+ return key
+ key = property(key)
+
+ #@property
+ def parsed_version(self):
+ try:
+ return self._parsed_version
+ except AttributeError:
+ self._parsed_version = pv = parse_version(self.version)
+ return pv
+
+ parsed_version = property(parsed_version)
+
+ #@property
+ def version(self):
+ try:
+ return self._version
+ except AttributeError:
+ for line in self._get_metadata('PKG-INFO'):
+ if line.lower().startswith('version:'):
+ self._version = safe_version(line.split(':',1)[1].strip())
+ return self._version
+ else:
+ raise ValueError(
+ "Missing 'Version:' header and/or PKG-INFO file", self
+ )
+ version = property(version)
+
+
+
+
+ #@property
+ def _dep_map(self):
+ try:
+ return self.__dep_map
+ except AttributeError:
+ dm = self.__dep_map = {None: []}
+ for name in 'requires.txt', 'depends.txt':
+ for extra,reqs in split_sections(self._get_metadata(name)):
+ if extra: extra = safe_extra(extra)
+ dm.setdefault(extra,[]).extend(parse_requirements(reqs))
+ return dm
+ _dep_map = property(_dep_map)
+
+ def requires(self,extras=()):
+ """List of Requirements needed for this distro if `extras` are used"""
+ dm = self._dep_map
+ deps = []
+ deps.extend(dm.get(None,()))
+ for ext in extras:
+ try:
+ deps.extend(dm[safe_extra(ext)])
+ except KeyError:
+ raise UnknownExtra(
+ "%s has no such extra feature %r" % (self, ext)
+ )
+ return deps
+
+ def _get_metadata(self,name):
+ if self.has_metadata(name):
+ for line in self.get_metadata_lines(name):
+ yield line
+
+ def activate(self,path=None):
+ """Ensure distribution is importable on `path` (default=sys.path)"""
+ if path is None: path = sys.path
+ self.insert_on(path)
+ if path is sys.path:
+ fixup_namespace_packages(self.location)
+ map(declare_namespace, self._get_metadata('namespace_packages.txt'))
+
+
+ def egg_name(self):
+ """Return what this distribution's standard .egg filename should be"""
+ filename = "%s-%s-py%s" % (
+ to_filename(self.project_name), to_filename(self.version),
+ self.py_version or PY_MAJOR
+ )
+
+ if self.platform:
+ filename += '-'+self.platform
+ return filename
+
+ def __repr__(self):
+ if self.location:
+ return "%s (%s)" % (self,self.location)
+ else:
+ return str(self)
+
+ def __str__(self):
+ try: version = getattr(self,'version',None)
+ except ValueError: version = None
+ version = version or "[unknown version]"
+ return "%s %s" % (self.project_name,version)
+
+ def __getattr__(self,attr):
+ """Delegate all unrecognized public attributes to .metadata provider"""
+ if attr.startswith('_'):
+ raise AttributeError,attr
+ return getattr(self._provider, attr)
+
+ #@classmethod
+ def from_filename(cls,filename,metadata=None, **kw):
+ return cls.from_location(
+ _normalize_cached(filename), os.path.basename(filename), metadata,
+ **kw
+ )
+ from_filename = classmethod(from_filename)
+
+ def as_requirement(self):
+ """Return a ``Requirement`` that matches this distribution exactly"""
+ return Requirement.parse('%s==%s' % (self.project_name, self.version))
+
+ def load_entry_point(self, group, name):
+ """Return the `name` entry point of `group` or raise ImportError"""
+ ep = self.get_entry_info(group,name)
+ if ep is None:
+ raise ImportError("Entry point %r not found" % ((group,name),))
+ return ep.load()
+
+ def get_entry_map(self, group=None):
+ """Return the entry point map for `group`, or the full entry map"""
+ try:
+ ep_map = self._ep_map
+ except AttributeError:
+ ep_map = self._ep_map = EntryPoint.parse_map(
+ self._get_metadata('entry_points.txt'), self
+ )
+ if group is not None:
+ return ep_map.get(group,{})
+ return ep_map
+
+ def get_entry_info(self, group, name):
+ """Return the EntryPoint object for `group`+`name`, or ``None``"""
+ return self.get_entry_map(group).get(name)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def insert_on(self, path, loc = None):
+ """Insert self.location in path before its nearest parent directory"""
+
+ loc = loc or self.location
+ if not loc:
+ return
+
+ if path is sys.path:
+ self.check_version_conflict()
+
+ nloc = _normalize_cached(loc)
+ bdir = os.path.dirname(nloc)
+ npath= map(_normalize_cached, path)
+
+ bp = None
+ for p, item in enumerate(npath):
+ if item==nloc:
+ break
+ elif item==bdir:
+ path.insert(p, loc)
+ npath.insert(p, nloc)
+ break
+ else:
+ path.append(loc)
+ return
+
+ # p is the spot where we found or inserted loc; now remove duplicates
+ while 1:
+ try:
+ np = npath.index(nloc, p+1)
+ except ValueError:
+ break
+ else:
+ del npath[np], path[np]
+ p = np # ha!
+
+ return
+
+
+
+
+ def check_version_conflict(self):
+ if self.key=='setuptools':
+ return # ignore the inevitable setuptools self-conflicts :(
+
+ nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt'))
+ loc = normalize_path(self.location)
+ for modname in self._get_metadata('top_level.txt'):
+ if (modname not in sys.modules or modname in nsp
+ or modname in _namespace_packages
+ ):
+ continue
+
+ fn = getattr(sys.modules[modname], '__file__', None)
+ if fn and normalize_path(fn).startswith(loc):
+ continue
+ issue_warning(
+ "Module %s was already imported from %s, but %s is being added"
+ " to sys.path" % (modname, fn, self.location),
+ )
+
+ def has_version(self):
+ try:
+ self.version
+ except ValueError:
+ issue_warning("Unbuilt egg for "+repr(self))
+ return False
+ return True
+
+ def clone(self,**kw):
+ """Copy this distribution, substituting in any changed keyword args"""
+ for attr in (
+ 'project_name', 'version', 'py_version', 'platform', 'location',
+ 'precedence'
+ ):
+ kw.setdefault(attr, getattr(self,attr,None))
+ kw.setdefault('metadata', self._provider)
+ return self.__class__(**kw)
+
+
+
+
+ #@property
+ def extras(self):
+ return [dep for dep in self._dep_map if dep]
+ extras = property(extras)
+
+
+def issue_warning(*args,**kw):
+ level = 1
+ g = globals()
+ try:
+ # find the first stack frame that is *not* code in
+ # the pkg_resources module, to use for the warning
+ while sys._getframe(level).f_globals is g:
+ level += 1
+ except ValueError:
+ pass
+ from warnings import warn
+ warn(stacklevel = level+1, *args, **kw)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+def parse_requirements(strs):
+ """Yield ``Requirement`` objects for each specification in `strs`
+
+ `strs` must be an instance of ``basestring``, or a (possibly-nested)
+ iterable thereof.
+ """
+ # create a steppable iterator, so we can handle \-continuations
+ lines = iter(yield_lines(strs))
+
+ def scan_list(ITEM,TERMINATOR,line,p,groups,item_name):
+
+ items = []
+
+ while not TERMINATOR(line,p):
+ if CONTINUE(line,p):
+ try:
+ line = lines.next(); p = 0
+ except StopIteration:
+ raise ValueError(
+ "\\ must not appear on the last nonblank line"
+ )
+
+ match = ITEM(line,p)
+ if not match:
+ raise ValueError("Expected "+item_name+" in",line,"at",line[p:])
+
+ items.append(match.group(*groups))
+ p = match.end()
+
+ match = COMMA(line,p)
+ if match:
+ p = match.end() # skip the comma
+ elif not TERMINATOR(line,p):
+ raise ValueError(
+ "Expected ',' or end-of-list in",line,"at",line[p:]
+ )
+
+ match = TERMINATOR(line,p)
+ if match: p = match.end() # skip the terminator, if any
+ return line, p, items
+
+ for line in lines:
+ match = DISTRO(line)
+ if not match:
+ raise ValueError("Missing distribution spec", line)
+ project_name = match.group(1)
+ p = match.end()
+ extras = []
+
+ match = OBRACKET(line,p)
+ if match:
+ p = match.end()
+ line, p, extras = scan_list(
+ DISTRO, CBRACKET, line, p, (1,), "'extra' name"
+ )
+
+ line, p, specs = scan_list(VERSION,LINE_END,line,p,(1,2),"version spec")
+ specs = [(op,safe_version(val)) for op,val in specs]
+ yield Requirement(project_name, specs, extras)
+
+
+def _sort_dists(dists):
+ tmp = [(dist.hashcmp,dist) for dist in dists]
+ tmp.sort()
+ dists[::-1] = [d for hc,d in tmp]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class Requirement:
+ def __init__(self, project_name, specs, extras):
+ """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!"""
+ self.unsafe_name, project_name = project_name, safe_name(project_name)
+ self.project_name, self.key = project_name, project_name.lower()
+ index = [(parse_version(v),state_machine[op],op,v) for op,v in specs]
+ index.sort()
+ self.specs = [(op,ver) for parsed,trans,op,ver in index]
+ self.index, self.extras = index, tuple(map(safe_extra,extras))
+ self.hashCmp = (
+ self.key, tuple([(op,parsed) for parsed,trans,op,ver in index]),
+ ImmutableSet(self.extras)
+ )
+ self.__hash = hash(self.hashCmp)
+
+ def __str__(self):
+ specs = ','.join([''.join(s) for s in self.specs])
+ extras = ','.join(self.extras)
+ if extras: extras = '[%s]' % extras
+ return '%s%s%s' % (self.project_name, extras, specs)
+
+ def __eq__(self,other):
+ return isinstance(other,Requirement) and self.hashCmp==other.hashCmp
+
+ def __contains__(self,item):
+ if isinstance(item,Distribution):
+ if item.key <> self.key: return False
+ if self.index: item = item.parsed_version # only get if we need it
+ elif isinstance(item,basestring):
+ item = parse_version(item)
+ last = None
+ for parsed,trans,op,ver in self.index:
+ action = trans[cmp(item,parsed)]
+ if action=='F': return False
+ elif action=='T': return True
+ elif action=='+': last = True
+ elif action=='-' or last is None: last = False
+ if last is None: last = True # no rules encountered
+ return last
+
+
+ def __hash__(self):
+ return self.__hash
+
+ def __repr__(self): return "Requirement.parse(%r)" % str(self)
+
+ #@staticmethod
+ def parse(s):
+ reqs = list(parse_requirements(s))
+ if reqs:
+ if len(reqs)==1:
+ return reqs[0]
+ raise ValueError("Expected only one requirement", s)
+ raise ValueError("No requirements found", s)
+
+ parse = staticmethod(parse)
+
+state_machine = {
+ # =><
+ '<' : '--T',
+ '<=': 'T-T',
+ '>' : 'F+F',
+ '>=': 'T+F',
+ '==': 'T..',
+ '!=': 'F++',
+}
+
+
+def _get_mro(cls):
+ """Get an mro for a type or classic class"""
+ if not isinstance(cls,type):
+ class cls(cls,object): pass
+ return cls.__mro__[1:]
+ return cls.__mro__
+
+def _find_adapter(registry, ob):
+ """Return an adapter factory for `ob` from `registry`"""
+ for t in _get_mro(getattr(ob, '__class__', type(ob))):
+ if t in registry:
+ return registry[t]
+
+
+def ensure_directory(path):
+ """Ensure that the parent directory of `path` exists"""
+ dirname = os.path.dirname(path)
+ if not os.path.isdir(dirname):
+ os.makedirs(dirname)
+
+def split_sections(s):
+ """Split a string or iterable thereof into (section,content) pairs
+
+ Each ``section`` is a stripped version of the section header ("[section]")
+ and each ``content`` is a list of stripped lines excluding blank lines and
+ comment-only lines. If there are any such lines before the first section
+ header, they're returned in a first ``section`` of ``None``.
+ """
+ section = None
+ content = []
+ for line in yield_lines(s):
+ if line.startswith("["):
+ if line.endswith("]"):
+ if section or content:
+ yield section, content
+ section = line[1:-1].strip()
+ content = []
+ else:
+ raise ValueError("Invalid section heading", line)
+ else:
+ content.append(line)
+
+ # wrap up last segment
+ yield section, content
+
+def _mkstemp(*args,**kw):
+ from tempfile import mkstemp
+ old_open = os.open
+ try:
+ os.open = os_open # temporarily bypass sandboxing
+ return mkstemp(*args,**kw)
+ finally:
+ os.open = old_open # and then put it back
+
+
+# Set up global resource manager
+_manager = ResourceManager()
+def _initialize(g):
+ for name in dir(_manager):
+ if not name.startswith('_'):
+ g[name] = getattr(_manager, name)
+_initialize(globals())
+
+# Prepare the master working set and make the ``require()`` API available
+working_set = WorkingSet()
+try:
+ # Does the main program list any requirements?
+ from __main__ import __requires__
+except ImportError:
+ pass # No: just use the default working set based on sys.path
+else:
+ # Yes: ensure the requirements are met, by prefixing sys.path if necessary
+ try:
+ working_set.require(__requires__)
+ except VersionConflict: # try it without defaults already on sys.path
+ working_set = WorkingSet([]) # by starting with an empty path
+ for dist in working_set.resolve(
+ parse_requirements(__requires__), Environment()
+ ):
+ working_set.add(dist)
+ for entry in sys.path: # add any missing entries from sys.path
+ if entry not in working_set.entries:
+ working_set.add_entry(entry)
+ sys.path[:] = working_set.entries # then copy back to sys.path
+
+require = working_set.require
+iter_entry_points = working_set.iter_entry_points
+add_activation_listener = working_set.subscribe
+run_script = working_set.run_script
+run_main = run_script # backward compatibility
+# Activate all distributions already on sys.path, and ensure that
+# all distributions added to the working set in the future (e.g. by
+# calling ``require()``) will get activated as well.
+add_activation_listener(lambda dist: dist.activate())
+working_set.entries=[]; map(working_set.add_entry,sys.path) # match order
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pubsub.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pubsub.py
new file mode 100644
index 0000000..ed17e19
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pubsub.py
@@ -0,0 +1,1263 @@
+
+#---------------------------------------------------------------------------
+"""
+This module provides a publish-subscribe component that allows
+listeners to subcribe to messages of a given topic. Contrary to the
+original wxPython.lib.pubsub module (which it is based on), it uses
+weak referencing to the subscribers so the lifetime of subscribers
+is not affected by Publisher. Also, callable objects can be used in
+addition to functions and bound methods. See Publisher class docs for
+more details.
+
+Thanks to Robb Shecter and Robin Dunn for having provided
+the basis for this module (which now shares most of the concepts but
+very little design or implementation with the original
+wxPython.lib.pubsub).
+
+The publisher is a singleton instance of the PublisherClass class. You
+access the instance via the Publisher object available from the module::
+
+ from wx.lib.pubsub import Publisher
+ Publisher().subscribe(...)
+ Publisher().sendMessage(...)
+ ...
+
+:Author: Oliver Schoenborn
+:Since: Apr 2004
+:Version: $Id: pubsub.py 69063 2011-09-11 18:19:32Z CJP $
+:Copyright: \(c) 2004 Oliver Schoenborn
+:License: wxWidgets
+"""
+
+_implNotes = """
+Implementation notes
+--------------------
+
+In class Publisher, I represent the topics-listener set as a tree
+where each node is a topic, and contains a list of listeners of that
+topic, and a dictionary of subtopics of that topic. When the Publisher
+is told to send a message for a given topic, it traverses the tree
+down to the topic for which a message is being generated, all
+listeners on the way get sent the message.
+
+Publisher currently uses a weak listener topic tree to store the
+topics for each listener, and if a listener dies before being
+unsubscribed, the tree is notified, and the tree eliminates the
+listener from itself.
+
+Ideally, _TopicTreeNode would be a generic _TreeNode with named
+subnodes, and _TopicTreeRoot would be a generic _Tree with named
+nodes, and Publisher would store listeners in each node and a topic
+tuple would be converted to a path in the tree. This would lead to a
+much cleaner separation of concerns. But time is over, time to move on.
+"""
+#---------------------------------------------------------------------------
+
+# for function and method parameter counting:
+from types import InstanceType
+from inspect import getargspec, ismethod, isfunction
+# for weakly bound methods:
+from new import instancemethod as InstanceMethod
+from weakref import ref as WeakRef
+
+# -----------------------------------------------------------------------------
+
+def _isbound(method):
+ """Return true if method is a bound method, false otherwise"""
+ assert ismethod(method)
+ return method.im_self is not None
+
+
+def _paramMinCountFunc(function):
+ """Given a function, return pair (min,d) where min is minimum # of
+ args required, and d is number of default arguments."""
+ assert isfunction(function)
+ (args, va, kwa, dflt) = getargspec(function)
+ lenDef = len(dflt or ())
+ lenArgs = len(args or ())
+ lenVA = int(va is not None)
+ return (lenArgs - lenDef + lenVA, lenDef)
+
+
+def _paramMinCount(callableObject):
+ """
+ Given a callable object (function, method or callable instance),
+ return pair (min,d) where min is minimum # of args required, and d
+ is number of default arguments. The 'self' parameter, in the case
+ of methods, is not counted.
+ """
+ if type(callableObject) is InstanceType:
+ min, d = _paramMinCountFunc(callableObject.__call__.im_func)
+ return min-1, d
+ elif ismethod(callableObject):
+ min, d = _paramMinCountFunc(callableObject.im_func)
+ return min-1, d
+ elif isfunction(callableObject):
+ return _paramMinCountFunc(callableObject)
+ else:
+ raise 'Cannot determine type of callable: '+repr(callableObject)
+
+
+def _tupleize(items):
+ """Convert items to tuple if not already one,
+ so items must be a list, tuple or non-sequence"""
+ if isinstance(items, list):
+ raise TypeError, 'Not allowed to tuple-ize a list'
+ elif isinstance(items, (str, unicode)) and items.find('.') != -1:
+ items = tuple(items.split('.'))
+ elif not isinstance(items, tuple):
+ items = (items,)
+ return items
+
+
+def _getCallableName(callable):
+ """Get name for a callable, ie function, bound
+ method or callable instance"""
+ if ismethod(callable):
+ return '%s.%s ' % (callable.im_self, callable.im_func.func_name)
+ elif isfunction(callable):
+ return '%s ' % callable.__name__
+ else:
+ return '%s ' % callable
+
+
+def _removeItem(item, fromList):
+ """Attempt to remove item from fromList, return true
+ if successful, false otherwise."""
+ try:
+ fromList.remove(item)
+ return True
+ except ValueError:
+ return False
+
+
+# -----------------------------------------------------------------------------
+
+class _WeakMethod:
+ """Represent a weak bound method, i.e. a method doesn't keep alive the
+ object that it is bound to. It uses WeakRef which, used on its own,
+ produces weak methods that are dead on creation, not very useful.
+ Typically, you will use the getRef() function instead of using
+ this class directly. """
+
+ def __init__(self, method, notifyDead = None):
+ """The method must be bound. notifyDead will be called when
+ object that method is bound to dies. """
+ assert ismethod(method)
+ if method.im_self is None:
+ raise ValueError, "We need a bound method!"
+ if notifyDead is None:
+ self.objRef = WeakRef(method.im_self)
+ else:
+ self.objRef = WeakRef(method.im_self, notifyDead)
+ self.fun = method.im_func
+ self.cls = method.im_class
+
+ def __call__(self):
+ """Returns a new.instancemethod if object for method still alive.
+ Otherwise return None. Note that instancemethod causes a
+ strong reference to object to be created, so shouldn't save
+ the return value of this call. Note also that this __call__
+ is required only for compatibility with WeakRef.ref(), otherwise
+ there would be more efficient ways of providing this functionality."""
+ if self.objRef() is None:
+ return None
+ else:
+ return InstanceMethod(self.fun, self.objRef(), self.cls)
+
+ def __eq__(self, method2):
+ """Two WeakMethod objects compare equal if they refer to the same method
+ of the same instance. Thanks to Josiah Carlson for patch and clarifications
+ on how dict uses eq/cmp and hashing. """
+ if not isinstance(method2, _WeakMethod):
+ return False
+ return self.fun is method2.fun \
+ and self.objRef() is method2.objRef() \
+ and self.objRef() is not None
+
+ def __hash__(self):
+ """Hash is an optimization for dict searches, it need not
+ return different numbers for every different object. Some objects
+ are not hashable (eg objects of classes derived from dict) so no
+ hash(objRef()) in there, and hash(self.cls) would only be useful
+ in the rare case where instance method was rebound. """
+ return hash(self.fun)
+
+ def __repr__(self):
+ dead = ''
+ if self.objRef() is None:
+ dead = '; DEAD'
+ obj = '<%s at %s%s>' % (self.__class__, id(self), dead)
+ return obj
+
+ def refs(self, weakRef):
+ """Return true if we are storing same object referred to by weakRef."""
+ return self.objRef == weakRef
+
+
+def _getWeakRef(obj, notifyDead=None):
+ """Get a weak reference to obj. If obj is a bound method, a _WeakMethod
+ object, that behaves like a WeakRef, is returned, if it is
+ anything else a WeakRef is returned. If obj is an unbound method,
+ a ValueError will be raised."""
+ if ismethod(obj):
+ createRef = _WeakMethod
+ else:
+ createRef = WeakRef
+
+ if notifyDead is None:
+ return createRef(obj)
+ else:
+ return createRef(obj, notifyDead)
+
+
+# -----------------------------------------------------------------------------
+
+def getStrAllTopics():
+ """Function to call if, for whatever reason, you need to know
+ explicitely what is the string to use to indicate 'all topics'."""
+ return ''
+
+
+# alias, easier to see where used
+ALL_TOPICS = getStrAllTopics()
+
+# -----------------------------------------------------------------------------
+
+
+class _NodeCallback:
+ """Encapsulate a weak reference to a method of a TopicTreeNode
+ in such a way that the method can be called, if the node is
+ still alive, but the callback does not *keep* the node alive.
+ Also, define two methods, preNotify() and noNotify(), which can
+ be redefined to something else, very useful for testing.
+ """
+
+ def __init__(self, obj):
+ self.objRef = _getWeakRef(obj)
+
+ def __call__(self, weakCB):
+ notify = self.objRef()
+ if notify is not None:
+ self.preNotify(weakCB)
+ notify(weakCB)
+ else:
+ self.noNotify()
+
+ def preNotify(self, dead):
+ """'Gets called just before our callback (self.objRef) is called"""
+ pass
+
+ def noNotify(self):
+ """Gets called if the TopicTreeNode for this callback is dead"""
+ pass
+
+
+class _TopicTreeNode:
+ """A node in the topic tree. This contains a list of callables
+ that are interested in the topic that this node is associated
+ with, and contains a dictionary of subtopics, whose associated
+ values are other _TopicTreeNodes. The topic of a node is not stored
+ in the node, so that the tree can be implemented as a dictionary
+ rather than a list, for ease of use (and, likely, performance).
+
+ Note that it uses _NodeCallback to encapsulate a callback for
+ when a registered listener dies, possible thanks to WeakRef.
+ Whenever this callback is called, the onDeadListener() function,
+ passed in at construction time, is called (unless it is None).
+ """
+
+ def __init__(self, topicPath, onDeadListenerWeakCB):
+ self.__subtopics = {}
+ self.__callables = []
+ self.__topicPath = topicPath
+ self.__onDeadListenerWeakCB = onDeadListenerWeakCB
+
+ def getPathname(self):
+ """The complete node path to us, ie., the topic tuple that would lead to us"""
+ return self.__topicPath
+
+ def createSubtopic(self, subtopic, topicPath):
+ """Create a child node for subtopic"""
+ return self.__subtopics.setdefault(subtopic,
+ _TopicTreeNode(topicPath, self.__onDeadListenerWeakCB))
+
+ def hasSubtopic(self, subtopic):
+ """Return true only if topic string is one of subtopics of this node"""
+ return self.__subtopics.has_key(subtopic)
+
+ def getNode(self, subtopic):
+ """Return ref to node associated with subtopic"""
+ return self.__subtopics[subtopic]
+
+ def addCallable(self, callable):
+ """Add a callable to list of callables for this topic node"""
+ try:
+ id = self.__callables.index(_getWeakRef(callable))
+ return self.__callables[id]
+ except ValueError:
+ wrCall = _getWeakRef(callable, _NodeCallback(self.__notifyDead))
+ self.__callables.append(wrCall)
+ return wrCall
+
+ def getCallables(self):
+ """Get callables associated with this topic node"""
+ return [cb() for cb in self.__callables if cb() is not None]
+
+ def hasCallable(self, callable):
+ """Return true if callable in this node"""
+ try:
+ self.__callables.index(_getWeakRef(callable))
+ return True
+ except ValueError:
+ return False
+
+ def sendMessage(self, message):
+ """Send a message to our callables"""
+ deliveryCount = 0
+ for cb in self.__callables:
+ listener = cb()
+ if listener is not None:
+ listener(message)
+ deliveryCount += 1
+ return deliveryCount
+
+ def removeCallable(self, callable):
+ """Remove weak callable from our node (and return True).
+ Does nothing if not here (and returns False)."""
+ try:
+ self.__callables.remove(_getWeakRef(callable))
+ return True
+ except ValueError:
+ return False
+
+ def clearCallables(self):
+ """Abandon list of callables to caller. We no longer have
+ any callables after this method is called."""
+ tmpList = [cb for cb in self.__callables if cb() is not None]
+ self.__callables = []
+ return tmpList
+
+ def __notifyDead(self, dead):
+ """Gets called when a listener dies, thanks to WeakRef"""
+ #print 'TreeNODE', `self`, 'received death certificate for ', dead
+ self.__cleanupDead()
+ if self.__onDeadListenerWeakCB is not None:
+ cb = self.__onDeadListenerWeakCB()
+ if cb is not None:
+ cb(dead)
+
+ def __cleanupDead(self):
+ """Remove all dead objects from list of callables"""
+ self.__callables = [cb for cb in self.__callables if cb() is not None]
+
+ def __str__(self):
+ """Print us in a not-so-friendly, but readable way, good for debugging."""
+ strVal = []
+ for callable in self.getCallables():
+ strVal.append(_getCallableName(callable))
+ for topic, node in self.__subtopics.iteritems():
+ strVal.append(' (%s: %s)' %(topic, node))
+ return ''.join(strVal)
+
+
+class _TopicTreeRoot(_TopicTreeNode):
+ """
+ The root of the tree knows how to access other node of the
+ tree and is the gateway of the tree user to the tree nodes.
+ It can create topics, and and remove callbacks, etc.
+
+ For efficiency, it stores a dictionary of listener-topics,
+ so that unsubscribing a listener just requires finding the
+ topics associated to a listener, and finding the corresponding
+ nodes of the tree. Without it, unsubscribing would require
+ that we search the whole tree for all nodes that contain
+ given listener. Since Publisher is a singleton, it will
+ contain all topics in the system so it is likely to be a large
+ tree. However, it is possible that in some runs, unsubscribe()
+ is called very little by the user, in which case most unsubscriptions
+ are automatic, ie caused by the listeners dying. In this case,
+ a flag is set to indicate that the dictionary should be cleaned up
+ at the next opportunity. This is not necessary, it is just an
+ optimization.
+ """
+
+ def __init__(self):
+ self.__callbackDict = {}
+ self.__callbackDictCleanup = 0
+ # all child nodes will call our __rootNotifyDead method
+ # when one of their registered listeners dies
+ _TopicTreeNode.__init__(self, (ALL_TOPICS,),
+ _getWeakRef(self.__rootNotifyDead))
+
+ def addTopic(self, topic, listener):
+ """Add topic to tree if doesnt exist, and add listener to topic node"""
+ assert isinstance(topic, tuple)
+ topicNode = self.__getTreeNode(topic, make=True)
+ weakCB = topicNode.addCallable(listener)
+ assert topicNode.hasCallable(listener)
+
+ theList = self.__callbackDict.setdefault(weakCB, [])
+ assert self.__callbackDict.has_key(weakCB)
+ # add it only if we don't already have it
+ try:
+ weakTopicNode = WeakRef(topicNode)
+ theList.index(weakTopicNode)
+ except ValueError:
+ theList.append(weakTopicNode)
+ assert self.__callbackDict[weakCB].index(weakTopicNode) >= 0
+
+ def getTopics(self, listener):
+ """Return the list of topics for given listener"""
+ weakNodes = self.__callbackDict.get(_getWeakRef(listener), [])
+ return [weakNode().getPathname() for weakNode in weakNodes
+ if weakNode() is not None]
+
+ def isSubscribed(self, listener, topic=None):
+ """Return true if listener is registered for topic specified.
+ If no topic specified, return true if subscribed to something.
+ Use topic=getStrAllTopics() to determine if a listener will receive
+ messages for all topics."""
+ weakCB = _getWeakRef(listener)
+ if topic is None:
+ return self.__callbackDict.has_key(weakCB)
+ else:
+ topicPath = _tupleize(topic)
+ for weakNode in self.__callbackDict[weakCB]:
+ if topicPath == weakNode().getPathname():
+ return True
+ return False
+
+ def unsubscribe(self, listener, topicList):
+ """Remove listener from given list of topics. If topicList
+ doesn't have any topics for which listener has subscribed,
+ nothing happens."""
+ weakCB = _getWeakRef(listener)
+ if not self.__callbackDict.has_key(weakCB):
+ return
+
+ cbNodes = self.__callbackDict[weakCB]
+ if topicList is None:
+ for weakNode in cbNodes:
+ weakNode().removeCallable(listener)
+ del self.__callbackDict[weakCB]
+ return
+
+ for weakNode in cbNodes:
+ node = weakNode()
+ if node is not None and node.getPathname() in topicList:
+ success = node.removeCallable(listener)
+ assert success == True
+ cbNodes.remove(weakNode)
+ assert not self.isSubscribed(listener, node.getPathname())
+
+ def unsubAll(self, topicList, onNoSuchTopic):
+ """Unsubscribe all listeners registered for any topic in
+ topicList. If a topic in the list does not exist, and
+ onNoSuchTopic is not None, a call
+ to onNoSuchTopic(topic) is done for that topic."""
+ for topic in topicList:
+ node = self.__getTreeNode(topic)
+ if node is not None:
+ weakCallables = node.clearCallables()
+ for callable in weakCallables:
+ weakNodes = self.__callbackDict[callable]
+ success = _removeItem(WeakRef(node), weakNodes)
+ assert success == True
+ if weakNodes == []:
+ del self.__callbackDict[callable]
+ elif onNoSuchTopic is not None:
+ onNoSuchTopic(topic)
+
+ def sendMessage(self, topic, message, onTopicNeverCreated):
+ """Send a message for given topic to all registered listeners. If
+ topic doesn't exist, call onTopicNeverCreated(topic)."""
+ # send to the all-toipcs listeners
+ deliveryCount = _TopicTreeNode.sendMessage(self, message)
+ # send to those who listen to given topic or any of its supertopics
+ node = self
+ for topicItem in topic:
+ assert topicItem != ''
+ if node.hasSubtopic(topicItem):
+ node = node.getNode(topicItem)
+ deliveryCount += node.sendMessage(message)
+ else: # topic never created, don't bother continuing
+ if onTopicNeverCreated is not None:
+ onTopicNeverCreated(topic)
+ break
+ return deliveryCount
+
+ def numListeners(self):
+ """Return a pair (live, dead) with count of live and dead listeners in tree"""
+ dead, live = 0, 0
+ for cb in self.__callbackDict:
+ if cb() is None:
+ dead += 1
+ else:
+ live += 1
+ return live, dead
+
+ # clean up the callback dictionary after how many dead listeners
+ callbackDeadLimit = 10
+
+ def __rootNotifyDead(self, dead):
+ #print 'TreeROOT received death certificate for ', dead
+ self.__callbackDictCleanup += 1
+ if self.__callbackDictCleanup > _TopicTreeRoot.callbackDeadLimit:
+ self.__callbackDictCleanup = 0
+ oldDict = self.__callbackDict
+ self.__callbackDict = {}
+ for weakCB, weakNodes in oldDict.iteritems():
+ if weakCB() is not None:
+ self.__callbackDict[weakCB] = weakNodes
+
+ def __getTreeNode(self, topic, make=False):
+ """Return the tree node for 'topic' from the topic tree. If it
+ doesnt exist and make=True, create it first."""
+ # if the all-topics, give root;
+ if topic == (ALL_TOPICS,):
+ return self
+
+ # not root, so traverse tree
+ node = self
+ path = ()
+ for topicItem in topic:
+ path += (topicItem,)
+ if topicItem == ALL_TOPICS:
+ raise ValueError, 'Topic tuple must not contain ""'
+ if make:
+ node = node.createSubtopic(topicItem, path)
+ elif node.hasSubtopic(topicItem):
+ node = node.getNode(topicItem)
+ else:
+ return None
+ # done
+ return node
+
+ def printCallbacks(self):
+ strVal = ['Callbacks:\n']
+ for listener, weakTopicNodes in self.__callbackDict.iteritems():
+ topics = [topic() for topic in weakTopicNodes if topic() is not None]
+ strVal.append(' %s: %s\n' % (_getCallableName(listener()), topics))
+ return ''.join(strVal)
+
+ def __str__(self):
+ return 'all: %s' % _TopicTreeNode.__str__(self)
+
+
+# -----------------------------------------------------------------------------
+
+class _SingletonKey: pass
+
+class PublisherClass:
+ """
+ The publish/subscribe manager. It keeps track of which listeners
+ are interested in which topics (see subscribe()), and sends a
+ Message for a given topic to listeners that have subscribed to
+ that topic, with optional user data (see sendMessage()).
+
+ The three important concepts for Publisher are:
+
+ - listener: a function, bound method or
+ callable object that can be called with one parameter
+ (not counting 'self' in the case of methods). The parameter
+ will be a reference to a Message object. E.g., these listeners
+ are ok::
+
+ class Foo:
+ def __call__(self, a, b=1): pass # can be called with only one arg
+ def meth(self, a): pass # takes only one arg
+ def meth2(self, a=2, b=''): pass # can be called with one arg
+
+ def func(a, b=''): pass
+
+ Foo foo
+ Publisher().subscribe(foo) # functor
+ Publisher().subscribe(foo.meth) # bound method
+ Publisher().subscribe(foo.meth2) # bound method
+ Publisher().subscribe(func) # function
+
+ The three types of callables all have arguments that allow a call
+ with only one argument. In every case, the parameter 'a' will contain
+ the message.
+
+ - topic: a single word, a tuple of words, or a string containing a
+ set of words separated by dots, for example: 'sports.baseball'.
+ A tuple or a dotted notation string denotes a hierarchy of
+ topics from most general to least. For example, a listener of
+ this topic::
+
+ ('sports','baseball')
+
+ would receive messages for these topics::
+
+ ('sports', 'baseball') # because same
+ ('sports', 'baseball', 'highscores') # because more specific
+
+ but not these::
+
+ 'sports' # because more general
+ ('sports',) # because more general
+ () or ('') # because only for those listening to 'all' topics
+ ('news') # because different topic
+
+ - message: this is an instance of Message, containing the topic for
+ which the message was sent, and any data the sender specified.
+
+ :note: This class is visible to importers of pubsub only as a
+ Singleton. I.e., every time you execute 'Publisher()', it's
+ actually the same instance of PublisherClass that is
+ returned. So to use, just do'Publisher().method()'.
+
+ """
+
+ __ALL_TOPICS_TPL = (ALL_TOPICS, )
+
+ def __init__(self, singletonKey):
+ """Construct a Publisher. This can only be done by the pubsub
+ module. You just use pubsub.Publisher()."""
+ if not isinstance(singletonKey, _SingletonKey):
+ raise invalid_argument("Use Publisher() to get access to singleton")
+ self.__messageCount = 0
+ self.__deliveryCount = 0
+ self.__topicTree = _TopicTreeRoot()
+
+ #
+ # Public API
+ #
+
+ def getDeliveryCount(self):
+ """How many listeners have received a message since beginning of run"""
+ return self.__deliveryCount
+
+ def getMessageCount(self):
+ """How many times sendMessage() was called since beginning of run"""
+ return self.__messageCount
+
+ def subscribe(self, listener, topic = ALL_TOPICS):
+ """
+ Subscribe listener for given topic. If topic is not specified,
+ listener will be subscribed for all topics (that listener will
+ receive a Message for any topic for which a message is generated).
+
+ This method may be called multiple times for one listener,
+ registering it with many topics. It can also be invoked many
+ times for a particular topic, each time with a different
+ listener. See the class doc for requirements on listener and
+ topic.
+
+ :note: The listener is held by Publisher() only by *weak*
+ reference. This means you must ensure you have at
+ least one strong reference to listener, otherwise it
+ will be DOA ("dead on arrival"). This is particularly
+ easy to forget when wrapping a listener method in a
+ proxy object (e.g. to bind some of its parameters),
+ e.g.::
+
+ class Foo:
+ def listener(self, event): pass
+ class Wrapper:
+ def __init__(self, fun): self.fun = fun
+ def __call__(self, *args): self.fun(*args)
+ foo = Foo()
+ Publisher().subscribe( Wrapper(foo.listener) ) # whoops: DOA!
+ wrapper = Wrapper(foo.listener)
+ Publisher().subscribe(wrapper) # good!
+
+ :note: Calling this method for the same listener, with two
+ topics in the same branch of the topic hierarchy, will
+ cause the listener to be notified twice when a message
+ for the deepest topic is sent. E.g.
+ subscribe(listener, 't1') and then subscribe(listener,
+ ('t1','t2')) means that when calling sendMessage('t1'),
+ listener gets one message, but when calling
+ sendMessage(('t1','t2')), listener gets message twice.
+
+ """
+ self.validate(listener)
+
+ if topic is None:
+ raise TypeError, 'Topic must be either a word, tuple of '\
+ 'words, or getStrAllTopics()'
+
+ self.__topicTree.addTopic(_tupleize(topic), listener)
+
+ def isSubscribed(self, listener, topic=None):
+ """Return true if listener has subscribed to topic specified.
+ If no topic specified, return true if subscribed to something.
+ Use topic=getStrAllTopics() to determine if a listener will receive
+ messages for all topics."""
+ return self.__topicTree.isSubscribed(listener, topic)
+
+ def validate(self, listener):
+ """Similar to isValid(), but raises a TypeError exception if not valid"""
+ # check callable
+ if not callable(listener):
+ raise TypeError, 'Listener '+`listener`+' must be a '\
+ 'function, bound method or instance.'
+ # ok, callable, but if method, is it bound:
+ elif ismethod(listener) and not _isbound(listener):
+ raise TypeError, 'Listener '+`listener`+\
+ ' is a method but it is unbound!'
+
+ # check that it takes the right number of parameters
+ min, d = _paramMinCount(listener)
+ if min > 1:
+ raise TypeError, 'Listener '+`listener`+" can't"\
+ ' require more than one parameter!'
+ if min <= 0 and d == 0:
+ raise TypeError, 'Listener '+`listener`+' lacking arguments!'
+
+ assert (min == 0 and d>0) or (min == 1)
+
+ def isValid(self, listener):
+ """Return true only if listener will be able to subscribe to
+ Publisher."""
+ try:
+ self.validate(listener)
+ return True
+ except TypeError:
+ return False
+
+ def unsubAll(self, topics=None, onNoSuchTopic=None):
+ """Unsubscribe all listeners subscribed for topics. Topics can
+ be a single topic (string or tuple) or a list of topics (ie
+ list containing strings and/or tuples). If topics is not
+ specified, all listeners for all topics will be unsubscribed,
+ ie. the Publisher singleton will have no topics and no listeners
+ left. If onNoSuchTopic is given, it will be called as
+ onNoSuchTopic(topic) for each topic that is unknown.
+ """
+ if topics is None:
+ del self.__topicTree
+ self.__topicTree = _TopicTreeRoot()
+ return
+
+ # make sure every topics are in tuple form
+ if isinstance(topics, list):
+ topicList = [_tupleize(x) for x in topics]
+ else:
+ topicList = [_tupleize(topics)]
+
+ # unsub every listener of topics
+ self.__topicTree.unsubAll(topicList, onNoSuchTopic)
+
+ def unsubscribe(self, listener, topics=None):
+ """Unsubscribe listener. If topics not specified, listener is
+ completely unsubscribed. Otherwise, it is unsubscribed only
+ for the topic (the usual tuple) or list of topics (ie a list
+ of tuples) specified. Nothing happens if listener is not actually
+ subscribed to any of the topics.
+
+ Note that if listener subscribed for two topics (a,b) and (a,c),
+ then unsubscribing for topic (a) will do nothing. You must
+ use getAssociatedTopics(listener) and give unsubscribe() the returned
+ list (or a subset thereof).
+ """
+ self.validate(listener)
+ topicList = None
+ if topics is not None:
+ if isinstance(topics, list):
+ topicList = [_tupleize(x) for x in topics]
+ else:
+ topicList = [_tupleize(topics)]
+
+ self.__topicTree.unsubscribe(listener, topicList)
+
+ def getAssociatedTopics(self, listener):
+ """Return a list of topics the given listener is registered with.
+ Returns [] if listener never subscribed.
+
+ :attention: when using the return of this method to compare to
+ expected list of topics, remember that topics that are
+ not in the form of a tuple appear as a one-tuple in
+ the return. E.g. if you have subscribed a listener to
+ 'topic1' and ('topic2','subtopic2'), this method
+ returns::
+
+ associatedTopics = [('topic1',), ('topic2','subtopic2')]
+ """
+ return self.__topicTree.getTopics(listener)
+
+ def sendMessage(self, topic=ALL_TOPICS,
+ data=None, onTopicNeverCreated=None,
+ context=None):
+ """Send a message for given topic, with optional data, to
+ subscribed listeners. If topic is not specified, only the
+ listeners that are interested in all topics will receive message.
+ The onTopicNeverCreated is an optional callback of your choice that
+ will be called if the topic given was never created (i.e. it, or
+ one of its subtopics, was never subscribed to by any listener).
+ It will be called as onTopicNeverCreated(topic)."""
+ aTopic = _tupleize(topic)
+ message = Message(aTopic, data, context=context)
+ self.__messageCount += 1
+
+ # send to those who listen to all topics
+ self.__deliveryCount += \
+ self.__topicTree.sendMessage(aTopic, message, onTopicNeverCreated)
+
+ #
+ # Private methods
+ #
+
+ def __call__(self):
+ """Allows for singleton"""
+ return self
+
+ def __str__(self):
+ return str(self.__topicTree)
+
+# Create the Publisher singleton. We prevent users from (inadvertently)
+# instantiating more than one object, by requiring a key that is
+# accessible only to module. From
+# this point forward any calls to Publisher() will invoke the __call__
+# of this instance which just returns itself.
+#
+# The only flaw with this approach is that you can't derive a new
+# class from Publisher without jumping through hoops. If this ever
+# becomes an issue then a new Singleton implementaion will need to be
+# employed.
+_key = _SingletonKey()
+Publisher = PublisherClass(_key)
+
+
+#---------------------------------------------------------------------------
+
+class Message:
+ """
+ A simple container object for the two components of a message: the
+ topic and the user data. An instance of Message is given to your
+ listener when called by Publisher().sendMessage(topic) (if your
+ listener callback was registered for that topic).
+ """
+ def __init__(self, topic, data, context=None):
+ self.topic = topic
+ self.data = data
+ self.context = context
+
+ Data = property(lambda self: self.data,
+ lambda self, data: setattr(self, 'data', data))
+ Context = property(lambda self: self.context,
+ lambda self, ctx: setattr(self, 'context', value))
+ Type = property(lambda self: self.topic)
+
+ def __str__(self):
+ return '[Topic: '+`self.topic`+', Data: '+`self.data`+']'
+
+ def GetContext(self):
+ """Get the context that this message was sent in"""
+ return self.context
+
+ def GetData(self):
+ """Return the messages data/value"""
+ return self.data
+
+ def GetType(self):
+ """Return the type of message"""
+ return self.topic
+
+#---------------------------------------------------------------------------
+
+
+#
+# Code for a simple command-line test
+#
+def test():
+ def done(funcName):
+ print '----------- Done %s -----------' % funcName
+
+ def testParam():
+ def testFunc00(): pass
+ def testFunc21(a,b,c=1): pass
+ def testFuncA(*args): pass
+ def testFuncAK(*args,**kwds): pass
+ def testFuncK(**kwds): pass
+
+ class Foo:
+ def testMeth(self,a,b): pass
+ def __call__(self, a): pass
+ class Foo2:
+ def __call__(self, *args): pass
+
+ assert _paramMinCount(testFunc00)==(0,0)
+ assert _paramMinCount(testFunc21)==(2,1)
+ assert _paramMinCount(testFuncA) ==(1,0)
+ assert _paramMinCount(testFuncAK)==(1,0)
+ assert _paramMinCount(testFuncK) ==(0,0)
+ foo = Foo()
+ assert _paramMinCount(Foo.testMeth)==(2,0)
+ assert _paramMinCount(foo.testMeth)==(2,0)
+ assert _paramMinCount(foo)==(1,0)
+ assert _paramMinCount(Foo2())==(1,0)
+
+ done('testParam')
+
+ testParam()
+ #------------------------
+
+ _NodeCallback.notified = 0
+ def testPreNotifyNode(self, dead):
+ _NodeCallback.notified += 1
+ print 'testPreNotifyNODE heard notification of', `dead`
+ _NodeCallback.preNotify = testPreNotifyNode
+
+ def testTreeNode():
+
+ class WS:
+ def __init__(self, s):
+ self.s = s
+ def __call__(self, msg):
+ print 'WS#', self.s, ' received msg ', msg
+ def __str__(self):
+ return self.s
+
+ def testPreNotifyRoot(dead):
+ print 'testPreNotifyROOT heard notification of', `dead`
+
+ node = _TopicTreeNode((ALL_TOPICS,), WeakRef(testPreNotifyRoot))
+ boo, baz, bid = WS('boo'), WS('baz'), WS('bid')
+ node.addCallable(boo)
+ node.addCallable(baz)
+ node.addCallable(boo)
+ assert node.getCallables() == [boo,baz]
+ assert node.hasCallable(boo)
+
+ node.removeCallable(bid) # no-op
+ assert node.hasCallable(baz)
+ assert node.getCallables() == [boo,baz]
+
+ node.removeCallable(boo)
+ assert node.getCallables() == [baz]
+ assert node.hasCallable(baz)
+ assert not node.hasCallable(boo)
+
+ node.removeCallable(baz)
+ assert node.getCallables() == []
+ assert not node.hasCallable(baz)
+
+ node2 = node.createSubtopic('st1', ('st1',))
+ node3 = node.createSubtopic('st2', ('st2',))
+ cb1, cb2, cb = WS('st1_cb1'), WS('st1_cb2'), WS('st2_cb')
+ node2.addCallable(cb1)
+ node2.addCallable(cb2)
+ node3.addCallable(cb)
+ node2.createSubtopic('st3', ('st1','st3'))
+ node2.createSubtopic('st4', ('st1','st4'))
+
+ print str(node)
+ assert str(node) == ' (st1: st1_cb1 st1_cb2 (st4: ) (st3: )) (st2: st2_cb )'
+
+ # verify send message, and that a dead listener does not get sent one
+ delivered = node2.sendMessage('hello')
+ assert delivered == 2
+ del cb1
+ delivered = node2.sendMessage('hello')
+ assert delivered == 1
+ assert _NodeCallback.notified == 1
+
+ done('testTreeNode')
+
+ testTreeNode()
+ #------------------------
+
+ def testValidate():
+ class Foo:
+ def __call__(self, a): pass
+ def fun(self, b): pass
+ def fun2(self, b=1): pass
+ def fun3(self, a, b=2): pass
+ def badFun(self): pass
+ def badFun2(): pass
+ def badFun3(self, a, b): pass
+
+ server = Publisher()
+ foo = Foo()
+ server.validate(foo)
+ server.validate(foo.fun)
+ server.validate(foo.fun2)
+ server.validate(foo.fun3)
+ assert not server.isValid(foo.badFun)
+ assert not server.isValid(foo.badFun2)
+ assert not server.isValid(foo.badFun3)
+
+ done('testValidate')
+
+ testValidate()
+ #------------------------
+
+ class SimpleListener:
+ def __init__(self, number):
+ self.number = number
+ def __call__(self, message = ''):
+ print 'Callable #%s got the message "%s"' %(self.number, message)
+ def notify(self, message):
+ print '%s.notify() got the message "%s"' %(self.number, message)
+ def __str__(self):
+ return "SimpleListener_%s" % self.number
+
+ def testSubscribe():
+ publisher = Publisher()
+
+ topic1 = 'politics'
+ topic2 = ('history','middle age')
+ topic3 = ('politics','UN')
+ topic4 = ('politics','NATO')
+ topic5 = ('politics','NATO','US')
+
+ lisnr1 = SimpleListener(1)
+ lisnr2 = SimpleListener(2)
+ def func(message, a=1):
+ print 'Func received message "%s"' % message
+ lisnr3 = func
+ lisnr4 = lambda x: 'Lambda received message "%s"' % x
+
+ assert not publisher.isSubscribed(lisnr1)
+ assert not publisher.isSubscribed(lisnr2)
+ assert not publisher.isSubscribed(lisnr3)
+ assert not publisher.isSubscribed(lisnr4)
+
+ publisher.subscribe(lisnr1, topic1)
+ assert publisher.getAssociatedTopics(lisnr1) == [(topic1,)]
+ publisher.subscribe(lisnr1, topic2)
+ publisher.subscribe(lisnr1, topic1) # do it again, should be no-op
+ assert publisher.getAssociatedTopics(lisnr1) == [(topic1,),topic2]
+ publisher.subscribe(lisnr2.notify, topic3)
+ assert publisher.getAssociatedTopics(lisnr2.notify) == [topic3]
+ assert publisher.getAssociatedTopics(lisnr1) == [(topic1,),topic2]
+ publisher.subscribe(lisnr3, topic5)
+ assert publisher.getAssociatedTopics(lisnr3) == [topic5]
+ assert publisher.getAssociatedTopics(lisnr2.notify) == [topic3]
+ assert publisher.getAssociatedTopics(lisnr1) == [(topic1,),topic2]
+ publisher.subscribe(lisnr4)
+
+ print "Publisher tree: ", publisher
+ assert publisher.isSubscribed(lisnr1)
+ assert publisher.isSubscribed(lisnr1, topic1)
+ assert publisher.isSubscribed(lisnr1, topic2)
+ assert publisher.isSubscribed(lisnr2.notify)
+ assert publisher.isSubscribed(lisnr3, topic5)
+ assert publisher.isSubscribed(lisnr4, ALL_TOPICS)
+ expectTopicTree = 'all: <lambda> (politics: SimpleListener_1 (UN: SimpleListener_2.notify ) (NATO: (US: func ))) (history: (middle age: SimpleListener_1 ))'
+ print "Publisher tree: ", publisher
+ assert str(publisher) == expectTopicTree
+
+ publisher.unsubscribe(lisnr1, 'booboo') # should do nothing
+ assert publisher.getAssociatedTopics(lisnr1) == [(topic1,),topic2]
+ assert publisher.getAssociatedTopics(lisnr2.notify) == [topic3]
+ assert publisher.getAssociatedTopics(lisnr3) == [topic5]
+ publisher.unsubscribe(lisnr1, topic1)
+ assert publisher.getAssociatedTopics(lisnr1) == [topic2]
+ assert publisher.getAssociatedTopics(lisnr2.notify) == [topic3]
+ assert publisher.getAssociatedTopics(lisnr3) == [topic5]
+ publisher.unsubscribe(lisnr1, topic2)
+ publisher.unsubscribe(lisnr1, topic2)
+ publisher.unsubscribe(lisnr2.notify, topic3)
+ publisher.unsubscribe(lisnr3, topic5)
+ assert publisher.getAssociatedTopics(lisnr1) == []
+ assert publisher.getAssociatedTopics(lisnr2.notify) == []
+ assert publisher.getAssociatedTopics(lisnr3) == []
+ publisher.unsubscribe(lisnr4)
+
+ expectTopicTree = 'all: (politics: (UN: ) (NATO: (US: ))) (history: (middle age: ))'
+ print "Publisher tree: ", publisher
+ assert str(publisher) == expectTopicTree
+ assert publisher.getDeliveryCount() == 0
+ assert publisher.getMessageCount() == 0
+
+ publisher.unsubAll()
+ assert str(publisher) == 'all: '
+
+ done('testSubscribe')
+
+ testSubscribe()
+ #------------------------
+
+ def testUnsubAll():
+ publisher = Publisher()
+
+ topic1 = 'politics'
+ topic2 = ('history','middle age')
+ topic3 = ('politics','UN')
+ topic4 = ('politics','NATO')
+ topic5 = ('politics','NATO','US')
+
+ lisnr1 = SimpleListener(1)
+ lisnr2 = SimpleListener(2)
+ def func(message, a=1):
+ print 'Func received message "%s"' % message
+ lisnr3 = func
+ lisnr4 = lambda x: 'Lambda received message "%s"' % x
+
+ publisher.subscribe(lisnr1, topic1)
+ publisher.subscribe(lisnr1, topic2)
+ publisher.subscribe(lisnr2.notify, topic3)
+ publisher.subscribe(lisnr3, topic2)
+ publisher.subscribe(lisnr3, topic5)
+ publisher.subscribe(lisnr4)
+
+ expectTopicTree = 'all: <lambda> (politics: SimpleListener_1 (UN: SimpleListener_2.notify ) (NATO: (US: func ))) (history: (middle age: SimpleListener_1 func ))'
+ print "Publisher tree: ", publisher
+ assert str(publisher) == expectTopicTree
+
+ publisher.unsubAll(topic1)
+ assert publisher.getAssociatedTopics(lisnr1) == [topic2]
+ assert not publisher.isSubscribed(lisnr1, topic1)
+
+ publisher.unsubAll(topic2)
+ print publisher
+ assert publisher.getAssociatedTopics(lisnr1) == []
+ assert publisher.getAssociatedTopics(lisnr3) == [topic5]
+ assert not publisher.isSubscribed(lisnr1)
+ assert publisher.isSubscribed(lisnr3, topic5)
+
+ #print "Publisher tree: ", publisher
+ expectTopicTree = 'all: <lambda> (politics: (UN: SimpleListener_2.notify ) (NATO: (US: func ))) (history: (middle age: ))'
+ assert str(publisher) == expectTopicTree
+ publisher.unsubAll(ALL_TOPICS)
+ #print "Publisher tree: ", publisher
+ expectTopicTree = 'all: (politics: (UN: SimpleListener_2.notify ) (NATO: (US: func ))) (history: (middle age: ))'
+ assert str(publisher) == expectTopicTree
+
+ publisher.unsubAll()
+ done('testUnsubAll')
+
+ testUnsubAll()
+ #------------------------
+
+ def testSend():
+ publisher = Publisher()
+ called = []
+
+ class TestListener:
+ def __init__(self, num):
+ self.number = num
+ def __call__(self, b):
+ called.append( 'TL%scb' % self.number )
+ def notify(self, b):
+ called.append( 'TL%sm' % self.number )
+ def funcListener(b):
+ called.append('func')
+
+ lisnr1 = TestListener(1)
+ lisnr2 = TestListener(2)
+ lisnr3 = funcListener
+ lisnr4 = lambda x: called.append('lambda')
+
+ topic1 = 'politics'
+ topic2 = 'history'
+ topic3 = ('politics','UN')
+ topic4 = ('politics','NATO','US')
+ topic5 = ('politics','NATO')
+
+ publisher.subscribe(lisnr1, topic1)
+ publisher.subscribe(lisnr2, topic2)
+ publisher.subscribe(lisnr2.notify, topic2)
+ publisher.subscribe(lisnr3, topic4)
+ publisher.subscribe(lisnr4)
+
+ print publisher
+
+ # setup ok, now test send/receipt
+ publisher.sendMessage(topic1)
+ assert called == ['lambda','TL1cb']
+ called = []
+ publisher.sendMessage(topic2)
+ assert called == ['lambda','TL2cb','TL2m']
+ called = []
+ publisher.sendMessage(topic3)
+ assert called == ['lambda','TL1cb']
+ called = []
+ publisher.sendMessage(topic4)
+ assert called == ['lambda','TL1cb','func']
+ called = []
+ publisher.sendMessage(topic5)
+ assert called == ['lambda','TL1cb']
+ assert publisher.getDeliveryCount() == 12
+ assert publisher.getMessageCount() == 5
+
+ # test weak referencing works:
+ _NodeCallback.notified = 0
+ del lisnr2
+ called = []
+ publisher.sendMessage(topic2)
+ assert called == ['lambda']
+ assert _NodeCallback.notified == 2
+
+ done('testSend')
+
+ testSend()
+ assert _NodeCallback.notified == 5
+
+ def testDead():
+ # verify if weak references work as expected
+ print '------ Starting testDead ----------'
+ node = _TopicTreeNode('t1', None)
+ lisnr1 = SimpleListener(1)
+ lisnr2 = SimpleListener(2)
+ lisnr3 = SimpleListener(3)
+ lisnr4 = SimpleListener(4)
+
+ node.addCallable(lisnr1)
+ node.addCallable(lisnr2)
+ node.addCallable(lisnr3)
+ node.addCallable(lisnr4)
+
+ print 'Deleting listeners first'
+ _NodeCallback.notified = 0
+ del lisnr1
+ del lisnr2
+ assert _NodeCallback.notified == 2
+
+ print 'Deleting node first'
+ _NodeCallback.notified = 0
+ del node
+ del lisnr3
+ del lisnr4
+ assert _NodeCallback.notified == 0
+
+ lisnr1 = SimpleListener(1)
+ lisnr2 = SimpleListener(2)
+ lisnr3 = SimpleListener(3)
+ lisnr4 = SimpleListener(4)
+
+ # try same with root of tree
+ node = _TopicTreeRoot()
+ node.addTopic(('',), lisnr1)
+ node.addTopic(('',), lisnr2)
+ node.addTopic(('',), lisnr3)
+ node.addTopic(('',), lisnr4)
+ # add objects that will die immediately to see if cleanup occurs
+ # this must be done visually as it is a low-level detail
+ _NodeCallback.notified = 0
+ _TopicTreeRoot.callbackDeadLimit = 3
+ node.addTopic(('',), SimpleListener(5))
+ node.addTopic(('',), SimpleListener(6))
+ node.addTopic(('',), SimpleListener(7))
+ print node.numListeners()
+ assert node.numListeners() == (4, 3)
+ node.addTopic(('',), SimpleListener(8))
+ assert node.numListeners() == (4, 0)
+ assert _NodeCallback.notified == 4
+
+ print 'Deleting listeners first'
+ _NodeCallback.notified = 0
+ del lisnr1
+ del lisnr2
+ assert _NodeCallback.notified == 2
+ print 'Deleting node first'
+ _NodeCallback.notified = 0
+ del node
+ del lisnr3
+ del lisnr4
+ assert _NodeCallback.notified == 0
+
+ done('testDead')
+
+ testDead()
+
+ print 'Exiting tests'
+#---------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ test()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcprint.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcprint.py
new file mode 100644
index 0000000..e477e0d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcprint.py
@@ -0,0 +1,614 @@
+#-----------------------------------------------------------------------------
+# Name: stcprint.py
+# Purpose: wx.StyledTextCtrl printing support
+#
+# Author: Rob McMullen
+#
+# Created: 2009
+# RCS-ID: $Id: stcprint.py 67499 2011-04-15 20:33:40Z CJP $
+# Copyright: (c) 2009 Rob McMullen <robm@users.sourceforge.net>
+# (c) 2007 Cody Precord <staff@editra.org>
+# License: wxWidgets
+#-----------------------------------------------------------------------------
+"""Printing support for the wx.StyledTextCtrl
+
+Concrete implementation of the wx.Printout class to generate a print preview
+and paper copies of the contents of a wx.StyledTextCtrl. This was written
+for U{Peppy<http://peppy.flipturn.org>} but has been designed as a standalone
+class with no dependencies on peppy. It can be used for general purpose
+printing or print preview of a wx.StyledTextCtrl. See the demo application at
+the end of this file for more information.
+
+I used code from U{Editra<http://www.editra.org>} as a starting point; other
+pointers came from the wxPython mailing list, and lots was just pure ol'
+trial and error because I couldn't find much specific documentation on the
+FormatRange method of the STC.
+
+NOTE: there are issues with certain scale factors when using print preview on
+MSW. Some scale factors seem to work correctly, like 150%, but other smaller
+scale factors cause the preview font size to fluctuate. Some zoom levels will
+use very small fonts and render all the lines in the top half of the page,
+while other zoom levels use an incorrectly large font and render lines off the
+bottom of the page. The printed output is unaffected, however, and renders
+the correct number of lines.
+"""
+
+import os
+
+import wx
+import wx.stc
+_ = wx.GetTranslation
+
+class STCPrintout(wx.Printout):
+ """Specific printing support of the wx.StyledTextCtrl for the wxPython
+ framework
+
+ This class can be used for both printing to a printer and for print preview
+ functions. Unless otherwise specified, the print is scaled based on the
+ size of the current font used in the STC so that specifying a larger font
+ produces a larger font in the printed output (and correspondingly fewer
+ lines per page). Alternatively, you can eihdec specify the number of
+ lines per page, or you can specify the print font size in points which
+ produces a constant number of lines per inch regardless of the paper size.
+
+ Note that line wrapping in the source STC is currently ignored and lines
+ will be truncated at the right margin instead of wrapping. The STC doesn't
+ provide a convenient method for determining where line breaks occur within
+ a wrapped line, so it may be a difficult task to ever implement printing
+ with line wrapping using the wx.StyledTextCtrl.FormatRange method.
+ """
+ debuglevel = 0
+
+ def __init__(self, stc, page_setup_data=None, print_mode=None, title=None,
+ border=False, lines_per_page=None, output_point_size=None,
+ job_title=None):
+ """Constructor.
+
+ @param stc: wx.StyledTextCtrl to print
+
+ @kwarg page_setup_data: optional wx.PageSetupDialogData instance that
+ is used to determine the margins of the page.
+
+ @kwarg print_mode: optional; of the wx.stc.STC_PRINT_*
+ flags indicating how to render color text. Defaults to
+ wx.stc.STC_PRINT_COLOURONWHITEDEFAULTBG
+
+ @kwarg title: optional text string to use as the title which will be
+ centered above the first line of text on each page
+
+ @kwarg border: optional flag indicating whether or not to draw a black
+ border around the text on each page
+
+ @kwarg lines_per_page: optional integer that will force the page to
+ contain the specified number of lines. Either of C{output_point_size}
+ and C{lines_per_page} fully specifies the page, so if both are
+ specified, C{lines_per_page} will be used.
+
+ @kwarg output_point_size: optional integer that will force the output
+ text to be drawn in the specified point size. (Note that there are
+ 72 points per inch.) If not specified, the point size of the text in
+ the STC will be used unless C{lines_per_page} is specified. Either of
+ C{output_point_size} and C{lines_per_page} fully specifies the page,
+ so if both are specified, C{lines_per_page} will be used.
+ """
+ if not job_title:
+ job_title = wx.PrintoutTitleStr
+ wx.Printout.__init__(self, job_title)
+ self.stc = stc
+ if print_mode:
+ self.print_mode = print_mode
+ else:
+ self.print_mode = wx.stc.STC_PRINT_COLOURONWHITEDEFAULTBG
+ if title is not None:
+ self.title = title
+ else:
+ self.title = ""
+ if page_setup_data is None:
+ self.top_left_margin = wx.Point(15,15)
+ self.bottom_right_margin = wx.Point(15,15)
+ else:
+ self.top_left_margin = page_setup_data.GetMarginTopLeft()
+ self.bottom_right_margin = page_setup_data.GetMarginBottomRight()
+
+ try:
+ value = float(output_point_size)
+ if value > 0.0:
+ self.output_point_size = value
+ except (TypeError, ValueError):
+ self.output_point_size = None
+
+ try:
+ value = int(lines_per_page)
+ if value > 0:
+ self.user_lines_per_page = value
+ except (TypeError, ValueError):
+ self.user_lines_per_page = None
+
+ self.border_around_text = border
+
+ self.setHeaderFont()
+
+ def OnPreparePrinting(self):
+ """Called once before a print job is started to set up any defaults.
+
+ """
+ dc = self.GetDC()
+ self._calculateScale(dc)
+ self._calculatePageCount()
+
+ def _calculateScale(self, dc):
+ """Scale the DC
+
+ This routine scales the DC based on the font size, determines the
+ number of lines on a page, and saves some useful pixel locations like
+ the top left corner and the width and height of the drawing area in
+ logical coordinates.
+ """
+ if self.debuglevel > 0:
+ print
+
+ dc.SetFont(self.stc.GetFont())
+
+ # Calculate pixels per inch of the various devices. The dc_ppi will be
+ # equivalent to the page or screen PPI if the target is the printer or
+ # a print preview, respectively.
+ page_ppi_x, page_ppi_y = self.GetPPIPrinter()
+ screen_ppi_x, screen_ppi_y = self.GetPPIScreen()
+ dc_ppi_x, dc_ppi_y = dc.GetPPI()
+ if self.debuglevel > 0:
+ print("printer ppi: %dx%d" % (page_ppi_x, page_ppi_y))
+ print("screen ppi: %dx%d" % (screen_ppi_x, screen_ppi_y))
+ print("dc ppi: %dx%d" % (dc_ppi_x, dc_ppi_y))
+
+ # Calculate paper size. Note that this is the size in pixels of the
+ # entire paper, which may be larger than the printable range of the
+ # printer. We need to use the entire paper size because we calculate
+ # margins ourselves. Note that GetPageSizePixels returns the
+ # dimensions of the printable area.
+ px, py, pw, ph = self.GetPaperRectPixels()
+ page_width_inch = float(pw) / page_ppi_x
+ page_height_inch = float(ph) / page_ppi_y
+ if self.debuglevel > 0:
+ print("page pixels: %dx%d" % (pw, ph))
+ print("page size: %fx%f in" % (page_width_inch, page_height_inch))
+
+ dw, dh = dc.GetSizeTuple()
+ dc_pixels_per_inch_x = float(dw) / page_width_inch
+ dc_pixels_per_inch_y = float(dh) / page_height_inch
+ if self.debuglevel > 0:
+ print("device pixels: %dx%d" % (dw, dh))
+ print("device pixels per inch: %fx%f" % (dc_pixels_per_inch_x, dc_pixels_per_inch_y))
+
+ # Calculate usable page size
+ page_height_mm = page_height_inch * 25.4
+ margin_mm = self.top_left_margin[1] + self.bottom_right_margin[1]
+ usable_page_height_mm = page_height_mm - margin_mm
+
+ # Lines per page is then the number of lines (based on the point size
+ # reported by wx) that will fit into the usable page height
+ self.lines_pp = self._calculateLinesPerPage(dc, usable_page_height_mm)
+
+ # The final DC scale factor is then the ratio of the total height in
+ # pixels inside the margins to the number of pixels that it takes to
+ # represent the number of lines
+ dc_margin_pixels = float(dc_pixels_per_inch_y) * margin_mm / 25.4
+ dc_usable_pixels = dh - dc_margin_pixels
+ page_to_dc = self._calculateScaleFactor(dc, dc_usable_pixels, self.lines_pp)
+
+ dc.SetUserScale(page_to_dc, page_to_dc)
+
+ if self.debuglevel > 0:
+ print("Usable page height: %f in" % (usable_page_height_mm / 25.4))
+ print("Usable page pixels: %d" % dc_usable_pixels)
+ print("lines per page: %d" % self.lines_pp)
+ print("page_to_dc: %f" % page_to_dc)
+
+ self.x1 = dc.DeviceToLogicalXRel(float(self.top_left_margin[0]) / 25.4 * dc_pixels_per_inch_x)
+ self.y1 = dc.DeviceToLogicalXRel(float(self.top_left_margin[1]) / 25.4 * dc_pixels_per_inch_y)
+ self.x2 = dc.DeviceToLogicalXRel(dw) - dc.DeviceToLogicalXRel(float(self.bottom_right_margin[0]) / 25.4 * dc_pixels_per_inch_x)
+ self.y2 = dc.DeviceToLogicalYRel(dh) - dc.DeviceToLogicalXRel(float(self.bottom_right_margin[1]) / 25.4 * dc_pixels_per_inch_y)
+ page_height = self.y2 - self.y1
+
+ #self.lines_pp = int(page_height / dc_pixels_per_line)
+
+ if self.debuglevel > 0:
+ print("page size: %d,%d -> %d,%d, height=%d" % (int(self.x1), int(self.y1), int(self.x2), int(self.y2), page_height))
+
+ def _calculateLinesPerPage(self, dc, usable_page_height_mm):
+ """Calculate the number of lines that will fit on the page.
+
+ @param dc: the Device Context
+
+ @param usable_page_height_mm: height in mm of the printable part of the
+ page (i.e. with the border height removed)
+
+ @returns: the number of lines on the page
+ """
+ if self.user_lines_per_page is not None:
+ return self.user_lines_per_page
+
+ font = dc.GetFont()
+ if self.output_point_size is not None:
+ points_per_line = self.output_point_size
+ else:
+ points_per_line = font.GetPointSize()
+
+ # desired lines per mm based on point size. Note: printer points are
+ # defined as 72 points per inch
+ lines_per_inch = 72.0 / float(points_per_line)
+
+ if self.debuglevel > 0:
+ print("font: point size per line=%d" % points_per_line)
+ print("font: lines per inch=%f" % lines_per_inch)
+
+ # Lines per page is then the number of lines (based on the point size
+ # reported by wx) that will fit into the usable page height
+ return float(usable_page_height_mm) / 25.4 * lines_per_inch
+
+ def _calculateScaleFactor(self, dc, dc_usable_pixels, lines_pp):
+ """Calculate the scale factor for the DC to fit the number of lines
+ onto the printable area
+
+ @param dc: the Device Context
+
+ @param dc_usable_pixels: the number of pixels that defines usable
+ height of the printable area
+
+ @param lines_pp: the number of lines to fit into the printable area
+
+ @returns: the scale facter to be used in wx.DC.SetUserScale
+ """
+ # actual line height in pixels according to the DC
+ dc_pixels_per_line = dc.GetCharHeight()
+
+ # actual line height in pixels according to the STC. This can be
+ # different from dc_pixels_per_line even though it is the same font.
+ # Don't know why this is the case; maybe because the STC takes into
+ # account additional spacing?
+ stc_pixels_per_line = self.stc.TextHeight(0)
+ if self.debuglevel > 0:
+ print("font: dc pixels per line=%d" % dc_pixels_per_line)
+ print("font: stc pixels per line=%d" % stc_pixels_per_line)
+
+ # Platform dependency alert: I don't know why this works, but through
+ # experimentation it seems like the scaling factor depends on
+ # different font heights depending on the platform.
+ if wx.Platform == "__WXMSW__":
+ # On windows, the important font height seems to be the number of
+ # pixels reported by the STC
+ page_to_dc = float(dc_usable_pixels) / (stc_pixels_per_line * lines_pp)
+ else:
+ # Linux and Mac: the DC font height seems to be the correct height
+ page_to_dc = float(dc_usable_pixels) / (dc_pixels_per_line * lines_pp)
+ return page_to_dc
+
+ def _calculatePageCount(self, attempt_wrap=False):
+ """Calculates offsets into the STC for each page
+
+ This pre-calculates the page offsets for each page to support print
+ preview being able to seek backwards and forwards.
+ """
+ page_offsets = []
+ page_line_start = 0
+ lines_on_page = 0
+ num_lines = self.stc.GetLineCount()
+
+ line = 0
+ while line < num_lines:
+ if attempt_wrap:
+ wrap_count = self.stc.WrapCount(line)
+ if wrap_count > 1 and self.debuglevel > 0:
+ print("found wrapped line %d: %d" % (line, wrap_count))
+ else:
+ wrap_count = 1
+
+ # If the next line pushes the count over the edge, mark a page and
+ # start the next page
+ if lines_on_page + wrap_count > self.lines_pp:
+ start_pos = self.stc.PositionFromLine(page_line_start)
+ end_pos = self.stc.GetLineEndPosition(page_line_start + lines_on_page - 1)
+ if self.debuglevel > 0:
+ print("Page: line %d - %d" % (page_line_start, page_line_start + lines_on_page))
+ page_offsets.append((start_pos, end_pos))
+ page_line_start = line
+ lines_on_page = 0
+ lines_on_page += wrap_count
+ line += 1
+
+ if lines_on_page > 0:
+ start_pos = self.stc.PositionFromLine(page_line_start)
+ end_pos = self.stc.GetLineEndPosition(page_line_start + lines_on_page)
+ page_offsets.append((start_pos, end_pos))
+
+ self.page_count = len(page_offsets)
+ self.page_offsets = page_offsets
+ if self.debuglevel > 0:
+ print("page offsets: %s" % self.page_offsets)
+
+ def _getPositionsOfPage(self, page):
+ """Get the starting and ending positions of a page
+
+ @param page: page number
+
+ @returns: tuple containing the start and end positions that can be
+ passed to FormatRange to render a page
+ """
+ page -= 1
+ start_pos, end_pos = self.page_offsets[page]
+ return start_pos, end_pos
+
+ def GetPageInfo(self):
+ """Return the valid page ranges.
+
+ Note that pages are numbered starting from one.
+ """
+ return (1, self.page_count, 1, self.page_count)
+
+ def HasPage(self, page):
+ """Returns True if the specified page is within the page range
+
+ """
+ return page <= self.page_count
+
+ def OnPrintPage(self, page):
+ """Draws the specified page to the DC
+
+ @param page: page number to render
+ """
+ dc = self.GetDC()
+ self._calculateScale(dc)
+
+ self._drawPageContents(dc, page)
+ self._drawPageHeader(dc, page)
+ self._drawPageBorder(dc)
+
+ return True
+
+ def _drawPageContents(self, dc, page):
+ """Render the STC window into a DC for printing.
+
+ Force the right margin of the rendered window to be huge so the STC
+ won't attempt word wrapping.
+
+ @param dc: the device context representing the page
+
+ @param page: page number
+ """
+ start_pos, end_pos = self._getPositionsOfPage(page)
+ render_rect = wx.Rect(self.x1, self.y1, 32000, self.y2)
+ page_rect = wx.Rect(self.x1, self.y1, self.x2, self.y2)
+
+ self.stc.SetPrintColourMode(self.print_mode)
+ edge_mode = self.stc.GetEdgeMode()
+ self.stc.SetEdgeMode(wx.stc.STC_EDGE_NONE)
+ end_point = self.stc.FormatRange(True, start_pos, end_pos, dc, dc,
+ render_rect, page_rect)
+ self.stc.SetEdgeMode(edge_mode)
+
+ def _drawPageHeader(self, dc, page):
+ """Draw the page header into the DC for printing
+
+ @param dc: the device context representing the page
+
+ @param page: page number
+ """
+ # Set font for title/page number rendering
+ dc.SetFont(self.getHeaderFont())
+ dc.SetTextForeground ("black")
+ dum, yoffset = dc.GetTextExtent(".")
+ yoffset /= 2
+ if self.title:
+ title_w, title_h = dc.GetTextExtent(self.title)
+ dc.DrawText(self.title, self.x1, self.y1 - title_h - yoffset)
+
+ # Page Number
+ page_lbl = _("Page: %d") % page
+ pg_lbl_w, pg_lbl_h = dc.GetTextExtent(page_lbl)
+ dc.DrawText(page_lbl, self.x2 - pg_lbl_w, self.y1 - pg_lbl_h - yoffset)
+
+ def setHeaderFont(self, point_size=10, family=wx.FONTFAMILY_SWISS,
+ style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_NORMAL):
+ """Set the font to be used as the header font
+
+ @param point_size: point size of the font
+
+ @param family: one of the wx.FONTFAMILY_* values, e.g.
+ wx.FONTFAMILY_SWISS, wx.FONTFAMILY_ROMAN, etc.
+
+ @param style: one of the wx.FONTSTYLE_* values, e.g.
+ wxFONTSTYLE_NORMAL, wxFONTSTYLE_ITALIC, etc.
+
+ @param weight: one of the wx.FONTWEIGHT_* values, e.g.
+ wx.FONTWEIGHT_NORMAL, wx.FONTWEIGHT_LIGHT, etc.
+ """
+ self.header_font_point_size = point_size
+ self.header_font_family = family
+ self.header_font_style = style
+ self.header_font_weight = weight
+
+ def getHeaderFont(self):
+ """Returns the font to be used to draw the page header text
+
+ @returns: wx.Font instance
+ """
+ point_size = self.header_font_point_size
+ font = wx.Font(point_size, self.header_font_family,
+ self.header_font_style, self.header_font_weight)
+ return font
+
+ def _drawPageBorder(self, dc):
+ """Draw the page border into the DC for printing
+
+ @param dc: the device context representing the page
+ """
+ if self.border_around_text:
+ dc.SetPen(wx.BLACK_PEN)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(self.x1, self.y1, self.x2 - self.x1 + 1, self.y2 - self.y1 + 1)
+
+
+if __name__ == "__main__":
+ import sys
+ import __builtin__
+ __builtin__._ = unicode
+
+ # Set up sample print data
+ top_left_margin = wx.Point(15,15)
+ bottom_right_margin = wx.Point(15,15)
+
+ def wrap(text, width=80):
+ """A word-wrap function that preserves existing line breaks
+ and most spaces in the text.
+
+ Expects that existing line breaks are posix newlines (\n).
+
+ http://code.activestate.com/recipes/148061/
+ """
+ return reduce(lambda line, word, width=width: '%s%s%s' %
+ (line,
+ ' \n'[(len(line)-line.rfind('\n')-1
+ + len(word.split('\n',1)[0]
+ ) >= width)],
+ word),
+ text.split(' ')
+ )
+
+ class TestSTC(wx.stc.StyledTextCtrl):
+ def __init__(self, *args, **kwargs):
+ wx.stc.StyledTextCtrl.__init__(self, *args, **kwargs)
+ self.SetMarginType(0, wx.stc.STC_MARGIN_NUMBER)
+ self.SetMarginWidth(0, 32)
+
+ class Frame(wx.Frame):
+ def __init__(self, *args, **kwargs):
+ super(self.__class__, self).__init__(*args, **kwargs)
+
+ self.stc = TestSTC(self, -1)
+
+ self.CreateStatusBar()
+ menubar = wx.MenuBar()
+ self.SetMenuBar(menubar) # Adding the MenuBar to the Frame content.
+ menu = wx.Menu()
+ menubar.Append(menu, "File")
+ self.menuAdd(menu, "Open", "Open File", self.OnOpenFile)
+ menu.AppendSeparator()
+ self.menuAdd(menu, "Print Preview", "Display print preview", self.OnPrintPreview)
+ self.menuAdd(menu, "Print", "Print to printer or file", self.OnPrint)
+ menu.AppendSeparator()
+ self.menuAdd(menu, "Quit", "Exit the pragram", self.OnQuit)
+
+ self.print_data = wx.PrintData()
+ self.print_data.SetPaperId(wx.PAPER_LETTER)
+
+
+ def loadFile(self, filename, word_wrap=False):
+ fh = open(filename)
+ text = fh.read()
+ if word_wrap:
+ text = wrap(text)
+ self.stc.SetText(fh.read())
+
+ def loadSample(self, paragraphs=10, word_wrap=False):
+ lorem_ipsum = u"""\
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus mattis
+commodo sem. Phasellus scelerisque tellus id lorem. Nulla facilisi.
+Suspendisse potenti. Fusce velit odio, scelerisque vel, consequat nec,
+dapibus sit amet, tortor.
+
+Vivamus eu turpis. Nam eget dolor. Integer at elit. Praesent mauris. Nullam non nulla at nulla tincidunt malesuada. Phasellus id ante. Sed mauris. Integer volutpat nisi non diam.
+
+Etiam elementum. Pellentesque interdum justo eu risus. Cum sociis natoque
+penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc
+semper.
+
+In semper enim ut odio. Nulla varius leo commodo elit. Quisque condimentum, nisl eget elementum laoreet, mauris turpis elementum felis, ut accumsan nisl velit et mi.
+
+And some Russian: \u041f\u0438\u0442\u043e\u043d - \u043b\u0443\u0447\u0448\u0438\u0439 \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f!
+
+"""
+ if word_wrap:
+ lorem_ipsum = wrap(lorem_ipsum)
+ self.stc.ClearAll()
+ for i in range(paragraphs):
+ self.stc.AppendText(lorem_ipsum)
+ wx.CallAfter(self.OnPrintPreview, None)
+
+ def menuAdd(self, menu, name, desc, fcn, id=-1, kind=wx.ITEM_NORMAL):
+ if id == -1:
+ id = wx.NewId()
+ a = wx.MenuItem(menu, id, name, desc, kind)
+ menu.AppendItem(a)
+ wx.EVT_MENU(self, id, fcn)
+ menu.SetHelpString(id, desc)
+
+ def OnOpenFile(self, evt):
+ dlg = wx.FileDialog(self, "Choose a text file",
+ defaultDir = "",
+ defaultFile = "",
+ wildcard = "*")
+ if dlg.ShowModal() == wx.ID_OK:
+ print("Opening %s" % dlg.GetPath())
+ self.loadFile(dlg.GetPath())
+ dlg.Destroy()
+
+ def OnQuit(self, evt):
+ self.Close(True)
+
+ def getPrintData(self):
+ return self.print_data
+
+ def OnPrintPreview(self, evt):
+ wx.CallAfter(self.showPrintPreview)
+
+ def showPrintPreview(self):
+ printout = STCPrintout(self.stc, title="Testing!!!", border=True, output_point_size=10)
+ printout2 = STCPrintout(self.stc, title="Testing!!!", border=True, output_point_size=10)
+ preview = wx.PrintPreview(printout, printout2, self.getPrintData())
+ preview.SetZoom(100)
+ if preview.IsOk():
+ pre_frame = wx.PreviewFrame(preview, self, _("Print Preview"))
+ dsize = wx.GetDisplaySize()
+ pre_frame.SetInitialSize((self.GetSize()[0],
+ dsize.GetHeight() - 100))
+ pre_frame.Initialize()
+ pre_frame.Show()
+ else:
+ wx.MessageBox(_("Failed to create print preview"),
+ _("Print Error"),
+ style=wx.ICON_ERROR|wx.OK)
+
+ def OnPrint(self, evt):
+ wx.CallAfter(self.showPrint)
+
+ def showPrint(self):
+ pdd = wx.PrintDialogData(self.getPrintData())
+ printer = wx.Printer(pdd)
+ printout = STCPrintout(self.stc)
+ result = printer.Print(self.stc, printout)
+ if result:
+ data = printer.GetPrintDialogData()
+ self.print_data = wx.PrintData(data.GetPrintData())
+ elif printer.GetLastError() == wx.PRINTER_ERROR:
+ wx.MessageBox(_("There was an error when printing.\n"
+ "Check that your printer is properly connected."),
+ _("Printer Error"),
+ style=wx.ICON_ERROR|wx.OK)
+ printout.Destroy()
+
+ app = wx.App(False)
+ frame = Frame(None, size=(800, -1))
+ word_wrap = False
+ filename = None
+ if len(sys.argv) > 1:
+ if not sys.argv[-1].startswith("-"):
+ filename = sys.argv[-1]
+ if '-d' in sys.argv:
+ STCPrintout.debuglevel = 1
+ if '-w' in sys.argv:
+ word_wrap = True
+ if filename:
+ frame.loadFile(filename, word_wrap)
+ else:
+ frame.loadSample(word_wrap=word_wrap)
+ frame.Show()
+ app.MainLoop()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcspellcheck.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcspellcheck.py
new file mode 100644
index 0000000..e253714
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcspellcheck.py
@@ -0,0 +1,815 @@
+#-----------------------------------------------------------------------------
+# Name: stcspellcheck.py
+# Purpose: Spell checking for the wx.StyledTextControl using pyenchant
+#
+# Author: Rob McMullen
+#
+# Created: 2008
+# RCS-ID: $Id: stcspellcheck.py 69791 2011-11-19 22:02:59Z CJP $
+# Copyright: (c) 2008 Rob McMullen
+# License: wxWidgets
+#-----------------------------------------------------------------------------
+#
+# Originally based on code from Luke-SDK, which includes the following
+# copyright notice:
+#
+# Copyright (c) 2007 Eur Ing Christopher Thoday, cthoday@mail.berlios.de.
+#
+# Permission to use, copy, modify and distribute this software and its
+# documentation for any purpose and without fee is hereby granted, provided
+# that the above copyright notice appear in all copies and that both
+# the copyright notice and this permission notice appear in supporting
+# documentation.
+#
+# Christopher Thoday makes no representations about the suitability of this
+# software for any purpose. It is provided "as is" without express or implied
+# warranty.
+
+"""Spell checking for the wx.StyledTextControl using pyenchant
+
+This module was insipred by the spell check function from Christopher Thoday's
+U{Luke SDK<http://luke-sdk.berlios.de/>}.
+
+Spell checking is provided by the pyenchant library, which is an external
+dependency not part of wxPython. Packages are available for Mac, Unix, and
+windows at U{http://pyenchant.sourceforge.net}
+
+Currently provides:
+ - spell checking of entire buffer, currently visible page, or selection region
+ - user specified indicator number (0 - 2), style, and color
+ - language can be changed on the fly
+ - update the spelling as you type
+ - check the document in either idle time or in a background thread
+
+@author: Rob McMullen
+@version: 1.2
+
+Changelog::
+ 1.2:
+ - Rewrote as a standalone class rather than a static mixin
+ 1.1:
+ - Added helper function to use idle processing time to check document
+ - Added word checking function for use in instant spell checking
+ 1.0:
+ - First public release
+"""
+
+import os
+import locale
+import wx
+import wx.stc
+
+# Assume MacPorts install of Enchant
+if wx.Platform == '__WXMAC__':
+ if 'PYENCHANT_LIBRARY_PATH' not in os.environ:
+ os.environ['PYENCHANT_LIBRARY_PATH'] = '/opt/local/lib/libenchant.dylib'
+
+try:
+ import enchant
+except ImportError:
+ # no big deal; support for enchant simply won't be included
+ pass
+except:
+ # big deal; enchant is there but there's some error that is preventing
+ # its import
+ import traceback
+ traceback.print_exc()
+
+class STCSpellCheck(object):
+ """Spell checking for use with wx.StyledTextControl.
+
+ This shows spelling errors using the styling indicators (e.g. the red
+ squiggly underline) of the styled text control; I find this much more
+ convenient than a dialog-box that makes you click through each mistake.
+
+ The eventual goal of the module is to provide on-the-fly spell checking
+ that will display errors as you type, and also will highlight errors
+ during idle time or in a background thread.
+
+ Spell checking is provided through the pyenchant module. Without
+ pyenchant, this object won't do anything useful, but it is still safe to
+ be used. It wraps all calls to pyenchant with try/except blocks to catch
+ import errors, and any calls to the spell checking functions will return
+ immediately.
+
+ To use the spelling check, use one of the methods L{checkAll},
+ L{checkCurrentPage}, or L{checkSelection}. Clear the spelling
+ indicators with L{clearAll}.
+ """
+ # Class attributes to act as default values
+ _spelling_lang = None
+ _spelling_dict = None
+
+ def __init__(self, stc, *args, **kwargs):
+ """Mixin must be initialized using this constructor.
+
+ Keyword arguments are also available instead of calling the
+ convenience functions. For L{setIndicator}, use C{indicator},
+ C{indicator_color}, and {indicator_style}; for L{setLanguage},
+ use C{language}; and for L{setMinimumWordSize}, use
+ C{min_word_size}. See the descriptions of those methods for more info.
+ """
+ self.stc = stc
+ self.setIndicator(kwargs.get('indicator', 2),
+ kwargs.get('indicator_color', "#FF0000"),
+ kwargs.get('indicator_style', wx.stc.STC_INDIC_SQUIGGLE))
+ self.setMinimumWordSize(kwargs.get('min_word_size', 3))
+ if 'language' in kwargs:
+ # Don't set default language unless explicitly specified -- it
+ # might have already been set through the class method
+ self.setDefaultLanguage(kwargs['language'])
+ if 'check_region' in kwargs:
+ # optional function to specify if the region should be spell
+ # checked. Function should return True if the position should
+ # be spell-checked; False if it doesn't make sense to spell check
+ # that part of the document
+ self._spell_check_region = kwargs['check_region']
+ else:
+ self._spell_check_region = lambda s: True
+ self._spelling_debug = False
+
+ self._spelling_last_idle_line = -1
+ self.dirty_range_count_per_idle = 5
+
+ self._no_update = False
+ self._last_block = -1
+
+ self.clearDirtyRanges()
+
+ def setIndicator(self, indicator=None, color=None, style=None):
+ """Set the indicator styling for misspelled words.
+
+ Set the indicator index to use, its color, and the visual style.
+
+ @param indicator: indicator number (usually 0, 1, or 2, but may be fewer
+ depending on the number of style bits you've chosen for the stc.)
+ @param color: string indicating the color of the indicator (e.g.
+ "#FF0000" for red)
+ @param style: stc indicator style; one of the wx.stc.STC_INDIC_*
+ constants (currently wx.stc.STC_INDIC_PLAIN, wx.stc.STC_INDIC_SQUIGGLE,
+ wx.stc.STC_INDIC_TT, wx.stc.STC_INDIC_DIAGONAL,
+ wx.stc.STC_INDIC_STRIKE, wx.stc.STC_INDIC_HIDDEN,
+ wx.stc.STC_INDIC_BOX, wx.stc.STC_INDIC_ROUNDBOX)
+ """
+ indicators = {0: wx.stc.STC_INDIC0_MASK,
+ 1: wx.stc.STC_INDIC1_MASK,
+ 2: wx.stc.STC_INDIC2_MASK
+ }
+ if indicator is not None:
+ if indicator not in indicators:
+ indicator = 0
+ # The current view may have fewer than 3 indicators
+ bitmax = 7 - self.stc.GetStyleBits()
+ if indicator > bitmax:
+ indicator = bitmax
+ self._spelling_indicator = indicator
+ self._spelling_indicator_mask = indicators[self._spelling_indicator]
+
+ if color is not None:
+ self._spelling_color = color
+ self.stc.IndicatorSetForeground(self._spelling_indicator,
+ self._spelling_color)
+
+ if style is not None:
+ if style > wx.stc.STC_INDIC_MAX:
+ style = wx.stc.STC_INDIC_MAX
+ self._spelling_style = style
+ self.stc.IndicatorSetStyle(self._spelling_indicator,
+ self._spelling_style)
+
+ @classmethod
+ def getAvailableLanguages(cls):
+ """Return a list of supported languages.
+
+ Pyenchant supplies a list of its supported languages, so this is just
+ a simple wrapper around its C{list_languages} function. Each item in
+ the list is a text string indicating the locale name, e.g. en_US, ru,
+ ru_RU, eo, es_ES, etc.
+
+ @return: a list of text strings indicating the supported languages
+ """
+ try:
+ return enchant.list_languages()
+ except NameError:
+ pass
+ return []
+
+ @classmethod
+ def _getDict(cls, lang):
+ try:
+ d = enchant.Dict(lang)
+ except:
+ # Catch all exceptions, because if pyenchant isn't available, you
+ # can't catch the enchant.DictNotFound error.
+ d = None
+ return d
+
+ def setCheckRegion(self, func):
+ """Set region checker callable
+ @param func: def func(pos): return bool
+
+ """
+ self.clearAll()
+ self._spell_check_region = func
+
+ @classmethod
+ def setDefaultLanguage(cls, lang):
+ """Set the default language for spelling check.
+
+ The string should be in language locale format, e.g. en_US, ru, ru_RU,
+ eo, es_ES, etc. See L{getAvailableLanguages}.
+
+ @param lang: text string indicating the language
+ """
+ cls._spelling_lang = lang
+ cls._spelling_dict = cls._getDict(lang)
+
+ @classmethod
+ def getSpellingDictionary(cls):
+ """Get the currently used spelling dictionary
+ @return: enchant.Dict instance or None
+
+ """
+ return cls._spelling_dict
+
+ def setLanguage(self, lang):
+ """Set the language for spelling check for this class, if different than
+ the default.
+
+ The string should be in language locale format, e.g. en_US, ru, ru_RU,
+ eo, es_ES, etc. See L{getAvailableLanguages}.
+
+ @param lang: text string indicating the language
+ """
+ # Note that this instance variable will shadow the class attribute
+ self._spelling_lang = lang
+ self._spelling_dict = self._getDict(lang)
+
+ def hasDictionary(self):
+ """Returns True if a dictionary is available to spell check the current
+ language.
+ """
+ return self._spelling_dict is not None
+
+ @classmethod
+ def isEnchantOk(cls):
+ """Returns True if enchant is available"""
+ return 'enchant' in globals()
+
+ @classmethod
+ def reloadEnchant(cls, libpath=u''):
+ """Try (re)loading the enchant module. Use to dynamically try to
+ import enchant incase it could be loaded at the time of the import of
+ this module.
+ @keyword libpath: optionally specify path to libenchant
+ @return: bool
+
+ """
+ try:
+ if libpath and os.path.exists(libpath):
+ os.environ['PYENCHANT_LIBRARY_PATH'] = libpath
+
+ if cls.isEnchantOk():
+ reload(enchant)
+ else:
+ mod = __import__('enchant', globals(), locals())
+ globals()['enchant'] = mod
+ except ImportError:
+ return False
+ else:
+ return True
+
+ def getLanguage(self):
+ """Returns True if a dictionary is available to spell check the current
+ language.
+ """
+ return self._spelling_lang
+
+ def setMinimumWordSize(self, size):
+ """Set the minimum word size that will be looked up in the dictionary.
+
+ Words smaller than this size won't be spell checked.
+ """
+ self._spelling_word_size = size
+
+ def clearAll(self):
+ """Clear the stc of all spelling indicators."""
+ self.stc.StartStyling(0, self._spelling_indicator_mask)
+ self.stc.SetStyling(self.stc.GetLength(), 0)
+
+ def checkRange(self, start, end):
+ """Perform a spell check over a range of text in the document.
+
+ This is the main spell checking routine -- it loops over the range
+ of text using the L{findNextWord} method to break the text into
+ words to check. Misspelled words are highlighted using the current
+ indicator.
+
+ @param start: starting position
+ @param end: last position to check
+ """
+ spell = self._spelling_dict
+ if not spell:
+ return
+
+ # Remove any old spelling indicators
+ mask = self._spelling_indicator_mask
+ count = end - start
+ if count <= 0:
+ if self._spelling_debug:
+ print("No need to check range: start=%d end=%d count=%d" % (start, end, count))
+ return
+ self.stc.StartStyling(start, mask)
+ self.stc.SetStyling(count, 0)
+
+ text = self.stc.GetTextRange(start, end) # note: returns unicode
+ unicode_index = 0
+ max_index = len(text)
+
+ last_index = 0 # last character in text a valid raw byte position
+ last_pos = start # raw byte position corresponding to last_index
+ while unicode_index < max_index:
+ start_index, end_index = self.findNextWord(text, unicode_index, max_index)
+ if end_index >= 0:
+ if end_index - start_index >= self._spelling_word_size:
+ if self._spelling_debug:
+ print("checking %s at text[%d:%d]" % (repr(text[start_index:end_index]), start_index, end_index))
+ if not spell.check(text[start_index:end_index]):
+ # Because unicode characters are stored as utf-8 in the
+ # stc and the positions in the stc correspond to the
+ # raw bytes, not the number of unicode characters, we
+ # have to find out the offset to the unicode chars in
+ # terms of raw bytes.
+
+ # find the number of raw bytes from the last calculated
+ # styling position to the start of the word
+ last_pos += len(text[last_index:start_index].encode('utf-8'))
+
+ # find the length of the word in raw bytes
+ raw_count = len(text[start_index:end_index].encode('utf-8'))
+
+ if self._spell_check_region(last_pos):
+ if self._spelling_debug:
+ print("styling text[%d:%d] = (%d,%d) to %d" % (start_index, end_index, last_pos, last_pos + raw_count, mask))
+ self.stc.StartStyling(last_pos, mask)
+ self.stc.SetStyling(raw_count, mask)
+ elif self._spelling_debug:
+ print("not in valid spell check region. styling position corresponding to text[%d:%d] = (%d,%d)" % (start_index, end_index, last_pos, last_pos + raw_count))
+ last_pos += raw_count
+ last_index = end_index
+ unicode_index = end_index
+ else:
+ break
+
+ def checkAll(self):
+ """Perform a spell check on the entire document."""
+ return self.checkRange(0, self.stc.GetLength())
+
+ def checkSelection(self):
+ """Perform a spell check on the currently selected region."""
+ return self.checkRange(self.stc.GetSelectionStart(), self.stc.GetSelectionEnd())
+
+ def checkLines(self, startline=-1, count=-1):
+ """Perform a spell check on group of lines.
+
+ Given the starting line, check the spelling on a block of lines. If
+ the number of lines in the block is not specified, use the number of
+ currently visibile lines.
+
+ @param startline: current line, or -1 to use the first visible line
+ @param count: number of lines in the block, or -1 to use the number of
+ lines visible on screen
+ """
+ if startline < 0:
+ startline = self.stc.GetFirstVisibleLine()
+ start = self.stc.PositionFromLine(startline)
+ if count < 0:
+ count = self.stc.LinesOnScreen()
+ endline = startline + count
+ if endline > self.stc.GetLineCount():
+ endline = self.stc.GetLineCount() - 1
+ end = self.stc.GetLineEndPosition(endline)
+ if self._spelling_debug:
+ print("Checking lines %d-%d, chars %d=%d" % (startline, endline, start, end))
+ return self.checkRange(start, end)
+
+ def checkCurrentPage(self):
+ """Perform a spell check on the currently visible lines."""
+ return self.checkLines()
+
+ def findNextWord(self, utext, index, length):
+ """Find the next valid word to check.
+
+ Designed to be overridden in subclasses, this method takes a starting
+ position in an array of text and returns a tuple indicating the next
+ valid word in the string.
+
+ @param utext: array of unicode chars
+ @param i: starting index within the array to search
+ @param length: length of the text
+ @return: tuple indicating the word start and end indexes, or (-1, -1)
+ indicating that the end of the array was reached and no word was found
+ """
+ while index < length:
+ if utext[index].isalpha():
+ end = index + 1
+ while end < length and utext[end].isalpha():
+ end += 1
+ return (index, end)
+ index += 1
+ return (-1, -1)
+
+ def startIdleProcessing(self):
+ """Initialize parameters needed for idle block spell checking.
+
+ This must be called before the first call to L{processIdleBlock}
+ or if you wish to restart the spell checking from the start
+ of the document. It initializes parameters needed by the
+ L{processIdleBlock} in order to process the document during idle
+ time.
+ """
+ self._spelling_last_idle_line = 0
+
+ def processIdleBlock(self):
+ """Process a block of lines during idle time.
+
+ This method is designed to be called during idle processing and will
+ spell check a small number of lines. The next idle processing event
+ will continue from where the previous call left off, and in this way
+ over some number of idle events will spell check the entire document.
+
+ Once the entire document is spell checked, a flag is set and
+ further calls to this method will immediately return. Calling
+ L{startIdleProcessing} will cause the idle processing to start
+ checking from the beginning of the document.
+ """
+ self.processDirtyRanges()
+ if self._spelling_last_idle_line < 0:
+ return
+ if self._spelling_debug:
+ print("Idle processing page starting at line %d" % self._spelling_last_idle_line)
+ self.checkLines(self._spelling_last_idle_line)
+ self._spelling_last_idle_line += self.stc.LinesOnScreen()
+ if self._spelling_last_idle_line > self.stc.GetLineCount():
+ self._spelling_last_idle_line = -1
+ return False
+ return True
+
+ def processCurrentlyVisibleBlock(self):
+ """Alternate method to check lines during idle time.
+
+ This method is designed to be called during idle processing and will
+ spell check the currently visible block of lines. Once the visible
+ block has been checked, repeatedly calling this method will have
+ no effect until the line position changes (or in the less frequent
+ occurrence when the number of lines on screen changes by resizing
+ the window).
+ """
+ self.processDirtyRanges()
+
+ self._spelling_last_idle_line = self.stc.GetFirstVisibleLine()
+ curr_block = self._spelling_last_idle_line + self.stc.LinesOnScreen()
+ if self._no_update or curr_block == self._last_block:
+ return
+
+ self.checkLines(self._spelling_last_idle_line)
+ self._spelling_last_idle_line += self.stc.LinesOnScreen()
+ self._last_block = self._spelling_last_idle_line
+ return True
+
+ def getSuggestions(self, word):
+ """Get suggestion for the correct spelling of a word.
+
+ @param word: word to check
+
+ @return: list of suggestions, or an empty list if any of the following
+ are true: there are no suggestions, the word is shorter than the
+ minimum length, or the dictionary can't be found.
+ """
+ spell = self._spelling_dict
+ if spell and len(word) >= self._spelling_word_size:
+ words = spell.suggest(word)
+ if self._spelling_debug:
+ print("suggestions for %s: %s" % (word, words))
+ return words
+ return []
+
+ def checkWord(self, pos=None, atend=False):
+ """Check the word at the current or specified position.
+
+ @param pos: position of a character in the word (or at the start or end
+ of the word), or None to use the current position
+ @param atend: True if you know the cursor is at the end of the word
+ """
+ if pos is None:
+ pos = self.stc.GetCurrentPos()
+ if atend:
+ end = pos
+ else:
+ end = self.stc.WordEndPosition(pos, True)
+ start = self.stc.WordStartPosition(pos, True)
+ if self._spelling_debug:
+ print("%d-%d: %s" % (start, end, self.stc.GetTextRange(start, end)))
+ self.checkRange(start, end)
+
+ def addDirtyRange(self, start, end, lines_added=0, deleted=False):
+ """Add a range of characters to a list of dirty regions that need to be
+ updated when some idle time is available.
+
+ """
+ count = end - start
+ if deleted:
+ count = -count
+ if start == self.current_dirty_end:
+ self.current_dirty_end = end
+ elif start >= self.current_dirty_start and start < self.current_dirty_end:
+ self.current_dirty_end += count
+ else:
+ ranges = []
+ if self.current_dirty_start >= 0:
+ ranges.append((self.current_dirty_start, self.current_dirty_end))
+ for range_start, range_end in self.dirty_ranges:
+ if start < range_start:
+ range_start += count
+ range_end += count
+ ranges.append((range_start, range_end))
+ self.dirty_ranges = ranges
+
+ self.current_dirty_start = start
+ self.current_dirty_end = end
+
+ # If there has been a change before the word that used to be under the
+ # cursor, move the pointer so it matches the text
+ if start < self.current_word_start:
+ self.current_word_start += count
+ self.current_word_end += count
+ elif start <= self.current_word_end:
+ self.current_word_end += count
+ # Prevent nonsensical word end if lots of text have been deleted
+ if self.current_word_end < self.current_word_start:
+ #print("word start = %d, word end = %d" % (self.current_word_start, self.current_word_end))
+ self.current_word_end = self.current_word_start
+
+ if lines_added > 0:
+ start = self.current_dirty_start
+ line = self.stc.LineFromPosition(start)
+ while True:
+ line_end = self.stc.GetLineEndPosition(line)
+ if line_end >= end:
+ #self.dirty_ranges.append((start, line_end))
+ if end > start:
+ self.current_dirty_start = start
+ self.current_dirty_end = end
+ else:
+ self.current_dirty_start = self.current_dirty_end = -1
+ break
+ self.dirty_ranges.append((start, line_end))
+ line += 1
+ start = self.stc.PositionFromLine(line)
+
+ if self._spelling_debug:
+ print("event: %d-%d, current dirty range: %d-%d, older=%s" % (start, end, self.current_dirty_start, self.current_dirty_end, self.dirty_ranges))
+
+ def clearDirtyRanges(self, ranges=None):
+ """Throw away all dirty ranges
+
+ """
+ self.current_dirty_start = self.current_dirty_end = -1
+ self.current_word_start = self.current_word_end = -1
+ if ranges is not None:
+ self.dirty_ranges = ranges
+ else:
+ self.dirty_ranges = []
+
+ def processDirtyRanges(self):
+ cursor = self.stc.GetCurrentPos()
+
+ # Check that the cursor has moved off the current word and if so check
+ # its spelling
+ if self.current_word_start > 0:
+ if cursor < self.current_word_start or cursor > self.current_word_end:
+ self.checkRange(self.current_word_start, self.current_word_end)
+ self.current_word_start = -1
+
+ # Check spelling around the region currently being typed
+ if self.current_dirty_start >= 0:
+ range_start, range_end = self.processDirtyRange(self.current_dirty_start, self.current_dirty_end)
+
+ # If the cursor is in the middle of a word, remove the spelling
+ # markers
+ if cursor >= range_start and cursor <= range_end:
+ word_start = self.stc.WordStartPosition(cursor, True)
+ word_end = self.stc.WordEndPosition(cursor, True)
+ mask = self._spelling_indicator_mask
+ self.stc.StartStyling(word_start, mask)
+ self.stc.SetStyling(word_end - word_start, 0)
+
+ if word_start != word_end:
+ self.current_word_start = word_start
+ self.current_word_end = word_end
+ else:
+ self.current_word_start = -1
+ self.current_dirty_start = self.current_dirty_end = -1
+
+ # Process a chunk of dirty ranges
+ needed = min(len(self.dirty_ranges), self.dirty_range_count_per_idle)
+ ranges = self.dirty_ranges[0:needed]
+ self.dirty_ranges = self.dirty_ranges[needed:]
+ for start, end in ranges:
+ if self._spelling_debug:
+ print("processing %d-%d" % (start, end))
+ self.processDirtyRange(start, end)
+
+ def processDirtyRange(self, start, end):
+ range_start = self.stc.WordStartPosition(start, True)
+ range_end = self.stc.WordEndPosition(end, True)
+ if self._spelling_debug:
+ print("processing dirty range %d-%d (modified from %d-%d): %s" % (range_start, range_end, start, end, repr(self.stc.GetTextRange(range_start, range_end))))
+ self.checkRange(range_start, range_end)
+ return range_start, range_end
+
+
+if __name__ == "__main__":
+ import sys
+ try:
+ import enchant
+ except:
+ print("pyenchant not available, so spelling correction won't work.")
+ print("Get pyenchant from http://pyenchant.sourceforge.net")
+
+ class TestSTC(wx.stc.StyledTextCtrl):
+ def __init__(self, *args, **kwargs):
+ wx.stc.StyledTextCtrl.__init__(self, *args, **kwargs)
+ self.spell = STCSpellCheck(self, language="en_US")
+ self.SetMarginType(0, wx.stc.STC_MARGIN_NUMBER)
+ self.SetMarginWidth(0, 32)
+ self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModified)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+ self.modified_count = 0
+ self.idle_count = 0
+
+ def OnModified(self, evt):
+ # NOTE: on really big insertions, evt.GetText can cause a
+ # MemoryError on MSW, so I've commented this dprint out.
+ mod = evt.GetModificationType()
+ if mod & wx.stc.STC_MOD_INSERTTEXT or mod & wx.stc.STC_MOD_DELETETEXT:
+ #print("(%s) at %d: text=%s len=%d" % (self.transModType(evt.GetModificationType()),evt.GetPosition(), repr(evt.GetText()), evt.GetLength()))
+ pos = evt.GetPosition()
+ last = pos + evt.GetLength()
+ self.spell.addDirtyRange(pos, last, evt.GetLinesAdded(), mod & wx.stc.STC_MOD_DELETETEXT)
+ #self.modified_count += 1
+ #if self.modified_count > 10:
+ # wx.CallAfter(self.spell.processDirtyRanges)
+ # self.modified_count = 0
+ evt.Skip()
+
+ def OnIdle(self, evt):
+ #print("Idle")
+ self.idle_count += 1
+ if self.idle_count > 10:
+ self.spell.processIdleBlock()
+ self.idle_count = 0
+
+ def transModType(self, modType):
+ st = ""
+ table = [(wx.stc.STC_MOD_INSERTTEXT, "InsertText"),
+ (wx.stc.STC_MOD_DELETETEXT, "DeleteText"),
+ (wx.stc.STC_MOD_CHANGESTYLE, "ChangeStyle"),
+ (wx.stc.STC_MOD_CHANGEFOLD, "ChangeFold"),
+ (wx.stc.STC_PERFORMED_USER, "UserFlag"),
+ (wx.stc.STC_PERFORMED_UNDO, "Undo"),
+ (wx.stc.STC_PERFORMED_REDO, "Redo"),
+ (wx.stc.STC_LASTSTEPINUNDOREDO, "Last-Undo/Redo"),
+ (wx.stc.STC_MOD_CHANGEMARKER, "ChangeMarker"),
+ (wx.stc.STC_MOD_BEFOREINSERT, "B4-Insert"),
+ (wx.stc.STC_MOD_BEFOREDELETE, "B4-Delete")
+ ]
+
+ for flag,text in table:
+ if flag & modType:
+ st = st + text + " "
+
+ if not st:
+ st = 'UNKNOWN'
+
+ return st
+
+ class Frame(wx.Frame):
+ def __init__(self, *args, **kwargs):
+ super(self.__class__, self).__init__(*args, **kwargs)
+
+ self.stc = TestSTC(self, -1)
+
+ self.CreateStatusBar()
+ menubar = wx.MenuBar()
+ self.SetMenuBar(menubar) # Adding the MenuBar to the Frame content.
+ menu = wx.Menu()
+ menubar.Append(menu, "File")
+ self.menuAdd(menu, "Open", "Open File", self.OnOpenFile)
+ self.menuAdd(menu, "Quit", "Exit the pragram", self.OnQuit)
+ menu = wx.Menu()
+ menubar.Append(menu, "Edit")
+ self.menuAdd(menu, "Check All", "Spell check the entire document", self.OnCheckAll)
+ self.menuAdd(menu, "Check Current Page", "Spell check the currently visible page", self.OnCheckPage)
+ self.menuAdd(menu, "Check Selection", "Spell check the selected region", self.OnCheckSelection)
+ menu.AppendSeparator()
+ self.menuAdd(menu, "Clear Spelling", "Remove spelling correction indicators", self.OnClearSpelling)
+ menu = wx.Menu()
+ menubar.Append(menu, "Language")
+ langs = self.stc.spell.getAvailableLanguages()
+ self.lang_id = {}
+ for lang in langs:
+ id = wx.NewId()
+ self.lang_id[id] = lang
+ self.menuAdd(menu, lang, "Change dictionary to %s" % lang, self.OnChangeLanguage, id=id)
+
+
+ def loadFile(self, filename):
+ fh = open(filename)
+ self.stc.SetText(fh.read())
+ self.stc.spell.clearDirtyRanges()
+ self.stc.spell.checkCurrentPage()
+
+ def loadSample(self, paragraphs=10):
+ lorem_ipsum = u"""\
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus mattis
+commodo sem. Phasellus scelerisque tellus id lorem. Nulla facilisi.
+Suspendisse potenti. Fusce velit odio, scelerisque vel, consequat nec,
+dapibus sit amet, tortor. Vivamus eu turpis. Nam eget dolor. Integer
+at elit. Praesent mauris. Nullam non nulla at nulla tincidunt malesuada.
+Phasellus id ante. Sed mauris. Integer volutpat nisi non diam. Etiam
+elementum. Pellentesque interdum justo eu risus. Cum sociis natoque
+penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc
+semper. In semper enim ut odio. Nulla varius leo commodo elit. Quisque
+condimentum, nisl eget elementum laoreet, mauris turpis elementum felis, ut
+accumsan nisl velit et mi.
+
+And some Russian: \u041f\u0438\u0442\u043e\u043d - \u043b\u0443\u0447\u0448\u0438\u0439 \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f!
+
+"""
+ self.stc.ClearAll()
+ for i in range(paragraphs):
+ self.stc.AppendText(lorem_ipsum)
+ # Call the spell check after the text has had a chance to be
+ # displayed and the window resized to the correct size.
+ self.stc.spell.clearDirtyRanges()
+ wx.CallAfter(self.stc.spell.checkCurrentPage)
+
+ def menuAdd(self, menu, name, desc, fcn, id=-1, kind=wx.ITEM_NORMAL):
+ if id == -1:
+ id = wx.NewId()
+ a = wx.MenuItem(menu, id, name, desc, kind)
+ menu.AppendItem(a)
+ wx.EVT_MENU(self, id, fcn)
+ menu.SetHelpString(id, desc)
+
+ def OnOpenFile(self, evt):
+ dlg = wx.FileDialog(self, "Choose a text file",
+ defaultDir = "",
+ defaultFile = "",
+ wildcard = "*")
+ if dlg.ShowModal() == wx.ID_OK:
+ print("Opening %s" % dlg.GetPath())
+ self.loadFile(dlg.GetPath())
+ dlg.Destroy()
+
+ def OnQuit(self, evt):
+ self.Close(True)
+
+ def OnCheckAll(self, evt):
+ self.stc.spell.checkAll()
+
+ def OnCheckPage(self, evt):
+ self.stc.spell.checkCurrentPage()
+
+ def OnCheckSelection(self, evt):
+ self.stc.spell.checkSelection()
+
+ def OnClearSpelling(self, evt):
+ self.stc.spell.clearAll()
+
+ def OnChangeLanguage(self, evt):
+ id = evt.GetId()
+ normalized = locale.normalize(self.lang_id[id])
+ try:
+ locale.setlocale(locale.LC_ALL, normalized)
+ print("Changing locale %s, dictionary set to %s" % (normalized, self.lang_id[id]))
+ except locale.Error:
+ print("Can't set python locale to %s; dictionary set to %s" % (normalized, self.lang_id[id]))
+ self.stc.spell.setLanguage(self.lang_id[id])
+ self.stc.spell.clearAll()
+ self.stc.spell.checkCurrentPage()
+
+ app = wx.App(False)
+ frame = Frame(None, size=(600, -1))
+ need_sample = True
+ if len(sys.argv) > 1:
+ if not sys.argv[-1].startswith("-"):
+ frame.loadFile(sys.argv[-1])
+ need_sample = False
+ if need_sample:
+ frame.loadSample()
+ if '-d' in sys.argv:
+ frame.stc.spell._spelling_debug = True
+ frame.Show()
+ app.MainLoop()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/vertedit.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/vertedit.py
new file mode 100644
index 0000000..3b35565
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/vertedit.py
@@ -0,0 +1,291 @@
+#!/usr/bin/env python2
+# -*- coding: latin1 -*-
+#
+# Created in 2008 by Don Quijote
+# Licence: wxWindows
+#
+# Updated 02/09/2011 Cody Precord
+
+#-----------------------------------------------------------------------------#
+
+import wx
+from wx import stc
+from collections import deque
+from functools import partial
+
+#-----------------------------------------------------------------------------#
+# Globals
+STATE_OFF = 0
+STATE_SELECTION = 1
+STATE_ACTIVE = 2
+
+#-----------------------------------------------------------------------------#
+
+class VertEdit(object):
+ """
+ Used instance variables:
+ - e STC Editor passed via class constructor
+ - enabled To deactivate this plugin after been loaded
+ - state 0: mode off, 1: mode just activated but still in dynamic line selection, 2: mode active, static block of lines
+ - stack Holds insertions and deletions, to replicate on all lines of the block
+ - oldCol Used by vertCaret() to remember last column of vertical caret
+ - markedLines Used by newMarkers() to remember highlighted lines
+ - orig Holds position of anchor when first switching from state 0 to state 1.
+ - origCol Holds column of anchor when first switching from state 0 to state 1.
+ - origLine Holds line of anchor when first switching from state 0 to state 1.
+ - gotDeletes An action caused STC to try to delete some text while in state 1.
+ - insCol Remembers column of cursor before STC deleted some text (see gotDeletes)
+ - delCol2 Remembers last column enclosing text to be deleted
+
+ """
+ INS = stc.STC_MOD_INSERTTEXT|stc.STC_PERFORMED_USER
+ DEL = stc.STC_MOD_DELETETEXT|stc.STC_PERFORMED_USER
+ BDEL = stc.STC_MOD_BEFOREDELETE|stc.STC_PERFORMED_USER
+
+ def __init__(self, editor,
+ blockBackColour="light blue",
+ markerNumber=1):
+ super(VertEdit, self).__init__()
+
+ # Attributes
+ self.e = editor
+ self.marker = markerNumber
+ self.enabled = False # Disable by default
+ self.state = STATE_OFF
+ self.stack = deque()
+ self.jitter = None
+ self.SetBlockColor(blockBackColour)
+ self.modmask = long(self.e.ModEventMask)
+
+ # Event Handlers
+# self.e.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+# self.e.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
+
+ def enable(self, enable=True):
+ """Enable the column edit mode"""
+ if not enable:
+ self.endMode()
+ self.enabled = enable
+
+ def disable(self):
+ """Disable the column edit mode"""
+ self.endMode()
+ self.enabled = False
+
+ @property
+ def Enabled(self):
+ """Is the column edit mode enabled"""
+ return self.enabled
+
+ def vertCaret(self, col=None, pos=None):
+ if col is None:
+ if pos is None:
+ pos = self.e.CurrentPos
+ col = self.e.GetColumn(pos)
+
+ if col != self.oldCol:
+ self.e.EdgeColumn = col
+ self.oldCol = col
+
+ def newMarkers(self, linesToMark=frozenset()):
+ # careful when STC collapses markers due to multiline deletion!
+ # for line in linesToMark.difference(self.markedLines):
+ for line in linesToMark:
+ self.e.MarkerAdd(line, self.marker)
+
+ for line in self.markedLines.difference(linesToMark):
+ self.e.MarkerDelete(line, self.marker)
+
+ self.markedLines = linesToMark
+
+ def OnKeyDown(self, evt):
+ if self.Enabled and self.state != STATE_OFF:
+ k = evt.GetKeyCode()
+ if k in (wx.WXK_ESCAPE, wx.WXK_LEFT, wx.WXK_NUMPAD_LEFT,
+ wx.WXK_RIGHT, wx.WXK_NUMPAD_RIGHT) and evt.Modifiers == 0:
+ if k == wx.WXK_ESCAPE:
+ self.endMode()
+ self.e.GotoPos(self.e.CurrentPos)
+ return
+ elif self.state == STATE_SELECTION:
+ self.e.Anchor = self.e.CurrentPos
+ evt.Skip()
+
+ def endMode(self):
+ if self.state != STATE_OFF:
+ self.e.SetModEventMask(self.modmask)
+ self.e.HideSelection(False)
+ self.state = STATE_OFF
+ self.e.EndUndoAction()
+ self.e.EdgeColumn, self.e.EdgeMode = self.edge
+ self.newMarkers()
+
+ def fn_ins(self, col, text, line):
+ colEnd = self.e.GetColumn(self.e.GetLineEndPosition(line))
+ if col > colEnd:
+ text = u" " * (col - colEnd) + text
+ col = colEnd
+
+ self.e.CurrentPos = pos = self.e.FindColumn(line, col)
+ self.e.AddText(text)
+ return col == self.e.GetColumn(pos)
+
+ def fn_del(self, col1, col2, line):
+ pos1 = self.e.FindColumn(line, col1)
+ pos2 = self.e.FindColumn(line, col2)
+ self.e.CurrentPos = pos1
+
+ if pos1 == pos2 or col2 != self.e.GetColumn(pos2):
+ return False
+
+ self.e.SetTargetStart(pos1)
+ self.e.SetTargetEnd(pos2)
+ self.e.ReplaceTarget(u'')
+ return True
+
+ def OnModified(self, evt):
+ if self.Enabled and self.state > STATE_OFF:
+ fn = None
+ if evt.ModificationType & VertEdit.INS == VertEdit.INS:
+ col = self.insCol or self.e.GetColumn(evt.Position)
+ fn = partial(self.fn_ins, col, evt.Text)
+ self.insCol = None
+ elif evt.ModificationType & VertEdit.DEL == VertEdit.DEL:
+ if self.state == STATE_ACTIVE:
+ fn = partial(self.fn_del, self.e.GetColumn(evt.Position), self.delCol2)
+ elif evt.ModificationType & VertEdit.BDEL == VertEdit.BDEL:
+ self.delCol2 = self.e.GetColumn(evt.Position + evt.Length)
+ if self.state == STATE_SELECTION and not self.gotDeletes:
+ self.gotDeletes = True
+ self.insCol = self.e.GetColumn(self.e.CurrentPos)
+
+ if fn:
+ if evt.LinesAdded:
+ self.endMode()
+ else:
+ self.stack.append(fn)
+
+ def SetBlockColor(self, color):
+ """Set the block background color used during the highlight
+ @param color: wxColor
+
+ """
+ self.e.MarkerDefine(self.marker,
+ stc.STC_MARK_BACKGROUND,
+ background=color)
+
+ def startMode(self, singleLine=False):
+ if self.state == STATE_OFF:
+ self.e.ModEventMask |= VertEdit.INS|VertEdit.DEL|VertEdit.BDEL
+ self.e.HideSelection(True)
+ orig = self.e.Anchor
+ self.origCol = self.e.GetColumn(orig)
+ self.origLine = self.e.LineFromPosition(orig)
+ self.stack.clear()
+ self.gotDeletes = False
+ self.e.BeginUndoAction()
+
+ # painting related
+ self.oldCol = -1
+ self.markedLines = frozenset()
+ self.edge = self.e.EdgeColumn, self.e.EdgeMode
+ self.e.EdgeMode = stc.STC_EDGE_LINE
+
+ self.state = STATE_SELECTION
+ self.insCol = None
+ self.curLine = self.e.LineFromPosition(self.e.CurrentPos)
+ self.lines = frozenset(range(min(self.origLine, self.curLine),
+ max(self.origLine, self.curLine) + 1))
+ self.jitter = None
+
+ if singleLine:
+ newA = self.e.PositionFromLine(self.curLine)
+ if newA == self.e.CurrentPos:
+ newA = self.e.GetLineEndPosition(self.curLine)
+ if newA == self.e.CurrentPos:
+ self.e.CurrentPos -= 1
+ newA += 1
+ self.e.Anchor = newA
+ self.jitter = newA
+
+ self.e.SetSelectionMode(stc.STC_SEL_LINES)
+
+ # painting related
+ self.vertCaret()
+ self.newMarkers(self.lines)
+
+ def OnUpdateUI(self, evt):
+ """Handle EVT_UPDATEUI"""
+ # Check if enabled
+ if not self.Enabled:
+ return
+
+ curP = self.e.CurrentPos
+ if self.state == STATE_OFF:
+ anchor = self.e.Anchor
+ selection = anchor != curP
+ sameCol = selection and self.e.GetColumn(curP) == self.e.GetColumn(anchor)
+ if sameCol:
+ self.startMode()
+ return
+
+ anchor = self.e.Anchor
+ selection = anchor != curP
+ sameCol = selection and self.e.GetColumn(curP) == self.origCol
+ linesOverride = None
+ if self.state == STATE_SELECTION:
+ if self.jitter == anchor and selection:
+ self.jitter = None
+ self.e.Anchor = anchor = self.e.FindColumn(self.origLine,self.origCol)
+ selection = anchor != curP
+
+ self.state = STATE_ACTIVE
+ if self.stack:
+ self.e.EndUndoAction()
+ self.e.Undo()
+ self.e.BeginUndoAction()
+ linesOverride = self.lines
+ self.newMarkers(self.lines)
+ curP = self.e.PositionFromLine(self.curLine)
+ elif sameCol:
+ self.startMode()
+ elif self.gotDeletes or selection:
+ if not self.gotDeletes:
+ self.e.Anchor = self.e.FindColumn(self.origLine, self.origCol)
+ self.endMode()
+ elif curP == self.e.FindColumn(self.origLine, self.origCol):
+ self.startMode(True)
+
+ if self.state == STATE_ACTIVE:
+ curI = self.e.LineFromPosition(curP)
+ if curP == self.e.GetLineEndPosition(curI):
+ self.e.GotoPos(curP)
+
+ if curI not in self.lines:
+ self.endMode()
+ else:
+ self.e.HideSelection(False)
+ curC = self.e.GetColumn(curP)
+ if self.stack:
+ self.state *= -1
+ lines = linesOverride or self.lines.difference((curI,))
+
+ cont = True
+ while(cont and self.stack):
+ fn = self.stack.popleft()
+ for line in lines:
+ if not fn(line):
+ self.e.EndUndoAction()
+ self.e.Undo()
+ self.e.BeginUndoAction()
+ cont = False
+ break
+
+ self.stack.clear()
+ self.e.EndUndoAction()
+ self.e.BeginUndoAction()
+ curC = self.e.GetColumn(self.e.CurrentPos)
+ self.e.GotoPos(self.e.FindColumn(curI, curC))
+ self.state *= -1
+
+ self.vertCaret(col = curC)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/generator.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/generator.py
new file mode 100644
index 0000000..70d3215
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/generator.py
@@ -0,0 +1,939 @@
+###############################################################################
+# Name: generator.py #
+# Purpose: Utility classes for creating various formatted plain text #
+# from the contents of a EdStc text buffer (i.e HTML, LaTeX, Rtf) #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides various methods and classes for generating code and transforming code
+to different formats such as html, latex, rtf with all the styling and formating
+intact from how the view is shown in the editor.
+
+It also provides a plugin interface that allows for plugins that wish to provide
+similar services for manipulating and transforming text.
+
+@summary: Editra's Generator interface and implementations
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: generator.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc
+import time
+
+# Editra Libraries
+import ed_glob
+import ed_menu
+from ed_style import StyleItem
+import util
+import plugin
+import ebmlib
+import eclib
+
+#--------------------------------------------------------------------------#
+# Globals
+_ = wx.GetTranslation
+
+FONT_FALLBACKS = "Trebuchet, Tahoma, sans-serif"
+
+#--------------------------------------------------------------------------#
+# Plugin Interface
+class GeneratorI(plugin.Interface):
+ """Plugins that are to be used for generating code/document need
+ to implement this interface.
+
+ """
+ def Generate(self, stc):
+ """Generates the code. The txt_ctrl parameter is a reference
+ to an ED_STC object (see ed_stc.py). The return value of this
+ function needs to be a 2 item tuple with the first item being
+ an associated file extension to use for setting highlighting
+ if available and the second item is the string of the new document.
+ @param stc: reference to an an stc defined in ed_stc.py
+ @see: L{ed_stc}
+
+ """
+ pass
+
+ def GetId(self):
+ """Must return the Id used for the generator objects
+ menu id. This is used to identify which Generator to
+ call on a menu event.
+ @return: menu id that identifies the implemented generator
+
+ """
+ pass
+
+ def GetMenuEntry(self, menu):
+ """Returns the MenuItem entry for this generator
+ @return: wx.MenuItem
+
+ """
+ pass
+
+#-----------------------------------------------------------------------------#
+
+class Generator(plugin.Plugin):
+ """Plugin Interface Extension Point for Generator
+ type plugin objects. Generator objects are used
+ to generate a document/code from one type to another.
+
+ """
+ observers = plugin.ExtensionPoint(GeneratorI)
+
+ def InstallMenu(self, menu):
+ """Appends the menu of available Generators onto
+ the given menu.
+ @param menu: menu to install entries into
+
+ """
+ # Fetch all the menu items for each generator object
+ menu_items = list()
+ for observer in self.observers:
+ try:
+ menu_i = observer.GetMenuEntry(menu)
+ if menu_i:
+ menu_items.append((menu_i.GetItemLabel(), menu_i))
+ except Exception, msg:
+ util.Log("[generator][err] %s" % str(msg))
+
+ # Construct the menu
+ menu_items.sort()
+ genmenu = ed_menu.EdMenu()
+ for item in menu_items:
+ genmenu.AppendItem(item[1])
+ menu.AppendMenu(ed_glob.ID_GENERATOR, _("Generator"), genmenu,
+ _("Generate Code and Documents"))
+
+ def GenerateText(self, e_id, txt_ctrl):
+ """Generates the new document text based on the given
+ generator id and contents of the given ED_STC text control.
+ @param e_id: event id originating from menu entry
+ @param txt_ctrl: EditraStc
+ @return: the generated text
+
+ """
+ gentext = None
+ start = time.time()
+ # Find the correct generator and run its generate method on the
+ # given text control.
+ for observer in self.observers:
+ if observer.GetId() == e_id:
+ gentext = observer.Generate(txt_ctrl)
+ util.Log("[generator][info] Generation time %f" % (time.time() - start))
+ return gentext
+
+#-----------------------------------------------------------------------------#
+
+class Html(plugin.Plugin):
+ """Transforms the text from a given Editra stc to a fully
+ styled html page. Inline CSS is generated and inserted into
+ the head of the Html to style the text regions by default
+ unless requested to generate a separate sheet.
+
+ """
+ plugin.Implements(GeneratorI)
+ def __init__(self, mgr):
+ """Creates the Html object from an Editra stc text control
+ @param mgr: This generators plugin manager
+
+ """
+ plugin.Plugin.__init__(self)
+
+ # Attributes
+ self._id = ed_glob.ID_HTML_GEN
+ self.stc = None
+ self.head = wx.EmptyString
+ self.css = dict()
+ self.body = wx.EmptyString
+
+ def __str__(self):
+ """Returns the string of html
+ @return: string version of html object
+
+ """
+ # Assemble the embedded html
+ style = "<style type=\"text/css\">\n%s</style>"
+ css = wx.EmptyString
+ for key in self.css:
+ css += str(self.css[key]) + "\n"
+ css = css % self.stc.GetFontDictionary()
+ style = style % css
+
+ # Insert the css into the head
+ head = self.head.replace('</head>', style + "\n</head>")
+
+ # Assemble the body of the html
+ html = "<html>\n%s\n%s\n</html>"
+ html = html % (head, self.body)
+ return html
+
+ def Unicode(self):
+ """Returns the html as Unicode
+ @return: Unicode string of html
+
+ """
+ return unicode(self.__str__())
+
+ def Generate(self, stc_ctrl):
+ """Generates and returns the document
+ @param stc_ctrl: text control to get text from
+
+ """
+ self.stc = stc_ctrl
+ self.head = self.GenerateHead()
+ self.body = self.GenerateBody()
+ return ("html", self.__str__())
+
+ def GenerateHead(self):
+ """Generates the html head block
+ @return: html header information
+
+ """
+ return "<head>\n<title>%s</title>\n" \
+ "<meta name=\"Generator\" content=\"Editra/%s\">\n" \
+ "<meta http-equiv=\"content-type\" content=\"text/html; " \
+ "charset=utf-8\">" \
+ "\n</head>" % (ebmlib.GetFileName(self.stc.GetFileName()),
+ ed_glob.VERSION)
+
+ def GenerateBody(self):
+ """Generates the body of the html from the stc's content. To do
+ this it does a character by character parse of the stc to determine
+ style regions and generate css and and styled spans of html in order
+ to generate an 'exact' html representation of the stc's window.
+ @return: the body section of the html generated from the text control
+
+ """
+ html = list()
+ parse_pos = 0
+ style_start = 0
+ style_end = 0
+ last_pos = self.stc.GetLineEndPosition(self.stc.GetLineCount()) + 1
+
+ # Get Document start point info
+ last_id = self.stc.GetStyleAt(parse_pos)
+ tag = self.stc.FindTagById(last_id)
+ if tag != wx.EmptyString:
+ s_item = StyleItem()
+ s_item.SetAttrFromStr(self.stc.GetStyleByName(tag))
+ self.css[tag] = CssItem(tag.split('_')[0], s_item)
+
+ # Optimizations
+ stc = self.stc
+ GetStyleAt = stc.GetStyleAt
+
+ # Build Html
+ while parse_pos < last_pos:
+ parse_pos += 1
+ curr_id = GetStyleAt(parse_pos)
+ style_end = parse_pos
+ # If style region has changed close section
+ if curr_id == 0 and GetStyleAt(parse_pos + 1) == last_id:
+ curr_id = last_id
+
+ if curr_id != last_id or parse_pos == last_pos:
+ tmp = stc.GetTextRange(style_start, style_end)
+ tmp = self.TransformText(tmp)
+ if tmp.isspace() or tag in ["default_style", "operator_style"]:
+ html.append(tmp)
+ else:
+ tmp2 = "<span class=\"%s\">%s</span>"
+ html.append(tmp2 % (tag.split('_')[0], tmp))
+
+ last_id = curr_id
+ style_start = style_end
+ tag = stc.FindTagById(last_id)
+ if tag not in self.css:
+ s_item = StyleItem()
+ s_item.SetAttrFromStr(stc.GetStyleByName(tag))
+ self.css[tag] = CssItem(tag.split('_')[0], s_item)
+
+ # Case for unstyled documents
+ if len(html) == 0:
+ s_item = StyleItem()
+ s_item.SetAttrFromStr(stc.GetStyleByName('default_style'))
+ self.css['default_style'] = CssItem('default', s_item)
+ html.append(self.TransformText(stc.GetText()))
+ else:
+ self.OptimizeCss()
+
+ return "<body class=\"default\">\n<pre>\n%s\n</pre>\n</body>" % \
+ "".join(html)
+
+ def GetId(self):
+ """Returns the menu identifier for the HTML generator
+ @return: id of this object
+
+ """
+ return self._id
+
+ def GetMenuEntry(self, menu):
+ """Returns the Menu control for the HTML generator
+ @return: menu entry for this generator
+
+ """
+ return wx.MenuItem(menu, self._id, _("Generate %s") % u"HTML",
+ _("Generate a %s version of the " \
+ "current document") % u"HTML")
+
+ def OptimizeCss(self):
+ """Optimizes the CSS Set
+ @postcondition: css is optimized to remove any redundant entries
+
+ """
+ # Must have the default style defined
+ if 'default_style' not in self.css:
+ return
+
+ # Don't style operators. This is to optimize the html size
+ if 'operator_style' in self.css:
+ self.css.pop('operator_style')
+
+ # All other css elements will inherit from the default
+ default = self.css['default_style']
+ for key in self.css:
+ if key == 'default_style':
+ continue
+ if default.GetFont() == self.css[key].GetFont():
+ self.css[key].SetFont(wx.EmptyString)
+ if default.GetFontSize() == self.css[key].GetFontSize():
+ self.css[key].SetFontSize(wx.EmptyString)
+ if default.GetBackground() == self.css[key].GetBackground():
+ self.css[key].SetBackground(wx.EmptyString)
+ if default.GetColor() == self.css[key].GetColor():
+ self.css[key].SetColor(wx.EmptyString)
+ for item in default.GetDecorators():
+ if item in self.css[key].GetDecorators():
+ self.css[key].RemoveDecorator(item)
+
+ def TransformText(self, text):
+ """Does character substitution on a string and returns
+ the html equivalent of the given string.
+ @param text: text to transform
+ @return: text with all special characters transformed
+
+ """
+ text = text.replace('&', "&amp;") # Ampersands
+ text = text.replace('<', "&lt;") # Less Than Symbols
+ text = text.replace('>', "&gt;") # Greater Than Symbols
+ text = text.replace("\"", "&quot;")
+ return text
+
+#-----------------------------------------------------------------------------#
+
+class CssItem:
+ """Converts an Editra StyleItem to a Css item for use in
+ generating html.
+
+ """
+ def __init__(self, class_tag, style_item):
+ """Initializes a Css object equivalent of an Editra StyleItem
+ @note: it is left up to the caller to do any string substitution
+ for font faces and size values as this class will construct the css
+ item as a mere reformation of StyleItem
+ @param class_tag: StyleItem tag name
+ @param style_item: ed_style.StyleItem
+ @see: L{ed_style}
+
+ """
+
+ # Attributes
+ self._tag = class_tag
+ self._back = style_item.GetBack()
+ self._fore = style_item.GetFore()
+ self._font = style_item.GetFace()
+ self._size = style_item.GetSize()
+
+ # List of additional style specs
+ self._decor = self.ExtractDecorators()
+ self._decor.extend(style_item.GetModifierList())
+
+ def __eq__(self, css2):
+ """Defines the == operator for the CssItem class
+ @param css2: CssItem to compare to
+ @return: whether the two items are equivalent
+
+ """
+ return self.__str__() == str(css2)
+
+ def __str__(self):
+ """Outputs the css item as a formatted css block
+ @return: CssItem as a string
+
+ """
+ # Generate the main style attributes
+ css = ".%s {\n%s}"
+ css_body = wx.EmptyString
+ if self._font != wx.EmptyString:
+ font = self._font.split(',')
+ css_body += u"\tfont-family: %s, %s;\n" % (font[0], FONT_FALLBACKS)
+ if self._size != wx.EmptyString:
+ size = self._size.split(',')
+ css_body += u"\tfont-size: %s;\n" % str(size[0])
+ if self._fore != wx.EmptyString:
+ fore = self._fore.split(',')
+ css_body += u"\tcolor: %s;\n" % fore[0]
+ if self._back != wx.EmptyString:
+ back = self._back.split(',')
+ css_body += u"\tbackground-color: %s;\n" % back[0]
+
+ # Add additional style modifiers
+ for item in self._decor:
+ if item == u'bold':
+ css_body += u"\tfont-weight: %s;\n" % item
+ elif item == u'italic':
+ css_body += u"\tfont-style: %s;\n" % item
+ elif item == u'underline':
+ css_body += u"\ttext-decoration: %s;\n" % item
+ else:
+ pass
+
+ # Format the tag and body into the css def
+ if css_body != wx.EmptyString:
+ return css % (self._tag, css_body)
+ else:
+ return css_body
+
+ def ExtractDecorators(self):
+ """Pulls additional style specs from the StyleItem such
+ as bold, italic, and underline styles.
+ @return: all decorators in the StyleItem (bold, underline, ect...)
+
+ """
+ decor = list()
+ for val in [ self._back, self._fore, self._font, self._size ]:
+ tmp = val.split(u',')
+ if len(tmp) < 2:
+ continue
+ else:
+ decor.append(tmp[1])
+ return decor
+
+ def GetBackground(self):
+ """Returns the Background value
+ @return: background color attribute
+
+ """
+ return self._back
+
+ def GetColor(self):
+ """Returns the Font/Fore Color
+ @return: foreground color attribute
+
+ """
+ return self._fore
+
+ def GetDecorators(self):
+ """Returns the list of decorators
+ @return: list of decorators item uses
+
+ """
+ return self._decor
+
+ def GetFont(self):
+ """Returns the Font Name
+ @return: font name attribute
+
+ """
+ return self._font
+
+ def GetFontSize(self):
+ """Returns the Font Size
+ @return: font size attribute
+
+ """
+ return self._size
+
+ def RemoveDecorator(self, item):
+ """Removes a specified decorator from the decorator set
+ @param item: decorator item to remove
+
+ """
+ if item in self._decor:
+ self._decor.remove(item)
+ else:
+ pass
+
+ def SetBackground(self, hex_str):
+ """Sets the Background Color
+ @param hex_str: hex color string to set background attribute with
+
+ """
+ self._back = hex_str
+
+ def SetColor(self, hex_str):
+ """Sets the Font/Fore Color
+ @param hex_str: hex color string to set foreground attribute with
+
+ """
+ self._fore = hex_str
+
+ def SetFont(self, font_face):
+ """Sets the Font Face
+ @param font_face: font face name to set font attribute with
+
+ """
+ self._font = font_face
+
+ def SetFontSize(self, size_str):
+ """Sets the Font Point Size
+ @param size_str: point size to use for font in style
+
+ """
+ self._size = size_str
+
+#-----------------------------------------------------------------------------#
+
+class LaTeX(plugin.Plugin):
+ """Creates a LaTeX document object from the contents of the
+ supplied document reference.
+ @todo: performance improvements and wordwrap in generated document
+
+ """
+ plugin.Implements(GeneratorI)
+ def __init__(self, plgmgr):
+ """Initializes the LaTeX object
+ @param plgmgr: pluginmanger for this object
+
+ """
+ plugin.Plugin.__init__(self)
+
+ # Attributes
+ self._stc = None
+ self._id = ed_glob.ID_TEX_GEN
+ self._dstyle = StyleItem()
+ self._cmds = dict()
+
+ def CreateCmdName(self, name):
+ """Creates and returns a proper cmd name
+ @param name: name to construct command from
+ @return: latex formated command string
+
+ """
+ name = name.replace('_', '')
+ tmp = list()
+ alpha = "ABCDEFGHIJ"
+ for char in name:
+ if char.isdigit():
+ tmp.append(alpha[int(char)])
+ else:
+ tmp.append(char)
+ return "".join(tmp)
+
+ def GenDoc(self):
+ """Generates the document body of the LaTeX document
+ @returns: the main body of the reference document marked up with latex
+
+ """
+ tex = list()
+ tmp = u''
+ start = parse_pos = 0
+ last_pos = self._stc.GetLineEndPosition(self._stc.GetLineCount())
+
+ # Define the default style
+ self.RegisterStyleCmd('default_style', \
+ self._stc.GetItemByName('default_style'))
+
+ # Get Document start point info
+ last_id = self._stc.GetStyleAt(parse_pos)
+ tmp = self.TransformText(self._stc.GetTextRange(parse_pos,
+ parse_pos + 1))
+ tag = self._stc.FindTagById(last_id)
+ if tag != wx.EmptyString:
+ self.RegisterStyleCmd(tag, self._stc.GetItemByName(tag))
+
+ # Optimizations
+ stc = self._stc
+ GetStyleAt = stc.GetStyleAt
+ GetTextRange = stc.GetTextRange
+ TransformText = self.TransformText
+
+ # Build LaTeX
+ for parse_pos in xrange(last_pos + 1):
+ curr_id = GetStyleAt(parse_pos)
+ if parse_pos > 1:
+ # This is the performance bottleneck, changing the text
+ # collection to when the style changes is much faster as
+ # it only needs to be done once per style section instead
+ # of once per character. Doing that however causes problems
+ # with the style and resulting document formatting.
+ tmp = TransformText(GetTextRange((parse_pos - 1), parse_pos))
+
+ if curr_id == 0 and GetStyleAt(parse_pos + 1) == last_id:
+ curr_id = last_id
+
+ # If style region has changed close section
+ if curr_id != last_id or tmp[-1] == "\n":
+ tmp_tex = TransformText(GetTextRange(start, parse_pos))
+# tmp_tex = u"".join(tmp)
+ if tag == "operator_style" or \
+ (tag == "default_style" and \
+ tmp_tex.isspace() and len(tmp_tex) <= 2):
+ tex.append(tmp_tex)
+ else:
+ if "\\\\\n" in tmp_tex:
+ tmp_tex = tmp_tex.replace("\\\\\n", "")
+ tmp2 = "\\%s{%s}\\\\\n"
+ else:
+ tmp2 = "\\%s{%s}"
+
+ cmd = self.CreateCmdName(tag)
+ if cmd in [None, wx.EmptyString]:
+ cmd = "defaultstyle"
+ tex.append(tmp2 % (cmd, tmp_tex))
+
+ last_id = curr_id
+ tag = stc.FindTagById(last_id)
+ if tag not in [None, wx.EmptyString]:
+ self.RegisterStyleCmd(tag, stc.GetItemByName(tag))
+ tmp = list()
+ start = parse_pos
+
+ # Case for unstyled documents
+ if tex == wx.EmptyString:
+ tex.append(self.TransformText(stc.GetText()))
+ return "\\begin{document}\n%s\n\\end{document}" % "".join(tex)
+
+ def Generate(self, stc_doc):
+ """Generates the LaTeX document
+ @param stc_doc: text control to generate latex from
+ @return: the reference document marked up in LaTeX.
+
+ """
+ self._stc = stc_doc
+ default_si = self._stc.GetItemByName('default_style')
+ self._dstyle.SetBack(default_si.GetBack().split(',')[0])
+ self._dstyle.SetFore(default_si.GetFore().split(',')[0])
+ self._dstyle.SetFace(default_si.GetFace().split(',')[0])
+ self._dstyle.SetSize(default_si.GetSize().split(',')[0])
+ body = self.GenDoc()
+ preamble = self.GenPreamble()
+ return ("tex", u"".join([preamble, body]))
+
+ def GenPreamble(self):
+ """Generates the Preamble of the document
+ @return: the LaTeX document preamble
+
+ """
+ # Preamble template
+ pre = ("%% \iffalse meta-comment\n"
+ "%%\n%% Generated by Editra %s\n"
+ "%% This is generator is Very Experimental.\n"
+ "%% The code should compile in most cases but there may\n"
+ "%% be some display issues when rendered.\n"
+ "%%\n%%\n\n"
+ "\\documentclass[11pt, a4paper]{article}\n"
+ "\\usepackage[a4paper, margin=2cm]{geometry}\n"
+ "\\usepackage[T1]{fontenc}\n"
+# "\\usepackage{ucs}\n"
+# "\\usepackage[utf8]{inputenc}\n"
+ "\\usepackage{color}\n"
+ "\\usepackage{alltt}\n"
+ "\\usepackage{times}\n") % ed_glob.VERSION
+
+ # Set the background color
+ pre += ("\\pagecolor[rgb]{%s}\n" % \
+ self.HexToRGB(self._dstyle.GetBack()))
+ pre += "\\parindent=0in\n\n"
+
+ # Insert all styling commands
+ pre += "%% Begin Styling Command Definitions"
+ for cmd in self._cmds:
+ pre += ("\n" + self._cmds[cmd])
+ pre += "\n%% End Styling Command Definitions\n\n"
+ return pre
+
+ def GetId(self):
+ """Returns the menu identifier for the LaTeX generator
+ @return: id of that identifies this generator
+
+ """
+ return self._id
+
+ def GetMenuEntry(self, menu):
+ """Returns the Menu control for the LaTeX generator
+ @param menu: menu to create MenuItem for
+
+ """
+ return wx.MenuItem(menu, self._id, _("Generate %s") % u"LaTeX",
+ _("Generate an %s version of the " \
+ "current document") % u"LaTeX")
+
+ def HexToRGB(self, hex_str):
+ """Returns a comma separated rgb string representation
+ of the input hex string. 1.0 = White, 0.0 = Black.
+ @param hex_str: hex string to convert to latex rgb format
+
+ """
+ r_hex = hex_str
+ if r_hex[0] == u"#":
+ r_hex = r_hex[1:]
+ ldiff = 6 - len(r_hex)
+ r_hex += ldiff * u"0"
+ # Convert hex values to integer
+ red = round(float(float(int(r_hex[0:2], 16)) / 255), 2)
+ green = round(float(float(int(r_hex[2:4], 16)) / 255), 2)
+ blue = round(float(float(int(r_hex[4:], 16)) / 255), 2)
+ return "%s,%s,%s" % (str(red), str(green), str(blue))
+
+ def RegisterStyleCmd(self, cmd_name, s_item):
+ """Registers and generates a command from the
+ supplied StyleItem.
+ @param cmd_name: name of command
+ @param s_item: style item to create command for
+ @postcondition: new styling command is created and registered for use
+
+ """
+ cmd_name = self.CreateCmdName(cmd_name)
+
+ # If we already made a command for this style return
+ if cmd_name in self._cmds:
+ return
+
+ # Templates
+ uline_tmp = u"\\underline{%s}"
+ ital_tmp = u"\\emph{%s}"
+ bold_tmp = u"\\textbf{%s}"
+ fore_tmp = u"\\textcolor[rgb]{%s}{%s}"
+ back_tmp = u"\\colorbox[rgb]{%s}{#1}"
+ cmd_tmp = u"\\newcommand{%s}[1]{%s}"
+
+ # Get Style Attributes
+ fore = s_item.GetFore()
+ if fore == wx.EmptyString:
+ fore = self._dstyle.GetFore()
+ back = s_item.GetBack()
+ if back == wx.EmptyString:
+ back = self._dstyle.GetBack()
+ face = s_item.GetFace()
+ if face == wx.EmptyString:
+ face = self._dstyle.GetFace()
+ size = s_item.GetSize()
+ if size == wx.EmptyString:
+ size = self._dstyle.GetSize()
+
+ back = back_tmp % self.HexToRGB(back.split(u',')[0])
+ fore = fore_tmp % (self.HexToRGB(fore.split(u',')[0]), back)
+ if u"bold" in unicode(s_item):
+ fore = bold_tmp % fore
+ if u"underline" in unicode(s_item):
+ fore = uline_tmp % fore
+ if u"italic" in unicode(s_item):
+ fore = ital_tmp % fore
+ cmd = cmd_tmp % ((u"\\" + cmd_name), u"\\texttt{\\ttfamily{%s}}" % fore)
+ self._cmds[cmd_name] = cmd
+
+ def TransformText(self, txt):
+ """Transforms the given text into LaTeX format, by
+ escaping all special characters and sequences.
+ @param txt: text to transform
+ @return: txt with all special characters transformed
+
+ """
+ ch_map = { "#" : "\\#", "$" : "\\$", "^" : "\\^",
+ "%" : "\\%", "&" : "\\&", "_" : "\\_",
+ "{" : "\\{", "}" : "\\}", "~" : "\\~",
+ "\\": "$\\backslash$", "\n" : "\\\\\n",
+ "@" : "$@$", "<" : "$<$", ">" : "$>$",
+ "-" : "$-$", "|" : "$|$"
+ }
+ tmp = list()
+ for char in txt:
+ tmp.append(ch_map.get(char, char))
+ return u''.join(tmp)
+
+#-----------------------------------------------------------------------------#
+
+class Rtf(plugin.Plugin):
+ """Generates a fully styled RTF document from the given text
+ controls contents.
+ @todo: add support for bold/italic/underline and multiple fonts
+
+ """
+ plugin.Implements(GeneratorI)
+ def __init__(self, mgr):
+ """Initializes and declares the attribute values for
+ this generator.
+ @param mgr: plugin manager of this object
+
+ """
+ plugin.Plugin.__init__(self)
+
+ # Attributes
+ self._stc = None
+ self._id = ed_glob.ID_RTF_GEN
+ self._colortbl = RtfColorTbl()
+
+ def __str__(self):
+ """Returns the RTF object as a string
+ @return: rtf object as a string
+
+ """
+ return self._GenRtf()
+
+ #---- Protected Member Functions ----#
+ def _GenRtf(self):
+ """Generates the RTF equivalent of the displayed text in the current
+ stc document window.
+ @precondition: self._stc must have been set by a call to Generate
+ @return: generated rtf marked up text
+
+ """
+ # Buffer hasn't been set
+ if self._stc is None:
+ return u''
+
+ # Optimizations
+ stc = self._stc
+ def_fore = stc.GetDefaultForeColour(as_hex=True)
+ self._colortbl.AddColor(def_fore)
+ def_back = stc.GetDefaultBackColour(as_hex=True)
+ self._colortbl.AddColor(def_back)
+ last_pos = stc.GetLineEndPosition(stc.GetLineCount())
+ parse_pos = 0
+ last_id = None
+ last_fore = None
+ last_back = None
+ start = end = 0
+ tmp_txt = list()
+ font_tmp = "\\f0"
+ fore_tmp = "\\cf%d"
+ back_tmp = "\\cb%d"
+ AddColor = self._colortbl.AddColor
+ GetColorIndex = self._colortbl.GetColorIndex
+ GetStyleAt = stc.GetStyleAt
+
+ # Parse all characters/style bytes in document
+ for parse_pos in xrange(last_pos + 1):
+ sty_id = GetStyleAt(parse_pos)
+ end = parse_pos
+
+ # If style has changed build the previous section
+ if sty_id != last_id:
+ tag = stc.FindTagById(last_id)
+ s_item = stc.GetItemByName(tag)
+ AddColor(s_item.GetFore())
+ AddColor(s_item.GetBack())
+ tplate = font_tmp
+ fid = GetColorIndex(s_item.GetFore())
+ if fid != last_fore:
+ last_fore = fid
+ tplate = tplate + (fore_tmp % fid)
+ bid = GetColorIndex(s_item.GetBack())
+ if bid != last_back:
+ last_back = bid
+ tplate = tplate + (back_tmp % bid)
+ tmp_txt.append(tplate + " " + \
+ self.TransformText(stc.GetTextRange(start, end)))
+ start = end
+ last_id = sty_id
+
+ head = "{\\rtf1\\ansi\\deff0{\\fonttbl{\\f0 %s;}}" % \
+ stc.GetDefaultFont().GetFaceName()
+ return u"%s%s%s}" % (head, self._colortbl, "".join(tmp_txt))
+
+ #---- End Protected Member Functions ----#
+
+ def Generate(self, stc_doc):
+ """Implements the GeneratorI's Generator Function by
+ returning the RTF equivalent of the given stc_doc
+ @param stc_doc: document to generate text from
+ @return: document marked up in rtf
+
+ """
+ self._stc = stc_doc
+ return ('rtf', self._GenRtf())
+
+ def GetId(self):
+ """Implements the GeneratorI's GetId function by returning
+ the identifier for this generator.
+ @return: identifier for this generator
+
+ """
+ return self._id
+
+ def GetMenuEntry(self, menu):
+ """Implements the GeneratorI's GetMenuEntry function by
+ returning the MenuItem to associate with this object.
+ @return: menu entry item for this generator
+
+ """
+ return wx.MenuItem(menu, self._id, _("Generate %s") % u"RTF",
+ _("Generate a %s version of the " \
+ "current document") % u"RTF")
+
+ def TransformText(self, text):
+ """Transforms the given text by converting it to RTF format
+ @param text: text to transform
+ @return: text with all special characters transformed
+ """
+ chmap = { "\t" : "\\tab ", "{" : "\\{", "}" : "\\}",
+ "\\" : "\\\\", "\n" : "\\par\n", "\r" : "\\par\n"}
+ text = text.replace('\r\n', '\n')
+ tmp = u''
+ for char in text:
+ tmp = tmp + chmap.get(char, char)
+ return tmp
+
+#-----------------------------------------------------------------------------#
+
+class RtfColorTbl:
+ """A storage class to help with generating the color table for
+ the Rtf Generator Class.
+ @see: Rtf
+
+ """
+ def __init__(self):
+ """Initialize the color table
+ @summary: creates an object for managing an rtf documents color table
+
+ """
+ # Attributes
+ self._index = list() # manages the order of the tables keys
+ self._tbl = dict() # map of style item color vals to rtf defs
+
+ def __str__(self):
+ """Returns the string representation of the table
+ @return: rtf color table object as an rtf formatted string
+
+ """
+ rstr = u''
+ for item in self._index:
+ rstr = rstr + self._tbl[item]
+ return u"{\\colortbl%s}" % rstr
+
+ def AddColor(self, si_color):
+ """Takes a style item and adds it to the table if
+ has not already been defined in the table.
+ @param si_color: hex color string
+
+ """
+ if si_color not in self._index:
+ rgb = eclib.HexToRGB(si_color.split(u',')[0])
+ color = "\\red%d\\green%d\\blue%d;" % tuple(rgb)
+ self._index.append(si_color)
+ self._tbl[si_color] = color
+ else:
+ pass
+
+ def GetColorIndex(self, si_color):
+ """Gets the index of a particular style items color
+ definition from the color table. Returns -1 if item is
+ not found.
+ @param si_color: style item color to find index in table for
+ @return: the colors index in the table
+
+ """
+ if si_color in self._index:
+ return self._index.index(si_color)
+ else:
+ return -1
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/iface.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/iface.py
new file mode 100644
index 0000000..0e8b59a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/iface.py
@@ -0,0 +1,170 @@
+###############################################################################
+# Name: iface.py #
+# Purpose: Plugin interface definitions #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This module contains numerous plugin interfaces and the Extension points that
+they extend. Included below is a list of interfaces available in this module.
+
+Intefaces:
+ - ShelfI: Interface into the L{Shelf}
+ - MainWindowI: Interface into L{ed_main.MainWindow}
+ - AutoCompI: Interface for adding autocompletion helpers
+
+@summary: Main Plugin interface defintions
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: iface.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import wx
+
+# Local Imports
+import plugin
+
+#--------------------------------------------------------------------------#
+
+class AutoCompI(plugin.Interface):
+ """The Autocompletion interface.
+
+ """
+ def GetCompleter(self, buff):
+ """Get the completer object implemented by this plugin
+ @param buff: EditraStc instance
+ @return: instance of autocomp.BaseCompleter
+
+ """
+ raise NotImplementedError
+
+ def GetFileTypeId(self):
+ """Get the filetype this completer is associated with
+ @return: int
+
+ """
+ return 0
+
+#--------------------------------------------------------------------------#
+
+class MainWindowI(plugin.Interface):
+ """The MainWindow Interface is intended as a simple general purpose
+ interface for adding functionality to the main window. It does little
+ managing of how objects that implement it are handled, most is left up to
+ the plugin. Some examples of plugins using this interface are the
+ FileBrowser and Calculator plugins.
+
+ """
+ def PlugIt(self, window):
+ """This method is called once and only once per window when it is
+ created. It should typically be used to register menu entries,
+ bind event handlers and other similar actions.
+ @param window: The parent window of the plugin
+ @postcondition: The plugins controls are installed in the L{MainWindow}
+
+ """
+ raise NotImplementedError
+
+ def GetMenuHandlers(self):
+ """Get menu event handlers/id pairs. This function should return a
+ list of tuples containing menu ids and their handlers. The handlers
+ should be not be a member of this class but a member of the ui component
+ that they handler acts upon.
+ @return: list [(ID_FOO, foo.OnFoo), (ID_BAR, bar.OnBar)]
+
+ """
+ pass
+
+ def GetUIHandlers(self):
+ """Get update ui event handlers/id pairs. This function should return a
+ list of tuples containing object ids and their handlers. The handlers
+ should be not be a member of this class but a member of the ui component
+ that they handler acts upon.
+ @return: list [(ID_FOO, foo.OnFoo), (ID_BAR, bar.OnBar)]
+
+ """
+ pass
+
+#-----------------------------------------------------------------------------#
+
+class ShelfI(plugin.Interface):
+ """Interface into the L{Shelf}. All plugins wanting to be
+ placed on the L{Shelf} should implement this interface.
+
+ """
+ def AllowMultiple(self):
+ """This method is used to check if multiple instances of this
+ item are allowed to be open at one time.
+ @return: True/False
+
+ """
+ return True
+
+ def CreateItem(self, parent):
+ """This is them method used to open the item in the L{Shelf}
+ It should return an object that is a Panel or subclass of a Panel.
+ @param parent: The would be parent window of this panel
+ @return: wx.Panel
+
+ """
+ raise NotImplementedError
+
+ def GetBitmap(self):
+ """Get the bitmap to show in the shelf for this item
+ @return: wx.Bitmap
+ @note: this method is optional
+
+ """
+ return wx.NullBitmap
+
+ def GetId(self):
+ """Return the id that identifies this item (same as the menuid)
+ @return: Item ID
+
+ """
+ raise NotImplementedError
+
+ def GetMenuEntry(self, menu):
+ """Returns the menu entry associated with this item
+ @param menu: The menu this entry will be added to
+ @return: wx.MenuItem or None if no menu entry is needed
+
+ """
+ raise NotImplementedError
+
+ def GetName(self):
+ """Return the name of this shelf item. This should be the
+ same as the MenuEntry's label.
+ @return: name of item
+
+ """
+ raise NotImplementedError
+
+ def InstallComponents(self, mainw):
+ """Called by the Shelf when the plugin is created to allow it
+ to install any extra components that it may have that fall outside
+ the normal interface. This method is optional and does not need
+ to be implemented if it is not needed.
+ @param mainw: MainWindow Instance
+
+ """
+ pass
+
+ def IsStockable(self):
+ """Return whether this item type is stockable. The shelf saves
+ what pages it had open the last time the program was run and then
+ reloads the pages the next time the program starts. If this
+ item can be reloaded between sessions return True otherwise return
+ False.
+ @return: bool
+
+ """
+ return True
+
+#-----------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/info.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/info.py
new file mode 100644
index 0000000..6b4a60d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/info.py
@@ -0,0 +1,22 @@
+###############################################################################
+# Name: info.py #
+# Purpose: Global project information #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""Editra Project information module"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: info.py 73347 2013-01-05 19:58:31Z CJP $"
+__revision__ = "$Revision: 73347 $"
+
+#-----------------------------------------------------------------------------#
+
+AUTHOR = 'Cody Precord'
+VERSION = '0.7.20'
+PROG_NAME = 'Editra'
+HOME_PAGE = "http://editra.org"
+I18N_PAGE = "https://translations.launchpad.net/editra/trunk/+pots/editra"
+CONTACT_MAIL = "staff@editra.org"
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/perspective.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/perspective.py
new file mode 100644
index 0000000..b0bc606
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/perspective.py
@@ -0,0 +1,414 @@
+###############################################################################
+# Name: perspectives.py #
+# Purpose: Editra's view management service #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides a perspective management class for saving and loading custom
+perspectives in the MainWindow.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: perspective.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import os
+import wx
+import wx.aui as aui
+
+# Editra Imports
+import util
+import ed_menu
+import ed_fmgr
+from profiler import Profile_Get, Profile_Set
+
+#--------------------------------------------------------------------------#
+# Globals
+AUTO_PERSPECTIVE = u'Automatic'
+DATA_FILE = u'perspectives'
+LAST_KEY = u'**LASTVIEW**'
+
+# ID's
+ID_SAVE_PERSPECTIVE = wx.NewId()
+ID_DELETE_PERSPECTIVE = wx.NewId()
+ID_AUTO_PERSPECTIVE = wx.NewId()
+
+# Aliases
+_ = wx.GetTranslation
+#--------------------------------------------------------------------------#
+
+class PerspectiveManager(object):
+ """Creates a perspective manager for the given aui managed window.
+ It supports saving and loading of on disk perspectives as created by
+ calling SavePerspective from the AuiManager. Mixin class for a wx.Frame.
+
+ """
+ def __init__(self, base):
+ """Initializes the perspective manager. The auimgr parameter is
+ a reference to the windows AuiManager instance, base is the base
+ path to where perspectives should be loaded from and saved to.
+ @param base: path to configuration cache
+
+ """
+ super(PerspectiveManager, self).__init__()
+
+ hint = aui.AUI_MGR_TRANSPARENT_HINT
+ if wx.Platform == '__WXGTK__':
+ # Use venetian blinds style as transparent can cause crashes
+ # on linux when desktop compositing is used.
+ hint = aui.AUI_MGR_VENETIAN_BLINDS_HINT
+
+ self._mgr = ed_fmgr.EdFrameManager(flags=aui.AUI_MGR_DEFAULT |
+ aui.AUI_MGR_TRANSPARENT_DRAG |
+ hint |
+ aui.AUI_MGR_ALLOW_ACTIVE_PANE)
+ self._mgr.SetManagedWindow(self)
+
+ # Attributes
+ self._ids = list() # List of menu ids
+ self._base = os.path.join(base, DATA_FILE) # Path to config
+ self._viewset = dict() # Set of Views
+ self.LoadPerspectives()
+ self._menu = ed_menu.EdMenu() # Control menu
+ self._currview = Profile_Get('DEFAULT_VIEW') # Currently used view
+
+ # Setup Menu
+ self._menu.Append(ID_SAVE_PERSPECTIVE, _("Save Current View"),
+ _("Save the current window layout"))
+ self._menu.Append(ID_DELETE_PERSPECTIVE, _("Delete Saved View"))
+ self._menu.AppendSeparator()
+ self._menu.Append(ID_AUTO_PERSPECTIVE, _("Automatic"),
+ _("Automatically save/use window state from last session"),
+ wx.ITEM_CHECK)
+ self._menu.AppendSeparator()
+ for name in self._viewset:
+ self.AddPerspectiveMenuEntry(name)
+
+ # Restore the managed windows previous position preference if available.
+ pos = Profile_Get('WPOS', "size_tuple", False)
+ if Profile_Get('SET_WPOS') and pos:
+ # Ensure window is on screen
+ if not self.IsPositionOnScreen(pos):
+ pos = self.GetPrimaryDisplayOrigin()
+ self.SetPosition(pos)
+
+ # Event Handlers
+ self.Bind(wx.EVT_MENU, self.OnPerspectiveMenu)
+
+ #---- Properties ----#
+ PanelMgr = property(lambda self: self._mgr)
+
+ def AddPerspective(self, name, p_data=None):
+ """Add a perspective to the view set. If the p_data parameter
+ is not set then the current view will be added with the given name.
+ @param name: name for new perspective
+ @keyword p_data: perspective data from auimgr
+ @return: bool (True == Added, False == Not Added)
+
+ """
+ # Don't allow empty keys or ones that override the automatic
+ # settings to be added
+ name = name.strip()
+ if not len(name) or name == AUTO_PERSPECTIVE:
+ return False
+
+ domenu = not self.HasPerspective(name)
+ if p_data is None:
+ self._viewset[name] = self._mgr.SavePerspective()
+ else:
+ self._viewset[name] = p_data
+ self._currview = name
+
+ if name != AUTO_PERSPECTIVE and domenu:
+ self.AddPerspectiveMenuEntry(name)
+
+ self.SavePerspectives()
+ return True
+
+ def AddPerspectiveMenuEntry(self, name):
+ """Adds an entry to list of perspectives in the menu for this manager.
+ @param name: name of perspective to add to menu
+ @return: bool (added or not)
+
+ """
+ name = name.strip()
+ if not len(name) or name == AUTO_PERSPECTIVE:
+ return False
+
+ per_id = wx.NewId()
+ self._ids.append(per_id)
+ self._menu.InsertAlpha(per_id, name, _("Change view to \"%s\"") % name,
+ kind=wx.ITEM_CHECK, after=ID_AUTO_PERSPECTIVE)
+ return True
+
+ def GetFrameManager(self):
+ """Returns the manager for this frame
+ @return: Reference to the AuiMgr of this window
+
+ """
+ return self._mgr
+
+ def GetPerspectiveControls(self):
+ """Returns the control menu for the manager
+ @return: menu of this manager
+
+ """
+ return self._menu
+
+ def GetPerspective(self):
+ """Returns the name of the current perspective used
+ @return: name of currently active perspective
+
+ """
+ return self._currview
+
+ def GetPerspectiveData(self, name):
+ """Returns the given named perspectives data string
+ @param name: name of perspective to fetch data from
+
+ """
+ return self._viewset.get(name, None)
+
+ def GetPersectiveHandlers(self):
+ """Gets a list of ID to UIHandlers for the perspective Menu
+ @return: list of [(ID, HandlerFunction)]
+
+ """
+ handlers = [(m_id, self.OnUpdatePerspectiveMenu) for m_id in self._ids]
+ return handlers + [(ID_AUTO_PERSPECTIVE, self.OnUpdatePerspectiveMenu)]
+
+ def GetPerspectiveList(self):
+ """Returns a list of all the loaded perspectives. The
+ returned list only provides the names of the perspectives
+ and not the actual data.
+ @return: list of all managed perspectives
+
+ """
+ return sorted(self._viewset.keys())
+
+ def GetPrimaryDisplayOrigin(self):
+ """Get the origin on the primary display to use as a default
+ window placement position.
+ @return: position tuple
+
+ """
+ # NOTE: don't default to 0,0 otherwise on osx the frame will be
+ # stuck behind the menubar.
+ for idx in range(wx.Display.GetCount()):
+ disp = wx.Display(idx)
+ if disp.IsPrimary():
+ drect = disp.GetClientArea()
+ return drect.GetPosition() + (5, 5)
+ else:
+ return (5, 5)
+
+ def HasPerspective(self, name):
+ """Returns True if there is a perspective by the given name
+ being managed by this manager, or False otherwise.
+ @param name: name of perspective to look for
+ @return: whether perspective is managed by this manager or not
+
+ """
+ return name in self._viewset
+
+ def InitWindowAlpha(self):
+ """Initialize the windows alpha setting"""
+ level = max(100, Profile_Get('ALPHA', default=255))
+ # Only set the transparency if it is not opaque
+ if level != 255:
+ self.SetTransparent(level)
+
+ def IsPositionOnScreen(self, pos):
+ """Check if the given position is on any of the connected displays
+ @param pos: Position Tuple
+ @return: bool
+
+ """
+ bOnScreen = False
+ if len(pos) == 2:
+ for idx in range(wx.Display.GetCount()):
+ disp = wx.Display(idx)
+ drect = disp.GetClientArea()
+ bOnScreen = drect.Contains(pos)
+ if bOnScreen:
+ break
+ return bOnScreen
+
+ def LoadPerspectives(self):
+ """Loads the perspectives data into the manager. Returns
+ the number of perspectives that were successfully loaded.
+ @return: number of perspectives loaded
+
+ """
+ reader = util.GetFileReader(self._base)
+ if reader == -1:
+ util.Log("[perspective][err] Failed to get " +
+ "file reader for %s" % self._base)
+ return 0
+
+ try:
+ for line in reader.readlines():
+ label, val = line.split(u"=", 1)
+ label = label.strip()
+ if not len(label):
+ continue
+ self._viewset[label] = val.strip()
+ reader.close()
+ finally:
+ if LAST_KEY in self._viewset:
+ self._currview = self._viewset[LAST_KEY]
+ del self._viewset[LAST_KEY]
+ return len(self._viewset)
+
+ def OnPerspectiveMenu(self, evt):
+ """Handles menu events generated by the managers control menu.
+ @param evt: event that called this handler
+
+ """
+ e_id = evt.GetId()
+ if e_id == ID_SAVE_PERSPECTIVE:
+ name = wx.GetTextFromUser(_("Perspective Name"), \
+ _("Save Perspective"))
+ if name:
+ self.AddPerspective(name, p_data=None)
+ self.SavePerspectives()
+ Profile_Set('DEFAULT_VIEW', name)
+
+ # It may make sense to update all windows to use this
+ # perspective at this point but it may be an unexpected
+ # event to happen when there is many windows open. Will
+ # leave this to future consideration.
+ for mainw in wx.GetApp().GetMainWindows():
+ mainw.AddPerspective(name, self._viewset[name])
+
+ elif e_id == ID_DELETE_PERSPECTIVE:
+ views = [ view for view in self._viewset.keys()
+ if view != AUTO_PERSPECTIVE ]
+ name = wx.GetSingleChoice(_("Perspective to Delete"),
+ _("Delete Perspective"), views)
+
+ if name:
+ self.RemovePerspective(name)
+ self.SavePerspectives()
+ for mainw in wx.GetApp().GetMainWindows():
+ mainw.RemovePerspective(name)
+ else:
+ pass
+
+ # Update all windows data sets
+ for mainw in wx.GetApp().GetMainWindows():
+ mainw.LoadPerspectives()
+
+ elif e_id in self._ids + [ID_AUTO_PERSPECTIVE]:
+ if e_id == ID_AUTO_PERSPECTIVE:
+ Profile_Set('DEFAULT_VIEW', AUTO_PERSPECTIVE)
+ self.SetAutoPerspective()
+ else:
+ self.SetPerspectiveById(e_id)
+ else:
+ evt.Skip()
+
+ def OnUpdatePerspectiveMenu(self, evt):
+ """Update the perspective menu's check mark states
+ @param evt: UpdateUI event that called this handler
+
+ """
+ e_id = evt.GetId()
+ if e_id in self._ids + [ID_AUTO_PERSPECTIVE]:
+ evt.Check(self._menu.GetLabel(e_id) == self._currview)
+ else:
+ evt.Skip()
+
+ def RemovePerspective(self, name):
+ """Removes a named perspective from the managed set
+ @param name: name of perspective to remove/delete
+
+ """
+ if name in self._viewset:
+ del self._viewset[name]
+ rem_id = self._menu.RemoveItemByName(name)
+ if rem_id:
+ self._ids.remove(rem_id)
+
+ def SetAutoPerspective(self):
+ """Set the current perspective management into automatic mode
+ @postcondition: window is set into
+
+ """
+ self._currview = AUTO_PERSPECTIVE
+ self.UpdateAutoPerspective()
+
+ def SavePerspectives(self):
+ """Writes the perspectives out to disk. Returns True if all data was
+ written and False if there was an error.
+ @return: whether save was successful
+
+ """
+ writer = util.GetFileWriter(self._base)
+ if writer == -1:
+ util.Log("[perspective][err] Failed to save %s" % self._base)
+ return False
+
+ try:
+ self._viewset[LAST_KEY] = self._currview
+ for perspect in self._viewset:
+ writer.write(u"%s=%s\n" % (perspect, self._viewset[perspect]))
+ del self._viewset[LAST_KEY]
+ except (IOError, OSError):
+ util.Log("[perspective][err] Write error: %s" % self._base)
+ return False
+ else:
+ return True
+
+ def SetPerspective(self, name):
+ """Sets the perspective of the managed window, returns
+ True on success and False on failure.
+ @param name: name of perspective to set
+ @return: whether perspective was set or not
+
+ """
+ if name in self._viewset:
+ self._mgr.LoadPerspective(self._viewset[name])
+ self._mgr.Update()
+
+ self._currview = name
+ self.SavePerspectives()
+ return True
+ else:
+ # Fall back to automatic mode
+ self.SetAutoPerspective()
+ return False
+
+ def SetPerspectiveById(self, per_id):
+ """Sets the perspective using the given control id
+ @param per_id: id of requested perspective
+ @return: whether perspective was set or not
+
+ """
+ name = None
+ for pos in range(self._menu.GetMenuItemCount()):
+ item = self._menu.FindItemByPosition(pos)
+ if per_id == item.GetId():
+ name = item.GetLabel()
+ break
+
+ if name is not None:
+ return self.SetPerspective(name)
+ else:
+ return False
+
+ def UpdateAutoPerspective(self):
+ """Update the value of the auto-perspectives current saved state
+ @postcondition: The perspective data for the Automatic setting is
+ updated to have data for the current state of the
+ window.
+
+ """
+ self._viewset[AUTO_PERSPECTIVE] = self._mgr.SavePerspective()
+ self.SavePerspectives()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugdlg.py
new file mode 100644
index 0000000..f4a6888
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugdlg.py
@@ -0,0 +1,1206 @@
+###############################################################################
+# Name: plugdlg.py #
+# Purpose: User interface into the PluginManager, also provides interface for #
+# downloading and installing plugins. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides a dialog for downloading, installing and configuring plugins or Editra.
+
+@todo: refactor list population and list item creation
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__cvsid__ = "$Id: plugdlg.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import os
+import sys
+import re
+import urllib2
+import wx
+import wx.lib.delayedresult as delayedresult
+
+# Local Imports
+import ed_glob
+import plugin
+import ed_event
+import ed_msg
+import util
+import ed_txt
+from profiler import Profile_Get, Profile_Set
+import ed_basewin
+import eclib
+
+#-----------------------------------------------------------------------------#
+# Globals
+
+CONFIG_PG = 0
+DOWNLOAD_PG = 1
+INSTALL_PG = 2
+PY_VER = str(sys.version_info[0]) + str(sys.version_info[1])
+PLUGIN_REPO = "http://editra.org/plugins.php?list=True&py=" + PY_VER
+
+# Panel Display Modes
+MODE_CONFIG = 0
+MODE_ERROR = 1
+
+# Image list indexes
+IMG_CONFIG = 0
+IMG_DOWNLOAD = 1
+IMG_INSTALL = 2
+IMG_ERROR = 3
+IMG_PLUGIN = 4
+
+_ = wx.GetTranslation
+
+#-----------------------------------------------------------------------------#
+
+def MakeThemeTool(tool_id):
+ """Makes a themed bitmap for the tool book of the plugin dialog.
+ @param tool_id: An art identifier id
+ @return: 32x32 bitmap
+ @todo: why does drawing a bitmap overlay on gtk not draw on transparent area
+
+ """
+ osize = Profile_Get('ICON_SZ', default=(24, 24))
+ Profile_Set('ICON_SZ', (32, 32))
+ base = wx.ArtProvider.GetBitmap(str(tool_id), wx.ART_TOOLBAR)
+ Profile_Set('ICON_SZ', osize)
+ if not base.IsOk():
+ base = wx.ArtProvider.GetBitmap(wx.ART_WARNING,
+ wx.ART_TOOLBAR,
+ size=(32, 32))
+
+ over = wx.ArtProvider.GetBitmap(str(ed_glob.ID_PLUGMGR), wx.ART_MENU)
+ if over.IsOk():
+ # Draw overlay onto button
+ mdc = wx.MemoryDC()
+ mdc.SelectObject(base)
+ mdc.SetBrush(wx.TRANSPARENT_BRUSH)
+ mdc.SetPen(wx.TRANSPARENT_PEN)
+ mdc.DrawBitmap(over, 15, 15, False)
+ mdc.SelectObject(wx.NullBitmap)
+
+ return base
+
+#-----------------------------------------------------------------------------#
+
+class PluginDialog(wx.Frame):
+ """Defines a Plugin manager Dialog that can be used to download plugins
+ from a defined repository, offers services to install plugins that
+ where downloaded with or without the dialog, as well as configure
+ already installed plugins. It is instanciated as a standalone window
+ when the show method is called so that if downloads are taking along time
+ it does not interfere with usage of the editor.
+
+ """
+ def __init__(self, parent, id=wx.ID_ANY, title=u'', size=wx.DefaultSize):
+ super(PluginDialog, self).__init__(parent, title=title, size=size,
+ style=wx.DEFAULT_FRAME_STYLE)
+ util.SetWindowIcon(self)
+
+ # Attributes
+ bstyle = eclib.SEGBOOK_STYLE_NO_DIVIDERS|eclib.SEGBOOK_STYLE_LABELS
+ self._nb = eclib.SegmentBook(self, style=bstyle)
+ self._cfg_pg = ConfigPanel(self._nb, style=wx.BORDER_SUNKEN)
+ self._dl_pg = DownloadPanel(self._nb)
+ self._inst_pg = InstallPanel(self._nb)
+ self._imglst = list()
+
+ # Setup
+ self.__InitImageList()
+
+ self._nb.AddPage(self._cfg_pg, _("Configure"), img_id=IMG_CONFIG)
+ self._nb.AddPage(self._dl_pg, _("Download"), img_id=IMG_DOWNLOAD)
+ self._nb.AddPage(self._inst_pg, _("Install"), img_id=IMG_INSTALL)
+
+ # Check for plugins with error conditions and if any are found
+ # Add the error page.
+ pmgr = wx.GetApp().GetPluginManager()
+ if len(pmgr.GetIncompatible()):
+ self._nb.AddPage(ConfigPanel(self._nb, style=wx.NO_BORDER,
+ mode=MODE_ERROR),
+ _("Errors"), img_id=IMG_ERROR)
+
+ # Layout
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(self._nb, 1, wx.EXPAND)
+ self.SetSizer(sizer)
+ self.SetStatusBar(eclib.ProgressStatusBar(self, style=wx.SB_FLAT))
+ self.SetInitialSize(size)
+
+ # Event Handlers
+ self.Bind(eclib.EVT_SB_PAGE_CHANGING, self.OnPageChanging)
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+
+ # Message Handlers
+ ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED)
+
+ def OnDestroy(self, evt):
+ """Cleanup message handlers on delete"""
+ if evt.GetId() == self.GetId():
+ ed_msg.Unsubscribe(self.OnThemeChange)
+ evt.Skip()
+
+ def __InitImageList(self):
+ """Initialize the segmentbooks image list"""
+ dorefresh = False
+ if len(self._imglst):
+ del self._imglst
+ self._imglst = list()
+ dorefresh = True
+
+ self._imglst.append(MakeThemeTool(ed_glob.ID_PREF))
+ self._imglst.append(MakeThemeTool(ed_glob.ID_WEB))
+ self._imglst.append(MakeThemeTool(ed_glob.ID_PACKAGE))
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_TOOLBAR, (32, 32))
+ self._imglst.append(bmp)
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_PREF),
+ wx.ART_TOOLBAR, (32, 32))
+ self._imglst.append(bmp)
+ self._nb.SetImageList(self._imglst)
+ self._nb.SetUsePyImageList(True)
+
+ if dorefresh:
+ self._nb.Refresh()
+
+ def OnClose(self, evt):
+ """Handles closing the dialog and unregistering it from the mainloop.
+ @param evt: wx.EVT_CLOSE
+
+ """
+ if self._dl_pg.IsDownloading():
+ dlg = wx.MessageDialog(self, _("Downloads are incomplete"),
+ _("Do you wish to exit?"),
+ style=wx.YES_NO|wx.ICON_EXCLAMATION| \
+ wx.CENTER)
+ result = dlg.ShowModal()
+ dlg.Destroy()
+ if result == wx.ID_NO:
+ return
+ else:
+ pass
+
+ if self._cfg_pg.ConfigChanged():
+ wx.MessageBox(_("You must restart Editra before your "
+ "changes will take full affect."),
+ _("Configuration Changes Made"),
+ wx.ICON_INFORMATION|wx.OK)
+
+
+ wx.GetApp().UnRegisterWindow(repr(self))
+ evt.Skip()
+
+ def OnThemeChange(self, msg):
+ """Update icons on theme change message"""
+ self.__InitImageList()
+
+ def Show(self, show=True):
+ """Shows the dialog
+ @postcondition: Dialog is registered with the main loop and shown
+
+ """
+ wx.GetApp().RegisterWindow(repr(self), self, True)
+ wx.Frame.Show(self, show)
+
+ def Busy(self, busy=True):
+ """Set the status of the frame to be busy or not
+ @keyword busy: Start or Stop being busy
+
+ """
+ if busy:
+ self.GetStatusBar().StartBusy()
+ else:
+ self.GetStatusBar().StopBusy()
+
+ def OnPageChanging(self, evt):
+ """Updates pages as they are being changed to.
+ @param evt: segmentbk.EVT_SB_PAGE_CHANGING
+
+ """
+ cur_pg = evt.GetSelection()
+ self.SetTitle(self.GetTitle().split(" | ")[0] + \
+ " | " + self._nb.GetPageText(cur_pg))
+ if cur_pg == CONFIG_PG:
+ self._cfg_pg.PopulateCtrl()
+ self.SetStatusText(_("Changes will take affect once the"
+ " program has been restarted"), 0)
+ elif cur_pg == DOWNLOAD_PG:
+ self._dl_pg.UpdateList()
+ elif cur_pg == INSTALL_PG:
+ pass
+ else:
+ page = self._nb.GetPage(cur_pg)
+ size = page.GetBestSize()
+ s2 = self.GetSize()
+ segbar = self._nb.GetSegmentBar()
+ segsize = segbar.GetBestSize()
+ self.SetClientSize((s2.GetWidth(),
+ size.GetHeight() + segsize.GetHeight()))
+ self.SetStatusText("", 0)
+
+ evt.Skip()
+
+#-----------------------------------------------------------------------------#
+
+class ConfigPanel(eclib.ControlBox):
+ """Creates a panel for configuring plugins."""
+ def __init__(self, parent, style=wx.NO_BORDER, mode=MODE_CONFIG):
+ """Build config panel"""
+ eclib.ControlBox.__init__(self, parent, style=style)
+
+ # Attrtibutes
+ self._mode = mode
+ self._changed = False
+ self._list = eclib.PanelBox(self)
+
+ # Layout Panel
+ self.SetWindow(self._list)
+
+ if self._mode == MODE_CONFIG:
+ self.PopulateCtrl()
+ else:
+ self.PopulateErrors()
+
+ # Event Handlers
+ self.Bind(ed_event.EVT_NOTIFY, self.OnNotify)
+
+ def ConfigChanged(self):
+ """Did the configuration change?
+ @return: bool
+
+ """
+ return self._changed
+
+ def GetItemIdentifier(self, name):
+ """Gets the named item and returns its identifier. The
+ identifier is the combination of the name and version
+ strings.
+ @param name: name of item in list
+ @return: identifier for the named list item
+
+ """
+ identifer = None
+ for item in self._list.GetItems():
+ if item.GetPluginName().lower() == name.lower():
+ identifer = (name, item.GetVersionString())
+ return identifer
+
+ def OnNotify(self, evt):
+ """Handles the notification events that are
+ posted from the list control.
+ @param evt: ed_event.NotificationEvent
+
+ """
+ e_id = evt.GetId()
+ if e_id == ed_glob.ID_PREF:
+ # TODO: check for an open existing instance of this config objects
+ # page.
+ cfg_obj = evt.GetValue()
+ parent = self.GetParent() # SegmentBook
+
+ bmp = cfg_obj.GetBitmap()
+ if bmp.IsNull():
+ idx = IMG_PLUGIN
+ else:
+ imglst = parent.GetImageList()
+ imglst.append(bmp)
+ idx = len(imglst) - 1
+
+ label = cfg_obj.GetLabel()
+ panel = cfg_obj.GetConfigPanel(parent)
+ parent.AddPage(panel, label, True, idx)
+ parent.SetSegmentCanClose(parent.GetPageCount() - 1, True)
+ else:
+ pname, enabled = evt.GetValue()
+ pmgr = wx.GetApp().GetPluginManager()
+ pmgr.EnablePlugin(pname, enabled)
+ self._changed = True
+
+ def PopulateCtrl(self):
+ """Populates the list of plugins and sets the
+ values of their states. Any successive calls to
+ this function will clear the list and Repopulate it
+ with current config values. Returns the number of
+ items populated to the list
+ @postcondition: list is populated with all plugins that are
+ currently loaded and sets the checkmarks accordingly
+ @return: number of items added to list
+
+ """
+ p_mgr = wx.GetApp().GetPluginManager()
+ if self._list.GetItemCount():
+ self._list.DeleteAllItems()
+
+ p_mgr.ReInit()
+ config = p_mgr.GetConfig()
+ keys = sorted([ ed_txt.DecodeString(name)
+ for name in config.keys() ],
+ key=unicode.lower)
+ uninstalled = Profile_Get('UNINSTALL_PLUGINS', default=list())
+
+ with eclib.Freezer(self._list) as _tmp:
+ for item in keys:
+ val = config[item]
+ mod = sys.modules.get(item)
+ dist = p_mgr.GetPluginDistro(item)
+ if dist is not None:
+ item = dist.project_name
+ version = dist.version
+ else:
+ version = str(getattr(mod, '__version__', _("Unknown")))
+
+ pdata = PluginData()
+ pdata.SetName(item)
+ desc = getattr(mod, '__doc__', None)
+ if not isinstance(desc, basestring):
+ desc = _("No Description Available")
+ pdata.SetDescription(desc.strip())
+ pdata.SetAuthor(getattr(mod, '__author__', _("Unknown")))
+ pdata.SetVersion(version)
+ pdata.SetDist(dist)
+ pbi = PBPluginItem(self._list, mod, pdata, None)
+
+ pbi.SetChecked(val)
+ util.Log("[pluginmgr][info] Adding %s to list" % item)
+ self._list.AppendItem(pbi)
+ if pbi.GetInstallPath() in uninstalled:
+ pbi.Enable(False)
+
+ self._list.SendSizeEvent()
+ return self._list.GetItemCount()
+
+ def PopulateErrors(self):
+ """Populates the list of plugins and sets the
+ values of their states. Any successive calls to
+ this function will clear the list and Repopulate it
+ with current config values. Returns the number of
+ items populated to the list
+ @postcondition: list is populated with all plugins that are
+ currently loaded and sets the checkmarks accordingly
+ @return: number of items added to list
+
+ """
+ p_mgr = wx.GetApp().GetPluginManager()
+ if self._list.GetItemCount():
+ self._list.DeleteAllItems()
+
+ p_mgr.ReInit()
+ errors = p_mgr.GetIncompatible()
+ keys = sorted([ ed_txt.DecodeString(name)
+ for name in errors.keys() ],
+ key=unicode.lower)
+ bmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_TOOLBAR, (32, 32))
+ msg = _("This plugin requires a newer version of Editra.")
+
+ with eclib.Freezer(self._list) as _tmp:
+ for item in keys:
+ val = errors[item]
+ mod = sys.modules.get(val)
+ dist = p_mgr.GetPluginDistro(item)
+ if dist is not None:
+ item = dist.project_name
+ version = dist.version
+ else:
+ version = unicode(getattr(mod, '__version__', _("Unknown")))
+
+ pin = PluginData()
+ pin.SetName(item)
+ pin.SetAuthor(getattr(mod, '__author__', _("Unknown")))
+ pin.SetVersion(version)
+ pin.SetDist(dist)
+ pbi = PluginErrorItem(self._list, pin, msg, bmp=bmp)
+
+ self._list.AppendItem(pbi)
+
+ self._list.SendSizeEvent()
+ return self._list.GetItemCount()
+
+#-----------------------------------------------------------------------------#
+
+class DownloadPanel(ed_basewin.EdBaseCtrlBox):
+ """Creates a panel with controls for downloading plugins."""
+ ID_DOWNLOAD = wx.NewId()
+ EGG_PATTERN = re.compile(r"(?P<name>[^-]+)"
+ r"( -(?P<ver>[^-]+) (-py(?P<pyver>[^-]+) (-(?P<plat>.+))? )? )?",
+ re.VERBOSE | re.IGNORECASE
+ ).match
+
+ def __init__(self, parent):
+ """Initializes the panel"""
+ super(DownloadPanel, self).__init__(parent)
+
+ # Attributes
+ self._p_list = dict() # list of available plugins/meta
+ self._dl_list = dict() # List of download urls
+ self._eggcount = 0 # Number of plugins to download
+ self._eggbasket = dict() # Basket of downloaded eggs
+ self._list = eclib.PanelBox(self)
+
+ # Layout Panel
+ cbar = self.CreateControlBar(wx.BOTTOM)
+ cbar.AddStretchSpacer()
+ self._downlb = wx.Button(cbar, DownloadPanel.ID_DOWNLOAD, _("Download"))
+ self._downlb.Disable()
+ cbar.AddControl(self._downlb, wx.ALIGN_RIGHT)
+ self.SetWindow(self._list)
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ self.Bind(ed_event.EVT_NOTIFY, self.OnNotify)
+
+ def _ResultCatcher(self, delayedResult):
+ """Catches the results from the download worker threads"""
+ # Check if result has come after the window is dead
+ try:
+ frame = self.GetGrandParent()
+ except wx.PyDeadObjectError:
+ return
+
+ self._eggcount = self._eggcount - 1
+ try:
+ result = delayedResult.get()
+ plug = result[0]
+ if result[1]:
+ self._eggbasket[plug] = result[2]
+ frame.SetStatusText(_("Downloaded") + ": " + plug, 0)
+ finally:
+ if not self._eggcount:
+ frame.SetStatusText(_("Finshed downloading plugins"), 0)
+ wx.CallAfter(frame.Busy, False)
+ inst_pg = self.GetParent().GetPage(INSTALL_PG)
+ for key in self._eggbasket:
+ inst_pg.AddItemToInstall(key)
+ self.GetParent().SetSelection(INSTALL_PG)
+
+ def _UpdateCatcher(self, delayedResult):
+ """Catches the results from the download worker threads"""
+ try:
+ frame = self.GetGrandParent()
+ result = delayedResult.get()
+ if len(result):
+ self._p_list = self.FormatPluginList(result)
+ self.PopulateList()
+ frame.SetStatusText(_("Select plugins to download"), 0)
+ except wx.PyDeadObjectError:
+ return
+ except Exception, msg:
+ util.Log("[plugdlg][err] Download failed " + str(msg))
+ frame.SetStatusText(_("Unable to retrieve plugin list"), 0)
+ wx.CallAfter(frame.Busy, False)
+
+ def FormatPluginList(self, data):
+ """Formats a list of plugin data served by the server into
+ PluginData objects for usage in the list view.
+ @return: PluginData of all available plugins
+
+ """
+ plugins = data
+ p_list = dict()
+ if len(plugins) < 2:
+ return p_list
+
+ for meta in plugins:
+ data = meta.split("\n")
+
+ if len(data) < 4:
+ continue
+
+ tmpdat = PluginData()
+ set_map = {'author' : tmpdat.SetAuthor,
+ 'version' : tmpdat.SetVersion,
+ 'name' : tmpdat.SetName,
+ 'description' : tmpdat.SetDescription,
+ 'url' : tmpdat.SetUrl}
+
+ for attr in data:
+ tmp = attr.split("=")
+ if len(tmp) != 2:
+ continue
+
+ funct = set_map.get(tmp[0].lower(), None)
+ if funct:
+ funct(ed_txt.DecodeString(tmp[1].strip()))
+
+ if tmpdat.GetName() != u'':
+ p_list[ed_txt.DecodeString(tmpdat.GetName())] = tmpdat
+
+ # Remove items that have already been installed
+ config_pg = self.GetParent().GetPage(CONFIG_PG)
+ to_clean = list()
+ for pin in p_list:
+ cfg_id = config_pg.GetItemIdentifier(pin.lower())
+ if cfg_id is not None:
+ try:
+ cur_id = [int(v) for v in cfg_id[1].split(".")]
+ dl_id = [int(v) for v in p_list[pin].GetVersion().split(".")]
+ except:
+ continue
+ if cur_id >= dl_id: # Installed version is >= avail dl
+ to_clean.append(pin)
+
+ for item in to_clean:
+ del p_list[item]
+
+ return p_list
+
+ def GetDownloadedData(self):
+ """Returns the dictionary of downloaded data or an
+ empty dictionary if no data has been downloaded.
+ @return: set of all successfully downloaded plugins
+
+ """
+ return self._eggbasket
+
+ def IsDownloading(self):
+ """Returns whether the panel has active download
+ threads or not.
+ @return: bool
+
+ """
+ if self._eggcount:
+ return True
+ else:
+ return False
+
+ def OnButton(self, evt):
+ """Handles the Button Events.
+ @param evt: wx.EVT_BUTTON
+
+ """
+ e_id = evt.GetId()
+ if e_id == self.ID_DOWNLOAD:
+ urls = list()
+ for item in self._dl_list:
+ if self._dl_list[item] and item in self._p_list:
+ urls.append(self._p_list[item].GetUrl())
+ self._eggcount = len(urls)
+
+ # Start a separate thread to download each selection
+ for egg in range(len(urls)):
+ self.GetGrandParent().SetStatusText(_("Downloading") + "...", 0)
+ self.GetGrandParent().Busy(True)
+ delayedresult.startWorker(self._ResultCatcher, _DownloadPlugin,
+ wargs=(urls[egg]), jobID=egg)
+ else:
+ evt.Skip()
+
+ def OnNotify(self, evt):
+ """Handles the notification events that are posted by the
+ list control when items are checked.
+ @param evt: ed_event.NotificationEvent
+
+ """
+ pin, enable = evt.GetValue()
+ self._dl_list[pin] = enable
+
+ if enable:
+ self._downlb.Enable()
+ else:
+ for item in self._dl_list:
+ if self._dl_list[item]:
+ self._downlb.Enable()
+ break
+ else:
+ self._downlb.Disable()
+
+ if pin in self._dl_list:
+ del self._dl_list[pin]
+
+ def PopulateList(self):
+ """Populates the list control based off data in the plugin data
+ list. The plugin data list is set as a result of calling UpdateList
+ it is not recommended to call this directly.
+
+ @return: number of items added to control
+
+ """
+ if self._list.GetItemCount():
+ self._list.DeleteAllItems()
+ pins = sorted([ name for name in self._p_list.keys() ], key=unicode.lower)
+ with eclib.Freezer(self) as _tmp:
+ for item in pins:
+ pbi = PBDownloadItem(self._list, self._p_list[item], None)
+ self._list.AppendItem(pbi)
+ self._list.SendSizeEvent()
+ return self._list.GetItemCount()
+
+ def RemoveDownloadedItem(self, item):
+ """Remove an item from the download cache
+ @param item: Name of item to remove
+
+ """
+ # Removed downloaded data
+ if item in self._eggbasket:
+ del self._eggbasket[item]
+
+ # Remove download entry data
+ match = self.EGG_PATTERN(item)
+ if match:
+ plugin_name = match.group('name').lower()
+ if plugin_name in self._dl_list:
+ del self._dl_list[plugin_name]
+
+ def UpdateList(self, url=PLUGIN_REPO):
+ """Update the list of available downloads
+ @param url: url to fetch update list from
+ @postcondition: Worker thread is started that will update list when it
+ finishes.
+
+ """
+ if self._list.GetItemCount():
+ self._list.DeleteAllItems()
+ frame = self.GetGrandParent()
+ frame.SetStatusText(_("Retrieving Plugin List") + "...", 0)
+ frame.Busy(True)
+ delayedresult.startWorker(self._UpdateCatcher, _GetPluginListData,
+ wkwargs={'url' : url}, jobID='update')
+
+#-----------------------------------------------------------------------------#
+# Download utility functions
+
+# The obtained meta data must be served as a file that is formatted
+# as follows. Each meta data item must be on a single line with
+# each set of meta data for different plugins separated by three
+# hash marks '###'.
+def _GetPluginListData(url=PLUGIN_REPO):
+ """Gets the list of plugins and their related meta data
+ as a string and returns it.
+ @return: list of data of available plugins from website
+
+ """
+ text = u''
+ try:
+ try:
+ if Profile_Get('USE_PROXY', default=False):
+ proxy_set = Profile_Get('PROXY_SETTINGS',
+ default=dict(uname='', url='',
+ port='80', passwd=''))
+ proxy = util.GetProxyOpener(proxy_set)
+ h_file = proxy.open(url)
+ else:
+ h_file = urllib2.urlopen(url)
+
+ text = h_file.read()
+ h_file.close()
+ except (IOError, OSError), msg:
+ util.Log("[plugdlg][err] %s" % str(msg))
+ finally:
+ return text.split("###")
+
+def _DownloadPlugin(*args):
+ """Downloads the plugin at the given url.
+ @note: *args is really a string that has been exploded
+ @return: name, completed, egg data
+ @rtype: tuple
+
+ """
+ url = "".join(args)
+ egg = None
+ try:
+ try:
+ if Profile_Get('USE_PROXY', default=False):
+ proxy_set = Profile_Get('PROXY_SETTINGS',
+ default=dict(uname='', url='',
+ port='80', passwd=''))
+ proxy = util.GetProxyOpener(proxy_set)
+ h_file = proxy.open(url)
+ else:
+ h_file = urllib2.urlopen(url)
+
+ egg = h_file.read()
+ h_file.close()
+ except (IOError, OSError), msg:
+ util.Log("[plugdlg][err] %s" % str(msg))
+ finally:
+ return (url.split("/")[-1], True, egg)
+
+#-----------------------------------------------------------------------------#
+
+class InstallPanel(ed_basewin.EdBaseCtrlBox):
+ """Creates a panel for installing plugins."""
+ ID_INSTALL = wx.NewId()
+ ID_USER = wx.NewId()
+ ID_SYS = wx.NewId()
+ ID_REMOVE_ITEM = wx.NewId()
+
+ def __init__(self, parent):
+ """Initializes the panel"""
+ super(InstallPanel, self).__init__(parent)
+
+ # Attributes
+ bbar = self.CreateControlBar(wx.BOTTOM)
+ toolt = wx.ToolTip(_("To add a new item drag and drop the plugin file "
+ "into the list.\n\nTo remove an item select it "
+ "and hit Delete or Backspace."))
+ self._install = wx.ListBox(self, wx.ID_ANY,
+ style=wx.LB_SORT|wx.BORDER_NONE)
+ self._install.SetToolTip(toolt)
+ self._install.SetDropTarget(util.DropTargetFT(self._install,
+ None, self.OnDrop))
+
+ self._instb = wx.Button(bbar, self.ID_INSTALL, _("Install"))
+ self._instb.Disable()
+ self._usercb = wx.CheckBox(bbar, self.ID_USER, _("User Directory"))
+ self._usercb.SetValue(True)
+ toolt = wx.ToolTip(_("Install the plugins only for the current user"))
+ self._usercb.SetToolTip(toolt)
+ self._syscb = wx.CheckBox(bbar, self.ID_SYS, _("System Directory"))
+ toolt = wx.ToolTip(_("Install the plugins for all users\n"
+ " **requires administrative privileges**"))
+ self._syscb.SetToolTip(toolt)
+ if not os.access(ed_glob.CONFIG['SYS_PLUGIN_DIR'], os.R_OK | os.W_OK):
+ self._syscb.Disable()
+
+ # Layout Panel
+ self.SetWindow(self._install)
+ bbar.AddControl(self._usercb)
+ bbar.AddControl(self._syscb)
+ bbar.AddStretchSpacer()
+ bbar.AddControl(self._instb, wx.ALIGN_RIGHT)
+ self.SendSizeEvent()
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ self.Bind(wx.EVT_CHECKBOX, self.OnCheckBox)
+ self._install.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+
+ def _Install(self):
+ """Install the plugins in the list.
+ @postcondition: all plugins listed in the list are installed and loaded
+
+ """
+ items = self._install.GetItems()
+ inst_loc = ed_glob.CONFIG['PLUGIN_DIR']
+ if self._syscb.GetValue():
+ inst_loc = ed_glob.CONFIG['SYS_PLUGIN_DIR']
+
+ for item in items:
+ egg_name = item.split(os.sep)[-1]
+ if os.path.isabs(item):
+ try:
+ reader = file(item, "rb")
+ egg = reader.read()
+ reader.close()
+ except (IOError, SystemError, OSError):
+ continue
+ else:
+ dl_pg = self.GetParent().GetPage(DOWNLOAD_PG)
+ egg = dl_pg.GetDownloadedData().get(item, None)
+ if not egg:
+ continue
+
+ try:
+ writer = file(inst_loc + egg_name, "wb")
+ writer.write(egg)
+ writer.close()
+ except (IOError, OSError):
+ continue
+ else:
+ # If successfully installed remove from list
+ ind = self._install.FindString(item)
+ dl_pg = self.GetParent().GetPage(DOWNLOAD_PG)
+ if ind != wx.NOT_FOUND:
+ self._install.Delete(ind)
+ dl_pg.RemoveDownloadedItem(item)
+
+ if not len(self._install.GetItems()):
+ # All plugins installed correctly
+ grand_p = self.GetTopLevelParent()
+ grand_p.SetStatusText(_("Successfully Installed Plugins"), 0)
+ # Note: need to do this because SetSelection doesn't fire a
+ # page change.
+ wx.GetApp().GetPluginManager().ReInit()
+ self.GetParent().SetSelection(CONFIG_PG)
+ self._instb.Disable()
+ else:
+ self.GetGrandParent().SetStatusText(_("Error"), 1)
+ dlg = wx.MessageDialog(self,
+ _("Failed to install %d plugins") % \
+ self._install.GetCount(),
+ _("Installation Error"),
+ style = wx.OK | wx.CENTER | wx.ICON_ERROR)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+ def AddItemToInstall(self, item):
+ """Adds an item to the install list, the item
+ should be a string of the path to the item or
+ the items name if it is an in memory file from the
+ download page.
+ @param item: path or name of plugin item
+
+ """
+ if self._install.FindString(item) == wx.NOT_FOUND:
+ self._instb.Enable()
+ self._install.Append(item)
+ else:
+ pass
+
+ def OnButton(self, evt):
+ """Handles button events generated by the panel.
+ @param evt: wx.EVT_BUTTON
+
+ """
+ if evt.GetId() == self.ID_INSTALL:
+ self._Install()
+ else:
+ evt.Skip()
+
+ def OnCheckBox(self, evt):
+ """Handles the checkbox events to make sure that
+ only one of the two check boxes is checked at a time
+ @param evt: wx.EVT_CHECKBOX
+
+ """
+ e_id = evt.GetId()
+ val = evt.GetEventObject().GetValue()
+ u_cb = self.FindWindowById(self.ID_USER)
+ s_cb = self.FindWindowById(self.ID_SYS)
+ if e_id == self.ID_USER:
+ if not s_cb.IsEnabled():
+ u_cb.SetValue(True)
+ else:
+ s_cb.SetValue(not val)
+ elif e_id == self.ID_SYS:
+ u_cb.SetValue(not val)
+ else:
+ pass
+ evt.Skip()
+
+ def OnDrop(self, files):
+ """Get Drop files and place paths in control
+ @todo: should also check entry points in addition to filetype
+ @param files: list of file paths
+ @postcondition: all non egg files are filtered only placing
+ the eggs in the list.
+ """
+ # Filter out any files that are not eggs
+ good = [ fname for fname in files if fname.split(u'.')[-1] == u'egg' ]
+ for item in good:
+ if self._install.FindString(item) == wx.NOT_FOUND:
+ self._install.Append(item)
+
+ if self._install.GetCount():
+ self._instb.Enable()
+
+ def OnKeyUp(self, evt):
+ """Key Event handler. Removes the selected item from
+ the list control when the delete or backspace kis is pressed.
+ @param evt: wx.KeyEvent(wx.EVT_KEY_UP)
+
+ """
+ if evt.GetKeyCode() in [wx.WXK_DELETE, wx.WXK_BACK]:
+ item = self._install.GetSelection()
+ if item != wx.NOT_FOUND:
+ self._install.Delete(item)
+
+ if not self._install.GetCount():
+ self._instb.Disable()
+
+ evt.Skip()
+
+#-----------------------------------------------------------------------------#
+
+class PBPluginItem(eclib.PanelBoxItemBase):
+ """PanelBox Item to display configuration information about a plugin."""
+ def __init__(self, parent, mod, pdata, bmp=None, enabled=False):
+ """Create the PanelBoxItem
+ @param parent: L{PanelBox}
+ @param mod: module
+ @param pdata: PluginData
+ @keyword bmp: Plugin Icon
+ @keyword enabled: Plugin is currently enabled (bool)
+
+ """
+ super(PBPluginItem, self).__init__(parent)
+
+ # Attributes
+ self._module = mod
+ self._pdata = pdata
+ self._bmp = bmp
+ self._title = wx.StaticText(self, label=self._pdata.GetName())
+ self._version = wx.StaticText(self, label=self._pdata.GetVersion())
+ self._desc = wx.StaticText(self, label=self._pdata.GetDescription())
+ self._auth = wx.StaticText(self, label=_("Author: %s") % self._pdata.GetAuthor())
+ self._enabled = wx.CheckBox(self, label=_("Enable"))
+ self._enabled.SetValue(enabled)
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DELETE), wx.ART_MENU)
+ self._uninstall = eclib.PlateButton(self, label=_("Uninstall"), bmp=bmp,
+ style=eclib.PB_STYLE_NOBG)
+ self._uninstall.Unbind(wx.EVT_ERASE_BACKGROUND)
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_PREF), wx.ART_MENU)
+ self._config = eclib.PlateButton(self,
+ label=_("Configure"), bmp=bmp,
+ style=eclib.PB_STYLE_NOBG)
+ self._config.Unbind(wx.EVT_ERASE_BACKGROUND)
+ self._config.Enable(enabled)
+
+ # Setup
+ if not hasattr(mod, 'GetConfigObject'):
+ self._config.Hide()
+
+ ipath = self.GetInstallPath()
+ if ipath:
+ if not os.access(ipath, os.R_OK|os.W_OK):
+ self._uninstall.Show(False)
+ else:
+ util.Log("[pluginmgr][warn] cant find plugin path for %s" % \
+ self._pdata.GetName())
+ self._uninstall.Show(False) # Should not happen
+
+ font = self._title.GetFont()
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ self._title.SetFont(font)
+ self._version.SetFont(font)
+
+ if wx.Platform == '__WXMAC__':
+ for ctrl in (self._desc, self._auth, self._enabled,
+ self._config, self._uninstall):
+ ctrl.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+
+ # Layout
+ self.__DoLayout()
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
+ self.Bind(wx.EVT_BUTTON, self.OnConfigButton, self._config)
+ self.Bind(wx.EVT_BUTTON, self.OnUninstallButton, self._uninstall)
+
+ def __DoLayout(self):
+ """Layout the panel"""
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ # Left side Bitmap and Checkbox
+ hsizer.Add((5, 5), 0)
+ if self._bmp is not None:
+ self._bmp = wx.StaticBitmap(self, bitmap=self._bmp)
+ hsizer.Add(self._bmp, 0, wx.ALIGN_CENTER_VERTICAL)
+
+ # Central area main content
+ csizer = wx.BoxSizer(wx.VERTICAL)
+ tsizer = wx.BoxSizer(wx.HORIZONTAL)
+ tsizer.AddMany([(self._title, 0), ((20, -1), 1, wx.EXPAND),
+ (self._version, 0, wx.ALIGN_RIGHT),
+ ((5, 5), 0)])
+
+ bsizer = wx.BoxSizer(wx.HORIZONTAL)
+ bsizer.AddMany([(self._auth, 0), ((5, -1), 1, wx.EXPAND),
+ (self._enabled, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5), 0),
+ (self._uninstall, 0, wx.ALIGN_CENTER_VERTICAL),
+ (self._config, 0, wx.ALIGN_CENTER_VERTICAL)])
+ csizer.AddMany([(tsizer, 1, wx.EXPAND), ((3, 3), 0),
+ (self._desc, 0), ((3, 3), 0),
+ (bsizer, 0, wx.EXPAND)])
+
+ # Finish Layout
+ hsizer.AddMany([((5, 5), 0), (csizer, 1, wx.EXPAND), ((5, 5), 0)])
+ vsizer.AddMany([((4, 4), 0), (hsizer, 0, wx.EXPAND), ((4, 4), 0)])
+ self.SetSizer(vsizer)
+ self.SetAutoLayout(True)
+
+ def GetInstallPath(self):
+ """Get the path of the plugin
+ @return: string
+
+ """
+ if self._pdata is not None:
+ dist = self._pdata.GetDist()
+ if dist is not None:
+ return dist.location
+ return u''
+
+ def GetPluginName(self):
+ """Get the name of the plugin
+ @return: string
+
+ """
+ return self._title.GetLabel()
+
+ def GetVersionString(self):
+ """Get the version of the plugin
+ @return: string
+
+ """
+ return self._version.GetLabel()
+
+ def OnConfigButton(self, evt):
+ """Handle when the configuration button is hit."""
+ if self._module is not None:
+ cfg_obj = self._module.GetConfigObject()
+ event = ed_event.NotificationEvent(ed_event.edEVT_NOTIFY,
+ ed_glob.ID_PREF, cfg_obj)
+ wx.PostEvent(self.GetParent(), event)
+
+ def OnUninstallButton(self, evt):
+ """Uninstall the plugin"""
+ msg = _("Are you sure you want to uninstall %s?\nThis cannot be undone.")
+ result = wx.MessageBox(msg % self.GetPluginName(),
+ _("Uninstall Plugin"),
+ wx.OK|wx.CANCEL|wx.ICON_WARNING)
+ if result == wx.OK:
+ self.Enable(False)
+ self._desc.SetLabel(_("This plugin will be uninstalled on next program launch."))
+ self._enabled.SetValue(False)
+ pname = self._title.GetLabel()
+ event = ed_event.NotificationEvent(ed_event.edEVT_NOTIFY, self.GetId(),
+ (pname, False), self)
+ wx.PostEvent(self.GetParent(), event)
+ plist = Profile_Get('UNINSTALL_PLUGINS', default=list())
+ plist.append(self.GetInstallPath())
+ Profile_Set('UNINSTALL_PLUGINS', plist)
+ else:
+ return
+
+ def OnCheck(self, evt):
+ """Notify container of changes to state of plugin"""
+ enabled = self._enabled.GetValue()
+ self._config.Enable(enabled)
+ pname = self._title.GetLabel()
+ event = ed_event.NotificationEvent(ed_event.edEVT_NOTIFY, self.GetId(),
+ (pname, enabled), self)
+ wx.PostEvent(self.GetParent(), event)
+
+ def SetChecked(self, check=True):
+ """Set the checkbox
+ @param check: bool
+
+ """
+ self._enabled.SetValue(check)
+ self._config.Enable(check)
+
+#-----------------------------------------------------------------------------#
+
+class PBDownloadItem(PBPluginItem):
+ """PanelBox Item to display download information about a plugin."""
+ def __init__(self, parent, pdata, bmp=None):
+ """Create the PanelBoxItem
+ @param parent: L{PanelBox}
+ @param pdata: PluginData
+ @keyword bmp: Plugin Icon
+
+ """
+ super(PBDownloadItem, self).__init__(parent, None, pdata, bmp=bmp)
+
+ # Setup
+ self._uninstall.Hide()
+ self._enabled.SetLabel(_("Download"))
+ self.Layout()
+
+#-----------------------------------------------------------------------------#
+
+class PluginErrorItem(eclib.PanelBoxItemBase):
+ """PanelBox Item to display configuration information about a plugin."""
+ def __init__(self, parent, pdata, msg, bmp):
+ """Create the PanelBoxItem
+ @param parent: L{PanelBox}
+ @param pdata: PluginData
+ @param msg: error msg
+ @param bmp: Bitmap
+
+ """
+ super(PluginErrorItem, self).__init__(parent)
+
+ # Attributes
+ self._bmp = bmp
+ self._title = wx.StaticText(self, label=pdata.GetName())
+ self._version = wx.StaticText(self, label=pdata.GetVersion())
+ self._msg = wx.StaticText(self, label=msg)
+ self._auth = wx.StaticText(self, label=_("Author: %s") % pdata.GetAuthor())
+
+ # Setup
+ font = self._title.GetFont()
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ self._title.SetFont(font)
+ self._version.SetFont(font)
+
+ if wx.Platform == '__WXMAC__':
+ self._msg.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+ self._auth.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+
+ # Layout
+ self.__DoLayout()
+
+ def __DoLayout(self):
+ """Layout the panel"""
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ # Left side Bitmap and Checkbox
+ hsizer.Add((5, 5), 0)
+ if self._bmp is not None:
+ self._bmp = wx.StaticBitmap(self, bitmap=self._bmp)
+ hsizer.Add(self._bmp, 0, wx.ALIGN_CENTER_VERTICAL)
+
+ # Central area main content
+ csizer = wx.BoxSizer(wx.VERTICAL)
+ tsizer = wx.BoxSizer(wx.HORIZONTAL)
+ tsizer.AddMany([(self._title, 0), ((20, -1), 1, wx.EXPAND),
+ (self._version, 0, wx.ALIGN_RIGHT)])
+
+ bsizer = wx.BoxSizer(wx.HORIZONTAL)
+ bsizer.AddMany([(self._auth, 0)])
+ csizer.AddMany([(tsizer, 1, wx.EXPAND), ((3, 3), 0),
+ (self._msg, 0), ((3, 3), 0),
+ (bsizer, 0, wx.EXPAND)])
+
+ # Finish Layout
+ hsizer.AddMany([((5, 5), 0), (csizer, 1, wx.EXPAND), ((5, 5), 0)])
+ vsizer.AddMany([((4, 4), 0), (hsizer, 0, wx.EXPAND), ((4, 4), 0)])
+ self.SetSizer(vsizer)
+ self.SetAutoLayout(True)
+
+#-----------------------------------------------------------------------------#
+
+class PluginData(plugin.PluginData):
+ """Plugin Metadata storage class used to store data
+ about plugins and where to download them from
+ @see: plugin.PluginData
+
+ """
+ def __init__(self, name=u'', descript=u'', \
+ author=u'', ver=u'', url=u''):
+ """Extends PluginData to include information about url to get it from.
+ @keyword name: Plugin name
+ @keyword descript: Plugin short description
+ @keyword author: Plugin Author Name
+ @keyword ver: Plugin Version (Unicode)
+ @keyword url: url to download plugin from
+
+ """
+ super(PluginData, self).__init__(name, descript, author, ver)
+
+ # Attributes
+ self._url = url
+
+ def GetUrl(self):
+ """Returns the URL of the plugin
+ @return: url string of plugins location
+
+ """
+ return self._url
+
+ def SetUrl(self, url):
+ """Sets the url of the plugin.
+ @param url: fully qualified url string
+
+ """
+ if not isinstance(url, basestring):
+ try:
+ url = str(url)
+ except (TypeError, ValueError):
+ url = u''
+ self._url = url
+
+#-----------------------------------------------------------------------------#
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugin.py
new file mode 100644
index 0000000..de6a669
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugin.py
@@ -0,0 +1,877 @@
+###############################################################################
+# Name: plugin.py #
+# Purpose: Plugin system architecture #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+#
+# Some of the code in this document was derived from trac's plugin architecture
+#
+# Copyright (C) 2003-2006 Edgewall Software
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. The name of the author may not be used to endorse or promote
+# products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""
+This module provides the core functionality of the plugin system for Editra.
+Its design is influenced by the system used in the web based project management
+software Trac (trac.edgewall.org). To create a plugin plugin class must derive
+from Plugin and in the class definintion it must state which Interface it
+Implements. Interfaces are defined throughout various locations in the core
+Editra code. The interface defines the contract that the plugin needs to
+conform to.
+
+Plugins consist of python egg files that can be created with the use of the
+setuptools package.
+
+There are some issues I dont like with how this is currently working that I
+hope to find a work around for in later revisions. Namely I dont like the fact
+that the plugins are loaded and kept in memory even when they are not activated.
+Although the footprint of the non activated plugin class members being held in
+memory is not likely to be very large.
+
+@summary: Plugin interface and mananger implementation
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: plugin.py 71475 2012-05-18 04:22:28Z CJP $"
+__revision__ = "$Revision: 71475 $"
+
+#--------------------------------------------------------------------------#
+# Dependancies
+import os
+import sys
+import shutil
+import wx
+
+# Editra Libraries
+import ed_glob
+from ed_txt import EncodeString
+import util
+from profiler import CalcVersionValue, Profile_Get, Profile_Set
+
+# Try to use the system version of pkg_resources if available else fall
+# back to the bundled version. Mostly for binary versions of Editra.
+try:
+ import pkg_resources
+except ImportError:
+ try:
+ from extern import pkg_resources
+ except ImportError:
+ pkg_resources = None
+
+#--------------------------------------------------------------------------#
+# Globals
+ENTRYPOINT = 'Editra.plugins'
+PLUGIN_CONFIG = "plugin.cfg"
+_implements = []
+
+_ = wx.GetTranslation
+
+#--------------------------------------------------------------------------#
+
+class Interface(object):
+ """Base class for defining interfaces. Interface classes are
+ used to define the method/contract from which the plugin must
+ conform to.
+
+ """
+ pass
+
+#-----------------------------------------------------------------------------#
+
+class ExtensionPoint(property):
+ """Declares what L{Interface} a plugin is extending"""
+ def __init__(self, interface):
+ """Initializes the extension point
+ @param interface: interface object that the extension point extends
+
+ """
+ property.__init__(self, self.Extensions)
+ self.interface = interface
+
+ def __repr__(self):
+ """@return: string representation of the object"""
+ return '<ExtensionPoint %s>' % self.interface.__name__
+
+ def Extensions(self, component):
+ """The exensions that extend this extention point
+ @param component: The component to get the exensions for
+ @return: a list of plugins that declare to impliment the
+ given extension point.
+
+ """
+ component = wx.GetApp().GetPluginManager()
+ extensions = PluginMeta._registry.get(self.interface, [])
+ return filter(None, [component[cls] for cls in extensions])
+
+#-----------------------------------------------------------------------------#
+
+class PluginMeta(type):
+ """Acts as the registration point for plugin entrypoint objects.
+ It makes sure that only a single instance of any particular entry
+ point is active at one time per plugin manager.
+
+ """
+ _plugins = list()
+ _registry = dict()
+
+ def __new__(mcs, name, bases, d):
+ """Initialize the MetaClass
+ @param mcs: Class instance
+ @param name: Name of object
+ @param bases: Plugin base classes
+ @param d: Items dictionary
+
+ """
+ d['_implements'] = _implements[:]
+ del _implements[:]
+ new_obj = type.__new__(mcs, name, bases, d)
+ if name == 'Plugin':
+ return new_obj
+
+ init = d.get("__init__")
+ if not init:
+ for init in [b.__init__._original for b in new_obj.mro()
+ if issubclass(b, Plugin) and '__init__' in b.__dict__]:
+ break
+
+ PluginMeta._plugins.append(new_obj)
+ for interface in d.get('_implements', []):
+ PluginMeta._registry.setdefault(interface, []).append(new_obj)
+
+ for base in [base for base in bases if hasattr(base, '_implements')]:
+ for interface in base._implements:
+ PluginMeta._registry.setdefault(interface, []).append(new_obj)
+ return new_obj
+
+#-----------------------------------------------------------------------------#
+
+class Plugin(object):
+ """Base class for all plugin type objects"""
+ __metaclass__ = PluginMeta
+ __name__ = 'EdPlugin'
+
+ def __new__(cls, pluginmgr):
+ """Only one instance of each plugin is allowed to exist
+ per manager. If an instance of this plugin has already be
+ initialized, that instance will be returned. If not this will
+ initialize a new instance of the plugin.
+ @param cls: Class object
+ @keyword pluginmgr: Plugin Manager instance
+ @return: a new class object or an existing instance if one
+ exists.
+
+ """
+ # Case for a pluginmanager being managed by a plugin manager
+ if issubclass(cls, PluginManager):
+ self = super(Plugin, cls).__new__(cls)
+ self.pluginmgr = self
+ return self
+
+ plugins = pluginmgr.GetPlugins()
+ self = plugins.get(cls)
+
+ # Check if it is a default plugin
+ if self is None:
+ defaults = pluginmgr.GetDefaultPlugins()
+ self = defaults.get(cls)
+
+ if self is None:
+ self = super(Plugin, cls).__new__(cls)
+ self.pluginmgr = pluginmgr
+ return self
+
+ def GetMinVersion(self):
+ """Override in subclasses to return the minimum version of Editra that
+ the plugin is compatible with. By default it will return the current
+ version of Editra.
+ @return: version str
+
+ """
+ return ed_glob.VERSION
+
+ def InstallHook(self):
+ """Override in subclasses to allow the plugin to be loaded
+ dynamically.
+ @return: None
+
+ """
+ pass
+
+ def IsInstalled(self):
+ """Return whether the plugins L{InstallHook} method has been called
+ or not already.
+ @return: bool
+
+ """
+ return False
+
+#-----------------------------------------------------------------------------#
+
+class PluginConfigObject(object):
+ """Plugin configuration object. Plugins that wish to provide a
+ configuration panel should implement a subclass of this object
+ in their __init__ module. The __init__ module must also have a
+ function 'GetConfigObject' that returns an instance of this
+ class.
+
+ """
+ def GetConfigPanel(self, parent):
+ """Get the configuration panel for this plugin
+ @param parent: parent window for the panel
+ @return: wxPanel
+
+ """
+ raise NotImplementedError
+
+ def GetBitmap(self):
+ """Get the 32x32 bitmap to show in the config dialog
+ @return: wx.Bitmap
+ @note: Optional if not implemented default icon will be used
+
+ """
+ return wx.NullBitmap
+
+ def GetLabel(self):
+ """Get the display label for the configuration
+ @return: string
+
+ """
+ raise NotImplementedError
+
+#-----------------------------------------------------------------------------#
+
+class PluginData(object):
+ """A storage class for representing data about a Plugin
+ @see: L{Plugin}
+
+ """
+ def __init__(self, name=u'', descript=u'', author=u'', ver=u''):
+ """Create the plugin data object
+ @keyword name: Name of the plugin
+ @keyword descript: Short description of plugin
+ @keyword author: Who made the plugin
+ @keyword ver: Version of the plugin (Unicode)
+
+ """
+ super(PluginData, self).__init__()
+
+ # Attributes
+ self._name = name
+ self._description = descript
+ self._author = author
+ self._version = ver
+
+ self._enabled = False
+ self._installed = True
+
+ self._inst = None
+ self._cls = None
+ self._distro = None
+
+ @property
+ def Distribution(self):
+ """Distrobution object"""
+ return self.GetDist()
+
+ @property
+ def Class(self):
+ """Class Reference"""
+ return self.GetClass()
+
+ def Enable(self, enable=True):
+ """Enable the plugin
+ @param enable: bool
+
+ """
+ self._enabled = enabled
+
+ def GetAuthor(self):
+ """@return: Author of the plugin"""
+ return self._author
+
+ def GetClass(self):
+ """@return class object of the plugin"""
+ return self._cls
+
+ def GetDescription(self):
+ """@return: Plugins description string"""
+ return self._description
+
+ def GetDist(self):
+ """Return the dist object associated with this plugin
+ @return: Distribution
+
+ """
+ return self._distro
+
+ def GetInstance(self):
+ """Get the plugin instance
+ @return: Plugin
+
+ """
+ return self._inst
+
+ def GetName(self):
+ """@return: Plugin's name string"""
+ return self._name
+
+ def GetVersion(self):
+ """@return: Plugin's version string"""
+ return self._version
+
+ @property
+ def Instance(self):
+ """Plugin Instance"""
+ return self.GetInstance()
+
+ def IsEnabled(self):
+ """Is the plugin enabled
+ @return: bool
+
+ """
+ return self._enabled
+
+ @property
+ def Module(self):
+ """Plugin Module Reference"""
+ return getattr(self.GetInstance(), '__module__', None)
+
+ def SetAuthor(self, author):
+ """Sets the author attribute
+ @param author: New Authors name string
+ @postcondition: Author attribute is set to new value
+
+ """
+ if not isinstance(author, basestring):
+ try:
+ author = str(author)
+ except (ValueError, TypeError):
+ author = u''
+ self._author = author
+
+ def SetClass(self, cls):
+ """Set the class used to create this plugins instance
+ @param cls: class
+
+ """
+ self._cls = cls
+
+ def SetDescription(self, descript):
+ """@return: Plugins description string"""
+ if not isinstance(descript, basestring):
+ try:
+ descript = str(descript)
+ except (ValueError, TypeError):
+ descript = u''
+ self._description = descript
+
+ def SetDist(self, distro):
+ """Set the distribution object
+ @param distro: Distribution
+
+ """
+ self._distro = distro
+
+ def SetInstance(self, inst):
+ """Set the plugin instance
+ @param inst: Plugin instance
+
+ """
+ self._inst = inst
+
+ def SetName(self, name):
+ """Sets the plugins name string
+ @param name: String to name plugin with
+ @postcondition: Plugins name string is set
+
+ """
+ if not isinstance(name, basestring):
+ try:
+ name = str(name)
+ except (ValueError, TypeError):
+ name = u''
+ self._name = name
+
+ def SetVersion(self, ver):
+ """Sets the version attribute of the plugin.
+ @param ver: Version string
+ @postcondition: Plugins version attribute is set to new value
+
+ """
+ if not isinstance(ver, basestring):
+ try:
+ ver = str(ver)
+ except (ValueError, TypeError):
+ ver = u''
+ self._version = ver
+
+#-----------------------------------------------------------------------------#
+
+def Implements(*interfaces):
+ """Used by L{Plugin}s to declare the interface that they
+ implment/extend.
+ @param interfaces: list of interfaces the plugin implements
+
+ """
+ _implements.extend(interfaces)
+
+#--------------------------------------------------------------------------#
+
+class PluginManager(object):
+ """The PluginManger keeps track of the active plugins. It
+ also provides an interface into loading and unloading plugins.
+ @todo: Allow loaded but inactive plugins to be initiated without
+ needing to restart the editor.
+
+ """
+ def __init__(self):
+ """Initializes a PluginManager object.
+ @postcondition: Plugin manager and plugins are initialized
+
+ """
+ object.__init__(self)
+ self.LOG = wx.GetApp().GetLog()
+ self.RemoveUninstalled()
+
+ self._config = self.LoadPluginConfig() # Enabled/Disabled Plugins
+ self._pi_path = list(set([ed_glob.CONFIG['PLUGIN_DIR'],
+ ed_glob.CONFIG['SYS_PLUGIN_DIR']]))
+ sys.path.extend(self._pi_path)
+ self._env = self.CreateEnvironment(self._pi_path)
+
+ # TODO: Combine enabled into pdata
+ self._pdata = dict() # Plugin data
+ self._defaults = dict() # Default plugins
+ self._enabled = dict() # Set of enabled plugins
+ self._loaded = list() # List of
+ self._obsolete = dict() # Obsolete plugins list
+
+ self.InitPlugins(self._env)
+ self.RefreshConfig()
+
+ # Enable/Disable plugins based on config data
+ self.UpdateConfig()
+
+ def __contains__(self, cobj):
+ """Returns True if a plugin is currently loaded and being
+ managed by this manager.
+ @param cobj: object to look for in loaded plugins
+
+ """
+ return cobj in [obj.GetClass() for obj in self._pdata]
+
+ def __getitem__(self, cls):
+ """Gets and returns the instance of given class if it has
+ already been activated.
+ @param cls: class object to get from metaregistery
+ @return: returns either None or the intialiazed class object
+
+ """
+ nspace = cls.__module__ + "." + cls.__name__
+ if nspace in ed_glob.DEFAULT_PLUGINS:
+ self._enabled[cls] = True
+
+ if cls not in self._enabled:
+ self._enabled[cls] = False # If its a new plugin disable by default
+
+ if not self._enabled[cls]:
+ return None
+
+# plugin = self._plugins.get(cls)
+ plugin = None
+ pdata = self._pdata.get(cls, None)
+ if pdata is not None:
+ plugin = pdata.GetInstance()
+ else:
+ # Check defaults
+ plugin = self._defaults.get(cls, None)
+
+ # Plugin not instantiated yet
+ if plugin is None:
+ if cls not in PluginMeta._plugins:
+ self.LOG("[pluginmgr][err] %s Not Registered" % cls.__name__)
+ try:
+ plugin = cls(self)
+ except (AttributeError, TypeError), msg:
+ self.LOG("[pluginmgr][err] Unable in initialize plugin")
+ self.LOG("[pluginmgr][err] %s" % str(msg))
+
+ return plugin
+
+ #---- End Private Members ----#
+
+ #---- Public Class Functions ----#
+ def AppendPath(self, path):
+ """Append a path to the environment path for the plugin manager
+ to look for plugins on. The path is only added to the environment
+ in order for it to be used you must call RefreshEnvironment afterwards
+ to re-initialize the running environment.
+
+ @param path: path to append to environment
+ @return: True if path was successfully added or False otherwise
+
+ """
+ if os.path.exists(path):
+ if path not in self._pi_path:
+ self._pi_path.append(path)
+ return True
+ else:
+ return False
+
+ def CreateEnvironment(self, path):
+ """Creates the environment based on the passed
+ in path list
+ @param path: path(s) to scan for extension points
+ @note: pkgutils does not like Unicode! only send encoded strings
+
+ """
+ if pkg_resources != None:
+ path = [ EncodeString(pname, sys.getfilesystemencoding())
+ for pname in path ]
+
+ try:
+ env = pkg_resources.Environment(path)
+ except UnicodeDecodeError, msg:
+ self.LOG("[pluginmgr][err] %s" % msg)
+ else:
+ self.LOG("[pluginmgr][warn] setuptools is not installed")
+ env = dict()
+ return env
+
+ def DisablePlugin(self, plugin):
+ """Disables a named plugin. Is a convenience function for
+ EnablePlugin(plugin, False).
+
+ @param plugin: plugin to disable
+ @precondition: plugin must be managed by this manager instance
+ @postcondition: plugin is disabled and will not be activated on
+ next reload.
+
+ """
+ self.EnablePlugin(plugin, False)
+
+ def EnablePlugin(self, plugin, enable=True):
+ """Enables a named plugin.
+ @param plugin: plugin to enable/disable (case insensitive)
+ @param enable: should plugin be enabled or disabled
+ @precondition: plugin must be managed by this manager instance
+ @postcondition: plugin is added to activate list for activation on
+ next program start.
+
+ """
+ for name in self._config:
+ if name.lower() == plugin.lower():
+ plugin = name
+ break
+
+ self._config[plugin] = enable
+ for cls in self._enabled:
+ if cls.__module__ == plugin:
+ self._enabled[cls] = enable
+
+ def GetConfig(self):
+ """Returns a dictionary of plugins and there configuration state.
+ @return: the mapped set of available plugins (dict)
+
+ """
+ self.RefreshConfig()
+ return self._config
+
+ def GetDefaultPlugins(self):
+ """Get the loaded default plugins
+ @return: dict(cls=instance)
+
+ """
+ return self._defaults
+
+ def GetEnvironment(self):
+ """Returns the environment that the plugin manager is currently
+ running with.
+ @return: the managers environment
+
+ """
+ return self._env
+
+ def GetIncompatible(self):
+ """Get the list of loaded plugins that are incompatible with the
+ current running version of Editra.
+ return: dict(name=module)
+
+ """
+ return self._obsolete
+
+ def GetPlugins(self):
+ """Returns a the dictionary of plugins managed by this manager
+ @return: all plugins managed by this manger (dict)
+
+ """
+ plugins = dict()
+ for pdata in self._pdata.values():
+ plugins[pdata.GetClass()] = pdata.GetInstance()
+ return plugins
+
+ def GetPluginDistro(self, pname):
+ """Get the distrobution object for a given plugin name
+ @param pname: plugin name
+ @return: Distrobution
+
+ """
+ for pdata in self._pdata.values():
+ if pname.lower() == pdata.GetName().lower():
+ return pdata.GetDist()
+ else:
+ return None
+
+ def GetPluginDistros(self):
+ """Get the plugin distrobution objects
+ @return: dict(name=Distrobution)
+
+ """
+ distros = dict()
+ for name, pdata in self._pdata:
+ distros[name] = pdata.GetDist()
+ return distros
+
+ def InitPlugins(self, env):
+ """Initializes the plugins that are contained in the given
+ environment. After calling this the list of available plugins
+ can be obtained by calling GetPlugins.
+ @note: plugins must emit the ENTRY_POINT defined in this file in order
+ to be recognized and initialized.
+ @postcondition: all plugins in the environment are initialized
+
+ """
+ if pkg_resources is None:
+ return
+
+ pkg_env = env
+ tmploaded = [ name.lower() for name in self._loaded ]
+ for name in pkg_env:
+ self.LOG("[pluginmgr][info] Found plugin: %s" % name)
+ if name.lower() in tmploaded:
+ self.LOG("[pluginmgr][info] %s is already loaded" % name)
+ continue
+
+ egg = pkg_env[name][0] # egg is of type Distribution
+ egg.activate()
+ editra_version = CalcVersionValue(ed_glob.VERSION)
+ for name in egg.get_entry_map(ENTRYPOINT):
+ try:
+ # Only load a given entrypoint once
+ if name not in self._loaded:
+ entry_point = egg.get_entry_info(ENTRYPOINT, name)
+ cls = entry_point.load()
+ self._loaded.append(name)
+ else:
+ self.LOG("[pluginmgr][info] Skip reloading: %s" % name)
+ continue
+ except Exception, msg:
+ self.LOG("[pluginmgr][err] Couldn't Load %s: %s" % (name, msg))
+ else:
+ try:
+ # Only initialize plugins that haven't already been
+ # initialized
+ if cls not in self._pdata:
+ self.LOG("[pluginmgr][info] Creating Instance of %s" % name)
+ instance = cls(self)
+ minv = CalcVersionValue(instance.GetMinVersion())
+ if minv <= editra_version:
+ mod = instance.__module__
+ desc = getattr(mod, '__doc__', _("No Description Available"))
+ auth = getattr(mod, '__author__', _("Unknown"))
+ pdata = PluginData(egg.project_name,
+ desc.strip(),
+ auth.strip(),
+ egg.version)
+ pdata.SetDist(egg)
+ pdata.SetInstance(instance)
+ pdata.SetClass(cls)
+ self._pdata[cls] = pdata
+ self.LOG("[pluginmgr][info] Cached Plugin: %s" % egg.project_name)
+ else:
+ # Save plugins that are not compatible with
+ # this version to use for notifications.
+ self._obsolete[name] = cls.__module__
+ else:
+ self.LOG("[pluginmgr][info] Skip re-init of %s" % cls)
+ finally:
+ pass
+
+ # Activate all default plugins
+ for d_pi in ed_glob.DEFAULT_PLUGINS:
+ obj = d_pi.split(".")
+ mod = ".".join(obj[:-1])
+ entry = __import__(mod, globals(), globals(), ['__name__'])
+ if hasattr(entry, obj[-1]) and entry not in self._defaults:
+ entry = getattr(entry, obj[-1])
+ self._defaults[entry] = entry(self)
+
+ return True
+
+ def LoadPluginByName(self, name):
+ """Loads a named plugin.
+ @todo: Implement this method
+
+ """
+ raise NotImplementedError
+
+ def LoadPluginConfig(self):
+ """Loads the plugin config file for the current user if
+ it exists. The configuration file contains which plugins
+ are active and which ones are not.
+ @return: configuration dictionary
+
+ """
+ config = dict()
+ reader = util.GetFileReader(os.path.join(ed_glob.CONFIG['CONFIG_DIR'],
+ PLUGIN_CONFIG))
+ if reader == -1:
+ self.LOG("[pluginmgr][err] Failed to read plugin config file")
+ return config
+
+ reading = True
+ for line in reader.readlines():
+ data = line.strip()
+ if len(data) and data[0] == u"#":
+ continue
+
+ data = data.split(u"=")
+ if len(data) == 2:
+ config[data[0].strip()] = data[1].strip().lower() == u"true"
+ else:
+ continue
+
+ reader.close()
+ return config
+
+ def RefreshConfig(self):
+ """Refreshes the config data comparing the loadable
+ plugins against the config data and removing any entries
+ that dont exist in both from the configuration data.
+ @postcondition: entries that could not be loaded or do not
+ exist any longer are removed from the config
+
+ """
+ plugins = [ plugin.GetInstance().__module__
+ for plugin in self._pdata.values() ]
+
+ config = dict()
+ for item in self._config:
+ if item in plugins:
+ config[item] = self._config[item]
+ self._config = config
+
+ def RefreshEnvironment(self):
+ """Refreshes the current environment to include any
+ plugins that may have been added since init.
+ @postcondition: environment is refreshed
+
+ """
+ self._env = self.CreateEnvironment(self._pi_path)
+
+ def ReInit(self):
+ """Reinitializes the plugin environment and all plugins
+ in the environment as well as the configuration data.
+ @postcondition: the manager is reinitialized to reflect
+ any configuration or environment changes
+ that may have occured.
+
+ """
+ self.RefreshEnvironment()
+ self.InitPlugins(self.GetEnvironment())
+ self.RefreshConfig()
+ self.UpdateConfig()
+
+ def RemoveUninstalled(self):
+ """Remove all uninstalled plugins
+ @todo: need error reporting and handling file permissions
+ @todo: handle multiple older versions that are installed
+ @todo: handle when installed in multiple locations
+
+ """
+ plist = Profile_Get('UNINSTALL_PLUGINS', default=list())
+ for path in list(plist):
+ try:
+ if os.path.isdir(path):
+ shutil.rmtree(path)
+ else:
+ os.remove(path)
+ except OSError:
+ # TODO: don't delete from list, so it can be kept to report
+ # removal errors to user.
+ if not os.path.exists(path):
+ plist.remove(path)
+ continue
+ else:
+ self.LOG("[pluginmgr][info] Uninstalled: %s" % path)
+ plist.remove(path)
+ Profile_Set('UNINSTALL_PLUGINS', plist)
+
+ def UnloadPluginByName(self, name):
+ """Unloads a named plugin.
+ @todo: implement this method
+
+ """
+ raise NotImplementedError
+
+ def UpdateConfig(self):
+ """Updates the in memory config data to recognize
+ any plugins that may have been added or initialzed
+ by a call to InitPlugins.
+ @postcondition: plugins are enabled or disabled based
+ on the configuration data.
+
+ """
+ for pdata in self._pdata.values():
+ plugin = pdata.GetClass()
+ if self._config.get(plugin.__module__):
+ self._enabled[plugin] = True
+ else:
+ self._config[plugin.__module__] = False
+ self._enabled[plugin] = False
+
+ def WritePluginConfig(self):
+ """Writes out the plugin config.
+ @postcondition: the configuration data is saved to disk
+
+ """
+ writer = util.GetFileWriter(os.path.join(ed_glob.CONFIG['CONFIG_DIR'],
+ PLUGIN_CONFIG))
+ if writer == -1:
+ self.LOG("[pluginmgr][err] Failed to write plugin config")
+ return
+
+ writer.write("# Editra %s Plugin Config\n#\n" % ed_glob.VERSION)
+ for item in self._config:
+ writer.write("%s=%s\n" % (item, str(self._config[item])))
+ writer.write("\n# EOF\n")
+ writer.close()
+ return
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/prefdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/prefdlg.py
new file mode 100644
index 0000000..ac0e6bf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/prefdlg.py
@@ -0,0 +1,2212 @@
+###############################################################################
+# Name: prefdlg.py #
+# Purpose: UI for configuring User Profile #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+The classes and functions contained in this file are used for creating the
+preference dialog that allows for dynamically configuring most of the options
+and setting of the program by setting values in the Profile.
+
+@summary: Editra's Preference Dialog
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: prefdlg.py 72221 2012-07-28 15:28:31Z CJP $"
+__revision__ = "$Revision: 72221 $"
+
+#----------------------------------------------------------------------------#
+# Dependencies
+import wx
+import wx.lib.mixins.listctrl as listmix
+import encodings
+import os
+import sys
+
+# Editra Libraries
+import ed_glob
+import profiler
+from profiler import Profile_Get, Profile_Set
+import ed_i18n
+import ed_event
+import ed_crypt
+import updater
+import util
+import syntax.syntax as syntax
+import ed_msg
+import ed_txt
+import eclib
+import ed_menu
+import extern.stcspellcheck as stcspellcheck
+
+#----------------------------------------------------------------------------#
+# Globals
+ID_CHECK_UPDATE = wx.NewId()
+ID_DOWNLOAD = wx.NewId()
+ID_UPDATE_MSG = wx.NewId()
+
+ID_PREF_BKUP_PATH = wx.NewId()
+ID_PREF_BKUP_SUFFIX = wx.NewId()
+ID_PREF_BKUP_LBL = wx.NewId()
+ID_PREF_AUTO_SPELL = wx.NewId()
+ID_PREF_SPELL_DICT = wx.NewId()
+ID_PREF_ENCHANT_PATH = wx.NewId()
+
+_ = wx.GetTranslation
+#----------------------------------------------------------------------------#
+# Utility
+
+def MakeThemeTool(tool_id):
+ """Makes a themed bitmap for the tool book of the pref dialog.
+ @param tool_id: An art identifier id
+ @return: 32x32 bitmap
+
+ """
+ osize = Profile_Get('ICON_SZ', 'size_tuple', (24, 24))
+ Profile_Set('ICON_SZ', (32, 32))
+ over = wx.ArtProvider.GetBitmap(str(tool_id), wx.ART_TOOLBAR)
+ Profile_Set('ICON_SZ', osize)
+ return over
+
+#----------------------------------------------------------------------------#
+
+class PreferencesPanelBase(object):
+ """Base mixin class for preference panels"""
+ def __init__(self):
+ super(PreferencesPanelBase, self).__init__()
+
+ # Attributes
+ self._layout_done = False
+
+ def DoSelected(self):
+ """Handle initial selection to create controls"""
+ if not self._layout_done:
+ self._layout_done = True
+ self._DoLayout()
+ self.SetAutoLayout(True)
+
+#----------------------------------------------------------------------------#
+
+class PreferencesDialog(wx.Frame):
+ """Preference dialog for configuring the editor
+ @summary: Provides an interface into configuring profile settings
+
+ """
+ __name__ = u'PreferencesDialog'
+
+ def __init__(self, parent, id_=wx.ID_ANY,
+ style=wx.DEFAULT_DIALOG_STYLE | wx.TAB_TRAVERSAL):
+ """Initializes the preference dialog
+ @param parent: The parent window of this window
+ @keyword id_: The id of this window
+ @keyword style: Window Style bitmask
+
+ """
+ super(PreferencesDialog, self).__init__(parent, id_,
+ _("Preferences - Editra"),
+ style=style)
+ util.SetWindowIcon(self)
+
+ # Extra Styles
+ self.SetTransparent(Profile_Get('ALPHA', default=255))
+
+ # Attributes
+ self._accel = wx.AcceleratorTable([(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, wx.ID_CLOSE)])
+ self.SetAcceleratorTable(self._accel)
+ self._tbook = PrefTools(self)
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ # Layout
+ sizer.Add(self._tbook, 1, wx.EXPAND)
+ self.SetSizer(sizer)
+ self.SetAutoLayout(True)
+ self.SetInitialSize()
+ wx.GetApp().RegisterWindow(repr(self), self, True)
+
+ # Bind Events
+ self.Bind(wx.EVT_MENU, lambda evt: self.Close(), id=wx.ID_CLOSE)
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.Bind(wx.EVT_SHOW, self.OnShow)
+
+ def OnClose(self, evt):
+ """Hanles the window closer event
+ @param evt: Event that called this handler
+
+ """
+ # XXX More strange wx is None errors have been reported here
+ # really need to find the cause of this!
+ if wx is not None:
+ wx.GetApp().UnRegisterWindow(repr(self))
+
+ # Save profile settings
+ profiler.TheProfile.Write(profiler.Profile_Get('MYPROFILE'))
+
+ evt.Skip()
+
+ def OnShow(self, evt):
+ """Hanles the window closer event
+ @param evt: Event that called this handler
+
+ """
+ self._tbook.OnPageChanged()
+ evt.Skip()
+
+#-----------------------------------------------------------------------------#
+
+class PrefTools(eclib.SegmentBook):
+ """Main sections of the configuration pages
+ @note: implements the top level book control for the prefdlg
+
+ """
+ GENERAL_PG = 0
+ APPEAR_PG = 1
+ DOC_PG = 2
+ UPDATE_PG = 3
+ ADV_PG = 4
+
+ def __init__(self, parent):
+ """Initializes the main book control of the preferences dialog
+ @summary: Creates the top level notebook control for the prefdlg
+ a toolbar is used for changing pages.
+
+ """
+ super(PrefTools, self).__init__(parent, wx.ID_ANY,
+ style=eclib.SEGBOOK_STYLE_LABELS|\
+ eclib.SEGBOOK_STYLE_NO_DIVIDERS)
+
+ # Attributes
+ self._imglst = list()
+ self.__InitImgList()
+
+ self.AddPage(GeneralPanel(self), _("General"),
+ img_id=self.GENERAL_PG)
+ self.AddPage(AppearancePanel(self), _("Appearance"),
+ img_id=self.APPEAR_PG)
+ self.AddPage(DocumentPanel(self), _("Document"),
+ img_id=self.DOC_PG)
+ self.AddPage(NetworkPanel(self), _("Network"),
+ img_id=self.UPDATE_PG)
+ self.AddPage(AdvancedPanel(self), _("Advanced"),
+ img_id=self.ADV_PG)
+
+ # Event Handlers
+ self.Bind(eclib.EVT_SB_PAGE_CHANGED, self.OnPageChanged)
+ self.Bind(eclib.EVT_SB_PAGE_CHANGING, self.OnPageChanging)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+
+ # Message Handlers
+ ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED)
+
+ def OnDestroy(self, evt):
+ """Cleanup message handlers when destroyed"""
+ if evt.GetId() == self.GetId():
+ ed_msg.Unsubscribe(self.OnThemeChange)
+ evt.Skip()
+
+ def __InitImgList(self):
+ """Setup the image list for the SegmentBook"""
+ dorefresh = False
+ if len(self._imglst):
+ del self._imglst
+ self._imglst = list()
+ dorefresh = True
+
+ self._imglst.append(MakeThemeTool(ed_glob.ID_PREF))
+ self._imglst.append(MakeThemeTool(ed_glob.ID_THEME))
+ self._imglst.append(MakeThemeTool(ed_glob.ID_DOCPROP))
+ self._imglst.append(MakeThemeTool(ed_glob.ID_WEB))
+ self._imglst.append(MakeThemeTool(ed_glob.ID_ADVANCED))
+ self.SetImageList(self._imglst)
+ self.SetUsePyImageList(True)
+
+ if dorefresh:
+ self.Refresh()
+
+ def OnPageChanging(self, evt):
+ """Handle notebook page change notifications"""
+ sel = evt.GetSelection()
+ page = self.GetPage(sel)
+ if hasattr(page, 'DoSelected'):
+ page.DoSelected()
+ evt.Skip()
+
+ def OnPageChanged(self, evt=None):
+ """Resizes the dialog based on the pages size
+ @todo: animate the resizing so its smoother
+
+ """
+ util.Log("[prefdlg][evt] toolbook page changed")
+ page = self.GetPage(self.GetSelection())
+ page.SetInitialSize()
+ parent = self.GetParent()
+ psz = page.GetSize()
+ width = psz.GetWidth()
+
+ cbar = self.GetControlBar(wx.TOP)
+ tbsz = cbar.GetBestSize()
+ if tbsz[0] > width:
+ width = tbsz[0]
+
+ with eclib.Freezer(page) as _tmp:
+ parent.SetClientSize((width, psz.GetHeight() + tbsz[1]))
+ parent.SendSizeEvent()
+ parent.Layout()
+ if evt is not None:
+ evt.Skip()
+
+ def OnThemeChange(self, msg):
+ """Update icons when the theme changes"""
+ self.__InitImgList()
+
+#-----------------------------------------------------------------------------#
+
+class GeneralPanel(wx.Panel, PreferencesPanelBase):
+ """Creates a panel with controls for Editra's general settings
+ @summary: Panel with a number of controls that affect the users
+ global profile setting for how Editra should operate.
+
+ """
+ def __init__(self, parent, style=wx.BORDER_SUNKEN):
+ """Create the panel
+ @param parent: Parent window of this panel
+ @keyword style: Window Style bitmask
+
+ """
+ wx.Panel.__init__(self, parent, style=style)
+ PreferencesPanelBase.__init__(self)
+
+ # Attributes
+ self.SetToolTipString(_("Changes made in this dialog are saved in your "
+ "current profile. Some Items such as Language "
+ "require the program to be restarted before "
+ "taking effect."))
+
+ # Layout this page right away
+ self._DoLayout()
+ self._layout_done = True
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
+ self.Bind(wx.EVT_CHOICE, self.OnChoice)
+ self.Bind(wx.EVT_COMBOBOX, self.OnChoice)
+
+ def _DoLayout(self):
+ """Add the controls and do the layout
+ @note: do not call this after __init__
+
+ """
+ # Startup Section
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ nbook = wx.Notebook(self)
+ nbook.AddPage(GeneralStartupPanel(nbook), _("Startup"))
+ nbook.AddPage(GeneralFilePanel(nbook), _("Files"))
+ sizer.AddMany([((10, 10), 0), (nbook, 1, wx.EXPAND), ((10, 10), 0)])
+ msizer = wx.BoxSizer(wx.VERTICAL)
+ msizer.AddMany([(sizer, 1, wx.EXPAND), ((10, 10), 0)])
+ self.SetSizer(msizer)
+
+ def OnCheck(self, evt):
+ """Handles events from the check boxes
+ @param evt: event that called this handler
+
+ """
+ util.Log("[prefdlg][evt] General Page: Check box clicked")
+ e_id = evt.GetId()
+ e_obj = evt.GetEventObject()
+ val = e_obj.GetValue()
+ if e_id in (ed_glob.ID_APP_SPLASH, ed_glob.ID_PREF_SPOS,
+ ed_glob.ID_SESSION,
+ ed_glob.ID_NEW_WINDOW, ed_glob.ID_PREF_CHKUPDATE,
+ ed_glob.ID_PREF_WARN_EOL, ed_glob.ID_PREF_AUTO_RELOAD):
+ Profile_Set(ed_glob.ID_2_PROF[e_id], e_obj.GetValue())
+ elif e_id == ed_glob.ID_REPORTER:
+ Profile_Set(ed_glob.ID_2_PROF[e_id], not e_obj.GetValue())
+ elif e_id == ed_glob.ID_PREF_CHKMOD:
+ Profile_Set(ed_glob.ID_2_PROF[e_id], val)
+ self.FindWindowById(ed_glob.ID_PREF_AUTO_RELOAD).Enable(val)
+ elif e_id == ed_glob.ID_PREF_AUTOBKUP:
+ Profile_Set(ed_glob.ID_2_PROF[e_id], val)
+ elif e_id == ID_PREF_AUTO_SPELL:
+ spref = Profile_Get('SPELLCHECK', default=dict())
+ spref['auto'] = val
+ Profile_Set('SPELLCHECK', spref)
+ else:
+ pass
+ evt.Skip()
+
+ @staticmethod
+ def OnChoice(evt):
+ """Handles events from the choice controls
+ @param evt: event that called this handler
+ @note: Also handles the Language ComboBox
+
+ """
+ e_id = evt.GetId()
+ e_obj = evt.GetEventObject()
+ if e_id in [ed_glob.ID_PREF_MODE,
+ ed_glob.ID_PREF_FHIST,
+ ed_glob.ID_PREF_LANG,
+ ed_glob.ID_PREF_ENCODING]:
+
+ Profile_Set(ed_glob.ID_2_PROF[e_id], e_obj.GetValue())
+ if e_id == ed_glob.ID_PREF_MODE:
+ val = e_obj.GetValue()
+ ed_glob.DEBUG = ('DEBUG' in val)
+ ed_glob.VDEBUG = ('VERBOSE' in val)
+ elif e_id == ed_glob.ID_PRINT_MODE:
+ Profile_Set(ed_glob.ID_2_PROF[e_id], e_obj.GetSelection())
+ elif e_id == ID_PREF_SPELL_DICT:
+ ssel = e_obj.GetStringSelection()
+ sprefs = Profile_Get('SPELLCHECK', default=dict())
+ sprefs['dict'] = ssel
+ Profile_Set('SPELLCHECK', sprefs)
+ else:
+ evt.Skip()
+
+#-----------------------------------------------------------------------------#
+
+class GeneralStartupPanel(wx.Panel):
+ """General Startup Settings"""
+ def __init__(self, parent):
+ super(GeneralStartupPanel, self).__init__(parent)
+
+ # Attributes
+
+ # Setup
+ self._DoLayout()
+
+ def _DoLayout(self):
+ """Do the panels layout"""
+ msizer = wx.BoxSizer(wx.HORIZONTAL)
+ msizer.AddMany([(wx.StaticText(self, label=_("Editor Mode") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (ExChoice(self, ed_glob.ID_PREF_MODE,
+ choices=['CODE', 'DEBUG', 'VERBOSE DEBUG'],
+ default=Profile_Get('MODE')),
+ 0, wx.ALIGN_CENTER_VERTICAL)])
+
+ psizer = wx.BoxSizer(wx.HORIZONTAL)
+ psizer.AddMany([(wx.StaticText(self, label=_("Printer Mode") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (ExChoice(self, ed_glob.ID_PRINT_MODE,
+ choices=GetPrintModeStrings(),
+ default=Profile_Get('PRINT_MODE')),
+ 0, wx.ALIGN_CENTER_VERTICAL)])
+
+ reporter_cb = wx.CheckBox(self, ed_glob.ID_REPORTER,
+ _("Disable Error Reporter"))
+ reporter_cb.SetValue(not Profile_Get('REPORTER'))
+ sess_cb = wx.CheckBox(self, ed_glob.ID_SESSION, _("Load Last Session"))
+ sess_cb.SetValue(Profile_Get('SAVE_SESSION', default=False))
+ sess_cb.SetToolTipString(_("Load files from last session on startup"))
+ splash_cb = wx.CheckBox(self, ed_glob.ID_APP_SPLASH,
+ _("Show Splash Screen"))
+ splash_cb.SetValue(Profile_Get('APPSPLASH'))
+
+ # Only enable update option if user has access to install directory
+ isadmin = os.access(ed_glob.CONFIG['INSTALL_DIR'], os.R_OK|os.W_OK)
+ if isadmin:
+ chk_update = wx.CheckBox(self, ed_glob.ID_PREF_CHKUPDATE,
+ _("Check for updates on startup"))
+ chk_update.SetValue(Profile_Get('CHECKUPDATE'))
+
+ # Locale
+ lsizer = wx.BoxSizer(wx.HORIZONTAL)
+ lsizer.AddMany([(wx.StaticText(self, label=_("Language") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (ed_i18n.LangListCombo(self, ed_glob.ID_PREF_LANG,
+ Profile_Get('LANG')),
+ 0, wx.ALIGN_CENTER_VERTICAL)])
+
+ # Layout items
+ sizer = wx.FlexGridSizer(11, 2, 5, 5)
+ sizer.AddMany([((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self,
+ label=_("Startup Settings") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), (msizer, 0),
+ ((5, 5),), (psizer, 0),
+ ((5, 5),), (reporter_cb, 0),
+ ((5, 5),), (sess_cb, 0),
+ ((5, 5),), (splash_cb, 0)])
+
+ if isadmin:
+ sizer.AddMany([((5, 5),), (chk_update, 0)])
+
+ sizer.AddMany([((5, 5),), ((5, 5),),
+ (wx.StaticText(self, label=_("Locale Settings") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), (lsizer, 0),
+ ((10, 10), 0)])
+
+ msizer = wx.BoxSizer(wx.HORIZONTAL)
+ msizer.AddMany([((10, 10), 0), (sizer, 1, wx.EXPAND), ((10, 10), 0)])
+ self.SetSizer(msizer)
+
+#-----------------------------------------------------------------------------#
+
+class GeneralFilePanel(wx.Panel):
+ """Configuration panel for general file settings"""
+ def __init__(self, parent):
+ super(GeneralFilePanel, self).__init__(parent)
+
+ # Attributes
+ self.bsuffix = None
+ self.bsuffix_lbl = None
+
+ # Setup
+ self._DoLayout()
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHECKBOX,
+ self.OnAutoBkup,
+ id=ed_glob.ID_PREF_AUTOBKUP)
+ self.Bind(wx.EVT_CHECKBOX,
+ self.OnCustomBackupPath,
+ id=ID_PREF_BKUP_LBL)
+ self.Bind(wx.EVT_DIRPICKER_CHANGED,
+ self.OnDirChange,
+ id=ID_PREF_BKUP_PATH)
+ self.Bind(wx.EVT_FILEPICKER_CHANGED,
+ self.OnFileChange,
+ id=ID_PREF_ENCHANT_PATH)
+ self.bsuffix.Bind(wx.EVT_KILL_FOCUS, self.OnBackupSuffixLoseFocus)
+
+ def _DoLayout(self):
+ """Layout the panel"""
+ # File settings
+ fhsizer = wx.BoxSizer(wx.HORIZONTAL)
+ fhsizer.AddMany([(wx.StaticText(self,
+ label=_("File History Length") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (ExChoice(self, ed_glob.ID_PREF_FHIST,
+ choices=[str(val) for val in range(1, 10)],
+ default=Profile_Get('FHIST_LVL', 'str')),
+ 0, wx.ALIGN_CENTER_VERTICAL)])
+
+ # Encoding options
+ d_encoding = Profile_Get('ENCODING',
+ 'str',
+ default=ed_txt.DEFAULT_ENCODING)
+ if d_encoding is None:
+ d_encoding = 'utf-8'
+ Profile_Set('ENCODING', d_encoding)
+ d_encoding = encodings.normalize_encoding(d_encoding)
+
+ enc_ch = ExChoice(self, ed_glob.ID_PREF_ENCODING,
+ choices=util.GetAllEncodings(),
+ default=d_encoding)
+ enc_ch.SetToolTipString(_("Encoding to try when auto detection fails"))
+ enc_sz = wx.BoxSizer(wx.HORIZONTAL)
+ enc_sz.AddMany([(wx.StaticText(self, label=_("Preferred Encoding") + u":"),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5),), (enc_ch, 1)])
+
+ win_cb = wx.CheckBox(self, ed_glob.ID_NEW_WINDOW,
+ _("Open files in new windows by default"))
+ win_cb.SetValue(Profile_Get('OPEN_NW'))
+ pos_cb = wx.CheckBox(self, ed_glob.ID_PREF_SPOS,
+ _("Remember File Position"))
+ pos_cb.SetValue(Profile_Get('SAVE_POS'))
+ chkmod_cb = wx.CheckBox(self, ed_glob.ID_PREF_CHKMOD,
+ _("Check if on disk file has been "
+ "modified by others"))
+ chkmod_val = Profile_Get('CHECKMOD', default=True)
+ chkmod_cb.SetValue(chkmod_val)
+ autorl_cb = wx.CheckBox(self, ed_glob.ID_PREF_AUTO_RELOAD,
+ _("Automatically reload files when "
+ "changes are detected on disk"))
+ autorl_cb.SetValue(Profile_Get('AUTO_RELOAD', default=False) and chkmod_val)
+ autorl_cb.Enable(chkmod_val)
+ eolwarn_cb = wx.CheckBox(self, ed_glob.ID_PREF_WARN_EOL,
+ _("Warn when mixed eol characters are detected"))
+ eolwarn_cb.SetValue(Profile_Get('WARN_EOL', default=True))
+
+ # Layout items
+ sizer = wx.FlexGridSizer(9, 2, 5, 5)
+ sizer.AddMany([((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self, label=_("File Settings") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), (enc_sz, 0),
+ ((5, 5),), (fhsizer, 0),
+ ((5, 5),), (win_cb, 0),
+ ((5, 5),), (pos_cb, 0),
+ ((5, 5),), (chkmod_cb, 0),
+ ((5, 5),), (autorl_cb, 0),
+ ((5, 5),), (eolwarn_cb, 0),
+ ((5, 5), 0)])
+
+ # Auto Backup
+ bksbox = wx.StaticBox(self, label=_("File Backups"))
+ bksboxsz = wx.StaticBoxSizer(bksbox, wx.VERTICAL)
+ autobk_cb = wx.CheckBox(self, ed_glob.ID_PREF_AUTOBKUP,
+ _("Automatically Backup Files"))
+ bAutoBkup = Profile_Get('AUTOBACKUP', default=False)
+ autobk_cb.SetValue(bAutoBkup)
+ autobk_cb.SetToolTipString(_("Backup buffer to file periodically"))
+ bdir = Profile_Get('AUTOBACKUP_PATH', default="")
+ bkup_path_lbl = wx.CheckBox(self, ID_PREF_BKUP_LBL,
+ label=_("Backup Path:"))
+ bkup_path_lbl.SetValue(bool(bdir))
+ bkup_path = wx.DirPickerCtrl(self, ID_PREF_BKUP_PATH,
+ path=bdir,
+ style=wx.DIRP_CHANGE_DIR|wx.DIRP_USE_TEXTCTRL)
+ bkup_path.SetToolTipString(_("Used to set a custom backup path. "
+ "If not specified the backup will be "
+ "put in the same directory as the file."))
+ bkup_path_lbl.Enable(bAutoBkup)
+ bkup_path.Enable(bAutoBkup)
+ bkup_p_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ bkup_p_sizer.AddMany([(bkup_path_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5), 0),
+ (bkup_path, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)])
+ suffix = Profile_Get('AUTOBACKUP_SUFFIX', default=".edbkup")
+ self.bsuffix = wx.TextCtrl(self, ID_PREF_BKUP_SUFFIX, suffix)
+ self.bsuffix.SetToolTipString(_("Suffix for backup file names"))
+ self.bsuffix_lbl = wx.StaticText(self, label=_("Backup file suffix:"))
+ self.bsuffix_lbl.Enable(bAutoBkup)
+ self.bsuffix.Enable(bAutoBkup)
+ bkup_s_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ bkup_s_sizer.AddMany([(self.bsuffix_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5), 0),
+ (self.bsuffix, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)])
+ bksboxsz.AddMany([(autobk_cb, 0),
+ ((5, 5), 0), (bkup_p_sizer, 0, wx.EXPAND),
+ ((5, 5), 0), (bkup_s_sizer, 0, wx.EXPAND)])
+ # End Auto-Backup
+
+ # Spellchecking settings
+ spell_dicts = stcspellcheck.STCSpellCheck.getAvailableLanguages()
+ sbox = wx.StaticBox(self, label=_("Spell Checking"))
+ sboxsz = wx.StaticBoxSizer(sbox, wx.VERTICAL)
+ sprefs = Profile_Get('SPELLCHECK', default=dict())
+ auto_cb = wx.CheckBox(self, id=ID_PREF_AUTO_SPELL,
+ label=_("Check spelling while typing"))
+ auto_cb.SetValue(sprefs.get('auto', False))
+ dict_ch = wx.Choice(self, id=ID_PREF_SPELL_DICT, choices=spell_dicts)
+ sdict = sprefs.get('dict', 'en_US')
+ if sdict in spell_dicts:
+ dict_ch.SetStringSelection(sdict)
+ sdh_sz = wx.BoxSizer(wx.HORIZONTAL)
+ dlbl = wx.StaticText(self, label=_("Dictionary:"))
+ sdh_sz.AddMany([(dlbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5), 0),
+ (dict_ch, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)])
+ sboxsz.AddMany([(auto_cb, 0), ((5, 5), 0), (sdh_sz, 0, wx.EXPAND)])
+
+ if not stcspellcheck.STCSpellCheck.isEnchantOk():
+ for ctrl in (auto_cb, dict_ch, dlbl):
+ ctrl.Enable(False)
+
+ liblbl = wx.StaticText(self, label=_("Enchant Path:"))
+ libpath = os.environ.get('PYENCHANT_LIBRARY_PATH', '')
+ prefpath = sprefs.get('epath', libpath)
+ if not prefpath:
+ prefpath = u""
+ libpicker = wx.FilePickerCtrl(self, ID_PREF_ENCHANT_PATH,
+ path=prefpath,
+ message=_("Path to libenchant"))
+ libpicker.SetToolTipString(_("Path to libenchant"))
+ lib_hsz = wx.BoxSizer(wx.HORIZONTAL)
+ lib_hsz.AddMany([(liblbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5), 0),
+ (libpicker, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)])
+ sboxsz.AddMany([((5, 5), 0), (lib_hsz, 0, wx.EXPAND)])
+
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ vsizer.AddMany([(sizer, 1, wx.EXPAND),
+ ((5, 5), 0), (bksboxsz, 0, wx.EXPAND),
+ ((5, 5), 0), (sboxsz, 0, wx.EXPAND),
+ ((10, 10), 0)])
+
+ msizer = wx.BoxSizer(wx.HORIZONTAL)
+ msizer.AddMany([((10, 10), 0), (vsizer, 1, wx.EXPAND), ((10, 10), 0)])
+ self.SetSizer(msizer)
+
+ def OnAutoBkup(self, evt):
+ """Enable/Disable the backup path controls
+ The profile is updated by L{GeneralPanel} so the event must be skipped
+
+ """
+ e_obj = evt.GetEventObject()
+ blbl = self.FindWindowById(ID_PREF_BKUP_LBL)
+ blbl.Enable(e_obj.Value)
+ dpick = self.FindWindowById(ID_PREF_BKUP_PATH)
+ bpath = Profile_Get('AUTOBACKUP_PATH', default="")
+ dpick.SetPath(bpath)
+ if not e_obj.Value:
+ dpick = self.FindWindowById(ID_PREF_BKUP_PATH)
+ dpick.Enable(False)
+ self.bsuffix.Enable(e_obj.Value)
+ self.bsuffix_lbl.Enable(e_obj.Value)
+ evt.Skip()
+
+ def OnCustomBackupPath(self, evt):
+ """Enable the use of a custom backup path"""
+ e_obj = evt.GetEventObject()
+ event_val = e_obj.GetValue()
+ dpick = self.FindWindowById(ID_PREF_BKUP_PATH)
+ if not event_val:
+ dpick.SetPath(u"")
+ Profile_Set('AUTOBACKUP_PATH', u"")
+ dpick.Enable(event_val)
+
+ def OnDirChange(self, evt):
+ """Update the backup directory path"""
+ path = evt.GetPath().strip()
+ bpath = Profile_Get('AUTOBACKUP_PATH', default="")
+ if bpath != path:
+ Profile_Set('AUTOBACKUP_PATH', path)
+
+ def OnFileChange(self, evt):
+ """Update enchant path and attempt to reload enchant if necessary"""
+ path = evt.GetPath().strip()
+ sprefs = Profile_Get('SPELLCHECK', default=dict())
+ cpath = sprefs.get('epath', u'')
+ if path != cpath:
+ try:
+ ok = stcspellcheck.STCSpellCheck.reloadEnchant(path)
+ except OSError:
+ ok = False
+
+ if ok:
+ # Reload was successful
+ sprefs['epath'] = path
+ Profile_Set('SPELLCHECK', sprefs)
+ else:
+ wx.MessageBox(_("Failed to load Enchant"),
+ _("Library Error"),
+ wx.OK|wx.ICON_ERROR)
+
+ def OnBackupSuffixLoseFocus(self, evt):
+ """Update the backup file name suffix"""
+ suffix = self.bsuffix.GetValue().strip()
+ old_suffix = Profile_Get('AUTOBACKUP_SUFFIX', default='')
+ if suffix != old_suffix:
+ Profile_Set('AUTOBACKUP_SUFFIX', suffix)
+
+#-----------------------------------------------------------------------------#
+
+class DocumentPanel(wx.Panel, PreferencesPanelBase):
+ """Creates a panel with controls for Editra's editing settings
+ @summary: Contains a wx.Notebook that contains a number of pages with
+ setting controls for how documents are handled by the
+ ed_stc.EditraStc text control.
+
+ """
+ def __init__(self, parent, style=wx.BORDER_SUNKEN):
+ """Create the panel
+ @param parent: Parent window of this panel
+ @keyword style: Window Style bitmask
+
+ """
+ wx.Panel.__init__(self, parent, style=style)
+ PreferencesPanelBase.__init__(self)
+
+ def _DoLayout(self):
+ """Do the layout of the panel
+ @note: Do not call this after __init__
+
+ """
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ nbook = wx.Notebook(self)
+ nbook.AddPage(DocGenPanel(nbook), _("General"))
+ nbook.AddPage(DocCodePanel(nbook), _("Code"))
+ nbook.AddPage(DocSyntaxPanel(nbook), _("Syntax Highlighting"))
+ sizer.AddMany([((10, 10), 0), (nbook, 1, wx.EXPAND), ((10, 10), 0)])
+ msizer = wx.BoxSizer(wx.VERTICAL)
+ msizer.AddMany([(sizer, 1, wx.EXPAND), ((10, 10), 0)])
+ self.SetSizer(msizer)
+
+ def GetSize(self):
+ """Get the size of the panel
+ @return: wx.Size
+
+ """
+ sz = wx.Panel.GetSize(self)
+ return wx.Size(sz[0] + 35, sz[1])
+
+class DocGenPanel(wx.Panel):
+ """Panel used for general document settings in the DocumentPanel's
+ notebook.
+ @summary: Panel with controls for setting the general attributes of
+ how a document is managed.
+
+ """
+ ID_FONT_PICKER = wx.NewId()
+ ID_FONT_PICKER2 = wx.NewId()
+
+ def __init__(self, parent):
+ """Create the panel
+ @param parent: Parent window of this panel
+
+ """
+ super(DocGenPanel, self).__init__(parent)
+
+ # Layout
+ self._DoLayout()
+ self.SetAutoLayout(True)
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHECKBOX, self.OnUpdateEditor)
+ self.Bind(wx.EVT_CHOICE, self.OnUpdateEditor)
+ self.Bind(eclib.EVT_FONT_CHANGED, self.OnFontChange)
+
+ def _DoLayout(self):
+ """Layout the controls
+ @note: Do not call this after __init__
+
+ """
+ # Format Section
+ tabsz = wx.BoxSizer(wx.HORIZONTAL)
+ tabsz.AddMany([(wx.StaticText(self, label=_("Tab Width") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (ExChoice(self, ed_glob.ID_PREF_TABW,
+ choices=['2','3','4','5','6','7','8','9','10'],
+ default=Profile_Get('TABWIDTH', 'str')), 0,
+ wx.ALIGN_CENTER_VERTICAL)])
+
+ indentsz = wx.BoxSizer(wx.HORIZONTAL)
+ indentsz.AddMany([(wx.StaticText(self, label=_("Indent Width") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (ExChoice(self, ed_glob.ID_PREF_INDENTW,
+ choices=['2','3','4','5','6','7','8','9','10'],
+ default=Profile_Get('INDENTWIDTH', 'str')), 0,
+ wx.ALIGN_CENTER_VERTICAL)])
+
+ at_cb = wx.CheckBox(self, ed_glob.ID_PREF_AUTOTRIM,
+ _("Automatically trim whitespace on save"))
+ at_cb.SetValue(Profile_Get('AUTO_TRIM_WS', 'bool', False))
+ ut_cb = wx.CheckBox(self, ed_glob.ID_PREF_TABS,
+ _("Use Tabs Instead of Spaces"))
+ ut_cb.SetValue(Profile_Get('USETABS', 'bool', False))
+ bsu_cb = wx.CheckBox(self, ed_glob.ID_PREF_UNINDENT,
+ _("Backspace Unindents"))
+ bsu_cb.SetValue(Profile_Get('BSUNINDENT', 'bool', True))
+
+ eolsz = wx.BoxSizer(wx.HORIZONTAL)
+
+ # NOTE: order must be kept insync with vals in ed_glob, ed_stc
+ eolmode = ExChoice(self, ed_glob.ID_EOL_MODE,
+ choices=[_("Old Macintosh (\\r)"), _("Unix (\\n)"),
+ _("Windows (\\r\\n)")])
+ eolmode.SetSelection(Profile_Get('EOL_MODE'))
+
+ eolsz.AddMany([(wx.StaticText(self,
+ label=_("Default EOL Mode") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (eolmode, 0, wx.ALIGN_CENTER_VERTICAL)])
+
+ # View Options
+ aa_cb = wx.CheckBox(self, ed_glob.ID_PREF_AALIAS, _("AntiAliasing"))
+ aa_cb.SetValue(Profile_Get('AALIASING'))
+ seol_cb = wx.CheckBox(self, ed_glob.ID_SHOW_EOL, _("Show EOL Markers"))
+ seol_cb.SetValue(Profile_Get('SHOW_EOL'))
+ sln_cb = wx.CheckBox(self, ed_glob.ID_SHOW_LN, _("Show Line Numbers"))
+ sln_cb.SetValue(Profile_Get('SHOW_LN'))
+ sws_cb = wx.CheckBox(self, ed_glob.ID_SHOW_WS, _("Show Whitespace"))
+ sws_cb.SetValue(Profile_Get('SHOW_WS'))
+ ww_cb = wx.CheckBox(self, ed_glob.ID_WORD_WRAP, _("Word Wrap"))
+ ww_cb.SetValue(Profile_Get('WRAP'))
+ ww_cb.SetToolTipString(_("Turn off for better performance"))
+ vs_cb = wx.CheckBox(self, ed_glob.ID_PREF_VIRT_SPACE,
+ _("View Virtual Space After Last Line"))
+ vs_cb.SetValue(Profile_Get('VIEWVERTSPACE', default=False))
+ vs_cb.SetToolTipString(_("Adds extra scrolling room after last line"))
+ cursw_sz = wx.BoxSizer(wx.HORIZONTAL)
+ curlbl = wx.StaticText(self, label=_("Caret Width:"))
+ curw_ch = ExChoice(self, ed_glob.ID_PREF_CARET_WIDTH,
+ choices=['1','2','3','4'],
+ default=Profile_Get('CARETWIDTH', default=1)-1)
+ cursw_sz.AddMany([(curlbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ (curw_ch, 0, wx.LEFT, 5)])
+
+ # Font Options
+ fnt = Profile_Get('FONT1', 'font', wx.Font(10, wx.FONTFAMILY_MODERN,
+ wx.FONTSTYLE_NORMAL,
+ wx.FONTWEIGHT_NORMAL))
+ fpick = eclib.PyFontPicker(self, DocGenPanel.ID_FONT_PICKER, fnt)
+ fpick.SetToolTipString(_("Sets the main/default font of the document"))
+ fnt = Profile_Get('FONT2', 'font', wx.Font(10, wx.FONTFAMILY_SWISS,
+ wx.FONTSTYLE_NORMAL,
+ wx.FONTWEIGHT_NORMAL))
+ fpick2 = eclib.PyFontPicker(self, DocGenPanel.ID_FONT_PICKER2, fnt)
+ fpick2.SetToolTipString(_("Sets a secondary font used for special "
+ "regions when syntax highlighting is in use"))
+
+ # Layout
+ sizer = wx.FlexGridSizer(21, 2, 5, 5)
+ sizer.AddGrowableCol(1, 1)
+ sizer.AddMany([((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self, label=_("Format") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), (at_cb, 0),
+ ((5, 5), 0), (ut_cb, 0),
+ ((5, 5), 0), (bsu_cb, 0),
+ ((5, 5), 0), (tabsz, 0),
+ ((5, 5), 0), (indentsz, 0),
+ ((5, 5), 0), (eolsz, 0),
+ ((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self, label=_("View Options") + u": "),
+ 0), (aa_cb, 0),
+ ((5, 5), 0), (seol_cb, 0),
+ ((5, 5), 0), (sln_cb, 0),
+ ((5, 5), 0), (sws_cb, 0),
+ ((5, 5), 0), (ww_cb, 0),
+ ((5, 5), 0), (vs_cb, 0),
+ ((5, 5), 0), (cursw_sz, 0),
+ ((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self, label=_("Primary Font") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL),
+ (fpick, 1, wx.EXPAND),
+ (wx.StaticText(self, label=_("Secondary Font") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL),
+ (fpick2, 1, wx.EXPAND),
+ ((10, 10), 0), ((10, 10), 0)])
+ msizer = wx.BoxSizer(wx.HORIZONTAL)
+ msizer.AddMany([((10, 10), 0), (sizer, 1, wx.EXPAND), ((10, 10), 0)])
+ self.SetSizer(msizer)
+
+ @staticmethod
+ def OnFontChange(evt):
+ """Handles L{eclib.EVT_FONT_CHANGED} from the font controls"""
+ e_id = evt.GetId()
+ if e_id in [DocGenPanel.ID_FONT_PICKER, DocGenPanel.ID_FONT_PICKER2]:
+ font = evt.GetValue()
+ if not isinstance(font, wx.Font) or font.IsNull():
+ return
+
+ if e_id == DocGenPanel.ID_FONT_PICKER:
+ Profile_Set('FONT1', font, 'font')
+ else:
+ Profile_Set('FONT2', font, 'font')
+
+ for main in wx.GetApp().GetMainWindows():
+ for stc in main.nb.GetTextControls():
+ stc.SetStyleFont(font, e_id == DocGenPanel.ID_FONT_PICKER)
+ stc.UpdateAllStyles()
+ else:
+ evt.Skip()
+
+ @staticmethod
+ def OnUpdateEditor(evt):
+ """Update any open text controls to reflect the changes made in this
+ panel from the checkboxes and choice controls.
+ @param evt: Event that called this handler
+
+ """
+ # XXX Why when running on windows this and other imports randomly
+ # become None. I have been unable to reproduce this behavior myself
+ # but have received enough error reports about it to believe it.
+ # If they were actually NoneTypes the dialog would not be able to
+ # be shown so this is very strange!!
+ global ed_glob
+ if ed_glob is None:
+ import ed_glob
+
+ e_id = evt.Id
+ if e_id in (ed_glob.ID_PREF_TABS, ed_glob.ID_PREF_TABW,
+ ed_glob.ID_PREF_UNINDENT, ed_glob.ID_EOL_MODE,
+ ed_glob.ID_PREF_AALIAS, ed_glob.ID_SHOW_EOL,
+ ed_glob.ID_SHOW_LN, ed_glob.ID_SHOW_WS,
+ ed_glob.ID_WORD_WRAP, ed_glob.ID_PREF_AALIAS,
+ ed_glob.ID_PREF_INDENTW, ed_glob.ID_PREF_AUTOTRIM,
+ ed_glob.ID_PREF_VIRT_SPACE, ed_glob.ID_PREF_CARET_WIDTH):
+
+ e_value = evt.EventObject.GetValue()
+ if e_id == ed_glob.ID_EOL_MODE:
+ e_value = evt.EventObject.GetSelection()
+ elif e_id == ed_glob.ID_PREF_CARET_WIDTH:
+ if e_value:
+ e_value = int(e_value)
+ else:
+ e_value = 1
+
+ Profile_Set(ed_glob.ID_2_PROF[e_id], e_value)
+ else:
+ evt.Skip()
+
+#----------------------------------------------------------------------------#
+
+class DocCodePanel(wx.Panel):
+ """Panel used for programming settings
+ @summary: Houses many of the controls for configuring the editors features
+ that are related to programming.
+
+ """
+ def __init__(self, parent):
+ """Create the panel
+ @param parent: Parent window of this panel
+
+ """
+ super(DocCodePanel, self).__init__(parent)
+
+ # Layout
+ self._DoLayout()
+ self.SetAutoLayout(True)
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
+ self.Bind(wx.EVT_CHOICE, self.OnCheck)
+ self.Bind(wx.EVT_SPINCTRL, self.OnSpin)
+
+ def _DoLayout(self):
+ """Layout the page
+ @note: Do not call this after __init__
+
+ """
+ # General Section
+ dlex_ch = ExChoice(self, ed_glob.ID_PREF_DLEXER,
+ choices=syntax.GetLexerList(),
+ default=Profile_Get('DEFAULT_LEX',
+ default="Plain Text"))
+ dlex_ch.SetToolTipString(_("Default highlighing for new documents"))
+ dlex_sz = wx.BoxSizer(wx.HORIZONTAL)
+ dlex_sz.AddMany([(wx.StaticText(self, label=_("Default Lexer") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((3, 3),),
+ (dlex_ch, 0, wx.ALIGN_CENTER_VERTICAL)])
+
+ # Visual Helpers Section
+ vis_lbl = wx.StaticText(self, label=_("Visual Helpers") + u": ")
+ br_cb = wx.CheckBox(self, ed_glob.ID_BRACKETHL,
+ _("Bracket Highlighting"))
+ br_cb.SetValue(Profile_Get('BRACKETHL'))
+ fold_cb = wx.CheckBox(self, ed_glob.ID_FOLDING, _("Code Folding"))
+ fold_cb.SetValue(Profile_Get('CODE_FOLD'))
+ edge_cb = wx.CheckBox(self, ed_glob.ID_SHOW_EDGE, _("Edge Guide"))
+ edge_cb.SetValue(Profile_Get('SHOW_EDGE'))
+ edge_sp = wx.SpinCtrl(self, ed_glob.ID_PREF_EDGE,
+ Profile_Get('EDGE', 'str'), min=0, max=160)
+ edge_sp.SetToolTipString(_("Guide Column"))
+ edge_col = wx.BoxSizer(wx.HORIZONTAL)
+ edge_col.AddMany([(edge_cb, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((10, 5), 0), (edge_sp, 0, wx.ALIGN_CENTER_VERTICAL)])
+ hlcaret_cb = wx.CheckBox(self, ed_glob.ID_HLCARET_LINE,
+ _("Highlight Caret Line"))
+ hlcaret_cb.SetValue(Profile_Get("HLCARETLINE"))
+ ind_cb = wx.CheckBox(self, ed_glob.ID_INDENT_GUIDES,
+ _("Indentation Guides"))
+ ind_cb.SetValue(Profile_Get('GUIDES'))
+
+ # Input Helpers
+ comp_cb = wx.CheckBox(self, ed_glob.ID_AUTOCOMP, _("Auto-Completion"))
+ comp_cb.SetValue(Profile_Get('AUTO_COMP'))
+ compex_cb = wx.CheckBox(self, ed_glob.ID_PREF_AUTOCOMPEX,
+ _("Extended Auto-Comp"))
+ compex_cb.SetValue(Profile_Get('AUTO_COMP_EX'))
+ compex_cb.Enable(comp_cb.GetValue())
+ compex_cb.SetToolTipString(_("Warning suggestions will include"
+ " context insensitive results"))
+ compex_sz = wx.BoxSizer(wx.HORIZONTAL)
+ compex_sz.AddMany([((16, -1), 0), (compex_cb, 0)])
+ ai_cb = wx.CheckBox(self, ed_glob.ID_AUTOINDENT, _("Auto-Indent"))
+ ai_cb.SetValue(Profile_Get('AUTO_INDENT'))
+ vi_cb = wx.CheckBox(self, ed_glob.ID_VI_MODE, _("Enable Vi Emulation"))
+ vi_cb.SetValue(Profile_Get('VI_EMU'))
+ vi_ncb = wx.CheckBox(self, ed_glob.ID_VI_NORMAL_DEFAULT,
+ _("Start in Normal Mode"))
+ vi_ncb.SetValue(Profile_Get('VI_NORMAL_DEFAULT'))
+ vi_ncb.Enable(vi_cb.GetValue())
+ vi_ncb_sz = wx.BoxSizer(wx.HORIZONTAL)
+ vi_ncb_sz.AddMany([((16, -1), 0), (vi_ncb, 0)])
+
+ # Layout the controls
+ sizer = wx.FlexGridSizer(15, 2, 5, 5)
+ sizer.AddMany([((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self, label=_("General") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), (dlex_sz, 0),
+ ((10, 10), 0), ((10, 10), 0),
+ (vis_lbl, 0), (br_cb, 0),
+ ((5, 5), 0), (fold_cb, 0),
+ ((5, 5), 0), (edge_col, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5), 0), (hlcaret_cb, 0),
+ ((5, 5), 0), (ind_cb, 0),
+ ((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self, label=_("Input Helpers") + u": "),
+ 0), (comp_cb, 0),
+ ((5, 5), 0), (compex_sz, 0),
+ ((5, 5), 0), (ai_cb, 0),
+ ((5, 5), 0), (vi_cb, 0),
+ ((5, 5), 0), (vi_ncb_sz, 0),
+ ((10, 10), 0), ((10, 10), 0)])
+ msizer = wx.BoxSizer(wx.HORIZONTAL)
+ msizer.AddMany([((10, 10), 0), (sizer, 1, wx.EXPAND), ((10, 10), 0)])
+ self.SetSizer(msizer)
+
+ def OnCheck(self, evt):
+ """Handles the events from this panels check boxes
+ @param evt: wx.CommandEvent
+
+ """
+ e_id = evt.GetId()
+ if e_id in (ed_glob.ID_BRACKETHL, ed_glob.ID_SHOW_EDGE,
+ ed_glob.ID_INDENT_GUIDES, ed_glob.ID_FOLDING,
+ ed_glob.ID_AUTOCOMP, ed_glob.ID_AUTOINDENT,
+ ed_glob.ID_PREF_EDGE, ed_glob.ID_VI_MODE,
+ ed_glob.ID_VI_NORMAL_DEFAULT,
+ ed_glob.ID_PREF_DLEXER, ed_glob.ID_HLCARET_LINE,
+ ed_glob.ID_PREF_AUTOCOMPEX):
+
+ e_val = evt.EventObject.GetValue()
+
+ # Update Profile
+ Profile_Set(ed_glob.ID_2_PROF[e_id], e_val)
+
+ # Make ui adjustments
+ meth = None
+ args = list()
+ if e_id == ed_glob.ID_SHOW_EDGE:
+ spin = self.FindWindowById(ed_glob.ID_PREF_EDGE)
+ if spin is not None:
+ spin.Enable(e_val)
+ elif e_id == ed_glob.ID_AUTOCOMP:
+ cbox = self.FindWindowById(ed_glob.ID_PREF_AUTOCOMPEX)
+ if cbox is not None:
+ cbox.Enable(e_val)
+ elif e_id == ed_glob.ID_VI_MODE:
+ cbox = self.FindWindowById(ed_glob.ID_VI_NORMAL_DEFAULT)
+ if cbox is not None:
+ cbox.Enable(e_val)
+ else:
+ evt.Skip()
+
+ @staticmethod
+ def OnSpin(evt):
+ """Catch actions from a slider
+ @param evt: wx.SpinEvent
+
+ """
+ e_id = evt.GetId()
+ if e_id == ed_glob.ID_PREF_EDGE:
+ val = evt.GetEventObject().GetValue()
+ Profile_Set(ed_glob.ID_2_PROF[e_id], val)
+
+ for mainw in wx.GetApp().GetMainWindows():
+ for stc in mainw.nb.GetTextControls():
+ stc.SetEdgeColumn(val)
+ else:
+ evt.Skip()
+
+#----------------------------------------------------------------------------#
+
+class DocSyntaxPanel(wx.Panel):
+ """Document syntax config panel
+ @summary: Manages the configuration of the syntax highlighting
+ of the documents in the editor.
+
+ """
+ def __init__(self, parent):
+ """Inialize the config panel
+ @param parent: parent window of this panel
+
+ """
+ super(DocSyntaxPanel, self).__init__(parent)
+
+ # Attributes
+ self._elist = ExtListCtrl(self)
+ self._elist.SetMinSize((425, 200))
+
+ # Layout page
+ self._DoLayout()
+ self.SetAutoLayout(True)
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ self.Bind(wx.EVT_CHECKBOX, self.OnSynChange)
+ self.Bind(wx.EVT_CHOICE, self.OnSynChange)
+
+ def _DoLayout(self):
+ """Layout all the controls
+ @note: Do not call this after __init__
+
+ """
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ # Syntax Settings
+ syn_cb = wx.CheckBox(self, ed_glob.ID_SYNTAX, _("Syntax Highlighting"))
+ syn_cb.SetValue(Profile_Get('SYNTAX'))
+ ss_lst = util.GetResourceFiles(u'styles', get_all=True, title=False)
+ ss_lst = [sheet for sheet in ss_lst if not sheet.startswith('.')]
+ syntheme = ExChoice(self, ed_glob.ID_PREF_SYNTHEME,
+ choices=sorted(ss_lst),
+ default=Profile_Get('SYNTHEME', 'str'))
+ line = wx.StaticLine(self, size=(-1, 2))
+ lsizer = wx.BoxSizer(wx.VERTICAL)
+ lsizer.Add(line, 0, wx.EXPAND)
+ lst_lbl = wx.StaticText(self, label=_("Filetype Associations") + u": ")
+
+ # Layout the controls
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer.AddMany([(syn_cb, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5), 1, wx.EXPAND),
+ (wx.StaticText(self, label=_("Color Scheme") + u": "),
+ 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL),
+ (syntheme, 0, wx.EXPAND), ((5, 5), 0)])
+
+ sizer.AddMany([((15, 15), 0), (hsizer, 0, wx.EXPAND),
+ ((5, 5), 0), (lsizer, 0, wx.EXPAND),
+ ((15, 15), 0), (lst_lbl, 0, wx.ALIGN_LEFT)])
+
+ hsizer2 = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer2.AddMany([((5, 5), 0), (self._elist, 1, wx.EXPAND), ((5, 5), 0)])
+
+ default_btn = wx.Button(self, wx.ID_DEFAULT, _("Revert to Default"))
+ if wx.Platform == '__WXMAC__':
+ default_btn.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+ sizer.AddMany([((10, 10), 0), (hsizer2, 1, wx.EXPAND), ((15, 15), 0),
+ (default_btn, 0, wx.ALIGN_LEFT), ((10, 10), 0)])
+
+ msizer = wx.BoxSizer(wx.HORIZONTAL)
+ msizer.AddMany([((5, 5), 0), (sizer, 1, wx.EXPAND), ((5, 5), 0)])
+ self.SetSizer(msizer)
+
+ def OnButton(self, evt):
+ """Reset button handler
+ @param evt: Event that called this handler
+
+ """
+ if evt.GetId() == wx.ID_DEFAULT:
+ syntax.ExtensionRegister().LoadDefault()
+ self._elist.UpdateExtensions()
+ else:
+ evt.Skip()
+
+ @staticmethod
+ def OnSynChange(evt):
+ """Handles the events from checkbox and choice control for this panel
+ @param evt: event that called this handler
+ @postcondition: all text controls are updated to reflect the changes
+ made in these controls.
+
+ """
+ e_id = evt.GetId()
+ e_obj = evt.GetEventObject()
+ if e_id in (ed_glob.ID_PREF_SYNTHEME, ed_glob.ID_SYNTAX):
+ Profile_Set(ed_glob.ID_2_PROF[e_id], e_obj.GetValue())
+ else:
+ evt.Skip()
+
+#-----------------------------------------------------------------------------#
+
+class AppearancePanel(wx.Panel, PreferencesPanelBase):
+ """Creates a panel with controls for Editra's appearance settings
+ @summary: contains all the controls for configuring the appearance
+ related settings in Editra.
+
+ """
+ def __init__(self, parent, style=wx.BORDER_SUNKEN):
+ """Create the panel
+ @param parent: Parent window of this panel
+ @keyword style: Window Style bitmask
+
+ """
+ wx.Panel.__init__(self, parent, style=style)
+ PreferencesPanelBase.__init__(self)
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
+ self.Bind(wx.EVT_CHOICE, self.OnChoice)
+ self.Bind(wx.EVT_SLIDER, self.OnSetTransparent, \
+ id=ed_glob.ID_TRANSPARENCY)
+ self.Bind(eclib.EVT_FONT_CHANGED, self.OnFontChange)
+
+ def _DoLayout(self):
+ """Add and layout the widgets
+ @note: Do not call this after __init__
+
+ """
+ # Icons Section
+ from ed_theme import BitmapProvider
+ icons = ['Default']
+ icons.extend(BitmapProvider(wx.GetApp().GetPluginManager()).GetThemes())
+ iconsz = wx.BoxSizer(wx.HORIZONTAL)
+ iconsz.AddMany([(wx.StaticText(self, label=_("Icon Theme") + u": "), 0,
+ wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (ExChoice(self, ed_glob.ID_PREF_ICON, icons,
+ Profile_Get('ICONS', 'str').title()), 0)])
+ tbiconsz = wx.BoxSizer(wx.HORIZONTAL)
+ tbiconsz.AddMany([(wx.StaticText(self, label=_("Toolbar Icon Size") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (ExChoice(self, ed_glob.ID_PREF_ICONSZ,
+ ['16', '24', '32'],
+ str(Profile_Get('ICON_SZ', 'size_tuple')[0])), 0)])
+ tabicon_cb = wx.CheckBox(self, ed_glob.ID_PREF_TABICON,
+ _("Show Icons on Tabs"))
+ tabicon_cb.SetValue(Profile_Get('TABICONS'))
+
+ # Layout Section
+ mainw = wx.GetApp().GetActiveWindow()
+ if mainw is not None:
+ pchoices = mainw.GetPerspectiveList()
+ else:
+ pchoices = list()
+ perspec_sz = wx.BoxSizer(wx.HORIZONTAL)
+ perspec_sz.AddMany([(wx.StaticText(self,
+ label=_("Default Perspective") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0),
+ (ExChoice(self, ed_glob.ID_PERSPECTIVES,
+ pchoices, Profile_Get('DEFAULT_VIEW')), 0)])
+ ws_cb = wx.CheckBox(self, ed_glob.ID_PREF_WSIZE, \
+ _("Remember Window Size on Exit"))
+ ws_cb.SetValue(Profile_Get('SET_WSIZE'))
+ wp_cb = wx.CheckBox(self, ed_glob.ID_PREF_WPOS, \
+ _("Remember Window Position on Exit"))
+ wp_cb.SetValue(Profile_Get('SET_WPOS'))
+ sb_cb = wx.CheckBox(self, ed_glob.ID_SHOW_SB, _("Show Status Bar"))
+ sb_cb.SetValue(Profile_Get('STATBAR'))
+ tb_cb = wx.CheckBox(self, ed_glob.ID_VIEW_TOOL, _("Show Toolbar"))
+ tb_cb.SetValue(Profile_Get('TOOLBAR'))
+
+ # Font
+ fnt = Profile_Get('FONT3', 'font', wx.NORMAL_FONT)
+ fpick = eclib.PyFontPicker(self, wx.ID_ANY, fnt)
+ fpick.SetToolTipString(_("Main display font for various UI components"))
+
+ # Layout
+ sizer = wx.FlexGridSizer(16, 2, 5, 5)
+ sizer.AddMany([((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self, label=_("Icons") + u": "), 0,
+ wx.ALIGN_CENTER_VERTICAL), (iconsz, 0),
+ ((5, 5), 0), (tbiconsz, 0),
+ ((5, 5), 0), (tabicon_cb, 0),
+ ((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self, label=_("Layout") + u": "), 0,
+ wx.ALIGN_CENTER_VERTICAL),
+ (perspec_sz, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5), 0), (ws_cb, 0),
+ ((5, 5), 0), (wp_cb, 0),
+ ((5, 5), 0), (sb_cb, 0),
+ ((5, 5), 0), (tb_cb, 0),
+ ((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self, label=_("Transparency") + u": "), 0),
+ (wx.Slider(self, ed_glob.ID_TRANSPARENCY,
+ Profile_Get('ALPHA'), 100, 255,
+ style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|\
+ wx.SL_LABELS), 0, wx.EXPAND),
+ ((10, 10), 0), ((10, 10), 0),
+ (wx.StaticText(self, label=_("Display Font") + u": "),
+ 0, wx.ALIGN_CENTER_VERTICAL),
+ (fpick, 1, wx.EXPAND),
+ ((10, 10), 0), ((10, 10), 0),
+ ])
+
+ msizer = wx.BoxSizer(wx.HORIZONTAL)
+ msizer.AddMany([((10, 10), 0), (sizer, 1, wx.EXPAND), ((10, 10), 0)])
+ self.SetSizer(msizer)
+
+ @staticmethod
+ def OnCheck(evt):
+ """Updates profile based on checkbox actions
+ @param evt: Event that called this handler
+
+ """
+ e_id = evt.GetId()
+ evalue = evt.GetEventObject().GetValue()
+ if e_id in (ed_glob.ID_PREF_WPOS, ed_glob.ID_PREF_WSIZE):
+ Profile_Set(ed_glob.ID_2_PROF[e_id], evalue)
+ elif e_id == ed_glob.ID_PREF_TABICON:
+ Profile_Set(ed_glob.ID_2_PROF[e_id], evalue)
+ ed_msg.PostMessage(ed_msg.EDMSG_THEME_NOTEBOOK)
+ elif e_id in (ed_glob.ID_SHOW_SB, ed_glob.ID_VIEW_TOOL):
+ Profile_Set(ed_glob.ID_2_PROF[e_id], evalue)
+ if e_id == ed_glob.ID_SHOW_SB:
+ fun = 'GetStatusBar'
+ else:
+ fun = 'GetToolBar'
+
+ # Update Window(s)
+ for mainw in wx.GetApp().GetMainWindows():
+ getattr(mainw, fun)().Show(evalue)
+ mainw.SendSizeEvent()
+ else:
+ evt.Skip()
+
+ @staticmethod
+ def OnChoice(evt):
+ """Handles selection events from the choice controls
+ @param evt: Event that called this handler
+
+ """
+ e_id = evt.GetId()
+ e_obj = evt.GetEventObject()
+ val = e_obj.GetValue()
+ if e_id in [ed_glob.ID_PREF_ICON, ed_glob.ID_PREF_ICONSZ]:
+ if e_id == ed_glob.ID_PREF_ICONSZ:
+ val = (int(val), int(val))
+ Profile_Set(ed_glob.ID_2_PROF[e_id], val)
+ wx.GetApp().ReloadArtProvider()
+ ed_msg.PostMessage(ed_msg.EDMSG_THEME_CHANGED, True)
+ elif e_id == ed_glob.ID_PERSPECTIVES:
+ Profile_Set('DEFAULT_VIEW', val)
+ for main_win in wx.GetApp().GetMainWindows():
+ main_win.SetPerspective(Profile_Get('DEFAULT_VIEW'))
+ else:
+ evt.Skip()
+
+ @staticmethod
+ def OnFontChange(evt):
+ """Send out update messages fo rdisplay font changes"""
+ font = evt.GetValue()
+ if isinstance(font, wx.Font) and not font.IsNull():
+ Profile_Set('FONT3', font, 'font')
+ ed_msg.PostMessage(ed_msg.EDMSG_DSP_FONT, font)
+
+ @staticmethod
+ def OnSetTransparent(evt):
+ """Sets the transparency of the editor while the slider
+ is being dragged.
+ @param evt: Event that called this handler
+
+ """
+ if evt.GetId() == ed_glob.ID_TRANSPARENCY:
+ value = evt.GetEventObject().GetValue()
+ for window in wx.GetApp().GetOpenWindows().values():
+ win = window[0]
+ if hasattr(win, 'SetTransparent'):
+ win.SetTransparent(value)
+ Profile_Set('ALPHA', value)
+ else:
+ evt.Skip()
+
+#-----------------------------------------------------------------------------#
+
+class NetworkPanel(wx.Panel, PreferencesPanelBase):
+ """Network related configration options"""
+ def __init__(self, parent, style=wx.BORDER_SUNKEN):
+ """Create the panel"""
+ wx.Panel.__init__(self, parent, style=style)
+ PreferencesPanelBase.__init__(self)
+
+ def _DoLayout(self):
+ """Do the layout of the panel
+ @note: Do not call this after __init__
+
+ """
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ nbook = wx.Notebook(self)
+ nbook.AddPage(NetConfigPage(nbook), _("Configuration"))
+
+ # Only show update page if user has access to do installs
+ if os.access(ed_glob.CONFIG['INSTALL_DIR'], os.R_OK|os.W_OK):
+ nbook.AddPage(UpdatePage(nbook), _("Update"))
+
+ sizer.AddMany([((10, 10), 0), (nbook, 1, wx.EXPAND), ((10, 10), 0)])
+ msizer = wx.BoxSizer(wx.VERTICAL)
+ msizer.AddMany([(sizer, 1, wx.EXPAND), ((10, 10), 0)])
+ self.SetSizer(msizer)
+
+#-----------------------------------------------------------------------------#
+
+ID_USE_PROXY = wx.NewId()
+ID_URL = wx.NewId()
+ID_PORT = wx.NewId()
+ID_USERNAME = wx.NewId()
+ID_PASSWORD = wx.NewId()
+
+class NetConfigPage(wx.Panel):
+ """Configuration page for network and proxy settings"""
+ def __init__(self, parent):
+ super(NetConfigPage, self).__init__(parent)
+
+ # Layout
+ self._DoLayout()
+ self.SetAutoLayout(True)
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHECKBOX, self.OnCheck, id=ID_USE_PROXY)
+ self.Bind(wx.EVT_BUTTON, self.OnApply, id=wx.ID_APPLY)
+
+ def _DoLayout(self):
+ """Layout the controls in the panel"""
+ msizer = wx.BoxSizer(wx.VERTICAL)
+
+ sboxsz = wx.StaticBoxSizer(wx.StaticBox(self,
+ label=_("Proxy Settings")), wx.VERTICAL)
+ flexg = wx.FlexGridSizer(4, 2, 10, 5)
+ flexg.AddGrowableCol(1, 1)
+
+ proxy_val = Profile_Get('PROXY_SETTINGS', default=dict())
+ use_proxy = wx.CheckBox(self, ID_USE_PROXY, _("Use Proxy"))
+ use_proxy.SetValue(Profile_Get('USE_PROXY', 'bool', False))
+ sboxsz.AddMany([(use_proxy, 0, wx.ALIGN_LEFT), ((10, 10), 0)])
+
+ url_sz = wx.BoxSizer(wx.HORIZONTAL)
+ url_lbl = wx.StaticText(self, label=_("Proxy URL") + u":")
+ url_txt = wx.TextCtrl(self, ID_URL, proxy_val.get('url', ''))
+ port_sep = wx.StaticText(self, label=":")
+ port_txt = wx.TextCtrl(self, ID_PORT, proxy_val.get('port', ''))
+ port_txt.SetToolTipString(_("Port Number"))
+ url_sz.AddMany([(url_txt, 1, wx.EXPAND), ((2, 2)),
+ (port_sep, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((2, 2)), (port_txt, 0, wx.ALIGN_CENTER_VERTICAL)])
+ flexg.AddMany([(url_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ (url_sz, 0, wx.EXPAND)])
+
+ usr_sz = wx.BoxSizer(wx.HORIZONTAL)
+ usr_lbl = wx.StaticText(self, label=_("Username") + u":")
+ usr_txt = wx.TextCtrl(self, ID_USERNAME, proxy_val.get('uname', ''))
+ usr_sz.Add(usr_txt, 1, wx.EXPAND)
+ flexg.AddMany([(usr_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ (usr_sz, 0, wx.EXPAND)])
+
+ pass_sz = wx.BoxSizer(wx.HORIZONTAL)
+ pass_lbl = wx.StaticText(self, label=_("Password") + u":")
+ pass_txt = wx.TextCtrl(self, ID_PASSWORD,
+ ed_crypt.Decrypt(proxy_val.get('passwd', ''),
+ proxy_val.get('pid', '')),
+ style=wx.TE_PASSWORD)
+ pass_sz.Add(pass_txt, 1, wx.EXPAND)
+ flexg.AddMany([(pass_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ (pass_sz, 0, wx.EXPAND), ((5, 5), 0)])
+
+ apply_b = wx.Button(self, wx.ID_APPLY)
+ flexg.Add(apply_b, 0, wx.ALIGN_RIGHT)
+
+ if wx.Platform == '__WXMAC__':
+ for lbl in (use_proxy, url_txt, port_sep, port_txt, url_lbl,
+ usr_lbl, usr_txt, pass_lbl, pass_txt, apply_b):
+ lbl.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+
+ self.EnableControls(use_proxy.GetValue())
+ sboxsz.Add(flexg, 1, wx.EXPAND)
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+ hsizer.AddMany([((5, 5)), (sboxsz, 1, wx.EXPAND), ((5, 5))])
+ msizer.AddMany([((10, 10)), (hsizer, 1, wx.EXPAND), ((10, 10))])
+ self.SetSizer(msizer)
+
+ def OnApply(self, evt):
+ """Apply the changes to the proxy settings
+ @param evt: wx.EVT_BUTTON
+
+ """
+ if evt.GetId() == wx.ID_APPLY:
+ key_map = { ID_USERNAME : 'uname', ID_URL : 'url',
+ ID_PORT : 'port', ID_PASSWORD : 'passwd' }
+ proxy_dict = dict(uname='', passwd='', url='', port='')
+ for val in (ID_URL, ID_PORT, ID_USERNAME, ID_PASSWORD):
+ win = self.FindWindowById(val)
+ if win is not None:
+ winval = win.GetValue()
+ if val == ID_PASSWORD:
+ # This is not the most secure method of saving a
+ # sensitive data but it is definitely better than plain
+ # text. ALso as to be able to obtain this info from the
+ # user profile the intruder would already have had to
+ # compromise the users system account making anymore
+ # such security rather moot by this point anyway.
+ pid = os.urandom(8)
+ winval = ed_crypt.Encrypt(winval, pid)
+ proxy_dict['pid'] = pid
+ proxy_dict[key_map[val]] = winval
+
+ Profile_Set('PROXY_SETTINGS', proxy_dict)
+ else:
+ evt.Skip()
+
+ def EnableControls(self, enable=True):
+ """Enable the controls in the box or disable them
+ @keyword enable: Enable or Disable
+
+ """
+ for child in self.GetChildren():
+ if isinstance(child, wx.StaticText) or \
+ isinstance(child, wx.TextCtrl) or \
+ isinstance(child, wx.Button):
+ child.Enable(enable)
+
+ def OnCheck(self, evt):
+ """Enable the use of the proxy settings or not
+ @param evt: wx.EVT_CHECKBOX
+
+ """
+ e_val = evt.GetEventObject().GetValue()
+ Profile_Set('USE_PROXY', e_val)
+ self.EnableControls(e_val)
+
+#-----------------------------------------------------------------------------#
+
+class UpdatePage(wx.Panel):
+ """Creates a panel with controls for updating Editra
+ @summary: Panel with controls to check and download updates for Editra
+
+ """
+ def __init__(self, parent):
+ """Create the panel
+ @param parent: Parent window of this panel
+
+ """
+ super(UpdatePage, self).__init__(parent)
+
+ # Layout
+ self._DoLayout()
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ self.Bind(ed_event.EVT_UPDATE_TEXT, self.OnUpdateText)
+
+ def _DoLayout(self):
+ """Do the layout of the panel
+ @note: Do not call this after __init__
+
+ """
+ # Status text and bar
+ cur_box = wx.StaticBox(self, label=_("Installed Version"))
+ cur_sz = wx.StaticBoxSizer(cur_box, wx.HORIZONTAL)
+ cur_sz.SetMinSize(wx.Size(150, 40))
+ cur_ver = wx.StaticText(self, wx.ID_ANY, ed_glob.VERSION)
+ cur_sz.Add(cur_ver, 0, wx.ALIGN_CENTER_HORIZONTAL)
+ e_update = updater.UpdateProgress(self, ed_glob.ID_PREF_UPDATE_BAR)
+ upd_box = wx.StaticBox(self, label=_("Latest Version"))
+ upd_bsz = wx.StaticBoxSizer(upd_box, wx.HORIZONTAL)
+ upd_bsz.SetMinSize(wx.Size(150, 40))
+ upd_bsz.Add(wx.StaticText(self, ID_UPDATE_MSG, _("Status Unknown")),
+ 0, wx.ALIGN_CENTER_HORIZONTAL)
+ upd_bsz.Layout()
+
+ # Layout Controls
+ statsz = wx.BoxSizer(wx.HORIZONTAL)
+ statsz.AddMany([((15, 15), 0), (cur_sz, 0), ((20, 10), 1),
+ (upd_bsz, 0), ((15, 15), 0)])
+
+ # Control buttons
+ dl_b = wx.Button(self, ID_DOWNLOAD, _("Download"))
+ dl_b.Disable()
+
+ bsizer = wx.BoxSizer(wx.HORIZONTAL)
+ bsizer.AddStretchSpacer()
+ bsizer.Add(wx.Button(self, ID_CHECK_UPDATE, _("Check")),
+ 0, wx.ALIGN_LEFT)
+ bsizer.AddStretchSpacer(2)
+ bsizer.Add(dl_b, 0, wx.ALIGN_RIGHT)
+ bsizer.AddStretchSpacer()
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.AddMany([((15, 15), 1), (statsz, 0, wx.EXPAND), ((15, 15), 0),
+ (e_update, 0, wx.EXPAND), ((15, 15), 0),
+ (bsizer, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL),
+ ((15, 15), 1)])
+
+ msizer = wx.BoxSizer(wx.HORIZONTAL)
+ msizer.AddMany([((5, 5), 0), (sizer, 1, wx.EXPAND), ((5, 5), 0)])
+ self.SetSizer(msizer)
+
+ def OnButton(self, evt):
+ """Handles events generated by the panels buttons
+ @param evt: event that called this handler
+
+ """
+ e_id = evt.GetId()
+ e_obj = evt.GetEventObject()
+ if e_id == ID_CHECK_UPDATE:
+ util.Log("[prefdlg][evt] Update Page: Check Update Clicked")
+ e_obj.Disable()
+ self.FindWindowById(ID_UPDATE_MSG).SetLabel(_("Checking..."))
+ prog_bar = self.FindWindowById(ed_glob.ID_PREF_UPDATE_BAR)
+ # Note this function returns right away but its result is
+ # handled on a separate thread. This window is then notified
+ # via a custom event being posted by the control.
+ prog_bar.CheckForUpdates()
+ elif e_id == ID_DOWNLOAD:
+ util.Log("[prefdlg][evt] Update Page: Download Updates Clicked")
+ e_obj.Disable()
+ self.FindWindowById(ID_CHECK_UPDATE).Disable()
+ dl_dlg = updater.DownloadDialog(None, ed_glob.ID_DOWNLOAD_DLG,
+ _("Downloading Update"))
+ dp_sz = wx.GetDisplaySize()
+ dl_dlg.SetPosition(((dp_sz[0] - (dl_dlg.GetSize()[0] + 5)), 25))
+ dl_dlg.Show()
+ else:
+ evt.Skip()
+
+ def OnUpdateText(self, evt):
+ """Handles text update events"""
+ util.Log("[prefdlg][evt] Update Page: Updating version status text")
+ upd = self.FindWindowById(ed_glob.ID_PREF_UPDATE_BAR)
+ if evt.GetId() == upd.ID_CHECKING:
+ self.FindWindowById(ID_UPDATE_MSG).SetLabel(upd.GetStatus())
+ if upd.GetUpdatesAvailable():
+ self.FindWindowById(ID_DOWNLOAD).Enable()
+ self.FindWindowById(ID_CHECK_UPDATE).Enable()
+ self.Layout()
+
+ # Trick the notebook into resizing to ensure everything fits
+ curr_pg = self.GetParent().GetSelection()
+ nbevt = wx.NotebookEvent(wx.wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED,
+ 0, curr_pg, curr_pg)
+ wx.PostEvent(self.GetParent(), nbevt)
+ gauge = self.FindWindowById(ed_glob.ID_PREF_UPDATE_BAR)
+ if gauge:
+ gauge.Stop()
+ gauge.SetValue(100)
+ self.Refresh()
+
+#-----------------------------------------------------------------------------#
+# Advanced Page
+
+class AdvancedPanel(wx.Panel):
+ """Creates a panel for holding advanced configuration options
+ @summary: Contains a wx.Notebook that contains a number of pages with
+ setting controls for configuring the advanced configuration
+ options.
+
+ """
+ def __init__(self, parent, style=wx.BORDER_SUNKEN):
+ """Create the panel
+ @param parent: Parent window of this panel
+ @keyword style: Window Style bitmask
+
+ """
+ super(AdvancedPanel, self).__init__(parent, style=style)
+
+ # Layout
+ self._layout_done = False
+
+ def _DoLayout(self):
+ """Do the layout of the panel
+ @note: Do not call this after __init__
+
+ """
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ nbook = wx.Notebook(self)
+ nbook.AddPage(KeyBindingPanel(nbook), _("Keybindings"))
+ sizer.AddMany([((10, 10), 0), (nbook, 1, wx.EXPAND), ((10, 10), 0)])
+ msizer = wx.BoxSizer(wx.VERTICAL)
+ msizer.AddMany([(sizer, 1, wx.EXPAND), ((10, 10), 0)])
+ self.SetSizer(msizer)
+
+ def DoSelected(self):
+ """Handle initial selection to create controls"""
+ if not self._layout_done:
+ self._layout_done = True
+ self._DoLayout()
+ self.SetAutoLayout(True)
+
+#-----------------------------------------------------------------------------#
+# Keybinding Panel
+
+ID_MENUS = wx.NewId()
+ID_MENU_ITEMS = wx.NewId()
+ID_MOD1 = wx.NewId()
+ID_MOD2 = wx.NewId()
+ID_KEYS = wx.NewId()
+ID_BINDING = wx.NewId()
+KEYS = ['', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+', '/', ',',
+ '.', '[', ']', '{', '}', '>', '<', ':', '|', 'Left', 'Right', 'Down',
+ 'Up', 'Home', 'End', 'Enter', 'Tab', 'Space', '"', "'"]
+KEYS.extend(["F" + str(x) for x in range(1, 13)]) # Add function keys
+
+if wx.Platform == '__WXMSW__':
+ KEYS.remove('Tab')
+
+MODIFIERS = ['', 'Alt', 'Shift']
+if wx.Platform == '__WXMAC__':
+ MODIFIERS.append('Cmd')
+else:
+ MODIFIERS.append('Ctrl')
+MODIFIERS.sort()
+
+class KeyBindingPanel(wx.Panel):
+ """Keybinding configuration options"""
+ def __init__(self, parent):
+ """Create the panel"""
+ super(KeyBindingPanel, self).__init__(parent)
+
+ # Attributes
+ self._dirty = False
+ self.menub = wx.GetApp().GetActiveWindow().GetMenuBar()
+ self.binder = ed_menu.KeyBinder()
+ self.menumap = dict()
+
+ # Load the Menu Map
+ for item in self.menub.GetMenuMap():
+ for key, val in item.iteritems():
+ if len(val):
+ if isinstance(val[0], int):
+ val = val[1:]
+ self.menumap[key] = sorted(val, key=lambda x: x[1])
+
+ # Layout
+ self._DoLayout()
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ self.Bind(wx.EVT_CHOICE, self.OnChoice)
+ self.Bind(wx.EVT_LISTBOX, self.OnListBox)
+ self.Bind(wx.EVT_UPDATE_UI,
+ lambda evt: evt.Enable(self.Dirty),
+ id=wx.ID_APPLY)
+
+ def _DoLayout(self):
+ """Layout the controls"""
+ msizer = wx.BoxSizer(wx.VERTICAL) # Main Sizer
+ spacer = ((5, 5), 0)
+
+ # Key profile section
+ profsz = wx.BoxSizer(wx.HORIZONTAL)
+ kprofiles = self.binder.GetKeyProfiles()
+ # Add an empty selection for the default profile
+ if len(kprofiles):
+ kprofiles.insert(0, u'')
+ cprofile = Profile_Get('KEY_PROFILE', default=None)
+ profiles = wx.Choice(self, ed_glob.ID_KEY_PROFILES, choices=kprofiles)
+ profiles.Enable(len(kprofiles))
+ if cprofile is None:
+ profiles.SetStringSelection(u'')
+ else:
+ profiles.SetStringSelection(cprofile)
+ profsz.AddMany([spacer,
+ (wx.StaticText(self, label=_("Key Profile") + u":"),
+ 0, wx.ALIGN_CENTER_VERTICAL), spacer,
+ (profiles, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL),
+ spacer, (wx.Button(self, wx.ID_NEW, _("New")), 0),
+ spacer, (wx.Button(self, wx.ID_DELETE, _("Delete")), 0),
+ spacer])
+
+ # Left Side Sizer
+ lvsizer = wx.BoxSizer(wx.VERTICAL)
+ menus = wx.Choice(self, ID_MENUS, choices=sorted(self.menumap.keys()))
+ menus.SetSelection(0)
+ milbls = [ item[1]
+ for item in self.menumap.get(menus.GetStringSelection()) ]
+ lvsizer.AddMany([(wx.StaticText(self, label=_("Menu") + u":"),
+ 0, wx.ALIGN_LEFT), spacer,
+ (menus, 0, wx.ALIGN_LEFT|wx.EXPAND), spacer,
+ (wx.ListBox(self, ID_MENU_ITEMS,
+ choices=sorted(milbls),
+ style=wx.SIMPLE_BORDER), 1, wx.EXPAND),
+ spacer])
+
+ # Right Side Sizer
+ rvsizer = wx.BoxSizer(wx.VERTICAL)
+ rvsizer.AddMany([(wx.StaticText(self, label=_("Modifier 1") + u":"),
+ 0, wx.ALIGN_LEFT), spacer,
+ (wx.Choice(self, ID_MOD1, choices=MODIFIERS),
+ 0, wx.ALIGN_LEFT|wx.EXPAND), spacer,
+ (wx.StaticText(self, label=_("Modifier 2") + u":"),
+ 0, wx.ALIGN_LEFT), spacer,
+ (wx.Choice(self, ID_MOD2, choices=[]),
+ 0, wx.ALIGN_LEFT|wx.EXPAND), spacer,
+ (wx.StaticText(self, label=_("Key") + u":"),
+ 0, wx.ALIGN_LEFT), spacer,
+ (wx.Choice(self, ID_KEYS, choices=KEYS),
+ 0, wx.ALIGN_LEFT|wx.EXPAND), spacer,
+ (wx.StaticText(self, label=_("Binding") + u":"),
+ 0, wx.ALIGN_LEFT), spacer,
+ (wx.StaticText(self, ID_BINDING, ""),
+ 0, wx.ALIGN_LEFT),
+ # Reserve size for widest string
+ ((self.GetTextExtent('Ctrl+Shift+Right')[0], 1), 0),
+ ])
+
+ # Lower Section
+ lmsizer = wx.BoxSizer(wx.HORIZONTAL)
+ lmsizer.AddMany([spacer, (lvsizer, 1, wx.EXPAND), ((10, 10), 0),
+ (rvsizer, 0, wx.EXPAND), spacer])
+
+ # Main Layout
+ line_sz = wx.BoxSizer(wx.HORIZONTAL)
+ line_sz.AddMany([(5, 1),
+ (wx.StaticLine(self, size=(-1, 1)), 1, wx.EXPAND),
+ (5, 1)])
+ line_sz2 = wx.BoxSizer(wx.HORIZONTAL)
+ line_sz2.AddMany([(5, 1),
+ (wx.StaticLine(self, size=(-1, 1)), 1, wx.EXPAND),
+ (5, 1)])
+ bsizer = wx.BoxSizer(wx.HORIZONTAL)
+ bsizer.AddMany([spacer, (wx.Button(self, wx.ID_REVERT,
+ _("Revert to Default")), 0, wx.ALIGN_LEFT),
+ ((-1, 5), 1, wx.EXPAND),
+ (wx.Button(self, wx.ID_APPLY, _("Apply")),
+ 0, wx.ALIGN_RIGHT), spacer])
+ msizer.AddMany([((10, 10), 0), (profsz, 0, wx.EXPAND), spacer,
+ (line_sz, 0, wx.EXPAND), spacer,
+ (lmsizer, 1, wx.EXPAND), ((10, 10), 0),
+ (line_sz2, 0, wx.EXPAND), spacer,
+ (bsizer, 0, wx.EXPAND), spacer])
+
+ # Use the small buttons on mac
+ if wx.Platform == '__WXMAC__':
+ for item in (wx.ID_REVERT, wx.ID_APPLY):
+ self.FindWindowById(item).SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
+
+ self.SetSizer(msizer)
+
+ # Setup control status
+ self.ClearKeyView()
+ self.EnableControls(len(profiles.GetStringSelection()))
+
+ def _GetMenuId(self):
+ """Get the id of the currently selected menu item
+ @return: int or None
+
+ """
+ sel_idx = self.FindWindowById(ID_MENU_ITEMS).GetSelection()
+ cmenu = self.FindWindowById(ID_MENUS).GetStringSelection()
+ menu_id = self.menumap.get(cmenu)[sel_idx][0]
+ return menu_id
+
+ def _UpdateBinding(self):
+ """Update the current keybinding and its display"""
+ binding = self.FindWindowById(ID_BINDING) # StaticText
+ bvalue = self.GetBindingValue()
+ bstr = u"+".join(bvalue)
+ if not len(bstr):
+ bstr = _("None")
+ binding.SetLabel(bstr)
+
+ def _UpdateKeyDisplay(self, keys):
+ """Update the controls that show the key binding of the current
+ menu item.
+ @param keys: tuple of keys
+
+ """
+ mod1 = self.FindWindowById(ID_MOD1) # Choice
+ mod1.SetItems(MODIFIERS)
+ mod2 = self.FindWindowById(ID_MOD2) # Choice
+ mod2.Enable()
+ key = self.FindWindowById(ID_KEYS) # Choice
+
+ if keys is None:
+ keys = ('')
+
+ # Change the main meta key for display reasons to keep it from
+ # being confused with the actual ctrl key since wx translates ctrl
+ # to apple key (cmd) automatically.
+ if wx.Platform == '__WXMAC__' and len(keys) and 'Ctrl' in keys:
+ nkeys = list()
+ for keystr in keys:
+ if keystr == 'Ctrl':
+ nkeys.append('Cmd')
+ else:
+ nkeys.append(keystr)
+ keys = nkeys
+
+ if len(keys) >= 3:
+ mod1.SetStringSelection(keys[0])
+ tmods = list(MODIFIERS)
+ tmods.remove(keys[0])
+ mod2.SetItems(tmods)
+ mod2.SetStringSelection(keys[1])
+ key.SetStringSelection(keys[2])
+ elif len(keys) == 2:
+ mod1.SetStringSelection(keys[0])
+ tmods = list(MODIFIERS)
+ tmods.remove(keys[0])
+ mod2.SetItems(tmods)
+ mod2.SetStringSelection('')
+ key.SetStringSelection(keys[1])
+ elif len(keys) == 1 and keys[0] in KEYS:
+ self.ClearKeyView()
+ key.SetStringSelection(keys[0])
+ else:
+ self.ClearKeyView()
+
+ self._UpdateBinding()
+
+ #---- Properties ----#
+
+ Dirty = property(lambda self: self._dirty,
+ lambda self, bDirty: setattr(self, '_dirty', bDirty))
+
+ def ClearKeyView(self):
+ """Clear all selections in the keybinding controls"""
+ self.FindWindowById(ID_MOD1).SetStringSelection('')
+ mod2 = self.FindWindowById(ID_MOD2) # Choice
+ mod2.Clear()
+ mod2.Disable()
+ self.FindWindowById(ID_KEYS).SetStringSelection('')
+ self._UpdateBinding()
+
+ def EnableControls(self, enable=True):
+ """Enable/Disable the controls for editing the keybinding settings
+ @keyword enable: enable (True), disable (False)
+
+ """
+ for ctrl in (ID_MENUS, ID_MENU_ITEMS,
+ wx.ID_APPLY, wx.ID_REVERT, wx.ID_DELETE):
+ self.FindWindowById(ctrl).Enable(enable)
+
+ self.EnableKeyView(enable)
+
+ def EnableKeyView(self, enable=True):
+ """Enable/Disable the key view/edit controls
+ @keyword enable: enable (True), disable (False)
+
+ """
+ for ctrl in (ID_MOD1, ID_MOD2, ID_KEYS, ID_BINDING):
+ self.FindWindowById(ctrl).Enable(enable)
+
+ def GetBindingValue(self):
+ """Get the values of the keybindings selected in the choice controls
+ @return: list
+
+ """
+ rval = list()
+ for cid in (ID_MOD1, ID_MOD2, ID_KEYS):
+ val = self.FindWindowById(cid).GetStringSelection()
+ if len(val):
+ rval.append(val)
+ return rval
+
+ def OnButton(self, evt):
+ """Handle button events
+ @param evt: wx.CommandEvent
+
+ """
+ e_id = evt.GetId()
+ profiles = self.FindWindowById(ed_glob.ID_KEY_PROFILES)
+ csel = profiles.GetStringSelection()
+ if e_id == wx.ID_NEW:
+ dlg = wx.TextEntryDialog(self, _("New Profile"),
+ _("Enter the name of the new key profile"))
+ dlg.ShowModal()
+ val = dlg.GetValue()
+ if len(val):
+ choices = profiles.GetItems() + ['', val]
+ profiles.SetItems(sorted(list(set(choices))))
+ profiles.SetStringSelection(val)
+ self.menub.NewKeyProfile(val)
+ profiles.Enable(len(profiles.GetItems()))
+ self.EnableControls(len(profiles.GetItems()))
+ elif e_id == wx.ID_DELETE:
+ val = profiles.GetStringSelection()
+ if val:
+ # Remove the selected profile
+ items = profiles.GetItems()
+ items.remove(val)
+ self.menub.DeleteKeyProfile(val)
+ if len(items) == 1 and items[0] == '':
+ items = list()
+
+ profiles.SetItems(items)
+ profiles.Enable(len(items))
+ if len(items):
+ profiles.SetSelection(0)
+
+ self.EnableControls(len(profiles.GetItems()))
+ csel = profiles.GetStringSelection()
+ if csel:
+ Profile_Set('KEY_PROFILE', csel)
+ else:
+ Profile_Set('KEY_PROFILE', None) # Use defaults
+ ed_msg.PostMessage(ed_msg.EDMSG_MENU_LOADPROFILE,
+ Profile_Get('KEY_PROFILE', default=None))
+ elif e_id == wx.ID_REVERT:
+ # Revert to the original settings
+ Profile_Set('KEY_PROFILE', None)
+ ed_msg.PostMessage(ed_msg.EDMSG_MENU_LOADPROFILE, None)
+ self.menub.SaveKeyProfile()
+ self.FindWindowById(ed_glob.ID_KEY_PROFILES).SetStringSelection('')
+ self.EnableControls(False)
+ elif e_id == wx.ID_APPLY:
+ # Update the menu(s) to the new settings
+ profiles = self.FindWindowById(ed_glob.ID_KEY_PROFILES)
+ csel = profiles.GetStringSelection()
+ if not len(csel):
+ csel = None
+ Profile_Set('KEY_PROFILE', csel)
+ ed_msg.PostMessage(ed_msg.EDMSG_MENU_REBIND)
+ self.menub.SaveKeyProfile()
+ else:
+ evt.Skip()
+
+ def OnChoice(self, evt):
+ """Handle selections in the choice controls
+ @param evt: wx.CommandEvent
+
+ """
+ e_id = evt.GetId()
+ csel = evt.GetEventObject().GetStringSelection()
+ if e_id == ed_glob.ID_KEY_PROFILES:
+ if not len(csel):
+ csel = None
+ self.binder.LoadKeyProfile(csel)
+ Profile_Set('KEY_PROFILE', csel)
+ ed_msg.PostMessage(ed_msg.EDMSG_MENU_REBIND)
+ self.menub.SaveKeyProfile()
+ self.EnableControls(csel is not None)
+ elif e_id == ID_MENUS:
+ mi_listbx = self.FindWindowById(ID_MENU_ITEMS)
+ if mi_listbx is not None:
+ mi_listbx.SetItems([item[1] for item in self.menumap.get(csel)])
+ self.ClearKeyView()
+ elif e_id == ID_MOD1:
+ mod2 = self.FindWindowById(ID_MOD2)
+ if not len(csel):
+ mod2.Clear()
+ mod2.Disable()
+ else:
+ mod2.Enable()
+ tmods = list(MODIFIERS)
+ tmods.remove(csel)
+ mod2.SetItems(tmods)
+ mod2.SetStringSelection('')
+ self._UpdateBinding()
+ self.Dirty = True
+ elif e_id in [ID_MOD2, ID_KEYS]:
+ self._UpdateBinding()
+ self.Dirty = True
+ else:
+ evt.Skip()
+
+ # Update the keybinding
+ if e_id in (ID_MOD1, ID_MOD2, ID_KEYS):
+ bval = u"+".join(self.GetBindingValue())
+ bval = bval.replace('Cmd', 'Ctrl', 1)
+ self.binder.SetBinding(self._GetMenuId(), bval)
+
+ def OnListBox(self, evt):
+ """Handle listbox selections and update binding display
+ @param evt: wx.CommandEvent
+
+ """
+ if evt.GetId() == ID_MENU_ITEMS:
+ sel_idx = evt.GetSelection()
+ cmenu = self.FindWindowById(ID_MENUS).GetStringSelection()
+ menu_id = self.menumap.get(cmenu)[sel_idx][0]
+ keys = self.binder.GetRawBinding(menu_id)
+ self._UpdateKeyDisplay(keys)
+ else:
+ evt.Skip()
+
+#----------------------------------------------------------------------------#
+
+class ExtListCtrl(eclib.EEditListCtrl):
+ """Class to manage the file extension associations
+ @summary: Creates a list control for showing file type to file extension
+ associations as well as providing an interface to editing these
+ associations
+
+ """
+ FILE_COL = 0
+ EXT_COL = 1
+ def __init__(self, parent):
+ """Initializes the Profile List Control
+ @param parent: The parent window of this control
+
+ """
+ super(ExtListCtrl, self).__init__(parent)
+
+# listmix.ListCtrlAutoWidthMixin.__init__(self)
+# eclib.ListRowHighlighter.__init__(self)
+
+ # Setup
+ self.InsertColumn(ExtListCtrl.FILE_COL, _("Lexer"))
+ self.InsertColumn(ExtListCtrl.EXT_COL, \
+ _("Extensions (space separated, no dots)"))
+ self._extreg = syntax.ExtensionRegister()
+ self._editing = None
+ self.LoadList()
+# listmix.TextEditMixin.__init__(self)
+
+ def CloseEditor(self, evt=None):
+ """Update list and extension register after edit window
+ closes.
+ @keyword evt: Action that triggered this function
+
+ """
+ super(ExtListCtrl, self).CloseEditor(evt)
+ def UpdateRegister(itempos):
+ """Update the ExtensionRegister
+ @param itempos: position of the item to base updates on
+
+ """
+ vals = self.GetItem(itempos[1], itempos[0]).GetText()
+ ftype = self.GetItem(itempos[1], ExtListCtrl.FILE_COL).GetText()
+ self._editing = None
+ self._extreg.SetAssociation(ftype, vals)
+
+ if self._editing != None:
+ wx.CallAfter(UpdateRegister, self._editing)
+ wx.CallAfter(self.UpdateExtensions)
+
+ def LoadList(self):
+ """Loads the list of filetypes to file extension mappings into the
+ list control.
+ @postcondition: The running configuration data that is kept by the
+ syntax manager that relates to file associations is
+ loaded into the list control in alphabetical order
+
+ """
+ for key in sorted(self._extreg.keys()):
+ index = self.InsertStringItem(sys.maxint, key)
+ self.SetStringItem(index, ExtListCtrl.FILE_COL, key)
+ self.SetStringItem(index, ExtListCtrl.EXT_COL, \
+ u' %s' % u' '.join(self._extreg[key]))
+
+ self.SetColumnWidth(ExtListCtrl.FILE_COL, wx.LIST_AUTOSIZE)
+ self.SetColumnWidth(ExtListCtrl.EXT_COL, wx.LIST_AUTOSIZE)
+
+ def OpenEditor(self, col, row):
+ """Disable the editor for the first column
+ @param col: Column to edit
+ @param row: Row to edit
+
+ """
+ if col != self.FILE_COL:
+ self._editing = (col, row)
+ super(ExtListCtrl, self).OpenEditor(col, row)
+
+ def UpdateExtensions(self):
+ """Updates the values in the EXT_COL to reflect changes
+ in the ExtensionRegister.
+ @postcondition: Any configuration changes made in the control are
+ set in the Extension register.
+ @see: L{syntax.syntax.ExtensionRegister}
+
+ """
+ for row in range(self.GetItemCount()):
+ ftype = self.GetItem(row, ExtListCtrl.FILE_COL).GetText()
+ self.SetStringItem(row, ExtListCtrl.EXT_COL, \
+ u' ' + u' '.join(self._extreg[ftype]))
+
+#----------------------------------------------------------------------------#
+
+class ExChoice(wx.Choice):
+ """Class to extend wx.Choice to have the GetValue
+ function. This allows the application function to remain
+ uniform in its value retrieval from all objects. This also extends
+ wx.Choice to have a default selected value on init.
+
+ """
+ def __init__(self, parent, cid=wx.ID_ANY, choices=list(), default=None):
+ """Constructs a Choice Control
+ @param parent: The parent window of this control
+
+ """
+ if len(choices) and isinstance(choices[0], int):
+ choices = [ unicode(choice) for choice in choices ]
+
+ super(ExChoice, self).__init__(parent, cid, choices=choices)
+
+ if default != None and isinstance(default, basestring):
+ self.SetStringSelection(default)
+ elif default is not None:
+ self.SetSelection(default)
+
+ def GetValue(self):
+ """Gets the Selected Value
+ @return: the value of the currently selected item
+ @rtype: string
+
+ """
+ val = self.GetStringSelection()
+ if val.isalpha():
+ val.lower()
+ return val
+
+#-----------------------------------------------------------------------------#
+# Utility Functions
+
+def GetPrintModeStrings():
+ """Get the strings for describing the print modes
+ @note: defined in a function so translations can take place at runtime
+ @note: Order must be kept in sync with the PRINT_ vals in ed_glob
+
+ """
+ return [_('Black/White'), # PRINT_BLACK_WHITE
+ _('Colour/White'), # PRINT_COLOR_WHITE
+ _('Colour/Default'), # PRINT_COLOR_DEF
+ _('Inverse'), # PRINT_INVERSE
+ _('Normal')] # PRINT_NORMAL
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/profiler.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/profiler.py
new file mode 100644
index 0000000..68127e5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/profiler.py
@@ -0,0 +1,456 @@
+###############################################################################
+# Name: profiler.py #
+# Purpose: Editra's user profile services #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This module provides the profile object and support functions for loading and
+saving user preferences between sessions. The preferences are saved on disk as
+a cPickle, because of this no objects that cannot be resolved in the namespace
+of this module prior to starting the mainloop must not be put in the Profile as
+it will cause errors on load. Ths means that only builtin python types should
+be used and that a translation from that type to the required type should
+happen during run time.
+
+@summary: Editra's user profile management
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: profiler.py 71278 2012-04-25 15:47:19Z CJP $"
+__revision__ = "$Revision: 71278 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import sys
+import cPickle
+import wx
+
+# Editra Imports
+from ed_glob import CONFIG, PROG_NAME, VERSION, PRINT_BLACK_WHITE, EOL_MODE_LF
+import util
+import dev_tool
+import ed_msg
+
+_ = wx.GetTranslation
+#--------------------------------------------------------------------------#
+# Globals
+_DEFAULTS = {
+ 'ALPHA' : 255, # Transparency level (0-255)
+ 'AALIASING' : False, # Use Anti-Aliasing if availble
+ 'APPSPLASH' : True, # Show splash at startup
+ 'AUTOBACKUP' : False, # Automatically backup files
+ 'AUTOBACKUP_PATH' : '', # Backup path
+ 'AUTOBACKUP_SUFFIX' : '.edbkup', # Backup suffix (e.g. .edbkup, ~)
+ 'AUTO_COMP' : True, # Use Auto-comp if available
+ 'AUTO_COMP_EX' : False, # Use extended autocompletion
+ 'AUTO_INDENT': True, # Use Auto Indent
+ 'AUTO_TRIM_WS' : False, # Trim whitespace on save
+ 'AUTO_RELOAD' : False, # Automatically reload files?
+ 'BRACKETHL' : True, # Use bracket highlighting
+ 'BSUNINDENT' : True, # Backspace Unindents
+ 'CARETWIDTH' : 1, # Preferred cursor width
+ 'CHECKMOD' : True, # Auto check file for file mod
+ 'CHECKUPDATE': True, # Check for updates on start
+ 'CODE_FOLD' : True, # Use code folding
+ 'CTRLBAR' : dict(), # ControlBar layouts
+ 'DEFAULT_LEX': 'Plain Text', # Default lexer for new documents
+ 'DEFAULT' : False, # No longer used I believe
+ 'DEFAULT_VIEW' : 'Automatic', # Default Perspective
+ 'EDGE' : 80, # Edge guide column
+ 'ENCODING' : None, # Prefered text encoding
+ 'EOL_MODE' : EOL_MODE_LF, # EOL mode 1 == LF, 2 == CRLF
+ 'FHIST' : list(), # List of history files
+ 'FHIST_LVL' : 9, # Filehistory length (9 is max)
+ 'FFILTER' : 0, # Last file filter used
+ 'GUIDES' : False, # Use Indentation guides
+ 'HLCARETLINE': False, # Highlight Caret Line
+ 'ICONS' : 'Tango', # Icon Theme
+ 'ICON_SZ' : (16, 16), # Toolbar Icon Size
+ 'INDENTWIDTH': 4, # Default indent width
+ 'ISBINARY' : False, # Is this instance a binary
+ 'KEY_PROFILE': None, # Keybinding profile
+ 'LANG' : 'Default', # UI language
+ 'LASTCHECK' : 0, # Last time update check was done
+ #'LEXERMENU' : [lang_name,] # Created on an as needed basis
+ 'MAXIMIZED' : False, # Was window maximized on exit
+ 'MODE' : 'CODE', # Overall editor mode
+ 'MYPROFILE' : 'default.ppb', # Path to profile file
+ 'OPEN_NW' : False, # Open files in new windows
+ 'PRINT_MODE' : PRINT_BLACK_WHITE,# Printer rendering mode
+ 'PROXY_SETTINGS' : dict(), # Proxy Server Settings
+ 'REPORTER' : True, # Error Reporter is Active
+ 'SAVE_POS' : True, # Remember Carat positions
+ 'SAVE_SESSION' : False, # Load previous session on startup
+ 'SEARCH_LOC' : list(), # Recent Search Locations
+ 'SEARCH_FILTER' : '', # Last used search filter
+ 'SESSION_KEY' : '', # Ipc Session Server Key
+ 'SET_WPOS' : True, # Remember window position
+ 'SET_WSIZE' : True, # Remember mainwindow size on exit
+ 'SHOW_EDGE' : True, # Show Edge Guide
+ 'SHOW_EOL' : False, # Show EOL markers
+ 'SHOW_LN' : True, # Show Line Numbers
+ 'SHOW_WS' : False, # Show whitespace markers
+ 'SPELLCHECK' : dict(auto=False,
+ dict='en_US',
+ epath=None), # Spell checking preferences
+ 'STATBAR' : True, # Show Status Bar
+ 'SYNTAX' : True, # Use Syntax Highlighting
+ 'SYNTHEME' : 'Default', # Syntax Highlight color scheme
+ 'TABICONS' : True, # Show Tab Icons
+ 'TABWIDTH' : 8, # Tab width
+ 'THEME' : 'DEFAULT', # For future use
+ 'TOOLBAR' : True, # Show Toolbar
+ 'USETABS' : False, # Use tabs instead of spaces
+ 'USE_PROXY' : False, # Use Proxy server settings?
+ 'VIEWVERTSPACE' : False, # Allow extra virtual space in buffer
+ 'VI_EMU' : False, # Use Vi emulation mode
+ 'VI_NORMAL_DEFAULT' : False, # Use Normal mode by default
+ 'WARN_EOL' : True, # Warn about mixed eol characters
+ 'WRAP' : False, # Use Wordwrap
+ 'WSIZE' : (700, 450) # Mainwindow size
+ #FONT1 created at runtime by ed_styles as primary font
+ #FONT2 created at runtime by ed_styles as secondary font
+ #FONT3 Standard Font by UI, added to profile when customized
+}
+
+#--------------------------------------------------------------------------#
+
+class Profile(dict):
+ """Class for managing profile data. All data is stored as builtin
+ python objects (i.e. str, tuple, list, ect...) however on a request
+ for data the object can be transformed in to a requested type where
+ applicable. The profile saves itself to disk using the cPickle module
+ to preserve data types and allow for easy loading.
+
+ """
+ _instance = None
+ _created = False
+
+ def __init__(self):
+ """Initialize the profile"""
+ if not self._created:
+ dict.__init__(self)
+ else:
+ pass
+
+ def __new__(cls, *args, **kargs):
+ """Maintain only a single instance of this object
+ @return: instance of this class
+
+ """
+ if cls._instance is None:
+ cls._instance = dict.__new__(cls, *args, **kargs)
+ return cls._instance
+
+ #---- End Private Members ----#
+
+ #---- Begin Public Members ----#
+ def DeleteItem(self, item):
+ """Removes an entry from the profile
+ @param item: items name
+
+ """
+ if item in self:
+ del self[item]
+ else:
+ pass
+
+ def Get(self, index, fmt=None, default=None):
+ """Gets the specified item from the data set
+
+ @param index: index of item to get
+ @keyword fmt: format the item should be in
+ @keyword default: Default value to return if index is
+ not in profile.
+
+ """
+ if index in self:
+ val = self.__getitem__(index)
+ else:
+ return default
+
+ if fmt is None:
+ return val
+ else:
+ return _ToObject(index, val, fmt)
+
+ def Load(self, path):
+ """Load the profiles data set with data from the given file
+ @param path: path to file to load data from
+ @note: The files data must have been written with a pickler
+
+ """
+ if os.path.exists(path):
+ try:
+ fhandle = open(path, 'rb')
+ val = cPickle.load(fhandle)
+ fhandle.close()
+ except (IOError, SystemError, OSError,
+ cPickle.UnpicklingError, EOFError), msg:
+ dev_tool.DEBUGP("[profile][err] %s" % str(msg))
+ else:
+ if isinstance(val, dict):
+ self.update(val)
+ self.Set('MYPROFILE', path)
+ dev_tool.DEBUGP("[profile][info] Loaded %s" % path)
+ else:
+ dev_tool.DEBUGP("[profile][err] %s does not exist" % path)
+ dev_tool.DEBUGP("[profile][info] Loading defaults")
+ self.LoadDefaults()
+ self.Set('MYPROFILE', path)
+ return False
+
+ # Update profile to any keys that are missing
+ for key in _DEFAULTS:
+ if key not in self:
+ self.Set(key, _DEFAULTS[key])
+ return True
+
+ def LoadDefaults(self):
+ """Loads the default values into the profile
+ @return: None
+
+ """
+ self.clear()
+ self.update(_DEFAULTS)
+
+ def Set(self, index, val, fmt=None):
+ """Set the value of the given index
+ @param index: Index to set
+ @param val: Value to set
+ @keyword fmt: Format to convert to string from
+
+ """
+ if fmt is None:
+ self.__setitem__(index, val)
+ else:
+ self.__setitem__(index, _FromObject(val, fmt))
+
+ # Notify all clients with the configuration change message
+ ed_msg.PostMessage(ed_msg.EDMSG_PROFILE_CHANGE + (index,), val)
+
+ def Write(self, path):
+ """Write the dataset of this profile as a pickle
+ @param path: path to where to write the pickle
+ @return: True on success / False on failure
+
+ """
+ try:
+ # Only write if given an absolute path
+ if not os.path.isabs(path):
+ return False
+ self.Set('MYPROFILE', path)
+ fhandle = open(path, 'wb')
+ cPickle.dump(self.copy(), fhandle, cPickle.HIGHEST_PROTOCOL)
+ fhandle.close()
+ UpdateProfileLoader()
+ except (IOError, cPickle.PickleError), msg:
+ dev_tool.DEBUGP(u"[profile][err] %s" % msg)
+ return False
+ else:
+ return True
+
+ def Update(self, update=None):
+ """Update the profile using data from provided dictionary
+ or the default set if none is given.
+ @keyword update: dictionary of values to update from or None
+ @postcondition: All profile values from the update set are set
+ in this profile. If update is None then the current
+ set is only updated to include values from the
+ DEFAULTS that are not currently present.
+
+ """
+ if update is None:
+ for key, val in _DEFAULTS.iteritems():
+ if key not in self:
+ self.Set(key, val)
+ else:
+ self.update(update)
+
+ #---- End Public Members ----#
+
+#-----------------------------------------------------------------------------#
+# Singleton reference instance
+
+TheProfile = Profile()
+
+#-----------------------------------------------------------------------------#
+# Profile convenience functions
+Profile_Del = TheProfile.DeleteItem
+Profile_Get = TheProfile.Get
+Profile_Set = TheProfile.Set
+
+def _FromObject(val, fmt):
+ """Convert the given value to a to a profile compatible value
+ @param val: value to convert
+ @param fmt: Format to convert to (string)
+
+ """
+ if fmt == u'font' and isinstance(val, wx.Font):
+ return "%s,%s" % (val.GetFaceName(), val.GetPointSize())
+ else:
+ return val
+
+def _ToObject(index, val, fmt):
+ """Convert the given value to a different object
+ @param index: fallback to retrieve item from defaults
+ @param val: value to convert
+ @param fmt: Format to convert to
+ @todo: exception handling,
+
+ """
+ tmp = fmt.lower()
+ if tmp == u'font':
+ fnt = val.split(',')
+ rval = wx.FFont(int(fnt[1]), wx.DEFAULT, face=fnt[0])
+ elif tmp == u'bool':
+ if isinstance(val, bool):
+ rval = val
+ else:
+ rval = _DEFAULTS.get(index, False)
+ elif tmp == u'size_tuple':
+ if len(val) == 2 and \
+ isinstance(val[0], int) and isinstance(val[1], int):
+ rval = val
+ else:
+ rval = _DEFAULTS.get(index, wx.DefaultSize)
+ elif tmp == u'str':
+ rval = unicode(val)
+ elif tmp == u'int':
+ if isinstance(val, int):
+ rval = val
+ elif isinstance(val, basestring) and val.isdigit():
+ rval = int(val)
+ else:
+ rval = _DEFAULTS.get(index)
+ else:
+ return val
+ return rval
+
+#---- Begin Function Definitions ----#
+
+def CalcVersionValue(ver_str="0.0.0"):
+ """Calculates a version value from the provided dot-formated string
+
+ 1) SPECIFICATION: Version value calculation AA.BBB.CCC
+ - major values: < 1 (i.e 0.0.85 = 0.850)
+ - minor values: 1 - 999 (i.e 0.1.85 = 1.850)
+ - micro values: >= 1000 (i.e 1.1.85 = 1001.850)
+
+ @keyword ver_str: Version string to calculate value of
+
+ """
+ ver_str = ''.join([char for char in ver_str
+ if char.isdigit() or char == '.'])
+ ver_lvl = ver_str.split(u".")
+ if len(ver_lvl) < 3:
+ return 0
+
+ major = int(ver_lvl[0]) * 1000
+ minor = int(ver_lvl[1])
+ if len(ver_lvl[2]) <= 2:
+ ver_lvl[2] += u'0'
+ micro = float(ver_lvl[2]) / 1000
+ return float(major) + float(minor) + micro
+
+def GetLoader():
+ """Finds the loader to use
+ @return: path to profile loader
+ @note: path may not exist, only returns the path to where the loader
+ should be.
+
+ """
+ cbase = util.GetUserConfigBase()
+ loader = os.path.join(cbase, u"profiles", u".loader2")
+ return loader
+
+def GetProfileStr():
+ """Reads the profile string from the loader and returns it.
+ The profile string must be the first line in the loader file.
+ @return: path of profile used in last session
+
+ """
+ reader = util.GetFileReader(GetLoader())
+ if reader == -1:
+ # So return the default
+ return CONFIG['PROFILE_DIR'] + u"default.ppb"
+
+ profile = reader.readline()
+ profile = profile.strip()
+ reader.close()
+ if not os.path.isabs(profile):
+ profile = CONFIG['PROFILE_DIR'] + profile
+ return profile
+
+def ProfileIsCurrent():
+ """Checks if profile is compatible with current editor version
+ and returns a bool stating if it is or not.
+ @return: whether profile on disk was written with current program version
+
+ """
+ if CalcVersionValue(ProfileVersionStr()) >= CalcVersionValue(VERSION):
+ return True
+ else:
+ return False
+
+def ProfileVersionStr():
+ """Checks the Loader for the profile version string and
+ returns the version string. If there is an error or the
+ string is not found it returns a zero version string.
+ @return: the version string value from the profile loader file
+
+ """
+ loader = GetLoader()
+ reader = util.GetFileReader(loader, sys.getfilesystemencoding())
+ if reader == -1:
+ return "0.0.0"
+
+ ret_val = "0.0.0"
+ count = 0
+ while True:
+ count += 1
+ value = reader.readline()
+ value = value.split()
+ if len(value) > 0:
+ if value[0] == u'VERSION':
+ ret_val = value[1]
+ break
+ # Give up after 20 lines if version string not found
+ if count > 20:
+ break
+ reader.close()
+
+ return ret_val
+
+def UpdateProfileLoader():
+ """Updates Loader File
+ @precondition: MYPROFILE has been set
+ @postcondition: on disk profile loader is updated
+ @return: 0 if no error, non zero for error condition
+
+ """
+ writer = util.GetFileWriter(GetLoader())
+ if writer == -1:
+ return 1
+
+ prof_name = Profile_Get('MYPROFILE')
+ if not prof_name or not os.path.isabs(prof_name):
+ prof_name = CONFIG['PROFILE_DIR'] + 'default.ppb'
+
+ if not os.path.exists(prof_name):
+ prof_name = os.path.join(CONFIG['CONFIG_DIR'],
+ os.path.basename(prof_name))
+ Profile_Set('MYPROFILE', prof_name)
+
+ # Use just the relative profile name for local(portable) config paths
+ prof_name = os.path.basename(prof_name)
+
+ writer.write(prof_name)
+ writer.write(u"\nVERSION\t" + VERSION)
+ writer.close()
+ return 0
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/style_editor.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/style_editor.py
new file mode 100644
index 0000000..deafb20
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/style_editor.py
@@ -0,0 +1,919 @@
+###############################################################################
+# Name: style_editor.py #
+# Purpose: Syntax Highlighting configuration dialog #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008-2011 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides an editor dialog for graphically editing how the text is presented in
+the editor when syntax highlighting is turned on. It does this by taking the
+data from the controls and formating it into an Editra Style Sheet that the
+editor can load to configure the styles of the text.
+
+@summary: Gui for creating custom Editra Style Sheets
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: style_editor.py 70228 2011-12-31 20:39:16Z CJP $"
+__revision__ = "$Revision: 70228 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import glob
+import wx
+
+# Editra Imports
+import ed_glob
+from profiler import Profile_Get, Profile_Set
+import ed_basestc
+from ed_style import StyleItem
+import util
+import syntax.syntax as syntax
+import eclib
+import ebmlib
+import ed_basewin
+
+# Function Aliases
+_ = wx.GetTranslation
+
+# Global Values
+ID_FORE_COLOR = wx.NewId()
+ID_BACK_COLOR = wx.NewId()
+ID_BOLD = wx.NewId()
+ID_ITALIC = wx.NewId()
+ID_EOL = wx.NewId()
+ID_ULINE = wx.NewId()
+ID_FONT = wx.NewId()
+ID_FONT_SIZE = wx.NewId()
+
+SETTINGS_IDS = [ ID_FORE_COLOR, ID_BACK_COLOR, ID_BOLD, ID_ITALIC,
+ ID_EOL, ID_ULINE, ID_FONT, ID_FONT_SIZE ]
+
+# Modification Flags
+MOD_NONE = 0
+MOD_DOESNT_EXIST = 1
+MOD_CHANGE_PRESENT = 2
+
+#--------------------------------------------------------------------------#
+
+class StyleEditor(ed_basewin.EdBaseDialog):
+ """This class creates the window that contains the controls
+ for editing/configuring the syntax highlighting styles it acts
+ as a graphical way to interact with the L{ed_style.StyleMgr}.
+
+ @see: ed_style.StyleMgr
+ """
+ def __init__(self, parent, id_=wx.ID_ANY, title=_("Style Editor"),
+ style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER):
+ super(StyleEditor, self).__init__(parent, id_, title, style=style)
+
+ # Attributes
+ self.LOG = wx.GetApp().GetLog()
+ self._panel = StyleEditorBox(self) #TODO
+
+ # Layout
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(self._panel, 1, wx.EXPAND)
+
+ # Create Buttons
+ b_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ ok_b = wx.Button(self, wx.ID_OK, _("Ok"))
+ ok_b.SetDefault()
+ b_sizer.AddMany([(wx.Button(self, wx.ID_CANCEL, _("Cancel")), 0),
+ ((5, 5), 0),
+ (wx.Button(self, wx.ID_SAVE, _("Save")), 0),
+ ((5, 5), 0), (ok_b, 0)])
+ sizer.Add(b_sizer, 0, wx.ALIGN_RIGHT |
+ wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
+
+ # Finish the Layout
+ self.SetSizer(sizer)
+ self.SetInitialSize()
+
+ # Event Handlers
+ self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
+ self.Bind(wx.EVT_BUTTON, self.OnOk, id=wx.ID_OK)
+ self.Bind(wx.EVT_BUTTON, self.OnSave, id=wx.ID_SAVE)
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+ #--- End Init ---#
+
+ def ExportStyleSheet(self):
+ """Writes the style sheet data out to a style sheet
+ @return: bool
+
+ """
+ saved = self._panel.SaveStyleSheet()
+ return saved
+
+ def OnCancel(self, evt):
+ """Catches the cancel button clicks and checks if anything
+ needs to be done before closing the window.
+ @param evt: event that called this handler
+
+ """
+ self.LOG('[style_editor][evt] Cancel Clicked Closing Window')
+ evt.Skip()
+
+ def OnClose(self, evt):
+ """Handles the window closer event
+ @param evt: event that called this handler
+
+ """
+ self.LOG("[style_editor][evt] Dialog closing...")
+ self.OnOk(evt)
+
+ def OnOk(self, evt):
+ """Catches the OK button click and checks if any changes need to be
+ saved before the window closes.
+ @param evt: event that called this handler
+
+ """
+ self.LOG('[style_editor][evt] Ok Clicked Closing Window')
+ modtype = self._panel.CheckForModifications()
+ result = wx.ID_NO
+ msg = None
+ if modtype == MOD_CHANGE_PRESENT:
+ msg = _("Some styles have been changed would "
+ "you like to save before exiting?")
+ elif modtype == MOD_DOESNT_EXIST:
+ msg = _("The new style sheet '%s' has not been saved "
+ "would you like to save before exiting?") % self._panel.StyleTheme
+ if msg is not None:
+ dlg = wx.MessageDialog(self, msg, _("Save Styles"),
+ style=wx.YES_NO | wx.YES_DEFAULT | \
+ wx.CANCEL | wx.ICON_INFORMATION)
+ dlg.CenterOnParent()
+ result = dlg.ShowModal()
+ dlg.Destroy()
+
+ if result == wx.ID_NO:
+ # Get Current Selection to update buffers
+ sheet = self._panel.StyleTheme
+ path = self._panel.GetStyleSheetPath(sheet)
+ if os.path.exists(path):
+ UpdateBufferStyles(sheet)
+ evt.Skip()
+ elif result == wx.ID_CANCEL:
+ self.LOG('[style_editor][info] canceled closing')
+ else:
+ result = self.ExportStyleSheet()
+ if result != wx.ID_CANCEL:
+ evt.Skip()
+
+ def OnSave(self, evt):
+ """Catches save button event
+ @param evt: event that called this handler
+
+ """
+ self.LOG('[style_editor][evt] Export Clicked')
+ self.ExportStyleSheet()
+
+#-----------------------------------------------------------------------------#
+
+class StyleEditorBox(ed_basewin.EdBaseCtrlBox):
+ """StyleEditor main Panel"""
+ def __init__(self, parent):
+ super(StyleEditorBox, self).__init__(parent)
+
+ # Attributes
+ self._prevTheme = None
+ ctrlbar = self.CreateControlBar(wx.TOP)
+ ss_lst = util.GetResourceFiles(u'styles', get_all=True, title=False)
+ ss_lst = [sheet for sheet in ss_lst if not sheet.startswith('.')]
+ self._style_ch = wx.Choice(ctrlbar, ed_glob.ID_PREF_SYNTHEME,
+ choices=sorted(ss_lst))
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_ADD), wx.ART_MENU)
+ if not bmp.IsOk():
+ bmp = None
+ self._addbtn = eclib.PlateButton(ctrlbar, label=_("New"),
+ bmp=bmp, style=eclib.PB_STYLE_NOBG)
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_REMOVE), wx.ART_MENU)
+ if not bmp.IsOk():
+ bmp = None
+ self._delbtn = eclib.PlateButton(ctrlbar, label=_("Remove"),
+ bmp=bmp, style=eclib.PB_STYLE_NOBG)
+
+ # Setup
+ ss_lbl = wx.StaticText(ctrlbar, label=_("Style Theme") + u": ")
+ ctrlbar.AddControl(ss_lbl, wx.ALIGN_LEFT)
+ self.StyleTheme = Profile_Get('SYNTHEME', 'str')
+ ctrlbar.AddControl(self._style_ch, wx.ALIGN_LEFT)
+ ctrlbar.AddControl(self._addbtn, wx.ALIGN_LEFT)
+ self._addbtn.SetToolTipString(_("Create a new style theme"))
+ ctrlbar.AddControl(self._delbtn, wx.ALIGN_LEFT)
+ self._delbtn.SetToolTipString(_("Remove Style"))
+ self.SetWindow(StyleEditorPanel(self))
+
+ # Events
+ self.Bind(wx.EVT_CHOICE, self.OnThemeChoice, self._style_ch)
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ self.Bind(wx.EVT_UPDATE_UI,
+ lambda evt: evt.Enable(not self.IsSystemStyleSheet()),
+ self._delbtn)
+
+ #--- Properties ----#
+ def __setStyleTheme(self, theme):
+ self._prevTheme = theme # Tracking for choice change
+ self._style_ch.SetStringSelection(theme)
+ StyleTheme = property(lambda self: self._style_ch.GetStringSelection(),
+ lambda self, val: self.__setStyleTheme(val))
+ SyntaxSheets = property(lambda self: self._style_ch.GetItems(),
+ lambda self, val: self._style_ch.SetItems(sorted(val)))
+
+ #---- Public Api ----#
+ def CheckForModifications(self, sheet_name=None):
+ """Check for any unsaved modifications to the styling information
+ @return: modification type
+
+ """
+ if sheet_name is None:
+ sheet_name = self.StyleTheme # currently selected
+ modtype = MOD_NONE
+ if self.Window.DiffStyles():
+ modtype = MOD_CHANGE_PRESENT
+ elif not self.SheetExistOnDisk(sheet_name):
+ modtype = MOD_DOESNT_EXIST
+ return modtype
+
+ def DoChangeStyleSheet(self, sheet_name):
+ """Change the StyleEditor for the given style sheet"""
+ if not self.SheetExistOnDisk(sheet_name):
+ # Changing to a fully transient style sheet that has
+ # not yet been written to disk.
+ self.SetDisplayForTransientSheet(sheet_name)
+ else:
+ self.Window.ChangeStyleSheet(sheet_name)
+ self.StyleTheme = sheet_name
+
+ def GetStyleSheetPath(self, sheet, syspath=False):
+ """Get the on disk path to where the style sheet should
+ be written to.
+ @param sheet: sheet name
+ @keyword syspath: look on the system install path
+ @return: path to the style sheet
+
+ """
+ if syspath:
+ cfgdir = ed_glob.CONFIG['SYS_STYLES_DIR'] # System Directory
+ else:
+ cfgdir = ed_glob.CONFIG['STYLES_DIR'] # User Directory
+ sheet_path = os.path.join(cfgdir, sheet)
+ sheet_path = ebmlib.AddFileExtension(sheet_path, '.ess')
+ return sheet_path
+
+ def IsSystemStyleSheet(self):
+ """Is the given style sheet a system provided one
+ @return: bool
+
+ """
+ # If it exists in user space it is not a system one
+ path = self.GetStyleSheetPath(self.StyleTheme)
+ return not os.path.exists(path)
+
+ def RefreshStyleSheets(self):
+ """Update the list of style sheets"""
+ ss_lst = util.GetResourceFiles(u'styles', get_all=True, title=False)
+ ss_lst = [sname for sname in ss_lst if not sname.startswith('.')]
+ self.SyntaxSheets = ss_lst
+
+ def SaveStyleSheet(self, sheetname=None):
+ """Save the changes to the currently selected StyleSheet
+ @return: bool
+
+ """
+ # Ensure user styles directory exists to save style sheet to
+ if ed_glob.CONFIG['STYLES_DIR'] == ed_glob.CONFIG['SYS_STYLES_DIR']:
+ path = util.GetUserConfigBase()
+ user_config = os.path.join(path, 'styles')
+ if not os.path.exists(user_config):
+ try:
+ os.mkdir(user_config)
+ except (OSError, IOError), msg:
+ util.Log("[style_editor][err] %s" % msg)
+ else:
+ ed_glob.CONFIG['STYLES_DIR'] = user_config
+
+ rval = False
+ if sheetname is None:
+ sheetname = self.StyleTheme
+ sheet_path = self.GetStyleSheetPath(sheetname)
+ if self.WriteStyleSheet(sheet_path):
+ # Update Style Sheet Control
+ self.RefreshStyleSheets()
+ sheet = u".".join(os.path.basename(sheet_path).split(u'.')[:-1])
+ self.StyleTheme = sheet
+ self.Window.ResetTransientStyleData()
+ util.Log("[style_editor][info] Successfully exported: %s" % sheet)
+
+ if sheet_path.startswith(ed_glob.CONFIG['STYLES_DIR']) or \
+ sheet_path.startswith(ed_glob.CONFIG['SYS_STYLES_DIR']):
+ # Update editor windows/buffer to use new style sheet
+ UpdateBufferStyles(sheet)
+ rval = True
+ return rval
+
+ def SetDisplayForTransientSheet(self, sheet_name):
+ """Setup the display and editor data for a transient style sheet"""
+ self.Window.SetBlankStyle()
+ themes = self.SyntaxSheets
+ if sheet_name not in themes:
+ themes.append(sheet_name)
+ self.SyntaxSheets = themes
+ self.StyleTheme = sheet_name
+
+ def SheetExistOnDisk(self, sheet_name):
+ """Check if the given style sheet exists on disk
+ @param sheet_name: style sheet name
+ @return: bool
+
+ """
+ path = self.GetStyleSheetPath(sheet_name) # User path
+ syspath = self.GetStyleSheetPath(sheet_name, True) # System path
+ exists = os.path.exists(path) or os.path.exists(syspath)
+ return exists
+
+ def WriteStyleSheet(self, path):
+ """Write the current style data to the given path
+ @param path: string
+ @return: bool
+
+ """
+ bOk = True
+ try:
+ writer = util.GetFileWriter(path)
+ writer.write(self.Window.GenerateStyleSheet())
+ writer.close()
+ except (AttributeError, IOError), msg:
+ util.Log('[style_editor][err] Failed to export style sheet')
+ util.Log('[style_editor][err] %s' % msg)
+ bOk = False
+ return bOk
+
+ #---- Event Handlers ----#
+
+ def OnButton(self, evt):
+ """Handle the Add/Remove Buttons"""
+ e_obj = evt.GetEventObject()
+ if e_obj is self._addbtn:
+ # TODO: warn about unsaved changes
+ fname = wx.GetTextFromUser(_("Enter style sheet name"),
+ _("New Style Sheet"),
+ parent=self)
+ if fname:
+ # Case insensitive check
+ if fname.lower() in [name.lower() for name in self.SyntaxSheets]:
+ # Already exists
+ wx.MessageBox(_("The style %s already exists. Please choose a different name.") % fname,
+ style=wx.OK|wx.CENTER|wx.ICON_INFORMATION)
+ else:
+ # Create it
+ self.SetDisplayForTransientSheet(fname)
+ elif e_obj is self._delbtn:
+ path = self.GetStyleSheetPath(self.StyleTheme)
+ try:
+ os.remove(path)
+ except OSError, msg:
+ wx.MessageBox(_("Failed to delete style sheet:\nError:\n%s") % msg,
+ style=wx.OK|wx.CENTER|wx.ICON_ERROR)
+ else:
+ self.RefreshStyleSheets()
+ self.StyleTheme = u"Default" # select the default style
+ self.DoChangeStyleSheet(self.StyleTheme)
+ else:
+ evt.Skip()
+
+ def OnThemeChoice(self, evt):
+ """Check if current style sheet has been saved when switching sheets"""
+ oldTheme = self._prevTheme
+ newTheme = self.StyleTheme # newly selected theme
+ msg = None
+ modtype = self.CheckForModifications(self._prevTheme)
+ if modtype == MOD_CHANGE_PRESENT:
+ # prompt to save before changing
+ msg = _("Would you like to save the changes to '%s' before changing themes?\n\n"
+ "Selecting No will result in all changes being lost.")
+ msg = msg % oldTheme
+ elif modtype == MOD_DOESNT_EXIST:
+ # prompt to save unsaved sheet
+ msg = _("The new style theme '%s' has not been saved.\n\n"
+ "Would you like to save it before changing themes?")
+ msg = msg % oldTheme
+
+ if msg is not None:
+ dlg = wx.MessageDialog(self, msg, _("Save Styles"),
+ style=wx.YES_NO | wx.YES_DEFAULT | \
+ wx.ICON_INFORMATION)
+ dlg.CenterOnParent()
+ result = dlg.ShowModal()
+ dlg.Destroy()
+ if result == wx.YES:
+ # Save the style sheet
+ self.SaveStyleSheet(oldTheme)
+
+ # Change the style sheet to the newly selected one
+ self.DoChangeStyleSheet(newTheme)
+
+#-----------------------------------------------------------------------------#
+
+class StyleEditorPanel(wx.Panel):
+ """Main panel for the editor portion of the StyleEditor"""
+ def __init__(self, parent):
+ super(StyleEditorPanel, self).__init__(parent)
+
+ # Attributes
+ self._settings = SettingsPanel(self)
+ self.preview = PreviewPanel(self)
+ self.prebuff = self.preview.GetPreviewBuffer() # TEMP HACK
+ self.styles_orig = DuplicateStyleDict(self.prebuff.GetStyleSet())
+ self.styles_new = DuplicateStyleDict(self.styles_orig)
+ self.prebuff.SetStyles('preview', self.styles_new, True)
+ self.preview.OpenPreviewFile('cpp')
+
+ # Setup
+ self.StyleTags = self.styles_orig.keys()
+ self.__DoLayout()
+ self.EnableSettings(False)
+
+ # Event Handlers
+ self.Bind(wx.EVT_LISTBOX, self.OnListBox)
+ self.Bind(wx.EVT_CHOICE, self.OnChoice)
+ self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
+ self.Bind(eclib.EVT_COLORSETTER, self.OnColor)
+ self.prebuff.Bind(wx.EVT_LEFT_UP, self.OnTextRegion)
+ self.prebuff.Bind(wx.EVT_KEY_UP, self.OnTextRegion)
+
+ def __DoLayout(self):
+ """Layout the window"""
+ vsizer = wx.BoxSizer(wx.VERTICAL)
+ vsizer.Add(self._settings, 0, wx.EXPAND|wx.ALL, 5)
+ vsizer.Add(self.preview, 1, wx.EXPAND)
+ self.SetSizer(vsizer)
+
+ #---- Properties ----#
+
+ StyleTags = property(lambda self: self._settings.TagList.GetItems(),
+ lambda self, val: self._settings.TagList.SetItems(sorted(val)))
+ SettingsPanel = property(lambda self: self._settings)
+
+ #---- Public API ----#
+
+ def ChangeStyleSheet(self, sheet_name):
+ """Change the style sheet that is being edited
+ @param sheet_name: style sheet name (without extension)
+
+ """
+ self.prebuff.UpdateAllStyles(sheet_name)
+ self.ResetTransientStyleData()
+ tag = self._settings.TagList.GetStringSelection()
+ if tag != wx.EmptyString:
+ self.UpdateSettingsPane(self.styles_new[tag])
+
+ def DiffStyles(self):
+ """Checks if the current style set is different from the
+ original set. Used internally to check if a save prompt needs
+ to be brought up. Returns True if the style sets are different.
+ @return: whether style set has been modified or not
+ @return: bool
+
+ """
+ diff = False
+ for key in self.styles_orig:
+ if self.styles_orig[key] != self.styles_new[key]:
+ diff = True
+ break
+ return diff
+
+ def EnableSettings(self, enable=True):
+ """Enables/Disables all settings controls
+ @keyword enable: whether to enable/disable settings controls
+
+ """
+ for child in self.SettingsPanel.GetChildren():
+ if not isinstance(child, wx.ListBox):
+ child.Enable(enable)
+
+ def GenerateStyleSheet(self):
+ """Generates a style sheet from the dialogs style data
+ @return: The dictionary of L{StyleItem} in self.styles_new transformed
+ into a string that is in Editra Style Sheet format.
+
+ """
+ sty_sheet = list()
+ ditem = self.styles_new.get('default_style', StyleItem())
+ dvals = ';\n\t\t'.join([item.replace(',', ' ')
+ for item in ditem.GetAsList() ]) + ';'
+ sty_sheet.append(''.join(['default_style {\n\t\t', dvals, '\n\n}\n\n']))
+
+ tags = sorted(self.styles_new.keys())
+ for tag in tags:
+ item = self.styles_new[tag]
+ if item.IsNull() or tag == 'default_style':
+ continue
+
+ stage1 = wx.EmptyString
+ for attr in ('fore', 'back', 'face', 'size'):
+ ival = item.GetNamedAttr(attr)
+ if attr in ('fore', 'back'):
+ ival = ival.upper()
+
+ if ival is None or ival == ditem.GetNamedAttr(attr):
+ continue
+
+ stage1 = ''.join((stage1, attr, u':',
+ ival.replace(',', ' '), u';'))
+
+ # Add any modifiers to the modifier tag
+ modifiers = item.GetModifiers()
+ if len(modifiers):
+ stage1 += (u"modifiers:" + modifiers + u";").replace(',', ' ')
+
+ # If the StyleItem had any set attributes add it to the stylesheet
+ if len(stage1):
+ sty_sheet.append(tag + u" {\n")
+ stage2 = u"\t\t" + stage1[0:-1].replace(u";", u";\n\t\t") + u";"
+ sty_sheet.append(stage2)
+ sty_sheet.append(u"\n}\n\n")
+
+ return u"".join(sty_sheet)
+
+ def ResetTransientStyleData(self):
+ """Reset the transient style data to mark the changes as not dirty"""
+ self.styles_new = DuplicateStyleDict(self.prebuff.GetStyleSet())
+ self.styles_orig = DuplicateStyleDict(self.styles_new)
+
+ def SetBlankStyle(self):
+ """Clear all the transient style data to a blank style set"""
+ self.styles_orig = self.prebuff.BlankStyleDictionary()
+ self.styles_new = DuplicateStyleDict(self.styles_orig)
+ self.prebuff.SetStyles('preview', self.styles_new, nomerge=True)
+ self.prebuff.UpdateAllStyles('preview')
+
+ # For some reason this causes the text display to refresh
+ # properly when nothing else would work.
+ self.OnTextRegion()
+
+ def UpdateSettingsPane(self, syntax_data):
+ """Updates all the settings controls to hold the
+ values of the selected tag.
+ @param syntax_data: syntax data set to configure panel from
+
+ """
+ val_str = unicode(syntax_data)
+ val_map = { ID_FORE_COLOR : syntax_data.GetFore(),
+ ID_BACK_COLOR : syntax_data.GetBack(),
+ ID_BOLD : "bold" in val_str,
+ ID_ITALIC : "italic" in val_str,
+ ID_EOL : "eol" in val_str,
+ ID_ULINE : "underline" in val_str,
+ ID_FONT : syntax_data.GetFace(),
+ ID_FONT_SIZE : syntax_data.GetSize()
+ }
+
+ # Fall back to defaults for color values
+ # that we may not be able to understand
+ if u"#" not in val_map[ID_FORE_COLOR]:
+ val_map[ID_FORE_COLOR] = self.prebuff.GetDefaultForeColour(as_hex=True)
+ if u"#" not in val_map[ID_BACK_COLOR]:
+ val_map[ID_BACK_COLOR] = self.prebuff.GetDefaultBackColour(as_hex=True)
+
+ for sid in SETTINGS_IDS:
+ ctrl = self.FindWindowById(sid)
+ if isinstance(ctrl, wx.CheckBox):
+ ctrl.SetValue(val_map[sid])
+ elif isinstance(ctrl, wx.Choice):
+ ctrl.SetStringSelection(val_map[sid])
+ elif isinstance(ctrl, eclib.ColorSetter):
+ ctrl.SetLabel(val_map[sid][:7])
+ return True
+
+ def UpdateStyleSet(self, id_):
+ """Updates the value of the style tag to reflect any changes
+ made in the settings controls.
+ @param id_: identifier of the style tag in the list
+
+ """
+ # Get the tag that has been modified
+ tag = self._settings.TagList.GetStringSelection()
+ if not tag:
+ return False
+
+ # Get the modified value
+ ctrl = self.FindWindowById(id_)
+ if isinstance(ctrl, wx.CheckBox):
+ val = ctrl.GetValue()
+ elif isinstance(ctrl, wx.Choice):
+ val = ctrl.GetStringSelection()
+ elif isinstance(ctrl, eclib.ColorSetter):
+ val = ctrl.GetLabel()
+ else:
+ return False
+
+ # Update the value of the modified tag
+ val_map = { ID_FONT : u"face",
+ ID_FONT_SIZE : u"size",
+ ID_BOLD : u"bold",
+ ID_EOL : u"eol",
+ ID_ITALIC : u"italic",
+ ID_ULINE : u"underline",
+ ID_FORE_COLOR : u"fore",
+ ID_BACK_COLOR : u"back"
+ }
+
+ if id_ in [ ID_FONT, ID_FONT_SIZE, ID_FORE_COLOR, ID_BACK_COLOR ]:
+ self.styles_new[tag].SetNamedAttr(val_map[id_], val)
+ elif id_ in [ ID_BOLD, ID_ITALIC, ID_ULINE, ID_EOL ]:
+ self.styles_new[tag].SetExAttr(val_map[id_], val)
+ else:
+ return False
+
+ # Update the Preview Area
+ self.prebuff.SetStyleTag(tag, self.styles_new[tag])
+ self.prebuff.RefreshStyles()
+
+ #---- Event Handlers ----#
+
+ def OnCheck(self, evt):
+ """Update Model for changes to styling settings"""
+ e_id = evt.GetId()
+ if e_id in [ID_BOLD, ID_EOL, ID_ULINE, ID_ITALIC]:
+ self.UpdateStyleSet(e_id)
+ else:
+ evt.Skip()
+
+ def OnChoice(self, evt):
+ """Update Model for changes to styling settings"""
+ e_id = evt.GetId()
+ if e_id in [ID_FONT, ID_FONT_SIZE]:
+ self.UpdateStyleSet(e_id)
+ else:
+ evt.Skip()
+
+ def OnColor(self, evt):
+ """Handles color selection events
+ @param evt: event that called this handler
+
+ """
+ # Update The Style data for current tag
+ self.UpdateStyleSet(evt.GetId())
+
+ def OnListBox(self, evt):
+ """Catches the selection of a style tag in the listbox
+ and updates the style window appropriately.
+ @param evt: event that called this handler
+
+ """
+ tag = evt.GetEventObject().GetStringSelection()
+ if tag != u"" and tag in self.styles_new:
+ self.UpdateSettingsPane(self.styles_new[tag])
+ self.EnableSettings()
+ else:
+ self.EnableSettings(False)
+
+ def OnTextRegion(self, evt=None):
+ """Processes clicks in the preview control and sets the style
+ selection in the style tags list to the style tag of the area
+ the cursor has moved into.
+ @param evt: event that called this handler
+
+ """
+ if evt is not None:
+ evt.Skip()
+
+ style_id = self.prebuff.GetStyleAt(self.prebuff.GetCurrentPos())
+ data = self.prebuff.FindTagById(style_id)
+ if data != wx.EmptyString and data in self.styles_new:
+ self._settings.TagList.SetStringSelection(data)
+ if wx.Platform == '__WXGTK__':
+ self._settings.TagList.SetFirstItemStr(data)
+ self.UpdateSettingsPane(self.styles_new[data])
+ self.EnableSettings()
+
+#-----------------------------------------------------------------------------#
+
+class SettingsPanel(wx.Panel):
+ """Panel holding all settings controls for changing the font,
+ colors, styles, ect.. in the style set.
+
+ """
+ def __init__(self, parent):
+ """Create the settings panel"""
+ super(SettingsPanel, self).__init__(parent)
+
+ # Attributes
+ self._tag_list = wx.ListBox(self,
+ size=(-1, 150),
+ style=wx.LB_SINGLE)
+
+ # Layout
+ self.__DoLayout()
+
+ TagList = property(lambda self: self._tag_list)
+
+ def __DoLayout(self):
+ """Layout the controls in the panel"""
+ hsizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ # Setup Left hand side with Style Tag List
+ ss_v = wx.BoxSizer(wx.VERTICAL)
+ style_lbl = wx.StaticText(self, label=_("Style Tags") + u": ")
+ ss_v.AddMany([(style_lbl, 0, wx.ALIGN_LEFT),
+ (self._tag_list, 1, wx.EXPAND)])
+ hsizer.Add(ss_v, 0, wx.EXPAND|wx.ALL, 5)
+
+ # Add divider line
+ hsizer.Add(wx.StaticLine(self, size=(-1, 2), style=wx.LI_VERTICAL),
+ 0, wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
+
+ # Setup the Right side
+ setting_sizer = wx.BoxSizer(wx.VERTICAL)
+ setting_top = wx.BoxSizer(wx.HORIZONTAL)
+
+ # Settings top
+ sbox = wx.StaticBox(self, label=_("Color"))
+ cbox_sizer = wx.StaticBoxSizer(sbox, wx.VERTICAL)
+
+ # Foreground
+ fground_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ fground_lbl = wx.StaticText(self, label=_("Foreground") + u": ")
+ fground_sel = eclib.ColorSetter(self, ID_FORE_COLOR, wx.BLACK)
+ fground_sizer.AddMany([((5, 5)),
+ (fground_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((2, 2), 0),
+ (fground_sel, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5))])
+ cbox_sizer.AddMany([(fground_sizer, 0, wx.ALIGN_LEFT | wx.EXPAND),
+ ((10, 10))])
+
+ # Background
+ bground_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ bground_lbl = wx.StaticText(self, label=_("Background") + u": ")
+ bground_sel = eclib.ColorSetter(self, ID_BACK_COLOR, wx.WHITE)
+ bground_sizer.AddMany([((5, 5)),
+ (bground_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((2, 2), 0),
+ (bground_sel, 0, wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5))])
+ cbox_sizer.Add(bground_sizer, 0, wx.EXPAND)
+ setting_top.AddMany([(cbox_sizer, 0, wx.ALIGN_TOP), ((10, 10), 0)])
+
+ # Attrib Box
+ attrib_box = wx.StaticBox(self, label=_("Attributes"))
+ abox_sizer = wx.StaticBoxSizer(attrib_box, wx.VERTICAL)
+
+ # Attributes
+ bold_cb = wx.CheckBox(self, ID_BOLD, _("bold"))
+ eol_cb = wx.CheckBox(self, ID_EOL, _("eol"))
+ ital_cb = wx.CheckBox(self, ID_ITALIC, _("italic"))
+ uline_cb = wx.CheckBox(self, ID_ULINE, _("underline"))
+ abox_sizer.AddMany([(bold_cb, 0),
+ (eol_cb, 0),
+ (ital_cb, 0),
+ (uline_cb, 0)])
+ setting_top.Add(abox_sizer, 0, wx.ALIGN_TOP)
+
+ # Font
+ fh_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ font_box = wx.StaticBox(self, label=_("Font Settings"))
+ fbox_sizer = wx.StaticBoxSizer(font_box, wx.VERTICAL)
+
+ # Font Face Name
+ fsizer = wx.BoxSizer(wx.HORIZONTAL)
+ flbl = wx.StaticText(self, label=_("Font") + u": ")
+ fontenum = wx.FontEnumerator()
+ if wx.Platform == '__WXMAC__':
+ # FixedWidthOnly Asserts on wxMac
+ fontenum.EnumerateFacenames(fixedWidthOnly=False)
+ else:
+ fontenum.EnumerateFacenames(fixedWidthOnly=True)
+ font_lst = [u"%(primary)s", u"%(secondary)s"]
+ font_lst.extend(sorted(fontenum.GetFacenames()))
+ fchoice = wx.Choice(self, ID_FONT, choices=font_lst)
+ fsizer.AddMany([((5, 5), 0), (flbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ (fchoice, 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5),0)])
+ fbox_sizer.Add(fsizer, 0)
+
+ # Font Size
+ fsize_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ fsize_lbl = wx.StaticText(self, label=_("Size") + u": ")
+ fsizes = [u"%(size)d", u"%(size2)d"]
+ fsizes.extend([ unicode(x) for x in range(4, 21) ])
+ fs_choice = wx.Choice(self, ID_FONT_SIZE, choices=fsizes)
+ fsize_sizer.AddMany([((5, 5), 0),
+ (fsize_lbl, 0, wx.ALIGN_CENTER_VERTICAL),
+ (fs_choice, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL),
+ ((5, 5), 0)])
+ fbox_sizer.AddMany([((5, 5), 0), (fsize_sizer, 0, wx.EXPAND)])
+ fh_sizer.AddMany([(fbox_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL), ((10, 10), 0)])
+
+ # Build Section
+ setting_sizer.AddMany([(setting_top, 0, wx.ALIGN_CENTER_HORIZONTAL),
+ ((10, 10), 0),
+ (fh_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL)])
+
+ # Setup Right hand side with the settings controls
+ hsizer.AddStretchSpacer()
+ hsizer.Add(setting_sizer, 0, wx.EXPAND|wx.ALL, 5)
+ hsizer.AddStretchSpacer()
+
+ self.SetSizer(hsizer)
+
+#-----------------------------------------------------------------------------#
+
+class PreviewPanel(ed_basewin.EdBaseCtrlBox):
+ """Panel to hold the preview window and selector"""
+ def __init__(self, parent):
+ super(PreviewPanel, self).__init__(parent)
+
+ # Attributes
+ self.LOG = wx.GetApp().GetLog()
+ self.preview = ed_basestc.EditraBaseStc(self, size=(-1, 200),
+ style=wx.SUNKEN_BORDER)
+
+ # Setup
+ self.preview.SetEdgeColumn(80)
+ self.preview.SetEdgeMode(wx.stc.STC_EDGE_LINE)
+ self.preview.SetCaretLineVisible(True)
+ self.__DoLayout()
+
+ # Event Handlers
+ self.Bind(wx.EVT_CHOICE, self.OnChoice)
+
+ def __DoLayout(self):
+ """Layout the Panel"""
+ # Create the ControlBar
+ cbar = self.CreateControlBar(wx.TOP)
+
+ # Setup the ControlBar's controls
+ lexer_lbl = wx.StaticText(cbar, label=_("Preview File") + u": ")
+ lexer_lst = wx.Choice(cbar, ed_glob.ID_LEXER,
+ choices=syntax.GetLexerList())
+ lexer_lst.SetToolTip(wx.ToolTip(_("Set the preview file type")))
+ lexer_lst.SetStringSelection(u"CPP")
+ cbar.AddControl(lexer_lbl)
+ cbar.AddControl(lexer_lst)
+
+ self.SetWindow(self.preview)
+
+ def GetPreviewBuffer(self):
+ """Get the STC instance"""
+ return self.preview
+
+ def OnChoice(self, evt):
+ """Update the preview file"""
+ if evt.GetId() == ed_glob.ID_LEXER:
+ e_obj = evt.GetEventObject()
+ val = e_obj.GetStringSelection()
+ self.OpenPreviewFile(val)
+ else:
+ evt.Skip()
+
+ def OpenPreviewFile(self, file_lbl):
+ """Opens a file using the names in the Syntax Files choice
+ control as a search query.
+ @param file_lbl: name of file to open in test data directory
+
+ """
+ fname = file_lbl.replace(u" ", u"_").replace(u"/", u"_").lower()
+ fname = fname.replace('#', 'sharp')
+ try:
+ fname = glob.glob(ed_glob.CONFIG['TEST_DIR'] + fname + ".*")[0]
+ except IndexError:
+ self.LOG('[style_editor][err] File %s Does not exist' % fname)
+ return False
+
+ self.preview.SetFileName(fname)
+ self.preview.ClearAll()
+ self.preview.LoadFile(fname)
+ self.preview.FindLexer()
+ self.preview.EmptyUndoBuffer()
+ return True
+
+#-----------------------------------------------------------------------------#
+# Utility functions
+def DuplicateStyleDict(style_dict):
+ """Duplicates the style dictionary to make a true copy of
+ it, as simply assigning the dictionary to two different variables
+ only copies a reference leaving both variables pointing to the
+ same object.
+ @param style_dict: dictionary of tags->StyleItems
+ @return: a copy of the given styleitem dictionary
+
+ """
+ new_dict = dict()
+ for tag in style_dict:
+ new_dict[tag] = style_dict[tag].Clone()
+ return new_dict
+
+def UpdateBufferStyles(sheet):
+ """Update the style used in all buffers
+ @param sheet: Style sheet to use
+
+ """
+ # Only update if the sheet has changed
+ if sheet is not None:
+ Profile_Set('SYNTHEME', sheet)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/README b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/README
new file mode 100644
index 0000000..828a924
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/README
@@ -0,0 +1,99 @@
+Syntax Plugin Specifications:
+
+Included in this document are the specifications of what is needed to write a
+a new module to extend the syntax highlighting support in Editra.
+
+0: Before you begin
+ - Editra uses Scintilla for its text control. Since documentation is not
+ readily available, its suggested that you grab the Scintilla sources and
+ see what settings are available for each language.
+
+1: File Specifications
+ - The plugin file is a python module that provides the editor with the
+ information that it needs to properly setup the lexer.
+
+2: What the plugin needs to provide
+
+ CLASS: SyntaxData a subclass instance of syndata.SyntaxDataBase
+
+ METHODS:
+ - FUNCTION: GetKeywords(self)
+ DESC: Provides a set of language keywords and their level to set in
+ the editor.
+ PARAM: None
+ RETURN: A list of tuples.
+ SPECIFICATIONS:
+ The tuples in the list each contain two items.
+ -The first item is an integer value specifying the Scintilla
+ keyword type to set for the Lexer.
+ -The second is a string of space separated keywords.
+ EXAMPLE RETURN: [(0, "spam ni"), (1, "monty python")]
+
+ - FUNCTION: GetSyntaxSpec(self)
+ DESC: This function is called to get the mapping of the stc style attributes
+ to the Editra Style Sheet tags.
+ PARAM: None
+ RETURN: List of tuple string pairs, that pair the STC value to the wanted
+ style tag.
+ SPECIFICATIONS:
+ The values in tuples of the return list must be ordered as follows
+ - (STC_* value, Editra Style Tag)
+ EXAMPLE RETURN: [('STC_C_DEFAULT', 'default_style'),
+ ('STC_C_COMMENT', 'comment_style')]
+
+ - FUNCTION: GetProperties(self)
+ DESC: This function is called to get any extra lexer properties that the
+ editor should set for the given language.
+ PARAM: None
+ RETURN: List of tuples
+ SPECIFICATIONS:
+ The values in the tuples of the return list must be as follows
+ - ("property", "value")
+ If there are no needed properties to set the function should
+ return an empty list.
+ EXAMPLE RETURN: [("fold", "1"), ("fold.comment", "1")]
+
+ - FUNCTION: GetCommentPattern(self)
+ DESC: Get the patern of comment meta characters to use for commenting
+ out code in the given language.
+ PARAM: None
+ RETURN: Ordered List of strings
+ SPECIFICATIONS:
+ The returned list of strings must be in the order that the characters
+ are to be added to the document. This only applies to languages that
+ have multi character sequences required for comments.
+ EXAMPLE RETURN:
+ - Bash: [ "#" ]
+ - C: ["/*", "*/]
+
+
+OPTIONAL EXTENSIONS:
+
+Optional Features that language extensions can provide. These methods can be
+added to a syntax module by using the syndata.SyntaxDataBase.RegisterFeature
+method.
+
+Currently Supported Features:
+
+ - FUNCTION: StyleText(stc, start, end)
+ DESC: Used for styling the text in a buffer that is using a container
+ lexer.
+ PARAM: stc The EditraStyledText control instance to do the styling in
+ PARAM: start The start position of the styling
+ PARAM: end The end position to style to
+ SPECIFICATIONS: Register with the synglob.FEATURE_STYLETEXT id
+ EXAMPLE:
+
+ - FUNCTION: AutoIndenter(stc, current_pos, indent_char)
+ DESC: Provide context sensitive auto indentation support
+ PARAM: stc The buffer to do the indentation in
+ PARAM: current_pos The current position of the caret in the buffer
+ PARAM: indent_char Prefered character to use for indentation
+ ("\t" or " " * tabwidth)
+ SPECIFICATIONS: Called when the Return key is hit. Note that the new
+ line character is not sent to the buffer so it needs
+ to be handled by this method. This method must also
+ call AddText to add the new whitespace to the buffer.
+
+ Register with the synglob.FEATURE_AUTOINDENT id
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/__init__.py
new file mode 100644
index 0000000..a8909fc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/__init__.py
@@ -0,0 +1,26 @@
+###############################################################################
+# Name: __init__.py #
+# Purpose: initialize the syntax package #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+"""Syntax data package
+
+Provides:
+ - Keyword Data
+ - Syntax styling definitions
+
+For all differn't file types and languages supported by Editra
+
+"""
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: __init__.py 63070 2010-01-05 01:56:27Z CJP $"
+__revision__ = "$Revision: 63070 $"
+
+#-----------------------------------------------------------------------------#
+# Setup Namespace
+
+from synxml import *
+
+#-----------------------------------------------------------------------------# \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_actionscript.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_actionscript.py
new file mode 100644
index 0000000..844f391
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_actionscript.py
@@ -0,0 +1,86 @@
+###############################################################################
+# Name: actionscript.py #
+# Purpose: Define ActionScript syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: actionscript.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration file for ActionScript
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _actionscript.py 70228 2011-12-31 20:39:16Z CJP $"
+__revision__ = "$Revision: 70228 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _cpp
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# ActionScript Keywords 0
+AS_KEYWORDS = ("break case catch continue default do each else finally for if "
+ "in label new return super switch throw while with "
+ # Attribute Keywords
+ "dynamic final internal native override private protected "
+ "public static "
+ # Definition Keywords
+ "class const extends function get implements interface "
+ "namespace package set var "
+ # Directives
+ "import include use "
+ # Primary Expression Keywords
+ "false null this true "
+ # Special Types
+ "void Null *")
+
+# ActionScript Keywords 1
+# Namespaces and Packages
+AS_TYPES = ("AS3 flash_proxy object_proxy flash accessibility display errors "
+ "events external filters geom media net printing profiler system "
+ "text ui utils xml ")
+
+#---- Syntax Style Specs ----#
+# Same as cpp
+
+#---- Extra Properties ----#
+# Same as cpp
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """ActionScript SyntaxData"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _cpp.AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [(0, AS_KEYWORDS), (1, AS_TYPES)]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return _cpp.SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [_cpp.FOLD, _cpp.FOLD_PRE]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'//']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ada.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ada.py
new file mode 100644
index 0000000..099a631
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ada.py
@@ -0,0 +1,78 @@
+###############################################################################
+# Name: ada.py #
+# Purpose: Define Ada syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+ FILE: ada.py
+ AUTHOR: Cody Precord
+ @summary: Lexer configuration module for ada
+ @todo: styles, keywords, testing
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _ada.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+ADA_KEYWORDS = (0, "abort abstract accept access aliased all array at begin "
+ "body case constant declare delay delta digits do else "
+ "elsif end entry exception exit for function generic goto "
+ "if in is limited loop new null of others out package "
+ "pragma private procedure protected raise range record "
+ "renames requeue return reverse select separate subtype "
+ "tagged task terminate then type until use when while with")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_ADA_CHARACTER, 'char_style'),
+ (stc.STC_ADA_CHARACTEREOL, 'stringeol_style'),
+ (stc.STC_ADA_COMMENTLINE, 'comment_style'),
+ (stc.STC_ADA_DEFAULT, 'default_style'),
+ (stc.STC_ADA_DELIMITER, 'operator_style'),
+ (stc.STC_ADA_IDENTIFIER, 'default_style'),
+ (stc.STC_ADA_ILLEGAL, 'error_style'),
+ (stc.STC_ADA_LABEL, 'keyword2_style'), # Style This
+ (stc.STC_ADA_NUMBER, 'number_style'),
+ (stc.STC_ADA_STRING, 'string_style'),
+ (stc.STC_ADA_STRINGEOL, 'stringeol_style'),
+ (stc.STC_ADA_WORD, 'keyword_style')]
+
+#---- Extra Properties ----#
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Ada"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_ADA)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List"""
+ return [ADA_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications"""
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code"""
+ return [ u'--' ]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_apache.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_apache.py
new file mode 100644
index 0000000..4ba7876
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_apache.py
@@ -0,0 +1,176 @@
+###############################################################################
+# Name: apache.py #
+# Purpose: Define Apache syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: apache.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Apache Configuration Files
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _apache.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+DIRECTIVES = (0, 'acceptmutex acceptpathinfo accessconfig accessfilename '
+ 'action addalt addaltbyencoding addaltbytype addcharset '
+ 'adddefaultcharset adddescription addencoding addhandler '
+ 'addicon addiconbyencoding addiconbytype addinputfilter '
+ 'addlanguage addmodule addmoduleinfo addoutputfilter '
+ 'addoutputfilterbytype addtype agentlog alias aliasmatch all '
+ 'allow allowconnect allowencodedslashes allowoverride '
+ 'anonymous anonymous_authoritative anonymous_logemail '
+ 'anonymous_mustgiveemail anonymous_nouserid '
+ 'anonymous_verifyemail assignuserid authauthoritative '
+ 'authdbauthoritative authdbgroupfile authdbmauthoritative '
+ 'authdbmgroupfile authdbmtype authdbmuserfile authdbuserfile '
+ 'authdigestalgorithm authdigestdomain authdigestfile '
+ 'authdigestgroupfile authdigestnccheck authdigestnonceformat '
+ 'authdigestnoncelifetime authdigestqop authdigestshmemsize '
+ 'authgroupfile authldapauthoritative authldapbinddn '
+ 'authldapbindpassword authldapcharsetconfig '
+ 'authldapcomparednonserver authldapdereferencealiases '
+ 'authldapenabled authldapfrontpagehack authldapgroupattribute '
+ 'authldapgroupattributeisdn authldapremoteuserisdn '
+ 'authldapurl authname authtype authuserfile bindaddress '
+ 'browsermatch browsermatchnocase bs2000account bufferedlogs '
+ 'cachedefaultexpire cachedirlength cachedirlevels '
+ 'cachedisable cacheenable cacheexpirycheck cachefile '
+ 'cacheforcecompletion cachegcclean cachegcdaily '
+ 'cachegcinterval cachegcmemusage cachegcunused '
+ 'cacheignorecachecontrol cacheignoreheaders '
+ 'cacheignorenolastmod cachelastmodifiedfactor cachemaxexpire '
+ 'cachemaxfilesize cacheminfilesize cachenegotiateddocs '
+ 'cacheroot cachesize cachetimemargin cgimapextension '
+ 'charsetdefault charsetoptions charsetsourceenc checkspelling '
+ 'childperuserid clearmodulelist contentdigest cookiedomain '
+ 'cookieexpires cookielog cookiename cookiestyle '
+ 'cookietracking coredumpdirectory customlog dav '
+ 'davdepthinfinity davlockdb davmintimeout defaulticon '
+ 'defaultlanguage defaulttype define deflatebuffersize '
+ 'deflatecompressionlevel deflatefilternote deflatememlevel '
+ 'deflatewindowsize deny directory directoryindex '
+ 'directorymatch directoryslash documentroot dumpioinput '
+ 'dumpiooutput enableexceptionhook enablemmap enablesendfile '
+ 'errordocument errorlog example expiresactive expiresbytype '
+ 'expiresdefault extendedstatus extfilterdefine '
+ 'extfilteroptions fancyindexing fileetag files filesmatch '
+ 'forcelanguagepriority forcetype forensiclog from group '
+ 'header headername hostnamelookups identitycheck ifdefine '
+ 'ifmodule imapbase imapdefault imapmenu include indexignore '
+ 'indexoptions indexorderdefault isapiappendlogtoerrors '
+ 'isapiappendlogtoquery isapicachefile isapifakeasync '
+ 'isapilognotsupported isapireadaheadbuffer keepalive '
+ 'keepalivetimeout languagepriority ldapcacheentries '
+ 'ldapcachettl ldapconnectiontimeout ldapopcacheentries '
+ 'ldapopcachettl ldapsharedcachefile ldapsharedcachesize '
+ 'ldaptrustedca ldaptrustedcatype limit limitexcept '
+ 'limitinternalrecursion limitrequestbody limitrequestfields '
+ 'limitrequestfieldsize limitrequestline limitxmlrequestbody '
+ 'listen listenbacklog loadfile loadmodule location '
+ 'locationmatch lockfile logformat loglevel maxclients '
+ 'maxkeepaliverequests maxmemfree maxrequestsperchild '
+ 'maxrequestsperthread maxspareservers maxsparethreads '
+ 'maxthreads maxthreadsperchild mcachemaxobjectcount '
+ 'mcachemaxobjectsize mcachemaxstreamingbuffer '
+ 'mcacheminobjectsize mcacheremovalalgorithm mcachesize '
+ 'metadir metafiles metasuffix mimemagicfile minspareservers '
+ 'minsparethreads mmapfile modmimeusepathinfo multiviewsmatch '
+ 'namevirtualhost nocache noproxy numservers nwssltrustedcerts '
+ 'nwsslupgradeable options order passenv pidfile port '
+ 'protocolecho proxy proxybadheader proxyblock proxydomain '
+ 'proxyerroroverride proxyiobuffersize proxymatch '
+ 'proxymaxforwards proxypass proxypassreverse '
+ 'proxypreservehost proxyreceivebuffersize proxyremote '
+ 'proxyremotematch proxyrequests proxytimeout proxyvia qsc '
+ 'readmename redirect redirectmatch redirectpermanent '
+ 'redirecttemp refererignore refererlog removecharset '
+ 'removeencoding removehandler removeinputfilter '
+ 'removelanguage removeoutputfilter removetype requestheader '
+ 'require resourceconfig rewritebase rewritecond rewriteengine '
+ 'rewritelock rewritelog rewriteloglevel rewritemap '
+ 'rewriteoptions rewriterule rlimitcpu rlimitmem rlimitnproc '
+ 'satisfy scoreboardfile script scriptalias scriptaliasmatch '
+ 'scriptinterpretersource scriptlog scriptlogbuffer '
+ 'scriptloglength scriptsock securelisten sendbuffersize '
+ 'serveradmin serveralias serverlimit servername serverpath '
+ 'serverroot serversignature servertokens servertype setenv '
+ 'setenvif setenvifnocase sethandler setinputfilter '
+ 'setoutputfilter singlelisten ssiendtag ssierrormsg '
+ 'ssistarttag ssitimeformat ssiundefinedecho '
+ 'sslcacertificatefile sslcacertificatepath '
+ 'sslcarevocationfile sslcarevocationpath '
+ 'sslcertificatechainfile sslcertificatefile '
+ 'sslcertificatekeyfile sslciphersuite sslengine sslmutex '
+ 'ssloptions sslpassphrasedialog sslprotocol '
+ 'sslproxycacertificatefile sslproxycacertificatepath '
+ 'sslproxycarevocationfile sslproxycarevocationpath '
+ 'sslproxyciphersuite sslproxyengine '
+ 'sslproxymachinecertificatefile '
+ 'sslproxymachinecertificatepath sslproxyprotocol '
+ 'sslproxyverify sslproxyverifydepth sslrandomseed sslrequire '
+ 'sslrequiressl sslsessioncache sslsessioncachetimeout '
+ 'sslusername sslverifyclient sslverifydepth startservers '
+ 'startthreads suexecusergroup threadlimit threadsperchild '
+ 'threadstacksize timeout transferlog typesconfig unsetenv '
+ 'usecanonicalname user userdir virtualdocumentroot '
+ 'virtualdocumentrootip virtualhost virtualscriptalias '
+ 'virtualscriptaliasip win32disableacceptex xbithack')
+
+PARAMS = (1, 'on off standalone inetd force-response-1.0 downgrade-1.0 '
+ 'nokeepalive indexes includes followsymlinks none x-compress '
+ 'x-gzip warn')
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_CONF_COMMENT, 'comment_style'),
+ (stc.STC_CONF_DEFAULT, 'default_style'),
+ (stc.STC_CONF_DIRECTIVE, 'keyword_style'),
+ (stc.STC_CONF_EXTENSION, 'pre_style'),
+ (stc.STC_CONF_IDENTIFIER, 'number_style'),
+ (stc.STC_CONF_IP, 'number2_style'),
+ (stc.STC_CONF_NUMBER, 'number_style'),
+ (stc.STC_CONF_OPERATOR, 'operator_style'),
+ (stc.STC_CONF_PARAMETER, 'global_style'),
+ (stc.STC_CONF_STRING, 'string_style')]
+
+#---- Extra Properties ----#
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Apache Conf files"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CONF)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [DIRECTIVES, PARAMS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm.py
new file mode 100644
index 0000000..04a5334
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm.py
@@ -0,0 +1,81 @@
+###############################################################################
+# Name: asm.py #
+# Purpose: Define ASM syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: asm.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration file GNU Assembly Code
+@todo: Complete Keywords/Registers
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _asm.py 70228 2011-12-31 20:39:16Z CJP $"
+__revision__ = "$Revision: 70228 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+#-----------------------------------------------------------------------------#
+
+# GNU Assembly CPU Instructions/Storage Types
+ASM_CPU_INST = (0, ".long .ascii .asciz .byte .double .float .hword .int .octa "
+ ".quad .short .single .space .string .word")
+
+# GNU FPU Instructions
+ASM_MATH_INST = (1, "")
+
+# GNU Registers
+ASM_REGISTER = (2, "")
+
+# GNU Assembly Directives/Special statements/Macros
+ASM_DIRECTIVES = (3, ".include .macro .endm")
+
+#---- Language Styling Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_ASM_DEFAULT, 'default_style'),
+ (stc.STC_ASM_CHARACTER, 'char_style'),
+ (stc.STC_ASM_COMMENT, 'comment_style'),
+ (stc.STC_ASM_COMMENTBLOCK, 'comment_style'),
+ (stc.STC_ASM_CPUINSTRUCTION, 'keyword_style'),
+ (stc.STC_ASM_DIRECTIVE, 'keyword3_style'),
+ (stc.STC_ASM_DIRECTIVEOPERAND, 'default_style'),
+ (stc.STC_ASM_EXTINSTRUCTION, 'default_style'),
+ (stc.STC_ASM_IDENTIFIER, 'default_style'),
+ (stc.STC_ASM_MATHINSTRUCTION, 'keyword_style'),
+ (stc.STC_ASM_NUMBER, 'number_style'),
+ (stc.STC_ASM_OPERATOR, 'operator_style'),
+ (stc.STC_ASM_REGISTER, 'keyword2_style'),
+ (stc.STC_ASM_STRING, 'string_style'),
+ (stc.STC_ASM_STRINGEOL, 'stringeol_style') ]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Assembly files"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ # synglob.ID_LANG_ASM
+ self.SetLexer(stc.STC_LEX_ASM)
+
+ def GetKeywords(self):
+ """Returns List of Keyword Specifications """
+ return [ASM_CPU_INST, ASM_DIRECTIVES]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u';']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm68k.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm68k.py
new file mode 100644
index 0000000..f05a29f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm68k.py
@@ -0,0 +1,134 @@
+###############################################################################
+# Name: asm68k.py #
+# Purpose: Define 68k/56k assembly syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: asm68k.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration file 68k/56k Assembly Code
+@todo: more color configuration
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _asm68k.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- 68K Keyword Definitions ----#
+
+ASM_CPU_INST = (0, "andi and as b beq bg b bl bne bge bpl bchg bclr bfchg "
+ "bfclr bfexts bfextu bfffo bfins bfset bftst bkpt bra bset "
+ "bsr btst callm cas2 cas chk2 chk clr cmpa cmpi cmpm cmp "
+ "dbcc dbcs dbvc dbvs dbeq dbf dbt dbge dbgt dbhi dbmi dble "
+ "dbls dblt dbne dbpl dbra eori eor exg extb ext illegaljmp "
+ "jsr lea link ls mm movea movec movem movep moveq moves "
+ "move nbcd negx neg nop not ori or pack pea reset ro rox rt "
+ "sbcd seq sne spl swap tas trap tst unlk unpk abcd")
+
+ASM_MATH_INST = (1, "adda addi addq addx add div mul suba subi subq subx sub "
+ "tdiv")
+
+ASM_REGISTER = (2, "a0 a1 a2 a3 a4 a5 a6 a7 d0 d1 d2 d3 d4 d5 d6 d7 pc sr "
+ "ccr sp usp ssp vbr sfc sfcr dfc dfcr msp isp zpc cacr "
+ "caar za0 za1 za2 za3 za4 za5 za6 za7 zd0 zd1 zd2 zd3 "
+ "zd4 zd5 zd6 zd7 crp srp tc ac0 ac1 acusr tt0 tt1 mmusr "
+ "dtt0 dtt1 itt0 itt1 urp cal val scc crp srp drp tc ac psr "
+ "pcsr bac0 bac1 bac2 bac3 bac4 bac5 bac6 bac7 bad0 bad1 "
+ "bad2 bad3 bad4 bad5 bad6 bad7 fp0 fp1 fp2 fp3 fp4 fp5 fp6 "
+ "fp7 control status iaddr fpcr fpsr fpiar ")
+
+ASM_DIRECTIVES = (3, "ALIGN CHIP COMLINE COMMON DC DCB DS END EQU FEQU FAIL "
+ "FOPT IDNT LLEN MASK2 NAME NOOBJ OFFSET OPT ORG PLEN REG "
+ "RESTORE SAVE SECT SECTION SET SPC TTL XCOM XDEF XREF")
+
+#---- 56K Keywords ----#
+
+ASM56K_CPU_INST = (0, "adc addl addr and andi asl asr bchg bclr bra "
+ "brclr brset bsclr bset bsr bsset btst bcc bcs bec beq "
+ "bes bge bgt blc ble bls blt bmi bne bnr bpl bnn brkcc "
+ "brkcs brkec brkeq brkes brkge brkgt brklc brkle brkls "
+ "brklt brkmi brkne brknr brkpl brknn bscc bscs bsec bseq "
+ "bses bsge bsgt bslc bsle bsls bslt bsmi bsne bsnr bspl "
+ "bsnn clb clr cmp cmpm cmpu debug dmac do "
+ "forever dor enddo eor extract extractu illegal inc "
+ "insert jclr jmp jsclr jset jsr jsset jcc jcs jec jeq "
+ "jes jge jgt jlc jle jls jlt jmi jne jnr jpl jnn jscc "
+ "jscs jsec jseq jses jsge jsgt jslc jsle jsls jslt jsmi "
+ "jsne jsnr jspl jsnn lra lsl lsr lua mac maci macr macri "
+ "max maxm merge move movem movec movep mpy mpyi mpyr "
+ "mpyri nop norm normf not or ori pflush pflushun "
+ "pfree plock plockr punlock punlockr rep reset rnd rol "
+ "ror rti rts sbc stop tcc tfr trap trapcc "
+ "trapcs trapec trapeq trapes trapge trapgt traplc traple "
+ "trapls traplt trapmi trapne trapnr trappl trapnn tst "
+ "vsl wait")
+
+ASM56K_MATH_INST = (1, "abs add dec div neg sub subl subr")
+
+ASM56K_REGISTERS = (2, "pc mr ccr sr eom com omr sz sc vba la lc sp ssh ssl ss "
+ "a a2 a1 a0 b b2 b1 b0 x x0 x1 y y0 y1 r0 r1 r2 r3 r4 "
+ "r5 r6 r7 m0 m1 m2 m3 m4 m5 m6 m7 n0 n1 n2 n3 n4 n5 n6 "
+ "n7 ")
+
+ASM56K_DIRECTIVES = (3, "org equ page tabs list nolist if endif else opt title "
+ "macro endm dup dupa dupc dupf baddr bsb bsc bsm dc "
+ "dcb ds dsm dsr buffer endbuf section endsec global "
+ "local xdef xref mode ")
+
+#---- Language Styling Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_ASM_DEFAULT, 'default_style'),
+ (stc.STC_ASM_CHARACTER, 'char_style'),
+ (stc.STC_ASM_COMMENT, 'comment_style'),
+ (stc.STC_ASM_COMMENTBLOCK, 'comment_style'),
+ (stc.STC_ASM_CPUINSTRUCTION, 'keyword_style'),
+ (stc.STC_ASM_DIRECTIVE, 'keyword3_style'),
+ (stc.STC_ASM_DIRECTIVEOPERAND, 'keyword4_style'),
+ (stc.STC_ASM_EXTINSTRUCTION, 'funct_style'),
+ (stc.STC_ASM_IDENTIFIER, 'default_style'),
+ (stc.STC_ASM_MATHINSTRUCTION, 'keyword_style'),
+ (stc.STC_ASM_NUMBER, 'number_style'),
+ (stc.STC_ASM_OPERATOR, 'operator_style'),
+ (stc.STC_ASM_REGISTER, 'keyword2_style'),
+ (stc.STC_ASM_STRING, 'string_style'),
+ (stc.STC_ASM_STRINGEOL, 'stringeol_style') ]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for 68k assembly files"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ # synglob.ID_LANG_68K, synglob.ID_LANG_DSP56K
+ self.SetLexer(stc.STC_LEX_ASM)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List"""
+ if self.LangId == synglob.ID_LANG_68K:
+ return [ASM_CPU_INST, ASM_MATH_INST, ASM_REGISTER, ASM_DIRECTIVES]
+ else:
+ return [ASM56K_CPU_INST, ASM56K_MATH_INST,
+ ASM56K_REGISTERS, ASM56K_DIRECTIVES]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications"""
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u';']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_batch.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_batch.py
new file mode 100644
index 0000000..6f527ed
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_batch.py
@@ -0,0 +1,128 @@
+###############################################################################
+# Name: batch.py #
+# Purpose: Define DOS Batch syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: batch.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration file for dos/windows batch scripts.
+@todo: incorportate winbat keywords
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _batch.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+DOSBAT_KEYWORDS = (0, "append arp assoc at atmadm attrib bootcfg break cacls "
+ "call cd chcp chdir chkdsk chkntfs cls cmd color command "
+ "comp compact control convert copy date debug defrag del "
+ "delete dir diskcomp diskcopy doskey echo edit edlin "
+ "else endlocal EQU erase errorlevel exists exit expand "
+ "fc find findstr for format ftp ftype GEQ goto graftabl "
+ "GTR help if ipconfig keyb label LEQ loadfix logoff LSS "
+ "md mkdir mode more move nbtstat NEQ net netsh netstat "
+ "nlsfunc not nslookup path pathping pause ping popd "
+ "print prompt pushd rd rem ren rename replace restore "
+ "rmdir route runas set setlocal setver share shift "
+ "shutdown sort start subst time title telnet tracetr "
+ "tree type ver verify vol xcopy ")
+
+# WinBatch Keywords
+WINBAT_KEYWORDS = (0, "if then else endif break end return exit next while for "
+ "gosub goto switch select to case endselect endwhile "
+ "endswitch aboveicons acc_attrib acc_chng_nt acc_control "
+ "acc_create acc_delete acc_full_95 acc_full_nt acc_list "
+ "acc_pfull_nt acc_pmang_nt acc_print_nt acc_read "
+ "acc_read_95 acc_read_nt acc_write amc arrange ascending "
+ "attr_a attr_a attr_ci attr_ci attr_dc attr_dc attr_di "
+ "attr_di attr_dm attr_dm attr_h attr_h attr_ic attr_ic "
+ "attr_p attr_p attr_ri attr_ri attr_ro attr_ro attr_sh "
+ "attr_sh attr_sy attr_sy attr_t attr_t attr_x attr_x "
+ "avogadro backscan boltzmann cancel capslock check "
+ "columnscommonformat cr crlf ctrl default default "
+ "deg2rad descending disable drive electric enable eulers "
+ "false faraday float8 fwdscan gftsec globalgroup gmtsec "
+ "goldenratio gravitation hidden icon lbutton lclick "
+ "ldblclick lf lightmps lightmtps localgroup magfield "
+ "major mbokcancel mbutton mbyesno mclick mdblclick minor "
+ "msformat multiple ncsaformat no none none noresize "
+ "normal notify nowait numlock off on open parsec "
+ "parseonly pi planckergs planckjoules printer rad2deg "
+ "rbutton rclick rdblclick regclasses regcurrent "
+ "regmachine regroot regusers rows save scrolllock server "
+ "shift single sorted stack string tab tile true uncheck "
+ "unsorted wait wholesection word1 word2 word4 yes zoomed "
+ "about abs acos addextender appexist appwaitclose asin "
+ "askfilename askfiletext askitemlist askline askpassword "
+ "askyesno atan average beep binaryalloc binarycopy "
+ "binaryeodget binaryeodset binaryfree binaryhashrec "
+ "binaryincr binaryincr2 binaryincr4 binaryincrflt "
+ "binaryindex binaryindexnc binaryoletype binarypeek "
+ "binarypeek2 binarypeek4 binarypeekflt binarypeekstr "
+ "binarypoke binarypoke2 binarypoke4 binarypokeflt "
+ "binarypokestr binaryread binarysort binarystrcnt "
+ "binarywrite boxbuttondraw boxbuttonkill boxbuttonstat "
+ "boxbuttonwait boxcaption boxcolor boxdataclear "
+ "boxdatatag boxdestroy boxdrawcircle boxdrawline "
+ "boxdrawrect boxdrawtext boxesup boxmapmode boxnew "
+ "boxopen boxpen boxshut boxtext boxtextcolor boxtextfont "
+ "boxtitle boxupdates break buttonnames by call callext "
+ "ceiling char2num clipappend clipget clipput continue "
+ "cos cosh datetime ddeexecute ddeinitiate ddepoke "
+ "dderequest ddeterminate ddetimeout debug debugdata "
+ "decimals delay dialog dialogbox dirattrget dirattrset "
+ "dirchange direxist")
+
+#---- Language Styling Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_BAT_DEFAULT, "default_style"),
+ (stc.STC_BAT_COMMAND, "class_style"),
+ (stc.STC_BAT_COMMENT, "comment_style"),
+ (stc.STC_BAT_HIDE, "string_style"),
+ (stc.STC_BAT_IDENTIFIER, "scalar_style"),
+ (stc.STC_BAT_LABEL, "class_style"),
+ (stc.STC_BAT_OPERATOR, "operator_style"),
+ (stc.STC_BAT_WORD, "keyword_style") ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Batch files"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_BATCH)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [DOSBAT_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications"""
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set"""
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'::']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_boo.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_boo.py
new file mode 100644
index 0000000..d5ead7f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_boo.py
@@ -0,0 +1,78 @@
+###############################################################################
+# Name: boo.py #
+# Purpose: Define Boo language syntax and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: boo.py
+@summary: Defines language and syntax highlighting settings for the Boo
+ programming language
+@todo: support for C style comment regions
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _boo.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _python
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+BOO_KW = (0, "abstract and as AST break callable cast char class constructor "
+ "continue def destructor do elif else ensure enum event except "
+ "failure final false for from get given goto if import in "
+ "interface internal is isa not null of or otherwise override "
+ "namespace partial pass private protected public raise ref retry "
+ "return self set static super struct success transient true try "
+ "typeof unless virtual when while yield")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [x for x in _python.SYNTAX_ITEMS if x[0] != stc.STC_P_DECORATOR]
+SYNTAX_ITEMS.append((stc.STC_P_DECORATOR, 'default_style'))
+
+#---- Extra Properties ----#
+
+FOLD = ("fold", "1")
+TIMMY = ("tab.timmy.whinge.level", "1") # Mark Inconsistent indentation
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Boo
+ @todo: needs custom highlighting handler
+
+ """
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_PYTHON)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [BOO_KW]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, TIMMY]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_caml.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_caml.py
new file mode 100644
index 0000000..dc16ec0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_caml.py
@@ -0,0 +1,95 @@
+###############################################################################
+# Name: caml.py #
+# Purpose: Define Caml syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: caml.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Caml
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _caml.py 66108 2010-11-10 21:04:54Z CJP $"
+__revision__ = "$Revision: 66108 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+# Objective Caml 3 textual keywords
+CAML_KW1 = (0, "and as assert asr begin class constraint do done downto else "
+ "end exception external false for fun function functor if in "
+ "include inherit initializer land lazy let lor lsl lsr lxor "
+ "match method mod module mutable new object of open or private "
+ "rec sig struct then to true try type val virtual when while "
+ "with")
+
+# Caml optional keywords
+CAML_KW2 = (1, "option Some None ignore ref lnot succ pred parser")
+
+# Caml type/library keywords
+CAML_KW3 = (2, "array bool char float int list string unit")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_CAML_CHAR, 'char_style'),
+ (stc.STC_CAML_COMMENT, 'comment_style'),
+ (stc.STC_CAML_COMMENT1, 'comment_style'),
+ (stc.STC_CAML_COMMENT2, 'comment_style'),
+ (stc.STC_CAML_COMMENT3, 'comment_style'),
+ (stc.STC_CAML_DEFAULT, 'default_style'),
+ (stc.STC_CAML_IDENTIFIER, 'default_style'),
+ (stc.STC_CAML_KEYWORD, 'keyword_style'),
+ (stc.STC_CAML_KEYWORD2, 'pre_style'),
+ (stc.STC_CAML_KEYWORD3, 'keyword2_style'),
+ (stc.STC_CAML_LINENUM, 'number_style'),
+ (stc.STC_CAML_NUMBER, 'number_style'),
+ (stc.STC_CAML_OPERATOR, 'operator_style'),
+ (stc.STC_CAML_STRING, 'string_style'),
+ (stc.STC_CAML_TAGNAME, 'directive_style')] #STYLE ME
+
+if wx.VERSION >= (2, 9, 0, 0, ''):
+ SYNTAX_ITEMS.append((stc.STC_CAML_WHITE, 'default_style')) #TODO
+
+#---- Extra Properties ----#
+FOLD = ('fold', '1')
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Caml"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CAML)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [CAML_KW1, CAML_KW2, CAML_KW3]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'(*', u'*)']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cobra.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cobra.py
new file mode 100644
index 0000000..42b7008
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cobra.py
@@ -0,0 +1,152 @@
+###############################################################################
+# Name: cobra.py #
+# Purpose: Define Cobra syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Define support for Cobra programming language.
+@summary: Lexer configuration module for Cobra.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _cobra.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+# Indenter keywords
+INDENT_KW = (u"body", u"branch", u"class", u"cue", u"def", u"else", u"except",
+ u"expect", u"finally", u"for", u"if", u"invariant", u"namespace",
+ u"on" u"post", u"shared", u"success", u"test", u"try", u"while")
+
+UNINDENT_KW = (u"return", u"raise", u"break", u"continue", u"pass")
+
+# Cobra Keywords
+KEYWORDS = ("abstract adds all and any as assert base be body bool branch "
+ "break callable catch char class const continue cue decimal def do"
+ "dynamic each else end ensure enum event every except expect "
+ "extend extern fake false finally float for from get has if ignore "
+ "implements implies import in inherits inlined inout int interface "
+ "internal invariant is listen mixin must namespace new nil "
+ "nonvirtual not number objc of off old on or out override partial "
+ "pass passthrough post print private pro protected public raise "
+ "ref require return same set shared sig stop struct success test "
+ "this throw to to\\? trace true try uint use using var vari "
+ "virtual where while yield")
+KEYWORDS = (0, KEYWORDS)
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_P_DEFAULT, 'default_style'),
+ (stc.STC_P_CHARACTER, 'char_style'),
+ (stc.STC_P_CLASSNAME, 'class_style'),
+ (stc.STC_P_COMMENTBLOCK, 'comment_style'),
+ (stc.STC_P_COMMENTLINE, 'comment_style'),
+ (stc.STC_P_DECORATOR, 'decor_style'),
+ (stc.STC_P_DEFNAME, 'keyword3_style'),
+ (stc.STC_P_IDENTIFIER, 'default_style'),
+ (stc.STC_P_NUMBER, 'number_style'),
+ (stc.STC_P_OPERATOR, 'operator_style'),
+ (stc.STC_P_STRING, 'string_style'),
+ (stc.STC_P_STRINGEOL, 'stringeol_style'),
+ (stc.STC_P_TRIPLE, 'string_style'),
+ (stc.STC_P_TRIPLEDOUBLE, 'string_style'),
+ (stc.STC_P_WORD, 'keyword_style'),
+ (stc.STC_P_WORD2, 'userkw_style')]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+TIMMY = ("tab.timmy.whinge.level", "1") # Mark Inconsistant indentation
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Cobra"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_PYTHON)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [KEYWORDS, ]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, TIMMY]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#', ]
+
+#-----------------------------------------------------------------------------#
+
+def AutoIndenter(estc, pos, ichar):
+ """Auto indent cobra code.
+ @param estc: EditraStyledTextCtrl
+ @param pos: current carat position
+ @param ichar: Indentation character
+
+ """
+ line = estc.GetCurrentLine()
+ spos = estc.PositionFromLine(line)
+ text = estc.GetTextRange(spos, pos)
+ eolch = estc.GetEOLChar()
+ inspace = text.isspace()
+
+ # Cursor is in the indent area somewhere
+ if inspace:
+ estc.AddText(eolch + text)
+ return
+
+ # Check if the cursor is in column 0 and just return newline.
+ if not len(text):
+ estc.AddText(eolch)
+ return
+
+ indent = estc.GetLineIndentation(line)
+ if ichar == u"\t":
+ tabw = estc.GetTabWidth()
+ else:
+ tabw = estc.GetIndent()
+
+ i_space = indent / tabw
+ end_spaces = ((indent - (tabw * i_space)) * u" ")
+
+ tokens = filter(None, text.strip().split())
+ if tokens and not inspace:
+ if tokens[-1].endswith(u""):
+ if tokens[0] in INDENT_KW:
+ i_space += 1
+ elif tokens[0] in UNINDENT_KW:
+ i_space = max(i_space - 1, 0)
+ elif tokens[-1].endswith(u"\\"):
+ i_space += 1
+
+ rval = eolch + (ichar * i_space) + end_spaces
+ if inspace and ichar != u"\t":
+ rpos = indent - (pos - spos)
+ if rpos < len(rval) and rpos > 0:
+ rval = rval[:-rpos]
+ elif rpos >= len(rval):
+ rval = eolch
+
+ # Put text in the buffer
+ estc.AddText(rval)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cpp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cpp.py
new file mode 100644
index 0000000..5d389b4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cpp.py
@@ -0,0 +1,226 @@
+###############################################################################
+# Name: cpp.py #
+# Purpose: Define C/CPP/ObjC/Vala syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: cpp.py
+@author: Cody Precord
+@summary: Lexer configuration file for C/C++/C#/Objective C/Vala/Cilk source files.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _cpp.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+import re
+
+# Local imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# C Keywords
+C_KEYWORDS = ("asm break case const continue default do else for goto return "
+ "if sizeof static switch typeof while")
+
+# C Types/Structures/Storage Classes
+C_TYPES = ("auto bool char clock_t complex div_t double enum extern float "
+ "fpos_t inline int int_least8_t int_least16_t int_least32_t "
+ "int_least64_t int8_t int16_t int32_t int64_t intmax_t intptr_t "
+ "jmp_buf ldiv_t long mbstate_t ptrdiff_t register sig_atomic_t "
+ "size_t ssize_t short signed struct typedef union time_t "
+ "uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t uint8_t "
+ "uint16_t uint32_t uint64_t uintptr_t uintmax_t unsigned va_list "
+ "void volatile wchar_t wctrans_t wctype_t wint_t FILE DIR __label__ "
+ "__complex__ __volatile__ __attribute__")
+
+# C/CPP Documentation Keywords (includes Doxygen keywords)
+DOC_KEYWORDS = (2, "TODO FIXME XXX author brief bug callgraph category class "
+ "code date def depreciated dir dot dotfile else elseif em "
+ "endcode enddot endif endverbatim example exception file if "
+ "ifnot image include link mainpage name namespace page par "
+ "paragraph param pre post return retval section struct "
+ "subpage subsection subsubsection test todo typedef union "
+ "var verbatim version warning $ @ ~ < > # % HACK")
+
+# CPP Keyword Extensions
+CPP_KEYWORDS = ("and and_eq bitand bitor catch class compl const_cast delete "
+ "dynamic_cast false friend new not not_eq operator or or_eq "
+ "private protected public reinterpret_cast static_cast this "
+ "throw try true typeid using xor xor_eq")
+
+# CPP Type/Structure/Storage Class Extensions
+CPP_TYPES = ("bool inline explicit export mutable namespace template typename "
+ "virtual wchar_t")
+
+# C# Keywords
+CSHARP_KW = ("abstract as base break case catch checked class const continue "
+ "default delegate do else event explicit extern false finally "
+ "fixed for foreach goto if implicit in interface internal is lock "
+ "new null operator out override params readonly ref return sealed "
+ "sizeof stackalloc static switch this throw true try typeof "
+ "unchecked unsafe using while")
+
+# C# Types
+CSHARP_TYPES = ("bool byte char decimal double enum float int long "
+ "namespace object private protected public sbyte short string "
+ "struct uint ulong ushort virtual void volatile")
+
+# Objective C
+OBJC_KEYWORDS = ("@catch @interface @implementation @end @finally @private "
+ "@protected @protocol @public @throw @try self super false "
+ "true")
+
+OBJC_TYPES = ("id")
+
+# Vala Keywords
+VALA_KEYWORDS = ("abstract as base break case catch checked construct continue "
+ "default delegate do else event false finally for foreach get "
+ "goto if implicit interface internal is lock new operator out "
+ "override params readonly ref return sealed set sizeof "
+ "stackalloc this throw true try typeof unchecked using while")
+
+VALA_TYPES = ("bool byte char class const decimal double enum explicit extern "
+ "fixed float int long namespace private protected public sbyte "
+ "short static string struct uint ulong unichar unsafe ushort var "
+ "volatile void virtual")
+
+# Cilk Keywords
+CILK_KEYWORDS = ("abort private shared spawn sync SYNCHED")
+
+CILK_TYPES = ("cilk inlet")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'),
+ (stc.STC_C_COMMENT, 'comment_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTDOC, 'comment_style'),
+ (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'),
+ (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTLINEDOC, 'comment_style'),
+ (stc.STC_C_CHARACTER, 'char_style'),
+ (stc.STC_C_GLOBALCLASS, 'global_style'),
+ (stc.STC_C_IDENTIFIER, 'default_style'),
+ (stc.STC_C_NUMBER, 'number_style'),
+ (stc.STC_C_OPERATOR, 'operator_style'),
+ (stc.STC_C_PREPROCESSOR, 'pre_style'),
+ (stc.STC_C_REGEX, 'pre_style'),
+ (stc.STC_C_STRING, 'string_style'),
+ (stc.STC_C_STRINGEOL, 'stringeol_style'),
+ (stc.STC_C_UUID, 'pre_style'),
+ (stc.STC_C_VERBATIM, 'number2_style'),
+ (stc.STC_C_WORD, 'keyword_style'),
+ (stc.STC_C_WORD2, 'keyword2_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_PRE = ("styling.within.preprocessor", "0")
+FOLD_COM = ("fold.comment", "1")
+FOLD_COMP = ("fold.compact", "1")
+FOLD_ELSE = ("fold.at.else", "0")
+ALLOW_DOLLARS = ("lexer.cpp.allow.dollars", "1")
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for many C like languages"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List"""
+ keywords = list()
+ kw1_str = [C_KEYWORDS]
+ kw2_str = [C_TYPES]
+ if self.LangId == synglob.ID_LANG_CPP:
+ kw1_str.append(CPP_KEYWORDS)
+ kw2_str.append(CPP_TYPES)
+ elif self.LangId == synglob.ID_LANG_CSHARP:
+ kw1_str = [CSHARP_KW]
+ kw2_str = [CSHARP_TYPES]
+ elif self.LangId == synglob.ID_LANG_OBJC:
+ kw1_str.append(OBJC_KEYWORDS)
+ kw2_str.append(OBJC_TYPES)
+ elif self.LangId == synglob.ID_LANG_VALA:
+ kw1_str = [VALA_KEYWORDS]
+ kw2_str = [VALA_TYPES]
+ elif self.LangId == synglob.ID_LANG_CILK:
+ kw1_str.append(CILK_KEYWORDS)
+ kw2_str.append(CILK_TYPES)
+ else:
+ pass
+
+ keywords.append((0, " ".join(kw1_str)))
+ keywords.append((1, " ".join(kw2_str)))
+ keywords.append(DOC_KEYWORDS)
+ return keywords
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set"""
+ return [FOLD, FOLD_PRE, FOLD_COM]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code
+
+ """
+ if self.LangId in [ synglob.ID_LANG_CPP,
+ synglob.ID_LANG_CSHARP,
+ synglob.ID_LANG_OBJC,
+ synglob.ID_LANG_VALA ]:
+ return [u'//']
+ else:
+ return [u'/*', u'*/']
+
+#-----------------------------------------------------------------------------#
+
+def AutoIndenter(estc, pos, ichar):
+ """Auto indent cpp code.
+ @param estc: EditraStyledTextCtrl
+ @param pos: current carat position
+ @param ichar: Indentation character
+ @return: string
+
+ """
+ rtxt = u''
+ line = estc.GetCurrentLine()
+ text = estc.GetTextRange(estc.PositionFromLine(line), pos)
+ eolch = estc.GetEOLChar()
+
+ indent = estc.GetLineIndentation(line)
+ if ichar == u"\t":
+ tabw = estc.GetTabWidth()
+ else:
+ tabw = estc.GetIndent()
+
+ i_space = indent / tabw
+ ndent = eolch + ichar * i_space
+ rtxt = ndent + ((indent - (tabw * i_space)) * u' ')
+
+ cdef_pat = re.compile('(public|private|protected)\s*\:')
+ case_pat = re.compile('(case\s+.+|default)\:')
+ text = text.strip()
+ if text.endswith('{') or cdef_pat.match(text) or case_pat.match(text):
+ rtxt += ichar
+
+ # Put text in the buffer
+ estc.AddText(rtxt)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_css.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_css.py
new file mode 100644
index 0000000..31387df
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_css.py
@@ -0,0 +1,223 @@
+###############################################################################
+# Name: css.py #
+# Purpose: Define CSS syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: css.py
+@author: Cody Precord
+@summary: Lexer configuration file for Cascading Style Sheets.
+
+ 0. CSS1 Properties
+ 1. Pseudo-classes
+ 2. CSS2 Properties
+ 3. CSS3 Properties
+ 4. Pseudo-elements
+ 5. Browser-Specific CSS Properties
+ 6. Browser-Specific Pseudo-classes
+ 7. Browser-Specific Pseudo-elements
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _css.py 72399 2012-08-29 19:56:26Z CJP $"
+__revision__ = "$Revision: 72399 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# CSS1 Keywords (Identifiers)
+CSS1_KEYWORDS = (0, "font-family font-style font-variant font-weight font-size "
+ "font color background-color background-image "
+ "background-repeat background-position background "
+ "word-spacing letter-spacing text-decoration "
+ "vertical-align text-transform text-align text-indent "
+ "line-height margin-top margin-right margin-left margin "
+ "padding-top padding-right padding-bottom padding-left "
+ "padding border-top-width border-right-width "
+ "border-bottom-width border-left-width border-width "
+ "border-color border-style border-top border-right "
+ "border-bottom border-left border width height float clear "
+ "display white-space list-style-type list-style-image "
+ "list-style-position list-style margin-bottom "
+ "text-decoration min-width min-height "
+ "background-attachment")
+
+# CSS Psuedo Classes
+CSS_PSUEDO_CLASS = (1, "link active visited indeterminate default "
+ # CSS 2
+ "first-child focus hover lang left right first "
+ # CSS 3
+ "empty enabled disabled checked not root target "
+ "only-child last-child nth-child nth-last-child "
+ "first-of-type last-of-type nth-of-type "
+ "nth-last-of-type only-of-type valid invalid required "
+ "optional")
+
+# CSS2 Keywords (Identifiers)
+# This is meant for css2 specific keywords, but in order to get a better
+# coloring effect this will contain special css properties as well.
+CSS2_KEYWORDS = (2, "ActiveBorder ActiveCaption AppWorkspace Background "
+ "ButtonFace ButtonHighlight ButtonShadow ButtonText "
+ "CaptionText GrayText Highlight HighlightText "
+ "InactiveBorder InactiveCaption InactiveCaptionText "
+ "InfoBackground InfoText Menu MenuText Scrollbar "
+ "ThreeDDarkShadow ThreeDFace ThreeDHighlight "
+ "ThreeDLightShadow ThreeDShadow Window WindowFrame "
+ "WindowText above absolute all always aqua armenian ascent "
+ "auto avoid azimuth baseline baseline bbox behind below "
+ "bidi-override black blink block blue bold bolder both "
+ "bottom capitalize center center centerline child circle "
+ "clear clip code collapse color compact content continuous "
+ "crop cross crosshair cursive cursor dashed default "
+ "descent digits disc dotted double during elevation embed "
+ "fantasy faster female fixed fixed float fuchsia georgian "
+ "gray green groove hebrew height help hidden hide higher "
+ "icon inherit inline inset inside inside invert italic "
+ "justify landscape larger leftwards level lighter lime "
+ "lowercase ltr male marks maroon mathline medium menu "
+ "middle mix monospace move narrower navy non none normal "
+ "nowrap oblique olive once orphans outset outside overflow "
+ "overline pointer portrait position pre purple quotes red "
+ "relative richness ridge rightwards rtl scroll scroll "
+ "separate show silent silver size slope slower smaller "
+ "solid square src static stemh stemv stress sub super teal "
+ "thick thin top topline underline uppercase visibility "
+ "visible volume wait wider widows width widths yellow "
+ "z-index outline left")
+
+# CSS3 Keywords
+CSS3_KEYWORDS = (3, "border-radius border-top-left-radius "
+ "border-top-right-radius border-bottom-left-radius "
+ "border-bottom-right-radius border-image "
+ "border-image-outset border-image-repeat "
+ "border-image-source border-image-slice border-image-width "
+ "break-after break-before break-inside columns "
+ "column-count column-fill column-gap column-rule "
+ "column-rule-color column-rule-style column-rule-width "
+ "column-span column-width @keframes animation "
+ "animation-delay animation-direction animation-duration "
+ "animation-fill-mode animation-iteration-count "
+ "animation-name animation-play-state "
+ "animation-timing-function transition transition-delay "
+ "transition-duration transition-timing-function "
+ "transition-property backface-visibility perspective "
+ "perspective-origin transform transform-origin "
+ "transform-style background-clip background-origin "
+ "background-size overflow-x overflow-y overflow-style "
+ "marquee-direction marquee-play-count marquee-speed "
+ "marquee-style box-shadow box-decoration-break opacity")
+
+PSEUDO_ELEMENTS = (4, "first-letter first-line before after selection")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_CSS_DEFAULT, 'default_style'),
+ (stc.STC_CSS_ATTRIBUTE, 'funct_style'),
+ (stc.STC_CSS_CLASS, 'global_style'),
+ (stc.STC_CSS_COMMENT, 'comment_style'),
+ (stc.STC_CSS_DIRECTIVE, 'directive_style'),
+ (stc.STC_CSS_DOUBLESTRING, 'string_style'),
+ (stc.STC_CSS_ID, 'scalar_style'),
+ (stc.STC_CSS_IDENTIFIER, 'keyword_style'),
+ (stc.STC_CSS_IDENTIFIER2, 'keyword3_style'),
+ (stc.STC_CSS_IMPORTANT, 'error_style'),
+ (stc.STC_CSS_OPERATOR, 'operator_style'),
+ (stc.STC_CSS_PSEUDOCLASS, 'scalar_style'),
+ (stc.STC_CSS_SINGLESTRING, 'string_style'),
+ (stc.STC_CSS_TAG, 'keyword_style'),
+ (stc.STC_CSS_UNKNOWN_IDENTIFIER, 'unknown_style'),
+ (stc.STC_CSS_UNKNOWN_PSEUDOCLASS, 'unknown_style'),
+ (stc.STC_CSS_VALUE, 'char_style') ]
+
+# TODO: add styling and keywords for new style regions in 2.9
+if wx.VERSION >= (2, 9, 0, 0, ''):
+ # Browser specific identifiers
+ SYNTAX_ITEMS.append((stc.STC_CSS_EXTENDED_IDENTIFIER, 'default_style'))
+ SYNTAX_ITEMS.append((stc.STC_CSS_EXTENDED_PSEUDOCLASS, 'default_style'))
+ SYNTAX_ITEMS.append((stc.STC_CSS_EXTENDED_PSEUDOELEMENT, 'default_style'))
+ # CSS3 Properties
+ SYNTAX_ITEMS.append((stc.STC_CSS_IDENTIFIER3, 'keyword2_style'))
+ # Pseudo elements
+ SYNTAX_ITEMS.append((stc.STC_CSS_PSEUDOELEMENT, 'default_style'))
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for CSS"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CSS)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ kwlist = [CSS1_KEYWORDS , CSS_PSUEDO_CLASS]
+ # 2.9 supports CSS3 so for 2.8 just add CSS3 keywords to the css2 list
+ if wx.VERSION < (2, 9, 0, 0, ''):
+ css2_kw = (CSS2_KEYWORDS[0], " ".join((CSS2_KEYWORDS[1], CSS3_KEYWORDS[1])))
+ kwlist.append(css2_kw)
+ else:
+ kwlist.append(CSS2_KEYWORDS)
+ kwlist.append(CSS3_KEYWORDS)
+ kwlist.append(PSEUDO_ELEMENTS)
+ return kwlist
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'/*', u'*/']
+
+#-----------------------------------------------------------------------------#
+
+def AutoIndenter(estc, pos, ichar):
+ """Auto indent cpp code.
+ @param estc: EditraStyledTextCtrl
+ @param pos: current carat position
+ @param ichar: Indentation character
+
+ """
+ rtxt = u''
+ line = estc.GetCurrentLine()
+ text = estc.GetTextRange(estc.PositionFromLine(line), pos)
+ eolch = estc.GetEOLChar()
+
+ indent = estc.GetLineIndentation(line)
+ if ichar == u"\t":
+ tabw = estc.GetTabWidth()
+ else:
+ tabw = estc.GetIndent()
+
+ i_space = indent / tabw
+ ndent = eolch + ichar * i_space
+ rtxt = ndent + ((indent - (tabw * i_space)) * u' ')
+
+ if text.endswith('{'):
+ rtxt += ichar
+
+ # Put text in the buffer
+ estc.AddText(rtxt)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_d.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_d.py
new file mode 100644
index 0000000..ca394f3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_d.py
@@ -0,0 +1,144 @@
+###############################################################################
+# Name: d.py #
+# Purpose: Define D programming language syntax for highlighting and other #
+# features. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: d.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for D programming language
+@todo: When 2.9 is out switch to the dedicated D Lexer
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _d.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+from _cpp import AutoIndenter
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+D_KEYWORDS = (0, "abstract alias align asm assert auto body break case cast "
+ "catch cent class continue debug default delegate delete "
+ "deprecated do else enum export extern false final finally "
+ "for foreach foreach_reverse function goto if import in inout "
+ "interface invariant is lazy mixin module new null out "
+ "override package pragma private protected public return "
+ "scope short struct super switch synchronized template this "
+ "throw true try union unittest version void while with")
+
+D_TYPES = (1, "bool byte cdouble cfloat char const creal dchar double float "
+ "idouble ifloat ireal int real long static typeof typedef typeid "
+ "ubyte ucent uint ulong ushort volatile wchar")
+
+DOC_KEYWORDS = (2, "TODO FIXME XXX \\author \\brief \\bug \\callgraph "
+ "\\category \\class \\code \\date \\def \\depreciated \\dir "
+ "\\dot \\dotfile \\else \\elseif \\em \\endcode \\enddot "
+ "\\endif \\endverbatim \\example \\exception \\file \\if "
+ "\\ifnot \\image \\include \\link \\mainpage \\name "
+ "\\namespace \\page \\par \\paragraph \\param \\return "
+ "\\retval \\section \\struct \\subpage \\subsection "
+ "\\subsubsection \\test \\todo \\typedef \\union \\var "
+ "\\verbatim \\version \\warning \\$ \\@ \\~ \\< \\> \\# \\% "
+ "HACK ")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+if wx.VERSION >= (2, 9, 0, 0, ''):
+ SYNTAX_ITEMS = [ (stc.STC_D_CHARACTER, 'char_style'),
+ (stc.STC_D_COMMENT, 'comment_style'),
+ (stc.STC_D_COMMENTDOC, 'comment_style'),
+ (stc.STC_D_COMMENTDOCKEYWORD, 'dockey_style'),
+ (stc.STC_D_COMMENTDOCKEYWORDERROR, 'error_style'),
+ (stc.STC_D_COMMENTLINE, 'comment_style'),
+ (stc.STC_D_COMMENTLINEDOC, 'comment_style'),
+ (stc.STC_D_COMMENTNESTED, 'comment_style'),
+ (stc.STC_D_DEFAULT, 'default_style'),
+ (stc.STC_D_IDENTIFIER, 'default_style'),
+ (stc.STC_D_NUMBER, 'number_style'),
+ (stc.STC_D_OPERATOR, 'operator_style'),
+ (stc.STC_D_STRING, 'string_style'),
+ (stc.STC_D_STRINGB, 'string_style'), #TODO
+ (stc.STC_D_STRINGEOL, 'stringeol_style'),
+ (stc.STC_D_STRINGR, 'string_style'), #TODO
+ (stc.STC_D_TYPEDEF, 'default_style'), # NEEDS STYLE
+ (stc.STC_D_WORD, 'keyword_style'),
+ (stc.STC_D_WORD2, 'keyword2_style'),
+ (stc.STC_D_WORD3, 'keyword3_style'),
+ (stc.STC_D_WORD5, 'default_style'), #TODO
+ (stc.STC_D_WORD6, 'default_style'), #TODO
+ (stc.STC_D_WORD7, 'default_style')] #TODO
+else:
+ SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'),
+ (stc.STC_C_COMMENT, 'comment_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTDOC, 'comment_style'),
+ (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'),
+ (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTLINEDOC, 'comment_style'),
+ (stc.STC_C_CHARACTER, 'char_style'),
+ (stc.STC_C_GLOBALCLASS, 'global_style'),
+ (stc.STC_C_IDENTIFIER, 'default_style'),
+ (stc.STC_C_NUMBER, 'number_style'),
+ (stc.STC_C_OPERATOR, 'operator_style'),
+ (stc.STC_C_PREPROCESSOR, 'pre_style'),
+ (stc.STC_C_REGEX, 'pre_style'),
+ (stc.STC_C_STRING, 'string_style'),
+ (stc.STC_C_STRINGEOL, 'stringeol_style'),
+ (stc.STC_C_UUID, 'pre_style'),
+ (stc.STC_C_VERBATIM, 'number2_style'),
+ (stc.STC_C_WORD, 'keyword_style'),
+ (stc.STC_C_WORD2, 'keyword2_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_PRE = ("styling.within.preprocessor", "0")
+FOLD_COM = ("fold.comment", "1")
+FOLD_COMP = ("fold.compact", "1")
+FOLD_ELSE = ("fold.at.else", "0")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for D"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ if wx.VERSION >= (2, 9, 0, 0, ''):
+ self.SetLexer(stc.STC_LEX_D)
+ else:
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [D_KEYWORDS, D_TYPES, DOC_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FOLD_PRE, FOLD_COM]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'//']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_diff.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_diff.py
new file mode 100644
index 0000000..ac9e2e2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_diff.py
@@ -0,0 +1,71 @@
+###############################################################################
+# Name: diff.py #
+# Purpose: Define Diff/Patch file syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: diff.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Diff/Patch files
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org"
+__svnid__ = "$Id: _diff.py 66108 2010-11-10 21:04:54Z CJP $"
+__revision__ = "$Revision: 66108 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+# None
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_DIFF_ADDED, 'global_style'),
+ (stc.STC_DIFF_COMMAND, 'pre_style'),
+ (stc.STC_DIFF_COMMENT, 'comment_style'),
+ (stc.STC_DIFF_DEFAULT, 'default_style'),
+ (stc.STC_DIFF_DELETED, 'error_style'),
+ (stc.STC_DIFF_HEADER, 'comment_style'),
+ (stc.STC_DIFF_POSITION, 'pre_style')]
+
+if wx.VERSION >= (2, 9, 0, 0, ''):
+ SYNTAX_ITEMS.append((stc.STC_DIFF_CHANGED, 'default_style')) #TODO
+
+#---- Extra Properties ----#
+FOLD = ('fold', '1')
+FOLD_COMPACT = ('fold.compact', '1')
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Diff files"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_DIFF)
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FOLD_COMPACT]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return ['--- ']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_django.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_django.py
new file mode 100644
index 0000000..57ce70f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_django.py
@@ -0,0 +1,141 @@
+###############################################################################
+# Name: django.py #
+# Purpose: Define Django syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: django.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Django Templates.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _django.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+from pygments.token import Token
+from pygments.lexers import get_lexer_by_name
+
+#Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+# Style Id's
+
+STC_DJANGO_DEFAULT, \
+STC_DJANGO_COMMENT, \
+STC_DJANGO_NUMBER, \
+STC_DJANGO_STRING, \
+STC_DJANGO_STRINGEOL, \
+STC_DJANGO_SCALAR, \
+STC_DJANGO_OPERATOR, \
+STC_DJANGO_PREPROCESSOR, \
+STC_DJANGO_ATTRIBUTE, \
+STC_DJANGO_TAG, \
+STC_DJANGO_BUILTIN, \
+STC_DJANGO_KEYWORD = range(12)
+
+#-----------------------------------------------------------------------------#
+
+# Python Keywords
+KEYWORDS = ("true false undefined null in as reversed recursive not and or is "
+ "if else import with loop block forloop")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (STC_DJANGO_DEFAULT, 'default_style'),
+ (STC_DJANGO_COMMENT, 'comment_style'),
+ (STC_DJANGO_NUMBER, 'number_style'),
+ (STC_DJANGO_STRING, 'string_style'),
+ (STC_DJANGO_STRINGEOL, 'stringeol_style'),
+ (STC_DJANGO_SCALAR, 'scalar_style'),
+ (STC_DJANGO_OPERATOR, 'operator_style'),
+ (STC_DJANGO_PREPROCESSOR, 'pre_style'),
+ (STC_DJANGO_ATTRIBUTE, 'keyword2_style'),
+ (STC_DJANGO_TAG, 'keyword_style'), # Need new tag
+ (STC_DJANGO_BUILTIN, 'keyword4_style'),
+ (STC_DJANGO_KEYWORD, 'keyword_style'), ]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Django"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CONTAINER)
+ self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [(1, KEYWORDS)]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u"#",]
+
+#-----------------------------------------------------------------------------#
+
+def StyleText(stc, start, end):
+ """Style the text
+ @param stc: Styled text control instance
+ @param start: Start position
+ @param end: end position
+
+ """
+ cpos = 0
+ stc.StartStyling(cpos, 0x1f)
+ lexer = get_lexer_by_name("html+django")
+ doctxt = stc.GetTextRange(0, end)
+ wineol = stc.GetEOLChar() == "\r\n"
+
+ # Need to convert to UTF-8 in order to calculate
+ # correct positions in STC.
+ try:
+ doctxt = doctxt.encode('utf-8')
+ except:
+ pass
+
+ for token, txt in lexer.get_tokens(doctxt):
+# print token, txt
+ style = TOKEN_MAP.get(token, STC_DJANGO_DEFAULT)
+ if style == STC_DJANGO_PREPROCESSOR and txt.startswith(u'#'):
+ style = STC_DJANGO_COMMENT
+# elif style == STC_DJANGO_STRING and txt[-1] not in '"\'':
+# style = STC_DJANGO_STRINGEOL
+
+ tlen = len(txt)
+ if wineol and "\n" in txt:
+ tlen += txt.count("\n")
+
+ if tlen:
+ stc.SetStyling(tlen, style)
+ cpos += tlen
+ stc.StartStyling(cpos, 0x1f)
+
+#-----------------------------------------------------------------------------#
+
+TOKEN_MAP = { Token.Literal.String : STC_DJANGO_STRING,
+ Token.Comment.Preproc : STC_DJANGO_PREPROCESSOR,
+ Token.Comment : STC_DJANGO_COMMENT,
+ Token.Name.Builtin : STC_DJANGO_BUILTIN,
+ Token.Operator : STC_DJANGO_OPERATOR,
+ Token.Punctuation : STC_DJANGO_OPERATOR,
+ Token.Number : STC_DJANGO_NUMBER,
+ Token.Keyword : STC_DJANGO_KEYWORD,
+ Token.Name.Attribute : STC_DJANGO_ATTRIBUTE,
+ Token.String.Interpol : STC_DJANGO_SCALAR,
+ Token.Name.Tag : STC_DJANGO_TAG }
+ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_dot.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_dot.py
new file mode 100644
index 0000000..aa4e3ba
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_dot.py
@@ -0,0 +1,114 @@
+###############################################################################
+# Name: dot.py #
+# Purpose: Define DOT graph visualization language syntax for highlighting #
+# and other features. #
+# Author: Rob McMullen <robm@users.sourceforge.net> #
+# Copyright: (c) 2007 Rob McMullen <robm@users.sourceforge.net #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: dot.py
+AUTHOR: Rob McMullen
+@summary: Lexer configuration module for the DOT graph description language
+
+"""
+
+__author__ = "Rob McMullen <robm@users.sourceforge.net>"
+__svnid__ = "$Id: _dot.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+DOT_KEYWORDS = (0, "node edge graph digraph subgraph strict")
+
+DOT_TYPES = (1,
+"Damping K URL arrowhead arrowsize arrowtail bb bgcolor center charsetil "
+"clusterrank color colorscheme comment compound concentrate constraint "
+"decorate defaultdist dim dir diredgeconstraints distortion dpi edgeURL "
+"edgehref edgetarget edgetooltip epsilon esep fillcolor fixedsize "
+"fontcolor fontname fontnames fontpath fontsize group headURL headclip "
+"headhref headlabel headport headtarget headtooltip height href label "
+"labelURL labelangle labeldistance labelfloat labelfontcolor "
+"labelfontname labelfontsize labelhref labeljust labelloc labeltarget "
+"labeltooltip landscape layer layers layersep len levelsgap lhead lp "
+"ltail margin maxiter mclimit mindist minlen mode model mosek nodesep "
+"nojustify normalize nslimit nslimit1 ordering orientation orientation "
+"outputorder overlap pack packmode pad page pagedir pencolor "
+"peripheries pin pos quantum rank rankdir ranksep ratio rects regular "
+"remincross resolution root rotate samehead sametail samplepoints "
+"searchsize sep shape shapefile showboxes sides size skew splines start "
+"style stylesheet tailURL tailclip tailhref taillabel tailport "
+"tailtarget tailtooltip target tooltip truecolor vertices viewport "
+"voro_margin weight width z arrowType clusterMode color colorList "
+"dirType escString layerList layerRange lblString outputMode packMode "
+"pagedir point pointf pointfList portPos rankType rankdir rect shape "
+"splineType startType style viewPort "
+)
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'),
+ (stc.STC_C_COMMENT, 'comment_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTDOC, 'comment_style'),
+ (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'),
+ (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTLINEDOC, 'comment_style'),
+ (stc.STC_C_CHARACTER, 'char_style'),
+ (stc.STC_C_GLOBALCLASS, 'global_style'),
+ (stc.STC_C_IDENTIFIER, 'default_style'),
+ (stc.STC_C_NUMBER, 'number_style'),
+ (stc.STC_C_OPERATOR, 'operator_style'),
+ (stc.STC_C_PREPROCESSOR, 'pre_style'),
+ (stc.STC_C_REGEX, 'pre_style'),
+ (stc.STC_C_STRING, 'string_style'),
+ (stc.STC_C_STRINGEOL, 'stringeol_style'),
+ (stc.STC_C_UUID, 'pre_style'),
+ (stc.STC_C_VERBATIM, "number2_style"),
+ (stc.STC_C_WORD, 'keyword_style'),
+ (stc.STC_C_WORD2, 'keyword2_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_PRE = ("styling.within.preprocessor", "0")
+FOLD_COM = ("fold.comment", "1")
+FOLD_COMP = ("fold.compact", "1")
+FOLD_ELSE = ("fold.at.else", "0")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for DOT"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [DOT_KEYWORDS, DOT_TYPES]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FOLD_PRE]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'//']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_editra_ss.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_editra_ss.py
new file mode 100644
index 0000000..39abd74
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_editra_ss.py
@@ -0,0 +1,82 @@
+###############################################################################
+# Name: editra_ss.py #
+# Purpose: Define Editra Style Sheet syntax for highlighting and other #
+# features. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: editra_ss.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration file for Editra Syntax Highlighter Style Sheets.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _editra_ss.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+from _css import AutoIndenter
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Editra Style Sheet Keywords
+ESS_KEYWORDS = (0, "fore back face size eol bold italic modifiers")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_CSS_DEFAULT, 'default_style'),
+ (stc.STC_CSS_CLASS, 'global_style'),
+ (stc.STC_CSS_COMMENT, 'comment_style'),
+ (stc.STC_CSS_DIRECTIVE, 'directive_style'),
+ (stc.STC_CSS_DOUBLESTRING, 'string_style'),
+ (stc.STC_CSS_ID, 'scalar_style'),
+ (stc.STC_CSS_IDENTIFIER, 'keyword4_style'),
+ (stc.STC_CSS_IDENTIFIER2, 'keyword3_style'),
+ (stc.STC_CSS_IMPORTANT, 'error_style'),
+ (stc.STC_CSS_OPERATOR, 'operator_style'),
+ (stc.STC_CSS_PSEUDOCLASS, 'scalar_style'),
+ (stc.STC_CSS_SINGLESTRING, 'string_style'),
+ (stc.STC_CSS_TAG, 'keyword_style'),
+ (stc.STC_CSS_UNKNOWN_IDENTIFIER, 'unknown_style'),
+ (stc.STC_CSS_UNKNOWN_PSEUDOCLASS, 'unknown_style'),
+ (stc.STC_CSS_VALUE, 'char_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Editra Style Sheets"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CSS)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [ESS_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'/*', '*/']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_edje.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_edje.py
new file mode 100644
index 0000000..6757c73
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_edje.py
@@ -0,0 +1,101 @@
+###############################################################################
+# Name: edje.py #
+# Purpose: Syntax provider module for the Enlightenment Foundation Libraries #
+# interface language Edje and Edje Data Collection files. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: edje.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Edje. Edje is a interface definition
+ language that is part of the Enlightenment Foundation Libraries for
+ E17.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _edje.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+EDJE_KW = (0, "action after align aspect border clip_to color color2 color3 "
+ "color_class effect fit font image inherit name normal max min "
+ "mouse_events offset relative repeat_events signal size smooth "
+ "source state step target text_class to to_x to_y transition "
+ "tween type visible")
+
+EDJE_SEC = (1, "collections description fill group images part parts program "
+ "programs rel1 rel2 text")
+
+DOC_KEYWORDS = (2, "TODO FIXME XXX HACK")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'),
+ (stc.STC_C_COMMENT, 'comment_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTDOC, 'comment_style'),
+ (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'),
+ (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTLINEDOC, 'comment_style'),
+ (stc.STC_C_CHARACTER, 'char_style'),
+ (stc.STC_C_GLOBALCLASS, 'global_style'),
+ (stc.STC_C_IDENTIFIER, 'default_style'),
+ (stc.STC_C_NUMBER, 'number_style'),
+ (stc.STC_C_OPERATOR, 'operator_style'),
+ (stc.STC_C_PREPROCESSOR, 'pre_style'),
+ (stc.STC_C_REGEX, 'pre_style'),
+ (stc.STC_C_STRING, 'string_style'),
+ (stc.STC_C_STRINGEOL, 'stringeol_style'),
+ (stc.STC_C_UUID, 'pre_style'),
+ (stc.STC_C_VERBATIM, 'number2_style'),
+ (stc.STC_C_WORD, 'keyword_style'),
+ (stc.STC_C_WORD2, 'keyword2_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_PRE = ("styling.within.preprocessor", "0")
+FOLD_COM = ("fold.comment", "1")
+FOLD_COMP = ("fold.compact", "1")
+FOLD_ELSE = ("fold.at.else", "0")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Edje"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [EDJE_KW, EDJE_SEC]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FOLD_PRE]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'//']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_eiffel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_eiffel.py
new file mode 100644
index 0000000..b58fe63
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_eiffel.py
@@ -0,0 +1,81 @@
+###############################################################################
+# Name: eiffel.py #
+# Purpose: Define Eiffel syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: eiffel.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Eiffel
+@todo: look into why io.anything is highlighted as a number
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _eiffel.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+EIFFEL_KW = (0, "alias all and any as bit boolean check class character clone "
+ "cluster create creation current debug deferred div do double "
+ "else elseif end ensure equal expanded export external false "
+ "feature forget from frozen general if implies indexing infix "
+ "inherit inspect integer invariant is language like local loop "
+ "mod name nochange none not obsolete old once or platform "
+ "pointer prefix precursor program real redefine rename require "
+ "rescue result retry root select separate string strip then "
+ "true undefine unique until variant void when xor")
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_EIFFEL_CHARACTER, 'char_style'),
+ (stc.STC_EIFFEL_COMMENTLINE, 'comment_style'),
+ (stc.STC_EIFFEL_DEFAULT, 'default_style'),
+ (stc.STC_EIFFEL_IDENTIFIER, 'default_style'),
+ (stc.STC_EIFFEL_NUMBER, 'number_style'),
+ (stc.STC_EIFFEL_OPERATOR, 'operator_style'),
+ (stc.STC_EIFFEL_STRING, 'string_style'),
+ (stc.STC_EIFFEL_STRINGEOL, 'stringeol_style'),
+ (stc.STC_EIFFEL_WORD, 'keyword_style')]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Eiffel"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_EIFFEL)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [EIFFEL_KW]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'--']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_erlang.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_erlang.py
new file mode 100644
index 0000000..ed00476
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_erlang.py
@@ -0,0 +1,105 @@
+###############################################################################
+# Name: erlang.py #
+# Purpose: Define Erlang syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: erlang.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for the Erlang Programming Language
+@todo: better styling
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _erlang.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+KEYWORDS = (0, "compile define else endif export file ifdef ifndef import "
+ "include include_lib module record undef author copyright doc "
+ "after begin case catch cond end fun if let of query receive "
+ "when define record export import include include_lib else "
+ "endif undef apply attribute call do in letrec module primop "
+ "try")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_ERLANG_ATOM, 'default_style'), # need new tag
+ (stc.STC_ERLANG_CHARACTER, 'char_style'),
+ (stc.STC_ERLANG_COMMENT, 'comment_style'),
+ (stc.STC_ERLANG_DEFAULT, 'default_style'),
+ (stc.STC_ERLANG_FUNCTION_NAME, 'funct_style'),
+ (stc.STC_ERLANG_KEYWORD, 'keyword_style'),
+ (stc.STC_ERLANG_MACRO, 'pre_style'),
+ (stc.STC_ERLANG_NODE_NAME, 'string_style'), # maybe change
+ (stc.STC_ERLANG_NUMBER, 'number_style'),
+ (stc.STC_ERLANG_OPERATOR, 'operator_style'),
+ (stc.STC_ERLANG_RECORD, 'keyword2_style'),
+ (stc.STC_ERLANG_STRING, 'string_style'),
+ (stc.STC_ERLANG_UNKNOWN, 'unknown_style'),
+ (stc.STC_ERLANG_VARIABLE, 'default_style')] # need custom?
+
+# Version specific
+if wx.VERSION >= (2, 9, 0, 0, ''):
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_ATOM_QUOTED, 'default_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_BIFS, 'default_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_COMMENT_DOC, 'dockey_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_COMMENT_DOC_MACRO, 'dockey_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_COMMENT_FUNCTION, 'comment_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_COMMENT_MODULE, 'comment_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_MACRO_QUOTED, 'default_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_MODULES, 'default_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_MODULES_ATT, 'default_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_NODE_NAME_QUOTED, 'default_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_PREPROC, 'pre_style')) # TODO
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_RECORD_QUOTED, 'default_style')) # TODO
+else:
+ SYNTAX_ITEMS.append((stc.STC_ERLANG_SEPARATOR, 'default_style')) # need style?
+
+#---- Extra Properties ----#
+FOLD = ('fold', '1')
+FOLD_CMT = ('fold.comments', '1')
+FOLD_KW = ('fold.keywords', '1')
+FOLD_BRACE = ('fold.braces', '1')
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Erlang"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_ERLANG)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'%%']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ferite.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ferite.py
new file mode 100644
index 0000000..c5fc033
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ferite.py
@@ -0,0 +1,68 @@
+###############################################################################
+# Name: ferite.py #
+# Purpose: Syntax Definitions for the Ferite Scripting Language #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+@summary: Lexer configuration module for Ferite Scripting Language
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _ferite.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _cpp
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+FERITE_KW = (0, "false null self super true abstract alias and arguments "
+ "attribute_missing break case class closure conformsToProtocol "
+ "constructor continue default deliver destructor diliver "
+ "directive do else extends eval final fix for function global "
+ "handle if iferr implements include instanceof isa "
+ "method_missing modifies monitor namespace new or private "
+ "protected protocol public raise recipient rename return "
+ "static switch uses using while")
+
+FERITE_TYPES = (1, "boolean string number array object void XML Unix Sys "
+ "String Stream Serialize RMI Posix Number Network Math "
+ "FileSystem Console Array Regexp XSLT")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Ferite"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _cpp.AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [FERITE_KW, FERITE_TYPES, _cpp.DOC_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return _cpp.SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [_cpp.FOLD,]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return ['//',]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_flagship.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_flagship.py
new file mode 100644
index 0000000..1473944
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_flagship.py
@@ -0,0 +1,182 @@
+###############################################################################
+# Name: flagship.py #
+# Purpose: Define Flagship syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: flagship.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for the Flagship programming language and
+ other XBase dialects.
+@todo: Custom style defs
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _flagship.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+FS_COMMANDS = (0, "? @ accept access all alternate announce ansi any append as "
+ "assign autolock average begin bell bitmap blank box call "
+ "cancel case century charset checkbox clear close cls color "
+ "combobox commit confirm console constant continue copy "
+ "count create cursor date dbread dbwrite decimals declare "
+ "default delete deleted delimiters device dir directory "
+ "display do draw edit else elseif eject end endcase enddo "
+ "endif endtext epoch erase error escape eval eventmask exact "
+ "exclusive extended external extra field file filter find "
+ "fixed font for form format from get gets global "
+ "global_extern go goto gotop guialign guicolor guicursor "
+ "guitransl html htmltext if image index input intensity join "
+ "key keyboard keytransl label lines list listbox local "
+ "locate margin memory memvar menu message method multibyte "
+ "multilocks next nfs nfslock nfs_force note on openerror "
+ "order outmode pack parameters path pixel pop printer "
+ "private prompt public push pushbutton quit radiobutton "
+ "radiogroup read recall refresh reindex relation release "
+ "rename replace report request restore richtext rowadapt "
+ "rowalign run save say scoreboard scrcompress screen seek "
+ "select sequence set setenhanced setstandard setunselected "
+ "skip softseek sort source static store struct structure sum "
+ "tag tbrowse text to total type typeahead unique unlock "
+ "update use wait while with wrap xml zap zerobyteout")
+
+FS_STDLIB = (1, "_displarr _displarrerr _displarrstd _displobj _displobjerr "
+ "_displobjstd aadd abs achoice aclone acopy adel adir "
+ "aelemtype aeval afields afill ains alert alias alltrim altd "
+ "ansi2oem appiomode appmdimode appobject array asc ascan asize "
+ "asort at atail atanychar autoxlock between bin2i bin2l bin2w "
+ "binand binlshift binor binrshift binxor bof break browse cdow "
+ "chr chr2screen cmonth col col2pixel color2rgb colorselect "
+ "colvisible consoleopen consolesize crc32 ctod curdir date "
+ "datevalid day dbappend dbclearfilter dbclearindex "
+ "dbclearrelation dbcloseall dbclosearea dbcommit dbcommitall "
+ "dbcreate dbcreateindex dbdelete dbedit dbeval dbf dbfilter "
+ "dbfinfo dbflock dbfused dbgetlocate dbgobottom dbgoto dbgotop "
+ "dbobject dbrecall dbreindex dbrelation dbrlock dbrlocklist "
+ "dbrselect dbrunlock dbseek dbselectarea dbsetdriver "
+ "dbsetfilter dbsetindex dbsetlocate dbsetorder dbsetrelation "
+ "dbskip dbstruct dbunlock dbunlockall dbusearea default "
+ "deleted descend devout devoutpict devpos directory diskspace "
+ "dispbegin dispbox dispcount dispend dispout doserror "
+ "doserror2str dow drawline dtoc dtos empty eof errorblock "
+ "errorlevel eval execname execpidnum exp fattrib fclose fcount "
+ "fcreate ferase ferror ferror2str fieldblock fielddeci "
+ "fieldget fieldgetarr fieldlen fieldname fieldpos fieldput "
+ "fieldputarr fieldtype fieldwblock file findexefile fklabel "
+ "fkmax flagship_dir flock flockf fopen found fread freadstdin "
+ "freadstr freadtxt frename fs_set fseek fwrite getactive "
+ "getalign getapplykey getdosetkey getenv getenvarr getfunction "
+ "getpostvalid getprevalid getreader guidrawline hardcr header "
+ "hex2num i2bin iif indexcheck indexcount indexdbf indexext "
+ "indexkey indexnames indexord infobox inkey inkey2read "
+ "inkey2str inkeytrap instdchar instdstring int int2num isalpha "
+ "isbegseq iscolor isdbexcl isdbflock isdbmultip isdbmultiple "
+ "isdbmultipleopen isdbrlock isdigit isfunction isguimode "
+ "islower isobjclass isobjequiv isobjproperty isprinter isupper "
+ "l2bin lastkey lastrec left len listbox lock log lower ltrim "
+ "lupdate macroeval macrosubst max max_col max_row maxcol "
+ "maxrow mcol mdblck mdiclose mdiopen mdiselect memocode "
+ "memodecode memoedit memoencode memoline memoread memory "
+ "memotran memowrit memvarblock mhide min minmax mlcount "
+ "mlctopos mleftdown mlpos mod month mpostolc mpresent "
+ "mreststate mrightdown mrow msavestate msetcursor msetpos "
+ "mshow mstate neterr netname nextkey num2hex num2int objclone "
+ "oem2ansi onkey ordbagext ordbagname ordcond ordcondset "
+ "ordcreate orddescend orddestroy ordfor ordisinique ordkey "
+ "ordkeyadd ordkeycount ordkeydel ordkeygoto ordkeyno ordkeyval "
+ "ordlistadd ordlistclear ordlistrebui ordname ordnumber "
+ "ordscope ordsetfocu ordsetrelat ordskipunique os outerr "
+ "outstd padc padl padr param parameters pcalls pcol pcount "
+ "pixel2col pixel2row printstatus procfile procline procname "
+ "procstack proper prow qout qout2 qqout qqout2 rat rddlist "
+ "rddname rddsetdefault readexit readinsert readkey readkill "
+ "readmodal readsave readupdated readvar reccount recno recsize "
+ "replicate restscreen right rlock rlockverify round row "
+ "row2pixel rowadapt rowvisible rtrim savescreen scrdos2unix "
+ "screen2chr scroll scrunix2dos seconds secondscpu select "
+ "serial set setansi setblink setcancel setcol2get setcolor "
+ "setcolorba setcursor setevent setguicursor setkey setmode "
+ "setpos setprc setvarempty sleep sleepms soundex space sqrt "
+ "statbarmsg statusmessage stod str strlen strlen2col "
+ "strlen2pix strlen2space strpeek strpoke strtran strzero stuff "
+ "substr tbcolumnnew tbmouse tbrowsearr tbrowsedb tbrowsenew "
+ "tempfilename time tone transform trim truepath type updated "
+ "upper used usersactive usersdbf usersmax val valtype version "
+ "webdate weberrorhandler webgetenvir webgetformdata "
+ "webhtmlbegin webhtmlend weblogerr webmaildomain weboutdata "
+ "websendmail word year")
+
+FS_FUNC = (2, "function procedure return exit")
+
+FS_CLASS = (3, "class instance export hidden protect prototype")
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_FS_ASM, ''),
+ (stc.STC_FS_BINNUMBER, 'number_style'),
+ (stc.STC_FS_COMMENT, 'comment_style'),
+ (stc.STC_FS_COMMENTDOC, 'dockey_style'),
+ (stc.STC_FS_COMMENTDOCKEYWORD, 'dockey_style'),
+ (stc.STC_FS_COMMENTDOCKEYWORDERROR, 'error_style'),
+ (stc.STC_FS_COMMENTLINE, 'comment_style'),
+ (stc.STC_FS_COMMENTLINEDOC, 'comment_style'),
+ (stc.STC_FS_CONSTANT, 'default_style'),
+ (stc.STC_FS_DATE, 'default_style'),
+ (stc.STC_FS_DEFAULT, 'default_style'),
+ (stc.STC_FS_ERROR, 'error_style'),
+ (stc.STC_FS_HEXNUMBER, 'number_style'),
+ (stc.STC_FS_IDENTIFIER, 'default_style'),
+ (stc.STC_FS_KEYWORD, 'keyword_style'),
+ (stc.STC_FS_KEYWORD2, 'keyword2_style'),
+ (stc.STC_FS_KEYWORD3, 'keyword3_style'),
+ (stc.STC_FS_KEYWORD4, 'keyword4_style'),
+ (stc.STC_FS_LABEL, 'default_style'),
+ (stc.STC_FS_NUMBER, 'number_style'),
+ (stc.STC_FS_OPERATOR, 'operator_style'),
+ (stc.STC_FS_PREPROCESSOR, 'pre_style'),
+ (stc.STC_FS_STRING, 'string_style'),
+ (stc.STC_FS_STRINGEOL, 'stringeol_style')]
+
+#---- Extra Properties ----#
+FOLD = ('fold', '1')
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Flagship"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_FLAGSHIP)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [FS_COMMANDS, FS_STDLIB, FS_FUNC, FS_CLASS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'//']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_forth.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_forth.py
new file mode 100644
index 0000000..e83b822
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_forth.py
@@ -0,0 +1,121 @@
+###############################################################################
+# Name: forht.py #
+# Purpose: Define Forth syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: _forth.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Forth
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _forth.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+
+# Control Keywords
+CONTROL_KW = (0, "again begin case do else endcase endof if loop of "
+ "repeat then until while [if] [else] [then] ?do")
+
+# Keywords
+KEYWORDS = (1, "dup drop rot swap over @ ! 2@ 2! 2dup 2drop 2swap 2over nip "
+ "r@ >r r&gt; 2r@ 2>r 2r>; 0= 0<; sp@ sp! w@ w! c@ c! < > = "
+ "<> 0<> space spaces key? key throw catch abort */ 2* /mod "
+ "cell+ cells char+ chars move erase dabs title hex decimal "
+ "hold <# # #s #> sign d. . u. dump (.\") >number ' immediate "
+ "exit recurse unloop leave here allot , c, w, compile, branch, "
+ "ret, lit, dlit, ?branch, \", >mark >resolve1 <mark >resolve "
+ "align aligned user-allot user-here header does> smudge hide "
+ ":noname last-word ?error error2 find1 sfind set-current "
+ "get-current definitions get-order forth only set-order also "
+ "previous voc-name. order latest literal 2literal sliteral "
+ "cliteral ?literal1 ?sliteral1 hex-literal hex-sliteral "
+ "?literal2 ?sliteral2 source EndOfChunk CharAddr PeekChar "
+ "IsDelimiter GetChar OnDelimiter SkipDelimiters OnNotDelimiter "
+ "SkipWord SkipUpTo ParseWord NextWord parse skip "
+ "console-handles refill depth ?stack ?comp word interpret bye "
+ "quit main1 evaluate include-file included >body +word "
+ "wordlist class! class@ par! par@ id. ?immediate ?voc "
+ "immediate VOC WordByAddrWl WordByAddr nlist words save options "
+ "/notransl ansi>oem accept emit cr type ekey? ekey ekey>char "
+ "externtask erase-imports ModuleName ModuleDirName environment? "
+ "drop-exc-handler set-exc-handler halt err close-file "
+ "create-file create-file-shared open-file-shared delete-file "
+ "file-position file-size open-file read-file reposition-file "
+ "dos-lines unix-lines read-line write-file resize-file "
+ "write-line allocate free resize start suspend resume stop "
+ "pause min max true false asciiz> r/o w/o ;class endwith or and "
+ "/string search compare export ;module space")
+
+# Definition Keywords
+DEFINITION_KW = (2, "variable create : value constant vm: m: var dvar chars "
+ "obj constr: destr: class: object: pointer user "
+ "user-create user-value vect wndproc: vocabulary -- task: "
+ "cez: module:")
+
+# Prewords with one argument
+PREWORDS1 = (3, "CHAR [CHAR] POSTPONE WITH ['] TO [COMPILE] CHAR ASCII \\'")
+
+# Prewords with two arguments
+PREWORDS2 = (4, "REQUIRE WINAPI:")
+
+# String definition Keywords
+STRING_DEF_KW = (5, "S\" ABORT\" Z\" \" .\" C\"")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_FORTH_DEFAULT, "default_style"),
+ (stc.STC_FORTH_COMMENT, "comment_style"),
+ (stc.STC_FORTH_COMMENT_ML, "comment_style"),
+# ("STC_FORTH_CONTROL", ""),
+# ("STC_FORTH_DEFWORD", ""),
+# ("STC_FORTH_IDENTIFIER", ""),
+ (stc.STC_FORTH_KEYWORD, "keyword_style"),
+# ("STC_FORTH_LOCALE", ""),
+ (stc.STC_FORTH_NUMBER, "number_style"),
+ (stc.STC_FORTH_PREWORD1, "keyword2_style"),
+ (stc.STC_FORTH_PREWORD2, "keyword3_style"),
+ (stc.STC_FORTH_STRING, "string_style")]
+
+
+#---- Extra Properties ----#
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Forth"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_FORTH)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [CONTROL_KW, KEYWORDS, DEFINITION_KW,
+ PREWORDS1, PREWORDS2, STRING_DEF_KW]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'\\ ']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_fortran.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_fortran.py
new file mode 100644
index 0000000..8315cab
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_fortran.py
@@ -0,0 +1,197 @@
+###############################################################################
+# Name: fortran.py #
+# Purpose: Define Fortran 77/95 syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: fortran.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Fortran f77 and f95
+@todo: check keywords more throughly
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _fortran.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+import re
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+# Fortran F77 and F95 keywords
+FORT_KEYWORDS = (0, "access action advance allocatable allocate apostrophe "
+ "assign assignment associate asynchronous backspace bind "
+ "blank blockdata call case character class close common "
+ "complex contains continue cycle data deallocate decimal "
+ "delim default dimension direct do dowhile double "
+ "doubleprecision else elseif elsewhere encoding end "
+ "endassociate endblockdata enddo endfile endforall "
+ "endfunction endif endinterface endmodule endprogram "
+ "endselect endsubroutine endtype endwhere entry eor "
+ "equivalence err errmsg exist exit external file flush fmt "
+ "forall form format formatted function go goto id if "
+ "implicit in include inout integer inquire intent "
+ "interface intrinsic iomsg iolength iostat kind len "
+ "logical module name named namelist nextrec nml none "
+ "nullify number only open opened operator optional out "
+ "pad parameter pass pause pending pointer pos position "
+ "precision print private program protected public quote "
+ "read readwrite real rec recl recursive result return "
+ "rewind save select selectcase selecttype sequential sign "
+ "size stat status stop stream subroutine target then to "
+ "type unformatted unit use value volatile wait where while "
+ "write")
+
+# Fortran Functions
+FORT_FUNC = (1, "abs achar acos acosd adjustl adjustr aimag aimax0 aimin0 aint "
+ "ajmax0 ajmin0 akmax0 akmin0 all allocated alog alog10 amax0 "
+ "amax1 amin0 amin1 amod anint any asin asind associated atan "
+ "atan2 atan2d atand bitest bitl bitlr bitrl bjtest bit_size "
+ "bktest break btest cabs ccos cdabs cdcos cdexp cdlog cdsin "
+ "cdsqrt ceiling cexp char clog cmplx conjg cos cosd cosh count "
+ "cpu_time cshift csin csqrt dabs dacos dacosd dasin dasind "
+ "datan datan2 datan2d datand date date_and_time dble dcmplx "
+ "dconjg dcos dcosd dcosh dcotan ddim dexp dfloat dflotk dfloti "
+ "dflotj digits dim dimag dint dlog dlog10 dmax1 dmin1 dmod "
+ "dnint dot_product dprod dreal dsign dsin dsind dsinh dsqrt "
+ "dtan dtand dtanh eoshift epsilon errsns exp exponent float "
+ "floati floatj floatk floor fraction free huge iabs iachar "
+ "iand ibclr ibits ibset ichar idate idim idint idnint ieor "
+ "ifix iiabs iiand iibclr iibits iibset iidim iidint iidnnt "
+ "iieor iifix iint iior iiqint iiqnnt iishft iishftc iisign "
+ "ilen imax0 imax1 imin0 imin1 imod index inint inot int int1 "
+ "int2 int4 int8 iqint iqnint ior ishft ishftc isign isnan "
+ "izext jiand jibclr jibits jibset jidim jidint jidnnt jieor "
+ "jifix jint jior jiqint jiqnnt jishft jishftc jisign jmax0 "
+ "jmax1 jmin0 jmin1 jmod jnint jnot jzext kiabs kiand kibclr "
+ "kibits kibset kidim kidint kidnnt kieor kifix kind kint kior "
+ "kishft kishftc kisign kmax0 kmax1 kmin0 kmin1 kmod knint knot "
+ "kzext lbound leadz len len_trim lenlge lge lgt lle llt log "
+ "log10 logical lshift malloc matmul max max0 max1 maxexponent "
+ "maxloc maxval merge min min0 min1 minexponent minloc minval "
+ "mod modulo mvbits nearest nint not nworkers "
+ "number_of_processors pack popcnt poppar precision present "
+ "product radix random random_number random_seed range real "
+ "repeat reshape rrspacing rshift scale scan secnds "
+ "selected_int_kind selected_real_kind set_exponent shape sign "
+ "sin sind sinh size sizeof sngl snglq spacing spread sqrt sum "
+ "system_clock tan tand tanh tiny transfer transpose trim "
+ "ubound unpack verify")
+
+# Fortran extended functions
+FORT_EXT = (2, "cdabs cdcos cdexp cdlog cdsin cdsqrt cotan cotand dcmplx "
+ "dconjg dcotan dcotand decode dimag dll_export dll_import "
+ "doublecomplex dreal dvchk encode find flen flush getarg "
+ "getcharqq getcl getdat getenv gettim hfix ibchng identifier "
+ "imag int1 int2 int4 intc intrup invalop iostat_msg isha ishc "
+ "ishl jfix lacfar locking locnear map nargs nbreak ndperr "
+ "ndpexc offset ovefl peekcharqq precfill prompt qabs qacos "
+ "qacosd qasin qasind qatan qatand qatan2 qcmplx qconjg qcos "
+ "qcosd qcosh qdim qexp qext qextd qfloat qimag qlog qlog10 "
+ "qmax1 qmin1 qmod qreal qsign qsin qsind qsinh qsqrt qtan qtand "
+ "qtanh ran rand randu rewrite segment setdat settim system "
+ "timer undfl unlock union val virtual volatile zabs zcos zexp "
+ "zlog zsin zsqrt")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_F_COMMENT, 'comment_style'),
+ (stc.STC_F_CONTINUATION, 'default_style'), # NEED STYLE
+ (stc.STC_F_DEFAULT, 'default_style'),
+ (stc.STC_F_IDENTIFIER, 'default_style'),
+ (stc.STC_F_LABEL, 'number2_style'), # NEED STYLE
+ (stc.STC_F_NUMBER, 'number_style'),
+ (stc.STC_F_OPERATOR, 'operator_style'),
+ (stc.STC_F_OPERATOR2, 'operator_style'), # NEED STYLE
+ (stc.STC_F_PREPROCESSOR, 'pre_style'),
+ (stc.STC_F_STRING1, 'string_style'),
+ (stc.STC_F_STRING2, 'string_style'),
+ (stc.STC_F_STRINGEOL, 'stringeol_style'),
+ (stc.STC_F_WORD, 'keyword_style'),
+ (stc.STC_F_WORD2, 'keyword3_style'),
+ (stc.STC_F_WORD3, 'funct_style')]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_COMP = ("fold.compact", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Fortran 77/95"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ if self.LangId == synglob.ID_LANG_F77:
+ self.SetLexer(stc.STC_LEX_F77)
+ else:
+ self.SetLexer(stc.STC_LEX_FORTRAN)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [FORT_KEYWORDS, FORT_FUNC , FORT_EXT]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FOLD_COMP]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ if self.LangId == synglob.ID_LANG_F77:
+ return ['*']
+ elif self.LangId == synglob.ID_LANG_F95:
+ return ['!']
+ else:
+ return list()
+
+#---- End Required Module Functions ----#
+
+def AutoIndenter(estc, pos, ichar):
+ """Auto indent cpp code.
+ @param estc: EditraStyledTextCtrl
+ @param pos: current carat position
+ @param ichar: Indentation character
+
+ """
+ rtxt = u''
+ line = estc.GetCurrentLine()
+ text = estc.GetTextRange(estc.PositionFromLine(line), pos)
+ eolch = estc.GetEOLChar()
+
+ indent = estc.GetLineIndentation(line)
+ if ichar == u"\t":
+ tabw = estc.GetTabWidth()
+ else:
+ tabw = estc.GetIndent()
+
+ i_space = indent / tabw
+ ndent = eolch + ichar * i_space
+ rtxt = ndent + ((indent - (tabw * i_space)) * u' ')
+
+ blks = '(program|function|subroutine|if|do|while)'
+ blk_pat = re.compile(blks + '\s*[(a-zA-Z][a-zA-Z0-9]*', re.IGNORECASE)
+ text = text.strip()
+ if text.endswith('{') or blk_pat.match(text) or text == 'else':
+ rtxt += ichar
+
+ # Put text in the buffer
+ estc.AddText(rtxt)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_glsl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_glsl.py
new file mode 100644
index 0000000..aa9a0a3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_glsl.py
@@ -0,0 +1,66 @@
+###############################################################################
+# Name: glsl.py #
+# Purpose: Define C/CPP/ObjC/Vala syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: glsl.py
+@author: Cody Precord
+@summary: Lexer configuration file for GLSL source files.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id$"
+__revision__ = "$Revision$"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+import re
+
+# Local imports
+import synglob
+import syndata
+
+import _cpp
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# C Keywords
+GLSL_KEYWORDS = (0, "attribute uniform varying const layout centroid varying flat "
+ "smooth noperspective patch sample break continue do for while "
+ "switch case default if else subroutine in out inout true false "
+ "invariant discard return lowp mediump highp precision")
+
+# C Types/Structures/Storage Classes
+GLSL_TYPES = (1, "mat2 mat3 float double int void bool mat4 dmat2 dmat3 dmat4 mat2x2 "
+ "mat2x3 mat2x4 dmat2x2 dmat2x3 dmat2x4 mat3x2 mat3x3 mat3x4 dmat3x2 "
+ "dmat3x3 dmat3x4 mat4x2 mat4x3 mat4x4 dmat4x2 dmat4x3 dmat4x4 vec2 "
+ "vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 dvec2 dvec3 dvec4 uint "
+ "uvec2 uvec3 uvec4 sampler1D sampler2D sampler3D samplerCube "
+ "sampler1DShadow sampler2DShadow samplerCubeShadow sampler1DArray "
+ "sampler2DArray sampler1DArrayShadow sampler2DArrayShadow isampler1D "
+ "isampler2D isampler3D isamplerCube isampler1DArray isampler2DArray "
+ "usampler1D usampler2D usampler3D usamplerCube usampler1DArray "
+ "usampler2DArray sampler2DRect sampler2DRectShadow isampler2DRect "
+ "usampler2DRect samplerBuffer isamplerBuffer usamplerBuffer sampler2DMS "
+ "isampler2DMS usampler2DMS sampler2DMSArray isampler2DMSArray "
+ "usampler2DMSArray samplerCubeArray samplerCubeArrayShadow "
+ "isamplerCubeArray usamplerCubeArray struct")
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(_cpp.SyntaxData):
+ """SyntaxData object for many C like languages"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List"""
+ return [GLSL_KEYWORDS, GLSL_TYPES, _cpp.DOC_KEYWORDS]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_groovy.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_groovy.py
new file mode 100644
index 0000000..1ab9cc4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_groovy.py
@@ -0,0 +1,117 @@
+###############################################################################
+# Name: groovy.py #
+# Purpose: Define Groovy syntax for highlighting and other features #
+# Author: Omar Gomez <omar.gomez@gmail.com> #
+# Copyright: (c) 2009 Omar Gomez <omar.gomez@gmail.com> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: groovy.py
+AUTHOR: Omar Gomez
+@summary: Lexer configuration module for Groovy (based on the Java one).
+
+"""
+
+__author__ = "Omar Gomez <omar.gomez@gmail.com>"
+__svnid__ = "$Id: _groovy.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+from _cpp import AutoIndenter
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+MAIN_KEYWORDS = (0,
+"""
+as assert Boolean Byte Character Class Double Float Integer Long Number Object
+Short String property void abstract assert boolean break byte case catch char
+class const continue default do double else extends false final finally float
+for goto if implements import instanceof in int interface long native new null
+package private protected public return short static strictfp super switch
+synchronized this throw throws transient true try void volatile while def
+"""
+)
+
+SECONDARY_KEYWORDS= (1,
+"""
+abs accept allProperties and any append asImmutable asSynchronized asWritable
+center collect compareTo contains count decodeBase64 div dump each eachByte
+eachFile eachFileRecurse eachLine eachMatch eachProperty eachPropertyName
+eachWithIndex encodeBase64 every execute filterLine find findAll findIndexOf
+flatten getErr getIn getOut getText inject inspect intersect intdiv invokeMethod
+isCase join leftShift max min minus mod multiply negate newInputStream
+newOutputStream newPrintWriter newReader newWriter next or padLeft padRight
+plus pop previous print println readBytes readLine readLines reverse
+reverseEach rightShift rightShiftUnsigned round size sort splitEachLine step
+subMap times toDouble toFloat toInteger tokenize toList toLong toURL
+transformChar transformLine upto use waitForOrKill withInputStream
+withOutputStream withPrintWriter withReader withStream withStreams withWriter
+withWriterAppend write writeLine
+"""
+)
+
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'),
+ (stc.STC_C_COMMENT, 'comment_style'),
+ (stc.STC_C_COMMENTDOC, 'comment_style'),
+ (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'),
+ (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTLINEDOC, 'comment_style'),
+ (stc.STC_C_CHARACTER, 'char_style'),
+ (stc.STC_C_GLOBALCLASS, 'global_style'),
+ (stc.STC_C_IDENTIFIER, 'default_style'),
+ (stc.STC_C_NUMBER, 'number_style'),
+ (stc.STC_C_OPERATOR, 'operator_style'),
+ (stc.STC_C_PREPROCESSOR, 'pre_style'),
+ (stc.STC_C_REGEX, 'pre_style'),
+ (stc.STC_C_STRING, 'string_style'),
+ (stc.STC_C_STRINGEOL, 'stringeol_style'),
+ (stc.STC_C_UUID, 'pre_style'),
+ (stc.STC_C_VERBATIM, 'number2_style'),
+ (stc.STC_C_WORD, 'keyword_style'),
+ (stc.STC_C_WORD2, 'keyword2_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_PRE = ("styling.within.preprocessor", "0")
+FOLD_COM = ("fold.comment", "1")
+FOLD_COMP = ("fold.compact", "1")
+FOLD_ELSE = ("fold.at.else", "0")
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Groovy"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [MAIN_KEYWORDS, SECONDARY_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FOLD_PRE]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [ u'//' ]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_gui4cli.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_gui4cli.py
new file mode 100644
index 0000000..715738f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_gui4cli.py
@@ -0,0 +1,148 @@
+###############################################################################
+# Name: gui4cli.py #
+# Purpose: Syntax configuration for the Gui4Cli programming language #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: gui4cli.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Gui4Cli
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _gui4cli.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+GLOBALS = (0, "3STATE #ANSI #FIXANSI #FIXOEM #FIXSYS #GUI #SEPARATOR #SYS ABRI "
+ "ACTIVE ALL ALTSTART APPDATA APPWIN ARRANGE ARROW ASCEND AUTO "
+ "BACK BC BITBUCKET BL BOLD BORDER BOTTOM BR BUFFERS BUSY BUTTON "
+ "BUTTONS CAPTION CENTER CHAR CHECK CHILD CLEAN CLEAR CLOSED "
+ "COLOR COMM COMMON.ALTSTART COMMON.DESKTOP COMMON.FAVORITES "
+ "COMMON.MENU COMMON.PROGRAMS COMMON.STARTUP COOKIES CROSS CURDIR "
+ "CURRENT CURSOR DATA DATE DAY DECORATIVE DEF1 DEF2 DEF3 DEF4 "
+ "DESCEND DESKTOP DIALOG DIR DISABLE DISABLED DISK DISKS DLBEGIN "
+ "DLCOMPLETE DLGFRAME DOUBLE DRAG DROP DROPLIST DTTM EDIT EDITOR "
+ "EFFECTS ELLIPSE EMBOSS END ENABLE ENDGUI ENGLISH ENTER ERROR "
+ "EXISTS EXPLORE EXT FAIL FAVORITES FIELDS FILE FILES FIND FIRST "
+ "FIXED FIXWIDTH FLAT FNUMBER FOCUS FOREGROUND FORMAT FORWARD "
+ "FREE FRONT FULL FULLPATH GCDIR GCEXE GCNAME GREEK GRID GUIPATH "
+ "HEAVY HEIGHT HELP HEX HIDDEN HIDE HIST HISTORY HOME HORIZONTAL "
+ "HOT HOUR IBEAM ICLEFT INDEX INFO INT INVOKE ITALIC ITEM JULIAN "
+ "JUSTIFY LARGE LAST LB LBLEFT LC LENGTH LIGHT LINE LINES LMB "
+ "LMDC LOAD LOADED LOWER LT MAX MAXI MAXBOX MAXIMIZE MEDIUM MENU "
+ "MINBOX MINI MINIMIZE MINUTE MMB MODERN MONTH MOVE MSEC MULTI "
+ "NAME NAVCOMPLETE NETCACHE NETHOOD NEW NEWMENU NEXT NO NOADJUST "
+ "NOBORDER NOERROR NOEXT NOFACE NOFILES NOFOCUS NOFOLDERS NONE "
+ "NOOPEN NOREFRESH NORESET NORMAL NORTH NOSIZE NOVECTOR NOVRT NOW "
+ "NOWRAP NUMBER OCTAL OFF OK OKCANCEL ON ONECLICK ONELINE OPEN "
+ "OVERLAP OWNED PARENT PATH PCPATH PERIOD PERSONAL POLYGON PREFS "
+ "PREV PREVIOUS PRINT PRINTERS PROGRAMS PROP PROPERTY PULSE "
+ "QUESTION QUOTE RAGGED RAISED RB RC REC RECENT REFRESH REMOVE "
+ "REMSIZE RENAME REPORT RESIZE RET RETRY RIGHT RMB ROMAN ROOT "
+ "ROUNDED ROUTINE ROWS RT SAVE SCALABLE SCREEN SCRIPT SCROLL "
+ "SEARCH SECOND SELECT SELECTED SELSCRIPT SENDTO SENSITIVE "
+ "SENTENCE SHELL SHOW SILENT SIMPLE SINGLE SIZE SMALL SMOOTH "
+ "SOLID SORT START STARTGUI STARTUP STAT0 STATIC STATUS STD STOP "
+ "STRECH STRIKE SUBCHILD SUBSUB SUNK SUNKEN SWISS SYSMENU TAB "
+ "TABS TC TEMPLATES TEXT THIN TIME TITLE TL TOGGLE TOOL TOP "
+ "TOPMOST TOTAL TR TRANS TRANSPARENT TTONLY TYPE UNDERLINE "
+ "UNFORMAT UNJULIAN UNQUOTE UNSELECT UNSELECTED UPPER USER VALID "
+ "VARIABLE VCENTER VERSION VERTICAL VIEW WAIT WARN WHEEL WIDTH "
+ "WINEDGE WORD YEAR YES YESNO YESTOALL YNCANCEL")
+
+EVENTS = (1, "XAREA XBROWSER XBUTTON XCHECKBOX XCOMBO XEDBOX XGROUPBOX XICON "
+ "XIMAGE XLISTVIEW XMENU XPAN XPROGRESS XRADIO XREBAR XSPLITER "
+ "XSTATUS XTAB XTEXTBOX XTEXTIN XTOOLBAR XTRACKBAR XTREEVIEW "
+ "XUPDOWN XAFTER XATTR XBEFORE XENUM XHOTKEY XNOTIFY XONACTIVE "
+ "XONBROWSER XONCLICK XONCLOSE XONDOUBLECLICK XONDROP XONFAIL "
+ "XONHELP XONINACTIVE XONKEY XONLMB XONLOAD XONLVCLICK XONLVDIR "
+ "XONMARK XONMMB XONOPEN XONQUIT XONRELOAD XONRETURN XONRMB "
+ "XONTEXTIN XONWHEELDOWN XONWHEELUP XPIPE XREQFILE XROUTINE "
+ "XTBARICON XTIMER XONKEY")
+
+ATTRIBUTES = (2, "ATTR BACKGROUND BUDDY BUFFERS COLORS COLSAVE DATA DBGSTEP DBGVARS "
+ "DEBUG DEEPTRANS EDITOR ENDGUI ESCAPE FAIL FILTER FONT FRAME "
+ "GRID HELP ICON ID IXICON KEY LIKE LOCAL LVCOLUMN MAXDATE "
+ "MAXSIZE MAXTRANS MCINOTIFY MCISIGNAL MENU MINDATE MINSIZE "
+ "NEXT OUTPUT PAGE PARENT PATH PREFS RBSTYLE RESIZE SAY SHAPE "
+ "SHOW STARTGUI STYLE TAB TITLE TRANSLATE VARIABLES")
+
+CONTROL = (3, "AND ANDIFEXISTS BREAK CALL CASE DOCASE ELSE ELSEIF ELSEIFEXISTS "
+ "ENDCASE ENDFOR ENDIF ENDWHILE FOR GO GOSUB GOTO IF IFEXISTS "
+ "LABEL OR ORIFEXISTS QUIT RETURN STOP WHILE")
+
+COMMANDS = (4, "ADD ADDRESS ADDUNIQUE APPEND APPVAR ASSIGN AUTO BRANCH BROWSER "
+ "CD CLOSE COMBO COMMAND COPY CREATE CREATELINK CUT CUTVAR DBSUM "
+ "DCKDEBUG DDEXEC DDPUT DDUSE DEC DEL DELAY DELETE DELVAR EDBOX "
+ "EMPTYBIN ENUM EXIT EXTRACT FLASH FREEFONT FREEICON GETCLIP "
+ "GETCOLOR GETFONT GOSUB GUI GUICLOSE GUILOAD GUIOPEN GUIQUIT "
+ "GUIRENAME GUIWINDOW HTMLHELP IMAGE INC JOINFILE LAUNCH "
+ "LISTVIEW LOADFONT LOADICON LV LVACTION LVCLIP LVREP LVSEARCH "
+ "LVSWITCH MAKEDIR MCI MOVE MSGBOX NEWFILE PARSEVAR POPMENU "
+ "QUICKMENU QUIT RANDOM REGCREATE REGDELETE REGGET REGSET RENAME "
+ "REPVAR REQFILE RUN SAY SEARCHVAR SEND SET SETATTR SETCLIP "
+ "SETEVENT SETGADVALUES SETICON SETPOINTER SETVAR SETWINATTR "
+ "SETWINTITLE SHELL STATUS SYSTEM TERMINATEPROC TEXTFILE "
+ "TREEVIEW TV UPDATE UPDOWN USE WAIT WINATTR WINDOW")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_GC_ATTRIBUTE, 'keyword3_style'),
+ (stc.STC_GC_COMMAND, 'keyword2_style'),
+ (stc.STC_GC_COMMENTBLOCK, 'comment_style'),
+ (stc.STC_GC_COMMENTLINE, 'comment_style'),
+ (stc.STC_GC_CONTROL, 'keyword_style'),
+ (stc.STC_GC_DEFAULT, 'default_style'),
+ (stc.STC_GC_EVENT, 'keyword4_style'),
+ (stc.STC_GC_GLOBAL, 'global_style'),
+ (stc.STC_GC_OPERATOR, 'operator_style'),
+ (stc.STC_GC_STRING, 'string_style')]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_COMP = ("fold.compact", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Gui4Cli"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_GUI4CLI)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [GLOBALS, EVENTS, ATTRIBUTES, CONTROL, COMMANDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set
+ @note: gui4cli supports folding but it seems to be partially broken
+
+ """
+ return list() #[FOLD, FOLD_COMP]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'//']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haskell.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haskell.py
new file mode 100644
index 0000000..7ce487a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haskell.py
@@ -0,0 +1,84 @@
+###############################################################################
+# Name: haskell.py #
+# Purpose: Define Haskell syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+ FILE: haskell.py
+ AUTHOR: Cody Precord
+ @summary: Lexer configuration module for the Haskell Programming Language
+ @todo: More custom highlighting
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _haskell.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+HA_KEYWORDS = (0, "as case class data default deriving do forall foreign "
+ "hiding if import in infix infixl infixr instance else let "
+ "mdo module newtype of qualified then type where")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_HA_CAPITAL, 'default_style'),
+ (stc.STC_HA_CHARACTER, 'char_style'),
+ (stc.STC_HA_CLASS, 'class_style'),
+ (stc.STC_HA_COMMENTBLOCK, 'comment_style'),
+ (stc.STC_HA_COMMENTBLOCK2, 'comment_style'),
+ (stc.STC_HA_COMMENTBLOCK3, 'comment_style'),
+ (stc.STC_HA_COMMENTLINE, 'comment_style'),
+ (stc.STC_HA_DATA, 'default_style'),
+ (stc.STC_HA_DEFAULT, 'default_style'),
+ (stc.STC_HA_IDENTIFIER, 'default_style'),
+ (stc.STC_HA_IMPORT, 'default_style'), # possibly use custom style
+ (stc.STC_HA_INSTANCE, 'default_style'),
+ (stc.STC_HA_KEYWORD, 'keyword_style'),
+ (stc.STC_HA_MODULE, 'default_style'),
+ (stc.STC_HA_NUMBER, 'number_style'),
+ (stc.STC_HA_OPERATOR, 'operator_style'),
+ (stc.STC_HA_STRING, 'string_style')]
+
+#---- Extra Properties ----#
+FOLD = ('fold', '1')
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Haskell"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_HASKELL)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [HA_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'--']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haxe.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haxe.py
new file mode 100644
index 0000000..c9f46a0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haxe.py
@@ -0,0 +1,65 @@
+###############################################################################
+# Name: haxe.py #
+# Purpose: Syntax Definitions for haXe web language #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+@summary: Lexer configuration module for haXe web programming language
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _haxe.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _cpp
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+HAXE_KW = (0, "abstract break case catch class const continue trace do else "
+ "enum extends finally for function goto if implements import in "
+ "instanceof int interface new package private public return "
+ "static super switch this throw throws transient try typeof var "
+ "void volatile while with" )
+
+HAXE_TYPES = (1, "Bool Enum false Float Int null String true Void ")
+
+#---- End Keyword Definitions ----#
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for HaXe"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _cpp.AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [HAXE_KW, HAXE_TYPES, _cpp.DOC_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return _cpp.SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [_cpp.FOLD,]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return ['//']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_html.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_html.py
new file mode 100644
index 0000000..a4b7399
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_html.py
@@ -0,0 +1,297 @@
+###############################################################################
+# Name: html.py #
+# Purpose: Define HTML syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: html.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for HTML/DHTML/SGML.
+@todo: Add Netscape/Microsoft Tag Extenstions (maybe)
+@todo: Styleing needs lots of tweaking
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _html.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _javascript
+import _vbscript
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# HTML Tags (HTML4)
+HTML_TAGS = (0, "address applet area a base basefont big blockquote br caption "
+ "center cite code dd dfn dir div dl dt font form hr html img "
+ "input isindex kbd li link map menu meta ol option param pre p "
+ "samp span select small strike sub sup table td textarea th tr "
+ "script noscript tt ul var xmp b i u h1 h2 h3 h4 h5 h6 em "
+ "strong head body title "
+ # HTML 4.0 Tags
+ "abbr acronym bdo button col label colgroup del fieldset "
+ "iframe ins legend object optgroup q s tbody tfoot thead "
+ # HTML 5 Tags
+ "article aside audio canvas command datalist details dialog "
+ "embed figcaption figure footer header hgroup keygen mark "
+ "meter nav output progress rp rt ruby section source time "
+ "video "
+ # Tag Attributes / Arguments
+ "action align alink alt archive background bgcolor border "
+ "bordercolor cellpadding cellspacing checked class clear "
+ "codebase color cols colspan content coords enctype face "
+ "gutter height hspace id link lowsrc marginheight marginwidth "
+ "maxlength method name prompt rel rev rows rowspan scrolling "
+ "selected shape size src start target text type url usemap "
+ "ismap valign value vlink vspace width wrap href http-equiv "
+ # HTML 4 Tag Attributes /Arguments
+ "accept accesskey axis char charoff charset cite classid "
+ "codetype compact data datetime declare defer dir disabled for "
+ "frame headers hreflang lang language longdesc multiple nohref "
+ "nowrap profile readonly rules scheme scope standby style "
+ "summary tabindex valuetype version "
+ # HTML 5 Tag Attributes / Arguments
+ "async autocomplete contenteditable contextmenu date "
+ "datetime-local draggable email formaction formenctype "
+ "formmethod formnovalidate formtarget hidden list manifest max "
+ "media min month novalidate number pattern ping range required "
+ "reversed role sandbox scoped seamless search sizes spellcheck "
+ "srcdoc step tel week "
+ # DHTML Support
+ "dtml-var dtml-if dtml-unless dtml-in dtml-with dtml-let "
+ "dtml-call dtml-raise dtml-try dtml-comment dtml-tree")
+
+#---- Extra defs ----#
+# ColdFusion Tags
+CF_TAGS = ("cfabort cfapplet cfapplication cfargument cfassociate cfbreak "
+ "cfcache cfcalendar cfcase cfcatch cfchart cfchartdata "
+ "cfchartseries cfcol cfcollection cfcomponent cfcontent cfcookie "
+ "cfdefaultcase cfdirectory cfdocument cfdocumentitem "
+ "cfdocumentsection cfdump cfelse cfelseif cferror cfexecute cfexit "
+ "cffile cfflush cfform cfformgroup cfformitem cfftp cffunction "
+ "cfgrid cfgridcolumn cfgridrow cfgridupdate cfheader cfhtmlhead "
+ "cfhttp cfhttpparam cfif cfimport cfinclude cfindex cfinput "
+ "cfinsert cfinvoke cfinvokeargument cfldap cflocation cflock cflog "
+ "cflogin cfloginuser cflogout cfloop cfmail cfmailparam cfmailpart "
+ "cfmodule cfNTauthenticate cfobject cfobjectcache cfoutput cfparam "
+ "cfpop cfprocessingdirective cfprocparam cfprocresult cfproperty "
+ "cfquery cfqueryparam cfregistry cfreport cfreportparam cfrethrow "
+ "cfreturn cfsavecontent cfschedule cfscript cfsearch cfselect cfset "
+ "cfsetting cfsilent cfslider cfstoredproc cfswitch cftable "
+ "cftextarea cfthrow cftimer cftrace cftransaction cftree cftreeitem "
+ "cftry cfupdate cfwddx cfxml")
+
+# JavaScript Keywords (see javascript.py)
+JS_KEYWORDS = (1, _javascript.KeywordString(synglob.ID_LANG_JS))
+
+# VBScript Keywords (currently unsupported)
+VBS_KEYWORDS = (2, _vbscript.VBS_KW)
+
+# Python Keywords (see python.py)
+PY_KEYWORDS = (3, "")
+
+# PHP Keywords (see php.py)
+# This module is loaded for files with a .html/htm extension so it is assumed
+# that there is no php in the file. On the other hand the php module loads
+# this module so that it can support embedded html. This behavior may be changed
+# in the future
+
+# XML Keywords (see xml.py)
+# XML files are handled independantly from html although there is support for
+# embedded xml highlighting it is currently not being used.
+
+# SGML Keywords
+SGML_KEYWORDS = (5, "ELEMENT DOCTYPE ATTLIST ENTITY NOTATION")
+#SGML_KEYWORDS = (5, "#CURRENT #IMPLIED #REQUIRED ATTLIST CDATA DOCTYPE "
+# "ELEMENT ENTITY HTML IDREF INCLUDE IGNORE NMTOKEN NUMBER "
+# "RCDATA TEMP")
+
+# SGML Block Keywords
+SGML_BLOCK = (7, "")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_H_DEFAULT, 'default_style'),
+ (stc.STC_H_ASP, 'array_style'),
+ (stc.STC_H_ASPAT, 'array_style'),
+ (stc.STC_H_ATTRIBUTE, 'keyword2_style'),
+ (stc.STC_H_ATTRIBUTEUNKNOWN, 'error_style'),
+ (stc.STC_H_CDATA, 'default_style'), # Style ME
+ (stc.STC_H_COMMENT, 'comment_style'),
+ (stc.STC_H_DOUBLESTRING, 'string_style'),
+ (stc.STC_H_ENTITY, 'default_style'), # Style ME
+ (stc.STC_H_NUMBER, 'number_style'),
+ (stc.STC_H_OTHER, 'default_style'), # Style ME
+ (stc.STC_H_QUESTION, 'scalar_style'),
+ (stc.STC_H_SCRIPT, 'funct_style'), # STYLE ME
+ (stc.STC_H_SGML_1ST_PARAM, 'keyword2_style'), # STYLE ME
+ (stc.STC_H_SGML_1ST_PARAM_COMMENT, 'comment_style'),
+ (stc.STC_H_SGML_BLOCK_DEFAULT, 'default_style'), # STYLE ME
+ (stc.STC_H_SGML_COMMAND, 'keyword_style'), # STYLE ME
+ (stc.STC_H_SGML_COMMENT, 'comment_style'),
+ (stc.STC_H_SGML_DEFAULT, 'array_style'), # STYLE ME
+ (stc.STC_H_SGML_DOUBLESTRING, 'string_style'),
+ (stc.STC_H_SGML_ENTITY, 'default_style'), # STYLE ME
+ (stc.STC_H_SGML_ERROR, 'error_style'),
+ (stc.STC_H_SGML_SIMPLESTRING, 'string_style'),
+ (stc.STC_H_SGML_SPECIAL, 'default_style'), # STYLE ME
+ (stc.STC_H_SINGLESTRING, 'string_style'),
+ (stc.STC_H_TAG, 'keyword_style'),
+ (stc.STC_H_TAGEND, 'keyword_style'),
+ (stc.STC_H_TAGUNKNOWN, 'error_style'),
+ (stc.STC_H_VALUE, 'number_style'),
+ (stc.STC_H_XCCOMMENT, 'comment_style'),
+ (stc.STC_H_XMLEND, 'scalar_style'),
+ (stc.STC_H_XMLSTART, 'scalar_style'),
+
+ # Embedded JavaScript
+ (stc.STC_HJ_COMMENT, 'comment_style'),
+ (stc.STC_HJ_COMMENTDOC, 'comment_style'),
+ (stc.STC_HJ_COMMENTLINE, 'comment_style'),
+ (stc.STC_HJ_DEFAULT, 'default_style'),
+ (stc.STC_HJ_DOUBLESTRING, 'default_style'), # STYLE ME
+ (stc.STC_HJ_KEYWORD, 'default_style'), # STYLE ME
+ (stc.STC_HJ_NUMBER, 'default_style'), # STYLE ME
+ (stc.STC_HJ_REGEX, 'default_style'), # STYLE ME
+ (stc.STC_HJ_SINGLESTRING, 'default_style'), # STYLE ME
+ (stc.STC_HJ_START, 'default_style'), # STYLE ME
+ (stc.STC_HJ_STRINGEOL, 'default_style'), # STYLE ME
+ (stc.STC_HJ_SYMBOLS, 'default_style'), # STYLE ME
+ (stc.STC_HJ_WORD, 'default_style'), # STYLE ME
+
+ (stc.STC_HJA_COMMENT, 'comment_style'),
+ (stc.STC_HJA_COMMENTDOC, 'comment_style'),
+ (stc.STC_HJA_COMMENTLINE, 'comment_style'),
+ (stc.STC_HJA_DEFAULT, 'default_style'),
+ (stc.STC_HJA_DOUBLESTRING, 'default_style'), # STYLE ME
+ (stc.STC_HJA_KEYWORD, 'default_style'), # STYLE ME
+ (stc.STC_HJA_NUMBER, 'default_style'), # STYLE ME
+ (stc.STC_HJA_REGEX, 'default_style'), # STYLE ME # STYLE ME
+ (stc.STC_HJA_SINGLESTRING, 'default_style'), # STYLE ME
+ (stc.STC_HJA_START, 'default_style'), # STYLE ME
+ (stc.STC_HJA_STRINGEOL, 'default_style'), # STYLE ME
+ (stc.STC_HJA_SYMBOLS, 'default_style'), # STYLE ME
+ (stc.STC_HJA_WORD, 'default_style'),
+
+ (stc.STC_HBA_DEFAULT, 'operator_style'), # Styles ( ) ?
+ (stc.STC_HBA_COMMENTLINE, 'comment_style'),
+ (stc.STC_HBA_IDENTIFIER, 'default_style'), # TODO
+ (stc.STC_HBA_NUMBER, 'number_style'),
+ (stc.STC_HBA_START, 'default_style'), # TODO
+ (stc.STC_HBA_STRING, 'string_style'),
+ (stc.STC_HBA_STRINGEOL, 'stringeol_style'),
+ (stc.STC_HBA_WORD, 'keyword_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FLD_HTML = ("fold.html", "1")
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Html and related languages"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_HTML)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List"""
+ if self.LangId == synglob.ID_LANG_COLDFUSION:
+ return [(HTML_TAGS[0], HTML_TAGS[1] + " " + CF_TAGS), JS_KEYWORDS]
+ else:
+ return [HTML_TAGS, JS_KEYWORDS, SGML_KEYWORDS, VBS_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications"""
+ return SYNTAX_ITEMS + _javascript.SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set"""
+ return [FOLD, FLD_HTML]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code"""
+ return [u'<!--', u'-->']
+
+#-----------------------------------------------------------------------------#
+
+def AutoIndenter(estc, pos, ichar):
+ """Auto indent python code.
+ @param estc: EditraStyledTextCtrl
+ @param pos: current carat position
+ @param ichar: Indentation character
+
+ """
+ rtxt = u''
+ line = estc.GetCurrentLine()
+ spos = estc.PositionFromLine(line)
+ text = estc.GetTextRange(spos, pos)
+ eolch = estc.GetEOLChar()
+ inspace = text.isspace()
+
+ # Cursor is in the indent area somewhere
+ if inspace:
+ estc.AddText(eolch + text)
+ return
+
+ # Check if the cursor is in column 0 and just return newline.
+ if not len(text):
+ estc.AddText(eolch)
+ return
+
+ if ichar == u"\t":
+ tabw = estc.GetTabWidth()
+ else:
+ tabw = estc.GetIndent()
+
+ # Standard indent to match previous line
+ indent = estc.GetLineIndentation(line)
+ levels = indent / tabw
+ end_spaces = ((indent - (tabw * levels)) * u" ")
+ rtxt = eolch + (ichar * levels) + end_spaces
+
+ # Check if we need some 'special' indentation
+ tmp = text.rstrip()
+ if tmp.endswith(u">"):
+ # At a tag check for if we need extra indentation
+ tagstart = tmp.rfind(u"<")
+ if tagstart >= 0:
+ tagval = tmp[tagstart:]
+ if not tagval.startswith(u"</") and \
+ not tagval.endswith(u"/>") and \
+ not tagval.endswith(u"?>"):
+ # Cursor is after an opening tag so we need to indent more
+ # First match to the starting tag
+ levels = (tagstart / tabw) # Add an extra level
+ end_spaces = ((tagstart - (tabw * levels)) * u" ")
+ rtxt = eolch + (ichar * (levels+1)) + end_spaces
+
+ # Put text in the buffer
+ estc.AddText(rtxt)
+
+#---- Syntax Modules Internal Functions ----#
+def KeywordString(option=0):
+ """Returns the specified Keyword String
+ @param option: specific subset of keywords to get
+
+ """
+ if option == synglob.ID_LANG_SGML:
+ return SGML_KEYWORDS[1]
+ else:
+ return HTML_TAGS[1]
+
+#---- End Syntax Modules Internal Functions ----#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_inno.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_inno.py
new file mode 100644
index 0000000..45d9312
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_inno.py
@@ -0,0 +1,176 @@
+###############################################################################
+# Name: inno.py #
+# Purpose: Syntax configuration module for Inno Setup Scripts #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: inno.py
+AUTHOR: Cody Preord
+@summary: Lexer configuration module for Inno Setup Scripts
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _inno.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc as stc
+import re
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+SECTION_KW = (0, "code components custommessages dirs files icons ini "
+ "installdelete langoptions languages messages registry run "
+ "setup types tasks uninstalldelete uninstallrun _istool")
+
+KEYWORDS = (1, "allowcancelduringinstall allownoicons allowrootdirectory "
+ "allowuncpath alwaysrestart alwaysshowcomponentslist "
+ "alwaysshowdironreadypage alwaysshowgrouponreadypage "
+ "alwaysusepersonalgroup appcomments appcontact appcopyright "
+ "appenddefaultdirname appenddefaultgroupname appid appmodifypath "
+ "appmutex appname apppublisher apppublisherurl appreadmefile "
+ "appsupporturl appupdatesurl appvername appversion "
+ "architecturesallowed architecturesinstallin64bitmode backcolor "
+ "backcolor2 backcolordirection backsolid changesassociations "
+ "changesenvironment compression copyrightfontname "
+ "copyrightfontsize createappdir createuninstallregkey "
+ "defaultdirname defaultgroupname defaultuserinfoname "
+ "defaultuserinfoorg defaultuserinfoserial dialogfontname "
+ "dialogfontsize direxistswarning disabledirpage "
+ "disablefinishedpage disableprogramgrouppage disablereadymemo "
+ "disablereadypage disablestartupprompt diskclustersize "
+ "diskslicesize diskspanning enablesdirdoesntexistwarning "
+ "encryption extradiskspacerequired flatcomponentslist "
+ "infoafterfile infobeforefile internalcompresslevel "
+ "languagedetectionmethod languagecodepage languageid languagename "
+ "licensefile mergeduplicatefiles minversion onlybelowversion "
+ "outputbasefilename outputdir outputmanifestfile password "
+ "privilegesrequired reservebytes restartifneededbyrun "
+ "setupiconfile showcomponentsizes showlanguagedialog "
+ "showtaskstreelines slicesperdisk solidcompression sourcedir "
+ "timestamprounding timestampsinutc titlefontname titlefontsize "
+ "touchdate touchtime uninstallable uninstalldisplayicon "
+ "uninstalldisplayname uninstallfilesdir uninstalllogmode "
+ "uninstallrestartcomputer updateuninstalllogappname "
+ "usepreviousappdir usepreviousgroup useprevioussetuptype "
+ "useprevioustasks useprevioususerinfo userinfopage usesetupldr "
+ "versioninfocompany versioninfocopyright versioninfodescription "
+ "versioninfotextversion versioninfoversion welcomefontname "
+ "welcomefontsize windowshowcaption windowstartmaximized "
+ "windowresizable windowvisible wizardimagebackcolor "
+ "wizardimagefile wizardimagestretch wizardsmallimagefile")
+
+PARAM_KW = (2, "afterinstall attribs beforeinstall check comment components "
+ "copymode description destdir destname excludes "
+ "extradiskspacerequired filename flags fontinstall "
+ "groupdescription hotkey infoafterfile infobeforefile "
+ "iconfilename iconindex key languages licensefile messagesfile "
+ "minversion name onlybelowversion parameters permissions root "
+ "runonceid section source statusmsg string subkey tasks type "
+ "types valuedata valuename valuetype workingdir")
+
+PREPROC_KW = (3, "append define dim else emit endif endsub error expr file for "
+ "if ifdef ifexist ifndef ifnexist include insert pragma sub "
+ "undef")
+
+PASCAL_KW = (4, "begin break case const continue do downto else end except "
+ "finally for function if of procedure repeat then to try until "
+ "uses var while with")
+
+USER_DEF = (5, "")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_INNO_COMMENT, 'comment_style'),
+ (stc.STC_INNO_COMMENT_PASCAL, 'comment_style'),
+ (stc.STC_INNO_DEFAULT, 'default_style'),
+ (stc.STC_INNO_IDENTIFIER, 'default_style'),
+ (stc.STC_INNO_KEYWORD, 'keyword_style'),
+ (stc.STC_INNO_KEYWORD_PASCAL, 'keyword4_style'),
+ (stc.STC_INNO_KEYWORD_USER, 'default_style'),
+ (stc.STC_INNO_PARAMETER, 'keyword2_style'),
+ (stc.STC_INNO_PREPROC, 'pre_style'),
+ (stc.STC_INNO_SECTION, 'scalar_style'),
+ (stc.STC_INNO_STRING_DOUBLE, 'string_style'),
+ (stc.STC_INNO_STRING_SINGLE, 'char_style')]
+
+if wx.VERSION >= (2, 9, 0, 0, ''):
+ SYNTAX_ITEMS.append((stc.STC_INNO_INLINE_EXPANSION, 'default_style')) #TODO
+else:
+ SYNTAX_ITEMS.append((stc.STC_INNO_PREPROC_INLINE, 'pre_style'))
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_COMP = ("fold.compact", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Inno Setup Scripts"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_INNOSETUP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [SECTION_KW, KEYWORDS, PARAM_KW, PREPROC_KW, PASCAL_KW]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ # Note: Inno can also use pascal comments (i.e {})
+ return [u';']
+
+#-----------------------------------------------------------------------------#
+
+def AutoIndenter(estc, pos, ichar):
+ """Auto indent Inno Setup Scripts.
+ @param estc: EditraStyledTextCtrl
+ @param pos: current carat position
+ @param ichar: Indentation character
+
+ """
+ rtxt = u''
+ line = estc.GetCurrentLine()
+ text = estc.GetTextRange(estc.PositionFromLine(line), pos)
+ eolch = estc.GetEOLChar()
+
+ indent = estc.GetLineIndentation(line)
+ if ichar == u"\t":
+ tabw = estc.GetTabWidth()
+ else:
+ tabw = estc.GetIndent()
+
+ i_space = indent / tabw
+ ndent = eolch + ichar * i_space
+ rtxt = ndent + ((indent - (tabw * i_space)) * u' ')
+
+ if_pat = re.compile('if\s+.*\sthen')
+ text = text.strip()
+ if text == u'begin' or if_pat.match(text):
+ rtxt += ichar
+
+ # Put text in the buffer
+ estc.AddText(rtxt)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_issuelist.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_issuelist.py
new file mode 100644
index 0000000..bac72c3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_issuelist.py
@@ -0,0 +1,127 @@
+###############################################################################
+# Name: issuelist.py #
+# Purpose: Define IssueList syntax for highlighting and other features #
+# Author: Torsten Mohr #
+# Copyright: (c) 2008 Cody Precord #
+# (c) 2008 Torsten Mohr #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: issuelist.py
+AUTHOR: Cody Precord, Torsten Mohr
+@summary: Lexer configuration module for Issue Lists.
+
+"""
+
+__author__ = "Cody Precord <cprecord>, Torsten Mohr <none_yet>"
+__svnid__ = "$Id: _issuelist.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+#Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+# Style Id's
+
+(STC_ISSL_DEFAULT,
+STC_ISSL_COMMENT,
+STC_ISSL_GREEN,
+STC_ISSL_RED,
+STC_ISSL_ORANGE,
+STC_ISSL_BLUE,
+STC_ISSL_PURPLE,
+STC_ISSL_PINK) = range(8)
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [
+ (STC_ISSL_DEFAULT, 'default_style'),
+ (STC_ISSL_COMMENT, 'comment_style'),
+ (STC_ISSL_GREEN, 'regex_style'),
+ (STC_ISSL_RED, 'number_style'),
+ (STC_ISSL_ORANGE, 'keyword4_style'),
+ (STC_ISSL_BLUE, 'dockey_style'),
+ (STC_ISSL_PURPLE, 'scalar2_style'),
+ (STC_ISSL_PINK, 'char_style'),
+ ]
+
+issl_table = ';+-?.#~'
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for IssueLists
+ This class is primarly intended as an example to creating a custom
+ lexer
+
+ """
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CONTAINER)
+ self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText)
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+#---- End Required Module Functions ----#
+
+# ; comment
+# + done
+# - open
+# ? question
+# . info
+# # strong
+# ~
+# *
+
+def StyleText(stc, start, end):
+ """Style the text
+ @param stc: Styled text control instance
+ @param start: Start position
+ @param end: end position
+
+ """
+
+ # First, figure out the line based on the position.
+ line = stc.LineFromPosition(start)
+
+ # Find the start of the line that's been styled before this one.
+ while line > 0 and stc.GetLineState(line) == 0:
+ line -= 1
+
+ eline = stc.LineFromPosition(end)
+
+ state = stc.GetLineState(line) - 1
+ if state < 0:
+ state = 0
+
+ for ln in range(line, eline + 1):
+ text = stc.GetLine(ln).encode('utf-8')
+ len_text = len(text)
+ text = text.strip()
+
+ if len(text) == 0:
+ state = 0
+ else:
+ if len(text) > 0:
+ ch = text[0]
+ ix = issl_table.find(ch)
+ if ix >= 0:
+ state = ix + 1
+
+ stc.StartStyling(stc.PositionFromLine(ln), 0xFF)
+ stc.SetStyling(len_text, state)
+
+ stc.SetLineState(ln, state + 1)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_java.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_java.py
new file mode 100644
index 0000000..fd20360
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_java.py
@@ -0,0 +1,120 @@
+###############################################################################
+# Name: java.py #
+# Purpose: Define Java syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: java.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration file for Java source files.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _java.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+from _cpp import AutoIndenter
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Java Keywords
+JAVA_KEYWORDS = (0, "goto if else switch while for "
+ "do this super new instanceof return "
+ "throw try catch finally assert synchronize "
+ "break continue ")
+
+JAVA_KEYWORDS2 = (1, "import native package synchronized throws "
+ "extends implements interface class "
+ "static synchronized transient volatile final "
+ "serializable public protected private abstract")
+
+# Java Types/Structures/Storage Classes
+JAVA_TYPES = (3, "boolean char byte short int long float double void "
+ "true false null "
+ "String Integer Long Float Double Byte Boolean "
+ "Map HashMap TreeMap CharSequence StringBuilder "
+ "List ArrayList Set HashSet TreeSet Collection "
+ "Exception System Runtime Collections Math ")
+
+
+# Documentation Keywords (Doxygen keywords/ect)
+DOC_KEYWORDS = (2, "TODO FIXME XXX \\author \\brief \\bug \\callgraph "
+ "\\category \\class \\code \\date \\def \\depreciated \\dir "
+ "\\dot \\dotfile \\else \\elseif \\em \\endcode \\enddot "
+ "\\endif \\endverbatim \\example \\exception \\file \\if "
+ "\\ifnot \\image \\include \\link \\mainpage \\name "
+ "\\namespace \\page \\par \\paragraph \\param \\return "
+ "\\retval \\section \\struct \\subpage \\subsection "
+ "\\subsubsection \\test \\todo \\typedef \\union \\var "
+ "\\verbatim \\version \\warning \\$ \\@ \\~ \\< \\> \\# \\% "
+ "@param @return @throws "
+ "HACK")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'),
+ (stc.STC_C_COMMENT, 'comment_style'),
+ (stc.STC_C_COMMENTDOC, 'comment_style'),
+ (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'),
+ (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTLINEDOC, 'comment_style'),
+ (stc.STC_C_CHARACTER, 'char_style'),
+ (stc.STC_C_GLOBALCLASS, 'global_style'),
+ (stc.STC_C_IDENTIFIER, 'default_style'),
+ (stc.STC_C_NUMBER, 'number_style'),
+ (stc.STC_C_OPERATOR, 'operator_style'),
+ (stc.STC_C_PREPROCESSOR, 'pre_style'),
+ (stc.STC_C_REGEX, 'pre_style'),
+ (stc.STC_C_STRING, 'string_style'),
+ (stc.STC_C_STRINGEOL, 'stringeol_style'),
+ (stc.STC_C_UUID, 'pre_style'),
+ (stc.STC_C_VERBATIM, 'number2_style'),
+ (stc.STC_C_WORD, 'keyword_style'),
+ (stc.STC_C_WORD2, 'keyword2_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_PRE = ("styling.within.preprocessor", "0")
+FOLD_COM = ("fold.comment", "1")
+FOLD_COMP = ("fold.compact", "1")
+FOLD_ELSE = ("fold.at.else", "0")
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Java"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [JAVA_KEYWORDS, JAVA_KEYWORDS2, DOC_KEYWORDS, JAVA_TYPES]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FOLD_PRE]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [ u'//' ]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_javascript.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_javascript.py
new file mode 100644
index 0000000..eb1b770
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_javascript.py
@@ -0,0 +1,109 @@
+###############################################################################
+# Name: javascript.py #
+# Purpose: Define JavaScript syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: javascript.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for JavaScript.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _javascript.py 70228 2011-12-31 20:39:16Z CJP $"
+__revision__ = "$Revision: 70228 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _cpp
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# JavaScript Keywords # set to 1 for embeded
+JS_KEYWORDS = (0, "abstract break boolean byte case const continue catch "
+ "class char debugger default delete do double default "
+ "export false else enum export extend final finally "
+ "float for function goto if implements import in "
+ "instanceof int interface long native new null "
+ "package private protected public return short static "
+ "synchronized switch super this throw throws transient "
+ "try true typeof var void volatile with while")
+
+#---- Syntax Style Spec ----#
+SYNTAX_ITEMS = [ (stc.STC_HJ_COMMENT, 'comment_style'),
+ (stc.STC_HJ_COMMENTDOC, 'dockey_style'),
+ (stc.STC_HJ_COMMENTLINE, 'comment_style'),
+ (stc.STC_HJ_DEFAULT, 'default_style'),
+ (stc.STC_HJ_DOUBLESTRING, 'string_style'),
+ (stc.STC_HJ_KEYWORD, 'keyword_style'),
+ (stc.STC_HJ_NUMBER, 'number_style'),
+ (stc.STC_HJ_REGEX, 'scalar_style'), # STYLE ME
+ (stc.STC_HJ_SINGLESTRING, 'string_style'),
+ (stc.STC_HJ_START, 'scalar_style'),
+ (stc.STC_HJ_STRINGEOL, 'stringeol_style'),
+ (stc.STC_HJ_SYMBOLS, 'array_style'),
+ (stc.STC_HJ_WORD, 'class_style'),
+ (stc.STC_HJA_COMMENT, 'comment_style'),
+ (stc.STC_HJA_COMMENTDOC, 'dockey_style'),
+ (stc.STC_HJA_COMMENTLINE, 'comment_style'),
+ (stc.STC_HJA_DEFAULT, 'default_style'),
+ (stc.STC_HJA_DOUBLESTRING, 'string_style'),
+ (stc.STC_HJA_KEYWORD, 'keyword_style'),
+ (stc.STC_HJA_NUMBER, 'number_style'),
+ (stc.STC_HJA_REGEX, 'scalar_style'), # STYLE ME
+ (stc.STC_HJA_SINGLESTRING, 'string_style'),
+ (stc.STC_HJA_START, 'scalar_style'),
+ (stc.STC_HJA_STRINGEOL, 'stringeol_style'),
+ (stc.STC_HJA_SYMBOLS, 'array_style'),
+ (stc.STC_HJA_WORD, 'class_style') ]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for JavaScript"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _cpp.AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [JS_KEYWORDS,]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ if self.LangId == synglob.ID_LANG_HTML:
+ return SYNTAX_ITEMS
+ else:
+ return _cpp.SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [("fold", "1")]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'//']
+
+#---- Syntax Modules Internal Functions ----#
+def KeywordString(option=0):
+ """Returns the specified Keyword String
+ @keyword option: specific subset of keywords to get
+
+ """
+ return JS_KEYWORDS[1]
+
+#---- End Syntax Modules Internal Functions ----#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_kix.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_kix.py
new file mode 100644
index 0000000..8d65a42
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_kix.py
@@ -0,0 +1,100 @@
+###############################################################################
+# Name: kix.py #
+# Purpose: Syntax configuration module for KIXtart scripts #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: kix.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for KIXtart scripts
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _kix.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+COMMANDS = (0, "? and beep big break call cd cls color cookie1 copy debug del "
+ "dim display do until exit flushkb for each next function "
+ "endfunction get gets global go gosub goto if else endif md or "
+ "password play quit rd redim return run select case endselect "
+ "set setl setm settime shell sleep small use while loop")
+
+FUNCTIONS = (1, "abs addkey addprinterconnection addprogramgroup "
+ "addprogramitem asc ascan at backupeventlog box cdbl chr cint "
+ "cleareventlog close comparefiletimes createobject cstr "
+ "dectohex delkey delprinterconnection delprogramgroup "
+ "delprogramitem deltree delvalue dir enumgroup enumipinfo "
+ "enumkey enumlocalgroup enumvalue execute exist existkey "
+ "expandenvironmentvars fix formatnumber freefilehandle "
+ "getdiskspace getfileattr getfilesize getfiletime "
+ "getfileversion getobject iif ingroup instr instrrev int "
+ "isdeclared join kbhit keyexist lcase left len loadhive "
+ "loadkey logevent logoff ltrim memorysize messagebox open "
+ "readline readprofilestring readtype readvalue redirectoutput "
+ "right rnd round rtrim savekey sendkeys sendmessage setascii "
+ "setconsole setdefaultprinter setfileattr setfocus setoption "
+ "setsystemstate settitle setwallpaper showprogramgroup "
+ "shutdown sidtoname split srnd substr trim ubound ucase "
+ "unloadhive val vartype vartypename writeline "
+ "writeprofilestring writevalue")
+
+MACROS = (2, "address build color comment cpu crlf csd curdir date day domain "
+ "dos error fullname homedir homedrive homeshr hostname inwin "
+ "ipaddress0 ipaddress1 ipaddress2 ipaddress3 kix lanroot ldomain "
+ "ldrive lm logonmode longhomedir lserver maxpwage mdayno mhz "
+ "monthno month msecs pid primarygroup priv productsuite "
+ "producttype pwage ras result rserver scriptdir scriptexe "
+ "scriptname serror sid site startdir syslang ticks time userid "
+ "userlang wdayno wksta wuserid ydayno year")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_KIX_COMMENT, 'comment_style'),
+ (stc.STC_KIX_DEFAULT, 'default_style'),
+ (stc.STC_KIX_FUNCTIONS, 'funct_style'),
+ (stc.STC_KIX_IDENTIFIER, 'default_style'),
+ (stc.STC_KIX_KEYWORD, 'keyword_style'),
+ (stc.STC_KIX_MACRO, 'pre_style'),
+ (stc.STC_KIX_NUMBER, 'number_style'),
+ (stc.STC_KIX_OPERATOR, 'operator_style'),
+ (stc.STC_KIX_STRING1, 'char_style'),
+ (stc.STC_KIX_STRING2, 'string_style'),
+ (stc.STC_KIX_VAR, 'scalar_style')]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Kix"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_KIX)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [COMMANDS, FUNCTIONS, MACROS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u';']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_latex.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_latex.py
new file mode 100644
index 0000000..c0bc90d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_latex.py
@@ -0,0 +1,95 @@
+###############################################################################
+# Name: latex.py #
+# Purpose: Define TeX/LateX syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: latex.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Tex/LaTex.
+@todo: Fairly poor needs lots of work.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _latex.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Tex Keywords
+TEX_KW = (0, "Downarrow backslash lceil rceil Uparrow downarrow lfloor rfloor "
+ "Updownarrow langle rangle Vert")
+# ConTeXt Dutch
+DUTCH = (1, "")
+# ConTeXt English
+ENG = (2, "")
+# ConTeXt German
+GERMAN = (3, "")
+# ConTeXt Czech
+CZECH = (4, "")
+# ConTeXt Italian
+ITALIAN = (5, "")
+# ConTeXt Romanian
+ROMAINIAN = (6, "")
+
+# LaTeXt
+# There are no keyword settings available for LaTeX
+
+#---- Syntax Style Specs ----#
+# TeX
+SYNTAX_ITEMS1 = [(stc.STC_TEX_DEFAULT, 'default_style'),
+ (stc.STC_TEX_COMMAND, 'keyword_style'),
+ (stc.STC_TEX_GROUP, 'scalar_style'),
+ (stc.STC_TEX_SPECIAL, 'operator_style'),
+ (stc.STC_TEX_SYMBOL, 'number_style'),
+ (stc.STC_TEX_TEXT, 'default_style') ]
+
+# LaTeX
+SYNTAX_ITEMS2 = [(stc.STC_L_DEFAULT, 'default_style'),
+ (stc.STC_L_COMMAND, 'pre_style'),
+ (stc.STC_L_COMMENT, 'comment_style'),
+ (stc.STC_L_MATH, 'operator_style'),
+ (stc.STC_L_TAG, 'keyword_style')]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for LaTeX/TeX"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ # TODO: change to LEX_TEX for TeX?
+ if self.LangId == synglob.ID_LANG_LATEX:
+ self.SetLexer(stc.STC_LEX_LATEX)
+ else:
+ self.SetLexer(stc.STC_LEX_TEX)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [TEX_KW]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ if self.LangId == synglob.ID_LANG_TEX:
+ return SYNTAX_ITEMS1
+ else:
+ return SYNTAX_ITEMS2
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'%']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lisp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lisp.py
new file mode 100644
index 0000000..aecaf4c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lisp.py
@@ -0,0 +1,405 @@
+###############################################################################
+# Name: lisp.py #
+# Purpose: Define Lisp syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Author: Jeff #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: lisp.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Lisp Files.
+@todo: Add Standard Variables
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _lisp.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+
+# Lisp Functions/Operators
+LISP_FUNC = (0, "abort abs access acons acos acosh add-method adjoin "
+ "adjust-array adjustable-array-p alist allocate-instance "
+ "alpha-char-p alphanumericp and append apply applyhook apropos "
+ "apropos-list aref arithmetic-error arithmetic-error-operands "
+ "arithmetic-error-operation array array-dimension "
+ "array-dimension-limit array-dimensions array-displacement "
+ "array-element-type array-has-fill-pointer-p "
+ "array-in-bounds-p array-rank array-rank-limit "
+ "array-row-major-index array-total-size "
+ "array-total-size-limit arrayp ash asin asinh assert assoc "
+ "assoc-if assoc-if-not atan atanh atom backquote baktrace "
+ "base-char base-string bignum bignums bit bit-and bit-andc1 "
+ "bit-andc2 bit-eqv bit-ior bit-nand bit-nor bit-not bit-orc1 "
+ "bit-orc2 bit-vector bit-vector-p bit-xor block boole boole-1 "
+ "boole-2 boole-and boole-andc1 boole-andc2 boole-c1 boole-c2 "
+ "boole-clr boole-eqv boole-ior boole-nand boole-nor boole-orc1 "
+ "boole-orc2 boole-set boole-xor boolean both-case-p boundp "
+ "break broadcast-stream broadcast-stream-streams "
+ "built-in-class butlast byte byte-position byte-size caaaar "
+ "caaadr caaar caadar caaddr caadr caar cadaar cadadr cadar "
+ "caddar cadddr caddr cadr call-arguments-limit call-method "
+ "call-next-method capitalize car case catch ccase cdaaar "
+ "cdaadr cdaar cdadar cdaddr cdadr cdar cddaar cddadr cddar "
+ "cdddar cddddr cdddr cddr cdr ceil-error ceil-error-name "
+ "ceiling cerror change-class char char-bit char-bits "
+ "char-bits-limit char-code char-code-limit char-control-bit "
+ "char-downcase char-equal char-font char-font-limit "
+ "char-greaterp char-hyper-bit char-int char-lessp "
+ "char-meta-bit char-name char-not-equal char-not-greaterp "
+ "char-not-lessp char-super-bit char-upcase char/= char<= char= "
+ "char>= character characterp check-type cirhash cis class "
+ "class-name class-of clear-input clear-output close code-char "
+ "coerce commonp compilation-speed compile compile-file "
+ "compile-file-pathname compiled-function compiled-function-p "
+ "compiler-let compiler-macro compiler-macro-function "
+ "complement complex complexp compute-applicable-methods "
+ "compute-restarts concatenate concatenated-stream "
+ "concatenated-stream-streams cond condition conjugate cons "
+ "consp constantly constantp continue control-error copy "
+ "copy-list copy-pprint-dispatch copy-readtable copy-seq "
+ "copy-structure copy-symbol copy-tree cos cosh count count-if "
+ "count-if-not ctypecase debug decf declaim declaration declare "
+ "decode-float decode-universal-time defclass defconstant "
+ "defgeneric define-compiler-macro define-condition "
+ "define-method-combination define-modify-macro "
+ "define-setf-expander define-setf-method define-symbol-macro "
+ "defmacro defmethod defpackage defparameter defsetf defstruct "
+ "deftype defun defvar delete delete-duplicates delete-file "
+ "delete-if delete-if-not delete-package denominator "
+ "deposite-field describe describe-object destructuring-bind "
+ "digit-char digit-char-p directory directory-namestring "
+ "disassemble division-by-zero do do* do-all-symbols "
+ "do-external-symbols do-symbols dolist dotimes double-float "
+ "double-float-epsilon double-float-negative-epsilion dpb "
+ "dribble dynamic-extent ecase echo-stream "
+ "echo-stream-input-stream echo-stream-output-stream ed eigth "
+ "elt encode-universal-time end-of-file endp enough-namestring "
+ "ensure-directories-exist ensure-generic-function eq eql equal "
+ "equalp error errset etypecase eval eval-when evalhook evenp "
+ "every exp export expt extend-char fboundp fceiling "
+ "fdefinition fflor fifth file-author file-error "
+ "file-error-pathname file-length file-namestring file-position "
+ "file-stream file-string-length file-write-date fill "
+ "fill-pointer find find-all-symbols find-class find-if "
+ "find-if-not find-method find-package find-restart find-symbol "
+ "finish-output first fixnum flet float float-digits "
+ "float-precision float-radix float-sign floating-point-inexact "
+ "floating-point-invalid-operation floating-point-underflow "
+ "floatp floor fmakunbound force-output format formatter fourth "
+ "fresh-line fround ftruncate ftype funcall function "
+ "function-keywords function-lambda-expression functionp gbitp "
+ "gcd generic-function gensym gentemp get get-decoded-time "
+ "get-dispatched-macro-character get-internal-real-time "
+ "get-internal-run-time get-macro-character "
+ "get-output-stream-string get-properties get-setf-expansion "
+ "get-setf-method get-universial-time getf gethash go "
+ "graphic-char-p handler-bind handler-case hash hash-table "
+ "hash-table-count hash-table-p hash-table-rehash-size "
+ "hash-table-rehash-threshold hash-table-size hash-table-test "
+ "host-namestring identity if if-exists ignorable ignore "
+ "ignore-errors imagpart import in-package incf "
+ "initialize-instance inline input-stream-p inspect int-char "
+ "integer integer-decode-float integer-length integerp "
+ "interactive-stream-p intern internal-time-units-per-second "
+ "intersection invalid-method-error invoke-debugger "
+ "invoke-restart invoke-restart-interactively isqrt keyword "
+ "keywordp l labels lambda lambda-list-keywords "
+ "lambda-parameters-limit last lcm ldb ldb-test ldiff "
+ "least-negative-double-float least-negative-long-float "
+ "least-negative-normalized-double-float "
+ "least-negative-normalized-long-float "
+ "least-negative-normalized-short-font "
+ "least-negative-normalized-single-font "
+ "least-negative-short-font least-negative-single-font "
+ "least-positive-double-float least-positive-long-float "
+ "least-positive-normalized-double-float "
+ "least-positive-normalized-long-float "
+ "least-positive-normalized-short-float "
+ "least-positive-normalized-single-float "
+ "least-positive-short-float least-positive-single-float length "
+ "let let* lisp lisp-implementation-type "
+ "lisp-implementation-version list list* "
+ "list-all-packages list-lenght listen listp load "
+ "load-logical-pathname-translation load-time-value locally "
+ "log logand logandc1 logandc2 logbitp logcount logeqv "
+ "logical-pathname logical-pathname-translations logior lognand "
+ "lognor lognot logorc1 logorc2 logtest logxor long-float "
+ "long-float-epsilon long-float-negative-epsilon long-site-name "
+ "loop loop-finish lower-case-p machine-instance machine-type "
+ "machine-version macro-function macroexpand macroexpand-1 "
+ "macroexpand-l macrolet make make-array make-broadcast-stream "
+ "make-char make-concatenated-stream make-condition "
+ "make-dispatch-macro-character make-echo-stream "
+ "make-hash-table make-instance make-instances-obsolete "
+ "make-list make-load-form make-load-form-saving-slots "
+ "make-method make-package make-pathname make-random-state "
+ "make-sequence make-string make-string-input-stream "
+ "make-string-output-stream make-symbol make-synonym-stream "
+ "make-two-way-stream makunbound map map-into mapc mapcan "
+ "mapcar mapcon maphash mapl maplist mask-field max member "
+ "member-if member-if-not merge merge-pathname merge-pathnames "
+ "method method-combination method-combination-error "
+ "method-qualifiers min minusp mismatch mod "
+ "most-negative-double-float most-negative-fixnum "
+ "most-negative-long-float most-negative-short-float "
+ "most-negative-single-float most-positive-fixnum "
+ "most-positive-long-float most-positive-short-float "
+ "most-positive-single-float muffle-warning "
+ "multiple-value-bind multiple-value-call multiple-value-limit "
+ "multiple-value-list multiple-value-prog1 multiple-value-seteq "
+ "multiple-value-setq name name-char namestring nbutlast nconc "
+ "next-method-p nil nintersection ninth no-applicable-method "
+ "no-next-method not notany notevery notinline nreconc nreverse "
+ "nset-difference nset-exclusive-or nstring nstring-capitalize "
+ "nstring-downcase nstring-upcase nstubst-if-not nsublis nsubst "
+ "nsubst-if nth nth-value nthcdr null number numberp numerator "
+ "nunion oddp open open-stream-p optimize or otherwise "
+ "output-stream-p package package-error package-error-package "
+ "package-name package-nicknames package-shadowing-symbols "
+ "package-use-list package-used-by-list packagep pairlis "
+ "parse-error parse-integer parse-namestring pathname "
+ "pathname-device pathname-directory pathname-host "
+ "pathname-match-p pathname-name pathname-type "
+ "pathname-version pathnamep peek-char phase pi plist plusp pop "
+ "position position-if position-if-not pprint pprint-dispatch "
+ "pprint-exit-if-list-exhausted pprint-fill pprint-indent "
+ "pprint-linear pprint-logical-block pprint-newline pprint-pop "
+ "pprint-tab pprint-tabular prin1 prin1-to-string princ "
+ "princ-to-string print print-not-readable "
+ "print-not-readable-object print-object probe-file proclaim "
+ "prog prog* prog1 prog2 progn program-error progv provide "
+ "psetf psetq push pushnew putprop quote random random-state "
+ "random-state-p rassoc rassoc-if rassoc-if-not ration rational "
+ "rationalize rationalp read read-byte read-car-no-hang "
+ "read-char read-delimited-list read-eval-print "
+ "read-from-string read-line read-preserving-whitespace "
+ "read-squence reader-error readtable readtable-case readtablep "
+ "real realp realpart reduce reinitialize-instance rem remf "
+ "remhash remove remove-duplicates remove-if "
+ "remove-if-not remove-method remprop rename-file "
+ "rename-package replace require rest restart restart-bind "
+ "restart-case restart-name return return-from revappend "
+ "reverse room rotatef round row-major-aref rplaca rplacd "
+ "safety satisfies sbit scale-float schar search second "
+ "sequence serious-condition set set-char-bit set-difference "
+ "set-dispatched-macro-character set-exclusive-or "
+ "set-macro-character set-pprint-dispatch "
+ "set-syntax-from-char setf setq seventh shadow "
+ "shadowing-import shared-initialize shiftf short-float "
+ "short-float-epsilon short-float-negative-epsilon "
+ "short-site-name signal signed-byte signum simple-array "
+ "simple-base-string simple-bit-vector- simple-bit-vector-p "
+ "simple-condition simple-condition-format-arguments "
+ "simple-condition-format-control simple-error simple-string "
+ "simple-string-p simple-type-error simple-vector "
+ "simple-vector-p simple-warning sin single-float "
+ "single-float-epsilon single-float-negative-epsilon sinh "
+ "sixth sleep slot-boundp slot-exists-p slot-makunbound "
+ "slot-missing slot-unbound slot-value software-type "
+ "software-version some sort space special special-form-p "
+ "special-operator-p speed sqrt stable-sort standard "
+ "standard-char standard-char-p standard-class "
+ "standard-generic-function standard-method standard-object "
+ "step storage-condition store-value stream stream-element-type "
+ "stream-error stream-error-stream stream-external-format "
+ "streamp streamup string string-capitalize string-char "
+ "string-char-p string-downcase string-equal string-greaterp "
+ "string-left-trim string-lessp string-not-equal "
+ "string-not-greaterp string-not-lessp string-right-strim "
+ "string-right-trim string-stream string-trim string-upcase "
+ "string/= string< string<= string= string> string>= stringp "
+ "structure structure-class structure-object style-warning "
+ "sublim sublis subseq subsetp subst subst-if subst-if-not "
+ "substitute substitute-if substitute-if-not subtypep svref "
+ "sxhash symbol symbol-function symbol-macrolet symbol-name "
+ "symbol-package symbol-plist symbol-value symbolp "
+ "synonym-stream synonym-stream-symbol sys system t tagbody "
+ "tailp tan tanh tenth terpri the third throw time trace "
+ "translate-logical-pathname translate-pathname tree-equal "
+ "truename truncase truncate two-way-stream "
+ "two-way-stream-input-stream two-way-stream-output-stream "
+ "type type-error type-error-datnum type-error-expected-type "
+ "type-of typecase typep unbound-slot unbound-slot-instance "
+ "unbound-variable undefined-function unexport unintern union "
+ "unless unread unread-char unsigned-byte untrace unuse-package "
+ "unwind-protect update-instance-for-different-class "
+ "update-instance-for-redefined-class "
+ "upgraded-array-element-type upgraded-complex-part-type "
+ "upper-case-p use-package use-value user user-homedir-pathname "
+ "value value-list values vector vector-pop vector-push "
+ "vector-push-extend vectorp warn warning when "
+ "wild-pathname-p with-accessors with-compilation-unit "
+ "with-condition-restarts with-hash-table-iterator "
+ "with-input-from-string with-open-file with-open-stream "
+ "with-output-to-string with-package-iterator "
+ "with-simple-restart with-slots with-standard-io-syntax write "
+ "write-byte write-char write-line write-sequence" )
+
+SCHEME_KW = (0, "* + - / < <= = => > >= abs acos and angle append apply asin "
+ "assoc assq assv atan begin boolean? caaaar caaadr caaar "
+ "caadar caaddr caadr caar cadaar cadadr cadar caddar cadddr "
+ "caddr cadr call-with-current-continuation "
+ "call-with-input-file call-with-output-file call-with-values "
+ "call/cc car case cdaaar cdaadr cdaar cdadar cdaddr cdadr cdar "
+ "cddaar cddadr cddar cdddar cddddr cdddr cddr cdr ceiling "
+ "char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? "
+ "char-ci>=? char-ci>? char-downcase char-lower-case? "
+ "char-numeric? char-ready? char-upcase char-upper-case? "
+ "char-whitespace? char<=? char<? char=? char>=? char>? char? "
+ "close-input-port close-output-port complex? cond cons cos "
+ "current-input-port current-output-port define define-syntax "
+ "delay denominator display do dynamic-wind else eof-object? "
+ "eq? equal? eqv? eval even? exact->inexact exact? exp expt "
+ "floor for-each force gcd if imag-part inexact->exact inexact? "
+ "input-port? integer->char integer? interaction-environment "
+ "lambda lcm length let let* let-syntax letrec letrec-syntax "
+ "list list->string list->vector list-ref list-tail list? load "
+ "log magnitude make-polar make-rectangular make-string "
+ "make-vector map max member memq memv min modulo negative? "
+ "newline not null-environment null? number->string number? "
+ "numerator odd? open-input-file open-output-file or "
+ "output-port? pair? peek-char positive? procedure? quasiquote "
+ "quote quotient rational? rationalize read read-char "
+ "real-part real? remainder reverse round "
+ "scheme-report-environment set! set-car! set-cdr! sin sqrt "
+ "string string->list string->number string->symbol "
+ "string-append string-ci<=? string-ci<? string-ci=? "
+ "string-ci>=? string-ci>? string-copy string-fill! "
+ "string-length string-ref string-set! string<=? string<? "
+ "string=? string>=? string>? string? substring symbol->string "
+ "symbol? syntax-rules transcript-off transcript-on truncate "
+ "unquote unquote-splicing values vector vector->list "
+ "vector-fill! vector-length vector-ref vector-set! vector? "
+ "with-input-from-file with-output-to-file write write-char "
+ "zero?" )
+
+# Lisp Keywords
+LISP_KEYWORDS = (1, ":abort :adjustable :append :array :base :case :circle "
+ ":conc-name :constructor :copier :count :create :default "
+ ":device :directory :displaced-index-offset :displaced-to "
+ ":element-type :end :end1 :end2 :error :escape :external "
+ ":from-end :gensym :host :include :if-does-not-exist "
+ ":if-exists :index :inherited :internal :initial-contents "
+ ":initial-element :initial-offset :initial-value :input "
+ ":io :junk-allowed :key :length :level :name :named "
+ ":new-version :nicknames :output :ouput=file :overwrite "
+ ":predicate :preserve-whitespace :pretty :print "
+ ":print-function :probe :radix :read-only :rehash-size "
+ ":rehash-threshold :rename :size :rename-and-delete :start "
+ ":start1 :start2 :stream :supersede :test :test-not :use "
+ ":verbose :version")
+
+NEWLISP_FUNC = (0, "! != % & * + - / : < << <= = > >= >> ? @ NaN? abort abs "
+ "acos acosh add address " "amb and append append-file apply "
+ "args array array-list array? asin asinh assoc assoc-set "
+ "atan atan2 atanh atom? base64-dec base64-enc bayes-query "
+ "bayes-train begin beta betai bind binomial callback case "
+ "catch ceil change-dir char chop clean close command-event "
+ "cond cons constant context context? copy-file cos cosh "
+ "count cpymem crc32 crit-chi2 crit-z current-line curry "
+ "date date-value debug dec def-new default define "
+ "define-macro delete delete-file delete-url destroy det "
+ "device difference directory directory? div do-until "
+ "do-while doargs dolist dostring dotimes dotree dump dup "
+ "empty? encrypt ends-with env erf error-event error-number "
+ "error-text eval eval-string exec exists exit exp expand "
+ "explode factor fft file-info file? filter find find-all "
+ "first flat " "float float? floor flt for for-all fork "
+ "format fv gammai gammaln gcd get-char get-float get-int "
+ "get-long get-string get-url global global? if if-not ifft "
+ "import inc index int integer integer? intersect invert irr "
+ "join lambda? last legal? length let letex letn list list? "
+ "load local log lookup lower-case macro? main-args make-dir "
+ "map mat match max member min mod mul multiply name "
+ "net-accept net-close net-connect net-error net-eval "
+ "net-listen net-local net-lookup net-peek net-peer net-ping"
+ "-receive " "net-receive-from net-receive-udp net-select "
+ "net-send net-send-to net-send-udp net-service net-sessions "
+ "new nil nil? normal not now nper npv nth nth-set null? "
+ "number? open or ostype pack parse parse-date peek pipe pmt "
+ "pop pop-assoc post-url pow pretty-print primitive? print "
+ "println prob-chi2 prob-z process prompt-event protected? "
+ "push put-url pv quote quote? rand random randomize "
+ "read-buffer read-char read-expr read-file read-key "
+ "read-line real-path ref ref-all ref-set regex regex-comp "
+ "remove-dir rename-file replace reset rest reverse rotate "
+ "round save search seed seek select semaphore sequence "
+ "series set set-assoc set-locale set-nth set-ref "
+ "set-ref-all setq sgn share signal silent sin sinh sleep "
+ "slice sort source spawn sqrt starts-with string string? "
+ "sub swap sym symbol? symbols sync sys-error sys-info tan "
+ "tanh throw throw-error time time-of-day timer title-case "
+ "trace trace-highlight transpose trim true true? unicode "
+ "unify unique unless unpack until upper-case utf8 utf8len "
+ "uuid wait-pid when while write-buffer write-char "
+ "write-file write-line xml-error xml-parse xml-type-tags "
+ "zero? | ~ lambda")
+
+# Lisp Keywords
+NEWLISP_KEYWORDS = (1, "$ $0 $1 $10 $11 $12 $13 $14 $15 $2 $3 $4 $5 $6 $7 $8 "
+ "$9 $args $idx $main-args MAIN :")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_LISP_DEFAULT, 'default_style'),
+ (stc.STC_LISP_COMMENT, 'comment_style'),
+ (stc.STC_LISP_MULTI_COMMENT, 'comment_style'),
+ (stc.STC_LISP_IDENTIFIER, 'default_style'),
+ (stc.STC_LISP_KEYWORD, 'keyword_style'),
+ (stc.STC_LISP_KEYWORD_KW, 'keyword2_style'),
+ (stc.STC_LISP_NUMBER, 'number_style'),
+ (stc.STC_LISP_OPERATOR, 'operator_style'),
+ (stc.STC_LISP_SPECIAL, 'operator_style'),
+ (stc.STC_LISP_STRING, 'string_style'),
+ (stc.STC_LISP_STRINGEOL, 'stringeol_style'),
+ (stc.STC_LISP_SYMBOL, 'scalar_style') ]
+
+#---- Extra Properties ----#
+FOLD = ('fold', '1')
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for List/newLisp/Scheme"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_LISP)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ if self.LangId == synglob.ID_LANG_LISP:
+ return [LISP_FUNC, LISP_KEYWORDS]
+ elif self.LangId == synglob.ID_LANG_SCHEME:
+ return [SCHEME_KW]
+ elif self.LangId == synglob.ID_LANG_NEWLISP:
+ return [NEWLISP_FUNC, NEWLISP_KEYWORDS]
+ else:
+ return list()
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u';']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lout.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lout.py
new file mode 100644
index 0000000..3bdae63
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lout.py
@@ -0,0 +1,116 @@
+###############################################################################
+# Name: lout.py #
+# Purpose: Define Lout syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: lout.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Lout
+@todo: style refinement
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _lout.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+# @ prefixed keywords
+LOUT_KW1 = (0, "@OptGall @FontDef @Family @Face @Name @Metrics @ExtraMetrics "
+ "@Mapping @Recode @Filter @FilterIn @FilterOut @FilterErr @AL "
+ "@Common @Rump @Meld @Insert @OneOf @Next @Plus @Minus @Wide "
+ "@High @HShift @VShift @BeginHeaderComponent @Document @TItle "
+ "@SetHeaderComponent @ClearHeaderComponent @OneCol @OneRow @Doc "
+ "@HMirror @VMirror @HScale @VScale @HCover @VCover @Scale @Text "
+ "@KernShrink @HContract @VContract @HLimited @VLimited @HExpand "
+ "@VExpand @StartHVSpan @StartHSpan @StartVSpan @HSpan @VSpan "
+ "@PAdjust @HAdjust @VAdjust @Rotate @Background @IncludeGraphic "
+ "@SysIncludeGraphic @Graphic @LinkSource @LinkDest @URLLink @BI "
+ "@PlainGraphic @Verbatim @RawVerbatim @Case @Yield @BackEnd @BL "
+ "@Char @Font @Space @YUnit @ZUnit @Break @Underline @SetColour "
+ "@SetColor @SetUnderlineColour @SetUnderlineColor @SetTexture "
+ "@Outline @Language @CurrLang @CurrFamily @CurrFace @CurrYUnit "
+ "@CurrZUnit @LEnv @@A @@B @@C @@D @@E @LClos @@V @LUse @LEO @PP "
+ "@Open @Use @NotRevealed @Tagged @Database @SysDatabase @I @B"
+ "@Include @SysInclude @IncludeGraphicRepeated @InitialFont "
+ "@SysIncludeGraphicRepeated @PrependGraphic @SysPrependGraphic "
+ "@Target @Null @PageLabel @Galley @ForceGalley @LInput @Split "
+ "@Tag @Key @Optimize @Merge @Enclose @Begin @End @Moment @Tab "
+ "@Second @Minute @Hour @Day @Month @Year @Century @WeekDay "
+ "@YearDay @DaylightSaving @SetContext @GetContext @Time @List "
+ "@EndHeaderComponent @Section @BeginSections @EndNote @Abstract "
+ "@AlphaList @Appendix @Author @Figure @Report @OuterNote "
+ "@IndentedList @InitialBreak @InitialLanguage InnerNote "
+ "@Heading @FootNote @Date @LeftList @LeftNote @ListItem "
+ "@RightDisplay @RightNote @EndSections")
+
+# Symbols
+LOUT_KW2 = (1, "&&& && & ^// ^/ ^|| ^| ^& // / || |")
+
+# Non @ keywords
+LOUT_KW3 = (2, "def langdef force horizontally into extend import export "
+ "precedence associativity left right body macro named "
+ "compulsory following preceding foll_or_prec now "
+ "Base Slope Bold BoldSlope Times Helvetica Courier Palatino "
+ "adjust breakstyle clines lines linesep hyphen nonhyphen ragged "
+ )
+
+# Document Classes
+LOUT_KW4 = (3, "fx vx aformat bformat doc eq graph slides tab text tbl")
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_LOUT_COMMENT, 'comment_style'),
+ (stc.STC_LOUT_DEFAULT,'default_style'),
+ (stc.STC_LOUT_IDENTIFIER, 'default_style'),
+ (stc.STC_LOUT_NUMBER, 'number_style'),
+ (stc.STC_LOUT_OPERATOR, 'operator_style'),
+ (stc.STC_LOUT_STRING, 'string_style'),
+ (stc.STC_LOUT_STRINGEOL, 'stringeol_style'),
+ (stc.STC_LOUT_WORD, 'scalar_style'),
+ (stc.STC_LOUT_WORD2, 'keyword2_style'),
+ (stc.STC_LOUT_WORD3, 'keyword_style'),
+ (stc.STC_LOUT_WORD4, 'class_style')]
+
+#---- Extra Properties ----#
+FOLD_COMPACT = ("fold.compact", '1')
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for LOUT"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_LOUT)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [LOUT_KW1, LOUT_KW2, LOUT_KW3]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD_COMPACT]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lua.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lua.py
new file mode 100644
index 0000000..dc223f5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lua.py
@@ -0,0 +1,131 @@
+###############################################################################
+# Name: lua.py #
+# Purpose: Define Lua5 syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: lua.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Lua
+@todo: This setup for Lua5, maybe add Lua4 support
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _lua.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+# Keywords
+LUA_KEYWORDS = (0, "and break do else elseif end false for function if "
+ "in local nil not or repeat return then true until while")
+
+# Basic Functions
+LUA_FUNCT = (1, "_VERSION assert collectgarbage dofile error gcinfo loadfile "
+ "loadstring print rawget rawset require tonumber tostring type "
+ "unpack "
+ # Lua5 Basic functions
+ "_G getfenv getmetatable ipairs loadlib next pairs pcall "
+ "rawequal setfenv setmetatable xpcall \string table math "
+ "coroutine io os debug \load module select")
+
+# String, (table) & math functions Lua5
+LUA_STR = (2, "string.byte string.char string.dump string.find string.len "
+ "string.lower string.rep string.sub string.upper string.format "
+ "string.gfind string.gsub table.concat table.foreach "
+ "table.foreachi table.getn table.sort table.insert table.remove "
+ "table.setn math.abs math.acos math.asin math.atan math.atan2 "
+ "math.ceil math.cos math.deg math.exp math.floor math.frexp "
+ "math.ldexp math.log math.log10 math.max math.min math.mod "
+ "math.pi math.pow math.rad math.random math.randomseed math.sin "
+ "math.sqrt math.tan string.gmatch string.match string.reverse "
+ "table.maxn math.cosh math.fmod math.modf math.sinh math.tanh "
+ "math.huge")
+
+# (coroutines), I/O & system facilities
+LUA_CO = (3, "coroutine.create coroutine.resume coroutine.status coroutine."
+ "wrap coroutine.yield io.close io.flush io.input io.lines io.open "
+ "io.output io.read io.tmpfile io.type io.write io.stdin io.stdout "
+ "io.stderr os.clock os.date os.difftime os.execute os.exit "
+ "os.getenv os.remove os.rename os.setlocale os.time os.tmpname "
+ "coroutine.running package.cpath package.loaded package.loadlib "
+ "package.path package.preload package.seeall io.popen")
+
+# user1
+LUA_U1 = (4, "")
+
+# user2
+LUA_U2 = (5, "")
+
+# user3
+LUA_U3 = (6, "")
+
+# user4
+LUA_U4 = (7, "")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_LUA_CHARACTER, 'char_style'),
+ (stc.STC_LUA_COMMENT, 'comment_style'),
+ (stc.STC_LUA_COMMENTDOC, 'dockey_style'),
+ (stc.STC_LUA_COMMENTLINE, 'comment_style'),
+ (stc.STC_LUA_DEFAULT, 'default_style'),
+ (stc.STC_LUA_IDENTIFIER, 'default_style'), # style maybe
+ (stc.STC_LUA_LITERALSTRING, 'string_style'),
+ (stc.STC_LUA_NUMBER, 'number_style'),
+ (stc.STC_LUA_OPERATOR, 'operator_style'),
+ (stc.STC_LUA_PREPROCESSOR, 'pre_style'),
+ (stc.STC_LUA_STRING, 'string_style'),
+ (stc.STC_LUA_STRINGEOL, 'stringeol_style'),
+ (stc.STC_LUA_WORD, 'keyword_style'),
+ (stc.STC_LUA_WORD2, 'keyword3_style'),
+ (stc.STC_LUA_WORD3, 'funct_style'),
+ (stc.STC_LUA_WORD4, 'funct_style'),
+ (stc.STC_LUA_WORD5, 'default_style'), # currently unused
+ (stc.STC_LUA_WORD6, 'default_style'), # currently unused
+ (stc.STC_LUA_WORD7, 'default_style'), # currently unused
+ (stc.STC_LUA_WORD8, 'default_style') # currently unused
+ ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_COMP = ("fold.compact", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Lua"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_LUA)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [LUA_KEYWORDS, LUA_FUNCT, LUA_STR, LUA_CO]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set"""
+ return [FOLD, FOLD_COMP]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'--']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_make.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_make.py
new file mode 100644
index 0000000..d42c780
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_make.py
@@ -0,0 +1,53 @@
+###############################################################################
+# Name: make.py #
+# Purpose: Define Makefile syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: make.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Makefiles.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _make.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+# Syntax Style Specs
+SYNTAX_ITEMS = [ (stc.STC_MAKE_DEFAULT, 'default_style'),
+ (stc.STC_MAKE_COMMENT, 'comment_style'),
+ (stc.STC_MAKE_IDENTIFIER, 'scalar_style'),
+ (stc.STC_MAKE_IDEOL, 'ideol_style'),
+ (stc.STC_MAKE_OPERATOR, 'operator_style'),
+ (stc.STC_MAKE_PREPROCESSOR, 'pre2_style'),
+ (stc.STC_MAKE_TARGET, 'keyword_style') ]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Makefiles"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_MAKEFILE)
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mako.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mako.py
new file mode 100644
index 0000000..6edfbe5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mako.py
@@ -0,0 +1,134 @@
+###############################################################################
+# Name: mako.py #
+# Purpose: Define Mako syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: mako.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Mako Templates.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _mako.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+from pygments.token import Token
+from pygments.lexers import get_lexer_by_name
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+# Style Id's
+
+STC_MAKO_DEFAULT, \
+STC_MAKO_COMMENT, \
+STC_MAKO_NUMBER, \
+STC_MAKO_STRING, \
+STC_MAKO_STRINGEOL, \
+STC_MAKO_SCALAR, \
+STC_MAKO_OPERATOR, \
+STC_MAKO_PREPROCESSOR, \
+STC_MAKO_ATTRIBUTE, \
+STC_MAKO_TAG, \
+STC_MAKO_BUILTIN, \
+STC_MAKO_KEYWORD = range(12)
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Python Keywords
+KEYWORDS = "include inherit namespace page"
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (STC_MAKO_DEFAULT, 'default_style'),
+ (STC_MAKO_COMMENT, 'comment_style'),
+ (STC_MAKO_NUMBER, 'number_style'),
+ (STC_MAKO_STRING, 'string_style'),
+ (STC_MAKO_STRINGEOL, 'stringeol_style'),
+ (STC_MAKO_SCALAR, 'scalar_style'),
+ (STC_MAKO_OPERATOR, 'operator_style'),
+ (STC_MAKO_PREPROCESSOR, 'pre_style'),
+ (STC_MAKO_ATTRIBUTE, 'keyword2_style'),
+ (STC_MAKO_TAG, 'keyword_style'), # Need new tag
+ (STC_MAKO_BUILTIN, 'keyword4_style'),
+ (STC_MAKO_KEYWORD, 'keyword_style'), ]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Mako"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CONTAINER)
+ self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [(1, KEYWORDS)]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u"#",]
+
+#-----------------------------------------------------------------------------#
+
+def StyleText(stc, start, end):
+ """Style the text
+ @param stc: Styled text control instance
+ @param start: Start position
+ @param end: end position
+
+ """
+ cpos = 0
+ stc.StartStyling(cpos, 0x1f)
+ lexer = get_lexer_by_name("html+mako")
+ doctxt = stc.GetTextRange(0, end)
+ wineol = stc.GetEOLChar() == "\r\n"
+ for token, txt in lexer.get_tokens(doctxt):
+# print token, txt
+ style = TOKEN_MAP.get(token, STC_MAKO_DEFAULT)
+ if style == STC_MAKO_PREPROCESSOR and txt.startswith(u'#'):
+ style = STC_MAKO_COMMENT
+# elif style == STC_MAKO_STRING and txt[-1] not in '"\'':
+# style = STC_MAKO_STRINGEOL
+
+ tlen = len(txt)
+ if wineol and "\n" in txt:
+ tlen += txt.count("\n")
+
+ if tlen:
+ stc.SetStyling(tlen, style)
+ cpos += tlen
+ stc.StartStyling(cpos, 0x1f)
+
+#-----------------------------------------------------------------------------#
+
+TOKEN_MAP = { Token.Literal.String : STC_MAKO_STRING,
+ Token.Comment.Preproc : STC_MAKO_PREPROCESSOR,
+ Token.Comment : STC_MAKO_COMMENT,
+ Token.Name.Builtin : STC_MAKO_BUILTIN,
+ Token.Operator : STC_MAKO_OPERATOR,
+ Token.Punctuation : STC_MAKO_OPERATOR,
+ Token.Number : STC_MAKO_NUMBER,
+ Token.Keyword : STC_MAKO_KEYWORD,
+ Token.Name.Attribute : STC_MAKO_ATTRIBUTE,
+ Token.String.Interpol : STC_MAKO_SCALAR,
+ Token.Name.Tag : STC_MAKO_TAG }
+ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_masm.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_masm.py
new file mode 100644
index 0000000..2f2c680
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_masm.py
@@ -0,0 +1,196 @@
+###############################################################################
+# Name: masm.py #
+# Purpose: Define MASM syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: masm.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration file Microsoft Assembly Code
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _masm.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+
+# MASM CPU Instructions/Operators
+MASM_CPU_INST = (0, "aaa aad aam aas adc and arpl bound bsf bsr bswap bt btc "
+ "btr bts call cdw cdq clc cld cli clts cmc cmp cmps cmpsb "
+ "cmpsw cmpsd cmpxchng cwd cwde daa das enter in ins insb "
+ "insw insd int into invd invlpg iret iretd ja jae jb jbe "
+ "jc jcxz jecxz je jz jg jge jl jle jna jnae jnb jnbe jnc "
+ "jne jng jnge jnl jnle jno jnp jns jnz jo jp jpe jpo js jz "
+ "jmp lahf lar lea leave lgdt lidt lgs lss lfs lods lodsb "
+ "lodsw lodsd loop loope loopz loone loopne retf retn lds "
+ "les lldt lmsw lock lsl ltr mov movs movsb movsw movsd "
+ "movsx movzx neg nop not or out outs outsb outsw outsd "
+ "pop popa popd popf popfd push pusha pushad pushf pushfd "
+ "rcl rcr rol roro rep repe repz repne repnz ret sahf sal "
+ "sar shl shr sbb scas scasb scasw scasd seta setae setb "
+ "setbe setc sete setg setge setl setle setna setnae setnb "
+ "setnbe setnc setne setng setnge setnl setnle setno setnp "
+ "setns setnz seto setp setpe setpo ses setz sgdt sidt shld "
+ "shrd sldt smsw stc std sti stos stosb stosw stosd str "
+ "test verr verw wait wbinvd xchg xlat xlatb xor add dec "
+ "idiv imul inc mul sub xadd div "
+ # MMX/SSE/SSE2 Instructions
+ "cflush cpuid emms femms cmovo cmovno cmovb cmovc cmovnae "
+ "cmovae cmovnb cmovnc cmove cmovz cmovne cmovnz cmovbe "
+ "cmovna cmova cmovnbe cmovs cmovns cmovp cmovpe cmovnp "
+ "cmovpo cmovl cmovnge cmovge cmovnl cmovle cmovng cmovg "
+ "cmovnle cmpxchg486 cmpxchg8b loadall loadall286 ibts "
+ "icebp int1 int3 int01 int03 iretw popaw popfw pushaw "
+ "pushfw rdmsr rdpmc rdshr rdtsc rsdc rsldt rsm rsts salc "
+ "smi smint smintold svdc svldt svts syscall sysenter "
+ "sysexit sysret ud0 ud1 ud2 umov xbts wrmsr wrshr")
+
+# floating point instructions
+MASM_FPU_INST = (1, "f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcom fcomp "
+ "fcompp fdecstp fdisi fdiv fdivp fdivr fdivrp feni ffree "
+ "fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit "
+ "fist fistp fisub fisubr fld fld1 fldcw fldenv fldenvw "
+ "fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex "
+ "fndisi fneni fninit fnop fnsave fnsavew fnstcw fnstenv "
+ "fnstenvw fnstsw fpatan fprem fptan frndint frstor frstorw "
+ "fsave fsavew fscale fsqrt fst fstcw fstenv fstenvw fstp "
+ "fstsw fsub fsubp fsubr fsubrp ftst fwait fxam fxch "
+ "fxtract fyl2x fyl2xp1 fsetpm fcos fldenvd fnsaved "
+ "fnstenvd fprem1 frstord fsaved fsin fsincos fstenvd fucom "
+ "fucomp fucompp fcomi fcomip ffreep fcmovb fcmove fcmovbe "
+ "fcmovu fcmovnb fcmovne fcmovnbe fcmovnu ")
+
+MASM_REGISTERS = (2, "ah al ax bh bl bp bx ch cl cr0 cr2 cr3 cr4 cs cx dh di "
+ "dl dr0 dr1 dr2 dr3 dr6 dr7 ds dx eax ebp ebx ecx edi edx "
+ "es esi esp fs gs si sp ss st tr3 tr4 tr5 tr6 tr7 st0 st1 "
+ "st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 "
+ "xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7")
+
+MASM_DIRECTIVES = (3, ".186 .286 .286c .286p .287 .386 .386c .386p .387 .486 "
+ ".486p .8086 .8087 .alpha .break .code .const .continue "
+ ".cref .data .data? .dosseg .else .elseif .endif .endw "
+ ".err .err1 .err2 .errb .errdef .errdif .errdifi .erre "
+ ".erridn .erridni .errnb .errndef .errnz .exit .fardata "
+ ".fardata? .if .lall .lfcond .list .listall .listif "
+ ".listmacro .listmacroall .model .no87 .nocref .nolist "
+ ".nolistif .nolistmacro .radix .repeat .sall .seq "
+ ".sfcond .stack .startup .tfcond .type .until .untilcxz "
+ ".while .xall .xcref .xlist alias align assume catstr "
+ "comm comment db dd df dosseg dq dt dup dw echo else "
+ "elseif elseif1 elseif2 elseifb elseifdef elseifdif "
+ "elseifdifi elseife elseifidn elseifidni elseifnb "
+ "elseifndef end endif endm endp ends eq equ even exitm "
+ "extern externdef extrn for forc ge goto group gt high "
+ "highword if if1 if2 ifb ifdef ifdif ifdifi ife ifidn "
+ "ifidni ifnb ifndef include includelib instr invoke irp "
+ "irpc label le length lengthof local low lowword "
+ "lroffset lt macro mask mod .msfloat name ne offset "
+ "opattr option org %out page popcontext proc proto ptr "
+ "public purge pushcontext record repeat rept seg segment "
+ "short size sizeof sizestr struc struct substr subtitle "
+ "subttl textequ this title type typedef union while "
+ "width")
+
+MASM_DIREC_OP = (4, "$ ? @b @f addr basic byte c carry? dword far far16 "
+ "fortran fword near near16 overflow? parity? pascal qword "
+ "real4 real8 real10 sbyte sdword sign? stdcall sword "
+ "syscall tbyte vararg word zero? flat near32 far32 abs all "
+ "assumes at casemap common compact cpu dotname emulator "
+ "epilogue error export expr16 expr32 farstack flat "
+ "forceframe huge language large listing ljmp loadds m510 "
+ "medium memory nearstack nodotname noemulator nokeyword "
+ "noljmp nom510 none nonunique nooldmacros nooldstructs "
+ "noreadonly noscoped nosignextend nothing notpublic "
+ "oldmacros oldstructs os_dos para private prologue radix "
+ "readonly req scoped setif2 smallstack tiny use16 use32 "
+ "uses")
+
+MASM_EXT_INST = (5, "addpd addps addsd addss andpd andps andnpd andnps cmpeqpd "
+ "cmpltpd cmplepd cmpunordpd cmpnepd cmpnltpd cmpnlepd "
+ "cmpordpd cmpeqps cmpltps cmpleps cmpunordps cmpneps "
+ "cmpnltps cmpnleps cmpordps cmpeqsd cmpltsd cmplesd "
+ "cmpunordsd cmpnesd cmpnltsd cmpnlesd cmpordsd cmpeqss "
+ "cmpltss cmpless cmpunordss cmpness cmpnltss cmpnless "
+ "cmpordss comisd comiss cvtdq2pd cvtdq2ps cvtpd2dq "
+ "cvtpd2pi cvtpd2ps cvtpi2pd cvtpi2ps cvtps2dq cvtps2pd "
+ "cvtps2pi cvtss2sd cvtss2si cvtsd2si cvtsd2ss cvtsi2sd "
+ "cvtsi2ss cvttpd2dq cvttpd2pi cvttps2dq cvttps2pi "
+ "cvttsd2si cvttss2si divpd divps divsd divss fxrstor "
+ "fxsave ldmxscr lfence mfence maskmovdqu maskmovdq maxpd "
+ "maxps paxsd maxss minpd minps minsd minss movapd movaps "
+ "movdq2q movdqa movdqu movhlps movhpd movhps movd movq "
+ "movlhps movlpd movlps movmskpd movmskps movntdq movnti "
+ "movntpd movntps movntq movq2dq movsd movss movupd movups "
+ "mulpd mulps mulsd mulss orpd orps packssdw packsswb "
+ "packuswb paddb paddsb paddw paddsw paddd paddsiw paddq "
+ "paddusb paddusw pand pandn pause paveb pavgb pavgw "
+ "pavgusb pdistib pextrw pcmpeqb pcmpeqw pcmpeqd pcmpgtb "
+ "pcmpgtw pcmpgtd pf2id pf2iw pfacc pfadd pfcmpeq pfcmpge "
+ "pfcmpgt pfmax pfmin pfmul pmachriw pmaddwd pmagw pmaxsw "
+ "pmaxub pminsw pminub pmovmskb pmulhrwc pmulhriw "
+ "pmulhrwa pmulhuw pmulhw pmullw pmuludq pmvzb pmvnzb "
+ "pmvlzb pmvgezb pfnacc pfpnacc por prefetch prefetchw "
+ "prefetchnta prefetcht0 prefetcht1 prefetcht2 pfrcp "
+ "pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd "
+ "pf2iw pinsrw psadbw pshufd pshufhw pshuflw pshufw psllw "
+ "pslld psllq pslldq psraw psrad psrlw psrld psrlq psrldq "
+ "psubb psubw psubd psubq psubsb psubsw psubusb psubusw "
+ "psubsiw pswapd punpckhbw punpckhwd punpckhdq punpckhqdq "
+ "punpcklbw punpcklwd punpckldq punpcklqdq pxor rcpps "
+ "rcpss rsqrtps rsqrtss sfence shufpd shufps sqrtpd sqrtps "
+ "sqrtsd sqrtss stmxcsr subpd subps subsd subss ucomisd "
+ "ucomiss unpckhpd unpckhps unpcklpd unpcklps xorpd xorps")
+
+#---- Language Styling Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_ASM_DEFAULT, 'default_style'),
+ (stc.STC_ASM_CHARACTER, 'char_style'),
+ (stc.STC_ASM_COMMENT, 'comment_style'),
+ (stc.STC_ASM_COMMENTBLOCK, 'comment_style'),
+ (stc.STC_ASM_CPUINSTRUCTION, 'keyword_style'),
+ (stc.STC_ASM_DIRECTIVE, 'keyword3_style'),
+ (stc.STC_ASM_DIRECTIVEOPERAND, 'keyword4_style'),
+ (stc.STC_ASM_EXTINSTRUCTION, 'funct_style'),
+ (stc.STC_ASM_IDENTIFIER, 'default_style'),
+ (stc.STC_ASM_MATHINSTRUCTION, 'keyword_style'),
+ (stc.STC_ASM_NUMBER, 'number_style'),
+ (stc.STC_ASM_OPERATOR, 'operator_style'),
+ (stc.STC_ASM_REGISTER, 'keyword2_style'),
+ (stc.STC_ASM_STRING, 'string_style'),
+ (stc.STC_ASM_STRINGEOL, 'stringeol_style') ]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for MASM"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_ASM)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [MASM_CPU_INST, MASM_FPU_INST, MASM_REGISTERS, MASM_DIRECTIVES,
+ MASM_DIREC_OP, MASM_EXT_INST]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u';']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_matlab.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_matlab.py
new file mode 100644
index 0000000..4792aab
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_matlab.py
@@ -0,0 +1,91 @@
+###############################################################################
+# Name: matlab.py #
+# Purpose: Define Matlab and Octave syntax for highlighting and other features#
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: matlab.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Matlab and Octave
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _matlab.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+MATLAB_KW = (0, "break case catch continue else elseif end for function "
+ "global if otherwise persistent return switch try while")
+
+OCTAVE_KW = (0, "break case catch continue do else elseif end "
+ "end_unwind_protect endfor endif endswitch endwhile for "
+ "function endfunction global if otherwise persistent return "
+ "switch try until unwind_protect unwind_protect_cleanup while")
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_MATLAB_COMMAND, 'funct_style'),
+ (stc.STC_MATLAB_COMMENT, 'comment_style'),
+ (stc.STC_MATLAB_DEFAULT, 'default_style'),
+ (stc.STC_MATLAB_DOUBLEQUOTESTRING, 'string_style'),
+ (stc.STC_MATLAB_IDENTIFIER, 'default_style'),
+ (stc.STC_MATLAB_KEYWORD, 'keyword_style'),
+ (stc.STC_MATLAB_NUMBER, 'number_style'),
+ (stc.STC_MATLAB_OPERATOR, 'operator_style'),
+ (stc.STC_MATLAB_STRING, 'string_style')]
+
+#---- Extra Properties ----#
+FOLD = ('fold', '1')
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for MatLab and Octave"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ if self.LangId == synglob.ID_LANG_MATLAB:
+ self.SetLexer(stc.STC_LEX_MATLAB)
+ else:
+ self.SetLexer(stc.STC_LEX_OCTAVE)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ if self.LangId == synglob.ID_LANG_MATLAB:
+ return [MATLAB_KW]
+ elif self.LangId == synglob.ID_LANG_OCTAVE:
+ return [OCTAVE_KW]
+ else:
+ return list()
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ if self.LangId == synglob.ID_LANG_MATLAB:
+ return [u'%']
+ elif self.LangId == synglob.ID_LANG_OCTAVE:
+ return [u'#']
+ else:
+ return list()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mssql.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mssql.py
new file mode 100644
index 0000000..7f6c036
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mssql.py
@@ -0,0 +1,89 @@
+###############################################################################
+# Name: mssql.py #
+# Purpose: Define Microsoft SQL syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: mssql.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Microsoft SQL.
+@todo: too many to list
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _mssql.py 68355 2011-07-24 20:06:07Z CJP $"
+__revision__ = "$Revision: 68355 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Data Types
+MSSQL_DAT = (0, "")
+# System Tables
+MSSQL_SYS = (1, "")
+# Global Variables
+MSSQL_GLOB = (2, "")
+# Functions
+MSSQL_FUNC = (3, "")
+# System Stored Procedures
+MSSQL_SYSP = (4, "")
+# Operators
+MSSQL_OPS = (5, "")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_MSSQL_DEFAULT, 'default_style'),
+ (stc.STC_MSSQL_COMMENT, 'comment_style'),
+ (stc.STC_MSSQL_COLUMN_NAME, 'keyword_style'),
+ (stc.STC_MSSQL_COLUMN_NAME_2, 'keyword_style'),
+ (stc.STC_MSSQL_DATATYPE, 'keyword2_style'),
+ (stc.STC_MSSQL_DEFAULT_PREF_DATATYPE, 'class_style'),
+ (stc.STC_MSSQL_FUNCTION, 'keyword3_style'),
+ (stc.STC_MSSQL_GLOBAL_VARIABLE, 'global_style'),
+ (stc.STC_MSSQL_IDENTIFIER, 'default_style'),
+ (stc.STC_MSSQL_LINE_COMMENT, 'comment_style'),
+ (stc.STC_MSSQL_NUMBER, 'number_style'),
+ (stc.STC_MSSQL_OPERATOR, 'operator_style'),
+ (stc.STC_MSSQL_STATEMENT, 'keyword_style'),
+ (stc.STC_MSSQL_STORED_PROCEDURE, 'scalar2_style'),
+ (stc.STC_MSSQL_STRING, 'string_style'),
+ (stc.STC_MSSQL_SYSTABLE, 'keyword4_style'),
+ (stc.STC_MSSQL_VARIABLE, 'scalar_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_COMMENT = ("fold.comment", "1")
+FOLD_COMPACT = ("fold.compact", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for MS SQL"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_MSSQL)
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FOLD_COMPACT]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'--']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nasm.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nasm.py
new file mode 100644
index 0000000..3bb0318
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nasm.py
@@ -0,0 +1,138 @@
+###############################################################################
+# Name: nasm.py #
+# Purpose: Define NASM syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: nasm.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration file Netwide Assembly Code
+@todo: Add mmx, sse, 3dnow, cyrix, amd instruction sets
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _nasm.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+
+# NASM CPU Instructions
+NASM_CPU_INST = (0, "cmps movs lcs lods stos xlat aaa aad aam adc and bound "
+ "bsf bsr bswap bt btc btr bts call cbw cdq clc cld cmc cmp "
+ "cmpsb cmpsd cmpsw cmpxchg cmpxchg8b cpuid cwd cwde daa "
+ "das enter int iret iretw jcxz jecxz jmp lahf lds lea "
+ "leave les lfs lgs lodsb lodsd lodsw loop loope loopne "
+ "loopnz loopz lss mov movsb movsd movsw movsx movzx neg "
+ "nop not or popa popad popaw popf popfd popfw push pusha "
+ "pushd pushaw pushf pushfd pushfw rcl rcr retf ret retn "
+ "rol ror sahf sal sar sbb scasb scasd scasw shl shld shrd "
+ "stc std stosb stosd stosw test xchg xlatb xor arpl lar "
+ "lsl verr verw lldt sldt lgdt sgdt ltr str clts lock wait "
+ "ins outs in insb insw insd out outsb outsw outsd cli sti "
+ "lidt sidt hlt invd lmsw prefetcht0 prefetcht1 prefetcht2 "
+ "prefetchnta rsm sfence smsw sysenter sysexit ud2 wbinvd "
+ "invlpg int1 int3 rdmsr rdtsc rdpmc wrmsr add dec div idiv "
+ "imul inc mul sub xaddf2xm1 "
+ )
+
+# NASM FPU Instructions
+NASM_FPU_INST = (1, "fchs fclex fcom fcomp fdecstp fdisi feni ffree ficom fild "
+ "finit fist fld fldcw fldenv fldl2e fldl2e fldl2t fldlg2 "
+ "fldln2 fldpi fldz fsave fscale fsetpm frndint frstor "
+ "fscale fsetpm fstcw fstenv fsts fstsw ftst fucom fucomp "
+ "fxam fxch fxtract fyl2x fyl2xp1"" fabs fadd faddp fbld "
+ "fcos fdiv fdivr fiadd fidiv fimul fisub fmul fpatan fptan "
+ "fsin fsincos fsqrt fsub fsubr fsave fbstp")
+
+# NASM Registers
+NASM_REGISTERS = (2, "ah al ax bh bl bp bx ch cl cr0 cr2 cr3 cr4 cs cx dh di "
+ "dl dr0 dr1 dr2 dr3 dr6 dr7 ds dx eax ebp ebx ecx edi edx "
+ "es esi esp fs gs si sp ss st tr3 tr4 tr5 tr6 tr7 st0 st1 "
+ "st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 "
+ "xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7")
+
+# NASM Directives
+NASM_DIRECTIVES = (3, "DF EXTRN FWORD RESF TBYTE FAR NEAR SHORT BYTE WORD "
+ "QWORD DQWORD HWORD DHWORD TWORD CDECL FASTCALL NONE "
+ "PASCAL STDCALL DB DW DD DQ DDQ DT RESB RESW RESD RESQ "
+ "REST EXTERN GLOBAL COMMON __BITS__ __DATE__ __FILE__ "
+ "__FORMAT__ __LINE__ __NASM_MAJOR__ __NASM_MINOR__ "
+ "__NASM_VERSION__ __TIME__ TIMES ALIGN ALIGNB INCBIN "
+ "EQU NOSPLIT SPLIT ABSOLUTE BITS SECTION SEGMENT DWORD "
+ "ENDSECTION ENDSEGMENT __SECT__ ENDPROC EPILOGUE LOCALS "
+ "PROC PROLOGUE USES ENDIF ELSE ELIF ELSIF IF DO ENDFOR "
+ "ENDWHILE FOR REPEAT UNTIL WHILE EXIT ORG EXPORT GROUP "
+ "UPPERCASE SEG WRT LIBRARY _GLOBAL_OFFSET_TABLE_ "
+ "__GLOBAL_OFFSET_TABLE_ ..start ..got ..gotoff ..gotpc "
+ "..pit ..sym %define %idefine %xdefine %xidefine %undef "
+ "%assign %iassign %strlen %substr %macro %imacro "
+ "%endmacro %rotate .nolist %if %elif %else %endif %ifdef "
+ "%ifndef %elifdef %elifndef %ifmacro %ifnmacro "
+ "%elifnmacro %ifctk %ifnctk %elifctk %elifnctk %ifidn "
+ "%ifnidn %elifidn %elifnidn %ifidni %ifnidni %elifidni "
+ "%elifnidni %ifid %ifnid %elifid %elifnid %ifstr %ifnstr "
+ "%elifstr %elifnstr %ifnum %ifnnum %elifnum %elifnnum "
+ "%error %rep %endrep %exitrep %include %push %pop %repl "
+ "struct endstruc istruc at iend align alignb %arg "
+ "%stacksize %local %line bits use16 use32 section "
+ "absolute extern global common cpu org section group "
+ "import export %elifmacro ")
+
+NASM_DIREC_OP = (4, "a16 a32 o16 o32 byte word dword nosplit $ $$ seq wrt flat "
+ "large small .text .data .bss near far %0 %1 %2 %3 %4 %5 "
+ "%6 %7 %8 %9")
+
+NASM_EXT_INST = (5, "")
+
+#---- Language Styling Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_ASM_DEFAULT, 'default_style'),
+ (stc.STC_ASM_CHARACTER, 'char_style'),
+ (stc.STC_ASM_COMMENT, 'comment_style'),
+ (stc.STC_ASM_COMMENTBLOCK, 'comment_style'),
+ (stc.STC_ASM_CPUINSTRUCTION, 'keyword_style'),
+ (stc.STC_ASM_DIRECTIVE, 'keyword3_style'),
+ (stc.STC_ASM_DIRECTIVEOPERAND, 'keyword4_style'),
+ (stc.STC_ASM_EXTINSTRUCTION, 'funct_style'),
+ (stc.STC_ASM_IDENTIFIER, 'default_style'),
+ (stc.STC_ASM_MATHINSTRUCTION, 'keyword_style'),
+ (stc.STC_ASM_NUMBER, 'number_style'),
+ (stc.STC_ASM_OPERATOR, 'operator_style'),
+ (stc.STC_ASM_REGISTER, 'keyword2_style'),
+ (stc.STC_ASM_STRING, 'string_style'),
+ (stc.STC_ASM_STRINGEOL, 'stringeol_style') ]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for NASM"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_ASM)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [NASM_CPU_INST, NASM_FPU_INST, NASM_REGISTERS,
+ NASM_DIRECTIVES, NASM_DIREC_OP]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u';']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nonmem.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nonmem.py
new file mode 100644
index 0000000..23778a9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nonmem.py
@@ -0,0 +1,207 @@
+###############################################################################
+# Name: nonmem.py #
+# Purpose: Define NONMEM syntax for highlighting and other features #
+# Author: Robert McLeay <robert\@fearthecow.net> #
+# Copyright: (c) 2008 Cody Precord (staff\@editra.org) #
+# (c) 2008 Torsten Mohr (none_yet) #
+# (c) 2010 Robert McLeay (robert\@fearthecow.net) #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: nonmem.py
+AUTHOR: Cody Precord, Torsten Mohr, Robert McLeay
+@summary: Lexer configuration module for NONMEM control streams.
+
+"""
+
+__author__ = "Cody Precord <cprecord>, Torsten Mohr <none_yet>"
+__svnid__ = "$Id: _nonmem.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+from pygments.lexer import RegexLexer, include, bygroups
+from pygments.token import Token, Text, Comment, Operator, \
+ Keyword, Name, String, Number, Punctuation
+
+import re
+
+#Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+# Style Id's
+
+# Style Id's
+
+STC_NONMEM_DEFAULT, \
+STC_NONMEM_COMMENT, \
+STC_NONMEM_NUMBER, \
+STC_NONMEM_STRING, \
+STC_NONMEM_STRINGEOL, \
+STC_NONMEM_OPERATOR, \
+STC_NONMEM_NAME, \
+STC_NONMEM_ABSTRACTRULE, \
+STC_NONMEM_FEATURE, \
+STC_NONMEM_CROSSREF, \
+STC_NONMEM_PACKAGE, \
+STC_NONMEM_KEYWORD, \
+STC_NONMEM_KEYWORD_PSEUDO = range(13)
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Xtext Keywords
+KEYWORDS = ("grammar generate import returns enum terminal hidden with as current")
+TERMINALS = ("ID INT STRING")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (STC_NONMEM_DEFAULT, 'default_style'),
+ (STC_NONMEM_COMMENT, 'comment_style'),
+ (STC_NONMEM_NUMBER, 'number_style'),
+ (STC_NONMEM_STRING, 'string_style'),
+ (STC_NONMEM_STRINGEOL, 'stringeol_style'),
+ (STC_NONMEM_OPERATOR, 'operator_style'),
+ (STC_NONMEM_NAME, 'default_style'),
+ (STC_NONMEM_ABSTRACTRULE, 'keyword3_style'),
+ (STC_NONMEM_FEATURE, 'default_style'),
+ (STC_NONMEM_CROSSREF, 'class_style'),
+ (STC_NONMEM_PACKAGE, 'class_style'),
+ (STC_NONMEM_KEYWORD, 'keyword_style'),
+ (STC_NONMEM_KEYWORD_PSEUDO, 'keyword2_style'), ]
+
+NONMEM_KEYWORDS = ("ADVAN\d+ BLOCK COMP COND CONDITIONAL DEFDOSE DEFOBS "
+ "DOWHILE ELSE ENDDO ENDIF EXP FILE FIX FIXED ICALL IF "
+ "IGNORE INTER INTERACTION LOG MATRIX MAX MAXEVAL METHOD "
+ "NEWIND NOABORT NOAPPEND NOPRINT NOHEADER ONEHEADER PRINT "
+ "SIG SIGDIGITS SLOW SUBPROBLEMS THEN TOL TRANS1 TRANS2 "
+ "TRANS3 TRANS4 ONLYSIM ENDIF")
+NONMEM_PARAMS = "DADT ERR EPS ETA THETA"
+#NONMEM_SPECIAL = "\$COV $DATA $DES $ERROR $EST \$INPUT $MODEL $OMEGA $PRED \\$PK $PROB $PROBLEM $SIGMA $SIM $SUB $TABLE $THETA"
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for IssueLists
+ This class is primarily intended as an example to creating a custom
+ lexer.
+
+ """
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CONTAINER)
+ self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText)
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+#---- End Required Module Functions ----#
+
+def StyleText(_stc, start, end):
+ """Style the text
+ @param _stc: Styled text control instance
+ @param start: Start position
+ @param end: end position
+
+ """
+ for index, token, txt in lexer.get_tokens_unprocessed(_stc.GetTextRange(0, end)):
+# print index, token, txt
+ style = TOKEN_MAP.get(token, STC_NONMEM_DEFAULT)
+
+# print "Text=%s, len=%s" % (txt, len(txt))
+ _stc.StartStyling(index, 0x1f)
+ tlen = len(txt)
+ if tlen:
+ _stc.SetStyling(len(txt), style)
+
+TOKEN_MAP = { Token.String : STC_NONMEM_STRING,
+ Token.Comment.Multiline : STC_NONMEM_COMMENT,
+ Token.Comment.Single : STC_NONMEM_COMMENT,
+ Token.Operator : STC_NONMEM_OPERATOR,
+ Token.Punctuation : STC_NONMEM_OPERATOR,
+ Token.Number.Integer : STC_NONMEM_NUMBER,
+ Token.Keyword : STC_NONMEM_KEYWORD,
+ Token.Keyword.Pseudo: STC_NONMEM_KEYWORD_PSEUDO,
+ Token.Name : STC_NONMEM_NAME,
+ Token.Name.AbstractRule : STC_NONMEM_ABSTRACTRULE,
+ Token.Name.Feature : STC_NONMEM_FEATURE,
+ Token.Name.CrossRef : STC_NONMEM_CROSSREF,
+ Token.Name.Package : STC_NONMEM_PACKAGE,
+ Token.Name.Package.EMF : STC_NONMEM_PACKAGE}
+
+
+class NONMEMLexer(RegexLexer):
+ """
+ Nonmem lexer based on statefull RegexLexer from pygments library.
+ """
+
+ name = 'NONMEM'
+ aliases = ['nonmem']
+ filenames = ['*.ctl']
+ mimetypes = ['text/x-nonmem']
+
+ flags = re.MULTILINE | re.DOTALL # | re.UNICODE
+
+ #: optional Comment or Whitespace
+ #_ws = r'(?:\s|//.*?\n|/[*].*?[*]/)+'
+
+ def AltWords(words):
+ """Makes lexer rule for alternative words from the given words list.
+ @param words: string consisting of space separated words
+ @return: string in the form \\bword1\\b|\\bword2\\b|\\bword3\\b...
+ """
+ return "|".join([ "\\b%s\\b" % w for w in words.split()])
+
+ _ident = r'\^?[a-zA-Z_\$][a-zA-Z0-9_]*'
+
+ tokens = {
+ 'root': [
+ (include('first')),
+ (_ident + r'(\.' + _ident + r')+', Name.Package),
+ ('(' + _ident + r')(\s*)(returns)',
+ bygroups(Name.AbstractRule, Text.Whitespace, Keyword), 'parserrule'),
+ ('(' + _ident + r')(\s*)(:)',
+ bygroups(Name.AbstractRule, Text.Whitespace, Punctuation), 'parserrule'),
+ (_ident, Name),
+ ],
+ 'first': [
+ (r';[^\n]*$', Comment.Single),
+ (r'\$[A-Z]+', Name.Package),
+ (r'[ \t]+', Text.Whitespace),
+ (r'"(\\\\|\\"|[^"])*"', String),
+ (r"'(\\\\|\\'|[^'])*'", String),
+ (r'\*|\?|\+|!|\||=|\?=|\+=|\.\.|->', Operator),
+ (r'[()\[\]{}:]', Punctuation),
+ (r'[0-9]+', Number.Integer),
+ (AltWords(NONMEM_KEYWORDS), Keyword),
+ (AltWords(NONMEM_PARAMS), Keyword.Pseudo),
+ # (AltWords(NONMEM_SPECIAL), Name.Package),
+ ],
+ 'parserrule': [
+ (include('first')),
+ ('(' + _ident + r'(\.' + _ident + r')?)([ \t]*)(=|\?=|\+=)',
+ bygroups(Name.Feature, Text.Whitespace, Operator)),
+ (_ident + r'(\.' + _ident + r')+', Name.Package),
+ (_ident, Name.CrossRef),
+ ],
+ }
+
+lexer = NONMEMLexer()
+
+if __name__=='__main__':
+ import codecs, sys
+ ftext = codecs.open(sys.argv[1], "r", "utf-8")
+ text = ftext.read()
+ ftext.close()
+ line=1
+ for index, token, txt in lexer.get_tokens_unprocessed(text):
+ if token is Token.EndOfLine:
+ line += 1
+ print line, token, txt
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nsis.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nsis.py
new file mode 100644
index 0000000..169bfc9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nsis.py
@@ -0,0 +1,160 @@
+###############################################################################
+# Name: nsis.py #
+# Purpose: Define NSIS syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: nsis.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Nullsoft Installer Scripts.
+@todo: Add User Defined KW
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _nsis.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# NSIS Functions
+NSIS_FUNCT = (0, "!addincludedir !addplugindir MakeNSIS Portions Contributors: "
+ "Abort AddBrandingImage AddSize AutoCloseWindow BGFont "
+ "BrandingText BringToFront Call CallInstDLL Caption ChangeUI "
+ "ClearErrors ComponentText GetDLLVersion GetDLLVersionLocal "
+ "GetFileTime GetFileTimeLocal CopyFiles CRCCheck FileRead "
+ "CreateFont CreateShortCut SetDatablockOptimize DeleteINISec "
+ "DeleteINIStr DeleteRegKey DeleteRegValue Delete DetailPrint "
+ "DirText DirShow DirVar DirVerify GetInstDirError BGGradient"
+ "AllowRootDirInstall CheckBitmap EnableWindow EnumRegKey "
+ "EnumRegValue Exch Exec ExecWait ExecShell ExpandEnvStrings "
+ "FindWindow FindClose FindFirst FindNext File FileBufSize "
+ "FlushINI ReserveFile FileClose FileErrorText FileOpen IntCmp "
+ "FileWrite FileReadByte FileWriteByte FileSeek Function Page "
+ "GetDlgItem GetFullPathName GetTempFileName HideWindow Icon "
+ "IfErrors IfFileExists IfRebootFlag IfSilent InstallDirRegKey "
+ "InstallColors InstallDir InstProgressFlags InstType IntOp "
+ "IntCmpU IntFmt IsWindow Goto LangString LangStringUP Return "
+ "LicenseForceSelection LicenseLangString LicenseText "
+ "LoadLanguageFile LogSet LogText MessageBox Nop Name OutFile "
+ "PageCallbacks PageEx PageExEnd Pop Push Quit ReadINIStr "
+ "ReadRegDWORD ReadRegStr ReadEnvStr Reboot RegDLL Rename "
+ "RMDir Section SectionEnd SectionIn SubSection SectionGroup "
+ "SubSectionEnd SectionGroupEnd SearchPath SectionSetFlags "
+ "SectionGetFlags SectionSetInstTypes SectionGetInstTypes "
+ "SectionGetText SectionSetText SectionGetSize SectionSetSize "
+ "GetCurInstType SetCurInstType InstTypeSetText SetCompress"
+ "SendMessage SetAutoClose SetCtlColors SetBrandingImage "
+ "SetCompressor SetCompressorDictSize SetCompressionLevel "
+ "SetDateSave SetDetailsView SetDetailsPrint SetErrors "
+ "GetErrorLevel SetFileAttributes SetFont SetOutPath "
+ "SetPluginUnload SetRebootFlag SetShellVarContext SetSilent "
+ "ShowInstDetails ShowUninstDetails ShowWindow SilentInstall "
+ "SilentUnInstall Sleep StrCmp StrCpy StrLen SubCaption "
+ "UninstallExeName UninstallCaption UninstallIcon UninstPage "
+ "UninstallText UninstallSubCaption UnRegDLL WindowIcon "
+ "WriteRegBin WriteRegDWORD WriteRegStr WriteRegExpandStr "
+ "WriteUninstaller XPStyle !packhdr !system !execute !echo "
+ "!include !cd !ifdef !ifndef !endif !define !undef !else "
+ "!warning !error !verbose !macro !macroend !insertmacro "
+ "!ifmacrondef MiscButtonText DetailsButtonText "
+ "InstallButtonText SpaceTexts CompletedText InitPluginsDir "
+ "GetLabelAddress GetCurrentAddress !AddPluginDir LockWindow "
+ "AllowSkipFiles Var VIAddVersionKey VIProductVersion "
+ "ShowUnInstDetails WriteIniStr CreateDirectory FunctionEnd "
+ "IfAbort LicenseData LicenseBkColor InstTypeGetText "
+ "SetErrorLevel SetOverwrite WriteINIStr !AddIncludeDir "
+ "!ifmacrodef UninstallButtonText GetFunctionAddress ")
+
+# NSIS Variables/Constants
+NSIS_VAR = (1, "$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $R0 $R1 $R2 $R3 $R4 $R5 $R6 $R7 "
+ "$R8 $R9 $\t $\" $\' $\` $VARNAME $0, $INSTDIR $OUTDIR $CMDLINE "
+ "$LANGUAGE $PROGRAMFILES $COMMONFILES $DESKTOP $EXEDIR "
+ "${NSISDIR} $WINDIR $SYSDIR $TEMP $STARTMENU $SMPROGRAMS "
+ "$SMSTARTUP $QUICKLAUNCH $DOCUMENTS $SENDTO $RECENT $FAVORITES "
+ "$MUSIC $PICTURES $VIDEOS $NETHOOD $FONTS $TEMPLATES $APPDATA "
+ "$PRINTHOOD $INTERNET_CACHE $COOKIES $HISTORY $PROFILE "
+ "$ADMINTOOLS $RESOURCES $RESOURCES_LOCALIZED $CDBURN_AREA "
+ "$HWNDPARENT $PLUGINSDIR $$ $\r $\n")
+
+# NSIS Lables (Attributes)
+NSIS_LBL = (2, "ARCHIVE FILE_ATTRIBUTE_ARCHIVE FILE_ATTRIBUTE_HIDDEN LEFT "
+ "FILE_ATTRIBUTE_NORMAL FILE_ATTRIBUTE_OFFLINE lastused HKCR "
+ "FILE_ATTRIBUTE_SYSTEM FILE_ATTRIBUTE_TEMPORARY HIDDEN HKCC "
+ "HKCU HKDD HKEY_CLASSES_ROOT HKEY_CURRENT_CONFIG IDYES SYSTEM "
+ "HKEY_DYN_DATA HKEY_LOCAL_MACHINE MB_ICONQUESTION OFFLINE "
+ "HKLM HKPD HKU IDABORT IDCANCEL IDIGNORE IDNO IDOK IDRETRY "
+ "MB_ABORTRETRYIGNORE MB_DEFBUTTON1 MB_DEFBUTTON2 MB_DEFBUTTON3 "
+ "MB_DEFBUTTON4 MB_ICONEXCLAMATION MB_ICONINFORMATION normal off "
+ "MB_ICONSTOP MB_OK MB_OKCANCEL MB_RETRYCANCEL MB_RIGHT listonly "
+ "MB_SETFOREGROUND MB_TOPMOST MB_YESNO MB_YESNOCANCEL NORMAL "
+ "READONLY SW_SHOWMAXIMIZED SW_SHOWMINIMIZED SW_SHOWNORMAL "
+ "TEMPORARY auto colored false force hide ifnewer nevershow "
+ "on show silent silentlog smooth true try lzma zlib bzip2 none "
+ "textonly both top left bottom right license components "
+ "instfiles uninstConfirm custom all leave current ifdiff "
+ "RIGHT CENTER dlg_id ALT CONTROL EXT SHIFT open print manual "
+ "alwaysoff FILE_ATTRIBUTE_READONLY HKEY_CURRENT_USER directory "
+ "HKEY_PERFORMANCE_DATA HKEY_USERS ")
+
+# NSIS User Defined (Not sure need help)
+NSIS_DEF = (3, "")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_NSIS_DEFAULT, 'default_style'),
+ (stc.STC_NSIS_COMMENT, 'comment_style'),
+ (stc.STC_NSIS_FUNCTION, 'funct_style'),
+ (stc.STC_NSIS_FUNCTIONDEF, 'keyword_style'),
+ (stc.STC_NSIS_IFDEFINEDEF, 'pre_style'),
+ (stc.STC_NSIS_LABEL, 'class_style'),
+ (stc.STC_NSIS_MACRODEF, 'pre_style'),
+ (stc.STC_NSIS_NUMBER, 'number_style'),
+ (stc.STC_NSIS_SECTIONDEF, 'keyword_style'),
+ (stc.STC_NSIS_STRINGDQ, 'string_style'),
+ (stc.STC_NSIS_STRINGLQ, 'string_style'),
+ (stc.STC_NSIS_STRINGRQ, 'string_style'),
+ (stc.STC_NSIS_STRINGVAR, 'string_style'),
+ (stc.STC_NSIS_SUBSECTIONDEF, 'keyword_style'),
+ (stc.STC_NSIS_USERDEFINED, 'pre_style'),
+ (stc.STC_NSIS_VARIABLE, 'scalar_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for NSIS"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_NSIS)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [NSIS_FUNCT, NSIS_VAR, NSIS_LBL]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u';']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ooc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ooc.py
new file mode 100644
index 0000000..8a6e3f9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ooc.py
@@ -0,0 +1,68 @@
+###############################################################################
+# Name: ooc.py #
+# Purpose: Define OOC Syntax Highlighting Support and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2010 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: ooc.py
+@author: Cody Precord
+@summary: Lexer configuration file for OOC (Out of Class)
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: $"
+__revision__ = "$Revision: $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local imports
+import synglob
+import syndata
+import _cpp
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+KEYWORDS = (0, "class cover interface implement func abstract extends from "
+ "this super new const final static include import use extern "
+ "inline proto break continue fallthrough operator if else for "
+ "while do switch case as in version return true false null "
+ "default")
+
+TYPES = (1, "Int Int8 Int16 Int32 Int64 Int80 Int128 UInt UInt8 UInt16 UInt32 "
+ "UInt64 UInt80 UInt128 Octet Short UShort Long ULong LLong ULLong "
+ "Float Double LDouble Float32 Float64 Float128 Char UChar WChar "
+ "String Void Pointer Bool SizeT This")
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for many OOC"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List"""
+ return [KEYWORDS, TYPES, _cpp.DOC_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return _cpp.SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set"""
+ return [_cpp.FOLD, _cpp.FOLD_COM]
+
+ def GetCommentPattern(self):
+ """Return comment pattern for OOC"""
+ return [u'//']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pascal.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pascal.py
new file mode 100644
index 0000000..aee8569
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pascal.py
@@ -0,0 +1,124 @@
+###############################################################################
+# Name: pascal.py #
+# Purpose: Define Pascal syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: pascal.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Pacal.
+@todo: Add Support for Turbo Pascal
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _pascal.py 66108 2010-11-10 21:04:54Z CJP $"
+__revision__ = "$Revision: 66108 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Pascal Keywords
+PAS_KEYWORDS = (0, "and array asm begin case cdecl class const constructor "
+ "default destructor div do downto else end end. except exit "
+ "exports external far file finalization finally for "
+ "function goto if implementation in index inherited "
+ "initialization inline interface label library message mod "
+ "near nil not object of on or out overload override packed "
+ "pascal private procedure program property protected public "
+ "published raise read record register repeat resourcestring "
+ "safecall set shl shr stdcall stored string then threadvar "
+ "to try type unit until uses var virtual while with write "
+ "xor")
+
+# Pascal Classwords (Types)
+PAS_CLASSWORDS = (1, "array boolean char integer file pointer real set string "
+ "text variant write read default public protected private "
+ "property published stored")
+
+# Pascal Std Functions
+PAS_FUNCT = ("pack unpack Dispose New Abs Arctan Cos Exp Ln Sin Sqr Sqrt Eof "
+ "Eoln Write Writeln Input Output Get Page Put Odd Pred Succ Chr "
+ "Ord Round Trunc")
+
+#---- Syntax Style Specs ----#
+if wx.VERSION >= (2, 9, 0, 0, ''):
+ SYNTAX_ITEMS = [ (stc.STC_PAS_ASM, 'default_style'), #TODO
+ (stc.STC_PAS_CHARACTER, 'char_style'),
+ (stc.STC_PAS_COMMENT, 'comment_style'),
+ (stc.STC_PAS_COMMENT2, 'comment_style'),
+ (stc.STC_PAS_COMMENTLINE, 'comment_style'),
+ (stc.STC_PAS_DEFAULT, 'default_style'),
+ (stc.STC_PAS_HEXNUMBER, 'number_style'), #TODO?
+ (stc.STC_PAS_IDENTIFIER, 'default_style'),
+ (stc.STC_PAS_NUMBER, 'number_style'),
+ (stc.STC_PAS_OPERATOR, 'operator_style'),
+ (stc.STC_PAS_PREPROCESSOR, 'pre_style'),
+ (stc.STC_PAS_PREPROCESSOR2, 'default_style'), #TODO
+ (stc.STC_PAS_STRING, 'string_style'),
+ (stc.STC_PAS_STRINGEOL, 'stringeol_style'),
+ (stc.STC_PAS_WORD, 'keyword_style'), ]
+else:
+ # Pascal Lexer Uses C values, but need to adjust styles accordingly
+ SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'),
+ (stc.STC_C_COMMENT, 'comment_style'),
+ (stc.STC_C_COMMENTDOC, 'comment_style'),
+ (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'),
+ (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTLINEDOC, 'comment_style'),
+ (stc.STC_C_CHARACTER, 'char_style'),
+ (stc.STC_C_GLOBALCLASS, 'global_style'),
+ (stc.STC_C_IDENTIFIER, 'default_style'),
+ (stc.STC_C_NUMBER, 'number_style'),
+ (stc.STC_C_OPERATOR, 'operator_style'),
+ (stc.STC_C_PREPROCESSOR, 'pre_style'),
+ (stc.STC_C_REGEX, 'pre_style'),
+ (stc.STC_C_STRING, 'string_style'),
+ (stc.STC_C_STRINGEOL, 'stringeol_style'),
+ (stc.STC_C_UUID, 'pre_style'),
+ (stc.STC_C_VERBATIM, 'number2_style'),
+ (stc.STC_C_WORD, 'keyword_style'),
+ (stc.STC_C_WORD2, 'keyword2_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FLD_COMMENT = ("fold.comment", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Pascal"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_PASCAL)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [PAS_KEYWORDS, PAS_CLASSWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FLD_COMMENT]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'{', u'}']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_perl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_perl.py
new file mode 100644
index 0000000..d705947
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_perl.py
@@ -0,0 +1,147 @@
+###############################################################################
+# Name: perl.py #
+# Purpose: Define Perl syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: perl.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Perl.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _perl.py 66108 2010-11-10 21:04:54Z CJP $"
+__revision__ = "$Revision: 66108 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Perl Keywords
+PERL_KW = (0, "if elseif unless else switch eq ne gt lt ge le cmp not and or "
+ "xor while for foreach do until continue defined undef and or "
+ "not bless ref BEGIN END my local our goto return last next redo "
+ "chomp chop chr crypt index lc lcfirst length org pack reverse "
+ "rindex sprintf substr uc ucfirst pos quotemet split study abs "
+ "atan2 cos exp hex int log oct rand sin sqrt srand spice unshift "
+ "shift push pop split join reverse grep map sort unpack each "
+ "exists keys values tie tied untie carp confess croak dbmclose "
+ "dbmopen die syscall binmode close closedir eof fileno getc "
+ "lstat print printf readdir readline readpipe rewinddir select "
+ "stat tell telldir write fcntl flock ioctl open opendir read "
+ "seek seekdir sysopen sysread sysseek syswrite truncate pack vec "
+ "chdir chmod chown chroot glob link mkdir readlink rename rmdir "
+ "symlink umask ulink utime caller dump eval exit wanarray "
+ "import alarm exec fork getpgrp getppid getpriority kill pipe "
+ "setpgrp setpriority sleep system times wait waitpid accept "
+ "bind connect getpeername getsockname getsockopt listen recv "
+ "send setsockopt shutdown socket socketpair msgctl msgget msgrcv "
+ "msgsnd semctl semget semop shmctl shmget shmread shmwrite "
+ "endhostent endnetent endprooent endservent gethostbyaddr "
+ "gethostbyname gethostent getnetbyaddr getnetbyname getnetent "
+ "getprotobyname getprotobynumber getprotoent getervbyname time "
+ "getservbyport getservent sethostent setnetent setprotoent "
+ "setservent getpwuid getpwnam getpwent setpwent endpwent "
+ "getgrgid getlogin getgrnam setgrent endgrent gtime localtime "
+ "times warn formline reset scalar delete prototype lock new "
+ "NULL __FILE__ __LINE__ __PACKAGE__ __DATA__ __END__ AUTOLOAD "
+ "BEGIN CORE DESTROY END EQ GE GT INIT LE LT NE CHECK use sub "
+ "elsif require getgrent ")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_PL_DEFAULT, 'default_style'),
+ (stc.STC_PL_ARRAY, 'array_style'),
+ (stc.STC_PL_BACKTICKS, 'btick_style'),
+ (stc.STC_PL_CHARACTER, 'char_style'),
+ (stc.STC_PL_COMMENTLINE, 'comment_style'),
+ (stc.STC_PL_DATASECTION, 'default_style'), # STYLE ME
+ (stc.STC_PL_ERROR, 'error_style'),
+ (stc.STC_PL_HASH, 'global_style'),
+ (stc.STC_PL_HERE_DELIM, 'here_style'),
+ (stc.STC_PL_HERE_Q, 'here_style'),
+ (stc.STC_PL_HERE_QQ, 'here_style'),
+ (stc.STC_PL_HERE_QX, 'here_style'),
+ (stc.STC_PL_IDENTIFIER, 'default_style'),
+ (stc.STC_PL_LONGQUOTE, 'default_style'), # STYLE ME
+ (stc.STC_PL_NUMBER, 'number_style'),
+ (stc.STC_PL_OPERATOR, 'operator_style'),
+ (stc.STC_PL_POD, 'comment_style'),
+ (stc.STC_PL_PREPROCESSOR, 'pre_style' ),
+ (stc.STC_PL_PUNCTUATION, 'default_style'), # STYLE ME
+ (stc.STC_PL_REGEX, 'regex_style'),
+ (stc.STC_PL_REGSUBST, 'regex_style'),
+ (stc.STC_PL_SCALAR, 'scalar_style'),
+ (stc.STC_PL_STRING, 'string_style'),
+ (stc.STC_PL_STRING_Q, 'string_style'),
+ (stc.STC_PL_STRING_QQ, 'string_style'),
+ (stc.STC_PL_STRING_QR, 'string_style'),
+ (stc.STC_PL_STRING_QW, 'string_style'),
+ (stc.STC_PL_STRING_QX, 'string_style'),
+ (stc.STC_PL_SYMBOLTABLE, 'default_style'), # STYLE ME
+ (stc.STC_PL_WORD, 'keyword_style') ]
+
+if wx.VERSION >= (2, 9, 0, 0, ''):
+ SYNTAX_ITEMS.append((stc.STC_PL_FORMAT, 'default_style')) #TODO
+ SYNTAX_ITEMS.append((stc.STC_PL_FORMAT_IDENT, 'default_style')) #TODO
+ SYNTAX_ITEMS.append((stc.STC_PL_SUB_PROTOTYPE, 'default_style')) #TODO
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FLD_COMPACT = ("fold.compact", "1")
+FLD_COMMENT = ("fold.comment", "1")
+FLD_POD = ("fold.perl.pod", "1")
+FLD_PKG = ("fold.perl.package", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Perl"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_PERL)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [PERL_KW]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#']
+
+#---- Syntax Modules Internal Functions ----#
+def KeywordString(option=0):
+ """Returns the specified Keyword String
+ @note: not used by most modules
+
+ """
+ if option == synglob.ID_LANG_PERL:
+ return PERL_KW[1]
+ else:
+ return u''
+
+#---- End Syntax Modules Internal Functions ----#
+
+#-----------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_php.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_php.py
new file mode 100644
index 0000000..e81e3eb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_php.py
@@ -0,0 +1,448 @@
+###############################################################################
+# Name: php.py #
+# Purpose: Define PHP syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: php.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for PHP.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _php.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _html
+from _cpp import AutoIndenter
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# PHP Keywords
+PHP_KEYWORDS = ("__LINE__ __FILE__ __FUNCTION__ __CLASS__ __METHOD__ declare "
+ "else enddeclare endswitch elseif endif if switch as do endfor "
+ "endforeach endwhile for foreach while case default switch "
+ "break continue var bool boolean int integer real "
+ "double float string array NULL extends global static "
+ "new true false function "
+ "class object self final public private protected try catch "
+ "throw abstract parent interface implements "
+ # Language Constructs
+ "die echo empty exit eval include include_once isset list "
+ "require require_once return print unset")
+
+# PHP Standard Functions/Methods
+# (roughly based off of PHP Pocket Reference by O'Reilly)
+PHP_FUNC = ("__construct __autoload __destruct __get __set __isset __unset "
+ "__call __sleep __wakeup __toString __set_state __clone "
+ "apache_child_terminate apache_lookup_uri apache_note "
+ "apache_request_headers apache_response_headers apache_setenv "
+ "ascii2ebcdic ebcdic2ascii getallheaders virtual jewishtojd "
+ "array_change_key_case array_chunk array_count_values "
+ "array_diff_assoc array_diff array_fill array_filter array_flip "
+ "array_intersect_assoc array_intersect array_key_exists array_keys "
+ "array_map array_merge_recursive array_merge array_multisort "
+ "array_pad array_pop array_push array_rand array_reduce array "
+ "array_reverse array_search array_shift array_slice array_splice "
+ "array_sum array_unique array_unshift array_values array_walk "
+ "arsort asort compact count current each end extract in_array key "
+ "krsort ksort natcasesort natsort next pos prev range reset "
+ "rsort shuffle sizeof sort uasort uksort usort aspell_check "
+ "aspell_new aspell_suggest bcadd bccomp bcdiv bcmod bcmul bcpow "
+ "bcpowmod bcscale bcsqrt bcsub bzclose bzcompress bzdecompress "
+ "bzerrno bzerror bzerrstr bzflush bzopen bzread bzwrite "
+ "cal_days_in_month cal_from_jd cal_info cal_to_jd easter_date "
+ "easter_days frenchtojd gregoriantojd jddayofweek jdmonthname "
+ "jdtofrench jdtogregorian jdtojewish jdtojulian jdtounix "
+ "juliantojd unixtojd ccvs_add ccvs_auth ccvs_command ccvs_count "
+ "ccvs_delete ccvs_done ccvs_init ccvs_lookup ccvs_new ccvs_report "
+ "ccvs_return ccvs_reverse ccvs_sale ccvs_status ccvs_textvalue "
+ "ccvs_void call_user_method_array call_user_method class_exists "
+ "get_class_methods get_class_vars get_class get_declared_classes "
+ "get_object_vars get_parent_class is_a is_subclass_of com_load "
+ "com_addref com_get com_invoke com_isenum com_load_typelib "
+ "com_propget com_propput com_propset com_release com_set "
+ "cpdf_add_annotation cpdf_add_outline cpdf_arc cpdf_begin_text "
+ "cpdf_circle cpdf_clip cpdf_close cpdf_closepath_fill_stroke "
+ "cpdf_closepath_stroke cpdf_closepath cpdf_continue_text "
+ "cpdf_end_text cpdf_fill_stroke cpdf_fill cpdf_finalize_page "
+ "cpdf_finalize cpdf_global_set_document_limits cpdf_import_jpeg "
+ "cpdf_lineto cpdf_moveto cpdf_newpath cpdf_open cpdf_output_buffer "
+ "cpdf_page_init cpdf_place_inline_image cpdf_rect cpdf_restore "
+ "cpdf_rlineto cpdf_rmoveto cpdf_rotate_text cpdf_rotate "
+ "cpdf_save_to_file cpdf_save cpdf_scale cpdf_set_action_url "
+ "cpdf_set_char_spacing cpdf_set_creator cpdf_set_current_page "
+ "cpdf_set_font_directories cpdf_set_font_map_file cpdf_set_font "
+ "cpdf_set_horiz_scaling cpdf_set_keywords cpdf_set_leading "
+ "cpdf_set_page_animation cpdf_set_subject cpdf_set_text_matrix "
+ "cpdf_set_text_pos cpdf_set_text_rendering cpdf_set_text_rise "
+ "cpdf_set_title cpdf_set_viewer_preferences cpdf_set_word_spacing "
+ "cpdf_setdash cpdf_setflat cpdf_setgray_fill cpdf_setgray_stroke "
+ "cpdf_setgray cpdf_setlinecap cpdf_setlinejoin cpdf_setlinewidth "
+ "cpdf_setmiterlimit cpdf_setrgbcolor_fill cpdf_setrgbcolor_stroke "
+ "cpdf_setrgbcolor cpdf_show_xy cpdf_show cpdf_stringwidth "
+ "cpdf_text cpdf_translate crack_check crack_closedict cpdf_curveto "
+ "crack_getlastmessage crack_opendict ctype_alnum ctype_alpha "
+ "ctype_cntrl ctype_digit ctype_graph ctype_lower ctype_print "
+ "ctype_punct ctype_space ctype_upper ctype_xdigit curl_close "
+ "curl_errno curl_error curl_exec curl_getinfo curl_init chgrp "
+ "curl_version checkdate date getdate gettimeofday gmdate gmmktime "
+ "gmstrftime localtime microtime mktime strftime strtotime time "
+ "dba_close dba_delete dba_exists dba_fetch dba_firstkey filetype "
+ "dba_insert dba_list dba_nextkey dba_open dba_optimize dba_popen "
+ "dba_replace dba_sync dbase_add_record dbase_close dbase_create "
+ "dbase_delete_record dbase_get_record_with_names dbase_get_record "
+ "dbase_numfields dbase_numrecords dbase_open dbase_pack filectime "
+ "dbase_replace_record dblist dbmclose dbmdelete dbmexists dbmfetch "
+ "dbmfirstkey dbminsert dbmnextkey dbmopen dbmreplace basename "
+ "chmod chown clearstatcache copy delete dirname disk_free_space "
+ "disk_total_space diskfreespace fclose feof fflush fgetc fgetcsv "
+ "fgets fgetss file_exists file_get_contents file fileatime ftell "
+ "filegroup fileinode filemtime fileowner fileperms filesize popen "
+ "flock fnmatch fopen fpassthru fputs fread fscanf fseek fstat stat "
+ "ftruncate fwrite glob is_dir is_executable is_file is_link "
+ "is_readable is_uploaded_file is_writable is_writeable link "
+ "lstat mkdir move_uploaded_file parse_ini_file pathinfo pclose "
+ "readfile readlink realpath rename rewind rmdir set_file_buffer "
+ "symlink tempnam tmpfile touch umask unlink ftp_cdup ftp_chdir "
+ "ftp_close ftp_connect ftp_delete ftp_exec ftp_fget ftp_fput "
+ "ftp_get_option ftp_get ftp_login ftp_mdtm ftp_mkdir textdomain "
+ "ftp_nb_fget ftp_nb_fput ftp_nb_get ftp_nb_put ftp_nlist ftp_pasv "
+ "ftp_put ftp_pwd ftp_quit ftp_rawlist ftp_rename ftp_rmdir checkin "
+ "ftp_set_option ftp_site ftp_size ftp_ssl_connect ftp_systype "
+ "call_user_func_array call_user_func create_function func_get_arg "
+ "func_get_args func_num_args function_exists get_defined_functions "
+ "register_shutdown_function register_tick_function method_exists "
+ "unregister_tick_function bind_textdomain_codeset bindtextdomain "
+ "dcgettext dcngettext dgettext dngettext gettext ngettext "
+ "gmp_abs gmp_add gmp_and gmp_clrbit gmp_cmp gmp_com gmp_div_q "
+ "gmp_div_qr gmp_div_r gmp_div gmp_divexact gmp_fact gmp_gcd "
+ "gmp_hamdist gmp_init gmp_intval gmp_invert gmp_jacobi gmp_gcdext "
+ "gmp_mod gmp_mul gmp_neg gmp_or gmp_perfect_square gmp_popcount "
+ "gmp_pow gmp_powm gmp_prob_prime gmp_random gmp_scan0 gmp_scan1 "
+ "gmp_setbit gmp_sign gmp_sqrt gmp_sqrtrm gmp_strval gmp_sub "
+ "header headers_sent setcookie hw_api_attribute hwapi_hgcsp "
+ "hw_api_content hw_api_object key langdepvalue value values insert "
+ "checkout children mimetype read content copy dbstat dcstat "
+ "dstofsrcanchors count reason find ftstat hwstat identify info "
+ "insertanchor insertcollection insertdocument link lock move "
+ "attreditable count insert remove title value object dstanchors "
+ "parents description type remove replace setcommitedversion assign "
+ "srcanchors srcsofdst unlock user userlist iconv_get_encoding "
+ "iconv_set_encoding iconv ob_iconv_handler exif_imagetype gmp_xor "
+ "exif_read_data exif_thumbnail gd_info getimagesize cpdf_stroke "
+ "image_type_to_mime_type image2wbmp imagealphablending imagearc "
+ "imagechar imagecharup imagecolorallocate imagecolorallocatealpha "
+ "imagecolorat imagecolorclosest imagecolorclosestalpha curl_setopt "
+ "imagecolorclosesthwb imagecolordeallocate imagecolorexact "
+ "imagecolorexactalpha imagecolorresolve imagecolorresolvealpha "
+ "imagecolorset imagecolorsforindex imagecolorstotal dba_handlers "
+ "imagecolortransparent imagecopy imagecopymerge imagecopymergegray "
+ "imagecopyresampled imagecopyresized imagecreate objectbyanchor "
+ "imagecreatefromgd2part imagecreatefromgd imagecreatefromgif "
+ "imagecreatefromjpeg imagecreatefrompng imagecreatefromstring "
+ "imagecreatefromwbmp imagecreatefromxbm imagecreatefromxpm "
+ "imagecreatetruecolor imagedashedline imagedestroy imageellipse "
+ "imagefill imagefilledarc imagefilledellipse imagefilledpolygon "
+ "imagefilledrectangle imagefilltoborder imagefontheight "
+ "imageftbbox imagefttext imagegammacorrect imagegd2 imagegd "
+ "imageinterlace imagejpeg imageline imageloadfont imagepalettecopy "
+ "imagepng imagepolygon imagepsbbox imagepscopyfont imagefontwidth "
+ "imagepsextendfont imagepsfreefont imagepsloadfont gmp_legendre "
+ "imagepstext imagerectangle imagerotate imagesetbrush imagegif "
+ "imagesetstyle imagesetthickness imagesettile imagestring "
+ "imagestringup imagesx imagesy imagetruecolortopalette "
+ "imagettftext imagetypes imagewbmp iptcembed iptcparse jpeg2wbmp "
+ "png2wbmp read_exif_data imap_8bit imap_alerts imap_append "
+ "imap_binary imap_body imap_bodystruct imap_check imap_base64 "
+ "imap_close imap_createmailbox imap_delete imap_deletemailbox "
+ "imap_errors imap_expunge imap_fetch_overview imap_fetchbody "
+ "imap_fetchheader imap_fetchstructure imap_get_quota imagettfbbox "
+ "imap_getmailboxes imap_getsubscribed imap_header imap_headerinfo "
+ "imap_headers imap_last_error imap_list imap_listmailbox "
+ "imap_listsubscribed imap_lsub imap_mail_compose imap_mail_copy "
+ "imap_mail_move imap_mail imap_mailboxmsginfo imap_listscan "
+ "imap_msgno imap_num_msg imap_num_recent imap_open imap_ping "
+ "imap_renamemailbox imap_reopen imap_rfc822_parse_adrlist linkinfo "
+ "imap_rfc822_parse_headers imap_rfc822_write_address imap_qprint "
+ "imap_search imap_set_quota imap_setacl imap_setflag_full "
+ "imap_status imap_subscribe imap_thread imap_uid imap_undelete "
+ "imap_unsubscribe imap_utf7_decode imap_utf7_encode imap_utf8 "
+ "assert_options assert dl extension_loaded get_cfg_var imap_sort "
+ "get_defined_constants get_extension_funcs get_included_files "
+ "get_loaded_extensions get_magic_quotes_gpc get_current_user "
+ "get_required_files getenv getlastmod getmygid getmyinode getmypid "
+ "getmyuid getopt getrusage ini_alter ini_get_all ini_get "
+ "ini_set php_ini_scanned_files php_logo_guid php_sapi_name "
+ "phpcredits phpinfo phpversion putenv set_magic_quotes_runtime "
+ "set_time_limit version_compare zend_logo_guid zend_version "
+ "ldap_8859_to_t61 ldap_add ldap_bind ldap_close ldap_compare "
+ "ldap_connect ldap_count_entries ldap_delete ldap_dn2ufn php_uname "
+ "ldap_errno ldap_error ldap_explode_dn ldap_first_attribute "
+ "ldap_first_entry ldap_first_reference ldap_free_result "
+ "ldap_get_attributes ldap_get_dn ldap_get_entries ldap_get_option "
+ "ldap_get_values_len ldap_get_values ldap_list ldap_mod_add "
+ "ldap_mod_del ldap_mod_replace ldap_modify ldap_next_attribute "
+ "ldap_next_entry ldap_next_reference ldap_parse_reference hypot "
+ "ldap_parse_result ldap_read ldap_rename ldap_search ldap_err2str "
+ "ldap_set_option ldap_set_rebind_proc ldap_sort ldap_start_tls "
+ "ldap_t61_to_8859 ldap_unbind ezmlm_hash mail abs acos acosh asin "
+ "asinh atan2 atan atanh base_convert bindec ceil cos cosh decbin "
+ "dechex decoct deg2rad exp expm1 floor fmod getrandmax hexdec "
+ "is_finite is_infinite is_nan lcg_value log10 log1p log max min "
+ "mt_getrandmax mt_rand mt_srand octdec pi pow rad2deg rand round "
+ "sin sinh sqrt srand tan tanh mb_convert_case mb_convert_encoding "
+ "mb_convert_kana mb_convert_variables mb_decode_mimeheader "
+ "mb_decode_numericentity mb_detect_encoding mb_detect_order "
+ "mb_encode_mimeheader mb_encode_numericentity mb_ereg_match "
+ "mb_ereg_replace mb_ereg_search_getpos mb_ereg_search_getregs "
+ "mb_ereg_search_init mb_ereg_search_pos mb_ereg_search_regs "
+ "mb_ereg_search_setpos mb_ereg_search mb_ereg mb_eregi_replace "
+ "mb_eregi mb_get_info mb_http_input mb_http_output ini_restore "
+ "mb_internal_encoding mb_language mb_output_handler mb_parse_str "
+ "mb_preferred_mime_name mb_regex_encoding mb_regex_set_options "
+ "mb_send_mail mb_split mb_strcut mb_strimwidth mb_strlen mb_strpos "
+ "mb_strrpos mb_strtolower mb_strtoupper mb_strwidth imagesetpixel "
+ "mb_substitute_character mb_substr_count mb_substr mcrypt_cbc "
+ "mcrypt_cfb mcrypt_create_iv mcrypt_decrypt mcrypt_ecb "
+ "mcrypt_enc_get_algorithms_name mcrypt_enc_get_block_size "
+ "mcrypt_enc_get_iv_size mcrypt_enc_get_key_size ftp_nb_continue "
+ "mcrypt_enc_get_modes_name mcrypt_enc_get_supported_key_sizes "
+ "mcrypt_enc_is_block_algorithm_mode mcrypt_enc_is_block_algorithm "
+ "mcrypt_enc_is_block_mode mcrypt_enc_self_test mcrypt_encrypt "
+ "mcrypt_generic_deinit mcrypt_generic_end mcrypt_generic_init "
+ "mcrypt_generic mcrypt_get_block_size mcrypt_get_cipher_name "
+ "mcrypt_get_iv_size mcrypt_get_key_size mcrypt_list_algorithms "
+ "mcrypt_list_modes mcrypt_module_close imap_scanmailbox "
+ "mcrypt_module_get_algo_key_size imap_get_quotaroot "
+ "mcrypt_module_is_block_algorithm_mode imap_mime_header_decode "
+ "mcrypt_module_is_block_mode mcrypt_module_open imagecreatefromgd2 "
+ "mcrypt_ofb mdecrypt_generic mhash_count mhash_get_block_size "
+ "mhash_get_hash_name mhash_keygen_s2k mhash mime_content_type "
+ "connection_aborted connection_status connection_timeout constant "
+ "defined get_browser highlight_file highlight_string "
+ "ignore_user_abort pack show_source sleep uniqid unpack usleep "
+ "msql_affected_rows msql_close msql_connect msql_create_db define "
+ "msql_data_seek msql_dbname msql_drop_db msql_dropdb msql_error "
+ "msql_fetch_array msql_fetch_field msql_fetch_object msql_createdb "
+ "msql_field_seek msql_fieldflags msql_fieldlen msql_fieldname "
+ "msql_fieldtable msql_fieldtype msql_free_result msql_freeresult "
+ "msql_list_dbs msql_list_fields msql_list_tables msql_listdbs "
+ "msql_listfields msql_listtables msql_num_fields msql_num_rows "
+ "msql_numfields msql_numrows msql_pconnect msql_query msql_regcase "
+ "msql_result msql_select_db msql_selectdb msql_tablename msql "
+ "checkdnsrr closelog debugger_off debugger_on gethostbyaddr "
+ "dns_check_record dns_get_mx dns_get_record fsockopen "
+ "gethostbyname gethostbynamel getmxrr getprotobyname "
+ "getservbyname getservbyport ip2long long2ip openlog pfsockopen "
+ "socket_get_status socket_set_blocking socket_set_timeout syslog "
+ "ocibindbyname ocicancel OCICollAppend ocicollassign "
+ "ocicollgetelem ocicollmax ocicollsize ocicolltrim ocicolumnisnull "
+ "ocicolumnname ocicolumnprecision ocicolumnscale ocicolumnsize "
+ "ocicolumntype ocicolumntyperaw ocicommit ocidefinebyname ocierror "
+ "ociexecute ocifetch ocifetchinto ocifetchstatement msql_fetch_row "
+ "ocifreecursor OCIFreeDesc ocifreestatement ociinternaldebug "
+ "ocilogoff ocilogon ocinewcollection ocinewcursor ocinewdescriptor "
+ "ocinlogon ocinumcols ociparse ociplogon ociresult ocirollback "
+ "ocirowcount ocisavelob ocisavelobfile ociserverversion ociloadlob "
+ "ocisetprefetch ocistatementtype ociwritelobtofile flush ob_clean "
+ "ob_end_clean ob_end_flush ob_flush ob_get_contents ob_get_length "
+ "ob_get_level ob_get_status ob_gzhandler ob_implicit_flush "
+ "overload pcntl_exec pcntl_fork pcntl_signal pcntl_waitpid "
+ "pcntl_wexitstatus pcntl_wifexited pcntl_wifsignaled ob_start "
+ "pcntl_wstopsig pcntl_wtermsig preg_grep preg_match_all preg_match "
+ "preg_quote preg_replace_callback preg_replace preg_split "
+ "pdf_add_annotation pdf_add_bookmark pdf_add_launchlink "
+ "pdf_add_note pdf_add_outline pdf_add_pdflink pdf_add_thumbnail "
+ "pdf_add_weblink pdf_arc pdf_arcn pdf_attach_file pdf_begin_page "
+ "pdf_begin_pattern pdf_begin_template pdf_circle pdf_add_locallink "
+ "pdf_close_pdi_page pdf_close_pdi pdf_close pcntl_wifstopped "
+ "pdf_closepath_stroke pdf_closepath pdf_concat pdf_continue_text "
+ "pdf_curveto pdf_delete pdf_end_page pdf_end_pattern "
+ "pdf_endpath pdf_fill_stroke pdf_fill pdf_findfont pdf_get_buffer "
+ "pdf_get_font pdf_get_fontname pdf_get_fontsize pdf_open_pdi_page "
+ "pdf_get_image_width pdf_get_majorversion pdf_get_minorversion "
+ "pdf_get_parameter pdf_get_pdi_parameter pdf_get_pdi_value "
+ "pdf_initgraphics pdf_lineto pdf_makespotcolor pdf_moveto pdf_new "
+ "pdf_open_CCITT pdf_open_file pdf_open_gif pdf_open_image_file "
+ "pdf_open_image pdf_open_jpeg pdf_open_memory_image "
+ "pdf_open_pdi pdf_open_png pdf_open_tiff pdf_open pdf_place_image "
+ "pdf_place_pdi_page pdf_rect pdf_restore pdf_rotate pdf_get_value "
+ "pdf_set_border_color pdf_set_border_dash pdf_set_border_style "
+ "pdf_set_char_spacing pdf_set_duration pdf_set_font "
+ "pdf_set_info_author pdf_set_info_creator pdf_set_info_keywords "
+ "pdf_set_info_subject pdf_set_info_title pdf_set_info "
+ "pdf_set_parameter pdf_set_text_matrix pdf_set_text_pos "
+ "pdf_set_text_rendering pdf_set_text_rise pdf_set_value "
+ "pdf_set_word_spacing pdf_setcolor pdf_setdash pdf_setflat "
+ "pdf_setgray_fill pdf_setgray_stroke pdf_setgray pdf_setlinecap "
+ "pdf_setlinejoin pdf_setlinewidth pdf_setmatrix pdf_setmiterlimit "
+ "pdf_setpolydash pdf_setrgbcolor_fill pdf_setrgbcolor_stroke "
+ "pdf_setrgbcolor pdf_show_boxed pdf_show_xy pdf_show pdf_skew "
+ "pdf_stringwidth pdf_stroke pdf_translate pg_affected_rows "
+ "pg_cancel_query pg_client_encoding pg_close pg_connect "
+ "pg_connection_busy pg_connection_reset pg_connection_status "
+ "pg_copy_from pg_copy_to pg_dbname pg_delete pg_end_copy "
+ "pg_escape_string pg_fetch_all pg_fetch_array pg_fetch_assoc "
+ "pg_fetch_object pg_fetch_result pg_fetch_row pg_field_is_null "
+ "pg_field_name pg_field_num pg_field_prtlen pg_field_size "
+ "pg_free_result pg_get_notify pg_get_pid pg_get_result pg_host "
+ "pg_last_error pg_last_notice pg_last_oid pg_lo_close pg_lo_create "
+ "pg_lo_export pg_lo_import pg_lo_open pg_lo_read_all pg_lo_read "
+ "pg_lo_seek pg_lo_tell pg_lo_unlink pg_lo_write pg_meta_data "
+ "pg_num_fields pg_num_rows pg_options pg_pconnect pg_ping pg_port "
+ "pg_put_line pg_query pg_result_error pg_result_seek pg_field_type "
+ "pg_select pg_send_query pg_set_client_encoding pg_trace pg_tty "
+ "pg_unescape_bytea pg_untrace pg_update posix_ctermid posix_getcwd "
+ "posix_getegid posix_geteuid posix_getgid posix_getgrgid pg_insert "
+ "posix_getgroups posix_getlogin posix_getpgid posix_getpgrp "
+ "posix_getppid posix_getpwnam posix_getpwuid posix_getrlimit "
+ "posix_getuid posix_isatty posix_kill posix_mkfifo posix_setegid "
+ "posix_seteuid posix_setgid posix_setpgid posix_setsid pdf_setfont "
+ "posix_times posix_ttyname posix_uname pspell_add_to_personal "
+ "pspell_add_to_session pspell_check pspell_clear_session "
+ "pspell_config_create pspell_config_ignore pspell_config_mode "
+ "pspell_config_personal pspell_config_repl posix_setuid "
+ "pspell_config_save_repl pspell_new_config pspell_new_personal "
+ "pspell_new pspell_save_wordlist pspell_store_replacement "
+ "recode_file recode_string recode ereg_replace ereg eregi_replace "
+ "split spliti sql_regcase ftok msg_get_queue msg_receive "
+ "msg_send msg_set_queue msg_stat_queue sem_acquire sem_get "
+ "sem_remove shm_attach shm_detach shm_get_var shm_put_var "
+ "shm_remove session_cache_expire session_cache_limiter sem_release "
+ "session_destroy session_encode session_get_cookie_params eregi "
+ "session_is_registered session_module_name session_name session_id "
+ "session_register session_save_path session_set_cookie_params "
+ "session_set_save_handler session_start session_unregister "
+ "session_write_close snmp_get_quick_print snmp_set_quick_print "
+ "snmprealwalk snmpset snmpwalk snmpwalkoid socket_accept snmpget "
+ "socket_clear_error socket_close socket_connect session_unset "
+ "socket_create_pair socket_create socket_get_option socket_bind "
+ "socket_getsockname socket_iovec_add socket_iovec_alloc "
+ "socket_iovec_delete socket_iovec_fetch socket_iovec_free "
+ "socket_iovec_set socket_last_error socket_listen socket_read "
+ "socket_readv socket_recv socket_recvfrom socket_recvmsg "
+ "socket_send socket_sendmsg socket_sendto socket_set_nonblock "
+ "socket_set_option socket_shutdown socket_strerror socket_write "
+ "socket_writev stream_context_create stream_context_get_options "
+ "stream_context_set_option stream_context_set_params socket_select "
+ "stream_filter_prepend stream_get_filters stream_get_meta_data "
+ "stream_get_wrappers stream_register_filter stream_filter_append "
+ "stream_select stream_set_blocking stream_set_timeout posix_getpid "
+ "stream_set_write_buffer addcslashes addslashes bin2hex chop chr "
+ "chunk_split convert_cyr_string count_chars crc32 crypt "
+ "fprintf get_html_translation_table hebrev hebrevc explode "
+ "htmlentities htmlspecialchars implode join levenshtein localeconv "
+ "md5_file md5 metaphone money_format nl_langinfo nl2br pg_convert "
+ "parse_str printf quoted_printable_decode quotemeta rtrim "
+ "setlocale sha1_file sha1 similar_text soundex sprintf sscanf ord "
+ "str_repeat str_replace str_rot13 str_shuffle str_word_count ltrim "
+ "strchr strcmp strcoll strcspn strip_tags stripcslashes strcasecmp "
+ "stristr strlen strnatcasecmp strnatcmp strncasecmp strncmp strpos "
+ "strrchr strrev strrpos strspn strstr strtok strtolower strtoupper "
+ "substr_count substr_replace substr trim ucfirst ucwords vprintf "
+ "wordwrap base64_decode base64_encode get_meta_tags parse_url "
+ "rawurldecode rawurlencode urldecode urlencode doubleval "
+ "get_defined_vars get_resource_type gettype stripslashes str_pad "
+ "intval is_array is_bool is_callable is_double is_float is_int "
+ "is_long is_null is_numeric is_object is_real is_resource floatval "
+ "is_string print_r serialize settype strval unserialize "
+ "var_dump var_export utf8_decode utf8_encode xml_error_string "
+ "xml_get_current_byte_index xml_get_current_column_number "
+ "xml_get_current_line_number xml_get_error_code is_scalar vsprintf "
+ "xml_parse xml_parser_create_ns xml_parser_create xml_parser_free "
+ "xml_parser_get_option xml_parser_set_option number_format "
+ "xml_set_default_handler xml_set_element_handler is_integer "
+ "xml_set_end_namespace_decl_handler xml_parse_into_struct strtr "
+ "xml_set_notation_decl_handler xml_set_object html_entity_decode "
+ "xml_set_processing_instruction_handler stream_register_wrapper "
+ "xml_set_unparsed_entity_decl_handler xslt_create xslt_errno "
+ "xslt_free xslt_output_process xslt_set_base xslt_set_encoding "
+ "xslt_set_error_handler xslt_set_log xslt_set_sax_handler "
+ "xslt_set_sax_handlers xslt_set_scheme_handler socket_getpeername "
+ "zip_close zip_entry_close zip_entry_compressedsize xslt_error "
+ "zip_entry_compressionmethod zip_entry_filesize zip_entry_name "
+ "zip_entry_open zip_entry_read zip_open zip_read session_decode "
+ "get_magic_quotes_runtime xslt_set_scheme_handlers pspell_suggest "
+ "xml_set_start_namespace_decl_handler import_request_variables "
+ "xml_set_external_entity_ref_handler socket_create_listen "
+ "xml_set_character_data_handler session_readonly shm_remove_var "
+ "msg_remove_queue pspell_config_runtogether posix_getsid "
+ "posix_getgrnam pg_result_status pg_escape_bytea pdf_set_leading "
+ "pdf_set_horiz_scaling pdf_save pdf_scale pdf_get_image_height "
+ "pdf_end_template pdf_closepath_fill_stroke ocicollassignelem "
+ "pdf_clip pdf_close_image ocifreecollection getprotobynumber "
+ "mcrypt_module_self_test define_syslog_variables "
+ "mcrypt_module_get_supported_key_sizes imap_clearflag_full "
+ "mcrypt_module_is_block_algorithm imagepsencodefont "
+ "mcrypt_module_get_algo_block_size imagepsslantfont count ")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_HPHP_DEFAULT, 'default_style'),
+ (stc.STC_HPHP_COMMENT, 'comment_style'),
+ (stc.STC_HPHP_COMMENTLINE, 'comment_style'),
+ (stc.STC_HPHP_COMPLEX_VARIABLE, 'pre_style'), #STYLE ME
+ (stc.STC_HPHP_HSTRING, 'string_style'),
+ (stc.STC_HPHP_HSTRING_VARIABLE, 'scalar_style'), # STYLE ME
+ (stc.STC_HPHP_NUMBER, 'number_style'),
+ (stc.STC_HPHP_OPERATOR, 'operator_style'),
+ (stc.STC_HPHP_SIMPLESTRING, 'string_style'),
+ (stc.STC_HPHP_VARIABLE, 'pre2_style'),
+ (stc.STC_HPHP_WORD, 'keyword_style') ]
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Php"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_HTML)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ # Support Embedded HTML highlighting
+ html = _html.SyntaxData(synglob.ID_LANG_HTML)
+ keywords = html.GetKeywords()
+ keywords.append((4, PHP_KEYWORDS))
+ return keywords
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return _html.SYNTAX_ITEMS + SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [_html.FOLD, _html.FLD_HTML]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code
+ @note: assuming pure php code for comment character(s)
+
+ """
+ return [u'//']
+
+#---- Syntax Modules Internal Functions ----#
+def KeywordString(option=0):
+ """Returns the specified Keyword String
+ @note: not used by most modules
+
+ """
+ return PHP_KEYWORDS
+
+#---- End Syntax Modules Internal Functions ----#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pike.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pike.py
new file mode 100644
index 0000000..f58b4a6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pike.py
@@ -0,0 +1,55 @@
+###############################################################################
+# Name: pike.py #
+# Purpose: Define highlighting/syntax for Pike programming language #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: pike.py
+@summary: Defines syntax and highlighting settings for the Pike programming
+ language. Pike is very similar in form to C/CPP so the Cpp lexer is
+ used to provide the highlighting settings.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _pike.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _cpp
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+PIKE_KW = (0, "goto break return continue case default if else switch while "
+ "foreach do gauge destruct lambda inherit import typeof catch "
+ "for inline nomask")
+
+PIKE_TYPE = (1, "private protected public static "
+ "int string void float mapping array multiset mixed program "
+ "object function")
+#---- End Keyword Definitions ----#
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(_cpp.SyntaxData):
+ """SyntaxData object for Pike"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [PIKE_KW, PIKE_TYPE, _cpp.DOC_KEYWORDS]
+
+ def GetCommentPattern(self):
+ """Get the comment pattern"""
+ return [u"//"]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_postscript.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_postscript.py
new file mode 100644
index 0000000..58d4cd1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_postscript.py
@@ -0,0 +1,170 @@
+###############################################################################
+# Name: postscript.py #
+# Purpose: Define Postscript syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: postscript.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for PostScript. (case sensitive)
+@todo: l3 keywords and ghostscript
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _postscript.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# PS Level 1 Operators
+PS_L1 = (0, "$error = == FontDirectory StandardEncoding UserObjects abs add "
+ "aload anchorsearch and arc arcn arcto array ashow astore atan "
+ "awidthshow begin bind bitshift bytesavailable cachestatus ceiling "
+ "charpath clear cleardictstack cleartomark clip clippath closefile "
+ "closepath concat concatmatrix copy copypage cos count "
+ "countdictstack countexecstack counttomark currentcmykcolor "
+ "currentcolorspace currentdash currentdict currentfile currentflat "
+ "currentfont currentgray currenthsbcolor currentlinecap "
+ "currentlinejoin currentlinewidth currentmatrix currentmiterlimit "
+ "currentpagedevice currentpoint currentrgbcolor currentscreen "
+ "currenttransfer cvi cvlit cvn cvr cvrs cvs cvx def defaultmatrix "
+ "definefont dict dictstack div dtransform dup echo end eoclip "
+ "eofill eq erasepage errordict exch exec execstack executeonly "
+ "executive exit exp false file fill findfont flattenpath floor "
+ "flush flushfile for forall ge get getinterval grestore "
+ "grestoreall gsave gt idetmatrix idiv idtransform if ifelse image "
+ "imagemask index initclip initgraphics initmatrix inustroke "
+ "invertmatrix itransform known kshow le length lineto ln load log "
+ "loop lt makefont mark matrix maxlength mod moveto mul ne neg "
+ "newpath noaccess nor not null nulldevice or pathbbox pathforall "
+ "pop print prompt pstack put putinterval quit rand rcheck rcurveto "
+ "read readhexstring readline readonly readstring rectstroke repeat "
+ "resetfile restore reversepath rlineto rmoveto roll rotate round "
+ "rrand run save scale scalefont search setblackgeneration "
+ "setcachedevice setcachelimit setcharwidth setcolorscreen "
+ "setcolortransfer setdash setflat setfont setgray sethsbcolor "
+ "setlinecap setlinejoin setlinewidth setmatrix setmiterlimit "
+ "setpagedevice setrgbcolor setscreen settransfer setvmthreshold "
+ "show showpage sin sqrt srand stack start status statusdict stop "
+ "stopped store string stringwidth stroke strokepath sub systemdict "
+ "token token transform translate true truncate type ueofill "
+ "undefineresource userdict usertime version vmstatus wcheck where "
+ "widthshow write writehexstring writestring xcheck xor")
+
+# PS Level 2 Operators
+PS_L2 = (1, "GlobalFontDirectory ISOLatin1Encoding SharedFontDirectory "
+ "UserObject arct colorimage cshow currentblackgeneration "
+ "currentcacheparams currentcmykcolor currentcolor "
+ "currentcolorrendering currentcolorscreen currentcolorspace "
+ "currentcolortransfer currentdevparams currentglobal currentgstate "
+ "currenthalftone currentobjectformat currentoverprint "
+ "currentpacking currentpagedevice currentshared "
+ "currentstrokeadjust currentsystemparams currentundercolorremoval "
+ "currentuserparams defineresource defineuserobject deletefile "
+ "execform execuserobject filenameforall fileposition filter "
+ "findencoding findresource gcheck globaldict glyphshow gstate "
+ "ineofill infill instroke inueofill inufill inustroke "
+ "languagelevel makepattern packedarray printobject product "
+ "realtime rectclip rectfill rectstroke renamefile resourceforall "
+ "resourcestatus revision rootfont scheck selectfont serialnumber "
+ "setbbox setblackgeneration setcachedevice2 setcacheparams "
+ "setcmykcolor setcolor setcolorrendering setcolorscreen "
+ "setcolorspace setcolortranfer setdevparams setfileposition "
+ "setglobal setgstate sethalftone setobjectformat setoverprint "
+ "setpacking setpagedevice setpattern setshared setstrokeadjust "
+ "setsystemparams setucacheparams setundercolorremoval "
+ "setuserparams setvmthreshold shareddict startjob uappend ucache "
+ "ucachestatus ueofill ufill undef undefinefont undefineresource "
+ "undefineuserobject upath ustroke ustrokepath vmreclaim "
+ "writeobject xshow xyshow yshow")
+
+# PS 3 Operators
+PS_L3 = (2, "cliprestore clipsave composefont currentsmoothness "
+ "findcolorrendering setsmoothness shfill")
+
+# RIP-specific operators
+RIP_OP = (3, ".begintransparencygroup .begintransparencymask .bytestring "
+ ".charboxpath .currentaccuratecurves .currentblendmode "
+ ".currentcurvejoin .currentdashadapt .currentdotlength "
+ ".currentfilladjust2 .currentlimitclamp .currentopacityalpha "
+ ".currentoverprintmode .currentrasterop .currentshapealpha "
+ ".currentsourcetransparent .currenttextknockout "
+ ".currenttexturetransparent .dashpath .dicttomark "
+ ".discardtransparencygroup .discardtransparencymask "
+ ".endtransparencygroup .endtransparencymask .execn .filename "
+ ".filename .fileposition .forceput .forceundef .forgetsave "
+ ".getbitsrect .getdevice .inittransparencymask .knownget "
+ ".locksafe .makeoperator .namestring .oserrno .oserrorstring "
+ ".peekstring .rectappend .runandhide .setaccuratecurves ."
+ "setblendmode .setcurvejoin .setdashadapt .setdebug "
+ ".setdefaultmatrix .setdotlength .setfilladjust2 .setlimitclamp "
+ ".setmaxlength .setopacityalpha .setoverprintmode .setrasterop "
+ ".setsafe .setshapealpha .setsourcetransparent .settextknockout "
+ ".settexturetransparent .stringbreak .stringmatch .tempfile "
+ ".type1decrypt .type1encrypt .type1execchar .unread arccos arcsin "
+ "copydevice copyscanlines currentdevice finddevice findlibfile "
+ "findprotodevice flushpage getdeviceprops getenv makeimagedevice "
+ "makewordimagedevice max min putdeviceprops setdevice")
+
+# User Defined Operators
+USER_DEF = (4, "")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_PS_DEFAULT, 'default_style'),
+ (stc.STC_PS_BADSTRINGCHAR, 'unknown_style'),
+ (stc.STC_PS_BASE85STRING, 'string_style'),
+ (stc.STC_PS_COMMENT, 'comment_style'),
+ (stc.STC_PS_DSC_COMMENT, 'comment_style'),
+ (stc.STC_PS_DSC_VALUE, 'comment_style'), # STYLE ME
+ (stc.STC_PS_HEXSTRING, 'number_style'),
+ (stc.STC_PS_IMMEVAL, 'comment_style'), # STYLE ME
+ (stc.STC_PS_KEYWORD, 'class_style'),
+ (stc.STC_PS_LITERAL, 'scalar2_style'),
+ (stc.STC_PS_NAME, 'keyword_style'),
+ (stc.STC_PS_NUMBER, 'number_style'),
+ (stc.STC_PS_PAREN_ARRAY, 'default_style'), # STYLE ME
+ (stc.STC_PS_PAREN_DICT, 'default_style'), # STYLE ME
+ (stc.STC_PS_PAREN_PROC, 'default_style'), # STYLE ME
+ (stc.STC_PS_TEXT, 'default_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for PostScript"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_PS)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [PS_L1, PS_L2]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'%']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_progress.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_progress.py
new file mode 100644
index 0000000..bfbd63f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_progress.py
@@ -0,0 +1,262 @@
+###############################################################################
+# Name: progress.py #
+# Purpose: Define Progress 4gl syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Syntax highlighting definition for Progress 4GL programming language.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _progress.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _sql
+
+#-----------------------------------------------------------------------------#
+
+# Reserved Progress 4GL keywords
+PROG_KW = (0, "accumulate active-window add alias all alter ambiguous analyze "
+ "and any apply as ascending assign at attr-space authorization "
+ "auto-return available background before-hide begins bell "
+ "between blank break btos by call can-do can-find centered "
+ "character check chr clear clipboard col colon color column "
+ "column-label columns compiler connected control count-of "
+ "cpstream create ctos current current-changed current-language "
+ "current-window current_date cursor database dataservers "
+ "dbcodepage dbcollation dbname dbrestrictions dbtaskid dbtype "
+ "dbversion dde deblank debug-list debugger decimal decimals "
+ "declare def default default-noxlate default-window define "
+ "delete delimiter descending dictionary disable disconnect disp "
+ "display distinct dos down drop editing enable encode entry "
+ "error-status escape etime except exclusive exclusive-lock "
+ "exclusive-web-user exists export false fetch field fields "
+ "file-information fill find find-case-sensitive find-global "
+ "find-next-occurrence find-prev-occurrence find-select "
+ "find-wrap-around first first-of focus font form format frame "
+ "frame-col frame-db frame-down frame-field frame-file "
+ "frame-index frame-line frame-name frame-row frame-value from "
+ "from-chars from-pixels gateways get-byte get-codepages "
+ "get-collations get-key-value getbyte global go-on go-pending "
+ "grant graphic-edge group having header help hide import in "
+ "index indicator input input-output insert integer into is "
+ "is-attr-space join kblabel key-code key-function key-label "
+ "keycode keyfunction keylabel keys keyword label last last-event "
+ "last-key last-of lastkey ldbname leave library like "
+ "line-counter listing locked lookup machine-class map member "
+ "message message-lines mouse mpe new next next-prompt no "
+ "no-attr-space no-error no-fill no-help no-hide no-labels "
+ "no-lock no-map no-message no-pause no-prefetch no-undo "
+ "no-validate no-wait not null num-aliases num-dbs num-entries "
+ "of off old on open opsys option or os-append os-command "
+ "os-copy os-create-dir os-delete os-dir os-drives os-error "
+ "os-rename os2 os400 output overlay page page-bottom page-number "
+ "page-top parameter pause pdbname persistent pixels preprocess "
+ "privileges proc-handle proc-status process program-name "
+ "Progress prompt prompt-for promsgs propath proversion put "
+ "put-byte put-key-value putbyte query query-tuning quit r-index "
+ "rcode-information readkey recid record-length rectangle release "
+ "reposition retain retry return return-value revert revoke run "
+ "save schema screen screen-io screen-lines scroll sdbname search "
+ "seek select self session set setuserid share-lock shared "
+ "show-stats skip some space status stream stream-io string-xref "
+ "system-dialog table term terminal text text-cursor "
+ "text-seg-growth this-procedure time title to today top-only "
+ "trans transaction trigger triggers trim true underline undo "
+ "unformatted union unique unix up update use-index use-revvideo "
+ "use-underline user userid using v6frame value values variable "
+ "view view-as vms wait-for web-context window window-maximized "
+ "window-minimized window-normal with work-table workfile write "
+ "xcode xref yes _cbit _control _list _memory _msg _pcontrol "
+ "_serial-num _trace "
+ "repeat transaction for each end finf where if then else skip "
+ "close"
+)
+
+# Progress 4GL Types
+PROG_TYPES = (1, "char character int integer format var variable log logical "
+ "da date")
+
+# Progress 4GL Operators
+PROG_OP = (7, "absolute accelerator across add-first add-last advise alert-box "
+ "allow-replication ansi-only anywhere append appl-alert-boxes "
+ "application as-cursor ask-overwrite attachment auto-end-key "
+ "auto-endkey auto-go auto-indent auto-resize auto-zap "
+ "available-formats average avg backwards base-key batch-mode "
+ "bgcolor binary bind-where block-iteration-display border-bottom "
+ "border-bottom-chars border-bottom-pixels border-left "
+ "border-left-chars border-left-pixels border-right "
+ "border-right-chars border-right-pixels border-top "
+ "border-top-chars border-top-pixels both bottom box "
+ "box-selectable browse browse-header buffer buffer-chars "
+ "buffer-lines button buttons byte cache cache-size can-query "
+ "can-set cancel-break cancel-button caps careful-paint "
+ "case-sensitive cdecl character character_length charset checked "
+ "choose clear-selection close code codepage codepage-convert "
+ "col-of colon-aligned color-table column-bgcolor column-dcolor "
+ "column-fgcolor column-font column-label-bgcolor "
+ "column-label-dcolor column-label-fgcolor column-label-font "
+ "column-of column-pfcolor column-scrolling combo-box command "
+ "compile complete connect constrained contents context "
+ "context-popup control-container control-form convert-to-offset "
+ "convert count cpcase cpcoll cpinternal cplog cpprint cprcodein "
+ "cprcodeout cpterm crc-value create-control "
+ "create-result-list-entry create-test-file current-column "
+ "current-environment current-iteration current-result-row "
+ "current-row-modified current-value cursor-char cursor-line "
+ "cursor-offset data-entry-return data-type date date-format day "
+ "db-references dcolor dde-error dde-id dde-item dde-name "
+ "dde-topic debug decimal default-button default-extension "
+ "defer-lob-fetch define defined delete-char delete-current-row "
+ "delete-line delete-selected-row delete-selected-rows "
+ "deselect-focused-row deselect-rows deselect-selected-row "
+ "design-mode dialog-box dialog-help dir disabled display-message "
+ "display-type double drag-enabled drop-down drop-down-list dump "
+ "dynamic echo edge edge-chars edge-pixels editor empty end-key "
+ "endkey entered eq error error-column error-row event-type "
+ "events exclusive-id execute exp expand extended extent external "
+ "extract fetch-selected-row fgcolor file file-name file-offset "
+ "file-type filename fill-in filled filters first-child "
+ "first-column first-procedure first-tab-item fixed-only float "
+ "focused-row font-based-layout font-table force-file foreground "
+ "forult-row current-row-modified current-value cursor-char "
+ "cursor-line cursor-offset data-entry-return data-type date "
+ "date-format day db-references full-width full-width-chars "
+ "full-width-pixels ge get get-blue-value get-char-property "
+ "get-double get-dynamic get-file get-float get-green-value "
+ "get-iteration get-license get-long get-message get-number "
+ "get-pointer-value get-red-value get-repositioned-row "
+ "get-selected-widget get-short get-signature get-size get-string "
+ "get-tab-item get-text-height get-text-height-chars "
+ "get-text-height-pixels get-text-width get-text-width-chars "
+ "get-text-width-pixels get-unsigned-short grayed "
+ "grid-factor-horizontal grid-factor-vertical grid-set grid-snap "
+ "grid-unit-height grid-unit-height-chars grid-unit-height-pixels "
+ "grid-unit-width grid-unit-width-chars grid-unit-width-pixels "
+ "grid-visible gt handle height height-chars height-pixels "
+ "help-context helpfile-name hidden hint horizontal hwnd image "
+ "image-down image-insensitive image-size image-size-chars "
+ "image-size-pixels image-up immediate-display index-hint "
+ "indexed-reposition information init initial initial-dir "
+ "initial-filter initiate inner inner-chars inner-lines "
+ "insert-backtab insert-file insert-row insert-string insert-tab "
+ "integer internal-entries is-lead-byte is-row-selected "
+ "is-selected item items-per-row join-by-sqldb keep-frame-z-order "
+ "keep-messages keep-tab-order key keyword-all label-bgcolor "
+ "label-dcolor label-fgcolor label-font label-pfcolor labels "
+ "languages large large-to-small last-child last-tab-item "
+ "last-procedure lc le leading left left-aligned left-trim length "
+ "line list-events list-items list-query-attrs list-set-attrs "
+ "list-widgets load load-control load-icon load-image "
+ "load-image-down load-image-insensitive load-image-up "
+ "load-mouse-pointer load-small-icon log logical lookahead lower "
+ "lt manual-highlight margin-extra margin-height "
+ "margin-height-chars margin-height-pixels margin-width "
+ "margin-width-chars margin-width-pixels matches max max-chars "
+ "max-data-guess max-height max-height-chars max-height-pixels "
+ "max-rows max-size max-value max-width max-width-chars "
+ "max-width-pixels maximize maximum memory menu menu-bar "
+ "menu-item menu-key menu-mouse menubar message-area "
+ "message-area-font message-line min min-height min-height-chars "
+ "min-height-pixels min-size min-value min-width min-width-chars "
+ "min-width-pixels minimum mod modified modulo month "
+ "mouse-pointer movable move-after-tab-item move-before-tab-item "
+ "move-column move-to-bottom move-to-eof move-to-top multiple "
+ "multiple-key multitasking-interval must-exist name native ne "
+ "new-row next-column next-sibling next-tab-item next-value "
+ "no-apply no-assign no-bind-where no-box no-column-scrolling "
+ "no-convert no-current-value no-debug no-drag no-echo "
+ "no-index-hint no-join-by-sqldb no-lookahead no-row-markers "
+ "no-scrolling no-separate-connection no-separators no-underline "
+ "no-word-wrap none num-buttons num-columns num-copies "
+ "num-formats num-items num-iterations num-lines "
+ "num-locked-columns num-messages num-results num-selected "
+ "num-selected-rows num-selected-widgets num-tabs num-to-retain "
+ "numeric numeric-format octet_length ok ok-cancel "
+ "on-frame-border ordered-join ordinal orientation os-getenv "
+ "outer outer-join override owner page-size page-width paged "
+ "parent partial-key pascal pathname pfcolor pinnable "
+ "pixels-per-column pixels-per-row popup-menu popup-only position "
+ "precision preselect prev prev-column prev-sibling prev-tab-item "
+ "primary printer-control-handle printer-setup private-data "
+ "profiler Progress-source publish put-double put-float put-long "
+ "put-short put-string put-unsigned-short query-off-end question "
+ "radio-buttons radio-set random raw raw-transfer read-file "
+ "read-only real recursive refresh refreshable replace "
+ "replace-selection-text replication-create replication-delete "
+ "replication-write request resizable resize retry-cancel "
+ "return-inserted return-to-start-dir reverse-from right "
+ "right-aligned right-trim round row row-markers row-of rowid "
+ "rule rule-row rule-y save-as save-file screen-value scroll-bars "
+ "scroll-delta scroll-horiz-value scroll-offset "
+ "scroll-to-current-row scroll-to-item scroll-to-selected-row "
+ "scroll-vert-value scrollable scrollbar-horizontal "
+ "scrollbar-vertical scrolled-row-position scrolling "
+ "se-check-pools se-enable-off se-enable-on se-num-pools "
+ "se-use-message section select-focused-row select-next-row "
+ "select-prev-row select-repositioned-row select-row selectable "
+ "selected selected-items selection-end selection-list "
+ "selection-start selection-text send sensitive "
+ "separate-connection separators set-blue-value set-break "
+ "set-cell-focus set-contents set-dynamic set-green-value "
+ "set-leakpoint set-pointer-value set-property set-red-value "
+ "set-repositioned-row set-selection set-size set-wait-state "
+ "side-lab side-labe side-label side-label-handle side-labels "
+ "silent simple single size size-chars size-pixels slider "
+ "smallint sort source source-procedure sql sqrt start "
+ "status-area status-area-font status-bar stdcall stenciled stop "
+ "stopped stored-procedure string sub-average sub-count "
+ "sub-maximum sub-menu sub-menu-help sub-minimum sub-total "
+ "subscribe substitute substring subtype sum super "
+ "suppress-warnings system-alert-boxes system-help tab-position "
+ "tabbable target target-procedure temp-directory temp-table "
+ "terminate text-selected three-d through thru tic-marks "
+ "time-source title-bgcolor title-dcolor title-fgcolor title-font "
+ "to-rowid toggle-box tool-bar top topic total trailing truncate "
+ "type unbuffered unique-id unload unsubscribe upper use "
+ "use-dict-exps use-filename use-text v6display valid-event "
+ "valid-handle validate validate-condition validate-message "
+ "variable vertical virtual-height virtual-height-chars "
+ "use-filename use-text v6display valid-event valid-handle "
+ "validate validate-condition validate-message variable vertical "
+ "virtual-height virtual-height-chars widget-pool width "
+ "width-chars width-pixels window-name window-state window-system "
+ "word-wrap x-of y-of year yes-no yes-no-cancel _dcm")
+
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Progress 4GL"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_SQL)
+
+ def GetKeywords(self):
+ """Progress 4GL keyword specifications """
+ return [PROG_KW, PROG_TYPES, PROG_OP]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return _sql.SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Language properties for folding ect... """
+ return [_sql.FOLD,]
+
+ def GetCommentPattern(self):
+ """Comment pattern """
+ return [u'/*', u'*/']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_props.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_props.py
new file mode 100644
index 0000000..4fcf59a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_props.py
@@ -0,0 +1,62 @@
+###############################################################################
+# Name: props.py #
+# Purpose: Define Properties/ini syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: props.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for properties/config files
+ (ini, cfg, ect..).
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _props.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_PROPS_ASSIGNMENT, 'operator_style'),
+ (stc.STC_PROPS_COMMENT, 'comment_style'),
+ (stc.STC_PROPS_DEFAULT, 'default_style'),
+ (stc.STC_PROPS_DEFVAL, 'string_style'),
+ (stc.STC_PROPS_KEY, 'scalar_style'),
+ (stc.STC_PROPS_SECTION, 'keyword_style')]
+
+#---- Extra Properties ----#
+FOLD = ('fold', '1')
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Properties files"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_PROPERTIES)
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return list(u'#')
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_python.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_python.py
new file mode 100644
index 0000000..bf7f92e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_python.py
@@ -0,0 +1,238 @@
+###############################################################################
+# Name: python.py #
+# Purpose: Define Python syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: python.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Python.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _python.py 69016 2011-09-06 20:00:06Z CJP $"
+__revision__ = "$Revision: 69016 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+import keyword
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Indenter keywords
+INDENT_KW = (u"def", u"if", u"elif", u"else", u"for", u"while",
+ u"class", u"try", u"except", u"finally", u"with")
+UNINDENT_KW = (u"return", u"raise", u"break", u"continue",
+ u"pass", u"exit", u"quit")
+
+# Python Keywords
+KEYWORDS = keyword.kwlist
+KEYWORDS.extend(['True', 'False', 'None', 'self'])
+PY_KW = (0, u" ".join(KEYWORDS))
+
+# Highlighted builtins
+try:
+ import __builtin__
+ BUILTINS = dir(__builtin__)
+except:
+ BUILTINS = list()
+#BUILTINS.append('self')
+BUILTINS = list(set(BUILTINS))
+
+PY_BIN = (1, u" ".join(sorted(BUILTINS)))
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_P_DEFAULT, 'default_style'),
+ (stc.STC_P_CHARACTER, 'char_style'),
+ (stc.STC_P_CLASSNAME, 'class_style'),
+ (stc.STC_P_COMMENTBLOCK, 'comment_style'),
+ (stc.STC_P_COMMENTLINE, 'comment_style'),
+ (stc.STC_P_DECORATOR, 'decor_style'),
+ (stc.STC_P_DEFNAME, 'keyword3_style'),
+ (stc.STC_P_IDENTIFIER, 'default_style'),
+ (stc.STC_P_NUMBER, 'number_style'),
+ (stc.STC_P_OPERATOR, 'operator_style'),
+ (stc.STC_P_STRING, 'string_style'),
+ (stc.STC_P_STRINGEOL, 'stringeol_style'),
+ (stc.STC_P_TRIPLE, 'string_style'),
+ (stc.STC_P_TRIPLEDOUBLE, 'string_style'),
+ (stc.STC_P_WORD, 'keyword_style'),
+ (stc.STC_P_WORD2, 'userkw_style')]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_QUOTES = ("fold.quotes.python", "1")
+FOLD_COMMENTS = ("fold.comment.python", "1")
+TIMMY = ("tab.timmy.whinge.level", "1") # Mark Inconsistent indentation
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Python"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_PYTHON)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [PY_KW, PY_BIN]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, TIMMY, FOLD_QUOTES, FOLD_COMMENTS]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#']
+
+#-----------------------------------------------------------------------------#
+
+def AutoIndenter(estc, pos, ichar):
+ """Auto indent python code.
+ @param estc: EditraStyledTextCtrl
+ @param pos: current carat position
+ @param ichar: Indentation character
+
+ """
+ line = estc.GetCurrentLine()
+ spos = estc.PositionFromLine(line)
+ text = estc.GetTextRange(spos, pos)
+ eolch = estc.GetEOLChar()
+ inspace = text.isspace()
+
+ # Cursor is in the indent area somewhere
+ if inspace:
+ estc.AddText(eolch + text.replace(eolch, u""))
+ return
+
+ # Check if the cursor is in column 0 and just return newline.
+ if not len(text):
+ estc.AddText(eolch)
+ return
+
+ # In case of open bracket: Indent next to open bracket
+ def BackTrack(tmp_text, tline):
+ bcount = [ tmp_text.count(brac) for brac in u")}]({[" ]
+ bRecurse = False
+ for idx, val in enumerate(bcount[:3]):
+ if val > bcount[idx+3]:
+ bRecurse = True
+ break
+ if bRecurse:
+ tline = tline - 1
+ if tline < 0:
+ return tmp_text
+ spos = estc.PositionFromLine(tline)
+ tmp_text = estc.GetTextRange(spos, pos)
+ BackTrack(tmp_text, tline)
+ return tmp_text
+ text = BackTrack(text, line)
+ pos = PosOpenBracket(text)
+ if pos > -1:
+ rval = eolch + (pos + 1) * u" "
+ estc.AddText(rval)
+ return
+
+ indent = estc.GetLineIndentation(line)
+ if ichar == u"\t":
+ tabw = estc.GetTabWidth()
+ else:
+ tabw = estc.GetIndent()
+
+ i_space = indent / tabw
+ end_spaces = ((indent - (tabw * i_space)) * u" ")
+
+ tokens = filter(None, text.strip().split())
+ if tokens and not inspace:
+ if tokens[-1].endswith(u":"):
+ if tokens[0].rstrip(u":") in INDENT_KW:
+ i_space += 1
+ elif tokens[-1].endswith(u"\\"):
+ i_space += 1
+ elif len(tokens[-1]) and tokens[-1][-1] in u"}])":
+ ptok = tokens[-1][-1]
+ paren_pos = pos - (len(text) - text.rfind(ptok))
+ oparen, cparen = estc.GetBracePair(paren_pos)
+ if cparen >= 0: # Found matching bracket
+ line = estc.LineFromPosition(cparen)
+ indent = estc.GetLineIndentation(line)
+ i_space = indent / tabw
+ end_spaces = ((indent - (tabw * i_space)) * u" ")
+ elif tokens[0] in UNINDENT_KW:
+ i_space = max(i_space - 1, 0)
+
+ rval = eolch + (ichar * i_space) + end_spaces
+ if inspace and ichar != u"\t":
+ rpos = indent - (pos - spos)
+ if rpos < len(rval) and rpos > 0:
+ rval = rval[:-rpos]
+ elif rpos >= len(rval):
+ rval = eolch
+
+ # Put text in the buffer
+ estc.AddText(rval)
+
+#---- End Required Module Functions ----#
+
+#---- Syntax Modules Internal Functions ----#
+def KeywordString():
+ """Returns the specified Keyword String
+ @note: not used by most modules
+
+ """
+ return PY_KW[1]
+
+def PosOpenBracket(text):
+ """Returns the position of the right most open bracket in text.
+ Brackets inside strings are ignored. In case of no open bracket
+ the returned value is -1
+ @param text: The line preceding the new line to be indented.
+ @return res: The position of right most open bracket.
+ @note: Used by AutoIndenter
+
+ """
+ # Store positions of '(', '[','{', ')', ']', '}'
+ brackets = [[], [], [], [], [], []]
+ quotes = u"'" + u'"'
+ in_string = False
+ for pos, char in enumerate(text):
+ if in_string:
+ in_string = not char == quote
+ else:
+ if char == u'#':
+ break
+ typ = u'([{)]}'.find(char)
+ if typ > -1:
+ brackets[typ].append(pos)
+ else:
+ typ = quotes.find(char)
+ if typ > -1:
+ in_string = True
+ quote = quotes[typ]
+ res = -1
+ for typ in range(3):
+ opn, cls = brackets[typ], brackets[typ+3]
+ nopn, ncls = len(opn), len(cls)
+ if nopn > ncls:
+ res = max(res, opn[nopn - ncls - 1])
+ return res
+
+#---- End Syntax Modules Internal Functions ----#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ruby.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ruby.py
new file mode 100644
index 0000000..ca99a14
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ruby.py
@@ -0,0 +1,149 @@
+###############################################################################
+# Name: ruby.py #
+# Purpose: Define Ruby syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: ruby.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Ruby.
+@todo: Default Style Refinement.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _ruby.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+import re
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Ruby Keywords
+# NOTE: putting words with question marks in them causes an assertion to be
+# raised when showing the list in the keyword helper! defined?
+RUBY_KW = (0, "__FILE__ and def end in or self unless __LINE__ begin defined "
+ "ensure module redo super until BEGIN break do false next "
+ "require rescue then when END case else for nil retry true while "
+ "alias class elsif if not return undef yieldr puts raise "
+ "protected private")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_RB_BACKTICKS, 'scalar_style'),
+ (stc.STC_RB_CHARACTER, 'char_style'),
+ (stc.STC_RB_CLASSNAME, 'class_style'),
+ (stc.STC_RB_CLASS_VAR, 'default_style'), # STYLE ME
+ (stc.STC_RB_COMMENTLINE, 'comment_style'),
+ (stc.STC_RB_DATASECTION, 'default_style'), # STYLE ME
+ (stc.STC_RB_DEFAULT, 'default_style'),
+ (stc.STC_RB_DEFNAME, 'keyword3_style'), # STYLE ME
+ (stc.STC_RB_ERROR, 'error_style'),
+ (stc.STC_RB_GLOBAL, 'global_style'),
+ (stc.STC_RB_HERE_DELIM, 'default_style'), # STYLE ME
+ (stc.STC_RB_HERE_Q, 'here_style'),
+ (stc.STC_RB_HERE_QQ, 'here_style'),
+ (stc.STC_RB_HERE_QX, 'here_style'),
+ (stc.STC_RB_IDENTIFIER, 'default_style'),
+ (stc.STC_RB_INSTANCE_VAR, 'scalar2_style'),
+ (stc.STC_RB_MODULE_NAME, 'global_style'), # STYLE ME
+ (stc.STC_RB_NUMBER, 'number_style'),
+ (stc.STC_RB_OPERATOR, 'operator_style'),
+ (stc.STC_RB_POD, 'default_style'), # STYLE ME
+ (stc.STC_RB_REGEX, 'regex_style'), # STYLE ME
+ (stc.STC_RB_STDIN, 'default_style'), # STYLE ME
+ (stc.STC_RB_STDOUT, 'default_style'), # STYLE ME
+ (stc.STC_RB_STRING, 'string_style'),
+ (stc.STC_RB_STRING_Q, 'default_style'), # STYLE ME
+ (stc.STC_RB_STRING_QQ, 'default_style'), # STYLE ME
+ (stc.STC_RB_STRING_QR, 'default_style'), # STYLE ME
+ (stc.STC_RB_STRING_QW, 'default_style'), # STYLE ME
+ (stc.STC_RB_STRING_QX, 'default_style'), # STYLE ME
+ (stc.STC_RB_SYMBOL, 'default_style'), # STYLE ME
+ (stc.STC_RB_UPPER_BOUND, 'default_style'), # STYLE ME
+ (stc.STC_RB_WORD, 'keyword_style'),
+ (stc.STC_RB_WORD_DEMOTED, 'keyword2_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+TIMMY = ("fold.timmy.whinge.level", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Ruby"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_RUBY)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [RUBY_KW]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, TIMMY]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#']
+
+#-----------------------------------------------------------------------------#
+
+def AutoIndenter(estc, pos, ichar):
+ """Auto indent cpp code.
+ @param estc: EditraStyledTextCtrl
+ @param pos: current carat position
+ @param ichar: Indentation character
+
+ """
+ rtxt = u''
+ line = estc.GetCurrentLine()
+ text = estc.GetTextRange(estc.PositionFromLine(line), pos)
+ eolch = estc.GetEOLChar()
+
+ indent = estc.GetLineIndentation(line)
+ if ichar == u"\t":
+ tabw = estc.GetTabWidth()
+ else:
+ tabw = estc.GetIndent()
+
+ i_space = indent / tabw
+ ndent = eolch + ichar * i_space
+ rtxt = ndent + ((indent - (tabw * i_space)) * u' ')
+
+ def_pat = re.compile('\s*(class|def)\s+[a-zA-Z_][a-zA-Z0-9_]*')
+ text = text.strip()
+ if text.endswith('{') or def_pat.match(text):
+ rtxt += ichar
+
+ # Put text in the buffer
+ estc.AddText(rtxt)
+
+#---- Syntax Modules Internal Functions ----#
+def KeywordString(option=0):
+ """Returns the specified Keyword String
+ @note: not used by most modules
+
+ """
+ return RUBY_KW[1]
+
+#---- End Syntax Modules Internal Functions ----#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_s.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_s.py
new file mode 100644
index 0000000..cb156af
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_s.py
@@ -0,0 +1,231 @@
+###############################################################################
+# Name: s.py #
+# Purpose: Define S and R syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: s.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for the S and R statistical languages
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _s.py 70466 2012-01-26 20:55:16Z CJP $"
+__revision__ = "$Revision: 70466 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+from pygments.token import Token
+from pygments.lexers import get_lexer_by_name
+import wx
+import wx.stc as stc
+
+#Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+# Style Id's
+
+STC_S_DEFAULT, \
+STC_S_COMMENT, \
+STC_S_NUMBER, \
+STC_S_STRING, \
+STC_S_STRINGEOL, \
+STC_S_OPERATOR, \
+STC_S_KEYWORD = range(7)
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+KEYWORDS = ("all array break call else exp for function if length library list "
+ "match max mean min while return try NULL NA TRUE FALSE")
+
+R_KEYWORDS = "if else repeat while function for in next break TRUE FALSE NULL NA Inf NaN"
+R_KEYWORDS2 = ("abbreviate abline abs acf acos acosh addmargins aggregate agrep "
+ "alarm alias alist all anova any aov aperm append apply approx "
+ "approxfun apropos ar args arima array arrows asin asinh assign "
+ "assocplot atan atanh attach attr attributes autoload autoloader "
+ "ave axis backsolve barplot basename beta bindtextdomain binomial "
+ "biplot bitmap bmp body box boxplot bquote break browser builtins "
+ "bxp by bzfile c call cancor capabilities casefold cat category "
+ "cbind ccf ceiling character charmatch chartr chol choose chull "
+ "citation class close cm cmdscale codes coef coefficients col "
+ "colnames colors colorspaces colours comment complex confint "
+ "conflicts contour contrasts contributors convolve cophenetic "
+ "coplot cor cos cosh cov covratio cpgram crossprod cummax cummin "
+ "cumprod cumsum curve cut cutree cycle data dataentry date dbeta "
+ "dbinom dcauchy dchisq de debug debugger decompose delay deltat "
+ "demo dendrapply density deparse deriv det detach determinant "
+ "deviance dexp df dfbeta dfbetas dffits dgamma dgeom dget dhyper "
+ "diag diff diffinv difftime digamma dim dimnames dir dirname "
+ "dist dlnorm dlogis dmultinom dnbinom dnorm dotchart double "
+ "dpois dput drop dsignrank dt dump dunif duplicated dweibull "
+ "dwilcox eapply ecdf edit effects eigen emacs embed end "
+ "environment eval evalq example exists exp expression factanal "
+ "factor factorial family fft fifo file filter find fitted fivenum "
+ "fix floor flush for force formals format formula forwardsolve "
+ "fourfoldplot frame frequency ftable function gamma gaussian gc "
+ "gcinfo gctorture get getenv geterrmessage gettext gettextf getwd "
+ "gl glm globalenv gray grep grey grid gsub gzcon gzfile hat "
+ "hatvalues hcl hclust head heatmap help hist history hsv "
+ "httpclient iconv iconvlist identical identify if ifelse image "
+ "influence inherits integer integrate interaction interactive "
+ "intersect invisible isoreg jitter jpeg julian kappa kernapply "
+ "kernel kmeans knots kronecker ksmooth labels lag lapply layout "
+ "lbeta lchoose lcm legend length letters levels lfactorial "
+ "lgamma library licence license line lines list lm load "
+ "loadhistory loadings local locator loess log logb logical "
+ "loglin lowess ls lsfit machine mad mahalanobis makepredictcall "
+ "manova mapply match matlines matplot matpoints matrix max mean "
+ "median medpolish menu merge message methods mget min missing "
+ "mode monthplot months mosaicplot mtext mvfft names napredict "
+ "naprint naresid nargs nchar ncol next nextn ngettext nlevels nlm "
+ "nls noquote nrow numeric objects offset open optim optimise "
+ "optimize options order ordered outer pacf page pairlist pairs "
+ "palette par parse paste pbeta pbinom pbirthday pcauchy pchisq "
+ "pdf pentagamma person persp pexp pf pgamma pgeom phyper pi pico "
+ "pictex pie piechart pipe plclust plnorm plogis plot pmatch pmax "
+ "pmin pnbinom png pnorm points poisson poly polygon polym "
+ "polyroot postscript power ppoints ppois ppr prcomp predict "
+ "preplot pretty princomp print prmatrix prod profile profiler "
+ "proj promax prompt provide psigamma psignrank pt ptukey punif "
+ "pweibull pwilcox q qbeta qbinom qbirthday qcauchy qchisq qexp qf "
+ "qgamma qgeom qhyper qlnorm qlogis qnbinom qnorm qpois qqline "
+ "qqnorm qqplot qr qsignrank qt qtukey quantile quarters quasi "
+ "quasibinomial quasipoisson quit qunif quote qweibull qwilcox "
+ "rainbow range rank raw rbeta rbind rbinom rcauchy rchisq "
+ "readline real recover rect reformulate regexpr relevel remove "
+ "reorder rep repeat replace replicate replications require "
+ "reshape resid residuals restart return rev rexp rf rgamma rgb "
+ "rgeom rhyper rle rlnorm rlogis rm rmultinom rnbinom rnorm round "
+ "row rownames rowsum rpois rsignrank rstandard rstudent rt rug "
+ "runif runmed rweibull rwilcox sample sapply save savehistory "
+ "scale scan screen screeplot sd search searchpaths seek segments "
+ "seq sequence serialize setdiff setequal setwd shell sign signif "
+ "sin single sinh sink smooth solve sort source spectrum spline "
+ "splinefun split sprintf sqrt stack stars start stderr stdin "
+ "stdout stem step stepfun stl stop stopifnot str strftime "
+ "strheight stripchart strptime strsplit strtrim structure "
+ "strwidth strwrap sub subset substitute substr substring sum "
+ "summary sunflowerplot supsmu svd sweep switch symbols symnum "
+ "system t table tabulate tail tan tanh tapply tempdir tempfile "
+ "termplot terms tetragamma text time title toeplitz tolower "
+ "topenv toupper trace traceback transform trigamma trunc truncate "
+ "try ts tsdiag tsp typeof unclass undebug union unique uniroot "
+ "unix unlink unlist unname unserialize unsplit unstack untrace "
+ "unz update upgrade url var varimax vcov vector version vi "
+ "vignette warning warnings weekdays weights which while window "
+ "windows with write wsbrowser xedit xemacs xfig xinch xor xtabs "
+ "xyinch yinch zapsmall")
+R_KEYWORDS3 = ("acme aids aircondit amis aml banking barchart barley beaver "
+ "bigcity boot brambles breslow bs bwplot calcium cane "
+ "capability cav censboot channing city claridge cloth cloud "
+ "coal condense contourplot control corr darwin densityplot "
+ "dogs dotplot ducks empinf envelope environmental ethanol fir "
+ "frets gpar grav gravity grob hirose histogram islay knn "
+ "larrows levelplot llines logit lpoints lsegments lset ltext "
+ "lvqinit lvqtest manaus melanoma melanoma motor multiedit "
+ "neuro nitrofen nodal ns nuclear oneway parallel paulsen "
+ "poisons polar qq qqmath remission rfs saddle salinity shingle "
+ "simplex singer somgrid splom stripplot survival tau tmd "
+ "tsboot tuna unit urine viewport wireframe wool xyplot")
+
+#---- Syntax Style Specs ----#
+if wx.VERSION >= (2, 9, 0, 0, ''):
+ SYNTAX_ITEMS = [ (stc.STC_R_BASEKWORD, 'class_style'), #TODO
+ (stc.STC_R_COMMENT, 'comment_style'),
+ (stc.STC_R_DEFAULT, 'default_style'),
+ (stc.STC_R_IDENTIFIER, 'default_style'),
+ (stc.STC_R_INFIX, 'default_style'), #TODO
+ (stc.STC_R_INFIXEOL, 'default_style'), #TODO
+ (stc.STC_R_KWORD, 'keyword_style'),
+ (stc.STC_R_NUMBER, 'number_style'),
+ (stc.STC_R_OPERATOR, 'operator_style'),
+ (stc.STC_R_OTHERKWORD, 'keyword2_style'),
+ (stc.STC_R_STRING, 'string_style'),
+ (stc.STC_R_STRING2, 'char_style')] #TODO
+else:
+ SYNTAX_ITEMS = [ (STC_S_DEFAULT, 'default_style'),
+ (STC_S_COMMENT, 'comment_style'),
+ (STC_S_NUMBER, 'number_style'),
+ (STC_S_STRING, 'string_style'),
+ (STC_S_STRINGEOL, 'stringeol_style'),
+ (STC_S_OPERATOR, 'operator_style'),
+ (STC_S_KEYWORD, 'keyword_style') ]
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for R and S"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ if wx.VERSION >= (2, 9, 0, 0, ''):
+ self.SetLexer(stc.STC_LEX_R)
+ else:
+ self.SetLexer(stc.STC_LEX_CONTAINER)
+ self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ if wx.VERSION >= (2, 9, 0, 0, ''):
+ return [(0, R_KEYWORDS), (1, R_KEYWORDS2), (2, R_KEYWORDS3)]
+ else:
+ return [(1, KEYWORDS)]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u"#",]
+
+#-----------------------------------------------------------------------------#
+
+def StyleText(_stc, start, end):
+ """Style the text
+ @param _stc: Styled text control instance
+ @param start: Start position
+ @param end: end position
+ @todo: performance improvements
+ @todo: style errors caused by unicode characters (related to internal utf8)
+
+ """
+ cpos = 0
+ _stc.StartStyling(cpos, 0x1f)
+ lexer = get_lexer_by_name("s")
+ is_wineol = _stc.GetEOLMode() == stc.STC_EOL_CRLF
+ for token, txt in lexer.get_tokens(_stc.GetTextRange(0, end)):
+ style = TOKEN_MAP.get(token, STC_S_DEFAULT)
+
+ tlen = len(txt)
+
+ # Account for \r\n end of line characters
+ if is_wineol and "\n" in txt:
+ tlen += txt.count("\n")
+
+ if tlen:
+ _stc.SetStyling(tlen, style)
+ cpos += tlen
+ _stc.StartStyling(cpos, 0x1f)
+
+#-----------------------------------------------------------------------------#
+
+TOKEN_MAP = { Token.Literal.String : STC_S_STRING,
+ Token.Comment : STC_S_COMMENT,
+ Token.Comment.Single : STC_S_COMMENT,
+ Token.Operator : STC_S_OPERATOR,
+ Token.Punctuation : STC_S_OPERATOR,
+ Token.Number : STC_S_NUMBER,
+ Token.Literal.Number : STC_S_NUMBER,
+ Token.Keyword : STC_S_KEYWORD,
+ Token.Keyword.Constant: STC_S_KEYWORD }
+ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sh.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sh.py
new file mode 100644
index 0000000..78a07dc
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sh.py
@@ -0,0 +1,131 @@
+###############################################################################
+# Name: sh.py #
+# Purpose: Define Bourne/Bash/Csh/Korn Shell syntaxes for highlighting and #
+# other features. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: sh.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration file for Bourne, Bash, Kornshell and
+ C-Shell scripts.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _sh.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+# Bourne Shell Keywords (bash and kornshell have these too)
+COMM_KEYWORDS = ("break eval newgrp return ulimit cd exec pwd shift umask "
+ "chdir exit read test wait continue kill readonly trap "
+ "contained elif else then case esac do done for in if fi "
+ "until while set export unset")
+
+# Bash/Kornshell extensions (in bash/kornshell but not bourne)
+EXT_KEYWORDS = ("function alias fg integer printf times autoload functions "
+ "jobs r true bg getopts let stop type false hash nohup suspend "
+ "unalias fc history print time whence typeset while select")
+
+# Bash Only Keywords
+BSH_KEYWORDS = ("bind disown local popd shopt builtin enable logout pushd "
+ "source dirs help declare")
+
+# Bash Shell Commands (statements)
+BCMD_KEYWORDS = ("chmod chown chroot clear du egrep expr fgrep find gnufind "
+ "gnugrep grep install less ls mkdir mv reload restart rm "
+ "rmdir rpm sed su sleep start status sort strip tail touch "
+ "complete stop echo")
+
+# Korn Shell Only Keywords
+KSH_KEYWORDS = "login newgrp"
+
+# Korn Shell Commands (statements)
+KCMD_KEYWORDS = ("cat chmod chown chroot clear cp du egrep expr fgrep find "
+ "grep install killall less ls mkdir mv nice printenv rm rmdir "
+ "sed sort strip stty su tail touch tput")
+
+# C-Shell Keywords
+CSH_KEYWORDS = ("alias cd chdir continue dirs echo break breaksw foreach end "
+ "eval exec exit glob goto case default history kill login "
+ "logout nice nohup else endif onintr popd pushd rehash repeat "
+ "endsw setenv shift source time umask switch unalias unhash "
+ "unsetenv wait")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_SH_DEFAULT, 'default_style'),
+ (stc.STC_SH_BACKTICKS, 'scalar_style'),
+ (stc.STC_SH_CHARACTER, 'char_style'),
+ (stc.STC_SH_COMMENTLINE, 'comment_style'),
+ (stc.STC_SH_ERROR, 'error_style'),
+ (stc.STC_SH_HERE_DELIM, 'here_style'),
+ (stc.STC_SH_HERE_Q, 'here_style'),
+ (stc.STC_SH_IDENTIFIER, 'default_style'),
+ (stc.STC_SH_NUMBER, 'number_style'),
+ (stc.STC_SH_OPERATOR, 'operator_style'),
+ (stc.STC_SH_PARAM, 'scalar_style'),
+ (stc.STC_SH_SCALAR, 'scalar_style'),
+ (stc.STC_SH_STRING, 'string_style'),
+ (stc.STC_SH_WORD, 'keyword_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FLD_COMMENT = ("fold.comment", "1")
+FLD_COMPACT = ("fold.compact", "0")
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for various shell scripting languages"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_BASH)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ keywords = list()
+ keyw_str = [COMM_KEYWORDS]
+ if self.LangId == synglob.ID_LANG_CSH:
+ keyw_str.append(CSH_KEYWORDS)
+ else:
+ if self.LangId != synglob.ID_LANG_BOURNE: # TODO ??
+ keyw_str.append(EXT_KEYWORDS)
+
+ if self.LangId == synglob.ID_LANG_BASH:
+ keyw_str.append(BSH_KEYWORDS)
+ keyw_str.append(BCMD_KEYWORDS)
+ elif self.LangId == synglob.ID_LANG_KSH:
+ keyw_str.append(KSH_KEYWORDS)
+ keyw_str.append(KCMD_KEYWORDS)
+ else:
+ pass
+
+ keywords.append((0, " ".join(keyw_str)))
+ return keywords
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FLD_COMMENT, FLD_COMPACT]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_smalltalk.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_smalltalk.py
new file mode 100644
index 0000000..1929809
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_smalltalk.py
@@ -0,0 +1,91 @@
+###############################################################################
+# Name: smalltalk.py #
+# Purpose: Define Smalltalk syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: smalltalk.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Smalltalk
+@todo: more keywords, styling fixes
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _smalltalk.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+# Special Selectors
+ST_KEYWORDS = (0, "ifTrue: ifFalse: whileTrue: whileFalse: ifNil: ifNotNil: "
+ "whileTrue repeat isNil put to at notNil super self "
+ "true false new not isNil inspect out nil do add for "
+ "methods methodsFor instanceVariableNames classVariableNames "
+ "poolDictionaries subclass")
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_ST_ASSIGN, 'operator_style'),
+ (stc.STC_ST_BINARY, 'operator_style'),
+ (stc.STC_ST_BOOL, 'keyword_style'),
+ (stc.STC_ST_CHARACTER, 'char_style'),
+ (stc.STC_ST_COMMENT, 'comment_style'),
+ (stc.STC_ST_DEFAULT, 'default_style'),
+ (stc.STC_ST_GLOBAL, 'global_style'),
+ (stc.STC_ST_KWSEND, 'keyword_style'),
+ (stc.STC_ST_NIL, 'keyword_style'),
+ (stc.STC_ST_NUMBER, 'number_style'),
+ (stc.STC_ST_RETURN, 'keyword_style'),
+ (stc.STC_ST_SELF, 'keyword_style'),
+ (stc.STC_ST_SPECIAL, 'pre_style'),
+ (stc.STC_ST_SPEC_SEL, 'keyword_style'), # Words in keyword list
+ (stc.STC_ST_STRING, 'string_style'),
+ (stc.STC_ST_SUPER, 'class_style'),
+ (stc.STC_ST_SYMBOL, 'scalar_style')]
+
+#---- Extra Properties ----#
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Smalltalk"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_SMALLTALK)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [ST_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'\"', u'\"']
+
+#---- Syntax Modules Internal Functions ----#
+def KeywordString():
+ """Returns the specified Keyword String
+ @note: not used by most modules
+
+ """
+ return ST_KEYWORDS[1]
+
+#---- End Syntax Modules Internal Functions ----#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sql.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sql.py
new file mode 100644
index 0000000..49347bd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sql.py
@@ -0,0 +1,392 @@
+###############################################################################
+# Name: sql.py #
+# Purpose: Define SQL syntax for highlighting and other features #
+# Author: Thomas Keul <tgkeul@web.de> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: sql.py
+AUTHOR: Thomas Keul
+
+SUMMARY:
+Lexer configuration module for Oracle 10 PL/SQL (and SQL, sqlplus, pldoc).
+This work is based on sql.properties of SciTE 1.74 and other documents
+which are linked (these links where current in October 2007)
+
+The keywords are divided in several sections which unfortunally overlap.
+As a fulltime PL/SQL programmer I decided which section I prefer for a
+keyword which belongs to multiple sections (like 'in', 'to' or 'else').
+It may be a challange to create an editor which colour the multiple
+used keywords depending on their context.
+/*+ HINT use same color for PL/SQL and SQL */
+Another thing the SQL-Lexer is not able to handle is a token consisting
+of several keywords. Although zone is only part in type definitions as
+"timestamp with local time zone" it will be coloured if used as identifier
+too.
+
+If you're unhappy feel free to change it or build a new SQL-Lexer :-)
+
+The sections I choose
+ - SQL keywords
+ - Exception names and transaction control (to hilite in a special color)
+ - SQL functions
+ - sqlplus keywords
+ - PL/SQL keywords
+ - data types
+ - standard packages
+ - pseudo variables and constants
+
+There are more section than supported by the lexer. Standard packages and
+sqlplus keywords share a slot. You may change it.
+
+In contrast to Gnome gtk-sourceview sql.lang file I did not divide the
+function section into subsections like "analytical functions".
+For my purpose distinct colours or fonts for different function types don't
+help me reading programs.
+... and the Scintilla SQL lexer does not support it.
+
+Some useful internals of the Lexer.
+It gets an array with 8 lists of keywords. These lists are defined below.
+
+ - WordList &keywords1 = *keywordlists[0]; : SQL_KW (SQL Keywords)
+ - WordList &keywords2 = *keywordlists[1]; : SQL_DBO (Data Types)
+ - WordList &kw_pldoc = *keywordlists[2]; : SQL_PLD (epydoc field tags)
+ - WordList &kw_sqlplus = *keywordlists[3]; : SQL_PLUS or SQL_PKG
+ - WordList &kw_user1 = *keywordlists[4]; : SQL_UKW1 (standard functions)
+ - WordList &kw_user2 = *keywordlists[5]; : SQL_UKW2 (exceptions)
+ - WordList &kw_user3 = *keywordlists[6]; : SQL_UKW3 (special variables)
+ - WordList &kw_user4 = *keywordlists[7]; : SQL_UKW4 (PL/SQL Keywords)
+
+As some keywords are used multiple the colour depends on the process in the
+lexer. I prefer the same colour for SQL and PL/SQL Keywords.
+
+if a token is realized as identifier, the keyword lists are scanned:
+ 1. keywords1 / SQL_KW
+ 2. keywords2 / SQL_DBO
+ 3. kw_sqlplus / SQL_PLUS
+ 4. kw_user1 / SQL_UKW1
+ 5. kw_user2 / SQL_UKW2
+ 6. kw_user3 / SQL_UKW3
+ 7. kw_user4 / SQL_UKW4
+
+What ever comes first wins. For this reason PL/SQL keyword are last in the
+list so no prior used keyword must be removed.
+Because of the preceeding @ pldoc is processed seperate.
+
+The Scintilla SQL Lexer 1.75 has a restriction when '#' and '$' are not
+identified as valid characters of an (Oracle-)identifier.
+wxPython 2.8.7.1 does not use not use lexer version 1.75 yet - so SQL_PKG
+wil not work.
+
+@summary: Lexer configuration module for Oracle 10 PL/SQL
+
+"""
+
+__author__ = "Thomas Keul <tgkeul@web.de>"
+__svnid__ = "$Id: _sql.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# SQL Keywords (Oracle 11g SQL reserved words)
+# (http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/ap_keywd.htm#i690190)
+SQL_KW = (0, "access add all alter and any as asc audit between by check "
+ "cluster column comment compress connect create current default "
+ "delete desc distinct drop else exclusive exists file for from "
+ "grant group having identified immediate in increment index "
+ "initial insert intersect into is like lock maxextents minus mode "
+ "modify noaudit nocompress not nowait number of offline on online "
+ "option or order pctfree prior privileges public rename resource "
+ "revoke row rows select session set share size start successful "
+ "synonym table to trigger union unique update validate values "
+ "view whenever where with primary key constraint foreign "
+ "references restrict no action without schema deferrable not "
+ "deferrable rule do")
+# dropped reserved words from the specification above:
+# char date decimal float integer long mlslabel number raw smallint varchar
+# varchar2 => SQL_DBO
+# level null rowid rownum sysdate uid user => SQL_UKW4
+# then => SQL_UKW3
+
+# SQL Data Object (ORACLE 11g predefined SQL and PL/SQL data types)
+# (http://download.oracle.com/docs/cd/B28359_01/appdev.111/b31088/exprn_expconcepts.htm#EXPRN007)
+SQL_DBO = (1, "anydata anydataset anytype bfile binary_float binary_integer "
+ "blob boolean char character clob date day dburitype dec decimal "
+ "double dsinterval_unconstrained float httpuritype int integer "
+ "interval local long minute mlslabel month national natural "
+ "naturaln nchar nclob number numeric nvarchar2 ordaudio orddicom "
+ "orddoc ordimage ordimagesignature ordvideo pls_integer positive "
+ "positiven precision raw real rowid sdo_geometry sdo_georaster "
+ "sdo_topo_geometry second second si_averagecolor si_color "
+ "si_colorhistogram si_featurelist si_positionalcolor "
+ "si_stillimage si_texture signtype simple_double simple_float "
+ "simple_integer smallint time timestamp timestamp_unconstrained "
+ "timestamp_ltz_unconstrained timestamp_tz_unconstrained urowid "
+ "varchar varchar2 varying xdburitype xmltype year "
+ "yminterval_unconstrained zone serial")
+# Note: some data types consist of more than one word like "interval year to
+# month" or "timestamp with local time zone"
+# some of these words are preferred in other sections:
+# to with => SQL_KW
+# cursor => SQL_UKW4
+
+# SQL PLDoc Keywords (and epydoc and ... enhance as you like it)
+# (http://pldoc.sourceforge.net/docs/Users_Guide/content.html)
+SQL_PLD = (2, "TODO author deprecated headcom param return see since throws "
+ "type ")
+
+# SQL Plus (I avoid sqlplus, so this section may be outdated)
+SQL_PLUS = (3, "acc~ept a~ppend archive attribute bre~ak bti~tle c~hange "
+ "col~umn comp~ute conn~ect copy def~ine del desc~ribe e~dit "
+ "exec~ute exit get help ho~st i~nput l~ist log passw~ord pau~se "
+ "pri~nt pro~mpt quit recover rem~ark repf~ooter reph~eader r~un "
+ "sav~e set sho~w shutdown spo~ol sta~rt startup store timi~ng "
+ "undef~ine var~iable whenever oserror whenever sqlerror cl~ear "
+ "disc~onnect ti~tle ")
+
+# SQL User Keywords 1 (Oracle 11g SQL Functions)
+# (http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/functions001.htm#i88893)
+SQL_UKW1 = (4, "abs acos add_months appendchildxml ascii asciistr asin atan "
+ "atan2 avg bfilename bin_to_num bitand cardinality cast ceil "
+ "chartorowid chr cluster_id cluster_probability cluster_set "
+ "coalesce compose concat convert corr cos cosh count count "
+ "covar_pop covar_samp cume_dist current_date current_timestamp "
+ "cv dbtimezone decode decompose deletexml dense_rank depth "
+ "deref dump empty_blob empty_clob existsnode exp extract "
+ "extractvalue feature_id feature_set feature_value first "
+ "first_value floor from_tz greatest group_id grouping "
+ "grouping_id hextoraw initcap insertchildxml insertxmlbefore "
+ "instr iteration_number lag last last_day last_value lead least "
+ "length ln lnnvl localtimestamp log lower lpad ltrim make_ref "
+ "max median min mod months_between nanvl new_time next_day "
+ "nls_charset_decl_len nls_charset_id nls_charset_name "
+ "nls_initcap nls_lower nls_upper nlssort ntile nullif "
+ "numtodsinterval numtoyminterval nvl nvl2 ora_hash path "
+ "percent_rank percentile_cont percentile_disc power "
+ "powermultiset powermultiset_by_cardinality prediction "
+ "prediction_bounds prediction_cost prediction_details "
+ "prediction_probability prediction_set presentnnv presentv "
+ "previous rank ratio_to_report rawtohex rawtonhex ref reftohex "
+ "regexp_instr regexp_replace regexp_substr remainder "
+ "round row_number rowidtochar rowidtonchar rpad rtrim "
+ "scn_to_timestamp sessiontimezone set sign sin sinh soundex "
+ "sqrt stats_binomial_test stats_crosstab stats_f_test "
+ "stats_ks_test stats_mode stats_mw_test stats_one_way_anova "
+ "stats_t_test_ stats_wsr_test stddev stddev_pop stddev_samp "
+ "substr sum sys_connect_by_path sys_dburigen sys_extract_utc "
+ "sys_xmlagg sys_xmlgen sysdate systimestamp tan tanh "
+ "timestamp_to_scn to_binary_double to_binary_float to_char "
+ "to_clob to_date to_dsinterval to_lob to_multi_byte to_nchar "
+ "to_nclob to_number to_single_byte to_timestamp to_timestamp_tz "
+ "to_yminterval translate treat trim trunc tz_offset unistr "
+ "updatexml upper value var_pop var_samp variance vsize "
+ "width_bucket xmlagg xmlcast xmlcdata xmlcolattval xmlcomment "
+ "xmlconcat xmldiff xmlelement xmlexists xmlforest xmlparse "
+ "xmlpatch xmlpi xmlquery xmlroot xmlsequence xmlserialize "
+ "xmltable xmltransform")
+# replace, collect => SQL_UKW4
+
+# SQL User Keywords 2 (Oracle 11g exceptions and transaction control)
+SQL_UKW2 = (5, "access_into_null case_not_found collection_is_null "
+ "cursor_already_open dup_val_on_index invalid_cursor "
+ "invalid_number login_denied no_data_found not_logged_on "
+ "program_error rowtype_mismatch self_is_null storage_error "
+ "subscript_beyond_count subscript_outside_limit "
+ "sys_invalid_rowid timeout_on_resource too_many_rows "
+ "value_error zero_divide commit savepoint rollback")
+
+# SQL User KW3 (Oracle 11g pseudo variables, methods and constants)
+SQL_UKW3 = (6, "binary_double_infinity binary_double_max_normal "
+ "binary_double_max_subnormal binary_double_min_normal "
+ "binary_double_min_subnormal binary_double_nan "
+ "binary_float_infinity1 binary_float_max_normal "
+ "binary_float_max_subnormal binary_float_min_normal "
+ "binary_float_min_subnormal binary_float_nan1 count currval "
+ "delete exists extend false first last level limit next nextval "
+ "null prior rowlabel rownum sql sqlcode sqldata sqlname "
+ "sqlstate sysdate trim true uid user")
+
+# SQL User Keywords 4 (Oracle 11g PL/SQL reserved and keywords)
+# (http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/reservewords.htm#CHDBBJFE)
+SQL_UKW4 = (7, "a add agent aggregate all alter and any array arrow as asc at "
+ "attribute authid avg begin between bfile_base binary blob_base "
+ "block body both bound bulk by byte c call calling cascade case "
+ "char_base charset charsetform charsetid check clob_base close "
+ "cluster clusters colauth collect columns comment commit "
+ "committed compiled compress connect constant constructor "
+ "context continue convert count crash create current cursor "
+ "customdatum dangling date_base declare default define delete "
+ "desc deterministic distinct drop duration element else elsif "
+ "empty end escape except exception exceptions exclusive execute "
+ "exists exit external fetch final fixed for forall force form "
+ "from function general goto grant group hash having heap hidden "
+ "hour identified if immediate in including index indexes "
+ "indicator indices infinite insert instantiable interface "
+ "intersect interval into invalidate is isolation java anguage "
+ "large leading length level library like like2 like4 likec "
+ "limit limited local lock long loop map max maxlen member merge "
+ "min minus minute mod mode modify month multiset name nan "
+ "national native nchar new nocompress nocopy not nowait null "
+ "number_base object ocicoll ocidate ocidatetime ociduration "
+ "ociinterval ociloblocator ocinumber ociraw ociref ocirefcursor "
+ "ocirowid ocistring ocitype of on only opaque open operator "
+ "option or oracle oradata order organization orlany orlvary "
+ "others out overlaps overriding package parallel_enable "
+ "parameter parameters partition pascal pipe pipelined pragma "
+ "precision prior private procedure public raise range raw read "
+ "record ref reference relies_on rem remainder rename replace "
+ "resource result result_cache return returning reverse revoke "
+ "rollback row sample save savepoint sb1 sb2 sb4 second segment "
+ "select self separate sequence serializable set share short "
+ "size size_t some sparse sql sqlcode sqldata sqlname sqlstate "
+ "standard start static stddev stored string struct style "
+ "submultiset subpartition substitutable subtype sum synonym "
+ "tabauth table tdo the then time timestamp timezone_abbr "
+ "timezone_hour timezone_minute timezone_region to trailing "
+ "transaction transactional trusted type ub1 ub2 ub4 under union "
+ "unique unsigned untrusted update use using valist value values "
+ "variable variance varray varying view views void when where "
+ "while with work wrapped write year zone")
+# char character date day decimal double float int => SQL_CBO
+
+# SQL PLUS replacement - for people not forced using acient tools
+# (needs Scintilla 1.75 SQL Lexer to handle)
+SQL_PKG = (3, "apex_custom_auth apex_application apex_item apex_util ctx_adm "
+ "ctx_cls ctx_ddl ctx_doc ctx_output ctx_query ctx_report "
+ "ctx_thes ctx_ulexer dbms_addm dbms_advanced_rewrite "
+ "dbms_advisor dbms_alert dbms_application_info dbms_apply_adm "
+ "dbms_aq dbms_aqadm dbms_aqelm dbms_aqin dbms_assert "
+ "dbms_auto_task_admin dbms_aw_stats dbms_capture_adm "
+ "dbms_cdc_publish dbms_cdc_subscribe dbms_comparison "
+ "dbms_connection_pool dbms_cq_notification dbms_crypto "
+ "dbms_csx_admin dbms_cube dbms_cube_advise dbms_data_mining "
+ "dbms_data_mining_transform dbms_datapump dbms_db_version "
+ "dbms_ddl dbms_debug dbms_defer dbms_defer_query dbms_defer_sys "
+ "dbms_describe dbms_dg dbms_dimension "
+ "dbms_distributed_trust_admin dbms_epg dbms_errlog dbms_expfil "
+ "dbms_fga dbms_file_group dbms_file_transfer dbms_flashback "
+ "dbms_frequent_itemset dbms_hm dbms_hprof dbms_hs_parallel "
+ "dbms_hs_passthrough dbms_iot dbms_java dbms_job dbms_ldap "
+ "dbms_ldap_utl dbms_libcache dbms_lob dbms_lock dbms_logmnr "
+ "dbms_logmnr_d dbms_logstdby dbms_metadata dbms_mgd_id_utl "
+ "dbms_mgwadm dbms_mgwmsg dbms_monitor dbms_network_acl_admin "
+ "dbms_network_acl_utility dbms_obfuscation_toolkit dbms_odci "
+ "dbms_offline_og dbms_outln dbms_outln_edit dbms_output "
+ "dbms_pclxutil dbms_pipe dbms_predictive_analytics "
+ "dbms_preprocessor dbms_profiler dbms_propagation_adm "
+ "dbms_random dbms_rectifier_diff dbms_redefinition "
+ "dbms_refresh dbms_repair dbms_repcat dbms_repcat_admin "
+ "dbms_repcat_instantiate dbms_repcat_rgt dbms_reputil "
+ "dbms_resconfig dbms_resource_manager "
+ "dbms_resource_manager_privs dbms_result_cache dbms_resumable "
+ "dbms_rlmgr dbms_rls dbms_rowid dbms_rule dbms_rule_adm "
+ "dbms_scheduler dbms_server_alert dbms_service dbms_session "
+ "dbms_shared_pool dbms_space dbms_space_admin dbms_spm dbms_sql "
+ "dbms_sqldiag dbms_sqlpa dbms_sqltune dbms_stat_funcs "
+ "dbms_stats dbms_storage_map dbms_streams dbms_streams_adm "
+ "dbms_streams_advisor_adm dbms_streams_auth "
+ "dbms_streams_messaging dbms_streams_tablespace_adm "
+ "dbms_tdb dbms_trace dbms_transaction dbms_transform dbms_tts "
+ "dbms_types dbms_utility dbms_warning dbms_wm "
+ "dbms_workload_capture dbms_workload_replay "
+ "dbms_workload_repository dbms_xa dbms_xdb dbms_xdb_admin "
+ "dbms_xdbresource dbms_xdb_version dbms_xdbt dbms_xdbz "
+ "dbms_xevent dbms_xmldom dbms_xmlgen dbms_xmlindex "
+ "dbms_xmlparser dbms_xmlquery dbms_xmlsave dbms_xmlschema "
+ "dbms_xmlstore dbms_xmltranslations dbms_xplan "
+ "dbms_xslprocessor debug_extproc htf htp ord_dicom "
+ "ord_dicom_admin owa_cache owa_cookie owa_custom owa_image "
+ "owa_opt_lock owa_pattern owa_sec owa_text owa_util sdo_cs "
+ "sdo_csw_process sdo_gcdr sdo_geom sdo_geor sdo_geor_admin "
+ "sdo_geor_utl sdo_lrs sdo_migrate sdo_net sdo_net_mem sdo_ols "
+ "sdo_pc_pkg sdo_sam sdo_tin_pkg sdo_topo sdo_topo_map sdo_tune "
+ "sdo_util sdo_wfs_lock sdo_wfs_process sem_apis sem_perf "
+ "utl_coll utl_compress utl_dbws utl_encode utl_file utl_http "
+ "utl_i18n utl_inaddr utl_lms utl_mail utl_nla utl_raw "
+ "utl_recomp utl_ref utl_smtp utl_spadv utl_tcp utl_url "
+ "wpg_docload ")
+
+#---- Syntax Style Specs ----#
+# Scintilla 1.75 SQL Lexer
+SYNTAX_ITEMS = [ (stc.STC_SQL_DEFAULT, 'default_style'), # 0
+ (stc.STC_SQL_CHARACTER, 'char_style'), # 7
+ (stc.STC_SQL_COMMENT, 'comment_style'), # 1
+ (stc.STC_SQL_COMMENTDOC, 'comment_style'), # 3
+ (stc.STC_SQL_COMMENTDOCKEYWORD, 'dockey_style'), # 17
+ (stc.STC_SQL_COMMENTDOCKEYWORDERROR, 'error_style'), # 18
+ (stc.STC_SQL_COMMENTLINE, 'comment_style'), # 2
+ (stc.STC_SQL_COMMENTLINEDOC, 'comment_style'), # 15
+ (stc.STC_SQL_IDENTIFIER, 'default_style'), # 11
+ (stc.STC_SQL_NUMBER, 'number_style'), # 4
+ (stc.STC_SQL_OPERATOR, 'operator_style'), # 10
+ (stc.STC_SQL_QUOTEDIDENTIFIER, 'default_style'), # 23
+ (stc.STC_SQL_SQLPLUS, 'scalar_style'), # 8
+ #('STC_SQL_SQLPLUS', 'funct_style'), # 8
+ (stc.STC_SQL_SQLPLUS_COMMENT, 'comment_style'), # 13
+ (stc.STC_SQL_SQLPLUS_PROMPT, 'default_style'), # 9
+ (stc.STC_SQL_STRING, 'string_style'), # 6
+ (stc.STC_SQL_USER1, 'funct_style'), # 19
+ (stc.STC_SQL_USER2, 'directive_style'), # 20
+ (stc.STC_SQL_USER3, 'keyword3_style'), # 21
+ (stc.STC_SQL_USER4, 'keyword_style'), # 22
+ (stc.STC_SQL_WORD, 'keyword_style'), # 5
+ (stc.STC_SQL_WORD2, 'keyword2_style') ] # 16
+
+#---- Extra Properties ----#
+# found in LexSQL.cxx of Scintilla 1.74
+# Folding is rather poor for PL/SQL
+FOLD = ("fold", "1")
+FOLD_COMMENT = ("fold.comment", "1")
+FOLD_COMPACT = ("fold.compact", "0")
+FOLD_SQL_ONLY_BEGIN = ("fold.sql.only.begin", "0")
+
+# Properties which do not match PL/SQL
+SQL_BACKSLASH_ESCAPES = ("sql.backslash.escapes", "0")
+SQL_BACKTICKS_IDENTIFIER = ("lexer.sql.backticks.identifier", "0")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for PL/SQL"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_SQL)
+
+ def GetKeywords(self):
+ """ Returns Specified Keywords List """
+ common = [ SQL_KW, SQL_DBO, SQL_PLD, SQL_UKW1, SQL_UKW2, SQL_UKW4 ]
+ if self.LangId == synglob.ID_LANG_SQL:
+ common.append(SQL_PLUS)
+ else:
+ common.extend([SQL_PKG, SQL_UKW3])
+ return common
+
+ def GetSyntaxSpec(self):
+ """ Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """ Returns a list of Extra Properties to set """
+ if self.LangId == synglob.ID_LANG_SQL:
+ return [FOLD]
+ else:
+ return [FOLD, FOLD_COMMENT, FOLD_COMPACT, FOLD_SQL_ONLY_BEGIN,
+ SQL_BACKSLASH_ESCAPES, SQL_BACKTICKS_IDENTIFIER]
+
+ def GetCommentPattern(self):
+ """ Returns a list of characters used to comment a block of code """
+ return [u'--']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_squirrel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_squirrel.py
new file mode 100644
index 0000000..e7a1362
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_squirrel.py
@@ -0,0 +1,65 @@
+###############################################################################
+# Name: squirrel.py #
+# Purpose: Syntax Definitions for Squirrel programming language #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+@summary: Lexer configuration module for Squirrel Programming Language
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _squirrel.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _cpp
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+SQUIRREL_KW = (0, "break case catch class clone continue const default "
+ "delegate delete do else enum extends for foreach function "
+ "if in local null resume return switch this throw try typeof "
+ "while parent yield constructor vargc vargv instanceof true "
+ "false static")
+
+SQUIRREL_TYPES = (1, "")
+
+#---- End Keyword Definitions ----#
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Squirrel"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _cpp.AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [SQUIRREL_KW, SQUIRREL_TYPES, _cpp.DOC_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return _cpp.SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [_cpp.FOLD,]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return ['//']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_stata.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_stata.py
new file mode 100644
index 0000000..46649f1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_stata.py
@@ -0,0 +1,434 @@
+###############################################################################
+# Name: stata.py #
+# Purpose: Define Stata syntax for highlighting and other features #
+# Author: Jean Eid<jeid@wlu.ca> #
+# Note: stata keywords are taken from TextWrangler module for stata #
+###############################################################################
+
+"""
+FILE: stata.py
+@author: Jean Eid
+@summary: Lexer configuration file for STATA source files.
+
+"""
+
+__author__ = "Jean Eid <jeid@wlu.ca>"
+__svnid__ = "$Id: _stata.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 0$"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local imports
+import synglob
+import syndata
+from _cpp import AutoIndenter
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Documentation Keywords (includes Doxygen keywords)
+SECONDARY_KEYWORDS =(1,
+ """
+ __GEEBT __GEERC __GEEUC _3dax0 _3daxmin _3daxout if
+ _3daxtbl _3ddflts _3dmkdta _3dmnmx _3dproj _3drproj
+ _3drshow _3dshad _3dsvusr _ac _addl _addop _adjksm
+ _all _bsqreg _byobs _callerr _cpmatnm _cr1form
+ _cr1invt _cr1se _cr1t _crc2use _crc4fld _crcacnt
+ _crcar1 _crcause _crcbcrt _crcbin _crcbygr _crcchi2
+ _crcchkt _crcchkw _crcci _crccip _crceprs _crcexn1
+ _crcexn2 _crcexn4 _crcexn5 _crcexn6 _crcexn7 _crcexn8
+ _crcexn9 _crcexna _crcexnb _crcexnc _crcexnd _crcexne
+ _crcexnf _crcexnt _crcgldv _crcglil _crcichi _crcird
+ _crcirr _crcksm _crclf _crcmeq _crcmiss _crcnlou
+ _crcnms2 _crcnuse _crcor _crcphdr _crcplst _crcra
+ _crcrd _crcrnfd _crcrr _crcrsfl _crcseq _crcshdr
+ _crcslbl _crcsrv2 _crcsrvc _crcstep _crcswxx _crct
+ _crctmge _crcunab _crcunit _crcvarl _crcwsrv _crczsku
+ _cu_c0 _diparm _evlist _fracchk _fraccox _fracddp
+ _fracdis _fracdv _fracin _fracmdp _fracord _fracpp
+ _fracpv _fracrep _fracwgt _fracxo _gcount _gcut _gdiff
+ _getbv _getrhs _getrres _gfill _ggroup _giqr _gladder
+ _glmfl _glmilnk _glmmapf _glmmapl _glmresd _glmrpt
+ _glmwgt _gma _gmad _gmax _gmdmean _gmdmed _gmean
+ _gmedian _gmin _gmtr _gpctile _grank _grank2 _grfirst
+ _grlast _grmax _grmean _grmin _grmiss _grmiss2 _grobs
+ _grsd _grsum _gsd _gsrank _gstd _gsum _gtma _gtrank
+ _hu _hub _hube _huber _inlist _invlist _isfit _jprfpdt
+ _jprfpdx _jprfpfp _jprfpgn _jprfpin _jprfplx _jprfpmm
+ _jprfppp _jprfpre _jprfprp _jprfpse _jprfptp _jprfpxo
+ _jprglef _jprglfl _jprglil _jprglld _jprglwz _jprxrpa
+ _kalman1 _ksmwrk _ldrtest _linemax _maked _merge
+ _mfrmvec _mkvec _mvec _newey _nlout _nobs _opnum
+ _parsevl _parsewt _partset _pctile _pred_me _pred_se
+ _predict _qreg _repart _result _rmcoll _robksm _robust
+ _sfran _subchar _svy _sw_lik _sw_lik2 _sw_ood _ts
+ _ts_dsmp _ts_flag _ts_gdat _ts_meqn _ts_pars _ts_peri
+ _tsheadr _ttest _ttest1 _ttest2 _tutends _tx_mtr1
+ _tx_mtr2 _tx_mtr3 _tx_mtr4 _tx_mtr5 _tx_rpl _wkapm
+ _wsrvcrv _xtrenorm
+ """)
+
+MAIN_KEYWORDS = (0,
+ """
+ abbrev about abs acprplot add
+ adjust ado adopath alpha an ano anov anova anovadef
+ aorder ap app appe appen append arch arch_dr arch_p
+ areg areg_p args arima arima_dr arima_p as ass asse
+ asser assert at avplot avplots aw aweight bcskew0 be
+ bee beep binreg bipp_lf bipr_lf bipr_p biprobit bitest
+ bitesti bitowt blogit bmemsize boot bootsamp boxcox
+ boxcox_p bprobit break brier bs bsampl_w bsample
+ bsqreg bstat bstrap by bys bysort byte c_local canon
+ canon_p capture cat cc cchart cci cd cell cellsize
+ centile cf char char chdir checksum chi2 chi2tail ci
+ cii cksum clear clo clocal clog clog_lf clog_p clogi
+ clogi_sw clogit clogit_p clogitp clogl_sw cloglog
+ close cluster cmdlog cnr cnre cnreg cnreg_sw cnsreg
+ codebook col collaps4 collapse compare compress
+ compute cond conf confi confir confirm cons const
+ constr constra constrai constrain constraint contract
+ copy cor corc corr corr2data corre correl correla
+ correlat correlate corrgram cou coun count cox cox_p
+ cox_sw coxbase coxhaz coxvar cp cprplot crc cross cs
+ cscript csi ct ct_is ctset ctst_5 ctst_st cttost cumsp
+ cumul cusum d datetof dbeta de debug debugbuf dec deco
+ decod decode def deff define des desc descr descri
+ describ describe dfbeta dfuller di dir dis discard
+ disp disp_res disp_s displ displa display do doe doed
+ doedi doedit dotplot dprobit drawnorm drop ds dstdize
+ dwstat dydx dyex dynre dynren e ed edi edit egen
+ eivreg else emdef en enc enco encod encode end eq
+ eqlist erase ereg ereg_lf ereg_p ereg_sw err erro
+ error est esti estim estima estimat estimate estimates
+ etodow etof etomdy ex exact exec execu execut execute
+ exi exit expand export eydx eyex F fac fact facto
+ factor fast fft fillin findit fit float for for5_0
+ force form forma format fpredict frac_154 frac_adj
+ frac_chk frac_cox frac_ddp frac_dis frac_dv frac_in
+ frac_mun frac_pp frac_pq frac_pv frac_wgt frac_xo
+ fracgen fracplot fracpoly fracpred freq frequency
+ Ftail ftodate ftoe ftomdy ftowdate fw fweight g gamma
+ gamma_lf gamma_p gamma_sw ge gen gene gener genera
+ generat generate genrank genstd genvmean gettoken gl
+ gladder glm glm_p glm_sw glmpred glo glob globa global
+ glogit glogit_p gnbre_lf gnbreg gnbreg_5 gnbreg_p
+ gomp_lf gompe_sw gomper_p gompertz gph gphdot gphpen
+ gphprint gprobi_p gprobit gr gr_print gra grap graph
+ grebar greigen grmeanby group gsort gwood h hadimvo
+ hareg hausman
+ he heck_d2 heckma_p heckman heckp_lf heckpr_p heckprob
+ hel help helpchk hereg hetpr_lf hetpr_p hetprob
+ hettest hilite hist hlogit hlu hotel hprobit hreg icd9
+ icd9p iis impute in index inf infi infil infile
+ infix inlist inp inpu input ins insh inshe inshee
+ insheet insp inspe inspec inspect int integ intreg
+ intrg_ll invchi2 invchi2tail invF invFtail invnchi2
+ invnorm invttail ipolate iqreg ir iri istdize ivreg iw
+ iweight joinby kalarma1 kap kap_3 kapmeier kappa
+ kapwgt kdensity keep ksm ksmirnov ktau kwallis l la
+ lab labe label ladder length level leverage lfit
+ lfit_p li lincom linesize linktest lis list llogi_sw
+ llogis_p llogist ln lnorm_lf lnorm_sw lnorma_p lnormal
+ lnskew0 lo loc loca local log logi logis_lf logistic
+ logit logit_p loglogs logrank logtype loneway long loo
+ look lookfor looku lookup lower lpredict lroc lrtest
+ ls lsens lsens_x lstat ltable ltrim lv lvr2plot m ma
+ mac macr macro man mantel mark markout marksample mat
+ matcell match matcol matcproc matname matr matri
+ matrix matrow matsize matstrik max mcc mcci md0_ md1_
+ md1debu_ md2_ md2debu_ mdytoe mdytof mean means median
+ memory memsize meqparse mer merg merge mfx mhodds min
+ missing mkdir mkmat mkspline ml ml_5 ml_adjs ml_bhhhs
+ ml_c_d ml_check ml_clear ml_cnt ml_debug ml_defd ml_e0
+ ml_e0i ml_e1 ml_e2 ml_ebfg0 ml_ebfr0 ml_ebh0q ml_ebhh0
+ ml_ebhr0 ml_ebr0i ml_ecr0i ml_edfp0 ml_edfr0 ml_edr0i
+ ml_eds ml_eer0i ml_egr0i ml_elf ml_elfi ml_elfs
+ ml_enr0i ml_enrr0 ml_exde ml_geqnr ml_grad0 ml_graph
+ ml_hbhhh ml_hd0 ml_init ml_inv ml_log ml_max ml_mlout
+ ml_model ml_nb0 ml_opt ml_plot ml_query ml_rdgrd
+ ml_repor ml_s_e ml_searc mleval mlf_ mlmatsum mlog
+ mlogi mlogit mlogit_p mlopts mlsum mlvecsum mnl0_ mor
+ more mov move mrdu0_ mvdecode mvencode mvreg n nbreg
+ nbreg_al nbreg_lf nbreg_sw nchi2 net newey newey_p
+ news nl nl_p nlexp2 nlexp2a nlexp3 nlgom3 nlgom4
+ nlinit nllog3 nllog4 nlogit nlpred no nobreak nod
+ nodiscrete noe noesample nof nofreq noi nois noisi
+ noisil noisily nol nolabel nonl nonlinear normden nose
+ note notes notify now nowght npnchi2 nptrend numlist
+ obs off old_ver olo olog ologi ologi_sw ologit
+ ologit_p ologitp on one onew onewa oneway op_colnm
+ op_comp op_diff op_inv op_str opr opro oprob oprob_sw
+ oprobi oprobi_p oprobit oprobitp order orthog orthpoly
+ ou out outf outfi outfil outfile outs outsh outshe
+ outshee outsheet ovtest pac par pars parse pause pc
+ pchart pchi pcorr pctile pentium percent pergram
+ permanent personal pkcollapse pkcross pkequiv
+ pkexamine pkshape pksumm pl playsnd plo plot plug
+ plugi plugin pnorm poisgof poiss_lf poiss_sw poisso_p
+ poisson pop popu popup post postclose postfile pperron
+ pr prais prais_e prais_p pred predi predic predict
+ predict preserve printgr priorest pro prob probi
+ probit probit_p prog progr progra program prove prtest
+ prtesti push pw pwcorr pwd pweight q qby qchi qnorm
+ qqplot qreg qreg_c qreg_p qreg_sw qu quadchk quantile
+ que quer query qui quie quiet quietl quietly range
+ ranksum rawsum rchart rcof real recast recode reg reg3
+ reg3_p regdw regr regre regre_p2 regres regres_p
+ regress regriv_p remap ren rena renam rename renpfix
+ repeat replace replay reshape restore ret retu retur
+ return reverse rm roccomp rocfit rocgold roctab rot
+ rota rotat rotate round row rreg rreg_p rtrim ru run
+ runtest rvfplot rvpplot sa safesum sample sampsi sav
+ save saving say sca scal scala scalar sco scob_lf
+ scob_p scobi_sw scobit scor score sd sdtest sdtesti se
+ search separate seperate serrbar set sfrancia sh she
+ shel shell shewhart showpoint signrank signtest simul
+ simulinit sktest sleep smcl smooth snapspan so sor
+ sort spearman speedchk1 speekchk2 spikeplt spline_x
+ sqreg sret sretu sretur sreturn st st_ct st_hc st_hcd
+ st_is st_issys st_note st_promo st_set st_show st_smpl
+ st_subid stack stackdepth stackreset statsby stbase
+ stci stcox stcox_p stcoxkm stcurv stcurve stdes stem
+ stereg stfill stgen stinit stir stjoin stmc stmh
+ stphplot stphtest stptime strate streg streset string
+ sts stset stsplit stsum sttocc sttoct stvary stweib su
+ subinstr subinword subpop substr subwin sum summ summa
+ summar summari summariz summarize sureg survcurv
+ survsum svmat svy_disp svy_dreg svy_est svy_get
+ svy_head svy_sub svy_x svydes svyintrg svyivreg svylc
+ svylog_p svylogit svymean svymlog svyolog svyoprob
+ svypois svyprobt svyprop svyratio svyreg svyreg_p
+ svyset svytab svytest svytotal sw swcnreg swcox swereg
+ swilk swlogis swlogit swologit swoprbt swpois swprobit
+ swqreg swtobit swweib symmetry symmi symplot syntax
+ sysdir sysmenu ta tab tab_or tab1 tab2 tabd tabdi
+ tabdis tabdisp tabi table tabodds tabstat tabu tabul
+ tabula tabulat tabulate te tempfile tempname tempvar
+ tes test testnl testparm teststd text timer tis tob
+ tobi tobit tobit_p tobit_sw token tokeni tokeniz
+ tokenize touch treatreg trim truncreg tset tsfill
+ tsreport tsrevar tsset tsunab ttail ttest ttesti
+ tut_chk tut_wait tutorial ty typ type typeof u unab
+ unabbrev uniform update upper us use using val values
+ var variable varlabelpos vce verinst vers versi versio
+ version vif vwls wdatetof wdctl wdlg wdupdate weib_lf
+ weib_lf0 weibu_sw weibul_p weibull wh whelp whi whic
+ which whil while wilc_st wilcoxon win wind windo
+ window winexec winhelp wmenu wntestb wntestq xchart
+ xcorr xi xpose xt_iis xt_tis xtabond xtbin_p xtclog
+ xtcnt_p xtcorr xtdata xtdes xtgee xtgee_p xtgls
+ xtgls_p xthaus xtile xtint_p xtintreg xtivreg xtlogit
+ xtnb_fe xtnb_lf xtnbreg xtpcse xtpois xtpred xtprobit
+ xtps_fe xtps_lf xtps_ren xtrch_p xtrchh xtrefe_p xtreg
+ xtreg_be xtreg_fe xtreg_ml xtreg_re xtregar xtrere_p
+ xtsum xttab xttest0 xttobit xttrans xwin xwind xwindo
+ xwindow zap_s zinb zinb_llf zinb_plf zip zip_llf zip_p
+ zip_plf zt_ct_5 zt_hc_5 zt_hcd_5 zt_is_5 zt_iss_5
+ zt_sho_5 zt_smp_5 ztbase_5 ztcox_5 ztdes_5 ztereg_5
+ ztfill_5 ztgen_5 ztir_5 ztjoin_5 zts_5 ztset_5
+ ztspli_5 ztsum_5 zttoct_5 ztvary_5 ztweib_5 comma tab
+ robust mvsktest oglm dlist mahapick viewresults
+ valuesof textbarplot freduse hcavar distrate zipsave
+ hutchens svylorenz goprobit regoprob digits cprplot2
+ devcon oaxaca supclust convert_top_lines graphbinary
+ trellis traces wtd glst lxpct_2 clv backrasch mmsrm
+ diplot kountry gologit2 intcens svygei_svyatk fitint
+ xtarsim eclpci beamplot samplepps classplot spearman2
+ fixsort casefat mehetprob svyselmlog svybsamp2
+ moremata checkfor2 dbmscopybatch palette_all ivreset
+ lookfor_all nmissing isvar descogini akdensity
+ biplotvlab genscore rrlogit ivvif hnblogit hnbclg
+ hglogit hgclg hplogit hpclg ztg cdfplot kdens cpoisson
+ samplesize gnbstrat nbstrat genass outreg2 kapprevi
+ sampsi_reg lgamma2 glgamma2 ivgauss2 givgauss2
+ sampsi_mcc cnbreg xtivreg2 sliceplot cquantile primes
+ scheme_rbn1mono subsave insob geekel2d censornb
+ estadd_plus estadd xtregre2 clorenz usmaps2 usswm
+ tablemat tmap mif2dta surface kdens2 onespell diffpi
+ plotbeta batplot relrank invcdf jmp jmp2 smithwelch
+ reswage dfl p2ci heterogi shuffle8 shuffle lincheck
+ bicdrop1 pre optifact matsort clustsens listmiss bic
+ hdquantile dirlist variog svypxcon svypxcat seast
+ xtlsdvc avplots4 eststo vclose gausshermite simirt
+ cprplots glcurve sscsubmit sdecode harmby ellip
+ mlboolean splitvallabels circular betacoef bnormpdf
+ grqreg genhwcci mrtab zandrews cvxhull abar mat2txt
+ gmlabvpos tableplot sortlistby mgen hlist ppplot rocss
+ pnrcheck stexpect rbounds regaxis pgmhaz8 meta_lr
+ mcqscore mvcorr ipf hapblock swblock raschtest
+ gammasym raschtestv7 vanelteren fs estout1 estout
+ loevh msp detect disjoint adjacent plotmatrix nnmatch
+ senspec twoway_estfit mkdat soepren alphawgt center
+ decompose wgttest cochran examples rollreg clemao_io
+ heckprob2 gipf metagraph hshaz tslist collapse2
+ gen_tail carryforward floattolong doubletofloat
+ margeff matin4-matout4 perturb coldiag2 sim_arma ndbci
+ labelmiss mcenter sslope reorder scat3 dummieslab rfl
+ xtvc metareg rc2 moments sxpose kaputil bystore mice
+ gzsave witch cureregr hprescott tabout gamet duncan
+ fview eret2 rc_spline tolerance modeldiag metaparm
+ profhap nsplit hlm fieller xtfisher matwrite usmaps
+ ellip6 ellip7 xi3 qhapipf slist nearest fedit extremes
+ mypkg pairplot cycleplot ciplot selectvars stcompet
+ full_palette catplot eclplot spellutil metadialog
+ psmatch2 bygap ingap mylabels metaaggr cleanlog gpfobl
+ mvprobit eqprhistogram slideplot majority hireg bigtab
+ vartyp codebook2 dmariano whotdeck crtest
+ collapseunique stripplot linkplot statsbyfast parplot
+ mitools groups wclogit xcontract xcollapse metafunnel
+ corrtab dmerge makematrix cibplot vreverse msplot
+ nicedates mkcorr nearmrg tabstatmat panelunit
+ panelauto safedrop gammafit gumbelfit betafit
+ lookforit savasas usesas etime usagelog tmpdir
+ confirmdir shortdir lambda survtime xtabond2
+ factortest checkvar vtokenize reshape8 pcorr2 tarow
+ cb2html survwgt svr jonter xsampsi ci2 domdiag
+ xtpattern nbfit distinct maketex triprobit smileplot
+ tabmerge avplot3 datesum _gclsort cltest varlab decomp
+ overlay tab3way tab2way ivreg2 hapipf varlag vececm
+ isco isko ptrend dpplot cipolate tknz levels reformat
+ xtab mvsumm fsum stkerhaz explist qlognorm tsspell
+ gphepssj texteditors alphawgt decompose inccat adjksm
+ outdat reshape7 qsim allpossible glmcorr gcause
+ selmlog matsave est2tex log2do2 hansen2 gam ivhettest
+ newey2 intext matrixof mrdum fastcd ivendog tabcount
+ tabcond minap qrowname cij ciw textgph latab autolog
+ histbox kdbox sunflower charlist adoedit lincomest
+ stylerules strgen wntstmvq grnote xttrans2 inequal7
+ tablepc hegy4 regdplot denormix chi2fit bstut aboutreg
+ _gstd01 cpcorr mktab vecar xdatelist strdate thinplate
+ gfields takelogs catgraph dsconcat tosql outseries
+ glcurve7 omninorm summdate sencode rgroup cf3 hlpdir
+ descsave outmat svytabs mstore savesome stbget spsurv
+ xtgraph effects stpm madfuller aformat todate _gwtmean
+ tsgraph soreg fbar metaninf blist johans vecar6
+ outtable factmerg factref factext hadrilm levinlin
+ nharvey ipshin gpreset geneigen dotex outtex sutex
+ dsearch chiplot idonepsu statsmat ds3 dthaz paran
+ gprefscode _gsoundex bpass bking labsort intreg2 sq
+ powercal denton corr_svy log2html dfao xpredict mcl
+ listtex raschcvt diagt estsave egenmore labutil
+ concord avplot2 tablecol metabias coldiag fitstat
+ doubmass cortesti fndmtch2 cusum6 ghistcum findval
+ centcalc xrigls dfgls charutil icomp enlarge kpss
+ metatrim ivgmm0 smhsiao matvsort roblpr modlpr recode2
+ showgph copydesc shapley rnd himatrix bspline stcascoh
+ stselpre nct ncf hist3 dolog dologx tscollap bcoeff
+ grfreq grlogit lrchg lrmatx lrplot lrutil forfile
+ printgph readlog spaces title dashln lomodrs ctabstat
+ expandby finddup fitmacro normtest predcalc _grmedf
+ ranvar matmap svmatf lincom2 csjl shownear fracdiff
+ genvars calibr fracirf xriml rowranks tgraph ordplot
+ cpr mlcoint stcmd xttest3 atkplot fsreg ciform rowsort
+ expgen epsigr dashgph addtxt swboot stak _grprod
+ sskapp xttest2 trinary ivprob-ivtobit6 torumm split q
+ linesize keyb expr xtlist xtcount xtcorr2 vce2 summvl
+ ststrata stcount simul2 regh pcamv pca mvpatt mokken
+ lrtest2 linest iia hordered htest elogit diag wraplist
+ qsort precmd modfycmd matfunc listuniq multgof hilite2
+ unlabeld to_msp sample2 placevar listby listblck hh
+ genl for2 dropvars countby bys icslib varcase tsplot
+ diagtest ssizebi studysi poverty ineq dissim geivars
+ ineqdec0 ineqdeco ineqfac povdeco sumdist xfrac
+ dagumfit smfit cpyxplot mkbilogn univstat hotdeck
+ matodd p_vlists gennorm tab_chi sbplot5 sbplot
+ mfracpol keyplot taba ds5 tabplot cistat probitiv
+ tobitiv _gslope sphdist ginidesc inequal2 kernreg1
+ kernreg2 outfix outfix2 seg outreg rfregk spautoc
+ onewplot pwcorrs ltable2 tabhbar hbox tabhplot cihplot
+ civplot sf36 pwploti partgam cf2 xtile2 ivglog
+ kwallis2 far5 jb6 gby strparse _gprod mfilegr desmat
+ areg2 margfx arimafit moreobs tsmktim durbinh bgtest
+ mnthplot archlm gphudak renames skewplot cnsrsig
+ recast2 doub2flt feldti tolower lfsum whitetst bpagan
+ listutil mdensity kdmany stquant byvar cflpois
+ workdays flower _grpos stcoxgof stcoxplt stpiece
+ overid overidxt swapval adotype fndmtch svvarlbl
+ gentrun storecmd sto lrdrop1 lrseq dmexogxt
+ probexog-tobexog predxcon predxcat mmerge tablab
+ for211 gmci grand nbinreg spikeplt ocratio biplot
+ coranal mca heckman2 marker markov pgamma qgamma
+ somersd pantest2 datmat distan missing quantil2
+ distplot tpred contrast cid rglm dtobit2 ljs ewma
+ barplot genfreq hbar hplot fodstr catdev rmanova
+ ranova seq intterms lmoments regresby reglike pweibull
+ wbull qweibull regpred logpred adjmean adjprop spell
+ switchr trnbin0 mvsamp1i mvsampsi tpvar mvtest addtex
+ pwcorrw vlist violin eba mstdize orthog stcumh
+ ccweight psbayes oprobpr cndnmb3 pbeta qbeta vmatch
+ kr20 sbrowni canon stbtcalc stgtcalc zb_qrm catenate
+ lprplot nnest longplot parmest qqplot2 jb zip zinb
+ hetprob unique longch gwhet williams adjust barplot2
+ grand2 histplot xcorplot clarify mlogpred nproc
+ labgraph vallist pexp qexp lms levene centroid medoid
+ cluster fulltab t2way5 epiconf lstack deaton colelms
+ confsvy median winsor bys torats venndiag chaos
+ muxyplot muxplot irrepro triplot tomode circstat tryem
+ white strip ralloc acplot stack symmetry omodel
+ allcross dups iia sdtest vplplot summvl labsumm
+ loopplot elapse istdize blogit2 sparl vallab gologit
+ mkstrsn poisml trpois0 cenpois sssplot hausman stcstat
+ forvalues
+ """
+)
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'),
+ (stc.STC_C_COMMENT, 'comment_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTDOC, 'comment_style'),
+ (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'),
+ (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'),
+ (stc.STC_C_COMMENTLINE, 'comment_style'),
+ (stc.STC_C_COMMENTLINEDOC, 'comment_style'),
+ (stc.STC_C_CHARACTER, 'char_style'),
+ (stc.STC_C_GLOBALCLASS, 'global_style'),
+ (stc.STC_C_IDENTIFIER, 'default_style'),
+ (stc.STC_C_NUMBER, 'number_style'),
+ (stc.STC_C_OPERATOR, 'operator_style'),
+ (stc.STC_C_PREPROCESSOR, 'pre_style'),
+ (stc.STC_C_REGEX, 'pre_style'),
+ (stc.STC_C_STRING, 'string_style'),
+ (stc.STC_C_STRINGEOL, 'default_style'),
+ (stc.STC_C_UUID, 'pre_style'),
+ (stc.STC_C_VERBATIM, 'number2_style'),
+ (stc.STC_C_WORD, 'keyword_style'),
+ (stc.STC_C_WORD2, 'keyword2_style') ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_PRE = ("styling.within.preprocessor", "0")
+FOLD_COM = ("fold.comment", "1")
+FOLD_COMP = ("fold.compact", "1")
+FOLD_ELSE = ("fold.at.else", "0")
+
+#------------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for STATA"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [MAIN_KEYWORDS, SECONDARY_KEYWORDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FOLD_PRE, FOLD_COM]
+
+ # TODO: this doesnt' look right...
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'//', u'/*', u'*/',u'*' ]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_tcl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_tcl.py
new file mode 100644
index 0000000..071a15d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_tcl.py
@@ -0,0 +1,198 @@
+###############################################################################
+# Name: tcl.py #
+# Purpose: Define TCL/TK syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: tcl.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for tcl
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _tcl.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+from _cpp import AutoIndenter
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+TCL_KW = (0, "after append array auto_execok auto_import auto_load catch cd "
+ "auto_load_index auto_qualify beep bgerror binary break case file "
+ "clock close concat continue dde default echo else elseif eof "
+ "encoding error eval exec exit expr fblocked fconfigure fcopy "
+ "fileevent flush for foreach format gets glob global history http "
+ "if incr info interp join lappend lindex linsert list llength "
+ "load loadTk lrange lreplace lsearch lset lsort memory msgcat "
+ "namespace open package pid pkg::create pkg_mkIndex regsub rename "
+ "Platform-specific proc puts pwd re_syntax read regexp registry "
+ "resource return scan seek set socket source split string subst "
+ "switch tclLog tclMacPkgSearch tclPkgSetup tclPkgUnknown tell "
+ "time trace unknown unset update uplevel upvar variable vwait "
+ "while")
+
+TK_KW = (1, "bell bind bindtags bitmap button canvas checkbutton clipboard "
+ "colors console cursors destroy entry event focus font frame grab "
+ "grid image Inter-client keysyms label labelframe listbox lower "
+ "menu menubutton message option options pack panedwindow photo "
+ "radiobutton raise scale scrollbar selection send spinbox text tk "
+ "tk_chooseColor tk_chooseDirectory tk_dialog tk_focusNext tkvars "
+ "tk_messageBox tk_optionMenu tk_popup tk_setPalette tkerror "
+ "tkwait toplevel winfo wish wm place tk_getOpenFile ")
+
+ITCL_KW = (2, "@scope body class code common component configbody constructor "
+ "define destructor hull import inherit itcl itk itk_component "
+ "itk_initialize itk_interior itk_option iwidgets keep method "
+ "private protected public typemethod typevariable")
+
+TK_COMMANDS = (3, "tk_bisque tk_chooseColor tk_dialog tk_focusFollowsMouse "
+ "tk_focusNext tk_focusPrev tk_getOpenFile tk_getSaveFile "
+ "tk_messageBox tk_optionMenu tk_popup tk_setPalette "
+ "tk_textCut tk_textPaste tkButtonAutoInvoke tkButtonDown "
+ "tkButtonEnter tkButtonInvoke tkButtonLeave tkButtonUp "
+ "tkCancelRepeat tkCheckRadioDown tkCheckRadioEnter "
+ "tkCheckRadioInvoke tkColorDialog tkColorDialog_BuildDialog "
+ "tkColorDialog_CancelCmd tkColorDialog_Config "
+ "tkColorDialog_CreateSelector tkColorDialog_DrawColorScale "
+ "tkColorDialog_EnterColorBar tkColorDialog_HandleRGBEntry "
+ "tkColorDialog_HandleSelEntry tkColorDialog_InitValues "
+ "tkColorDialog_LeaveColorBar tkColorDialog_MoveSelector "
+ "tkColorDialog_OkCmd tk_textCopy tkColorDialog_StartMove "
+ "tkColorDialog_RedrawColorBars tkColorDialog_ResizeColorBars "
+ "tkColorDialog_RedrawFinalColor tkColorDialog_ReleaseMouse "
+ "tkColorDialog_RgbToX tkColorDialog_SetRGBValue "
+ "tkColorDialog_XToRgb tkConsoleAbout tkConsoleBind "
+ "tkConsoleExit tkConsoleHistory tkConsoleInit tkFocusOK "
+ "tkConsoleInsert tkConsoleInvoke tkConsoleOutput "
+ "tkConsolePrompt tkConsoleSource tkDarken tkEntryAutoScan "
+ "tkEntryBackspace tkEntryButton1 tkEntryClosestGap "
+ "tkEntryGetSelection tkEntryInsert tkEntryKeySelect "
+ "tkEntryMouseSelect tkEntryNextWord tkEntryPaste tkFirstMenu "
+ "tkEntryPreviousWord tkEntrySeeInsert tkEntrySetCursor "
+ "tkEntryTranspose tkEventMotifBindings tkFDGetFileTypes "
+ "tkFocusGroup_BindIn tkFocusGroup_BindOut tkFocusGroup_Out"
+ "tkFocusGroup_Create tkFocusGroup_Destroy tkFocusGroup_In "
+ "tkGenerateMenuSelect tkIconList tkIconList_Add "
+ "tkIconList_Arrange tkIconList_AutoScan tkIconList_Btn1 "
+ "tkIconList_Config tkIconList_Create tkIconList_CtrlBtn1 "
+ "tkIconList_Curselection tkIconList_DeleteAll "
+ "tkIconList_Double1 tkIconList_DrawSelection tkIconList_See "
+ "tkIconList_FocusIn tkIconList_FocusOut tkIconList_Get "
+ "tkIconList_Goto tkIconList_Index tkIconList_Invoke "
+ "tkIconList_KeyPress tkIconList_Leave1 tkIconList_LeftRight "
+ "tkIconList_Motion1 tkIconList_Reset tkIconList_ReturnKey "
+ "tkIconList_Select tkIconList_Selection tkIconList_ShiftBtn1 "
+ "tkIconList_UpDown tkListbox tkListboxKeyAccel_Key "
+ "tkListboxAutoScan tkListboxBeginExtend tkListboxBeginSelect "
+ "tkListboxBeginToggle tkListboxCancel tkListboxDataExtend "
+ "tkListboxExtendUpDown tkListboxKeyAccel_Goto tkMbButtonUp "
+ "tkListboxKeyAccel_Reset tkListboxKeyAccel_Set "
+ "tkListboxKeyAccel_Unset tkListboxMotion tkListboxSelectAll "
+ "tkMbEnter tkMbLeave tkMbMotion tkMbPost tkMenuButtonDown "
+ "tkMenuDownArrow tkMenuDup tkMenuEscape tkMenuFind "
+ "tkMenuFindName tkMenuFirstEntry tkMenuInvoke tkMenuLeave "
+ "tkMenuLeftArrow tkMenuMotion tkMenuNextEntry tkMenuNextMenu "
+ "tkMenuRightArrow tkMenuUnpost tkMenuUpArrow tkMessageBox "
+ "tkMotifFDialog tkMotifFDialog_ActivateDList tkScaleDrag "
+ "tkMotifFDialog_ActivateFEnt tkMotifFDialog_ActivateFList "
+ "tkMotifFDialog_ActivateSEnt tkMotifFDialog_BrowseDList "
+ "tkMotifFDialog_BrowseFList tkMotifFDialog_BuildUI "
+ "tkMotifFDialog_CancelCmd tkMotifFDialog_Config "
+ "tkMotifFDialog_Create tkMotifFDialog_FileTypes "
+ "tkMotifFDialog_FilterCmd tkMotifFDialog_InterpFilter "
+ "tkMotifFDialog_LoadFiles tkMotifFDialog_MakeSList "
+ "tkMotifFDialog_OkCmd tkMotifFDialog_SetFilter "
+ "tkMotifFDialog_SetListMode tkMotifFDialog_Update "
+ "tkPostOverPoint tkRecolorTree tkRestoreOldGrab "
+ "tkSaveGrabInfo tkScaleActivate tkScaleButton2Down "
+ "tkScaleButtonDown tkScaleControlPress tkScaleEndDrag "
+ "tkScaleIncrement tkScreenChanged tkScrollButton2Down "
+ "tkScrollButtonDown tkScrollButtonDrag tkScrollButtonUp "
+ "tkScrollByPages tkScrollByUnits tkScrollDrag tkTextNextPos "
+ "tkScrollEndDrag tkScrollSelect tkScrollStartDrag "
+ "tkScrollTopBottom tkScrollToPos tkTabToWindow tkTearOffMenu "
+ "tkTextAutoScan tkTextButton1 tkTextClosestGap tkTextInsert "
+ "tkTextKeyExtend tkTextKeySelect tkTextNextPara "
+ "tkTextNextWord tkTextPaste tkTextPrevPara tkTextPrevPos "
+ "tkTextPrevWord tkTextResetAnchor tkTextScrollPages "
+ "tkTextSelectTo tkTextSetCursor tkTextTranspose "
+ "tkTextUpDownLine tkTraverseToMenu tkTraverseWithinMenu "
+ "tkListboxUpDown ")
+
+EXPAND = (4, "")
+
+USER1_KW = (5, "")
+
+USER2_KW = (6, "")
+
+USER3_KW = (7, "")
+
+USER4_KW = (8, "")
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_TCL_BLOCK_COMMENT, 'comment_style'),
+ (stc.STC_TCL_COMMENT, 'comment_style'),
+ (stc.STC_TCL_COMMENTLINE, 'comment_style'),
+ (stc.STC_TCL_COMMENT_BOX, 'comment_style'),
+ (stc.STC_TCL_DEFAULT, 'default_style'),
+ (stc.STC_TCL_EXPAND, 'default_style'), # STYLE NEEDED
+ (stc.STC_TCL_IDENTIFIER, 'default_style'),
+ (stc.STC_TCL_IN_QUOTE, 'string_style'),
+ (stc.STC_TCL_MODIFIER, 'default_style'), # STYLE NEEDED
+ (stc.STC_TCL_NUMBER, 'number_style'),
+ (stc.STC_TCL_OPERATOR, 'operator_style'),
+ (stc.STC_TCL_SUBSTITUTION, 'scalar_style'),
+ (stc.STC_TCL_SUB_BRACE, 'string_style'), # STYLE NEEDED
+ (stc.STC_TCL_WORD, 'keyword_style'), # tcl_kw
+ (stc.STC_TCL_WORD2, 'keyword2_style'), # tk_kw
+ (stc.STC_TCL_WORD3, 'keyword3_style'), # itcl_kw
+ (stc.STC_TCL_WORD4, 'keyword4_style'), # tkCommands
+ (stc.STC_TCL_WORD5, 'default_style'),
+ (stc.STC_TCL_WORD6, 'default_style'),
+ (stc.STC_TCL_WORD7, 'default_style'),
+ (stc.STC_TCL_WORD8, 'default_style'),
+ (stc.STC_TCL_WORD_IN_QUOTE, 'default_style')]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_COMMENT = ("fold.comment", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for TCL/Tk"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_TCL)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [TCL_KW, TK_KW, ITCL_KW, TK_COMMANDS]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD, FOLD_COMMENT]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vbscript.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vbscript.py
new file mode 100644
index 0000000..a7e17bd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vbscript.py
@@ -0,0 +1,95 @@
+###############################################################################
+# Name: vbscript.py #
+# Purpose: Define VBScript syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: vbscript.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for VBScript.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _vbscript.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+VBS_KW = ("addressof alias and as attribute base begin binary boolean byref "
+ "byte byval call case cdbl cint clng compare const csng cstr "
+ "currency date decimal declare defbool defbyte defcur defdate defdbl "
+ "defdec defint deflng defobj defsng defstr defvar dim do double each "
+ "else elseif empty end enum eqv erase error event exit explicit "
+ "false for friend function get global gosub goto if imp implements "
+ "in input integer is len let lib like load lock long loop lset me "
+ "mid midb mod new next not nothing null object on option optional "
+ "or paramarray preserve print private property public raiseevent "
+ "randomize redim rem resume return rset seek select set single "
+ "static step stop string sub text then time to true type typeof "
+ "unload until variant wend while with withevents xor")
+
+# Syntax specifications
+SYNTAX_ITEMS = [ (stc.STC_B_ASM, 'asm_style'),
+ (stc.STC_B_BINNUMBER, 'default_style'), # STYLE NEEDED
+ (stc.STC_B_COMMENT, 'comment_style'),
+ (stc.STC_B_CONSTANT, 'const_style'),
+ (stc.STC_B_DATE, 'default_style'), # STYLE NEEDED
+ (stc.STC_B_DEFAULT, 'default_style'),
+ (stc.STC_B_ERROR, 'error_style'),
+ (stc.STC_B_HEXNUMBER, 'number_style'),
+ (stc.STC_B_IDENTIFIER, 'default_style'),
+ (stc.STC_B_KEYWORD, 'keyword_style'),
+ (stc.STC_B_KEYWORD2, 'class_style'), # STYLE NEEDED
+ (stc.STC_B_KEYWORD3, 'funct_style'), # STYLE NEEDED
+ (stc.STC_B_KEYWORD4, 'scalar_style'), # STYLE NEEDED
+ (stc.STC_B_LABEL, 'directive_style'), # STYLE NEEDED
+ (stc.STC_B_NUMBER, 'number_style'),
+ (stc.STC_B_OPERATOR, 'operator_style'),
+ (stc.STC_B_PREPROCESSOR, 'pre_style'),
+ (stc.STC_B_STRING, 'string_style'),
+ (stc.STC_B_STRINGEOL, 'stringeol_style')
+ ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for VbScript"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_VBSCRIPT)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [(0, VBS_KW),]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'\'']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_verilog.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_verilog.py
new file mode 100644
index 0000000..be8d62d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_verilog.py
@@ -0,0 +1,375 @@
+###############################################################################
+# Name: verilog.py #
+# Purpose: Configuration module for Verilog HDL language #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: verilog.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Verilog Hardware Description Language
+ and System Verilog programming languages. Much help in creating this
+ module from Tim Corcoran.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _verilog.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+#TODO: What to do with preprocessors?
+#TODO: What to do with standard methods?
+
+#---- Keyword Definitions ----#
+
+#==============================================================================
+# IEEE 1364-1995 Verilog
+#==============================================================================
+# IEEE 1364-1995 Verilog Preprocessors
+V_1364_1995_PREPROCESSORS = (
+ # 1364-1995 Section 14
+ "`celldefine `default_nettype `define `else `endcelldefine `endif `ifdef "
+ "`include `nounconnected_drive `resetall `timescale `unconnected_drive "
+ "`undef "
+ # 1364-1995 Annex G
+ "`default_decay_time `default_trireg_strength `delay_mode_distributed "
+ "`delay_mode_path `delay_mode_unit `delay_mode_zero "
+ #1364-1995 Verilog Preprocessor Commercial Extensions
+ "`accelerate `autoexpand_vectornets `disable_portfaults `enable_portfaults "
+ "`endprotect `endprotected `expand_vectornets `noaccelerate "
+ "`noexpand_vectornets `noremove_gatenames `noremove_netnames "
+ "`nosuppress_faults `portcoerce `protect `protected "
+ "`remove_gatenames `remove_netnames `suppress_faults "
+)
+
+# IEEE 1364-1995 Verilog Keywords (NOT USED: attribute endattribute signed unsigned)
+V_1364_1995_KEYWORDS = (
+ "always assign begin case casex casez deassign default defparam disable "
+ "edge else end endcase endfunction endmodule endprimitive endspecify "
+ "endtable endtask for force forever fork function if ifnone initial "
+ "inout input join macromodule module negedge output parameter posedge "
+ "primitive release repeat scalared specify specparam strength table task "
+ "vectored wait while"
+)
+
+# IEEE 1364-1995 Verilog Types (NOT USED: xbuf)
+V_1364_1995_TYPES = (
+ "and buf bufif0 bufif1 cmos event highz0 highz1 integer large medium nand "
+ "nmos nor not notif0 notif1 or pmos pull0 pull1 pulldown pullup rcmos real "
+ "realtime reg rnmos rpmos rtran rtranif0 rtranif1 small strong0 strong1 "
+ "supply0 supply1 time tran tranif0 tranif1 tri tri0 tri1 triand trior "
+ "trireg wand weak0 weak1 wire wor xnor xor"
+)
+
+# IEEE 1364-1995 Verilog System Tasks and Functions
+V_1364_1995_TASKS = (
+ # 1364-1995 Section 14
+ "$async$and$array $async$and$plane $async$nand$array $async$nand$plane "
+ "$async$nor$array $async$nor$plane $async$or$array $async$or$plane "
+ "$bitstoreal $display $displayb $displayh $displayo $dist_chi_square "
+ "$dist_erlang $dist_exponential $dist_normal $dist_poisson $dist_t "
+ "$dist_uniform $dumpall $dumpfile $dumpflush $dumplimit $dumpoff $dumpon "
+ "$dumpvars $fclose $fdisplay $fdisplayb $fdisplayh $fdisplayo $finish "
+ "$fmonitor $fmonitorb $fmonitorh $fmonitoro $fopen $fstrobe $fstrobeb "
+ "$fstrobeh $fstrobeo $fwrite $fwriteb $fwriteh $fwriteo $hold $itor "
+ "$monitor $monitorb $monitorh $monitoro $monitoroff $monitoron $nochange "
+ "$period $printtimescale $q_add $q_exam $q_full $q_initialize $q_remove "
+ "$random $readmemb $readmemh $realtime $realtobits $recovery $rtoi $setup "
+ "$setuphold $skew $stime $stop $strobe $strobeb $strobeh $strobeo "
+ "$sync$and$array $sync$and$plane $sync$nand$array $sync$nand$plane "
+ "$sync$nor$array $sync$nor$plane $sync$or$array $sync$or$plane $time "
+ "$timeformat $width $write $writeb $writeh $writeo "
+ # 1364-1995 Annex F
+ "$countdrivers $getpattern $incsave $input $key $list $log $nokey $nolog "
+ "$reset $reset_count $reset_value $restart $save $scale $scope $showscopes "
+ "$showvars $sreadmemb $sreadmemh"
+)
+
+#==============================================================================
+# IEEE 1364-2001 Verilog
+#==============================================================================
+# IEEE 1364-2001 Verilog Preprocessors
+V_1364_2001_PREPROCESSORS = (
+ "`elsif `ifndef `line"
+)
+
+# IEEE 1364-2001 Verilog Keywords
+V_1364_2001_KEYWORDS = (
+ "automatic cell config design endconfig endgenerate generate genvar incdir "
+ "include instance liblist library localparam noshowcancelled "
+ "pulsestyle_ondetect pulsestyle_onevent showcancelled signed unsigned use"
+)
+
+# IEEE 1364-2001 Verilog Types
+V_1364_2001_TYPES = (
+ ""
+)
+
+# IEEE 1364-2001 Verilog System Tasks and Functions
+V_1364_2001_TASKS = (
+ "$dumpports $dumpportsall $dumpportsflush $dumpportslimit $dumpportsoff "
+ "$dumpportson $ferror $fflush $fgetc $fgets $fread $fscanf $fseek $ftell "
+ "$rewind $sdf_annotate $sformat $signed $sscanf $swrite $swriteb $swriteh "
+ "$swriteo $test$plusargs $ungetc $unsigned $value$plusargs"
+)
+
+#==============================================================================
+# IEEE 1364-2005 Verilog
+#==============================================================================
+# IEEE 1364-2005 Verilog Preprocessors
+V_1364_2005_PREPROCESSORS = (
+ "`pragma"
+)
+
+# IEEE 1364-2005 Verilog Keywords (NONE)
+V_1364_2005_KEYWORDS = (
+ ""
+)
+
+# IEEE 1364-2005 Verilog Types
+V_1364_2005_TYPES = (
+ "uwire"
+)
+
+# IEEE 1364-2005 Verilog System Tasks and Functions (NONE)
+V_1364_2005_TASKS = (
+ ""
+)
+
+#VERILOG_PREPROCESSORS = " ".join([V_1364_1995_PREPROCESSORS, V_1364_2001_PREPROCESSORS, V_1364_2005_PREPROCESSORS])
+#VERILOG_KEYWORDS = " ".join([V_1364_1995_KEYWORDS, V_1364_2001_KEYWORDS, V_1364_2005_KEYWORDS ])
+#VERILOG_TYPES = " ".join([V_1364_1995_TYPES, V_1364_2001_TYPES, V_1364_2005_TYPES ])
+#VERILOG_TASKS = " ".join([V_1364_1995_TASKS, V_1364_2001_TASKS, V_1364_2005_TASKS ])
+
+# ---\/----- Overkill maybe? -----\/---
+VERILOG_PREPROCESSORS = " ".join( [V_1364_1995_PREPROCESSORS,
+ V_1364_2001_PREPROCESSORS,
+ V_1364_2005_PREPROCESSORS] ).split()
+VERILOG_PREPROCESSORS.sort()
+VERILOG_PREPROCESSORS = " ".join( VERILOG_PREPROCESSORS )
+
+VERILOG_KEYWORDS = " ".join( [V_1364_1995_KEYWORDS,
+ V_1364_2001_KEYWORDS,
+ V_1364_2005_KEYWORDS] ).split()
+VERILOG_KEYWORDS.sort()
+VERILOG_KEYWORDS = " ".join( VERILOG_KEYWORDS )
+
+VERILOG_TYPES = " ".join( [V_1364_1995_TYPES,
+ V_1364_2001_TYPES,
+ V_1364_2005_TYPES] ).split()
+VERILOG_TYPES.sort()
+VERILOG_TYPES = " ".join( VERILOG_TYPES )
+
+VERILOG_TASKS = " ".join( [V_1364_1995_TASKS,
+ V_1364_2001_TASKS,
+ V_1364_2005_TASKS] ).split()
+VERILOG_TASKS.sort()
+VERILOG_TASKS = " ".join( VERILOG_TASKS )
+# ---/\----- Overkill maybe? -----/\---
+
+#---- System Verilog Extensions ----#
+
+#==============================================================================
+# IEEE 1800-2005 SystemVerilog
+#==============================================================================
+# IEEE 1800-2005 SystemVerilog Preprocessors
+SV_1800_2005_PREPROCESSORS = (
+ # One of "1800-2009" "1800-2005" "1364-2005" "1364-2001" "1364-2001-noconfig" "1364-1995"
+ "`begin_keywords `end_keywords"
+)
+
+# IEEE 1800-2005 SystemVerilog Keywords
+SV_1800_2005_KEYWORDS = (
+ "alias always_comb always_ff always_latch assert assume before bind "
+ "bins binsof bit break constraint covergroup coverpoint class clocking const"
+ "context continue cover cross dist do endclass endclocking endgroup endinterface "
+ "endpackage endprogram endproperty endsequence expect export extends extern "
+ "final first_match foreach forkjoin iff ignore_bins illegal_bins import "
+ "inside interface intersect join_any join_none modport new null package "
+ "priority process program property pure randcase randsequence ref return "
+ "sequence solve super this throughout timeprecision timeunit type unique "
+ "wait_order wildcard with within "
+ "local packed protected static struct tagged typedef union virtual"
+)
+
+# IEEE 1800-2005 SystemVerilog Types
+SV_1800_2005_TYPES = (
+ "byte chandle enum int logic longint rand randc shortint shortreal std "
+ "string var void"
+ # Moved to keywords
+# "local packed protected static struct tagged typedef union virtual"
+)
+
+# IEEE 1800-2005 SystemVerilog System Tasks and Functions
+SV_1800_2005_TASKS = (
+ "$assertkill $assertoff $asserton $bits $countones $coverage_control "
+ "$coverage_get $coverage_get_max $coverage_merge $coverage_save "
+ "$dimensions $error $exit $fatal $fell $high $increment $info $isunbounded "
+ "$isunknown $left $low $onehot $onehot0 $psprintf $right $rose $sampled "
+ "$size $stable $typename $unpacked_dimensions $warning"
+)
+
+# IEEE 1800-2005 SystemVerilog Standard Methods
+SV_1800_2005_METHODS = (
+ "and atobin atohex atoi atooct atoreal await back bintoa clear compare data "
+ "delete empty eq erase erase_range exists find find_first find_first_index "
+ "find_index find_last find_last_index finish first front get getc hextoa "
+ "icompare index insert insert_range itoa kill last len max min name neq new "
+ "next num octtoa or peek pop_back pop_front prev product purge push_back "
+ "push_front put putc rand_mode realtoa resume reverse rsort self set shuffle "
+ "size sort start status stop substr sum suspend swap tolower toupper try_get "
+ "try_peek try_put unique unique_index xor"
+)
+
+#==============================================================================
+# IEEE 1800-2009 SystemVerilog
+#==============================================================================
+SV_1800_2009_PREPROCESSORS = (
+ "`__FILE__ `__LINE__ `undefineall"
+)
+
+# IEEE 1800-2009 SystemVerilog Keywords
+SV_1800_2009_KEYWORDS = (
+ "accept_on checker endchecker eventually global implies let matches nexttime "
+ "reject_on restrict s_always s_eventually s_nexttime s_until s_until_with "
+ "sync_accept_on sync_reject_on unique0 until until_with untyped weak "
+ # 34.4 Protect pragma directives
+ "protect "
+ "author author_info begin_protected comment data_block data_decrypt_key "
+ "data_keyname data_keyowner data_method data_public_key decrypt_license "
+ "digest_block digest_decrypt_key digest_key_method digest_keyname "
+ "digest_keyowner digest_method digest_public_key encoding encrypt_agent "
+ "encrypt_agent_info encrypt_license end_protected key_block key_keyname "
+ "key_keyowner key_method key_public_key reset runtime_license viewport"
+)
+
+# IEEE 1800-2009 SystemVerilog Types
+SV_1800_2009_TYPES = (
+ # TODO: Are there new types?
+ ""
+)
+
+# IEEE 1800-2009 SystemVerilog System Tasks and Functions
+SV_1800_2009_TASKS = (
+ # Section 20.1 General
+ "$acos $acosh $asin $asinh $assertfailoff $assertfailon $assertnonvacuouson "
+ "$assertpassoff $assertpasson $assertvacuousoff $atan $atan2 $atanh "
+ "$bitstoshortreal $cast $ceil $changed $changed_gclk $changing_gclk $clog2 "
+ "$cos $cosh $exp $falling_gclk $fell_gclk $floor $future_gclk $get_coverage "
+ "$hypot $ln $load_coverage_db $log10 $past $past_gclk $pow $rising_gclk "
+ "$rose_gclk $set_coverage_db_name $sformatf $shortrealtobits $sin $sinh "
+ "$sqrt $stable_gclk $steady_gclk $system $tan $tanh"
+)
+
+# IEEE 1800-2009 SystemVerilog Standard Methods
+SV_1800_2009_METHODS = (
+ # TODO: Add new methods
+ ""
+)
+
+#SYSTEMVERILOG_PREPROCESSORS = " ".join( [VERILOG_PREPROCESSORS, SV_1800_2005_PREPROCESSORS, SV_1800_2009_PREPROCESSORS] )
+#SYSTEMVERILOG_KEYWORDS = " ".join( [VERILOG_KEYWORDS, SV_1800_2005_KEYWORDS, SV_1800_2009_KEYWORDS ] )
+#SYSTEMVERILOG_TYPES = " ".join( [VERILOG_TYPES, SV_1800_2005_TYPES, SV_1800_2009_TYPES ] )
+#SYSTEMVERILOG_TASKS = " ".join( [VERILOG_TASKS, SV_1800_2005_TASKS, SV_1800_2009_TASKS ] )
+
+# ---\/----- Overkill maybe? -----\/---
+SYSTEMVERILOG_PREPROCESSORS = " ".join( [VERILOG_PREPROCESSORS,
+ SV_1800_2005_PREPROCESSORS,
+ SV_1800_2009_PREPROCESSORS] ).split()
+SYSTEMVERILOG_PREPROCESSORS.sort()
+SYSTEMVERILOG_PREPROCESSORS = " ".join( SYSTEMVERILOG_PREPROCESSORS )
+
+SYSTEMVERILOG_KEYWORDS = " ".join( [VERILOG_KEYWORDS,
+ SV_1800_2005_KEYWORDS,
+ SV_1800_2009_KEYWORDS] ).split()
+SYSTEMVERILOG_KEYWORDS.sort()
+SYSTEMVERILOG_KEYWORDS = " ".join( SYSTEMVERILOG_KEYWORDS )
+
+SYSTEMVERILOG_TYPES = " ".join( [VERILOG_TYPES,
+ SV_1800_2005_TYPES,
+ SV_1800_2009_TYPES] ).split()
+SYSTEMVERILOG_TYPES.sort()
+SYSTEMVERILOG_TYPES = " ".join( SYSTEMVERILOG_TYPES )
+
+SYSTEMVERILOG_TASKS = " ".join( [VERILOG_TASKS,
+ SV_1800_2005_TASKS,
+ SV_1800_2009_TASKS] ).split()
+SYSTEMVERILOG_TASKS.sort()
+SYSTEMVERILOG_TASKS = " ".join( SYSTEMVERILOG_TASKS )
+# ---/\----- Overkill maybe? -----/\---
+
+#---- End System Verilog Extensions ----#
+
+USER_KW = ( 3, "" )
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [
+ (stc.STC_V_COMMENT, 'comment_style' ),
+ (stc.STC_V_COMMENTLINE, 'comment_style' ),
+ (stc.STC_V_COMMENTLINEBANG, 'comment_style' ),
+ (stc.STC_V_DEFAULT, 'default_style' ),
+ (stc.STC_V_IDENTIFIER, 'default_style' ),
+ (stc.STC_V_NUMBER, 'number_style' ),
+ (stc.STC_V_OPERATOR, 'operator_style' ),
+ (stc.STC_V_PREPROCESSOR, 'pre_style' ),
+ (stc.STC_V_STRING, 'string_style' ),
+ (stc.STC_V_STRINGEOL, 'stringeol_style'),
+ (stc.STC_V_USER, 'default_style' ),
+ (stc.STC_V_WORD, 'keyword_style' ),
+ (stc.STC_V_WORD2, 'keyword2_style' ),
+ (stc.STC_V_WORD3, 'scalar_style' )
+]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+FOLD_CMT = ("fold.comment", "1")
+FOLD_PRE = ("fold.preprocessor", "1")
+FOLD_COMP = ("fold.compact", "1")
+FOLD_ELSE = ("fold.at.else", "0")
+FOLD_MOD = ("fold.verilog.flags", "0")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for Verilog and SysVerilog"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_VERILOG)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ if self.LangId == synglob.ID_LANG_VERILOG:
+ return [(0, VERILOG_KEYWORDS),
+ (1, VERILOG_TYPES),
+ (2, VERILOG_TASKS)]
+ else:
+ return [(0, SYSTEMVERILOG_KEYWORDS),
+ (1, SYSTEMVERILOG_TYPES),
+ (2, SYSTEMVERILOG_TASKS)]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'//']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vhdl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vhdl.py
new file mode 100644
index 0000000..9870cdd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vhdl.py
@@ -0,0 +1,130 @@
+###############################################################################
+# Name: vhdl.py #
+# Purpose: Define VHDL syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: vhdl.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for VHDL. Very High Scale Integrated
+ Circuit Hardware Description Language
+@todo: Maybe add highlighting for values S0S, S1S, ect..
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _vhdl.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# VHDL Keywords
+VHDL_KW = (0, "access after alias all assert architecture array attribute for "
+ "begin block body buffer bus case component configuration inout "
+ "constant if else disconnect downto elsif end entity exit file "
+ "function generate generic group guarded impure in inertial is "
+ "label library linkage literal loop map new next null of on open "
+ "others out package port postponed procedure process pure range "
+ "record register reject report return select severity signal use "
+ "shared subtype then to transport type unaffected units until "
+ "variable wait when while with note warning error failure true "
+ "false")
+
+# VHDL Operators
+VHDL_OP = (1, "and nand or nor xor xnor rol ror sla sll sra srl mod rem abs "
+ "not ")
+
+# VHDL Attributes
+VHDL_AT = (2, "'high 'left 'length 'low 'range 'reverse_range 'right 'foreign "
+ "'ascending 'behavior 'structure 'simple_name 'instance_name "
+ "'path_name 'active 'delayed 'event 'last_active 'last_event "
+ "'last_value 'quiet 'stable 'transaction 'driving 'driving_value "
+ "'base 'high 'left 'leftof 'low 'pos 'pred 'rightof 'succ 'val "
+ "'image 'value")
+
+# Standard Functions
+VHDL_STDF = (3, "now readline read writeline write endfile to_stdulogicvector "
+ "to_bitvector to_stdulogic to_stdlogicvector resolved to_bit "
+ "to_x01 to_x01z to_UX01 rising_edge falling_edge is_x "
+ "shift_right rotate_left rotate_right resize to_integer "
+ "to_unsigned to_signed std_match to_01 shift_left ")
+
+# Standard Packages
+VHDL_STDP = (4, "std ieee work standard textio std_logic_1164 std_logic_arith "
+ "std_logic_misc std_logic_signed std_logic_textio "
+ "numeric_bit numeric_std math_complex math_real "
+ "vital_timing std_logic_unsigned vital_primitives ")
+
+# Standard Types
+VHDL_STDT = (5, "bit bit_vector character boolean integer real time string "
+ "severity_level positive natural signed unsigned line text "
+ "std_logic std_logic_vector std_ulogic std_ulogic_vector "
+ "qsim_state qsim_state_vector qsim_12state qsim_12state_vector "
+ "qsim_strength mux_bit mux_vector reg_bit reg_vector wor_bit "
+ "wor_vector")
+
+# User Words
+VHDL_UKW = (6, "")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_VHDL_DEFAULT, 'default_style'),
+ (stc.STC_VHDL_ATTRIBUTE, 'default_style'), # NEEDS STYLE
+ (stc.STC_VHDL_COMMENT, 'comment_style'),
+ (stc.STC_VHDL_COMMENTLINEBANG, 'comment_style'),
+ (stc.STC_VHDL_IDENTIFIER, 'default_style'),
+ (stc.STC_VHDL_KEYWORD, 'keyword_style'),
+ (stc.STC_VHDL_NUMBER, 'default_style'),
+ (stc.STC_VHDL_OPERATOR, 'operator_style'),
+ (stc.STC_VHDL_STDFUNCTION, 'funct_style'),
+ (stc.STC_VHDL_STDOPERATOR, 'operator_style'),
+ (stc.STC_VHDL_STDPACKAGE, 'pre_style'),
+ (stc.STC_VHDL_STDTYPE, 'class_style'),
+ (stc.STC_VHDL_STRING, 'string_style'),
+ (stc.STC_VHDL_STRINGEOL, 'stringeol_style'),
+ (stc.STC_VHDL_USERWORD, 'default_style') ]
+
+#---- Extra Property Specifications ----#
+FOLD = ("fold", "1")
+FLD_COMMENT = ("fold.comment", "1")
+FLD_COMMPACT = ("fold.compact", "1")
+FLD_ATELSE = ("fold.at.else", "1")
+FLD_ATBEGIN = ("fold.at.Begin", "1")
+FLD_ATPAREN = ("fold.at.Parenthese", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for VHDL"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_VHDL)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [VHDL_KW, VHDL_AT, VHDL_STDF, VHDL_STDP, VHDL_STDT]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'--']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_visualbasic.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_visualbasic.py
new file mode 100644
index 0000000..4dba95a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_visualbasic.py
@@ -0,0 +1,205 @@
+###############################################################################
+# Name: visualbasic.py #
+# Purpose: Define Visual Basic syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: visualbasic.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for Visual Basic.
+@todo: Incomplete requires color/kw tuning
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _visualbasic.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Visual Basic Keywords (Statements)
+VB_KW = (0, "AppActivate Base Beep Begin Call Case ChDir ChDrive Const Declare "
+ "DefByte DefCur DefDate DefDbl DefDec DefInt DefLng DefObj DefSng "
+ "DefStr Deftype DefVar DeleteSetting Dim Do Else End Enum Erase "
+ "Event Exit Explicit FileCopy For ForEach Function Get GoSub GoTo "
+ "If Implements Kill Let LineInput Lock LSet MkDir Name Next "
+ "On Option Private Property Public Put RaiseEvent Randomize ReDim "
+ "Rem Reset Resume Return RmDir RSet SavePicture SaveSetting With "
+ "SendKeys SetAttr Static Sub Then Type Unlock Wend While Width "
+ "Write Height DefBool OnError ")
+
+# Visual Basic User Keywords 1 (Functions)
+VB_UKW1 = (1, "Abs Array Asc AscB AscW Atn Avg CBool CByte CCur CDate CDbl "
+ "Choose Chr ChrB ChrW CInt CLng Command Cos Count CreateObject "
+ "CSng CStr CurDir CVar CVDate CVErr Date DateAdd DateDiff Cdec "
+ "DatePart DateSerial DateValue Day DDB Dir DoEvents Environ EOF "
+ "Error Exp FileAttr FileDateTime FileLen Fix Format FreeFile FV "
+ "GetAllStrings GetAttr GetAutoServerSettings GetObject NPV "
+ "Hex Hour IIf IMEStatus Input InputB InputBox InStr InstB Int "
+ "IPmt IsArray IsDate IsEmpty IsError IsMissing IsNull IsNumeric "
+ "IsObject LBound LCase Left LeftB Len LenB LoadPicture Loc LOF "
+ "Log LTrim Max Mid MidB Min Minute MIRR Month MsgBox Now NPer "
+ "Oct Partition Pmt PPmt PV QBColor Rate RGB Right RightB Rnd "
+ "RTrim Second Seek Sgn Shell Sin SLN Space Spc Sqr StDev StDevP "
+ "Str StrComp StrConv String Switch Sum SYD Tab Tan Time Timer "
+ "TimeSerial TimeValue Trim TypeName UBound UCase Val Var VarP "
+ "VarType Weekday Year GetSetting ")
+
+# Visual Basic User Keywords 2 (Methods)
+VB_UKW2 = (2, "Accept Activate Add AddCustom AddFile AddFromFile AddItem "
+ "AddFromTemplate AddNew AddToAddInToolbar AddToolboxProgID "
+ "Append AppendChunk Arrange Assert AsyncRead BatchUpdate "
+ "BeginTrans Bind Cancel CancelAsyncRead CancelBatch CancelUpdate "
+ "CanPropertyChange CaptureImage CellText CellValue Circle Clear "
+ "ClearFields ClearSel ClearSelCols Clone Close Cls ColContaining "
+ "ColumnSize CommitTrans CompactDatabase Compose Connect Copy "
+ "CopyQueryDef CreateDatabase CreateDragImage CreateEmbed "
+ "CreateField CreateGroup CreateIndex CreateLink Customize"
+ "CreatePreparedStatement CreatePropery CreateQueryCreateQueryDef "
+ "CreateRelation CreateTableDef CreateUser CreateWorkspace "
+ "Delete DeleteColumnLabels DeleteColumns DeleteRowLabels Open "
+ "DeleteRows DoVerb Drag Draw Edit EditCopy EditPaste EndDoc "
+ "EnsureVisible EstablishConnection Execute ExtractIcon Fetch "
+ "FetchVerbs Files FillCache Find FindFirst FindItem FindLast "
+ "FindNext GoForward KillDoc LoadFile MakeCompileFile MoveNext "
+ "FindPrevious Forward GetBookmark GetChunk GetClipString GetData "
+ "GetFirstVisible GetFormat GetHeader GetLineFromChar GetNumTicks "
+ "GetRows GetSelectedPart GetText GetVisibleCount GoBack OLEDrag "
+ "Hide HitTest HoldFields Idle InitializeLabels InsertRows Item "
+ "InsertColumnLabels InsertColumns InsertObjDlg InsertRowLabels "
+ "Layout Line LinkExecute LinkPoke LinkRequest LinkSend Listen "
+ "LoadResData LoadResPicture LoadResString LogEvent OpenResultset "
+ "MakeReplica MoreResults Move MoveData MoveFirst MoveLast Point "
+ "MovePrevious NavigateTo NewPage NewPassword NextRecordset Quit "
+ "OnAddinsUpdate OnConnection OnDisconnection OnStartupComplete "
+ "OpenConnection OpenDatabase OpenQueryDef OpenRecordset Reload "
+ "OpenURL Overlay PaintPicture Paste PastSpecialDlg PeekData Play "
+ "PopulatePartial PopupMenu Print PrintForm PropertyChanged PSet "
+ "Raise RandomDataFill RandomFillColumns RandomFillRows Remove "
+ "rdoCreateEnvironment rdoRegisterDataSource ReadFromFile "
+ "Rebind ReFill Refresh RefreshLink RegisterDatabase ReadProperty "
+ "RemoveAddInFromToolbar RemoveItem Render RepairDatabase Reply "
+ "ReplyAll Requery ResetCustom ResetCustomLabel ResolveName "
+ "RestoreToolbar Resync Rollback RollbackTrans RowBookmark "
+ "RowContaining RowTop Save SaveAs SaveFile SaveToFile SelectAll "
+ "SaveToolbar SaveToOle1File Scale ScaleX ScaleY Scroll Select "
+ "SelectPart SelPrint Send SendData Set SetAutoServerSettings "
+ "SetData SetFocus SetOption SetSize SetText SetViewport Show "
+ "ShowColor ShowFont ShowHelp ShowOpen ShowPrinter ShowSave "
+ "ShowWhatsThis SignOff SignOn Size Span SplitContaining "
+ "StartLabelEdit StartLogging Stop Synchronize TextHeight "
+ "TextWidth ToDefaults TwipsToChartPart TypeByChartType "
+ "Update UpdateControls UpdateRecord UpdateRow Upto WhatsThisMode "
+ "WriteProperty ZOrder")
+
+# Visual Basic User Keywords 3 (Events)
+VB_UKW3 = (3, "AccessKeyPress AfterAddFile AfterChangeFileName AfterCloseFile "
+ "AfterColEdit AfterColUpdate AfterDelete AfterInsert "
+ "AfterLabelEdit AfterRemoveFile AfterUpdate AfterWriteFile "
+ "AmbienChanged ApplyChanges Associate AsyncReadComplete "
+ "AxisActivated AxisLabelActivated AxisLabelSelected Collapse "
+ "AxisLabelUpdated AxisSelected AxisTitleActivated BeforeColEdit "
+ "AxisTitleSelected AxisTitleUpdated AxisUpdated BeforeClick "
+ "BeforeColUpdate BeforeConnect BeforeDelete BeforeInsert "
+ "BeforeLabelEdit BeforeLoadFile BeforeUpdate ButtonClick "
+ "ButtonCompleted ButtonGotFocus ButtonLostFocus Change ColResize "
+ "ChartActivated ChartSelected ChartUpdated Click ColEdit "
+ "ColumnClick Compare ConfigChageCancelled ConfigChanged "
+ "ConnectionRequest DataArrival DataChanged DataUpdated DblClick "
+ "Deactivate DeviceArrival DeviceOtherEvent DeviceQueryRemove "
+ "DeviceQueryRemoveFailed DeviceRemoveComplete DoGetNewFileName "
+ "DeviceRemovePending DevModeChange Disconnect DisplayChanged "
+ "Dissociate Done DonePainting DownClick DragDrop DragOver "
+ "DropDown EditProperty EnterCell EnterFocus ExitFocus Expand "
+ "FootnoteActivated FootnoteSelected FootnoteUpdated GotFocus "
+ "HeadClick InfoMessage Initialize IniProperties ItemActivated "
+ "ItemAdded ItemCheck ItemClick ItemReloaded ItemRemoved "
+ "ItemRenamed ItemSeletected KeyDown KeyPress KeyUp LeaveCell "
+ "LegendActivated LegendSelected LegendUpdated LinkClose "
+ "LinkError LinkNotify LinkOpen Load LostFocus MouseDown "
+ "MouseMove MouseUp NodeClick ObjectMove OLECompleteDrag "
+ "OLEDragDrop OLEDragOver OLEGiveFeedback OLESetData OLEStartDrag "
+ "OnAddNew OnComm Paint PanelClick PanelDblClick PathChange "
+ "PatternChange PlotActivated PlotSelected PlotUpdated "
+ "PointActivated Reposition SelChange StateChanged TitleActivated "
+ "PointLabelActivated PointLabelSelected PointLabelUpdated "
+ "PointSelected PointUpdated PowerQuerySuspend PowerResume "
+ "PowerStatusChanged PowerSuspend QueryChangeConfig QueryComplete "
+ "QueryCompleted QueryTimeout QueryUnload ReadProperties "
+ "RequestChangeFileName RequestWriteFile Resize ResultsChanged "
+ "RowColChange RowCurrencyChange RowResize RowStatusChanged "
+ "SelectionChanged SendComplete SendProgress SeriesActivated "
+ "SeriesSelected SeriesUpdated SettingChanged SplitChange Unload "
+ "StatusUpdate SysColorsChanged Terminate TimeChanged "
+ "TitleSelected TitleActivated UnboundAddData UnboundDeleteRow "
+ "UnboundGetRelativeBookmark UnboundReadData UnboundWriteData "
+ "UpClick Updated Validate ValidationError WillAssociate "
+ "WillDissociate WillExecute WillUpdateRows WriteProperties "
+ "WillChangeData")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (stc.STC_B_ASM, 'asm_style'),
+ (stc.STC_B_BINNUMBER, 'default_style'), # STYLE NEEDED
+ (stc.STC_B_COMMENT, 'comment_style'),
+ (stc.STC_B_CONSTANT, 'const_style'),
+ (stc.STC_B_DATE, 'default_style'), # STYLE NEEDED
+ (stc.STC_B_DEFAULT, 'default_style'),
+ (stc.STC_B_ERROR, 'error_style'),
+ (stc.STC_B_HEXNUMBER, 'number_style'),
+ (stc.STC_B_IDENTIFIER, 'default_style'),
+ (stc.STC_B_KEYWORD, 'keyword_style'),
+ (stc.STC_B_KEYWORD2, 'class_style'), # STYLE NEEDED
+ (stc.STC_B_KEYWORD3, 'funct_style'), # STYLE NEEDED
+ (stc.STC_B_KEYWORD4, 'scalar_style'), # STYLE NEEDED
+ (stc.STC_B_LABEL, 'directive_style'), # STYLE NEEDED
+ (stc.STC_B_NUMBER, 'number_style'),
+ (stc.STC_B_OPERATOR, 'operator_style'),
+ (stc.STC_B_PREPROCESSOR, 'pre_style'),
+ (stc.STC_B_STRING, 'string_style'),
+ (stc.STC_B_STRINGEOL, 'stringeol_style')
+ ]
+
+#---- Extra Properties ----#
+FOLD = ("fold", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for VisualBasic"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_VB)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ keywords = list()
+ tmp = [VB_KW, VB_UKW1, VB_UKW2, VB_UKW3]
+ for keyw in tmp:
+ keywords.append((keyw[0], keyw[1].lower()))
+ return keywords
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'\'']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xml.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xml.py
new file mode 100644
index 0000000..00e9023
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xml.py
@@ -0,0 +1,63 @@
+###############################################################################
+# Name: xml.py #
+# Purpose: Define XML syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: xml.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for XML Files.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _xml.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+
+# Local Imports
+import synglob
+import syndata
+import _html
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Xml Keywords
+XML_KEYWORDS = ("rss atom pubDate channel version title link description "
+ "language generator item")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for XML"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_XML)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _html.AutoIndenter)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ sgml = _html.KeywordString(synglob.ID_LANG_SGML)
+ return [(5, XML_KEYWORDS + u" " + sgml)]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return _html.SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [_html.FOLD, _html.FLD_HTML]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'<!--', u'-->']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xtext.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xtext.py
new file mode 100644
index 0000000..a9da959
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xtext.py
@@ -0,0 +1,261 @@
+###############################################################################
+# Name: xtext.py #
+# Purpose: Define xtext syntax for highlighting and other features #
+# Author: Igor Dejanovic <igor.dejanovic@gmail.com> #
+# Copyright: (c) 2009 Igor Dejanovic <igor.dejanovic@gmail.com> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: xtext.py
+AUTHOR: Igor Dejanovic
+@summary: Lexer module for Xtext language.
+ For more information see <http://www.eclipse.org/modeling/tmf/> or
+ <http://www.openarchitectureware.org/>.
+"""
+
+__author__ = "Igor Dejanovic <igor.dejanovic@gmail.com>"
+__svnid__ = "$Id: _xtext.py 70229 2012-01-01 01:27:10Z CJP $"
+__revision__ = "$Revision: 70229 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx.stc as stc
+from pygments.lexer import RegexLexer, include, bygroups
+from pygments.token import Token, Text, Comment, Operator, \
+ Keyword, Name, String, Number, Punctuation
+import re
+
+# Local Imports
+import synglob
+import syndata
+
+#-----------------------------------------------------------------------------#
+# Style Id's
+
+STC_XTEXT_DEFAULT, \
+STC_XTEXT_COMMENT, \
+STC_XTEXT_NUMBER, \
+STC_XTEXT_STRING, \
+STC_XTEXT_STRINGEOL, \
+STC_XTEXT_OPERATOR, \
+STC_XTEXT_NAME, \
+STC_XTEXT_ABSTRACTRULE, \
+STC_XTEXT_FEATURE, \
+STC_XTEXT_CROSSREF, \
+STC_XTEXT_PACKAGE, \
+STC_XTEXT_KEYWORD, \
+STC_XTEXT_KEYWORD_PSEUDO = range(13)
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Specifications ----#
+
+# Xtext Keywords
+KEYWORDS = ("grammar generate import returns enum terminal hidden with as current")
+TERMINALS = ("ID INT STRING")
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [ (STC_XTEXT_DEFAULT, 'default_style'),
+ (STC_XTEXT_COMMENT, 'comment_style'),
+ (STC_XTEXT_NUMBER, 'number_style'),
+ (STC_XTEXT_STRING, 'string_style'),
+ (STC_XTEXT_STRINGEOL, 'stringeol_style'),
+ (STC_XTEXT_OPERATOR, 'operator_style'),
+ (STC_XTEXT_NAME, 'default_style'),
+ (STC_XTEXT_ABSTRACTRULE, 'keyword3_style'),
+ (STC_XTEXT_FEATURE, 'default_style'),
+ (STC_XTEXT_CROSSREF, 'class_style'),
+ (STC_XTEXT_PACKAGE, 'class_style'),
+ (STC_XTEXT_KEYWORD, 'keyword_style'),
+ (STC_XTEXT_KEYWORD_PSEUDO, 'keyword2_style'), ]
+
+
+#-------- Xtext grammar rules ---------------
+
+#---- Extra Properties ----#
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for XText"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_CONTAINER)
+ self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter)
+ self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return [(1, KEYWORDS)]
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u"//"]
+
+#-----------------------------------------------------------------------------#
+# Features
+
+def StyleText(stc, start, end):
+ """Style the text
+ @param stc: Styled text control instance
+ @param start: Start position
+ @param end: end position
+
+ """
+
+ for index, token, txt in lexer.get_tokens_unprocessed(stc.GetTextRange(0, end)):
+# print index, token, txt
+ style = TOKEN_MAP.get(token, STC_XTEXT_DEFAULT)
+
+# print "Text=%s, len=%s" % (txt, len(txt))
+ stc.StartStyling(index, 0x1f)
+ tlen = len(txt)
+ if tlen:
+ stc.SetStyling(len(txt), style)
+
+def AutoIndenter(estc, pos, ichar):
+ """Auto indent xtext code.
+ This code is based on python AutoIndenter.
+ @param estc: EditraStyledTextCtrl
+ @param pos: current carat position
+ @param ichar: Indentation character
+ @return: string
+
+ """
+ rtxt = u''
+ line = estc.GetCurrentLine()
+ spos = estc.PositionFromLine(line)
+ text = estc.GetTextRange(spos, pos)
+ eolch = estc.GetEOLChar()
+ inspace = text.isspace()
+
+ # Cursor is in the indent area somewhere or in the column 0.
+ if inspace or not len(text):
+ estc.AddText(eolch + text)
+ return
+
+ text = text.strip()
+ if text.endswith(";"):
+ estc.AddText(eolch)
+ return
+
+ indent = estc.GetLineIndentation(line)
+ if ichar == u"\t":
+ tabw = estc.GetTabWidth()
+ else:
+ tabw = estc.GetIndent()
+
+ i_space = indent / tabw
+ end_spaces = ((indent - (tabw * i_space)) * u" ")
+
+ if text.endswith(u":"):
+ i_space += 1
+
+ rtxt = eolch + ichar * i_space + end_spaces
+
+ # Put text in the buffer
+ estc.AddText(rtxt)
+
+#-----------------------------------------------------------------------------#
+
+TOKEN_MAP = { Token.String : STC_XTEXT_STRING,
+ Token.Comment.Multiline : STC_XTEXT_COMMENT,
+ Token.Comment.Single : STC_XTEXT_COMMENT,
+ Token.Operator : STC_XTEXT_OPERATOR,
+ Token.Punctuation : STC_XTEXT_OPERATOR,
+ Token.Number.Integer : STC_XTEXT_NUMBER,
+ Token.Keyword : STC_XTEXT_KEYWORD,
+ Token.Keyword.Pseudo: STC_XTEXT_KEYWORD_PSEUDO,
+ Token.Name : STC_XTEXT_NAME,
+ Token.Name.AbstractRule : STC_XTEXT_ABSTRACTRULE,
+ Token.Name.Feature : STC_XTEXT_FEATURE,
+ Token.Name.CrossRef : STC_XTEXT_CROSSREF,
+ Token.Name.Package : STC_XTEXT_PACKAGE,
+ Token.Name.Package.EMF : STC_XTEXT_PACKAGE}
+
+
+class XTextLexer(RegexLexer):
+ """
+ Xtext lexer based on statefull RegexLexer from pygments library.
+ """
+
+ name = 'Xtext'
+ aliases = ['xtext']
+ filenames = ['*.xtxt']
+ mimetypes = ['text/x-xtext']
+
+ flags = re.MULTILINE | re.DOTALL # | re.UNICODE
+
+ #: optional Comment or Whitespace
+ #_ws = r'(?:\s|//.*?\n|/[*].*?[*]/)+'
+
+ def AltWords(words):
+ """Makes lexer rule for alternative words from the given words list.
+ @param words: string consisting of space separated words
+ @return: string in the form \\bword1\\b|\\bword2\\b|\\bword3\b...
+ """
+ return "|".join([ "\\b%s\\b" % w for w in words.split()])
+
+ _ident = r'\^?[a-zA-Z_\$][a-zA-Z0-9_]*'
+
+ tokens = {
+ 'root': [
+ (include('first')),
+ (_ident + r'(\.' + _ident + r')+', Name.Package),
+ ('(' + _ident + r')(\s*)(returns)',
+ bygroups(Name.AbstractRule, Text.Whitespace, Keyword), 'parserrule'),
+ ('(' + _ident + r')(\s*)(:)',
+ bygroups(Name.AbstractRule, Text.Whitespace, Punctuation), 'parserrule'),
+ (_ident, Name),
+ ],
+ 'first': [
+ (r'/\*', Comment.Multiline, 'comment'),
+ (r'\n', Token.EndOfLine),
+ (r'//[^\n]*$', Comment.Single),
+ (r'[ \t]+', Text.Whitespace),
+ (r'"(\\\\|\\"|[^"])*"', String),
+ (r"'(\\\\|\\'|[^'])*'", String),
+ (r'\*|\?|\+|!|\||=|\?=|\+=|\.\.|->', Operator),
+ (r'[()\[\]{}:]', Punctuation),
+ (r'[0-9]+', Number.Integer),
+ (AltWords(KEYWORDS), Keyword),
+ (AltWords(TERMINALS), Keyword.Pseudo),
+ (_ident + r'(::' + _ident + r')+', Name.Package.EMF),
+ ],
+ 'parserrule': [
+ (include('first')),
+ ('(' + _ident + r'(\.' + _ident + r')?)([ \t]*)(=|\?=|\+=)',
+ bygroups(Name.Feature, Text.Whitespace, Operator)),
+ (_ident + r'(\.' + _ident + r')+', Name.Package),
+ (_ident, Name.CrossRef),
+ (r';', Punctuation, "#pop"),
+ ],
+ 'comment': [
+ # Nested and multiline comments
+ (r'/\*', Comment.Multiline, "#push"),
+ (r'\*/', Comment.Multiline, "#pop"),
+ (r'\n', Token.EndOfLine),
+ (r'[^/*\n]+', Comment.Multiline),
+ (r'\*|\/', Comment.Multiline),
+ ],
+ }
+
+lexer = XTextLexer()
+
+if __name__=='__main__':
+ import codecs, sys
+ ftext = codecs.open(sys.argv[1], "r", "utf-8")
+ text = ftext.read()
+ ftext.close()
+ line=1
+ for index, token, txt in lexer.get_tokens_unprocessed(text):
+ if token is Token.EndOfLine:
+ line += 1
+ print line, token, txt
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_yaml.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_yaml.py
new file mode 100644
index 0000000..26407ee
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_yaml.py
@@ -0,0 +1,77 @@
+###############################################################################
+# Name: yaml.py #
+# Purpose: Define YAML syntax for highlighting and other features #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: yaml.py
+AUTHOR: Cody Precord
+@summary: Lexer configuration module for YAML
+@todo: Maybe new custom style for text regions
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: _yaml.py 68798 2011-08-20 17:17:05Z CJP $"
+__revision__ = "$Revision: 68798 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import wx
+import wx.stc as stc
+
+# Local Imports
+import syndata
+
+#-----------------------------------------------------------------------------#
+
+#---- Keyword Definitions ----#
+YAML_KW = [(0, "true false yes no")]
+
+#---- End Keyword Definitions ----#
+
+#---- Syntax Style Specs ----#
+SYNTAX_ITEMS = [(stc.STC_YAML_COMMENT, 'comment_style'),
+ (stc.STC_YAML_DEFAULT, 'default_style'),
+ (stc.STC_YAML_DOCUMENT, 'scalar_style'),
+ (stc.STC_YAML_ERROR, 'error_style'),
+ (stc.STC_YAML_IDENTIFIER, 'keyword2_style'),
+ (stc.STC_YAML_KEYWORD, 'keyword_style'),
+ (stc.STC_YAML_NUMBER, 'number_style'),
+ (stc.STC_YAML_REFERENCE, 'global_style'),
+ (stc.STC_YAML_TEXT, 'default_style')] # Different style maybe
+
+if wx.VERSION >= (2, 9, 0, 0, ''):
+ SYNTAX_ITEMS.append((stc.STC_YAML_OPERATOR, 'operator_style'))
+
+#---- Extra Properties ----#
+FOLD_COMMENT = ("fold.comment.yaml", "1")
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxData(syndata.SyntaxDataBase):
+ """SyntaxData object for YAML"""
+ def __init__(self, langid):
+ super(SyntaxData, self).__init__(langid)
+
+ # Setup
+ self.SetLexer(stc.STC_LEX_YAML)
+
+ def GetKeywords(self):
+ """Returns Specified Keywords List """
+ return YAML_KW
+
+ def GetSyntaxSpec(self):
+ """Syntax Specifications """
+ return SYNTAX_ITEMS
+
+ def GetProperties(self):
+ """Returns a list of Extra Properties to set """
+ return [FOLD_COMMENT]
+
+ def GetCommentPattern(self):
+ """Returns a list of characters used to comment a block of code """
+ return [u'#']
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syndata.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syndata.py
new file mode 100644
index 0000000..c2ab987
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syndata.py
@@ -0,0 +1,141 @@
+ #-*- coding: utf-8 -*-
+###############################################################################
+# Name: syndata.py #
+# Purpose: Syntax Data Base #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+""" Interface definition for syntax data
+
+@summary: Editra Syntax Data Interface Definition
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: syndata.py 67392 2011-04-04 21:06:43Z CJP $"
+__revision__ = "$Revision: 67392 $"
+
+__all__ = ['SyntaxDataBase',]
+
+#-----------------------------------------------------------------------------#
+# Imports
+import collections
+import wx.stc as stc
+
+# Local Imports
+import synglob
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxDataBase(object):
+ """Syntax data container object base class"""
+ def __init__(self, langid=synglob.ID_LANG_TXT):
+ object.__init__(self)
+
+ # Attributes
+ self._langid = langid
+ self._lexer = stc.STC_LEX_NULL
+ self._features = dict()
+
+ @property
+ def CommentPattern(self):
+ return self.GetCommentPattern()
+
+ @property
+ def Keywords(self):
+ return self.GetKeywords()
+
+ @property
+ def LangId(self):
+ return self.GetLangId()
+
+ @property
+ def Lexer(self):
+ return self.GetLexer()
+
+ @property
+ def Properties(self):
+ return self.GetProperties()
+
+ @property
+ def SyntaxSpec(self):
+ return self.GetSyntaxSpec()
+
+ #---- Interface Methods ----#
+
+ def GetCommentPattern(self):
+ """Get the comment pattern
+ @return: list of strings ['/*', '*/']
+
+ """
+ return list()
+
+ def GetKeywords(self):
+ """Get the Keyword List(s)
+ @return: list of tuples [(1, ['kw1', kw2']),]
+
+ """
+ return list()
+
+ def GetLangId(self):
+ """Get the language id
+ @return: int
+
+ """
+ return self._langid
+
+ def GetLexer(self):
+ """Get the lexer id
+ @return: wx.stc.STC_LEX_
+
+ """
+ return self._lexer
+
+ def GetProperties(self):
+ """Get the Properties List
+ @return: list of tuples [('fold', '1'),]
+
+ """
+ return list()
+
+ def GetSyntaxSpec(self):
+ """Get the the syntax specification list
+ @return: list of tuples [(int, 'style_tag'),]
+ @note: required override for subclasses
+
+ """
+ raise NotImplementedError
+
+ #---- End Interface Methods ----#
+
+ def GetFeature(self, name):
+ """Get a registered features callable
+ @param name: feature name
+ @return: callable or None
+
+ """
+ return self._features.get(name, None)
+
+ def RegisterFeature(self, name, funct):
+ """Register an extension feature with the factory
+ @param name: feature name
+ @param funct: callable
+
+ """
+ assert isinstance(funct, collections.Callable), "funct must be callable object"
+ self._features[name] = funct
+
+ def SetLexer(self, lex):
+ """Set the lexer object for this data object"""
+ self._lexer = lex
+
+ def SetLangId(self, lid):
+ """Set the language identifier
+ @param lid: int
+
+ """
+ self._langid = lid
+
+#-----------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synextreg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synextreg.py
new file mode 100644
index 0000000..60b6a34
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synextreg.py
@@ -0,0 +1,598 @@
+###############################################################################
+# Name: synextreg.py #
+# Purpose: IDs and descriptions for supported file types, and also the #
+# ExtensionRegister. These items are here in this module inorder to #
+# be usable external to Editra and where wx may not be available. #
+# #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: synextreg.py
+LANGUAGE: Python
+@summary: This module defines all supported language/filetype identifiers and
+ an extension register for mapping file extensions to filetypes.
+@see: synglob.py for more details on how this data is used
+
+@note: Don't use this module directly for internal use only
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: synextreg.py 70228 2011-12-31 20:39:16Z CJP $"
+__revision__ = "$Revision: 70228 $"
+
+#-----------------------------------------------------------------------------#
+import os
+
+#-----------------------------------------------------------------------------#
+
+def _NewId():
+ global _idCounter
+ _idCounter += 1
+ return _idCounter
+
+_idCounter = 32100
+
+#-----------------------------------------------------------------------------#
+
+#---- Language Identifiers Keys ----#
+# Used for specifying what dialect/keyword set to load for a specific lexer
+
+#---- Use LEX_NULL ----#
+ID_LANG_TXT = _NewId()
+LANG_TXT = u'Plain Text'
+
+#---- Use LEX_ADA ----#
+ID_LANG_ADA = _NewId()
+LANG_ADA = u'Ada'
+
+#---- Use LEX_ASM ----#
+ID_LANG_ASM = _NewId()
+LANG_ASM = u'GNU Assembly'
+ID_LANG_DSP56K = _NewId()
+LANG_DSP56K = u'DSP56K Assembly'
+ID_LANG_68K = _NewId()
+LANG_68K = u'68k Assembly'
+ID_LANG_MASM = _NewId()
+LANG_MASM = u'MASM'
+ID_LANG_NASM = _NewId()
+LANG_NASM = u'Netwide Assembler'
+
+# Use LEX_BASH
+ID_LANG_BOURNE = _NewId()
+LANG_BOURNE = u'Bourne Shell Script'
+ID_LANG_BASH = _NewId()
+LANG_BASH = u'Bash Shell Script'
+ID_LANG_CSH = _NewId()
+LANG_CSH = u'C-Shell Script'
+ID_LANG_KSH = _NewId()
+LANG_KSH = u'Korn Shell Script'
+
+# Use LEX_CAML
+ID_LANG_CAML = _NewId()
+LANG_CAML = u'Caml'
+
+# Use LEX_CONF
+ID_LANG_APACHE = _NewId()
+LANG_APACHE = u'Apache Conf'
+
+# Use LEX_CPP
+ID_LANG_AS = _NewId()
+LANG_AS = u'ActionScript'
+ID_LANG_C = _NewId()
+LANG_C = u'C'
+ID_LANG_CILK = _NewId()
+LANG_CILK = u'Cilk'
+ID_LANG_CPP = _NewId()
+LANG_CPP = u'CPP'
+ID_LANG_CSHARP = _NewId()
+LANG_CSHARP = u'C#'
+ID_LANG_D = _NewId()
+LANG_D = u'D'
+ID_LANG_DOT = _NewId()
+LANG_DOT = u'DOT'
+ID_LANG_EDJE = _NewId()
+LANG_EDJE = u'Edje'
+ID_LANG_FERITE = _NewId()
+LANG_FERITE = u'Ferite'
+ID_LANG_GLSL = _NewId()
+LANG_GLSL = u'GLSL'
+ID_LANG_HAXE = _NewId()
+LANG_HAXE = u'HaXe'
+ID_LANG_JAVA = _NewId()
+LANG_JAVA = u'Java'
+ID_LANG_OBJC = _NewId()
+LANG_OBJC = u'Objective C'
+ID_LANG_OOC = _NewId()
+LANG_OOC = u'OOC'
+ID_LANG_PIKE = _NewId()
+LANG_PIKE = u'Pike'
+ID_LANG_SQUIRREL = _NewId()
+LANG_SQUIRREL = u'Squirrel'
+ID_LANG_STATA = _NewId()
+LANG_STATA = u'Stata'
+ID_LANG_VALA = _NewId()
+LANG_VALA = u'Vala'
+
+# Use LEX_CSS
+ID_LANG_CSS = _NewId()
+LANG_CSS = u'Cascading Style Sheet'
+ID_LANG_ESS = _NewId()
+LANG_ESS = u'Editra Style Sheet'
+
+# Use LEX_EIFFEL
+ID_LANG_EIFFEL = _NewId()
+LANG_EIFFEL = u'Eiffel'
+
+# Use LEX_ERLANG
+ID_LANG_ERLANG = _NewId()
+LANG_ERLANG = u'Erlang'
+
+# Use LEX_FLAGSHIP
+ID_LANG_FLAGSHIP = _NewId()
+LANG_FLAGSHIP = u'FlagShip'
+
+# Use LEX_F77
+ID_LANG_F77 = _NewId()
+LANG_F77 = u'Fortran 77'
+
+# Use LEX_FORTH
+ID_LANG_FORTH = _NewId()
+LANG_FORTH = u"Forth"
+
+# Use LEX_FORTRAN
+ID_LANG_F95 = _NewId()
+LANG_F95 = u'Fortran 95'
+
+# Use LEX_GUI4CLI
+ID_LANG_GUI4CLI = _NewId()
+LANG_GUI4CLI = u'Gui4Cli'
+
+# Use LEX_HASKELL
+ID_LANG_HASKELL = _NewId()
+LANG_HASKELL = u'Haskell'
+
+# Use LEX_HTML
+ID_LANG_COLDFUSION = _NewId()
+LANG_COLDFUSION = u'ColdFusion'
+ID_LANG_HTML = _NewId()
+LANG_HTML = u'HTML'
+ID_LANG_JS = _NewId()
+LANG_JS = u'JavaScript'
+ID_LANG_PHP = _NewId()
+LANG_PHP = u'PHP'
+ID_LANG_XML = _NewId()
+LANG_XML = u'XML'
+ID_LANG_SGML = _NewId()
+
+# Use LEX_INNOSETUP
+ID_LANG_INNO = _NewId()
+LANG_INNO = u'Inno Setup Script'
+
+# Use LEX_KIX
+ID_LANG_KIX = _NewId()
+LANG_KIX = u'Kix'
+
+# Use LEX_LISP
+ID_LANG_LISP = _NewId()
+LANG_LISP = u'Lisp'
+ID_LANG_SCHEME = _NewId()
+LANG_SCHEME = u'Scheme'
+ID_LANG_NEWLISP = _NewId()
+LANG_NEWLISP = u'newLISP'
+
+# Use LEX_LOUT
+ID_LANG_LOUT = _NewId()
+LANG_LOUT = u'Lout'
+
+# Use LEX_LUA
+ID_LANG_LUA = _NewId()
+LANG_LUA = u'Lua'
+
+# Use LEX_MSSQL (Microsoft SQL)
+ID_LANG_MSSQL = _NewId()
+LANG_MSSQL = u'Microsoft SQL'
+
+# Use LEX_NONMEM
+ID_LANG_NONMEM = _NewId()
+LANG_NONMEM = u'NONMEM Control Stream'
+
+# Use LEX_NSIS
+ID_LANG_NSIS = _NewId()
+LANG_NSIS = u'Nullsoft Installer Script'
+
+# Use LEX_PASCAL
+ID_LANG_PASCAL = _NewId()
+LANG_PASCAL = u'Pascal'
+
+# Use LEX_PERL
+ID_LANG_PERL = _NewId()
+LANG_PERL = u'Perl'
+
+# Use LEX_PS
+ID_LANG_PS = _NewId()
+LANG_PS = u'Postscript'
+
+# Use LEX_PYTHON
+ID_LANG_BOO = _NewId()
+LANG_BOO = u'Boo'
+ID_LANG_PYTHON = _NewId()
+LANG_PYTHON = u'Python'
+ID_LANG_COBRA = _NewId()
+LANG_COBRA = u'Cobra'
+
+# Use LEX_MATLAB
+ID_LANG_MATLAB = _NewId()
+LANG_MATLAB = u'Matlab'
+
+# Use LEX_RUBY
+ID_LANG_RUBY = _NewId()
+LANG_RUBY = u'Ruby'
+
+# Use LEX_SMALLTALK
+ID_LANG_ST = _NewId()
+LANG_ST = u'Smalltalk'
+
+# Use LEX_SQL (PL/SQL, SQL*Plus)
+ID_LANG_SQL = _NewId()
+LANG_SQL = u'SQL'
+ID_LANG_PLSQL = _NewId()
+LANG_PLSQL = u'PL/SQL'
+ID_LANG_4GL = _NewId()
+LANG_4GL = u"Progress 4GL"
+
+# Use LEX_TCL
+ID_LANG_TCL = _NewId()
+LANG_TCL = u'Tcl/Tk'
+
+# Use LEX_TEX
+ID_LANG_TEX = _NewId()
+LANG_TEX = u'Tex'
+ID_LANG_LATEX = _NewId()
+LANG_LATEX = u'LaTeX'
+
+# Use LEX_VB
+ID_LANG_VB = _NewId()
+LANG_VB = u'Visual Basic'
+
+# Use LEX_VBSCRIPT
+ID_LANG_VBSCRIPT = _NewId()
+LANG_VBSCRIPT = u'VBScript'
+
+# Use LEX_VERILOG
+ID_LANG_VERILOG = _NewId()
+LANG_VERILOG = u'Verilog'
+ID_LANG_SYSVERILOG = _NewId()
+LANG_SYSVERILOG = u'System Verilog'
+
+# Use LEX_VHDL
+ID_LANG_VHDL = _NewId()
+LANG_VHDL = u'VHDL'
+
+# Use LEX_OCTAVE
+ID_LANG_OCTAVE = _NewId()
+LANG_OCTAVE = u'Octave'
+
+# Use LEX_OTHER (Batch, Diff, Makefile)
+ID_LANG_BATCH = _NewId()
+LANG_BATCH = u'DOS Batch Script'
+ID_LANG_DIFF = _NewId()
+LANG_DIFF = u'Diff File'
+ID_LANG_MAKE = _NewId()
+LANG_MAKE = u'Makefile'
+ID_LANG_PROPS = _NewId()
+LANG_PROPS = u'Properties'
+
+# Use LEX_YAML
+ID_LANG_YAML = _NewId()
+LANG_YAML = u'YAML'
+
+# Use LEX_CONTAINER
+ID_LANG_DJANGO = _NewId()
+LANG_DJANGO = u'Django'
+ID_LANG_ISSL = _NewId()
+LANG_ISSL = u'IssueList'
+ID_LANG_MAKO = _NewId()
+LANG_MAKO = u'Mako'
+ID_LANG_R = _NewId()
+LANG_R = u'R'
+ID_LANG_S = _NewId()
+LANG_S = u'S'
+ID_LANG_GROOVY = _NewId()
+LANG_GROOVY = u'Groovy'
+ID_LANG_XTEXT = _NewId()
+LANG_XTEXT = u'Xtext'
+
+#---- End Language Identifier Keys ----#
+
+# Default extensions to file type mapping
+EXT_MAP = {
+ '4gl' : LANG_4GL,
+ '56k' : LANG_DSP56K,
+ '68k' : LANG_68K,
+ 'ada adb ads a' : LANG_ADA,
+ 'conf htaccess' : LANG_APACHE,
+ 'as asc mx' : LANG_AS,
+ 'gasm' : LANG_ASM,
+ 'bsh sh configure' : LANG_BASH,
+ 'bat cmd' : LANG_BATCH,
+ 'boo' : LANG_BOO,
+ 'c h' : LANG_C,
+ 'ml mli' : LANG_CAML,
+ 'cilk cilkh' : LANG_CILK,
+ 'cobra' : LANG_COBRA,
+ 'cfm cfc cfml dbm' : LANG_COLDFUSION,
+ 'cc c++ cpp cxx hh h++ hpp hxx' : LANG_CPP,
+ 'csh' : LANG_CSH,
+ 'cs' : LANG_CSHARP,
+ 'css' : LANG_CSS,
+ 'd' : LANG_D,
+ 'patch diff' : LANG_DIFF,
+ 'django' : LANG_DJANGO,
+ 'dot' : LANG_DOT,
+ 'edc' : LANG_EDJE,
+ 'e' : LANG_EIFFEL,
+ 'erl' : LANG_ERLANG,
+ 'ess' : LANG_ESS,
+ 'f for' : LANG_F77,
+ 'f90 f95 f2k fpp' : LANG_F95,
+ 'fe' : LANG_FERITE,
+ 'fth 4th fs seq' : LANG_FORTH,
+ 'prg' : LANG_FLAGSHIP,
+ 'frag vert glsl' : LANG_GLSL,
+ 'gc gui' : LANG_GUI4CLI,
+ 'hs' : LANG_HASKELL,
+ 'hx hxml' : LANG_HAXE,
+ 'htm html shtm shtml xhtml' : LANG_HTML,
+ 'isl' : LANG_ISSL,
+ 'iss' : LANG_INNO,
+ 'java' : LANG_JAVA,
+ 'js' : LANG_JS,
+ 'kix' : LANG_KIX,
+ 'ksh' : LANG_KSH,
+ 'aux tex sty' : LANG_LATEX,
+ 'cl lisp' : LANG_LISP,
+ 'lsp' : LANG_NEWLISP,
+ 'lt' : LANG_LOUT,
+ 'lua' : LANG_LUA,
+ 'mak makefile mk' : LANG_MAKE,
+ 'mao mako' : LANG_MAKO,
+ 'asm masm' : LANG_MASM,
+ 'matlab' : LANG_MATLAB,
+ 'mssql' : LANG_MSSQL,
+ 'nasm' : LANG_NASM,
+ 'ctl nonmem' : LANG_NONMEM,
+ 'nsi nsh' : LANG_NSIS,
+ 'mm m' : LANG_OBJC,
+ 'oct octave' : LANG_OCTAVE,
+ 'ooc' : LANG_OOC,
+ 'dfm dpk dpr inc p pas pp' : LANG_PASCAL,
+ 'cgi pl pm pod' : LANG_PERL,
+ 'php php3 phtml phtm' : LANG_PHP,
+ 'pike' : LANG_PIKE,
+ 'plsql' : LANG_PLSQL,
+ 'ini inf reg url cfg cnf' : LANG_PROPS,
+ 'ai ps' : LANG_PS,
+ 'py pyw python' : LANG_PYTHON,
+ 'r' : LANG_R,
+ 'do ado' : LANG_STATA,
+ 'rake rb rbw rbx gemspec' : LANG_RUBY,
+ 's' : LANG_S,
+ 'scm smd ss' : LANG_SCHEME,
+ 'sql' : LANG_SQL,
+ 'nut' : LANG_SQUIRREL,
+ 'st' : LANG_ST,
+ 'sv svh' : LANG_SYSVERILOG,
+ 'itcl tcl tk' : LANG_TCL,
+ 'txt' : LANG_TXT,
+ 'vala' : LANG_VALA,
+ 'bas cls frm vb' : LANG_VB,
+ 'vbs dsm' : LANG_VBSCRIPT,
+ 'v' : LANG_VERILOG,
+ 'vh vhdl vhd' : LANG_VHDL,
+ 'axl dtd plist rdf svg xml xrc xsd xsl xslt xul' : LANG_XML,
+ 'yaml yml' : LANG_YAML,
+ 'groovy' : LANG_GROOVY,
+ 'xtext' : LANG_XTEXT,
+ }
+
+
+#-----------------------------------------------------------------------------#
+
+class ExtensionRegister(dict):
+ """A data storage class for managing mappings of
+ file types to file extensions. The register is created as a singleton.
+
+ """
+ instance = None
+ config = u'synmap'
+ def __init__(self):
+ """Initializes the register"""
+ if not ExtensionRegister.instance:
+ self.LoadDefault()
+
+ def __new__(cls, *args, **kargs):
+ """Maintain only a single instance of this object
+ @return: instance of this class
+
+ """
+ if not cls.instance:
+ cls.instance = dict.__new__(cls, *args, **kargs)
+ return cls.instance
+
+ def __missing__(self, key):
+ """Return the default value if an item is not found
+ @return: txt extension for plain text
+
+ """
+ return u'txt'
+
+ def __setitem__(self, i, y):
+ """Ensures that only one filetype is associated with an extension
+ at one time. The behavior is that more recent settings override
+ and remove associations from older settings.
+ @param i: key to set
+ @param y: value to set
+ @throws: TypeError Only accepts list() objects
+
+ """
+ if not isinstance(y, list):
+ raise TypeError, "Extension Register Expects a List"
+ for key, val in self.iteritems():
+ for item in y:
+ if item in val:
+ val.pop(val.index(item))
+ y.sort()
+ dict.__setitem__(self, i, [x.strip() for x in y])
+
+ def __str__(self):
+ """Converts the Register to a string that is formatted
+ for output to a config file.
+ @return: the register as a string
+
+ """
+ keys = self.keys()
+ keys.sort()
+ tmp = list()
+ for key in keys:
+ tmp.append("%s=%s" % (key, u':'.join(self.__getitem__(key))))
+ return os.linesep.join(tmp)
+
+ def Associate(self, ftype, ext):
+ """Associate a given file type with the given file extension(s).
+ The ext parameter can be a string of space separated extensions
+ to allow for multiple associations at once.
+ @param ftype: file type description string
+ @param ext: file extension to associate
+
+ """
+ assoc = self.get(ftype, None)
+ exts = ext.strip().split()
+ if assoc:
+ for x in exts:
+ if x not in assoc:
+ assoc.append(x)
+ else:
+ assoc = list(set(exts))
+ assoc.sort()
+ super(ExtensionRegister, self).__setitem__(ftype, assoc)
+
+ def Disassociate(self, ftype, ext):
+ """Disassociate a file type with a given extension or space
+ separated list of extensions.
+ @param ftype: filetype description string
+ @param ext: extension to disassociate
+
+ """
+ to_drop = ext.strip().split()
+ assoc = self.get(ftype, None)
+ if assoc:
+ for item in to_drop:
+ if item in assoc:
+ assoc.remove(item)
+ super(ExtensionRegister, self).__setitem__(ftype, assoc)
+ else:
+ pass
+
+ def FileTypeFromExt(self, ext):
+ """Returns the file type that is associated with
+ the extension. Matching is done with a case insensitive search.
+ If no association is found Plain Text
+ will be returned by default.
+ @param ext: extension to lookup
+
+ """
+ ext = ext.lower()
+ for key, val in self.iteritems():
+ if ext in [ext2.lower() for ext2 in val]:
+ return key
+ return LANG_TXT
+
+ def GetAllExtensions(self):
+ """Returns a sorted list of all extensions registered
+ @return: list of all registered extensions
+
+ """
+ ext = list()
+ for extension in self.values():
+ ext.extend(extension)
+ ext.sort()
+ return ext
+
+ def LoadDefault(self):
+ """Loads the default settings
+ @postcondition: sets dictionary back to default installation state
+
+ """
+ self.clear()
+ for key in EXT_MAP:
+ self.__setitem__(EXT_MAP[key], key.split())
+
+ def LoadFromConfig(self, config):
+ """Load the extension register with values from a config file
+ @param config: path to config file to load settings from
+
+ """
+ path = os.path.join(config, self.config)
+ if not os.path.exists(path):
+ self.LoadDefault()
+ else:
+ file_h = file(path, "rb")
+ lines = file_h.readlines()
+ file_h.close()
+ for line in lines:
+ tmp = line.split(u'=')
+ if len(tmp) != 2:
+ continue
+ ftype = tmp[0].strip()
+ exts = tmp[1].split(u':')
+ self.__setitem__(ftype, exts)
+
+ def Remove(self, ftype):
+ """Remove a filetype from the register
+ @param ftype: File type description string
+ @return: bool removed or not
+
+ """
+ if ftype in self:
+ del self[ftype]
+ return True
+ return False
+
+ def SetAssociation(self, ftype, ext):
+ """Like Associate but overrides any current settings instead of
+ just adding to them.
+ @param ftype: File type description string
+ @param ext: space separated list of file extensions to set
+
+ """
+ self.__setitem__(ftype, list(set(ext.split())))
+
+#-----------------------------------------------------------------------------#
+
+def GetFileExtensions():
+ """Gets a sorted list of all file extensions the editor is configured
+ to handle.
+ @return: all registered file extensions
+
+ """
+ extreg = ExtensionRegister()
+ return extreg.GetAllExtensions()
+
+def RegisterNewLangId(langId, langName):
+ """Register a new language identifier
+ @param langId: "ID_LANG_FOO"
+ @param langName: "Foo"
+ @return: int
+
+ """
+ gdict = globals()
+ if langId not in gdict:
+ gdict[langId] = _NewId()
+ gdict[langId[3:]] = langName
+ return gdict[langId]
+
+#-----------------------------------------------------------------------------#
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synglob.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synglob.py
new file mode 100644
index 0000000..5b71318
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synglob.py
@@ -0,0 +1,170 @@
+###############################################################################
+# Name: synglob.py #
+# Purpose: Acts as a registration point for all supported languages. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+FILE: synglob.py
+AUTHOR: Cody Precord
+@summary: Provides configuration and basic API functionality to all the syntax
+ modules. It also acts as a configuration file for the syntax
+ management code. When support for a new languages is added it must
+ have a registration entry in the below L{LANG_MAP} dictionary in
+ order to be loadable by the syntax module.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: synglob.py 69887 2011-12-01 19:54:13Z CJP $"
+__revision__ = "$Revision: 69887 $"
+
+#-----------------------------------------------------------------------------#
+# Dependencies
+import wx.stc as stc
+
+# The language identifiers and the EXT_MAP have been moved out of this
+# module in order to be independent of Editra and wx, but they are
+# still needed here...
+from synextreg import *
+
+#-----------------------------------------------------------------------------#
+# Feature Identifiers
+FEATURE_AUTOINDENT = u"AutoIndenter"
+FEATURE_STYLETEXT = u"StyleText"
+
+#-----------------------------------------------------------------------------#
+
+# Maps file types to syntax definitions
+LANG_MAP = {LANG_4GL : (ID_LANG_4GL, '_progress'),
+ LANG_DSP56K : (ID_LANG_DSP56K, '_asm68k'),
+ LANG_68K : (ID_LANG_68K, '_asm68k'),
+ LANG_ADA : (ID_LANG_ADA, '_ada'),
+ LANG_APACHE : (ID_LANG_APACHE, '_apache'),
+ LANG_AS : (ID_LANG_AS, '_actionscript'),
+ LANG_ASM : (ID_LANG_ASM, '_asm'),
+ LANG_BASH : (ID_LANG_BASH, '_sh'),
+ LANG_BATCH : (ID_LANG_BATCH, '_batch'),
+ LANG_BOO : (ID_LANG_BOO, '_boo'),
+ LANG_C : (ID_LANG_C, '_cpp'),
+ LANG_CAML : (ID_LANG_CAML, '_caml'),
+ LANG_CILK : (ID_LANG_CILK, '_cpp'),
+ LANG_COBRA : (ID_LANG_COBRA, '_cobra'),
+ LANG_COLDFUSION : (ID_LANG_COLDFUSION, '_html'),
+ LANG_CPP : (ID_LANG_CPP, '_cpp'),
+ LANG_CSH : (ID_LANG_CSH, '_sh'),
+ LANG_CSHARP : (ID_LANG_CSHARP, '_cpp'),
+ LANG_CSS : (ID_LANG_CSS, '_css'),
+ LANG_D : (ID_LANG_D, '_d'),
+ LANG_DIFF : (ID_LANG_DIFF, '_diff'),
+ LANG_DJANGO : (ID_LANG_DJANGO, '_django'),
+ LANG_DOT : (ID_LANG_DOT, '_dot'),
+ LANG_EDJE : (ID_LANG_EDJE, '_edje'),
+ LANG_EIFFEL : (ID_LANG_EIFFEL, '_eiffel'),
+ LANG_ERLANG : (ID_LANG_ERLANG, '_erlang'),
+ LANG_ESS : (ID_LANG_ESS, '_editra_ss'),
+ LANG_F77 : (ID_LANG_F77, '_fortran'),
+ LANG_F95 : (ID_LANG_F95, '_fortran'),
+ LANG_FERITE : (ID_LANG_FERITE, '_ferite'),
+ LANG_FLAGSHIP: (ID_LANG_FLAGSHIP, '_flagship'),
+ LANG_FORTH : (ID_LANG_FORTH, '_forth'),
+ LANG_GLSL : (ID_LANG_GLSL, '_glsl'),
+ LANG_GUI4CLI : (ID_LANG_GUI4CLI, '_gui4cli'),
+ LANG_HASKELL : (ID_LANG_HASKELL, '_haskell'),
+ LANG_HAXE : (ID_LANG_HAXE, '_haxe'),
+ LANG_HTML : (ID_LANG_HTML, '_html'),
+ LANG_INNO : (ID_LANG_INNO, '_inno'),
+ LANG_ISSL : (ID_LANG_ISSL, '_issuelist'),
+ LANG_JAVA : (ID_LANG_JAVA, '_java'),
+ LANG_JS : (ID_LANG_JS, '_javascript'),
+ LANG_KIX : (ID_LANG_KIX, '_kix'),
+ LANG_KSH : (ID_LANG_KSH, '_sh'),
+ LANG_LATEX : (ID_LANG_LATEX, '_latex'),
+ LANG_LISP : (ID_LANG_LISP, '_lisp'),
+ LANG_LOUT : (ID_LANG_LOUT, '_lout'),
+ LANG_LUA : (ID_LANG_LUA, '_lua'),
+ LANG_MAKE : (ID_LANG_MAKE, '_make'),
+ LANG_MAKO : (ID_LANG_MAKO, '_mako'),
+ LANG_MASM : (ID_LANG_MASM, '_masm'),
+ LANG_MATLAB : (ID_LANG_MATLAB, '_matlab'),
+ LANG_MSSQL : (ID_LANG_MSSQL, '_mssql'),
+ LANG_NASM : (ID_LANG_NASM, '_nasm'),
+ LANG_NEWLISP: (ID_LANG_NEWLISP,'_lisp'),
+ LANG_NONMEM : (ID_LANG_NONMEM, '_nonmem'),
+ LANG_NSIS : (ID_LANG_NSIS, '_nsis'),
+ LANG_OBJC : (ID_LANG_OBJC, '_cpp'),
+ LANG_OCTAVE : (ID_LANG_OCTAVE, '_matlab'),
+ LANG_OOC : (ID_LANG_OOC, '_ooc'),
+ LANG_PASCAL : (ID_LANG_PASCAL, '_pascal'),
+ LANG_PERL : (ID_LANG_PERL, '_perl'),
+ LANG_PHP : (ID_LANG_PHP, '_php'),
+ LANG_PIKE : (ID_LANG_PIKE, '_pike'),
+ LANG_PLSQL : (ID_LANG_PLSQL, '_sql'),
+ LANG_PROPS : (ID_LANG_PROPS, '_props'),
+ LANG_PS : (ID_LANG_PS, '_postscript'),
+ LANG_PYTHON : (ID_LANG_PYTHON, '_python'),
+ LANG_R : (ID_LANG_R, '_s'),
+ LANG_RUBY : (ID_LANG_RUBY, '_ruby'),
+ LANG_S : (ID_LANG_S, '_s'),
+ LANG_SCHEME : (ID_LANG_SCHEME, '_lisp'),
+ LANG_SQL : (ID_LANG_SQL, '_sql'),
+ LANG_SQUIRREL : (ID_LANG_SQUIRREL, '_squirrel'),
+ LANG_ST : (ID_LANG_ST, '_smalltalk'),
+ LANG_STATA : (ID_LANG_STATA, '_stata'),
+ LANG_SYSVERILOG : (ID_LANG_SYSVERILOG, '_verilog'),
+ LANG_TCL : (ID_LANG_TCL, '_tcl'),
+ LANG_TXT : (ID_LANG_TXT, None),
+ LANG_VALA : (ID_LANG_VALA, '_cpp'),
+ LANG_VB : (ID_LANG_VB, '_visualbasic'),
+ LANG_VBSCRIPT : (ID_LANG_VBSCRIPT, '_vbscript'),
+ LANG_VERILOG: (ID_LANG_VERILOG, '_verilog'),
+ LANG_VHDL : (ID_LANG_VHDL, '_vhdl'),
+ LANG_XML : (ID_LANG_XML, '_xml'),
+ LANG_YAML : (ID_LANG_YAML, '_yaml'),
+ LANG_GROOVY : (ID_LANG_GROOVY, '_groovy'),
+ LANG_XTEXT : (ID_LANG_XTEXT, '_xtext')
+ }
+
+
+### TODO: Profiling on the following methods to see if caching is necessary ###
+
+# Dynamically finds the language description string that matches the given
+# language id.
+# Used when manually setting lexer from a menu/dialog
+def GetDescriptionFromId(lang_id):
+ """Get the programming languages description string from the given
+ language id. If no corresponding language is found the plain text
+ description is returned.
+ @param lang_id: Language Identifier ID
+ @note: requires that all languages are defined in ID_LANG_NAME, LANG_NAME
+ pairs to work properly.
+
+ """
+ rval = LANG_TXT
+ # Guard against async code that may be modifying globals
+ globs = dict(globals())
+ for key, val in globs.iteritems():
+ if val == lang_id and key.startswith('ID_LANG'):
+ rval = globs.get(key[3:], LANG_TXT)
+ break
+ return rval
+
+def GetIdFromDescription(desc):
+ """Get the language identifier for the given file type string. The search
+ is case insensitive.
+ @param desc: unicode (i.e u"Python")
+ @note: if lookup fails ID_LANG_TXT is returned
+
+ """
+ rval = ID_LANG_TXT
+ desc = desc.lower()
+ # Guard against async code that may be modifying globals
+ globs = dict(globals())
+ for key, val in globs.iteritems():
+ if isinstance(val, unicode):
+ if val.lower() == desc and key.startswith('LANG_'):
+ rval = globs.get("ID_" + key, ID_LANG_TXT)
+ break
+ return rval
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syntax.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syntax.py
new file mode 100644
index 0000000..e913f45
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syntax.py
@@ -0,0 +1,441 @@
+###############################################################################
+# Name: syntax.py #
+# Purpose: Manage and dynamically load/provide syntax on request from editor. #
+# Also manages the mappings of file extensions to lexers. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2007 Cody Precord <staff@editra.org> #
+# Licence: wxWindows Licence #
+###############################################################################
+
+"""
+FILE: syntax.py
+AUTHOR: Cody Precord
+
+SUMMARY:
+
+Toolkit for managing the importing of syntax modules and providing the data
+to the requesting text control. It is meant to be the main access point to the
+resources and api provided by this package.
+
+DETAIL:
+
+The main item of this module is the L{SyntaxMgr} it is a singleton object that
+manages the dynamic importing of syntax data and configurations for all of the
+editors supported languages. It allows only the needed data to be loaded into
+memory when requested. The loading is only done once per session and all
+subsequent requests share the same object.
+
+In addition to the L{SyntaxMgr} there are also a number of other utility and
+convienience functions in this module for accessing data from other related
+objects such as the Extension Register.
+
+@summary: Main api access point for the syntax package.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: syntax.py 71711 2012-06-09 18:59:03Z CJP $"
+__revision__ = "$Revision: 71711 $"
+
+#-----------------------------------------------------------------------------#
+# Dependencies
+import wx
+import os
+
+#-----------------------------------------------------------------------------#
+# Data Objects / Constants
+
+# Used to index the tuple returned by getting data from EXT_REG
+LANG_ID = 0
+MODULE = 1
+
+_ = wx.GetTranslation
+#-----------------------------------------------------------------------------#
+# Imports
+import synglob
+import syndata
+import synxml
+
+# Needed by other modules that use this api
+from synextreg import ExtensionRegister, GetFileExtensions, RegisterNewLangId
+
+#-----------------------------------------------------------------------------#
+
+class SyntaxMgr(object):
+ """Class Object for managing loaded syntax data. The manager
+ is only created once as a singleton and shared amongst all
+ editor windows
+
+ """
+ instance = None
+ first = True
+ def __init__(self, config=None):
+ """Initialize a syntax manager. If the optional
+ value config is set the mapping of extensions to
+ lexers will be loaded from a config file.
+ @keyword config: path of config file to load file extension config from
+
+ """
+ if SyntaxMgr.first:
+ object.__init__(self)
+ SyntaxMgr.first = False
+ self._extreg = ExtensionRegister()
+ self._config = config
+ self._loaded = dict()
+
+ # Syntax mode extensions
+ self._extensions = dict() # loaded extensions "py" : PythonMode()
+
+ self.InitConfig()
+
+ def __new__(cls, config=None):
+ """Ensure only a single instance is shared amongst
+ all objects.
+ @return: class instance
+
+ """
+ if cls.instance is None:
+ cls.instance = object.__new__(cls)
+ return cls.instance
+
+ def _ExtToMod(self, ext):
+ """Gets the name of the module that is is associated
+ with the given extension or None in the event that there
+ is no association or that the association is plain text.
+ @param ext: extension string to lookup module for
+
+ """
+ ftype = self._extreg.FileTypeFromExt(ext)
+ lexdat = synglob.LANG_MAP.get(ftype)
+ mod = None
+ if lexdat:
+ mod = lexdat[MODULE]
+ return mod
+
+ def GetLangId(self, ext):
+ """Gets the language Id that is associated with the file
+ extension.
+ @param ext: extension to get lang id for
+
+ """
+ ftype = self._extreg.FileTypeFromExt(ext)
+ return synglob.LANG_MAP[ftype][LANG_ID]
+
+ def InitConfig(self):
+ """Initialize the SyntaxMgr's configuration state"""
+ if self._config:
+ self._extreg.LoadFromConfig(self._config)
+ else:
+ self._extreg.LoadDefault()
+
+ if self._config:
+ self.LoadExtensions(self._config)
+
+ def IsModLoaded(self, modname):
+ """Checks if a module has already been loaded
+ @param modname: name of module to lookup
+
+ """
+ if modname in self._loaded:
+ return True
+ else:
+ return False
+
+ def LoadModule(self, modname):
+ """Dynamically loads a module by name. The loading is only
+ done if the modules data set is not already being managed
+ @param modname: name of syntax module to load
+
+ """
+ if modname == None:
+ return False
+ if not self.IsModLoaded(modname):
+ try:
+ self._loaded[modname] = __import__(modname, globals(),
+ locals(), [''])
+ except ImportError, msg:
+ return False
+ return True
+
+ def SaveState(self):
+ """Saves the current configuration state of the manager to
+ disk for use in other sessions.
+ @return: whether save was successful or not
+
+ """
+ if not self._config or not os.path.exists(self._config):
+ return False
+ path = os.path.join(self._config, self._extreg.config)
+ try:
+ file_h = open(path, "wb")
+ file_h.write(str(self._extreg))
+ file_h.close()
+ except IOError:
+ return False
+ return True
+
+ def GetSyntaxData(self, ext):
+ """Fetches the language data based on a file extension string. The file
+ extension is used to look up the default lexer actions from the EXT_REG
+ dictionary.
+ @see: L{synglob}
+ @param ext: a string representing the file extension
+ @return: SyntaxData object
+
+ """
+ # The Return Value
+ lang = self._extreg.FileTypeFromExt(ext)
+ if lang in self._extensions:
+ syn_data = self._extensions[lang]
+ return syn_data
+
+ # Check for extensions that may have been removed
+ if lang not in synglob.LANG_MAP:
+ self._extreg.Remove(lang)
+
+ lex_cfg = synglob.LANG_MAP.get(lang, synglob.LANG_MAP[synglob.LANG_TXT])
+
+ # Check if module is loaded and load if necessary
+ if not self.LoadModule(lex_cfg[MODULE]):
+ # Bail out and return a default plaintext config as
+ # nothing else can be done at this point
+ return syndata.SyntaxDataBase()
+
+ # This little bit of code fetches the keyword/syntax
+ # spec set(s) from the specified module
+ mod = self._loaded[lex_cfg[MODULE]]
+ syn_data = mod.SyntaxData(lex_cfg[LANG_ID])
+ return syn_data
+
+ def LoadExtensions(self, path):
+ """Load all extensions found at the extension path
+ @param path: path to look for extension on
+
+ """
+ for fname in os.listdir(path):
+ if fname.endswith(u".edxml"):
+ fpath = os.path.join(path, fname)
+ modeh = synxml.LoadHandler(fpath)
+
+ if modeh.IsOk():
+ sdata = SynExtensionDelegate(modeh)
+ self._extensions[sdata.GetXmlObject().GetLanguage()] = sdata
+ else:
+ pass
+ #TODO: report error
+
+ def SetConfigDir(self, path):
+ """Set the path to locate config information at. The SyntaxMgr will
+ look for file type associations in a file called synmap and will load
+ syntax extensions from .edxml files found at this path.
+ @param path: string
+
+ """
+ self._config = path
+
+#-----------------------------------------------------------------------------#
+
+class SynExtensionDelegate(syndata.SyntaxDataBase):
+ """Delegate SyntaxData class for SynXml Extension class instances"""
+ def __init__(self, xml_obj):
+ """Initialize the data class
+ @param xml_obj: SynXml
+
+ """
+ langId = _RegisterExtensionHandler(xml_obj)
+ syndata.SyntaxDataBase.__init__(self, langId)
+
+ # Attributes
+ self._xml = xml_obj
+
+ # Setup
+ self.SetLexer(self._xml.GetLexer())
+ #TODO: Load and register features specified by the xml object
+
+ #---- Syntax Data Implementation ----#
+
+ def GetCommentPattern(self):
+ """Get the comment pattern
+ @return: list of strings ['/*', '*/']
+
+ """
+ return self._xml.GetCommentPattern()
+
+ def GetKeywords(self):
+ """Get the Keyword List(s)
+ @return: list of tuples [(1, ['kw1', kw2']),]
+
+ """
+ keywords = self._xml.GetKeywords()
+ rwords = list()
+ for sid, words in keywords:
+ rwords.append((sid, u" ".join(words)))
+ return rwords
+
+ def GetProperties(self):
+ """Get the Properties List
+ @return: list of tuples [('fold', '1'),]
+
+ """
+ return self._xml.GetProperties()
+
+ def GetSyntaxSpec(self):
+ """Get the the syntax specification list
+ @return: list of tuples [(int, 'style_tag'),]
+
+ """
+ return self._xml.GetSyntaxSpec()
+
+ #---- End Syntax Data Implementation ----#
+
+ def GetXmlObject(self):
+ """Get the xml object
+ @return: EditraXml instance
+
+ """
+ return self._xml
+
+#-----------------------------------------------------------------------------#
+
+def GenLexerMenu():
+ """Generates a menu of available syntax configurations
+ @return: wx.Menu
+
+ """
+ lex_menu = wx.Menu()
+ f_types = dict()
+ for key in synglob.LANG_MAP:
+ f_types[key] = synglob.LANG_MAP[key][LANG_ID]
+ f_order = list(f_types)
+ f_order.sort(key=unicode.lower)
+
+ for lang in f_order:
+ lex_menu.Append(f_types[lang], lang,
+ _("Switch Lexer to %s") % lang, wx.ITEM_CHECK)
+ return lex_menu
+
+def GenFileFilters():
+ """Generates a list of file filters
+ @return: list of all file filters based on extension associations
+
+ """
+ extreg = ExtensionRegister()
+ # Convert extension list into a formatted string
+ f_dict = dict()
+ for key, val in extreg.iteritems():
+ val.sort()
+ if key.lower() == 'makefile':
+ continue
+
+ f_dict[key] = u";*." + u";*.".join(val)
+
+ # Build the final list of properly formatted strings
+ filters = list()
+ for key in f_dict:
+ tmp = u" (%s)|%s|" % (f_dict[key][1:], f_dict[key][1:])
+ filters.append(key + tmp)
+ filters.sort(key=unicode.lower)
+ filters.insert(0, u"All Files (*)|*|")
+ filters[-1] = filters[-1][:-1] # IMPORTANT trim last '|' from item in list
+ return filters
+
+def GetLexerList():
+ """Gets the list of all supported file types
+ @return: list of strings
+
+ """
+ f_types = synglob.LANG_MAP.keys()
+ f_types.sort(key=unicode.lower)
+ return f_types
+
+#---- Syntax id set ----#
+SYNTAX_IDS = None
+
+def SyntaxIds():
+ """Gets a list of all Syntax Ids and returns it
+ @return: list of all syntax language ids
+
+ """
+ # Use the cached list if its available
+ if SYNTAX_IDS is not None:
+ return SYNTAX_IDS
+
+ syn_ids = list()
+ for item in dir(synglob):
+ if item.startswith("ID_LANG"):
+ syn_ids.append(getattr(synglob, item))
+
+ return syn_ids
+
+SYNTAX_IDS = SyntaxIds()
+
+def SyntaxNames():
+ """Gets a list of all Syntax Labels
+ @return: list of strings
+
+ """
+ syn_list = list()
+ for item in dir(synglob):
+ if item.startswith("LANG_"):
+ val = getattr(synglob, item)
+ if isinstance(val, basestring):
+ syn_list.append(val)
+ return syn_list
+
+#---- End Syntax ids ----#
+
+def GetExtFromId(ext_id):
+ """Takes a language ID and fetches an appropriate file extension string
+ @param ext_id: language id to get extension for
+ @return: file extension
+
+ """
+ extreg = ExtensionRegister()
+ ftype = synglob.GetDescriptionFromId(ext_id)
+ rval = u''
+ if len(extreg[ftype]):
+ rval = extreg[ftype][0]
+ return rval
+
+def GetIdFromExt(ext):
+ """Get the language id from the given file extension
+ @param ext: file extension (no dot)
+ @return: language identifier id from extension register
+
+ """
+ ftype = ExtensionRegister().FileTypeFromExt(ext)
+ if ftype in synglob.LANG_MAP:
+ return synglob.LANG_MAP[ftype][LANG_ID]
+ else:
+ return synglob.ID_LANG_TXT
+
+def GetTypeFromExt(ext):
+ """Get the filetype description string from the given extension.
+ The return value defaults to synglob.LANG_TXT if nothing is found.
+ @param ext: file extension string (no dot)
+ @return: String
+
+ """
+ return ExtensionRegister().FileTypeFromExt(ext)
+
+def _RegisterExtensionHandler(xml_obj):
+ """Register an ExtensionHandler with this module.
+ @todo: this is a temporary hack till what to do with the language id's
+ is decided.
+
+ """
+ # Create an ID value for the lang id string
+ langId = xml_obj.GetLangId()
+ rid = RegisterNewLangId(langId, xml_obj.GetLanguage())
+ setattr(synglob, langId, rid)
+ setattr(synglob, langId[3:], xml_obj.GetLanguage())
+
+ # Register file extensions with extension register
+ ExtensionRegister().Associate(xml_obj.GetLanguage(),
+ u" ".join(xml_obj.FileExtensions))
+
+ # Update static syntax id list
+ if rid not in SYNTAX_IDS:
+ SYNTAX_IDS.append(rid)
+
+ return rid
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synxml.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synxml.py
new file mode 100644
index 0000000..40fe7b5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synxml.py
@@ -0,0 +1,823 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+# Name: synxml.py #
+# Purpose: Syntax Mode Xml Interface #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+""" Interface for extending language support through the use of xml files
+
+@summary: EditraXml Implementation
+
+"""
+
+xml_spec = """
+<editra version="1">
+ <syntax language="Python" lexer="STC_LEX_PYTHON" id="ID_LANG_PYTHON">
+
+ <associations value="py pyw"/>
+
+ <keywordlist>
+ <keywords value="0">
+ if else elif for while in
+ </keywords>
+ <keywords value="1">
+ str len setattr getattr
+ </keywords>
+ </keywordlist>
+
+ <syntaxspeclist>
+ <syntaxspec value="STC_P_DEFAULT" tag="default_style"/>
+ <syntaxspec value="STC_P_WORD" tag="keyword_style"/>
+ </syntaxspeclist>
+
+ <propertylist>
+ <property value="fold" enable="1"/>
+ <property value="tab.timmy.whinge.level" enable="1"/>
+ </propertylist>
+
+ <commentpattern value="#"/>
+
+ <featurelist>
+ <feature method="AutoIndenter" source="myextension.py"/>
+ <!-- <feature method="StyleText" source="myextension.py"/> -->
+ </featurelist>
+
+ </syntax>
+
+</editra>
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: synxml.py 68814 2011-08-21 17:10:03Z CJP $"
+__revision__ = "$Revision: 68814 $"
+
+#----------------------------------------------------------------------------#
+# Imports
+import os
+from xml import sax
+
+# Workaround for building packages when wx is not available
+try:
+ import wx.stc as stc
+except ImportError:
+ pass
+
+#----------------------------------------------------------------------------#
+# Tag Definitions
+EXML_START = u"editra"
+EXML_SYNTAX = u"syntax"
+EXML_KEYWORDLIST = u"keywordlist"
+EXML_KEYWORDS = u"keywords"
+EXML_SYNSPECLIST = u"syntaxspeclist"
+EXML_SYNTAXSPEC = u"syntaxspec"
+EXML_PROPERTYLIST = u"propertylist"
+EXML_PROPERTY = u"property"
+EXML_COMMENTPAT = u"commentpattern"
+EXML_FEATURELIST = u"featurelist"
+EXML_FEATURE = u"feature"
+EXML_ASSOCIATIONS = u"associations"
+
+# Attributes
+EXML_ENABLE = u"enable"
+EXML_LANG = u"language"
+EXML_LEXER = u"lexer"
+EXML_METHOD = u"method"
+EXML_SOURCE = u"source"
+EXML_TAG = u"tag"
+EXML_VALUE = u"value"
+EXML_VERSION = u"version"
+EXML_NAME = u"name"
+EXML_ID = u"id"
+
+#----------------------------------------------------------------------------#
+
+class EditraXml(sax.ContentHandler):
+ """Base class for all Editra syntax xml objects"""
+ def __init__(self, path=None):
+ sax.ContentHandler.__init__(self)
+
+ # Attributes
+ self.name = u'' # Tag name
+ self.level = 0 # Set the level of the element
+ self.indent = 3 # Indentation
+ self.path = path
+ self._ok = False # Did the object load correctly
+
+ self._context = None # Current parse context
+ self._reg_handler = dict() # Registered parse handlers
+
+ def __eq__(self, other):
+ return self.GetXml() == other.GetXml()
+
+ def __str__(self):
+ return self.GetXml()
+
+ #---- Internal Parser Api ----#
+
+ def startElement(self, name, attrs):
+ if self._context is not None:
+ # Delegate to current context
+ self._context.startElement(name, attrs)
+ elif name in self._reg_handler:
+ self._context = self._reg_handler.get(name)
+ self._context.startElement(name, attrs)
+ else:
+ # Unknown tag
+ # raise?
+ pass
+
+ def endElement(self, name):
+ if self._context is not None:
+ if self._context.Name == name:
+ self._context = None
+ else:
+ # Delegate to registered handler
+ self._context.endElement(name)
+ else:
+ # Unknown tag ending
+ pass
+
+ def characters(self, chars):
+ if not chars.isspace():
+ if self._context is not None:
+ self._context.characters(chars)
+ else:
+ # No current context or context is self
+ pass
+
+ def GetXml(self):
+ """Get the xml representation of this object
+ @return: string
+
+ """
+ ident = self.GetIndentationStr()
+ xml = ident + self.GetStartTag()
+ xml += (self.GetSubElements() + os.linesep)
+ xml += (ident + self.GetEndTag())
+ return xml
+
+ def GetSubElements(self):
+ """Get the sub elements
+ @return: string
+
+ """
+ xml = u''
+ for handler in self.GetHandlers():
+ handler.SetLevel(self.Level + 1)
+ xml += (os.linesep + handler.GetXml())
+ return xml
+
+ def GetStartTag(self):
+ """Get the opening tag
+ @return: string
+
+ """
+ return u"<%s>" % self.name
+
+ def GetEndTag(self):
+ """Get the closing tag
+ @return: string
+
+ """
+ return u"</%s>" % self.name
+
+ def LoadFromDisk(self):
+ """Load the object from from disk
+ @precondition: path has been set
+ @return: bool
+ @todo: set error state on failed loads
+
+ """
+ assert self.path is not None, "Must SetPath before calling Load"
+ try:
+ sax.parse(self.path, self)
+ except (sax.SAXException, OSError, IOError, UnicodeDecodeError):
+ self._ok = False
+ return False
+ else:
+ self._ok = True
+ return True
+
+ def LoadFromString(self, txt):
+ """Load and initialize the object from an xml string
+ @param txt: string
+
+ """
+ sax.parseString(txt, self)
+
+ #---- External Api ----#
+
+ @property
+ def Context(self):
+ return self._context
+
+ @property
+ def Indentation(self):
+ return self.indent
+
+ @property
+ def Level(self):
+ return self.level
+
+ @property
+ def Name(self):
+ return self.name
+
+ @property
+ def Ok(self):
+ return self.IsOk()
+
+ def GetHandler(self, tag):
+ """Get the handler associated with the given tag
+ @param tag: string
+ @return: EditraXml object or None
+
+ """
+ return self._reg_handler.get(tag, None)
+
+ def GetHandlers(self):
+ """Get all the handlers registered with this element
+ @return: list of EditraXml objects
+
+ """
+ return self._reg_handler.values()
+
+ def GetIndentation(self):
+ """Get the indentation string
+ @return: int
+
+ """
+ return self.indent
+
+ def GetIndentationStr(self):
+ """Get the indentation string taking level into consideration
+ @return: string
+
+ """
+ return (self.indent * u" ") * self.level
+
+ def GetLevel(self):
+ """Get the level of this element
+ @return: int
+
+ """
+ return self.level
+
+ def GetName(self):
+ """Get the tag name for the handler
+ @return: string
+
+ """
+ return self.name
+
+ def GetPath(self):
+ """Get the xml files path
+ @return: string
+
+ """
+ return self.path
+
+ def IsOk(self):
+ """Did the object load from file correctly?
+ return: bool
+
+ """
+ return self._ok
+
+ def RegisterHandler(self, handler):
+ """Register a handler for a tag. Parsing will be delegated to the
+ the registered handler until its end tag is encountered.
+ @param handler: EditraXml instance
+
+ """
+ tag = handler.GetName()
+ assert tag not in self._reg_handler, "%s already registered!" % tag
+ handler.SetLevel(self.Level + 1)
+ self._reg_handler[tag] = handler
+
+ def SetIndentation(self, indent):
+ """Set the indentation level
+ @param indent: int
+
+ """
+ self.indent = indent
+
+ def SetLevel(self, level):
+ """Set the level of this element
+ @param level: int
+
+ """
+ self.level = level
+
+ def SetName(self, tag):
+ """Set this handlers tag name used for identifying the open and
+ end tags.
+ @param tag: string
+
+ """
+ self.name = tag
+
+ def SetPath(self, path):
+ """Set the path to load this element from
+ @param path: path
+
+ """
+ self.path = path
+
+#----------------------------------------------------------------------------#
+
+class SyntaxModeHandler(EditraXml):
+ """Main Xml interface to extending filetype handling support"""
+ def __init__(self, path=None):
+ EditraXml.__init__(self, path)
+
+ # Attributes
+ self._start = False
+ self._version = 0
+ self.syntax = Syntax()
+
+ # Setup
+ self.SetName(EXML_START)
+ self.SetIndentation(3)
+ self.RegisterHandler(self.syntax)
+
+ def startElement(self, name, attrs):
+ if self._start:
+ EditraXml.startElement(self, name, attrs)
+ elif name == EXML_START:
+ self._version = int(attrs.get(EXML_VERSION, 0))
+ self._start = True
+
+ def endElement(self, name):
+ if name == EXML_START:
+ self._start = False
+ else:
+ EditraXml.endElement(self, name)
+
+ def GetStartTag(self):
+ return u"<%s version=\"%s\">" % (self.GetName(), self.Version)
+
+ #---- Get External Api ----#
+
+ # Properties
+ @property
+ def CommentPattern(self):
+ return self.GetCommentPattern()
+
+ @property
+ def FileExtensions(self):
+ return self.GetFileExtensions()
+
+ @property
+ def Keywords(self):
+ return self.GetKeywords()
+
+ @property
+ def LangId(self):
+ return self.GetLangId()
+
+ @property
+ def Lexer(self):
+ return self.GetLexer()
+
+ @property
+ def Properties(self):
+ return self.GetProperties()
+
+ @property
+ def SyntaxSpec(self):
+ return self.GetSyntaxSpec()
+
+ @property
+ def Version(self):
+ return self._version
+
+ # Getters
+ def GetCommentPattern(self):
+ """Get the comment pattern list
+ @return: list of strings
+
+ """
+ return self.syntax.GetCommentPattern()
+
+ def GetFileExtensions(self):
+ """Get the list of associated file extensions
+ @return: list of strings
+
+ """
+ return self.syntax.GetFileExtensions()
+
+ def GetKeywords(self):
+ """Get the keyword list
+ @return: list of tuples [(idx, ['word', 'word2',]),]
+
+ """
+ kwxml = self.syntax.GetKeywordXml()
+ return kwxml.GetKeywords()
+
+ def GetFeatureFromXml(self, fet):
+ """Get the callable associated with the given feature
+ @param fet: string
+ @return: string
+
+ """
+ fetxml = self.syntax.GetFeatureXml()
+ return fetxml.GetFeature(fet)
+
+ def GetSyntaxSpec(self):
+ """Get the syntax spec
+ @return: list of tuples [(style_id, "style_tag")]
+
+ """
+ spxml = self.syntax.GetSyntaxSpecXml()
+ return spxml.GetStyleSpecs()
+
+ def GetLangId(self):
+ """Get the language id string
+ @return: str "ID_LANG_"
+
+ """
+ return self.syntax.GetLangId()
+
+ def GetLanguage(self):
+ """Get the language name string
+ @return: string
+
+ """
+ return self.syntax.GetLanguage()
+
+ def GetLexer(self):
+ """Get the lexer id
+ @return: wx.stc.STC_LEX_
+
+ """
+ return self.syntax.GetLexer()
+
+ def GetProperties(self):
+ """Get the property defs
+ @return: list of tuples [("fold", "1"),]
+
+ """
+ propxml = self.syntax.GetPropertiesXml()
+ return propxml.GetProperties()
+
+#----------------------------------------------------------------------------#
+
+class Syntax(EditraXml):
+ """Syntax definition for initializing a Scintilla Lexer"""
+ def __init__(self):
+ EditraXml.__init__(self)
+
+ # Attributes
+ self.language = u"Plain Text"
+ self.langid = u"ID_LANG_TXT"
+ self.lexstr = u"STC_LEX_NULL"
+ self.lexer = stc.STC_LEX_NULL
+ self.file_ext = list()
+
+ # Sub Xml Objects
+ self.keywords = KeywordList()
+ self.synspec = SyntaxSpecList()
+ self.props = PropertyList()
+ self.features = FeatureList()
+ self.comment = list()
+
+ # Setup
+ self.SetName(EXML_SYNTAX)
+ self.RegisterHandler(self.keywords)
+ self.RegisterHandler(self.synspec)
+ self.RegisterHandler(self.props)
+ self.RegisterHandler(self.features)
+
+ def startElement(self, name, attrs):
+ """Parse the Syntax Xml"""
+ if name == EXML_COMMENTPAT:
+ val = attrs.get(EXML_VALUE, '')
+ tmp = val.split()
+ # Trailing space may be significant for some comments
+ if len(tmp) == 1:
+ comment = [val,]
+ else:
+ comment = tmp
+ self.comment = comment
+ elif name == EXML_ASSOCIATIONS:
+ self.file_ext = attrs.get(EXML_VALUE, '').split()
+ elif name == self.Name:
+ lang = attrs.get(EXML_LANG, u"Plain Text")
+ langid = attrs.get(EXML_ID, u"ID_LANG_TXT")
+ assert langid.startswith(u"ID_LANG_"), "id must start with ID_LANG_"
+ lexer = attrs.get(EXML_LEXER, 'STC_LEX_NULL')
+ lexval = getattr(stc, lexer, None)
+ assert lexval is not None, "Invalid Lexer: %s" % lexer
+ self.language = lang
+ self.langid = langid
+ self.lexstr = lexer
+ self.lexer = lexval
+ else:
+ EditraXml.startElement(self, name, attrs)
+
+ def GetStartTag(self):
+ """Get the syntax opening tag and attributes"""
+ return u"<%s %s=\"%s\" %s=\"%s\" %s=\"%s\">" % (self.Name, EXML_LANG,
+ self.language, EXML_LEXER,
+ self.lexstr, EXML_ID,
+ self.langid)
+
+ def GetSubElements(self):
+ """Get the SubElements xml string
+ @return: string
+
+ """
+ xml = EditraXml.GetSubElements(self)
+ ident = self.GetIndentationStr() + (self.Indentation * u" ")
+ xml += os.linesep
+ cpat = u" ".join(self.GetCommentPattern())
+ comment = u"<%s %s=\"%s\"/>" % (EXML_COMMENTPAT, EXML_VALUE, cpat.strip())
+ xml += os.linesep
+ xml += (ident + comment)
+ xml += os.linesep
+ fileext = u"<%s %s=\"%s\"/>" % (EXML_ASSOCIATIONS, EXML_VALUE, u" ".join(self.file_ext))
+ xml += (ident + fileext)
+ return xml
+
+ #---- External Api ----#
+
+ def GetCommentPattern(self):
+ """Get the comment pattern
+ @return: list of strings ["/*", "*/"]
+
+ """
+ return self.comment
+
+ def GetFeatureXml(self):
+ """Get the FeatureList xml object"""
+ return self.features
+
+ def GetFileExtensions(self):
+ """Get the list of associated file extensions"""
+ return self.file_ext
+
+ def GetKeywordXml(self):
+ """Get the Keyword Xml object"""
+ return self.keywords
+
+ def GetLanguage(self):
+ """Get the language description/name
+ @return: string
+
+ """
+ return self.language
+
+ def GetLangId(self):
+ """Get the language id
+ @return: string
+
+ """
+ return self.langid
+
+ def GetLexer(self):
+ """Get the lexer to use for this language
+ @return: stc.STC_LEX_FOO
+
+ """
+ return self.lexer
+
+ def GetSyntaxSpecXml(self):
+ """Get the Syntax Spec Xml object"""
+ return self.synspec
+
+ def GetPropertiesXml(self):
+ """Get the properties xml object"""
+ return self.props
+
+#----------------------------------------------------------------------------#
+
+class KeywordList(EditraXml):
+ """Container object for all keyword sets"""
+ def __init__(self):
+ EditraXml.__init__(self)
+
+ # Attributes
+ self._current = None
+ self._keywords = dict() # { index : word_list }
+
+ # Setup
+ self.SetName(EXML_KEYWORDLIST)
+
+ def startElement(self, name, attrs):
+ if name == EXML_KEYWORDS:
+ idx = attrs.get(EXML_VALUE, None)
+ assert idx is not None, "value attribute not set"
+ idx = int(idx)
+ assert idx not in self._keywords, "Duplicate index set %d" % idx
+ self._keywords[idx] = list()
+ self._current = self._keywords[idx]
+ else:
+ pass
+
+ def endElement(self, name):
+ if name == EXML_KEYWORDS:
+ self._current = None
+
+ def characters(self, chars):
+ chars = chars.strip().split()
+ if self._current is not None:
+ if len(chars):
+ self._current.extend(chars)
+
+ def GetSubElements(self):
+ """Get the keyword list elements"""
+ xml = u""
+ tag = u"<%s %s=" % (EXML_KEYWORDS, EXML_VALUE)
+ tag += "\"%s\">"
+ end = u"</%s>" % EXML_KEYWORDS
+ ident = self.GetIndentationStr() + (self.Indentation * u" ")
+ for key in sorted(self._keywords.keys()):
+ xml += os.linesep + ident
+ xml += (tag % key)
+ xml += os.linesep + ident
+ words = (self.Indentation * u" ") + u" ".join(self._keywords[key])
+ xml += words
+ xml += os.linesep + ident
+ xml += end
+ return xml
+
+ #---- External Api ----#
+
+ def GetKeywords(self):
+ """Get the list of keyword strings
+ @return: sorted list of tuples [(kw_idx, [word1, word2,])]
+
+ """
+ keys = sorted(self._keywords.keys())
+ keywords = [ (idx, self._keywords[idx]) for idx in keys ]
+ keywords.sort(key=lambda x: x[0])
+ return keywords
+
+ def GetKeywordList(self, idx):
+ """Get the list of keywords associated with the given index
+ @return: list of strings
+
+ """
+ return self._keywords.get(idx, None)
+
+#----------------------------------------------------------------------------#
+
+class SyntaxSpecList(EditraXml):
+ """Container element for holding the syntax specification elements"""
+ def __init__(self):
+ EditraXml.__init__(self)
+
+ # Attributes
+ self._specs = list()
+
+ # Setup
+ self.SetName(EXML_SYNSPECLIST)
+
+ def startElement(self, name, attrs):
+ """Parse all syntaxspec elements in the list"""
+ if name == EXML_SYNTAXSPEC:
+ lid = attrs.get(EXML_VALUE, '')
+ assert len(lid), "Style Id not specified"
+ if lid.isdigit():
+ style_id = int(lid)
+ else:
+ # Scintilla Value
+ style_id = getattr(stc, lid, None)
+ assert style_id is not None, "Invalid STC Value: %s" % lid
+ assert isinstance(style_id, int), "Invalid ID: %s" % lid
+
+ self._specs.append((style_id, attrs.get(EXML_TAG, 'default_style')))
+ else:
+ # Unknown Tag
+ # Raise?
+ pass
+
+ def GetSubElements(self):
+ """Get the xml for all the syntax spec elements"""
+ xml = u""
+ tag = u"<%s %s=" % (EXML_SYNTAXSPEC, EXML_VALUE)
+ tag += ("\"%s\" " + EXML_TAG + "=\"%s\"/>")
+ ident = self.GetIndentationStr() + (self.Indentation * u" ")
+ for spec in self._specs:
+ xml += os.linesep + ident
+ xml += (tag % spec)
+ return xml
+
+ #---- External Api ----#
+
+ def GetStyleSpecs(self):
+ """Get the list of keyword strings
+ @return: list of tuples [(style_id, "style_tag"),]
+
+ """
+ return self._specs
+
+#----------------------------------------------------------------------------#
+
+class PropertyList(EditraXml):
+ """Container class for the syntax properties"""
+ def __init__(self):
+ EditraXml.__init__(self)
+
+ # Attributes
+ self.properties = list()
+
+ # Setup
+ self.SetName(EXML_PROPERTYLIST)
+
+ def startElement(self, name, attrs):
+ if name == EXML_PROPERTY:
+ prop = attrs.get(EXML_VALUE, '')
+ if prop:
+ enable = attrs.get(EXML_ENABLE, '0')
+ self.properties.append((prop, enable))
+ else:
+ pass
+
+ def GetSubElements(self):
+ xml = u""
+ tag = u"<%s %s=" % (EXML_PROPERTY, EXML_VALUE)
+ tag += ("\"%s\" " + EXML_ENABLE + "=\"%s\"/>")
+ ident = self.GetIndentationStr() + (self.Indentation * u" ")
+ for prop in self.properties:
+ xml += os.linesep + ident
+ xml += (tag % prop)
+ return xml
+
+ #---- External Api ----#
+
+ def GetProperties(self):
+ """Get the list of properties
+ @return: list of tuples [("property", "1")]
+
+ """
+ return self.properties
+
+#----------------------------------------------------------------------------#
+
+class FeatureList(EditraXml):
+ """Container for all other misc syntax features.
+ Currently Available Features:
+ - AutoIndent
+ - StyleText
+
+ """
+ def __init__(self):
+ EditraXml.__init__(self)
+
+ # Attributes
+ self._features = dict()
+
+ # Setup
+ self.SetName(EXML_FEATURELIST)
+
+ def startElement(self, name, attrs):
+ if name == EXML_FEATURE:
+ meth = attrs.get(EXML_METHOD, None)
+ assert meth is not None, "method not defined"
+ mod = attrs.get(EXML_SOURCE, None)
+ assert mod is not None, "source not defined"
+
+ self._features[meth] = mod
+ else:
+ EditraXml.startElement(self, name, attrs)
+
+ def GetSubElements(self):
+ xml = u""
+ tag = u"<%s %s=" % (EXML_FEATURE, EXML_METHOD)
+ tag += ("\"%s\" " + EXML_SOURCE + "=\"%s\"/>")
+ ident = self.GetIndentationStr() + (self.Indentation * u" ")
+ for feature in self._features.iteritems():
+ xml += (os.linesep + ident)
+ xml += (tag % feature)
+ return xml
+
+ #---- External Api ----#
+
+ def GetFeature(self, fet):
+ """Get the callable feature by name
+ @param fet: string (module name)
+
+ """
+ feature = None
+ src = self._features.get(fet, None)
+ if src is not None:
+ feature = src
+ return feature
+
+#----------------------------------------------------------------------------#
+
+def LoadHandler(path):
+ """Load and initialize a SyntaxModeHandler from an on disk xml config file
+ @param path: path to an EditraXml file to load a handler from
+ @return: SyntaxModeHandler instance
+
+ """
+ synmode = SyntaxModeHandler(path)
+ synmode.LoadFromDisk()
+ return synmode
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/updater.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/updater.py
new file mode 100644
index 0000000..f33520d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/updater.py
@@ -0,0 +1,718 @@
+###############################################################################
+# Name: updater.py #
+# Purpose: UI and services for checking update status and downloading updates #
+# for Editra. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+Provides controls/services that are used in checking and downloading updates
+for the editor if they are available. The main control exported by this module
+is the L{UpdateProgress} bar it displays the progress of the network action and
+provides a higher level interface into the L{UpdateService}.
+
+@summary: Utilities and controls for updating Editra
+@todo: This module could benefit from a bit of a re-write...
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: updater.py 66703 2011-01-17 23:07:45Z CJP $"
+__revision__ = "$Revision: 66703 $"
+
+#--------------------------------------------------------------------------#
+# Dependencies
+import os
+import sys
+import stat
+import re
+import urllib2
+import threading
+import wx
+import wx.lib.delayedresult as delayedresult
+
+# Editra Libraries
+import ed_glob
+import ed_event
+from profiler import CalcVersionValue, Profile_Get
+import util
+import ebmlib
+
+#--------------------------------------------------------------------------#
+# Globals
+RE_VERSION = re.compile('<\s*span id\="VERSION"[^>]*>(.*?)<\s*/span\s*>')
+RE_CURL = re.compile('<\s*a id\="CURRENT"\s*href=\"(.*?)\"[^>]*>.*?<\s*/a\s*>')
+DL_VERSION = ed_glob.HOME_PAGE + "/version.php"
+DL_REQUEST = ed_glob.HOME_PAGE + "/e_update.php?dist=%s"
+DL_LIN = 'SRC' # This may need to change in future
+DL_MAC = 'Macintosh'
+DL_SRC = 'SRC'
+DL_WIN = 'Windows'
+ISBIN = hasattr(sys, 'frozen')
+
+_ = wx.GetTranslation
+#--------------------------------------------------------------------------#
+
+class UpdateService(object):
+ """Defines an updater service object for Editra"""
+ def __init__(self):
+ """Initializes the Updater Object"""
+ super(UpdateService, self).__init__()
+ self._abort = False
+ self._progress = (0, 100)
+
+ def __GetUrlHandle(self, url):
+ """Gets a file handle for the given url. The caller is responsible for
+ closing the handle.
+ @requires: network connection
+ @param url: url to get page from
+ @return: all text from the given url
+
+ """
+ h_file = None
+ try:
+ if Profile_Get('USE_PROXY', default=False):
+ proxy_set = Profile_Get('PROXY_SETTINGS',
+ default=dict(uname='', url='',
+ port='80', passwd=''))
+
+ proxy = util.GetProxyOpener(proxy_set)
+ h_file = proxy.open(url)
+ else:
+ h_file = urllib2.urlopen(url)
+
+ finally:
+ return h_file
+
+ def Abort(self):
+ """Cancel any pending or in progress actions.
+ @postcondition: any download actions will be aborted
+
+ """
+ self._abort = True
+
+ def GetCurrFileURL(self):
+ """Returns the url for the current version of the program
+ for the current operating system, by requesting the data from
+ project homepage.
+ @requires: active network connection
+ @return: url of latest available program version
+
+ """
+ if wx.Platform == '__WXGTK__':
+ dist = DL_LIN
+ elif wx.Platform == '__WXMAC__' and ISBIN:
+ dist = DL_MAC
+ elif wx.Platform == '__WXMSW__' and ISBIN:
+ dist = DL_WIN
+ else:
+ dist = DL_SRC
+
+ url = self.GetPageText(DL_REQUEST % dist)
+ url = re.findall(RE_CURL, url)
+ if len(url):
+ url = url[0]
+ else:
+ url = wx.EmptyString
+
+ return url.strip()
+
+ def GetCurrFileName(self):
+ """Returns the name of the file that is currently available for
+ download as a string.
+ @return: name of currently available file without url
+
+ """
+ url = self.GetCurrFileURL()
+ return url.split(u'/')[-1]
+
+ def GetCurrentVersionStr(self):
+ """Parses the project website front page for the most
+ recent version of the program.
+ @requires: network connection
+ @return: version number of latest available program
+
+ """
+ page = self.GetPageText(ed_glob.HOME_PAGE + "/version.php?check=True")
+ found = re.findall(RE_VERSION, page)
+ if len(found):
+ return found[0] # Should be the first/only match found
+ else:
+ util.Log("[updater][warn] UpdateService.GetCurrentVersionStr "
+ "Failed to get version info.")
+ # TODO: GetTranslation is not threadsafe!!!
+ return "Unable to retrieve version info"
+
+ def GetFileSize(self, url):
+ """Gets the size of a file by address
+ @param url: url to look up file on
+ @return: size of the file in bytes
+
+ """
+ size = 0
+ try:
+ dl_file = self.__GetUrlHandle(url)
+ info = dl_file.info()
+ size = int(info['Content-Length'])
+ dl_file.close()
+ finally:
+ return size
+
+ def GetPageText(self, url):
+ """Gets the text of a url
+ @requires: network conection
+ @param url: url to get page from
+ @return: all text from the given url
+
+ """
+ text = u''
+ try:
+ h_file = self.__GetUrlHandle(url)
+ text = h_file.read()
+ h_file.close()
+ finally:
+ return text
+
+ def GetProgress(self):
+ """Returns the current progress/total tuple
+ @return: tuple of progress data
+
+ """
+ return self._progress
+
+ def GetUpdateFiles(self, dl_to=wx.GetHomeDir()):
+ """Gets the requested version of the program from the website
+ if possible. It will download the current files for the host system to
+ location (dl_to). On success it returns True, otherwise it returns
+ false.
+ @keyword dl_to: where to download the file to
+
+ """
+ # Check version to see if update is needed
+ # Dont allow update if files are current
+ verpat = re.compile('[0-9]+\.[0-9]+\.[0-9]+')
+ current = self.GetCurrentVersionStr()
+ if not re.match(verpat, current):
+ return False
+
+ if CalcVersionValue(ed_glob.VERSION) < CalcVersionValue(current):
+ dl_path = self.GetCurrFileURL()
+ dl_file = dl_path.split('/')[-1]
+ dl_to = ebmlib.GetUniqueName(dl_to, dl_file)
+ blk_sz = 4096
+ read = 0
+ try:
+ # Download the file in chunks so it can be aborted if need be
+ # inbetween reads.
+ webfile = self.__GetUrlHandle(dl_path)
+ fsize = int(webfile.info()['Content-Length'])
+ locfile = open(dl_to, 'wb')
+ while read < fsize and not self._abort:
+ locfile.write(webfile.read(blk_sz))
+ read += blk_sz
+ self.UpdaterHook(int(read/blk_sz), blk_sz, fsize)
+
+ locfile.close()
+ webfile.close()
+ finally:
+ self._abort = False
+ if os.path.exists(dl_to) and \
+ os.stat(dl_to)[stat.ST_SIZE] == fsize:
+ return True
+ else:
+ return False
+ else:
+ return False
+
+ def UpdaterHook(self, count, block_sz, total_sz):
+ """Updates the progress tuple of (amount_done, total) on
+ each iterative call during the download.
+ @param count: number of blocks fetched
+ @param block_sz: size of download blocks
+ @param total_sz: total size of file to be downloaded
+
+ """
+ done = count * block_sz
+ if done > total_sz:
+ done = total_sz
+ self._progress = (done, total_sz)
+
+#-----------------------------------------------------------------------------#
+
+class UpdateThread(threading.Thread):
+ """Thread for checking for updates"""
+ def __init__(self, parent, jobId):
+ """Create the thread object
+ @param parent: parent window to post event to after completion
+ @param jobId: job identification id will be set as event id on finish
+
+ """
+ super(UpdateThread, self).__init__()
+
+ # Attributes
+ self.parent = parent
+ self.id = jobId
+
+ def run(self):
+ """Run the update check job"""
+ service = UpdateService()
+ result = service.GetCurrentVersionStr()
+ if result.replace('.', '').isdigit():
+ isupdate = CalcVersionValue(result) > CalcVersionValue(ed_glob.VERSION)
+ else:
+ isupdate = False
+
+ evt = ed_event.NotificationEvent(ed_event.edEVT_NOTIFY,
+ self.id, (isupdate, result))
+ wx.PostEvent(self.parent, evt)
+
+#-----------------------------------------------------------------------------#
+
+class UpdateProgress(wx.Gauge, UpdateService):
+ """Creates a progress bar that is controlled by the UpdateService"""
+ ID_CHECKING = wx.NewId()
+ ID_DOWNLOADING = wx.NewId()
+ ID_TIMER = wx.NewId()
+
+ def __init__(self, parent, id_, range_=100,
+ style=wx.GA_HORIZONTAL | wx.GA_PROGRESSBAR):
+ """Initiliazes the bar in a disabled state."""
+ wx.Gauge.__init__(self, parent, id_, range_, style=style)
+ UpdateService.__init__(self)
+
+ #---- Attributes ----#
+ self.LOG = wx.GetApp().GetLog()
+ self._checking = False
+ self._downloading = False
+ self._dl_result = False
+ self._mode = 0
+ self._status = _("Status Unknown")
+ self._timer = wx.Timer(self, id=self.ID_TIMER)
+
+ #---- Layout ----#
+ if wx.Platform == '__WXMAC__':
+ self.SetWindowVariant(wx.WINDOW_VARIANT_LARGE)
+
+ #---- Bind Events ----#
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+ self.Bind(wx.EVT_TIMER, self.OnUpdate, id = self.ID_TIMER)
+
+ # Disable bar till caller is ready to use it
+ self.Disable()
+
+ def OnDestroy(self, evt):
+ """Cleans up when the control is destroyed
+ @postcondition: if timer is running it is stopped before deletion
+
+ """
+ if evt.GetId() == self.GetId():
+ if self._timer.IsRunning():
+ self.LOG("[updater][info]UpdateProgress: __del__, stopped timer")
+ self._timer.Stop()
+ evt.Skip()
+
+ def Abort(self):
+ """Overides the UpdateService abort function
+ @postcondition: any download actions in the L{UpdateService} are aborted
+
+ """
+ self.LOG("[updater][info] UpdateProgress: Download aborted")
+ UpdateService.Abort(self)
+ if self._timer.IsRunning():
+ self._timer.Stop()
+ self.SetValue(0)
+
+ def CheckForUpdates(self):
+ """Checks for updates and activates the bar. In order to keep the
+ UI from freezing while checking for updates the actual work is carried
+ out on another thread. When the thread exits it will set the _checking
+ attribute to false and set the _status attribute (See GetStatus) to the
+ return value of the check function which is either a version string or
+ an appropriate error message.
+
+ @see: L{_UpdatesCheckThread}
+
+ """
+ # Set bar to Checking mode so it knows to simulate update progress
+ self._mode = self.ID_CHECKING
+ self.SetValue(0)
+ self.Start(10)
+ self._checking = True
+ delayedresult.startWorker(self._ResultNotifier,
+ self._UpdatesCheckThread,
+ jobID=self.ID_CHECKING)
+
+ def DownloadUpdates(self, dl_loc=wx.EmptyString):
+ """Downloads available updates and configures the bar.
+ Returns True if the update was successfull or False if
+ it was not. The updates will be downloaded to the
+ specified location or to the Users Desktop or Home
+ Folder if no location is specified.
+ @keyword dl_loc: location to download file to
+
+ """
+ self.LOG("[updater][info] UpdateProgress: Download Starting...")
+ if dl_loc == wx.EmptyString:
+ dl_loc = self.GetDownloadLocation()
+ self._mode = self.ID_DOWNLOADING
+ self.SetValue(0)
+ self.Start(50) #XXX Try this for starters
+ self._downloading = True # Mark the work status as busy
+ delayedresult.startWorker(self._ResultNotifier, self._DownloadThread,
+ wargs=dl_loc, jobID=self.ID_DOWNLOADING)
+
+ def GetDownloadResult(self):
+ """Returns the status of the last download action. Either
+ True for success or False for failure.
+ @return: whether last download was successfull or not
+
+ """
+ return self._dl_result
+
+ def GetDownloadLocation(self):
+ """Returns the path that the file will be downloaded to.
+ Currently will either return the users Desktop path or the
+ users home directory in the case that there is no deskop directory
+ @return: path to download file
+
+ """
+ dl_loc = wx.GetHomeDir() + os.sep
+ if os.path.exists(dl_loc + u"Desktop"):
+ dl_loc = dl_loc + u"Desktop" + os.sep
+ return dl_loc
+
+ def GetMode(self):
+ """Returns the current mode of operation or 0 if the bar
+ is currently inactive.
+ @return: mode of operation for the progres bar
+
+ """
+ return self._mode
+
+ def GetStatus(self):
+ """Returns the status attribute string
+ @return: status set by any update actions
+
+ """
+ return self._status
+
+ def GetUpdatesAvailable(self):
+ """Compares the status against the version of the running
+ program to see if updates are available. It is expected
+ that CheckForUpdates has been called prior to calling this
+ function. Returns True if Available and False otherwise.
+ @return: whether udpates are available or not
+
+ """
+ if self._status[0].isdigit():
+ return CalcVersionValue(self._status) > CalcVersionValue(ed_glob.VERSION)
+ else:
+ return False
+
+ def IsDownloading(self):
+ """Returns a bool stating whether there is a download
+ in progress or not.
+ @return: whether downloading is active or not
+
+ """
+ return self._downloading
+
+ def OnUpdate(self, evt):
+ """Timer Event Handler Updates the progress bar
+ on each cycle of the timer
+ @param evt: event that called this handler
+
+ """
+ mode = self.GetMode()
+ if mode not in (self.ID_CHECKING, self.ID_DOWNLOADING):
+ return
+
+ progress = self.GetProgress()
+ prange = self.GetRange()
+ if mode == self.ID_CHECKING:
+ # Simulate updates
+ if progress[0] < prange:
+ self.UpdaterHook(progress[0] + 1, 1, 90)
+ progress = self.GetProgress()
+ if not self._checking and progress[0] >= prange:
+ self.Stop()
+
+ if mode == self.ID_DOWNLOADING:
+ if not self._downloading and progress[0] >= prange:
+ self.Stop()
+
+ # Update Range if need be
+ if prange != progress[1]:
+ self.SetRange(progress[1])
+
+ # Update Progress
+ if progress[0] < progress[1]:
+ self.SetValue(progress[0])
+ elif progress[0] == progress[1]:
+ self.Pulse()
+ else:
+ pass
+
+ def Start(self, msec=100):
+ """Starts the progress bar and timer if not already active
+ @keyword msec: pulse time for clock in milliseconds
+
+ """
+ if not self._timer.IsRunning():
+ self.LOG('[updater][info] UpdateProgress: Starting Timer')
+ self.Enable()
+ self.SetValue(0)
+ self._timer.Start(msec)
+ else:
+ pass
+
+ def Stop(self):
+ """Stops the progress bar
+ @postcondition: progress bar is stopped
+
+ """
+ if self._timer.IsRunning():
+ self.LOG('[updater][info] UpdateProgress: Stopping Clock')
+ self._timer.Stop()
+ self._mode = 0
+ self.SetValue(self.GetRange())
+ else:
+ pass
+ self.Enable(False)
+
+ def Pulse(self):
+ if self._mode == 0:
+ return
+ super(UpdateProgress, self).Pulse()
+
+ #--- Protected Member Functions ---#
+ def _DownloadThread(self, *args):
+ """Processes the download and checks that the file has been downloaded
+ properly. Then returns either True if the download was successful or
+ False if it failed in some way.
+ @return: success status of download
+
+ """
+ dl_ok = self.GetUpdateFiles(u"".join(args))
+ return dl_ok
+
+ def _ResultNotifier(self, delayedResult):
+ """Receives the return from the result of the worker thread and
+ notifies the interested party with the result.
+ @param delayedResult: value from worker thread
+
+ """
+ jid = delayedResult.getJobID()
+ try:
+ self.LOG("[updater][info] UpdateProgress: Worker thread exited. ID = %d" % jid)
+ self._checking = self._downloading = False # Work has finished
+ except wx.PyDeadObjectError:
+ return
+
+ try:
+ if jid == self.ID_CHECKING:
+ mevt = ed_event.UpdateTextEvent(ed_event.edEVT_UPDATE_TEXT, \
+ self.ID_CHECKING)
+ wx.PostEvent(self.GetParent(), mevt)
+ self.SetValue(self.GetRange())
+ elif jid == self.ID_DOWNLOADING:
+ result = delayedResult.get()
+ self._dl_result = result
+ else:
+ pass
+ except (OSError, IOError, UnicodeDecodeError), msg:
+ self.LOG("[updater][err] UpdateProgress: Error on thread exit")
+ self.LOG("[updater][err] UpdateProgress: error = %s" % str(msg))
+
+ def _UpdatesCheckThread(self):
+ """Sets internal status value to the return value from calling
+ GetCurrentVersionStr. This function is called on a separate thread
+ in the CheckForUpdates function to allow the ui to update properly
+ while this function waits for the result from the network. Returns
+ True to the consumer if updates are available and false if they
+ are not or status is unknown.
+ @return: whether updates are available or not
+
+ """
+ self.LOG("[updater][info] UpdateProgress: Checking for updates")
+ self._checking = True
+ ret = self.GetCurrentVersionStr()
+ self._status = ret
+ self.LOG("[updater][info] UpdateProgress: Check Finished: result = " + ret)
+ if ret[0].isdigit() and \
+ CalcVersionValue(ret) > CalcVersionValue(ed_glob.VERSION):
+ ret = True
+ else:
+ ret = False
+ return ret
+
+#-----------------------------------------------------------------------------#
+
+class DownloadDialog(wx.Frame):
+ """Creates a standalone download window
+ @todo: Status bar is sometimes not wide enough to display all data.
+ """
+ ID_PROGRESS_BAR = wx.NewId()
+ ID_TIMER = wx.NewId()
+ SB_DOWNLOADED = 0
+ SB_INFO = 1
+
+ def __init__(self, parent, id_, title,
+ style=wx.DEFAULT_DIALOG_STYLE | wx.MINIMIZE_BOX):
+ """Creates a standalone window that is used for downloading
+ updates for the editor.
+ @param parent: Parent Window of the dialog
+ @param title: Title of dialog
+
+ """
+ super(DownloadDialog, self).__init__(parent, id_, title, style=style)
+ util.SetWindowIcon(self)
+
+ #---- Attributes/Objects ----#
+ self.LOG = wx.GetApp().GetLog()
+ panel = wx.Panel(self)
+ self._progress = UpdateProgress(panel, self.ID_PROGRESS_BAR)
+ fname = self._progress.GetCurrFileName()
+ floc = self._progress.GetDownloadLocation()
+ dl_file = wx.StaticText(panel, label=_("Downloading: %s") % fname)
+ dl_loc = wx.StaticText(panel, wx.ID_ANY,
+ _("Downloading To: %s") % floc)
+ self._cancel_bt = wx.Button(panel, wx.ID_CANCEL, _("Cancel"))
+ self._timer = wx.Timer(self, id=self.ID_TIMER)
+ self._proghist = list()
+
+ #---- Layout ----#
+ self.CreateStatusBar(2)
+ self._sizer = wx.GridBagSizer()
+ bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_WEB), wx.ART_TOOLBAR)
+ mdc = wx.MemoryDC(bmp)
+ tmp_bmp = wx.Image(ed_glob.CONFIG['SYSPIX_DIR'] + u"editra.png",
+ wx.BITMAP_TYPE_PNG)
+ tmp_bmp.Rescale(20, 20, wx.IMAGE_QUALITY_HIGH)
+ mdc.DrawBitmap(tmp_bmp.ConvertToBitmap(), 11, 11)
+ mdc.SelectObject(wx.NullBitmap)
+ bmp = wx.StaticBitmap(panel, wx.ID_ANY, bmp)
+ self._sizer.AddMany([(bmp, (1, 1), (3, 2)),
+ (dl_file, (1, 4), (1, 4)),
+ (dl_loc, (2, 4), (1, 4)),
+ ((15, 15), (3, 5), (1, 1))])
+ self._sizer.Add(self._progress, (4, 1), (1, 10), wx.EXPAND)
+
+ bsizer = wx.BoxSizer(wx.HORIZONTAL)
+ bsizer.AddStretchSpacer()
+ bsizer.Add(self._cancel_bt, 0, wx.ALIGN_CENTER_HORIZONTAL)
+ bsizer.AddStretchSpacer()
+
+ self._sizer.Add(bsizer, (6, 1), (1, 10), wx.EXPAND)
+ self._sizer.Add((5, 5), (7, 1))
+ self._sizer.Add((5, 5), (7, 11))
+ panel.SetSizer(self._sizer)
+ mwsz = wx.BoxSizer(wx.HORIZONTAL)
+ mwsz.Add(panel, 1, wx.EXPAND)
+ self.SetSizer(mwsz)
+ self.SetInitialSize()
+
+ self.SetStatusWidths([-1, 100])
+ self.SetStatusText(_("Downloading") + u"...", self.SB_INFO)
+
+ #---- Bind Events ----#
+ self.Bind(wx.EVT_BUTTON, self.OnButton)
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
+ self.Bind(wx.EVT_TIMER, self.OnUpdate, id=self.ID_TIMER)
+
+ def OnDestroy(self, evt):
+ """Cleans up on exit
+ @postcondition: if timer was running it is stopped
+
+ """
+ if evt.GetId() == self.GetId():
+ if self._timer.IsRunning():
+ self.LOG('[updater][info] DownloadDialog: __del__ Timer Stopped')
+ self._timer.Stop()
+ evt.Skip()
+
+ def CalcDownRate(self):
+ """Calculates and returns the approximate download rate
+ in Kb/s
+ @return: current downlaod rate in Kb/s
+ @rtype: float
+
+ """
+ dlist = list()
+ last = 0
+ for item in self._proghist:
+ val = item - last
+ dlist.append(val)
+ last = item
+ return round((float(sum(dlist) / len(self._proghist)) / 1024), 2)
+
+ def OnButton(self, evt):
+ """Handles events that are generated when buttons are pushed.
+ @param evt: event that called this handler
+
+ """
+ e_id = evt.GetId()
+ if e_id == wx.ID_CANCEL:
+ self.LOG("[updater][evt] DownloadDialog: Cancel pressed")
+ self._progress.Abort()
+ self._cancel_bt.Disable()
+ self.SetStatusText(_("Canceled"), self.SB_INFO)
+ else:
+ evt.Skip()
+
+ def OnClose(self, evt):
+ """Handles the window closer event
+ @param evt: event that called this handler
+
+ """
+ self.LOG("[updater][evt] DownloadDialog: Closing Download Dialog")
+ self._progress.Abort()
+ # Wait till thread has halted before exiting
+ while self._progress.IsDownloading():
+ wx.YieldIfNeeded()
+ wx.GetApp().UnRegisterWindow(repr(self))
+ evt.Skip()
+
+ def OnUpdate(self, evt):
+ """Updates the status text on each pulse from the timer
+ @param evt: event that called this handler
+
+ """
+ e_id = evt.GetId()
+ if e_id == self.ID_TIMER:
+ prog = self._progress.GetProgress()
+ self._proghist.append(prog[0])
+ speed = self.CalcDownRate()
+ if self._progress.IsDownloading():
+ self.SetStatusText(_("Rate: %.2f Kb/s") % speed,
+ self.SB_DOWNLOADED)
+ else:
+ self.LOG("[updater][evt] DownloadDialog:: Download finished")
+ self.SetStatusText(u'', self.SB_DOWNLOADED)
+ if self._progress.GetDownloadResult():
+ self.LOG("[updater][info] DownloadDialog: Download Successful")
+ self.SetStatusText(_("Finished"), self.SB_INFO)
+ else:
+ self.LOG("[updater][info] DownloadDialog: Download Failed")
+ self.SetStatusText(_("Failed"), self.SB_INFO)
+ self._progress.Enable()
+ self._progress.SetValue(self._progress.GetProgress()[0])
+ self._timer.Stop()
+ self._cancel_bt.Disable()
+ else:
+ evt.Skip()
+
+ def Show(self):
+ """Shows the Dialog and starts downloading the updates
+ @postcondition: window is registered with mainloop and shown on screen
+ @todo: Allow setting of download location to be set when shown
+
+ """
+ # Tell the main loop we are busy
+ wx.GetApp().RegisterWindow(repr(self), self, True)
+ self._timer.Start(1000) # One pulse every second
+ self._progress.DownloadUpdates()
+ super(DownloadDialog, self).Show()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/util.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/util.py
new file mode 100644
index 0000000..12e000a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/util.py
@@ -0,0 +1,791 @@
+###############################################################################
+# Name: util.py #
+# Purpose: Misc utility functions used through out Editra #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+This file contains various helper functions and utilities that the program uses.
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: util.py 72623 2012-10-06 19:33:06Z CJP $"
+__revision__ = "$Revision: 72623 $"
+
+#--------------------------------------------------------------------------#
+# Imports
+import os
+import sys
+import mimetypes
+import encodings
+import codecs
+import urllib2
+import wx
+
+# Editra Libraries
+import ed_glob
+import ed_event
+import ed_crypt
+import dev_tool
+import syntax.syntax as syntax
+import syntax.synglob as synglob
+import ebmlib
+
+_ = wx.GetTranslation
+#--------------------------------------------------------------------------#
+
+class DropTargetFT(wx.PyDropTarget):
+ """Drop target capable of accepting dropped files and text
+ @todo: has some issues with the clipboard on windows under certain
+ conditions. They are not fatal but need fixing.
+
+ """
+ def __init__(self, window, textcallback=None, filecallback=None):
+ """Initializes the Drop target
+ @param window: window to receive drop objects
+ @keyword textcallback: Callback for when text is dropped
+ @keyword filecallback: Callback for when file(s) are dropped
+
+ """
+ super(DropTargetFT, self).__init__()
+
+ # Attributes
+ self.window = window
+ self._data = dict(data=None, fdata=None, tdata=None,
+ tcallb=textcallback, fcallb=filecallback)
+ self._tmp = None
+ self._lastp = None
+
+ # Setup
+ self.InitObjects()
+
+ def CreateDragString(self, txt):
+ """Creates a bitmap of the text that is being dragged
+ @todo: possibly set colors to match highlighting of text
+ @todo: generalize this to be usable by other widgets besides stc
+
+ """
+ if not isinstance(self.window, wx.stc.StyledTextCtrl):
+ return
+
+ stc = self.window
+ txt = txt.split(stc.GetEOLChar())
+ longest = (0, 0)
+ for line in txt:
+ ext = stc.GetTextExtent(line)
+ if ext[0] > longest[0]:
+ longest = ext
+
+ cords = [ (0, x * longest[1]) for x in range(len(txt)) ]
+ try:
+ mdc = wx.MemoryDC(wx.EmptyBitmap(longest[0] + 5,
+ longest[1] * len(txt), 32))
+ mdc.SetBackgroundMode(wx.TRANSPARENT)
+ mdc.SetTextForeground(stc.GetDefaultForeColour())
+ mdc.SetFont(stc.GetDefaultFont())
+ mdc.DrawTextList(txt, cords)
+ self._tmp = wx.DragImage(mdc.GetAsBitmap())
+ except wx.PyAssertionError, msg:
+ Log("[droptargetft][err] %s" % str(msg))
+
+ def InitObjects(self):
+ """Initializes the text and file data objects
+ @postcondition: all data objects are initialized
+
+ """
+ self._data['data'] = wx.DataObjectComposite()
+ self._data['tdata'] = wx.TextDataObject()
+ self._data['fdata'] = wx.FileDataObject()
+ self._data['data'].Add(self._data['tdata'], True)
+ self._data['data'].Add(self._data['fdata'], False)
+ self.SetDataObject(self._data['data'])
+
+ def OnEnter(self, x_cord, y_cord, drag_result):
+ """Called when a drag starts
+ @param x_cord: x cord of enter point
+ @param y_cord: y cord of enter point
+ @param drag_result: wxDrag value
+ @return: result of drop object entering window
+
+ """
+ # GetData seems to happen automatically on msw, calling it again
+ # causes this to fail the first time.
+ if wx.Platform in ['__WXGTK__', '__WXMSW__']:
+ return wx.DragCopy
+
+ if wx.Platform == '__WXMAC__':
+ try:
+ self.GetData()
+ except wx.PyAssertionError:
+ return wx.DragError
+
+ self._lastp = (x_cord, y_cord)
+ files = self._data['fdata'].GetFilenames()
+ text = self._data['tdata'].GetText()
+ if len(files):
+ self.window.SetCursor(wx.StockCursor(wx.CURSOR_COPY_ARROW))
+ else:
+ self.CreateDragString(text)
+ return drag_result
+
+ def OnDrop(self, x_cord=0, y_cord=0):
+ """Gets the drop cords
+ @keyword x_cord: x cord of drop object
+ @keyword y_cord: y cord of drop object
+ @todo: implement snapback when drop is out of range
+
+ """
+ self._tmp = None
+ self._lastp = None
+ return True
+
+ def OnDragOver(self, x_cord, y_cord, drag_result):
+ """Called when the cursor is moved during a drag action
+ @param x_cord: x cord of mouse
+ @param y_cord: y cord of mouse
+ @param drag_result: Drag result value
+ @return: result of drag over
+ @todo: For some reason the caret position changes which can be seen
+ by the brackets getting highlighted. However the actual caret
+ is not moved.
+
+ """
+ stc = self.window
+ if self._tmp is None:
+ if hasattr(stc, 'DoDragOver'):
+ val = stc.DoDragOver(x_cord, y_cord, drag_result)
+ self.ScrollBuffer(stc, x_cord, y_cord)
+ drag_result = wx.DragCopy
+ else:
+ # A drag image was created
+ if hasattr(stc, 'DoDragOver'):
+ point = wx.Point(x_cord, y_cord)
+ self._tmp.BeginDrag(point - self._lastp, stc)
+ self._tmp.Hide()
+ stc.DoDragOver(x_cord, y_cord, drag_result)
+ self._tmp.Move(point)
+ self._tmp.Show()
+ self._tmp.RedrawImage(self._lastp, point, True, True)
+ self._lastp = point
+ self.ScrollBuffer(stc, x_cord, y_cord)
+ drag_result = wx.DragCopy
+
+ return drag_result
+
+ def OnData(self, x_cord, y_cord, drag_result):
+ """Gets and processes the dropped data
+ @param x_cord: x coordinate
+ @param y_cord: y coordinate
+ @param drag_result: wx Drag result value
+ @postcondition: dropped data is processed
+
+ """
+ self.window.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ if self.window.HasCapture():
+ self.window.ReleaseMouse()
+
+ try:
+ data = self.GetData()
+ except wx.PyAssertionError:
+ wx.PostEvent(self.window.GetTopLevelParent(), \
+ ed_event.StatusEvent(ed_event.edEVT_STATUS, -1,
+ _("Unable to accept dropped file "
+ "or text")))
+ data = False
+ drag_result = wx.DragCancel
+
+ if data:
+ files = self._data['fdata'].GetFilenames()
+ text = self._data['tdata'].GetText()
+ if len(files) > 0 and self._data['fcallb'] is not None:
+ self._data['fcallb'](files)
+ elif len(text) > 0:
+ if self._data['tcallb'] is not None:
+ self._data['tcallb'](text)
+ elif hasattr(self.window, 'DoDropText'):
+ self.window.DoDropText(x_cord, y_cord, text)
+ self.InitObjects()
+ return drag_result
+
+ def OnLeave(self):
+ """Handles the event of when the drag object leaves the window
+ @postcondition: Cursor is set back to normal state
+
+ """
+ self.window.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ if self.window.HasCapture():
+ self.window.ReleaseMouse()
+
+ if self._tmp is not None:
+ try:
+ self._tmp.EndDrag()
+ except wx.PyAssertionError, msg:
+ Log("[droptargetft][err] %s" % str(msg))
+
+ @staticmethod
+ def ScrollBuffer(stc, x_cord, y_cord):
+ """Scroll the buffer as the dragged text is moved towards the
+ ends.
+ @param stc: StyledTextCtrl
+ @param x_cord: int (x position)
+ @param y_cord: int (y position)
+ @note: currently does not work on wxMac
+
+ """
+ try:
+ cline = stc.PositionFromPoint(wx.Point(x_cord, y_cord))
+ if cline != wx.stc.STC_INVALID_POSITION:
+ cline = stc.LineFromPosition(cline)
+ fline = stc.GetFirstVisibleLine()
+ lline = stc.GetLastVisibleLine()
+ if (cline - fline) < 2:
+ stc.ScrollLines(-1)
+ elif lline - cline < 2:
+ stc.ScrollLines(1)
+ else:
+ pass
+ except wx.PyAssertionError, msg:
+ Log("[droptargetft][err] ScrollBuffer: %s" % msg)
+
+#---- End FileDropTarget ----#
+
+class EdClipboard(ebmlib.CycleCache):
+ """Local clipboard object
+ @todo: make into a singleton
+
+ """
+ def GetNext(self):
+ """Get the next item in the cache"""
+ # Initialize the clipboard if it hasn't been loaded yet and
+ # there is something in the system clipboard
+ if self.GetCurrentSize() == 0:
+ txt = GetClipboardText()
+ if txt is not None:
+ self.Put(txt)
+
+ return super(EdClipboard, self).GetNext()
+
+ def IsAtIndex(self, txt):
+ """Is the passed in phrase at the current cycle index in the
+ cache. Used to check if index should be reset or to continue in
+ the cycle.
+ @param txt: selected text
+
+ """
+ pre = self.PeekPrev()
+ next = self.PeekNext()
+ if txt in (pre, next):
+ return True
+ else:
+ return False
+
+ def Put(self, txt):
+ """Put some text in the clipboard
+ @param txt: Text to put in the system clipboard
+
+ """
+ pre = self.PeekPrev()
+ next = self.PeekNext()
+ if len(txt) and txt not in (pre, next):
+ self.PutItem(txt)
+
+#---- Misc Common Function Library ----#
+# Used for holding the primary selection on mac/msw
+FAKE_CLIPBOARD = None
+
+def GetClipboardText(primary=False):
+ """Get the primary selection from the clipboard if there is one
+ @return: str or None
+
+ """
+ if primary and wx.Platform == '__WXGTK__':
+ wx.TheClipboard.UsePrimarySelection(True)
+ elif primary:
+ # Fake the primary selection on mac/msw
+ global FAKE_CLIPBOARD
+ return FAKE_CLIPBOARD
+ else:
+ pass
+
+ text_obj = wx.TextDataObject()
+ rtxt = None
+
+ if wx.TheClipboard.IsOpened() or wx.TheClipboard.Open():
+ if wx.TheClipboard.GetData(text_obj):
+ rtxt = text_obj.GetText()
+ wx.TheClipboard.Close()
+
+ if primary and wx.Platform == '__WXGTK__':
+ wx.TheClipboard.UsePrimarySelection(False)
+ return rtxt
+
+def SetClipboardText(txt, primary=False):
+ """Copies text to the clipboard
+ @param txt: text to put in clipboard
+ @keyword primary: Set txt as primary selection (x11)
+
+ """
+ # Check if using primary selection
+ if primary and wx.Platform == '__WXGTK__':
+ wx.TheClipboard.UsePrimarySelection(True)
+ elif primary:
+ # Fake the primary selection on mac/msw
+ global FAKE_CLIPBOARD
+ FAKE_CLIPBOARD = txt
+ return True
+ else:
+ pass
+
+ data_o = wx.TextDataObject()
+ data_o.SetText(txt)
+ if wx.TheClipboard.IsOpened() or wx.TheClipboard.Open():
+ wx.TheClipboard.SetData(data_o)
+ wx.TheClipboard.Close()
+ if primary and wx.Platform == '__WXGTK__':
+ wx.TheClipboard.UsePrimarySelection(False)
+ return True
+ else:
+ return False
+
+def FilterFiles(file_list):
+ """Filters a list of paths and returns a list of paths
+ that can probably be opened in the editor.
+ @param file_list: list of files/folders to filter for good files in
+
+ """
+ good = list()
+ checker = ebmlib.FileTypeChecker()
+ for path in file_list:
+ if not checker.IsBinary(path):
+ good.append(path)
+ return good
+
+def GetFileType(fname):
+ """Get what the type of the file is as Editra sees it
+ in a formatted string.
+ @param fname: file path
+ @return: string (formatted/translated filetype)
+
+ """
+ if os.path.isdir(fname):
+ return _("Folder")
+
+ eguess = syntax.GetTypeFromExt(fname.split('.')[-1])
+ if eguess == synglob.LANG_TXT and fname.split('.')[-1] == 'txt':
+ return _("Text Document")
+ elif eguess == synglob.LANG_TXT:
+ mtype = mimetypes.guess_type(fname)[0]
+ if mtype is not None:
+ return mtype
+ else:
+ return _("Unknown")
+ else:
+ return _("%s Source File") % eguess
+
+def GetFileReader(file_name, enc='utf-8'):
+ """Returns a file stream reader object for reading the
+ supplied file name. It returns a file reader using the encoding
+ (enc) which defaults to utf-8. If lookup of the reader fails on
+ the host system it will return an ascii reader.
+ If there is an error in creating the file reader the function
+ will return a negative number.
+ @param file_name: name of file to get a reader for
+ @keyword enc: encoding to use for reading the file
+ @return file reader, or int if error.
+
+ """
+ try:
+ file_h = file(file_name, "rb")
+ except (IOError, OSError):
+ dev_tool.DEBUGP("[file_reader] Failed to open file %s" % file_name)
+ return -1
+
+ try:
+ reader = codecs.getreader(enc)(file_h)
+ except (LookupError, IndexError, ValueError):
+ dev_tool.DEBUGP('[file_reader] Failed to get %s Reader' % enc)
+ reader = file_h
+ return reader
+
+def GetFileWriter(file_name, enc='utf-8'):
+ """Returns a file stream writer object for reading the
+ supplied file name. It returns a file writer in the supplied
+ encoding if the host system supports it other wise it will return
+ an ascii reader. The default will try and return a utf-8 reader.
+ If there is an error in creating the file reader the function
+ will return a negative number.
+ @param file_name: path of file to get writer for
+ @keyword enc: encoding to write text to file with
+
+ """
+ try:
+ file_h = open(file_name, "wb")
+ except IOError:
+ dev_tool.DEBUGP("[file_writer][err] Failed to open file %s" % file_name)
+ return -1
+ try:
+ writer = codecs.getwriter(enc)(file_h)
+ except (LookupError, IndexError, ValueError):
+ dev_tool.DEBUGP('[file_writer][err] Failed to get %s Writer' % enc)
+ writer = file_h
+ return writer
+
+# TODO: DEPRECATED - remove once callers migrate to ebmlib
+GetFileManagerCmd = ebmlib.GetFileManagerCmd
+
+def GetUserConfigBase():
+ """Get the base user configuration directory path"""
+ cbase = ed_glob.CONFIG['CONFIG_BASE']
+ if cbase is None:
+ cbase = wx.StandardPaths_Get().GetUserDataDir()
+ if wx.Platform == '__WXGTK__':
+ if u'.config' not in cbase and not os.path.exists(cbase):
+ # If no existing configuration return xdg config path
+ base, cfgdir = os.path.split(cbase)
+ tmp_path = os.path.join(base, '.config')
+ if os.path.exists(tmp_path):
+ cbase = os.path.join(tmp_path, cfgdir.lstrip(u'.'))
+ return cbase + os.sep
+
+def HasConfigDir(loc=u""):
+ """ Checks if the user has a config directory and returns True
+ if the config directory exists or False if it does not.
+ @return: whether config dir in question exists on an expected path
+
+ """
+ cbase = GetUserConfigBase()
+ to_check = os.path.join(cbase, loc)
+ return os.path.exists(to_check)
+
+def MakeConfigDir(name):
+ """Makes a user config directory
+ @param name: name of config directory to make in user config dir
+
+ """
+ cbase = GetUserConfigBase()
+ try:
+ os.mkdir(cbase + name)
+ except (OSError, IOError):
+ pass
+
+def RepairConfigState(path):
+ """Repair the state of profile path, updating and creating it
+ it does not exist.
+ @param path: path of profile
+
+ """
+ if os.path.isabs(path) and os.path.exists(path):
+ return path
+ else:
+ # Need to fix some stuff up
+ CreateConfigDir()
+ import profiler
+ return profiler.Profile_Get("MYPROFILE")
+
+def CreateConfigDir():
+ """ Creates the user config directory its default sub
+ directories and any of the default config files.
+ @postcondition: all default configuration files/folders are created
+
+ """
+ #---- Resolve Paths ----#
+ config_dir = GetUserConfigBase()
+ profile_dir = os.path.join(config_dir, u"profiles")
+ dest_file = os.path.join(profile_dir, u"default.ppb")
+ ext_cfg = [u"cache", u"styles", u"plugins"]
+
+ #---- Create Directories ----#
+ if not os.path.exists(config_dir):
+ os.mkdir(config_dir)
+
+ if not os.path.exists(profile_dir):
+ os.mkdir(profile_dir)
+
+ for cfg in ext_cfg:
+ if not HasConfigDir(cfg):
+ MakeConfigDir(cfg)
+
+ import profiler
+ profiler.TheProfile.LoadDefaults()
+ profiler.Profile_Set("MYPROFILE", dest_file)
+ profiler.TheProfile.Write(dest_file)
+ profiler.UpdateProfileLoader()
+
+def ResolvConfigDir(config_dir, sys_only=False):
+ """Checks for a user config directory and if it is not
+ found it then resolves the absolute path of the executables
+ directory from the relative execution path. This is then used
+ to find the location of the specified directory as it relates
+ to the executable directory, and returns that path as a
+ string.
+ @param config_dir: name of config directory to resolve
+ @keyword sys_only: only get paths of system config directory or user one
+ @note: This method is probably much more complex than it needs to be but
+ the code has proven itself.
+
+ """
+ # Try to get a User config directory
+ if not sys_only:
+ user_config = GetUserConfigBase()
+ user_config = os.path.join(user_config, config_dir)
+
+ if os.path.exists(user_config):
+ return user_config + os.sep
+
+ # Check if the system install path has already been resolved once before
+ if ed_glob.CONFIG['INSTALL_DIR'] != u"":
+ tmp = os.path.join(ed_glob.CONFIG['INSTALL_DIR'], config_dir)
+ tmp = os.path.normpath(tmp) + os.sep
+ if os.path.exists(tmp):
+ return tmp
+ else:
+ del tmp
+
+ # The following lines are used only when Editra is being run as a
+ # source package. If the found path does not exist then Editra is
+ # running as as a built package.
+ if not hasattr(sys, 'frozen'):
+ path = __file__
+ if not ebmlib.IsUnicode(path):
+ path = path.decode(sys.getfilesystemencoding())
+ path = os.sep.join(path.split(os.sep)[:-2])
+ path = path + os.sep + config_dir + os.sep
+ if os.path.exists(path):
+ if not ebmlib.IsUnicode(path):
+ path = unicode(path, sys.getfilesystemencoding())
+ return path
+
+ # If we get here we need to do some platform dependent lookup
+ # to find everything.
+ path = sys.argv[0]
+ if not ebmlib.IsUnicode(path):
+ path = unicode(path, sys.getfilesystemencoding())
+
+ # If it is a link get the real path
+ if os.path.islink(path):
+ path = os.path.realpath(path)
+
+ # Tokenize path
+ pieces = path.split(os.sep)
+
+ if wx.Platform == u'__WXMSW__':
+ # On Windows the exe is in same dir as config directories
+ pro_path = os.sep.join(pieces[:-1])
+
+ if os.path.isabs(pro_path):
+ pass
+ elif pro_path == u"":
+ pro_path = os.getcwd()
+ pieces = pro_path.split(os.sep)
+ pro_path = os.sep.join(pieces[:-1])
+ else:
+ pro_path = os.path.abspath(pro_path)
+ elif wx.Platform == u'__WXMAC__':
+ # On OS X the config directories are in the applet under Resources
+ stdpath = wx.StandardPaths_Get()
+ pro_path = stdpath.GetResourcesDir()
+ pro_path = os.path.join(pro_path, config_dir)
+ else:
+ pro_path = os.sep.join(pieces[:-2])
+ if pro_path.startswith(os.sep):
+ pass
+ elif pro_path == u"":
+ pro_path = os.getcwd()
+ pieces = pro_path.split(os.sep)
+ if pieces[-1] not in [ed_glob.PROG_NAME.lower(), ed_glob.PROG_NAME]:
+ pro_path = os.sep.join(pieces[:-1])
+ else:
+ pro_path = os.path.abspath(pro_path)
+
+ if wx.Platform != u'__WXMAC__':
+ pro_path = pro_path + os.sep + config_dir + os.sep
+
+ path = os.path.normpath(pro_path) + os.sep
+
+ # Make sure path is unicode
+ if not ebmlib.IsUnicode(path):
+ path = unicode(path, sys.getdefaultencoding())
+
+ return path
+
+def GetResources(resource):
+ """Returns a list of resource directories from a given toplevel config dir
+ @param resource: config directory name
+ @return: list of resource directory that exist under the given resource path
+
+ """
+ rec_dir = ResolvConfigDir(resource)
+ if os.path.exists(rec_dir):
+ rec_lst = [ rec.title() for rec in os.listdir(rec_dir)
+ if os.path.isdir(rec_dir + rec) and rec[0] != u"." ]
+ return rec_lst
+ else:
+ return -1
+
+def GetResourceFiles(resource, trim=True, get_all=False,
+ suffix=None, title=True):
+ """Gets a list of resource files from a directory and trims the
+ file extentions from the names if trim is set to True (default).
+ If the get_all parameter is set to True the function will return
+ a set of unique items by looking up both the user and system level
+ files and combining them, the default behavior returns the user
+ level files if they exist or the system level files if the
+ user ones do not exist.
+ @param resource: name of config directory to look in (i.e cache)
+ @keyword trim: trim file extensions or not
+ @keyword get_all: get a set of both system/user files or just user level
+ @keyword suffix: Get files that have the specified suffix or all (default)
+ @keyword title: Titlize the results
+
+ """
+ rec_dir = ResolvConfigDir(resource)
+ if get_all:
+ rec_dir2 = ResolvConfigDir(resource, True)
+ rec_list = list()
+ if not os.path.exists(rec_dir):
+ return -1
+ else:
+ recs = os.listdir(rec_dir)
+ if get_all and os.path.exists(rec_dir2):
+ recs.extend(os.listdir(rec_dir2))
+
+ for rec in recs:
+ if os.path.isfile(rec_dir + rec) or \
+ (get_all and os.path.isfile(rec_dir2 + rec)):
+
+ # If a suffix was specified only keep files that match
+ if suffix is not None:
+ if not rec.endswith(suffix):
+ continue
+
+ # Trim the last part of an extension if one exists
+ if trim:
+ rec = ".".join(rec.split(u".")[:-1]).strip()
+
+ # Make the resource name a title if requested
+ if title and len(rec):
+ rec = rec[0].upper() + rec[1:]
+
+ if len(rec):
+ rec_list.append(rec)
+ rec_list.sort()
+
+ return list(set(rec_list))
+
+def GetAllEncodings():
+ """Get all encodings found on the system
+ @return: list of strings
+
+ """
+ elist = encodings.aliases.aliases.values()
+ elist = list(set(elist))
+ elist.sort()
+ elist = [ enc for enc in elist if not enc.endswith('codec') ]
+ return elist
+
+def Log(msg, *args):
+ """Push the message to the apps log
+ @param msg: message string to log
+ @param args: optional positional arguments to use as a printf formatting
+ to the message.
+
+ """
+ try:
+ wx.GetApp().GetLog()(msg, args)
+ except:
+ pass
+
+def GetProxyOpener(proxy_set):
+ """Get a urlopener for use with a proxy
+ @param proxy_set: proxy settings to use
+
+ """
+ Log("[util][info] Making proxy opener with %s" % str(proxy_set))
+ proxy_info = dict(proxy_set)
+ auth_str = "%(uname)s:%(passwd)s@%(url)s"
+ url = proxy_info['url']
+ if url.startswith('http://'):
+ auth_str = "http://" + auth_str
+ proxy_info['url'] = url.replace('http://', '')
+ else:
+ pass
+
+ if len(proxy_info.get('port', '')):
+ auth_str = auth_str + ":%(port)s"
+
+ proxy_info['passwd'] = ed_crypt.Decrypt(proxy_info['passwd'],
+ proxy_info['pid'])
+ Log("[util][info] Formatted proxy request: %s" % \
+ (auth_str.replace('%(passwd)s', '****') % proxy_info))
+ proxy = urllib2.ProxyHandler({"http" : auth_str % proxy_info})
+ opener = urllib2.build_opener(proxy, urllib2.HTTPHandler)
+ return opener
+
+#---- GUI helper functions ----#
+
+def SetWindowIcon(window):
+ """Sets the given windows icon to be the programs
+ application icon.
+ @param window: window to set app icon for
+
+ """
+ try:
+ if wx.Platform == "__WXMSW__":
+ ed_icon = ed_glob.CONFIG['SYSPIX_DIR'] + u"editra.ico"
+ window.SetIcon(wx.Icon(ed_icon, wx.BITMAP_TYPE_ICO))
+ else:
+ ed_icon = ed_glob.CONFIG['SYSPIX_DIR'] + u"editra.png"
+ window.SetIcon(wx.Icon(ed_icon, wx.BITMAP_TYPE_PNG))
+ finally:
+ pass
+
+#-----------------------------------------------------------------------------#
+
+class IntValidator(wx.PyValidator):
+ """A Generic integer validator"""
+ def __init__(self, min_=0, max_=0):
+ """Initialize the validator
+ @keyword min_: min value to accept
+ @keyword max_: max value to accept
+
+ """
+ wx.PyValidator.__init__(self)
+ self._min = min_
+ self._max = max_
+
+ # Event management
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+
+ def Clone(self):
+ """Clones the current validator
+ @return: clone of this object
+
+ """
+ return IntValidator(self._min, self._max)
+
+ def Validate(self, win):
+ """Validate an window value
+ @param win: window to validate
+
+ """
+ val = win.GetValue()
+ return val.isdigit()
+
+ def OnChar(self, event):
+ """Process values as they are entered into the control
+ @param event: event that called this handler
+
+ """
+ key = event.GetKeyCode()
+ if key < wx.WXK_SPACE or key == wx.WXK_DELETE or \
+ key > 255 or chr(key) in '0123456789':
+ event.Skip()
+ return
+
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+
+ return
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/wxcompat.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/wxcompat.py
new file mode 100644
index 0000000..70b9e5f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/wxcompat.py
@@ -0,0 +1,49 @@
+###############################################################################
+# Name: wxcompat.py #
+# Purpose: Help with compatibility between wx versions. #
+# Author: Cody Precord <cprecord@editra.org> #
+# Copyright: (c) 2008 Cody Precord <staff@editra.org> #
+# License: wxWindows License #
+###############################################################################
+
+"""
+@summary: wx Compatibility helper module
+
+"""
+
+__author__ = "Cody Precord <cprecord@editra.org>"
+__svnid__ = "$Id: wxcompat.py 68998 2011-09-03 22:03:32Z CJP $"
+__revision__ = "$Revision: 68998 $"
+
+#-----------------------------------------------------------------------------#
+# Imports
+import os
+import wx
+
+#-----------------------------------------------------------------------------#
+
+if wx.Platform == '__WXMAC__':
+ # MacThemeColour is defined in wxPython2.9 but does not exist in 2.8
+ # This is a 2.8 version of this method.
+ if not hasattr(wx, 'MacThemeColour'):
+ def MacThemeColour(theme_id):
+ """Get a specified Mac theme colour
+ @param theme_id: Carbon theme id
+ @return: wx.Colour
+
+ """
+ brush = wx.Brush(wx.BLACK)
+ brush.MacSetTheme(theme_id)
+ return brush.GetColour()
+
+ wx.MacThemeColour = MacThemeColour
+
+ wx.SystemOptions.SetOptionInt("mac.textcontrol-use-spell-checker", 1)
+
+elif wx.Platform == '__WXGTK__':
+ os.environ['LIBOVERLAY_SCROLLBAR'] = '0'
+
+# GetText is not available in 2.9 but GetItemLabel is not available pre 2.8.6
+if wx.VERSION < (2, 8, 6, 0, ''):
+ wx.MenuItem.GetItemLabel = wx.MenuItem.GetText
+ wx.MenuItem.GetItemLabelText = wx.MenuItem.GetLabel
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlackBoard.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlackBoard.ess
new file mode 100644
index 0000000..ac3fb28
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlackBoard.ess
@@ -0,0 +1,172 @@
+/* File: BlackBoard.ess
+ * Author: Cody Precord
+ * License: wxWidgets
+ */
+
+default_style {
+ fore:#F8F8F8;
+ back:#0C1021;
+ face:%(primary)s;
+ size:%(size)d;
+}
+
+array_style {
+ fore:#B86214;
+}
+
+brace_bad {
+ fore:#0000FF;
+ back:#FFFFFF;
+ modifiers:bold;
+}
+
+brace_good {
+ fore:#FF0000;
+ back:#000000;
+ modifiers:bold;
+}
+
+btick_style {
+ fore:#cc33ee;
+ back:#000000;
+}
+
+calltip {
+ back:#1c2131;
+}
+
+caret_line {
+ back:#1a1e2e;
+}
+
+char_style {
+ fore:#E19618;
+}
+
+class_style {
+ fore:#FF0404;
+ modifiers:bold;
+}
+
+class2_style {
+ fore:#FF0404;
+}
+
+comment_style {
+ fore:#626262;
+ modifiers:italic;
+}
+
+decor_style {
+ fore:#C35E21;
+ modifiers:italic;
+}
+
+directive_style {
+ fore:#2DE1CB;
+}
+
+dockey_style {
+ fore:#39EAE1;
+}
+
+error_style {
+ fore:#FE5252;
+}
+
+foldmargin_style {
+ back:#2d3243;
+}
+
+funct_style {
+ fore:#49DE38;
+ modifiers:italic;
+}
+
+global_style {
+ fore:#2F86F0;
+ modifiers:bold;
+}
+
+here_style {
+ fore:#41ce77;
+}
+
+keyword_style {
+ fore:#FBDE2D;
+}
+
+keyword2_style {
+ fore:#4179C5;
+ modifiers:bold;
+}
+
+keyword3_style {
+ fore:#4179C5;
+ modifiers:bold;
+}
+
+keyword4_style {
+ fore:#64DA3D;
+}
+
+line_num {
+ back:#1c2131;
+}
+
+marker_style {
+ fore:#F8F8F8;
+}
+
+number_style {
+ fore:#D8FA3C;
+}
+
+number2_style {
+ fore:#D8Fa3C;
+}
+
+operator_style {
+ fore:#BBBBBB;
+}
+
+pre_style {
+ fore:#27E71D;
+}
+
+pre2_style {
+ fore:#CC33EE;
+}
+
+regex_style {
+ fore:#22eeff;
+ modifiers:italic;
+}
+
+scalar_style {
+ fore:#cc33ee;
+}
+
+scalar2_style {
+ fore:#cc33ee;
+ modifiers:bold;
+}
+
+select_style {
+ back:#142DD6;
+}
+
+string_style {
+ fore:#61CE3C;
+}
+
+stringeol_style {
+ fore:#408080;
+ back:#E0C0E0;
+ modifiers:eol;
+}
+
+unknown_style {
+ fore:#F8F8f8;
+ back:#FF0000;
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Blue.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Blue.ess
new file mode 100644
index 0000000..034f8c1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Blue.ess
@@ -0,0 +1,197 @@
+/* Editra Style Sheet
+ * Name: Blue
+ * Author: Cody Precord <cprecord@editra.org>
+ * License: wxWindows License
+ */
+
+default_style {
+ fore:#FFEEDD;
+ back:#000A87;
+ face:%(primary)s;
+ size:%(size)d;
+}
+
+array_style {
+ fore:#CC1313;
+}
+
+brace_bad {
+ fore:#000A87;
+ back:#FF0024;
+}
+
+brace_good {
+ fore:#EEFFDD;
+ back:#0093FF;
+}
+
+btick_style {
+ fore:#008AC1;
+}
+
+calltip {
+ fore:#4D4D4D;
+ back:#009FFF;
+}
+
+caret_line {
+ back: #000FD6;
+}
+
+char_style {
+ fore:#00CDCD;
+}
+
+class_style {
+ fore:#F33C33;
+ modifiers: bold;
+}
+
+class2_style {
+ fore:#F33C33;
+}
+
+comment_style {
+ fore:#9B9BA7;
+}
+
+ctrl_char {
+ fore:#000000;
+}
+
+decor_style {
+ fore:#00A709;
+ modifiers: italic;
+}
+
+directive_style {
+ fore:#00FFA2;
+}
+
+dockey_style {
+ fore:#80007B;
+}
+
+error_style {
+ fore:#000A87;
+ back:#FE5252;
+}
+
+foldmargin_style {
+ fore:#FFEEDD;
+}
+
+funct_style {
+ fore:#DF5900;
+ modifiers:italic;
+}
+
+global_style {
+ fore:#00D00F;
+ modifiers:bold;
+}
+
+guide_style {
+ fore: #FFEEDD;
+}
+
+here_style {
+ fore:#ED0088;
+ back:#121A97;
+}
+
+ideol_style {
+ fore:#FFDDEE;
+ back:#00F8FF;
+ modifiers:eol;
+}
+
+keyword_style {
+ fore:#FFCF20;
+}
+
+keyword2_style {
+ fore:#00F639;
+ modifiers:bold;
+}
+
+keyword3_style {
+ fore:#E94F0B;
+}
+
+keyword4_style {
+ fore:#0062AF;
+ modifiers:bold;
+}
+
+line_num {
+ fore:#FFEEDD;
+ back:#242787;
+}
+
+margin_style {
+ fore:#000000;
+ back:#FFFFFF;
+}
+
+marker_style {
+ fore:#000000;
+ back:#FFFFFF;
+}
+
+number_style {
+ fore:#ED0088;
+}
+
+number2_style {
+ fore:#ED0088;
+ modifiers:bold;
+}
+
+operator_style {
+ fore:#FFEEDD;
+ modifiers:bold;
+}
+
+pre_style {
+ fore:#EE5507;
+ modifiers:bold;
+}
+
+pre2_style {
+ fore:#EE5507;
+}
+
+select_style {
+ back:#067B40;
+}
+
+string_style {
+ fore:#00CDCD;
+}
+
+stringeol_style {
+ fore:#000A87;
+ back:#00CDCD;
+ modifiers:bold eol;
+}
+
+regex_style {
+ fore:#00BFFF;
+ back:#000A87;
+ modifiers:italic bold;
+}
+
+scalar_style {
+ fore:#B037FF;
+ modifiers:bold;
+}
+
+scalar2_style {
+ fore:#B037FF;
+}
+
+unknown_style {
+ fore:#000000;
+ back:#FF0000;
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlueMonday.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlueMonday.ess
new file mode 100644
index 0000000..7e1ccba
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlueMonday.ess
@@ -0,0 +1,184 @@
+/* Editra Style Sheet
+ * Name: BlueMonday
+ * Author: Thomas Keul
+ * License: N/A
+ */
+
+default_style {
+ fore:#FFFFFF;
+ back:#233B5A;
+ face:%(primary)s;
+ size:%(size)d;
+}
+
+array_style {
+ fore:#000000;
+}
+
+brace_good {
+ fore:#000000;
+}
+
+btick_style {
+ fore:#000000;
+}
+
+calltip {
+ fore:#000000;
+ back:#FFFFFF;
+}
+
+caret_line {
+ back: #3F6BA5;
+}
+
+char_style {
+ fore:#00B000;
+}
+
+class_style {
+ fore:#FF8040;
+}
+
+class2_style {
+ fore:#000000;
+}
+
+comment_style {
+ fore:#C0C0C0;
+ back:#1E324D;
+}
+
+ctrl_char {
+ fore:#000000;
+}
+
+directive_style {
+ fore:#FF4242;
+}
+
+error_style {
+ fore:#000000;
+}
+
+foldmargin_style {
+ fore:#000000;
+}
+
+funct_style {
+ fore:#FF8000;
+}
+
+global_style {
+ fore:#000000;
+}
+
+here_style {
+ fore:#000000;
+}
+
+ideol_style {
+ fore:#000000;
+}
+
+keyword_style {
+ fore:#F1B411;
+}
+
+keyword2_style {
+ fore:#FF8040;
+}
+
+keyword3_style {
+ fore:#FF8040;
+}
+
+keyword4_style {
+ fore:#FFFF64;
+}
+
+keyword5_style {
+ fore:#19C864;
+}
+
+keyword6_style {
+ fore:#FF8000;
+}
+
+keyword7_style {
+ fore:#FFFF64;
+}
+
+keyword8_style {
+ fore:#FFFF64;
+}
+
+line_num {
+ fore:#000000;
+ back:#C0C0C0;
+}
+
+margin_style {
+ back:#000000;
+}
+
+marker_style {
+ fore:#000000;
+}
+
+number_style {
+ fore:#00FFFF;
+}
+
+number2_style {
+ fore:#800000;
+}
+
+operator_style {
+ fore:#FFFFFF;
+}
+
+pre_style {
+ fore:#000000;
+}
+
+pre2_style {
+ fore:#000000;
+}
+
+regex_style {
+ fore:#000000;
+}
+
+scalar_style {
+ fore:#FF8000;
+}
+
+scalar2_style {
+ fore:#000000;
+}
+
+select_style {
+ back:#8699C4;
+}
+
+string_style {
+ fore:#00C800;
+}
+
+stringeol_style {
+ fore:#FF00FF;
+}
+
+unknown_style {
+ fore:#000000;
+}
+
+brace_bad {
+ fore:#000000;
+}
+
+dockey_style {
+ fore:#876D92;
+ back:#1E324D;
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Cream.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Cream.ess
new file mode 100644
index 0000000..efde31f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Cream.ess
@@ -0,0 +1,209 @@
+/* Editra Style Sheet
+ * Name: Default
+ * Author: Cody Precord <cprecord@editra.org>
+ * License: wxWindows License
+ */
+
+/* Main Style all others inherit from */
+default_style {
+ fore: #000000;
+ back: #F6F6F6;
+ face: %(primary)s;
+ size: %(size)d;
+}
+
+brace_good {
+ fore: #FFFFFF;
+ back: #0000FF;
+ modifiers: bold;
+}
+
+brace_bad {
+ back: #FF0000;
+ modifiers: bold;
+}
+
+calltip {
+ fore: #404040;
+ back: #FFFFB8;
+}
+
+caret_line {
+ back: #D8F8FF;
+}
+
+ctrl_char {
+ fore: #000000;
+ back: #F6F6F6;
+ face: %(primary)s;
+}
+
+line_num {
+ back: #C0C0C0;
+ face: %(secondary)s;
+}
+
+array_style {
+ fore: #EE8B02;
+ modifiers: bold;
+ face: %(secondary)s;
+}
+
+btick_style {
+ fore: #8959F6;
+ modifiers: bold;
+ back: #FFFFFF;
+}
+
+char_style {
+ fore: #FF3AFF;
+ back: #FFFFFF;
+}
+
+class_style {
+ fore: #2E8B57;
+ modifiers: bold;
+}
+
+class2_style {
+ fore: #2E8B57;
+ modifiers: bold;
+ back: #FFFFFF;
+}
+
+comment_style {
+ fore: #838383;
+}
+
+decor_style {
+ fore: #BA0EEA;
+ modifiers: italic;
+ face: %(secondary)s;
+}
+
+directive_style {
+ fore: #0000FF;
+ modifiers: bold;
+ face: %(secondary)s;
+}
+
+dockey_style {
+ fore: #0000FF;
+}
+
+error_style {
+ fore: #DD0101;
+ modifiers: bold;
+ face: %(secondary)s;
+}
+
+foldmargin_style {
+ back: #D1D1D1;
+}
+
+funct_style {
+ fore: #008B8B;
+ modifiers:italic;
+}
+
+global_style {
+ fore: #007F7F;
+ modifiers:bold;
+ face: %(secondary)s;
+}
+
+guide_style {
+ fore: #838383;
+}
+
+here_style {
+ fore: #CA61CA;
+ modifiers:bold;
+ face: %(secondary)s;
+}
+
+ideol_style {
+ fore: #E0C0E0;
+ face: %(secondary)s;
+}
+
+keyword_style {
+ fore: #A52B2B;
+ modifiers:bold;
+}
+
+keyword2_style {
+ fore: #2E8B57;
+ modifiers:bold;
+}
+
+keyword3_style {
+ fore: #008B8B;
+ modifiers: bold;
+}
+
+keyword4_style {
+ fore: #9D2424;
+}
+
+margin_style {
+ fore: #FFFFFF;
+ back: #000000;
+}
+
+number_style {
+ fore: #DD0101;
+}
+
+number2_style {
+ fore: #DD0101;
+ modifiers: bold;
+}
+
+operator_style {
+ face: %(primary)s;
+ modifiers: bold;
+}
+
+pre_style {
+ fore: #AB39F2;
+ modifiers: bold;
+}
+
+pre2_style {
+ fore: #AB39F2;
+ modifiers: bold;
+ back: #FFFFFF;
+}
+
+regex_style {
+ fore: #008B8B;
+}
+
+scalar_style {
+ fore: #AB37F2;
+ modifiers: bold;
+ face: %(secondary)s;
+}
+
+scalar2_style {
+ fore: #AB37F2;
+ face: %(secondary)s;
+}
+
+string_style {
+ fore: #FF3AFF;
+ modifiers:bold;
+}
+
+stringeol_style {
+ back: #EEC0EE;
+ modifiers:eol bold;
+ face: %(secondary)s;
+}
+
+unknown_style {
+ fore: #FFFFFF;
+ back: #DD0101;
+ modifiers:bold eol;
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Default.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Default.ess
new file mode 100644
index 0000000..4c6d571
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Default.ess
@@ -0,0 +1,198 @@
+default_style {
+ fore:#000000;
+ back:#FFFFFF;
+ face:%(primary)s;
+ size:%(size)d;
+}
+
+margin_style {
+ fore:#FFFFFF;
+ back:#000000;
+}
+
+number2_style {
+ fore:#DD0101;
+ modifiers:bold;
+}
+
+caret_line {
+ back:#D8F8FF;
+}
+
+comment_style {
+ fore:#838383;
+}
+
+foldmargin_style {
+ back:#D1D1D1;
+}
+
+keyword_style {
+ fore:#A52B2B;
+ modifiers:bold;
+}
+
+keyword3_style {
+ fore:#008B8B;
+ modifiers:bold;
+}
+
+guide_style {
+ fore:#838383;
+}
+
+edge_style {
+ fore:#838383;
+}
+
+error_style {
+ fore:#FE5252;
+ face:%(secondary)s;
+ modifiers:bold;
+}
+
+ideol_style {
+ fore:#E0C0E0;
+}
+
+array_style {
+ fore:#EE8B02;
+ modifiers:bold;
+}
+
+global_style {
+ fore:#007F7F;
+ modifiers:bold;
+}
+
+line_num {
+ back:#C0C0C0;
+}
+
+pre2_style {
+ fore:#AB39F2;
+ modifiers:bold;
+}
+
+string_style {
+ fore:#FF3AFF;
+ modifiers:bold;
+}
+
+class_style {
+ fore:#2E8B57;
+ modifiers:bold;
+}
+
+ctrl_char {
+ back:#FFFFFF;
+}
+
+marker_style {
+ back:#FFFFFF;
+}
+
+keyword2_style {
+ fore:#2E8B57;
+ modifiers:bold;
+}
+
+class2_style {
+ fore:#2E8B57;
+ modifiers:bold;
+}
+
+userkw_style {
+ back:#FFFFFF;
+}
+
+char_style {
+ fore:#FF3AFF;
+}
+
+keyword4_style {
+ fore:#9D2424;
+}
+
+unknown_style {
+ fore:#FFFFFF;
+ back:#DD0101;
+ modifiers:bold eol;
+}
+
+btick_style {
+ fore:#8959F6;
+ modifiers:bold;
+}
+
+scalar_style {
+ fore:#AB37F2;
+ modifiers:bold;
+}
+
+operator_style {
+ fore:#000000;
+}
+
+here_style {
+ fore:#CA61CA;
+ modifiers:bold;
+}
+
+regex_style {
+ fore:#008B8B;
+}
+
+stringeol_style {
+ back:#EEC0EE;
+ modifiers:eol bold;
+}
+
+decor_style {
+ fore:#BA0EEA;
+ face:%(secondary)s;
+ modifiers:italic;
+}
+
+scalar2_style {
+ fore:#AB37F2;
+}
+
+funct_style {
+ fore:#008B8B;
+ modifiers:italic;
+}
+
+brace_good {
+ fore:#0000FF;
+ modifiers:bold;
+}
+
+pre_style {
+ fore:#AB39F2;
+ modifiers:bold;
+}
+
+directive_style {
+ fore:#0000FF;
+ modifiers:bold;
+}
+
+calltip {
+ fore:#404040;
+ back:#FFFFB8;
+}
+
+number_style {
+ fore:#DD0101;
+}
+
+brace_bad {
+ fore:#FF0000;
+ modifiers:bold;
+}
+
+dockey_style {
+ fore:#0000FF;
+}
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Dessert.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Dessert.ess
new file mode 100644
index 0000000..b8201de
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Dessert.ess
@@ -0,0 +1,168 @@
+/* Editra Style Sheet
+ * Name: Dessert
+ * Author: Greg Allen <mail@jga23.com>
+ * License: wxWindows License
+ */
+default_style {
+ fore:#CCCCCC;
+ back:#333333;
+ face:%(primary)s;
+ size:%(size)d;
+}
+
+number2_style {
+ fore:#CCCCCC;
+}
+
+stringeol_style {
+ fore:#FF0000;
+}
+
+caret_line {
+ back: #3F3F3F;
+}
+
+comment_style {
+ fore:#999999;
+}
+
+keyword_style {
+ fore:#F0E68C;
+}
+
+keyword3_style {
+ fore:#CD5C5C;
+}
+
+guide_style {
+ fore:#CCCCCC;
+}
+
+keyword4_style {
+ fore:#CCCCCC;
+}
+
+ideol_style {
+ fore:#CCCCCC;
+}
+
+array_style {
+ fore:#87CEEB;
+}
+
+global_style {
+ fore:#CCCCCC;
+}
+
+line_num {
+ fore:#CCCCCC;
+}
+
+pre2_style {
+ fore:#CCCCCC;
+}
+
+string_style {
+ fore:#98FB98;
+}
+
+class_style {
+ fore:#87CEEB;
+}
+
+ctrl_char {
+ fore:#CCCCCC;
+}
+
+marker_style {
+ fore:#CCCCCC;
+}
+
+keyword2_style {
+ fore:#87CEEB;
+}
+
+class2_style {
+ fore:#CCCCCC;
+}
+
+unknown_style {
+ fore:#CCCCCC;
+}
+
+calltip {
+ fore:#CCCCCC;
+}
+
+scalar_style {
+ fore:#CCCCCC;
+}
+
+char_style {
+ fore:#98FB98;
+}
+
+here_style {
+ fore:#CCCCCC;
+}
+
+number_style {
+ fore:#CCCCCC;
+}
+
+regex_style {
+ fore:#CCCCCC;
+}
+
+folder_style {
+ fore:#CCCCCC;
+}
+
+pre_style {
+ fore:#CCCCCC;
+}
+
+decor_style {
+ fore:#87CEEB;
+}
+
+scalar2_style {
+ fore:#CCCCCC;
+}
+
+funct_style {
+ fore:#CCCCCC;
+}
+
+brace_good {
+ fore:#CCCCCC;
+}
+
+error_style {
+ fore:#CD5C5C;
+}
+
+directive_style {
+ fore:#CCCCCC;
+}
+
+btick_style {
+ fore:#CCCCCC;
+}
+
+operator_style {
+ fore:#BDB76B;
+}
+
+margin_style {
+ fore:#CCCCCC;
+}
+
+brace_bad {
+ fore:#CCCCCC;
+}
+
+dockey_style {
+ fore:#CCCCCC;
+}
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Guepardo.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Guepardo.ess
new file mode 100644
index 0000000..60c0c2c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Guepardo.ess
@@ -0,0 +1,109 @@
+/* Guepardo Style Sheet ( Inspired by OSX 10.5 color scheme )
+ * Name: Guepardo
+ * Author: Omar Gomez <omar.gomez@gmail.com>
+ * License: wxWindows License
+ */
+
+default_style {
+ fore:#000000;
+ back:#FCFCFC;
+ face:%(primary)s;
+ size:%(size)d;
+}
+
+error_style {
+ fore:#FFD7D7;
+}
+
+stringeol_style {
+ fore:#FFFFFF;
+ back:#4900CC;
+ face:%(secondary)s;
+ modifiers:eol bold;
+}
+
+caret_line {
+ back:#DEEFFF;
+}
+
+comment_style {
+ fore:#5181AB;
+ modifiers:italic;
+}
+
+keyword_style {
+ fore:#0086B5;
+ modifiers:bold;
+}
+
+keyword3_style {
+ fore:#d66715;
+ modifiers:bold;
+}
+
+ideol_style {
+ fore:#FFFFFF;
+ back:#4900CC;
+ face:%(secondary)s;
+ modifiers:eol bold;
+}
+
+line_num {
+ fore:#FFFFFF;
+ back:#5181AB;
+ face:%(secondary)s;
+}
+
+string_style {
+ fore:#4900CC;
+}
+
+class_style {
+ fore:#1CA330;
+ modifiers:bold;
+}
+
+keyword2_style {
+ fore:#1ca330;
+ modifiers:bold;
+}
+
+class2_style {
+ fore:#0086B5;
+ modifiers:bold;
+}
+
+number_style {
+ fore:#5181AB;
+}
+
+pre_style {
+ fore:#894C24;
+ modifiers:bold;
+}
+
+decor_style {
+ fore:#894C24;
+ modifiers:bold italic;
+}
+
+brace_good {
+ fore:#FFFFFF;
+ back:#FF8D03;
+ modifiers:bold;
+}
+
+char_style {
+ fore:#4900CC;
+}
+
+brace_bad {
+ back:#FF0000;
+ modifiers:bold;
+}
+
+dockey_style {
+ fore:#0064F3;
+ modifiers:bold;
+}
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Midnight.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Midnight.ess
new file mode 100644
index 0000000..b0e9678
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Midnight.ess
@@ -0,0 +1,189 @@
+/* Editra Style Sheet
+ * Name: Midnight
+ * Author: Cody Precord <cprecord@editra.org>
+ * License: wxWindows License
+ */
+
+default_style {
+ fore: #FFFFFF;
+ back: #000000;
+ face: %(primary)s;
+ size: %(size)d;
+}
+
+array_style {
+ fore: #EE8B02;
+ modifiers: bold;
+}
+
+brace_good {
+ fore: #FFFFFF;
+ back: #0000FF;
+ modifiers: bold;
+}
+
+brace_bad {
+ back: #FF0000;
+ modifiers: bold;
+}
+
+btick_style {
+ fore: #8959F6;
+ modifiers: bold;
+}
+
+calltip {
+ fore: #FFE200;
+ back: #09026A;
+}
+
+caret_line {
+ back: #262626;
+}
+
+char_style {
+ fore: #FF3AFF;
+}
+
+class_style {
+ fore: #2E8B57;
+ modifiers: bold;
+}
+
+class2_style {
+ fore: #2E8B57;
+ modifiers: bold;
+}
+
+ctrl_char {
+ fore: #FFFFFF;
+ back: #000000;
+ face: %(primary)s;
+}
+
+comment_style {
+ fore: #0033CC;
+ face: %(primary)s;
+}
+
+decor_style {
+ fore: #BA0EEA;
+ face: %(secondary)s;
+ modifiers: italic;
+}
+
+directive_style {
+ fore: #0000FF;
+ modifiers: bold;
+}
+
+dockey_style {
+ fore: #00A6FF;
+}
+
+error_style {
+ fore: #FE5252;
+}
+
+funct_style {
+ fore: #008B8B;
+ modifiers: italic;
+}
+
+global_style {
+ fore: #007F7F;
+ modifiers: bold;
+}
+
+guide_style {
+ fore: #F6F6F6;
+}
+
+here_style {
+ fore: #CA61CA;
+ modifiers: bold;
+}
+
+ideol_style {
+ fore: #E0C0E0;
+}
+
+keyword_style {
+ fore: #A52B2B;
+ modifiers: bold;
+}
+
+keyword2_style {
+ fore: #2E8B57;
+ modifiers: bold;
+}
+
+keyword3_style {
+ fore: #008B8B;
+ modifiers: bold;
+}
+
+keyword4_style {
+ fore: #9D2424;
+}
+
+number_style {
+ fore: #DD0101;
+}
+
+number2_style {
+ fore: #DD0101;
+ modifiers: bold;
+}
+
+operator_style {
+ fore: #FFFFFF;
+ modifiers: bold;
+}
+
+pre_style {
+ fore: #AB39F2;
+ modifiers: bold;
+}
+
+pre2_style {
+ fore: #AB39F2;
+ back: #101010;
+ modifiers: bold;
+}
+
+regex_style {
+ fore: #008B8B;
+ modifiers: bold;
+}
+
+scalar_style {
+ fore: #AB37F2;
+ modifiers: bold;
+}
+
+scalar2_style {
+ fore: #AB37F2;
+}
+
+select_style {
+ back: #03087D;
+}
+
+string_style {
+ fore: #FF3AFF;
+ modifiers: bold;
+}
+
+stringeol_style {
+ fore: #000000;
+ back: #EEC0EE;
+ size: %(size)d;
+ modifiers: bold eol;
+}
+
+unknown_style {
+ fore: #FFFFFF;
+ back: #DD0101;
+ modifiers: bold eol;
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Mocha.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Mocha.ess
new file mode 100644
index 0000000..bbdd886
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Mocha.ess
@@ -0,0 +1,210 @@
+/* Mocha.ess
+ *
+ */
+
+default_style {
+ fore:#BDAE9D;
+ back:#2A211C;
+ face:%(primary)s;
+ size:%(size)d;
+}
+
+number2_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+stringeol_style {
+ fore:#FF0000;
+}
+
+caret_line {
+ fore:#CCCCCC;
+ back:#382C25;
+}
+
+error_style {
+ fore:#CD5C5C;
+ back:#333333;
+}
+
+comment_style {
+ fore:#80756A;
+ size:%(size)d;
+ modifiers:italic;
+}
+
+foldmargin_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+keyword_style {
+ fore:#43A8ED;
+}
+
+keyword3_style {
+ fore:#CD5C5C;
+ back:#333333;
+}
+
+guide_style {
+ fore:#665E55;
+ back:#333333;
+}
+
+keyword4_style {
+ fore:#CCCCCC;
+}
+
+ideol_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+array_style {
+ fore:#87CEEB;
+ back:#333333;
+}
+
+global_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+line_num {
+ fore:#80756A;
+ back:#333333;
+}
+
+pre2_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+select_style {
+ fore:#CCCCCC;
+ back:#482C25;
+}
+
+string_style {
+ fore:#049B0A;
+}
+
+class_style {
+ fore:#87CEEB;
+ back:#333333;
+}
+
+ctrl_char {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+marker_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+keyword2_style {
+ fore:#327FB3;
+}
+
+class2_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+operator_style {
+ fore:#8C8175;
+}
+
+unknown_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+calltip {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+scalar_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+char_style {
+ fore:#98FB98;
+ back:#333333;
+}
+
+here_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+regex_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+folder_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+decor_style {
+ fore:#87CEEB;
+ back:#333333;
+}
+
+scalar2_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+funct_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+brace_good {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+pre_style {
+ fore:#AB39F2;
+ modifiers:bold;
+}
+
+directive_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+btick_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+number_style {
+ fore:#44AA43;
+}
+
+margin_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+brace_bad {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
+dockey_style {
+ fore:#CCCCCC;
+ back:#333333;
+}
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/68k_assembly.68k b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/68k_assembly.68k
new file mode 100644
index 0000000..0a5aaa6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/68k_assembly.68k
@@ -0,0 +1,38 @@
+; Syntax Test file for 68k Assembly code
+; Some comments about this file
+.D0 00000000
+MS 2100 00000002
+MM 2000;DI
+ LEA.L $002100,A1
+ MOVE.L #2,-(A1)
+ BSR $00002050
+
+MM 2050;DI
+ MOVE.L (A1)+,D1
+ MOVE.L (A1),D2
+ ADD.L D1,D2
+ MOVE.L D2,D0
+ RTS
+
+.D0 00000000
+.D3 00000100
+.D4 00000200
+.D5 00000300
+MM 2000;DI
+ CMP D3,D4
+ BGE $002100
+ CMP D3,D5
+ BGE $002150
+ MOVE.L D3,D0
+.
+MM 2100;DI
+ CMP D4,D5
+ BGE $002150
+ MOVE.L D4,D0
+.
+MM 2150;DI
+ MOVE.L D5,D0
+.
+
+.PC 2000
+TR \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/Xtext.xtext b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/Xtext.xtext
new file mode 100644
index 0000000..bef01df
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/Xtext.xtext
@@ -0,0 +1,43 @@
+/*
+ Syntax Highlighting test file for Xtext language.
+*/
+grammar simpleStateMachine with someOtherGrammar hidden(WS, ML_COMMENT, SL_COMMENT)
+import "http://www.eclipse.org/emf/2002/Ecore" as ecore
+generate simpleStateMachine "http://www.simplestatemachine.com/simpleStateMachine"
+
+/* This is multiline comment with
+ a nested comment.
+ /* Nested
+ comment
+ */
+*/
+
+// Terminals
+terminal ML_COMMENT : '/*' -> '*/';
+terminal SL_COMMENT : '//' !('\n'|'\r')* ('\r'? '\n')?;
+
+terminal WS : (' '|'\t'|'\r'|'\n')+;
+
+// Parser Rules
+Machine:
+ "machine" name=ID ";"
+ (states+=State)* // testing CrossRef support in codebrowser
+ (transitions+=Transition)*
+;
+
+State:
+ "state" name=ID ";"
+;
+
+Transition:
+ "for" input=STRING oldState=[State] "->" newState=[State]
+ ("out" output=STRING)?
+ ";"
+;
+
+// Enumeration
+enum EnumerationTest:
+ first="FIRST"|
+ second="SECOND" |
+ third="THIRD"
+;
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/actionscript.as b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/actionscript.as
new file mode 100644
index 0000000..d21e70d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/actionscript.as
@@ -0,0 +1,38 @@
+// ActionScript Syntax Highlighting Test File
+// Comments are like this
+/** Multi-line comments are like these lines here
+ * @summary Documentation keywords are like this
+ */
+
+// Hello World ActionScript 2.0
+class com.example.Greeter extends MovieClip
+{
+ public function Greeter()
+ {
+ var txtHello:TextField = this.createTextField("txtHello", 0, 0, 0, 100, 100);
+ txtHello.text = "Hello World";
+ }
+}
+
+// Hellow World ActionScript 3.0
+package com.example
+{
+ import flash.text.TextField;
+ import flash.display.Sprite;
+
+ public class Greeter extends Sprite
+ {
+ public function Greeter()
+ {
+ var txtHello:TextField = new TextField();
+ txtHello.text = "Hello World";
+ addChild(txtHello);
+ }
+ }
+}
+
+// Some Variable Definitions
+var item1:String="ABC";
+var item2:Boolean=true;
+var item3:Number=12
+var item4:Array=["a","b","c"];
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ada.adb b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ada.adb
new file mode 100644
index 0000000..03731e4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ada.adb
@@ -0,0 +1,13 @@
+-- Syntax Highlighting test file for Ada
+-- Some Comments about this file
+pragma Name (Parameter_List);
+with Ada.Text_IO;
+
+procedure Hello is
+begin
+ Ada.Text_IO.Put_Line("Hello, world!");
+ Ada.Text_IO.Put_Line("Unclosed string);
+end Hello;
+
+My_Number := 1;
+_Ilegal_Identifier := 'a';
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/apache_conf.conf b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/apache_conf.conf
new file mode 100644
index 0000000..4229d09
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/apache_conf.conf
@@ -0,0 +1,31 @@
+## Syntax Highlighting Test File for Apache Configuration Files
+## Comment line
+
+# Directive and Parameter
+ServerType standalone
+
+# Directive and String
+ServerRoot "/usr"
+
+# Directive and Number
+Timeout 300
+
+# Directive and IP number
+Listen 12.34.56.78:80
+
+# Directive and Extension
+AccessFileName .htaccess
+
+# Some Extra Examples
+DefaultType text/plain
+HostnameLookups Off
+ErrorLog "/private/var/log/httpd/error_log"
+LogLevel warn
+
+<IfModule mod_setenvif.c>
+ BrowserMatch "Mozilla/2" nokeepalive
+ BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+ BrowserMatch "RealPlayer 4\.0" force-response-1.0
+ BrowserMatch "Java/1\.0" force-response-1.0
+ BrowserMatch "JDK/1\.0" force-response-1.0
+</IfModule>
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/bash_shell_script.sh b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/bash_shell_script.sh
new file mode 100644
index 0000000..a239e93
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/bash_shell_script.sh
@@ -0,0 +1,36 @@
+# Syntax Highlighting Test File for Bash
+# Comment Line
+
+# Test Assignment
+BLUE=""
+CYAN=""
+GREEN=""
+RED=""
+YELLOW=""
+OFF=""
+
+echo "${YELLOW}**${OFF} Hello World in Yellow ${YELLOW}**${OFF}"
+sleep 2
+
+# Test Scalar
+HELLO=$(Hello)
+HELLO2=${Hello}
+HELLO3=`Hello`
+
+# Test Loop/Condition
+if [ 'a' == 'a' ]; then
+ for file in $( ls ); do
+ echo $file
+ done
+fi
+
+# Test Function Definition
+function quit {
+ exit
+}
+
+# Here Statement
+cat <<EOF
+This is a multiline block for testing the
+highlighting of a here statement
+EOF
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/boo.boo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/boo.boo
new file mode 100644
index 0000000..4c38b0d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/boo.boo
@@ -0,0 +1,27 @@
+# Syntax Highlighting Test File for Boo
+# Comment line
+/* This is also a comment line but highlighting is not
+* currently supported by Editra
+*/
+// So is this but also not currently supported
+
+import System
+name = Console.ReadLine()
+print "Hello, ${name}"
+
+# Class Def
+class TestClass:
+ public Name as string
+ public Size as int
+
+# More complex class def
+public abstract class Hello:
+ abstract def Hello():
+ print "HELLO"
+
+# Function Def
+def fib():
+ a, b = 0L, 1L
+ while true:
+ yield b
+ a, b = b, a + b
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c-shell_script.csh b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c-shell_script.csh
new file mode 100644
index 0000000..a364a41
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c-shell_script.csh
@@ -0,0 +1,14 @@
+# Some Comments about this file
+
+echo "Hello, World!"
+
+# Look for the file specified as arg 1 and
+# say if we find it or not
+set f = $1
+foreach d (*)
+ if (-e $d/$f) then
+ echo FOUND: $d/$f
+ exit(0)
+ endif
+end
+echo $f not found in subdirectories
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c.c b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c.c
new file mode 100644
index 0000000..4360183
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c.c
@@ -0,0 +1,25 @@
+/** Syntax Highlighting Test File for C
+ * \brief Doxygen tag highlighting
+ */
+
+#include"stdlib.h"
+
+int main()
+{
+ int val1 = 10;
+ int val2 = val1 * 2;
+ char mychar = 'A';
+
+ for(;;)
+ {
+ val2 = val1 - 1;
+ if(val <= 0) break;
+ }
+
+ printf("Hello World, %d + %d = %d", val1, val2, val1 + val2);
+ printf("An unclosed string and unmatched brace
+}/*End Main*/
+
+void *test(void) {;}
+
+/*EOF*/
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/caml.ml b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/caml.ml
new file mode 100644
index 0000000..d4eb218
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/caml.ml
@@ -0,0 +1,16 @@
+(* Syntax Highlighting Test File for Caml *)
+(* Some Comments about this file *)
+
+(* Hello World *)
+print_endline "Hello world!";;
+
+(* Calculate Fibbonacci Value of N *)
+let rec fib n =
+ if n < 2 then 1 else fib(n-1) + fib(n-2);;
+let main () =
+ let arg = int_of_string Sys.argv.(1) in
+ print_int(fib arg);
+ print_newline();
+ exit 0;;
+main ();;
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cascading_style_sheet.css b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cascading_style_sheet.css
new file mode 100644
index 0000000..54ad496
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cascading_style_sheet.css
@@ -0,0 +1,52 @@
+/* Comments About This File */
+
+/* Directive */
+@charset "iso-8859-1";
+
+/*** Plain tag definition ***/
+a { text-decoration : none; }
+
+/** Tag:psuedo class def **/
+a:link { color : #456; }
+
+/** Tag/Attribute def **/
+input[type="submit"] {
+ border: 2px #369 outset;
+ background-color: #369;
+ color: white;
+}
+
+/** Class def **/
+.tiny {
+ font-family : "Bitstream Vera", "Vera", "Trebuchet MS", sans-serif;
+ color : #666;
+ font-size : 10px;
+ line-height : 10px;
+}
+
+/*** Ids defs ***/
+#docpane {
+ width: 98%;
+ padding-top: 10px;
+ margin: 5px;
+}
+
+/*** uses some css 2 keywords ****/
+form input.objectA {
+ position: absolute;
+ text-align: left;
+ width: 550px;
+ z-index: 2;
+}
+
+/** Syntax Error/Non WC3 compliant css **/
+a:what { color: red; }
+
+/** Important **/
+.hide { display: none !important; }
+
+.hide p { color: blue; }
+
+.hide .hidedecendant { color: red; }
+
+.hide #someID { color: yellow; }
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cilk.cilk b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cilk.cilk
new file mode 100644
index 0000000..3ca8e60
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cilk.cilk
@@ -0,0 +1,15 @@
+// Syntax Highlighting Test file for Cilk
+// Comments are like this
+/* And This */
+
+cilk int fib (int n) {
+ if (n<2) return (n);
+ else {
+ int x,y;
+ spawn x = fib(n-1);
+ spawn y = fib(n-2);
+ sync;
+ return (x+y);
+ }
+}
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cobra.cobra b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cobra.cobra
new file mode 100644
index 0000000..914d593
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cobra.cobra
@@ -0,0 +1,25 @@
+# Syntax Highlighting Test File for Cobra
+# Comments look like this
+
+"""
+DocString
+
+"""
+
+class Hello
+
+ # Class variables
+ var _name as String
+ var _verbosity = 1
+
+ def init(name as String, verbosity as Int)
+ _name = name
+ _verbosity = verbosity
+
+ .define('quit', 'built-in:quit')
+
+ def main is shared
+ print 'Hello, world.'
+
+ def quit
+ _didQuit = true
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/coldfusion.cfm b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/coldfusion.cfm
new file mode 100644
index 0000000..1d1ae99
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/coldfusion.cfm
@@ -0,0 +1,43 @@
+<!--- Some comments about this file --->
+<!-- Support is still a work in progress -->
+
+<cfscript>
+function helloWorld() {
+ var greeting = "Hello World!";
+ return greeting;
+}
+</cfscript>
+
+<cfoutput>#helloWorld()#</cfoutput>
+
+<cfset Foo1 = "Hello">
+<cfset Foo2 = "Hello World">
+
+<cfoutput>
+<!--- pound signs output the returned value --->
+<p>The first position of #Foo1# in #Foo2# is #Find(Foo1,Foo2)#</p>
+</cfoutput>
+<CFSCRIPT>
+/**
+ * Returns a list of all factors for a given
+ * positive integer.
+ *
+ * @param integer Any non negative integer greater
+ * than or equal to 1.
+ * @return Returns a comma delimited list
+ * of values.
+ * @author Rob Brooks-Bilson (rbils@amkor.com)
+ * @version 1.1, September 6, 2001
+ */
+function factor(integer)
+{
+ Var i=0;
+ Var Factors = "";
+ for (i=1; i LTE integer/2; i=i+1) {
+ if (Int(integer/i) EQ integer/i) {
+ Factors = ListAppend(Factors, i);
+ }
+ }
+ Return ListAppend(Factors, integer);
+}
+</CFSCRIPT>
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cpp.cpp b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cpp.cpp
new file mode 100644
index 0000000..9c4af41
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cpp.cpp
@@ -0,0 +1,30 @@
+/** Syntax Highlighting test file for C++
+ * \brief Doxygen tag highlighting
+ */
+#include<iostream>
+#include<cstdlib>
+
+using namespace std;
+
+int main(void)
+{
+ cout << "\nHello World" << endl;
+ cout << "\nUnclosed String << endl;
+
+ // One line comment
+ int a = 0;
+
+ exit(a);
+}
+
+int add(int x, int y)
+{
+ return x + y;
+}
+
+void TestClass::Foo(int &nVal)
+{
+ nVal++;
+}
+
+// EOF
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/csharp.cs b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/csharp.cs
new file mode 100644
index 0000000..dc35b7c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/csharp.cs
@@ -0,0 +1,30 @@
+// C# Syntax Highlighting Test File
+// Comments are like this
+/** Multiline comments are like this
+ * @summary <- Documentation Keyword
+ * \brief <- Doxygen style keyword
+ */
+
+using System;
+
+#region Foo
+class Foo
+{
+ void Create() {}
+}
+#endregion Foo
+
+// Hello World
+class HelloClass
+{
+ static void Main()
+ {
+ System.Console.WriteLine("Hello, world!");
+ }
+
+ public static void PrintPlusOne(int x)
+ {
+ System.Console.WriteLine(x + 1);
+ }
+}
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/d.d b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/d.d
new file mode 100644
index 0000000..11fbac4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/d.d
@@ -0,0 +1,59 @@
+// Syntax Highlighting test file for D programming language
+// A single line comment
+/* A multi-line comment about this file.
+ * Adopted from http://en.wikipedia.org/wiki/D_%28programming_language%29
+ */
+
+import std.stdio;
+int main(char[][] args)
+{
+ writefln("Hello World");
+
+ // Strings are denoted as a dynamic array of chars 'char[]'
+ // auto type inference and built-in foreach
+ foreach(argc, argv; args)
+ {
+ auto cl = new CmdLin(argc, argv); // OOP is supported
+ writefln(cl.argnum, cl.suffix, " arg: %s", cl.argv); // user-defined class properties.
+
+ delete cl; // Garbage Collection or explicit memory management - your choice
+ }
+
+ // Nested structs, classes and functions
+ struct specs
+ {
+ // all vars automatically initialized to 0 at runtime
+ int count, allocated;
+ // however you can choose to avoid array initialization
+ int[10000] bigarray = void;
+ }
+
+ specs argspecs(char[][] args)
+ // Optional (built-in) function contracts.
+ in
+ {
+ assert(args.length > 0); // assert built in
+ }
+ out(result)
+ {
+ assert(result.count == CmdLin.total);
+ assert(result.allocated > 0);
+ }
+ body
+ {
+ specs* s = new specs;
+ // no need for '->'
+ s.count = args.length; // The 'length' property is number of elements.
+ s.allocated = typeof(args).sizeof; // built-in properties for native types
+ foreach(arg; args)
+ s.allocated += arg.length * typeof(arg[0]).sizeof;
+ return *s;
+ }
+
+ // built-in string and common string operations, eg. '~' is concatenate.
+ char[] argcmsg = "argc = %d";
+ char[] allocmsg = "allocated = %d";
+ writefln(argcmsg ~ ", " ~ allocmsg,
+ argspecs(args).count,argspecs(args).allocated);
+ return 0;
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/diff_file.diff b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/diff_file.diff
new file mode 100644
index 0000000..660aefe
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/diff_file.diff
@@ -0,0 +1,39 @@
+--- Syntax Highlighting Test File for Diff results
+--- Comment Lines are like this
+--- cpp.cpp 2007-06-26 07:14:22.000000000 -0500
++++ hello_diff.cpp 2007-08-06 17:01:47.000000000 -0500
+@@ -2,24 +2,29 @@
+ *
+ */
+ #include<iostream>
+-#include<cstdlib>
+
+ using namespace std;
+
+ int main(void)
+ {
+- cout << "\nHello World" << endl;
++ cout << "\nHello World!" << endl;
+ cout << "\nUnclosed String << endl;
+
+ // One line comment
+ int a = 0;
+-
+- exit(a);
++ cout << add(a, 22) << endl;
+ }
+
+-int add(x, y)
++// Add two numbers
++int add(int x, int y)
+ {
+ return x + y;
+ }
+
++// Subtract two numbers
++int sub(int x, int y)
++{
++ return x - y;
++}
++
+ // EOF \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/django.django b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/django.django
new file mode 100644
index 0000000..203f5a7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/django.django
@@ -0,0 +1,25 @@
+<!-- Syntax Highlighting Test File for Django -->
+<!-- Comments are like this -->
+
+<!-- base.html -->
+<html>
+ <head>
+ <title>{% block head_title %}mysite.com{% endblock %}</title>
+ </head>
+ <body>
+ </body>
+</html>
+
+<!-- application/model_index.html -->
+{% extends "base.html" %}
+{% block head_title %}{{ object.title|title }} &amp;ndash; {{ block.super }}{% endblock %}
+
+<!-- result, when {{ object.title }} was "My test entry" -->
+<html>
+ <head>
+ <title>My Test Entry &amp;ndash; mysite.com</title>
+ </head>
+ <body>
+ <p class="hello">Hello</p>
+ </body>
+</html>
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dos_batch_script.bat b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dos_batch_script.bat
new file mode 100644
index 0000000..60768d1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dos_batch_script.bat
@@ -0,0 +1,23 @@
+:: Syntax Highlighting Test File for Dos Batch Scripts
+:: Comment Line
+
+:BEGIN
+set HELLO="WORLD"
+set WORLD="HELLO"
+set HELLOWORLD="%WORLD% %HELLO%"
+
+if "%1" == "/?" goto HELP
+if "%1" == "go" goto EXECUTE
+
+:HELP
+echo .
+echo Here is test file to show some dos batch highlighting
+echo .
+goto END
+
+:EXECUTE
+echo .
+echo %HELLOWORLD%
+echo .
+
+:END
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dot.dot b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dot.dot
new file mode 100644
index 0000000..c1bc0c8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dot.dot
@@ -0,0 +1,32 @@
+// Syntax Highlighting Test file for DOT
+// Some Comments about this file
+// Sample graphviz DOT file from
+// http://www.graphviz.org/Gallery/directed/cluster.html
+
+digraph "Example" {
+
+ subgraph cluster_0 {
+ style=filled;
+ color=lightgrey;
+ node [style=filled,color=white];
+ a0 -> a1 -> a2 -> a3;
+ label = 'process #1';
+ }
+
+ subgraph cluster_1 {
+ node [style=filled];
+ b0 -> b1 -> b2 -> b3;
+ label = "process #2";
+ color=blue
+ }
+ begin -> a0;
+ begin -> b0;
+ a1 -> b3;
+ b2 -> a3;
+ a3 -> a0;
+ a3 -> end;
+ b3 -> end;
+
+ begin [shape=Mdiamond];
+ end [shape=Msquare];
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dsp56k_assembly.56k b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dsp56k_assembly.56k
new file mode 100644
index 0000000..9e9274d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dsp56k_assembly.56k
@@ -0,0 +1,31 @@
+;*****************************************************************************
+; DSP56K Highlighting Test File
+; Comments look like this
+;*****************************************************************************
+ PAGE 110,60,1,1
+ TABS 4
+;*****************************************************************************
+; DEFINITIONS & POINTERS
+;*****************************************************************************
+START EQU $000100 ; program start location
+SERIAL EQU $2 ; serial number location
+
+TXD EQU $FFFFBC ; ESSI0 Transmit Data Register 0
+RXD EQU $FFFFB8 ; ESSI0 Receive Data Register
+SSISR EQU $FFFFB7 ; ESSI0 Status Register
+CRB EQU $FFFFB6 ; ESSI0 Control Register B
+CRA EQU $FFFFB5 ; ESSI0 Control Register A
+PCRC EQU $FFFFBF ; Port C (ESSI_0) control register
+PCTL EQU $FFFFFD ; PLL control register
+TXREG EQU $FFFF89 ; external TX register
+RXREG EQU $FFFF8A ; external RX register
+
+PDRB EQU $FFFFC9 ; Port B (HOST) GPIO data
+PRRB EQU $FFFFC8 ; Port B (HOST) GPIO direction
+PCRB EQU $FFFFC4 ; Port B (HOST) control register
+
+PCRE EQU $FFFF9F ; Port E (SCI) control register
+PRRE EQU $FFFF9E ; Port E (SCI) data direction
+PDRE EQU $FFFF9D ; Port E (SCI) data
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/editra_style_sheet.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/editra_style_sheet.ess
new file mode 100644
index 0000000..9412e3f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/editra_style_sheet.ess
@@ -0,0 +1,23 @@
+/* Syntax Highlighting Test File for Editra Style Sheets
+ * Comments are like this
+ */
+
+default_style {
+ fore: #FFFFFF;
+ back: #000000;
+ face: %(mono)s;
+ size: %(size)d;
+}
+
+keyword_style {
+ fore: #A52B2B bold;
+ back: #F6F6F6;
+ size: %(size)d;
+}
+
+/* Definition with a bad attribute size5 */
+class_style {
+ fore: #2E8B57 bold;
+ back: #F6F6F6;
+ size5: %(size)d;
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/edje.edc b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/edje.edc
new file mode 100644
index 0000000..215d078
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/edje.edc
@@ -0,0 +1,70 @@
+// Syntax Highlighting test file for Edje
+// Some comments about this file
+/********************************************************************
+ * Multi line comments are like this.
+ ********************************************************************/
+#define FRAME LOSSY 60
+
+images {
+ image: "eracnid.png" LOSSY 80;
+ image: "shadow.png" COMP;
+ image: "E-wavy_000001.png" FRAME;
+ image: "E-wavy_000002.png" FRAME;
+ image: "E-wavy_000003.png" FRAME;
+}
+
+collections {
+ group {
+ name: "desktop/background";
+ parts {
+ part {
+ name: "background_image";
+ mouse_events: 0;
+ description {
+ state: "default" 0.0;
+ align: 0.5 0.5;
+ image {
+ normal: "eracnid.png";
+ }
+ }
+ }
+ part {
+ name: "logo";
+ mouse_events: 0;
+ description {
+ aspect: 3.33 3.33;
+ state: "default" 0.0;
+ min: 112 148;
+ max: 200 269;
+ align: 1.0 1.0;
+ rel1 {
+ relative: 0.796 0.355;
+ offset: 0 0;
+ to, "background_image";
+ }
+ rel2 {
+ relative: 0.796 0.355;
+ offset: 0 0;
+ to, "background_image";
+ }
+ image {
+ normal: "E-wavy_000001.png";
+ tween: "E-wavy_000002.png";
+ tween: "E-wavy_000003.png";
+ }
+ }
+ }
+ }
+ programs {
+ program {
+ name: "logo_animate";
+ signal: "show";
+ source: "";
+ action: STATE_SET "default" 0.0;
+ transition: LINEAR 4.0;
+ target: "logo";
+ after: "logo_animate";
+ }
+ }
+ }
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/eiffel.e b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/eiffel.e
new file mode 100644
index 0000000..464cc84
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/eiffel.e
@@ -0,0 +1,27 @@
+-- Syntax Highlighting Test File for Eiffel
+-- Some Comments about this file
+
+class
+ HELLO_WORLD
+create
+ make
+feature
+ make
+ do
+ io.put_string ("Hello, world!")
+ io.put_new_line
+ io.put_string('Unclosed String
+ end
+end
+
+-- Run the HelloWorld program
+
+program hello_prog
+
+root
+ HELLO_WORLD: "make"
+cluster
+ "./"
+end
+ include "$EIFFEL_S/library/lib.pdl"
+end -- hello_prog
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/erlang.erl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/erlang.erl
new file mode 100644
index 0000000..c1f8138
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/erlang.erl
@@ -0,0 +1,29 @@
+%% Syntax Highlighting Test file for Erlang
+%% Some comments about this file
+
+%% quicksort:qsort(List)
+%% Sort a list of items
+-module(quicksort).
+-export([qsort/1]).
+
+qsort([]) -> [];
+qsort([Pivot|Rest]) ->
+ qsort([ X || X <- Rest, X < Pivot]) ++ [Pivot] ++ qsort([ Y || Y <- Rest, Y >= Pivot]).
+
+%% --------------------------------------------------------------------- %%
+%% Sort a list by length
+-module(listsort).
+-export([by_length/1]).
+
+by_length(Lists) ->
+ F = fun(A,B) when is_list(A), is_list(B) ->
+ length(A) < length(B)
+ end,
+ qsort(Lists, F).
+
+ qsort([], _)-> [];
+ qsort([Pivot|Rest], Smaller) ->
+ qsort([ X || X <- Rest, Smaller(X,Pivot)], Smaller)
+ ++ [Pivot] ++
+ qsort([ Y ||Y- Rest, not(Smaller(Y, Pivot))], Smaller).
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ferite.fe b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ferite.fe
new file mode 100644
index 0000000..010e2af
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ferite.fe
@@ -0,0 +1,66 @@
+// Syntax Highlighting Test File for Ferite
+// Comments are like this
+/** Multiline comments are like this
+ * @summary Documentation keyword
+ * \brief Another Doc keyword
+ */
+
+// Hello World
+uses "console";
+Console.println( "Hello World" );
+Console.println( "Unclosed String
+
+// Types
+number a;
+string b;
+array c;
+
+a = 2;
+b = "2";
+c = [ a, b ];
+
+// Function
+function f( number x ) {
+ if( x > 1 ) {
+ return f( x - 1 ) * 2;
+ }
+ return 1;
+}
+Console.println( f(10) );
+
+// Class
+class A {
+ string value;
+
+ function constructor() {
+ .value = "Class.A";
+ }
+
+ function f() {
+ return .value;
+ }
+}
+
+// Some Namespace defs
+namespace A {
+ function f() {
+ return "A.f";
+ }
+}
+
+namespace modifies A {
+ function g() {
+ return "A.g";
+ }
+}
+
+// Protocols
+protocol C {
+ function getX();
+ function getY();
+}
+
+class A implements C {
+ function getX() { return "X"; }
+ function getY() { return "Y"; }
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/flagship.prg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/flagship.prg
new file mode 100644
index 0000000..9889c7c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/flagship.prg
@@ -0,0 +1,23 @@
+// Syntax Highlighting test file for Flagship/XBase programming languages
+// Some comments about this file
+/* A multline comment about some stuff in this
+ * file.
+ */
+
+// Hello World in Clipper
+? "Hello World!"
+
+
+USE address ALIAS adr SHARED NEW
+SET COLOR TO "W+/B,GR+/R,W/B,W/B,GR+/BG"
+cls
+@ 1, 0 SAY "Id No. " GET adr->IdNum PICT "999999" VALID IdNum > 0
+@ 3, 0 SAY "Company" GET adr->Company
+@ 3,35 SAY "Branch" GET adr->Branch WHEN !empty(adr->Company)
+@ 4, 0 SAY "Name " GET adr->Name VALID !empty(adr->Name)
+@ 4,35 SAY "First " GET adr->First
+@ 6, 0 SAY "Country" GET adr->Country PICTURE "@!"
+@ 8, 0 SAY "Zip " GET adr->Zip PICT "@!" VALID !empty(adr->Zip)
+@ 9, 0 SAY "City " GET adr->City
+@ 10, 0 SAY "Street " GET adr->Street
+READ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/forth.4th b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/forth.4th
new file mode 100644
index 0000000..44cade2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/forth.4th
@@ -0,0 +1,10 @@
+\ Test file for Forth Syntax
+\ Comments are like this
+10 constant ten
+: .hello ( -- )
+ s" Hello World" type [char] ! emit ;
+: hello ( flag -- )
+ ?dup if .hello then drop ;
+hello
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_77.for b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_77.for
new file mode 100644
index 0000000..73181c0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_77.for
@@ -0,0 +1,42 @@
+* Fortran 77 Syntax Test File
+* Some Comments about this file
+
+* Hello World
+
+ PROGRAM HELLOW
+ PRINT '(A)', 'Hello, world'
+ STOP
+ END
+
+* euclid.f (FORTRAN 77)
+* Find greatest common divisor using the Euclidean algorithm
+
+ PROGRAM EUCLID
+ PRINT *, 'A?'
+ READ *, NA
+ IF (NA.LE.0) THEN
+ PRINT *, 'A must be a positive integer.'
+ STOP
+ END IF
+ PRINT *, 'B?'
+ READ *, NB
+ IF (NB.LE.0) THEN
+ PRINT *, 'B must be a positive integer.'
+ STOP
+ END IF
+ PRINT *, 'The GCD of', NA, ' and', NB, ' is', NGCD(NA, NB), '.'
+ STOP
+ END
+
+ FUNCTION NGCD(NA, NB)
+ IA = NA
+ IB = NB
+ 1 IF (IB.NE.0) THEN
+ ITEMP = IA
+ IA = IB
+ IB = MOD(ITEMP, IB)
+ GOTO 1
+ END IF
+ NGCD = IA
+ RETURN
+ END
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_95.f95 b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_95.f95
new file mode 100644
index 0000000..3314b78
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_95.f95
@@ -0,0 +1,45 @@
+! Fortran 95 Syntax Test File
+! Some comments about this file
+
+! Hello World
+program HelloWorld
+ write (*,*) 'Hello, world!' ! This is an inline comment
+end program HelloWorld
+
+program HelloWorld2
+ ihello = 0
+ 1 if (ihello.NE.10) ! This line shows the label style
+ write (*,*) "Hello, World2!"
+ ihello = ihello + 1
+ goto 1
+ end if
+end program HelloWord2
+
+!----------------------------------------------------------
+subroutine Swap_Real(a1, a2)
+
+ implicit none
+
+! Input/Output
+ real, intent(inout) :: a1(:), a2(:)
+
+! Locals
+ integer :: lb(1), & !Lower bound
+ ub(1) !Upper bound
+ integer i
+ real a
+
+! Get bounds
+ lb = lbound(a1)
+ ub = ubound(a1)
+
+! Swap
+ do i = lb(1), ub(1)
+ a = a1(i)
+ a1(i) = a2(i)
+ a2(i) = a
+ end do
+
+end subroutine Swap_Real
+
+!----------------------------------------------------------
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/glsl.glsl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/glsl.glsl
new file mode 100644
index 0000000..a6ef335
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/glsl.glsl
@@ -0,0 +1,19 @@
+// Syntax Highlighting Test File for GLSL
+// Comment Text
+
+#define MAX_JOINT_NUM 36
+#define MAX_LIGHT_NUM 8
+
+uniform mat4 JointTransform[MAX_JOINT_NUM];
+
+void main()
+{
+ int index;
+ float dist;
+ mat4 ModelTransform = gl_ModelViewProjectionMatrix;
+ index = int(gl_Color.r * 255.99);
+ mat4 vertTran = JointTransform[index - 1];
+ index = int(gl_Color.g * 255.99);
+ if(index > 0)
+ vertTran += JointTransform[index - 1];
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/groovy.groovy b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/groovy.groovy
new file mode 100644
index 0000000..256331e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/groovy.groovy
@@ -0,0 +1,73 @@
+/**
+ * Mortgage Calculator
+ * @author: Jeremy Rayner
+ * based on algorithms by Jeff Louie, Dr W Carlini and Newton
+ */
+
+println "__..::~~'''~~::..__"
+println "Mortgage Calculator"
+println "~~~~~~~~~~~~~~~~~~~"
+println "Please input 3 of the 4 values in your mortgage calculation"
+println "This program will then calculate the value you leave blank"
+println ""
+
+def variables = [
+ "Amount of mortgage" : 0.0,
+ "Annual interest rate (%)" : 0.0,
+ "Loan duration (months)" : 0.0,
+ "Monthly payments" : 0.0
+]
+
+for (entry in variables.entrySet()) {
+ print("${entry.key}:")
+ def userInput = System.in.readLine()
+ if ("" == userInput) {
+ valueToCalculate = entry.key
+ } else {
+ entry.value = userInput.toDouble()
+ }
+}
+
+println "$valueToCalculate = ${calculateValueOf(valueToCalculate)}"
+
+def calculateValueOf(valueToCalculate) {
+ def result = 0
+ def principal = variables["Amount of mortgage"]
+ def interest = variables["Annual interest rate (%)"] / 1200
+ def months = variables["Loan duration (months)"]
+ def payment = variables["Monthly payments"]
+
+ switch (valueToCalculate) {
+ case "Amount of mortgage":
+ result = 1 + interest
+ result = 1/Math.pow(result,months)
+ result = ((1-result)/interest) * payment
+ break
+ case "Loan duration (months)":
+ result = (1 - (principal * interest / payment))
+ result = Math.log(result)
+ result = - result / Math.log(1 + interest)
+ break
+ case "Monthly payments":
+ result = 1 + interest
+ result = 1 / Math.pow(result,months)
+ result = (principal * interest) / (1 - result)
+ break
+ case "Annual interest rate (%)":
+ result = payment / principal
+ def diff = 100; def accuracy = 0.00001; def maxIterations = 1000
+ def index = 0
+ while ((diff > accuracy) && (index < maxIterations)) {
+ def temp = result
+ def numerator = (principal * temp / payment) + Math.pow((1 + temp), -months) - 1
+ def denominator= (principal / payment) - months * Math.pow((1 + temp), (-months - 1))
+ result = temp - (numerator / denominator)
+ diff = result - temp
+ diff = Math.abs(diff)
+ index++
+ }
+ result *= 1200
+ break
+ }
+ return result
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/gui4cli.gui b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/gui4cli.gui
new file mode 100644
index 0000000..4634f0a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/gui4cli.gui
@@ -0,0 +1,20 @@
+// Syntax Highlighting test file for Gui4Cli
+// Some Comments about this file
+// Note lexer only works correctly with CRLF eol chars
+
+WINDOW 10 10 180 20 'IconBar'
+ Winattr style clear/topmost/move/remsize/noborder/border/tool
+ winattr background color 200/200/220
+
+// Control
+if $test = 0
+ cutvar buff cut char $wrapWidth buff2
+else
+ cutvar buff cut char $test buff2
+endif
+
+// Event
+xOnKey F1
+ run :somthing
+ lv add $somthing
+ add
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haskell.hs b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haskell.hs
new file mode 100644
index 0000000..6004c4c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haskell.hs
@@ -0,0 +1,39 @@
+-- Syntax Highlighting test file for Haskell
+-- Some comments about this file
+
+-- Hello World in Haskell
+putStrLn "Hello, Haskell"
+
+-- Simple do structure
+do putStrLn "What is 2 + 2?"
+ x <- readLn
+ if x == 4
+ then putStrLn "You're right!"
+ else putStrLn "You're wrong!"
+
+-- Class def
+class Num a where
+ (+) :: a -> a -> a
+ negate :: a -> a
+
+-- Data Declaration
+data Set a = NilSet
+ | ConsSet a (Set a)
+
+-- Import statement
+import somthing
+
+-- Instance
+instance Num Int where
+ x + y = addInt x y
+ negate x = negateInt x
+
+-- Module
+module Tree ( Tree(Leaf,Branch), fringe ) where
+
+data Tree a = Leaf a | Branch (Tree a) (Tree a)
+
+fringe :: Tree a -> [a]
+fringe (Leaf x) = [x]
+fringe (Branch left right) = fringe left ++ fringe right
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haxe.hx b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haxe.hx
new file mode 100644
index 0000000..5bb56bb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haxe.hx
@@ -0,0 +1,32 @@
+// Syntax Highlighting Test File for haXe
+// Comments are like this
+/* Mulitline comments are like
+ * this block of text
+ */
+
+// Ints / Floats
+0;
+-1234;
+0xFF00;
+123.4;
+
+// Strings
+"Hello World";
+"Unclosed String;
+
+// Constants
+true;
+false;
+null;
+
+// Class Def
+package my.pack;
+
+class MyClass {
+ var id : Int;
+ static var name : String = "MyString";
+ function foo() : Void {
+ }
+ static function bar( s : String, v : Bool ) : Void {
+ }
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/html.html b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/html.html
new file mode 100644
index 0000000..8342f22
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/html.html
@@ -0,0 +1,39 @@
+<!-- Syntax Highlighting Test File for Html -->
+<%@ LANGUAGE=VBScript %>
+<% OPTION EXPLICIT %>
+<!-- Embedded ASP -->
+<%
+ Dim sMessage
+ Dim bIncludeJavaScript
+
+ sMessage = "Hello World" 'This is the message to be displayed
+
+ 'Getting a request value that defines if the javascript part should be included
+ bIncludeJavaScript = FALSE
+ If (Request("withJavaScript") = "Y") Then
+ bIncludeJavaScript = TRUE
+ End If
+%>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <!-- Some Comments about this file -->
+ <title>Hello World</title>
+ <link href="hello.css" rel="stylesheet" type="text/css">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <script language="JavaScript" type="text/JavaScript">
+ <!-- Some Embedded JavaScript --!>
+ <!--
+ function MM_swapImgRestore() { //v3.0
+ var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
+ }
+ //-->
+ </script>
+ </head>
+ <body>
+ <div>
+ <h1>Hello World HTML</h1>
+ <p class="bigHello">HELLO HELLO HELLO</p>
+ </div>
+ </body>
+</html>
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/inno_setup_script.iss b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/inno_setup_script.iss
new file mode 100644
index 0000000..b986085
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/inno_setup_script.iss
@@ -0,0 +1,34 @@
+; Syntax Highlighting Test File for Inno Setup Scripts
+; Some comments about this file
+
+; Preprocessor
+#pragma verboselevel 9
+#define Debug
+
+; Sections
+[Setup]
+AppName=My Program
+AppVerName=My Program version 1.5
+DefaultDirName={code:MyConst}\My Program
+DefaultGroupName=My Program
+UninstallDisplayIcon={app}\MyProg.exe
+InfoBeforeFile=Readme.txt
+OutputDir=userdocs:Inno Setup Examples Output
+
+[Files]
+Source: "MyProg.exe"; DestDir: "{app}"; Check: MyProgCheck; BeforeInstall: BeforeMyProgInstall('MyProg.exe'); AfterInstall: AfterMyProgInstall('MyProg.exe')
+Source: "MyProg.chm"; DestDir: "{app}"; Check: MyProgCheck; BeforeInstall: BeforeMyProgInstall('MyProg.chm'); AfterInstall: AfterMyProgInstall('MyProg.chm')
+Source: "Readme.txt"; DestDir: "{app}"; Flags: isreadme
+
+[Code]
+var
+ MyProgChecked: Boolean;
+ MyProgCheckResult: Boolean;
+ FinishedInstall: Boolean;
+
+function InitializeSetup(): Boolean;
+begin
+ Result := MsgBox('InitializeSetup:' #13#13 'Setup is initializing. Do you really want to start setup?', mbConfirmation, MB_YESNO) = idYes;
+ if Result = False then
+ MsgBox('InitializeSetup:' #13#13 'Ok, bye bye.', mbInformation, MB_OK);
+end;
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/issuelist.isl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/issuelist.isl
new file mode 100644
index 0000000..2300494
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/issuelist.isl
@@ -0,0 +1,26 @@
+; Syntax Highlighting Test file for IssueList
+; Comments look like this
+
++ This item is done
+- This is still open
+; This is a cancelled item, so it is shown in gray
+? This item still needs to be clarified
+ There are some questions open to solve it.
+ In detail:
+ - Is it too expensive ?
+ + Can it technically be done ?
+
+- Technically it is quite challenging,
+ and some details are yet open.
+ But can be surely solved.
+
+So there are some more colors:
+
+# for maybe something important
+. Because blue looks cool
+
+~ This could be used for deep-red items or so
+
+;;; Local Variables:
+;;; mode: outline
+;;; End:
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/java.java b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/java.java
new file mode 100644
index 0000000..c41ae44
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/java.java
@@ -0,0 +1,42 @@
+// Syntax Highlighting Test File For Java
+// Comment Line
+
+/*
+ * HelloWorld Using Swing
+ */
+import javax.swing.*;
+
+public class HelloWorldSwing {
+ /**
+ * Create the GUI and show it. For thread safety,
+ * this method should be invoked from the
+ * event-dispatching thread.
+ */
+ private static void createAndShowGUI() {
+ //Create and set up the window.
+ JFrame frame = new JFrame("HelloWorldSwing");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ //Add the ubiquitous "Hello World" label.
+ JLabel label = new JLabel("Hello World");
+ frame.getContentPane().add(label);
+
+ //Display the window.
+ frame.pack();
+ frame.setVisible(true);
+
+ a = 1000;
+ // unclosed string
+ System.out.println("test);
+ }
+
+ public static void main(String[] args) {
+ //Schedule a job for the event-dispatching thread:
+ //creating and showing this application's GUI.
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ createAndShowGUI();
+ }
+ });
+ }
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/javascript.js b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/javascript.js
new file mode 100644
index 0000000..5f3707d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/javascript.js
@@ -0,0 +1,16 @@
+// Syntax Highlighting Test File for JavaScript
+// Some Comments about this file
+
+function HelloAlert ()
+{
+ alert("Hello World!")
+}
+
+function count(to)
+{
+ for (i = 0; i <= to; i++)
+ {
+ document.write("The number is " + i)
+ document.write("<br />")
+ }
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/kix.kix b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/kix.kix
new file mode 100644
index 0000000..fe3787e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/kix.kix
@@ -0,0 +1,27 @@
+; Syntax Highighting test file for KIXtart scripts
+; Some comments about this file
+
+Dim $Type, $S, $J, $R
+
+If KeyExist("HKCU\Software\Hello") = 1
+ $Type = Readtype("HKCU\Software\Hello","World")
+ $R = ReadValue("HKCU\Software\Hello", "World2")
+
+ Select
+ Case $Type = "Reg_Multi_SZ"
+ $S = Split($R,"|")
+ $J = Join($S," ")
+ Case $Type = "Reg_SZ"
+ $J = $R
+ Case 1
+ @Error = 5
+ EndSelect
+
+ If $J = "HelloWorld"
+ ? "We have a match. The string returned was: " $J
+ Else
+ ? "No match found. The string returned was: " $J
+ EndIf
+Else
+ Exit 1
+EndIf
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/korn_shell_script.ksh b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/korn_shell_script.ksh
new file mode 100644
index 0000000..4600ee3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/korn_shell_script.ksh
@@ -0,0 +1,11 @@
+# Syntax Highlighting Test File for Korn Shell
+# Some comments about this file
+
+export FRIENDS="Jon Kosuke Bill Sandra"
+for FRIEND in ${FRIENDS}
+do
+ # each loop say hello
+ echo "HELLO " $FRIEND
+done
+
+exit 0
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/latex.tex b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/latex.tex
new file mode 100644
index 0000000..6ac3502
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/latex.tex
@@ -0,0 +1,10 @@
+% Syntax Highlighting Test File For LaTeX
+% Some Comments About This File
+\documentclass{article}
+\title{Lets Say Hello}
+\author{Jane Doe}
+\date{April 2007}
+\begin{document}
+ \maketitle
+ Hello world!
+\end{document}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lisp.lisp b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lisp.lisp
new file mode 100644
index 0000000..30bc069
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lisp.lisp
@@ -0,0 +1,26 @@
+; Syntax Highlighting Test File for Lisp
+; Comment Line
+
+; Lisp funciton and keyword test
+(defpackage :mypackage
+ (:use :common-lisp :cffi))
+
+; hello version 1
+(defun hello-word1 ()
+ (print (list 'HELLO 'WORLD)))
+
+; hello version 2
+(defun hello-world ()
+ (format t "hello world~%"))
+
+; Lets do some factorials too
+(defun factorial (N)
+ (if (= N 1)
+ 1
+ (* N (factorial (- N 1)))))
+
+; Fibonacci numbers are fun too
+(defun fibonacci (N)
+ (if (or (zerop N) (= N 1))
+ 1
+ (+ (fibonacci (- N 1)) (fibonacci (- N 2)))))
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lout.lt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lout.lt
new file mode 100644
index 0000000..23c299e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lout.lt
@@ -0,0 +1,34 @@
+ # Lexer Test File for Basser Lout
+ # http://en.wikipedia.org/wiki/Lout
+ # Some Comments about this file
+
+ # Use the `doc' document class and its default style.
+ @SysInclude { doc }
+
+ @Document
+ @InitialFont { Times Base 10p }
+ //
+
+ # Beginning of document contents.
+ @Text @Begin
+
+ # Paragraph with a number of differen't keywords, symbols and strings in it
+ @PP
+ Hello Word this is a paragraph. One can easily embed @B { bold } or
+ @I { italic } text. One can also easily change the style of
+ text, such as { Helvetica Base } @Font { changing the font
+ being used } Here is a string @Code "@Font" and a string that
+ is not closed @Code "@Font.
+
+ @BeginSections
+ @Section @Title { The First Section }
+ @Begin
+
+ @PP
+ This is the content of a section.
+
+ @End @Section
+ @EndSections
+
+ @End @Text
+ # End of the document.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lua.lua b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lua.lua
new file mode 100644
index 0000000..8f65a80
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lua.lua
@@ -0,0 +1,38 @@
+-- Lua Syntax Test File
+-- Some comments about this file
+
+-- Hello World Program
+print "Hello World"
+print "An Open String
+
+-- Factorial Calculator
+function factorial(n)
+ if n == 0 then
+ return 1
+ end
+ return n * factorial(n - 1)
+end
+
+-- Fibonacci Numbers
+fibs = { 1, 1 }
+setmetatable(fibs, {
+ __index = function(name, n)
+ name[n] = name[n - 1] + name[n - 2]
+ return name[n]
+ end
+})
+
+-- string buffer implementation
+function newbuf ()
+ local buf = {
+ _buf = {},
+ clear = function (self) self._buf = {}; return self end,
+ content = function (self) return table.concat(self._buf) end,
+ append = function (self, s)
+ self._buf[#(self._buf) + 1] = s
+ return self
+ end,
+ set = function (self, s) self._buf = {s}; return self end,
+ }
+ return buf
+end \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/makefile.mak b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/makefile.mak
new file mode 100644
index 0000000..c78e3bb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/makefile.mak
@@ -0,0 +1,20 @@
+# Syntax Highlighting Test File for Makefile
+# Some more comments about this file
+
+# Some Identifiers and Preproccessor stuff
+!ifndef DEBUG
+CFLAGS=-DDEBUG -g $(CFLAGS)
+!else
+CFLAGS=-Os $(CFLAGS)
+!endif
+
+# Some Targets
+helloworld: helloworld.o
+ cc -o $@ $<
+
+helloworld.o: helloworld.c
+ cc -c -o $@ $<
+
+.PHONY: clean
+clean:
+ rm -f helloworld helloworld.o *~ core
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/mako.mako b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/mako.mako
new file mode 100644
index 0000000..53d7de4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/mako.mako
@@ -0,0 +1,17 @@
+# Syntax Highlighting Test File for Mako Templates
+# Comments are like this
+
+<%def name="label(field, content)">
+<label for="${field}">${content}</label>
+</%def>
+
+<%def name="make_option(opt)">
+ <%
+ import os
+ from mako.template import Template
+
+ f = open("%s/templates/pages/admin/options/%s" \
+ % (c.root, opt)).read()
+ return Template(f).render()
+ %>
+</%def>
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/masm.masm b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/masm.masm
new file mode 100644
index 0000000..3caed05
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/masm.masm
@@ -0,0 +1,20 @@
+; Syntax Highlighting Test File for MASM
+; Comment Line's are like this
+; Hello world in MASM Assembly
+.MODEL tiny
+.CODE
+ ORG 100h
+HELLO PROC
+ MOV AH,09h
+ LEA DX,msg
+ INT 21h ;Display Hello World
+
+ MOV AX,4C00h ;Exit to DOS
+ INT 21h
+HELLO ENDP
+ msg DB 'Hello World$'
+ END HELLO
+
+
+
+ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/matlab.matlab b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/matlab.matlab
new file mode 100644
index 0000000..9335c8f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/matlab.matlab
@@ -0,0 +1,54 @@
+% Syntax Highlight Test File for MatLab
+% Some comments about this file
+
+% HelloWorld in MatLab
+disp('Hello World');
+
+% And now some other randomness to test different color regions
+for j=1:4,
+ j
+end
+
+A = 1; B = [];
+if(A|B) disp 'The statement is true', end;
+
+% Plotting Polynomials
+x=[27.7 28 29 30];
+a=[4.1 4.3 4.1];
+b=[0.749 0.503 -0.781];
+c=[0.0 -0.819 -0.470];
+d=[-0.910 0.116 0.157];
+
+for i=1:3
+ ['p_' num2str(i) '(x) = ' num2str(a(i)) ' + ' ...
+ num2str(b(i)) ' (x - ' num2str(x(i)) ') + ' ...
+ num2str(c(i)) ' (x - ' num2str(x(i)) ')^2 + ' ...
+ num2str(d(i)) ' (x - ' num2str(x(i)) ')^3']
+end;
+
+%---------------------------------------------------------------------
+function y = nev(xx,n,x,Q)
+% NEV Neville's algorithm as a function
+% y= nev(xx,n,x,Q)
+%
+% inputs:
+% n = order of interpolation (n+1 = # of points)
+% x(1),...,x(n+1) x coords
+% Q(1),...,Q(n+1) y coords
+% xx=evaluation point for interpolating polynomial p
+%
+% output: p(xx)
+for i = n:-1:1
+ for j = 1:i
+ Q(j) = (xx-x(j))*Q(j+1) - (xx-x(j+n+1-i))*Q(j);
+ Q(j) = Q(j)/(x(j+n+1-i)-x(j));
+ end
+end
+
+y = Q(1);
+
+%---------------------------------------------------------------------
+function ssum = geom(a,N)
+ n=0:N;
+ ssum = sum(a.^n);
+end
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/microsoft_sql.sql b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/microsoft_sql.sql
new file mode 100644
index 0000000..a9efca9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/microsoft_sql.sql
@@ -0,0 +1,149 @@
+-- MS SQL test code for lexer
+CREATE TABLE page (
+ id INT NOT NULL AUTO_INCREMENT,
+ pagename VARCHAR(100) NOT NULL,
+ hits INT NOT NULL DEFAULT 0,
+ pagedata TEXT NOT NULL DEFAULT '',
+ cached_html TEXT NOT NULL DEFAULT '', -- added with 1.3.11
+ PRIMARY KEY (id),
+ UNIQUE (pagename)
+);
+
+CREATE TABLE version (
+ id INT NOT NULL,
+ version INT NOT NULL,
+ mtime INT NOT NULL,
+ minor_edit TINYINT DEFAULT 0,
+ content TEXT NOT NULL DEFAULT '',
+ versiondata TEXT NOT NULL DEFAULT '',
+ PRIMARY KEY (id,version)
+);
+CREATE INDEX version_mtime ON version (mtime);
+
+CREATE TABLE recent (
+ id INT NOT NULL,
+ latestversion INT,
+ latestmajor INT,
+ latestminor INT,
+ PRIMARY KEY (id)
+);
+
+CREATE TABLE nonempty (
+ id INT NOT NULL,
+ PRIMARY KEY (id)
+);
+
+CREATE TABLE link (
+ linkfrom INT NOT NULL,
+ linkto INT NOT NULL
+);
+CREATE INDEX linkfrom ON link (linkfrom);
+CREATE INDEX linkto ON link (linkto);
+
+CREATE TABLE session (
+ sess_id CHAR(32) NOT NULL DEFAULT '',
+ sess_data BLOB NOT NULL,
+ sess_date INT UNSIGNED NOT NULL,
+ sess_ip CHAR(40) NOT NULL,
+ PRIMARY KEY (sess_id)
+);
+CREATE INDEX sessdate_index ON session (sess_date);
+CREATE INDEX sessip_index ON session (sess_ip);
+
+-- Optional DB Auth and Prefs
+-- For these tables below the default table prefix must be used
+-- in the DBAuthParam SQL statements also.
+
+CREATE TABLE pref (
+ userid CHAR(48) NOT NULL UNIQUE,
+ prefs TEXT NULL DEFAULT '',
+ passwd CHAR(48) DEFAULT '',
+ groupname CHAR(48) DEFAULT 'users',
+ PRIMARY KEY (userid)
+);
+-- update to 1.3.12: (see lib/upgrade.php)
+-- ALTER TABLE pref ADD passwd CHAR(48) DEFAULT '';
+-- ALTER TABLE pref ADD groupname CHAR(48) DEFAULT 'users';
+
+-- better use the extra pref table where such users can be created easily
+-- without password.
+--CREATE TABLE user (
+-- userid CHAR(48) NOT NULL UNIQUE,
+-- passwd CHAR(48) DEFAULT '',
+-- prefs TEXT NULL DEFAULT '',
+-- groupname CHAR(48) DEFAULT 'users',
+-- PRIMARY KEY (userid)
+--);
+
+--CREATE TABLE member (
+-- userid CHAR(48) NOT NULL,
+-- groupname CHAR(48) NOT NULL DEFAULT 'users',
+-- INDEX (userid),
+-- INDEX (groupname)
+--);
+--CREATE INDEX member_userid ON member (userid);
+--CREATE INDEX member_groupname ON member (groupname);
+
+-- only if you plan to use the wikilens theme
+CREATE TABLE rating (
+ dimension INT(4) NOT NULL,
+ raterpage INT(11) NOT NULL,
+ rateepage INT(11) NOT NULL,
+ ratingvalue FLOAT NOT NULL,
+ rateeversion INT(11) NOT NULL,
+ tstamp TIMESTAMP(14) NOT NULL,
+ PRIMARY KEY (dimension, raterpage, rateepage)
+);
+CREATE INDEX rating_dimension ON rating (dimension);
+CREATE INDEX rating_raterpage ON rating (raterpage);
+CREATE INDEX rating_rateepage ON rating (rateepage);
+
+-- if ACCESS_LOG_SQL > 0
+-- only if you need fast log-analysis (spam prevention, recent referrers)
+-- see http://www.outoforder.cc/projects/apache/mod_log_sql/docs-2.0/#id2756178
+CREATE TABLE accesslog (
+ time_stamp INT UNSIGNED,
+ remote_host VARCHAR(50),
+ remote_user VARCHAR(50),
+ request_method VARCHAR(10),
+ request_line VARCHAR(255),
+ request_args VARCHAR(255),
+ request_file VARCHAR(255),
+ request_uri VARCHAR(255),
+ request_time CHAR(28),
+ status SMALLINT UNSIGNED,
+ bytes_sent SMALLINT UNSIGNED,
+ referer VARCHAR(255),
+ agent VARCHAR(255),
+ request_duration FLOAT
+);
+CREATE INDEX log_time ON accesslog (time_stamp);
+CREATE INDEX log_host ON accesslog (remote_host);
+-- create extra indices on demand (usually referer. see plugin/AccessLogSql)
+
+ALTER TABLE ticket_history ADD FOREIGN KEY (ticket_id) REFERENCES `ticket(id)`;
+ALTER TABLE ticket_history_type ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;
+ALTER TABLE ticket_history_type ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`;
+ALTER TABLE ticket_history_type ADD FOREIGN KEY (valid_id) REFERENCES `valid(id)`;
+ALTER TABLE article_type ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;
+ALTER TABLE article_type ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`;
+ALTER TABLE article_type ADD FOREIGN KEY (valid_id) REFERENCES `valid(id)`;
+ALTER TABLE article_sender_type ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;
+ALTER TABLE article_sender_type ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`;
+ALTER TABLE article_sender_type ADD FOREIGN KEY (valid_id) REFERENCES `valid(id)`;
+ALTER TABLE article_flag ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;
+ALTER TABLE article ADD FOREIGN KEY (article_sender_type_id) REFERENCES `article_sender_type(id)`;
+ALTER TABLE article ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;
+ALTER TABLE article ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`;
+ALTER TABLE article ADD FOREIGN KEY (valid_id) REFERENCES `valid(id)`;
+ALTER TABLE article ADD FOREIGN KEY (article_type_id) REFERENCES `article_type(id)`;
+ALTER TABLE article ADD FOREIGN KEY (ticket_id) REFERENCES `ticket(id)`;
+ALTER TABLE article_plain ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;
+ALTER TABLE article_plain ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`;
+ALTER TABLE article_plain ADD FOREIGN KEY (article_id) REFERENCES `article(id)`;
+ALTER TABLE article_attachment ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;
+ALTER TABLE article_attachment ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`;
+ALTER TABLE article_attachment ADD FOREIGN KEY (article_id) REFERENCES `article(id)`;
+ALTER TABLE standard_response ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;
+ALTER TABLE standard_response ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`;
+ALTER TABLE standard_response ADD FOREIGN KEY (valid_id) REFERENCES `valid(id)`; \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/netwide_assembler.nasm b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/netwide_assembler.nasm
new file mode 100644
index 0000000..d933dac
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/netwide_assembler.nasm
@@ -0,0 +1,24 @@
+; Syntax Highlighting Test File for NASM
+; Some Comments about this file
+; Hello World in NASM
+
+section .text
+
+_start:
+ push dword len
+ push dword msg
+ push dword 1
+ mov eax, 0x4
+ call _syscall
+ add esp, 12
+
+ push dword 0
+ mov eax, 0x1
+ call _syscall
+
+_syscall:
+ int 0x80
+ ret
+
+msg db "Hello World",0xa
+len equ $ - msg
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/newlisp.lsp b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/newlisp.lsp
new file mode 100644
index 0000000..d3e8032
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/newlisp.lsp
@@ -0,0 +1,22 @@
+; Syntax Highlighting Test File for newLISP
+; Comments are like this
+
+(context 'EditraTest)
+
+(define (hello)
+ "Says hello."
+ (println "Hello world"))
+
+(define (EditraTest:EditraTest substance (times 10))
+ (let ((n times))
+ (while (> n 0)
+ (println (format "%d bottles of %s on the wall" n (string substance)))
+ (dec 'n)))
+ (println "Time to get to the " substance " store!"))
+
+(context 'MAIN)
+
+(dolist (substance '("beer" "apple juice" "spam"))
+ (EditraTest substance)
+ (println))
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nonmem_control_stream.ctl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nonmem_control_stream.ctl
new file mode 100644
index 0000000..467f7d9
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nonmem_control_stream.ctl
@@ -0,0 +1,21 @@
+$PROB theophylline pharmacodynamics standard control stream
+$DATA theopd.dat IGNORE #
+$INPUT ID TIME THEO AGE WT GEND RACE DIAG PEFR=DV
+$ESTIM PRINT=1 POSTHOC
+MSFO=theopd.msf
+$COV
+$THETA (0,150.,) ;popE0 1
+$THETA (0,200.,) ;popEMAX 2
+$THETA (.001,10,) ;popEC50 3
+$OMEGA 0.5 ;etaE0 1
+$OMEGA 0.5 ;etaEMAX 2
+$OMEGA 0.5 ;etaEC50 3
+$SIGMA 100 ;errSD 1
+$PRED
+E0=THETA(1)*EXP(ETA(1))
+EMAX=THETA(2)*EXP(ETA(2))
+EC50=THETA(3)*EXP(ETA(3))
+Y = E0 + EMAX*THEO/(THEO+EC50) + ERR(1)
+$TABLE ID TIME THEO AGE WT GEND RACE DIAG
+E0 EMAX EC50 Y
+NOPRINT ONEHEADER FILE=theopd.fit
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nullsoft_installer_script.nsi b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nullsoft_installer_script.nsi
new file mode 100644
index 0000000..694fcb6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nullsoft_installer_script.nsi
@@ -0,0 +1,26 @@
+; Syntax Highlighting Test File for NSIS
+; Comments are Like this
+# Comments can also be like this
+
+; Function and String
+!define PRODUCT_NAME "HelloWorld"
+
+; Function and Label
+SetCompressor lzma
+
+; Section Definition
+Section "MainSection" SEC01
+ SetOutPath "$INSTDIR"
+ SetOverwrite try
+
+SectionEnd
+
+; Section, Function, Variable, String
+Section -Post
+ WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+SectionEnd
+
+; Function Definition
+Function LaunchHello
+ Exec '"$INSTDIR\hello.exe"'
+FunctionEnd
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/objective_c.mm b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/objective_c.mm
new file mode 100644
index 0000000..a812f29
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/objective_c.mm
@@ -0,0 +1,56 @@
+// Syntax Highlighting Test File for Objective C
+// Comments are like this
+/* Multi line comments are like
+ * this
+ */
+
+// Hello World
+#import <stdio.h>
+
+int main( int argc, const char *argv[] ) {
+ printf( "Hello World\n" );
+ printf( "Unclosed string );
+ return 0;
+}
+
+// Interface
+#import <Foundation/NSObject.h>
+
+@interface Fraction: NSObject {
+ int numerator;
+ int denominator;
+}
+
+-(void) print;
+-(void) setNumerator: (int) d;
+-(void) setDenominator: (int) d;
+-(int) numerator;
+-(int) denominator;
+@end
+
+// Class implementation
+#import "Fraction.h"
+#import <stdio.h>
+
+@implementation Fraction
+-(void) print {
+ printf( "%i/%i", numerator, denominator );
+}
+
+-(void) setNumerator: (int) n {
+ numerator = n;
+}
+
+-(void) setDenominator: (int) d {
+ denominator = d;
+}
+
+-(int) denominator {
+ return denominator;
+}
+
+-(int) numerator {
+ return numerator;
+}
+@end
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/octave.oct b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/octave.oct
new file mode 100644
index 0000000..3c02298
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/octave.oct
@@ -0,0 +1,15 @@
+# Syntax Highlight Test File for Octave
+# Some comments about this file
+
+# HelloWorld in Octave
+printf("Hello World\n")
+
+a = [ 1, 1, 2; 3, 5, 8; 13, 21, 34 ]
+
+function s = plus (varargin)
+ if (nargin==0)
+ s = 0;
+ else
+ s = varargin{1} + plus (varargin{2:nargin});
+ endif
+endfunction
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ooc.ooc b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ooc.ooc
new file mode 100644
index 0000000..a240cd6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ooc.ooc
@@ -0,0 +1,38 @@
+// Syntax Highlighting Sample File for OOC
+// Comments are like this
+import structs/ArrayList
+
+SPACE := const ' '
+
+StringUtilities: class {
+ split: static func (string: String) -> ArrayList<String> {
+ tokens := ArrayList<String> new()
+
+ lastIndex := 0
+ for(index in 0..string length()) {
+ if(string[index] == SPACE) {
+ token := string[lastIndex..index]
+
+ if(!token empty?()) {
+ tokens add(token)
+ }
+ lastIndex = index + 1
+ }
+ }
+
+ rest := string[lastIndex..string length()]
+ if(!rest empty?()) {
+ tokens add(rest)
+ }
+
+ return tokens
+ }
+}
+
+main: func(arguments: ArrayList<String>) {
+ for(argument in arguments) {
+ for(token in StringUtilities split(argument)) {
+ token println()
+ }
+ }
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pascal.pas b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pascal.pas
new file mode 100644
index 0000000..7133c6d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pascal.pas
@@ -0,0 +1,31 @@
+{ Syntax Highlighting Test File for Pascal
+ Comments are like this
+ Hello World in Pascal
+}
+program Hello;
+
+uses
+ crt;
+
+begin
+ ClrScr;
+ Write('Hello world');
+ Readln;
+end.
+
+program Variables;
+
+const
+ pi: Real = 3.14;
+
+var
+ Num1, Num2, Ans: Integer;
+
+begin
+ Ans := 1 + 1;
+ Num1 := 5;
+ Ans := Num1 + 3;
+ Num2 := 2;
+ Ans := Num1 - Num2;
+ Ans := Ans * Num1;
+end.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/perl.pl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/perl.pl
new file mode 100644
index 0000000..96c9fcd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/perl.pl
@@ -0,0 +1,45 @@
+# Syntax Highlighting test file for Perl
+# Some comments about this file
+
+# Hello world in Perl
+print "Hello, world!\n";
+
+# Numerous other style region tests
+
+# Number
+$number1 = 42;
+
+# String Tests
+$answer = "The answer is $number1"; # Variable interpolation
+$h1 = "Hello World \"Perl\""; # Double quoted string
+$h2 = 'Hello World "Perl"'; # Single Quoted String
+$h3 = qq(Hello World "Perl"); # qq() instead of quotes
+$multilined_string =<<EOF
+A multilined string that is terminated with
+with the word "EOF"
+EOF
+
+# Array
+@greetings = ('Hello', 'Holla', 'Konichiwa');
+
+# Hash Table
+%translate = (
+ Hello => 'Hola',
+ Bye => 'Adios'
+);
+print $translate[Hello];
+
+=item B<function1>
+
+This is a POD doc section
+
+=cut
+sub function1 {
+ my %args = @_;
+ print "Joe said '$args{Joe}'\n";
+}
+function1( Joe => "Hello World" );
+
+# Some Regular Expressions
+$x =~ m/abc/
+$x =~ s/abc/aBc/; # substitute lowercase b with uppercase B
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/php.php b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/php.php
new file mode 100644
index 0000000..2df8144
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/php.php
@@ -0,0 +1,69 @@
+<?php
+ // Syntax Highlighting Test File for PHP
+ /* Some comments about this file */
+ // Comment line
+ $hello = "HELLO"
+ $world = "WORLD"
+
+ include_once($hello_root_path . 'hellolib.php');
+
+ function print_mood()
+ {
+ switch($_GET['friendly'])
+ {
+ case "yes":
+ echo "<h1>$hello $world</h1>";
+ break;
+ case "no":
+ echo "<h1>Bah!!</h1>"
+ break;
+ default:
+ echo "<h1>$hello???</h1>";
+ }
+ }
+
+ /* Class Definition Test */
+ class Foo
+ {
+ var $myvalue;
+
+ function bar()
+ {
+ if (isset($this))
+ {
+ echo '$this is defined (';
+ echo get_class($this);
+ echo ")\n";
+ } else {
+ echo "\$this is not defined.\n";
+ }
+ }
+ function helloA(param) {
+ echo "$param";
+ }
+ function printEndTag() {
+ echo "?>"
+ }
+ function printStartTag() {
+ echo "<?php"
+ }
+
+ }
+
+ function hello(param) {
+ echo "$param";
+ }
+?>
+
+<html>
+ <head>
+ <!-- Some Embedded HTML -->
+ <title>Hello.php</title>
+ </head>
+ <body>
+ <div>
+ <p>Today is <?php disp_date() ?> and this website says <?php print_mood() ?></p>
+ </div>
+ </body>
+</html>
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pike.pike b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pike.pike
new file mode 100644
index 0000000..9827b46
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pike.pike
@@ -0,0 +1,28 @@
+// Syntax Highlighting test file for Pike
+/* Some Comments about this file */
+
+// Hello world in Pike
+int main() {
+ write("Hello world!\n");
+ return 0;
+}
+
+//! \todo <- Documentation Doxygen Keyword highlighting
+mixed something;
+something = 5;
+something = 2.5;
+
+string testString;
+testString = "a regular string";
+testString = "an open string
+
+// Print a list of unique characters
+string data = "an apple a day";
+array(string) chars = data/"";
+mapping(string:int) seen = ([]);
+
+foreach(chars ;; string char)
+ seen[char]++;
+
+write("unique chars are: %s\n", sort(indices(seen))*"");
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pl_sql.plsql b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pl_sql.plsql
new file mode 100644
index 0000000..9492221
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pl_sql.plsql
@@ -0,0 +1,94 @@
+/**
+ * Syntax Highlighting Test File for PLSQL
+ * This is a package example for syntax colourising of
+ * Oracle PL/SQL 11g
+ * It is developed to meet at least my requirements.
+ * Copyright 2007 Thomas G. Keul
+ * @author Thomas G. Keul (tgkeul@web.de)
+ */
+
+ /**
+ * Example pldoc header of a procedure.
+ *
+ * @param param_1 in parameter
+ * @param param_2 out parameter
+ * @param param_3 in out parameter
+ * @throws no_data_found
+ */
+ procedure my_proc
+ (param_1 in my_table.the_key%type,
+ param_2 out my_table%rowtype,
+ param_3 in out nocopy plsql_table_type);
+
+ /**
+ * Example pldoc header of a function.
+ *
+ * @param param_1 in parameter
+ * @return true or false
+ */
+ function my_func (param_1 in pls_integer) return boolean;
+end example
+/
+
+create or replace package body example is
+
+ type t_boolean_table is table of boolean index by binary_integer;
+ subtype t_sample is positive range 1..6;
+ real_sample constant t_sample := 3;
+
+ cursor get_it (param_1 in varchar2) is
+ select /*+ a Hint */
+ distinct foo
+ from bar
+ where the_key = param_1
+ and a_column is not null;
+
+ procedure nested_outer (param_1 in number) is
+ procedure nested_inner is
+ begin
+ if a_collection.count > 0
+ then
+ for l in a_collection.first .. a_collection.last
+ loop
+ doit; -- just for fun
+ end loop;
+ elsif its_a_rainy_day
+ then help (who => me);
+ else sigh;
+ end if;
+ end nested_inner;
+
+ begin
+ update a_table
+ set a_column = 1
+ where the_key = 4711
+ returning something bulk collect into a_collection;
+
+ << a_label >>
+ for ex in 1..3
+ loop
+ case ex
+ when 1 then dbms_output.put_line ('number one');
+ when 2 then junk := greatest (ex, nvl(foo, bar));
+ when 3 then exit (a_label);
+ else rollback;
+ end case;
+ end loop a_label;
+
+ exception
+ when no_data_found then null;
+ when others then raise;
+ end nested_outer;
+
+begin
+ oops := 'no string eol';
+end example;
+/
+-- -----------------------------------------------------------
+declare
+ d date := sysdate;
+begin
+ dbms_output.put_line (to_char (sysdate, 'DD.MM.YYYY'));
+end;
+-- -----------------------------------------------------------
+exec dbms_job.run(4711);
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/plain_text.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/plain_text.txt
new file mode 100644
index 0000000..f92fd39
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/plain_text.txt
@@ -0,0 +1,4 @@
+Here is some plain text to test the editor with highlighting in an in active state. This is rather boring isn't it?
+
+Hello World
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/postscript.ps b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/postscript.ps
new file mode 100644
index 0000000..dedf668
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/postscript.ps
@@ -0,0 +1,11 @@
+%!PS
+% Syntax Highlighting Test File for Postscript
+% Comments are like this
+% Hello World in Postscript
+1.00000 0.99083 scale
+/Courier findfont 12 scalefont setfont
+0 0 translate
+/row 769 def
+85 {/col 18 def 6 {col row moveto (Hello World)show /col col 90 add def}
+repeat /row row 9 sub def} repeat
+showpage save restore
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/progress_4gl.4gl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/progress_4gl.4gl
new file mode 100644
index 0000000..7c93df2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/progress_4gl.4gl
@@ -0,0 +1,34 @@
+/* Syntax highlight test file for Progress 4GL */
+
+DEFINE TEMP-TABLE tt
+ FIELDS site like ld_site
+ FIELDS loc like ld_loc
+ FIELDS part like ld_part
+ FIELDS lot like ld_lot
+ FIELDS ref like ld_ref
+ FIELDS ldt like ld_date
+ FIELDS ldst like ld_status
+ FIELDS qoh like ld_qty_oh
+ FIELDS coh like ld_cust_consign_qty.
+
+INPUT FROM "ld-ncstkinconsignloc.d".
+ REPEAT TRANSACTION.
+ CREATE tt.
+ IMPORT tt.
+END.
+ INPUT CLOSE.
+
+OUTPUT TO "cyc-amt-02.d".
+FOR EACH tt:
+ FINF FIRST pt_mstr WHERE pt_part = part NO-LOCK NO-ERROR.
+
+ FIND FIRST pl_mstr WHERE pl_prod_line = pt_prod_line NO-LOCK NO-ERROR.
+ FIND FIRST sct_det where sct_sim = "standard"
+ AND sct_site = "g1"
+ AND sct_part = part NO-LOCK NO-ERROR.
+ EXPORT site loc part lot ref
+ pt_prod_line
+ pl_inv_acct
+ pl_inv_cc
+ qoh sct_cst_tot qoh * sct_cst_tot.
+END.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/properties.ini b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/properties.ini
new file mode 100644
index 0000000..02f0099
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/properties.ini
@@ -0,0 +1,14 @@
+# Syntax Highlighting Test file for Properties Files
+# Some comments about this file
+
+# Section Def
+[greetings]
+hello=1
+world=2
+
+[food]
+cheese=('gouda', 'swiss')
+bread=('french', 'italian', 'sliced')
+meat=('steak', 'pork')
+fish=('salmon', 'tuna')
+fruit=('apple', 'orange', 'watermelon')
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/python.python b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/python.python
new file mode 100644
index 0000000..3414f2d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/python.python
@@ -0,0 +1,43 @@
+# Syntax Highlight Test File for Python
+# Some Comments about this file
+
+"""
+A test file for checking styles for the python highlighter.
+This is a docstring
+
+"""
+__author__ = "Cody Precord"
+
+# Keyword statement
+import sys
+
+# Function Definition
+def say_hello():
+ """Prints hello world to the console"""
+ print "Hello World"
+ print "unclosed string
+
+# Class Definition
+class Greeting:
+ """A class to represent a greeting"""
+ def __init__(self, language):
+ """initializes the greeting"""
+ self._lang = language
+
+ def __str__(self):
+ """Returns the string representation of the greeting"""
+ if self._lang == "English":
+ return "Hello"
+ elif self._lang == "Spanish":
+ return "Holla"
+ else:
+ return "Sorry I dont know %s" % self._lang
+
+ # Decorator's (python 2.4+)
+ @property
+ def classdocs(self):
+ return '\n'.join([ x.__doc__ for x in dir(self) if hasattr(x, '__doc__')])
+
+if __name__ == '__main__':
+ say_hello()
+ print Greeting('English')
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/r.r b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/r.r
new file mode 100644
index 0000000..abc6a7e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/r.r
@@ -0,0 +1,28 @@
+# Syntax Highlighting test file for R
+# Comments look like this
+
+options(digits=7)
+
+## powers
+outer(a <- -4:12, -2:7, "^")
+
+for (n1 in 1:7)
+ print(zapsmall(polyroot(1:n1), digits = 10))
+
+## lowess() {incl. sort, etc}:
+options(digits = 5)
+
+lowess(c(3,2,6,3,8,4))$y # this used to differ on Linux
+
+y1 <- c(3,1:2,5:2,4,1:3,3)
+lowess(y1)$y
+lowess(y1, f = .4)$y
+
+lowess(c(y1,100), f = .4)$y
+
+## this is the test sample from Cleveland's original lowess.doc:
+x <- c(1:5, rep(6,10),8,10,12,14,50)
+y <- c(18,2,15,6,10,4,16,11,7,3,14,17,20,12,9,13,1,8,5,19)
+lowess(x,y, f = .25, iter = 0, delta = 0)$y
+lowess(x,y, f = .25, iter = 0, delta = 3)$y
+lowess(x,y, f = .25, iter = 2, delta = 0)$y
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ruby.rb b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ruby.rb
new file mode 100644
index 0000000..6e74037
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ruby.rb
@@ -0,0 +1,27 @@
+# Syntax Highlighting Test File for Ruby
+# Some Comments about this file
+# Hello World in ruby
+
+# Keyword statement and string
+puts 'Hello world'
+
+# Function Definitions
+def hello2(name)
+ puts "Hello #{name}!"
+end
+
+# Class Definition
+class Greeter
+ def intialize(name = "World")
+ @name = name
+ end
+ def say_hello
+ puts "Hello #{@name}!"
+ end
+ def say_bye
+ puts "Bye #{@name}, come again."
+ end
+end
+
+# Keyword and some Numbers
+puts 5 ** 2
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/s.s b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/s.s
new file mode 100644
index 0000000..73c7b97
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/s.s
@@ -0,0 +1,28 @@
+# Syntax Highlighting test file for S
+# Comments look like this
+
+options(digits=7)
+
+## powers
+outer(a <- -4:12, -2:7, "^")
+
+for (n1 in 1:7)
+ print(zapsmall(polyroot(1:n1), digits = 10))
+
+## lowess() {incl. sort, etc}:
+options(digits = 5)
+
+lowess(c(3,2,6,3,8,4))$y # this used to differ on Linux
+
+y1 <- c(3,1:2,5:2,4,1:3,3)
+lowess(y1)$y
+lowess(y1, f = .4)$y
+
+lowess(c(y1,100), f = .4)$y
+
+## this is the test sample from Cleveland's original lowess.doc:
+x <- c(1:5, rep(6,10),8,10,12,14,50)
+y <- c(18,2,15,6,10,4,16,11,7,3,14,17,20,12,9,13,1,8,5,19)
+lowess(x,y, f = .25, iter = 0, delta = 0)$y
+lowess(x,y, f = .25, iter = 0, delta = 3)$y
+lowess(x,y, f = .25, iter = 2, delta = 0)$y
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/scheme.scm b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/scheme.scm
new file mode 100644
index 0000000..2d67cb1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/scheme.scm
@@ -0,0 +1,17 @@
+; Syntax Highlighting Test File for Scheme
+; Comments are like this
+
+; Hello World
+(define hello-world
+ (lambda ()
+ (begin
+ (write 'Hello-World)
+ (newline)
+ (hello-world))))
+
+; Factorial
+(define (fact n)
+ (if (= n 0)
+ 1
+ (* n (fact (- n 1)))))
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/smalltalk.st b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/smalltalk.st
new file mode 100644
index 0000000..e7d57cb
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/smalltalk.st
@@ -0,0 +1,41 @@
+" Syntax Highlighting Test File for Smalltalk "
+" Comments are like this "
+" Hello World in smalltalk "
+
+" Heres helloworld doesnt get much easier that this "
+'Hello World!'
+
+" Heres a version in a window "
+| window |
+window := Window new.
+window label: 'Hello World'.
+window open.
+
+" Character Definition"
+| mychar |
+mychar := $A
+
+" Symbol Definition "
+| mySym |
+mySym := #foo
+
+" Symbol Array "
+mySym := #(1 2 3 4)
+
+" Class Def "
+Object subclass: #MessagePublisher
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'Smalltalk Examples'
+
+| rectangles aPoint|
+rectangles := OrderedCollection
+ with: (Rectangle left: 0 right: 10 top: 100 bottom: 200)
+ with: (Rectangle left: 10 right: 10 top: 110 bottom: 210).
+aPoint := Point x: 20 y: 20.
+collisions := rectangles select: [:aRect | aRect containsPoint: aPoint].
+
+result := a > b
+ ifTrue:[ 'greater' ]
+ ifFalse:[ 'less' ]
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/sql.sql b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/sql.sql
new file mode 100644
index 0000000..76ff1d8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/sql.sql
@@ -0,0 +1,166 @@
+/******************************************
+* Syntax Highlighting Test File for SQL *
+* Multi-Line Comment Block *
+* Oracle 9i SQL *
+*******************************************/
+--- Single Line Comments are like this
+
+--- Drop all tables, in case they were previously created ---
+DROP TABLE shipment;
+DROP TABLE customer;
+DROP TABLE truck;
+DROP TABLE city;
+
+--- Create the customer table ---
+CREATE TABLE customer
+(
+ CUS_ID Char(4) CONSTRAINT cus_id_pk PRIMARY KEY,
+ CUS_LNAME Varchar2(20),
+ CUS_FNAME Varchar2(20),
+ ANN_REVENUE Number(12,2),
+ CUS_TYPE Char(1)
+);
+
+--- Create the truck table ---
+CREATE TABLE truck
+(
+ TRUCK_ID Char(4) CONSTRAINT truck_id_pk PRIMARY KEY,
+ DRIVER_NAME Varchar2(40)
+);
+
+--- Create the city table ---
+CREATE TABLE city
+(
+ CITY_ID Varchar2(4) CONSTRAINT city_id_pk PRIMARY KEY,
+ CITY_NAME Varchar2(30),
+ CITY_STATE Char(2),
+ POPULATION Number(10)
+);
+
+--- Create the shipment table ---
+CREATE TABLE shipment
+(
+ SHIPMENT_ID Char(4) CONSTRAINT ship_id_pk PRIMARY KEY,
+ CUS_ID Char(4) CONSTRAINT cust_id_fk REFERENCES customer(cus_id),
+ WEIGHT Number(12,2),
+ TRUCK_ID Char(4) CONSTRAINT truck_id_fk REFERENCES truck(truck_id),
+ CITY_ID Varchar2(4) CONSTRAINT city_id_fk REFERENCES city(city_id),
+ SHIP_DATE DATE
+);
+
+--- Insert records into customer table ---
+INSERT INTO customer VALUES
+ ('C101','Smith','Joe',3000000.3,'P');
+INSERT INTO customer VALUES
+ ('C102','Sneider','Jenny',7000000.5,'P');
+INSERT INTO customer VALUES
+ ('C103','Robinson','Dan',1000000.8,'C');
+COMMIT;
+
+--- Insert records into truck table ---
+INSERT INTO truck VALUES
+ ('T101','Dan Brun');
+INSERT INTO truck VALUES
+ ('T102','Bob Lee');
+INSERT INTO truck VALUES
+ ('T104','Jerry Carlson');
+INSERT INTO truck VALUES
+ ('T103','Frank Hong');
+COMMIT;
+
+--- Insert records into city table ---
+INSERT INTO city VALUES
+ ('101','Dekalb','IL',50000);
+INSERT INTO city VALUES
+ ('201','Lincoln','NE',160000);
+INSERT INTO city VALUES
+ ('301','Houston','TX',800000);
+INSERT INTO city VALUES
+ ('401','Laredo','TX',260000);
+COMMIT;
+
+--- Insert records into shipment table ---
+INSERT INTO shipment VALUES
+ ('2001','C101',2500.2,'T101','101','12-Apr-2002');
+INSERT INTO shipment VALUES
+ ('2002','C102',7500.7,'T101','201','20-Apr-2002');
+INSERT INTO shipment VALUES
+ ('2003','C103',800000.8,'T103','201','25-May-2002');
+INSERT INTO shipment VALUES
+ ('2004','C102',95.00,'T102','301','02-May-2003');
+INSERT INTO shipment VALUES
+ ('2005','C101',85.00,'T102','401','02-May-2003');
+COMMIT;
+
+--- Queries 1 - 10 ---
+
+--- How many shipments between 1/1/02 & 5/1/03?
+--- Version 1 shows all records between the given dates
+SELECT *
+FROM shipment
+WHERE SHIP_DATE >= '01-Jan-2002'
+AND SHIP_DATE <= '01-May-2003';
+
+--- Version 2 returns simply a count of all the given dates
+SELECT COUNT(*)
+FROM shipment
+WHERE SHIP_DATE >= '01-Jan-2002'
+AND SHIP_DATE <= '01-May-2003';
+
+--- What is destination city name of shipment id# 2004
+SELECT CITY_NAME
+FROM shipment,city
+WHERE SHIPMENT_ID = '2004'
+AND shipment.CITY_ID = city.CITY_ID;
+
+--- What are the truck ids of trucks that have carried
+--- shipments over 100 lbs?
+SELECT DISTINCT TRUCK_ID
+FROM shipment
+WHERE WEIGHT >= 100;
+
+--- Give the Names of customers who have sent shipments to cities
+--- starting with 'L'?
+SELECT CUS_LNAME, CUS_FNAME
+FROM customer,shipment,city
+WHERE customer.CUS_ID = shipment.CUS_ID
+AND shipment.CITY_ID = city.CITY_ID
+AND city.CITY_NAME LIKE 'L%';
+
+--- What are the names of customers who have sent packages to
+--- Lincoln, NE?
+SELECT CUS_LNAME, CUS_FNAME
+FROM customer,shipment,city
+WHERE customer.CUS_ID = shipment.CUS_ID
+AND shipment.CITY_ID = city.CITY_ID
+AND city.CITY_NAME = 'Lincoln';
+
+--- Who are the customers having over 5 million in revenue and
+--- have sent less than 100lbs?
+SELECT DISTINCT CUS_FNAME, CUS_LNAME
+FROM customer, shipment
+WHERE customer.ANN_REVENUE > 5000000
+AND shipment.WEIGHT < 100;
+
+--- For each customer what is the average weight of a package,
+--- show name and avg weight?
+SELECT CUS_FNAME, CUS_LNAME, AVG(WEIGHT)
+FROM customer,shipment
+WHERE customer.CUS_ID = shipment.CUS_ID
+GROUP BY CUS_FNAME, CUS_LNAME;
+
+--- For each city with a population over 100,000 what is the
+--- minimum weight of a package sent there?
+SELECT CITY_NAME, MIN(WEIGHT)
+FROM city,shipment
+WHERE city.POPULATION >= 100000
+AND city.CITY_ID = shipment.CITY_ID
+GROUP BY CITY_NAME;
+
+--- For each city that has recieved at least 2 packages, what is the
+--- average weight of a package sent to that city?
+SELECT CITY_NAME, COUNT(SHIPMENT_ID), AVG(WEIGHT)
+FROM city,shipment
+WHERE shipment.CITY_ID = city.CITY_ID
+GROUP BY CITY_NAME
+HAVING COUNT(shipment.CITY_ID) >= 2;
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/squirrel.nut b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/squirrel.nut
new file mode 100644
index 0000000..2378860
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/squirrel.nut
@@ -0,0 +1,40 @@
+// Squirrel Syntax Highlighting Test File
+// Comments are like this
+/** Multiline comments are like this
+ * @summary <- Documentation keywords are like this
+ */
+
+// Hello World
+print("Hello World")
+
+// Literals
+local a = 123 // Decimal
+local b = 0x0012 // Hexadecimal
+local c = 075 // Octal
+local d = 'w' // Char
+local e = "string" // String
+local f = "Unclosed string
+
+// Function Definition
+function fib(n)
+{
+ if (n < 2) return 1
+ return fib(n-2) + fib(n-1)
+}
+
+// Class Construct
+class Foo {
+ //constructor
+ constructor(a)
+ {
+ bar = ["bar", 1, 2, 3];
+ }
+
+ function PrintBar()
+ {
+ foreach(i, val in bar)
+ {
+ ::print("idx = " + i + " = " + val + " \n");
+ }
+ }
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/stata.do b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/stata.do
new file mode 100644
index 0000000..257f1c3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/stata.do
@@ -0,0 +1,14 @@
+/* STATA Test File /*
+/* Comments look like this */
+
+set mem 100m
+use "this\is\where\stata\file\is\file.dta", clear
+use "file.dta", clear
+
+
+forvalues i = 1(1)10 {
+
+ keep if auction==`i'
+ tabstat V1, by(V2) s(mean sd median count)
+ reg V1 V2 V3,robust
+ }
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/svg.svg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/svg.svg
new file mode 100644
index 0000000..0b8d0df
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/svg.svg
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Some Comments about this file -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <g
+ id="layer1">
+ <rect
+ width="282.85715"
+ height="260"
+ x="245.71428"
+ y="249.50504"
+ style="fill:#efefef;fill-opacity:1;stroke:#373131;stroke-opacity:1"
+ id="rect2160" />
+ <path
+ d="M 288.57142 749.50507 A 62.857143 74.285713 0 1 1 162.85714,749.50507 A 62.857143 74.285713 0 1 1 288.57142 749.50507 z"
+ style="fill:#efefef;fill-opacity:1;stroke:#373131;stroke-opacity:1"
+ id="path2162" />
+ <text
+ x="91.428574"
+ y="169.50504"
+ style="font-size:36px;font-style:normal;font-weight:bold;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ id="text2164"
+ xml:space="preserve"><tspan
+ x="91.428574"
+ y="169.50504"
+ id="tspan2166">Hello World</tspan></text>
+ <path
+ d="M 137.14286,303.79075 L 104.79416,323.98742 L 103.09272,362.08531 L 73.888247,337.56098 L 37.129231,347.71572 L 51.428572,312.36218 L 30.411685,280.54026 L 68.453639,283.2149 L 92.223505,253.39314 L 101.43538,290.39969 L 137.14286,303.79075 z "
+ style="fill:#efefef;fill-opacity:1;stroke:#373131;stroke-opacity:1"
+ id="path2168" />
+ </g>
+</svg>
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/system_verilog.sv b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/system_verilog.sv
new file mode 100644
index 0000000..ae548bd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/system_verilog.sv
@@ -0,0 +1,139 @@
+// System Verilog Syntax Highlighting Test File
+// Comments are like this
+
+package oop;
+
+class BaseScoreboard;
+ string name;
+ bit[3:0] srce, dest;
+ int run_for_n_packets; // max number of packets to transmit before giving up on coverage goals
+ static int pkts_checked = 0;
+ static int sent_pkt_count = 0;
+ static int recvd_pkt_count = 0;
+ Packet refPkts[$];
+
+ function new(string name = "class", int run_for_n_packets );
+ if (TRACE_ON) $display("@%0d: %s.new() started", $time, name);
+ this.name = name;
+ this.run_for_n_packets = run_for_n_packets;
+ endfunction : new
+
+ task report();
+ if (TRACE_ON) $display("@%0d: %s.report() started", $time, name);
+ $display("%0d packets sent, %0d packets sampled, %0d packets checked\n",
+ sent_pkt_count, recvd_pkt_count, pkts_checked);
+ endtask : report
+
+endclass : BaseScoreboard
+
+
+class Scoreboard extends BaseScoreboard;
+
+ covergroup router_cvg;
+ coverpoint srce;
+ coverpoint dest;
+ cross srce, dest;
+ option.at_least = 1;
+ option.auto_bin_max = 256;
+ endgroup
+
+ function new(string name = "class", int run_for_n_packets );
+ super.new(name, run_for_n_packets);
+ router_cvg = new();
+ endfunction : new
+
+ task check(Packet pktrecvd);
+ int index;
+ int status;
+ string diff;
+ Packet pktsent;
+ if (TRACE_ON) $display("@%0d: %s.check() started", $time, name);
+ endtask
+
+
+endclass : Scoreboard
+
+endpackage : oop
+
+/*****************************************************************************/
+
+program test(io_if dutif, input bit clk);
+
+import oop::*;
+
+bit[3:0] srce, dest;
+reg[7:0] payload[$], pkt2cmp_payload[$];
+
+Scoreboard sb;
+
+initial begin
+ DONE <= 0;
+ sb = new("sb", 2500);
+ pkt2send = new();
+ pkt2send.pt_mode = 1;
+ do begin
+ fork
+ begin send(); end
+ begin recv(); end
+ join
+ end
+ repeat(10) @(posedge clk);
+end
+
+task automatic recv();
+ static int pkts_recvd = 0;
+ int i;
+ pktrecvd = new($psprintf("Pkt_recvd[%0d]", pkts_recvd++));
+ pktrecvd.payload = new[pkt2cmp_payload.size()];
+ for (i=0; i<pkt2cmp_payload.size(); i++)
+ pktrecvd.payload[i] = pkt2cmp_payload[i];
+ pktrecvd.dest = dest;
+endtask
+
+task automatic send();
+ int i;
+ payload.delete();
+ for (i=0; i<pkt2send.payload.size(); i++)
+ payload.push_back(pkt2send.payload[i]);
+ srce = pkt2send.srce;
+ dest = pkt2send.dest;
+endtask
+
+endprogram
+
+interface io(input clock, input bit[15:0] din, frame_n);
+bit [15:0] passthru;
+
+sequence s_pass_thru_0 ;
+ frame_n[ 0] ##1 !frame_n[ 0] ##0 din[ 0] == 0 [*4]; // 0000
+endsequence
+
+property p_pass_thru_0 ;
+ @(posedge clk) fr_valid |-> s_pass_thru_0;
+endproperty
+
+assert property (p_pass_thru_0) $info("%m OK");
+ else $error("%m Problem");
+endinterface
+
+sequence s_pass_thru_1 ;
+ frame_n[ 1] ##1 !frame_n[ 1] ##0 din[ 1] == 0 [*4]; // 0000
+endsequence
+
+property p_pass_thru_1 ;
+ @(posedge clk) fr_valid |-> s_pass_thru_1;
+endproperty
+
+assert property (p_pass_thru_1) $info("%m OK");
+ else $error("%m Problem");
+endinterface
+
+module top;
+bit clk;
+bit[15:0] din;
+bit frame_n;
+
+io IF1 (.clk, .din, .frame_n);
+test TB1 (.clk, io_if(IF1) );
+
+endmodule
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/tcl_tk.tcl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/tcl_tk.tcl
new file mode 100644
index 0000000..1dda0a6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/tcl_tk.tcl
@@ -0,0 +1,60 @@
+# Syntax Highlighting Test File for TCL/TK
+# Comments are like this
+# Hello World in tcl/tk
+
+wm title . "Hello world!"
+
+frame .h -borderwidth 2
+frame .q -borderwidth 2
+button .h.hello -text "Hello world" \
+ -command "puts stdout \"Hello world!\"" -cursor gumby
+button .q.quit -text "Quit" -command exit -cursor pirate
+
+pack .h -side left
+pack .q -side right
+pack .h.hello
+pack .q.quit
+
+# Procedure Definition
+proc printArguments args {
+ foreach arg $args {
+ puts $arg
+ }
+}
+
+proc foo::xxxx {} {
+ set a xxxxxxxxxxxx
+}
+proc foo_bar {} {
+ set b xxxxxxx
+}
+
+proc foo::yyyy {} {
+ set a bbbbbbb
+}
+
+# SNIT
+package provide test 1.0
+
+snit::widgetadaptor mySnit {
+
+ package require mypack 2.2
+
+ constructor {args} {
+ installhull using text -insertwidth 0
+ $self configurelist $args
+ }
+
+ typevariable myList [list]
+
+ typemethod list {} {
+ return $myList
+ }
+
+ # Disable the insert and delete methods, to make this readonly.
+ method insert {args} {}
+ method delete {args} {}
+}
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/unicode_text.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/unicode_text.txt
new file mode 100644
index 0000000..c9087db
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/unicode_text.txt
@@ -0,0 +1,18 @@
+The next line should show some Japanese characters
+こにちは 今晩は
+
+The next lines should show a bunch of other special characters, the description
+of the character is o the left and should be directly followed by the actual
+character to the right of the ':'.
+
+Trademark symbol: ™
+Infinity: ∞
+Bullet: •
+Not Equal: ≠
+Yen Symbol: ¥
+Triangle: ∆
+Greater than equal to: ≥
+Less than equal to: ≤
+Checkmark: √
+Pi: π
+Copyright: ©
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vala.vala b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vala.vala
new file mode 100644
index 0000000..cfa7cb0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vala.vala
@@ -0,0 +1,31 @@
+// Syntax Highlighting Test File for Vala
+// Comments are like this
+/* Multiline comments are like
+ * this.
+ */
+
+// Hello World in Vala
+using GLib;
+
+//! \summary Documentation keyword
+public class Sample : Object {
+
+ // Some Variable definitions
+ public static const double ASPECT = 8.0/6.0;
+ static unichar a_char = 'a';
+
+ public Sample () {
+ }
+
+ public void run () {
+ stdout.printf ("Hello World\n");
+ stdout.printf ("Unclosed string);
+ stdout.printf ('a'); // <- Char
+ }
+
+ static int main (string[] args) {
+ var sample = new Sample ();
+ sample.run ();
+ return 0;
+ }
+}
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vbscript.vbs b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vbscript.vbs
new file mode 100644
index 0000000..6edacc1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vbscript.vbs
@@ -0,0 +1,51 @@
+' Syntax Highlighting test file for VBScript
+' Comments look like this
+
+function hello(name) 'comment for function
+
+ on error resume next
+
+ dim x,y
+
+ if name<>"World" then
+ for x = 1 to 10
+ wscript.echo "Hello " & name
+ next
+ else
+ x=0
+ do while x<10
+ wscript.echo "Hello World"
+ x=x+1
+ loop
+ end if
+
+ hello=x+y
+
+end function
+
+Public Function testPublicFunct()
+ dim c,d
+end Sub
+
+sub testStub()
+ dim a,b
+end sub
+
+Public Sub testPublicSub()
+ dim c,d
+end Sub
+
+'---------------------------
+
+on error resume next
+
+dim didIt
+dim userid
+
+set WshShell = WScript.CreateObject("WScript.Shell")
+'Finds the user name from an environment variable
+userid=wshshell.expandenvironmentstrings("%username%")
+
+didIt=hello(userid)
+
+wscript.exit(0)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/verilog.v b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/verilog.v
new file mode 100644
index 0000000..f905254
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/verilog.v
@@ -0,0 +1,33 @@
+// Syntax Highlighting Test file for Verilog
+// Some Comments about this file
+
+module toplevel(clock,reset);
+ input clock;
+ input reset;
+
+ reg flop1;
+ reg flop2;
+
+ always @ (posedge reset or posedge clock)
+ if (reset)
+ begin
+ flop1 <= 0;
+ flop2 <= 1;
+ end
+ else
+ begin
+ flop1 <= flop2;
+ flop2 <= flop1;
+ end
+endmodule
+
+initial
+ fork
+ $write("A");
+ $write("B");
+ begin
+ #1;
+ $write("C");
+ end
+ join
+ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vhdl.vhdl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vhdl.vhdl
new file mode 100644
index 0000000..ef2f779
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vhdl.vhdl
@@ -0,0 +1,45 @@
+-- Syntax Highlighting Test File for VHDL
+-- Comments are like this
+-- Hello World in VHDL
+
+entity hello_world is
+end;
+
+ architecture hello_world of hello_world is
+ begin
+ stimulus : process
+ begin
+ assert false report "Hello World By Deepak"
+ severity note;
+ wait;
+ end process stimulus;
+end hello_world;
+
+-- A simple counter
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity counter is
+port( clk: in std_logic;
+ reset: in std_logic;
+ enable: in std_logic;
+ count: out std_logic_vector(3 downto 0)
+);
+end counter;
+
+architecture behav of counter is
+ signal pre_count: std_logic_vector(3 downto 0);
+ begin
+ process(clk, enable, reset)
+ begin
+ if reset = '1' then
+ pre_count <= "0000";
+ elsif (clk='1' and clk'event) then
+ if enable = '1' then
+ pre_count <= pre_count + "1";
+ end if;
+ end if;
+ end process;
+ count <= pre_count;
+end behav;
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/visual_basic.vb b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/visual_basic.vb
new file mode 100644
index 0000000..c7332be
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/visual_basic.vb
@@ -0,0 +1,32 @@
+' Visual Basic Hello World
+' Some more comments about this file
+VERSION 4.00
+Begin VB.Form Form1
+ Caption = "Hello"
+ ClientHeight = 6030
+ ClientLeft = 1095
+ ClientTop = 1515
+ ClientWidth = 6720
+ Height = 6435
+ Left = 1035
+ LinkTopic = "Form1"
+ ScaleHeight = 6030
+ ScaleWidth = 6720
+ Top = 1170
+ Width = 6840
+ Begin VB.CommandButton Command1
+ Caption = "Hello World"
+ Height = 975
+ Left = 2040
+ TabIndex = 0
+ Top = 2280
+ Width = 2535
+ End
+End
+Attribute VB_Name = "Form1"
+Attribute VB_Creatable = False
+Attribute VB_Exposed = False
+Private Sub Command1_Click()
+Cls
+Print "Hello World"
+End Sub \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/xml.xml b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/xml.xml
new file mode 100644
index 0000000..b4d0d52
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/xml.xml
@@ -0,0 +1,20 @@
+<!-- Syntax Highlighting Test File for XML -->
+<!-- Comments are like this -->
+<?xml version="1.0" encoding="utf-8"?>
+<rss version="2.0">
+ <channel>
+ <title>Editra.org</title>
+ <link>http://editra.org/index.php</link>
+ <description>Editra Text Editor</description>
+ <language>en-us</language>
+ <generator>Editra.org</generator>
+ <item>
+ <title>Cleanup Round 2</title>
+ <link>http://editra.org/index.php?artical=helloWorld</link>
+ <description>Hello XML</description>
+ <author>admin@editra.org (cody)</author>
+ <pubDate>Sat, 11 Nov 2006 17:47:39 -0800</pubDate>
+ <guid isPermaLink="true">http://editra.org/index.php?artical=helloWorld</guid>
+ </item>
+ </channel>
+</rss>
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/yaml.yaml b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/yaml.yaml
new file mode 100644
index 0000000..e8c4b84
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/yaml.yaml
@@ -0,0 +1,25 @@
+# Syntax Highlighting Test file for YAML
+# Some Comments about this file
+
+---!myDocument
+logEvent: Hello World
+date: 2007-08-06
+customer:
+ given: Joe
+ family: Bazooka
+
+greet: &id001
+ location: |
+ In Front of you
+
+greeting:
+ - first: Hello
+ second: World
+
+ - first: Buy my gum
+ second: I give you Comics
+
+specialGreeting: >
+ This is a text section of a yaml document all
+ the (xxx:) items are identifiers.
+...
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/AttributePanel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/AttributePanel.py
new file mode 100644
index 0000000..ce0491f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/AttributePanel.py
@@ -0,0 +1,453 @@
+# Name: AttributePanel.py
+# Purpose: View components for editing attributes
+# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
+# Created: 17.06.2007
+# RCS-ID: $Id: AttributePanel.py 73215 2012-12-19 18:05:05Z RD $
+
+import string
+import wx
+import wx.lib.buttons as buttons
+from globals import *
+import params
+import component
+import undo
+import images
+
+
+labelSize = (100,-1)
+
+# Panel class is the attribute panel containing class name, XRC ID and
+# a notebook with particular pages.
+
+class ScrolledPage(wx.ScrolledWindow):
+ def __init__(self, parent):
+ wx.ScrolledWindow.__init__(self, parent)
+ self.topSizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self.topSizer)
+ self.panel = None
+ self.SetScrollRate(5, 5)
+
+ def Reset(self):
+ if self.panel:
+ self.panel.Destroy()
+ self.panel = None
+
+ def SetPanel(self, panel):
+ self.Reset()
+ self.panel = panel
+ self.topSizer.Add(panel, 0, wx.ALL | wx.EXPAND, 2)
+ self.topSizer.Layout()
+ self.SendSizeEvent()
+
+# No highlighting please
+class ToggleButton(buttons.GenBitmapToggleButton):
+ def GetBackgroundBrush(self, dc):
+ colBg = self.GetBackgroundColour()
+ brush = wx.Brush(colBg, wx.SOLID)
+ if self.style & wx.BORDER_NONE:
+ myAttr = self.GetDefaultAttributes()
+ parAttr = self.GetParent().GetDefaultAttributes()
+ myDef = colBg == myAttr.colBg
+ parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg
+ if myDef and parDef:
+ if wx.Platform == "__WXMAC__":
+ brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
+ elif wx.Platform == "__WXMSW__":
+ if self.DoEraseBackground(dc):
+ brush = None
+ elif myDef and not parDef:
+ colBg = self.GetParent().GetBackgroundColour()
+ brush = wx.Brush(colBg, wx.SOLID)
+ return brush
+
+class Panel(wx.Panel):
+ '''Attribute panel main class.'''
+ def __init__(self, *args, **kw):
+ wx.Panel.__init__(self, *args, **kw)
+
+ # Set common sizes
+ params.InitParams(self)
+
+ topSizer = wx.BoxSizer(wx.VERTICAL)
+ pinSizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer = wx.FlexGridSizer(cols=2, vgap=1, hgap=5)
+ self.labelRef = wx.StaticText(self, -1, 'ref:')
+ self.textRef = params.ParamText(self, 'ref', textWidth=200)
+ sizer.AddMany([ (self.labelRef, 0, wx.ALIGN_CENTER_VERTICAL),
+ (self.textRef, 0, wx.LEFT, 5) ])
+ self.labelClass = wx.StaticText(self, -1, 'class:')
+ self.textClass = params.ParamText(self, 'class', textWidth=200)
+ sizer.AddMany([ (self.labelClass, 0, wx.ALIGN_CENTER_VERTICAL),
+ (self.textClass, 0, wx.LEFT, 5) ])
+ self.labelName = wx.StaticText(self, -1, 'name:')
+ self.textName = params.ParamText(self, 'name', textWidth=200)
+ sizer.AddMany([ (self.labelName, 0, wx.ALIGN_CENTER_VERTICAL),
+ (self.textName, 0, wx.LEFT, 5) ])
+ pinSizer.Add(sizer, 0, wx.ALL, 5)
+ pinSizer.Add((0, 0), 1)
+ self.pinButton = ToggleButton(self, bitmap=images.ToolPin.GetBitmap(),
+ style=wx.BORDER_NONE)
+ self.pinButton.SetBitmapSelected(images.ToolPinDown.GetBitmap())
+ self.pinButton.SetToggle(g.conf.panelPinState)
+ self.pinButton.SetToolTipString('Sticky page selection')
+ pinSizer.Add(self.pinButton)
+ topSizer.Add(pinSizer, 0, wx.EXPAND)
+ self.sizer = sizer
+
+ self.nb = wx.Notebook(self, -1)
+ if wx.Platform == '__WXGTK__':
+ # Redefine AddPage on GTK to fix when page added is not shown
+ _oldAddPage = wx.Notebook.AddPage
+ def _newAddPage(self, page, label):
+ _oldAddPage(self, page, label)
+ page.Show(True)
+ wx.Notebook.AddPage = _newAddPage
+
+ # Create scrolled windows for panels
+ self.pageA = ScrolledPage(self.nb)
+ self.nb.AddPage(self.pageA, 'Attributes')
+ # Style page
+ self.pageStyle = ScrolledPage(self.nb)
+ self.pageStyle.Hide()
+ # Extra style page
+ self.pageExStyle = ScrolledPage(self.nb)
+ self.pageExStyle.Hide()
+ # Window attributes page
+ self.pageWA = ScrolledPage(self.nb)
+ self.pageWA.Hide()
+ # Implicit attributes page
+ self.pageIA = ScrolledPage(self.nb)
+ self.pageIA.Hide()
+ # Code page
+ self.pageCode = ScrolledPage(self.nb)
+ self.pageCode.Hide()
+
+ topSizer.Add(self.nb, 1, wx.EXPAND)
+ self.SetSizer(topSizer)
+
+ self.undo = None # pending undo object
+
+ def SetData(self, container, comp, node):
+
+ oldLabel = self.nb.GetPageText(self.nb.GetSelection())
+ self.nb.SetSelection(0)
+ map(self.nb.RemovePage, range(self.nb.GetPageCount()-1, 0, -1))
+
+ # Don't freeze while removing the pages, but do it
+ # after the removes instead. See
+ # https://groups.google.com/d/topic/wxpython-users/I8AJgkUCPj8/discussion
+ self.Freeze()
+
+ self.container = container
+ self.comp = comp
+ self.node = node # main node
+ self.refNode = node
+ panels = []
+ # Class and name
+ if node.nodeType == node.COMMENT_NODE:
+ self.labelRef.Hide()
+ self.textRef.Hide()
+ self.labelClass.Hide()
+ self.textClass.Hide()
+ elif node.tagName == 'object_ref':
+ self.labelRef.Show()
+ self.textRef.Show()
+ self.textRef.SetValue(node.getAttribute('ref'))
+ self.labelClass.Hide()
+ self.textClass.Hide()
+ # 'class' can be present for ref?
+ self.textClass.SetValue(node.getAttribute('class'))
+ else:
+ self.labelRef.Hide()
+ self.textRef.Hide()
+ if comp.klass != 'root':
+ self.labelClass.Show()
+ self.textClass.Show()
+ subclass = node.getAttribute('subclass')
+ if not subclass:
+ self.textClass.SetValue(node.getAttribute('class'))
+ else:
+ self.textClass.SetValue(subclass + '(%s)' % node.getAttribute('class'))
+ else: # root node
+ self.labelClass.Hide()
+ self.textClass.Hide()
+ self.labelRef.Hide()
+ self.textRef.Hide()
+ self.labelName.Show(comp.hasName)
+ self.textName.Show(comp.hasName)
+ if comp.hasName:
+ self.textName.SetValue(node.getAttribute('name'))
+
+ self.Layout() # update after hiding/showing
+
+ panel = AttributePanel(self.pageA, comp.attributes, comp.params, comp.renameDict)
+ panels.append(panel)
+ self.pageA.SetPanel(panel)
+ self.SetValues(panel, node)
+
+ if comp.windowAttributes:
+ panel = AttributePanel(self.pageWA, comp.windowAttributes,
+ rename_dict = params.WARenameDict)
+ panels.append(panel)
+ self.pageWA.SetPanel(panel)
+ self.nb.AddPage(self.pageWA, "Look'n'Feel")
+ self.SetValues(panel, node)
+
+ if comp.styles or comp.genericStyles:
+ # Create style page
+ panel = params.StylePanel(self.pageStyle, comp.styles, comp.genericStyles,
+ equiv = comp.equivStyles)
+ panels.append(panel)
+ self.pageStyle.SetPanel(panel)
+ self.nb.AddPage(self.pageStyle, 'Style')
+ self.SetStyleValues(panel, comp.getAttribute(node, 'style'))
+
+ if comp.exStyles or comp.genericExStyles:
+ # Create extra style page
+ panel = params.StylePanel(self.pageExStyle, comp.exStyles + comp.genericExStyles,
+ tag='exstyle', equiv = comp.equivStyles)
+ panels.append(panel)
+ self.pageExStyle.SetPanel(panel)
+ self.nb.AddPage(self.pageExStyle, 'ExStyle')
+ self.SetStyleValues(panel, comp.getAttribute(node, 'exstyle'))
+
+ # Additional panel for hidden node
+ if container and container.requireImplicit(node) and container.implicitAttributes:
+ panel = AttributePanel(self.pageIA,
+ container.implicitAttributes,
+ container.implicitParams,
+ container.implicitRenameDict)
+ panel.comp = container
+ panels.append(panel)
+ self.pageIA.SetPanel(panel)
+ self.nb.AddPage(self.pageIA, container.implicitPageName)
+ self.SetValues(panel, node.parentNode)
+
+ if comp.hasCode:
+ # Create code page
+ panel = CodePanel(self.pageCode, comp.events)
+ panel.node = node
+ panels.append(panel)
+ self.pageCode.SetPanel(panel)
+ self.nb.AddPage(self.pageCode, 'Code')
+ self.SetCodeValues(panel, comp.getAttribute(node, 'XRCED'))
+
+ # Select old page if possible and pin is down
+ if g.conf.panelPinState:
+ for i in range(1, self.nb.GetPageCount()):
+ if oldLabel == self.nb.GetPageText(i):
+ self.nb.SetSelection(i)
+ break
+
+ self.Thaw()
+
+ return panels
+
+ def Clear(self):
+ self.comp = None
+ self.nb.SetSelection(0)
+ map(self.nb.RemovePage, range(self.nb.GetPageCount()-1, 0, -1))
+ self.pageA.Reset()
+ self.undo = None
+
+ self.textClass.SetValue('')
+ self.labelName.Show(False)
+ self.textName.Show(False)
+
+ self.Layout()
+
+ def GetActivePanel(self):
+ if self.nb.GetSelection() >= 0:
+ return self.nb.GetPage(self.nb.GetSelection()).panel
+ else:
+ return None
+
+ # Set data for a panel
+ def SetValues(self, panel, node):
+ panel.node = node
+ if isinstance(panel, AttributePanel) and panel.comp:
+ comp = panel.comp
+ else:
+ comp = self.comp
+ for a,w in panel.controls:
+ value = comp.getAttribute(node, a)
+ w.SetValue(value)
+
+ # Set data for a style panel
+ def SetStyleValues(self, panel, style):
+ panel.style = style
+ panel.node = self.node
+ panel.SetValues([('XRCED', style)])
+
+ # Set data for a style panel
+ def SetCodeValues(self, panel, data):
+ panel.SetValues([('XRCED', data)])
+
+
+################################################################################
+
+class AttributePanel(wx.Panel):
+ '''Particular attribute panel, normally inside a notebook.'''
+ def __init__(self, parent, attributes, param_dict={}, rename_dict={}):
+ wx.Panel.__init__(self, parent, -1)
+ self.controls = []
+ self.comp = None # if not None overrides default component
+ sizer = wx.FlexGridSizer(len(attributes), 2, 0, 0)
+ sizer.AddGrowableCol(1, 0)
+ for a in attributes:
+ # Find good control class
+ paramClass = param_dict.get(a, params.paramDict.get(a, params.ParamText))
+ sParam = rename_dict.get(a, a)
+ control = paramClass(self, sParam)
+ labelPanel = wx.Panel(self, -1)
+ labelSizer = wx.BoxSizer()
+ labelPanel.SetSizer(labelSizer)
+ if control.isCheck: # checkbox-like control
+ label = wx.StaticText(labelPanel, -1, control.defaultString)
+ sizer.AddMany([ (control, 1, wx.EXPAND),
+ (labelPanel, 1, wx.EXPAND) ])
+ labelSizer.Add(label, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 2)
+ else:
+ if sParam:
+ label = wx.StaticText(labelPanel, -1, sParam, size=labelSize)
+ sizer.AddMany([ (labelPanel, 1, wx.EXPAND),
+ (control, 1, wx.EXPAND) ])
+ else: # for node-level params
+ label = wx.StaticText(labelPanel, -1, '')
+ sizer.Add(control, 1, wx.LEFT, 20)
+ labelSizer.Add(label, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 20)
+ self.controls.append((a, control))
+ self.SetSizerAndFit(sizer)
+
+ def GetValues(self):
+ '''Generic method used for creating XML and for other operations.'''
+ return [(a,c.GetValue()) for a,c in self.controls]
+
+ def SetValues(self, values):
+ '''Generic method used for undo.'''
+ for ac,a2v in zip(self.controls, values):
+ a,c = ac
+ v = a2v[1]
+ c.SetValue(v)
+
+################################################################################
+
+class CodePanel(wx.Panel):
+ ID_BUTTON_DEL = wx.NewId()
+ ID_COMBO_EVENT = wx.NewId()
+ ART_REMOVE = 'ART_REMOVE'
+
+ '''Code generation panel.'''
+ def __init__(self, parent, events):
+ wx.Panel.__init__(self, parent, -1)
+ self.SetFont(g.smallerFont())
+ self.events = events
+ self.checks = []
+ topSizer = wx.BoxSizer(wx.HORIZONTAL)
+ # Events on the left
+ leftSizer = wx.BoxSizer(wx.VERTICAL)
+ sizer = wx.GridSizer(cols=1, vgap=0, hgap=5)
+ label = wx.StaticText(self, label='Events')
+ label.SetFont(g.labelFont())
+ sizer.Add(label, 0, wx.LEFT, 20)
+ for ev in events:
+ check = wx.CheckBox(self, label=ev)
+ sizer.Add(check)
+ self.checks.append((ev, check))
+ leftSizer.Add(sizer)
+ # Additional comboboxes
+ self.extra = []
+ self.eventSizer = wx.FlexGridSizer(cols=2)
+ leftSizer.Add(self.eventSizer)
+ topSizer.Add(leftSizer)
+ # Right sizer
+ rightSizer = wx.BoxSizer(wx.VERTICAL)
+ rightSizer.Add((0, 10))
+ if g.Presenter.container is not component.Manager.rootComponent:
+ self.checkVar = wx.CheckBox(self, label='assign variable')
+ rightSizer.Add(self.checkVar, 0, wx.LEFT, 20)
+ else:
+ self.checkVar = None
+ topSizer.Add(rightSizer)
+ # Cach all checkbox events
+ self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
+ self.SetSizerAndFit(topSizer)
+ # Extra combos and buttons
+ self.Bind(wx.EVT_BUTTON, self.OnButtonDel, id=self.ID_BUTTON_DEL)
+ self.Bind(wx.EVT_COMBOBOX, self.OnComboEvent, id=self.ID_COMBO_EVENT)
+ self.Bind(wx.EVT_TEXT, self.OnComboText, id=self.ID_COMBO_EVENT)
+
+ def GetValues(self):
+ events = []
+ for s,check in self.checks:
+ if check.IsChecked(): events.append(s)
+ # Encode data to a dictionary and the cPicke it
+ data = {}
+ for btn,combo in self.extra[:-1]:
+ events.append(combo.GetValue())
+ if events: data['events'] = '|'.join(events)
+ if self.checkVar and self.checkVar.GetValue(): data['assign_var'] = '1'
+ if data:
+ return [('XRCED', data)]
+ else:
+ return []
+
+ def AddExtraEvent(self, event=''):
+ btn = wx.BitmapButton(self, self.ID_BUTTON_DEL,
+ bitmap=wx.ArtProvider.GetBitmap(self.ART_REMOVE, wx.ART_BUTTON),
+ size=(20,20))
+ if not event: btn.Disable()
+ self.eventSizer.Add(btn, 0, wx.ALIGN_CENTRE_VERTICAL)
+ combo = wx.ComboBox(self, self.ID_COMBO_EVENT, value=event, choices=component.Component.genericEvents)
+ btn.combo = combo
+ self.eventSizer.Add(combo)
+ self.extra.append((btn, combo))
+
+ def SetValues(self, values):
+ data = values[0][1]
+ events = data.get('events', '').split('|')
+ if events == ['']: events = []
+ for ev,check in self.checks:
+ check.SetValue(ev in events)
+ # Add comboboxes for other events
+ for ev in events:
+ if ev not in self.events:
+ self.AddExtraEvent(ev)
+ # Empty combo box for adding new events
+ self.AddExtraEvent()
+ self.Fit()
+ self.SetMinSize(self.GetBestSize())
+ if self.checkVar:
+ self.checkVar.SetValue(int(data.get('assign_var', '0')))
+
+ def OnCheck(self, evt):
+ g.Presenter.setApplied(False)
+
+ def OnButtonDel(self, evt):
+ btn = evt.GetEventObject()
+ self.extra.remove((btn, btn.combo))
+ btn.combo.Destroy()
+ btn.Destroy()
+ self.eventSizer.Layout()
+ self.Fit()
+ self.SetMinSize(self.GetBestSize())
+ g.Presenter.setApplied(False)
+
+ def OnComboText(self, evt):
+ if evt.GetEventObject() == self.extra[-1][1]:
+ self.extra[-1][0].Enable()
+ self.AddExtraEvent()
+ self.eventSizer.Layout()
+ self.Fit()
+ self.SetMinSize(self.GetBestSize())
+ g.Presenter.setApplied(False)
+
+ def OnComboEvent(self, evt):
+ if evt.GetEventObject() == self.extra[-1][1]:
+ self.extra[-1][0].Enable()
+ self.AddExtraEvent()
+ self.eventSizer.Layout()
+ self.Fit()
+ self.SetMinSize(self.GetBestSize())
+ g.Presenter.setApplied(False)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/CHANGES.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/CHANGES.txt
new file mode 100644
index 0000000..489c44e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/CHANGES.txt
@@ -0,0 +1,458 @@
+0.2.1-1
+-------
+* ticket #13573 (test view for items without a name selects parent view)
+* do not set modified flag if starting without a file argument
+* ticket #14282
+
+0.2.1-0
+-------
+
+Merged patch by darktjm with fixes and enhansements:
+
+* equivalent styles for supporting deprecated style flags
+* wxCheckListBox content editing
+* edit capability in item lists
+* support for tooltip/helptext attrs of radiobox items
+* break pseudoclass for menus
+* wxAnimationCtrl, wxRichTextCtrl (disabled), wxDirPickerCtrl,
+ wxFontPickerCtrl, wxColourPickerCtrl, wxOwnerDrawnComboBox,
+ wxBitmapComboBox (partial), wxCollapsiblePane
+
+0.2.0-9
+-------
+
+Fixed ticket 10775 (TreeListCtrl styles).
+
+0.1.8-8
+-------
+
+Fixed several issues related to comment nodes. Test view for a "pragma"
+comment node executes it.
+
+0.1.8-7
+-------
+
+Restored a feature present in the old XRCed: interpreted comment nodes
+(inserted using 'comment' command from the top-level pull-down menu).
+Comments starting with '%' are executed in the context of main module
+(xrced.py) when the file is being loaded. This allows, for example, to
+preload external resource files as follows:
+
+%Manager.addExternal('external.xrc')
+
+where external.xrc may contain resources references by the current
+resource file (using object_ref tag).
+
+0.1.8-6
+-------
+
+Various fixes and improvements to get look-and-feel similar across
+different platforms.
+
+0.1.8-5
+-------
+
+Preferences for default "sizeritem" parameters for new panels and
+controls can be configured ("File">"Preferences...").
+
+Implemented comment object for including simple one-line comments and
+comment directives as tree nodes. No validation is performed for a
+valid XML string so comments must not contain "-->". Comment directive
+is a special comment starting with '%' character, followed by a line
+of python code. It is executed using 'exec' when the resource file is
+opened. This is useful to import plugin modules containing custom
+handlers which are specific to the resource file, hovewer this is of
+course a security hole if you use foreign XRC files. A warning is
+displayed if the preference option 'ask' is selected (by default).
+
+Added support for custom controls and plugin modules. Refer to this
+wxPythonWiki for the details:
+ http://wiki.wxpython.org/index.cgi/XRCed#custom
+
+Tool panel sections can be collapsed/expanded by clicking on the
+label of a tool group.
+
+Some undo/redo and other fixes.
+
+0.1.8-4
+-------
+
+Fixes for wxMSW (notebook highlighting, control sizes, tree Unselect).
+
+0.1.8-3
+-------
+
+Notebook page highlighting fix. Highlight resizes when the window
+is resized. ParamUnit spin button detects event handler re-entry
+(wxGTK probably has a bug in wxSpinButton with repeated events).
+
+0.1.8-2
+-------
+
+Fix for dealing with empty 'growable' property, using MiniFrame
+for properties panel, the panel is restored together with the
+main window.
+
+0.1.8-1
+-------
+
+Fixed SetItemBold and editing 'growable' properties of
+wxFlexGridSizer.
+
+0.1.8-0
+-------
+
+New feature added from a patch submitted on sourceforge by botg:
+moving of tree items.
+
+Bugs fixed:
+- ChecklistBox content editing;
+- Window styles more in sync with the docs;
+- Replacing items;
+- Reference property page created correctly (every property is
+ optional).
+
+0.1.7-5
+-------
+
+Fix for non-ascii characters support when using other encodings
+than utf-8 in 'content' property. Tested under unicode build.
+
+0.1.7-4
+-------
+
+Second fix for Copy/Paste (using expat.native_encoding property).
+Added cellpos,cellspan properties for Spacer in GridBag sizer.
+
+0.1.7-3
+-------
+
+Fix for Copy/Paste objects with international characters.
+
+0.1.7-2
+-------
+
+Fixed Cut command, added support for MenuBar inside Frame/Dialog.
+
+0.1.7-1
+-------
+
+Important update of Paste command code which was passing too much data
+thru clipboard using cPickle. Objects created while unpickling (from
+minidom) were clogging memory. Now using toxml() (why didn't I do it
+before - was I drunk or what? :) ).
+
+0.1.7-0
+-------
+
+Added new controls (Choicebook, Listbook, StatusBar, DatePicker), and
+completed style flags. Test window is opened for an available parent
+control if no specific view defined. Better handling of exceptions
+(highlighting does not 'stick' anymore). Tested on wxGTK 2.6.1.0.
+
+0.1.6-7
+-------
+
+Using system clipboard for Copy/Paste.
+
+0.1.6-6
+-------
+
+Improved some dialogs (window styles, growable cols). Changed the
+range for wxSpinCtrl min/max to all integers (default 0/100 is not
+always good).
+
+0.1.6-5
+-------
+
+Fixed testing for any element inside object tree.
+
+0.1.6-4
+-------
+
+Fixed replacing op for sizer children and spacer objects.
+UndoReplace is not yet implemented.
+
+0.1.6-3
+-------
+
+Fix for crash when opening new file with active tree selection.
+Replacing controls bug fixed.
+
+0.1.6-2
+-------
+
+wxMSW wxTreeCtrl behaviour is still different from wxGTK for
+wxTR_MULTIPLE, some fixes for this.
+
+0.1.6-1
+-------
+
+New (experimental ;) ) feature: support for "object_ref" tag, for
+creating references to named objects (see tn0014.txt). "reference..."
+menu command creates new object_ref node. Properties of the top-level
+object can be overriden, but overriding child controls is not working
+as expected (maybe a bug in wx).
+
+0.1.5-3
+-------
+
+xxxStdDialogButtonSizer pulldown menu with standard buttons.
+
+Some fixes for selecting tools inside toolbar with test window open
+(whole toolbar is selected).
+
+Toolbars can be added inside windows.
+
+0.1.5-2
+-------
+
+Using wx.GetDefaultPyEncoding/wx.SetDefaultPyEncoding for changing active encoding.
+
+Fixed pasting siblings (Ctrl key pressed while pasting).
+
+Dealed with ascii build (Python does not recognize 'ascii' as valid encoding).
+If encoding is not specified it is not written in XRC. Will add more
+customization in the future.
+
+Changed to use SimpleTool instead or Toggle tool (does not work on Win32).
+
+0.1.5-1
+-------
+
+Added wxWizard, wxWizardPageSimple (only from pull-down menu).
+
+Hide command for test window.
+
+Replacing classes works better.
+
+Added Locate tool.
+
+0.1.4-1
+-------
+
+Edit->Locate command (Ctrl-L) for quick selection of items.
+Works with event-handling controls (buttons, text fields) but
+not with labels/sizers.
+
+Some improvements: relative paths for files supplied as command-
+line argument work correctly, notebook panels are highlighted
+better.
+
+0.1.2-1
+_______
+
+Added support for wxGridBagSizer (supported in wxPython 2.5).
+
+0.1.1-5
+-------
+
+Added subclass attribute.
+
+0.1.1-4
+-------
+
+Fixed problems with wxStaticBitmap (stock_id attribute, icon type
+switching).
+
+Changed some dimensions in properties panel elements.
+
+0.1.1-3
+-------
+
+Sizes of some controls were not normal on wxMSW. Fixed.
+
+Some changes to test window code to make it resize better and to
+have focus control with sawfish for all types of windows.
+
+0.1.1-2
+-------
+
+Bugs with currentEncoding and frame testing fixed.
+
+Some required parameters are set to default if missing.
+
+Unsupported classes are tolerated, with warning message.
+
+wxScrolledWindow added (to 'control' pulldown menu, not yet to the
+tool palette).
+
+Multi-line editing for labels and some values (wxTextCtrl,
+wxHtmlWindow).
+
+0.1.1-1
+-------
+
+Changed internationalization support. '-i' option removed, default
+encoding is used (should be defined in sitecustomize.py, or 'ascii' by
+default). When XRC file is opened with encoding specified,
+translations are not used.
+
+0.1.1
+-----
+
+Replace command added (not quite finished yet).
+
+0.1.0
+-----
+
+Finally implemented tools panel for almost all controls (except
+wxHtmlWindow, wxCalendarCtrl and wxGenericDirCtrl - they are too
+rarely used).
+
+Changed some sizes in panel to better work with different fonts.
+
+Fixed double-refreshing after Ctrl+R.
+
+Maybe something else that I've forgot. It's been a looong day... :)
+
+
+0.0.9-6
+-------
+
+Added dialog unit support.
+
+Dealing with non-specified required values (set to defaults, if exist).
+
+Added 'minsize' parameter of sizeritem.
+
+Added '-i' option to turn off translations and use international characters.
+
+0.0.9-5
+-------
+
+Mac platform-specific checks.
+
+0.0.9-4
+-------
+
+Implemented standard bitmap selection.
+
+Fixed a bug in FlexGridSizer code.
+
+0.0.9-3
+-------
+
+File browsing (for bitmaps/icons, etc.) had a small problem when current
+file was not saved yet.
+
+0.0.9-2
+-------
+
+Small bug fix for initial don't panic message.
+
+0.0.9-1
+-------
+
+Changed program structure, reduced use of global variables (grouped in
+module 'globals', which creates an instanse 'g' of class Globals.
+
+First version of undo/redo working!
+
+Support for toolbars inside panels and frames.
+
+Added 'container' submenu for creating Panel, Notebook and ToolBar objects.
+
+wxMSW-only: added code to switch focus back to main window when test
+window is updated.
+
+0.0.8-2
+-------
+
+Fixed unicode problem for unicode build.
+
+0.0.8-1
+-------
+
+Using WX_2_4_BRANCH.
+
+Added new controls: wxSpinCtrl, wxGenericDirCtrl, unknown (custom
+control), improved wxXRC format suppor (menu styles, etc.).
+
+Some I18N support: parsing "encoding" attribute in XML header, later
+it can be modified in "properties" panel for "XML tree".
+
+UNIX note: currently XML writing for non-ascii chars works only if
+sys.getdefaultencoding() returns good value. To do this, one has to
+put following lines to "sitecustomize.py" file:
+
+# Start code segment
+import sys
+sys.setdefaultencoding('iso-8859-1') # or whatever
+# End code segment
+
+0.0.7
+-----
+
+Some command-line arguments.
+
+"Test window" command and toolbar button.
+
+New panel interphace (wxHTMLWindow is not used anymore).
+
+Toggling between embedded and detached panel.
+
+Cache for already used windows.
+
+Current top-level control is bold, if test window shown.
+
+Undo/redo broken.
+
+CheckListBox does not work unless wxXRC source fixed (in both wxPytnon and
+wxWin):
+
+contrib/src/xrc/xmlrsall.cpp
+45,46c45,46
+< AddHandler(new wxListCtrlXmlHandler);
+< #if CHECKLISTBOX
+---
+> AddHandler(new wxListCtrlXmlHandler);
+> #if wxUSE_CHECKLISTBOX
+
+This is fixed in CVS.
+
+0.0.6
+-----
+
+Toolbar, bitmap, icon support (no display yet).
+
+Changed parameter objects, added support for multiple parameters (like
+`growablecols').
+
+Fixed double-clicking problem with tree control on Windows.
+
+Some performance improovements.
+
+
+0.0.5
+-----
+
+Added notebook with properties page and style page. Fixed some problems
+on Windows.
+
+
+0.0.4
+-----
+
+Some fixes suggested by RD
+
+
+0.0.3
+-----
+
+Faster preview window refresh.
+
+Cut/Paste works better.
+
+Some tree icons.
+
+Tree item names.
+
+Bugfixes.
+
+
+0.0.2
+-----
+
+The first release.
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/README.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/README.txt
new file mode 100644
index 0000000..a0b1738
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/README.txt
@@ -0,0 +1,91 @@
+********************************************************************************
+
+ XRCed README
+
+********************************************************************************
+
+System requirements
+-------------------
+
+wxPython version must be recent enough to support all features (a warning
+message is shown if not).
+
+
+User requirements
+-----------------
+
+To use XRCed it is really important to be familiar with wxWindows class names
+and at least partially with XRC resource format (read
+wxWindows/doc/tech/tn0014.txt for reference).
+
+
+Short manual
+------------
+
+XRCed's idea is very straightforward: it is a visual tool for editing an XML
+file conforming to XRC format. Every operation performed in XRCed has direct
+correspondence to XML structure. So it is not really a usual point-and-click
+GUI builder, but don't let that scare you.
+
+To start xrced, change to the directory where you installed it and run
+"python2.2 xrced.py".
+
+On UNIX you can edit wrapper script "xrced.sh" to point to your installation
+directory.
+
+To create an object, first you should select some object in the tree (or the
+root item if it's empty) then press the right mouse button and select an
+appropriate command. The pulldown menu is context-dependent on the selected
+object.
+
+XRCed tries to guess if new object should be added as a next sibling or a
+child of current object, depending on the possibility of the object to have
+child objects and expanded state (if tree item is collapsed, new object will
+be sibling). You can change this behavior to create siblings by pressing and
+holding the Shift and Control keys before clicking the mouse.
+
+Pressed Control key while pressing right button makes next item a sibling of
+selected item regardless of its expanded state.
+
+Pressed Shift key changes the place for inserting new child to be before
+selected child, not after as by default.
+
+Panel on the right contains object properties. Properties which are optional
+should be "checked" first. This panel can be made separate by unchecking
+"Embed Panel" in View menu.
+
+All properties can be edited as text, and some are supplied with special
+editing controls.
+
+When no 'Edit' button is provided for editing a property's value, it is
+supposed to be copied verbatim to XRC file.
+
+The names of the properties are exactly as in XRC file, and it's usually not
+hard to guess what they do. "XML ID" is the name of the window, and must be
+present for top-level windows (though this is not enforced by XRCed).
+
+To display the preview window double-click a top-level object (you should
+assign an XMLID to it first), press "Test" toolbar button or select command
+from View menu, or press F5. After that, if you select a child object, it
+becomes highlighted, and if you change it, preview is updated when you select
+another item or press Ctrl-R (refresh). To turn off automatic update, toggle
+"View->Auto-refresh" or toolbar auto-refresh button (to the right of the
+refresh button). If you double-click a non-window object (a button for
+example), then test view is created for a closest ancestor which is a window.
+
+
+Bugs
+----
+
+- Some combinations of parent/child windows are not valid but possible to put
+ into XML tree by using XRCed. Usually this produces a meaningful error
+ message from XRC library when test view is opened.
+
+- Be careful when replacing a non-empty container control with another class,
+ and check parameters which can be copied from the previous object but not
+ valid for the new one. Is it not possible to undo replacement yet.
+
+
+--------------------------------------------------------------------------------
+
+Copyright 2001-2005 Roman Rolinsky <rollrom@xrced.sourceforge.net>
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/TODO.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/TODO.txt
new file mode 100644
index 0000000..83f854d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/TODO.txt
@@ -0,0 +1,33 @@
+TODO for XRCed with plugins
+===========================
+
+- copy/paste for multiple items
+
++ better help
+
+- undo/redo (op-specific)
+
+- put some default values in tree ctrl etc.
+
+- special (fast) update for some values: pos/size, value/content, sizeritem
+ stuff (?), well, as much as possible
+
++ highlighting with better method
+
+- import XRC files
+
+- selecting object by clicking in test window
+
++ fix DnD highlight for miniframe
+
++ fix integer parameter text edit (not updated)
+
+- panel scroll update after page change with AUI
+
++ test without frame: bind size to main sizer
+
++ test with frame: use Fit
+
+- test with non-top-level: add resizing
+
+- implement templates
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/TestWin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/TestWin.py
new file mode 100644
index 0000000..0690e46
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/TestWin.py
@@ -0,0 +1,442 @@
+# Name: view.py
+# Purpose: TestWindow and related classes
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 13.07.2007
+# RCS-ID: $Id: view.py 47356 2007-07-12 01:00:57Z ROL $
+
+from globals import *
+import wx
+import view
+from component import Manager
+
+def getAllChildren(w):
+ '''Get all children recursively.'''
+ children = []
+ for ch in w.GetChildren():
+ children.append(ch)
+ children.extend(getAllChildren(ch))
+ return children
+
+class TestWindow:
+ '''Test window manager showing currently edited subtree.'''
+ def __init__(self):
+ self.Init()
+
+ def Init(self):
+ self.hl = self.hlDT = None # highlight objects (Rect)
+ self.frame = self.object = None # currenly shown frame and related object
+ self.item = None
+ self.pos = wx.DefaultPosition
+ self.size = wx.DefaultSize
+ self.isDirty = False # if refresh needed
+ self.trash = [] # trash to be destroyed later
+
+ def SetView(self, frame, object, item):
+ '''
+ Set current test objects: frame is testwin frame, object is top-level object,
+ item is top-level item.
+ '''
+ TRACE('SetView %s %s', frame, object)
+ restoreSize = False
+ if self.object:
+ # Old window must be destroyed if new uses different frame
+ # or is itself a toplevel window
+ if not frame or frame and not self.frame:
+ # Remember old item
+ if item == self.item:
+ restoreSize = True
+ TRACE('Closing old frame, restoreSize=%d', restoreSize)
+ self.GetFrame().Close()
+ elif self.frame:
+ # Destroy old object but re-use frame
+ self.object.Destroy()
+ self.frame = frame
+ self.object = object
+ self.isDirty = False
+ object.SetDropTarget(DropTarget(object))
+ if wx.Platform == '__WXMAC__':
+ for ch in getAllChildren(object):
+ ch.SetDropTarget(DropTarget(ch))
+ if wx.Platform == '__WXMSW__':
+ object.Bind(wx.EVT_PAINT, self.OnPaint)
+ if self.pos != wx.DefaultPosition:
+ self.GetFrame().SetPosition(self.pos)
+ if restoreSize: # keep same size in refreshing
+ TRACE('restoring size %s', self.size)
+ self.GetFrame().SetSize(self.size)
+ self.item = item
+ self.hl = self.hlDT = None
+ g.Listener.InstallTestWinEvents()
+
+ def OnPaint(self, evt):
+ # This is a completely crazy way to force wxMSW to refresh
+ # highlight _after_ window is painted
+ dc = wx.PaintDC(self.object)
+ dc.Destroy()
+ self.object.Bind(wx.EVT_IDLE, self.OnIdle)
+
+ def OnIdle(self, evt):
+ self.object.Unbind(wx.EVT_IDLE)
+ if self.hl: self.hl.Refresh()
+ if self.hlDT: self.hlDT.Refresh()
+
+ def GetFrame(self):
+ if self.frame: return self.frame
+ else: return self.object
+
+ def Show(self, show=True):
+ TRACE('TestWindow.Show')
+ self.GetFrame().Show(show)
+
+ # re-raise the main window so the test window doesn't steal
+ # the activation from it.
+ if g.lastActiveFrame:
+ g.lastActiveFrame.Raise()
+
+ def IsShown(self):
+ return self.object is not None and self.object.IsShown()
+
+ def IsDirty(self):
+ '''If test window must be refreshed.'''
+ return self.IsShown() and self.isDirty
+
+ def EmptyTrash(self):
+ [l.Destroy() for l in self.trash]
+ self.trash = []
+
+ def Destroy(self):
+ TRACE('Destroy test window')
+ # Remember dimensions
+ self.pos = self.GetFrame().GetPosition()
+ self.size = self.GetFrame().GetSize()
+ self.RemoveHighlight()
+ self.RemoveHighlightDT()
+ self.GetFrame().Destroy()
+ self.frame = self.object = self.item = None
+ self.isDirty = False
+
+ # Find the object for an item
+ def FindObject(self, item):
+ tree = view.tree
+ if not item or item == tree.root:
+ return None
+ if item == self.item: return self.object
+ # Traverse tree until we reach the root or the test object
+ items = [item]
+ while 1:
+ item = tree.GetItemParent(item)
+ if item == tree.root: return None # item outside if the test subtree
+ elif item == self.item: break
+ else: items.append(item)
+ # Now traverse back, searching children
+ obj = self.object
+ comp = Manager.getNodeComp(tree.GetPyData(self.item))
+ while items and obj:
+ if not (isinstance(obj, wx.Window) or isinstance(obj, wx.Sizer)):
+ return None
+ parentItem = item
+ item = items.pop()
+ index = tree.ItemIndexWin(item)
+ obj = comp.getChildObject(tree.GetPyData(parentItem), obj, index)
+ node = tree.GetPyData(item)
+ comp = Manager.getNodeComp(node)
+ return obj
+
+ # Find tree item corresponding to testWin object
+ def FindObjectItem(self, item, obj):
+ # We simply perform depth-first traversal, sinse it's too much
+ # hassle to deal with all sizer/window combinations
+ w = self.FindObject(item)
+ if w == obj or isinstance(w, wx.SizerItem) and w.GetWindow() == obj:
+ return item
+ if view.tree.ItemHasChildren(item):
+ child = view.tree.GetFirstChild(item)[0]
+ while child:
+ found = self.FindObjectItem(child, obj)
+ if found: return found
+ child = view.tree.GetNextSibling(child)
+ return None
+
+ # Find the rectangle or rectangles corresponding to a tree item
+ # in the test window (or return None)
+ def FindObjectRect(self, item):
+ tree = view.tree
+ if not item or item == tree.root: return None
+ if item == self.item: # top-level
+ comp = Manager.getNodeComp(tree.GetPyData(item))
+ rects = comp.getRect(self.object)
+ if not self.frame and rects:
+ # Make rects relative to the object (for top-level windows)
+ offset = wx.Point(-rects[0].GetLeft(),-rects[0].GetTop())
+ [r.Offset(offset) for r in rects]
+ return rects
+ # Traverse tree until we reach the root or the test object
+ items = [item]
+ while 1:
+ item = tree.GetItemParent(item)
+ if item == self.item: break
+ elif item == tree.root: return None # item outside of the test subtree
+ else: items.append(item)
+ # Now traverse back from parents to children
+ obj = self.object
+ if self.frame:
+ # Maybe GetClientAreaOrigin should not return (0,0) for panels with borders
+ offset = obj.ClientToScreen((0,0)) - self.frame.panel.ClientToScreen((0,0))
+ else:
+ offset = wx.Point(0,0)
+ rects = None
+ comp = Manager.getNodeComp(tree.GetPyData(self.item))
+ while items and obj:
+ if not (isinstance(obj, wx.Window) or isinstance(obj, wx.Sizer)):
+ return None
+ parentItem = item
+ if rects: parentRect = rects[0]
+ parent = obj
+ item = items.pop()
+ index = tree.ItemIndexWin(item)
+ obj = comp.getChildObject(tree.GetPyData(parentItem), parent, index)
+ if isinstance(parent, wx.Notebook) and index != parent.GetSelection():
+ parent.SetSelection(index)
+ node = tree.GetPyData(item)
+ comp = Manager.getNodeComp(node)
+ rects = comp.getRect(obj)
+ if not rects: return None
+ r = rects[0]
+ if isinstance(parent, wx.Sizer) and parentRect:
+ sizerItem = parent.GetChildren()[index]
+ flag = sizerItem.GetFlag()
+ border = sizerItem.GetBorder()
+ if border != 0:
+ x = (r.GetLeft() + r.GetRight()) / 2
+ if flag & wx.TOP:
+ rects.append(wx.Rect(x, r.GetTop() - border, 0, border))
+ if flag & wx.BOTTOM:
+ rects.append(wx.Rect(x, r.GetBottom() + 1, 0, border))
+ y = (r.GetTop() + r.GetBottom()) / 2
+ if flag & wx.LEFT:
+ rects.append(wx.Rect(r.GetLeft() - border, y, border, 0))
+ if flag & wx.RIGHT:
+ rects.append(wx.Rect(r.GetRight() + 1, y, border, 0))
+ if isinstance(obj, wx.Notebook) and items:
+ offset += obj.GetClientRect().GetTopLeft()
+ elif isinstance(obj, wx.Window) and items:
+ offset += r.GetTopLeft()
+ [r.Offset(offset) for r in rects]
+ return rects
+
+ # Return highlight parent window
+ def HLParent(self):
+ if self.frame: return self.frame.panel
+ else: return self.object
+
+ def Highlight(self, rect):
+ if not self.hl:
+ self.hl = Highlight(self.HLParent(), rect)
+ else:
+ self.hl.Move(rect)
+
+ def HighlightDT(self, rect, item):
+ if not self.hlDT:
+ self.hlDT = Highlight(self.HLParent(), rect, wx.BLUE, False)
+ self.hlDT.origColour = view.tree.GetItemTextColour(item)
+ else:
+ self.hlDT.Move(rect)
+ view.tree.SetItemTextColour(self.hlDT.item, self.hlDT.origColour)
+ view.tree.SetItemTextColour(item, view.tree.COLOUR_DT)
+ self.hlDT.item = item
+
+ def RemoveHighlight(self):
+ if self.hl is None: return
+ self.hl.Destroy()
+ self.EmptyTrash()
+ self.hl = None
+
+ def RemoveHighlightDT(self):
+ if self.hlDT is None: return
+ if self.hlDT.item:
+ view.tree.SetItemTextColour(self.hlDT.item, self.hlDT.origColour)
+ # Destroying is sensitive if done directly in DropTarget methods
+ wx.CallAfter(self.hlDT.Destroy)
+ self.hlDT = None
+ view.frame.SetStatusText('')
+
+
+################################################################################
+
+# DragAndDrop
+
+class DropTarget(wx.DropTarget):
+ def __init__(self, win):
+ self.win = win
+ self.do = MyDataObject()
+ wx.DropTarget.__init__(self, self.do)
+ self.onHL = self.left = False
+
+ # Find best object for dropping
+ def WhereToDrop(self, x, y, d):
+ # Find object by position
+ if wx.Platform == '__WXMAC__': # on mac x,y relative to children
+ scrPos = self.win.ClientToScreen((x,y))
+ else:
+ scrPos = view.testWin.object.ClientToScreen((x,y))
+ obj = wx.FindWindowAtPoint(scrPos)
+ if not obj:
+ return wx.DragNone, ()
+ if obj.GetId() == Highlight.ID_HL:
+ self.onHL = True
+ return d, ()
+ item = view.testWin.FindObjectItem(view.testWin.item, obj)
+ if not item:
+ return wx.DragNone, ()
+ # If window has a sizer use it as parent
+ if obj.GetSizer():
+ obj = obj.GetSizer()
+ item = view.testWin.FindObjectItem(view.testWin.item, obj)
+ return d, (obj,item)
+
+ # Drop
+ def OnData(self, x, y, d):
+ view.testWin.RemoveHighlightDT()
+ self.onHL = self.left = False
+ self.GetData()
+ id = int(self.do.GetDataHere())
+ d,other = self.WhereToDrop(x, y, d)
+ if d != wx.DragNone and other:
+ obj,item = other
+ g.Presenter.setData(item)
+ comp = Manager.findById(id)
+ mouseState = wx.GetMouseState()
+ forceSibling = mouseState.ControlDown()
+ forceInsert = mouseState.ShiftDown()
+ g.Presenter.updateCreateState(forceSibling, forceInsert)
+ if not g.Presenter.checkCompatibility(comp):
+ return wx.DragNone
+ item = g.Presenter.create(comp)
+ node = view.tree.GetPyData(item)
+ parentItem = view.tree.GetItemParent(item)
+ parentNode = view.tree.GetPyData(parentItem)
+ parentComp = Manager.getNodeComp(parentNode)
+ # If pos if not set by default and parent is not a sizer, set pos to
+ # drop coordinates
+ if 'pos' in comp.attributes and not comp.getAttribute(node, 'pos') \
+ and parentComp.isContainer() and \
+ not parentComp.isSizer():
+ # Calc relative coords
+ rect = view.testWin.FindObjectRect(parentItem)
+ x -= rect[0].x
+ y -= rect[0].y
+ comp.addAttribute(node, 'pos', '%d,%d' % (x, y))
+ g.Presenter.setData(item)
+ view.frame.SetStatusText('Object created')
+ return d
+
+ def OnDragOver(self, x, y, d):
+ d,other = self.WhereToDrop(x, y, d)
+ if d == wx.DragNone:
+ view.frame.SetStatusText('Inappropriate drop target')
+ view.testWin.RemoveHighlightDT()
+ elif other:
+ if self.left:
+ view.testWin.RemoveHighlightDT()
+ self.onHL = self.left = False
+ obj,item = other
+ hl = view.testWin.hlDT
+ if not hl or hl.item != item:
+ rect = view.testWin.FindObjectRect(item)
+ if not rect: return wx.DragNone
+ view.testWin.HighlightDT(rect, item)
+ view.tree.EnsureVisible(item)
+ view.frame.SetStatusText('Drop target: %s' % view.tree.GetItemText(item))
+ return d
+
+ def OnLeave(self):
+ # Try to prevent flashing when pointer passes on highlight lines
+ if self.onHL:
+ view.testWin.RemoveHighlightDT()
+ self.onHL = False
+ else: self.left = True
+
+################################################################################
+
+class Highlight:
+ '''
+ Create a highlight rectangle by using multiple windows. rect is a
+ single Rect or a list of Rects (for sizeritems).
+ '''
+ ID_HL = wx.NewId()
+ def __init__(self, w, rect, colour=wx.Colour(222,0,0), more_lines=True):
+ self.win = w
+ self.colour = colour
+ self.moreLines = more_lines
+ rects = rect[1:]
+ rect = rect[0]
+ if rect.width == -1: rect.width = 0
+ if rect.height == -1: rect.height = 0
+ self.lines = [wx.Window(w, self.ID_HL, rect.GetTopLeft(), (rect.width, 2)),
+ wx.Window(w, self.ID_HL, rect.GetTopLeft(), (2, rect.height)),
+ wx.Window(w, self.ID_HL, (rect.x + rect.width - 2, rect.y), (2, rect.height)),
+ wx.Window(w, self.ID_HL, (rect.x, rect.y + rect.height - 2), (rect.width, 2))]
+ for l in self.lines:
+ l.SetBackgroundColour(colour)
+ l.SetDropTarget(DropTarget(l))
+ if wx.Platform == '__WXMSW__':
+ [l.Bind(wx.EVT_PAINT, self.OnPaint) for l in self.lines]
+ if more_lines: [self.AddSizerItem(r) for r in rects]
+
+ # Repainting is not always done for these windows on Windows
+ def OnPaint(self, evt):
+ w = evt.GetEventObject()
+ dc = wx.PaintDC(w)
+ w.ClearBackground()
+ dc.Destroy()
+ def Destroy(self, i=0):
+ '''Destroy highlight lines from some index.'''
+ if wx.Platform == '__WXMAC__':
+ [l.Hide() for l in self.lines[i:]]
+ view.testWin.trash.extend(self.lines[i:])
+ else:
+ [l.Destroy() for l in self.lines[i:]]
+ self.lines[i:] = []
+
+ def Refresh(self):
+ [l.Refresh() for l in self.lines]
+
+ def Move(self, rect):
+ rects = rect[1:]
+ rect = rect[0]
+ pos = rect.GetTopLeft()
+ size = rect.GetSize()
+ if size.width == -1: size.width = 0
+ if size.height == -1: size.height = 0
+ self.Destroy(4)
+ self.lines[0].SetDimensions(pos.x, pos.y, size.width, 2)
+ self.lines[1].SetDimensions(pos.x, pos.y, 2, size.height)
+ self.lines[2].SetDimensions(pos.x + size.width - 2, pos.y, 2, size.height)
+ self.lines[3].SetDimensions(pos.x, pos.y + size.height - 2, size.width, 2)
+ [l.Raise() for l in self.lines]
+ if self.moreLines: [self.AddSizerItem(r) for r in rects]
+
+ def AddSizerItem(self, rect):
+ w = self.win
+ # 0 means a line from outer box to inner
+ if rect.width == 0 or rect.height == 0:
+ colour = wx.Colour(255,64,0)
+ if rect.height == 0:
+ line = wx.Window(w, -1, rect.GetTopLeft(), (rect.width, 1))
+ else:
+ line = wx.Window(w, -1, rect.GetTopLeft(), (1, rect.height))
+ line.SetBackgroundColour(colour)
+ self.lines.append(line)
+ return
+ colour = wx.Colour(255,0,0)
+ lines = []
+ lines.append(wx.Window(w, -1, rect.GetTopLeft(), (rect.width, 1)))
+ lines.append(wx.Window(w, -1, rect.GetTopLeft(), (1, rect.height)))
+ if rect.height > 1:
+ lines.append(wx.Window(w, self.ID_HL, (rect.x, rect.y + rect.height - 1), (rect.width, 1)))
+ if rect.width > 1:
+ lines.append(wx.Window(w, self.ID_HL, (rect.x + rect.width - 1, rect.y), (1, rect.height)))
+ for l in lines:
+ l.SetBackgroundColour(colour)
+ l.SetDropTarget(DropTarget(l))
+ self.lines.extend(lines)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/XMLTree.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/XMLTree.py
new file mode 100644
index 0000000..6a3cd32
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/XMLTree.py
@@ -0,0 +1,265 @@
+# Name: XMLTree.py
+# Purpose: XMLTree class
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 31.05.2007
+# RCS-ID: $Id: XMLTree.py 64627 2010-06-18 18:17:45Z ROL $
+
+from globals import *
+from model import Model
+from component import Manager, Component, Container
+import images
+
+class XMLTree(wx.TreeCtrl):
+ def __init__(self, parent):
+ style = wx.TR_HAS_BUTTONS | wx.TR_MULTIPLE | \
+ wx.TR_HIDE_ROOT | wx.TR_LINES_AT_ROOT
+ wx.TreeCtrl.__init__(self, parent, style=style)
+
+ self.locals = {} # namespace for comment directives
+
+ # Color scheme
+ self.SetBackgroundColour(wx.Colour(222, 248, 222))
+ self.COLOUR_COMMENT = wx.Colour(0, 0, 255)
+ self.COLOUR_REF = wx.Colour(0, 0, 128)
+ self.COLOUR_HIDDEN = wx.Colour(128, 128, 128)
+ self.COLOUR_HL = wx.Colour(255, 0, 0)
+ self.COLOUR_DT = wx.Colour(0, 0, 255)
+
+ # Comments use italic font
+ self.fontComment = wx.FFont(self.GetFont().GetPointSize(),
+ self.GetFont().GetFamily(),
+ wx.FONTFLAG_ITALIC)
+
+ # Create image list
+ il = wx.ImageList(22, 22, True)
+ # 0 is the default image index
+ im = images.TreeDefault.GetImage()
+ if im.GetWidth() != 22 or im.GetHeight() != 22:
+ im.Resize((22,22), ((22-im.GetWidth())/2,(22-im.GetHeight())/2))
+ il.Add(im.ConvertToBitmap())
+ # 1 is the default container image
+ im = images.TreeDefaultContainer.GetImage()
+ if im.GetWidth() != 22 or im.GetHeight() != 22:
+ im.Resize((22,22), ((22-im.GetWidth())/2,(22-im.GetHeight())/2))
+ il.Add(im.ConvertToBitmap())
+ # root icon
+# self.rootImage = il.Add(images.TreeRoot.GetImage().Scale(16,16).ConvertToBitmap())
+ # Loop through registered components which have images
+ for component in Manager.components.values():
+ for im in component.images:
+ # Resize image if necessary
+ if im.GetWidth() != 22 or im.GetHeight() != 22:
+ im.Resize((22,22), ((22-im.GetWidth())/2,(22-im.GetHeight())/2))
+ im.Id = il.Add(im.ConvertToBitmap())
+ self.il = il
+ self.SetImageList(il)
+
+ self.root = self.AddRoot('XML tree') #, self.rootImage)
+ self.SetItemHasChildren(self.root)
+
+ def Clear(self):
+ '''Clear everything except the root item.'''
+ self.UnselectAll()
+ self.DeleteChildren(self.root)
+
+ # Add tree item for given parent item if node is DOM element node with
+ # object/object_ref tag
+ def AddNode(self, parent, node):
+ # Append tree item
+ try:
+ comp = Manager.getNodeComp(node, None)
+ className = comp.klass
+ except:
+ className = node.getAttribute('class')
+ # Try to create some generic component on-the-fly
+ attributes = []
+ isContainer = False
+ for n in node.childNodes:
+ if is_element(n):
+ isContainer = True
+ elif n.nodeType == node.ELEMENT_NODE and not n.tagName in attributes:
+ attributes.append(n.tagName)
+ if isContainer:
+ comp = Container(className, 'unknown', attributes)
+ else:
+ comp = Component(className, 'unknown', attributes)
+ Manager.register(comp)
+ wx.LogWarning('Unknown component class "%s", registered as generic' % className)
+ item = self.AppendItem(parent, comp.getTreeText(node),
+ image=comp.getTreeImageId(node),
+ data=wx.TreeItemData(node))
+ self.SetItemStyle(item, node)
+ # Try to find children objects
+ if comp.isContainer():
+ for n in filter(is_object, node.childNodes):
+ self.AddNode(item, comp.getTreeNode(n))
+ elif node.nodeType == node.COMMENT_NODE:
+ if node.data and node.data[0] == '%' and g.conf.allowExec != 'no':
+ if g.conf.allowExec == 'ask' and Model.allowExec is None:
+ say = wx.MessageBox('''This file contains executable comment directives. \
+Allow to execute?''', 'Warning', wx.ICON_EXCLAMATION | wx.YES_NO)
+ if say == wx.YES:
+ Model.allowExec = True
+ else:
+ Model.allowExec = False
+ if g.conf.allowExec == 'yes' or Model.allowExec:
+ code = node.data[1:] # skip '%'
+ self.ExecCode(code)
+
+ # Maybe this should be moved to presenter?
+ def ExecCode(self, code):
+ logger.debug('executing comment pragma: \n%s', code)
+ try:
+ exec code in globals(), self.locals
+ except:
+ wx.LogError('exec error: "%s"' % code)
+ logger.exception("execution of in-line comment failed")
+
+ def SetItemStyle(self, item, node):
+ # Different color for comments and references
+ if node.nodeType == node.COMMENT_NODE:
+ self.SetItemTextColour(item, self.COLOUR_COMMENT)
+ self.SetItemFont(item, self.fontComment)
+ elif node.tagName == 'object_ref':
+ self.SetItemTextColour(item, self.COLOUR_REF)
+# elif treeObj.hasStyle and treeObj.params.get('hidden', False):
+# self.SetItemTextColour(item, self.COLOUR_HIDDEN)
+
+ def Flush(self):
+ '''Update all items after changes in model.'''
+ self.Clear()
+ # Update root item
+ self.SetPyData(self.root, Model.mainNode)
+ # (first node is test node, skip it)
+ for n in filter(is_object, Model.mainNode.childNodes[1:]):
+ self.AddNode(self.root, n)
+
+ def FlushSubtree(self, item, node):
+ '''Update all items after changes in model.'''
+ if item is None or item == self.root:
+ self.Flush()
+ return
+ self.DeleteChildren(item)
+ className = node.getAttribute('class')
+ try:
+ comp = Manager.components[className]
+ except:
+ # Flush completely if unknown
+ self.Flush()
+ return
+ for n in filter(is_object, node.childNodes):
+ self.AddNode(item, comp.getTreeNode(n))
+
+ def ExpandAll(self):
+ i, cookie = self.GetFirstChild(self.root)
+ while i:
+ self.ExpandAllChildren(i)
+ i, cookie = self.GetNextChild(self.root, cookie)
+
+ def CollapseAll(self):
+ i, cookie = self.GetFirstChild(self.root)
+ while i:
+ self.CollapseAllChildren(i)
+ i, cookie = self.GetNextChild(self.root, cookie)
+
+ # Override to use same form as InsertItem
+ def InsertItemBefore(self, parent, next, label, image=-1, data=None):
+ prev = self.GetPrevSibling(next)
+ if prev:
+ return self.InsertItem(parent, prev, label, image, data=data)
+ else:
+ return self.PrependItem(parent, label, image, data=data)
+
+ def GetSelection(self):
+ if self.GetSelections():
+ return self.GetSelections()[-1]
+ else: return None
+
+ # Return item index in parent
+ def ItemIndex(self, item):
+ n = 0 # index of sibling
+ prev = self.GetPrevSibling(item)
+ while prev.IsOk():
+ prev = self.GetPrevSibling(prev)
+ n += 1
+ return n
+
+ # Full tree index of an item - list of positions
+ def ItemFullIndex(self, item):
+ if not item.IsOk(): return None
+ l = []
+ while item != self.root:
+ l.insert(0, self.ItemIndex(item))
+ item = self.GetItemParent(item)
+ return l
+
+ # Get item position from full index
+ def ItemAtFullIndex(self, index):
+ if index is None: return wx.TreeItemId()
+ item = self.root
+ for i in index:
+ item = self.GetFirstChild(item)[0]
+ for k in range(i): item = self.GetNextSibling(item)
+ return item
+
+ # Return item child index in parent (skip non-window items)
+ def ItemIndexWin(self, item):
+ n = 0 # index of sibling
+ prev = self.GetPrevSibling(item)
+ while prev.IsOk():
+ if self.GetPyData(prev).nodeType != Model.dom.COMMENT_NODE:
+ n += 1
+ prev = self.GetPrevSibling(prev)
+ return n
+
+ # Get expanded state of all items
+ def GetFullState(self, item=None):
+ if not item: item = self.root
+ states = []
+ item = self.GetFirstChild(item)[0]
+ while item:
+ if self.ItemHasChildren(item):
+ state = self.IsExpanded(item)
+ states.append(state)
+ if state: states.extend(self.GetFullState(item))
+ item = self.GetNextSibling(item)
+ return states
+
+ # Set expanded state of all items
+ def SetFullState(self, states, item=None):
+ if not item:
+ item = self.root
+ states = states[:]
+ item = self.GetFirstChild(item)[0]
+ while item:
+ if self.ItemHasChildren(item):
+ state = states.pop(0)
+ if state: self.Expand(item)
+ else: self.Collapse(item)
+ if state: self.SetFullState(states, item)
+ item = self.GetNextSibling(item)
+
+ # Find item with given data (node)
+ def Find(self, item, name):
+ node = self.GetPyData(item)
+ if is_element(node) and node.getAttribute('name') == name:
+ return item
+ item,cookie = self.GetFirstChild(item)
+ while item:
+ found = self.Find(item, name)
+ if found: return found
+ item = self.GetNextSibling(item)
+ return None
+
+ # Fixes for broken and platform-incompatible functions
+
+ def ItemHasChildren(self, item):
+ return self.GetChildrenCount(item)
+
+ if wx.Platform == '__WXMSW__':
+
+ # Generate selection event
+ def SelectItem(self, item):
+ wx.TreeCtrl.SelectItem(self, item)
+ evt = wx.TreeEvent(wx.EVT_TREE_SEL_CHANGED.typeId, self, item)
+ wx.PostEvent(self, evt)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/XMLTreeMenu.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/XMLTreeMenu.py
new file mode 100644
index 0000000..b7a52e1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/XMLTreeMenu.py
@@ -0,0 +1,107 @@
+# Name: XMLTreeMenu.py
+# Purpose: dynamic pulldown menu for XMLTree
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 31.05.2007
+# RCS-ID: $Id: XMLTreeMenu.py 64107 2010-04-22 14:05:36Z ROL $
+
+import wx
+from globals import ID
+from component import Manager
+
+class XMLTreeMenu(wx.Menu):
+ '''dynamic pulldown menu for XMLTree'''
+ def __init__(self, container, comp, tree, createSibling, insertBefore):
+ '''
+ Create tree pull-down menu. createSibling flag is set if the
+ child must be a sibling of the selected item, insertBefore
+ flag is set if the child should be put before selected item in
+ sibling mode or as the first child in non-sibling mode.
+ '''
+ wx.Menu.__init__(self)
+ items = tree.GetSelections()
+ if len(items) <= 1:
+ item = tree.GetSelection()
+ if not item: item = tree.root
+ if not container:
+ menu = self.CreateTopLevelMenu(comp)
+ elif container is Manager.rootComponent and createSibling:
+ menu = self.CreateTopLevelMenu(container)
+ else:
+ if createSibling:
+ menu = self.CreateSubMenus(container)
+ else:
+ menu = self.CreateSubMenus(comp)
+ # Select correct label for submenu
+ if createSibling:
+ if insertBefore:
+ self.AppendMenu(ID.SIBLING, 'Create Sibling', menu,
+ 'Create sibling before selected object')
+ else:
+ self.AppendMenu(ID.SIBLING, 'Create Sibling', menu,
+ 'Create sibling after selected object')
+ else:
+ if insertBefore:
+ self.AppendMenu(ID.INSERT, 'Insert', menu,
+ 'Create object as the first child')
+ else:
+ self.AppendMenu(ID.APPEND, 'Append', menu,
+ 'Create object as the last child')
+ if comp is not Manager.rootComponent:
+ self.Append(ID.SUBCLASS, 'Sublass...', 'Define subclass')
+ self.AppendSeparator()
+
+ if container:
+ if container is Manager.rootComponent:
+ menu = self.CreateTopLevelMenu(container, ID.SHIFT)
+ else:
+ menu = self.CreateSubMenus(container, ID.SHIFT)
+ self.AppendMenu(ID.REPLACE, 'Replace With', menu,
+ 'Replace selected object by another')
+ self.AppendSeparator()
+
+ self.Append(wx.ID_CUT, 'Cut', 'Cut to the clipboard')
+ self.Append(wx.ID_COPY, 'Copy', 'Copy to the clipboard')
+ if createSibling and item != tree.root:
+ self.Append(ID.PASTE_SIBLING, 'Paste Sibling',
+ 'Paste from the clipboard as a sibling')
+ else:
+ self.Append(ID.PASTE, 'Paste', 'Paste from the clipboard')
+ if items:
+ self.Append(wx.ID_DELETE, 'Delete', 'Delete selected objects')
+ if comp.isContainer():
+ self.AppendSeparator()
+ self.Append(ID.EXPAND, 'Expand', 'Expand tree')
+ self.Append(ID.COLLAPSE, 'Collapse', 'Collapse tree')
+
+ def CreateTopLevelMenu(self, comp, idShift=0):
+ m = wx.Menu()
+ for index,component,label,help in Manager.menus['TOP_LEVEL']:
+ if comp.canHaveChild(component):
+ m.Append(component.id + idShift, label, help)
+ m.AppendSeparator()
+ m.Append(ID.REF, 'reference...', 'Create object_ref node')
+ m.Append(ID.COMMENT, 'comment', 'Create comment node')
+ return m
+
+ def CreateSubMenus(self, comp, idShift=0):
+ menu = wx.Menu()
+ for index,component,label,help in Manager.menus['ROOT']:
+ if comp.canHaveChild(component):
+ menu.Append(component.id + idShift, label, help)
+ if menu.GetMenuItemCount():
+ menu.AppendSeparator()
+ for name in Manager.menuNames[2:]:
+ # Skip empty menu groups
+ if not Manager.menus.get(name, []): continue
+ m = wx.Menu()
+ for index,component,label,help in Manager.menus[name]:
+ if comp.canHaveChild(component):
+ m.Append(component.id + idShift, label, help)
+ if m.GetMenuItemCount():
+ menu.AppendMenu(ID.MENU, name, m)
+ menu.AppendSeparator()
+ else:
+ m.Destroy()
+ menu.Append(ID.REF, 'reference...', 'Create object_ref node')
+ menu.Append(ID.COMMENT, 'comment', 'Create comment node')
+ return menu
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/__init__.py
new file mode 100644
index 0000000..54e9b26
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/__init__.py
@@ -0,0 +1,4 @@
+#
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/attribute.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/attribute.py
new file mode 100644
index 0000000..23b89d7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/attribute.py
@@ -0,0 +1,242 @@
+# Name: attribute.py
+# Purpose: Attribute classes
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 25.06.2007
+# RCS-ID: $Id$
+
+'''
+Attribute processing classes.
+
+This module contains some predefined classes which can be used to store and
+retrieve XML data into Python objects.
+'''
+
+import cPickle
+from model import Model
+
+class Attribute:
+ '''Base class, used for simple attributes, i.e. single attributes
+ storing data as text strings.'''
+ @staticmethod
+ def add(parentNode, attribute, value):
+ '''Store attribute value in DOM as a text node.
+
+ @param attribute: Attribute name.
+ @param value: Attribute value (Python string).
+ '''
+ if attribute == '':
+ elem = parentNode
+ else:
+ elem = Model.dom.createElement(attribute)
+ parentNode.appendChild(elem)
+ text = Model.dom.createTextNode(value)
+ elem.appendChild(text)
+ @staticmethod
+ def get(node):
+ '''Get value (or return a default value) from a DOM C{Element} object.'''
+ if node is None: return ''
+ try:
+ n = node.childNodes[0]
+ return n.wholeText
+ except IndexError:
+ return ''
+
+class ContentAttribute:
+ '''Content attribute class. Value is a list of strings.'''
+ @staticmethod
+ def add(parentNode, attribute, value):
+ contentElem = Model.dom.createElement(attribute)
+ parentNode.appendChild(contentElem)
+ for item in value:
+ elem = Model.dom.createElement('item')
+ text = Model.dom.createTextNode(item)
+ elem.appendChild(text)
+ contentElem.appendChild(elem)
+ @staticmethod
+ def get(node):
+ if node is None: return []
+ value = []
+ for n in node.childNodes:
+ if n.nodeType == node.ELEMENT_NODE and n.tagName == 'item':
+ value.append(Attribute.get(n))
+ return value
+
+class CheckContentAttribute:
+ '''CheckList content. Value is a list of tuples (checked, string).'''
+ @staticmethod
+ def add(parentNode, attribute, value):
+ contentElem = Model.dom.createElement(attribute)
+ parentNode.appendChild(contentElem)
+ for item in value:
+ try:
+ checked, item = item
+ except:
+ checked = False
+ elem = Model.dom.createElement('item')
+ if checked:
+ elem.setAttribute('checked', '1')
+ text = Model.dom.createTextNode(item)
+ elem.appendChild(text)
+ contentElem.appendChild(elem)
+ @staticmethod
+ def get(node):
+ if node is None: return []
+ value = []
+ for n in node.childNodes:
+ if n.nodeType == node.ELEMENT_NODE and n.tagName == 'item':
+ try:
+ checked = int(n.getAttribute('checked'))
+ except:
+ checked = 0
+ value.append((checked, str(Attribute.get(n))))
+ return value
+
+class HelpContentAttribute:
+ '''RadioBox content. Value is a list of tuples (string, tooltip, help).'''
+ @staticmethod
+ def add(parentNode, attribute, value):
+ contentElem = Model.dom.createElement(attribute)
+ parentNode.appendChild(contentElem)
+ for item in value:
+ try:
+ item, tooltip, helptext = item
+ except:
+ tooltip = helptext = ''
+ elem = Model.dom.createElement('item')
+ if tooltip:
+ elem.setAttribute('tooltip', tooltip)
+ if helptext:
+ elem.setAttribute('helptext', helptext)
+ text = Model.dom.createTextNode(item)
+ elem.appendChild(text)
+ contentElem.appendChild(elem)
+ @staticmethod
+ def get(node):
+ if node is None: return []
+ value = []
+ for n in node.childNodes:
+ if n.nodeType == node.ELEMENT_NODE and n.tagName == 'item':
+ tooltip = n.getAttribute('tooltip')
+ helptext = n.getAttribute('helptext')
+ value.append((str(Attribute.get(n)), str(tooltip), str(helptext)))
+ return value
+
+
+class DictAttribute:
+ '''DictAttribute uses dictionary object for passing data.'''
+ attributes = []
+ @classmethod
+ def add(cls, parentNode, attribute, value):
+ fontElem = Model.dom.createElement(attribute)
+ parentNode.appendChild(fontElem)
+ for a in filter(value.has_key, cls.attributes):
+ elem = Model.dom.createElement(a)
+ text = Model.dom.createTextNode(value[a])
+ elem.appendChild(text)
+ fontElem.appendChild(elem)
+ @staticmethod
+ def get(node):
+ if node is None: return {}
+ value = {}
+ for n in node.childNodes:
+ if n.nodeType == node.ELEMENT_NODE:
+ value[n.tagName] = Attribute.get(n)
+ return value
+
+class FontAttribute(DictAttribute):
+ attributes = ['size', 'style', 'weight', 'underlined', 'family', 'face', 'encoding',
+ 'sysfont', 'relativesize']
+
+class CodeAttribute(DictAttribute):
+ attributes = ['events', 'assign_var']
+
+class MultiAttribute:
+ '''Repeated attribute like growablecols.'''
+ @staticmethod
+ def add(parentNode, attribute, value):
+ for v in value:
+ elem = Model.dom.createElement(attribute)
+ parentNode.appendChild(elem)
+ text = Model.dom.createTextNode(v)
+ elem.appendChild(text)
+ @staticmethod
+ def get(node):
+ if node is None: return []
+ tag = node.tagName # remember tag name
+ value = []
+ # Look for multiple tags
+ while node:
+ if node.nodeType == node.ELEMENT_NODE and node.tagName == tag:
+ value.append(Attribute.get(node))
+ node = node.nextSibling
+ return value
+
+class BitmapAttribute:
+ '''Bitmap attribute.'''
+ @staticmethod
+ def add(parentNode, attribute, value):
+ if not value[0] and not value[1]: return
+ if attribute == 'object':
+ elem = parentNode
+ else:
+ elem = Model.dom.createElement(attribute)
+ parentNode.appendChild(elem)
+ if value[0]:
+ elem.setAttribute('stock_id', value[0])
+ else:
+ if elem.hasAttribute('stock_id'): elem.removeAttribute('stock_id')
+ text = Model.dom.createTextNode(value[1])
+ elem.appendChild(text)
+ @staticmethod
+ def get(node):
+ if node is None: return []
+ return [node.getAttribute('stock_id'), Attribute.get(node)]
+
+class AttributeAttribute:
+ '''Attribute as an XML attribute of the element node.'''
+ @staticmethod
+ def add(elem, attribute, value):
+ if value:
+ elem.setAttribute(attribute, value)
+ else:
+ if elem.hasAttribute(attribute): elem.removeAttribute(attribute)
+ @staticmethod
+ def getAA(elem, attribute):
+ return elem.getAttribute(attribute)
+
+class EncodingAttribute(AttributeAttribute):
+ '''Encoding is a special attribute stored in dom object.'''
+ @staticmethod
+ def add(elem, attribute, value):
+ Model.dom.encoding = value
+ @staticmethod
+ def getAA(elem, attribute):
+ return Model.dom.encoding
+
+class CDATAAttribute(Attribute):
+ def add(parentNode, attribute, value):
+ '''value is a dictionary.'''
+ if value:
+ elem = Model.dom.createElement(attribute)
+ parentNode.appendChild(elem)
+ data = Model.dom.createCDATASection(cPickle.dumps(value))
+ elem.appendChild(data)
+ @staticmethod
+ def get(node):
+ '''Get XRCED data from a CDATA text node.'''
+ try:
+ n = node.childNodes[0]
+ if n.nodeType == n.CDATA_SECTION_NODE:
+ return cPickle.loads(n.wholeText.encode())
+ except IndexError:
+ pass
+
+class CommentAttribute(AttributeAttribute):
+ '''Comment is the value of comment object.'''
+ @staticmethod
+ def add(node, attribute, value):
+ node.data = value
+ @staticmethod
+ def getAA(node, attribute):
+ return node.data
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/component.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/component.py
new file mode 100644
index 0000000..1b06a99
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/component.py
@@ -0,0 +1,793 @@
+# Name: component.py
+# Purpose: base component classes
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 31.05.2007
+# RCS-ID: $Id: component.py 72147 2012-07-20 00:24:55Z RD $
+
+"""
+Component plugin classes.
+
+This module defines base classes and for deriving component plugin
+classes and contains some global variables used to register components
+with XRCed.
+
+Components are objects of Component class or one of the derived
+classes used to define specialized components (such as sizers). After
+a component object is constructed and configured it can be registered
+using the Manager global object.
+
+"""
+
+
+import os,sys,bisect
+import wx
+try: set
+except: from sets import Set as set
+from globals import *
+from model import Model
+from attribute import *
+import params
+import view
+import images
+
+DEFAULT_POS = (1000,1000)
+
+# Group compatibility specifications.
+# Key is the parent group, value is the list of child groups.
+# !value means named main group is excluded from possible children.
+# "root" is a special group for the tree root
+parentChildGroups = {
+ 'root': ['top_level', 'component'], # top-level objects
+ 'frame': ['toolbar', 'menubar', 'statusbar'],
+ 'mdi_parent_frame': ['toolbar', 'menubar', 'statusbar', 'mdi_child_frame'],
+ 'mdi_child_frame': ['toolbar', 'menubar', 'statusbar',
+ 'control', 'window', 'sizer', 'btnsizer',
+ '!frame', '!mdi_child_frame'],
+ 'wizard': ['wizard_page'],
+ 'window': ['control', 'window', 'sizer', 'btnsizer', '!frame', '!mdi_child_frame'],
+ 'sizer': ['control', 'sizer', 'btnsizer', 'spacer', 'toolbar'],
+ 'book': ['control', 'window', '!sizer', '!btnsizer'],
+ 'btnsizer': ['stdbtn'],
+ 'menubar': ['menu'],
+ 'toolbar': ['tool', 'separator'],
+ 'menu': ['menu', 'menu_item', 'separator', 'break'],
+}
+'''
+Definition of compatibility of component groups as I{key}:I{group_list} pairs, where
+I{key} is a parent group name and I{group_list} is a list of children group names or
+group names prefixed with '!' character to exclude components having corresponding
+primary group. This dictionary can be modified by component plugins directly
+(some care must be taken not to redefine existing relations or breake them).
+'''
+
+
+class Component(object):
+ '''Base class for component plugins.'''
+ # Common window attributes
+ windowAttributes = ['fg', 'bg', 'font', 'tooltip', 'help',
+ 'enabled', 'focused', 'hidden']
+ '''Default window attributes for window-like components.'''
+ genericStyles = [
+ 'wxBORDER_SIMPLE', 'wxBORDER_SUNKEN', 'wxBORDER_THEME',
+ 'wxBORDER_RAISED', 'wxBORDER_STATIC', 'wxBORDER_NONE',
+ 'wxCLIP_CHILDREN', 'wxTRANSPARENT_WINDOW', 'wxWANTS_CHARS',
+ 'wxNO_FULL_REPAINT_ON_RESIZE', 'wxFULL_REPAINT_ON_RESIZE',
+ 'wxTAB_TRANSVERSAL', 'wxALWAYS_SHOW_SB',
+ # deprecated
+ 'wxBORDER_DOUBLE'
+ ]
+ '''Default style flag equivalents'''
+ equivStyles = {'wxBORDER_SIMPLE': 'wxSIMPLE_BORDER',
+ 'wxBORDER_SUNKEN': 'wxSUNKEN_BORDER',
+ 'wxBORDER_DOUBLE': 'wxDOUBLE_BORDER',
+ 'wxBORDER_RAISED': 'wxRAISED_BORDER',
+ 'wxBORDER_STATIC': 'wxSTATIC_BORDER',
+ 'wxBORDER_NONE': 'wxNO_BORDER'}
+ '''Default generic styles.'''
+ genericExStyles = [
+ 'wxWS_EX_VALIDATE_RECURSIVELY',
+ 'wxWS_EX_BLOCK_EVENTS',
+# 'wxWS_EX_TRANSIENT', # not processed by XRC (yet?)
+ 'wxWS_EX_PROCESS_IDLE',
+ 'wxWS_EX_PROCESS_UI_UPDATES'
+ ]
+ '''Default generic extended styles.'''
+ genericEvents = [
+ 'EVT_WINDOW_CREATE', 'EVT_WINDOW_DESTROY',
+ 'EVT_MOVE', 'EVT_SIZE',
+ 'EVT_MOUSE_EVENTS', 'EVT_MOTION',
+ 'EVT_LEFT_DOWN', 'EVT_LEFT_DCLICK',
+ 'EVT_MIDDLE_DOWN', 'EVT_MIDDLE_DCLICK',
+ 'EVT_RIGHT_DOWN', 'EVT_RIGHT_DCLICK', 'EVT_MOUSEWHEEL',
+ 'EVT_ENTER_WINDOW', 'EVT_LEAVE_WINDOW',
+ 'EVT_KEY_DOWN', 'EVT_KEY_UP', 'EVT_CHAR',
+ 'EVT_PAINT', 'EVT_ERASE_BACKGROUND',
+ 'EVT_CONTEXT_MENU', 'EVT_HELP',
+ 'EVT_SET_FOCUS', 'EVT_KILL_FOCUS', 'EVT_CHILD_FOCUS',
+ 'EVT_UPDATE_UI', 'EVT_IDLE',
+ ]
+ '''Default generic events.'''
+ hasName = True # most elements have XRC IDs
+ '''True if component has an XRC ID attribute.'''
+ isTopLevel = False # if can be created as top level window
+ '''True if component can be a top-level object in XML tree.'''
+ renameDict = {}
+ '''Dictionary of I{old_name}:I{new_name} for renaming some attributes
+ in the Attribute Panel.'''
+ hasCode = True
+ '''True if component can generate code.'''
+ isTestable = False
+ '''True if component can be inserted directly in the test view.'''
+
+ def __init__(self, klass, groups, attributes, **kargs):
+ '''
+ Construct a new Component object.
+
+ @param klass: Interface element class name (e.g. C{'wxButton'}).
+ @param groups: List of group names to which this component belongs.
+ First group is considered to be the I{primary group}.
+ @param attributes: List of XRC attribute names.
+
+ B{Supported keyword parameters:}
+
+ @keyword defaults: Dictionary of default attribute values for creating
+ new items.
+ @keyword specials: Dictionary of I{attribute_name}:I{attribute_class} pairs
+ for specifying special attribute classes for some attributes, instead of
+ using default Attribute class.
+ @keyword params: Dictionary of pairs I{attribute_name}:I{param_class} where
+ I{param_class} is a attribute interface class (one of classes in
+ params.py or a custom class). If a param class is not specified, a default
+ value defined by C{paramDict} dictionary is used.
+ @keyword image,images: C{wx.Image} object or a list of C{wx.Image} objects
+ for tree icons.
+ @keyword events: List of event names for code generation panel.
+ '''
+ self.klass = klass
+ self.groups = groups
+ self.attributes = attributes
+ self.styles = []
+ self.exStyles = []
+ self.defaults = kargs.pop('defaults', {})
+ # Special Attribute classes if required
+ self.specials = kargs.pop('specials', {})
+ # Some default special attributes
+ self.specials['font'] = FontAttribute
+ self.specials['XRCED'] = CodeAttribute
+ # Special Param classes if required
+ self.params = kargs.pop('params', {})
+ # Tree image
+ if 'images' in kargs:
+ self.images = kargs.pop('images')
+ elif 'image' in kargs:
+ self.images = [kargs.pop('image')]
+ elif not 'image' in self.__dict__:
+ self.images = []
+ # Code generation data
+ self.events = kargs.pop('events', [])
+
+ def addStyles(self, *styles):
+ '''Add more styles.'''
+ self.styles.extend(styles)
+
+ def addExStyles(self, *styles):
+ '''Add more extra styles.'''
+ self.exStyles.extend(styles)
+
+ def addEquivStyles(self, equiv):
+ '''Add more style equivalencies'''
+ self.equivStyles.update(equiv)
+
+ def setSpecial(self, attrName, attrClass):
+ '''Set special attribute class for processing XML.
+
+ @param attrName: Attribute name.
+ @param attrClass: Attribute class.
+ '''
+ self.specials[attrName] = attrClass
+
+ def setParamClass(self, attrName, paramClass):
+ '''Set special attribute panel class for editing attribute value.
+
+ @param attrName: Attribute name.
+ @param paramClass: Param class.
+ '''
+ self.params[attrName] = paramClass
+
+ def getTreeImageId(self, node):
+ try:
+ return self.images[0].Id
+ except IndexError:
+ if self.isContainer():
+ return 1
+ return 0
+
+ def getTreeText(self, node):
+ if node.nodeType == node.COMMENT_NODE:
+ return node.data
+ if node.tagName == 'object_ref':
+ ref = node.getAttribute('ref')
+ label = 'ref: %s' % ref
+ else:
+ label = node.getAttribute('subclass')
+ if not label:
+ label = node.getAttribute('class')
+ if self.hasName:
+ name = node.getAttribute('name')
+ if name: label += ' "%s"' % name
+ return label
+
+ def addEvents(self, *events):
+ '''Add more events.'''
+ self.events.extend(events)
+
+ # Order components having same index by group and klass
+ def __cmp__(self, other):
+ if self.groups < other.groups: return -1
+ elif self.groups == other.groups:
+ if self.klass < other.klass: return -1
+ elif self.klass == other.klass: return 0
+ else: return 1
+ else: return 1
+
+ def __repr__(self):
+ return "Component('%s', %s)" % (self.klass, self.attributes)
+
+ def canHaveChild(self, component):
+ '''True if the current component can have child of given type.
+
+ This function is redefined by container classes.'''
+ return False
+
+ def canBeReplaced(self, component):
+ '''True if the current component can be replaced by component.
+
+ This function can be redefined by derived classes.'''
+ return component.groups == groups
+
+ def isContainer(self):
+ '''True if component is a container (can have child nodes).'''
+ return isinstance(self, Container)
+
+ def getAttribute(self, node, attribute):
+ attrClass = self.specials.get(attribute, Attribute)
+ # 'object' means attribute is a text node without element tag,
+ if attribute == 'object':
+ return attrClass.get(node)
+ elif issubclass(attrClass, AttributeAttribute):
+ return attrClass.getAA(node, attribute)
+ for n in node.childNodes:
+ if n.nodeType == node.ELEMENT_NODE and n.tagName == attribute:
+ return attrClass.get(n)
+ return attrClass.get(None)
+
+ def addAttribute(self, node, attribute, value):
+ '''Add attribute element.'''
+ attrClass = self.specials.get(attribute, Attribute)
+ attrClass.add(node, attribute, value)
+
+ def makeTestWin(self, res, name):
+ '''Method can be overridden by derived classes to create custom test view.
+
+ @param res: C{wx.xrc.XmlResource} object with current test resource.
+ @param name: XRC ID of tested object.
+ '''
+ testWin = view.testWin
+ if self.isTopLevel:
+ # Top-level window creates frame itself
+ frame = None
+ object = res.LoadObject(view.frame, STD_NAME, self.klass)
+ object.Fit()
+ testWin.size = object.GetSize()
+ else:
+ # Create MiniFrame to hold selected subtree
+ frame = testWin.frame
+ if not frame:
+ frame = wx.MiniFrame(view.frame, -1, '%s: %s' % (self.klass, name), name=STD_NAME,
+ style=wx.CAPTION|wx.CLOSE_BOX|wx.RESIZE_BORDER)
+ frame.panel = wx.Panel(frame)
+ object = res.LoadObject(frame.panel, STD_NAME, self.klass)
+ if not object or not isinstance(object, wx.Window):
+ raise TestWinError
+ object.SetPosition((10,10))
+ if g.conf.fitTestWin:
+ object.Fit()
+ if frame:
+ frame.SetClientSize(object.GetSize()+(20,20))
+ testWin.size = frame.GetSize()
+ return frame, object
+
+ def getRect(self, obj):
+ '''Return bounding box coordinates for C{obj}.'''
+ # Object's rect must be relative to testWin.object
+ if isinstance(obj, wx.Window):
+ return [obj.GetRect()]
+ elif isinstance(obj, wx.Rect): # spacer
+ return [obj]
+ else:
+ return None
+
+ def copyAttributes(self, srcNode, dstNode):
+ '''Copy relevant attribute nodes from srcNode to dstNode.'''
+ dstComp = Manager.getNodeComp(dstNode)
+ if dstComp.hasName:
+ dstNode.setAttribute('name', srcNode.getAttribute('name'))
+ for n in srcNode.childNodes:
+ if n.nodeType == n.ELEMENT_NODE:
+ a = n.tagName
+ # Check if attributes are compatible
+ srcAttrClass = self.specials.get(a, Attribute)
+ dstAttrClass = dstComp.specials.get(a, Attribute)
+ if srcAttrClass is not dstAttrClass: continue
+ srcParamClass = self.params.get(a, params.paramDict.get(a, params.ParamText))
+ dstParamClass = dstComp.params.get(a, params.paramDict.get(a, params.ParamText))
+ if srcParamClass is not dstParamClass: continue
+ # Style and exstyle are not in attributes and can be treated specially
+ if a == 'style':
+ styles = self.getAttribute(srcNode, a).split('|')
+ allStyles = dstComp.styles + self.genericStyles + self.equivStyles.values()
+ dstStyles = [s for s in styles if s.strip() in allStyles]
+ if dstStyles:
+ dstComp.addAttribute(dstNode, a, '|'.join(dstStyles))
+ elif a == 'exstyle':
+ styles = self.getAttribute(srcNode, a).split('|')
+ allStyles = dstComp.exStyles + self.genericExStyles + self.equivStyles.values()
+ dstStyles = [s for s in styles if s.strip() in allStyles]
+ if dstStyles:
+ dstComp.addAttribute(dstNode, a, '|'.join(dstStyles))
+ elif a in dstComp.attributes:
+ value = self.getAttribute(srcNode, a)
+ dstComp.addAttribute(dstNode, a, value)
+
+ def copyImplicitAttributes(self, srcNode, dstNode, dstComp):
+ '''Copy relevant implicit attribute nodes from srcNode to dstNode.'''
+ for n in srcNode.childNodes:
+ if n.nodeType == n.ELEMENT_NODE and not is_object(n):
+ a = n.tagName
+ if a in dstComp.implicitAttributes:
+ value = self.getAttribute(srcNode, a)
+ dstComp.addAttribute(dstNode, a, value)
+
+
+class SimpleComponent(Component):
+ '''Component without window attributes and styles.'''
+ windowAttributes = []
+ genericStyles = genericExStyles = []
+
+
+class Container(Component):
+ isTestable = True
+ '''Base class for containers.'''
+ def canHaveChild(self, component):
+ # Test exclusion first
+ for g in self.groups:
+ if '!'+component.groups[0] in parentChildGroups.get(g, []): return False
+ # Test for any possible parent-child
+ groups = set(component.groups)
+ for g in self.groups:
+ if groups.intersection(parentChildGroups.get(g, [])):
+ return True
+ return False
+
+ def isSizer(self):
+ '''If this container manages children positions and sizes.'''
+ return False
+
+ def requireImplicit(self, node):
+ '''If there are implicit nodes for this particular node.'''
+ return False
+
+ def getTreeNode(self, node):
+ '''Some containers may hide some internal elements.'''
+ return node
+
+ def getTreeOrImplicitNode(self, node):
+ '''Return topmost child (implicit if exists).'''
+ return node
+
+ def appendChild(self, parentNode, node):
+ '''Append child node. Can be overriden to create implicit nodes.'''
+ parentNode.appendChild(node)
+
+ def insertBefore(self, parentNode, node, nextNode):
+ '''Insert node before nextNode. Can be overriden to create implicit nodes.'''
+ parentNode.insertBefore(node, nextNode)
+
+ def insertAfter(self, parentNode, node, prevNode):
+ '''Insert node after prevNode. Can be overriden to create implicit nodes.'''
+ parentNode.insertBefore(node, prevNode.nextSibling)
+
+ def removeChild(self, parentNode, node):
+ '''
+ Remove node and the implicit node (if present). Return
+ top-level removed child.
+ '''
+ return parentNode.removeChild(node)
+
+ def copyObjects(self, srcNode, dstNode):
+ # Copy child objects only for the same group
+ dstComp = Manager.getNodeComp(dstNode)
+ if self.groups[0] != dstComp.groups[0]: return
+ children = []
+ for n in filter(is_object, srcNode.childNodes):
+ n = self.getTreeNode(n)
+ if dstComp.canHaveChild(Manager.getNodeComp(n)):
+ dstComp.appendChild(dstNode, n)
+
+ def replaceChild(self, parentNode, newNode, oldNode):
+ '''Replace oldNode by newNode keeping relevant attributes.'''
+ # Keep compatible children
+ oldComp = Manager.getNodeComp(oldNode)
+ oldComp.copyAttributes(oldNode, newNode)
+ if oldComp.isContainer():
+ oldComp.copyObjects(oldNode, newNode)
+ parentNode.replaceChild(newNode, oldNode)
+
+ def getChildObject(self, node, obj, index):
+ """Get index'th child of a tested interface element."""
+ if isinstance(obj, wx.Window) and obj.GetSizer():
+ return obj.GetSizer()
+ try:
+ return obj.GetChildren()[index]
+ except IndexError:
+ return None
+
+
+class SimpleContainer(Container):
+ '''Container without window attributes and styles.'''
+ windowAttributes = []
+ genericStyles = genericExStyles = []
+ isTestable = False
+
+
+class RootComponent(Container):
+ '''Special root component.'''
+ windowAttributes = []
+ genericStyles = genericExStyles = []
+ hasName = False
+ hasCode = False
+
+
+class SmartContainer(Container):
+ '''Base class for containers with implicit nodes.'''
+ implicitRenameDict = {}
+ def __init__(self, klass, groups, attributes, **kargs):
+ Container.__init__(self, klass, groups, attributes, **kargs)
+ self.implicitKlass = kargs.pop('implicit_klass')
+ self.implicitPageName = kargs.pop('implicit_page')
+ self.implicitAttributes = kargs.pop('implicit_attributes')
+ # This is optional
+ self.implicitParams = kargs.pop('implicit_params', {})
+
+ def getTreeNode(self, node):
+ if is_element(node) and node.getAttribute('class') == self.implicitKlass:
+ for n in node.childNodes: # find first object
+ if is_object(n): return n
+ # Maybe some children are not implicit
+ return node
+
+ def getTreeOrImplicitNode(self, node):
+ '''Return topmost child (implicit if exists).'''
+ if node.parentNode.getAttribute('class') == self.implicitKlass:
+ return node.parentNode
+ else:
+ return node
+
+ def appendChild(self, parentNode, node):
+ if self.requireImplicit(node):
+ elem = Model.createObjectNode(self.implicitKlass)
+ elem.appendChild(node)
+ parentNode.appendChild(elem)
+ else:
+ parentNode.appendChild(node)
+
+ def insertBefore(self, parentNode, node, nextNode):
+ if self.requireImplicit(nextNode):
+ nextNode = nextNode.parentNode
+ if self.requireImplicit(node):
+ elem = Model.createObjectNode(self.implicitKlass)
+ elem.appendChild(node)
+ parentNode.insertBefore(elem, nextNode)
+ else:
+ parentNode.insertBefore(node, nextNode)
+
+ def insertAfter(self, parentNode, node, prevNode):
+ if self.requireImplicit(prevNode):
+ nextNode = prevNode.parentNode.nextSibling
+ else:
+ nextNode = prevNode.nextSibling
+ if self.requireImplicit(node):
+ elem = Model.createObjectNode(self.implicitKlass)
+ elem.appendChild(node)
+ parentNode.insertBefore(elem, nextNode)
+ else:
+ parentNode.insertBefore(node, nextNode)
+
+ def removeChild(self, parentNode, node):
+ if self.requireImplicit(node):
+ implicitNode = node.parentNode
+ return parentNode.removeChild(implicitNode)
+ else:
+ return parentNode.removeChild(node)
+
+ def replaceChild(self, parentNode, newNode, oldNode):
+ # Do similarly to Container for object child nodes
+ oldComp = Manager.getNodeComp(oldNode)
+ oldComp.copyAttributes(oldNode, newNode)
+ if oldComp.isContainer():
+ oldComp.copyObjects(oldNode, newNode)
+ # Special treatment for implicit nodes
+ if self.requireImplicit(oldNode):
+ implicitNode = oldNode.parentNode
+ if self.requireImplicit(newNode):
+ implicitNode.replaceChild(newNode, oldNode)
+ else:
+ parentNode.replaceChild(newNode, implicitNode)
+ else:
+ if self.requireImplicit(newNode):
+ elem = Model.createObjectNode(self.implicitKlass)
+ elem.appendChild(newNode)
+ parentNode.replaceChild(elem, oldNode)
+ else:
+ parentNode.replaceChild(newNode, oldNode)
+
+ def requireImplicit(self, node):
+ # SmartContainer by default requires implicit
+ return True
+
+ def setImplicitParamClass(self, attrName, paramClass):
+ '''Set special Param class.'''
+ self.implicitParams[attrName] = paramClass
+
+
+class Sizer(SmartContainer):
+ '''Sizers are not windows and have common implicit node.'''
+ windowAttributes = []
+ hasName = False
+ isTestable = False
+ genericStyles = []
+ genericExStyles = []
+ renameDict = {'orient':'orientation'}
+ implicitRenameDict = {'option':'proportion'}
+ def __init__(self, klass, groups, attributes, **kargs):
+ kargs.setdefault('implicit_klass', 'sizeritem')
+ kargs.setdefault('implicit_page', 'SizerItem')
+ kargs.setdefault('implicit_attributes', ['option', 'flag', 'border', 'minsize', 'ratio'])
+ kargs.setdefault('implicit_params', {'option': params.ParamInt,
+ 'minsize': params.ParamPosSize,
+ 'ratio': params.ParamPosSize})
+ SmartContainer.__init__(self, klass, groups, attributes, **kargs)
+
+ def isSizer(self):
+ return True
+
+ def requireImplicit(self, node):
+ return is_element(node) and node.getAttribute('class') != 'spacer'
+
+ def getChildObject(self, node, obj, index):
+ obj = obj.GetChildren()[index]
+ if obj.IsSizer():
+ return obj.GetSizer()
+ elif obj.IsWindow():
+ return obj.GetWindow()
+ elif obj.IsSpacer():
+ return obj.GetRect()
+ return None # normally this is an error
+
+ def getRect(self, obj):
+ rects = [wx.RectPS(obj.GetPosition(), obj.GetSize())]
+ for sizerItem in obj.GetChildren():
+ rect = sizerItem.GetRect()
+ rects.append(rect)
+ # Add lines to show borders
+ flag = sizerItem.GetFlag()
+ border = sizerItem.GetBorder()
+ if border == 0: continue
+ x = (rect.GetLeft() + rect.GetRight()) / 2
+ if flag & wx.TOP:
+ rects.append(wx.Rect(x, rect.GetTop() - border, 0, border))
+ if flag & wx.BOTTOM:
+ rects.append(wx.Rect(x, rect.GetBottom() + 1, 0, border))
+ y = (rect.GetTop() + rect.GetBottom()) / 2
+ if flag & wx.LEFT:
+ rects.append(wx.Rect(rect.GetLeft() - border, y, border, 0))
+ if flag & wx.RIGHT:
+ rects.append(wx.Rect(rect.GetRight() + 1, y, border, 0))
+ return rects
+
+
+class BoxSizer(Sizer):
+ '''Sizers are not windows and have common implicit node.'''
+
+ def __init__(self, klass, groups, attributes, **kargs):
+ Sizer.__init__(self, klass, groups, attributes, **kargs)
+
+ def getTreeImageId(self, node):
+ if self.getAttribute(node, 'orient') == 'wxVERTICAL':
+ return self.images[0].Id
+ else:
+ return self.images[1].Id
+
+ def getRect(self, obj):
+ rects = Sizer.getRect(self, obj)
+ for sizerItem in obj.GetChildren():
+ rect = sizerItem.GetRect()
+ flag = sizerItem.GetFlag()
+ if flag & wx.EXPAND:
+ if obj.GetOrientation() == wx.VERTICAL:
+ y = (rect.GetTop() + rect.GetBottom()) / 2
+ rects.append(wx.Rect(rect.x, y, rect.width, 0))
+ else:
+ x = (rect.GetLeft() + rect.GetRight()) / 2
+ rects.append(wx.Rect(x, rect.y, 0, rect.height))
+ return rects
+
+ def setDefaults(self, node):
+ if node.nodeType == node.COMMENT_NODE or \
+ node.tagName == 'object_ref': return
+ if self.requireImplicit(node):
+ comp = Manager.getNodeComp(node)
+ sizerItem = self.getTreeOrImplicitNode(node)
+ if comp.isContainer():
+ for a,v in g.conf.defaultsContainer.items():
+ self.addAttribute(sizerItem, a, v)
+ else:
+ for a,v in g.conf.defaultsControl.items():
+ self.addAttribute(sizerItem, a, v)
+
+ def appendChild(self, parentNode, node):
+ Sizer.appendChild(self, parentNode, node)
+ self.setDefaults(node)
+
+ def insertBefore(self, parentNode, node, nextNode):
+ Sizer.insertBefore(self, parentNode, node, nextNode)
+ self.setDefaults(node)
+
+ def insertAfter(self, parentNode, node, prevNode):
+ Sizer.insertAfter(self, parentNode, node, prevNode)
+ self.setDefaults(node)
+
+################################################################################
+
+class _ComponentManager:
+ '''Component manager used to register component plugins.'''
+ def __init__(self):
+ self.rootComponent = RootComponent('root', ['root'], ['encoding'],
+ specials={'encoding': EncodingAttribute},
+ params={'encoding': params.ParamEncoding})
+ self.components = {}
+ self.ids = {}
+ self.firstId = self.lastId = -1
+ self.menus = {}
+ self.panels = {}
+ self.menuNames = ['TOP_LEVEL', 'ROOT', 'bar', 'control', 'button', 'box',
+ 'container', 'sizer', 'custom']
+ self.panelNames = ['Windows', 'Panels', 'Controls', 'Sizers', 'Menus',
+ 'Gizmos', 'Custom']
+ self.panelImages = {}
+
+ def init(self):
+ self.firstId = self.lastId = wx.NewId()
+ self.external = [] # external resources
+ self.handlers = [] # registered XmlHandlers
+
+ def register(self, component):
+ '''Register component object.'''
+ TRACE('register %s' % component.klass)
+ self.components[component.klass] = component
+ # unique wx ID for event handling
+ component.id = self.lastId = wx.NewId()
+ self.ids[component.id] = component
+
+ def forget(self, klass):
+ '''Remove registered component.'''
+ del self.components[klass]
+ for menu,iclh in self.menus.items():
+ if iclh[1].klass == klass:
+ self.menus[menu].remove(iclh)
+ for panel,icb in self.panels.items():
+ if icb[1].klass == klass:
+ self.panels[panel].remove(icb)
+
+ def getNodeComp(self, node, defaultClass='unknown'):
+ # For ref nodes without class name, need to find ref element
+ if node is Model.mainNode:
+ return self.rootComponent
+ elif node.nodeType == node.COMMENT_NODE:
+ return self.components['comment']
+ cls = node.getAttribute('class')
+ if node.tagName == 'object_ref':
+ if not cls:
+ refNode = Model.findResource(node.getAttribute('ref'))
+ if refNode:
+ cls = refNode.getAttribute('class')
+ else:
+ cls = 'unknown'
+ if defaultClass and cls not in self.components:
+ cls = defaultClass
+ return self.components[cls]
+
+ def getMenuData(self, menu):
+ return self.menus.get(menu, None)
+
+ def setMenu(self, component, menu, label, help, index=999999):
+ '''Set pulldown menu data.'''
+ if menu not in self.menuNames: self.menuNames.append(menu)
+ if menu not in self.menus: self.menus[menu] = []
+ bisect.insort_left(self.menus[menu], (index, component, label, help))
+
+ def getPanelData(self, panel):
+ return self.panels.get(panel, None)
+
+ def setTool(self, component, panel, bitmap=None,
+ pos=DEFAULT_POS, span=(1,1)):
+ '''Set toolpanel data.'''
+ if panel not in self.panelNames: self.panelNames.append(panel)
+ if panel not in self.panels: self.panels[panel] = []
+ # Auto-select bitmap if not provided
+ if not bitmap:
+ bmpPath = os.path.join('bitmaps', component.klass + '.png')
+ if os.path.exists(bmpPath):
+ bitmap = wx.Bitmap(bmpPath)
+ else:
+ bitmap = images.ToolPanel_Default.GetBitmap()
+ if g.conf.toolIconScale != 100:
+ im = bitmap.ConvertToImage().Scale(
+ bitmap.GetWidth() * g.conf.toolIconScale / 100,
+ bitmap.GetHeight() * g.conf.toolIconScale / 100)
+ bitmap = im.ConvertToBitmap()
+ bisect.insort_left(self.panels[panel], (pos, span, component, bitmap))
+
+ def addXmlHandler(self, h):
+ '''
+ Add an XML resource handler. h must be a class derived from
+ XmlResourceHandler or a function loaded from a dynamic library
+ using ctypes.
+ '''
+ self.handlers.append(h)
+
+ def findById(self, id):
+ return self.ids[id]
+
+ def addXmlHandlers(self, res):
+ '''Register XML handlers before creating a test window.'''
+ for h in self.handlers:
+ TRACE('registering Xml handler %s', h)
+ if g._CFuncPtr and isinstance(h, g._CFuncPtr):
+ try:
+ apply(h, ())
+ except:
+ logger.exception('error calling DL func "%s"', h)
+ wx.LogError('error calling DL func "%s"' % h)
+ else: # assume a python class handler
+ try:
+ res.AddHandler(apply(h, ()))
+ except:
+ logger.exception('error adding XmlHandler "%s"', h)
+ wx.LogError('error adding XmlHandler "%s"' % h)
+
+ def addExternal(self, f):
+ '''Add an external resource file f to the list of preloaded
+ resources.'''
+ self.external.append(f)
+ Model.addExternal(f)
+
+ def preload(self, res):
+ '''Preload external resources.'''
+ for f in self.external:
+ TRACE('Loading external resources: %s', f)
+ res.Load(f)
+
+
+# Singleton object
+Manager = _ComponentManager()
+'''Singleton global object of L{_ComponentManager} class.'''
+
+c = SimpleComponent('comment', ['top_level', 'control'], ['comment'],
+ specials={'comment': CommentAttribute},
+ image=images.TreeComment.GetImage())
+c.hasName = False
+c.hasCode = False
+c.setParamClass('comment', params.ParamMultilineText)
+Manager.register(c)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/encode_bitmaps.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/encode_bitmaps.py
new file mode 100644
index 0000000..72e80b4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/encode_bitmaps.py
@@ -0,0 +1,42 @@
+"""
+A simple script to encode all the images the XRCed needs into a Python module
+"""
+
+import sys, os, glob
+from wx.tools import img2py
+
+def main(filemask, output):
+ # get the list of PNG files
+ files = glob.glob(filemask)
+ files.sort()
+
+ # Truncate the inages module
+ open(output, 'w')
+
+ # call img2py on each file
+ for file in files:
+
+ # extract the basename to be used as the image name
+ name = os.path.splitext(os.path.basename(file))[0]
+
+ # encode it
+ if file == files[0]:
+ cmd = "-F -u -n %s %s %s" % (name, file, output)
+ else:
+ cmd = "-a -F -u -n %s %s %s" % (name, file, output)
+ img2py.main(cmd.split())
+
+ # Encode icons
+ files = glob.glob('src-images/*.ico')
+ files.sort()
+ for file in files:
+ # extract the basename to be used as the image name
+ name = os.path.splitext(os.path.basename(file))[0]
+ # encode it
+ cmd = "-a -F -i -u -n %s %s %s" % (name, file, output)
+ img2py.main(cmd.split())
+
+if __name__ == "__main__":
+ main('src-images/*.png', 'images.py')
+ main('src-images/32x32/*.png', 'images_32x32.py')
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/generate.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/generate.py
new file mode 100644
index 0000000..138a2a8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/generate.py
@@ -0,0 +1,73 @@
+# Name: generate.py
+# Purpose: Code-generation related classes
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 25.07.2007
+# RCS-ID: $Id$
+
+from globals import *
+from presenter import Presenter
+
+class PythonOptions(wx.Dialog):
+
+ def __init__(self, parent, cfg, dataFile):
+ pre = wx.PreDialog()
+ g.res.LoadOnDialog(pre, parent, "PYTHON_OPTIONS")
+ self.PostCreate(pre)
+
+ self.cfg = cfg
+ self.dataFile = dataFile
+
+ self.AutoGenerateCB = xrc.XRCCTRL(self, "AutoGenerateCB")
+ self.EmbedCB = xrc.XRCCTRL(self, "EmbedCB")
+ self.GettextCB = xrc.XRCCTRL(self, "GettextCB")
+ self.MakeXRSFileCB = xrc.XRCCTRL(self, "MakeXRSFileCB")
+ self.FileNameTC = xrc.XRCCTRL(self, "FileNameTC")
+ self.BrowseBtn = xrc.XRCCTRL(self, "BrowseBtn")
+ self.GenerateBtn = xrc.XRCCTRL(self, "GenerateBtn")
+ self.SaveOptsBtn = xrc.XRCCTRL(self, "SaveOptsBtn")
+
+ self.Bind(wx.EVT_BUTTON, self.OnBrowse, self.BrowseBtn)
+ self.Bind(wx.EVT_BUTTON, self.OnGenerate, self.GenerateBtn)
+ self.Bind(wx.EVT_BUTTON, self.OnSaveOpts, self.SaveOptsBtn)
+
+ if self.cfg.Read("filename", "") != "":
+ self.FileNameTC.SetValue(self.cfg.Read("filename"))
+ else:
+ name = os.path.splitext(os.path.split(dataFile)[1])[0]
+ name += '_xrc.py'
+ self.FileNameTC.SetValue(name)
+ self.AutoGenerateCB.SetValue(self.cfg.ReadBool("autogenerate", False))
+ self.EmbedCB.SetValue(self.cfg.ReadBool("embedResource", False))
+ self.MakeXRSFileCB.SetValue(self.cfg.ReadBool("makeXRS", False))
+ self.GettextCB.SetValue(self.cfg.ReadBool("genGettext", False))
+
+
+ def OnBrowse(self, evt):
+ path = self.FileNameTC.GetValue()
+ dirname = os.path.abspath(os.path.dirname(path))
+ name = os.path.split(path)[1]
+ dlg = wx.FileDialog(self, 'Save As', dirname, name, '*.py',
+ wx.SAVE | wx.OVERWRITE_PROMPT)
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ self.FileNameTC.SetValue(path)
+ dlg.Destroy()
+
+
+ def OnGenerate(self, evt):
+ pypath = self.FileNameTC.GetValue()
+ embed = self.EmbedCB.GetValue()
+ genGettext = self.GettextCB.GetValue()
+ Presenter.generatePython(self.dataFile, pypath, embed, genGettext)
+ self.OnSaveOpts()
+
+
+ def OnSaveOpts(self, evt=None):
+ self.cfg.Write("filename", self.FileNameTC.GetValue())
+ self.cfg.WriteBool("autogenerate", self.AutoGenerateCB.GetValue())
+ self.cfg.WriteBool("embedResource", self.EmbedCB.GetValue())
+ self.cfg.WriteBool("makeXRS", self.MakeXRSFileCB.GetValue())
+ self.cfg.WriteBool("genGettext", self.GettextCB.GetValue())
+
+ self.EndModal(wx.ID_OK)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/globals.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/globals.py
new file mode 100644
index 0000000..e76bb1d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/globals.py
@@ -0,0 +1,142 @@
+# Name: globals.py
+# Purpose: XRC editor, global variables
+# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
+# Created: 02.12.2002
+# RCS-ID: $Id: globals.py 71790 2012-06-17 15:43:08Z ROL $
+
+import os,sys
+import wx
+import wx.xrc as xrc
+try:
+ import wx.wizard
+except:
+ pass
+
+import logging
+logging.basicConfig()
+logger = logging.getLogger('xrced')
+
+# Global constants
+
+progname = 'xrced'
+ProgName = 'XRCed'
+version = '0.2.1-0'
+# Minimal wxWidgets version
+MinWxVersion = (2,8,0)
+if wx.VERSION[:3] < MinWxVersion:
+ print '''\
+******************************* WARNING **************************************
+ This version of XRCed may not work correctly on your version of wxWidgets.
+ Please upgrade wxWidgets to %d.%d.%d or higher.
+******************************************************************************''' % MinWxVersion
+
+# Can be changed to set other default encoding different
+#defaultEncoding = ''
+# you comment above and can uncomment this:
+defaultEncoding = wx.GetDefaultPyEncoding()
+
+# Constant to define standart window name for tested component
+STD_NAME = '_XRCED_T_W'
+TEST_FILE = 'test.xrc'
+
+# Global id constants
+class ID:
+ SHIFT = 1000 # shift ids of replace commands
+ MENU = wx.NewId()
+ EXPAND = wx.NewId()
+ COLLAPSE = wx.NewId()
+ COLLAPSE_ALL = wx.NewId()
+ PASTE_SIBLING = wx.NewId()
+ PASTE = wx.NewId()
+ TOOL_PASTE = wx.NewId()
+ INSERT = wx.NewId()
+ APPEND = wx.NewId()
+ SIBLING = wx.NewId()
+ REPLACE = wx.NewId()
+ SUBCLASS = wx.NewId()
+ REF = wx.NewId()
+ COMMENT = wx.NewId()
+
+# Constants
+AUTO_REFRESH_POLICY_SELECTION = 0
+AUTO_REFRESH_POLICY_FOCUS = 1
+
+# Global variables
+
+_debug = False # default debug flag
+def set_debug(v):
+ global _debug
+ _debug = v
+ logger.setLevel(logging.DEBUG)
+def get_debug():
+ return _debug
+
+_verbose = False # default debug flag
+def set_verbose(v):
+ global _verbose
+ _verbose = v
+def get_verbose():
+ return _verbose
+
+def TRACE(msg, *args):
+ if _debug and _verbose: print >> sys.stderr, 'TRACE: ' + (msg % args)
+
+class Globals:
+ undoMan = None
+ conf = None
+ useMeta = False # use meta-components
+ _CFuncPtr = None # _CFuncPtr from ctypes
+ lastActiveFrame = None
+
+ def _makeFonts(self):
+ self._sysFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ self._labelFont = wx.Font(self._sysFont.GetPointSize(), wx.DEFAULT, wx.NORMAL, wx.BOLD)
+ self._modernFont = wx.Font(self._sysFont.GetPointSize(), wx.MODERN, wx.NORMAL, wx.NORMAL)
+ self._smallerFont = wx.Font(self._sysFont.GetPointSize()-1, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
+
+ def sysFont(self):
+ if not hasattr(self, "_sysFont"): self._makeFonts()
+ return self._sysFont
+ def labelFont(self):
+ if not hasattr(self, "_labelFont"): self._makeFonts()
+ return self._labelFont
+ def modernFont(self):
+ if not hasattr(self, "_modernFont"): self._makeFonts()
+ return self._modernFont
+ def smallerFont(self):
+ if not hasattr(self, "_smallerFont"): self._makeFonts()
+ return self._smallerFont
+
+
+g = Globals()
+
+# Set application path for loading resources
+if __name__ == '__main__':
+ g.basePath = os.path.dirname(sys.argv[0])
+else:
+ g.basePath = os.path.dirname(__file__)
+g.basePath = os.path.abspath(g.basePath)
+
+# Data object used for clipboard
+class MyDataObject(wx.PyDataObjectSimple):
+ def __init__(self, data=''):
+ wx.PyDataObjectSimple.__init__(self, wx.CustomDataFormat('XRCed_DND'))
+ self.data = data
+ def GetDataSize(self):
+ return len(self.data)
+ def GetDataHere(self):
+ return self.data # returns a string
+ def SetData(self, data):
+ self.data = data
+ return True
+
+# Test for object elements (!!! move somewhere?)
+def is_element(node):
+ return node.nodeType == node.ELEMENT_NODE and \
+ node.tagName in ['object', 'object_ref', 'component']
+
+def is_object(node):
+ return is_element(node) or node.nodeType == node.COMMENT_NODE
+
+# Exception class
+class TestWinError(Exception): pass
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/images.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/images.py
new file mode 100644
index 0000000..b39b679
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/images.py
@@ -0,0 +1,1216 @@
+#----------------------------------------------------------------------
+# This file was generated by encode_bitmaps.py
+#
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+AutoRefresh = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wUIEhkj6H6O3AAABNZJREFUOMvFlVtsVEUc"
+ "xr+ZOWfPdk+3LdvL0hXaAqESBQRayrW1pRAfUBKNIQ2LCS8GfFSJCdEYjTHEoCEBDaAEL7Dl"
+ "+mBAFB+E3gKUpTcapEXUdun2BnTbvZ/bjA9um22BxDcn+ZLJzH9+Z+abb3KA/7NtPbOb/Ze6"
+ "6lOrS9afXeMCAPLEgh8qSpkiv8eADYZpFgpwmRIWpZSOcmFd5pyfJVHedGVnmzG5pvLkKjfj"
+ "/KoGc8M1b0f/NDARXlJ7+u+jAOrWza20PVvwnORUVDDCkDQ0xI0Y7k/0W51DHbHR2AiDIJ+Z"
+ "tuh+h55JkxR+WFYpEaK44Y22wDTwxlNrvy3Onrd129LtDs3SEE6OQ1WccMgqKCgoIRAAKCGI"
+ "aBG09DUkW4OtukXE4Pqi9fNvj3QbocTEokZv64A0dfzjZatUWX19w/yNjsP+r/ho4gGVQGFy"
+ "LigRplstTJTPqVCXz17BDHBoIoHqBbX2FXPK7X+O3XPWFG8it4Y7TZ3qHADoJJhJ9l1OW5Z6"
+ "rP2omDDDRJUzkpZlnWn0tlJLJNwDseCmn/+4eG5v8yfx9iG/yGAqBhNBjJtjKPdUEIlK0C0L"
+ "alKaDqbAS/3hAHE5c0Ol7oUdSVMPgWMfADR5u0Mt227euFx3tU6zjHW/3r3kP9b2TTyb5uAZ"
+ "RxFaRhsgUxsgLKIzbTrYIkJx2BzBkoKiI6o96wQo7nLFCs1MTLPX36mb+p6IHmYO2YnhRBAA"
+ "h0LtMIRFIMscAKY8FpYVz8rMO6Dasy7EFe2hTsT37vys8Exwla9sCYN0/s2ytxS3owAetRBr"
+ "C6qhMAWcm4TLtulgl8cxz2w8zz96+Tx/2gOoOl5WyAm5RLjlOOQ/qAkhYBEBKgS4EDDBbWbs"
+ "38ubilu1b+UDTkjmk4BCiIgkyKaka6xHjGZmPO3DVMjKtR2lo4L4hJQ2nvPdZp8kUxsEEaCg"
+ "0MwkPm5+XwuE+965sv1GV6pOA4CaI2Wy4YJj+bLKZJ4+a1bP/a61Q4/ufy2IL2+aFRZAFMmO"
+ "lpHfQATByvx1OH3Hpw1EA182eP0nZu6OZ0puu8UOZUWkHxN8Ij8cC+1kks1KS1kqxylfdG7C"
+ "o86FAND9oEsQ0CWrT66cOxPMgCwurDXheHh7b/D27mgiUsIE+WtyXkrzkRBQLM5ZiqH4ACQq"
+ "YW/NF/YzPfW1v9z7qaemvuKgwflNUAQUk0oW+OcZckZOT/BOtV2yCZeaazxKhI4+BgYAQgji"
+ "ehwLs5+HYWm4FWpDZVEVK/dUONqG/O8OR4aSg5EgeZh4pCqEoSDDjUUFi5Cn5pP6zhNJqmf6"
+ "HgNTSkl/uA8fNO4Zp6B084JXbC8W19jHzTEIcCwrXC4ZsxdnMlAQUJjCgMFNTGghnOzwRQ3D"
+ "ert5x+VkurUAwEpe83x4Y+BarK8psKXrQO/+YHZg8HqoecFEckKVmY06bU7ilJ3g4DC5iage"
+ "QfvATX6x94IWHorsu7qr3ZfiCQDWZI7tVb6yUOj36NbuT3tvA8hIyV6yxfOCp9Zdx2bJKyQK"
+ "xSGrRsKMMy4EjChvGWkaPXSvPtAFIJFSHEB8EkxWH1766vVdtxoB2AEoaZJTYnIuk3MXu1zR"
+ "4Xgo2hsLAdBTudZS0EiqL570a2JpsElJ6cdMyUhJB2CmxqbaP0R8PsUa4mUWAAAAAElFTkSu"
+ "QmCC")
+
+#----------------------------------------------------------------------
+Copy = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wUJAiwtCW2leAAAAmpJREFUOI2Vlc9PE0EU"
+ "x79vZrctPbS3Xrm0dOtfoQcTjVf/Ae9ESxSMxLMJYEEx/oga/TM8mRACJURSJQHa1DMegIMQ"
+ "SLqddp6HYXc7dbuUubTpe/uZz3vzdkq1V0sPWOsKrrlIiObj6uzXUXFHdbve09n563LxenXZ"
+ "S4o7QhAA4PT079jQXC4PIkrMcZKCzEzdblcO/YZUKg1m5rHB7fZvC9r4tXP/4uJ8EsAAhEBk"
+ "Nni5vPAohklEtGaBp6ZK4Xff9+Xa+vfJuSfPiJmT67apqK0s3hxprHoKl6Z0dnY6Lhe5XB4A"
+ "eKRxp9PBZn19bCBg2hOsGGMTVKprJTabzSuhnhe9Dha4VCrCsNgYb22EMc+LH9tgc2aON2Zm"
+ "tNvtEKyUshJbrVYsNEphVCo3InAQYGYUiwPGvo+t7c0wsVKJyrQtTT4RJRmbHjMzlOr9ZzwI"
+ "NJ/Bph6YgXQ6bYO11qGxAQO+38H2j3qYWC6XQ7thYyIBx5FQSkFrHYH7/b5VFrM9OsyMg4Ng"
+ "Kuy8bDaLfD4PACgUCiFrABzAAguywOXylAUEGEJISCmhtYYQAkH1l4dnJmBiYiJsCRHBdd2h"
+ "wyIQRVPgui6IhLFznPDw6lsb0FrDcVOp1rsPb2IveiIKNxu0FUKASEBrjY+f38c92nSS/gUW"
+ "ll48HO5/UD4zmzaAcff2PQDA8ckRGj93wIRPiffxcP9d14GU5hFjTZDSXNeHfw6xt7+LTDb7"
+ "pTo9s3olWCmFTCZjvbJSRtb9vsbxyRH29ncBQdPV6Zm3AJB4z9ZWFr/1er07gD1+wWIwGNAC"
+ "1NDgW/Nzz8+D2D8qwJznbf5BFgAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+Cut = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAABwgAAAcIAHND5ueAAAAB3RJTUUH1gcMCjIxQXznpwAABCZJREFUOMuFk11IXEcU"
+ "x/8zO3fv3awm8WNjzK66hTaxNDG2JdWIhiTa0pY+hIC0FElfBKU2rfRBBUuLhUCSBrQUIaQh"
+ "DyEUP4KxhpIWU4lpirUPNSUmaaQVY9VtNKvu9917Z+70ISvIsq5/uAzcc/jNOf85hyBJnV+f"
+ "G7Msq9w0zaq2lvY72ECnz55qBtCpaY755o8/9STHaXIypbTswIEy5ObkDiONNE376u233gGl"
+ "1H367KlracFOp/PDN15/k3gLn4ON2rRvL57vSAX9prurx73LzbK2Z+NQ1WHszNu5Ly2Yc+7O"
+ "zXEBAKoOHQaA9hQWFMXj8XfLyyoghICmaYhEIwVpwfF4fGro+jXLbrdDYQry8vJtV767PLI+"
+ "JzMzc/BgeQU4F6CU4tbozwiFQq1pwQCOLT1dIroeg5QSJfv2IxwOHVlXbaUQotTjLoSUEk8W"
+ "nyAeN1bbWtq70oLbWtofA7g0ODQgnU4npJR4ef+r6OvveQQAGRkZPxw9UgPOORhjGL09glgs"
+ "WprqHZIrRltLe72u64GHf92XhBDk5roQCgV3X7x0oWv7tqytmuqAlBITd/+Aqqq9iWI2ByfU"
+ "+Nv4GNmy5RnkYHklMjMzPykoLIKUEpQSzM3PGiebmt/baBxTgtta2nstyxr95c5ty2azQVEU"
+ "qKoGwTkIIfhp+EeEQqHqdHNO08Q++Gf6bwkiIaVE8e4XEYmEMT0zDWazPUi3lQBg2yhwc3gk"
+ "UF1z1PHf1FRlcUkpTNOEYRjwP3yAE41NO7CJ0lWM4s86jPjMDCb/nEBxcTGJhUJYmnqEQbu9"
+ "YzMwSf5xBfBu07QOSkhtnHNt796XiN/hwL/jv6Og7DXkxGKYnLwvVcZ0S8r+gK5/UQfMpAUP"
+ "2u2Nis32eVFWVr6mKFDos4bGZ2dlIleWFRYSADAtC7pp4vHKis8U4stjhnE+pRUDHneNkLJ1"
+ "j8uVvxqL+Sd9vhV/NIrFcBiGEGdY7fELhhBnFsNh+KNRTPp8K6uxmH+Py5UvpGwd8LhrUnsc"
+ "jdZXeL1efySCxXC4zxCi26EoWAgGYQF3j/f0NwCYWAgG4VAUGEJ0L4bDff5IBBVerxfRaH1q"
+ "sGk+rzGGiGHwJSGGVMYanHY7KCHzJ4DrALQ64HtKyLzTbofKWMOSEEMRw+AaY5CG8cJ6a9na"
+ "BcTknqCuY6umoYSxG57sbEwsLCzNct4HwA1AAsAs573w+epe8Xh2zC0v31AY40FdB+XCDUAD"
+ "YAIQNHELtTN2eS4QQIaiMIeq4p7Ph2Upf/2I834A2YnP1cT51adSjt3z+eBQVWQoCpsLBGAx"
+ "1gNATewGIesWhV3VtBYqZbUlJfFJefOkaQ4kYlZSh7yTsdpdlFYzQkSckFvv6/o5AHytYpI0"
+ "eiThO01AlKSRXOvQSkDEuhMJuywA+B+n69WfhO60vAAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+Locate = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wUJAwcewQ9TMAAAAypJREFUOMuF1cFvVFUU"
+ "x/HPDDMtdBKZAk8gMZGLCcaA6RhNWMwCCAZ2bo1JTf0TgIUrVBL32q0LI5jGsDESNgbcdOEs"
+ "XDFGTEQSbokaC8PQFnmvpULrYt4MM0OLJ3nJu++d+73n/O459xY8x0I9zCYHkiMb/cvameuX"
+ "rxc2m1vYBDiNGibsVDWygVMbq5pYio149H/BOXQqeTOpKtGab3HbLPblzwXjpoyRvJTI5jLp"
+ "nbQZG/GNTcH90Na9Fre9hz8wjy9xBIdRRsW4K5W9FdqegZeeB42NeLHvfy+A2IiN/NvJVHql"
+ "sreiolIL9XCtCy/1BVxLDifVPPUeNEzmeq+asIayL0IISzgVZ+LVYXgXVuyLdqJ1d0NoE+cs"
+ "mLOI1AWcw6kwGWqxEa9acDL9O5U+SIV6uNYDd6O1xgbQS3EmzsosWUZbM87EWUwPwGEHyYGk"
+ "1g/u2G1T/dJgLs7ExXx8CsfyxcSZ2MyrpAoWnJQ9nVwaqrb3Qz0cx8tWTVjweajnejZi85k6"
+ "H/QZsGHw2723NazrbkZ1yK+GI0M+A1YcGk/FRizERiwoaxpzuj/9PuvIMuhzbPOIx13A12CL"
+ "JS9oxstxdqjNe7KEEHo+4XhYt3WDiLO5jDFCPZzIN+coPgiToTaQfi5LXjXne9lsQ9Y5nHot"
+ "Heqhhq/sVbPS2eFuCYXJcB778gapKmvaYimHXoozcTEcD+vGsYhlp2MjTheGj8hW2iLDPe+4"
+ "40esY6tX/IBDyj62xfdW/eWmtv0eGadSqpDpHaXFvio407rR+iWpJIxhl8t2OZHvQ0nmH8tY"
+ "8JNf3XLTyjA0vZeeCfVQHQTP+9OKD1s3Wtd78N0uOqjlRW/lkbNm1H5tB90fgN5Nz3rou9jo"
+ "NNRTKULYjVE7HDDqs+TV5HXoSdNvWzvAsW1jsnbWgaa+8dDDGGNrGLwnT7tgp/2Kqko+7S6w"
+ "0dWU3k3PeuI3y36WeoDHMcb7w+ARHQG25wf5qqpDirYrWDPiEwWveeIj/7ql4LHU71bMYwQP"
+ "kMUYV5+9QUIo5LqXMZpPKKBsj28VHfbIu9qudgRRxCMsYD3GuN5l/Qe3YXJJdwMq5QAAAABJ"
+ "RU5ErkJggg==")
+
+#----------------------------------------------------------------------
+LocateArmed = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wQaExMj1CO6xQAAAWRJREFUSMe1lTFuwzAM"
+ "RSmje87g3XsM9BwZvGeXjiLt2TP4HAGcPbvP4BOoQ/DbX5qSG6PhaBHvi5+kLPLmcFsJQ9fm"
+ "2vn1MbtdAgz2BzsnLdtCTQ3uDz/w6eQlLU/odPKiz0uVNjU4wABy9LfZsVBJpNmCi4iEEFwI"
+ "YWVBCMH1t6c1JRGnBSz49GmXD7iICHLSInI8e8GFGqupGg47uAfTyQsLs9j9kmyLeFoYHmPM"
+ "2iLYo6sDI8aYzSbrhjL8+pjd8bxuOGBcBeJDf0B5sOx+STJ0bcacQ4wtRc6f98AK3PLVWFXw"
+ "y4IxiWUJ7Iox5lXOmOoC/Zi+vUQDtS1sF+dY49xYbws3rVc34nNMWel9qi6atUTWomHK9KKh"
+ "Kld7KlgkxpgxYey5huN8tcnsLRL55taileDVMbVELIv4u4bzZf7th2PBN3+Z7HspdD9e/ifz"
+ "WFpNLoF3xdC1eejavPfZeEt8AZHHDNdIUA3RAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+MoveDown = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wUJAjEUqQRBbAAABBVJREFUOI2NlE1oXFUYht9z5t7JnZuZyZ+pBnpmJhis"
+ "goR02UWCacnAJF0UERRsF+JCcRErdKFgcSGou6iIKPiD1EV1K+3oSCC6kZqNSrUVtLl3TshM"
+ "TYK5c+f+ZO7P58IZHJKb4gcHDi/veXjPd757WaVSMarVagkH6tSpU59MTk6eHRkZSTUaDVdK"
+ "+dX6+voLB31HlZIkzszMvL24uPj4wsLCEBGh0WiMrq6uPsk5t+7evfuOYRjN/wMerFQq53uC"
+ "7/sPAJjN5XLZzc1N+L4PRVEwMTGRz+fzJ3Z2dlI1IR7JMKYxICZgd7Ze30wCqwCu9ARN0wAA"
+ "pmlGnuchnU7DcRxIKdHpdMAYywKYV4ATnLFnCfjjh0LhpRD4e7Ze/6kfvFetVocPtOI9VVUv"
+ "2Lad1zQNtm2j2WzarVbrzyAI7LKU73etL64VCstZxj7LAPb3hcITc/X6rcQeF4tFtd1ufyql"
+ "HLcs63Qmk0m5ruu1Wq1V13W/NE1zq9/fIfqwDbSzjH08xNiba4XCGx2i24fApmkGpVLp51ar"
+ "9Zrv+18oiqKEYegHQfB7FEUbB/1lKfdrQlxtERWHOX+ZATfLUv6YOBVEFAPocM73VVUN4zj2"
+ "AQSMsTjJX5bSrQnx+m4cP3Qf5+dXhVAPgUulkpJOpx8+fvz4K1NTU+WhoSFla2vLNQzjm729"
+ "vXcnJydvbmxshAnwsCZECKDIgJlDYMMwwpMnTz5/5syZs/Pz8/k4jrG9vT28trZ27saNG7ue"
+ "560A2Dp4rr8YUFYA5CuVysWe2Ol0xoloLpPJDPZGjHOOsbGxXC6Xe3B3dzdfLBYbpmnSveC9"
+ "xCs9IZ1O95JHnudhYGAA7XYbUkrs7+/fiwXWXdQFt6rV6mi/YXp6eoVz/oxt20MDAwNwHAfN"
+ "ZtOyLOt2GIbWUWl7KQnJc6w4jvORlHLMsqyyruuK4ziubdtfe553NY7j7aMS825ingQ2TTMs"
+ "Fou3bNt+1XXdK6lUikVR1Imi6E4cx1umaR6aCACoCaEyQOlexUuc4+5V692VWDUhUmUpo+5+"
+ "WAHeynL+lEWEeSn1JLDGGNOIaE/XdXJdd6mrX+Ocl4ioQUSdspRRTYjfAMylGbucZey51L9/"
+ "u3UktQKAT0Q+gB70eldf0jTN8H1fENFmTYgWB9qjnF+OgWUFgEX03WP1+mkAUIIgGAaw2D18"
+ "vW9/vg+K8fHxwPf9ix8cO3aupKqXcoxlVcZyCmPLThzDA76dq9fLPT/nnAe6rl/Tdf0aAPTt"
+ "tf5r2LbdcBzn2F9RtA2AQoB1iGDF8S820YXZPigAoFKpGEe8D/WlB2PsaV3XiXN+PwDUhNir"
+ "CWHUhHg06XBSjzmAGP99REsAQESfu67LLo2OaguDg6mylMPdx/s1CfwPBWAC+CiCmmwAAAAA"
+ "SUVORK5CYII=")
+
+#----------------------------------------------------------------------
+MoveLeft = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wUJAjQCIKcAeAAAA5tJREFUOI2dlO9rHEUYx7+zP87drZduLngm6PZ2EVFC"
+ "iecLkRR8U4i4qUjavOgbhfpKLL7whb7wvdo3ohV9UxFFFAVBQbQ5mph/QAMhBUUazO3eBu7S"
+ "9NK7vcnc3u3urC+6FzbNNQk+MMzMd3Y/z3efnRli27ZTqVRMpGGapug4Tjw9Pf2VZVkvj46O"
+ "ivV6nXme9yul9LMgCG5Vq9UYR4R0v+A4Tlwul6/Ozs5emJmZOZkkCer1emF5efniyspKu9fr"
+ "fQqgcRzwCdu2Xx0IQRCMAzibz+fzm5ubCIIAkiRhYmJiZGRk5Klms6mXSqUt13WTo8AygG8H"
+ "gqIoA+e82+0il8thd3cXnueh3++DEHKU2T1wq1Kp6FmxXC5/Lsvya5TSEUVR0Ol00Gg0Or7v"
+ "/xtFkX+U2wF4X5RKJZlS+rXneY+02+2zqqqKjLGu7/vLjLEfOed3juNYuF9wXTeMomhtdXX1"
+ "YqvVejeO4zvb29tvUko/CMNwzXXd/nHABxwDgOM4UalUIsVicUGSpLcYY78BSLIlME1TlmX5"
+ "aVVVT0mSRIIg6PT7/Vuc862NjQ0+FJw6TyYnJ3k65tk10zRlTdOeN03zQ9M0TyuKQmq1Wtvz"
+ "vO993//CsqzaA8GHBSHksXw+/97c3NyZqakpMQxD1Go1fWlp6fW1tbWtIAi+PA64aNv221kh"
+ "CILHc7ncM6Ioio7jIIoiAMDY2NiYoihPiqL40FHgXQAGgE+y4mCvr6+vQ9d1CIIA3/fRaDT2"
+ "khwKrlQqXQAHToRlWad0Xb+qquorhUJBFEURvu+jXq/fZoz9Hcdx8L9qzDmvU0o/qlarerPZ"
+ "fEKW5ROU0hal9Ider3edc34omKQtyfQJcG+vW5b1x0t3777/ws7OVgQYW4QUrgjCIud8x3Xd"
+ "B2+3LCjTDxLgWhQlItBRCenIhHyjxvHHG46zdyoPnDzcu5QAAJqm9QBcSNsgUS5dPhcDmzIh"
+ "IECRABtZyDDH4cAlY+wcgIV0Pp+CjRuG8SyA7wTgPIAracZ9P1kKw1AHMJvOF9LxLoBLGSgA"
+ "/Axg/tr4+BwB3skT8rBAyO9RkiAG/kyAf/aBBUEINU27DgCMMTIYd7vdy0ly8HbcjuNtS5aT"
+ "CCAkScCS5CaAN170vJv7HrRt2xlSDqSfPZuZD+r86A3DOLNoGK1Fw3AWDeP0sJeH1VgAwAEQ"
+ "TdMSxth8qv8EgJzP52UO3BaB5wD8AuCvYeD/AOQorv2N7OunAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+MoveRight = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wUJAjUzaGIxAwAAA2VJREFUOI2dkk1oI3UYxp//fOTjnyZtkq27WTfGiDWF"
+ "0kKgWuoXeAlMe1uKLos3PSsIelAPenPrwcPqag+rLOLJm+IGmkNFELbSg1C0UkyZ6Wyatmmr"
+ "ziRvMp1k/h5MpAzJNuxzGuZ5n987PPMyTdP0YrH4OHyampqKJxKJO9ls9tlIJMIqlYp1eHh4"
+ "o91u39nY2Gj65/1SBhmBQODjpaWlwvz8fLDdbsMwjESpVPpgZ2enDKA0DDiiadqrfsNxnDnO"
+ "eWB3dxeO40CWZaRSqQQR8UwmwwzDEOeBVQBf+41gMIhyuSzi8ThkWUa9XkelUkGz2QQACUDn"
+ "PPDfxWJxzG/k8/mvOOfXk8lkQFVVWJaFarX6l23bBOCBX9sD91Wj0XhT1/Urx8fHTyuKEm61"
+ "WgdEtOK67o+GYXgPDd7e3rYmJydf2dvbe9G2beRyuY1ms1nb2tpyz4MCADRN089bzjmvDgU7"
+ "I2mIGQbg0oBshHN+BGABwALnvNd9YGAVZ8FE9E73uTffliQpFAqF6kS0COAuABDRIudcEBEb"
+ "BixxzpeJ6BcAUQCPAPjO87wlImK+2btEtDg+Ph4fpor/T4tz/n04HL7dXfb5oIBt20P9vL5i"
+ "jPFupwtnXi9wzoUkSY8NU0VfCSFaRBTnnN8nopcBgHP+AxGNAmg9NBiAB8COnp4+8eXly9cU"
+ "xsbertVSL42OOtdiMfeB4JmZmUczmQyPRqOsWq12jo6Oapubm1bPX02nVQCLEnADQGjl4kUA"
+ "+KRgmk5fcCaTYSMjI7lsNntrYmIiHw6HJVVV64yxlbm5uU/X19dPVtNpGcDrAG6GGYMMwBLi"
+ "QwCN1XT6Vl+wYRhidnb2/UKh8Fw+nw+4rouDg4PY2traG6l7935aTqf/6AAveMBNBkAG4AJg"
+ "wJoAcgDCCoAxTdOu++Gu6z7DGFN1XYfrumCMIRaLxa54nhtibFJi7AKAjxhwVQBPWZ5XAvAW"
+ "gN8KpimU7rJv/GBVVVEul0UikYCiKLAsC5VKBdlOJ3kK3JaFuNA98FYH+BbAuwXT/LOXVwA0"
+ "isXiuB88PT39maIoryWTyaCqqrBtG/v7+7Vfhbj/pBBXGf47CwA1ARwXTLN2Nj/wKhzHeU/X"
+ "9UsnJyfPB4NB1mg0/iGi5Z8l6fcvTLM1KNfTv8MRYRfOZO7TAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+MoveUp = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wUJAjIEn54CywAABCZJREFUOI2FlE9oHFUcx7+/ebP/Znd2U5PUgx2ya9rG"
+ "ovjn5ClpQ+mWTXrwLKIHEQsq1oPSiuiheBBBIZ4KgkgoFAQRtV27IER7sLmUHoIVSdJNnolJ"
+ "szG7mZ2Z3Z198/OQ2bAm2/jgMb95j/n8vu/Ldx4KhUIZ/x2iUxiGwQAmwsmapvUBEEXLopJl"
+ "HStZ1u8lyyL0GHqPNRU+2XXdSQA3wvfJeDy+xZ73mAbkAFwHUAXwJIC5fWClVDJUhBDSqV/q"
+ "ggLADSHEhUsDA+MEfJwgygggo4CrJcv6FMDdvJS7DbQgCCKGYVw3DON6ePxO3d6rwnGcw/1C"
+ "HAqPylEiZDTtaZNoOkH0WcmyntoFRyKRquu65LouAUBXfa1LPYjovXg8/v7ra2vfMvCWzVyv"
+ "BsHfbeapCBFMojNxoqmSZR0DAK2Hx7us0McJABPM/EnYsHJWyh8AvBIA1UoQXK4zT7UBZIhO"
+ "RommS5Z1+CBwKJR+C72mcLbCve8BnMtLWWkxf7QdBFcUoBHwPIBEr1RgaGhIE0Jk4/H4iUQi"
+ "QZ7ntZrN5jwzLy8uLrYBIC+lArAY1lUA53+xrJGMpp3aYr63D5zNZvVoNPrEkSNHLh09ejSf"
+ "yWT01dVVt1wu36xWq1MA7j7seAw4Yaj3KyaigWQyef706dPnxsfH00EQYGNjo29mZuaF2dnZ"
+ "zYPACviTgckAOz9IulAoXAj3Ikopv91un0wkEkkpJVqtFjRNQ39/v2ma5vDDoKHidKfuKP68"
+ "syCEgO/7c+VyGZ7nIRaLoV6vQ0qJZrN5EBfclTIdwHaxWHyks5DL5R41TfPiwsKCZdt2JhaL"
+ "wXEcrK2t1Wq12h//AxaMHfo+j4Mg2HQc50spZX+tVssbhqE7juPatv2T53nXDpQMpMIGrX3g"
+ "paWldjabvVev1z/wPG9aCCGUUg2l1GIQBKsHUQkwQ/BqzxwzsyaESJumOWAYhnAcp+E4zoZS"
+ "SqDHHVKyrIQOjPdpWmybGQr4tVeOI7FY7Nnh4eGLIyMjp9LptL6ysuLNz8//XKlUvsjlcnfu"
+ "37/f6oLGo0THU0RnBDDGwFcA3umV48FUKvXq2NjYmdHRUVMphc3NzfStW7cmb9++/cB13b9u"
+ "WpZOwAMAiBI9kyJ6QwderDEXW8wf5qWs6QD6CoXCyx2w7/smM4/pum4sLS3B930QEdLpdDKZ"
+ "TA4JIVLwfcskGtGIjjNw3mc+4QHfNJjfzku5BuykwgfwdQcciUTged6d7hzbtg0pJRqNBpgZ"
+ "AC63geeIeZWB7zzmN7Fz0W91ODoAp1gsDnZ5PJhKpd5dWFh43Lbtvmg0CsdxsL6+vlWr1eaU"
+ "UlsAXvOYGwCaAOp5Kf/Za+k+j5l503XdK8vLy4eq1eqkYRgR13Xr29vbPzabzatBEFTOSrm+"
+ "97u9418tpvCNFrJAcwAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+New = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/ADpAE8017ENAAAA"
+ "CXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH1QISDiUwykMmCQAAAkFJREFUOMutlc1rE2EQ"
+ "h5+Z3VSa4gdNmzUInjyIeBLEVvAf8NKDJ2/i1bMIYi+i4sc/4cGLeJDcRREENaUXC3qyudSQ"
+ "GCgiMabZZMfDfmZT7Wp9IWR32Pd5Z36/mV1hn2vUWRGgBPiuV7c4LvHF/Yd3bwOrfwNVCagc"
+ "GVBb7OGosTPUxxcvNK+5Xr3vZp5bvXH9ZmGomQ/+R4L+S3yrYJTZ/vrpiuG8GnVWnrr5Dc1m"
+ "E8dxMDNEBJGwqOw1GCVpUdYXOKVZbOYS4sxzaOE1Fjy7LPZtXfPgGBBDzAzMMDMsMMwAxqj0"
+ "ENnBZAF0HlDgADAuA4f3BCNAHFNBFUQcAjlIwCIy2gT/DQQdhoMGYj82gO3fglU1/BdBRNPD"
+ "RFFxCDjKgGWGdgKGa7j+czY/byEET4CWuxtYVVONEZCsxgIqCDOYHMOnwphTzM6VaGx858zJ"
+ "1gfg51TGa+uNSbMy2Sc/4iocTOcw5zgyc5pev4Tr1fuuV7cp8LmzS9RqtZympHKoRPdRdaJh"
+ "VZNjwa5StNvtcJNpKENSPkkVkadED0wt909dYWJJdvleTg4QQSkATjYBGpkVagqi0X0cj5IN"
+ "47lxzwfevX87lZFIKEUMzWossQl7gZeXzlOtVtMe1shENDJOEBTVbJdoMY273e5EuzHxnpDk"
+ "gGxlhTROT9GMeRGQeMRJ9C8MTrLR1LiIF1uZTqNJpo8LZpy4Ho82k8aFVVAsY8/z+B8rAQdB"
+ "cOfBo3u39gP7stW6OvXNy6vwj+zkY/oLI/uTo02YtuAAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+Open = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH1QsVES80sHy0HwAAA3ZJREFUOMu1lV9oW1Uc"
+ "xz/n5ja9SW7Wptmytuuqc0Wn7TpkymQKguCrIM6JDwVBfFZh+KaC+qq++aAPg+nUsnUguIeB"
+ "Pvgg7sH+WWxruz92pSVJ2yymadI2ybnn58NN0si2yAp+4Rx+/H7nfn+/e35/juI+OPfN2dMo"
+ "Rj3tIQitoFAIggifvPnGW++3PHzh0nfyICgUCnLu/NlGBPbIyMhxg3dZKct3jiIcDlm66gHg"
+ "edpX3wfGGAC0rhIMBht6u1DIf/n2O+/ubz68spqmt/cAAJOTk6TSaSylfH7ZuQAQjAixWCdD"
+ "g0MNJwC2QXSxWGRifByAcCRMX38vJ595lnw+x8DAAEeOPIZlBXwiI4hIQwbBtm1S6Qxa6yZi"
+ "z6y3Ox3E43sBiCc6OXniOUqlEouLi/w+Po4TCjXFSIOgPRjkof5+BgeHWF3L4LruDrEVUJHK"
+ "dqHqOE7b6lqGPbEIoVCIhYWbVLXm6PAQSvw7VpZCjKAsUEphPCGxv5u5+Xnm5ueIx7s+bRA7"
+ "jpNMZ1JPh0MRIq7LC8+/SDa7xl8Lt9koboDgl5sxSD2NlsK2A4ScEIlEgj9mrtHVFfvs5ZdO"
+ "nWlk4NXXXnnv2PCxD/v6DoadcBudsR6+vZJkNr+vZTk6Ab9qtr3AXbZH3ZWrNnA7l/u7eujw"
+ "wzw5/BRjP1xm5PXTKFUrMaX8FlD+8hPHjv0e+Pyri4/bQK5crlQ9zyMajXJ1yeFoxTCbKrEb"
+ "9MYcimXRFjCTza5WPa1JZVIEA+Y/W7gVCrk7sq0Dy9aF0bG044QkGu2guFHg+BMHkF3ydoTb"
+ "KG2VTV/p5zMWQGF9vWxE8/2Pv9KTiJPf8hABI4IxYIzUFrUGabbR0IfbAyyls1VgxgaIuJHx"
+ "WzcWDvX0Hcbd108qX2Fb19qz1mVSm2HUJVW3+ehy29CekJy9ufTL6Fja9j9mslgsnup+5CC5"
+ "oiadKzfNRAHxx6Kqyb6uZgMQRcUTJiaS1cTmbx8D2ED78nIqGd0TNSd6E9bMqt6Jtua1vqt/"
+ "zd8dW6KjnapnmJtNrv00OvZ1nXjv9PR0pLun27ry5+bdGRH/GmjaVSNS36a1wEbGY3PlImAB"
+ "xgY2stns9WtTUx9F3NkPdltm+s71G1OXvjgPuECh/ncOEK4p3ZrXB4EAFWATyAFb9+pLq+WT"
+ "0Rqm+Sn4X/APqDnRZPJeirYAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+Paste = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wUJAiwoeQdR9wAAAq1JREFUOI2lkk1IVFEU"
+ "gL/75ictbdRx/EmEQFByF+bCTVjkiLTIrE1gO3eR26ZFMNQgbbJFFIQTBAlua+PsykVJkC4k"
+ "EAoCMUNnxnTe8znTjOO9Leb/OaNYBx7v3nvu+d53z32CI2J0dPQD0G9Znpuenr50WJ0onvj9"
+ "aCtzOAFSzdfO20+cfiel8vT0dCFEZqtSisXFb2iaiKaTOyPO8NsFgLP9pPx+5AHw+IDttkI+"
+ "k5IagD/1fVpzZ59ob28ua7S2FmXj+7yq2pqXCtAEppLa3efv998A2HOm25/k05GLHa7wXhNf"
+ "jG4Sxj5ut4eOjs68Q0Y6804mYWOjS1S3nbP1nl7GRdg1O/9jEiiAV+Zw1tqpczg0Fra68T14"
+ "jB7TmZx8wtLSclnj2toafL771DfUM/HwHiMtm0glGkGRB+f7ogRmEtwNbuw2G4FAgHQ6XRZs"
+ "t9sRQuBy1RFPidLLsoKtIYTA4XBUzCuliiZHgIvzoVDoECgMDnor5g81HhoaKgNU2UcipSxT"
+ "VQlcpGw1LkAVoBgYGPg/44Jh5p2DG4ZOU1PL0WBL/5mdDQGq5Pherzc/NnaMirUW40JaSsng"
+ "oLfEUMpMX3Nr0Ui04mkrtqIYUNyK9fVfmOYu8XgcpY5zeWXBMmusWF39yfDwjfw+XY8dF7xf"
+ "As23Imup6zEMw8A0d/7FuHBJu6ZJJBJBZf9dwzAIhzeYejXF1ZbFyuDctZ1ySqKbUVpb2/Kb"
+ "2ixFuh4rgbqdu0cbt8uvTDzyEU9plQ6Tj5ttnzlpS5XN2QFez5Ecv8KWmUh7LpzR6VUfSzZZ"
+ "/9EDISBmpgEVKVrKxJ3LXBea9gKlPNacZVz2mwqxLaubA3st/S+DwZnEgYKxsVtVgAuoAxoA"
+ "N9CYHdcACSAGbAG/ge3sfBswg8EZCfAXXMGHi74Y/3sAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+Redo = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH1gcaChMjSyiLTwAAArdJREFUOMutlE1rE1EU"
+ "ht9z5yOtqa39NNaKjSKiVAtWhYJYqShtlSwEEcGVyPwGl/4BF+ouGxf6C2bhR6GgoBQXxbYL"
+ "sdQWa2maJpiJzUczNzP3uknCZJiktXjgMHDP4TnvvHPmAv8YsbguY3H94G59DPuL7Vhc7/zv"
+ "4CsT5wEg0wy+X8W7wmkXP8MAHgJ47odul1No1/rw6d0iAHSZBrf2BI7F9UkAbyb1/kX38sDZ"
+ "YltJrdbKZQd5noGdE4hEIoFwagC9CeD97fFRFFpd/Mla4HIHjBFIJXDbBlMJVrIAYkA0Gq3C"
+ "w6bBi4HgWFw/AWDl+q1RlGURaStZkyAcCaYQpGbDzknYeQGqfCUPXDMN7qgBgl9cvXTaJlAo"
+ "ZW1CuvVFl2yoCsGxRe3MA+0yDe4AQBB4SvaGkMyvQlEYujsPA2DQKARZaZBwsS2WoIcJA5HB"
+ "QI+DwNCoFQqp6Ohph7ZVxMzscl392tRFqC1oCG2yx4S2jlZspRNyZnY5C+CMaXAyDU4AoJDW"
+ "FNoQrEBFRBmSS5+zLoC7psG/e+u2W6hCjwVBG1phy5xbkqoDIHQqwb/5t8cD3djrL00AVo/O"
+ "u7k/pTQA4OkTJCt9VB3AC/K4afCE96yZYgJAUsovv62FCcKwqDnjCdPguk+U9GVdsTqZ5Tfx"
+ "eHpH6XRcLtVSKDv5TLtfgau+1CpPxf9GXjVUKbKfH0Tx5A2WSqxlYhfGoyK5kRmzVmW8mAZV"
+ "+r3JPFB4FSs+xQSAlt+Kr4NjbC6VtB70dx9Ybx9y7x0ZYT/WPoqEB1YFKhWg8Nqh+C6jGnxl"
+ "WqwcitJLrjoaAUSMcpFhZod7ycn+krZwahARACbygZnHlprvI4+U7r5z7A4x9EkXWwuv3NfC"
+ "laJHKCLST2qoRYqNdbkzP+c61SEUsG5B2eiK9W5DnRV/AfIcOgCbYwEfAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Refresh = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABHNCSVQICAgIfAhkiAAAABl0"
+ "RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAATmSURBVDiNtZVpTBRnGMf/7zsz"
+ "O7uzSzmWW+QQa5GgFkWoaBuPmiatMWnaEIKamKYC1k+2TROTJv3SNDE1adJaFCQ1toCkNGm1"
+ "sUdiPEqtCgRBWwVCPRAWAXGBved4n35gIRx+8Esn+WeSmWd+85tnnpmXERH+j40/S1FZWYv0"
+ "LHUb9jdnl77bkgAA7GnGJZXfrlAU9SMwbDVNK00QFIkzP+ds1BJ0QZBoERT4o6O20pi55qV9"
+ "p1MEp79MC1s76ysezAMzBlb6XnM9wMpffnGpbWVOsuxyquCcQdcNBEIGHjyatG70egIj4wGJ"
+ "MRz2c+ULl6Rz6LzdEmIFMZHVUbtnYB5444Hmk9lpcWV7Xl+tRQwLE/4wYjQVmqpA4gDjDKBp"
+ "A38wgkud98PX/x7SScCzqTBr2a3+EWNyIph37cSuQXkGWlT1XUmCS3t7e/Ey7euWdjHmDXLO"
+ "AWEREYOZ6naFSgoynIUvpEpEQMggbF2fay/Kz7D3P3wS82pRFuvqHTZ1IYl5L88uK9XPuVRn"
+ "/ZlOmgoYzGFXwpYQ31+rreAhjhTPiH/7uda+Hz79pjXY1jNMTlXC0HgITwIm1uenM0XmsCwB"
+ "2R6eDwbDawPDk8wdF+Ndnp16Q9dNLyA+B4CbNRXe9vqKtis15eWGbm38/Upf+4kfO4LxDo7M"
+ "JA2Xbo1CkTgsIVhkoTEJqJpDHcrMSK6N1ewNYLzPIpt34cS01VV06YZ5aCqgSzEOBUPjIQgA"
+ "doXDsogpQhYAMNtjS4hgosvxZYzD/rOuq48pwk7FLE2eWgguqmpcpcjS2eq3itSkeA1piU5s"
+ "LkiGqkgwBTGbtQDsSEvPOYvL4szeNwQAoHLFovkuqmpIY8R/syzSjra0R0gQiADC9F4IsulW"
+ "QABzPpDiqqYxBrgW0QAQwce42P7E5u5x+UYcT6sBAIWgtp/aO0oEkuccj2v4ZIdskzkABsaA"
+ "sG7i47rWyP2RyfevH9/dHa2LTNvXKUC8VlpQGHbH6PHd/z4sHRx9XEeExHmtABGz22RcuDUC"
+ "BkJpXhKazt+JDIz6jrYd39Ww0E4WzhRJFcdUh++nybBImvD7q2yybM2cnzNu05aGKZCR6AQD"
+ "0N0/RpyxVcXvNC9d9NwSnrMssWHSF9x9+97gh75AOJtx3J298awwiDEAa3LiMDgexJCX48iB"
+ "Lfam8z3bzl3p7ympbvpKWNQBYgNcsWQi6YhDVeJ67g5ttikSuWM1wzsRql8EnpZmCIZ05C+J"
+ "RcS00HnPi1cKM6Xi/HSt487wB57HvrBnzMfGJ4JOycaQ4taQl5OMxDgna/ylK6yZeuMiMGeM"
+ "3X80hUM1lyY4A9+xablty7osuzdgwiKgMC9NLrBSXYxN988QBNMUmPBH0PjrDb9lGAcvntwb"
+ "npUkIjDGpPWVDUas0xbo77q4w9Nx5lHulsqd7iW51aufT8vIz01RMlNjmdNhQ8QQMEwLkwEd"
+ "Xb0ecfXmQz04MXK4+/TBGgBhAGEi0mfA9nX7Grx+z+2y3nOf/QPAEY09fe3ONSkrt5UrWvxa"
+ "cKY6VcUIRkyJCBAR35+jfa3HBq42dQMIRRMkouAMmK3efezNmw37LwOwA1DnRIlGkpxuJSGj"
+ "ICHoHfYGRvu8APToXEeiUB+ACBHRoqWJMSbNgc1EBiBh+jdvRWNEowMwiciay/kPKWlcmnLc"
+ "32AAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+Remove = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAFZJ"
+ "REFUOI1jYBgFAw8YkTkiIiLnGRgYDAjoufDmzRtDGIcFTdLgdUUAA8OXHwwMn78zMHz6xsDw"
+ "6SsDwwcY/sIg+vYHigVMGObj0czw/gv1vTAKBgMAAEXnKp/wjOxsAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Save = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH1QsKDTQVSGVyBgAABAtJREFUOMutlV1sFFUU"
+ "x38z+zmdbbvTZZfd1mVZPpYiBdqSVosfWBMfMEI0RnzQF9P4ADVIVVID+iBGAhiLaWwfRB80"
+ "ipLIiw9oDDE2xog0QVSsJbS1NsXW3bbTdr9nZ3d8aHdsqVBM/Cc35+aec/73f889M1dgAZ57"
+ "o/39PxKVj8amtIqF65LNSPpc8b6V8m9tna9+9h23AaE46fqgrfbsj+GLqyMbs6GVPjGeE51V"
+ "ZU7xz7jGVDrL9NXzQ6lkxhFW+tu7Xzv98XLEliLp+f7A2VVbHnAPD/TbB4eHbSO/D4ojE5PY"
+ "SitQnHac3nXKdLpQdj3m3LnrEc+li9/8OnArYhHgh2vO43essA4nBr662ui98HRPxz7xvlDv"
+ "ztzM9dnRwStGdDZOPJlA8QWQfUHHL7Gtn770+i55WWI1Ja2z5BMz968ffejoi+99AnDs4Edf"
+ "NgRHjyRUVUjOTqFlUgD4gutFr6yNTGjh7mVr/NShFz4PO3I/z6qFwwudDkng26kQqzfVL0py"
+ "p/uY+GucysL0jXztnW93nQCwAgTL4l+kJu3dx46+uWTnB9u6lqxlPHcxOtTDhycX6eDlQweP"
+ "AyfMUqTG7dcUt5dUau64yWTSHCZZ+p+5xWZfFDcyOkIymcTr9bL/QGutqRhY6/cHAEgkE7hk"
+ "178qLcIoFAB47MhpdE3jzOE9ACiKQiwWiwCXxfnY3XVb60mn0wgIptLqhh1UN+ygXPECkM1m"
+ "5mw6zrrau1lT0wBAiVQCwD1N9wJsNksBPFxZWbVI1bvPNzPw0/cAjI0OgWGQ13Nk0kniMyoA"
+ "Q1d6eWffdjMnGAwBvAIg7j/QWitJJdjtdjwejxkU8IboaNlGf28PFd5KCoYxXweDMreHgcsX"
+ "6GjZRqgyAoAsy/Pl8LD/QGutCERW+vwAqKqKLMvIsowoioSrNtC5t8kkFwUBV3kFA5cv0Lm3"
+ "iXDVBjNeVedOUV5WDhARgc13btxELpczrFYLMzMzqKqKJEnIskxNpJ5Tbc309/bgXhFguO8S"
+ "p9qaqYnUm4SqqpLP6yQSCWPtmrUATWI2m93i9/txuVyCrucpzN94MUFVVSpKA3Q820B/bw9v"
+ "PVNPRWnA9AHk8zoIoCiKEAyuIpPJllodDsfuSCRitsvNoCiNfH2ycdnfZXV1NU6no8UKEIvF"
+ "mJycvHnfFi/uNnxe71xrFj8QNE3D4/Fw7tw5HA4HsquEUlcZoigiSRKCICBJEi6XC1VV8fl8"
+ "RKPRJbZILC7cTdd1LBYLhmEgChay2SyapmEYBjab7ZbKb4SpWBAE0uk0dXW16Hoei8WCrutm"
+ "oN1u57/AChCNRg2/3z//THmWTXK73QCEw+EldmxszAAE4YknH98TCPjP8D9ibGx8+9/nYJ9T"
+ "cCLRagAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+Test = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wUJAw4SGXukUgAABGlJREFUOI19lU1sVFUU"
+ "x3/3481M5810XssMSGmFWCJQbEXjUghRlJgQ44JE45qFCzcaExITY0JiiCwwxoXBhcTEGCwf"
+ "MYYYsXwtECuIkgZF1EhbPuw0xXY6M53O+7jXxZsZ2grc5OS93Hve7/zPOffeJ3jAsNaK7u7u"
+ "ji8OTpzWGk8piCKLMXy4eZv54EHfivvMe4Ofiz97elRe6wTdqxy0kmhtsTZidNxnairk3Pfm"
+ "yz177WvAzFKAvgd0l5TylSc3ibwVGaRoxw/awCosEIQ1OjvmKCwrc+MG26WcP2KMeQu4vBCi"
+ "lkBfEkJ83Nvb621Yb7OFQhqllqG0i1QplE5iTBJjoF4POH/BTY3fXJEul8tbjDFTwO/3Am9y"
+ "HOf9tWvXtjmOs3J6OsXmp32USqOkRCqBUpbIGKLQJwzm2LO3CyllxvM8WSqVBowxPwETC8Ee"
+ "8POaNWtcx3FWCiGYuuOglWX9o1WkjJByHilrBGGFwK8weDTNld+SGGMQQmRd11UzMzNPAF8D"
+ "803w5VwuF3ie1yNE3E9rLVevpdiwbppCvoSUVZSsEPoVgmCOd9/rxhjT8tVaZ4QQtWq1uhIY"
+ "kgBCiEyhUOiw1rLQwjDk0GGXKKxiojLYCsbUOHQkhzGGpf65XG6VEOLF5q7Y0d7enpFS5mwc"
+ "flE3r15z+eFHl3I1QSoleGrTDIPHlv8PCiCl8LTWc0EQ7NDAzlQqdcdamxPAQqy1FiEEr78Z"
+ "0tu7Gq01t29LUqky6XS6BbQLxHR2ds4Xi8WdEkBrnWw6NK2Z6uTkJPl8vlXPfD5PtVptrS8t"
+ "idY6mcvlEAc+YrSri9V+EMsVDdmW+P3EyQSnzj68qDzPbh1n+zY/zs4CAkTj6Thw6gyfycjE"
+ "ZQ0DCEPwfagHUK/DXA0e749It83j+z6VSoVEYo6N60PKFajVYj/fBz+AIIhZxoDa2MdfjsOr"
+ "jo4nIhMHiMKmo6X3kQrDF3xmZ31eeH6OFcsDrAVr7oKsBWPhzjSUy7wj9+3neBhBGMXAMIit"
+ "7jesDpd+dgGPbDbL5RGXej2er/ux2rChtilo336OS4DZWYpCxgtBQ2nrGcDwxfZWff+ZSDI2"
+ "nmytNX3DEKSAep1ZAAkwOcmuWi3uQxTG6qOGgvPD2UVbylrLV8fzcXbh3UytjXuiFHtad8Xw"
+ "Bf7Y2MfLrktBiEZKBsbGkwyd6Vi0T1tHHuju8hEClIwDfDuk3zh7rv+TYrEYSICBgYH2b74b"
+ "eO7vUW7/OwNaQxTB8MUs9xsXL7UTmTiAH8DYOBNjN/oOW2OdVimstRIQQ6cHtl4f1QfHxsHR"
+ "cPNWomyXHPEFp7I8eDR9q1SCySl17MTJx7YAQsg4pdavqb+//yGgzVrr9K27/kynV9194FOB"
+ "UiqtlEplMpmatZZKpZKOoqgWRVFCCPFLT0/P7mw2OyOECKSUtZGRkeIicAO+wlqbsNY6xBeU"
+ "LJVK7aVS6e1qtQqA67p4nncim82eASIhRCgEwZUrv95cyPoP7sJ02sxdq5AAAAAASUVORK5C"
+ "YII=")
+
+#----------------------------------------------------------------------
+ToolPanel_Controls = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAA6cAAAOxAF19oSB"
+ "AAAAB3RJTUUH1wcFDyACNseopgAAA5BJREFUaN7tl09MHFUcxz87DsIMbJa5kE22GvGwrkCv"
+ "KKYlJsDGsIg3wlKSPah3TuVgPRA4UJWsWq81sZqIVBorWBtqICkHAyvWCHKwuIdaDhyWrOyy"
+ "3Z3uzs9DLSnL8kdamiGZT/KymZlfXr7f9/v99r0HDg4ODg4OxxhX8YvRsW9F13VbilVVFV3X"
+ "eL359JZu9dGAH69PSVPTK5SpZYhNV3zyh2vbTT36cC+bRVXLuJ/P27ZkpGhl1VIRllg2NiB7"
+ "GxAE7Ksf2M+AgPUYHfD91av8dusWemUl6dQG7517n/6zZ/nwoxG+vPQFBavA2++8+4TklzQg"
+ "OwvtgJimyY0bU1y48BkAN2dvcvnyGCB8cH6Y+oYGOjs7Dz1/KQdKqQhLDjfSm2mMamPr+cSJ"
+ "51hbW0OA27f/JPBy4NBzPxzFPaCU7PKHWfifo9pTTWI9QTz+F7lsls8vXqStLQhA9JNP+Tga"
+ "ZWlp8dDz/ydu/xKyHiPFw8PnGb8yzj/JJOFwmJcCAdqCQXRNY2QkytjYNwQCARTlmSPqgZJh"
+ "B0fTNXp7e7fNGAw+yELZsypnes/sIuVwDkrvAzb+G5X9SsgSC8vGDvbcyLSKCjKZLJnMPRun"
+ "YLuBHafRS199LffzecSy33FOLVN58YXnaT59ymXfFXY4Zuyopdgvv8rfd1dtKbaiopz2N4Ku"
+ "XQ38vvSHpDZSnGyos6WBbDbHz3Mx3nqzvfSV8s6duzSfasLtdtvSgNvtRtMqtr0rOszZ9Sa8"
+ "O8pBglKpFNPT0weacGJiYsdueZSou32Ym5tjZmaGlpYWfD4fo6OjLCwsEAqFqKurIx6PMz4+"
+ "Tk1NDZFIhFgsxuzsLPPz84RCIZaXl5mcnKSjo4P6+vqn42by2nXZ2NgQEZFEIiGmaUpXV5es"
+ "rq5Ke3u7ZDIZCYfDYpqmdHd3y+bmpiQSCcnlctLT0yOZTEYaGxslm81KJBLZ+n2STP00Lftm"
+ "wDRN+vv7qa2tZWVlBcuyCAQCaJqGpmmk02m8Xi+6rqPrOuvr63i9XjRNw+/3k06nicfjRKNR"
+ "/H4/IoLL5Xp6JVQoFEgmkyiKgqI8aJNYLMbg4CA+nw/DMDAMg4GBATweD319feTzeYaGhlhc"
+ "XMQwDFpbW8nn81RVVR2Z+D1LyK4Ul5DCMWebgfLycnI509aCiy9bO4rzyncTUlVVaUvxhUIB"
+ "j8fDa682OvcBBwcHBwcA/gWitAOivrbnzAAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+ToolPanel_Default = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABmJLR0QA/wD/AP+gvaeTAAAM"
+ "nklEQVR42u2Ze4xc1X3HP+ece+/c2dnd2dm3bbAx5mlswMFOCI0hdUuI1FapmlZCav8h6SOq"
+ "WqmK+ohQm0r9I1QKJWlKURqpiVpKE6DUEGD9wBjbLMbEGNtgGxvvrr3e58zsY2Z2dmbu45zT"
+ "P/Yu2bg2sSGof9Q/6ejO/WPu/X7P+f6eF67YFbtiV+yK/X828TE9T1zCs22yWHL9PyOwCFie"
+ "t8QHgDfnLfthiIhfIPAU4ABNQEfyO7vkHXNACdBADETJCpP7+MMQEb8A4G4C+ubJgd2vCgHS"
+ "8wiDiDCo8/p/PU6jEdPd7qE1jBXn+ON/+PE3gJ1AMSFWS4hEl0tE/AKA/0ph6JUnpZL4mRYQ"
+ "HsNDpylPTdK/+yXu/cJvk2lqw6meozh8Ahk3mJiZY3qqwQMPbX0EeBk4B5SBOhBcDhHxUYDn"
+ "B19+0vF9Ul4GIR0mRs5Qmp2lf+uPEMrQ25ml59a7yXV2kct14LopTDDL6BsvIXRAJYgZOFPg"
+ "Kw8//yiwPSFSuhwi4jKB+8C6/NDufcpx8DNZBDA+OsJ0Mc+LT/w7YagByLWlWdbWwvKNdyMV"
+ "uK5DOt1ONpvFcSW1sTPMjQ+QkjWGJkrMlQMeeGjro8DzwMSlEhE/B7xMnDENfDo/vKfPUSk8"
+ "P4OxlvFzZ5nNT/LKM09SDqL3/+gpSXOzR64lw7Wf+ixS/TT2RGFEc7aTpqZmcrk24uIw00NH"
+ "cURAcTpgfLrMlx969m+AfmAqkVYtIRImQWCRyEUJCEAlkeWXCsN7dziuh+s2Yaxluljg3OBJ"
+ "Xtn6DI1Q4zoLCMMoxgqBEILWtEdXe4ZVGzejHBchBMaC1THGaOIwJJNpJdPaRi7XjporUDxz"
+ "HBHNMTMfMnB2ij/99gt/DewFZpNVAxrJiRjAXoyAC9w1dXbPHgCZSiFVM8X8KCODp+h/9jlC"
+ "a1BKIIwgshprwVoLFoQUNKUdsuk0q+/cjKNc9FQeffpdapPnqHg+rWvX43f1YKIGLS1t5Hp6"
+ "6Vm+BjMzwsTJN7GmzuDEDFOzAX/2yIt/lfjIDFBJSMSAURcAL4EvjZzc/kyjHhBEAYXJCYrF"
+ "PEdf/E/GBgZAgnIF1gikBC+lUEoilWCq0sNo7XNMldpo9c+RznWhT5+gfXKKbj9Lyk8TlAoU"
+ "3zuCrtfx29sJ5vKUx4eplmbwMlm6127i5MEDzNc1Uaz51M0r7t17+GwDOLEk3BoSff8vcxzn"
+ "0NU3ff5zCcubCgO7HmvOdZL2UgwdOUCleJb5akQYxDSMRkoYGslyaPAqcl1Z0n4F6yj2nugB"
+ "9xzXNSZIr7yJrmwPYmYU38uDmKJ65iReazNOJkNsYky5RtuqFqpBxODYLA9+bzfAEeAJIYRj"
+ "rfUTWdcW5X+hExDGmEKSZHrzQzueTqU9BILu3h5Wr72Nqk4RNwJ8L0RYwePbb+BsoRXlWrSp"
+ "EQYVypU8oQ7pnD+Kl07TnO1ASqjX55gtT1KtVwAwOsK/agM33PV5lq2+nmh2nLETb2DCkDtu"
+ "7GH/8YnnhBBVIcSItTYEqolDX1RCIonz6/JDO/b5fgbHSSEwGB1hjGXVNSu57rY7UC0dnDhe"
+ "ZnBYU5m3KGWwpkGjUWa+PkOtXqIzGqCBi8USR2XmqkUmy5M46Qydn7iXdV/8A6664QZEaZLS"
+ "6NvE5Qkc26DFd8j4KT5xfe/GvUdHTgEz1tp5IURgra0nUrLnE/CTU1k/Nbz7dS/l4jgppALl"
+ "+QuyMxptDHFYo6v3am7/5C1cv7rC8pZpitOW+UBhCYmiORqNKk2pBvX5CvVGmUZ9FusYujbc"
+ "wy1f/ENWrl1HPDtKafgoYX0KpUOsCSCOwUBL1seXLptu6t20680zo8A4MG+tXcwN+nwC8v77"
+ "7//lV3d+dw/WoKSLEgIhBUI6COkAJok4hjCYx+iQ1Wtu4vY7b2XV1XWWpYvMVBzKtRhsSFPa"
+ "IurTdORaWb95C7f/zu9zzS0biGdHqY4eJ67P4BJjtcaaGKwBbYhDcFKS1lwrbZ7L+tWdm3Ye"
+ "HBTW2ncTH4iAWJwnnTuO/eT5g9esWo50XUxcX2ClQCon0WyM0aDjCB3HGGvQkcFxPFLpDJGO"
+ "OfjqHt49PMTuQ2VW5KbZ8pnb2XjvfVg8CmeOYeJZnLhBHMVIqxEmJo41WIPRAYQao0A5DtJJ"
+ "Yxyf6ZFzDI7N8NXv7NgFfM1aOwmUzyeQBR54+h+/8si1167hls/ch5KSWIeYKPhpMS8kcVzH"
+ "xCwQ0NH77iSUIt3cxuxMmbf372LTlt+io72V4RP7qc2XicN5olhDHEEQgF54rtZmYfcBYTVG"
+ "OCgPqoUye48O0wg1Dz/R/0NgmzHmJDAJlMQFSocmoA3Y/NwPHnziuuXdrPnkFqS01GtzWBsv"
+ "nEQMFos2MdYYMIpYRzhuGmMMI2+9zMv97/Clv/hbfGWZOnuIOAgxcQOtQxqNCB2GGKNRYoFE"
+ "rB1MFKGFpDxe4PXjI2AF3/zRa9uttf3W2mljzHBSK+WBirhAEnOT2qcD6AXu3vpPf/KNmzdu"
+ "YsWa9RhrqddKCBv/TBCLdYBUaXQUUDy6m5cPDrP517/A6KF9/Orv/RGukoydfB0dzGMkhI2A"
+ "xlwVE9YxxmKNJtKWidFJXntrmNgVfP+5w3uBA8aYEpA3xhQT4MXF8lt9QK8aJdVg6cltP8nf"
+ "tcrdXClMkG5ycNNZhPIIgoWMbgEhJUG9xuSh59n/5gB33nkr3ctWMfTO6xQGB7hx46dpae+m"
+ "NHkWdIyIInQcMDVToVYLmRif4o0jA8xW6sw3Ir7/wlGEEE8ZYwrW2glr7Vgim6mkCWoAsbxI"
+ "r7oIvgwMAMG169biyzoHtm/l+L6d5E8ewXM8pJsmjjSN+Rpjrz3Lzv7TrFqeQ8oI31e4ymFm"
+ "eoK+f3kYIX1WrtsMcYySMUE9YqYwS/9bpzg5nKentYVl3a2s7M0ipdwNaGtt2Vo7nsimkJTZ"
+ "ix2clh/QcC+SqAIVhUEIwbVrVuDGU4y/9ybHD+xiZuAdgkbEqV1b2X9sgg03LqezqxllDQ4C"
+ "RwmEgFK1TN/3vo3X1MbKDVuYmyqz89XDHBucpLO5iY6WJrSw2NgyUaySlM0NIUQ1KeJmEyw/"
+ "U43KnzM10Ivx1sQar3sVeG04TVla29pxw1mOvNbPsVd/zL7DQ6xa1kZTswNIYiSx46IcB1dJ"
+ "sIapuTz/8c2/ozwf83z/abJ+ilyLTxjHGLsQ94UjWN7dgrVWG2OCJb1AsGQA8H4/4FxCO2kB"
+ "I6zF8TII5aCas+igBnMlVq6EWEdsuet6/KZmTFRbiAZuChMblADPdYgMiMhSi8o89dhDNDua"
+ "eKF5Q0mR1PAST7qMF4oYYyKgYoxpfFBH5lwCeAvY2kyBdFsvKpMjDGqoFBBFWKFImRArNZo0"
+ "jlo4VCEdrHRISYfIBkgJKU9CoDDWYFILjY8ORQJE0tnVRUdvDzNVjTEmstaWE4cNlu76UlOX"
+ "2NCf+7e+w7Xf/bUN99Co4fkZlN8K0kUqB6Ek0kkjlUIIhREC4aRo7bqa0vgptI4IIwMClJII"
+ "BFhQQuL5ivb2TlasXsnI2AxPHyjy3R/2PWKMOWitLSZRZ7GJ0eeTEJdIwEmSW04p+fCOf/3z"
+ "32jxU2S6l4HfTFArYaIIwoXSw0iwsWHl+ns4tee/mZnNY0ODNYLQGIxeyLheU5bW9nbeGzjH"
+ "ntMR27ZteyyKojFjzLS1tpCEzXzixIv1z4cisJjgMkCnkrIDIb5+4KkH71PKx2vNIVIZGvUy"
+ "WI21ljg2rLxhE6f3bmV2Ko8WAAYTAG6abHcPJ0+d5ZX3Qvr6+v7ZGDOptS4BpSRxFYHpJb1w"
+ "eCEZXc5cSC0ZrWSAdiVlm8XufeOpr6McD68li2jKMj9fJQpCrrn+Nk7t20plukAUamxTC9mO"
+ "HoYGh9n+dpUdO3Y8GkXRuLW2Yq0tWWtriWRKyZpPQnl0Iflc7mRu6ZjFS1q7NNCmlOo0xuze"
+ "/8TXEFZhc904fjPLV6zm1L4XqVRLyHSW4cExdr1XZ9u2bd+Jomgi0XbZWltJdnrRaeeXxPv4"
+ "YuA/6mjRWTwRIUTGcZw2oNPo+KWnv/VlfL+FtZ/9TcaPH+D40WO8cKRCX1/f30dRNJMkpBJQ"
+ "EUKUEgKLwC8U7z/yaPEDJ3ZKqbS11lNKNVlrW4wxPcaYr+74wYP37TtwjG89vusva7Xaoo4r"
+ "ySol12oik/qSHbcXC5sfx3hdAtJ13ZQxxrXWetbaNNBqrc0k/pL0ozSSXa4k19rlDnM/rg8c"
+ "Sz9oLEorlQD3k3uSE2gkux1+FOAf5yempT6yuBYTpj7PMT808Ct2xa7Ygv0PzFW8GpCLx+gA"
+ "AAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+ToolPanel_Gizmos = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAC4jAAAuIwF4pT92"
+ "AAAAB3RJTUUH1wcLFzgWXOxheQAACbJJREFUaN7t2VvIZtddx/HvWmufnr2fw3vMnDqTmRzM"
+ "ZGYEkUBFQ0ARVPBAKHrRGy9KL6xNtK1KqqAoHrAiaYPFGMQDVsSLWgtiDaaVWEGkmdKE2saM"
+ "k5nYTGbmnff4nPZhrfX/e/EQ8DbvOzzxIn/Yd8+C34f/3mvt/37gvXqvjlTmKIv/9Nm/KF7+"
+ "z8uXdsZ3Hhqd6J9XK2Vxj1svB9WxxNqimQVcbtAutnfeOrjeTdr9MOHK2VPnvvJ7v/371941"
+ "wCd/4+NnWuM/m5yMP7RypiqH6xXV8ZzJrZbRyRJSCFOlOWgpV1LqnUgInoObM3Zfn2JAwi5P"
+ "PfM7z/7BuwL44Ed++sULP3z2sWvfvE610ked0qtyNBqMsZhUMSIEIhKFMDVQdYQY6Pf7nPue"
+ "e3nj6zdDe9ldfPrpZ147CiB5pwt++alf+q6b/vpjONi4bwMvLb1jjrSCJLeEHShPFCSFo21a"
+ "QhOQfUd1epU717Y5deIE4xtTVs+UyfVvbT8JfPQoAPtOF7zyyisXhhsDsixh0K9o7ngGvRGT"
+ "7Zrxdk099ozvTDm4PaGdd7TTQONbdq8eYJoMR4JVi04t/eO9n/nn5/8pXWoHqmF5NobAbLsm"
+ "tobJVs21b7yFw2LTgImCG4PNHIoQglD0MmY3WzZPbLB/fUpeJkRR8uNm8/Nf+sL7gX9bWgeM"
+ "JcuqlHwlIx0ZTCIkFVAJwUZi4vEaCEmHuEg6hM62gLB6vMLlSt5PQWC0McAnzY8ttQPz+XxH"
+ "4ggVhaiAI3jFoCiCREOcCEWREjshBEUaxWlODIKI0rYRiYqI0j+WPnoUwDvuwGxab7dzj3oh"
+ "hIBNDKGOaADUEkIkdIqvA+3UE+ZCvd+R5znTvZqm9ogXktTS7Ld4Gx554YUXyqUBLp6/sDXb"
+ "nxOC0rUBohK7iHhFOoGoWGfQYNFOkSZi1bF6coR4g0RhPpkTfGB20FCu5uXffvGvzy8NcOGh"
+ "i9+YH7ShmXmyLCFJUlQAgdAGCNDNA2EeEBF8G+nlORalmwdSY8myFJc6sjSlGuYczCY/sDTA"
+ "E088WYdZvJ4XDpc4onhijEgQANQYTG4QDxhoph1lWRGiYgxEUQigQQGLjRn99eK7lwYAEM/l"
+ "8e0aP4s084A2EANohK72JAk0ex0mWEIj5HmJBJAgmM4x2W1p9wUN4KPHVVxYMiC+WDc1aVVg"
+ "jOLnim8ieIt24DTBiiM2kISM+qCj249oUJraYzMhH0C1mtHOW9KevbRUwKmTZ/5l58YeooJN"
+ "ISkMJolkA4vJFZsrXj3RNKT9lLRymEIpVnLER1QFFV1sxWKwmR19+o8+faid6FCAP/uTP391"
+ "sjV706rgfSCEgFEIXrDOEHzEZko9CwyHIyQoMSqqiwsxqIKIkGYZvUHO1Wv/9fDSAADR8/z8"
+ "oGXvzQnTOzV7b8yY3KoRlK4ViiqhO/BkWUoza2lnnvm0o5l52ibQtREVxdc1Rdljb2//7FIB"
+ "iU2/dOfGHnmRc/LSOqce2SDrp+xem6AqCFBWJUWZkWYJeZGQOEfeT7EkIJa2DszrGusc49n+"
+ "ylIBP/KDP/r81n9vt2qExDmw0N/ocfzhVXau7BNDwBi3+LEBRVEVsiKjHs+xzpDlOf1hn3pa"
+ "k/TS1aUCfvGJj02JyQsmgRAULGi09DYLkixn/NacsiqInaBRMMYsDjwHzrrF8yCKs8nipF4b"
+ "LbcDAKENfz/cqGj2G5yzGBSjhmMPrrDz1gHrJ1dpZh1RBLDI2yd2UCRGRAQJoDXM2kl2mAzv"
+ "+G30/9ZgNKyKviVqXJwDGKS22NyQ2hxrUpCAwYAqFoN4JbaRMAdjhKiCy2AwHK4tHSASTlvb"
+ "J82hmdQUvQKZgXaOalgx3ZqjIhg1JDaiURAU44BEManBeMEYh8Ecaj4/0i1kc3tq8/QKapVq"
+ "rUcbOmaThlkzpSgzVAWXJITOgwWTOVyWkGYpzaSDKKgscofgw9IBWZE+OOj3wUbECyvvK+nf"
+ "k5H3UtJsMerGGGin3WJrjYuLxBC7SIygalARfBsOlg4I0Z/0UUmzDJdZ1AJiiSESW6GrAxIW"
+ "70l+FnHO4lIDKCoGVQMqiCpdK8sFfOaZp51JOSbBMxxVoAZjlSR3uCQhSRwuMbSNx/vAdL+h"
+ "m3cYNRi3QKC6mBmawGx3dnOpAJfY40lprQQlLwpiK1hjURbzsbGWYlBQjgpGG31C1yKizPbm"
+ "0BlCq8R2MSPPpw2ba/d8Z6mAyy+9tDlYKZAAsVPCPCKtoi2AIYaIioARqtWKvMzJ8oS0ysiH"
+ "DpMoXdfQ7Hds3xhz5sy9l5cKuLV9Zz1Lc3wTyPIUErC5gRysMxT9nGI1Q1EQSDILzmCdwSUJ"
+ "eZHi8oT+So9+2bv9m7/2W7uHyXHoc2BlMDprswTrLMFHVBYTmXghyVNcP6FcyVEEZx2+TdCo"
+ "2NQQWk/Wc3gRfBdQXeKHrbcr0JUuc8QQ8fMOXweascfPPU4c1VqPtfcNWLt3QFI4jj04Yv34"
+ "KuoXz0o+TBAECUq7E75y2ByH7sBosF4RIcjildioZVAOkGgQNahrGN1fIa8L5UqBsRY/DqwV"
+ "Q3avj8lMhrWWnVt74d5T931+6YC6qaWaGWxqEQMPPHwf5T05e3HC2rmK6UENY8fm/SP8vuCT"
+ "QNd5zBQ2Hxhx+8oeqoCYL3/qdz91+7A5Dn0LTcbT3aarsYlldX2FEDwmU4YnSlxmWT83pGlb"
+ "1o6vMDjTQ7xAUHqrGWnpsLnlYGtK0mSfPWyGIwFUwuvzeYtLDf3NnKyXIEHIsoRqs6AbB4TA"
+ "1vU9wliZbXUMNkvy9ZwgQuoS5jvNS4//5Af+4V0BfP/3vf/b0inFKAc1+BhJnKOee6QF6ZR8"
+ "mNA7YQhFTXUyZbbfEJrI9GbH9o098TN98qd+/HF9VwCffOrXb4aJvKZGCW0k+AheKUrH3htj"
+ "+psF21cmdLXQ1RGXJnSTwM6VMdPdCX6bz/zd33zh348S/kgAgOnW7I/rg4aujpTDjNl+g6ow"
+ "326InZAWKdvfnLL77Zrp6zWTWw3ttGXvav3VR7/30aeOGv7IgIfuv/jsnasHr4VWwFgmuzWz"
+ "vZZilPHm13aRqDSzDnXKfF6z8509tr81+Y9zxy/+xIc//HPd3QAc6X9igJ/90IceaNPxv568"
+ "tHGiKBJ8F8nzDEWoxx3lao56uPbym+Rd+ZeXHn7kI5/42C/M70b4uwIA+MSvfPzs1etX/nB0"
+ "uny8v9Y33nvSNCFKYL7bMt1qXy5t/1c/91ef+8e7FfyuAt6ujz7x8+dfvfrqY84l54u8iNPZ"
+ "5H/uP/3Ai88999wrdzv4e/X/pf4XB3h4NJVf36kAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+ToolPanel_Menus = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAA6cAAAOxAF19oSB"
+ "AAAAB3RJTUUH1wcFDx8Yk3t74AAABbZJREFUaN7tmM9vE+kZxz8z9oxnxjHeJE6cFJJNSTZG"
+ "hCK12hVBFNREQliCvSAOiDNVL6jNsf9BDxx65MSBU6hU5AuCSEFq6UoFyRACFcUWoZtkjddW"
+ "mjixEzyx533fHkzYZUXAAueXmq80mtHMq+d5v+/zfZ7nfQd2sYv/b2jvelkqldR2nXAoFHpr"
+ "zv53DTIMg+LyK/7yzXNWCaD7/A1wrYjaHl8f6W0ooXfOTClFqVzlm5cGfstp3Oopl9NfyY0n"
+ "oGkaChASNNk4h1LTUaqx6tTXj7hCSoEQgp4Wk98djxIKaPzx1F6UlPS0moQCGs22zt6wQYuj"
+ "02zrSCFotnU6Qn5+++sokaAPIWp2pJQopVBK8ejRIy5dukQ+n+fcuXMIIZiYmCCfz5PJZHj6"
+ "9Cmzs7NkMhmklGQyGdLpdH0ElFKvI6AQQiKkpOR6/Kq7iel5l192BYmGDE4ebGZwfwifrjjx"
+ "RZjB/SGkUgzuD/HdgsvETAkhZc2GkG8RUEoRDocZGxvj4MGDjI2N8eLFC65evUoikaBcLjM6"
+ "OkoikUAIQSKRoK+vrz4CmqahlEJIgZA1x5OzJTwhWXxVJWBoSCn5V6aElIrnuRXKFYFbETSZ"
+ "Gp/ZPoQUKCVRsrYAa9ePCZw4cQKA1tZWisUiSikGBwdRSnH48GFs2yYQCDA3N0cul2NxcbH+"
+ "JEaBFAqE5PvFVeaKFRZWqnzeavHdgsuXP9/DakWQ/HYJT0gefLtEvljhy549/HNqkfYmA8On"
+ "8XmrRWbBfZ0DCvk6p7q6uohGowwPD5NKpejv72d8fBzTNBkeHgZgaGiI7u5u7ty5QzweZ35+"
+ "vr4+UC6X1Wy+wO9H/4NmWA1LuBbD5c/nv/gkG9Fo9MN94AcJSTTZuKqxJqFN6QNNhuJPp5p4"
+ "WSij+82PdhC2fQT9kvb2dgAqlcrm9AHTNJkuVPnr8yC6z1hHbB9Gq1bkD7+J0NzczEbgvXuE"
+ "ivShGTafEvSqz2IjsX4Vqj0hhKA9ZBCyakNfzJXfazDW4dDfbnPzyTwKkJrcfAI/EAEhJLap"
+ "EYta7G0OEPBDZ9hkeVXQEjQolj06wyZzy1VWViUTsyX6oxaelLVSrG/sxnbdRrbGQAiJFIq5"
+ "UoXU9yv0tlm4VYnp09BR3E0XcKuSv6cKtDg+3FWB8CTyTffdAgJvIgAIIVhxq+QWXfZYPiam"
+ "i2gosgWX/NIqnifILbpUq4K5YoUDHTZhx0csatf2P2ILJLSWA0qBJyQz/63p/t8vlwFIZZff"
+ "Gv+3ZwsA/CNduz+eLb75JtUWEFiTkK48hAA07aMdKG9165L42C+6ibSVUbrxUcY1FJ2f/QzU"
+ "q62RUNAyOfXV3k92MjU1tUVVaAegrtP6w4cPefDgAfl8npGREZ49e0YsFmNpaYlCoUAkEiGX"
+ "y9Hb28vk5CRTU1MEg0EuXLiw4QT090nox7AsC8dxuHHjBtlslitXrnDt2jV0Xefy5cvous7o"
+ "6ChDQ0McOXIEn8+3KRGoW0LBYJBwOMzKygqapnH8+HEcx+HQoUN0dXUxMDCA53k8fvyYZDLJ"
+ "2bNnt47ATyPQ09PDsWPHaGtr4/z58yilCAaDxONxNE0jHo/j9/s5efIky8vLBAIBksnkphBY"
+ "90RWKpUAaGtra0gV6ujoaMiEf/pnbsdXobqTeEcR2EmoS0Lz8/PMzMyQyWQ+aPDJkydcv36d"
+ "bDa7KQT89Uhoenqau3fvkkqlGBkZIZlMcuDAAbLZLJ7n4XkeSin6+voYGBggn89z69YtLl68"
+ "uD0iALBv3z6OHj3KzZs3qVQq3L59m3Q6zenTp0mn05w5c4b79+9j2zadnZ0IIbZXDjiOw+Tk"
+ "JLFYDKj9NfP7/ViWRVNTE4FAAIDx8XHu3btHJBLZFAK7fWBbVqGdhHWrkGma5HI5FhYWPtmJ"
+ "4zgbRuCdWnFdV1Wr1W254nXlwC52sYudg/8BPBDU8FaMEoEAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+ToolPanel_Panels = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAA6cAAAOxAF19oSB"
+ "AAAAB3RJTUUH1wcFEDkIWmgM7QAAA6pJREFUaN7tmU1IKl0Yx/9qZgaihhgVtOh7UQpC0ibU"
+ "jbRoGbRwI1EERQYRtH3fhYvAWhUERdDC3OTaTVAuYmhhaItaCC1skdGgMTPYMI1z7srheq3u"
+ "LebN8b3+YRjOB8z5zXPOc87zHKCppv5uaX6tODo6+qfOYzo3m83ey8vLqkqz2Qy/33/ucrnO"
+ "PwRIp9PE6XTWbfTRaBRDQ0MYGBiAKIqQJAmSJIFhGKRSKQQCgaoxa9U2JR4fHzE6OgqNpvrf"
+ "GgwG6HS6mv6qAwAgD75QKODq6qqm/me1qHVxsiwLiqIgCAIMBgP6+vre7PeuBTiOQzKZ/O2H"
+ "FhcXIYqi4gAmkwkzMzMIBAJwu93Q6/Vv9nvXAgzD4PT0FMfHx+jt7cXd3R2CwSBsNht2dnbQ"
+ "3d2NqakpAEAkEkE2m0UwGMTk5KRiEC8vL/Iifn19/RzAz1pbWwNN0zg8PESxWEQ4HIbFYpHb"
+ "V1dX5XYlAJLJpOyBCCEghEAUReTz+a8B6PV66HQ6SJKE/v5+UBQFv98PjuNq2pWQ3++vcqGi"
+ "KKJUKuHi4uLP14DJZILP58P09DS0Wi1MJhO8Xi+Wl5dRLBYRiURA03RNe92VTqdJPbW1tUUk"
+ "SSKCIBCe50mpVCIMw5B8Pk/i8ThpiH3gM2p4ANVuZIVCATRNy2WbzdZYAJIkoVwugxDyoXdT"
+ "LYDdbofdbpdd6fPzc2MB0DSt7BTiOA6pVAoej+dbADo6OmCxWKo2sk8BsCyLRCKBXC6H8fFx"
+ "uFwulMtl1VlK+xFANBpFKBTC7u4uWJbF2dlZ4wAAgMPhQGtrK6xWq2LnnG8FaASpLqjf3t6G"
+ "w+GQ/X/lLYoicrkcVlZWNF/yQt+prq4utLS01MTAPM///6ZQE6AJ0ARoAtRX7+4DPM9jYWEB"
+ "w8PD8Hg8cDqd2Nvbw+3tLZaWlnBwcFCV8FIyoaUIgEajgdFoRFtbG8bGxiAIAoxGI+x2OxKJ"
+ "BIDqhJfqAAAgHA7j5uYG+/v7yOfzmJubw/39PSiKAqB8Qquih4eHqqNEJTP39PT0OYBYLIZy"
+ "uYz5+XmwLItYLIaRkRF4vV5wHPefJbR8Pp8cSlYenuffjEfeBTAYDAiFQnLZarViY2Ojpl8l"
+ "g9f0Qr8om82ip6cH7e3tWF9fbzyAwcFBxONxzM7OYnNz82uLuN6amJiA2+2W7wcIIeq3QGdn"
+ "J66vr2vqeZ6HIAi/t0Amk/k3k8nUk+E8l8t5T05Oqv545Z5YzTOmqYbUD2LQSUJ+JkydAAAA"
+ "AElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+ToolPanel_Sizers = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wcFEQkvIeblQgAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAAAmElEQVRo3u2XQQ6AIAwEWcP/v1wvHghRAtIUMTNX47aDFjElAAAAGMb+0LyL"
+ "hDqq2US46hy9eAxq9Jn71uyhlNS+dpcjJTNLKu8dzSk4wt+fq1EznzEIF/AGAQQQ2JzwD9ls"
+ "DgD8bIjjT6PD3X/sNOoNAqvJodWkzQXqIW5tAp3SfQKtEK09psRuowwxAgggUMMvJQAAbM0J"
+ "LEI1OD2LmAsAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+ToolPanel_Windows = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAA6cAAAOxAF19oSB"
+ "AAAAB3RJTUUH1wcFDx4V9NE2HAAAAw5JREFUaN7tmM1rVFcYh59z7yDOkJAK0YkaKLaSdNQp"
+ "CDYj3VTaXQq1FItm3X2xKLhz4S4QUPwfTApCoJB2pyhoi00TPyijSEM+pNHY4kyuIcy993y4"
+ "uB9J0EkmM4sYOD+4zJ1zfrznfc77njMwYGVlta0lGjENDl02W5HchfM/bZhfZr3Jm7dumyuj"
+ "48x2n9qS3f3mR2XOfvcZX574QjQFcGV0nB2Ffl5WXje8aK0yT7v26s7rXCcq29mQb0ehn7ND"
+ "V5urwODQZfNP17csvIqS9/99hBDOWz5pBNn9h9Ne1EsvcQ/21V1w4e87fHS0m/lnjfnyfacY"
+ "PNFr6rXTuhVQWhOEEoC+D17RvqsTIRwcx4k/BY+fTjFd+xjHjUI5gJSSQ/tyHNqbS2OVny9T"
+ "nl+OY6oIPvYBlOeX17wnPqV182fAaINWUYCvjn9KT28PruPiZlwymQyu6/LrjbtMPdGATgEC"
+ "KendsxOpVBqrd89OHsx5GGPS8UBKQim5dPIA1//6j++P7ebiL9MEUqY+0xIABm2iAEIIHMfB"
+ "caMKJI8QAq01iJWFpJQorfn5zxfp2Jm+LmScmIo3RUrJwzmPkXsLDJTyjNxb4OFcdC4S30bX"
+ "n7MugIkAtNEIR6xJfDWAiT0JbBgqtNaEoUqf5LsxINWKr9CVY6CU59ofzxko5Sl05db4jDEt"
+ "VMBEbQTw+2SZmReVOHEXJwa6X57CmCLolYVCKZmcqXKmlE/HJmeqhFLCqgqEcQudG3nMo2ev"
+ "mZyppuOJryUAtMKoEIDfqj1QfZfpExxXp74kgYnpChPTlXdsikLG3sSXaPV76tOqlUOs0DLY"
+ "8O7XcqX/a2QJZifqejv2HcSrVsg06DMtAUgfXfM29esZAB0fHqk7v+RVgVrDPpRsDqCjLcvn"
+ "uVlKBcnm9X/9qf2b8/k1nzayzVXgh9NfEwQBW6nFxUXGxsaau0a3gyyABbAAFsACWAALYAEs"
+ "gAWwABbAAlgAC7BNte7fKr7v43nelibo+35zAMVikeHh4fdil4vF4nZvFCsrq3p6A8PNt8Q7"
+ "ja/MAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+ToolPin = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wcJAQIldDfJXwAAAvhJREFUSMftlVtIk2EYx//f9n1z0+k23fSbm5pFB6Uj"
+ "qWGZqIQJ2QGKCIJuiq6qu4qIIKKiu7roRoKuCgoNQxMPLQLNWWlqqeWpppMv59zZHb99h66C"
+ "itycIt30v3xf/s/v+T88Ly/wL8W2Pd7Ff2ovFB0TkuXWIBa74Hq71nuvnx+ThyyEtLggLG4/"
+ "Msjq15iVufmvCW3eK0kaHVoRgB8e0AW6W8Z5W5c6lXQBMjXEBRt4kgMKa72iStuUtLn6MZJp"
+ "k0Sl5xMGAIAw821dwGF7Ev0+VgT7JGSeESgEF0SvFfDPgVXQkBRUWiT5ZbeoHfseEcm5kYQA"
+ "AOCdHDJKJ8yf5X4mlXd+AEuqADcDGecDJQYguO0Q/AR4Y8k3Ymf5ZXnN1YaEAAAwef9SndL5"
+ "5ayUNgJyCghOQ4y6wBI0+AgHBTcLWO3gHIC/+PixDRfvPPvpJZcCsMm07GDXDEprjNCSgJLU"
+ "gVJngwy5kFRQCXs4DRLt6IJ3ZKAzxbixP+EE1o6HL4bfmw94PG6IiIKdZVCYrQZtzJzSVZy8"
+ "Nw/tc1KeZjVsLBT/9MZNwHwwZc321pcXHz4IadCBQDiI+bk5OC3TXkn65tq8bbUjsfwxE/AB"
+ "9w73YHszNdNm8LAColwUmVsrwKtohMPiTf2WI9fiNfjXBExPx1puqPFB4GOjkXcxBhkBRHkB"
+ "HmYa6ap+eB0eGGqvzC9lvH8F+Jmxc5nseFVoPAjCUIS5KR8WuDAiwSjCAR9S0rWwW8a+LBug"
+ "M+bXJaXXWJQyxf4ombLVPf89p8/8FUeraaQKs5AqsyAa6FMAXsYDxN0i0TeaMfGus37C1LGn"
+ "qlhOURQIAlIEI6Tg9GUdWnPmdkvCCX7rIG2TMy/XUKJRq1oGbrRe4G0jVQIzdNrR/WYvqc1Z"
+ "0juKqabmp5syMjRCb49J8+u5x9ywXbQOUSsGKJVKV9nuotEVF1pMGo06YmqtP7Fcf8yfSqFQ"
+ "vC0tLXJlG/KaVqV7vT7r7tRkn2zVxvNfAPADQ+E0joDDAqQAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+ToolPinDown = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wcJARYBZpr62wAAAsxJREFUSMftkltIUwEch39nO2dOnW7q1KObt6LUYaak"
+ "RmWiEiZkJRS9BL0UPVVvFRFBREWPPfQSQU8JhYahSWqLQHOS5iV13nM6OTp339zmPDuXXktT"
+ "tgx6qN/j/+H7+OAP/N+/Oba94SA/0qET7TOSnbKIjQeuv3uP5+7VKfmaiZCW5gfFovphNi3b"
+ "oMjM+Uiosz5I4um1HQn4saFkf0/bNG/pVsWRTkCmgrhqAU9ygK7OIyrVLVEFNQ2IofUSZRof"
+ "sQAAhMW53X675WVoaaoE1lnI3EZEC06IHjPgWwEbTUOSX2WS5JQ/oIqPvSBiMtcjEgCAZ3ZU"
+ "K50xjMt9TBzvGABLKgEXAxnnBSX6IbisEHwEeG3ZHHGg4qa89nZTRAIAmH1y46nCMXFZSmsB"
+ "OQUEFiCGnGAJGvw6h2huGTBbwdkBX+m5s3uvP3q9kUFuJ7DI1Oxw9yIO1WqhJgEFmQxKlQ5y"
+ "zYmo/CpYg/GQqCdXPcahrlht7mDEBebO52/H+gwn3G4XRITALjPQpatAa1PmkyvPP7ZB/YaU"
+ "x5s1uTpxK8aWBcyAPnW5v7Gi9PRJSAN2+IMB2FZW4DAteCSJBXVZ++uMCGO/LOD9rmLXcEcr"
+ "tdiucbMCQlwIKYWV4JU0gkHxftq++jvhwDcVML2du7jR5mf+r81a3sloZAQQ4gW4mQUkKgfh"
+ "sbuhqbtlCxe+SeBjpq6ksNPVa9MBEJoSrMx7scoFsR4IIej3IjZRDatpauK3BcnanKdRibUm"
+ "hSz6eIiMLXTZljK+GL7hTA2NOGEZUkUqRA19AcD7cAVbfpHonUya+dzVOKPvPFJdKqcoCgQB"
+ "KQLrpODwpp7KvvSwLeKCn8zxeY6sTE1ZgkrZNnTv3TXeYqwWmNGL9p5PR0l1BhkOfNu1tL7K"
+ "S0pKEPp79Qk/3t2GpiLRPErtWAAA5YdLJv8I6K9tfKQvZqeM79ccK3IFJvEiAAAAAElFTkSu"
+ "QmCC")
+
+#----------------------------------------------------------------------
+TreeBitmap = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAA4AAAASCAYAAABrXO8xAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDhwKdc1BSQAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAACsUlEQVQ4y2WTy49URRTGf/W4t4e2u8f00E0UZZgHCAECwWAiJsYHklE0UWNM"
+ "YAEJceGCsCNhR/gzSFy4IERhCSqJRCTIZgSJCS6E7llglBnnAZluw517q85hcRlH8CS1q993"
+ "qr7zHTOVTamiAIgqiqIqPF3GWAwGawwAfhmKKgQp+OrmWfpZn6zISFxC6lOiRN7f+h5rG2sB"
+ "V4LL0Ex/mtOTZ/hox4e0a61STCJBAlnIuHDrW0ZWr2fPhrdxxmNFlSw85PTkGT7bfZjnG8+R"
+ "upTEJiQuwVtPxVf4YNs+phdnuP7nDUQjVjTy9c1zfLLzYyq+QmITKm6A1KU443DWYY3FGssb"
+ "46/z0+1rKIoFyIqM5qrm489bvHVY4zCPjfhvDdWHuD13pwRDDIgKokLUSC/vEaRAVFDVlYMy"
+ "1hqlM9cpQW8dUUsjFpcWudz5kQfZA6JEugtdpnvTKyIoSyEvxyGqRIkAqCpRI1e6V2k+8yy9"
+ "rE+73qYx0CCqMNubY2RofdlRUQopKGKBotQqNTa2xzHGUh+o0661CBKIErk7f5eta7ZgDYa9"
+ "m9/h0u8/UMSCPOZU0yrNapOx5igDvgJAkMj9hwsMVht467HWOEabI0QJdOa75CEnSiAPOYUU"
+ "BIkUMZCHJS79dpkDO/djjSufao3j0K6D3JnpcOOPX8qLsSCPBUECs//Mcv7Xbzj82iESl2Aw"
+ "mG7WVVFFNCIqnDh/ksQnvLt9glpa47tbF7l6/RpfHv2CRqVRzhdTZrVMvENRhtvDDA+tY3Lq"
+ "ZxRlfM0Y+rJST+v/QtYYvMGwvCHWOF5svsBSyHlr05t46wkSmOvP46zHGVuu2HLHUgVE4ZV1"
+ "u/j81BE2jW1ksDrIX/P32Lt9zxMQUJqzAhta1RbHPz3G3wuzXLzyPbs3v8rESxP/y+wjHwdM"
+ "yMvIwOAAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeBitmapButton = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAYAAAAS7Y8mAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDhopgfCXvQAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAAB8klEQVQ4y62U3WpTQRSFv3POHJP0tJLTJMZISaJetDY0WrxReqH48w6CDyHe"
+ "iY8hPog1ir+INUK1YEvF2Iq1tETSqCUtITHmb7YXbSqScwQhezMMzLAWe69Ze4x7G7NSbVRR"
+ "hs0gwjAhaAdR1V9VLp68gEYzqHj66RnKEouWbjHQEAMlgNb91dbbdQpbK77YTOIUju34MWPu"
+ "bf05t5qnLU0iwy7RkQiVxjYL6wt8r3/DtAzmVvOeOEF6xN6XnW6HxOFjpNwUubcPeDL/nEAw"
+ "wIe1Arl3D+l0O77EAigAEelrRovGNEyKu0UKnz9y89oNYk6Uzd1NljaW0aIpVUskRhIeQuAv"
+ "BYAyLSr1HbKnp4gMjaJFEx+OkxmbBMANud5YEUxE2Jfl77XnStyhMKXSFpXGDrV2HWUq1r5+"
+ "odVqEbACvljVq9irH2VamHaQTHKSV+/zxGNHKJXLjMbCzOZzJKNJzh6f/j9X9NIyLK5mL3Pl"
+ "zCVs22Zm6hz55dfMTJ/nzv273ihhz8dejycihFSIdDh9cJY9muXF+kv0T2F+8Q0TJ8a9sf+S"
+ "YmJsnEcrj7HVoYOzZrvJj/I2t6/fIupE8JUR2Z886Z+8dCRFOpLqx2T/2NF3ohGUZZnUWrWB"
+ "fhVd0Sgn4LBYXEJ3uwMhNS2LpJvkN6H3I3eVaYw5AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+TreeButton = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAASCAYAAABfJS4tAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDDc1tl9FcwAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABTklEQVQ4y7WUP0uCURTGf9f3SqKFlc0uDREtLg01lPQFQugThPRZgj5Bf0ax"
+ "gmiLoECHGlIjDVISg4SGaKtXwTTfexocXHqr4XoOl7uc58fhuQ9XNToN8cTDZjnKQVffargd"
+ "F62CVqAqAKFgCO1+uiRnVzEYaxtf1C/Rjjj0TM+qFYhCC2CMwTIZPbhkFGDxBedKeR6f60Rj"
+ "UVIr64SD4X9iIQAgIj+eXCnP1kaahbl5sudH5Ip5POPR6ra5qRR8dUOwTwPsnR6QPTtmeXGJ"
+ "3G0eI4Z2t0XhvuivE0Ejgp/FAqRTmzy8VilXKygUfdOnZ76GAz715+PtnuzzzgdriSSxyWm2"
+ "D3eYmBlHi/5FJ6hMLSOJeMJqJq6ergc5FhHLYWOEORbAiLGMFbTjBGj32lbBnhh0ZCzC3UsZ"
+ "49n5kwOOQ3wqjmp2m6KUsmuFCN99Z81uYi/9qQAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeCheckBox = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDQQLgpdX3wAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAAA2ElEQVQY043QMYrCUBDG8f97GFZEjYUaESwiSIolHsDGQrvXrkcQDyKeyBSK"
+ "iBZeQRZNIVjIKmtgQReEZ2IhLIRs4bTzG2a+Ef3xIOKFSgGM1DDRuN1vTPwpZjrPbD1H/jet"
+ "Q8340+Pr54gO7wBPqEMdg6v9ivM1wK2+0613nlAIgbfxWOyWABwuBzZHn4pp0aq14jcCbE8+"
+ "AMFvgBSCtt2ObZFRFKEchZUvsT35fF/O2EWbwpsZhwCGNFCOIpfOAtCsuImAf6kNadBzP3Cs"
+ "BuVMOQHFqw9/AAnUP+Hao6QqAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+TreeCheckListBox = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAIAAABPIytRAAAAAXNSR0IArs4c6QAAAAlwSFlz"
+ "AAANEgAADToB6N2Z3gAAAAd0SU1FB9sLHg8RIv7ecjgAAAAddEVYdENvbW1lbnQAQ3JlYXRl"
+ "ZCB3aXRoIFRoZSBHSU1Q72QlbgAAAO5JREFUOMtj3P54hyi3CAPp4PXXNyyi3CJyAnIMZAEm"
+ "BgaGX39/IQudvnn69os7WFXP3DUbmcvCwMDw7/+/zRe3SPNJGykaMjAwXLh/8cOXT6KiIjde"
+ "3ZDllP31/5eKnDJEVoxXFN1mBgYGV22Xl29eQdji/OIcnOxCvEKu2q6SghIKIvJw2Yu3L124"
+ "dxGumfHMuzPk+fnRh0dMDBSAgdVMfFTturL77ONzZEaVtZrVvuv7jWWNyImqplWtKmIqo1FF"
+ "dFQdvnnk2J3jZEYVDyvP/U/3yclVf/79eff9PQsj6yCIKpbXX9+Qp/P11zcAPRSkxqrj4tsA"
+ "AAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeChoice = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAYAAAAS7Y8mAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDhc2uVbkBQAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABWElEQVQ4y7WUPUoDQRSAv+xOSCCFpIlN3MKIYqFX0D5Y5haCTYhYeAERb6Ao"
+ "FhaKRAsLrbxAUttFUmgCplgikXX3PYvNj4mQ3UCcxzA8+ObNzMfMJKqNO3V7LiaRZB4tYUE6"
+ "mca4Xy7bhS0EiZzk+R4pk0LRqdzjyxPGVhtPvFi7aX+2WVpw8OV7OqgJjAIiEquwqKBIDF4x"
+ "4aAzeYzmFSvE4oX0Cw7yQAP2zw6ovdYnSLAAVDVWRxURGeZH18dUr+7ZPdyj8dEYsTCbCp1Q"
+ "USmVqZTKfxWpYlAlrmJVHVvh5vmWVrMFwE6xiJN1hqz121lUMOF4c32Di4dL3oJ38tn8GDez"
+ "itFkWMkVOD85pZBbHlOhSniPh0eMVCFh2V/82uLquKb+Bv7tHocvT+O/vEGPWtjYtkXX68Yq"
+ "bCxDp9fBF38qF6hgMqkMtWYdCYK5fJuWbeNkHX4AhOgP4SlaxN0AAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeComboBox = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAYAAAAS7Y8mAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDhcL4T6oFAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABFUlEQVQ4y7WSwUpCQRiFvzt3AhctrMBFxiXdRSC6k95B27btJaIH8AUC6QWK"
+ "NhG1cGUm9BhqKxdpBip0IRCdv0VUCl2die4/q2HOfBzOf7xatyb9txeU5xM1/XGP3c0MNuMp"
+ "SKwl0INwQHmvtFTcaDc4yBaxnXrrHg1qpVAEpmZqDUY8tJUOMMbgQLYDf0olDrA4gQUcHMsP"
+ "+Pbxjudu7/t+WCqzk0wvgJVLFF8nt5/jsn5F9eKcoT8kndxeeEdsoxBhPonsVoZq5YzrhxtO"
+ "j074LaU/L68Q5Ckc5yMWG1MrRLDv8fzy/rcVcfRYACMGFxMaVn8wMiOchNbgmRh0aj1F86mJ"
+ "VtHm268dxu8jK6jyfYKNgA+sz3ZB07qXmQAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeComment = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAAAXNSR0IArs4c6QAAAAZiS0dE"
+ "AP8A/wD/oL2nkwAAAAlwSFlzAAANEgAADToB6N2Z3gAAAAd0SU1FB9oEBggrF1QqReMAAAAd"
+ "dEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAN9JREFUKM9jvPfj3n8G"
+ "CgATLom5x+czbLi0kYGBgYFh3vEFcDZRBnz99Y3h8fsnDGpiagw/fv9gePzhMYOamBpWAxiR"
+ "vXDz5S2GZWdX4HQuPwc/Q5FTPm4DYGDludUMP//8ZIgzi2FYfX4Nw9df3xkSzGOJ98LTD08Z"
+ "pPmlGRgYGBgev3/KICsgjdNVcBf8/fePoWlHC94Qz7LNYBDnFcPvhXOPzzNsubqNodqtguHy"
+ "sysMm65sYah2q2BgZmImzgvPPj5jEOcVY2BmYkZhE50Onn58ziDJJ4nBJhgG5AIAiU9gp6jc"
+ "WfUAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeDefault = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDgoZ7eu1QAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABtElEQVQoz4WQz2sTQRiGn5lsQhvUNkmLERvRQ38c9FQvVtGb/hXiXf9OBT2p"
+ "VFBiUgxIye5mm81md2Z3Zmc8RKNUwef2vfA+vHxirMeePwiLkPffP1DVFUWlUEahK8VGa5MX"
+ "x8+5jLwcDOMh9wfH7G3fpH/tOjtXemy1t5hlM86X538JgsuBtiXaalK9IFUpqUqZZQlpnmKc"
+ "+b9A/ZydqpQwiwjnIa2gxcnBA6ZZSFIkOO9w3tHZ7BBERcQ4OcM6g6ktw+lXOu1tvsUTkuUF"
+ "pdE8PDzh2f5TcpOvy847PkdfCE6nn7jXv0uUxyhTIBCMojFxNkOXGmN/z659jfce6yzWWZx3"
+ "BKUpcd6RV0vyqmDQ2+Pj5BRdKm7tDqi9oymbeDzOO0xt0FbjWYkCbTXaarJyybyYk+QJO1d7"
+ "mLbh1aOXALyevKGsS5RRWGfxeASCQDYI4ixmoTOmiykX+ZzKVhhrcN6tpwshKG2JdXZ1I5BC"
+ "0my0CPKyIFyGxNlsVa4NdV3TDJprwdHuIaNkhBQSgUAISUM2uNO5TXDQ3+ft6B2/fuGcQ0rJ"
+ "k6PHa0F3o0v3Rpd/8QPZ/Bl4qenM9gAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeDefaultContainer = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAIAAABL1vtsAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDiYubGd74QAAAfFJREFUOMvdlEtvEzEQx21nN2ojoHk0IoiGtqr6ONBT"
+ "uVAQ3OBTIO7wneCTwA0kOBVUKlBIadKiKPtqNptdv8ZjDgEURZtKCTf+N3tmfv7bHg19dfS6"
+ "UW6QRXUWnjnrtfXN+sbCCLSGkX/Wf4Nwcne9zDv6+UkZlSnONReKLxWXnx88m8NFK2jdax6s"
+ "lW83btxcvVZbKa2ESdgb9eZwIUAKELEYxjyOeRwmUZzGGvUcCK441zzmsZf43sArOsXDnfv9"
+ "xIuyCC2ixcpyZauyNY3wM/80+gGotYFW/3ulVO4E3Wh0KbV4sHv4dPtJqtNxPVr86n/LQRz3"
+ "v+w37vppwHVGCW37p0ESCik0/PZvrLHWAgIgoMWci0gt0WKqRqnKmrW1z91jIfmdetNYdJlr"
+ "iUWL2mgBwhILCDkIAUKASORokA2iNFq9XtMl/fLhC0LIu+57aSTXHBAssZRQhxVyEEESDEXS"
+ "H/Yv04ECpUH/dUsplSDHJ1NCGWVuoZiDSGXmjbwgCRUobbQxxnXccWivvtuO2owySiilrMAK"
+ "m5WNHMROY/tD++P4RRCRMfZ479E4VF2qVm9VZzU4fXP+NndeaITihFs78QWTOumdOLPYLnNm"
+ "lV3VnZTQyaUldtrzn4TJkHN1zZRyE5xO1BHAFx4W59HFL52bPckdnR6/AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+TreeDialog = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAIAAABL1vtsAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDSwcXBl8sgAAAjtJREFUOMvtks1vEkEYxt8ZhgV2gX4wtKSCQNLU9KAH"
+ "Y62nJsZ4Uk82/iXGP0fvGtuzGo3Gr0ST2rQ1pmrirtCuLOxWWFhgd2deD2jVirHi1ecwmTfz"
+ "5jfzvPOQ+5UHK2ur8Vg8EAEcTn4YACIAIMKVU8uRxJI6xacopSktlUlP+hjkxqfTWpowmojF"
+ "IUJSakpRooRRFmUsypBIPpaZyczwMR5C+GT7KQMCrW6z7XXqe43ykRIAlidKZquWncjanr1Y"
+ "nHe7ru3ZqqLansPVzJb5uh/6ZwqLpvvJsD8iASpREkIXSgvFyaPT6WkhZavrRoDqDYMirTfr"
+ "dttpdd2e32s0G6EIASAMw7Xqq92mGYhAomRCCkS0OlYhV6h+rvrCf1F5iYiUULNtDswTIAhI"
+ "CLFcqx/2gzDY7G4BACEkEAG5vn4jN56DUaXbOitmiuVsaWSEREHhn/Uf8V1sf9fstTy/Q8mh"
+ "oL7wC+OFgwjP78zy2f3y2fZzwzEunbyYjCV/RXyw9SGvAACJcrDeeXNXr+k7nd2l3tKOs+O4"
+ "e1zlSGWe5+PROAAgyGGzQJAoJcqH7x9ZnqVosQRLqEpCN41yrnT78cpGZVNhyqBncNlBBAJI"
+ "lEKKuezc+rsNu2afnz+nRtVaw7p579bisdMnisdbPVdIIaSQiMONCCkQgCf5tQtXtZimRBSB"
+ "cvns5Z96vpkdglCYsl1/C/AVX+/84UcA8gcRXMtkNX7ILCD8xsiPB38RLcMxemF35GhWnOoX"
+ "dDYswVEEFVoAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeFrame = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAIAAABL1vtsAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDSw5Fx2o9QAAAXBJREFUOMvtkM1OwlAQhWcutwg14E+LEA0CS/caXfkU"
+ "xsfTN9An0JVuNEETceGOCrEKtFoKFHp/xoUJQaOEYOLKk9lMzpkvM4NnjfOT6mlqISWUgNkU"
+ "SwFEAEAEh9sHifS+uWavMcYyixkruxqTKCzns4tZ5Cy9kIIEZsxMMmkgZ9zg3OCE2l6y1q11"
+ "e8mWIC8eLjkgdKOgN+i3XzuVjTIAVVbKbvclt5LzBt5uaSuMQm/gmUnTG/i2adXc+5GM94q7"
+ "bvjseI+EwDRpRLZT3imtbuazeaV1NwoTwOodhxFrB22v53ejcBgPO0FHKgkAUspq8+YpcIUS"
+ "mjRXWhFRq98qForNt2as4qvGNRExZG7P/TgeAQkIEVthayRHQoq7qAYAiCiUwKPb48JyAeZV"
+ "3avzklWq5MpzIzQpBr/WP+If8dcIoSUiG9cUBP/JMBgn0rNs8QmBgJMtAX1JjwOTFp8+80Xf"
+ "BrjjO0MZzf3Lht98B9fgtCT+vOW+AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+TreeGauge = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAIAAACdjxhxAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDiMlhsJWLAAAANpJREFUOMul0kFuwjAQBdD/x1bSQth0X27cnowjwAW6"
+ "oq0oQcnM7wKJxnRji9l5JD9/28O33ft5GlHW6XLaPG1QUV3u8nkaV/1q2V13z0O/3r681hD7"
+ "j0MGBGjZFUBaslxDGC1DiCgJCRKqKwsKRElEAwBkABEF0QYAWYDuUpTLqhTSv7eAmgjFHQFJ"
+ "eijF7E41XsTIv/0xS06kJoJmdjs/JNAgNhAEEg3A7LPkiVyGqhtQ0JhdcgVppBmNbZ9KhFzh"
+ "1yzXsXd6AzH0w9f4vWwdfz4v0+hepSRLv0Gpb9SsRdiOAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+TreeListBox = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDQ4JlnbeeQAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABBklEQVQ4y+2Uz0oCcRRGz8RIidofmZ8WMlPR0MZVtqtt82JBDxG9QS9QGNSi"
+ "qIUWTgQpSgO6KWcwkYZgsJmW7czFXRj0rS+Hj3sPVzvrnScqYyARPwzQVcbAWraQyhxA9BVR"
+ "a9Vov3YmDh9XT34F6gBxEtPwXIYfI5QyaPabmGmTKImwrS1KiyUqmzsUcmq6hgDFpSIL6Xny"
+ "uTxO2WFtZZUNYx2nfMBb0AfAbT/SeHEnArX6oJ5I7bA77P40FD3K7AOn1ab6dMF970FOm/3t"
+ "PS6fr9g1KzLaHJ4eYRfsf21mSZvr1g23nTs5bbKpLN7Ik/k243jM4PMdXUv9cW10PwzEYH4Y"
+ "8A3oJpVpLSV68QAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeListCtrl = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDgoZ7eu1QAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABtElEQVQoz4WQz2sTQRiGn5lsQhvUNkmLERvRQ38c9FQvVtGb/hXiXf9OBT2p"
+ "VFBiUgxIye5mm81md2Z3Zmc8RKNUwef2vfA+vHxirMeePwiLkPffP1DVFUWlUEahK8VGa5MX"
+ "x8+5jLwcDOMh9wfH7G3fpH/tOjtXemy1t5hlM86X538JgsuBtiXaalK9IFUpqUqZZQlpnmKc"
+ "+b9A/ZydqpQwiwjnIa2gxcnBA6ZZSFIkOO9w3tHZ7BBERcQ4OcM6g6ktw+lXOu1tvsUTkuUF"
+ "pdE8PDzh2f5TcpOvy847PkdfCE6nn7jXv0uUxyhTIBCMojFxNkOXGmN/z659jfce6yzWWZx3"
+ "BKUpcd6RV0vyqmDQ2+Pj5BRdKm7tDqi9oymbeDzOO0xt0FbjWYkCbTXaarJyybyYk+QJO1d7"
+ "mLbh1aOXALyevKGsS5RRWGfxeASCQDYI4ixmoTOmiykX+ZzKVhhrcN6tpwshKG2JdXZ1I5BC"
+ "0my0CPKyIFyGxNlsVa4NdV3TDJprwdHuIaNkhBQSgUAISUM2uNO5TXDQ3+ft6B2/fuGcQ0rJ"
+ "k6PHa0F3o0v3Rpd/8QPZ/Bl4qenM9gAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeMenu = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAWCAIAAABGyIsrAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDSMTSz597AAAAepJREFUOMvNlN1v0lAYxs9pTz+ASvnsAEeGum4kmpi0"
+ "zLF5oRd6rYlGr+a/qFeaODO50mic2YWRKmI719VBPxhtKaWU4QWEhGQmzCvfm/ecvM+bJ88v"
+ "JwfunewlI0mwWHX6HZSKpgpMYcEFCCE2OamOqnv6uaLBaFBTaqPxaHJFk/b2R03Rlbvrd1pO"
+ "u8Dmte5vP/QJjHh4/QEE8ND6tXHZjxExAAA28+Jz/NeTOgBANhVxWYAAJqKsPbBJnGQj8Znh"
+ "1EFcFizPqhTFn5ZcSq5kohmxKNCIZkjGDdwgHErGNzEvAADggX2weGjN1TBwwfrXhWaneewc"
+ "n6vwQ3+3+WY2nYZ+p7yXdeX26rbRM7JM1nCNXtAjcOLxjUc4hleLm8+/vHgm7MxhXcvxjXYD"
+ "YajttDeKFRIns0zGCRwI4Evp1f21e3MO26Ut07OWGO670biWusrFuK1SlcKpOBX3Q58m6Zbb"
+ "yjP5/xpr3ajLp/LfsL5u7kqmNBf609G+rCu3rlQ63mkiynb7drdvU4h8evMJjeh0NL1/9Lmc"
+ "Ls+/1qVVxTxEOLJ9p7qyeYlm8mzODdxgFJQz6+FZOFVOKKmOankWx3CSLvFpPhVJmX2TxMkE"
+ "lRieDT+oH4WCkKBYzdUujBVZnjUejxf/BP4At2vcLl9p4lgAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeMenuBar = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAKCAYAAACwoK7bAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDS8jwVICTAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABc0lEQVQoz7WSz2sTYRiEn939YrNFk+1nm8CGtoFEm0OUhOKlIFh6En/9iXqT"
+ "VJAiiNqLbamosYIN8SCua6BNSrCw0Ww23aJ5PRS8SI8752GYYR5js7spJCDj69hLJFgJExIJ"
+ "nsiErb0dgl8Bl7XGnXWxUzaFvPufOQgDnr9+gaMd1m6sYl+w+db1MQ0TS1mc/j6l7JYAMEUE"
+ "79Djwa17WKaF3/Pp/ejx9MMGjTdPGMUjRAQRYRD9JK9z3Fm5jWVaPN5t0Nhep3PU4e3+Ox6u"
+ "PyKMQkQEJQjRScTGzjOCKCCfzTEYDdhrfmRhfp7+cZ+iWwRARHj/uUlsxJQXSmTJUivViOKI"
+ "dHqKeqXOtD2NIGeNZzIO92/epTDjolQK56JD5fpVcnM5tNb/GpuGgTIVkz+CzmgORod88vdR"
+ "KsWldAb/+Dvh+Gyh0Q7b8nL7FdHJmOVqncXC4rmHeB2P1pc2AFeKZa4tVc/HrTVsJYPbMB4m"
+ "gttfwd+fUZxCmekAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeMenuItem = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAICAIAAAB/FOjAAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDSMxnl48CAAAAM5JREFUGNONkM0OwVAQhWeqbahGVSwoDRuxsLuXNW/A"
+ "E9NHsPKTiJZI/ZQrqqkWTS0qVhadzZyTnMmXMzg+jNWcCunm+rjyJamkyVrKA0TkErW77xzf"
+ "+RsKo9CwjCiOEssna7IyLMcatPvH+0lTqvZtH7wDgRNGnSECbti2VwvyQh4AuB+rVWnNDnMA"
+ "MC8WrRMELEqKG7piRlRyhR/wS6B1wnzW1emamU21UZbKVCdZPiuLsvf0nu/X4rykVQIAOHWn"
+ "6Uvbns0zn8VxnP6tH1wDT0VKdioxAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+TreeNotebook = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDQ0SNz5EVgAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABXUlEQVQ4y+2RvU4CQRSFz+7O/gyYFZKNBYXGYKEGjT6ANjTG1tgb38j4CsbO"
+ "RGPhC4g/jQ004h+BAg1G0BCFgeHakAXdQZRoYziTae7JfHPvudrWxTYVygWoZBkWluNLsJmt"
+ "9KOhCFzbVXpsIjKO1ekVpSlJIpU7wZQXD3gE4OrxGrNjM+AmD4K5yeGYjhLcohYc5kDXdaXP"
+ "TQ4hhRKsAwSizs3cZSCaAkSEFhEGlU4AqH2EFDhIH+KmdAsCtQfuaOdoF3un+7ivPPQHA/C7"
+ "Pcuew3M8HKdTfi0QT1OCGawvmHV3Neq62ExuIJ3LtBf0sWvbssE5/zyIGkw+AEjEEgCA+ck5"
+ "P55urSfXvp0xA0E5sh/RgMtj/Z7WGjVU3p6VXrVexdNrGUI2VBn3lqEZWIwtoOfnI+ryZSkL"
+ "pkH7suNoKPrjGMJWGDr+SEPwEPwfwCxfyUPI+q9Ciy9FvAPrC5AiX0iARwAAAABJRU5ErkJg"
+ "gg==")
+
+#----------------------------------------------------------------------
+TreePanel = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAIAAABL1vtsAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDS0dMgV9ZQAAAGxJREFUOMtjnHdhvoSABAO54MHbByzywvKKogpkG/Hv"
+ "/18mBorBqBGjRowaMaSN+P3vDyMjExzhMYIFlwQrE8v///+IcQWKEYwMjMjc/wz/0VTDFSBL"
+ "seDXgwawKmB5+O7hjz/fyQ7Lx++eAACyLh8pK2aCxwAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeRadioBox = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDgoZ7eu1QAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABtElEQVQoz4WQz2sTQRiGn5lsQhvUNkmLERvRQ38c9FQvVtGb/hXiXf9OBT2p"
+ "VFBiUgxIye5mm81md2Z3Zmc8RKNUwef2vfA+vHxirMeePwiLkPffP1DVFUWlUEahK8VGa5MX"
+ "x8+5jLwcDOMh9wfH7G3fpH/tOjtXemy1t5hlM86X538JgsuBtiXaalK9IFUpqUqZZQlpnmKc"
+ "+b9A/ZydqpQwiwjnIa2gxcnBA6ZZSFIkOO9w3tHZ7BBERcQ4OcM6g6ktw+lXOu1tvsUTkuUF"
+ "pdE8PDzh2f5TcpOvy847PkdfCE6nn7jXv0uUxyhTIBCMojFxNkOXGmN/z659jfce6yzWWZx3"
+ "BKUpcd6RV0vyqmDQ2+Pj5BRdKm7tDqi9oymbeDzOO0xt0FbjWYkCbTXaarJyybyYk+QJO1d7"
+ "mLbh1aOXALyevKGsS5RRWGfxeASCQDYI4ixmoTOmiykX+ZzKVhhrcN6tpwshKG2JdXZ1I5BC"
+ "0my0CPKyIFyGxNlsVa4NdV3TDJprwdHuIaNkhBQSgUAISUM2uNO5TXDQ3+ft6B2/fuGcQ0rJ"
+ "k6PHa0F3o0v3Rpd/8QPZ/Bl4qenM9gAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeRadioButton = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDDYJgCsItQAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAAB50lEQVQ4y6WTzW8SURTFfw8Gi6mdptAE0cIYbJHUrxAjxUx0Af4NmujGj/+s"
+ "O43pyo+VLtRJLDERFkJrIgo0Qg1gHBJkaGeeCzOlU5CYeHfv5p2Te+45V1QHVcl/lHK0IZFY"
+ "toXt2AAIIVB8Cn6h4Be+6QRDZ0h/r0/xW4lq+wudXgeBIDwXIhlZIbOUIeALeAiEK8GyLdr9"
+ "Ns8+vmD+uMqNs9fR5jUAaj9rvP78BnNgcjt9C/WY6iWQSEzL5ElpgwunzpNP5CbqfVl9RblZ"
+ "5v7Ve14Jlm1R/l4hfCJEPpFj39nHqBt87dYAOBPS0OM6+USOptmk2CqSjqaRUuIDsB2bSmuL"
+ "rLYGgFE3WA4vc3Mlz2DPYmv3E0bdACCrrVHcKSEQABystdvrElNjfzR362Pju72YGqP5o4UQ"
+ "YiTBfRyup+XnU/33TKD4FMJzIRpmAwAtFB8DuL2G2SC6EEUiRwR+oXDp9EXe1TYB0OM6qUiS"
+ "YGCGYGCGVCSJHtcB2KwVSC9dRkrpzYEtHdbfr7MaXZ1qY6VV4WHmwSiph2/BHJo8+vAYNTgh"
+ "SNW39H6Z3L1yh9nALI50xgncSQo7BbZ3t2mbHQAW1UVSJ89xLZZFIA7AEwlcVwTC446U0gP8"
+ "6zW6nyUS/uHQfwM6BdufWiyrrgAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeRoot = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDgoZ7eu1QAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABtElEQVQoz4WQz2sTQRiGn5lsQhvUNkmLERvRQ38c9FQvVtGb/hXiXf9OBT2p"
+ "VFBiUgxIye5mm81md2Z3Zmc8RKNUwef2vfA+vHxirMeePwiLkPffP1DVFUWlUEahK8VGa5MX"
+ "x8+5jLwcDOMh9wfH7G3fpH/tOjtXemy1t5hlM86X538JgsuBtiXaalK9IFUpqUqZZQlpnmKc"
+ "+b9A/ZydqpQwiwjnIa2gxcnBA6ZZSFIkOO9w3tHZ7BBERcQ4OcM6g6ktw+lXOu1tvsUTkuUF"
+ "pdE8PDzh2f5TcpOvy847PkdfCE6nn7jXv0uUxyhTIBCMojFxNkOXGmN/z659jfce6yzWWZx3"
+ "BKUpcd6RV0vyqmDQ2+Pj5BRdKm7tDqi9oymbeDzOO0xt0FbjWYkCbTXaarJyybyYk+QJO1d7"
+ "mLbh1aOXALyevKGsS5RRWGfxeASCQDYI4ixmoTOmiykX+ZzKVhhrcN6tpwshKG2JdXZ1I5BC"
+ "0my0CPKyIFyGxNlsVa4NdV3TDJprwdHuIaNkhBQSgUAISUM2uNO5TXDQ3+ft6B2/fuGcQ0rJ"
+ "k6PHa0F3o0v3Rpd/8QPZ/Bl4qenM9gAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeScrollBar = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAICAYAAAD9aA/QAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDQEAaDJ6EgAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABeUlEQVQoz22SwWpTQRSGv7l3TIlgIriI1Aoqgi4K6tqK+ASCvoHgi/hQca3o"
+ "IkpX6s42tWmKKEkarZ17Z+ac4+LaVJqc1fB/Z37OP3Ncf9S3w/l3Lvo252v865DrlzdYVaOj"
+ "Aza6yyzkE652evjJyYQntx/jKJaatkfbbN16uNL43e77lUxNebP7lgJ1RInUUjGrZuzPv1FL"
+ "RS0VhqGmDKdDvk52ABhOh6gphiEmiAn9j68ZzQ4QEwzDO0+hKGLCcTxmsD+gSvXigpkhKkRJ"
+ "RKkxM6IkRBumqqgqnz994cWrl4yPxo1misea8dUU5xwOh5o2sdCzsxmGLeL+z8wM/qU71fxp"
+ "w5pf48G1+6jamZkqSRNlUSImZM2URUnStJgM4O7mHZ4/fUbvUm9h7rNmQgo45wBolReocgVA"
+ "0kTIgW67A8C8ntNtdwg5NEwCAI/ubTUbIaF5Lo349c46g70PtHxr6Yenf2ZEiSu34sfvn2TN"
+ "S3qVa25eucFfTP0TLifzTpkAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeSeparator = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAACCAYAAABc8yy2AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDTYU4u8OWwAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAAAF0lEQVQI12Nce3/tfwYaAMYXf1/QxGAAfsIHBx4nJ1QAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeSizerFlexGrid = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wsXDgwjfb3LdAAAAD9JREFUOMtjFBAQYPig8+E/A5mABcYQuCLAiCzxQefD"
+ "f3QxdPBB58N/JgYKwcAbwDgaiKMGDIqExCggIECRCwBFqxoCQOm6JQAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeSizerGrid = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wsXDgw2EGAvnwAAADZJREFUOMtjFBAQYPig8+E/A5mABcYQuCLAiE3BB50P"
+ "//HJMTFQCEYNYGBgHI3G0WiEGUAJAABQ2RoC2hMJYQAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeSizerGridBag = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78"
+ "AAAAB3RJTUUH1wsXDg0IyBoDdQAAAEtJREFUOMtjFBAQYPig8+E/A5mABcYQuCLAiCwREBLA"
+ "sGHNBryaP+h8+M/EQCEYeAMYaRaIH3Q+/EcXG6aBOGoAFRISo4CAAEUuAACOExkCdACh7AAA"
+ "AABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeSizerH = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wsXDg0Y1a0TEQAAAEVJREFUOMtjFBAQYKAEMDFQCCg2gIWBgYHhg86H/xQZ"
+ "wMDAwCBwRYARm4IPOh/+45Mb+DAYNYAKBjAKCAhQlJAYh35mAgBtQQ7IJHdgMwAAAABJRU5E"
+ "rkJggg==")
+
+#----------------------------------------------------------------------
+TreeSizerV = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wsXDg0ljcVfAAAAADlJREFUOMtjFBAQYEAGH3Q+/GcgAASuCDDC2CyEFKAD"
+ "dAuYGCgEowbgiAVionI0GodVNDKiZ2dSAQDuMhKd7SieJQAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeSlider = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAICAYAAAD9aA/QAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDiEeBf/digAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABeUlEQVQoz42Sz2tTQRSFv5l5816TxXuWxloXuhCrdVNQzLL/hP7L4jJSdKdk"
+ "YWKQgjGk5v2auXdchCatUPDu7rmHj8Phmmk7Tdya76sZV9dX/O9453lxfMogG9zRs9vLYr1g"
+ "EzaMn75l2Sw5PDi8F7hsloyGI+pQM/kxYfxkjLd+D57MP+2W2WrG+/N3OOvw1mONBaCXnqiR"
+ "siipQ03u8q3HeSpX4W3O5eKSgR/uwR+mHzmpjgG47v5gjEGTIknoNQCQAIyhk54E9BqIGtGk"
+ "3BhqadCtk/nvOdlBllMOSgCCBEQFAE1KLx0AhSsIKmgSrDF00hE17r0omc3wdtusNZbs4tnF"
+ "Lr5GpZceZx2SlCDbxKJCG1tsYQkS0KREFSTtQ1RFuavi/PEDslcnZztwNSz5/PMLp6PntKGl"
+ "M1t96IeklFi3a7zz1KGmCS2bvqaJDa20vHn4msIVO5b5992+/vrGfDUnaiSz2b1fcXPPXc7Z"
+ "o5ccDY7u3P8CCPa93kLRoaQAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeSpacer = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78"
+ "AAAAB3RJTUUH1wsXDwYJXSuAHwAAAG5JREFUOMvtk7ENgDAMBM+IAX6QDEPBmBQZJoN4g1Bg"
+ "kEBQQCgouOblL6z3SzZJePIKGHBbexZMRYQJYMM4kKe8zWfqya0Lo/KM2h0236U9gUWJPGUt"
+ "sapod4YnJ4q9xJN/oIM/wQsJrPUbTRItzCrJLwrVI82eAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+TreeSpinButton = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAQCAYAAAArij59AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDhkmOmLZ7wAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABBklEQVQoz22Rz0oCcRSFvxl/YwpjVgS5GRF7hAiindBTiBC9Sz1A+AARRO9Q"
+ "BG16CFu4NSVX/llM+LunxYyJTvfu7v3gnHNvcPtxp/bxKYUKRLVcxSWHCZfti8LezHj5fMUJ"
+ "WJkHtAVIAoEDYTJMnoe3RwBurq4JCBDC5ThP78/c9/sARKWIXqcLkAFC9Drdv+F6lktketr1"
+ "kLfLwCKwLifE12yMye8eYmOyUTv5V2IwGWxMjmYj5ukCgNpeTGO/AUC4Nlmv1BnPJ3wvpzQP"
+ "moSEGwkhKlGF8+SMuBzj5fHyWUzllxQiKkWkPt2OaTKWP0sMK/zCMNxwOmSRzncSBoRhSOuo"
+ "xS+qlIjuQyw/7wAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeSpinCtrl = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAYAAAAS7Y8mAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDQMVN9n8ewAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABmUlEQVQ4y6WUTUsbURSGn7m5TkRNo6LiQkahKaXi0orob9CVSPEnCF22KriW"
+ "rqQ/oKsuxG0hmxYVsuiqVAy4UAkaVNQqCdQZdPIx97gRjUwWk+S93M058JyXwznHSp+m5cr9"
+ "h7JiNKLz4hmpvjehuKXA1jb62rtm9t0MjWrnaIfp19MEEoRyPw9/oUHRrAIJqJpq2LWoFqiA"
+ "iGCM4W9+l0/flqmYKsYYQNCtgvPFPIurHylcFkh2vWJlfukl2IhhI7OJbdvMT81Fhju9Dr+/"
+ "Z56LIQg1Dd7IbDLsOKBh62A7mmMEkTq/Fpzdz/LeGWfy7QR7f7LRwXUeUtOKREeC29Itbskj"
+ "2Z+MBHZ9l8JdoW7uCbww+4H1H1/xSz7Lc58jgRPxBLa2Q/HcTe4ZnOpL8WVhrbGpQHDLLhf/"
+ "LwGI6zjDPQ4itD7HnW2d3FfuOCmeMNIzgrIUUtuKpuEIY4NjjA6MElOKclBufUEMBiPm8fhY"
+ "+FX/qZgG0zTYr/h4Fa/uDbHSp2nxfA+tGjOfuzmmvS08ESoWY6h7iAfDaL5HCRgjkAAAAABJ"
+ "RU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeSplitterWindow = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAIAAABL1vtsAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDiYubGd74QAAAfFJREFUOMvdlEtvEzEQx21nN2ojoHk0IoiGtqr6ONBT"
+ "uVAQ3OBTIO7wneCTwA0kOBVUKlBIadKiKPtqNptdv8ZjDgEURZtKCTf+N3tmfv7bHg19dfS6"
+ "UW6QRXUWnjnrtfXN+sbCCLSGkX/Wf4Nwcne9zDv6+UkZlSnONReKLxWXnx88m8NFK2jdax6s"
+ "lW83btxcvVZbKa2ESdgb9eZwIUAKELEYxjyOeRwmUZzGGvUcCK441zzmsZf43sArOsXDnfv9"
+ "xIuyCC2ixcpyZauyNY3wM/80+gGotYFW/3ulVO4E3Wh0KbV4sHv4dPtJqtNxPVr86n/LQRz3"
+ "v+w37vppwHVGCW37p0ESCik0/PZvrLHWAgIgoMWci0gt0WKqRqnKmrW1z91jIfmdetNYdJlr"
+ "iUWL2mgBwhILCDkIAUKASORokA2iNFq9XtMl/fLhC0LIu+57aSTXHBAssZRQhxVyEEESDEXS"
+ "H/Yv04ECpUH/dUsplSDHJ1NCGWVuoZiDSGXmjbwgCRUobbQxxnXccWivvtuO2owySiilrMAK"
+ "m5WNHMROY/tD++P4RRCRMfZ479E4VF2qVm9VZzU4fXP+NndeaITihFs78QWTOumdOLPYLnNm"
+ "lV3VnZTQyaUldtrzn4TJkHN1zZRyE5xO1BHAFx4W59HFL52bPckdnR6/AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+TreeStaticBitmap = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAA4AAAASCAYAAABrXO8xAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDhwKdc1BSQAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAACsUlEQVQ4y2WTy49URRTGf/W4t4e2u8f00E0UZZgHCAECwWAiJsYHklE0UWNM"
+ "YAEJceGCsCNhR/gzSFy4IERhCSqJRCTIZgSJCS6E7llglBnnAZluw517q85hcRlH8CS1q993"
+ "qr7zHTOVTamiAIgqiqIqPF3GWAwGawwAfhmKKgQp+OrmWfpZn6zISFxC6lOiRN7f+h5rG2sB"
+ "V4LL0Ex/mtOTZ/hox4e0a61STCJBAlnIuHDrW0ZWr2fPhrdxxmNFlSw85PTkGT7bfZjnG8+R"
+ "upTEJiQuwVtPxVf4YNs+phdnuP7nDUQjVjTy9c1zfLLzYyq+QmITKm6A1KU443DWYY3FGssb"
+ "46/z0+1rKIoFyIqM5qrm489bvHVY4zCPjfhvDdWHuD13pwRDDIgKokLUSC/vEaRAVFDVlYMy"
+ "1hqlM9cpQW8dUUsjFpcWudz5kQfZA6JEugtdpnvTKyIoSyEvxyGqRIkAqCpRI1e6V2k+8yy9"
+ "rE+73qYx0CCqMNubY2RofdlRUQopKGKBotQqNTa2xzHGUh+o0661CBKIErk7f5eta7ZgDYa9"
+ "m9/h0u8/UMSCPOZU0yrNapOx5igDvgJAkMj9hwsMVht467HWOEabI0QJdOa75CEnSiAPOYUU"
+ "BIkUMZCHJS79dpkDO/djjSufao3j0K6D3JnpcOOPX8qLsSCPBUECs//Mcv7Xbzj82iESl2Aw"
+ "mG7WVVFFNCIqnDh/ksQnvLt9glpa47tbF7l6/RpfHv2CRqVRzhdTZrVMvENRhtvDDA+tY3Lq"
+ "ZxRlfM0Y+rJST+v/QtYYvMGwvCHWOF5svsBSyHlr05t46wkSmOvP46zHGVuu2HLHUgVE4ZV1"
+ "u/j81BE2jW1ksDrIX/P32Lt9zxMQUJqzAhta1RbHPz3G3wuzXLzyPbs3v8rESxP/y+wjHwdM"
+ "yMvIwOAAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeStaticBox = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAIAAABL1vtsAAAAAXNSR0IArs4c6QAAAAlwSFlz"
+ "AAANEgAADToB6N2Z3gAAAAd0SU1FB9sLHg8XC+o2TdIAAACnSURBVDjLY7z34x4DZYCJgWJA"
+ "VSOqN9XCGXA2sjgBI6o31bb6NcNVw9kQcfxGsBy4cdBBwx7NNkybb7y4iVX/g7cPWOSF5dFs"
+ "RgMQh2hIqGM14t//v4x7H+9TFFUgOyyvPb822CJ11Ijhb8Tvf38YGZngCF82wyXBysTy//8/"
+ "YlyBYgQjAyMy9z/DfzTVcAXIUiz49aABrApYHr57+OPPd7LD8vG7JwCKb0Uo5BCtBwAAAABJ"
+ "RU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeStaticBoxSizerH = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wsXDg4M5FqUrwAAAFJJREFUOMtjFBAQYKAEMKELfND58J9sAz7ofPgvcEWA"
+ "kRRDWJA1oruAGINY0AWQXQBjwwzH5l0mdM3INFmBSHEsjBpAOmAUEBAgOfliGDC0wwAA8pIl"
+ "0wUY404AAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeStaticBoxSizerV = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wsXDg4eF+Pl5wAAAFRJREFUOMtjFBAQYMAFPuh8+C9wRYCRAQ9gIqT5g86H"
+ "/yQZgKwBnQ3DRLmAgYGBAdn5AlcEGLF5h4mQZrLDgFgwDAxgwZUGKDIAX8iTlA5GY4E4AABb"
+ "Fil3I9jn1wAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeStaticLine = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAACCAYAAABc8yy2AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDTYHZlFPhQAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAAAF0lEQVQI12Nce3/tfwYaAMYXf1/QxGAAfsIHBx4nJ1QAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeStaticText = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAICAYAAAD9aA/QAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDTsNMyrY1gAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAACAUlEQVQoz42QW0iTcRjGfxv/LxTL0oJBBFGODhdWFIWyrorUm6ItS2jpYlkZ"
+ "i0CoG4luUjPXASQ7iKUJCYElo9bhomarLMhsbjhP7cOg1tRAdKO21P27WH3QnT944YHnfR8e"
+ "Xp0aVyV/qX5ey536VgB63O/JTssGoC/Sh9m6n30OC05LHfNB/0+EJkO0NrRpxsD4oKb7I0EA"
+ "jMtzmC9a8I2XTSR/J7FWHgTg80RIWxr5ntKRyTG2nsxnfUkut941af5UYorzz2rYXLGNnKK1"
+ "5FVuTwV/+NbDw+udHHAUU5C7E4DR8S/aoX84AEDsZ5RTdgdSwsVzlwjHwiTmEtgaj9By+S4W"
+ "814u1NdQtKsAAdDgvgZCx54tu0kXaQCoX1UAZpIzBDwBstZkUWuuRtErvCjswtvuZSI2wevQ"
+ "G/xuP7bTpZwtrEo12QDCPfSEt/e7ATh02Ka1/OjthaMw+GOI2egs+SV5KHqFxFyCT90+xCKB"
+ "cakRl+8RAKsNq/77sXC2XUFkKlytc6LoFQAaXTcJPA0QjoUJRgYA8LhfcW9dO70hH9HRaSqq"
+ "jpGhZGBYYgCguaMFoRdMx6NsWrERMAlp67RLNa5qY+0ok5iEbA7elnZXucQkpN1VLheXLZNp"
+ "5oXy+OMTcvjXiFTjquyP9cvSBzaZXpwpdTsWyJVnjNIz5pF/AHm51hdHwnK2AAAAAElFTkSu"
+ "QmCC")
+
+#----------------------------------------------------------------------
+TreeTextCtrl = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAYAAAAS7Y8mAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDQIL1M3wWQAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAAAYElEQVQ4y+3MoRWAMAwFwJ82AkEtzMAwMG00TIKpgloqENBgGCE8TG+AI4mi"
+ "27HDkYcF1YI+dOCUE6ZhhKV5XeAAB2tM/oP1VeMa1/inuJinl94giaL5zGDHNmm50DYBD+9q"
+ "HJo8ucgXAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+TreeToggleButton = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAYAAAAS7Y8mAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDhgkzXeJggAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAAA80lEQVQ4y9XSvUoDYRCF4Xdnxywp1kWxW+ETK9Nkg3gTdgqCjT83JN6AP4Vg"
+ "IYIoFhZego0bJLFLhKhFUMEizW6+tbfQwknhaWd4OAwTXPavqt5bj7H3WERDZWHWof33J7K0"
+ "iYhglc5rFy3HJSJCGIRmsPceu5rfMjFYfxred3Pyxza+9IgK2VKTViP7e+NWI2N3fZvh55Cd"
+ "tS3iuZiT61MGH892pyh8wdntOZurGxzeHNvBo2LEdBkTaUStqNnBSZRQd3UOLo6YX0x/3Q/2"
+ "7varFbds+sf5oP0P/3hy8JSqPRoK6mYcDy8dqCoTNJCANEn5Am64QzC1J/rQAAAAAElFTkSu"
+ "QmCC")
+
+#----------------------------------------------------------------------
+TreeTool = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAAsAAAAJCAYAAADkZNYtAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDRwXFI2TyQAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABPElEQVQY0z3QUUrjQACA4T+dSdMmCK6NiqmKstYK+moF8UHxBOJZ9Gh7lFUR"
+ "DS6UZWts09pMQiYzs0/6HeHzntWzq3TF0/sToR9xuDFAG01WZLwvM062jpEtCYB39+vehX7E"
+ "fn+Pl/Er1lq8NoStECdgPYhJegkOiwx0h+vTKxrT0P+RoE1DbWq00SzKBb//PPDxOeX1X4r0"
+ "e5K8nFPUBc5ZfOHT9UOidkgc9UhWE8bTMZ4AaZwhL3NKXXK0McQBZa1QusRYg3WGt+yNy4NL"
+ "ZCADZmpGHMXMqwXGNhhnsc7Q2AZVlyyXBbvxDjJfzrHOcbD+E1UrGttQG02lK3I15yF95GJ4"
+ "jvAEUgpBt92lqBUzNeXlb0qWZwSiTX9lm9vRDcPNQwCksJLJZEI6SVlrrXE2GDGIB3T84Pv3"
+ "y38ceKGMmSSP8gAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeToolBar = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAJCAYAAAA2NNx1AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDRstncDcvAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAACS0lEQVQoz1WSzW4TZxiFn/HMeDweUUHiJopT00AJCbRSs0i7KJUIYoGQYAHc"
+ "TgT3AZvS3EQr0bQLftQVqio5RmmwSJVWVSaJnXpm7O/nfVkQkDjS2RwdHZ3FE2yX2zq2Y17t"
+ "v6IZZ1ycWcR6S17k7I9yvpr7kqgW8V7rGw/o/tXlXGuBLMlOUkUBL57Xwz63r9wievjbI5px"
+ "xrn5Bf7o/8mz3nOCOjRrTTSE/DCnPd1GES7PXaYYF6xdv8q9lbucPd1BVXHicOpw4vjh9x/5"
+ "6cXPRIltcP2bazjvmD/TxnqH8QbrLcfVMd3dLQ7+P+T1f33O3zqPqDL7ySztU3MkYYITh6KI"
+ "CLWgRhxG6ESJ4umIQTWkMAWqQhzGpHGTrN6klU3TPt1m73CPIIQ0TlFVakGAIFixWLHvHn+w"
+ "R0SIvHoG1YDKVizPLKFAZUpKW+HFI+p5k79h7cIaAOI9xluMM9SCEHcy7NXjxGGdRVSIkijh"
+ "qDyilbUYjo/x4vAqyEmxNBWjUcHZVudkWKhMyebOr5STkuHoGCcOEUEDoZyU7x4PRkNElQuf"
+ "fkFpSpw4jLeM7ZhBOWSr3+P7pe8IgxAAZz0Ta9gf5VyaWWbX7bL6+SoH5QGPn26QNlK8eqIo"
+ "DEnrKYUpOSoP2fm3Tz7IScI686c+4963d1iavfgBt5tXbvDyn5d02h2cOrp7W1zqLJM0Ehpx"
+ "AxFBVAnWn9xXYwwFBVO1KVYWv2axtUgjTj7i971EhV+6mzzpbZLVMyJCwlrI2Ezo/d0jzVJS"
+ "Ut4Cv35XCWG/LuAAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+TreeTreeCtrl = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDgoZ7eu1QAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJ"
+ "TVDvZCVuAAABtElEQVQoz4WQz2sTQRiGn5lsQhvUNkmLERvRQ38c9FQvVtGb/hXiXf9OBT2p"
+ "VFBiUgxIye5mm81md2Z3Zmc8RKNUwef2vfA+vHxirMeePwiLkPffP1DVFUWlUEahK8VGa5MX"
+ "x8+5jLwcDOMh9wfH7G3fpH/tOjtXemy1t5hlM86X538JgsuBtiXaalK9IFUpqUqZZQlpnmKc"
+ "+b9A/ZydqpQwiwjnIa2gxcnBA6ZZSFIkOO9w3tHZ7BBERcQ4OcM6g6ktw+lXOu1tvsUTkuUF"
+ "pdE8PDzh2f5TcpOvy847PkdfCE6nn7jXv0uUxyhTIBCMojFxNkOXGmN/z659jfce6yzWWZx3"
+ "BKUpcd6RV0vyqmDQ2+Pj5BRdKm7tDqi9oymbeDzOO0xt0FbjWYkCbTXaarJyybyYk+QJO1d7"
+ "mLbh1aOXALyevKGsS5RRWGfxeASCQDYI4ixmoTOmiykX+ZzKVhhrcN6tpwshKG2JdXZ1I5BC"
+ "0my0CPKyIFyGxNlsVa4NdV3TDJprwdHuIaNkhBQSgUAISUM2uNO5TXDQ3+ft6B2/fuGcQ0rJ"
+ "k6PHa0F3o0v3Rpd/8QPZ/Bl4qenM9gAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+TreeWizard = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAIAAABL1vtsAAAACXBIWXMAAA0SAAANOgHo3Zne"
+ "AAAAB3RJTUUH1wsXDwEvwGeTJQAAAqNJREFUOMudk0tPU1EQx+ece24LxT6gb2xpMSqPgisJ"
+ "JBoSH1E/AIJK3Lg00Y36BUB8xLXRjbhRF8bgiw0LXfhIBBSJoERQ6StcbHtb+6Dt7T33HBck"
+ "xGADlMmsZia//P8zGfQq8npk6mmVvkrVVNhalKgKnAMA59C7v0eo7jY4bA6MsbHGaDXVlbjq"
+ "sjhNNSZEcLW+CgRkNBh1OhERTERCRMIRs5mt9dZ6m9lGgb77/p4AgkwhncuvxFOJxp1+AN5Y"
+ "65cyv+21djkvd/pasoWsnJcNOoOcT9oM1lnpq0JLXd5OKbscksMcAWacIYQ7/B2+uganyakx"
+ "lilkBcDBRAhzHE/H5VwyU8gWS8VEOkE1CgCU0qno56W0pGoq44xoTOOcx1ZiXpc3+ida0koT"
+ "kUnOOUZYykmr5hEgDhwhFMvGFKqoVJ0pzAIAQkjVVDQ8fd9lccF2IygHic/qa7T7t41gXMNl"
+ "G6li6uXEaGwlzjijjG5MKY/QC/rbD+/cezOMEX4xPXr+7oUNEKRsVcBCg62hzRsYfD5k1pt3"
+ "6GoqQyiaMj4/7va4A55Au6ctmopykVWGePD20bw0f/jAoUwxQzBhwBbDIQCgGiUC2XwXX5Zm"
+ "EssJnUH/YXI8kook80lFU1qbmo9cPj7y8ZlClc1V7Ktvbz3ZomhK37V+i8NCNTofXggHIyc6"
+ "jvV29mzVCBGIIAjdXQe/heZ+zi06/HaRiFf6LlV2VATIX+vvP3r6+sXBjJw2u819t85UdlQA"
+ "WJPdtjvwQ/qVTqQrUwEAKqMIYYTwzbM3VKXk2eV5PPGEA68AIWLCOVvNq+cGcvnc2KexhdjC"
+ "JggE6N9cqzc7m/a69+SLhSVJWtdav4uyOgFAFMShUwMAwDn/f4aEkqEiLWz72SPJ6F8fukGl"
+ "454ftwAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+Undo = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH1gcaCjgAnz8HVAAAA4BJREFUOMutlF9oW1Uc"
+ "x7/n/slNe5u0qY3NXeyfdOlcdT7MlyJbhdWiosiK+jKRMcqEPu1R8UVBpj6Kij44KKEvGxOh"
+ "ogzELVtjdOZh08kE3azapH+SdclC/t7knnuOD55bLlkaoXjgx7333B+f8z3f3+8coMO4dG7s"
+ "ZDIGjl0MaacfSwtDRzTzzzPY5ZB2gg5Imfjks8/gfwNvQ2fGAXtt12BlJ6jFR6Aq3QB+RTIG"
+ "3rBww7TwU4OR89c31MTp95rVTmC5HZTTVcDzOAih2DOqIzwWRjBshPr8cqWYL+195EH7xfCE"
+ "+kMiyUodwRcWRw4FkF6enBlH3RqD5D0IAOBQAckApAEo2h7oPWx4dN/Dj6oa3T/A7z0ZnlCv"
+ "JZJssy340tm9x3X611eTM+OoWSOQiAJZ0VwpNqxmGY16Dpn0VXB4ofv9xB8cDnuraXv0gHol"
+ "kWRWK5gAwJcLQ0ceEDaYNArAAogXtcoG8lu/3F8YBRh86Glc//7Hn+vlQuq5ecy3Bbd6nLvT"
+ "RKm0jvFoBJBDAADTrKNaycKsFEAUAk/XEBrWfqxcW7r51Ek8tmNXzM5lLi8tDE1fjW/Gn5g2"
+ "UBM1T33z3XZyifcgZAzz3r51gkYJeg8FPMFRYKtzH8/OZS4XaGA6dfE2IpHI9vzhEyCHT4AU"
+ "yt5jxfzdrXp1kNvUBocFi8k9NHfUoLmjRscDMjuXubJWN55PXbwNKGPuPOnVU3fPZwvktfX1"
+ "IrSuXk6tPGe2Ccq8oMz7nydRBqAufhR6IRkDF5eQxxXqt7FAMf/7AfuPVIhe+MzH3bVqVUwc"
+ "VcJ3z/FT2fjN3OBL4r8brMmEQ5LUZqnc3bTtxqYQI7UrngNWRZICQJp/I7cMYACA162qzrQs"
+ "UXSjnP9NsihZFQtSEcwBkzaKFZcK550AIGdO9876fCTUpOrG2iYLVouNcwC6AdQFlAPgSktP"
+ "ty6iunYh+3xQovv0NyPRWvaLz5fVOzn+7tsf4msA2r+nCpYDl1ugkvtiEnMyABKNSvriB4FP"
+ "An1mOb5csTdW2VvvfIqE2L4DdazgpMVjxeWxrKpQpg5pgamDsuHXWb9XsyeqNSq9/j6PiS3b"
+ "IpoiqPhmjsd45ZiHdHVxj2kq5NYtxmybEXDYL09Zen8/C66krfTfK7jx8VncE1AIdcy1gOPx"
+ "ff1H2nhNWu4V58ldwdyFA4B/ANW9dTHXQUUsAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Icon = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABOVJ"
+ "REFUWIWllmtsU2UYx3/n0na9nLbboLvgLt2F4RxCDEgmJIoxaDRigiwIJn7VqAkJMTFRPxpi"
+ "CDF+wEQTEmOIMUgEIsgHox/Q6GCMyyAhJDA3xmDretu605527TmvHxYqZd3Wdk9yPpzL8///"
+ "3ue87/O+SLLCctfR748JSVY4dfac+Hvgshi4OiRKySvpkmSFYvHH+T+FpmkAaLLAUbMaNyZx"
+ "Q8chZIYnw7z0wvNS0eQyQgU49uNxEQwG8apgU1WqqqowZDseyWQmJ0jGwtx+MIWu60QiYTrb"
+ "mlAdnpV6/w+wvrsDn8PJnbM/E54I0bp7D6HQJJLq4sqVqzQ01KO5bKiqiqIoxBNpFGVugdi5"
+ "334XbS31xBJpntu8Sfrh+Anx9p6+JaukAuiGyZyZ4fbQEPcGLxFb1YjhcBF/MEZjRxdpI03a"
+ "SOeTQpOTSPJC3YDbQbXTg9NTS2hsVETTOQBO/nJG7Nr5elEQSZIVTp0+IexOPyMj/y74IBSa"
+ "YmL0Lke/O7rkSD7/4pDY/uJ2XE4XfpvE7VCCC4NDjM1k2LGxia516/DKguC6bun02V+FkU6z"
+ "d/ebUn4SHvnmW/Go4IfvvZs37KqpFq11Dbj9Gif7LxYFOXjosOjt7cWyTCzL4vyFG1y6Oc6G"
+ "jtVs29yD01mFrus01fgIBALzcyuZXHwVPB4bV/lFY0MT527cWLQSXx35Wrjdbnw+H6mUQSwa"
+ "paGpjejEHaaiswRsMs0bnqGn5yncmKRSqdIBAHqfqBeramo4c/3mssvv/bf2Cq22msb2Lqrr"
+ "67DZbciShMej4a/243K6GB8fLw+g3esRwZpa7Jp30Urs3LxJaAhSCZ3QzDT/TIakTz46IDyB"
+ "RrxeDbvdjs/nQ9O8jI6OzK+CUmM4oUsuRRJtLuei33glmJyKEEkaXAtPSQAHD39ZAPvxp5+J"
+ "xtrV7D+wXyqrAgB1LqdY6/fz14OJBRXo27heROPTRHSD69FISV2ybACAbp9fdK6px6H5+Oni"
+ "RWnf1q0CXedeeIqZTLZk84oBmt120eKrpTPYiixLpBJJ7kcjhGeT3JyZLmt/KGsOPAwjJzGT"
+ "ThKPxKiSBNFkmnA6TTSbKVtLrgQgnMlIyZxFZDbB3FwWw8ySmcsQShll744VAQA4JBU9m8ay"
+ "2cmZJsMJvaKtuWIAI5dGtSRExkCSKj8WVAzgVKtI5ixSJihyxTKVAwAoioKqWNhWILMiANM0"
+ "mZ0zVyKxMgCbKtDsCmkrV7FGyX1gYLBfRGJJAJx2wQdv9GEJlWxOWtEcKKkTDgz2i472joJn"
+ "21o7sakCv9ODYoHZWM+ufe+wtrsdgGCwdYFOLBYnkUjwysuv5ZfNshUoZp6dna+ELMvYkTGx"
+ "sCwr/37Lli0AjIxNEgqFUJg/wGZyMplYtEBrSYBi5gA2zQ1AzpSxqQLdyGKXZVzVvrw5QLC5"
+ "nmBzfQH45VuFlkUBBgb7BUAx84dCANPZLHV4UBUFj8dDW1vbUuMhbui8uuOlgq61AGCxURck"
+ "eVzs6NsNgGbliKYydG9YT0+wedGc2VSOK0O3FjwvmISlmD8MIQQ5PZX/HcvF+PAIT296dkHP"
+ "zgM8ai6EWFF/fzwikQhrO58sKpj/BUPXhojH4kUFAg0tBfdOuyh8H6hbEmAxc6jwRLRU3L0/"
+ "UUDXsqZhyVL+B0Qv7WbNxR4hAAAAAElFTkSuQmCC")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/images_32x32.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/images_32x32.py
new file mode 100644
index 0000000..9d47405
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/images_32x32.py
@@ -0,0 +1,498 @@
+#----------------------------------------------------------------------
+# This file was generated by encode_bitmaps.py
+#
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+AutoRefresh = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "AAAAB3RJTUUH1wsUDC8JCZ4OQwAAB4tJREFUWMPFl21wVFcZx//nnHvv7t7dbEgIJCWFEBJS"
+ "QlScamVax84ICNaUt8JUQFPQ0aKOM8z4ob6g4yc7fnA6Y3V0fEFIEetQA5YKlFZo8YWK1I4U"
+ "wnvYbEKahIRs9vW+nvP4IbvpsoQN/eSZOXPv3Tn3+f/Os//znHNZXV0d/p9Nu5dBn+tsWGyK"
+ "0CZAa5fw5/vSq+BM+IwxSwPv8eH+U0r5yq2g/Y9Tm4bccrHW7lmw4eVt17sKz6xcBlbvbWrT"
+ "EdxVreoWfei+pZHaynoR0SugawaU8uH4LtL2OEYyQ7JnpDs7gCskFN9lw37+yNZ4vDRee2fj"
+ "SgDHDm+NsWkBVnc2bQvyyM9Wzv18uKG6mQGAIglFBCIJCTURAAAHB2MClp/B1eFz3r8Txz0o"
+ "f59k3vde7oiNAsDjexZ8UhP6a55yzWkB1nU2PRHkkb1Ptu4wo4HKCWEogAg0CSJBRBNAUCAo"
+ "MHAY3IAkiXcHznhnxv5qg3nbFbGLgmt/X1G/IXK0/0UUA9zhgVW7Fs4E579bt3C7GQ1UAkRw"
+ "fRspOwVXWuBcQ9iIIGJEoaCglA+fPPiKQPCQ8xwwJrBk7lK9YWaT/vq1/b9N0k1z2ZyNVFsx"
+ "Z3oThgz11Y9EHg3URGajd/QyvdX7phrT+rggxogIAEBEipjw5umtTkttW2ReVRMPagYcacEj"
+ "Czk3DSuThqGZ+GzLJtP2LAT0AFNKTQ/AEXx6cd2DwcPv/lHG1QVAeIIxzbGVM6BL2nLwS7HT"
+ "ALD6xcbKa+47S2/c6P4K9aF9UcXDrKW2NcQFwfJzkFDIeUk4MotKowZD2Rjuj7TcAXCbB9b9"
+ "YoEpouZIa+gho9t6C9VUr2nQcFNdT7i6aD685dLYVIZdv7e+SsL8umDiux+NPhpsqW3Tks4t"
+ "5PzxvE8kAKCxcgl2X/gxHd4a4+9PuKjJCtZIUGZ39rRo0FvZjFDVmND4sGTUfTdxADjYMZA4"
+ "1HH1WYesB86Ov/nagcu7EdGqUROqBxGh8NcJzsHBndszXpwOpbgjLZjcvBUImid0I3jC9+RV"
+ "Jil+LwXrSEf8PSL6VwCGK4RA2k1BQk0u2RK5Oz3gki4F81Cj1x8NG+YFxljSM6PmzZzO7gVg"
+ "TWfj10zUfOexhU8aKWcElpcEg5qU5YyVB/CRiwvoyDnZk05ipEcTXiZjjTi+8jPTia/vXLhW"
+ "4+Zz7c1bQgE9gKAexsxQPRgAMAbBtYkMELu7CQFg1d6mucc6evo/yIayes/8ZYqx4/c6vmwh"
+ "0pTqW9O50JokJKn5jPSpAilDzT66OT7yyrbeE/mqXLY9/uuNAtp/5027Gz7ziedDE7WfACh4"
+ "0oOCAgfHULofXdd+nrKV+7Gjm+Mj5QS7Th8Mbli63p6cjPH2GsXYgWJYPuXMlEJvshu9yXPo"
+ "TXZjIHMFOS+JcXsUf+75VZakt/LItt5r5cTfGSQW1r15x8//qe59MS4LRawsQGkL61UQ0LD/"
+ "4i+VS9YXCtWwXNuHH7J++8qnIEXb6+deaurq6tJ0zVgLAJqN8gBU7FJwRI1qWH4ORMTBxOa1"
+ "extrpgPQz1+OZmXyEeJYzEm03ay59Gki2qIRAzQ3PQ2Auu1+MHMdjBG++OEdeKhy+ROcRM/a"
+ "3U07lu9pid4NQPq5VQbT2wT44pyb+vjf+l/aFxWzBOc8fbBjIFHWhAQFxgRqgnUYs4cgyUfG"
+ "SwBeAnNmNujRyEb92vDFZ/vdCz9a/0Jzl0PeCw4FzhzfdiXVcai5MqBmfzPr577dEH4gdWrg"
+ "WN3ZxBv1Jq+isGbqCUlvl60D7Z2N9K0Hn4OnbKTtFMLBCJL2KEatQSTdUUjlQxM6ItoMAMDA"
+ "eJ98L9OXTdNwQAgREBoHGAHEyJUSEaqU1YFaLRQ0EE9fTVte9huHnur9/bSH0oFkTB2I/YY3"
+ "6UusRxqXh4QQ4ACITRxQxuQgNCZQFZkhZlfMikoo5JwsHM+CTx4EE0wYHFL5moSPZC4Fx7Uz"
+ "owF7f7k6wABgONWHw7HO9M2ziVX23P8s6/e6f9Ba8bDeUDNfy/gp5NxxeOTBJxe2dMAKnmEA"
+ "N4AAaZBQ8KQDxhhs28awFbfSw85Tp54ZYnnvKQAQkUik2JCBxeuqv38pdTY71H1r8+mfjF2P"
+ "HUtdtp30X2R94r5Y9sr9JkVRHZ7FDS0IzjgUTZwIiQAFAiOCYhNbMANhLJ1UN5xY7lbM3n5y"
+ "58CpvA7LLzZV8AADYAAw2jsbU5kb9pdP7hx8o/BboTc8pi9oWlG3uaIqsGKGqFU15uxQKGgy"
+ "XdfBGIMiCc93kXMzSNkpOeoPWY7lnb90bHBn7wE7BsAt6U4BgOdFAst/Ovfp4zv6/wAgUAIw"
+ "+cxrvYrmz1QtqV0UXRqeGWgxDD5LCdKIkRCSZaRHg8lh52T81Nir/a/avQWxYuH81S5eBVOK"
+ "5btecq/n/SOK0wnAB+AVdbdMdwA4xSb0Sna0QlCZD+znXywIi5JCRvmxxeO9oveKoez89bZV"
+ "QHkqr+jl4tmWChfMxEqAVRmQgjCVqwMqP9DOi2lFELwIgE2RsWKIYmG/sOw+6NdxYSZOSa1g"
+ "U8y+GILu9XT0P8k9y73OJ+9HAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Copy = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAopJ"
+ "REFUWIXNl01rE0EYx//Pzu6aeEkOln6CZIsSv4HgQaSnHPwOPegthEaRgidLG9GC+IJ48KSC"
+ "V+9SLcWjoh4CalWEhuohSdmkS15mPMTd7Cw7+6Ib9IGQmZ3Z+f/m/zyz2QD/OAgAtraaF53h"
+ "aDHLhU3T+FmvNe7GzdMBwBmOFq80rmapj43m+kKSebq/0+12MxEvFouJ52qZKP5F6PFTkgfn"
+ "fD4AT589vnTY6yXKqRtEwEbz+jXVuGEY7+u1xulQgFarJfUPe72Fy6vZFunmjfUKoHBgaWlJ"
+ "6r/ceQEgmyIlIhQKBa//fxZhMAVZhRAiGYAqBVkIByEiT4HqWKVxyBUUQqBUKkHXZUllCqLO"
+ "dNChKOEgRKwDnHOUy2Xp2s7udqxgnHDYeChAECYsVCmIErQsK/QeCcAVTJuCqF0Hx4hIDeBC"
+ "BFOw+/pVKEhSu+eSgqSCwNR+FYQHwDn3BKPsF0J4+Yyz2/32t4lIWl8CSCKeRDBufiSAP4LX"
+ "3AVUKYiDsSwLRJRNCv6kABlj6idh1inwj2maBsaYB6Bpsx9hCSCXy0kQ/onBYkqyeyKShN32"
+ "fnsfAmIGYJrGwZ17t5X/C4hmUGnsJiI8fPQApmkCAEzDxHA0RD6Xny7qAtRrjfsqcWD6bsc5"
+ "V9ocZTcAnDt7Hu79juPg7bs3INATDyBJhAH42yq7GWPgnKPT6UAIgU97H2Ef2T2nP1xJDaDa"
+ "tUpY13VwzjEYDGDbNr59/4rBkd05WamcqS5XB6kAJpMJ8vm8VIxEBCKCpmnShzEGIQT6fRsA"
+ "sPflM9o/2gIC28dOHL9QXa56b7cULifHzVubH0bj8amksG6I37WuMXYw5pOVtdW152nXmHv8"
+ "AlZUDO8eTfS7AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Cut = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAB95J"
+ "REFUWIWtl3tsFMcdx78zO7d3t3fnO+O3TfyIDZhijAKxETQQMI+mVaK2f9QRJC1VE7AqlKoi"
+ "AWw3RJdAqR1DTZumjftUSpM2NFGI1KoiYBChQIqBBjBYNsQGv7DP2Bjf7T12d2b6hzlkHnZs"
+ "pT/pp13t/Ob7++zM/mZmCSawn+/Ztd0wYi9Hw6bH7/eHJoq913bX19abpvVjlTm1TZs2RcaL"
+ "o+M11NbWZnLBN6WlpsU8XuerU0leU/PaXIBWpKSkxgSsFyeKHRfAptJ3F5YsVFetXG0HyA93"
+ "7tpZOJnkUkqi2p17Fy/6qn31yq/ZFUq3TtT3gQA1NTsW21TbghkFM5mUBIsWLrI7bOrbkwGo"
+ "212z3uPx5Odk51AhJEpLSzUnU2unBABK52VlTlc455BSIjf3YepwOObU7vrZMxMl37lzZwql"
+ "dFfZ8pVuwzAhpUR6eiaVUpZMCUAA5z9vv6JISACAaVpYVbbSpRD6hv+X/oTxxJya+sacrxSp"
+ "jNkgpQSlFGfONkU45yenBFC9pfo4QOpPnDgeppRCSgmHQ0NBQYHDw101D+pTs2vHUkLJU3OL"
+ "iu2ccwCArgfR2dml66HouikBAIAejLzW1d0VCgZvgRACzgVKHi11Uop1dXU/LR4b29DQYFMV"
+ "+5/Llq3QTNMCAKiqDY1HGnVuWusnKuFxAfx+f9jixobGw4d0VR0dUsMw8djipQ7Fpr4tpSTx"
+ "2FBouDI1LTXZ55sGIQQIIbh8uc2KGdFTW7dW7x8vx4QAAFC5+eWPDMNoarvcahFCICWQkZFF"
+ "PW5PQV1dzToAqKvbngeKyqWPLXcZhgEpJRSFoOlsk2FE+A8m0v9CAACIRa3nTp9pMhhjkFIi"
+ "FothRdkqN2XkF/X1fh+zOf9YWrJINc3Rr95ut+OTfx/VqURNVVXV1S8NUFVV1S6l2HP8xLFw"
+ "fCoIoZg9u0jlUvtAddhLcnPyWHzoh28NIRAIDLrdvgd+rFMGAIDQSHR7d09nMBQKAgAsy8K8"
+ "ufMcikKXlywodUUiEUgpoWkaDh9p1C3D/F5FRYX5fwPw+/1R07KeazxySNc0DVJKRCJRLFta"
+ "Rs6d/wxCCDDGcKH5nMEF/9eWLdVHJ6M7aQAAqNz8k38apvnplc/bLMYYLl9pRWJiIlRVxdVr"
+ "HVCYggvNF2Lc0DdOVnNKAADAjcj6ptOnDLvdju6ebgQCATy+ZBla21pwqPGAzgWv3LzZH5iK"
+ "pjKV4IMHjww/mZ3x/KAUiWUrnkB8lSThMK4fO2q6Dxwu/8f162IqmmwqwW9peNT20ft5g3n5"
+ "OHvmFKw/NSBy6SJigzfgNGIueHyvANg2FU3yxSGj1gDYmIdcmp/+cD7LziUd0zPR98FeFHhT"
+ "MN2TBFDgWGdrWHA5a30E3V8a4B0gEZRuZJSu5UJMJwQqZQoryslTXE4nzvRdjQzpwQ+ZQr41"
+ "P/EhTbXb0acPW53DN27ZI7ABoFRRuizL+hsT4lflwNCkAd4BvkMo/UOKz8eyUlOdXpcLEkD/"
+ "0BDau7vhSHRGB6L6YfcI/3bQQ95Ld3u/nsY8dremoXmoB6uLSkAA3BwZQUdPT6RnYMAC58+v"
+ "BfZ9IcBfKX2JKoq/OD/fZVoWOvv7bwV1XVUUxTZ/9mwWjkRwsbOjX4lZWeUAfzMFbmeMfpLv"
+ "TZ3ngo1Shw3tnT0jQgiSlJBA8rKy3JRSNLW06Bbn29dY1l2no7vK8F2gnFL66oLCQldnf3/4"
+ "Ynt7181g8PuKEEkRblZfam9HWlISpCkSygEOABsHEAoxsaxjKADLRnC1q3ckFout4aZZeH1w"
+ "sPI/zc03r/X1RRcXF7sYpdv+oihPPxBgH+AllP6ueMYMraO3Nzw0MnLKK8SM7wL7y4GIKvD3"
+ "SCwWub0p3VU9PxrCiC0iucvlgmGajABn1gC9zwJvKkLk9QYCbVe6umIlc+a4GPDbfcC0+wAs"
+ "SiuSExMZANy4eTPk5fyJbwCxeLsAlvjcbjOo62CMddw7dUxhHS7FDo+mWQJYFn9eDtxShFja"
+ "GwhECYCs1FSbRemG+wAUStdNT0nRugcGwlyIHWOTNwCaoiivz8zJSejs64sKzvfeCyA439vV"
+ "1xfNzchIUCjd3QBoYyEE8Pq1vr5oblaW08bYnSPaHQDOeZ7b5YIeDhsAzo5N7mXs44yUFK+q"
+ "qugOBExDiN/cC6AI8eueQMBUVRVJPl9SgqIcHAshhGgK6nrU6/HAtKzc+wBAiAUAbqdTIUDx"
+ "C0DC74G1HkVpz0hOfmROQYHz5Llz+hCwaR0gASQBSI57OUBuEPLiZ21t+szsbEeyz/eIm9KO"
+ "BmDtM0ACoXSBW9NslFIQ4M5yfacM32Psw5k5Od+c5vWSU83NusW5kuB2m4W5uR6HquLk+fPh"
+ "65w3vGBZb90Gp7i7jCUAsYexDVmUVsyfNUuLmibae3qCQV1XGWNixcKFzuGREXm6peXA04bx"
+ "JAAeF2C1wIxsRfm0MDfX/VB6OrUxhpFQCB29vdHuQIC3SOnfLsTHAGwY3UPirmC0JK24V1O6"
+ "sgjYlpmaquRlZjqSfD4AQE9/v/hva2uwzbIefwVoBWCOfQNaDxSnMbYbo38ylFDaN8T5/veF"
+ "2HsECN5OFncyxuUY5wD4EsBTTumzyYw9Bc4zCCAEpWe7TPOlrcC527ByvL0gLkzvSUof4MDo"
+ "nMoxV377Pj4yYkzbXfY/Sz97xTRIV6kAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+Locate = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wsdFjs1ZObMvQAAA2BJREFUWMPtls1vG1UU"
+ "xX/j2EnqkajddmgjkOgNUirUohiBlIUXaRXU7NgipKDwJ6RdsGqhUveQLQtEgyzUDaLKBjVs"
+ "vGAWrDqIIFEq9SYChJuJ6zhkJo5pbBZ+HtnGcmIHxIIc6UnzceedM+fed9+DYxzjP4bV7weS"
+ "lbwz4Ux3excWQ1aXV61/RYBkZRHIAJOcJsVwl6AiUMUDyurq5X9MgCGfd153UsTBL/iwTh44"
+ "b8YSaeZJgvOiQ7gWEjwJPHX1tSMLaCX3N31Y5x3gF6AAfApMA1NAArBJc98es6HIoUTE+yVX"
+ "V++2vI9i1VXXPJsNCO7bYzY2dkay8qCXiPgBBmScKSdlLI/IZc7UQ5VJakCCT0SkDCxoTlc6"
+ "RfQiiB3w95P+RldyD7hFiTW2gIAl4BawIHOSUVdXKDEb/B4QbAdIVh70LaD599SgC/k9zWme"
+ "kDK7QBFPc5oHFttEAJwCZ8LJDCKggXXmW0UBa5rTLXO/AFwxotCcemZVpAAoMUvYe/r4IVbh"
+ "u5KVGeAlqkxS4mPJmny76v2tT7THHIjDCHgzuqoBdZp2pjpTBkx3xByI2CFi5tVVS121SOCR"
+ "5Fqr7S1opKM95srRHUizBHwOwBBlnsPTZc13tOcoHSISxciM1Bk9ggPhWghJkKxcNUV2GXhP"
+ "5iTTZrtJh1kldyJ3TgBhY5PquxVLVjLAZ4yRodKo6ObSkjm5A5w3jShFAo8hyob8nuZ0S2ak"
+ "ThrYAna5pq4u9r0XNLdeP/AhBDZ5iyd8C9SBUV7mG+ASCT5giK+p8huPKDLOHmmw4zaE9Nyi"
+ "exdhjev+Q/8Hx3YgCZxhmTNcNbUTJ+QPdoES3/Ejj3lEpZM82AyuS1ZSgwko8CsV3vcf+quR"
+ "iLPc5SI+z/OGcQJqjDBOkYs8bSPfCG6ww1fqRo2rzxSInAVGOMUEI3zkXHBeBYhS0orRBnHy"
+ "RJKwGDbIA75ghx1V9QcVcM7YbXGacWKkiHO7KaTbkSzYCG6wz0/s8j0B28AzVX06qIBhGsaf"
+ "NAeOKikuEeMkFjWG+RCLV9jnJn/yGItnBPxMhQIwDGwDoapWBz8RiVimVhLAiJnYAhKc40ti"
+ "TLHH2xRZaSSCGLAHlIC6qtaP1AnNBPtmVFqEvdAlttDvKTvGMf7v+AvsF3zgy4iAXQAAAABJ"
+ "RU5ErkJggg==")
+
+#----------------------------------------------------------------------
+MoveDown = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wsdFjkO59tHGwAABC9JREFUWMPtVk1oJFUQ"
+ "/t6bnklPZ2YySUg0kJ4fDKyChOSYQ4LZkIFJ9rCIoGD2IB4UD3GFPSi4eBD8OUVFRMEfZD2s"
+ "HrxIdnQkEL1IzEVldVfQTfe8MDMxCU53T/9k+ud5cEaGkJhNJiBCChqqinqvvqpXXVXAGZ3R"
+ "f0zkIGU+n1cKhUJmv35iYuLDbDZ7obe3N1SpVCzG2Bfr6+vPdAJAuFvDsbGxN+bm5h6enZ3t"
+ "4ZyjUqn0raysPEop1ba2tt5UFKV6mgC68/n8QktwHOdeAJPxeDy2ubkJx3EgCAKGhoYSiUTi"
+ "3M7OTqgoyw9ECREJEHBgd7JU2uwEQBjAtZYgiiIAQFVV37ZtRCIRmKYJxhgajQYIITEA0wJw"
+ "jhLyJAd++y6Ves4D/pwslX44CYBaoVBI7nuCt8Ph8CXDMBKiKMIwDFSrVUPX9d9d1zVyjL3T"
+ "NH12NZVajBHycRQwvk2lHpkqlW51VAPpdDpcr9c/YowNaJp2PhqNhizLsnVdX7Es6zNVVcvt"
+ "9g3O36sD9RghH/QQ8upqKvVKg/PbOcb0EwFQVdXNZDI/6rr+kuM4nwqCIHie57iu+6vv+xv7"
+ "7XOM7RVl+brOeTpJ6fMEuJlj7PuD7qZ3W62c8wBAg1K6Fw6HHUqpA8AlhAQH2ecYszzg5d0g"
+ "+DxByMKKLL9+4ifIZDJCJBK5f3h4+IWRkZFcT0+PUC6XLUVRvqrVam9ls9mbGxsb3gEgvKIs"
+ "ewDSBBg7MQBFUbzx8fGnZ2ZmLkxPTyeCIMD29nZydXX14tra2q5t20sAykd0vNxxACTy+fzl"
+ "f4qq0RjgnE9Fo9Hu1q9HKUV/f388Ho/ft7u7m0in0xVVVflpdsKlFhOJRFqZ8G3bRldXF+r1"
+ "Ohhj2NvbO7LXEwD8mAD0QqHQ164YHR1dopQ+YRhGT1dXF0zTRLVa1TRNu+15nnZY9C0HvMM+"
+ "IJim+T5jrF/TtJwkSYJpmpZhGF/atn09CILtw87SZgZoJwBUVfXS6fQtwzBetCzrWigUIr7v"
+ "N3zfvxMEQVlVVe+gc0VZDhNAaEZvdzQNmykuNT8c4jCUY8xv8kkBeC1G6WMa55hmTOoEgEgI"
+ "ETnnNUmSuGVZ8039MqU0wzmvcM4bOcb8oiz/AmAqQsjVGCFPhf6ejuud7gMO59wB0HJ+o6mf"
+ "F0VRcRxH5pxvFmVZp0C9j9KrAbAoANA4/+ahUun8sQC4rpsEMNcUb7TxC23OMTAw4DqOc/nd"
+ "wcGLmXD4SpyQWJiQuEDIohkEsIGvp0ql3L9FdmBxUkpdSZKWJUlaBoA2Xmy3MwyjYprm4B++"
+ "vw2AewBpcA4tCH4yOL80eYTzQymfzyuHzaS2bIAQ8rgkSZxSek+z8GpFWVaKsvzgae+EFEDQ"
+ "1tTmmxPyE8uyyJW+PnG2uzuUYyzZLMKfz/b9M/rf0F/SjQQIbOsI7gAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+MoveLeft = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wsdFjkfjWtn6QAAA61JREFUWMPtls9rI2UY"
+ "x7/vTCbOzJo4bbG26GxmEFHKUuNBpAteFipOV6S7PexFYT2J4sGDHryrexFd0cuKKKIoCAqi"
+ "27Ct/Qe0ULKgyBaTSaaQZNt0k8mbN5PMzDteZpao3aWkARH6wMv7Ps+8zPt5n3l+DHAsx/If"
+ "CznIaFmWXSgUjEQ3DEO0bTtcWFj4zDTN5yYmJsRarcYcx/mRUvqR53k3yuVyOApA6jCbbNsO"
+ "8/n85aWlpfOLi4v3RVGEWq02ubGxcWFzc7Pd7/c/BFAfJ8AJy7JeSBTP82YAnMlkMpmdnR14"
+ "nodUKoXZ2dlsNpt9tNlsarlcrlGpVKJxAUgAvkwUWZYTT/Ber4d0Oo1utwvHcTAYDEAIGTkG"
+ "7gTQKhQK2rAhn89/LEnSi5TSrCzL6HQ6qNfrHdd1/wyCwB3l9oeOgVwuJ1FKP3cc5/52u31G"
+ "URSRMdZzXXeDMfYt53xvVA8Ih9lUqVT8IAiKW1tbF1qt1pthGO7t7u6+Qil9x/f9YqVSGYz7"
+ "ExyUCUEulyPT09OrqVTqNcbYTwCiYdcbhiFJkvSYoignU6kU8TyvMxgMbnDOG6VSiR8JIPZE"
+ "NDc3x+P1315oGIakqupThmG8axjGKVmWSbVabTuO87Xrup+Yplktl8v8SAB3rWiEPJjJZN5a"
+ "Xl4+PT8/L/q+j2q1qq2vr79ULBYbnud9CqA7LoBpy7JeHzZ4nvdQOp1+XBRF0bZtBEEAAJia"
+ "mpqSZfkRURTvGRdAF4AO4INhY1Irtre3oWkaBEGA67qo1+u3YY4cAwBQKBR6B/UQ0zRPapp2"
+ "WVGU5ycnJ0VRFOG6Lmq12k3G2O9hGHpjAbiTcM5rlNL3yuWy1mw2H5Yk6QSltEUp/abf71/l"
+ "nI8FgMQjGpqjpFaYpvnLs7duvf30/n4jAPQGIZOXBGGNc77/z6wZFeD2gUNzAoIrQRCJQEch"
+ "pCMR8oUShu+XbHvvyJUwbk4AAFVV+wDOxyMBSsePz4bAjkQICDBNgNK4KqGf3JoxdhbAaqyv"
+ "xAD6NV1/AsBXAnAOwKWYjIwE4Pu+BmApVlfjdRfAxaHDAeB7ACtXZmaWCfBGhpB7BUJ+DqII"
+ "IfBrBPwxEoAgCL6qqlcBgDFGknWv13s1iv7ddXfDcNeUpCgACIkisCi6DuDlZxzn+kgpZVmW"
+ "fZcgXBrSkzh44Jqun17T9daarttrun5q3N1QAMABEFVVI8bYSmz/DgA5l8lIHLgpAk8C+AHA"
+ "b8f/+8fyv5G/AAJEtIKkFvP8AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+MoveRight = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wsdFjkxUb1qJgAAA3FJREFUWMPtVk9oI1Uc"
+ "/t78yZ8Xm24mDd1sNx2zXUwgtBColvr3FpjW01IUFk+riCcVDx7Ug97c9eBBRPewyrIIgt5E"
+ "B5pDZUFYtAehaKWYMtPZadqmretM85LpTPI8mJUltuhuZxGh3/F7f37f+36/33sPOMYx/mOQ"
+ "g0hN0wxd1x/s50ulUkpRlKv5fP7RRCJBbNt2tra2LgZBcHVxcbF1LwKku5kciUTem5ubq0xP"
+ "T0eDIIBpmkq1Wn17dXW1BqAapoCEpmnP9ZOe501RSiNra2vwPA+iKCKbzSqMMaqqKjFNk4cl"
+ "QAZwrZ+MRqOo1Wo8lUpBFEXs7e3Btm20Wi0AEAB0whJwS9f1E/1kuVz+lFJ6Pp1OR2RZhuM4"
+ "qNfrv7muywDw+14DzWbzFcMwTu/s7DwsSVK83W5vMsYu+77/rWma3fsuYGVlxSkWi8+ur68/"
+ "6bouCoXCYqvVaiwvL/uh9qamacY/CaeU1sOIJRzh/jh5yH4JSuk2gBkAM5TS27UROXIK7hTA"
+ "GHu9b49AEIRYLBbbY4zNAvgGABhjs5RSzhgjYaYg1jvZUwCeBnABwBCAlw6ZP5PJZFJhpuCv"
+ "lqOUfhWPx68AECilHx22wHXdUIvw4LwQQnvOzNx5ekopFwRhNMwaONgWztuMsRSl9CZj7Jme"
+ "Q18zxgYBtMNMwWHoAnAH9vfPfH7q1NkvR0Ymh4Mge2Fw0JvP5fxQHJiYmBhRVZUODAyQer3e"
+ "2d7ebiwtLTm3x+dzORnArABcBBC7PDwMAO9XLMs7kgOqqpJSqVTM5/PXCoXC92NjYz+Mjo5e"
+ "z2Qyr05NTSm94CKAFwB8Eick9gAhAPAOgBfnc7n4kRwwTZNPTk6+ValUHiuXyxHf97G5uZlc"
+ "WFh4OXvjxvVLudwvHeCJLvABASAC8P+8sRY4UAAQB9D6twJOaJp2vp/0ff8RQohsGAZ83wch"
+ "BMlkMnm62/VjhBQFQoYAvEuAcxx4yOl2qwBeA/BTxbL43TjgA/jsb58EWUatVuOKokCSJDiO"
+ "A9u2ke900vvAFZHzoV6Udgf4AsAbFcv69V5ew6au65l+cnx8/ENJkp5Pp9NRWZbhui42NjYa"
+ "P3J+8yzn50ivDQA0OLBTsaxGqM+x53lvGoZxcnd39/FoNEqazebvjLFL3wnCzx9bVvv4j3+M"
+ "/yX+ABtPUyn42ht5AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+MoveUp = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wsdFjoW35qMjgAABDhJREFUWMPtlk1oXFUU"
+ "x//n3fl8M28mNUldmEdmTNtYFD9WrpI2hEyZpgvXIroQsaBiXSitiC6KCxEU4qogiJRCQRBR"
+ "07EDQjUL003poliRfExyTUyaiZnJm/fezLy577h5kaHUpJl0oZADl3fuffdyfvfj/O8F9m3f"
+ "/ouWz+dLdzWJLUfXdQZwMiisaVoXAFEwTSqa5uGiaf5aNE2631ih++yngi87jjMO4EpQH4/F"
+ "Yhvsuo9oQBbAJIAKgMcB3OoYQCmVCGaIINiW/0JbcAC4IoQ4c66nZ4SAD+NEaQGkFXCpaJof"
+ "A7iZk3JbEO1ejb7vh3Vdn9R1fTJY9i2/dXdf27YPdgtxIJgNR4iQ1rQnDaKLcaJPiqb5xK4B"
+ "wuFwxXEcchyHAKDNv9y2GiCid2Kx2Luvrqx8zcAbFnOt4vt/tpgnwkQwiMZiRBNF0zy8K4Bt"
+ "jIJ9PgngJDN/FICVT0j5HYCXfKBS9v3zNeaJFoA00bEI0cWiaR58EADBxOmX4CxQUJrBv28B"
+ "nMpJWW4yf7Dp+xcUoBHwLID4XrIA/f39mhAiE4vFjsbjcXJdt9loNGaYeXFubq4FADkpFYC5"
+ "wK8AOP2TaQ6mNe34BvNtAHpHAJlMJhSJRB7r6+s7d+jQoVw6nQ4tLy87pVLpaqVSmQBw89/G"
+ "MmAHotD5ChBRTyKROD06OnpqZGQk5fs+1tbWuq5du/bc9evX17cDUMDvDIz7uxSiVD6fP7OV"
+ "FEopr9VqHYvH4wkpJZrNJjRNQ3d3t2EYxsB28AykOlXCT//RYSHged6tUqkE13URjUZRq9Ug"
+ "pUSj0cAOAFonAJuFQuGhrUo2m33YMIyzs7OzpmVZ6Wg0Ctu2sbKyUq1Wq7/tACB4m3S7rzPg"
+ "+/66bdufSym7q9VqTtf1kG3bjmVZP7iue3mH4ckApNkxwMLCQiuTydyu1Wrvua57UQghlFJ1"
+ "pdSc7/vLOyiXEQAs70kHmFkTQqQMw+jRdV3Ytl23bXtNKSXudUcUTTMeAka6NC26yQwF/Nwx"
+ "QCaTCUej0acHBgbODg4OHk+lUqGlpSV3Zmbmx3K5/Fk2m70xPz/fbAseixAdSRKNCWCYgS8A"
+ "vLUXHehNJpMvDw8Pjw0NDRlKKayvr6empqbGp6en7ziO88dV0wwRcAcAIkRPJYleCwHPV5kL"
+ "Teb3c1JWdwPQlc/nX9yqeJ5nMPNwKBTSFxYW4HkeiAipVCqRSCT6hRBJeJ5pEA1qREcYOO0x"
+ "H3WBr+rMb+akXNltGnoAvmy7nuG67o12HbAsC1JK1Ot1MDMAnG8BzxDzMgPfuMyvBw+SjU50"
+ "wC4UCr1tZ6A3mUy+PTs7+6hlWV2RSAS2bWN1dXWjWq3eUkptAHjFZa4DaACo5aT864G9CZl5"
+ "3XGcC4uLiwcqlcq4ruthx3Fqm5ub3zcajUu+75dPSLm6/5zft/+l/Q33KPCXllHwqwAAAABJ"
+ "RU5ErkJggg==")
+
+#----------------------------------------------------------------------
+New = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAA6dJ"
+ "REFUWIXFl0tPW0cUgL8zc20Mxi4QTCAlm6pS2WTRDRWL7rrptn+ABbv+iG677IruKvUP9B9U"
+ "aqUuKqGGRkFqQyLikhIIuDWElx/cmdPFtZGx78O4VD3SaGY013O+85rxwP8s8l9sqsoYJ4UF"
+ "8m4GF4wDYMMGbVtnqrkvQjsRYH19/bNcLvetiJSMMRhj8N7jvScMQ5xzsX13PF54y/Q7x0wW"
+ "T5kYbxAEV3jvcc625udqX3/80cvvkMZzKVEDCPoBrLXfrK2tlUQitjAMCYKgY5n2Wao3x/oG"
+ "0d8Q3QHdA60hNKI1KY798OPF50iuivgJ1dZjEeoDAGEYTokI1WoVEcE5R7FYpN1u04Xq76Nx"
+ "m7zdIh9sE5gdcsE+VmqoRBEw0mbxweUYFB6hwJm5VG38PADQtUpErlvvPAnAyhGBPSSwB+Ts"
+ "PtacI/YDkHudL+rMVbZA8kvgz8HXOJ98MQDgvY9VmAYCEASnWPMWI3Ws1BC7BLKEmMXoW15j"
+ "c2fA3w/B7oGpIM37qQDDeqLrYpEmRpog4yAziHkI9sPOxoKYlyDlHHpVRmQCb0uxAHFhiHN/"
+ "L0BSaKJCu5m812LlagDAOZeqPDEPpIBqAaWA+kvE1KNKcN2dX6P+L9DTENwZqpcEbrAK4gCS"
+ "5jetnUGZRpnFU8f6V5HdcthZP8Zd/QG4V+AOwNc4ab0xaQCbm5uxAHHNcx/lAV7fxflFnC+C"
+ "2wb3pNO2OTxqgra20XYV0Wcyz0WiBwCWl5ev6z87FAU87+G0Ef1Yiyiz4KN5kCtT3X3M0vut"
+ "p9B+SrG5BTEnoXMOVY2sumVJKhWcPgImUD+NkRMgArAyxYud3/n0E/cTxeaWSJQdqR7ol2Fy"
+ "AmZxTKMc4zlC9BwkjzcL/PLr98jkxZPePYeugizlN0svQKmgWommCsoEl42BlBsOoNfCrPJM"
+ "ElW9DmkmQP+t15Xbng1pt2ciQBiGsUqzgOIA+mVoD8QpzjoHRgVIPIgANjY2MGYwcYYFNMZk"
+ "5sbA7mEYXsdqZWUl9WJKUpzkoThJDUH/1ZzmifgzIVtSQzCM0qy1LJjYKkgqw1HAusd6kozk"
+ "gbuUW90FWTKK50YC6K2MLBBVTQXrBygbY05VtVwulxGJ3gVBEPzrvADI5/NnwDxwDLT6AUpA"
+ "ZW9v78vV1dUvRDoviruT5u7u7lfAAmCBA8D3+nAMmAPuAVOdub0r5UTGXgB14E/gHOJfx2NA"
+ "odPf1evZAVdEbm/R8z/9H3wxyNYpdILJAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Open = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABVRJ"
+ "REFUWIXtlk9sG8cVxn+zf0iJVEpZEl2lBgQENuwacH0QcnPt+hBfah98dFug8KUnn3qvDRg5"
+ "GM41hwCG0ZtRH4oeAhQF4iLIoUHrwEnQSg4c2aAoyTJpailxl8td7p+Z6UEiwyVp2SqK9pJv"
+ "sZid997O9715szsD/2eI/ZyXLl36udb6z7Ztd4ZjDcPANE1M0xSmaWJZFr3WMAyEECaQ24vp"
+ "x/faW7duCQBrX3VCfDE5Ocn9+/eLaZqitQZAa92/exjuG4aBbduZ8Xr+69ev920WwNWrVz+L"
+ "4/hn40SEYTgoKNO+DoOCepBSopSSGQFxHJ+5ceMGrVYrk4HWmtu3bwPQbDZ58ODBGxGPw4kT"
+ "Jzh9+jTtdhvDMPyMAMuydqrVavnZs2eZl4Ig4NixY6RpCsCFCxeA8TMx7nnYFgQB9XodIUQ9"
+ "I8AwjGapVCrPzs5mBHiex+LiImEY4nkeDx8+PHDm58+fzwipVqvEcfyPjAAhRK3Vav242Wxm"
+ "Xl5bW+PKlSu0Wi3iOGZxcfG1WQ4/D6+h1dXVTrfb/VtGgJRyM5fLUS6XUUoBkCQJrusyPz/P"
+ "0tISz58/x/f7pTswTp48iW3bVCoVKaUcEVB1HEd7nieiKEJrzcbGBhcvXqTRaNDpdJiZmWFm"
+ "ZubAde+1SZJQq9WI49i5c+fOk4wAoN7tdpP5+flcu90G4NGjR1y7do2VlRVc16XT6bxxtrZt"
+ "Mzc3NyJkeXk5DMPwo8FYC0ApVXccJxFC5FzXxfM8pqenSdO0/2kWCoUDrf4gCDK2JEl4+vRp"
+ "LIS4OyIAeOn7vjp16hRaayqVCpcvX+abJyt88EnE6O/kP4T9XgnYefc372UFCCFeuq4rms0m"
+ "jUaD9fV1jhw5wqd/X2Jhforf/vLMwcl0rxmVr4EoSvndnc82+gI8z8sfPnyYzc1Njh8/ju/7"
+ "tEL4UXmaZjtiac3djydDOGrL9o/MTrKz4yO0+NQAuHfvnhdFEc1mk0qlwtmzZ3Ech+1AMFMq"
+ "4AVphlADWoPa24CU1ij0Xn/Xp1UvZq+vd6VJpclZBt+uOx2Zyr8avYGFEK1isUiSJExNTSGE"
+ "oOFrpn9QoB2mYwkzBMOEvau/c0IqNWGSMpEzWVlrCoH6vL8dG4ax7ThO2fd9bNtGKYXTlkwV"
+ "crS6Caq3FY+d3t42/eryJFKRpIrihEXTDYniJP7i7q9XjYH4mmVZBEFAsVjENC2afkphwiaM"
+ "1djpVAPZ7WZN/7nnk1LTTSRxqtBAIW+yVnMRpvE5DBxItNab29vbSCkRQrDlK8qHinQTjZRq"
+ "JMNxi28wRirdvweRs0yqm9sdlag/ZgSkaboqpdSWZYkoilhzYg7PvkU7TPrZ9QhVbx2ovVoP"
+ "lqM/Q6MQYvdct17bMVNpfDI8Ay9brVaUpunEzZs38WZ/yrtnzhNEklTtTqXUGq3GD/4myFsm"
+ "9W0fBbWvf/+LF8MCamEYJufOnZvY2triYfA2hYkcbpCQ7JVgGOOOXH3fGJswYP3FTorUf+rZ"
+ "+gJM02z4vi/z+Tx1V2JOWsQYBPF3/wD0+IH3Jd4zCCBONOsvnG6i9B9GBCRJ8tLzPGtubo6a"
+ "eIe58hztboqSQ5/fKyj1qCkDIQQtxyOJZeuru7/6ckTA48ePw6NHj+a/rk8QmrMsHCrRjeXo"
+ "SK/iGUOa9Wuqa7Wws73xIfAW0M4IWF5ejhYWFp409MJPSDWP//ntvuQHg5BaCGTs/+vpx+//"
+ "Bcj1PQNRpXw+Xy7N/vAdMXloJk3i3OhAB4fSOo3i1EcpGWxV6oADbAJyWABAHigBk4DNfw8p"
+ "kAAu0OH1a/l7/O/wb2AlR4xselGZAAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Paste = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAA7pJ"
+ "REFUWIWtl92LG1UYh5/5ysems9kPaIl4o60kVwWvShcKCy5eCKtCr4RFAv4BumIt+AcIuiAK"
+ "pSIoFNkLvRFFrFBWQSq2eqMUSxaqppWliCzZppuPzSRzXi+yM5mZTJJJ3RcOnJk55/ye8/7O"
+ "nDmjMWWsra3dAU6NePzH5ubmU9OMZ04LAJw6d+5pdF0L3VRKuH7911FgI0Ob3ATK5Zff7fXU"
+ "64ABcPr0EzSbjVCbXO4Yt25VvUvXNPX3rlz59M3EABdfOL7RVfKaiDaUld35Z1lZOYthDB7t"
+ "79dDbWw779ddt8fW1g0Wa9fQIlPUkJ6hae9vfP3vBQhY0FWsn19aMKIdAC7/DoXC49Tre2iH"
+ "DTKZTH/ASAdN05idnUPkBqtn8mRTeuh5tyfmVz8/WAfCACL44r9Z53no5gLdKuTz84gIIIgA"
+ "iNdv6N7MTL/vj9pLpPU0AFkaLP7zOU8etxDpWxkCCMZDN8fFC2/51+VymWr1DqZpBUQ98MDF"
+ "IUCtVsMwDNZffQPbtgF4Z+NtVLDpOAAv6vUHAKysPMPVq1sopcY190PXdZaWztJo7KOUSz4/"
+ "18eL6T4EoGQYc3V1leXlZZrNViIAANM0/HUybuxhAAUDhwZh27afzqQhIiGLElkQAzl1BEXD"
+ "9QQAcZTb29uPJFwqlUKiiTIQ51OpVEosPmr2iQGmtWAgDOP2hjigWICkFsTNNChYKDzG7Kz9"
+ "KBYMN4paEE33qNlHM/C/LRjnczjt0frosRMtwkqlEhIZFgzeg2KxGILwdtCpLfBm13+dJi+2"
+ "uNmLyAAghmCiBZOF4yFCO+AhQDILAh8Mb5CoBdGBbNumUChEYPpnA8MY7OtTb0SeYLFYYvLs"
+ "w7M2DMMv3qFlqrcgevhIKqzrui9smia9Xo/qvSqCxB5ARy5C70s2zudouk3T5KNPPgyNl7JS"
+ "OF1n6Og2EUApNWZhDfscTPfzz73oCzpOh+9/+A6n00kGID6AGys4ymeviIgvXturcfOXn2g1"
+ "W6RSVtIM9AVcV40Ujvrs1R3HIZ1Oo5TiduU2f939E+egg507RqfbmW4NKKXIZmeGTjWapqHr"
+ "eqh4r9q9v+/S6XT49to3tNttVNdlfn6OhYVFdu7vJMuACGSkwaXLH8R2GBdC/0/H7XVJWRZY"
+ "Fq2DNq37O1huA3cMgI6G6vZEP3nC4qR8EfyIHU3oQClD2xHQUMAJYNcDSB901Mdf3tx7BbSY"
+ "I+lRhrh7TfUZMAMYwXWRBRaBPJA6LEcZDv08HAC7QA3o/gdv7VVF6PIUygAAAABJRU5ErkJg"
+ "gg==")
+
+#----------------------------------------------------------------------
+Redo = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAABl0"
+ "RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAVwSURBVFiFxZZbbBRVGMf/35nZ"
+ "nd221N7shVKLBSkWod64R0K4VAxNVmOIRtEXWUSefJFHo1FMTNT4pIlLYsCEqCSENUFUQkAU"
+ "KtIChYKUWkrphd536XYvczufD+xututuoZDA2Xw558ycOb/f+ebMzhAz40EWca8TeHzalx6f"
+ "dtfz3LMAgO1Cwa8en+Z+UAK0cPaKVULBKY9PK3kQAlg8f41zWd36OhJo9fi0OfddQJCC2qp6"
+ "Ze3TL5aTEM0en7b4vgkQCAIqRs1uzCytFhuXv1KgCPWox6c13h8BIggSIAgEjB48lF8Iz6o3"
+ "cjWn6wfPLm3bba+fzv+Ax6flAGgggVeJ6FlmLhWsztjW+BH69Quw2YTNBnKVYpCl4uem78MT"
+ "sfGvDryl77hnAY9PW00C+2YWV2u11U/mFc8oozytEDnOfAhS0R+9AItNSDZhsQmXyIOKHBz+"
+ "e3/4ZihwkCU2+726OW0Bj09zksBnBe7yLQ2LX3ZXFy1E1ApC5zBMGYMpozA4CpsN2GzBZgMx"
+ "O4T+WBtUcqHMWYvzl85FBodvnGWJF/xePXTHAh6fVk4Cfyx7bEPV8vkbNRs6ovImJFuw2EjW"
+ "idQnBK5FmhG1gwAATeSh0rUI/3Rc1Hv6uq+xxBK/Vx9PMNSpVi8UfLN0/vpHV85rVELWMARu"
+ "bTbg1u5P1JRyJGQNJ+EAkKsWwzQtjI6MWAD2p8KnFPD4tLVVxbXrl8zdoATNPgAAkwqAkz8k"
+ "e4kWMKR3JOcocdZAswtx4vTxiG7G3vdv0b9I52QUiN/33eue2uQK26OwWIeACgaDmOBSZkAh"
+ "R8oVhL7YeYybgzBkBABQps0D6Tk40XI8Yprmdr9X352JlS0Dm2sqFhTl5uYiYPRAkAoGkK+W"
+ "wcFu/DvYyr0jV6Ij40MyGBrNebPhPcEsMWx0AgAqXHWwwgKnzvwZsW3rNb9X92fLdGYBwoKa"
+ "8jrXhDUCyRYIAvnOMvSPdeJwy75oKBrYy4yjANoFKX8xSwzo7YjZNzHT9QSi4zaaz50MSykb"
+ "/V79WDZ4VgGh0ONFuRVkyChstlDgqERnf5t9qOW7AZbY5PfqTYmxL+1y82CsA6N6F2a56xEc"
+ "nZBn21pCLHmd36s3TwXPngFGjcPhgC5DUIUTUSOCX5r3GsxY6vfqfalDJUuE7VHMctdjeGDM"
+ "vtDeGmDJz/m9+uXbwbMKMHOJRVFItqFRLlo7m6IM+9N0eKJYHEPP9V6ro+vKAEus9Hv163cC"
+ "B7K8jAShLRAZwq1HS+LaQDszI+MuBoDLHZeMjq4rV1nimenAswpoMblnLNhtEggmGzCNiGWG"
+ "ZZCIBBEpRKQmAgB6+3vaAl1yxU9bjbH4eSU+lu5KwG3y/v6ei2dsacGQERRq7kDosnQCSA9N"
+ "Wnyw7Ufr+eM7rVjaOQcABxE54rIZhf4nQETi23ftCXM08smNkUsRU0ZQ+khpUeVssTodDsB5"
+ "7ANzS+dv0s4AT22riTqenaSISAETESkAFADKgZ3Gkf7Ojh3j4cFgYXGFKHxE2/BwFXLSJndO"
+ "DEFNyKSvPg5OhJIaRCSAlLdh/IASl0q2tx4oaZxbs+jtWHTcbP+97etDn8dOjw3CBkBpGWQA"
+ "8jZhp/eJmRFPySRwanvjx0VVyxvqXw+bY86LTVcPHvkw1BEOJTMo0uD2NNp2egbSBZL94jmK"
+ "c807ldUFs5WaoasTN07tCXQPtFlmPBOpGciUifSVSwA2M9uTPkgy3IZEJDPkyCFRsVB1Fs9R"
+ "3YoDSrBX6t0n9ZgZBcfhmUTSpSxmlpP2QIoEZYGn1olVpz9WnCFSJWxmtifxpvoki8ukCmWC"
+ "U3zyTBJJOGcBTeuzPE0s2U0VyAbKVv4D5I/Z5OF31HMAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+Refresh = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAB59J"
+ "REFUWIXFl2lsVNcVx//33rfM5hkPttlxDWlqhKEsBlw15AMoJSVRi0IVWuOAmhTjpooUtVKU"
+ "lrZS+6H5UKmt1EZFoSxpsEkFocrSqgkRcUMJTQBjlhoSiLENeLdns2fmrff0w8zQ5wXb33qk"
+ "qzf3zbnn/zt3zj3vDfB/NjYTp9VPNy7z+dXvKByPOw5VOK5bxDlzGFiWC9Zuu/Ij13XeMZO+"
+ "M23Ht1tTxVpbf+RbF/6088SMANbVH63SNX4wEvIt3bCyPFQ+r1iEgxp0TYEjJUzDxnDKQM9g"
+ "yr18cyB9tz9FjNNB06Lftx6s6xofr/qZxs3geK/lwFP3dO8LsK6+6bt+XfnD9q9VBZcuLmVE"
+ "gCQCSYJLBClzfgSAM0DhDKmMjdYbffbp8522Q26TI7G3Zf+OIQBY+73GhxRFnLRdNzAtwLqG"
+ "pm0BXT3y/LdrAsVhH2RekEAgmQNxJIGIICVBEiApB6KrHK4kfHTptn26pdNwgAYm6boQ/F9b"
+ "N1WF3jh5BV4AZbz4+l1/LuGMH2p4ojowK+KDSwTDchBLZGFYDhQhUBTUEAnpIAJsV8JyJEgS"
+ "bEkwbReCMzy8ukKtrChT/3LyyoF4Mht4YtMyWjg3PCHZCQAUUOvXL5+vzysrwtX2AXr/41ty"
+ "MJHhjIERUc6HSArO7MXzo+aqpfNDlRUl3KcypE0XGdNGMmMhlUkhqCvYsWVVIGvY0HSVuZKm"
+ "B9AF31NTtcB36O2L7q27CTiShODctCynm7i7o2X/rk8AoHrPscj1W0M17d3x3YB8fE3lArai"
+ "cp4fXCBtuHAlEE/bGDVdzInoaO8bxbKFE3dgTA1U73kl4FeKB1dWztEuftqHaDioKApH31Ai"
+ "Lhz1i/8+uD02Wc2seLYp6nf5s4Kzn3xl5SLfysp5ymDSRDxjQ0pCIfO1D0Tx61fPUMuBOl5Y"
+ "y72BOBUtJlDg0me94gsLSlhJNBgTQvSDWNv9xAHg6r66+Ln9tS8ZFlWevdx18tU3L6AkpKC8"
+ "NACiXLECAOcMnMEco+mdSCa5YTnQfL7hkN/3QUDXP3Ac5yaRO+FMT2ath2p7APpYUbilKAri"
+ "oxaIACKAMYCziYduTA0oNlxHALOjoX8EA/o1xnmyOBIMDA2PzKhjVtc3fj/s139c+9gqrT9p"
+ "IJG2IJHrFYUdmBIg68guVXCMZrIf9nc77bYiRpPZhOm69uh04jUNTVt9uvbbXd9Y7dd1FUGf"
+ "hvLSAMAABgZVcAgGD07OJiCte/r1RecP196ZScYFW7P7tU0M/NRM/afshNW7G0lwli3MJZFC"
+ "BHWyQNLVZrce3j44U+EnnzwmuiJG+bkDuzoK9yb0AQB4+YWv+4Fc8Ugi2K6ElLlC6uhNYt+J"
+ "8ynbcqunE29u7vBt3LjYKMzbi61vMuJ/hSdxPtlCSYTLnQm0dsRxuTOBa3dSiI2aGIhncODN"
+ "lrTjOpsvHtz5+ZTpEjE3qpY3tw3M/Z8YuUCuiU0JMN5mhTSoguGPx85Jw3brCt1wKvvFL8Gu"
+ "380+LCCrTl3tf6C5uVlRVW1r7ltjGgBPoTIGlBRpyGRtAMQFeG31nqOl0wF0Ri6F42n3qwBf"
+ "pnCqaovP2UgkdzAGWEKMTAngfWYQATd7RyA5xw93PoQNa8q3CY72dfVHnq+pa5zY3POWlvaj"
+ "qsKqOKNlibS19vjp601F4SLBOR+5uq8uXvCbtAglEThjmF/qR08sC9slxEYsxEaAJYvK1FnR"
+ "IvXyp70vdXYP/Wp9w9ETtiNf0wyc/6TpqVT1i+9HioTvudG08+LyilDq7bN35p651LEgEPCR"
+ "L+BTE4nUBa/WpMfwdz/ajKzlIpHKIhzyoy+RRfdwFv0JE66U0FWBaFCFlISunph7tyeWjo9k"
+ "dCEUnXEFlH92S8dBIKi70WhY0QN+3OnqGcma5g8uvrKjccodIAJu3knIw2+18AfLS7JbNjzo"
+ "VwQHYwQCkDEdpA0HQjBEo2ExuywSJgmMpA2kDRuOS+CcMa5ocEkqjgukkmlYhjFqxtVjXq3x"
+ "AAwAbvUm0Pj31pHh2+cftVMVmzp6Yj9fs3ShuqRitpJM24ilLdgOwXIkTFtCEt1bzjUdQub6"
+ "huW6ADFkMlkM9vVnjUTPrrbjLzDkak8CgPCIcwD6guptP7tyoz89dPtS7a13f3Orv+29z8xs"
+ "8m8jfPa8z2/HF/p1BXOiIe7XFTCG/HshQDJ3lSTzeeR2Kz6clAO9g5nMYHtD24m9Z/M6OQdA"
+ "snvogAZAq97dmMombj9z7Y29zYV7hVFa9ciS+csfq/VFSh8pDgdlaWnUHwz4mKapAGNwJGCa"
+ "NtKGhWQy7SZjiaxtZv7TffGtn/ZfeacDgDVumMyTvQZA/3Lty3uuvP7cUQD6OIB7c80fKSpb"
+ "vmVl8cIVNXpR2Ze4ppeBuEKMCQY5Kh2z14j3fTh045/vDlw/1VkQ8wrnr4b3FEwqlh/quM9q"
+ "vn6EdzsBOABszxif8ZjsAZjeIrQx9lgWgrr5wE5+YUFYYGwjo7yv19/2rPNCGfnrpH9MCj+H"
+ "irHZjhcuFFMhRgG4AD0ZSEH4Xq+d7lVL5IULENwD4BUvAHghvMJO/t4Em9G73iRrvKMg7oWY"
+ "+A/kPvZfhD3CiG0yc3YAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+Save = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAB2pJ"
+ "REFUWIXFl31wVNUVwH/3vre7yW42a9ZAMB8QjA0hoZSaGhSQIsjnEGiFWOugDqOlY/+xM7UD"
+ "rf2gHafWkXHGP9qZUmf6h9NOdbCOLS2VDtFCizpolaAdIKABA6SLJpvNvpfd9969t3+EfU0C"
+ "SB3p9Myceffr3fPbc849dx/8n0VcacHMtY93aCM2SWEWg4gicIzSBzDiub49W1/7nwHUr3wy"
+ "bdvebxLx2IJ5bY2J6dOq5DWV5QSBon9gSL9xpK+QGcq/rfDv7N/9vTNXFaBu9eP1EWn2t8+Z"
+ "kZs/t6lKSDE9YltYEiwpkVIgBBw5fkbt2X8kXwzMrf1/2nbkqgC0dW2P5vOxVxa1N50DUX82"
+ "MzzNitiV06elK+e21ElLSoqeQhtDPGYz8GGOX+9+PaM9f96plx4590kBrMkD8cYVD11blVh4"
+ "LpNr6e3P7B/Kuo8ODTsv9J05X37s5LmZNzTWROyIRdFT5As+6VScZKKs/L3+oeuzvX957lN5"
+ "oL7ryXIrX+y2LDHHN3rNB3/87oHx842rfnpXujrxy3vXL6gYGikSKI0xhpp0gl89fyD34fDo"
+ "ok8aCjm+Y40U5hlhTgda3THZOEDfn7f9dnBw9PfH+zLKtiR+oCn6GmfU5/OtjQkLs/mTGIdJ"
+ "Hpix5tEN2oiWmyveftYY84tIJLLEsqwJkMN+nNFrbmT54nYGBvMEaiwXyqKSZ198mS9UHsMY"
+ "E65XSinf9593XffePXv2FCcD2OM7WlunpQ7+obX+2aZNm5Z2dnYipQw3NMaQd4vctuVppAQv"
+ "0GhtGBn1qUmnkHacnTt3YowZr9YzzzxzZ3d39xvAEx8LUPT16flNH4yIQTF/xYoV/OGVHr75"
+ "5EsXuc22JUIIPF+htUEbQyxi4RQ8Zm98asLaL32xmYe6VtPd3f0AsAMwE/Ya38nse+Rf0Ws2"
+ "fHXZ7benLcuiY3YN379/EU+/2MPShZ+lvCyKJQW2JRGA52u0MWhtMAK2bVmNlAJj4PXD73Nu"
+ "4Dzf+PJcUqkUbW1tzUKIpbt27dp3WYALcv+qVavI5/P4vs/KjkYygy67D/6T225pI5MdxS0E"
+ "GAzGjIXFLQa88NcTuMWA9uYaAq/AkaN9/PxbS9EqwHEcli9fzrvvvvt1YALAhATbsGHD9VOn"
+ "Tl1aV1eH4zjYto1t22xeO5cbm6t59a1jTK0qRxlDNl9k4COH984Oc+Z8nmy+SFNtijIb/v7m"
+ "MR57cDHpVBwpJaOjozQ3N1NRUbF+3bp1NZcFEEI8sHHjRuG6bqmP1hqlFA/f3cG0VIxX3zpB"
+ "OllGdqRIzvVQeiyktdUVzLyukn0H3+Hbd7cz87pKjDEIITDG4Ps+y5Yti0Yikc2XBFiyZIkt"
+ "hLivvb2dfD6PbdsYY1BKEQQBKvD5web5RPE52XeGm2ZPIxoZK6SViSg3tdTw8sF36Fwwg46W"
+ "qSilwtMjpcR1XTo6OgC2bN++XV4EkE6n1yxatKg2EolQKBSQUhIEAZ7nUSwWKRaLaBXw6AM3"
+ "k8sOc3bgI+bPnka8LMKtc+t57e1e6qtj3HHrjHC953kEQYBt23ieRzKZZM6cOTMPHz684iIA"
+ "IcTXVq5cSS6XAyAIAowx4SbGGLTWRCzDjza3c/zkaQazOdbeMpPe98+Ryw7zYGcznufh+z6+"
+ "7xMEAVJKlFJorXFdl8WLF2NZ1pYJAOvWrautrq5e1dDQgOM4KKXI5/MAlJeXh8VIKYVSispy"
+ "yQ/v+RxvHu7lb2+eoOdoHw93tWAJQxAEaK0BKCsrQwhBLpdDa02hUKCpqYnKysrOrq6uuhDA"
+ "tu371q9fb7uuixAi1NHRUXzfJ5FIEI/HiUajCCGwLIva6gRb75pDz9FTbP1KG1OrEkSjUeLx"
+ "OMlkkmQyied5OI6DlBIpJZFIBKUUCxcutLXW98OFOiCEuLu9vR3XdamtrSWbzTIyMoIQgiAI"
+ "wrZlWSSTSWDs/N+cTvO7nzRQUW4jpURrjdZ6LF+0Dt+RUpJKpaiurqa/v5+Ojg727t17D/Dj"
+ "UiH6TDKZZGRkhLNnz6K1Rsqx9LAsKzSotQ7zodSP2eD7/gTPxWIxhPjPPWeMIZ/P4zgOWmum"
+ "TJmC1vqG0ANAzPM8bNsOXxx/AZWeJajLzY+fK+n4uVJuDAwMhO2wFAdBwPHjxy/aQGs9+Xa7"
+ "5Nh/uxagtrY2hA1/UokI4NChQ/T09NDb20t/fz+ZTIZsNovjOBSLxbDIlKqcMYbBwUEaGhrI"
+ "ZrM0NDQwNDTE9OnTyWazNDY2hs/JtkKA8e4qxf1ycim3T567XDgAlFIf74FYLDYh3h8HMnnz"
+ "yXOXkvG2whwoURljaG1tRSkVltCSy5VSCCEm1PkrwUweKx1tQIcAxpi+U6dONc6aNStMnFLy"
+ "lNpX0rq6OrTWtLa24nkeLS0tFAoFmpubcRyHpqYmcrkcqVSqdNSPAWU2gOu639mxY8cTUsr6"
+ "K/r9KohSqj+TyTwGREvVogy4FqgCKoEoELnKdj3GPoQKQA44D5wf/7dcAIkLWsYlvpo+pQQX"
+ "tADkLwDxb1ieXX//pNp4AAAAAElFTkSuQmCC")
+
+#----------------------------------------------------------------------
+Test = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+ "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wsdFjonjkSMtAAABKBJREFUWMPtlttvVEUc"
+ "xz8zZ053u2cvp2VXpJdIUiI3t6IxJiZCiMHwQowmGvkDePCBF40JiS8mJIbIA2o0MfggL8Zg"
+ "ucQYYsRye0CsIEgaFNFE2gKl2xTosrvd7rnM+HC2pQWqW4zRh/6SyZyc+c38vr/v7zIDC7Ig"
+ "/7GI+W4wxoiOjo6Wz/eMHFMK17IgDA1a88HaDfq9fxOA2/OZ+L2z08oq1URHu42yJEoZjAkZ"
+ "GPIYGws4+Z3+YvsO8xow3sihqkHjW6SUm59cI7JGJJEijec3g7EwgB9UaW2ZILeoxJUrbJRy"
+ "cr/W+k3g/N8dbDVg/EUhxMddXV3uyhUmlcslsKxFWMpBWnEsFUPrGFpDreZz6rQTH7q6OFEq"
+ "ldZprceAX/8JgDW2bb+7bNmyZtu2l9y6FWftsx6WlcCSEmkJLMsQak0YeAT+BNt3tCGlTLqu"
+ "K4vFYrfW+kdg5EEAuMC5pUuXOrZtLxFCMHbDRlmGFY9WkDJEykmkrOIHZXyvTM+BBBd+iaG1"
+ "RgiRchzHGh8ffwL4CpicL4DzmUzGd123UwgxVQFcvBRn5fJb5LJFpKxgyTKBV8b3J3j7nQ60"
+ "1tO6SqmkEKJaqVSWAL33MyLnLA8hkrlcrsUYw8wRBAF79zmEQQUdlsCU0brK3v0ZtNbcrZ/J"
+ "ZNqFEC/Mtwo2pdPppJQyYyJ3Zi1evOTw/Q8OpUoT8bjgqTXj9Bx86B7jAFIKVyk14fv+JuBQ"
+ "owBejsfjN4wxGQGY2Y0IIQRb3wjo6noEpRTDw5J4vEQikZg2bGaAbm1tnSwUCi/fD8CcIVBK"
+ "xaYOmhpTFI+OjpLNZqfjnc1mqVQq0+t3h0IpFctkMo2HYPeHrG9ru9bu+ZH7ok6DIfo+fKSJ"
+ "oyda8TwPz/Miyl4qsXHDjYgtE/VYUZ9tm/ajx+H9jxpMwlBHYQ98CALwPKj5UKvBRBUez4ck"
+ "mifxPI9yuUxT0wSrVwSUylCtRnqeB54Pvh+dVSerMQADg2y9PgJhEAHw6yA8D2qTIGXI5leG"
+ "CYIxSqUSzzx9E4OOjE/e0fXre4dHIB5nf8MAdu7iUBBCEEYAAj8aNa8+anD2nAO4pFIpzvc7"
+ "1GrR/1rdeFD3PggiR3buujcB/zIJb9+mIOQdBnx/xuxD35n0tO71kRiDQ7HptSndIAApoFbj"
+ "9lx25gQwOsqWajXKpzCI2AjrHp3qS80qNWMMXx7KRmwFd5gzJsoZy2L7vO+CvtP8tnoVrzoO"
+ "OSHqVGoYHIrRe7xlVp1Pt2qgo81DCLBkBOSbXvX6iZP5TwqFgj8vBrq7u9Nff9v9/B8DDN8c"
+ "B6UgDKHvTGrOy+PM2XRUQUQVMDjEyOCVVfuMNva8Q2CMkYDoPda9/vKA2jM4BLaCq9eaSuau"
+ "1jxjT6nnQOJasQijY9bBw0ceWwcIIYV4oCdZPp9/GGg2xtirll9+rtWtbNv9qcCyrIRlWfFk"
+ "Mlk1xlAulxNhGFbDMGwSQvzU2dm5LZVKjQshfClltb+/v/DAb8J8Pr/YGNNkjLHrnVMWi8V0"
+ "sVh8q1KpAOA4Dq7rHk6lUseBUAgRCIF/4cLPVxfe/Qvyv5c/AYrsfsh2c5paAAAAAElFTkSu"
+ "QmCC")
+
+#----------------------------------------------------------------------
+Undo = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAABl0"
+ "RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAXTSURBVFiFxZZ9bFV3Gcc/zznn"
+ "3t6+XZB2dRsUug6hMmSrwiKtmzjmHyWa+YckMwEGy6JzCSaaaDLHYnyZJmZGEf9xjtnRLeqm"
+ "Lr5k2XQzyGiB8aahrIxSRkuBSmnv5fb2vpyX3+Mf7b1eLpeuL0t8kie/37n3d87383t+z/Oc"
+ "I6rK/9Os2d8q0vW8fP/oMzJvLgDObG469KJEjfJHhfVjYX4yF4AZR2D/HllmjJxYtOLBey3b"
+ "ceciPmOAznbZ4DiVx5a1fru+rvHzIYU5J9C0AQ7skScj8xr+cMf6pysrqqsEZK7awDRy4G8d"
+ "UlkNv12w6L77Fzd/JaLeOwTZM1jh2/ggIKYEONguDdWO9ffFdz62pHbx+lCQOYIGl0GcD0R8"
+ "SoCuX8t9dqT6labWH1SXz6+XIH0UNUnAZuLkBBGxwzYXD7wgcYRzGvB7Mby6dquemi6AlGpE"
+ "XXvkG+XRpU8ta/1exAkFBNnToFlUs/kxVNUGZozAj+O7I7jJPhJX3nOH+//lq3Hf8DweuWeb"
+ "Ds8IYG+7RMI27QsWrn+gofmrEQ36UX8IAMUH9SYBXDAeaq4S+ENgxhCrCrvso4hTz+jgv/1L"
+ "fYcynjf6aOsmfXFaAJ3PSbUVovPWpk3Lb172QNhPHwFNki8UDQAfVQ9MEm98Lxpcv0GxPoRT"
+ "fjdq30V/958z46M9B2KjtLVt12wpgHwZtj6sYwi7Rwb3B142huXUoiYDJg0mjWoG1SwaxHCT"
+ "r5cUB1ATwxt/nSDVQWPz5yILFja3zJ/Pj6Z1BACde6TNCUdfXt76eEWkIip+5jCoDxg0SOCN"
+ "vwmaZqIKpu5DYtfgRB+i9+0/ZTLxvntbturh9wUA6OqQlWD/Y+maxxZEP3yn7Y/vw3gD+Om3"
+ "QVMARGp3gAaopkEzaDCKnzmBcU8DQf5ZdtnH8Mwa7T30XP+8CMtXbNRr2nfJTtiyWbshWNl3"
+ "ZFfPxZ7fuOLcgvHO5cUn0IXuf+7ye/Y/nzp7/C9j/+nvdX1WU1bzNezImvyyIHuSSKVK9KYl"
+ "N8XSfKlY64atuGWzXs76rLl89s3Xzh79Xdqp+iJ2ZPX/FqiH72UCdzy2LjF84cFLZ49/q/dQ"
+ "x8X3jrWnxG7CqVg3+XhDkD5CtLa+QoQV0wYAWLdVM5/cxBeSo+d2nup8Nq3WKpzK+wELNRPR"
+ "cKG3dau++qktujMeozExHPvpyc6XMr5fgV12BwAmGCFU5oglrJoRwORWde1mfdxNx7/8bmdH"
+ "KpsOEaragJpxipOwbbtmWx7SHRpknxg4uS9lhRpAwqhJ4oRA4SOzAJiwli36gvG8z545+trV"
+ "+OULZqISStuFcnamk8nziZF+FbsOwUJkHFVqZg0AsHabdnmqzYPvHj9/8fRbnqiWfCNt3KiB"
+ "Gp5JXb3iiYTBqiAzNowI78wKQCbMEhH701sY6OvhEyOD5w8bY8LdZwiJiFPgtohYxjDme2kf"
+ "DCJlJEbjWRPw12kBFAg6IhICQkA455t/SHr7z9nguuzuv0AIKCv8HwhnfaJqLEEDPNcQG0r4"
+ "ls8vr9MqbEQiIpNQOZeiebETjSKJRD4bFdC7m3B+9gQHlzTV1ZZXhYLB0yPWyEjm6c88zI8B"
+ "o6omp+kUiFtF4qVcKIJJJPLCudF8fRttldUhNxQxp4YGYvPj8cyBHbvZxcTHhExu1Kiqiqrm"
+ "dm4XiRVfF/5WCJIzA5hnv8vapqXWI3X14VQq7kZHh83J7/yCp946Tiq3ZtIDVTU5gBsJT2cu"
+ "gLl9EfaTj7KusYHVlVGy6SShcwO88c2d7Lt0CbdQODdX1aAwAqV2XSoK10Rg9Soq7vk4NXc1"
+ "cfstdSz0fcZiMYb2HuTEr17hSrFowXWQP4LJHLgRxDWJWFWFXVOD03gr4ZW3UVl7M+UVFo5n"
+ "8IcGSO7vJnHsFNkiQS0CCXRS+LrXcdFxvG8VFNg1lVAknBt9LRIs+T1QADMVQH5ZkXhuzEeg"
+ "WHTaAFNAlRKfUJ7hA/8L5wToVGBKwGEAAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+Icon = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABOVJ"
+ "REFUWIWllmtsU2UYx3/n0na9nLbboLvgLt2F4RxCDEgmJIoxaDRigiwIJn7VqAkJMTFRPxpi"
+ "CDF+wEQTEmOIMUgEIsgHox/Q6GCMyyAhJDA3xmDretu605527TmvHxYqZd3Wdk9yPpzL8///"
+ "3ue87/O+SLLCctfR748JSVY4dfac+Hvgshi4OiRKySvpkmSFYvHH+T+FpmkAaLLAUbMaNyZx"
+ "Q8chZIYnw7z0wvNS0eQyQgU49uNxEQwG8apgU1WqqqowZDseyWQmJ0jGwtx+MIWu60QiYTrb"
+ "mlAdnpV6/w+wvrsDn8PJnbM/E54I0bp7D6HQJJLq4sqVqzQ01KO5bKiqiqIoxBNpFGVugdi5"
+ "334XbS31xBJpntu8Sfrh+Anx9p6+JaukAuiGyZyZ4fbQEPcGLxFb1YjhcBF/MEZjRxdpI03a"
+ "SOeTQpOTSPJC3YDbQbXTg9NTS2hsVETTOQBO/nJG7Nr5elEQSZIVTp0+IexOPyMj/y74IBSa"
+ "YmL0Lke/O7rkSD7/4pDY/uJ2XE4XfpvE7VCCC4NDjM1k2LGxia516/DKguC6bun02V+FkU6z"
+ "d/ebUn4SHvnmW/Go4IfvvZs37KqpFq11Dbj9Gif7LxYFOXjosOjt7cWyTCzL4vyFG1y6Oc6G"
+ "jtVs29yD01mFrus01fgIBALzcyuZXHwVPB4bV/lFY0MT527cWLQSXx35Wrjdbnw+H6mUQSwa"
+ "paGpjejEHaaiswRsMs0bnqGn5yncmKRSqdIBAHqfqBeramo4c/3mssvv/bf2Cq22msb2Lqrr"
+ "67DZbciShMej4a/243K6GB8fLw+g3esRwZpa7Jp30Urs3LxJaAhSCZ3QzDT/TIakTz46IDyB"
+ "RrxeDbvdjs/nQ9O8jI6OzK+CUmM4oUsuRRJtLuei33glmJyKEEkaXAtPSQAHD39ZAPvxp5+J"
+ "xtrV7D+wXyqrAgB1LqdY6/fz14OJBRXo27heROPTRHSD69FISV2ybACAbp9fdK6px6H5+Oni"
+ "RWnf1q0CXedeeIqZTLZk84oBmt120eKrpTPYiixLpBJJ7kcjhGeT3JyZLmt/KGsOPAwjJzGT"
+ "ThKPxKiSBNFkmnA6TTSbKVtLrgQgnMlIyZxFZDbB3FwWw8ySmcsQShll744VAQA4JBU9m8ay"
+ "2cmZJsMJvaKtuWIAI5dGtSRExkCSKj8WVAzgVKtI5ixSJihyxTKVAwAoioKqWNhWILMiANM0"
+ "mZ0zVyKxMgCbKtDsCmkrV7FGyX1gYLBfRGJJAJx2wQdv9GEJlWxOWtEcKKkTDgz2i472joJn"
+ "21o7sakCv9ODYoHZWM+ufe+wtrsdgGCwdYFOLBYnkUjwysuv5ZfNshUoZp6dna+ELMvYkTGx"
+ "sCwr/37Lli0AjIxNEgqFUJg/wGZyMplYtEBrSYBi5gA2zQ1AzpSxqQLdyGKXZVzVvrw5QLC5"
+ "nmBzfQH45VuFlkUBBgb7BUAx84dCANPZLHV4UBUFj8dDW1vbUuMhbui8uuOlgq61AGCxURck"
+ "eVzs6NsNgGbliKYydG9YT0+wedGc2VSOK0O3FjwvmISlmD8MIQQ5PZX/HcvF+PAIT296dkHP"
+ "zgM8ai6EWFF/fzwikQhrO58sKpj/BUPXhojH4kUFAg0tBfdOuyh8H6hbEmAxc6jwRLRU3L0/"
+ "UUDXsqZhyVL+B0Qv7WbNxR4hAAAAAElFTkSuQmCC")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/license.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/license.txt
new file mode 100644
index 0000000..933ec7d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/license.txt
@@ -0,0 +1,23 @@
+Copyright (c) 2002, Roman Rolinsky <rollrom@users.sourceforge.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/listener.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/listener.py
new file mode 100644
index 0000000..3fbd307
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/listener.py
@@ -0,0 +1,958 @@
+# Name: listener.py
+# Purpose: Listener for dispatching events from view to presenter
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 07.06.2007
+# RCS-ID: $Id: listener.py 71790 2012-06-17 15:43:08Z ROL $
+
+import wx
+import os,sys,shutil,tempfile
+from globals import *
+from presenter import Presenter
+from component import Manager
+from model import Model
+import view
+import undo
+from generate import PythonOptions
+
+class _Listener:
+ '''
+ Installs event handlers to view objects and delegates some events
+ to Presenter.
+ '''
+ def Install(self, frame, tree, panel, toolFrame, testWin):
+ '''Set event handlers.'''
+ self.frame = frame
+ self.tree = tree
+ self.panel = panel
+ self.toolFrame = toolFrame
+ self.testWin = testWin
+ self.lastSearch = None
+
+ self.dataElem = wx.CustomDataObject('XRCED_elem')
+ self.dataNode = wx.CustomDataObject('XRCED_node')
+
+ # Some local members
+ self.inUpdateUI = self.inIdle = False
+ self.clipboardHasData = False
+
+ # Component events
+ wx.EVT_MENU_RANGE(frame, Manager.firstId, Manager.lastId,
+ self.OnComponentCreate)
+ wx.EVT_MENU_RANGE(frame, Manager.firstId + ID.SHIFT, Manager.lastId + ID.SHIFT,
+ self.OnComponentReplace)
+
+ wx.EVT_MENU(frame, ID.REF, self.OnReference)
+ wx.EVT_MENU(frame, ID.COMMENT, self.OnComment)
+
+ # Other events
+ frame.Bind(wx.EVT_IDLE, self.OnIdle)
+ frame.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+# frame.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+# wx.EVT_KEY_UP(frame, tools.OnKeyUp)
+# wx.EVT_ICONIZE(frame, self.OnIconize)
+
+ frame.Bind(wx.EVT_ACTIVATE, self.OnFrameActivate)
+ if toolFrame:
+ toolFrame.Bind(wx.EVT_ACTIVATE, self.OnFrameActivate)
+ if frame.miniFrame:
+ frame.miniFrame.Bind(wx.EVT_ACTIVATE, self.OnFrameActivate)
+
+ # Menubar events
+ # File
+ frame.Bind(wx.EVT_MENU, self.OnRecentFile, id=wx.ID_FILE1, id2=wx.ID_FILE9)
+ wx.EVT_MENU(frame, wx.ID_NEW, self.OnNew)
+ wx.EVT_MENU(frame, wx.ID_OPEN, self.OnOpen)
+ wx.EVT_MENU(frame, wx.ID_SAVE, self.OnSaveOrSaveAs)
+ wx.EVT_MENU(frame, wx.ID_SAVEAS, self.OnSaveOrSaveAs)
+ wx.EVT_MENU(frame, frame.ID_GENERATE_PYTHON, self.OnGeneratePython)
+ wx.EVT_MENU(frame, wx.ID_PREFERENCES, self.OnPrefs)
+ wx.EVT_MENU(frame, wx.ID_EXIT, self.OnExit)
+ if frame.miniFrame:
+ wx.EVT_MENU(frame.miniFrame, wx.ID_EXIT, self.OnExit)
+
+ # Edit
+ wx.EVT_MENU(frame, wx.ID_UNDO, self.OnUndo)
+ wx.EVT_MENU(frame, wx.ID_REDO, self.OnRedo)
+ wx.EVT_MENU(frame, wx.ID_CUT, self.OnCut)
+ wx.EVT_MENU(frame, wx.ID_COPY, self.OnCopy)
+ wx.EVT_MENU(frame, wx.ID_PASTE, self.OnMenuPaste)
+ wx.EVT_MENU(frame, ID.PASTE, self.OnCmdPaste)
+ wx.EVT_MENU(frame, ID.PASTE_SIBLING, self.OnPasteSibling)
+ wx.EVT_MENU(frame, wx.ID_DELETE, self.OnDelete)
+ wx.EVT_MENU(frame, frame.ID_UNSELECT, self.OnUnselect)
+ wx.EVT_MENU(frame, frame.ID_TOOL_PASTE, self.OnToolPaste)
+ wx.EVT_MENU(frame, wx.ID_FIND, self.OnFind)
+ wx.EVT_MENU(frame, frame.ID_FINDAGAIN, self.OnFindAgain)
+ wx.EVT_MENU(frame, frame.ID_LOCATE, self.OnLocate)
+ wx.EVT_MENU(frame, frame.ID_TOOL_LOCATE, self.OnLocate)
+ # View
+ wx.EVT_MENU(frame, frame.ID_EMBED_PANEL, self.OnEmbedPanel)
+ wx.EVT_MENU(frame, frame.ID_SHOW_TOOLS, self.OnShowTools)
+ wx.EVT_MENU(frame, frame.ID_TEST, self.OnTest)
+ wx.EVT_MENU(frame, wx.ID_REFRESH, self.OnRefresh)
+ wx.EVT_MENU(frame, frame.ID_AUTO_REFRESH, self.OnAutoRefresh)
+ wx.EVT_MENU(frame, frame.ID_TEST_HIDE, self.OnTestHide)
+ wx.EVT_MENU(frame, frame.ID_SHOW_XML, self.OnShowXML)
+ # Move
+ wx.EVT_MENU(frame, frame.ID_MOVEUP, self.OnMoveUp)
+ wx.EVT_MENU(frame, frame.ID_MOVEDOWN, self.OnMoveDown)
+ wx.EVT_MENU(frame, frame.ID_MOVELEFT, self.OnMoveLeft)
+ wx.EVT_MENU(frame, frame.ID_MOVERIGHT, self.OnMoveRight)
+ # Help
+ wx.EVT_MENU(frame, wx.ID_ABOUT, self.OnHelpAbout)
+ wx.EVT_MENU(frame, wx.ID_HELP_CONTENTS, self.OnHelpContents)
+ wx.EVT_MENU(frame, frame.ID_README, self.OnHelpReadme)
+ if get_debug():
+ wx.EVT_MENU(frame, frame.ID_DEBUG_CMD, self.OnDebugCMD)
+
+ # Pulldown menu commands
+ wx.EVT_MENU(frame, ID.SUBCLASS, self.OnSubclass)
+ wx.EVT_MENU(frame, ID.COLLAPSE, self.OnCollapse)
+ wx.EVT_MENU(frame, ID.COLLAPSE_ALL, self.OnCollapseAll)
+ wx.EVT_MENU(frame, ID.EXPAND, self.OnExpand)
+
+ # Update events
+ wx.EVT_UPDATE_UI(frame, wx.ID_SAVE, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, wx.ID_CUT, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, wx.ID_COPY, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, wx.ID_PASTE, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, wx.ID_DELETE, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, frame.ID_LOCATE, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, frame.ID_FINDAGAIN, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, frame.ID_TOOL_LOCATE, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, frame.ID_TOOL_PASTE, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, wx.ID_UNDO, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, wx.ID_REDO, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, frame.ID_TEST, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, frame.ID_MOVEUP, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, frame.ID_MOVEDOWN, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, frame.ID_MOVELEFT, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, frame.ID_MOVERIGHT, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, wx.ID_REFRESH, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, frame.ID_SHOW_XML, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, ID.COLLAPSE, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, ID.EXPAND, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(frame, ID.SUBCLASS, self.OnUpdateUI)
+
+ wx.EVT_MENU_HIGHLIGHT_ALL(self.frame, self.OnMenuHighlight)
+
+ # XMLTree events
+ tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
+ tree.Bind(wx.EVT_RIGHT_DOWN, self.OnTreeRightDown)
+ tree.Bind(wx.EVT_TREE_SEL_CHANGING, self.OnTreeSelChanging)
+ tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTreeSelChanged)
+ tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnTreeItemCollapsed)
+
+ # AttributePanel events
+ panel.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPanelPageChanging)
+ panel.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPanelPageChanged)
+ panel.pinButton.Bind(wx.EVT_BUTTON, self.OnPanelTogglePin)
+
+ # Make important keys work when focus is in the panel frame
+ self.accels = wx.AcceleratorTable([
+ (wx.ACCEL_NORMAL, wx.WXK_F5, frame.ID_TEST),
+ (wx.ACCEL_NORMAL, wx.WXK_F6, frame.ID_TEST_HIDE),
+ (wx.ACCEL_CTRL, ord('r'), wx.ID_REFRESH),
+ ])
+ if frame.miniFrame:
+ self.frame.miniFrame.SetAcceleratorTable(self.accels)
+ # Propagate all menu commands to the frame
+ self.frame.miniFrame.Bind(wx.EVT_MENU, lambda evt: frame.ProcessEvent(evt))
+
+ # Tool panel events
+ toolPanel = g.toolPanel
+ toolPanel.tp.Bind(wx.EVT_TOOLBOOK_PAGE_CHANGED, self.OnToolPanelPageChanged)
+ wx.EVT_COMMAND_RANGE(toolPanel.tp, Manager.firstId, Manager.lastId,
+ wx.wxEVT_COMMAND_BUTTON_CLICKED,
+ self.OnComponentTool)
+ if toolFrame:
+ toolFrame.Bind(wx.EVT_CLOSE, self.OnCloseToolFrame)
+
+ def InstallTestWinEvents(self):
+ self.idleAfterSizeBound = False
+ frame = self.testWin.GetFrame()
+ frame.Bind(wx.EVT_CLOSE, self.OnCloseTestWin)
+ frame.Bind(wx.EVT_SIZE, self.OnSizeTestWin)
+ frame.SetAcceleratorTable(self.accels)
+ frame.Bind(wx.EVT_MENU, self.OnTestWinEvent)
+ frame.Bind(wx.EVT_BUTTON, self.OnTestWinEvent)
+
+ def OnTestWinEvent(self, evt):
+ TRACE('Test window event: %s', evt)
+
+ def Uninstall(self):
+ '''Unbind some event before destroying.'''
+ self.frame.Unbind(wx.EVT_IDLE)
+
+ def OnComponentCreate(self, evt):
+ '''Hadnler for creating new elements.'''
+ state = self.tree.GetFullState() # state just before
+ comp = Manager.findById(evt.GetId())
+ if comp.groups[0] == 'component':
+ node = Model.createComponentNode('Component')
+ item = Presenter.create(comp, node)
+ else:
+ item = Presenter.create(comp)
+ itemIndex = self.tree.ItemFullIndex(item)
+ g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, state))
+
+ def OnComponentReplace(self, evt):
+ '''Hadnler for creating new elements.'''
+ comp = Manager.findById(evt.GetId() - ID.SHIFT)
+ item = self.tree.GetSelection()
+ index = self.tree.ItemFullIndex(item)
+ oldComp = Presenter.comp
+ oldNode = Presenter.replace(comp)
+ g.undoMan.RegisterUndo(undo.UndoReplace(index, oldComp, oldNode))
+
+ def OnReference(self, evt):
+ '''Create reference to an existing object.'''
+ ref = wx.GetTextFromUser('Create reference to:', 'Create reference')
+ if not ref: return
+ Presenter.createRef(ref)
+
+ def OnComment(self, evt):
+ '''Create comment node.'''
+ Presenter.createComment()
+
+ def OnNew(self, evt):
+ '''wx.ID_NEW hadndler.'''
+ if not self.AskSave(): return
+ if self.testWin.IsShown(): self.testWin.Destroy()
+ Presenter.init()
+
+ def OnOpen(self, evt):
+ '''wx.ID_OPEN handler.'''
+ if not self.AskSave(): return
+ exts = 'XRC files (*.xrc)|*.xrc'
+ if g.useMeta: exts += '|CRX files (*.crx)|*.crx'
+ dlg = wx.FileDialog(self.frame, 'Open', os.path.dirname(Presenter.path),
+ '', exts, wx.OPEN | wx.CHANGE_DIR)
+ if dlg.ShowModal() == wx.ID_OK:
+ if self.testWin.IsShown(): self.testWin.Destroy()
+ # Clear old undo data
+ g.undoMan.Clear()
+ path = dlg.GetPath()
+ wx.BeginBusyCursor()
+ try:
+ Presenter.open(path)
+ self.frame.SetStatusText('Data loaded')
+ self.SaveRecent(path)
+ finally:
+ wx.EndBusyCursor()
+ dlg.Destroy()
+
+ def OnRecentFile(self, evt):
+ '''wx.ID_FILE<n> handler.'''
+ if not self.AskSave(): return
+
+ # get the pathname based on the menu ID
+ fileNum = evt.GetId() - wx.ID_FILE1
+ path = g.fileHistory.GetHistoryFile(fileNum)
+
+ wx.BeginBusyCursor()
+ try:
+ if self.testWin.IsShown(): self.testWin.Destroy()
+ Presenter.open(path)
+ self.frame.SetStatusText('Data loaded')
+ # add it back to the history so it will be moved up the list
+ self.SaveRecent(path)
+ finally:
+ wx.EndBusyCursor()
+
+ def OnSaveOrSaveAs(self, evt):
+ '''wx.ID_SAVE and wx.ID_SAVEAS handler'''
+ path = Presenter.path
+ if evt.GetId() == wx.ID_SAVEAS or not path:
+ dirname = os.path.abspath(os.path.dirname(path))
+ exts = 'XRC files (*.xrc)|*.xrc'
+ if g.useMeta: exts += '|CRX files (*.crx)|*.crx'
+ dlg = wx.FileDialog(self.frame, 'Save As', dirname, '', exts,
+ wx.SAVE | wx.OVERWRITE_PROMPT | wx.CHANGE_DIR)
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ if isinstance(path, unicode):
+ path = path.encode(sys.getfilesystemencoding())
+ if not os.path.splitext(path)[1]:
+ if g.useMeta:
+ path += '.crx'
+ else:
+ path += '.xrc'
+ dlg.Destroy()
+ else:
+ dlg.Destroy()
+ return
+
+ if g.conf.localconf:
+ # if we already have a localconf then it needs to be
+ # copied to a new config with the new name
+ lc = g.conf.localconf
+ nc = Presenter.createLocalConf(path)
+ flag, key, idx = lc.GetFirstEntry()
+ while flag:
+ nc.Write(key, lc.Read(key))
+ flag, key, idx = lc.GetNextEntry(idx)
+ g.conf.localconf = nc
+ else:
+ # otherwise create a new one
+ g.conf.localconf = Presenter.createLocalConf(path)
+ wx.BeginBusyCursor()
+ try:
+ Presenter.save(path) # save temporary file first
+ if g.conf.localconf.ReadBool("autogenerate", False):
+ pypath = g.conf.localconf.Read("filename")
+ embed = g.conf.localconf.ReadBool("embedResource", False)
+ genGettext = g.conf.localconf.ReadBool("genGettext", False)
+ Presenter.generatePython(path, pypath, embed, genGettext)
+ self.frame.SetStatusText('Data saved')
+ self.SaveRecent(path)
+ finally:
+ wx.EndBusyCursor()
+
+ def OnPrefs(self, evt):
+ self.frame.ShowPrefs()
+
+ def OnExit(self, evt):
+ '''wx.ID_EXIT handler'''
+ self.frame.Close()
+
+ def OnGeneratePython(self, evt):
+ if Presenter.modified or not g.conf.localconf:
+ wx.MessageBox("Save the XRC file first!", "Error")
+ return
+
+ dlg = PythonOptions(view.frame, g.conf.localconf, Presenter.path)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+ def SaveRecent(self, path):
+ '''Append path to recently used files.'''
+ g.fileHistory.AddFileToHistory(path)
+
+ def AskSave(self):
+ '''Show confirmation dialog.'''
+ if not Presenter.modified: return True
+ flags = wx.ICON_EXCLAMATION | wx.YES_NO | wx.CANCEL | wx.CENTRE
+ dlg = wx.MessageDialog(self.frame, 'File is modified. Save before exit?',
+ 'Save before too late?', flags)
+ say = dlg.ShowModal()
+ dlg.Destroy()
+ wx.Yield()
+ if say == wx.ID_YES:
+ self.OnSaveOrSaveAs(wx.CommandEvent(wx.EVT_MENU.typeId, wx.ID_SAVE))
+ # If save was successful, modified flag is unset
+ if not Presenter.modified: return True
+ elif say == wx.ID_NO:
+ Presenter.setModified(False)
+ return True
+ return False
+
+ def OnCloseWindow(self, evt):
+ '''wx.EVT_CLOSE handler'''
+ if not self.AskSave(): return
+ if self.testWin.object: self.testWin.Destroy()
+ self.panel.undo = False # prevent undo
+ g.undoMan.Clear()
+ # Remember sizes and position
+ conf = g.conf
+ if g.useAUI:
+ conf.perspective = view.frame.mgr.SavePerspective()
+ if not self.frame.IsIconized():
+ conf.pos = self.frame.GetPosition()
+ if wx.Platform == '__WXMAC__':
+ conf.size = self.frame.GetClientSize()
+ else:
+ conf.size = self.frame.GetSize()
+ if not g.useAUI:
+ if conf.embedPanel:
+ conf.sashPos = self.frame.splitter.GetSashPosition()
+ else:
+ if self.frame.miniFrame:
+ conf.panelPos = self.frame.miniFrame.GetPosition()
+ conf.panelSize = self.frame.miniFrame.GetSize()
+ if conf.showToolPanel and self.toolFrame:
+ conf.toolPanelPos = self.toolFrame.GetPosition()
+ conf.toolPanelSize = self.toolFrame.GetSize()
+ #self.tree.UnselectAll()
+ g.undoMan.Clear()
+ #self.panel.Destroy() # destroy panel before tree
+ self.Uninstall()
+ self.frame.Destroy()
+
+ def OnUndo(self, evt):
+ if g.undoMan.CanUndo():
+ g.undoMan.Undo()
+
+ def OnRedo(self, evt):
+ if g.undoMan.CanRedo():
+ g.undoMan.Redo()
+
+ def OnCut(self, evt):
+ '''wx.ID_CUT handler.'''
+ item = self.tree.GetSelection()
+ index = self.tree.ItemFullIndex(item)
+ state = self.tree.GetFullState()
+ node = Presenter.cut()
+ g.undoMan.RegisterUndo(undo.UndoCutDelete(index, state, node))
+
+ def OnDelete(self, evt):
+ '''wx.ID_DELETE handler.'''
+ if len(self.tree.GetSelections()) == 1:
+ item = self.tree.GetSelection()
+ index = self.tree.ItemFullIndex(item)
+ state = self.tree.GetFullState()
+ node = Presenter.delete(self.tree.GetSelection())
+ g.undoMan.RegisterUndo(undo.UndoCutDelete(index, state, node))
+ else:
+ # Save all if multiselection
+ g.undoMan.RegisterUndo(undo.UndoGlobal())
+ Presenter.deleteMany(self.tree.GetSelections())
+
+ def OnCopy(self, evt):
+ '''wx.ID_COPY handler.'''
+ Presenter.copy()
+
+ def OnMenuPaste(self, evt):
+ '''wx.ID_PASTE handler (for XMLTreeMenu).'''
+ state = self.tree.GetFullState() # state just before
+ item = Presenter.paste()
+ if not item: return # error in paste()
+ itemIndex = self.tree.ItemFullIndex(item)
+ g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, state))
+
+ def OnCmdPaste(self, evt):
+ '''ID.PASTE handler (for Edit menu and shortcuts).'''
+ TRACE('OnCmdPaste')
+ state = wx.GetMouseState()
+ forceSibling = state.AltDown()
+ forceInsert = state.ShiftDown()
+ g.Presenter.updateCreateState(forceSibling, forceInsert)
+ state = self.tree.GetFullState() # state just before
+ item = Presenter.paste()
+ if not item: return # error in paste()
+ itemIndex = self.tree.ItemFullIndex(item)
+ g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, state))
+
+ def OnToolPaste(self, evt):
+ '''frame.ID_TOOL_PASTE handler.'''
+ state = wx.GetMouseState()
+ # Ctrl+click does not work with tools on Mac, Alt+click often
+ # bound to window move on wxGTK
+ if wx.Platform == '__WXMAC__':
+ forceSibling = state.AltDown()
+ else:
+ forceSibling = state.ControlDown()
+ forceInsert = state.ShiftDown()
+ g.Presenter.updateCreateState(forceSibling, forceInsert)
+ treeState = self.tree.GetFullState() # state just before
+ item = Presenter.paste()
+ if not item: return # error in paste()
+ itemIndex = self.tree.ItemFullIndex(item)
+ g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, treeState))
+
+ def OnPasteSibling(self, evt):
+ '''ID.PASTE_SIBLING handler.'''
+ forceSibling = True
+ state = wx.GetMouseState()
+ forceInsert = state.ShiftDown()
+ g.Presenter.updateCreateState(forceSibling, forceInsert)
+ treeState = self.tree.GetFullState() # state just before
+ item = Presenter.paste()
+ itemIndex = self.tree.ItemFullIndex(item)
+ g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, treeState))
+
+ def OnUnselect(self, evt):
+ self.tree.UnselectAll()
+ if not Presenter.applied: Presenter.update()
+ Presenter.setData(self.tree.root)
+
+ def OnMoveUp(self, evt):
+ self.inIdle = True
+ g.undoMan.RegisterUndo(undo.UndoGlobal())
+ Presenter.moveUp()
+ self.inIdle = False
+
+ def OnMoveDown(self, evt):
+ self.inIdle = True
+ g.undoMan.RegisterUndo(undo.UndoGlobal())
+ Presenter.moveDown()
+ self.inIdle = False
+
+ def OnMoveLeft(self, evt):
+ self.inIdle = True
+ g.undoMan.RegisterUndo(undo.UndoGlobal())
+ Presenter.moveLeft()
+ self.inIdle = False
+
+ def OnMoveRight(self, evt):
+ self.inIdle = True
+ g.undoMan.RegisterUndo(undo.UndoGlobal())
+ Presenter.moveRight()
+ self.inIdle = False
+
+ def OnFind(self, evt):
+ name = wx.GetTextFromUser('Find name:', caption='Find')
+ if not name: return
+ self.lastSearch = name
+ self.frame.SetStatusText('Looking for "%s"' % name)
+ if Presenter.item == self.tree.root:
+ item = self.tree.Find(self.tree.root, name)
+ else:
+ # Find from current position
+ item = Presenter.item
+ while item:
+ found = self.tree.Find(item, name)
+ if found:
+ item = found
+ break
+ # Search the rest of the current subtree, then go up
+ next = self.tree.GetNextSibling(item)
+ while not next:
+ next = self.tree.GetItemParent(item)
+ if next == self.tree.root:
+ next = None
+ break
+ item = next
+ next = self.tree.GetNextSibling(next)
+ item = next
+ if not item:
+ ask = wx.MessageBox('Search failed. Search from the root?',
+ 'Question', wx.YES_NO)
+ if ask == wx.YES:
+ item = self.tree.Find(self.tree.root, name)
+ else:
+ self.frame.SetStatusText('')
+ return
+ if not item:
+ self.frame.SetStatusText('Search failed')
+ wx.LogError('No such name')
+ return
+ self.frame.SetStatusText('Search succeded')
+ Presenter.unselect()
+ self.tree.EnsureVisible(item)
+ self.tree.SelectItem(item)
+
+ def OnFindAgain(self, evt):
+ self.frame.SetStatusText('Looking for "%s"' % self.lastSearch)
+ if Presenter.item == self.tree.root:
+ item = self.tree.Find(self.tree.root, self.lastSearch)
+ else:
+ # Find from current position
+ item = Presenter.item
+ while item:
+ # Search the rest of the current subtree, then go up
+ next = self.tree.GetNextSibling(item)
+ while not next:
+ next = self.tree.GetItemParent(item)
+ if next == self.tree.root:
+ next = None
+ break
+ item = next
+ next = self.tree.GetNextSibling(next)
+ item = next
+ if item:
+ found = self.tree.Find(item, self.lastSearch)
+ if found:
+ item = found
+ break
+ if not item:
+ ask = wx.MessageBox('Search failed. Search from the root?',
+ 'Question', wx.YES_NO)
+ if ask == wx.YES:
+ item = self.tree.Find(self.tree.root, name)
+ if not item:
+ self.frame.SetStatusText('Search failed')
+ wx.LogError('Search from the root failed.')
+ return
+ else:
+ self.frame.SetStatusText('')
+ return
+ self.lastFoundItem = item
+ self.frame.SetStatusText('Search succeded')
+ Presenter.unselect()
+ self.tree.EnsureVisible(item)
+ self.tree.SelectItem(item)
+
+ def OnLocate(self, evt):
+ frame = self.testWin.GetFrame()
+ frame.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDownTestWin)
+ frame.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLostTestWin)
+ frame.CaptureMouse()
+ wx.SetCursor(wx.CROSS_CURSOR)
+
+ def OnRefresh(self, evt):
+ if self.testWin.IsShown():
+ self.testWin.isDirty = True
+ Presenter.refreshTestWin()
+
+ def OnAutoRefresh(self, evt):
+ g.conf.autoRefresh = evt.IsChecked()
+ self.frame.menuBar.Check(self.frame.ID_AUTO_REFRESH, g.conf.autoRefresh)
+ if g.conf.embedPanel:
+ self.frame.tb.ToggleTool(self.frame.ID_AUTO_REFRESH, g.conf.autoRefresh)
+ else:
+ self.frame.miniFrame.tb.ToggleTool(self.frame.ID_AUTO_REFRESH, g.conf.autoRefresh)
+
+ def OnHelpAbout(self, evt):
+ str = '''\
+XRCed version %s
+
+(c) Roman Rolinsky <rollrom@users.sourceforge.net>
+Homepage: http://xrced.sourceforge.net\
+''' % version
+ dlg = wx.MessageDialog(self.frame, str, 'About XRCed', wx.OK | wx.CENTRE)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+ def OnHelpContents(self, evt):
+ self.frame.htmlCtrl.DisplayContents()
+
+ def OnHelpReadme(self, evt):
+ self.frame.ShowReadme()
+
+ # Simple emulation of python command line
+ def OnDebugCMD(self, evt):
+ while 1:
+ try:
+ exec raw_input('C:\> ')
+ except EOFError:
+ print '^D'
+ break
+ except:
+ import traceback
+ (etype, value, tb) =sys.exc_info()
+ tblist =traceback.extract_tb(tb)[1:]
+ msg =' '.join(traceback.format_exception_only(etype, value)
+ +traceback.format_list(tblist))
+ print msg
+
+ def OnEmbedPanel(self, evt):
+ self.frame.EmbedUnembed(evt.IsChecked())
+
+ def OnShowTools(self, evt):
+ conf = g.conf
+ self.toolFrame.Show()
+ conf.showToolPanel = True
+
+ def OnTest(self, evt):
+ if not Presenter.item: return
+ Presenter.createTestWin(Presenter.item)
+
+ # Test window events
+
+ def OnCloseTestWin(self, evt):
+ TRACE('OnCloseTestWin')
+ Presenter.closeTestWin()
+
+ def OnSizeTestWin(self, evt):
+ TRACE('OnSizeTestWin')
+ if view.testWin.hl and not self.idleAfterSizeBound:
+ self.idleAfterSizeBound = True
+ frame = self.testWin.GetFrame()
+ frame.Bind(wx.EVT_IDLE, self.OnIdleAfterSize)
+ evt.Skip()
+
+ def OnIdleAfterSize(self, evt):
+ frame = self.testWin.GetFrame()
+ frame.Unbind(wx.EVT_IDLE)
+ self.idleAfterSizeBound = False
+ TRACE('OnIdleAfterSize')
+ Presenter.highlight(Presenter.item)
+
+ def OnTestHide(self, evt):
+ Presenter.closeTestWin()
+
+ def OnCaptureLostTestWin(self, evt):
+ frame = self.testWin.GetFrame()
+ wx.SetCursor(wx.NullCursor)
+ frame.ReleaseMouse()
+ frame.Unbind(wx.EVT_LEFT_DOWN)
+ self.frame.tb.ToggleTool(view.frame.ID_TOOL_LOCATE, False)
+ self.frame.miniFrame.tb.ToggleTool(view.frame.ID_TOOL_LOCATE, False)
+
+ def OnLeftDownTestWin(self, evt):
+ frame = self.testWin.GetFrame()
+ wx.SetCursor(wx.NullCursor)
+ frame.ReleaseMouse()
+ frame.Unbind(wx.EVT_LEFT_DOWN)
+ self.frame.tb.ToggleTool(view.frame.ID_TOOL_LOCATE, False)
+ self.frame.miniFrame.tb.ToggleTool(view.frame.ID_TOOL_LOCATE, False)
+
+ scrPos = view.testWin.object.ClientToScreen(evt.GetPosition())
+ obj = wx.FindWindowAtPoint(scrPos)
+ if not obj: return
+ item = self.testWin.FindObjectItem(self.testWin.item, obj)
+ if not item: return
+ # If window has a sizer use it as parent
+ if obj.GetSizer():
+ obj = obj.GetSizer()
+ item = self.testWin.FindObjectItem(self.testWin.item, obj)
+ Presenter.unselect()
+ self.tree.EnsureVisible(item)
+ self.tree.SelectItem(item)
+
+ def OnShowXML(self, evt):
+ Presenter.showXML()
+
+ def OnMenuHighlight(self, evt):
+ menuId = evt.GetMenuId()
+ if menuId != -1:
+ menu = evt.GetEventObject()
+ try:
+ help = menu.GetHelpString(menuId)
+ if menuId == wx.ID_UNDO:
+ help += ' ' + g.undoMan.GetUndoLabel()
+ elif menuId == wx.ID_REDO:
+ help += ' ' + g.undoMan.GetRedoLabel()
+ self.frame.SetStatusText(help)
+ except:
+ self.frame.SetStatusText('')
+ else:
+ self.frame.SetStatusText('')
+
+ def OnUpdateUI(self, evt):
+ if self.inUpdateUI: return # Recursive call protection
+ self.inUpdateUI = True
+ container = Presenter.container
+ comp = Presenter.comp
+ treeNode = self.tree.GetPyData(Presenter.item)
+ isComment = treeNode and treeNode.nodeType == treeNode.COMMENT_NODE
+ # Wokraround for wxMSW: view.tree.GetPrevSibling crashes
+ if evt.GetId() in [self.frame.ID_MOVEUP, self.frame.ID_MOVERIGHT,
+ self.frame.ID_MOVEDOWN, self.frame.ID_MOVELEFT] and \
+ Presenter.item is view.tree.root:
+ pass
+ elif evt.GetId() in [wx.ID_CUT, wx.ID_COPY, wx.ID_DELETE]:
+ evt.Enable(bool(self.tree.GetSelection()))
+ elif evt.GetId() in [self.frame.ID_MOVEUP, self.frame.ID_MOVERIGHT]:
+ evt.Enable(view.tree.GetPrevSibling(Presenter.item).IsOk())
+ elif evt.GetId() == self.frame.ID_MOVEDOWN:
+ evt.Enable(view.tree.GetNextSibling(Presenter.item).IsOk())
+ elif evt.GetId() == self.frame.ID_MOVELEFT:
+ evt.Enable(container is not Manager.rootComponent and \
+ view.tree.GetItemParent(Presenter.item).IsOk())
+ elif evt.GetId() == wx.ID_SAVE:
+ evt.Enable(Presenter.modified)
+# elif evt.GetId() in [self.frame.ID_SHOW_XML]:
+# evt.Enable(len(self.tree.GetSelections()) == 1)
+ elif evt.GetId() in [wx.ID_PASTE, self.frame.ID_TOOL_PASTE]:
+ evt.Enable(self.clipboardHasData)
+ elif evt.GetId() in [self.frame.ID_TEST,
+ self.frame.ID_MOVEUP, self.frame.ID_MOVEDOWN,
+ self.frame.ID_MOVELEFT, self.frame.ID_MOVERIGHT]:
+ evt.Enable(bool(self.tree.GetSelection()))
+ elif evt.GetId() in [self.frame.ID_LOCATE, self.frame.ID_TOOL_LOCATE,
+ wx.ID_REFRESH]:
+ evt.Enable(self.testWin.IsShown())
+ elif evt.GetId() == self.frame.ID_FINDAGAIN:
+ evt.Enable(self.lastSearch is not None)
+ elif evt.GetId() == wx.ID_UNDO: evt.Enable(g.undoMan.CanUndo())
+ elif evt.GetId() == wx.ID_REDO: evt.Enable(g.undoMan.CanRedo())
+ elif evt.GetId() in [ID.COLLAPSE, ID.EXPAND]:
+ evt.Enable(not self.tree.GetSelection() or
+ len(self.tree.GetSelections()) == 1 and \
+ self.tree.ItemHasChildren(self.tree.GetSelection()))
+ elif evt.GetId() == ID.SUBCLASS:
+ evt.Enable(not isComment)
+ self.inUpdateUI = False
+
+ def OnIdle(self, evt):
+ if self.inIdle: return # Recursive call protection
+ self.inIdle = True
+ if not Presenter.applied:
+ item = self.tree.GetSelection()
+ if item: Presenter.update(item)
+
+ # Check clipboard
+ if not wx.TheClipboard.IsOpened():
+ self.clipboardHasData = False
+ if wx.TheClipboard.IsSupported(self.dataElem.GetFormat()):
+ self.clipboardHasData = True
+ elif wx.TheClipboard.IsSupported(self.dataNode.GetFormat()):
+ self.clipboardHasData = True
+
+ self.inIdle = False
+
+ def OnIconize(self, evt):
+ conf = g.conf
+ if evt.Iconized():
+ conf.pos = self.frame.GetPosition()
+ conf.size = self.frame.GetSize()
+ if conf.embedPanel:
+ conf.sashPos = self.frame.splitter.GetSashPosition()
+ elif self.miniFrame:
+ conf.panelPos = self.miniFrame.GetPosition()
+ conf.panelSize = self.miniFrame.GetSize()
+ self.miniFrame.Show(False)
+ else:
+ if not conf.embedPanel and self.miniFrame:
+ self.miniFrame.Show(True)
+ evt.Skip()
+
+ def OnSubclass(self, evt):
+ node = self.tree.GetPyData(Presenter.item)
+ subclass = node.getAttribute('subclass')
+ dlg = wx.TextEntryDialog(self.frame, 'Subclass:', defaultValue=subclass)
+ if dlg.ShowModal() == wx.ID_OK:
+ subclass = dlg.GetValue()
+ Presenter.subclass(Presenter.item, subclass)
+ dlg.Destroy()
+
+ # Expand/collapse subtree
+ def OnExpand(self, evt):
+ if self.tree.GetSelection():
+ map(self.tree.ExpandAllChildren, self.tree.GetSelections())
+ else:
+ self.tree.ExpandAll()
+
+ def OnCollapse(self, evt):
+ # Prevent multiple calls to setData
+ self.tree.Unbind(wx.EVT_TREE_ITEM_COLLAPSED)
+ if self.tree.GetSelection():
+ map(self.tree.CollapseAllChildren, self.tree.GetSelections())
+ else:
+ self.tree.CollapseAll()
+ self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnTreeItemCollapsed)
+ if not self.tree.GetSelection():
+ if not Presenter.applied: Presenter.update()
+ Presenter.setData(self.tree.root)
+
+ def OnCollapseAll(self, evt):
+ # Prevent multiple calls to setData
+ self.tree.Unbind(wx.EVT_TREE_ITEM_COLLAPSED)
+ self.tree.UnselectAll()
+ self.tree.CollapseAll()
+ self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnTreeItemCollapsed)
+ if not Presenter.applied: Presenter.update()
+ Presenter.setData(self.tree.root)
+
+ #
+ # XMLTree event handlers
+ #
+
+ def OnTreeLeftDown(self, evt):
+ pt = evt.GetPosition();
+ item, flags = self.tree.HitTest(pt)
+ if flags & wx.TREE_HITTEST_NOWHERE or not item:
+ # Unselecting seems to be broken on wxGTK!!!
+ Presenter.unselect()
+ evt.Skip()
+
+ def OnTreeRightDown(self, evt):
+ if wx.Platform == '__WXMAC__':
+ forceSibling = evt.AltDown()
+ else:
+ forceSibling = evt.ControlDown()
+ forceInsert = evt.ShiftDown()
+ Presenter.popupMenu(forceSibling, forceInsert, evt.GetPosition())
+
+ def OnTreeSelChanging(self, evt):
+ #TRACE('OnTreeSelChanging: %s=>%s', evt.GetOldItem(), evt.GetItem())
+ #TRACE('Selection: %s', self.tree.GetSelections())
+ if not self.tree.GetSelections(): return
+ # Permit multiple selection for same level only
+ state = wx.GetMouseState()
+ oldItem = evt.GetOldItem()
+ if oldItem and (state.ShiftDown() or state.ControlDown()) and \
+ self.tree.GetItemParent(oldItem) != self.tree.GetItemParent(evt.GetItem()):
+ evt.Veto()
+ self.frame.SetStatusText('Veto selection (not same level)')
+ return
+ # If panel has a pending undo, register it
+ if Presenter.panelIsDirty():
+ Presenter.registerUndoEdit()
+ evt.Skip()
+
+ def OnTreeSelChanged(self, evt):
+ TRACE('OnTreeSelChanged: %s=>%s', evt.GetOldItem(), evt.GetItem())
+ TRACE('Selection: %s', self.tree.GetSelections())
+ # On wxMSW (at least) two selection events are generated
+ if not self.tree.GetSelections(): return
+ if evt.GetOldItem():
+ if not Presenter.applied:
+ Presenter.update(evt.GetOldItem())
+ # Refresh test window after finishing
+ if g.conf.autoRefresh and self.testWin.IsDirty():
+ wx.CallAfter(Presenter.refreshTestWin)
+ # Tell presenter to update current data and view
+ item = evt.GetItem()
+ if not item: item = self.tree.root
+ wx.CallAfter(Presenter.setData, item)
+ # Set initial sibling/insert modes
+ Presenter.createSibling = not Presenter.comp.isContainer()
+ Presenter.insertBefore = False
+ evt.Skip()
+
+ def OnTreeItemCollapsed(self, evt):
+ # If no selection, reset panel
+ if not self.tree.GetSelection():
+ if not Presenter.applied: Presenter.update()
+ Presenter.setData(self.tree.root)
+ evt.Skip()
+
+ def OnPanelPageChanging(self, evt):
+ TRACE('OnPanelPageChanging: %d=>%d', evt.GetOldSelection(), evt.GetSelection())
+ # Register undo if something was changed
+ i = evt.GetOldSelection()
+ if i >= 0 and Presenter.panelIsDirty():
+ g.undoMan.RegisterUndo(self.panel.undo)
+ evt.Skip()
+
+ def OnPanelPageChanged(self, evt):
+ TRACE('OnPanelPageChanged: %d=>%d', evt.GetOldSelection(), evt.GetSelection())
+ # Register new undo
+ if Presenter.panelIsDirty():
+ Presenter.createUndoEdit(page=evt.GetSelection())
+ # Refresh test window after finishing
+ if g.conf.autoRefresh and self.testWin.IsDirty():
+ wx.CallAfter(Presenter.refreshTestWin)
+ evt.Skip()
+
+ def OnPanelTogglePin(self, evt):
+ g.conf.panelPinState = evt.GetIsDown()
+ evt.Skip()
+
+ # Tool panel
+
+ def OnToolPanelPageChanged(self, evt):
+ TRACE('OnToolPanelPageChanged: %d > %d', evt.GetOldSelection(), evt.GetSelection())
+ # Update tool frame (if exists)
+ panel = g.toolPanel.panels[evt.GetSelection()]
+ if self.toolFrame:
+ self.toolFrame.SetTitle(panel.name)
+ evt.Skip()
+
+ def OnComponentTool(self, evt):
+ '''Hadnler for creating new elements.'''
+ comp = Manager.findById(evt.GetId())
+ # Check compatibility
+ if Presenter.checkCompatibility(comp):
+ state = self.tree.GetFullState() # state just before
+ if comp.groups[0] == 'component':
+ node = Model.createComponentNode('Component')
+ item = Presenter.create(comp, node)
+ else:
+ item = Presenter.create(comp)
+ itemIndex = self.tree.ItemFullIndex(item)
+ g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, state))
+ evt.Skip()
+
+ def OnCloseToolFrame(self, evt):
+ '''wx.EVT_CLOSE handler'''
+ conf = g.conf
+ if not self.toolFrame.IsIconized():
+ if conf.showToolPanel:
+ conf.toolPanelPos = self.toolFrame.GetPosition()
+ conf.toolPanelSize = self.toolFrame.GetSize()
+ self.toolFrame.Show(False)
+ conf.showToolPanel = False
+
+ def OnFrameActivate(self, evt):
+ if evt.GetActive():
+ TRACE('Setting active frame')
+ g.lastActiveFrame = evt.GetEventObject()
+ evt.Skip()
+
+
+# Singleton class
+Listener = g.Listener = _Listener()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/meta.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/meta.py
new file mode 100644
index 0000000..7bafd26
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/meta.py
@@ -0,0 +1,40 @@
+# Name: meta.py
+# Purpose:
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 05.07.2007
+# RCS-ID: $Id: core.py 47129 2007-07-04 22:38:37Z ROL $
+
+from globals import *
+import component
+from attribute import *
+import params
+
+# Meta-components for loading CRX files
+
+Component = component.SimpleComponent(
+ 'Component', ['component'],
+ ['provider', 'version', 'url',
+ 'groups', 'attributes', 'params', 'has-name', 'styles', 'events',
+ 'DL', 'module', 'handler',
+ 'menu', 'label', 'help', 'index', 'panel', 'pos', 'span'],
+ specials={'provider': AttributeAttribute,
+ 'version': AttributeAttribute,
+ 'url': AttributeAttribute,
+ 'groups': ContentAttribute,
+ 'attributes': ContentAttribute,
+ 'params': ContentAttribute,
+ 'styles': ContentAttribute,
+ 'events': ContentAttribute},
+ params={'provider': params.ParamLongText,
+ 'url': params.ParamLongText,
+ 'groups': params.ParamContent,
+ 'attributes': params.ParamContent,
+ 'params': params.ParamContent,
+ 'styles': params.ParamContent,
+ 'events': params.ParamContent,
+ 'has-name': params.ParamBool,
+ 'handler': params.ParamLongText,
+ 'index': params.ParamInt,
+ 'pos': params.ParamPosSize,
+ 'span': params.ParamPosSize})
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/test.xrc b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/test.xrc
new file mode 100644
index 0000000..3def8aa
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/test.xrc
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resource>
+ <object class="wxFrame">
+ <object class="wxMenuBar">
+ <object class="wxMenu" name="MENU">
+ <label>Menu</label>
+ <help>Help</help>
+ <object class="wxMenuItem">
+ <label>Menu Item</label>
+ <bitmap/>
+ <help>Help on Item</help>
+ <checkable>1</checkable>
+ </object>
+ <object class="separator"/>
+ <object class="wxMenuItem">
+ <label>Another Item</label>
+ <bitmap stock_id="wxART_GO_HOME"/>
+ </object>
+ </object>
+ </object>
+ <object class="wxToolBar">
+ <object class="tool">
+ <bitmap stock_id="wxART_CDROM"/>
+ <bitmap2/>
+ <tooltip>tool tip</tooltip>
+ <longhelp>tool long help</longhelp>
+ <label>tool label</label>
+ </object>
+ <object class="separator"/>
+ <object class="wxTextCtrl">
+ <size>200,-1</size>
+ <value>TextCtrl inside ToolBar</value>
+ </object>
+ </object>
+ <object class="wxStatusBar">
+ <fields>1</fields>
+ </object>
+ <object class="wxPanel" name="PANEL">
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <label>This is a label</label>
+ <fg>#FF0000</fg>
+ <bg>#1E90FF</bg>
+ </object>
+ <option>2</option>
+ <flag>wxALL|wxALIGN_CENTRE_VERTICAL</flag>
+ <border>10</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxChoice">
+ <content>
+ <item>choice 1</item>
+ <item>choice 2</item>
+ </content>
+ <selection>0</selection>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>0</border>
+ </object>
+ </object>
+ </object>
+ <title>Test Frame</title>
+ </object>
+
+</resource> \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/test_wxlib.xrc b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/test_wxlib.xrc
new file mode 100644
index 0000000..6efce85
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/test_wxlib.xrc
@@ -0,0 +1,19 @@
+<?xml version="1.0" ?>
+<resource>
+ <object class="wxFrame">
+ <object class="FoldPanelBar">
+ <object class="foldpanel">
+ <object class="wxPanel">
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxButton">
+ <label>butter</label>
+ </object>
+ </object>
+ </object>
+ </object>
+ <label>label</label>
+ </object>
+ </object>
+ </object>
+</resource> \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/tools.xrc b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/tools.xrc
new file mode 100644
index 0000000..45562df
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/misc/tools.xrc
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resource>
+ <object class="wxFrame" name="FRAME_Panels">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxGridBagSizer">
+ <object class="sizeritem">
+ <object class="wxListBox">
+ <size>40,36d</size>
+ <content>
+ <item>Item 1</item>
+ <item>Item 2</item>
+ <item>Item 3</item>
+ <item>Item 4</item>
+ <item>Item 5</item>
+ </content>
+ </object>
+ <option>0</option>
+ <cellpos>0,0</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxListCtrl">
+ <size>40,36d</size>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <cellpos>0,1</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxTreeCtrl">
+ <size>50,36d</size>
+ <style>wxSUNKEN_BORDER</style>
+ </object>
+ <cellpos>0,2</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxPanel" name="wxStaticBox">
+ <size>40,30d</size>
+ <object class="wxStaticBox">
+ <pos>2,2d</pos>
+ <size>36,26d</size>
+ <label>StaticBox</label>
+ </object>
+ </object>
+ <option>0</option>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>14</border>
+ <cellpos>2,0</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxGrid" name="wxGrid_bad">
+ <size>80,30d</size>
+ </object>
+ <option>0</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>8</border>
+ <cellpos>2,1</cellpos>
+ <cellspan>1,2</cellspan>
+ </object>
+ <object class="sizeritem">
+ <object class="wxNotebook">
+ <object class="notebookpage">
+ <object class="wxPanel"/>
+ <label>page1</label>
+ </object>
+ <size>40,30d</size>
+ </object>
+ <cellpos>1,0</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxListbook">
+ <object class="listbookpage">
+ <object class="wxPanel">
+ <bg>#FFFFFF</bg>
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <size>-1,30d</size>
+ <label>list
+book</label>
+ </object>
+ </object>
+ </object>
+ </object>
+ <label>Item1</label>
+ <bitmap>src-images/ListbookPage.png</bitmap>
+ </object>
+ <size>40,30d</size>
+ <style>wxLB_LEFT</style>
+ </object>
+ <cellpos>0,3</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxTreebook">
+ <object class="treebookpage">
+ <object class="wxPanel">
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <size>35,35d</size>
+ <label>tree
+book</label>
+ </object>
+ <option>1</option>
+ </object>
+ </object>
+ <size>35,35d</size>
+ <bg>#FFFFFF</bg>
+ </object>
+ <label>Item1</label>
+ </object>
+ <object class="treebookpage">
+ <object class="wxPanel">
+ <bg>#BFBFBF</bg>
+ </object>
+ <label>Item2</label>
+ <depth>1</depth>
+ </object>
+ <size>85,35d</size>
+ </object>
+ <cellpos>1,1</cellpos>
+ <cellspan>1,2</cellspan>
+ </object>
+ <object class="sizeritem">
+ <object class="wxChoicebook">
+ <object class="choicebookpage">
+ <object class="wxPanel">
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <size>40,-1d</size>
+ <label>choice
+book</label>
+ </object>
+ </object>
+ </object>
+ <size>40,40</size>
+ <bg>#FFFFFF</bg>
+ </object>
+ <label>Item1</label>
+ </object>
+ <size>40,30d</size>
+ </object>
+ <cellpos>1,3</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxSplitterWindow">
+ <object class="wxPanel">
+ <bg>#FFFFFF</bg>
+ <style>wxSUNKEN_BORDER</style>
+ </object>
+ <object class="wxPanel">
+ <bg>#FFFFFF</bg>
+ <style>wxSUNKEN_BORDER</style>
+ </object>
+ <size>40,30d</size>
+ <orientation>vertical</orientation>
+ <sashpos>15d</sashpos>
+ </object>
+ <flag>wxEXPAND</flag>
+ <cellpos>0,4</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxScrolledWindow">
+ <size>40,30d</size>
+ <bg>#FFFFFF</bg>
+ </object>
+ <cellpos>1,4</cellpos>
+ </object>
+ <vgap>8</vgap>
+ <hgap>8</hgap>
+ <growablecols/>
+ <growablerows/>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ </object>
+ </object>
+ <title/>
+ </object>
+ <object class="wxFrame" name="FRAME_Controls">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxFlexGridSizer">
+ <object class="sizeritem">
+ <object class="wxPanel" name="wxStaticText">
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <label>StaticText</label>
+ </object>
+ <flag>wxALL|wxALIGN_CENTRE</flag>
+ <border>3</border>
+ </object>
+ </object>
+ <pos>40,-1d</pos>
+ </object>
+ <flag>wxALIGN_CENTRE</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton">
+ <size>40,-1d</size>
+ <label>Button</label>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxTextCtrl"/>
+ </object>
+ <object class="sizeritem">
+ <object class="wxPanel" name="wxStaticLine">
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxStaticLine">
+ <size>30,-1d</size>
+ </object>
+ <option>0</option>
+ <flag>wxALL|wxALIGN_CENTRE</flag>
+ <border>5</border>
+ </object>
+ <orient>wxHORIZONTAL</orient>
+ </object>
+ <pos>40,-1d</pos>
+ </object>
+ <flag>wxALIGN_CENTRE</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticBitmap">
+ <size>24,24</size>
+ <bitmap stock_id="wxART_INFORMATION"/>
+ </object>
+ <flag>wxALL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBitmapButton">
+ <size>40,-1d</size>
+ <bitmap stock_id="wxART_FIND"/>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxSpinCtrl">
+ <size>40,-1d</size>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxGauge">
+ <size>40,-1d</size>
+ <range>20</range>
+ <value>7</value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxSpinButton"/>
+ </object>
+ <object class="sizeritem">
+ <object class="wxToggleButton">
+ <pos>40,-1d</pos>
+ <label>Toggle</label>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxComboBox">
+ <size>40,-1d</size>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxSlider">
+ <size>40,-1d</size>
+ <value>2</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxScrollBar">
+ <style>wxSB_HORIZONTAL</style>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxRadioButton">
+ <size>40,-1d</size>
+ <label>radio</label>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxChoice">
+ <size>40,-1d</size>
+ <content>
+ <item>choice</item>
+ </content>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxFilePickerCtrl">
+ <size>40,-1d</size>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox">
+ <size>40,-1d</size>
+ <label>check</label>
+ <checked>1</checked>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxPanel" name="wxHyperlinkCtrl">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxHyperlinkCtrl">
+ <url>http://www</url>
+ </object>
+ <flag>wxALL</flag>
+ <border>3</border>
+ </object>
+ </object>
+ <size>40,-1d</size>
+ </object>
+ </object>
+ <cols>4</cols>
+ <rows>5</rows>
+ <vgap>8</vgap>
+ <hgap>8</hgap>
+ </object>
+ <flag>wxALL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ <title/>
+ </object>
+ <object class="wxFrame" name="PANEL_Gizmos">
+ <size>100,80</size>
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxFlexGridSizer">
+ <object class="sizeritem">
+ <object class="DynamicSashWindow">
+ <size>80,80</size>
+ <style>wxDS_MANAGE_SCROLLBARS|wxDS_DRAG_CORNER</style>
+ </object>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="EditableListBox">
+ <size>80,80</size>
+ <content>
+ <item>item1</item>
+ <item>item2</item>
+ </content>
+ </object>
+ <option>1</option>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="TreeListCtrl">
+ <size>40,30</size>
+ </object>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="LEDNumberCtrl">
+ <size>40,30</size>
+ <value>123</value>
+ <style>wxLED_ALIGN_CENTER</style>
+ </object>
+ <border>5</border>
+ </object>
+ <vgap>5</vgap>
+ <hgap>5</hgap>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ </object>
+ </object>
+ </object>
+ <object class="wxMenuBar" name="PANEL_Menus">
+ <object class="wxMenu" name="MENU1">
+ <object class="wxMenuItem" name="MENU_ITEM">
+ <label>Item1</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem" name="MENU_ITEM">
+ <label>Item2</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem" name="MENU_ITEM">
+ <label>Item3</label>
+ <bitmap/>
+ </object>
+ <label>Menu1</label>
+ </object>
+ <object class="wxMenu" name="MENU2">
+ <object class="wxMenuItem" name="MENU_ITEM">
+ <label>Item1</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem" name="MENU_ITEM">
+ <label>Item2</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem" name="MENU_ITEM">
+ <label>Item3</label>
+ <bitmap/>
+ </object>
+ <label>Menu2</label>
+ </object>
+ </object>
+ <object class="wxFrame" name="FRAME">
+ <size>120,80</size>
+ <title>Frame</title>
+ <style>wxCAPTION|wxSYSTEM_MENU|wxRESIZE_BORDER|wxCLOSE_BOX|wxMAXIMIZE_BOX</style>
+ </object>
+ <object class="wxDialog" name="DIALOG">
+ <size>100,80</size>
+ <title>Dialog</title>
+ </object>
+ <object class="wxPropertySheetDialog" name="PROPSHEETDIALOG">
+ <object class="propertysheetpage">
+ <object class="wxPanel">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxCheckBox">
+ <label>item1</label>
+ </object>
+ <flag>wxALL</flag>
+ <border>5</border>
+ </object>
+ </object>
+ </object>
+ <label>Page1</label>
+ </object>
+ <object class="propertysheetpage">
+ <object class="wxPanel"/>
+ </object>
+ <size>100,80</size>
+ <title>Props</title>
+ <sheetstyle>wxPROPSHEET_DEFAULT</sheetstyle>
+ <style>wxDEFAULT_DIALOG_STYLE</style>
+ </object>
+ <object class="wxFrame" name="FRAME_MenuBar">
+ <object class="wxMenuBar" name="MENUBAR">
+ <object class="wxMenu" name="MENU">
+ <object class="wxMenuItem">
+ <label>Item 1</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem">
+ <label>Item 2</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem">
+ <label>Item 3</label>
+ <bitmap/>
+ </object>
+ <label>Menu 1</label>
+ </object>
+ <object class="wxMenu" name="MENU">
+ <object class="wxMenuItem">
+ <label>Item 1</label>
+ <bitmap/>
+ </object>
+ <object class="separator"/>
+ <object class="wxMenuItem">
+ <label>Item 2</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem">
+ <label>Item 3</label>
+ <bitmap/>
+ </object>
+ <label>Menu 2</label>
+ </object>
+ </object>
+ </object>
+ <object class="wxFrame" name="FRAME_ToolBar">
+ <object class="wxToolBar">
+ <object class="tool">
+ <bitmap stock_id="wxART_NEW"/>
+ <bitmap2/>
+ </object>
+ <object class="tool">
+ <bitmap stock_id="wxART_FILE_OPEN"/>
+ <bitmap2/>
+ </object>
+ <object class="tool">
+ <bitmap stock_id="wxART_FILE_SAVE"/>
+ <bitmap2/>
+ </object>
+ </object>
+ </object>
+ <object class="wxWizard" name="WIZARD">
+ <object class="wxWizardPageSimple" name="page">
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxRadioBox">
+ <content>
+ <item>Here</item>
+ <item>There</item>
+ </content>
+ <style>wxRA_SPECIFY_COLS</style>
+ </object>
+ </object>
+ </object>
+ <bitmap>src-images/neat.png</bitmap>
+ </object>
+ <title>Wizard</title>
+ <bitmap stock_id="wxART_MISSING_IMAGE"/>
+ </object>
+ <object class="wxFrame" name="FRAME_DialogButtonSizer">
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxStdDialogButtonSizer">
+ <object class="button">
+ <object class="wxButton" name="wxID_OK"/>
+ </object>
+ <object class="button">
+ <object class="wxButton" name="wxID_CANCEL"/>
+ </object>
+ </object>
+ <flag>wxALL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ </object>
+ <object class="wxFrame" name="main_frame">
+ <object class="wxMenuBar" name="menu_bar">
+ <object class="wxMenu" name="Snap">
+ <object class="wxMenuItem" name="snap_controls">
+ <label>Controls</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem" name="snap_panels">
+ <label>Panels</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem" name="snap_frame">
+ <label>Frame</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem" name="snap_dialog">
+ <label>Dialog</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem" name="snap_propsheetdialog">
+ <label>PropertySheetDialog</label>
+ </object>
+ <object class="wxMenuItem" name="snap_menubar">
+ <label>Menubar</label>
+ <bitmap/>
+ </object>
+ <object class="wxMenuItem" name="snap_toolbar">
+ <label>Toolbar</label>
+ <bitmap/>
+ </object>
+ <object class="separator"/>
+ <object class="wxMenuItem" name="wxID_EXIT">
+ <label>Exit\tCtrl+Q</label>
+ <bitmap/>
+ </object>
+ <label>Snap</label>
+ </object>
+ </object>
+ <size>100,100</size>
+ <centered>1</centered>
+ <object class="wxStatusBar"/>
+ </object>
+</resource> \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/model.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/model.py
new file mode 100644
index 0000000..d65b30f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/model.py
@@ -0,0 +1,194 @@
+# Name: model.py
+# Purpose: Model class and related
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 07.06.2007
+# RCS-ID: $Id: model.py 65578 2010-09-21 07:39:45Z ROL $
+
+import os,sys
+from xml.dom import minidom
+from globals import *
+
+# Redefine writing to include encoding
+class MyDocument(minidom.Document):
+ def __init__(self):
+ minidom.Document.__init__(self)
+ self.encoding = ''
+ def writexml(self, writer, indent="", addindent="", newl="", encoding=""):
+ if encoding: encdstr = 'encoding="%s"' % encoding
+ else: encdstr = ''
+ writer.write('<?xml version="1.0" %s?>\n' % encdstr)
+ for node in self.childNodes:
+ node.writexml(writer, indent, addindent, newl)
+
+# Model object is used for data manipulation
+class _Model:
+ def __init__(self):
+ self.dom = None
+
+ def init(self, dom=None):
+ self.external = []
+ self.allowExec = None
+ if self.dom: self.dom.unlink()
+ if not dom:
+ self.dom = MyDocument()
+ self.mainNode = self.dom.createElement('resource')
+ self.dom.appendChild(self.mainNode)
+ # Dummy node to be replaced by the node being tested
+ self.testElem = self.dom.createElement('dummy')
+ else:
+ dom.normalize()
+ self.dom = dom
+ self.testElem = self.dom.createElement('dummy')
+ self.mainNode = dom.documentElement
+ # Test element node is always first
+ self.mainNode.insertBefore(self.testElem, self.mainNode.firstChild)
+
+ def loadXML(self, path):
+ f = open(path)
+ dom = minidom.parse(f)
+ f.close()
+ self.init(dom)
+
+ # Set encoding global variable and default encoding
+ if dom.encoding:
+ wx.SetDefaultPyEncoding(dom.encoding.encode())
+ else:
+ dom.encoding = ''
+
+ def saveXML(self, path):
+ if self.dom.encoding:
+ import codecs
+ f = codecs.open(path, 'w', self.dom.encoding)
+ else:
+ f = open(path, 'wt')
+ # Make temporary copy for formatting it
+ domCopy = MyDocument()
+ mainNode = domCopy.appendChild(self.mainNode.cloneNode(True))
+ # Remove first child (testElem)
+ mainNode.removeChild(mainNode.firstChild).unlink()
+ self.indent(domCopy, mainNode)
+ domCopy.writexml(f, encoding = self.dom.encoding)
+ f.close()
+ domCopy.unlink()
+
+ def saveTestMemoryFile(self):
+ # Save in memory FS
+ memFile = MemoryFile(TEST_FILE)
+ encd = self.dom.encoding
+ if not encd: encd = None
+ try:
+ self.dom.writexml(memFile, encoding=encd)
+ except:
+ logger.exception('error writing temporary XML file')
+ wx.LogError('Error writing temporary XML file')
+ memFile.close() # write to wxMemoryFS
+
+ def indent(self, domCopy, node, indent = 0):
+ '''Indent node which must be a comment or an element node and children.'''
+ if indent != 0:
+ prevNode = node.previousSibling
+ if prevNode and prevNode.nodeType == prevNode.TEXT_NODE:
+ prevNode.data = '\n' + ' ' * indent
+ else:
+ text = domCopy.createTextNode('\n' + ' ' * indent)
+ node.parentNode.insertBefore(text, node)
+ # Indent element/comment children recurcively
+ if node.hasChildNodes():
+ lastIndented = None
+ for n in node.childNodes[:]:
+ if n.nodeType in [n.ELEMENT_NODE, n.COMMENT_NODE]:
+ self.indent(domCopy, n, indent + 2)
+ lastIndented = n
+
+ # Insert newline after last element/comment child
+ if lastIndented:
+ n = lastIndented.nextSibling
+ if n and n.nodeType == n.TEXT_NODE:
+ n.data = '\n' + ' ' * indent
+ else:
+ text = domCopy.createTextNode('\n' + ' ' * indent)
+ node.appendChild(text)
+
+ def createObjectNode(self, className):
+ node = self.dom.createElement('object')
+ node.setAttribute('class', className)
+ return node
+
+ def createRefNode(self, ref):
+ node = self.dom.createElement('object_ref')
+ node.setAttribute('ref', ref)
+ return node
+
+ def createCommentNode(self):
+ node = self.dom.createComment('')
+ return node
+
+ def createComponentNode(self, className):
+ node = self.dom.createElement('component')
+ node.setAttribute('class', className)
+ return node
+
+ def parseString(self, data):
+ return minidom.parseString(data).childNodes[0]
+
+ def setTestElem(self, elem):
+ oldTestElem = Model.testElem
+ self.mainNode.replaceChild(elem, oldTestElem)
+ self.testElem = elem
+ oldTestElem.unlink()
+
+ def addExternal(self, path):
+ f = open(path)
+ self.external.append(minidom.parse(f))
+ f.close()
+
+ def findResource(self, name, classname='', recursive=True):
+ found = DoFindResource(self.mainNode, name, classname, recursive)
+ if found: return found
+ # Try to look in external files
+ for dom in self.external:
+ found = DoFindResource(dom.documentElement, name, '', True)
+ if found: return found
+ wx.LogError('XRC resource "%s" not found!' % name)
+
+Model = _Model()
+
+class MemoryFile:
+ '''Memory file proxy for python-like file object.'''
+ def __init__(self, name):
+ self.name = name
+ self.buffer = ''
+ def write(self, data):
+ if Model.dom.encoding:
+ encoding = Model.dom.encoding
+ else:
+ encoding = wx.GetDefaultPyEncoding()
+ try:
+ self.buffer += data.encode(encoding)
+ except UnicodeEncodeError:
+ self.buffer += data.encode(encoding, 'xmlcharrefreplace')
+
+ def close(self):
+ wx.MemoryFSHandler.AddFile(self.name, self.buffer)
+
+# Imitation of FindResource/DoFindResource from xmlres.cpp
+def DoFindResource(parent, name, classname, recursive):
+ for n in parent.childNodes:
+ if n.nodeType == minidom.Node.ELEMENT_NODE and \
+ n.tagName in ['object', 'object_ref'] and \
+ n.getAttribute('name') == name:
+ cls = n.getAttribute('class')
+ if not classname or cls == classname: return n
+ if not cls and n.tagName == 'object_ref':
+ refName = n.getAttribute('ref')
+ if not refName: continue
+ refNode = FindResource(refName)
+ if refName and refNode.getAttribute('class') == classname:
+ return n
+ if recursive:
+ for n in parent.childNodes:
+ if n.nodeType == minidom.Node.ELEMENT_NODE and \
+ n.tagName in ['object', 'object_ref']:
+ found = DoFindResource(n, name, classname, True)
+ if found: return found
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/params.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/params.py
new file mode 100644
index 0000000..6e292bf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/params.py
@@ -0,0 +1,1121 @@
+# Name: params.py
+# Purpose: Classes for parameter introduction
+# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
+# Created: 22.08.2001
+# RCS-ID: $Id: params.py 71829 2012-06-21 19:15:52Z ROL $
+
+'''
+Visual C{Param*} classes for populating C{AtrtibutePanel} with attribute editing
+blocks.
+'''
+
+import string
+import os
+import wx.combo
+from globals import *
+
+WARenameDict = {'fg': 'foreground', 'bg': 'background'}
+
+def InitParams(panel):
+ '''Set pixel common size based on parent window.'''
+
+ global Presenter
+ from presenter import Presenter
+ global Listener
+ from listener import Listener
+
+ dc = wx.ClientDC(panel)
+ global textH, textB
+ textH = -1
+ if wx.Platform == '__WXMAC__':
+ textB = 3 # bigger text border needed for mac highlighting
+ else:
+ textB = 2
+ dc.Destroy()
+
+ # make a custom bitmap showing "..."
+ bw, bh = 14, 16
+ bmp = wx.EmptyBitmap(bw,bh)
+ dc = wx.MemoryDC(bmp)
+
+ # clear to a specific background colour
+ bgcolor = wx.Colour(255,254,255)
+ dc.SetBackground(wx.Brush(bgcolor))
+ dc.Clear()
+
+ # draw the label onto the bitmap
+ label = "..."
+ font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ dc.SetFont(font)
+ tw,th = dc.GetTextExtent(label)
+ dc.DrawText(label, (bw-tw)/2, (bw-tw)/2)
+ del dc
+
+ # now apply a mask using the bgcolor
+ bmp.SetMaskColour(bgcolor)
+ global bmpEdit
+ bmpEdit = bmp
+
+ # Set known encodings
+ for i in range(wx.FontMapper.GetSupportedEncodingsCount()):
+ ParamEncoding.values.append(wx.FontMapper.GetEncodingName(
+ wx.FontMapper.GetEncoding(i)))
+ ParamEncoding.values.sort()
+
+
+# Class that can properly disable children
+class PPanel(wx.Panel):
+ '''Abstract base class creating an empty C{wx.Panel}.'''
+ isCheck = False
+ def __init__(self, parent, name):
+ wx.Panel.__init__(self, parent, -1, name=name)
+ self.name = name
+ def Enable(self, value):
+ self.enabled = value
+ # Something strange is going on with enable so we make sure...
+ for w in self.GetChildren():
+ w.Enable(value)
+ #wx.Panel.Enable(self, value)
+ # Common method to set modified state
+ def OnChange(self, evt):
+ Presenter.setApplied(False)
+ evt.Skip()
+ def OnKillFocus(self, evt):
+ # Refresh test window if auto refresh policy on focus
+ if Listener.testWin.IsShown() and g.conf.autoRefresh and \
+ g.conf.autoRefreshPolicy == AUTO_REFRESH_POLICY_FOCUS:
+ wx.CallAfter(Presenter.refreshTestWin)
+ evt.Skip()
+
+class ParamBinaryOr(PPanel):
+ '''Editing binary flag attributes defined by a string separated by '|'.'''
+ def __init__(self, parent, name):
+ PPanel.__init__(self, parent, name)
+ self.freeze = False
+ sizer = wx.BoxSizer()
+ popup = CheckListBoxComboPopup(self.values)
+ self.combo = wx.combo.ComboCtrl(self, size=(220,-1))
+ self.combo.SetPopupControl(popup)
+ if wx.Platform == '__WXMAC__':
+ sizer.Add(self.combo, 1, wx.ALL, 0)
+ else:
+ sizer.Add(self.combo, 1, wx.ALL, 2)
+ self.SetSizerAndFit(sizer)
+ self.combo.Bind(wx.EVT_TEXT, self.OnChange)
+ self.combo.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ def GetValue(self):
+ return self.combo.GetValue()
+ def SetValue(self, value):
+ self.freeze = True
+ self.combo.SetValue(value)
+ self.freeze = False
+ def SetValues(self):
+ self.combo.InsertItems(self.values, 0)
+ def OnChange(self, evt):
+ # ComboCtrl still generates events in SetValue
+ if self.freeze: return
+ Presenter.setApplied(False)
+ evt.Skip()
+
+class ParamFlag(ParamBinaryOr):
+ '''Sizer flag editing.'''
+ values = ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL',
+ 'wxEXPAND', 'wxGROW', 'wxSHAPED', 'wxSTRETCH_NOT',
+ 'wxALIGN_CENTRE', 'wxALIGN_LEFT', 'wxALIGN_RIGHT',
+ 'wxALIGN_TOP', 'wxALIGN_BOTTOM',
+ 'wxALIGN_CENTRE_VERTICAL', 'wxALIGN_CENTRE_HORIZONTAL',
+ 'wxADJUST_MINSIZE', 'wxFIXED_MINSIZE',
+ 'wxRESERVE_SPACE_EVEN_IF_HIDDEN',
+ ]
+ equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE',
+ 'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL',
+ 'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL',
+ 'wxUP': 'wxTOP', 'wxDOWN': 'wxBOTTOM', 'wxNORTH': 'wxTOP',
+ 'wxSOUTH': 'wxBOTTOM', 'wxWEST': 'wxLEFT', 'wxEAST': 'wxRIGHT'}
+
+class ParamColour(PPanel):
+ '''Color attribute editing.'''
+ def __init__(self, parent, name):
+ PPanel.__init__(self, parent, name)
+ sizer = wx.BoxSizer()
+ self.text = wx.TextCtrl(self, size=(80,textH))
+ sizer.Add(self.text, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, textB)
+ self.button = wx.Panel(self, size=(20, 20))
+ sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 3)
+ self.SetSizer(sizer)
+ self.textModified = False
+ self.button.Bind(wx.EVT_PAINT, self.OnPaintButton)
+ self.text.Bind(wx.EVT_TEXT, self.OnChange)
+ self.text.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.button.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ def GetValue(self):
+ return self.text.GetValue()
+ def SetValue(self, value):
+ self.text.ChangeValue(value) # update text ctrl
+ self.UpdateColour(value)
+ def UpdateColour(self, value):
+ try:
+ colour = wx.Colour(int(value[1:3], 16), int(value[3:5], 16), int(value[5:7], 16))
+ self.button.SetBackgroundColour(colour)
+ except: # ignore errors
+ self.button.SetBackgroundColour(self.GetBackgroundColour())
+ self.button.Refresh()
+ def OnChange(self, evt):
+ Presenter.setApplied(False)
+ self.UpdateColour(evt.GetString())
+ evt.Skip()
+ def OnPaintButton(self, evt):
+ dc = wx.PaintDC(self.button)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ if self.IsEnabled(): dc.SetPen(wx.BLACK_PEN)
+ else: dc.SetPen(wx.GREY_PEN)
+ size = self.button.GetSize()
+ dc.DrawRectangle(0, 0, size.width, size.height)
+ def OnLeftDown(self, evt):
+ data = wx.ColourData()
+ data.SetColour(self.GetValue())
+ dlg = wx.ColourDialog(self, data)
+ if dlg.ShowModal() == wx.ID_OK:
+ self.SetValue('#%02X%02X%02X' % dlg.GetColourData().GetColour().Get())
+ Presenter.setApplied(False)
+ dlg.Destroy()
+
+################################################################################
+
+# Mapping from wx constants to XML strings
+fontFamiliesWx2Xml = {wx.DEFAULT: 'default', wx.DECORATIVE: 'decorative',
+ wx.ROMAN: 'roman', wx.SCRIPT: 'script', wx.SWISS: 'swiss',
+ wx.MODERN: 'modern'}
+fontStylesWx2Xml = {wx.NORMAL: 'normal', wx.SLANT: 'slant', wx.ITALIC: 'italic'}
+fontWeightsWx2Xml = {wx.NORMAL: 'normal', wx.LIGHT: 'light', wx.BOLD: 'bold'}
+def ReverseMap(m):
+ rm = {}
+ for k,v in m.items(): rm[v] = k
+ return rm
+fontFamiliesXml2wx = ReverseMap(fontFamiliesWx2Xml)
+fontStylesXml2wx = ReverseMap(fontStylesWx2Xml)
+fontWeightsXml2wx = ReverseMap(fontWeightsWx2Xml)
+
+class ParamFont(PPanel):
+ '''Font attribute editing.'''
+ def __init__(self, parent, name):
+ PPanel.__init__(self, parent, name)
+ sizer = wx.BoxSizer()
+ self.button = wx.FontPickerCtrl(
+ self, style=wx.FNTP_FONTDESC_AS_LABEL | wx.FNTP_USE_TEXTCTRL
+ )
+ self.text = self.button.GetTextCtrl()
+ if wx.Platform == '__WXMAC__':
+ sizer.Add(self.button, 0, wx.LEFT, -2)
+ else:
+ sizer.Add(self.button, 0, wx.LEFT, textB)
+ self.SetSizer(sizer)
+ self.Bind(wx.EVT_FONTPICKER_CHANGED, self.OnPickFont)
+ self.text.Bind(wx.EVT_TEXT, self.OnText)
+ self.text.Bind(wx.EVT_KILL_FOCUS, self.OnTextKillFocus)
+ def OnText(self, evt):
+ Presenter.setApplied(False)
+ if not evt.GetString():
+ self.text.ChangeValue('')
+ self.value = {}
+ def OnTextKillFocus(self, evt):
+ if self.text.GetValue():
+ evt.Skip()
+ def GetValue(self):
+ return self.value
+ def dict2font(self, d):
+ error = False
+ if 'size' in d:
+ try: size = int(d['size'])
+ except ValueError: error = True; wx.LogError('Invalid size specification')
+ else:
+ size = g.sysFont().GetPointSize()
+ if 'family' in d:
+ try: family = fontFamiliesXml2wx[d['family']]
+ except KeyError: error = True; wx.LogError('Invalid family specification')
+ else:
+ family = wx.DEFAULT
+ if 'style' in d:
+ try: style = fontStylesXml2wx[d['style']]
+ except KeyError: error = True; wx.LogError('Invalid style specification')
+ else:
+ style = wx.NORMAL
+ if 'weight' in d:
+ try: weight = fontWeightsXml2wx[d['weight']]
+ except KeyError: error = True; wx.LogError('Invalid weight specification')
+ else:
+ weight = wx.NORMAL
+ try: underlined = bool(int(d.get('underlined', '0')))
+ except ValueError: error = True; wx.LogError('Invalid underlined flag specification')
+ face = d.get('face','')
+ enc = wx.FONTENCODING_DEFAULT
+ mapper = wx.FontMapper()
+ if 'encoding' in d and d['encoding'] != 'default':
+ enc = mapper.CharsetToEncoding(d['encoding'])
+ if error: wx.LogError('Invalid font specification')
+ if enc == wx.FONTENCODING_DEFAULT: enc = wx.FONTENCODING_SYSTEM
+ font = wx.Font(size, family, style, weight, underlined, face, enc)
+ return font
+
+ def SetValue(self, value):
+ if not value:
+ self.text.ChangeValue('')
+ else:
+ self.button.SetSelectedFont(self.dict2font(value))
+ self.value = value
+ def OnPickFont(self, evt):
+ font = evt.GetFont()
+ if font.GetEncoding() == wx.FONTENCODING_SYSTEM:
+ encName = ''
+ else:
+ encName = wx.FontMapper.GetEncodingName(font.GetEncoding()).encode()
+ value = {'size': str(font.GetPointSize()),
+ 'family': fontFamiliesWx2Xml.get(font.GetFamily(), "default"),
+ 'style': fontStylesWx2Xml.get(font.GetStyle(), "normal"),
+ 'weight': fontWeightsWx2Xml.get(font.GetWeight(), "normal"),
+ 'underlined': str(int(font.GetUnderlined())),
+ 'face': font.GetFaceName().encode(),
+ 'encoding': encName}
+ self.SetValue(value)
+ Presenter.setApplied(False)
+
+################################################################################
+
+# This is a replacement for SpinCtrl to make ParamUnit looking similar.
+# Unfortunately there is no SpinCtrl::GetStringValue...
+class ParamInt(PPanel):
+ '''TextCtrl with SpinButton for integer parameters.'''
+ default = 0
+ range = (-2147483648, 2147483647)
+ def __init__(self, parent, name):
+ PPanel.__init__(self, parent, name)
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.spin = wx.SpinButton(self, style = wx.SP_VERTICAL, size=(-1,10))
+ textW = 60 - self.spin.GetSize()[0]
+ self.text = wx.TextCtrl(self, size=(textW,textH))
+ self.spin.SetRange(*self.range)
+ if wx.Platform == '__WXMAC__':
+ sizer.Add(self.text, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.ALL, textB)
+ else:
+ sizer.Add(self.text, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | \
+ wx.LEFT | wx.TOP | wx.BOTTOM, textB)
+ sizer.Add(self.spin, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
+ self.SetSizer(sizer)
+ self.spin.Bind(wx.EVT_SPIN_UP, self.OnSpinUp)
+ self.spin.Bind(wx.EVT_SPIN_DOWN, self.OnSpinDown)
+ self.text.Bind(wx.EVT_TEXT, self.OnChange)
+ self.text.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+ def GetValue(self):
+ return self.text.GetValue()
+ def SetValue(self, value):
+ self.text.ChangeValue(value)
+ self.SyncSpin(value)
+ def SyncSpin(self, value):
+ try:
+ intValue = int(value)
+ self.spin.SetValue(intValue)
+ except:
+ self.spin.SetValue(self.default)
+ def OnChange(self, evt):
+ self.SyncSpin(evt.GetString())
+ Presenter.setApplied(False)
+ evt.Skip()
+ def SyncText(self, spinValue):
+ if self.range[0] <= spinValue <= self.range[1]:
+ self.text.ChangeValue(str(spinValue))
+ Presenter.setApplied(False)
+ def OnSpinUp(self, evt):
+ self.SyncText(evt.GetPosition())
+ evt.Skip()
+ def OnSpinDown(self, evt):
+ self.SyncText(evt.GetPosition())
+ evt.Skip()
+
+def MetaParamInt(**kargs):
+ '''Create ParamInt class with default value.'''
+ return type('ParamInt', (ParamInt,), kargs)
+
+ParamIntNN = MetaParamInt(default=0, range=(0, 2147483647)) # non-negative
+ParamIntP = MetaParamInt(default=1, range=(1, 2147483647)) # positive
+
+# Same as ParamInt but allows dialog units (XXXd)
+class ParamUnit(ParamInt):
+ '''Similar to L{ParamInt}, 'd' can be appended to the value to specify
+ dialog units mode.'''
+ def _splitValue(self, value):
+ units = ''
+ if value[-1:].upper() == 'D':
+ units = value[-1]
+ value = value[:-1]
+ return value,units
+ def SyncSpin(self, value):
+ try:
+ value,units = self._splitValue(value)
+ intValue = int(value)
+ self.spin.SetValue(intValue)
+ except:
+ self.spin.SetValue(self.default)
+ def SyncText(self, spinValue):
+ if self.range[0] <= spinValue <= self.range[1]:
+ value,units = self._splitValue(self.text.GetValue())
+ self.text.ChangeValue(str(spinValue)+units)
+ Presenter.setApplied(False)
+
+class ParamMultilineText(PPanel):
+ '''Multiline text editing.'''
+ def __init__(self, parent, name, textWidth=-1):
+ PPanel.__init__(self, parent, name)
+ sizer = wx.BoxSizer()
+ self.text = wx.TextCtrl(self, size=wx.Size(200,textH))
+ sizer.Add(self.text, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, textB)
+ self.button = wx.BitmapButton(self, bitmap=bmpEdit, size=(-1,textH))
+ sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
+ self.SetSizer(sizer)
+ self.button.Bind(wx.EVT_BUTTON, self.OnButtonEdit)
+ self.text.Bind(wx.EVT_TEXT, self.OnChange)
+ self.text.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ def GetValue(self):
+ return self.text.GetValue()
+ def SetValue(self, value):
+ self.text.ChangeValue(value)
+ def OnButtonEdit(self, evt):
+ dlg = g.res.LoadDialog(self, 'DIALOG_TEXT')
+ textCtrl = xrc.XRCCTRL(dlg, 'TEXT')
+ textCtrl.SetValue(self.text.GetValue())
+ if dlg.ShowModal() == wx.ID_OK:
+ self.text.ChangeValue(textCtrl.GetValue())
+ Presenter.setApplied(False)
+ dlg.Destroy()
+
+class ParamText(PPanel):
+ '''Text attribute.'''
+ textWidth = -1
+ proportion = 0
+ def __init__(self, parent, name, **kargs):
+ PPanel.__init__(self, parent, name)
+ style = kargs.pop('style', 0)
+ textWidth = kargs.pop('textWidth', self.textWidth)
+ option = kargs.pop('proportion', self.proportion)
+ if textWidth == -1: option = 1
+ # We use sizer even here to have the same size of text control
+ sizer = wx.BoxSizer()
+ self.text = wx.TextCtrl(self, size=wx.Size(textWidth,textH), style=style)
+ sizer.Add(self.text, option, wx.ALIGN_CENTER_VERTICAL | wx.ALL, textB)
+ self.SetSizer(sizer)
+ self.text.Bind(wx.EVT_TEXT, self.OnChange)
+ self.text.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ def GetValue(self):
+ return self.text.GetValue()
+ def SetValue(self, value):
+ self.text.ChangeValue(value)
+
+def MetaParamText(textWidth, proportion=0):
+ '''Return a L{ParamText} class with specified width and proportion.'''
+ return type('ParamText__length', (ParamText,),
+ {'textWidth': textWidth, 'proportion': proportion})
+
+ParamLongText = MetaParamText(200, 1)
+ParamAccel = MetaParamText(100)
+ParamHelp = MetaParamText(200, 1)
+ParamPosSize = MetaParamText(80)
+
+class ParamComment(ParamText):
+ '''Comment node editing.'''
+ def __init__(self, parent, name):
+ ParamText.__init__(self, parent, name, textWidth=330,
+ style=wx.TE_PROCESS_ENTER)
+
+class ContentDialog(wx.Dialog):
+ '''Dialog for editing content attributes.'''
+ def __init__(self, parent, value):
+ # Load from resource
+ pre = wx.PreDialog()
+ g.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT')
+ self.PostCreate(pre)
+ self.list = xrc.XRCCTRL(self, 'LIST')
+ # Set list items
+ for v in value:
+ self.list.Append(v)
+ self.SetAutoLayout(True)
+ self.GetSizer().Fit(self)
+ # Callbacks
+ self.ID_BUTTON_APPEND = xrc.XRCID('BUTTON_APPEND')
+ self.ID_BUTTON_EDIT = xrc.XRCID('BUTTON_EDIT')
+ self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
+ self.ID_BUTTON_UP = xrc.XRCID('BUTTON_UP')
+ self.ID_BUTTON_DOWN = xrc.XRCID('BUTTON_DOWN')
+ wx.EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_EDIT, self.OnUpdateUI)
+ def OnButtonUp(self, evt):
+ i = self.list.GetSelection()
+ str = self.list.GetString(i)
+ self.list.Delete(i)
+ self.list.InsertItems([str], i-1)
+ self.list.SetSelection(i-1)
+ def OnButtonDown(self, evt):
+ i = self.list.GetSelection()
+ str = self.list.GetString(i)
+ self.list.Delete(i)
+ self.list.InsertItems([str], i+1)
+ self.list.SetSelection(i+1)
+ def OnButtonAppend(self, evt):
+ str = wx.GetTextFromUser('Enter new item:', 'Append', '', self)
+ self.list.Append(str)
+ def OnButtonEdit(self, evt):
+ i = self.list.GetSelection()
+ str = wx.GetTextFromUser('Edit item:', 'Change', self.list.GetString(i), self)
+ self.list.SetString(i, str)
+ def OnButtonRemove(self, evt):
+ self.list.Delete(self.list.GetSelection())
+ def OnUpdateUI(self, evt):
+ if evt.GetId() == self.ID_BUTTON_REMOVE or evt.GetId() == self.ID_BUTTON_EDIT:
+ evt.Enable(self.list.GetSelection() != -1)
+ elif evt.GetId() == self.ID_BUTTON_UP:
+ evt.Enable(self.list.GetSelection() > 0)
+ elif evt.GetId() == self.ID_BUTTON_DOWN:
+ evt.Enable(self.list.GetSelection() != -1 and \
+ self.list.GetSelection() < self.list.GetCount() - 1)
+
+class ContentCheckListDialog(ContentDialog):
+ '''Dialog for editing content checklist attributes.'''
+ def __init__(self, parent, value):
+ pre = wx.PreDialog()
+ g.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT_CHECKLIST')
+ self.PostCreate(pre)
+ self.list = xrc.XRCCTRL(self, 'CHECK_LIST')
+ # Set list items
+ i = 0
+ for ch,v in value:
+ self.list.Append(v)
+ self.list.Check(i, ch)
+ i += 1
+ self.SetAutoLayout(True)
+ self.GetSizer().Fit(self)
+ # Callbacks
+ self.ID_BUTTON_APPEND = xrc.XRCID('BUTTON_APPEND')
+ self.ID_BUTTON_EDIT = xrc.XRCID('BUTTON_EDIT')
+ self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
+ self.ID_BUTTON_UP = xrc.XRCID('BUTTON_UP')
+ self.ID_BUTTON_DOWN = xrc.XRCID('BUTTON_DOWN')
+ wx.EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_EDIT, self.OnUpdateUI)
+ def OnButtonUp(self, evt):
+ i = self.list.GetSelection()
+ str, ch = self.list.GetString(i), self.list.IsChecked(i)
+ self.list.Delete(i)
+ self.list.InsertItems([str], i-1)
+ self.list.Check(i-1, ch)
+ self.list.SetSelection(i-1)
+ def OnButtonDown(self, evt):
+ i = self.list.GetSelection()
+ str, ch = self.list.GetString(i), self.list.IsChecked(i)
+ self.list.Delete(i)
+ self.list.InsertItems([str], i+1)
+ self.list.Check(i+1, ch)
+ self.list.SetSelection(i+1)
+
+class ContentHelpListDialog(wx.Dialog):
+ '''Dialog for editing content attributes with help text.'''
+ def __init__(self, parent, value):
+ pre = wx.PreDialog()
+ g.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT_HELPLIST')
+ self.PostCreate(pre)
+ self.list = xrc.XRCCTRL(self, 'LIST')
+ self.list.InsertColumn(0, 'label')
+ self.list.InsertColumn(1, 'tooltip')
+ self.list.InsertColumn(2, 'help text')
+ # Set list items
+ i = 0
+ for v,t,h in value:
+ self.list.InsertStringItem(i, v)
+ self.list.SetStringItem(i, 1, t)
+ self.list.SetStringItem(i, 2, h)
+ i += 1
+ self.SetAutoLayout(True)
+ self.GetSizer().Fit(self)
+ # Callbacks
+ self.ID_BUTTON_APPEND = xrc.XRCID('BUTTON_APPEND')
+ self.ID_BUTTON_EDIT = xrc.XRCID('BUTTON_EDIT')
+ self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
+ self.ID_BUTTON_UP = xrc.XRCID('BUTTON_UP')
+ self.ID_BUTTON_DOWN = xrc.XRCID('BUTTON_DOWN')
+ wx.EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
+ wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_EDIT, self.OnUpdateUI)
+ def OnButtonUp(self, evt):
+ i = self.list.GetNextItem(-1, state = wx.LIST_STATE_SELECTED)
+ v, t, h = self.list.GetItem(i, 0), self.list.GetItem(i, 1), self.list.GetItem(i, 2)
+ self.list.DeleteItem(i)
+ i = self.list.InsertStringItem(i-1, v.GetText())
+ self.list.SetStringItem(i, 1, t.GetText())
+ self.list.SetStringItem(i, 2, h.GetText())
+ self.list.SetItemState(i, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
+ def OnButtonDown(self, evt):
+ i = self.list.GetNextItem(-1, state = wx.LIST_STATE_SELECTED)
+ v, t, h = self.list.GetItem(i, 0), self.list.GetItem(i, 1), self.list.GetItem(i, 2)
+ self.list.DeleteItem(i)
+ i = self.list.InsertStringItem(i+1, v.GetText())
+ self.list.SetStringItem(i, 1, t.GetText())
+ self.list.SetStringItem(i, 2, h.GetText())
+ self.list.SetItemState(i, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
+ def OnButtonAppend(self, evt):
+ dlg = g.res.LoadDialog(self, 'DIALOG_HELPTEXT')
+ v = xrc.XRCCTRL(dlg, 'TEXT')
+ t = xrc.XRCCTRL(dlg, 'TOOLTIP')
+ h = xrc.XRCCTRL(dlg, 'HELPTEXT')
+ if dlg.ShowModal() == wx.ID_OK:
+ i = self.list.GetItemCount()
+ self.list.InsertStringItem(i, v.GetValue())
+ self.list.SetStringItem(i, 1, t.GetValue())
+ self.list.SetStringItem(i, 2, h.GetValue())
+ dlg.Destroy()
+ def OnButtonEdit(self, evt):
+ s = self.list.GetNextItem(-1, state = wx.LIST_STATE_SELECTED)
+ dlg = g.res.LoadDialog(self, 'DIALOG_HELPTEXT')
+ v = xrc.XRCCTRL(dlg, 'TEXT')
+ t = xrc.XRCCTRL(dlg, 'TOOLTIP')
+ h = xrc.XRCCTRL(dlg, 'HELPTEXT')
+ v.SetValue(self.list.GetItem(s, 0).GetText())
+ t.SetValue(self.list.GetItem(s, 1).GetText())
+ h.SetValue(self.list.GetItem(s, 2).GetText())
+ if dlg.ShowModal() == wx.ID_OK:
+ self.list.SetStringItem(s, 0, v.GetValue())
+ self.list.SetStringItem(s, 1, t.GetValue())
+ self.list.SetStringItem(s, 2, h.GetValue())
+ dlg.Destroy()
+ def OnButtonRemove(self, evt):
+ self.list.DeleteItem(self.list.GetNextItem(-1, state = wx.LIST_STATE_SELECTED))
+ def OnUpdateUI(self, evt):
+ s = self.list.GetNextItem(-1, state = wx.LIST_STATE_SELECTED)
+ if evt.GetId() == self.ID_BUTTON_REMOVE or evt.GetId() == self.ID_BUTTON_EDIT:
+ evt.Enable(s != -1)
+ elif evt.GetId() == self.ID_BUTTON_UP:
+ evt.Enable(s > 0)
+ elif evt.GetId() == self.ID_BUTTON_DOWN:
+ evt.Enable(s != -1 and s < self.list.GetItemCount() - 1)
+
+class ParamContent(PPanel):
+ '''Editing of content attribute.'''
+ def __init__(self, parent, name):
+ PPanel.__init__(self, parent, name)
+ sizer = wx.BoxSizer()
+ self.text = wx.TextCtrl(self, size=wx.Size(200,textH))
+ sizer.Add(self.text, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, textB)
+ self.button = wx.BitmapButton(self, bitmap=bmpEdit, size=(-1,textH))
+ sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
+ self.SetSizer(sizer)
+ self.textModified = False
+ self.button.Bind(wx.EVT_BUTTON, self.OnButtonEdit)
+ self.text.Bind(wx.EVT_TEXT, self.OnChange)
+ def OnChange(self, evt):
+ Presenter.setApplied(False)
+ self.textModified = True
+ evt.Skip()
+ def GetValue(self):
+ if self.textModified: # text has newer value
+ try:
+ return self.text.GetValue().split('|')
+ except ValueError:
+ return []
+ return self.value
+ def SetValue(self, value):
+ if not value: value = []
+ self.value = value
+ repr_ = '|'.join(map(str, value))
+ self.text.ChangeValue(repr_) # update text ctrl
+ def OnButtonEdit(self, evt):
+ if self.textModified: # text has newer value
+ self.value = self.GetValue()
+ dlg = ContentDialog(self, self.value)
+ if dlg.ShowModal() == wx.ID_OK:
+ value = []
+ for i in range(dlg.list.GetCount()):
+ value.append(dlg.list.GetString(i))
+ self.SetValue(value)
+ Presenter.setApplied(False)
+ self.textModified = False
+ dlg.Destroy()
+
+# CheckList content
+class ParamContentCheckList(ParamContent):
+ '''Editing of content check list attribute.'''
+ def __init__(self, parent, name):
+ ParamContent.__init__(self, parent, name)
+ def OnButtonEdit(self, evt):
+ if self.textModified: # text has newer value
+ self.value = self.GetValue()
+ dlg = ContentCheckListDialog(self, self.value)
+ if dlg.ShowModal() == wx.ID_OK:
+ value = []
+ for i in range(dlg.list.GetCount()):
+ value.append((int(dlg.list.IsChecked(i)), str(dlg.list.GetString(i))))
+ self.SetValue(value)
+ Presenter.setApplied(False)
+ self.textModified = False
+ dlg.Destroy()
+
+# HelpList content
+class ParamContentHelpList(ParamContent):
+ '''Editing of content attribute with help text.'''
+ def __init__(self, parent, name):
+ ParamContent.__init__(self, parent, name)
+ def OnButtonEdit(self, evt):
+ if self.textModified: # text has newer value
+ self.value = self.GetValue()
+ dlg = ContentHelpListDialog(self, self.value)
+ if dlg.ShowModal() == wx.ID_OK:
+ value = []
+ for i in range(dlg.list.GetItemCount()):
+ value.append((str(dlg.list.GetItem(i, 0).GetText()),
+ str(dlg.list.GetItem(i, 1).GetText()),
+ str(dlg.list.GetItem(i, 2).GetText())))
+ self.SetValue(value)
+ Presenter.setApplied(False)
+ self.textModified = False
+ dlg.Destroy()
+
+class IntListDialog(wx.Dialog):
+ '''Dialog for editing integer lists.'''
+ def __init__(self, parent, value):
+ pre = wx.PreDialog()
+ g.res.LoadOnDialog(pre, parent, 'DIALOG_INTLIST')
+ self.PostCreate(pre)
+ self.list = xrc.XRCCTRL(self, 'LIST')
+ # Set list items
+ value.sort()
+ for v in value:
+ self.list.Append(v)
+ self.SetAutoLayout(True)
+ self.GetSizer().Fit(self)
+ # Callbacks
+ self.spinCtrl = xrc.XRCCTRL(self, 'SPIN')
+ wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_ADD'), self.OnButtonAdd)
+ self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
+ wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
+ wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_CLEAR'), self.OnButtonClear)
+ wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
+ def OnButtonAdd(self, evt):
+ # Check that it's unique
+ try:
+ v = self.spinCtrl.GetValue()
+ s = str(v) # to be sure
+ i = self.list.FindString(s)
+ if i == -1: # ignore non-unique
+ # Find place to insert
+ found = False
+ for i in range(self.list.GetCount()):
+ if int(self.list.GetString(i)) > v:
+ found = True
+ break
+ if found: self.list.InsertItems([s], i)
+ else: self.list.Append(s)
+ except ValueError:
+ wx.LogError('List item is not an int!')
+ def OnButtonRemove(self, evt):
+ self.list.Delete(self.list.GetSelection())
+ def OnButtonClear(self, evt):
+ self.list.Clear()
+ def OnUpdateUI(self, evt):
+ if evt.GetId() == self.ID_BUTTON_REMOVE:
+ evt.Enable(self.list.GetSelection() != -1)
+
+# For growable list
+class ParamIntList(ParamContent):
+ '''Editing integer list attribute.'''
+ def __init__(self, parent, name):
+ ParamContent.__init__(self, parent, name)
+ def OnButtonEdit(self, evt):
+ if self.textModified: # text has newer value
+ try:
+ self.value = self.text.GetValue().split('|')
+ except ValueError:
+ self.value = []
+ dlg = IntListDialog(self, self.value)
+ if dlg.ShowModal() == wx.ID_OK:
+ value = []
+ for i in range(dlg.list.GetCount()):
+ value.append(dlg.list.GetString(i))
+ self.SetValue(value)
+ Presenter.setApplied()
+ self.textModified = False
+ dlg.Destroy()
+
+# Boxless radiobox
+class RadioBox(PPanel):
+ def __init__(self, parent, name='radiobox'):
+ PPanel.__init__(self, parent, name)
+ topSizer = wx.BoxSizer()
+ self.choicesInv = {}
+ for i,v in self.choices.items():
+ self.choicesInv[v] = i
+ button = wx.RadioButton(self, -1, i, name=i)
+ topSizer.Add(button, 0, wx.RIGHT, 5)
+ wx.EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice)
+ self.SetSizer(topSizer)
+ def SetStringSelection(self, value):
+ for i in self.choices.keys():
+ self.FindWindowByName(i).SetValue(i == value)
+ self.value = value
+ def OnRadioChoice(self, evt):
+ if evt.GetSelection():
+ self.value = evt.GetEventObject().GetName()
+ Presenter.setApplied(False)
+ def GetStringSelection(self):
+ return self.value
+ def GetValue(self):
+ return self.choices[self.GetStringSelection()]
+ def SetValue(self, value):
+ if not value: value = self.default
+ self.SetStringSelection(self.choicesInv[value])
+
+# Base type for checkable parameters
+class CheckBox(PPanel):
+ isCheck = True
+ def __init__(self, parent, name='checkbox'):
+ PPanel.__init__(self, parent, name)
+ topSizer = wx.BoxSizer()
+ self.check = wx.CheckBox(self, -1, name, size=(-1,textH))
+ topSizer.Add(self.check, 0, wx.TOP | wx.BOTTOM, textB)
+ self.check.Bind(wx.EVT_CHECKBOX, self.OnCheck)
+ self.SetSizer(topSizer)
+ def OnCheck(self, evt):
+ Presenter.setApplied(False)
+ if Presenter.panelIsDirty():
+ Presenter.registerUndoEdit()
+ if Listener.testWin.IsShown() and g.conf.autoRefresh and \
+ g.conf.autoRefreshPolicy == AUTO_REFRESH_POLICY_FOCUS:
+ Listener.testWin.isDirty = True
+ wx.CallAfter(Presenter.refreshTestWin)
+ evt.Skip()
+
+class ParamBool(CheckBox):
+ '''Editing on/off attributes.'''
+ defaultString = '(default is OFF)'
+ def GetValue(self):
+ return ('', '1')[self.check.IsChecked()]
+ def SetValue(self, value):
+ self.check.SetValue(value == '1')
+
+class ParamInverseBool(CheckBox):
+ '''like L{ParamBool} but defined if unchecked'''
+ defaultString = '(default is ON)'
+ def GetValue(self):
+ return ('0', '')[self.check.IsChecked()]
+ def SetValue(self, value):
+ self.check.SetValue(not value or value == '1')
+
+class ParamOrient(RadioBox):
+ '''Orientation attribute editing for sizers.'''
+ choices = {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
+ default = 'wxHORIZONTAL'
+
+class ParamOrientation(RadioBox):
+ '''Orientaiton attribute editing for C{wx.SplitterWindow}.'''
+ choices = {'horizontal': 'horizontal', 'vertical': 'vertical'}
+ default = 'vertical'
+
+class ParamBitmap(PPanel):
+ def __init__(self, parent, name):
+ pre = wx.PrePanel()
+ g.res.LoadOnPanel(pre, parent, 'PANEL_BITMAP')
+ self.PostCreate(pre)
+ self.modified = False
+ self.radio_std = xrc.XRCCTRL(self, 'RADIO_STD')
+ self.radio_file = xrc.XRCCTRL(self, 'RADIO_FILE')
+ self.combo = xrc.XRCCTRL(self, 'COMBO_STD')
+ self.text = xrc.XRCCTRL(self, 'TEXT_FILE')
+ self.button = xrc.XRCCTRL(self, 'BUTTON_BROWSE')
+ self.textModified = False
+ wx.EVT_RADIOBUTTON(self, xrc.XRCID('RADIO_STD'), self.OnRadioStd)
+ wx.EVT_RADIOBUTTON(self, xrc.XRCID('RADIO_FILE'), self.OnRadioFile)
+ wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_BROWSE'), self.OnButtonBrowse)
+ wx.EVT_COMBOBOX(self, xrc.XRCID('COMBO_STD'), self.OnCombo)
+ wx.EVT_TEXT(self, xrc.XRCID('COMBO_STD'), self.OnChange)
+ wx.EVT_TEXT(self, xrc.XRCID('TEXT_FILE'), self.OnChange)
+ def OnRadioStd(self, evt):
+ Presenter.setApplied(False)
+ self.SetValue(['wxART_MISSING_IMAGE',''])
+ def OnRadioFile(self, evt):
+ Presenter.setApplied(False)
+ self.SetValue(['',''])
+ def updateRadios(self):
+ if self.value[0]:
+ self.radio_std.SetValue(True)
+ self.radio_file.SetValue(False)
+ self.text.Enable(False)
+ self.button.Enable(False)
+ self.combo.Enable(True)
+ else:
+ self.radio_std.SetValue(False)
+ self.radio_file.SetValue(True)
+ self.text.Enable(True)
+ self.button.Enable(True)
+ self.combo.Enable(False)
+ def OnChange(self, evt):
+ Presenter.setApplied(False)
+ self.textModified = True
+ evt.Skip()
+ def OnCombo(self, evt):
+ Presenter.setApplied(False)
+ self.value[0] = self.combo.GetValue()
+ def GetValue(self):
+ return [self.combo.GetValue(), self.text.GetValue()]
+ def SetValue(self, value):
+ if not value:
+ self.value = ['', '']
+ else:
+ self.value = value
+ self.combo.SetValue(self.value[0])
+ self.text.ChangeValue(self.value[1]) # update text ctrl
+ self.updateRadios()
+ def OnButtonBrowse(self, evt):
+ if self.textModified: # text has newer value
+ self.value[1] = self.text.GetValue()
+ dlg = wx.FileDialog(self,
+ defaultDir = os.path.abspath(os.path.dirname(self.value[1])),
+ defaultFile = os.path.basename(self.value[1]))
+ if dlg.ShowModal() == wx.ID_OK:
+ # Get common part of selected path and current
+ if Presenter.path:
+ curpath = os.path.abspath(Presenter.path)
+ else:
+ curpath = os.path.join(os.getcwd(), '')
+ common = os.path.commonprefix([curpath, dlg.GetPath()])
+ self.SetValue(['', dlg.GetPath()[len(common):]])
+ Presenter.setApplied(False)
+ self.textModified = False
+ dlg.Destroy()
+
+class ParamImage(PPanel):
+ '''Image selector.'''
+ def __init__(self, parent, name):
+ PPanel.__init__(self, parent, name)
+ sizer = wx.BoxSizer()
+ self.text = wx.TextCtrl(self, size=wx.Size(200,textH))
+ sizer.Add(self.text, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, textB)
+ self.button = wx.Button(self, -1, 'Browse...')
+ sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
+ self.SetSizer(sizer)
+ self.button.Bind(wx.EVT_BUTTON, self.OnButtonBrowse)
+ self.text.Bind(wx.EVT_TEXT, self.OnChange)
+ def OnChange(self, evt):
+ Presenter.setApplied(False)
+ evt.Skip()
+ def GetValue(self):
+ return self.text.GetValue()
+ def SetValue(self, value):
+ self.text.ChangeValue(value)
+ def OnButtonBrowse(self, evt):
+ value = self.text.GetValue()
+ dlg = wx.FileDialog(self,
+ defaultDir = os.path.abspath(os.path.dirname(value)),
+ defaultFile = os.path.basename(value))
+ if dlg.ShowModal() == wx.ID_OK:
+ # Get common part of selected path and current
+ if Presenter.path:
+ curpath = os.path.abspath(Presenter.path)
+ else:
+ curpath = os.path.join(os.getcwd(), '')
+ common = os.path.commonprefix([curpath, dlg.GetPath()])
+ self.SetValue(dlg.GetPath()[len(common):])
+ Presenter.setApplied(False)
+ self.textModified = False
+ dlg.Destroy()
+
+class ParamCombo(PPanel):
+ values = []
+ '''Combo box.'''
+ def __init__(self, parent, name):
+ PPanel.__init__(self, parent, name)
+ sizer = wx.BoxSizer()
+ self.combo = wx.ComboBox(self, size=(220,-1))
+ if wx.Platform == '__WXMAC__':
+ sizer.Add(self.combo, 0, wx.ALL, 0)
+ else:
+ sizer.Add(self.combo, 0, wx.ALL, 2)
+ self.SetSizerAndFit(sizer)
+ self.combo.Bind(wx.EVT_TEXT, self.OnChange)
+ self.SetValues()
+ def GetValue(self):
+ return self.combo.GetValue()
+ def SetValue(self, value):
+ self.combo.SetValue(value)
+ def SetValues(self):
+ for v in self.values:
+ self.combo.Append(v)
+
+class ParamEncoding(ParamCombo):
+ '''Editing encoding attribute of the XML root node.'''
+ pass
+
+paramDict = {
+ # sizer params
+ 'flag': ParamFlag, 'orient': ParamOrient, 'option': ParamInt,
+ 'cellpos': ParamPosSize, 'cellspan': ParamPosSize,
+ 'border': ParamUnit, 'borders': ParamUnit,
+ 'cols': ParamIntP, 'rows': ParamIntP,
+ 'vgap': ParamUnit, 'hgap': ParamUnit,
+ # common window params
+ 'pos': ParamPosSize, 'size': ParamPosSize,
+ 'checkable': ParamBool, 'checked': ParamBool, 'radio': ParamBool,
+ 'accel': ParamAccel, 'help': ParamHelp, 'centered': ParamBool,
+ 'label': ParamMultilineText, 'title': ParamLongText, 'value': ParamLongText,
+ 'content': ParamContent, 'selection': ParamIntNN,
+ 'min': ParamInt, 'max': ParamInt,
+ # window attributes
+ 'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont,
+ 'enabled': ParamInverseBool, 'focused': ParamBool, 'hidden': ParamBool,
+ 'tooltip': ParamLongText,
+ # other
+ 'bitmap': ParamBitmap, 'icon': ParamBitmap,
+ 'comment': ParamComment,
+ 'wrap': ParamInt,
+ }
+'''Default classes for standard attributes.'''
+
+class StylePanel(wx.Panel):
+ '''Style panel.'''
+ equivStyles = []
+ def __init__(self, parent, styles, genericStyles=[], tag='style', equiv={}):
+ wx.Panel.__init__(self, parent, -1)
+ self.SetFont(g.smallerFont())
+ self.node = None
+ self.controls = []
+ self.tag = tag
+ self.equivStyles = equiv
+ topSizer = wx.BoxSizer(wx.HORIZONTAL)
+ if genericStyles:
+ # Generic styles
+ sizer = wx.GridSizer(cols=1, vgap=1, hgap=5)
+ label = wx.StaticText(self, label='Generic')
+ label.SetFont(g.labelFont())
+ sizer.Add(label, 0, wx.LEFT, 20)
+ for s in genericStyles:
+ if s[:2] == 'wx': label = s[2:]
+ else: label = s
+ control = wx.CheckBox(self, label=label)
+ sizer.Add(control)
+ self.controls.append((s, control))
+ topSizer.Add(sizer)
+ if styles:
+ # Specific styles
+ sizer = wx.GridSizer(cols=1, vgap=1, hgap=5)
+ if genericStyles:
+ label = wx.StaticText(self, label='Specific')
+ label.SetFont(g.labelFont())
+ sizer.Add(label, 0, wx.LEFT, 20)
+ for s in styles:
+ if s[:2] == 'wx': label = s[2:]
+ else: label = s
+ control = wx.CheckBox(self, label=label)
+ sizer.Add(control)
+ self.controls.append((s, control))
+ topSizer.Add(sizer)
+ self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
+ self.SetSizerAndFit(topSizer)
+
+ def GetValues(self):
+ checked = []
+ for s,check in self.controls:
+ if check.IsChecked(): checked.append(s)
+ return [(self.tag, '|'.join(checked))]
+
+ def SetValues(self, values):
+ styles = map(string.strip, values[0][1].split('|'))
+ for s,check in self.controls:
+ check.SetValue(s in styles or (self.equivStyles.has_key(s) and self.equivStyles[s] in styles))
+
+ def OnCheck(self, evt):
+ Presenter.setApplied(False)
+ if Listener.testWin.IsShown() and g.conf.autoRefresh and \
+ g.conf.autoRefreshPolicy == AUTO_REFRESH_POLICY_FOCUS:
+ Listener.testWin.isDirty = True
+ wx.CallAfter(Presenter.refreshTestWin)
+ evt.Skip()
+
+#############################################################################
+
+class CheckListBoxComboPopup(wx.CheckListBox, wx.combo.ComboPopup):
+
+ def __init__(self, values):
+ self.values = values
+ self.PostCreate(wx.PreCheckListBox())
+ wx.combo.ComboPopup.__init__(self)
+
+ def Create(self, parent):
+ wx.CheckListBox.Create(self, parent)
+ self.InsertItems(self.values, 0)
+ # Workaround for mac/windows - see ticket #14282
+ if wx.Platform in ['__WXMAC__', '__WXMSW__']:
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ return True
+
+ def GetControl(self):
+ return self
+
+ def OnPopup(self):
+ combo = self.GetCombo()
+ value = map(string.strip, combo.GetValue().split('|'))
+ if value == ['']: value = []
+ self.ignored = []
+ for i in value:
+ try:
+ self.Check(self.values.index(i))
+ except ValueError:
+ # Try to find equal
+ if self.equal.has_key(i):
+ self.Check(self.values.index(self.equal[i]))
+ else:
+ logger.warning('unknown flag: %s: ignored.', i)
+ self.ignored.append(i)
+
+ wx.combo.ComboPopup.OnPopup(self)
+
+ def OnDismiss(self):
+ combo = self.GetCombo()
+ value = []
+ for i in range(self.GetCount()):
+ if self.IsChecked(i):
+ value.append(self.values[i])
+ # Add ignored flags
+ value.extend(self.ignored)
+ strValue = '|'.join(value)
+ if combo.GetValue() != strValue:
+ combo.SetValue(strValue)
+ Presenter.setApplied(False)
+
+ wx.combo.ComboPopup.OnDismiss(self)
+
+ if wx.Platform in ['__WXMAC__', '__WXMSW__']:
+ def OnMotion(self, evt):
+ item = self.HitTest(evt.GetPosition())
+ if item >= 0:
+ self.Select(item)
+ self.curitem = item
+
+ def OnLeftDown(self, evt):
+ self.value = self.curitem
+ self.Check(self.value, not self.IsChecked(self.value))
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugin.py
new file mode 100644
index 0000000..f233651
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugin.py
@@ -0,0 +1,150 @@
+# Name: plugin.py
+# Purpose: Pluggable component support
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 31.05.2007
+# RCS-ID: $Id: plugin.py 69876 2011-11-30 15:46:26Z ROL $
+
+'''
+Functions for loading plugins.
+'''
+
+import os, sys, glob
+from xml.dom import minidom
+from globals import *
+from presenter import Manager
+import component
+import meta
+
+def load_plugins_from_dirs():
+ '''Load plugins from XRCEDPATH directories.'''
+ dirs = os.getenv('XRCEDPATH')
+ if dirs:
+ for dir in dirs.split(':'):
+ if os.path.isdir(dir):
+ load_plugins(dir)
+
+def load_plugins(dir):
+ '''Load plugins from C{dir}.'''
+ sys_path = sys.path
+ cwd = os.getcwd()
+ dir = os.path.abspath(os.path.normpath(dir))
+ TRACE('* load_plugins from %s' % dir)
+ os.chdir(dir)
+ sys.path = [dir] + sys_path
+ try: # try/finally shield
+ ff_py = glob.glob('[!_]*.py')
+ for f in ff_py:
+ name = os.path.splitext(f)[0]
+ TRACE('* __import__ %s', name)
+ try:
+ __import__(name, globals(), locals(), ['*'])
+ except ImportError:
+ logger.exception('importing %s failed', name)
+ ff_crx = glob.glob('*.crx')
+ for crx in ff_crx:
+ TRACE('* load_crx %s', crx)
+ try:
+ load_crx(crx)
+ except:
+ logger.exception('parsing CRX file %s failed', crx)
+ dirs = glob.glob('*/')
+ for dir in dirs:
+ if os.path.isfile(os.path.join(dir, '__init__.py')):
+ TRACE('* import __init__.py in %s', dir)
+ try:
+ __import__(dir, globals(), locals(), ['*'])
+ except ImportError:
+ logger.exception('importing __init__.py failed')
+ finally:
+ sys.path = sys_path
+ os.chdir(cwd)
+
+def load_crx(filename):
+ '''Load components defined in a manifest file.'''
+ dom = minidom.parse(filename)
+ for node in dom.documentElement.childNodes:
+ if node.nodeType == node.ELEMENT_NODE and node.tagName == 'component':
+ create_component(node)
+
+def create_component(node):
+ '''Create component from a manifest data.
+
+ @param node: DOM C{Element} object containing component manifest data.
+ '''
+ klass = node.getAttribute('class')
+ name = node.getAttribute('name')
+ TRACE('create_component %s', name)
+ comp = getattr(meta, klass)
+ compClass = getattr(component, comp.klass) # get component class
+ attributesIn = comp.getAttribute(node, 'attributes')
+ # Process attr:klass pairs
+ attributes = []
+ specials = {}
+ for a in attributesIn:
+ i = a.find(':')
+ if i != -1:
+ a,kl = a[:i],a[i+1:]
+ specials[a] = getattr(component, kl)
+ attributes.append(a)
+ attParamsIn = comp.getAttribute(node, 'params')
+ # Process attr:param_class pairs
+ params = {}
+ for a in attParamsIn:
+ i = a.find(':')
+ if i != -1:
+ a,kl = a[:i],a[i+1:]
+ params[a] = getattr(component.params, kl)
+ groups = comp.getAttribute(node, 'groups')
+ styles = comp.getAttribute(node, 'styles')
+ events = comp.getAttribute(node, 'events')
+ c = compClass(name, groups, attributes, specials=specials, params=params, events=events)
+ c.hasName = bool(comp.getAttribute(node, 'has-name'))
+ c.addStyles(*styles)
+ Manager.register(c)
+ menu = comp.getAttribute(node, 'menu')
+ label = comp.getAttribute(node, 'label')
+ if menu and label:
+ try:
+ index = int(comp.getAttribute(node, 'index'))
+ except:
+ index = 1000
+ help = comp.getAttribute(node, 'help')
+ Manager.setMenu(c, menu, label, help, index)
+ panel = comp.getAttribute(node, 'panel')
+ if panel:
+ try:
+ pos = map(int, comp.getAttribute(node, 'pos').split(','))
+ except:
+ pos = component.DEFAULT_POS
+ try:
+ span = map(int, comp.getAttribute(node, 'span').split(','))
+ except:
+ span = (1, 1)
+ Manager.setTool(c, panel, pos=pos, span=span)
+ dlName = comp.getAttribute(node, 'DL')
+ if dlName:
+ TRACE('Loading dynamic library: %s', dlName)
+ if not g._CFuncPtr:
+ try:
+ import ctypes
+ g._CFuncPtr = ctypes._CFuncPtr
+ except:
+ print 'import ctypes module failed'
+ if g._CFuncPtr:
+ dl = ctypes.CDLL(dlName)
+ try:
+ Manager.addXmlHandler(dl.AddXmlHandlers)
+ except:
+ logger.exception('DL registration failed')
+ module = comp.getAttribute(node, 'module')
+ handler = comp.getAttribute(node, 'handler')
+ if module and handler:
+ TRACE('importing handler %s from %s', handler, module)
+ try:
+ mod = __import__(module, globals(), locals(), [handler])
+ Manager.addXmlHandler(getattr(mod, handler))
+ except ImportError:
+ logger.exception("can't import handler module")
+ except AttributeError:
+ logger.exception("can't find handler class")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/_bitmaps.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/_bitmaps.py
new file mode 100644
index 0000000..9fd8584
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/_bitmaps.py
@@ -0,0 +1,321 @@
+#----------------------------------------------------------------------
+# This file was generated by ../encode_bitmaps.py
+#
+from wx.lib.embeddedimage import PyEmbeddedImage
+
+wxDialog = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAE8AAABGCAYAAACNO8lOAAAABHNCSVQICAgIfAhkiAAACuBJ"
+ "REFUeJztnFtsHNd5x3/nnJld7nKXt9WFoigpMnWJKdhS1SiyHOfSGGkrtEgNBEjSvqRF0QZ9"
+ "CJDHvgV5SV+bhyJBC6NAYSBtgCYBqgiundSxEMOJA9lWTMmSFZG2xDu5vO1ldmfOpQ8zu1pR"
+ "VOxkWqCu5w8Md3fmzNnz/c73fec7A3DFsZPnaG4sebsOHj88MHr4T621XxdC4JxD8P9TThDb"
+ "5gAhEjt3ttYRc3DOIaT4WrM69x3dWJ25M7usxUOTp/ODYxNfGNl/5B/3n3xS9Y9PenHH7j0M"
+ "432MNyaC0e3EUQTbLb4LTSG9HI35N/Xsa8+bhVtTf/3mSxeeEac+fv5g5fCpm8c++9XcxlaD"
+ "VtAEITq3/voBvCfA/zclEERby+i1dwD74IYOkIr87sMMjx2h3dziyne/oR873P8Vb3D08J/v"
+ "O/lpWV2v0Wxs4ft5hHPIXqfawcGso+PQD/xe2Q2JuJUjnslOl0KIe849qI/4+/6HJsoBUtLe"
+ "WES2qhw88RGUl0Ngk7HEzYSIfdGhaDXrrC/MEK75BLLM0JGzXq059S3PWvv1vtHjrC4s4/cV"
+ "aDdrNN55jVazgZASh7uPj3MW6RcYeug0XqEUk+yViE+1I4t1rpMv8KXE92KgxkI7MigpyHkS"
+ "0TtBLu7DEfeBg5wvYpDJtW67bd+7vY/759YhlE9zdZah3Xtp5SroVkBowZPgSYEQ0NYOYx0F"
+ "X2JzIzTCGQrNdfIjFQpjk7x68T/xhBBYa9HGgrYo3WKiWKc0LEF5XQ8RiRcJKRDOcf32Es3G"
+ "JvhFcL1uLzDWUS4ofudAmYGijxCSVmRZ3Ah4ezWgrR2VkseJiWGW64bp5QZam7uznvxRUnBy"
+ "vB/fU9xYCghaEeC6cyW3RUTHc0QvXHF/4AhnYqcA2u0Wvg05ua/I0lbEwmYbbRzHRwsMFnx+"
+ "OVvHoDDWYqxDa4O1FqUknsPhrMVai9EGXwp+7+wjPHHqCMLvQwpQSiGlTA4FQvIv33+Oi3fA"
+ "GHNPqpVC0I4MB0dyfP7MHgZVwNz8IiOVCl5xPz95s8p3X1mi1FfgYwcFr1y+yvU1hRoYJecp"
+ "BAJjDEFk6c9Jzj9SoWTW+fsbt9iUe/D8HH5CLTIW62KIzoGUAl+CcXEq8KRCO4e123OawSbV"
+ "RBQZynn4gxPDFHzJt1+cp5hTfPkTozTaltfv1NDW4pzDOocxJkkzDq8zQdZZhIsbKU/Rl88h"
+ "fR8pBLIHnvI8fCnwfQ+HS+7riSXpuqFazHlMXbnG09/7EYXyEH/zhfOcn9zH61M3aIWKQ/sO"
+ "cMPXyNoSf/LxSU4fKuELR9N4XLiywtTsFnlP4rVrBPNXGTnYz+ee+BCT+4pYa3ljrsnFK0ss"
+ "bWl2l30+d2aUybEi08sNcn6OnIh4+oUZZmuSvpyHtbHRQkhIYHjCsbTZ4kfX1vjS43v52/MH"
+ "8KSgrR3/9oslWqFGSIVzsYN1bAOBJJklbHwyPu6GQKexSxy9m7ddb/vuchBfdzFUhKMRBFTD"
+ "PNNmnEszLYYH+jiQ3yRcmWaw3E+fJ9Fhi7W1Dd65eY3Z6escGXH80XGfQb2CNlEyUMsXz43z"
+ "qYk8L//kWS6//CLnJ0ucP+Yjwi3+8NHdfObDZaZeucTNV37Myb2w398kmv4pYX0NhMQRO4dL"
+ "4t45hzHxueevVvnpzU32DeaolHx+8OoyL/9qHYlN2sQsrHXdBc7jLovuIWXsbUophBAoFYer"
+ "lPF7IUUye3QTcu8q6rqdgbNxmalKu+kb2AUOdFAjqodYrdFGM9gHR8fKHB0ZwJgIz/MYUCHF"
+ "+gymcQQrwfckHzlSYX5ujmf+40UGxo5x5mzAgUITsXqDIyMPU99a519/+CJLeoBHf3eN8TKY"
+ "oIZhE+dGux7RcRAQWGNphYZT42VOHSix3tBIKfjk8SGuztW5XQ0QMt40xODupgDZMdw6i7M2"
+ "XkmFQ4k4lyiZvCYJXCUJWPTkSmvtPe9tx3WBkeEhjh4a47FjFZ48UWFxcZlrN99O8pslNHBo"
+ "V4lPTe6hHdS58Ox/Mb+wiFQKdIiNWiilsA7mqk12VYY5d+5xPnr2MSrDQ6wuL9GszrGyUae/"
+ "VObsmTM8du5jHBgfS1aHeLT2vrCLjyDUDBckn//oXgo5yd9duMU3n3ubSsnnrz6xH5xFJ3nO"
+ "WjDGdXdfXmc973hOpC2Xr9+hXqsjVA4hQEgZ12xCxHlPwtWZRYw7iOp4regscA6cxTiobtQ4"
+ "fHCMLz81wkC5n8bqDM88f4mpmRXOfPI0K2sbtJt1FtabXH2nytjQAKdPPUpkJbWNKkaHbNZb"
+ "eFFEqx3xnUtv8WdPfIgv/fHjIBRvvXGZH77wM0KnePaXK+wq5/nsp89we2kDL6oRiXimu+ml"
+ "N90kyd5ZQ7Mdcel6ldvVgDdma2jjiLShUsrFq6vocTBnu8uj1+ncWgM2IsTjpaUiL83VQMhu"
+ "2dBZWDp7QiOG8QcKOKuTUcRtLOAJx0o95J8uvopfvYawhlZoWNmosbDeIr/vYeb1IN/895+z"
+ "MHWVFbGHf7g4xS49z+bqIi5fxjMBc9UGP/jZLWx1mvVawPrbGyysvs4uu4IJtphdXGUlkPij"
+ "R5muRlz4+S382m2UDRnf+/uEzYBmM0D1AVbHY3WJDdbgYs9gs6n53uUllARfSXKe4IXra9ik"
+ "zkNxN6qsiUszkeQ8Zw3ORDgTA1CDY9xfHXWSYxLvwsUD0OG9l5OwrjcaXKlros0BsBohJX7f"
+ "KIWJEjJfYisUXF4zyOLD5Ar9zDUU07V+pN6PwMMaQ244x1sbOazeT363QuX7mQsl05sBLlTk"
+ "ynsojpbRfon+Qo5zj+zDD4cZ6s+DbvP9iz9mraHJ7fUxUYizJsnPBvJlmptV2qHEGoef1N9R"
+ "Yp9K4ERa4EyIh8b6RXTYju124MW5qwNPxPlKR3SK+R7Hu6+6dw/g21Gxv4goH6UTI/FKZ7E4"
+ "pI0olQZw5UGsNfhAfvf+xDhHp3jPAWJwJM6rzpITgvzucUDEIWQt0lnqzTbPX55moHUbEwbM"
+ "La4ys1RDjDwEXh6jQ3rDQxQrWF2H1ZsIY7pbzXs3KfEWTSmPfOUAbfrQ7QCcSXKeVHhKgYnA"
+ "SkTPVuvdnpm823Vnkhy4rWXnkzU6/pxsoyxh92qyGMZpXcfvhaNbMvX2KQVEoeG1OxG2ncdZ"
+ "HymH8Q71IT0fRGLfPYMQuFyJ0tiHkdx1lB3tAFqhwYStJI0JnBB4prbK/OvPYdZWCZX3vn5S"
+ "0nk218FqAPNr7AmBQPbesU29t3ZLFIcTiqKM8E5N7OEv/vJJjDFIKdMO/32onWJjJ4nkwagg"
+ "CJr889O38QbKJU4cn0g2u4p3fYb3AVb80EFQr9fpL/Qlq62DMIrwrH1fR+3/vpJaOIriBw8Q"
+ "J+xOEZx53s4SAty28uKDmOR+K+0UkRm8FMrgpVAGL4UyeCmUwUuhDF4KZfBSKIOXQhm8FMrg"
+ "pVAGL4UyeCmUwUuhDF4KZfBSKIOXQhm8FMrgpVAGL4UyeCmUwUuhDF4KZfBSKIOXQhm8FMrg"
+ "pVAGL4UyeCmUwUuhDF4KZfBSKIOXQhm8FMrgpVAGL4UyeCmUwUuhDF4KZfBSKIOXQhm8FMrg"
+ "pVAGL4UyeO9RQtz/H7ldeHd/mSfTTtqJj+yc3Ilspnu1nZEnpSSKImq1Gp7nPeC2TB0559Ba"
+ "I6VEPPXUU25iYoIgCD6gvzHwm8k5h5SS6elp/htoVcToXnTr8QAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+wxFrame = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAF4AAABGCAYAAABFVyOYAAAABHNCSVQICAgIfAhkiAAADFRJ"
+ "REFUeJztnFmMHMd5x39V3TM9MzuzB7kk9yC55JKSKNGkSCnOAj4iGQKi3IKRA0GABIHi5CHI"
+ "Ux4CBMiL85DkIa8JHMBAAMM2oCSyFdgSFFti5FgWKCoWD5GiDpJL7pK73PuYu7urvjxUz+yu"
+ "uCKNQFAnUv+BwcxUd/VU/eq7ugZodf+Jz1FfnvF37T9ysHd4/DettX+rlEJEUHxyJQqUACjc"
+ "RNW28xUcBxFxDap7AFSnz/akNvdVWv9lfXH6Wdtcnpy6OR+r8YceDfqGx397YPTQ10cffsIr"
+ "7z3qK3f2zzD8/8dLowSFxsQh1sZd7B+cdadV+3mU9hxEpUAEE7UTuGrbfg64h/bz1G9diqfP"
+ "vmRmr178yjuvPf9tdfKLv7J34MCxK0d+48+D1VqDZqMOSnW63n3wP9Pi/B9UAsSETaL5K0hU"
+ "AzTbz1eBWFRpB+Xh+4mtAxqtzWJWb35In43fwcsRDB5kYPQQ7doa5/7lb+LPHar8mV8ZGnt6"
+ "5MQT3tJqlXptnVw+QImg1CZ73sawRcDeY3G02uq+Ati0F0uABHpr7gp7RvdR7h8EEfQ28zRW"
+ "0L7P3NRVWJ2kPPQACzevEdgmez8zgfZ8FBaRDRI68Qi0R6O2zurtG4TLeRr0MHDfhL/euPQ1"
+ "3xr71cLQERZn58kVioTNGrUb52jV151rIXewFbEoP6Bv7Dj5yk6wdusJye+2Y4ux0o2PnlYE"
+ "Oe0G9kEYSb872j6sXW1z3t3aO8dE0LkCjeU5PBtiy3uoGo8otkTmzk55X+GLRvr2s/z2KcaH"
+ "D9NcmaVn5ADNXD9xq0VoIOeDpxRKQSsWxAqFnMYEg9Ra1yg1Vwj6+imOPMSbL/wHvkuklthY"
+ "iC06bjNerFLpU+D7KASltItrgNbOiq/dnGO5towuDYA1W2ZnRQh8zcl9PQz2BmjtoZVitRHz"
+ "1s0qjVa4haVSjtNmZ+hYn2yCmOQzFGDFvW9ZQ7VhA1s8drNE0MpgrMFXGhvHRHHI3oGAA4MF"
+ "QKE7pyq4PNtgqdYmiiIsEBmTjFNotVoUCDk62sPUcpvFWoSxwoPDJUo5j7dmahjxsFYwVoiM"
+ "xVqL52l8EKwVrLWY2OAr+OJnj/L4ycPofBGtwPM8tNbJy0NpzXd/8GOeuWiI4xi9ybyUUkSx"
+ "pa+g+bUTgxzuFyZvTBNFMdfWFjl3ewWv/z5IKifP84iNIGLJ+R6eVhhjCWMLCvzEiowIvlZY"
+ "K0RGyPsKhXIxd5NX5nyNpxVhbImtCx9CZxEUYBFrESuA88Z2ZDg2WuTLjwyiUFsW8x9fmeH2"
+ "ahtjDQgYY7se3I4Mu8qaXz++g8gIX/vRDLsrOf7ksSHmqxHnptcxKKxYB98Y97sCvjMCB16J"
+ "G5DveRSCHF4+h1YKvQm85/nkfE2Q84HY9RW7MTXlvlsRijmf2ZnrfPM7L7LSNNSaEX7PDv7u"
+ "K7/MSstNem5plX89M8uxg3t44kgfRc8iXo7Xrq7z4oV5HjsyyJPHB5leajHSHzC33ua9200e"
+ "PdBLT+Dx3Tdu8ZMr6xTyPhPjfXzpwX56A8WNpZDnzs4ztRziKechSZZBJ+MTwFpLaAyegu+f"
+ "X+TVK2tUCj7N0PLk0QGUCMYarLEIznIRsFbwlDC93OTly8v83sQe/upX9xPkFPWW5d/emCOM"
+ "DUrTZWStuwaQeJUIiAPROdR52aRd2HhXG11cm2zuQTduiFgOHRzjj//gd/iLP/19nnzyF6kM"
+ "H+L+kTL3D0S888YpTn3vGVaunGFtZZHp61eYfPcCvVR56ngf+/UcZT/m+GgJb/l9rr/9JhNj"
+ "RR7fF3P+9Cvsrxh+6RAUGrc4vLvIH35hhB2ywtz1d/n8eInfeiiH11qhm3QQN+bE2hV0LdGK"
+ "cHs15O1bNd6brXN5pspiNXKRwNouB2dk7jomCR3fO7/AT6+vs3cgoK/g8+xP5zgzuYbGOg9B"
+ "sF1WzvP8TZwcQKFr5Z7noeiEGg+tFZ7WqMT6O4u15Qajs0BJvTs7t8ALL77E6lqVmYUV4r6D"
+ "mDjm/Ftv843nTlEvDLNndCf37enhgbEKJmyQD/KUPEt/OEO4XGJxqZ8XXn6Vti7x2Ucf5szr"
+ "Z/jW86d57PMT9Aaglt5nd34/+3cWuFbLM9BXYX1tjbJdIVi6RG3Xo/j5QjK/xIisC0AuxDpP"
+ "73y2JmkTF4ZNlFh8AjuZJdZY2qFh4mA/D470sFSL8D3F40cGuDxbZ2alhdLK9bMu3HTkdy8i"
+ "FmWdlSoleLgEp5VycV6RgFeJtUh3YGC7ERTl4nCnbLw9t8DLb06yIAPkC8OMB73duBr0D2F3"
+ "n2TP2ChfOnGAQrzCN154hYlHjnPy2INoBNuuY41F50sUKkNoP4+xhnzfbnLFMjauI3Gb1fV1"
+ "Vhohly6/z49eP0e5VKTWaDI/t0Cxt4rxAxDravhOpaUdkDix+IO7ikyM97pQExn2DgTcWm66"
+ "49YmMX7D6+vtiJFen9+d2IOxlq8+N8lwf8DTvzDK018Y4a///QoiLq6Lcd7ViQ6+c0O6DZER"
+ "zr53i1a9hvYDVx3opARUzuJ9T/HmO1PEdmeyAHQug3a+jIiwVm3QrFUpV3qRncdR5V14Zc3C"
+ "ap16tYoRhefnWWtZLlxf4uf2+vz8Iyco9PSwsLhE2G7SDCMWl1dpt5uoEiyurFOvVbHGUm22"
+ "idfWQAwXp9f5/pkpHh7bx5d3D1EoBPz49FnstMYLerDWJCXQhtWDYKxFIZy7scrJsV4+M1pK"
+ "ErJiZqXJtfl6klglifFuAcQKYi21ZsxLFxe4PFvj3dk656egHceUA98lU+1Me0uMV4nFI9YN"
+ "zMZE4nF6vsTpmRqoRmcboxu6VfLBqjJeuRdt4y1VhQU0Qr1t+PYrl6m//xrL6yFeX4SOWqzW"
+ "Pf7+2f9m5vxPiKSfQAlr9Tbf/K9rvGSmaC1OU7c+fT0BU1M3KdcrTN48xbXrMwRmmH/4zmvM"
+ "XHoP4w/xT89foDV5mvV6iG0avvXqJP8pt+kxK9QbTaZnF/GL+7BoREw3pioxiHWJz4qrO89O"
+ "VTkzudbNXx0FOY2nk1BsO5ZvsEqhtWaxFvHMmVl8T5H3NSLww4tLSXGhkxLX5Qk3Brsp1IhB"
+ "TIQk5bjXN8zGlsF2t62glbNsG4cfPAQK2m3DpdUWRsYIdvng5xAb02zGvL4YovIPEJTKiFJg"
+ "2iyHlltrBaQ9hO/7TK4K+YF+6qbM9GpIbudxQsqcnTPoyjHyhRIXZpqYcIRgt08uKNIwOS5W"
+ "y0T1EE2R/M4RcoUebNwG7XeJWmmi8kXarQaydJOYPAoh2G6qLSFSHjSWKVR20opiJN9DY3We"
+ "dt5ixZJXIDGErSR+J9eJYoWYkJwyWL9IFLaTGw3l6ngxHfDu5oc46t7UbDL4O+DLPfbICoU8"
+ "qjjmXEwsYiIUUO4pIeVxrHWxFROhlaKyYxewJ8kzKknSlkB77jxrKWuFsANrDUWlUCV3fSsW"
+ "JTE9vf3QN+AA2yRBCmCijYHZGPwCUhlC1m6hWnVwQfPOSSi3VxOUd6D799FoNFA9u7DROiy+"
+ "i7K2U+dtvWlWCiWC5+fI79hHm4C43QQxKMBX2sfzPDcwq1GbMu+99h7vddx5t2xsn3bCkXFf"
+ "1ObVBewmD+s2K7Bx1P0xa9w5ne2QD17fdgHfbcPW8TTaozh4gNI9JqKA0AqtdgvVSWiFPirl"
+ "gXtuJYpAMzKYsNUtPgSFb2qLzJ77AWZ5kdDztwa4T7gEaCvV3Q7Z/qSOMWyUzgAh0ND6Lv02"
+ "X8J2zUmUR0lH+A+P7+LpP3oCY4yrzT91kg/LZJvO2P5vkk5ouve/EorOvn2z2eCfv34Dv7dS"
+ "5ugDh7DG4Pk+d3ecTP9bibh9rFq1SqlY6FQ1EMYxfveWNtNHLwc2jNz+lg8u0ehurMvIf9Ry"
+ "hYDqfgb4NAb1j13bRZEMfErKwKekDHxKysCnpAx8SsrAp6QMfErKwKekDHxKysCnpAx8SsrA"
+ "p6QMfErKwKekDHxKysCnpAx8SsrAp6QMfErKwKekDHxKysCnpAx8SsrAp6QMfErKwKekDHxK"
+ "ysCnpAx8SsrAp6QMfErKwKekDHxKysCnpAx8SsrAp6QMfErKwKekDHxKysCnpAx8SsrAp6QM"
+ "fErKwH8M2u5BRF3wG09MzfRRazu2evNTUTN9fPK11kRRRLVaxff9tMfziZaIuKePa4166qmn"
+ "5PDhwzSbzU/pM8k+PokIWmuuXr3K/wCobQ9DCns9YgAAAABJRU5ErkJggg==")
+
+#----------------------------------------------------------------------
+wxPanel = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAE0AAABGCAIAAAAGrI4kAAAAA3NCSVQICAjb4U/gAAAAyklE"
+ "QVRoge3bsQnEQAxEUY3ZGhZ34Zrd3YJLEEgX+LKLjeHfvGg300exdJ6npKAbkvZ9n3NW1dvD"
+ "PELSWmtExJzzOI6qQi62qjJz3K+q2rbt7ZEe8a27P8hN3iRJYu7wlztZ3MniThZ3sriTxZ0s"
+ "7mRxJ4s7WdzJ4k4Wd7K4k8WdLO5kcSeLO1ncyeJOFneyuJPFnSzuZHEniztZ3MniThZ3sriT"
+ "xZ0sf9bZ3e/O8ajuHhEhqbszE3kF2t2SRkSstTITebd8R17X9QFVODvBZcI23wAAAABJRU5E"
+ "rkJggg==")
+
+#----------------------------------------------------------------------
+wxPropertySheetDialog = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAE0AAABMCAYAAAAoVToVAAAABHNCSVQICAgIfAhkiAAADmJJ"
+ "REFUeJztnHlsFFeawH+vumy320fbbWN84cbGNnEaMA7HgjFoMJlBgzLs5lAynrAi0Yxg2Wh2"
+ "pdUqGYn8kc2xEknQrnb/cVaMQjZBWZIMyYZNpJAMs5OQ2EDAgA+MjTHYGLtt4/voq+rtH31g"
+ "46Od9gVZ/6RSlfq9evW9733f+95R1QIf1hzbT5OyVj4bboopYYFRuIb632+/Vvn2jfrqLwEE"
+ "gDXH9tfrHvttaVTqA6aIRZnzK+E9iLOjkcFbtUNnj/3739yor35XtebYfrrusd++FZGzNXJY"
+ "kwz1Dc23jLOO5hrG0VKJPtwXNG/kknxM8akIq8UUt6L2LaBNTcpa+Wtj8vLIYZcHTZezL/E8"
+ "IzU3wy3VpOcWEGW2BM1/7WIZZpOKU8QSk26LHL5V+2s1PDLmKUP8Epy9g95C3Q6GL59AKmGT"
+ "FuaOTCQuay0IMSOVmSt0lwM8DlyKCWffcPD8pkQcXa2IRXGYkrNRwoxPqQC6puPxaACoukZ+"
+ "ShgmcyJCKAgBQogxx4lzDbjd+QjFMOED40wqW5bHAyAlOD06ta2DNHc5kPNk1LpH9551HV3X"
+ "saWaiI1UKWvwump6fAS2VBNfVHcDoGkampR4PBqa5hVaBZBSouvewgwGwfai1dhsNgwGA4qi"
+ "3DkrCorv+uL1Q/TpOoKJLS0hSmXf1nTqG65zs9VOzoNZdC2PofSra1zrAVVRkFL6jFXg1nSE"
+ "EBgUEAgkEk33yqcIgUERvvz+NImUoCgCg68MfPfoE7SKlDoC0HQdTdNYtzSazTlmVEVyoXmQ"
+ "v9+WQoo5nM8udfqUK9F9+pHyLqX5f9B1r1CKogQOoQiEogQORVFAgC51FKlMqDR/mZ999Q3v"
+ "//ECv9hWyO9+81ck9V1EN+VQum8zVc39hOGkrLqJDyv6efihpTz60CJUfRiPMHLsezt/qu2i"
+ "YGkcLz+Ww/nGbhJMClIJ49++aKDq1jB7tlrZtCwGx1A/bsJ4/9R1/tzgRKjhYy1Nlxh8SvNo"
+ "GqX/e5OYCIW//UkqAPY+Fy/8oQGPpgWULKWOrsu7lDaiggjvWSh3XFERCkrg2nvGd6OcxM/8"
+ "KduLN5GXv4bsjBTa7B1ca6gnLD0GAK2vhX95+yM6e4dIyVrFrzZs5OL57zn6P3/kl4/uoGR9"
+ "DrW1tUgZB8Ctq5d4/0wl/7DnV/wsU6e2oZPtK9bQ1tbKkY+/oGfQyY2brTij8ohYtAzE3Y3q"
+ "lUr63BPgo3PtFGabAbjQ1E992+Cohvdbm/9e1ZcSqLyU0mthYoSljbI873VAYZMpzZfW2dlF"
+ "9aVazpY7KD9fRcewgZVLIwD49kwFVbcchC/OY/niJSREh3O+uo7qDkG1XecnG6II66zEsygR"
+ "gEuXr3Lm+iCDLklchAT7JUpPLKUwHZ76xTYio838839+RcdtBV3TEAYxrkyapuPx6KTGRfC7"
+ "n1tp73PRPeimOM9Cc5eDj8+1B/JrukSO555+rUtxxz0Dljbi2hscvH2HHqRP8z/k3KXL/Nef"
+ "ajBEWRBROUQkJWCITQHA5dYwRCegWjLoIZbWXifFRX+BKyqNLQ9l03KrjY72dqKtvQBs2bgO"
+ "U1IX8TEmLlW009/bQ2wEfHG6jlWZCTy6fSnpkQ5qRCxSKEhfvQIy+YZVfvd8dM0iFAGvHb9G"
+ "Y8cQ//jzTH6zJY0Pz7TesTTf4bcP1VdUwPSGnR5+f7yc+G9q7igKn0uOiKT2fh3VAneccCwu"
+ "t0azvYu+gUFUczIRqSvAEI4QCm4R7k3rHwDFAEJwvWOQfz12lr/Mj+fRjdl025v4j4/+m6Ze"
+ "SZYvSnd0tLM+J4XKqmre/cPneNQElibF8FDaCsIMgmOffcWpstNoltUoURaEQb27KQFv9NQ0"
+ "jbe/bubIdy3Ye50AvPF5A7//cxhaoE+TAcWNck+p60jN4y1MKLTEF9LiV4Zk9NmHki5Aakht"
+ "dEuOpNHexy9fPYartY7w5OVIn11KqY9N0zy4EZy75aGs4hs8HY1IzYUSaSYsxYYweYcu5yrr"
+ "OPHuSaTHhSHSQlhiJi8fPY+z6Xs0x4A3+sakEW6KR0odfPUKqExzA3csraNPG5XeO6TRO+S6"
+ "k1/3Dvql5kbq2gilSQ39rsKZxO38StQ1bfI8gGqxYjCngFCQyEDjTJYWtigb1WIN9JfCoKJh"
+ "YHDYiUfTUM2pqAlWEArCEA6KgjGr0KskKb2/q+FeY+CuRhUGHLoKbQ3oYVFB5Vf6bqGk5uFw"
+ "Ob3lE7A0LdACs4JvdiE1DdCmlibUQLtJCeVX7BT/3Un0/nbCkx/w3ie84zw0DYTBe/jw9mXj"
+ "e0F4YiairwWt73pQ0SPSVjEwNOwrc4Sl4XYgHcEnr/NNePwSiF8CgHQOhFyO0wHhEbEYIuOD"
+ "5h3sbr8zrPJbmpkeEm6XExc2cd/0o2RiQxzNiDiiaRqmOIG6cnkW//Tic7jds+iePxIGBgZ4"
+ "5ZUmlMlG9AuMjyLus6Wde4GJZ9sLTMjdw+Vxaenopa65HZf77rHcXCOwxEbxYOZiooxjVzDm"
+ "CjVYn3a7b4i3PjtP83A00jD5au5cEK518jN7Nzs32QgPm3gBdDZRg/Vpx7+tJi4lk9RYS7A5"
+ "wqwjAV3zcLaumr6WjzEK17j5FEUhLi6O1atXk5ycPONyBLU0o7uHfdtXY44JPuWYC3Rd51NX"
+ "LYnmbLKs6RPmaWtro7KycnaUFszSYlU3qjL5YuNcE616MIYpuFzjWxpAcnIyNTU1s/L8+3Kc"
+ "NhWZFUUJrBHONFMactxLir0XZJnSkAPuDWHvFaastPHQNC2gTCEEBsP0hwD6iA0Pg8HA3X3u"
+ "yJ2z+SJkpfX29rJ37140TSMyMhJFUXjuuedYt27dtAT68MMPOX78OGfPnuXIkSOsXbt2WuXN"
+ "BkGjp5+7W9ff4m+++SZpaWkcPXqUI0eO0NjYyLfffovFYmHv3r0sXrwYu91OaWkpLpeLBx98"
+ "kPT0dDZv3kxFRQXHjh3DaDSya9cuMjMzKSoqoqCggDfeeGNcq7oXLG3ageDixYuUl5dz4cIF"
+ "li1bRkFBAfv372fx4sW8/vrraJrGa6+9RnZ2Nvv27eOdd96hrq6Oq1evUlpayhNPPEFBQQEH"
+ "DhwAIDU1lbS0NMLD52+aFIygg1s/47U4QEVFBRaLhQ0bNrB+/XrKy8u5cuUKt2/fprq6mp6e"
+ "Hq5evcqrr75KTEwMxcXFADQ0NFBXV8enn37K0NAQ33333ai914meey8wrUAAsHv3bjIyMtB1"
+ "ncOHD1NfX8+uXbu4cuUKNTU1qKpKWFgY3d3dREVF0dXVRUJCApGRkWRnZ7Nz506MRiMlJd4X"
+ "MP3u59+L9b+74edeUOKU+7SpEB0dTVdXF6dOneLmzZt4PB6io6PZuXMnBw8eJC8vj6qqKnJz"
+ "c7HZbGRkZPDll18SHR2N0WgkPz+fkydPcu7cOaqqqjh69Ch9fX1s27Zt1HPmW3Ehu6fJZGL/"
+ "/v0kJSUFrGHHjh1kZ2fjcDjYunUrjz/+OEIInnzySVasWIGmady4cQOj0UhCQgL79u2jsbER"
+ "t9tNYmIiUkrS09MxGAysX78egJSUlHvOXadkaeMJqqoqNptt1G9RUVEUFBSMyXv79m0uX74M"
+ "QGtrK7t37wYgMTGRxMTEUXlzc3PJzc39wfLMJVO2tOlgNpuxWCy43W5eeOEFcnJyZv2Zs8m0"
+ "A8FUMJvNPPLII3PxqDnhvpt73gtyLGyshMDCFl4ITMk9tSm8HTRXCCGIjIzk/PnzqOrE4gsh"
+ "6Onp4YMPPphy2bquY7Va2bhx46T5phQ9Z2LJZ6YQQlBUVMSWLVtmvOyOjg7KysqC5puT6DnT"
+ "jFxzm0mm6lELgSAEFgJBCNyXu1HzzYJ7hsC0loaCWemP1fVDjp66rlNXf5WOjs5x05daM0hP"
+ "T/tRKm5afVplZTUWi4UlS9JHHZqu09R8c0x+u93OwYMH6erq4vDhw9OeR1ZVVfHSSy/x9NNP"
+ "c+LEiWmV9UMI2T2FEAhF8MDyXMzm2FFpUkra2trGWFl0dDSbN2/m4sWLHDp0iKSkJDZt2oTL"
+ "5aKmpgYpJTabDYvFQnV1NUajkebmZgwGA6tXr+bGjRvY7XYyMzPJysoiJiaGhx9+GFVVaWpq"
+ "ClkJP5RpDm4nVrgY8/UbtLW1ceDAAZ599lncbjfd3d309/dz6NAhYmJi0HWdsrIy9uzZw6FD"
+ "h9B1ncLCQsrKyjh+/Di5ubm4XC4++eQTXnzxRaxWK1arlQsXLkyvGj+QkKOn9xupydMnwmaz"
+ "kZKSQklJCQMDA1RUVLB27Vry8/MpLy+nv78fKSU7duygpKSEPXv2UF9fT0lJCc888wwA7e3t"
+ "oYo+baa1cjvZF3hTfQPQ6XTS1dUVmIAXFxdjMpkA73K4EAKTyURERATR0dE4HA4MBsO8LiJM"
+ "q09DQHd3Nx7P6Hdx+/v7J1VoVJT3BcErV66QlJTEqlWrWLlyJVlZWdjt9ilvFPf29tLe3k5n"
+ "ZycRERE0NTWRkZERUn1+CIaioqKXtm7dOuEEuL6+nszMzDHLMEIIPB6NquoaGq41jjp6e/vI"
+ "yV6GOXZ0gPDvYxYWFgJw8uRJ1qxZw5o1azh16hSnT59GVVXy8vLQNI3c3Fzi4uIC9/k3bVwu"
+ "F7m5uTQ2NvLee+/hdrtxOBy0tLSwYcOGkJUxNDRES0vLhHsYLpeLr7/+GvH888/Ll19+ecIv"
+ "Vj7//HOKi4sxGo1j0oJZ6f02Revs7OTMmTPs2LFj3HTvFyuvTC963m9KmSkW5p4hsLA0FAIL"
+ "lhYCC+tpIbBgaSEwpejZ29uLw+GYbVnmnanWMeiMIC0tjdOnT8+ETPcFVqs1aJ6gc8/8/Hzy"
+ "8/NnSqYfBQtDjhBYCAQhsDDkCIEFSwuBBaWFgCqEwOl0Mjwc/J84/7/j/yhX7Ny5U2ZlZS38"
+ "A8wUaWxs5P8AE8WsR2Tbeb8AAAAASUVORK5CYII=")
+
+#----------------------------------------------------------------------
+wxWizard = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAAIsAAABOCAYAAAAQPOX4AAAABHNCSVQICAgIfAhkiAAAF4JJ"
+ "REFUeJztnXl4VdXd7z97n2GfMeckOZlzMhASCAgyakVRJmdLK9ah7+stb1+tw9OqfSvFVmt7"
+ "b7nX9nnt7dtWbav11VptHajloiIiCIpihDCFwTBKICFkICRnyBn33uv+cZLDnIQQQ6Dn8zwH"
+ "nuyzztpr/fZ3/9Zvr70GiS4sNsc9+cPHPJtXdhEpUgAc2ruNxj1b742Egs8BSAB2p0tc/Z2f"
+ "4yq+GCWr9NyWMMWQIdq6D9/+Gpb/6ad0BnyS0WJz3HP1dxZgH3UtYU0Q8ocAsBgEVqPAbJRp"
+ "jwhimnSOi57ibNFiESINW9Ai/l7T2orGYXPnYxqewbBpd7L7g5fuMeYPH/Osw3sR4ZiKpgvy"
+ "bXHKHVHSHTI2EcBulvmoycn+oILHBoc7daK6YRCqlmIgEVqccON2vBXjsbkyek3/Rc2nuKxG"
+ "opITV8nFpOcPe9aYN+wiDOlFRH2dAKQZInh8n9PeqlMX1uhUsmmVFbIUldnlVnYfPMIR1Upz"
+ "2EhbxEAgLn/Z9UwxAOjRCMQjRGUbEX+49/Q2D5EjjUhZldhyy3HlDsMIoOs6qqoBsKXNzCHD"
+ "MDo0O8E9azH41yOP+xqZmkrVui3Ej9TjLfEyo7Kc9+pkqhu1L7eWZ4gsSYwrcpLhMLGq9giy"
+ "BFdUpBON62w+EECWYVxRGp1RjUhcI9+tsL7Ojy+kDmg5nBYj44udBCIqm/YHBjTv/qBrieuk"
+ "6zq6rlOZZ8NpMbBuX6JsBekKlblWVtR2AKBpOpoQqKqGpgmAhFiELtB1PZEZcEhzAiAXjSey"
+ "egNK2E9b1EjVp8sxV17Jfr+X2s1+mmNOdN00qJXuDVmWmFjsYPb4bNas/pDM4RO5a2o+4VCQ"
+ "x2pryPBWcvfUfJat/JjGOIw02ahuqEWzj0A2W45mJEDQ9QRwTLgmEnZDOuaYhIQAhBDJ426b"
+ "gTsvy2VH7Q6qqr/A7Cn5UuvdG0LXkQCtSyxTypxMKUtDlgQ19Z08OCMPb4bCsu1HgISohBDJ"
+ "/6FbLEIkDxyHUUEfdjmmxY+jIROd/C9ouRcTjkFTzN5djMGoa5+Ja4LtBwPceLGH0RlxbEo7"
+ "8WiIWDiIJ1ZPrlJEVpqJj9d8yrQrr+ArE0bx95Ub+M7V2YzMd+Kw20lz2nnmrY28t1tlziWF"
+ "XFVmxW4W6AYbf/uskRXbD/P83eOQJYnWjk78AR9/WL6PQm8+90wvQhER9rZGcSgGtIifUP1m"
+ "jOmFSPK5i/V0ITCQEIuqqjyzsp40SzEPzSwAoCUQY/7CPcTVhIcVQqALga6LE8TS9eWpMOUM"
+ "p62jHVvJBOSC0adNN5Ro8kU5HIwzfvRwwqrO5zt209kZ5OIRxaRlmYhEIuzZ38gMxQ66jh4J"
+ "8vKqnbjD+5k7ZxZup43Plr5GyDmOHfUWpLY2XFYDUyaN4aZKK1XVDQgxFoUY7yx+k8/3NXEw"
+ "CD+c812UuI/fPf9XikuGMbHkumSZhBBH3dK5oOvcosuzALy+rplLStMA2LQ/wK6mzmOSd4lF"
+ "CLodgrE7o9OJQFZsqLqE7M4Hs+28EMuhjiiHOqJcOq6SDl+A1xcvw+XJ5cYrx6NYbGz9fBcR"
+ "3YhkSjQ7Qug0d4S56dpZ5HgyePT//Jo9HTK5OWbunFpKlqWA5pbDWM0mIsYwpo69iFiYvYcO"
+ "8snm3QSc5Rgy0ijJsrN16142fnGEdttwbo4cjefOtVi6r5um6aiqTnaamYevLaItGMcfVpk2"
+ "Mp29LSGW1BxOptd0gdD1ZLG7PMvRmOVYyjxGKrNNvGkCQ9xPtiWMw+FA13UafSqd8aHZ9+IL"
+ "xalr6WT8pFxcTgfbd31BoTmPDE8OmU4L769YBbYMJMPReOuGCV5uurSU91Z8hDurkOKsHEwZ"
+ "XiryHNTu2Mmipav4H9+4CbPJALqKQCRcttmB0e1FtrnZ0xKmoqyEq6+8lOKK0aSn2ZL5C5Ew"
+ "/LkiKRZdR9U0bpucjWKU+cU7X7C3JcQjN5Zy/wwvizc2H1deXZzQDJ0YdphkKHAb+MHVuWTa"
+ "TbxvU8iINTJ3okJWdgadwSDPr2mnM24evNqeAUIIaur9XF5mo27fPjpCMURApr4tRCzkZ2vt"
+ "LmSHh5Bm5HC7D1XVGO114/P5GDNqBKMqR/Lq8o2sbQvxZtU+Litxccmk8bR3RjGKOKqq0h4I"
+ "4/P5E27akDDjf6/cw7cmuZg9dSx7GlqoP2jFHwh2F+q4QPkcGAVIBK6apvHymgbeWNtI/ZEI"
+ "AE8u2UtWmoLW9dTU3QyJY5oh6fKvf0d4r3uQptZ2AIwGmD02jdnjs3A5rAgheOPFl/BkZjLl"
+ "6plYrFY27mnlf7/XMtRi25OI1K0jfngfBocHS9F4hKYR2vUhSGAtnoQho5hQ7XLQ4igFYwnX"
+ "rQX9aNNhKZ6MwZlN5MBGtGALRocHNdiGQbFjyq0kUleN0elBKbkU2WxDCJ14235ijVsRmorB"
+ "mobWeQSTuwBl2FeQpHMX4Ip4GCVYj1wwjnAk2nv6zsNYtQB6+jCiwQ5aPnyu+9FZQ9cTUbAk"
+ "gRb2s7ImhtGsYDQacU+4FtlsJqybqGvs5C+ftaFrA9sv8WVgLhiDKWdE4g+jgmSWsY2+FnQd"
+ "yWBECB1L2eWgqUhGE7ZRie+SyDKYLFhKJiO0WCJPSU783mhO5CV0kA1J+xnd+RgcHhAaSVfS"
+ "5dKFdA7vLkkmoknQUocwO3pP7zuIXFBJNBZFiIRNkmIRahyAiAr/2BIHeu/lOy8wJJrKRICp"
+ "gWwCucspqnGQDGA0JP6WZTihQ1poKiCBQTl6sPv3ciLmEbp+gsiMdLfwx+dzbjFnD0dqryPe"
+ "Wt9rWlvJJIKdifeEosvbJmqkRhHRc9/LmOLLJRoNoNg8KM7cXtMG21uOPvl2i8WutWNt/IRi"
+ "9dwrP8UgEDzzn+i6jtkpMI6rHMbPf/4g8Xh84AuW4oIgGAyyYEHjiS10ihSnJyWWFH0mJZYU"
+ "fSYllhR9xth7kr4hhKC9vZ26ujqampoQQjBypJWCggoUpQBJGprvkVL0nQERixCCJe++y6Jl"
+ "q7AWjCKeNoyOkMS/Z/5fXng9i+EFV/Evd9yOoii9Z5ZiyHJWYpHlz/H7dX77+7fpMFu47F/v"
+ "QugSlrw8pPhOHLZCPjI9zsK332TVmsdY8NgDFBcXD1TZUwwyZxWzSNJB/IF5FI/t4NY7Z9BY"
+ "8xZv/M+57F73DBUZT7OhPo/wFyvQkVi5N4MnfvXseTEeJsWpOSuxbNqUxXN/L2H2dXsozdiG"
+ "TTbyran1GDc9z1M/2cr2516gtO5xFIuCIWMUb37s46233h6osqcYZPrdDOm6zpL3VmAaezf7"
+ "gk1kW5qJxaNkeGW+eb1EW1sHVrPEY08VsVsrQ2oOoKdN5G8L3+Waa67GarUOZD1SDAL9Fovf"
+ "76fBD1mKj0BnOtUrDtC25TVG/asRixkKCgwc2K+y90gW7sIIXxu/nFhnjDQtSEtLI8XFZQNZ"
+ "jxSDQL/FEggE6IgaEUd0Xnrqz7RULWXB3TI5ipHOOoFkEDhDEjeN2MyLNe+zX7FjUtJoaozT"
+ "1uYjFeeef/RbLIqiYDIYaWgWqIFGMvMn8pu36hnmbeS7Uy2YPBJtUcGIYVGkt9/h3cZvY80b"
+ "TXbnekymoTXXKEXf6LdYqqqq0Js2Yj28F6tUwm3frKTR/yJP/MrNrZeH+fjvUVrX6zxbX4DP"
+ "MRlbgQlddpLj8FNYWDiAVUgxWPRLLOvXr6empoZv3n4r0WiU5uZmMj3vs1WLY794FL98bQ1V"
+ "2xzc7Agx1uZjbcYwlNyRBOoPMP36YaSnpw90PVIMAv16dH7ppZe45ZZbWLRoEY/8+HGee/VV"
+ "Gv0HeeODb6KMjrK8Q0K7XeKjeJwJriCeyGdEOqIU6mu5+665A12HFINEvzxLPB6ntbWVSCTC"
+ "sFIvRlOY3/zGQl0A7CaBeZYFzNAx3kVHTYCLIuv5vC2DX/7kTtxu90DXIcUg0S+xTJkyhcWL"
+ "F1NeXk5ZWRlOp5Oy4RX8r98+T2PHXnSzitVsJmSOsyEucb0rhqsoyCWTxw10+VMMIv0Si81m"
+ "o7W1lTlz5jBq1CiampoYPXo0WZ4M5s2bh1cfR0FRAWk5acSuDeOrWoj7UA3rqtZw7Q03DXQd"
+ "UgwS/RJLcXEx7e3tuFwuPB4Pra2tHDhwgNLSUubPn8/WrVuZN28eVqsVn8/Hw3dvp6ypmrdf"
+ "+W+uvu4GZDk1jOZ8pF9XbfLkyYwdO5a6ujo6OzvJz8+nubmZqqoqQqEQQgg6OhKLwrhcLuZ+"
+ "bx5VkXTCukw02vtsuBRDk373s8ydO5eFCxcSCoW44YYbaGhoYMeOHciyTCgUOi7tJV+5jB88"
+ "+UfGjh2beid0HtPv9mDEiBE8/PDDNDU18corr1BdXc3mzZvZvn07Y8aMITMzM5lWURSmTZtG"
+ "RkbvC9+lGHo4HInprv32LJIkYbPZuOuuu1iyZAnZ2dl8+9vfprS0FKNxwEZrphhCGIGzmmDm"
+ "dDq54447BqxAKYYewWBiGmPqsSRFn0mJJUWfSYklRZ/pUyTa3t6e7DdJceFRWtq3zT36JBaP"
+ "x0NOTs5ZFSjF0CUWi/UpXZ/EomlacmG6FP+8pGKWFH0mJZYUvdLdg5sSS4o+02PMoqoqDQ0H"
+ "icaiQ37N2/4gG2Sys7JwuVy9pg2Hw7QdOXJBLqcmyzJ2m53MzIweV7voUSx1+w+w8sPV2Gw2"
+ "rFYL0jldInrg0TSNtDQnV029Aovl9Cs8xONxNm/ZSiAYxCAbLrjlQwyyTGcoxCWTJ+HJPP3L"
+ "3h7FsqZqLcOHD8ftdhMOhy845xIMBtm5cycjK8opLi46bbrGQ03EY3FmTZ+G2XzhLRsihGDX"
+ "7t1s2LCRa6+ZddL33e+GehRLLBol3e2muLiIdHfvrvp8Y9VHnyDJBmK9NC1+f4A0lwvZYEzu"
+ "x3OhkZ+fz8efrOkxTY9ikSQJJAlVVU+5a8j5jkD0sWFNbHZwIfc1ia6NqHqibwNPetiP6J+J"
+ "09lACEEsFsNgMGAwnDqmSWyJN3Rjnb5c3z6Jpaedzv7ZOJUd2tvbWf3eUjJzcxl/yaXYbLak"
+ "MILBIOvXV5OVlU1FRcWQnec9cGI5C8/S0tJCS0tLcqPJzEwPCEFuXt4pz9Pc3IzD4Uh2BB37"
+ "XVNTEw6HA6fT2a+ynHzCM0t7Ojts37ge48aP2NHaRtOBOmbOvhmXy4Wvo4NVi/9B8NMPWG+y"
+ "IT/wMOXlFRgMR7eSCXV20tTcRCQcwWgykZmZedyQ1IGmo6ODaDR60ru+ARNLf9F0nVdefpma"
+ "LTWMGTMGgIkTJyIE5OTmnuSWNV2ntraWktLSk8QSi8V45pmnmT59BjNnzvwyi31aTmVOAWgC"
+ "DG3NjA22sfmtV1ltMHDJzGuofu8dWP0epkMNhPKG4/f70XU9KRafz8cf//AHYvEYVquVWCyG"
+ "1WLlP37wgy+tDh+sWMGu3bt55Ec/Qj7DZrGPYumnZxECgeC6665PDr1ct24t69dvoNBbyO9+"
+ "81u8RUXs3LmD6dNn8LWvf40dO2pxOBwIXefPf36R+gP1ZGVn8dBD3wdg06aNLFr0D+LxOA89"
+ "9H0qKyvPvFz9QHTX5xR2GDlmLIuzS9EPN3OR5Kdm8av8fe9e3HtriDYdYm96PuNmXk9eXj6S"
+ "LCc8FPDaa69hNpu57/77cTqdRKNR2o60IYQgEAzy2//6L/bV7cNb6OV7Dz5AOBTiiSeeoKxs"
+ "ODtqa5k6dSq33XEHsiSxbNkyli59F1VVuf6665lzyy3U19fz7B//SFNzE7NmzuLmOXMQXcE6"
+ "XWU4rn690MdmqH8duN2GXbt2LQBWmxWhCxoa6gl1hti2bRv33ncft956K4//5CdMnjyZhoYG"
+ "yssrqKmpIRaL8bunnyYYDGCz2UFAa2srTz75K95f/j5PP/UUT//+9/0oWX8QyYt8IhmZmVxx"
+ "512seD5C2d7NjA42c2TLajpDETaZXVwx+xtcevkVZGVnI8syAgiFQnxWVcWPH30UZ1piB1TF"
+ "YiE/vwBBoqPsvvvvx5mWxjNPP8XLf3mZG2+6kW1bt3Lfffdz2+238/hjj/KVyy6jtraWlR98"
+ "wBO/+CUOu53Dhw8TV1We/M//5KavfpWpU6fy6KM/Jis7u7sqiWtzjGfpizPo07sh0W2oM/2Q"
+ "EJrDYScjIwO3252YjdglvuKSYioqKsjMzMThdBCJRpLnnDx5Mpqq8fB/fJ9P13yazG/atOmY"
+ "FYXRoy/icNvh5CbV/fmcEeJooH/iR5IkSsvKmPD129hqz8ZgT6NIj2KIhrEoZvLy8/F4PJiM"
+ "xuPPLZ06v+7Y7ZlnnuaB732XDz/8kEOHGhG6oNDrZWRlJenp6bjc7q6OxR1MvepKXC4XBqOR"
+ "nNxcfL4Otm3byt/++goPPfggmzdvprm5KXnjn1iXEz3NqejjozP92ma2ezPGUaNGMXPWLCRg"
+ "xYoVCVcoBLIsI3VNZZWQELroOo2gpKSEn/7sZzQ3N/PII/MZMWIEIBLTTIRAlqTkDqFSP6fD"
+ "9m6ekyp0Wjt0tLfTuH0LwxWJuk6dwxGVyXYziq+B9QtfIT09g4qRIzF1TZOxWixMnz6DN954"
+ "nXvvvY/0jAzCoRCNhxrxFnr5xS+e4KavzuaHP5zPa6+9yvbt2xFdNjsaa0hIkkRuTi67du4i"
+ "EolgNpkIhULYrDa8RUXMf+RHlJeXEwqFMBqNLF36Lt1e8tiI5dw/DYmui98ltmMfwZP5dR9P"
+ "xkWJzqH11dUsW7aMuBqnuLiYtLS0pJCSzcExd/tgcDo7tB05wqrX/4pxy2d0tjTxubsAW2UJ"
+ "NbXVXGwFdd82Plm0EPe/30NeXl4ysJ89ezZ/+ctL/PrXv07mlZeby7333ce4ceNY8s7brK9e"
+ "h9/nx2A0dHmAo/ETJLzajJkzefHFF/jZT3+KyWRkwoQJ3HzzHO68806e/9OfUBQFZ5qTOXNu"
+ "Oel6JOt2zL+nQ5o/f754/PHHT/nl8y+8xMRJk8jO8uDuR3e/ruusXfsZBtmA1ZbY49jr9SLL"
+ "Mlarlc5gEHd6OkIIfD4fdrudcDiMoigIXccfCCCEwGazYbfbCQaDKIqCoiS2lPX5fGc1y7Fq"
+ "bTU7andw7dUzKB9++tUzt27bjqpqjBg54pRi+Wj5+7QtfIHYoQa2OLIZN/sbjLl4HBtXLSf6"
+ "0VJGxf2sMWUy5aFHmHTJpZhMJvx+H/v3HyAWixEI+FHjKrIh8fY3Ny+P3NxcfD4fABaLBSEE"
+ "drudQCBAepfN/H4/NpsNk8lEOBTCH0hsXWi32xP7b2saHT4f8VgMo8lEWloaqqqiqupJ3Q/R"
+ "aJRF/28xd/3bt06qX2JzqgV97ZTr352rqiofr1593LG5c/+NnNzEHn3uruXCJElKLvJzbKeV"
+ "5YR50WldgSCAwWAY1OmwR+/mE44LQWZuLpt0I83uQi665gYunTKFvNw8MjMzWWmxsW7lu/jN"
+ "NjRNT742aWpqYum7S055rvKKCm6+eQ7Z3QHpMaQfY7Njh1ZYbbbkDdmNfAobnU2nYJ9jlv64"
+ "epPJxA/nP3Jydudpb/DpmrzyihHwwDx8/gAFXi+5uXmJDjaPh2tuvoVNXi/hSBRvUREGQ6I5"
+ "KS+vOKVtkucaZBt1N3E90WfPcr5e4B45oyqd/inKZDIxYtRoNE1Lvh+Co3f/5VdOQ1XjmM1K"
+ "4tF5CNpywAJcXRNo2oX41vkM0grQNL0Ho0oYDAlznmgrg8HYJSBpyNqxL6MKeh2iIITgSHs7"
+ "4Uikp6TnJaoaR9f1XocpGA0G4qpKOBxBF0PzYp8tkXAYRTH3mKZHseTkZLNz1y4sFutxL78u"
+ "BATQGQxiMhlx9PJi0pPlYcPGzSiKBavN3q8+p6GMruvs2rWLERXlPabrUSxXXnE5qz5cnej5"
+ "G9DiDQ0URWHm9KvIzvL0mM6TmcmYi0axrnoD7e0dQzLmOBsURaGsbBgXjx3TY7oexeJypfGN"
+ "W74+oAUbaui63usIOEmS8BYWUuT1DlKpzg292aFHsQghLsipD/3hQhxWeqYYIdFDd+L4ke4R"
+ "3SlSdK8wagRYsGDBOS1MiqFPXV0d/x9DK+bUFdQgewAAAABJRU5ErkJggg==")
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/DynamicSashWindow.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/DynamicSashWindow.png
new file mode 100644
index 0000000..dccc64e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/DynamicSashWindow.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/EditableListBox.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/EditableListBox.png
new file mode 100644
index 0000000..eab8bda
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/EditableListBox.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/LEDNumberCtrl.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/LEDNumberCtrl.png
new file mode 100644
index 0000000..72ad2d0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/LEDNumberCtrl.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/TreeListCtrl.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/TreeListCtrl.png
new file mode 100644
index 0000000..5ca19e3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/TreeListCtrl.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/separator.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/separator.png
new file mode 100644
index 0000000..752e21e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/separator.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/sizer.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/sizer.png
new file mode 100644
index 0000000..4fb2ca3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/sizer.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/spacer.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/spacer.png
new file mode 100644
index 0000000..8321a08
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/spacer.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/tool.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/tool.png
new file mode 100644
index 0000000..63115dd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/tool.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxBitmapButton.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxBitmapButton.png
new file mode 100644
index 0000000..54c0096
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxBitmapButton.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxBoxSizer.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxBoxSizer.png
new file mode 100644
index 0000000..97d77a8
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxBoxSizer.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxButton.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxButton.png
new file mode 100644
index 0000000..03505a0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxButton.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxCheckBox.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxCheckBox.png
new file mode 100644
index 0000000..3622fd5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxCheckBox.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxChoice.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxChoice.png
new file mode 100644
index 0000000..f101642
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxChoice.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxChoicebook.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxChoicebook.png
new file mode 100644
index 0000000..7475d50
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxChoicebook.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxComboBox.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxComboBox.png
new file mode 100644
index 0000000..e6f68e0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxComboBox.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxDialog.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxDialog.png
new file mode 100644
index 0000000..023ff21
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxDialog.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFilePickerCtrl.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFilePickerCtrl.png
new file mode 100644
index 0000000..b3faf0d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFilePickerCtrl.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFlexGridSizer.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFlexGridSizer.png
new file mode 100644
index 0000000..21f86e0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFlexGridSizer.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFrame.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFrame.png
new file mode 100644
index 0000000..6c564ac
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxFrame.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGauge.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGauge.png
new file mode 100644
index 0000000..e2500c0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGauge.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGrid.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGrid.png
new file mode 100644
index 0000000..b1b704c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGrid.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGridBagSizer.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGridBagSizer.png
new file mode 100644
index 0000000..1d0ba28
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGridBagSizer.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGridSizer.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGridSizer.png
new file mode 100644
index 0000000..9ab886d
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGridSizer.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGrid_bad.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGrid_bad.png
new file mode 100644
index 0000000..9f54583
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxGrid_bad.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxHyperlinkCtrl.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxHyperlinkCtrl.png
new file mode 100644
index 0000000..d0be9de
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxHyperlinkCtrl.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListBox.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListBox.png
new file mode 100644
index 0000000..c295709
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListBox.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListCtrl.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListCtrl.png
new file mode 100644
index 0000000..750e289
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListCtrl.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListbook.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListbook.png
new file mode 100644
index 0000000..209ba2c
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxListbook.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenu.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenu.png
new file mode 100644
index 0000000..2860ddf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenu.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenuBar.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenuBar.png
new file mode 100644
index 0000000..bd31766
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenuBar.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenuItem.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenuItem.png
new file mode 100644
index 0000000..f76b807
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxMenuItem.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxNotebook.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxNotebook.png
new file mode 100644
index 0000000..49aa4d5
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxNotebook.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxRadioButton.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxRadioButton.png
new file mode 100644
index 0000000..f494c00
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxRadioButton.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxScrollBar.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxScrollBar.png
new file mode 100644
index 0000000..abfff63
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxScrollBar.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxScrolledWindow.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxScrolledWindow.png
new file mode 100644
index 0000000..2125467
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxScrolledWindow.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSlider.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSlider.png
new file mode 100644
index 0000000..566be76
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSlider.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSpinButton.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSpinButton.png
new file mode 100644
index 0000000..3011506
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSpinButton.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSpinCtrl.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSpinCtrl.png
new file mode 100644
index 0000000..4ee9d5a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSpinCtrl.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSplitterWindow.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSplitterWindow.png
new file mode 100644
index 0000000..e518f04
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxSplitterWindow.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBitmap.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBitmap.png
new file mode 100644
index 0000000..99d09ff
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBitmap.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBox.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBox.png
new file mode 100644
index 0000000..3480c42
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBox.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBoxSizer.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBoxSizer.png
new file mode 100644
index 0000000..2e15f26
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticBoxSizer.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticLine.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticLine.png
new file mode 100644
index 0000000..8d0dbb2
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticLine.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticText.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticText.png
new file mode 100644
index 0000000..96a54f3
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStaticText.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStatusBar.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStatusBar.png
new file mode 100644
index 0000000..88c763b
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxStatusBar.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTextCtrl.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTextCtrl.png
new file mode 100644
index 0000000..d24eaba
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTextCtrl.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxToggleButton.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxToggleButton.png
new file mode 100644
index 0000000..44e9eaf
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxToggleButton.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxToolBar.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxToolBar.png
new file mode 100644
index 0000000..5ff49bd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxToolBar.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTreeCtrl.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTreeCtrl.png
new file mode 100644
index 0000000..161c9bd
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTreeCtrl.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTreebook.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTreebook.png
new file mode 100644
index 0000000..d3c1b41
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/bitmaps/wxTreebook.png
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/controls.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/controls.py
new file mode 100644
index 0000000..a36d1ab
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/controls.py
@@ -0,0 +1,577 @@
+# Name: controls.py
+# Purpose: Control components
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 31.05.2007
+# RCS-ID: $Id: core.py 47823 2007-07-29 19:24:35Z ROL $
+
+from wx.tools.XRCed import component, images, attribute, params
+from wx.tools.XRCed.globals import TRACE
+import _bitmaps as bitmaps
+
+TRACE('*** creating control components')
+
+# Set panel images
+component.Manager.panelImages['Controls'] = images.ToolPanel_Controls.GetImage()
+
+### wxStaticText
+
+c = component.Component('wxStaticText', ['control','tool'],
+ ['pos', 'size', 'label', 'wrap'], defaults={'label': 'LABEL'},
+ image=images.TreeStaticText.GetImage())
+c.addStyles('wxALIGN_LEFT', 'wxALIGN_RIGHT', 'wxALIGN_CENTRE', 'wxST_NO_AUTORESIZE')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'label', 'wxStaticText', 10)
+component.Manager.setTool(c, 'Controls', pos=(0,0))
+
+### wxStaticLine
+
+c = component.Component('wxStaticLine', ['control','tool'],
+ ['pos', 'size'], image=images.TreeStaticLine.GetImage())
+c.addStyles('wxLI_HORIZONTAL', 'wxLI_VERTICAL')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'line', 'wxStaticLine', 20)
+component.Manager.setTool(c, 'Controls', pos=(0,3))
+
+### wxStaticBitmap
+
+c = component.Component('wxStaticBitmap', ['control','tool'],
+ ['pos', 'size', 'bitmap'],
+ image=images.TreeStaticBitmap.GetImage())
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'bitmap', 'wxStaticBitmap', 30)
+component.Manager.setTool(c, 'Controls', pos=(1,0))
+
+### wxTextCtrl
+
+c = component.Component('wxTextCtrl', ['control','tool'],
+ ['pos', 'size', 'value', 'maxlength'],
+ image=images.TreeTextCtrl.GetImage())
+c.addStyles('wxTE_NO_VSCROLL',
+ 'wxTE_AUTO_SCROLL',
+ 'wxTE_PROCESS_ENTER',
+ 'wxTE_PROCESS_TAB',
+ 'wxTE_MULTILINE',
+ 'wxTE_PASSWORD',
+ 'wxTE_READONLY',
+ 'wxHSCROLL',
+ 'wxTE_RICH',
+ 'wxTE_RICH2',
+ 'wxTE_AUTO_URL',
+ 'wxTE_NOHIDESEL',
+ 'wxTE_LEFT',
+ 'wxTE_CENTRE',
+ 'wxTE_RIGHT',
+ 'wxTE_DONTWRAP',
+ 'wxTE_LINEWRAP',
+ 'wxTE_CHARWRAP',
+ 'wxTE_WORDWRAP')
+c.setParamClass('value', params.ParamMultilineText)
+c.addEvents('EVT_TEXT', 'EVT_TEXT_ENTER', 'EVT_TEXT_URL', 'EVT_TEXT_MAXLEN')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'text ctrl', 'wxTextCtrl', 40)
+component.Manager.setTool(c, 'Controls', pos=(0,2))
+
+#### wxRichTextCtrl
+#
+#c = component.Component('wxRichTextCtrl', ['control','tool'],
+# ['pos', 'size', 'value', 'maxlength'],
+# image=images.TreeTextCtrl.GetImage())
+#c.addStyles('wxTE_PROCESS_ENTER',
+# 'wxTE_PROCESS_TAB',
+# 'wxTE_MULTILINE',
+# 'wxTE_READONLY',
+# 'wxTE_AUTO_URL')
+#c.setParamClass('value', params.ParamMultilineText)
+#c.addEvents('EVT_TEXT', 'EVT_TEXT_ENTER', 'EVT_TEXT_URL', 'EVT_TEXT_MAXLEN')
+#component.Manager.register(c)
+#component.Manager.setMenu(c, 'control', 'rich text ctrl', 'wxTRichextCtrl', 41)
+#
+### wxChoice
+
+c = component.Component('wxChoice', ['control','tool'],
+ ['pos', 'size', 'content', 'selection'],
+ image=images.TreeChoice.GetImage())
+c.addStyles('wxCB_SORT')
+c.setSpecial('content', attribute.ContentAttribute)
+c.addEvents('EVT_CHOICE')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'choice', 'wxChoice', 50)
+component.Manager.setTool(c, 'Controls', pos=(3,2))
+
+### wxSlider
+
+c = component.Component('wxSlider', ['control','tool'],
+ ['pos', 'size', 'value', 'min', 'max',
+ 'tickfreq', 'pagesize', 'linesize', 'thumb', 'tick',
+ 'selmin', 'selmax'],
+ image=images.TreeSlider.GetImage())
+c.addStyles('wxSL_HORIZONTAL', 'wxSL_VERTICAL', 'wxSL_AUTOTICKS', 'wxSL_LABELS',
+ 'wxSL_LEFT', 'wxSL_RIGHT', 'wxSL_TOP', 'wxSL_BOTTOM',
+ 'wxSL_BOTH', 'wxSL_SELRANGE', 'wxSL_INVERSE')
+component.Manager.register(c)
+c.setParamClass('value', params.ParamInt)
+c.setParamClass('tickfreq', params.ParamIntNN)
+c.setParamClass('pagesize', params.ParamIntNN)
+c.setParamClass('linesize', params.ParamIntNN)
+c.setParamClass('thumb', params.ParamUnit)
+c.setParamClass('tick', params.ParamInt)
+c.setParamClass('selmin', params.ParamInt)
+c.setParamClass('selmax', params.ParamInt)
+c.addEvents('EVT_SCROLL', 'EVT_SCROLL_TOP', 'EVT_SCROLL_BOTTOM',
+ 'EVT_SCROLL_LINEUP', 'EVT_SCROLL_LINEDOWN', 'EVT_SCROLL_PAGEUP',
+ 'EVT_SCROLL_PAGEDOWN', 'EVT_SCROLL_THUMBTRACK', 'EVT_SCROLL_THUMBRELEASE',
+ 'EVT_SCROLL_CHANGED', 'EVT_SCROLL', 'EVT_SCROLL_TOP',
+ 'EVT_SCROLL_BOTTOM', 'EVT_SCROLL_LINEUP',
+ 'EVT_SCROLL_LINEDOWN', 'EVT_SCROLL_PAGEUP',
+ 'EVT_SCROLL_PAGEDOWN', 'EVT_SCROLL_THUMBTRACK',
+ 'EVT_SCROLL_THUMBRELEASE', 'EVT_SCROLL_CHANGED')
+component.Manager.setMenu(c, 'control', 'slider', 'wxSlider', 60)
+component.Manager.setTool(c, 'Controls', pos=(2,3))
+
+### wxGauge
+
+c = component.Component('wxGauge', ['control','tool'],
+ ['pos', 'size', 'range', 'value', 'shadow', 'bezel'],
+ image=images.TreeGauge.GetImage())
+c.addStyles('wxGA_HORIZONTAL', 'wxGA_VERTICAL', 'wxGA_SMOOTH')
+c.setParamClass('range', params.ParamIntNN)
+c.setParamClass('value', params.ParamIntNN)
+c.setParamClass('shadow', params.ParamUnit)
+c.setParamClass('bezel', params.ParamUnit)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'gauge', 'wxGauge', 70)
+component.Manager.setTool(c, 'Controls', pos=(1,3))
+
+### wxSpinCtrl
+
+c = component.Component('wxSpinCtrl', ['control','tool'],
+ ['pos', 'size', 'value', 'min', 'max'],
+ image=images.TreeSpinCtrl.GetImage())
+c.addStyles('wxSP_HORIZONTAL', 'wxSP_VERTICAL', 'wxSP_ARROW_KEYS', 'wxSP_WRAP')
+c.setParamClass('value', params.ParamInt)
+c.addEvents('EVT_SPINCTRL')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'spin ctrl', 'wxSpinCtrl', 80)
+component.Manager.setTool(c, 'Controls', pos=(1,2))
+
+### wxScrollBar
+
+c = component.Component('wxScrollBar', ['control'],
+ ['pos', 'size', 'value', 'thumbsize', 'range', 'pagesize'],
+ image=images.TreeScrollBar.GetImage())
+c.addStyles('wxSB_HORIZONTAL', 'wxSB_VERTICAL')
+c.setParamClass('range', params.ParamIntNN)
+c.setParamClass('value', params.ParamIntNN)
+c.setParamClass('thumbsize', params.ParamUnit)
+c.setParamClass('pagesize', params.ParamUnit)
+c.addEvents('EVT_SCROLL', 'EVT_SCROLL_TOP', 'EVT_SCROLL_BOTTOM',
+ 'EVT_SCROLL_LINEUP', 'EVT_SCROLL_LINEDOWN', 'EVT_SCROLL_PAGEUP',
+ 'EVT_SCROLL_PAGEDOWN', 'EVT_SCROLL_THUMBTRACK', 'EVT_SCROLL_THUMBRELEASE',
+ 'EVT_SCROLL_CHANGED', 'EVT_SCROLL', 'EVT_SCROLL_TOP',
+ 'EVT_SCROLL_BOTTOM', 'EVT_SCROLL_LINEUP',
+ 'EVT_SCROLL_LINEDOWN', 'EVT_SCROLL_PAGEUP',
+ 'EVT_SCROLL_PAGEDOWN', 'EVT_SCROLL_THUMBTRACK',
+ 'EVT_SCROLL_THUMBRELEASE', 'EVT_SCROLL_CHANGED')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'scroll bar', 'wxScrollBar', 90)
+component.Manager.setTool(c, 'Controls', pos=(3,3))
+
+### wxListCtrl
+
+c = component.Component('wxListCtrl', ['control','tool'], ['pos', 'size'],
+ image=images.TreeListCtrl.GetImage())
+c.addStyles('wxLC_LIST', 'wxLC_REPORT', 'wxLC_ICON', 'wxLC_SMALL_ICON',
+ 'wxLC_ALIGN_TOP', 'wxLC_ALIGN_LEFT', 'wxLC_AUTOARRANGE',
+ 'wxLC_USER_TEXT', 'wxLC_EDIT_LABELS', 'wxLC_NO_HEADER',
+ 'wxLC_SINGLE_SEL', 'wxLC_SORT_ASCENDING', 'wxLC_SORT_DESCENDING',
+ 'wxLC_VIRTUAL', 'wxLC_HRULES', 'wxLC_VRULES', 'wxLC_NO_SORT_HEADER')
+c.addEvents('EVT_LIST_BEGIN_DRAG',
+ 'EVT_LIST_BEGIN_RDRAG',
+ 'EVT_LIST_BEGIN_LABEL_EDIT',
+ 'EVT_LIST_END_LABEL_EDIT',
+ 'EVT_LIST_DELETE_ITEM',
+ 'EVT_LIST_DELETE_ALL_ITEMS',
+ 'EVT_LIST_ITEM_SELECTED',
+ 'EVT_LIST_ITEM_DESELECTED',
+ 'EVT_LIST_KEY_DOWN',
+ 'EVT_LIST_INSERT_ITEM',
+ 'EVT_LIST_COL_CLICK',
+ 'EVT_LIST_ITEM_RIGHT_CLICK',
+ 'EVT_LIST_ITEM_MIDDLE_CLICK',
+ 'EVT_LIST_ITEM_ACTIVATED',
+ 'EVT_LIST_CACHE_HINT',
+ 'EVT_LIST_COL_RIGHT_CLICK',
+ 'EVT_LIST_COL_BEGIN_DRAG',
+ 'EVT_LIST_COL_DRAGGING',
+ 'EVT_LIST_COL_END_DRAG',
+ 'EVT_LIST_ITEM_FOCUSED')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'list ctrl', 'wxListCtrl', 100)
+component.Manager.setTool(c, 'Panels', pos=(0,1))
+
+### wxTreeCtrl
+
+c = component.Component('wxTreeCtrl', ['control','tool'], ['pos', 'size'],
+ image=images.TreeTreeCtrl.GetImage())
+c.addStyles('wxTR_EDIT_LABELS',
+ 'wxTR_NO_BUTTONS',
+ 'wxTR_HAS_BUTTONS',
+ 'wxTR_TWIST_BUTTONS',
+ 'wxTR_NO_LINES',
+ 'wxTR_FULL_ROW_HIGHLIGHT',
+ 'wxTR_LINES_AT_ROOT',
+ 'wxTR_HIDE_ROOT',
+ 'wxTR_ROW_LINES',
+ 'wxTR_HAS_VARIABLE_ROW_HEIGHT',
+ 'wxTR_SINGLE',
+ 'wxTR_MULTIPLE',
+ 'wxTR_EXTENDED',
+ 'wxTR_DEFAULT_STYLE')
+c.addEvents('EVT_TREE_BEGIN_DRAG',
+ 'EVT_TREE_BEGIN_RDRAG',
+ 'EVT_TREE_BEGIN_LABEL_EDIT',
+ 'EVT_TREE_END_LABEL_EDIT',
+ 'EVT_TREE_DELETE_ITEM',
+ 'EVT_TREE_GET_INFO',
+ 'EVT_TREE_SET_INFO',
+ 'EVT_TREE_ITEM_EXPANDED',
+ 'EVT_TREE_ITEM_EXPANDING',
+ 'EVT_TREE_ITEM_COLLAPSED',
+ 'EVT_TREE_ITEM_COLLAPSING',
+ 'EVT_TREE_SEL_CHANGED',
+ 'EVT_TREE_SEL_CHANGING',
+ 'EVT_TREE_KEY_DOWN',
+ 'EVT_TREE_ITEM_ACTIVATED',
+ 'EVT_TREE_ITEM_RIGHT_CLICK',
+ 'EVT_TREE_ITEM_MIDDLE_CLICK',
+ 'EVT_TREE_END_DRAG',
+ 'EVT_TREE_STATE_IMAGE_CLICK',
+ 'EVT_TREE_ITEM_GETTOOLTIP',
+ 'EVT_TREE_ITEM_MENU')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'tree ctrl', 'wxTreeCtrl', 110)
+component.Manager.setTool(c, 'Panels', pos=(0,2))
+
+### wxHtmlWindow
+
+c = component.Component('wxHtmlWindow', ['control'],
+ ['pos', 'size', 'borders', 'url', 'htmlcode'])
+c.addStyles('wxHW_SCROLLBAR_NEVER', 'wxHW_SCROLLBAR_AUTO', 'wxHW_NO_SELECTION')
+c.setParamClass('url', params.ParamLongText)
+c.setParamClass('htmlcode', params.ParamMultilineText)
+c.addEvents('EVT_HTML_CELL_CLICKED', 'EVT_HTML_CELL_HOVER',
+ 'EVT_HTML_LINK_CLICKED')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'HTML window', 'wxHtmlWindow', 120)
+
+### wxCalendarCtrl
+
+c = component.Component('wxCalendarCtrl', ['control', 'tool'], ['pos', 'size'])
+c.addStyles('wxCAL_SUNDAY_FIRST', 'wxCAL_MONDAY_FIRST', 'wxCAL_SHOW_HOLIDAYS',
+ 'wxCAL_NO_YEAR_CHANGE', 'wxCAL_NO_MONTH_CHANGE',
+ 'wxCAL_SEQUENTIAL_MONTH_SELECTION', 'wxCAL_SHOW_SURROUNDING_WEEKS')
+c.addEvents('EVT_CALENDAR_SEL_CHANGED', 'EVT_CALENDAR_DAY_CHANGED',
+ 'EVT_CALENDAR_MONTH_CHANGED', 'EVT_CALENDAR_YEAR_CHANGED',
+ 'EVT_CALENDAR_DOUBLECLICKED', 'EVT_CALENDAR_WEEKDAY_CLICKED')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'calendar ctrl', 'wxCalendarCtrl', 130)
+
+### wxGenericDirCtrl
+
+c = component.Component('wxGenericDirCtrl', ['control'],
+ ['pos', 'size', 'defaultfolder', 'filter', 'defaultfilter'])
+c.addStyles('wxDIRCTRL_DIR_ONLY', 'wxDIRCTRL_3D_INTERNAL', 'wxDIRCTRL_SELECT_FIRST',
+ 'wxDIRCTRL_SHOW_FILTERS', 'wxDIRCTRL_EDIT_LABELS')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'generic dir ctrl', 'wxGenericDirCtrl', 160)
+
+### wxFilePickerCtrl
+
+c = component.Component('wxFilePickerCtrl', ['control'],
+ ['pos', 'size', 'value', 'message', 'wildcard'])
+c.addStyles('wxFLP_OPEN', 'wxFLP_SAVE', 'wxFLP_OVERWRITE_PROMPT',
+ 'wxFLP_FILE_MUST_EXIST', 'wxFLP_CHANGE_DIR',
+ 'wxFLP_DEFAULT_STYLE', 'wxFLP_USE_TEXTCTRL')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'file picker ctrl', 'wxFilePickerCtrl', 170)
+component.Manager.setTool(c, 'Controls', pos=(4,2))
+
+### wxDirPickerCtrl
+
+c = component.Component('wxDirPickerCtrl', ['control'],
+ ['pos', 'size', 'value', 'message', 'wildcard'])
+c.addStyles('wxDIRP_USE_TEXTCTRL',
+ 'wxDIRP_DIR_MUST_EXIST', 'wxDIRP_CHANGE_DIR',
+ 'wxDIRP_DEFAULT_STYLE')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'dir picker ctrl', 'wxDirPickerCtrl', 171)
+
+### wxDatePickerCtrl
+
+c = component.Component('wxDatePickerCtrl', ['control'], ['pos', 'size'])
+c.addStyles('wxDP_DEFAULT', 'wxDP_SPIN', 'wxDP_DROPDOWN',
+ 'wxDP_ALLOWNONE', 'wxDP_SHOWCENTURY')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'date picker ctrl', 'wxDateCtrl', 180)
+
+### wxFontPickerCtrl
+
+c = component.Component('wxFontPickerCtrl', ['control'], ['pos', 'size', 'value'])
+c.addStyles('wxFNTP_USE_TEXTCTRL', 'wxFNTP_FONTDESC_AS_LABEL',
+ 'wxFNTP_USEFONT_FOR_LABEL', 'wxFNTP_DEFAULT_STYLE')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'font picker ctrl', 'wxFontPickerCtrl', 181)
+
+### wxColourPickerCtrl
+
+c = component.Component('wxColourPickerCtrl', ['control'], ['pos', 'size', 'value'])
+c.addStyles('wxCLRP_USE_TEXTCTRL', 'wxCLRP_SHOW_LABEL', 'wxCLRP_DEFAULT_STYLE')
+c.addEvents('EVT_COMMAND_COLOURPICKER_CHANGED')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'colour picker ctrl', 'wxColourPickerCtrl', 181)
+
+### wxAnimationCtrl
+
+c = component.Component('wxAnimationCtrl', ['control','tool'],
+ ['pos', 'size', 'animation', 'inactive-bitmap'])
+c.addStyles('wxAC_NO_AUTORESIZE', 'wxAC_DEFAULT_STYLE')
+c.setSpecial('inactive-bitmap', attribute.BitmapAttribute)
+c.setParamClass('inactive-bitmap', params.ParamBitmap)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'animation ctrl', 'wxAnimationCtrl', 182)
+
+### wxGrid
+
+c = component.Component('wxGrid', ['control'], ['pos', 'size'])
+c.addEvents('EVT_GRID_CELL_LEFT_CLICK',
+ 'EVT_GRID_CELL_RIGHT_CLICK',
+ 'EVT_GRID_CELL_LEFT_DCLICK',
+ 'EVT_GRID_CELL_RIGHT_DCLICK',
+ 'EVT_GRID_LABEL_LEFT_CLICK',
+ 'EVT_GRID_LABEL_RIGHT_CLICK',
+ 'EVT_GRID_LABEL_LEFT_DCLICK',
+ 'EVT_GRID_LABEL_RIGHT_DCLICK',
+ 'EVT_GRID_ROW_SIZE',
+ 'EVT_GRID_COL_SIZE',
+ 'EVT_GRID_RANGE_SELECT',
+ 'EVT_GRID_CELL_CHANGE',
+ 'EVT_GRID_SELECT_CELL',
+ 'EVT_GRID_EDITOR_SHOWN',
+ 'EVT_GRID_EDITOR_HIDDEN',
+ 'EVT_GRID_EDITOR_CREATED',
+ 'EVT_GRID_CELL_BEGIN_DRAG')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'grid', 'wxGrid', 190)
+component.Manager.setTool(c, 'Panels', pos=(2,1), span=(1,2))
+
+### wxHyperlinkCtrl
+
+c = component.Component('wxHyperlinkCtrl', ['control','tool'],
+ ['pos', 'size', 'label', 'url'],
+ params={'url': params.ParamText},
+ defaults={'url': 'http://'})
+c.addStyles('wxHL_CONTEXTMENU', 'wxHL_ALIGN_LEFT', 'wxHL_ALIGN_RIGHT',
+ 'wxHL_ALIGN_CENTRE', 'wxHL_DEFAULT_STYLE')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'hyperlink', 'wxHyperlinkCtrl', 200)
+component.Manager.setTool(c, 'Controls', pos=(3,0))
+
+################################################################################
+# Buttons
+
+### wxButton
+
+c = component.Component('wxButton', ['control', 'tool', 'stdbtn'],
+ ['pos', 'size', 'label', 'default'],
+ image=images.TreeButton.GetImage())
+c.addStyles('wxBU_LEFT', 'wxBU_TOP', 'wxBU_RIGHT', 'wxBU_BOTTOM', 'wxBU_EXACTFIT')
+c.setParamClass('default', params.ParamBool)
+c.addEvents('EVT_BUTTON')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'button', 'button', 'wxButton', 10)
+component.Manager.setTool(c, 'Controls', pos=(0,1))
+
+### wxBitmapButton
+
+c = component.Component('wxBitmapButton', ['control', 'tool'],
+ ['pos', 'size', 'default',
+ 'bitmap', 'selected', 'focus', 'disabled', 'hover'],
+ image=images.TreeBitmapButton.GetImage())
+c.addStyles('wxBU_AUTODRAW', 'wxBU_LEFT', 'wxBU_RIGHT', 'wxBU_TOP', 'wxBU_BOTTOM',
+ 'wxBU_EXACTFIT')
+c.setParamClass('default', params.ParamBool)
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+c.setSpecial('selected', attribute.BitmapAttribute)
+c.setParamClass('selected', params.ParamBitmap)
+c.setSpecial('focus', attribute.BitmapAttribute)
+c.setParamClass('focus', params.ParamBitmap)
+c.setSpecial('disabled', attribute.BitmapAttribute)
+c.setParamClass('disabled', params.ParamBitmap)
+c.setSpecial('hover', attribute.BitmapAttribute)
+c.setParamClass('hover', params.ParamBitmap)
+c.addEvents('EVT_BUTTON')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'button', 'bitmap button', 'wxBitmapButton', 20)
+component.Manager.setTool(c, 'Controls', pos=(1,1))
+
+### wxRadioButton
+
+c = component.Component('wxRadioButton', ['control', 'tool'],
+ ['pos', 'size', 'label', 'value'],
+ image=images.TreeRadioButton.GetImage())
+c.addStyles('wxRB_GROUP', 'wxRB_SINGLE')
+c.setParamClass('value', params.ParamBool)
+c.addEvents('EVT_RADIOBUTTON')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'button', 'radio button', 'wxRadioButton', 30)
+component.Manager.setTool(c, 'Controls', pos=(3,1))
+
+### wxSpinButton
+
+c = component.Component('wxSpinButton', ['control', 'tool'],
+ ['pos', 'size', 'value', 'min', 'max'],
+ image=images.TreeSpinButton.GetImage())
+c.addStyles('wxSP_HORIZONTAL', 'wxSP_VERTICAL', 'wxSP_ARROW_KEYS', 'wxSP_WRAP')
+c.addEvents('EVT_SPIN', 'EVT_SPIN_UP', 'EVT_SPIN_DOWN')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'button', 'spin button', 'wxSpinButton', 40)
+component.Manager.setTool(c, 'Controls', pos=(2,0))
+
+### wxToggleButton
+
+c = component.Component('wxToggleButton', ['control', 'tool'],
+ ['pos', 'size', 'label', 'checked'],
+ image=images.TreeToggleButton.GetImage())
+c.addEvents('EVT_TOGGLEBUTTON')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'button', 'toggle button', 'wxToggleButton', 50)
+component.Manager.setTool(c, 'Controls', pos=(2,1))
+
+################################################################################
+# Boxes
+
+### wxCheckBox
+
+c = component.Component('wxCheckBox', ['control','tool'],
+ ['pos', 'size', 'label', 'checked'],
+ image=images.TreeCheckBox.GetImage())
+c.addStyles('wxCHK_2STATE', 'wxCHK_3STATE', 'wxCHK_ALLOW_3RD_STATE_FOR_USER',
+ 'wxALIGN_RIGHT')
+c.addEvents('EVT_CHECKBOX')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'box', 'check box', 'wxCheckBox', 10)
+component.Manager.setTool(c, 'Controls', pos=(4,1))
+
+### wxComboBox
+
+c = component.Component('wxComboBox', ['control','tool'],
+ ['pos', 'size', 'content', 'selection', 'value'],
+ image=images.TreeComboBox.GetImage())
+c.addStyles('wxCB_SIMPLE', 'wxCB_DROPDOWN', 'wxCB_READONLY',
+ 'wxCB_SORT', 'wxTE_PROCESS_ENTER')
+c.setSpecial('content', attribute.ContentAttribute)
+c.addEvents('EVT_COMBOBOX', 'EVT_TEXT', 'EVT_TEXT_ENTER')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'box', 'combo box', 'wxComboBox', 20)
+component.Manager.setTool(c, 'Controls', pos=(2,2))
+
+### wxOwnerDrawnComboBox
+
+c = component.Component('wxOwnerDrawnComboBox', ['control','tool'],
+ ['pos', 'size', 'content', 'selection', 'value'],
+ image=images.TreeComboBox.GetImage())
+c.addStyles('wxCB_SIMPLE', 'wxCB_DROPDOWN', 'wxCB_READONLY', 'wxCB_SORT',
+ 'wxODCB_STD_CONTROL_PAINT', 'wxODCB_DCLICK_CYCLES', 'wxTE_PROCESS_ENTER')
+c.setSpecial('content', attribute.ContentAttribute)
+c.addEvents('EVT_COMBOBOX', 'EVT_TEXT', 'EVT_TEXT_ENTER')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'box', 'owner-drawn combo box', 'wxOwnerDrawnComboBox', 21)
+
+#### wxBitmapComboBox
+## FIXME: needs special content support (bitmap, text)
+#
+#c = component.Component('wxBitmapComboBox', ['control','tool'],
+# ['pos', 'size', 'ownerdrawnitem', 'selection', 'value'],
+# image=images.TreeComboBox.GetImage())
+#c.addStyles('wxCB_READONLY', 'wxCB_SORT')
+#c.setSpecial('ownerdrawnitem', attribute.ContentAttribute)
+#c.addEvents('EVT_COMBOBOX', 'EVT_TEXT', 'EVT_TEXT_ENTER')
+#component.Manager.register(c)
+#component.Manager.setMenu(c, 'box', 'virtual combo box', 'wxBitmapComboBox', 20)
+#
+### wxRadioBox
+
+c = component.Component('wxRadioBox', ['control','tool'],
+ ['pos', 'size', 'label', 'dimension',
+ 'content', 'selection', 'dimension'])
+c.addStyles('wxRA_SPECIFY_ROWS', 'wxRA_SPECIFY_COLS', 'wxRA_HORIZONTAL',
+ 'wxRA_VERTICAL')
+c.setSpecial('content', attribute.HelpContentAttribute)
+c.setParamClass('content', params.ParamContentHelpList)
+c.setParamClass('dimension', params.ParamInt)
+c.addEvents('EVT_RADIOBOX')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'box', 'radio box', 'wxRadioBox', 30)
+#component.Manager.setTool(c, 'Panels')
+
+### wxListBox
+
+c = component.Component('wxListBox', ['control','tool'],
+ ['pos', 'size', 'content', 'selection'],
+ image=images.TreeListBox.GetImage())
+c.addStyles('wxLB_SINGLE', 'wxLB_MULTIPLE', 'wxLB_EXTENDED', 'wxLB_HSCROLL',
+ 'wxLB_ALWAYS_SB', 'wxLB_NEEDED_SB', 'wxLB_SORT')
+c.setSpecial('content', attribute.ContentAttribute)
+c.addEvents('EVT_LISTBOX', 'EVT_LISTBOX_DCLICK')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'box', 'list box', 'wxListBox', 40)
+component.Manager.setTool(c, 'Panels', pos=(0,0))
+
+### wxSimpleHtmlListBox
+
+c = component.Component('wxSimpleHtmlListBox', ['control','tool'],
+ ['pos', 'size', 'content', 'selection'],
+ image=images.TreeListBox.GetImage())
+c.addStyles('wxHLB_MULTIPLE', 'wxHLB_DEFAULT_STYLE')
+c.setSpecial('content', attribute.ContentAttribute)
+c.addEvents('EVT_LISTBOX', 'EVT_LISTBOX_DCLICK')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'box', 'html list box', 'wxSimpleHtmlListBox', 41)
+
+### wxCheckListBox
+
+c = component.Component('wxCheckListBox', ['control','tool'],
+ ['pos', 'size', 'content', 'selection'],
+ image=images.TreeCheckListBox.GetImage())
+c.addStyles('wxLB_SINGLE', 'wxLB_MULTIPLE', 'wxLB_EXTENDED', 'wxLB_HSCROLL',
+ 'wxLB_ALWAYS_SB', 'wxLB_NEEDED_SB', 'wxLB_SORT')
+c.setSpecial('content', attribute.CheckContentAttribute)
+c.setParamClass('content', params.ParamContentCheckList)
+c.addEvents('EVT_CHECKLISTBOX')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'box', 'check list box', 'wxCheckListBox', 50)
+#component.Manager.setTool(c, 'Panels', pos=(0,0))
+
+### wxStaticBox
+
+c = component.Component('wxStaticBox', ['control','tool'],
+ ['pos', 'size', 'label'],
+ image=images.TreeStaticBox.GetImage())
+component.Manager.register(c)
+component.Manager.setMenu(c, 'box', 'static box', 'wxStaticBox', 60)
+component.Manager.setTool(c, 'Panels', pos=(2,0))
+
+### unknown
+
+c = component.Component('unknown', ['control'], ['pos', 'size'])
+component.Manager.register(c)
+component.Manager.setMenu(c, 'control', 'unknown', 'unknown control')
+
+### wxXXX
+
+#c = component.Component('wxXXX', ['control','tool'],
+# ['pos', 'size', ...])
+#c.addStyles(...)
+#component.Manager.register(c)
+#component.Manager.setMenu(c, 'control', 'XXX', 'wxXXX', NN)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/core.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/core.py
new file mode 100644
index 0000000..211a691
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/core.py
@@ -0,0 +1,607 @@
+# Name: core.py
+# Purpose: Core components
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 31.05.2007
+# RCS-ID: $Id: core.py 71860 2012-06-25 15:46:16Z ROL $
+
+import wx
+from wx.tools.XRCed import component, images, attribute, params, view
+from wx.tools.XRCed.globals import TRACE,is_object,is_element,STD_NAME
+import _bitmaps as bitmaps
+
+TRACE('*** creating core components')
+
+# Set panel images
+component.Manager.panelImages['Windows'] = images.ToolPanel_Windows.GetImage()
+component.Manager.panelImages['Menus'] = images.ToolPanel_Menus.GetImage()
+component.Manager.panelImages['Sizers'] = images.ToolPanel_Sizers.GetImage()
+component.Manager.panelImages['Panels'] = images.ToolPanel_Panels.GetImage()
+component.Manager.panelImages['Gizmos'] = images.ToolPanel_Gizmos.GetImage()
+
+### wxFrame
+
+class Frame(component.Container):
+ def getChildObject(self, node, obj, index):
+ # Do not count toolbar and menubar
+ objects = filter(is_element, node.childNodes)
+ indexOffset = 0 # count non-window children
+ for i,o in enumerate(objects):
+ if o.getAttribute('class') == 'wxMenuBar':
+ if i == index: return obj.GetMenuBar()
+ elif i < index: indexOffset += 1
+ elif o.getAttribute('class') == 'wxToolBar':
+ if i == index: return obj.GetToolBar()
+ elif i < index: indexOffset += 1
+ return component.Container.getChildObject(self, node, obj, index - indexOffset)
+
+c = Frame('wxFrame', ['frame','window','top_level'],
+ ['pos', 'size', 'title', 'centered'],
+ image=images.TreeFrame.GetImage())
+c.isTopLevel = True
+c.addStyles('wxDEFAULT_FRAME_STYLE', 'wxDEFAULT_DIALOG_STYLE', 'wxCAPTION',
+ 'wxSTAY_ON_TOP', 'wxSYSTEM_MENU',
+ 'wxRESIZE_BORDER', 'wxCLOSE_BOX',
+ 'wxMAXIMIZE_BOX', 'wxMINIMIZE_BOX',
+ 'wxFRAME_NO_TASKBAR', 'wxFRAME_SHAPED', 'wxFRAME_TOOL_WINDOW',
+ 'wxFRAME_FLOAT_ON_PARENT',
+ 'wxTAB_TRAVERSAL')
+c.addExStyles('wxFRAME_EX_CONTEXTHELP', 'wxFRAME_EX_METAL')
+c.addEvents('EVT_SIZE', 'EVT_CLOSE', 'EVT_MENU_HIGHLIGHT', 'EVT_ICONIZE', 'EVT_MAXIMIZE',
+ 'EVT_ACTIVATE', 'EVT_UPDATE_UI')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'frame', 'wxFrame', 10)
+component.Manager.setTool(c, 'Windows', bitmaps.wxFrame.GetBitmap(), (0,0))
+
+### wxMDIParentFrame
+
+class MDIParentFrame(component.Container):
+ def getChildObject(self, node, obj, index):
+ # Do not count toolbar and menubar
+ objects = filter(is_element, node.childNodes)
+ indexOffset = 0 # count non-window children
+ for i,o in enumerate(objects):
+ if o.getAttribute('class') == 'wxMenuBar':
+ if i == index: return obj.GetMenuBar()
+ elif i < index: indexOffset += 1
+ elif o.getAttribute('class') == 'wxToolBar':
+ if i == index: return obj.GetToolBar()
+ elif i < index: indexOffset += 1
+ return obj.GetClientWindow().GetChildren()[index]
+
+c = MDIParentFrame('wxMDIParentFrame', ['mdi_parent_frame','top_level'],
+ ['pos', 'size', 'title', 'centered'],
+ image=images.TreeFrame.GetImage())
+c.isTopLevel = True
+c.addStyles('wxDEFAULT_FRAME_STYLE', 'wxDEFAULT_DIALOG_STYLE', 'wxCAPTION',
+ 'wxSTAY_ON_TOP', 'wxSYSTEM_MENU',
+ 'wxRESIZE_BORDER', 'wxCLOSE_BOX',
+ 'wxMAXIMIZE_BOX', 'wxMINIMIZE_BOX',
+ 'wxFRAME_NO_TASKBAR', 'wxFRAME_SHAPED', 'wxFRAME_TOOL_WINDOW',
+ 'wxFRAME_FLOAT_ON_PARENT', 'wxFRAME_NO_WINDOW_MENU',
+ 'wxTAB_TRAVERSAL')
+c.addExStyles('wxFRAME_EX_METAL')
+c.addEvents('EVT_SIZE', 'EVT_CLOSE', 'EVT_MENU_HIGHLIGHT', 'EVT_ICONIZE', 'EVT_MAXIMIZE',
+ 'EVT_ACTIVATE', 'EVT_UPDATE_UI')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'MDI parent frame', 'wxMDIParentFrame', 11)
+#component.Manager.setTool(c, 'Windows', bitmaps.wxFrame.GetBitmap(), (0,0))
+
+### wxMDIChildFrame
+
+class MDIChildFrame(component.Container):
+ def getChildObject(self, node, obj, index):
+ # Do not count toolbar and menubar
+ objects = filter(is_element, node.childNodes)
+ indexOffset = 0 # count non-window children
+ for i,o in enumerate(objects):
+ if o.getAttribute('class') == 'wxMenuBar':
+ if i == index: return obj.GetMenuBar()
+ elif i < index: indexOffset += 1
+ elif o.getAttribute('class') == 'wxToolBar':
+ if i == index: return obj.GetToolBar()
+ elif i < index: indexOffset += 1
+ return component.Container.getChildObject(self, node, obj, index - indexOffset)
+
+c = MDIChildFrame('wxMDIChildFrame', ['mdi_child_frame','window'],
+ ['pos', 'size', 'title', 'centered'],
+ image=images.TreeFrame.GetImage())
+c.addStyles('wxDEFAULT_FRAME_STYLE', 'wxDEFAULT_DIALOG_STYLE', 'wxCAPTION',
+ 'wxSTAY_ON_TOP', 'wxSYSTEM_MENU',
+ 'wxRESIZE_BORDER', 'wxCLOSE_BOX',
+ 'wxMAXIMIZE_BOX', 'wxMINIMIZE_BOX',
+ 'wxFRAME_NO_TASKBAR', 'wxFRAME_SHAPED', 'wxFRAME_TOOL_WINDOW',
+ 'wxFRAME_FLOAT_ON_PARENT', 'wxFRAME_NO_WINDOW_MENU',
+ 'wxTAB_TRAVERSAL')
+c.addExStyles('wxFRAME_EX_METAL')
+c.addEvents('EVT_SIZE', 'EVT_CLOSE', 'EVT_MENU_HIGHLIGHT', 'EVT_ICONIZE', 'EVT_MAXIMIZE',
+ 'EVT_ACTIVATE', 'EVT_UPDATE_UI')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'container', 'MDI child frame', 'wxMDIChildFrame', 12)
+#component.Manager.setTool(c, 'Windows', bitmaps.wxFrame.GetBitmap(), (0,0))
+
+### wxDialog
+
+c = component.Container('wxDialog', ['frame','window','top_level'],
+ ['pos', 'size', 'title', 'centered', 'icon'],
+ image=images.TreeDialog.GetImage())
+c.isTopLevel = True
+c.setSpecial('icon', attribute.BitmapAttribute)
+c.addStyles('wxDEFAULT_DIALOG_STYLE', 'wxCAPTION',
+ 'wxSTAY_ON_TOP', 'wxSYSTEM_MENU',
+ 'wxRESIZE_BORDER', 'wxCLOSE_BOX',
+ 'wxMAXIMIZE_BOX', 'wxMINIMIZE_BOX',
+ 'wxDIALOG_NO_PARENT', 'wxFRAME_SHAPED',
+ 'wxTAB_TRAVERSAL')
+c.addExStyles('wxDIALOG_EX_CONTEXTHELP', 'wxDIALOG_EX_METAL')
+c.addEvents('EVT_INIT_DIALOG', 'EVT_SIZE', 'EVT_CLOSE',
+ 'EVT_ICONIZE', 'EVT_MAXIMIZE', 'EVT_ACTIVATE', 'EVT_UPDATE_UI')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'dialog', 'wxDialog', 20)
+component.Manager.setTool(c, 'Windows', bitmaps.wxDialog.GetBitmap(), (0,1))
+
+### wxPanel
+
+c = component.Container('wxPanel', ['window', 'top_level', 'control'],
+ ['pos', 'size'],
+ image=images.TreePanel.GetImage())
+c.addStyles('wxTAB_TRAVERSAL')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'panel', 'wxPanel', 30)
+component.Manager.setMenu(c, 'container', 'panel', 'wxPanel', 10)
+component.Manager.setTool(c, 'Windows', bitmaps.wxPanel.GetBitmap(), (0,2))
+
+### wxWizard
+
+class Wizard(component.Container):
+ genericStyles = genericExStyles = []
+ def makeTestWin(self, res, name):
+ wiz = wx.wizard.PreWizard()
+ res.LoadOnObject(wiz, view.frame, STD_NAME, self.klass)
+ # Find and select first page
+ firstPage = None
+ for w in wiz.GetChildren():
+ if isinstance(w, wx.wizard.WizardPage):
+ firstPage = w
+ break
+ if firstPage:
+ wiz.RunWizard(firstPage)
+ else:
+ wx.LogMessage('Wizard is empty')
+ wiz.Destroy()
+ return None, None
+c = Wizard('wxWizard', ['wizard', 'top_level'],
+ ['pos', 'title', 'bitmap'],
+ image=images.TreeWizard.GetImage())
+c.addExStyles('wxWIZARD_EX_HELPBUTTON')
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'wizard', 'wxWizard', 40)
+component.Manager.setTool(c, 'Windows', bitmaps.wxWizard.GetBitmap(), (1,0), (1,2))
+
+### wxWizardPage
+
+class WizardPage(component.Container):
+ def makeTestWin(self, res, name):
+ # Create single-page wizard
+ wiz = wx.wizard.Wizard(view.frame, title='Test Wizard')
+ print self.klass
+ import pdb;pdb.set_trace()
+ page = wx.wizard.PrePyWizardPage()
+ print res.LoadOnObject(page, wiz, STD_NAME, self.klass)
+# page = res.LoadObject(wiz, STD_NAME, self.klass)
+ print page
+ wiz.RunWizard(page)
+ wiz.Destroy()
+ return None, None
+
+c = WizardPage('wxWizardPage', ['wizard_page', 'window'], ['bitmap'],
+ image=images.TreePanel.GetImage())
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'container', 'wizard page', 'wxWizardPage')
+
+### wxWizardPageSimple
+
+c = component.Container('wxWizardPageSimple', ['wizard_page', 'window'], ['bitmap'],
+ image=images.TreePanel.GetImage())
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'container', 'simple wizard page', 'wxWizardPageSimple')
+
+### wxPropertySheetDialog
+
+class ParamButtons(params.ParamBinaryOr):
+ '''Button flags.'''
+ values = ['wxOK', 'wxCANCEL', 'wxYES', 'wxNO', 'wxHELP', 'wxNO_DEFAULT']
+c = component.SmartContainer('wxPropertySheetDialog', ['frame','book','window','top_level'],
+ ['pos', 'size', 'title', 'centered', 'icon', 'buttons'],
+ params={'buttons': ParamButtons},
+ implicit_klass='propertysheetpage',
+ implicit_page='PropertySheetPage',
+ implicit_attributes=['label', 'selected', 'bitmap'],
+ implicit_params={'label': params.ParamText, 'selected': params.ParamBool},
+ image=images.TreeDialog.GetImage())
+c.isTopLevel = True
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+c.setSpecial('icon', attribute.BitmapAttribute)
+c.addStyles('wxDEFAULT_DIALOG_STYLE', 'wxCAPTION', 'wxFRAME_SHAPED',
+ 'wxTAB_TRAVERSAL', 'wxSTAY_ON_TOP', 'wxSYSTEM_MENU',
+ 'wxRESIZE_BORDER', 'wxCLOSE_BOX', 'wxMAXIMIZE_BOX', 'wxMINIMIZE_BOX',
+ 'wxDIALOG_MODAL', 'wxDIALOG_MODELESS', 'wxDIALOG_NO_PARENT',
+ 'wxTAB_TRAVERSAL')
+c.addExStyles('wxDIALOG_EX_CONTEXTHELP', 'wxDIALOG_EX_METAL')
+c.addEvents('EVT_INIT_DIALOG', 'EVT_SIZE', 'EVT_CLOSE',
+ 'EVT_ICONIZE', 'EVT_MAXIMIZE', 'EVT_ACTIVATE', 'EVT_UPDATE_UI')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'propery sheet dialog', 'wxPropertySheetDialog', 50)
+component.Manager.setTool(c, 'Windows', bitmaps.wxPropertySheetDialog.GetBitmap(), (1,1))
+
+### wxBoxSizer
+
+c = component.BoxSizer('wxBoxSizer', ['sizer'], ['orient'],
+ defaults={'orient': 'wxVERTICAL'},
+ images=[images.TreeSizerV.GetImage(), images.TreeSizerH.GetImage()])
+component.Manager.register(c)
+component.Manager.setMenu(c, 'sizer', 'box sizer', 'wxBoxSizer', 10)
+component.Manager.setTool(c, 'Sizers', pos=(0,0))
+
+### wxStaticBoxSizer
+
+c = component.BoxSizer('wxStaticBoxSizer', ['sizer'], ['label', 'orient'],
+ defaults={'orient': 'wxVERTICAL'},
+ images=[images.TreeSizerV.GetImage(), images.TreeSizerH.GetImage()])
+component.Manager.register(c)
+component.Manager.setMenu(c, 'sizer', 'static box sizer', 'wxStaticBoxSizer', 20)
+component.Manager.setTool(c, 'Sizers', pos=(0,2))
+
+### wxGridSizer
+
+c = component.Sizer('wxGridSizer', ['sizer'],
+ ['cols', 'rows', 'vgap', 'hgap'],
+ defaults={'cols': '2', 'rows': '2'},
+ image=images.TreeSizerGrid.GetImage())
+component.Manager.register(c)
+component.Manager.setMenu(c, 'sizer', 'grid sizer', 'wxGridSizer', 30)
+component.Manager.setTool(c, 'Sizers', pos=(0,1))
+
+### wxFlexGridSizer
+
+c = component.Sizer('wxFlexGridSizer', ['sizer'],
+ ['cols', 'rows', 'vgap', 'hgap', 'growablecols', 'growablerows'],
+ defaults={'cols': '2', 'rows': '2'},
+ image=images.TreeSizerFlexGrid.GetImage())
+c.setSpecial('growablecols', attribute.MultiAttribute)
+c.setParamClass('growablecols', params.ParamIntList)
+c.setSpecial('growablerows', attribute.MultiAttribute)
+c.setParamClass('growablerows', params.ParamIntList)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'sizer', 'flex grid sizer', 'wxFlexGridSizer', 40)
+component.Manager.setTool(c, 'Sizers', pos=(1,0))
+
+### wxGridBagSizer
+
+c = component.Sizer('wxGridBagSizer', ['sizer'],
+ ['vgap', 'hgap', 'growablecols', 'growablerows'],
+ image=images.TreeSizerGridBag.GetImage(),
+ implicit_attributes=['option', 'flag', 'border', 'minsize', 'ratio', 'cellpos', 'cellspan'])
+c.setSpecial('growablecols', attribute.MultiAttribute)
+c.setParamClass('growablecols', params.ParamIntList)
+c.setSpecial('growablerows', attribute.MultiAttribute)
+c.setParamClass('growablerows', params.ParamIntList)
+c.setImplicitParamClass('cellpos', params.ParamPosSize)
+c.setImplicitParamClass('cellspan', params.ParamPosSize)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'sizer', 'grid bag sizer', 'wxGridBagSizer', 50)
+component.Manager.setTool(c, 'Sizers', pos=(1,1))
+
+### wxStdDialogButtonSizer
+
+class StdDialogButtonSizer(component.Sizer):
+ def getChildObject(self, node, obj, index):
+ # This sizer orders buttons by fixed ordering, so we must
+ # get the ID to find them
+ try:
+ n = filter(is_element, node.childNodes)[index]
+ n = filter(is_element, n.childNodes)[0]
+ id = n.getAttribute('name')
+ except IndexError:
+ return None
+ items = filter(wx.SizerItem.IsWindow, obj.GetChildren())
+ for item in items:
+ w = item.GetWindow()
+ if w.GetName() == id: return w
+ return None
+c = StdDialogButtonSizer('wxStdDialogButtonSizer', ['btnsizer'], [],
+ implicit_klass='button',
+ implicit_attributes=[])
+component.Manager.register(c)
+component.Manager.setMenu(c, 'sizer', 'dialog button sizer', 'wxStdDialogButtonSizer', 60)
+#component.Manager.setTool(c, 'Sizers', pos=(0,2))
+
+### spacer
+
+c = component.SimpleComponent('spacer', ['spacer'], ['size', 'option', 'flag', 'border'],
+ image=images.TreeSpacer.GetImage())
+c.hasName = False
+component.Manager.register(c)
+component.Manager.setMenu(c, 'sizer', 'spacer', 'spacer', 70)
+component.Manager.setTool(c, 'Sizers', pos=(1,2))
+
+################################################################################
+# Containers
+
+# wxPanel is already added
+
+### wxScrolledWindow
+
+c = component.Container('wxScrolledWindow', ['window', 'control'], ['pos', 'size'])
+c.addStyles('wxHSCROLL', 'wxVSCROLL', 'wxTAB_TRAVERSAL')
+c.addEvents('EVT_SCROLLWIN_TOP',
+ 'EVT_SCROLLWIN_BOTTOM',
+ 'EVT_SCROLLWIN_LINEUP',
+ 'EVT_SCROLLWIN_LINEDOWN',
+ 'EVT_SCROLLWIN_PAGEUP',
+ 'EVT_SCROLLWIN_PAGEDOWN',
+ 'EVT_SCROLLWIN_THUMBTRACK',
+ 'EVT_SCROLLWIN_THUMBRELEASE')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'container', 'scrolled window', 'wxScrolledWindow', 20)
+component.Manager.setTool(c, 'Panels', pos=(3,0))
+
+### wxSplitterWindow
+
+c = component.Container('wxSplitterWindow', ['book', 'window', 'control'],
+ ['pos', 'size', 'orientation', 'sashpos', 'minsize', 'gravity'],
+ # note: no flt[0..1], so just leaving gravity as text
+ params={'orientation': params.ParamOrientation,
+ 'sashpos': params.ParamUnit,
+ 'minsize': params.ParamUnit},
+ image=images.TreeSplitterWindow.GetImage())
+c.addStyles('wxSP_3D', 'wxSP_3DSASH', 'wxSP_3DBORDER', 'wxSP_BORDER',
+ 'wxSP_FULLSASH', 'wxSP_NOBORDER', 'wxSP_PERMIT_UNSPLIT', 'wxSP_LIVE_UPDATE',
+ 'wxSP_NO_XP_THEME')
+c.addEvents('EVT_SPLITTER_SASH_POS_CHANGING', 'EVT_SPLITTER_SASH_POS_CHANGED',
+ 'EVT_SPLITTER_UNSPLIT', 'EVT_SPLITTER_DCLICK')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'container', 'splitter window', 'wxSplitterWindow', 30)
+component.Manager.setTool(c, 'Panels', pos=(2,3))
+
+### wxNotebook
+
+c = component.SmartContainer('wxNotebook', ['book', 'window', 'control'], ['pos', 'size'],
+ implicit_klass='notebookpage',
+ implicit_page='NotebookPage',
+ implicit_attributes=['label', 'selected', 'bitmap'],
+ implicit_params={'label': params.ParamText, 'selected': params.ParamBool},
+ image=images.TreeNotebook.GetImage())
+c.addStyles('wxBK_DEFAULT', 'wxBK_TOP', 'wxBK_LEFT', 'wxBK_RIGHT', 'wxBK_BOTTOM',
+ 'wxNB_FIXEDWIDTH', 'wxNB_MULTILINE', 'wxNB_NOPAGETHEME')
+c.addEquivStyles({'wxBK_DEFAULT': 'wxNB_DEFAULT', 'wxBK_LEFT': 'wxNB_LEFT',
+ 'wxBK_RIGHT': 'wxNB_RIGHT', 'wxBK_TOP': 'wxNB_TOP',
+ 'wxBK_BOTTOM': 'wxNB_BOTTOM'})
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+c.addEvents('EVT_NOTEBOOK_PAGE_CHANGED', 'EVT_NOTEBOOK_PAGE_CHANGING')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'container', 'notebook', 'Notebook control', 40)
+component.Manager.setTool(c, 'Panels', pos=(1,0))
+
+### wxChoicebook
+
+c = component.SmartContainer('wxChoicebook', ['book', 'window', 'control'], ['pos', 'size'],
+ implicit_klass='choicebookpage',
+ implicit_page='ChoicebookPage',
+ implicit_attributes=['label', 'selected', 'bitmap'],
+ implicit_params={'label': params.ParamText, 'selected': params.ParamBool})
+c.addStyles('wxBK_DEFAULT', 'wxBK_TOP', 'wxBK_LEFT', 'wxBK_RIGHT', 'wxBK_BOTTOM')
+c.addEquivStyles({'wxBK_DEFAULT': 'wxCHB_DEFAULT', 'wxBK_LEFT': 'wxCHB_LEFT',
+ 'wxBK_RIGHT': 'wxCHB_RIGHT', 'wxBK_TOP': 'wxCHB_TOP',
+ 'wxBK_BOTTOM': 'wxCHB_BOTTOM'})
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+c.addEvents('EVT_CHOICEBOOK_PAGE_CHANGED', 'EVT_CHOICEBOOK_PAGE_CHANGING')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'container', 'choicebook', 'wxChoicebook', 50)
+component.Manager.setTool(c, 'Panels', pos=(1,3))
+
+### wxListbook
+
+class ListBook(component.SmartContainer):
+ def getChildObject(self, node, obj, index):
+ # Listbook's first child is ListView
+ return obj.GetChildren()[index+1]
+c = ListBook('wxListbook', ['book', 'window', 'control'], ['pos', 'size'],
+ implicit_klass='listbookpage',
+ implicit_page='ListbookPage',
+ implicit_attributes=['label', 'selected', 'bitmap'],
+ implicit_params={'label': params.ParamText, 'selected': params.ParamBool})
+c.addStyles('wxBK_DEFAULT', 'wxBK_LEFT', 'wxBK_RIGHT', 'wxBK_TOP', 'wxBK_BOTTOM')
+c.addEquivStyles({'wxBK_DEFAULT': 'wxLB_DEFAULT', 'wxBK_LEFT': 'wxLB_LEFT',
+ 'wxBK_RIGHT': 'wxLB_RIGHT', 'wxBK_TOP': 'wxLB_TOP',
+ 'wxBK_BOTTOM': 'wxLB_BOTTOM'})
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+c.addEvents('EVT_LISTBOOK_PAGE_CHANGED', 'EVT_LISTBOOK_PAGE_CHANGING')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'container', 'listbook', 'wxListbook', 60)
+component.Manager.setTool(c, 'Panels', pos=(0,3))
+
+### wxTreebook
+
+class TreeBook(component.SmartContainer):
+ def getChildObject(self, node, obj, index):
+ # Listbook's first child is ListView
+ return obj.GetChildren()[index+1]
+c = TreeBook('wxTreebook', ['book', 'window', 'control'], ['pos', 'size'],
+ implicit_klass='treebookpage',
+ implicit_page='TreebookPage',
+ implicit_attributes=['label', 'selected', 'bitmap', 'depth'],
+ implicit_params={'label': params.ParamText,
+ 'selected': params.ParamBool,
+ 'depth': params.ParamInt})
+c.addStyles('wxBK_DEFAULT', 'wxBK_LEFT', 'wxBK_RIGHT', 'wxBK_TOP', 'wxBK_BOTTOM')
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+c.addEvents('EVT_TREEBOOK_PAGE_CHANGED', 'EVT_TREEBOOK_PAGE_CHANGING',
+ 'EVT_TREEBOOK_NODE_COLLAPSED', 'EVT_TREEBOOK_NODE_EXPANDED')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'container', 'treebook', 'wxTreebook', 70)
+component.Manager.setTool(c, 'Panels', pos=(1,1), span=(1,2))
+
+### wxCollapsiblePane
+
+c = component.SmartContainer('wxCollapsiblePane', ['book', 'window', 'control'], ['pos', 'size', 'label', 'collapsed'],
+ implicit_klass='panewindow',
+ implicit_page='',
+ implicit_attributes=[])
+c.addStyles('wxCP_NO_TLW_RESIZE', 'wxCP_DEFAULT_STYLE')
+c.setParamClass('collapsed', params.ParamBool)
+c.addEvents('EVT_COMMAND_COLLPANE_CHANGED')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'container', 'collapsible pane', 'wxCollapsiblePane', 71)
+
+################################################################################
+# Menus
+
+### wxMenuBar
+
+class MenuBar(component.SimpleContainer):
+ isTestable = True
+ # Menubar should be shown in a normal frame
+ def makeTestWin(self, res, name):
+ frame = wx.Frame(None, -1, '%s: %s' % (self.klass, name), name=STD_NAME)
+ object = res.LoadMenuBarOnFrame(frame, STD_NAME)
+ return None, frame
+ def getRect(self, obj):
+ return None
+
+c = MenuBar('wxMenuBar', ['menubar', 'top_level'], [],
+ image=images.TreeMenuBar.GetImage())
+c.addStyles('wxMB_DOCKABLE')
+c.addEvents('EVT_MENU', 'EVT_MENU_OPEN', 'EVT_MENU_CLOSE', 'EVT_MENU_HIGHLIGHT_ALL')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'menu bar', 'wxMenuBar', 40)
+component.Manager.setMenu(c, 'bar', 'menu bar', 'wxMenuBar', 10)
+component.Manager.setTool(c, 'Menus', pos=(1,0))
+
+### wxMenu
+
+c = component.SimpleContainer('wxMenu', ['menu', 'top_level'],
+ ['label', 'help', 'enabled'],
+ image=images.TreeMenu.GetImage())
+#c.setSpecial('bitmap', attribute.BitmapAttribute)
+c.addStyles('wxMENU_TEAROFF')
+c.addEvents('EVT_MENU', 'EVT_MENU_OPEN', 'EVT_MENU_CLOSE', 'EVT_MENU_HIGHLIGHT_ALL')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'menu', 'wxMenu', 50)
+component.Manager.setMenu(c, 'ROOT', 'menu', 'wxMenu', 20)
+component.Manager.setTool(c, 'Menus', pos=(1,1), span=(2,1))
+
+### wxMenuItem
+
+c = component.SimpleComponent('wxMenuItem', ['menu_item'],
+ ['label', 'bitmap', 'accel', 'help',
+ 'checkable', 'radio', 'enabled', 'checked'],
+ image=images.TreeMenuItem.GetImage())
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+c.addEvents('EVT_MENU', 'EVT_MENU_HIGHLIGHT')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'ROOT', 'menu item', 'wxMenuItem', 10)
+component.Manager.setTool(c, 'Menus', pos=(1,2))
+
+### wxToolBar
+
+class ToolBar(component.SimpleContainer):
+ isTestable = True
+ # Toolbar should be shown in a normal frame
+ def makeTestWin(self, res, name):
+ frame = wx.Frame(None, -1, '%s: %s' % (self.klass, name), name=STD_NAME)
+ object = res.LoadToolBar(frame, STD_NAME)
+ return None, frame
+ def getRect(self, obj):
+ return None
+
+c = ToolBar('wxToolBar', ['toolbar', 'top_level', 'control'],
+ ['bitmapsize', 'margins', 'packing', 'separation',
+ 'dontattachtoframe', 'pos', 'size'],
+ image=images.TreeToolBar.GetImage())
+c.addStyles('wxTB_FLAT', 'wxTB_DOCKABLE', 'wxTB_VERTICAL', 'wxTB_HORIZONTAL',
+ 'wxTB_3DBUTTONS','wxTB_TEXT', 'wxTB_NOICONS', 'wxTB_NODIVIDER',
+ 'wxTB_NOALIGN', 'wxTB_HORZ_LAYOUT', 'wxTB_HORZ_TEXT',
+ 'wxTB_TOP', 'wxTB_LEFT', 'wxTB_RIGHT', 'wxTB_BOTTOM')
+c.setParamClass('dontattachtoframe', params.ParamBool)
+c.setParamClass('bitmapsize', params.ParamPosSize)
+c.setParamClass('margins', params.ParamPosSize)
+c.setParamClass('packing', params.ParamUnit)
+c.setParamClass('separation', params.ParamUnit)
+c.renameDict = {'dontattachtoframe': "don't attach"}
+c.addEvents('EVT_TOOL', 'EVT_TOOL_ENTER', 'EVT_TOOL_RCLICKED')
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'tool bar', 'wxToolBar', 50)
+component.Manager.setMenu(c, 'bar', 'tool bar', 'wxToolBar', 20)
+component.Manager.setTool(c, 'Menus', pos=(0,0))
+
+### wxTool
+
+c = component.SimpleComponent('tool', ['tool'],
+ ['bitmap', 'bitmap2', 'radio', 'toggle',
+ 'tooltip', 'longhelp', 'label'],
+ image=images.TreeTool.GetImage())
+component.Manager.register(c)
+c.setSpecial('bitmap', attribute.BitmapAttribute)
+c.setSpecial('bitmap2', attribute.BitmapAttribute)
+c.setParamClass('bitmap2', params.ParamBitmap)
+c.setParamClass('toggle', params.ParamBool)
+c.addEvents('EVT_TOOL', 'EVT_TOOL_ENTER', 'EVT_TOOL_RCLICKED')
+component.Manager.setMenu(c, 'ROOT', 'tool', 'wxTool', 10)
+component.Manager.setTool(c, 'Menus', pos=(0,1))
+
+### wxSeparator
+
+c = component.SimpleComponent('separator', ['separator'], [],
+ image=images.TreeSeparator.GetImage())
+c.hasName = False
+component.Manager.register(c)
+component.Manager.setMenu(c, 'ROOT', 'separator', 'separator', 20)
+component.Manager.setTool(c, 'Menus', pos=(0,2))
+
+### wxBreak
+
+c = component.SimpleComponent('break', ['break'], [],
+ image=images.TreeSeparator.GetImage())
+c.hasName = False
+component.Manager.register(c)
+component.Manager.setMenu(c, 'ROOT', 'break', 'break', 21)
+
+### wxStatusBar
+
+c = component.SimpleComponent('wxStatusBar', ['statusbar'], ['fields', 'widths', 'styles'])
+c.addStyles('wxST_SIZEGRIP')
+c.setParamClass('fields', params.ParamIntP)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'bar', 'status bar', 'wxStatusBar', 30)
+component.Manager.setTool(c, 'Menus', pos=(2,0))
+
+################################################################################
+
+### wxBitmap
+
+c = component.SimpleComponent('wxBitmap', ['top_level'], ['object'])
+c.renameDict = {'object': ''}
+c.setSpecial('object', attribute.BitmapAttribute)
+c.setParamClass('object', params.ParamBitmap)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'bitmap', 'wxBitmap', 60)
+
+### wxIcon
+
+c = component.SimpleComponent('wxIcon', ['top_level'], ['object'])
+c.renameDict = {'object': ''}
+c.setSpecial('object', attribute.BitmapAttribute)
+c.setParamClass('object', params.ParamBitmap)
+component.Manager.register(c)
+component.Manager.setMenu(c, 'TOP_LEVEL', 'icon', 'wxIcon', 70)
+
+### wxXXX
+
+#c = component.Component('wxXXX', ['control','tool'],
+# ['pos', 'size', ...])
+#c.addStyles(...)
+#component.Manager.register(c)
+#component.Manager.setMenu(c, 'control', 'XXX', 'wxXXX', NN)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/gizmos.crx b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/gizmos.crx
new file mode 100644
index 0000000..5f3f1e4
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/gizmos.crx
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<resource>
+ <component class="Component" name="LEDNumberCtrl" provider="Roman Rolinsky &lt;genericsoma@gmail.com&gt;">
+ <groups>
+ <item>control</item>
+ </groups>
+ <attributes>
+ <item>pos</item>
+ <item>size</item>
+ <item>value</item>
+ </attributes>
+ <has-name>1</has-name>
+ <styles>
+ <item>wxLED_ALIGN_LEFT</item>
+ <item>wxLED_ALIGN_RIGHT</item>
+ <item>wxLED_ALIGN_CENTER</item>
+ <item>wxLED_ALIGN_FADED</item>
+ </styles>
+ <module>xh_gizmos</module>
+ <handler>LEDNumberCtrlXmlHandler</handler>
+ <menu>gizmo</menu>
+ <label>LED number</label>
+ <help>LED-style control</help>
+ <panel>Gizmos</panel>
+ <pos>1,0</pos>
+ </component>
+ <component class="Component" name="EditableListBox" provider="Roman Rolinsky &lt;genericsoma@gmail.com&gt;">
+ <groups>
+ <item>control</item>
+ </groups>
+ <attributes>
+ <item>pos</item>
+ <item>size</item>
+ <item>label</item>
+ <item>content:ContentAttribute</item>
+ </attributes>
+ <has-name>1</has-name>
+ <styles>
+ <item>wxEL_ALLOW_NEW</item>
+ <item>wxEL_ALLOW_EDIT</item>
+ <item>wxEL_ALLOW_DELETE</item>
+ </styles>
+ <module>xh_gizmos</module>
+ <handler>EditableListBoxXmlHandler</handler>
+ <menu>gizmo</menu>
+ <label>editable list box</label>
+ <help>list box with editable items</help>
+ <panel>Gizmos</panel>
+ <pos>0,1</pos>
+ </component>
+ <component class="Component" name="TreeListCtrl" provider="Roman Rolinsky &lt;genericsoma@gmail.com&gt;">
+ <groups>
+ <item>control</item>
+ </groups>
+ <attributes>
+ <item>pos</item>
+ <item>size</item>
+ </attributes>
+ <has-name>1</has-name>
+ <styles>
+ <item>wxTR_DEFAULT_STYLE</item>
+ <item>wxTR_EDIT_LABELS</item>
+ <item>wxTR_NO_BUTTONS</item>
+ <item>wxTR_HAS_BUTTONS</item>
+ <item>wxTR_TWIST_BUTTONS</item>
+ <item>wxTR_NO_LINES</item>
+ <item>wxTR_FULL_ROW_HIGHLIGHT</item>
+ <item>wxTR_LINES_AT_ROOT</item>
+ <item>wxTR_HIDE_ROOT</item>
+ <item>wxTR_ROW_LINES</item>
+ <item>wxTR_HAS_VARIABLE_ROW_HEIGHT</item>
+ <item>wxTR_SINGLE</item>
+ <item>wxTR_MULTIPLE</item>
+ <item>wxTR_EXTENDED</item>
+ </styles>
+ <module>xh_gizmos</module>
+ <handler>TreeListCtrlXmlHandler</handler>
+ <menu>gizmo</menu>
+ <label>tree list ctrl</label>
+ <help>tree combined with list control</help>
+ <panel>Gizmos</panel>
+ <pos>0,0</pos>
+ </component>
+ <component class="Component" name="DynamicSashWindow" provider="Roman Rolinsky &lt;genericsoma@gmail.com&gt;">
+ <groups>
+ <item>control</item>
+ </groups>
+ <attributes>
+ <item>pos</item>
+ <item>size</item>
+ </attributes>
+ <has-name>1</has-name>
+ <styles>
+ <item>wxDS_MANAGE_SCROLLBARS</item>
+ <item>wxDS_DRAG_CORNER</item>
+ </styles>
+ <events>
+ <item>wxEVT_DYNAMIC_SASH_SPLIT</item>
+ <item>wxEVT_DYNAMIC_SASH_UNIFY</item>
+ </events>
+ <module>xh_gizmos</module>
+ <handler>DynamicSashWindowXmlHandler</handler>
+ <menu>gizmo</menu>
+ <label>dynamic sash window</label>
+ <panel>Gizmos</panel>
+ <pos>0,2</pos>
+ </component>
+ <object class="wxPanel" name="test">
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="EditableListBox">
+ <size>100,100</size>
+ <label>label</label>
+ <content>
+ <item>item1</item>
+ </content>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="TreeListCtrl"/>
+ </object>
+ <object class="sizeritem">
+ <object class="DynamicSashWindow">
+ <size>100,100</size>
+ </object>
+ </object>
+ </object>
+ </object>
+</resource> \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/wxlib.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/wxlib.py
new file mode 100644
index 0000000..25f29d0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/wxlib.py
@@ -0,0 +1,39 @@
+# Name: wxlib.py
+# Purpose: Component plugins for wx.lib classes
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 05.09.2007
+# RCS-ID: $Id$
+
+import xh_wxlib
+from wx.tools.XRCed import component, params
+from wx.tools.XRCed.globals import TRACE
+from wx.lib.ticker_xrc import wxTickerXmlHandler
+
+TRACE('*** creating wx.lib components')
+
+# wx.lib.foldpanelbar.FoldPanelBar
+
+c = component.SmartContainer('wx.lib.foldpanelbar.FoldPanelBar', ['book', 'window', 'control'],
+ ['pos', 'size'],
+ implicit_klass='foldpanel',
+ implicit_page='FoldPanel',
+ implicit_attributes=['label', 'collapsed'],
+ implicit_params={'collapsed': params.ParamBool})
+c.addStyles('FPB_SINGLE_FOLD', 'FPB_COLLAPSE_TO_BOTTOM',
+ 'FPB_EXCLUSIVE_FOLD', 'FPB_HORIZONTAL', 'FPB_VERTICAL')
+component.Manager.register(c)
+component.Manager.addXmlHandler(xh_wxlib.FoldPanelBarXmlHandler)
+component.Manager.setMenu(c, 'bar', 'fold panel bar', 'FoldPanelBar', 1000)
+
+# wx.lib.ticker.Ticker
+
+class ParamDirection(params.RadioBox):
+ choices = {'right to left': 'rtl', 'left to right': 'ltr'}
+ default = 'rtl'
+c = component.Component('wxTicker', ['control'],
+ ['pos', 'size', 'start', 'text', 'ppf', 'fps', 'direction'],
+ params={'ppf': params.ParamInt, 'fps': params.ParamInt,
+ 'direction': ParamDirection})
+component.Manager.register(c)
+component.Manager.addXmlHandler(wxTickerXmlHandler)
+component.Manager.setMenu(c, 'control', 'ticker', 'Ticker', 1000)
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/xh_gizmos.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/xh_gizmos.py
new file mode 100644
index 0000000..4e74905
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/xh_gizmos.py
@@ -0,0 +1,158 @@
+# Name: gizmos.py
+# Purpose: XML handlers for wx.gismos classes
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 09.07.2007
+# RCS-ID: $Id$
+
+import wx
+import wx.xrc as xrc
+import wx.gizmos as gizmos
+
+class LEDNumberCtrlXmlHandler(xrc.XmlResourceHandler):
+ def __init__(self):
+ xrc.XmlResourceHandler.__init__(self)
+ # Standard styles
+ self.AddWindowStyles()
+ # Custom styles
+ self.AddStyle('wxLED_ALIGN_LEFT', gizmos.LED_ALIGN_LEFT)
+ self.AddStyle('wxLED_ALIGN_RIGHT', gizmos.LED_ALIGN_RIGHT)
+ self.AddStyle('wxLED_ALIGN_CENTER', gizmos.LED_ALIGN_CENTER)
+ self.AddStyle('wxLED_DRAW_FADED', gizmos.LED_DRAW_FADED)
+
+ def CanHandle(self,node):
+ return self.IsOfClass(node, 'LEDNumberCtrl')
+
+ # Process XML parameters and create the object
+ def DoCreateResource(self):
+ assert self.GetInstance() is None
+ w = gizmos.LEDNumberCtrl(self.GetParentAsWindow(),
+ self.GetID(),
+ self.GetPosition(),
+ self.GetSize(),
+ self.GetStyle())
+ # wxLED_ALIGN_MASK was incorrect
+ align = self.GetStyle() & 7
+ if align: w.SetAlignment(self.GetStyle() & 7)
+ w.SetValue(self.GetText('value'))
+ self.SetupWindow(w)
+ return w
+
+
+class EditableListBoxXmlHandler(xrc.XmlResourceHandler):
+ def __init__(self):
+ xrc.XmlResourceHandler.__init__(self)
+ # Standard styles
+ self.AddWindowStyles()
+ # Custom styles
+ self.AddStyle('wxEL_ALLOW_NEW', gizmos.EL_ALLOW_NEW)
+ self.AddStyle('wxEL_ALLOW_EDIT', gizmos.EL_ALLOW_EDIT)
+ self.AddStyle('wxEL_ALLOW_DELETE', gizmos.EL_ALLOW_DELETE)
+
+ def CanHandle(self, node):
+ return self.IsOfClass(node, 'EditableListBox')
+# return self.IsOfClass(node, 'EditableListBox') or \
+# self.insideBox and node.GetName() == 'item'
+
+ # Process XML parameters and create the object
+ def DoCreateResource(self):
+ assert self.GetInstance() is None
+
+ w = gizmos.EditableListBox(self.GetParentAsWindow(),
+ self.GetID(),
+ self.GetText("label"),
+ self.GetPosition(),
+ self.GetSize(),
+ self.GetStyle(),
+ self.GetName())
+
+ # Doesn't work
+ #self.insideBox = True
+ #self.CreateChildrenPrivately(None, self.GetParamNode('content'))
+ #self.insideBox = False
+
+ # Long way
+ strings = []
+ n = self.GetParamNode('content')
+ if n: n = n.GetChildren()
+ while n:
+ if n.GetType() != xrc.XML_ELEMENT_NODE or n.GetName() != "item":
+ n = n.GetNext()
+ continue
+ strings.append(n.GetNodeContent())
+ n = n.GetNext()
+ w.SetStrings(strings)
+ self.SetupWindow(w)
+ return w
+
+
+class TreeListCtrlXmlHandler(xrc.XmlResourceHandler):
+ def __init__(self):
+ xrc.XmlResourceHandler.__init__(self)
+ # Standard styles
+ self.AddWindowStyles()
+ # Custom styles
+ self.AddStyle('wxTR_DEFAULT_STYLE', wx.TR_DEFAULT_STYLE)
+ self.AddStyle('wxTR_EDIT_LABELS', wx.TR_EDIT_LABELS)
+ self.AddStyle('wxTR_NO_BUTTONS', wx.TR_NO_BUTTONS)
+ self.AddStyle('wxTR_HAS_BUTTONS', wx.TR_HAS_BUTTONS)
+ self.AddStyle('wxTR_TWIST_BUTTONS', wx.TR_TWIST_BUTTONS)
+ self.AddStyle('wxTR_NO_LINES', wx.TR_NO_LINES)
+ self.AddStyle('wxTR_FULL_ROW_HIGHLIGHT', wx.TR_FULL_ROW_HIGHLIGHT)
+ self.AddStyle('wxTR_LINES_AT_ROOT', wx.TR_LINES_AT_ROOT)
+ self.AddStyle('wxTR_HIDE_ROOT', wx.TR_HIDE_ROOT)
+ self.AddStyle('wxTR_ROW_LINES', wx.TR_ROW_LINES)
+ self.AddStyle('wxTR_HAS_VARIABLE_ROW_HEIGHT', wx.TR_HAS_VARIABLE_ROW_HEIGHT)
+ self.AddStyle('wxTR_SINGLE', wx.TR_SINGLE)
+ self.AddStyle('wxTR_MULTIPLE', wx.TR_MULTIPLE)
+ self.AddStyle('wxTR_EXTENDED', wx.TR_EXTENDED)
+
+ def CanHandle(self, node):
+ return self.IsOfClass(node, 'TreeListCtrl')
+
+ # Process XML parameters and create the object
+ def DoCreateResource(self):
+ assert self.GetInstance() is None
+
+ w = gizmos.TreeListCtrl(self.GetParentAsWindow(),
+ self.GetID(),
+ style=self.GetStyle(),
+ name=self.GetName())
+ w.AddColumn("Main column")
+ w.AddColumn('Column 1')
+ w.SetMainColumn(0)
+ w.SetColumnWidth(0, 50)
+ w.SetColumnWidth(1, 50)
+ root = w.AddRoot('Root')
+ w.SetItemText(root, "col 1", 1)
+ item1 = w.AppendItem(root, 'item 1')
+ w.SetItemText(item1, "col 1", 1)
+ w.Expand(root)
+ return w
+
+
+class DynamicSashWindowXmlHandler(xrc.XmlResourceHandler):
+ def __init__(self):
+ xrc.XmlResourceHandler.__init__(self)
+ # Standard styles
+ self.AddWindowStyles()
+ # Custom styles
+ self.AddStyle('wxDS_MANAGE_SCROLLBARS', gizmos.DS_MANAGE_SCROLLBARS)
+ self.AddStyle('wxDS_DRAG_CORNER', gizmos.DS_DRAG_CORNER)
+
+ def CanHandle(self, node):
+ return self.IsOfClass(node, 'DynamicSashWindow')
+
+ # Process XML parameters and create the object
+ def DoCreateResource(self):
+ assert self.GetInstance() is None
+
+ w = gizmos.DynamicSashWindow(self.GetParentAsWindow(),
+ self.GetID(),
+ self.GetPosition(),
+ self.GetSize(),
+ self.GetStyle(),
+ self.GetName())
+
+ self.SetupWindow(w)
+ return w
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/xh_wxlib.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/xh_wxlib.py
new file mode 100644
index 0000000..7c52e57
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/plugins/xh_wxlib.py
@@ -0,0 +1,62 @@
+# Name: wxlib.py
+# Purpose: XML handlers for wx.lib classes
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 05.09.2007
+# RCS-ID: $Id$
+
+import wx
+import wx.xrc as xrc
+import wx.lib.foldpanelbar as fpb
+from wx.lib.ticker_xrc import wxTickerXmlHandler
+
+from wx.tools.XRCed.globals import TRACE
+
+class FoldPanelBarXmlHandler(xrc.XmlResourceHandler):
+ def __init__(self):
+ xrc.XmlResourceHandler.__init__(self)
+ # Standard styles
+ self.AddWindowStyles()
+ # Custom styles
+ self.AddStyle('FPB_SINGLE_FOLD', fpb.FPB_SINGLE_FOLD)
+ self.AddStyle('FPB_COLLAPSE_TO_BOTTOM', fpb.FPB_COLLAPSE_TO_BOTTOM)
+ self.AddStyle('FPB_EXCLUSIVE_FOLD', fpb.FPB_EXCLUSIVE_FOLD)
+ self.AddStyle('FPB_HORIZONTAL', fpb.FPB_HORIZONTAL)
+ self.AddStyle('FPB_VERTICAL', fpb.FPB_VERTICAL)
+ self._isInside = False
+
+ def CanHandle(self,node):
+ return not self._isInside and self.IsOfClass(node, 'wx.lib.foldpanelbar.FoldPanelBar') or \
+ self._isInside and self.IsOfClass(node, 'foldpanel')
+
+ # Process XML parameters and create the object
+ def DoCreateResource(self):
+ TRACE('DoCreateResource: %s', self.GetClass())
+ if self.GetClass() == 'foldpanel':
+ n = self.GetParamNode('object')
+ if n:
+ old_ins = self._isInside
+ self._isInside = False
+ bar = self._w
+ item = self.CreateResFromNode(n, bar, None)
+ self._isInside = old_ins
+ wnd = item
+ if wnd:
+ item = bar.AddFoldPanel(self.GetText('label'),
+ collapsed=self.GetBool('collapsed'))
+ bar.AddFoldPanelWindow(item, wnd)
+ return wnd
+ else:
+ w = fpb.FoldPanelBar(self.GetParentAsWindow(),
+ self.GetID(),
+ self.GetPosition(),
+ self.GetSize(),
+ self.GetStyle(),
+ self.GetStyle('exstyle'))
+ self.SetupWindow(w)
+ self._w = w
+ old_ins = self._isInside
+ self._isInside = True
+ self.CreateChildren(w, True)
+ self._isInside = old_ins
+ return w
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/presenter.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/presenter.py
new file mode 100644
index 0000000..9c3ae5f
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/presenter.py
@@ -0,0 +1,738 @@
+# Name: presenter.py
+# Purpose: Presenter part
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 07.06.2007
+# RCS-ID: $Id: presenter.py 71860 2012-06-25 15:46:16Z ROL $
+
+import os,tempfile,shutil
+from xml.parsers import expat
+import cPickle
+from globals import *
+import view
+from model import Model, MyDocument
+from component import Manager
+import undo
+
+# Presenter class linking model to view objects
+class _Presenter:
+ def init(self):
+ Model.init()
+ self.path = ''
+ # Global modified state
+ self.setModified(False) # sets applied
+ view.frame.Clear()
+ view.tree.Clear()
+ view.tree.SetPyData(view.tree.root, Model.mainNode)
+ view.testWin.Init()
+ g.undoMan.Clear()
+ # Insert/append mode flags
+ self.createSibling = self.insertBefore = False
+ # Select main node attributes
+ self.setData(view.tree.root)
+
+ def loadXML(self, path):
+ Model.loadXML(path)
+ view.tree.Flush()
+ view.tree.SetPyData(view.tree.root, Model.mainNode)
+ self.setData(view.tree.root)
+ if g.conf.expandOnOpen:
+ view.tree.ExpandAll()
+
+ def saveXML(self, path):
+ Model.saveXML(path)
+
+ def open(self, path):
+ if not os.path.exists(path):
+ wx.LogError('File does not exists: %s' % path)
+ raise IOError
+ try:
+ self.path = os.path.abspath(path)
+ TRACE('Loading XML file: %s', self.path)
+ self.loadXML(self.path)
+ # Change dir
+ dir = os.path.dirname(self.path)
+ if dir: os.chdir(dir)
+ self.setModified(False)
+ g.conf.localconf = self.createLocalConf(path)
+ except:
+ logger.exception('error loading XML file')
+ wx.LogError('Error loading XML file: %s' % path)
+ raise
+
+ def save(self, path):
+ # Apply changes if needed
+ if not self.applied:
+ self.update(self.item)
+ try:
+ tmpFile,tmpName = tempfile.mkstemp(prefix='xrced-')
+ os.close(tmpFile)
+ TRACE('Saving temporary file: %s', tmpName)
+ self.saveXML(tmpName)
+ TRACE('copying to the main file: %s', path)
+ shutil.copy(tmpName, path)
+ self.path = path
+ self.setModified(False)
+ except:
+ logger.exception('error saving XML file')
+ wx.LogError('Error saving XML file: %s' % path)
+ raise
+
+ def setModified(self, state=True, setDirty=True):
+ '''Set global modified state.'''
+ TRACE('setModified %s %s', state, setDirty)
+ self.modified = state
+ # Set applied flag
+ if not state: self.applied = True
+ name = os.path.basename(self.path)
+ if not name: name = 'UNTITLED'
+ # Update GUI
+ if state:
+ view.frame.SetTitle(progname + ': ' + name + ' *')
+ # Update test window
+ if view.testWin.IsShown() and setDirty:
+ view.testWin.isDirty = True
+ if g.conf.autoRefresh:
+ self.refreshTestWin()
+ else:
+ view.frame.SetTitle(progname + ': ' + name)
+
+ def setApplied(self, state=True):
+ '''Set panel state.'''
+ TRACE('setApplied %s', state)
+ self.applied = state
+ if not state and not self.modified:
+ self.setModified(setDirty=False) # toggle global state
+
+ def createUndoEdit(self, item=None, page=None):
+ TRACE('createUndoEdit')
+ # Create initial undo object
+ if item is None: item = self.item
+ if page is None: page = view.panel.nb.GetSelection()
+ view.panel.undo = undo.UndoEdit(item, page)
+
+ def registerUndoEdit(self):
+ TRACE('registerUndoEdit')
+ g.undoMan.RegisterUndo(view.panel.undo)
+ view.panel.undo = None
+
+ def panelIsDirty(self):
+ '''Check if the panel was changed since last undo.'''
+ # Register undo
+ if view.panel.undo:
+ panel = view.panel.GetActivePanel()
+ if view.panel.undo.values != panel.GetValues():
+ return True
+ return False
+
+ def setData(self, item):
+ '''Set data and view for current tree item.'''
+
+ self.item = item
+ if item == view.tree.root:
+ TRACE('setData: root node')
+ self.container = None
+ self.comp = Manager.rootComponent
+ self.panels = view.panel.SetData(self.container, self.comp, Model.mainNode)
+ else:
+ node = view.tree.GetPyData(item)
+ if node.nodeType != node.COMMENT_NODE:
+ TRACE('setData: %s', node.getAttribute('class'))
+ self.comp = Manager.getNodeComp(node)
+ parentItem = view.tree.GetItemParent(item)
+ parentNode = view.tree.GetPyData(parentItem)
+ if parentNode == Model.mainNode:
+ self.container = Manager.rootComponent
+ else:
+ parentClass = parentNode.getAttribute('class')
+ self.container = Manager.components[parentClass]
+ self.panels = view.panel.SetData(self.container, self.comp, node)
+ # Create new pending undo
+ self.createUndoEdit(self.item)
+
+ if view.testWin.IsShown():
+ self.highlight(item)
+
+ def highlight(self, item):
+ TRACE('highlight')
+ if view.testWin.IsDirty() or item == view.tree.root or \
+ view.tree.GetPyData(item).nodeType == Model.dom.COMMENT_NODE:
+ view.testWin.RemoveHighlight()
+ return
+ try:
+ rect = view.testWin.FindObjectRect(item)
+ if not rect:
+ view.testWin.RemoveHighlight()
+ return
+ view.testWin.Highlight(rect)
+ except:
+ logger.exception('highlighting failed')
+
+ def updateCreateState(self, forceSibling, forceInsert):
+ if self.container:
+ if self.comp.isContainer():
+ self.createSibling = forceSibling
+ else:
+ self.createSibling = True
+ else:
+ self.createSibling = False
+ self.insertBefore = forceInsert
+ TRACE('updateCreateState: %s %s', self.createSibling, self.insertBefore)
+
+ def popupMenu(self, forceSibling, forceInsert, pos):
+ '''Show popup menu and set sibling/insert flags.'''
+ self.updateCreateState(forceSibling, forceInsert)
+ menu = view.XMLTreeMenu(self.container, self.comp, view.tree,
+ self.createSibling, self.insertBefore)
+ view.tree.PopupMenu(menu, pos)
+ menu.Destroy()
+
+ def create(self, comp, child=None):
+ '''
+ Add DOM node as child or sibling depending on flags. Return new item.
+
+ If child is passed replace by existing data.
+ '''
+ if child is None:
+ child = Model.createObjectNode(comp.klass)
+ # Set default values
+ for k,v in comp.defaults.items():
+ comp.addAttribute(child, k, v)
+ data = wx.TreeItemData(child)
+ item = self.item
+ if not self.applied:
+ self.update(item)
+ if item == view.tree.root:
+ self.createSibling = False # can't create sibling of root
+ if self.createSibling:
+ parentItem = view.tree.GetItemParent(item)
+ parentNode = view.tree.GetPyData(parentItem)
+ else:
+ parentNode = view.tree.GetPyData(item)
+ label = comp.getTreeText(child)
+ imageId = comp.getTreeImageId(child)
+ if self.createSibling:
+ node = view.tree.GetPyData(item)
+ if self.insertBefore:
+ self.container.insertBefore(parentNode, child, node)
+ item = view.tree.InsertItemBefore(
+ parentItem, item, label, imageId, data=data)
+
+ else:
+ self.container.insertAfter(parentNode, child, node)
+ item = view.tree.InsertItem(
+ parentItem, item, label, imageId, data=data)
+ else:
+ if self.insertBefore and view.tree.ItemHasChildren(item):
+ nextNode = view.tree.GetPyData(view.tree.GetFirstChild(item)[0])
+ self.comp.insertBefore(parentNode, child, nextNode)
+ item = view.tree.PrependItem(item, label, imageId, data=data)
+ else:
+ self.comp.appendChild(parentNode, child)
+ item = view.tree.AppendItem(item, label, imageId, data=data)
+ view.tree.SetItemStyle(item, child)
+ view.tree.EnsureVisible(item)
+ view.tree.UnselectAll()
+ if view.testWin.IsShown():
+ view.testWin.isDirty = True
+ view.tree.SelectItem(item)
+ self.setModified()
+ return item
+
+ def createRef(self, ref, child=None):
+ '''Create object_ref element node.'''
+ if child is None:
+ child = Model.createRefNode(ref)
+ refNode = Model.findResource(ref)
+ if refNode:
+ comp = Manager.getNodeComp(refNode)
+ else:
+ comp = Manager.getNodeComp(child)
+ self.create(comp, child)
+
+ def createComment(self):
+ '''Create comment node.'''
+ node = Model.createCommentNode()
+ comp = Manager.getNodeComp(node)
+ self.create(comp, node)
+
+ def replace(self, comp, node=None):
+ '''Replace DOM node by new or passed node. Return new item.'''
+ TRACE('replace')
+ if node is None:
+ node = Model.createObjectNode(comp.klass)
+ if not self.applied:
+ self.update(item)
+ data = wx.TreeItemData(node)
+ item = self.item
+ parentItem = view.tree.GetItemParent(item)
+ parentNode = view.tree.GetPyData(parentItem)
+ oldNode = view.tree.GetPyData(item)
+ self.container.replaceChild(parentNode, node, oldNode)
+ # Replace tree item: insert new, remove old
+ label = comp.getTreeText(node)
+ imageId = comp.getTreeImageId(node)
+ item = view.tree.InsertItem(parentItem, item, label, imageId, data=data)
+ view.tree.Delete(view.tree.GetPrevSibling(item))
+ self.item = item
+ # Add children
+ for n in filter(is_object, node.childNodes):
+ view.tree.AddNode(item, comp.getTreeNode(n))
+ view.tree.EnsureVisible(item)
+ # Update panel
+ view.tree.SelectItem(item)
+ self.setModified()
+ return oldNode
+
+ def subclass(self, item, subclass):
+ node = view.tree.GetPyData(item)
+ if subclass:
+ node.setAttribute('subclass', subclass)
+ elif node.hasAttribute('subclass'):
+ node.removeAttribute('subclass')
+ # Update item label
+ view.tree.SetItemImage(item, self.comp.getTreeImageId(node))
+ view.tree.SetItemText(item, self.comp.getTreeText(node))
+ # Update panel
+ view.tree.SelectItem(item)
+ self.setModified()
+
+ def update(self, item):
+ '''Update DOM with new attribute values. Update tree if necessary.'''
+ node = view.tree.GetPyData(item)
+ isComment = node.nodeType == node.COMMENT_NODE
+ if isComment:
+ subclass = None
+ else:
+ subclass = node.getAttribute('subclass')
+ # Update (sub)class if needed
+ cls = view.panel.textClass.GetValue()
+ if not subclass:
+ if not isComment and cls != self.comp.klass:
+ if node.tagName == 'object_ref' and not cls:
+ if node.hasAttribute('class'):
+ node.removeAttribute('class')
+ TRACE('removed "class" tag')
+ else:
+ TRACE('update class: %s', cls)
+ node.setAttribute('class', cls)
+ else:
+ value = subclass + '(%s)' % self.comp.klass
+ if cls != value:
+ iLeft = cls.find('(')
+ iRight = cls.find(')')
+ if iLeft != -1 and iLeft < iRight:
+ subclass = cls[:iLeft]
+ klass = cls[iLeft+1:iRight]
+ TRACE('update class/subclass: %s', cls)
+ node.setAttribute('class', klass)
+ node.setAttribute('subclass', subclass)
+ else:
+ TRACE('remove subclass')
+ node.removeAttribute('subclass')
+ node.setAttribute('class', cls)
+ if self.comp and self.comp.hasName:
+ name = view.panel.textName.GetValue()
+ if name:
+ node.setAttribute('name', name)
+ elif node.hasAttribute('name'): # clean up empty names
+ node.removeAttribute('name')
+ if item != view.tree.root:
+ for panel in self.panels:
+ if not panel.node: continue
+ # Replace node contents except object children
+ for n in panel.node.childNodes[:]:
+ if not is_object(n):
+ panel.node.removeChild(n)
+ n.unlink()
+ for panel in self.panels:
+ for a,value in panel.GetValues():
+ if value:
+ try:
+ if isinstance(panel, view.AttributePanel) and panel.comp:
+ comp = panel.comp
+ else:
+ comp = self.comp
+ comp.addAttribute(panel.node, a, value)
+ except:
+ logger.exception('addAttribute error: %s %s', a, value)
+ if item != view.tree.root:
+ view.tree.SetItemImage(item, self.comp.getTreeImageId(node))
+ view.tree.SetItemText(item, self.comp.getTreeText(node))
+ self.setApplied()
+ # Set dirty flag
+ if view.testWin.IsShown():
+ view.testWin.isDirty = True
+
+ def unselect(self):
+ if not self.applied:
+ self.update(self.item)
+ if view.testWin.IsShown() and view.testWin.item == self.item:
+ view.testWin.Destroy()
+ view.tree.UnselectAll()
+ self.setData(view.tree.root)
+
+ def flushSubtree(self, item=None, node=None):
+ # Remember test item index
+ TRACE('flushSubtree')
+ if view.testWin.item is not None:
+ itemIndex = view.tree.ItemFullIndex(view.testWin.item)
+ view.tree.FlushSubtree(item, node)
+ if view.testWin.item is not None:
+ view.testWin.item = view.tree.ItemAtFullIndex(itemIndex)
+
+ def delete(self, item):
+ '''Delete selected object(s). Return removed XML node.'''
+ TRACE('delete')
+ parentItem = view.tree.GetItemParent(item)
+ parentNode = view.tree.GetPyData(parentItem)
+ node = view.tree.GetPyData(item)
+ node = self.container.removeChild(parentNode, node)
+ view.tree.Delete(item)
+ # If deleting the top-level object, remove view
+ if view.testWin.IsShown() and view.testWin.item == item:
+ view.testWin.Destroy()
+ self.setApplied()
+ self.unselect()
+ self.setModified()
+ return node
+
+ def deleteMany(self, items):
+ '''Delete selected object(s).'''
+ for item in items:
+ if not item.IsOk(): continue # child already deleted
+ parentItem = view.tree.GetItemParent(item)
+ parentNode = view.tree.GetPyData(parentItem)
+ node = view.tree.GetPyData(item)
+ node = self.container.removeChild(parentNode, node)
+ node.unlink() # delete completely
+ view.tree.Delete(item)
+ self.setApplied()
+ self.unselect()
+ self.setModified()
+
+ def cut(self):
+ self.copy()
+ return self.delete(view.tree.GetSelection())
+
+ def copy(self):
+ # Update values from panel first
+ item = view.tree.GetSelection()
+ if not self.applied:
+ self.update(item)
+ node = view.tree.GetPyData(item)
+ if self.container.requireImplicit(node):
+ implicit = node.parentNode
+ else:
+ implicit = None
+ if wx.TheClipboard.Open():
+ if node.nodeType == node.ELEMENT_NODE:
+ data = wx.CustomDataObject('XRCED_elem')
+ s = node.toxml(encoding=expat.native_encoding)
+ # Replace by a pair
+ if implicit: s = [s, implicit.toxml(encoding=expat.native_encoding)]
+ else:
+ # Non-element nodes are normally comments
+ data = wx.CustomDataObject('XRCED_node')
+ s = node.data
+ data.SetData(cPickle.dumps(s))
+ wx.TheClipboard.SetData(data)
+ wx.TheClipboard.Close()
+ else:
+ wx.MessageBox("Unable to open the clipboard", "Error")
+
+ def checkCompatibility(self, comp):
+ '''Check parent/child compatibility.'''
+ if self.createSibling: container = self.container
+ else: container = self.comp
+ if not container.canHaveChild(comp):
+ wx.LogError('Incompatible parent/child: parent is %s, child is %s!' %
+ (container.klass, comp.klass))
+ return False
+ return True
+
+ def paste(self):
+ success = success_node = False
+ if wx.TheClipboard.IsOpened() or wx.TheClipboard.Open():
+ try:
+ data = wx.CustomDataObject('XRCED_elem')
+ if wx.TheClipboard.IsSupported(data.GetFormat()):
+ try:
+ success = wx.TheClipboard.GetData(data)
+ except:
+ # there is a problem if XRCED_node is in clipboard
+ # but previous SetData was for XRCED
+ pass
+ if not success: # try other format
+ data = wx.CustomDataObject('XRCED_node')
+ if wx.TheClipboard.IsSupported(data.GetFormat()):
+ success_node = wx.TheClipboard.GetData(data)
+ finally:
+ wx.TheClipboard.Close()
+
+ if not success and not success_node:
+ wx.MessageBox(
+ "There is no data in the clipboard in the required format",
+ "Error")
+ return
+
+ # XML representation of element or node value string
+ data = cPickle.loads(data.GetData())
+ implicit = None
+ if success:
+ if type(data) is list:
+ node = Model.parseString(data[0])
+ implicit = Model.parseString(data[1])
+ else:
+ node = Model.parseString(data)
+ else:
+ node = Model.dom.createComment(data)
+ comp = Manager.getNodeComp(node)
+
+ # Check compatibility
+ if not self.checkCompatibility(comp):
+ node.unlink()
+ return
+
+ item = view.tree.GetSelection()
+ if item and not self.applied:
+ self.update(item)
+
+ item = self.create(comp, node)
+ if implicit: # copy parameters for implicit node if possible
+ parentNode = view.tree.GetPyData(view.tree.GetItemParent(item))
+ parentComp = Manager.getNodeComp(parentNode)
+ if parentComp.requireImplicit(node) and \
+ parentComp.implicitKlass == implicit.getAttribute('class'):
+ parentComp.copyImplicitAttributes(implicit, node.parentNode, parentComp)
+ implicit.unlink()
+
+ # Add children
+ for n in filter(is_object, node.childNodes):
+ view.tree.AddNode(item, comp.getTreeNode(n))
+ self.setModified()
+ return item
+
+ def moveUp(self):
+ parentItem = view.tree.GetItemParent(self.item)
+ treeNode = view.tree.GetPyData(self.item)
+ node = self.container.getTreeOrImplicitNode(treeNode)
+ parent = node.parentNode
+ prevNode = node.previousSibling
+ while not is_object(prevNode):
+ prevNode = prevNode.previousSibling
+ parent.removeChild(node)
+ parent.insertBefore(node, prevNode)
+ index = view.tree.ItemFullIndex(self.item)
+ self.flushSubtree(parentItem, parent)
+ index[-1] -= 1
+ self.item = view.tree.ItemAtFullIndex(index)
+ self.setModified()
+ view.tree.SelectItem(self.item)
+
+ def moveDown(self):
+ parentItem = view.tree.GetItemParent(self.item)
+ treeNode = view.tree.GetPyData(self.item)
+ node = self.container.getTreeOrImplicitNode(treeNode)
+ parent = node.parentNode
+ nextNode = node.nextSibling
+ while not is_object(nextNode):
+ nextNode = nextNode.nextSibling
+ nextNode = nextNode.nextSibling
+ while nextNode and not is_object(nextNode):
+ nextNode = nextNode.nextSibling
+ parent.removeChild(node)
+ parent.insertBefore(node, nextNode)
+ index = view.tree.ItemFullIndex(self.item)
+ self.flushSubtree(parentItem, parent)
+ index[-1] += 1
+ self.item = view.tree.ItemAtFullIndex(index)
+ self.setModified()
+ view.tree.SelectItem(self.item)
+
+ def moveLeft(self):
+ parentItem = view.tree.GetItemParent(self.item)
+ grandParentItem = view.tree.GetItemParent(parentItem)
+ parent = view.tree.GetPyData(parentItem)
+ grandParent = view.tree.GetPyData(grandParentItem)
+ if grandParent is Model.mainNode:
+ grandParentComp = Manager.rootComponent
+ else:
+ grandParentComp = Manager.getNodeComp(grandParent)
+ if not grandParentComp.canHaveChild(self.comp):
+ wx.LogError('Incompatible parent/child: parent is %s, child is %s!' %
+ (grandParentComp.klass, self.comp.klass))
+ return
+
+ node = view.tree.GetPyData(self.item)
+ nextItem = view.tree.GetNextSibling(parentItem)
+ self.container.removeChild(parent, node)
+ if nextItem:
+ nextNode = view.tree.GetPyData(nextItem)
+ grandParentComp.insertBefore(grandParent, node, nextNode)
+ else:
+ grandParentComp.appendChild(grandParent, node)
+ index = view.tree.ItemFullIndex(self.item)
+ self.flushSubtree(grandParentItem, grandParent)
+ index.pop()
+ index[-1] += 1
+ self.item = view.tree.ItemAtFullIndex(index)
+ self.setModified()
+ view.tree.SelectItem(self.item)
+
+ def moveRight(self):
+ parentItem = view.tree.GetItemParent(self.item)
+ parent = view.tree.GetPyData(parentItem)
+ newParent = view.tree.GetPyData(view.tree.GetPrevSibling(self.item))
+ newParentComp = Manager.getNodeComp(newParent)
+ if not newParentComp.canHaveChild(self.comp):
+ wx.LogError('Incompatible parent/child: parent is %s, child is %s!' %
+ (newParentComp.klass, self.comp.klass))
+ return
+
+ node = view.tree.GetPyData(self.item)
+ self.container.removeChild(parent, node)
+ newParentComp.appendChild(newParent, node)
+ index = view.tree.ItemFullIndex(self.item)
+ n = view.tree.GetChildrenCount(view.tree.GetPrevSibling(self.item))
+ self.flushSubtree(parentItem, parent)
+ index[-1] -= 1
+ index.append(n)
+ self.item = view.tree.ItemAtFullIndex(index)
+ self.setModified()
+ view.tree.SelectItem(self.item)
+
+ def createLocalConf(self, path):
+ name = os.path.splitext(path)[0]
+ name += '.xcfg'
+ return wx.FileConfig(localFilename=name)
+
+ def createTestWin(self, item):
+ TRACE('createTestWin')
+ # Create a window with this resource
+ node = view.tree.GetPyData(item)
+ # Execute "pragma" comment node
+ if node.nodeType == node.COMMENT_NODE:
+ if node.data and node.data[0] == '%' and g.conf.allowExec != 'no':
+ say = wx.NO
+ if g.conf.allowExec == 'ask' and Model.allowExec is None:
+ say = wx.MessageBox('Execute comment directive?', 'Warning',
+ wx.ICON_EXCLAMATION | wx.YES_NO)
+ if g.conf.allowExec == 'yes' or say == wx.YES:
+ code = node.data[1:] # skip '%'
+ view.tree.ExecCode(code)
+ return
+ # Close old window, remember where it was
+ comp = Manager.getNodeComp(node)
+ # Use parent object if the current one does not support test view
+ testWinItem = item
+ while not comp.isTestable:
+ testWinItem = view.tree.GetItemParent(testWinItem)
+ node = view.tree.GetPyData(testWinItem)
+ comp = Manager.getNodeComp(node)
+ # Create memory XML file
+ elem = node.cloneNode(True)
+ if not node.hasAttribute('name'):
+ name = 'noname'
+ else:
+ name = node.getAttribute('name')
+ elem.setAttribute('name', STD_NAME)
+ Model.setTestElem(elem)
+ Model.saveTestMemoryFile()
+ xmlFlags = 0
+ if not g.conf.useSubclassing:
+ xmlFlags |= xrc.XRC_NO_SUBCLASSING
+ # Use translations if encoding is not specified
+ if not Model.dom.encoding:
+ xmlFlags |= xrc.XRC_USE_LOCALE
+ res = xrc.EmptyXmlResource(xmlFlags)
+ xrc.XmlResource.Set(res) # set as global
+ # Init other handlers
+ Manager.addXmlHandlers(res)
+ Manager.preload(res)
+ # Same module list
+ res.Load('memory:test.xrc')
+ testWin = view.testWin
+ try:
+ try:
+ frame, object = comp.makeTestWin(res, name)
+ if not object: # skip the rest
+ raise EOFError
+ # Reset previous tree item and locate tool
+ if testWin.item:
+ view.tree.SetItemBold(testWin.item, False)
+ testWin.SetView(frame, object, testWinItem)
+ testWin.Show()
+ view.tree.SetItemBold(testWinItem, True)
+ # For reused frame, object is not positioned immediately
+ wx.CallAfter(self.highlight, item)
+ except EOFError:
+ pass
+ except TestWinError:
+ wx.LogError('Test window could not be created for %s' % node.getAttribute('class'))
+ logger.exception('error creating test view')
+ except:
+ wx.LogError('Error creating test view')
+ logger.exception('error creating test view')
+ if get_debug(): raise
+ finally:
+ # Cleanup
+ res.Unload(TEST_FILE)
+ xrc.XmlResource.Set(None)
+ wx.MemoryFSHandler.RemoveFile(TEST_FILE)
+
+ def closeTestWin(self):
+ TRACE('closeTestWin')
+ if not view.testWin.object: return
+ view.tree.SetItemBold(view.testWin.item, False)
+ view.tree.Refresh()
+ view.frame.tb.ToggleTool(view.frame.ID_TOOL_LOCATE, False)
+ if view.frame.miniFrame:
+ view.frame.miniFrame.tb.ToggleTool(view.frame.ID_TOOL_LOCATE, False)
+ view.testWin.Destroy()
+
+ def refreshTestWin(self):
+ '''Refresh test window after some change.'''
+ TRACE('refreshTestWin')
+ if not view.testWin.IsDirty(): return
+ if not self.applied: self.update(self.item)
+ # Dumb refresh
+ self.createTestWin(view.testWin.item)
+ self.highlight(self.item)
+ if view.frame.miniFrame and view.frame.miniFrame.IsShown():
+ view.frame.miniFrame.Raise()
+ else:
+ view.frame.Raise()
+
+ def showXML(self):
+ '''Show some source.'''
+ node = view.tree.GetPyData(self.item)
+ dom = MyDocument()
+ node = dom.appendChild(node.cloneNode(True))
+ Model.indent(dom, node)
+ text = node.toxml()#Model.dom.encoding)
+ dom.unlink()
+ lines = text.split('\n')
+ maxLen = max(map(len, lines))
+ w = max(40, min(80, maxLen))
+ h = max(20, min(40, len(lines)))
+ dlg = view.ScrolledMessageDialog(view.frame, text, 'XML Source',
+ textSize=(w,h), centered=False)
+ dlg.Bind(wx.EVT_CLOSE, lambda evt: dlg.Destroy())
+ dlg.Bind(wx.EVT_BUTTON, lambda evt: dlg.Destroy(), id=wx.ID_OK)
+ dlg.Show()
+
+ def generatePython(self, dataFile, pypath, embed, genGettext):
+ try:
+ from wx.tools import pywxrc
+ rescomp = pywxrc.XmlResourceCompiler()
+ rescomp.MakePythonModule([dataFile], pypath, embed, genGettext,
+ assignVariables=False)
+ except:
+ logger.exception('error generating python code')
+ wx.LogError('Error generating python code : %s' % pypath)
+ raise
+
+# Singleton class
+Presenter = g.Presenter = _Presenter()
+
+undo.Presenter = Presenter
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/tools.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/tools.py
new file mode 100644
index 0000000..b48e6d6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/tools.py
@@ -0,0 +1,230 @@
+# Name: tools.py
+# Purpose: XRC editor, toolbar
+# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
+# Created: 19.03.2003
+# RCS-ID: $Id: tools.py 67456 2011-04-13 18:02:41Z RD $
+
+from globals import *
+from component import Manager, DEFAULT_POS
+import view
+import images
+import wx.lib.foldpanelbar as fpb
+
+#if wx.Platform in ['__WXMAC__', '__WXMSW__']:
+ # Mac and Win are better off with generic
+import wx.lib.buttons
+BitmapButton = wx.lib.buttons.GenBitmapButton
+#else:
+# wx.BitmapButton.SetBezelWidth = lambda self, w: None
+
+class ToolPanel(wx.PyPanel):
+ '''Manages a Listbook with tool bitmap buttons.'''
+ defaultPos = wx.GBPosition(*DEFAULT_POS)
+ def __init__(self, parent):
+ if wx.Platform == '__WXGTK__':
+ wx.PyPanel.__init__(self, parent, -1,
+ style=wx.RAISED_BORDER|wx.WANTS_CHARS)
+ else:
+ wx.PyPanel.__init__(self, parent, -1, style=wx.WANTS_CHARS)
+ self.bg = wx.Colour(115, 180, 215)
+ # Top sizer
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ # Use toolbook or foldpanelbar depending of preferences
+ if g.conf.toolPanelType == 'TB':
+ self.tp = wx.Toolbook(self, -1, style=wx.BK_TOP)
+ sizer.Add(self.tp, 1, wx.EXPAND)
+ # Image list
+ thumbSize = g.conf.toolThumbSize
+ il = wx.ImageList(thumbSize, thumbSize, True)
+ # Default Id 0
+ il.Add(images.ToolPanel_Default.GetImage().Scale(thumbSize, thumbSize).ConvertToBitmap())
+ self.il = il
+ self.tp.AssignImageList(il)
+ elif g.conf.toolPanelType == 'FPB':
+ self.tp = fpb.FoldPanelBar(self, -1, wx.DefaultPosition, wx.DefaultSize,
+ agwStyle=fpb.FPB_VERTICAL)
+ sizer.Add(self.tp, 1, wx.EXPAND)
+ self.panels = []
+ for name in Manager.panelNames:
+ panelData = Manager.getPanelData(name)
+ if not panelData: continue
+ try:
+ im = Manager.panelImages[name]
+ imageId = il.Add(im.Scale(thumbSize, thumbSize).ConvertToBitmap())
+ except:
+ imageId = 0
+ panel = self.AddPanel(name)
+ self.panels.append(panel)
+ for pos,span,comp,bmp in panelData:
+ self.AddButton(panel, pos, span, comp.id, bmp, comp.klass)
+ panel.Fit()
+ if g.conf.toolPanelType == 'TB':
+ self.tp.AddPage(panel, '', imageId=imageId)
+ else:
+ p = self.tp.AddFoldPanel(name, collapsed=False)
+ p.SetBackgroundColour(self.bg)
+ panel.Reparent(p)
+ p.AddWindow(panel, fpb.FPB_ALIGN_WIDTH)
+ self.tp.Fit()
+
+ self.SetSizer(sizer)
+ # Allow to be resized in horizontal direction only
+ # Events
+# wx.EVT_KEY_DOWN(self, self.OnKeyDown)
+# wx.EVT_KEY_UP(self, self.OnKeyUp)
+ self.drag = None
+
+ def DoGetBestSize(self):
+ # Do our own DoGetBestSize because the FoldPanelBar doesn't
+ h = w = 0
+ for p in self.panels:
+ ems = p.GetEffectiveMinSize()
+ w = max(w, ems.width)
+ h = max(h, ems.height)
+ h += 64
+ return wx.Size(w,h)
+
+ def AddButton(self, panel, pos, span, id, bmp, text):
+ button = BitmapButton(panel, id, bmp,
+ style=wx.NO_BORDER)# | wx.WANTS_CHARS)
+ button.SetBezelWidth(0)
+# wx.EVT_KEY_DOWN(button, self.OnKeyDown)
+# wx.EVT_KEY_UP(button, self.OnKeyUp)
+ button.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDownOnButton)
+ button.Bind(wx.EVT_MOTION, self.OnMotionOnButton)
+ button.Bind(wx.EVT_BUTTON, self.OnButton)
+ button.SetToolTipString(text)
+ # Look for an available place if not specified
+ r0,c0 = 0,0
+ if pos != self.defaultPos:
+ if panel.sizer.CheckForIntersectionPos(pos, span):
+ r0,c0 = pos # start from pos
+ pos = self.defaultPos # reset to default
+ if pos == self.defaultPos:
+ # Find the smallest position we can insert into
+ try:
+ for r in range(r0, panel.size.rowspan):
+ for c in range(c0, panel.size.colspan):
+ if not panel.sizer.CheckForIntersectionPos((r,c), span):
+ pos = (r,c)
+ raise StopIteration
+ except StopIteration:
+ pass
+ if pos == self.defaultPos: # insert new col/row
+ if panel.size.colspan + span[0] <= panel.size.rowspan + span[1]:
+ pos = (0,panel.size.colspan)
+ else:
+ pos = (panel.size.rowspan,0)
+ assert pos[0] >= 0 and pos[1] >= 0, 'invalid position'
+ panel.sizer.Add(button, pos, span, wx.ALIGN_CENTRE)
+ panel.controls[id] = button
+ panel.size.rowspan = max(panel.size.rowspan, pos[0]+span[0])
+ panel.size.colspan = max(panel.size.colspan, pos[1]+span[1])
+
+ def AddPanel(self, name):
+ # Each group is inside box
+ panel = wx.Panel(self.tp)
+ panel.SetBackgroundColour(self.bg)
+ panel.name = name
+ panel.controls = {}
+ panel.size = wx.GBSpan(1, 1) # current size
+ topSizer = wx.BoxSizer()
+ panel.sizer = wx.GridBagSizer(0, 0)
+ panel.sizer.SetEmptyCellSize((24, 24))
+ topSizer.Add(panel.sizer, 1, wx.EXPAND | wx.ALL, 5)
+ panel.SetSizer(topSizer)
+ return panel
+
+ # Mouse events for DnD and append/insert mode
+ def OnLeftDownOnButton(self, evt):
+ self.posDown = evt.GetPosition()
+ self.btnDown = evt.GetEventObject()
+ forceSibling = evt.ControlDown()
+ forceInsert = evt.ShiftDown()
+ g.Presenter.updateCreateState(forceSibling, forceInsert)
+ evt.Skip()
+
+ def OnButton(self, evt):
+ if not self.drag: evt.Skip()
+ self.drag = False
+ if view.frame.miniFrame:
+ if not g.useAUI and not g.conf.embedPanel:
+ view.frame.miniFrame.Raise()
+ else:
+ view.frame.Raise()
+
+ def OnMotionOnButton(self, evt):
+ # Detect dragging
+ if evt.Dragging() and evt.LeftIsDown():
+ d = evt.GetPosition() - self.posDown
+ if max(abs(d[0]), abs(d[1])) >= 5:
+ if self.btnDown.HasCapture():
+ # Generate up event to release mouse
+ evt = wx.MouseEvent(wx.EVT_LEFT_UP.typeId)
+ #evt.SetId(self.btnDown.GetId())
+ # Set flag to prevent normal button operation
+ self.drag = True
+ self.btnDown.ProcessEvent(evt)
+ self.StartDrag()
+ evt.Skip()
+
+ def StartDrag(self):
+ bm = self.btnDown.GetBitmapLabel()
+ # wxGTK requires wxIcon cursor, wxWIN and wxMAC require wxCursor
+ if wx.Platform == '__WXGTK__':
+ icon = wx.EmptyIcon()
+ icon.CopyFromBitmap(bm)
+ dragSource = wx.DropSource(self, icon)
+ else:
+ curs = wx.CursorFromImage(wx.ImageFromBitmap(bm))
+ dragSource = wx.DropSource(self, curs)
+ do = MyDataObject(str(self.btnDown.GetId()))
+ dragSource.SetData(do)
+ view.frame.SetStatusText('Release the mouse button over the test window')
+ dragSource.DoDragDrop()
+ view.testWin.RemoveHighlightDT()
+ view.testWin.EmptyTrash()
+
+ # Process key events
+ def OnKeyDown(self, evt):
+ print evt.GetEventObject(), evt.GetKeyCode()
+ evt.Skip()
+ return
+ if evt.GetKeyCode() == wx.WXK_CONTROL:
+ g.tree.ctrl = True
+ elif evt.GetKeyCode() == wx.WXK_SHIFT:
+ g.tree.shift = True
+ self.UpdateIfNeeded()
+ evt.Skip()
+
+ def OnKeyUp(self, evt):
+ if evt.GetKeyCode() == wx.WXK_CONTROL:
+ g.tree.ctrl = False
+ elif evt.GetKeyCode() == wx.WXK_SHIFT:
+ g.tree.shift = False
+ self.UpdateIfNeeded()
+ evt.Skip()
+
+ def OnMouse(self, evt):
+ # Update control and shift states
+ g.tree.ctrl = evt.ControlDown()
+ g.tree.shift = evt.ShiftDown()
+ self.UpdateIfNeeded()
+ evt.Skip()
+
+ # Update UI after key presses, if necessary
+ def UpdateIfNeeded(self):
+ tree = g.tree
+ if self.ctrl != tree.ctrl or self.shift != tree.shift:
+ # Enabling is needed only for ctrl
+ if self.ctrl != tree.ctrl: self.UpdateUI()
+ self.ctrl = tree.ctrl
+ self.shift = tree.shift
+ if tree.ctrl:
+ status = 'SBL'
+ elif tree.shift:
+ status = 'INS'
+ else:
+ status = ''
+ g.frame.SetStatusText(status, 1)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/undo.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/undo.py
new file mode 100644
index 0000000..9b78e33
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/undo.py
@@ -0,0 +1,201 @@
+# Name: undo.py
+# Purpose: XRC editor, undo/redo module
+# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
+# Created: 01.12.2002
+# RCS-ID: $Id: undo.py 54812 2008-07-29 13:39:00Z ROL $
+
+from globals import *
+import view
+from component import Manager
+from model import Model
+
+undo_depth = 10 # max number of undo remembered
+
+# Undo/redo classes
+class UndoManager:
+ # Undo/redo stacks
+ undo = []
+ redo = []
+ def RegisterUndo(self, undoObj):
+ TRACE('RegisterUndo: %s', undoObj.label)
+ self.undo.append(undoObj)
+ while len(self.undo) > undo_depth: self.undo.pop(0)
+ map(Undo.destroy, self.redo)
+ self.redo = []
+ self.UpdateToolHelp()
+ def GetUndoLabel(self):
+ return self.undo[-1].label
+ def GetRedoLabel(self):
+ return self.redo[-1].label
+ def Undo(self):
+ undoObj = self.undo.pop()
+ undoObj.undo()
+ self.redo.append(undoObj)
+ view.frame.SetStatusText('Undone')
+ Presenter.setModified()
+ self.UpdateToolHelp()
+ def Redo(self):
+ undoObj = self.redo.pop()
+ undoObj.redo()
+ self.undo.append(undoObj)
+ view.frame.SetStatusText('Redone')
+ Presenter.setModified()
+ self.UpdateToolHelp()
+ def Clear(self):
+ map(Undo.destroy, self.undo)
+ self.undo = []
+ map(Undo.destroy, self.redo)
+ self.redo = []
+ self.UpdateToolHelp()
+ def CanUndo(self):
+ return bool(self.undo)
+ def CanRedo(self):
+ return bool(self.redo)
+ def UpdateToolHelp(self):
+ if g.undoMan.CanUndo():
+ msg = 'Undo ' + self.GetUndoLabel()
+ view.frame.tb.SetToolShortHelp(wx.ID_UNDO, msg)
+ view.frame.tb.SetToolLongHelp(wx.ID_UNDO, msg)
+ if g.undoMan.CanRedo():
+ msg = 'Redo ' + self.GetRedoLabel()
+ view.frame.tb.SetToolShortHelp(wx.ID_REDO, msg)
+ view.frame.tb.SetToolLongHelp(wx.ID_REDO, msg)
+
+class Undo:
+ '''ABC for Undo*.'''
+ def redo(self): # usually redo is same as undo
+ self.undo()
+ def destroy(self):
+ pass
+
+class UndoCutDelete(Undo):
+ label = 'cut/delete'
+ def __init__(self, itemIndex, state, node):
+ self.itemIndex = itemIndex
+ self.state = state
+ self.node = node
+ def destroy(self):
+ if self.node: self.node.unlink()
+ self.node = None
+ def undo(self):
+ Presenter.unselect()
+ # Updating DOM. Find parent node first
+ parentItem = view.tree.ItemAtFullIndex(self.itemIndex[:-1])
+ parentNode = view.tree.GetPyData(parentItem)
+ parentComp = Manager.getNodeComp(parentNode)
+ nextItem = view.tree.ItemAtFullIndex(self.itemIndex)
+ if nextItem:
+ nextNode = parentComp.getTreeOrImplicitNode(view.tree.GetPyData(nextItem))
+ else:
+ nextNode = None
+ # Insert before next
+ parentNode.insertBefore(self.node, nextNode)
+ # Remember test window item
+ if view.testWin.item is not None:
+ testItemIndex = view.tree.ItemFullIndex(view.testWin.item)
+ # Update tree and presenter
+ view.tree.FlushSubtree(parentItem, parentNode)
+ view.tree.SetFullState(self.state)
+ # Restore test window item
+ if view.testWin.item is not None:
+ view.testWin.item = view.tree.ItemAtFullIndex(testItemIndex)
+ item = view.tree.ItemAtFullIndex(self.itemIndex)
+ view.tree.EnsureVisible(item)
+ # This will generate events
+ view.tree.SelectItem(item)
+ def redo(self):
+ item = view.tree.ItemAtFullIndex(self.itemIndex)
+ Presenter.setData(item)
+ self.node = Presenter.delete(item)
+
+# Undoing paste/create is the opposite of cut/delete, so we can reuse
+# UndoCutDelete class swapping undo<->redo
+class UndoPasteCreate(UndoCutDelete):
+ label = 'paste/create'
+ # The ctor is different because node is not known initially
+ def __init__(self, itemIndex, state):
+ self.itemIndex = itemIndex # new item index
+ self.state = state # tree state
+ self.node = None
+ undo = UndoCutDelete.redo
+ redo = UndoCutDelete.undo
+
+class UndoReplace(Undo):
+ label = 'replace'
+ def __init__(self, itemIndex, comp, node):
+ self.itemIndex = itemIndex
+ self.comp = comp
+ self.node = node
+ def destroy(self):
+ if self.node: self.node.unlink()
+ self.node = None
+ def undo(self):
+ # Replace current node with old node
+ Presenter.unselect()
+ item = view.tree.ItemAtFullIndex(self.itemIndex)
+ Presenter.setData(item)
+ comp = self.comp
+ node = self.node
+ data = wx.TreeItemData(node)
+ parentItem = view.tree.GetItemParent(item)
+ parentNode = view.tree.GetPyData(parentItem)
+ self.node = view.tree.GetPyData(item)
+ self.comp = Presenter.comp
+ Presenter.container.replaceChild(parentNode, node, self.node)
+ # Replace tree item: insert new, remove old
+ label = comp.getTreeText(node)
+ imageId = comp.getTreeImageId(node)
+ item = view.tree.InsertItem(parentItem, item, label, imageId, data=data)
+ view.tree.Delete(view.tree.GetPrevSibling(item))
+ Presenter.item = item
+ # Add children
+ for n in filter(is_object, node.childNodes):
+ view.tree.AddNode(item, comp.getTreeNode(n))
+ view.tree.EnsureVisible(item)
+ # Update panel
+ view.tree.SelectItem(item)
+ Presenter.setModified()
+
+class UndoEdit(Undo):
+ '''Undo class for using in AttributePanel.'''
+ label = 'edit'
+ def __init__(self, item, page):
+ self.index = view.tree.ItemFullIndex(item)
+ self.page = page
+ panel = view.panel.nb.GetPage(page).panel
+ self.values = panel.GetValues()
+ def undo(self):
+ # Go back to the previous item
+ Presenter.unselect()
+ item = view.tree.ItemAtFullIndex(self.index)
+ Presenter.setData(item)
+ panel = view.panel.nb.GetPage(self.page).panel
+ values = panel.GetValues()
+ panel.SetValues(self.values)
+ Presenter.update(item)
+ self.values = values
+ view.tree.SelectItem(item)
+
+class UndoGlobal(Undo):
+ '''Undo class storing a copy of the complete tree. Can be used for
+ non-frequent operations to avoid programming special undo
+ classes.'''
+ label = 'global'
+ def __init__(self):
+ self.mainNode = Model.mainNode.cloneNode(True)
+ self.state = view.tree.GetFullState()
+ def destroy(self):
+ self.mainNode.unlink()
+ def undo(self):
+ # Exchange
+ Model.mainNode,self.mainNode = \
+ self.mainNode,Model.dom.replaceChild(self.mainNode, Model.mainNode)
+ # Replace testElem
+ Model.testElem = Model.mainNode.childNodes[0]
+ state = view.tree.GetFullState()
+ Presenter.flushSubtree()
+ view.tree.SetFullState(self.state)
+ self.state = state
+ def redo(self):
+ self.undo()
+ Presenter.unselect()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/view.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/view.py
new file mode 100644
index 0000000..27b885a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/view.py
@@ -0,0 +1,578 @@
+# Name: view.py
+# Purpose: View classes
+# Author: Roman Rolinsky <rolinsky@femagsoft.com>
+# Created: 07.06.2007
+# RCS-ID: $Id: view.py 64107 2010-04-22 14:05:36Z ROL $
+
+import os
+from XMLTree import XMLTree
+from XMLTreeMenu import XMLTreeMenu
+from AttributePanel import Panel, AttributePanel
+from TestWin import TestWindow
+from tools import *
+import images
+if wx.Platform == '__WXMAC__':
+ # Substitute higher-res icons for Mac
+ import images_32x32
+ images.__dict__.update(images_32x32.__dict__)
+import wx.aui
+import wx.html
+
+def create_view():
+ '''
+ Create all necessary view objects. Some of them are set as module
+ global variables for convenience.
+ '''
+
+ # Load resources
+ res = xrc.EmptyXmlResource()
+ res.Load(os.path.join(g.basePath, 'xrced.xrc'))
+ g.res = res
+
+ global frame
+ frame = Frame(g.conf.pos, g.conf.size)
+
+ global toolFrame
+ toolFrame = create_tools()
+
+ global testWin
+ testWin = TestWindow()
+
+def create_tools():
+ if g.useAUI:
+ g.toolPanel = ToolPanel(frame)
+ frame.mgr.AddPane(g.toolPanel, wx.aui.AuiPaneInfo().Name('tools').Caption("Tools").
+ MinSize(g.toolPanel.GetBestSize()).
+ Right().CloseButton(True).MaximizeButton(False))
+ frame.mgr.Update()
+ if g.conf.HasEntry('perspective'):
+ frame.mgr.LoadPerspective(g.conf.Read('perspective'))
+ return None
+ else:
+ # Tool panel on a MiniFrame
+ toolFrame = wx.MiniFrame(frame, -1, 'Components',
+ g.conf.toolPanelPos,
+ style=wx.CAPTION|wx.CLOSE_BOX|wx.RESIZE_BORDER)
+ # This causes hiding on KDE
+ # |wx.FRAME_TOOL_WINDOW)
+ if wx.Platform != '__WXMAC__':
+ toolFrame.SetIcons(frame.icns)
+ g.toolPanel = toolFrame.panel = ToolPanel(toolFrame)
+ if toolFrame.panel.panels:
+ toolFrame.SetTitle(toolFrame.panel.panels[0].name)
+ toolFrame.Fit()
+ minSize = toolFrame.GetSize()
+ if minSize[0] < 320: minSize[0] = 320
+ toolFrame.SetMinSize(minSize)
+ #toolFrame.SetPosition(g.conf.toolPanelPos)
+ toolFrame.SetSize(g.conf.toolPanelSize)
+ return toolFrame
+
+#############################################################################
+
+class Frame(wx.Frame):
+ def __init__(self, pos, size):
+ wx.Frame.__init__(self, None, -1, 'XRCed', pos, size)
+ bar = self.CreateStatusBar(2)
+ bar.SetStatusWidths([-1, 40])
+ if wx.Platform != '__WXMAC__':
+ self.icns = wx.IconBundleFromIcon(images.Icon.GetIcon())
+ self.SetIcons(self.icns)
+
+ self.InitMenuBar()
+
+ self.ID_TOOL_PASTE = wx.NewId()
+ self.ID_TOOL_LOCATE = wx.NewId()
+
+ # Init HTML help
+ wx.FileSystem.AddHandler(wx.ZipFSHandler())
+ self.htmlCtrl = wx.html.HtmlHelpController()
+ programPath = os.path.dirname(__file__)
+ if not (self.htmlCtrl.AddBook(os.path.join(programPath, "xrced.htb"))) :
+ print >> sys.stderr, "Cannot load help file \"xrced.htb\""
+ self.GetMenuBar().Enable(wx.ID_HELP_CONTENTS, False)
+
+ # Create toolbar
+ self.tb = tb = wx.ToolBar(self, -1, style=wx.TB_FLAT | wx.TB_NODIVIDER)
+ # Use bigger icon size on Mac
+ if wx.Platform == '__WXMAC__':
+ tb.SetToolBitmapSize((32,32))
+ elif wx.Platform == '__WXMSW__':
+ tb.SetToolBitmapSize((22,22))
+
+ self.InitToolBar(g.useAUI or g.conf.embedPanel) # add tools
+
+ if g.useAUI:
+ self.mgr = wx.aui.AuiManager()
+ self.mgr.SetManagedWindow(self)
+ parent = self
+ else:
+ splitter = wx.SplitterWindow(self, -1, style=wx.SP_3DSASH)
+ self.splitter = splitter
+ splitter.SetMinimumPaneSize(100)
+ parent = splitter
+
+ # always use the native toolbar on Mac, it looks too sucky otherwise
+ if g.useAUI and wx.Platform != '__WXMAC__':
+ self.mgr.AddPane(tb, wx.aui.AuiPaneInfo().
+ Name("tb").Caption("Toolbar").
+ ToolbarPane().Top().LeftDockable(False).RightDockable(False))
+ else:
+ self.SetToolBar(tb)
+
+
+ global tree
+ tree = XMLTree(parent)
+
+ global panel
+ if g.useAUI:
+ self.mgr.AddPane(tree, wx.aui.AuiPaneInfo().
+ Name("tree").Caption("XML Tree").
+ CenterPane())
+
+ panel = Panel(self)
+ self.mgr.AddPane(panel, wx.aui.AuiPaneInfo().
+ Name("attrpanel").Caption("Attributes").
+ MinSize(panel.GetBestSize()).
+ Right().CloseButton(True).MaximizeButton(False))
+
+ self.miniFrame = None
+ else:
+
+ # Miniframe for split mode
+ self.miniFrame = mf = wx.MiniFrame(self, -1, 'Attributes',
+ g.conf.panelPos, g.conf.panelSize,
+ style=wx.CAPTION|wx.RESIZE_BORDER)
+ # This causes hiding on KDE
+ # |wx.FRAME_TOOL_WINDOW)
+ if wx.Platform != '__WXMAC__':
+ mf.SetIcons(self.icns)
+ mf.tb = mf.CreateToolBar(wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT)
+
+ # Use bigger icon size on Mac
+ if wx.Platform == '__WXMAC__':
+ mf.tb.SetToolBitmapSize((32,32))
+ elif wx.Platform == '__WXMSW__':
+ mf.tb.SetToolBitmapSize((22,22))
+ self.InitMiniFrameToolBar(mf.tb)
+
+ mfSizer = wx.BoxSizer()
+ mf.SetMinSize((100,100))
+ mf.SetSizer(mfSizer)
+ if wx.Platform == '__WXMAC__': # mac don't respect pos and size exactly
+ mf.SetPosition(g.conf.panelPos)
+ mf.SetSize(g.conf.panelSize)
+
+ # Create attribute panel
+ if g.conf.embedPanel:
+ panel = Panel(splitter)
+ # Set plitter windows
+ splitter.SplitVertically(tree, panel, g.conf.sashPos)
+ else:
+ panel = Panel(mf)
+ mfSizer.Add(panel, 1, wx.EXPAND)
+ splitter.Initialize(tree)
+
+ if wx.Platform == '__WXMAC__':
+ self.SetClientSize(size)
+
+ def Clear(self):
+ pass
+
+ def InitMenuBar(self):
+ # Make menus
+ menuBar = wx.MenuBar()
+
+ menu = wx.Menu() # File menu
+ menu.Append(wx.ID_NEW, '&New\tCtrl-N', 'New file')
+ menu.AppendSeparator()
+ menu.Append(wx.ID_OPEN, '&Open...\tCtrl-O', 'Open XRC file')
+
+ self.recentMenu = wx.Menu()
+ g.fileHistory.UseMenu(self.recentMenu)
+ g.fileHistory.AddFilesToMenu()
+
+ menu.AppendMenu(-1, 'Open &Recent', self.recentMenu, 'Open a recent file')
+
+ menu.AppendSeparator()
+ menu.Append(wx.ID_SAVE, '&Save\tCtrl-S', 'Save XRC file')
+ menu.Append(wx.ID_SAVEAS, 'Save &As...', 'Save XRC file under different name')
+ self.ID_GENERATE_PYTHON = wx.NewId()
+ menu.Append(self.ID_GENERATE_PYTHON, '&Generate Python...',
+ 'Generate a Python module that uses this XRC')
+ menu.AppendSeparator()
+ menu.Append(wx.ID_PREFERENCES, 'Preferences...', 'Change XRCed settings')
+ menu.AppendSeparator()
+ menu.Append(wx.ID_EXIT, '&Quit\tCtrl-Q', 'Exit application')
+
+ menuBar.Append(menu, '&File')
+
+ menu = wx.Menu() # Edit menu
+ menu.Append(wx.ID_UNDO, '&Undo\tCtrl-Z', 'Undo')
+ menu.Append(wx.ID_REDO, '&Redo\tCtrl-Y', 'Redo')
+ menu.AppendSeparator()
+ menu.Append(wx.ID_CUT, 'Cut\tCtrl-X', 'Cut to the clipboard')
+ menu.Append(wx.ID_COPY, '&Copy\tCtrl-C', 'Copy to the clipboard')
+ menu.Append(ID.PASTE, '&Paste\tCtrl-V', 'Paste from the clipboard')
+ menu.Append(ID.PASTE_SIBLING, '&Paste Sibling\tAlt-Ctrl-V',
+ 'Paste clipboard as a sibling')
+ menu.Append(wx.ID_DELETE, '&Delete\tCtrl-D', 'Delete object')
+ menu.AppendSeparator()
+ self.ID_UNSELECT = wx.NewId()
+ menu.Append(self.ID_UNSELECT, '&Unselect All', 'Clear tree selection')
+ menu.Append(ID.COLLAPSE_ALL, '&Collapse All', 'Collapse tree')
+ menu.AppendSeparator()
+ menu.Append(wx.ID_FIND, '&Find\tCtrl-F', 'Find a named control')
+ self.ID_FINDAGAIN = wx.NewId()
+ menu.Append(self.ID_FINDAGAIN, 'Find A&gain\tCtrl-G', 'Repeat last search')
+ self.ART_LOCATE = 'ART_LOCATE'
+ self.ID_LOCATE = wx.NewId()
+ menu.Append(self.ID_LOCATE, '&Locate\tCtrl-L', 'Locate control in test window and select it')
+
+ menuBar.Append(menu, '&Edit')
+
+ menu = wx.Menu() # View menu
+ self.ID_EMBED_PANEL = wx.NewId()
+ menu.Append(self.ID_EMBED_PANEL, '&Embed Panel',
+ 'Toggle embedding properties panel in the main window', True)
+ menu.Check(self.ID_EMBED_PANEL, g.conf.embedPanel)
+ self.ID_SHOW_TOOLS = wx.NewId()
+ menu.Append(self.ID_SHOW_TOOLS, 'Show &Components', 'Show components')
+ menu.AppendSeparator()
+ self.ID_TEST = wx.NewId()
+ self.ART_TEST = 'ART_TEST'
+ menu.Append(self.ID_TEST, '&Test\tF5', 'Show test window')
+ self.ID_TEST_HIDE = wx.NewId()
+ menu.Append(self.ID_TEST_HIDE, '&End testing\tF6', 'Close test window')
+ self.ART_REFRESH = 'ART_REFRESH'
+ menu.Append(wx.ID_REFRESH, '&Refresh\tCtrl-R', 'Refresh test window')
+ self.ID_AUTO_REFRESH = wx.NewId()
+ self.ART_AUTO_REFRESH = 'ART_AUTO_REFRESH'
+ menu.Append(self.ID_AUTO_REFRESH, '&Auto-refresh\tAlt-A',
+ 'Toggle auto-refresh mode', True)
+ menu.Check(self.ID_AUTO_REFRESH, g.conf.autoRefresh)
+ menu.AppendSeparator()
+ self.ID_SHOW_XML = wx.NewId()
+ menu.Append(self.ID_SHOW_XML, 'Show &XML...',
+ 'Display XML source for the selected subtree')
+
+ menuBar.Append(menu, '&View')
+
+ menu = wx.Menu() # Move menu
+ self.ID_MOVEUP = wx.NewId()
+ self.ART_MOVEUP = 'ART_MOVEUP'
+ menu.Append(self.ID_MOVEUP, '&Up', 'Move before previous sibling')
+ self.ID_MOVEDOWN = wx.NewId()
+ self.ART_MOVEDOWN = 'ART_MOVEDOWN'
+ menu.Append(self.ID_MOVEDOWN, '&Down', 'Move after next sibling')
+ self.ID_MOVELEFT = wx.NewId()
+ self.ART_MOVELEFT = 'ART_MOVELEFT'
+ menu.Append(self.ID_MOVELEFT, '&Make sibling', 'Make sibling of parent')
+ self.ID_MOVERIGHT = wx.NewId()
+ self.ART_MOVERIGHT = 'ART_MOVERIGHT'
+ menu.Append(self.ID_MOVERIGHT, '&Make child', 'Make child of previous sibling')
+
+ menuBar.Append(menu, '&Move')
+
+ menu = wx.Menu() # Help menu
+ menu.Append(wx.ID_HELP_CONTENTS, '&Contents...', 'On-line help contents')
+ menu.Append(wx.ID_ABOUT, '&About...', 'About XCRed')
+ self.ID_README = wx.NewId()
+ menu.Append(self.ID_README, '&Readme...\tF1', 'View the README file')
+ if get_debug():
+ self.ID_DEBUG_CMD = wx.NewId()
+ menu.Append(self.ID_DEBUG_CMD, 'CMD', 'Python command line')
+
+ menuBar.Append(menu, '&Help')
+
+ self.menuBar = menuBar
+ self.SetMenuBar(menuBar)
+
+ def InitToolBar(self, long):
+ '''Initialize toolbar, long is boolean.'''
+ tb = self.tb
+ tb.ClearTools()
+ new_bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_TOOLBAR)
+ open_bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR)
+ save_bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR)
+ undo_bmp = wx.ArtProvider.GetBitmap(wx.ART_UNDO, wx.ART_TOOLBAR)
+ redo_bmp = wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_TOOLBAR)
+ cut_bmp = wx.ArtProvider.GetBitmap(wx.ART_CUT, wx.ART_TOOLBAR)
+ copy_bmp = wx.ArtProvider.GetBitmap(wx.ART_COPY, wx.ART_TOOLBAR)
+ paste_bmp= wx.ArtProvider.GetBitmap(wx.ART_PASTE, wx.ART_TOOLBAR)
+ if g.conf.TB_file:
+ tb.AddSimpleTool(wx.ID_NEW, new_bmp, 'New', 'New file')
+ tb.AddSimpleTool(wx.ID_OPEN, open_bmp, 'Open', 'Open file')
+ tb.AddSimpleTool(wx.ID_SAVE, save_bmp, 'Save', 'Save file')
+ tb.AddSeparator()
+ if g.conf.TB_undo:
+ tb.AddSimpleTool(wx.ID_UNDO, undo_bmp, 'Undo', 'Undo')
+ tb.AddSimpleTool(wx.ID_REDO, redo_bmp, 'Redo', 'Redo')
+ tb.AddSeparator()
+ if g.conf.TB_copy:
+ tb.AddSimpleTool(wx.ID_CUT, cut_bmp, 'Cut', 'Cut')
+ tb.AddSimpleTool(wx.ID_COPY, copy_bmp, 'Copy', 'Copy')
+ tb.AddSimpleTool(self.ID_TOOL_PASTE, paste_bmp, 'Paste', 'Paste')
+ tb.AddSeparator()
+ if g.conf.TB_move:
+ bmp = wx.ArtProvider.GetBitmap(self.ART_MOVEUP, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(self.ID_MOVEUP, bmp,
+ 'Up', 'Move before previous sibling')
+ bmp = wx.ArtProvider.GetBitmap(self.ART_MOVEDOWN, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(self.ID_MOVEDOWN, bmp,
+ 'Down', 'Move after next sibling')
+ bmp = wx.ArtProvider.GetBitmap(self.ART_MOVELEFT, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(self.ID_MOVELEFT, bmp,
+ 'Make Sibling', 'Make sibling of parent')
+ bmp = wx.ArtProvider.GetBitmap(self.ART_MOVERIGHT, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(self.ID_MOVERIGHT, bmp,
+ 'Make Child', 'Make child of previous sibling')
+ if long:
+ tb.AddSeparator()
+ bmp = wx.ArtProvider.GetBitmap(self.ART_LOCATE, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(self.ID_TOOL_LOCATE, bmp,
+ 'Locate', 'Locate control in test window and select it', True)
+ bmp = wx.ArtProvider.GetBitmap(self.ART_TEST, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(self.ID_TEST, bmp, 'Test', 'Test window')
+ bmp = wx.ArtProvider.GetBitmap(self.ART_REFRESH, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(wx.ID_REFRESH, bmp, 'Refresh', 'Refresh view')
+ bmp = wx.ArtProvider.GetBitmap(self.ART_AUTO_REFRESH, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(self.ID_AUTO_REFRESH, bmp,
+ 'Auto-refresh', 'Toggle auto-refresh mode', True)
+ tb.ToggleTool(self.ID_AUTO_REFRESH, g.conf.autoRefresh)
+ tb.Realize()
+ self.minWidth = tb.GetSize()[0] # minimal width is the size of toolbar
+
+ def InitMiniFrameToolBar(self, tb):
+ bmp = wx.ArtProvider.GetBitmap(self.ART_LOCATE, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(self.ID_TOOL_LOCATE, bmp,
+ 'Locate', 'Locate control in test window and select it', True)
+ bmp = wx.ArtProvider.GetBitmap(self.ART_TEST, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(self.ID_TEST, bmp, 'Test', 'Test window')
+ bmp = wx.ArtProvider.GetBitmap(self.ART_REFRESH, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(wx.ID_REFRESH, bmp, 'Refresh', 'Refresh view')
+ bmp = wx.ArtProvider.GetBitmap(self.ART_AUTO_REFRESH, wx.ART_TOOLBAR)
+ tb.AddSimpleTool(self.ID_AUTO_REFRESH, bmp,
+ 'Auto-refresh', 'Toggle auto-refresh mode', True)
+ tb.ToggleTool(self.ID_AUTO_REFRESH, g.conf.autoRefresh)
+ tb.Realize()
+
+ def EmbedUnembed(self, embedPanel):
+ conf = g.conf
+ conf.embedPanel = embedPanel
+ if conf.embedPanel:
+ # Remember last dimentions
+ conf.panelPos = self.miniFrame.GetPosition()
+ conf.panelSize = self.miniFrame.GetSize()
+ conf.size = self.GetSize()
+ conf.sashPos = self.GetClientSize()[0]
+ panelWidth = panel.GetSize()[0] # client size
+ panel.Reparent(self.splitter)
+ self.miniFrame.GetSizer().Remove(panel)
+ # Widen
+ conf.size.width += panelWidth
+ self.SetSize(conf.size)
+ self.splitter.SplitVertically(tree, panel, conf.sashPos)
+ self.miniFrame.Show(False)
+ else:
+ conf.sashPos = self.splitter.GetSashPosition()
+ conf.size = self.GetSize()
+ conf.panelSize[0] = panel.GetSize()[0]
+ self.splitter.Unsplit(panel)
+ sizer = self.miniFrame.GetSizer()
+ panel.Reparent(self.miniFrame)
+ panel.Show(True)
+ sizer.Add(panel, 1, wx.EXPAND)
+ self.miniFrame.Show(True)
+ self.miniFrame.SetPosition(conf.panelPos)
+ self.miniFrame.SetSize(conf.panelSize)
+ self.miniFrame.Layout()
+ # Reduce width
+ conf.size.width -= conf.panelSize.width
+ self.SetSize(conf.size)
+
+ # Set long or short toolbar
+ self.InitToolBar(embedPanel)
+
+ def ShowReadme(self):
+ text = open(os.path.join(g.basePath, 'README.txt'), 'r').read()
+ dlg = ScrolledMessageDialog(frame, text, "XRCed README")
+ dlg.ShowModal()
+ dlg.Destroy()
+
+ def ShowPrefs(self):
+ dlg = PrefsDialog(self)
+ conf = g.conf
+ toolPanelType = conf.toolPanelType
+ if dlg.ShowModal() == wx.ID_OK:
+ # Fetch new preferences
+ for id,cdp in dlg.checkControls.items():
+ c,d,p = cdp
+ if dlg.FindWindowById(id).IsChecked():
+ d[p] = str(c.GetValue())
+ elif p in d: del d[p]
+ conf.useAUI = dlg.check_AUI.GetValue()
+ conf.toolPanelType = ['TB','FPB'][dlg.radio_toolPanelType.GetSelection()]
+ conf.toolThumbSize = dlg.slider_thumbSize.GetValue()
+ conf.toolIconScale = dlg.slider_iconScale.GetValue()
+ conf.expandOnOpen = dlg.check_expandOnOpen.GetValue()
+ conf.fitTestWin = dlg.check_fitTestWin.GetValue()
+ conf.autoRefreshPolicy = dlg.radio_autoRefreshPolicy.GetSelection()
+ conf.TB_file = dlg.check_TB_file.GetValue()
+ conf.TB_undo = dlg.check_TB_undo.GetValue()
+ conf.TB_copy = dlg.check_TB_copy.GetValue()
+ conf.TB_move = dlg.check_TB_move.GetValue()
+ conf.useSubclassing = dlg.check_useSubclassing.GetValue()
+ conf.allowExec = ('ask', 'yes', 'no')[dlg.radio_allowExec.GetSelection()]
+ wx.LogMessage('Restart may be needed for some settings to take effect.')
+ dlg.Destroy()
+
+#############################################################################
+
+# ScrolledMessageDialog - modified from wxPython lib to set fixed-width font
+class ScrolledMessageDialog(wx.Dialog):
+ def __init__(self, parent, msg, caption, textSize=(80,40), centered=True):
+ from wx.lib.layoutf import Layoutf
+ wx.Dialog.__init__(self, parent, -1, caption)
+ text = wx.TextCtrl(self, -1, msg, wx.DefaultPosition,
+ wx.DefaultSize, wx.TE_MULTILINE | wx.TE_READONLY)
+ text.SetFont(g.modernFont())
+ dc = wx.WindowDC(text)
+ w, h = dc.GetFullTextExtent(' ', g.modernFont())[:2]
+ ok = wx.Button(self, wx.ID_OK, "OK")
+ ok.SetDefault()
+ text.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self,ok)))
+ text.SetSize((w * textSize[0] + 30, h * textSize[1]))
+ text.ShowPosition(1) # scroll to the first line
+ ok.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!35', (self,)))
+ self.SetAutoLayout(True)
+ self.Fit()
+ if centered:
+ self.CenterOnScreen(wx.BOTH)
+
+################################################################################
+
+class PrefsDialog(wx.Dialog): #(wx.PropertySheetDialog): !!! not wrapper yed - wrap by hand
+
+ def __init__(self, parent):
+ pre = g.res.LoadObject(parent, 'DIALOG_PREFS', 'wxPropertySheetDialog')
+ self.PostCreate(pre)
+
+ self.Fit()
+
+ self.checkControls = {} # map of check IDs to (control,dict,param)
+ conf = g.conf
+
+ # Defaults
+
+ self.check_proportionContainer = xrc.XRCCTRL(self, 'check_proportionContainer')
+ id = self.check_proportionContainer.GetId()
+ wx.EVT_CHECKBOX(self, id, self.OnCheck)
+ self.checkControls[id] = (xrc.XRCCTRL(self, 'spin_proportionContainer'),
+ conf.defaultsContainer, 'option')
+
+ self.check_flagContainer = xrc.XRCCTRL(self, 'check_flagContainer')
+ id = self.check_flagContainer.GetId()
+ wx.EVT_CHECKBOX(self, id, self.OnCheck)
+ self.checkControls[id] = (xrc.XRCCTRL(self, 'text_flagContainer'),
+ conf.defaultsContainer, 'flag')
+
+ self.check_proportionControl = xrc.XRCCTRL(self, 'check_proportionControl')
+ id = self.check_proportionControl.GetId()
+ wx.EVT_CHECKBOX(self, id, self.OnCheck)
+ self.checkControls[id] = (xrc.XRCCTRL(self, 'spin_proportionControl'),
+ conf.defaultsControl, 'option')
+
+ self.check_flagControl = xrc.XRCCTRL(self, 'check_flagControl')
+ id = self.check_flagControl.GetId()
+ wx.EVT_CHECKBOX(self, id, self.OnCheck)
+ self.checkControls[id] = (xrc.XRCCTRL(self, 'text_flagControl'),
+ conf.defaultsControl, 'flag')
+
+ for id,cdp in self.checkControls.items():
+ c,d,p = cdp
+ try:
+ if isinstance(c, wx.SpinCtrl):
+ c.SetValue(int(d[p]))
+ else:
+ c.SetValue(d[p])
+ self.FindWindowById(id).SetValue(True)
+ except KeyError:
+ c.Enable(False)
+
+ # Appearance
+
+ self.check_AUI = xrc.XRCCTRL(self, 'check_AUI')
+ self.check_AUI.SetValue(conf.useAUI)
+ self.radio_toolPanelType = xrc.XRCCTRL(self, 'radio_toolPanelType')
+ self.radio_toolPanelType.SetSelection(['TB','FPB'].index(conf.toolPanelType))
+ self.slider_thumbSize = xrc.XRCCTRL(self, 'slider_thumbSize')
+ self.slider_thumbSize.SetValue(conf.toolThumbSize)
+ self.slider_iconScale = xrc.XRCCTRL(self, 'slider_iconScale')
+ self.slider_iconScale.SetValue(conf.toolIconScale)
+
+ self.check_expandOnOpen = xrc.XRCCTRL(self, 'check_expandOnOpen')
+ self.check_expandOnOpen.SetValue(conf.expandOnOpen)
+ self.check_fitTestWin = xrc.XRCCTRL(self, 'check_fitTestWin')
+ self.check_fitTestWin.SetValue(conf.fitTestWin)
+ self.radio_autoRefreshPolicy = xrc.XRCCTRL(self, 'radio_autoRefreshPolicy')
+ self.radio_autoRefreshPolicy.SetSelection(conf.autoRefreshPolicy)
+
+ self.check_TB_file = xrc.XRCCTRL(self, 'check_TB_file')
+ self.check_TB_file.SetValue(conf.TB_file)
+ self.check_TB_undo = xrc.XRCCTRL(self, 'check_TB_undo')
+ self.check_TB_undo.SetValue(conf.TB_undo)
+ self.check_TB_copy = xrc.XRCCTRL(self, 'check_TB_copy')
+ self.check_TB_copy.SetValue(conf.TB_copy)
+ self.check_TB_move = xrc.XRCCTRL(self, 'check_TB_move')
+ self.check_TB_move.SetValue(conf.TB_move)
+
+ self.check_useSubclassing = xrc.XRCCTRL(self, 'check_useSubclassing')
+ self.check_useSubclassing.SetValue(conf.useSubclassing)
+
+ self.radio_allowExec = xrc.XRCCTRL(self, 'radio_allowExec')
+ try:
+ index = {'ask': 0, 'yes':1, 'no': 2}[g.conf.allowExec]
+ except KeyError:
+ index = 0
+ self.radio_allowExec.SetSelection(index)
+
+ def OnCheck(self, evt):
+ self.checkControls[evt.GetId()][0].Enable(evt.IsChecked())
+ evt.Skip()
+
+#############################################################################
+
+# ArtProvider for toolbar icons
+class ToolArtProvider(wx.ArtProvider):
+ def __init__(self):
+ wx.ArtProvider.__init__(self)
+ self.images = {
+ 'ART_LOCATE': images.Locate.GetImage(),
+ 'ART_TEST': images.Test.GetImage(),
+ 'ART_REFRESH': images.Refresh.GetImage(),
+ 'ART_AUTO_REFRESH': images.AutoRefresh.GetImage(),
+ 'ART_MOVEUP': images.MoveUp.GetImage(),
+ 'ART_MOVEDOWN': images.MoveDown.GetImage(),
+ 'ART_MOVELEFT': images.MoveLeft.GetImage(),
+ 'ART_MOVERIGHT': images.MoveRight.GetImage(),
+ 'ART_REMOVE': images.Remove.GetImage()
+ }
+ if wx.Platform in ['__WXMAC__', '__WXMSW__']:
+ self.images.update({
+ wx.ART_NORMAL_FILE: images.New.GetImage(),
+ wx.ART_FILE_OPEN: images.Open.GetImage(),
+ wx.ART_FILE_SAVE: images.Save.GetImage(),
+ wx.ART_UNDO: images.Undo.GetImage(),
+ wx.ART_REDO: images.Redo.GetImage(),
+ wx.ART_CUT: images.Cut.GetImage(),
+ wx.ART_COPY: images.Copy.GetImage(),
+ wx.ART_PASTE: images.Paste.GetImage()
+ })
+
+ def CreateBitmap(self, id, client, size):
+ bmp = wx.NullBitmap
+ if id in self.images:
+ bmp = wx.BitmapFromImage(self.images[id])
+ return bmp
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.htb b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.htb
new file mode 100644
index 0000000..bbcc139
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.htb
Binary files differ
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.py
new file mode 100644
index 0000000..6c9bf89
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.py
@@ -0,0 +1,267 @@
+# Name: xrced.py
+# Purpose: XRC editor, main module
+# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
+# Created: 20.08.2001
+# RCS-ID: $Id: xrced.py 71858 2012-06-25 09:55:13Z ROL $
+
+"""
+
+usage: xrced [options] [XRC file]
+
+options:
+ --version show program's version number and exit
+ -h, --help show this help message and exit
+ -d, --debug add Debug command to Help menu
+ -m, --meta activate meta-components
+ -v, --verbose verbose messages
+
+"""
+
+import os
+from optparse import OptionParser
+from globals import *
+import params
+from presenter import Presenter
+from listener import Listener
+from component import Manager
+import view
+import undo
+import plugin
+
+# for helping to attach to the process with gdb...
+#print "%s\nPID: %d\n" % (wx.version(), os.getpid()); #raw_input("Press Enter...")
+
+# to enable the widget inspector & its hot-key
+USE_INSPECTOR = False
+
+# Parse string in form var1=val1[,var2=val2]* as dictionary
+def ReadDictFromString(s):
+ d = {}
+ for vv in s.split(','):
+ var,val = vv.split(':')
+ d[var.strip()] = val
+ return d
+
+# Transform dictionary with strings into one string
+def DictToString(d):
+ return ','.join(map(':'.join, d.items()))
+
+
+if USE_INSPECTOR:
+ import wx.lib.mixins.inspection
+ AppBase = wx.lib.mixins.inspection.InspectableApp
+else:
+ AppBase = wx.App
+
+
+class App(AppBase):
+ def OnInit(self):
+ if USE_INSPECTOR:
+ self.Init()
+
+ # Check version
+ if wx.VERSION[:3] < MinWxVersion:
+ wx.LogWarning('''\
+This version of XRCed may not work correctly on your version of wxWidgets. \
+Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion)
+
+ g.undoMan = undo.UndoManager()
+ Manager.init()
+
+ parser = OptionParser(prog=progname,
+ version='%s version %s' % (ProgName, version),
+ usage='%prog [options] [XRC file]')
+ parser.add_option('-d', '--debug', action='store_true',
+ help='add Debug command to Help menu')
+ parser.add_option('-m', '--meta', action='store_true',
+ dest = 'meta',
+ help='activate meta-components')
+ parser.add_option('-v', '--verbose', action='store_true',
+ help='verbose messages')
+
+ # Process command-line arguments
+ options, args = parser.parse_args()
+ if options.debug:
+ set_debug(True)
+ if options.verbose:
+ set_verbose(True)
+ if options.meta:
+ g.useMeta = True
+ import meta
+ Manager.register(meta.Component)
+ Manager.setMenu(meta.Component, 'TOP_LEVEL', 'component', 'component plugin')
+
+ self.SetAppName(progname)
+
+ self.ReadConfig()
+
+ # Add handlers
+ wx.FileSystem.AddHandler(wx.MemoryFSHandler())
+ self.toolArtProvider = view.ToolArtProvider()
+ wx.ArtProvider.Push(self.toolArtProvider)
+
+ # Load standard plugins first
+ plugin.load_plugins(os.path.join(g.basePath, 'plugins'))
+ # ... and then from user-defined dirs
+ plugin.load_plugins_from_dirs()
+
+ # Setup MVP
+ view.create_view()
+ Presenter.init()
+ Listener.Install(view.frame, view.tree, view.panel,
+ view.toolFrame, view.testWin)
+
+ if args:
+ path = args[0]
+ # Change current directory
+ dir = os.path.dirname(path)
+ if dir:
+ os.chdir(dir)
+ path = os.path.basename(path)
+ if os.path.isfile(path):
+ # Populate after final creation
+ wx.CallAfter(Presenter.open, path)
+ else:
+ # Future name
+ Presenter.path = path
+ # Reset modified flag
+ Presenter.setModified(False)
+ view.frame.Show()
+ if not g.useAUI:
+ if not g.conf.embedPanel:
+ view.frame.miniFrame.Show()
+ if g.conf.showToolPanel:
+ Listener.toolFrame.Show()
+
+ return True
+
+ def OnExit(self):
+ self.WriteConfig()
+
+ def ReadConfig(self):
+ # Settings
+ conf = g.conf = wx.Config(style = wx.CONFIG_USE_LOCAL_FILE)
+ conf.localconf = None
+ conf.autoRefresh = conf.ReadBool('autoRefresh', True)
+ conf.autoRefreshPolicy = conf.ReadInt('autoRefreshPolicy', 0)
+ conf.pos = wx.Point(conf.ReadInt('x', -1), conf.ReadInt('y', -1))
+ conf.size = wx.Size(conf.ReadInt('width', 800), conf.ReadInt('height', 600))
+ g.useAUI = conf.useAUI = conf.ReadBool('useAUI', False)
+ conf.embedPanel = conf.ReadBool('embedPanel', True)
+ conf.panelPinState = conf.ReadBool('panelPinState', False)
+ conf.showToolPanel = conf.ReadBool('showToolPanel', True)
+ conf.sashPos = conf.ReadInt('sashPos', 200)
+
+ # read recently used files
+ g.fileHistory = wx.FileHistory()
+ g.fileHistory.Load(conf)
+
+ conf.panelPos = wx.Point(conf.ReadInt('panelX', -1),
+ conf.ReadInt('panelY', -1))
+ conf.panelSize = wx.Size(conf.ReadInt('panelWidth', 200),
+ conf.ReadInt('panelHeight', 200))
+ conf.sashPos = conf.ReadInt('sashPos', 200)
+
+ conf.toolPanelPos = wx.Point(conf.ReadInt('toolPanelX', -1),
+ conf.ReadInt('toolPanelY', -1))
+ if wx.Platform == '__WXMAC__':
+ conf.toolPanelPos.y += 4 # OSX has some issues with miniframe
+ conf.toolPanelSize = wx.Size(conf.ReadInt('toolPanelWidth', -1),
+ conf.ReadInt('toolPanelHeight', -1))
+
+ # Preferences
+ conf.toolPanelType = conf.Read('Prefs/toolPanelType', 'TB')
+ conf.toolThumbSize = conf.ReadInt('Prefs/toolThumbSize', 48)
+ conf.toolIconScale = conf.ReadInt('Prefs/toolIconScale', 100)
+ conf.expandOnOpen = conf.ReadBool('Prefs/expandOnOpen', True)
+ conf.fitTestWin = conf.ReadBool('Prefs/fitTestWin', True)
+ conf.useSubclassing = conf.ReadBool('Prefs/useSubclassing', False)
+ conf.allowExec = conf.Read('Prefs/allowExec', 'ask')
+ # Toolbar configuration
+ conf.TB_file = conf.ReadBool('Prefs/TB_file', True)
+ conf.TB_undo = conf.ReadBool('Prefs/TB_undo', True)
+ conf.TB_copy = conf.ReadBool('Prefs/TB_copy', True)
+ conf.TB_move = conf.ReadBool('Prefs/TB_move', True)
+ p = 'Prefs/Defaults/Container'
+ if conf.HasEntry(p):
+ conf.defaultsContainer = ReadDictFromString(conf.Read(p))
+ else:
+ conf.defaultsContainer = {}
+ p = 'Prefs/Defaults/Control'
+ if conf.HasEntry(p):
+ conf.defaultsControl = ReadDictFromString(conf.Read(p))
+ else:
+ conf.defaultsControl = {}
+ conf.SetPath('/')
+
+ def WriteConfig(self):
+
+ # Write config
+ conf = g.conf
+ conf.SetPath('/')
+ conf.WriteBool('autoRefresh', conf.autoRefresh)
+ conf.WriteInt('autoRefreshPolicy', conf.autoRefreshPolicy)
+ conf.WriteBool('useAUI', conf.useAUI)
+ if g.useAUI:
+ conf.Write('perspective', conf.perspective)
+ conf.WriteInt('x', conf.pos.x)
+ conf.WriteInt('y', conf.pos.y)
+ conf.WriteInt('width', conf.size.x)
+ conf.WriteInt('height', conf.size.y)
+ conf.WriteInt('embedPanel', conf.embedPanel)
+ conf.WriteInt('panelPinState', conf.panelPinState)
+ conf.WriteInt('showTools', conf.showToolPanel)
+ if not conf.embedPanel:
+ conf.WriteInt('panelX', conf.panelPos.x)
+ conf.WriteInt('panelY', conf.panelPos.y)
+ conf.WriteInt('sashPos', conf.sashPos)
+ conf.WriteInt('panelWidth', conf.panelSize.x)
+ conf.WriteInt('panelHeight', conf.panelSize.y)
+ conf.WriteInt('showToolPanel', conf.showToolPanel)
+ conf.WriteInt('toolPanelX', conf.toolPanelPos.x)
+ conf.WriteInt('toolPanelY', conf.toolPanelPos.y)
+ conf.WriteInt('toolPanelWidth', conf.toolPanelSize.x)
+ conf.WriteInt('toolPanelHeight', conf.toolPanelSize.y)
+ g.fileHistory.Save(conf)
+ # Preferences
+ conf.DeleteGroup('Prefs')
+ conf.Write('Prefs/toolPanelType', conf.toolPanelType)
+ conf.WriteInt('Prefs/toolThumbSize', conf.toolThumbSize)
+ conf.WriteInt('Prefs/toolIconScale', conf.toolIconScale)
+ conf.WriteInt('Prefs/expandOnOpen', conf.expandOnOpen)
+ conf.WriteInt('Prefs/fitTestWin', conf.fitTestWin)
+ conf.WriteInt('Prefs/TB_file', conf.TB_file)
+ conf.WriteInt('Prefs/TB_undo', conf.TB_undo)
+ conf.WriteInt('Prefs/TB_copy', conf.TB_copy)
+ conf.WriteInt('Prefs/TB_move', conf.TB_move)
+ conf.WriteInt('Prefs/useSubclassing', conf.useSubclassing)
+ conf.Write('Prefs/allowExec', conf.allowExec)
+ v = conf.defaultsContainer
+ if v: conf.Write('Prefs/Defaults/Container', DictToString(v))
+ v = conf.defaultsControl
+ if v: conf.Write('Prefs/Defaults/Control', DictToString(v))
+
+ conf.Flush()
+
+def main():
+ if 'wxMac' in wx.PlatformInfo:
+ # if running from an App bundle on Mac then there could be an
+ # unexpected -psb_blahblah command-line arg. Blow it away.
+ for idx,arg in enumerate(sys.argv):
+ if arg.startswith('-psn'):
+ del sys.argv[idx]
+ break
+
+ app = App(0, useBestVisual=False)
+ #app.SetAssertMode(wx.PYAPP_ASSERT_LOG)
+ app.MainLoop()
+
+if __name__ == '__main__':
+ # Substitute wx.tools.XRCed with local module
+ try:
+ from XRCed.xrced import main
+ except ImportError:
+ print >>sys.stderr, 'XRCed parent directory must be in PYTHONPATH for local running'
+ raise
+ sys.modules['wx.tools.XRCed'] = sys.modules['XRCed']
+ main()
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.xrc b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.xrc
new file mode 100644
index 0000000..30cb4a0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/XRCed/xrced.xrc
@@ -0,0 +1,1064 @@
+<?xml version="1.0" ?>
+<resource>
+ <object class="wxDialog" name="DIALOG_TEXT">
+ <title>Text Dialog</title>
+ <centered>1</centered>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="TEXT">
+ <value/>
+ <size>250,100</size>
+ <style>wxTE_MULTILINE</style>
+ </object>
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStdDialogButtonSizer">
+ <object class="button">
+ <object class="wxButton" name="wxID_OK">
+ </object>
+ </object>
+ <object class="button">
+ <object class="wxButton" name="wxID_CANCEL">
+ </object>
+ </object>
+ </object>
+ <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
+ </object>
+ <object class="wxDialog" name="DIALOG_CONTENT">
+ <title>Content</title>
+ <centered>1</centered>
+ <size>250,300</size>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <object class="wxListBox" name="LIST">
+ <content/>
+ </object>
+ <option>1</option>
+ <flag>wxTOP|wxBOTTOM|wxLEFT|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_UP">
+ <label>Move Up</label>
+ </object>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_DOWN">
+ <label>Move Down</label>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="spacer">
+ <size>10,20</size>
+ <option>1</option>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_APPEND">
+ <label>Append...</label>
+ </object>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_EDIT">
+ <label>Edit...</label>
+ </object>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_REMOVE">
+ <label>Remove</label>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ </object>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticLine"/>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <object class="wxButton" name="wxID_OK">
+ <label>OK</label>
+ <default>1</default>
+ </object>
+ <flag>wxRIGHT</flag>
+ <border>10</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="wxID_CANCEL">
+ <label>Cancel</label>
+ </object>
+ </object>
+ </object>
+ <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
+ </object>
+ <object class="wxDialog" name="DIALOG_CONTENT_CHECKLIST">
+ <title>Content</title>
+ <centered>1</centered>
+ <size>250,300</size>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <object class="wxCheckListBox" name="CHECK_LIST">
+ <content/>
+ </object>
+ <option>1</option>
+ <flag>wxTOP|wxBOTTOM|wxLEFT|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_UP">
+ <label>Move Up</label>
+ </object>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_DOWN">
+ <label>Move Down</label>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="spacer">
+ <size>10,20</size>
+ <option>1</option>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_APPEND">
+ <label>Append...</label>
+ </object>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_EDIT">
+ <label>Edit...</label>
+ </object>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_REMOVE">
+ <label>Remove</label>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ </object>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="spacer">
+ <size>0,10</size>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStdDialogButtonSizer">
+ <object class="button">
+ <object class="wxButton" name="wxID_OK">
+ </object>
+ </object>
+ <object class="button">
+ <object class="wxButton" name="wxID_CANCEL">
+ </object>
+ </object>
+ </object>
+ <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
+ </object>
+ <object class="wxDialog" name="DIALOG_CHOICES">
+ <title>Choices</title>
+ <centered>1</centered>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxCheckListBox" name="CHECKLIST">
+ <content/>
+ <size>250,250</size>
+ <style/>
+ </object>
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="spacer">
+ <size>0,10</size>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStdDialogButtonSizer">
+ <object class="button">
+ <object class="wxButton" name="wxID_OK">
+ </object>
+ </object>
+ <object class="button">
+ <object class="wxButton" name="wxID_CANCEL">
+ </object>
+ </object>
+ </object>
+ <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
+ </object>
+ <object class="wxDialog" name="DIALOG_STYLES">
+ <title>Window Styles</title>
+ <centered>1</centered>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxStaticText" name="LABEL_SPECIFIC">
+ <label>Specific styles:</label>
+ </object>
+ <flag>wxTOP|wxLEFT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckListBox" name="CHECKLIST_SPECIFIC">
+ <content/>
+ <size>250,150</size>
+ <style/>
+ </object>
+ <option>1</option>
+ <flag>wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <label>Generic styles:</label>
+ </object>
+ <flag>wxLEFT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckListBox" name="CHECKLIST_GENERIC">
+ <content/>
+ <size>250,150</size>
+ <style/>
+ </object>
+ <option>1</option>
+ <flag>wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="spacer">
+ <size>0,10</size>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStdDialogButtonSizer">
+ <object class="button">
+ <object class="wxButton" name="wxID_OK">
+ </object>
+ </object>
+ <object class="button">
+ <object class="wxButton" name="wxID_CANCEL">
+ </object>
+ </object>
+ </object>
+ <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
+ </object>
+ <object class="wxDialog" name="DIALOG_INTLIST">
+ <title>Numbers</title>
+ <centered>1</centered>
+ <size>100,300</size>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <object class="wxListBox" name="LIST">
+ <content/>
+ <size>80,150</size>
+ <style>wxLB_SORT</style>
+ </object>
+ <option>1</option>
+ <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxSpinCtrl" name="SPIN">
+ <size>60,-1</size>
+ </object>
+ <flag>wxBOTTOM</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_ADD">
+ <label>Add</label>
+ </object>
+ <flag>wxBOTTOM</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_REMOVE">
+ <label>Remove</label>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_CLEAR">
+ <label>Clear</label>
+ </object>
+ <flag>wxTOP</flag>
+ <border>5</border>
+ </object>
+ </object>
+ <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>5</border>
+ </object>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>0</border>
+ </object>
+ <object class="spacer">
+ <size>0,10</size>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStdDialogButtonSizer">
+ <object class="button">
+ <object class="wxButton" name="wxID_OK">
+ </object>
+ </object>
+ <object class="button">
+ <object class="wxButton" name="wxID_CANCEL">
+ </object>
+ </object>
+ </object>
+ <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
+ </object>
+ <object class="wxPanel" name="PANEL_BITMAP">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxPanel">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxFlexGridSizer">
+ <cols>2</cols>
+ <rows>2</rows>
+ <object class="sizeritem">
+ <object class="wxRadioButton" name="RADIO_STD">
+ <label>art:</label>
+ </object>
+ <flag>wxALIGN_CENTRE_VERTICAL</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxComboBox" name="COMBO_STD">
+ <content>
+ <item>wxART_ADD_BOOKMARK</item>
+ <item>wxART_DEL_BOOKMARK</item>
+ <item>wxART_HELP_SIDE_PANEL</item>
+ <item>wxART_HELP_SETTINGS</item>
+ <item>wxART_HELP_BOOK</item>
+ <item>wxART_HELP_FOLDER</item>
+ <item>wxART_HELP_PAGE</item>
+ <item>wxART_GO_BACK</item>
+ <item>wxART_GO_FORWARD</item>
+ <item>wxART_GO_UP</item>
+ <item>wxART_GO_DOWN</item>
+ <item>wxART_GO_TO_PARENT</item>
+ <item>wxART_GO_HOME</item>
+ <item>wxART_FILE_OPEN</item>
+ <item>wxART_FILE_SAVE</item>
+ <item>wxART_FILE_SAVE_AS</item>
+ <item>wxART_PRINT</item>
+ <item>wxART_HELP</item>
+ <item>wxART_TIP</item>
+ <item>wxART_REPORT_VIEW</item>
+ <item>wxART_LIST_VIEW</item>
+ <item>wxART_NEW_DIR</item>
+ <item>wxART_HARDDISK</item>
+ <item>wxART_FLOPPY</item>
+ <item>wxART_CDROM</item>
+ <item>wxART_REMOVABLE</item>
+ <item>wxART_FOLDER</item>
+ <item>wxART_FOLDER_OPEN</item>
+ <item>wxART_GO_DIR_UP</item>
+ <item>wxART_EXECUTABLE_FILE</item>
+ <item>wxART_NORMAL_FILE</item>
+ <item>wxART_TICK_MARK</item>
+ <item>wxART_CROSS_MARK</item>
+ <item>wxART_ERROR</item>
+ <item>wxART_QUESTION</item>
+ <item>wxART_WARNING</item>
+ <item>wxART_INFORMATION</item>
+ <item>wxART_MISSING_IMAGE</item>
+ <item>wxART_COPY</item>
+ <item>wxART_CUT</item>
+ <item>wxART_PASTE</item>
+ <item>wxART_DELETE</item>
+ <item>wxART_NEW</item>
+ <item>wxART_UNDO</item>
+ <item>wxART_REDO</item>
+ <item>wxART_QUIT</item>
+ <item>wxART_FIND</item>
+ <item>wxART_FIND_AND_REPLACE</item>
+ </content>
+ </object>
+ <flag>wxLEFT|wxEXPAND|wxALIGN_RIGHT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxRadioButton" name="RADIO_FILE">
+ <label>file:</label>
+ </object>
+ <flag>wxALIGN_CENTRE_VERTICAL</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="TEXT_FILE"/>
+ <option>1</option>
+ <flag>wxRIGHT|wxEXPAND</flag>
+ <border>3</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_BROWSE">
+ <label>Browse...</label>
+ <size>40,-1d</size>
+ </object>
+ </object>
+ </object>
+ <flag>wxLEFT|wxEXPAND|wxALIGN_RIGHT</flag>
+ <border>5</border>
+ </object>
+ <vgap>2</vgap>
+ <growablecols>1</growablecols>
+ </object>
+ <flag>wxALL</flag>
+ <border>2</border>
+ </object>
+ </object>
+ <style>wxSUNKEN_BORDER</style>
+ </object>
+ <flag>wxALL</flag>
+ <border>2</border>
+ </object>
+ </object>
+ </object>
+ <object class="wxDialog" name="PYTHON_OPTIONS">
+ <title>Python Module Config</title>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="AutoGenerateCB">
+ <label>Autogenerate Python module when saving XRC</label>
+ </object>
+ <flag>wxBOTTOM|wxLEFT|wxRIGHT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="EmbedCB">
+ <label>Embed resources in the Python module</label>
+ </object>
+ <flag>wxBOTTOM|wxLEFT|wxRIGHT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="GettextCB">
+ <label>Generate gettext strings</label>
+ </object>
+ <flag>wxBOTTOM|wxLEFT|wxRIGHT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="MakeXRSFileCB">
+ <label>Generate and use compressed XRS file</label>
+ <enabled>0</enabled>
+ <hidden>1</hidden>
+ </object>
+ <flag>wxBOTTOM|wxLEFT|wxRIGHT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <label>Filename:</label>
+ </object>
+ <flag>wxALL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="FileNameTC">
+ <size>500,-1</size>
+ </object>
+ <flag>wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_CENTRE_VERTICAL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BrowseBtn">
+ <label>Browse...</label>
+ </object>
+ <flag>wxBOTTOM|wxRIGHT</flag>
+ <border>5</border>
+ </object>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ </object>
+ <flag>wxALL</flag>
+ <border>10</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticLine"/>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="spacer">
+ <size>1,10</size>
+ <option>1</option>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="GenerateBtn">
+ <label>Generate module</label>
+ <default>1</default>
+ </object>
+ </object>
+ <object class="spacer">
+ <size>10,1</size>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="SaveOptsBtn">
+ <label>Save options</label>
+ <style/>
+ </object>
+ </object>
+ <object class="spacer">
+ <size>10,1</size>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="wxID_CANCEL">
+ <label/>
+ </object>
+ </object>
+ </object>
+ <flag>wxALL|wxEXPAND|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ </object>
+ <object class="wxPropertySheetDialog" name="DIALOG_PREFS">
+ <object class="propertysheetpage">
+ <object class="wxPanel">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxStaticBoxSizer">
+ <label>Defaults for new containers</label>
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxFlexGridSizer">
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_proportionContainer">
+ <label>proportion</label>
+ </object>
+ <flag>wxALIGN_CENTRE_VERTICAL</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxSpinCtrl" name="spin_proportionContainer">
+ <size>30,-1d</size>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_flagContainer">
+ <label>flag</label>
+ </object>
+ <flag>wxALIGN_CENTRE_VERTICAL</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="text_flagContainer">
+ <size>200,-1</size>
+ </object>
+ </object>
+ <cols>2</cols>
+ <rows>2</rows>
+ <vgap>4</vgap>
+ <hgap>10</hgap>
+ </object>
+ </object>
+ </object>
+ <flag>wxALL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticBoxSizer">
+ <label>Defaults for new controls</label>
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxFlexGridSizer">
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_proportionControl">
+ <label>proportion</label>
+ </object>
+ <flag>wxALIGN_CENTRE_VERTICAL</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxSpinCtrl" name="spin_proportionControl">
+ <size>30,-1d</size>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_flagControl">
+ <label>flag</label>
+ </object>
+ <flag>wxALIGN_CENTRE_VERTICAL</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="text_flagControl">
+ <size>200,-1</size>
+ </object>
+ </object>
+ <cols>2</cols>
+ <rows>2</rows>
+ <vgap>4</vgap>
+ <hgap>10</hgap>
+ </object>
+ </object>
+ </object>
+ <flag>wxALL</flag>
+ <border>5</border>
+ </object>
+ </object>
+ </object>
+ <label>Defaults</label>
+ </object>
+ <object class="propertysheetpage">
+ <object class="wxPanel">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_AUI">
+ <label>Use AUI</label>
+ <tooltip>Use AUI subsystem for layout</tooltip>
+ </object>
+ <flag>wxALL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxRadioBox" name="radio_toolPanelType">
+ <label>Component panel style</label>
+ <dimension>0</dimension>
+ <content>
+ <item>ToolBook</item>
+ <item>FoldPanelBar</item>
+ </content>
+ <dimension>0</dimension>
+ <style>wxRA_SPECIFY_COLS</style>
+ </object>
+ <flag>wxBOTTOM|wxRIGHT</flag>
+ <border>4</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticBoxSizer">
+ <object class="sizeritem">
+ <object class="wxStaticBoxSizer">
+ <object class="sizeritem">
+ <object class="wxSlider" name="slider_thumbSize">
+ <min>16</min>
+ <max>48</max>
+ <tickfreq>8</tickfreq>
+ <pagesize>8</pagesize>
+ <linesize>8</linesize>
+ <style>wxSL_HORIZONTAL|wxSL_LABELS</style>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ <label>Group thumbnail size</label>
+ <orient>wxVERTICAL</orient>
+ </object>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticBoxSizer">
+ <object class="sizeritem">
+ <object class="wxSlider" name="slider_iconScale">
+ <min>10</min>
+ <max>100</max>
+ <tickfreq>10</tickfreq>
+ <pagesize>10</pagesize>
+ <linesize>10</linesize>
+ <style>wxSL_HORIZONTAL|wxSL_LABELS</style>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ <label>Component icon scaling</label>
+ <orient>wxVERTICAL</orient>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ <label>Component palette</label>
+ <orient>wxVERTICAL</orient>
+ </object>
+ <flag>wxRIGHT|wxEXPAND</flag>
+ <border>4</border>
+ </object>
+ </object>
+ </object>
+ <label>Appearance</label>
+ </object>
+ <object class="propertysheetpage">
+ <object class="wxPanel">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_TB_file">
+ <label>New/Open/Save</label>
+ </object>
+ <flag>wxTOP|wxLEFT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_TB_undo">
+ <label>Undo/Redo</label>
+ </object>
+ <flag>wxTOP|wxLEFT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_TB_copy">
+ <label>Cut/Copy/Paste</label>
+ </object>
+ <flag>wxTOP|wxLEFT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_TB_move">
+ <label>Move</label>
+ </object>
+ <flag>wxTOP|wxLEFT</flag>
+ <border>5</border>
+ </object>
+ </object>
+ </object>
+ <label>Toolbar</label>
+ </object>
+ <object class="propertysheetpage">
+ <object class="wxPanel">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_expandOnOpen">
+ <label>Expand tree on open</label>
+ <tooltip>Expand XML tree after opening the resource file</tooltip>
+ </object>
+ <flag>wxALL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_fitTestWin">
+ <label>Fit test window</label>
+ <tooltip>Fit test window after creating</tooltip>
+ </object>
+ <flag>wxTOP|wxLEFT|wxRIGHT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxRadioBox" name="radio_autoRefreshPolicy">
+ <label>Auto-refresh activated by</label>
+ <content>
+ <item>selection change</item>
+ <item>atomic change</item>
+ </content>
+ <style>wxRA_SPECIFY_ROWS</style>
+ </object>
+ <flag>wxTOP|wxLEFT|wxRIGHT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="check_useSubclassing">
+ <label>Use subclassing</label>
+ <tooltip>Use subclassing when creating the test view</tooltip>
+ </object>
+ <flag>wxTOP|wxLEFT|wxRIGHT</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxRadioBox" name="radio_allowExec">
+ <label>Allow executable comments</label>
+ <content>
+ <item>ask</item>
+ <item>yes</item>
+ <item>no</item>
+ </content>
+ <help>Control of execution &quot;%command&quot; comments</help>
+ <style>wxRA_SPECIFY_ROWS</style>
+ </object>
+ <flag>wxTOP|wxLEFT|wxRIGHT</flag>
+ <border>5</border>
+ </object>
+ </object>
+ </object>
+ <label>Misc</label>
+ </object>
+ <title>XRCed Preferences</title>
+ <centered>1</centered>
+ <buttons>wxOK|wxCANCEL</buttons>
+ <style>wxDEFAULT_DIALOG_STYLE</style>
+ </object>
+ <object class="wxPanel" name="PANEL_ATTRIBUTES">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxStaticBoxSizer">
+ <label>XML ID</label>
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="TEXT_XRCID">
+ <size>100,-1d</size>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <object class="wxNotebook" name="NOTEBOOK"/>
+ </object>
+ </object>
+ </object>
+ <object class="wxDialog" name="DIALOG_CONTENT_HELPLIST">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <object class="wxListCtrl" name="LIST">
+ <size>250,-1</size>
+ <style>wxLC_REPORT</style>
+ </object>
+ <option>1</option>
+ <flag>wxTOP|wxBOTTOM|wxLEFT|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_UP">
+ <label>Move Up</label>
+ </object>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_DOWN">
+ <label>Move Down</label>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="spacer">
+ <size>10,20</size>
+ <option>1</option>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_APPEND">
+ <label>Append...</label>
+ </object>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_EDIT">
+ <label>Edit...</label>
+ </object>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="BUTTON_REMOVE">
+ <label>Remove</label>
+ </object>
+ <flag>wxEXPAND</flag>
+ </object>
+ </object>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="spacer">
+ <size>0,10</size>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStdDialogButtonSizer">
+ <object class="button">
+ <object class="wxButton" name="wxID_OK">
+ </object>
+ </object>
+ <object class="button">
+ <object class="wxButton" name="wxID_CANCEL">
+ </object>
+ </object>
+ </object>
+ <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ <size>350,300</size>
+ <title>Content</title>
+ <centered>1</centered>
+ <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
+ </object>
+ <object class="wxDialog" name="DIALOG_HELPTEXT">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <label>Value</label>
+ </object>
+ <flag>wxALL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="TEXT">
+ <style>wxTE_MULTILINE</style>
+ </object>
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ <orient>wxHORIZONTAL</orient>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <label>Tooltip</label>
+ </object>
+ <flag>wxALL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="TOOLTIP">
+ <size>250,100</size>
+ <style>wxTE_MULTILINE</style>
+ </object>
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <label>Help Text</label>
+ </object>
+ <flag>wxALL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="HELPTEXT">
+ <size>250,100</size>
+ <style>wxTE_MULTILINE</style>
+ </object>
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>5</border>
+ </object>
+ </object>
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStdDialogButtonSizer">
+ <object class="button">
+ <object class="wxButton" name="wxID_OK">
+ </object>
+ </object>
+ <object class="button">
+ <object class="wxButton" name="wxID_CANCEL">
+ </object>
+ </object>
+ </object>
+ <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
+ <border>10</border>
+ </object>
+ </object>
+ <title>Edit item</title>
+ <centered>1</centered>
+ <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
+ </object>
+</resource> \ No newline at end of file
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/__init__.py
new file mode 100644
index 0000000..6c958a6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/__init__.py
@@ -0,0 +1,18 @@
+"""
+Some useful tools and utilities for wxPython.
+"""
+
+
+# XRCed is purposfully left out so epydoc won't document it
+__all__ = [
+ 'dbg',
+ 'genaxmodule',
+ 'helpviewer',
+ 'img2img',
+ 'img2png',
+ 'img2py',
+ 'img2xpm',
+ ]
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/dbg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/dbg.py
new file mode 100644
index 0000000..959a347
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/dbg.py
@@ -0,0 +1,268 @@
+#----------------------------------------------------------------------------
+# Name: dbg.py
+# RCS-ID: $Id$
+# Author: Will Sadkin
+# Email: wsadkin@nameconnector.com
+# Created: 07/11/2002
+# Copyright: (c) 2002 by Will Sadkin, 2002
+# License: wxWindows license
+#----------------------------------------------------------------------------
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o V2.5 compatability update
+#
+
+"""
+This module provides a useful debugging framework that supports
+showing nesting of function calls and allows a program to contain
+lots of debugging print statements that can easily be turned on
+or off to debug the code. It also supports the ability to
+have each function indent the debugging statements contained
+within it, including those of any other function called within
+its scope, thus allowing you to see in what order functions are
+being called, and from where.
+
+This capability is particularly useful in wxPython applications,
+where exactly events occur that cause functions to be called is
+not entirely clear, and because wxPython programs can't be run
+from inside other debugging environments that have their own
+message loops.
+
+This module defines a Logger class, responsible for managing
+debugging output. Each Logger instance can be given a name
+at construction; if this is done, '<name>:' will precede each
+logging output made by that Logger instance.
+
+The log() function this class provides takes a set of positional
+arguments that are printed in order if debugging is enabled
+(just like print does), followed by a set of keyword arguments
+that control the behavior of the log() function itself on subsequent
+calls. The current keyword arguments are:
+
+indent
+ When set to a value of 1, this increments the current
+ indentation level, causing all subsequent dbg() outputs to be
+ indented by 3 more spaces. When set to a value of 0,
+ this process is reversed, causing the indent to decrease by
+ 3 spaces. The default indentation level is 0.
+
+enable
+ When set to a value of 1, this turns on dbg() output for
+ for program importing this module, until told to do otherwise.
+ When set to a value of 0, dbg output is turned off. (dbg
+ output is off by default.)
+
+suspend
+ When set to a value of 1, this increments the current
+ "suspension" level. This makes it possible for a function
+ to temporarily suspend its and any of its dependents'
+ potential outputs that use the same Logger instance.
+ When set to a value of 0, the suspension level is
+ decremented. When the value goes back to 0, potential
+ logging is resumed (actual output depends on the
+ "enable" status of the Logger instance in question.)
+
+wxlog
+ When set to a value of 1, the output will be sent to the
+ active wxLog target.
+
+stream
+ When set to a non-None value, the current output stream
+ (default of sys.stdout) is pushed onto a stack of streams,
+ and is replaced in the dbg system with the specified stream.
+ When called with a value of None, the previous stream will
+ be restored (if stacked.) If set to None without previously
+ changing it will result in no action being taken.
+
+You can also call the log function implicitly on the Logger
+instance, ie. you can type::
+
+ from wx.tools.dbg import Logger
+ dbg = Logger()
+ dbg('something to print')
+
+Using this fairly simple mechanism, it is possible to get fairly
+useful debugging output in a program. Consider the following
+code example:
+
+>>> d = {1:'a', 2:'dictionary', 3:'of', 4:'words'}
+>>> dbg = dbg.Logger('module')
+>>> dbg(enable=1)
+module: dbg enabled
+>>> def foo(d):
+... dbg('foo', indent=1)
+... bar(d)
+... dbg('end of foo', indent=0)
+...
+>>> def bar(d):
+... dbg('bar', indent=1)
+... dbg('contents of d:', indent=1)
+... l = d.items()
+... l.sort()
+... for key, value in l:
+... dbg('%d =' % key, value)
+... dbg(indent=0)
+... dbg('end of bar', indent=0)
+...
+>>> foo(d)
+module: foo
+ module: bar
+ module: contents of d:
+ module: 1 = a
+ module: 2 = dictionary
+ module: 3 = of
+ module: 4 = words
+ module: end of bar
+ module: end of foo
+>>>
+
+"""
+
+
+class Logger:
+ def __init__(self, name=None):
+ import sys
+ self.name = name
+ self._indent = 0 # current number of indentations
+ self._dbg = 0 # enable/disable flag
+ self._suspend = 0 # allows code to "suspend/resume" potential dbg output
+ self._wxLog = 0 # use wxLogMessage for debug output
+ self._outstream = sys.stdout # default output stream
+ self._outstream_stack = [] # for restoration of streams as necessary
+
+
+ def IsEnabled():
+ return self._dbg
+
+ def IsSuspended():
+ return _suspend
+
+
+ def log(self, *args, **kwargs):
+ """
+ This function provides a useful framework for generating
+ optional debugging output that can be displayed at an
+ arbitrary level of indentation.
+ """
+ if not self._dbg and not 'enable' in kwargs.keys():
+ return
+
+ if self._dbg and len(args) and not self._suspend:
+ # (emulate print functionality; handle unicode as best as possible:)
+ strs = []
+ for arg in args:
+ try:
+ strs.append(str(arg))
+ except:
+ strs.append(repr(arg))
+
+ output = ' '.join(strs)
+ if self.name: output = self.name+': ' + output
+ output = ' ' * 3 * self._indent + output
+
+ if self._wxLog:
+ wx.LogMessage(output)
+ else:
+ self._outstream.write(output + '\n')
+ self._outstream.flush()
+ # else do nothing
+
+ # post process args:
+ for kwarg, value in kwargs.items():
+ if kwarg == 'indent':
+ self.SetIndent(value)
+ elif kwarg == 'enable':
+ self.SetEnabled(value)
+ elif kwarg == 'suspend':
+ self.SetSuspend(value)
+ elif kwarg == 'wxlog':
+ self.SetWxLog(value)
+ elif kwarg == 'stream':
+ self.SetStream(value)
+
+ # aliases for the log function
+ dbg = log # backwards compatible
+ msg = log #
+ __call__ = log # this one lets you 'call' the instance directly
+
+
+ def SetEnabled(self, value):
+ if value:
+ old_dbg = self._dbg
+ self._dbg = 1
+ if not old_dbg:
+ self.dbg('dbg enabled')
+ else:
+ if self._dbg:
+ self.dbg('dbg disabled')
+ self._dbg = 0
+
+
+ def SetSuspend(self, value):
+ if value:
+ self._suspend += 1
+ elif self._suspend > 0:
+ self._suspend -= 1
+
+
+ def SetIndent(self, value):
+ if value:
+ self._indent += 1
+ elif self._indent > 0:
+ self._indent -= 1
+
+
+ def SetWxLog(self, value):
+ self._wxLog = value
+
+
+ def SetStream(self, value):
+ if value:
+ self._outstream_stack.append( self._outstream )
+ self._outstream = value
+ elif value is None and len(self._outstream_stack) > 0:
+ self._outstream = self._outstream_stack.pop(-1)
+
+
+#------------------------------------------------------------
+
+if __name__ == "__main__":
+ import sys
+ import wx
+
+ wx.Log_SetActiveTarget( wx.LogStderr() )
+ logger = Logger('module')
+ dbg = logger.dbg
+ dbg(enable=1)
+ logger('test __call__ interface')
+ dbg('testing wxLog output to stderr:', wxlog=1, indent=1)
+ dbg('1,2,3...')
+ dbg('testing wx.LogNull:')
+ devnull = wx.LogNull()
+ dbg('4,5,6...') # shouldn't print, according to doc...
+ del devnull
+ dbg('(resuming to wx.LogStdErr)', '7,8,9...', indent=0)
+ dbg('disabling wx.Log output, switching to stderr:')
+ dbg(wxlog=0, stream=sys.stderr)
+ dbg(logger._outstream, 'switching back to stdout:')
+ dbg(stream=None)
+ dbg(logger._outstream )
+ def foo(str):
+ dbg('foo:', indent=1)
+ dbg(str, indent=0)
+ foo('testing dbg inside function')
+ class bar(Logger):
+ def __init__(self, name):
+ Logger.__init__(self, name)
+ def enable(self, value):
+ self.dbg(enable=value)
+ def foo(self, str):
+ self.dbg('foo:', indent=1)
+ self.dbg(str, indent=0)
+ f = bar('class mixin')
+ f.foo("shouldn't print")
+ f.enable(1)
+ f.foo("should print")
+ dbg('test completed.', enable=0)
+ dbg('(double-checking ;-)')
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/genaxmodule.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/genaxmodule.py
new file mode 100644
index 0000000..e7e255a
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/genaxmodule.py
@@ -0,0 +1,46 @@
+"""
+
+
+When this script is run it will create a .py module (output to the
+current directory) containing a class derived from
+wx.activex.ActiveXWindow for the progID or CLSID given on the command
+line. By default the class name will be used as the module name as
+well, but this is just because I am lazy, not trying to define a
+standard or anything. Feel free to rename the module, I do.
+
+Usage:
+
+ python genax.py CLSID|progID className
+
+"""
+
+import wx
+import wx.activex
+import sys
+
+
+def main(args=None):
+ if not args:
+ args = sys.argv
+
+ if len(args) < 3:
+ print __doc__
+ sys.exit(1)
+
+ # unfortunatly we need to make an app, frame and an instance of
+ # the ActiceX control in order to get the TypeInfo about it...
+ app = wx.App()
+ f = wx.Frame(None, -1, "")
+ clsid = wx.activex.CLSID(args[1])
+ axw = wx.activex.ActiveXWindow(f, clsid)
+
+ wx.activex.GernerateAXModule(axw, args[2], '.', verbose=True)
+
+ # Cleanup
+ f.Close()
+ app.MainLoop()
+
+
+if __name__ == "__main__":
+ main(sys.argv)
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/helpviewer.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/helpviewer.py
new file mode 100644
index 0000000..2e41c19
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/helpviewer.py
@@ -0,0 +1,91 @@
+#----------------------------------------------------------------------
+# Name: wx.tools.helpviewer
+# Purpose: HTML Help viewer
+#
+# Author: Robin Dunn
+#
+# Created: 11-Dec-2002
+# RCS-ID: $Id$
+# Copyright: (c) 2002 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""
+helpviewer.py -- Displays HTML Help in a wxHtmlHelpController window.
+
+Usage:
+ helpviewer [--cache=path] helpfile [helpfile(s)...]
+
+ Where helpfile is the path to either a .hhp file or a .zip file
+ which contians a .hhp file. The .hhp files are the same as those
+ used by Microsoft's HTML Help Workshop for creating CHM files.
+"""
+
+
+import sys, os
+
+#---------------------------------------------------------------------------
+
+def makeOtherFrame(helpctrl):
+ import wx
+ parent = helpctrl.GetFrame()
+ otherFrame = wx.Frame(parent)
+
+
+def main(args=sys.argv):
+ if len(args) < 2:
+ print __doc__
+ return
+
+ args = args[1:]
+ cachedir = None
+ if args[0][:7] == '--cache':
+ cachedir = os.path.expanduser(args[0].split('=')[1])
+ args = args[1:]
+
+ if len(args) == 0:
+ print __doc__
+ return
+
+ import wx
+ import wx.html
+
+ app = wx.App()
+ #wx.Log.SetActiveTarget(wx.LogStderr())
+ wx.Log.SetLogLevel(wx.LOG_Error)
+
+ # Set up the default config so the htmlhelp frame can save its preferences
+ app.SetVendorName('wxWindows')
+ app.SetAppName('helpviewer')
+ cfg = wx.ConfigBase.Get()
+
+ # Add the Zip filesystem
+ wx.FileSystem.AddHandler(wx.ZipFSHandler())
+
+ # Create the viewer
+ helpctrl = wx.html.HtmlHelpController()
+ if cachedir:
+ helpctrl.SetTempDir(cachedir)
+
+ # and add the books
+ for helpfile in args:
+ print "Adding %s..." % helpfile
+ helpctrl.AddBook(helpfile, 1)
+
+ # The frame used by the HtmlHelpController is set to not prevent
+ # app exit, so in the case of a standalone helpviewer like this
+ # when the about box or search box is closed the help frame will
+ # be the only one left and the app will close unexpectedly. To
+ # work around this we'll create another frame that is never shown,
+ # but which will be closed when the helpviewer frame is closed.
+ wx.CallAfter(makeOtherFrame, helpctrl)
+
+ # start it up!
+ helpctrl.DisplayContents()
+ app.MainLoop()
+
+
+if __name__ == '__main__':
+ main()
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2img.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2img.py
new file mode 100644
index 0000000..14580f1
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2img.py
@@ -0,0 +1,90 @@
+#----------------------------------------------------------------------
+# Name: wx.tools.img2img
+# Purpose: Common routines for the image converter utilities.
+#
+# Author: Robin Dunn
+#
+# RCS-ID: $Id$
+# Copyright: (c) 2002 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o V2.5 compatability update
+#
+
+import getopt
+import glob
+import os
+import sys
+
+import wx
+
+def convert(file, maskClr, outputDir, outputName, outType, outExt):
+ if os.path.splitext(file)[1].lower() == ".ico":
+ icon = wx.Icon(file, wx.BITMAP_TYPE_ICO)
+ img = wx.BitmapFromIcon(icon)
+ else:
+ img = wx.Bitmap(file, wx.BITMAP_TYPE_ANY)
+
+ if not img.Ok():
+ return 0, file + " failed to load!"
+ else:
+ if maskClr:
+ om = img.GetMask()
+ mask = wx.Mask(img, maskClr)
+ img.SetMask(mask)
+ if om is not None:
+ om.Destroy()
+ if outputName:
+ newname = outputName
+ else:
+ newname = os.path.join(outputDir,
+ os.path.basename(os.path.splitext(file)[0]) + outExt)
+ if img.SaveFile(newname, outType):
+ return 1, file + " converted to " + newname
+ else:
+ img = wx.ImageFromBitmap(img)
+ if img.SaveFile(newname, outType):
+ return 1, "ok"
+ else:
+ return 0, file + " failed to save!"
+
+
+
+
+def main(args, outType, outExt, doc):
+ if not args or ("-h" in args):
+ print doc
+ return
+
+ outputDir = ""
+ maskClr = None
+ outputName = None
+
+ try:
+ opts, fileArgs = getopt.getopt(args, "m:n:o:")
+ except getopt.GetoptError:
+ print __doc__
+ return
+
+ for opt, val in opts:
+ if opt == "-m":
+ maskClr = val
+ elif opt == "-n":
+ outputName = val
+ elif opt == "-o":
+ outputDir = val
+
+ if not fileArgs:
+ print doc
+ return
+
+ for arg in fileArgs:
+ for file in glob.glob(arg):
+ if not os.path.isfile(file):
+ continue
+ ok, msg = convert(file, maskClr, outputDir, outputName,
+ outType, outExt)
+ print msg
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2png.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2png.py
new file mode 100644
index 0000000..5f71b40
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2png.py
@@ -0,0 +1,55 @@
+#----------------------------------------------------------------------
+# Name: wx.tools.img2png
+# Purpose: Convert an image to PNG format
+#
+# Author: Robin Dunn
+#
+# RCS-ID: $Id$
+# Copyright: (c) 2002 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o V2.5 compatability update
+#
+
+"""
+img2png.py -- convert several image formats to PNG format.
+
+Usage:
+
+ img2png.py [options] image_files...
+
+Options:
+
+ -o <dir> The directory to place the .png file(s), defaults to
+ the current directory.
+
+ -m <#rrggbb> If the original image has a mask or transparency defined
+ it will be used by default. You can use this option to
+ override the default or provide a new mask by specifying
+ a colour in the image to mark as transparent.
+
+ -n <name> A filename to write the .png data to. Defaults to the
+ basename of the image file + '.png' This option overrides
+ the -o option.
+"""
+
+
+import sys
+import wx
+import img2img
+
+app = None
+def main():
+ # some bitmap related things need to have a wxApp initialized...
+ if wx.GetApp() is None:
+ global app
+ app = wx.App()
+ img2img.main(sys.argv[1:], wx.BITMAP_TYPE_PNG, ".png", __doc__)
+
+if __name__ == '__main__':
+ main()
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2py.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2py.py
new file mode 100644
index 0000000..8299f76
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2py.py
@@ -0,0 +1,317 @@
+#----------------------------------------------------------------------
+# Name: wx.tools.img2py
+# Purpose: Convert an image to Python code.
+#
+# Author: Robin Dunn
+#
+# RCS-ID: $Id$
+# Copyright: (c) 2002 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+#
+# Changes:
+# - Cliff Wells <LogiplexSoftware@earthlink.net>
+# 20021206: Added catalog (-c) option.
+#
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+# V2.5 compatibility update
+#
+# 2/25/2007 - Gianluca Costa (archimede86@katamail.com)
+# -Refactorization of the script-creation code in a specific "img2py()" function
+# -Added regex parsing instead of module importing
+# -Added some "try/finally" statements
+# -Added default values as named constants
+# -Made some parts of code a bit easier to read
+# -Updated the module docstring
+# -Corrected a bug with EmptyIcon
+#
+# 11/26/2007 - Anthony Tuininga (anthony.tuininga@gmail.com)
+# -Use base64 encoding instead of simple repr
+# -Remove compression which doesn't buy anything in most cases and
+# costs more in many cases
+# -Use wx.lib.embeddedimage.PyEmbeddedImage class which has methods
+# rather than using standalone methods
+#
+
+
+
+"""
+img2py.py -- Convert an image to PNG format and embed it in a Python
+ module with appropriate code so it can be loaded into
+ a program at runtime. The benefit is that since it is
+ Python source code it can be delivered as a .pyc or
+ 'compiled' into the program using freeze, py2exe, etc.
+
+Usage:
+
+ img2py.py [options] image_file python_file
+
+Options:
+
+ -m <#rrggbb> If the original image has a mask or transparency defined
+ it will be used by default. You can use this option to
+ override the default or provide a new mask by specifying
+ a colour in the image to mark as transparent.
+
+ -n <name> Normally generic names (getBitmap, etc.) are used for the
+ image access functions. If you use this option you can
+ specify a name that should be used to customize the access
+ fucntions, (getNameBitmap, etc.)
+
+ -c Maintain a catalog of names that can be used to reference
+ images. Catalog can be accessed via catalog and
+ index attributes of the module.
+ If the -n <name> option is specified then <name>
+ is used for the catalog key and index value, otherwise
+ the filename without any path or extension is used
+ as the key.
+
+ -a This flag specifies that the python_file should be appended
+ to instead of overwritten. This in combination with -n will
+ allow you to put multiple images in one Python source file.
+
+ -i Also output a function to return the image as a wxIcon.
+
+ -f Generate code compatible with the old function interface.
+ (This option is ON by default in 2.8, use -F to turn off.)
+
+You can also import this module from your Python scripts, and use its img2py()
+function. See its docstring for more info.
+"""
+
+import base64
+import getopt
+import glob
+import os
+import re
+import sys
+import tempfile
+
+import wx
+import img2img
+
+try:
+ b64encode = base64.b64encode
+except AttributeError:
+ b64encode = base64.encodestring
+
+app = None
+DEFAULT_APPEND = False
+DEFAULT_COMPRESSED = True
+DEFAULT_MASKCLR = None
+DEFAULT_IMGNAME = ""
+DEFAULT_ICON = False
+DEFAULT_CATALOG = False
+DEFAULT_COMPATIBLE = False
+
+# THIS IS USED TO IDENTIFY, IN THE GENERATED SCRIPT, LINES IN THE FORM
+# "index.append('Image name')"
+indexPattern = re.compile(r"\s*index.append\('(.+)'\)\s*")
+
+
+def convert(fileName, maskClr, outputDir, outputName, outType, outExt):
+ # if the file is already the right type then just use it directly
+ if maskClr == DEFAULT_MASKCLR and fileName.upper().endswith(outExt.upper()):
+ if outputName:
+ newname = outputName
+ else:
+ newname = os.path.join(outputDir,
+ os.path.basename(os.path.splitext(fileName)[0]) + outExt)
+ file(newname, "wb").write(file(fileName, "rb").read())
+ return 1, "ok"
+
+ else:
+ return img2img.convert(fileName, maskClr, outputDir, outputName, outType, outExt)
+
+
+def img2py(image_file, python_file,
+ append=DEFAULT_APPEND,
+ compressed=DEFAULT_COMPRESSED,
+ maskClr=DEFAULT_MASKCLR,
+ imgName=DEFAULT_IMGNAME,
+ icon=DEFAULT_ICON,
+ catalog=DEFAULT_CATALOG,
+ functionCompatible=DEFAULT_COMPATIBLE,
+ functionCompatibile=-1, # typo version for backward compatibility
+ ):
+ """
+ Converts an image file to a data structure written in a Python file
+ --image_file: string; the path of the source image file
+ --python_file: string; the path of the destination python file
+ --other arguments: they are equivalent to the command-line arguments
+ """
+
+ # was the typo version used?
+ if functionCompatibile != -1:
+ functionCompatible = functionCompatibile
+
+ global app
+ if not wx.GetApp():
+ app = wx.App()
+
+ # convert the image file to a temporary file
+ tfname = tempfile.mktemp()
+ try:
+ ok, msg = convert(image_file, maskClr, None, tfname, wx.BITMAP_TYPE_PNG, ".png")
+ if not ok:
+ print msg
+ return
+
+ lines = []
+ data = b64encode(open(tfname, "rb").read())
+ while data:
+ part = data[:72]
+ data = data[72:]
+ output = ' "%s"' % part
+ if not data:
+ output += ")"
+ lines.append(output)
+ data = "\n".join(lines)
+ finally:
+ if os.path.exists(tfname):
+ os.remove(tfname)
+
+ old_index = []
+ if catalog and append and python_file != '-':
+ # check to see if catalog exists already (file may have been created
+ # with an earlier version of img2py or without -c option)
+ pyPath, pyFile = os.path.split(python_file)
+
+ append_catalog = True
+
+ sourcePy = open(python_file, "r")
+ try:
+ for line in sourcePy:
+
+ if line == "catalog = {}\n":
+ append_catalog = False
+ else:
+ lineMatcher = indexPattern.match(line)
+ if lineMatcher:
+ old_index.append(lineMatcher.groups()[0])
+ finally:
+ sourcePy.close()
+
+ if append_catalog:
+ out = open(python_file, "a")
+ try:
+ out.write("\n# ***************** Catalog starts here *******************")
+ out.write("\n\ncatalog = {}\n")
+ out.write("index = []\n\n")
+ finally:
+ out.close()
+
+ if python_file == '-':
+ out = sys.stdout
+ elif append:
+ out = open(python_file, "a")
+ else:
+ out = open(python_file, "w")
+
+ try:
+ imgPath, imgFile = os.path.split(image_file)
+ if not imgName:
+ imgName = os.path.splitext(imgFile)[0]
+ print "\nWarning: -n not specified. Using filename (%s) for name of image and/or catalog entry." % imgName
+
+ out.write("#" + "-" * 70 + "\n")
+ if not append:
+ out.write("# This file was generated by %s\n#\n" % sys.argv[0])
+ out.write("from wx.lib.embeddedimage import PyEmbeddedImage\n\n")
+ if catalog:
+ out.write("catalog = {}\n")
+ out.write("index = []\n\n")
+
+ letters = []
+ for letter in imgName:
+ if not letter.isalnum():
+ letter = "_"
+ letters.append(letter)
+ if not letters[0].isalpha() and letters[0] != '_':
+ letters.insert(0, "_")
+ varName = "".join(letters)
+
+ out.write("%s = PyEmbeddedImage(\n%s\n" % (varName, data))
+
+ if catalog:
+ if imgName in old_index:
+ print "Warning: %s already in catalog." % imgName
+ print " Only the last entry will be accessible.\n"
+ old_index.append(imgName)
+ out.write("index.append('%s')\n" % imgName)
+ out.write("catalog['%s'] = %s\n" % (imgName, varName))
+
+ if functionCompatible:
+ out.write("get%sData = %s.GetData\n" % (varName, varName))
+ out.write("get%sImage = %s.GetImage\n" % (varName, varName))
+ out.write("get%sBitmap = %s.GetBitmap\n" % (varName, varName))
+ if icon:
+ out.write("get%sIcon = %s.GetIcon\n" % (varName, varName))
+
+ out.write("\n")
+
+ if imgName:
+ n_msg = ' using "%s"' % imgName
+ else:
+ n_msg = ""
+
+ if maskClr:
+ m_msg = " with mask %s" % maskClr
+ else:
+ m_msg = ""
+
+ print "Embedded %s%s into %s%s" % (image_file, n_msg, python_file, m_msg)
+ finally:
+ if python_file != '-':
+ out.close()
+
+
+
+def main(args=None):
+ if not args:
+ args = sys.argv[1:]
+
+ if not args or ("-h" in args):
+ print __doc__
+ return
+
+ append = DEFAULT_APPEND
+ compressed = DEFAULT_COMPRESSED
+ maskClr = DEFAULT_MASKCLR
+ imgName = DEFAULT_IMGNAME
+ icon = DEFAULT_ICON
+ catalog = DEFAULT_CATALOG
+ compatible = DEFAULT_COMPATIBLE
+
+ try:
+ opts, fileArgs = getopt.getopt(args, "auicfFn:m:")
+ except getopt.GetoptError:
+ print __doc__
+ return
+
+ for opt, val in opts:
+ if opt == "-a":
+ append = True
+ elif opt == "-n":
+ imgName = val
+ elif opt == "-m":
+ maskClr = val
+ elif opt == "-i":
+ icon = True
+ elif opt == "-c":
+ catalog = True
+ elif opt == "-f":
+ compatible = True
+ elif opt == "-F":
+ compatible = False
+
+ if len(fileArgs) != 2:
+ print __doc__
+ return
+
+ image_file, python_file = fileArgs
+ img2py(image_file, python_file,
+ append, compressed, maskClr, imgName, icon, catalog, compatible)
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2xpm.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2xpm.py
new file mode 100644
index 0000000..eb39bb7
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/img2xpm.py
@@ -0,0 +1,55 @@
+#----------------------------------------------------------------------
+# Name: wx.tools.img2xpm
+# Purpose: Convert an image to XPM format
+#
+# Author: Robin Dunn
+#
+# RCS-ID: $Id$
+# Copyright: (c) 2002 by Total Control Software
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+# 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+#
+# o V2.5 compatability update
+#
+
+"""
+img2xpm.py -- convert several image formats to XPM.
+
+Usage:
+
+ img2xpm.py [options] image_files...
+
+Options:
+
+ -o <dir> The directory to place the .xpm file(s), defaults to
+ the current directory.
+
+ -m <#rrggbb> If the original image has a mask or transparency defined
+ it will be used by default. You can use this option to
+ override the default or provide a new mask by specifying
+ a colour in the image to mark as transparent.
+
+ -n <name> A filename to write the .xpm data to. Defaults to the
+ basename of the image file + '.xpm' This option overrides
+ the -o option.
+"""
+
+import sys
+import wx
+import img2img
+
+app = None
+def main():
+ # some bitmap related things need to have a wxApp initialized...
+ if wx.GetApp() is None:
+ global app
+ app = wx.App()
+ img2img.main(sys.argv[1:], wx.BITMAP_TYPE_XPM, ".xpm", __doc__)
+
+
+if __name__ == '__main__':
+ main()
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/pywxrc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/pywxrc.py
new file mode 100644
index 0000000..9b1a9b6
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/pywxrc.py
@@ -0,0 +1,933 @@
+#----------------------------------------------------------------------
+# Name: wx.tools.pywxrc
+# Purpose: XML resource compiler
+#
+# Author: Robin Dunn
+# Based on wxrc.cpp by Vaclav Slavik, Eduardo Marques
+# Ported to Python in order to not require yet another
+# binary in wxPython distributions
+#
+# Massive rework by Eli Golovinsky
+#
+# Editable blocks by Roman Rolinsky
+#
+# RCS-ID: $Id$
+# Copyright: (c) 2004 by Total Control Software, 2000 Vaclav Slavik
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+"""
+pywxrc -- Python XML resource compiler
+ (see http://wiki.wxpython.org/index.cgi/pywxrc for more info)
+
+Usage: python pywxrc.py -h
+ python pywxrc.py [-p] [-g] [-e] [-v] [-o filename] xrc input files...
+
+ -h, --help show help message
+ -p, --python generate python module
+ -g, --gettext output list of translatable strings (may be combined with -p)
+ -e, --embed embed XRC resources in the output file
+ -v, --novar suppress default assignment of variables
+ -o, --output output filename, or - for stdout
+"""
+
+import sys, os, getopt, glob, re, cPickle
+import xml.dom.minidom as minidom
+import wx
+import wx.xrc
+
+#----------------------------------------------------------------------
+
+reBeginBlock = re.compile(r'^#!XRCED:begin-block:(\S+)')
+reEndBlock = re.compile(r'^#!XRCED:end-block:(\S+)')
+
+class PythonTemplates:
+ FILE_HEADER = """\
+# This file was automatically generated by pywxrc.
+# -*- coding: UTF-8 -*-
+
+import wx
+import wx.xrc as xrc
+
+__res = None
+
+def get_resources():
+ \"\"\" This function provides access to the XML resources in this module.\"\"\"
+ global __res
+ if __res == None:
+ __init_resources()
+ return __res
+
+"""
+
+ CLASS_HEADER = """\
+class xrc%(windowName)s(wx.%(windowClass)s):
+#!XRCED:begin-block:xrc%(windowName)s.PreCreate
+ def PreCreate(self, pre):
+ \"\"\" This function is called during the class's initialization.
+
+ Override it for custom setup before the window is created usually to
+ set additional window styles using SetWindowStyle() and SetExtraStyle().
+ \"\"\"
+ pass
+
+#!XRCED:end-block:xrc%(windowName)s.PreCreate
+
+ def __init__(self, parent):
+ # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation)
+ pre = wx.Pre%(windowClass)s()
+ self.PreCreate(pre)
+ get_resources().LoadOn%(windowClass)s(pre, parent, "%(windowName)s")
+ self.PostCreate(pre)
+
+ # Define variables for the controls, bind event handlers
+"""
+
+ SUBCLASS_HEADER = """\
+class %(subclass)s(wx.%(windowClass)s):
+ def __init__(self):
+ # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation)
+ pre = wx.Pre%(windowClass)s()
+ self.PostCreate(pre)
+ self.Bind(wx.EVT_WINDOW_CREATE, self.OnCreate)
+
+#!XRCED:begin-block:%(subclass)s._PostInit
+ def _PostInit(self):
+ \"\"\" This function is called after the subclassed object is created.
+
+ Override it for custom setup before the window is created usually to
+ set additional window styles using SetWindowStyle() and SetExtraStyle().
+ \"\"\"
+ pass
+#!XRCED:end-block:%(subclass)s._PostInit
+
+ def OnCreate(self, evt):
+ self.Unbind(wx.EVT_WINDOW_CREATE)
+ self._PostInit()
+"""
+
+ CREATE_WIDGET_VAR = """\
+ self.%(widgetName)s = xrc.XRCCTRL(self, \"%(widgetName)s\")
+"""
+
+ FRAME_MENUBAR_VAR = """\
+ self.%(widgetName)s = self.GetMenuBar()
+"""
+
+ FRAME_MENUBAR_MENUITEM_VAR = """\
+ self.%(widgetName)s = self.GetMenuBar().FindItemById(xrc.XRCID(\"%(widgetName)s\"))
+"""
+
+ FRAME_MENUBAR_MENU_VAR = """\
+ idx = self.GetMenuBar().FindMenu(\"%(label)s\")
+ if idx != wx.NOT_FOUND:
+ self.%(widgetName)s = self.GetMenuBar().GetMenu(idx)
+ else:
+ self.%(widgetName)s = self.GetMenuBar().FindItemById(xrc.XRCID(\"%(widgetName)s\")).GetSubMenu()
+"""
+
+
+ MENUBAR_MENUITEM_VAR = """\
+ self.%(widgetName)s = self.FindItemById(xrc.XRCID(\"%(widgetName)s\"))
+"""
+
+ MENUBAR_MENU_VAR = """\
+ idx = self.FindMenu(\"%(label)s\")
+ if idx != wx.NOT_FOUND:
+ self.%(widgetName)s = self.GetMenu(idx)
+ else:
+ self.%(widgetName)s = self.FindItemById(xrc.XRCID(\"%(widgetName)s\")).GetSubMenu()
+"""
+
+ MENU_MENUITEM_VAR = """\
+ self.%(widgetName)s = self.FindItemById(xrc.XRCID(\"%(widgetName)s\"))
+"""
+
+ MENU_MENU_VAR = """\
+ self.%(widgetName)s = self.FindItemById(xrc.XRCID(\"%(widgetName)s\")).GetSubMenu()
+"""
+
+ FRAME_TOOLBAR_VAR = """\
+ self.%(widgetName)s = self.GetToolBar()
+"""
+
+ FRAME_TOOLBAR_TOOL_VAR = """\
+ self.%(widgetName)s = self.GetToolBar().FindById(xrc.XRCID(\"%(widgetName)s\"))
+"""
+
+ TOOLBAR_TOOL_VAR = """\
+ self.%(widgetName)s = self.FindById(xrc.XRCID(\"%(widgetName)s\"))
+"""
+
+ BIND_WIDGET_EVENT = """\
+ self.Bind(wx.%(event)s, self.%(eventHandler)s, %(eventObject)s)
+"""
+
+ BIND_EVENT = """\
+ self.Bind(wx.%(event)s, self.%(eventHandler)s)
+"""
+
+ CREATE_EVENT_HANDLER = """\
+#!XRCED:begin-block:xrc%(windowName)s.%(eventHandler)s
+ def %(eventHandler)s(self, evt):
+ # Replace with event handler code
+ print \"%(eventHandler)s()\"
+#!XRCED:end-block:xrc%(windowName)s.%(eventHandler)s
+"""
+
+ MENU_CLASS_HEADER = """\
+class xrc%(windowName)s(wx.%(windowClass)s):
+ def __init__(self):
+ pre = get_resources().LoadMenu("%(windowName)s")
+
+ # This is a copy of Robin's PostCreate voodoo magic in wx.Window that
+ # relinks the self object with the menu object.
+ self.this = pre.this
+ self.thisown = pre.thisown
+ pre.thisown = 0
+ if hasattr(self, '_setOORInfo'):
+ self._setOORInfo(self)
+
+ # Define variables for the menu items
+"""
+
+ MENUBAR_CLASS_HEADER = """\
+class xrc%(windowName)s(wx.%(windowClass)s):
+ def __init__(self):
+ pre = get_resources().LoadMenuBar("%(windowName)s")
+ self.PostCreate(pre)
+
+ # Define variables for the menu items
+"""
+
+ TOOLBAR_CLASS_HEADER = """\
+class xrc%(windowName)s(wx.%(windowClass)s):
+ def __init__(self, parent):
+ pre = get_resources().LoadToolBar(parent, "%(windowName)s")
+ self.PostCreate(pre)
+
+ # Define variables for the toolbar items
+"""
+
+ INIT_RESOURE_HEADER = """\
+# ------------------------ Resource data ----------------------
+
+def __init_resources():
+ global __res
+ __res = xrc.EmptyXmlResource()
+"""
+
+ LOAD_RES_FILE = """\
+ __res.Load('%(resourceFilename)s')"""
+
+ FILE_AS_STRING = """\
+ %(filename)s = '''\\
+%(fileData)s'''
+
+"""
+
+ PREPARE_MEMFS = """\
+ wx.FileSystem.AddHandler(wx.MemoryFSHandler())
+"""
+
+ ADD_FILE_TO_MEMFS = """\
+ wx.MemoryFSHandler.AddFile('XRC/%(memoryPath)s/%(filename)s', %(filename)s)
+"""
+
+ LOAD_RES_MEMFS = """\
+ __res.Load('memory:XRC/%(memoryPath)s/%(resourceFilename)s')
+"""
+
+ GETTEXT_DUMMY_FUNC = """
+# ----------------------- Gettext strings ---------------------
+
+def __gettext_strings():
+ # This is a dummy function that lists all the strings that are used in
+ # the XRC file in the _("a string") format to be recognized by GNU
+ # gettext utilities (specificaly the xgettext utility) and the
+ # mki18n.py script. For more information see:
+ # http://wiki.wxpython.org/index.cgi/Internationalization
+
+ def _(str): pass
+
+%s
+"""
+
+#----------------------------------------------------------------------
+
+class XmlResourceCompiler:
+
+ templates = PythonTemplates()
+
+ """This class generates Python code from XML resource files (XRC)."""
+
+ def MakePythonModule(self, inputFiles, outputFilename,
+ embedResources=False, generateGetText=False,
+ assignVariables=True):
+
+ self.blocks = {}
+ self.outputFilename = outputFilename
+ outputFile = self._OpenOutputFile(outputFilename)
+ self.assignVariables = assignVariables
+
+ classes = []
+ subclasses = []
+ resources = []
+ gettextStrings = []
+
+ # process all the inputFiles, collecting the output data
+ for inFile in inputFiles:
+ resourceDocument = minidom.parse(inFile)
+ subclasses.append(self.GenerateSubclasses(resourceDocument))
+ classes.append(self.GenerateClasses(resourceDocument))
+
+ if embedResources:
+ res = self.GenerateInitResourcesEmbedded(inFile, resourceDocument)
+ else:
+ res = self.GenerateInitResourcesFile(inFile, resourceDocument)
+ resources.append(res)
+
+ if generateGetText:
+ gettextStrings += self.FindStringsInNode(resourceDocument.firstChild)
+
+ # now write it all out
+ print >>outputFile, self.templates.FILE_HEADER
+
+ # Note: Technically it is not legal to have anything other
+ # than ascii for class and variable names, but since the user
+ # can create the XML with non-ascii names we'll go ahead and
+ # allow for it here, and then let Python complain about it
+ # later when they try to run the program.
+ if subclasses:
+ subclasses = self.ReplaceBlocks(u"\n".join(subclasses))
+ print >>outputFile, subclasses.encode("UTF-8")
+ if classes:
+ classes = self.ReplaceBlocks(u"\n".join(classes))
+ print >>outputFile, classes.encode("UTF-8")
+
+ print >>outputFile, self.templates.INIT_RESOURE_HEADER
+ if embedResources:
+ print >>outputFile, self.templates.PREPARE_MEMFS
+ resources = u"\n".join(resources)
+ print >>outputFile, resources.encode("UTF-8")
+
+ if generateGetText:
+ # These have already been converted to utf-8...
+ gettextStrings = [' _("%s")' % s for s in gettextStrings]
+ gettextStrings = "\n".join(gettextStrings)
+ print >>outputFile, self.templates.GETTEXT_DUMMY_FUNC % gettextStrings
+
+ #-------------------------------------------------------------------
+
+ def MakeGetTextOutput(self, inputFiles, outputFilename):
+ """
+ Just output the gettext strings by themselves, with no other
+ code generation.
+ """
+ outputFile = self._OpenOutputFile(outputFilename)
+ for inFile in inputFiles:
+ resourceDocument = minidom.parse(inFile)
+ resource = resourceDocument.firstChild
+ strings = self.FindStringsInNode(resource)
+ strings = ['_("%s");' % s for s in strings]
+ print >>outputFile, "\n".join(strings)
+
+ #-------------------------------------------------------------------
+
+ def GenerateClasses(self, resourceDocument):
+ outputList = []
+
+ resource = resourceDocument.firstChild
+ topWindows = [e for e in resource.childNodes
+ if e.nodeType == e.ELEMENT_NODE and e.tagName == "object" \
+ and not e.getAttribute('subclass')]
+
+ # Generate a class for each top-window object (Frame, Panel, Dialog, etc.)
+ for topWindow in topWindows:
+ windowClass = topWindow.getAttribute("class")
+ windowClass = re.sub("^wx", "", windowClass)
+ windowName = topWindow.getAttribute("name")
+ if not windowName: continue
+
+ if windowClass in ["MenuBar"]:
+ genfunc = self.GenerateMenuBarClass
+ elif windowClass in ["Menu"]:
+ genfunc = self.GenerateMenuClass
+ elif windowClass in ["ToolBar"]:
+ genfunc = self.GenerateToolBarClass
+ else:
+ genfunc = self.GenerateWidgetClass
+
+ vars = []
+ outputList += genfunc(windowClass, windowName, topWindow, vars)
+ outputList.append('\n')
+
+ outputList += self.GenerateEventHandlers(windowClass, windowName, topWindow, vars)
+
+ return "".join(outputList)
+
+ #-------------------------------------------------------------------
+
+ def CheckAssignVar(self, widget):
+ if self.assignVariables: return True # assign_var override mode
+ assign_var = False
+ for node in widget.getElementsByTagName("XRCED"):
+ if node.parentNode is widget:
+ try:
+ elem = node.getElementsByTagName("assign_var")[0]
+ except IndexError:
+ continue
+ if elem.childNodes:
+ ch = elem.childNodes[0]
+ if ch.nodeType == ch.TEXT_NODE and bool(ch.nodeValue):
+ assign_var = True
+ return assign_var
+
+
+ def GenerateMenuBarClass(self, windowClass, windowName, topWindow, vars):
+ outputList = []
+
+ # output the header
+ outputList.append(self.templates.MENUBAR_CLASS_HEADER % locals())
+
+ # create an attribute for menus and menu items that have names
+ for widget in topWindow.getElementsByTagName("object"):
+ if not self.CheckAssignVar(widget): continue
+ widgetClass = widget.getAttribute("class")
+ widgetClass = re.sub("^wx", "", widgetClass)
+ widgetName = widget.getAttribute("name")
+ if widgetName != "" and widgetClass != "":
+ vars.append(widgetName)
+ if widgetClass == "MenuItem":
+ outputList.append(self.templates.MENUBAR_MENUITEM_VAR % locals())
+ elif widgetClass == "Menu":
+ label = widget.getElementsByTagName("label")[0]
+ label = label.childNodes[0].data
+ outputList.append(self.templates.MENUBAR_MENU_VAR % locals())
+ else:
+ raise RuntimeError("Unexpected widgetClass for MenuBar: %s" % widgetClass)
+
+ return outputList
+
+
+ def GenerateMenuClass(self, windowClass, windowName, topWindow, vars):
+ outputList = []
+
+ # output the header
+ outputList.append(self.templates.MENU_CLASS_HEADER % locals())
+ for widget in topWindow.getElementsByTagName("object"):
+ if not self.CheckAssignVar(widget): continue
+ widgetClass = widget.getAttribute("class")
+ widgetClass = re.sub("^wx", "", widgetClass)
+ widgetName = widget.getAttribute("name")
+ if widgetName != "" and widgetClass != "":
+ vars.append(widgetName)
+ if widgetClass == "MenuItem":
+ outputList.append(self.templates.MENU_MENUITEM_VAR % locals())
+ elif widgetClass == "Menu":
+ label = widget.getElementsByTagName("label")[0]
+ label = label.childNodes[0].data
+ outputList.append(self.templates.MENU_MENU_VAR % locals())
+ else:
+ raise RuntimeError("Unexpected widgetClass for Menu: %s" % widgetClass)
+
+ return outputList
+
+
+ def GenerateToolBarClass(self, windowClass, windowName, topWindow, vars):
+ outputList = []
+
+ # output the header
+ outputList.append(self.templates.TOOLBAR_CLASS_HEADER % locals())
+
+ # create an attribute for menus and menu items that have names
+ for widget in topWindow.getElementsByTagName("object"):
+ if not self.CheckAssignVar(widget): continue
+ widgetClass = widget.getAttribute("class")
+ widgetClass = re.sub("^wx", "", widgetClass)
+ widgetName = widget.getAttribute("name")
+ if widgetName != "" and widgetClass != "":
+ vars.append(widgetName)
+ if widgetClass == "tool":
+ outputList.append(self.templates.TOOLBAR_TOOL_VAR % locals())
+ else:
+ raise RuntimeError("Unexpected widgetClass for ToolBar: %s" % widgetClass)
+
+ return outputList
+
+
+ def GenerateWidgetClass(self, windowClass, windowName, topWindow, vars):
+ outputList = []
+
+ # output the header
+ outputList.append(self.templates.CLASS_HEADER % locals())
+
+ # Generate an attribute for each named item in the container
+ for widget in topWindow.getElementsByTagName("object"):
+ if not self.CheckAssignVar(widget): continue
+ widgetClass = widget.getAttribute("class")
+ widgetClass = re.sub("^wx", "", widgetClass)
+ widgetName = widget.getAttribute("name")
+ if widgetName != "" and widgetClass != "":
+ vars.append(widgetName)
+ if widgetClass not in \
+ ['tool', 'unknown', 'notebookpage', 'separator',
+ 'sizeritem', 'Menu', 'MenuBar', 'MenuItem']:
+ outputList.append(self.templates.CREATE_WIDGET_VAR % locals())
+ elif widgetClass == "MenuBar":
+ outputList.append(self.templates.FRAME_MENUBAR_VAR % locals())
+ elif widgetClass == "MenuItem":
+ outputList.append(self.templates.FRAME_MENUBAR_MENUITEM_VAR % locals())
+ elif widgetClass == "Menu":
+ label = widget.getElementsByTagName("label")[0]
+ label = label.childNodes[0].data
+ outputList.append(self.templates.FRAME_MENUBAR_MENU_VAR % locals())
+ elif widgetClass == "ToolBar":
+ outputList.append(self.templates.FRAME_TOOLBAR_VAR % locals())
+ elif widgetClass == "tool":
+ outputList.append(self.templates.FRAME_TOOLBAR_TOOL_VAR % locals())
+
+ return outputList
+
+ #-------------------------------------------------------------------
+
+ def GenerateSubclasses(self, resourceDocument):
+ outputList = []
+
+ objectNodes = resourceDocument.getElementsByTagName("object")
+ subclasses = set()
+ bases = {}
+ baseName = os.path.splitext(self.outputFilename)[0]
+ for node in objectNodes:
+ subclass = node.getAttribute('subclass')
+ if subclass:
+ module = subclass[:subclass.find('.')]
+ if module != baseName: continue
+ klass = node.getAttribute("class")
+ if subclass not in subclasses:
+ subclasses.add(subclass)
+ bases[subclass] = klass
+ else:
+ if klass != bases[subclass]:
+ print 'pywxrc: error: conflicting base classes for subclass %(subclass)s' \
+ % subclass
+
+ # Generate subclasses
+ for subclass in subclasses:
+ windowClass = bases[subclass]
+ subclass = re.sub("^\S+\.", "", subclass)
+ windowClass = re.sub("^wx", "", windowClass)
+ outputList.append(self.templates.SUBCLASS_HEADER % locals())
+ outputList.append('\n')
+
+ return "".join(outputList)
+
+ #-------------------------------------------------------------------
+
+ def GenerateEventHandlers(self, windowClass, windowName, topWindow, vars):
+ outputList = []
+
+ # Generate child event handlers
+ eventHandlers = []
+ for elem in topWindow.getElementsByTagName("XRCED"):
+ try:
+ eventNode = elem.getElementsByTagName("events")[0]
+ except IndexError:
+ continue
+ events = eventNode.childNodes[0].data.split('|')
+ for event in events:
+ if elem.parentNode is topWindow:
+ eventHandler = "On%s" % event[4:].capitalize()
+ outputList.append(self.templates.BIND_EVENT % locals())
+ eventHandlers.append(eventHandler)
+ else:
+ widget = elem.parentNode
+ widgetClass = widget.getAttribute("class")
+ widgetClass = re.sub("^wx", "", widgetClass)
+ widgetName = widget.getAttribute("name")
+ if not widgetName or not widgetClass: continue
+ eventObject = None
+ if widgetClass == "MenuItem" and windowClass != "MenuBar":
+ if widgetName[:2] == "wx":
+ eventObject = 'id=wx.%s' % re.sub("^wx", "", widgetName)
+ eventHandler = "On%s_%s" % (event[4:].capitalize(), widgetName)
+ if widgetName in vars: eventObject = "self.%s" % widgetName
+ else:
+ eventHandler = "On%s_%s" % (event[4:].capitalize(), widgetName)
+ if widgetName in vars: eventObject = "self.%s" % widgetName
+ if not eventObject:
+ eventObject = "id=xrc.XRCID('%s')" % widgetName
+ outputList.append(self.templates.BIND_WIDGET_EVENT % locals())
+ eventHandlers.append(eventHandler)
+ outputList.append("\n")
+
+ for eventHandler in eventHandlers:
+ block = "xrc%(windowName)s.%(eventHandler)s" % locals()
+ try:
+ outputList.append(self.blocks[block])
+ except KeyError:
+ outputList.append(self.templates.CREATE_EVENT_HANDLER % locals())
+ outputList.append("\n")
+
+ outputList.append("\n")
+ return "".join(outputList)
+
+ #-------------------------------------------------------------------
+
+ def GenerateInitResourcesEmbedded(self, resourceFilename, resourceDocument):
+ outputList = []
+ files = []
+
+ resourcePath = os.path.split(resourceFilename)[0]
+ memoryPath = self.GetMemoryFilename(os.path.splitext(os.path.split(resourceFilename)[1])[0])
+ resourceFilename = self.GetMemoryFilename(os.path.split(resourceFilename)[1])
+
+ self.ReplaceFilenamesInXRC(resourceDocument.firstChild, files, resourcePath)
+
+ filename = resourceFilename
+ fileData = resourceDocument.toxml() # what about this? encoding=resourceDocument.encoding)
+ outputList.append(self.templates.FILE_AS_STRING % locals())
+
+ for f in files:
+ filename = self.GetMemoryFilename(f)
+ fileData = self.FileToString(os.path.join(resourcePath, f))
+ outputList.append(self.templates.FILE_AS_STRING % locals())
+
+ for f in [resourceFilename] + files:
+ filename = self.GetMemoryFilename(f)
+ outputList.append(self.templates.ADD_FILE_TO_MEMFS % locals())
+
+ outputList.append(self.templates.LOAD_RES_MEMFS % locals())
+
+ return "".join(outputList)
+
+ #-------------------------------------------------------------------
+
+ def GenerateInitResourcesFile(self, resourceFilename, resourceDocument):
+ # take only the filename portion out of resourceFilename
+ resourceFilename = os.path.split(resourceFilename)[1]
+ outputList = []
+ outputList.append(self.templates.LOAD_RES_FILE % locals())
+ return "".join(outputList)
+
+ #-------------------------------------------------------------------
+
+ def GetMemoryFilename(self, filename):
+ # Remove special chars from the filename
+ return re.sub(r"[^A-Za-z0-9_]", "_", filename)
+
+ #-------------------------------------------------------------------
+
+ def FileToString(self, filename):
+ outputList = []
+
+ buffer = open(filename, "rb").read()
+ fileLen = len(buffer)
+
+ linelng = 0
+ for i in xrange(fileLen):
+ s = buffer[i]
+ c = ord(s)
+ if s == '\n':
+ tmp = s
+ linelng = 0
+ elif c < 32 or c > 127 or s == "'":
+ tmp = "\\x%02x" % c
+ elif s == "\\":
+ tmp = "\\\\"
+ else:
+ tmp = s
+
+ if linelng > 70:
+ linelng = 0
+ outputList.append("\\\n")
+
+ outputList.append(tmp)
+ linelng += len(tmp)
+
+ return "".join(outputList)
+
+ #-------------------------------------------------------------------
+
+ def NodeContainsFilename(self, node):
+ """ Does 'node' contain filename information at all? """
+
+ # Any bitmaps:
+ if node.nodeName == "bitmap":
+ return True
+
+ if node.nodeName == "icon":
+ return True
+
+ # URLs in wxHtmlWindow:
+ if node.nodeName == "url":
+ return True
+
+ # wxBitmapButton:
+ parent = node.parentNode
+ if parent.__class__ != minidom.Document and \
+ parent.getAttribute("class") == "wxBitmapButton" and \
+ (node.nodeName == "focus" or node.nodeName == "disabled" or
+ node.nodeName == "selected"):
+ return True
+
+ # wxBitmap or wxIcon toplevel resources:
+ if node.nodeName == "object":
+ klass = node.getAttribute("class")
+ if klass == "wxBitmap" or klass == "wxIcon":
+ return True
+
+ return False
+
+ #-------------------------------------------------------------------
+
+ def ReplaceFilenamesInXRC(self, node, files, resourcePath):
+ """ Finds all files mentioned in resource file, e.g. <bitmap>filename</bitmap>
+ and replaces them with the memory filenames.
+
+ Fills a list of the filenames found."""
+
+ # Is 'node' XML node element?
+ if node is None: return
+ if node.nodeType != minidom.Document.ELEMENT_NODE: return
+
+ containsFilename = self.NodeContainsFilename(node);
+
+ for n in node.childNodes:
+
+ if (containsFilename and
+ (n.nodeType == minidom.Document.TEXT_NODE or
+ n.nodeType == minidom.Document.CDATA_SECTION_NODE)):
+
+ filename = n.nodeValue
+ memoryFilename = self.GetMemoryFilename(filename)
+ n.nodeValue = memoryFilename
+
+ if filename not in files:
+ files.append(filename)
+
+ # Recurse into children
+ if n.nodeType == minidom.Document.ELEMENT_NODE:
+ self.ReplaceFilenamesInXRC(n, files, resourcePath);
+
+ #-------------------------------------------------------------------
+
+ def FindStringsInNode(self, parent):
+ def is_number(st):
+ try:
+ i = int(st)
+ return True
+ except ValueError:
+ return False
+
+ strings = []
+ if parent is None:
+ return strings;
+
+ for child in parent.childNodes:
+ if ((parent.nodeType == parent.ELEMENT_NODE) and
+ # parent is an element, i.e. has subnodes...
+ (child.nodeType == child.TEXT_NODE or
+ child.nodeType == child.CDATA_SECTION_NODE) and
+ # ...it is textnode...
+ (
+ parent.tagName == "label" or
+ (parent.tagName == "value" and
+ not is_number(child.nodeValue)) or
+ parent.tagName == "help" or
+ parent.tagName == "longhelp" or
+ parent.tagName == "tooltip" or
+ parent.tagName == "htmlcode" or
+ parent.tagName == "title" or
+ parent.tagName == "item"
+ )):
+ # ...and known to contain translatable string
+ if (parent.getAttribute("translate") != "0"):
+ strings.append(self.ConvertText(child.nodeValue))
+
+ # subnodes:
+ if child.nodeType == child.ELEMENT_NODE:
+ strings += self.FindStringsInNode(child)
+
+ return strings
+
+ #-------------------------------------------------------------------
+
+ def ConvertText(self, st):
+ st2 = ""
+ dt = list(st)
+
+ skipNext = False
+ for i in range(len(dt)):
+ if skipNext:
+ skipNext = False
+ continue
+
+ if dt[i] == '_':
+ if dt[i+1] == '_':
+ st2 += '_'
+ skipNext = True
+ else:
+ st2 += '&'
+ elif dt[i] == '\n':
+ st2 += '\\n'
+ elif dt[i] == '\t':
+ st2 += '\\t'
+ elif dt[i] == '\r':
+ st2 += '\\r'
+ elif dt[i] == '\\':
+ if dt[i+1] not in ['n', 't', 'r']:
+ st2 += '\\\\'
+ else:
+ st2 += '\\'
+ elif dt[i] == '"':
+ st2 += '\\"'
+ else:
+ st2 += dt[i]
+
+ return st2.encode("UTF-8")
+
+ #-------------------------------------------------------------------
+
+ # Replace editable block contents with previous
+ def ReplaceBlocks(self, input):
+ output = []
+ block = None
+ blockLines = []
+ for l in input.split('\n'):
+ if not block:
+ mo = reBeginBlock.match(l)
+ if mo and mo.groups()[0] in self.blocks:
+ block = mo.groups()[0]
+ output.append(self.blocks[block])
+ else:
+ output.append(l + '\n')
+ else:
+ mo = reEndBlock.match(l)
+ if mo:
+ if mo.groups()[0] != block:
+ print "pywxrc: error: block mismatch: %s != %s" % (block, mo.groups()[0])
+ block = None
+ return ''.join(output)
+
+ #-------------------------------------------------------------------
+
+ def _OpenOutputFile(self, outputFilename):
+ if outputFilename == "-":
+ outputFile = sys.stdout
+ else:
+ # Parse existing file to collect editable blocks
+ if os.path.isfile(outputFilename):
+ outputFile = open(outputFilename)
+ block = None
+ blockLines = []
+ for l in outputFile.readlines():
+ if not block:
+ mo = reBeginBlock.match(l)
+ if mo:
+ block = mo.groups()[0]
+ blockLines = [l]
+ else:
+ blockLines.append(l)
+ mo = reEndBlock.match(l)
+ if mo:
+ if mo.groups()[0] != block:
+ print "pywxrc: error: block mismatch: %s != %s" % (block, mo.groups()[0])
+ self.blocks[block] = "".join(blockLines)
+ block = None
+
+ try:
+ outputFile = open(outputFilename, "wt")
+ except IOError:
+ raise IOError("Can't write output to '%s'" % outputFilename)
+ return outputFile
+
+
+
+
+
+#---------------------------------------------------------------------------
+
+def main(args=None):
+ if not args:
+ args = sys.argv[1:]
+
+ resourceFilename = ""
+ outputFilename = None
+ embedResources = False
+ generateGetText = False
+ assignVariables = True
+ generatePython = False
+
+ try:
+ opts, args = getopt.gnu_getopt(args,
+ "hpgevo:",
+ "help python gettext embed novar output=".split())
+ except getopt.GetoptError, e:
+ print "\nError : %s\n" % str(e)
+ print __doc__
+ sys.exit(1)
+
+ # If there is no input file argument, show help and exit
+ if not args:
+ print __doc__
+ print "No xrc input file was specified."
+ sys.exit(1)
+
+ # Parse options and arguments
+ for opt, val in opts:
+ if opt in ["-h", "--help"]:
+ print __doc__
+ sys.exit(1)
+
+ if opt in ["-p", "--python"]:
+ generatePython = True
+
+ if opt in ["-o", "--output"]:
+ outputFilename = val
+
+ if opt in ["-e", "--embed"]:
+ embedResources = True
+
+ if opt in ["-v", "--novar"]:
+ assignVariables = False
+
+ if opt in ["-g", "--gettext"]:
+ generateGetText = True
+
+
+ # check for and expand any wildcards in the list of input files
+ inputFiles = []
+ for arg in args:
+ inputFiles += glob.glob(arg)
+
+
+ comp = XmlResourceCompiler()
+
+ try:
+ if generatePython:
+ if not outputFilename:
+ outputFilename = os.path.splitext(args[0])[0] + "_xrc.py"
+ comp.MakePythonModule(inputFiles, outputFilename,
+ embedResources, generateGetText,
+ assignVariables)
+
+ elif generateGetText:
+ if not outputFilename:
+ outputFilename = '-'
+ comp.MakeGetTextOutput(inputFiles, outputFilename)
+
+ else:
+ print __doc__
+ print "One or both of -p, -g must be specified."
+ sys.exit(1)
+
+
+ except IOError, e:
+ print >>sys.stderr, "%s." % str(e)
+ else:
+ if outputFilename != "-":
+ print >>sys.stderr, "Resources written to %s." % outputFilename
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/webkit.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/webkit.py
new file mode 100644
index 0000000..27cb37e
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/webkit.py
@@ -0,0 +1,290 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+wx.webkit.WebKitCtrl for Mac OSX.
+"""
+
+import _webkit
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+class WebKitCtrl(_core.Control):
+ """Proxy of C++ WebKitCtrl class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int winID=-1, String strURL=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=WebKitNameStr) -> WebKitCtrl
+ """
+ _webkit.WebKitCtrl_swiginit(self,_webkit.new_WebKitCtrl(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int winID=-1, String strURL=EmptyString,
+ Point pos=DefaultPosition, Size size=DefaultSize,
+ long style=0, Validator validator=DefaultValidator,
+ String name=WebKitNameStr) -> bool
+ """
+ return _webkit.WebKitCtrl_Create(*args, **kwargs)
+
+ def LoadURL(*args, **kwargs):
+ """LoadURL(self, String url)"""
+ return _webkit.WebKitCtrl_LoadURL(*args, **kwargs)
+
+ def CanGoBack(*args, **kwargs):
+ """CanGoBack(self) -> bool"""
+ return _webkit.WebKitCtrl_CanGoBack(*args, **kwargs)
+
+ def CanGoForward(*args, **kwargs):
+ """CanGoForward(self) -> bool"""
+ return _webkit.WebKitCtrl_CanGoForward(*args, **kwargs)
+
+ def GoBack(*args, **kwargs):
+ """GoBack(self) -> bool"""
+ return _webkit.WebKitCtrl_GoBack(*args, **kwargs)
+
+ def GoForward(*args, **kwargs):
+ """GoForward(self) -> bool"""
+ return _webkit.WebKitCtrl_GoForward(*args, **kwargs)
+
+ def Reload(*args, **kwargs):
+ """Reload(self)"""
+ return _webkit.WebKitCtrl_Reload(*args, **kwargs)
+
+ def Stop(*args, **kwargs):
+ """Stop(self)"""
+ return _webkit.WebKitCtrl_Stop(*args, **kwargs)
+
+ def CanGetPageSource(*args, **kwargs):
+ """CanGetPageSource(self) -> bool"""
+ return _webkit.WebKitCtrl_CanGetPageSource(*args, **kwargs)
+
+ def GetPageSource(*args, **kwargs):
+ """GetPageSource(self) -> String"""
+ return _webkit.WebKitCtrl_GetPageSource(*args, **kwargs)
+
+ def SetPageSource(*args, **kwargs):
+ """SetPageSource(self, String source, String baseUrl=EmptyString)"""
+ return _webkit.WebKitCtrl_SetPageSource(*args, **kwargs)
+
+ def GetPageURL(*args, **kwargs):
+ """GetPageURL(self) -> String"""
+ return _webkit.WebKitCtrl_GetPageURL(*args, **kwargs)
+
+ def GetPageTitle(*args, **kwargs):
+ """GetPageTitle(self) -> String"""
+ return _webkit.WebKitCtrl_GetPageTitle(*args, **kwargs)
+
+ def GetSelection(*args, **kwargs):
+ """GetSelection(self) -> String"""
+ return _webkit.WebKitCtrl_GetSelection(*args, **kwargs)
+
+ def CanIncreaseTextSize(*args, **kwargs):
+ """CanIncreaseTextSize(self) -> bool"""
+ return _webkit.WebKitCtrl_CanIncreaseTextSize(*args, **kwargs)
+
+ def IncreaseTextSize(*args, **kwargs):
+ """IncreaseTextSize(self)"""
+ return _webkit.WebKitCtrl_IncreaseTextSize(*args, **kwargs)
+
+ def CanDecreaseTextSize(*args, **kwargs):
+ """CanDecreaseTextSize(self) -> bool"""
+ return _webkit.WebKitCtrl_CanDecreaseTextSize(*args, **kwargs)
+
+ def DecreaseTextSize(*args, **kwargs):
+ """DecreaseTextSize(self)"""
+ return _webkit.WebKitCtrl_DecreaseTextSize(*args, **kwargs)
+
+ def Print(*args, **kwargs):
+ """Print(self, bool showPrompt=False)"""
+ return _webkit.WebKitCtrl_Print(*args, **kwargs)
+
+ def MakeEditable(*args, **kwargs):
+ """MakeEditable(self, bool enable=True)"""
+ return _webkit.WebKitCtrl_MakeEditable(*args, **kwargs)
+
+ def IsEditable(*args, **kwargs):
+ """IsEditable(self) -> bool"""
+ return _webkit.WebKitCtrl_IsEditable(*args, **kwargs)
+
+ def RunScript(*args, **kwargs):
+ """RunScript(self, String javascript) -> String"""
+ return _webkit.WebKitCtrl_RunScript(*args, **kwargs)
+
+ PageSource = property(GetPageSource,SetPageSource,doc="See `GetPageSource` and `SetPageSource`")
+ PageTitle = property(GetPageTitle,doc="See `GetPageTitle`")
+ PageURL = property(GetPageURL,doc="See `GetPageURL`")
+ Selection = property(GetSelection,doc="See `GetSelection`")
+_webkit.WebKitCtrl_swigregister(WebKitCtrl)
+cvar = _webkit.cvar
+WebKitNameStr = cvar.WebKitNameStr
+
+def PreWebKitCtrl(*args, **kwargs):
+ """PreWebKitCtrl() -> WebKitCtrl"""
+ val = _webkit.new_PreWebKitCtrl(*args, **kwargs)
+ return val
+
+WEBKIT_STATE_START = _webkit.WEBKIT_STATE_START
+WEBKIT_STATE_NEGOTIATING = _webkit.WEBKIT_STATE_NEGOTIATING
+WEBKIT_STATE_REDIRECTING = _webkit.WEBKIT_STATE_REDIRECTING
+WEBKIT_STATE_TRANSFERRING = _webkit.WEBKIT_STATE_TRANSFERRING
+WEBKIT_STATE_STOP = _webkit.WEBKIT_STATE_STOP
+WEBKIT_STATE_FAILED = _webkit.WEBKIT_STATE_FAILED
+WEBKIT_NAV_LINK_CLICKED = _webkit.WEBKIT_NAV_LINK_CLICKED
+WEBKIT_NAV_BACK_NEXT = _webkit.WEBKIT_NAV_BACK_NEXT
+WEBKIT_NAV_FORM_SUBMITTED = _webkit.WEBKIT_NAV_FORM_SUBMITTED
+WEBKIT_NAV_RELOAD = _webkit.WEBKIT_NAV_RELOAD
+WEBKIT_NAV_FORM_RESUBMITTED = _webkit.WEBKIT_NAV_FORM_RESUBMITTED
+WEBKIT_NAV_OTHER = _webkit.WEBKIT_NAV_OTHER
+wxEVT_WEBKIT_STATE_CHANGED = _webkit.wxEVT_WEBKIT_STATE_CHANGED
+wxEVT_WEBKIT_BEFORE_LOAD = _webkit.wxEVT_WEBKIT_BEFORE_LOAD
+wxEVT_WEBKIT_NEW_WINDOW = _webkit.wxEVT_WEBKIT_NEW_WINDOW
+class WebKitBeforeLoadEvent(_core.CommandEvent):
+ """Proxy of C++ WebKitBeforeLoadEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def IsCancelled(*args, **kwargs):
+ """IsCancelled(self) -> bool"""
+ return _webkit.WebKitBeforeLoadEvent_IsCancelled(*args, **kwargs)
+
+ def Cancel(*args, **kwargs):
+ """Cancel(self, bool cancel=True)"""
+ return _webkit.WebKitBeforeLoadEvent_Cancel(*args, **kwargs)
+
+ def GetURL(*args, **kwargs):
+ """GetURL(self) -> String"""
+ return _webkit.WebKitBeforeLoadEvent_GetURL(*args, **kwargs)
+
+ def SetURL(*args, **kwargs):
+ """SetURL(self, String url)"""
+ return _webkit.WebKitBeforeLoadEvent_SetURL(*args, **kwargs)
+
+ def SetNavigationType(*args, **kwargs):
+ """SetNavigationType(self, int navType)"""
+ return _webkit.WebKitBeforeLoadEvent_SetNavigationType(*args, **kwargs)
+
+ def GetNavigationType(*args, **kwargs):
+ """GetNavigationType(self) -> int"""
+ return _webkit.WebKitBeforeLoadEvent_GetNavigationType(*args, **kwargs)
+
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window win=(wxWindow *) NULL) -> WebKitBeforeLoadEvent"""
+ _webkit.WebKitBeforeLoadEvent_swiginit(self,_webkit.new_WebKitBeforeLoadEvent(*args, **kwargs))
+ NavigationType = property(GetNavigationType,SetNavigationType,doc="See `GetNavigationType` and `SetNavigationType`")
+ URL = property(GetURL,SetURL,doc="See `GetURL` and `SetURL`")
+_webkit.WebKitBeforeLoadEvent_swigregister(WebKitBeforeLoadEvent)
+
+class WebKitStateChangedEvent(_core.CommandEvent):
+ """Proxy of C++ WebKitStateChangedEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window win=None) -> WebKitStateChangedEvent"""
+ _webkit.WebKitStateChangedEvent_swiginit(self,_webkit.new_WebKitStateChangedEvent(*args, **kwargs))
+ def GetState(*args, **kwargs):
+ """GetState(self) -> int"""
+ return _webkit.WebKitStateChangedEvent_GetState(*args, **kwargs)
+
+ def SetState(*args, **kwargs):
+ """SetState(self, int state)"""
+ return _webkit.WebKitStateChangedEvent_SetState(*args, **kwargs)
+
+ def GetURL(*args, **kwargs):
+ """GetURL(self) -> String"""
+ return _webkit.WebKitStateChangedEvent_GetURL(*args, **kwargs)
+
+ def SetURL(*args, **kwargs):
+ """SetURL(self, String url)"""
+ return _webkit.WebKitStateChangedEvent_SetURL(*args, **kwargs)
+
+ State = property(GetState,SetState,doc="See `GetState` and `SetState`")
+ URL = property(GetURL,SetURL,doc="See `GetURL` and `SetURL`")
+_webkit.WebKitStateChangedEvent_swigregister(WebKitStateChangedEvent)
+
+class WebKitNewWindowEvent(_core.CommandEvent):
+ """Proxy of C++ WebKitNewWindowEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def GetURL(*args, **kwargs):
+ """GetURL(self) -> String"""
+ return _webkit.WebKitNewWindowEvent_GetURL(*args, **kwargs)
+
+ def SetURL(*args, **kwargs):
+ """SetURL(self, String url)"""
+ return _webkit.WebKitNewWindowEvent_SetURL(*args, **kwargs)
+
+ def GetTargetName(*args, **kwargs):
+ """GetTargetName(self) -> String"""
+ return _webkit.WebKitNewWindowEvent_GetTargetName(*args, **kwargs)
+
+ def SetTargetName(*args, **kwargs):
+ """SetTargetName(self, String name)"""
+ return _webkit.WebKitNewWindowEvent_SetTargetName(*args, **kwargs)
+
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Window win=None) -> WebKitNewWindowEvent"""
+ _webkit.WebKitNewWindowEvent_swiginit(self,_webkit.new_WebKitNewWindowEvent(*args, **kwargs))
+ URL = property(GetURL,SetURL,doc="See `GetURL` and `SetURL`")
+ TargetName = property(GetTargetName,SetTargetName)
+_webkit.WebKitNewWindowEvent_swigregister(WebKitNewWindowEvent)
+
+EVT_WEBKIT_STATE_CHANGED = wx.PyEventBinder(wxEVT_WEBKIT_STATE_CHANGED)
+EVT_WEBKIT_BEFORE_LOAD = wx.PyEventBinder(wxEVT_WEBKIT_BEFORE_LOAD)
+EVT_WEBKIT_NEW_WINDOW = wx.PyEventBinder(wxEVT_WEBKIT_NEW_WINDOW)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/wizard.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/wizard.py
new file mode 100644
index 0000000..627e830
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/wizard.py
@@ -0,0 +1,471 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+`Wizard` is a dialog class that guides the user through a sequence of steps,
+or pages.
+"""
+
+import _wizard
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _windows
+import _core
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+WIZARD_EX_HELPBUTTON = _wizard.WIZARD_EX_HELPBUTTON
+WIZARD_VALIGN_TOP = _wizard.WIZARD_VALIGN_TOP
+WIZARD_VALIGN_CENTRE = _wizard.WIZARD_VALIGN_CENTRE
+WIZARD_VALIGN_BOTTOM = _wizard.WIZARD_VALIGN_BOTTOM
+WIZARD_HALIGN_LEFT = _wizard.WIZARD_HALIGN_LEFT
+WIZARD_HALIGN_CENTRE = _wizard.WIZARD_HALIGN_CENTRE
+WIZARD_HALIGN_RIGHT = _wizard.WIZARD_HALIGN_RIGHT
+WIZARD_TILE = _wizard.WIZARD_TILE
+wxEVT_WIZARD_PAGE_CHANGED = _wizard.wxEVT_WIZARD_PAGE_CHANGED
+wxEVT_WIZARD_PAGE_CHANGING = _wizard.wxEVT_WIZARD_PAGE_CHANGING
+wxEVT_WIZARD_CANCEL = _wizard.wxEVT_WIZARD_CANCEL
+wxEVT_WIZARD_HELP = _wizard.wxEVT_WIZARD_HELP
+wxEVT_WIZARD_FINISHED = _wizard.wxEVT_WIZARD_FINISHED
+wxEVT_WIZARD_PAGE_SHOWN = _wizard.wxEVT_WIZARD_PAGE_SHOWN
+wxEVT_WIZARD_BEFORE_PAGE_CHANGED = _wizard.wxEVT_WIZARD_BEFORE_PAGE_CHANGED
+EVT_WIZARD_PAGE_CHANGED = wx.PyEventBinder( wxEVT_WIZARD_PAGE_CHANGED, 1)
+EVT_WIZARD_PAGE_CHANGING = wx.PyEventBinder( wxEVT_WIZARD_PAGE_CHANGING, 1)
+EVT_WIZARD_CANCEL = wx.PyEventBinder( wxEVT_WIZARD_CANCEL, 1)
+EVT_WIZARD_HELP = wx.PyEventBinder( wxEVT_WIZARD_HELP, 1)
+EVT_WIZARD_FINISHED = wx.PyEventBinder( wxEVT_WIZARD_FINISHED, 1)
+EVT_WIZARD_PAGE_SHOWN = wx.PyEventBinder( wxEVT_WIZARD_PAGE_SHOWN, 1)
+EVT_WIZARD_BEFORE_PAGE_CHANGED = wx.PyEventBinder( wxEVT_WIZARD_PAGE_SHOWN, 1)
+
+class WizardEvent(_core.NotifyEvent):
+ """Proxy of C++ WizardEvent class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, EventType type=wxEVT_NULL, int id=-1, bool direction=True,
+ WizardPage page=None) -> WizardEvent
+ """
+ _wizard.WizardEvent_swiginit(self,_wizard.new_WizardEvent(*args, **kwargs))
+ def GetDirection(*args, **kwargs):
+ """GetDirection(self) -> bool"""
+ return _wizard.WizardEvent_GetDirection(*args, **kwargs)
+
+ def GetPage(*args, **kwargs):
+ """GetPage(self) -> WizardPage"""
+ return _wizard.WizardEvent_GetPage(*args, **kwargs)
+
+ Direction = property(GetDirection,doc="See `GetDirection`")
+ Page = property(GetPage,doc="See `GetPage`")
+_wizard.WizardEvent_swigregister(WizardEvent)
+
+class WizardPage(_windows.Panel):
+ """Proxy of C++ WizardPage class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ def __init__(self): raise AttributeError, "No constructor defined"
+ __repr__ = _swig_repr
+ def Create(*args, **kwargs):
+ """Create(self, Wizard parent, Bitmap bitmap=wxNullBitmap) -> bool"""
+ return _wizard.WizardPage_Create(*args, **kwargs)
+
+ def GetPrev(*args, **kwargs):
+ """GetPrev(self) -> WizardPage"""
+ return _wizard.WizardPage_GetPrev(*args, **kwargs)
+
+ def GetNext(*args, **kwargs):
+ """GetNext(self) -> WizardPage"""
+ return _wizard.WizardPage_GetNext(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self) -> Bitmap"""
+ return _wizard.WizardPage_GetBitmap(*args, **kwargs)
+
+ Bitmap = property(GetBitmap,doc="See `GetBitmap`")
+ Next = property(GetNext,doc="See `GetNext`")
+ Prev = property(GetPrev,doc="See `GetPrev`")
+_wizard.WizardPage_swigregister(WizardPage)
+
+class PyWizardPage(WizardPage):
+ """Proxy of C++ PyWizardPage class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, Wizard parent, Bitmap bitmap=wxNullBitmap) -> PyWizardPage"""
+ _wizard.PyWizardPage_swiginit(self,_wizard.new_PyWizardPage(*args, **kwargs))
+ self._setOORInfo(self);PyWizardPage._setCallbackInfo(self, self, PyWizardPage)
+
+ def Create(*args, **kwargs):
+ """Create(self, Wizard parent, Bitmap bitmap=wxNullBitmap) -> bool"""
+ return _wizard.PyWizardPage_Create(*args, **kwargs)
+
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _wizard.PyWizardPage__setCallbackInfo(*args, **kwargs)
+
+ def DoMoveWindow(*args, **kwargs):
+ """DoMoveWindow(self, int x, int y, int width, int height)"""
+ return _wizard.PyWizardPage_DoMoveWindow(*args, **kwargs)
+
+ def DoSetSize(*args, **kwargs):
+ """DoSetSize(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO)"""
+ return _wizard.PyWizardPage_DoSetSize(*args, **kwargs)
+
+ def DoSetClientSize(*args, **kwargs):
+ """DoSetClientSize(self, int width, int height)"""
+ return _wizard.PyWizardPage_DoSetClientSize(*args, **kwargs)
+
+ def DoSetVirtualSize(*args, **kwargs):
+ """DoSetVirtualSize(self, int x, int y)"""
+ return _wizard.PyWizardPage_DoSetVirtualSize(*args, **kwargs)
+
+ def DoGetSize(*args, **kwargs):
+ """DoGetSize() -> (width, height)"""
+ return _wizard.PyWizardPage_DoGetSize(*args, **kwargs)
+
+ def DoGetClientSize(*args, **kwargs):
+ """DoGetClientSize() -> (width, height)"""
+ return _wizard.PyWizardPage_DoGetClientSize(*args, **kwargs)
+
+ def DoGetPosition(*args, **kwargs):
+ """DoGetPosition() -> (x,y)"""
+ return _wizard.PyWizardPage_DoGetPosition(*args, **kwargs)
+
+ def DoGetVirtualSize(*args, **kwargs):
+ """DoGetVirtualSize(self) -> Size"""
+ return _wizard.PyWizardPage_DoGetVirtualSize(*args, **kwargs)
+
+ def DoGetBestSize(*args, **kwargs):
+ """DoGetBestSize(self) -> Size"""
+ return _wizard.PyWizardPage_DoGetBestSize(*args, **kwargs)
+
+ def GetDefaultAttributes(*args, **kwargs):
+ """GetDefaultAttributes(self) -> VisualAttributes"""
+ return _wizard.PyWizardPage_GetDefaultAttributes(*args, **kwargs)
+
+ def OnInternalIdle(*args, **kwargs):
+ """OnInternalIdle(self)"""
+ return _wizard.PyWizardPage_OnInternalIdle(*args, **kwargs)
+
+ def base_DoMoveWindow(*args, **kw):
+ return PyWizardPage.DoMoveWindow(*args, **kw)
+ base_DoMoveWindow = wx.deprecated(base_DoMoveWindow,
+ "Please use PyWizardPage.DoMoveWindow instead.")
+
+ def base_DoSetSize(*args, **kw):
+ return PyWizardPage.DoSetSize(*args, **kw)
+ base_DoSetSize = wx.deprecated(base_DoSetSize,
+ "Please use PyWizardPage.DoSetSize instead.")
+
+ def base_DoSetClientSize(*args, **kw):
+ return PyWizardPage.DoSetClientSize(*args, **kw)
+ base_DoSetClientSize = wx.deprecated(base_DoSetClientSize,
+ "Please use PyWizardPage.DoSetClientSize instead.")
+
+ def base_DoSetVirtualSize(*args, **kw):
+ return PyWizardPage.DoSetVirtualSize(*args, **kw)
+ base_DoSetVirtualSize = wx.deprecated(base_DoSetVirtualSize,
+ "Please use PyWizardPage.DoSetVirtualSize instead.")
+
+ def base_DoGetSize(*args, **kw):
+ return PyWizardPage.DoGetSize(*args, **kw)
+ base_DoGetSize = wx.deprecated(base_DoGetSize,
+ "Please use PyWizardPage.DoGetSize instead.")
+
+ def base_DoGetClientSize(*args, **kw):
+ return PyWizardPage.DoGetClientSize(*args, **kw)
+ base_DoGetClientSize = wx.deprecated(base_DoGetClientSize,
+ "Please use PyWizardPage.DoGetClientSize instead.")
+
+ def base_DoGetPosition(*args, **kw):
+ return PyWizardPage.DoGetPosition(*args, **kw)
+ base_DoGetPosition = wx.deprecated(base_DoGetPosition,
+ "Please use PyWizardPage.DoGetPosition instead.")
+
+ def base_DoGetVirtualSize(*args, **kw):
+ return PyWizardPage.DoGetVirtualSize(*args, **kw)
+ base_DoGetVirtualSize = wx.deprecated(base_DoGetVirtualSize,
+ "Please use PyWizardPage.DoGetVirtualSize instead.")
+
+ def base_DoGetBestSize(*args, **kw):
+ return PyWizardPage.DoGetBestSize(*args, **kw)
+ base_DoGetBestSize = wx.deprecated(base_DoGetBestSize,
+ "Please use PyWizardPage.DoGetBestSize instead.")
+
+ def base_InitDialog(*args, **kw):
+ return PyWizardPage.InitDialog(*args, **kw)
+ base_InitDialog = wx.deprecated(base_InitDialog,
+ "Please use PyWizardPage.InitDialog instead.")
+
+ def base_TransferDataToWindow(*args, **kw):
+ return PyWizardPage.TransferDataToWindow(*args, **kw)
+ base_TransferDataToWindow = wx.deprecated(base_TransferDataToWindow,
+ "Please use PyWizardPage.TransferDataToWindow instead.")
+
+ def base_TransferDataFromWindow(*args, **kw):
+ return PyWizardPage.TransferDataFromWindow(*args, **kw)
+ base_TransferDataFromWindow = wx.deprecated(base_TransferDataFromWindow,
+ "Please use PyWizardPage.TransferDataFromWindow instead.")
+
+ def base_Validate(*args, **kw):
+ return PyWizardPage.Validate(*args, **kw)
+ base_Validate = wx.deprecated(base_Validate,
+ "Please use PyWizardPage.Validate instead.")
+
+ def base_AcceptsFocus(*args, **kw):
+ return PyWizardPage.AcceptsFocus(*args, **kw)
+ base_AcceptsFocus = wx.deprecated(base_AcceptsFocus,
+ "Please use PyWizardPage.AcceptsFocus instead.")
+
+ def base_AcceptsFocusFromKeyboard(*args, **kw):
+ return PyWizardPage.AcceptsFocusFromKeyboard(*args, **kw)
+ base_AcceptsFocusFromKeyboard = wx.deprecated(base_AcceptsFocusFromKeyboard,
+ "Please use PyWizardPage.AcceptsFocusFromKeyboard instead.")
+
+ def base_GetMaxSize(*args, **kw):
+ return PyWizardPage.GetMaxSize(*args, **kw)
+ base_GetMaxSize = wx.deprecated(base_GetMaxSize,
+ "Please use PyWizardPage.GetMaxSize instead.")
+
+ def base_AddChild(*args, **kw):
+ return PyWizardPage.AddChild(*args, **kw)
+ base_AddChild = wx.deprecated(base_AddChild,
+ "Please use PyWizardPage.AddChild instead.")
+
+ def base_RemoveChild(*args, **kw):
+ return PyWizardPage.RemoveChild(*args, **kw)
+ base_RemoveChild = wx.deprecated(base_RemoveChild,
+ "Please use PyWizardPage.RemoveChild instead.")
+
+ def base_ShouldInheritColours(*args, **kw):
+ return PyWizardPage.ShouldInheritColours(*args, **kw)
+ base_ShouldInheritColours = wx.deprecated(base_ShouldInheritColours,
+ "Please use PyWizardPage.ShouldInheritColours instead.")
+
+ def base_GetDefaultAttributes(*args, **kw):
+ return PyWizardPage.GetDefaultAttributes(*args, **kw)
+ base_GetDefaultAttributes = wx.deprecated(base_GetDefaultAttributes,
+ "Please use PyWizardPage.GetDefaultAttributes instead.")
+
+ def base_OnInternalIdle(*args, **kw):
+ return PyWizardPage.OnInternalIdle(*args, **kw)
+ base_OnInternalIdle = wx.deprecated(base_OnInternalIdle,
+ "Please use PyWizardPage.OnInternalIdle instead.")
+
+_wizard.PyWizardPage_swigregister(PyWizardPage)
+
+def PrePyWizardPage(*args, **kwargs):
+ """PrePyWizardPage() -> PyWizardPage"""
+ val = _wizard.new_PrePyWizardPage(*args, **kwargs)
+ return val
+
+class WizardPageSimple(WizardPage):
+ """Proxy of C++ WizardPageSimple class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Wizard parent, WizardPage prev=None, WizardPage next=None,
+ Bitmap bitmap=wxNullBitmap) -> WizardPageSimple
+ """
+ _wizard.WizardPageSimple_swiginit(self,_wizard.new_WizardPageSimple(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Wizard parent=None, WizardPage prev=None, WizardPage next=None,
+ Bitmap bitmap=wxNullBitmap) -> bool
+ """
+ return _wizard.WizardPageSimple_Create(*args, **kwargs)
+
+ def SetPrev(*args, **kwargs):
+ """SetPrev(self, WizardPage prev)"""
+ return _wizard.WizardPageSimple_SetPrev(*args, **kwargs)
+
+ def SetNext(*args, **kwargs):
+ """SetNext(self, WizardPage next)"""
+ return _wizard.WizardPageSimple_SetNext(*args, **kwargs)
+
+ def Chain(*args, **kwargs):
+ """Chain(WizardPageSimple first, WizardPageSimple second)"""
+ return _wizard.WizardPageSimple_Chain(*args, **kwargs)
+
+ Chain = staticmethod(Chain)
+_wizard.WizardPageSimple_swigregister(WizardPageSimple)
+
+def PreWizardPageSimple(*args, **kwargs):
+ """PreWizardPageSimple() -> WizardPageSimple"""
+ val = _wizard.new_PreWizardPageSimple(*args, **kwargs)
+ return val
+
+def WizardPageSimple_Chain(*args, **kwargs):
+ """WizardPageSimple_Chain(WizardPageSimple first, WizardPageSimple second)"""
+ return _wizard.WizardPageSimple_Chain(*args, **kwargs)
+
+class Wizard(_windows.Dialog):
+ """Proxy of C++ Wizard class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, Window parent, int id=-1, String title=EmptyString,
+ Bitmap bitmap=wxNullBitmap, Point pos=DefaultPosition,
+ long style=DEFAULT_DIALOG_STYLE) -> Wizard
+ """
+ _wizard.Wizard_swiginit(self,_wizard.new_Wizard(*args, **kwargs))
+ self._setOORInfo(self)
+
+ def Create(*args, **kwargs):
+ """
+ Create(self, Window parent, int id=-1, String title=EmptyString,
+ Bitmap bitmap=wxNullBitmap, Point pos=DefaultPosition) -> bool
+ """
+ return _wizard.Wizard_Create(*args, **kwargs)
+
+ def Init(*args, **kwargs):
+ """Init(self)"""
+ return _wizard.Wizard_Init(*args, **kwargs)
+
+ def RunWizard(*args, **kwargs):
+ """RunWizard(self, WizardPage firstPage) -> bool"""
+ return _wizard.Wizard_RunWizard(*args, **kwargs)
+
+ def GetCurrentPage(*args, **kwargs):
+ """GetCurrentPage(self) -> WizardPage"""
+ return _wizard.Wizard_GetCurrentPage(*args, **kwargs)
+
+ def SetPageSize(*args, **kwargs):
+ """SetPageSize(self, Size size)"""
+ return _wizard.Wizard_SetPageSize(*args, **kwargs)
+
+ def GetPageSize(*args, **kwargs):
+ """GetPageSize(self) -> Size"""
+ return _wizard.Wizard_GetPageSize(*args, **kwargs)
+
+ def FitToPage(*args, **kwargs):
+ """FitToPage(self, WizardPage firstPage)"""
+ return _wizard.Wizard_FitToPage(*args, **kwargs)
+
+ def GetPageAreaSizer(*args, **kwargs):
+ """GetPageAreaSizer(self) -> Sizer"""
+ return _wizard.Wizard_GetPageAreaSizer(*args, **kwargs)
+
+ def SetBorder(*args, **kwargs):
+ """SetBorder(self, int border)"""
+ return _wizard.Wizard_SetBorder(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """GetBitmap(self) -> Bitmap"""
+ return _wizard.Wizard_GetBitmap(*args, **kwargs)
+
+ def SetBitmap(*args, **kwargs):
+ """SetBitmap(self, Bitmap bitmap)"""
+ return _wizard.Wizard_SetBitmap(*args, **kwargs)
+
+ def IsRunning(*args, **kwargs):
+ """IsRunning(self) -> bool"""
+ return _wizard.Wizard_IsRunning(*args, **kwargs)
+
+ def SetBitmapBackgroundColour(*args, **kwargs):
+ """SetBitmapBackgroundColour(self, Colour colour)"""
+ return _wizard.Wizard_SetBitmapBackgroundColour(*args, **kwargs)
+
+ def GetBitmapBackgroundColour(*args, **kwargs):
+ """GetBitmapBackgroundColour(self) -> Colour"""
+ return _wizard.Wizard_GetBitmapBackgroundColour(*args, **kwargs)
+
+ def SetBitmapPlacement(*args, **kwargs):
+ """SetBitmapPlacement(self, int placement)"""
+ return _wizard.Wizard_SetBitmapPlacement(*args, **kwargs)
+
+ def GetBitmapPlacement(*args, **kwargs):
+ """GetBitmapPlacement(self) -> int"""
+ return _wizard.Wizard_GetBitmapPlacement(*args, **kwargs)
+
+ def SetMinimumBitmapWidth(*args, **kwargs):
+ """SetMinimumBitmapWidth(self, int w)"""
+ return _wizard.Wizard_SetMinimumBitmapWidth(*args, **kwargs)
+
+ def GetMinimumBitmapWidth(*args, **kwargs):
+ """GetMinimumBitmapWidth(self) -> int"""
+ return _wizard.Wizard_GetMinimumBitmapWidth(*args, **kwargs)
+
+ def TileBitmap(*args, **kwargs):
+ """TileBitmap(Rect rect, DC dc, Bitmap bitmap) -> bool"""
+ return _wizard.Wizard_TileBitmap(*args, **kwargs)
+
+ TileBitmap = staticmethod(TileBitmap)
+ def ShowPage(*args, **kwargs):
+ """ShowPage(self, WizardPage page, bool goingForward=True) -> bool"""
+ return _wizard.Wizard_ShowPage(*args, **kwargs)
+
+ def HasNextPage(*args, **kwargs):
+ """HasNextPage(self, WizardPage page) -> bool"""
+ return _wizard.Wizard_HasNextPage(*args, **kwargs)
+
+ def HasPrevPage(*args, **kwargs):
+ """HasPrevPage(self, WizardPage page) -> bool"""
+ return _wizard.Wizard_HasPrevPage(*args, **kwargs)
+
+ Bitmap = property(GetBitmap,SetBitmap)
+ CurrentPage = property(GetCurrentPage,doc="See `GetCurrentPage`")
+ PageAreaSizer = property(GetPageAreaSizer,doc="See `GetPageAreaSizer`")
+ PageSize = property(GetPageSize,SetPageSize,doc="See `GetPageSize` and `SetPageSize`")
+_wizard.Wizard_swigregister(Wizard)
+
+def PreWizard(*args, **kwargs):
+ """PreWizard() -> Wizard"""
+ val = _wizard.new_PreWizard(*args, **kwargs)
+ return val
+
+def Wizard_TileBitmap(*args, **kwargs):
+ """Wizard_TileBitmap(Rect rect, DC dc, Bitmap bitmap) -> bool"""
+ return _wizard.Wizard_TileBitmap(*args, **kwargs)
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/xrc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/xrc.py
new file mode 100644
index 0000000..cd15007
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/xrc.py
@@ -0,0 +1,791 @@
+# This file was created automatically by SWIG 1.3.29.
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+The `XmlResource` class allows program resources defining menus, layout of
+controls on a panel, etc. to be loaded from an XML file.
+"""
+
+import _xrc
+import new
+new_instancemethod = new.instancemethod
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+import _core
+wx = _core
+__docfilter__ = wx.__DocFilter(globals())
+#---------------------------------------------------------------------------
+
+WX_XMLRES_CURRENT_VERSION_MAJOR = _xrc.WX_XMLRES_CURRENT_VERSION_MAJOR
+WX_XMLRES_CURRENT_VERSION_MINOR = _xrc.WX_XMLRES_CURRENT_VERSION_MINOR
+WX_XMLRES_CURRENT_VERSION_RELEASE = _xrc.WX_XMLRES_CURRENT_VERSION_RELEASE
+WX_XMLRES_CURRENT_VERSION_REVISION = _xrc.WX_XMLRES_CURRENT_VERSION_REVISION
+XRC_USE_LOCALE = _xrc.XRC_USE_LOCALE
+XRC_NO_SUBCLASSING = _xrc.XRC_NO_SUBCLASSING
+XRC_NO_RELOADING = _xrc.XRC_NO_RELOADING
+class XmlResource(_core.Object):
+ """Proxy of C++ XmlResource class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String filemask, int flags=XRC_USE_LOCALE, String domain=wxEmptyString) -> XmlResource"""
+ _xrc.XmlResource_swiginit(self,_xrc.new_XmlResource(*args, **kwargs))
+ self.InitAllHandlers()
+
+ __swig_destroy__ = _xrc.delete_XmlResource
+ __del__ = lambda self : None;
+ def Load(*args, **kwargs):
+ """Load(self, String filemask) -> bool"""
+ return _xrc.XmlResource_Load(*args, **kwargs)
+
+ def LoadFromString(*args, **kwargs):
+ """LoadFromString(self, buffer data) -> bool"""
+ return _xrc.XmlResource_LoadFromString(*args, **kwargs)
+
+ def LoadFile(*args, **kwargs):
+ """LoadFile(self, String file) -> bool"""
+ return _xrc.XmlResource_LoadFile(*args, **kwargs)
+
+ def Unload(*args, **kwargs):
+ """Unload(self, String filename) -> bool"""
+ return _xrc.XmlResource_Unload(*args, **kwargs)
+
+ def InitAllHandlers(*args, **kwargs):
+ """InitAllHandlers(self)"""
+ return _xrc.XmlResource_InitAllHandlers(*args, **kwargs)
+
+ def AddHandler(*args, **kwargs):
+ """AddHandler(self, XmlResourceHandler handler)"""
+ return _xrc.XmlResource_AddHandler(*args, **kwargs)
+
+ def InsertHandler(*args, **kwargs):
+ """InsertHandler(self, XmlResourceHandler handler)"""
+ return _xrc.XmlResource_InsertHandler(*args, **kwargs)
+
+ def ClearHandlers(*args, **kwargs):
+ """ClearHandlers(self)"""
+ return _xrc.XmlResource_ClearHandlers(*args, **kwargs)
+
+ def AddSubclassFactory(*args, **kwargs):
+ """AddSubclassFactory(XmlSubclassFactory factory)"""
+ return _xrc.XmlResource_AddSubclassFactory(*args, **kwargs)
+
+ AddSubclassFactory = staticmethod(AddSubclassFactory)
+ def LoadMenu(*args, **kwargs):
+ """LoadMenu(self, String name) -> Menu"""
+ return _xrc.XmlResource_LoadMenu(*args, **kwargs)
+
+ def LoadMenuBar(*args, **kwargs):
+ """LoadMenuBar(self, String name) -> MenuBar"""
+ return _xrc.XmlResource_LoadMenuBar(*args, **kwargs)
+
+ def LoadMenuBarOnFrame(*args, **kwargs):
+ """LoadMenuBarOnFrame(self, Window parent, String name) -> MenuBar"""
+ return _xrc.XmlResource_LoadMenuBarOnFrame(*args, **kwargs)
+
+ def LoadToolBar(*args, **kwargs):
+ """LoadToolBar(self, Window parent, String name) -> wxToolBar"""
+ return _xrc.XmlResource_LoadToolBar(*args, **kwargs)
+
+ def LoadDialog(*args, **kwargs):
+ """LoadDialog(self, Window parent, String name) -> wxDialog"""
+ return _xrc.XmlResource_LoadDialog(*args, **kwargs)
+
+ def LoadOnDialog(*args, **kwargs):
+ """LoadOnDialog(self, wxDialog dlg, Window parent, String name) -> bool"""
+ return _xrc.XmlResource_LoadOnDialog(*args, **kwargs)
+
+ def LoadPanel(*args, **kwargs):
+ """LoadPanel(self, Window parent, String name) -> wxPanel"""
+ return _xrc.XmlResource_LoadPanel(*args, **kwargs)
+
+ def LoadOnPanel(*args, **kwargs):
+ """LoadOnPanel(self, wxPanel panel, Window parent, String name) -> bool"""
+ return _xrc.XmlResource_LoadOnPanel(*args, **kwargs)
+
+ def LoadFrame(*args, **kwargs):
+ """LoadFrame(self, Window parent, String name) -> wxFrame"""
+ return _xrc.XmlResource_LoadFrame(*args, **kwargs)
+
+ def LoadOnFrame(*args, **kwargs):
+ """LoadOnFrame(self, wxFrame frame, Window parent, String name) -> bool"""
+ return _xrc.XmlResource_LoadOnFrame(*args, **kwargs)
+
+ def LoadObject(*args, **kwargs):
+ """LoadObject(self, Window parent, String name, String classname) -> Object"""
+ return _xrc.XmlResource_LoadObject(*args, **kwargs)
+
+ def LoadOnObject(*args, **kwargs):
+ """LoadOnObject(self, Object instance, Window parent, String name, String classname) -> bool"""
+ return _xrc.XmlResource_LoadOnObject(*args, **kwargs)
+
+ def LoadObjectRecursively(*args, **kwargs):
+ """LoadObjectRecursively(self, Window parent, String name, String classname) -> Object"""
+ return _xrc.XmlResource_LoadObjectRecursively(*args, **kwargs)
+
+ def LoadOnObjectRecursively(*args, **kwargs):
+ """LoadOnObjectRecursively(self, Object instance, Window parent, String name, String classname) -> bool"""
+ return _xrc.XmlResource_LoadOnObjectRecursively(*args, **kwargs)
+
+ def LoadBitmap(*args, **kwargs):
+ """LoadBitmap(self, String name) -> Bitmap"""
+ return _xrc.XmlResource_LoadBitmap(*args, **kwargs)
+
+ def LoadIcon(*args, **kwargs):
+ """LoadIcon(self, String name) -> Icon"""
+ return _xrc.XmlResource_LoadIcon(*args, **kwargs)
+
+ def AttachUnknownControl(*args, **kwargs):
+ """AttachUnknownControl(self, String name, Window control, Window parent=None) -> bool"""
+ return _xrc.XmlResource_AttachUnknownControl(*args, **kwargs)
+
+ def GetXRCID(*args, **kwargs):
+ """GetXRCID(String str_id, int value_if_not_found=ID_NONE) -> int"""
+ return _xrc.XmlResource_GetXRCID(*args, **kwargs)
+
+ GetXRCID = staticmethod(GetXRCID)
+ def GetVersion(*args, **kwargs):
+ """GetVersion(self) -> long"""
+ return _xrc.XmlResource_GetVersion(*args, **kwargs)
+
+ def CompareVersion(*args, **kwargs):
+ """CompareVersion(self, int major, int minor, int release, int revision) -> int"""
+ return _xrc.XmlResource_CompareVersion(*args, **kwargs)
+
+ def Get(*args, **kwargs):
+ """Get() -> XmlResource"""
+ return _xrc.XmlResource_Get(*args, **kwargs)
+
+ Get = staticmethod(Get)
+ def Set(*args, **kwargs):
+ """Set(XmlResource res) -> XmlResource"""
+ return _xrc.XmlResource_Set(*args, **kwargs)
+
+ Set = staticmethod(Set)
+ def GetFlags(*args, **kwargs):
+ """GetFlags(self) -> int"""
+ return _xrc.XmlResource_GetFlags(*args, **kwargs)
+
+ def SetFlags(*args, **kwargs):
+ """SetFlags(self, int flags)"""
+ return _xrc.XmlResource_SetFlags(*args, **kwargs)
+
+ def GetDomain(*args, **kwargs):
+ """GetDomain(self) -> String"""
+ return _xrc.XmlResource_GetDomain(*args, **kwargs)
+
+ def SetDomain(*args, **kwargs):
+ """SetDomain(self, String domain)"""
+ return _xrc.XmlResource_SetDomain(*args, **kwargs)
+
+ def GetResourceNode(*args, **kwargs):
+ """GetResourceNode(self, String name) -> XmlNode"""
+ return _xrc.XmlResource_GetResourceNode(*args, **kwargs)
+
+ Domain = property(GetDomain,SetDomain,doc="See `GetDomain` and `SetDomain`")
+ Flags = property(GetFlags,SetFlags,doc="See `GetFlags` and `SetFlags`")
+ Version = property(GetVersion,doc="See `GetVersion`")
+_xrc.XmlResource_swigregister(XmlResource)
+cvar = _xrc.cvar
+UTF8String = cvar.UTF8String
+StyleString = cvar.StyleString
+SizeString = cvar.SizeString
+PosString = cvar.PosString
+BitmapString = cvar.BitmapString
+IconString = cvar.IconString
+FontString = cvar.FontString
+AnimationString = cvar.AnimationString
+
+def EmptyXmlResource(*args, **kwargs):
+ """EmptyXmlResource(int flags=XRC_USE_LOCALE, String domain=wxEmptyString) -> XmlResource"""
+ val = _xrc.new_EmptyXmlResource(*args, **kwargs)
+ val.InitAllHandlers()
+ return val
+
+def XmlResource_AddSubclassFactory(*args, **kwargs):
+ """XmlResource_AddSubclassFactory(XmlSubclassFactory factory)"""
+ return _xrc.XmlResource_AddSubclassFactory(*args, **kwargs)
+
+def XmlResource_GetXRCID(*args, **kwargs):
+ """XmlResource_GetXRCID(String str_id, int value_if_not_found=ID_NONE) -> int"""
+ return _xrc.XmlResource_GetXRCID(*args, **kwargs)
+
+def XmlResource_Get(*args):
+ """XmlResource_Get() -> XmlResource"""
+ return _xrc.XmlResource_Get(*args)
+
+def XmlResource_Set(*args, **kwargs):
+ """XmlResource_Set(XmlResource res) -> XmlResource"""
+ return _xrc.XmlResource_Set(*args, **kwargs)
+
+def XRCID(str_id, value_if_not_found = wx.ID_NONE):
+ return XmlResource_GetXRCID(str_id, value_if_not_found)
+
+def XRCCTRL(window, str_id, *ignoreargs):
+ return window.FindWindowById(XRCID(str_id))
+
+#---------------------------------------------------------------------------
+
+class XmlSubclassFactory(object):
+ """Proxy of C++ XmlSubclassFactory class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> XmlSubclassFactory"""
+ _xrc.XmlSubclassFactory_swiginit(self,_xrc.new_XmlSubclassFactory(*args, **kwargs))
+ XmlSubclassFactory._setCallbackInfo(self, self, XmlSubclassFactory)
+
+ __swig_destroy__ = _xrc.delete_XmlSubclassFactory
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _xrc.XmlSubclassFactory__setCallbackInfo(*args, **kwargs)
+
+_xrc.XmlSubclassFactory_swigregister(XmlSubclassFactory)
+
+#---------------------------------------------------------------------------
+
+XML_ELEMENT_NODE = _xrc.XML_ELEMENT_NODE
+XML_ATTRIBUTE_NODE = _xrc.XML_ATTRIBUTE_NODE
+XML_TEXT_NODE = _xrc.XML_TEXT_NODE
+XML_CDATA_SECTION_NODE = _xrc.XML_CDATA_SECTION_NODE
+XML_ENTITY_REF_NODE = _xrc.XML_ENTITY_REF_NODE
+XML_ENTITY_NODE = _xrc.XML_ENTITY_NODE
+XML_PI_NODE = _xrc.XML_PI_NODE
+XML_COMMENT_NODE = _xrc.XML_COMMENT_NODE
+XML_DOCUMENT_NODE = _xrc.XML_DOCUMENT_NODE
+XML_DOCUMENT_TYPE_NODE = _xrc.XML_DOCUMENT_TYPE_NODE
+XML_DOCUMENT_FRAG_NODE = _xrc.XML_DOCUMENT_FRAG_NODE
+XML_NOTATION_NODE = _xrc.XML_NOTATION_NODE
+XML_HTML_DOCUMENT_NODE = _xrc.XML_HTML_DOCUMENT_NODE
+class XmlProperty(object):
+ """Proxy of C++ XmlProperty class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, String name=EmptyString, String value=EmptyString,
+ XmlProperty next=None) -> XmlProperty
+ """
+ _xrc.XmlProperty_swiginit(self,_xrc.new_XmlProperty(*args, **kwargs))
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _xrc.XmlProperty_GetName(*args, **kwargs)
+
+ def GetValue(*args, **kwargs):
+ """GetValue(self) -> String"""
+ return _xrc.XmlProperty_GetValue(*args, **kwargs)
+
+ def GetNext(*args, **kwargs):
+ """GetNext(self) -> XmlProperty"""
+ return _xrc.XmlProperty_GetNext(*args, **kwargs)
+
+ def SetName(*args, **kwargs):
+ """SetName(self, String name)"""
+ return _xrc.XmlProperty_SetName(*args, **kwargs)
+
+ def SetValue(*args, **kwargs):
+ """SetValue(self, String value)"""
+ return _xrc.XmlProperty_SetValue(*args, **kwargs)
+
+ def SetNext(*args, **kwargs):
+ """SetNext(self, XmlProperty next)"""
+ return _xrc.XmlProperty_SetNext(*args, **kwargs)
+
+ Name = property(GetName,SetName,doc="See `GetName` and `SetName`")
+ Next = property(GetNext,SetNext,doc="See `GetNext` and `SetNext`")
+ Value = property(GetValue,SetValue,doc="See `GetValue` and `SetValue`")
+_xrc.XmlProperty_swigregister(XmlProperty)
+
+class XmlNode(object):
+ """Proxy of C++ XmlNode class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """
+ __init__(self, XmlNode parent=None, int type=0, String name=EmptyString,
+ String content=EmptyString, XmlProperty props=None,
+ XmlNode next=None, int lineNo=-1) -> XmlNode
+ """
+ _xrc.XmlNode_swiginit(self,_xrc.new_XmlNode(*args, **kwargs))
+ __swig_destroy__ = _xrc.delete_XmlNode
+ __del__ = lambda self : None;
+ def AddChild(*args, **kwargs):
+ """AddChild(self, XmlNode child)"""
+ return _xrc.XmlNode_AddChild(*args, **kwargs)
+
+ def InsertChild(*args, **kwargs):
+ """InsertChild(self, XmlNode child, XmlNode before_node) -> bool"""
+ return _xrc.XmlNode_InsertChild(*args, **kwargs)
+
+ def InsertChildAfter(*args, **kwargs):
+ """InsertChildAfter(self, XmlNode child, XmlNode precedingNode) -> bool"""
+ return _xrc.XmlNode_InsertChildAfter(*args, **kwargs)
+
+ def RemoveChild(*args, **kwargs):
+ """RemoveChild(self, XmlNode child) -> bool"""
+ return _xrc.XmlNode_RemoveChild(*args, **kwargs)
+
+ def AddProperty(*args, **kwargs):
+ """AddProperty(self, XmlProperty prop)"""
+ return _xrc.XmlNode_AddProperty(*args, **kwargs)
+
+ def AddPropertyName(*args, **kwargs):
+ """AddPropertyName(self, String name, String value)"""
+ return _xrc.XmlNode_AddPropertyName(*args, **kwargs)
+
+ def DeleteProperty(*args, **kwargs):
+ """DeleteProperty(self, String name) -> bool"""
+ return _xrc.XmlNode_DeleteProperty(*args, **kwargs)
+
+ def GetType(*args, **kwargs):
+ """GetType(self) -> int"""
+ return _xrc.XmlNode_GetType(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _xrc.XmlNode_GetName(*args, **kwargs)
+
+ def GetContent(*args, **kwargs):
+ """GetContent(self) -> String"""
+ return _xrc.XmlNode_GetContent(*args, **kwargs)
+
+ def IsWhitespaceOnly(*args, **kwargs):
+ """IsWhitespaceOnly(self) -> bool"""
+ return _xrc.XmlNode_IsWhitespaceOnly(*args, **kwargs)
+
+ def GetDepth(*args, **kwargs):
+ """GetDepth(self, XmlNode grandparent=None) -> int"""
+ return _xrc.XmlNode_GetDepth(*args, **kwargs)
+
+ def GetNodeContent(*args, **kwargs):
+ """GetNodeContent(self) -> String"""
+ return _xrc.XmlNode_GetNodeContent(*args, **kwargs)
+
+ def GetParent(*args, **kwargs):
+ """GetParent(self) -> XmlNode"""
+ return _xrc.XmlNode_GetParent(*args, **kwargs)
+
+ def GetNext(*args, **kwargs):
+ """GetNext(self) -> XmlNode"""
+ return _xrc.XmlNode_GetNext(*args, **kwargs)
+
+ def GetChildren(*args, **kwargs):
+ """GetChildren(self) -> XmlNode"""
+ return _xrc.XmlNode_GetChildren(*args, **kwargs)
+
+ def HasAttribute(*args, **kwargs):
+ """HasAttribute(self, String attrName) -> bool"""
+ return _xrc.XmlNode_HasAttribute(*args, **kwargs)
+
+ def GetLineNumber(*args, **kwargs):
+ """GetLineNumber(self) -> int"""
+ return _xrc.XmlNode_GetLineNumber(*args, **kwargs)
+
+ def GetProperties(*args, **kwargs):
+ """GetProperties(self) -> XmlProperty"""
+ return _xrc.XmlNode_GetProperties(*args, **kwargs)
+
+ def GetPropVal(*args, **kwargs):
+ """GetPropVal(self, String propName, String defaultVal) -> String"""
+ return _xrc.XmlNode_GetPropVal(*args, **kwargs)
+
+ def HasProp(*args, **kwargs):
+ """HasProp(self, String propName) -> bool"""
+ return _xrc.XmlNode_HasProp(*args, **kwargs)
+
+ def SetType(*args, **kwargs):
+ """SetType(self, int type)"""
+ return _xrc.XmlNode_SetType(*args, **kwargs)
+
+ def SetName(*args, **kwargs):
+ """SetName(self, String name)"""
+ return _xrc.XmlNode_SetName(*args, **kwargs)
+
+ def SetContent(*args, **kwargs):
+ """SetContent(self, String con)"""
+ return _xrc.XmlNode_SetContent(*args, **kwargs)
+
+ def SetParent(*args, **kwargs):
+ """SetParent(self, XmlNode parent)"""
+ return _xrc.XmlNode_SetParent(*args, **kwargs)
+
+ def SetNext(*args, **kwargs):
+ """SetNext(self, XmlNode next)"""
+ return _xrc.XmlNode_SetNext(*args, **kwargs)
+
+ def SetChildren(*args, **kwargs):
+ """SetChildren(self, XmlNode child)"""
+ return _xrc.XmlNode_SetChildren(*args, **kwargs)
+
+ def SetProperties(*args, **kwargs):
+ """SetProperties(self, XmlProperty prop)"""
+ return _xrc.XmlNode_SetProperties(*args, **kwargs)
+
+ def SetAttributes(*args, **kwargs):
+ """SetAttributes(self, wxXmlAttribute attr)"""
+ return _xrc.XmlNode_SetAttributes(*args, **kwargs)
+
+ def AddAttribute(*args):
+ """
+ AddAttribute(self, wxXmlAttribute attr)
+ AddAttribute(self, String attrName, String value)
+ """
+ return _xrc.XmlNode_AddAttribute(*args)
+
+ def GetAttribute(*args, **kwargs):
+ """GetAttribute(self, String attrName, String defaultVal) -> String"""
+ return _xrc.XmlNode_GetAttribute(*args, **kwargs)
+
+ def GetAttributes(*args, **kwargs):
+ """GetAttributes(self) -> XmlProperty"""
+ return _xrc.XmlNode_GetAttributes(*args, **kwargs)
+
+ Children = property(GetChildren,SetChildren,doc="See `GetChildren` and `SetChildren`")
+ Content = property(GetContent,SetContent,doc="See `GetContent` and `SetContent`")
+ Name = property(GetName,SetName,doc="See `GetName` and `SetName`")
+ Next = property(GetNext,SetNext,doc="See `GetNext` and `SetNext`")
+ Parent = property(GetParent,SetParent,doc="See `GetParent` and `SetParent`")
+ Properties = property(GetProperties,SetProperties,doc="See `GetProperties` and `SetProperties`")
+ Type = property(GetType,SetType,doc="See `GetType` and `SetType`")
+_xrc.XmlNode_swigregister(XmlNode)
+
+def XmlNodeEasy(*args, **kwargs):
+ """XmlNodeEasy(int type, String name, String content=EmptyString) -> XmlNode"""
+ val = _xrc.new_XmlNodeEasy(*args, **kwargs)
+ return val
+
+XML_NO_INDENTATION = _xrc.XML_NO_INDENTATION
+XMLDOC_NONE = _xrc.XMLDOC_NONE
+XMLDOC_KEEP_WHITESPACE_NODES = _xrc.XMLDOC_KEEP_WHITESPACE_NODES
+class XmlDocument(_core.Object):
+ """Proxy of C++ XmlDocument class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self, String filename, String encoding=UTF8String) -> XmlDocument"""
+ _xrc.XmlDocument_swiginit(self,_xrc.new_XmlDocument(*args, **kwargs))
+ __swig_destroy__ = _xrc.delete_XmlDocument
+ __del__ = lambda self : None;
+ def Load(*args, **kwargs):
+ """Load(self, String filename, String encoding=UTF8String, int flags=XMLDOC_NONE) -> bool"""
+ return _xrc.XmlDocument_Load(*args, **kwargs)
+
+ def LoadFromStream(*args, **kwargs):
+ """LoadFromStream(self, InputStream stream, String encoding=UTF8String, int flags=XMLDOC_NONE) -> bool"""
+ return _xrc.XmlDocument_LoadFromStream(*args, **kwargs)
+
+ def Save(*args, **kwargs):
+ """Save(self, String filename, int indentstep=1) -> bool"""
+ return _xrc.XmlDocument_Save(*args, **kwargs)
+
+ def SaveToStream(*args, **kwargs):
+ """SaveToStream(self, wxOutputStream stream, int indentstep=1) -> bool"""
+ return _xrc.XmlDocument_SaveToStream(*args, **kwargs)
+
+ def IsOk(*args, **kwargs):
+ """IsOk(self) -> bool"""
+ return _xrc.XmlDocument_IsOk(*args, **kwargs)
+
+ def GetRoot(*args, **kwargs):
+ """GetRoot(self) -> XmlNode"""
+ return _xrc.XmlDocument_GetRoot(*args, **kwargs)
+
+ def GetVersion(*args, **kwargs):
+ """GetVersion(self) -> String"""
+ return _xrc.XmlDocument_GetVersion(*args, **kwargs)
+
+ def GetFileEncoding(*args, **kwargs):
+ """GetFileEncoding(self) -> String"""
+ return _xrc.XmlDocument_GetFileEncoding(*args, **kwargs)
+
+ def DetachRoot(*args, **kwargs):
+ """DetachRoot(self) -> XmlNode"""
+ return _xrc.XmlDocument_DetachRoot(*args, **kwargs)
+
+ def SetRoot(*args, **kwargs):
+ """SetRoot(self, XmlNode node)"""
+ return _xrc.XmlDocument_SetRoot(*args, **kwargs)
+
+ def SetVersion(*args, **kwargs):
+ """SetVersion(self, String version)"""
+ return _xrc.XmlDocument_SetVersion(*args, **kwargs)
+
+ def SetFileEncoding(*args, **kwargs):
+ """SetFileEncoding(self, String encoding)"""
+ return _xrc.XmlDocument_SetFileEncoding(*args, **kwargs)
+
+ FileEncoding = property(GetFileEncoding,SetFileEncoding,doc="See `GetFileEncoding` and `SetFileEncoding`")
+ Root = property(GetRoot,SetRoot,doc="See `GetRoot` and `SetRoot`")
+ Version = property(GetVersion,SetVersion,doc="See `GetVersion` and `SetVersion`")
+_xrc.XmlDocument_swigregister(XmlDocument)
+
+def XmlDocumentFromStream(*args, **kwargs):
+ """XmlDocumentFromStream(InputStream stream, String encoding=UTF8String) -> XmlDocument"""
+ val = _xrc.new_XmlDocumentFromStream(*args, **kwargs)
+ return val
+
+def EmptyXmlDocument(*args, **kwargs):
+ """EmptyXmlDocument() -> XmlDocument"""
+ val = _xrc.new_EmptyXmlDocument(*args, **kwargs)
+ return val
+
+#---------------------------------------------------------------------------
+
+class XmlResourceHandler(_core.Object):
+ """Proxy of C++ XmlResourceHandler class"""
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """__init__(self) -> XmlResourceHandler"""
+ _xrc.XmlResourceHandler_swiginit(self,_xrc.new_XmlResourceHandler(*args, **kwargs))
+ XmlResourceHandler._setCallbackInfo(self, self, XmlResourceHandler)
+
+ __swig_destroy__ = _xrc.delete_XmlResourceHandler
+ __del__ = lambda self : None;
+ def _setCallbackInfo(*args, **kwargs):
+ """_setCallbackInfo(self, PyObject self, PyObject _class)"""
+ return _xrc.XmlResourceHandler__setCallbackInfo(*args, **kwargs)
+
+ def CreateResource(*args, **kwargs):
+ """CreateResource(self, XmlNode node, Object parent, Object instance) -> Object"""
+ return _xrc.XmlResourceHandler_CreateResource(*args, **kwargs)
+
+ def SetParentResource(*args, **kwargs):
+ """SetParentResource(self, XmlResource res)"""
+ return _xrc.XmlResourceHandler_SetParentResource(*args, **kwargs)
+
+ def GetResource(*args, **kwargs):
+ """GetResource(self) -> XmlResource"""
+ return _xrc.XmlResourceHandler_GetResource(*args, **kwargs)
+
+ def GetNode(*args, **kwargs):
+ """GetNode(self) -> XmlNode"""
+ return _xrc.XmlResourceHandler_GetNode(*args, **kwargs)
+
+ def GetClass(*args, **kwargs):
+ """GetClass(self) -> String"""
+ return _xrc.XmlResourceHandler_GetClass(*args, **kwargs)
+
+ def GetParent(*args, **kwargs):
+ """GetParent(self) -> Object"""
+ return _xrc.XmlResourceHandler_GetParent(*args, **kwargs)
+
+ def GetInstance(*args, **kwargs):
+ """GetInstance(self) -> Object"""
+ return _xrc.XmlResourceHandler_GetInstance(*args, **kwargs)
+
+ def GetParentAsWindow(*args, **kwargs):
+ """GetParentAsWindow(self) -> Window"""
+ return _xrc.XmlResourceHandler_GetParentAsWindow(*args, **kwargs)
+
+ def IsOfClass(*args, **kwargs):
+ """IsOfClass(self, XmlNode node, String classname) -> bool"""
+ return _xrc.XmlResourceHandler_IsOfClass(*args, **kwargs)
+
+ def GetNodeContent(*args, **kwargs):
+ """GetNodeContent(self, XmlNode node) -> String"""
+ return _xrc.XmlResourceHandler_GetNodeContent(*args, **kwargs)
+
+ def HasParam(*args, **kwargs):
+ """HasParam(self, String param) -> bool"""
+ return _xrc.XmlResourceHandler_HasParam(*args, **kwargs)
+
+ def GetParamNode(*args, **kwargs):
+ """GetParamNode(self, String param) -> XmlNode"""
+ return _xrc.XmlResourceHandler_GetParamNode(*args, **kwargs)
+
+ def GetParamValue(*args, **kwargs):
+ """GetParamValue(self, String param) -> String"""
+ return _xrc.XmlResourceHandler_GetParamValue(*args, **kwargs)
+
+ def AddStyle(*args, **kwargs):
+ """AddStyle(self, String name, int value)"""
+ return _xrc.XmlResourceHandler_AddStyle(*args, **kwargs)
+
+ def AddWindowStyles(*args, **kwargs):
+ """AddWindowStyles(self)"""
+ return _xrc.XmlResourceHandler_AddWindowStyles(*args, **kwargs)
+
+ def GetStyle(*args, **kwargs):
+ """GetStyle(self, String param=StyleString, int defaults=0) -> int"""
+ return _xrc.XmlResourceHandler_GetStyle(*args, **kwargs)
+
+ def GetText(*args, **kwargs):
+ """GetText(self, String param, bool translate=True) -> String"""
+ return _xrc.XmlResourceHandler_GetText(*args, **kwargs)
+
+ def GetID(*args, **kwargs):
+ """GetID(self) -> int"""
+ return _xrc.XmlResourceHandler_GetID(*args, **kwargs)
+
+ def GetName(*args, **kwargs):
+ """GetName(self) -> String"""
+ return _xrc.XmlResourceHandler_GetName(*args, **kwargs)
+
+ def GetBool(*args, **kwargs):
+ """GetBool(self, String param, bool defaultv=False) -> bool"""
+ return _xrc.XmlResourceHandler_GetBool(*args, **kwargs)
+
+ def GetLong(*args, **kwargs):
+ """GetLong(self, String param, long defaultv=0) -> long"""
+ return _xrc.XmlResourceHandler_GetLong(*args, **kwargs)
+
+ def GetColour(*args, **kwargs):
+ """GetColour(self, String param) -> Colour"""
+ return _xrc.XmlResourceHandler_GetColour(*args, **kwargs)
+
+ def GetSize(*args, **kwargs):
+ """GetSize(self, String param=SizeString) -> Size"""
+ return _xrc.XmlResourceHandler_GetSize(*args, **kwargs)
+
+ def GetPosition(*args, **kwargs):
+ """GetPosition(self, String param=PosString) -> Point"""
+ return _xrc.XmlResourceHandler_GetPosition(*args, **kwargs)
+
+ def GetDimension(*args, **kwargs):
+ """GetDimension(self, String param, int defaultv=0) -> int"""
+ return _xrc.XmlResourceHandler_GetDimension(*args, **kwargs)
+
+ def GetBitmap(*args, **kwargs):
+ """
+ GetBitmap(self, String param=BitmapString, wxArtClient defaultArtClient=wxART_OTHER,
+ Size size=DefaultSize) -> Bitmap
+ """
+ return _xrc.XmlResourceHandler_GetBitmap(*args, **kwargs)
+
+ def GetIcon(*args, **kwargs):
+ """
+ GetIcon(self, String param=IconString, wxArtClient defaultArtClient=wxART_OTHER,
+ Size size=DefaultSize) -> Icon
+ """
+ return _xrc.XmlResourceHandler_GetIcon(*args, **kwargs)
+
+ def GetFont(*args, **kwargs):
+ """GetFont(self, String param=FontString) -> Font"""
+ return _xrc.XmlResourceHandler_GetFont(*args, **kwargs)
+
+ def GetAnimation(*args, **kwargs):
+ """GetAnimation(self, String param=AnimationString) -> wxAnimation"""
+ return _xrc.XmlResourceHandler_GetAnimation(*args, **kwargs)
+
+ def SetupWindow(*args, **kwargs):
+ """SetupWindow(self, Window wnd)"""
+ return _xrc.XmlResourceHandler_SetupWindow(*args, **kwargs)
+
+ def CreateChildren(*args, **kwargs):
+ """CreateChildren(self, Object parent, bool this_hnd_only=False)"""
+ return _xrc.XmlResourceHandler_CreateChildren(*args, **kwargs)
+
+ def CreateChildrenPrivately(*args, **kwargs):
+ """CreateChildrenPrivately(self, Object parent, XmlNode rootnode=None)"""
+ return _xrc.XmlResourceHandler_CreateChildrenPrivately(*args, **kwargs)
+
+ def CreateResFromNode(*args, **kwargs):
+ """CreateResFromNode(self, XmlNode node, Object parent, Object instance=None) -> Object"""
+ return _xrc.XmlResourceHandler_CreateResFromNode(*args, **kwargs)
+
+ def GetCurFileSystem(*args, **kwargs):
+ """GetCurFileSystem(self) -> FileSystem"""
+ return _xrc.XmlResourceHandler_GetCurFileSystem(*args, **kwargs)
+
+ Class = property(GetClass,doc="See `GetClass`")
+ CurFileSystem = property(GetCurFileSystem,doc="See `GetCurFileSystem`")
+ ID = property(GetID,doc="See `GetID`")
+ Instance = property(GetInstance,doc="See `GetInstance`")
+ Name = property(GetName,doc="See `GetName`")
+ Node = property(GetNode,doc="See `GetNode`")
+ Parent = property(GetParent,doc="See `GetParent`")
+ ParentAsWindow = property(GetParentAsWindow,doc="See `GetParentAsWindow`")
+ Resource = property(GetResource,doc="See `GetResource`")
+_xrc.XmlResourceHandler_swigregister(XmlResourceHandler)
+
+#----------------------------------------------------------------------------
+# The global was removed in favor of static accessor functions. This is for
+# backwards compatibility:
+
+TheXmlResource = XmlResource_Get()
+
+
+#----------------------------------------------------------------------------
+# Create a factory for handling the subclass property of the object tag.
+
+
+def _my_import(name):
+ try:
+ mod = __import__(name)
+ except ImportError:
+ import traceback
+ print traceback.format_exc()
+ raise
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+
+
+class XmlSubclassFactory_Python(XmlSubclassFactory):
+ def __init__(self):
+ XmlSubclassFactory.__init__(self)
+
+ def Create(self, className):
+ assert className.find('.') != -1, "Module name must be specified!"
+ mname = className[:className.rfind('.')]
+ cname = className[className.rfind('.')+1:]
+ module = _my_import(mname)
+ klass = getattr(module, cname)
+ inst = klass()
+ return inst
+
+
+XmlResource_AddSubclassFactory(XmlSubclassFactory_Python())
+
+#----------------------------------------------------------------------------
+
+
+
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wxPython-3.0.2.0-py2.7.egg-info b/lib/python2.7/site-packages/wx-3.0-msw/wxPython-3.0.2.0-py2.7.egg-info
new file mode 100644
index 0000000..acbd0e0
--- /dev/null
+++ b/lib/python2.7/site-packages/wx-3.0-msw/wxPython-3.0.2.0-py2.7.egg-info
@@ -0,0 +1,30 @@
+Metadata-Version: 1.1
+Name: wxPython
+Version: 3.0.2.0
+Summary: Cross platform GUI toolkit for Python
+Home-page: http://wxPython.org/
+Author: Robin Dunn
+Author-email: Robin Dunn <robin@alldunn.com>
+License: wxWidgets Library License (LGPL derivative)
+Download-URL: http://wxPython.org/download.php
+Description: wxPython is a GUI toolkit for Python that is a wrapper around the
+ wxWidgets C++ GUI library. wxPython provides a large variety of
+ window types and controls, all implemented with a native look and
+ feel (by using the native widgets) on the platforms upon which it is
+ supported.
+
+Keywords: GUI,wx,wxWindows,wxWidgets,cross-platform,awesome
+Platform: WIN32
+Platform: OSX
+Platform: POSIX
+Classifier: Development Status :: 6 - Mature
+Classifier: Environment :: MacOS X :: Carbon
+Classifier: Environment :: Win32 (MS Windows)
+Classifier: Environment :: X11 Applications :: GTK
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: Microsoft :: Windows :: Windows 98/2000/XP/Vista
+Classifier: Operating System :: POSIX
+Classifier: Programming Language :: Python
+Classifier: Topic :: Software Development :: User Interfaces